pax_global_header00006660000000000000000000000064126627072700014523gustar00rootroot0000000000000052 comment=8a9abd765e274218dcee65fff7c9524ecbf8b014 singular-4.0.3+ds/000077500000000000000000000000001266270727000137555ustar00rootroot00000000000000singular-4.0.3+ds/AUTHORS000066400000000000000000000000001266270727000150130ustar00rootroot00000000000000singular-4.0.3+ds/COPYING000066400000000000000000000126211266270727000150120ustar00rootroot00000000000000 SINGULAR version 4-0 University of Kaiserslautern Department of Mathematics and Centre for Computer Algebra Authors: W. Decker, G.-M. Greuel, G. Pfister, H. Schoenemann Copyright (C) 1986-2016 *NOTICE* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation (version 2 or version 3 of the License). Some single files have a copyright given within the file: Singular/links/ndbm.* (BSD) The following software modules shipped with SINGULAR have their own copyright: the omalloc library, the readline library, the GNU Multiple Precision Library (GMP), NTL: A Library for doing Number Theory (NTL), Flint: Fast Library for Number Theory, the Singular-Factory library, the Singular-libfac library, surfex, and, for the Windows distributions, the Cygwin DLL and the Cygwin tools (Cygwin), and the XEmacs editor (XEmacs). Their copyrights and licenses can be found in the accompanying files COPYING which are distributed along with these packages. (Since version 3-0-3 of SINGULAR, all parts have GPL or LGPL as (one of) their licences.) This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA (see GPL) Please send any comments or bug reports to . If you want to be informed of new releases, please register as a SINGULAR user by sending an email to with subject line `register' and body containing the following data: your name, email address, organisation, country and platform(s). For information on how to cite SINGULAR see `http://www.singular.uni-kl.de/index.php/how-to-cite-singular'. You can also support SINGULAR by informing us about your result obtained by using SINGULAR. Availability ============ The latest information regarding the status of SINGULAR is always available from `http://www.singular.uni-kl.de'. Acknowledgements ================ The development of SINGULAR is directed and coordinated by Wolfram Decker, Gert-Martin Greuel, Gerhard Pfister, and Hans Scho"nemann. Current devteams: Abdus Salam School of Mathematical Sciences in Lahore, BTU Cottbus, Center for Advanced Security Research Darmstadt (CASED), FU Berlin, Isfahan University of Technology, Mathematisches Forschunginstitut Oberwolfach, Oklahoma State University, RWTH Aachen, Universidad de Buenos Aires, Université de Versailles Saint-Quentin-en-Yvelines, University of Go"ttingen, University of Hannover, University of La Laguna and University of Valladolid. Current SINGULAR developers: Wolfram Decker, Gert-Martin Greuel, Gerhard Pfister, Hans Scho"nemann, Shawki Al-Rashed, Daniel Andres, Mohamed Barakat, Isabel Bermejo, Muhammad Asan Binyamin, Rene' Birkner, Rocio Blanco, Xenia Bogomolec, Michael Brickenstein, Stanislav Bulygin, Antonio Campillo, Raza Choudery, Alexander Dreyer, Christian Eder, Santiago Encinas, Jose Ignacio Farran, Anne Fru"hbis-Kru"ger, Rosa de Frutos, Eva Garcia-Llorente, Ignacio Garcia-Marco, Christian Haase, Amir Hashemi, Fernando Hernando, Bradford Hovinen, Nazeran Idress, Anders Jensen, Lars Kastner, Junaid Alan Khan, Kai Kru"ger, Santiago Laplagne, Grégoire Lecerf, Martin Lee, Viktor Levandovskyy, Benjamin Lorenz, Christoph Lossen, Thomas Markwig, Hannah Markwig, Irene Marquez, Bernd Martin, Edgar Martinez, Martin Monerjan, Francisco Monserrat, Oleksandr Motsak, Andreas Paffenholz, Maria Jesus Pisabarro, Diego Ruano, Afshan Sadiq, Kristina Schindelar, Mathias Schulze, Frank Seelisch, Andreas Steenpass, Stefan Steidel, Grischa Studzinski, Katharina Werner and Eva Zerz. Further contributions to SINGULAR have been made by: Martin Albrecht, Olaf Bachmann, Muhammad Ahsan Banyamin, Thomas Bauer, Thomas Bayer, Markus Becker, J. Boehm, Gergo Gyula Borus, Winfried Bruns, Fernando Hernando Carrillo, Victor Castellanos, Nadine Cremer, Michael Cuntz, Kai Dehmann, Christian Dingler, Marcin Dumnicki, Stephan Endrass, Vladimir Gerdt, Philippe Gimenez, Christian Gorzel, Hubert Grassmann, Jan Hackfeld, Agnes Heydtmann, Dietmar Hillebrand, Tobias Hirsch, Markus Hochstetter, N. Idrees, Manuel Kauers, Simon King, Sebastian Jambor, Oliver Labs, Anen Lakhal, Martin Lamm, Francisco Javier Lobillo, Christoph Mang, Michael Messollen, Andrea Mindnich, Antonio Montes, Jorge Martin Morales, Thomas Nu"ssler, Wolfgang Neumann, Markus Perling, Wilfried Pohl, Adrian Popescu, Tetyana Povalyaeva, Carlos Rabelo, Philipp Renner, J.-J.Salazar-Gonzalez, Alfredo Sanchez-Navarro, Ivor Saynisch, Jens Schmidt, Thomas Siebert, Christof Soeger, Silke Spang, William Stein, Ru"diger Stobbe, Henrik Strohmayer, Christian Stussak, Imade Sulandra, Akira Suzuki, Christine Theis, Enrique Tobis, Alberto Vigneron-Tenorio, Moritz Wenk, Eric Westenberger, Tim Wichmann, Oliver Wienand, Denis Yanovich and Oleksandr Yena. We should like to acknowledge the financial support given by the Volkswagen-Stiftung, the Deutsche Forschungsgemeinschaft and the Stiftung fu"r Innovation des Landes Rheinland-Pfalz to the SINGULAR project. singular-4.0.3+ds/ChangeLog000066400000000000000000000000001266270727000155150ustar00rootroot00000000000000singular-4.0.3+ds/GPL2000066400000000000000000000431311266270727000144060ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. singular-4.0.3+ds/GPL3000066400000000000000000001045131266270727000144110ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . singular-4.0.3+ds/IntegerProgramming/000077500000000000000000000000001266270727000175555ustar00rootroot00000000000000singular-4.0.3+ds/IntegerProgramming/BigInt.cc000066400000000000000000000134541266270727000212470ustar00rootroot00000000000000// BigInt.cc #ifndef BIG_INT_CC #define BIG_INT_CC #include "BigInt.h" // // Konstruktoren fuer die Klasse BigInt // // Default-Konstruktor BigInt::BigInt() { mpz_init(value); } BigInt::BigInt(int a) { mpz_init(value); mpz_set_si(value,(long)a); } // Copy-Konstruktor BigInt::BigInt(const BigInt& a) { mpz_init(value); mpz_set(value,a.value); } // Destruktor BigInt::~BigInt() { mpz_clear(value); } // // Zuweisungsoperatoren // BigInt& BigInt::operator=(int a) { mpz_set_si(value,(long)a); return *this; } BigInt& BigInt::operator=(const BigInt& a) { mpz_set(value,a.value); return *this; } // // Type-Conversion // BigInt::operator bool() { if (mpz_sgn(value)) return true; return false; } BigInt::operator int() { long int ret_val; ret_val=mpz_get_si(value); return (int)ret_val; } BigInt::operator short() { long int ret_val; ret_val=mpz_get_si(value); return (short)ret_val; } // // unary arithmetic operators // // unary Minus BigInt BigInt::operator-() { BigInt erg; mpz_neg(erg.value,value); return erg; } // += Operator BigInt& BigInt::operator+=(const BigInt &a) { BigInt aux; mpz_set(aux.value,value); mpz_add(value,aux.value,a.value); return *this; } // -= Operator BigInt& BigInt::operator-=(const BigInt &a) { BigInt aux; mpz_set(aux.value,value); mpz_sub(value,aux.value,a.value); return *this; } // *= Operator BigInt& BigInt::operator*=(const BigInt &a) { BigInt aux; mpz_set(aux.value,value); mpz_mul(value,aux.value,a.value); return *this; } // /= Operator BigInt& BigInt::operator/=(const BigInt &a) { BigInt aux; mpz_set(aux.value,value); mpz_fdiv_q(value,aux.value,a.value); return *this; } // prefix ++ BigInt& BigInt::operator++() { BigInt aux; mpz_set(aux.value,value); mpz_add(value,aux.value,BigInt(1).value); return *this; } // postfix ++ BigInt BigInt::operator++(int) { BigInt erg; mpz_add(erg.value,value,BigInt(1).value); return erg; } // prefix -- BigInt& BigInt::operator--() { BigInt aux; mpz_set(aux.value,value); mpz_sub(value,aux.value,BigInt(1).value); return *this; } // postfix -- BigInt BigInt::operator--(int) { BigInt erg; mpz_add(erg.value,value,BigInt(1).value); return erg; } BigInt operator-(const BigInt& r) { BigInt erg; mpz_neg(erg.value,r.value); return erg; } // // Vergleichsoperatorn // bool operator<(const BigInt& a,const BigInt& b) { if (mpz_cmp(a.value,b.value)<0) return true; return false; } bool operator<=(const BigInt& a,const BigInt& b) { if (mpz_cmp(a.value,b.value)>0) return false; return true; } bool operator>(const BigInt& a,const BigInt& b) { if (mpz_cmp(a.value,b.value)>0) return true; return false; } bool operator>=(const BigInt& a,const BigInt& b) { if (mpz_cmp(a.value,b.value)<0) return false; return true; } bool operator==(const BigInt& a,const BigInt& b) { if (!mpz_cmp(a.value,b.value)) return true; return false; } bool operator!=(const BigInt& a,const BigInt& b) { if (!mpz_cmp(a.value,b.value)) return false; return true; } bool operator<(const int& a,const BigInt& b) { if (mpz_cmp(BigInt(a).value,b.value)<0) return true; return false; } bool operator<=(const int& a,const BigInt& b) { if (mpz_cmp(BigInt(a).value,b.value)>0) return false; return true; } bool operator>(const int& a,const BigInt& b) { if (mpz_cmp(BigInt(a).value,b.value)>0) return true; return false; } bool operator>=(const int& a,const BigInt& b) { if (mpz_cmp(BigInt(a).value,b.value)<0) return false; return true; } bool operator==(const int& a,const BigInt& b) { if (!mpz_cmp(BigInt(a).value,b.value)) return true; return false; } bool operator!=(const int& a,const BigInt& b) { if (!mpz_cmp(BigInt(a).value,b.value)) return false; return true; } bool operator<(const BigInt& a,const int& b) { if (mpz_cmp(a.value,BigInt(b).value)<0) return true; return false; } bool operator<=(const BigInt& a,const int& b) { if (mpz_cmp(a.value,BigInt(b).value)>0) return false; return true; } bool operator>(const BigInt& a,const int& b) { if (mpz_cmp(a.value,BigInt(b).value)>0) return true; return false; } bool operator>=(const BigInt& a,const int& b) { if (mpz_cmp(a.value,BigInt(b).value)<0) return false; return true; } bool operator==(const BigInt& a,const int& b) { if (!mpz_cmp(a.value,BigInt(b).value)) return true; return false; } bool operator!=(const BigInt& a,const int& b) { if (!mpz_cmp(a.value,BigInt(b).value)) return false; return true; } // // die Grundoperationen // BigInt operator+(const BigInt& a,const BigInt &b) { BigInt erg(a); return erg+=b; } BigInt operator-(const BigInt& a,const BigInt &b) { BigInt erg(a); return erg-=b; } BigInt operator*(const BigInt& a,const BigInt &b) { BigInt erg(a); return erg*=b; } BigInt operator/(const BigInt& a,const BigInt &b) { BigInt erg(a); return erg/=b; } BigInt operator+(const int& a,const BigInt &b) { BigInt erg(a); return erg+=b; } BigInt operator-(const int& a,const BigInt &b) { BigInt erg(a); return erg-=b; } BigInt operator*(const int& a,const BigInt &b) { BigInt erg(a); return erg*=b; } BigInt operator/(const int& a,const BigInt &b) { BigInt erg(a); return erg/=b; } BigInt operator+(const BigInt& a,const int &b) { BigInt erg(a); return erg+=BigInt(b); } BigInt operator-(const BigInt& a,const int &b) { BigInt erg(a); return erg-=BigInt(b); } BigInt operator*(const BigInt& a,const int &b) { BigInt erg(a); return erg*=BigInt(b); } BigInt operator/(const BigInt& a,const int &b) { BigInt erg(a); return erg/=BigInt(b); } // liefert das Vorzeichen int sgn(const BigInt& a) { return mpz_sgn(a.value); } // liefert den Absolutbetrag BigInt abs(const BigInt& a) { BigInt erg; if (mpz_sgn(a.value)<0) mpz_neg(erg.value,a.value); else mpz_set(erg.value,a.value); return erg; } #endif // BIG_INT_CC singular-4.0.3+ds/IntegerProgramming/BigInt.h000066400000000000000000000052621266270727000211070ustar00rootroot00000000000000// BigInt.h // A BigInt-class with not much more functions than needed by the // LLL-algorithm. Wrapper class for the GNU MP library. #ifndef BIG_INT_H #define BIG_INT_H #include #include #include #include #include #include #include class BigInt { mpz_t value; public: BigInt( ); BigInt( int ); BigInt( const BigInt& ); ~BigInt( ); BigInt& operator = ( int ); BigInt& operator = ( const BigInt& ); operator bool( ); operator int( ); operator short( ); BigInt operator - ( ); BigInt& operator += ( const BigInt& ); BigInt& operator -= ( const BigInt& ); BigInt& operator *= ( const BigInt& ); BigInt& operator /= ( const BigInt& ); BigInt& operator ++ ( ); BigInt operator ++ ( int ); BigInt& operator -- ( ); BigInt operator -- ( int ); friend BigInt operator - ( const BigInt& ); friend bool operator < ( const BigInt&, const BigInt& ); friend bool operator <= ( const BigInt&, const BigInt& ); friend bool operator > ( const BigInt&, const BigInt& ); friend bool operator >= ( const BigInt&, const BigInt& ); friend bool operator == ( const BigInt&, const BigInt& ); friend bool operator != ( const BigInt&, const BigInt& ); friend bool operator < ( const int&, const BigInt& ); friend bool operator <= ( const int&, const BigInt& ); friend bool operator > ( const int&, const BigInt& ); friend bool operator >= ( const int&, const BigInt& ); friend bool operator == ( const int&, const BigInt& ); friend bool operator != ( const int&, const BigInt& ); friend bool operator < ( const BigInt&, const int& ); friend bool operator <= ( const BigInt&, const int& ); friend bool operator > ( const BigInt&, const int& ); friend bool operator >= ( const BigInt&, const int& ); friend bool operator == ( const BigInt&, const int& ); friend bool operator != ( const BigInt&, const int& ); friend int sgn ( const BigInt& ); friend BigInt abs ( const BigInt& ); }; BigInt operator + ( const BigInt&, const BigInt& ); BigInt operator - ( const BigInt&, const BigInt& ); BigInt operator * ( const BigInt&, const BigInt& ); BigInt operator / ( const BigInt&, const BigInt& ); BigInt operator + ( const int&, const BigInt& ); BigInt operator - ( const int&, const BigInt& ); BigInt operator * ( const int&, const BigInt& ); BigInt operator / ( const int&, const BigInt& ); BigInt operator + ( const BigInt&, const int& ); BigInt operator - ( const BigInt&, const int& ); BigInt operator * ( const BigInt&, const int& ); BigInt operator / ( const BigInt&, const int& ); #endif // BIG_INT_H singular-4.0.3+ds/IntegerProgramming/Buchberger.cc000066400000000000000000002700101266270727000221340ustar00rootroot00000000000000// Buchberger.cc // implementation of Buchberger's Algorithm. #ifndef BUCHBERGER_CC #define BUCHBERGER_CC #include "ideal.h" ///////////////////////////////////////////////////////////////////////////// /////////////// S-pair computation ////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// BOOLEAN ideal::unnecessary_S_pair(list_iterator& first_iter, list_iterator& second_iter) const { // This function checks several criteria to discard th S-pair of the // binomials referenced by the iterators. The criteria depend on the // settings of the ideal´s S-pair flags. // The arguments are iterators instead of the referenced binomials // because we have to do some equality tests. These are more efficient on // iterators than on binomials. ///////////// criterion of relatively prime leading terms /////////////////// // An S-pair can discarded if the leading terms of the two binomials are // relatively prime. if(rel_primeness) if(relatively_prime(first_iter.get_element(),second_iter.get_element()) ==TRUE) return TRUE; //////////// criterion M /////////////////////////////////////////////////// if(M_criterion) { list_iterator iter; binomial& bin1=first_iter.get_element(); binomial& bin2=second_iter.get_element(); // The M-criterion of Gebauer/Moeller checks binomial triples as // explained in binomial.h; these are built of the elements referenced // by the argument iterators and a third element appearing before the // element referenced by second_iter in the generator lists. #ifdef NO_SUPPORT_DRIVEN_METHODS_EXTENDED iter.set_to_list(generators); #endif // NO_SUPPORT_DRIVEN_METHODS_EXTENDED #ifdef SUPPORT_DRIVEN_METHODS_EXTENDED // The support of the lcm of two monomials is the union of their supports. // To test criterion M, we then only have to consider lists whose support // is a subset of the union of (first_iter.get_element()).head_support and // (second_iter.get_element()).head_support. As only elements before // second_iter.get_element() are tested, we can stop iteraton as soon as // we reach this element. int supp2=bin2.head_support%Number_of_Lists; int supp_union=(bin1.head_support%Number_of_Lists)|supp2; // supp_union (read as binary vector) is the union of the supports of // first_iter.get_element() and second_iter.get_element() // (restricted to List_Support_Variables variables). for(int i=0;i0); first_iter.next(); } #endif // NO_SUPPORT_DRIVEN_METHODS_EXTENDED #ifdef SUPPORT_DRIVEN_METHODS_EXTENDED // In this case, the reduction has to be organized in a slightly different // way to use the support information to its full extend. // As soon as an reduction has taken place, the iteration over the reducer // lists is restarted using the new tail support information. list_iterator first_iter; for(int i=0;i0); first_iter.next(); } } #endif // SUPPORT_DRIVEN_METHODS_EXTENDED return(*this); } ////////////////////////////////////////////////////////////////////////////// ////////////////////// auxiliary stuff /////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// int ideal::add_new_generators() { // Reduces the binomials in the "new_generators" list(s) by the generators // and moves them to the "generators" list(s). #ifdef NO_SUPPORT_DRIVEN_METHODS_EXTENDED int result=0; // element inserted? list_iterator iter(new_generators); while(iter.is_at_end()==FALSE) { binomial& bin=iter.get_element(); reduce(bin,FALSE); if(bin==0) iter.delete_element(); else { add_generator(bin); iter.extract_element(); result=1; } } #endif // NO_SUPPORT_DRIVEN_METHODS_EXTENDED #ifdef SUPPORT_DRIVEN_METHODS_EXTENDED int result=0; // element inserted? list_iterator iter; for(int i=0;i0) as soon as bin // is really reduced iter.next(); } } while((reduced>0) && (bin!=0)); if(complete==TRUE) do { iter.set_to_list(generators); reduced=0; // not yet reduced while(iter.is_at_end()==FALSE) { reduced+=bin.reduce_tail_by(iter.get_element(),w); // reduced is incremented (and so set to a value >0) as soon as bin // is really reduced iter.next(); } } while((reduced>0) && (bin!=0)); #endif // NO_SUPPORT_DRIVEN_METHODS_EXTENDED #ifdef SUPPORT_DRIVEN_METHODS_EXTENDED do { reduced=0; // not yet reduced int supp=bin.head_support%Number_of_Lists; // determine the lists over which we have to iterate // As soon as some reduction is done, the iteration is started with // the new support information; so we do not finish iterations over lists // that cannot contain reducers any more. for(int i=0;(i0) && (bin!=0)); if(complete==TRUE) do { reduced=0; // not yet reduced int supp=bin.tail_support%Number_of_Lists; // determine the lists over which we have to iterate // As soon as some reduction is done, the iteration is started with // the new support information; so we do not finish iterations over // lists that cannot contain reducers any more. for(int i=0;(i0); // bin cannot be reduced to zero by a tail reduction #endif // SUPPORT_DRIVEN_METHODS_EXTENDED return(bin); } ////////////////////////////////////////////////////////////////////////////// /////////// variants of Buchberger´s algorithm /////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ideal& ideal::reduced_Groebner_basis_1(const int& S_pair_criteria, const float& interred_percentage) { // set flags for the use of the S-pair criteria // for an explaination see in globals.h rel_primeness=(S_pair_criteria & 1); M_criterion=(S_pair_criteria & 2); F_criterion=(S_pair_criteria & 4); B_criterion=(S_pair_criteria & 8); second_criterion=(S_pair_criteria & 16); interreduction_percentage=interred_percentage; int done; // control variable for recognizing when Buchberger's algorithm has reached // his end // first minimalize the initial generating system minimalize(); do { done=1; // no new generators found yet compute_actual_S_pairs_1(); // compute the S-pairs of the actual generators // These are stored in a unreduced form in aux_list. list_iterator S_pair_iter(aux_list); // now reduce and insert the computed S-pairs while(S_pair_iter.is_at_end()==FALSE) { binomial& S_bin=S_pair_iter.get_element(); reduce(S_bin,FALSE); if(S_bin!=0) // new generator found { add_generator(S_bin); S_pair_iter.extract_element(); done=0; // algorithm does not terminate when a new generator is found } else S_pair_iter.delete_element(); } // now all computed S-pairs are inserted as generators // enough for a minimalization? if(interreduction_percentage>=0) // intermediate interreductions allowed { if(number_of_new_binomials>=size*interreduction_percentage/100) // enough new generators since last minimalization { minimalize(); number_of_new_binomials=0; } } // now we restart the algorithm with the new generating system // if the generating system has changed during the last iteration } while(done==0); // if done==1, all computed S-pairs reduced to zero // compute reduced from minimal Groebner basis final_reduce(); return(*this); } ideal& ideal::reduced_Groebner_basis_1a(const int& S_pair_criteria, const float& interred_percentage) { // set flags for the use of the S-pair criteria // for an explaination see in globals.h rel_primeness=(S_pair_criteria & 1); M_criterion=(S_pair_criteria & 2); F_criterion=(S_pair_criteria & 4); B_criterion=(S_pair_criteria & 8); second_criterion=(S_pair_criteria & 16); interreduction_percentage=interred_percentage; int done; // control variable for recognizing when Buchberger's algorithm has reached // his end // first minimalize the initial generating system minimalize(); do { done=1; // no new generators found yet compute_actual_S_pairs_1a(); // compute the S-pairs of the actual generators // These are stored in a unreduced form in aux_list. // aux_list is ordered according to the ideal´s term ordering. list_iterator S_pair_iter(aux_list); // now reduce and insert the computed S-pairs while(S_pair_iter.is_at_end()==FALSE) { binomial& S_bin=S_pair_iter.get_element(); reduce(S_bin,FALSE); if(S_pair_iter.get_element()!=0) // new generator found { add_generator(S_bin); S_pair_iter.extract_element(); done=0; // algorithm does not terminate when a new generator is found } else S_pair_iter.delete_element(); } // now all computed S-pairs are inserted as generators // enough for a minimalization? if(interreduction_percentage>=0) // intermediate interreductions allowed { if(number_of_new_binomials>=size*interreduction_percentage/100) // enough new generators since last minimalization { minimalize(); number_of_new_binomials=0; } } // now we restart the algorithm with the new generating system // if the generating system has changed during the last iteration } while(done==0); // if done==1, all computed S-pairs reduced to zero // compute reduced from minimal Groebner basis final_reduce(); return(*this); } ideal& ideal::reduced_Groebner_basis_2(const int& S_pair_criteria, const float& interred_percentage) { // set flags for the use of the S-pair criteria // for an explaination see in globals.h rel_primeness=(S_pair_criteria & 1); M_criterion=(S_pair_criteria & 2); F_criterion=(S_pair_criteria & 4); B_criterion=(S_pair_criteria & 8); second_criterion=(S_pair_criteria & 16); interreduction_percentage=interred_percentage; int done; // control variable for recognizing when Buchberger's algorithm has reached // his end // first minimalize the initial generating system minimalize(); do { done=1; // no new generators found yet compute_actual_S_pairs_2(); // compute the S-pairs of the actual generators // These are stored in a reduced version in aux_list. minimalize_S_pairs(); // minimalize the binomials in aux_list // These are not only S-pairs, but also ideal generators that were // reduced by an S-pair during the S-pair computation. list_iterator S_pair_iter(aux_list); if(S_pair_iter.is_at_end()==FALSE) // Zero binomials are not inserted in aux_list during the S-pair // computation; i.e. if aux_list is not empty, a further iteration step // has to be done. done=0; // now insert the computed S-pairs while(S_pair_iter.is_at_end()==FALSE) // S_pairs remaining { add_generator(S_pair_iter.get_element()); S_pair_iter.extract_element(); } // now all computed S-pairs are inserted as generators // enough for a minimalization? if(interreduction_percentage>=0) // intermediate interreductions allowed { if(number_of_new_binomials>=size*interreduction_percentage/100) // enough new generators since last minimalization { minimalize(); number_of_new_binomials=0; } } // now we restart the algorithm with the new generating system // if the generating system has changed during the last iteration } while(done==0); // if done==1, all computed S-pairs reduced to zero // compute reduced from minimal Groebner basis final_reduce(); return(*this); } ideal& ideal::reduced_Groebner_basis_3(const int& S_pair_criteria, const float& interred_percentage) { // set flags for the use of the S-pair criteria // for an explaination see in globals.h rel_primeness=(S_pair_criteria & 1); M_criterion=(S_pair_criteria & 2); F_criterion=(S_pair_criteria & 4); B_criterion=(S_pair_criteria & 8); second_criterion=(S_pair_criteria & 16); interreduction_percentage=interred_percentage; int not_done; // control variable for recognizing when Buchberger's algorithm has reached // his end // first minimalize the initial generating system minimalize(); do { compute_actual_S_pairs_3(); // compute the S-pairs of the actual generators // These are stored in areduced version in the list(s) new_generators. minimalize_new_generators(); // minimalize the binomials in aux_list // These are not only S-pairs, but also ideal generators that were // reduced by an S-pair during the S-pair computation. not_done=add_new_generators(); // move binomials from new_generators to generators // now all computed S-pairs are inserted as generators // enough for a minimalization? if(interreduction_percentage>=0) // intermediate interreductions allowed { if(number_of_new_binomials>=size*interreduction_percentage/100) // enough new generators since last reduction { minimalize(); number_of_new_binomials=0; } } // now we restart the algorithm with the new generating system // if the generating system has changed during the last iteration } while(not_done==1); // if not_done==0, all computed S-pairs reduced to zero // compute reduced from minimal Groebner basis final_reduce(); return(*this); } ideal& ideal::reduced_Groebner_basis(const int& version, const int& S_pair_criteria, const float& interred_percentage) { switch(version) { case 0: return reduced_Groebner_basis_1a(S_pair_criteria, interred_percentage); case 1: return reduced_Groebner_basis_1(S_pair_criteria, interred_percentage); case 2: return reduced_Groebner_basis_2(S_pair_criteria, interred_percentage); case 3: return reduced_Groebner_basis_3(S_pair_criteria, interred_percentage); default: cerr<<"WARNING: ideal& ideal::reduced_Groebner_basis(const int&, " "const int&, const float&):\n" "version argument out of range, nothing done"< #include /////////////// method for printing compilation settings //////////////////// void print_flags(ofstream& output) { output<<"compiler settings:"<>format_string; if(!input) { cerr<<"ERROR: int Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading format specification,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of variables / matrix columns,\n" "input format not accepted"<>variables; if(!input) { cerr<<"ERROR: int Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of variables / matrix columns,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of constraints / matrix rows,\n" "input format not accepted"<>constraints; if(!input) { cerr<<"ERROR: int Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of constraints / matrix rows,\n" "input format not accepted" <>format_string; if(!input) { cerr<<"ERROR: int Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading matrix,\n" "input format not accepted"<0) output<0) output<>format_string; if(!input) { cerr<<"ERROR: int Positive_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading format specification,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Positive_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of variables / matrix columns,\n" "input format not accepted"<>variables; if(!input) { cerr<<"ERROR: int Positive_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of variables / matrix columns,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Positive_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" " input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Positive_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Positive_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of constraints / matrix rows,\n" "input format not accepted"<>constraints; if(!input) { cerr<<"ERROR: int Positive_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of constraints / matrix rows,\n" "input format not accepted" <>format_string; if(!input) { cerr<<"ERROR: int Positive_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading matrix,\n" "input format not accepted"<0) output<0) output<>format_string; if(!input) { cerr<<"ERROR: int Elim_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading format specification,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Elim_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of variables / matrix columns,\n" "input format not accepted"<>variables; if(!input) { cerr<<"ERROR: int Elim_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of variables / matrix columns,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Elim_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Elim_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Elim_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of constraints / matrix rows,\n" "input format not accepted"<>constraints; if(!input) { cerr<<"ERROR: int Elim_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of constraints / matrix rows,\n" "input format not accepted" <>format_string; if(!input) { cerr<<"ERROR: int Elim_Conti_Traverso(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading matrix,\n" "input format not accepted"<0) output<>format_string; if(!input) { cerr<<"ERROR: int Pottier(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading format specification,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Pottier(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of variables / matrix columns,\n" "input format not accepted"<>variables; if(!input) { cerr<<"ERROR: int Pottier(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of variables / matrix columns,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Pottier(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Pottier(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Pottier(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of constraints / matrix rows,\n" " input format not accepted"<>constraints; if(!input) { cerr<<"ERROR: int Pottier(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of constraints / matrix rows,\n " "input format not accepted" <>format_string; if(!input) { cerr<<"ERROR: int Pottier(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading matrix,\n" "input format not accepted"<0) output<>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading format specification,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of variables / matrix columns,\n" "input format not accepted"<>variables; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of variables / matrix columns,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of constraints / matrix rows,\n" "input format not accepted"<>constraints; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of constraints / matrix rows,\n" "input format not accepted" <>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading matrix,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading positive row space vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading positive row space vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading positive row space vector,\n" " input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading positive row space vector,\n" "input format not accepted"<>hom_grad[i]; if(!input) { cerr<<"ERROR: int Hosten_Sturmfels(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading positive grading / row space vector,\n" "input format not accepted"<0) output<>format_string; if(!input) { cerr<<"ERROR: int DiBiase_Urbanke(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading format specification,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int DiBiase_Urbanke(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of variables / matrix columns,\n" "input format not accepted"<>variables; if(!input) { cerr<<"ERROR: int DiBiase_Urbanke(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of variables / matrix columns,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int DiBiase_Urbanke(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int DiBiase_Urbanke(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" " input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int DiBiase_Urbanke(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of constraints / matrix rows,\n" " input format not accepted"<>constraints; if(!input) { cerr<<"ERROR: int DiBiase_Urbanke(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of constraints / matrix rows,\n" "input format not accepted" <>format_string; if(!input) { cerr<<"ERROR: int DiBiase_Urbanke(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading matrix,\n" "input format not accepted"<reduced_Groebner_basis(version,S_pair_criteria,interred_percentage); } else { // construct term ordering to start with // Here we have much freedom: The term ordering must only be an // elimination ordering for the actual flip variable. // To avoid supplementary functions to manipulate term orderings, we // simply realize this as follows: The weight of the actual // flip variable is set to 1, all other weights are set to zero. This // still allows the use of different term orderings (by setting the // refining ordering). float* weights=new float[variables]; for(int j=0;jreduced_Groebner_basis(version,S_pair_criteria,interred_percentage); I->flip_variable_unsafe(F[0]); // "unsafe" means that head and tail can be exchanged (cf. the routine // ideal::swap_variables_unsafe(...) ) // But the following change of the term ordering will correct this. for(int l=1;lchange_term_ordering_to(w); I->reduced_Groebner_basis(version,S_pair_criteria,interred_percentage); I->flip_variable_unsafe(F[l]); } // Now we have a generating system of the saturated ideal. // Compute Groebner basis with respect to the objective function. I->change_term_ordering_to(c); I->reduced_Groebner_basis(version,S_pair_criteria,interred_percentage); } end=clock(); // time measurement float elapsed=((float) (end-start))/CLOCKS_PER_SEC; ///////////////////////// output //////////////////////////////////////////// // create output file char GROEBNER[128]; int i=0; while(MATRIX[i]!='\0' && MATRIX[i]!='.') { GROEBNER[i]=MATRIX[i]; i++; } GROEBNER[i]='\0'; strcat(GROEBNER,".GB.du"); ofstream output(GROEBNER); // format output file output.flags(output.flags()|ios::fixed); // output of fixed point numbers output<<"GROEBNER"<0) output<number_of_generators()<format_print(output); output<0) delete[] F; delete I; return 1; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// int Bigatti_LaScala_Robbiano(INPUT_FILE MATRIX, const int& version, const int& S_pair_criteria, const float& interred_percentage, const BOOLEAN& verbose) { /////////////////////////// input ///////////////////////////////////////// char format_string[128]; // to verifie file format int constraints; // number of equality constraints int variables; // number of variables ifstream input(MATRIX); // verfifie existence of file if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "cannot read from input file, possibly not found"<>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading format specification,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of variables / matrix columns,\n" "input format not accepted"<>variables; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of variables / matrix columns,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading cost vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading number of constraints / matrix rows,\n" "input format not accepted"<>constraints; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure when reading number of constraints / matrix rows,\n" "input format not accepted" <>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading matrix,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading positive row space vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading positive row space vector,\n" "input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading positive row space vector,\n" " input format not accepted"<>format_string; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):\n" "input failure before reading positive row space vector,\n" "input format not accepted"<>hom_grad[_i]; if(!input) { cerr<<"ERROR: int Bigatti_LaScala_Robbiano(INPUT_FILE, const BOOLEAN&):" "\n" "input failure when reading positive grading / row space vector,\n" "input format not accepted"<0) output<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading format specification of second input file,\n" "input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading algorithm from second input file,\n" "input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading algorithm from second input file,\n" "input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading algorithm from second input file,\n" "input format not accepted"<>algorithm; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading algorithm from second input file,\n" "input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading term ordering from second \n" "input file, input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading term ordering \n" "from second input file, input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from second input file, input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from second input file, input format not accepted"<>elimination_variables; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from second input file, input format not accepted"<0) { groebner>>elimination_refinement; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from second input file, input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from second input file, input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from second input file, input format not accepted"<>weighted_variables; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from second input file, input format not accepted"<>weighted_refinement; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from second input file, input format not accepted"<0) { int elimination_ref; if(!strcmp(elimination_refinement,"LEX")) elimination_ref=LEX; if(!strcmp(elimination_refinement,"DEG_LEX")) elimination_ref=DEG_LEX; if(!strcmp(elimination_refinement,"DEG_REV_LEX")) elimination_ref=DEG_REV_LEX; w.convert_to_elimination_ordering(elimination_variables,elimination_ref); if(w.error_status()<0) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading new cost vector from second input file,\n" "input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading number of ideal generators \n" "from second input file, input format not accepted"<>size; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading number of ideal generators \n" "from second input file, input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading ideal generators \n" "from second input file, input format not accepted"<>format_string; if(!groebner) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading ideal generators \n" "from second input file, input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading format specification of first input file,\n" "input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading vector dimension from first input file,\n" "input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading vector dimension from first input file,\n" "input format not accepted"<>problem_variables; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading vector dimension from first input file,\n" "input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading number of instances from first input file," "\n" "input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading number of instances from first input file," "\n" "input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading number of instances from first input file," "\n" "input format not accepted"<>instances; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading number of instances from first input file,\n" "input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading right hand / initial solution vectors \n" "from first input file, input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading right hand / initial solution vectors \n" "from first input file, input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading right hand / initial solution vectors \n" "from first input file, input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading right hand / initial solution vectors \n" "from first input file, input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading right hand / initial solution vectors \n" "from first input file, input format not accepted"<>format_string; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure before reading right hand / initial solution vectors \n" "from first input file, input format not accepted"<>right_hand[i]; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading right hand vector "<>right_hand[i]; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading right hand vector "<>initial_solution[i]; if(!problem) { cerr<<"ERROR: int solve(INPUT_FILE, INPUT_FILE):\n" "input failure when reading right hand vector "<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading format specification of first input file,\n" "input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading algorithm from first input file,\n" "input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading algorithm from first input file,\n" "input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading algorithm from first input file,\n" "input format not accepted"<>algorithm; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading algorithm from first input file,\n" "input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading term ordering from first \n" "input file, input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading term ordering \n" "from first input file, input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from first input file, input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from first input file, input format not accepted"<>elimination_variables; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from first input file, input format not accepted"<0) { old>>elimination_refinement; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from first input file, input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from first input file, input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from first input file, input format not accepted"<>weighted_variables; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from first input file, input format not accepted"<>weighted_refinement; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading term ordering \n" "from first input file, input format not accepted"<>format_string; if(!_new) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading format specification\n" "from second input file, input format not accepted"<>format_string; if(!_new) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading number of variables \n" "from second input file, input format not accepted"<>new_variables; if(!_new) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading number of variables \n" "from second input file, input format not accepted"<>format_string; if(!_new) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading new cost vector from second input file,\n" "input format not accepted"<>format_string; if(!_new) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading new cost vector from second input file,\n" "input format not accepted"<0) { int elimination_ref; if(!strcmp(elimination_refinement,"LEX")) elimination_ref=LEX; if(!strcmp(elimination_refinement,"DEG_LEX")) elimination_ref=DEG_LEX; if(!strcmp(elimination_refinement,"DEG_REV_LEX")) elimination_ref=DEG_REV_LEX; w.convert_to_elimination_ordering(elimination_variables,elimination_ref); if(w.error_status()<0) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading new cost vector from second input file,\n" "input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading number of ideal generators \n" "from first input file, input format not accepted"<>old_size; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure when reading number of ideal generators \n" "from first input file, input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading ideal generators \n" "from first input file, input format not accepted"<>format_string; if(!old) { cerr<<"ERROR: int change_cost(INPUT_FILE, INPUT_FILE):\n" "input failure before reading ideal generators \n" "from first input file, input format not accepted"<0) output<0) output< // where is an abbreviation for the used algorithm: // ct for Conti_Traverso(...) // pct for Positive_Conti_Traverso(...) // ect for Elim_Conti_Traverso(...) // pt for Pottier(...) // hs for Hosten_Sturmfels(...) // du for DiBiase_Urbanke(...) // blr for Bigatti_LaScala_Robbiano(...) extern int Conti_Traverso(INPUT_FILE MATRIX, const int& version=1, const int& S_pair_criteria=11, const float& interred_percentage=12.0, const BOOLEAN& verbose=FALSE); // The complete algorithm of Conti and Traverso which computes the toric // ideal of an extended matrix and which can be used for solving // integer programs without initial solution. extern int Positive_Conti_Traverso(INPUT_FILE MATRIX, const int& version=1, const int& S_pair_criteria=11, const float& interred_percentage=12.0, const BOOLEAN& verbose=FALSE); // The variant of the above algorithm for matrices and right hand vector // with only nonnegative entries using one elimination variable less. extern int Elim_Conti_Traverso(INPUT_FILE MATRIX, const int& version=1, const int& S_pair_criteria=11, const float& interred_percentage=12.0, const BOOLEAN& verbose=FALSE); // A version of the Conti-Traverso-algorithm which really computes the toric // ideal of A. Used for test purposes (correctness and performance of the // other algorithms). Nonnegativity is ignored. extern int Pottier(INPUT_FILE MATRIX, const int& version=1, const int& S_pair_criteria=11, const float& interred_percentage=12.0, const BOOLEAN& verbose=FALSE); // The algorithm proposed by Pottier using one elimination variable and // a lattice basis of the matrix kernel to compute the toric ideal A. extern int Hosten_Sturmfels(INPUT_FILE MATRIX, const int& version=1, const int& S_pair_criteria=11, const float& interred_percentage=12.0, const BOOLEAN& verbose=FALSE); // The algorithm proposed by Hosten and Sturmfels which computes the toric // ideal of A from its kernel lattice basis without supplementary // variables, but with various Groebner basis calculations. extern int DiBiase_Urbanke(INPUT_FILE MATRIX, const int& version=1, const int& S_pair_criteria=11, const float& interred_percentage=12.0, const BOOLEAN& verbose=FALSE); // The algorithm proposed by DiBiase and Urbanke which computes the toric // ideal of A from its kernel lattice basis using "variable flips". extern int Bigatti_LaScala_Robbiano(INPUT_FILE MATRIX, const int& version=1, const int& S_pair_criteria=11, const float& interred_percentage=12.0, const BOOLEAN& verbose=FALSE); // A modified version of the algorithm called EATI using "pseudo-elimination". // This algorithm is quite similar to Pottier's algorithm, but deals with // homogenous binomials. // The second step of the IP-solution is to reduce one or more given // initial solutions (which also define right-hand vectors b) with respect // to the computed Groebner basis. In the case that the Groebner basis // was computed via the algorithm of Conti and Traverso, it is sufficient // to give the right-hand vectors. In all other cases we need explicit // initial solutions. The routine extern int solve(INPUT_FILE PROBLEM, INPUT_FILE GROEBNER); // solves the IP-problems given by the vectors in PROBLEM with respect // to GROEBNER which should contain a Groebner basis as computed above. The // output is appended to a (eventually newly created) file named as GROEBNER // with extensions replaced by: // .sol. // where is an abbreviation of the algorithm used to compute GROEBNER. // We also provide functionality to recompute toric ideals with respect to // another cost function: extern int change_cost(INPUT_FILE GROEBNER, INPUT_FILE NEW_COST, const int& version=1, const int& S_pair_criteria=11, const float& interred_percentage=12.0, const BOOLEAN& verbose=FALSE); // recomputes the Groebner basis in GROEBNER with respect to the cost given // in NEW_COST and writes the result into the file named as NEW_COST with // extension replaced by // .GB. // where is an abbreviation of the algorithm used to compute GROEBNER. ////////////////////////////////////////////////////////////////////////////// //////////// FORMAT OF INPUT AND OUTPUT FILES /////////////////////// ////////////////////////////////////////////////////////////////////////////// // The files appearing under the name MATRIX in the above declarations should // look as follows to be accepted by the algorithms: // MATRIX (* specifie format *) // // columns: // // // cost vector: // // // rows: // // // matrix: // // // positive row space vector: (* optional, see below *) // // For example: // MATRIX // // columns: // 3 // // cost vector: // 1 1 1 // // rows: // 2 // // matrix: // 1 2 3 // 4 5 6 // // positive row space vector: // 1 2 3 // The positive row space vector is only needed by the algorithms of // Hosten/Sturmfels and Bigatti/LaScala/Robbiano. It is ignored by the other // algorithms, as well as further lines in the input file. This allows us to // use the same input format for all algorithms. The comments (as the word // "rows:") are only written into the file to make it easy to read. // The file named NEW_COST in the change_cost procedure should have the // following format: // NEW_COST // // variables: (* only weighted variables *) // // // cost vector: // // For convenience, the MATRIX format is also accepted by the change_cost // procedure. The lines following the cost vector are then ignored. // The files appearing under the name GROEBNER in the above declarations // are created in the following form by the algorithms for computing toric // ideals. This form is accepted by the solve(...) and the // change_cost(...) procedures: // GROEBNER (* specifie format *) // // computed with algorithm: // (* abbreviations as above *) // from file(s): (* the following four lines are // optional *) // computation time: // // // term ordering: // elimination block // // variables >0 *) // weighted block // // should always >0 *) // // // size: // // // Groebner basis: // (* one basis element in each row, // given by the coefficients of // its vector representation *) // settings for the (* all following lines are // Buchberger algorithm: optional, verbose mode *) // version: (* as explained in ideal.h, // between 0 and 3 *) // S-pair criteria: // <{relatively prime leading terms, (* a subset of these criteria *) // criterion M, criterion F, // criterion B, second criterion}> // interreduction percentage: // // // compiler settings: (* see the procedure // ... print_flags(...) in // ... IP_algorithms.cc *) // If the GROEBNER file is created by change_cost(...), the algorithm name // and MATRIX file are chosen as those of the original GROEBNER file; the // new_cost file is specified as a second MATRIX file. // The files appearing under the name PROBLEM in the above declarations should // look as follows to be accepted by the procedure solve(...): // PROBLEM (* specifie format *) // // vector size: // // // number of instances: // // // right hand or initial solution vectors: // (* one vector per row *) // solve(...) verifies if the vector size given in the PROBLEM file and // the number of variables given in the GROEBNER file match the respective // algorithm. In the matching case, it creates a SOLUTION file of the // following format (not used as an input file for any procedure): // SOLUTION (* specifie format *) // // computed with algorithm: (* from the respective // GROEBNER file *) // from file: (* the GROEBNER file *) // // // vector: // // solvable: (* only if right-hand // vector is given *) // optimal solution: (* only in the case of // existence *) // computation time: (* only reduction time *) // // // ... (* further vectors *) #endif singular-4.0.3+ds/IntegerProgramming/LLL.cc000066400000000000000000000320321266270727000205070ustar00rootroot00000000000000#ifndef LLL_CC #define LLL_CC #include "LLL.h" // subroutines for the LLL-algorithms void REDI_KB(const short& k, const short& l, BigInt** b, const short& number_of_vectors, const short& vector_dimension, BigInt** H, BigInt* d, BigInt** lambda) // the REDI procedure for relations(...) (to compute the Kernel Basis, // algorithm 2.7.2 in Cohen's book) { #ifdef GMP if(abs(BigInt(2)*lambda[k][l])<=d[l+1]) #else // GMP if(labs(2*lambda[k][l])<=d[l+1]) // labs is the abs-function for long ints #endif // GMP return; #ifdef GMP BigInt q=(BigInt(2)*lambda[k][l]+d[l+1])/(BigInt(2)*d[l+1]); #else // GMP long q=(long int) floor(((float)(2*lambda[k][l]+d[l+1]))/(2*d[l+1])); #endif // GMP // q is the integer quotient of the division // (2*lambda[k][l]+d[l+1])/(2*d[l+1]). // Because of the rounding mode (always towards zero) of GNU C++, // we cannot use the built-in integer division // here; it causes errors when dealing with negative numbers. Therefore // the complicated casts: The divident is first casted to a float which // causes the division result to be a float. This result is explicitly // rounded downwards. As the floor-function returns a double (for range // reasons), this has to be casted to an integer again. for(short n=0;n1) for(short j=0;j<=k-2;j++) { // exchange lambda[k][j] and lambda[k-1][j] BigInt swap=lambda[k][j]; lambda[k][j]=lambda[k-1][j]; lambda[k-1][j]=swap; } BigInt _lambda=lambda[k][k-1]; BigInt B=(d[k-1]*d[k+1] + _lambda*_lambda)/d[k]; // It might be better to choose another evaluation order for this formula, // see below. for(short i=k+1;i<=k_max;i++) { BigInt t=lambda[i][k]; lambda[i][k]=(d[k+1]*lambda[i][k-1] - _lambda*t)/d[k]; lambda[i][k-1]=(B*t + _lambda*lambda[i][k])/d[k+1]; } d[k]=B; } void SWAPK(const short& k, const short& k_max, BigInt** b, BigInt** H, char *f, BigInt* d, BigInt** lambda) // the SWAPK procedure of algorithm 2.7.2 { // exchange H[k] and H[k-1] // This can be done efficiently by swapping pointers (not entries). BigInt *swap=H[k]; H[k]=H[k-1]; H[k-1]=swap; // exchange b[k] and b[k-1] by the same method swap=b[k]; b[k]=b[k-1]; b[k-1]=swap; if(k>1) for(short j=0;j<=k-2;j++) { // exchange lambda[k][j] and lambda[k-1][j] BigInt swap=lambda[k][j]; lambda[k][j]=lambda[k-1][j]; lambda[k-1][j]=swap; } BigInt _lambda=lambda[k][k-1]; if(_lambda==BigInt(0)) { d[k]=d[k-1]; f[k-1]=0; f[k]=1; lambda[k][k-1]=0; for(short i=k+1;i<=k_max;i++) { lambda[i][k]=lambda[i][k-1]; lambda[i][k-1]=0; } } else // lambda!=0 { for(short i=k+1;i<=k_max;i++) lambda[i][k-1]=(_lambda*lambda[i][k-1])/d[k]; // Multiplie lambda[i][k-1] by _lambda/d[k]. // One could also write // lambda[i][k-1]*=(lambda/d[k]); (*) // Without a BigInt class, this can prevent overflows when computing // _lambda*lambda[i][k-1]. // But examples show that lambda/d[k] is in general not an integer. // So (*) could lead to problems due to the inexact floating point // arithmetic... // Therefore, we chose the secure evaluation order in all such cases. BigInt t=d[k+1]; d[k]=(_lambda*_lambda)/d[k]; d[k+1]=d[k]; for(short j=k+1;j<=k_max-1;j++) for(short i=j+1;i<=k_max;i++) lambda[i][j]=(lambda[i][j]*d[k])/t; for(short j=k+1;j<=k_max;j++) d[j+1]=(d[j+1]*d[k])/t; } } typedef BigInt* BigIntP; short relations(BigInt **b, const short& number_of_vectors, const short& vector_dimension, BigInt**& H) { // first check arguments if(number_of_vectors<0) { cerr<<"\nWARNING: short relations(BigInt**, const short&, const short&, " "BigInt**):\nargument number_of_vectors out of range"<k. // Step 1: Initialization short k=1; short k_max=0; // for iteration d[0]=1; BigInt t=0; for(short m=0;m=number_of_vectors. do { // Step 2: Incremental Gram-Schmidt if(k>k_max) // else we can immediately go to step 3. { k_max=k; for(short j=0;j<=k;j++) if((f[j]==0) && (j1) k--; else k=1; // k=max(1,k-1) } else break; } while(1); // Now the conditions above are no longer satisfied. for(short l=k-2;l>=0;l--) if(f[l]!=0) REDI_KB(k,l,b,number_of_vectors,vector_dimension,H,d,lambda); k++; // Step 4: Finished? } while(k0) H=new BigIntP[r]; for(short i=0;ik. // Step 1: Initialization short k=1; short k_max=0; // for iteration d[0]=1; d[1]=0; for(short n=0;nr. do { // Step 2: Incremental Gram-Schmidt if(k>k_max) // else we can immediately go to step 3. { k_max=k; for(short j=0;j<=k;j++) { BigInt u=0; // compute scalar product of b[k] and b[j] for(short n=0;n1) k--; // k=max(1,k-1) } else break; } while(1); // Now the condition above is no longer satisfied. for(short l=k-2;l>=0;l--) REDI_IL(k,l,b,vector_dimension,d,lambda); k++; // Step 4: Finished? } while(k: gcc 3.2.2 port singular-4.0.3+ds/IntegerProgramming/binomial.cc000066400000000000000000001252231266270727000216630ustar00rootroot00000000000000// binomial.cc // implementation of class binomial #ifndef BINOMIAL_CC #define BINOMIAL_CC #include #include "binomial__term_ordering.h" ///////////////////////// constructors and destructor ////////////////////// // For a better overview, the constructor code is separated for // NO_SUPPORT_DRIVEN_METHODS and SUPPORT_DRIVEN_METHODS. #ifdef NO_SUPPORT_DRIVEN_METHODS binomial::binomial(const short& number_of_variables) :_number_of_variables(number_of_variables) { exponent_vector=new Integer[_number_of_variables]; } binomial::binomial(const short& number_of_variables,const Integer* exponents) :_number_of_variables(number_of_variables) { // range check for rarely used constructors if(_number_of_variables<=0) { cerr<<"\nWARNING: binomial::binomial(const short&, const Integer*):\n" "argument out of range"<=0) for(short i=0;i<_number_of_variables;i++) exponent_vector[i]=exponents[i]; else for(short i=0;i<_number_of_variables;i++) exponent_vector[i]=-exponents[i]; } binomial::binomial(const binomial& b) :_number_of_variables(b._number_of_variables) { exponent_vector=new Integer[_number_of_variables]; for(short i=0;i<_number_of_variables;i++) exponent_vector[i]=b.exponent_vector[i]; } #endif // NO_SUPPORT_DRIVEN_METHODS #ifdef SUPPORT_DRIVEN_METHODS binomial::binomial(const short& number_of_variables) :_number_of_variables(number_of_variables),head_support(0),tail_support(0) { exponent_vector=new Integer[_number_of_variables]; } binomial::binomial(const short& number_of_variables, const Integer* exponents) :_number_of_variables(number_of_variables),head_support(0),tail_support(0) { // range check for rarely used constructors if(_number_of_variables<=0) { exponent_vector=NULL; // to avoid problems when deleting cerr<<"\nWARNING: binomial::binomial(const short&, const Integer*):\n" "argument out of range"<0) head_support|=(1<=0) sign=1; else sign=-1; for(short i=0;i<_number_of_variables;i++) { #ifdef SUPPORT_VARIABLES_FIRST Integer actual_entry=sign*exponents[i]; exponent_vector[i]=actual_entry; #endif // SUPPORT_VARIABLES_FIRST #ifdef SUPPORT_VARIABLES_LAST short j=_number_of_variables-1-i; Integer actual_entry=sign*exponents[j]; exponent_vector[j]=actual_entry; #endif // SUPPORT_VARIABLES_LAST if(i0) head_support|=(1<comp_value) return(FALSE); return(TRUE); } BOOLEAN binomial::operator>=(const Integer comp_value) const { #ifdef SUPPORT_DRIVEN_METHODS if(comp_value==0) if(tail_support!=0) return(FALSE); #endif for(short i=0;i<_number_of_variables;i++) if(exponent_vector[i]0 and b.exponent_vector[i]>0 // (0 if there are no such quotients). // A negative return value means b=0 or head(b)=1. { #ifdef NO_SUPPORT_DRIVEN_METHODS Integer result=-1; Integer new_result=-1; // -1 stands for infinitely many reductions for(short i=0;i<_number_of_variables;i++) // explicit sign tests for all components { Integer actual_b_component=b.exponent_vector[i]; if(actual_b_component>0) // else variable i is not involved in the head of b { Integer actual_component=exponent_vector[i]; if(actual_component=1 if((new_result_number_of_variables) size_of_support_vectors=_number_of_variables; // number of components of the support vectors #ifdef SUPPORT_VARIABLES_FIRST for(short i=0;i0 ! // (head support contains that of b) if(new_result==0) // exponent_vector[i]=1 if((new_result0) // else variable i is not involved in the head of b { Integer actual_component=exponent_vector[i]; if(actual_component=1 if((new_result0 ! // (head support contains that of b) if(new_result==0) // exponent_vector[_number_of_variables-1-i] // =1 if((new_result0) // else variable number_of_variables-1-i is not involved in the head of b { Integer actual_component=exponent_vector[j]; if(actual_component=1 if((new_result0 // (0 if there are no such quotients). // A negative return value means b=0 or head(b)=1. { #ifdef NO_SUPPORT_DRIVEN_METHODS Integer result=-1; Integer new_result=-1; // -1 stands for infinitely many reductions for(short i=0;i<_number_of_variables;i++) // explicit sign tests for all components { Integer actual_b_component=b.exponent_vector[i]; if(actual_b_component>0) // else variable i is not involved in the head of b { Integer actual_component=-exponent_vector[i]; if(actual_component=1 if((new_result_number_of_variables) size_of_support_vectors=_number_of_variables; // number of components of the support vectors #ifdef SUPPORT_VARIABLES_FIRST for(short i=0;i=1 if((new_result0) // else variable i is not involved in the head of b { Integer actual_component=-exponent_vector[i]; if(actual_component=1 if((new_result=1 if((new_result0) // else variable number_of_variables-1-i is not involved in the head of b { Integer actual_component=-exponent_vector[j]; if(actual_component=1 if((new_result0) head_support|=(1<0) head_support|=(1<0) head_support|=(1<0) head_support|=(1<0) result.head_support|=(1<0) result.head_support|=(1<0) && (b.exponent_vector[i]>0)) return FALSE; return TRUE; #endif // NO_SUPPORT_DRIVEN_METHODS #ifdef SUPPORT_DRIVEN_METHODS if((a.head_support & b.head_support)!=0) // common support variable in the heads return FALSE; // no common support variable in the heads, look at remaining variables short size_of_support_vectors=CHAR_BIT*sizeof(unsigned long); #ifdef SUPPORT_VARIABLES_FIRST for(short i=size_of_support_vectors;i0) && (b.exponent_vector[i]>0)) return FALSE; return TRUE; #endif // SUPPORT_VARIABLES_FIRST #ifdef SUPPORT_VARIABLES_LAST for(short i=a._number_of_variables-1-size_of_support_vectors;i>=0;i--) if((a.exponent_vector[i]>0) && (b.exponent_vector[i]>0)) return FALSE; return TRUE; #endif // SUPPORT_VARIABLES_LAST #endif // SUPPORT_DRIVEN_METHODS } BOOLEAN M(const binomial& a, const binomial& b, const binomial& c) // Returns TRUE iff lcm(head(a),head(c)) divides properly lcm(head(b),head(c)). // This is checked by comparing the positive components of the exponent // vectors. { #ifdef SUPPORT_DRIVEN_METHODS long b_or_c=b.head_support|c.head_support; if((a.head_support|b_or_c) != b_or_c) return FALSE; // The support of lcm(head(a),head(c)) equals the union of the head supports // of a and c. The above condition verifies if the support of // lcm(head(a),head(c)) is contained in the support of lcm(head(b),head(c)) // by checking if head a involves a variable that is not involved in // head(b) or head(c). #endif // SUPPORT_DRIVEN_METHODS BOOLEAN properly=FALSE; for(short i=0;i0) { if(m1>m2) return FALSE; if(m10 || m2>0)) return FALSE; } return TRUE; } BOOLEAN B(const binomial& a, const binomial& b, const binomial& c) // verifies if head(a) divides lcm(head(b),head(c)) and // lcm(head(a),head(b))!=lcm(head(b),head(c))!=lcm(head(a),head(c)) { #ifdef SUPPORT_DRIVEN_METHODS long a_or_b=a.head_support|b.head_support; long a_or_c=a.head_support|c.head_support; long b_or_c=b.head_support|c.head_support; if((a.head_support & b_or_c)!=a.head_support) return FALSE; // The above condition verifies if the support of head(a) is contained in // the support of lcm(head(b),head(c)). if( (a_or_c != b_or_c) && (a_or_b != b_or_c)) // Then the inequality conditions are guaranteed... { for(short i=0;iMAXIMUM(b_exponent,c_exponent)) return FALSE; } return (TRUE); } if(a_or_b != b_or_c) // Then the first inequality conditions is guaranteed... // Verifie only the second. { BOOLEAN not_equal=FALSE; for(short i=0;im) return FALSE; if(MAXIMUM(a_exponent,c_exponent) != m) not_equal=TRUE; } return(not_equal); } if( a_or_c != b_or_c ) // Then the second inequality conditions is guaranteed... // Verifie only the first. { BOOLEAN not_equal=FALSE; for(short i=0;i m) return FALSE; if(MAXIMUM(a_exponent,b_exponent) != m) not_equal=TRUE; } return(not_equal); } #endif // SUPPORT_DRIVEN_METHODS BOOLEAN not_equal_1=FALSE; BOOLEAN not_equal_2=FALSE; for(short i=0;i m) return FALSE; if(MAXIMUM(a_exponent,b_exponent) != m) not_equal_1=TRUE; if(MAXIMUM(a_exponent,c_exponent) != m) not_equal_2=TRUE; } return (not_equal_1 && not_equal_2); } BOOLEAN second_crit(const binomial& a, const binomial& b, const binomial& c) // verifies if head(a) divides lcm(head(b),head(c)) { #ifdef SUPPORT_DRIVEN_METHODS if((a.head_support & (b.head_support|c.head_support))!=a.head_support) return FALSE; // The above condition verifies if the support of head(a) is contained in // the support of lcm(head(b),head(c)) #endif // SUPPORT_DRIVEN_METHODS. for(short i=0;iMAXIMUM(b_exponent,c_exponent)) return FALSE; } return (TRUE); } //////// special routines needed by the IP-algorithms /////////////////////// BOOLEAN binomial::involves_elimination_variables(const term_ordering& w) { // The use of support information would require the distinction of various // cases here (relation between the number of variables to eliminate // and the number of support variables) and be quite difficult. // It is doubtful if this would improve performance. // As this function is not used in Buchberger´s algorithm (and therefore // rather rarely), I renounce to implement this. for(short i=0;i=0) for(short i=0;i<_number_of_variables;i++) exponent_vector[i]=aux[i]; else for(short i=0;i<_number_of_variables;i++) exponent_vector[i]=-aux[i]; delete[] aux; #ifdef SUPPORT_DRIVEN_METHODS // Recompute head and tail. // Normally, this routine is only called for binomials that do not involve // the variables to eliminate. But if SUPPORT_VARIABLES_LAST is enabled, // the support changes in spite of this. Therefore, the support is // recomputed... For the same reasons as mentionned in the preceeding // routine, the existing support information is not used. head_support=0; tail_support=0; short size_of_support_vectors=CHAR_BIT*sizeof(unsigned long); if(size_of_support_vectors>_number_of_variables) size_of_support_vectors=_number_of_variables; #ifdef SUPPORT_VARIABLES_FIRST for(short i=0;i0) head_support|=(1<0) head_support|=(1<=0) { for(short i=0;i_number_of_variables) size_of_support_vectors=_number_of_variables; #ifdef SUPPORT_VARIABLES_FIRST for(short i=0;i0) head_support|=(1<0) head_support|=(1<_number_of_variables) size_of_support_vectors=_number_of_variables; #ifdef SUPPORT_VARIABLES_FIRST if(i0) // bit i will be 1 in the new head_support, 0 in the new tail_support { head_support|=(1<0) // bit j will be 1 in the new head_support, 0 in the new tail_support { head_support|=(1<=_number_of_variables-size_of_support_vectors) // else i is no support variable { if(exponent_vector[j]>0) // bit _number_of_variables-1-i will be 1 in the new head_support, // 0 in the new tail_support { short k=_number_of_variables-1-i; head_support|=(1<=_number_of_variables-size_of_support_vectors) // else j is no support variable { if(exponent_vector[i]>0) // bit _number_of_variables-1-j will be 1 in the new head_support, // 0 in the new tail_support { short k=_number_of_variables-1-j; head_support|=(1<_number_of_variables) size_of_support_vectors=_number_of_variables; #ifdef SUPPORT_VARIABLES_FIRST if(i0) // variable i will be moved from head to tail { head_support&=~(1<=_number_of_variables-size_of_support_vectors) // else i is no support variable { if(exponent_vector[i]>0) // variable i will be moved from head to tail { short k=_number_of_variables-1-i; head_support&=~(1<=(const Integer comp_value) const; // operators for an efficient comparison with the zero binomial // (comp_value=0) // basic routines for Buchbergers's algorithm Integer head_reductions_by(const binomial& b) const; // Returns the number of possible reductions of the actual binomial's head // by the binomial b. // The return value -1 means that b==0 or head(b)==1; one should not try // reduce by such a binomial (reduction is undefined or does not terminate). // The procedure reduce_tail_by(...) returns the unchanged binomial in such // a case without a warning. This is done in view of the application: // If a generator of an ideal is reduced to zero during a Groebner basis // calculation and one forgets to delete it, this generator is ignored // (else it would probably cause a fatal error). Integer tail_reductions_by(const binomial& b) const; // Returns the number of possible reductions of the actual binomial's tail // by the binomial b. // For the return value -1 see above. int reduce_head_by(const binomial& b, const term_ordering& w); // Performs a multiple reduction of the actual binomial's head by the // binomial b and computes the new head and tail with respect to the term // ordering w. // The return value is 1 if the binomial has really been reduced, 2 if // the binomial has been reduced to zero, 0 if the binomial has not been // changed. int reduce_tail_by(const binomial& b, const term_ordering& w); // Performs a multiple reduction of the actual binomial's tail by the // binomial b and computes the new head and tail with respect to the term // ordering w. // The return value is 1 if the binomial has really been reduced, else 0. // (By a tail reduction, the binomial cannot be reduced to zero if the // binomial itself and b are consistent with w, i.e. if head and tail are // correct.) friend binomial& S_binomial(const binomial& a, const binomial& b, const term_ordering& w); // Computes the S-binomial of a and b with respect to the term ordering w // and returns a reference on it (the necessary memory is allocated during // the computation). // criteria for unnecessary S-Pairs friend BOOLEAN relatively_prime(const binomial& a, const binomial& b); // Returns TRUE iff the leading terms of a and b are relatively prime. friend BOOLEAN M(const binomial& a,const binomial& b,const binomial& c); // Verifies if lcm(head(a),head(c)) divides properly lcm(head(b),head(c)). friend BOOLEAN F(const binomial& a, const binomial& b, const binomial& c); // Verifies if lcm(head(a),head(c))=lcm(head(b),head(c)). friend BOOLEAN B(const binomial& a, const binomial& b, const binomial& c); // Verifies if head(a) divides lcm(head(b),head(c)) and // lcm(head(a),head(b))!=lcm(head(b),head(c))!=lcm(head(a),head(c)). friend BOOLEAN second_crit(const binomial& a, const binomial& b, const binomial& c); // Verifies if head(a) divides lcm(head(b),head(c)). // special routines needed by the IP-algorithms // All this routines are not very frequently used (especially not in // Buchberger's algorithm), so I haven't spent much time in optimization. // None of them performs range checks on their arguments. BOOLEAN involves_elimination_variables(const term_ordering& w); // Verifies if the binomial involves elimination variables with respect // to w. // UNCHECKED PRECONDITION: w and the binomial are compatible, i.e. // involve the same number of variables. BOOLEAN drop_elimination_variables(const term_ordering& w); // Cuts the elimination variables (with respect to w) from the binomial // and adapts the member _number_of_variables as well as the head and the // tail. // UNCHECKED PRECONDITION: w and the binomial are compatible. // The interesting part of the binomial (ot its additive inverse) is copied // hereby to be able to free the memory needed by the dropped components. BOOLEAN drop_last_weighted_variable(const term_ordering& w); // Cuts the last variable from the binomial and adapts the member // _number_of_variables as well as head and tail (the last two to the given // term_ordering) // UNCHECKED PRECONDITION: w is a weighted termordering (without elimination // variables) that is compatible to the actual binomial. // The interesting part of the binomial (ot its additive inverse) is copied // hereby to be able to free the memory needed by the dropped components. int adapt_to_term_ordering(const term_ordering&); // Determines head and tail of the binomial with respect to the given term // ordering; i.e. multiplies the exponent vector with -1 and exchanges // head_support and tail_support, if necessary. // Returns -1 if head and tail were exchanged, 1 else. // UNCHECKED PRECONDITION: w and the binomial are compatible. binomial& swap_variables(const short& i,const short& j); // Swaps the components i and j of the exponent vector and actualizes // head_support and tail_support. // No range check on the arguments! binomial& flip_variable(const short& i); // Inverts component i of the exponent vector and actualizes head_support // and tail_support. // No range check on i! // output void print() const; void print_all() const; // Writes the actual binomial to the standard output medium. // The first routine only prints the exponent vector, the second prints // the head and tail support, too (if SUPPORT_DRIVEN_METHODS are used). void print(FILE* output) const; void print_all(FILE* output) const; // Writes the actual binomial to the referenced file which must have // been opened for writing before. void print(ofstream&) const; void print_all(ofstream&) const; // Writes the actual binomial to the given ofstream. void format_print(ofstream&) const; // Writes the given binomial to the actual ofstream in the format needed // by the IP-algorithms. friend class ideal; // The class ideal is declared as a friend for efficiency reasons: // This avoids many unnecessary function calls for inspecting members // like head_support and tail_support. // The class ideal does not change any members of the binomial class. friend short term_ordering::compare(const binomial&, const binomial&) const; }; #endif // BINOMIAL_H singular-4.0.3+ds/IntegerProgramming/binomial__term_ordering.h000066400000000000000000000006661266270727000246070ustar00rootroot00000000000000// binomial__term_ordering.h // The class binomial needs to know the class term_ordering and vice versa. // But for a beautiful design, I did not want to write this declarations // into the same file. The file binter.h simply puts the two corresponding // header files together. #ifndef BINOMIAL__TERM_ORDERING_H #define BINOMIAL__TERM_ORDERING_H #include "term_ordering.h" #include "binomial.h" #endif // BINOMIAL__TERM_ORDERING_H singular-4.0.3+ds/IntegerProgramming/change_cost.cc000066400000000000000000000124341266270727000223450ustar00rootroot00000000000000// change_cost.cc // This file provides an interface for changing the cost vector in IP-problems // and for recomputing Groebner basis of toric ideals. #ifndef CHANGE_COST_CC #define CHANGE_COST_CC #include "IP_algorithms.h" int main(int argc, char *argv[]) { // initialize arguments for the IP-algorithms (Buchberger) // with default settings BOOLEAN verbose=FALSE; short version=1; short S_pair_criteria=11; double interreduction_percentage=12.0; ///////////////////////// parse options ///////////////////////////////////// if(argc>=3) // argc has to be at least 3 (except when help is required, see below): // program name, GROEBNER file, NEW_COST file { for(short i=1;i=argc-2) // file arguments reached break; if(!strcmp(argv[i],"RP")) { S_pair_criteria|=1; continue; } if(!strcmp(argv[i],"M")) { S_pair_criteria|=2; continue; } if(!strcmp(argv[i],"F")) { S_pair_criteria|=4; continue; } if(!strcmp(argv[i],"B")) { S_pair_criteria|=8; continue; } if(!strcmp(argv[i],"2")) { S_pair_criteria|=16; continue; } // option does not belong to an S-pair criterion break; } while(1); i--; // reset counter so that the outer loop continue; // continues with the just considered argument } if(!strcmp(argv[i],"-p")) { // read interreduction percentage i++; char** rest; interreduction_percentage=strtod(argv[i],rest); // The function strtod converts a string into a double. As the // specification is not correct, it may cause trouble... // For example, if the argument can be read as a float, the value // of rest should be NULL. This is not the case. Therefore, we can // only check by the following string comparison if a float has been // built. An argument as 15xy is thereby considered as valid // (with interreduction_percentage==15.0). if(!(strcmp(argv[i],*rest))) // argument was no float { cerr<<"ERROR: invalid argument for interreduction percentage"< where GB stands for GROEBNER and is the abbreviation of the algorithm used for computing the input GROEBNER file (see the help for solve_IP or toric_ideal for an explaination). A GROEBNER file looks as follows: GROEBNER computed with algorithm: (* abbreviations as above *) from file(s): (* the following four lines are optional *) computation time: term ordering: elimination block variables >0 *) weighted block should always be >0 *) size: Groebner basis: (* optional *) The Groebner basis consists always of binomials of the form x^a - x^b where x^a and x^b are relatively prime. Such a binomial can be represented by the vector a-b. The basis elements in the GROEBNER file are given by the coefficients of this vector representation. The settings for Buchberger´s algorithm and the compiler flags are produced when the GROEBNER file is generated by a call of solve_IP with the verbose output option -v, --verbose Example: GROEBNER computed with algorithm: du term ordering: elimination block: 0 weighted block: 3 W_LEX 1 2 3 size: 1 Groebner basis: 2 3 -2 (* x^2 * y^3 - z^2 *) A NEW_COST file should look as follows: NEW_COST variables: cost vector: OPTIONS: -p percentage of new generators to cause an autoreduction during Buchberger´s algorithm; may be an arbitrary float, a negative value allows no intermediate autoreductions default is -p 12.0 -S [RP] [M] [B] [M] [2] criteria to use in Buchberger´s algorithm for discarding unneccessary S-pairs RP relatively prime leading terms M Gebauer-Moeller criterion M F Gebauer-Moeller criterion F B Gebauer-Moeller criterion B 2 Buchberger´s second criterion default is -S RP M B -v, --verbose verbose output mode; writes the settings for Buchberger´s algorithm and the compiler flags into the output GROEBNER file -V , --version version of Buchberger´s algorithm to use; may be 1, 1a, 2 or 3 default is -V 1 singular-4.0.3+ds/IntegerProgramming/gen_test.cc000066400000000000000000000037651266270727000217070ustar00rootroot00000000000000// gentest.cc // a program that generates some test data #ifndef GEN_TEST_CC #define GEN_TEST_CC #include "testdata.h" int main(void) { ofstream output1("IP/testmatrix1"); random_matrix(3,4,0,5,output1); ofstream output2("IP/testmatrix2"); random_matrix(4,6,0,5,output2); ofstream output3("IP/testmatrix3"); random_matrix(3,4,-5,5,output3); ofstream output4("IP/testmatrix4"); random_matrix(5,8,0,1,output4); ofstream output5("IP/testmatrix5"); transportation_problem(3,4,5,output5); ofstream output6("IP/testmatrix6"); transportation_problem(3,5,5,output6); ofstream output1a("IP/testproblem1a"); random_problems(3,5,-5,5,output1a); ofstream output1b("IP/testproblem1b"); random_problems(3,5,0,5,output1b); ofstream output1c("IP/testproblem1c"); random_problems(4,5,0,5,output1c); ofstream output2a("IP/testproblem2a"); random_problems(4,5,-5,5,output2a); ofstream output2b("IP/testproblem2b"); random_problems(4,5,0,5,output2b); ofstream output2c("IP/testproblem2c"); random_problems(6,5,0,5,output2c); ofstream output3a("IP/testproblem3a"); random_problems(3,5,-5,5,output3a); ofstream output3b("IP/testproblem3b"); random_problems(3,5,0,5,output3b); ofstream output3c("IP/testproblem3c"); random_problems(4,5,0,5,output3c); ofstream output4a("IP/testproblem4a"); random_problems(5,5,-5,5,output4a); ofstream output4b("IP/testproblem4b"); random_problems(5,5,0,5,output4b); ofstream output4c("IP/testproblem4c"); random_problems(8,5,0,5,output4c); ofstream output5a("IP/testproblem5a"); random_problems(3+4,5,-5,5,output5a); ofstream output5b("IP/testproblem5b"); random_problems(3+4,5,0,5,output5b); ofstream output5c("IP/testproblem5c"); random_problems(3*4,5,0,5,output5c); ofstream output6a("IP/testproblem6a"); random_problems(3+5,5,-5,5,output6a); ofstream output6b("IP/testproblem6b"); random_problems(3+5,5,0,5,output6b); ofstream output6c("IP/testproblem6c"); random_problems(3*5,5,0,5,output6c); return 0; } #endif singular-4.0.3+ds/IntegerProgramming/globals.h000066400000000000000000000201071266270727000213510ustar00rootroot00000000000000// globals.h // In this file // - some facilities as the g++ input/output routines are included, // - the general data type can be chosen (the people of Singular do not like // templates), // - some makros are defined for an easier handling of the program, // - some flags and constants can be set to observe the behaviour of the // algorithms when using different strategies. #ifndef GLOBALS_H #define GLOBALS_H // Include facilities needed by several files: // the following is not good! TODO: move to all including sources... #include #include #ifndef HAVE_IOSTREAM_H #include #include #include #include #else #include #include #include #include #endif #include #include #include #include using namespace std; // Include a BigInt class from a foreign library: // This is needed by the LLL algorithm. If no such class is included, // it computes with long ints; this results in overflows and unexpected // behaviour even when computing with relatively small instances. #define GMP #ifdef GMP #include "BigInt.h" #else // GMP typedef long BigInt; #endif // GMP // Define the general data type: // short seems to be sufficient for most practicable instances. typedef short Integer; // The general data type to deal with can be short, long or int... //#define _SHORT_ // For an overflow control for thE result of the LLL algorithm, we have to // know the data type used. // Define a BOOLEAN data type etc. for an easy-to-read code: typedef char BOOLEAN; #define TRUE 1 #define FALSE 0 #define MAXIMUM(a,b) (a>b? a:b) #define INHOMOGENEOUS 0 #define HOMOGENEOUS 1 // For a more comfortable call of the term_ordering constructors. // Enumerate the algorithms: // The ideal constructor (builds an ideal from the input matrix) depends on // the algorithm. The constants are defined to make constructor calls easier // (you do not need to remember a number). #define CONTI_TRAVERSO 1 #define POSITIVE_CONTI_TRAVERSO 2 #define POTTIER 3 #define HOSTEN_STURMFELS 4 #define DIBIASE_URBANKE 5 #define BIGATTI_LASCALA_ROBBIANO 6 // Enumerate the criteria to discard unnecessary S-pairs: // The constants are defined to allow an easier call of Buchberger´s algorithm // with different criteria. This algorithm takes as an argument a short int // which represents the combination of criteria to be used (with a default // combination if no argument is given). // The method to compute the argument for a certain combination is simple: // Simply add the constants that belong to criteria you want to use. As the // constants are chosen to be different powers of 2, each short int (in the // range of 0 to 31) gives a unique combination (cf. the read-write-execute // rights for files in UNIX systems). // EXAMPLE: // If you want to call Buchberger´s algorithm with the criterion "relatively // prime leading terms" and the second criterion for the ideal I, write: // // I.reduced_Groebner_basis_1(REL_PRIMENESS + SECOND_CRITERION); // or // I.reduced_Groebner_basis_1(17); // // The argument 0 means that no criteria are used, the argument 31 leads to // the use of all criteria. #define REL_PRIMENESS 1 #define M_CRITERION 2 #define F_CRITERION 4 #define B_CRITERION 8 #define SECOND_CRITERION 16 // The names of tehse criteria are chosen according to the criteria // described in Gebauer/Moeller (except from the last). // The first one (relatively prime leading terms) is a local criterion // and the most effective. // The last four criteria are global ones involving searches over the // generator lists. But although the lcm-computations performed by these // checks are not much cheaper than a reduction, most of the criteria seem to // accelerate the computations. // REL_PRIMENESS should always be used. // The Gebauer/Moeller-criteria (M,F,B) seem to improve computation time in // the general case; Buchberger's second criterion seems to improve it in // more special cases (for example the transportation problem). They should // be switched on and off according to these results, but never be enabled // together; the overhead of too many criteria leads to a rather bad // performance in all cases. // The relatively primeness criterion is tested first because it // is very easy to check. The order of the Gebauer/Moeller-criteria does not // really affect computation. The relative order of the Gebauer/Moeller // criteria and the second criterion (if they are enabled together) has almost // the same effect as switching off the last criterion in this order. // There is no possibility to change the order in which the criteria are // tested without changing the program! // Enumerate the term orderings that can be used to refine the weight: // W_REV_LEX will give a term ordering in the classical sense if and only if // all weights are positive. It has been implemented because several // algorithms need a reverse lexicographical refinement. (Of course, these // algorithms control if they have a positive grading.) // A warning will be output when using W_REV_LEX in an insecure case. #define W_LEX 4 #define W_REV_LEX 5 #define W_DEG_LEX 6 #define W_DEG_REV_LEX 7 // Enumerate the term ordering used for the block of elimination variables: #define LEX 1 #define DEG_LEX 2 #define DEG_REV_LEX 3 ////////////////////////////////////////////////////////////////////////////// /////////////// TEST PARAMETER SECTION //////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // Set flags concerning the basic operations and the course of Buchberger's // algorithm: #define SUPPORT_DRIVEN_METHODS // possibilities: // SUPPORT_DRIVEN_METHODS // NO_SUPPORT_DRIVEN_METHODS // This flag allows to switch of and on the use of the support vectors in // the binomial class; these are used to speed up tests for reducibility of // binomials, relative primeness etc. #define SUPPORT_DRIVEN_METHODS_EXTENDED // possibilities: // SUPPORT_DRIVEN_METHODS_EXTENDED // NO_SUPPORT_DRIVEN_METHODS_EXTENDED // This flag allows to switch of and on the extended use of the support // information. This includes the splitting of the ideal generators into // several lists according to their head support. This discards many // unnecessary tests for divisibility etc. // SUPPORT_DRIVEN_METHODS_EXTENDED should only be enabled when // SUPPORT_DRIVEN_METHODS is set, too! The combination // NO_SUPPORT_DRIVEN_METHODS and SUPPORT_DRIVEN_METHODS_EXTENDED is quite // senseless and will only work if your compiler automatically initializes // integers to zero. const unsigned short List_Support_Variables=8; // This is the number of variables considered to create and maintain the // generator lists of an ideal if SUPPORT_DRIVEN_METHODS_EXTENDED is // enabled. As there are 2^List_Support_Variables lists, this number // should not be too big (to avoid the overhead of many empty lists). // The best number may depend on the problem size and structure... #define SUPPORT_VARIABLES_LAST // possibilities: // SUPPORT_VARIABLES_LAST // SUPPORT_VARIABLES_FIRST // This flag determines whether the first or the last variables are considered // by the support methods. So this setting will only affect the computation if // such methods are enabled. // The reason for the introduction of this flag is the following: // The Conti-Traverso algorithm for solving an integer program works in two // phases: Given an artificial solution in auxiliary variables, these // variables are first eliminated to get a feasible solution. The elimination // variables are for technical reasons always the last. In a second phase, // this solution is reduced to a minimal solution with respect to a given // term ordering. // If SUPPORT_VARIABLES_LAST is set, the first phase will probably take // less time as if SUPPORT_VARIABLES_FIRST is set. If one is only interested // in finding a feasible solution (not necessary minimal), // SUPPORT_VARIABLES_LAST might be the better choice. #endif // GLOBALS_H singular-4.0.3+ds/IntegerProgramming/ideal.cc000066400000000000000000000722351266270727000211530ustar00rootroot00000000000000// ideal.cc // implementation of some general ideal functions #ifndef IDEAL_CC #define IDEAL_CC #include #include "ideal.h" ///////////////////////////////////////////////////////////////////////////// ////////////////// private member functions ///////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////// subset_tree data structure //////////////////////////////////// #ifdef SUPPORT_DRIVEN_METHODS_EXTENDED void ideal::create_subset_tree() { for(int i=0;i(const BigInt &)SHRT_MAX) || ((A.H)[j][k]<(const BigInt &)SHRT_MIN)) { cerr<<"\nWARNING: ideal& ideal::Pottier_ideal(matrix&, const " "term_ordering&):\n" "LLL-reduced kernel basis does not fit into the used " "basic data type int."<(const BigInt&)INT_MAX) || ((A.H)[j][k]<(const BigInt&)INT_MIN)) { cerr<<"\nWARNING: ideal& ideal::Pottier_ideal(matrix&, const " "term_ordering&):\n" "LLL-reduced kernel basis does not fit into the used " "basic data type int."<(const BigInt&)LONG_MAX) || ((A.H)[j][k]<(const BigInt&)LONG_MIN)) { cerr<<"\nWARNING: ideal& ideal::Pottier_ideal(matrix&, const " "term_ordering&):\n" "LLL-reduced kernel basis does not fit into the used " "basic data type long."<(const BigInt &)SHRT_MAX) || ((A.H)[j][k]<(const BigInt &)SHRT_MIN)) { cerr<<"\nWARNING: ideal& ideal::Hosten_Sturmfels_ideal(matrix&, const " "term_ordering&):\nLLL-reduced kernel basis does not fit " "into the used basic data type int."<(const BigInt&)INT_MAX) || ((A.H)[j][k]<(const BigInt&)INT_MIN)) { cerr<<"\nWARNING: ideal& ideal::Hosten_Sturmfels_ideal(matrix&, const " "term_ordering&):\nLLL-reduced kernel basis does not fit " "into the used basic data type int."<(const BigInt&)LONG_MAX) || ((A.H)[j][k]<(const BigInt&)LONG_MIN)) { cerr<<"\nWARNING: ideal& ideal::Hosten_Sturmfels_ideal(matrix&, const " "term_ordering&):\nLLL-reduced kernel basis does not fit " "into the used basic data type long."<0) { for(int i=0;i<_w.number_of_weighted_variables();i++) if((_w[i]!=0) && (i!=F[0])) ordering_okay=FALSE; } if(ordering_okay==FALSE) cerr<<"\nWARNING: ideal& ideal::DiBiase_Urbanke_ideal(matrix&, const " "term_ordering&):\nargument term ordering might be inappropriate"<(const BigInt &)SHRT_MAX) || ((A.H)[j][k]<(const BigInt &)SHRT_MIN)) { cerr<<"\nWARNING: ideal& ideal::DiBiase_Urbanke_ideal(matrix&, const " "term_ordering&):\nLLL-reduced kernel basis does not fit " "into the used basic data type int."<(const BigInt&)INT_MAX) || ((A.H)[j][k]<(const BigInt&)INT_MIN)) { cerr<<"\nWARNING: ideal& ideal::DiBiase_Urbanke_ideal(matrix&, const " "term_ordering&):\nLLL-reduced kernel basis does not fit " "into the used basic data type int."<(const BigInt&)LONG_MAX) || ((A.H)[j][k]<(const BigInt&)LONG_MIN)) { cerr<<"\nWARNING: ideal& ideal::DiBiase_Urbanke_ideal(matrix&, const " "term_ordering&):\nLLL-reduced kernel basis does not fit " "into the used basic data type long."<(const BigInt &)SHRT_MAX) || ((A.H)[j][k]<(const BigInt &)SHRT_MIN)) { cerr<<"\nWARNING: ideal& ideal::Bigatti_LaScala_Robbiano_ideal" "(matrix&, const term_ordering&):\nLLL-reduced kernel basis does " "not fit into the used basic data type int."<(const BigInt&)INT_MAX) || ((A.H)[j][k]<(const BigInt&)INT_MIN)) { cerr<<"\nWARNING: ideal& ideal::Bigatti_LaScala_Robbiano_ideal" "(matrix&, const term_ordering&):\nLLL-reduced kernel basis does " "not fit into the used basic data type int."<(const BigInt&)LONG_MAX) || ((A.H)[j][k]<(const BigInt&)LONG_MIN)) { cerr<<"\nWARNING: ideal& ideal::Bigatti_LaScala_Robbiano_ideal" "(matrix&, const term_ordering&):\nLLL-reduced kernel basis does " "not fit into the used basic data type long."<>generator[j]; if(!input) // input failure, set "error flag" { cerr<<"\nWARNING: ideal::ideal(ifstream&, const term_ordering&, " "const int&): \ninput failure when reading generator "<=w.number_of_weighted_variables()) || (j<0) || (j>=w.number_of_weighted_variables())) { cout<<"WARNING: ideal::swap_variables(const int&, const int&)\n " "or ideal::swap_variables_unsafe(const int&, const int&):\n" "index out of range"<=w.number_of_weighted_variables())) { cout<<"WARNING: ideal::flip_variables(const int&):\n" "argument out of range, nothing done"<previous=NULL; begin_dummy->next=end_dummy; begin_dummy->entry=NULL; begin_dummy->done=FALSE; begin_dummy->head_reduced=FALSE; end_dummy->previous=begin_dummy; #endif // DL_LIST end_dummy->next=NULL; end_dummy->entry=NULL; end_dummy->done=TRUE; end_dummy->head_reduced=TRUE; #ifdef DL_LIST start=begin_dummy; #endif // DL_LIST #ifdef SL_LIST start=end_dummy; #endif // SL_LIST } // The dummy elements have the following functions: // - The end_dummy guarantees that the deletion method of the simply linked // list works: Deletion is done by copying the next element to the actual // position and then deleting the original, see below for an explaination. // This would cause problems when deleting the last element; then the // next-pointer of the preceeding element would reference freed memory // (it cannot be manipulated, is unknown). So the end_dummy as an // artificial last element avoids this problem. // - With the described deletion method for a simply linked list, the start // pointer of a list has never to be changed by the list_iterator class // (as long as the list is not empty; but with the end_dummy, the list // never becomes empty). So a list iterator must never know on which list // he operates on. // Doubly linked lists use another, more secure deletion method (which // really deletes the actual element). Therefore, the comfort of a start // pointer which has never to be manipulated by the iterators must be // reached in another way: This is the purpose of the begin_dummy, an // artificial first element which is referenced by the start pointer and // never changed. // - With the dummy elements, we do need to distinguish the cases of inserting // or deleting at the beginning or the end of a list. // - Furthermore, the end_dummy is a stopper for Buchberger's algorithm: // By setting all flags to TRUE, we can eliminate many calls of the // is_at_end()-function of the list iterator class. // The dummy elements should never be deleted (the dletion method is not // secure)! list::list(const list& l) { #ifdef DL_LIST element* begin_dummy=new element; #endif // DL_LIST element* end_dummy=new element; #ifdef DL_LIST begin_dummy->previous=NULL; begin_dummy->next=end_dummy; begin_dummy->entry=NULL; begin_dummy->done=FALSE; begin_dummy->head_reduced=FALSE; end_dummy->previous=NULL; #endif // DL_LIST end_dummy->next=NULL; end_dummy->entry=NULL; end_dummy->done=TRUE; end_dummy->head_reduced=TRUE; #ifdef DL_LIST start=begin_dummy; element *iter=(l.start)->next; #endif // DL_LIST #ifdef SL_LIST element* iter=l.start; #endif // SL_LIST if(iter==NULL) { cerr<<"\nWARNING: list::list(const list&):\ntry to construct a list from" " a corrupt one; empty list created"<next)!=NULL) // end_dummy not reached { copy_insert(*(iter->entry)); iter=iter->next; } } list::~list() { #ifdef DL_LIST element *iter=start->next; #endif // DL_LIST #ifdef SL_LIST element *iter=start; #endif // SL_LIST while(iter->next!=NULL) // delete non-dummy elements { element* aux=iter; iter=iter->next; delete aux->entry; delete aux; } // end_dummy reached, delete it delete iter; #ifdef DL_LIST // delete begin_dummy delete start; #endif // DL_LIST } ///////////////////// inserting //////////////////////////////////////////// // For a better overview, the code for the simply and for the doubly linked // list is separated (except from the "copy-insert"-routines). #ifdef DL_LIST list& list::insert(binomial& bin) { // insert at the beginning (after the begin_dummy) // initialize element element* aux=new element; aux->entry=&bin; aux->done=FALSE; aux->head_reduced=FALSE; // set pointers aux->next=start->next; aux->next->previous=aux; aux->previous=start; start->next=aux; return(*this); } list& list::_insert(binomial& bin) { // insert at the beginning // initialize element element* aux=new element; aux->entry=&bin; // set pointers aux->next=start->next; aux->next->previous=aux; aux->previous=start; start->next=aux; return(*this); } list& list::ordered_insert(binomial& bin, const term_ordering& w) { // search for the place to insert element* iter=start->next; while(iter->entry!=NULL) // end_dummy not reached { if(w.compare(*(iter->entry),bin)<=0) // bin is bigger in term ordering then the referenced binomial iter=iter->next; else break; } // now bin is smaller in term ordering then the referenced binomial // or the referenced binomial is the end_dummy // initialize element element*aux=new element; aux->entry=&bin; aux->done=FALSE; aux->head_reduced=FALSE; // set pointers aux->previous=iter->previous; aux->previous->next=aux; aux->next=iter; iter->previous=aux; return *this; } list& list::_ordered_insert(binomial& bin, const term_ordering& w) { // search for the place to insert element* iter=start->next; while(iter->entry!=NULL) // end_dummy not reached { if(w.compare(*(iter->entry),bin)<=0) // bin is bigger in term ordering then the referenced binomial iter=iter->next; else break; } // now bin is smaller in term ordering then the referenced binomial // or the referenced binomial is the end_dummy // initialize element element*aux=new element; aux->entry=&bin; // set pointers aux->previous=iter->previous; aux->previous->next=aux; aux->next=iter; iter->previous=aux; return *this; } #endif // DL_LIST #ifdef SL_LIST list& list::insert(binomial& bin) { // insert at the beginning // initialize element element* aux=new element; aux->entry=&bin; aux->done=FALSE; aux->head_reduced=FALSE; // set pointers aux->next=start; start=aux; return(*this); } list& list::_insert(binomial& bin) { // insert at the beginning // initialize element element* aux=new element; aux->entry=&bin; // set pointers aux->next=start; start=aux; return(*this); } list& list::ordered_insert(binomial& bin, const term_ordering& w) { // search for the place to insert element* iter=start; while(iter->entry!=NULL) // end_dummy not reached { if(w.compare(*(iter->entry),bin)<=0) // bin is bigger in term ordering then the referenced binomial iter=iter->next; else break; } // now bin is smaller in term ordering then the referenced binomial // or the referenced binomial is the end_dummy // here we have to consider a special case if(iter==start) return insert(bin); // insert new element by first allocating a new list place behind the // referenced element, then moving the referenced element to that // new place... element*aux=new element; aux->entry=iter->entry; aux->done=iter->done; aux->head_reduced=iter->head_reduced; aux->next=iter->next; // .. and finally inserting bin at the old place // Remember that we cannot insert a new element between the referenced // element and its preceeding (we do not know the preceeding element) iter->entry=&bin; iter->done=FALSE; iter->head_reduced=FALSE; iter->next=aux; return *this; } list& list::_ordered_insert(binomial& bin, const term_ordering& w) { // search for the place to insert element* iter=start; while(iter->entry!=NULL) // end_dummy not reached { if(w.compare(*(iter->entry),bin)<=0) // bin is bigger in term ordering then the referenced binomial iter=iter->next; else break; } // now bin is smaller in term ordering then the referenced binomial // or the referenced binomial is the end_dummy // here we have to consider a special case if(iter==start) return _insert(bin); // insert new element by first allocating a new list place behind the // referenced element, then moving the referenced element to that // new place... element*aux=new element; aux->entry=iter->entry; aux->next=iter->next; // .. and finally inserting bin at the old place // Remember that we cannot insert a new element between the referenced // element and its preceeding (we do not know the preceeding element) iter->entry=&bin; iter->next=aux; return *this; } #endif // SL_LIST // copy-insert routines list& list::copy_insert(const binomial& bin) { binomial* _bin=new binomial(bin); return insert(*_bin); } list& list::_copy_insert(const binomial& bin) { binomial *_bin=new binomial(bin); return _insert(*_bin); } list& list::ordered_copy_insert(const binomial& bin, const term_ordering& w) { binomial *_bin=new binomial(bin); return ordered_insert(*_bin,w); } list& list::_ordered_copy_insert(const binomial& bin, const term_ordering& w) { binomial *_bin=new binomial(bin); return _ordered_insert(*_bin,w); } /////////////////////////// output ////////////////////////////////////////// void list::print() const { #ifdef DL_LIST element* iter=start->next; #endif // DL_LIST #ifdef SL_LIST element *iter=start; #endif // SL_LIST if(iter==NULL) { cerr<<"\nWARNING: void list::print() const:\ncannot print corrupt list" <next!=NULL) { iter->entry->print(); iter=iter->next; } } void list::ordered_print(const term_ordering& w) const { #ifdef DL_LIST element* iter=start->next; #endif // DL_LIST #ifdef SL_LIST element *iter=start; #endif // SL_LIST if(iter==NULL) { cerr<<"\nWARNING: void list::print(const term_ordering&) const:\n" "cannot print corrupt list"<next!=NULL) { aux._ordered_insert(*(iter->entry),w); iter=iter->next; } aux.print(); // delete aux, but only the element structs, not the binomials // (these are still stored in the actual list!) #ifdef DL_LIST iter=aux.start->next; #endif // DL_LIST #ifdef SL_LIST iter=aux.start; #endif while(iter->next!=NULL) // end_dummy not reached { element* aux2=iter->next; iter->next=iter->next->next; delete aux2; } // the dummy elements are deleted by the destructor } void list::print(FILE* output) const { #ifdef DL_LIST element* iter=start->next; #endif // DL_LIST #ifdef SL_LIST element *iter=start; #endif // SL_LIST if(iter==NULL) { cerr<<"\nWARNING: void list::print(FILE*) const:\ncannot print corrupt " "list"<next!=NULL) { iter->entry->print(output); iter=iter->next; } } void list::ordered_print(FILE* output, const term_ordering& w) const { #ifdef DL_LIST element* iter=start->next; #endif // DL_LIST #ifdef SL_LIST element *iter=start; #endif // SL_LIST if(iter==NULL) { cerr<<"\nWARNING: void list::print(const term_ordering&) const:\n" "cannot print corrupt list"<next!=NULL) { aux._ordered_insert(*(iter->entry),w); iter=iter->next; } aux.print(output); // delete aux, but only the element structs, not the binomials // (these are still stored in the actual list!) #ifdef DL_LIST iter=aux.start->next; #endif // DL_LIST #ifdef SL_LIST iter=aux.start; #endif while(iter->next!=NULL) // end_dummy not reached { element* aux2=iter->next; iter->next=iter->next->next; delete aux2; } // the dummy elements are deleted by the destructor } void list::print(ofstream& output) const { #ifdef DL_LIST element* iter=start->next; #endif // DL_LIST #ifdef SL_LIST element *iter=start; #endif // SL_LIST if(iter==NULL) { cerr<<"\nWARNING: void list::print(ofstream&) const:\n" "cannot print corrupt list"<next!=NULL) { iter->entry->print(output); iter=iter->next; } } void list::ordered_print(ofstream& output, const term_ordering& w) const { #ifdef DL_LIST element* iter=start->next; #endif // DL_LIST #ifdef SL_LIST element *iter=start; #endif // SL_LIST if(iter==NULL) { cerr<<"\nWARNING: void list::ordered_print(const term_ordering&) const:\n" "cannot print corrupt list"<next!=NULL) { aux._ordered_insert(*(iter->entry),w); iter=iter->next; } aux.print(output); // delete aux, but only the element structs, not the binomials // (these are still stored in the actual list!) #ifdef DL_LIST iter=(aux.start)->next; #endif // DL_LIST #ifdef SL_LIST iter=aux.start; #endif while((iter->next)!=NULL) { element* aux1=iter->next; iter->next=iter->next->next; delete aux1; } // the dummy elements are deleted by the destructor } void list::format_print(ofstream& output) const { #ifdef DL_LIST element* iter=start->next; #endif // DL_LIST #ifdef SL_LIST element *iter=start; #endif // SL_LIST if(iter==NULL) { cerr<<"\nWARNING: void list::print(ofstream&) const:\n" "cannot print corrupt list"<next!=NULL) { iter->entry->format_print(output); iter=iter->next; } } void list::ordered_format_print(ofstream& output, const term_ordering& w) const { #ifdef DL_LIST element* iter=start->next; #endif // DL_LIST #ifdef SL_LIST element *iter=start; #endif // SL_LIST if(iter==NULL) { cerr<<"\nWARNING: void list::ordered_format_print(const term_ordering&) " "const:\n" "cannot print corrupt list"<next!=NULL) { aux._ordered_insert(*(iter->entry),w); iter=iter->next; } aux.format_print(output); // delete aux, but only the element structs, not the binomials // (these are still stored in the actual list!) #ifdef DL_LIST iter=(aux.start)->next; #endif // DL_LIST #ifdef SL_LIST iter=aux.start; #endif while((iter->next)!=NULL) { element* aux1=iter->next; iter->next=iter->next->next; delete aux1; } // the dummy elements are deleted by the destructor } ///////////////////////////////////////////////////////////////////////////// ////////////////////// class list_iterator ////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // implementation of class list_iterator // Most of these function can be inlined. I have tried this and not improved // the performance. Perhaps the compiler does this automatically... ///////////////////////// constructors and destructor /////////////////////// list_iterator::list_iterator() { actual=NULL; } list_iterator::list_iterator(list& l) { #ifdef DL_LIST actual=(l.start)->next; #endif // DL_LIST #ifdef SL_LIST actual=l.start; #endif // SL_LIST } list_iterator::list_iterator(list_iterator& iter) { actual=iter.actual; } list_iterator::~list_iterator() { } /////////////////// object information ///////////////////////////////////// BOOLEAN list_iterator::element_is_marked_done() const { return(actual->done); } BOOLEAN list_iterator::element_is_marked_head_reduced() const { return(actual->head_reduced); } BOOLEAN list_iterator::is_at_end() const { if(actual==NULL) // actual references no list return(TRUE); if(actual->next==NULL) // actual references dummy element return(TRUE); // actual references a real element return(FALSE); } ////////////////////////// assignment /////////////////////////////////////// list_iterator& list_iterator::set_to_list(const list& l) { #ifdef DL_LIST actual=(l.start)->next; #endif // DL_LIST #ifdef SL_LIST actual=l.start; #endif // SL_LIST return *this; } list_iterator& list_iterator::operator=(const list_iterator& iter) { if((&iter)!=this) actual=iter.actual; return *this; } list_iterator& list_iterator::next() { actual=actual->next; return *this; } /////////////////// comparison //////////////////////////////////////////// int list_iterator::operator==(const list_iterator& iter) const { return(actual==iter.actual); } int list_iterator::operator!=(const list_iterator& iter) const { return(!(actual==iter.actual)); } int list_iterator::next_is(const list_iterator& iter) const { return ((actual->next)==iter.actual); } ////////////// manipulation of list elements ////////////////////////////// // For a better overview, the code of the delete- and extract-routine is // separated for simply and doubly linked lists. binomial& list_iterator::get_element() { return(*(actual->entry)); } #ifdef DL_LIST list_iterator& list_iterator::delete_element() { binomial* aux1=actual->entry; element* aux2=actual; actual->previous->next=actual->next; actual->next->previous=actual->previous; actual=actual->next; delete aux1; delete aux2; return *this; } list_iterator& list_iterator::extract_element() { element* aux=actual; actual->previous->next=actual->next; actual->next->previous=actual->previous; actual=actual->next; delete aux; return *this; } #endif // DL_LIST #ifdef SL_LIST // When deleting or extracting an element of a simply linked list, the // next-pointer of the previous element cannot be manipulated (is unkonwn!). // So deletion must be done by copying the next element to the actual position // and then deleting the original. Notice that only pointers are copies, never // binomials. list_iterator& list_iterator::delete_element() { binomial* aux1=actual->entry; element* aux2=actual->next; actual->done=actual->next->done; actual->head_reduced=actual->next->head_reduced; actual->entry=actual->next->entry; actual->next=actual->next->next; delete aux1; delete aux2; return *this; } list_iterator& list_iterator::extract_element() { element* aux=actual->next; actual->done=actual->next->done; actual->head_reduced=actual->next->head_reduced; actual->entry=actual->next->entry; actual->next=actual->next->next; delete aux; return *this; } #endif // SL_LIST list_iterator& list_iterator::mark_element_done() { actual->done=TRUE; return *this; } list_iterator& list_iterator::mark_element_undone() { actual->done=FALSE; return *this; } list_iterator& list_iterator::mark_element_head_reduced() { actual->head_reduced=TRUE; return *this; } list_iterator& list_iterator::mark_element_head_unreduced() { actual->head_reduced=FALSE; return *this; } #endif // LIST_CC singular-4.0.3+ds/IntegerProgramming/list.h000066400000000000000000000202611266270727000207020ustar00rootroot00000000000000// list.h // The classes "list" and "list_iterator" are designed for the special needs // of Buchberger's algorithm; it is not recommendable to use them for // more general purposes. // "list" implements a simply linked list of binomials (or, more exactly, // pointers on binomials). // A list_iterator is not much more than a pointer to a list element, but using // iterators instead of pointers makes the code of Buchberger's algorithm much // easier to read. // The delegation of tasks to this classes and the realization of some // functions are quite special. // So is the insertion of list elements the task of the class list, while the // deletion is delegated to the iterator class. The reason is the simple: // Elements are almost always inserted at the beginning of a list (except // from the case of an ordered list), but can be deleted from an arbitrary // place (this is necessary e.g. if a binomial is reduced to zero during // Buchberger's algorithm). // For efficiency reasons, the iterator operations are not secure. They do // not check if the iterator really references a list element or if it has // reached the end of the list. To assert this, use the is_at_end()-test. // I have designed an own iterator class instead of taking pointers for // iteration as lists members for flexibility reasons: // Buchberger's algorithm requires to form pairs of binomials (or, for // testing criteria to discard S-Pairs, even triples). So we need up to // three pointers to iterate over the generator lists. The advantage of the // iterator class is simply that the programmer does not have to keep // in mind the lists over which he is actually iterating. // This was very helpful for me during the implementation of Buchberger's // algorithm (especially for the implementation of // SUPPORT_DRIVEN_METHODS_EXTENDED where many lists have to be considered). // There are two different implementations of the class list: // - If SL_LIST is set, we use a simply linked list. // The insert operations are very efficient because we have to set very // few pointers. But the deletion of an element is a dangerous operation // because it moves the following element (not the binomial, but the struct) // to another storage place. // - If DL_LIST is set, we use a doubly linked list. // This shows to be considerably slower, but it is easier to use #ifndef LIST_H #define LIST_H #define DL_LIST // possibilities: // SL_LIST // DL_LIST #include "binomial__term_ordering.h" ////////////////////////////// struct element /////////////////////////////// typedef struct Element { binomial *entry; struct Element *next; #ifdef DL_LIST struct Element *previous; #endif // DL_LIST // flags needed by the ideal implementation to speed up Buchberger's // algorithm BOOLEAN done; BOOLEAN head_reduced; } element; /////////////////////////// class list //////////////////////////////////// class list { private: element *start; // pointer to the beginning public: // constructors and destructor list(); // Creates an "empty" list (with a dummy element for a user friendly // iterator class, see the comments in list.cc). list(const list&); // copy-constructor ~list(); // destructor // inserting list& insert(binomial&); list& copy_insert(const binomial&); // These operations insert a binomial at the beginning of the list: // insert does this by placing pointers on it, copy_insert by copying the // binomial. // The first operation is dangerous; but the consequent use of the // combination insert - extract_element (cf. class list_iterator) instead of // copy_insert - delete_element is very important for the performance of // Buchberger's algorithm. list& _insert(binomial&); list& _copy_insert(const binomial&); // A little more efficient insert function for list that do not use // the 3 flags - these are not set. // It is not more efficient to implement these simpler lists as an own class. list& ordered_insert(binomial&, const term_ordering&); list& ordered_copy_insert(const binomial&, const term_ordering&); // These operations insert a binomial according to the given term ordering // into a list. (The list should be ordered by the same term ordering.) // To insert elements, we use a simple linear search. list& _ordered_insert(binomial&, const term_ordering&); list& _ordered_copy_insert(const binomial&, const term_ordering&); // A little more efficient ordered_insert function for list that do not use // the 3 flags - these are not set. // output void print() const; void ordered_print(const term_ordering&) const; // Writes the list to the standard output medium. // The first routine writes the list elements as they are oredred in // the list. // The second one writes them in increasing order with respect to the // argument term ordering; the list has not to be ordered before and // will not be ordered after. This routine is essentially written to // compare Gröbner bases. void print(FILE* output) const; void ordered_print(FILE* output, const term_ordering&) const; // Writes the list to the referenced file which has to be opened for // writing before. void print(ofstream&) const; void ordered_print(ofstream&, const term_ordering&) const; // Writes the list to the given ofstream. void format_print(ofstream&) const; void ordered_format_print(ofstream&, const term_ordering&) const; // Writes the list to the given ofstream in the format needed by the // IP-algorithms. friend class list_iterator; }; ///////////////////// class list_iterator //////////////////////////////// class list_iterator { private: element* actual; public: // constructors and destructor list_iterator(); // Sets actual to NULL. list_iterator(list& l); // Sets a list_iterator to the beginning of l. list_iterator(list_iterator& iter); // Sets a list iterator to the same position as iter. ~list_iterator(); // destructor // object information BOOLEAN element_is_marked_done() const; // Returns the "done"-component of the referenced element. BOOLEAN element_is_marked_head_reduced() const; // Returns the "head_reduced"-component of the referenced element. BOOLEAN is_at_end() const; // Returns TRUE iff the iterator is at the end of "its" list // (especially if the iterator references no list). // assignment list_iterator& set_to_list(const list& l); // Sets the iterator to the beginning of l. list_iterator& operator=(const list_iterator& iter); // Sets the iterator to the same element as iter. list_iterator& next(); // Sets the iterator to the next entry. // comparison int operator==(const list_iterator& iter) const; int operator!=(const list_iterator& iter) const; // These operators verifie if actual references the same element // as iter.actual. int next_is(const list_iterator& iter) const; // Checks if actual->next references the same element as iter.actual. // This check is needed in very special situations (two iterators reference // subsequent elements of a list, and the first is deleted; then the // iterator referencing the second before deletion references freed memory // after deletion, cf. the implementation of delete and extract). // manipulation of list elements // All this operations could be declared as const because they do not // change the "actual" pointer. For suggestive reasons, this is not done // because they change the referenced list element. binomial& get_element(); // Returns the referenced binomial. list_iterator& delete_element(); // Deletes the referenced binomial. list_iterator& extract_element(); // Only resets pointers so that the refenced binomial is no longer found // when iterating over the list. list_iterator& mark_element_done(); // Sets the "done"-component of the referenced element to TRUE. list_iterator& mark_element_undone(); // Sets the "done"-component of the referenced element to FALSE. list_iterator& mark_element_head_reduced(); // Sets the "head_reduced"-component of the referenced element to TRUE. list_iterator& mark_element_head_unreduced(); // Sets the "head_reduced"-component of the referenced element to FALSE. }; #endif // list.h singular-4.0.3+ds/IntegerProgramming/matrix.cc000066400000000000000000000420531266270727000213740ustar00rootroot00000000000000// matrix.cc // implementation of class matrix #ifndef MATRIX_CC #define MATRIX_CC #include "matrix.h" ////////////// constructors and destructor ////////////////////////////////// typedef Integer* IntegerP; typedef BigInt* BigIntP; matrix::matrix(const int& row_number, const int& column_number) :rows(row_number),columns(column_number) { _kernel_dimension=-2; // LLL-algorithm not yet performed // argument check if((rows<=0)||(columns<=0)) // bad input, set "error flag" { cerr<<"\nWARNING: matrix::matrix(const int&, const int&):\n" "argument out of range"<>rows; if(!input) // input failure, set "error flag" { cerr<<"\nWARNING: matrix::matrix(ifstream&): input failure"<>columns; if(!input) // input failure, set "error flag" { cerr<<"\nWARNING: matrix::matrix(ifstream&): input failure"<>coefficients[i][j]; if(!input) // bad input, set error flag { cerr<<"\nWARNING: matrix::matrix(ifstream&): input failure"<>coefficients[i][j]; if(!input) // bad input, set error flag { columns=-2; return; } } } matrix::matrix(const matrix& A) :rows(A.rows),columns(A.columns),_kernel_dimension(A._kernel_dimension) { if(columns<0) { cerr<<"\nWARNING: matrix::matrix(const matrix&):\n" "Building a matrix from a corrupt one"<0) { H=new BigIntP[_kernel_dimension]; for(int k=0;k<_kernel_dimension;k++) H[k]=new BigInt[columns]; for(int k=0;k<_kernel_dimension;k++) for(int j=0;j0) // LLL-algorithm performed { for(int i=0;i<_kernel_dimension;i++) delete[] H[i]; delete[] H; } } //////////////////// object properties ////////////////////////////////////// BOOLEAN matrix::is_nonnegative() const { for(int i=0;iBigInt(0)) { if(min_index==-1) min_index=i; else if(M[i] desired vector does not exist return 0; // add the square of the norm to the vectors with the least common zero // components // discard the others for(int i=current_position;i<_kernel_dimension;i++) if(M[i]!=min) M[i]=-1; else for(int j=0;jBigInt(0)) { if(min_index==0) min_index=i; else if(M[i]columns) // more negative than positive components in H[0] // all variables corresponding to positive components will be flipped { r=columns-r; F=new int[r]; memset(F,0,r*sizeof(int)); int counter=0; for(int j=0;j BigInt(0)) { F[counter]=j; counter++; } } else // more (or as many) positive than negative components in v // all variables corresponding to negative components will be flipped { F=new int[r]; memset(F,0,r*sizeof(int)); int counter=0; for(int j=0;j which is already staurated return 0; int number_of_sat_var=0; sat_var=new int[columns/2]; memset(sat_var,0,sizeof(int)*(columns/2)); BOOLEAN* ideal_saturated_by_var=new BOOLEAN[columns]; // auxiliary array used to remember by which variables the ideal has still to // be saturated for(int j=0;j BigInt(0)) pos_sat_var++; else if(H[k][j]< BigInt(0)) neg_sat_var++; } } // now add the smaller set to the saturation variables if(pos_sat_var<=neg_sat_var) { for(int j=0;j BigInt(0)) // ideal has to be saturated by the variables corresponding // to positive components { sat_var[number_of_sat_var]=j; ideal_saturated_by_var[j]=TRUE; number_of_sat_var++; } else if(H[k][j]< BigInt(0)) // then the ideal is automatically saturated by the variables // corresponding to negative components ideal_saturated_by_var[j]=TRUE; } } else { for(int j=0;j BigInt(0)) // then the ideal is automatically saturated by the variables // corresponding to positive components ideal_saturated_by_var[j]=TRUE; } } } // clean up memory delete[] ideal_saturated_by_var; return number_of_sat_var; } //////////////////// output /////////////////////////////////////////////// void matrix::print() const { printf("\n%3d x %3d\n",rows,columns); for(int i=0;i=0, else FALSE. int error_status() const; // Returns columns iff columns<0 (this is the "error flag"), else 0. int row_number() const; // Retuns the row number. int column_number() const; // Returns the column number. int kernel_dimension() const; // Returns the kernel dimension. // special routines for the IP-algorithms int LLL_kernel_basis(); // Computes a LLL-reduced integer basis of the matrix kernel and returns // the kernel dimension (-1 if an error has occurred). // This dimension is also stored in the member kernel_dimension. int compute_nonzero_kernel_vector(); // Transforms the kernel lattice basis stored in H so that it contains // a vector whose components are all !=0; // returns 0 if no such vector exists, else 1. // If no such basis has been computed before, this is done now. int compute_flip_variables(int*&); // Computes a set of flip variables for the algorithm of DiBiase and // Urbanke from a kernel vector with no zero components. // Returns the size of that set if such a kernel vector exists, else -1. // If necessary, such a vector is computed. // The computed set is copied to the argument pointer (memory allocation // is done in the routine) to be accessible for the calling function. int hosten_shapiro(int*& sat_var); // Computes a set of saturation variables for the ideal defined by the // kernel lattice and returns the size of that set. // If no lattice basis has been computed before, this is done now. // The computed set is stored in the argument pointer (memory allocation // is done in the routine) to be accessible for the calling function. // This routine implements the most simple strategy for computing this set: // The kernel vectors are examined in their actual. A "greedy" strategy // choosing "clever" kernel vectors to begin with could give better results // in many cases, but this is not guaranteed... // (And what is a clever choice?) // output void print() const; // Writes the matrix to the standard output medium. void print(FILE*) const; // Writes the matrix to the referenced file which has to be opened // for writing before. void print(ofstream&) const; // Writes the matrix to the given ofstream. friend class ideal; // Our toric ideals are all constructed from matrices, and the matrix class // is designed only for the needs of these constructors. So it would be // unnecessary overhead to hide the matrix members from these constructors. }; #endif singular-4.0.3+ds/IntegerProgramming/solve_IP.cc000066400000000000000000000210011266270727000215760ustar00rootroot00000000000000// solve_IP.cc // This file provides the interface to call the implemented IP-algorithms. // This includes a short help text on the choice of algorithms and their // arguments and the required formats of the input file. #ifndef SOLVE_IP_CC #define SOLVE_IP_CC #include "IP_algorithms.h" int main(int argc, char *argv[]) { // initialize arguments for the IP-algorithms (Buchberger) // with default settings BOOLEAN verbose=FALSE; int version=1; int S_pair_criteria=11; double interreduction_percentage=12.0; ///////////////////////// parse options ///////////////////////////////////// int alg_option=0; // no algorithm specified yet if(argc>=3) // argc has to be at least 3 (except when help is required, see below): // program name, (MATRIX or) GROEBNER file, PROBLEM file { for(int i=1;i=argc-2) // file arguments reached break; if(!strcmp(argv[i],"RP")) { S_pair_criteria|=1; continue; } if(!strcmp(argv[i],"M")) { S_pair_criteria|=2; continue; } if(!strcmp(argv[i],"F")) { S_pair_criteria|=4; continue; } if(!strcmp(argv[i],"B")) { S_pair_criteria|=8; continue; } if(!strcmp(argv[i],"2")) { S_pair_criteria|=16; continue; } // option does not belong to an S-pair criterion break; } while(1); i--; // reset counter so that the outer loop continue; // continues with the just considered argument } if(!strcmp(argv[i],"-p")) { // read interreduction percentage i++; char** rest; interreduction_percentage=strtod(argv[i],rest); // The function strtod converts a string into a double. As the // specification is not correct, it may cause trouble... // For example, if the argument can be read as a float, the value // of rest should be NULL. This is not the case. Therefore, we can // only check by the following string comparison if a float has been // built. An argument as 15xy is thereby considered as valid // (with interreduction_percentage==15.0). if(!(strcmp(argv[i],*rest))) // argument was no float { cerr<<"ERROR: invalid argument for interreduction percentage\n" <<"Type `solve_IP --help' for help on options.\n"; return 1; } continue; } if(!strcmp(argv[i],"-alg") || !strcmp(argv[i],"--algorithm")) { // check if next argument is a valid algorithm specification i++; if(!strcmp(argv[i],"ct") || !strcmp(argv[i],"pct") || !strcmp(argv[i],"ect") || !strcmp(argv[i],"pt") || !strcmp(argv[i],"hs") || !strcmp(argv[i],"du") || !strcmp(argv[i],"blr")) { alg_option=i; continue; } // When reaching this line, the algorithm argument was invalid. cerr<<"ERROR: unkwon algorithm\n" <<"Type `solve_IP --help' for help on options.\n"; return 1; } // When reaching this line, the argument is no legal option. cerr<<"ERROR: invalid option "<>format_string; if(!strcmp(format_string,"MATRIX")) { if(alg_option==0) { cerr<<"ERROR: first input file is a MATRIX file;\n" "algorithm has to be specified\n"; return 1; } // perform specified algorithm to compute a Groebner basis of the // toric ideal defined by the input matrix int success; if(!strcmp(argv[alg_option],"ct")) success=Conti_Traverso(argv[argc-2], version, S_pair_criteria, interreduction_percentage, verbose); if(!strcmp(argv[alg_option],"pct")) success=Positive_Conti_Traverso(argv[argc-2], version, S_pair_criteria, interreduction_percentage, verbose); if(!strcmp(argv[alg_option],"ect")) success=Elim_Conti_Traverso(argv[argc-2], version, S_pair_criteria, interreduction_percentage, verbose); if(!strcmp(argv[alg_option],"pt")) success=Pottier(argv[argc-2], version, S_pair_criteria, interreduction_percentage, verbose); if(!strcmp(argv[alg_option],"hs")) success=Hosten_Sturmfels(argv[argc-2], version, S_pair_criteria, interreduction_percentage, verbose); if(!strcmp(argv[alg_option],"du")) success=DiBiase_Urbanke(argv[argc-2], version, S_pair_criteria, interreduction_percentage, verbose); if(!strcmp(argv[alg_option],"blr")) success=Bigatti_LaScala_Robbiano(argv[argc-2], version, S_pair_criteria, interreduction_percentage, verbose); if(!success) { cerr<<"ERROR: could not perform required IP-algorithm,\n" "no GROEBNER file created\n"; return 1; } // Groebner basis successfully computed // now solve problems char* GROEBNER=new char[128]; memset(GROEBNER,0,128); int i=0; while(argv[argc-2][i]!='\0' && argv[argc-2][i]!='.' && argv[argc-2][i]>' ') { GROEBNER[i]=argv[argc-2][i]; i++; } strcat(GROEBNER,".GB."); strcat(GROEBNER,argv[alg_option]); success=solve(argv[argc-1],GROEBNER); delete[] GROEBNER; return(!success); // ! because 0 indicates in general a regular program termination } else // first input file is no MATRIX file, GROEBNER file assumed { if(argc>3) // input options are ignored when program is called with a // GROEBNER file cerr<<"WARNING: program called with a GROEBNER file,\n" "specified options will not have any effect\n"; return(!solve(argv[argc-1],argv[argc-2])); } } /////////////////////// provide help text /////////////////////////////////// // handle the case of "missing" arguments if((argc==2) && !strcmp(argv[1],"--help")) // help required { system("less solve_IP.hlp"); return 0; } else // invalid arguments cerr<<"USAGE: solve_IP [options] toric_file problem_file\n" <<"Type `solve_IP --help' for help on options.\n"; return 1; } #endif // SOLVE_IP_CC singular-4.0.3+ds/IntegerProgramming/solve_IP.hlp000066400000000000000000000155061266270727000220110ustar00rootroot00000000000000USAGE: solve_IP [options] toric_file problem_file DESCRIPTION: solve_IP is a program for solving integer programming problems with the Buchberger algorithm: Let A an integral (mxn)-matrix, b a vector with m integral coefficients and c a vector with n nonnegative real coefficients. The solution of the IP-problem minimize{ cx | Ax=b, all components of x are nonnegative integers } proceeds in two steps: 1. We compute the toric ideal of A and its Groebner basis with respect to a term ordering refining the cost function c. 2. We reduce the right hand vector b or an initial solution of the problem modulo this ideal. For these purposes, we can use seven different algorithms: The algorithm of Conti/Traverso (ct) can compute an optimal solution of the IP-problem directly from the right hand vector b. The same is true for its "positive" variant (pct) which can only be applied if A and b have nonnegative entries, but should be faster in that case. All other algorithms need initial solutions of the IP-problem. Except from the elimination version of the Conti-Traverso algorithm (ect), they should be more efficient than the algorithm mentionned before. These are the algorithms of Pottier (pt), Bigatti/La Scala/Robbiano (blr), Hosten/Sturmfels (hs) and Di Biase/Urbanke (du). The last two seem to be the fastest in the actual implementation. FILE FORMAT: The first input file may be a MATRIX or a GROEBNER file; these two types are called "toric files". The second input file has to be a PROBLEM file. If the PROBLEM file contains a positive number of problems ,i.e. right hand vectors or initial solutions, solve_IP appends its solutions to a SOLUTION file named like the first input file with extensions replaced by .sol. where sol stands for solution and is the abbreviation of the used algorithm as above. When called with a MATRIX file, solve_IP produces a GROEBNER file named like the MATRIX file with extensions replaced by .GB. where GB stands for GROEBNER. A MATRIX file should look as follows: MATRIX columns: cost vector: rows: matrix: positive row space vector: The last two lines are only needed when solve_IP is called with the algorithms of Hosten/Sturmfels or Bigatti/La Scala/Robbiano, i.e. the options -alg hs or -alg blr The other algorithms ignore these lines. Example: MATRIX columns: 3 cost vector: 1 1 1 rows: 2 matrix: 1 2 3 4 5 6 positive row space vector: 1 2 3 A GROEBNER file looks as follows: GROEBNER computed with algorithm: (* abbreviations as above *) from file(s): (* the following four lines are optional *) computation time: term ordering: elimination block variables >0 *) weighted block should always be >0 *) size: Groebner basis: (* optional *) The Groebner basis consists always of binomials of the form x^a - x^b where x^a and x^b are relatively prime. Such a binomial can be represented by the vector a-b. The basis elements in the GROEBNER file are given by the coefficients of this vector representation. The settings for Buchberger´s algorithm and the compiler flags are produced when the GROEBNER file is generated by a call of solve_IP with the verbose output option -v, --verbose Example (not belonging to the example above): GROEBNER computed with algorithm: du term ordering: elimination block: 0 weighted block: 3 W_LEX 1 2 3 size: 1 Groebner basis: 2 3 -2 (* x^2 * y^3 - z^2 *) A PROBLEM file should look as follows: PROBLEM vector size: number of instances: right-hand or initial solution vectors: A SOLUTION file looks as follows: SOLUTION computed with algorithm: from file: (* the GROEBNER file *) vector: solvable: (* only if right-hand vector is given *) optimal solution: (* only in the case of existence *) computation time: (* only for reduction *) ... (* further vectors, same format *) OPTIONS: -alg , --algorithm algorithm to use for solving the given IP instances; may be ct for Conti/Traverso, pct for the positive Conti/Traverso, ect for Conti/Traverso with elimination, pt for Pottier, hs for Hosten/Sturmfels, du for Di Biase/Urbanke, blr for Bigatti-LaScal-Robbiano. -p percentage of new generators to cause an autoreduction during Buchberger´s algorithm; may be an arbitrary float, a negative value allows no intermediate autoreductions default is -p 12.0 -S [RP] [M] [B] [M] [2] criteria to use in Buchberger´s algorithm for discarding unneccessary S-pairs RP relatively prime leading terms M Gebauer-Moeller criterion M F Gebauer-Moeller criterion F B Gebauer-Moeller criterion B 2 Buchberger´s second criterion default is -S RP M B -v, --verbose verbose output mode; writes the settings for Buchberger´s algorithm and the compiler flags into the output GROEBNER file -V , --version version of Buchberger´s algorithm to use; may be 1, 1a, 2 or 3 default is -V 1 When called with a GROEBNER file, these options do not affect computation and are ignored by solve_IP.singular-4.0.3+ds/IntegerProgramming/term_ordering.cc000066400000000000000000001016431266270727000227310ustar00rootroot00000000000000// term_ordering.cc // implementation of class term ordering #ifndef TERM_ORDERING_CC #define TERM_ORDERING_CC #include "binomial__term_ordering.h" /////////////// constructors and destructor /////////////////////////////////// term_ordering::term_ordering(const BOOLEAN& _homogeneous) :homogeneous(_homogeneous) { weight_vector=NULL; weighted_block_size=0; elimination_block_size=0; } term_ordering::term_ordering(const short& number_of_weighted_variables, const float* weights, const short& _weighted_ordering, const BOOLEAN& _homogeneous) :weighted_block_size(number_of_weighted_variables), homogeneous(_homogeneous) { if((_weighted_ordering<4) || (_weighted_ordering>7)) // unknown ordering refining the weight, set "error flag" weighted_block_size=-1; else weighted_ordering=_weighted_ordering; if(weighted_block_size<0) // argument out of range, set "error flag" weighted_block_size=-1; if(weighted_block_size>0) { weight_vector=new float[weighted_block_size]; BOOLEAN negative_weight=FALSE; BOOLEAN zero_weight=FALSE; // for checking the input for(short i=0;i7)) // unknown ordering refining the weight, set "error flag" weighted_block_size=-1; else weighted_ordering=_weighted_ordering; if((_elimination_ordering<1) || (_elimination_ordering>3)) // unknown ordering on the elimination variables, set "error flag" weighted_block_size=-1; else elimination_ordering=_elimination_ordering; if((weighted_block_size<0)||(elimination_block_size<0)) // argument out of range, set "error flag" weighted_block_size=-1; if(weighted_block_size>0) { weight_vector=new float[weighted_block_size]; BOOLEAN negative_weight=FALSE; BOOLEAN zero_weight=FALSE; // for checking the input for(short i=0;i7)) // unknown ordering refining the weight, set "error flag" weighted_block_size=-1; else weighted_ordering=_weighted_ordering; input>>weighted_block_size; if(!input) // input failure, set "error flag" weighted_block_size=-2; if(weighted_block_size<0) // input out of range, set error flag weighted_block_size=-1; if(weighted_block_size>0) { weight_vector=new float[weighted_block_size]; BOOLEAN negative_weight=FALSE; BOOLEAN zero_weight=FALSE; // for checking the input for(short i=0;i>weight_vector[i]; if(!input) // input failure, set "error flag" { weighted_block_size=-2; cerr<<"\nWARNING: term_ordering::term_ordering(ifstream&, const " "short&):\nInput failed reading term ordering from ofstream"<7)) // unknown ordering refining the weight, set "error flag" weighted_block_size=-1; else weighted_ordering=_weighted_ordering; if(n<0) // input out of range, set error flag weighted_block_size=-1; else weighted_block_size=n; if(weighted_block_size>0) { weight_vector=new float[weighted_block_size]; BOOLEAN negative_weight=FALSE; BOOLEAN zero_weight=FALSE; // for checking the input for(short i=0;i>weight_vector[i]; if(!input) // input failure, set "error flag" { weighted_block_size=-2; cerr<<"\nWARNING: term_ordering::term_ordering(const short&, " "ifstream&, const short&):\nInput failed reading term ordering " "from ofstream"<0) { weight_vector=new float[weighted_block_size]; for(short i=0;i0) delete[] weight_vector; } /////////////// object properties ///////////////////////////////////////// short term_ordering::number_of_weighted_variables() const { return weighted_block_size; } short term_ordering::weight_refinement() const { return weighted_ordering; } short term_ordering::number_of_elimination_variables() const { return elimination_block_size; } short term_ordering::elimination_refinement() const { return elimination_ordering; } BOOLEAN term_ordering::is_homogeneous() const { return homogeneous; } short term_ordering::error_status() const { if(weighted_block_size<0) return weighted_block_size; return 0; } BOOLEAN term_ordering::is_nonnegative() const { for(int i=0;i0) switch(elimination_ordering) { case LEX: for(short i=weighted_block_size;i0) return 1; if(actual_component<0) return -1; } break; case DEG_LEX: // compute the degree for(short i=weighted_block_size;i0) return 1; if(w<0) return -1; // if the degree is zero: // tie breaking with the lexicographical ordering for(short i=weighted_block_size;i0) return 1; if(actual_component<0) return -1; } break; case DEG_REV_LEX: //compute the degree for(short i=weighted_block_size;i0) return 1; if(w<0) return -1; // if the degree is zero: // tie breaking with the reverse lexicographical ordering for(short i=last_index-1;i>=weighted_block_size;i--) { Integer actual_component=v[i]; if(actual_component<0) return 1; if(actual_component>0) return -1; } } // When reaching this line, the vector components corresponding to // elimination variables are all zero. // Compute the weight. // If the term ordering is a homogeneous one, this is superfluous. if(!homogeneous) { w=weight(v); if(w>0) return 1; if(w<0) return -1; } // When reaching this line, the weight of the vector components corresponding // to weighted variables is zero. // Tie breaking with the term ordering refining the weight. switch(weighted_ordering) { case W_LEX: for(short i=0;i0) return 1; if(actual_component<0) return -1; } break; case W_REV_LEX: for(short i=weighted_block_size-1;i>=0;i--) { Integer actual_component=v[i]; if(actual_component<0) return 1; if(actual_component>0) return -1; } break; case W_DEG_LEX: for(short i=0;i0) return 1; if(w<0) return -1; for(short i=0;i0) return 1; if(actual_component<0) return -1; } break; case W_DEG_REV_LEX: for(short i=0;i0) return 1; if(w<0) return -1; for(short i=weighted_block_size-1;i>=0;i--) { Integer actual_component=v[i]; if(actual_component<0) return 1; if(actual_component>0) return -1; } } // When reaching this line, the argument vector is the zero vector. return 0; } short term_ordering::compare(const binomial& bin1, const binomial& bin2) const { unsigned short last_index=weighted_block_size+elimination_block_size; double w1=0; double w2=0; Integer* v1=bin1.exponent_vector; Integer* v2=bin2.exponent_vector; // First compare the heads of the input binomials. // The code is analogous to the routine compare_to_zero(...), except // from the fact that we must consider the sign of the vector components. // First check the elimination variables. if(elimination_block_size>0) switch(elimination_ordering) { case LEX: for(short i=weighted_block_size;i0 || comp2>0) { if(comp1>comp2) return 1; if(comp10) w1+=comp1; if(comp2>0) w2+=comp2; } if(w1>w2) return 1; if(w10 || comp2>0) { if(comp1>comp2) return 1; if(comp10) w1+=comp1; if(comp2>0) w2+=comp2; } if(w1>w2) return 1; if(w1=weighted_block_size;i--) { Integer comp1=v1[i]; Integer comp2=v2[i]; if(comp1>0 || comp2>0) { if(comp1comp2) return -1; } } } // When reaching this line, the heads are equal in the elimination // variables. // Compute the weight of the heads. w1=0; for(short i=0;i0) w1+=actual_component*weight_vector[i]; } w2=0; for(short i=0;i0) w2+=actual_component*weight_vector[i]; } if(w1>w2) return 1; if(w10 || comp2>0) { if(comp1>comp2) return 1; if(comp1=0;i--) { Integer comp1=v1[i]; Integer comp2=v2[i]; if(comp1>0 || comp2>0) { if(comp1comp2) return -1; } } break; case W_DEG_LEX: for(short i=0;i0) w1+=comp1; if(comp2>0) w2+=comp2; } if(w1>w2) return 1; if(w10 || comp2>0) { if(comp1>comp2) return 1; if(comp10) w1+=comp1; if(comp2>0) w2+=comp2; } if(w1>w2) return 1; if(w1=0;i--) { Integer comp1=v1[i]; Integer comp2=v2[i]; if(comp1>0 || comp2>0) { if(comp1comp2) return -1; } } } // When reaching this line, the heads of the binomials are equal. // Now we decide by the tails. // This part of the code could also be omitted in the current context: // The compare(...)-function is only called when dealing with ordered // lists. This is done in two cases: // - When computing with ordered S-pair lists, it doesn't really matter // if such similar binomials are in the right order. // - When outputting a reduced Groebner basis, it cannot happen that two // heads are equal. w1=0; w2=0; // First check the elimination variables. if(elimination_block_size>0) switch(elimination_ordering) { case LEX: for(short i=weighted_block_size;i0 || comp2>0) { if(comp1>comp2) return 1; if(comp10) w1+=comp1; if(comp2>0) w2+=comp2; } if(w1>w2) return 1; if(w10 || comp2>0) { if(comp1>comp2) return 1; if(comp10) w1+=comp1; if(comp2>0) w2+=comp2; } if(w1>w2) return 1; if(w1=weighted_block_size;i--) { Integer comp1=-v1[i]; Integer comp2=-v2[i]; if(comp1>0 || comp2>0) { if(comp1comp2) return -1; } } } // When reaching this line, the tails are equal in the elimination // variables. // Compute the weight of the tails. w1=0; for(short i=0;i0) w1+=actual_component*weight_vector[i]; } w2=0; for(short i=0;i0) w2+=actual_component*weight_vector[i]; } if(w1>w2) return 1; if(w10 || comp2>0) { if(comp1>comp2) return 1; if(comp1=0;i--) { Integer comp1=-v1[i]; Integer comp2=-v2[i]; if(comp1>0 || comp2>0) { if(comp1comp2) return -1; } } break; case W_DEG_LEX: for(short i=0;i0) w1+=comp1; if(comp2>0) w2+=comp2; } if(w1>w2) return 1; if(w10 || comp2>0) { if(comp1>comp2) return 1; if(comp10) w1+=comp1; if(comp2>0) w2+=comp2; } if(w1>w2) return 1; if(w1=0;i--) { Integer comp1=-v1[i]; Integer comp2=-v2[i]; if(comp1>0 || comp2>0) { if(comp1comp2) return -1; } } } return 0; } ///////// operators and routines needed by the IP-algorithms //////////////// ///////// to manipulate the term ordering //////////////////////////////// term_ordering& term_ordering::operator=(const term_ordering& w) { if(&w==this) return *this; if(weighted_block_size>0) delete[] weight_vector; weighted_block_size=w.weighted_block_size; weighted_ordering=w.weighted_ordering; elimination_block_size=w.elimination_block_size; elimination_ordering=w.elimination_ordering; homogeneous=w.homogeneous; if(weighted_block_size>0) { weight_vector=new float[weighted_block_size]; for(short i=0;i=weighted_block_size)) { cerr<<"\nWARNING: float term_ordering::operator[](const short& i):\n" "access to invalid weight vector component"<3)) // unknown ordering on the elimination variables, set "error flag" weighted_block_size=-1; else elimination_ordering=_elimination_ordering; if(number_of_elimination_variables<0) // argument out of range, set error flag weighted_block_size=-1; else elimination_block_size=number_of_elimination_variables; if(weighted_block_size<0) cerr<<"\nWARNING: term_ordering& term_ordering::" "convert_to_elimination_ordering(const short&, const short&):\n" "argument out of range"<=0) { float *aux=weight_vector; weight_vector=new float[weighted_block_size+1]; for(short i=0;i0) delete[] aux; weighted_block_size++; } else cerr<<"\nWARNING: term_ordering& term_ordering::append_weighted_variable" "(const float&):\n" "called for a corrupt term ordering, term ordering not changed" <0) { float *aux=weight_vector; if(weighted_block_size>1) weight_vector=new float[weighted_block_size-1]; for(short i=0;i=weighted_block_size) || (j<0) || (j>=weighted_block_size)) { cout<<"\nWARNING: term_ordering& termordering::swap_weights" "(const short, const short):\nindex out of range"<0) { printf("ordering on elimination variables: "); switch(elimination_ordering) { case LEX: printf("LEX\n"); break; case DEG_LEX: printf("DEG_LEX\n"); break; case DEG_REV_LEX: printf("DEG_REV_LEX\n"); break; } } printf("ordering refining the weight: "); switch(weighted_ordering) { case W_LEX: printf("W_LEX\n\n"); break; case W_REV_LEX: printf("W_REV_LEX\n\n"); break; case W_DEG_LEX: printf("W_DEG_LEX\n\n"); break; case W_DEG_REV_LEX: printf("W_DEG_REV_LEX\n\n"); break; } } void term_ordering::print_weight_vector(FILE* output) const { if(weighted_block_size<0) { fprintf(output,"\nWARNING: void term_ordering::print_weight_vector(FILE*)" ":\ncannot print corrupt term ordering\n"); return; } fprintf(output,"("); for(short i=0;i0) { fprintf(output,"ordering on elimination variables: "); switch(elimination_ordering) { case LEX: fprintf(output,"LEX\n"); break; case DEG_LEX: fprintf(output,"DEG_LEX\n"); break; case DEG_REV_LEX: fprintf(output,"DEG_REV_LEX\n"); break; } } fprintf(output,"ordering refining the weight: "); switch(weighted_ordering) { case W_LEX: fprintf(output,"W_LEX\n\n"); break; case W_REV_LEX: fprintf(output,"W_REV_LEX\n\n"); break; case W_DEG_LEX: fprintf(output,"W_DEG_LEX\n\n"); break; case W_DEG_REV_LEX: fprintf(output,"W_DEG_REV_LEX\n\n"); break; } } void term_ordering::print_weight_vector(ofstream& output) const { if(weighted_block_size<0) { output<<"\nWARNING: void term_ordering::print_weight_vector(ofstream&):\n" "cannot print corrupt term ordering"<0) { output<<"ordering on elimination variables: "; switch(elimination_ordering) { case LEX: output<<"LEX\n"<=0. // If this is not the case, Buchberger's algorithm will perhaps not // terminate using the actual ordering, i.e. the ordering is no // well ordering. BOOLEAN is_positive() const; // Returns TRUE ifs all components of the weight vector are >0. // If this is not the case, this may lead to problems even if all weights // are nonnegative: Zero weights do not give a well ordering in combination // with a reverse lexicographical refinement. // frequently used comparison functions double weight(const Integer* v) const; // Returns the weight of an Integer vector v with respect to weight_vector, // i.e. the scalar product of the two vectors. // UNCHECKED PRECONDITION: v has weighted_block_size components. // The return type is double to avoid overflows. short compare_to_zero(const Integer* v) const; // This function is used to determine a binomials's head with respect to the // actual term ordering. The comparison of its two monomials is done // according to the binomial data structure: // Instead of comparing explicitely two monomials, the Integer vector // corresponding to their difference is compared to the zero vector. // The function returns // 1, if v>0, // -1, if v<0, // 0, if v=0 // UNCHECKED PRECONDITION: // v has weighted_block_size + elimination_block_size components short compare(const binomial& bin1, const binomial& bin2) const; // Compares the given binomials by first comparing the heads, then in the // case of equality the tails. // UNCHECKED PRECONDITION: The exponent vectors of the binomials have // already the correct sign, i.e. the positive part of a vector is really // its head and not its tail. // The function returns // -1 if bin1bin2 // operators and routines needed by the algorithms to manipulate the term // ordering term_ordering& operator=(const term_ordering&); // assignment operator with memory control float operator[](const short& i) const; // Returns weight_vector[i] (FLT_MAX if i is out of range). term_ordering& convert_to_weighted_ordering(); // Sets elimination_block_size to 0. term_ordering& convert_to_elimination_ordering (const short& number_of_elimination_variables, const short& _elimination_ordering); // Sets elimination_block_size to number_of_elimination_variables // and the ordering on the elimination variables as given in the argument. term_ordering& append_weighted_variable(const float& weight); // Appends the given weight to the weight vector (with memory control). term_ordering& delete_last_weighted_variable(); // Deletes the last weighted variable (with memory control). term_ordering& swap_weights(const short& i, const short& j); // This function is used if two weighted variables must change their // position (order) with respect to the refining ordering. // output void print_weight_vector() const; void print() const; // Writes the term ordering to the standard output medium // (only the weight vector or with supplementary information). void print_weight_vector(FILE*) const; void print(FILE*) const; // Writes the term ordering to the referenced file // which has to be opened for writing before. void print_weight_vector(ofstream&) const; void print(ofstream&) const; // Writes the term ordering to the given ofstream. void format_print_weight_vector(ofstream&) const; // Writes the term ordering to the given ofstream in the format required // by the IP-algorithms. }; #endif // TERM_ORDERING_H singular-4.0.3+ds/IntegerProgramming/testdata.cc000066400000000000000000000135301266270727000216770ustar00rootroot00000000000000// testdata.cc // Implements the data generation routines declared in testdata.h. #ifndef TESTDATA_CC #define TESTDATA_CC #include "testdata.h" int random_matrix(const short& rows, const short& columns, const Integer& lower_bound, const Integer& upper_bound, ofstream& MATRIX) { // check arguments if(rows<=0) { cerr<<"ERROR: int random_matrix(const short&, const short&, \n" " const Integer&, const Integer&, ofstream&):\n" "first argument out of range: number of matrix rows must be positive" <=2 && strcmp(argv[1],"--help")) // argc has to be at least 2 // program name, MATRIX file { for(short i=1;i=argc-2) // file arguments reached break; if(!strcmp(argv[i],"RP")) { S_pair_criteria|=1; continue; } if(!strcmp(argv[i],"M")) { S_pair_criteria|=2; continue; } if(!strcmp(argv[i],"F")) { S_pair_criteria|=4; continue; } if(!strcmp(argv[i],"B")) { S_pair_criteria|=8; continue; } if(!strcmp(argv[i],"2")) { S_pair_criteria|=16; continue; } // option does not belong to an S-pair criterion break; } while(1); i--; // reset counter so that the outer loop continue; // continues with the just considered argument } if(!strcmp(argv[i],"-p")) { // read interreduction percentage i++; char** rest; interreduction_percentage=strtod(argv[i],rest); // The function strtod converts a string into a double. As the // specification is not correct, it may cause trouble... // For example, if the argument can be read as a float, the value // of rest should be NULL. This is not the case. Therefore, we can // only check by the following string comparison if a float has been // built. An argument as 15xy is thereby considered as valid // (with interreduction_percentage==15.0). if(!(strcmp(argv[i],*rest))) // argument was no float { cerr<<"ERROR: invalid argument for interreduction percentage"< where GB stands for GROEBNER and is the abbreviation for the used algorithm as above. A MATRIX file should look as follows: MATRIX columns: cost vector: rows: matrix: positive row space vector: The last two lines are only needed when toric_ideal is called with the algorithms of Hosten/Sturmfels or Bigatti/La Scala/Robbiano, i.e. the options -alg hs or -alg blr The other algorithms ignore these lines. Example: MATRIX columns: 3 cost vector: 1 1 1 rows: 2 matrix: 1 2 3 4 5 6 positive row space vector: 1 2 3 A GROEBNER file looks as follows: GROEBNER computed with algorithm: (* abbreviations as above *) from file(s): (* the following four lines are optional *) computation time: term ordering: elimination block variables >0 *) weighted block should always be >0 *) size: Groebner basis: (* optional *) The Groebner basis consists always of binomials of the form x^a - x^b where x^a and x^b are relatively prime. Such a binomial can be represented by the vector a-b. The basis elements in the GROEBNER file are given by the coefficients of this vector representation. The settings for Buchberger´s algorithm and the compiler flags are produced when the GROEBNER file is generated by a call of toric_ideal with the verbose output option -v, --verbose Example (not belonging to the example above): GROEBNER computed with algorithm: du term ordering: elimination block: 0 weighted block: 3 W_LEX 1 2 3 size: 1 Groebner basis: 2 3 -2 (* x^2 * y^3 - z^2 *) OPTIONS: -alg , --algorithm algorithm to use for computing the toric ideal; may be ct for Conti/Traverso, pct for the positive Conti/Traverso, ect for Conti/Traverso with elimination, pt for Pottier, hs for Hosten/Sturmfels, du for Di Biase/Urbanke, blr for Bigatti-LaScal-Robbiano. -p percentage of new generators to cause an autoreduction during Buchberger´s algorithm; may be an arbitrary float, a negative value allows no intermediate autoreductions default is -p 12.0 -S [RP] [M] [B] [M] [2] criteria to use in Buchberger´s algorithm for discarding unneccessary S-pairs RP relatively prime leading terms M Gebauer-Moeller criterion M F Gebauer-Moeller criterion F B Gebauer-Moeller criterion B 2 Buchberger´s second criterion default is -S RP M B -v, --verbose verbose output mode; writes the settings for Buchberger´s algorithm and the compiler flags into the output GROEBNER file -V , --version version of Buchberger´s algorithm to use; may be 1, 1a, 2 or 3 default is -V 1 singular-4.0.3+ds/Makefile.am000066400000000000000000000016171266270727000160160ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I m4 if ENABLE_FACTORY USE_FACTORY = factory endif SUBDIRS = resources omalloc xalloc $(USE_FACTORY) \ libpolys gfanlib IntegerProgramming \ kernel Singular \ dox emacs redhat desktop EXTRA_DIST = README README.md README.pkg autogen.sh git-version-gen doxy redhat/singular.spec.in GPL2 GPL3 doc/doc.tbz2 bin_SCRIPTS = libsingular-config dist-hook: $(srcdir)/git-version-gen $(srcdir)/.tarball-git-version > $(distdir)/.tarball-git-version install-data-local: -cat ${top_srcdir}/doc/doc.tbz2| (cd $(datadir)/singular;tar jxf -) -mkdir $(datadir)/info -mv $(datadir)/singular/singular.hlp $(datadir)/info/. configheaderdir = ${includedir}/singular nodist_configheader_HEADERS = singularconfig.h DISTCLEANFILES = $(nodist_configheader_HEADERS) dist_man1_MANS = doc/Singular.man doc/ESingular.man doc/TSingular.man pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = Singular.pc singular-4.0.3+ds/NEWS000066400000000000000000000000001266270727000144420ustar00rootroot00000000000000singular-4.0.3+ds/README000066400000000000000000000015171266270727000146410ustar00rootroot00000000000000CAS Singular ============ Singular is a computer algebra system for polynomial computations, with special emphasis on commutative and non-commutative algebra, algebraic geometry, and singularity theory. It is free and open-source under the GNU General Public Licence (See [COPYING]). * Installation instructions from source code: * Homepage: * Source code: * User Manual: * Bug/Issue-Tracker: * Singular Wiki: * [Developer and Reference Manual:](@ref main_page) singular-4.0.3+ds/README.pkg000066400000000000000000000020331266270727000154130ustar00rootroot00000000000000Debian (and Debian based Operating Systems) =========================================== The Debian [1] package for Singular is currently maintained by the Debian Science Team [2,3]: the git repository for the singular Debian package is at Alioth [4]. [1] https://www.debian.org/ [2] https://wiki.debian.org/DebianScience [3] https://qa.debian.org/developer.php?login=debian-science-maintainers@lists.alioth.debian.org [4] http://anonscm.debian.org/cgit/debian-science/packages/singular.git/ Fedora (and RPM based Operating Systems) ======================================= To build Singular rpm packages run (with 4.0.0 replaced by the respective Singular version): $ rpmbuild -tb singular-4.0.0.tar.gz To install the newly created packages run (as superuser, with x86_64 replaced by your architecture and 4.0.0 by the respective Singular version): $ cd `rpm --eval '%{_topdir}'`/RPMS $ rpm -i x86_64/singular-4.0.0-1.x86_64.rpm noarch/singular-common-4.0.0-1.noarch.rpm Gentoo ====== install from the main tree: emerge singular is sufficient. singular-4.0.3+ds/Singular.pc.in000066400000000000000000000006171266270727000164760ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libSingular Description: The Singular high level functionality Version: @PACKAGE_VERSION@ URL: https://github.com/Singular/Sources/ Requires: @PKG_REQUIRE@ libpolys Conflicts: Cflags: -I${includedir} -I${includedir}/singular @SINGULAR_CFLAGS@ Libs: -L${libdir} -lSingular @USEPPROCSDYNAMICLD@ Libs.private: singular-4.0.3+ds/Singular/000077500000000000000000000000001266270727000155415ustar00rootroot00000000000000singular-4.0.3+ds/Singular/COPYING000066400000000000000000000021551266270727000165770ustar00rootroot00000000000000 SINGULAR version 4-0 University of Kaiserslautern Department of Mathematics and Centre for Computer Algebra Authors: G.-M. Greuel, G. Pfister, H. Schoenemann Copyright (C) 1986-2016 *NOTICE* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation ( version 2 or version 3 of the License ). Some single files have a copyright given within the file: Singular/ndbm.* (BSD). This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA (see GPL) Please send any comments or bug reports to . singular-4.0.3+ds/Singular/ChangeLog000066400000000000000000000000021266270727000173030ustar00rootroot00000000000000 singular-4.0.3+ds/Singular/LIB/000077500000000000000000000000001266270727000161475ustar00rootroot00000000000000singular-4.0.3+ds/Singular/LIB/.singularrc000066400000000000000000000000321266270727000203140ustar00rootroot00000000000000system("--allow-net", 1); singular-4.0.3+ds/Singular/LIB/COPYING000066400000000000000000000276011266270727000172100ustar00rootroot00000000000000 SINGULAR version 4-0 Singular-libraries University of Kaiserslautern Department of Mathematics and Centre for Computer Algebra Authors: see the header of the libraries or the list below Copyright (C) 1986-2016 This directory contains all Singular libraries, some came from the Singular team, some were contributed by users. Therefore, the default copyright notice of Singular applies, unless the library itself states something else. *NOTICE* The copyrights of the libaries are given in the header of the libraries. If no copyright is given, the following applies: This package is part of the software SINGULAR: the copyright of the corresponding SINGULAR version applies. Please send any comments or bug reports to or the author(s) of the library. Contributors: ============= absfact.lib Gregoire Lecerfr lecerf at math.uvsq.fr Wolfram Deckerr decker at math.uni-sb.de Gerhard Pfister pfister at mathematik.uni-kl.de aksaka.lib Christoph Mang ainvar.lib Gerhard Pfiste pfister@mathematik.uni-kl.de Gert-Martin Greuel greuel@mathematik.uni-kl.de alexpoly.lib Fernando Hernando Carrillo hernando@agt.uva.es Thomas Markwig keilen@mathematik.uni-kl.de algebra.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de Agnes Eileen Heydtmann Gerhard Pfister pfister@mathematik.uni-kl.de arcpoint.lib Nadine Cremer atkins.lib Stefan Steidel steidel@mathematik.uni-kl.de bfun.lib Daniel Andres daniel.andres@math.rwth-aachen.de Viktor Levandovskyy levandov@math.rwth-aachen.de brnoeth.lib Jose Ignacio Farran Martin ignfar@eis.uva.es Christoph Lossen lossen@mathematik.uni-kl.de central.lib Oleksandr Motsak motsak at mathematik dot uni minus kl dot de cimonom.lib I.Bermejo ibermejo@ull.es I.Garcia-Marco iggarcia@ull.es J.-J.Salazar-Gonzalez jjsalaza@ull.es classify.lib Kai Krueger krueger@mathematik.uni-kl.de compregb.lib Akira Suzuki sakira@kobe-u.ac.jp control.lib Oleksandr Iena yena@mathematik.uni-kl.de Markus Becker mbecker@mathematik.uni-kl.de Viktor Levandovskyy levandov@mathematik.uni-kl.de curvepar.lib Maryna Viazovska viazovsk@mathematik.uni-kl.de crypto.lib Gerhard Pfister pfister@mathematik.uni-kl.de deform.lib Bernd Martin martin@math.tu-cottbus.de discretize.lib Viktor Levandovskyy levandov@risc.uni-linz.ac.at dmod.lib Viktor Levandovskyy levandov@risc.uni-linz.ac.at Jorge Martin Morales jorge@unizar.es dmodapp.lib Viktor Levandovskyy levandov@math.rwth-aachen.de Daniel Andres daniel.andres@math.rwth-aachen.de elim.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de Gerhard Pfister pfister@mathematik.uni-kl.de Hans Schoenemann hannes@mathematik.uni-kl.de equising.lib Andrea Mindnich mindnich@mathematik.uni-kl.de finvar.lib Agnes E. Heydtmann Simon King simon.king@nuigalway.ie freegb.lib Viktor Levandovskyy levandov@math.rwth-aachen.de general.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de Anne Fruehbis-Krueger anne@mathematik.uni-kl.de gkdim.lib Lobillo, F.J. jlobillo@ugr.es Rabelo, C. crabelo@ugr.es gmspoly.lib Mathias Schulze mschulze@mathematik.uni-kl.de gmssing.lib Mathias Schulze mschulze@mathematik.uni-kl.de graphics.lib Christian Gorzel gorzelc@math.uni-muenster.de groups.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de Gerhard Pfister pfister@mathematik.uni-kl.de grwalk.lib I Made Sulandra hnoether.lib Martin Lamm lamm@mathematik.uni-kl.de homolog.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de Bernd Martin martin@math.tu-cottbus.de hyperel.lib Markus Hochstetter markushochstetter@gmx.de inout.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de Bernd Martin martin@math.tu-cottbus.de intprog.lib Christine Theis ctheis@math.uni-sb.de involut.lib Oleksandr Iena yena@mathematik.uni-kl.de Markus Becker mbecker@mathematik.uni-kl.de Viktor Levandovskyy levandov@mathematik.uni-kl.de jacobson.lib Kristina Schindelar Kristina.Schindelar@math.rwth-aachen.de Viktor Levandovskyy levandov@math.rwth-aachen.de kskernel.lib Tetyana Povalyaeva povalyae@mathematik.uni-kl.de latex.lib Christian Gorzel gorzelc@math.uni-muenster.de lll.lib Alberto Vigneron-Tenorio alberto.vigneron@uca.es Alfredo Sanchez-Navarro alfredo.sanchez@uca.es linalg.lib Ivor Saynisch ivs@math.tu-cottbus.de Mathias Schulze mschulze@mathematik.uni-kl.de makedbm.lib Kai Krueger krueger@mathematik.uni-kl.de matrix.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de Bernd Martin martin@math.tu-cottbus.de mprimdec.lib Alexander Dreyer dreyer@mathematik.uni-kl.de modstd.lib A. Hashemi Amir.Hashemi@lip6.fr G. Pfister pfister@mathematik.uni-kl.de H. Schoenemann hannes@mathematik.uni-kl.de mondromy.lib Mathias Schulze mschulze@mathematik.uni-kl.de mregular.lib I.Bermejo ibermejo@ull.es Ph.Gimenez pgimenez@agt.uva.es G.-M.Greuel greuel@mathematik.uni-kl.de multigrading.lib Rene Birkner rbirkner@math.fu-berlin.de Lars Kastner lkastner@math.fu-berlin.de Oleksandr Motsak motsak at mathematik dot uni minus kl dot de ncalg.lib Viktor Levandovskyy levandov@mathematik.uni-kl.de Oleksandr Motsak motsak at mathematik dot uni minus kl dot de ncdecomp.lib Viktor Levandovskyy levandov@mathematik.uni-kl.de nchomolog.lib Viktor Levandovskyy levandov@math.rwth-aachen.de Gerhard Pfister pfister@mathematik.uni-kl.de nctools.lib Levandovskyy V. levandov@mathematik.uni-kl.de Lobillo, F.J. jlobillo@ugr.es Rabelo, C. crabelo@ugr.es Oleksandr Motsak motsak at mathematik dot uni minus kl dot de noether.lib A. Hashemi Amir.Hashemi@lip6.fr normal.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de G. Pfister pfister@mathematik.uni-kl.de normaliz.ib W. Bruns Winfried.Bruns@Uni-Osnabrueck.de C. Soeger Christof.Soeger@Uni-Osnabrueck.de ntsolve.lib Wilfred Pohl pohl@mathematik.uni-kl.de Dietmar Hillebrand paramet.lib Thomas Keilen keilen@mathematik.uni-kl.de perron.lib Oleksandr Motsak motsak at mathematik dot uni minus kl dot de phindex.lib pointid.lib Stefan Steidel steidel@mathematik.uni-kl.de poly.lib Olaf Bachmann obachman@mathematik.uni-kl.de Gert-Martin Greuel greuel@mathematik.uni-kl.de Anne Fruehbis-Krueger anne@mathematik.uni-kl.de polymake.lib Thomas Markwig keilen@mathematik.uni-kl.de presolve.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de primdec.lib Gerhard Pfister pfister@mathematik.uni-kl.de Wolfram Decker decker@mathematik.uni-kl.de Hans Schoenemann hannes@mathematik.uni-kl.de Santiago Laplagne slaplagn@dm.uba.ar primitiv.lib Martin Lamm lamm@mathematik.uni-kl.de qhmoduli.lib Thomas Bayer bayert@in.tum.de qmatrix.lib Lobillo, F.J. jlobillo@ugr.es Rabelo, C. crabelo@ugr.es random.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de Bernd Martin martin@math.tu-cottbus.de realrad.lib Silke Spang redcgs.lib Antonio Montes Hans Schoenemann reesclos.lib Tobias Hirsch hirsch@math.tu-cottbus.de resbinomial.lib R. Blanco rblanco@modulor.arq.uva.es G. Pfister pfister@mathematik.uni-kl.de resgraph.lib A. Fruehbis-Krueger anne@mathematik.uni-kl.de resolve.lib A. Fruehbis-Krueger anne@mathematik.uni-kl.de G. Pfister pfister@mathematik.uni-kl.de reszeta.lib A. Fruehbis-Krueger anne@mathematik.uni-kl.de G. Pfister pfister@mathematik.uni-kl.de ring.lib G.-M.Greuel greuel@mathematik.uni-kl.de rinvar.lib Thomas Bayer bayert@in.tum.de rootsmr.lib Enrique A. Tobis etobis@dc.uba.ar rootsur.lib Enrique A. Tobis etobis@dc.uba.ar sagbi.lib Gerhard Pfister pfister@mathematik.uni-kl.de Anen Lakhal alakhal@mathematik.uni-kl.de sheafcoh.lib Wolfram Decker decker@mathematik.uni-kl.de Christoph Lossen lossen@mathematik.uni-kl.de Gerhard Pfister pfister@mathematik.uni-kl.de signcond.lib Enrique A. Tobis etobis@dc.uba.ar sing.lib Gert-Martin Greuel greuel@mathematik.uni-kl.de Bernd Martin martin@math.tu-cottbus.de solve.lib Moritz Wenk wenk@mathematik.uni-kl.de spcurve.lib Anne Fruehbis-Krueger anne@mathematik.uni-kl.de spectrum.lib S. Endrass standard.lib Olaf Bachmann obachman@mathematik.uni-kl.de Hans Schoenemann hannes@mathematik.uni-kl.de stratify.lib Anne Fruehbis-Krueger anne@mathematik.uni-kl.de surf.lib Hans Schoenemann hannes@mathematik.uni-kl.de S. Endrass surfex.lib Oliver Labs teachstd.lib G.-M. Greuel greuel@mathematik.uni-kl.de tropical.lib A. Jensen jensen@math.tu-berlin.de H. Markwig hannah@uni-math.gwdg.de T. Markwig keilen@mathematik.uni-kl.de toric.lib Christine Theis ctheis@math.uni-sb.de triang.lib D. Hillebrand weierstr.lib G.-M. Greuel greuel@mathematik.uni-kl.de zeroset.lib Thomas Bayer bayert@in.tum.de singular-4.0.3+ds/Singular/LIB/GND.lib000066400000000000000000000710661266270727000172610ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////////////////// version="version GND.lib 4.0.1.2 Nov_2015 "; category="Commutative Algebra"; info=" LIBRARY : GND.lib AUTHOR : Adrian Popescu, popescu@mathematik.uni-kl.de OVERVIEW : A method to compute the General Neron Desingularization in the frame of one dimensional local domains REFERENCES: @* [1] A. Popescu, D. Popescu, \"A method to compute the General Neron Desingularization in the frame of one dimensional local domains\", arxiv.org/abs/1508.05511 KEYWORDS: desingularization; general neron. PROCEDURES: desingularization() "; /////////////////////////////////////////////////////////////////////////////////////////// LIB "primdec.lib"; LIB "linalg.lib"; LIB "poly.lib"; /////////////////////////////////////////////////////////////////////////////////////////// static proc deltaf(ideal i,int r,int howmanyy) "USAGE: computes delta_f = ideal generated by the r x r minors of the jacobian of i" { matrix drond = jacob(i); matrix drond2[size(i)][howmanyy] = drond[1..size(i),(nvars(basering)-howmanyy+1)..(nvars(basering))]; ideal d = minor(drond2,r); return(d); } /////////////////////////////////////////////////////////////////////////////////////////// static proc comb(int n, int r,int start,list l,list tot) "USAGE: returns combinations of n taken r, and saves it in tot and returns tot" { int i; if(size(l) == r) { tot[size(tot)+1] = l; return(tot); } for(i=start+1;i<=n;i++) { list ll = l + list(i); tot = comb(n,r,i,ll,tot); kill ll; } return(tot); } /////////////////////////////////////////////////////////////////////////////////////////// static proc H(ideal I, int howmanyy,ideal xid) "USAGE: returns H_{B/A} = radical(...)" { I = std(I); xid = std(xid); list HBA; int n=size(I); int r,i,j,kk,found; list total; for(r = 1;r<=n && r<=howmanyy;r++) { list c; total = total + comb(n,r,0,c,total); kill c; } for(i = 1;i<=size(total);i++) { ideal f; for(j = 1; j<= size(total[i]);j++) { f = f + I[total[i][j]]; } ideal fx = f; for(kk = 1;kk<=nvars(basering)-howmanyy;kk++) { fx = subst(fx,var(kk),1); } fx = fx + 0; found = 0; for(kk=1;(kk<=size(fx)) && (found == 0);kk++) { if(deg(fx[kk])>0) { found =1; } } kill fx; if((size(f)<=(howmanyy)) && found == 1) { list term; attrib(xid,"isSB",1); term[1] = reduce(quotient(f+xid,I),xid); term[2] = deltaf(f,size(f),howmanyy); term[3] = f; term[4] = total[i]; if((term[1]!= 0) && (term[2] != 0) ) { HBA[size(HBA)+1] = term; } kill term; } kill f; } //HBA = radical(HBA); return(HBA); } /////////////////////////////////////////////////////////////////////////////////////////// static proc extractP(list wP, ideal I) "USAGE: choose P from wP and save it's properties" { list P; int i,j,k; poly f; int found = 0; for(i=1;(i<=size(wP)) && (found == 0);i++) { for(j=1;j<=size(wP[i][1]) && (found == 0);j++) { for(k = 1;k<=size(wP[i][2]) && (found == 0);k++) { f = wP[i][1][j] * wP[i][2][k]; /*if(size(std(f)) > 1) { //"Is this possible?";~; } f = std(f)[1];*/ if((f != 0) && (std(reduce(f,std(I))) != 0)) { P[1] = f; P[2] = wP[i][1][j]; P[3] = wP[i][2][k]; P[4] = wP[i][3]; P[5] = wP[i][4]; found = 1; } } } } if(size(P) <1) { ERROR("No suitable P was found"); } return(P); } /////////////////////////////////////////////////////////////////////////////////////////// static proc isinList(string f, list L) "USAGE: tests if string f is in the list L" { int i; for(i=1;i<=size(L);i++) { if(L[i] == f) { return(1); } } return(0); } /////////////////////////////////////////////////////////////////////////////////////////// static proc findmc(ideal I,ideal m) "USAGE: finds the smallest c s.t. m^c is included in I" { int i=1; while(1) { if(std(reduce(I,std(m^i))) != 0) { return(i-1); } i++; } } /////////////////////////////////////////////////////////////////////////////////////////// static proc finddz(poly vp,int nra,int nrx) "USAGE: finds d and z" { int i,j,k; ideal x; string xs; //string as; /* for(i=1;i<=nra;i++) { as = as + ","+string(var(i)); } as = as[2..size(as)]; */ for(i=1;i<=nrx;i++) { x[i] = var(i); xs = xs + ","+string(var(i)); } xs = xs[2..size(xs)]; /* if(std(reduce(variables(vp), std(x))) == 0) { return(list(vp,poly(1))); } */ int c = findmc(vp,x); ideal mc = x^c; for(i=1; i<=ncols(mc);i++) { if(std(reduce(variables(mc[i]), std(x))) != 0) { mc[i] = 0; } } mc = mc+0; ideal mc2 = mc; for(i=1;i<=ncols(mc2);i++) { if(std(reduce(mc2[i],std(vp))) != 0) { mc2[i] = 0; } } mc2 = mc2 + 0; if(mc2[1] != 0) { for(i=1;i<=ncols(mc2);i++) { if(mc2[i]/vp != 0) { return(list(mc2[i],mc2[i]/vp)); } } ideal vpid = std(vp); for(i=1;i<=ncols(mc2);i++) { for(j=1;j<=ncols(vpid);j++) { if(vpid[j] != 0) { if(mc2[i]/vpid[j] != 0) { return(list(mc2[i],mc2[i]/vpid[j])); } } } } } else { ideal vpid = std(vp); for(i=1;i<=ncols(mc);i++) { for(j=1;j<=ncols(vpid);j++) { if(vpid[j] != 0) { if(mc[i]/vpid[j] != 0) { return(list(mc[i],mc[i]/vpid[j])); } } } } } return(list(0,0)); } /////////////////////////////////////////////////////////////////////////////////////////// static proc inY(poly p,int nrx,int nry) "USAGE: tests if poly p contains just the variables var(nrx+1),...,var(nry)" { int i; ideal y; for(i=1;i<=nry;i++) { y[size(y)+1] = var(nrx+i); } y = std(y); if(std(reduce(variables(p),y)) == 0) { return(1); } return(0); } /////////////////////////////////////////////////////////////////////////////////////////// static proc myjet(ideal p, int bound,string param,string variab) "USAGE: computes the jet in the right ring (instead of switching it on and on)" { def r = basering; def R2 = ring(crl(param,variab,"ds")); setring(R2); ideal p = imap(r,p); for(int i=1;i<=ncols(p);i++) { p[i] = jet(p[i],bound); } setring r; return(imap(R2,p)); } /////////////////////////////////////////////////////////////////////////////////////////// proc invp(poly p, int bound,list param,list variab) "USAGE: computes the inverse in Q(param)[variab]" { def r = basering; def R2 = ring(crl(param,variab,"ds")); setring(R2); poly p = imap(r,p); if(bound<=0) { ERROR("My inverse : negative bound in the inverse"); } if(p == 0) { ERROR("My inverse : p is 0"); } poly original,res; original = p; if(ord(p) != 0) { ERROR("My inverse : the power series is not a unit."); } poly q = 1/p[1]; res = q; p = q * (p[1] - jet(p,bound)); poly s = p; while(p != 0) { res = res + q * p; p = jet(p*s,bound); } //res = division(poly(1),p,bound); //TEST if(jet(original*res,bound) != poly(1)) { ERROR("Myinverse does not work properly."); } setring r; poly res = imap(R2,res); return(res); } /////////////////////////////////////////////////////////////////////////////////////////// static proc findminor(int y, poly mr, ideal f) "USAGE: returns the entries from which the minor comes from" { int n = ncols(f); int max = y; if(n > y) { max = n; } matrix drond = jacob(f); matrix M[n][y] = drond[1..n,(nvars(basering)-y+1)..(nvars(basering))]; list resf,resy; list total2; for(int r = 1;r<=max;r++) { list c; total2 = total2 + comb(max,r,0,c,total2); kill c; } int i,j; i=1; while(i<=size(total2)) { if(size(total2[i]) == n) {break;} i=i+1; } while(size(total2[i]) == n) { if(total2[i][n] <= n) { def dummy = total2[i]; resf[size(resf)+1] = intvec(dummy[1..size(total2[i])]); kill dummy; } if(total2[i][n] <= y) { def dummy = total2[i]; resy[size(resy)+1] = intvec(dummy[1..size(total2[i])]); kill dummy; } i = i+1; } matrix m[n][n]; for(i = 1; i<=size(resf); i++) { for(j = 1; j<=size(resy); j++) { m = M[resf[i],resy[j]]; if(det(m) == mr || det(m) == -mr) { return(resf[i],resy[j]); } } } ERROR("No such minor found!"); } /////////////////////////////////////////////////////////////////////////////////////////// proc findnewvar(string Z) "USAGE: Finds new unused variable Z,Z1,Z2,..." { string S = "," + charstr(basering) + "," + varstr(basering) + ","; Z = "," + Z + ","; if(find(S,Z) == 0) { return(Z[2..size(Z)-1]); } int i=1; while(find(S,Z+"("+string(i)+")") == 1) { i++; } Z = string(Z[2..size(Z)-1])+"("+string(i)+")"; return(Z); } /////////////////////////////////////////////////////////////////////////////////////////// static proc mylcm(ideal id,list asl) "USAGE: computes the lcm of these numbers" { int i; def r1 = basering; def r2 = ring(crl(list(),asl,"dp")); setring(r2); ideal id = imap(r1,id); poly lcmi=1; for(i=1;i<=size(id);i++) { lcmi = lcm(lcmi,id[i]); } setring r1; return(imap(r2,lcmi)); } /////////////////////////////////////////////////////////////////////////////////////////// static proc mysubstpoly(poly p,int which,poly what,list #) "USAGE: substitutes parameters also for denominators (what is just a number)" { if(size(#)!= 1) { return(p); } if(#[1]!= "par" && #[1] != "var") { return(p); } number lcm = denominator(content(p)); p = p*lcm; if(#[1] == "par") { p = subst(p,par(which),what); lcm = leadcoef(subst(lcm,par(which),what)); } if(#[1] == "var") { p = subst(p, var(which), what); lcm = leadcoef(subst(lcm,var(which),what)); } p = p / lcm; return(p); } /////////////////////////////////////////////////////////////////////////////////////////// static proc mysubst(ideal i,int which,poly what,list #) "USAGE: substitutes parameters also for denominators (what is just a number)" { if(size(#)!= 1) { return(i); } if(#[1]!= "par" && #[1] != "var") { return(i); } for(int j = 1; j<=size(i);j++) { i[j] = mysubstpoly(i[j], which, what, #); } return(i); } /////////////////////////////////////////////////////////////////////////////////////////// static proc crl(list param, list variab, string order) "USAGE: construct the desired ringlist" { list l; if(size(param)==0) { l[1] = 0; } else { l[1] = list(0,param,list(list("lp",1)),ideal(0)); } l[2] = variab; l[3] = list(list(order,1),list("C",0)); l[4] = ideal(0); return(l); } /////////////////////////////////////////////////////////////////////////////////////////// proc desingularization(all, int nra, int nrx, int nry, ideal xid, ideal yid, ideal aid, ideal f, list #) "USAGE : Returns as output a General Neron Desingularization as in the Paper http://arxiv.org/abs/1508.05511" { // First we construct everything //def oldoption = option(get); //option(notWarnSB); if(ncols(f)!=nry || nra<0 || nrx<0 || nry<0 || nra+nrx+nry!=nvars(all)) { ERROR("Input is wrong"); } int computeker = 1; int debug = 0; if(size(#) > 0) { if(isinList("injective",#)) { computeker = 0; } if(isinList("debug",#)) { debug = 1; } } string as,xs,ys; list asl,xsl,ysl; ideal a,x,y; int i,j,k; if(nra != 0) { as = string(var(1)); asl[1] = string(var(1)); a[1] = var(1); for(i=2;i<=nra;i++) { as = as+","+string(var(i)); a[ncols(a)+1] = var(i); asl[size(asl)+1] = string(var(i)); } } //as; if(nrx!=0) { xs = string(var(nra+1)); x[1] = var(nra+1); xsl[1] = string(var(nra+1)); for(i=nra+2;i<=nra+nrx;i++) { xs = xs+","+string(var(i)); x[ncols(x)+1] = var(i); xsl[size(xsl)+1] = string(var(i)); } } //xs; if(nry!=0) { ys = string(var(nra+nrx+1)); y[1] = var(nra+nrx+1); ysl[1] = string(var(nra+nrx+1)); for(i=nra+nrx+2;i<=nra+nrx+nry;i++) { ys = ys+","+string(var(i)); y[ncols(y)+1] = var(i); ysl[size(ysl)+1] = string(var(i)); } } //ys; def Abase = ring(crl(list(),xsl,"dp")); setring Abase; qring A = std(imap(all,xid)); def Bbase = ring(crl(xsl,ysl,"dp")); setring Bbase; ideal yid = imap(all, yid); i = ncols(yid); yid = std(yid); if(ncols(yid)!=i) { if(debug) { "yid is not a SB."; "We change yid with its SB:"; yid; } } qring B = yid; def Bfalsebase = ring(crl(list(),xsl+ysl,"dp")); setring(Bfalsebase); qring Bfalse = std(imap(all,yid)); if(nra!=0) { def Apreal = ring(crl(asl,xsl,"dp")); def Apbase = ring(crl(list(),asl+xsl,"dp")); setring Apbase; qring Ap = std(imap(all,xid)+imap(all,aid)); } else { def Apbase = ring(crl(list(),xsl,"dp")); setring Apbase; qring Ap = std(imap(all,xid)); } ideal vid; for(i=1; i<=nrx; i++) { vid[ncols(vid)+1] = var(nra+i); } vid = vid + imap(all,f); map vBfalse = Bfalse,vid; // We start with the reduction to the case... setring Bfalse; if(computeker == 1) { if(debug) { "Computing the kernel:"; } def ker = kernel(Ap, vBfalse); if(debug) { ker; } Bfalse = std(ker); } else { if(debug) { "We do not compute the kernel since of \"injective\" argument in the input"; } } ideal I = ringlist(Bfalse)[4]; setring Bfalsebase; list whereP = H(imap(Bfalse,I),nry,imap(all,xid)); if(debug) { //whereP[1];~; } def Plist = extractP(whereP,imap(Bfalse,I)); setring Bfalse; def Plist = imap(Bfalsebase,Plist); if(debug) { "This is Plist:";Plist; } list whichminor = findminor(nry, Plist[3], Plist[4]); if(debug) { "The minor comes from these vars:";whichminor; } poly Pprim = Plist[1]; if(debug) { "P' = ",Pprim; } setring Ap; poly vpprim = vBfalse(Pprim); setring Apreal; if(debug) { "v(P'):";imap(Ap,vpprim); } setring Apreal; def dz = finddz(imap(Ap,vpprim),nra,nrx); int secondstrategy = 0; if(dz[1] == 0 && dz[2] == 0) { if(debug) { "The first strategy to find d and z failed"; "Try the second strategy (this may take longer)"; } setring all; secondstrategy = 1; poly M = imap(Bfalse,Plist)[3]; ideal ff; for(i=1;i<=nra+nrx;i++) { ff[i] = var(i); } ff = ff + f; map v = basering,ff; // It should be enough to consider the minor I have found. int found = 0; //ideal mino = minor(jacob(yid),min(nrows(jacob(yid)),ncols(jacob(yid)))); //mino;~; //for(k = 1;size(mino);i++) //{ //M = mino[k]; for(i=1;found == 0;i++) { for(j=1;j<=nrx && found == 0;j++) { a = var(nra+j); if(reduce(a^i,std(v(M) + a^(2*i))) == 0) { dz[1] = a[1]^i; dz[2] = v(M) /dz[1]; //z is actually 1/z so we have to construct it's invers dz[2] = 1/leadcoef(dz[2])*invp(dz[2]/leadcoef(dz[2]),3*i,asl,xsl); found = 1; } } } //} } poly d = dz[1]; poly z = dz[2]; // We have to truncate it: z = reduce(jet(z,deg(d^3)),std(reduce(d^3, std(imap(all,xid))))); if(secondstrategy == 1) { setring Apreal; def d = imap(all, d); def z = imap(all, z); setring all; } if(z == 0) { ERROR("Something went wrong in finddz since z=0"); } if(debug) { "d' =",d; "z =",z; } ideal denz; for(i=1;i<=size(z);i++) { denz[size(denz)+1] = denominator(leadcoef(z[i])); } def den = mylcm(denz,asl); z = z * den; int newAptest = 0; if(den != 1) { newAptest = 1; string aa = "a"; list newpar; newpar[1] = string(findnewvar(aa)); as = as + "," + findnewvar(aa); nra = nra + 1; def newApbase = ring(crl(list(),asl+xsl,"dp")); setring newApbase; poly p = var(nra)*imap(Apreal,den)-1; qring newAp = std(imap(all,xid)+imap(all,aid)+p); def d = imap(Apreal,d); def z = imap(Apreal,z)*var(nra); if(debug) { "new z = ",z; } def vid = imap(Ap,vid); Apbase = newApbase; Ap = newAp; def newApreal = ring(crl(asl,xsl,"dp")); setring newApreal; def z = imap(Ap,z); def d = imap(Apreal,d); def den = imap(Apreal,den); Apreal = newApreal; def newaring = ring(crl(list(),newpar,"dp")); setring newaring; } else { setring Ap; def d = imap(Apreal,d); setring Apreal; } // Construct B1 = B[Z]/d-pz and the maps string Z = "Z"; list newvar; newvar[1] = string(findnewvar(Z)); def newvarring = ring(crl(list(),newvar,"dp")); def B1base = Bbase+newvarring; def B1 = B+newvarring; def B1falsebase = Bfalsebase + newvarring; def B1false2 = Bfalse + newvarring; setring B1false2; poly frp1 = -imap(Apreal,d)+imap(Bfalse,Pprim)*var(nvars(B1false2)); qring B1false = std(fetch(B1false2,frp1) + ringlist(B1false2)[4]); ideal B1falseideal = ringlist(B1false)[4]; setring Apreal; def vid = imap(Ap,vid); vid[ncols(vid)+1] = z; setring B1false; //If P is constant (i.e. no Y), than I can work with d = d' = P = P' poly Pconst = reduce(imap(Bfalse,Pprim),std(imap(all,y))); if(Pconst == imap(Bfalse,Pprim)) { poly P =Pconst; //This is the case if P is constant if(debug) { "P is constant (no Y), so d = d' = P = P'"; "P = P' = ",P; } setring Apreal; def dprim = imap(B1false,P); d = dprim; } else { poly P = imap(Bfalse,Pprim)^2*var(nvars(B1false))^2; if(debug) { "P = P'^2 * Z^2";P; } setring Apreal; def dprim = d; d = d^2; } if(debug) { "d = ",d; } int c = deg(d); int s = deg(d^3); ideal vidjet; if(debug) { //vid; } for(i=1;i<=ncols(vid);i++) { vidjet[size(vidjet)+1] = reduce(jet(vid[i],s),std(reduce(d^3, std(imap(all,xid))))); } if(debug) { "vidjet:";vidjet; } map vBfalse = B1false,vidjet; poly Py = vBfalse(P); if(debug) { "Py =",Py; } // Prepare and build C, D and S setring Apreal; ideal lam; poly pp; for(i=1;i<=size(vidjet);i++) { pp = vidjet[i]; while(pp != 0) { if(leadcoef(vidjet[i]) != 1) { lam[size(lam)+1] = denominator(leadcoef(pp)); lam[size(lam)+1] = numerator(leadcoef(pp)); } pp = pp-lead(pp); } } setring Ap; def lam = imap(Apreal,lam); list newas; int howmanyfinala; if(size(lam) == 0) { def Cbase = ring(crl(list(),xsl,"dp")); setring Cbase; } else { ideal varlam = variables(lam); howmanyfinala = ncols(varlam); for(i=1;i<=ncols(varlam);i++) { newas[size(newas)+1] = string(varlam[i]); } def Cbase = ring(crl(list(),newas+xsl,"dp")); setring Cbase; } setring Ap; def aid = imap(all,aid); if(newAptest == 1) { ideal newaid = reduce(aid+imap(newApbase,p),std(varlam)); } else { ideal newaid = reduce(aid,std(varlam)); } for(i=1;i<=ncols(newaid)-1;i++) { if(newaid[i]!=0 ) { newaid[i] = aid[i]; } } if(newAptest == 1) { newaid[size(newaid)+1] = imap(newApbase,p); } newaid = newaid+0; setring Cbase; qring C = std(imap(Ap,newaid) + imap(all,xid)+imap(Apreal,d)^3); if(debug) { "This is C:";C; } setring Cbase; qring D = std(imap(Ap,newaid) + imap(all,xid)); if(debug) { "This is D:";D; } def vid = imap(Apreal,vid); ideal vidjet = imap(Apreal,vidjet); // Build the nice matrix setring B1; ideal wy,wf; ideal I = imap(Bfalse,I); for(i=1;i<=size(whichminor[1]);i++) { wf[size(wf)+1] = I[whichminor[1][i]]; } for(i=1;i<=size(whichminor[2]);i++) { wy[size(wy)+1] = var(whichminor[2][i]); } wy = reduce(std(reduce(maxideal(1),std(var(nvars(B1))))),std(wy))+0; poly frp1 = -imap(Apreal,d)+imap(Bfalse,Pprim)*var(nvars(B1)); ideal PMf = wf + wy + frp1; matrix PM[size(PMf)][nvars(B1)]; PM = jacob(PMf); matrix adj = adjoint(PM); matrix G = imap(Bfalse,Plist)[2]*var(nvars(B1))^2*adj; def seeGring = ring(crl(list(),list(string(ys[1])+string(nvars(B1))),"dp")); def seeG = B1 + seeGring; setring seeG; matrix G = imap(Bfalse,Plist)[2]*var(nvars(seeG))^2*imap(B1,adj); matrix H = imap(B1,PM); H = subst(H,var(nvars(seeG)-1),var(nvars(seeG))); G = subst(G,var(nvars(seeG)-1),var(nvars(seeG))); if(debug) { "This is the minor bordered matrix (H)";print(H); } if(debug) { "This is G: ";print(G); G; } setring D; def d = imap(Apreal,d); def Py = imap(Apreal,Py); poly ss = Py/d; ideal ssid = std(ss); for(i=1;i<=size(ssid);i++) { if(size(ssid[i]) < size(ss)) { ss = ssid[i]; } } // Recall that a was a quotient /*if(newAptest == 1) { ss = reduce(ss, imap(Apreal, z)*imap(Apreal, den)-1); }*/ if(debug) { if(newAptest == 1) { "s =",reduce(ss, std(var(nvars(basering)-nrx)*imap(Apreal, den)-1)); //"s =",subst(ss, imap(Apreal, z),1/imap(Apreal, den)); } else { "s =",ss; } } ideal dquot = ringlist(D)[4]; // Start constructing E list ts,yz; yz = ysl + list(string(ys[1]) + string(nry+1)); string t = "T"; def newvart = findnewvar(t); for(i=1;i<=nry+1;i++) { ts[size(ts)+1] = newvart + string(i); } def Efalsebase = ring(crl(list(),newas+xsl+yz+ts,"dp")); setring Efalsebase; qring Efalse = std(imap(D,dquot)); def f = imap(Bfalse,Plist)[4]; f[size(f)+1] = -imap(Apreal,dprim)+imap(Bfalse,Pprim)*var(nvars(Efalsebase)-nry-1); def vidjet = imap(Apreal,vidjet); vidjet = vidjet[nrx+1..size(vidjet)]; ideal id; for(i=1;i<=nvars(D);i++) { id[i] = var(i); } for(i=1;i<=size(vidjet);i++) { id[ncols(id)+1] = vidjet[i]; } map mapvidjet = Efalse,id; f = mapvidjet(f); ideal cc; for(i=1;i<=ncols(f);i++) { cc[i] = f[i] / (imap(Ap,d)^2); } if(debug) { "This is cc";cc; } def E = ring(crl(newas+xsl,yz+ts,"dp")); setring E; def d = imap(D,d); number ss = leadcoef(imap(D,ss)); def G = imap(seeG,G); def vidjet = imap(Apreal,vidjet); map mapvidjet = E,vidjet[nrx+1..ncols(vidjet)]; G = mapvidjet(G); execute("matrix T[nry+1][1] = "+string(ts)+";"); execute("ideal tid = "+string(ts)+";"); matrix ymy[nry+1][1]; for(i=1;i<=nry+1;i++) { ymy[i,1] = var(i)-vidjet[i+nrx]; } //ymy; //G; matrix hh = ss*ymy-d*G*T; ideal h; for(i=1;i<=nry+1;i++) { h[size(h)+1] = hh[i,1]; } //if(debug) if(1) { if(newAptest == 1) { "h = ";mysubst(h, npars(basering)-nrx,1/imap(Apreal, den),"par"); } else { "h = ";h; } } setring Apreal; /* matrix eps[nry+1][1]; //def vid = imap(Ap,vid); ideal dummy; ideal d2 = std(d^2); for(i=1;i<=nry;i++) { dummy = std(vid[i+nrx]-vidjet[i+nrx]); for(j=1;j<=ncols(dummy);j++) { for(k=1;k<=size(d2);k++) { if(dummy[j] / d2[k] != 0) { eps[i,1] = dummy[j] / d2[k]; } } } eps; if(eps[i,1] == 0 && vid[i+nrx] != vidjet[i+nrx]) { ERROR("problem appeared at the construction of eps"); } } if(debug) { "eps = ";eps; } setring E; def eps = imap(Apreal,eps); def HH = imap(B1,PM); HH = mapvidjet(HH); def tm = HH * eps; ideal tid; for(i=1;i<=nry+1;i++) { tid[i] = tm[i,1]; } if(debug) { "This is t:";tid; } */ setring E; def f = imap(Bfalse,Plist)[4]; f[size(f)+1] = -d+imap(Bfalse,Pprim)*var(nry+1); int m = deg(f[1]); for(i=2;i<=size(f);i++) { if(deg(f[i])>m) { m = deg(f[i]); } } if(debug) { "m =",m; } poly ff,ffx,fd; number ssm; ideal QT; ssm = ss^m; if(debug) { if(newAptest == 1) { "s^m =";mysubst(ssm, npars(basering)-nrx,1/imap(Apreal, den),"par"); } else { "s^m =",ssm; } } poly ssmd2 = ssm*d^2; for(i=1;i<=size(f);i++) { ff = f[i]; ffx = mapvidjet(ff); ffx = ssm*(ff-ffx); for(j=1;j<=nry+1;j++) { fd = diff(ff,var(j)); fd = mapvidjet(fd); ffx = ffx - (ssm)*(var(j)-vidjet[j+nrx])*fd; } attrib(h,"isSB",1); ffx = reduce(ffx,h); QT[i] = ffx / ssmd2; } if(debug) { if(newAptest == 1) { "QT =";mysubst(QT, npars(basering)-nrx,1/imap(Apreal, den),"par"); } else { "QT =";QT; } "f =";f; } ideal cc = imap(Efalse,cc); ideal g; for(i=1;i<=size(f);i++) { g[i] = ssm * cc[i] + ssm * var(nry+1+i) + QT[i]; } if(debug) { "g = "; if(newAptest == 1) { mysubst(g, npars(basering)-nrx,1/imap(Apreal, den),"par"); //reduce(mysubst(g, npars(basering)-nrx,1/imap(Apreal, den),"par"),std(x2^6,x1^4)); } else { g; } } // Activate this if the output is too big - in this way you could see a truncation. // Remember to change myvar and mypar if(0) { basering; poly gg; ideal p1,p2; string myvar = "x1,x2"; string mypar = "a1,a2,T1,T2,T3,T4,T5,Y1,Y2,Y3,Y4,Y5"; //QT = mysubst(QT, npars(basering)-nrx,1/imap(Apreal, den),"par"); for(int kk = 1; kk<=3;kk++) { "Next one!"; gg = QT[kk]; while(gg!=0) { p1 = ideal(numerator(leadcoef(gg))); p2 = ideal(denominator(leadcoef(gg))); myjet(p1,10,mypar,myvar); myjet(p2,10,mypar,myvar); leadmonom(lead(gg)); //lead(gg); ~; gg = gg-lead(gg); } } for(int kk = 1; kk<=3;kk++) { "Next one!"; gg = g[kk]; while(gg!=0) { p1 = ideal(numerator(leadcoef(gg))); p2 = ideal(denominator(leadcoef(gg))); myjet(p1,10,mypar,myvar); myjet(p2,10,mypar,myvar); leadmonom(lead(gg)); //lead(gg); ~; gg = gg-lead(gg); } } } setring Efalse; if(0) { setring Efalse; "h"; imap(E,h); "QT" imap(E,QT); "g"; imap(E,g); //reduce(imap(E,g),poly(x2^5)); def ggg = imap(E,g); ggg = reduce(ggg,x2^5); setring E; imap(Efalse,ggg);~; poly frp1 = -imap(E,d)+imap(Bfalse,Pprim)*var(nry+1); "frp1";~; frp1; qring Eprefinal = imap(D,dquot)+imap(E,h)+imap(E,g)+imap(Bfalse,I)+frp1; Eprefinal; setring E; def drond = jacob(g); matrix drond2[size(g)][nry+1] = drond[1..(size(g)),(nry+2)..ncols(drond)]; poly ssp = minor(drond2,size(g))[1]; poly invssp = ss*ssp; for(i=1;i<=nvars(E) div 2;i++) { invssp = subst(invssp,var(i),vidjet[i+nrx]); invssp = subst(invssp, var(nvars(E)-i+1),tid[i]); } //invssp = 1/invssp; ideal e2 = std(g,h); if(debug) { "And this is the map:"; } //execute("ideal themap = vidjet[nrx+1..size(vidjet)],"+t+",invssp;"); invssp = 1/invssp; if(debug) { themap; } string zz = "Z"; def newvar2 = findnewvar(zz); //execute("ring Efinalbase = (0,"+parstr(E)+"),("+varstr(E)+","+newvar2+"),dp;"); def q = imap(E,e2); poly teta = var(nvars(Efinalbase)) * imap(E,ss)*imap(E,ssp) - 1; qring Efinal = std(q,teta); if(debug) { "This is final E:"; basering; } } //option(set,oldoption); } example { "EXAMPLE:"; echo = 2; //Example 1 ring All = 0,(a1,a2,a3,x1,x2,x3,Y1,Y2,Y3),dp; int nra = 3; int nrx = 3; int nry = 3; ideal xid = x2^3-x3^2,x1^3-x3^2; ideal yid = Y1^3-Y2^3; ideal aid = a3^2-a1*a2; poly y; int i; for(i=0;i<=30;i++) { y = y + a1*x3^i/factorial(i); } for(i=31;i<=50;i++) { y = y + a2*x3^i/factorial(i); } ideal f = a3*x1,a3*x2,y; desingularization(All, nra,nrx,nry,xid,yid,aid,f); // With debug output desingularization(All, nra,nrx,nry,xid,yid,aid,f,"debug"); kill All,nra,nrx,nry,i; //Example 4 ring All = 0,(a1,a2,a3,a4,x,Y1,Y2,Y3),dp; int nra = 4; int nrx = 1; int nry = 3; ideal xid = 0; ideal yid = Y1^3-Y2^3; ideal aid = a3^2-a1*a2,a4^2+a4+1; poly y; int i; for(i=0;i<=30;i++) { y = y + a1*x3^i/factorial(i); } for(i=31;i<=50;i++) { y = y + a2*x3^i/factorial(i); } ideal f = a3*x,a3*a4*x,y; desingularization(All, nra,nrx,nry,xid,yid,aid,f); } singular-4.0.3+ds/Singular/LIB/JMBTest.lib000066400000000000000000000522541266270727000201170ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////// version="version JMBTest.lib 4.0.0.0 Jun_2013 "; // $Id: aba2de11ed1e911bbf56c65b39cfd2621b578a49 $ category="Algebraic Geometry"; // summary description of the library info=" LIBRARY: JMBTest.lib A library for Singular which performs JM basis test. AUTHOR: Michela Ceria, email: michela.ceria@unito.it SEE ALSO: JMSConst_lib KEYWORDS: J-marked schemes OVERVIEW: The library performs the J-marked basis test, as described in [CR], [BCLR]. Such a test is performed via the criterion explained in [BCLR], concerning Eliahou-Kervaire polynomials (EK from now on). We point out that all the polynomials are homogeneous and they must be arranged by degree. The fundamental steps are the following:@* -construct the Vm polynomials, via the algorithm VConstructor explained in [CR];@* -construct the Eliahou-Kervaire polynomials defined in [BCLR];@* -reduce the Eliahou-Kervaire polynomials using the Vm's;@* -if it exist an Eliahou-Kervaire polynomial such that its reduction mod Vm is different from zero, the given one is not a J-Marked basis. The algorithm terminates only if the ordering is rp. Anyway, the number of reduction steps is bounded. REFERENCES: [CR] Francesca Cioffi, Margherita Roggero,Flat Families by Strongly Stable Ideals and a Generalization of Groebner Bases, J. Symbolic Comput. 46, 1070-1084, (2011).@* [BCLR] Cristina Bertone, Francesca Cioffi, Paolo Lella, Margherita Roggero, Upgraded methods for the effective computation of marked schemes on a strongly stable ideal, Journal of Symbolic Computation (2012), http://dx.doi.org/10.1016/j.jsc.2012.07.006 @* PROCEDURES: Minimus(ideal) minimal variable in an ideal Maximus(ideal) maximal variable in an ideal StartOrderingV(list,list) ordering of polynomials as in [BCLR] TestJMark(list) tests whether we have a J-marked basis "; LIB "qhmoduli.lib"; LIB "monomialideal.lib"; LIB "ring.lib"; //////////////////////////////////////////////////////////////////// proc mod_init() "USAGE: mod_init(); RETURN: struct: jmp EXAMPLE: example mod_init; shows an example" { newstruct("jmp", "poly h, poly t"); } example { "EXAMPLE:"; echo = 2; mod_init(); } //////////////////////////////////////////////////////////////////// proc Terns(list G, int c) "USAGE: Terns(G,c); G list, c int RETURN: list: T NOTE: Input is a list of J-marked polynomials (arranged by degree) and an integer. EXAMPLE: example Terns; shows an example" { list T=list(); int z; for(int k=1; k<=size(G[c]);k=k+1) { //Loop on G[c] making positions of polynomials in G[c] z=size(T); T=insert(T,list(1,c,k) ,size(T)); } return(T); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); Terns(G2F, 1); Terns(G2F, 2); } //////////////////////////////////////////////////////////////////// proc VConst(list G, int c) "USAGE: VConst(G, c); G list, c int RETURN: list: V NOTES: this procedure computes the Vm polynomials following the algorithm in [CR],but it only keeps in memory the monomials by which the G's must be multplied and their positions. EXAMPLE: example VConst; shows an example" { jmp f=G[1][1]; int aJ=deg(f.h); // minimal degree of polynomials in G //print(aJ); list V=list(); V[1]=Terns(G,1); // V[1]=G[1] (keeping in memory only [head, position]) //print(c-aJ+1); int i; int j; int m; list OO; jmp p; for(m=2; m<=c-aJ+1; m=m+1) { //print("entro nel form"); if(m>size(G)) {V[m]=list(); //If we have not G[m] we insert a list() //print("vuota prima"); } else {V[m]=Terns(G,m); //print("piena prima"); } for(i=1; imax){max=L[i];} } return(max); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; ideal I=y,x,z; Maximus(I); } //////////////////////////////////////////////////////////////////// proc GJmpMins(jmp P, jmp Q) "USAGE: GJmpMins(P,Q); P jmp, Q jmp RETURN: int: d EXAMPLE: example GJmpMins; shows an example" { int d=1; //-1=lower, 0=equal, 1=higher //At the beginning suppose Q is higher if(deg(P.h)B[1]) { //the ordering MUST be rp //print("Maggiore per Lex"); d=1; } } return(d); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); TernCompare([1,1,1],[x,1,1],G2F); } //////////////////////////////////////////////////////////////////// proc MinOfV(list V, list G) "USAGE: Minimal(V,G); V list, G list RETURN: int: R NOTE: Input=lista(terne), G. EXAMPLE: example Minimal; shows an example" { //Minimal element for a given degree list R=list(); list MIN=V[1]; int h=1; int i; for(i=2; i<=size(V); i++) { //I consider the first as minimum //If I find something smaller I change minimum if(TernCompare(V[i],MIN,G)<=0) { MIN=V[i]; h=i; } } //Return: [minimum,position of the minimum] R=MIN,h; return(R); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); MinOfV(VConst(G2F,4,basering)[1],G2F); } //////////////////////////////////////////////////////////////////// proc OrderingV(list V,list G,list R) "USAGE: OrderingV(V,G,R); V list, G list, R list RETURN: list: R NOTE: Input: Vm,G,emptylist EXAMPLE: example OrderingV; shows an example" { //Order V[m] //R will contain results but at the beginning it is empty list M=list(); if(size(V)==1) { R=insert(R,V[1],size(R)); } else { M=MinOfV(V,G); R=insert(R,M[1],size(R)); V=delete(V,M[2]); //recursive call R=OrderingV(V,G,R); } return(R); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); OrderingV(VConst(G2F,4,basering)[1],G2F,list()); } //////////////////////////////////////////////////////////////////// proc StartOrderingV(list V,list G) "USAGE: StartOrdina(V,G); V list, G list RETURN: list: R NOTE: Input Vm,G. This procedure uses OrderingV to get the ordered polynomials as in [BCLR]. EXAMPLE: example StartOrderingV; shows an example" { return(OrderingV(V,G, list())); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); StartOrderingV(VConst(G2F,4,basering)[1],G2F); } //////////////////////////////////////////////////////////////////// proc Multiply(list L, list G) "USAGE: moltiplica(L,G); L list, G list RETURN: jmp: K NOTE: Input: a 3-ple,G. It performs the product associated to the 3-uple. EXAMPLE: example Multiply; shows an example" { jmp g=G[L[2]][L[3]]; jmp K; K.h=L[1]*g.h; K.t=L[1]*g.t; return(K); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; list P=x^2,1,1; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); Multiply(P,G2F); } //////////////////////////////////////////////////////////////////// proc IdealOfV(list V) "USAGE: IdealOfV(V); V list RETURN: ideal: I NOTES: this procedure takes a list of Vm's of a certain degree and construct their ideal, multiplying the head by the weighted variable t. EXAMPLE: example IdealOfV; shows an example" { ideal I=0; int i; if (size(V)!=0) { list M=list(); jmp g; for(i=1; i<= size(V); i++) { g=V[i]; g.h=t*g.h; M[i]=g.h+g.t; } I=M[1..size(M)]; //print("IdealOfV"); //I=std(I); } return(I); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z,t), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); IdealOfV(G2F[1]); } //////////////////////////////////////////////////////////////////// proc NewWeight(int n) "USAGE: NewWeight(n); n int RETURN: intvec: u EXAMPLE: example NewWeight; shows an example" { intvec u=0; u[n]=1; return(u); } example { "EXAMPLE:"; echo = 2; NewWeight(3); } //////////////////////////////////////////////////////////////////// proc FinalVm(list V1 , list G1 ,def r) "USAGE: FinalVm(V1, G1, r); V1 list, G1 list , r RETURN: intvec: u EXAMPLE: example NewWeight; shows an example" { //multiply and reduce, degree by degree intvec u=NewWeight(nvars(r)+1); list L=ringlist(r); L[2]=insert(L[2],"t",size(L[2])); //print(L[2]); list ordlist="a",u; L[3]=insert(L[3],ordlist,0); def H=ring(L); //print(V1); //print(G1); list M=list(); jmp p; list N; poly q; poly s; int i; int j; for(i=1; i<=size(G1); i++) { N=list(); for(j=1; j<=size(G1[i]); j++) { p=G1[i][j]; q=p.h; s=p.t; N[j]=list(q,s); } M[i]=N; } p.h=poly(0); p.t=poly(0); setring H; list R=list(); list S=list(); //print("anello definito"); def V=imap(r,V1); //def G=imap(r,G1); //print(V); def MM=imap(r,M); list G=list(); list N=list(); for(i=1; i<=size(MM); i++) { for(j=1; j<=size(MM[i]); j++) { p.h=MM[i][j][1]; p.t=MM[i][j][2]; N[j]=p; } G[i]=N; } ideal I=0; jmp LL; jmp UU; for(i=1; i<=size(V);i++) { R[i]=list(); S[i]=list(); I=0; for(j=1;j<=size(V[i]); j++) { LL=Multiply(V[i][j],G); LL.t=reduce(t*LL.t,I); //I only reduce the tail LL.t=subst(LL.t,t,1); S[i]=insert(S[i],LL,size(S[i])); LL.h=t*LL.h; R[i]=insert(R[i],LL,size(R[i])); UU=R[i][j]; I=I+ideal(UU.h+UU.t); attrib(I,"isSB",1); } } list M=list(); poly q; poly s; for(i=1; i<=size(S); i++) { N=list(); for(j=1; j<=size(S[i]); j++) { p=S[i][j]; q=p.h; s=p.t; N[j]=list(q,s); } M[i]=N; } p.h=poly(0); p.t=poly(0); setring r; def MM=imap(H,M); list MMM=list(); for(i=1; i<=size(MM); i++) { N=list(); for(j=1; j<=size(MM[i]); j++) { p.h=MM[i][j][1]; p.t=MM[i][j][2]; N[j]=p; } MMM[i]=N; } return(MMM); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); FinalVm(VConst(G2F,6,r) , G2F, r); } //////////////////////////////////////////////////////////////////// proc ConstructorMain(list G, int c,def r) "USAGE: Costruttore(G,c); G list, c int RETURN: list: R NOTE: At the end separated by degree. EXAMPLE: example Costruttore; shows an example" { list V=list(); V= VConst(G,c); //print("VConst"); //V non ordered list L=list(); list R=list(); int i; // head, position //order the different degrees for(i=1; i<=size(V); i++) { L[i]=StartOrderingV(V[i], G); } //multiply and reduce //print("Ordinare"); R=FinalVm(L, G, r); //print("FinalVm"); return(R); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); ConstructorMain(G2F,6,r); } //////////////////////////////////////////////////////////////////// proc EKCouples(jmp A, jmp B) "USAGE: CoppiaEK(A,B); A list, B list RETURN: list: L NOTE: At the end the monomials involved by EK. EXAMPLE: example EKCouples; shows an example" { poly E; list L=0,0; string s=varstr(basering); list VVV=varstr(basering); //L will contain results poly h=Minimus(variables(A.h)); //print(h); int l=findvars(h,1)[2][1]; if(l!=nvars(basering)) { //print("vero"); //print(l); for(int j=l+1;j<=nvars(basering); j++) { //print("entrata"); //print(var(j)); E=var(j)*A.h/B.h; //Candidate for * product //print(E); if(E!=0) { //print("primo if passato"); if(Minimus(variables(B.h))>=Maximus(variables(E))) { //Does it work with * ? //print("secondo if passato"); L[1]=j; L[2]=E; break; } } } } return (L); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp A; A.h=y*z^2; A.t=poly(0); jmp B; B.h=y^2*z; B.t=poly(0); EKCouples(A,B); EKCouples(B,A); } //////////////////////////////////////////////////////////////////// proc EKPolys(list G) "USAGE: PolysEK(G); G list RETURN: list: EK, list: D NOTE: At the end EK polynomials and their degrees EXAMPLE: example PolysEK; shows an example" { list D=list(); list C=list(); list N=0,0; list EK=list(); int i; int j; int k; int l; jmp p; for(i=1; i<=size(G); i++) { for(j=1; j<=size(G[i]); j++) { for(k=1; k<=size(G); k++) { for(l=1; l<=size(G[k]); l++) { if(i!=k||j!=l) { //Loop on polynomials C=EKCouples(G[i][j], G[k][l]); //print("coppia"); if(C[2]!=0) { C=insert(C,list(i,j,k,l),size(C)); EK=insert(EK,C,size(EK)); p=G[k][l]; D=insert(D,deg(C[2]*p.h),size(D)); } } } } } } //Double Return return(EK, D); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); EKPolys(G2F); } //////////////////////////////////////////////////////////////////// proc EKPolynomials(list EK, list G) "USAGE: EKPolynomials(EK,G); EK list, G list RETURN: list: p NOTE: At the end I obtain the EK polynomials and their degrees. EXAMPLE: example SpolyEK; shows an example" { jmp u=G[EK[3][1]][EK[3][2]]; jmp q=G[EK[3][3]][EK[3][4]]; return(var(EK[1])*(u.h+u.t)-EK[2]*(q.h+q.t)); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); list EK,D=EKPolys(G2F); EKPolynomials(EK[1],G2F); } //////////////////////////////////////////////////////////////////// proc TestJMark(list G1,def r) "USAGE: TestJMark(G); G list RETURN: int: i NOTE: This procedure performs J-marked basis test.@* The input is a list of J-marked polynomials (jmp) arranged by degree, so G1 is a list of list.@* The output is a boolean evaluation: True=1/False=0 EXAMPLE: example TestJMark; shows an example" {int flag=1; if(size(G1)==1 && size(G1[1])==1) { //Hypersurface print("Only One Polynomial"); flag=1; } else { int d=0; list EK,D=EKPolys(G1); //print("PolysEK"); //I found EK couples int massimo=Max(D); list V1=ConstructorMain(G1,massimo,r); //print("Costruttore"); //print(V1); jmp mi=V1[1][1]; int minimo=Min(deg(mi.h)); intvec u=NewWeight(nvars(r)+1); list L=ringlist(r); L[2]=insert(L[2],"t",size(L[2])); //print(L[2]); list ordlist="a",u; L[3]=insert(L[3],ordlist,0); def H=ring(L); list JJ=list(); jmp pp; jmp qq; int i; int j; list NN; for(i=size(V1);i>0;i--) { NN=list(); for(j=size(V1[i]);j>0;j--) { //print(j); pp=V1[i][j]; NN[j]=list(pp.h,pp.t); } //print(NN); JJ[i]=NN; //print(JJ[i]); //print(i); } //print(JJ); list KK=list(); list UU=list(); //jmp qq; for(i=size(G1);i>0;i--) { for(j=size(G1[i]);j>0;j--) { //print(j); qq=G1[i][j]; UU[j]=list(qq.h,qq.t); } //print(UU); KK[i]=UU; } setring H; //I defined the new ring with the weighted //variable t poly p; //print("anello definito"); def JJJ=imap(r,JJ); def EK=imap(r,EK); //print(flag); //imap(r,D); list V=list(); jmp fp; //int i; //int j; list N; for(i=size(JJJ); i>0; i--) { N=list(); for(j=size(JJJ[i]); j>0; j--) { fp.h=JJJ[i][j][1]; fp.t=JJJ[i][j][2]; N[j]=fp; } V[i]=N; } //print(V); def KKJ=imap(r,KK); list G=list(); list U=list(); for(i=1; i<=size(KKJ); i++) { for(j=1; j<=size(KKJ[i]); j++) { fp.h=KKJ[i][j][1]; fp.t=KKJ[i][j][2]; U[j]=fp; } G[i]=U; } // print(V); //print(G); //I imported in H everithing I need poly q; ideal I; for(j=1; j<=size(EK);j++) { d=D[j]; p=EKPolynomials(EK[j],G); //print("arrivo"); I=IdealOfV(V[d-minimo+1]); attrib(I,"isSB",1); //print(I); q=reduce(t*p,I); //print(I[1]); //print(t*p); q=subst(q,t,1); //I reduce all the EK polynomials // q=RiduzPoly(V[d-minimo+1], p); if(q!=0) { //check whether reduction is 0 print("NOT A BASIS"); flag=0; break; } } } //print(flag); setring r; //typeof(flag); return(flag); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); TestJMark(G2F,r); } singular-4.0.3+ds/Singular/LIB/JMSConst.lib000066400000000000000000000720631266270727000203070ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////// version="version JMSConst.lib 4.0.0.0 Jun_2013 "; // $Id: 5c86effa6bafb0638746722abd113742e7f3c762 $ category="Algebraic Geometry"; // summary description of the library info=" LIBRARY: JMSConst.lib A library for Singular which constructs J-Marked Schemes. AUTHOR: Michela Ceria, email: michela.ceria@unito.it SEE ALSO: JMBTest_lib KEYWORDS: J-marked schemes, Borel ideals OVERVIEW: The library performs the J-marked computation, as described in [BCLR]. As in JMBTest.lib we construct the V polynomials and we reduce the EK polynomials w.r.t. them, putting the coefficients as results. The algorithm terminates only if the ordering is rp. Anyway, the number of reduction steps is bounded. REFERENCES: [CR] Francesca Cioffi, Margherita Roggero,Flat Families by Strongly Stable Ideals and a Generalization of Groebner Bases, J. Symbolic Comput. 46, 1070-1084, (2011).@* [BCLR] Cristina Bertone, Francesca Cioffi, Paolo Lella, Margherita Roggero, Upgraded methods for the effective computation of marked schemes on a strongly stable ideal, Journal of Symbolic Computation (2012), http://dx.doi.org/10.1016/j.jsc.2012.07.006 @* SEE ALSO: JMSConst_lib PROCEDURES: BorelCheck(ideal,r) checks whether the given ideal is Borel JMarkedScheme(list, list, list, int) computes authomatically all the J-marked scheme "; LIB "presolve.lib"; LIB "qhmoduli.lib"; LIB "monomialideal.lib"; //////////////////////////////////////////////////////////////////// proc BorelCheck(ideal Borid,def r) "USAGE: BorelCheck(Borid,r); Borid ideal, r ring RETURN: int: d NOTE: Input must be a monomial ideal. The procedure checks whether the Borel moves produce elements belonging to Borid. EXAMPLE: example QuanteC; shows an example" { int n= nvars(r); int b=1; int i=1; int k; intvec v; int j; int u; //b =bool. b=1 true; b=0 false //we suppose true! //i=counter on the elements of Borid int s= size(Borid); while(b && i<=s) { v=leadexp(Borid[i]); j=1; u=size(v); while(b && j<=u) { if(v[j]!=0) { k=j+1; while(b && k<=n) { b=(reduce(Borid[i]*var(k)/var(j),std(Borid))==0); k++; } } j++; } i++; } return(b); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z),rp; ideal Borid=y^2*z,y*z^2,z^3,y^5; BorelCheck(Borid,r); } //////////////////////////////////////////////////////////////////// proc ArrangeBorel(ideal Borid) "USAGE: ArrangeBorel(Borid); Borid ideal RETURN: list: Input NOTE: Input must be a monomial ideal, increasingly ordered by degree. The procedure groups the monomials in a list of lists as needed to compute J-marked scheme. // It also returns a list containing the size of every sublist generated. EXAMPLE: example ArrangeBorel; shows an example" { list Input; int j=1; //list numero=1; Input[1]=list(Borid[1]); for(int i=2; i<=size(Borid); i++) { if(deg(Borid[i])!=deg(Borid[i-1])) { j++; Input[j]=list(); // numero[j]=0; } Input[j]=insert(Input[j],Borid[i],size(Input[j])); //numero[j]=numero[j]+1; } return(Input); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z),rp; ideal Borid=y^2*z,y*z^2,z^3,y^5; ArrangeBorel(Borid); } //////////////////////////////////////////////////////////////////// proc NumNewVar(list B, list NumN) "USAGE: NumNewVar(B,NumN); B list, NumN list RETURN: int: d NOTE: B is the grouped Borel, while NumN is a list containing the cardinalities of the obtained groups. EXAMPLE: example NumNewVar; shows an example" { int d; int j; int i; for(i=1; i<=size(B); i++) { d=d+size(B[i])*NumN[i]; } return(d); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z),rp; ideal Borid=y^2*z,y*z^2,z^3,y^5; list B= ArrangeBorel(Borid); list NumN=7,8; NumNewVar(B,NumN); } //////////////////////////////////////////////////////////////////// proc NewTails(ideal NI, int s) "USAGE: NewTails(NI,s); NI ideal, s int RETURN: list: M NOTE: The procedure construct the tails of the required unknown J-marked polynomials. EXAMPLE: example NewTails; shows an example" { poly p=0; for(int i=1; i<=size(NI); i++)//Loop on the Groebner escalier { p=p+NI[i]*c(i+s); //multiply by c's } int u=size(NI); list M=p,u; return(M); } example { "EXAMPLE:"; echo = 2; ring r=(0,c(1..7)), (x,y,z),rp; ideal NI=x^2,x*y,y^2,z^2; NewTails(NI,3); } //////////////////////////////////////////////////////////////////// proc ArrangeTails(list Q) "USAGE: ArrangeTails(Q); Q list RETURN: list: Q NOTE: Constructs the final list of J-marked polynomials. EXAMPLE: example FormaInput; shows an example" { jmp m=Q[1][1]; jmp M=Q[size(Q)][1]; int minimo=deg(m.h); int massimo=deg(M.h); //print(minimo); //print(massimo); int i=2; jmp qi; while(i<=size(Q)) { //print("entro nel ciclo"); //print(i); qi=Q[i][1]; if(deg(qi.h)!=minimo+1) { //print("qui riempire"); //print(i); Q=insert(Q,list(),i-1);//Insert empty list for all intermediate degree between the minimum and the maximum, not having polynomials. //print(Q); } minimo=minimo+1; i=i+1; //print("ora ho"); //print(minimo); //print(i); } return(Q); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z),rp; ideal Borid=y^2*z,y*z^2,z^3,y^5; attrib(Borid,"isSB",1); list B=ArrangeBorel(Borid); list NumN; list N; int i; int d; for(i=1;i<=size(B);i++) { d=deg(B[i][1]); N[i]=kbase(Borid,d); NumN[i]=size(N[i]); } int qc=NumNewVar(B, NumN); //Now I must define the NEW RING, putting the c parameters inside. list L=ringlist(r); list L2; L2[1]=L[1]; L2[2]=list(); for(i=qc;i>=1;i--) { L2[2][i]="c("+string(i)+")"; } L2[3]=list(list("rp",qc)); L2[4]=L[4]; L[1]=L2; def K=ring(L); setring(K); ideal Borid=imap(r,Borid); list N=imap(r,N); list B=imap(r,B); //NumN contains only scalars so I do not imap it int j; list Q; int s; list M; jmp pp; for(i=1;i<=size(B);i++) { Q[i]=list(); for(j=1;j<=size(B[i]);j++) { M=NewTails(N[i],s); pp.h=B[i][j]; pp.t=M[1]; Q[i][j]=pp; s=s+M[2]; //print(s); } } list P=ArrangeTails(Q); int ll; int uu; jmp Pp; for(ll=1; ll<=size(P);ll++) { for(uu=1;uu<=size(P[ll]);uu++) {Pp=P[ll][uu]; Pp.h; Pp.t;} } } //////////////////////////////////////////////////////////////////// proc mod_init() "USAGE: mod_init(); RETURN: struct: jmp EXAMPLE: example mod_init; shows an example" { newstruct("jmp", "poly h, poly t"); } example { "EXAMPLE:"; echo = 2; mod_init(); } //////////////////////////////////////////////////////////////////// proc Terns(list G, int c) "USAGE: Terns(G,c); G list, c int RETURN: list: T NOTE: Input is a list of J-marked polynomials (arranged by degree) and an integer. EXAMPLE: example Terns; shows an example" { list T=list(); int z; for(int k=1; k<=size(G[c]);k=k+1) { //Loop on G[c] making positions of polynomials in G[c] z=size(T); T=insert(T,list(1,c,k) ,size(T)); } return(T); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); Terns(G2F, 1); Terns(G2F, 2); } //////////////////////////////////////////////////////////////////// proc VConst(list G, int c) "USAGE: VConst(G, c); G list, c int RETURN: list: V NOTES: this procedure computes the Vm polynomials following the algorithm in [CR],but it only keeps in memory the monomials by which the G's must be multplied and their positions. EXAMPLE: example VConst; shows an example" { jmp f=G[1][1]; int aJ=deg(f.h); // minimal degree of polynomials in G //print(aJ); list V=list(); V[1]=Terns(G,1); // V[1]=G[1] (keeping in memory only [head, position]) //print(c-aJ+1); int i; int j; int m; list OO; jmp p; for(m=2; m<=c-aJ+1; m=m+1) { //print("entro nel form"); if(m>size(G)) {V[m]=list(); //If we have not G[m] we insert a list() //print("vuota prima"); } else {V[m]=Terns(G,m); //print("piena prima"); } for(i=1; imax){max=L[i];} } return(max); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; ideal I=y,x,z; Maximus(I); } //////////////////////////////////////////////////////////////////// proc GPolyMin(jmp P, jmp Q) "USAGE: GPolyMin(P,Q); P jmp, Q jmp RETURN: int: d EXAMPLE: example GPolyMin; shows an example" { int d=1; //-1=lower, 0=equal, 1=higher //At the beginning suppose Q is higher if(deg(P.h)B[1]) { //the ordering MUST be rp //print("Maggiore per Lex"); d=1; } } return(d); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); TernComparer([1,1,1],[x,1,1],G2F); } //////////////////////////////////////////////////////////////////// proc MinimalV(list V, list G) "USAGE: Minimal(V,G); V list, G list RETURN: int: R NOTE: Input=list(terns), G. EXAMPLE: example MinimalV; shows an example" { //Minimal element for a given degree list R=list(); list MIN=V[1]; int h=1; int i; for(i=2; i<=size(V); i++) { //I consider the first as minimum //If I find something smaller I change minimum if(TernComparer(V[i],MIN,G)<=0) { MIN=V[i]; h=i; } } //Return: [minimum,position of the minimum] R=MIN,h; return(R); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); MinimalV(VConst(G2F,4,basering)[1],G2F); } //////////////////////////////////////////////////////////////////// proc OrderV(list V,list G,list R) "USAGE: Ordinare(V,G,R); V list, G list, R list RETURN: list: R NOTE: Input: Vm,G,emptylist EXAMPLE: example Ordinare; shows an example" { //Order V[m] //R will contain results but at the beginning it is empty list M=list(); if(size(V)==1) { R=insert(R,V[1],size(R)); } else { M=MinimalV(V,G); R=insert(R,M[1],size(R)); V=delete(V,M[2]); //recursive call R=OrderV(V,G,R); } return(R); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); OrderV(VConst(G2F,4,r)[1],G2F,list()); } //////////////////////////////////////////////////////////////////// proc StartOrderingV(list V,list G) "USAGE: StartOrderingV(V,G); V list, G list RETURN: list: R NOTE: Input Vm,G. This procedure uses OrderV to get the ordered polynomials as in [BCLR]. EXAMPLE: example StartOrderingV; shows an example" { return(OrderV(V,G, list())); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); StartOrderingV(VConst(G2F,4,basering)[1],G2F); } //////////////////////////////////////////////////////////////////// proc MultiplyJmP(list L, list G) "USAGE: MultiplyJmP(L,G); L list, G list RETURN: jmp: K NOTE: Input: a 3-ple,G. It performs the product associated to the 3-uple. EXAMPLE: example MultiplyJmP; shows an example" { jmp g=G[L[2]][L[3]]; jmp K; K.h=L[1]*g.h; K.t=L[1]*g.t; return(K); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; list P=x^2,1,1; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); MultiplyJmP(P,G2F); } //////////////////////////////////////////////////////////////////// //proc JmpIdeal(list V,r) //"USAGE: JmpIdeal(V); V list //RETURN: ideal: I //NOTES: this procedure takes a list of Vm's of a certain degree //and construct their ideal, multiplying the head by the weighted //variable t. //EXAMPLE: example JmpIdeal; shows an example" //{ //ideal I=0; //int i; //if (size(V)!=0) // { // list M=list(); //jmp g; // for(i=1; i<= size(V); i++) // { // g=V[i]; // g.h=(g.h)*t; // M[i]=g.h+g.t; // } // I=M[1..size(M)]; //attrib(I,"isSB",1); // } //return(I); //} //example //{ "EXAMPLE:"; echo = 2; // ring r=0, (x,y,z,t), rp; //jmp r1; //r1.h=z^3; //r1.t=poly(0); //jmp r2; //r2.h=z^2*y; //r2.t=poly(0); //jmp r3; //r3.h=z*y^2 ; //r3.t=-x^2*y; //jmp r4; //r4.h=y^5; //r4.t=poly(0); //list G2F=list(list(r1,r2,r3),list(r4)); //JmpIdeal(VConst(G2F,6,r)[1],r); //} //////////////////////////////////////////////////////////////////// proc NewWeight(int n) "USAGE: NewWeight(n); n int RETURN: intvec: u EXAMPLE: example NewWeight; shows an example" { intvec u=0; u[n]=1; return(u); } example { "EXAMPLE:"; echo = 2; NewWeight(3); } //////////////////////////////////////////////////////////////////// proc FinalVm(list V1 , list G1 , def r) "USAGE: FinalVm(V1, G1, r); V1 list, G1 list , r RETURN: intvec: u EXAMPLE: example FinalVm; shows an example" { //multiply and reduce, degree by degree intvec u=NewWeight(nvars(r)+1); list L=ringlist(r); L[2]=insert(L[2],"t",size(L[2])); //print(L[2]); list ordlist="a",u; L[3]=insert(L[3],ordlist,0); def H=ring(L); //print(V1); //print(G1); list M=list(); jmp p; list N; poly q; poly s; int i; int j; for(i=1; i<=size(G1); i++) { N=list(); for(j=1; j<=size(G1[i]); j++) { p=G1[i][j]; q=p.h; s=p.t; N[j]=list(q,s); } M[i]=N; } //print("M is"); //print(M); p.h=poly(0); p.t=poly(0); setring H; list R=list(); list S=list(); //print("anello definito"); list V=imap(r,V1); //def G=imap(r,G1); //print(V); list MM=imap(r,M); list G=list(); list N=list(); for(i=1; i<=size(MM); i++) { for(j=1; j<=size(MM[i]); j++) { p.h=MM[i][j][1]; p.t=MM[i][j][2]; N[j]=p; } G[i]=N; } ideal I=0; jmp LL; jmp UU; //print("pronta x ridurre"); for(i=1; i<=size(V);i++) { //print("sono a V di"); //print(i); R[i]=list(); S[i]=list(); I=0; attrib(I,"isSB",1); for(j=1;j<=size(V[i]); j++) { //print(j); //print("esimo elem"); LL=MultiplyJmP(V[i][j],G); LL.t=reduce(t*LL.t,I); //I only reduce the tail //print(LL.t); LL.t=subst(LL.t,t,1); S[i]=insert(S[i],LL,size(S[i])); LL.h=t*LL.h; R[i]=insert(R[i],LL,size(R[i])); UU=R[i][j]; I=I+ideal(UU.h+UU.t); attrib(I,"isSB",1); } } //print("ho ridotto"); list M=list(); poly q; poly s; for(i=1; i<=size(S); i++) { N=list(); for(j=1; j<=size(S[i]); j++) { p=S[i][j]; q=p.h; s=p.t; N[j]=list(q,s); } M[i]=N; } p.h=poly(0); p.t=poly(0); setring r; def MM=imap(H,M); list MMM=list(); for(i=1; i<=size(MM); i++) { N=list(); for(j=1; j<=size(MM[i]); j++) { p.h=MM[i][j][1]; p.t=MM[i][j][2]; N[j]=p; } MMM[i]=N; } return(MMM); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); FinalVm(VConst(G2F,6,r) , G2F, r); } //////////////////////////////////////////////////////////////////// proc VmConstructor(list G, int c,def r) "USAGE: VmConstructor(G,c); G list, c int RETURN: list: R NOTE: At the end separated by degree. EXAMPLE: example VmConstructor; shows an example" { list V=list(); V= VConst(G,c); //print("VConst"); //V non ordered list L=list(); list R=list(); int i; // head, position //order the different degrees for(i=1; i<=size(V); i++) { L[i]=StartOrderingV(V[i], G); } //print("finito ordine"); //multiply and reduce //print("Ordinare"); //R=FinalVm(L, G, r); //print("FinalVm"); return(L); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2 ; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); VmConstructor(G2F,6,r); } //////////////////////////////////////////////////////////////////// proc EKCouples(jmp A, jmp B) "USAGE: CoppiaEK(A,B); A list, B list RETURN: list: L NOTE: At the end the monomials involved by EK. EXAMPLE: example EKCouples; shows an example" { poly E; list L=0,0; string s=varstr(basering); list VVV=varstr(basering); //L will contain results poly h=Minimus(variables(A.h)); //print(h); int l=findvars(h)[2][1]; if(l!=nvars(basering)) { //print("vero"); //print(l); for(int j=l+1;j<=nvars(basering); j++) { //print("entrata"); //print(var(j)); E=var(j)*A.h/B.h; //Candidate for * product //print(E); if(E!=0) { //print("primo if passato"); if(Minimus(variables(B.h))>=Maximus(variables(E))) { //Does it work with * ? //print("secondo if passato"); L[1]=j; L[2]=E; break; } } } } return (L); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp A; A.h=y*z^2; A.t=poly(0); jmp B; B.h=y^2*z; B.t=poly(0); EKCouples(A,B); EKCouples(B,A); } //////////////////////////////////////////////////////////////////// proc EKPolynomials(list G) "USAGE: EKPolynomials(G); G list RETURN: list: EK, list: D NOTE: At the end EK polynomials and their degrees EXAMPLE: example EKPolynomials; shows an example" { list D=list(); list C=list(); list N=0,0; list EK=list(); int i; int j; int k; int l; jmp p; for(i=1; i<=size(G); i++) { for(j=1; j<=size(G[i]); j++) { for(k=1; k<=size(G); k++) { for(l=1; l<=size(G[k]); l++) { if(i!=k||j!=l) { //Loop on polynomials C=EKCouples(G[i][j], G[k][l]); //print("coppia"); if(C[2]!=0) { C=insert(C,list(i,j,k,l),size(C)); EK=insert(EK,C,size(EK)); p=G[k][l]; D=insert(D,deg(C[2]*p.h),size(D)); } } } } } } //Double Return return(EK, D); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); EKPolynomials(G2F); } //////////////////////////////////////////////////////////////////// proc MultEKPolys(list EK, list G) "USAGE: MultEKPolys(G); G list RETURN: list: p NOTE: At the end I obtain the EK polynomials and their degrees. EXAMPLE: example MultEKPolys; shows an example" { jmp u; u=G[EK[3][1]][EK[3][2]]; //print("u"); jmp q; q=G[EK[3][3]][EK[3][4]]; return(var(EK[1])*(u.h+u.t)-EK[2]*(q.h+q.t)); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z), rp; jmp r1; r1.h=z^3; r1.t=poly(0); jmp r2; r2.h=z^2*y; r2.t=poly(0); jmp r3; r3.h=z*y^2; r3.t=-x^2*y; jmp r4; r4.h=y^5; r4.t=poly(0); list G2F=list(list(r1,r2,r3),list(r4)); list EK,D=EKPolynomials(G2F); MultEKPolys(EK[2],G2F); } //////////////////////////////////////////////////////////////////// proc SchemeEq(list W, list EK,list D,list Q,def r) "USAGE: SchemeEq(W,EK,D,Q,r); W list, EK list, D list, Q list, r ring RETURN: int: i NOTE: This procedure performs the reduction of EK-polynomials, obtaining the J-marked scheme. EXAMPLE: example SchemeEq; shows an example" { list Jms=list(); //ideal I; list M=list(); jmp mini; mini=W[1][1]; int minimo=deg(mini.h); //multiply variables poly pd=poly(1); for(int i=1;i<=nvars(r);i++) {pd=pd*var(i);} //CHANGE RING intvec u=NewWeight(nvars(r)+1); list L=ringlist(r); L[2]=insert(L[2],"t",size(L[2])); //print(L[2]); list ordlist="a",u; L[3]=insert(L[3],ordlist,0); def H=ring(L); //list M=list(); jmp pu; list N; poly q; poly s; i=0; int j; for(i=1; i<=size(Q); i++) { N=list(); for(j=1; j<=size(Q[i]); j++) { pu=Q[i][j]; q=pu.h; s=pu.t; N[j]=list(q,s); } M[i]=N; } list O; pu.h=poly(0); pu.t=poly(0); for(i=1; i<=size(W); i++) { N=list(); for(j=1; j<=size(W[i]); j++) { pu=W[i][j]; q=pu.h; s=pu.t; N[j]=list(q,s); } O[i]=N; } pu.h=poly(0); pu.t=poly(0); setring H; list R=list(); list S=list(); //print("anello definito"); def EK=imap(r,EK); def MM=imap(r,M); def OO=imap(r,O); def pd=imap(r,pd); list G=list(); list N=list(); for(i=1; i<=size(MM); i++) { for(j=1; j<=size(MM[i]); j++) { pu.h=MM[i][j][1]; pu.t=MM[i][j][2]; N[j]=pu; } G[i]=N; } list V; for(i=1; i<=size(OO); i++) { for(j=1; j<=size(OO[i]); j++) { pu.h=OO[i][j][1]; pu.t=OO[i][j][2]; N[j]=pu; } V[i]=N; } //print(V); //print(G); matrix C; list COEFF; poly p=0; poly q=0; ideal I; list M; i=0; jmp g; int k; for(j=1; j<=size(EK);j++) { //print("arrivo"); //print(j); p=MultEKPolys(EK[j],G); //ideal I=0; if (size(V[D[j]-minimo+1])!=0) { M=list(); // jmp g; for(i=1; i<= size(V[D[j]-minimo+1]); i++) { g=V[D[j]-minimo+1][i]; g.h=(g.h)*t; M[i]=g.h+g.t; } I=M[1..size(M)]; attrib(I,"isSB",1); //print(I); } //print(I); q=reduce(t*p,I); q=subst(q,t,1); C=coef(q,pd); COEFF=C[2,1..ncols(C)]; for(k=1;k<=size(COEFF);k++) { if(COEFF[k]!=0) { Jms=insert(Jms,COEFF[k],size(Jms));} } } setring r; def Jms=imap(H,Jms); return(Jms); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z),rp; ideal Borid=y^2*z,y*z^2,z^3,y^5; attrib(Borid,"isSB",1); list B=ArrangeBorel(Borid); list NumN; list N; int i; int d; for(i=1;i<=size(B);i++) { d=deg(B[i][1]); N[i]=kbase(Borid,d); NumN[i]=size(N[i]); } int qc=NumNewVar(B, NumN); //Now I must define the NEW RING, //putting the c parameters inside. list L=ringlist(r); list L2; L2[1]=L[1]; L2[2]=list(); for(i=qc;i>=1;i--) { L2[2][i]="c("+string(i)+")"; } L2[3]=list(list("rp",qc)); L2[4]=L[4]; L[1]=L2; if(defined(K)){kill K;} def K=ring(L); export K; setring(K); def Borid=imap(r,Borid); def N=imap(r,N); def B=imap(r,B); //NumN contains only scalars so I do not imap it int j; list Q; int s; list M; jmp pp; for(i=1;i<=size(B);i++) { Q[i]=list(); for(j=1;j<=size(B[i]);j++) { M=NewTails(N[i],s); pp.h=B[i][j]; pp.t=M[1]; Q[i][j]=pp; s=s+M[2]; //print(s); } } list P=ArrangeTails(Q); list EK,D= EKPolynomials(P); int massimo=Max(D); //list V=VConst(P, massimo); //pause(); list V=VmConstructor(P,massimo,r); list W=FinalVm(V,P,K); //print("I V ridotti in ordine sono"); //print(W); list Jms=SchemeEq(W,EK,D,P,K); Jms;} ////////////////////////////////////////////////////////////////////// proc JMarkedScheme(ideal Borid,def r) "USAGE: JMarkedScheme(Borid, r); Borid ideal, r ring RETURN: list: Jms NOTE: This procedure performs automatically the whole construction of the J-marked scheme. EXAMPLE: example JMarkedScheme; shows an example" { list Jms; if(BorelCheck(Borid,r)) { if(size(Borid)==1) { Jms=list();} else{ //print("Input is OK"); attrib(Borid,"isSB",1); list B=ArrangeBorel(Borid); list NumN; list N; int i; int d; for(i=1;i<=size(B);i++) { d=deg(B[i][1]); N[i]=kbase(Borid,d); NumN[i]=size(N[i]); } int qc=NumNewVar(B, NumN); if(qc==0) {Jms=list(0);} else { //Now I must define the NEW RING, //putting the c parameters inside. list L=ringlist(r); list L2; L2[1]=L[1]; L2[2]=list(); for(i=qc;i>=1;i--) { L2[2][i]="c("+string(i)+")"; } L2[3]=list(list("rp",qc)); L2[4]=L[4]; L[1]=L2; if(defined(K)){kill K;} def K=ring(L); export K; setring(K); def Borid=imap(r,Borid); def N=imap(r,N); def B=imap(r,B); //NumN contains only scalars so I do not imap it int j; list Q; int s; list M; jmp pp; for(i=1;i<=size(B);i++) { Q[i]=list(); for(j=1;j<=size(B[i]);j++) { M=NewTails(N[i],s); pp.h=B[i][j]; pp.t=M[1]; Q[i][j]=pp; s=s+M[2]; //print(s); } } list P=ArrangeTails(Q); list EK,D= EKPolynomials(P); int massimo=Max(D); //list V=VConst(P, massimo); //pause(); list V=VmConstructor(P,massimo,r); list W=FinalVm(V,P,K); //print("I V ridotti in ordine sono"); //print(W); //list Jms=SchemeEq(W,EK,D,P,K); keepring K;} } } else { print("WRONG IDEAL IN INPUT"); print("It is NOT BOREL"); } return(Jms); } example { "EXAMPLE:"; echo = 2; ring r=0, (x,y,z),rp; ideal Borid=y^2*z,y*z^2,z^3,y^5; JMarkedScheme(Borid,r); } //////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/KVequiv.lib000066400000000000000000000550071266270727000202400ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version KVequiv.lib 4.0.0.0 Jun_2013 "; // $Id: fb5e49e92a1d4a305d8000f7f8825cab074b942c $ info=" LIBRARY: KVequiv.lib PROCEDURES RELATED TO K_V-EQUIVALENCE AUTHOR: Anne Fruehbis-Krueger, anne@mathematik.uni-kl.de OVERVIEW: Let (V,0) be a complete intersection singularity in (C^p,0) and f_0:(C^n,0) --> (C^p,0) an analytic map germ, which is viewed as a section ov V so that the singularity V_0=f_0^-1(V) is a pullback. K_V equivalence is then given by the group K_V={g | g(C^n x V) (subset) C^n x V} (subset) K, where K is the contact group of Mather. This library provides functionality for computing K_V tangent space, K_V normal space and liftable vector fields. A more detailed introduction to K_V equivalence can e.g. be found in [Damon,J.: On the legacy of free divisors, Amer.J.Math. 120,453-492] PROCEDURES: derlogV(iV); derlog(V(iV)) KVtangent(I,rname,dername,k) K_V tangent space to given singularity KVversal(KVtan,I,rname,idname) K_V versal family KVvermap(KVtan,I) section inducing K_V versal family lft_vf(I,rname,idname) liftable vector fields REMARKS: * monomial ordering should be of type (c,...) * monomial ordering should be local on the original (2) rings SEE ALSO: sing_lib, deform_lib, spcurve_lib "; //////////////////////////////////////////////////////////////////////////// // REQUIRED LIBRARIES //////////////////////////////////////////////////////////////////////////// // first the ones written in Singular LIB "poly.lib"; // then the ones written in C/C++ LIB("loctriv.so"); //////////////////////////////////////////////////////////////////////////// // PROCEDURES //////////////////////////////////////////////////////////////////////////// proc derlogV(ideal iV) "USAGE: @code{derlogV(iV)}; @code{iV} ideal RETURN: matrix whose columns generate derlog(V(iV)), i.e. the module of vector fields on (C^p,0) tangent to V EXAMPLE: @code{example derlogV}; shows an example " { //-------------------------------------------------------------------------- // Compute jacobian matrix of iV and add all iV[i]*gen(j) as extra columns //-------------------------------------------------------------------------- int j; def jiV=jacob(iV); module mmV=jiV; for(int i=1;i<=size(iV);i++) { for(j=1;j<=size(iV);j++) { mmV=mmV,iV[i]*gen(j); } } //-------------------------------------------------------------------------- // The generators of derlog(V) are given by the part of the syzygy matrix // of mmV which deals with the jacobian matrix //-------------------------------------------------------------------------- def smmV=syz(mmV); matrix smaV=matrix(smmV); matrix smV[nvars(basering)][ncols(smaV)]= smaV[1..nvars(basering),1..ncols(smaV)]; return(smV); } example { "EXAMPLE:";echo=2; ring r=0,(a,b,c,d,e,f),ds; ideal i=ad-bc,af-be,cf-de; def dV=derlogV(i); print(dV); } //////////////////////////////////////////////////////////////////////////// proc KVtangent(ideal mapi,string rname,string dername,list #) "USAGE: @code{KVtangent(I,rname,dername[,k])}; @code{I} ideal @code{rname,dername} strings @code{[k]} int RETURN: K_V tangent space to a singularity given as a section of a model singularity NOTE: The model singularity lives in the ring given by rname and its derlog(V) is given by dername in that ring. The section is specified by the generators of mapi. If k is given, the first k variables are used as variables, the remaining ones as parameters EXAMPLE: @code{example KVtangent}; shows an example " { //-------------------------------------------------------------------------- // Sanity Checks //-------------------------------------------------------------------------- if(size(#)==0) { int k=nvars(basering); } else { if(typeof(#[1])=="int") { int k=#[1]; } else { int k=nvars(basering); } } def baser=basering; string teststr="setring " + rname + ";"; execute(teststr); if(nameof(basering)!=rname) { ERROR("rname not name of a ring"); } teststr="string typeder=typeof(" + dername + ");"; execute(teststr); if((typeder!="matrix")&&(typeder!="module")) { ERROR("dername not name of a matrix or module in rname"); } setring(baser); if((k > nvars(basering))||(k < 1)) { ERROR("k should be between 1 and the number of variables"); } //-------------------------------------------------------------------------- // Define the map giving the section and use it for substituting the // variables of the ring rname by the entries of mapi in the matrix // given by dername //-------------------------------------------------------------------------- setring baser; string mapstr="map f0=" + rname + ","; for(int i=1;i1) { if (jj==-1) { ERROR("Your ring contains a variable A(i)!"); } } //--------------------------------------------------------------------------- // Extend our current ring by adjoining the correct number of variables // A(i) for the parameters and copy our objects to this ring //--------------------------------------------------------------------------- def rbas=basering; ring rtemp=0,(A(1..size(kbKVt))),(c,dp); def rpert=rbas + rtemp; setring rpert; def mapi=imap(rbas,mapi); def kbKVt=imap(rbas,kbKVt); matrix mapv[ncols(mapi)][1]=mapi; // I hate the conversion from ideal vector mapV=mapv[1]; // to vector //--------------------------------------------------------------------------- // Build up the map of the perturbed section and apply it to the ideal // idname //--------------------------------------------------------------------------- for(i=1;i<=size(kbKVt);i++) { mapV=mapV+A(i)*kbKVt[i]; } string mapstr="map fpert=" + rname + ","; for(int i=1;i1) { if (jj==-1) { ERROR("Your ring contains a variable A(i)!"); } } //--------------------------------------------------------------------------- // Extend our current ring by adjoining the correct number of variables // A(i) for the parameters and copy our objects to this ring //--------------------------------------------------------------------------- def rbas=basering; ring rtemp=0,(A(1..size(kbKVt))),(c,dp); def rpert=rbas + rtemp; setring rpert; def mapi=imap(rbas,mapi); def kbKVt=imap(rbas,kbKVt); matrix mapv[ncols(mapi)][1]=mapi; vector mapV=mapv[1]; //--------------------------------------------------------------------------- // Build up the map of the perturbed section //--------------------------------------------------------------------------- for(i=1;i<=size(kbKVt);i++) { mapV=mapV+A(i)*kbKVt[i]; } ideal mappert=mapV[1..size(mapV)]; //--------------------------------------------------------------------------- // Return the new ring and the name of an ideal describing the perturbed map //--------------------------------------------------------------------------- export mappert; list retlist=basering,"mappert"; return(retlist); } example { "EXAMPLE:";echo=2; ring ry=0,(a,b,c,d),ds; ideal idy=ab,cd; def dV=derlogV(idy); echo=1; export ry; export dV; export idy; echo=2; ring rx=0,(x,y,z),ds; ideal mi=x-z+2y,x+y-z,y-x-z,x+2z-3y; def M=KVtangent(mi,"ry","dV"); list li=KVvermap(M,mi); def rnew=li[1]; setring rnew; `li[2]`; echo=1; setring ry; kill idy; kill dV; setring rx; kill ry; } ///////////////////////////////////////////////////////////////////////////// proc lft_vf(ideal mapi, string rname, string idname, intvec wv, int b, list #) "USAGE: @code{lft_vf(I,rname,iname,wv,b[,any])} @code{I} ideal @code{wv} intvec @code{b} int @code{rname,iname} strings @code{[any]} def RETURN: list [1]: ring in which objects specified by the strings [2] and [3] live [2]: name of ideal describing the liftable vector fields - computed up to order b in the parameters [3]: name of basis of the K_V-normal space of the original singularity [4]: (if 6th argument is given) ring in which the reduction of the liftable vector fields has taken place. [5]: name of liftable vector fields in ring [4] [6]: name of ideal we are using for reduction of [5] in [4] ASSUME: input is assumed to be quasihomogeneous in the following sense: there are weights for the variables in the current basering such that, after plugging in mapi[i] for the i-th variable of the ring rname in the ideal idname, the resulting expression is quasihomogeneous; wv specifies the weight vector of the ring rname. b is the degree bound up in the perturbation parameters up to which computations are performed. NOTE: the original ring should not contain any variables of name A(i) or e(j) EXAMPLE:@code{example lft_vf;} gives an example " { //--------------------------------------------------------------------------- // Sanity checks //--------------------------------------------------------------------------- def baser=basering; def qid=maxideal(1); string teststr="setring " + rname + ";"; execute(teststr); if(nameof(basering)!=rname) { ERROR("rname not name of a ring"); } def ry=basering; teststr="string typeid=typeof(" + idname + ");"; execute(teststr); if(typeid!="ideal") { ERROR("idname not name of an ideal in rname"); } setring baser; for(int i=1; i<=ncols(mapi); i++) { if(rvar(e(i))) { int jj=-1; break; } } if (defined(jj)>1) { if (jj==-1) { ERROR("Your ring contains a variable e(j)!"); } } setring ry; //--------------------------------------------------------------------------- // first prepare derlog(V) for the model singularity // and set the correct weights //--------------------------------------------------------------------------- def @dV=derlogV(`idname`); export(@dV); setring baser; map maptemp=`rname`,mapi; def tempid=maptemp(`idname`); intvec ivm=qhweight(tempid); string ringstr="ring baserw=" + charstr(baser) + ",(" + varstr(baser) + "),(c,ws(" + string(ivm) + "));"; execute(ringstr); def mapi=imap(baser,mapi); //--------------------------------------------------------------------------- // compute the unperturbed K_V tangent space // and check K_V codimension //--------------------------------------------------------------------------- def KVt=KVtangent(mapi,rname,"@dV",nvars(basering)); def sKVt=std(KVt); if(dim(sKVt)>0) { ERROR("K_V-codimension not finite"); } //--------------------------------------------------------------------------- // Construction of the versal family //--------------------------------------------------------------------------- list lilit=KVvermap(KVt,mapi); def rpert=lilit[1]; setring rpert; def mapipert=`lilit[2]`; def KVt=imap(baserw,KVt); def mapi=imap(baserw,mapi); def KVtpert=KVtangent(mapipert,rname,"@dV",nvars(baser)); //--------------------------------------------------------------------------- // put the unperturbed and the perturbed tangent space into a module // (1st component unperturbed) and run a groebner basis computation // which only considers spolys with non-vanishing first component //--------------------------------------------------------------------------- def rxa=basering; string rchange="ring rexa=" + charstr(basering) + ",(e(1.." + string(ncols(mapi)) + ")," + varstr(basering) + "),(c,ws(" + string((-1)*wv) + "," + string(ivm) + "),dp);"; execute(rchange); def mapi=imap(rxa,mapi); ideal eid=e(1..ncols(mapi)); // for later use def KVt=imap(rxa,KVt); def KVtpert=imap(rxa,KVtpert); intvec iv=1..ncols(mapi); ideal KVti=mod2id(KVt,iv); //---------------------------------------------------------------------------- // small intermezzo (here because we did not have all input any earlier) // get kbase of KVti for later use and determine an // integer l such that m_x^l*(e_1,\dots,e_r) lies in KVt //---------------------------------------------------------------------------- ideal sKVti=std(KVti); ideal lsKVti=lead(sKVti); module tmpmo=id2mod(lsKVti,iv); setring baser; def tmpmo=imap(rexa,tmpmo); attrib(tmpmo,"isSB",1); module kbKVt=kbase(tmpmo); setring rexa; def kbKVt=imap(baser,kbKVt); ideal kbKVti=mod2id(kbKVt,iv); def qid=imap(baser,qid); intvec qiv; for(i=1;i<=ncols(qid);i++) { qiv[rvar(qid[i])]=1; } int counter=1; while(size(reduce(lsKVti,std(jet(lsKVti,i,qiv))))!=0) { counter++; } //---------------------------------------------------------------------------- // end of intermezzo // proceed to the previously announced Groebner basis computation //---------------------------------------------------------------------------- ideal KVtpi=mod2id(KVtpert,iv); export(KVtpi); matrix Eing[2][ncols(KVti)]=KVti,KVtpi; module EinMo=Eing; EinMo=EinMo,eid^2*gen(1),eid^2*gen(2); module Ausg=Loctriv::kstd(EinMo,1); //--------------------------------------------------------------------------- // * collect those elements of Ausg for which the first component is non-zero // into mx and the others into mt // * cut off the first component // * find appropriate weights for the reduction //--------------------------------------------------------------------------- intvec eiv; for(i=1;i<=ncols(eid);i++) { eiv[rvar(eid[i])]=1; } if(size(reduce(var(nvars(basering)),std(eid)))!=0) { eiv[nvars(basering)]=0; } module Aus2=jet(Ausg,1,eiv); Aus2=simplify(Aus2,2); ideal mx; ideal mt; int ordmax,ordmin; int ordtemp; for (i=1;i<=size(Aus2);i++) { if(Aus2[1,i]!=0) { mx=mx,Aus2[2,i]; ordtemp=ord(lead(Aus2[1,i])); if(ordtemp>ordmax) { ordmax=ordtemp; } else { if(ordtemp=0){ return(c);} else{ return(-c);} } //////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/absfact.lib000066400000000000000000000605711266270727000202530ustar00rootroot00000000000000//// version="version absfact.lib 4.0.0.0 Jun_2013 "; // $Id: 16f65d70800ea54737b5628579e58c191cd32a8c $ category="Factorization"; info=" LIBRARY: absfact.lib Absolute factorization for characteristic 0 AUTHORS: Wolfram Decker, decker at math.uni-sb.de Gregoire Lecerf, lecerf at math.uvsq.fr Gerhard Pfister, pfister at mathematik.uni-kl.de Martin Lee, mlee at mathematik.uni-kl.de OVERVIEW: A library for computing the absolute factorization of multivariate polynomials f with coefficients in a field K of characteristic zero. Using Trager's idea, the implemented algorithm computes an absolutely irreducible factor by factorizing over some finite extension field L (which is chosen such that V(f) has a smooth point with coordinates in L). Then a minimal extension field is determined making use of the Rothstein-Trager partial fraction decomposition algorithm. absFactorizeBCG uses the algorithm of Bertone, Cheze and Galligo for bivariate polynomials and similar ideas as above to reduce to this case. REFERENCES: G. Cheze, G. Lecerf: Lifting and recombination techniques for absolute factorization. Journal of Complexity, 23(3):380-420, 2007. C. Bertone, G. Cheze, and A. Galligo: Modular las vegas algorithms for polynomial absolute factorization. J. Symb. Comput., 45(12):1280-1295, December 2010 KEYWORDS: factorization; absolute factorization. SEE ALSO: factorize PROCEDURES: absFactorize(); absolute factorization of poly absFactorizeBCG(); absolute factorization of poly "; //////////////////////////////////////////////////////////////////// static proc partialDegree(poly p, int i) "USAGE: partialDegree(p,i); p poly, i int RETURN: int, the degree of p in the i-th variable " { int n = nvars(basering); intvec tmp; tmp[n] = 0; tmp[i] = 1; return(deg(p,tmp)); } //////////////////////////////////////////////////////////////////// static proc belongTo(string s, list l) "USAGE: belongTo(s,l); s string, l list RETURN: 1 if s belongs to l, 0 otherwise " { string tmp; for(int i = 1; i <= size(l); i++) { tmp = l[i]; if (tmp == s) { return(1); } } return(0); } //////////////////////////////////////////////////////////////////// static proc variableWithSmallestPositiveDegree(poly p) "USAGE: variableWithSmallestPositiveDegree(p); p poly RETURN: int; 0 if p is constant. Otherwise, the index of the variable which has the smallest positive degree in p. " { int n = nvars(basering); int v = 0; int d = deg(p); int d_loc; for(int i = 1; i <= n; i++) { d_loc = partialDegree(p, i); if (d_loc >= 1 and d_loc <= d) { v = i; d = d_loc; } } return(v); } //////////////////////////////////////////////////////////////////// static proc smallestProperSimpleFactor(poly p) "USAGE: smallestProperSimpleFactor(p); p poly RETURN: poly: a proper irreducible simple factor of p of smallest degree. If no such factor exists, 0 is returned. " { list p_facts = factorize(p); int s = size(p_facts[1]); int d = deg(p)+1; poly q = 0; poly f; int e; for(int i = 1; i <= s; i++) { f = p_facts[1][i]; e = deg(f); if (e >= 1 and e < d and p_facts[2][i] == 1) { q = f / leadcoef(f); d = e; } } return(q); } //////////////////////////////////////////////////////////////////// static proc smallestProperFactor(poly p) "USAGE: smallestProperFactor(p); p poly RETURN: poly: a proper irreducible factor of p of smallest degree. If p is constant, 0 is returned. " { list p_facts = factorize(p); int s = size(p_facts[1]); int d = deg(p)+1; poly q = 0; poly f; int e; for(int i = 1; i <= s; i++) { f = p_facts[1][i]; e = deg(f); if (e >= 1 and e < d) { q = f / leadcoef(f); d = e; } } return(q); } //////////////////////////////////////////////////////////////////// static proc extensionContainingSmoothPoint(poly p, int m) "USAGE: extensionContainingSmoothPoint(p,m); p poly, m int RETURN: poly: an irreducible univariate polynomial that defines an algebraic extension of the current ground field that contains a smooth point of the hypersurface defined by p=0. " { int n = nvars(basering) - 1; poly q = 0; int i; list a; for(i=1;i<=n+1;i++){a[i] = 0;} a[m] = var(n+1); // The list a is to be taken with random entries in [-e, e]. // Every 10 * n trial, e is incremented by 1. int e = 1; int nbtrial = 0; map h; while (q == 0) { h = basering, a[1..n+1]; q = smallestProperSimpleFactor(h(p)); for(i = 1; i <= n ; i = i + 1) { if (i != m) { a[i] = random(-e, e); } } nbtrial++; if (nbtrial >= 10 * n) { e = e + 1; nbtrial = 0; } } return(q); } //////////////////////////////////////////////////////////////////// static proc RothsteinTragerResultant(poly g, poly f, int m) "USAGE: RothsteinTragerResultant(g,f,m); g,f poly, m int RETURN: poly NOTE: To be called by the RothsteinTrager procedure only. " { def MPz = basering; int n = nvars(MPz) - 1; int d = partialDegree(f, m); poly df = diff(f, var(m)); list a; int i; for(i=1;i<=n+1;i++){ a[i] = 0; } a[m] = var(m); poly q = 0; int e = 1; int nbtrial = 0; map h; while (q == 0) { h = MPz, a[1..n+1]; q = resultant(h(f), h(df) * var(n+1) - h(g), var(m)); if (deg(q) == d) { return(q/leadcoef(q)); } q = 0; for(i = 1; i <= n ; i++) { if (i != m) { a[i] = random(-e, e); } } nbtrial++; if (nbtrial >= 10 * n) { e++; nbtrial = 0; } } } //////////////////////////////////////////////////////////////////// static proc RothsteinTrager(list g, poly p, int m, int expectedDegQ) "USAGE: RothsteinTrager(g,p,m,d); g list, p poly, m,d int RETURN: list L consisting of two entries of type poly NOTE: the return value is the Rothstein-Trager partial fraction decomposition of the quotient s/p, where s is a generic linear combination of the elements of g. The genericity via d (the expected degree of L[1]). " { def MPz = basering; int n = nvars(MPz) - 1; poly dp = diff(p, var(m)); int r = size(g); list a; int i; for(i=1;i<=r;i++){a[i] = 0;} a[r] = 1; int nbtrial = 0; int e = 1; poly s; poly q; while (1) { s = 0; for(i = 1; i <= r; i++){s = s + a[i] * g[i];} q = RothsteinTragerResultant(s, p, m); q = smallestProperFactor(q); if (deg(q) == expectedDegQ) { // Go into the quotient by q(z)=0 ring MP_z = (0,var(n+1)), (x(1..n)), dp; list lMP_z = ringlist(MP_z); lMP_z[1][4] = ideal(imap(MPz,q)); list tmp = ringlist(MPz)[2]; lMP_z[2] = list(tmp[1..n]); def MPq = ring(lMP_z); setring(MPq); poly f = gcd(imap(MPz, p), par(1) * imap(MPz, dp) - imap(MPz, s)); f = f / leadcoef(f); setring(MPz); return(list(q, imap(MPq, f))); } for(i = 1; i <= r ; i++) { a[i] = random(-e, e); } nbtrial++; if (nbtrial >= 10 * r) { e++; nbtrial = 0; } } } //////////////////////////////////////////////////////////////////// static proc absFactorizeIrreducible(poly p) "USAGE: absFactorizeIrreducible(p); p poly ASSUME: p is an irreducible polynomial that does not depend on the last variable @z of the basering. RETURN: list L of two polynomials: q=L[1] is an irreducible polynomial of minimal degree in @z such that p has an absolute factor over K[@z]/, and f represents such an absolute factor. " { int dblevel = printlevel - voice + 2; dbprint(dblevel,"Entering absfact.lib::absFactorizeIrreducible with ",p); def MPz = basering; int d = deg(p); int n = nvars(MPz) - 1; if (d < 1) { return(list(var(n+1), p)); } int m = variableWithSmallestPositiveDegree(p); // var(m) is now considered as the main variable. poly q = extensionContainingSmoothPoint(p, m); int r = deg(q); if (r == 1) { return(list(var(n+1), p)); } list tmp = ringlist(MPz)[2]; // Go into the quotient by q(z)=0 ring MP_z = (0,var(n+1)), (x(1..n)), dp; list lMP_z = ringlist(MP_z); lMP_z[1][4] = ideal(imap(MPz,q)); lMP_z[2] = list(tmp[1..n]); def MPq = ring(lMP_z); setring(MPq); dbprint(dblevel-1,"Factoring in algebraic extension"); // "Factoring p in the algebraic extension..."; poly p_loc = imap(MPz, p); poly f = smallestProperSimpleFactor(p_loc); int degf = deg(f); if (degf == d) { setring(MPz); return(list(var(n+1), p)); } if (degf * r == d) { setring(MPz); return(list(q, imap(MPq, f))); } dbprint(dblevel-1,"Absolutely irreducible factor found"); dbprint(dblevel,"Minimizing field extension"); // "Need to find a minimal extension"; poly co_f = p_loc / f; poly e = diff(f, var(m)) * co_f; setring(MPz); poly e = imap(MPq, e); list g; int i; for(i = 1; i <= r; i++) { g[i] = subst(e, var(n+1), 0); e = diff(e, var(n+1)); } return(RothsteinTrager(g, p, m, d div degf)); } //////////////////////////////////////////////////////////////////// proc absFactorize(poly p, list #) "USAGE: absFactorize(p [,s]); p poly, s string ASSUME: coefficient field is the field of rational numbers or a transcendental extension thereof RETURN: ring @code{R} which is obtained from the current basering by adding a new parameter (if a string @code{s} is given as a second input, the new parameter gets this string as name). The ring @code{R} comes with a list @code{absolute_factors} with the following entries: @format absolute_factors[1]: ideal (the absolute factors) absolute_factors[2]: intvec (the multiplicities) absolute_factors[3]: ideal (the minimal polynomials) absolute_factors[4]: int (total number of nontriv. absolute factors) @end format The entry @code{absolute_factors[1][1]} is a constant, the entry @code{absolute_factors[3][1]} is the parameter added to the current ring.@* Each of the remaining entries @code{absolute_factors[1][j]} stands for a class of conjugated absolute factors. The corresponding entry @code{absolute_factors[3][j]} is the minimal polynomial of the field extension over which the factor is minimally defined (its degree is the number of conjugates in the class). If the entry @code{absolute_factors[3][j]} coincides with @code{absolute_factors[3][1]}, no field extension was necessary for the @code{j}th (class of) absolute factor(s). NOTE: All factors are presented denominator- and content-free. The constant factor (first entry) is chosen such that the product of all (!) the (denominator- and content-free) absolute factors of @code{p} equals @code{p / absolute_factors[1][1]}. SEE ALSO: factorize, absPrimdecGTZ EXAMPLE: example absFactorize; shows an example " { int dblevel = printlevel - voice + 2; dbprint(dblevel,"Entering absfact.lib::absFactorize with ",p); def MP = basering; int i; if (char(MP) != 0) { ERROR("// absfact.lib::absFactorize is only implemented for "+ "characteristic 0"); } if(minpoly!=0) { ERROR("// absfact.lib::absFactorize is not implemented for algebraic " +"extensions"); } int n = nvars(MP); int pa=npars(MP); list lMP= ringlist(MP); list buflMP= lMP; intvec vv,vk; for(i=1;i<=n;i++){vv[i]=1;} vk=vv,1; //if the basering has parameters, add the parameters to the variables //takes care about coefficients and possible denominators if(pa>0) { poly qh=cleardenom(p); if (p==0) { number cok=0; } else { number cok=leadcoef(p)/leadcoef(qh); } p=qh; string sp; for(i=1;i<=npars(basering);i++) { sp=string(par(i)); sp=sp[2..size(sp)-1]; lMP[2][n+i]=sp; vv=vv,1; } lMP[1]=0; n=n+npars(MP); } // MPz is obtained by adding the new variable @z to MP // ordering is wp(1...1) // All the above subroutines work in MPz string newvar; if(size(#)>0) { if(typeof(#[1])=="string") { newvar=#[1]; } else { newvar = "a"; } } else { newvar = "a"; } if (newvar=="a") { if(belongTo(newvar, lMP[2])||defined(a)){newvar = "b";} if(belongTo(newvar, lMP[2])||defined(b)){newvar = "c";} if(belongTo(newvar, lMP[2])||defined(c)){newvar = "@c";} while(belongTo(newvar, lMP[2])) { newvar = "@" + newvar; } } lMP[2][n+1] = newvar; // new ordering vv=vv,1; list orst; orst[1]=list("wp",vv); orst[2]=list("C",0); lMP[3]=orst; def MPz = ring(lMP); setring(MPz); poly p=imap(MP,p); // special treatment in the homogeneous case, dropping one variable // by substituting the first variable by 1 int ho=homog(p); if(ho) { int dh=deg(p); p=subst(p,var(1),1); int di=deg(p); } list rat_facts = factorize(p); int s = size(rat_facts[1]); list tmpf; // absolute factors intvec tmpm; // respective multiplicities tmpf[1] = list(var(n+1), leadcoef(imap(MP,p))); tmpm[1] = 1; poly tmp; for(i = 2; i <= s; i++) { tmp = rat_facts[1][i]; tmp = tmp / leadcoef(tmp); tmpf[i] = absFactorizeIrreducible(tmp); tmpm[i] = rat_facts[2][i]; } // the homogeneous case, homogenizing the result // the new variable has to have degree 0 // need to change the ring if(ho) { list ll=ringlist(MPz); vv[size(vv)]=0; ll[3][1][2]=vv; def MPhelp=ring(ll); setring(MPhelp); list tmpf=imap(MPz,tmpf); for(i=2;i<=size(tmpf);i++) { tmpf[i][2]=homog(tmpf[i][2],var(1)); } if(dh>di) { tmpf[size(tmpf)+1]=list(var(n+1),var(1)); tmpm[size(tmpm)+1]=dh-di; } setring(MPz); tmpf=imap(MPhelp,tmpf); } // in case of parameters we have to go back to the old ring // taking care about constant factors if(pa) { setring(MP); n=nvars(MP); list lM=ringlist(MP); orst[1]=list("wp",vk); orst[2]=list("C",0); lM[2][n+1] = newvar; lM[3]=orst; def MPout=ring(lM); setring(MPout); list tmpf=imap(MPz,tmpf); number cok=imap(MP,cok); tmpf[1][2]=cok*tmpf[1][2]; } else { def MPout=MPz; } // if we want the output as string if(size(#)>0) { if(typeof(#[1])=="int") { if(#[1]==77) { // undocumented feature for Gerhard's absPrimdecGTZ if (size(tmpf)<2){ list abs_fac = list(var(n+1),poly(1)); } else { list abs_fac=tmpf[2..size(tmpf)]; } abs_fac=abs_fac,newvar; string result = string(abs_fac); setring(MP); return(result); } } } // preparing the output for SINGULAR standard // a list: factors(ideal),multiplicities(intvec),minpolys(ideal), // number of factors in the absolute factorization // the output(except the coefficient) should have no denominators // and no content ideal facts,minpols; intvec mults; int nfacts; number co=1; minpols[1]=tmpf[1][1]; facts[1]=tmpf[1][2]; //the coefficient for(i=2;i<=size(tmpf);i++) { minpols[i]=cleardenom(tmpf[i][1]); facts[i]=cleardenom(tmpf[i][2]); co=co*(leadcoef(tmpf[i][2])/leadcoef(facts[i]))^(deg(minpols[i])*tmpm[i]); } facts[1]=facts[1]*co; for(i=1;i<=size(tmpm);i++) { mults[i]=tmpm[i]; } for(i=2;i<=size(mults);i++) { nfacts=nfacts+mults[i]*deg(minpols[i]); } list absolute_factors=facts,mults,minpols,nfacts; // create ring with extra parameter `newvar` for output: setring(MP); list Lout=ringlist(MP); if(!pa) { list Lpar=list(char(MP),list(newvar),list(list("lp",intvec(1))),ideal(0)); } else { list Lpar=Lout[1]; Lpar[2][size(Lpar[2])+1]=newvar; vv=Lpar[3][1][2]; vv=vv,1; Lpar[3][1][2]=vv; } Lout[1]=Lpar; def MPo=ring(Lout); setring(MPo); list absolute_factors=imap(MPout,absolute_factors); export absolute_factors; setring(MP); dbprint( printlevel-voice+3," // 'absFactorize' created a ring, in which a list absolute_factors (the // absolute factors) is stored. // To access the list of absolute factors, type (if the name S was assigned // to the return value): // setring(S); absolute_factors; "); return(MPo); } example { "EXAMPLE:"; echo = 2; ring R = (0), (x,y), lp; poly p = (-7*x^2 + 2*x*y^2 + 6*x + y^4 + 14*y^2 + 47)*(5x2+y2)^3*(x-y)^4; def S = absFactorize(p) ; setring(S); absolute_factors; } //////////////////////////////////////////////////////////////////////////////// proc absFactorizeBCG(poly p, list #) "USAGE: absFactorizeBCG(p [,s]); p poly, s string ASSUME: coefficient field is the field of rational numbers or a transcendental extension thereof RETURN: ring @code{R} which is obtained from the current basering by adding a new parameter (if a string @code{s} is given as a second input, the new parameter gets this string as name). The ring @code{R} comes with a list @code{absolute_factors} with the following entries: @format absolute_factors[1]: ideal (the absolute factors) absolute_factors[2]: intvec (the multiplicities) absolute_factors[3]: ideal (the minimal polynomials) absolute_factors[4]: int (total number of nontriv. absolute factors) @end format The entry @code{absolute_factors[1][1]} is a constant, the entry @code{absolute_factors[3][1]} is the parameter added to the current ring.@* Each of the remaining entries @code{absolute_factors[1][j]} stands for a class of conjugated absolute factors. The corresponding entry @code{absolute_factors[3][j]} is the minimal polynomial of the field extension over which the factor is minimally defined (its degree is the number of conjugates in the class). If the entry @code{absolute_factors[3][j]} coincides with @code{absolute_factors[3][1]}, no field extension was necessary for the @code{j}th (class of) absolute factor(s). NOTE: All factors are presented denominator- and content-free. The constant factor (first entry) is chosen such that the product of all (!) the (denominator- and content-free) absolute factors of @code{p} equals @code{p / absolute_factors[1][1]}. SEE ALSO: factorize, absPrimdecGTZ, absFactorize EXAMPLE: example absFactorizeBCG; shows an example " { int dblevel = printlevel - voice + 2; dbprint(dblevel,"Entering absfact.lib::absFactorizeBCG with ",p); def MP = basering; int i; if (char(MP) != 0) { ERROR("// absfact.lib::absFactorizeBCG is only implemented for "+ "characteristic 0"); } if(minpoly!=0) { ERROR("// absfact.lib::absFactorizeBCG is not implemented for algebraic " +"extensions"); } int n = nvars(MP); int pa=npars(MP); list lMP= ringlist(MP); intvec vv,vk; for(i=1;i<=n;i++){vv[i]=1;} vk=vv,1; //if the basering has parameters, add the parameters to the variables //takes care about coefficients and possible denominators if(pa>0) { poly qh=cleardenom(p); if (p==0) { number cok=0; } else { number cok=leadcoef(p)/leadcoef(qh); } p=qh; string sp; for(i=1;i<=npars(basering);i++) { sp=string(par(i)); sp=sp[2..size(sp)-1]; lMP[2][n+i]=sp; vv=vv,1; } lMP[1]=0; n=n+npars(MP); } // MPz is obtained by adding the new variable @z to MP // ordering is wp(1...1) // All the above subroutines work in MPz string newvar; if(size(#)>0) { if(typeof(#[1])=="string") { newvar=#[1]; } else { newvar = "a"; } } else { newvar = "a"; } if (newvar=="a") { if(belongTo(newvar, lMP[2])||defined(a)){newvar = "b";} if(belongTo(newvar, lMP[2])||defined(b)){newvar = "c";} if(belongTo(newvar, lMP[2])||defined(c)){newvar = "@c";} while(belongTo(newvar, lMP[2])) { newvar = "@" + newvar; } } // create ring with extra parameter `newvar` for output: setring(MP); list Lout=ringlist(MP); if(!pa) { list Lpar=list(char(MP),list(newvar),list(list("lp",intvec(1))),ideal(0)); } else { list Lpar=Lout[1]; Lpar[2][size(Lpar[2])+1]=newvar; vv=Lpar[3][1][2]; vv=vv,1; Lpar[3][1][2]=vv; } Lout[1]=Lpar; def MPo=ring(Lout); setring(MPo); poly p=imap(MP,p); // special treatment in the homogeneous case, dropping one variable // by substituting the first variable by 1 int ho=homog(p); if(ho) { int dh=deg(p); p=subst(p,var(1),1); int di=deg(p); } list tmpf=system ("absFact", p); // the homogeneous case, homogenizing the result // the new variable has to have degree 0 // need to change the ring if(ho) { list ll=ringlist(MPo); vv[size(vv)]=0; ll[3][1][2]=vv; def MPhelp=ring(ll); setring(MPhelp); list tmpf=imap(MPo,tmpf); for(i=2;i<=size(tmpf[1]);i++) { tmpf[1][i]=homog(tmpf[1][i],var(1)); } if(dh>di) { tmpf[1][size(tmpf[1])+1]=var(1); tmpf[2][size(tmpf[2])+1]=dh-di; tmpf[3][size(tmpf[3])+1]=par(npars(MPo)); tmpf[4]= tmpf[4]+dh-di; } setring(MPo); tmpf=imap(MPhelp,tmpf); } if (pa) { number cok=imap(MP,cok); tmpf[1][1]=cok*tmpf[1][1]; } // if we want the output as string if(size(#)>0) { if(typeof(#[1])=="int") { if(#[1]==77) { // undocumented feature for Gerhard's absPrimdecGTZ if (size(tmpf[1])<2){ list abs_fac = list(var(n+1),poly(1)); } else { list abs_fac= tmpf[3][2]; abs_fac= abs_fac, tmpf[1][2]; for (i= 3; i <= size(tmpf[1]); i++) { abs_fac=abs_fac,tmpf[3][i]; abs_fac=abs_fac,tmpf[1][i]; } } abs_fac=abs_fac,newvar; string result = string(abs_fac); setring(MP); return(result); } } } list absolute_factors= tmpf; export absolute_factors; setring(MP); dbprint( printlevel-voice+3," // 'absFactorizeBCG' created a ring, in which a list absolute_factors (the // absolute factors) is stored. // To access the list of absolute factors, type (if the name S was assigned // to the return value): // setring(S); absolute_factors; "); return(MPo); } example { "EXAMPLE:"; echo = 2; ring R = (0), (x,y), lp; poly p = (-7*x^2 + 2*x*y^2 + 6*x + y^4 + 14*y^2 + 47)*(5x2+y2)^3*(x-y)^4; def S = absFactorizeBCG(p) ; setring(S); absolute_factors; } /* ring r=0,(x,t),dp; poly p=x^4+(t^3-2t^2-2t)*x^3-(t^5-2t^4-t^2-2t-1)*x^2 -(t^6-4t^5+t^4+6t^3+2t^2)*x+(t^6-4t^5+2t^4+4t^3+t^2); def S = absFactorize(p,"s"); setring(S); absolute_factors; ring r1=(0,a,b),(x,y),dp; poly p=(a3-a2b+27ab3-27b4)/(a+b5)*x2+(a2+27b3)*y; def S = absFactorize(p); setring(S); absolute_factors; ring r2=0,(x,y,z,w),dp; poly f=(x2+y2+z2)^2+w4; def S =absFactorize(f); setring(S); absolute_factors; ring r=0,(x),dp; poly p=0; def S = absFactorize(p); setring(S); absolute_factors; ring r=0,(x),dp; poly p=7/11; def S = absFactorize(p); setring(S); absolute_factors; ring r=(0,a,b),(x,y),dp; poly p=0; def S = absFactorize(p); setring(S); absolute_factors; ring r=(0,a,b),(x,y),dp; poly p=(a+1)/b; def S = absFactorize(p); setring(S); absolute_factors; ring r=(0,a,b),(x,y),dp; poly p=(a+1)/b*x; def S = absFactorize(p,"s"); setring(S); absolute_factors; ring r=(0,a,b),(x,y),dp; poly p=(a+1)/b*x + 1; def S = absFactorize(p,"s"); setring(S); absolute_factors; ring r=(0,a,b),(x,y),dp; poly p=(a+1)/b*x + y; def S = absFactorize(p,"s"); setring(S); absolute_factors; ring r=0,(x,t),dp; poly p=x^4+(t^3-2t^2-2t)*x^3-(t^5-2t^4-t^2-2t-1)*x^2 -(t^6-4t^5+t^4+6t^3+2t^2)*x+(t^6-4t^5+2t^4+4t^3+t^2); def S = absFactorize(p,"s"); setring(S); absolute_factors; ring r1=(0,a,b),(x,y),dp; poly p=(a3-a2b+27ab3-27b4)/(a+b5)*x2+(a2+27b3)*y; def S = absFactorize(p); setring(S); absolute_factors; ring r2=0,(x,y,z,w),dp; poly f=(x2+y2+z2)^2+w4; def S =absFactorize(f); setring(S); absolute_factors; ring r3=0,(x,y,z,w),dp; poly f=(x2+y2+z2)^4+w8; def S =absFactorize(f); setring(S); absolute_factors; ring r4=0,(x,y),dp; poly f=y6-(2x2-2x-14)*y4-(4x3+35x2-6x-47)*y2+14x4-12x3-94x2; def S=absFactorize(f); setring(S); absolute_factors; ring R1 = 0, x, dp; def S1 = absFactorize(x4-2); setring(S1); absolute_factors; ring R3 = 0, (x,y), dp; poly f = x2y4+y6+2x3y2+2xy4-7x4+7x2y2+14y4+6x3+6xy2+47x2+47y2; def S3 = absFactorize(f); setring(S3); absolute_factors; ring R4 = 0, (x,y), dp; poly f = y4+2*xy2-7*x2+14*y2+6*x+47; def S4 = absFactorize(f); setring(S4); absolute_factors; */ singular-4.0.3+ds/Singular/LIB/ainvar.lib000066400000000000000000000472151266270727000201300ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version ainvar.lib 4.0.0.0 Jun_2013 "; // $Id: 43bf74d54af86b68f5f318ff2719221f2488449a $ category="Invariant theory"; info=" LIBRARY: ainvar.lib Invariant Rings of the Additive Group AUTHORS: Gerhard Pfister (email: pfister@mathematik.uni-kl.de), Gert-Martin Greuel (email: greuel@mathematik.uni-kl.de) PROCEDURES: invariantRing(m..); compute ring of invariants of (K,+)-action given by m derivate(m,f); derivation of f with respect to the vector field m actionIsProper(m); tests whether action defined by m is proper reduction(p,I); SAGBI reduction of p in the subring generated by I completeReduction(); complete SAGBI reduction localInvar(m,p..); invariant polynomial under m computed from p,... furtherInvar(m..); compute further invariants of m from the given ones sortier(id); sorts generators of id by increasing leading terms "; LIB "inout.lib"; LIB "general.lib"; LIB "algebra.lib"; /////////////////////////////////////////////////////////////////////////////// proc sortier(def id) "USAGE: sortier(id); id ideal/module RETURN: the same ideal/module but with generators ordered by their leading terms, starting with the smallest EXAMPLE: example sortier; shows an example " { if(size(id)==0) {return(id); } intvec i=sortvec(id); int j; if( typeof(id)=="ideal") { ideal m; } if( typeof(id)=="module") { module m; } if( typeof(id)!="ideal" and typeof(id)!="module") { ERROR("input must be of type ideal or module"); } for (j=1;j<=size(i);j++) { m[j] = id[i[j]]; } return(m); } example { "EXAMPLE:"; echo = 2; ring q=0,(x,y,z,u,v,w),dp; ideal i=w,x,z,y,v; sortier(i); } /////////////////////////////////////////////////////////////////////////////// proc derivate (matrix m, def id) "USAGE: derivate(m,id); m matrix, id poly/vector/ideal ASSUME: m is an nx1 matrix, where n = number of variables of the basering RETURN: poly/vector/ideal (same type as input), result of applying the vector field by the matrix m componentwise to id; NOTE: the vector field is m[1,1]*d/dx(1) +...+ m[1,n]*d/dx(n) EXAMPLE: example derivate; shows an example " { execute (typeof(id)+ " j;"); ideal I = ideal(id); matrix mh=matrix(jacob(I))*m; if(typeof(j)=="poly") { j = mh[1,1]; } else { j = mh[1]; } return(j); } example { "EXAMPLE:"; echo = 2; ring q=0,(x,y,z,u,v,w),dp; poly f=2xz-y2; matrix m[6][1] =x,y,0,u,v; derivate(m,f); vector v = [2xz-y2,u6-3]; derivate(m,v); derivate(m,ideal(2xz-y2,u6-3)); } /////////////////////////////////////////////////////////////////////////////// proc actionIsProper(matrix m) "USAGE: actionIsProper(m); m matrix ASSUME: m is a nx1 matrix, where n = number of variables of the basering RETURN: int = 1, if the action defined by m is proper, 0 if not NOTE: m defines a group action which is the exponential of the vector field m[1,1]*d/dx(1) +...+ m[1,n]*d/dx(n) EXAMPLE: example actionIsProper; shows an example " { int i; ideal id=maxideal(1); def bsr=basering; //changes the basering bsr to bsr[@t] execute("ring s="+charstr(basering)+",("+varstr(basering)+",@t),dp;"); poly inv,delta,tee,j; ideal id=imap(bsr,id); matrix @m[size(id)+1][1]; @m=imap(bsr,m),0; int auxv; //computes the exp(@t*m)(var(i)) for all i for(i=1;i<=nvars(basering)-1;i++) { inv=var(i); delta=derivate(@m,inv); j=1; auxv=1; tee=@t; while(delta!=0) { inv=inv+1/j*delta*tee; auxv=auxv+1; j=j*auxv; tee=tee*@t; delta=derivate(@m,delta); } id=id+ideal(inv); } i=inSubring(@t,id)[1]; setring(bsr); return(i); } example { "EXAMPLE:"; echo = 2; ring rf=0,x(1..7),dp; matrix m[7][1]; m[4,1]=x(1)^3; m[5,1]=x(2)^3; m[6,1]=x(3)^3; m[7,1]=(x(1)*x(2)*x(3))^2; actionIsProper(m); ring rd=0,x(1..5),dp; matrix m[5][1]; m[3,1]=x(1); m[4,1]=x(2); m[5,1]=1+x(1)*x(4)^2; actionIsProper(m); } /////////////////////////////////////////////////////////////////////////////// proc reduction(poly p, ideal dom, list #) "USAGE: reduction(p,I[,q,n]); p poly, I ideal, [q monomial, n int (optional)] RETURN: a polynomial equal to p-H(f1,...,fr), in case the leading term LT(p) of p is of the form H(LT(f1),...,LT(fr)) for some polynomial H in r variables over the base field, I=f1,...,fr; if q is given, a maximal power a is computed such that q^a divides p-H(f1,...,fr), and then (p-H(f1,...,fr))/q^a is returned; return p if no H is found if n=1, a different algorithm is chosen which is sometimes faster (default: n=0; q and n can be given (or not) in any order) NOTE: this is a kind of SAGBI reduction in the subalgebra K[f1,...,fr] of the basering EXAMPLE: example reduction; shows an example " { int i,choose; int z=ncols(dom); def bsr=basering; if( size(#) >0 ) { if( typeof(#[1]) == "int") { choose = #[1]; } if( typeof(#[1]) == "poly") { poly q = #[1]; } if( size(#)>1 ) { if( typeof(#[2]) == "poly") { poly q = #[2]; } if( typeof(#[2]) == "int") { choose = #[2]; } } } // -------------------- first algorithm (default) ----------------------- if ( choose == 0 ) { list L = algebra_containment(lead(p),lead(dom),1); if( L[1]==1 ) { // the ring L[2] = char(bsr),(x(1..nvars(bsr)),y(1..z)),(dp(n),dp(m)), // contains polynomial check s.t. LT(p) is of the form check(LT(f1),...,LT(fr)) def s1 = L[2]; map psi = s1,maxideal(1),dom; poly re = p - psi(check); // divide by the maximal power of #[1] if ( defined(q) == voice ) { while ((re!=0) && (re!=#[1]) &&(subst(re,#[1],0)==0)) { re=re/#[1]; } } return(re); } return(p); } // ------------------------- second algorithm --------------------------- else { //----------------- arranges the monomial v for elimination ------------- poly v=product(maxideal(1)); //------------- changes the basering bsr to bsr[@(0),...,@(z)] ---------- execute("ring s="+charstr(basering)+",("+varstr(basering)+",@(0..z)),dp;"); // Ev hier die Reihenfolge der Vars aendern. Dazu muss unten aber entsprechend // geaendert werden: // execute("ring s="+charstr(basering)+",(@(0..z),"+varstr(basering)+"),dp;"); //constructs the leading ideal of dom=(p-@(0),dom[1]-@(1),...,dom[z]-@(z)) ideal dom=imap(bsr,dom); for (i=1;i<=z;i++) { dom[i]=lead(dom[i])-var(nvars(bsr)+i+1); } dom=lead(imap(bsr,p))-@(0),dom; //---------- eliminates the variables of the basering bsr -------------- //i.e. computes dom intersected with K[@(0),...,@(z)] (this is hard) //### hier Variante analog zu algebra_containment einbauen! ideal kern=eliminate(dom,imap(bsr,v)); //--------- test wether @(0)-h(@(1),...,@(z)) is in ker --------------- // for some polynomial h and divide by maximal power of q=#[1] poly h; z=size(kern); for (i=1;i<=z;i++) { h=kern[i]/@(0); if (deg(h)==0) { h=(1/h)*kern[i]; // define the map psi : s ---> bsr defined by @(i) ---> p,dom[i] setring bsr; map psi=s,maxideal(1),p,dom; poly re=psi(h); // divide by the maximal power of #[1] if (size(#)>0) { while ((re!=0) && (re!=#[1]) &&(subst(re,#[1],0)==0)) { re=re/#[1]; } } return(re); } } setring bsr; return(p); } } example { "EXAMPLE:"; echo = 2; ring q=0,(x,y,z,u,v,w),dp; poly p=x2yz-x2v; ideal dom =x-w,u2w+1,yz-v; reduction(p,dom); reduction(p,dom,w); } /////////////////////////////////////////////////////////////////////////////// proc completeReduction(poly p, ideal dom, list #) "USAGE: completeReduction(p,I[,q,n]); p poly, I ideal, [q monomial, n int] RETURN: a polynomial, the SAGBI reduction of the polynomial p with respect to I via the procedure 'reduction' as long as possible if n=1, a different algorithm is chosen which is sometimes faster (default: n=0; q and n can be given (or not) in any order) NOTE: help reduction; shows an explanation of SAGBI reduction EXAMPLE: example completeReduction; shows an example " { poly p1=p; poly p2=reduction(p,dom,#); while (p1!=p2) { p1=p2; p2=reduction(p1,dom,#); } return(p2); } example { "EXAMPLE:"; echo = 2; ring q=0,(x,y,z,u,v,w),dp; poly p=x2yz-x2v; ideal dom =x-w,u2w+1,yz-v; completeReduction(p,dom); completeReduction(p,dom,w); } /////////////////////////////////////////////////////////////////////////////// proc completeReductionnew(poly p, ideal dom, list #) "USAGE: completeReduction(p,I[,q,n]); p poly, I ideal, [q monomial, n int] RETURN: a polynomial, the SAGBI reduction of the polynomial p with I via the procedure 'reduction' as long as possible if n=1, a different algorithm is chosen which is sometimes faster (default: n=0; q and n can be given (or not) in any order) NOTE: help reduction; shows an explanation of SAGBI reduction EXAMPLE: example completeReduction; shows an example " { if(p==0) { return(p); } poly p1=p; poly p2=reduction(p,dom,#); while (p1!=p2) { p1=p2; p2=reduction(p1,dom,#); } poly re=lead(p2)+completeReduction(p2-lead(p2),dom,#); return(re); } /////////////////////////////////////////////////////////////////////////////// proc localInvar(matrix m, poly p, poly q, poly h) "USAGE: localInvar(m,p,q,h); m matrix, p,q,h polynomials ASSUME: m(q) and h are invariant under the vector field m, i.e. m(m(q))=m(h)=0 h must be a ring variable RETURN: a polynomial, the invariant polynomial of the vector field @format m = m[1,1]*d/dx(1) +...+ m[n,1]*d/dx(n) @end format with respect to p,q,h. It is defined as follows: set inv = p if p is invariant, and else set inv = m(q)^N * sum_i=1..N-1{ (-1)^i*(1/i!)*m^i(p)*(q/m(q))^i } where m^N(p) = 0, m^(N-1)(p) != 0; the result is inv divided by h as often as possible EXAMPLE: example localInvar; shows an example " { if ((derivate(m,h) !=0) || (derivate(m,derivate(m,q)) !=0)) { "//the last two polynomials of the input must be invariant functions"; return(q); } int ii,k; for ( k=1; k <= nvars(basering); k++ ) { if (h == var(k)) { ii=1; } } if( ii==0 ) { "// the last argument must be a ring variable"; return(q); } poly inv=p; poly dif= derivate(m,inv); poly a=derivate(m,q); poly sgn=-1; poly coeff=sgn*q; k=1; if (dif==0) { return(inv); } while (dif!=0) { inv=(a*inv)+(coeff*dif); dif=derivate(m,dif); k=k+1; coeff=q*coeff*sgn/k; } while ((inv!=0) && (inv!=h) &&(subst(inv,h,0)==0)) { inv=inv/h; } return(inv); } example { "EXAMPLE:"; echo = 2; ring q=0,(x,y,z),dp; matrix m[3][1]; m[2,1]=x; m[3,1]=y; poly in=localInvar(m,z,y,x); in; } /////////////////////////////////////////////////////////////////////////////// proc furtherInvar(matrix m, ideal id, ideal karl, poly q, list #) "USAGE: furtherInvar(m,id,karl,q); m matrix, id,karl ideals, q poly, n int ASSUME: karl,id,q are invariant under the vector field m, moreover, q must be a variable RETURN: list of two ideals, the first ideal contains further invariants of the vector field @format m = sum m[i,1]*d/dx(i) with respect to id,p,q, @end format i.e. we compute elements in the (invariant) subring generated by id which are divisible by q and divide them by q as often as possible. The second ideal contains all invariants given before. If n=1, a different algorithm is chosen which is sometimes faster (default: n=0) EXAMPLE: example furtherInvar; shows an example " { list ll = q; if ( size(#)>0 ) { ll = ll+list(#[1]); } int i; ideal null,eins; int z=ncols(id); intvec v; def br=basering; ideal su; for (i=1; i<=z; i++) { su[i]=subst(id[i],q,0); } // -- define the map phi : r1 ---> br defined by y(i) ---> id[i](q=0) -- execute ("ring r1="+charstr(basering)+",(y(1..z)),dp;"); setring br; map phi=r1,su; setring r1; // --------------- compute the kernel of phi --------------------------- ideal ker=preimage(br,phi,null); ker=mstd(ker)[2]; // ---- define the map psi : r1 ---> br defined by y(i) ---> id[i] ----- setring br; map psi=r1,id; // ------------------- compute psi(ker(phi)) -------------------------- ideal rel=psi(ker); // divide by maximal power of q, test wether we really obtain invariants for (i=1;i<=size(rel);i++) { while ((rel[i]!=0) && (rel[i]!=q) &&(subst(rel[i],q,0)==0)) { rel[i]=rel[i]/q; if (derivate(m,rel[i])!=0) { "// error in furtherInvar, function not invariant:"; rel[i]; } } rel[i]=simplify(rel[i],1); } // --------------------------------------------------------------------- // test whether some variables occur linearly and then delete the // corresponding invariant function setring r1; int j; for (i=1;i<=size(ker);i=i+1) { for (j=1;j<=z;j++) { if (deg(ker[i]/y(j))==0) { setring br; rel[i]= completeReduction(rel[i],karl,ll); if(rel[i]!=0) { karl[j+1]=rel[i]; rel[i]=0; eins=1; } setring r1; } } } setring br; rel=rel+null; if(size(rel)==0){rel=eins;} list l=rel,karl; return(l); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,u),dp; matrix m[4][1]; m[2,1]=x; m[3,1]=y; m[4,1]=z; ideal id=localInvar(m,z,y,x),localInvar(m,u,y,x); ideal karl=id,x; list in=furtherInvar(m,id,karl,x); in; } /////////////////////////////////////////////////////////////////////////////// proc invariantRing(matrix m, poly p, poly q, int b, list #) "USAGE: invariantRing(m,p,q,b[,r,pa]); m matrix, p,q poly, b,r int, pa string ASSUME: p,q variables with m(p)=q and q invariant under m i.e. if p=x(i) and q=x(j) then m[j,1]=0 and m[i,1]=x(j) RETURN: ideal, containing generators of the ring of invariants of the additive group (K,+) given by the vector field @format m = m[1,1]*d/dx(1) +...+ m[n,1]*d/dx(n). @end format If b>0 the computation stops after all invariants of degree <= b (and at least one of higher degree) are found or when all invariants are computed. If b<=0, the computation continues until all generators of the ring of invariants are computed (should be used only if the ring of invariants is known to be finitely generated, otherwise the algorithm might not stop). If r=1 a different reduction is used which is sometimes faster (default r=0). DISPLAY: if pa is given (any string as 5th or 6th argument), the computation pauses whenever new invariants are found and displays them THEORY: The algorithm for computing the ring of invariants works in char 0 or suffiently large characteristic. (K,+) acts as the exponential of the vector field defined by the matrix m. For background see G.-M. Greuel, G. Pfister, Geometric quotients of unipotent group actions, Proc. London Math. Soc. (3) 67, 75-105 (1993). EXAMPLE: example invariantRing; shows an example " { ideal j; int i,it; list ll=q; int bou=b; if( size(#) >0 ) { if( typeof(#[1]) == "int") { ll=ll+list(#[1]); } if( typeof(#[1]) == "string") { string pau=#[1]; } if( size(#)>1 ) { if( typeof(#[2]) == "string") { string pau=#[2]; } if( typeof(#[2]) == "int") { ll=ll+list(#[2]); } } } int z; ideal karl; ideal k1=1; list k2; //------------------ computation of local invariants ------------------ for (i=1;i<=nvars(basering);i++) { karl=karl+localInvar(m,var(i),p,q); } if( defined(pau) ) { ""; "// local invariants computed:"; ""; karl; ""; pause("// hit return key to continue!"); ""; } //------------------ computation of further invariants ---------------- it=0; while (size(k1)!=0) { // test if the new invariants are already in the ring generated // by the invariants we constructed so far it++; karl=sortier(karl); j=q; for (i=1;i<=size(karl);i++) { j=j + simplify(completeReduction(karl[i],j,ll),1); } karl=j; j[1]=0; j=simplify(j,2); k2=furtherInvar(m,j,karl,q); k1=k2[1]; karl=k2[2]; if(k1[1]!=1) { k1=sortier(k1); z=size(k1); for (i=1;i<=z;i++) { k1[i]= completeReduction(k1[i],karl,ll); if (k1[i]!=0) { karl=karl+simplify(k1[i],1); } } if( defined(pau) == voice) { "// the invariants after",it,"iteration(s):"; ""; karl;""; pause("// hit return key to continue!"); ""; } if( (bou>0) && (size(k1)>0) ) { if( deg(k1[size(k1)])>bou ) { return(karl); } } } } return(karl); } example { "EXAMPLE:"; echo = 2; //Winkelmann: free action but Spec(k[x(1),...,x(5)]) --> Spec(invariant ring) //is not surjective ring rw=0,(x(1..5)),dp; matrix m[5][1]; m[3,1]=x(1); m[4,1]=x(2); m[5,1]=1+x(1)*x(4)+x(2)*x(3); ideal in=invariantRing(m,x(3),x(1),0); //compute full invarint ring in; //Deveney/Finston: The ring of invariants is not finitely generated ring rf=0,(x(1..7)),dp; matrix m[7][1]; m[4,1]=x(1)^3; m[5,1]=x(2)^3; m[6,1]=x(3)^3; m[7,1]=(x(1)*x(2)*x(3))^2; ideal in=invariantRing(m,x(4),x(1),6); //all invariants up to degree 6 in; } /////////////////////////////////////////////////////////////////////////////// /* Further examplex //Deveney/Finston: Proper Ga-action which is not locally trivial //r[x(1),...,x(5)] is not flat over the ring of invariants LIB "invar.lib"; ring rd=0,(x(1..5)),dp; matrix m[5][1]; m[3,1]=x(1); m[4,1]=x(2); m[5,1]=1+x(1)*x(4)^2; ideal in=invariantRing(m,x(3),x(1),0,1); in; actionIsProper(m); //compute the algebraic relations between the invariants int z=size(in); ideal null; ring r1=0,(y(1..z)),dp; setring rd; map phi=r1,in; setring r1; ideal ker=preimage(rd,phi,null); ker; //the discriminant ring r=0,(x(1..2),y(1..2),z,t),dp; poly p=z+(1+x(1)*y(2)^2)*t+x(1)*y(1)*y(2)*t^2+(1/3)*x(1)*y(1)^2*t^3; matrix m[5][5]; m[1,1]=z; m[1,2]=x(1)*y(2)^2+1; m[1,3]=x(1)*y(1)*y(2); m[1,4]=1/3*x(1)*y(1)^2; m[1,5]=0; m[2,1]=0; m[2,2]=z; m[2,3]=x(1)*y(2)^2+1; m[2,4]=x(1)*y(1)*y(2); m[2,5]=1/3*x(1)*y(1)^2; m[3,1]=x(1)*y(2)^2+1; m[3,2]=2*x(1)*y(1)*y(2); m[3,3]=x(1)*y(1)^2; m[3,4]=0; m[3,5]=0; m[4,1]=0; m[4,2]=x(1)*y(2)^2+1; m[4,3]=2*x(1)*y(1)*y(2); m[4,4]=x(1)*y(1)^2; m[4,5]=0; m[5,1]=0; m[5,2]=0; m[5,3]=x(1)*y(2)^2+1; m[5,4]=2*x(1)*y(1)*y(2); m[5,5]=x(1)*y(1)^2; poly disc=9*det(m)/(x(1)^2*y(1)^4); LIB "invar.lib"; matrix n[6][1]; n[2,1]=x(1); n[4,1]=y(1); n[5,1]=1+x(1)*y(2)^2; derivate(n,disc); //x(1)^3*y(2)^6-6*x(1)^2*y(1)*y(2)^3*z+6*x(1)^2*y(2)^4+9*x(1)*y(1)^2*z^2-18*x(1)*y(1)*y(2)*z+9*x(1)*y(2)^2+4 ////////////////////////////////////////////////////////////////////////////// //constructive approach to Weizenboecks theorem int n=5; // int n=6; //limit ring w=32003,(x(1..n)),wp(1..n); // definition of the vector field m=sum m[i]*d/dx(i) matrix m[n][1]; int i; for (i=1;i<=n-1;i=i+1) { m[i+1,1]=x(i); } ideal in=invariantRing(m,x(2),x(1),0,""); in; */ singular-4.0.3+ds/Singular/LIB/aksaka.lib000066400000000000000000000302511266270727000200730ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////////// version="version aksaka.lib 4.0.0.1 Jun_2014 "; // $Id: bc74504c42ff955c330251e3f092f84d4c6c8a0d $ category="Teaching"; info=" LIBRARY: aksaka.lib Procedures for primality testing after Agrawal, Saxena, Kayal AUTHORS: Christoph Mang OVERVIEW: Algorithms for primality testing in polynomial time based on the ideas of Agrawal, Saxena and Kayal. PROCEDURES: fastExpt(a,m,n) a^m for numbers a,m; if a^k>n n+1 is returned log2(n) logarithm to basis 2 of n PerfectPowerTest(n) checks if there are a,b>1, so that a^b=n wurzel(r) square root of number r euler(r) phi-function of Euler coeffmod(f,n) polynomial f modulo number n (coefficients mod n) powerpolyX(q,n,a,r) (polynomial a)^q modulo (poly r,number n) ask(n) ASK-Algorithm; deterministic Primality test "; LIB "crypto.lib"; LIB "ntsolve.lib"; /////////////////////////////////////////////////////////////// // // // FAST (MODULAR) EXPONENTIATION // // // /////////////////////////////////////////////////////////////// proc fastExpt(bigint a,bigint m,bigint n) "USAGE: fastExpt(a,m,n); a, m, n = number; RETURN: the m-th power of a; if a^m>n the procedure returns n+1 NOTE: uses fast exponentiation EXAMPLE:example fastExpt; shows an example " { bigint b,c,d; c=m; b=a; d=1; while(c>=1) { if(b>n) { return(n+1); } if((c mod 2)==1) { d=d*b; if(d>n) { return(n+1); } } b=b^2; c=c div 2; } return(d) } example { "EXAMPLE:"; echo = 2; fastExpt(2,10,1022); } //////////////////////////////////////////////////////////////////////////// proc coeffmod(poly f,bigint n) "USAGE: coeffmod(f,n); ASSUME: poly f depends on at most var(1) of the basering RETURN: poly f modulo number n NOTE: at first the coefficients of the monomials of the polynomial f are determined, then their remainder modulo n is calculated, after that the polynomial 'is put together' again EXAMPLE:example coeffmod; shows an example " { matrix M=coeffs(f,var(1)); //Bestimmung der Polynomkoeffizienten int i=1; poly g; int o=nrows(M); while(i<=o) { g=g+(bigint(leadcoef(M[i,1])) mod n)*var(1)^(i-1) ; // umwandeln der Koeffizienten in bigint, // Berechnung der Reste dieser bigint modulo n, // Polynom mit neuen Koeffizienten wieder zusammensetzen i++; } return(g); } example { "EXAMPLE:"; echo = 2; ring R = 0,x,dp; poly f=2457*x4+52345*x3-98*x2+5; bigint n=3; coeffmod(f,n); } ////////////////////////////////////////////////////////////////////////// proc powerpolyX(bigint q,bigint n,poly a,poly r) "USAGE: powerpolyX(q,n,a,r); RETURN: the q-th power of poly a modulo poly r and number n EXAMPLE:example powerpolyX; shows an example " { ideal I=r; if(q==1){return(coeffmod(reduce(a,I),n));} if((q mod 5)==0){return(coeffmod(reduce(powerpolyX(q div 5,n,a,r)^5,I),n));} if((q mod 4)==0){return(coeffmod(reduce(powerpolyX(q div 4,n,a,r)^4,I),n));} if((q mod 3)==0){return(coeffmod(reduce(powerpolyX(q div 3,n,a,r)^3,I),n));} if((q mod 2)==0){return(coeffmod(reduce(powerpolyX(q div 2,n,a,r)^2,I),n));} return(coeffmod(reduce(a*powerpolyX(q-1,n,a,r),I),n)); } example { "EXAMPLE:"; echo = 2; ring R=0,x,dp; poly a=3*x3-x2+5; poly r=x7-1; bigint q=123; bigint n=5; powerpolyX(q,n,a,r); } /////////////////////////////////////////////////////////////// // // // GENERAL PROCEDURES // // // /////////////////////////////////////////////////////////////// proc log2(bigint xx) "USAGE: log2(x); RETURN: logarithm to basis 2 of x NOTE: calculates the natural logarithm of x with a power-series of the ln, then the basis is changed to 2 EXAMPLE: example log2; shows an example " { ring r=0,@x,dp; number b,c,d,t,l,x; x=number(xx); int k; // log2=logarithmus zur basis 2, // log=natuerlicher logarithmus b=100000000000000000000000000000000000000000000000000; c=141421356237309504880168872420969807856967187537695; // c/b=sqrt(2) d=69314718055994530941723212145817656807550013436026; // d/b=log(2) //bringen x zunaechst zwischen 1/sqrt(2) und sqrt(2), so dass Reihe schnell //konvergiert, berechnen dann Reihe bis 30. Summanden und letztendlich //log2(x)=log(x)/log(2)=(log(x/2^j)+j*log(2))/log(2) fuer grosse x //log2(x)=log(x)/log(2)=(log(x*2^j)-j*log(2))/log(2) fuer kleine x number j=0; if(x<(b/c)) { while(x<(b/c)) { x=x*2; j=j+1; } t=(x-1)/(x+1); k=0; l=0; while(k<30) //fuer x*2^j wird Reihe bis k-tem Summanden berechnet { l=l+2*(t^(2*k+1))/(2*k+1); //l=log(x*2^j) nach k Summanden k=k+1; } return (intPart((l*b/d)-j)); //log2(x)=log(x*2^j)/log(2)-j wird ausgegeben } while(x>(c/b)) { x=x/2; j=j+1; } t=(x-1)/(x+1); k=0; l=0; while(k<30) //fuer x/2^j wird Reihe bis k-tem Summanden berechnet { l=l+2*(t^(2*k+1))/(2*k+1); //l=log(x/2^j) nach k Summanden k=k+1; } return(intPart(((l*b/d)+j))); //hier wird log2(x)=log(x/2^j)/log(2)+j ausgegeben } example { "EXAMPLE:"; echo = 2; log2(1024); } ////////////////////////////////////////////////////////////////////////// proc wurzel(number r) "USAGE: wurzel(r); ASSUME: characteristic of basering is 0, r>=0 RETURN: number, square root of r EXAMPLE:example wurzel; shows an example " { poly f=var(1)^2-r; //Wurzel wird als Nullstelle eines Polys //mit proc nt_solve genaehert def B=basering; ring R=(real,40),var(1),dp; poly g=imap(B,f); list l=nt_solve(g,1.1); number m=leadcoef(l[1][1]); setring B; return(imap(R,m)); } example { "EXAMPLE:"; echo = 2; ring R = 0,x,dp; wurzel(7629412809180100); } ////////////////////////////////////////////////////////////////////////// proc euler(bigint r) "USAGE: euler(r); RETURN: bigint phi(r), where phi is Eulers phi-function NOTE: first r is factorized with proc PollardRho, then phi(r) is calculated with the help of phi(p) of every factor p; EXAMPLE:example euler; shows an example " { list l=PollardRho(r,5000,1); //bestimmen der Primfaktoren von r int k; bigint phi=r; for(k=1;k<=size(l);k++) { phi=phi-phi div l[k]; //berechnen phi(r) mit Hilfe der } //Primfaktoren und Eigenschaften der phi-Fktn return(phi); } example { "EXAMPLE:"; echo = 2; euler(99991); } /////////////////////////////////////////////////////////////// // // // PERFECT POWER TEST // // // /////////////////////////////////////////////////////////////// proc PerfectPowerTest(bigint n) "USAGE: PerfectPowerTest(n); RETURN: 0 if there are numbers a,b>1 with a^b=n; 1 if there are no numbers a,b>1 with a^b=n; if printlevel>=1 and there are a,b>1 with a^b=n, then a,b are printed EXAMPLE:example PerfectPowerTest; shows an example " { bigint a,b,c,e,f,m,l,p; b=2; l=log2(n); e=0; f=1; while(b<=l) { a=1; c=n; while(c-a>=2) { m=(a+c) div 2; p=fastExpt(m,b,n); if(p==n) { if(printlevel>=1){"es existieren Zahlen a,b>1 mit a^b=n"; "a=";m;"b=";b;pause();} return(e); } if(p=1){"es existieren keine Zahlen a,b>1 mit a^b=n";pause();} return(f); } example { "EXAMPLE:"; echo = 2; PerfectPowerTest(887503681); } /////////////////////////////////////////////////////////////// // // // ASK PRIMALITY TEST // // // /////////////////////////////////////////////////////////////// proc ask(bigint n) "USAGE: ask(n); ASSUME: n>1 RETURN: 0 if n is composite; 1 if n is prime; if printlevel>=1, you are informed what the procedure will do or has calculated NOTE: ASK-algorithm; uses proc powerpolyX for step 5 EXAMPLE:example ask; shows an example " { bigint c,p; c=0; p=1; if(n==2) { return(p); } if(printlevel>=1){"Beginn: Test ob a^b=n fuer a,b>1";pause();} if(0==PerfectPowerTest(n)) // Schritt1 des ASK-Alg. { return(c); } if(printlevel>=1) { "Beginn: Berechnung von r, so dass ord(n) in Z/rZ groesser log2(n)^2 "; pause(); } bigint k,M,M2,b; int r; // Zeile 526-542: Schritt 2 M=log2(n); // darin sind die Schritte M2=M^2; // 3 und 4 integriert r=2; if(gcd(n,r)!=1) //falls ggt ungleich eins, Teiler von n gefunden, // Schritt 3 des ASK-Alg. { if(printlevel>=1){"Zahl r gefunden mit r|n";"r=";r;pause();} return(c); } if(r==n-1) // falls diese Bedingung erfuellt ist, ist // ggT(a,n)=1 fuer 0=1){"ggt(r,n)=1 fuer alle 1log2(n)^2 und Schleife //wird nicht mehr ausgefuehrt { if(r==2147483647) { string e="error: r ueberschreitet integer Bereich und darf nicht als Grad eines Polynoms verwendet werden"; return(e); } r=r+1; if(gcd(n,r)!=1) //falls ggt ungleich eins, Teiler von n gefunden, //wird aufgrund von Schritt 3 des ASK-Alg. fuer //jeden Kandidaten r getestet { if(printlevel>=1){"Zahl r gefunden mit r|n";"r=";r;pause();} return(c); } if(r==n-1) //falls diese Bedingung erfuellt ist, //ist n wegen Zeile 571 prim //wird aufgrund von Schritt 4 des ASK-Alg. fuer //jeden Kandidaten r getestet { if(printlevel>=1){"ggt(r,n)=1 fuer alle 1=1) { "Zahl r gefunden, so dass ord(n) in Z/rZ groesser log2(n)^2 "; "r=";r;pause(); } ring @R=0,@x,dp; bigint l=1; // Zeile 603-628: Schritt 5 poly f,g; // Zeile 618 ueberprueft Gleichungen fuer // das jeweilige a g=var(1)^r-1; bigint grenze=intPart(wurzel(euler(r))*M); if(printlevel>=1) {"Beginn: Ueberpruefung ob (x+a)^n kongruent x^n+a mod (x^r-1,n) fuer 0=1){"a=";l;} f=var(1)+l; if(powerpolyX(bigint(n),bigint(n),f,g)!=(var(1)^(int((n mod r)))+l)) { if(printlevel>=1) {"Fuer a=";l;"ist (x+a)^n nicht kongruent x^n+a mod (x^r-1,n)"; pause(); } return(c); } l=l+1; } if(printlevel>=1) {"(x+a)^n kongruent x^n+a mod (x^r-1,n) fuer 0=1) // otherwise the graph consists only of the strict transform { grp[1..omega,1..omega]=gr[1..omega,1..omega]; } // add the points of multiplicity 1 up to weight maxcontact[i] and the strict transform // and connect them for (j=omega+1;j<=maxcontact[i]+1;j++) { // adding the vertex to the graph and adding the total multiplicities if (j<=maxcontact[i]) { grp[j,j]=j; if (j>1) { tm[j]=tm[j-1]+1; mt[j]=1; } else // then there is no previous point in the graph { tm[j]=1; mt[j]=1; } } // connecting the vertex with the previous part of the graph if (j>1) // otherwise there is nothing to connect to { grp[j-1,j]=1; grp[j,j-1]=1; } } gr=grp; // replace the subgraph by the prolonged subgraph } gr[nrows(gr),ncols(gr)]=-i; // give the strict transform in the ith branch weight -i graphs[i]=gr; totmult[i]=tm; multipl[i]=mt; } /////////////////////////////////////////////////////////////////////////////// // Check, if the procedure is called from inside tau_es2. int check_tau; if (size(#)==1) { if (#[1]=="tau") { check_tau=1; } } ///////////////////////////////////////////////////////////////////////////////// // The procedure tau_es2 expects the branches to be ordered according to their // contact during the resolution process. ///////////////////////////////////////////////////////////////////////////////// if ((size(#)==0) or (check_tau==1)) { list SORT; for (i=1;i<=ncols(contact)-2;i++) { SORT=sort_branches(contact,graphs,totmult,multipl,i,ncols(contact)); contact=SORT[1]; graphs=SORT[2]; totmult=SORT[3]; multipl=SORT[4]; } } /////////////////////////////////////////////////////////////////////////////////// /// If the procedure is called from inside tau_es2, the output will be the prolonged /// resolutiongraphs of the branches, their multiplicity sequences and their contact matrix. if (check_tau==1) { return(list(graphs,multipl,contact)); } ///////////////////////////////////////////////////////////////////////////////////// // Sort the branches in such a way, that in the blowing up procedure whenever to branches // C_i and C_j have contact k (i.e. after k steps they are separated) and one of the following // situations occurs: // A) some exceptional divisor E_l (l=i, t!=j one position further). Else do nothing particular. // Then, if ji, then // (C_j,C_t) does NOT have bad contact for t=i+1,...,j-1. For this we consider the 3 cases: // 1) contact(C_t,C_j)=contact(C_i,C_j)=k: E_l stays with C_j in k-th step and C_t and C_j // separate there, so (C_t,C_j) has bad contact // and hence (C_j,C_t) does NOT have bad contact // 2) contact(C_t,C_j)>contact(C_i,C_j)=k: CANNOT HAPPEN - C_i had no bad contact with C_t, // hence E_l did not stay with C_t in the k-th step; // however, E_l stays with C_j there, so C_t and C_j // cannot have a contact higher than k // 3) contact(C_t,C_j)n_j : C_i stays with "less" E's than C_j does (i.e. with none) hence (C_i,C_j) has bad contact. // n_i=n_j=0 : Not possible, since then both would stay with E_k-1. // n_i=n_j=2 : Both separate from E_k-1 as well as from some E_l (ln_j) or ((n_i==1) and (n_j==1) and (connections_i[1]contact[i,maxcp]){maxcp=j;} } kp[i]=maxcp; // the j such that C_i has its maximal contact to C_j k[i]=contact[i,maxcp]; // the maximal contact of C_i with C_1,...,C_i-1 /////////////////////////////////////////////////////////////////////////////////// // Find in the graph of C_1,...,C_i-1 the points p of wgt k and q of wgt k-1 // connected to C_maxcp. // Since non of C_j for j1) { if (gr[k[i],k[i]-1]!=1) { for (j=k[i]+1;j<=ncols(gr);j++) { if(gr[k[i]-1,j]==1) { rgraph[s+j-k[i],q[i]]=1; rgraph[q[i],s+j-k[i]]=1; } } // Cut the connection from p[i] to q[i]. rgraph[p[i],q[i]]=0; rgraph[q[i],p[i]]=0; } } stricttransforms[i+1]=ncols(rgraph); //////////////////////////////////////////////////////////////////////////////// // Adjust the total multiplicities //////////////////////////////////////////////////////////////////////////////// // Add the total multiplicities for the added subgraph to rtm tm=totmult[i]; mt=multipl[i]; if (k[i]=1) { s=stricttransforms[maxcp]+1; // Line in the graph of the start. pt. of the subgraph of C_maxcp. for (j=rgraph[s,s];j<=e;j++) // Adjust the multiplicities. { rtm[s+j-rgraph[s,s],i]=tm[j]; rmt[s+j-rgraph[s,s],i]=mt[j]; } maxcp=kp[maxcp]; // To which subgraph has the subgraph of C_maxcp been glued? e=rgraph[s,s]-1; // What is the highest weight of a pt. that has not yet been assigned its tot.mult.? } e=nrows(rtm); // Number of rows in the matrix of totalmultiplicities. // The total multiplicities of the C_s for s=1,...,i-1 along the exceptional divisors // which are introduced after the strict transform of C_s has separated (i.e. the entries // in rows stricttransform[i]+1,...,stricttransform[i+1]-1 in the s-th column of the matrix // of total multiplicities still have to be calculated. for (s=1;s0) // If it belongs to an exceptional curve. { for (j=1;j<=e;j++) // Calculate the Euler charateristik of the smooth locus of the exc. curve. { if ((gr[i,j]==1) and (i!=j)) { chi=chi-1; } } if (chi!=0) // If the Euler characteristik is not zero, then it gives a factor in the AP. { for (k=1;k<=r;k++) { hilfspoly=hilfspoly*t(k)^tm[i,k]; } hilfspoly=1-hilfspoly; if (chi<0) // ... either in the numerator ... { alexnumerator=alexnumerator * hilfspoly^-chi; } else // ... or in the denominator. { alexdenominator=alexdenominator * hilfspoly^chi; } alexfactor=hilfspoly,-chi; alexfactors[s]=alexfactor; s++; } chi=2; hilfspoly=1; } } // Calculate the Alexander Polynomial. if (ncols(tm)==1) // If we have only one branch, then the numerator has to be multiplied by 1-t. { alexnumerator=alexnumerator*(1-t(1)); alexfactor=1-t(1),1; alexfactors[size(alexfactors)+1]=alexfactor; } poly alexpoly=alexnumerator / alexdenominator; // Calculate the Zeta Function of the Monodromy Operator. poly zeta_monodromy=alexpoly; for (i=1;i<=r;i++) { zeta_monodromy=subst(zeta_monodromy,t(i),t); } export zeta_monodromy; export alexnumerator; export alexdenominator; export alexfactors; export alexpoly; list ALEX=ALEXring; return(ALEX); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y),ls; poly f1=(y2-x3)^2-4x5y-x7; poly f2=y2-x3; poly f3=y3-x2; list ALEX=alexanderpolynomial(f1*f2*f3); def ALEXring=ALEX[1]; setring ALEXring; alexfactors; alexpoly; zeta_monodromy; } proc semigroup (def INPUT) "USAGE: semigroup(INPUT); INPUT poly or list ASSUME: INPUT is either a REDUCED bivariate polynomial defining a plane curve singularity, or the output of @code{hnexpansion(f[,\"ess\"])}, or the list @code{hne} in the ring created by @code{hnexpansion(f[,\"ess\"])}, or the output of @code{develop(f)} resp. of @code{extdevelop(f,n)}, or a list containing the contact matrix and a list of integer vectors with the characteristic exponents of the branches of a plane curve singularity, or an integer vector containing the characteristic exponents of an irreducible plane curve singularity. RETURN: a list with three entries. The first and the second are lists @code{v_1,...,v_s} and @code{w_1,...,w_r} respectively of integer vectors such that the semigroup of the plane curve defined by the INPUT is generated by the vectors @code{v_1,...,v_s,w_1+k*e_1,...,w_r+k*e_r}, where e_i denotes the i-th standard basis vector and k runs through all non-negative integers. The thrid entry is the conductor of the plane curve singularity. Note that r is the number of branches of the plane curve singularity and integer vectors thus have size r. NOTE: If the output is zero this means that the curve has one branch and is regular. In the reducible case the set of generators may not be minimal. @* If you are not sure whether the INPUT polynomial is reduced or not, use @code{squarefree(INPUT)} as input instead. SEE ALSO: resolutiongraph, totalmultiplicities EXAMPLE: example semigroup; shows an example " { //////////////////////////////////////////////////////////////////////////////////////// // Uses the algorithm in [CDG99] A. Campillo, F. Delgado, S.M. Gusein-Zade, On the // generators of the semigroup of a plane curve singularity, // J. London Math. Soc. (2) 60 (1999), 420-430. //////////////////////////////////////////////////////////////////////////////////////// intvec conductor; // conductor of the singularity list charexp; // characteristic exponents of the singularity int i,j; ///////////////////////////////////////////////////////////////////////////////// // Decide, which kind of input we have, and define the contact matrix ///////////////////////////////////////////////////////////////////////////////// // Input: a polynomial defining a plane curve singularity. ////////////////////////////////////////////////////////////////////////////// if (typeof(INPUT)=="poly") { /* poly FFF=squarefree(INPUT); if ( deg(FFF)!=deg(INPUT) ) { dbprint(printlevel-voice+3,"// input polynomial was not reduced"); dbprint(printlevel-voice+3,"// we continue with its reduction"); } list I@N@V=invariants(FFF); */ list I@N@V=invariants(INPUT); } else { /////////////////////////////////////////////////////////////////////////////////// // Input: the vector of characteristic exponents of an irreducible plane curve /////////////////////////////////////////////////////////////////////////////////// if (typeof(INPUT)=="intvec") { // Calculate the semigroup and the conductor directly. conductor[1]=charexp2conductor(INPUT); intvec gener=charexp2generators(INPUT); list genera; for (i=1;i<=size(gener);i++) { genera[i]=gener[i]; } return(list(genera,list(),conductor)); } else { if (typeof(INPUT)=="list") { ///////////////////////////////////////////////////////////////////////////////// // Input: intersection-matrix and characteristic exponents. ////////////////////////////////////////////////////////////////////////////// if (typeof(INPUT[1])=="intmat") { intmat contact=INPUT[1]; charexp=INPUT[2]; int n=ncols(contact); // to know how many branches we have if (n==1) // Only one branch! { return(semigroup(charexp[1])); } intmat intersecmult=charexp2inter(contact,charexp); for(i=1;i<=ncols(contact);i++) { conductor[i]=charexp2conductor(charexp[i]);//list with the characteristic exponents } } else { ///////////////////////////////////////////////////////////////////////////////// // Input: output of hnexpansion or hne in the ring created by hnexpansion ////////////////////////////////////////////////////////////////////////////// if ((typeof(INPUT[1])=="ring") or (typeof(INPUT[1])=="list")) { list I@N@V=invariants(INPUT); } else { //////////////////////////////////////////////////////////////////////////////////// // Input: output of develop or extdevelop -- irreducible plane curve singularity //////////////////////////////////////////////////////////////////////////////////// if (typeof(INPUT[1])=="matrix") { return(semigroup(invariants(INPUT)[1])); } else { ERROR("The input is invalid!"); } } } } else { ERROR("The input is invalid!"); } } } /////////////////////////////////////////////////////////////////////////////////////////////////// // If the input was a poly or an HN-Expansion, then calculate the contact matrix and char.exponents. /////////////////////////////////////////////////////////////////////////////////////////////////// if (defined(I@N@V)) { int n =size(I@N@V)-1;// number of branches // If the singularity is irreducible, then we calculate the semigroup directly. if (n==1) { return(semigroup(I@N@V[1][1])); } // If the singularity is not irreducible, then we go on. intmat contact=I@N@V[size(I@N@V)][1]; // contact matrix intmat intersecmult=I@N@V[size(I@N@V)][2]; // intersection multiplicities for(i=1;i<=n;i++) { conductor[i]=I@N@V[i][5]; charexp[i]=I@N@V[i][1]; } } ///////////////////////////////////////////////////////////////////////////////////// // If we have come so far, the curve is reducible! ///////////////////////////////////////////////////////////////////////////////////// // Compute the conductor of the curve. ///////////////////////////////////////////////////////////////////////////////////// for(i=1;i<=size(conductor);i++) { for(j=1;j<=size(conductor);j++) { conductor[i]=conductor[i]+intersecmult[i,j]; } } ///////////////////////////////////////////////////////////////////////////////////// /// The total multiplicity vectors of the exceptional divisors generate the semigroup, /// however, this system of generators is not minimal. Theorem 2 in [CDG99] leads /// to the following algorithm for minimizing the set of generators. ///////////////////////////////////////////////////////////////////////////////////// list resgr_totmult=totalmultiplicities(list(contact,charexp)); // resolution graph and tot. mult. intmat resgr=resgr_totmult[1]; // resolution graph intmat totmult=resgr_totmult[2]; // total multiplicities list conpts; // ith entry = points to which i is connected and their weights intvec series; // ith entry = row in totmult which corresponds to w_i intvec deadarc; // Star point and the point connected to the star point of a dead arc. list deadarcs; // Saves deadarc for all dead arcs. int stop,ctp,ctpstop; list ordinary_generators, series_generators; // the v_i and the w_i from the description // Find for each branch of the curve all the points in the graph to which it is connected // and save the numbers of the corresponding rows in the graph as well as the weight of the point. for (i=1;i<=ncols(resgr);i++) { conpts[i]=find_connection_points(resgr,i); } ////////////////////////////////////////////////////////////////////////////////// // Check for each point in the graph, whether it contributes to the semigroup. // If it does not contribute to the semigroup, then set the weight of the point // to zero, i.e. resgr[i,i]=0. Note that the vertex 1 always contributes! ////////////////////////////////////////////////////////////////////////////////// // Find first all the points corresponding to the branches and the end points of dead arcs. // The points to which the branch k is connected contributes to w_k. The end points of // dead arcs contribute to the v_i, while the remaining points of the dead arcs are to be removed. j=1; // Counter for dead arcs - the star points of dead arcs have to be saved for future use. for (i=2;i<=ncols(resgr);i++) { // The end points of dead arcs and the end points corresponding to the branches are // recognized by the fact that they are only connected to one other point. if (size(conpts[i][1])==1) // row i in the graph corresponds to an end point { // For an end point corresponding to a branch k the last point E_alpha(k), to which it is // connected, contributes to the generator w_k. if (resgr[i,i]<0) { series[-resgr[i,i]]=conpts[i][1][1]; // Find E_alpha(k), where k=-resgr[i,i] ctp=conpts[i][1][1]; resgr[ctp,ctp]=0; // So E_alph(k) does not contribute to the v_i. } // For an end point of a dead arc the end point contributes, but all the other points // of the dead arc - including the star point = separation pt of the dead arc - do not contribute. if (resgr[i,i]>0) { stop=0; // Stop checks whether the star point of the dead arc has been reached. ctp=conpts[i][1][1]; // The point to which the end point is connected. // Set the weights of all the other points in the dead arc to zero. while ((stop==0) and (ctp!=1)) // If the star point or the vertex 1 has been reached, stop. { deadarc[2]=i; // i might be the point connected to the star point of the dead arc. resgr[ctp,ctp]=0; if (size(conpts[ctp][1])==2) // If ctp was an ordinary vertex, we go on. { deadarc[2]=ctp; // ctp might be the point connectd to the star point of the dead arc. ctp=conpts[ctp][1][2]; // This is the second point (of higher weight) to which ctp is connected. } else // If ctp is the star point, we stop. { deadarc[1]=ctp; // Star point of this dead arc. deadarcs[j]=deadarc; // Save the j-th dead arc. j++; stop=1; } } } } } ////////////////////////////////////////////////////////////////////////////////// // Points (!=1) which are on the geodesics of every branch don't contribute. // (The geodesic of a branch is the shortest connection of the strict transform to 1 in the graph.) stop=0; // Checks whether the points on all geodesics have been found. ctp=1; // Point (=row in resgr) to be considered. int prev_ctp; // Previous point in the graph, to which ctp was connected. int dead_arc_ctp; // If ctp is the star pt of a dead arc, this is the connection pt of ctp in the d.a. int dastarptcheck; // Checks whether a point is a star point of a dead arc. if (size(conpts[1][1])>=2) // The graphs separate already at point 1. { stop=1; } else // The graphs do not separate at point 1. { prev_ctp=1; ctp=conpts[1][1][1]; // Next point to be considered. } // Pass on along the graph until we reach the first point where some branches separate. while (stop==0) { if (size(conpts[ctp][1])==2) // Point ctp is connected to 2 other points, hence is a normal vertex. { resgr[ctp,ctp]=0; // Point ctp is a normal vertex. prev_ctp=ctp; // Save the position of ctp for future use. ctp=conpts[ctp][1][2]; // Next point to which ctp is connected. } if (size(conpts[ctp][1])>3) // More than three points are connected to ctp. { resgr[ctp,ctp]=0; stop=1; // The graphs separate at point ctp. } if (size(conpts[ctp][1])==3) // At ctp a dead arc might depart or some branch(es)! { // If a dead arc departs, then the branches stay together. resgr[ctp,ctp]=0; // Check if a dead arc departs at point ctp (i.e. if ctp is the star point of a dead arc), // then the branches do not separate at ctp. dastarptcheck=0; i=1; while ((i<=size(deadarcs)) and (dastarptcheck==0)) { if (ctp==deadarcs[i][1]) // ctp is the star point of a dead arc. { dastarptcheck=1; dead_arc_ctp=deadarcs[i][2]; // The point in the dead arc to which ctp is connected. } i++; } if (dastarptcheck==0) // ctp is not the star point of a dead arc, hence the graphs separate at ctp. { stop=1; } else { // Set ctp to the point connected to ctp which is not in the dead arc and is not prev_ctp. i=1; ctpstop=0; while ((i<=3) and (ctpstop==0)) { if ((conpts[ctp][1][i]!=prev_ctp) and (conpts[ctp][1][i]!=dead_arc_ctp)) { prev_ctp=ctp; ctp=conpts[ctp][1][i]; ctpstop=1; } i++; } } } } ///////////////////////////////////////////////////////////////////////////////////////////// // Collect the generators v_j by checking which points in the graph still have // a positive weight! These points contribute their total multiplicity vector as // generator v_j. j=1; for (i=1;i<=ncols(resgr);i++) { if (resgr[i,i]>0) { ordinary_generators[j]=intvec(totmult[i,1..ncols(totmult)]); j++; } } // The "exceptional" generators w_i, for which we have to include w_i+ke_i (for all k) // are the total multiplicity vectors of the points saved in series. for (i=1;i<=ncols(totmult);i++) { series_generators[i]=intvec(totmult[series[i],1..ncols(totmult)]); } return(list(ordinary_generators,series_generators,conductor)); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y),ls; // Irreducible Case semigroup((x2-y3)^2-4x5y-x7); // In the irreducible case, invariants() also calculates a minimal set of // generators of the semigroup. invariants((x2-y3)^2-4x5y-x7)[1][2]; // Reducible Case poly f=(y2-x3)*(y2+x3)*(y4-2x3y2-4x5y+x6-x7); semigroup(f); } proc charexp2generators (intvec charexp) "USAGE: charexp2generators(v), v intvec ASSUME: v contains the characteristic exponents of an irreducible plane curve singularity RETURN: intvec, the minimal set of generators of the semigroup of the plane curve singularity SEE ALSO: invariants, resolutiongraph, totalmultiplicities, alexanderpolynomial KEYWORDS: generators; semigroup; characteristic exponents; topological invariants EXAMPLE: example charexp2generators; shows an example" { int end=size(charexp); // If the singularity is smooth! if (end==1) { return(1); } int i,j; intvec gener; intvec GGT; for (i=1;i<=end;i++) { // Calculate the sequence of gcd's of the characteristic exponents. if (i==1) { GGT[1]=charexp[1]; } else { GGT[i]=gcd(GGT[i-1],charexp[i]); } // Calculate the generators. gener[i]=charexp[i]; for (j=2;j<=i-1;j++) { gener[i]=gener[i]+((GGT[j-1]-GGT[j]) div GGT[i-1])*charexp[j]; } } return(gener); } example { "EXAMPLE:"; echo=2; charexp2generators(intvec(28,64,66,77)); } proc charexp2multseq (intvec charexp) "USAGE: charexp2multseq(v), v intvec ASSUME: v contains the characteristic exponents of an irreducible plane curve singularity RETURN: intvec, the multiplicity sequence of the plane curve singularity NOTE: If the curve singularity is smooth, then the multiplicity sequence is empty. This is expressed by returning zero. SEE ALSO: invariants, resolutiongraph, totalmultiplicities, alexanderpolynomial KEYWORDS: characteristic exponents; multiplicity sequence; topological invariants EXAMPLE: example charexp2multseq; shows an example" { int end=size(charexp); // If the singularity is smooth! if (end==1) { return(1); // ERROR: Should be 0, but for the time being, Singular returns 1. } intvec multseq=euclidseq(charexp[2],charexp[1]); for (int i=3;i<=end;i++) { multseq=multseq,euclidseq(charexp[i]-charexp[i-1],multseq[size(multseq)]); } return(multseq); } example { "EXAMPLE:"; echo=2; charexp2multseq(intvec(28,64,66,77)); } proc multseq2charexp(def v) // Procedure written by Fernando. "USAGE: multseq2charexp(v), v intvec ASSUME: The input is an intvec, which contains the mutiplicity sequence of an irreducible plane curve singularity . RETURN: An intvec, which contains the sequence of characteristic exponents of the irreducible plane curve singularity defined by v. EXAMPLE: example multseq2charexp; shows an example. " { /////// Preamble which reduces the input of an intvec to ///////////// /////// the originally assumed input of a list of intvecs ///////////// /////// and tests the input. ///////////// if (typeof(v)=="intvec") { list RESULT=multseq2charexp(list(v)); return(RESULT[1]); } if (typeof(v)!="list") { ERROR("Invalid Input!"); } if (typeof(v)=="list") { int TESTV; for (int III=1;III<=size(v);III++) { if (typeof(v[III])!="intvec") { TESTV=1; } } if (TESTV==1) { ERROR("Invalid Input!"); } } /////////////////////////////////////////////////////////// list L=v; int n =size(L); // /////////////////////////////////////////////////////// // we look the size of each vector intvec mm; for(int j=1;j<=n;j++) { mm[j]=size(L[j]); } // /////////////////////////////////////////////////////// // we define some variables list LL; int temp, temp1,temp2; int ind,r,l,boolean; int old,new; int contador; list EUCLI,EUCLI1; intvec exponent,exponentes1; int new1,old1; int contador1; int a,b,f; //with the for we round each branch. for(int k=1;k<=n;k++) { l=1; old=L[k][l]; //if the vertor has more than one element if(mm[k]<>1) { // /////////////////////////////////////////////////////////////////////////////// // the first step is special because is easy to know the two first characteristic exponents new=L[k][l+1]; contador=1; while(old==new)//we check how many consecutives elements are equal, starting in the first. { contador=contador+1; old=new; new=L[k][contador+1]; } exponent=L[k][l],contador*L[k][l]+L[k][l+contador];// those are the first two characteristic exponents. LL[k]=exponent;// we insert them in the final matrix EUCLI=euclides(LL[k][2],LL[k][1]);// compute the euclides algorithm for the two first characteristic exponents. temp=size(EUCLI[1]); // measure how many elements of the multiplicity sequence belong to the first euclidean algorithm. for(ind=1;ind<=temp;ind=ind+1) { l=l+EUCLI[1][ind]; } l=l-1;//this is the number we are looking for. /////////////////////////////////////////////////////////////// r=1; //repeat the same process until the end of the multiplicity sequence. if(mm[k]-1>l) { while( l0) { q=a div b; r=a mod b; for (i=1;i<=q;i++) { multseq[s+i]=b; } s=s+q; // size of multseq a=b; b=r; } return(multseq); } static proc puiseuxchainpart (int piij, int muij, intvec multpl, int initial_tm, int end_tm, int j) "USAGE: puiseuxchainpart(piij,muiij,multpl,initial_tm,end_tm,j); RETURN: list L, L[1] incidence matrix of a part of the Puiseux chain, L[2] the total multiplicities of this part of the Puiseux chain. NOTE: This procedure is only for internal use; it is called by puiseuxchain. " { int delta=1; if (j==1){delta=0;} // Delta measures whether j is 1 or not. intvec totalmultiplicity; // Keeps the total multiplicities. intmat pcp[muij][muij]; // Keeps the incidence matrix of the Puiseuxchainpart S_i,j. // Calculate the total multiplicities and the Puiseuxchainpart S_i,j. totalmultiplicity[1]=initial_tm+end_tm+multpl[1]; pcp[1,1]=piij+1; for (int k=2;k<=muij;k++) { pcp[k,k]=piij+k; pcp[k-1,k]=1; pcp[k,k-1]=1; totalmultiplicity[k]=totalmultiplicity[k-1]+delta*initial_tm+multpl[k]; } list result=pcp,totalmultiplicity; return(result); } static proc puiseuxchain (int initial, intvec divseq, intvec multpl, int initial_tm) "USAGE: puiseuxchain(initial,divseq,multpl,initial_tm); int initial, initial_tm, intvec divseq, multpl RETURN: list L, L[1] incidence matrix of a Puiseux chain, L[2] the weight of the point to which the previous Puiseux chain has to be connected, L[3] the sequence of total multiplicities of the points in this Puiseux chain. NOTE: This procedure is only for internal use; it is called by irred_resgraph_totmult. " { int j,k,l,connectpoint; intvec multpli; int pc_tm=initial_tm; // Keeps the total multipl. of the endpoint of P_i-1. int end_tm=0; int start=1; int omega=size(divseq); // Keep the endpoints of the puiseuxchainparts (minus initial) s_i,j in divseq_sum. intvec divseq_sum=divseq[1]; for (j=2;j<=omega;j++) { divseq_sum[j]=divseq_sum[j-1]+divseq[j]; } // Define the connecting point of the Puiseuxchain P_i-1 with P_i. if (divseq[1]==0) { // If divseq[1]=mu_i,1=0, then the Puiseuxchainpart S_i,1 is empty. // We may start building the Puiseuxchain with part 2, i.e. set start=2. start=2; if (omega>=3) { connectpoint=initial+divseq_sum[2]+1; // startpoint of s_i+1,3 } else { connectpoint=initial+divseq_sum[2]; // endpoint of s_i+1,2 } } else { connectpoint=initial+1; } // Build the Puiseuxchainparts s_i,j and put them as blocks into pc=P_i. multpli=multpl[initial+1..initial+divseq_sum[start]]; list pcp=puiseuxchainpart(initial,divseq[start],multpli,initial_tm,end_tm,start); intmat pc=pcp[1]; intvec tm=pcp[2]; for (j=start+1;j<=omega;j++) { // Keep the final total multipl. of the puiseuxchainpart S_i,j-2 resp. P_i-1, if S_i,1 empty. if (j>2){end_tm=initial_tm;} // Calculate the endpoint of S_i,j-1. initial=initial+divseq[j-1]; // Keep the total multiplicity of the endpoint of S_i,j-1 initial_tm=pcp[2][size(pcp[2])]; // Build the new puiseuxchainpart S_i,j multpli=multpl[initial+1..initial+divseq[j]]; pcp=puiseuxchainpart(initial,divseq[j],multpli,initial_tm,end_tm,j); pc=addmat(pc,pcp[1]); tm=tm,pcp[2]; } // Connect the Puiseuxchainparts s_i,j. for (j=start;j<=omega-2;j++) { k=divseq_sum[j]; // endpoint of s_i,j l=divseq_sum[j+1]+1; // startpoint of s_i,j+2 pc[k,l]=1; // connecting these pc[l,k]=1; } if (omega>=start+1) // If there are at least two non-empty s_i,j. { k=divseq_sum[omega-1]; // endpoint of s_i,omega-1 l=divseq_sum[omega]; // endpoint of s_i,omega pc[k,l]=1; // connecting these pc[l,k]=1; } list ergebnis=pc,connectpoint,tm; return(ergebnis); } static proc irred_resgraph_totmult (intvec charexp) "USAGE: irred_resgraph_totmult(charexp); charexp intvec ASSUME: charexp is an integer vector containg the characteristic exponents of an irreducible plane curve singularity RETURN: list L, L[1] is the incidence matrix of the resolution graph of the plane curve singularity defined by INPUT, and L[2] is its sequence of total multiplicities NOTE: This procedure is only for internal use; it is called by resgraph. " { int k,l; intvec multpl=charexp2multseq(charexp); // multiplicity sequence of the singularity // Do first the case where the singularity is actually smooth. if (size(charexp)==1) { intmat resgraph[1][1]=0; intvec tm=1; // there is no exceptional divisor in the resolution - ERROR: should be 0, // but for the time being, Singular returns 1 as multiplicity of smooth curves list result=resgraph,tm,multpl; return(result); } // End of the smooth case int initial_tm=0; // total multipl. of the endpoint of Puiseux chain P_i-1 int g=size(charexp); list es=divsequence(charexp[2],charexp[1]); // keeps the lengths of the Puiseuxchainparts s_i,j intvec divseq=es[1]; int r=es[2]; int initial=0; // Build the Puiseuxchains P_i and put them as blocks into a matrix. list pc=puiseuxchain(initial,divseq,multpl,initial_tm); intmat resgraph=pc[1]; intvec endpoints=resgraph[nrows(resgraph),ncols(resgraph)]; intvec connectpoints=pc[2]; intvec tm=pc[3]; for (int i=3;i<=g;i++) { initial_tm=tm[size(tm)]; es=divsequence(charexp[i]-charexp[i-1],r); divseq=es[1]; r=es[2]; initial=endpoints[size(endpoints)]; pc=puiseuxchain(initial,divseq,multpl,initial_tm); resgraph=addmat(resgraph,pc[1]); endpoints=endpoints,resgraph[nrows(resgraph),ncols(resgraph)]; connectpoints=connectpoints,pc[2]; tm=tm,pc[3]; } // Adding the * for the strict transform to the Graph. resgraph=addmat(resgraph,0); // The connecting point of the * with the graph. connectpoints=connectpoints,nrows(resgraph); // Connect the P_i with each other and with *. for (i=2;i<=g;i++) { k=endpoints[i-1]; // endpoint of P_i-1 l=connectpoints[i]; // conncting point of P_i resp. of * resgraph[k,l]=1; // connecting these resgraph[l,k]=1; } list result=resgraph,tm,multpl; //HIER GEAENDERT!!!! return(result); } static proc max_in_intvec (intvec v, list #) "USAGE: max_in_intvec(v); v intvec RETURN: int m, maximum of the integers in v USAGE: max_in_intvec(v,1); v intvec RETURN: intvec m, m[1] maximum of the integers in v, m[2] position of the last occurence of the maximum in v NOTE: This procedure is only for internal use; this procedure is called by totalmultiplicities and semigroup. " { int max=v[1]; int maxpos=1; for (int i=2;i<=size(v);i++) { if (v[i]>max) { max=v[i]; maxpos=i; } } if (size(#)==0) { return(max); } else { return(intvec(max,maxpos)); } } static proc addmat (intmat A,intmat B) "USAGE: max_in_intvec(A,B); A, B integer matrices RETURN: intmat C, block matrix with left-upper block A, right-lower block B NOTE: This procedure is only for internal use; this procedure is called several times. " { int nc=ncols(A); int nr=nrows(A); int mc=ncols(B); int mr=nrows(B); int i,j; intmat AB[nr+mr][nc+mc]; for (i=1;i<=nr;i++) { for (j=1;j<=nc;j++) { AB[i,j]=A[i,j]; } } for (i=1;i<=mr;i++) { for (j=1;j<=mc;j++) { AB[i+nr,j+nc]=B[i,j]; } } return(AB); } static proc divsequence(int a,int b) "USAGE: divsequence(a,b); a,b integers RETURN: list l, l[1] the multiplicities of the divisors in the Euclidean algorithm and l[2] the last non-zero remainder in the Euclidean algorithm NOTE: This procedure is only for internal use; it is called in irred_res_graph. " { int q=a div b; int r=a mod b; intvec divseq=q; while(r<>0) { a=b; b=r; q=a div b; r=a mod b; divseq = divseq,q; } list result=divseq,b; return(result); } static proc adjust_tot_mult (intvec rtm_fix, intvec rtm_var, intvec rmt_fix, intvec rmt_var, def p, def q, def stricttransforms, int k) "USAGE: adjust_tot_mult(v1,v2,v3,v4,p,q,st,k); v1,...,st intvecs and k an integer RETURN: intvec rtm_var, adjusted total multiplicities NOTE: This procedure is only for internal use; it is called in totalmultiplicities. " { int j,l,store; // Help variables. // Recalculate the entries in rtm_var from stricttransforms[k]+1,...,stricttransforms[k+1]-1. for (j=stricttransforms[k]+1;j0) { if (j==stricttransforms[k]+1) // V is p[k] (to which the subgraph was glued) and W is q[k], the { // vertex of weight one less, to which p[k] is connected. rtm_var[j]=rtm_var[p[k]]+rtm_var[q[k]]; // In this case the subgraph separates p[k] and q[k]! } if (j==stricttransforms[k]+2) // V belongs to the subgraph (it is the vertex considerd in the { // previous case!), and W is p[k] or q[k]. In this case the subgraph separates p[k] and q[k]. if (store==rtm_fix[p[k]]) // If W=p[k], ... { rtm_var[j]=rtm_var[j-1]+rtm_var[p[k]]; } else // else W=q[k] ... . { rtm_var[j]=rtm_var[j-1]+rtm_var[q[k]]; // separates p[k] and q[k]. } } if (j>stricttransforms[k]+2) // V belongs to the subgraph and W either does as well or is p[k]. { l=j-2; while (storestricttransforms[k]+1) // If l-1 belongs to the graph, then reduce l. { l=l-1; } else // If l-1 is stricttransform[k], hence isn't in the graph, then reducing l gives p[k]. { // If l=p[k] and still storek, such that v[i]=1, or 0 if no such i exists. NOTE: This procedure is only for internal use; it is called in totalmultiplicities. " { for (int i=size(v)-1;i>=k+1;i--) { if (v[i]==1) { return(i); } } return(0); } static proc find_connection_points (intmat resgr, int k) "USAGE: find_connection_points(resgr,k); where resgr is an intmat, and k is an integer RETURN: list of two intvecs ctps and ctpswts, where ctps contains all integers i!=k, such that resgr[k,i]=1, and ctpswts contains for each such i the weight resgr[i,i]. NOTE: This procedure is only for internal use; it is called in totalmultiplicities. " { intvec ctps; intvec ctpswts; int j=1; for (int i=1;i<=ncols(resgr);i++) { if ((resgr[k,i]==1) and (i!=k)) { ctps[j]=i; ctpswts[j]=resgr[i,i]; j++; } } return(list(ctps,ctpswts)); } static proc find_lower_connection_points (intmat resgr, int k) "USAGE: find_lower_connection_points(resgr,k); where resgr is an intmat, and k is an integer ASSUME: resgr is the resolutiongraph of an IRREDUCIBLE curve singularity and k0)) { lower_ctps[i]=ctps[i]; i++; } return(lower_ctps); } static proc euclides(int a,int b) // Procedure of Fernando. "USAGE: euclides(m,n);where m,n are integers. RETURN: The divisor, the quotients and the remainders of the euclidean algorithm performing for m and n. NOTE: This procedure is only for internal use; it is called in multseq2charexp. " { int c=a div b;//we compute in c the integer division between a and b. int r=a mod b;//in r the remainer of the division between a and b intvec dividendo=c;// we define the intvec of the dividens and we initialize it to c intvec remain=r;// we define the intvec of the remainders and we initialize it to r a=b;//change a to b b=r;// and b to r while(r<>0)// while the current remainder is diferent to 0 we make the same af before { c=a div b; r=a mod b; dividendo =dividendo,c; if(r<>0) { remain=remain,r; } a=b; b=r; } list L=dividendo,remain;//we put in a list all the dividens and all the remainders return(L);// and return the list } static proc tau_es_qh (poly f) "USAGE: tau_es_qh(f), poly f RETURN: int, equisingular Tjurina number NOTE: This procedure is only for internal use; it is called in Tau_es. " { intvec qh=qhweight(f); if (qh[1]==0) { ERROR("Input is not quasi-homogenous."); } else { int d_f = deg(f,qh); list Tj=Tjurina(f,1); ideal tj=Tj[2]; int Taues=size(tj); for (int i=1;i<=size(tj);i++) { if (deg(tj[i],qh)>=d_f) { Taues--; } } } return(Taues); } static proc move_row (intmat M, int i,int j) "USAGE: move_row(M,i,j), intmat M, int i,j RETURN: intmat, the matrix M with j-th row now i-th row and the remaining rows moved accordingly. NOTE: This procedure is only for internal use; it is called in move_row_col. " { if ((i>nrows(M)) or (j>nrows(M))) { ERROR("The matrix has not enough rows."); } if (i==j) { return(M); } if (i>1) { intmat N[nrows(M)+1][ncols(M)]=intvec(M[1..i-1,1..ncols(M)]),intvec(M[j,1..ncols(M)]),intvec(M[i..nrows(M),1..ncols(M)]); } if (i==1) { intmat N[nrows(M)+1][ncols(M)]=intvec(M[j,1..ncols(M)]),intvec(M[i..nrows(M),1..ncols(M)]); } if (ij) { N=delete_row(N,j); } return(N); } static proc move_col (intmat M, int i,int j) "USAGE: move_col(M,i,j), intmat M, int i,j RETURN: intmat, the matrix M with j-th column now i-th column and the remaining columns moved accordingly. NOTE: This procedure is only for internal use; it is called in move_row_col. " { return(transpose(move_row(transpose(M),i,j))); } static proc move_row_col (intmat M,int i,int j) "USAGE: move_row(M,i,j), intmat M, int i,j RETURN: intmat, the matrix M with j-th row/column now i-th row/column and the remaining rows and columns moved accordingly. NOTE: This procedure is only for internal use; it is called in totalmultiplicities. " { return(move_col(move_row(M,i,j),i,j)); } static proc delete_row (intmat M,int i) "USAGE: delete_row(M,i); M intmat, i int RETURN: intmat, which is derived from M by removing the ith row NOTE: This procedure is only for internal use; it is called in move_row and tau_es2. " { if ((i!=1) and (i!=nrows(M))) { return(intmat(intvec(M[1..i-1,1..ncols(M)],M[i+1..nrows(M),1..ncols(M)]),nrows(M)-1,ncols(M))); } if (i==1) { return(intmat(intvec(M[2..nrows(M),1..ncols(M)]),nrows(M)-1,ncols(M))); } else { return(intmat(intvec(M[1..nrows(M)-1,1..ncols(M)]),nrows(M)-1,ncols(M))); } } static proc delete_col (intmat M, int i) "USAGE: delete_col(M,i); M intmat, i int RETURN: intmat, which is derived from M by removing the ith column NOTE: This procedure is only for internal use; it is called in tau_es. " { return(transpose(delete_row(transpose(M),i))); } static proc sort_branches (intmat contact, list graphs, list totmult, list multpl, int k,int l) "USAGE: sort_branches(K,L,M,N,k,l); K intmat, L,M,N lists, k,l integers ASSUME: K = contact matrix of the branches of a curve, L = their resolutiongraphs, M = their totalmultiplicities, N = their multiplicities RETURN: list LL, LL[1] transformed K, LL[2..4] transformed L,M,N. The procedure sorts the branches from k+1 to l according to descending contact with with the branch k. NOTE: This procedure is only for internal use; it is called in totalmultiplicities. " { intvec max; for (int i=k+1;i<=l;i++) { // Find the last graph max between i and l which has maximal contact with k. max=max_in_intvec(intvec(contact[k,i..l]),1); max[2]=max[2]+i-1; if (i!=max[2]) // If max is not i, then move max to position i! { graphs=insert(graphs,graphs[max[2]],i-1); graphs=delete(graphs,max[2]+1); totmult=insert(totmult,totmult[max[2]],i-1); totmult=delete(totmult,max[2]+1); multpl=insert(multpl,multpl[max[2]],i-1); multpl=delete(multpl,max[2]+1); contact=move_row_col(contact,i,max[2]); } } return(list(contact,graphs,totmult,multpl)); } static proc find_last_non_one (intvec v,int k) "USAGE: find_last_non_one (v,k); intvec v, int k RETURN: int i, the last index i>=k such that v[i]!=1, or k-1 if no such i exists. NOTE: This procedure is only for internal use; it is called in tau_es2. " { int i=size(v); while (i>=k) { if (v[i]!=1) { return(i); } else { i--; } } return(i); } static proc intmat_minus_one (intmat M) "USAGE: intmat_minus_one(M); intmat M RETURN: intmat, all non-zero entries of M deminuished by 1. NOTE: This procedure is only for internal use; it is called in tau_es2. " { int i,j; for (i=1;i<=nrows(M);i++) { for (j=1;j<=ncols(M);j++) { if (M[i,j]!=0) { M[i,j]=M[i,j]-1; } } } return(M); } proc proximitymatrix (def INPUT) "USAGE: proximitymatrix(INPUT); INPUT poly or list or intmat ASSUME: INPUT is either a REDUCED bivariate polynomial defining a plane curve singularity, or the output of @code{hnexpansion(f[,\"ess\"])}, or the list @code{hne} in the ring created by @code{hnexpansion(f[,\"ess\"])}, or the output of @code{develop(f)} resp. of @code{extdevelop(f,n)}, or a list containing the contact matrix and a list of integer vectors with the characteristic exponents of the branches of a plane curve singularity, or an integer vector containing the characteristic exponents of an irreducible plane curve singularity, or the resolution graph of a plane curve singularity (i.e. the output of resolutiongraph or the first entry in the output of totalmultiplicities). RETURN: list, of three integer matrices. The first one is the proximity matrix of the plane curve defined by the INPUT, i.e. the entry i,j is 1 if the infinitely near point corresponding to row i is proximate to the infinitely near point corresponding to row j. The second integer matrix is the incidence matrix of the resolution graph of the plane curve. The entry on the diagonal in row i is -s-1 if s is the number of points proximate to the infinitely near point corresponding to the ith row in the matrix. The third integer matrix is the incidence matrix of the Enriques diagram of the plane curve singularity, i.e. each row corresponds to an infinitely near point in the minimal standard resolution, including the strict transforms of the branches, the diagonal element gives the level of the point, and the entry i,j is -1 if row i is proximate to row j. NOTE: In case the Hamburger-Noether expansion of the curve f is needed for other purposes as well it is better to calculate this first with the aid of @code{hnexpansion} and use it as input instead of the polynomial itself. @* If you are not sure whether the INPUT polynomial is reduced or not, use @code{squarefree(INPUT)} as input instead. @* If the input is a smooth curve, then the output will consist of three one-by-one zero matrices. @* For the definitions of the computed objects see e.g. the book Eduardo Casas-Alvero, Singularities of Plane Curves. SEE ALSO: develop, hnexpansion, totalmultiplicities, alexanderpolynomial EXAMPLE: example proximitymatrix; shows an example " { ///////// Decide on the type of input. ////////// if (typeof(INPUT)=="intmat") { intmat resgr=INPUT; } else { intmat resgr=totalmultiplicities(INPUT)[1]; } //////// Deal with the case of a smooth curve //////////////// if (size(resgr)==1) { return(list(intmat(intvec(1),1,1),intmat(intvec(-1),1,1),intmat(intvec(0),1,1))); } //////// Calculate the proximity resolution graph //////////// int i,j; int n=nrows(resgr); intvec diag; // Diagonal of the Enriques diagram. int si; // number of points proximate to the point corresponding to the ith row // Adjust the weights of the nodes corresponding to strict transforms so // as if there had been one additional blow up. for (i=1;i<=n;i++) { // Check if the row corresponds to an exceptional divisor ... if (resgr[i,i]<0) { j=1; while ((resgr[i,j]==0) or (i==j)) { j++; } resgr[i,i]=resgr[j,j]+1; } } // Set the weights in the resolution graph to the blowing up level in the resolution. for (i=1;i<=n;i++) { resgr[i,i]=resgr[i,i]-1; diag[i]=resgr[i,i]; // The level of the corresponding infinitely near point. } // Replace the weights in the resolution graph by // -s-1, where s is the number of points which are proximate to the point. for (i=1;i<=n;i++) { si=-1; // Find the points of higher weight which are connected to the ith row. for (j=i+1;j<=n;j++) { // If the point in row j is connected to the ith row, then all the points of // weight resgr[i,i]+1 to weight resgr[j,j] in the corresponding subgraph // are proximate to the point of the ith row. This number is just resgr[j,j]-resgr[i,i]. if ((resgr[i,j]!=0) and (resgr[j,j]>0)) { si=si-(resgr[j,j]-resgr[i,i]); } } resgr[i,i]=si; } /////////////// Calculate the proximity matrix /////////////////// intmat proximity=proxgauss(resgr); intmat enriques=proximity; for (i=1;i<=nrows(enriques);i++) { enriques[i,i]=diag[i]; } return(list(proximity,resgr,enriques)); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y),ls; poly f1=(y2-x3)^2-4x5y-x7; poly f2=y2-x3; poly f3=y3-x2; list proximity=proximitymatrix(f1*f2*f3); /// The proximity matrix P /// print(proximity[1]); /// The proximity resolution graph N /// print(proximity[2]); /// They satisfy N=-transpose(P)*P /// print(-transpose(proximity[1])*proximity[1]); /// The incidence matrix of the Enriques diagram /// print(proximity[3]); /// If M is the matrix of multiplicities and TM the matrix of total /// multiplicities of the singularity, then M=P*TM. /// We therefore calculate the (total) multiplicities. Note that /// they have to be slightly extended. list MULT=extend_multiplicities(totalmultiplicities(f1*f2*f3)); intmat TM=MULT[1]; // Total multiplicites. intmat M=MULT[2]; // Multiplicities. /// Check: M-P*TM=0. M-proximity[1]*TM; /// Check: inverse(P)*M-TM=0. intmat_inverse(proximity[1])*M-TM; } static proc addmultiplrows (intmat M, int i, int j, int ki, int kj) "USAGE: addmultiplrows(M,i,j,ki,kj); intmat M, int i,j,ki,kj RETURN: intmat, replaces the j-th row in M by ki-times the i-th row plus kj times the j-th NOTE: This procedure is only for internal use; it is called in intmat_inverse and proxgauss. " { int k=ncols(M); M[j,1..k]=kj*M[j,1..k]+ki*M[i,1..k]; return(M); } static proc proxgauss (intmat M) "USAGE: proxgauss(M); intmat M ASSUME: M is the output of proximity_resgr RETURN: intmat, replaces the j-th row in M by ki-times the i-th row plus kj times the j-th NOTE: This procedure is only for internal use; it is called in intmat_inverse. " { int i; int n=nrows(M); if (n==1) { M[1,1]=1; return(M); } else { if (M[n,n]<0) { M=addmultiplrows(M,n,n,-1,0); } for (i=n-1;i>=1;i--) { if (M[i,n]!=0) { M=addmultiplrows(M,n,i,-M[i,n],M[n,n]); } } intmat N[n-1][n-1]=M[1..n-1,1..n-1]; N=proxgauss(N); M[1..n-1,1..n-1]=N[1..n-1,1..n-1]; return(M); } } proc extend_multiplicities (list rg) "USAGE: extend_multiplicities(rg); list rg ASSUME: rg is the output of the procedure totalmultiplicities RETURN: list, the first entry is an integer matrix containing the total multiplicities and the second entry is an integer matrix containing the multiplicies of the resolution given by rg, where the zeros corresponding to the strict transforms of the branches of the curve have been replaced by the (total) multiplicities of the infinitely near point corresponding to one further blow up for each branch. KEYWORDS: total multiplicities; multiplicity sequence; resolution graph EXAMPLE: example extend_multiplicities; shows an example " { intmat resgr,tm,mt=rg[1],rg[2],rg[3]; int i,j; for (i=1;i<=nrows(resgr);i++) { if (resgr[i,i]<0) { j=1; while ((resgr[i,j]==0) or (i==j)) { j++; } tm[i,1..ncols(tm)]=tm[j,1..ncols(tm)]; tm[i,-resgr[i,i]]=tm[i,-resgr[i,i]]+1; mt[i,-resgr[i,i]]=1; } } return(list(tm,mt)); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y),ls; poly f1=(y2-x3)^2-4x5y-x7; poly f2=y2-x3; poly f3=y3-x2; // Calculate the resolution graph and the (total) multiplicities of f1*f2*f3. list RESGR=totalmultiplicities(f1*f2*f3); // Extend the (total) multiplicities. list MULT=extend_multiplicities(RESGR); // Compare the total multiplicities. RESGR[2]; MULT[1]; // Compare the multiplicities. RESGR[3]; MULT[2]; } proc intmat_inverse (intmat M) "USAGE: intmat_inverse(M); intmat M ASSUME: M is a lower triangular integer matrix with diagonal entries 1 or -1 RETURN: intmat, the inverse of M KEYWORDS: integer matrix, inverse EXAMPLE: example intmat_inverse; shows an example " { int i,j,k; int n=nrows(M); intmat U[n][n]; U=U+1; for (i=1;i<=n;i++) { if (M[i,i]==-1) { M=addmultiplrows(M,i,i,-1,0); U=addmultiplrows(U,i,i,-1,0); } for (j=i+1;j<=n;j++) { U=addmultiplrows(U,i,j,-M[j,i],M[i,i]); M=addmultiplrows(M,i,j,-M[j,i],M[i,i]); } } return(U); } example { "EXAMPLE:";echo=2; intmat M[5][5]=1,0,0,0,0,1,1,0,0,0,2,1,1,0,0,3,1,1,1,0,4,1,1,1,1 ; intmat U=intmat_inverse(M); print(U); print(U*M); } singular-4.0.3+ds/Singular/LIB/algebra.lib000066400000000000000000001106401266270727000202360ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version algebra.lib 4.0.1.1 Dec_2014 "; // $Id: 2bb3191198fbd2218ed724a0340d9b6d804e14b8 $ category="Commutative Algebra"; info=" LIBRARY: algebra.lib Compute with Algbras and Algebra Maps AUTHORS: Gert-Martin Greuel, greuel@mathematik.uni-kl.de, @* Agnes Eileen Heydtmann, agnes@math.uni-sb.de, @* Gerhard Pfister, pfister@mathematik.uni-kl.de PROCEDURES: algebra_containment(); query of algebra containment module_containment(); query of module containment over a subalgebra inSubring(p,I); test whether polynomial p is in subring generated by I algDependent(I); computes algebraic relations between generators of I alg_kernel(phi); computes the kernel of the ringmap phi is_injective(phi); test for injectivity of ringmap phi is_surjective(phi); test for surjectivity of ringmap phi is_bijective(phi); test for bijectivity of ring map phi noetherNormal(id); noether normalization of ideal id mapIsFinite(R,phi,I); query for finiteness of map phi:R --> basering/I finitenessTest(i,z); find variables which occur as pure power in lead(i) nonZeroEntry(id); list describing non-zero entries of an identifier "; LIB "inout.lib"; LIB "elim.lib"; LIB "ring.lib"; LIB "matrix.lib"; /////////////////////////////////////////////////////////////////////////////// proc algebra_containment (poly p, ideal A, list #) "USAGE: algebra_containment(p,A[,k]); p poly, A ideal, k integer. @* A = A[1],...,A[m] generators of subalgebra of the basering RETURN: @format - k=0 (or if k is not given) an integer: 1 : if p is contained in the subalgebra K[A[1],...,A[m]] 0 : if p is not contained in K[A[1],...,A[m]] - k=1 : a list, say l, of size 2, l[1] integer, l[2] ring, satisfying l[1]=1 if p is in the subalgebra K[A[1],...,A[m]] and then the ring l[2]: ring, contains poly check = h(y(1),...,y(m)) if p=h(A[1],...,A[m]) l[1]=0 if p is not in the subalgebra K[A[1],...,A[m]] and then l[2] contains the poly check = h(x,y(1),...,y(m)) if p satisfies the nonlinear relation p = h(x,A[1],...,A[m]) where x = x(1),...,x(n) denote the variables of the basering @end format DISPLAY: if k=0 and printlevel >= voice+1 (default) display the polynomial check NOTE: The proc inSubring uses a different algorithm which is sometimes faster. THEORY: The ideal of algebraic relations of the algebra generators A[1],..., A[m] is computed introducing new variables y(i) and the product order with x(i) >> y(i). p reduces to a polynomial only in the y(i) <=> p is contained in the subring generated by the polynomials A[1],...,A[m]. EXAMPLE: example algebra_containment; shows an example " { int DEGB = degBound; degBound = 0; if (size(#)==0) { #[1] = 0; } def br=basering; int n = nvars(br); int m = ncols(A); int i; string mp=string(minpoly); //----------------- // neu CL 10/05: int is_qring; if (size(ideal(br))>0) { is_qring=1; ideal IdQ = ideal(br); } //----------------- // ---------- create new ring with extra variables -------------------- execute ("ring R=("+charstr(br)+"),(x(1..n),y(1..m)),(dp(n),dp(m));"); if (mp!="0") { execute ("minpoly=number("+mp+");"); } ideal vars=x(1..n); map emb=br,vars; ideal A=ideal(emb(A)); poly check=emb(p); for (i=1;i<=m;i=i+1) { A[i]=A[i]-y(i); } //----------------- // neu CL 10/05: if (is_qring) { A = A,emb(IdQ); } //----------------- A=std(A); check=reduce(check,A); /*alternatively we could use reduce(check,A,1) which is a little faster but result is bigger since it is not tail-reduced */ //--- checking whether all variables from old ring have disappeared ------ // if so, then the sum of the first n leading exponents is 0, hence i=1 // use i also to control the display i = (sum(leadexp(check),1..n)==0); degBound = DEGB; if( #[1] == 0 ) { dbprint(printlevel-voice+3,"// "+string(check)); return(i); } else { list l = i,R; kill A,vars,emb; export check; dbprint(printlevel-voice+3," // 'algebra_containment' created a ring as 2nd element of the list. // The ring contains the polynomial check which defines the algebraic relation. // To access to the ring and see check you must give the ring a name, // e.g.: def S = l[2]; setring S; check; "); setring br; return(l); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; int p = printlevel; printlevel = 1; ring R = 0,(x,y,z),dp; ideal A=x2+y2,z2,x4+y4,1,x2z-1y2z,xyz,x3y-1xy3; poly p1=z; poly p2= x10z3-x8y2z3+2x6y4z3-2x4y6z3+x2y8z3-y10z3+x6z4+3x4y2z4+3x2y4z4+y6z4; algebra_containment(p1,A); algebra_containment(p2,A); list L = algebra_containment(p2,A,1); L[1]; def S = L[2]; setring S; check; printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc module_containment(poly p, ideal P, ideal S, list #) "USAGE: module_containment(p,P,M[,k]); p poly, P ideal, M ideal, k int @* P = P[1],...,P[n] generators of a subalgebra of the basering, @* M = M[1],...,M[m] generators of a module over the subalgebra K[P] ASSUME: ncols(P) = nvars(basering), the P[i] are algebraically independent RETURN: @format - k=0 (or if k is not given), an integer: 1 : if p is contained in the module over K[P] 0 : if p is not contained in - k=1, a list, say l, of size 2, l[1] integer, l[2] ring: l[1]=1 : if p is in and then the ring l[2] contains the polynomial check = h(y(1),...,y(m),z(1),...,z(n)) if p = h(M[1],...,M[m],P[1],...,P[n]) l[1]=0 : if p is in not in , then l[2] contains the poly check = h(x,y(1),...,y(m),z(1),...,z(n)) if p satisfies the nonlinear relation p = h(x,M[1],...,M[m],P[1],...,P[n]) where x = x(1),...,x(n) denote the variables of the basering @end format DISPLAY: the polynomial h(y(1),...,y(m),z(1),...,z(n)) if k=0, resp. a comment how to access the relation check if k=1, provided printlevel >= voice+1 (default). THEORY: The ideal of algebraic relations of all the generators p1,...,pn, s1,...,st given by P and S is computed introducing new variables y(j), z(i) and the product order: x^a*y^b*z^c > x^d*y^e*z^f if x^a > x^d with respect to the lp ordering or else if z^c > z^f with respect to the dp ordering or else if y^b > y^e with respect to the lp ordering again. p reduces to a polynomial only in the y(j) and z(i), linear in the z(i) <=> p is contained in the module. EXAMPLE: example module_containment; shows an example " { def br=basering; int DEGB = degBound; degBound=0; if (size(#)==0) { #[1] = 0; } int n=nvars(br); if ( ncols(P)==n ) { int m=ncols(S); string mp=string(minpoly); // ---------- create new ring with extra variables -------------------- execute ("ring R=("+charstr(br)+"),(x(1..n),y(1..m),z(1..n)),(lp(n),dp(m),lp(n));"); if (mp!="0") { execute ("minpoly=number("+mp+");"); } ideal vars = x(1..n); map emb = br,vars; ideal P = emb(P); ideal S = emb(S); poly check = emb(p); ideal I; for (int i=1;i<=m;i=i+1) { I[i]=S[i]-y(i); } for (i=1;i<=n;i=i+1) { I[m+i]=P[i]-z(i); } I=std(I); check = reduce(check,I); //--- checking whether all variables from old ring have disappeared ------ // if so, then the sum of the first n leading exponents is 0 i = (sum(leadexp(check),1..n)==0); if( #[1] == 0 ) { dbprint(i*(printlevel-voice+3),"// "+string(check)); setring br; return(i); } else { list l = i,R; kill I,vars,emb,P,S; export check; dbprint(printlevel-voice+3," // 'module_containment' created a ring as 2nd element of the list. The // ring contains the polynomial check which defines the algebraic relation // for p. To access to the ring and see check you must give the ring // a name, e.g.: def S = l[2]; setring S; check; "); setring br; return(l); } } else { setring br; "ERROR: the first ideal must have nvars(basering) entries"; return(); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; int p = printlevel; printlevel = 1; ring R=0,(x,y,z),dp; ideal P = x2+y2,z2,x4+y4; //algebra generators ideal M = 1,x2z-1y2z,xyz,x3y-1xy3; //module generators poly p1= x10z3-x8y2z3+2x6y4z3-2x4y6z3+x2y8z3-y10z3+x6z4+3x4y2z4+3x2y4z4+y6z4; module_containment(p1,P,M); poly p2=z; list l = module_containment(p2,P,M,1); l[1]; def S = l[2]; setring S; check; printlevel=p; } /////////////////////////////////////////////////////////////////////////////// proc inSubring(poly p, ideal I) "USAGE: inSubring(p,i); p poly, i ideal RETURN: @format a list l of size 2, l[1] integer, l[2] string l[1]=1 if and only if p is in the subring generated by i=i[1],...,i[k], and then l[2] = y(0)-h(y(1),...,y(k)) if p = h(i[1],...,i[k]) l[1]=0 if and only if p is in not the subring generated by i, and then l[2] = h(y(0),y(1),...,y(k)) where p satisfies the nonlinear relation h(p,i[1],...,i[k])=0. @end format NOTE: the proc algebra_containment tests the same using a different algorithm, which is often faster if l[1] == 0 then l[2] may contain more than one relation h(y(0),y(1),...,y(k)), separated by comma EXAMPLE: example inSubring; shows an example " {int z=ncols(I); int i; def gnir=basering; int n = nvars(gnir); string mp=string(minpoly); list l; // neu CL 10/05: int is_qring; if (size(ideal(gnir))>0) { is_qring=1; ideal IdQ = ideal(gnir); } // ---------- create new ring with extra variables -------------------- //the intersection of ideal nett=(p-y(0),I[1]-y(1),...) //with the ring k[y(0),...,y(n)] is computed, the result is ker execute ("ring r1= ("+charstr(basering)+"),(x(1..n),y(0..z)),lp;"); // execute ("ring r1= ("+charstr(basering)+"),(y(0..z),x(1..n)),dp;"); if (mp!="0") { execute ("minpoly=number("+mp+");"); } ideal va = x(1..n); map emb = gnir,va; ideal nett = emb(I); for (i=1;i<=z;i++) { nett[i]=nett[i]-y(i); } nett=emb(p)-y(0),nett; // neu CL 10/05: if (is_qring) { nett = nett,emb(IdQ); } //----------------- ideal ker=eliminate(nett,product(va)); ker=std(ker); //---------- test wether y(0)-h(y(1),...,y(z)) is in ker -------------- l[1]=0; l[2]=""; for (i=1;i<=size(ker);i++) { if (deg(ker[i]/y(0))==0) { string str=string(ker[i]); setring gnir; l[1]=1; l[2]=str; return(l); } if (deg(ker[i]/y(0))>0) { if( l[2] != "" ){ l[2] = l[2] + ","; } l[2] = l[2] + string(ker[i]); } } setring gnir; return(l); } example { "EXAMPLE:"; echo = 2; ring q=0,(x,y,z,u,v,w),dp; poly p=xyzu2w-1yzu2w2+u4w2-1xu2vw+u2vw2+xyz-1yzw+2u2w-1xv+vw+2; ideal I =x-w,u2w+1,yz-v; inSubring(p,I); } ////////////////////////////////////////////////////////////////////////////// proc algDependent( ideal A, list # ) "USAGE: algDependent(f[,c]); f ideal (say, f = f1,...,fm), c integer RETURN: @format a list l of size 2, l[1] integer, l[2] ring: - l[1] = 1 if f1,...,fm are algebraic dependent, 0 if not - l[2] is a ring with variables x(1),...,x(n),y(1),...,y(m) if the basering has n variables. It contains the ideal 'ker', depending only on the y(i) and generating the algebraic relations between the f[i], i.e. substituting y(i) by fi yields 0. Of course, ker is nothing but the kernel of the ring map K[y(1),...,y(m)] ---> basering, y(i) --> fi. @end format NOTE: Three different algorithms are used depending on c = 1,2,3. If c is not given or c=0, a heuristically best method is chosen. The basering may be a quotient ring. To access to the ring l[2] and see ker you must give the ring a name, e.g. def S=l[2]; setring S; ker; DISPLAY: The above comment is displayed if printlevel >= 0 (default). EXAMPLE: example algDependent; shows an example " { int bestoption = 3; // bestoption is the default algorithm, it may be set to 1,2 or 3; // it should be changed, if another algorithm turns out to be faster // in general. Is perhaps dependent on the input (# vars, size ...) int tt; if( size(#) > 0 ) { if( typeof(#[1]) == "int" ) { tt = #[1]; } } if( size(#) == 0 or tt == 0 ) { tt = bestoption; } def br=basering; int n = nvars(br); ideal B = ideal(br); int m = ncols(A); int s = size(B); int i; string mp = string(minpoly); // --------------------- 1st variant of algorithm ---------------------- // use internal preimage command (should be equivalent to 2nd variant) if ( tt == 1 ) { execute ("ring R1=("+charstr(br)+"),y(1..m),dp;"); if (mp!="0") { execute ("minpoly=number("+mp+");"); } setring br; map phi = R1,A; setring R1; ideal ker = preimage(br,phi,B); } // ---------- create new ring with extra variables -------------------- execute ("ring R2=("+charstr(br)+"),(x(1..n),y(1..m)),(dp);"); if (mp!="0") { execute ("minpoly=number("+mp+");"); } if( tt == 1 ) { ideal ker = imap(R1,ker); } else { ideal vars = x(1..n); map emb = br,vars; ideal A = emb(A); for (i=1; i<=m; i=i+1) { A[i] = A[i]-y(i); } // --------------------- 2nd variant of algorithm ---------------------- // use internal eliminate for eliminating m variables x(i) from // ideal A[i] - y(i) (uses extra eliminating 'first row', a-order) if ( s == 0 and tt == 2 ) { ideal ker = eliminate(A,product(vars)); } else // eliminate does not work in qrings // --------------------- 3rd variant of algorithm ---------------------- // eliminate m variables x(i) from ideal A[i] - y(i) by choosing product // order {execute ("ring R3=("+charstr(br)+"),(x(1..n),y(1..m)),(dp(n),dp(m));"); if (mp!="0") { execute ("minpoly=number("+mp+");"); } if ( s != 0 ) { ideal vars = x(1..n); map emb = br,vars; ideal B = emb(B); attrib(B,"isSB",1); qring Q = B; } ideal A = imap(R2,A); A = std(A); ideal ker = nselect(A,1..n); setring R2; if ( defined(Q)==voice ) { ideal ker = imap(Q,ker); } else { ideal ker = imap(R3,ker); } kill A,emb,vars; } } // --------------------------- return ---------------------------------- s = size(ker); list L = (s!=0), R2; export(ker); dbprint(printlevel-voice+3," // The 2nd element of the list l is a ring with variables x(1),...,x(n), // and y(1),...,y(m) if the basering has n variables and if the ideal // is f[1],...,f[m]. The ring contains the ideal ker which depends only // on the y(i) and generates the relations between the f[i]. // I.e. substituting y(i) by f[i] yields 0. // To access to the ring and see ker you must give the ring a name, // e.g.: def S = l[2]; setring S; ker; "); setring br; return (L); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring R = 0,(x,y,z,u,v,w),dp; ideal I = xyzu2w-1yzu2w2+u4w2-1xu2vw+u2vw2+xyz-1yzw+2u2w-1xv+vw+2, x-w, u2w+1, yz-v; list l = algDependent(I); l[1]; def S = l[2]; setring S; ker; printlevel = p; } ////////////////////////////////////////////////////////////////////////////// proc alg_kernel( map phi, def pr, list #) "USAGE: alg_kernel(phi,pr[,s,c]); phi map to basering, pr preimage ring, s string (name of kernel in pr), c integer. RETURN: a string, the kernel of phi as string. If, moreover, a string s is given, the algorithm creates, in the preimage ring pr the kernel of phi with name s. Three different algorithms are used depending on c = 1,2,3. If c is not given or c=0, a heuristically best method is chosen. (algorithm 1 uses the preimage command) NOTE: Since the kernel of phi lives in pr, it cannot be returned to the basering. If s is given, the user has access to it in pr via s. The basering may be a quotient ring. EXAMPLE: example alg_kernel; shows an example " { int tt; def BAS = basering; if( size(#) >0 ) { if( typeof(#[1]) == "int") { tt = #[1]; } if( typeof(#[1]) == "string") { string nker=#[1]; } if( size(#)>1 ) { if( typeof(#[2]) == "string") { string nker=#[2]; } if( typeof(#[2]) == "int") { tt = #[2]; } } } int n = nvars(basering); string mp = string(minpoly); ideal A = ideal(phi); //def pr = preimage(phi); //folgendes Auffuellen oder Stutzen ist ev nicht mehr noetig //falls map das richtig macht int m = nvars(pr); ideal j; j[m]=0; A=A,j; A=A[1..m]; list L = algDependent(A,tt); // algDependent is called with "bestoption" if tt = 0 def S = L[2]; execute ("ring R=("+charstr(basering)+"),(@(1..n),"+varstr(pr)+"),(dp);"); if (mp!="0") { execute ("minpoly=number("+mp+");"); } ideal ker = fetch(S,ker); //in order to have variable names correct string sker = string(ker); if (defined(nker) == voice) { setring pr; execute("ideal "+nker+"="+sker+";"); execute("export("+nker+");"); } setring BAS; return(sker); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,c),ds; ring s = 0,(x,y,z,u,v,w),dp; ideal I = x-w,u2w+1,yz-v; map phi = r,I; // a map from r to s: alg_kernel(phi,r); // a,b,c ---> x-w,u2w+1,yz-v ring S = 0,(a,b,c),ds; ring R = 0,(x,y,z),dp; qring Q = std(x-y); ideal i = x, y, x2-y3; map phi = S,i; // a map to a quotient ring alg_kernel(phi,S,"ker",3); // uses algorithm 3 setring S; // you have access to kernel in preimage ker; } ////////////////////////////////////////////////////////////////////////////// proc is_injective( map phi,def pr,list #) "USAGE: is_injective(phi,pr[,c,s]); phi map, pr preimage ring, c int, s string RETURN: @format - 1 (type int) if phi is injective, 0 if not (if s is not given). - If s is given, return a list l of size 2, l[1] int, l[2] ring: l[1] is 1 if phi is injective, 0 if not l[2] is a ring with variables x(1),...,x(n),y(1),...,y(m) if the basering has n variables and the map m components, it contains the ideal 'ker', depending only on the y(i), the kernel of the given map @end format NOTE: Three differnt algorithms are used depending on c = 1,2,3. If c is not given or c=0, a heuristically best method is chosen. The basering may be a quotient ring. However, if the preimage ring is a quotient ring, say pr = P/I, consider phi as a map from P and then the algorithm returns 1 if the kernel of phi is 0 mod I. To access to the ring l[2] and see ker you must give the ring a name, e.g. def S=l[2]; setring S; ker; DISPLAY: The above comment is displayed if printlevel >= 0 (default). EXAMPLE: example is_injective; shows an example " { def bsr = basering; int tt; if( size(#) >0 ) { if( typeof(#[1]) == "int") { tt = #[1]; } if( typeof(#[1]) == "string") { string pau=#[1]; } if( size(#)>1 ) { if( typeof(#[2]) == "string") { string pau=#[2]; } if( typeof(#[2]) == "int") { tt = #[2]; } } } int n = nvars(basering); string mp = string(minpoly); ideal A = ideal(phi); //def pr = preimage(phi); //folgendes Auffuellen oder Stutzen ist ev nicht mehr noetig //falls map das richtig macht int m = nvars(pr); ideal j; j[m]=0; A=A,j; A=A[1..m]; list L = algDependent(A,tt); L[1] = L[1]==0; // the preimage ring may be a quotient ring, we still have to check whether // the kernel is 0 mod ideal of the quotient ring setring pr; if ( size(ideal(pr)) != 0 ) { def S = L[2]; ideal proj; proj [n+1..n+m] = maxideal(1); map psi = S,proj; L[1] = size(NF(psi(ker),std(0))) == 0; } setring bsr; if ( defined(pau) != voice ) { return (L[1]); } else { dbprint(printlevel-voice+3," // The 2nd element of the list is a ring with variables x(1),...,x(n), // y(1),...,y(m) if the basering has n variables and the map is // F[1],...,F[m]. // It contains the ideal ker, the kernel of the given map y(i) --> F[i]. // To access to the ring and see ker you must give the ring a name, // e.g.: def S = l[2]; setring S; ker; "); return(L); } } example { "EXAMPLE:"; echo = 2; int p = printlevel; ring r = 0,(a,b,c),ds; ring s = 0,(x,y,z,u,v,w),dp; ideal I = x-w,u2w+1,yz-v; map phi = r,I; // a map from r to s: is_injective(phi,r); // a,b,c ---> x-w,u2w+1,yz-v ring R = 0,(x,y,z),dp; ideal i = x, y, x2-y3; map phi = R,i; // a map from R to itself, z --> x2-y3 list l = is_injective(phi,R,""); l[1]; def S = l[2]; setring S; ker; } /////////////////////////////////////////////////////////////////////////////// proc is_surjective( map phi ) "USAGE: is_surjective(phi); phi map to basering, or ideal defining it RETURN: an integer, 1 if phi is surjective, 0 if not NOTE: The algorithm returns 1 if and only if all the variables of the basering are contained in the polynomial subalgebra generated by the polynomials defining phi. Hence, it tests surjectivity in the case of a global odering. If the basering has local or mixed ordering or if the preimage ring is a quotient ring (in which case the map may not be well defined) then the return value 1 needs to be interpreted with care. EXAMPLE: example is_surjective; shows an example " { def br=basering; ideal B = ideal(br); int s = size(B); int n = nvars(br); ideal A = ideal(phi); int m = ncols(A); int ii,t=1,1; string mp=string(minpoly); // ------------ create new ring with extra variables --------------------- execute ("ring R=("+charstr(br)+"),(x(1..n),y(1..m)),(dp(n),dp(m));"); if (mp!="0") { execute ("minpoly=number("+mp+");"); } ideal vars = x(1..n); map emb = br,vars; if ( s != 0 ) { ideal B = emb(B); attrib(B,"isSB",1); qring Q = B; ideal vars = x(1..n); map emb = br,vars; } ideal A = emb(A); for ( ii=1; ii<=m; ii++ ) { A[ii] = A [ii]-y(ii); } A=std(A); // ------------- check whether the x(i) are in the image ----------------- poly check; for (ii=1; ii<=n; ii++ ) { check=reduce(x(ii),A,1); // --- checking whether all variables from old ring have disappeared ----- // if so, then the sum of the first n leading exponents is 0 if( sum(leadexp(check),1..n)!=0 ) { t=0; break; } } setring br; return(t); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; ideal i = x, y, x2-y3; map phi = R,i; // a map from R to itself, z->x2-y3 is_surjective(phi); qring Q = std(ideal(z-x37)); map psi = R, x,y,x2-y3; // the same map to the quotient ring is_surjective(psi); ring S = 0,(a,b,c),dp; map psi = R,ideal(a,a+b,c-a2+b3); // a map from R to S, is_surjective(psi); // x->a, y->a+b, z->c-a2+b3 } /////////////////////////////////////////////////////////////////////////////// proc is_bijective ( map phi,def pr ) "USAGE: is_bijective(phi,pr); phi map to basering, pr preimage ring RETURN: an integer, 1 if phi is bijective, 0 if not NOTE: The algorithm checks first injectivity and then surjectivity. To interprete this for local/mixed orderings, or for quotient rings type help is_surjective; and help is_injective; DISPLAY: A comment if printlevel >= voice-1 (default) EXAMPLE: example is_bijective; shows an example " { def br = basering; int n = nvars(br); ideal B = ideal(br); int s = size(B); ideal A = ideal(phi); //folgendes Auffuellen oder Stutzen ist ev nicht mehr noetig //falls map das richtig macht int m = nvars(pr); ideal j; j[m]=0; A=A,j; A=A[1..m]; int ii,t = 1,1; string mp=string(minpoly); // ------------ create new ring with extra variables --------------------- execute ("ring R=("+charstr(br)+"),(x(1..n),y(1..m)),(dp(n),dp(m));"); if (mp!="0") { execute ("minpoly=number("+mp+");"); } ideal vars = x(1..n); map emb = br,vars; if ( s != 0 ) { ideal B = emb(B); attrib(B,"isSB",1); qring Q = B; ideal vars = x(1..n); map emb = br,vars; } ideal A = emb(A); for ( ii=1; ii<=m; ii++ ) { A[ii] = A[ii]-y(ii); } A=std(A); def bsr = basering; // ------- checking whether phi is injective by computing the kernel ------- ideal ker = nselect(A,1..n); t = size(ker); setring pr; if ( size(ideal(pr)) != 0 ) { ideal proj; proj[n+1..n+m] = maxideal(1); map psi = bsr,proj; t = size(NF(psi(ker),std(0))); } if ( t != 0 ) { dbprint(printlevel-voice+3,"// map not injective" ); setring br; return(0); } else // -------------- checking whether phi is surjective ---------------------- { t = 1; setring bsr; poly check; for (ii=1; ii<=n; ii++ ) { check=reduce(x(ii),A,1); // --- checking whether all variables from old ring have disappeared ----- // if so, then the sum of the first n leading exponents is 0 if( sum(leadexp(check),1..n)!=0 ) { t=0; break; } } if ( t == 0 ) { dbprint(printlevel-voice+3,"// map injective, but not surjective" ); } setring br; return(t); } } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring R = 0,(x,y,z),dp; ideal i = x, y, x2-y3; map phi = R,i; // a map from R to itself, z->x2-y3 is_bijective(phi,R); qring Q = std(z-x2+y3); is_bijective(ideal(x,y,x2-y3),Q); ring S = 0,(a,b,c,d),dp; map psi = R,ideal(a,a+b,c-a2+b3,0); // a map from R to S, is_bijective(psi,R); // x->a, y->a+b, z->c-a2+b3 qring T = std(d,c-a2+b3); map chi = Q,a,b,a2-b3; // amap between two quotient rings is_bijective(chi,Q); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc noetherNormal(ideal i, list #) "USAGE: noetherNormal(id[,p]); id ideal, p integer RETURN: @format a list l of two ideals, say I,J: - I defines a map (coordinate change in the basering), such that: - J is generated by a subset of the variables with size(J) = dim(id) if we define map phi=basering,I; then k[var(1),...,var(n)]/phi(id) is finite over k[J]. If p is given, 0<=p<=100, a sparse coordinate change with p percent of the matrix entries being 0 (default: p=0 i.e. dense) @end format NOTE: Designed for characteristic 0.It works also in char k > 0 if it terminates,but may result in an infinite loop in small characteristic. EXAMPLE: example noetherNormal; shows an example " { i=simplify(i,2); if (size(i)== 0) { list l = maxideal(1),maxideal(1); return( l ); } int p; if( size(#) != 0 ) { p = #[1]; } def r = basering; int n = nvars(r); list good; // ------------------------ change of ordering --------------------------- //a procedure from ring.lib changing the order to dp creating a new //basering @R in order to compute the dimension d of i def @R=changeord(list(list("dp",1:nvars(basering)))); setring @R; ideal i = imap(r,i); list j = mstd(i); i = j[2]; int d = dim(j[1]); if ( d <= 0) { setring r; list l = maxideal(1),ideal(0); return( l ); } // ------------------------ change of ordering --------------------------- //Now change the order to (dp(n-d),lp) creating a new basering @S def @S=changeord(list(list("dp",1:(n-d)),list("lp",1:d))); setring @S; ideal m; // ----------------- sparse-random coordinate change -------------------- //creating lower triangular random generators for the maximal ideal //a procedure from random.lib, as sparse as possible if( char(@S) > 0 ) { m=ideal(sparsetriag(n,n,p,char(@S)+1)*transpose(maxideal(1))); } if( char(@S) == 0 ) { if ( voice <= 6 ) { m=ideal(sparsetriag(n,n,p,10)*transpose(maxideal(1))); } if( voice > 6 and voice <= 11) { m=ideal(sparsetriag(n,n,p,100)*transpose(maxideal(1))); } if ( voice > 11 ) { m=ideal(sparsetriag(n,n,p,30000)*transpose(maxideal(1))); } } map phi=r,m; //map phi=@R,m; ideal i=std(phi(i)); // ----------------------- test for finiteness --------------------------- //We need a test whether the coordinate change was random enough, if yes //we are ready, else call noetherNormal again list l=finitenessTest(i); setring r; list l=imap(@S,l); if(size(l[3]) == d) //the generic case { good = fetch(@S,m),l[3]; kill @S,@R; return(good); } else //the bad case { kill @S,@R; if ( voice >= 21 ) { "// WARNING: In case of a finite ground field"; "// the characteristic may be too small."; "// This could result in an infinte loop."; "// Loop in noetherNormal, voice:";, voice;""; } if ( voice >= 16 ) { "// Switch to dense coordinate change";""; return(noetherNormal(i)); } return(noetherNormal(i,p)); } } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; ideal i= xy,xz; noetherNormal(i); } /////////////////////////////////////////////////////////////////////////////// proc finitenessTest(ideal i, list #) "USAGE: finitenessTest(J[,v]); J ideal, v intvec (say v1,...,vr with vi>0) RETURN: @format a list l with l[1] integer, l[2], l[3], l[4] ideals - l[1] = 1 if var(v1),...,var(vr) are in l[2] and 0 else - l[2] (resp. l[3]) contains those variables which occur, (resp. do not occur) as pure power in the leading term of one of the generators of J, - l[4] contains those J[i] for which the leading term is a pure power of a variable (which is then in l[2]) (default: v = [1,2,..,nvars(basering)]) @end format THEORY: If J is a standard basis of an ideal generated by x_1 - f_1(y),..., x_n - f_n with y_j ordered lexicographically and y_j >> x_i, then, if y_i appears as pure power in the leading term of J[k], J[k] defines an integral relation for y_i over the y_(i+1),... and the f's. Moreover, in this situation, if l[2] = y_1,...,y_r, then K[y_1,...y_r] is finite over K[f_1..f_n]. If J contains furthermore polynomials h_j(y), then K[y_1,...y_z]/ is finite over K[f_1..f_n]. For a proof cf. Prop. 3.1.5, p. 214. in [G.-M. Greuel, G. Pfister: A SINGULAR Introduction to Commutative Algebra, 2nd Edition, Springer Verlag (2007)] EXAMPLE: example finitenessTest; shows an example " { int n = nvars(basering); intvec v,w; int j,z,ii; v[n]=0; //v should have size n intvec V = 1..n; list nze; //the non-zero entries of a leadexp if (size(#) != 0 ) { V = #[1]; } intmat W[1][n]; //create intmat with 1 row, having 1 at //position V[j], i = 1..size(V), 0 else for( j=1; j<=size(V); j++ ) { W[1,V[j]] = 1; } ideal relation,zero,nonzero; // ---------------------- check leading exponents ------------------------- for(j=1;j<=ncols(i);j++) { w = leadexp(i[j]); nze = nonZeroEntry(w); if( nze[1] == 1 ) //the leading term of i[j] is a { //pure power of some variable if( W*w != 0 ) //case: variable has index appearing in V { relation[size(relation)+1] = i[j]; v=v+w; } } } // ----------------- pick the corresponding variables --------------------- //the nonzero entries of v correspond to variables which occur as //pure power in the leading term of some polynomial in i for(j=1; j<=size(v); j++) { if(v[j]==0) { zero[size(zero)+1]=var(j); } else { nonzero[size(nonzero)+1]=var(j); } } // ---------------- do we have all pure powers we want? ------------------- // test this by dividing the product of corresponding variables ideal max = maxideal(1); max = max[V]; z = (product(nonzero)/product(max) != 0); return(list(z,nonzero,zero,relation)); } example { "EXAMPLE:"; echo = 2; ring s = 0,(x,y,z,a,b,c),(lp(3),dp); ideal i= a -(xy)^3+x2-z, b -y2-1, c -z3; ideal j = a -(xy)^3+x2-z, b -y2-1, c -z3, xy; finitenessTest(std(i),1..3); finitenessTest(std(j),1..3); } /////////////////////////////////////////////////////////////////////////////// proc mapIsFinite(map phi,def R, list #) "USAGE: mapIsFinite(phi,R[,J]); R the preimage ring of the map phi: R ---> basering J an ideal in the basering, J = 0 if not given RETURN: 1 if R ---> basering/J is finite and 0 else NOTE: R may be a quotient ring (this will be ignored since a map R/I-->S/J is finite if and only if the induced map R-->S/J is finite). SEE ALSO: finitenessTest EXAMPLE: example mapIsFinite; shows an example " { def bsr = basering; ideal J; if( size(#) != 0 ) { J = #[1]; } string os = ordstr(bsr); int m = nvars(bsr); int n = nvars(R); ideal PHI = ideal(phi); if ( ncols(PHI) < n ) { PHI[n]=0; } // --------------------- change of variable names ------------------------- execute("ring @bsr = ("+charstr(bsr)+"),y(1..m),("+os+");"); ideal J = fetch(bsr,J); ideal PHI = fetch(bsr,PHI); // --------------------------- enlarging ring ----------------------------- execute("ring @rr = ("+charstr(bsr)+"),(y(1..m),x(1..n)),(lp(m),dp);"); ideal J = imap(@bsr,J); ideal PHI = imap(@bsr,PHI); ideal M; int i; for(i=1;i<=n;i++) { M[i]=x(i)-PHI[i]; } M = std(M+J); // ----------------------- test for finiteness --------------------------- list l = finitenessTest(M,1..m); int result = l[1]; setring bsr; return( result ); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,c),dp; ring s = 0,(x,y,z),dp; ideal i= xy; map phi= r,(xy)^3+x2+z,y2-1,z3; mapIsFinite(phi,r,i); } ////////////////////////////////////////////////////////////////////////////// proc nonZeroEntry(def id) "USAGE: nonZeroEntry(id); id=object for which the test 'id[i]!=0', i=1,..,N, N=size(id) (resp. ncols(id) for id of type ideal or module) is defined (e.g. ideal, vector, list of polynomials, intvec,...) RETURN: @format a list, say l, with l[1] an integer, l[2], l[3] integer vectors: - l[1] number of non-zero entries of id - l[2] intvec of size l[1] with l[2][i]=i if id[i] != 0 in case l[1]!=0 (and l[2]=0 if l[1]=0) - l[3] intvec with l[3][i]=1 if id[i]!=0 and l[3][i]=0 else @end format NOTE: EXAMPLE: example nonZeroEntry; shows an example " { int ii,jj,N,n; intvec v,V; if ( typeof(id) == "ideal" || typeof(id) == "module" ) { N = ncols(id); } else { N = size(id); } for ( ii=1; ii<=N; ii++ ) { V[ii] = 0; if ( id[ii] != 0 ) { n++; v=v,ii; //the first entry of v is always 0 V[ii] = 1; } } if ( size(v) > 1 ) //if id[ii] != 0 for at least one ii delete the first 0 { v = v[2..size(v)]; } list l = n,v,V; return(l); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,c),dp; poly f = a3c+b3+c2+a; intvec v = leadexp(f); nonZeroEntry(v); intvec w; list L = 37,0,f,v,w; nonZeroEntry(L); } ////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/all.lib.tmpl000066400000000000000000000006531266270727000203660ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version all.lib 4.0.3.0 Jan_2016 "; category = "General purpose"; info=" LIBRARY: all.lib Load all libraries (commutative case) AUTHORS: Singular team (automatically generated, do not edit) use: help Singular libraries; for a list of the libraries "; /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/arcpoint.lib000066400000000000000000000370221266270727000204620ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version arcpoint.lib 4.0.0.0 Jun_2013 "; // $Id: 14a93d330540dc1bfea332ae44d5ca619952e74a $ //-*- mode:C++;-*- category="Singularities"; info=" LIBRARY: arcpoint.lib Truncations of arcs at a singular point AUTHOR: Nadine Cremer cremer@mathematik.uni-kl.de OVERVIEW: An arc is given by a power series in one variable, say t, and truncating it at a positive integer i means cutting the t-powers > i. The set of arcs truncated at order is denoted Tr(i). An algorithm for computing these sets (which happen to be constructible) is given in [Lejeune-Jalabert, M.: Courbes trac\'ees sur un germe d'hypersurface, American Journal of Mathematics, 112 (1990)]. Our procedures for computing the locally closed sets contributing to the set of truncations rely on this algorithm. PROCEDURES: nashmult(f,bound); determines locally closed sets relevant for computing truncations of arcs over a hypersurface with isolated singularity defined by f. The sets are given by two ideals specifying relations between coefficients of power series in t. One of the ideals defines an open set, the other one the complement of a closed set within the open one. We consider only coefficients up to t^. Moreover, the sequence of Nash Multiplicities of each set is displayed removepower(I); modifies the ideal I such that the algebraic set defined by it remains the same: removes powers of variables idealsimplify(I,maxiter); further simplification of I in the above sense: reduction with other elements of I. The positive integer gives a bound to the number of repetition steps equalJinI(I,J); tests if two ideals I and J are equal under the assumption that J is contained in I. Returns 1 if this is true and 0 otherwise "; LIB "ring.lib"; LIB "general.lib"; LIB "standard.lib"; LIB "sing.lib"; ////////////////////////////////////////////////////////////////////// // // // RELEVANT LOCALLY CLOSED SETS // // // ////////////////////////////////////////////////////////////////////// proc nashmult (poly f, int bound) "USAGE: nashmult(f,bound); f polynomial, bound positive integer CREATE: allsteps: @format a list containing all relevant locally closed sets up to order and their sequences of Nash Multiplicities @end format setstep: @format list of relevant locally closed sets obtained from sequences of length bound+1 @end format RETURN: ring, original basering with additional variables t and coefficients up to t^ EXAMPLE: example nashmult; shows an example" { // Make sure that only admissible parameters are entered if (bound<1) { ERROR("Integer parameter must be positive!"); } // General setup, declarations and initialization... int k,s,step,loop; // loop variables int pos; // position parameter int countall; // position parameter list allsteps; // saves results from all // steps def r=basering; int startvar=nvars(basering); intvec control=order(f); // initialize def R=ringchange(bound+1); // ring in which result lies setring R; // make it basering ideal I0; list init=control,I0,I0; list setstep=insert(setstep,init); // stores Nash multiplicities kill I0; // and underlying sets (given kill init; // that the sets are not // empty),will be a list of // lists, each of which // containing an intvec and // two ideals // consider all possible sequences of multiplicities<=: for(step=2;step<=bound+1;step++) { list setsteptmp; // temporary variable, local // to this loop int count; // position parameter int setsize=size(setstep); setring r; def rplug=pluginCoeffs(f,step); // substitute variables in f // by polynomials in t of // degree setring R; ideal coe=imap(rplug,resultcoe); // gives the t-coefficients kill rplug; // consider all sequences of length giving rise to a // family... for(loop=1;loop<=setsize;loop++) { control=setstep[loop][1]; // initialization. int sizecontrol=size(control); // describes Nash mutiplicities ideal gprev=setstep[loop][3]; // in this step, and ideal fprev=setstep[loop][2]; // the already obtained // relations ideal actcoe=reduce(coe,slimgb(fprev)); // take into account // existing relations pos=1; // determine first nonzero while(actcoe[pos]==0) // t-coefficient { pos++; } ideal fset; // will store relations ideal gset; // defining the // constructible sets int m0=control[sizecontrol]; // bounds the computations // consider all possible sequences arising from ... control=control,0; for (s=1;s<=m0;s++) { control[step]=control[step]+1; // the next possible sequence // of multiplicities fset=fset,actcoe[pos+s-1],gset; // add new condition gset=gset,fset; for(k=0;k: ideal coevar=coeffs(actcoe[pos+s], var(startvar+1+step+k*(bound+1))); int coesize=ncols(coevar); if (coesize>=2) // add coeff. of nonconstant { // terms in "highest" gset=gset,coevar[2..coesize]; // variables } kill coevar; kill coesize; } fset=fprev,fset; // add obtained conditions gset=fprev,gset; // to the existing ones... gset=idealsimplify(gset,1000); // ...and simplify fset=idealsimplify(fset,1000); // if we have found a nontrivial component... if (control[step-1]==1) { list comp=control,fset,gset; // ...add it and setsteptmp=insert(setsteptmp,comp,count); // multiplicity count++; kill comp; } else { if (equalJinI(gset,fset)==0) { list comp=control,fset,gset; // ...add it and setsteptmp=insert(setsteptmp,comp,count);// multiplicity count++; kill comp; } } } kill fset,gset,actcoe,sizecontrol,fprev,gprev,m0; } setstep=setsteptmp; allsteps=insert(allsteps,setstep,countall); // add results from countall++; // this step kill setsteptmp,count,coe,setsize; } export(setstep); export(allsteps); return(R); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; poly f=z4+y3-x2; def R=nashmult(f,2); setring R; allsteps; } ////////////////////////////////////////////////////////////////////// // // // SUBSTITUE VARIABLES BY POLYNOMIALS // // // ////////////////////////////////////////////////////////////////////// static proc pluginCoeffs (poly f,int i) "USAGE: pluginCoeffs(f,i); f polynomial, i integer CREATE: matrix, the t-coefficients obtained by replacing each variable of f by a polynomial in t RETURN: ring, corresponds to f and i in the sense that it is the original ring with added variables t and t-coefficients up to t^ " { int startvar=nvars(basering); def r=basering; def R=ringchange(i); // changes the ring setring R; // makes it new basering; ideal I=tpolys(i,startvar); map h=r,I; // define map ideal resultplug=h(f); matrix resultcoe=coeffs(resultplug[1],t); export(resultcoe); // keep accessible export(resultplug); return(R); // } ////////////////////////////////////////////////////////////////////// static proc tpolys (int i,int k) "USAGE: tpolys(i,k); i,k integer RETURN: ideal, generated by k polynomials in t of degree i of the form a(1)*t+..+a(i)*t^i NOTE: called from pluginCoeffs" { int s,t; int v; poly sum; ideal I; for(t=1;t<=k;t++) { v=(t-1)*i; for(s=1;s<=i;s++) { sum=sum+var(1+k+v+s)*var(k+1)^s; } I[t]=sum; sum=0; } return(I); } ////////////////////////////////////////////////////////////////////// // // // CONSTRUCTING THE RESULT RING // // // ////////////////////////////////////////////////////////////////////// static proc ringchange (int i) "USAGE: ringchange(i); i integer RETURN: ring, extends basering by variables t and #(variables of basering)*i new variables" { def R=changevar(""+varstr(basering)+",t," +variables_str(nvars(basering),i)+""); return(R); } ///////////////////////////////////////////////////////////////////// static proc variables_str (int k,int i) "USAGE: variables_str(k,i); k,i integer ASSUME: 1<=k<=26, i>=1 RETURN: string of names of variables added in ringchange NOTE: called from ringchange, we use this procedure to obtain a nice shape of the ring created " { list l; int s,u; string str; for (u=1;u<=k;u++) { for (s=1;s<=i;s++) { str=""+atoz(u)+"("+string(s)+")"; // creates new variables l[(u-1)*i+s]=str; // saves them in a list } } string str1=string(l); // makes a string of the return(str1); // list (needed for change } // of ring) ////////////////////////////////////////////////////////////////////// static proc atoz (int n) "USAGE: atoz(n); n integer ASSUME: 1<=n<=26 RETURN: string, the nth letter of the alphabet" { string s="ring r=0,("+A_Z("a",n)+"),ds;"; execute(s); return (string(var(n))); } ////////////////////////////////////////////////////////////////////// // // // AUXILIARY PROCEDURES // // // ////////////////////////////////////////////////////////////////////// static proc order (poly f) "USAGE: order(f); f polynomial RETURN: int i, such that f_i is the smallest (in terms of degree) non-zero homogeneous part NOTE: is designed for ordering dp" { int k=deg(f); int i; for(i=1;i<=k;i++) { if(jet(f,i)!=0) { return(i); } } } ////////////////////////////////////////////////////////////////////// static proc modd (poly f, poly g) "USAGE: modd(f,g); f,g polynomials RETURN: poly, f mod g division with remainder NOTE: called from idealsimplify where it is used to modify the generating set of an ideal" { poly result=f-(f/g)*g; return(result); } ////////////////////////////////////////////////////////////////////// proc removepower (ideal I) "USAGE: removepower(I); I ideal SEE ALSO:idealsimplify RETURN: ideal defining the same zeroset as I: if any generator of I is a power of one single variable, replace it by the respective variable EXAMPLE: example removepower; shows an example" { int i,j; int divisornumber=0; int pos; I=simplify(I,6); // remove 0 and multiple generators for(j=1;j<=ncols(I);j++) { if(size(I[j])==1) // test if generators are powers { // of variables... for(i=1;i<=nvars(basering);i++) { if(modd(I[j],var(i))==0) { divisornumber++; pos=i; } } } if(divisornumber==1) // ...if so, replace by variable { I[j]=var(pos); } divisornumber=0; } return(I); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; ideal I = x3,y+z2-x2; I; removepower(I); } ////////////////////////////////////////////////////////////////////// proc idealsimplify (ideal I, int maxiter) "USAGE: idealsimplify(I,m); I ideal, m int ASSUME: procedure is stable for sufficiently large m RETURN: ideal defining the same zeroset as I: replace generators of I by the generator modulo other generating elements EXAMPLE: example idealsimplify; shows an example " { if(maxiter<1) {ERROR("The integer argument has to be positive!")} ideal comp; int iteration; int changed=0; int i,j,ci,n,cols; for(iteration=0;iteration=1;j--) // reduce with higher elements { for(i=n;i>j;i--) { if(I[i]!=0) { I[j]=modd(I[j],I[i]); } } } I=simplify(removepower(I),7); if (ncols(I)==ncols(comp)) //check if I has changed { cols=ncols(I); changed=0; for(ci=1;ci<=cols;ci++) { if (I[ci]!=comp[ci]) { changed=1; break; } } if (changed==0) break; } } return(I); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; ideal I = x3,y+z2-x2; I; idealsimplify(I,10); } ////////////////////////////////////////////////////////////////////// proc equalJinI (ideal I, ideal J) "USAGE: equalJinI(I,J); (I,J ideals) ASSUME: J contained in I and both I and J have been processed with idealsimplify before SEE ALSO: idealsimplify RETURN: 1, if I=J, 0 otherwise EXAMPLE: example equalJinI; shows an example" { int col=ncols(I); J=slimgb(J); int k; for(k=1;k<=col;k++) { if(reduce(I[k],J)!=0) { return(0);} } return(1); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; ideal I = x,y+z2; ideal J1= x; ideal J2= x,y+z2; equalJinI(I,J1); equalJinI(I,J2); } singular-4.0.3+ds/Singular/LIB/arr.lib000066400000000000000000003021731266270727000174310ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version arr.lib 4.0.2.0 Feb 2015 "; // $Id: da6cd859e2bb646dfdaa5235b8fc68962c7378b8 $ category="Miscellaneous"; /* ** TOPICS ** (Ctrl+f to search) #1 NEWSTRUCTS & OVERLOADS #2 CONSTRUCTORS #3 ACCESS & ASSIGNEMENT #4 DELETION #5 COMPERATORS #6 TYPE CASTING #7 INHERITED FUNCTIONS #8 PRINTING #9 MANIPULATING VARIABLES #10 CENTER COMPUTATIONS #11 GEOMETRIC CONSTRUCTIONS #11 EXAMPLES OF ARRANGEMENTS #13 ORLIK SOLOMON AND POINCARE POLYNOMIAL #14 FREENESS #15 MULTI-ARRANGEMENTS #16 COMBINATORICS */ info=" LIBRARY: arr.lib a library of algorithms for arrangements of hyperplanes AUTHORS: Randolf Scholz (rscholz@rhrk.uni-kl.de), Patrick Serwene (serwene@mathematik.uni-kl.de), Lukas Kuehne (lf.kuehne@gmail.com) OVERLOADS: // OPERATORS = arrAdd assignment + arrAdd union of two arrs [ arrGet access to a single/multiple hyperplane(s) - arrMinus deletes given hyperplanes from the arr <= arrLEQ comparison >= arrGEQ comparison == arrEQ comparison != arrNEQ comparison < arrLNEQ comparison > arrGNEQ comparison // TYPECASTING matrix arr2mat coeff matrix poly arr2poly defining polynomial // OTHER variables arrVariables ideal generated by the variables the arr depends on nvars arrNvars number of variables the arr depends on delete arrDelete deletes hyperplanes by indices print arrPrint prints the arr on the screen // IDEAL INHERITED FUNCTIONS homog arrHomog checks if arrangement is homogeneous simplify arrSimplify simplifies arrangement size arrSize number of planes subst arrSubst substitute variables // MULTI-ARRANGEMENTS = multarrAdd assignement of multarr + multarrAdd union of multarr poly multarr2poly defining polynomial size multarrSize number of hyperplanes with mult. print multarrPrint displays multiarr delete multarrDelete deletes hyperplane PROCEDURES: arrSet(arr A, int k, poly p) replaces the k-th Hyperplane with poly p type2arr(#) converts general input to 'arr' using arrAdd. mat2arr( matrix M) affine arrangement from coeff matrix mat2carr(matrix M) central arrangement from coeff matrix arrPrintMatrix(arr A) readable output as a coeff matrix varMat(intvec v) matrix of the corresponding ring_variables varNum(def u) number of given variable (enh. version of varNum in dmod.lib) arrSwapVar(arr A, i, j) swaps two variables in the arrangement arrLastVar(arr A) ring_variable of largest index used in arrangement arrCenter(arr A) computes center of an arrangement arrCentral(arr A) checks if arrangement is central arrCentered(arr A) checks if arrangement is centered arrCentralize(arr A) makes centered arrangement central arrCoordChange(A, T, #) performs coordinate change arrCoordNormalize(A, v) performs projection onto coordinate hyperplane arrCone(arr A, var) coned arrangement arrDecone(arr A, int k) deconed arrangement arrLocalize(arr A, intvec v) localization of an arrangement onto a flat arrRestrict(arr A, intvec v) restricted arrangement onto a flat arrIsEssential(arr A) checks if arrangement is essential arrEssentialize(arr A) essentialized arragnement arrBoolean(int v) boolean arrangement arrBraid(int v) braid arrangement arrTypeB(int v) type B arrangement arrTypeD(int v) type D arrangement arrRandom(d,m,n) random (affine) arrangement arrRandomCentral(d,m,n) random central arrangement arrEdelmanReiner() Edelman-Reiner arrangement arrOrlikSolomon(arr A) Orlik-Solomon algebra of the arrangement arrDer(A) module of derivation arrIsFree(A) checks if arrangement is free arrExponents(A) exponents of a (free) arrangement arr2multarr(arr A, intvec v) converts normal arrangement to multiarrangement multarr2arr(multarr A) converts multiarrangement to normal arrangement multarrRestrict(arr A, v) restriction of A (as arr) to a flat with multiplicities multarrMultRestrict(A, int k) restriction of A (as multarr) to a hyperplane with multiplicities arrFlats(arr A) intersection lattice arrLattice(arr A) computes the intersection lattice / poset moebius(arrposet P) computes moebius values arrCharPoly(arr A) characteristic polynomial arrPoincare(arr A) poincare polynomial of the arrangement arrChambers(arr A) number of chambers of the arrangement arrBoundedChambers(arr A) number of bounded chambers of the arrangement printMoebius(arr A) displays the moebius values of all the flats in the poset "; //============================================================================// //-------------------------- #1 NEWSTRUCTS & OVERLOADS -----------------------// //============================================================================// // initialization of the library static proc mod_init() { // NEWSTRUCTS newstruct("arr","ideal l"); newstruct("flat", "intvec REL, int moebius, intvec parents, int flag"); newstruct("arrposet","arr A, list r"); newstruct("arrflats","arr A, list r"); newstruct("multarr","ideal l, intvec m"); // intvec: multiplicities of hyperplanes // OPERATORS system("install","arr","=" ,arrAdd ,1); // assignment system("install","arr","+" ,arrAdd ,2); // union of arrs system("install","arr","[" ,arrGet ,2); // access system("install","arr","-" ,arrMinus ,2); // delete plane system("install","arr","<=" ,arrLEQ ,2); // comparison system("install","arr",">=" ,arrGEQ ,2); // comparison system("install","arr","==" ,arrEQ ,2); // comparison system("install","arr","!=" ,arrNEQ ,2); // comparison system("install","arr","<" ,arrLNEQ ,2); // comparison system("install","arr",">" ,arrGNEQ ,2); // comparison // TYPECASTING system("install","arr","matrix" ,arr2mat ,1); // coeff matrix system("install","arr","poly" ,arr2poly ,1); // defining polynomial system("install","arr","list" ,arr2list ,1); // list of defining polynomials system("install","arr","ideal" ,arr2ideal ,1); // list of defining polynomials // OTHER system("install","arr","variables" ,arrVariables ,1); system("install","arr","nvars" ,arrNvars ,1); system("install","arr","delete" ,arrDelete ,2); system("install","arr","print" ,arrPrint ,1); // IDEAL INHERITED FUNCTIONS system("install","arr","homog" ,arrHomog ,1); // checks if homogeneous system("install","arr","homog" ,arrHomog ,2); // checks if homogeneous system("install","arr","simplify" ,arrSimplify ,2); // simplifies arrangement system("install","arr","size" ,arrSize ,1); // number of planes system("install","arr","subst" ,arrSubst ,4); // substitute variables // MULTI-ARRANGEMENTS system("install","multarr","=" ,multarrAdd ,1); // assignement of multarr system("install","multarr","+" ,multarrAdd ,2); // union of multarr system("install","multarr","poly" ,multarr2poly ,1); // defining polynomial system("install","multarr","size" ,multarrSize ,1); // number of hyperplanes with mult. system("install","multarr","print" ,multarrPrint ,1); // displays multiarr system("install","multarr","delete" ,multarrDelete ,2); // deletes hyperplane // COMBINATORICS system("install","arr","rank" ,arrRank ,1); system("install","arrflats","print" ,arrPrintFlats ,1); system("install","arrposet","print" ,arrPrintPoset ,1); // NEEDED LIBRARIES LIB "general.lib"; LIB "monomialideal.lib"; } //============================================================================// //--------------------------- #2 CONSTRUCTORS --------------------------------// //============================================================================// // general method for creating arrangements static proc arrAdd "USAGE: A = #; A +#; # list containing arr/ideal/list/matrix/poly RETURN: [arr] Arrangement constructed by input parameters. REMARKS: The algorithm splits up the list # and uses the appropiate procedure to handle the input. NOTE: arrAdd simplifies certain inputs, for example A = (x,y,2x); gives the same arrangement as A = (x,y); SEE ALSO: arrAdd, type2arr KEYWORDS: arrangement; equal; constructor; operator EXAMPLE: example arrAdd; shows an example" { arr A; for(int k=1; k<=size(#); k++){ while(1){ //simulates switch, which singular doesn't offer if(typeof(#[k]) == "arr" ){A = arrAddArr (A, #[k]);break;} if(typeof(#[k]) == "poly" ){A = arrAddPoly (A, #[k]);break;} if(typeof(#[k]) == "ideal" ){A = arrAddIdeal (A, #[k]);break;} if(typeof(#[k]) == "matrix"){A = arrAddMatrix(A, #[k]);break;} if(typeof(#[k]) == "intmat"){A = arrAddMatrix(A, #[k]);break;} if(typeof(#[k]) == "list" ){A = arrAdd ( #[k]);break;} ERROR("bad input type"); } } return (A); } example { "EXAMPLE: Creating a few arrangements"; echo = 2; ring R = 0,(x,y,z),dp; arr A= ideal(x,y,z); A; arr B = A + ideal(x+1, x-1); B; arr C = list(A, x+1, x-1); C; arr D = x2 - y2; D; } // union of two arrangements static proc arrAddArr(arr A, arr B){ return (arrAddIdeal(A, B.l)); } // adds a single poly to the arrangement // if the poly is linear, it is just added, otherwise Singular factorizes static proc arrAddPoly(arr A, poly p){ if(deg(p) == 0){ ERROR("Given poly is not linear or Singluar is not able to factorize it");} else{ if(deg(p) == 1){ A.l = A.l + p; return (A); } else{ ideal I = factorize(p,1); if(size(I) == 1){ERROR("Given poly is not a hyperplane");} else{ return (arrAdd(A,I)); } } } return(A); } // adds defining polys to the arrangement static proc arrAddIdeal(arr A, ideal I){ for(int k=1; k<=size(I); k++){ A = arrAddPoly(A,I[k]); } return (A); } // adds defining polys to the arrangement static proc arrAddMatrix(arr A, matrix M){ return ( arrAddArr(A,mat2arr(M)) ); } //============================================================================// //--------------------------- #3 ACCESS & ASSIGNEMENT ------------------------// //============================================================================// // access to hyperplanes, overloads [] operator static proc arrGet(arr A, intvec v) "USAGE: A[v]; v int/intvec RETURN: [poly] if v is [int] The defining poly of the the v-th hyperplane+ [arr] if v is [intvec] The corresponing subarrangement SEE ALSO: arrGet, arrSet KEYWORDS: arrangement; get; operator EXAMPLE: example arrGet; shows an example" { if(size(v) == 1){ return (A.l[v[1]]); } //returns poly if v is integer ideal I = A.l; A = ideal(I[v]); return (A); } example { "EXAMPLE: "; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x,y,z); A[2]; intvec v = 1,3; A[v]; } // replaces the k-th plane with poly p proc arrSet(arr A, int k, poly p) "USAGE: arrSet(A, k, p); arr A, int k, poly p; RETURN: [arr] Arrangement where the k-th hyperplane is replaced by p. NOTE: p must be linear KEYWORDS: arrangement; hyperplane; assign; set EXAMPLE: example arrSet; shows an example" { if(deg(p) != 1){ERROR("Given poly is not a hyperplane");} else{ // looks akward but needs to be done this way ideal I = A.l; I[k] = p; A = I; } return (A); } example { "EXAMPLE: "; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x,y,z); arrSet(A,1,x+1); } //============================================================================// //------------------------------- #4 DELETION --------------------------------// //============================================================================// // deletes all hyperplanes of the given indices static proc arrDelete(arr A, intvec v) "USAGE: delete(A, v); v integer/intvec RETURN: [arr] Arrangement A without the hyperplanes given by v; NOTE: for deleting hyperplanes via polynomials, use arrMinus instead SEE ALSO: arrDelete, arrMinus KEYWORDS: arrangement; delete EXAMPLE: example arrDelete; shows an example" { int i = 0; int k; int n = size(A); intvec u = 1..n; // puts 0 in u for every element that needs to be deleted // is done this way to deal with the case that the user gives the same index multiple times. for(k=1; k<=size(v); k++){ if(u[v[k]] != 0){ u[v[k]] = 0; i++; } // i = #elts that need to be deleted } if( i == n){return (emptyArr); } // create intvec of the remaining indices v = 1..(n-i); i=1; for(k=1; k<=n; k++){ if(u[k] != 0) { v[i] = u[k]; i++; } } arr A' = arrGet(A,v); return (A'); } example { "EXAMPLE: "; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x,y,z); delete(A,2); intvec v = (1,3); delete(A,v); } // deletes hyperplanes, overloads - operator static proc arrMinus "USAGE: A - #; # list containing arr/ideal/list/matrix/poly RETURN: [arr] arrangement A without the hyperplanes of the arrangement defined by #. REMARKS: algorithm creates an arrangement B from # using arrAdd and then deletes hyperplanes which occur in both A and B. NOTE: The alorithm does not simplify by scalars, i.e. some hyperplanes might not be deleted. See example. SEE ALSO: arrDelete, arrMinus KEYWORDS: arrangement; delete; operator EXAMPLE: example arrMinus; shows an example" { if(typeof(#[1]) != "arr"){ERROR("First input must be arr!");} arr A = #[1]; arr B = #[2..size(#)]; // collects hyperplanes to be deleted list L; int k, l; for(k=1; k<=size(A); k++){ // create list of hyperplanes to be deleted for(l=1; l<=size(B); l++){ if(A[k] == B[l]){L = insert(L,k);} } } l = size(L); // transforms list to intvec if(l != 0){ intvec v = 1..l; for(k=1; k<=l; k++){v[k] = L[k];} A = delete(A,v); } return (A); } example { "EXAMPLE: "; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x,y,z); A - ideal(x,y); A - poly(2x); } //============================================================================// //------------------------------- #5 COMPERATORS -----------------------------// //============================================================================// // returns logical value of 'A<=B' static proc arrLEQ(arr A, arr B) "USAGE: A<=B; A,B arr RETURN: [0,1] true if A is a subarrangement of B NOTE: algorithm is based on arrMinus and does not simplify by scalars, hence some technically equal hyperplanes might not be detected. See example. SEE ALSO: arrLEQ, arrLNEQ, arrGEQ, arrGNEQ, arrEQ, arrNEQ KEYWORDS: comparison; subarrangement; operator EXAMPLE: example arrLEQ; shows an example" { arr C = A - B; if(C[1] == 0){ return (1); } return (0); } example{example arrEQ;} // returns logical value of 'A>=B' static proc arrGEQ(arr A, arr B) "USAGE: A>=B; A,B arr RETURN: [0,1] true if B is a subarrangement of A NOTE: algorithm is based on arrMinus and does not simplify by scalars, hence some technically equal hyperplanes might not be detected. See example. SEE ALSO: arrLEQ, arrLNEQ, arrGEQ, arrGNEQ, arrEQ, arrNEQ KEYWORDS: comparison; subarrangement; operator EXAMPLE: example arrLEQ; shows an example" { arr C = B - A; if(C[1] == 0){ return (1); } return (0); } example{example arrEQ;} // returns logical value of 'A==B' static proc arrEQ(arr A, arr B) "USAGE: A==B; A,B arr RETURN: [0,1] true if A equals B NOTE: algorithm is based on arrMinus and does not simplify by scalars, hence some technically equal hyperplanes might not be detected. See example. SEE ALSO: arrLEQ, arrLNEQ, arrGEQ, arrGNEQ, arrEQ, arrNEQ KEYWORDS: comparison; equal; operator EXAMPLE: example arrLEQ; shows an example" { return ((A<=B) & (A>=B)); } example { "EXAMPLE: Relationships between a few arrangements."; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x,y,z); arr B = ideal(x,y); A<=B; A>=B; A==B; A!=B; AB; } // returns logical value of 'A!=B' static proc arrNEQ(arr A, arr B) "USAGE: A!=B; A,B arr RETURN: [0,1] true if A is not equal to B NOTE: algorithm is based on arrMinus and does not simplify by scalars, hence some technically equal hyperplanes might not be detected. See example. SEE ALSO: arrLEQ, arrLNEQ, arrGEQ, arrGNEQ, arrEQ, arrNEQ KEYWORDS: comparison; equal; operator EXAMPLE: example arrLEQ; shows an example" { return (!(A==B)); } example{example arrEQ;} // returns logical value of 'AB' static proc arrGNEQ(arr A, arr B) "USAGE: A>B; A,B arr RETURN: [0,1] true if B is a proper subarrangement of A NOTE: algorithm is based on arrMinus and does not simplify by scalars, hence some technically equal hyperplanes might not be detected. See example. SEE ALSO: arrLEQ, arrLNEQ, arrGEQ, arrGNEQ, arrEQ, arrNEQ KEYWORDS: comparison; subarrangement; operator EXAMPLE: example arrLEQ; shows an example" { return ((A>=B) & (A!=B)); } example{example arrEQ;} //============================================================================// //------------------------------ #6 TYPE CASTING -----------------------------// //============================================================================// // TYPE => ARRANGEMENT proc type2arr(list #) "USAGE: type2arr(#); # def RETURN: [arr] Arrangement defined by the input NOTE: The procedure tries to cast the input to [arr] using arrAdd KEYWORDS: typecasting; arrangement EXAMPLE: example tye2arr; shows an example" { return (arrAdd(#)); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; ideal I = x,y,z; typeof(type2arr(I)); } // ARRANGEMENT => POLY static proc arr2poly(arr A) "USAGE: poly(A); arr A RETURN: [poly] The defining polynomial which is the product of polynomials occuring in arr NOTE: The procedure will automatically simplify the polynomial by scalar multiplication. SEE ALSO: arrAdd, arr2poly, arr2mat, arr2list, arr2ideal, type2arr KEYWORDS: typecasting; defining polynomial EXAMPLE: example arr2poly; shows an example" { poly f = simplify(product(A.l),1); if(f == 0){ return (1); } return (f); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x+1, 2x-2, y); arr2poly(A); } // ARRANGEMENT => LIST static proc arr2list(arr A) "USAGE: arr2list(A); A arr RETURN: [list] containing all generators of A SEE ALSO: arrAdd, arr2poly, arr2mat, arr2list, arr2ideal, type2arr KEYWORDS: typecasting; list EXAMPLE: example arr2list; shows an example" { int n = size(A); list L; for(int k=1; k<=n; k++){L[k] = A[k];} return (L); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; arr A= ideal(x,y,z); arr2list(A); } // ARRANGEMENT => IDEAL static proc arr2ideal(arr A) "USAGE: arr2ideal(A); A arr RETURN: [ideal], the internal ideal of A NOTE: arr2ideal(A); is the same as A.l - which may become private SEE ALSO: arrAdd, arr2poly, arr2mat, arr2list, arr2ideal, type2arr KEYWORDS: typecasting; ideal EXAMPLE: example arr2ideal; shows an example" { return (A.l); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x,y,z); arr2ideal(A); } // ARRANGEMENT => MATRIX static proc arr2mat(arr A, list #) "USAGE: matrix(A); A arr matrix(A, 'c') for central arrangements (shorter matrix) RETURN: [matrix] M = [T|b] representing the arrangement NOTE: If the arrangement is central or one is not interested in the const terms one can use "matrix(A, 'c')" instead to get the same matrix without the last column. SEE ALSO: arr2mat, mat2arr, mat2carr KEYWORDS: typecasting; matrix; coefficient EXAMPLE: example arr2mat;" { matrix M = jacob(A.l); if(size(#) == 0){return ( concat(M, transpose(jet(A.l,0))) );} if(#[1] == 'c'){return (M);} ERROR("Bad optional input parameter!") } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x,y,z); arr D = ideal(x+1, y-2, z, x+y+4); print(arr2mat(A)); print(arr2mat(D)); } // MATRIX => ARRANGEMENT proc mat2arr(matrix M) "USAGE: mat2arr(M); matrix (M|b) RETURN: [arr] interprets the rows of the matrix as the defining polynomial equations of the arrangement where the last column will be considered as the constant terms, i.e. if M is an m*(n+1) matrix we have H_i = Ker( M_i1*x_1 +...+ M_in*x_n + M_i(n+1) ) for i=1...m and A = {H_1,...,H_m} the resulting arrangement. SEE ALSO: mat2carr KEYWORDS: typecasting; matrix; coefficient EXAMPLE: example mat2arr;" { if(ncols(M) > nvars(basering)+1) { ERROR("Matrix too big! Please add variables to basering."); } int n = ncols(M)-1; matrix X[n+1][1]; X[1..n,1] = varMat(1..n); X[n+1 ,1] = 1; arr A = ideal(M*X); return(A); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; matrix M[4][4] = 1,0,1,1,1,1,0,2,0,1,1,3,2,1,1,4; print(M); mat2arr(M); } // MATRIX => ARRANGEMENT (central) proc mat2carr(matrix M) "USAGE: mat2carr(M); matrix M RETURN: [arr] interprets the rows of the matrix as the defining polynomial equations of the arrangement. I.e. if M is an m*n matrix we have H_i = Ker( M_i1*x_1 +...+ M_in*x_n) for i=1...m and A = {H_1,...,H_m} the resulting arrangement. SEE ALSO: mat2arr KEYWORDS: typecasting; matrix; coefficient; central EXAMPLE: example mat2carr;" { if( ncols(M) > nvars(basering) ){ ERROR("Error! not enough variables in the basering."); } arr A = ideal(M*varMat(1..ncols(M))); return(A); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; matrix M[4][3] = 1,0,1,1,1,0,0,1,1,2,1,1; print(M); mat2carr(M); } //============================================================================// //---------------------------- #7 IDEAL FUNCTIONS ----------------------------// //============================================================================// // checks if A is central, homogenizes static proc arrHomog(arr A, list #) "USAGE: homog(A); arr A homog(A, p); arr A, ring_variable p RETURN: [0,1] homog(A) is the same as arrCentral(A) [arr] homog(A,p) homogenizes A with respect to p NOTE: homog(A,p) is not the same as arrCone(A,p) as it does not add the additional hyperplane SEE ALSO: arrHomog, arrCentral, arrCone KEYWORDS: central; homogenize EXAMPLE: example arrHomog; shows an example" { if(size(#) == 0){ return (homog(A.l)); } if(size(#) == 1){ A = homog(A.l, #[1]); return (A); } ERROR("Too many innput arguments!"); } example { "EXAMPLE: "; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x,y); arr B = ideal(x,y,x+y+1); homog(A); homog(B); homog(B,z); homog(_); } // simplified arrangement static proc arrSimplify(arr A, list #) "USAGE: arrSimplify(A); simplify(A, n); arr A, int n RETURN: [arr] simplified arrangement. NOTE: arrSimplify(A) is the same as simplify(A, 1), simplify with higher ints is not needed SEE ALSO: arrSimplify KEYWORDS: simplify EXAMPLE: example arrSimplify; shows an example" { if(size(#) == 0){ A = simplify(A.l, 1); return (A); } if(size(#) == 1){ A = simplify(A.l, #[1]); return (A); } ERROR("Too many input arguments!"); } example { "EXAMPLE: "; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(2x,2y-1,2z-2); arrSimplify(A); } // number of hyperplanes static proc arrSize(arr A) "USAGE: size(A); arr A; RETURN: [int] number of hyperplanes in the arangement NOTE: size(A) also useable for multi-arrangements SEE ALSO: arrSize, multarrSize KEYWORDS: hyperplanes; size; number EXAMPLE: example arrSize; shows an example" { return (size(A.l)); } example { "EXAMPLE: "; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x,y,z); size(A); } // substitute variables static proc arrSubst(arr A, list #) "USAGE: arrSubst(A, #); arr A, ring_variables/integers i,j; RETURN: [arr] with the corresponding substitutions made NOTE: applies 'subst' on the arrangement SEE ALSO: arrSubst KEYWORDS: variables; ring_variable; substitute EXAMPLE: example arrSubst; shows an example" { if(size(#)%2 != 0){ ERROR("Odd number of parameter inputs!"); } for(int i=1; ia+b)=> (a+b|b) =(b->b-a)=> (b|b-a) =(a->b-a)=> (b|a) A = subst(A.l, u, u+v); A = subst(A.l, v, v-u); A = subst(A.l, u, v-u); return (A); } example { "EXAMPLE: "; echo = 2; ring R = 0,(x,y,z),lp; arr A = ideal(x+1,x+y,z); arrSwapVar(A,x,z); } //ring_variable of largest index used in arrangement proc arrLastVar(arr A) "USAGE: arrLastVar(A); arr A RETURN: [int] number of the last variable A uses NOTE: useful if you want a list containing all variables x_1 ... x_k used in A, but you do not want to skip any like variables(A) does. SEE ALSO: varMat, varNum, arrSwapVar, arrLastVar KEYWORDS: variables; ring_variable EXAMPLE: example arrLastVar; shows an example" { return ( rvar(variables(A)[arrNvars(A)]) ); } example { "EXAMPLE: "; echo = 2; ring R = 0,x(1..10),dp; arr A = ideal(x(1), x(2), x(3), x(6)); int n = arrLastVar(A); varMat(1..n); variables(A); } //============================================================================// //--------------------------- #10 CENTER COMPUTATIONS ------------------------// //============================================================================// // checks if arr is central proc arrCentral(arr A) "USAGE: arrCentral(A); arr A RETURN: [0,1] true if arr is central(i.e. all planes intersect in 0) NOTE: This is the same as homog(A) SEE ALSO: arrCentered, arrCentral, arrCenter, arrCentralize KEYWORDS: center; central EXAMPLE: example arrCentral;" { return (homog(A)); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; // centered and central arr A = ideal(x,y,z); arrCentered(A); arrCentral(A); // centered but not central (center: (-1,-1/2, 1)) arr B = ideal(x+1,2y+1,-z+1); arrCentered(B); arrCentral(B); } // checks wether arrangement has a center proc arrCentered(arr A) "USAGE: arrCentered(A); arr A RETURN: [0,1] true if A is centered(i.e. intersection of all planes not empty) NOTE: The algorithm uses the rank of matrix: Ax=b has a solution iff rank(A) = rank(A|b) SEE ALSO: arrCentered, arrCentral, arrCenter, arrCentralize KEYWORDS: center EXAMPLE: example arrCentered;" { matrix M = matrix(A); // classic test: Ax=b has a solution if and only if rank(A|b) == rank(A) if( rank(M) == rank(submat(M,1..nrows(M), 1..ncols(M)-1))){ return (1); } return (0); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; arr A= ideal(x,y,x-y+1); // centerless arrCentral(A); arr B= ideal(x,y,z); // central with center being the origin arrCentral(B); arr C= ideal(x+1,2y+1,-z+1); // central with center (-1,-1/2, 1) arrCentral(C); } // computes center of an arrangement proc arrCenter(arr A) "USAGE: arrCenter(A); arr A RETURN: [list] L entry 0 if A not centered or entries 1, x, H, where x is any particular point of the center and H is a matrix consisting of vectors which spanning linear intersection space. If there is exactly one solution, then H = 0. NOTE: The intersection of all hyperplanes can be expressed in forms of a linear system Ax=b, where (A|b) is the coeff. matrix of the arrange- ment, which is then solved using L-U decomposition SEE ALSO: arrCentered, arrCentral, arrCenter, arrCentralize KEYWORDS: center EXAMPLE: example arrCenter;" { matrix M = matrix(A); //return matrix (T|b) matrix T = submat(M, 1..nrows(M), 1..ncols(M)-1); matrix b = submat(M, 1..nrows(M), ncols(M))*(-1); list L = ludecomp(T); list Q = lusolve(L[1], L[2], L[3], b); return (Q); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; arr A= ideal(x,y,x-y+1); // centerless arrCenter(A); arr B= ideal(x,y,z); // center is a single point arrCenter(B); arr C= ideal(x,z,x+z); // center is a line // here we get a wrong result because the matrix is simplified since A doesn't // contain any "y" the matrix (A|b) will be 3x3 only. arrCenter(C); } // makes centered arrangement central proc arrCentralize(arr A) "USAGE: arrCenteralize(A); arr A RETURN: [arr] A after centralization via coordinate change NOTE: The coordinate change only does translation, vector of translation is the second output of arrCenter SEE ALSO: arrCentered, arrCentral, arrCenter, arrCentralize KEYWORDS: central; center; coordinate change EXAMPLE: example arrCenter;" { if(arrCentral(A)){ print("The arrangement is already central!"); return (); } list L = arrCenter(A); if(L[1] == 0){ print("The arrangement has no center and therefor cannot be centralized!"); return (); } int n = nvars(basering); matrix T = diag(1,n); matrix c = L[2]; A = arrCoordChange(A, T, c); return (A); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; arr A = ideal(x-1,y,x-z-1,x-z-1); arrCentralize(A); } //============================================================================// //------------------------ #11 GEOMETRIC CONSTRUCTIONS -----------------------// //============================================================================// // performs coordinate change proc arrCoordChange(arr A, matrix T, list #) "USAGE: arrCoordChange(A, T); arr A, (m*n mat) n*n or n*n+1 matrix T arrCoordChange(A, T , c); arr A, n*n matrix T, n*1 matrix/vector RETURN: [arr]: Arrangement A [A|b] after a coordinate change f: x -> Tx + c with T invertible i.e. [A|b] => [AT^-1|b+AT^-1c] since we have f(H) = f(ker(a1*x1 + ... + an*xn - b)) = {f(x) : a'x -b = 0} = {y : a'f^-1(y) -b = 0)} = {y : a'(T^-1(y-c)) - b = 0} = {y : a'T^-1y -(b + a'T^-1c) = 0} NOTE: There are 3 options how you can give the input (in each case n <= nvars(basering)) 1. Just a nxn matrix with => Will automatically complete T by a unit matrix and perform x -> Tx 2. A nxn matrix T and a nx1 vector/matrix c with => Will automatically complete T and c and perform x -> Tx +c 3. A nxn+1 matrix T with => will use last column as translation vector c SEE ALSO: arrCoordChange, arrCoordNormalize KEYWORDS: coordinate change EXAMPLE: example arrCoordChange; shows an example" { int n = nvars(basering); int k = nrows(T); int l = ncols(T); matrix c; if( k>n || l-1>n ){ ERROR("Matrix too big! (It has more cols/rows than there are variables.)"); } // const vector integrated in matrix => split [T|c] into T and c if( l == k+1 ){ if(size(#) > 0){ ERROR("Bad input. If given a constant vector the matrix must be square!") } c = submat(T, 1..k, l); T = submat(T, 1..k, 1..k); l=k; } if( l != k || rank(T) != k){ ERROR("Given matrix is not a base change matrix.") } if(size(#) > 0){ if(size(#) >= 2){ERROR("Too many input arguments!");} c = matrix(#[1]); if(nrows(c) > n || ncols(c) > 1){ ERROR("Constant vector maldefined. Dimension too big.") } } matrix M[n][n] = diag(1,n); M[1..k,1..k] = T; T = M; T = luinverse(T)[2]; M = jacob(A.l); matrix b[n][1]; b[1..nrows(c),1] = c; c = b; // gives c the right length. b = transpose(jet(A.l, 0)); // constants b = b - M*T*c; M = M*T; A = mat2arr(concat(M,b)); return(A); } example { "EXAMPLE: "; echo =2; ring r = 0,(x,y,z),lp; arr A = x,y,z; arrCoordChange(A,1,[0,0,1]); //lifts z-hyperplane by 1 unit matrix T[2][2] = [0,1,1,0]; // swaps x and y arrCoordChange(A,T); matrix c[2][1] = [1,0]; T = concat(T,c); // now swap x and y and add 1 to x afterwards arrCoordChange(A,T); // Note how T doesn't even need to be a full 3x3 base change matrix. } // performs projection onto coordinate hyperplanes proc arrCoordNormalize(arr A, intvec v) "USAGE: arrCoordChange(A, v); RETURN: [arr]: Arrangement after a coordinate change that transforms the arrangement such that after a tranformation x -> Tx + c we have the arrangement has the matrix representation [AT^-1|b+AT^-1c] such that [AT^-1]_v = I and [b+AT^-1c]_v = 0; NOTE: algorith performs a base change if H_k is homogenous (i.e. has no) constant term and an affine transformation otherwise Ax+b = 0, Transformation x = Ty+c: AT^-1y + AT^-1c + b = 0 Now we want to have (AT^-1)_v = I and (AT^-1c +b)_v = AT^-1_v*c + b_v = 0 SEE ALSO: arrCoordChange, arrCoordNormalize KEYWORDS: coordinate change EXAMPLE: example arrCoordChange; shows an example" { int n = nvars(basering); if(size(v) > n){ ERROR("Too many rows chosen, at max you can choose "+string(n)); } matrix M = matrix(A); matrix Av[n][n]; matrix bv[n][1]; Av[1..size(v), 1..n] = submat(M,v,1..n); bv[1..size(v),1] = submat(M,v, n+1); if(rank(Av) != n){ if(rank(Av) != size(v)){ ERROR("Normal vectors of the given hyperplanes are not linearily " + "independent. Cannot perform coordinate change!"); } // Adds linearly independent lines to Av in order to make it invertible module F = freemodule(n); module Add = reduce(F,std(transpose(Av))); Add = transpose(simplify(transpose(Add),2)); Av[(size(v)+1)..n, 1..n] = matrix(Add); } if(rank(Av) != n){ERROR("Av not invertible!");} A = arrCoordChange(A,Av,bv); return (A); } example { "EXAMPLE: "; echo=2; ring r = 0,(x,y,z),lp; arr A = ideal(x,y,z,x+z+4); intvec v = 1,2,4; arrCoordNormalize(A,v); } // coned arrangement proc arrCone(arr A, list #) "USAGE: arrCone(A); arrCone(A, ring_variable); arr A arrangement in variables x_1...x_n; RETURN: arr, the coned hyperplane Arrangement cA with respect to the given ring_variable, or the last ring_variable if none was given. NOTE: The hyperplanes are homogenized w.r.t. v and a new hyperplane H = ker(x_n+1) is added. SEE ALSO: arrCone, arrDecone, arrRestrict, arrIsEssential, arrEssentialize KEYWORDS: cone; decone EXAMPLE: example arrCone; shows an example" { poly p; int i; // case 1: no ring_variable given if(size(#) == 0){ p = var(nvars(basering)); } // case 2: a ring_variable is given else{ p = #[1]; } // computation A = homog(A, p); A = A + p; return(A); } example { "EXAMPLE: Coning the arrangement A = (x+1, y) alongside x, y and z:"; echo=2; ring R = 0,(x,y,z),dp; arr A = ideal(x+1, x,x-2,x-1); arrCone(A, y); arr B= ideal(x,y,x+y-1); arrCone(B); } // deconed arrangement proc arrDecone(arr A, int k) "USAGE: arrDecone(A, k); arrangement A, integer k; RETURN: arr: the deconed hyperplane Arrangement dA NOTE: A has to be non-empty and central. arrDecone is an inverse operation to arrCone since A == arrDecone(arrCone(A),size(A)+1) for any A. One can also decone a central arrangement with respect to any hyper- plane k, but than a coordinate change is necessary to make H_k = ker(x_k). Since such a coordinate change is not unique, use arrCoordchange to do so. SEE ALSO: arrCone, arrDecone, arrRestrict, arrIsEssential, arrEssentialize KEYWORDS: cone; decone EXAMPLE: example arrDecone; shows an example" { if( !arrCentral(A) ){ ERROR("Non-central arrangement can not be deconed!");} if( size(A) == 0){ ERROR("Empty arrangement can not be deconed!");} if( size(A) < k){ ERROR("There is no k-th hyperplane");} poly p = A[k]; int n = rvar(p); if( n == 0 ){ ERROR("H_" + string(k) + " = " + string(p) + " is not of the form ker(x_i). Please do a coordinate change first." + "You can use arrCoordinateChange to transform the arrangement accordingly."); } A = A - p; A = arrSubst(A, p, 1); return(A); } example { "EXAMPLE: We decone arr consisting of (x,y,x+z) with respect to y"; echo = 2; ring R = 0,(x,y,z),dp; arr A= ideal(x,y,z,x+y-z); arrDecone(A,3); } proc arrLocalize(arr A, intvec v) "USAGE: arrLocalize(A, v); arrangement A, intvec v; RETURN: arr: the localized arrangement A_X, i.e. A_X only contains the hyperplanes which contain the flat X, which is defined by the equations A[v] SEE ALSO: arrCone, arrDecone, arrRestrict, arrIsEssential, arrEssentialize KEYWORDS: localization EXAMPLE: example arrLocalize; shows an example" { ideal I=std(arr2ideal(A[v])); arr L; int k; for(k=1; k nvars(basering)){ return("Error, too few variables or too high dimension"); } intmat M = random(d,m,n+1); arr A = mat2arr(M); return(A); } example { "EXAMPLE:"; echo = 2; ring R = 0,x(1..20),dp; arrRandom(7,3,15); } // random central arrangement proc arrRandomCentral(int d, int m, int n) "USAGE: arrRandomCentral(d,m,n); int d,m,n RETURN: Random central arrangement, where m is the number of hyperplanes, n the dimension, d the upper bound for absolute value of coefficients. SEE ALSO: arrBoolean, arrBraid, arrTypeB, arrTypeD, arrRandom, arrEdelmanReiner KEYWORDS: example; random; central EXAMPLE: example arrRandomCentral;" { if(n > nvars(basering)){ return("Error, too few variables or too high dimension"); } intmat M = random(d,m,n); arr A = mat2carr(M); return(A); } example { "EXAMPLE:"; echo = 2; ring R = 0,x(1..20),dp; arrRandomCentral(7,3,15); } // Edelman-Reiner arrangement proc arrEdelmanReiner() "USAGE: arrEdelmanReiner(); RETURN: the Edelman-Reiner arrangement, which is a free arrangement but the restriction to the 6-th hyperplane is nonfree. (i.e. counterexample for Orlik-Conjecture) NOTE: the active ring must have at least five variables SEE ALSO: arrBoolean, arrBraid, arrTypeB, arrTypeD, arrRandom, arrEdelmanReiner KEYWORDS: example; Edelman-Reiner EXAMPLE: example arrEdelmanReiner;" { if(nvars(basering) < 5){ ERROR("not enough variables"); } arr arrER = arrBoolean(5); int a,b,c,d; for(a=1; a<=2; a++){ for(b=1; b<=2; b++){ for(c=1; c<=2; c++){ for(d=1; d<=2; d++){ arrER = arrER + (var(1)+(-1)^a*var(2)+(-1)^b*var(3)+(-1)^c*var(4)+(-1)^d*var(5)); }}}} return(arrER); } example { "EXAMPLE:"; echo = 2; ring r=0,x(1..5),dp; arrEdelmanReiner(); } //============================================================================// //--------------------- #13 Orlik Solomon and Poincare Poly ------------------// //============================================================================// // Orlik-Solomon algebra of the arrangement proc arrOrlikSolomon(arr A) "USAGE: arrOrlikSolomon(A); arr A RETURN: [ring] exterior Algebra E as ring with Orlik-Solomon ideal as attribute I. The Orlik-Solomon ideal is generated by the differentials of dependent tuples of hyperplanes. For a complex arrangement the quotient E/I is isomorphic to the cohomology ring of the complement of the arrangement. NOTE: In order to access this ideal I activate this exterior algebra with setring. SEE ALSO: arrOrlikSolomon KEYWORDS: Orlik-Solomon EXAMPLE: example arrOrlikSolomon;" { int central = arrCentral(A); // 0: non-central, 1: central if(central == 0){ A = arrCone(A); } module M = syz(A.l); M = jet(M,0); //Only use linear syzygies M = simplify(M,2); // drop zeros int n = ncols(A.l); def startRing = basering; ring R = 0,e(1..n),dp; def ER = Exterior(); setring ER; // defines the Exterioralgebra ideal I; //final orlik solomon ideal matrix X = transpose(varMat(1..n)); module M = fetch(startRing,M); //brings the module M to the Exterior Algebra ideal OSI = ideal(X*M); if(size(OSI) == 0){ // no relations among hyperplanes, I==0 export(I); return(basering); } // monomial subideal procedure due to Sorin Popescu ideal K = OSI; ideal J; while(isMonomial(K) == 0){ J = lead(std(K)); K = intersect(J,OSI); K = interred(K); } OSI = K; poly diffOp; //now applying the differential operator ideal vars; int j; for(int i=1; i<=ncols(OSI); i++) { vars = variables(OSI[i]); diffOp = 0; for(j=1; j<=ncols(vars); j++) { diffOp = diffOp+(-1)^(j+1)*vars[j]; } I = I + ideal( diff(diffOp,ideal(OSI[i])) ); } if(central ==0 ){//project back in the non-central case n = nvars(basering)-1; ring R = 0,e(1..n),dp; def ERDC = Exterior(); setring ERDC; ideal I = fetch(ER,I); } export(I); return (basering); } example { "EXAMPLE: Computing the Orlik-Solomon-Ideal for the D3-Arrangement"; echo = 2; ring R = 0,(x,y,z),dp; arr A = arrTypeB(3); def E = arrOrlikSolomon(A); setring E; //The generators of the Orlik-Solomon-Ideal are: I; } // The following 3 procedures were replaced by their faster combinatorical counterparts /* // poincare polynomial of the arrangement proc arrPoincare(arr A) "USAGE: arrPoincare(A); arr A RETURN: [intvec] The Poincare polynomial as integer vector of the arrangement, which is equal to the second kind Poincare-Series of the Orlik-Solomon Algebra. SEE ALSO: arrPoincare, arrChambers, arrBoundedChambers KEYWORDS: Poincare polynomial EXAMPLE: example arrPoincare;" { def startRing = basering; def Ext = arrOrlikSolomon(A); setring Ext; ideal OSI = lead(I); OSI = OSI + ideal(Ext); int n = nvars(Ext); ring suppRing = 0,x(1..n),dp; ideal I = fetch(Ext,OSI); intvec HP = hilb(std(I),2); return(HP); } example { "EXAMPLE: Computing the Poincare polynomial as intvec for the D3-Arrangement"; echo = 2; ring R = 0,(x,y,z),dp; arr A = arrTypeB(3); //The coefficients of the Poincare polynomial are: arrPoincare(A); } // number of chambers of the arrangement proc arrChambers(arr A) "USAGE: arrChambers(A); arr A RETURN: [int] The number of chambers of an arrangement, which is equal to the evaluation of the Poincare polynomial at 1. SEE ALSO: arrPoincare, arrChambers, arrBoundedChambers KEYWORDS: chambers EXAMPLE: example arrChambers;" { intvec HP = arrPoincare(A); intvec ones = 1:(size(HP)); return ( transpose(ones)*HP ); } example { "EXAMPLE: Computing the number of chambers for the D3-Arrangement"; echo = 2; ring R = 0,(x,y,z),dp; arr A = arrTypeD(3); //The number of chambers of the D3-Arrangement is: arrChambers(A); } // number of bounded chambers of the arrangement proc arrBoundedChambers(arr A) "USAGE: arrBoundedChambers(A); arr A RETURN: [int] The number of bounded chambers of an arrangement, which is equal to the evaluation of the Poincare polynomial at -1. SEE ALSO: arrPoincare, arrChambers, arrBoundedChambers KEYWORDS: chambers EXAMPLE: example arrBoundedChambers;" { intvec HP = arrPoincare(A); intvec altOnes; for(int i=1; i<=size(HP); i++){ altOnes[i] = (-1)^(i-1); } return ( transpose(altOnes)*HP ); } example { "EXAMPLE: Computing the number of chambers for the D3-Arrangement"; echo = 2; ring R = 0,(x,y,z),dp; arr A = arrTypeD(3); // The number of bounded chambers of the D3-Arrangement is: arrBoundedChambers(A); } */ //============================================================================// //------------------------------- #14 Freeness -------------------------------// //============================================================================// // module of derivation proc arrDer "USAGE: arrDer(A); arr A , multarr A RETURN: [module] The module Der(A) of derivations of the (multi-)arrangement A, i.e. the derivations tangent to each hyperplane of A (resp. with multiplicities) NOTE: This is only defined for central (multi-)arrangements SEE ALSO: arrDer, arrIsFree, arrExponents KEYWORDS: derivation; multiarrangement EXAMPLE: example arrDer;" { def A = #[1]; if( (typeof(A) != "arr") && ( typeof(A) != "multarr") ){ ERROR("bad input type!"); } if(homog(A.l) == 0){ ERROR("Arrangement not central!"); } module fA = jacob(A.l); ideal J; if( typeof(A) == "arr" ){ J = arr2ideal(A); } if(typeof(A) == "multarr"){ J = multIdeal(A); } module tA = diag(matrix(J)); module K = modulo(fA,tA); module derivations = lessGenerators(K); return (derivations); } example { "EXAMPLE: Computing the derivation module of the boolean and braid arrangement"; echo = 2; ring R = 0,(x,y,z),dp; arr A3 = arrBoolean(3); arr B3 = arrTypeB(3); arr G = ideal(x,y,z,x+y+z); //The derivation module of the Boolean 3-arrangement: arrDer(A3); //The derivation module of the Braid 3-arrangement: arrDer(B3); //The derivation module of the generic arrangement: arrDer(G); } // checks if arrangement is free proc arrIsFree(list #) "USAGE: arrIsFree(A); arr A, multarr A RETURN: [0,1] 1 if the (multi-)arrangement is free, i.e. Der(A) is a free module NOTE: only defined for central arrangements SEE ALSO: arrDer, arrIsFree, arrExponents KEYWORDS: free; multiarrangement EXAMPLE: example arrIsFree;" { def A = #[1]; module derivations = arrDer(A); return ( nvars(basering) == ncols(derivations) ); } example { "EXAMPLE: checking freeness of the Edelman-Reiner arrangement and its restriction: "; echo = 2; ring R = 0,(x,y,z),dp; arr A3 = arrBoolean(3); arr B3 = arrTypeB(3); arr G = ideal(x,y,z,x+y+z); arrIsFree(A3); arrIsFree(B3); arrIsFree(G); } // exponents of a (free) arrangement proc arrExponents "USAGE: arrExponents(A); arr A, multarr A RETURN: [intvec] The exponents of a free (multi-) arrangement, i.e. the degrees of a basis of D(A) the derivation module. NOTE: only defined for central arrangements SEE ALSO: arrDer, arrIsFree, arrExponents KEYWORDS: free; exponents; multiarrangement EXAMPLE: example arrExponents;" { def A = #[1]; if(arrIsFree(A) != 1){ ERROR("Arrangement is not free!"); } module der = arrDer(A); intvec exp; for(int i =1; i<=size(der); i++){ exp[i] = deg(der[i]); } return(exp); } example { "EXAMPLE: computing the exponents of the Edelman-Reiner arrangement and its restriction: "; echo = 2; ring R = 0,(x,y,z),dp; arr A3 = arrBoolean(3); arr B3 = arrTypeB(3); arr G = ideal(x,y,z,x+y+z); arrExponents(A3); arrExponents(B3); } // Tries to reduce the number of generators of a generating set for a module static proc lessGenerators(module X){ module Z = syz(X); matrix K = getColumnIndependentUnitPositions(Z); if( K == unitmat(nrows(Z)) ){ return(X); } module Xnew = X*K; Xnew = simplify(Xnew,2); return(lessGenerators(Xnew)); } // Looks for a generator which is redundant static proc getColumnIndependentUnitPositions(module Z){ int n = nrows(Z); // number of generators of D matrix K = unitmat(n); int i; for(int j=1; j<=ncols(Z); j++){ for(i=1; i<=nrows(Z); i++){ if(deg(Z[i,j]) == 0){ K[i,i] = 0; return(K); } } } return(K); } // Outputs the ideal of powers of hyperplanes of a multiarrangement. // Needed for the computation of arrDer. static proc multIdeal(multarr A){ ideal I; for(int i=1; i<=size(A.l); i++){ I[i] = A.l[i]^A.m[i]; } return(I); } //============================================================================// //-------------------------- #15 MULTI-ARRANGEMENTS --------------------------// //============================================================================// //============================================================================// //------------------------------- CONSTRUCTORS -------------------------------// //============================================================================// // general method for creating multiarrangements static proc multarrAdd "USAGE: A = #; A +#; # list containing arr/ideal/list/matrix/poly RETURN: [multarr] multiarrangement constructed by the input parameters. NOTE: algorithm splits up the list # and uses appropiate procedure to handle the input KEYWORDS: multiarrangement; equal; constructor; operator EXAMPLE: example multarrAdd; shows an example" { multarr A; for(int k=1; k<=size(#); k++){ while(1){ //simulates switch, which singular doesn't offer if(typeof(#[k]) == "poly" ) {A = multarrAddPoly (A, #[k]);break;} if(typeof(#[k]) == "ideal") {A = multarrAddIdeal(A, #[k]);break;} if(typeof(#[k]) == "multarr"){A = multarrAddArr (A, #[k]);break;} if(typeof(#[k]) == "list" ) {A = multarrAdd ( #[k]);break;} ERROR("bad input type"); } } return (A); } example { "EXAMPLE: Creating a few multiarrangements"; echo = 2; ring R = 0,(x,y,z),dp; multarr A = ideal(x,y,z,x); A; multarr B = A + ideal(x+1, x-1,y); B; multarr C = list(B, x+1, x-1); C; multarr D = (x2 - y2)^2; D; } // adds a single poly to the arrangement // if the poly is linear, it is just added. If not Singular tries factorization static proc multarrAddPoly(multarr A, poly p) { p=simplify(p,1); if(deg(p) == 0){ ERROR("Given poly is not linear or Singluar is not able to factorize it");} else{ if(deg(p) == 1){ int k; int b = 0; for(k=1; k<=size(A.l); k++){ if(A.l[k] == p){ A.m[k] = A.m[k]+1; b = 1; } } if(b == 0){ A.l[size(A.l)+1] = p; A.m[size(A.l)] = 1; } return(A); } else{ list I = factorize(p,2); if((size(I[1]) == 1) && (deg(I[1][1] > 1))){ERROR("Given poly is not a hyperplane");} else{ int j,i; ideal J; for(i=1; i<=size(I[1]); i++) { for(j=1; j<=I[2][i]; j++){ J[size(J)+1] = I[1][i]; } } return (multarrAdd(A,J)); } } } return(A); } // adds defining polys to the arrangement static proc multarrAddIdeal(multarr A, ideal I){ for(int k=1; k<=size(I); k++){ A = multarrAddPoly(A,I[k]); } return (A); } // union of two multarrangements static proc multarrAddArr(multarr A, multarr B){ return (multarrAddIdeal(A, multIdeal(B))); } //============================================================================// //------------------------------- TYPE CASTING -------------------------------// //============================================================================// // computes the defining polynomial static proc multarr2poly(multarr A) "USAGE: multArrQPoly(multarr A); RETURN: [poly] q: defining polynomial of a multiarrangement with multiplicities SEE ALSO: arr2poly, multarr2poly KEYWORDS: multiarrangement; defining polynomial EXAMPLE: example multArrQPolys;" { poly q=1; for(int i=1;i<=size(A.l);i=i+1) { q=q*A.l[i]^A.m[i]; } return(q); } example { "EXAMPLE: Computing the Q-Poly for a multiarrangement"; echo = 2; ring R = 0,(x,y,z),dp; multarr A = ideal(x,y,z,x,y,x-y,x-z,x-z,y-z); A; poly q=multarr2poly(A); q; } // converts simple arrangement to multiarrangement proc arr2multarr(arr A, intvec v) "USAGE: multArrFromIntvec(arr A, intvec v); RETURN: [multarr] multiarrangement MA, which is the arrangement A with multiplicities v NOTE: the size of v must match the number of hyperplanes of the arrangement A SEE ALSO: arr2multarr, multarr2arr KEYWORDS: multiarrangement; arrangement; constructor EXAMPLE: example arr2multarr" { if(ncols(A.l)!=size(v)){ ERROR("Vector's size does not match the hyperplanes."); } multarr B; B.l=A.l; B.m=v; return(B); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; arr A = arrTypeB(3); A; intvec v=2:9; v; multarr MA=arr2multarr(A,v); MA; } // converts multiarrangement to simple arrangement proc multarr2arr(multarr A) "USAGE: multarr2arr(multarr A, intvec v); RETURN: [arr] arrangement A, with all multiplicities removed SEE ALSO: arr2multarr, multarr2arr KEYWORDS: multiarrangement; arrangement; constructor EXAMPLE: example multarr2arr" { arr B; B.l=A.l; return(B); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; multarr A=x2y3z5; A; arr AS = multarr2arr(A); AS; } //============================================================================// //------------------------------- PRINTING -----------------------------------// //============================================================================// // prints arrangement in the console static proc multarrPrint(multarr A) "USAGE: A; A arr RETURN: [] better readable output in the console as newstruct print. SEE ALSO: arrPrint, multarrPrint KEYWORDS: print EXAMPLE: example multarrPrint;" { for(int j=1;j<=ncols(A.l);j++){ print("_["+string(j)+"]=("+string(A.l[j])+")^"+ string(A.m[j])); } } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; multarr A = ideal(x2,y3,z); A; } // number of hyperplanes with multiplicities static proc multarrSize(multarr A) "USAGE: size(A); A multarr RETURN: [int] Number of hyperplanes with multiplicities SEE ALSO: arrSize KEYWORDS: multiarrangement; size; number; hyperplanes EXAMPLE: example multarrSize;" { return (sum(A.m)); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; multarr A = ideal(x2,y3,z); A; } //============================================================================// //------------------------ RESTRICTION & DELETION ----------------------------// //============================================================================// // decrements the multiplicity of a hyperplane by one static proc multarrDelete(multarr A, int k) "USAGE: multarrDelete(A, k); arrangement A, integer k; RETURN: [multarr] the hyperplane Multiarrangement A', i.e. the multiarrangement with multiplicity of H_k decremented by one. If m(H_k)=1, then the hyperplane H_k is deleted SEE ALSO: arrDelete, multarrDelete, KEYWORDS: multiarrangement; delete EXAMPLE: example multarrDelete;" { if(k>ncols(A.l)){ ERROR("There is no k-th hyperplane"); } poly q = multarr2poly(A); q = q/(A.l[k]); multarr MA = q; return (MA); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; multarr A =ideal(x2,y3,z); multarr AD = multarrDelete(A,2); AD; } // restriction of A (as arr) to a hyperplane with multiplicities proc multarrRestrict(arr A,intvec v, list #) "USAGE: multarrRestrict(A, v); arrangement A, int/intvec v, optional argument "CC"; RETURN: [multarr] the restricted hyperplane Multi-Arrangement (A^X) with multiplicities i.e. counting how often one element of the restricted arrangement occurs as intersetion of hyperplane of the first arrangement. This definition is due to Guenter M. Ziegler. NOTE: A has to be non-empty. REMARKS: We restrict A to the flat X, defined by the equations in A[v]. The restriction will only be performed, if the ideal defining the flat X is monomial (i.e. X is an intersection of coordinate planes). If the optional argument CC is given, the arrangement is transformed in such a way that X has the above form. SEE ALSO: multarrRestrict, multarrMultRestrict, arrRestrict KEYWORDS: multiarrangement; restriction EXAMPLE: example multarrRestrict; " { ideal I=A.l; I=I[v]; option(redSB); I=std(I); // defining equations for flat X //option(none); ideal Al=arr2ideal(A); int i; if(isMonomial(I)==1){ for(i=1;i<= size(I);i++){ Al=subst(Al,I[i],0); } multarr AR=simplify(Al,3); return(AR); } if(size(#) == 0){ ERROR("The flat X is not defined by a monomial ideal. " + "Please do a coordinate change first. You can use arrCoordNormalize to " + "transform the arrangement accordingly by adding the argument CC."); } if(#[1]!="CC"){ ERROR("The flat X is not defined by a monomial ideal. " + "Please do a coordinate change first. You can use arrCoordNormalize to " + "transform the arrangement accordingly by adding the argument CC."); } if(size(v)==0){return(A);} intvec w=v[1]; intvec tmp; for(i=2;i<=size(v);i++){ tmp=w,v[i]; if(rank(matrix(A[w]))==size(tmp)){ w=tmp; } } arr B=arrCoordNormalize(A,w); ideal Bl=arr2ideal(B); for(i=1;i<= size(w);i++){ Bl=subst(Bl,Bl[w[i]],0); } multarr BR=simplify(Bl,3); return(BR); } example { "EXAMPLE:"; echo = 2; ring R = 0,x(1..5),dp; arr A = arrEdelmanReiner(); A; multarr AR = multarrRestrict(A,6,"CC"); AR; } // restriction of A (as multarr) to a hyperplane with multiplicities proc multarrMultRestrict(multarr A,int k) "USAGE: multarrMultRestrict(A, k); multiarrangement A, integer k; RETURN: [multarr] the restricted hyperplane Multi-Arrangement (A^H_k) with multiplicities, i.e. counting with multiplicities how often one element of the restricted arrangement occurs as intersetion of hyperplane of the first multiarrangement. This definition is due to Guenter M. Ziegler. NOTE: A has to be non-empty. REMARKS: The restriction will only be performed, if H_k = ker(x_i) for some i. One can also restrict an arrangement with respect to any hyper- plane k, but than a coordinate change is necessary first to make H_k = ker(x_k). Since such a coordinate change is not unique, please use arrCoordchange to do so. SEE ALSO: multarrRestrict, multarrMultRestrict, arrRestrict KEYWORDS: multiarrangement; restriction EXAMPLE: example multarrMultRestrict; " { ideal I = variables(A.l); ideal J; int j,i; for(i=1;i<=size(A.l);i=i+1) { for(j=1;j<=A.m[i];j++){ J[ncols(J)+1]=A.l[i]; } } poly p = simplify(A.l[k],1); int n = rvar(p); if( n == 0 ){ ERROR("H_" + string(k) + " = " + string(p) + " is not of the form ker(x_i). Please do a coordinate change first." + "You can use arrCoordinateChange to transform the arrangement accordingly."); } J = subst(J, p, 0); multarr MA = simplify(J,3); return(MA); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; multarr A =ideal(x2,y2,z2,(x-y)^3,(x-z)^2,(y-z)); A; //The restriction of the multiarrangement is: multarr AR = multarrMultRestrict(A,1); AR; } //============================================================================// //----------------------------- #16 COMBINATORICS ---------------------------// //============================================================================// /* RELATIONS can have 3 values: -1 : flat&hyperplane are parallel 0 : hyperplane intersects the flat, but only further on in the lattice. +1 : hyperplane is part of the flat. */ // intvec: multiplicities of hyperplanes proc arrLattice(arr ARR) "USAGE: arrLattice(arr ARR) RETURN: [arrposet] intersection poset of the arrangement NOTE: The algorithm works by a bottom up approach, i.e. it calculates the SEE ALSO: arrLattice, arrFlats KEYWORDS: intersection lattice; poset; lattice EXAMPLE: example arrFlats;" { //Performance test system("--ticks-per-sec",1); timer = 0; int start = timer; // start dbprint(3-voice,newline); dbprint(3-voice,"=== Computing poset ==="); dbprint(3-voice,newline); // Initialization list L,L2; intvec u,v, NFLAT; int i,j,l,m,n,rk, rk2,rk3, tic, toc, numberOfFlats,numberOfHplanes, counter, ntests; matrix NewRel, M; // Initialization of matrix ntests = 0; M = matrix(ARR); // m x n+1 matrix m = size(ARR); // m = # hplanes n = nvars(basering); // n = # variables numberOfHplanes = m; // Initialization of poset and flat flat F; arrposet P; P.A = ARR; F.REL = 0:m; F.moebius = -1; for(i=1; i<=n; i++){ P.r = insert(P.r,list());} for(i=1; i<=m; i++){ F.REL[i] = 1; L[i] = F; F.REL[i] = 0;} F.moebius = 0; P.r[1] = L; // calculating r[i] step by step for(rk=2; rk<=rank(ARR); rk++){ // maximal flat possible has rank A.v ofc counter = 0; tic = timer; // Initialization of current round L = P.r[rk-1]; // flats from the last iteration give rise to current ones. numberOfFlats = size(L); L2 = list(); // new list for elts of rk= NewRel = getOldRel(L,m); // contains all the information of the old arrangement // find the next leftmost child by looking for intersetion of F_j with hyperplanes for(j=1; j<=numberOfFlats; j++){ // goes over the elts of L.r[i-1] NFLAT = L[j].REL; for(i=1; i<=numberOfHplanes; i++){ if (NewRel[i,j] == 0){ //test this hyperplane NFLAT[i] = 1; v = collectHplanes(NFLAT); rk2 = rank(submat(M,v,1..n)); ntests = ntests+2; // CHILD FOUND BY INTERSECTING WITH H_i if(rk2 == rank(submat(M,v,1..n+1))){ NewRel[i,j] = 1; counter++; // potentially there exist more hyperplanes which intersect in the same space for(l=i+1; l<=m; l++){ if(NewRel[l,j] == 0){ NFLAT[l] = 1; u = collectHplanes(NFLAT); rk3 = rank(submat(M, u, 1..n)); ntests = ntests +2; // FLAT EXISTS if(rk3 == rank(submat(M,u,1..n+1)) ){ if(rk2 == rk3){NewRel[l,j] = 1;} else{NFLAT[l] = 0;} //itersecting with both yields higher rank flat } // FLAT DOES NOT EXIST else{NFLAT[l] = -1;} } } // Add new flat to list, reset NFLAT. F.REL = NFLAT; NFLAT = L[j].REL; // refresh. // Find Parents: (most expensive part it seems) F.parents = j:1; //parent in any case for(l=j+1; l<=numberOfFlats; l++){ if(isParent(L[l].REL, F.REL)){ F.parents = F.parents,l; NewRel[1..m,l] = updateRel(F.REL, submat(NewRel,1..m,l)); } } L2 = insert(L2,F,size(L2)); // means that the flat is parallel } else{ L[j].REL[i] = -1; NewRel[i,j] = -1; NFLAT[i] = -1; } } } } toc = timer; dbprint(3-voice,"rank "+string(rk)+": found "+ string(counter) + " flats in "+string(toc - tic)+"s"); counter = 0; P.r[rk] = L2; } dbprint(3-voice,newline); //dbprint(3-voice,"Computation time: "+string(timer - start)+"s"); dbprint(3-voice,"Matrix tests: "+string(ntests)); return (P); } example { "EXAMPLE: Intersection lattice of the braid arrangement in 3 dimensions "; echo = 2; ring r; arrLattice(arrTypeB(3)); } static proc arrRank(arr A){ int n = rank(matrix(A)); int m = nvars(A); if(n < m) {return (n);} return (m); } static proc getOldRel(list L, int m){ int n = size(L); matrix NewRel[m][n]; for(int i=1; i<=n; i++){ NewRel[1..m,i] = L[i].REL; } return (NewRel); } static proc updateRel(intvec REL, matrix NewRel){ for(int i=1; i<=size(REL); i++){ if(NewRel[i,1] == 0 && REL[i] == 1){NewRel[i,1] = 1;} } return (NewRel); } // Flat F is a parent of Flat G if F[i] == 1 => G[i] == 1 for all i static proc isParent(intvec parent, intvec child){ int counter = 0; for(int i=1; i<= size(parent); i++){ if(parent[i]==1){ if(child[i] == 1){counter++;} else{ return (0); } } } if(counter == 0){ return (0); } return (1); } // transforms the "rel" intvec into an intvec which contains the indices of the hyperplanes. static proc collectHplanes(intvec RELATIONS){ intvec result; for(int i=1; i<=size(RELATIONS); i++){ if(RELATIONS[i] > 0){result = result,i;} } result = result[2..size(result)]; return (result); } static proc getFlat(arrposet P, int i, int j){ list L = P.r[i]; return (L[j]); } static proc setFlat(arrposet P, int i, int j, flat F){ list L = P.r[i]; L[j] = F; P.r[i] = L; return (P); } static proc getFlag(arrposet P, int i, int j){ flat F = getFlat(P,i,j); return (F.flag); } static proc setFlag(arrposet P, int i, int j, int flag){ flat F = getFlat(P,i,j); F.flag = flag; return (setFlat(P,i,j,F)); } //============================================================================// //------------------------- #16 INTERSECTION-LATTICE -------------------------// //============================================================================// //============================================================================// //-------------------------- MOEBIUS -------------------------------------// //============================================================================// // calculates the moebius values of the poset proc moebius(arrposet P) "USAGE: moebius(arrposet P) RETURN: [arrposet] fills in the moebius values of the flats in the poset SEE ALSO: moebius KEYWORDS: moebius function EXAMPLE: example arrCharPoly; shows an example" { list L; int i,j; for(i=2; i<=rank(P.A); i++){ L = P.r[i]; for(j=1; j<=size(L); j++){ arrposet Q = P; export Q; L[j].moebius = -(1 + moebiusRecursion(i, j)); kill Q; } P.r[i] = L; } return (P); } example { "EXAMPLE: We look at the moebius values of the braid arrangement in 4 dimensions: "; echo = 2; ring R = 0,(x,y,z,t),dp; arr A = arrBraid(4); arrposet P = arrLattice(A); P; //As you can see the values are not calculated yet: printMoebius(P); P = moebius(P); //Now all entries are initialized: printMoebius(P); } // moebiusrecursion(i,j) is the sum moebius(X) over {X | V>X>Flat_ij} // Vss: all moebius values of rank < i are known and correctly saved in P static proc moebiusRecursion(int i, int j){ flat F = getFlat(Q, i, j); int m = F.moebius; if(getFlag(Q,i,j) == 1){return (0);} else { Q = setFlag(Q,i,j,1); if(i > 1){ for(int k=1; k<=size(F.parents); k++){ m = m + moebiusRecursion(i-1, F.parents[k]); } } } return (m); } // pi(A,t) = sum[X in L(A); moebius(X)*(-t)^r(X)] proc arrPoincare(def input) "USAGE: arrPoincare(A); arr A RETURN: [intvec] The Poincare polynomial as integer vector of the arrangement, which is equal to the second kind Poincare-Series of the Orlik-Solomon Algebra. SEE ALSO: arrPoincare, arrChambers, arrBoundedChambers KEYWORDS: Poincare polynomial EXAMPLE: example arrPoincare;" { while(1){ if(typeof(input) == "arr"){ arr A = input; arrposet P = arrLattice(A); break; } if(typeof(input) == "arrposet"){ arr A = input.A; arrposet P = input; break; } ERROR("Bad input type"); } P = moebius(P); int i, j, coeff, sign; list L; intvec v = 1; sign = 1; for(i=1; i<= rank(A); i++){ L = P.r[i]; sign = (-1)*sign; coeff = 0; for(j=1;j<=size(L);j++){ coeff = coeff + L[j].moebius; } coeff = sign*coeff; v = v,coeff; } return (v); } example { "EXAMPLE: The poincare polynomial of the braid arrangement in k dimensions is given as: " + "pi(A,t) = (1 + t)*...*(1 + (k-1)*t)"; echo = 2; ring R = 0,(x,y,z,u,v),dp; arr A = arrBraid(5); intvec v = arrPoincare(A); (1+x)*(1+2x)*(1+3x)*(1+4x); v; } // X(A,t) = t^l * pi(A,-t^-1) proc arrCharPoly(def input) "USAGE: arrCharPoly(arr A) RETURN: [intvec] coefficients of the characteristic polynomial of A in incresing order REMARKS: The algorithm only returns the coefficients of the characteristic polynomial since they are whole numbers but the basering could be something different. SEE ALSO: arrCharPoly, arrPoincare KEYWORDS: characteristic polynomial EXAMPLE: example arrCharPoly; shows an example" { intvec v = arrPoincare(input); int l = size(v); v = v[l..1]; //reverses order for(int i=2; i<=l; i=i+2){ v[i] = -v[i]; } return (v); } example { "EXAMPLE: The characteristic polynomial of the Braid arrangement in k dimensions is given as: " + "X(A,t) = t*(t-1)*...*(t-(k-1)))"; echo = 2; ring R = 0,(x,y,z,u,v),dp; arr A = arrBraid(5); intvec v = arrCharPoly(A); x*(x-1)*(x-2)*(x-3)*(x-4); v; } // number of chambers of the arrangement proc arrChambers(arr A) "USAGE: arrChambers(A); arr A RETURN: [int] The number of chambers of an arrangement, which is equal to the evaluation of the Poincare polynomial at 1. SEE ALSO: arrPoincare, arrChambers, arrBoundedChambers KEYWORDS: chambers EXAMPLE: example arrChambers;" { intvec v = arrPoincare(A); return(sum(v)); } example { "EXAMPLE: Computing the number of number of chambers in a simple arrangement"; echo = 2; ring R = 0,(x,y),dp; arr A = ideal(x,y,x+y-1); arrChambers(A); } // number of bounded chambers of the arrangement proc arrBoundedChambers(arr A) "USAGE: arrBoundedChambers(A); arr A RETURN: [int] The number of bounded chambers of an arrangement, which is equal to the evaluation of the Poincare polynomial at -1. SEE ALSO: arrPoincare, arrChambers, arrBoundedChambers KEYWORDS: chambers EXAMPLE: example arrBoundedChambers;" { intvec v = arrPoincare(A); for(int i=2; i<=size(v); i=i+2){ v[i] = -v[i]; } return (sum(v)); } example { "EXAMPLE: Computing the number of bounded chambers in a simple arrangement"; echo = 2; ring R = 0,(x,y),dp; arr A = ideal(x,y,x+y-1); arrBoundedChambers(A); } //============================================================================// //------------------------------- OUTPUT ------------------------------------// //============================================================================// static proc arrPrintPoset(arrposet P){ print("Given Arrangement:"); P.A; print("Corresponding poset:"); string s; int i,j; list L; for(i=1; i<= size(P.r); i++){ print("====== rank "+string(i)+": "+string(size(P.r[i]))+" flats ======"); s = ""; L = P.r[i]; for(j=1; j<=size(L); j++){ s = s + " (" + string(collectHplanes(L[j].REL)) + "), "; } print(s); if(size(P.r[i]) == 0){break;} } } proc printMoebius(arrposet P) "USAGE: printMoebius(A); arr A RETURN: [] displays the moebius values of all the flats in the poset REMARKS: Mainly used for debugging. EXAMPLE: example printMoebius;" { print("Moebius values: "); string s; int i,j; list L; for(i=1; i<= size(P.r); i++){ print("====== rank "+string(i)+": "+string(size(P.r[i]))+" flats ======"); s = ""; L = P.r[i]; for(j=1; j<=size(L); j++){ s = s + " (" + string(L[j].moebius) + "), "; } print(s); if(size(P.r[i]) == 0){break;} } } example { "EXAMPLE: We look at the moebius values of the braid arrangement in 4 dimensions: "; echo = 2; ring R = 0,(x,y,z,t),dp; arr A = arrBraid(4); arrposet P = arrLattice(A); P; //As you can see the values are not calculated yet: printMoebius(P); P = moebius(P); //Now all entries are initialized: printMoebius(P); } //============================================================================// //-------------------------------- arrFlats Stuff --------------------------------// //============================================================================// // test via hyperplanes. proc arrFlats(arr ARR) "USAGE: size(A); A arr RETURN: [arrposet] Intersection lattice SEE ALSO: arrFlats KEYWORDS: intersection lattice EXAMPLE: example arrFlats;" { print(newline); print("=== Computing poset ==="); print(newline); //Performance test system("--ticks-per-sec",1000); timer = 0; int time = timer; // Initialization list L,L2; intvec u,v,w,src; int i,j,k,l,m,n,d, rk,rk2; int counter, ntests; ntests = 0; matrix S,T; intmat REL; // Initialization of matrix matrix M = matrix(ARR); // m x n+1 matrix m = size(ARR); n = nvars(basering); // Initialization of P arrflats P; P.A = ARR; for(i=1; i<=n; i++){ P.r = insert(P.r,list());} for(i=1; i<=m; i++){ L[i] = i;} P.r[1] = L; // calculating r[i] step by step for(i=2; i<=n; i++){ // maximal flat possible has rank A.v ofc counter = 0; L = P.r[i-1]; // flats from the last iteration give rise to current ones. if(size(L) <= 1){break;} // finish early if no more intersections possible. L2 = list(); // new list for elts of rk=i // REL is an intmat that contains information about the relations between // the i-1 flats and the Hyperplanes. // REL[i,j] = 1 means that H_i intersects F_j // REL[i,j] = 0 means that it has not been tested yet // REL[i,j] = -1 means that H_i does NOT intersect F_j, i.e. they are parallel // resetting the REL-matrix REL = intmat(intvec(0),m,size(L)); // filles in the trivial entries, i.e. each flat intersects all hplanes it is composed of. for(j=1; j<=size(L); j++){ u = L[j]; for(k=1; k<= size(u); k++){ REL[u[k],j] = 1; } } //find new flat of rank i for(j=1; j<=size(L); j++){ // goes over the elts of L.r[i-1] // Looking for intersetion of F_j with hyperplanes u = L[j]; for(k=1; k<=m; k++){ if (REL[k,j] == 0 ){ v = insertVal(u,k); counter++; ntests = ntests +2; rk = rank(submat(M,v,1..n)); if(rk == rank(submat(M,v,1..n+1))){ //INTERSECTION FOUND // potentially there exist more hyperplanes which intersect in the same // space. For example (x,y,x+y) all intersect in (0,0) REL[k,j] = 1; for(l=k+1; l<=m; l++){ if(REL[l,j] == 0){ u = insertVal(v,l); ntests = ntests +2; rk2 = rank(submat(M, u, 1..n)); if( rk == rk2 && rk == rank(submat(M,u,1..n+1)) ){ v = u; REL[l,j] = 1; } }} // Add new flat to list, reset u. L2 = insert(L2,v,size(L2)); u = L[j]; //if k = m this is not necessary.... } }} } print("rank: "+string(i)+", expected OPS: "+string(binomial(size(L),2)) +", excecuted OPS: " + string(counter)); counter = 0; //cleanup => doing this during computation increases speed!! for(j=1; ju[size(u)]){ u = u,k; return (u); } int i = 2; while(u[i] v[n]){res[k] = v[n]; n++; break;} if(u[m] == v[n]){res[k] = u[m]; m++; n++; break;} ERROR("Something went wrong in proc mergeIV"); } } while(m <= size(u)){res[k] = u[m]; m++; k++;} while(n <= size(v)){res[k] = v[n]; n++; k++;} return (res); } // checks if v[i] < u[i] for all i static proc isSmaller(intvec u, intvec v){ for(int i= 1; i<=size(u); i++){ if(u[i] > v[i]){ return (0); } } return (1); } static proc new2old(arrposet P){ arrflats Q; Q.A = P.A; int i,j; list L = P.r; for(i=1; i<=size(L); i++){ list L2 = L[i]; for(j=1; j<=size(L2); j++){ L2[j] = collectHplanes(L2[j].REL); } L[i] = L2; } Q.r = L; return (Q); } /********************************************************************* newstruct("arr","ideal l"); Defines a hyperplane arrangement by a list of linear polynomials such that the hyperplanes are the varieties of those polynomials. supported operators: A = input defines an arrangement by the input which may consist of the types arr/ideal/poly/matrix/list A + input adds arrangement defined by the right hand side to the left hand side A - input deletes hyperplanes from the arrangement <, >, <=, >=, ==, != set theoretical comparison of two arrangements A[int] access to a single hyperplane A[intvec] subarrangement defined by the indexed hyperplanes A; prints the arrangement on the screen supported type conversions: matrix(A) returns coefficient matrix of the defining polynomials poly(A) returns the defining polynomial which is the product of all the single polynomials list(A) returns the defining polynomials as a list ideal(A) returns the defining polynomials as an ideal type2arr(input) returns arrangement defined by the input which may consist of the types arr/ideal/poly/matrix/list supported inherited functions: delete(A, intvec) deletes indexed hyperplanes from the arrangement homog(A) checks wether the defining polys are all homogenous <=> arr is central homog(A, rvar) homogenizes the def. polys with respect to the given ring variable size(A) number of hyperplanes in the arrangement subst(A,rvar,poly,...) substitutes ringvariables with given polynomials, though they need to remain linear variables(A) ideal generated by the ring variables that A depends on nvars(A) number of ring variables that A depends on newstruct("multarr","ideal l, intvec m"); Defines a hyperplane arrangement with multiplicities by a list of linear polynomials such that the hyperplanes are the varieties of those polynomials and an intvec in which the multiplicities are saved. supported operators: M = input defines an multarr by the input which may consist of the types multarr/ideal/poly/list M + input adds arrangement defined by the right hand side to the left hand side M; prints the multarr on the screen supported type conversions: poly(M) returns defining polynomial with multiplicities arr2multarr(A,intvec) returns multarr with multiplicities defined by the intvec. multarr2arr(M) returns the internal arrangement (all multiplicities set to 1) delete(M,int) decrements the multiplicity of the hyperplane defined by the index by 1 size(M) returns number of hyperplanes counting multiplicities. *-----------------------------------------------------------------------*/ singular-4.0.3+ds/Singular/LIB/assprimeszerodim.lib000066400000000000000000000474021266270727000222460ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version assprimeszerodim.lib 4.0.0.0 Jun_2014 "; // $Id: 4c9703d9d449016b92ecb5f8786539f6d04d29ed $ category="Commutative Algebra"; info=" LIBRARY: assprimeszerodim.lib associated primes of a zero-dimensional ideal AUTHORS: N. Idrees nazeranjawwad@gmail.com G. Pfister pfister@mathematik.uni-kl.de A. Steenpass steenpass@mathematik.uni-kl.de S. Steidel steidel@mathematik.uni-kl.de OVERVIEW: A library for computing the associated primes and the radical of a zero-dimensional ideal in the polynomial ring over the rational numbers, Q[x_1,...,x_n], using modular computations. SEE ALSO: primdec_lib PROCEDURES: zeroRadical(I); computes the radical of I assPrimes(I); computes the associated primes of I "; LIB "primdec.lib"; LIB "modstd.lib"; //////////////////////////////////////////////////////////////////////////////// proc zeroRadical(ideal I, list #) "USAGE: zeroRadical(I[, exactness]); I ideal, exactness int ASSUME: I is zero-dimensional in Q[variables] RETURN: the radical of I NOTE: A final test is applied to the result if exactness != 0 (default), otherwise no final test is done. EXAMPLE: example zeroRadical; shows an example " { /* read optional parameter */ int exactness = 1; if(size(#) > 0) { if(size(#) > 1 || typeof(#[1]) != "int") { ERROR("wrong optional parameter"); } exactness = #[1]; } /* compute a standard basis if necessary */ if (!attrib(I, "isSB")) { I = modStd(I, exactness); } /* call modular() */ // TODO: write deleteUnluckyPrimes_zeroRadical() if(exactness) { ideal F = modular("Assprimeszerodim::zeroRadP", list(I), Modstd::primeTest_std, Modular::deleteUnluckyPrimes_default, pTest_zeroRadical, finalTest_zeroRadical); } else { ideal F = modular("Assprimeszerodim::zeroRadP", list(I), Modstd::primeTest_std, Modular::deleteUnluckyPrimes_default, pTest_zeroRadical); } /* compute the squarefree parts */ poly f; int k; int i; for(i = nvars(basering); i > 0; i--) { f = gcd(F[i], diff(F[i], var(i))); k = k + deg(f); F[i] = F[i]/f; } /* return the result */ if(k == 0) { return(I); } else { return(modStd(I + F, exactness)); } } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = xy4-2xy2+x, x2-x, y4-2y2+1; zeroRadical(I); } //////////////////////////////////////////////////////////////////////////////// /* The pTest for zeroRadical(), to be used in modular(). */ static proc pTest_zeroRadical(string command, list args, ideal result, int p) { /* change to characteristic p */ def br = basering; list lbr = ringlist(br); if(typeof(lbr[1]) == "int") { lbr[1] = p; } else { lbr[1][1] = p; } def rp = ring(lbr); setring(rp); ideal Ip = fetch(br, args)[1]; ideal Fp_result = fetch(br, result); /* run the command and compare with given result */ execute("ideal Fp = "+command+"(Ip);"); int i; for(i = nvars(br); i > 0; i--) { if(Fp[i] != Fp_result[i]) { setring(br); return(0); } } setring(br); return(1); } //////////////////////////////////////////////////////////////////////////////// /* The finalTest for zeroRadical, to be used in modular(). */ static proc finalTest_zeroRadical(string command, list args, ideal F) { int i; for(i = nvars(basering); i > 0; i--) { if(reduce(F[i], args[1]) != 0) { return(0); } } return(1); } //////////////////////////////////////////////////////////////////////////////// proc assPrimes(def I, list #) "USAGE: assPrimes(I[, alg, exactness]); I ideal or module, alg string (optional), exactness int (optional) - alg = "GTZ": method of Gianni/Trager/Zacharias (default) - alg = "EHV": method of Eisenbud/Hunecke/Vasconcelos - alg = "Monico": method of Monico ASSUME: I is zero-dimensional over Q[variables] RETURN: a list of the associated primes of I NOTE: A final test is applied to the result if exactness != 0 (default), otherwise no final test is done. EXAMPLE: example assPrimes; shows an example " { /* read input */ if(typeof(I) != "ideal") { if(typeof(I) != "module") { ERROR("The first argument must be of type 'ideal' or 'module'."); } module M = I; kill I; ideal I = Ann(M); kill M; } /* read optional parameters */ list defaults = list("GTZ", 1); int i; for(i = 1; i <= size(defaults); i++) { if(typeof(#[i]) != typeof(defaults[i])) { # = insert(#, defaults[i], i-1); } } if(size(#) != size(defaults)) { ERROR("wrong optional parameters"); } string alg = #[1]; int exactness = #[2]; int a; if(alg == "GTZ") { a = 1; } if(alg == "EHV") { a = 2; } if(alg == "Monico") { a = 3; } if(a == 0) // alg != "GTZ" && alg != "EHV" && alg != "Monico" { ERROR("unknown method"); } /* compute a standard basis if necessary */ if(printlevel >= 10) { "========== Start modStd =========="; } if (!attrib(I, "isSB")) { I = modStd(I, exactness); } if(printlevel >= 10) { "=========== End modStd ==========="; } int d = vdim(I); if(d == -1) { ERROR("Ideal is not zero-dimensional."); } if(homog(I) == 1) { return(list(maxideal(1))); } /* compute the radical if necessary */ ideal J = I; int isRad; poly f; isRad, f = pTestRad(I, d); while(!isRad) { J = zeroRadical(I, exactness); J = modStd(J, exactness); d = vdim(J); isRad, f = pTestRad(J, d); } I = J; kill J; /* call modular() */ if(exactness) { ideal F = modular("Assprimeszerodim::modpSpecialAlgDep", list(I, f, d, a), Modstd::primeTest_std, Modular::deleteUnluckyPrimes_default, pTest_assPrimes, finalTest_assPrimes); } else { ideal F = modular("Assprimeszerodim::modpSpecialAlgDep", list(I, f, d, a), Modstd::primeTest_std, Modular::deleteUnluckyPrimes_default, pTest_assPrimes); } /* compute the components */ list result; list H = factorize(F[1]); for(i = size(H[1])-1; i > 0; i--) { result[i] = I + ideal(quickSubst(H[1][i+1], f, I)); } /* return the result */ return(result); } example { "EXAMPLE:"; echo = 2; ring R = 0,(a,b,c,d,e,f),dp; ideal I = 2fb+2ec+d2+a2+a, 2fc+2ed+2ba+b, 2fd+e2+2ca+c+b2, 2fe+2da+d+2cb, f2+2ea+e+2db+c2, 2fa+f+2eb+2dc; assPrimes(I); } //////////////////////////////////////////////////////////////////////////////// /* Computes a poly F in Q[T] such that * = kernel(Q[T] --> basering, T |-> f), * T := last variable in the basering. */ static proc specialAlgDepEHV(ideal I, poly f) { def R = basering; execute("ring QT = ("+charstr(R)+"), "+varstr(R, nvars(R))+", dp;"); setring(R); map phi = QT, f; setring QT; ideal F = preimage(R, phi, I); // corresponds to std(I, f-T) in dp(n),dp(1) setring(R); ideal F = imap(QT, F); return(F); } //////////////////////////////////////////////////////////////////////////////// /* Assume I is zero-dimensional. * Computes a poly F in Q[T] such that * = kernel(Q[T] --> basering, T |-> f), * T := last variable in the basering. */ static proc specialAlgDepGTZ(ideal I, poly f) { def R = basering; if(nvars(R) > 1) { def Rlp = changeord(list(list("dp", 1:(nvars(R)-1)), list("dp", 1:1))); setring(Rlp); poly f = imap(R, f); ideal I; } ideal K = maxideal(1); K[nvars(R)] = 2*var(nvars(R))-f; map phi = R, K; I = phi(I); I = std(I); ideal F = I[1]; if(nvars(R) > 1) { setring(R); ideal F = imap(Rlp, F); } return(F); } //////////////////////////////////////////////////////////////////////////////// /* Assume I is zero-dimensional. * Computes a poly F in Q[T], the characteristic polynomial of the map * basering/I ---> basering/I defined by the multiplication with f, * T := last variable in the basering. * In case I is radical, it is the same polynomial as in specialAlgDepEHV. */ static proc specialAlgDepMonico(ideal I, poly f, int d) { def R = basering; int j; matrix M[d][d]; ideal J = std(I); ideal basis = kbase(J); poly vars = var(nvars(R)); for(j = nvars(R)-1; j > 0; j--) { vars = var(j)*vars; } for(j = 1; j <= d; j++) { M[1..d, j] = coeffs(reduce(f*basis[j], J), basis, vars); } execute("ring QT = ("+charstr(R)+"), "+varstr(R, nvars(R))+", dp;"); matrix M = imap(R, M); ideal F = det(M-var(1)*freemodule(d)); setring(R); ideal F = imap(QT, F); return(F); } //////////////////////////////////////////////////////////////////////////////// static proc specialTest(int d, poly p, ideal I) { //=== computes a poly F in Q[T] such that =kernel(Q[T]--->basering) //=== mapping T to p and test if d=deg(F) def R = basering; execute("ring Rhelp = ("+charstr(R)+"), T, dp;"); setring R; map phi = Rhelp,p; setring Rhelp; ideal F = preimage(R,phi,I); int e=deg(F[1]); setring R; return((e==d), fetch(Rhelp, F)[1]); } //////////////////////////////////////////////////////////////////////////////// /* Assume d = vector space dim(basering/J). * Tries to find a (sparse) linear form r such that d = deg(F), where * F is a poly in Q[T] such that = kernel(Q[T]-->basering) mapping T to r. * If found, returns (1, r, F). If not found, returns (0, 0, 0). */ static proc findGen(ideal J, int d) { def R = basering; int n = nvars(R); int okay; poly F; /* try trivial transformation */ poly r = var(n); okay, F = specialTest(d, r, J); if(okay) { return(1, r, F); } /* try transformations of the form var(n) + var(i) */ int i; for(i = 1; i < n; i++) { okay, F = specialTest(d, r+var(i), J); if(okay) { return(1, r+var(i), F); } } /* try transformations of the form var(n) + \sum var(i) */ if(n > 2) { for(i = 1; i < n; i++) { r = r + var(i); okay, F = specialTest(d, r, J); if(okay) { return(1, r, F); } } } /* try random transformations */ int N = 2; // arbitrarily chosen for(i = N; i > 0; i--) { r = randomLast(100)[n]; okay, F = specialTest(d, r, J); if(okay) { return(1, r, F); } } /* not found */ return(0, 0, 0); } //////////////////////////////////////////////////////////////////////////////// /* Assume d = vector space dim(basering/I). * Tests if I is radical over F_p, where p is some randomly chosen prime. * If yes, chooses a linear form r such that d = deg(squarefreepart(F)), where * F is a poly in Z/p[T] such that = kernel(Z/p[T]-->Z/p[vars(basering)]) * mapping T to r. * Returns (1, r), if I is radical over F_p, and (0, 0) otherwise. */ static proc pTestRad(ideal I, int d) { int N = 2; // Try N random primes. Value of N can be chosen arbitrarily. def R = basering; list rl = ringlist(R); int p; int okay; int i; for(i = N; i > 0; i--) { p = prime(random(100000000,536870912)); // change to characteristic p if(typeof(rl[1]) == "int") { rl[1] = p; } else { rl[1][1] = p; } def Rp(i) = ring(rl); setring Rp(i); ideal I = imap(R, I); // find and test transformation poly r; poly F; okay, r, F = findGen(I, d); if(okay) { poly f = gcd(F, diff(F, var(1))); if(d == deg(F/f)) // F squarefree? { setring(R); return(1, imap(Rp(i), r)); } } setring(R); } return(0, 0); } //////////////////////////////////////////////////////////////////////////////// /* Computes an ideal F such that ncols(F) = nvars(basering), * < F[i] > = (I intersected with K[var(i)]), and F[i] is monic. */ static proc zeroRadP(ideal I) { intvec opt = option(get); option(redSB); I = std(I); ideal F = finduni(I); // F[i] generates I intersected with K[var(i)] F = simplify(F, 1); option(set, opt); return(F); } //////////////////////////////////////////////////////////////////////////////// static proc quickSubst(poly h, poly r, ideal I) { //=== assume h is in Q[x_n], r is in Q[x_1,...,x_n], computes h(r) mod I attrib(I,"isSB",1); int n = nvars(basering); poly q = 1; int i,j,d; intvec v; list L; for(i = 1; i <= size(h); i++) { L[i] = list(leadcoef(h[i]),leadexp(h[i])[n]); } d = L[1][2]; i = 0; h = 0; while(i <= d) { if(L[size(L)-j][2] == i) { h = reduce(h+L[size(L)-j][1]*q,I); j++; } q = reduce(q*r,I); i++; } return(h); } //////////////////////////////////////////////////////////////////////////////// /* Simple switch for specialAlgDepEHV, specialAlgDepGTZ, and * specialAlgDepMonico. */ static proc modpSpecialAlgDep(ideal I, poly f, int d, int alg) { ideal F; if(alg == 1) { F = specialAlgDepEHV(I, f); } if(alg == 2) { F = specialAlgDepGTZ(I, f); } if(alg == 3) { F = specialAlgDepMonico(I, f, d); } F = simplify(F, 1); return(F); } //////////////////////////////////////////////////////////////////////////////// /* The pTest for assPrimes(), to be used in modular(). */ static proc pTest_assPrimes(string command, list args, ideal F, int p) { def br = basering; list lbr = ringlist(br); if(typeof(lbr[1]) == "int") { lbr[1] = p; } else { lbr[1][1] = p; } def rp = ring(lbr); setring(rp); list args_p = fetch(br, args); ideal F = fetch(br, F); execute("ideal Fp = "+command+"(" +Tasks::argsToString("args_p", size(args_p))+");"); int k = (Fp[1] == F[1]); setring br; return(k); } //////////////////////////////////////////////////////////////////////////////// /* The finalTest for assPrimes(), to be used in modular(). */ static proc finalTest_assPrimes(string command, alias list args, ideal F) { F = cleardenom(F[1]); if(deg(F[1]) != args[3]) { return(0); } if(gcd(F[1], diff(F[1], var(nvars(basering)))) != 1) { return(0); }; if(quickSubst(F[1], args[2], args[1]) != 0) { return(0); } return(1); } //////////////////////////////////////////////////////////////////////////////// /* Examples: ========= //=== Test for zeroR ring R = 0,(x,y),dp; ideal I = xy4-2xy2+x, x2-x, y4-2y2+1; //=== Cyclic_6 ring R = 0,x(1..6),dp; ideal I = cyclic(6); //=== Amrhein ring R = 0,(a,b,c,d,e,f),dp; ideal I = 2fb+2ec+d2+a2+a, 2fc+2ed+2ba+b, 2fd+e2+2ca+c+b2, 2fe+2da+d+2cb, f2+2ea+e+2db+c2, 2fa+f+2eb+2dc; //=== Becker-Niermann ring R = 0,(x,y,z),dp; ideal I = x2+xy2z-2xy+y4+y2+z2, -x3y2+xy2z+xyz3-2xy+y4, -2x2y+xy4+yz4-3; //=== Roczen ring R = 0,(a,b,c,d,e,f,g,h,k,o),dp; ideal I = o+1, k4+k, hk, h4+h, gk, gh, g3+h3+k3+1, fk, f4+f, eh, ef, f3h3+e3k3+e3+f3+h3+k3+1, e3g+f3g+g, e4+e, dh3+dk3+d, dg, df, de, d3+e3+f3+1, e2g2+d2h2+c, f2g2+d2k2+b, f2h2+e2k2+a; //=== FourBodyProblem //=== 4 bodies with equal masses, before symmetrisation. //=== We are looking for the real positive solutions ring R = 0,(B,b,D,d,F,f),dp; ideal I = (b-d)*(B-D)-2*F+2, (b-d)*(B+D-2*F)+2*(B-D), (b-d)^2-2*(b+d)+f+1, B^2*b^3-1,D^2*d^3-1,F^2*f^3-1; //=== Reimer_5 ring R = 0,(x,y,z,t,u),dp; ideal I = 2x2-2y2+2z2-2t2+2u2-1, 2x3-2y3+2z3-2t3+2u3-1, 2x4-2y4+2z4-2t4+2u4-1, 2x5-2y5+2z5-2t5+2u5-1, 2x6-2y6+2z6-2t6+2u6-1; //=== ZeroDim.example_12 ring R = 0, (x, y, z), lp; ideal I = 7xy+x+3yz+4y+2z+10, x3+x2y+3xyz+5xy+3x+2y3+6y2z+yz+1, 3x4+2x2y2+3x2y+4x2z2+xyz+xz2+6y2z+5z4; //=== ZeroDim.example_27 ring R = 0, (w, x, y, z), lp; ideal I = -2w2+9wx+9wy-7wz-4w+8x2+9xy-3xz+8x+6y2-7yz+4y-6z2+8z+2, 3w2-5wx-3wy-6wz+9w+4x2+2xy-2xz+7x+9y2+6yz+5y+7z2+7z+5, 7w2+5wx+3wy-5wz-5w+2x2+9xy-7xz+4x-4y2-5yz+6y-4z2-9z+2, 8w2+5wx-4wy+2wz+3w+5x2+2xy-7xz-7x+7y2-8yz-7y+7z2-8z+8; //=== Cassou_1 ring R = 0, (b,c,d,e), dp; ideal I = 6b4c3+21b4c2d+15b4cd2+9b4d3+36b4c2+84b4cd+30b4d2+72b4c+84b4d-8b2c2e -28b2cde+36b2d2e+48b4-32b2ce-56b2de-144b2c-648b2d-32b2e-288b2-120, 9b4c4+30b4c3d+39b4c2d2+18b4cd3+72b4c3+180b4c2d+156b4cd2+36b4d3+216b4c2 +360b4cd+156b4d2-24b2c3e-16b2c2de+16b2cd2e+24b2d3e+288b4c+240b4d -144b2c2e+32b2d2e+144b4-432b2c2-720b2cd-432b2d2-288b2ce+16c2e2-32cde2 +16d2e2-1728b2c-1440b2d-192b2e+64ce2-64de2-1728b2+576ce-576de+64e2 -240c+1152e+4704, -15b2c3e+15b2c2de-90b2c2e+60b2cde-81b2c2+216b2cd-162b2d2-180b2ce +60b2de+40c2e2-80cde2+40d2e2-324b2c+432b2d-120b2e+160ce2-160de2-324b2 +1008ce-1008de+160e2+2016e+5184, -4b2c2+4b2cd-3b2d2-16b2c+8b2d-16b2+22ce-22de+44e+261; ================================================================================ The following timings are conducted on an Intel Xeon X5460 with 4 CPUs, 3.16 GHz each, 64 GB RAM under the Gentoo Linux operating system by using the 32-bit version of Singular 3-1-1. The results of the timinings are summarized in the following table where assPrimes* denotes the parallelized version of the algorithm on 4 CPUs and (1) approach of Eisenbud, Hunecke, Vasconcelos (cf. specialAlgDepEHV), (2) approach of Gianni, Trager, Zacharias (cf. specialAlgDepGTZ), (3) approach of Monico (cf. specialAlgDepMonico). Example | minAssGTZ | assPrimes assPrimes* | | (1) (2) (3) (1) (2) (3) -------------------------------------------------------------------- Cyclic_6 | 5 | 5 10 7 4 7 6 Amrhein | 1 | 3 3 5 1 2 21 Becker-Niermann | - | 0 0 1 0 0 0 Roczen | 0 | 3 2 0 2 4 1 FourBodyProblem | - | 139 139 148 96 83 96 Reimer_5 | - | 132 128 175 97 70 103 ZeroDim.example_12 | 170 | 125 125 125 67 68 63 ZeroDim.example_27 | 27 | 215 226 215 113 117 108 Cassou_1 | 525 | 112 112 112 56 56 57 minAssGTZ (cf. primdec_lib) runs out of memory for Becker-Niermann, FourBodyProblem and Reimer_5. ================================================================================ //=== One component at the origin ring R = 0, (x,y), dp; poly f1 = (y5 + y4x7 + 2x8); poly f2 = (y3 + 7x4); poly f3 = (y7 + 2x12); poly f = f1*f2*f3 + y19; ideal I = f, diff(f, x), diff(f, y); ring R = 0, (x,y), dp; poly f1 = (y5 + y4x7 + 2x8); poly f2 = (y3 + 7x4); poly f3 = (y7 + 2x12); poly f4 = (y11 + 2x18); poly f = f1*f2*f3*f4 + y30; ideal I = f, diff(f, x), diff(f, y); ring R = 0, (x,y), dp; poly f1 = (y15 + y14x7 + 2x18); poly f2 = (y13 + 7x14); poly f3 = (y17 + 2x22); poly f = f1*f2*f3 + y49; ideal I = f, diff(f, x), diff(f, y); ring R = 0, (x,y), dp; poly f1 = (y15 + y14x20 + 2x38); poly f2 = (y19 + 3y17x50 + 7x52); poly f = f1*f2 + y36; ideal I = f, diff(f, x), diff(f, y); //=== Several components ring R = 0, (x,y), dp; poly f1 = (y5 + y4x7 + 2x8); poly f2 = (y13 + 7x14); poly f = f1*subst(f2, x, x-3, y, y+5); ideal I = f, diff(f, x), diff(f, y); ring R = 0, (x,y), dp; poly f1 = (y5 + y4x7 + 2x8); poly f2 = (y3 + 7x4); poly f3 = (y7 + 2x12); poly f = f1*f2*subst(f3, y, y+5); ideal I = f, diff(f, x), diff(f, y); ring R = 0, (x,y), dp; poly f1 = (y5 + 2x8); poly f2 = (y3 + 7x4); poly f3 = (y7 + 2x12); poly f = f1*subst(f2,x,x-1)*subst(f3, y, y+5); ideal I = f, diff(f, x), diff(f, y); */ singular-4.0.3+ds/Singular/LIB/atkins.lib000066400000000000000000001006101266270727000201260ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version atkins.lib 4.0.0.1 Jun_2014 "; category="Teaching"; info=" LIBRARY: atkins.lib Procedures for teaching cryptography AUTHOR: Stefan Steidel, steidel@mathematik.uni-kl.de NOTE: The library contains auxiliary procedures to compute the elliptic curve primality test of Atkin and the Atkin's Test itself. The library is intended to be used for teaching purposes but not for serious computations. Sufficiently high printlevel allows to control each step, thus illustrating the algorithms at work. PROCEDURES: newTest(L,D) checks if number D already exists in list L bubblesort(L) sorts elements of the list L disc(N,k) generates a list of negative discriminants Cornacchia(d,p) computes solution (x,y) for x^2+d*y^2=p CornacchiaModified(D,p) computes solution (x,y) for x^2+|D|*y^2=4p maximum(L) computes the maximal number contained in L sqr(w,k) computes the square root of w w.r.t. accuracy k expo(z,k) computes exp(z) jOft(t,k) computes the j-invariant of t round(r) rounds r to the nearest number out of Z HilbertClassPoly(D,k) computes the Hilbert Class Polynomial rootsModp(p,P) computes roots of the polynomial P modulo p wUnit(D) computes the number of units in Q(sqr(D)) Atkin(N,K,B) tries to prove that N is prime "; LIB "crypto.lib"; LIB "general.lib"; LIB "ntsolve.lib"; LIB "inout.lib"; /////////////////////////////////////////////////////////////////////////////// proc newTest(list L, def D) "USAGE: newTest(L,D); RETURN: 1, if D does not already exist in L, -1, if D does already exist in L EXAMPLE:example new; shows an example " { int a=1; // a=1 means: D does not already exist in L int i; for(i=1;i<=size(L);i++) { if(D==L[i]) { a=-1; // a=-1 means: D does already exist in L break; } } return(a); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; list L=8976,-223456,556,-778,3,-55603,45,766677; number D=-55603; newTest(L,D); } proc bubblesort(list L) "USAGE: bubblesort(L); RETURN: list L, sort in decreasing order EXAMPLE:example bubblesort; shows an example " { def b; int n,i,j; while(j==0) { i=i+1; j=1; for(n=1;n<=size(L)-i;n++) { if(L[n]=x(0))||(p<=x(0))) { x(0)=-x(0) mod p+p; } a=p; b=x(0); l=intRoot(p); while(b>l) // (3)[Euclidean algorithm] { r=a mod b; a=b; b=r; } c=(p-b^2) div d; // (4)[Test solution] i=intRoot(c); if((((p-b^2) mod d)!=0)||(c!=i^2)) { return(-1); } else { list L=b,i; return(L); } } } } example { "EXAMPLE:"; echo = 2; Cornacchia(55,9551); } proc CornacchiaModified(bigint D, bigint p) "USAGE: CornacchiaModified(D,p); RETURN: x,y such that x^2+|D|*y^2=p with p prime, -1, if the Diophantine equation has no solution, 0, if the parameters are wrong selected ASSUME: D<0, D kongruent 0 or 1 modulo 4 and |D|<4p EXAMPLE:example CornacchiaModified; shows an example " { if((D>=0)||((D mod 4)==-2)||((D mod 4)==-1)||(absValue(D)>=4*p)) { // (0)[Test if assumptions well-defined] return(0); // ERROR("Parameters wrong selected!"); } else { if(p==2) // (1)[Case p=2] { if((D+8)==intRoot(D+8)^2) { return(intRoot(D+8),1); } else { return(-1); // ERROR("The Diophantine equation has no solution!"); } } else { bigint k,x(0),a,b,l,r,c; k=Jacobi(D,p); // (2)[Test if residue] if(k==-1) { return(-1); // ERROR("The Diophantine equation has no solution!"); } else { x(0)=squareRoot(D,p); // (3)[Compute square root] if((x(0) mod 2)!=(-(D mod 2))) // D is <0 { x(0)=p-x(0); } a=2*p; b=x(0); l=intRoot(4*p); while(b>l) // (4)[Euclidean algorithm] { r=a mod b; a=b; b=r; } c=(4*p-b^2) div absValue(D); // (5)[Test solution] bigint root_c=intRoot(c); if((((4*p-b^2) mod absValue(D))!=0)||(c!=root_c^2)) { return(-1); // ERROR("The Diophantine equation has no solution!"); } else { list L=b,root_c; return(L); } } } } } example { "EXAMPLE:"; echo = 2; CornacchiaModified(-107,1319); } static proc pFactor1(number n,int B, list P) "USAGE: pFactor1(n,B,P); n to be factorized, B a bound , P a list of primes RETURN: a list of factors of n or the message: no factor found NOTE: Pollard's p-factorization creates the product k of powers of primes (bounded by B) from the list P with the idea that for a prime divisor p of n p-1|k then p devides gcd(a^k-1,n) for some random a EXAMPLE:example pFactor1; shows an example " { int i; number k=1; number w; while(iB) {break;} while(w*P[i]<=B) { w=w*P[i]; } k=k*w; } number a=random(2,2147483629); number d=gcd(powerN(a,k,n)-1,n); if((d>1)&&(dmax) { max=L[i]; } } return(max); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; list L=465,867,1233,4567,776544,233445,2334,556; maximum(L); } static proc cmod(number x, number y) "USAGE: cmod(x,y); RETURN: x mod y ASSUME: x,y out of Z and x,y<=2147483647 NOTE: this algorithm is a helping procedure to be able to calculate x mod y with x,y out of Z while working in the complex field EXAMPLE:example cmod; shows an example " { int rest=int(x-y*int(x/y)); if(rest<0) { rest=rest+int(y); } return(rest); } example { "EXAMPLE:"; echo = 2; ring r = (complex,30,i),x,dp; number x=-1004456; number y=1233; cmod(x,y); } proc sqr(number w, int k) "USAGE: sqr(w,k); RETURN: the square root of w ASSUME: w>=0 NOTE: k describes the number of decimals being calculated in the real numbers, k, intPart(k/5) are inputs for the procedure "nt_solve" EXAMPLE:example sqr; shows an example " { poly f=var(1)^2-w; def S=basering; ring R=(real,k),var(1),dp; poly f=imap(S,f); ideal I=nt_solve(f,1.1,list(k,k div 5)); number c=leadcoef(I[1]); setring S; number c=imap(R,c); return(c); } example { "EXAMPLE:"; echo = 2; ring R = (real,60),x,dp; number ww=288469650108669535726081; sqr(ww,60); } proc expo(number z, int k) "USAGE: expo(z,k); RETURN: e^z to the order k NOTE: k describes the number of summands being calculated in the exponential power series EXAMPLE:example expo; shows an example " { number q=1; number e=1; int n; for(n=1;n<=k;n++) { q=q*z/n; e=e+q; } return(e); } example { "EXAMPLE:"; echo = 2; ring r = (real,30),x,dp; number z=40.35; expo(z,1000); } proc jOft(number t, int k) "USAGE: jOft(t,k); RETURN: the j-invariant of t ASSUME: t is a complex number with positive imaginary part NOTE: k describes the number of summands being calculated in the power series, 10*k is input for the procedure @code{expo} EXAMPLE:example jOft; shows an example " { number q1,q2,qr1,qi1,tr,ti,m1,m2,f,j; number pi=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989; tr=repart(t); ti=impart(t); if(tr==-1/2){qr1=-1;} else { if(tr==0){qr1=1;} else { tr=tr-round(tr); qr1=expo(2*i*pi*tr,10*k); } } qi1=expo(-pi*ti,10*k); q1=qr1*qi1^2; q2=q1^2; int n=1; while(n<=k) { m1=m1+(-1)^n*(q1^(n*(3*n-1) div 2)+q1^(n*(3*n+1) div 2)); m2=m2+(-1)^n*(q2^(n*(3*n-1) div 2)+q2^(n*(3*n+1) div 2)); n++; } f=q1*((1+m2)/(1+m1))^24; j=(256*f+1)^3/f; return(j); } example { "EXAMPLE:"; echo = 2; ring r = (complex,30,i),x,dp; number t=(-7+i*sqr(7,250))/2; jOft(t,50); } proc round(number r) "USAGE: round(r); RETURN: the nearest number to r out of Z ASSUME: r should be a rational or a real number EXAMPLE:example round; shows an example " { number a=absValue(r); number v=r/a; number d=10; int e; while(1) { e=e+1; if(a-d^e<0) { e=e-1; break; } } number b=a; int k; for(k=0;k<=e;k++) { while(1) { b=b-d^(e-k); if(b<0) { b=b+d^(e-k); break; } } } if(b<1/2) { return(v*(a-b)); } else { return(v*(a+1-b)); } } example { "EXAMPLE:"; echo = 2; ring R = (real,50),x,dp; number r=7357683445788723456321.6788643224; round(r); } proc HilbertClassPoly(bigint D, int k) "USAGE: HilbertClassPoly(D,k); RETURN: the monic polynomial of degree h(D) in Z[X] of which jOft((D+sqr(D))/2) is a root ASSUME: D is a negative discriminant NOTE: k is input for the procedure "jOft", 5*k is input for the procedure "sqr", 10*k describes the number of decimals being calculated in the complex numbers EXAMPLE:example HilbertClassPoly; shows an example " { if(D>=0) // (0)[Test if assumptions well-defined] { ERROR("Parameter wrong selected!"); } else { def S=basering; string s1,s2,s3; bigint B=intRoot(absValue(D) div 3); ring C=(complex,10*k,i),x,dp; number DD=D; poly P=1; // (1)[Initialize] number b=cmod(DD,2); number t,a,g,tau,j; list L; bigint a1,b1,t1,g1; int step=2; while(1) { if(step==2) // (2)[Initialize a] { t=(b^2-DD)/4; L=b,1; a=maximum(L); step=3; } if(step==3) // (3)[Test] { if((cmod(t,a)!=0)) { step=4; } else { s1=string(a); s2=string(b); s3=string(t); execute("a1="+s1+";"); execute("b1="+s2+";"); execute("t1="+s3+";"); g1=gcd(gcd(a1,b1),t1 div a1); setring C; g=g1; if(g!=1) { step=4; } else { tau=(-b+i*sqr(absValue(DD),5*k))/(2*a); j=jOft(tau,k); if((a==b)||(a^2==t)||(b==0)) { P=P*(var(1)-repart(j)); step=4; } else { P=P*(var(1)^2-2*repart(j)*var(1)+repart(j)^2+impart(j)^2); step=4; } } } } if(step==4) // (4)[Loop on a] { a=a+1; if(a^2<=t) { step=3; continue; } else { step=5; } } if(step==5) // (5)[Loop on b] { b=b+2; if(b<=B) { step=2; } else { break; } } } matrix M=coeffs(P,var(1)); list liste; int n; for(n=1;n<=nrows(M);n++) { liste[n]=round(repart(number(M[n,1]))); } poly Q; int m; for(m=1;m<=size(liste);m++) { Q=Q+liste[m]*var(1)^(m-1); } string s=string(Q); setring S; execute("poly Q="+s+";"); return(Q); } } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; bigint D=-23; HilbertClassPoly(D,50); } proc rootsModp(int p, poly P) "USAGE: rootsModp(p,P); RETURN: list of roots of the polynomial P modulo p with p prime ASSUME: p>=3 NOTE: this algorithm will be called recursively, and it is understood that all the operations are done in Z/pZ (excepting squareRoot(d,p)) EXAMPLE:example rootsModp; shows an example " { if(p<3) // (0)[Test if assumptions well-defined] { ERROR("Parameter wrong selected, since p<3!"); } else { def S=basering; ring R=p,var(1),dp; poly P=imap(S,P); number d; int a; list L; poly A=gcd(var(1)^p-var(1),P); // (1)[Isolate roots in Z/pZ] if(subst(A,var(1),0)==0) { L[1]=0; A=A/var(1); } if(deg(A)==0) // (2)[Small degree?] { return(L); } if(deg(A)==1) { matrix M=coeffs(A,var(1)); L[size(L)+1]=-leadcoef(M[1,1])/leadcoef(M[2,1]); setring S; list L=imap(R,L); return(L); } if(deg(A)==2) { matrix M=coeffs(A,var(1)); d=leadcoef(M[2,1])^2-4*leadcoef(M[1,1])*leadcoef(M[3,1]); ring T=0,var(1),dp; number d=imap(R,d); number e=squareRoot(bigint(d),bigint(p)); setring R; number e=imap(T,e); L[size(L)+1]=(-leadcoef(M[2,1])+e)/(2*leadcoef(M[3,1])); L[size(L)+1]=(-leadcoef(M[2,1])-e)/(2*leadcoef(M[3,1])); setring S; list L=imap(R,L); return(L); } poly B=1; // (3)[Random splitting] poly C; while((deg(B)==0)||(deg(B)==deg(A))) { a=random(0,p-1); B=gcd((var(1)+a)^((p-1) div 2)-1,A); C=A/B; } setring S; // (4)[Recurse] poly B=imap(R,B); poly C=imap(R,C); list l=L+rootsModp(p,B)+rootsModp(p,C); return(l); } } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; poly f=x4+2x3-5x2+x; rootsModp(7,f); poly g=x5+112x4+655x3+551x2+1129x+831; rootsModp(1223,g); } proc wUnit(bigint D) "USAGE: wUnit(D); RETURN: the number of roots of unity in the quadratic order of discriminant D ASSUME: D<0 a discriminant kongruent to 0 or 1 modulo 4 EXAMPLE:example w; shows an example " { if((D>=0)||((D mod 4)==2)||((D mod 4)==3)) { ERROR("Parameter wrong selected!"); } else { if(D<-4) {return(2);} if(D==-4){return(4);} if(D==-3){return(6);} } } example { "EXAMPLE:"; echo = 2; bigint D=-3; wUnit(D); } proc Atkin(number N, int K, int B) "USAGE: Atkin(N,K,B); RETURN: 1, if N is prime, -1, if N is not prime, 0, if the algorithm is not applicable, since there are too few discriminants ASSUME: N is coprime to 6 and different from 1 NOTE: K/2 is input for the procedure "disc",@* K is input for the procedure "HilbertClassPoly",@* B describes the number of recursions being calculated.@* The basis of the algorithm is the following theorem: Let N be an integer coprime to 6 and different from 1 and E be an ellipic curve modulo N.@* Assume that we know an integer m and a point P of E(Z/NZ) satisfying the following conditions.@* (1) There exists a prime divisor q of m such that q > (4-th root(N)+1)^2.@* (2) m*P = O(E) = (0:1:0).@* (3) (m/q)*P = (x:y:t) with t element of (Z/NZ)*.@* Then N is prime. EXAMPLE:example Atkin; shows an example " { if(N==1) {return(-1);} // (0)[Test if assumptions well-defined] if((N==2)||(N==3)) {return(1);} if(gcd(N,6)!=1) { if(printlevel>=1) {"gcd(N,6) = "+string(gcd(N,6));pause();"";} return(-1); } else { int i; // (1)[Initialize] int n(i); number N(i)=N; if(printlevel>=1) {"Set i = 0, n = 0 and N(i) = N(0)= "+string(N(i))+".";pause();"";} // declarations: int j(0),j(1),j(2),j(3),j(4),k; // running indices list L; // all primes smaller than 1000 list H; // sequence of negative discriminants number D; // discriminant out of H list L1,L2,S,S1,S2,R; // lists of relevant elements list P,P1,P2; // elliptic points on E(Z/N(i)Z) number m,q; // m=|E(Z/N(i)Z)| and q|m number a,b,j,c; // characterize E(Z/N(i)Z) number g,u; // g out of Z/N(i)Z, u=Jacobi(g,N(i)) poly T; // T=HilbertClassPoly(D,K) matrix M; // M contains the coefficients of T if(printlevel>=1) {"List H of possibly suitable discriminants will be calculated.";} H=disc(bigint(N),K div 2); if(printlevel>=1) {"H = "+string(H);pause();"";} int step=2; while(1) { if(step==2) // (2)[Is N(i) small??] { L=5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997; for(j(0)=1;j(0)<=size(L);j(0)++) { if(N(i)==L[j(0)]){return(1);} if(((N(i) mod L[j(0)])==0)&&(N(i)!=L[j(0)])) { if(printlevel>=1) {"N("+string(i)+") = "+string(N(i))+" is divisible by "+string(L[j(0)])+".";pause();"";} step=14; break; } } if(step==2) { step=3; } } if(step==3) // (3)[Choose next discriminant] { n(i)=n(i)+1; if(n(i)==size(H)+1) { if(printlevel>=1) {"Algorithm is not applicable, since there are not enough suitable discriminants."; "Increase the parameter of accuracy K and start the algorithm again.";pause();"";} return(0); } D=H[n(i)]; if(printlevel>=1) {"Next discriminant D will be chosen. D = "+string(D)+".";pause();"";} if(Jacobi(D,N(i))!=1) { if(printlevel>=1) {"Jacobi(D,N("+string(i)+")) = "+string(Jacobi(D,N(i)));pause();"";} continue; } else { L1=CornacchiaModified(D,N(i)); if(size(L1)>1) { if(printlevel>=1) {"The solution (x,y) of the equation x^2+|D|y^2 = 4N("+string(i)+") is";L1;pause();"";} step=4; } else { if(L1[1]==-1) { if(printlevel>=1) {"The equation x^2+|D|y^2 = 4N("+string(i)+") has no solution.";pause();"";} continue; } if(L1[1]==0) { if(printLevel>=1) {"Algorithm is not applicable for N("+string(i)+") = "+string(N(i))+","; "since there are not enough suitable discriminants.";pause();"";} step=14; } } } } if(step==4) // (4)[Factor m] { if(printlevel>=1) {"List L2 of possible m = |E(Z/N("+string(i)+")Z)| will be calculated.";} if(absValue(L1[1])^2<=4*N(i)) {L2=N(i)+1+L1[1],N(i)+1-L1[1];} if(D==-4) { if(absValue(2*L1[2])^2<=4*N(i)) {L2[size(L2)+1]=N(i)+1+2*L1[2]; L2[size(L2)+1]=N(i)+1-2*L1[2];} } // At this point "<=4*N(i)" has been replaced by "<=16*N(i)". if(D==-3) { if(absValue(L1[1]+3*L1[2])^2<=16*N(i)) {L2[size(L2)+1]=N(i)+1+(L1[1]+3*L1[2])/2; L2[size(L2)+1]=N(i)+1-(L1[1]+3*L1[2])/2;} if(absValue(L1[1]-3*L1[2])^2<=16*N(i)) {L2[size(L2)+1]=N(i)+1+(L1[1]-3*L1[2])/2; L2[size(L2)+1]=N(i)+1-(L1[1]-3*L1[2])/2;} } /////////////////////////////////////////////////////////////// if(size(L2)==0) { if(printlevel>=1) {"Due to the theorem of Hasse there were no possible m = |E(Z/N("+string(i)+")Z)|"; "found for D = "+string(D)+".";} step=3; continue; } else { if(printlevel>=1) {"L2 = ";L2;pause();"";} } if(printlevel>=1) {"List S of factors of all possible m will be calculated.";} S=list(); for(j(1)=1;j(1)<=size(L2);j(1)++) { m=L2[j(1)]; if(m!=0) { S1=PollardRho(m,10000,1,L); S2=pFactor(m,100,L); S[size(S)+1]=list(m,S1+S2); } } if(printlevel>=1) {"S=";S;pause();"";} step=5; } if(step==5) // (5)[Does a suitable m exist??] { for(j(2)=1;j(2)<=size(S);j(2)++) { m=L2[j(2)]; for(j(3)=1;j(3)<=size(S[j(2)][2]);j(3)++) { q=S[j(2)][2][j(3)]; // sqr(sqr(N(i),50),50) replaces intRoot(intRoot(N(i))) if((q>(sqr(sqr(N(i),50),50)+1)^2) && (MillerRabin(q,5)==1)) { step=6; break; } ////////////////////////////////////////////////////// } if(step==6) { if(printlevel>=1) {"Suitable pair (m,q) has been found such that q|m,"; "q > (4-th root(N("+string(i)+"))+1)^2 and q passes the Miller-Rabin-Test."; "m = "+string(m)+",";"q = "+string(q);pause();"";} break; } else { step=3; } } if(step==3) { if(printlevel>=1) {"No suitable pair (m,q) has been found such that q|m,"; "q > (4-th root(N("+string(i)+"))+1)^2 and q passes the Miller-Rabin-Test."; pause();"";} continue; } } if(step==6) // (6)[Compute elliptic curve] { if(D==-4) { a=-1; b=0; if(printlevel>=1) {"Since D = -4, set a = -1 and b = 0.";pause();"";} } if(D==-3) { a=0; b=-1; if(printlevel>=1) {"Since D = -3, set a = 0 and b = -1.";pause();"";} } if(D<-4) { if(printlevel>=1) {"The minimal polynomial T of j((D+sqr(D))/2) in Z[X] will be calculated for D="+string(D)+".";} T=HilbertClassPoly(D,K); if(printlevel>=1) {"T = "+string(T);pause();"";} M=coeffs(T,var(1)); T=0; for(j(4)=1;j(4)<=nrows(M);j(4)++) { M[j(4),1]=leadcoef(M[j(4),1]) mod N(i); T=T+M[j(4),1]*var(1)^(j(4)-1); } if(printlevel>=1) {"Set T = T mod N("+string(i)+").";"T = "+string(T);pause();"";} R=rootsModp(int(N(i)),T); if(deg(T)>size(R)) { ERROR("The polynomial T does not completely split into linear factors modulo N("+string(i)+")." "Increase the parameter of accuracy K and start the algorithm again."); } if(printlevel>=1) {if(deg(T)>1) {"The "+string(deg(T))+" zeroes of T modulo N("+string(i)+") are"; R;pause();"";} if(deg(T)==1){"The zero of T modulo N("+string(i)+") is";R;pause();"";}} j=R[1]; c=j*exgcdN(j-1728,N(i))[1]; a=-3*c mod N(i); b=2*c mod N(i); if(printlevel>=1) {"Choose the zero j = "+string(j)+" and set"; "c = j/(j-1728) mod N("+string(i)+"), a = -3c mod N("+string(i)+"), b = 2c mod N("+string(i)+")."; "a = "+string(a)+",";"b = "+string(b);pause();"";} } step=7; } if(step==7) // (7)[Find g] { if(D==-3) { while(1) { g=random(1,2147483647) mod N(i); u=Jacobi(g,N(i)); if((u==-1)&&(powerN(g,(N(i)-1)/3,N(i))!=1)) { if(printlevel>=1) {"g = "+string(g);pause();"";} break; } } } else { while(1) { g=random(1,2147483647) mod N(i); u=Jacobi(g,N(i)); if(u==-1) { if(printlevel>=1) {"g = "+string(g);pause();"";} break; } } } step=8; } if(step==8) // (8)[Find P] { if(printlevel>=1) {"A random point P on the elliptic curve corresponding"; "to the equation y^2 = x^3+ax+b for";"N("+string(i)+") = "+string(N(i))+","; " a = "+string(a)+",";" b = "+string(b);"will be chosen.";} P=ellipticRandomPoint(N(i),a,b); if(printlevel>=1) {"P = ("+string(P)+")";pause();"";} if(size(P)==1) { step=14; } else { step=9; } } if(step==9) // (9)[Find right curve] { if(printlevel>=1) {"The points P2 = (m/q)*P and P1 = q*P2 on the curve will be calculated.";} P2=ellipticMult(N(i),a,b,P,m/q); P1=ellipticMult(N(i),a,b,P2,q); if(printlevel>=1) {"P1 = ("+string(P1)+"),";"P2 = ("+string(P2)+")";pause();"";} if((P1[1]==0)&&(P1[2]==1)&&(P1[3]==0)) { step=12; } else { if(printlevel>=1) {"Since P1 != (0:1:0), it holds m != |E(Z/N("+string(i)+")Z)| for the coefficients a = "+string(a)+" and b = "+string(b)+"."; "Therefore choose new coefficients a and b.";pause();"";} step=10; } } if(step==10) // (10)[Change coefficients] { k=k+1; if(k>=wUnit(bigint(D))) { if(printlevel>=1) {"Since k = wUnit(D) = "+string(k)+", it holds that N("+string(i)+") = "+string(N(i))+" is not prime.";pause();"";} step=14; } else { if(D<-4) {a=a*g^2 mod N(i); b=b*g^3 mod N(i); if(printlevel>=1) {"Since D < -4, set a = a*g^2 mod N("+string(i)+") and b = b*g^3 mod N("+string(i)+")."; "a = "+string(a)+",";"b = "+string(b)+",";"k = "+string(k);pause();"";}} if(D==-4){a=a*g mod N(i); if(printlevel>=1) {"Since D = -4, set a = a*g mod N("+string(i)+").";"a = "+string(a)+","; "b = "+string(b)+",";"k = "+string(k);pause();"";}} if(D==-3){b=b*g mod N(i); if(printlevel>=1) {"Since D = -3, set b = b*g mod N("+string(i)+").";"a = "+string(a)+","; "b = "+string(b)+",";"k = "+string(k);pause();"";}} step=8; continue; } } if(step==11) // (11)[Find a new P] { if(printlevel>=1) {"A new random point P on the elliptic curve will be chosen,"; "since also P2 = (0:1:0).";} P=ellipticRandomPoint(N(i),a,b); if(printlevel>=1) {"P = ("+string(P)+")";pause();"";} if(size(P)==1) { step=14; } else { if(printlevel>=1) {"The points P2 = (m/q)*P and P1 = q*P2 on the curve will be calculated.";} P2=ellipticMult(N(i),a,b,P,m/q); P1=ellipticMult(N(i),a,b,P2,q); if(printlevel>=1) {"P1 = ("+string(P1)+"),";"P2 = ("+string(P2)+")";pause();"";} if((P1[1]!=0)||(P1[2]!=1)||(P1[3]!=0)) { if(printlevel>=1) {"Since P1 != (0:1:0), it holds m != |E(Z/N("+string(i)+")Z)| for the coefficients a = "+string(a)+" and b = "+string(b)+"."; "Therefore choose new coefficients a and b.";pause();"";} step=10; continue; } else { step=12; } } } if(step==12) // (12)[Check P] { if((P2[1]==0)&&(P2[2]==1)&&(P2[3]==0)) { step=11; continue; } else { step=13; } } if(step==13) // (13)[Recurse] { if(i=1) {string(i+1)+". Recursion:";""; "N("+string(i)+") = "+string(N(i))+" suffices the conditions of the underlying theorem,"; "since P1 = (0:1:0) and P2[3] in (Z/N("+string(i)+")Z)*.";""; "Now check if also the found factor q="+string(q)+" suffices these assumptions."; "Therefore set i = i+1, N("+string(i+1)+") = q = "+string(q)+" and restart the algorithm.";pause();"";} i=i+1; int n(i); number N(i)=q; k=0; step=2; continue; } else { if(printlevel>=1) {"N(B) = N("+string(i)+") = "+string(N(i))+" suffices the conditions of the underlying theorem,"; "since P1 = (0:1:0) and P2[3] in (Z/N("+string(i)+")Z)*."; "In particular N = "+string(N)+" is prime.";pause();"";} return(1); } } if(step==14) // (14)[Backtrack] { if(i>0) { if(printlevel>=1) {"Set i = i-1 and restart the algorithm for N("+string(i-1)+") = "+string(N(i-1))+" with"; "a new discriminant.";pause();"";} i=i-1; k=0; step=3; } else { if(printlevel>=1) {"N(0) = N = "+string(N)+" and therefore N is not prime.";pause();"";} return(-1); } } } } } example { "EXAMPLE:"; echo = 2; ring R = 0,x,dp; Atkin(7691,100,5); Atkin(3473,10,2); printlevel=1; Atkin(10000079,100,2); } singular-4.0.3+ds/Singular/LIB/bfun.lib000066400000000000000000001550311266270727000175760ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version bfun.lib 4.0.0.0 Jun_2013 "; // $Id: ec07870569d6828b6cb89ea4e65c85db66e7e604 $ category="Noncommutative"; info=" LIBRARY: bfun.lib Algorithms for b-functions and Bernstein-Sato polynomial AUTHORS: Daniel Andres, daniel.andres@math.rwth-aachen.de @* Viktor Levandovskyy, levandov@math.rwth-aachen.de OVERVIEW: Given a polynomial ring R = K[x_1,...,x_n] and a polynomial F in R, one is interested in the global b-function (also known as Bernstein-Sato polynomial) b(s) in K[s], defined to be the non-zero monic polynomial of minimal degree, satisfying a functional identity L * F^{s+1} = b(s) F^s, for some operator L in D[s] (* stands for the action of differential operator)@* By D one denotes the n-th Weyl algebra K. One is interested in the following data:@* - Bernstein-Sato polynomial b(s) in K[s],@* - the list of its roots, which are known to be rational@* - the multiplicities of the roots.@* There is a constructive definition of a b-function of a holonomic ideal I in D (that is, an ideal I in a Weyl algebra D, such that D/I is holonomic module) with respect to the given weight vector w: For a polynomial p in D, its initial form w.r.t. (-w,w) is defined as the sum of all terms of p which have maximal weighted total degree where the weight of x_i is -w_i and the weight of d_i is w_i. Let J be the initial ideal of I w.r.t. (-w,w), i.e. the K-vector space generated by all initial forms w.r.t (-w,w) of elements of I. Put s = w_1 x_1 d_1 + ... + w_n x_n d_n. Then the monic generator b_w(s) of the intersection of J with the PID K[s] is called the b-function of I w.r.t. w. Unlike Bernstein-Sato polynomial, general b-function with respect to arbitrary weights need not have rational roots at all. However, b-function of a holonomic ideal is known to be non-zero as well. REFERENCES: [SST] Saito, Sturmfels, Takayama: Groebner Deformations of Hypergeometric Differential Equations (2000),@* Noro: An Efficient Modular Algorithm for Computing the Global b-function, (2002). PROCEDURES: bfct(f[,s,t,v]); compute the BS polynomial of f with linear reductions bfctSyz(f[,r,s,t,u,v]); compute the BS polynomial of f with syzygy-solver bfctAnn(f[,s]); compute the BS polynomial of f via Ann f^s + f bfctOneGB(f[,s,t]); compute the BS polynomial of f by just one GB computation bfctIdeal(I,w[,s,t]); compute the b-function of ideal w.r.t. weight pIntersect(f,I[,s]); intersection of ideal with subalgebra K[f] for a polynomial f pIntersectSyz(f,I[,p,s,t]); intersection of ideal with subalgebra K[f] with syz-solver linReduce(f,I[,s]); reduce a polynomial by linear reductions w.r.t. ideal linReduceIdeal(I,[s,t]); interreduce generators of ideal by linear reductions linSyzSolve(I[,s]); compute a linear dependency of elements of ideal I allPositive(v); checks whether all entries of an intvec are positive scalarProd(v,w); computes the standard scalar product of two intvecs vec2poly(v[,i]); constructs an univariate polynomial with given coefficients SEE ALSO: dmod_lib, dmodapp_lib, dmodvar_lib, gmssing_lib KEYWORDS: D-module; global Bernstein-Sato polynomial; Bernstein-Sato polynomial; b-function; graded Weyl algebra; initial ideal; initial form; principal intersection; linear interreduction; initial ideal approach "; /* CHANGELOG 03.03.11: - simplified scalarProd - fixed bug in bfct when user used vars t,Dt - now bFactor is used by bfct, bfctAnn, i.e. the static procs addRoot, listofroots are superfluous - fixed printlevel/debug message issue in bfct, bfctAnn - fixed small issue for zero ideal input in linReduceIdeal 16.03.11 - fixed bug in linReduceIdeal when ideal contained unlucky constellation of zeros - fixed printlevel/debug message issue in linReduceIdeal */ LIB "qhmoduli.lib"; // for Max LIB "dmod.lib"; // for SannfsBFCT etc LIB "dmodapp.lib"; // for initialIdealW etc LIB "nctools.lib"; // for isWeyl etc LIB "presolve.lib"; // for valvars //--------------- auxiliary procedures ---------------------------------------- /* static proc gradedWeyl (intvec u,intvec v) "USAGE: gradedWeyl(u,v); u,v intvecs RETURN: a ring, the associated graded ring of the basering w.r.t. u and v PURPOSE: compute the associated graded ring of the basering w.r.t. u and v ASSUME: basering is a Weyl algebra EXAMPLE: example gradedWeyl; shows examples NOTE: u[i] is the weight of x(i), v[i] the weight of D(i). @* u+v has to be a non-negative intvec. " { // todo check assumption int i; def save = basering; int n = nvars(save) div 2; if (nrows(u)<>n || nrows(v)<>n) { ERROR("weight vectors have wrong dimension"); } intvec uv,gr; uv = u+v; for (i=1; i<=n; i++) { if (uv[i]>=0) { if (uv[i]==0) { gr[i] = 0; } else { gr[i] = 1; } } else { ERROR("the sum of the weight vectors has to be a non-negative intvec"); } } list l = ringlist(save); list l2 = l[2]; matrix l6 = l[6]; for (i=1; i<=n; i++) { if (gr[i] == 1) { l2[n+i] = "xi("+string(i)+")"; l6[i,n+i] = 0; } } l[2] = l2; l[6] = l6; def G = ring(l); return(G); } example { "EXAMPLE:"; echo = 2; ring @D = 0,(x,y,z,Dx,Dy,Dz),dp; def D = Weyl(); setring D; intvec u = -1,-1,1; intvec v = 2,1,1; def G = gradedWeyl(u,v); setring G; G; } */ static proc safeVarName (string s) { string S = "," + charstr(basering) + "," + varstr(basering) + ","; s = "," + s + ","; while (find(S,s) <> 0) { s[1] = "@"; s = "," + s; } s = s[2..size(s)-1]; return(s) } proc allPositive (intvec v) "USAGE: allPositive(v); v an intvec RETURN: int, 1 if all components of v are positive, or 0 otherwise PURPOSE: check whether all components of an intvec are positive EXAMPLE: example allPositive; shows an example " { int i; for (i=1; i<=size(v); i++) { if (v[i]<=0) { return(0); break; } } return(1); } example { "EXAMPLE:"; echo = 2; intvec v = 1,2,3; allPositive(v); intvec w = 1,-2,3; allPositive(w); } static proc findFirst (list l, def i) "USAGE: findFirst(l,i); l a list, i an argument of any type RETURN: int, the position of the first appearance of i in l, @* or 0 if i is not a member of l PURPOSE: check whether the second argument is a member of a list EXAMPLE: example findFirst; shows an example " { int j; for (j=1; j<=size(l); j++) { if (l[j]==i) { return(j); break; } } return(0); } // findFirst(list(1, 2, list(1)),2); // seems to be a bit buggy, // findFirst(list(1, 2, list(1)),3); // but works for the purposes // findFirst(list(1, 2, list(1)),list(1)); // of this library // findFirst(l,list(2)); example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; list l = 1,2,3; findFirst(l,4); findFirst(l,2); } proc scalarProd (intvec v, intvec w) "USAGE: scalarProd(v,w); v,w intvecs RETURN: int, the standard scalar product of v and w PURPOSE: computes the scalar product of two intvecs ASSUME: the arguments are of the same size EXAMPLE: example scalarProd; shows examples " { if (size(v)!=size(w)) { ERROR("non-matching dimensions"); } else { intvec u = transpose(v)*w; } return(u[1]); } example { "EXAMPLE:"; echo = 2; intvec v = 1,2,3; intvec w = 4,5,6; scalarProd(v,w); } //-------------- main procedures ------------------------------------------------------- proc linReduceIdeal(ideal I, list #) "USAGE: linReduceIdeal(I [,s,t,u]); I an ideal, s,t,u optional ints RETURN: ideal or list, linear reductum (over field) of I by its elements PURPOSE: reduces a list of polys only by linear reductions (no monomial @* multiplications) NOTE: If s<>0, a list consisting of the reduced ideal and the coefficient @* vectors of the used reductions given as module is returned. @* Otherwise (and by default), only the reduced ideal is returned. @* If t<>0 (and by default) all monomials are reduced (if possible), @* otherwise, only leading monomials are reduced. @* If u<>0 (and by default), the ideal is first sorted in increasing order. @* If u is set to 0 and the given ideal is not sorted in the way described, @* the result might not be as expected. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example linReduceIdeal; shows examples " { // #[1] = remembercoeffs // #[2] = redtail // #[3] = sortideal int ppl = printlevel - voice + 2; int remembercoeffs = 0; // default int redtail = 1; // default int sortideal = 1; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { remembercoeffs = #[1]; } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { redtail = #[2]; } if (size(#)>2) { if (typeof(#[3])=="int" || typeof(#[3])=="number") { sortideal = #[3]; } } } } int sI = ncols(I); int sZeros = sI - size(I); int i,j,k; ideal J,lmJ,ordJ; list lJ = sort(I); intvec iv,iv2; //todo module M; // for the coefficients // step 1: prepare, e.g. sort I if (sortideal <> 0) { if (sZeros > 0) // I contains zeros { if (remembercoeffs <> 0) { j = 0; k = 0; intvec posNonZero; for (i=1; i<=sI; i++) { if (I[i] == 0) { j++; J[j] = 0; ordJ[j] = -1; M[j] = gen(i); } else { k++; M[k+sZeros] = gen(lJ[2][k]); posNonZero = posNonZero,i; } } posNonZero = posNonZero[2..nrows(posNonZero)]; posNonZero = posNonZero[lJ[2]]; for (i=1; i<=size(lJ[1]); i++) { M[i+sZeros] = gen(posNonZero[i]); } kill posNonZero; } else { for (i=1; i<=sZeros; i++) { J[i] = 0; ordJ[i] = -1; } } I = J,lJ[1]; } else // I contains no zeros { I = lJ[1]; if (remembercoeffs <> 0) { for (i=1; i<=size(lJ[1]); i++) { M[i] = gen(lJ[2][i]); } } } } else // assume I is already sorted { if (remembercoeffs <> 0) { for (i=1; i<=ncols(I); i++) { M[i] = gen(i); } } } dbprint(ppl,"// initially sorted ideal:", I); if (remembercoeffs <> 0) { dbprint(ppl,"// used permutations:", M); } // step 2: reduce leading monomials by linear reductions poly lm,c,redpoly,maxlmJ; J[sZeros+1] = I[sZeros+1]; lm = I[sZeros+1]; maxlmJ = leadmonom(lm); lmJ[sZeros+1] = maxlmJ; int ordlm,reduction; ordJ[sZeros+1] = ord(lm); vector v; int noRedPast; for (i=sZeros+2; i<=sI; i++) { redpoly = I[i]; lm = leadmonom(redpoly); ordlm = ord(lm); if (remembercoeffs <> 0) { v = M[i]; } reduction = 1; while (reduction == 1) // while there was a reduction { noRedPast = i; reduction = 0; for (j=sZeros+1; j maxlmJ) { break; } //lm is bigger than maximal monomial to reduce with if (ordlm == ordJ[j]) { if (lm == lmJ[j]) { dbprint(ppl-1,"// reducing " + string(redpoly)); dbprint(ppl-1,"// with " + string(J[j])); c = leadcoef(redpoly)/leadcoef(J[j]); redpoly = redpoly - c*J[j]; dbprint(ppl-1,"// to " + string(redpoly)); lm = leadmonom(redpoly); ordlm = ord(lm); if (remembercoeffs <> 0) { M[i] = M[i] - c * M[j]; } noRedPast = j; reduction = 1; } } } } for (j=sZeros+1; j 0) { v = M[i]; M = deleteGenerator(M,i); M = insertGenerator(M,v,j); } maxlmJ = lmJ[i]; } // step 3: reduce tails by linear reductions as well if (redtail <> 0) { dbprint(ppl,"// finished reducing leading monomials"); dbprint(ppl-1,string(J)); if (remembercoeffs <> 0) { dbprint(ppl-1,"// used reductions:" + string(M)); } for (i=sZeros+1; i<=sI; i++) { lm = lmJ[i]; for (j=i+1; j<=sI; j++) { for (k=2; k<=size(J[j]); k++) // run over all terms in J[j] { if (ordJ[i] == ord(J[j][k])) { if (lm == normalize(J[j][k])) { c = leadcoef(J[j][k])/leadcoef(J[i]); dbprint(ppl-1,"// reducing " + string(J[j])); dbprint(ppl-1,"// with " + string(J[i])); J[j] = J[j] - c*J[i]; dbprint(ppl-1,"// to " + string(J[j])); if (remembercoeffs <> 0) { M[j] = M[j] - c * M[i]; } } } } } } } if (sI == sZeros) // if I=0,0,...,0, we now have one too much by construction due to sort { J = J[1..sZeros]; } if (remembercoeffs <> 0) { return(list(J,M)); } else { return(J); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; ideal I = 3,x+9,y4+5x,2y4+7x+2; linReduceIdeal(I); // reduces tails linReduceIdeal(I,0,0); // no reductions of tails list l = linReduceIdeal(I,1); // reduces tails and shows reductions used l; module M = I; matrix(l[1]) - M*l[2]; } proc linReduce(poly f, ideal I, list #) "USAGE: linReduce(f, I [,s,t,u]); f a poly, I an ideal, s,t,u optional ints RETURN: poly or list, linear reductum (over field) of f by elements from I PURPOSE: reduce a polynomial only by linear reductions (no monomial multiplications) NOTE: If s<>0, a list consisting of the reduced polynomial and the coefficient @* vector of the used reductions is returned, otherwise (and by default) @* only reduced polynomial is returned. @* If t<>0 (and by default) all monomials are reduced (if possible), @* otherwise, only leading monomials are reduced. @* If u<>0 (and by default), the ideal is linearly pre-reduced, i.e. @* instead of the given ideal, the output of @code{linReduceIdeal} is used. @* If u is set to 0 and the given ideal does not equal the output of @* @code{linReduceIdeal}, the result might not be as expected. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example linReduce; shows examples " { int ppl = printlevel - voice + 2; int remembercoeffs = 0; // default int redtail = 1; // default int prepareideal = 1; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { remembercoeffs = #[1]; } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { redtail = #[2]; } if (size(#)>2) { if (typeof(#[3])=="int" || typeof(#[3])=="number") { prepareideal = #[3]; } } } } int i,j,k; int sI = ncols(I); // pre-reduce I: module M; if (prepareideal <> 0) { if (remembercoeffs <> 0) { list sortedI = linReduceIdeal(I,1,redtail); I = sortedI[1]; M = sortedI[2]; dbprint(ppl-1,"// prepared ideal:" +string(I)); dbprint(ppl-1,"// with operations:" +string(M)); } else { I = linReduceIdeal(I,0,redtail); } } else { if (remembercoeffs <> 0) { for (i=1; i<=sI; i++) { M[i] = gen(i); } } } ideal lmI,lcI,ordI; for (i=1; i<=sI; i++) { lmI[i] = leadmonom(I[i]); lcI[i] = leadcoef(I[i]); ordI[i] = ord(lmI[i]); } vector v; poly c; // === reduce leading monomials === poly lm = leadmonom(f); int ordf = ord(lm); for (i=sI; i>=1; i--) // I is sorted: smallest lm's on top { if (lm == 0) { break; } else { if (ordf == ordI[i]) { if (lm == lmI[i]) { c = leadcoef(f)/lcI[i]; f = f - c*I[i]; lm = leadmonom(f); ordf = ord(lm); if (remembercoeffs <> 0) { v = v - c * M[i]; } } } } } // === reduce tails as well === if (redtail <> 0) { dbprint(ppl,"// finished reducing leading monomials"); dbprint(ppl-1,string(f)); if (remembercoeffs <> 0) { dbprint(ppl-1,"// used reductions:" + string(v)); } for (i=1; i<=sI; i++) { dbprint(ppl,"// testing ideal entry "+string(i)); for (j=1; j<=size(f); j++) { if (ord(f[j]) == ordI[i]) { if (normalize(f[j]) == lmI[i]) { c = leadcoef(f[j])/lcI[i]; f = f - c*I[i]; dbprint(ppl-1,"// reducing with " + string(I[i])); dbprint(ppl-1,"// to " + string(f)); if (remembercoeffs <> 0) { v = v - c * M[i]; } } } } } } if (remembercoeffs <> 0) { list l = f,v; return(l); } else { return(f); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; ideal I = 1,y,xy; poly f = 5xy+7y+3; poly g = 7x+5y+3; linReduce(g,I); // reduces tails linReduce(g,I,0,0); // no reductions of tails linReduce(f,I,1); // reduces tails and shows reductions used f = x3+y2+x2+y+x; I = x3-y3, y3-x2,x3-y2,x2-y,y2-x; list l = linReduce(f,I,1); l; module M = I; f - (l[1]-(M*l[2])[1,1]); } proc linSyzSolve (ideal I, list #) "USAGE: linSyzSolve(I[,s]); I an ideal, s an optional int RETURN: vector, coefficient vector of linear combination of 0 in elements of I PURPOSE: compute a linear dependency between the elements of an ideal @* if such one exists NOTE: If s<>0, @code{std} is used for Groebner basis computations, @* otherwise, @code{slimgb} is used. @* By default, @code{slimgb} is used in char 0 and @code{std} in char >0. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example linSyzSolve; shows examples " { int whichengine = 0; // default int enginespecified = 0; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { whichengine = int( #[1]); enginespecified = 1; } } int ppl = printlevel - voice +2; int sI = ncols(I); // check if we are done if (I[sI]==0) { vector v = gen(sI); } else { // ------- 1. introduce undefined coeffs ------------------ def save = basering; list RL = ringlist(save); int nv = nvars(save); int np = npars(save); int p = char(save); string cs = "(" + charstr(save) + ")"; if (enginespecified == 0) { if (p <> 0) { whichengine = 1; } } int i; list Lvar; for (i=1; i<=sI; i++) { Lvar[i] = safeVarName("@a(" + string(i) + ")"); } list L@A = RL[1..4]; L@A[2] = Lvar; L@A[3] = list(list("lp",intvec(1:sI)),list("C",intvec(0))); def @A = ring(L@A); L@A[2] = list(safeVarName("@z")); L@A[3][1] = list("dp",intvec(1)); if (size(L@A[1])>1) { L@A[1][2] = L@A[1][2] + Lvar; L@A[1][3][size(L@A[1][3])+1] = list("lp",intvec(1:sI)); } else { L@A[1] = list(p,Lvar,list(list("lp",intvec(1:sI))),ideal(0)); } def @aA = ring(L@A); def @B = save + @aA; setring @B; ideal I = imap(save,I); // ------- 2. form the linear system for the undef coeffs --- poly W; ideal QQ; for (i=1; i<=sI; i++) { W = W + par(np+i)*I[i]; } while (W!=0) { QQ = QQ,leadcoef(W); W = W - lead(W); } // QQ consists of polynomial expressions in @a(i) of type number setring @A; ideal QQ = imap(@B,QQ); // ------- 3. this QQ is a polynomial ideal, so "solve" the system ----- dbprint(ppl, "// linSyzSolve: starting Groebner basis computation with engine:", whichengine); QQ = engine(QQ,whichengine); dbprint(ppl, "// QQ after engine:", QQ); if (dim(QQ) == -1) { dbprint(ppl+1, "// no solutions by linSyzSolve"); // output zeroes setring save; kill @A,@aA,@B; return(v); } // ------- 4. in order to get the numeric values ------- matrix AA = matrix(maxideal(1)); module MQQ = std(module(QQ)); AA = NF(AA,MQQ); // todo: we still receive NF warnings dbprint(ppl, "// AA after NF:",AA); // "AA after NF:"; print(AA); for(i=1; i<=sI; i++) { AA = subst(AA,var(i),1); } dbprint(ppl, "// AA after subst:",AA); // "AA after subst: "; print(AA); vector v = (module(transpose(AA)))[1]; setring save; vector v = imap(@A,v); kill @A,@aA,@B; } return(v); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; ideal I = x,2x; linSyzSolve(I); ideal J = x,x2; linSyzSolve(J); } proc pIntersect (poly s, ideal I, list #) "USAGE: pIntersect(f, I [,s]); f a poly, I an ideal, s an optional int RETURN: vector, coefficient vector of the monic polynomial PURPOSE: compute the intersection of ideal I with the subalgebra K[f] ASSUME: I is given as Groebner basis, basering is not a qring. NOTE: If the intersection is zero, this proc might not terminate. @* If s>0 is given, it is searched for the generator of the intersection @* only up to degree s. Otherwise (and by default), no bound is assumed. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example pIntersect; shows examples " { def save = basering; int n = nvars(save); list RL = ringlist(save); int i,j,k; if (RL[4]<>0) { ERROR ("basering must not be a qring"); } // assume I is given in Groebner basis if (attrib(I,"isSB") <> 1) { print("// WARNING: The input has no SB attribute!"); print("// Treating it as if it were a Groebner basis and proceeding..."); attrib(I,"isSB",1); // set attribute for suppressing NF messages } int bound = 0; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { bound = #[1]; } } int ppl = printlevel-voice+2; // ---case 1: I = basering--- if (size(I) == 1) { if (simplify(I,2)[1] == 1) { return(gen(1)); // = 1 } } // ---case 2: intersection is zero--- intvec degs = leadexp(s); intvec possdegbounds; list degI; i = 1; while (i <= ncols(I)) { if (i == ncols(I)+1) { break; } degI[i] = leadexp(I[i]); for (j=1; j<=n; j++) { if (degs[j] == 0) { if (degI[i][j] <> 0) { break; } } if (j == n) { k++; possdegbounds[k] = Max(degI[i]); } } i++; } int degbound = Min(possdegbounds); if (bound>0 && bound0 && i>bound) { return(vector(0)); } dbprint(ppl,"// Testing degree "+string(i)); if (i>1) { oldNF = newNF; tobracket = s^(i-1) - oldNF; if (tobracket==0) // todo bug in bracket? { toNF = 0; } else { toNF = bracket(tobracket,secNF); } newNF = NF(toNF+oldNF*secNF,I); // = NF(s^i,I) } else { newNF = NF(s,I); secNF = newNF; } ll = linReduce(newNF,redNI,1); rednewNF = ll[1]; l[i+1] = ll[2]; dbprint(ppl-1,"// newNF is: "+string(newNF)); dbprint(ppl-1,"// rednewNF is: "+string(rednewNF)); if (rednewNF != 0) // no linear dependency { redNI[i+1] = rednewNF; i++; } else // there is a linear dependency, hence we are done { dbprint(ppl,"// degree of the generator of the intersection is: "+string(i)); break; } } dbprint(ppl-1,"// used linear reductions:", l); // we obtain the coefficients of the generator by the used reductions: list Lvar; for (j=1; j<=i+1; j++) { Lvar[j] = safeVarName("a("+string(j)+")"); } list Lord = list("dp",intvec(1:(i+1))),list("C",intvec(0)); list L@R = RL[1..4]; L@R[2] = Lvar; L@R[3] = Lord; def @R = ring(L@R); setring @R; list l = imap(save,l); ideal C; for (j=1;j<=i+1;j++) { C[j] = 0; for (k=1;k<=j;k++) { C[j] = C[j]+l[j][k]*var(k); } } for (j=i;j>=1;j--) { C[i+1]= subst(C[i+1],var(j),var(j)+C[j]); } matrix m = coeffs(C[i+1],maxideal(1)); vector v = gen(i+1); for (j=1;j<=i+1;j++) { v = v + m[j,1]*gen(j); } setring save; v = imap(@R,v); kill @R; return(v); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = x^2+y^3+x*y^2; def D = initialMalgrange(f); setring D; inF; pIntersect(t*Dt,inF); pIntersect(t*Dt,inF,1); } proc pIntersectSyz (poly s, ideal I, list #) "USAGE: pIntersectSyz(f, I [,p,s,t]); f poly, I ideal, p,t optial ints, p prime RETURN: vector, coefficient vector of the monic polynomial PURPOSE: compute the intersection of an ideal I with the subalgebra K[f] ASSUME: I is given as Groebner basis. NOTE: If the intersection is zero, this procedure might not terminate. @* If p>0 is given, this proc computes the generator of the intersection in @* char p first and then only searches for a generator of the obtained @* degree in the basering. Otherwise, it searches for all degrees by @* computing syzygies. @* If s<>0, @code{std} is used for Groebner basis computations in char 0, @* otherwise, and by default, @code{slimgb} is used. @* If t<>0 and by default, @code{std} is used for Groebner basis @* computations in char >0, otherwise, @code{slimgb} is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example pIntersectSyz; shows examples " { // assume I is given as Groebner basis if (attrib(I,"isSB") <> 1) { print("// WARNING: The input has no SB attribute!"); print("// Treating it as if it were a Groebner basis and proceeding..."); attrib(I,"isSB",1); // set attribute for suppressing NF messages } int ppl = printlevel-voice+2; int whichengine = 0; // default int modengine = 1; // default int solveincharp = 0; // default def save = basering; int n = nvars(save); if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { solveincharp = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { whichengine = int(#[2]); } if (size(#)>2) { if (typeof(#[3])=="int" || typeof(#[3])=="number") { modengine = int(#[3]); } } } } int i,j; vector v; poly tobracket,toNF,newNF,p; ideal NI = 1; newNF = NF(s,I); NI[2] = newNF; list RL = ringlist(save); if (solveincharp) { int psolveincharp = prime(solveincharp); if (solveincharp <> psolveincharp) { print("// " + string(solveincharp) + " is invalid characteristic of ground field."); print("// " + string(psolveincharp) + " is used."); solveincharp = psolveincharp; kill psolveincharp; } list RLp = RL[1..4]; if (typeof(RL[1]) == "int") { RLp[1] = solveincharp; } else { RLp[1][1] = solveincharp; } // parameters def @Rp = ring(RLp); setring @Rp; number c; setring save; int shortSave = short; // workaround for maps Q(a_i) -> Z/p(a_i) short = 0; string str; int badprime; i=1; while (badprime == 0 && i<=size(s)) // detect bad primes { str = string(denominator(leadcoef(s[i]))); str = "c = " + str + ";"; setring @Rp; execute(str); if (c == 0) { badprime = 1; } setring save; i++; } str = "poly s = " + string(s) + ";"; if (size(RL) > 4) // basering is NC-algebra { string RL5 = "@C = " + string(RL[5]) + ";"; string RL6 = "@D = " + string(RL[6]) + ";"; setring @Rp; matrix @C[n][n]; matrix @D[n][n]; execute(RL5); execute(RL6); def Rp = nc_algebra(@C,@D); } else { def Rp = @Rp; } setring Rp; kill @Rp; dbprint(ppl-1,"// solving in ring ", Rp); execute(str); vector v; number c; ideal NI = 1; setring save; i=1; while (badprime == 0 && i<=size(I)) // detect bad primes { str = string(leadcoef(cleardenom(I[i]))); str = "c = " + str + ";"; setring Rp; execute(str); if (c == 0) { badprime = 1; } setring save; i++; } if (badprime == 1) { print("// WARNING: bad prime"); short = shortSave; return(vector(0)); } } i = 1; dbprint(ppl,"// pIntersectSyz starts..."); dbprint(ppl-1,"// with ideal I=", I); while (1) { dbprint(ppl,"// testing degree: "+string(i)); if (i>1) { tobracket = s^(i-1)-NI[i]; if (tobracket!=0) { toNF = bracket(tobracket,NI[2]) + NI[i]*NI[2]; } else { toNF = NI[i]*NI[2]; } newNF = NF(toNF,I); NI[i+1] = newNF; } // look for a solution dbprint(ppl-1,"// linSyzSolve starts with: "+string(matrix(NI))); if (solveincharp) // modular method { for (j=1; j<=size(newNF); j++) { str = string(denominator(leadcoef(s[i]))); str = "c = " + str + ";"; setring Rp; execute(str); if (c == 0) { print("// WARNING: bad prime"); setring save; short = shortSave; return(vector(0)); } setring save; } str = "NI[" + string(i) + "+1] = " + string(newNF) + ";"; setring Rp; execute(str); // NI[i+1] = [newNF]_{solveincharp} v = linSyzSolve(NI,modengine); if (v!=0) // there is a modular solution { dbprint(ppl,"// got solution in char "+string(solveincharp)+" of degree "+string(i)); setring save; v = linSyzSolve(NI,whichengine); if (v==0) { break; } } else // no modular solution { setring save; v = 0; } } else // non-modular method { v = linSyzSolve(NI,whichengine); } matrix MM[1][nrows(v)] = matrix(v); dbprint(ppl-1,"// linSyzSolve ready with: "+string(MM)); kill MM; // "linSyzSolve ready with"; print(v); if (v!=0) { // a solution: //check for the reality of the solution p = 0; for (j=1; j<=i+1; j++) { p = p + v[j]*NI[j]; } if (p!=0) { dbprint(ppl,"// linSyzSolve: bad solution!"); } else { dbprint(ppl,"// linSyzSolve: got solution!"); // "got solution!"; break; } } // no solution: i++; } dbprint(ppl,"// pIntersectSyz finished"); if (solveincharp) { short = shortSave; } return(v); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = x^2+y^3+x*y^2; def D = initialMalgrange(f); setring D; inF; poly s = t*Dt; pIntersectSyz(s,inF); int p = prime(20000); pIntersectSyz(s,inF,p,0,0); } proc vec2poly (list #) "USAGE: vec2poly(v [,i]); v a vector or an intvec, i an optional int RETURN: poly, an univariate polynomial in i-th variable with coefficients given by v PURPOSE: constructs an univariate polynomial in K[var(i)] with given coefficients, @* such that the coefficient at var(i)^{j-1} is v[j]. NOTE: The optional argument i must be positive, by default i is 1. EXAMPLE: example vec2poly; shows examples " { def save = basering; int i,ringvar; ringvar = 1; // default if (size(#) > 0) { if (typeof(#[1])=="vector" || typeof(#[1])=="intvec") { def v = #[1]; } else { ERROR("wrong input: expected vector/intvec expression"); } if (size(#) > 1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { ringvar = int(#[2]); } } } if (ringvar > nvars(save)) { ERROR("var out of range"); } poly p; for (i=1; i<=nrows(v); i++) { p = p + v[i]*(var(ringvar))^(i-1); } return(p); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; vector v = gen(1) + 3*gen(3) + 22/9*gen(4); intvec iv = 3,2,1; vec2poly(v,2); vec2poly(iv); } /* // // listofroots and addRoots aren't needed anymore due to some modifications // // static proc listofroots (list #) // { // def save = basering; // int n = nvars(save); // int i; // poly p; // if (typeof(#[1])=="vector") // { // vector b = #[1]; // for (i=1; i<=nrows(b); i++) // { // p = p + b[i]*(var(1))^(i-1); // } // } // else // { // p = #[1]; // } // int substitution = int(#[2]); // string s = safeVarName("s"); // list RL = ringlist(save); RL = RL[1..4]; // RL[2] = list(s); RL[3] = list(list("dp",intvec(1)),list("C",0)); // def S = ring(RL); setring S; // ideal J; // for (i=1; i<=n; i++) // { // J[i] = var(1); // } // map @m = save,J; // poly p = @m(p); // if (substitution == 1) // { // p = subst(p,var(1),-var(1)-1); // } // // the rest of this proc is nicked from bernsteinBM from dmod.lib // list P = factorize(p);//with constants and multiplicities // ideal bs; intvec m; //the BS polynomial is monic, so we are not interested in constants // for (i=2; i<= size(P[1]); i++) //we delete P[1][1] and P[2][1] // { // bs[i-1] = P[1][i]; // m[i-1] = P[2][i]; // } // bs = normalize(bs); // bs = -subst(bs,var(1),0); // setring save; // ideal bs = imap(S,bs); // kill S; // list BS = bs,m; // return(BS); // } // // // static proc addRoot(number q, list L) // { // // add root to list in bFactor format // int i,qInL; // ideal I = L[1]; // intvec v = L[2]; // list LL; // if (v == 0) // { // I = poly(q); // v = 1; // LL = I,v; // } // else // { // for (i=1; i<=ncols(I); i++) // { // if (I[i] == q) // { // qInL = i; // break; // } // } // if (qInL) // { // v[qInL] = v[qInL] + 1; // } // else // { // I = q,I; // v = 1,v; // } // } // LL = I,v; // if (size(L) == 3) // irreducible factor // { // if (L[3] <> "0" && L[3] <> "1") // { // LL = LL + list(L[3]); // } // } // return(LL); // } */ static proc bfctengine (poly f, int inorann, int whichengine, int addPD, int stdsum, int methodord, int methodpIntersect, int pIntersectchar, int modengine, intvec u0) { int printlevelsave = printlevel; printlevel = printlevel + 1; int ppl = printlevel - voice + 2; int i; def save = basering; int n = nvars(save); if (isCommutative() == 0) { ERROR("basering must be commutative"); } if (char(save) <> 0) { ERROR("characteristic of basering has to be 0"); } list L = ringlist(save); int qr; if (L[4] <> 0) // qring { print("// basering is qring:"); print("// discarding the quotient and proceeding..."); L[4] = ideal(0); qr = 1; def save2 = ring(L); setring save2; poly f = imap(save,f); } if (inorann == 0) // bfct using initial ideal { // list L = ringlist(basering); intvec iv = valvars(f)[1]; // heuristacally better ordering for initialMalgrange list varL = L[2]; varL = varL[iv]; L[2] = varL; if (u0 <> 0) { u0 = u0[iv]; } def newr = ring(L); kill varL,iv,L; setring newr; poly f = imap(save,f); dbprint(ppl,"// starting computation of the initial ideal of the Malgrange ideal..."); def D = initialMalgrange(f,whichengine,methodord,u0); dbprint(ppl,"// ...done"); setring D; ideal J = inF; kill inF; poly s = var(1)*var(n+2); } else // bfct using Ann(f^s) { dbprint(ppl,"// starting computation of the s-parametric annihilator..."); def D = SannfsBFCT(f,addPD,whichengine,stdsum); dbprint(ppl,"// ...done"); setring D; ideal J = LD; kill LD; poly s = var(1); } vector b; dbprint(ppl,"// starting to intersect with subalgebra..."); // try it modular if (methodpIntersect <> 0) // pIntersectSyz { if (pIntersectchar == 0) // pIntersectSyz::modular { list L = ringlist(D); int lb = 10000; int ub = 536870909; // bounds for random primes list usedprimes; int sJ = size(J); int sLJq; ideal LJ; for (i=1; i<=sJ; i++) { LJ[i] = leadcoef(cleardenom(J[i])); } int short_save = short; // workaround for map Q(a_i) -> Z/q(a_i) short = 0; string strLJq = "ideal LJq = " + string(LJ) + ";"; int nD = nvars(D); string L5 = "matrix @C[nD][nD]; @C = " + string(L[5]) + ";"; string L6 = "matrix @D[nD][nD]; @D = " + string(L[6]) + ";"; L = L[1..4]; i = 1; while (b == 0) { dbprint(ppl,"// number of run in the loop: "+string(i)); int q = prime(random(lb,ub)); if (findFirst(usedprimes,q)==0) // if q has not been used already { usedprimes = usedprimes,q; dbprint(ppl,"// using prime: "+string(q)); if (typeof(L[1]) == "int") { L[1] = q; } else { L[1][1] = q; } // parameters def @Rq = ring(L); setring @Rq; execute(L5); execute(L6); def Rq = nc_algebra(@C,@D); // def Rq = nc_algebra(1,@D); setring Rq; kill @Rq; execute(strLJq); sLJq = size(LJq); setring D; kill Rq; if (sLJq <> sJ ) // detect unlucky prime { dbprint(ppl,"// " +string(q) + " is unlucky"); b = 0; } else { b = pIntersectSyz(s,J,q,whichengine,modengine); } } i++; } short = short_save; } else // pIntersectSyz::non-modular { b = pIntersectSyz(s,J,0,whichengine); } } else // pIntersect: linReduce { b = pIntersect(s,J); } dbprint(ppl,"// ...done"); // with the intersection poly pb = vec2poly(b); if (inorann == 0) { pb = subst(pb,var(1),-var(1)-1); } else // bfctAnn { if (addPD) { pb = pb*(var(1)+1); } } list l = bFactor(pb); setring save; list l = imap(D,l); printlevel = printlevelsave; return(l); } proc bfct (poly f, list #) "USAGE: bfct(f [,s,t,v]); f a poly, s,t optional ints, v an optional intvec RETURN: list of ideal and intvec PURPOSE: computes the roots of the Bernstein-Sato polynomial b(s) @* for the hypersurface defined by f. ASSUME: The basering is commutative and of characteristic 0. BACKGROUND: In this proc, the initial Malgrange ideal is computed according to @* the algorithm by Masayuki Noro and then a system of linear equations is @* solved by linear reductions. NOTE: In the output list, the ideal contains all the roots @* and the intvec their multiplicities. @* If s<>0, @code{std} is used for GB computations, @* otherwise, and by default, @code{slimgb} is used. @* If t<>0, a matrix ordering is used for Groebner basis computations, @* otherwise, and by default, a block ordering is used. @* If v is a positive weight vector, v is used for homogenization @* computations, otherwise and by default, no weights are used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example bfct; shows examples " { int ppl = printlevel - voice +2; int i; int n = nvars(basering); // in # we have two switches: // one for the engine used for Groebner basis computations, // one for M() ordering or its realization // in # can also be the optional weight vector int whichengine = 0; // default int methodord = 0; // default intvec u0 = 0; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { whichengine = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { methodord = int(#[2]); } if (size(#)>2) { if (typeof(#[3])=="intvec" && size(#[3])==n && allPositive(#[3])==1) { u0 = #[3]; } } } } list b = bfctengine(f,0,whichengine,0,0,methodord,0,0,0,u0); return(b); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = x^2+y^3+x*y^2; bfct(f); intvec v = 3,2; bfct(f,1,0,v); } proc bfctSyz (poly f, list #) "USAGE: bfctSyz(f [,r,s,t,u,v]); f poly, r,s,t,u optional ints, v opt. intvec RETURN: list of ideal and intvec PURPOSE: computes the roots of the Bernstein-Sato polynomial b(s) @* for the hypersurface defined by f ASSUME: The basering is commutative and of characteristic 0. BACKGROUND: In this proc, the initial Malgrange ideal is computed according to @* the algorithm by Masayuki Noro and then a system of linear equations is @* solved by computing syzygies. NOTE: In the output list, the ideal contains all the roots and the intvec @* their multiplicities. @* If r<>0, @code{std} is used for GB computations in characteristic 0, @* otherwise, and by default, @code{slimgb} is used. @* If s<>0, a matrix ordering is used for GB computations, otherwise, @* and by default, a block ordering is used. @* If t<>0, the computation of the intersection is solely performed over @* charasteristic 0, otherwise and by default, a modular method is used. @* If u<>0 and by default, @code{std} is used for GB computations in @* characteristic >0, otherwise, @code{slimgb} is used. @* If v is a positive weight vector, v is used for homogenization @* computations, otherwise and by default, no weights are used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example bfctSyz; shows examples " { int ppl = printlevel - voice +2; int i; // in # we have four switches: // one for the engine used for Groebner basis computations in char 0, // one for M() ordering or its realization // one for a modular method when computing the intersection // and one for the engine used for Groebner basis computations in char >0 // in # can also be the optional weight vector int n = nvars(basering); int whichengine = 0; // default int methodord = 0; // default int pIntersectchar = 0; // default int modengine = 1; // default intvec u0 = 0; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { whichengine = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { methodord = int(#[2]); } if (size(#)>2) { if (typeof(#[3])=="int" || typeof(#[3])=="number") { pIntersectchar = int(#[3]); } if (size(#)>3) { if (typeof(#[4])=="int" || typeof(#[4])=="number") { modengine = int(#[4]); } if (size(#)>4) { if (typeof(#[5])=="intvec" && size(#[5])==n && allPositive(#[5])==1) { u0 = #[5]; } } } } } } list b = bfctengine(f,0,whichengine,0,0,methodord,1,pIntersectchar,modengine,u0); return(b); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = x^2+y^3+x*y^2; bfctSyz(f); intvec v = 3,2; bfctSyz(f,0,1,1,0,v); } proc bfctIdeal (ideal I, intvec w, list #) "USAGE: bfctIdeal(I,w[,s,t]); I an ideal, w an intvec, s,t optional ints RETURN: list of ideal and intvec PURPOSE: computes the roots of the global b-function of I w.r.t. the weight (-w,w). ASSUME: The basering is the n-th Weyl algebra in characteristic 0 and for all @* 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the @* sequence of variables is given by x(1),...,x(n),D(1),...,D(n), @* where D(i) is the differential operator belonging to x(i). @* Further we assume that I is holonomic. BACKGROUND: In this proc, the initial ideal of I is computed according to the @* algorithm by Masayuki Noro and then a system of linear equations is @* solved by linear reductions. NOTE: In the output list, say L, @* - L[1] of type ideal contains all the rational roots of a b-function, @* - L[2] of type intvec contains the multiplicities of above roots, @* - optional L[3] of type string is the part of b-function without rational roots. @* Note, that a b-function of degree 0 is encoded via L[1][1]=0, L[2]=0 and @* L[3] is 1 (for nonzero constant) or 0 (for zero b-function). @* If s<>0, @code{std} is used for GB computations in characteristic 0, @* otherwise, and by default, @code{slimgb} is used. @* If t<>0, a matrix ordering is used for GB computations, otherwise, @* and by default, a block ordering is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example bfctIdeal; shows examples " { int ppl = printlevel - voice +2; int i; def save = basering; int n = nvars(save) div 2; int whichengine = 0; // default int methodord = 0; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { whichengine = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { methodord = int(#[2]); } } } if (isWeyl()==0) { ERROR("basering is not a Weyl algebra"); } for (i=1; i<=n; i++) { if (bracket(var(i+n),var(i))<>1) { ERROR(string(var(i+n))+" is not a differential operator for " +string(var(i))); } } int isH = isHolonomic(I); if (isH<>1) { print("WARNING: given ideal is not holonomic"); print("... setting bound for degree of b-function to 10 and proceeding"); isH = 10; } else { isH = 0; } // no degree bound for pIntersect ideal J = initialIdealW(I,-w,w,whichengine,methodord); poly s; for (i=1; i<=n; i++) { s = s + w[i]*var(i)*var(n+i); } vector b = pIntersect(s,J,isH); list RL = ringlist(save); RL = RL[1..4]; RL[2] = list(safeVarName("s")); RL[3] = list(list("dp",intvec(1)),list("C",intvec(0))); def @S = ring(RL); setring @S; vector b = imap(save,b); poly bs = vec2poly(b); list l = bFactor(bs); setring save; list l = imap(@S,l); return(l); } example { "EXAMPLE:"; echo = 2; ring @D = 0,(x,y,Dx,Dy),dp; def D = Weyl(); setring D; ideal I = 3*x^2*Dy+2*y*Dx,2*x*Dx+3*y*Dy+6; I = std(I); intvec w1 = 0,1; intvec w2 = 2,3; bfctIdeal(I,w1); bfctIdeal(I,w2,0,1); ideal J = I[size(I)]; // J is not holonomic by construction bfctIdeal(J,w1); // b-function of D/J w.r.t. w1 is non-zero bfctIdeal(J,w2); // b-function of D/J w.r.t. w2 is zero } proc bfctOneGB (poly f,list #) "USAGE: bfctOneGB(f [,s,t]); f a poly, s,t optional ints RETURN: list of ideal and intvec PURPOSE: computes the roots of the Bernstein-Sato polynomial b(s) for the @* hypersurface defined by f, using only one GB computation ASSUME: The basering is commutative and of characteristic 0. BACKGROUND: In this proc, the initial Malgrange ideal is computed based on the @* algorithm by Masayuki Noro and combined with an elimination ordering. NOTE: In the output list, the ideal contains all the roots and the intvec @* their multiplicities. @* If s<>0, @code{std} is used for the GB computation, otherwise, @* and by default, @code{slimgb} is used. @* If t<>0, a matrix ordering is used for GB computations, @* otherwise, and by default, a block ordering is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example bfctOneGB; shows examples " { int ppl = printlevel - voice +2; if (!isCommutative()) { ERROR("Basering must be commutative"); } def save = basering; int n = nvars(save); if (char(save) <> 0) { ERROR("characteristic of basering has to be 0"); } list L = ringlist(save); int qr; if (L[4] <> 0) // qring? { print("// basering is qring:"); print("// discarding the quotient and proceeding..."); L[4] = ideal(0); qr = 1; def save2 = ring(L); setring save2; poly f = imap(save,f); } int N = 2*n+4; int i; int whichengine = 0; // default int methodord = 0; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { whichengine = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { methodord = int(#[2]); } } } // creating the homogenized extended Weyl algebra // create names for vars list Lvar; Lvar[1] = safeVarName("t"); Lvar[2] = safeVarName("s"); Lvar[n+3] = safeVarName("D"+Lvar[1]); Lvar[N] = safeVarName("h"); for (i=1; i<=n; i++) { Lvar[i+2] = string(var(i)); Lvar[i+n+3] = safeVarName("D" + string(var(i))); } // create ordering intvec uv = -1; uv[n+3] = 1; uv[N] = 0; intvec @a = 1:N; @a[2] = 2; intvec @a2 = @a; @a2[2] = 0; @a2[2*n+4] = 0; list Lord; Lord[1] = list("a",@a); Lord[2] = list("a",@a2); if (methodord == 0) // default: block ordering { //ring @Dh = 0,(t,s,x(n..1),Dt,D(n..1),h),(a(@a),a(@a2),a(uv),dp(N-1),lp(1)); Lord[3] = list("a",uv); Lord[4] = list("dp",intvec(1:(N-1))); Lord[5] = list("lp",intvec(1)); Lord[6] = list("C",intvec(0)); } else // M() ordering { intmat @Ord[N][N]; @Ord[1,1..N] = uv; @Ord[2,1..N] = 1:(N-1); for (i=1; i<=N-2; i++) { @Ord[2+i,N - i] = -1; } dbprint(ppl,"// weights for ordering: "+string(transpose(@a))); dbprint(ppl,"// the ordering matrix:",@Ord); //ring @Dh = 0,(t,s,x(n..1),Dt,D(n..1),h),(a(@a),a(@a2),M(@Ord)); Lord[3] = list("M",intvec(@Ord)); Lord[4] = list("C",intvec(0)); } // create commutative ring list L@Dh = ringlist(basering); L@Dh = L@Dh[1..4]; // if basering is commutative nc_algebra L@Dh[2] = Lvar; L@Dh[3] = Lord; def @Dh = ring(L@Dh); setring @Dh; dbprint(ppl,"// the ring @Dh:",@Dh); // create non-commutative relations matrix @relD[N][N]; @relD[1,2] = var(1)*var(N)^2; // s*t = t*s + t*h^2 @relD[2,n+3] = var(n+3)*var(N)^2; // Dt*s = s*Dt+Dt*h^2 @relD[1,n+3] = var(N)^2; for (i=1; i<=n; i++) { @relD[i+2,n+3+i] = var(N)^2; } dbprint(ppl,"// nc relations:",@relD); def Dh = nc_algebra(1,@relD); setring Dh; kill @Dh; dbprint(ppl,"// computing in ring",Dh); poly f = imap(save,f); f = homog(f,h); // create the Malgrange ideal ideal I = var(1) - f, var(1)*var(n+3) - var(2); for (i=1; i<=n; i++) { I[3+i] = var(i+n+3)+diff(f,var(i+2))*var(n+3); } dbprint(ppl-1, "// the Malgrange ideal: " +string(I)); // the hard part: Groebner basis computation dbprint(ppl, "// starting Groebner basis computation with engine: "+string(whichengine)); I = engine(I, whichengine); dbprint(ppl, "// finished Groebner basis computation"); I = subst(I,h,1); // dehomogenization dbprint(ppl-1,string(I)); // 3.3 the initial form I = inForm(I,uv); dbprint(ppl, "// the initial ideal:", string(matrix(I))); // read off the solution intvec tonselect = 1; for (i=3; i<=2*n+4; i++) { tonselect = tonselect,i; } I = nselect(I,tonselect); dbprint(ppl, "// generators containing only s:", string(matrix(I))); I = engine(I, whichengine); // is now a principal ideal; if (qr == 1) { setring save2; } else { setring save; } ideal J; J[2] = var(1); map @m = Dh,J; ideal I = @m(I); poly p = I[1]; p = subst(p,var(1),-var(1)-1); list l = bFactor(p); if (qr == 1) { setring save; list l = imap(save2,l); } return(l); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = x^2+y^3+x*y^2; bfctOneGB(f); bfctOneGB(f,1,1); } proc bfctAnn (poly f, list #) "USAGE: bfctAnn(f [,a,b,c]); f a poly, a, b, c optional ints RETURN: list of ideal and intvec PURPOSE: computes the roots of the Bernstein-Sato polynomial b(s) for the @* hypersurface defined by f. ASSUME: The basering is commutative and of characteristic 0. BACKGROUND: In this proc, Ann(f^s) is computed and then a system of linear @* equations is solved by linear reductions. NOTE: In the output list, the ideal contains all the roots and the intvec @* their multiplicities. @* If a<>0, only f is appended to Ann(f^s), otherwise, and by default, @* f and all its partial derivatives are appended. @* If b<>0, @code{std} is used for GB computations, otherwise, and by @* default, @code{slimgb} is used. @* If c<>0, @code{std} is used for Groebner basis computations of ideals @* when I is already a Groebner basis of . @* Otherwise, and by default the engine determined by the switch b is used. @* Note that in the case c<>0, the choice for b will be overwritten only @* for the types of ideals mentioned above. @* This means that if b<>0, specifying c has no effect. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example bfctAnn; shows examples " { def save = basering; int ppl = printlevel - voice + 2; int addPD = 1; // default int whichengine = 0; // default int stdsum = 0; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { addPD = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { whichengine = int(#[2]); } if (size(#)>2) { if (typeof(#[3])=="int" || typeof(#[3])=="number") { stdsum = int(#[3]); } } } } list b = bfctengine(f,1,whichengine,addPD,stdsum,0,0,0,0,0); return(b); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = x^2+y^3+x*y^2; bfctAnn(f); def R = reiffen(4,5); setring R; RC; // the Reiffen curve in 4,5 bfctAnn(RC,0,1); } /* static proc hardexamples () { // some hard examples ring r1 = 0,(x,y,z,w),dp; // ab34 poly ab34 = (z3+w4)*(3z2x+4w3y); bfct(ab34); // ha3 poly ha3 = xyzw*(x+y)*(x+z)*(x+w)*(y+z+w); bfct(ha3); // ha4 poly ha4 = xyzw*(x+y)*(x+z)*(x+w)*(y+z)*(y+w); bfct(ha4); // chal4: reiffen(4,5)*reiffen(5,4) ring r2 = 0,(x,y),dp; poly chal4 = (x4+xy4+y5)*(x5+x4y+y4); bfct(chal4); // (xy+z)*reiffen(4,5) ring r3 = 0,(x,y,z),dp; poly xyzreiffen45 = (xy+z)*(y4+yz4+z5); bfct(xyzreiffen45); // sparse ideal as suggested by Alex; gives 1 as std ideal I1 = 28191*y^2+14628*x*Dy, 24865*x^2+24072*x*Dx+17756*Dy^2; std(I1); } */ singular-4.0.3+ds/Singular/LIB/bimodules.lib000066400000000000000000000632631266270727000206340ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version bimodules.lib 4.0.0.0 Jun_2013 "; // $Id: 2e5433493a3f629deb8c418171e37dcc76027d6a $ category="Noncommutative"; info=" LIBRARY: bimodules.lib Tools for handling bimodules AUTHORS: Ann Christina Foldenauer, Christina.Foldenauer@rwth-aachen.de @* Viktor Levandovskyy, levandov@math.rwth-aachen.de OVERVIEW: @* The main purpose of this library is the handling of bimodules @* which will help e.g. to determine weak normal forms of representation matrices @* and total divisors within non-commutative, non-simple G-algebras. @* We will use modules homomorphisms between a G-algebra and its enveloping algebra @* in order to work left Groebner basis theory on bimodules. @* Assume we have defined a (non-commutative) G-algebra A over the field K, and an (A,A)-bimodule M. @* Instead of working with M over A, we define the enveloping algebra A^{env} = A otimes_K A^{opp} @* (this can be done with command envelope(A)) and embed M into A^{env} via imap(). @* Thus we obtain the left A^{env}-module M otimes 1 in A^{env}. @* This has a lot of advantages, because left module theory has much more commands @* that are already implemented in SINGULAR:PLURAL. Two important procedures that we can use are std() @* which computes the left Groebner basis, and NF() which computes the left normal form. @* With the help of this method we are also able to determine the set of bisyzygies of a bimodule. @* @* A built-in command @code{twostd} in PLURAL computes the two-sided Groebner basis of an ideal @* by using the right completion algorithm of [2]. @code{bistd} from this library uses very different @* approach, which is often superior to the right completion. REFERENCES: @* The procedure bistd() is the implementation of an algorithm M. del Socorro Garcia Roman presented in [1](page 66-78). @* [1] Maria del Socorro Garcia Roman, Effective methods in Algebras with PBW bases: @* G-algebras and Yang-Baxter Algebras, Ph.D. thesis, Universidad de La Laguna, 2005. @* [2] Viktor Levandovskyy, Non-commutative Computer Algebra for polynomial Algebras: @* Groebner Bases, Applications and Implementations, Ph.D. thesis, Kaiserlautern, 2005. @* [3] N. Jacobson, The theory of rings, AMS, 1943. @* [4] P. M. Cohn, Free Rings and their Relations, Academic Press Inc. (London) Ltd., 1971. PROCEDURES: bistd(M); computes the two-sided Groebner bases of an ideal or module bitrinity(M); computes the trinity of M: Groebner basis, lift matrix and bisyzygies liftenvelope(M,g); computes the coefficients of an element g concerning the generators of a bimodule M in the enveloping algebra CompDecomp(p); returns an ideal which contains the component decomposition of a polynomial p in the enveloping algebra regarding the right side of the tensors isPureTensor(p); checks whether an element p in A^{env} is a pure tensor isTwoSidedGB(I); checks whether an ideal I is two-sided Groebner basis SEE ALSO: ncalg_lib; nctools_lib KEYWORDS: bimodules; bisyzygies; lift; enveloping algebra; pure tensor; total divisors; two-sided; two-sided Groebner basis; tensor "; LIB "ncalg.lib"; LIB "nctools.lib"; proc testbimoduleslib() { /* tests all procs for consistency */ "MAIN PROCEDURES:"; example bistd; example bitrinity; example liftenvelope; example isPureTensor; example isTwoSidedGB; "SECONDARY BIMODULES PROCEDURES:"; example enveltrinity; example CompDecomp; } proc bistdIdeal (ideal M) "does bistd directly for ideals " { intvec optionsave = option(get); option(redSB); option(redTail); def save = basering ; def saveenv = envelope(save); setring saveenv; ideal M = imap(save, M); int i; int n = nvars(save); ideal K; for (i=1; i <= n; i++) { K[i] = var(i)-var(2*n-i+1); } M = M+K; M = std(M); option(set,optionsave); setring save; list L = ringlist(save); if (size(ringlist(save)) > 4) { L = delete(L,6); L = delete(L,5);} def Scom = ring(L); setring Scom; ideal P; for (i= 1; i <= n; i++) { P[i] = var(i); P[2*n-i+1] = var(i); } map Pi = saveenv, P; ideal N = Pi(M) ; setring save; ideal MM = fetch(Scom,N); return(MM); } example { "EXAMPLE:"; echo = 2; ring w = 0,(x,s),Dp; def W=nc_algebra(1,s); // 1st shift algebra setring W; ideal I1 = s^3-x^2*s; print(matrix(bistd(I1))); // compare with twostd: print(matrix(twostd(I1))); ideal I2 = I1, x*s; print(matrix(bistd(I2))); // compare with twostd: print(matrix(twostd(I2))); } proc bistd (module M) "USAGE: bistd(M); M is (two-sided) ideal/module RETURN: ideal or module (same type as the argument) PURPOSE: Computes the two-sided Groebner basis of an ideal/module with the help the enveloping algebra of the basering, alternative to twostd() for ideals. EXAMPLE: example bistd; shows examples " { // VL: added simplify // commented out: Additionally you should use simplify(N,2+4+8) on the output N = bistd(M), where M denotes to the ideal/module in the argument. // NOTE: option(redSB), option(redTail) are used by the procedure. // intvec optionsave = option(get); // option(redSB); // option(redTail); int ROW = nrows(M); def save = basering ; def saveenv = envelope(save); setring saveenv; module M = imap(save, M); int i; int n = nvars(save); module B; for (i=1; i <= n; i++) { B[i] = var(i) - var(2*n-i+1); } module K ; int j;int m = 1; for (i=1; i <= n; i++) { for(j=1;j<=ROW;j++) { K[m]= B[i][1,1]*gen(j);m++; } } M = M+K; M = std(M); // option(set,optionsave); setring save; list L = ringlist(save); if (size(ringlist(save)) > 4) {L = delete(L,6);L = delete(L,5);} def Scom = ring(L); setring Scom; ideal P; for (i= 1; i <= n; i++) { P[i] = var(i) ; P[2*n-i+1] = var(i); } map Pi = saveenv, P; module N = Pi(M) ; setring save; module MM = fetch(Scom,N); if (nrows(MM)==1) { //i.e. MM is an ideal indeed ideal @M = ideal(MM); kill MM; ideal MM = @M; } MM = simplify(MM,2+4+8); return(MM); } example { "EXAMPLE:"; echo = 2; ring w = 0,(x,s),Dp; def W=nc_algebra(1,s); // 1st shift algebra setring W; matrix m[3][3]=[s^2,s+1,0],[s+1,0,s^3-x^2*s],[2*s+1, s^3+s^2, s^2]; print(m); module L = m; module M2 = bistd(L); print(M2); } proc enveltrinityIdeal(ideal f) " enveltrinity for an ideal directly" { // AUXILIARY PROCEDURES: Uses Zersubcols(matrix N, int l). intvec optionsave = option(get); def save = basering ; option(redSB); int i; int n = nvars(save); def saveenv = envelope(save); setring saveenv; def R = makeModElimRing(saveenv); setring R; ideal K; for (i=1; i <= n; i++) { K[i] = var(i)-var(2*n-i+1);} K = std(K); ideal f = imap(save, f); // now we compute the trinity (GB,Liftmatrix,Syzygy) // can do it with f but F=NF(f,kr), so the ideals are the same in R env ideal I = f, K; // ideal I = F, K; int l = ncols(I); int j = ncols(f); matrix M[j+1][l]; for (i = 1; i<= l;i++) { M[1,i] = I[i]; } for (i=1; i <= j;i++) { M[i+1,i] = 1; } matrix N = std(M); option(set,optionsave); int m = ncols(N); intvec sypos; for (i=1; i <= m; i++) { if (N[1,i] == 0) { sypos = sypos,i; } } intvec Nrows = 2..(j+1); matrix BS = submat(N,Nrows,sypos); // e.g. for each column (b_1,...,b_j) you get 0 = sum_i (b_i*f_i) module BSy = BS; setring saveenv; ideal K = imap(R,K); module BS = imap(R,BSy); matrix N = imap(R,N); kill R; export K; export BS; export N; return(saveenv); } static proc Zersubcols(matrix N, int l) { if (nrows(N) <= l) { string f = "Inputinteger ist zu gross. Muss kleiner sein als die Anzahl der Zeilen von der Inputmatrix."; return(f); } else { matrix O[l][1]; int m = ncols(N); matrix H = submat(N,1..l,1..m); int i; intvec s; intvec c; for(i=1; i<= m;i++) { if(H[i] != O[1]) {c = c,i;} else {s = s,i;} } list L = s,c; return(L); } } proc enveltrinity(module M) "USAGE: enveltrinity(M); M is (two-sided) ideal/module RETURN: ring, the enveloping algebra of the basering with objects K, N, BS in it. PURPOSE: compute two-sided Groebner basis, module of bisyzygies and the bitransformation matrix of M. THEORY: Assume R is a G-algebra generated by x_1, \dots x_k. Let psi_s be the epimorphism of left R (X) R^{opp} modules: @* psi_s (s (X)_K t) = smt := (s_1 m t_1, ... , s_s m t_s) = (\psi(s_1 (X) t_1) , ... , psi(s_s (X) t_s)) in R^s @* additionally we define for a given bimodule M = < f_1, ... , f_r > the matrix M' := [F, I_r], [K, 0] @* where I_r refers to the identity matrix in Mat(r,R), K is a matrix which columns are the generators of the kernel of psi_s. @* These have the form (x_i-X_i)e_j for j in {1,...,s}, i in {1,...,k}. @* The matrix F = (f_1 ... f_r), where the f_i's are the generators of M and 0 is the matrix with only entries that are zero. @* Enveltrinity() calculates the kernel K of psi_s and left normal form N of the matrix M' which also yields the bisyzygies of M @* and a coefficient matrix as submatrix of N which we need in the procedures bitrinity() and liftenevelope(). NOTE: In the output, @* ideal/module K is the kernel of psi_s above @* matrix N is the left Groebner basis of the matrix M' @* module BS corresponds to the set of bisyzygies of M. @* To get K,N or BS, use @code{def G = enveltrinity(M); setring G; K; N; BS;}. EXAMPLE: example enveltrinity; shows examples " { def save = basering ; intvec optionsave = option(get); option(redSB); int ROW = nrows(M); int i; int n = nvars(save); def saveenv = envelope(save); setring saveenv; def R = makeModElimRing(saveenv); setring R; module B; for (i=1; i <= n; i++) { B[i] = var(i) - var(2*n-i+1);} module K ; int t;int g = 1; for (i=1; i <= n; i++) { for(t=1;t<=ROW;t++) { K[g]= B[i][1,1]*gen(t);g++; } } K = std(K); module M = imap(save,M); module I = M,K; int l = ncols(I); int j = ncols(M); matrix NN[j+ROW][l]; for (t=1; t <= ROW; t++) { for (i = 1; i<= l;i++) { NN[t,i] = I[t,i];} } for (i=ROW+1; i <= j+ROW;i++) { NN[i,i-ROW] = 1;} // now we compute the trinity (GB,Liftmatrix,Syzygy) // can do it with f but F=NF(f,kr), so the ideals are the same in R env matrix N = std(NN); option(set,optionsave); intvec sypos = Zersubcols(N,ROW)[1]; sypos = sypos[2..nrows(sypos)]; intvec Nrows = (ROW+1)..(j+ROW); matrix BS = submat(N,Nrows,sypos); // e.g. for each column (b_1,...,b_j) you get 0 = sum_i (b_i*f_i) module BSy = BS; setring saveenv; matrix N = imap(R,N); module BS = imap(R,BSy); module K = imap(R,K); if (nrows(K)==1) { // i.e. K is an ideal ideal @K = ideal(K); kill K; ideal K = @K; } kill R; export K; export BS; export N; return(saveenv); } example {"EXAMPLE"; echo = 2; ring r = 0,(x,s),dp; def R = nc_algebra(1,s); setring R; poly f = x*s + s^2; ideal I = f; def G = enveltrinity(I); setring G; print(matrix(K)); // kernel of psi_s print(BS); // module of bisyzygies print(N); // bitransformation matrix } proc bitrinityIdeal(ideal f) "direct appl of bitrinity to ideal" { intvec optionsave = option(get); option(redSB); option(redTail); int j = ncols(f); def A = enveltrinity(f); setring A; // A = envelope(basering) int i; def R = makeModElimRing(A); setring R; ideal K = imap(A,K); K = std(K); option(set,optionsave); matrix N = imap(A,N); int m = ncols(N); //decomposition of N: Liftmatrix, Bisyzygymatrix: intvec cfpos; for (i=1; i <= m; i++) { if (N[1,i] != 0) {cfpos = cfpos,i;} } cfpos = cfpos[2..nrows(cfpos)]; matrix C = submat(N,1..(j+1),cfpos); module Coef; for(i=1;i<=ncols(C);i++) { poly p = NF(C[1,i],K); if( (p != 0) && (p == C[1,i])) { Coef = Coef,C[i];} } matrix Co = Coef; matrix Coe = submat(Co,1..nrows(Co),2..ncols(Co)); module CC = Coe; //e.g. i-th column is (a_i1,...,a_ij) (see top) setring A; matrix Coeff = imap(R,CC); matrix Bisyz = BS;// e.g. for each column (b_1,...,b_j) you get 0 = sum_i (b_i*f_i) kill R; list L = Coeff,Bisyz; // output is a Coefficient-Matrix Co and a Bisyzygy-Matriy BS such that (g1,...,gk) = (f1,...,fj)*Submat(Coeff,2..nrows(Coeff),1..ncols(Coeff)) and (0,...,0) = (f1,...,fj)*BiSyz export L; return(A); } proc bitrinity(module M) "USAGE: bitrinity(M); M is (two-sided) ideal/module RETURN: ring, the enveloping algebra of the basering, with objects in it. additionally it exports a list L = Coeff, Bisyz. THEORY: Let psi_s be the epimorphism of left R (X) R^{opp} modules: @* psi_s(s (X)_K t) = smt := (s_1 m t_1, ... , s_s m t_s) = (\psi(s_1 (X) t_1) , \dots , psi(s_s (X) t_s)) in R^s. @* Then psi_s(A) := (psi_s(a_{ij})) for every matrix A in Mat(n x m, R)$. @* For a two-sided ideal I = < f_1, ... , f_j> with Groebner basis G = {g_1, ... , g_k} in R, Coeff is the Coefficient-Matrix and BiSyz a bisyzygy matrix. @* Let C be the submatrix of Coeff, where C is Coeff without the first row. Then (g_1,...,g_k) = psi_s(C^T * (f_1 ... f_j)^T) and (0,...,0) = psi_s(BiSyz^T * (f_1 ... f_j)^T). @* The first row of Coeff (G_1 ... G_n)$ corresponds to the image of the Groebner basis of I: psi_s((G_1 ... G_n)) = G = {g_1 ... g_k }. @* For a (R,R)-bimodule M with Groebner basis G = {g_1, ... , g_k} in R^r, Coeff is the coefficient matrix and BiSyz a bisyzygy matrix. @* Let C be the submatrix of Coeff, where C is Coeff without the first r rows. Then (g_1 ... g_k) = psi_s(C^T * (f_1 ... f_j)^T) and (0 ... 0) = psi_s(BiSyz^T * (f_1 ... f_j)^T). @* The first r rows of Coeff = (G_1 ... G_n) (Here G_i denotes to the i-th column of the first r rows) corresponds to the image of the Groebner basis of M: psi_s((G_1 ... G_n)) = G = {g_1 ... g_k}. PURPOSE: This procedure returns a coefficient matrix in the enveloping algebra of the basering R, that gives implicitly the two-sided Groebner basis of a (R,R)-bimodule M and the coefficients that produce the Groebner basis with the help of the originally used generators of M. Additionally it calculates the bisyzygies of M as left-module of the enveloping algebra of R. AUXILIARY PROCEDURES: Uses the procedure enveltrinity(). NOTE: To get list L = Coeff, BiSyz, we set: def G = bitrinity(); setring G; L; or $L[1]; L[2];. EXAMPLE: example bitrinity; shows examples " { intvec optionsave = option(get); option(redSB); option(redTail); int ROW = nrows(M); int j = ncols(M); def A = enveltrinity(M); setring A; // A = envelope(basering) int i; def R = makeModElimRing(A); setring R; module K = imap(A,K); K = std(K); option(set,optionsave); matrix N = imap(A,N); int m = ncols(N); //decomposition of N: Liftmatrix, Bisyzygymatrix: intvec cfpos = Zersubcols(N,ROW)[2]; cfpos = cfpos[2..nrows(cfpos)]; matrix C1 = submat(N,1..nrows(N),cfpos); matrix C2 = submat(N,1..ROW,cfpos); module Coef; matrix O[ROW][1]; module p; for(i=1;i<=ncols(C2);i++) { p = NF(C2[i],K); if( (p[1] != O[1]) && (p[1] == C2[i])) { Coef = Coef,C1[i];} } matrix Co = Coef; matrix Coe = submat(Co,1..nrows(Co),2..ncols(Co)); module CC = Coe; setring A; matrix Coeff = imap(R,CC); matrix Bisyz = BS; kill R; list L = Coeff,Bisyz; export L; return(A); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,s),dp; def R = nc_algebra(1,s); setring R; // 1st shift algebra poly f = x*s + s^2; // only one generator ideal I = f; // note, two sided Groebner basis of I is xs, s^2 def G = bitrinity(I); setring G; print(L[1]); // Coeff //the first row shows the Groebnerbasis of I consists of // psi_s(SX) = xs , phi(S^2) = s^2: // remember phi(a (X) b - c (X) d) = psi_s(a (X) b) - phi(c (X) d) := ab - cd in R. // psi_s((-s+S+1)*(x*s + s^2)) = psi_s(-xs2-s3+xsS+xs+s2S) // = -xs^2-s^3+xs^2+xs+s^3 = xs // psi_s((s-S)*(x*s + s^2)) = psi_s(xs2+s3-xsS-s2S+s2) = s^2 print(L[2]); //Bisyzygies // e.g. psi_s((x2-2sS+s-X2+2S2+2X+S-1)(x*s + s^2)) // = psi_s(x3s+x2s2-2xs2S+xs2-2s3S+s3-xsX2+2xsS2+2xsX+xsS-xs-s2X2+2s2S2+2s2X-s2S) // = x^3s+x^2s^2-2xs^3+xs^2-2s^4+s^3-xsx^2+2xs^3+2xsx+xs^2-xs-s^2x^2+2s^4+2s^2x-s^3 // = 0 in R } proc liftenvelope(module I,poly g) "USAGE: liftenvelope(M,g); M ideal/module, g poly RETURN: ring, the enveloping algebra of the basering R. Given a two-sided ideal M in R and a polynomial g in R this procedure returns the enveloping algebra of R. Additionally it exports a list l = C, B; where B is the left Groebner basis of the left-syzygies of M \otimes 1 and C is a vector of coefficients in the enveloping algebra of R such that psi_s(C^T *(f_1 \dots f_n)) = g. @* psi_s is an epimorphism of left R (X) R^{opp} modules: @* psi_s (s (X)_K t) = smt := (s_1 m t_1, ... , s_s m t_s) = (\psi(s_1 (X) t_1) , \dots , psi(s_s (X) t_s)) in R^s. @* Then psi_s(A) := (psi_s(a_{ij})) for every matrix A in Mat(n x m, R)$. ASSUME: The second component has to be an element of the first component. PURPOSE: This procedure is used for computing total divisors. Let {f_1, ..., f_n} be the generators of the first component and let the second component be called g. Then the returned list l = C, B = (b_1, ..., b_n); defines an affine set A = C + sum_i a_i b_i with (a_1,..,a_n) in the enveloping algebra of the basering R such that psi_s(a^T * (f_1 ... f_n)) = g for all a in A. For certain rings R, we csn find pure tensors within this set A, and if we do, liftenvelope() helps us to decide whether f is a total divisor of g. NOTE: To get list l = C, B. we set: def G = liftenvelope(); setring G; l; or l[1]; l[2];. EXAMPLE: example liftenvelope; shows examples " { def save = basering; int m = ncols(I); intvec optionsave = option(get); option(redSB); option(redTail); def A = enveltrinity(I); setring A; // A = envelope(basering) int i; def R = makeModElimRing(A); setring R; module N = imap(A,N); N = std(N); //intvec Nrows = 2..(j+1); module g = imap(save,g); matrix G[nrows(N)][1]; for (i=2;i<=m;i++) { G[1,1] = g; G[i,1]=0; } module NFG = (-1)*NF(G,N); module C = submat(NFG,2..nrows(N),1); setring A; module C = imap(R,C); kill R; module B = std(BS); option(set,optionsave); list l = C,B; // transpose(C)*(f1,...,fn) = g export l; return(A); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,s),dp; def R = nc_algebra(1,s); setring R; ideal I = x*s; poly p = s*x*s*x; // = (s (x) x) * x*s = (sX) * x*s p; def J = liftenvelope(I,p); setring J; print(l[1]); //2s+SX = (2s (x) 1) + (1 (x) sx) print(l[2]); // Groebnerbasis of BiSyz(I) as LeftSyz in R^{env} // We get : 2s+SX + ( sX - 2s -SX) = sX - a pure tensor!!!! } static proc twoComp(poly q) "USAGE: twoComp(g); g poly NOTE: This procedure only works if the basering is an enveloping algebra A^{env} of a (non-commutative) ring A. Thus also the polynomial in the argument has to be in A^{env}. RETURN: Returns the second half of the leading exponent of a polynomial p in A^{env}: @* lm(p) = c x1^a1 x2^a2 ... xn^an (X) xn^bn * x(n-1)^b(n-1) * ... * x1^b1 such that lex(p) = [a1,..,an,bn,...,b1]. Then the procedure returns [bn,...,b1] (of lex(p)!). " { if (q == 0) {return(q);} def saveenv = basering; int n = nvars(saveenv); int k = n div 2; intvec v = leadexp(q); intvec w = v[k+1..2*k]; return(w); } static proc firstComp(poly q) "USAGE: firstComp(g); g poly NOTE: This procedure only works if the basering is an enveloping algebra A^{env} of a (non-commutative) ring A. Thus also the polynomial in the argument has to be in A^{env}. RETURN: Returns the first half of the leading exponent of a polynomial p in A^{env}: @* lm(p) = c x1^a1 x2^a2 ... xn^an (X) xn^bn * x(n-1)^b(n-1) * ... * x1^b1 such that lex(p) = [a1,..,an,bn,...,b1]. Then the procedure returns [a1,...,an] (of lex(p)!). " { if (q == 0) {return(q);} def saveenv = basering; int n = nvars(saveenv); int k = n div 2; intvec v = leadexp(q); intvec w = v[1..k]; return(w); } proc CompDecomp(poly p) "USAGE: CompDecomp(p); p poly NOTE: This procedure only works if the basering is an enveloping algebra A^{env} of a (non-commutative) ring A. Thus also the polynomial in the argument has to be in A^{env}. RETURN: Returns an ideal I in A^{env}, where the sum of all terms of the argument with the same right side (of the tensor summands) are stored as a generator of I. @* Let b != c, then for p = (a (X) b) + (c (X) b) + (a (X) c) the ideal I := CompDecomp(p) is given by: I[1] = (a (X) b) + (c (X) b); I[2] = a (X) c. PURPOSE: By decomposing the polynomial we can easily check whether the given polynomial is a pure tensor. EXAMPLE: example CompDecomp; shows examples " { poly s = p; ideal Q; int j = 0; poly t; poly w; while (s!= 0) { t = lead(s); w = s-t; s = s-t; j++; Q[j] = t; while(w !=0) { if (twoComp(w) == twoComp(t)) { Q[j] = Q[j]+lead(w); s = s-lead(w); } w = w-lead(w); } } return(Q); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,s),dp; def R = nc_algebra(1,s); setring R; //1st shift algebra def Re = envelope(R); setring Re; //basering is now R^{env} = R (X) R^{opp} poly f = X*S*x^2+5*x*S*X+S*X; f; ideal I = CompDecomp(f); print(matrix(I)); // what means that f = (x2+5x+1)*SX + x2*S poly p = x*S+X^2*S+2*s+x*X^2*s+5*x*s; p; ideal Q = CompDecomp(p); print(matrix(Q)); } proc getOneComp(poly p) "USAGE: getOneComp(p); p poly NOTE: This procedure only works if the basering is an enveloping algebra A^{env} of a (non-commutative) ring A. Thus also the polynomial in the argument has to be in A^{env}. ASSUME: The given polynomial has to be of the form sum_i a_i \otimes b = (sum_i a_i) (X) b. RETURN: Returns a polynomial in A^{env}, which is the sum of the left-side (of the tensor summands) of all terms of the argument. @* Let A be a G-algebra. For a given polynomial p in A^{env} of the form p = sum_i a_i (X) b = (sum_i a_i) (X) b this procedure returns g = (\sum_i a_i) (X) 1 written sum_i a_i in A^{env}. PURPOSE: This is an auxiliary procedure for isPureTensor(). EXAMPLE: example getOneComp; shows examples " { ideal I; int i; int m = size(p);poly f; if (size(p) == 0) {f = 1; return(f);} for(i=1;i<=m;i++) { I[i] = leadcoef(p[i])*monomial(firstComp(p[i]));} f = sum(I); return(f); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,s),dp; def R = nc_algebra(1,s); setring R; //1st shift algebra def Re = envelope(R); setring Re; //basering is now R^{env} = R (X) R^{opp} poly f = 5*x*s*S+x^2*S+s*S+3*x*S; // f = (x2+5xs+3x+s)*S getOneComp(f); } proc isPureTensor(poly g) "USAGE: isPureTensor(g); g poly NOTE: This procedure only works if the basering is an enveloping algebra A^{env} of a (non-commutative) ring A. Thus also the polynomial in the argument has to be in A^{env}. RETURN: Returns 0 if g is not a pure tensor and if g is a pure tensor then isPureTensor() returns a vector v with v = a*gen(1)+b*gen(2) = (a,b)^T with a (X) b = g. PURPOSE: Checks whether a given polynomial in $\A^{env}$ is a pure tensor. This is also an auxiliary procedure for checking total divisibility. EXAMPLE: example isPureTensor; shows examples " { ideal I = CompDecomp(g); ideal U;int i; int k = ncols(I); for (i = 1 ; i <= k; i++) { U[i] = getOneComp(I[i]); } poly q = normalize(U[1]); for (i=2; i<= k;i++) { if ( U[i] != leadcoef(U[i])*q) { return(0); } } def saveenv = basering; int n = nvars(saveenv); int l = n div 2; ideal P; intvec d = 0:l; intvec vv; for (i=1;i<=k;i++) { vv= d,twoComp(I[i]); P[i] = leadcoef(U[i])*monomial(vv); } poly w = sum(P); vector v = [q, w]; return(v); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,s),dp; def R = nc_algebra(1,s); setring R; //1st shift algebra def Re = envelope(R); setring Re; //basering is now R^{env} = R (X) R^{opp} poly p = x*(x*s)*x + s^2*x; p; // p is of the form q(X)1, a pure tensor indeed: isPureTensor(p); // v = transpose( x3s+x2s+xs2+2s2 1 ) i.e. p = x3s+x2s+xs2+2s2 (X) 1 poly g = S*X+ x*s*X+ S^2*x; g; isPureTensor(g); // indeed g is not a pure tensor poly d = x*X+s*X+x*S*X+s*S*X;d; isPureTensor(d); // d is a pure tensor indeed // v = transpose( x+s S*X+X ) i.e. d = x+s (X) s*x+x // remember that * denotes to the opposite mulitiplication s*x = xs in R. } proc isTwoSidedGB(ideal I) "USAGE: isTwoSidedGB(I); I ideal RETURN: Returns 0 if the generators of a given ideal are not two-sided, 1 if they are.\\ NOTE: This procedure should only be used for non-commutative rings, as every element is two-sided in a commutative ring. PURPOSE: Auxiliary procedure for diagonal forms. Let R be a non-commutative ring (e.g. G-algebra), and p in R, this program checks whether p is two-sided i.e. Rp = pR. EXAMPLE: example isTwoSidedGB; shows examples " { int i; int n = nvars(basering); ideal J; // determine whether I is a left Groebner basis if (attrib(I,"isSB")) { J = I; J = simplify(J,1+2+4+8); attrib(J,"isSB",1); } else { intvec optionsave = option(get); option(redSB); option(redTail); J = std(I); J = simplify(J,1+2+4+8); attrib(J,"isSB",1); I = interred(I); I = simplify(I,1+2+4+8); if ( size(J) != size(I)) { option(set,optionsave); return(int(0)); } for(i = 1; i <= size(I); i++) { if (I[i] != J[i]) { option(set,optionsave); return(int(0)); } } } // I = simplify(I,1+2+4+8); // now, we check whether J is right complete for(i = 1; i <= n; i++) { if ( simplify( NF(J*var(i),J), 2) != 0 ) { return(int(0)); } } return(int(1)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,s),dp; def R = nc_algebra(1,s); setring R; //1st shift algebra ideal I = s^2, x*s, s^2 + 3*x*s; isTwoSidedGB(I); // I is two-sided ideal J = s^2+x; isTwoSidedGB(J); // J is not two-sided; twostd(J) = s,x; } singular-4.0.3+ds/Singular/LIB/brillnoether.lib000066400000000000000000000127161266270727000213370ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////// version="version brillnoether.lib 4.0.1.0 Oct_2014 "; // $Id: 629d46281fe8201d290fac3c41d8d1d6f54e3688 $ category="Algebraic Geometry"; info=" LIBRARY: brillnoether.lib Riemann-Roch spaces of divisors on curves AUTHORS: I. Stenger: stenger@mathematik.uni-kl.de Janko Boehm boehm@mathematik.uni-kl.de PROCEDURES: RiemannRochBN(); Computes a vector space basis of the Riemann-Roch space of a divisor D on a projective curve C "; LIB "normal.lib"; LIB "paraplanecurves.lib"; LIB "qhmoduli.lib"; LIB "divisors.lib"; /////////////////////////////////////////////////////////////////// ///////////////////// Main Procedure ////////////////////////////// //_________________________________________________________________ proc RiemannRochBN(ideal C,ideal I,ideal J) "USAGE: RiemannRochBN(C,I,J); ideal C, ideal I, ideal J ASSUME: C is a homogeneous ideal defining a projective curve. If C is a non-planar curve, then C is assumed to be nonsingular. This assumption is not checked. The ideals I and J represent a a divisor D on C. RETURN: A vector space basis of the Riemann-Roch space of D, stored in a list RRBasis. The list RRBasis contains a list IH and a form F. The vector space basis of L(D) consists of all rational functions G/F, where G is an element of IH. EXAMPLE: example RiemannRochBN; shows an example " { def R_base = basering; int i,boundFinal,boundReg,boundDeg; // C is a plane curve and is allowed to have singularities // involves the computation of the (Gorenstein) adjoint ideal if (nvars(R_base) == 3) { poly f = C[1]; //computation of the Gorenstein adjoint ideal adjointId = adjointIdeal(f); // every form of I defines an adjoint curve of C I = intersect(I,adjointId); // the curve is a plane curve, regularity not needed boundReg = 1; } else { // curve is non-planar and is assumed to be nonsingular // need to compute the regularity as a lower bound // for the degrees def Cres = mres(C,0); boundReg = regularity(Cres)-1; if (printlevel > 1) { "The regularity is"+string(boundReg); } } qring Q = std(C); ideal I = imap(R_base,I); ideal J = imap(R_base,J); divisor D = makeDivisor(I,J); // kill common places of the positive and negative divisor D = normalForm(D); I = D.num; J = D.den; // compute a set of minimal generators //I = minbase(sat(I,maxideal(1))[1]); //J = minbase(sat(J,maxideal(1))[1]); list degI; for (i=1; i<=size(I); i++) { degI[i]=deg(I[i]); } // compute the minimal degree of the gen. set boundDeg = Min(degI); boundFinal = Max(list(boundReg,boundDeg)); // choose a form F of I of degree greater or equal than boundFinal // such that the deg(:J) = deg() poly F = findRandomForm(I,J,boundFinal); if (printlevel > 1) { "The chosen form is "+string(F); } int n = deg(F[1]); // compute the residual divisor ideal Iresidual = quotient((sat(ideal(F),maxideal(1)))[1],I); ideal IH = intersect(Iresidual,J); IH = minbase(truncate1(IH,n)); //choose all forms of IH degree n IH = chooseGenerators(IH,n); setring R_base; ideal IH = imap(Q,IH); poly F = imap(Q,F); list RRBasis = IH,F; return(RRBasis); } example { "EXAMPLE:"; echo=2; ring R = 0,(x,y,z),dp; poly f = y^2+x^2-1; f = homog(f,z); ideal C = f; ideal P1 = x,y-z; ideal P2 = x^2+y^2,z; ideal I = intersect(P1^3,P2^2); ideal P3 = x+z,y; ideal J = P3^2; RiemannRochBN(C,I,J); } //////////////////////////////////////////////////////////////////// ///////////////////// Essential Static Procedures ////////////////// //_________________________________________________________________ static proc truncate1(ideal I,int r) "USAGE: truncate1(I,r); ideal I,int r ASSUME: I homogeneous ideal RETURN: the subideal of I consisting of all forms of degree greater or equal than r " { ideal IH; int i; for (i=1;i<=size(I);i++) { if (deg(I[i]) < r ) { IH = IH+maxideal(r-deg(I[i]))*I[i]; } else { IH = IH+I[i]; } } return(IH); } //__________________________________________________________________ static proc findRandomForm(ideal I,ideal J,int r) "USAGE: findRandomForm(I,J,r); ideal I, ideal J, int r ASSUME: I and J are homogeneous ideals RETURN: a form F of I of degree greater or than r such that the ideals :J and have the same degree THEORY: Assures that the divisor defined by F and the divisor defined by J have disjoint supports. " { int i,s; int h=1; ideal F1,G; while(h) { s = 0; while (s<5) { s++; poly Fhelp; for (i=1;i<=size(I);i++) { if( deg(I[i]) <= r) { Fhelp = Fhelp + I[i]*sparseid(1,r-deg(I[i]),r-deg(I[i]),0,10)[1]; } } G = Fhelp; F1 = quotient(G,J); if (mult(std(F1)) == mult(std(G))) { if (dim(std(G)) < dim(std(ideal(0)))) { h = 0; break; } } kill Fhelp; r++; } } poly finalform = G[1]; return(finalform); } //__________________________________________________________________ static proc chooseGenerators(ideal I,int r) { int i; ideal final; int counter; for (i=1; i<=size(I);i++) { if(deg(I[i]) == r) { counter++; final[counter] = I[i]; } } return(final); } singular-4.0.3+ds/Singular/LIB/brnoeth.lib000066400000000000000000004303461266270727000203120ustar00rootroot00000000000000//////////////////////////////////////////////////////////////// version="version brnoeth.lib 4.0.0.0 Jun_2013 "; // $Id: 3dd109188a2e487076094ac66d0477d8f11adb91 $ category="Coding theory"; info=" LIBRARY: brnoeth.lib Brill-Noether Algorithm, Weierstrass-SG and AG-codes AUTHORS: Jose Ignacio Farran Martin, ignfar@eis.uva.es Christoph Lossen, lossen@mathematik.uni-kl.de OVERVIEW: Implementation of the Brill-Noether algorithm for solving the Riemann-Roch problem and applications to Algebraic Geometry codes. The computation of Weierstrass semigroups is also implemented.@* The procedures are intended only for plane (singular) curves defined over a prime field of positive characteristic.@* For more information about the library see the end of the file brnoeth.lib. PROCEDURES: Adj_div(f) computes the conductor of a curve NSplaces(h,A) computes non-singular places with given degrees BrillNoether(D,C) computes a vector space basis of the linear system L(D) Weierstrass(P,m,C) computes the Weierstrass semigroup of C at P up to m extcurve(d,C) extends the curve C to an extension of degree d AGcode_L(G,D,E) computes the evaluation AG code with divisors G and D AGcode_Omega(G,D,E) computes the residual AG code with divisors G and D prepSV(G,D,F,E) preprocessing for the basic decoding algorithm decodeSV(y,K) decoding of a word with the basic decoding algorithm closed_points(I) computes the zero-set of a zero-dim. ideal in 2 vars dual_code(C) computes the dual code sys_code(C) computes an equivalent systematic code permute_L(L,P) applies a permutation to a list KEYWORDS: Weierstrass semigroup; Algebraic Geometry codes; Brill-Noether algorithm "; LIB "matrix.lib"; LIB "triang.lib"; LIB "hnoether.lib"; LIB "inout.lib"; /////////////////////////////////////////////////////////////////////////////// // ********************************************************** // * POINTS, PLACES AND DIVISORS OF (SINGULAR) PLANE CURVES * // ********************************************************** proc closed_points (ideal I) "USAGE: closed_points(I); I an ideal RETURN: list of prime ideals (each a Groebner basis), corresponding to the (distinct affine closed) points of V(I) NOTE: The ideal must have dimension 0, the basering must have 2 variables, the ordering must be lp, and the base field must be finite and prime.@* It might be convenient to set the option(redSB) in advance. SEE ALSO: triang_lib EXAMPLE: example closed_points; shows an example " { ideal II=std(I); if (II[1]==1) { return(list()); } list TL=triangMH(II); int s=size(TL); list L=list(); int i,j,k; ideal Facts; poly G2; for (i=1;i<=s;i=i+1) { Facts=factorize(TL[i][1],1); k=size(Facts); G2=TL[i][2]; for (j=1;j<=k;j=j+1) { L=L+pd2(Facts[j],G2); } } // eliminate possible repetitions s=size(L); list LP=list(); LP[1]=std(L[1]); int counter=1; for (i=2;i<=s;i=i+1) { if (isPinL(L[i],LP)==0) { counter=counter+1; LP[counter]=std(L[i]); } } return(LP); } example { "EXAMPLE:"; echo = 2; ring s=2,(x,y),lp; // this is just the affine plane over F_4 : ideal I=x4+x,y4+y; list L=closed_points(I); // and here you have all the points : L; } /////////////////////////////////////////////////////////////////////////////// static proc pd2 (poly g1,poly g2) { // If g1,g2 is a std. resp. lex. in (x,y) then the procedure // factorizes g2 in the "extension given by g1" // (then g1 must be irreducible) and returns a list of // ideals with always g1 as first component and the // distinct factors of g2 as second components list L=list(); ideal J=g1; int i,s; if (deg(g1)==1) { poly A=-subst(g1,var(2),0); poly B=subst(g2,var(2),A); ideal facts=factorize(B,1); s=size(facts); for (i=1;i<=s;i=i+1) { J[2]=facts[i]; L[i]=J; } } else { def BR=basering; poly A=g1; poly B=g2; ring raux1=char(basering),(x,y,@a),lp; poly G; ring raux2=(char(basering),@a),(x,y),lp; map psi=BR,x,@a; minpoly=number(psi(A)); if(!defined(psi)){ map psi=BR,x,@a; } poly f=psi(B); ideal facts=factorize(f,1); s=size(facts); poly g; string sg; for (i=1;i<=s;i=i+1) { g=facts[i]; sg=string(g); setring raux1; execute("G="+sg+";"); G=subst(G,@a,y); setring BR; map ppssii=raux1,var(1),var(2),0; J[2]=ppssii(G); L[i]=J; kill ppssii; setring raux2; } setring BR; kill raux1,raux2; } return(L); } /////////////////////////////////////////////////////////////////////////////// static proc isPinL (ideal P,list L) { // checks if a (plane) point P is in a list of (plane) points L // by just comparing generators // it works only if all (prime) ideals are given in a "canonical way", // namely: // the first generator is monic and irreducible, // and depends only on the second variable, // and the second one is monic in the first variable // and irreducible over the field extension determined by // the second variable and the first generator as minpoly int s=size(L); int i; for (i=1;i<=s;i=i+1) { if ( P[1]==L[i][1] && P[2]==L[i][2] ) { return(1); } } return(0); } /////////////////////////////////////////////////////////////////////////////// static proc s_locus (poly f) { // computes : ideal of affine singular locus // the equation f must be affine // warning : if there is an error message then the output is "none" // option(redSB) is convenient to be set in advance ideal I=f,jacob(f); I=std(I); if (dim(I)>0) { // dimension check (has to be 0) ERROR("something was wrong; possibly non-reduced curve"); } else { return(I); } } /////////////////////////////////////////////////////////////////////////////// static proc curve (poly f) "USAGE: curve(f), where f is a polynomial (affine or projective) CREATE: poly CHI in both rings aff_r=p,(x,y),lp and Proj_R=p,(x,y,z),lp also ideal (std) Aff_SLocus of affine singular locus in the ring aff_r RETURN: list (size 3) with two rings aff_r,Proj_R and an integer deg(f) NOTE: f must be absolutely irreducible, but this is not checked it is not implemented yet for extensions of prime fields " { def base_r=basering; ring aff_r=char(basering),(x,y),lp; ring Proj_R=char(basering),(x,y,z),lp; setring base_r; int degX=deg(f); if (nvars(basering)==2) { setring aff_r; map embpol=base_r,x,y; poly CHI=embpol(f); export(CHI); kill embpol; ideal Aff_SLocus=s_locus(CHI); export(Aff_SLocus); setring Proj_R; poly CHI=homog(imap(aff_r,CHI),z); export(CHI); setring base_r; list L=list(); L[1]=aff_r; L[2]=Proj_R; L[3]=degX; kill aff_r,Proj_R; return(L); } if (nvars(basering)==3) { setring Proj_R; map embpol=base_r,x,y,z; poly CHI=embpol(f); export(CHI); kill embpol; string s=string(subst(CHI,z,1)); setring aff_r; execute("poly CHI="+s+";"); export(CHI); ideal Aff_SLocus=s_locus(CHI); export(Aff_SLocus); setring base_r; list L=list(); L[1]=aff_r; L[2]=Proj_R; L[3]=degX; kill aff_r,Proj_R; return(L); } ERROR("basering must have 2 or 3 variables"); } /////////////////////////////////////////////////////////////////////////////// static proc Aff_SL (ideal ISL) { // computes : affine singular (closed) points as a list of lists of // prime ideals and intvec (for storing the places over each point) // the ideal ISL=s_locus(CHI) is assumed to be computed in advance for // a plane curve CHI, and it must be given by a standard basis // for our purpose the function must called with the "global" ideal // "Aff_SLocus" list SL=list(); ideal I=ISL; if ( I[1] != 1 ) { list L=list(); ideal aux; intvec iv; int i,s; L=closed_points(I); s=size(L); for (i=1;i<=s;i=i+1) { aux=std(L[i]); SL[i]=list(aux,iv); } } return(SL); } /////////////////////////////////////////////////////////////////////////////// static proc inf_P (poly f) { // computes : all (closed) points at infinity as homogeneous polynomials // output : two lists with respectively singular and non-singular points intvec iv; def base_r=basering; ring r_auxz=char(basering),(x,y,z),lp; poly f=imap(base_r,f); poly F=homog(f,z); // equation of projective curve poly f_inf=subst(F,z,0); setring base_r; poly f_inf=imap(r_auxz,f_inf); ideal I=factorize(f_inf,1); // points at infinity as homogeneous // polynomials int s=size(I); int i; list IP_S=list(); // for singular points at infinity list IP_NS=list(); // for non-singular points at infinity int counter_S; int counter_NS; poly aux; for (i=1;i<=s;i=i+1) { aux=subst(I[i],y,1); if (aux==1) { // the point is (1:0:0) setring r_auxz; poly f_yz=subst(F,x,1); if ( subst(subst(diff(f_yz,y),y,0),z,0)==0 && subst(subst(diff(f_yz,z),y,0),z,0)==0 ) { // the point is singular counter_S=counter_S+1; kill f_yz; setring base_r; IP_S[counter_S]=list(I[i],iv); } else { // the point is non-singular counter_NS=counter_NS+1; kill f_yz; setring base_r; IP_NS[counter_NS]=list(I[i],iv); } } else { // the point is (a:1:0) | a is root of aux if (deg(aux)==1) { // the point is rational and no field extension is needed setring r_auxz; poly f_xz=subst(F,y,1); poly aux=imap(base_r,aux); number A=-number(subst(aux,x,0)); map phi=r_auxz,x+A,0,z; poly f_origin=phi(f_xz); if ( subst(subst(diff(f_origin,x),x,0),z,0)==0 && subst(subst(diff(f_origin,z),x,0),z,0)==0 ) { // the point is singular counter_S=counter_S+1; kill f_xz,aux,A,phi,f_origin; setring base_r; IP_S[counter_S]=list(I[i],iv); } else { // the point is non-singular counter_NS=counter_NS+1; kill f_xz,aux,A,phi,f_origin; setring base_r; IP_NS[counter_NS]=list(I[i],iv); } } else { // the point is non-rational and a field extension with minpoly=aux // is needed ring r_ext=(char(basering),@a),(x,y,z),lp; poly F=imap(r_auxz,F); poly f_xz=subst(F,y,1); poly aux=imap(base_r,aux); minpoly=number(subst(aux,x,@a)); map phi=r_ext,x+@a,0,z; poly f_origin=phi(f_xz); if ( subst(subst(diff(f_origin,x),x,0),z,0)==0 && subst(subst(diff(f_origin,z),x,0),z,0)==0 ) { // the point is singular counter_S=counter_S+1; setring base_r; kill r_ext; IP_S[counter_S]=list(I[i],iv); } else { // the point is non-singular counter_NS=counter_NS+1; setring base_r; kill r_ext; IP_NS[counter_NS]=list(I[i],iv); } } } } kill r_auxz; return(list(IP_S,IP_NS)); } /////////////////////////////////////////////////////////////////////////////// static proc closed_points_ext (poly f,int d,ideal SL) { // computes : (closed affine non-singular) points over an extension of // degree d // remark(1) : singular points are supposed to be listed appart // remark(2) : std SL=s_locus(f) is supposed to be computed in advance // remark(3) : ideal SL is used to remove those points which are singular // output : list of list of prime ideals with an intvec for storing the // places int Q=char(basering)^d; // cardinality of the extension field ideal I=f,x^Q-x,y^Q-y; // ideal of the searched points I=std(I); if (I==1) { return(list()); } list LP=list(); int m=size(SL); list L=list(); ideal aux; intvec iv; int i,s,j,counter; L=closed_points(I); s=size(L); for (i=1;i<=s;i=i+1) { aux=std(L[i]); for (j=1;j<=m;j=j+1) { // check if singular i.e. if SL is contained in aux if ( NF(SL[j],aux) != 0 ) { counter=counter+1; LP[counter]=list(aux,iv); break; } } } return(LP); } /////////////////////////////////////////////////////////////////////////////// static proc degree_P (list P) "USAGE: degree_P(P), where P is either a polynomial or an ideal RETURN: integer with the degree of the closed point given by P SEE ALSO: closed_points NOTE: If P is a (homogeneous irreducible) polynomial the point is at infinity, and if P is a (prime) ideal the points is affine, and the ideal must be given by 2 generators: the first one irreducible and depending only on y, and the second one irreducible over the extension given by y with the first generator as minimal polynomial " { // computes : the degree of a given point // remark(1) : if the input is (irreducible homogeneous) polynomial => the point // is at infinity // remark(2) : it the input is (std. resp. lp. prime) ideal => the point is // affine if (typeof(P[1])=="ideal") { if (size(P[1])==2) { int d=deg(P[1][1]); poly aux=subst(P[1][2],y,1); d=d*deg(aux); return(d); } else { // this should not happen in principle ERROR("non-valid parameter"); } } else { if (typeof(P[1])=="poly") { return(deg(P[1])); } else { ERROR("parameter must have a polynomial or ideal in the first component"); } } } /////////////////////////////////////////////////////////////////////////////// static proc closed_points_deg (poly f,int d,ideal SL) { // computes : (closed affine non-singular) points of degree d // remark(1) : singular points are supposed to be listed appart // remark(2) : std SL=s_locus(f) is supposed to be computed in advance list L=closed_points_ext(f,d,SL); int s=size(L); int i,counter; list LP=list(); for (i=1;i<=s;i=i+1) { if (degree_P(L[i])==d) { counter++; LP[counter]=L[i]; } } return(LP); } /////////////////////////////////////////////////////////////////////////////// static proc idealSubset (ideal I,ideal J) { // checks wether I is contained in J and returns a boolean // remark : J is assumed to be given by a standard basis int s=ncols(I); int i; for (i=1;i<=s;i=i+1) { if ( NF(I[i],std(J)) != 0 ) { return(0); } } return(1); } /////////////////////////////////////////////////////////////////////////////// static proc belongs (list P,ideal I) { // checks if affine point P is contained in V(I) and returns a boolean // remark : P[1] is assumed to be an ideal given by a standard basis if (typeof(P[1])=="ideal") { return(idealSubset(I,P[1])); } else { ERROR("first argument must be an affine point"); } } /////////////////////////////////////////////////////////////////////////////// static proc equals (ideal I,ideal J) { // checks if I is equal to J and returns a boolean // remark : I and J are assumed to be given by a standard basis int answer=0; if (idealSubset(I,J)==1) { if (idealSubset(J,I)==1) { answer=1; } } return(answer); } /////////////////////////////////////////////////////////////////////////////// static proc isInLP (ideal P,list LP) { // checks if affine point P is a list LP and returns either its position or // zero // remark : all points in LP and P itself are assumed to be given by a // standard basis // warning : the procedure does not check whether the points are affine or // not int s=size(LP); if (s==0) { return(0); } int i; for (i=1;i<=s;i=i+1) { if (equals(P,LP[i][1])==1) { return(i); } } return(0); } /////////////////////////////////////////////////////////////////////////////// static proc res_deg () { // computes the residual degree of the basering with respect to its prime // field // warning : minpoly must depend on a parameter called "a" int ext; string s_m=string(minpoly); if (s_m=="0") { ext=1; } else { ring auxr=char(basering),a,lp; execute("poly minp="+s_m+";"); ext=deg(minp); } return(ext); } /////////////////////////////////////////////////////////////////////////////// static proc Frobenius (def etwas,int r) { // applies the Frobenius map over F_{p^r} to an object defined over an // extension of such field // usually it is called with r=1, i.e. the Frobenius map over the prime // field F_p // returns always an object of the same type, and works correctly on // numbers, polynomials, ideals, matrices or lists of the above types // maybe : types vector and module should be added in the future, but they // are not needed now int q=char(basering)^r; if (typeof(etwas)=="number") { return(etwas^q); } if (typeof(etwas)=="poly") { int s=size(etwas); poly f; int i; for (i=1;i<=s;i=i+1) { f=f+(leadcoef(etwas[i])^q)*leadmonom(etwas[i]); } return(f); } if (typeof(etwas)=="ideal") { int s=ncols(etwas); ideal I; int i; for (i=1;i<=s;i=i+1) { I[i]=Frobenius(etwas[i],r); } return(I); } if (typeof(etwas)=="matrix") { int m=nrows(etwas); int n=ncols(etwas); matrix A[m][n]; int i,j; for (i=1;i<=m;i=i+1) { for (j=1;j<=n;j=j+1) { A[i,j]=Frobenius(etwas[i,j],r); } } return(A); } if (typeof(etwas)=="list") { int s=size(etwas); list L=list(); int i; for (i=1;i<=s;i=i+1) { if (typeof(etwas[i])<>"none") { L[i]=Frobenius(etwas[i],r); } } return(L); } return(etwas); } /////////////////////////////////////////////////////////////////////////////// static proc conj_b (list L,int r) { // applies the Frobenius map over F_{p^r} to a list of type HNE defined over // a larger extension // when r=1 it turns to be the Frobenius map over the prime field F_{p} // returns : a list of type HNE which is either conjugate of the input or // the same list in case of L being actually defined over the base field // F_{p^r} int p=char(basering); int Q=p^r; list LL=list(); int m=nrows(L[1]); int n=ncols(L[1]); matrix A[m][n]; poly f; poly aux; int i,j; for (i=1;i<=m;i=i+1) { for (j=1;j<=n;j=j+1) { aux=L[1][i,j]; if (aux<>x) { A[i,j]=aux^Q; } else { A[i,j]=aux; break; } } } m=size(L[4]); for (i=1;i<=m;i=i+1) { f=f+(leadcoef(L[4][i])^Q)*leadmonom(L[4][i]); } LL[1]=A; LL[2]=L[2]; LL[3]=L[3]; LL[4]=f; return(LL); } /////////////////////////////////////////////////////////////////////////////// static proc grad_b (list L,int r) { // computes the degree of a list of type HNE which is actually defined over // F_{p^r} eventhough it is given in an extension of such field int gr=1; int rd=res_deg() div r; list LL=L; int i; for (i=1;i<=rd;i=i+1) { LL=conj_b(LL,r); if ( LL[1]==L[1] && LL[4]==L[4] ) { break; } else { gr=gr+1; } } return(gr); } /////////////////////////////////////////////////////////////////////////////// static proc conj_bs (list L,int r) { // computes all the conjugates over F_{p^r} of a list of type HNE defined // over an extension // returns : a list of lists of type HNE, where the first one is the input // list // remark : notice that the degree of the branch is then the size of the // output list branches=list(); int gr=1; branches[1]=L; int rd=res_deg() div r; list LL=L; int i; for (i=1;i<=rd;i=i+1) { LL=conj_b(LL,r); if ( LL[1]==L[1] && LL[4]==L[4] ) { break; } else { gr=gr+1; branches[gr]=LL; } } return(branches); } /////////////////////////////////////////////////////////////////////////////// static proc subfield (def sf) { // writes the generator "a" of a subfield of the coefficients field of // basering in terms of the current generator (also called "a") as a // string sf is an existing ring whose coefficient field is such a subfield // warning : in basering there must be a variable called "x" and subfield // must not be prime def base_r=basering; string new_m=string(minpoly); setring sf; string old_m=string(minpoly); if (old_m==new_m) { setring base_r; return("a"); } else { if (old_m<>string(0)) { ring auxring=char(basering),(a,x),lp; execute("poly mpol="+old_m+";"); mpol=subst(mpol,a,x); setring base_r; poly mpol=imap(auxring,mpol); kill auxring; string answer="? error : non-primitive element"; int r=res_deg(); int q=char(basering)^r; int i; number b; for (i=1;i<=q-2;i=i+1) { b=a^i; if (subst(mpol,x,b)==0) { answer=string(b); break; } } if (answer<>"? error : non-primitive element") { return(answer); } else { // list all the elements of the finite field F_q int p=char(basering); list FF1,FF2; for (i=0;i1&2 the point is assumed non-singular and the local conductor // should be zero list PP=list(); if (Pp[1]==0) { if (Pp[2]==0) { PP=Aff_SPoints[Pp[3]]; } if (Pp[2]==1) { PP=Inf_Points[1][Pp[3]]; } if (Pp[2]==2) { PP=Inf_Points[2][Pp[3]]; } } else { PP=Aff_Points(Pp[2])[Pp[3]]; } if (PP[2]<>0) { return(CURVE); } intvec PtoPl; def base_r=basering; int ext1; list Places=CURVE[3]; intvec Conductor=CURVE[4]; list update_CURVE=CURVE; if (typeof(PP[1])=="ideal") { ideal P=PP[1]; if (size(P)==2) { int d=deg(P[1]); poly aux=subst(P[2],y,1); d=d*deg(aux); ext1=d; // the point is (A:B:1) but one must distinguish several cases // P is assumed to be a std. resp. "(x,y),lp" and thus P[1] depends // only on "y" if (d==1) { // the point is rational number B=-number(subst(P[1],y,0)); poly aux2=subst(P[2],y,B); number A=-number(subst(aux2,x,0)); // the point is (A:B:1) ring local_aux=char(basering),(x,y),ls; number coord@1=imap(base_r,A); number coord@2=imap(base_r,B); number coord@3=number(1); map phi=base_r,x+coord@1,y+coord@2; poly CHI=phi(CHI); } else { if (deg(P[1])==1) { // the point is non-rational but the second component needs no // field extension number B=-number(subst(P[1],y,0)); poly aux2=subst(P[2],y,B); // the point has degree d>1 // careful : the parameter will be called "a" anyway ring local_aux=(char(basering),a),(x,y),ls; map psi=base_r,a,0; minpoly=number(psi(aux2)); number coord@1=a; number coord@2=imap(base_r,B); number coord@3=number(1); // the point is (a:B:1) map phi=base_r,x+a,y+coord@2; poly CHI=phi(CHI); } else { if (deg(subst(P[2],y,1))==1) { // the point is non-rational but the needed minpoly is just P[1] // careful : the parameter will be called "a" anyway poly P1=P[1]; poly P2=P[2]; ring local_aux=(char(basering),a),(x,y),ls; map psi=base_r,0,a; minpoly=number(psi(P1)); // the point looks like (A:a:1) // A is computed by substituting y=a in P[2] poly aux1=imap(base_r,P2); poly aux2=subst(aux1,y,a); number coord@1=-number(subst(aux2,x,0)); number coord@2=a; number coord@3=number(1); map phi=base_r,x+coord@1,y+a; poly CHI=phi(CHI); } else { // this is the most complicated case of non-rational point // firstly : construct an extension of degree d and guess the // minpoly poly P1=P[1]; poly P2=P[2]; int p=char(basering); int Q=p^d; ring aux_r=(Q,a),(x,y,t),ls; string minpoly_string=string(minpoly); ring local_aux=(char(basering),a),(x,y),ls; execute("minpoly="+minpoly_string+";"); // secondly : compute one root of P[1] poly P_1=imap(base_r,P1); poly P_2=imap(base_r,P2); ideal factors1=factorize(P_1,1); // hopefully this works !!!! number coord@2=-number(subst(factors1[1],y,0)); // thirdly : compute one of the first components for the above root poly P_0=subst(P_2,y,coord@2); ideal factors2=factorize(P_0,1); // hopefully this works !!!! number coord@1=-number(subst(factors2[1],x,0)); number coord@3=number(1); map phi=base_r,x+coord@1,y+coord@2; poly CHI=phi(CHI); kill aux_r; } } } } else { // this should not happen in principle ERROR("non-valid parameter"); } } else { if (typeof(PP[1])=="poly") { poly P=PP[1]; ring r_auxz=char(basering),(x,y,z),lp; poly CHI=imap(base_r,CHI); CHI=homog(CHI,z); setring base_r; poly aux=subst(P,y,1); if (aux==1) { // the point is (1:0:0) ring local_aux=char(basering),(x,y),ls; number coord@1=number(1); number coord@2=number(0); number coord@3=number(0); map Phi=r_auxz,1,x,y; poly CHI=Phi(CHI); ext1=1; } else { // the point is (A:1:0) where A is a root of aux int d=deg(aux); ext1=d; if (d==1) { // the point is rational number A=-number(subst(aux,x,0)); ring local_aux=char(basering),(x,y),ls; number coord@1=imap(base_r,A); number coord@2=number(1); number coord@3=number(0); map Phi=r_auxz,x+coord@1,1,y; poly CHI=Phi(CHI); } else { // the point has degree d>1 // careful : the parameter will be called "a" anyway ring local_aux=(char(basering),a),(x,y),ls; map psi=base_r,a,1; minpoly=number(psi(P)); number coord@1=a; number coord@2=number(1); number coord@3=number(0); map Phi=r_auxz,x+a,1,y; poly CHI=Phi(CHI); } } kill r_auxz; } else { ERROR("a point must have a polynomial or ideal in the first component"); } } export(coord@1); export(coord@2); export(coord@3); export(CHI); int i,j,k; int m,n; list LLL=ratdevelop(CHI); // list LLL=hnexpansion(CHI,"ess"); if (typeof(LLL[1])=="ring") { def altring=basering; def HNEring = LLL[1]; setring HNEring; def L@HNE = HND; kill HND; // def L@HNE = hne; // kill hne; } else { def L@HNE=LLL; // def L@HNE=LLL[1]; def HNEring=basering; setring HNEring; } kill LLL; export(L@HNE); int n_branches=size(L@HNE); list Li_aux=list(); int N_branches; int N=size(Places); if (sing==1) { list delta2=list(); for (i=1;i<=n_branches;i=i+1) { delta2[i]=invariants(L@HNE[i])[5]; } int dq; } int ext2=res_deg(); list dgs=list(); int ext_0; int check; string sss,olda,newa; if (defined(Q)==0) { int Q; } if (ext1==1) { if (ext2==1) { if (sing==1) { intmat I_mult[n_branches][n_branches]; if (n_branches>1) { for (i=1;i<=n_branches-1;i=i+1) { for (j=i+1;j<=n_branches;j=j+1) { I_mult[i,j]=intersection(L@HNE[i],L@HNE[j]); I_mult[j,i]=I_mult[i,j]; } } } } //////// check=0; //////// if (size(update_CURVE[5])>0) { if (typeof(update_CURVE[5][1])=="list") { check=1; } } if (check==0) { intvec dgs_points(1); ring S(1)=char(basering),(x,y,t),ls; list BRANCHES=list(); list POINTS=list(); list LOC_EQS=list(); list PARAMETRIZATIONS=list(); export(BRANCHES); export(POINTS); export(LOC_EQS); export(PARAMETRIZATIONS); } else { intvec dgs_points(1)=update_CURVE[5][1][2]; def S1=update_CURVE[5][1][1]; execute("ring S(1)="+string(update_CURVE[5][1][1])+";"); fetchall(S1); kill S1; } N_branches=size(BRANCHES); for (i=1;i<=n_branches;i=i+1) { dgs_points(1)[N_branches+i]=1; POINTS[N_branches+i]=list(); POINTS[N_branches+i][1]=imap(local_aux,coord@1); POINTS[N_branches+i][2]=imap(local_aux,coord@2); POINTS[N_branches+i][3]=imap(local_aux,coord@3); LOC_EQS[N_branches+i]=imap(local_aux,CHI); setring HNEring; Li_aux=L@HNE[i]; setring S(1); BRANCHES=insert(BRANCHES,imap(HNEring,Li_aux),N_branches+i-1); PARAMETRIZATIONS[N_branches+i]=param(BRANCHES[N_branches+i],0); N=N+1; intvec iw=1,N_branches+i; Places[N]=iw; if (sing==1) { dq=delta2[i]; for (j=1;j<=n_branches;j=j+1) { dq=dq+I_mult[i,j]; } Conductor[N]=dq; } if (sing==2) { Conductor[N]=local_conductor(iw[2],S(1)); } kill iw; PtoPl[i]=N; } setring base_r; update_CURVE[5][1]=list(); update_CURVE[5][1][1]=S(1); update_CURVE[5][1][2]=dgs_points(1); } else { // we start with a rational point but we get non-rational branches // they may have different degrees and then we may need to reduce the // field extensions for each one, and finally check if the minpoly // fetches with S(i) or not // if one of the branches is rational, we may trust that it is written // correctly if (sing==1) { int n_geobrs; int counter_c; list auxgb=list(); list geobrs=list(); for (i=1;i<=n_branches;i=i+1) { auxgb=conj_bs(L@HNE[i],1); dgs[i]=size(auxgb); n_geobrs=n_geobrs+dgs[i]; for (j=1;j<=dgs[i];j=j+1) { counter_c=counter_c+1; geobrs[counter_c]=auxgb[j]; } } intmat I_mult[n_geobrs][n_geobrs]; for (i=1;i=ext_0) { if (typeof(update_CURVE[5][ext_0])=="list") { check=1; } } if (check==0) { if (ext_0>1) { if (ext_0==ext2) { sss=string(minpoly); } else { Q=char(basering)^ext_0; ring auxxx=(Q,a),z,lp; sss=string(minpoly); setring base_r; kill auxxx; } ring S(ext_0)=(char(basering),a),(x,y,t),ls; execute("minpoly="+sss+";"); } else { ring S(ext_0)=char(basering),(x,y,t),ls; } intvec dgs_points(ext_0); list BRANCHES=list(); list POINTS=list(); list LOC_EQS=list(); list PARAMETRIZATIONS=list(); export(BRANCHES); export(POINTS); export(LOC_EQS); export(PARAMETRIZATIONS); } else { intvec dgs_points(ext_0)=update_CURVE[5][ext_0][2]; def Sext_0=update_CURVE[5][ext_0][1]; setring Sext_0; string SM=string(minpoly); string SR=string(update_CURVE[5][ext_0][1]); execute("ring S("+string(ext_0)+")="+SR+";"); execute("minpoly="+SM+";"); kill SM,SR; fetchall(Sext_0); kill Sext_0; } N_branches=size(BRANCHES); dgs_points(ext_0)[N_branches+1]=1; POINTS[N_branches+1]=list(); POINTS[N_branches+1][1]=imap(local_aux,coord@1); POINTS[N_branches+1][2]=imap(local_aux,coord@2); POINTS[N_branches+1][3]=imap(local_aux,coord@3); LOC_EQS[N_branches+1]=imap(local_aux,CHI); // now fetch the branches into the new local ring if (ext_0==1) { setring HNEring; Li_aux=L@HNE[i]; setring S(1); BRANCHES=insert(BRANCHES,imap(HNEring,Li_aux),N_branches); } else { // rationalize branch setring HNEring; newa=subfield(S(ext_0)); m=nrows(L@HNE[i][1]); n=ncols(L@HNE[i][1]); setring S(ext_0); list Laux=list(); poly paux=rationalize(HNEring,"L@HNE["+string(i)+"][4]",newa); matrix Maux[m][n]; for (j=1;j<=m;j=j+1) { for (k=1;k<=n;k=k+1) { Maux[j,k]=rationalize(HNEring,"L@HNE["+string(i)+"][1]["+ string(j)+","+string(k)+"]",newa); } } setring HNEring; intvec Li2=L@HNE[i][2]; int Li3=L@HNE[i][3]; setring S(ext_0); Laux[1]=Maux; Laux[2]=Li2; Laux[3]=Li3; Laux[4]=paux; BRANCHES=insert(BRANCHES,Laux,N_branches); kill Laux,Maux,paux,Li2,Li3; } PARAMETRIZATIONS[N_branches+1]=param(BRANCHES[N_branches+1],0); N=N+1; intvec iw=ext_0,N_branches+1; Places[N]=iw; if (sing==2) { Conductor[N]=local_conductor(iw[2],S(ext_0)); } kill iw; PtoPl[i]=N; setring HNEring; update_CURVE[5][ext_0]=list(); update_CURVE[5][ext_0][1]=S(ext_0); update_CURVE[5][ext_0][2]=dgs_points(ext_0); } if (sing==1) { int N_ini=N-n_branches; counter_c=1; for (i=1;i<=n_branches;i=i+1) { dq=delta2[i]; for (j=1;j<=n_geobrs;j=j+1) { dq=dq+I_mult[counter_c,j]; } Conductor[N_ini+i]=dq; counter_c=counter_c+dgs[i]; } } setring base_r; } } else { if (ext1==ext2) { // the degree of the point equals to the degree of all branches // one must just fetch the minpoly's of local_aux, HNEring and S(ext2) if (sing==1) { intmat I_mult[n_branches][n_branches]; if (n_branches>1) { for (i=1;i<=n_branches-1;i=i+1) { for (j=i+1;j<=n_branches;j=j+1) { I_mult[i,j]=intersection(L@HNE[i],L@HNE[j]); I_mult[j,i]=I_mult[i,j]; } } } } //////// check=0; //////// if (size(update_CURVE[5])>=ext2) { if (typeof(update_CURVE[5][ext2])=="list") { check=1; } } if (check==0) { sss=string(minpoly); ring S(ext2)=(char(basering),a),(x,y,t),ls; execute("minpoly="+sss+";"); intvec dgs_points(ext2); list BRANCHES=list(); list POINTS=list(); list LOC_EQS=list(); list PARAMETRIZATIONS=list(); export(BRANCHES); export(POINTS); export(LOC_EQS); export(PARAMETRIZATIONS); } else { intvec dgs_points(ext2)=update_CURVE[5][ext2][2]; def Sext2=update_CURVE[5][ext2][1]; setring Sext2; string SM=string(minpoly); string SR=string(update_CURVE[5][ext2][1]); execute("ring S("+string(ext2)+")="+SR+";"); execute("minpoly="+SM+";"); kill SM,SR; fetchall(Sext2); kill Sext2; } N_branches=size(BRANCHES); for (i=1;i<=n_branches;i=i+1) { // fetch all the data into the new local ring olda=subfield(local_aux); dgs_points(ext2)[N_branches+i]=ext1; POINTS[N_branches+i]=list(); POINTS[N_branches+i][1]=number(importdatum(local_aux,"coord@1",olda)); POINTS[N_branches+i][2]=number(importdatum(local_aux,"coord@2",olda)); POINTS[N_branches+i][3]=number(importdatum(local_aux,"coord@3",olda)); LOC_EQS[N_branches+i]=importdatum(local_aux,"CHI",olda); newa=subfield(HNEring); setring HNEring; m=nrows(L@HNE[i][1]); n=ncols(L@HNE[i][1]); setring S(ext2); list Laux=list(); poly paux=importdatum(HNEring,"L@HNE["+string(i)+"][4]",newa); matrix Maux[m][n]; for (j=1;j<=m;j=j+1) { for (k=1;k<=n;k=k+1) { Maux[j,k]=importdatum(HNEring,"L@HNE["+string(i)+"][1]["+ string(j)+","+string(k)+"]",newa); } } setring HNEring; intvec Li2=L@HNE[i][2]; int Li3=L@HNE[i][3]; setring S(ext2); Laux[1]=Maux; Laux[2]=Li2; Laux[3]=Li3; Laux[4]=paux; BRANCHES=insert(BRANCHES,Laux,N_branches+i-1); kill Laux,Maux,paux,Li2,Li3; PARAMETRIZATIONS[N_branches+i]=param(BRANCHES[N_branches+i],0); N=N+1; intvec iw=ext2,N_branches+i; Places[N]=iw; if (sing==1) { dq=delta2[i]; for (j=1;j<=n_branches;j=j+1) { dq=dq+I_mult[i,j]; } Conductor[N]=dq; } if (sing==2) { Conductor[N]=local_conductor(iw[2],S(ext2)); } kill iw; PtoPl[i]=N; } setring base_r; update_CURVE[5][ext2]=list(); update_CURVE[5][ext2][1]=S(ext2); update_CURVE[5][ext2][2]=dgs_points(ext2); } else { // this is the most complicated case if (sing==1) { int n_geobrs; int counter_c; list auxgb=list(); list geobrs=list(); for (i=1;i<=n_branches;i=i+1) { auxgb=conj_bs(L@HNE[i],ext1); dgs[i]=size(auxgb); n_geobrs=n_geobrs+dgs[i]; for (j=1;j<=dgs[i];j=j+1) { counter_c=counter_c+1; geobrs[counter_c]=auxgb[j]; } } intmat I_mult[n_geobrs][n_geobrs]; for (i=1;i=ext_0) { if (typeof(update_CURVE[5][ext_0])=="list") { check=1; } } if (check==0) { if (ext_0>ext1) { if (ext_0==ext2) { sss=string(minpoly); } else { Q=char(basering)^ext_0; ring auxxx=(Q,a),z,lp; sss=string(minpoly); setring base_r; kill auxxx; } } else { setring local_aux; sss=string(minpoly); } ring S(ext_0)=(char(basering),a),(x,y,t),ls; execute("minpoly="+sss+";"); intvec dgs_points(ext_0); list BRANCHES=list(); list POINTS=list(); list LOC_EQS=list(); list PARAMETRIZATIONS=list(); export(BRANCHES); export(POINTS); export(LOC_EQS); export(PARAMETRIZATIONS); } else { intvec dgs_points(ext_0)=update_CURVE[5][ext_0][2]; def Sext_0=update_CURVE[5][ext_0][1]; setring Sext_0; string SM=string(minpoly); string SR=string(update_CURVE[5][ext_0][1]); execute("ring S("+string(ext_0)+")="+SR+";"); execute("minpoly="+SM+";"); kill SM,SR; fetchall(badring); kill badring; } N_branches=size(BRANCHES); // now fetch all the data into the new local ring olda=subfield(local_aux); dgs_points(ext_0)[N_branches+1]=ext1; POINTS[N_branches+1]=list(); POINTS[N_branches+1][1]=number(importdatum(local_aux,"coord@1",olda)); POINTS[N_branches+1][2]=number(importdatum(local_aux,"coord@2",olda)); POINTS[N_branches+1][3]=number(importdatum(local_aux,"coord@3",olda)); LOC_EQS[N_branches+1]=importdatum(local_aux,"CHI",olda); setring HNEring; newa=subfield(S(ext_0)); m=nrows(L@HNE[i][1]); n=ncols(L@HNE[i][1]); setring S(ext_0); list Laux=list(); poly paux=rationalize(HNEring,"L@HNE["+string(i)+"][4]",newa); matrix Maux[m][n]; for (j=1;j<=m;j=j+1) { for (k=1;k<=n;k=k+1) { Maux[j,k]=rationalize(HNEring,"L@HNE["+string(i)+"][1]["+ string(j)+","+string(k)+"]",newa); } } setring HNEring; intvec Li2=L@HNE[i][2]; int Li3=L@HNE[i][3]; setring S(ext_0); Laux[1]=Maux; Laux[2]=Li2; Laux[3]=Li3; Laux[4]=paux; BRANCHES=insert(BRANCHES,Laux,N_branches); kill Laux,Maux,paux,Li2,Li3; PARAMETRIZATIONS[N_branches+1]=param(BRANCHES[N_branches+1],0); N=N+1; intvec iw=ext_0,N_branches+1; Places[N]=iw; if (sing==2) { Conductor[N]=local_conductor(iw[2],S(ext_0)); } kill iw; PtoPl[i]=N; setring HNEring; update_CURVE[5][ext_0]=list(); update_CURVE[5][ext_0][1]=S(ext_0); update_CURVE[5][ext_0][2]=dgs_points(ext_0); } if (sing==1) { int N_ini=N-n_branches; counter_c=1; for (i=1;i<=n_branches;i=i+1) { dq=delta2[i]; for (j=1;j<=n_geobrs;j=j+1) { dq=dq+I_mult[counter_c,j]; } Conductor[N_ini+i]=dq; counter_c=counter_c+dgs[i]; } } setring base_r; } } update_CURVE[3]=Places; update_CURVE[4]=Conductor; PP[2]=PtoPl; if (Pp[1]==0) { if (Pp[2]==0) { Aff_SPoints[Pp[3]]=PP; } if (Pp[2]==1) { Inf_Points[1][Pp[3]]=PP; } if (Pp[2]==2) { Inf_Points[2][Pp[3]]=PP; } } else { Aff_Points(Pp[2])[Pp[3]]=PP; } update_CURVE[1][1]=base_r; kill HNEring; kill local_aux; return(update_CURVE); } /////////////////////////////////////////////////////////////////////////////// static proc local_conductor (int k,def SS) { // computes the degree of the local conductor at a place of a plane curve // if the point is non-singular the result will be zero // the computation is carried out with the "Dedekind formula" via // parametrizations int a,b,Cq; def b_ring=basering; setring SS; poly fx=diff(LOC_EQS[k],x); poly fy=diff(LOC_EQS[k],y); int nr=ncols(BRANCHES[k][1]); poly xt=PARAMETRIZATIONS[k][1][1]; poly yt=PARAMETRIZATIONS[k][1][2]; int ordx=PARAMETRIZATIONS[k][2][1]; int ordy=PARAMETRIZATIONS[k][2][2]; map phi_t=basering,xt,yt,1; poly derf; if (fx<>0) { derf=fx; poly tt=diff(yt,t); b=mindeg(tt); if (ordy>-1) { while (b>=ordy) { BRANCHES[k]=extdevelop(BRANCHES[k],2*nr); nr=ncols(BRANCHES[k][1]); PARAMETRIZATIONS[k]=param(BRANCHES[k],0); ordy=PARAMETRIZATIONS[k][2][2]; yt=PARAMETRIZATIONS[k][1][2]; tt=diff(yt,t); b=mindeg(tt); } xt=PARAMETRIZATIONS[k][1][1]; ordx=PARAMETRIZATIONS[k][2][1]; } poly ft=phi_t(derf); } else { derf=fy; poly tt=diff(xt,t); b=mindeg(tt); if (ordx>-1) { while (b>=ordx) { BRANCHES[k]=extdevelop(BRANCHES[k],2*nr); nr=ncols(BRANCHES[k][1]); PARAMETRIZATIONS[k]=param(BRANCHES[k],0); ordx=PARAMETRIZATIONS[k][2][1]; xt=PARAMETRIZATIONS[k][1][1]; tt=diff(xt,t); b=mindeg(tt); } yt=PARAMETRIZATIONS[k][1][2]; ordy=PARAMETRIZATIONS[k][2][2]; } poly ft=phi_t(derf); } a=mindeg(ft); if ( ordx>-1 || ordy>-1 ) { if (ordy==-1) { while (a>ordx) { BRANCHES[k]=extdevelop(BRANCHES[k],2*nr); nr=ncols(BRANCHES[k][1]); PARAMETRIZATIONS[k]=param(BRANCHES[k],0); ordx=PARAMETRIZATIONS[k][2][1]; xt=PARAMETRIZATIONS[k][1][1]; ft=phi_t(derf); a=mindeg(ft); } } else { if (ordx==-1) { while (a>ordy) { BRANCHES[k]=extdevelop(BRANCHES[k],2*nr); nr=ncols(BRANCHES[k][1]); PARAMETRIZATIONS[k]=param(BRANCHES[k],0); ordy=PARAMETRIZATIONS[k][2][2]; yt=PARAMETRIZATIONS[k][1][2]; ft=phi_t(derf); a=mindeg(ft); } } else { int ordf=ordx; if (ordx>ordy) { ordf=ordy; } while (a>ordf) { BRANCHES[k]=extdevelop(BRANCHES[k],2*nr); nr=ncols(BRANCHES[k][1]); PARAMETRIZATIONS[k]=param(BRANCHES[k],0); ordx=PARAMETRIZATIONS[k][2][1]; ordy=PARAMETRIZATIONS[k][2][2]; ordf=ordx; if (ordx>ordy) { ordf=ordy; } xt=PARAMETRIZATIONS[k][1][1]; yt=PARAMETRIZATIONS[k][1][2]; ft=phi_t(derf); a=mindeg(ft); } } } } Cq=a-b; setring b_ring; return(Cq); } /////////////////////////////////////////////////////////////////////////////// static proc max_D (intvec D1,intvec D2) { // computes the maximum of two divisors (intvec) int s1=size(D1); int s2=size(D2); int i; if (s1>s2) { for (i=1;i<=s2;i=i+1) { if (D2[i]>D1[i]) { D1[i]=D2[i]; } } for (i=s2+1;i<=s1;i=i+1) { if (D1[i]<0) { D1[i]=0; } } return(D1); } else { for (i=1;i<=s1;i=i+1) { if (D1[i]>D2[i]) { D2[i]=D1[i]; } } for (i=s1+1;i<=s2;i=i+1) { if (D2[i]<0) { D2[i]=0; } } return(D2); } } /////////////////////////////////////////////////////////////////////////////// static proc deg_D (intvec D,list PP) { // computes the degree of a divisor (intvec or list of integers) int i; int d=0; int s=size(D); for (i=1;i<=s;i=i+1) { d=d+D[i]*PP[i][1]; } return(d); } /////////////////////////////////////////////////////////////////////////////// // ============================================================================ // ******* MAIN PROCEDURES for the "preprocessing" of Brill-Noether ******** // ============================================================================ proc Adj_div (poly f,list #) "USAGE: Adj_div( f [,l] ); f a poly, [l a list] RETURN: list L with the computed data: @format L[1] a list of rings: L[1][1]=aff_r (affine), L[1][2]=Proj_R (projective), L[2] an intvec with 2 entries (degree, genus), L[3] a list of intvec (closed places), L[4] an intvec (conductor), L[5] a list of lists: L[5][d][1] a (local) ring over an extension of degree d, L[5][d][2] an intvec (degrees of base points of places of degree d) @end format NOTE: @code{Adj_div(f);} computes and stores the fundamental data of the plane curve defined by f as needed for AG codes. In the affine ring you can find the following data: @format poly CHI: affine equation of the curve, ideal Aff_SLocus: affine singular locus (std), list Inf_Points: points at infinity Inf_Points[1]: singular points Inf_Points[2]: non-singular points, list Aff_SPoints: affine singular points (if not empty). @end format In the projective ring you can find the projective equation CHI of the curve (poly). In the local rings L[5][d][1] you find: @format list POINTS: base points of the places of degree d, list LOC_EQS: local equations of the curve at the base points, list BRANCHES: Hamburger-Noether developments of the places, list PARAMETRIZATIONS: local parametrizations of the places, @end format Each entry of the list L[3] corresponds to one closed place (i.e., a place and all its conjugates) which is represented by an intvec of size two, the first entry is the degree of the place (in particular, it tells the local ring where to find the data describing one representative of the closed place), and the second one is the position of those data in the lists POINTS, etc., inside this local ring.@* In the intvec L[4] (conductor) the i-th entry corresponds to the i-th entry in the list of places L[3]. With no optional arguments, the conductor is computed by local invariants of the singularities; otherwise it is computed by the Dedekind formula. @* An affine point is represented by a list P where P[1] is std of a prime ideal and P[2] is an intvec containing the position of the places above P in the list of closed places L[3]. @* If the point is at infinity, P[1] is a homogeneous irreducible polynomial in two variables. If @code{printlevel>=0} additional comments are displayed (default: @code{printlevel=0}). WARNING: The parameter of the needed field extensions is called 'a'. Thus, there should be no global object named 'a' when executing Adj_div. KEYWORDS: Hamburger-Noether expansions; adjunction divisor SEE ALSO: closed_points, NSplaces EXAMPLE: example Adj_div; shows an example " { // computes the adjunction divisor and the genus of a (singular) plane curve // as a byproduct, it computes all the singular points with the corresponding // places and the genus of the curve // the adjunction divisor is stored in an intvec // also the non-singular places at infinity are computed // returns a list with all the computed data if (char(basering)==0) { ERROR("Base field not implemented"); } if (npars(basering)>0) { ERROR("Base field not implemented"); } if (defined(a)==1) { if ((typeof(a)=="int") or (typeof(a)=="intvec") or (typeof(a)=="intmat") or (typeof(a)=="string") or (typeof(a)=="proc") or (typeof(a)=="list")) { print("WARNING: There is an object named 'a' of the global type " + typeof(a)+"."); print("This will cause problems when " + "executing Adj_div, as 'a' is used for " + "the name of the parameter of the field extensions needed."); ERROR("Please rename or kill the object named 'a'"); } } intvec opgt=option(get); option(redSB); def Base_R=basering; list CURVE=curve(f); def aff_r=CURVE[1]; def Proj_R=CURVE[2]; int degX=CURVE[3]; int genusX=(degX-1)*(degX-2); genusX = genusX div 2; intvec iivv=degX,genusX; intvec Conductor; setring aff_r; dbprint(printlevel+1,"Computing affine singular points ... "); list Aff_SPoints=Aff_SL(Aff_SLocus); int s=size(Aff_SPoints); if (s>0) { export(Aff_SPoints); } dbprint(printlevel+1,"Computing all points at infinity ... "); list Inf_Points=inf_P(CHI); export(Inf_Points); list update_CURVE=list(); update_CURVE[1]=list(); update_CURVE[1][1]=aff_r; update_CURVE[1][2]=Proj_R; update_CURVE[2]=iivv; update_CURVE[3]=list(); update_CURVE[4]=Conductor; update_CURVE[5]=list(); int i; intvec pP=0,0,0; if (size(#)==0) { dbprint(printlevel+1,"Computing affine singular places ... "); if (s>0) { for (i=1;i<=s;i=i+1) { pP[3]=i; update_CURVE=place(pP,1,update_CURVE); } } dbprint(printlevel+1,"Computing singular places at infinity ... "); s=size(Inf_Points[1]); if (s>0) { pP[2]=1; for (i=1;i<=s;i=i+1) { pP[3]=i; update_CURVE=place(pP,1,update_CURVE); } } } else { dbprint(printlevel+1,"Computing affine singular places ... "); s=size(Aff_SPoints); if (s>0) { for (i=1;i<=s;i=i+1) { pP[3]=i; update_CURVE=place(pP,2,update_CURVE); } } dbprint(printlevel+1,"Computing singular places at infinity ... "); s=size(Inf_Points[1]); if (s>0) { pP[2]=1; for (i=1;i<=s;i=i+1) { pP[3]=i; update_CURVE=place(pP,2,update_CURVE); } } } dbprint(printlevel+1,"Computing non-singular places at infinity ... "); s=size(Inf_Points[2]); if (s>0) { pP[2]=2; for (i=1;i<=s;i=i+1) { pP[3]=i; update_CURVE=place(pP,0,update_CURVE); } } dbprint(printlevel+1,"Adjunction divisor computed successfully"); list Places=update_CURVE[3]; Conductor=update_CURVE[4]; genusX = genusX - (deg_D(Conductor,Places) div 2); update_CURVE[2][2]=genusX; setring Base_R; dbprint(printlevel+1," "); dbprint(printlevel+2,"The genus of the curve is "+string(genusX)); option(set,opgt); return(update_CURVE); } example { "EXAMPLE:"; echo = 2; int plevel=printlevel; printlevel=-1; ring s=2,(x,y),lp; list C=Adj_div(y9+y8+xy6+x2y3+y2+x3); def aff_R=C[1][1]; // the affine ring setring aff_R; listvar(aff_R); // data in the affine ring CHI; // affine equation of the curve Aff_SLocus; // ideal of the affine singular locus Aff_SPoints[1]; // 1st affine singular point: (1:1:1), no.1 Inf_Points[1]; // singular point(s) at infinity: (1:0:0), no.4 Inf_Points[2]; // list of non-singular points at infinity // pause("press RETURN"); def proj_R=C[1][2]; // the projective ring setring proj_R; CHI; // projective equation of the curve C[2][1]; // degree of the curve C[2][2]; // genus of the curve C[3]; // list of computed places C[4]; // adjunction divisor (all points are singular!) // pause("press RETURN"); // we look at the place(s) of degree 2 by changing to the ring C[5][2][1]; def S(2)=C[5][2][1]; setring S(2); POINTS; // base point(s) of place(s) of degree 2: (1:a:1) LOC_EQS; // local equation(s) PARAMETRIZATIONS; // parametrization(s) and exactness BRANCHES; // Hamburger-Noether development printlevel=plevel; } /////////////////////////////////////////////////////////////////////////////// proc NSplaces (intvec h,list CURVE) "USAGE: NSplaces( h, CURVE ), where h is an intvec and CURVE is a list RETURN: list L with updated data of CURVE after computing all non-singular affine closed places whose degrees are in the intvec h: @* @format in L[1][1]: (affine ring) lists Aff_Points(d) with affine non-singular (closed) points of degree d (if non-empty), in L[3]: the newly computed closed places are added, in L[5]: local rings created/updated to store (repres. of) new places. @end format See @ref{Adj_div} for a description of the entries in L. NOTE: The list_expression should be the output of the procedure Adj_div.@* Raising @code{printlevel}, additional comments are displayed (default: @code{printlevel=0}). WARNING: The parameter of the needed field extensions is called 'a'. Thus, there should be no global object named 'a' when executing NSplaces. SEE ALSO: closed_points, Adj_div EXAMPLE: example NSplaces; shows an example " { // computes all the non-singular affine (closed) places with fixed degrees // creates lists of points and the corresponding places // list CURVE must be the output of the procedure "Adj_div" // notice : if h==0 then nothing is done // warning : non-positive entries are forgotten if (defined(a)==1) { if ((typeof(a)=="int") or (typeof(a)=="intvec") or (typeof(a)=="intmat") or (typeof(a)=="string") or (typeof(a)=="proc") or (typeof(a)=="list")) { print("WARNING: There is an object named 'a' of the global type " + typeof(a)+"."); print("This will cause problems when " + "executing Adj_div, as 'a' is used for " + "the name of the parameter of the field extensions needed."); ERROR("Please rename or kill the object named 'a'"); } } if (h==0) { return(CURVE); } intvec opgt=option(get); option(redSB); def Base_R=basering; def aff_r=CURVE[1][1]; int M=size(h); list update_CURVE=CURVE; int i,j,l,s; setring aff_r; intvec pP=1,0,0; for (i=1;i<=M;i=i+1) { l=h[i]; if (l>0) { dbprint(printlevel+1,"Computing non-singular affine places of degree " +string(l)+" ... "); if (defined(Aff_Points(l))==0) { list Aff_Points(l)=closed_points_deg(CHI,l,Aff_SLocus); s=size(Aff_Points(l)); if (s>0) { export(Aff_Points(l)); pP[2]=l; for (j=1;j<=s;j=j+1) { dbprint(printlevel-voice-2,"Place No.\ "+string(j)); pP[3]=j; update_CURVE=place(pP,0,update_CURVE); } } } } } setring Base_R; option(set,opgt); return(update_CURVE); } example { "EXAMPLE:"; echo = 2; int plevel=printlevel; printlevel=-1; ring s=2,(x,y),lp; list C=Adj_div(x3y+y3+x); // The list of computed places: C[3]; // create places up to degree 4 list L=NSplaces(1..4,C); // The list of computed places is now: L[3]; // e.g., affine non-singular points of degree 4 : def aff_r=L[1][1]; setring aff_r; Aff_Points(4); // e.g., base point of the 1st place of degree 4 : def S(4)=L[5][4][1]; setring S(4); POINTS[1]; printlevel=plevel; } /////////////////////////////////////////////////////////////////////////////// // ** SPECIAL PROCEDURES FOR LINEAR ALGEBRA ** static proc Ker (matrix A) { // warning : "lp" ordering is necessary intvec opgt=option(get); option(redSB); matrix M=transpose(syz(A)); option(set,opgt); return(M); } /////////////////////////////////////////////////////////////////////////////// static proc get_NZsol (matrix A) { matrix sol=Ker(A); return(submat(sol,1..1,1..ncols(sol))); } /////////////////////////////////////////////////////////////////////////////// static proc supplement (matrix W,matrix V) "USAGE: supplement(W,V), where W,V are matrices of numbers such that the vector space generated by the rows of W is contained in that generated by the rows of V RETURN: matrix whose rows generate a supplementary vector space of W in V, or a zero row-matrix if == NOTE: W,V must be given with maximal rank " { // W and V represent independent sets of vectors and is assumed to be // contained in // computes matrix S whose rows are l.i. vectors s.t. union is a // basis of // careful : the size of all vectors is assumed to be the same but it is // not checked and neither the linear independence of the vectors is checked // the trivial case W=0 is not covered by this procedure (and thus V<>0) // if = then a zero row-matrix is returned // warning : option(redSB) must be set in advance int n1=nrows(W); int n2=nrows(V); int s=n2-n1; if (s==0) { int n=ncols(W); matrix HH[1][n]; return(HH); } matrix H=transpose(lift(transpose(V),transpose(W))); H=supplem(H); return(H*V); } /////////////////////////////////////////////////////////////////////////////// static proc supplem (matrix M) "USAGE: supplem(M), where M is a matrix of numbers with maximal rank RETURN: matrix whose rows generate a supplementary vector space of in k^n, where k is the base field and n is the number of columns SEE ALSO: supplement NOTE: The rank r is assumed to be 1=0 // exports ideal nFORMS(n) whose generators are ranged with lp order // in Proj_R and returns size(nFORMS(n)) // warning : it is supposed to be called inside Proj_R // if n<=0 then nFORMS(0) is "computed fast" ideal nFORMS(n); int N; if (n>0) { N=(n+1)*(n+2); N=N div 2; N=N+1; int i,j,k; for (i=0;i<=n;i=i+1) { for (j=0;j<=n-i;j=j+1) { k=k+1; nFORMS(n)[N-k]=x^i*y^j*z^(n-i-j); } } export(nFORMS(n)); } else { N=2; nFORMS(0)=1; export(nFORMS(0)); } return(N-1); } /////////////////////////////////////////////////////////////////////////////// static proc nmultiples (int n,int dgX,poly f) { // computes a basis of the space of forms of degree n which are multiple of // CHI // returns a matrix whose rows are the coordinates (related to nFORMS(n)) // of such a basis // warning : it is supposed to be called inside Proj_R // warning : nFORMS(n) is created in the way, together with nFORMS(n-degX) // warning : n must be greater or equal than the degree of the curve if (defined(nFORMS(n))==0) { dbprint(printlevel+1,string(nforms(n))); } int m=n-dgX; if (defined(nFORMS(m))==0) { int k=nforms(m); } else { int k=size(nFORMS(m)); } ideal nmults; int i; for (i=1;i<=k;i=i+1) { nmults[i]=f*nFORMS(m)[i]; } return(transpose(lift(nFORMS(n),nmults))); } /////////////////////////////////////////////////////////////////////////////// static proc interpolating_forms (intvec D,int n,list CURVE) { // computes a vector basis of the space of forms of degree n whose // intersection divisor with the curve is greater or equal than D>=0 // the procedure is supposed to be called inside the ring Proj_R and // assumes that the forms nFORMS(n) are previously computed // the output is a matrix whose rows are the coordinates in nFORMS(n) of // such a basis // remark : the support of D may contain "extra" places def BR=basering; def aff_r=CURVE[1][1]; int N=size(nFORMS(n)); matrix totalM[1][N]; int s=size(D); list Places=CURVE[3]; int NPls=size(Places); int i,j,k,kk,id,ip,RR,ordx,ordy,nr,NR; if (s<=NPls) { for (i=1;i<=s;i=i+1) { if (D[i]>0) { id=Places[i][1]; ip=Places[i][2]; RR=D[i]; def SS=CURVE[5][id][1]; setring SS; poly xt=PARAMETRIZATIONS[ip][1][1]; poly yt=PARAMETRIZATIONS[ip][1][2]; ordx=PARAMETRIZATIONS[ip][2][1]; ordy=PARAMETRIZATIONS[ip][2][2]; nr=ncols(BRANCHES[ip][1]); if ( ordx>-1 || ordy>-1 ) { while ( ( RR>=ordx && ordx>-1 ) || ( RR>=ordy && ordy>-1 ) ) { BRANCHES[ip]=extdevelop(BRANCHES[ip],2*nr); nr=ncols(BRANCHES[ip][1]); PARAMETRIZATIONS[ip]=param(BRANCHES[ip],0); xt=PARAMETRIZATIONS[ip][1][1]; yt=PARAMETRIZATIONS[ip][1][2]; ordx=PARAMETRIZATIONS[ip][2][1]; ordy=PARAMETRIZATIONS[ip][2][2]; } } if (POINTS[ip][3]==number(1)) { number A=POINTS[ip][1]; number B=POINTS[ip][2]; map Mt=BR,A+xt,B+yt,1; kill A,B; } else { if (POINTS[ip][2]==number(1)) { number A=POINTS[ip][1]; map Mt=BR,A+xt,1,yt; kill A; } else { map Mt=BR,1,xt,yt; } } ideal nFORMS(n)=Mt(nFORMS(n)); // rewrite properly the above conditions to obtain the local equations matrix partM[RR][N]; matrix auxMC=coeffs(nFORMS(n),t); NR=nrows(auxMC); if (RR<=NR) { for (j=1;j<=RR;j=j+1) { for (k=1;k<=N;k=k+1) { partM[j,k]=number(auxMC[j,k]); } } } else { for (j=1;j<=NR;j=j+1) { for (k=1;k<=N;k=k+1) { partM[j,k]=number(auxMC[j,k]); } } for (j=NR+1;j<=RR;j=j+1) { for (k=1;k<=N;k=k+1) { partM[j,k]=number(0); } } } matrix localM=partM; matrix conjM=partM; for (j=2;j<=id;j=j+1) { conjM=Frobenius(conjM,1); localM=transpose(concat(transpose(localM),transpose(conjM))); } localM=gauss_row(localM); setring BR; totalM=transpose(concat(transpose(totalM),transpose(imap(SS,localM)))); totalM=transpose(compress(transpose(totalM))); setring SS; kill xt,yt,Mt,nFORMS(n),partM,auxMC,conjM,localM; setring BR; kill SS; } } } else { // distinguish between "standard" places and "extra" places for (i=1;i<=NPls;i=i+1) { if (D[i]>0) { id=Places[i][1]; ip=Places[i][2]; RR=D[i]; def SS=CURVE[5][id][1]; setring SS; poly xt=PARAMETRIZATIONS[ip][1][1]; poly yt=PARAMETRIZATIONS[ip][1][2]; ordx=PARAMETRIZATIONS[ip][2][1]; ordy=PARAMETRIZATIONS[ip][2][2]; nr=ncols(BRANCHES[ip][1]); if ( ordx>-1 || ordy>-1 ) { while ( ( RR>=ordx && ordx>-1 ) || ( RR>=ordy && ordy>-1 ) ) { BRANCHES[ip]=extdevelop(BRANCHES[ip],2*nr); nr=ncols(BRANCHES[ip][1]); PARAMETRIZATIONS[ip]=param(BRANCHES[ip],0); xt=PARAMETRIZATIONS[ip][1][1]; yt=PARAMETRIZATIONS[ip][1][2]; ordx=PARAMETRIZATIONS[ip][2][1]; ordy=PARAMETRIZATIONS[ip][2][2]; } } if (POINTS[ip][3]==number(1)) { number A=POINTS[ip][1]; number B=POINTS[ip][2]; map Mt=BR,A+xt,B+yt,1; kill A,B; } else { if (POINTS[ip][2]==number(1)) { number A=POINTS[ip][1]; map Mt=BR,A+xt,1,yt; kill A; } else { map Mt=BR,1,xt,yt; } } ideal nFORMS(n)=Mt(nFORMS(n)); // rewrite properly the above conditions to obtain the local equations matrix partM[RR][N]; matrix auxMC=coeffs(nFORMS(n),t); NR=nrows(auxMC); if (RR<=NR) { for (j=1;j<=RR;j=j+1) { for (k=1;k<=N;k=k+1) { partM[j,k]=number(auxMC[j,k]); } } } else { for (j=1;j<=NR;j=j+1) { for (k=1;k<=N;k=k+1) { partM[j,k]=number(auxMC[j,k]); } } for (j=NR+1;j<=RR;j=j+1) { for (k=1;k<=N;k=k+1) { partM[j,k]=number(0); } } } matrix localM=partM; matrix conjM=partM; for (j=2;j<=id;j=j+1) { conjM=Frobenius(conjM,1); localM=transpose(concat(transpose(localM),transpose(conjM))); } localM=gauss_row(localM); setring BR; totalM=transpose(concat(transpose(totalM),transpose(imap(SS,localM)))); totalM=transpose(compress(transpose(totalM))); setring SS; kill xt,yt,Mt,nFORMS(n),partM,auxMC,conjM,localM; setring BR; kill SS; } } k=s-NPls; int l; for (i=1;i<=k;i=i+1) { // in this case D[NPls+i]>0 is assumed to be true during the // Brill-Noether algorithm RR=D[NPls+i]; setring aff_r; def SS=@EXTRA@[2][i]; def extra_dgs=@EXTRA@[3]; setring SS; poly xt=PARAMETRIZATION[1][1]; poly yt=PARAMETRIZATION[1][2]; ordx=PARAMETRIZATION[2][1]; ordy=PARAMETRIZATION[2][2]; nr=ncols(BRANCH[1]); if ( ordx>-1 || ordy>-1 ) { while ( ( RR>=ordx && ordx>-1 ) || ( RR>=ordy && ordy>-1 ) ) { BRANCH=extdevelop(BRANCH,2*nr); nr=ncols(BRANCH[1]); PARAMETRIZATION=param(BRANCH,0); xt=PARAMETRIZATION[1][1]; yt=PARAMETRIZATION[1][2]; ordx=PARAMETRIZATION[2][1]; ordy=PARAMETRIZATION[2][2]; } } number A=POINT[1]; number B=POINT[2]; map Mt=BR,A+xt,B+yt,1; kill A,B; ideal nFORMS(n)=Mt(nFORMS(n)); // rewrite properly the above conditions to obtain the local equations matrix partM[RR][N]; matrix auxMC=coeffs(nFORMS(n),t); NR=nrows(auxMC); if (RR<=NR) { for (j=1;j<=RR;j=j+1) { for (kk=1;kk<=N;kk=kk+1) { partM[j,kk]=number(auxMC[j,kk]); } } } else { for (j=1;j<=NR;j=j+1) { for (kk=1;kk<=N;kk=kk+1) { partM[j,kk]=number(auxMC[j,kk]); } } for (j=NR+1;j<=RR;j=j+1) { for (kk=1;kk<=N;kk=kk+1) { partM[j,kk]=number(0); } } } matrix localM=partM; matrix conjM=partM; l=extra_dgs[i]; for (j=2;j<=l;j=j+1) { conjM=Frobenius(conjM,1); localM=transpose(concat(transpose(localM),transpose(conjM))); } localM=gauss_row(localM); setring BR; totalM=transpose(concat(transpose(totalM),transpose(imap(SS,localM)))); totalM=transpose(compress(transpose(totalM))); setring SS; kill xt,yt,Mt,nFORMS(n),partM,auxMC,conjM,localM; setring BR; kill SS; } } return(Ker(totalM)); } /////////////////////////////////////////////////////////////////////////////// static proc local_IN (poly h,int m) { // computes the intersection number of h and the curve CHI at a certain place // returns a list with the intersection number and the "leading coefficient" // the procedure must be called inside a local ring, h must be a local // equation with respect to the desired place, and m indicates the // number of place inside that local ring, containing lists // POINT(S)/BRANCH(ES)/PARAMETRIZATION(S) when m=0 an "extra place" is // considered def BR=basering; if (m>0) { int nr=ncols(BRANCHES[m][1]); poly xt=PARAMETRIZATIONS[m][1][1]; poly yt=PARAMETRIZATIONS[m][1][2]; int ordx=PARAMETRIZATIONS[m][2][1]; int ordy=PARAMETRIZATIONS[m][2][2]; map phi=BR,xt,yt,1; poly ht=phi(h); int inum=mindeg(ht); if ( ordx>-1 || ordy>-1 ) { while (((inum>ordx||inum==-1) && ordx>-1) || ((inum>ordy||inum==-1) && ordy>-1)) { BRANCHES[m]=extdevelop(BRANCHES[m],2*nr); nr=ncols(BRANCHES[m][1]); PARAMETRIZATIONS[m]=param(BRANCHES[m],0); xt=PARAMETRIZATIONS[m][1][1]; yt=PARAMETRIZATIONS[m][1][2]; ordx=PARAMETRIZATIONS[m][2][1]; ordy=PARAMETRIZATIONS[m][2][2]; phi=BR,xt,yt,1; ht=phi(h); inum=mindeg(ht); } } } else { int nr=ncols(BRANCH[1]); poly xt=PARAMETRIZATION[1][1]; poly yt=PARAMETRIZATION[1][2]; int ordx=PARAMETRIZATION[2][1]; int ordy=PARAMETRIZATION[2][2]; map phi=basering,xt,yt,1; poly ht=phi(h); int inum=mindeg(ht); if ( ordx>-1 || ordy>-1 ) { while (((inum>ordx||inum==-1) && ordx>-1) || ((inum>ordy||inum==-1) && ordy>-1)) { BRANCH=extdevelop(BRANCH,2*nr); nr=ncols(BRANCH[1]); PARAMETRIZATION=param(BRANCH,0); xt=PARAMETRIZATION[1][1]; yt=PARAMETRIZATION[1][2]; ordx=PARAMETRIZATION[2][1]; ordy=PARAMETRIZATION[2][2]; phi=BR,xt,yt,1; ht=phi(h); inum=mindeg(ht); } } } list answer=list(); answer[1]=inum; number AA=number(coeffs(ht,t)[inum+1,1]); answer[2]=AA; return(answer); } /////////////////////////////////////////////////////////////////////////////// static proc extra_place (ideal P) { // computes the "rational" place which is defined over a (closed) "extra" // point // an "extra" point will be necessarily affine, non-singular and non-rational // creates : a specific local ring to deal with the (unique) place above it // returns : list with the above local ring and the degree of the point/place // warning : the procedure must be called inside the affine ring aff_r def base_r=basering; int ext=deg(P[1]); poly aux=subst(P[2],y,1); ext=ext*deg(aux); // P is assumed to be a std. resp. "(x,y),lp" and thus P[1] depends only // on "y" if (deg(P[1])==1) { // the point is non-rational but the second component needs no field // extension number B=-number(subst(P[1],y,0)); poly aux2=subst(P[2],y,B); // careful : the parameter will be called "a" anyway ring ES=(char(basering),a),(x,y,t),ls; map psi=base_r,a,0; minpoly=number(psi(aux2)); if (defined (psi)) { kill psi; } number A=a; number B=imap(base_r,B); } else { if (deg(subst(P[2],y,1))==1) { // the point is non-rational but the needed minpoly is just P[1] // careful : the parameter will be called "a" anyway poly P1=P[1]; poly P2=P[2]; ring ES=(char(basering),a),(x,y,t),ls; map psi=base_r,0,a; minpoly=number(psi(P1)); if (defined (psi)) { kill psi; } poly aux1=imap(base_r,P2); poly aux2=subst(aux1,y,a); number A=-number(subst(aux2,x,0)); number B=a; } else { // this is the most complicated case of non-rational point poly P1=P[1]; poly P2=P[2]; int p=char(basering); int Q=p^ext; ring aux_r=(Q,a),(x,y,t),ls; string minpoly_string=string(minpoly); ring ES=(char(basering),a),(x,y,t),ls; execute("minpoly="+minpoly_string+";"); poly P_1=imap(base_r,P1); poly P_2=imap(base_r,P2); ideal factors1=factorize(P_1,1); number B=-number(subst(factors1[1],y,0)); poly P_0=subst(P_2,y,B); ideal factors2=factorize(P_0,1); number A=-number(subst(factors2[1],x,0)); kill aux_r; } } list POINT=list(); POINT[1]=A; POINT[2]=B; export(POINT); map phi=base_r,x+A,y+B; poly LOC_EQ=phi(CHI); kill A,B,phi; list LLL=hnexpansion(LOC_EQ,"ess"); if (typeof(LLL[1])=="ring") { def altring=basering; def HNEring = LLL[1]; setring HNEring; def L@HNE = hne[1]; kill hne; export(L@HNE); int m=nrows(L@HNE[1]); int n=ncols(L@HNE[1]); intvec Li2=L@HNE[2]; int Li3=L@HNE[3]; setring ES; string newa=subfield(HNEring); poly paux=importdatum(HNEring,"L@HNE[4]",newa); matrix Maux[m][n]; int i,j; for (i=1;i<=m;i=i+1) { for (j=1;j<=n;j=j+1) { Maux[i,j]=importdatum(HNEring,"L@HNE[1]["+string(i)+","+ string(j)+"]",newa); } } } else { def L@HNE=LLL[1][1]; matrix Maux=L@HNE[1]; intvec Li2=L@HNE[2]; int Li3=L@HNE[3]; poly paux=L@HNE[4]; def HNEring=basering; setring HNEring; } kill LLL; list BRANCH=list(); BRANCH[1]=Maux; BRANCH[2]=Li2; BRANCH[3]=Li3; BRANCH[4]=paux; export(BRANCH); list PARAMETRIZATION=param(BRANCH,0); export(PARAMETRIZATION); kill HNEring; setring base_r; list answer=list(); answer[1]=ES; answer[2]=ext; kill ES; return(answer); } /////////////////////////////////////////////////////////////////////////////// static proc intersection_div (poly H,list CURVE) "USAGE: intersection_div(H,CURVE), where H is a homogeneous polynomial in ring Proj_R=p,(x,y,z),lp and CURVE is the list of data for the given curve CREATE: new places which had not been computed in advance if necessary those places are stored each one in a local ring where you find lists POINT,BRANCH,PARAMETRIZATION for the place living in that ring; the degree of the point/place in such a ring is stored in an intvec, and the base points in the remaining list Everything is exported in a list @EXTRA@ inside the ring aff_r=CURVE[1][1] and returned with the updated CURVE RETURN: list with the intersection divisor (intvec) between the underlying curve and H=0, and the list CURVE updated SEE ALSO: Adj_div, NSplaces, closed_points NOTE: The procedure must be called from the ring Proj_R=CURVE[1][2] (projective). If @EXTRA@ already exists, the new places are added to the previous data. " { // computes the intersection divisor of H and the curve CHI // returns a list with (possibly) "extra places" and it must be called // inside Proj_R // in case of extra places, some local rings ES(1) ... ES(m) are created // together with an integer list "extra_dgs" containing the degrees of // those places intvec opgt=option(get); option(redSB); intvec interdiv; def BRing=basering; int Tz1=deg(H); list Places=CURVE[3]; int N=size(Places); def aff_r=CURVE[1][1]; setring aff_r; if (defined(@EXTRA@)==0) { list @EXTRA@=list(); list EP=list(); list ES=list(); list extra_dgs=list(); } else { list EP=@EXTRA@[1]; list ES=@EXTRA@[2]; list extra_dgs=@EXTRA@[3]; } int NN=size(extra_dgs); int counterEPl=0; setring BRing; poly h=subst(H,z,1); int Tz2=deg(h); int Tz3=Tz1-Tz2; int i,j,k,l,m,n,s,np,NP,I_N; if (Tz3==0) { // if this still does not work -> try always with ALL points in // Inf_Points !!!! poly Hinf=subst(H,z,0); setring aff_r; // compute the points at infinity of H and see which of them are in // Inf_Points poly h=imap(BRing,h); poly hinf=imap(BRing,Hinf); ideal pinf=factorize(hinf,1); list TIP=Inf_Points[1]+Inf_Points[2]; s=size(TIP); NP=size(pinf); for (i=1;i<=NP;i=i+1) { for (j=1;j<=s;j=j+1) { if (pinf[i]==TIP[j][1]) { np=size(TIP[j][2]); for (k=1;k<=np;k=k+1) { n=TIP[j][2][k]; l=Places[n][1]; m=Places[n][2]; def SS=CURVE[5][l][1]; setring SS; // local equation h of H if (POINTS[m][2]==number(1)) { number A=POINTS[m][1]; map psi=BRing,x+A,1,y; kill A; } else { map psi=BRing,1,x,y; } poly h=psi(H); I_N=local_IN(h,m)[1]; interdiv[n]=I_N; kill h,psi; setring aff_r; kill SS; } break; } } } kill hinf,pinf; } else { // H is a multiple of z and hence all the points in Inf_Points intersect // with H setring aff_r; poly h=imap(BRing,h); list TIP=Inf_Points[1]+Inf_Points[2]; s=size(TIP); for (j=1;j<=s;j=j+1) { np=size(TIP[j][2]); for (k=1;k<=np;k=k+1) { n=TIP[j][2][k]; l=Places[n][1]; m=Places[n][2]; def SS=CURVE[5][l][1]; setring SS; // local equation h of H if (POINTS[m][2]==number(1)) { number A=POINTS[m][1]; map psi=BRing,x+A,1,y; kill A; } else { map psi=BRing,1,x,y; } poly h=psi(H); I_N=local_IN(h,m)[1]; interdiv[n]=I_N; kill h,psi; setring aff_r; kill SS; } } } // compute common affine points of H and CHI ideal CAL=h,CHI; CAL=std(CAL); if (CAL<>1) { list TAP=list(); TAP=closed_points(CAL); NP=size(TAP); list auxP=list(); int dP; for (i=1;i<=NP;i=i+1) { if (belongs(TAP[i],Aff_SLocus)==1) { // search the point in the list Aff_SPoints j=isInLP(TAP[i],Aff_SPoints); np=size(Aff_SPoints[j][2]); for (k=1;k<=np;k=k+1) { n=Aff_SPoints[j][2][k]; l=Places[n][1]; m=Places[n][2]; def SS=CURVE[5][l][1]; setring SS; // local equation h of H number A=POINTS[m][1]; number B=POINTS[m][2]; map psi=BRing,x+A,y+B,1; poly h=psi(H); I_N=local_IN(h,m)[1]; interdiv[n]=I_N; kill A,B,h,psi; setring aff_r; kill SS; } } else { auxP=list(); auxP[1]=TAP[i]; dP=degree_P(auxP); if (defined(Aff_Points(dP))<>0) { // search the point in the list Aff_Points(dP) j=isInLP(TAP[i],Aff_Points(dP)); n=Aff_Points(dP)[j][2][1]; l=Places[n][1]; m=Places[n][2]; def SS=CURVE[5][l][1]; setring SS; // local equation h of H number A=POINTS[m][1]; number B=POINTS[m][2]; map psi=BRing,x+A,y+B,1; poly h=psi(H); I_N=local_IN(h,m)[1]; interdiv[n]=I_N; kill A,B,h,psi; setring aff_r; kill SS; } else { // previously check if it is an existing "extra place" j=isInLP(TAP[i],EP); if (j>0) { def SS=ES[j]; setring SS; // local equation h of H number A=POINT[1]; number B=POINT[2]; map psi=BRing,x+A,y+B,1; poly h=psi(H); I_N=local_IN(h,0)[1]; interdiv[N+j]=I_N; setring aff_r; kill SS; } else { // then we must create a new "extra place" counterEPl=counterEPl+1; list EXTRA_PLACE=extra_place(TAP[i]); def SS=EXTRA_PLACE[1]; ES[NN+counterEPl]=SS; extra_dgs[NN+counterEPl]=EXTRA_PLACE[2]; EP[NN+counterEPl]=list(); EP[NN+counterEPl][1]=TAP[i]; EP[NN+counterEPl][2]=0; setring SS; // local equation h of H number A=POINT[1]; number B=POINT[2]; map psi=BRing,x+A,y+B,1; poly h=psi(H); I_N=local_IN(h,0)[1]; kill A,B,h,psi; interdiv[N+NN+counterEPl]=I_N; setring aff_r; kill SS; } } } } kill TAP,auxP; } kill h,CAL,TIP; @EXTRA@[1]=EP; @EXTRA@[2]=ES; @EXTRA@[3]=extra_dgs; kill EP; list update_CURVE=CURVE; if (size(extra_dgs)>0) { export(@EXTRA@); update_CURVE[1][1]=basering; } else { kill @EXTRA@; } setring BRing; kill h; kill aff_r; list answer=list(); answer[1]=interdiv; answer[2]=update_CURVE; option(set,opgt); return(answer); } /////////////////////////////////////////////////////////////////////////////// static proc local_eq (poly H,def SS,int m) { // computes a local equation of polynomial H in the ring SS related to the place // "m" // list POINT/POINTS is searched depending on wether m=0 or m>0 respectively // warning : the procedure must be called from ring "Proj_R" and returns a // string def BRing=basering; setring SS; if (m>0) { if (POINTS[m][3]==number(1)) { number A=POINTS[m][1]; number B=POINTS[m][2]; map psi=BRing,x+A,y+B,1; } else { if (POINTS[m][2]==number(1)) { number A=POINTS[m][1]; map psi=BRing,x+A,1,y; } else { map psi=BRing,1,x,y; } } } else { number A=POINT[1]; number B=POINT[2]; map psi=BRing,x+A,y+B,1; } poly h=psi(H); string str_h=string(h); setring BRing; return(str_h); } /////////////////////////////////////////////////////////////////////////////// static proc min_wt_rmat (matrix M) { // finds the row of M with minimum non-zero entries, i.e. minimum // "Hamming-weight" int m=nrows(M); int n=ncols(M); int i,j; int Hwt=0; for (j=1;j<=n;j=j+1) { if (M[1,j]<>0) { Hwt=Hwt+1; } } int minHwt=Hwt; int k=1; for (i=2;i<=m;i=i+1) { Hwt=0; for (j=1;j<=n;j=j+1) { if (M[i,j]<>0) { Hwt=Hwt+1; } } if (Hwt0) { kill @EXTRA@; } setring BRing; update_CURVE[1][1]=aux_RING; kill aux_RING; matrix B0=supplement(W,V2); if (Hamming_wt(B0)==0) { return(list()); } int ld=nrows(B0); list Bres=list(); ideal HH; poly H; for (j=1;j<=ld;j=j+1) { H=0; for (i=1;i<=N;i=i+1) { H=H+(B0[j,i]*nFORMS(n)[i]); } HH=H,Ho; Bres[j]=simplifyRF(HH); } kill nFORMS(n); dbprint(printlevel+1," "); dbprint(printlevel+2,"Vector basis successfully computed "); dbprint(printlevel+1," "); return(Bres); } example { "EXAMPLE:"; echo = 2; int plevel=printlevel; printlevel=-1; ring s=2,(x,y),lp; list C=Adj_div(x3y+y3+x); C=NSplaces(1..4,C); // the first 3 Places in C[3] are of degree 1. // we define the rational divisor G = 4*C[3][1]+4*C[3][3] (of degree 8): intvec G=4,0,4; def R=C[1][2]; setring R; list LG=BrillNoether(G,C); // here is the vector basis of L(G): LG; printlevel=plevel; } /////////////////////////////////////////////////////////////////////////////// // *** procedures for dealing with "RATIONAL FUNCTIONS" over a plane curve *** // a rational function F may be given by (homogeneous) ideal or (affine) poly // (or number) static proc polytoRF (F) { // converts a polynomial (or number) into a "rational function" of type "ideal" // warning : it must be called inside "R" and the polynomial is expected to be affine ideal RF; RF[1]=homog(F,z); RF[2]=z^(deg(F)); return(RF); } /////////////////////////////////////////////////////////////////////////////// static proc simplifyRF (ideal F) { // simplifies a rational function f/g extracting the gcd(f,g) // maybe add a "restriction" to the curve "CHI" but it is not easy to // programm poly auxp=gcd(F[1],F[2]); return(ideal(division(F,auxp)[1])); } /////////////////////////////////////////////////////////////////////////////// static proc sumRF (def F,def G) { // sum of two "rational functions" F,G given by either a pair // numerator/denominator or a poly if ( typeof(F)=="ideal" && typeof(G)=="ideal" ) { ideal FG; FG[1]=F[1]*G[2]+F[2]*G[1]; FG[2]=F[2]*G[2]; return(simplifyRF(FG)); } else { if (typeof(F)=="ideal") { ideal GG=polytoRF(G); ideal FG; FG[1]=F[1]*GG[2]+F[2]*GG[1]; FG[2]=F[2]*GG[2]; return(simplifyRF(FG)); } else { if (typeof(G)=="ideal") { ideal FF=polytoRF(F); ideal FG; FG[1]=FF[1]*G[2]+FF[2]*G[1]; FG[2]=FF[2]*G[2]; return(simplifyRF(FG)); } else { return(F+G); } } } } /////////////////////////////////////////////////////////////////////////////// static proc negRF (def F) { // returns -F as rational function if (typeof(F)=="ideal") { ideal FF=F; FF[1]=-F[1]; return(FF); } else { return(-F); } } /////////////////////////////////////////////////////////////////////////////// static proc escprodRF (def l,def F) { // computes l*F as rational function // l should be either a number or a polynomial of degree zero if (typeof(F)=="ideal") { ideal lF=F; lF[1]=l*F[1]; return(lF); } else { return(l*F); } } /////////////////////////////////////////////////////////////////////////////// // ******** procedures to compute Weierstrass semigroups ******** static proc orderRF (ideal F,def SS,int m) "USAGE: orderRF(F,SS,m); F an ideal, SS a ring and m an integer RETURN: list with the order (int) and the leading coefficient (number) NOTE: F represents a rational function, thus the procedure must be called from global ring R or R(d). SS contains the name of a local ring where rational places are stored, and then we take that which is in position m in the corresponding lists of data. The order of F at the place given by SS,m is returned together with the coefficient of minimum degree in the corresponding power series. " { // computes the order of a rational function F at a RATIONAL place given by // a local ring SS and a position "m" inside SS // warning : the procedure must be called from global projective ring "R" or // "R(i)" // returns a list with the order (int) and the "leading coefficient" (number) def BR=basering; poly f=F[1]; string sf=local_eq(f,SS,m); poly g=F[2]; string sg=local_eq(g,SS,m); setring SS; execute("poly ff="+sf+";"); execute("poly gg="+sg+";"); list o1=local_IN(ff,m); list o2=local_IN(gg,m); int oo=o1[1]-o2[1]; number lc=o1[2]/o2[2]; setring BR; number LC=number(imap(SS,lc)); return(list(oo,LC)); } /////////////////////////////////////////////////////////////////////////////// proc Weierstrass (int P,int m,list CURVE) "USAGE: Weierstrass( i, m, CURVE ); i,m integers and CURVE a list RETURN: list WS of two lists: @format WS[1] list of integers (Weierstr. semigroup of the curve at place i up to m) WS[2] list of ideals (the associated rational functions) @end format NOTE: The procedure must be called from the ring CURVE[1][2], where CURVE is the output of the procedure @code{NSplaces}. @* i represents the place CURVE[3][i]. @* Rational functions are represented by numerator/denominator in form of ideals with two homogeneous generators. WARNING: The place must be rational, i.e., necessarily CURVE[3][i][1]=1. @* SEE ALSO: Adj_div, NSplaces, BrillNoether EXAMPLE: example Weierstrass; shows an example " { // computes the Weierstrass semigroup at a RATIONAL place P up to a bound "m" // together with the functions achieving each value up to m, via // Brill-Noether // returns 2 lists : the first consists of all the poles up to m in // increasing order and the second consists of the corresponging rational // functions list Places=CURVE[3]; intvec pl=Places[P]; int dP=pl[1]; int nP=pl[2]; if (dP<>1) { ERROR("the given place is not defined over the prime field"); } if (m<=0) { if (m==0) { list semig=list(); int auxint=0; semig[1]=auxint; list funcs=list(); ideal auxF; auxF[1]=1; auxF[2]=1; funcs[1]=auxF; return(list(semig,funcs)); } else { ERROR("second argument must be non-negative"); } } int auxint=0; ideal auxF; auxF[1]=1; auxF[2]=1; // Brill-Noether algorithm intvec mP; mP[P]=m; list LmP=BrillNoether(mP,CURVE); int lmP=size(LmP); if (lmP==1) { list semig=list(); semig[1]=auxint; list funcs=list(); funcs[1]=auxF; return(list(semig,funcs)); } def SS=CURVE[5][dP][1]; list ordLmP=list(); list polLmP=list(); list sortpol=list(); int maxpol; int i,j,k; for (i=1;i<=lmP-1;i=i+1) { for (j=1;j<=lmP-i+1;j=j+1) { ordLmP[j]=orderRF(LmP[j],SS,nP); polLmP[j]=-ordLmP[j][1]; } sortpol=sort(polLmP); polLmP=sortpol[1]; maxpol=polLmP[lmP-i+1]; LmP=permute_L(LmP,sortpol[2]); ordLmP=permute_L(ordLmP,sortpol[2]); // triangulate LmP for (k=1;k<=lmP-i;k=k+1) { if (polLmP[lmP-i+1-k]==maxpol) { LmP[lmP-i+1-k]=sumRF(LmP[lmP-i+1-k],negRF(escprodRF( ordLmP[lmP-i+1-k][2]/ordLmP[lmP-i+1][2],LmP[lmP-i+1]))); } else { break; } } } polLmP[1]=auxint; LmP[1]=auxF; return(list(polLmP,LmP)); } example { "EXAMPLE:"; echo = 2; int plevel=printlevel; printlevel=-1; ring s=2,(x,y),lp; list C=Adj_div(x3y+y3+x); C=NSplaces(1..4,C); def R=C[1][2]; setring R; // Place C[3][1] has degree 1 (i.e it is rational); list WS=Weierstrass(1,7,C); // the first part of the list is the Weierstrass semigroup up to 7 : WS[1]; // and the second part are the corresponding functions : WS[2]; printlevel=plevel; } /////////////////////////////////////////////////////////////////////////////// // axiliary procedure for permuting a list or intvec proc permute_L (def L,def P) "USAGE: permute_L( L, P ); L,P either intvecs or lists RETURN: list obtained from L by applying the permutation given by P. NOTE: If P is a list, all entries must be integers. SEE ALSO: sys_code, AGcode_Omega, prepSV EXAMPLE: example permute_L; shows an example " { // permutes the list L according to the permutation P (both intvecs or // lists of integers) int s=size(L); int n=size(P); int i; if (s0) { return(number(0)); } else { ERROR("the function is not well-defined at the given place"); } } } /////////////////////////////////////////////////////////////////////////////// // // ******** procedures for constructing AG codes ******** // /////////////////////////////////////////////////////////////////////////////// static proc gen_mat (list LF,intvec LP,def RP) "USAGE: gen_mat(LF,LP,RP); LF list of rational functions, LP intvec of rational places and RP a local ring RETURN: a generator matrix of the evaluation code given by LF and LP SEE ALSO: extcurve KEYWORDS: evaluation codes NOTE: Rational places are searched in local ring RP The procedure must be called from R or R(d) fromlist CURVE after having executed extcurve(d,CURVE) " { // computes a generator matrix (with numbers) of the evaluation code given // by a list of rational functions LF and a list of RATIONAL places LP int m=size(LF); int n=size(LP); matrix GM[m][n]; int i,j; for (i=1;i<=m;i=i+1) { for (j=1;j<=n;j=j+1) { GM[i,j]=evalRF(LF[i],RP,LP[j]); } } return(GM); } /////////////////////////////////////////////////////////////////////////////// proc dual_code (matrix G) "USAGE: dual_code(G); G a matrix of numbers RETURN: a generator matrix of the dual code generated by G NOTE: The input should be a matrix G of numbers. @* The output is also a parity check matrix for the code defined by G KEYWORDS: linear code, dual EXAMPLE: example dual_code; shows an example " { // computes the dual code of C given by a generator matrix G // i.e. computes a parity-check matrix H of C // conversely : computes also G if H is given return(Ker(G)); } example { "EXAMPLE:"; echo = 2; ring s=2,T,lp; // here is the Hamming code of length 7 and dimension 3 matrix G[3][7]=1,0,1,0,1,0,1,0,1,1,0,0,1,1,0,0,0,1,1,1,1; print(G); matrix H=dual_code(G); print(H); } /////////////////////////////////////////////////////////////////////////////// // ====================================================================== // *********** initial test for disjointness *************** // ====================================================================== static proc disj_divs (intvec H,intvec P,list EC) { int s1=size(H); int s2=size(P); list PLACES=EC[3]; def BRing=basering; def auxR=EC[1][5]; setring auxR; int s=res_deg(); setring BRing; kill auxR; int i,j,k,d,l,N,M; intvec auxIV,iw; for (i=1;i<=s;i=i+1) { if ( (s mod i) == 0 ) { if (typeof(EC[5][i])=="list") { def auxR=EC[5][i][1]; setring auxR; auxIV[i]=size(POINTS); setring BRing; kill auxR; } else { auxIV[i]=0; } } else { auxIV[i]=0; } } for (i=1;i<=s1;i=i+1) { if (H[i]<>0) { iw=PLACES[i]; d=iw[1]; if ( (s mod d) == 0 ) { l=iw[2]; // check that this place(s) is/are not in sup(D) if (d==1) { for (j=1;j<=s2;j=j+1) { if (l==P[j]) { return(0); } } } else { N=0; for (j=1;j1) { def R=EC[1][2]; setring R; list LG=BrillNoether(G,EC); setring BR; list LG=imap(R,LG); setring R; kill LG; setring BR; kill R; } else { list LG=BrillNoether(G,EC); } def RP=EC[1][5]; matrix M=gen_mat(LG,D,RP); kill LG; return(M); } example { "EXAMPLE:"; echo = 2; int plevel=printlevel; printlevel=-1; ring s=2,(x,y),lp; list HC=Adj_div(x3+y2+y); HC=NSplaces(1..2,HC); HC=extcurve(2,HC); def ER=HC[1][4]; setring ER; intvec G=5; // the rational divisor G = 5*HC[3][1] intvec D=2..9; // D = sum of the rational places no. 2..9 over F_4 // let us construct the corresponding evaluation AG code : matrix C=AGcode_L(G,D,HC); // here is a linear code of type [8,5,>=3] over F_4 print(C); printlevel=plevel; } /////////////////////////////////////////////////////////////////////////////// proc AGcode_Omega (intvec G,intvec D,list EC) "USAGE: AGcode_Omega( G, D, EC ); G,D intvec, EC a list RETURN: a generator matrix for the residual AG code defined by the divisors G and D. NOTE: The procedure must be called within the ring EC[1][4], where EC is the output of @code{extcurve(d)} (or within the ring EC[1][2] if d=1). @* The entry i in the intvec D refers to the i-th rational place in EC[1][5] (i.e., to POINTS[i], etc., see @ref{extcurve}).@* The intvec G represents a rational divisor (see @ref{BrillNoether} for more details).@* The code computes the residues of a vector space basis of @math{\Omega(G-D)} at the rational places given by D. WARNINGS: G should satisfy @math{ 2*genus-2 < deg(G) < size(D) }, which is not checked by the algorithm. G and D should have disjoint supports (checked by the algorithm). SEE ALSO: Adj_div, BrillNoether, extcurve, AGcode_L EXAMPLE: example AGcode_Omega; shows an example " { // returns a generator matrix for the residual AG code given by G and D // G must be a divisor defined over the prime field and D an intvec or // "rational places" // it must be called inside R or R(d) and requires previously "extcurve(d)" return(dual_code(AGcode_L(G,D,EC))); } example { "EXAMPLE:"; echo = 2; int plevel=printlevel; printlevel=-1; ring s=2,(x,y),lp; list HC=Adj_div(x3+y2+y); HC=NSplaces(1..2,HC); HC=extcurve(2,HC); def ER=HC[1][4]; setring ER; intvec G=5; // the rational divisor G = 5*HC[3][1] intvec D=2..9; // D = sum of the rational places no. 2..9 over F_4 // let us construct the corresponding residual AG code : matrix C=AGcode_Omega(G,D,HC); // here is a linear code of type [8,3,>=5] over F_4 print(C); printlevel=plevel; } /////////////////////////////////////////////////////////////////////////////// // ============================================================================ // ******* auxiliary procedure to define AG codes over extensions ******** // ============================================================================ proc extcurve (int d,list CURVE) "USAGE: extcurve( d, CURVE ); d an integer, CURVE a list RETURN: list L which is the update of the list CURVE with additional entries @format L[1][3]: ring (p,a),(x,y),lp (affine), L[1][4]: ring (p,a),(x,y,z),lp (projective), L[1][5]: ring (p,a),(x,y,t),ls (local), L[2][3]: int (the number of rational places), @end format the rings being defined over a field extension of degree d. @* If d<2 then @code{extcurve(d,CURVE);} creates a list L which is the update of the list CURVE with additional entries @format L[1][5]: ring p,(x,y,t),ls, L[2][3]: int (the number of computed places over the base field). @end format In both cases, in the ring L[1][5] lists with the data for all the computed rational places (after a field extension of degree d) are created (see @ref{Adj_div}): @format lists POINTS, LOC_EQS, BRANCHES, PARAMETRIZATIONS. @end format NOTE: The list CURVE should be the output of @code{NSplaces}, and must contain (at least) one place of degree d. @* You actually need all the places with degree dividing d. Otherwise, not all the places are computed, but only part of them. @* This procedure must be executed before constructing AG codes, even if no extension is needed. The ring L[1][4] must be active when constructing codes over the field extension.@* SEE ALSO: closed_points, Adj_div, NSplaces, AGcode_L, AGcode_Omega EXAMPLE: example extcurve; shows an example " { // extends the underlying curve and all its associated objects to a larger // base field in order to evaluate points over such a extension // if d<2 then the only change is that a local ring "RatPl" (which is a // copy of "S(1)") is created in order to store the rational places // where we can do evaluations // otherwise, such a ring contains all places which are rational over the // extension // warning : list Places does not change so that only divisors which are // "rational over the prime field" are allowed; this probably will // change in the future // warning : the places in RatPl are ranged in increasing degree, respecting // the order from list Places and placing the conjugate branches all // together def BR=basering; list ext_CURVE=CURVE; if (d<2) { def SS=CURVE[5][1][1]; ring RatPl=char(basering),(x,y,t),ls; list POINTS=imap(SS,POINTS); list LOC_EQS=imap(SS,LOC_EQS); list BRANCHES=imap(SS,BRANCHES); list PARAMETRIZATIONS=imap(SS,PARAMETRIZATIONS); export(POINTS); export(LOC_EQS); export(BRANCHES); export(PARAMETRIZATIONS); int NrRatPl=size(POINTS); ext_CURVE[2][3]=NrRatPl; setring BR; ext_CURVE[1][5]=RatPl; dbprint(printlevel+1,""); dbprint(printlevel+2,"Total number of rational places : "+string(NrRatPl)); dbprint(printlevel+1,""); kill RatPl; return(ext_CURVE); } else { // exclude the case when no place of degree d was previously computed/found int dd=size(CURVE[5]); if (dd"list") { ERROR("you did not compute/find any place of degree "+string(d)); } // Define the ring "RatPl" : def S(d)=CURVE[5][d][1]; setring S(d); string smin=string(minpoly); setring BR; ring RatPl=(char(basering),a),(x,y,t),ls; execute("minpoly="+smin+";"); // import data from local ring S(d) list POINTS=imap(S(d),POINTS); list LOC_EQS=imap(S(d),LOC_EQS); list BRANCHES=imap(S(d),BRANCHES); list PARAMETRIZATIONS=imap(S(d),PARAMETRIZATIONS); kill S(d); // conjugate data from S(d) int s=size(POINTS); int counter=0; int piv=0; int i,j,k; for (j=1;j<=s;j=j+1) { counter=counter+1; piv=counter; for (k=1;k=2;i=i-1) { if ( (d mod i)==0 ) { if (typeof(CURVE[5][i])=="list") { def S(i)=CURVE[5][i][1]; // embedd S(i) inside basering == RatPl " ==S(d) " olda=subfield(S(i)); setring S(i); s=size(POINTS); setring RatPl; // import data from S(i) for (j=s;j>=1;j=j-1) { counter=0; POINTS=insert(POINTS,list(),0); POINTS[1][1]=number(importdatum(S(i),"POINTS["+string(j) +"][1]",olda)); POINTS[1][2]=number(importdatum(S(i),"POINTS["+string(j) +"][2]",olda)); POINTS[1][3]=number(importdatum(S(i),"POINTS["+string(j) +"][3]",olda)); LOC_EQS=insert(LOC_EQS,importdatum(S(i),"LOC_EQS["+string(j) +"]",olda),0); BRANCHES=insert(BRANCHES,list(),0); setring S(i); m=nrows(BRANCHES[j][1]); n=ncols(BRANCHES[j][1]); iv=BRANCHES[j][2]; kk=BRANCHES[j][3]; poly par@1=subst(PARAMETRIZATIONS[j][1][1],t,x); poly par@2=subst(PARAMETRIZATIONS[j][1][2],t,x); export(par@1); export(par@2); iw=PARAMETRIZATIONS[j][2]; setring RatPl; paux=importdatum(S(i),"BRANCHES["+string(j)+"][4]",olda); matrix Maux[m][n]; for (ii=1;ii<=m;ii=ii+1) { for (jj=1;jj<=n;jj=jj+1) { Maux[ii,jj]=importdatum(S(i),"BRANCHES["+string(j) +"][1]["+string(ii)+","+string(jj)+"]",olda); } } BRANCHES[1][1]=Maux; BRANCHES[1][2]=iv; BRANCHES[1][3]=kk; BRANCHES[1][4]=paux; kill Maux; PARAMETRIZATIONS=insert(PARAMETRIZATIONS,list(),0); PARAMETRIZATIONS[1][1]=ideal(0); PARAMETRIZATIONS[1][1][1]=importdatum(S(i),"par@1",olda); PARAMETRIZATIONS[1][1][2]=importdatum(S(i),"par@2",olda); PARAMETRIZATIONS[1][1][1]=subst(PARAMETRIZATIONS[1][1][1],x,t); PARAMETRIZATIONS[1][1][2]=subst(PARAMETRIZATIONS[1][1][2],x,t); PARAMETRIZATIONS[1][2]=iw; for (k=1;k0) { w=w+1; } } } return(w); } /////////////////////////////////////////////////////////////////////////////// // Basic Algorithm of Skorobogatov and Vladut for decoding AG codes // warning : the user must choose carefully the parameters for the code and // the decoding since they will never be checked by the procedures proc prepSV (intvec G,intvec D,intvec F,list EC) "USAGE: prepSV( G, D, F, EC ); G,D,F intvecs and EC a list RETURN: list E of size n+3, where n=size(D). All its entries but E[n+3] are matrices: @format E[1]: parity check matrix for the current AG code E[2] ... E[n+2]: matrices used in the procedure decodeSV E[n+3]: intvec with E[n+3][1]: correction capacity @math{epsilon} of the algorithm E[n+3][2]: designed Goppa distance @math{delta} of the current AG code @end format NOTE: Computes the preprocessing for the basic (Skorobogatov-Vladut) decoding algorithm.@* The procedure must be called within the ring EC[1][4], where EC is the output of @code{extcurve(d)} (or in the ring EC[1][2] if d=1) @* The intvec G and F represent rational divisors (see @ref{BrillNoether} for more details).@* The intvec D refers to rational places (see @ref{AGcode_Omega} for more details.). The current AG code is @code{AGcode_Omega(G,D,EC)}.@* If you know the exact minimum distance d and you want to use it in @code{decodeSV} instead of @math{delta}, you can change the value of E[n+3][2] to d before applying decodeSV. If you have a systematic encoding for the current code and want to keep it during the decoding, you must previously permute D (using @code{permute_L(D,P);}), e.g., according to the permutation P=L[3], L being the output of @code{sys_code}. WARNINGS: F must be a divisor with support disjoint from the support of D and with degree @math{epsilon + genus}, where @math{epsilon:=[(deg(G)-3*genus+1)/2]}.@* G should satisfy @math{ 2*genus-2 < deg(G) < size(D) }, which is not checked by the algorithm. G and D should also have disjoint supports (checked by the algorithm). KEYWORDS: SV-decoding algorithm, preprocessing SEE ALSO: extcurve, AGcode_Omega, decodeSV, sys_code, permute_L EXAMPLE: example prepSV; shows an example " { if (disj_divs(F,D,EC)==0) { dbprint(printlevel+3,"? the divisors do not have disjoint supports, empty list returned ?"); return(list()); } list E=list(); list Places=EC[3]; int m=deg_D(G,Places); int genusX=EC[2][2]; int e=(m+1-3*genusX) div 2; if (e<1) { dbprint(printlevel+3,"? the correction capacity of the basic algorithm is zero, empty list returned ?"); return(list()); } // deg(F)==e+genusX should be satisfied, and sup(D),sup(F) should be // disjoint !!!! int n=size(D); // 2*genusX-2=5] over F_4: matrix C=AGcode_Omega(G,D,HC); // we can correct 1 error and the genus is 1, thus F must have degree 2 // and support disjoint from that of D; intvec F=2; list SV=prepSV(G,D,F,HC); // now everything is prepared to decode with the basic algorithm; // for example, here is a parity check matrix to compute the syndrome : print(SV[1]); // and here you have the correction capacity of the algorithm : int epsilon=SV[size(D)+3][1]; epsilon; printlevel=plevel; } /////////////////////////////////////////////////////////////////////////////// proc decodeSV (matrix y,list K) "USAGE: decodeSV( y, K ); y a row-matrix and K a list RETURN: a codeword (row-matrix) if possible, resp. the 0-matrix (of size 1) if decoding is impossible. For decoding the basic (Skorobogatov-Vladut) decoding algorithm is applied. NOTE: The list_expression should be the output K of the procedure @code{prepSV}.@* The matrix_expression should be a (1 x n)-matrix, where n = ncols(K[1]).@* The decoding may fail if the number of errors is greater than the correction capacity of the algorithm. KEYWORDS: SV-decoding algorithm SEE ALSO: extcurve, AGcode_Omega, prepSV EXAMPLE: example decodeSV; shows an example " { // decodes y with the "basic decoding algorithm", if possible // requires the preprocessing done by the procedure "prepSV" // the procedure must be called from ring R or R(d) // returns either a codeword (matrix) of none (in case of too many errors) matrix syndr=K[1]*transpose(y); if (Hamming_wt(syndr)==0) { return(y); } matrix Ey=y[1,1]*K[2]; int n=ncols(y); int i; for (i=2;i<=n;i=i+1) { Ey=Ey+y[1,i]*K[i+1]; } matrix Ky=get_NZsol(Ey); if (Hamming_wt(Ky)==0) { dbprint(printlevel+3,"? no error-locator found ?"); dbprint(printlevel+3,"? too many errors occur, 0-matrix returned ?"); matrix answer; return(answer); } int r=nrows(K[n+2]); matrix ErrLoc[1][n]; list Z=list(); list NZ=list(); int j; for (j=1;j<=n;j=j+1) { for (i=1;i<=r;i=i+1) { ErrLoc[1,j]=ErrLoc[1,j]+K[n+2][i,j]*Ky[1,i]; } if (ErrLoc[1,j]==0) { Z=insert(Z,j,size(Z)); } else { NZ=insert(NZ,j,size(NZ)); } } int k=size(NZ); int l=nrows(K[1]); int s=l+k; matrix A[s][n]; matrix b[s][1]; for (i=1;i<=l;i=i+1) { for (j=1;j<=n;j=j+1) { A[i,j]=K[1][i,j]; } b[i,1]=syndr[i,1]; } for (i=1;i<=k;i=i+1) { A[l+i,NZ[i]]=number(1); } intvec opgt=option(get); option(redSB); matrix L=transpose(syz(concat(A,-b))); if (nrows(L)==1) { if (L[1,n+1]<>0) { poly pivote=L[1,n+1]; matrix sol=submat(L,1..1,1..n); if (pivote<>1) { sol=(number(1)/number(pivote))*sol; } // check at least that the number of comitted errors is less than half // the Goppa distance // imposing Hamming_wt(sol)<=K[n+3][1] would be more correct, but maybe // is too strong // on the other hand, if Hamming_wt(sol) is too large the decoding may // not be acceptable if ( Hamming_wt(sol) <= (K[n+3][2]-1) div 2 ) { option(set,opgt); return(y-sol); } else { dbprint(printlevel+3,"? non-acceptable decoding ?"); } } else { dbprint(printlevel+3,"? no solution found ?"); } } else { dbprint(printlevel+3,"? non-unique solution ?"); } option(set,opgt); dbprint(printlevel+3,"? too many errors occur, 0-matrix returned ?"); matrix answer; return(answer); } example { "EXAMPLE:"; echo = 2; int plevel=printlevel; printlevel=-1; ring s=2,(x,y),lp; list HC=Adj_div(x3+y2+y); HC=NSplaces(1..2,HC); HC=extcurve(2,HC); def ER=HC[1][4]; setring ER; intvec G=5; // the rational divisor G = 5*HC[3][1] intvec D=2..9; // D = sum of the rational places no. 2..9 over F_4 // construct the corresp. residual AG code of type [8,3,>=5] over F_4: matrix C=AGcode_Omega(G,D,HC); // we can correct 1 error and the genus is 1, thus F must have degree 2 // and support disjoint from that of D intvec F=2; list SV=prepSV(G,D,F,HC); // now we produce 1 error on the zero-codeword : matrix y[1][8]; y[1,3]=a; // and then we decode : print(decodeSV(y,SV)); printlevel=plevel; } /////////////////////////////////////////////////////////////////////////////// proc sys_code (matrix C) "USAGE: sys_code(C); C is a matrix of constants RETURN: list L with: @format L[1] is the generator matrix in standard form of an equivalent code, L[2] is the parity check matrix in standard form of such code, L[3] is an intvec which represents the needed permutation. @end format NOTE: Computes a systematic code which is equivalent to the given one.@* The input should be a matrix of numbers.@* The output has to be interpreted as follows: if the input was the generator matrix of an AG code then one should apply the permutation L[3] to the divisor D of rational points by means of @code{permute_L(D,L[3]);} before continuing to work with the code (for instance, if you want to use the systematic encoding together with a decoding algorithm). KEYWORDS: linear code, systematic SEE ALSO: permute_L, AGcode_Omega, prepSV EXAMPLE: example sys_code; shows an example " { // computes a systematic code which is equivalent to that given by C int i,j,k,l,h,r; int m=nrows(C); int n=ncols(C); int mr=m; matrix A[m][n]=C; poly c,p; list corners=list(); if(m>n) { mr=n; } // first the matrix A will be reduced with elementary operations by rows for(i=1;i<=mr;i=i+1) { if((i+l)>n) { // the process is finished break; } // look for a non-zero element if(A[i,i+l]==0) { h=i; p=0; for (j=i+1;j<=m;j=j+1) { c=A[j,i+l]; if (c!=0) { p=c; h=j; break; } } if (h!=i) { // permutation of rows i and h for (j=1;j<=n;j=j+1) { c=A[i,j]; A[i,j]=A[h,j]; A[h,j]=c; } } if(p==0) { // non-zero element not found in the current column l=l+1; continue; } } // non-zero element was found in "strategic" position corners[i]=i+l; // make zeros below that position for(j=i+1;j<=m;j=j+1) { c=A[j,i+l]/A[i,i+l]; for(k=i+l+1;k<=n;k=k+1) { A[j,k]=A[j,k]-A[i,k]*c; } A[j,i+l]=0; A[j,i]=0; } // the rank is at least r // when the process stops the last r is actually the true rank of A=a r=i; } if (rj) { // interchange columns j and corners[j] for (i=1;i<=m;i=i+1) { c=A[i,j]; A[i,j]=A[i,corners[j]]; A[i,corners[j]]=c; } k=PCols[j]; PCols[j]=PCols[corners[j]]; PCols[corners[j]]=k; } } // convert the diagonal into ones for (i=1;i<=m;i=i+1) { for (j=i+1;j<=n;j=j+1) { A[i,j]=A[i,j]/A[i,i]; } A[i,i]=1; } // complete a block with the identity matrix for (k=1;k1; else use R instead setring ER; Now you have to decide the divisor G and the sequence of rational points D to use for constructing the codes; first notice that the syntax for G and D is different: (a) G is a divisor supported on the closed places of CURVE[3], and you must say just the coefficient of each such a point; for example, G=2,0,-1 means 2 times the place 1 minus 1 times the place 3. (b) D is a sequence of rational points (all different and counted 1 time each one), whose data are read from the lists inside CURVE[1][5] and now you must say just the order how you range the chosen point; for example, D=2,4,1 means that you choose the rational places 1,2,4 and you range them as 2,4,1. (3.1) matrix C=AGcode_L(divisor,places,CURVE); (3.2) AGcode_Omega(divisor,places,CURVE); In the same way as for defining the codes, the auxiliary divisor F must have disjoint support to that of D, and its degree has to be given by a formula (see help prepSV). (3.3) list SV=prepSV(divisor,places,auxiliary_divisor,CURVE); (3.4) decodeSV(word,SV); Special Issues : (I) AG codes with systematic encoding : matrix C=AGcode_Omega(G,D,CURVE); list CODE=sys_code(G); C=CODE[1]; // generator matrix in standard form D=permute_L(D,CODE[3]); // suitable permutation of coordinates list SV=prepSV(G,D,F,CURVE); SV[1]=CODE[2]; // parity-check matrix in standard form (II) Using the true minimum distance d for decoding : matrix C=AGcode_Omega(G,D,CURVE); int n=size(D); list SV=prepSV(G,D,F,CURVE); SV[n+3][2]=d; // then use decodeSV(y,SV); // ============================================================================ // *** Some "macros" with typical examples of curves in Coding Theory **** // ============================================================================ proc Klein () { list KLEIN=Adj_div(x3y+y3+x); KLEIN=NSplaces(1..3,KLEIN); KLEIN=extcurve(3,KLEIN); dbprint(printlevel+1,"Klein quartic over F_8 successfully constructed"); return(KLEIN); } proc Hermite (int m) { int p=char(basering); int r=p^m; list HERMITE=Adj_div(y^r+y-x^(r+1)); HERMITE=NSplaces(1..2*m,HERMITE); HERMITE=extcurve(2*m,HERMITE); dbprint(printlevel+1,"Hermitian curve over F_("+string(r)+"^2) successfully constructed"); return(HERMITE); } proc Suzuki () { list SUZUKI=Adj_div(x10+x3+y8+y); SUZUKI=NSplaces(1..3,SUZUKI); SUZUKI=extcurve(3,SUZUKI); dbprint(printlevel+1,"Suzuki curve over F_8 successfully constructed"); return(SUZUKI); } // **** Other interesting examples : // A hyperelliptic curve with 33 rational points over F_16 list CURVE=Adj_div(x5+y2+y); CURVE=NSplaces(1..4,CURVE); CURVE=extcurve(4,CURVE); // A nice curve with 113 rational points over F_64 list CURVE=Adj_div(y9+y8+xy6+x2y3+y2+x3); intvec ww=1,2,3,6; CURVE=NSplaces(ww,CURVE); CURVE=extcurve(6,CURVE); */ singular-4.0.3+ds/Singular/LIB/central.lib000066400000000000000000001572731266270727000203060ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version central.lib 4.0.0.0 Jun_2013 "; // $Id: d434884257d4a520a8c7c42187abfbaf6f948124 $ category="Noncommutative"; info=" LIBRARY: central.lib Computation of central elements of GR-algebras AUTHOR: Oleksandr Motsak, U@D, where U={motsak}, D={mathematik.uni-kl.de} OVERVIEW: A library for computing elements of the center and centralizers of sets of elements in GR-algebras. KEYWORDS: center; centralizer; reduce; centralize; PBW PROCEDURES: centralizeSet(F, V) v.s. basis of the centralizer of F within V centralizerVS(F, D) v.s. basis of the centralizer of F centralizerRed(F, D[, N]) reduced basis of the centralizer of F centerVS(D) v.s. basis of the center centerRed(D[, k]) reduced basis of the center center(D[, k]) reduced basis of the center centralizer(F, D[, k]) reduced bais of the centralizer of F sa_reduce(V) 's.a. reduction' of pairwise commuting elements sa_poly_reduce(p, V) 's.a. reduction' of p by pairwise commuting elements inCenter(T) checks the centrality of list/ideal/poly T inCentralizer(T, S) checks whether list/ideal/poly T commute with S isCartan(p) checks whether polynomial p is a Cartan element applyAdF(Basis, f) images of elements under the k-linear map Ad_f linearMapKernel(Images) kernel of a linear map given by images linearCombinations(Basis, C) k-linear combinations of elements variablesStandard() set of algebra generators in their natural order variablesSorted() heuristically sorted set of algebra generators PBW_eqDeg(Deg) PBW monomials of given degree PBW_maxDeg(MaxDeg) PBW monomials up to given degree PBW_maxMonom(MaxMonom) PBW monomials up to given maximal monomial "; LIB "general.lib" // for "sort" LIB "poly.lib" // for "maxdeg" /******************************************************/ // ::DefaultStuff:: Shortcuts to useful short functions. Just to avoid if( if( if( ... ))). /******************************************************/ /******************************************************/ static proc DefaultValue ( def s, list # ) // Process general variable parameters list " RETURN: s or (typeof(s))(#) " { def @p = s; if ( size(#) > 0 ) { if ( typeof(#[1]) == typeof(s) ) { @p = #[1]; } } return( @p ); } /******************************************************/ static proc DefaultInt( list # ) // Process variable parameters list with 'int' default value " RETURN: 0 or int(#) " { int @p = 0; return( DefaultValue( @p, # ) ); } /******************************************************/ static proc DefaultIdeal ( list # ) // Process variable parameters list with 'ideal' default value " RETURN: 0 or ideal(#) " { ideal @p = 0; return( DefaultValue( @p, # ) ); } /******************************************************/ // ::Debug:: Shortcuts to used debugging functions. /******************************************************/ /******************************************************/ static proc toprint( int pl ) // To print or not to print?!? The answer is here! " RETURN: 1 means to print, otherwise 0. " { return( printlevel >= ( 3 - pl) ); // voice + ? } /******************************************************/ static proc DBPrint( int pl, list # ) // My 'dbprint' which uses toprint(i). " USAGE: " { if( toprint(pl) ) { dbprint(1, #); } } /******************************************************/ static proc BCall( string Name, list # ) // This function must be called at the beginning of every 'mathematical' function. " USAGE: Name is a name of a mathematical function to trace. # means parameters into the function. " { if( toprint(0) ) { "CALL: ", Name, "( "; dbprint(1, #); " )"; } } /******************************************************/ static proc ECall(string Name, list #) // This function must be called at the end of every 'mathematical' function. " USAGE: Name is a name of a mathematical function to trace. # means result of the function. " { if( toprint(0) ) { "RET : ", Name, " => Result: {"; dbprint(1, #); " }"; } } /******************************************************/ // ::Helpers:: Small functions used in this library. /******************************************************/ /******************************************************/ static proc makeNice( def l ) " RETURN: the same as input PURPOSE: make 'nice' polynomials, kill scalars " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "makeNice", l ); } /*4DEBUG*/ poly p; if( typeof(l) == "poly" ) { // "normal" polynomial form == no denominators, gcd of coeffs is a unit l = cleardenom( l ); if ( maxdegInt(l) > 0 ) { l = cleardenom( l / leadcoef(l) ); } } else { if( typeof(l) == "ideal" ) { for( int i = 1; i <= size(l); i++ ) { p = l[i]; p = cleardenom( p ); // Now make polynomials look nice: if ( maxdegInt(p) > 0 ) // throw away scalars! { // "normal" polynomial form == no denominators, gcd of coeffs is a unit p = cleardenom( p / leadcoef(p) ); } else { p = 0; // no constants } l[i] = p; } l = simplify(l, 2 + 8); } } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "makeNice", l ); } /*4DEBUG*/ return( l ); } /******************************************************/ static proc monomialForm( def p ) " : p is either poly or ideal RETURN: polynomial with all monomials from p but without coefficients. " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "monomialForm", p ); } /*4DEBUG*/ poly result = 0; int k, j; poly m; if( typeof(p) == "ideal" ) // { if( ncols(p) > 0 ) { result = uni_poly( p[1] ); for ( k = ncols(p); k > 1; k -- ) { for( j = size(p[k]); j > 0; j-- ) { m = leadmonom( p[k][j] ); if( size(result + m) > size(result) ) // trick! { result = result + m; } } } } } else { if( typeof(p) == "poly" ) // { result = uni_poly(p); } else { ERROR( "ERROR: Wrong input! Expected polynomial or ideal!" ); } } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "monomialForm", result ); } /*4DEBUG*/ return( result ); } /******************************************************/ static proc uni_poly( poly p ) " returns polynomial with the same monomials but without coefficients. " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "uni_poly", p ); } /*4DEBUG*/ poly result = 0; for ( int k = size(p); k > 0; k -- ) { result = result + leadmonom( p[k] ); } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "uni_poly", result ); } /*4DEBUG*/ return( result ); } /******************************************************/ static proc smoothQideal( ideal I, list #) " PURPOSE: smooths the ideal in a current QUOTIENT(!) ring. " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "smoothQideal", I ); } /*4DEBUG*/ ideal A = matrix(I) - matrix(NF( I, twostd(DefaultIdeal(#)), 1 )); // component wise if( size(A) > 0 ) // Were there any changes (any non-zero component)? { ideal T; int j = 1; for( int i = 1; i <= ncols(I); i++ ) { if( size(A[i]) == 0 ) // keep only unchanged elements { T[ j ] = I[i]; j++; } } I = T; } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "smoothQideal", I ); } /*4DEBUG*/ return( I ); } /******************************************************/ // ::PBW:: PBW basis construction. /******************************************************/ /******************************************************/ proc PBW_maxDeg( int MaxDeg ) " USAGE: PBW_maxDeg(MaxDeg); MaxDeg int PURPOSE: Compute PBW elements up to a given maximal degree. RETURN: ideal consisting of found elements. NOTE: unit is omitted. Weights are ignored! " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "PBW_maxDeg", MaxDeg ); } /*4DEBUG*/ ideal Basis = 0; for (int k = 1; k <= MaxDeg; k ++ ) { Basis = Basis + maxideal(k); } Basis = smoothQideal( Basis ); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "PBW_maxDeg", Basis ); } /*4DEBUG*/ return( Basis ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(e,f,h),dp; matrix D[3][3]=0; D[1,2]=-h; D[1,3]=2*e; D[2,3]=-2*f; def A = nc_algebra(1,D); // this algebra is U(sl_2) setring A; // PBW Basis of A_2 - monomials of degree <= 2, without unit: PBW_maxDeg( 2 ); } /******************************************************/ proc PBW_eqDeg( int Deg ) " USAGE: PBW_eqDeg(Deg); Deg int PURPOSE: Compute PBW elements of a given degree. RETURN: ideal consisting of found elements. NOTE: Unit is omitted. Weights are ignored! " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "PBW_eqDeg", Deg ); } /*4DEBUG*/ ideal Basis = smoothQideal( maxideal( Deg ) ); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "PBW_eqDeg", Basis ); } /*4DEBUG*/ return( Basis ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(e,f,h),dp; matrix D[3][3]=0; D[1,2]=-h; D[1,3]=2*e; D[2,3]=-2*f; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) // PBW Basis of A_2 \ A_1 - monomials of degree == 2: PBW_eqDeg( 2 ); } /******************************************************/ proc PBW_maxMonom( poly MaxMonom ) " USAGE: PBW_maxMonom(m); m poly PURPOSE: Compute PBW elements up to a given maximal one. RETURN: ideal consisting of found elements. NOTE: Unit is omitted. Weights are ignored! " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "PBW_maxMonom", MaxMonom ); } /*4DEBUG*/ ideal K = 0; intvec exp = leadexp( MaxMonom ); for ( int k = 1; k <= size(exp); k ++ ) { K[ 1 + size(K) ] = var(k)^( 1 + exp[k] ); } attrib(K, "isSB", 1); K = kbase(K); K = K[ (ncols(K)-1)..1]; // reverse, kill last 1 K = smoothQideal( K ); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "PBW_maxMonom", K ); } /*4DEBUG*/ return( K ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(e,f,h),dp; matrix D[3][3]=0; D[1,2]=-h; D[1,3]=2*e; D[2,3]=-2*f; def A = nc_algebra(1,D); // this algebra is U(sl_2) setring A; // At most 1st degree in e, h and at most 2nd degree in f, unit is omitted: PBW_maxMonom( e*(f^2)* h ); } /******************************************************/ // ::CORE:: Core procedures... /******************************************************/ /******************************************************/ proc applyAdF( ideal I, poly p ) " USAGE: applyAdF(B, f); B ideal, f poly PURPOSE: Apply Ad_f to every element of B RETURN: ideal, generated by Ad_f(B[i]), 1<=i<=size(B) NOTE: Ad_f(v) := [f, v] = f*v - v*f SEE ALSO: linearMapKernel; linearMapKernel " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "applyAdF", I, p ); } /*4DEBUG*/ poly t; ideal II = 0; for ( int k = ncols(I); k > 0; k --) { t = I[k]; II[k] = p * t - t * p; // we have to reduce smooth images in Qrings... } II = NF( II, twostd(0) ); // ... now! /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "applyAdF", II ); } /*4DEBUG*/ return( II ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(e,f,h),dp; matrix D[3][3]=0; D[1,2]=-h; D[1,3]=2*e; D[2,3]=-2*f; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) // Let us consider the linear map Ad_{e} from A_2 into A. // Compute the PBW basis of A_2: ideal Basis = PBW_maxDeg( 2 ); Basis; // Compute images of basis elements under the linear map Ad_e: ideal Image = applyAdF( Basis, e ); Image; // Now we have a linear map given by: Basis_i --> Image_i // Let's compute its kernel K: // 1. compute syzygy module C: module C = linearMapKernel( Image ); C; // 2. compute corresponding combinations of basis vectors: ideal K = linearCombinations(Basis, C); K; // Let's check that Ad_e(K) is zero: applyAdF( K, e ); } /******************************************************/ proc linearMapKernel( ideal Images ) " USAGE: linearMapKernel( Images ); Images ideal PURPOSE: Computes the syzygy module of the linear map given by Images. RETURN: syzygy module, or int(0) if all images are zeroes SEE ALSO: applyAdF; linearMapKernel " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "linearMapKernel", Images ); } /*4DEBUG*/ // This must be a list of monomials in a form of polynomial (sum with coeffs == 1) poly Monomials = monomialForm( Images ); int N = size( Monomials ); // number of different monomials if ( N == 0 ) // & ncols( Images ) > 0 => all Images == 0 { int result = 0; /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "linearMapKernel", result ); } /*4DEBUG*/ return( result ); } // Compute matrix MD module MD; // zero int x, y; vector w; poly p, m; int V = ncols(Images); // must be equal to ncols(Basis) and size(Basis)! // We take monomials as vector space basis of _k... // TODO: Is there any other way to compute a basis of it and represent images as // linear combination of them??? // Maybe some 'free resolution' stuff??? But we need linear maps only!!! for ( x = 1; x <= V; x++ ) // For every Image vector { w = 0; p = Images[x]; y = 1; // from 1st monomial in Monomials... while( size(p) > 0 ) { m = leadmonom(p); // y < N! while( Monomials[y] != m ) // There MUST be this monomial because of the construction of Monomials polynomial! { y++; // to size() } // found monomial m at position y. w = w + leadcoef(p) * gen(y); // leadcoef(p) MUST be nonzero! p = p - lead(p); // kill lead term } MD[x] = w; } /*******************************************/ // save options intvec v = option( get ); // set right options option( redSB ); option( redTail ); // compute everything in a right form MD = simplify( groebner( syz(MD) ), 1 + 2 + 8 ); // note that MD is a matrix of numbers - no polynomials... // restore options option( set, v ); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "linearMapKernel", MD ); } /*4DEBUG*/ return( MD ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(e,f,h),dp; matrix D[3][3]=0; D[1,2]=-h; D[1,3]=2*e; D[2,3]=-2*f; def A = nc_algebra(1,D); // this algebra is U(sl_2) setring A; // Let us consider the linear map Ad_{e} from A_2 into A. // Compute the PBW basis of A_2: ideal Basis = PBW_maxDeg( 2 ); Basis; // Compute images of basis elements under the linear map Ad_e: ideal Image = applyAdF( Basis, e ); Image; // Now we have a linear map given by: Basis_i --> Image_i // Let's compute its kernel K: // 1. compute syzygy module C: module C = linearMapKernel( Image ); C; // 2. compute corresponding combinations of basis vectors: ideal K = linearCombinations(Basis, C); K; // Let's check that Ad_e(K) is zero: ideal Z = applyAdF( K, e ); Z; // Now linearMapKernel will return a single integer 0: def CC = linearMapKernel(Z); typeof(CC); CC; } /******************************************************/ proc linearCombinations( ideal Basis, module KER ) " USAGE: linearCombinations( Basis, C ); Basis ideal, C module PURPOSE: forms linear combinations of elements from Basis by replacing gen(i) by Basis[i] in C RETURN: ideal generated by computed linear combinations SEE ALSO: linearMapKernel; applyAdF " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "linearCombinations", Basis, KER ); } /*4DEBUG*/ number c; int x, y; vector w; poly p; ideal result = 0; // Kernel' basis translation for ( x = 1; x <= ncols(KER); x++ ) { p = 0; w = KER[x]; for ( y = 1; y <= nrows(w); y++ ) { c = leadcoef( w[y] ); if ( c != 0 ) { p = p + c * Basis[y]; // linear combination of base vectors { Basis[y] } } } result[ x ] = p; } // no reduction in quotient algebras is needed. No multiplications were done! /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "linearCombinations", result ); } /*4DEBUG*/ return( result ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(e,f,h),dp; matrix D[3][3]=0; D[1,2]=-h; D[1,3]=2*e; D[2,3]=-2*f; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) // Let us consider the linear map Ad_{e} from A_2 into A. // Compute the PBW basis of A_2: ideal Basis = PBW_maxDeg( 2 ); Basis; // Compute images of basis elements under the linear map Ad_e: ideal Image = applyAdF( Basis, e ); Image; // Now we have a linear map given by: Basis_i --> Image_i // Let's compute its kernel K: // 1. compute syzygy module C: module C = linearMapKernel( Image ); C; // 2. compute corresponding combinations of basis vectors: ideal K = linearCombinations(Basis, C); K; // Let's check that Ad_e(K) is zero: applyAdF( K, e ); } /******************************************************/ static proc LINEAR_MAP_KERNEL(ideal Basis, ideal Images ) // Ker of the linear map given by its values on basis vectors " PURPOSE: Computation of the kernel basis of the linear map given by the list @given " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "LINEAR_MAP_KERNEL", Basis, Images ); } /*4DEBUG*/ ideal result = 0; if ( size( Basis ) == 0 ) { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "LINEAR_MAP_KERNEL", result ); } /*4DEBUG*/ return( result ); } // compute fundamental solutions system def T = linearMapKernel( Images ); // check result of linearMapKernel if( typeof(T) == "int" ) { if( T == 0 ) { // All zeroes! Return Basis: /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "LINEAR_MAP_KERNEL", Basis ); } /*4DEBUG*/ return( Basis ); } } else { if( typeof(T) != "module" ) { ERROR( "Wrong output from the 'linearMapKernel' function!" ); } } result = linearCombinations( Basis, T ); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "LINEAR_MAP_KERNEL", result ); } /*4DEBUG*/ return( result ); } /******************************************************/ static proc ZeroKer( ideal Basis, ideal Images ) // VS Basis of a Kernel of the linear map AD_h, h is a Cartan element " PURPOSE: Computes VS Basis of a Kernel of the linear map AD_h, when h is a Cartan element NOTE: the result is a set of all basis vectors having a zero image " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "ZeroKer", Basis, Images ); } /*4DEBUG*/ ideal result = 0; for( int i = 1; i <= ncols( Basis ); i++ ) { if( size( Images[i] ) == 0 ) // zero image? { result[ 1 + size(result) ] = Basis[i]; // take this basis vector! } } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "ZeroKer", result ); } /*4DEBUG*/ return( result ); } /******************************************************/ // ::Variables:: Computes a set of variables /******************************************************/ /******************************************************/ // Returns an ideal of variables in a current base ring. proc variablesStandard() " USAGE: variablesStandard(); RETURN: ideal, generated by algebra variables PURPOSE: computes the set of algebra variables taken in their natural order SEE ALSO: variablesSorted EXAMPLE: example variablesStandard; shows an example " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "variablesStandard" ); } /*4DEBUG*/ ideal result = maxideal(1); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "variablesStandard", result ); } /*4DEBUG*/ return( result ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) // Variables in their natural order: variablesStandard(); } /******************************************************/ // Sorts variables into an ideal. This is a kind of heuristics! proc variablesSorted() " USAGE: variablesSorted(); RETURN: ideal, generated by sorted algebra variables PURPOSE: computes the set of algebra variables sorted so that @* Cartan variables go first NOTE: This is a heuristics for the computation of the center: @* it is better to compute centralizers of Cartan variables first since in this @* case we can omit solving the system of equations. SEE ALSO: variablesStandard EXAMPLE: example variablesSorted; shows an example "{ /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "variablesSorted" ); } /*4DEBUG*/ ideal V = variablesStandard(); int N = size( V ); // == nvars( basering ) ideal result = 0; int r_begin = 1; int r_end = N; poly v; for( int k = 1; k <= N; k++ ) { v = V[k]; if( isCartan(v) == 1 ) // Cartan elements go 1st { result[r_begin] = v; r_begin++; } else // Other - in the end... { result[r_end] = v; r_end--; } } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "variablesSorted", result ); } /*4DEBUG*/ return( result ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) // There is only one Cartan variable - z in U(sl_2), // it must go 1st: variablesSorted(); } /******************************************************/ /******************************************************/ // ::BasicCentralizerComputation:: Basic functions for centralize' computation. /******************************************************/ /******************************************************/ /******************************************************/ // HL 'core' function proc centralizeSet( ideal F, ideal V ) " USAGE: centralizeSet( F, V ); F, V ideals INPUT: F, V finite sets of elements of the base algebra RETURN: ideal, generated by computed elements PURPOSE: computes a vector space basis of the centralizer of the set F in the vector space generated by V over the ground field SEE ALSO: centralizerVS; centralizer; inCentralizer EXAMPLE: example centralizeSet; shows an example " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "centralizeSet", F, V ); } /*4DEBUG*/ int N = size(F); if( N == 0) { ERROR( "F MUST be non empty!!!" ); } DBPrint(1, "BasisSize: " + string(size(V)) ); ideal Images; for( int v = 1; (v <= N) and (size(V) > 0); v++ ) { DBPrint(1, "Centralizing " + string(F[v]) ); Images = applyAdF( V, F[v] ); if( (isCartan(F[v]) == 1) or (size(V) == 1) ) { V = ZeroKer( V, Images ); } else { V = LINEAR_MAP_KERNEL( V, Images ); } // Printing... DBPrint(1, "Progress: [ " + string(v) + " / " + string(N) + " ]"+ " => BasisSize: " + string(size(V)) ); } V = makeNice(V); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "centralizeSet", V ); } /*4DEBUG*/ return( V ); } example { "EXAMPLE:"; echo = 2; ring A = 0,(e(1..4)),dp; matrix D[4][4]=0; D[2,4] = -e(1); D[3,4] = -e(2); // This is A_4_1 - the first real Lie algebra of dimension 4. def A_4_1 = nc_algebra(1,D); setring A_4_1; ideal F = variablesSorted(); F; // the center of A_4_1 is generated by // e(1) and -1/2*e(2)^2+e(1)*e(3) // therefore one may consider computing it in the following way: // 1. Compute a PBW basis consisting of // monomials with exponent <= (1,2,1,0) ideal V = PBW_maxMonom( e(1) * e(2)^ 2 * e(3) ); // 2. Compute the centralizer of F within the vector space // spanned by these monomials: ideal C = centralizeSet( F, V ); C; inCenter(C); // check the result } /******************************************************/ proc centralizerVS( ideal F, int d ) " USAGE: centralizerVS( F, D ); F ideal, D int RETURN: ideal, generated by computed elements PURPOSE: computes a vector space basis of centralizer(F) up to degree D NOTE: D must be non-negative SEE ALSO: centerVS; centralizer; inCentralizer EXAMPLE: example centralizerVS; shows an example " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "centralizerVS", F, d ); } /*4DEBUG*/ if( size(F) == 0) { ERROR( "F MUST be non-empty!!!" ); } ideal V = centralizeSet( F, PBW_maxDeg( d ) ); // basis of the Centralizer of S in PBW basis /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "centralizerVS", V ); } /*4DEBUG*/ return( V ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) ideal F = x, y; // find generators of the vector space of elements // of degree <= 4 commuting with x and y: ideal C = centralizerVS(F, 4); C; inCentralizer(C, F); // check the result } /******************************************************/ // ::CenterAliases:: Basic functions/aliases for center' computation. /******************************************************/ /******************************************************/ proc centerVS( int D ) " USAGE: centerVS( D ); D int RETURN: ideal, generated by computed elements PURPOSE: computes a vector space basis of the center up to degree D NOTE: D must be non-negative SEE ALSO: centralizerVS; center; inCenter EXAMPLE: example centerVS; shows an example " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "centerVS", D ); } /*4DEBUG*/ if( nameof( basering ) == "basering" ) { // ERROR( "No current ring!" ); } if( D < 0 ) { ERROR( "Degree D must be non-negative!" ); } ideal result = centralizerVS( variablesSorted(), D ); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "centerVS", result ); } /*4DEBUG*/ return( result ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) // find a basis of the vector space of all // central elements of degree <= 4: ideal Z = centerVS(4); Z; // note that the second element is the square of the first // plus a multiple of the first: Z[2] - Z[1]^2 + 8*Z[1]; inCenter(Z); // check the result } /******************************************************/ proc centralizerRed( ideal F, int D, list # ) " USAGE: centralizerRed( F, D[, N] ); F ideal, D int, N optional int RETURN: ideal, generated by computed elements PURPOSE: computes subalgebra generators of centralizer(F) up to degree D. NOTE: In general, one cannot compute the whole centralizer(F). @* Hence, one has to specify a termination condition via arguments D and/or N. @* If D is positive, only centralizing elements up to degree D are computed. @* If D is negative, the termination is determined by N only. @* If N is given, the computation stops if at least N elements have been found. @* Warning: if N is given and bigger than the actual number of generators, @* the procedure may not terminate. @* Current ordering must be a degree compatible well-ordering. SEE ALSO: centralizerVS; centerRed; centralizer; inCentralizer EXAMPLE: example centralizerRed; shows an example " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "centralizerRed", F, D, # ); } /*4DEBUG*/ if( nameof( basering ) == "basering" ) { // ERROR( "No current ring!" ); } if( size(F) == 0) { ERROR( "F MUST be non-empty!!!" ); } ///////////////////////////////////////////////////////////////////////////// int i, j, l, d; ///////////////////////////////////////////////////////////////////////////// int k = DefaultInt(#); int m = (k > 0); int @MinDeg = 6; // starting guess for Maximal Bounding Degree, 6 int @Delta = 4; // increment of it, 4 if( m and (D <= 0) ) { // minimal guess D = @MinDeg; } if( !m and D < 0) { ERROR("Wrong bounding condition!"); } ///////////////////////////////////////////////////////////////////////////// def NCRING = basering; // Non-commutative ring list L = ringlist( NCRING ); def L1, L2, L3, L4 = L[1..4]; // General components def COMMRING = ring( list( L1, L2, L3, L4 ) ); // Underlying commutative ring ///////////////////////////////////////////////////////////////////////////// // we keep the list of found leading monomials in the commutative ring! setring COMMRING; // Init list FOUND_LEADING_MONOMIALS = list(); for( i = 1; i <= D; i++ ) { FOUND_LEADING_MONOMIALS[i] = ideal(); } ideal FLM, NEW, T; // in COMMRING ///////////////////////////////////////////////////////////////////////////// setring NCRING; ideal result, FLM, PBW, NEW, T, P; // in NCRING // Main loop: i = 1; while( i <= D ) { DBPrint( 1, "Current degree is " + string(i) ); ///////////////////////////////////////////////////////////////////////////// // Compute current "reduced" PBW basis... // Prepare current found leading monomials setring COMMRING; FLM = FOUND_LEADING_MONOMIALS[i]; // And back to NCRing setring NCRING; FLM = imap(COMMRING, FLM); // We cannot write imap(COMMRING, FOUND_LEADING_MONOMIALS[i]) :((( attrib(FLM, "isSB", 1); // just to avoid "no standard basis" warning. // degrees should not change, // no monomials should be multiplied here T = reduce( PBW_eqDeg( i ), FLM, 1 ); // we simply kill in T monomials occurring in FOUND_LEADING_MONOMIALS[i] P = PBW + T; // + simplifies // Compute current centralizer NEW = centralizeSet( F, P ); if( size(NEW) > 0 ) { // In order to speedup multiplications we are going into a commutative ring: setring COMMRING; // we can perform commutative interreduction // since no monomials should be multiplied! // degrees should not change NEW = interred( imap( NCRING, NEW ) ); // Go back! setring NCRING; NEW = imap( COMMRING, NEW ); DBPrint( 1, "Found: ", NEW ); // Add them to result... result = result + NEW; } // Did we find needed number of generators? Or reached the bound? if( (m and (size(result) >= k)) or (!m and (i == D)) ) { break; // Get out of here!!! } // otherwise we must update FOUND_LEADING_MONOMIALS if( size(NEW) > 0 ) { setring COMMRING; FLM = 0; // We must update FOUND_LEADING_MONOMIALS!!! for( j = 1; j <= size(NEW); j++ ) { FLM[j] = leadmonom( NEW[j] ); // we are interested in leading monomials only! } FOUND_LEADING_MONOMIALS[i] = FOUND_LEADING_MONOMIALS[i] + FLM; for( j = 1; j <= D; j = j + i ) // For every degree (j*i) of LNEW, do: { for( l = j; (l+i) <= D; l++ ) { FOUND_LEADING_MONOMIALS[l+i] = FOUND_LEADING_MONOMIALS[l+i] + FOUND_LEADING_MONOMIALS[l] * FLM; } } // Return to NCRING setring NCRING; FLM = imap(COMMRING, FLM); attrib(FLM, "isSB", 1);// just to avoid "no standard basis" warning. // we simply kill in T monomials occurring in FOUND_LEADING_MONOMIALS[i] T = reduce( T, FLM, 1 ); PBW = PBW + T; } else { PBW = P; } if( m and (i == D) ) // Was the previous estimation too small??? { // We must update FOUND_LEADING_MONOMIALS in their Commutative world: setring COMMRING; // Init new grades: for( j = D + 1; j <= (D + @Delta); j++ ) { FOUND_LEADING_MONOMIALS[j] = ideal(); } FLM = 0; // All previously computed elements in their order! NEW = imap( NCRING, result ); for( j = 1; j <= size(NEW); j++ ) { FLM[j] = leadmonom( NEW[j] ); // we are interested in leading monomials only! } while( size(FLM) > 0 ) { // minimal degree: d = mindegInt(FLM); /// ### /// // take all of minimal degree: T = jet( FLM, d ); // there are size(T) elements of smallest degree (deg(FLM[1])) in FLM! // Add them in the same way: for( j = 1; j <= (D + @Delta); j = j + d ) // For every degree (j*d) of T, do: { for( l = j; (l + d) <= (D + @Delta); l++ ) { if( (l + d) > D ) // Only new should be updated! { FOUND_LEADING_MONOMIALS[l+d] = FOUND_LEADING_MONOMIALS[l+d] + FOUND_LEADING_MONOMIALS[l] * T; } } } // Kill them from FLM: if( size(T) < size(FLM) ) { FLM = FLM[ (size(T)+1) .. size(FLM) ]; } else { FLM = 0; // break; } } // Go back... setring NCRING; /* if(toprint()) { typeof(@Delta); @Delta; typeof(D); D; } */ // And set new Bound D = D + @Delta; } i++; } result = makeNice(result); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "centralizerRed", result ); } /*4DEBUG*/ return( result ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) ideal F = x, y; // find subalgebra generators of degree <= 4 of the subalgebra of // all elements commuting with x and y: ideal C = centralizerRed(F, 4); C; inCentralizer(C, F); // check the result } /******************************************************/ proc centerRed( int D, list # ) " USAGE: centerRed( D[, N] ); D int, N optional int RETURN: ideal, generated by computed elements PURPOSE: computes subalgebra generators of the center up to degree D NOTE: In general, one cannot compute the whole center. @* Hence, one has to specify a termination condition via arguments D and/or N. @* If D is positive, only central elements up to degree D will be found. @* If D is negative, the termination is determined by N only. @* If N is given, the computation stops if at least N elements have been found. @* Warning: if N is given and bigger than the actual number of generators, @* the procedure may not terminate. @* Current ordering must be a degree compatible well-ordering. SEE ALSO: centralizerRed; centerVS; center; inCenter EXAMPLE: example centerRed; shows an example " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "centerRed", D, # ); } /*4DEBUG*/ if( nameof( basering ) == "basering" ) { // ERROR( "No current ring!" ); } ideal result = centralizerRed( variablesSorted(), D, # ); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "centerRed", result ); } /*4DEBUG*/ return( result ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=z; def A = nc_algebra(1,D); setring A; // it is a Heisenberg algebra // find a basis of the vector space of // central elements of degree <= 3: ideal VSZ = centerVS(3); // There should be 3 degrees of z. VSZ; inCenter(VSZ); // check the result // find "minimal" central elements of degree <= 3 ideal SAZ = centerRed(3); // Only 'z' must be computed SAZ; inCenter(SAZ); // check the result } /******************************************************/ /******************************************************/ // ::SubAlgebraReduction:: A kind of subalgebra reduction... /******************************************************/ /******************************************************/ /******************************************************/ static proc INTERRED( ideal S ) " USAGE: INTERRED( S ); S ideal RETURN: ideal, interreduced S PURPOSE: interreduction without monomial multiplication, just make every leading monomial occur in a single polynomial " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "INTERRED", S ); } /*4DEBUG*/ ideal result = S; int flag = 1; int i, j, N; poly p, lm; while( flag == 1 ) { flag = 0; result = sort( simplify( result, 1 + 2 + 8) )[1]; // sorting w.r.t. actual monomial ordering // generators with SMALLER(!) leading term come FIRST N = size(result); // kill leading monomials: i = 1; while( i < N ) { p = result[i]; lm = leadmonom(p); j = i + 1; while( leadmonom(result[j]) == lm ) { result[j] = result[j] - p; // leadcoefs are 1 because of simplify. flag = 1; // we have changed something => we do still need to care about it... j++; if( j > N ) { break; } } i = j; } } // We are done! No common leading monomials! // The result is sorted /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "INTERRED", result ); } /*4DEBUG*/ return( result ); } /******************************************************/ static proc SANF( poly p, list FOUND_LEADING_MONOMIALS ) " reduce p w.r.t. found multiples without ANY polynomial multiplications! " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "SANF", p, FOUND_LEADING_MONOMIALS); } /*4DEBUG*/ poly q = p; poly head = 0; int d; int N = size(FOUND_LEADING_MONOMIALS); while( size(q) > 0 ) { d = maxdegInt(p); /// ### /// if( (0 < d) and (d <= N) ) { if( size(FOUND_LEADING_MONOMIALS[d]) > 0 ) { attrib( FOUND_LEADING_MONOMIALS[d], "isSB", 1); q = reduce( p, FOUND_LEADING_MONOMIALS[d] ); } DBPrint(1, string(p) + " --> " + string(q) ); } if( q == p ) { p = lead(q); if( d > 0 ) { // No scalars! head = head + p; } q = q - p; } p = q; } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "SANF", head ); } /*4DEBUG*/ return( head ); } /******************************************************/ static proc maxdegInt( ideal I ) { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "maxdegInt", I ); } /*4DEBUG*/ intmat D = maxdeg(I); int max = D[1, 1]; int m; for( int c = 2; c <= ncols(D); c++ ) { m = D[1, c]; if( m > max ) { max = m; } } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "maxdegInt", max ); } /*4DEBUG*/ return( max ); } /******************************************************/ static proc mindegInt( ideal I ) { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "mindegInt", I ); } /*4DEBUG*/ intmat D = mindeg(I); int min = D[1, 1]; int m; for( int c = 2; c <= ncols(D); c++ ) { m = D[1, c]; if( m < min ) { min = m; } } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "mindegInt", min ); } /*4DEBUG*/ return( min ); } /******************************************************/ // 'subalgebra basis' computation proc sa_reduce( ideal V ) " USAGE: sa_reduce(V); V ideal RETURN: ideal, generated by computed elements PURPOSE: compute a subalgebra basis of an algebra generated by the elements of V NOTE: At the moment the usage of this procedure is limited to G-algebras SEE ALSO: sa_poly_reduce EXAMPLE: example sa_reduce; shows an example " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "sa_reduce", V ); } /*4DEBUG*/ ideal result = ideal(); ideal FLM = INTERRED( V ); // The output is sorted "[1]<[2]<[3]<..." // We are bounded by maximal degree!!! int D = maxdegInt( FLM ); // Init list FOUND_LEADING_MONOMIALS = list(); int i; for( i = 1; i <= D; i++ ) { FOUND_LEADING_MONOMIALS[i] = ideal(); } int d, j, l; poly p, q; ideal T; int c = 1; // polynomials in FLM commute pairwise for( j = 1; (j < size(FLM)) and (c == 1); j++ ) { p = FLM[j]; for( l = j+1; (l <= size(FLM)) and (c == 1); l++ ) { q = FLM[l]; if( NF(p*q - q*p, twostd(0)) != 0 ) { c = 0; // There exists non-commuting pair } } } while( size(FLM) > 0 ) { // FLM; // Take the 1st element of FLM... p = FLM[1]; // SANF( FLM[1], FOUND_LEADING_MONOMIALS ); FLM[1] = 0; // ...and kill it from FLM d = maxdegInt( p ); T = ideal(p); // d; size(FOUND_LEADING_MONOMIALS); if( d > 0 ) { FOUND_LEADING_MONOMIALS[d] = FOUND_LEADING_MONOMIALS[d] + T; for( j = 1; j <= D; j = j + d ) // For every degree (j*d) of T, do: { for( l = j; (l + d) <= D; l++ ) { FOUND_LEADING_MONOMIALS[l+d] = FOUND_LEADING_MONOMIALS[l+d] + FOUND_LEADING_MONOMIALS[l] * T; if( c != 1 ) { FOUND_LEADING_MONOMIALS[l+d] = FOUND_LEADING_MONOMIALS[l+d] + T * FOUND_LEADING_MONOMIALS[l]; } } } } if( size(FLM) > 0 ) { for( i = 2; i <= ncols(FLM); i++ ) { FLM[i] = SANF( FLM[i], FOUND_LEADING_MONOMIALS ); } FLM = INTERRED( FLM ); } if( size(T) > 0 ) { DBPrint(1, "Found: " + string(T) ); result = result + T; } } result = makeNice(result); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "sa_reduce", result ); } /*4DEBUG*/ return( result ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) poly f = 4*x*y+z^2-2*z; // a central polynomial ideal I = f, f*f, f*f*f - 10*f*f, f+3*z^3; I; sa_reduce(I); // should be just f and z^3 } /******************************************************/ // subalgebra reduction of a polynomial proc sa_poly_reduce( poly p, ideal V ) " USAGE: sa_poly_reduce(p, V); p poly, V ideal RETURN: polynomial, a reduction of p w.r.t. V PURPOSE: computes a reduction of the polynomial p w.r.t. the subalgebra generated by elements of V NOTE: At the moment the usage of this procedure is limited to G-algebras SEE ALSO: sa_reduce EXAMPLE: example sa_poly_reduce; shows an example " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "sa_poly_reduce", p, V ); } /*4DEBUG*/ // As previous... ideal FLM = INTERRED( V ); // The output is sorted "[1]<[2]<[3]<..." // We are bounded by maximal degree!!! int D = maxdegInt( FLM + ideal(p) ); // Init list FOUND_LEADING_MONOMIALS = list(); int i; for( i = 1; i <= D; i++ ) { FOUND_LEADING_MONOMIALS[i] = ideal(); } int d, j, l; poly f, q; ideal T; int c = 1; // polynomials in FLM commute pairwise for( j = 1; (j < size(FLM)) and (c == 1); j++ ) { f = FLM[j]; for( l = j+1; (l <= size(FLM)) and (c == 1); l++ ) { q = FLM[l]; if( NF(f*q - q*f, twostd(0)) != 0 ) { c = 0; } } } while( size(FLM) > 0 ) { // Take the 1st element of FLM... q = SANF( FLM[1], FOUND_LEADING_MONOMIALS ); FLM[1] = 0; // ...and kill it from FLM d = maxdegInt(q); T = ideal(q); FOUND_LEADING_MONOMIALS[d] = FOUND_LEADING_MONOMIALS[d] + T; for( j = 1; j <= D; j = j + d ) // For every degree (j*d) of T, do: { for( l = j; (l + d) <= D; l++ ) { FOUND_LEADING_MONOMIALS[l+d] = FOUND_LEADING_MONOMIALS[l+d] + FOUND_LEADING_MONOMIALS[l] * T; if( c != 1 ) { FOUND_LEADING_MONOMIALS[l+d] = FOUND_LEADING_MONOMIALS[l+d] + T * FOUND_LEADING_MONOMIALS[l]; } } } if( size(FLM) > 0 ) { for( i = 2; i <= ncols(FLM); i++ ) { FLM[i] = SANF( FLM[i], FOUND_LEADING_MONOMIALS ); } FLM = INTERRED( FLM ); } } poly result = SANF(p, FOUND_LEADING_MONOMIALS); result = makeNice( result ); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "sa_poly_reduce", result ); } /*4DEBUG*/ return( result ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) poly f = 4*x*y+z^2-2*z; // a central polynomial sa_poly_reduce(f + 3*f*f + x, ideal(f) ); // should be just 'x' } /******************************************************/ // ::inStuff:: inCentralizer, inCenter, isCartan helpers /******************************************************/ /******************************************************/ static proc inCentralizer_poly( poly p, ideal S ) " if p in centralizer(S) => return 1, otherwise return 0 " { poly f; for( int k = 1; k <= size(S); k++ ) { f = S[k]; if( NF( f * p - p * f, twostd(0) ) != 0 ) { DBPrint( 1, "POLY: " + string (p) + " is NOT in the centralizer of polynomial {" + string(f) + "}" ); return (0); } } return( 1 ); } /******************************************************/ static proc inCentralizer_list( def l, ideal S ) { for( int @i = 1; @i <= size(l); @i++ ) { if( (typeof(l[@i])=="poly") or (typeof(l[@i]) == "int") or (typeof(l[@i]) == "number") ) { if(! inCentralizer_poly(l[@i], S) ) { return(0); } } else { if( (typeof(l[@i])=="list") or (typeof(l[@i])=="ideal") ) { if(! inCentralizer_list(l[@i], S) ) { return(0); } } } } return(1); } /******************************************************************************/ // Checks the commutativity of polynomials of a with the polynomials in S proc inCentralizer( def a, ideal S ) " USAGE: inCentralizer(E, S); E poly/list/ideal, S poly/ideal RETURN: integer, 1 if E is in the centralizer(S), 0 otherwise PURPOSE: check whether the elements of E are in the centralizer(S) EXAMPLE: example inCentralizer; shows examples " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "inCentralizer", a, S ); } /*4DEBUG*/ if( nameof( basering ) == "basering" ) { // ERROR( "No current ring!" ); } int res; if( (typeof(a) == "poly") or (typeof(a) == "int") or (typeof(a) == "number") ) { res = inCentralizer_poly(a, S); } else { if( (typeof(a)=="list") or (typeof(a)=="ideal") ) { res = inCentralizer_list(a, S); } else { res = -1; } } if( res == -1 ) { ERROR( "Wrong argument!" ); } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "inCentralizer", res ); } /*4DEBUG*/ return (res); } example { "EXAMPLE:";echo=2; ring R = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; def r = nc_algebra(1,D); setring r; // the Heisenberg algebra poly f = x^2; poly a = z; // 'z' is central => it lies in every centralizer! poly b = y^2; inCentralizer(a, f); inCentralizer(b, f); list l = list(1, a); inCentralizer(l, f); ideal I = a, b; inCentralizer(I, f); printlevel = 2; inCentralizer(a, f); // yes inCentralizer(b, f); // no } /******************************************************/ // Checks the centrality of a proc inCenter( def a ) " USAGE: inCenter(E); E poly/list/ideal RETURN: integer, 1 if E is in the center, 0 otherwise PURPOSE: check whether the elements of E are central EXAMPLE: example inCenter; shows examples " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "inCenter", a ); } /*4DEBUG*/ if( nameof( basering ) == "basering" ) { // ERROR( "No current ring!" ); } int result = inCentralizer( a, variablesStandard() ); /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "inCenter", result ); } /*4DEBUG*/ return( result ); } example { "EXAMPLE:";echo=2; ring R=0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def r = nc_algebra(1,D); setring r; // this is U(sl_2) poly p=4*x*y+z^2-2*z; inCenter(p); poly f=4*x*y; inCenter(f); list l= list( 1, p, p^2, p^3); inCenter(l); ideal I= p, f; inCenter(I); } /******************************************************/ // Checks whether f is a Cartan element. proc isCartan( poly f ) " USAGE: isCartan(f); f poly PURPOSE: check whether f is a Cartan element. RETURN: integer, 1 if f is a Cartan element and 0 otherwise. NOTE: f is a Cartan element of the algebra A @* if and only if for all g in A there exists C in K such that [f, g] = C * g @* if and only if for all variables v_i there exist C in K such that [f, v_i] = C * v_i. " { /*4DEBUG*/ if( defined( @@@DEBUG ) ){ BCall( "isCartan", f ); } /*4DEBUG*/ if( nameof( basering ) == "basering" ) { // ERROR( "No current ring!" ); } ideal V = variablesStandard(); int r = 1; poly v, g; for( int i = size(V); i > 0; i-- ) { v = leadmonom(V[i]); // V[i] must be just a variable, but... g = NF( f*v - v*f, twostd(0) ); // [f, V[i]] if( size(g) > 0 ) { if( size(g) > 1 ) // it is not just \alpha * v_i. { r = 0; break; } if( leadmonom(g) != v ) // g = \alpha * v_j, j != i. { r = 0; break; } } // else \alpha = 0 } /*4DEBUG*/ if( defined( @@@DEBUG ) ){ ECall( "isCartan", r ); } /*4DEBUG*/ return( r ); } example { "EXAMPLE:";echo=2; ring R=0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def r = nc_algebra(1,D); setring r; // this is U(sl_2) with cartan - z isCartan(z); // yes! poly p=4*x*y+z^2-2*z; isCartan(p); // central elements are Cartan elements! poly f=4*x*y; isCartan(f); // no way! isCartan( 10 + p + z ); // scalar + central + cartan } /******************************************************/ /******************************************************/ // ::MainAliases:: The main non-static functions, visible to user are here. They are wrappers around basic functions. /******************************************************/ /******************************************************/ /******************************************************/ // Computes the generators of the center of a basering proc center( int D, list # ) " USAGE: center(D[, N]); D int, N optional int RETURN: ideal, generated by computed elements PURPOSE: computes subalgebra generators of the center up to degree D NOTE: In general, one cannot compute the whole center. @* Hence, one has to specify a termination condition via arguments D and/or N. @* If D is positive, only central elements up to degree D will be found. @* If D is negative, the termination is determined by N only. @* If N is given, the computation stops if at least N elements have been found. @* Warning: if N is given and bigger than the actual number of generators, @* the procedure may not terminate. @* Current ordering must be a degree compatible well-ordering. SEE ALSO: centralizer; inCenter EXAMPLE: example center; shows an example " { if( nameof( basering ) == "basering" ) { // ERROR( "No current ring!" ); } if( DefaultInt( # ) > 0 ) { return( centerRed( D, # ) ); } if( D >= 0 ) { return( sa_reduce( centerVS(D) ) ); // Experimental! May be wrong!!! } ERROR( "Wrong arguments!" ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z,t),dp; matrix D[4][4]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) tensored with K[t] // find generators of the center of degree <= 3: ideal Z = center(3); Z; inCenter(Z); // check the result // find at least one generator of the center: ideal Z2 = center(-1, 1); Z2; inCenter(Z2); // check the result } /******************************************************/ // Computes the generators of the centralizer of S in a basering proc centralizer( ideal S, int D, list # ) " USAGE: centralizer(F, D[, N]); F poly/ideal, D int, N optional int RETURN: ideal, generated by computed elements PURPOSE: computes subalgebra generators of centralizer(F) up to degree D NOTE: In general, one cannot compute the whole centralizer(F). @* Hence, one has to specify a termination condition via arguments D and/or N. @* If D is positive, only centralizing elements up to degree D will be found. @* If D is negative, the termination is determined by N only. @* If N is given, the computation stops if at least N elements have been found. @* Warning: if N is given and bigger than the actual number of generators, @* the procedure may not terminate. @* Current ordering must be a degree compatible well-ordering. SEE ALSO: center; inCentralizer EXAMPLE: example centralizer; shows an example " { if( nameof( basering ) == "basering" ) { // ERROR( "No current ring!" ); } if( DefaultInt( # ) > 0 ) { return( centralizerRed( S, D, # ) ); } if( D >= 0 ) { return( sa_reduce( centralizerVS(S, D) ) ); // Experimental! May be wrong!!! } ERROR( "Wrong arguments!" ); } example { "EXAMPLE:"; echo = 2; ring AA = 0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def A = nc_algebra(1,D); setring A; // this algebra is U(sl_2) poly f = 4*x*y+z^2-2*z; // a central polynomial f; // find generators of the centralizer of f of degree <= 2: ideal c = centralizer(f, 2); c; // since f is central, the answer consists of generators of A inCentralizer(c, f); // check the result // find at least two generators of the centralizer of f: ideal cc = centralizer(f,-1,2); cc; inCentralizer(cc, f); // check the result poly g = z^2-2*z; // some non-central polynomial // find generators of the centralizer of g of degree <= 2: c = centralizer(g, 2); c; inCentralizer(c, g); // check the result // find at least one generator of the centralizer of g: centralizer(g,-1,1); // find at least two generators of the centralizer of g: cc = centralizer(g,-1,2); cc; inCentralizer(cc, g); // check the result } /******************************************************* // normally one should use this library together with ncalg.lib in the following way: LIB "ncalg.lib"; def Usl3 = makeUsl(3); // U(sl_3) setring Usl3; // show current ring: basering; LIB "central.lib"; // easy example(few seconds), must compute two polynomials of degrees 2 and 3. center(3); kill Usl3; def Ug2 = makeUg2(); // U(g_2) setring Ug2; // show current ring: basering; // easy example(few seconds), must compute one polynomial of degree 2. center(2); // hard example (~hours), must compute two polynomials of degrees 2 and 6. center(6); quit; *******************************************************/ singular-4.0.3+ds/Singular/LIB/chern.lib000066400000000000000000002767611266270727000177610ustar00rootroot00000000000000//////////////////////////////////////////////////////////////// version = "version chern.lib 0.6 Oct_2015 "; //$Id:$ category = "Chern classes"; info=" LIBRARY: chern.lib Symbolic Computations with Chern classes AUTHOR: Oleksandr Iena, oleksandr.iena@uni.lu, yena@mathematik.uni-kl.de REFERENCES: [1] Iena, Oleksandr, On symbolic computations with Chern classes: remarks on the library chern.lib for Singular, http://hdl.handle.net/10993/22395, 2015 [2] Lascoux, Alain, Classes de Chern d'un produit tensoriel. C. R. Acad. Sci., Paris, Ser. A 286, 385-387 (1978). PROCEDURES: symm(l [,N]); symmetric functions in the entries of l symNsym(f, c); symmetric and non-symmetric parts of a polynomial f CompleteHomog(N, l); complete homogeneous symmetric functions segre(N, c); Segre classes in terms of Chern classes chern(N, s); Chern classes in terms of Segre classes chNum(N, c); the non-zero Chern numbers in degree N in the entries of c chNumbers(N, c); the Chern numbers in degree N in the entries of c sum_of_powers(k, l); the sum of k-th powers of the entries of l powSumSym(c [,N]); the sums of powers [up to degree N] in terms of the elementary symmetric polynomials (entries of l) chAll(c [,N]); Chern character in terms of the Chern classes chAllInv(c); Chern classes in terms of the Chern character chHE(c); the highest term of the Chern character ChernRootsSum(a, b); the Chern roots of a direct sum chSum(c, C); the Chern classes of a direct sum ChernRootsDual(l); the Chern roots of the dual vector bundle chDual(c); the Chern classes of the dual vector bundle ChernRootsProd(l, L); the Chern roots of a tensor product of vector bundles chProd(r, c, R, C [,N]); Chern classes of a tensor product of vector bundles chProdE(c, C); Chern classes of a tensor product of vector bundles chProdL(r, c, R, C); Chern classes of a tensor product of vector bundles chProdLP(r, c, R, C); total Chern class of a tensor product of vector bundles ChernRootsHom(l, L); the Chern roots of a Hom vector bundle chHom(r, c, R, C [,N]); Chern classes of the Hom-vector bundle ChernRootsSymm(n, l); the Chern roots of the n-th symmetric power of a vector bundle with Chern roots from l ChernRootsWedge(n, l); the Chern roots of the n-th exterior power of a vector bundle with Chern roots from l chSymm(k, r, c [,p]); the rank and the Chern classes of the k-th symmetric power of a vector bundle of rank r with Chern classes c chSymm2L(r, c); the rank and the Chern classes of the second symmetric power of a vector bundle of rank r with Chern classes c chSymm2LP(r, c); the total Chern class of the second symmetric power of a vector bundle of rank r with Chern classes c chWedge(k, r, c [,p]); the rank and the Chern classes of the k-th exterior power of a vector bundle of rank r with Chern classes c chWedge2L(r, c); the rank and the Chern classes of the second exterior power of a vector bundle of rank r with Chern classes c chWedge2LP(r, c); the total Chern class of the second exterior power of a vector bundle of rank r with Chern classes c todd(c [,n]); the Todd class toddE(c); the highest term of the Todd class Bern(n); the second Bernoulli numbers tdCf(n); the coefficients of the Todd class of a line bundle tdTerms(n, f); the terms of the Todd class of a line bundle coresponding to the Chern root t tdFactor(n, t); the Todd class of a line bundle coresponding to the Chern root t cProj(n); the total Chern class of (the tangent bundle on) the projective space P_n chProj(n); the Chern character of (the tangent bundle on) the projective space P_n tdProj(n); the Todd class of (the tangent bundle on) the projective space P_n eulerChProj(n, r, c); Euler characteristic of a vector bundle on the projective space P_n via Hirzebruch-Riemann-Roch theorem chNumbersProj(n); the Chern numbers of the projective space P_n classpoly(l, t); polynomial in t with coefficients from l (without constant term) chernPoly(l, t); Chern polynomial (constant term 1) chernCharPoly(r, l, t); polynomial in t corresponding to the Chern character (constant term r) toddPoly(td, t); polynomial in t corresponding to the Todd class (constant term 1) rHRR(N, ch, td); the main ingredient of the right-hand side of the Hirzebruch-Riemann-Roch formula SchurS(I, S); the Schur polynomial corresponding to partition I in terms of the Segre classes S SchurCh(I, C); the Schur polynomial corresponding to partition I in terms of the Chern classes C part(m, n); partitions of integers not exceeding n into m non-negative summands dualPart(I [,N]); partition dual to I PartC(I, m); the complement of a partition with respect to m partOver(n, J); partitions over a given partition J with summands not exceeding n partUnder(J); partitions under a given partition J "; LIB "general.lib"; //---------------------------------------------------------- proc symm(list l, list #) "USAGE: symm(l [,n]); l a list of polynomials, n integer RETURN: list of polynomials PURPOSE: computes the list of elementary symmetric functions in the entries of l EXAMPLE: example symm; shows an example NOTE: makes sense only for a list of polynomials " { int N=size(l); int n=size(l); if(size(#)!=0) { if( is_integer(#[1]) ) { N = #[1]; } } if(n==0) // if the list is empty, return the empty list { return(list()); } else { int i, j; list rez=list(1, l[1]); for(i=2; i<=n; i++) { if( i<=N ) { rez=rez+list(0); } for(j = min(i, N); j>=1; j--) { rez[j+1] = rez[j+1] + rez[j]*l[i]; } } return(delete(rez, 1)); } } example { "EXAMPLE:";echo =2; // elementary symmetric functions in x, y, z: ring r = 0, (x, y, z), dp; list l=(x, y, z); print(symm(l)); //now let us compute only the first two symmetric polynomials in a(1), ... , a(10) ring q= 0,(a(1..10)), dp; list l=a(1..10); print(symm(l, 2)); } //----------------------------------------------------------------------- proc symNsym(poly f, list c) "USAGE: symNsym(f, c); f polynomial; c list of polynomials RETURN: list with 2 poly entries PURPOSE: computes a symmetric and a non-symmetric part of f in terms of the elementary symmetric functions from c as well a non-symmetric remainder EXAMPLE: example symNsym; shows an example NOTE: constants are not considered symmetric " { ideal V=variables(f); // variables f depends on int nV=size(V); // their number if(nV==0) { return(list(f, 0)); } // now f is non-constant and does depend on some variables c=append_by_zeroes(nV, c); // append c by zeroes if it is too short def br@=basering; // remember the base ring // add additional variables to the base ring execute("ring r@= ("+ charstr(basering) +"),("+varstr(basering)+",c@(1..nV),A@(1..nV)), dp;" ); execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings ideal V=F(V); poly f=F(f); int i; for(i=1; i<=nV; i++) { f=subst(f, V[i], A@(i) ); // rename the variables of f into A@(1..nV) } int N1=nvars(basering)-nV+1; // the number of variable A@(1) poly rez1=0; // to be the expression in c@(i) of the symmetric part of f poly rez2=0; // to be the remainder poly mon; // monomial in c@(i) poly monc; // the corresponding expression in A@(i) list l=symm(list(A@(1..nV) )); // symmetric functions in A@(i) intvec v=leadexp(f), 0; // the exponent of the leading monomial while(v[N1]!=0) { mon=leadcoef(f); // leading coefficient of f monc=mon; for(i=1; v[N1+i-1]!=0 ;i++ ) { mon = mon*c@(i)^( v[N1+i-1]-v[N1+i] ); monc = monc*l[i]^( v[N1+i-1]-v[N1+i] ); // has the same leading coefficient as f } rez1=rez1+mon; // add a monomial f=f-monc; // subtract the monomial v=leadexp(f), 0; } while( leadexp(f)!=0 ) { rez2=rez2+lead(f); f=f-lead(f); } rez1=rez1+f; setring br@; // come back to the initial base ring // define the specialization homomorphism execute("map FF = r@,"+varstr(br@)+",c[1..nV], V[1..nV];"); return( list( FF(rez1), FF(rez2) ) ); } example { "EXAMPLE:";echo=2; ring r=0, (x,y,z, c(1..3)), dp; list l=c(1..3); // The symmetric part of f = 3x2 + 3y2 + 3z2 + 7xyz + y // in terms of the elemenatary symmetric functions c(1), c(2), c(3) // and the remainder poly f = 3x2 + 3y2 + 3z2 + 7xyz + y; print( symNsym(f, l) ); // Take a symmetrix polynomial in variables x and z f=x2+xz+z2; // Express it in terms of the elementary the symmetric functions print( symNsym(f, l)[1]); } //------------------------------------------------------------------------------------------- proc CompleteHomog(int N, list c) "USAGE: CompleteHomog(N, c); N integer, c list of polynomials RETURN: list of polynomials PURPOSE: computes the list of the complete homogeneous symmetric polynomials in terms of the elementary symmetric polynomials (entries of c) EXAMPLE: example CompleteHomog; shows an example NOTE: " { c=append_by_zeroes(N, c); if(N<0) // if N is negative, return the empty list { return(list()); } list rez=list(1); // the result will be computed here int i, j; int sign; poly f; for(i=1; i<=N; i++) // use the resursive formula { f=0; sign=1; for(j=1;j<=i; j++) // compute the next complete homogeneous symmetric polynomial { f=f+sign*c[j]*rez[i-j+1]; sign=-sign; } rez=rez+( list(f) ); } return(rez); } example { "EXAMPLE:";echo =2; ring r = 0, (x(1..3)), dp; list l=x(1..3); //Complete homogeneous symmetric polynomials up to degree 3 in variables x(1), x(2), x(3) print( CompleteHomog(3, l) ); } //----------------------------------------------------------------------- proc segre(list c, list #) "USAGE: segre(c[, N]); c list of polynomials, N integer RETURN: list of polynomials PURPOSE: computes the list of the Segre classes up to degree N in terms of the Chern classes from c EXAMPLE: example segre; shows an example NOTE: " { int N; if(size(#)>0) { if( is_integer(#[1]) ) { N=#[1]; } } else { N=size(c); } c=append_by_zeroes(N, c); if(N<0) // if N is negative, return the empty list { return(list()); } list rez=list(1); // the result will be computed here int i, j; poly f; for(i=1; i<=N; i++) // use the resursive formula { f=0; for(j=1;j<=i; j++) // compute the next Segre class { f=f-c[j]*rez[i-j+1]; } rez=rez+( list(f) ); } return(delete(rez,1)); } example { "EXAMPLE:";echo =2; ring r = 0, (c(1..3)), dp; list l=c(1..3); //Segre classes up to degree 5 in Chern classes c(1), c(2), c(3) print( segre(l, 5) ); } //----------------------------------------------------------------------- proc chern(list s, list #) "USAGE: chern(s); s list of polynomials RETURN: list of polynomials PURPOSE: computes the list of the Chern classes up to degree N in terms of the Segre classes from s EXAMPLE: example chern; shows an example NOTE: " { return( segre(s, #) ); } example { "EXAMPLE:"; echo =2; ring r = 0, (s(1..3)), dp; list l=s(1..3); // Chern classes in Segre classes s(1), s(2), s(3) print( chern(l) ); // This procedure is inverse to segre(...). Indeed: print( segre(chern(l), 3) ); } //----------------------------------------------------------------------- proc chNum(int N, list c) "USAGE: chNun(N, c); N integer, c list RETURN: list PURPOSE: computes the Chern numbers of a vector bundle with Chern classes c on a complex manifold (variety) of dimension N, the zeroes corresponding to the higher zero Chern classes are ignored EXAMPLE: example chNumbers; shows an example NOTE: computes basically the partitions of N in summands not greater than the length of c " { int n=size(c); if(N<0) { print(""); return( list() ); } if( (n==0) || (N==0) ) { return(list(1)); } if(n==1) // if there is only one entry in the list { return(list(c[1]^N)); } int i; int j; poly f; // the powers of the last variable will be stored here list l=delete(c, n); // delete the last variable list L; list rez=chNum(N, l); // monomials not involving the last variable for(i=1;i<=(N div n); i++) // add the monomials involving the last variable { f=c[n]^i; // the power of the last variable // monomials without the last variable that, // multiplied by the i-th power of the last variable, // give a monomial of the required type L=chNum(N-n*i, l); for(j=1; j<=size(L) ;j++) // multiply every such monomial { L[j]=L[j]*f; // by the i-th power of the last variable } rez=rez+L; // add the monomials involving the i-th power of the last variable } return(rez); } example { "EXAMPLE:";echo=2; ring r = 0, (c(1..2)), dp; list l=c(1..2); // Let c(1) be a variable of degree 1, let c(2) be a variable of degree 2. // The monomials in c(1) and c(2) of weighted degree 5 are: print( chNum( 5, l ) ); // Compare the result to the output of chNumbers(...): print( chNumbers(5, l) ); } //---------------------------------------------------------------------------------------- proc chNumbers(int r, list c) "USAGE: chNumbers(r, c); r integer, c list RETURN: list PURPOSE: computes the Chern numbers of a vector bundle with Chern classes c on a complex manifold (variety) of dimension r EXAMPLE: example chNumbers; shows an example NOTE: computes basically the patitions of r " { if(r<0) { print("The dimension of a manifold must be a non-negative integer!"); return(list()); // return the empty list in this case } if(r==0) { return(list(1)); } //----------------- // from now on r>0 //---------------- int n=size(c); c=append_by_zeroes(r, c); c=c[1..r]; // throw away redundant data return(chNum(r, c)); } example { "EXAMPLE:";echo=2; ring r = 0, (c(1..3)), dp; list l=c(1..3); // The Chern numbers of a vector bundle with Chern classes c(1), c(2), c(3) // on a 3-fold: print( chNumbers( 3, l ) ); // If the highest Chern class is zero, the Chern numbers are: l=c(1..2); print( chNumbers( 3, l ) ); // Compare this to the output of chNum(...): print( chNum( 3, l ) ); } //--------------------------------------------------------------------------------------- proc sum_of_powers(int k, list l) "USAGE: sum_of_powers(k, l); k non-negative integer, l list of polynomials RETURN: polynomial PURPOSE: computes the sum of k-th powers of the entries of l EXAMPLE: example sum_of_powers; shows an example NOTE: returns 0 if k is negative " { if(k<0) // return 0 if k is negative { print("The exponent must be non-negative; 0 has been returned"); return(0); } int i; int n=size(l); poly rez; // the result will be computed here for(i=1;i<=n;i++) // compute the sum of powers { rez=rez+l[i]^k; } return(rez); } example { "EXAMPLE:";echo =2; ring r = 0, (x, y, z), dp; list l=x, y, z; //sum of 7-th powers of x, y, z print( sum_of_powers(7, l) ); } //----------------------------------------------------------------------- proc powSumSym(list c, list #) "USAGE: powSumSym(l [,N]); l a list of polynomials, N integer RETURN: list of polynomials PURPOSE: computes the expressions for the sums of powers [up to degree N] in terms of the elementary symmetric polynomials (entries of l), EXAMPLE: example powSumSym; shows an example NOTE: returns the terms of the Chern character multiplied by the correspoding factorials " { int n; if( size(#) == 0 ) // if there are no optional parameters { n = size(c); // set n to be the length of c } else // if there are optional parameters { if( is_integer(#[1])) // if the first optional parameter is an integer { n = max( #[1], 0 ); // if the parameter is negative, reset it to be zero c = append_by_zeroes(n, c); // if n is greater than the length of c, append c by zeroes if( n != 0 ) // if n is non-zero { c = c[1..n]; // take into account only the first n entries of c } } else // if the optional parameter is not an integer, then { n=size(c); // ingore it and set n to be the length of c } } list rez; // the result will be computed here if(n==0) // return the empty list { return(rez) } else // otherwise proceed as follows: { // first compute the sums of powers of the Chern roots // in terms of the Chern classes using the Newton's identities int i, j, sign; poly f; // the first term of the Chern character coincides with the first Chern class, // or equivalently with the sum of Chern roots rez = rez + list(c[1]); // compute the sums of powers of Chern roots recursively using the Newton's identities for(j=2; j<=n; j++) { sign=1; f=0; for(i=1; i 0 if it is an integer; R > 0 if it is an integer //---------------------------------------------------------- int n; if( is_integer(r) && is_integer(R) ) // if both r and R are integers { n=r*R; // set n to be the rank of the product bundle } else // otherwise define the rank of the product vector bundle by { n=size(c)*size(C); // looking at the lenghts of c and C } if( size(#) != 0 ) // if there is an optional parameter { if( is_integer( #[1] ) ) // if this parameter is an integer { if( #[1]<=0 ) // if it is negative or zero, return the empty list { return( list() ); } // now #[1] is positive // the product bundle can only have non-zero Chern classes up to degree n // so ignore the optional parameter if it is greater than n n = min(#[1], n); } } if(n==0) // if n is zero, return the empty list { return( list() ); } //----------------------------------------------------------- //now n is positive, we can perform the relevant computations //----------------------------------------------------------- int i, j; c=append_by_zeroes(n, c); // append c by zeroes up to degree n C=append_by_zeroes(n, C); // append C by zeroes up to degree n c=c[1..n]; // throw away the redundant data if needed C=C[1..n]; // throw away the redundant data if needed // build the list of all terms of the Chern characters: for rank r, and Chern classes c list ch = list(r) + chAll(c); list CH = list(R) + chAll(C); // do the same for rank R and Chern classes C poly f; list chP; // compute the list of the non-zero degree terms of the Chern character // of the tensor product of two vector bundles for(i=1;i<=n;i++) // using the multiplicativity of the Chern character { f=0; for(j=0;j<=i;j++) { f=f+ch[j+1]*CH[i-j+1]; } chP=chP+list(f); } return( chAllInv(chP) ); // return the corresponding Chern classes } example { "EXAMPLE:"; echo =2; ring H = 0, ( r, R, c(1..3), C(1..2) ), dp; list l=c(1..3); list L=C(1..2); // the Chern classes of the tensor product of a vector bundle E of rank 3 // with Chern classes c(1), c(2), c(3) // and a vector bundle F of rank 2 with Chern classes C(1) and C(2): print( chProd(3, l, 2, L) ); // the first two Chern classes of the tensor product // of a vector bundle E of rank r with Chern classes c(1) and c(2) // and a vector bundle G of rank R with Chern classes C(1) and C(2) // this gives the Chern classes of a tensor product on a complex surface l=c(1..2); L=C(1..2); print( chProd(r, l, R, L, 2 ) ); } //--------------------------------------------------------------------------------- proc chProdE(list c, list C) "USAGE: chProdE(c, C); c, C lists of polynomials RETURN: list of polynomials PURPOSE: computes the list of Chern classes of the product of two vector bundles in terms of their Chern clases EXAMPLE: example chProdE; shows an example NOTE: makes sense only for (lists of) polynomials; uses elimination, hence very inefficient; included only for comparison with chProd(...) " { int r=size(c); int R=size(C); if( (r==0) && (R==0) ) // if one of the ranks is 0, { return( list() ); // return the empty list (zero bundles have no Chern classes) } //------------------------------------ //now both r and R are greater than 0 //------------------------------------ int n=r*R; // the rank of the product of two vector bundles def br@=basering; // remember the base ring // add additional variables a@(1..r), b@(1..R), x@ to the base ring execute("ring r@=("+ charstr(basering) +"),("+varstr(basering)+",a@(1..r),b@(1..R),x@ ), ls;"); execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings list c=F(c); // embedd c in the bigger ring list C=F(C); // embedd C in the bigger ring list A=a@(1..r); // list of Chern roots of the first vector bundle list syma = symm(A); // symmetric functions in the Chern roots of the first vector bundles list B=b@(1..R); // list of Chern roots of the second vector bundle list symb=symm(B); // symmetric functions in the Chern roots of the second vector bundles ideal I; int i, j; // the product of variables (all Chern roots) which should be eliminated poly E=product(A)*product(B); for(i=1; i<=r; i++) { for(j=1; j<=R; j++) { I=I, c[i]-syma[i], C[j]-symb[j]; // add the relations } } // the Chern roots of the tensor product in terms of the Chern roots of the factors list crt=ChernRootsProd(A, B); list Cf=symm(crt); // Chern classes of the product in terms of the Chern roots of the factors list rez; // the result will be computed here ideal J; for(i=1;i<=n;i++) { J = I, x@-Cf[i]; // add the equation for the i-th Chern class to the ideal of relations J = elim(J, E); // eliminate the Chern roots // get the expression for the i-th Chern class of the product // in terms of the Chern classes of the factors rez = rez + list( -subst(J[1], x@, 0) ); } setring br@; // come back to the initial base ring execute( "map FF= r@,"+varstr(br@)+";" ); // define the specialization homomorphism t@=0 list rez=FF(rez); // bring the result to the base ring return(rez); // return the corresponding Chern classes } example { "EXAMPLE:"; echo =2; ring H = 0, ( c(1..3), C(1..2) ), dp; list l=c(1..3); list L=C(1..2); // the Chern classes of the tensor product of a vector bundle E of rank 3 // with Chern classes c(1), c(2), c(3) // and a vector bundle F of rank 2 with Chern classes C(1) and C(2): print( chProdE(l, L) ); } //------------------------------------------------------------------------------------ proc chProdL(int r, list c, int R, list C) "USAGE: chProdL(r, c, R, C); r, R integers; c, C lists of polynomials RETURN: list PURPOSE: computes the list of Chern classes of the product of two vector bundles in terms of their Chern clases EXAMPLE: example chProdL; shows an example NOTE: Implementation of the formula of Lascoux, the Schur polynomials are computed using the second Jacobi-Trudi formula (in terms of the Chern classes) " { // check the input data if(r<=0) // if r is negative or zero return the empty list { return( list() ); } //---------------------------- //now r is a positive integer //---------------------------- c=append_by_zeroes(r, c); // append c by zeroes if r is greater than the length of c c=c[1..r]; // make c shorter (of length r) if r is smaller than the length of c if(R<=0) // if R is negative or zero return the empty list { return( list() ); } //---------------------------- //now R is a positive integer //---------------------------- C=append_by_zeroes(R, C); // append C by zeroes if R is greater than the length of C C=C[1..R]; // make C shorter (of length R) if R is smaller than the length of C //---------------------------------------------------------- // now r > 0 and R > 0 //---------------------------------------------------------- def br@=basering; // remember the base ring // add additional variables to the base ring execute("ring r@=("+charstr(basering)+"), ("+varstr(basering)+", t@, c@(1..r), C@(1..R)), dp;"); execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings list c, C; int i; for(i=1;i<=r;i++) { c[i]=c@(i)*t@^i; } for(i=1;i<=R;i++) { C[i]=C@(i)*t@^i; } poly f = chProdLP(r,c,R,C); // get the total Chern class using the Lascoux formula matrix CF = coeffs(f, t@); // get its coefficients in front of the powers of t@ int N=r*R; list rez; // write them in a list for(i=1;i<=N;i++) { rez=rez+list(CF[i+1,1]); } setring br@; // come back to the initial base ring // define the specialization homomorphism execute("map FF = r@,"+varstr(br@)+",0, c[1..r], C[1..R];"); return( FF( rez ) ); // bring the result to the initial ring } example { "EXAMPLE:"; echo =2; // The Chern classes of the tensor product of a vector bundle of rank 3 // with Chern classes c(1), c(2), c(3) and a vector bundle of rank 1 with // Chern class C(1) ring r = 0, ( c(1..3), C(1)), dp; list c=c(1..3); list C=C(1); print( chProdL(3,c,1,C) ); } //--------------------------------------------------------------------------------------- proc chProdLP(int r, list c, int R, list C) "USAGE: chProdLP(r, c, R, C); r, R integers; c, C lists of polynomials RETURN: polynomial PURPOSE: computes the total Chern class of the product of two vector bundles in terms of their ranks and Chern clases EXAMPLE: example chProdLP; shows an example NOTE: Implementation of the formula of Lascoux, the Schur polynomials are computed using the second Jacobi-Trudi formula (in terms of the Chern classes) " { if(r<=0) // if r is negative or zero, return 1 { return( 1 ); } if(R<=0) // if R is negative or zero, return 1 { return( 1 ); } //------------------------------------------- // now r and R are positive //------------------------------------------- c=append_by_zeroes(r, c); C=append_by_zeroes(R, C); c=c[1..r]; C=C[1..R]; list P; P=part(r, R); // compute the partitions of numbers up to R into r summands int sz=size(P); // number of such partitions int szu; int i, j; list T; list PU; list TU; poly rez; // the result will be computed here poly ST; // implement the formula of Lascoux: for(i=1;i<=sz;i++) // run through all the partitions from P { T=P[i]; // the current partition ST= SchurS( PartC(T, R) , C ); // compute the corresponding Schur polynomial PU=partUnder(T); // compute the partitions under T szu=size(PU); // number of such partitions for(j=1;j<=szu;j++) // run through all the partitions lying under T { TU=PU[j]; // for each of them rez=rez+IJcoef(T, TU)* SchurCh(TU, c) *ST; // add the corresponding term to the result } } return(rez); // return the result } example { "EXAMPLE:"; echo =2; // The total Chern class of the tensor product of a vector bundle of rank 3 // with Chern classes c(1), c(2), c(3) and a vector bundle of rank 1 with // Chern class C(1) ring r = 0, ( c(1..3), C(1)), ws(1,2,3, 1); list c=c(1..3); list C=C(1); print( chProdLP(3,c,1,C) ); } //--------------------------------------------------------------------------------------- proc ChernRootsHom(list a, list b) "USAGE: ChernRootsHom(a, b); a, b lists of polynomials RETURN: list of polynomials PURPOSE: for a vector bundle E with Chern roots a and a vector bundle F with Chern roots b, computes the Chern roots of Hom(E, F) EXAMPLE: example ChernRootsHom; shows an example NOTE: " { int na=size(a); int nb=size(b); int i; int j; list rez; // the result will be computed here for(i=1;i<=na;i++) // compute the result { for(j=1;j<=nb;j++) { rez=rez+list(-a[i]+b[j]); } } return(rez); } example { "EXAMPLE:"; echo=2; ring r=0, (a(1..2), b(1..3)), dp; list l=a(1..2); list L=b(1..3); // Let E be a vector bundle with Chern roots a(1). a(2), // let F be a vector bundle with CHern roots b(1), b(2), b(3). // Then the Chern roots of Hom(E, F) are print(ChernRootsHom(l, L)); } //----------------------------------------------------------------------------------------- proc chHom(def r, list c, def R, list C, list #) "USAGE: chHom(r, c, R, C [, N]); r, R polynomials (integers); c, C lists of polynomials, N integer RETURN: list of polynomials PURPOSE: computes [up to degree N] the list of Chern classe of the vector bundle Hom(E, F) in terms of the ranks and the Chern clases of E and F EXAMPLE: example chHom; shows an example NOTE: " { return( chProd(r, chDual(c), R, C, # ) ); } example { "EXAMPLE:"; echo=2; ring H = 0, ( r, R, c(1..3), C(1..2) ), dp; list l=c(1..3); list L=C(1..2); // the Chern classes of Hom(E, F) for a vector bundle E of rank 3 // with Chern classes c(1), c(2), c(3) // and a vector bundle F of rank 2 with Chern classes C(1) and C(2): print( chHom(3, l, 2, L) ); // the first two Chern classes of Hom(E, F) for a vector bundle E of rank r // with Chern classes c(1) and c(2) // and a vector bundle G of rank R with Chern classes C(1) and C(2) // this gives the Chern classes of a tensor product on a complex surface l=c(1..2); L=C(1..2); print( chHom(r, l, R, L, 2 ) ); } //--------------------------------------------------------------------------------- proc ChernRootsSymm(int n, list l) "USAGE: ChernRootsSymm(m, l); m integer, l a list of polynomials RETURN: list of polynomials PURPOSE: computes the Chern roots of m-th symmetric power of a vector bundle with Chern roots from l EXAMPLE: example ChernRootsSymm; shows an example NOTE: " { if(n<0) // return the empty list if n is negative { return(list(0)); } int r=size(l); def br@=basering; // remember the base ring ring r@=0, (a@(1..r)), dp; ideal mon = a@(1..r); mon=mon^n; // all monomials of degree n list rez; int i, j; int N = size(mon); intvec v; for(i=1; i<=N; i++) // collect in rez the exponents of the monomials of degree n { v = leadexp(mon[i]); rez = rez + list(v); } setring br@; poly f; list rez1; // run over all exponents and construct the corresponding sums of the Chern roots for(i=1; i<=N; i++) { f=0; for(j=1;j<=r;j++) { f=f+rez[i][j]*l[j]; } rez1=rez1+list(f); } return(rez1); } example { "EXAMPLE:";echo =2; ring r=0, (a(1..3)), dp; list l=a(1..3); // the Chern roots of the second symmetric power of a vector bundle // with Chern roots a(1), a(2), a(3) print( ChernRootsSymm(2, l) ); } //------------------------------------------------------------ proc ChernRootsWedge( int m, list l) "USAGE: ChernRootsWedge(m, l); m integer, l a list of polynomials RETURN: list of polynomials PURPOSE: computes the Chern roots of m-th exterior power of a vector bundle with Chern roots from l EXAMPLE: example ChernRootsWedge; shows an example NOTE: makes sense only for list of polynomials " { int n=size(l); if((m>n)||(m<=0) ) // if m is bigger that n or non-positive { return( list(0) ); // return the list with one zero entry } else { if(m==n) // if m equals n, the only Chern root of the exterior power will be { return( list(sum(l)) ); // the sum of the initial Chern roots } else // otherwise proceed recursively { int i; list rez; list rez1; list l1 = delete(l, 1); // throw away the first element from the list poly f = l[1]; // remember the first entry of l // compute the Chern roots of the (m-1)-th exterior power of the smaller list rez1 = ChernRootsWedge(m-1, l1 ); int s = size( rez1 ); // add the first entry of the bigger list to every entry in the result, // this will give all Chern roots involving f for(i=1; i<=s; i++) { rez1[i] = f+rez1[i]; } // return the union of those Chern roots with f and those without f rez = ChernRootsWedge(m, l1) + rez1; return( rez ); } } } example { "EXAMPLE:";echo =2; ring r=0, (a(1..3)), dp; list l=a(1..3); // the Chern roots of the second exterior power of a vector bundle // with Chern roots a(1), a(2), a(3) print( ChernRootsWedge(2, l) ); } //--------------------------------------------------------------------------------- proc chSymm(int k, int r, list c, list #) "USAGE: chSymm(k, r, c[, pos]); k, r integers, c list of polynomials, pos list of integers RETURN: list with entries: int N, list of polynomials l PURPOSE: computes the rank and the Chern classes of the symmetric power of a vector bundle EXAMPLE: example chSymm; shows an example NOTE: for the second symmetric power chSymm2L(...) could be faster " { if(r<0) // if the rank is negative { print("The rank of a vector bundle can non be negative"); return(list()); // return the empty list in this case } if(r==0) // if we deal with the zero bundle { return( list( 0, list() ) ); // return the data corresponding to the zero bundle } //----------------------------------- // from now on we are in the case r>0 //----------------------------------- int i; // if the length n of the list of Chern classes is smaller // than the rank of the vector bundle, // the higher classes are assumed to be zero and the list is appended by zeroes up to length r c=append_by_zeroes(r, c); // if the lenght of the list of the Chern classes is greater than the rank c=c[1..r]; // throw away the redundant data //----------------------------------- // from now on the lenght of c is r>0 //----------------------------------- if(k<0) { print("You are trying to compute a negative symmetric power of a vector bundle"); return( list(0, list() ) ); // assume such a power to be just a zero bundle } if(k==0) // the zeroth symmetric power is the trivial line bundle { return( list(1, list(0)) ); } if(k==1) // the first symmetric power is equal to the vector bundle itself { return(list(r, c)); } //----------------------------------- // from now on we are in the case k>2 //----------------------------------- list LM = integer_list(#); int M = LM[2]; // maximum among the optional parameters # = LM[1]; // take into account only the first integer optional parameters that are positive //------------------------------- // Perform the computations now //------------------------------- def br@=basering; // remember the base ring // add additional variables to the base ring execute("ring r@=(" + charstr(basering) + "),("+varstr(basering)+", x@, a@(1..r)), ls;" ); execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings list c=F(c); // embed c into the bigger ring list rez; // the Chern classes of the symmetric power are going to be written here poly E = product( list( a@(1..r ) ) ); // product of the Chern roots list ss=ChernRootsSymm(k, list( a@(1..r) ) ); // list of the Chern roots of the symmetric power int N=size(ss); // number of such roots, it equals the rank of the symmetric power // the entries in C will be the Chern classes of the symmetric power // expressed in terms of the Chern roots of the initial vector bundle list C; ideal I, J; // list of the Chern classes of the initial vector bundle expressed in its Chern roots list sym=symm(list(a@(1..r))); if(size(#)==0) // if there are no optional parameters, compute all Chern classes { // the entries here are the Chern classes of the symmetric power // expressed in terms of Chern roots of the initial vector bundle C=symm(ss); for(i=1;i<=N;i++) // eliminate the Chern roots { if(i<= r) // first add all relevant formulas for the Chern classes in terms of Chern roots { I=I, c[i]-sym[i]; } J = I, x@-C[i]; // Notice that elim(...) is from the library "elim.lib", // it is loaded as a result of loading "general.lib" J=simplify(elim(J, E), 1); // get the expression of the next Chern class // in terms of the Chern classes of the initial vector bundle rez=rez+list( -subst( J[1], x@, 0) ); } } else // otherwise compute only the needed Chern classes { C=symm(ss, M); // only the needed Chern classes int j; i=1; // the maximal number of optional parameters to be considered does not exceed N, // i.e., the rank of the symmetric power int NN = min( size(#), N); for(j=1; j <= NN; j++) // process the optional parameters { // process the optional parameters only untill they are not bigger than N; // notice they are positive anyway after integer_list(...) if( #[j]<=N ) { for( ; i<=#[j];i++) { if(i<=r) { // add the relevant formulas for the Chern classes in terms of the Chern roots I=I, c[i]-sym[i]; } } J= I, x@-C[ #[j]]; // Notice that elim(...) is from the library "elim.lib", // it is loaded as a result of loading "general.lib" J=simplify(elim(J, E), 1); // get the expression of the next Chern class // in terms of the Chern classes of the initial vector bundle rez=rez+list( -subst( J[1], x@, 0) ); } else // get out from the loop { break; } } } // used because Singular seems not to be able to apply maps to empty lists (see below) if(size(rez)==0) { return(list(N, list())); } setring br@; // come back to the initial base ring // define the specialization homomorphism, // evaluate the formulas for the Chern classes on their given values execute( "map FF = r@,"+varstr(br@)+";" ); list rez=FF( rez ); // bring the result back to the initial ring return( list( N, rez ) ); // return the result together with the rank of the symmetric power } example { "EXAMPLE:";echo =2; ring r=0, (c(1..5)), dp; list l=c(1..5); // the rank and the Chern classes of the second symmetric power of a vector bundle of rank 3 print( chSymm(2, 3, l) ); // the rank and the first 3 Chern classes // of the second symmetric power of a vector bundle of rank 5 print( chSymm(2, 5, l, 1, 2, 3) ); } //---------------------------------------------------------------------------------- proc chSymm2L(int r, list c) "USAGE: chSymm2L(r, c); r integer, c list of polynomials RETURN: list of polynomials PURPOSE: computes the Chern classes of the second symmetric power of a vector bundle EXAMPLE: example chSymm2L; shows an example NOTE: Implementation of the formula of Lascoux, the Schur polynomials are computed using the second Jacobi-Trudi formula (in terms of the Chern classes) " { if(r<0) // if the rank is negative { print("The rank of a vector bundle can non be negative"); return(list()); // return the empty list in this case } if(r==0) // if we deal with the zero bundle { return( list( 0, list() ) ); // return the data corresponding to the zero bundle } //----------------------------------- // from now on we are in the case r>0 //----------------------------------- c=append_by_zeroes(r, c); c=c[1..r]; def br@=basering; // remember the base ring // add additional variables to the base ring execute("ring r@=(" + charstr(basering) + "), ("+varstr(basering)+", t@, c@(1..r)), dp;" ); execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings list c; int i; for(i=1;i<=r;i++) { c[i]=c@(i)*t@^i; } poly f = chSymm2LP(r,c); // get the total Chern class using the formula of Lascoux matrix CF = coeffs(f, t@); int N=r*(r+1) div 2; list rez; // write the coefficients in front of the powers of t@ into a list for(i=1;i<=N;i++) { rez=rez+list(CF[i+1,1]); } setring br@; // come back to the initial base ring execute("map FF = r@,"+varstr(br@)+",0, c[1..r];"); // define the specialization homomorphism return( list(N, FF( rez )) ); // bring the result to the initial ring } example { "EXAMPLE:";echo =2; ring r=0, (c(1..2)), dp; list l=c(1..2); // the Chern classes of the second symmetric power of a vector bundle of rank 2 print( chSymm2L(2, l)); } //--------------------------------------------------------------------------------------- proc chSymm2LP(int r, list c) "USAGE: chSymm2LP(r, c); r integer, c list of polynomials RETURN: poly PURPOSE: computes the total Chern class of the second symmetric power of a vector bundle EXAMPLE: example chSymm2LP; shows an example NOTE: Implementation of the formula of Lascoux, the Schur polynomials are computed using the second Jacobi-Trudi formula (in terms of the Chern classes) " { if(r<0) // if the rank is negative { print("The rank of a vector bundle can non be negative"); return(1); // return 1 in this case } if(r==0) // if we deal with the zero bundle { return( 1 ); // return 1 in this case } //------------------------------------------- // from now on we are in the case r > 0 //------------------------------------------- c=append_by_zeroes(r, c); c=c[1..r]; list I; // the partition (1,2,...,r) will be stored here int i; for(i=1;i<=r;i++) { I=I+list(i); } list PU = partUnder(I); // compute the partitions under I int sz=size(PU); // get their number poly rez; // the result will be computed here list J; poly cf; int ex; // implement the formula of Lascoux for(i=1;i<=sz;i++) { J=PU[i]; ex=sum(J)- r*(r-1) div 2; if(ex>=0) { cf=bigint(2)^ex*IJcoef(I, J); } else { cf=IJcoef(I, J)/bigint(2)^(-ex); } rez = rez + cf * SchurCh(J, c ); } return(rez); } example { "EXAMPLE:";echo =2; ring r=0, (c(1..2)), ws(1, 2); list l=c(1..2); // the total Chern class of the second symmetric power of a vector bundle of rank 2 print( chSymm2LP(2, l)); } //--------------------------------------------------------------------------------------- proc chWedge(int k, int r, list c, list #) "USAGE: chWedge(k, r, c [,pos]); k, r integers, c list of polynomials, pos list of integers RETURN: list with entries: int N, list of polynomials l PURPOSE: computes the rank and the Chern classes of the exterior power of a vector bundle EXAMPLE: example chWedge; shows an example NOTE: for the second exterior power chWedge2L(...) could be faster " { if(r<0) // if the rank is negative { print("The rank of a vector bundle can non be negative"); return(list()); // return the empty list in this case } if(r==0) // if we deal with the zero bundle { return( list( 0, list() ) ); // return the data corresponding to the zero bundle } //------------------------------------------- // from now on we are in the case r > 0 //------------------------------------------- if(k<0) { print("You are trying to compute a negative exterior power of a vector bundle"); return( list(0, list() ) ); // assume such a power to be just a zero bundle } if(k==0) // the zeroth exterior power is the trivial line bundle { return( list(1, list(0)) ); } if(k==1) // the first exterior power is equal to the vector bundle itself { c=append_by_zeroes(r, c); c=c[1..r]; return(list(r, c)); } //--------------------------------------- // from now on we are in the case k > 2 //--------------------------------------- int i; // if the length of the list of Chern classes is smaller than the rank of the vector bundle, // the higher classes are assumed to be zero and the list is appended by zeroes up to length r c=append_by_zeroes(r, c); // if the length of the list of the Chern classes is greater than the rank c=c[1..r]; // throw away the redundant data //------------------------------------------ // from now on the length of c is r > 0 //------------------------------------------ if( k>r ) // if k>r, the exterior power is zero { return( list( int(0), list() ) ); } //----------------------------------------------- // from now on we are in the case 0 < k <= r = n //----------------------------------------------- if(k==r) { return(list( int(1), list( c(1) ) ) ); } //----------------------------------------------- // from now on we are in the case 0 < k < r = n //----------------------------------------------- list LM = integer_list(#); int M=LM[2]; // maximum among the optional parameters if there are any, zero otherwise # = LM[1]; // take into account only the first integer optional parameters that are positive //----------------------------- // Let us compute now //----------------------------- def br@=basering; // remember the base ring // add additional variables a@(1..r), x@ to the base ring execute("ring r@= (" + charstr(basering) + "), ("+varstr(basering)+", x@, a@(1..r)), ls;" ); execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings list c = F(c); // embed c into the bigger ring list rez; // the result should be computed here poly E = product( list( a@(1..r ) ) ); // product of the Chern roots to be eliminaned list ss=ChernRootsWedge(k, list( a@(1..r) )); // list of the Chern roots of the exterior product int N=size(ss); // length of ss, equals the rank of the exterior product // list of the Chern classes of the initial vector bundle in terms of their Chern roots list sym=symm(list(a@(1..r))); // the entries here will be the Chern classes we need // expressed in terms of the Chern roots of the initial vector bundle list C; ideal I, J; if( size(#) == 0 ) // if there are no optional parameters, compute all Chern classes { // the entries here are the Chern classes we need // expressed in terms of the Chern roots of the initial vector bundle C=symm(ss); for(i=1;i<=N;i++) // eliminate the Chern roots { if(i<= r) // first add all relevant formulas for the Chern classes in terms of Chern roots { I=I, c[i]-sym[i]; } J = I, x@-C[i]; // Notice that elim(...) is from the library "elim.lib", // it is loaded as a result of loading "general.lib" J=simplify(elim(J, E), 1); // get the expression of the next Chern class // in terms of the Chern classes of the initial vector bundle rez=rez+list( -subst( J[1], x@, 0) ); } } else // otherwise compute only the needed Chern classes { // the entries here are the Chern classes we need // expressed in terms of the Chern roots of the initial vector bundle C=symm(ss, M); int j; i=1; // the maximal number of optional parameters to be considered // does not exceed N, the rank of the exterior power int NN = min( size(#), N); for(j=1; j <= NN; j++) // process the optional parameters { // process the optional parameters only untill they are not bigger than N; // notice they are positive anyway after integer_list(...) if( #[j]<=N ) { for( ; i<=#[j]; i++) { if( i<=r ) { // add the relevant formulas for the Chern classes in terms of the Chern roots I=I, c[i]-sym[i]; } } J= I, x@-C[ #[j]]; // Notice that elim(...) is from the library "elim.lib", // it is loaded as a result of loading "general.lib" J=simplify(elim(J, E), 1); // get the expression of the next Chern class // in terms of the Chern classes of the initial vector bundle rez=rez+list( -subst( J[1], x@, 0) ); } else // get out from the loop { break; } } } // used because Singular seems not to be able to apply maps to empty lists (see below) if(size(rez)==0) { return(list(N, list())); } setring br@; // come back to the initial base ring // define the specialization homomorphism, // evaluate the formulas for the Chern classes on their given values execute( "map FF = r@,"+varstr(br@)+";" ); list rez=FF( rez ); // bring the result back to the initial ring return( list( N, rez ) ); //return the rank and the Chern classes of the exterior product } example { "EXAMPLE:";echo =2; ring r=0, (c(1..5)), dp; list l=c(1..5); // the rank and the Chern classes of the second exterior power of a vector bundle of rank 3 print( chWedge(2, 3, l) ); // the rank and the first 3 Chern classes // of the fourth exterior power of a vector bundle of rank 5 print( chWedge(4, 5, l, 1, 2, 3) ); } //--------------------------------------------------------------------------------- proc chWedge2L(int r, list c) "USAGE: chWedge2L(r, c ); r integer, c list of polynomials RETURN: list of polynomials PURPOSE: computes the Chern classes of the second exterior power of a vector bundle EXAMPLE: example chWedge2L; shows an example NOTE: Implementation of the formula of Lascoux, the Schur polynomials are computed using the second Jacobi-Trudi formula (in terms of the Chern classes) " { if(r<0) // if the rank is negative { print("The rank of a vector bundle can non be negative"); return(list()); // return the empty list in this case } if(r==0) // if we deal with the zero bundle { return( list( 0, list() ) ); // return the data corresponding to the zero bundle } //------------------------------------------- // from now on we are in the case r > 0 //------------------------------------------- c=append_by_zeroes(r, c); c=c[1..r]; def br@=basering; // remember the base ring // add additional variables to the base ring execute("ring r@=(" + charstr(basering) + "), ("+varstr(basering)+", t@, c@(1..r)), dp;" ); execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings list c; int i; for(i=1;i<=r;i++) { c[i]=c@(i)*t@^i; } poly f = chWedge2LP(r,c); // get the total Chern class using the formula of Lascoux matrix CF = coeffs(f, t@); int N=r*(r-1) div 2; list rez; // write its coefficients in front of the powers of t@ to a list for(i=1;i<=N;i++) { rez=rez+list(CF[i+1,1]); } setring br@; // come back to the initial base ring execute("map FF = r@,"+varstr(br@)+",0, c[1..r];"); // define the specialization homomorphism return( list(N, FF( rez )) ); // bring the result to the initial ring } example { "EXAMPLE:";echo =2; ring r=0, (c(1..3)), dp; list l=c(1..3); // the Chern classes of the second exterior power of a vector bundle of rank 3 print(chWedge2L(3, l)); } //--------------------------------------------------------------------------------------- proc chWedge2LP(int r, list c) "USAGE: chWedge2LP(r, c ); r integer, c list of polynomials RETURN: poly PURPOSE: computes the total Chern class of the second exterior power of a vector bundle EXAMPLE: example chWedge2LP; shows an example NOTE: Implementation of the formula of Lascoux, the Schur polynomials are computed using the second Jacobi-Trudi formula (in terms of the Chern classes) " { if(r<0) // if the rank is negative { print("The rank of a vector bundle can non be negative"); return(1); // return 1 in this case } if(r==0) // if we deal with the zero bundle { return( 1 ); // return 1 in this case } //------------------------------------------- // from now on we are in the case r > 0 //------------------------------------------- c=append_by_zeroes(r, c); c=c[1..r]; list I; // the partition (0,1,...,r-1) will be stored here int i; for(i=0;i<=r-1;i++) { I=I+list(i); } list PU = partUnder(I); // compute the partitions under I int sz=size(PU); // get their number poly rez; // the result will be computed here list J; poly cf; // implement the Lascoux formula for(i=1;i<=sz;i++) { J=PU[i]; cf = IJcoef(I,J)/bigint(2)^( r*(r-1) div 2-sum(J) ); rez = rez + cf * SchurCh(J, c ); } return(rez); } example { "EXAMPLE:";echo =2; ring r=0, (c(1..3)), ws(1,2,3); list l=c(1..3); // the total Chern class of the second exterior power of a vector bundle of rank 3 print(chWedge2LP(3, l)); } //--------------------------------------------------------------------------------------- proc todd(list c, list #) "USAGE: todd(l [, n] ); l a list of polynomials, n integer RETURN: list of polynomials PURPOSE: computes [the first n] terms of the Todd class EXAMPLE: example todd; shows an example NOTE: returns an empty list if l is empty " { int n; # = integer_list(#)[1]; // take into account only the first integer entries that are positive if( size(#) == 0 ) // if there are no optional parameters { n = size(c); } else { // set n to be 0, if the parameter is non-positive, // set n to the value of the parameter otherwise n = max( #[1], 0 ); c = append_by_zeroes(n, c); // append c by zeroes if the length of c is smaller than n if(n!=0) // throw away the redundant data if n is positive and smaller than the length of c { c = c[1..n]; } } if(n==0) // return the empty list { return(list()); } else // otherwise proceed as follows { def br@=basering; // remember the base ring // add additional variables to the base ring execute("ring r@=(" + charstr(basering) + "), ("+varstr(basering)+", a@, c@(1..n)), dp;" ); execute( "map F= br@,"+varstr(br@)+";" ); // define the corresponding inclusion of rings list c=F(c); // embed c into the bigger ring list prev; list next; next=tdTerms(n, c@(1)); // the Todd class terms of a line budle list step = tdTerms(n, a@); int i, j, k; poly f; list hC=c@(1)-a@; // "old" first Chern class for(k=2;k<=n;k++) // do n-1 iterations { prev=next; next=list(); hC=hC+list( c@(k)-a@*hC[k-1] ); // "old" k-th Chern class for(i=0;i=1;j--) { for(k=0;k=1;j--) { steprez[j]=j*(steprez[j]-steprez[j+1]); } rez=rez+list(steprez[1]); } return(rez); } example { "EXAMPLE:";echo =2; // first 10 Bernoulli numbers: B(0), ..., B(9) ring r=0,(t), dp; print( Bern(9) ); } //--------------------------------------------------------------------------------- proc tdCf(int n) "USAGE: tdCf(n); n integer RETURN: list of rational numbers PURPOSE: computes up to degree n the coefficients of the Todd class of a line bundle EXAMPLE: example tdCf; shows an example NOTE: " { list rez=Bern(n); // notice that Bern(n) is able to take care of negative n int i; for(i=1;i<=n+1;i++) { rez[i]=rez[i]/factorial(i-1); } return(rez); } example { "EXAMPLE:";echo =2; // first 5 coefficients ring r=0,(t), dp; print( tdCf(4) ); } //--------------------------------------------------------------------------------- proc tdTerms(int n, poly f) "USAGE: tdTerms(n, f); n integer, f polynomial RETURN: list of polynomials PURPOSE: computes the terms of the Todd class of the line bundle with the Chern root f EXAMPLE: example tdTerms; shows an example NOTE: " { list rez=Bern(n); // notice that Bern(n) takes care of negative n int i; for(i=1;i<=n+1;i++) { rez[i]=( rez[i]/factorial(i-1) )* f^(i-1); } return(rez); } example { "EXAMPLE:";echo =2; ring r=0, (t), ls;; // the terms of the Todd class of a line bundle with Chern root t up to degree 4 print( tdTerms(4, t) ); } //--------------------------------------------------------------------------------- proc tdFactor(int n, poly t) "USAGE: tdFactor(n, a); n integer, a polynomial RETURN: polynomial PURPOSE: computes up to degree n the Todd class of the line bundle coresponding to the Chern root t EXAMPLE: example tdFactor; shows an example NOTE: returns 0 if n is negative " { int i; poly rez=0; list l=Bern(n); // get the coefficients for(i=0; i<=n; i++) // form the polynomial { rez=rez+(l[i+1]/factorial(i))*t^i; } return(rez); } example { "EXAMPLE:";echo =2; // the Todd class up do degree 4 ring r=0,(t), ls; print( tdFactor(4, t) ); } //--------------------------------------------------------------------------------- proc cProj(int n) "USAGE: cProj(n); n integer RETURN: list of integers PURPOSE: computes the terms of positive degree of the total Chern class of the tangent bundle on the complex projective space EXAMPLE: example cProj; shows an example NOTE: " { if(n<0) { print("The dimension of the projective space must be non-negative!"); return(list()); // return the empty list in this case } else { list rez; int i; for(i=1;i<=n;i++) { rez=rez+list( binomial(n+1, i) ); } return(rez); } } example { "EXAMPLE:";echo =2; ring r=0, (t), dp; // the coefficients of the total Chern class of the complex projective line print( cProj(1) ); // the coefficients of the total Chern class of the complex projective line print( cProj(2) ); // the coefficients of the total Chern class of the complex projective line print( cProj(3) ); } //------------------------------------------------------------------------------------------ proc chProj(int n) "USAGE: chProj(n); n integer RETURN: list of (rational) numbers PURPOSE: computes the terms of the Chern character of the tangent bundle on the complex projective space EXAMPLE: example chProj; shows an example NOTE: " { if(n<0) { print("The dimension of the projective space must be non-negative!"); return( list() ); // return the empty list in this case } else { list rez=list(number(n)); int i; for(i=1;i<=n;i++) { rez=rez+list( (n+1)/factorial(i) ); } return(rez); } } example { "EXAMPLE:";echo =2; ring r=0, (t), dp; // the coefficients of the Chern character of the complex projective line print( chProj(1) ); // the coefficients of the Chern character of the complex projective plane print( chProj(2) ); // the coefficients of the Chern character of the complex 3-dimentional projectice space print( chProj(3) ); } //------------------------------------------------------------------------------------------ proc tdProj(int n) "USAGE: tdProj(n); n integer RETURN: list of (rational) numbers PURPOSE: computes the terms of the Todd class of the (tangent bundle of the) complex projective space EXAMPLE: example tdProj; shows an example NOTE: " { if(n<0) { print("The dimension of the projective space must be non-negative!"); return( list() ); // return the empty list in this case } else { def br@=basering; // remember the base ring ring r@= 0, t@, lp; // ring with one variable t@ ideal T=std( t@^(n+1) ); poly f= tdFactor(n, t@); f=reduce( f^(n+1), T); matrix C = coeffs(f, t@); list rez; int i; for(i=0;i<=n;i++) { rez=rez+list(C[i+1, 1]); } setring br@; // come back to the initial base ring map FF= r@, 0 ; // define the specialization homomorphism t@=0 return(FF(rez)); // bring the result to the base ring } } example { "EXAMPLE:";echo =2; ring r=0, (t), dp; // the coefficients of the Todd class of the complex projective line print( tdProj(1) ); // the coefficients of the Todd class of the complex projective line print( tdProj(2) ); // the coefficients of the Todd class of the complex projective line print( tdProj(3) ); } //------------------------------------------------------------------------------------------ proc eulerChProj(int n, def r, list c) "USAGE: eulerChProj(n, r, c); n integer, r polynomial (or integer), c list of polynomials RETURN: polynomial PURPOSE: computes the Euler characteristic of a vector bundle on P_n in terms of its rank and Chern classses EXAMPLE: example eulerChProj; shows an example NOTE: " { if(n<0) { print("The dimension of the projective space must be non-negative!"); return(0); // return zero in this case } else { int sz=size(c); list td = tdProj(n); // terms of the Todd class of P_n int N = min( n, sz ); int i; list ch = list(r) + chAll(c); // terms of the Chern character of the vector bundle return( rHRR(n, ch, td) ); } } example { "EXAMPLE:";echo =2; ring h=0, (r, c(1..3)), ws(0,1,2,3); list l=c(1..3); // the Euler characteristic of a vector bundle on the projective line print( eulerChProj(1, r, l) ); // the Euler characteristic of a vector bundle on the projective plane print( eulerChProj(2, r, l) ); // the Euler characteristic of a vector bundle on P_3 print( eulerChProj(3, r, l) ); // assume now that we have a bundle framed at a subplane of P_3 // this implies c(1)=c(2)=0 l= 0, 0, c(3); // the Euler characteristic is print( eulerChProj(3, r, l) ); // which implies that c(3) must be even in this case } //------------------------------------------------------- proc chNumbersProj(int n) "USAGE: chNumbersProj(n); n integer RETURN: list of integers PURPOSE: computes the Chern numbers of the projective space P_n EXAMPLE: example chNumbersProj; shows an example NOTE: " { return( chNumbers( n, cProj(n) ) ); } example { "EXAMPLE:";echo =2; ring h=0, (t), dp; // The Chern numbers of the projective plane P_2: print( chNumbersProj(2) ); // The Chern numbers of P_3: print( chNumbersProj(3) ); } //------------------------------------------------------- proc classpoly(list l, poly t) "USAGE: classpoly(l, t); l list of polynomials, t polynomial RETURN: polynomial PURPOSE: computes the polynomial in t with coefficients being the entries of l EXAMPLE: example classpoly; shows an example NOTE: " { int n=size(l); poly pow=1; // powers of t will be compured here poly rez=0; // result will be computed here int i; for(i=1; i<=n; i++) { pow=pow*t; // compute the required power of t // add the i-th entry of l multiplied by the corresponding power of t to the result rez=rez + l[i]*pow; } return( rez ); } example { "EXAMPLE:";echo=2; ring r=0, (c(1..5), t), ds; list l=c(1..5); // get the polynomial c(1)*t + c(2)*t^2 + ... + c(5)*t^5 print( classpoly(l, t) ); } //---------------------------------------------------------------------------------------- proc chernPoly(list c, poly t) "USAGE: chernPoly(c, t); c list of polynomials, t polynomial RETURN: polynomial PURPOSE: computes the Chern polynomial in t EXAMPLE: example chernPoly; shows an example NOTE: does the same as toddPoly(...) " { return( 1+classpoly(c, t) ); } example { "EXAMPLE:";echo=2; ring r=0, (c(1..5), t), ds; list l=c(1..5); // get the Chern polynomial 1 + c(1)*t + c(2)*t^2 + ... + c(5)*t^5 print( chernPoly(l, t) ); } //---------------------------------------------------------------------------------------- proc chernCharPoly(poly r, list ch, poly t) "USAGE: chernCharPoly(r, ch, t); r polynomial, ch list of polynomials, t polynomial RETURN: polynomial PURPOSE: computes the polynomial in t corresponding to the Chern character EXAMPLE: example chernpoly; shows an example NOTE: " { return( r+classpoly(ch, t) ); } example { "EXAMPLE:";echo=2; ring h=0, (r, ch(1..5), t), ds; list l=ch(1..5); // get the polynomial r + ch(1)*t + ch(2)*t^2 + ... + ch(5)*t^5 print( chernCharPoly(r, l, t) ); } //---------------------------------------------------------------------------------------- proc toddPoly(list td, poly t) "USAGE: toddPoly(td, t); td list of polynomials, t polynomial RETURN: polynomial PURPOSE: computes the polynomial in t corresponding to the Todd class EXAMPLE: example toddPoly; shows an example NOTE: does the same as chernPoly(...) " { return( 1+classpoly(td, t) ); } example { "EXAMPLE:"; echo=2; ring r=0, (td(1..5), c(1..5), t), ds; list l=td(1..5); // get the polynomial 1 + td(1)*t + td(2)*t^2 + ... + td(5)*t^5 print( toddPoly(l, t) ); } //--------------------------------------------------------------------------------------- proc rHRR(int N, list ch, list td) "USAGE: rHRR( N, ch, td); N integer, ch, td lists of polynomials RETURN: polynomial PURPOSE: computes the the main ingredient of the right-hand side of the Hirzebruch-Riemann-Roch formula EXAMPLE: example rHRR; shows an example NOTE: in order to get the right-hand side of the HRR formula one needs to be able to compute the degree of the output of this procedure " { poly rez; // to be the result int i; int nch=size(ch); // length of ch int ntd=size(td); // length of td for(i=1; i<=N+1; i++) // compute the highest degree term of ch.td { if( (i<=nch) && (N-i+2 <= ntd) ) { rez = rez + ch[i]*td[N-i+2]; } } return(rez); } example { "EXAMPLE:"; echo=2; ring r=0, (td(0..3), ch(0..3)), dp; // Let ch(0), ch(1), ch(2), ch(3) be the terms of the Chern character // of a vector bundle E on a 3-fold X. list c = ch(0..3); // Let td(0), td(1), td(2), td(3) be the terms of the Todd class of X. list t = td(0..3); // Then the highest term of the product ch(E).td(X) is: print( rHRR(3, c, t) ); } //--------------------------------------------------------------------------------------- proc SchurS(list I, list S) "USAGE: SchurS(I, S); I list of integers representing a partition, S list of polynomials RETURN: poly PURPOSE: computes the Schur polynomial in the Segre classes S, i.e., in the complete homogeneous symmetric polynomials, with respect to the partition I EXAMPLE: example SchurS; shows an example NOTE: if S are the Segre classes of the tautological bundle on a grassmanian, this gives the cohomology class of a Schubert cycle " { int m=size(I); // size of I S=list(1)+S; // add the zeroth Segre class int szS=size(S); // size of S int h,k; int in; // variable for the index of the required Segre class // construct the required m x m matrix from the first determinantal (Jacobi-Trudi) formula matrix M[m][m]; for(h=1;h<=m;h++) { for(k=1;k<=m;k++) { in=I[k]+k-h; // compute the index if(in<0) // if it is negative, assume the corresponding Segre class to be zero { M[h,k]=0; } else { if(in>=szS) // if it is bigger than the number of the highest available Segre class in S { M[h, k]=0; // assume the corresponding Segre class is zero } else // otherwise { M[h, k]= S[in+1]; // use a value from S for the corresponding Segre class } } } } return(det(M)); // return the determinant of the computed matrix } example { "EXAMPLE:"; echo=2; // The Schur polynomial corresponding to the partition 1,2,3 // and the Segre classes 1, s(1), s(2),..., s(5) ring r=0,(s(1..5)), dp; list I=1,2,3; list S=s(1..5); print( SchurS(I, S) ); // compare this with the Schur polynomial computed using Chern classes list C=chern(S); print( SchurCh(I, C) ); } //--------------------------------------------------------------------------------------- proc SchurCh(list I, list C) "USAGE: SchurCh(I, C); I list of integers representing a partition, C list of polynomials RETURN: poly PURPOSE: computes the Schur polynomial in the Chern classes C, i.e., in the elementary symmetric polynomials, with respect to the partition I EXAMPLE: example SchurCh; shows an example NOTE: if C are the Chern classes of the tautological bundle on a grassmanian, this gives the cohomology class of a Schubert cycle " { I=dualPart(I); // dual partition to I int m=size(I); // size of I C=list(1)+C; // add the zeroth Chern class int szC=size(C); // size of C int h,k; int in; // variable for the index of the required Chern class // construct the required m x m matrix from the second determinantal (Jacobi-Trudi) formula matrix M[m][m]; for(h=1;h<=m;h++) { for(k=1;k<=m;k++) { in=I[k]+k-h; // compute the index if(in<0) // if it is negative, assume the corresponding Chern class to be zero { M[h,k]=0; } else { if(in>=szC) // if it is bigger than the number of the highest available Chern class in C { M[h, k]=0; // assume the corresponding Chern class is zero } else // otherwise { M[h, k]= C[in+1]; // use a value from C for the corresponding Chern class } } } } return(det(M)); // return the determinant of the computed matrix } example { "EXAMPLE:"; echo=2; // The Schur polynomial corresponding to the partition 1,2,3 // and the Chern classes c(1), c(2), c(3) ring r=0,(c(1..3)), dp; list I=1,2,3; list C=c(1..3); print( SchurCh(I, C) ); // Compare this with the Schur polynomial computed using Segre classes list S=segre(list(c(1..3)), 5); print(SchurS(I,S)); } //--------------------------------------------------------------------------------------- proc part(int m, int n) "USAGE: part( m, n ); m positive integer, n non-negative integer RETURN: list of lists PURPOSE: computes all partitions of integers not exceeding n into m non-negative summands EXAMPLE: example part; shows an example NOTE: if n is negative or m is non-positive, the list with one empty entry is returned " { if( n<0 ) // if n is negative { return(list(list())); // return the list with one empty entry } if(n==0) // if n equals 0, there is only one partition of 0 into m non-negative summands { return(list(listSame(0,m))); // return the list with one entry consistion of m zeroes } // otherwise proceed recursively list rez=part(m, n-1); // get all partitions for n-1 int i; for(i=1;i<=m;i++) // for every i between 1 and m, add the partitions with exactly { rez=rez + appendToAll( part(m-i, n-1), listSame(n, i) ); // i summands equal to n } return(rez); // return the result } example { "EXAMPLE:"; echo=2; // partitions into 3 summands of numbers not exceeding 1 print( part(3, 1) ); } //--------------------------------------------------------------------------------------- proc dualPart(list I, list #) "USAGE: dualPart( I [,N] ); I list of integers, N integer RETURN: list of integers PURPOSE: computes the partition dual (conjugate) to I EXAMPLE: example dualPart; shows an example NOTE: the result is extended by zeroes to length N if an optional integer parameter N is given and the length of the computed dual partition is smaller than N " { int m= size(I); // size of I if(m==0) // if I is the empty list { print("You are trying to compute the dual of the empty partition!"); print("The partition with one zero is returned."); return(list(0)); } // compute the dual partition list J; // the result will be computed here int i; int j=I[1]; int k; for(k=1;k<=j;k++) { J=list(m)+J; } for(i=2;i<=m;i++) { j=I[i]-I[i-1]; for(k=1;k<=j;k++) { J=list(m-i+1)+J; } } if(size(J)==0) // if the dual partition J is empty (if I consists of zeroes) { J = list(0); // add zero to the result } if(size(#)>0) // if there is an optional parameter N { if( is_integer( #[1] ) ) // if the parameter is an integer, { if( size(J) < #[1] ) // if N is bigger than the lebgth of J, { J=listSame(0, #[1]-size(J))+J; // extend J by zeroes to length N } } } return(J); // return the result } example { "EXAMPLE:"; echo =2; // dual partition to (1, 3, 4): list I = 1, 3, 4; print( dualPart(I) ); } //--------------------------------------------------------------------------------------- proc PartC(list I, int m) "USAGE: PartC( I, m); I list of integers, m integer RETURN: list of integers PURPOSE: commputes the complement of a partition with respect to m EXAMPLE: example PartC; shows an example NOTE: returns the zero partition if the maximal element of the partition is smaller than m " { int n=size(I); // size of I if( m=1;i--) // invert the order of numbers { J=J+list(m-I[i]); // and substitute them by their complemenst to m } return(J); // return the result } example { "EXAMPLE:"; echo =2; // Complement of the partition (1, 3, 4) with respect to 5 list I = 1, 3, 4; print( PartC(I, 5) ); } //--------------------------------------------------------------------------------------- proc partOver(int n, list J) "USAGE: partOver( n, J); n integer, J list of integers (partition) RETURN: list of lists PURPOSE: computes the partitions over a given one with summands not exceeding n EXAMPLE: example partOver; shows an example NOTE: " { int m=size(J); // size of J if( m==0 ) // if J is an empty list { // give a warning print("You are trying to compute partitions over an empty partition!"); return( list() ); // and return the emty list } if( J[m] > n ) // if the biggest summand of the partition is bigger than n { return( list( ) ); // return the emty list } if( J[m] == 0 ) // if J consists of zeroes { return( part(m,n) ); // return all partitions of n into m summands } // now J is non-empty, contains con-zero summands, has partitions over it list rez1; // the result will be computed here int i,j; if(m==1) // if J has only one element { for(j=J[1]; j<=n; j++) // run through the integers from J[1] to n { rez1=rez1 + list(j); // add the corresponding one element lists to the result } return(rez1); // return the result } // now J has at least two elements // get the partitions over the partition without the last summand list rez = partOver(n, delete(J, m)); int sz=size(rez); // number of such partitions list P; int last; for(i=1; i<=sz; i++) // run trough all such partitions { P=rez[i]; // for each partition P of this type last = max( P[size(P)], J[m] ); for(j = last;j<= n;j++) // run through the integers exceding the last summands of P and J { // append them to P at the end and add the resulting partition to the result rez1=rez1 + list(P+list(j)); } } return(rez1); // return the result } example { "EXAMPLE:"; echo =2; // Partitions over the partition (3, 3, 4) with summands not exceeding 4 list I = 3, 3, 4; print( partOver(4, I) ); } //--------------------------------------------------------------------------------------- proc partUnder(list J) "USAGE: partUnder(J); J list of integers (partition) RETURN: list of lists PURPOSE: computes the partitions under a given one EXAMPLE: example partUnder; shows an example NOTE: " { int m=size(J); // size of J if(m==0) // if J is empty { return(list()); // return an empty list } list rez1; // the result will be computed here int i; if(m==1) // if J contains only one element { for(i=0; i<=J[1]; i++) { rez1=rez1+list(list(i)); } } // now J contains at least two elements list rez; int Jlast=J[m]; // last element of J rez = partUnder(delete(J, m)); // partitions under J without the last element int j; int sz=size(rez); // their number list P; int last; for(i=1; i<=sz; i++) // for every such partition { P = rez[i]; last = P[size(P)]; for(j = last;j<=Jlast ;j++) // for every number between its last entry and the last entry of J { // append that number to the end of the partition // and append the resulting partition to the final result rez1 = rez1 + list(P+list(j)); } } return(rez1); } example { "EXAMPLE:"; echo =2; // Partitions under the partition (0, 1, 1) list I = 0, 1, 1; print( partUnder(I) ); } //---------------------------------------------------------------------------------------- // The procedures below are for the internal usage only //---------------------------------------------------------------------------------------- static proc append_by_zeroes(int N, list c) "USAGE: append_by_zeroes( N, c); N integer, c a list RETURN: list PURPOSE: appends by zeroes up to the length N EXAMPLE: example append_by_zeroes; shows an example NOTE: " { int n=size(c); if(N>n) // if N is greater than the length of c, append c by zeroes up to the length N { int i; for(i=n+1;i<=N;i++) { c=c+list( poly(0) ); } } return(c); } example { "EXAMPLE:";echo =2; ring r = 0, (x, y, z), dp; list l=(x, y, z); //append the list by two zeroes and get a list of lenght 5 print( append_by_zeroes(5, l) ); } //----------------------------------------------------------------------- static proc is_integer(def r) "USAGE: is_integer(r); r any type RETURN: 1 or 0 PURPOSE: checks whether r is of type int or bigint EXAMPLE: example is_integer; shows an example NOTE: returns 1 if r is of type int or bigint, otherwise returns 0 " { if( (typeof(r)=="int") || (typeof(r)=="bigint") ) { return(1); } else { return(0); } } example { "EXAMPLE:";echo =2; // test on int, bigint, poly ring r; int i=12; bigint j=16; poly f=x; print( is_integer(i) ); print( is_integer(j) ); print( is_integer(f) ); } //------------------------------------------------------------------------------------ static proc integer_list(list l) "USAGE: integer_list(l); l list RETURN: list PURPOSE: gets the first positive ingerer entries of l, computes their maximum; used for adjusting the lists of optional parameters that are suposed to be integers EXAMPLE: example integer_list; shows an example NOTE: used in chWedge(...) and chSymm(...) " { int M=0; int n=size(l); if(n==0) { return(list(l, M)); } // now n>0 list rez; // the result will be computed here int i=1; while( is_integer( l[i] ) ) // take only the first integer entries of l { if(l[i]>0) // if they are positive { rez=rez+list( l[i] ); if(l[i]>M) // adjust the maximum if necessary { M=l[i]; } i++; } else // otherwise get out from the loop { break; } } return( list( rez, M) ); } example { "EXAMPLE:";echo =2; // the first integer entries of 1,2,3,t are 1,2,3 ring r=0,(t), ls; list l=1,2,3, t; print( integer_list(l) ); } //--------------------------------------------------------------------------------------- static proc appendToAll(list L, list A) "USAGE: appendToAll( L, A ); L list of lists, A list RETURN: list PURPOSE: appends A to every entry of L EXAMPLE: example appendToAll; shows an example NOTE: " { int n=size(L); int i; for(i=1;i<=n;i++) // run through all elements of L { L[i]=L[i]+A; // and append A to each of them } return(L); } example { "EXAMPLE:"; echo=2; // Consider two lists list l1, l2; l1=1,2; l2=3,4; // The first one is print(l1); // The second one is print(l2); // Now consider the list with entries l1 and l2 list L= l1, l2; print(L); // and consider a list A list A = 7,9; print(A); // append A to all entries of L print( appendToAll(L, A) ); } //--------------------------------------------------------------------------------------- static proc listSame(int n, int k) "USAGE: listSame( n, k ); n integer, k non-negative integer RETURN: list PURPOSE: list with k entries each equal to n EXAMPLE: example listSame; shows an example NOTE: if k is negative or zero, the empty list is returned " { list rez; int i; for(i=1;i<=k;i++) // create a list with k entries, each equal to n { rez=rez+list(n); } return(rez); } example { "EXAMPLE:"; echo=2; // list of 5 zeroes print( listSame(0, 5) ); } //--------------------------------------------------------------------------------------- static proc IJcoef(list I, list J) "USAGE: IJcoef( I, J); J, J lists of integers RETURN: bigint PURPOSE: computes the coefficient used in the formula of Lascoux EXAMPLE: example IJcoef; shows an example NOTE: these coefficients are denoted (I, J) in the paper of Lascoux " { int m = size(I); if(m != size(J)) // if the sizes of I and J are different { // give a warning print("The sizes of the partitions are different!"); print("Zero is returned."); return( bigint(0) ); // and return zero } // now the sizes of I and J are equal m int h, k; bigintmat M[m][m]; // construct the required matrix for(h=1; h<=m; h++) { for(k=1; k<=m; k++) { M[h,k] = binomial( I[k]+k-1, J[h]+h-1 ); } } return( det(M) ); // and return its determinant } example { "EXAMPLE:"; echo =2; // The coefficient corresponding to the partitions (1, 3, 4) and (0, 3, 3) list I = 1, 3, 4; list J = 1, 3, 3; print( IJcoef(I, J) ); } //--------------------------------------------------------------------------------------- singular-4.0.3+ds/Singular/LIB/cimonom.lib000066400000000000000000000351661266270727000203130ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version cimonom.lib 4.0.0.0 Jun_2013 "; // $Id: e11a453b266bcdb659f84fafd1624269e6d55c4b $ category="Commutative Algebra"; info=" LIBRARY: cimonom.lib Determines if the toric ideal of an affine monomial curve is a complete intersection AUTHORS: I.Bermejo, ibermejo@ull.es @* I.Garcia-Marco, iggarcia@ull.es @* J.-J.Salazar-Gonzalez, jjsalaza@ull.es OVERVIEW: A library for determining if the toric ideal of an affine monomial curve is a complete intersection with NO NEED of computing explicitly a system of generators of such ideal. It also contains procedures to obtain the minimum positive multiple of an integer which is in a semigroup of positive integers. The procedures are based on a paper by Isabel Bermejo, Ignacio Garcia and Juan Jose Salazar-Gonzalez: 'An algorithm to check whether the toric ideal of an affine monomial curve is a complete intersection', Preprint. SEE ALSO: Integer programming PROCEDURES: BelongSemig(n,v[,sup]); checks whether n is in the semigroup generated by v; MinMult(a,b); computes k, the minimum positive integer such that k*a is in the semigroup of positive integers generated by the elements in b. CompInt(d); checks wether I(d) is a complete intersection or not. "; LIB "general.lib"; /////////////////////////////////////////////////////////////////////////////////////////////////////////// // proc BelongSemig(bigint n, intvec v, list #) " USAGE: BelongSemig (n,v[,sup]); n bigint, v and sup intvec RETURN: In the default form, it returns 1 if n is in the semigroup generated by the elements of v or 0 otherwise. If the argument sup is added and in case n belongs to the semigroup generated by the elements of v, it returns a monomial in the variables {x(i) | i in sup} of degree n if we set deg(x(sup[j])) = v[j]. ASSUME: v and sup positive integer vectors of same size, sup has no repeated entries, x(i) has to be an indeterminate in the current ring for all i in sup. EXAMPLE: example BelongSemig; shows some examples " { //--------------------------- initialisation --------------------------------- int i, j, num; bigint PartialSum; num = size(v); int e = size(#); if (e > 0) { intvec sup = #[1]; poly mon; } for (i = 1; i <= nrows(v); i++) { if ((n % v[i]) == 0) { // ---- n is multiple of v[i] if (e) { mon = x(sup[i])^(int(n/v[i])); return(mon); } else { return (1); } } } if (num == 1) { // ---- num = 1 and n is not multiple of v[1] --> FALSE return(0); } intvec counter; counter[num] = 0; PartialSum = 0; intvec w = sort(v)[1]; intvec cambio = sort(v)[2]; // ---- Iterative procedure to determine if n is in the semigroup generated by v while (1) { if (n >= PartialSum) { if (((n - PartialSum) % w[1]) == 0) { // ---- n belongs to the semigroup generated by v, if (e) { // ---- obtain the monomial. mon = x(sup[cambio[1]])^(int((n - PartialSum) / w[1])); for (j = 2; j <= num; j++) { mon = mon * x(sup[cambio[j]])^(counter[j]); } return(mon); } else { // ---- returns true. return (1); } } } i = num; while (!defined(end)) { if (i == 1) { // ---- Stop, n is not in the semigroup return(0); } if (i > 1) { // counters control if (counter[i] >= ((n - PartialSum) / w[i])) { PartialSum = PartialSum - (counter[i]*w[i]); counter[i] = 0; i--; } else { counter[i] = counter[i] + 1; PartialSum = PartialSum + w[i]; int end; } } } kill end; } } example { "EXAMPLE:"; ring r=0,x(1..5),dp; int a = 125; intvec v = 13,17,51; intvec sup = 2,4,1; BelongSemig(a,v,sup); BelongSemig(a,v); } /////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////// proc MinMult(int a, intvec b) " USAGE: MinMult (a, b); a integer, b integer vector. RETURN: an integer k, the minimum positive integer such that ka belongs to the semigroup generated by the integers in b. ASSUME: a is a positive integer, b is a positive integers vector. EXAMPLE: example MinMult; shows some examples. " { //--------------------------- initialisation --------------------------------- int i, j, min, max; int n = nrows(b); if (n == 1) { // ---- trivial case return(b[1]/gcd(a,b[1])); } max = b[1]; for (i = 2; i <= n; i++) { if (b[i] > max) { max = b[i]; } } int NumNodes = a + max; //----Number of nodes in the graph int dist = 1; // ---- Auxiliary structures to obtain the shortest path between the nodes 1 and a+1 of this graph intvec queue = 1; intvec queue2; // ---- Control vector: // control[i] = 0 -> node not reached yet // control[i] = 1 -> node in queue1 // control[i] = 2 -> node in queue2 // control[i] = 3 -> node already processed intvec control; control[1] = 3; // Starting node control[a + max] = 0; // Ending node int current = 1; // Current node int next; // Node connected to corrent by arc (current, next) int ElemQueue, ElemQueue2; int PosQueue = 1; // Algoritmo de Dijkstra while (1) { if (current <= a) { // ---- current <= a, arcs are (current, current + b[i]) for (i = 1; i <= n; i++) { next = current + b[i]; if (next == a+1) { kill control; kill queue; kill queue2; return (dist); } if ((control[next] == 0)||(control[next] == 2)) { control[next] = 1; queue = queue, next; } } } if (current > a) { // ---- current > a, the only possible ars is (current, current - a) next = current - a; if (control[next] == 0) { control[next] = 2; queue2[nrows(queue2) + 1] = next; } } PosQueue++; if (PosQueue <= nrows(queue)) { current = queue[PosQueue]; } else { dist++; if (control[a+1] == 2) { return(dist); } queue = queue2[2..nrows(queue2)]; current = queue[1]; PosQueue = 1; queue2 = 0; } control[current] = 3; } } example { "EXAMPLE:"; "int a = 46;"; "intvec b = 13,17,59;"; "MinMult(a,b);"; int a = 46; intvec b = 13,17,59; MinMult(a,b); "// 3*a = 8*b[1] + 2*b[2]" } /////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////// proc CompInt(intvec d) " USAGE: CompInt(d); d intvec. RETURN: 1 if the toric ideal I(d) is a complete intersection or 0 otherwise. ASSUME: d is a vector of positive integers. NOTE: If printlevel > 0, additional info is displayed in case I(d) is a complete intersection: if printlevel >= 1, it displays a minimal set of generators of the toric ideal formed by quasihomogeneous binomials. Moreover, if printlevel >= 2 and gcd(d) = 1, it also shows the Frobenius number of the semigroup generated by the elements in d. EXAMPLE: example CompInt; shows some examples " { //--------------------------- initialisation --------------------------------- int i,j,k,l,divide,equal,possible; int n = nrows(d); int max = 2*n - 1; ring r = 0, x(1..n), dp; int level = printlevel - voice + 2; // ---- To decide how much extra information calculate and display if (level > 1) { int e = d[1]; for (i = 2; i <= n; i++) { e = gcd(e,d[i]); } if (e <> 1) { print ("// Semigroup generated by d is not numerical!"); } } if (level > 0) { ideal id; vector mon; mon[max] = 0; if ((level > 1)&&(e == 1)) { bigint frob = 0; } } // ---- Trivial cases: n = 1,2 (it is a complete intersection). if (n == 1) { print("// Ideal is (0)"); return (1); } if (n == 2) { if (level > 0) { intvec d1 = d[1]; intvec d2 = d[2]; int f1 = MinMult(d[1],d2); int f2 = MinMult(d[2],d1); id = x(1)^(f1) - x(2)^(f2); print ("// Toric ideal:"); id; if ((level > 1)&&(e == 1)) { frob = d[1]*f1 - d[1] - d[2]; print ("// Frobenius number of the numerical semigroup:"); frob; } } return (1); } // ---- For n >= 3 (non-trivial cases) matrix mat[max][n]; intvec using, bound, multiple; multiple[max] = 0; bound[max] = 0; using[max] = 0; for (i = 1; i <= n; i++) { using[i] = 1; multiple[i] = 0; mat[i,i] = 1; } if (level > 1) { if (e == 1) { for (i = 1; i <= n; i++) { frob = frob - d[i]; } } } int new, new1, new2; for (i = 1; i <= n; i++) { for (j = 1; j < i; j++) { if (i <> j) { new = gcd(d[i],d[j]); new1 = d[j]/new; new2 = d[i]/new; if (!bound[i] ||(new1 < bound[i])) { bound[i] = new1; } if (!bound[j] ||(new2 < bound[j])) { bound[j] = new2; } } } } // ---- Begins the inductive part for (i = 1; i < n; i++) { // ---- n-1 stages for (j = 1; j < n + i; j++) { if ((using[j])&&(multiple[j] == 0)) { possible = 0; for (k = 1; (k < n + i)&&(!possible); k++) { if ((using[k])&&(k != j)&&(bigint(bound[k])*d[k] == bigint(bound[j])*d[j])) { possible = 1; } } if (possible) { // ---- If possible == 1, then c_j has to be computed intvec aux; // ---- auxiliary vector containing all d[l] in use except d[j] k = 1; for (l = 1; l < n + i; l++) { if (using[l] && (l != j)) { aux[k] = d[l]; k++; } } multiple[j] = MinMult(d[j], aux); kill aux; if (j <= n) { if (level > 0) { mon = mon + (x(j)^multiple[j])*gen(j); } } else { // ---- if j > n, it has to be checked if c_j belongs to a certain semigroup intvec aux, sup; k = 1; for (l = 1; l <= n; l++) { if (mat[j, l] <> 0) { sup[k] = l; aux[k] = d[l]; k++; } } if (level > 0) { mon = mon + (BelongSemig(bigint(multiple[j])*d[j], aux, sup))*gen(j); if (mon[j] == 0) { // ---- multiple[j]*d[j] does not belong to the semigroup generated by aux, // ---- then it is NOT a complete intersection return (0); } } else { if (!BelongSemig(bigint(multiple[j])*d[j], aux)) { // ---- multiple[j]*d[j] does not belong to the semigroup generated by aux, // ---- then it is NOT a complete intersection return (0); } } kill sup; kill aux; } // ---- Searching if there exist k such that multiple[k]*d[k]= multiple[j]*d[j] equal = 0; for (k = 1; k < n+i; k++) { if ((k <> j) && multiple[k] && using[k]) { if (d[j]*bigint(multiple[j]) == d[k]*bigint(multiple[k])) { // found equal = k; break; } } } // ---- if equal = 0 no coincidence if (!equal) { if (j == n + i - 1) { // ---- All multiple[k]*d[k] in use are different -> NOT complete intersection return (0); } } else { // ---- Next stage is prepared if (level > 0) { //---- New generator of the toric ideal id[i] = mon[j] - mon[equal]; if ((level > 1)&&(e == 1)) { frob = frob + bigint(multiple[j])*d[j]; } } //---- Two exponents are removed and one is added using[j] = 0; using[equal] = 0; using[n + i] = 1; d[n + i] = gcd(d[j], d[equal]); //---- new exponent for (l = 1; l <= n; l++) { mat[n + i, l] = mat[j, l] + mat[equal, l]; } // Bounds are reestablished for (l = 1; l < n+i; l++) { if (using[l]) { divide = gcd(d[l],d[n+i]); new = d[n+i] / divide; if ((multiple[l])&&(multiple[l] > new)) { return (0); } if (new < bound[l]) { bound[l] = new; } new = d[l] / divide; if ( !bound[n+i] || (new < bound[n+i])) { bound[n+i] = new; } } } break; } } } if (j == n + i - 1) { // ---- All multiple[k]*d[k] in use are different -> NOT complete intersection return (0); } } } if (level > 0) { "// Toric ideal: "; id; if ((level > 1)&&(e == 1)) { "// Frobenius number of the numerical semigroup: "; frob; } } return(1); } example { "EXAMPLE:"; printlevel = 0; intvec d = 14,15,10,21; CompInt(d); printlevel = 3; d = 36,54,125,150,225; CompInt(d); d = 45,70,75,98,147; CompInt(d); }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/cisimplicial.lib000066400000000000000000001373571266270727000213210ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////// category= "Commutative Algebra"; version="version cisimplicial.lib 4.0.0.0 Jun_2013 "; // $Id: b1e4c69c3130d49927f6191ddfb5770d163f2c3c $ info=" LIBRARY: cisimplicial.lib. Determines if the toric ideal of a simplicial toric variety is a complete intersection AUTHORS: I.Bermejo, ibermejo@ull.es @* I.Garcia-Marco, iggarcia@ull.es OVERVIEW: A library for determining if a simplicial toric ideal is a complete intersection with NO NEED of computing explicitly a system of generators of such ideal. The procedures are based on two papers: I. Bermejo, I. Garcia-Marco and J.J. Salazar-Gonzalez: 'An algorithm for checking whether the toric ideal of an affine monomial curve is a complete intersection', J. Symbolic Computation 42 (2007) pags: 971--991 and I.Bermejo and I. Garcia-Marco: 'Complete intersections in simplicial toric varieties', Preprint (2010) PROCEDURES: minMult(a,b); computes the minimum multiple of a that belongs to the semigroup generated by b belongSemigroup(v,A[,n]); checks whether A*x = v has a nonnegative integral solution oneDimBelongSemigroup(n,v[,m]); checks whether v*x = n has a nonnegative integral solution cardGroup(A); computes the cardinal of Z^m / ZA isCI(A); checks wether I(A) is a complete intersection "; LIB "general.lib"; ///////////////////////////////////////////////////////////////////// static proc Multiple(intvec v, intmat A, list #) " USAGE: Multiple(v,A[,n]); v is an integral vector, A is an integral matrix, n is an integer. RETURN: 0 if none of the [n first] columns of A divides the vector v or an intvec otherwise. In this case v = answer[2] * (answer[1]-th column of A). ASSUME: nrows(v) = nrows(A) [and n <= nrows(A)]. " { intvec answer; if (v == 0) { answer[1] = 1; answer[2] = 0; return (answer); } int last; int e = size(#); if (e > 0) { last = #[1]; } else { last = ncols(A); } int i,j,s; for (j = 1; j <= last; j++) { s = 0; for (i = 1; i <= nrows(A); i++) { if ((v[i] == 0)&&(A[i,j] != 0)) { // it is not multiple of A_j break; } if (v[i] != 0) { if (A[i,j] == 0) { // it is not multiple of A_j break; } if (s == 0) { s = v[i] div A[i,j]; } if (v[i] != s * A[i,j]) { break; } } if (i == nrows(A)) { answer[1] = j; answer[2] = s; // v = s * A_j return (answer); } } } // None of the columns of A divides v return (0); } ///////////////////////////////////////////////////////////////////// proc oneDimBelongSemigroup(int n, intvec v, list #) " USAGE: oneDimBelongSemigroup(n,v[,m]); v is an integral vector, n is a positive integer[, m is a positive integer]. RETURN: counters, a vector with nonnegative entries such that v*counters = n. If it does not exist such a vector, it returns 0. If a third parameter m is introduced, it will only consider the first m entries of v. ASSUME: v is an integral vector with positive entries. EXAMPLE: example oneDimBelongSemigroup; shows some examples. " { //--------------------------- initialisation --------------------------------- int i, j; int PartialSum; int num; int e = size(#); if (e > 0) { num = #[1]; } else { num = nrows(v); } intvec v2 = v[1..num]; intvec counter, belong; belong[num] = 0; counter[num] = 0; for (i = 1; i <= num; i++) { if (n % v[i] == 0) { // ---- n is multiple of v[i] belong[i] = n div v[i]; return (belong); } } if (num == 1) { // ---- num = 1 and n is not multiple of v[1] --> FALSE return(0); } PartialSum = 0; intvec w = sort(v2)[1]; intvec cambio = sort(v2)[2]; // ---- Iterative procedure to determine if n is in the semigroup generated by v while (1) { if (n >= PartialSum) { if (((n - PartialSum) % w[1]) == 0) { // ---- n belongs to the semigroup generated by v, belong[cambio[1]] = (n - PartialSum) div w[1]; for (j = 2; j <= num; j++) { belong[cambio[j]] = counter[j]; } return(belong); } } i = num; while (!defined(end)) { if (i == 1) { // ---- Stop, n is not in the semigroup return(0); } if (i > 1) { // counters control if (w[i] > n - PartialSum) { PartialSum = PartialSum - (counter[i]*w[i]); counter[i] = 0; i--; } else { counter[i] = counter[i] + 1; PartialSum = PartialSum + w[i]; int end; } } } kill end; } } example { "EXAMPLE:";echo=2; int a = 95; intvec v = 18,51,13; oneDimBelongSemigroup(a,v); "// 95 = 1*18 + 1*25 + 2*13"; oneDimBelongSemigroup(a,v,2); "// 95 is not a combination of 18 and 52;"; } ///////////////////////////////////////////////////////////////////// proc SBelongSemigroup (intvec v, intmat A, list #) " USAGE: SBelongSemigroup(v,A[,k]); v is an integral vector, A is an integral matrix, n is a positive integer. RETURN: counters, a vector with nonnegative entries such that A*counters = v. If it does not exist such vector, it returns 0. If a third parameter k is introduced, it will only consider the first k columns of A. ASSUME: A is an m x n matrix with nonnegative entries, n >= m, for every i,j <= m, i != j then A[i,j] = 0, v has nonnegative entries and nrows(v) = nrows(A); " { int last; int e = size(#); if (e > 0) { last = #[1]; } else { last = ncols(A); } intvec counters; counters[last] = 0; int i, j, k, l; intvec d; for (i = 1; i <= nrows(A); i++) { d[i] = A[i,i]; } i = 1; while ((i < nrows(v)) && (v[i] % d[i] == 0)) { i++; } if (v[i] % d[i] == 0) { // v is a combination of the first nrows(A) columns for (j = 1; j <= nrows(v); j++) { counters[j] = v[j] div d[j]; } return(counters); } int gcdrow; for (i = 1; i <= nrows(A); i++) { gcdrow = d[i]; for (j = nrows(A)+1; j <= last; j++) { if (A[i,j] != 0) { gcdrow = gcd(gcdrow,A[i,j]); } } if (v[i] % gcdrow != 0) { return (0); } } intvec swap; for (i = 1; i <= last; i++) { swap[i] = i; } for (i = nrows(A) + 1; i <= last; i++) { for (j = 1; j <= nrows(v); j++) { if (A[j,i] > v[j]) { swap[i] = 0; for (k = 1; k <= nrows(A); k++) { A[k,i] = A[k,last]; } swap[i] = swap[last]; last--; i--; break; } } } if (nrows(A) == last) { return (0); } intvec order; order[last] = 0; for (i = nrows(A) + 1; i <= last; i++) { order[i] = 1; for (j = 1; j <= nrows(A); j++) { if (A[j,i] > 0) { order[i] = lcm(order[i], d[j] div gcd(A[j,i],d[j])); } } } intvec counters2; counters2[last] = 0; // A full enumeration is performed while(1) { i = nrows(counters2); while (1) { j = 1; if (counters2[i] < order[i] - 1) { while ((j < nrows(A)) and (v[j] >= A[j,i])) { j++; } } if ((v[j] < A[j,i])||(counters2[i] == order[i] - 1)) { // A_j is not < v componentwise or counters2 = order[i] // we cannot increase counters2[i] if (counters2[i] != 0) { for (k = 1; k <= nrows(v); k++) { v[k] = v[k] + counters2[i] * A[k,i]; } counters2[i] = 0; } i--; if (i <= nrows(A)) { // A*x = v has not nonnegative integral solution return(0); } } else { // j = nrows(A), then A_j < v (componentwise) // we add one unit to counters2[i] for (k = 1; k <= nrows(v); k++) { v[k] = v[k] - A[k,i]; } counters2[i] = counters2[i] + 1; l = 1; while ((l < nrows(v)) and (v[l] % d[l] == 0)) { l++; } if (v[l] % d[l] == 0) { // v is a combination of the first nrows(A) columns for (k = 1; k <= nrows(v); k++) { counters[k] = v[k] div d[k]; } for (k = nrows(v) + 1; k <= nrows(counters2); k++) { counters[swap[k]] = counters2[k]; } // A*counters = v return(counters); } break; } } } } ///////////////////////////////////////////////////////////////////// proc belongSemigroup (intvec v, intmat A, list #) " USAGE: belongSemigroup(v,A[,k]); v is an integral vector, A is an integral matrix, n is a positive integer. RETURN: counters, a vector with nonnegative entries such that A*counters = v. If it does not exist such a vector, it returns 0. If a third parameter k is introduced, it will only consider the first k columns of A. ASSUME: A is a matrix with nonnegative entries, nonzero colums, v is a nonnegative vector and nrows(v) = nrows(A). EXAMPLE: example belongSemigroup; shows some examples. " { int inputlast; int e = size(#); if (e > 0) { inputlast = #[1]; } else { inputlast = ncols(A); } int i, j, k; intvec counters; int last = inputlast; if (last == 0) { return (counters); } intvec swap; for (i = 1; i <= last; i++) { swap[i] = i; } for (i = 1; i <= last; i++) { for (j = 1; j <= nrows(v); j++) { if (A[j,i] > v[j]) { swap[i] = 0; for (k = 1; k <= nrows(A); k++) { A[k,i] = A[k,last]; } swap[i] = swap[last]; last--; i--; break; } } } if (last == 0) { return (0); } intvec multip = Multiple(v, A, last); if (multip != 0) { intvec counters2; counters2[inputlast] = 0; // v = mult.value * ((mult.column)-th column of A) counters2[swap[multip[1]]] = multip[2]; return (counters2); } counters[last] = 0; // A full enumeration is performed // Example: si v = (3,2,6), a1 = (1,0,0), a2 = (0,1,1), a3 = (0,0,1), then counters will take the // following values: // 000, 001, 002, 003, 004, 005, 006, 010, 011, 012, 013, 014, 015, 020, 021, 022, 023, 024 ---> 324 while(1) { i = nrows(counters); while (1) { j = 1; while (j <= nrows(A)) { if (v[j] < A[j,i]) { break; } j++; } if (j <= nrows(A)) { if (counters[i] != 0) { for (k = 1; k <= nrows(A); k++) { v[k] = v[k] + counters[i] * A[k,i]; } counters[i] = 0; } i--; if (i < 2) { // Does not belong return (0); } } else { for (k = 1; k <= nrows(A); k++) { v[k] = v[k] - A[k,i]; } counters[i] = counters[i] + 1; multip = Multiple(v, A, i); if (multip != 0) { // v belongs, we return the solution counters so that A * counters = v counters[multip[1]] = multip[2]; intvec counters2; counters2[inputlast] = 0; for (i = 1; i <= last; i++) { counters2[swap[i]] = counters[i]; } return (counters2); } break; } } } } example { "EXAMPLE:"; echo=2; intmat A[3][4] = 10,3,2,1,2,1,1,3,5,0,1,2; print(A); intvec v = 23,12,10; belongSemigroup(v,A); "// A * (1,3,1,2) = v"; belongSemigroup(v,A,3); "// v is not a combination of the first 3 columns of A"; intvec w = 12,4,1; belongSemigroup(w,A); "// w is not a combination of the columns of A"; } ///////////////////////////////////////////////////////////////////// proc cardGroup(intmat A, list #) " USAGE: cardGroup(A[,n]); A is a matrix with integral coefficients. RETURN: It returns a bigint. If we denote by ZA the group generated by the columns of the matrix A, then it returns the number of elements of the group of Z^m / ZA, where m = number of rows of A. If a second parameter n is introduced, it will only consider the first n columns of A. It returns 0 if Z^m / ZA is infinite; this is, when rank ZA < m. EXAMPLE: example cardGroup; shows an example. " { int i, j, k, l; int coef1, coef2, aux; bigint aux2, aux3; list gcdiv; int last; int e = size(#); if (e > 0) { last = #[1]; } else { last = ncols(A); } // First we put the matrix A in diagonal form. for (i = 1; i <= nrows(A); i++) { j = i; while (A[i,j] == 0) { j++; if (j > last) { return (0); // Group is infinite } } if (j > i) { for (k = i; k <= nrows(A); k++) { // swap columns to have a nonzero pivot aux = A[k,i]; A[k,i] = A[k,j]; A[k,j] = aux; } } for (k = j+1; k <= last; k++) { if (A[i,k] != 0) { gcdiv = extgcd(A[i,i],A[i,k]); coef1 = A[i,k] div gcdiv[1]; coef2 = A[i,i] div gcdiv[1]; for (l = i; l <= nrows(A); l++) { // Perform elemental operations in the matrix // to put A in diagonal form aux2 = bigint(gcdiv[2]) * bigint(A[l,i]) + bigint(gcdiv[3]) * bigint(A[l,k]); aux3 = bigint(coef1) * bigint(A[l,i]) - bigint(coef2) * bigint(A[l,k]); A[l,k] = int(aux3); A[l,i] = int(aux2); } } } } // Once the matrix is in diagonal form, we only have to multiply // the diagonal elements bigint determinant = bigint(A[1,1]); bigint entry; for (i = 2; i <= nrows(A); i++) { entry = bigint(A[i,i]); determinant = determinant * entry; } determinant = absValue(determinant); return(determinant); } example { "EXAMPLE:"; echo=2; intmat A[3][5] = 24, 0, 0, 8, 3, 0, 24, 0, 10, 6, 0, 0, 24, 5, 9; cardGroup(A); } /////////////////////////////////////////////////////////////////////////////////////////////////////////// proc minMult(int a, intvec b) " USAGE: minMult (a, b); a integer, b integer vector. RETURN: an integer k, the minimum positive integer such that k*a belongs to the semigroup generated by the integers in b. ASSUME: a is a positive integer, b is a vector of positive integers. EXAMPLE: example minMult; shows an example. " { //--------------------------- initialisation --------------------------------- int i, j, min, max; int n = nrows(b); if (n == 1) { // ---- trivial case return(b[1]/gcd(a,b[1])); } max = b[1]; for (i = 2; i <= n; i++) { if (b[i] > max) { max = b[i]; } } int NumNodes = a + max; //----Number of nodes in the graph int dist = 1; // ---- Auxiliary structures to obtain the shortest path between the nodes 1 and a+1 of this graph intvec queue = 1; intvec queue2; // ---- Control vector: // control[i] = 0 -> node not reached yet // control[i] = 1 -> node in queue1 // control[i] = 2 -> node in queue2 // control[i] = 3 -> node already processed intvec control; control[1] = 3; // Starting node control[a + max] = 0; // Ending node int current = 1; // Current node int next; // Node connected to corrent by arc (current, next) int ElemQueue, ElemQueue2; int PosQueue = 1; // Algoritmo de Dijkstra while (1) { if (current <= a) { // ---- current <= a, arcs are (current, current + b[i]) for (i = 1; i <= n; i++) { next = current + b[i]; if (next == a+1) { kill control; kill queue; kill queue2; return (dist); } if ((control[next] == 0)||(control[next] == 2)) { control[next] = 1; queue = queue, next; } } } if (current > a) { // ---- current > a, the only possible ars is (current, current - a) next = current - a; if (control[next] == 0) { control[next] = 2; queue2[nrows(queue2) + 1] = next; } } PosQueue++; if (PosQueue <= nrows(queue)) { current = queue[PosQueue]; } else { dist++; if (control[a+1] == 2) { return(dist); } queue = queue2[2..nrows(queue2)]; current = queue[1]; PosQueue = 1; queue2 = 0; } control[current] = 3; } } example { "EXAMPLE:";echo=2; int a = 46; intvec b = 13,17,59; minMult(a,b); "// 3*a = 8*b[1] + 2*b[2]" } ///////////////////////////////////////////////////////////////////// static proc CheckMin (int posiblemin, intmat A, int column, list #) " USAGE: CheckMin(posiblemin,A,column[,n]); posiblemin is an integer, A is an integral matrix and column and last are integers. RETURN: 1 if posiblemin is the minimum value x such that x * (column-th colum of A) belongs to the semigroup generated by all the columns of A except A_column. It returns 0 otherwise. If an extra parameter n is introduced then it will only consider the first n columns of A. ASSUME: 1 <= column <= ncols(A), A does not have negative entries or zero columns " { // If one can write (posiblemin-1)*A_column as a non-trivial combination of the // colums of A, then posiblemin is > to the real minimum intvec counters, multip; counters[ncols(A)] = 0; int i,j,k; int last; int e = size(#); if (e > 0) { last = #[1]; } else { last = ncols(A); } intvec v, aux; for (i = 1; i <= nrows(A); i++) { v[i] = (posiblemin-1)*A[i,column]; // We swap A_column with A_1 aux[i] = A[i,1]; A[i,1] = A[i,column]; A[i,column] = aux[i]; } for (i = 2; i <= last; i++) { for (j = 1; j <= nrows(v); j++) { if (A[j,i] > v[j]) { for (k = 1; k <= nrows(A); k++) { A[k,i] = A[k,last]; } last--; i--; break; } } } // A full enumeration is performed while(1) { i = last; while (1) { j = 1; while (j <= nrows(A)) { if (v[j] < A[j,i]) { break; } j++; } if (j <= nrows(A)) { if (counters[i] != 0) { for (k = 1; k <= nrows(A); k++) { v[k] = v[k] + counters[i] * A[k,i]; } counters[i] = 0; } i--; if (i == 1) { // The only solution is that v = (posiblemin-1)*A.col[1] return (1); } } else { for (k = 1; k <= nrows(A); k++) { v[k] = v[k] - A[k,i]; } counters[i] = counters[i]+1; multip = Multiple(v, A, i); if (multip != 0) { return (0); } break; } } } } ///////////////////////////////////////////////////////////////////// static proc SimplicialCheckMin (int posiblemin, intmat A, int column, list #) " USAGE: SimplicialCheckMin(posiblemin,A,column[,last]); posiblemin is an integer, A is an integral matrix and column and last are integers. RETURN: 1 if posiblemin is less or equal to the minimum value x such that x * A_column belongs to the semigroup generated by all the columns of A except A_column. It returns 0 otherwise. If an extra parameter last is introduced then it will only consider the first n columns of A. ASSUME: 1 <= column <= ncols(A), A does not have negative entries or zero columns A[i,j] = 0 for all 1 <= i,j <= nrows(A) where i != j " { // If one can write (posiblemin-1)*A_column as a non-trivial combination of the // colums of A, then posiblemin is > than the real minimum int last; int e = size(#); if (e > 0) { last = #[1]; } else { last = ncols(A); } int i, j, k, l; intvec d, v; for (i = 1; i <= nrows(A); i++) { d[i] = A[i,i]; } for (i = 1; i <= nrows(A); i++) { v[i] = A[i,column] * (posiblemin-1); } i = 1; while ((i < nrows(v)) && (v[i] % d[i] == 0)) { i++; } if (v[i] % d[i] == 0) { // v is a combination of the first nrows(A) columns return(0); } int aux; for (i = 1; i <= nrows(A); i++) { aux = A[i,nrows(A)+1]; A[i,nrows(A)+1] = A[i,column]; A[i,column] = aux; } for (i = nrows(A) + 2; i <= last; i++) { for (j = 1; j <= nrows(v); j++) { if (A[j,i] > v[j]) { for (k = 1; k <= nrows(A); k++) { A[k,i] = A[k,last]; } last--; i--; break; } } } intvec order; order[last] = 0; for (i = nrows(A) + 1; i <= last; i++) { order[i] = 1; for (j = 1; j <= nrows(A); j++) { if (A[j,i] > 0) { order[i] = lcm(order[i], d[j] div gcd(A[j,i],d[j])); } } } if (order[nrows(A)+1] < posiblemin-1) { return (0); } order[nrows(A)+1] = posiblemin-1; intvec counters; counters[last] = 0; // A full enumeration is performed while(1) { i = last; while (1) { j = 1; if (counters[i] < order[i] - 1) { while ((j < nrows(A)) and (v[j] >= A[j,i])) { j++; } } if ((v[j] < A[j,i])||(counters[i] == order[i] - 1)) { // A_j is not < v componentwise or counters = order[i]-1 // we cannot increase counters[i] if (counters[i] != 0) { for (k = 1; k <= nrows(v); k++) { v[k] = v[k] + counters[i] * A[k,i]; } counters[i] = 0; } i--; if (i <= nrows(A)) { // A*x = v has not nonnegative integral solution different // from the trivial one return(1); } } else { // j = nrows(A), then A_j < v (componentwise) // we add one unit to counters[i] for (k = 1; k <= nrows(v); k++) { v[k] = v[k] - A[k,i]; } counters[i] = counters[i] + 1; l = 1; while ((l < nrows(v)) and (v[l] % d[l] == 0)) { l++; } if (v[l] % d[l] == 0) { // v is a combination of the first nrows(A) columns return(0); } break; } } } } ///////////////////////////////////////////////////////////////////// static proc Proportional(intvec a, intvec b) " USAGE: Proportional(a,b); a,b integral vectors RETURN: 1 if nrows(a) = nrows(b) and the vectors a and b are proportional; this is, there exist a rational number k such that k*a = b, and 0 otherwise ASSUME: a, b are nonzero vectors " { if (nrows(a) != nrows(b)) { return (0) } int i, pivot; pivot = 1; while (a[pivot] == 0) { if (b[pivot] != 0) { // Not proportional return (0); } pivot++; } if (b[pivot] == 0) { // Not proportional return (0); } for (i = pivot + 1; i <= nrows(a); i++) { if (a[i] * b[pivot] != a[pivot] * b[i]) { // Not proportional return (0); } } return (1); } ///////////////////////////////////////////////////////////////////// static proc StimatesMin(intmat A, int column, intvec line, list #) " USAGE: StimatesMin(A,column,line[,n]); A is an integral matrix, column is an integer, line is an integral vector and n is an integer. RETURN: The minimum integer k such that k * A_column belongs to the semigroup generated by all the columns of A except A_column. It returns 0 if it is not necessary to compute for the main program. If an extra parameter n is introuduced it considers the first n colums of A. ASSUME: 1 <= column [<= n] <= ncols(A), A has nonnegative entries, line is a vector such that line[i] = line[j] if and only if the i-th and j-th columns of A are proportional " { int last; int e = size(#); if (e > 0) { last = #[1]; } else { last = nrows(line); } intvec current; int i,j,k; for (i = 1; i <= nrows(A); i++) { current[i] = A[i,column]; } int nonzero = 1; while (current[nonzero] == 0) { nonzero++; } // We will only consider those colums A_j such that line[j] = line[column] intvec prop, jthcolumn; for (j = 1; j <= last; j++) { if (j != column) { if (line[column] == line[j]) { prop[nrows(prop)+1] = A[nonzero,j]; } } } int posiblemin = 0; if (prop[nrows(prop)] > 0) { // 1-dim minimum posiblemin = minMult(current[nonzero],prop); } if (line[column] <= nrows(A)) { // It is not necessary to do CheckMin return(posiblemin); } if (posiblemin > 0) { if (SimplicialCheckMin(posiblemin, A, column, last)) { // It is the real minimum, otherwise minimum < posiblemin return (posiblemin); } } // Not necessary to compute the minimum explicitly return (0); } ///////////////////////////////////////////////////////////////////// proc isCI(intmat A) " USAGE: isCI(A); A is an integral matrix RETURN: 1 if the simplicial toric ideal I(A) is a complete intersection and 0 otherwise. If printlevel > 0 and I(A) is a complete intersection it also shows a minimal set of generators of I(A) ASSUME: A is an m x n integral matrix with nonnegative entries and for every 1 <= i <= m, there exist a column in A whose i-th coordinate is not null and the rest are 0. EXAMPLE: example isCI; shows some examples " { //--------------------------- initialisation --------------------------------- intvec d; intvec minimum; intvec swap; // swap[i] = j if and only if the i-th column of B equals the j-th column of A intvec line; // line[i] = line[j] if and only if the i-th and the j-th column of B are proportional int n, m; // Size of the input int i,j,k,l,t; n = ncols(A); m = nrows(A); intmat B[m][n]; // auxiliary matrix intmat support[2*n-m][n]; // support[i,j] = 1 if and only if a_j belongs to V_i if (printlevel > 0) { ring r = 0,x(1..n),dp; ideal toric; // In case I(A) is a complete intersection, we obtain a // minimal set of generators } for (i = 1; i <= n; i++) { int zero = 0; swap[i] = i; for (j = 1; j <= m; j++) { B[j,i] = A[j,i]; if (B[j,i] > 0) { zero++; } if (B[j,i] < 0) { print("// There are negative entries in the matrix"); return (0); } } if (zero == 0) { print ("// There is a zero column in the matrix"); return (0); } kill zero; } //--------------------------- preprocessing the input --------------------------------- int aux, found; // We write B in a standard form; this is, for 1 <= i,j <= m, j != i then B[i,j] = 0 for (i = 1; i <= m; i++) { j = i; found = 0; while (j <= n) { if (B[i,j] != 0) { k = 1; while ((k == i)||(B[k,j] == 0)) { k++; if (k == m+1) { for (l = 1; l <= m; l++) { aux = B[l,j]; B[l,j] = B[l,i]; B[l,i] = aux; } aux = swap[j]; swap[j] = swap[i]; swap[i] = aux; found = 1; break; } } } if (found == 1) { break; } j++; } if (j == n+1) { print("// There exists an i such that no column in A has the i-th coordinate positive and the rest are 0."); // It is not simplicial return (0); } } // Initialisation of variables int numgens = 0; // number of generators built for (i = 1; i <= n; i++) { support[i,i] = 1; } intvec ithcolumn, jthcolumn, belong; int numcols = ncols(B); line[numcols] = 0; // line[i] = line[j] if and only if B_i and B_j are proportional. // Moreover for i = 1,...,nrows(B) we have that line[i]= i for (i = 1; i <= numcols; i++) { if (line[i] == 0) { for (j = 1; j <= nrows(B); j++) { ithcolumn[j] = B[j,i]; } line[i] = i; for (j = i+1; j <= numcols; j++) { for (k = 1; k <= nrows(B); k++) { jthcolumn[k] = B[k,j]; } if (Proportional(ithcolumn, jthcolumn)) { line[j] = i; } } } } //----------------- We apply reduction --------------- bigint det1, det2; int minim, swapiold, lineiold; int change = 1; det1 = cardGroup(B,numcols); while (change == 1) { change = 0; for (i = 1; i <= numcols; i++) { for (j = 1; j <= m; j++) { ithcolumn[j] = B[j,i]; B[j,i] = B[j,numcols]; } swapiold = swap[i]; swap[i] = swap[numcols]; lineiold = line[i]; line[i] = line[numcols]; det2 = cardGroup(B,numcols-1); minim = int(det2/det1); if (lineiold > m) { belong = SBelongSemigroup(minim*ithcolumn,B,numcols-1); if (belong != 0) { // It belongs, we remove the ith column if (printlevel > 0) { // Create a generator poly mon1 = x(swapiold)^(minim); poly mon2 = 1; for (j = 1; j <= nrows(belong); j++) { mon2 = mon2 * x(swap[j])^(belong[j]); } toric = toric, mon1-mon2; kill mon1; kill mon2; } det1 = det2; change = 1; numgens++; numcols--; i--; } } else { // line[i] <= m intvec semigroup, supportmon; int position; for (j = 1; j <= numcols-1; j++) { if (line[j] == lineiold) { position = j; semigroup = semigroup, B[lineiold,j]; supportmon = supportmon, swap[j]; } } if (semigroup == 0) { belong = 0; } else { semigroup = semigroup[2..nrows(semigroup)]; supportmon = supportmon[2..nrows(supportmon)]; belong = oneDimBelongSemigroup(minim*ithcolumn[lineiold],semigroup); } if (belong != 0) { // It belongs, we remove the ith column if (printlevel > 0) { // We create a generator poly mon1,mon2; mon1 = x(swapiold)^(minim); mon2 = 1; for (j = 1; j <= nrows(supportmon); j++) { mon2 = mon2 * x(supportmon[j])^(belong[j]); } toric = toric, mon1-mon2; kill mon1, mon2; } det1 = det2; numcols--; numgens++; change = 1; if (i <= m) { // We put again B in standard form if (position != i) { for (j = 1; j <= m; j++) { aux = B[j,position]; B[j,position] = B[j,i]; B[j,i] = aux; } aux = swap[i]; swap[i] = swap[position]; swap[position] = aux; aux = line[i]; line[i] = line[position]; line[position] = aux; } } i--; } kill position; kill semigroup; kill supportmon; } if (belong == 0) { for (j = 1; j <= m; j++) { B[j,i] = ithcolumn[j]; } swap[i] = swapiold; line[i] = lineiold; } } } // Initialisation of variables minimum[numcols] = 0; //----------------- We run the first part of the algorithm --------------- // Estimation of m_i with i = 1,...,n for (i = 1; i <= numcols; i++) { minimum[i] = StimatesMin(B,i,line,numcols); } int nonzero; int stagenumber = 0; change = 1; while (change == 1) { // If for every i,j we have that m_i*B_i != m_j*B_j we leave the while loop change = 0; for (i = 1; (i <= numcols) && (change == 0); i++) { if (minimum[i] != 0) { for (j = i+1; (j <= numcols) && (change == 0); j++) { if ((minimum[j] != 0)&&(line[i] == line[j])) { // We look for a nonzero entry in B_i nonzero = 1; while (B[nonzero,i] == 0) { nonzero++; } if (minimum[i]*B[nonzero,i] == minimum[j]*B[nonzero,j]) { // m_i b_i = m_j b_j numgens++; stagenumber++; if (swap[i] <= n) { // For k = swap[i], we have that V_k = {b_i}, so m_i b_i belongs to V_k if (printlevel > 0) { poly mon1 = x(swap[i])^(minimum[i]); } } else { // We check wether m_i b_i belongs to the semigroup generated by V_k // where k = swap[i]. All vectors in V_k are proportional to b_i intvec checkbelong; int miai; intvec supporti; miai = minimum[i]*B[nonzero,i]; for (k = 1; k <= n; k++) { if (support[swap[i],k]) { supporti = supporti, k; checkbelong[nrows(supporti)-1] = A[nonzero,k]; } } // 1-dim belong semigroup belong = oneDimBelongSemigroup(miai,checkbelong); if (belong == 0) { // It does not belong print ("// It is NOT a complete intersection"); return (0); } if (printlevel > 0) { poly mon1 = 1; // It belongs, we construct a monomial of the new generator for (k = 1; k < nrows(supporti); k++) { mon1 = mon1 * x(supporti[k+1])^(belong[k]); } } kill miai; kill checkbelong; kill supporti; } if (swap[j] <= n) { // For k = swap[j], we have that V_k = {b_j}, so m_j b_j belongs to V_k if (printlevel > 0) { poly mon2 = x(swap[j])^(minimum[j]); toric = toric, mon1-mon2; kill mon1; kill mon2; } } else { // We check wether m_j b_j belongs to the semigroup generated by V_k // where k = swap[j]. All vectors in V_k are proportional to b_j intvec checkbelong; int mjaj; intvec supportj; nonzero = 1; while (B[nonzero,j] == 0) { nonzero++; } mjaj = minimum[j]*B[nonzero,j]; for (k = 1; k <= n; k++) { if (support[swap[j],k]) { supportj = supportj, k; checkbelong[nrows(supportj)-1] = A[nonzero,k]; } } // 1-dim belong semigroup belong = oneDimBelongSemigroup(mjaj,checkbelong); if (belong == 0) { // It does not belong print ("// It is NOT a complete intersection"); return (0); } if (printlevel > 0) { poly mon2 = 1; // It belongs, we construct the second monomial of the generator for (k = 1; k < nrows(supportj); k++) { mon2 = mon2 * x(supportj[k+1])^(belong[k]); } toric = toric,mon1-mon2; kill mon1; kill mon2; } kill checkbelong; kill mjaj; kill supportj; } // Now we remove b_i, b_j from B and we add gcd(b_i,b_j) change = 1; for (k = 1; k <= n; k++) { // V_{support.nrows} = V_i + V_j support[n+stagenumber,k] = support[swap[i],k] + support[swap[j],k]; } // line[i] does not change line[j] = line[numcols]; swap[i] = n+stagenumber; swap[j] = swap[numcols]; k = 1; while (B[k,i] == 0) { k++; } int dp; dp = gcd(B[k,i], B[k,j]); int factor = B[k,i] div dp; B[k,i] = dp; k++; kill dp; while (k <= nrows(B)) { B[k,i] = B[k,i] / factor; k++; } kill factor; for (k = 1; k <= nrows(B); k++) { B[k,j] = B[k,numcols]; } minimum[j] = minimum[numcols]; numcols--; // We compute a new m_i minimum[i] = StimatesMin(B,i,line,numcols); } } } } } } //--------------------------- We apply reduction --------------------------------- intvec minZ; for (i = 1; i <= n+stagenumber; i++) { minZ[i] = 1; } det1 = cardGroup(B,numcols); int posaux; intvec counters1,counters2; while (numgens < n - m) { change = 0; i = nrows(B) + 1; while ((i <= numcols)&&(numgens < n-m)) { // The vector we are going to study for (j = 1; j <= nrows(B); j++) { ithcolumn[j] = B[j,i]; B[j,i] = B[j,numcols]; } posaux = swap[i]; swap[i] = swap[numcols]; numcols--; det2 = cardGroup(B,numcols); minim = int(det2/det1); if (minim != 1) { // If minimum = 1, we have previously checked that current does not belong to // the semigroup generated by the columns of B. for (j = 1; j <= nrows(B); j++) { ithcolumn[j] = ithcolumn[j]*minim; } minZ[posaux] = minim * minZ[posaux]; det1 = det2; // det1 *= minimum intvec support1, support2; nonzero = 1; while (ithcolumn[nonzero] == 0) { nonzero++; if (nonzero > nrows(ithcolumn)) { print("// ERROR"); return (0); } } int currentnonzero = ithcolumn[nonzero]; intvec B1; for (j = 1; j <= n; j++) { if (support[posaux,j]) { // a_j is proportional to b_i = a_posaux support1 = support1, j; B1[nrows(support1)-1] = A[nonzero,j]; } } // 1-dim belongsemigroup counters1 = oneDimBelongSemigroup(currentnonzero, B1); kill currentnonzero; kill B1; if (counters1 != 0) { intmat B2[m][n]; // It belongs, now we have to check if current belongs to the semigroup // generated by the columns of B2 for (j = 1; j <= numcols; j++) { for (k = 1; k <= n; k++) { if (support[swap[j],k]) { // a_k may not be proportional to b_i = a_posaux support2 = support2, k; for (l = 1; l <= m; l++) { B2[l,nrows(support2)-1] = A[l,k]; } } } } // We write B2 in standard form for (l = 1; l <= m; l++) { j = l; found = 0; while (found == 0) { if (B2[l,j] != 0) { k = 1; while ((k == l)||(B2[k,j] == 0)) { k++; if (k == m + 1) { for (t = 1; t <= m; t++) { jthcolumn[t] = B2[t,j]; B2[t,j] = B2[t,l]; B2[t,l] = jthcolumn[t]; } aux = support2[j+1]; support2[j+1] = support2[l+1]; support2[l+1] = aux; found = 1; break; } } } j++; } } // m-dim belong semigroup counters2 = SBelongSemigroup(ithcolumn, B2, nrows(support2)-1); kill B2; if (counters2 != 0) { // current belongs, we construct the new generator numgens++; if (printlevel > 0) { poly mon1, mon2; mon1 = 1; mon2 = 1; for (j = 1; j < nrows(support1); j++) { mon1 = mon1 * x(support1[j+1])^(counters1[j]); } for (j = 1; j < nrows(support2); j++) { mon2 = mon2 * x(support2[j+1])^(counters2[j]); } toric = toric, mon1-mon2; kill mon1; kill mon2; } if (i != numcols) { i--; } change = 1; // We have removed a column of B } } kill support1,support2; } if ((counters1 == 0)||(counters2 == 0)||(minim == 1)) { // We swap again the columns in B for (j = 1; j <= m; j++) { B[j,i] = ithcolumn[j]; } numcols++; swap[numcols] = swap[i]; swap[i] = posaux; } if ((i == numcols)&&(change == 0)) { print(" // It is NOT a Complete Intersection."); return (0); } i++; } } // We have removed all possible columns if (printlevel > 0) { print("// Generators of the toric ideal"); toric = simplify(toric,2); toric; } print("// It is a complete intersection"); return(1); } example { "EXAMPLE:"; echo=2; intmat A[2][5] = 60,0,140,150,21,0,60,140,150,21; print(A); printlevel = 0; isCI(A); printlevel = 1; isCI(A); intmat B[3][5] = 12,0,0,1,2,0,10,0,3,2,0,0,8,3,3; print(B); isCI(B); printlevel=0; } singular-4.0.3+ds/Singular/LIB/classify.lib000066400000000000000000002712651266270727000204710ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version classify.lib 4.0.2.0 Apr_2015 "; // $Id: 5f28162ecb414c8e68253cf3ee6b0e86d04ae364 $ category="Singularities"; info=" LIBRARY: classify.lib Arnold Classifier of Singularities AUTHOR: Kai Krueger, krueger@mathematik.uni-kl.de OVERVIEW: A library for classifying isolated hypersurface singularities w.r.t. right equivalence, based on the determinator of singularities by V.I. Arnold. SEE ALSO: realclassify_lib PROCEDURES: basicinvariants(f); computes Milnor number, determinacy-bound and corank of classify(f); normal form of polynomial f determined with Arnold's method corank(f); computes the corank of f (i.e. of the Hessian of f) Hcode(v); coding of intvec v acoording to the number repetitions init_debug([n]); print trace and debugging information depending on int n internalfunctions();display names of internal procedures of this library milnorcode(f[,e]); Hilbert polynomial of [e-th] Milnor algebra coded with Hcode morsesplit(f); residual part of f after applying the splitting lemma quickclass(f) normal form of f determined by invariants (milnorcode) singularity(s,[]); normal form of singularity given by its name s and index A_L(s/f); shortcut for quickclass(f) or normalform(s) normalform(s); normal form of singularity given by its name s debug_log(lev,[]); print trace and debugging information w.r.t level>@DeBug swap(a,b); swaps the arguments modality(f); modality of the singularity complexSingType(f); complex type of the singularity as a string prepRealclassify(f); the modality and the complex type of the singularity at once (parameters in square brackets [] are optional) "; LIB "inout.lib"; LIB "elim.lib"; LIB "sing.lib"; LIB "makedbm.lib"; /////////////////////////////////////////////////////////////////////////////// proc classify_init { string s; link l="DBM:r NFlist"; s = read(l,"VERSION"); if (s == "" ) { if (printlevel > 0) { "(classify.lib): Need to create database..."; } create_sing_dbm(); } close(l); l="DBM:r NFlist"; s = read(l,"VERSION"); //"(classify.lib): Creation done. Current version:", s; } /////////////////////////////////////////////////////////////////////////////// proc classify (poly f_in) "USAGE: classify(f); f=poly COMPUTE: normal form and singularity type of f with respect to right equivalence, as given in the book \"Singularities of differentiable maps, Volume I\" by V.I. Arnold, S.M. Gusein-Zade, A.N. Varchenko RETURN: normal form of f, of type poly REMARK: This version of classify is only beta. Please send bugs and comments to: \"Kai Krueger\" @* Be sure to have at least @sc{Singular} version 1.0.1. Updates can be found at: @* URL=http://www.mathematik.uni-kl.de/~krueger/Singular/ NOTE: type init_debug(n); (0 <= n <= 10) in order to get intermediate information, higher values of n give more information. The proc creates several global objects with names all starting with @, hence there should be no name conflicts. EXAMPLE: example classify; shows an example" { //---------------------------- initialisation --------------------------------- poly f_out; int n, i, corank, show_nf; string s2; list v; def ring_ext = basering; // Namespaces: if(defined(A_Z)==0) { proc A_Z = General::A_Z; export A_Z; } init_debug(); // initialize trace/debug mode if(checkring()) { return(f_in); } n = nvars(basering); show_nf = 1; // return normal form if set to '1' // define new ring ring ring_top=char(basering),(x(1..n)),(c,ds); map conv_ext2top=ring_ext,maxideal(1); if(defined(@ringdisplay)!=0) { kill @ringdisplay; } string @ringdisplay = "ring_ext"; export @ringdisplay; v = Klassifiziere(conv_ext2top(f_in)); if(typeof(v[1])=="poly") { poly f_out = v[1]; s2 = v[2]; // s2: Typ des Polynoms f z.b: E[18] corank = v[3]; } else { s2="NoClass"; } //---------------- collect results and create return-value -------------------- if( s2=="error!" || s2=="NoClass") { setring ring_ext; return(f_in); } if(show_nf==1) { poly f_nf = normalform(s2); for(i=corank+1;i<=n;i=i+1) { f_nf = f_nf + x(i)^2; } debug_log(2, "Normal form NF(f)=", f_nf); } if(corank>1) { for(i=corank+1;i<=n;i=i+1) { f_out = f_out + x(i)^2; } } setring ring_ext; map conv_top2ext=ring_top,maxideal(1); if(show_nf == 1) { return(conv_top2ext(f_nf)); } else { return(conv_top2ext(f_out)); } } example {"EXAMPLE"; echo=2; ring r=0,(x,y,z),ds; poly f=(x2+3y-2z)^2+xyz-(x-y3+x2*z3)^3; classify(f); init_debug(3); classify(f); } /////////////////////////////////////////////////////////////////////////////// static proc Klassifiziere (poly f) { //--------------------------- initialisation ---------------------------------- string s1; int n, cnt, corank_f, K, Mu; list v, cstn; map PhiG; def ring_top = basering; n = nvars(basering); // Zahl der Variablen des aktuellen Rings. PhiG = ring_top, maxideal(1); cstn[4] = PhiG; if( defined(@ringdisplay) == 0) { string @ringdisplay; // Define always 'ringdisplay' to be export @ringdisplay; // able to run 'Show(f)' } @ringdisplay = "setring RingB;"; if(defined(RingB)!=0) { kill RingB; } execute ("ring RingB="+charstr(basering)+",("+A_Z("x", n)+"),(c,ds);"); export RingB; setring ring_top; //---------------------- compute basciinvariants ------------------------------ if(jet(f,0) != 0 ) { cstn[1] = corank(f); cstn[2]=-1; cstn[3]=1; return(printresult(1, f, "a unit", cstn, -1)); } debug_log(1, "Computing Basicinvariants of f ..."); K, Mu, corank_f = basicinvariants(f); debug_log(0, "About the singularity :"); debug_log(0, " Milnor number(f) = "+string(Mu)); debug_log(0, " Corank(f) = "+string(corank_f)); debug_log(0, " Determinacy <= "+string(K)); cstn[1] = corank_f; cstn[2] = Mu; cstn[3] = K; if( Mu == 0) { cstn[1]=1; cstn[3]=1; return(printresult(1, f, "A[0]", cstn, 0)); } if(Mu<0) { debug_log(0, "The Milnor number of the function is infinite."); debug_log(0, "The singularity is not in Arnolds list."); return(printresult(1, 1, "error!", cstn, -1)); } f = jet(f, K); v = HKclass(milnorcode(f)); if(v[2]>0) { debug_log(0, "Guessing type via Milnorcode: ", v[1]);} else { debug_log(0, "Hilbert polynomial not recognised. Milnor code = ", milnorcode(f)); } debug_log(0, ""); debug_log(0, "Computing normal form ..."); //------------ step 1, classification according to corank(f) ------------------ if(corank_f == 0) { return(printresult(2, f, "A["+string(Mu)+"]", cstn, 0)); } if(corank_f == 1) { return(printresult(2, f, "A["+string(Mu)+"]", cstn, 0)); } cstn[4] = 0; if(corank_f == 2) { return(Funktion1bis(f, cstn)); } if(corank_f == 3) { return(Funktion1bis(f, cstn)); } return(printresult(105, f, "NoClass", cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion1bis (poly f, list cstn) { //---------------------------- initialisation --------------------------------- def ring_top=basering; poly g; int n, corank, K; map conv, PhiG; string s1; list v_res, v_class, v, iv; corank = cstn[1]; K = cstn[3]; n = nvars(basering); //-------------------- apply morsesplit if n>corank --------------------------- if( n > corank) { debug_log(0, "I have to apply the splitting lemma. This will take some time....:-)"); v_res = Morse(f, K, corank, 0); g = v_res[1]; PhiG = v_res[2]; conv = ReOrder(g); g = conv(g); PhiG = conv(PhiG); if(defined(RingB) != 0 ) { kill RingB; } ring ring_rest=char(basering),(x(1..corank)),(c,ds); map MapReduce=ring_top,maxideal(1); poly G = MapReduce(g); map PhiG=ring_top,maxideal(1);// Konstruiere Id auf r PhiG = MapReduce(PhiG); execute("ring RingB="+charstr(basering)+",("+A_Z("x",corank)+"),(c,ds);"); export RingB; setring ring_rest; } else { ring ring_rest=char(basering),(x(1..corank)),(c,ds); map PhiG=ring_top,maxideal(1); poly G = PhiG(f); } //--------------------- step 1 of Arnold now finished ------------------------- map phi = ring_rest,maxideal(1); cstn[4] = phi; if(corank == 2) { v_class = Funktion3(G, cstn); } else { if(corank == 3) { v_class = Funktion50(G, cstn); } else { v_class = printresult(1, f, "error!", cstn, -1); } } //-------------------------- classification done ------------------------------ if(typeof(v_class[1])!="poly") { return(v); } poly f_result = v_class[1]; v[2] = v_class[2]; v[3] = v_class[3]; map Phi = v_class[4]; PhiG = Phi(PhiG); setring ring_top; if(defined(conv)!=0) { kill conv; } map conv=ring_rest,maxideal(1); v[1] = conv(f_result); return(v); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion3 (poly f, list cstn) { //---------------------------- initialisation --------------------------------- poly f3 = jet(f, 3); ideal Jf; int Dim, Mult, Mu; debug_log(1, "Step 3"); if( f3 == 0 ) { return(Funktion13(f, cstn)); } // f3 ~ x3 , x2y+y3 , x2y Jf = std(jacob(f3)); Dim = dim(Jf); if(Dim == 0) { return(printresult(4, f, "D[4]", cstn, 0)); } Mult = mult(Jf); Mu = cstn[2]; if(Dim == 1) { if( Mult == 1) { return(printresult(5,f,"D["+string(Mu)+"]", cstn, 0)); } if( Mult == 2) { return(Funktion6(f, cstn));} // series E,J debug_log(0, "dimension 1 und deg != 1, 2 => error, ", "this should never occur"); return(printresult(3, f, "error!", cstn, -1)); // Should never reach this line } // Should never reach this line return(printresult(3, f, "error!", cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion6 (poly f, list cstn) { // Arnold's steps 6-12 //---------------------------- initialisation --------------------------------- poly f3, fk; ideal JetId, Jf; int k, Dim, Mult, n, Mu; map PhiG, Phi; intvec RFlg; list v; def ring_top=basering; f3 = jet(f, 3); // 3-Jet von f n = nvars(basering); Mu = cstn[2]; PhiG = cstn[4]; k = 1; debug_log(1, " Step 6"); RFlg = GetRf(f, n); v = Faktorisiere(f, f3, 3, 1, RFlg); f = v[1]; Phi = v[2]; PhiG = Phi(PhiG); cstn[4] = PhiG; //---------------------------- begin of loop ---------------------------------- while( (6*k) <= Mu ) { JetId = x(1)^3+x(2)^(3*k); fk = jet(f, 3*k, weight(JetId)); //--------------------------- step 6(k) --------------------------------- if( fk == Coeff(fk,x(1), x(1)^3)*x(1)^3 ) { JetId = x(1)^3+x(2)^(3*k+1); // check jet x3,y3k+1 : E[6k] fk = jet(f, 3*(3*k+1), weight(JetId)); if( Coeff(fk,x(2),x(2)^(3*k+1)) != 0 ) { return(printresult(7, f, "E["+string(6*k)+"]", cstn, k-1)); } JetId = x(1)^3+x(1)*x(2)^(2*k+1); // check jet x3,xy2k+1 : E[6k+1] fk = jet(f, 3*(2*k+1), weight(JetId)); if( Coeff(fk, x(1)*x(2), x(1)*x(2)^(2*k+1)) != 0 ) { return(printresult(8, f,"E["+string(6*k+1)+"]", cstn, k-1)); } JetId = x(1)^3+x(2)^(3*k+2); // check jet x3,y3k+1 : E[6k+2] fk = jet(f, 3*(3*k+2), weight(JetId)); if( Coeff(fk,x(2),x(2)^(3*k+2)) != 0 ) { return(printresult(9, f,"E["+string(6*k+2)+"]", cstn, k-1)); } //------------------------- step 10(k) -------------------------------- k++; JetId = x(1)^3+x(2)^(3*k); fk = jet(f, 3*k, weight(JetId)); Jf = std(jacob(fk)); Dim = dim(Jf); if(Dim==0) { return(printresult(11,f,"J["+string(k)+",0]",cstn,k-1)); } Mult = mult(Jf); if( Dim ==1 && Mult==1) { return(printresult(12,f,"J["+string(k)+","+string(Mu - 6*k +2)+"]", cstn, k-1)); } if( Dim == 1 && Mult == 2) { if(Coeff(fk, x(2), x(2)^(3*k)) != 0) { v = Faktorisiere(f, fk, 3, k, RFlg); f = v[1]; Phi = v[2]; PhiG = Phi(PhiG); cstn[4] = PhiG; } } } } // Should never reach this line return(printresult(6, f, "error!", cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion13 (poly f, list cstn) { //---------------------------- initialisation --------------------------------- poly f4; ideal Jf; int Dim, Mult, Mu; debug_log(1, " Step 13"); Mu = cstn[2]; f4 = jet(f, 4); if( f4 == 0 ) { return(Funktion47(f, cstn)); } // f4 ~ x4+ax2y2+y4, x4+x2y2, x2y2, x3y, x4 Jf = std(jacob(f4)); Dim = dim(Jf); if(Dim==0) { return(printresult(14,f,"X[9] = X[1,0] = T[2,4,4]",cstn,1)); } Mult = mult(Jf); if( Dim == 1) { if( Mult == 1 ) { return(printresult(15, f, "X[1,"+string(Mu-9)+"] = T[2,4,"+string(Mu-5)+"]", cstn, 1)); } if( Mult == 2 ) { Jf = Jf, jacob(Jf); Jf = std(Jf); Dim = dim(Jf); if(Dim==0){return(printresult(16,f,"Y[1,p,q] = T[2,4+p,4+q]",cstn,1));} if( Dim == 1 ) { return(Funktion17(f, cstn)); } } if( Mult == 3 ) { return(Funktion25(f, cstn)); } } // Should never reach this line return(printresult(13, f, "error!", cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion17 (poly f, list cstn) { // Analog zu Fumktion 6, Kombination 17-24 //---------------------------- initialisation --------------------------------- poly fk, ft; ideal JetId, Jf; int p, Dim, Mult, Mu; list v; map PhiG, Phi; def ring_top=basering; debug_log(1, " Step 17"); Mu = cstn[2]; PhiG = cstn[4]; fk = jet(f, 4); p = 1; //---------------------------- begin of loop ---------------------------------- while( 3*p<= Mu) { debug_log(1, " Step 18("+string(p)+")"); v = Isomorphie_s17(f, fk, p, 1); f, Phi = v[1..2]; PhiG = Phi(PhiG); cstn[4] = PhiG; if ( p>1) { JetId = x(1)^3*x(2) + x(2)^(3*p); fk = jet(f, 3*p, weight(JetId)); } //--------------------------- step 18(p) -------------------------------- JetId = x(1)^3*x(2) + x(2)^(3*p+2); // check jet x3y,y3k+2 : Z[6p+5] fk = jet(f, 3*(3*p+2), weight(JetId)); if( Coeff(fk, x(2), x(2)^(3*p+2)) != 0) { return(printresult(19,f, "Z["+string(6*p+5)+"]", cstn, p)); } JetId = x(1)^3*x(2)+x(1)*x(2)^(2*p+2); // check jet x3y,xy2k+2 : Z[6p+6] fk = jet(f, 2*(3*p+2)+1, weight(JetId)); if( Coeff(fk, x(1)*x(2), x(1)*x(2)^(2*p+2)) != 0) { return(printresult(20, f, "Z["+string(6*p+6)+"]", cstn, p)); } JetId = x(1)^3*x(2) + x(2)^(3*p+3); // check jet x3y,y3k+3 : Z[6p+7] fk = jet(f, 3*(3*p+3), weight(JetId)); if( Coeff(fk, x(2), x(2)^(3*p+3)) != 0) { return(printresult(21, f, "Z["+string(6*p+7)+"]", cstn, p)); } //---------------------------- step 22 ---------------------------------- p = p+1; JetId = x(1)^3*x(2) + x(2)^(3*p+1); fk = jet(f, 3*p+1, weight(JetId)); ft = Teile(fk, x(2)); Jf = std(jacob(ft)); Dim = dim(Jf); Mult = mult(Jf); if(Dim==0) { return(printresult(23,f,"Z["+string(p-1)+",0]", cstn, p)); } if( Mult == 1 ) { return(printresult(24, f, "Z["+string(p-1)+","+string(Mu-3-6*p)+"]", cstn, p)); } } // Should never reach this line return(printresult(17, f, "error!", cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion25 (poly f, list cstn) { // Analog zu Fumktion 6, Kombination 25-46 //---------------------------- initialisation --------------------------------- poly fk, ft; ideal JetId, Jf; int k, Dim, Mult, Mu; map PhiG, Phi; intvec RFlg; list v; def ring_top=basering; debug_log(1, " Step 25"); Mu = cstn[2]; PhiG = cstn[4]; fk = jet(f, 4); k = 1; RFlg = GetRf(f, 2); //---------------------------- begin of loop ---------------------------------- while (k0 ist. for(i=1;i<4;i=i+1) { if(diff(diff(f3, x(i)), x(i)) != 0) { kx = i; i=4; } } if(kx == 2) { ky = 1; kz = 3; } if(kx == 3) { ky = 2; kz = 1; } //-------------------------- compute -l1*l2 ------------------------------- f3 = jet(f, 3); Jfsyz = f3, diff(f3, x(kx)); Mat = matrix(syz(Jfsyz)); if(deg(Mat[2,1])>1) { Jfsyz = f3, Mat[2,1]; Mat = matrix(syz(Jfsyz)); // berechen Abb. sodass f=x2*l2 l1 = Mat[2,1]; a = Coeff(l1, x(kx), x(kx)); l1 = l1 / number(a); b = Coeff(l1, x(ky), x(ky)); c = Coeff(l1, x(kz), x(kz)); B[rvar(x(kx))] = x(kx) - b * x(ky) - c * x(kz); VERT = ring_top, B; f = VERT(f); PhiG = VERT(PhiG); cstn[4] = PhiG; f3 = jet(f, 3); l2 = f3 / x(kx)^2; // sorge dafuer, dass b<>0 ist. b = Coeff(l2, x(ky), x(ky)); if( b== 0) { ky, kz = swap(ky, kz); } // Koordinaten-Transf. s.d. f=x2y b = Coeff(l2, x(ky), x(ky)); l2 = l2 / number(b); a = Coeff(l2, x(kx), x(kx)); c = Coeff(l2, x(kz), x(kz)); B = maxideal(1); B[rvar(x(ky))] = -a * x(kx) + x(ky) - c * x(kz); VERT = ring_top, B; f = VERT(f); PhiG = VERT(PhiG); cstn[4] = PhiG; } //------------------------------- step 98 --------------------------------- Jfsyz = x(kx)^2*x(ky) + x(ky)^4 + x(kz)^4; a = jet(f, 8, weight(Jfsyz)); Jf = std(jacob(a)); Dim = dim(Jf); Mult = mult(Jf); if( Dim == 0) { return(printresult(99, f, "V[1,0]", cstn, 3)); } if( Dim == 1) { if(Mult==1) {return(printresult(100,f,"V[1,"+string(Mu-15)+"]",cstn,3));} if(Mult==2){return(printresult(101,f,"V#[1,"+string(Mu-15)+"]",cstn,3));} } " Dim=",Dim," Mult=",Mult; return(printresult(102, f, "NoClass", cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// proc tschirnhaus (poly f, poly x) "USAGE: tschirnhaus();" { //---------------------------- initialisation --------------------------------- poly b; ideal B; int n, j, hc; matrix cf; intvec z; string s; list v; map Phi, EH; def ring_top=basering; n = nvars(basering); cf = coeffs(f, x); hc = nrows(cf) - 1; // hoechster exponent von x_i b = cf[hc+1,1]; // koeffizient von x_i^hc B = maxideal(1); z[n] = 0; EH = ring_top, z; Phi = ring_top, B; v[1] = f; if ( EH(b) != 0) // pruefe ob der Koeff von x_i^hc { B[rvar(x)] = x -1*(cf[hc,1]/(hc*b)); v[1] = Phi(f); } v[2] = Phi; return(v); } /////////////////////////////////////////////////////////////////////////////// static proc Isomorphie_s17 (poly f, poly fk, int k, int ct, list #) { //---------------------------- initialisation --------------------------------- ideal Jfsyz, JetId, bb; poly a, b, c, d, Relation, an, bn; int B,C, alpha, beta, gamma, g; matrix Matx, Maty; map PhiG, VERT; list v; def ring_top=basering; if(size(#)==1) { PhiG = #[1]; } else { PhiG = ring_top,maxideal(1); } bb = maxideal(1); // Ziel: bestimme a,b,c,d sodass fk = (ax+by^k)^3(cx+dy) gilt. debug_log(2, "Isomorphie_s17:"); debug_log(2, "Faktor: f=",Show(f)," Jet=",Show(fk)," k=",k, "cnt=", ct); if( k == 1) { Jfsyz = fk, diff(fk, x(1)); Matx = matrix(syz(Jfsyz)); Jfsyz = fk, diff(fk, x(2)); Maty = matrix(syz(Jfsyz)); a = Coeff(fk, x(1), x(1)^4); b = Coeff(fk, x(2), x(2)^4); c = Coeff(fk, x(1)*x(2), x(1)^3*x(2)); d = Coeff(fk, x(1)*x(2), x(1)*x(2)^3); if( (a != 0) && (b != 0) ) { B = -int(Coeff(Matx[1,1], x(2), x(2))); C = -int(Coeff(Maty[1,1], x(1), x(1))); alpha = int(Coeff(Matx[2,1], x(1), x(1)^2)); beta = int(Coeff(Matx[2,1], x(1)*x(2), x(1)*x(2))); gamma = int(Coeff(Matx[2,1], x(2), x(2)^2)); bb[rvar(x(1))] = x(1) - (2*number(gamma) / (B - beta))*x(2); bb[rvar(x(2))] = x(2) - ((C - number(beta)) / (2*gamma))*x(1); VERT = ring_top,bb; Relation = VERT(f); fk = jet(Relation, 4); an = Coeff(fk, x(1), x(1)^4); bn = Coeff(fk, x(2), x(2)^4); if( (an != 0) & (bn != 0) ) { VERT=ring_top,x(1),(x(2) + a*x(1))/ b; } f = VERT(f); fk = jet(f, 4); PhiG = VERT(PhiG); a = Coeff(fk, x(1), x(1)^4); b = Coeff(fk, x(2), x(2)^4); c = Coeff(fk, x(1)*x(2), x(1)^3*x(2)); d = Coeff(fk, x(1)*x(2), x(1)*x(2)^3); Jfsyz = fk, diff(fk, x(1)); Matx = matrix(syz(Jfsyz)); Jfsyz = fk, diff(fk, x(2)); Maty = matrix(syz(Jfsyz)); } if( (a == 0) || (b == 0) ) { if( a == 0) { if( c == 0) { // y3(ax+by) Relation = - Matx[2,1] / Matx[1,1]; a = Coeff(Relation, x(1), x(1)); b = Coeff(Relation, x(2), x(2)); VERT=ring_top,a*x(2)^k - b*x(1), x(1); } else { // (ax+by)^3y Relation = - 3*Matx[2,1] / Matx[1,1]; a = Coeff(Relation, x(1), x(1)); b = Coeff(Relation, x(2), x(2)); VERT=ring_top,a*x(1) - b*x(2), x(2); } } else { if( d == 0) { // x3(ax+by) Relation = - Maty[2,1] / Maty[1,1]; a = Coeff(Relation, x(1), x(1)); b = Coeff(Relation, x(2), x(2)); VERT=ring_top,x(1), b*x(2)^k - a*x(1); } else { // x(ax+by)^3 Relation = - 3*Maty[2,1] / Maty[1,1]; a = Coeff(Relation, x(1), x(1)); b = Coeff(Relation, x(2), x(2)); VERT=ring_top,x(2), b*x(1) - a*x(2); } } f = VERT(f); PhiG = VERT(PhiG); } else { // "Weder b noch a sind 0"; if(ct > 5) { v[1]=f; v[2]=PhiG; return(v); } fk = jet(f, 4); return(Isomorphie_s17(f, fk, k, ct+1, PhiG)); } } else { // k >1 a = fk/x(2); Jfsyz = a, diff(a, x(1)); Matx = matrix(syz(Jfsyz)); Relation = -3 * Matx[2,1] / Matx[1,1]; a = Coeff(Relation, x(1), x(1)); b = Coeff(Relation, x(2), x(2)^k); VERT = basering,x(1)-b*x(2)^k,x(2); f = VERT(f); PhiG = VERT(PhiG); JetId = x(1)^3*x(2) + x(2)^(3*k+1); fk = jet(f, 3*k+1, weight(JetId)); } v = f, PhiG; debug_log(2, "Isomorphie_s17: done"); debug_log(2, "Faktor: f=",Show(f)," Jet=",Show(fk)," k=",k); return(v); } /////////////////////////////////////////////////////////////////////////////// static proc printresult (int step, poly f, string typ, list cstn, int m) { if(defined(onlyreturninvariants)) { if(onlyreturninvariants == 1) { Modality = m; Type = typ; } } //---------------------------- initialisation --------------------------------- int corank, Mu, K; list v; corank, Mu, K = cstn[1..3]; debug_log(0," Arnold step number "+string(step)); if( @DeBug >= 0 ) { "The singularity"; " "+Show(jet(f, K))+""; if( typ != "error!" && typ != "NoClass" ) { "is R-equivalent to "+typ+"."; } if ( typ == "NoClass" ) { "is not in Arnolds list."; } // if(K>=0) { " det = "+string(K); } if(Mu>=0) { " Milnor number = "+string(Mu); } if(m>=0) { " modality = "+string(m); } } v = f, typ, corank, cstn[4]; return(v); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion47 (poly f, list cstn) { int corank = cstn[1]; int Mu = cstn[2]; int K = cstn[3]; string s = "The Singularity "+Show(jet(f, K)); string tp=""; // return(printresult(47, f, tp, cstn, -1)); s = s +" has 4-jet equal to zero. (F47), mu="+string(Mu); s; // +" ("+SG_Typ+")"; s = "No further classification available."; s; return(Show(f), tp, corank); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion91 (poly f, list cstn, int k) { string tp = "U*[k,0]"; return(printresult(91, f, tp, cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion92 (poly f, list cstn, int k) { string tp = "UP[k]"; return(printresult(92, f, tp, cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion93 (poly f, list cstn, int k) { string tp = "UQ[k]"; return(printresult(93, f, tp, cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion94 (poly f, list cstn, int k) { string tp = "UR[k]"; return(printresult(94, f, tp, cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion95 (poly f, list cstn, int k) { string tp = "US[k]"; return(printresult(95, f, tp, cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// static proc Funktion96 (poly f, list cstn, int k) { string tp = "UT[k]"; return(printresult(96, f, tp, cstn, -1)); } /////////////////////////////////////////////////////////////////////////////// proc morsesplit(poly f) " USAGE: morsesplit(f); f=poly RETURN: Normal form of f in M^3 after application of the splitting lemma COMPUTE: apply the splitting lemma (generalized Morse lemma) to f EXAMPLE: example morsesplit; shows an example" { //---------------------------- initialisation --------------------------------- poly f_out; int n, K, Mu, corank; list v; if(defined(@ringdisplay) != 0 ) { kill @ringdisplay; } string @ringdisplay = "setring "+nameof(basering); export @ringdisplay; def ring_ext=basering; n = nvars(basering); // if trace/debug mode not set, do it! init_debug(); K, Mu, corank = basicinvariants(f); ring ring_top=char(basering),(x(1..n)),(c,ds); map Conv=ring_ext,maxideal(1); setring ring_top; v = Morse(jet(Conv(f),K), K, corank, 0); poly f_out = v[1]; setring ring_ext; map ConvUp = ring_top, maxideal(1); return(ConvUp(f_out)); } example { "EXAMPLE"; echo=2; ring r=0,(x,y,z),ds; export r; init_debug(1); poly f=(x2+3y-2z)^2+xyz-(x-y3+x2*z3)^3; poly g=morsesplit(f); g; } /////////////////////////////////////////////////////////////////////////////// static proc Coeffs (list #) { matrix m=matrix(coeffs(#[1],#[2]), deg(#[1])+1, 1); return(m); } /////////////////////////////////////////////////////////////////////////////// static proc Morse(poly f, int K, int corank, int ShowPhi) { //---------------------------- initialisation --------------------------------- poly fc, f2, a, P, Beta, fi; ideal Jfx, B; int n, i, j, k, Rang, Done; matrix Mat; map Id, Psi, Phi, PhiG; intvec Abb, RFlg; list v; fi = f; n = nvars(basering); init_debug(); def ring_top=basering; debug_log(3, "Split the polynomial below using determinacy: ", string(K)); debug_log(3, Show(fi)); for( j=1; j<=n ; j++) { Abb[j] = 0; } RFlg = GetRf(fi, n); debug_log(2, "Permutations:", RFlg ); PhiG=ring_top,maxideal(1); //----------------- find quadratic term, if there is only one ----------------- B = maxideal(1); if(corank == (n-1)) { Done = 0; f2 = jet(fi, 2); j = 1; Jfx = f2, diff(f2, x(j)); while(j<=n && (diff(f2, x(j))==0)) { j++; Jfx = f2, diff(f2, x(j)); } Mat = matrix(syz(Jfx)); Beta = 2*Mat[2,1]/Mat[1,1]; for( j=1; j<=n ; j++) { f2 = Coeff(Beta, x(RFlg[j]), x(RFlg[j])); if(f2!=0) { k = RFlg[j]; break; } } for( j=1; j<=n ; j=j+1) { f2 = Coeff(Beta, x(j), x(j)); if(j == k) { B[rvar(x(j))] = (2*f2*x(j)-Beta) / number(f2); } } Phi =ring_top,B; fi = Phi(fi); PhiG = Phi(PhiG); } if( ShowPhi > 1) { PhiG; } //------------------------ compute spliting lemma ----------------------------- fc = fi; i = 1; // Index fuer Variablen wird bearbeitet while( i <= n) { Phi=ring_top,maxideal(1); debug_log(6, "Pruefe Variable x(" +string(RFlg[i]) + ")"); debug_log(6, "--------------------"); j = i + 1; // setze j fuer evtle Verschiebung f2 = jet(fc,2); debug_log(6, "Rechne 2-Jet =" , string(f2)); if( (f2 - subst(f2, x(RFlg[i]), 0)) == 0 ) { Abb[RFlg[i]] = 1; } if( (f2 - subst(f2, x(RFlg[i]), 0)) != 0 ) { while( (j<=n) || (i==n) ) { debug_log(6, "Pruefe 2-Jet mit Wert : " + string(jet(fc,2))); a = Coeff(jet(fc,2), x(RFlg[i]), x(RFlg[i])^2); debug_log(6,"Koeffizient von x(" + string(RFlg[i]) + ")^2 ist:", a); if( (a != 0) || (i==n) ) { debug_log(6, "BREAK!!!!!!!!!!!!!!"); break; } debug_log(6,"Verschiebe evtl Variable x(",string(RFlg[j]),") um x(", string(RFlg[i]), ")"); B = maxideal(1); for( k=1; k<=n ; k=k+1) { if(k==RFlg[j]) { B[rvar(x(k))] = x(k) + x(RFlg[i]); } } Phi = ring_top,B; fc = Phi(fi); j++; } // Ende while( (j<=n) || (i==n) ) debug_log(6, "Moegliche Verschiebung fertig!"); PhiG = Phi(PhiG); if( ShowPhi > 1) { "NachVersch.:"; Phi; } if( (j<=n) || (i==n)) { P = Coeff(fc, x(RFlg[i]), x(RFlg[i])); debug_log(6, "Koeffizient von x("+string(RFlg[i])+") ist: ", string(P)); if(P != 0) { debug_log(6, "1 Koeffizient von x("+string(RFlg[i])+") ist: ", string(P)); debug_log(6, "a=" + string(a)); P = P / number (2 * a); debug_log(6, "2 Koeffizient von x("+string(RFlg[i])+") ist: ", string(P)); B = maxideal(1); for( k=1; k<=n ; k=k+1) {if(k==RFlg[i]) {B[rvar(x(k))]=x(k)-P;}} Phi =ring_top,B; debug_log(6, "Quadratische-Ergaenzung durch:", Phi); fi = Phi(fc); PhiG = Phi(PhiG); fc = jet(fi,K); P = Coeff(fc, x(RFlg[i]), x(RFlg[i])); if( P != 0) { fi = fc; continue; } } // Ende if(P != 0) // Fertig mit Quadratischer-Ergaenzung } // Ende if( (j<=n) || (i==n)) } // Ende if( (f2 - subst(f2, x(RFlg[i]), 0)) != 0 ) fi = fc; i++; debug_log(6, "++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); } debug_log(6, "Ende ---------------------------------------------------"); //--------------------------- collect results --------------------------------- if( ShowPhi > 0 ) { "Abbildung innerhalb des Morse-Lemmas:"; PhiG; "Vergleich:"; "PhiG(f)= " + Show(jet(PhiG(f), K)); "fi = " + Show(fi); } Rang = 0; B = maxideal(1); for( i=1; i<=n ; i++) { if(Abb[i] != 1) { Rang ++; B[rvar(x(i))] = 0; } } Phi = ring_top,B; PhiG = Phi(PhiG); fi = Phi(fi); v = fi, PhiG; debug_log(2, "rank determined with Morse rg=", Rang); debug_log(1, "Residual singularity f=",Show(fi)); return(v); } /////////////////////////////////////////////////////////////////////////////// static proc Coeff(poly f, list #) { //---------------------------- initialisation --------------------------------- poly a, term; int n, i; matrix K; n = nvars(basering); i = 1; term = #[2]; K = coef(f, #[1]); while( (i<=ncols(K)) && (K[1,i] != term) ) { i++; if(i>ncols(K)) break; } if(i<=ncols(K)) { a = K[2,i]; } if(i>ncols(K)) { a = 0; } return(a); } /////////////////////////////////////////////////////////////////////////////// static proc ReOrder(poly f) { //---------------------------- initialisation --------------------------------- poly result; ideal B = maxideal(1); int i, n, Ctn, Ctv; map conv; n = nvars(basering); Ctv = 1; // Zahl der Vorhandenen Variablen Ctn = n; // Zahl der Nicht-Vorhandenen Variablen def ring_top=basering; for( i=1; i<=n; i=i+1) { result = subst(f,x(i), 0) - f; if( result != 0 ) { B[rvar(x(i))] = x(Ctv); Ctv++; } else { B[rvar(x(i))] = x(Ctn); Ctn--; } } conv = ring_top,B; return(conv); } /////////////////////////////////////////////////////////////////////////////// proc quickclass(poly f) " USAGE: quickclass(f); f=poly RETURN: Normal form of f in Arnold's list REMARK: try to determine the normal form of f by invariants, mainly by computing the Hilbert function of the Milnor algebra, no coordinate change is needed (see also proc 'milnorcode'). EXAMPLE: example quickclass; shows an example" { //---------------------------- initialisation --------------------------------- string Typ; int cnt, K, Mu, corank; list v; def ring_top=basering; // check basic condition on the basering. if(checkring()) { return(f); } if( f==0 ) { "Normal form : 0"; return(f); } if( jet(f,0)!=0 ) { "Normal form : 1"; return(f); } K, Mu, corank = basicinvariants(f); if(Mu<0) { debug_log(0, "The Milnor number of the function is infinite."); return(f); } // Do the classification of f // typ: list of types matching the milnorcode // cnt: number of matches found v = HKclass(milnorcode(f)); Typ, cnt = v[1..2]; "Singularity R-equivalent to :",Typ; if(cnt==0) { "Hilbert polynomial not recognised. Milnor code = ", milnorcode(f); return(); } if(cnt==1) { debug_log(1,"Getting normal form from database."); "normal form :",A_L(Typ); return(A_L(Typ)); } // Hier nun der Fall cnt>1 "Hilbert-Code of Jf^2"; "We have ", cnt, "cases to test"; Cubic(f); return(v); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),ds; poly f=(x2+3y-2z)^2+xyz-(x-y3+x2*z3)^3; quickclass(f); } /////////////////////////////////////////////////////////////////////////////// proc milnorcode (poly f, list #) "USAGE: milnorcode(f[,e]); f=poly, e=int RETURN: intvec, coding the Hilbert function of the e-th Milnor algebra of f, i.e. of basering/(jacob(f)^e) (default e=1), according to proc Hcode EXAMPLE: example milnorcode; shows an example" { int e=1; if(size(#)==1) { e=#[1]; } ideal jf=std(jacob(f)^e); intvec v=hilb(jf,2); return(Hcode(v)); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),ds; poly f=x2y+y3+z2; milnorcode(f); milnorcode(f,2); // a big second argument may result in memory overflow } /////////////////////////////////////////////////////////////////////////////// proc Hcode (intvec v) "USAGE: Hcode(v); v=intvec RETURN: intvec, coding v according to the number of successive repetitions of an entry EXAMPLE: example Hcode; shows an example." { int col, len, i, cur, cnt, maxcoef, nlen; intvec hil1, hil2; col = 1; len = size(v); v[len+1] = 0; init_debug(); debug_log(1, "Hcode:", v ); for(i=1; i<=len; i++) { if( v[i] > maxcoef) { maxcoef = v[i]; } } nlen = 2*maxcoef - 1; hil1[nlen] = 0; hil2[nlen] = 0; for(i=1; i<=nlen; i++) { if( i > maxcoef) { hil2[i] = 2*maxcoef-i; } else { hil2[i] = i; } } for(i=1; i<=nlen; i++) { cnt=0; while( (col<=len) && (v[col] == hil2[i]) ) { cnt++; col++; } hil1[i] = cnt; } return(hil1); } example { "EXAMPLE:"; echo=2; intvec v1 = 1,3,5,5,2; Hcode(v1); intvec v2 = 1,2,3,4,4,4,4,4,4,4,3,2,1; Hcode(v2); } /////////////////////////////////////////////////////////////////////////////// static proc Cubic (poly f) { //---------------------------- initialisation --------------------------------- poly f3; ideal Jf, Jf1, Jf2; int Dim, Mult; f3 = jet(f, 3); if( jet(f,2) != 0) { return("2-jet non zero"); } if( f3 == 0 ) { return("null form"); } Jf1 = jacob(f3); Jf = std(Jf1); Dim = dim(Jf); Mult = mult(Jf); if(Dim == 0) { return("P[8]:smooth cubic"); } // x3 + y3 + z3 + axyz if(Dim == 1) { if(Mult == 2) { Jf2 = wedge(jacob(Jf1),3-Dim), Jf1; Jf2 = std(Jf2); Dim = dim(Jf2); if (Dim == 0) { return("R:conic + line"); } // x3 + xyz if (Dim == 1) { return("Q:cuspidal cubic"); } // x3 + yz2 } if(Mult == 3) { Jf2 = wedge(jacob(Jf1),3-Dim), Jf1; Jf2 = std(Jf2); Dim = dim(Jf2); if(Dim == 0) { return("T:three lines"); } // xyz if(Dim == 1) { return("S:conic + tangent"); } // x2z + yz2 } if(Mult == 4) { return("U:three concurrent lines"); } // x3 + xz2 } if(Dim == 2) { if(Mult == 1) { return("V:doubleline + line"); } // x2y if(Mult == 2) { return("V': tripple line"); } // x3 } if(Dim == 3) { return("P[9]:nodal cubic"); } // x3 + y3 + xyz return(""); } /////////////////////////////////////////////////////////////////////////////// static proc parity (int e) "USAGE: parity()" { int r = e div 2; if( 2*r == e ) { return(0); } return(1); } /////////////////////////////////////////////////////////////////////////////// static proc HKclass (intvec sg) { //---------------------------- initialisation --------------------------------- int cnt = 0; string SG_Typ = ""; list v; // if trace/debug mode not set, do it! init_debug(); debug_log(1, "Milnor code : ", sg ); if(size(sg) == 1) { v ="A["+string(sg[1])+"]", 1; return(v); } if(size(sg) == 3) { return(HKclass3(sg, SG_Typ, cnt)); } if(size(sg) == 5) { return(HKclass5(sg, SG_Typ, cnt)); } if(size(sg) == 7) { return(HKclass7(sg, SG_Typ, cnt)); } debug_log(1, "No solution found." ); v = "", 0; return(v); } /////////////////////////////////////////////////////////////////////////////// static proc HKclass3 (intvec sg, string SG_Typ, int cnt) { list v; if(sg[1] == 1) { v = HKclass3_teil_1(sg, SG_Typ, cnt); } debug_log(6, "HKclass3: ", v[1], " cnt=", v[2]); return(v); } /////////////////////////////////////////////////////////////////////////////// static proc HKclass3_teil_1 (intvec sg, string SG_Typ, int cnt) { int k, r, s; list v; debug_log(2, "entering HKclass3_teil_1", sg); if(sg[2]==1) { SG_Typ=SG_Typ+" D[k]=D["+string(sg[3]+3)+"]";cnt++;} // D[k] if(sg[2]>=1) { if( parity(sg[2])) { // sg[2] ist ungerade if(sg[2]<=sg[3]) { k = (sg[2]+1) div 2; if(k>1) { cnt++; SG_Typ=SG_Typ+" J[k,r]=J["+string(k)+","+string(sg[3]+1-2*k)+"]"; }// J[k,r] } if(sg[2]==sg[3]+2) { // E[6k+2] k = (sg[2]-1) div 2; if(k>0) {cnt++; SG_Typ=SG_Typ+" E[6k+2]=E[" + string(6*k+2) + "]"; } } } else { // sg[2] ist gerade if( sg[2] == sg[3]+1) { // E[6k] k = sg[2] div 2; cnt++; SG_Typ=SG_Typ + " E[6k]=E[" + string(6*k) + "]"; } if( sg[2] == sg[3]) { // E[6k+1] k=sg[2] div 2; cnt++; SG_Typ=SG_Typ+" E[6k+1]=E["+string(6*k+1)+"]"; } } } debug_log(2, "finishing HKclass3_teil_1"); debug_log(6, "HKclass3: ", SG_Typ, " cnt=", cnt); v = SG_Typ, cnt; return(v); } /////////////////////////////////////////////////////////////////////////////// static proc HKclass5 (intvec sg, string SG_Typ, int cnt) { list v; if(sg[1] == 1 && sg[2] == 1) { v = HKclass5_teil_1(sg, SG_Typ,cnt); } if(sg[1] == 1 && sg[2] == 0) { v = HKclass5_teil_2(sg, SG_Typ,cnt); } debug_log(6, "HKclass5: ", v[1], " cnt=", v[2]); return(v); } /////////////////////////////////////////////////////////////////////////////// static proc HKclass5_teil_1 (intvec sg, string SG_Typ, int cnt) { int k, r, s; list v; debug_log(2, "entering HKclass5_teil_1", sg); if(parity(sg[3])) { // Dritte Stelle soll ungerade sein k = (sg[3]+1) div 2; if(sg[3] > sg[4]) { k--; if( (sg[4]==sg[5]) && (sg[3] == sg[4]+1) && k>0 ) { // W[12k+6] SG_Typ = SG_Typ + " W[12k+6]=W["+string(12*k+6)+"]"; cnt++; } if( (sg[3]==sg[5]) && (sg[3] == sg[4]+2) && k>0 ) { // W[12k+5] SG_Typ = SG_Typ + " W[12k+5]=W["+string(12*k+5)+"]"; cnt++; } } else { // sg[3] <= sg[4] if( (sg[3]==sg[4]) && (sg[5] >= sg[3]) ) { r = sg[5] - sg[4]; SG_Typ=SG_Typ +" X[k,r]=X["+string(k)+","+string(r)+"]"; cnt++; } if( (sg[3]==1) && (sg[4]==3) && (sg[5]>=sg[4])) { // Z[1,r] r = sg[5] - sg[4]; SG_Typ = SG_Typ + " Z[1,r]=Z[1,"+string(r)+"]"; cnt++; } if( sg[4] == sg[5]) { if(parity(sg[4])) { // Z[k,r,0] r = (sg[4] - sg[3]) div 2; if( r>0 ) { cnt++; SG_Typ = SG_Typ + " Z[k,r,0]=Z["+string(k)+","+string(r)+",0]"; } } else { // Z[k,12k+6r] r = (sg[4] - 2*k) div 2; cnt++; SG_Typ = SG_Typ+" Z[k,12k+6r]=Z["+string(k)+","+string(12*k+6*r)+"]"; } } if( parity(sg[4]) ) { // 4. Stelle ist ungerade if(sg[4] == sg[5]+2) { // Z[k,12k+6r+1] r = (sg[4]-2*k-1) div 2; cnt++; SG_Typ=SG_Typ+" Z[k,12k+6r+1]=Z["+string(k)+","; SG_Typ=SG_Typ+string(12*k+6*r+1)+"]"; } if( (sg[5]>sg[4]) && (sg[4]>sg[3]) ) { // Z[k,r,s] r = (sg[4] - sg[3]) div 2; cnt++; s = sg[5] - sg[4]; SG_Typ = SG_Typ + " Z[k,r,s]="; SG_Typ = SG_Typ + "Z["+string(k)+","+string(r)+","+string(s)+"]"; } } else { // 4. Stelle ist gerade if( sg[4] == sg[5]+1) { // Z[k,12k+6r-1] r = (sg[4] - 2*k) div 2; cnt++; SG_Typ=SG_Typ+" Z[k,12k+6r-1]=Z["+string(k)+","; SG_Typ=SG_Typ+string(12*k+6*r-1)+"]"; } } if(sg[4]>sg[3]) { // Y[k,r,s] r = sg[4] - sg[3]; s = sg[5] - sg[3] + r; if( s<0 ) { s = -s; } SG_Typ = SG_Typ + " Y[k,r,s]="; cnt++; SG_Typ = SG_Typ + "Y["+string(k)+","+string(r)+","+string(s)+"]"; } } } else { // Dritte Stelle soll gerade sein k = sg[3] div 2; // sortiere verschiedene W's if(k>0) { if( (sg[4]==2*k-1) && (sg[4]==sg[5]) ) { // W[12k] SG_Typ = SG_Typ + " W[12k]=W["+string(12*k)+"]"; cnt++; } if( (sg[4]==2*k-1) && (sg[3]==sg[5]) ) { // W[12k+1] SG_Typ = SG_Typ + " W[12k+1]=W["+string(12*k+1)+"]"; cnt++; } if( (sg[4]==2*k) && (sg[5]>=sg[4]) ) { // W[k,r] r = sg[5] - sg[4]; SG_Typ=SG_Typ+" W[k,r]=W["+string(k)+","+string(r)+"]"; cnt++; } if( (sg[5]==2*k-1) && (sg[4]>sg[3]) ) { // W#[k,2r-1] r = sg[4] - sg[3]; cnt++; SG_Typ = SG_Typ + " W#[k,2r-1]=W["+string(k)+","+string(2*r-1)+"]"; } if( (sg[5]==2*k) && (sg[4]>sg[3]) ) { // W#[k,2r] r = sg[4] - sg[3]; cnt++; SG_Typ = SG_Typ + " W#[k,2r]=W["+string(k)+","+string(2*r)+"]"; } } // ENDIF k>0 } debug_log(2, "finishing HKclass5_teil_1"); debug_log(6, "HKclass5_teil_1: ", SG_Typ, " cnt=", cnt); v = SG_Typ, cnt; return(v); } /////////////////////////////////////////////////////////////////////////////// static proc HKclass5_teil_2 (intvec sg, string SG_Typ, int cnt) { int k, r, s; list v; debug_log(2, "entering HKclass5_teil_2", sg); // finde T[p,q,r] k = sg[3] + 1; r = sg[4] + k; s = sg[5] + r - 1; if(k>2 && r>2 && s>2) { // T[k,r,s] cnt++; SG_Typ = SG_Typ + " T[k,r,s]=T["+string(k)+","+string(r)+","+string(s)+"]"; } // finde weitere Moeglicjkeiten. if(sg[3]==2) { // Q[...] if(parity(sg[4])) { // 4. Stelle ist ungerade. if(sg[4]==sg[5]) { // Q[6k+4] k=(sg[4]+1) div 2; cnt++; SG_Typ=SG_Typ+" Q[6k+4]=Q["+string(6*k+4)+"]"; } if(sg[4]+1==sg[5]) { // Q[6k+5] k=sg[5] div 2; cnt++; SG_Typ=SG_Typ+" Q[6k+5]=Q["+string(6*k+5)+"]"; } } else { // 4. Stelle ist gerade. if(sg[4]==sg[5]+1) { // Q[6k+6] k=sg[4] div 2; cnt++; SG_Typ=SG_Typ+" Q[6k+6]=Q["+string(6*k+6)+"]"; } if(sg[4]=2) { r=sg[5]+1-2*k; cnt++; SG_Typ=SG_Typ+" Q[k,r]=Q["+string(k)+","+string(r)+"]"; } } } } else { // S[...] if(parity(sg[3])) { // 3. Stelle ist ungerade. k = (sg[3]-1) div 2; if(sg[3]==sg[4]+3 && sg[3]==sg[5]+2) { // S[12k-1] cnt++; SG_Typ = SG_Typ + " S[12k-1]=S["+string(12*k-1)+"]"; } if(sg[3]==sg[4]+3 && sg[3]==sg[5]+1) { // s[12k] cnt++; SG_Typ = SG_Typ + " S[12k]=S["+string(12*k)+"]"; } if(sg[3]==sg[4]+2 && sg[5]>=sg[4]+1) { // S[k,r] r = sg[5] - 2*k; cnt++; SG_Typ = SG_Typ + " S[k,r]=S["+string(k)+","+string(r)+"]"; } if(sg[3]==sg[5]+2 && sg[4]>=sg[5]) { // S#[k,2r-1] r = sg[4] - 2*k + 1; cnt++; SG_Typ = SG_Typ + " S#[k,2r-1]=S#["+string(k)+","+string(2*r-1)+"]"; } if(sg[3]==sg[5]+1 && sg[4]>=sg[5]) { // S#[k,2r] r = sg[4] - 2*k + 1; cnt++; SG_Typ = SG_Typ + " S#[k,2r]=S#["+string(k)+","+string(2*r)+"]"; } } else { // 3. Stelle ist gerade. if(sg[3]==sg[5]+1 && sg[5]==sg[4]+3) { // S[12k+4] k = (sg[3]-2) div 2; cnt++; SG_Typ = SG_Typ + " S[12k+4]=S["+string(12*k+4)+"]"; } if(sg[3]==sg[5]+2 && sg[5]==sg[4]+1) { // S[12k+5] k = (sg[3]-2) div 2; cnt++; SG_Typ = SG_Typ + " S[12k+5]=S["+string(12*k+5)+"]"; } } } debug_log(2, "finishing HKclass5_teil_2"); debug_log(6, "HKclass5_teil_2: ", SG_Typ, " cnt=", cnt); v = SG_Typ, cnt; return(v); } /////////////////////////////////////////////////////////////////////////////// static proc HKclass7 (intvec sg, string SG_Typ, int cnt) { list v; if(sg[1]==1 && sg[2]==0 && sg[3]==1) { v=HKclass7_teil_1(sg, SG_Typ, cnt); } else { v[1]="not in list"; v[2]=0; } debug_log(6, "HKclass7: ", v[1], " cnt=", v[2]); return(v); } /////////////////////////////////////////////////////////////////////////////// static proc HKclass7_teil_1 (intvec sg, string SG_Typ, int cnt) { int k, r, s; list v; debug_log(2, "entering HKclass7_teil_1", sg); if(sg[4] == 2) { // V[...] if(sg[5] == 0 && sg[6] == 1 && sg[7]>0) { // V[1,r] r = sg[7] - 1; cnt++; SG_Typ = SG_Typ + " V[1,r]=V[1,"+string(r)+"]"; } if(sg[5] == 1 && sg[7] == 1) { // V#[1,2r-1] r=sg[6]+1; cnt++; SG_Typ=SG_Typ+" V#[1,2r-1]=V#[1,"+string(2*r-1)+"]"; } if(sg[5] == 1 && sg[7] == 2) { // V#[1,2r] r=sg[6]+1; cnt++; SG_Typ=SG_Typ+" V#[1,2r]=V#[1,"+string(2*r)+"]"; } } // Moegliche U[...]'s k = sg[4]; if(sg[5]==2*k-1 && sg[6]==0 && sg[7]==sg[5]) { // U[12k] cnt++;SG_Typ = SG_Typ + " U[12k]=U["+string(12*k)+"]"; } if(sg[5]==2*k && sg[6]==0 && sg[7]==sg[5]) { // U[12k+4] cnt++;SG_Typ = SG_Typ + " U[12k+4]=U["+string(12*k+4)+"]"; } if(sg[5]==2*k-1 && sg[6]>0 && sg[7]==sg[5]) { // U[k,2r-1] r=sg[6]-1; cnt++; SG_Typ=SG_Typ+" U[k,2r-1]=U["+string(k)+","+string(2*r-1)+"]"; } if(sg[5]==2*k-1 && sg[6]>0 && sg[7]==2*k) { // U[k,2r] r = sg[6]; cnt++; SG_Typ = SG_Typ + " U[k,2r]=U["+string(k)+","+string(2*r)+"]"; } debug_log(2, "finishing HKclass7_teil_1"); debug_log(6, "HKclass7_teil_1: ", SG_Typ, " cnt=", cnt); v = SG_Typ, cnt; return(v); } /////////////////////////////////////////////////////////////////////////////// proc singularity(string typ, list #) "USAGE: singularity(t, l); t=string (name of singularity), l=list of integers/polynomials (indices/parmeters of singularity) COMPUTE: get the singularity named by type t from the database. list l is as follows: @* l= k [,r [,s [,a [,b [,c [,d]..]: k,r,s=int a,b,c,d=poly. @* The name of the dbm-databasefile is: NFlist.[dir,pag]. The file is found in the current directory. If it does not exist, please run the script MakeDBM first. RETURN: Normal form and corank of the singularity named by type t and its index (indices) l. EXAMPLE: example singularity; shows an example" { poly a1, a2, a3, a4, f; int k, r, s; int len = size(#); list v, ret; classify_init(); ret = 0, 0; k = #[1]; if(len>=2) { r = #[2]; } else { r = 0; } if(len>=3) { s = #[3]; } else { s = 0; } if( k<0 || r<0 || s<0) { "Initial condition failed: k>=0; r>=0; s>=0"; "k="+string(k)+" r="+string(r)+" s="+string(s); return(ret); } int crk; init_debug(); def ring_top=basering; if(len>=4) { a1 = #[4]; } else { a1=1; } if(len>=5) { a2 = #[5]; } else { a2=1; } if(len>=6) { a3 = #[6]; } else { a3=1; } if(len>=7) { a4 = #[7]; } else { a4=1; } debug_log(4, "Values: len=", string(len), " k=", string(k), " r=", string(r)); if(defined(RingNF) != 0 ) { kill RingNF; } ring RingNF=char(basering),(x,y,z),(c,ds); poly f; map Conv=ring_top,maxideal(1); v = Singularitaet(typ, k, r, s, Conv(a1), Conv(a2), Conv(a4), Conv(a4)); f, crk = v[1..2]; debug_log(2, "Info=", f ); setring ring_top; if(defined(Phi) != 0 ) { kill Phi; } map Phi=RingNF,maxideal(1); ret = Phi(f), crk; return(ret); } example { "EXAMPLE"; echo=2; ring r=0,(x,y,z),(c,ds); init_debug(0); singularity("E[6k]",6); singularity("T[k,r,s]", 3, 7, 5); poly f=y; singularity("J[k,r]", 4, 0, 0, f); } /////////////////////////////////////////////////////////////////////////////// static proc Singularitaet (string typ,int k,int r,int s,poly a,poly b,poly c,poly d) { list v; string DBMPATH=system("getenv","DBMPATH"); string DatabasePath, Database, S, Text, Tp; poly f, f1; int crk, Mu, ret; intvec MlnCd; if( DBMPATH != "" ) { DatabasePath = DBMPATH+"/NFlist"; } else { DatabasePath = "NFlist"; } Database="DBM: ",DatabasePath; link dbmLink=Database; debug_log(2, "Opening Singalarity-database: ", newline, Database); Tp = read(dbmLink, typ); debug_log(2,"DBMread(", typ, ")=", Tp, "."); if( Tp != "(null)" && Tp !="" ) { string Key = "I_", typ; S = "f = ", Tp, ";"; debug_log(2,"S=", S, " Tp=", Tp, "Key=", Key); execute(S); execute(read(dbmLink, Key)+";"); debug_log(1, "Polynom f=", f, " crk=", crk, " Mu=", Mu, " MlnCd=", MlnCd); v = f, crk, Mu, MlnCd; } else { v = 0, 0, 0, 0; } close(dbmLink); return(v); } /////////////////////////////////////////////////////////////////////////////// proc RandomPolyK (int M, string Typ) "USAGE: RandomPolyK(M, Typ)" { //---------------------------- initialisation --------------------------------- int n, b, i, k, r, s, crk; ideal B; map Phi; string txt, Tp; list v; def ring_ext=basering; n=4; if(M<5) { M = 5; } k = random(1, M); r = random(-5, 2*M); s = random(-5, 2*M); if(r<0) { r = 0; } if(s<0) { s = 0; } ring RgAnf=char(basering),(x,y,z,t),(c,ds); poly f; v = singularity(Typ, k, r, s); f, crk = v[1..2]; // f = f +t2; if(crk==1) { f = f + y2 + z2; } if(crk==2) { f = f + z2; } txt="RandomPoly-Series: gewaehlt fall "+Typ+" mit"; txt=txt+" f="+string(f); txt; setring ring_ext; B = maxideal(1); r=1; for(i=n; i>0; i--,r++) { // for(i=1; i<=n; i=i+1) B[rvar(x(r))] = x(i); if(i>2 && random(1,10)<3) { B[rvar(x(r))] = B[rvar(x(r))] + x(i-1); } // if(i==1 && random(1,10)<4) { B[rvar(x(r))] = B[rvar(x(r))]- x(n); } if(i>0) { for(b=3; b<5; b=b+1) { // B[rvar(x(r))] = B[rvar(x(r))] + random(0,9) * x(i)^(b+2); if(random(1,20)<3) { B[rvar(x(r))] = B[rvar(x(r))] - random(-2,2)*x(b)^2; } } } } Phi=RgAnf, B; Phi; poly fr=Phi(f); fr = fr+(x(1)+x(2))^2; // return(Phi(f)); return(fr); } /////////////////////////////////////////////////////////////////////////////// proc debug_log (int level, list #) "USAGE: debug_log(level,li); level=int, li=comma separated \"message\" list COMPUTE: print \"messages\" if level>=@DeBug. useful for user-defined trace messages. EXAMPLE: example debug_log; shows an example SEE ALSO: init_debug " { int len = size(#); // int printresult = printlevel - level +1; // if(level>1) // { // dbprint(printresult, "Debug:("+ string(level)+ "): ", #[2..len]); // } // else { dbprint(printresult, #[1..len]); } if( defined(@DeBug) == 0 ) { init_debug(); } if(@DeBug>=level) { if(level>1) { "Debug:("+ string(level)+ "): ", #[1..len]; } else { #[1..len]; } } } example { "EXAMPLE:"; echo=2; example init_debug; } /////////////////////////////////////////////////////////////////////////////// proc init_debug(list #) "USAGE: init_debug([level]); level=int COMPUTE: Set the global variable @DeBug to level. The variable @DeBug is used by the function debug_log(level, list of strings) to know when to print the list of strings. init_debug() reports only changes of @DeBug. NOTE: The procedure init_debug(n); is usefull as trace-mode. n may range from 0 to 10, higher values of n give more information. EXAMPLE: example init_debug; shows an example" { int newDebug=0; if( defined(@DeBug) != 0 ) { newDebug = @DeBug; } if( size(#) > 0 ) { newDebug=#[1]; } else { string s=system("getenv", "SG_DEBUG"); if( s != "" && defined(@DeBug)==0) { s="newDebug="+s; execute(s); } } if( defined(@DeBug) == 0) { int @DeBug = newDebug; export @DeBug; if(@DeBug>0) { "Debugging level is set to ", @DeBug; } } else { if( (size(#) == 0) && (newDebug < @DeBug) ) { return(); } if( @DeBug != newDebug) { int oldDebug = @DeBug; @DeBug = newDebug; if(@DeBug>0) { "Debugging level change from ", oldDebug, " to ",@DeBug; } else { if( @DeBug==0 && oldDebug>0 ) { "Debugging switched off."; } } } } printlevel = @DeBug; } example { "EXAMPLE:"; echo=2; init_debug(); debug_log(1,"no trace information printed"); init_debug(1); debug_log(1,"some trace information"); init_debug(2); debug_log(2,"nice for debugging scripts"); init_debug(0); } /////////////////////////////////////////////////////////////////////////////// proc basicinvariants(poly f) "USAGE: basicinvariants(f); f = poly COMPUTE: Compute basic invariants of f: an upper bound d for the determinacy, the milnor number mu and the corank c of f RETURN: intvec: d, mu, c EXAMPLE: example basicinvariants; shows an example" { intvec v; ideal Jfs = std(jacob(f)); v[1] = system("HC")+1; v[2] = vdim(Jfs); v[3] = corank(f); if( v[2]0 ; j=j-1) { l1 = 0; l1w = 0; for(k=1;k<=n;k=k+1) { if(Haeufigkeit[k]>l1w) { l1=k; l1w=Haeufigkeit[k];}} RFlg[j] = l1; Haeufigkeit[l1] = 0; } debug_log(2, "Permutations:", RFlg); return(RFlg); } /////////////////////////////////////////////////////////////////////////////// static proc Show(poly g) { string s; def ring_save=basering; execute(@ringdisplay); map showpoly=ring_save,maxideal(1); s = string(showpoly(g)); setring ring_save; return (s); } /////////////////////////////////////////////////////////////////////////////// static proc checkring { int CH = char(basering); if(CH >= 2 && CH<=13) { "Ring has characteristic ",CH; "Characteristic other than 0 or 0 1 ) { i = k; k = k div t; b = i - t*k; if( (s1 == "Q[") && (b==0) ) { k=k-1; b=6; } if(Typ == "Z[") { if(b==0) { k=k-1; b=6; } if(b==1) { k=k-1; b=7; } } if( b == 0 ) { s3 = string(t)+"k"; } else { s3 = string(t)+"k+"+string(b); } } if( Typ == "S[") { i = k+1; k = i/12; b = i - 12*k; if( b == 1 ) { s3 = "k"; } else { if(b==0) { s3 = "12k"+string(b-1); } else { s3 = "12k+"+string(b-1); } } } s2 = Typ + s3 +"]"; } // es kommt mindestens ein komma vor... //----------------------- more than 1 parameter ----------------------------- else { b = find(s1, ","); s2 = "k = ",s1[1..b-1],";"; execute(s2); s1 = s1[b+1..size(s1)]; if(find(s1, ",") == 0) { debug_log(8, " Number of columns 1"); s2 = "r = "+s1+";"; execute(s2); s4 = "r"; s3 = "k"; if(r==0) { s4 = string(0); } if(k==0 && Typ=="Z[") { s3 = string(1); } if(Typ[2] == "#") { i = r+1; r = i div 2; b = i - 2*r; if( b == 1 ) { s4 = "2r"; } else { s4 = "2r-1"; } } s2 = Typ + s3 + "," + s4 +"]"; } // es kommt mindestens zwei komma vor... //----------------------- get third parameter ----------------------------- else { debug_log(8, " Number of columns >=2"); debug_log(2, "Y[k,r,s] / Z[k,r,s] / T[k,r,s]"); b = find(s1, ","); s2 = "r = ",s1[1..b-1],";"; if ((s2[5]>"0") && (s2[5]<="9")) { execute(s2); } s2 = "s = ",s1[b+1..size(s1)],";"; if ((s2[5]>"0") && (s2[5]<="9")) { execute(s2); } if(Typ=="Y[") { s2 = "Y[k,r,s]"; } if(Typ=="Z[") { s2 = "Z[k,r,s]"; } if(Typ=="T[") { s2 = "T[k,r,s]"; } } } debug_log(2, "Looking for Normalform of ",s2,"with (k,r,s) = (", k,",",r,",", s, ")" ); v = s2, k, r, s; return(v); } /////////////////////////////////////////////////////////////////////////////// proc A_L "USAGE: A_L(f); f poly A_L(s); s string, the name of the singularity COMPUTE: the normal form of f in Arnold's list of singularities in case 1, in case 2 nothing has to be computed. RETURN: A_L(f): compute via 'milnorcode' the class of f and return the normal form of f found in the database. A_L(\"name\"): get the normal form from the database for the singularity given by its name. EXAMPLE: example A_L; shows an example" { // if trace/debug mode not set, do it! init_debug(); if( typeof(#[1]) == "string" ) { if(checkring()) { return(#[1]); } return(normalform(#[1])); } if( typeof(#[1]) == "poly" ) { if(checkring()) { return(#[1]); } return(quickclass(#[1])); } } example { "EXAMPLE:"; echo=2; ring r=0,(a,b,c),ds; poly f=A_L("E[13]"); f; A_L(f); } /////////////////////////////////////////////////////////////////////////////// proc normalform(string s_in) "USAGE: normalform(s); s=string RETURN: Arnold's normal form of singularity with name s EXAMPLE: example normalform; shows an example." { string Typ; int k, r, s, crk; int n, i; poly f; list v; def ring_ext = basering; n = nvars(basering); ring ring_top=char(basering),(x(1..n)),(c,ds); if(checkring()) { return(s_in); } if(nvars(basering)<=1) { "We need at least 2 variables in basering, you have",nvars(basering),"."; return(); } // if trace/debug mode not set, do it! init_debug(); v = DecodeNormalFormString(s_in); Typ, k, r, s = v[1..4]; if(Typ=="Error") { return(0); } v = singularity(Typ, k, r, s); poly f_out; f_out, crk = v[1..2]; if(crk>1) { for(i=crk+1;i<=n;i=i+1) { f_out = f_out + x(i)^2; } } setring ring_ext; map conv_top2ext=ring_top,maxideal(1); f = conv_top2ext(f_out); // f, crk = v[1..2]; return(f); } example { "EXAMPLE:"; echo=2; ring r=0,(a,b,c),ds; normalform("E[13]"); } /////////////////////////////////////////////////////////////////////////////// proc swap "USAGE: swap(a,b); RETURN: b,a if a,b is the input (any type)" { return(#[2],#[1]); } example { "EXAMPLE:"; echo=2; swap("variable1","variable2"); } /////////////////////////////////////////////////////////////////////////////// proc Setring(int c, string name) "USAGE: " { string s="ring "+name+"=0,(x(1.."+ string(c) +")),(c,ds);"; return(s); } /////////////////////////////////////////////////////////////////////////////// proc internalfunctions() "USAGE: internalfunctions(); RETURN: nothing, display names of internal procedures of classify.lib EXAMPLE: no example" { " Internal functions for the classification using Arnold's method,"; " the function numbers correspond to numbers in Arnold's classifier:"; "Klassifiziere(poly f); //determine the type of the singularity f Funktion1bis (poly f, list cstn) Funktion3 (poly f, list cstn) Funktion6 (poly f, list cstn) Funktion13 (poly f, list cstn) Funktion17 (poly f, list cstn) Funktion25 (poly f, list cstn) Funktion40 (poly f, list cstn, int k) Funktion47 (poly f, list cstn) Funktion50 (poly f, list cstn) Funktion58 (poly fin, list cstn) Funktion59 (poly f, list cstn) Funktion66 (poly f, list cstn) Funktion82 (poly f, list cstn) Funktion83 (poly f, list cstn) Funktion91 (poly f, list cstn, int k) Funktion92 (poly f, list cstn, int k) Funktion93 (poly f, list cstn, int k) Funktion94 (poly f, list cstn, int k) Funktion95 (poly f, list cstn, int k) Funktion96 (poly f, list cstn, int k) Funktion97 (poly f, list cstn) Isomorphie_s82_x (poly f, poly fk, int k) Isomorphie_s82_z (poly f, poly fk, int k) Isomorphie_s17 (poly f, poly fk, int k, int ct) printresult (string f,string typ,int Mu,int m,int corank,int K) "; " Internal functions for the classifcation by invariants: Cubic (poly f) parity (int e) //return the parity of e HKclass (intvec i) HKclass3( intvec i, string SG_Typ, int cnt) HKclass3_teil_1 (intvec i, string SG_Typ, int cnt) HKclass5 (intvec i, string SG_Typ, int cnt) HKclass5_teil_1 (intvec i, string SG_Typ, int cnt) HKclass5_teil_2 (intvec i, string SG_Typ, int cnt) HKclass7 (intvec i, string SG_Typ, int cnt) HKclass7_teil_1 (intvec i, string SG_Typ, int cnt) "; " Internal functions for the Morse-splitting lemma: Morse(poly fi, int K, int corank) //splitting lemma itself Coeffs (list #) Coeff "; " Internal functions providing tools: ReOrder(poly f) Singularitaet(string typ,int k,int r,int s,poly a,poly b,poly c,poly d) RandomPolyK Faktorisiere(poly f, poly g, int p, int k) compute g = (ax+by^k)^p Teile(poly f, poly g); //divides f by g GetRf(poly f, int n); Show(poly f); checkring(); DecodeNormalFormString(string s); Setring(int n, string ringname); "; } example { "EXAMPLE"; echo=2; internalfunctions(); } /////////////////////////////////////////////////////////////////////////////// proc prepRealclassify(poly f) " USAGE: prepRealclassify(f); f poly RETURN: a list, containing the modality of the singularity and the type of the singularity as a string @* This procedure is needed in realclassify.lib in order to avoid classify() being called more than once. EXAMPLE: example prepRealclassify; shows an example" { exportinvariants(f); return(list(Modality, Type)); } example { "EXAMPLE"; echo = 2; ring r = 0, (x,y,z), ds; poly f = (x2+3y-2z)^2+xyz-(x-y3+x2z3)^3; prepRealclassify(f); } /////////////////////////////////////////////////////////////////////////////// proc modality(poly f) " USAGE: modality(f); f poly RETURN: the modality of the singularity EXAMPLE: example modality; shows an example" { exportinvariants(f); return(Modality); } example { "EXAMPLE"; echo = 2; ring r = 0, (x,y,z), ds; poly f = (x2+3y-2z)^2+xyz-(x-y3+x2z3)^3; modality(f); } /////////////////////////////////////////////////////////////////////////////// proc complexSingType(poly f) " USAGE: complexSingType(f); f poly RETURN: the type of the singularity as a string EXAMPLE: example complexSingType; shows an example" { exportinvariants(f); return(Type); } example { "EXAMPLE"; echo = 2; ring r = 0, (x,y,z), ds; poly f = (x2+3y-2z)^2+xyz-(x-y3+x2z3)^3; complexSingType(f); } /////////////////////////////////////////////////////////////////////////////// /* some of the invariants will be exported during the computation of * classify(f) such that they are accessible at for all procs in the library */ static proc exportinvariants(poly f) { init_debug(-1); if(!defined(onlyreturninvariants)) { int onlyreturninvariants; export(onlyreturninvariants); } onlyreturninvariants = 1; if(!defined(Modality)) { int Modality; export(Modality); } if(!defined(Type)) { string Type; export(Type); } f = classify(f); } /////////////////////////////////////////////////////////////////////////////// // E n d O f F i l e singular-4.0.3+ds/Singular/LIB/classify_aeq.lib000066400000000000000000001650671266270727000213210ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version classify_aeq.lib 4.0.0.0 Jun_2013 "; // $Id: ee0a0534da1692b82475460664b9b5b0733ea66b $ category="Singularities"; info=" LIBRARY: classifyAeq.lib Simple Space Curve singularities in characteristic 0 AUTHORS: Faira Kanwal Janjua fairakanwaljanjua@gmail.com Gerhard Pfister pfister@mathematik.uni-kl.de Khawar Mehmood khawar1073@gmail.com NEU OVERVIEW: A library for classifying the simple singularities with respect to A equivalence in characteristic 0. Simple Surface singularities in characteristic O have been classified by Bruce and Gaffney [4] resp. Gibson and Hobbs [1] with respect to A equivalence. If the input is one of the simple singularities in [1] it returns a normal form otherwise a zero ideal(i.e not simple). REFERENCES: [1] Gibson,C.G; Hobbs,C.A.:Simple SIngularities of Space Curves. Math.Proc. Comb.Phil.Soc.(1993),113,297. [2] Hefez,A;Hernandes,M.E.:Standard bases for local rings of branches and their modules of differentials. Journal of Symbolic Computation 42(2007) 178-191. [3] Hefez,A;Hernandes,M.E.:The Analytic Classification Of Plane Branches. Bull.Lond Math Soc.43.(2011) 2,289-298. [4] Bruce, J.W.,Gaffney, T.J.: Simple singularities of mappings (C, 0) ->(C2,0). J. London Math. Soc. (2) 26 (1982), 465-474. [5] Ishikawa,G; Janeczko,S.: The Complex Symplectic Moduli Spaces of Unimodal Parametric Plane Curve NEU Singularities. Insitute of Mathematics of the Polish Academy of Sciences,Preprint 664(2006) PROCEDURES: sagbiAlg(G); Compute the Sagbi-basis of the Algebra. sagbiMod(I,A); Compute the Sagbi- basis of the Module. semiGroup(G); Compute the Semi-Group of the Algebra provided the input is Sagbi Bases of the Algebra. semiMod(I,A); Compute the Semi-Module provided that the input are the Sagbi Bases of the Algebra resp.Module. planeCur(I); Compute the type of the Simple Plane Curve singularity. spaceCur(I); Compute the type of the simple Space Curve singularity. "; LIB "algebra.lib"; LIB "curvepar.lib"; /////////////////////////////////////////////////////////////////////////////// proc planeCur(ideal I) "USAGE": planeCur(I); I ideal RETURN: An ideal.Ideal is one of the singularity in the list of Bruce and Gaffney [4] EXAMPLE: example planeCur; shows an example " { def R=basering; I=sortMOD(I); list M; list K; if(I==0) {return(I);} ideal G=sagbiAlg(I); list L=semiGroup(G); ideal J=diff(G,var(1)); J=sagbiMod(J,G); M=semiMod(J,G); int C=L[2]; ideal Z=0,0; if(L[1][1]>4) { return(Z); } if(L[1][1]==1) { ideal A=var(1); K=Guess(A); if(CompareList(M,K,6)!=0) { return(A); } else { return(Z); } } if(L[1][1]==2) { ideal A=var(1)^2,var(1)^(L[2]+1); K=Guess(A); if(CompareList(M,K,6)!=0) { return(A); } else { return(Z); } } if(L[1][1]==4) { if(L[1][2]==5) { intvec q=4,5; if((L[1]==q)&&(L[2]==12)&&(size(L[3])==7)) { intvec q1=3,4; intvec q2=3,4,10; if((M[4]==q1)&&(M[5]==11)&&(size(M[6])==6)) { ideal A=var(1)^4,var(1)^5; K=Guess(A); if(CompareList(M,K,6)!=0) { return(A); } } if((M[4]==q2)&&(M[5]==7)&&(size(M[6])==3)) { ideal A=var(1)^4,var(1)^5+var(1)^7; K=Guess(A); if(CompareList(M,K,6)!=0) { return(A); } } else { return(Z); } } else { return(Z); } } if(L[1][2]==6) { ideal A=var(1)^4,var(1)^6+var(1)^(L[1][3]-6); K=Guess(A); if(L[1][3] mod 2 !=0) { ideal S=t4,t6+t^(M[2]-9); if(CompareList(M,K,6)!=0) { return(S); } if(CompareList(M,K,6)==0) { int m=size(K[4])+1; if(size(M[4])==m) { return(S); } else{return(Z);} } } else { return(Z); } } if(L[1][2]==7) { intvec q=4,7;list K; ideal A=var(1)^4,var(1)^7; ideal B=var(1)^4,var(1)^7+var(1)^9; ideal T=var(1)^4,var(1)^7+var(1)^10; list Q=A,B,T; for(int i=1;i<=3;i++) { K=Guess(Q[i]); if(CompareList(M,K,6)!=0) { if(i==1) { return(A); break; } if(i==2) { return(B); break; } if(i==3) { return(T); break; } } } else { return(Z); } } else { return(Z); } } if(L[1][1]==3) { int k=L[1][2]-1; int p=L[1][2]-2; if(k mod 3 ==0) { if(size(M[4])==2) { ideal A=var(1)^3,var(1)^L[1][2]; ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5]; list Q=A,B; for(int i=1;i<=2;i++) { K=Guess(Q[i]); if(CompareList(M,K,6)!=0) { return(Q[i]); } } } if(size(M[4])==3) { ideal A=var(1)^3,var(1)^L[1][2]; ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5]; list Q=A,B; for(int i=1;i<=2;i++) { K=Guess(Q[i]); if(CompareList(M,K,6)!=0) { return(Q[i]); } } } else { return(Z); } } if(p mod 3 ==0) { if(size(M[4])==2) { ideal A=var(1)^3,var(1)^L[1][2]; ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5]; list Q=A,B; for(int i=1;i<=2;i++) { K=Guess(Q[i]); if(CompareList(M,K,6)!=0) { return(Q[i]); } } } if(size(M[4])==3) { ideal A=var(1)^3,var(1)^L[1][2]; ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5]; list Q=A,B; for(int i=1;i<=2;i++) { K=Guess(Q[i]); if(CompareList(M,K,6)!=0) { return(Q[i]); } } } else { return(Z); } } else { return(Z) } } } example { "EXAMPLE:"; echo=2; ring R=0,t,Ds; ideal I=t4+4t5+6t6+8t7+13t8+12t9+10t10+12t11+6t12+4t13+4t14+t16,t7+7t8+22t9+51t10+113t11+219t12+366t13+589t14+876t15+1170t16+1514t17 +1828t18+2011t19+2165t20+2163t21+1982t22+1806t23+1491t24+1141t25+889t26+588t27+379t28+252t29+120t30+72t31+36t32+9t33+9t34+t36; planeCur(I); } //////////////////////////////////////////////////////////////////////////////// proc spaceCur(ideal I) "USAGE": spaceCur(I); I ideal RETURN: an ideal. Ideal is one of the singularity in the list of C.G.Gibson and C.A.Hobbs. EXAMPLE: example spaceCur; shows an example " { def R=basering; I=sortMOD(I); list M; list K; if(I==0) {return(I);} ideal G=sagbiAlg(I); if(size(G)<=2){return(planeCur(G));} list L=semiGroup(G); ideal J=diff(G,var(1)); J=sagbiMod(J,G); M=semiMod(J,G); int C=L[2]; ideal Z=0,0,0; if(L[1][1]>5) { return(Z); } if(L[1][1]==3) { int k=L[1][2]-1; int p=L[1][2]-2; if(k mod 3 ==0) { poly q=var(1)*(J[2])-G[2]; if(leadexp(q)!=leadexp(J[3])) { if(size(M[4])!=3) { ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5],var(1)^L[1][3]; return(B); } if(size(M[4])==3) { ideal I1=G[1],G[2]; I1=sortMOD(I1); ideal T=sagbiAlg(I1); ideal J1=diff(T,var(1)); J1=sagbiMod(J1,T); K=semiMod(J1,T); if(size(K[4])!=2) { ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5],var(1)^L[1][3]; return(B); } if(size(K[4])==2) { ideal A=var(1)^3,var(1)^L[1][2],var(1)^L[1][3]; return(A); } } } if(leadexp(q)==leadexp(J[3])) { if(size(M[4])!=3) { ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5],var(1)^L[1][3]; return(B); } if(size(M[4])==3) { ideal I1=G[1],G[2]; I1=sortMOD(I1); ideal T=sagbiAlg(I1); ideal J1=diff(T,var(1)); J1=sagbiMod(J1,T); K=semiMod(J1,T); if(size(K[4])!=2) { ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5],var(1)^L[1][3]; return(B); } if(size(K[4])==2) { ideal A=var(1)^3,var(1)^L[1][2],var(1)^L[1][3]; return(A); } } } } if(p mod 3 ==0) { poly q=var(1)^3*(J[2])-var(1)^2*(G[2]); if(leadexp(q)!=leadexp(J[3])) { if(size(M[4])!=3) { ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5],var(1)^L[1][3]; return(B); } if(size(M[4])==3) { ideal I1=G[1],G[2]; I1=sortMOD(I1); ideal T=sagbiAlg(I1); ideal J1=diff(T,var(1)); J1=sagbiMod(J1,T); K=semiMod(J1,T); if(size(K[4])!=2) { ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5],var(1)^L[1][3]; return(B); } if(size(K[4])==2) { ideal A=var(1)^3,var(1)^L[1][2],var(1)^L[1][3]; return(A); } } } if(leadexp(q)==leadexp(J[3])) { if(size(M[4])!=3) { ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5],var(1)^L[1][3]; return(B); } if(size(M[4])==3) { ideal I1=G[1],G[2]; ideal T=sagbiAlg(I1); ideal J1=diff(T,var(1)); J1=sagbiMod(J1,T); K=semiMod(J1,T); if(size(K[4])!=2) { ideal B=var(1)^3,var(1)^L[1][2]+var(1)^M[5],var(1)^L[1][3]; return(B); } if(size(K[4])==2) { ideal A=var(1)^3,var(1)^L[1][2],var(1)^L[1][3]; return(A); } } } } else { return(Z); } } if(L[1][1]==4) { if(L[1][2]==5) { if(L[1][3]==11) { ideal A=var(1)^4,var(1)^5,var(1)^11; ideal B=var(1)^4,var(1)^5+var(1)^7,var(1)^11; list Q=A,B; ideal Ij=jet(I,10); Ij=simplify(Ij,2); ideal Gj=sagbiAlg(Ij); list Lj=semiGroup(Gj); ideal Jj=diff(Gj,var(1)); Jj=sagbiMod(Jj,Gj); list Mj=semiMod(Jj,Gj); if(size(Mj[4])==2) { K=Guess(Q[1]); if(CompareList(M,K,6)!=0) { return(Q[1]); } } if(size(Mj[4])==3) { K=Guess(Q[2]); if(CompareList(M,K,6)!=0) { return(Q[2]); } } } if(L[1][3]!=11) { ideal A=var(1)^4,var(1)^5,var(1)^6; ideal B=var(1)^4,var(1)^5,var(1)^7; list Q=A,B; for(int i=1;i<=2;i++) { K=Guess(Q[i]); if(CompareList(M,K,6)!=0) { return(Q[i]); break; } } } else {return(Z); } } if(L[1][2]==6) { if(size(L[1])==3) { if(size(M[4])==3) { ideal A=var(1)^4,var(1)^6,var(1)^L[1][3]; K=Guess(A); if(CompareList(M,K,6)!=0) { return(A); } else { return(Z); } } if(size(M[4])==4) { ideal A=var(1)^4,var(1)^6+var(1)^(L[1][3]-2),var(1)^L[1][3]; K=Guess(A); if(CompareList(M,K,6)!=0) { return(A); } else { return(Z); } } } if(size(L[1])==4) { if(size(M[4])==4) { ideal A=var(1)^4,var(1)^6+var(1)^(L[1][3]-4),var(1)^L[1][3]; K=Guess(A); if(CompareList(M,K,6)!=0) { return(A); } else { return(Z); } } if(size(M[4])==5) { ideal A=var(1)^4,var(1)^6+var(1)^(L[1][4]-8),var(1)^L[1][4]; K=Guess(A); if(CompareList(M,K,6)!=0) { return(A); } else { return(Z); } } } else { return(Z); } } if(L[1][2]==7) { if(L[1][3]==9) { ideal A=var(1)^4,var(1)^7,var(1)^9+var(1)^10; ideal B=var(1)^4,var(1)^7,var(1)^9; list Q=A,B; for(int i=1;i<=2;i++) { K=Guess(Q[i]); if(CompareList(M,K,6)!=0) { return(Q[i]); break; } } } if(L[1][3]==10) { ideal A=var(1)^4,var(1)^7,var(1)^10; ideal B=var(1)^4,var(1)^7+var(1)^9,var(1)^10; list Q=A,B; for(int i=1;i<=2;i++) { K=Guess(Q[i]); if(CompareList(M,K,6)!=0) { return(Q[i]); break; } } } if(L[1][3]==13) { ideal A=var(1)^4,var(1)^7,var(1)^13; ideal B=var(1)^4,var(1)^7+var(1)^9,var(1)^13; list Q=A,B; ideal Ij=jet(I,12); Ij=simplify(Ij,2); ideal Gj=sagbiAlg(Ij); list Lj=semiGroup(Gj); ideal Jj=diff(Gj,var(1)); Jj=sagbiMod(Jj,Gj); Jj=jet(Jj,12); Jj=simplify(Jj,2); list Mj=semiMod(Jj,Gj); if(size(Jj)==2) { K=Guess(Q[1]); if(CompareList(M,K,6)!=0) { return(A); break; } } if(size(Jj)==3) { K=Guess(Q[2]); if(CompareList(M,K,6)!=0) { return(B); break; } } } if(L[1][3]==17) { ideal A=var(1)^4,var(1)^7,var(1)^17; ideal B=var(1)^4,var(1)^7+var(1)^9,var(1)^17; ideal T=var(1)^4,var(1)^7+var(1)^10,var(1)^17; list Q=A,B,T; for(int i=1;i<=3;i++) { K=Guess(Q[i]); if(CompareList(M,K,6)!=0) { if(i==2) { return(Q[i]); break; } else { ideal Ij=jet(I,16); Ij=simplify(Ij,2); ideal Gj=sagbiAlg(Ij); list Lj=semiGroup(Gj); ideal Jj=diff(Gj,var(1)); Jj=sagbiMod(Jj,Gj); Jj=jet(Jj,16); Jj=simplify(Jj,2); list Mj=semiMod(Jj,Gj); if(size(Jj)==2) { if(CompareList(M,K,6)!=0) { return(A); break; } } if(size(Jj)==3) { if(CompareList(M,K,6)!=0) { return(T); break; } } } } } } else { return(Z); } } } } example { "EXAMPLE:"; echo=2; ring R=0,t,Ds; ideal I=t3+3t4+3t5+t6,t13+14t14+92t15+377t16+1079t17+2288t18+3718t19+4719t20+4719t21+3718t22+2288t23+1079t24+377t25+92t26+14t27+t28,t17+17t18+136t19+680t20+2380t21+6188t22+12376t23+19448t24+24310t25+24310t26+19448t27+12376t28+6188t29+2380t30+680t31+136t32+17t33+t34; spaceCur(I); } //////////////////////////////////////////////////////////////////////////////// proc sagbiAlg(ideal I,list #) "USAGE": sagbiAlg(I); I ideal RETURN: An ideal.The sagbi bases of I. EXAMPLE: example sagbiAlg; shows an example { def R=basering; def O=changeord(list(list("Ds",nvars(R)))); setring O; ideal I=imap(R,I); ideal L; poly h; int z,n; if(size(I)==0){return(I);} if(size(#)==0) { int b=ConductorBound(I); // int b=200; // b=correctBound(I,b); } else { int b=#[1]; } ideal S=interReduceSagbi(I,b) ; // b=correctBound(S,b); while(size(S)!=n) { n=size(S); L=sagbiSP(S); for (z=1;z<=size(L);z++) { h=sagbiNF(L[z],S,b); if(h!=0) { S=insertOne(h,S,b); } } } setring R; ideal S=imap(O,S); return(S); } example { "EXAMPLE:"; echo=2; ring R=0,t,ds; ideal I=t8,t10+t13,t12+t15; sagbiAlg(I); I=t8,t10+t13,t12+2t15; sagbiAlg(I); } //////////////////////////////////////////////////////////////////////////////// NEU proc reducedSagbiAlg(ideal I,list #) { I=sagbiAlg(I,#); intvec L=semiGroup(I)[3]; if(size(#)==0) { int b=findConductor(L); } else { int b=#[1]; } int i; poly q; for(i=1;i<=size(I);i++) { q=I[i]-lead(I[i]); q=sagbiNF(q,I,b); I[i]=lead(I[i])+q; } return(I); } example { "EXAMPLE:"; echo=2; ring R=0,t,ds; ideal I=t4+2t9,t9+t10+19/18t11-3t12+t13-t14; reducedSagbiAlg(I); } //////////////////////////////////////////////////////////////////////////////// NEU proc classifyAEQunimodal(ideal I) "USAGE": classifyAEQunimodal(I); I ideal generated by 2 polynomials RETURN: An ideal.Ideal is one of the singularity in the list of Ishikawa and Jenczko [5] EXAMPLE: example classifyAEQunimodal; shows an example " { def R=basering; ring @S=0,t,ds; ideal I=fetch(R,I); ideal J; poly g; if(size(I)>=3){ERROR("not a plane curve");} I=simplify(I,2); //deletes zero’s i I I=simplify(I,1); //creates monic generators in I if(ord(I[1])>ord(I[2])){poly q=I[2];I[2]=I[1];I[1]=q;} if((ord(I[1])>=6)||(ord(I[1])<=3)){return("not in the unimodal list");} //compute estimate of the term with the modulus int c=ord(sagbiNF(I[2],ideal(I[1]),10)); if(c==10) { if(ord(I[1])!=4){return("not in the unimodal list");} c=ord(I[2][2])+2; } else { c=0; intvec v=ord(I[1]),ord(I[2]); if(v==intvec(5,6)){c=14;} if(v==intvec(5,7)){c=18;} if(v==intvec(5,8)){c=22;} if(v==intvec(4,9)){c=19;} if(v==intvec(4,11)){c=25;} if(c==0){return("not in the unimodal list");} } while(size(I[1])>1) { I=jet(subst(I,t,t-number(1)/number(ord(I[1]))*leadcoef(I[1][2])*t^(ord(I[1][2])-ord(I[1])+1)),c); } ideal G=I; G[2]=sagbiNF(G[2],ideal(G[1]),c); ideal M=sagbiMod(diff(G,t),G); list K=semiMod(M,G); if(K[1]==intvec(4,9)) { if(K[4]==intvec(3,8)){J=t4,t9;} if(K[4]==intvec(3,8,22)){J=t4,t9+t19;} if(K[4]==intvec(3,8,18)){J=t4,t9+t15;} if(K[4]==intvec(3,8,14)){J=t4,t9+t11;} if(K[4]==intvec(3,8,13)) { G=reducedSagbiAlg(G,15); if(ord(G[2][4])==14) { //kill the term t14 by some transformation G=subst(G,t,t-leadcoef(G[2][4])/9*t^6); G=jet(G,15); G[1]=sagbiNF(G[1],ideal(G[2]),15); //arrange the first element to be t4 while(size(G[1])>1) { G=subst(G,t,t-1/4*(G[1]-lead(G[1]))/t^3); G=jet(G,15); } } G[2]=sagbiNF(G[2],ideal(G[1]),15); //arrange the coefficient of t10 to become 1 number m=leadcoef(G[2]-lead(G[2])); G[2]=m^9*subst(G[2],t,1/m*t); J=G; } if(K[4]==intvec(3,8,13,18)) { G=reducedSagbiAlg(G,11); number m=leadcoef(G[2]-lead(G[2])); G[2]=m^9*subst(G[2],t,1/m*t); J=G; } } if(K[1]==intvec(4,11)) { if(K[4]==intvec(3,10)){J=t4,t11;} if(K[4]==intvec(3,10,28)){J=t4,t11+t25;} if(K[4]==intvec(3,10,24)){J=t4,t11+t21;} if(K[4]==intvec(3,10,20)){J=t4,t11+t17;} if(K[4]==intvec(3,10,16)) { G=reducedSagbiAlg(G,14); number m=leadcoef(G[2]-lead(G[2])); number l=leadcoef(G[2][3]); //lambda^2=l^2/m^3 J=G; } if(K[4]==intvec(3,10,17)) { G=reducedSagbiAlg(G,21); if(ord(G[2][4])==18) { //kill the term t18 by some transformation G=subst(G,t,t-leadcoef(G[2][4])/11*t^8); G=jet(G,21); G[1]=sagbiNF(G[1],ideal(G[2]),21); //arrange the first element to be t4 while(size(G[1])>1) { G=subst(G,t,t-1/4*(G[1]-lead(G[1]))/t^3); G=jet(G,21); } } G[2]=sagbiNF(G[2],ideal(G[1]),21); //arrange the coefficient of t14 to become 1 number m=leadcoef(G[2]-lead(G[2])); number l=leadcoef(G[2][4]); //lambda^2=l^3/m^10 J=G; } if(K[4]==intvec(3,10,17,24)) { G=reducedSagbiAlg(G,18); //arrange the coefficient of t14 to become 1 number m=leadcoef(G[2]-lead(G[2])); G[2]=t11+t14+leadcoef(G[2][3])/m^2*t17; J=G; } } if((size(K[1])==3)&&(K[1][1]==4)&&(K[1][2]==10)) { int l=(K[1][3]-19) div 2; G=reducedSagbiAlg(G,2*l+12); number m=leadcoef(G[2]-lead(G[2])); number s=leadcoef(G[2][3]); //lambda^(2l-1)=s^(2l-1)/m^(2l+1) J=G; } if(K[1]==intvec(5,6)) { if(K[4]==intvec(4,5)){J=t5,t6;} if(K[4]==intvec(4,5,18)){J=t5,t6+t14;} if(K[4]==intvec(4,5,13)){J=t5,t6+t9;} if(K[4]==intvec(4,5,12)) { G=reducedSagbiAlg(G,9); if(ord(G[2][2])==7) { //kill the term t7 by some transformation G=subst(G,t,t-leadcoef(G[2][2])/6*t^2); G=jet(G,10); G[1]=sagbiNF(G[1],ideal(G[2]),9); //arrange the first element to be t4 while(size(G[1])>1) { G=subst(G,t,t-1/5*(G[1]-lead(G[1]))/t^4); G=jet(G,9); } } G[2]=sagbiNF(G[2],ideal(G[1]),9); //arrange the coefficient of t8 to become 1 number m=leadcoef(G[2]-lead(G[2])); number l=leadcoef(G[2][3]); //lambda^2=l^2/m^3 J=G; } } if(K[1]==intvec(5,7)) { if(K[4]==intvec(4,6)){J=t5,t7;} if(K[4]==intvec(4,6,22)){J=t5,t7+t18;} if(K[4]==intvec(4,6,17)){J=t5,t7+t13;} if(K[4]==intvec(4,6,12)) { G=reducedSagbiAlg(G,11); if(ord(G[2][3])==9) { //kill the term t9 by some transformation G=subst(G,t,t-leadcoef(G[2][3])/7*t^3); G=jet(G,11); G[1]=sagbiNF(G[1],ideal(G[2]),11); //arrange the first element to be t4 while(size(G[1])>1) { G=subst(G,t,t-1/5*(G[1]-lead(G[1]))/t^4); G=jet(G,11); } } G[2]=sagbiNF(G[2],ideal(G[1]),11); //arrange the coefficient of t8 to become 1 number m=leadcoef(G[2]-lead(G[2])); G[2]=m^7*subst(G[2],t,1/m*t); J=G; } if(K[4]==intvec(4,6,15)) { G=reducedSagbiAlg(G,14); if(ord(G[2][2])==9) { //kill the term t9 by some transformation G=subst(G,t,t-leadcoef(G[2][2])/7*t^3); G=jet(G,14); G[1]=sagbiNF(G[1],ideal(G[2]),14); //arrange the first element to be t4 while(size(G[1])>1) { G=subst(G,t,t-1/5*(G[1]-lead(G[1]))/t^4); G=jet(G,14); } } G[2]=sagbiNF(G[2],ideal(G[1]),14); //arrange the coefficient of t11 to become 1 number m=leadcoef(G[2]-lead(G[2])); number l=leadcoef(G[2][3]); //lambda^2=l^2/m^3 J=G; } } if(K[1]==intvec(5,8)) { if(K[4]==intvec(4,7)){J=t5,t8;} if(K[4]==intvec(4,7,26)){J=t5,t8+t22;} if(K[4]==intvec(4,7,21)){J=t5,t8+t17;} if(K[4]==intvec(4,7,13)) { G=reducedSagbiAlg(G,12); if(ord(G[2][3])==11) { //kill the term t11 by some transformation G=subst(G,t,t-leadcoef(G[2][3])/8*t^4); G=jet(G,12); G[1]=sagbiNF(G[1],ideal(G[2]),12); //arrange the first element to be t4 while(size(G[1])>1) { G=subst(G,t,t-1/5*(G[1]-lead(G[1]))/t^4); G=jet(G,12); } } G[2]=sagbiNF(G[2],ideal(G[1]),12); //arrange the coefficient of t9 to become 1 number m=leadcoef(G[2]-lead(G[2])); G[2]=m^8*subst(G[2],t,1/m*t); J=G; } if(K[4]==intvec(4,7,16)) { G=reducedSagbiAlg(G,14); if(ord(G[2][2])==11) { //kill the term t11 by some transformation G=subst(G,t,t-leadcoef(G[2][2])/8*t^4); G=jet(G,14); G[1]=sagbiNF(G[1],ideal(G[2]),14); //arrange the first element to be t4 while(size(G[1])>1) { G=subst(G,t,t-1/5*(G[1]-lead(G[1]))/t^4); G=jet(G,14); } } G[2]=sagbiNF(G[2],ideal(G[1]),14); //arrange the coefficient of t12 to become 1 number m=leadcoef(G[2]-lead(G[2])); number l=leadcoef(G[2][3]); //lambda^2=l^2/m^3 J=G; } if(K[4]==intvec(4,7,18)) { G=reducedSagbiAlg(G,17); if(ord(G[2][2])==11) { //kill the term t11 by some transformation G=subst(G,t,t-leadcoef(G[2][2])/8*t^4); G=jet(G,17); G[1]=sagbiNF(G[1],ideal(G[2]),17); //arrange the first element to be t4 while(size(G[1])>1) { G=subst(G,t,t-1/5*(G[1]-lead(G[1]))/t^4); G=jet(G,17); } } G[2]=sagbiNF(G[2],ideal(G[1]),17); //arrange the coefficient of t12 to become 1 number m=leadcoef(G[2]-lead(G[2])); number l=leadcoef(G[2][3]); //lambda^2=l^2/m^3 J=G; } } setring R; ideal J=fetch(@S,J); if(size(J)==0) { return("not in the unimodal list"); } return(J); } example { "EXAMPLE:"; echo=2; ring R=0,t,ds; ideal I=t4,9t9+18t10+38t11-216t12+144t13-288t14; classifyAEQunimodal(I); I=t4,9t9+18t10+40t11-216t12+144t13-288t14; classifyAEQunimodal(I); I=t4,t11+t12+3t14+2t15+7t16+7t17; classifyAEQunimodal(I); I=t4,t11+t14+25/22t17+3t18+4t21; classifyAEQunimodal(I); I=t5,t6+2t7+t8+3t9; classifyAEQunimodal(I); I=t5,t7+3t8+3t9+5t10; classifyAEQunimodal(I); I=t5,t7+3t11+3t12+5t13; classifyAEQunimodal(I); I=t5,t8+3t9+5t10+2t11+3t12+5t13; classifyAEQunimodal(I); I=t5,t8+5t11+3t12+7t13+5t14; classifyAEQunimodal(I); I=t5,t8+5t11+7t13+5t14+7t15+2t16+8t17; classifyAEQunimodal(I); I=subst(I,t,t+t2); classifyAEQunimodal(I); I=t4+2t5+3t6+5t7+t8,9t9+18t10+40t11-216t12+144t13-288t14; classifyAEQunimodal(I); } //////////////////////////////////////////////////////////////////////////////// NEU proc computeModulus(poly p) "USAGE": computeModulus(p); p monic poly with 3 or 4 monomials RETURN: A polynomial with first and second coefficient 1 EXAMPLE: computeModulus; shows an example ASSUME: the basering has one vearable and one parameter " { def R=basering; int a1=ord(p); int a2=ord(p-lead(p)); number m=leadcoef(p-lead(p)); poly q=par(1)^(a2-a1)-1/m; ring S=(0,a),t,ds; number m=fetch(R,m); minpoly=par(1)^(a2-a1)-1/m; poly p=fetch(R,p); p=1/par(1)^a1*subst(p,var(1),par(1)*var(1)); setring R; p=imap(S,p); return(list(p,q)); } example { "EXAMPLE:"; echo=2; ring R=(0,a),t,ds; poly p=t8-395/16t14+4931/32t17; computeModulus(p); p=t8+3t12-395/16t14; computeModulus(p); p=t8-395/16t14+4931/32t17; computeModulus(p); } //////////////////////////////////////////////////////////////////////////////// NEU static proc n_thRoot(poly p,int n, int b) { //computes the n-th root of 1+p up to order b //assumes that p(0)=0 poly s=1; poly q=jet(p,b); if(q==0){return(s);} int i; for(i=1;i<=b;i++) { s=s+bino(n,i)*q; q=jet(q*p,b); } return(jet(s,b)); } //////////////////////////////////////////////////////////////////////////////// NEU static proc bino(number n, int i) { //computes the i-th binomial coefficient of 1/n if(i==0){return(1);} return(bino(n,i-1)*(1/n-i+1)/i); } //////////////////////////////////////////////////////////////////////////////// proc sagbiMod(ideal I,ideal G) "USAGE": sagbiMod(I,G); I an ideal module and ideal G being the sagbi bases of the Algebra RETURN: An ideal. the sagbi bases for the differential module. EXAMPLE: example sagbiMod; shows an example { def R=basering;//up till now the ordering of the base ring is ds def O=changeord(list(list("Ds",nvars(R)))); setring O; ideal I=imap(R,I); ideal G=imap(R,G); int n=ncols(G);poly h; if(I==0) { return(I);} ideal S,J,M; I=sortMOD(I); if(deg(lead(I[1]))<=1) { setring R; return(imap(O,I));} int b=ConductorBound(lead(G))+deg(lead(I[1])); list P;int i; P=createP(I); while(size(P)!=0) { J=P[1][1],P[1][2]; P=delete(P,1); S=SpolyMOD(J,G); for(i=1;i<=size(S);i++) { h=sagbiNFMOD(S[i],G,I,b); if(h!=0) { h=simplify(h,1); P=enlargeP(h,P,I); I[size(I)+1]=h; } } } I=sortMOD(I); setring R; ideal K=imap(O,I); return(K); } example { "EXAMPLE:"; echo=2; ring r=0,t,Ds; ideal G=t8,t10+t13,t12+t15,t23-t29,t27; ideal I=diff(G,t); sagbiMod(I,G); } //////////////////////////////////////////////////////////////////////////////// proc semiGroup(ideal I) "USAGE": semiGroup(I); I ideal the sagbi bases of Algebra. RETURN: list L; list with three entries associated to the algebra generated by the sagbi basis: generators of the semigroup the conductor the semigroup EXAMPLE: example planeCur; shows an example { list M; if(deg(I[1])<=1) { M[1]=intvec(1); M[2]=1; M[3]=intvec(0,1); } else { ideal J=lead(I); int b=ConductorBound(J); int i; list L=J[1]; for(i=2;i<=size(J);i++) { L[i]=J[i]; } M=WSemigroup(L,b); intvec v=0,M[3]; M[3]=cutAfterConductor(v); M[2]=findConductor(M[3]); } return(M); } example { "EXAMPLE:"; echo=2; ring R=0,t,ds; ideal I=t8,t10+t13,t12+t15,t23-t29,t27; semiGroup(I); I=t8,t10+t13,t12+2t15,t27-3t33,t29; semiGroup(I); } //////////////////////////////////////////////////////////////////////////////// proc semiMod(ideal I,ideal G) "USAGE": semiMod(I,G); I ideal,G ideal;I and G are the sagbi bases of the differential module resp.Algebra. RETURN: list K; K[1]min generators of the semialgebra. K[2]conductor of the algebra. K[3]genrators for the semialgebra. K[4]min generators of the module. K[5]conductor of the module. K[6]semigroup of the module. EXAMPLE: example semiMod; shows an example { list L=semiGroup(G); intvec M; list C;intvec S; int j; int k; int b; for(int i=1;i<=size(I);i++) { M[size(M)+1]=ord(I[i]); } M=M[2..size(M)]; for(i=1;i<=size(M);i++) { C[size(C)+1]=M[i]+L[3]; } int a=M[1]+L[2]; for(j=1;j<=size(M);j++) { for(i=0;i<=a;i++) { for(k=1;k<=size(L[3]);k++) { if(i==C[j][k]) { S[size(S)+1]=i; } } } } S=S[2..size(S)]; list K; K[1]=L[1];//generators of the semialgebra. K[2]=L[2];//conductor of the algebra. K[3]=L[3];//semi group of the algebra. K[4]=M;// generators of the semimodule. K[5]=findConductor(sortIntvec(S)); //conductor of the module. K[6]=cutAfterConductor(sortIntvec(S));//semigroup of the module. return(K); } example { "EXAMPLE:"; echo=2; ring r=0,t,Ds; ideal G=t4,t7+t10; ideal I=diff(G,t); ideal k=sagbiMod(I,G); semiMod(k,G); } //////////////////////////////////////////////////////////////////////////////// static proc sagbiNF(poly f,ideal I,int b) { //computes the Sagbi normal form list L=1; map psi; f=jet(f,b); if(f==0){return(f);} while((f!=0) && (L[1]!=0)) { L= algebra_containment(lead(f),lead(I),1); if (L[1]==1) { def S= L[2]; psi= S,maxideal(1),I; f=jet(f-psi(check),b); kill S; } } return (lead(f)+sagbiNF(f-lead(f),I,b)); } /* ring R=0,t,ds; ideal I=t5+t7,t4; sagbiNF(t7+2t9+3t11+t14+t13+6t15+t17,I,20); */ //////////////////////////////////////////////////////////////////////////////// static proc sagbiSP(ideal I) { //computes the set of Sagbi-s-polys if(I==0){ return(I); } list L=algDependent(lead(I)); def S= L[2]; map phi= S,maxideal(1),I; return(simplify(phi(ker),2)); } /* ring R=0,t,ds; ideal I=t4+t5,t7+t11,t9+t20; sagbiSP(I); */ //////////////////////////////////////////////////////////////////////////////// static proc sortSagbi(ideal I) { //sorts, makes input monic and removes zeros I=simplify(I,2+1); int i; int n=1; poly p; while(n) { n=0; for(i=1;ideg(lead(I[i+1]))) { n=1; p=I[i]; I[i]=I[i+1]; I[i+1]=p; break; } } } return(I); } /* ring R=0,t,ds; ideal I=3t5,7t2+t7,6t3+t8,3t+t7; sortSagbi(I); */ //////////////////////////////////////////////////////////////////////////////// static proc insertOne(poly p, ideal I, int b) { //assume I is sorted, inserts p at the correct place int i,j; poly q; for(i=1;i<=size(I);i++) { if(deg(lead(p))i;j--) { I[j]=I[j-1]; } I[i]=simplify(p,1); } if(i=c list L; int i; for(i=1;i<=size(I);i++) { L[i]=I[i]; } list M=WSemigroup(L,b); if(b>M[2]) {b=M[2]+1;} return(b); } /* ring R=0,t,ds; ideal I=t8,t10+t13,t12+t15; correctBound(I,40); I=t8,t10+t13,t12+2t15; correctBound(I,40); */ //////////////////////////////////////////////////////////////////////////////// static proc sortMinord(ideal I) { //input an ideal //output a list L[1]=minimal order, // L[2]=poly having the minimal order, // L[3]=the k suchthat I[k] has the minimal order, // L[4]=ideal I sorted in a way that minimal degree polynomial //appears as the last polynomial of the ideal.ie I[size(I)]=I[k]. int i; int n=1; list L; poly p; while(n) { n=0; for(i=1;i1)) { p=L[2]/var(1)^L[1]; J=L[4]; for(i=1;i<=L[3]-1;i++) { J[i]=J[i]/var(1)^L[1]*inversP(p,b); if(deg(lead(J[i]))==0){J[i]=J[i]-lead(J[i]);} } J=simplify(J,2); L=sortMinord(J); M[size(M)+1]=L[1]; } if(M[size(M)]==1){break;} } for(i=1;i<=size(M)-1;i++) { c=c+M[i]*(M[i]-1); } return(c+1); } /* ring r=0,t,Ds; ideal I=t3+3t7,t8+5t9; ConductorBound(I); */ //////////////////////////////////////////////////////////////////////////////// static proc sortMOD(ideal I) { //sorts, makes input monic and removes zeros I=simplify(I,2); I=simplify(I,1); int i; int n=1; poly p; while(n) { n=0; for(i=1;ideg(lead(I[i+1]))) { n=1; p=I[i]; I[i]=I[i+1]; I[i+1]=p; break; } } } return(I); } //////////////////////////////////////////////////////////////////////////////// static proc SpolyMOD(ideal S,ideal P) { //Assume that the basering is a ring in one variable. //input two ideals ideal S= generators of the module and ideal P= the sagbi basis of the algebra //output is an ideal generated by Q[p_1,p_2,...p_n]s_1-R[p_1,p_2,...p_n]s_2 for generators of //Q[lead(p_1),lead(p_2),.,lead(p_n)]lead(s_1)-R[lead(p_1),lead(p_2),.,lead(p_n)]lead(s_2)=0 . def br=basering; int n=ncols(P); ideal P1=lead(P); ideal S1=lead(S); execute ("ring T=("+charstr(br)+",x(1),z(1..n)),(y(1..2)),dp;"); poly q; execute ("ring R=("+charstr(br)+"),(x(1),y(1..2),z(1..n)),(lp(3),dp(n));"); map phi=br,x(1); ideal G=phi(P1); ideal I=phi(S1); ideal K,J; int d,o,s,j; poly q=I[1]; if(deg(I[1])>deg(I[2])) { o=1; q=I[2]; } I=I/q; for(int i=1;i<=2;i++) { K[i]=I[i]-y(i); } for(i=1;i<=n;i++) { K[2+i]=G[i]-z(i); } option(redSB); K=std(K); for(i=1;i<=size(K);i++) { if((K[i]/x(1)==0)&&((diff(K[i],y(1))!=0)||(diff(K[i],y(2))!=0))) { q=K[i]; for(j=1;j<=2;j++) { q=subst(q,y(j),0); } K[i]=K[i]-q+q*y(o+1); q=K[i]; setring T; q=imap(R,q); s=deg(q); setring R; if(s==1){J[size(J)+1]=simplify(q,1);} } } setring br; map phi=R,maxideal(1),S,P; return(phi(J)); } /* ring r=0,t,dp; ideal I=4t3,7t6+10t9; ideal J=t4,t7+t10; sortSagbi(SpolyMOD(I,J)); */ //////////////////////////////////////////////////////////////////////////////// static proc sagbiNFMODO(poly p, ideal G, ideal I,int b) { //input a poly ideal G ideal I int b is a bound //output an ideal K such that in each K[i] generators of I appear in linear. def br=basering; p=jet(p,b); if(p==0){return(p);} int n=ncols(G); int m=ncols(I); ideal G1=lead(G); ideal I1=lead(I); poly p1=lead(p); //create new ring with extra variables - execute ("ring T=("+charstr(br)+",x(1),z(1..n)),(x(2),y(1..m)),dp;"); execute ("ring R=("+charstr(br)+"),(x(1..2),y(1..m),z(1..n)),(lp(2),dp(m),dp(n));"); map phi = br,x(1); ideal P = phi(G1); ideal S = phi(I1); poly check = phi(p1); poly keep=S[1]; S=S/keep; check=check/keep; ideal M; poly q; for (int i=1;i<=m;i=i+1) { M[i]=S[i]-y(i); } for (i=1;i<=n;i=i+1) { M[m+i]=P[i]-z(i); } M[size(M)+1]=check-x(2); check=check*keep; option(redSB); M=std(M); int j,s; for(i=1;i<=size(M);i++) { if((deg(M[i]/x(2))==0)&&(M[i]/x(1)==0)) { q=subst(M[i],x(2),0); for(j=1;j<=m;j++) { q=subst(q,y(j),0); } M[i]=M[i]-q+q*y(1); q=M[i]; setring T; poly q=imap(R,q); s=deg(q); setring R; if(s==1){check=simplify(q,1);break;} } } setring br; map psi=R,maxideal(1),p,I,G; return(psi(check)); } //////////////////////////////////////////////////////////////////////////////// static proc sagbiNFMOD(poly p, ideal G, ideal I, int b) { poly f=jet(p,b); if(f==0){return(f);} poly h; while(f!=h) { h=f; f=sagbiNFMODO(f,G,I,b); } return(lead(f)+sagbiNFMOD(p-lead(p),G,I,b)); } //////////////////////////////////////////////////////////////////////////////// static proc createP(ideal I) { list P; int i=1; int j; while(i<=size(I)-1) { j=i+1; while(j<=size(I)) { P[size(P)+1]=list(I[i],I[j]); j++; } i++; } return(P); } //////////////////////////////////////////////////////////////////////////////// static proc enlargeP(poly h,list P,ideal I) { int i; for(i=1;i<=size(I);i++) { P[size(P)+1]=list(I[i],h); } return(P); } /* ring r=0,t,Ds; ideal I=4t3,7t6+10t9; ideal G=t4,t7+t10; sagbiMod(I,G,18); */ //////////////////////////////////////////////////////////////////////////////// static proc sortIntvec(intvec L) { //input: intvec L. //output: L sorted, multiple elements canceled. int i; int j; int n=1; intvec M; while(n) { for(i=1;i<=size(L);i++) { for(j=i+1;j<=size(L);j++) { if(L[i]==L[j]) { L[j]=0; } } } n=0; } for(i=1;i<=size(L);i++) { if((L[i]!=0)||(i==1)) { M[size(M)+1]=L[i]; } } int m=1;int p; while(m) { m=0; for(i=1;iM[i+1]) { m=1; p=M[i]; M[i]=M[i+1]; M[i+1]=p; break; } } } M=M[2..size(M)]; return(M); } //////////////////////////////////////////////////////////////////////////////// static proc findConductor(intvec L) { //input a intvec L //output is an integer which came before the gap from right to left. int i;int j; list K; int c; for(i=size(L);i>=2;i--) { if(L[i]!=L[i-1]+1) { c=L[i]; break; } } if(c==0){c=1;} return(c); } //////////////////////////////////////////////////////////////////////////////// static proc cutAfterConductor(intvec L) { //input an integer vector //output cut all the integers in the intvec which came after the conductor int i;int j; intvec K; int c=findConductor(L); for(i=1;i<=size(L);i++) { if(L[i]==c) { K[1..i]=L[1..i]; } } return(K); } //////////////////////////////////////////////////////////////////////////////// static proc CompareList(list L,list M,int n) { //input two list L,M with the same size n //out put 0 if not equal 1 if equal. for(int i=1;i<=n;i++) { if(L[i]!=M[i]) { i=0; break; } } return(i); } //////////////////////////////////////////////////////////////////////////////// static proc Guess(ideal I) { // comput the sagbi basis of the module //which we guess . I=sagbiAlg(I); ideal H=diff(I,var(1)); H=sagbiMod(H,I); list K=semiMod(H,I); return(K); } //////////////////////////////////////////////////////////////////////////////// /* =============================== Examples========================================== ideal I=t4+4t5+6t6+8t7+13t8+12t9+10t10+12t11+6t12+4t13+4t14+t16,t7+7t8+22t9+51t10+113t11+219t12+366t13+589t14+876t15+1170t16+1514t17+1828t1 8+2011t19+2165t20+2163t21+1982t22+1806t23+1491t24+1141t25+889t26+588t27+379t28+2 52t29+120t30+72t31+36t32+9t33+9t34+t36; planeCur(I); //============================= ideal I=t4+4t5+6t6+8t7+13t8+12t9+10t10+12t11+6t12+4t13+4t14+t16,t7+7t8+21t9+42t10+77t11+126t12+168t13+211t14+252t15+252t16+245t17+231t18+17 5t19+140t20+105t21+56t22+42t23+21t24+7t25+7t26+t28 planeCur(I); //=============================== ideal I=t4+4t5+6t6+8t7+13t8+12t9+10t10+12t11+6t12+4t13+4t14+t16,t5+5t6+11t7+22t8+46t9+73t10+107t11+161t12+198t13+231t14+272t15+262t16+250t1 7+236t18+175t19+141t20+105t21+56t22+42t23+21t24+7t25+7t26+t28 planeCur(I); //=============================== ideal I=t4+4t5+6t6+8t7+13t8+12t9+10t10+12t11+6t12+4t13+4t14+t16,t6+7t7+22t8+47t9+87t10+143t11+202t12+258t13+307t14+332t15+327t16+305t17+266 t18+205t19+155t20+111t21+62t22+42t23+22t24+7t25+7t26+t28 planeCur(I); //=============================== ideal I=t2+2t3+t4+2t5+2t6+t8,t+t2+t4; planeCur(I); //=============================== ideal I=t2+2t3+t4+2t5+2t6+t8,t3+3t4+3t5+4t6+6t7+3t8+3t9+3t10+t12; planeCur(I); //=============================== ideal I=t2+2t3+t4+2t5+2t6+t8,t5+5t6+10t7+15t8+25t9+31t10+30t11+35t12+30t13+20t14+20t15+10t16+5t17+5t18+t 20; planeCur(I); //================================================================ ideal I=t2+2t3+t4+2t5+2t6+t8,t11+11t12+55t13+176t14+440t15+957t16+1837t17+3135t18+4917t19+7150t20+9581t2 1+12046t22+14300t23+15851t24+16665t25+16687t26+15642t27+14025t28+12012t29+9570t3 0+7392t31+5412t32+3630t33+2442t34+1485t35+825t36+495t37+220t38+110t39+55t40+11t4 1+11t42+t44 planeCur(I); //=============================== ideal I=t2+2t3+t4+2t5+2t6+t8,t45+45t46+990t47+14235t48+150975t49+1264329t50+8742030t51+51530985t52+26531 7525t53+1216052255t54+5037384726t55+19091253735t56+66860434260t57+218159032410t5 8+667743178590t59+1928258130018t60+5278946615910t61+13758022145340t62+3425642198 1760t63+81743054778990t64+187438301870193t65+413998043743845t66+882643063827960t 67+1819834573178925t68+3634672399863945t69+7042671464388093t70+13256726980146210 t71+24271349963247255t72+43270648586469315t73+75192560924341905t74+1274795590273 39134t75+211037186585880765t76+341404127193205395t77+540109313678250885t78+83615 2328502076770t79+1267494306126371433t80+1882391473790147350t81+27403488768330021 60t82+3912426884928977910t83+5480608823069934180t84+7535946071701345419t85+10175 247273088233765t86+13496177050168252770t87+17590776929351920305t88+2253760903474 9950330t89+28392934993342165732t90+35181553858703840610t91+42888103580926417860t 92+51449748796644626670t93+60751205041524651720t94+70622965899108523296t95+80843 398349265488310t96+91145062374529367655t97+101225220090613564275t98+110760068529 877638960t99+119421810187582522995t100+126897320456330125725t101+132906930278955 392505t102+137221752614812709130t103+139678059865381605315t104+14018746206071963 5683t105+138742016728357115865t106+135413875517988518550t107+1303495836626693311 25t108+123759636437037165840t109+115904304930914703126t110+107077029168089360280 t111+97586814544772570280t112+87741050370279892245t113+77830012377996062865t114+ 68114044171037561004t115+58814074232856531765t116+50105762317964865600t117+42117 223130580686220t118+34929979773602146200t119+28582581501297657240t120+2307618932 9698326690t121+18381388272325750530t122+14445518786710710480t123+111999120315284 53530t124+8566543884036576384t125+6463772035817658320t126+4810966835075093880t12 7+3531977599087147320t128+2557482632962404180t129+1826346112628778972t130+128615 1054039308160t131+893096793855988260t132+611445912380539110t133+4126879484894709 90t134+274559737461674588t135+180030436220988810t136+116328756134241090t137+7406 1684381355110t138+46450833440621940t139+28695217633493598t140+17456561066064945t 141+10455665532950385t142+6164429567615550t143+3576677924170795t144+204174682346 8917t145+1146414046643415t146+632953124099190t147+343522434444255t148+1832093883 47205t149+95981896978935t150+49375510221510t151+24930700142535t152+1234956944936 0t153+5998779092790t154+2855797655022t155+1331635383390t156+607860009900t157+271 401068250t158+118455934740t159+50498441136t160+20999419155t161+8518084355t162+33 61582620t163+1290701115t164+481780299t165+173664315t166+61087950t167+20511645t16 8+6704775t169+2115729t170+610170t171+191565t172+42570t173+15180t174+1980t175+990 t176+45t177+45t178+t180 planeCur(I); //=============================== ideal I=t3+3t4+3t5+4t6+6t7+3t8+3t9+3t10+t12,t2+2t3+t4+2t5+2t6+t8 planeCur(I); //=============================== ideal I=t3+3t4+3t5+4t6+6t7+3t8+3t9+3t10+t12,t5+5t6+10t7+15t8+25t9+31t10+30t11+35t12+30t13+20t14+20t15+10t16+5t17+5t18+t20 planeCur(I); //=============================== ideal I=t3+3t4+3t5+4t6+6t7+3t8+3t9+3t10+t12,t4+4t5+6t6+8t7+13t8+12t9+10t10+12t11+6t12+4t13+4t14+t16 planeCur(I); //========================================================================== ring r=0,t,Ds; ideal I=t3,t10+t14; planeCur(I); //=============================== ideal I=t3+3t4+3t5+t6,t10+10t11+45t12+120t13+211t14+266t15+301t16+484t17+1046t18+2012t19+3004t20+ 3432t21+3003t22+2002t23+1001t24+364t25+91t26+14t27+t28 planeCur(I); //======================================= ideal I=t3+3t4+3t5+t6,t10+10t11+45t12+120t13+210t14+252t15+210t16+120t17+45t18+10t19+t20 planeCur(I); //=============================== ring r=0,t,Ds; ideal I=t3+3t4+3t5+t6,t13+14t14+92t15+377t16+1079t17+2288t18+3718t19+4719t20+4719t21+3718t22+2288 t23+1079t24+377t25+92t26+14t27+t28,t20+20t21+190t22+1140t23+4845t24+15504t25+38760t26+77520t27+125970t28+16796 0t29+184756t30+167960t31+125970t32+77520t33+38760t34+15504t35+4845t36+1140t37+19 0t38+20t39+t40 spaceCur(I); //===================================================== ideal I=t3+3t4+3t5+t6,t13+14t14+92t15+377t16+1079t17+2288t18+3718t19+4719t20+4719t21+3718t22+2288 t23+1079t24+377t25+92t26+14t27+t28,t17+17t18+136t19+680t20+2380t21+6188t22+12376t23+19448t24+24310t25+24310t26 +19448t27+12376t28+6188t29+2380t30+680t31+136t32+17t33+t34 spaceCur(I); //======================================================== ideal I=t3,t16,t14; spaceCur(I); //============================================= ideal I=t3,t19,t14; spaceCur(I); //============================================== ideal I=t3,t14+t16,t19; spaceCur(I); //=============================================== ideal I=t3,t14+t16,t25; spaceCur(I); //======================================= ideal I=t3+3t4+3t5+t6,t14+14t15+91t16+364t17+1001t18+2002t19+3003t20+3432t21+3004t22+2024t23+1232 t24+1904t25+7406t26+26348t27+74614t28+170544t29+319770t30+497420t31+646646t32+70 5432t33+646646t34+497420t35+319770t36+170544t37+74613t38+26334t39+7315t40+1540t4 1+231t42+22t43+t44,t25+25t26+300t27+2300t28+12650t29+53130t30+177100t31+480700t32+1081575t33+2 042975t34+3268760t35+4457400t36+5200300t37+5200300t38+4457400t39+3268760t40+2042 975t41+1081575t42+480700t43+177100t44+53130t45+12650t46+2300t47+300t48+25t49+t50 spaceCur(I); //========================================================= ideal I=t3+3t4+3t5+t6,t14+14t15+91t16+364t17+1001t18+2003t19+3022t20+3603t21+3972t22+5878t23+1262 9t24+27496t25+50479t26+75596t27+92379t28+92378t29+75582t30+50388t31+27132t32+116 28t33+3876t34+969t35+171t36+19t37+t38,t25+25t26+300t27+2300t28+12650t29+53130t30+177100t31+480700t32+1081575t33+2 042975t34+3268760t35+4457400t36+5200300t37+5200300t38+4457400t39+3268760t40+2042 975t41+1081575t42+480700t43+177100t44+53130t45+12650t46+2300t47+300t48+25t49+t50 spaceCur(I); //============================================================== ideal I=t3+3t4+3t5+t6,t14+14t15+92t16+380t17+1121t18+2562t19+4823t20+7800t21+11011t22+13442t23+13 871t24+11804t25+8099t26+4382t27+1821t28+560t29+120t30+16t31+t32,t19+19t20+171t21+969t22+3876t23+11628t24+27132t25+50388t26+75582t27+92378t2 8+92378t29+75582t30+50388t31+27132t32+11628t33+3876t34+969t35+171t36+19t37+t38 spaceCur(I); //====================================================================== ideal I=t3+3t4+3t5+t6,t14+14t15+92t16+380t17+1121t18+2562t19+4823t20+7800t21+11011t22+13442t23+13 871t24+11804t25+8099t26+4382t27+1821t28+560t29+120t30+16t31+t32,t25+25t26+300t27+2300t28+12650t29+53130t30+177100t31+480700t32+1081575t33+2 042975t34+3268760t35+4457400t36+5200300t37+5200300t38+4457400t39+3268760t40+2042 975t41+1081575t42+480700t43+177100t44+53130t45+12650t46+2300t47+300t48+25t49+t50 spaceCur(I); //================================================================ ideal I=t3+3t4+3t5+t6,t16+16t17+120t18+560t19+1820t20+4368t21+8008t22+11440t23+12870t24+11440t25+ 8008t26+4368t27+1820t28+560t29+120t30+16t31+t32 ,t14+14t15+91t16+364t17+1001t18+2002t19+3003t20+3432t21+3003t22+2002t23+1001 t24+364t25+91t26+14t27+t28 spaceCur(I); //=========================================================================================== */ singular-4.0.3+ds/Singular/LIB/classifyceq.lib000066400000000000000000001722561266270727000211620ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////////// version="version classifyceq.lib 4.0.0.0 Jun_2013 "; // $Id: f5489b4e3f68ada1e8639d108b4560159de83dc6 $ category="Singularities"; info=" LIBRARY: classifyCeq.lib simple hypersurface singularities in characteristic p > 0 AUTHORS: Deeba Afzal deebafzal@gmail.com Faira Kanwal Janjua fairakanwaljanjua@gmail.com OVERVIEW: A library for classifying the simple singularities with respect to contact equivalence in charateristic p > 0 . Simple hypersurface singularities in charateristic p > 0 were classified by Greuel and Kroening [1] with respect to contact equivalence. The classifier we use has been proposed in [2]. REFERENCES: [1] Greuel, G.-M.; Kroening, H.: Simple singularities in positive characteristic. Math.Z. 203, 339-354 (1990). [2] Afzal,D.;Binyamin,M.A.;Janjua,F.K.: On the classification of simple singularities in positive characteristic. PROCEDURES: classifyCeq(f); simple hypersurface singularities in charateristic p > 0 "; LIB "sing.lib"; LIB "classify.lib"; LIB "primdec.lib"; LIB "ring.lib"; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// proc classifyCeq(poly f) "USAGE: classifyCeq(f); f poly RETURN: string including the Tjurina number of f and its type in the classification of Greuel and Kroening EXAMPLE: example classifyCeq; shows an example " { def R=basering; def S=changeord(list(list("ds",1:nvars(basering)))); setring S; poly f=imap(R,f); string re; if(char(basering)==0) { re=(string(classify(f))); } if(char(basering)!=2) { re=classifyCeq1(f); } if(char(basering)==2) { re=classifyCeq2(f); } setring R; return(re); } example { "EXAMPLE:"; echo=2; ring R=3,(x,y,z,u,v,w),ds; classifyCeq(-x2+xy+y2+xz-yz-z2+w2+u3+v4); } /////////////////////////////////////////////////////////// char p > 2 ////////////////////////////////////////// static proc blowupone(poly f) { //=== input f smooth or isolated simple singularity at zero //=== output var(1) or poly with isolated singularity at zero def R=basering; def S=changeord(list(list("ds",1:nvars(basering)))); setring S; int n=nvars(basering); int i; poly f=imap(R,f); if(deg(lead(f))<=1){setring R;return(var(1));} def T=changeord(list(list("lp",1:nvars(basering)))); setring T; map phi; ideal mphi, sing; poly p,q; //=========== blow up ======================================================= for(i=1;i<=n;i++) { mphi=var(i)*maxideal(1); mphi[i]=var(i); phi=S,mphi; p=phi(f); q=p/var(i); while(size(p)==size(q)) { p=q; q=q/var(i); } //=============== p is the strict transform var(i) exceptional divisor ==== //=============== analysis of singularities ================================ sing=jacob(p),p,var(i); sing=radical(sing); option(redSB); sing=std(sing); sing=simplify(sing,1); if(size(sing)>1) { if(size(sing)!=n){ERROR("not simple");} ideal mpsi=std(maxideal(1)); for(i=1;i<=n;i++){mpsi[i]=var(i)-sing[n-i+1][2];} map psi=T,mpsi; p=psi(p); setring R; poly p=imap(T,p); return(p); } } setring R; return(var(1)); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc classifyCeq1(poly f) //====Classify Simple hypersurface singularities when charateristic p!=2 { // char!=2 //====input poly f //====output The function defines ......not an isolated singularity or not a simple singularity and tjurina // of the singularity or a simple singularity ,tjurina of the singularity and type of the singularity. def R=basering; int d; int m=tjurina(f); if(m==-1) { return("The given function defines not an isolated singularity" ); } poly g; int c; c=corank(f); if(c<=1) { if(c==0) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". A[1]:"+string(var(1))+"^2+"+string(var(2))+"^2"); } if(c==1) { poly w=blowupone(f); int n=tjurina(w); int b=m-n; if(b<=2) { return( "The given function defines a simple singularity. The tjurina number is "+string(m)+". A["+string(m)+"]:"+string(var(1))+"^2+"+string(var(2))+"^"+string(m+1)+""); } else { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". A["+string(m-1)+"]:"+string(var(1))+"^2+"+string(var(2))+"^"+string(m)+""); } } } if(c==2) { g=jet(f,3); if(g==0) { return( "The given function defines not a simple singularity. The tjurina number is "+string(m)+"."); } if(g!=0) { def S=GDsplitting(f); setring S; poly g=jet(f,3); if(g==0) { setring(R); return("The given function defines not a simple singularity. The tjurina number is "+string(m)+"."); } list L=factorize(g); if(size(L[1])==2) { ideal M=var(1),var(2)^2; ideal N=std(M^3); poly h=reduce(f,N); if(h==0) { return(" The given function defines not a simple singularity The tjurina number is "+string(m)+"."); } if(h!=0) { if((char(R)!=3)&&(char(R)!=5)) { setring R; if(m==6) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^0[6]:"+string(var(1))+"^3+"+string(var(2))+"^4"); } if(m==7) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^0[7]:"+string(var(1))+"^3+"+string(var(1))+"*"+string(var(2))+"^3"); } if(m==8) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^0[8]:"+string(var(1))+"^3+"+string(var(2))+"^5"); } } if(char(R)==5) { setring R; if(m==6) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^0[6]:"+string(var(1))+"^3+"+string(var(2))+"^4"); } if(m==7) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^0[7]:"+string(var(1))+"^3+"+string(var(1))+"*"+string(var(2))+"^3"); } if(m==10) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^0[8]:"+string(var(1))+"^3+"+string(var(2))+"^5"); } if(m==8) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^1[8]:"+string(var(1))+"^3+"+string(var(2))+"^5+"+string(var(1))+"*"+string(var(2))+"^4"); } } if(char(R)==3) { poly p=blowupone(f); int e=(std(jacob(p)+ideal(p))==1); setring R; if((m==7)&&e) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^1[6]:"+string(var(1))+"^3+"+string(var(2))+"^4+"+string(var(1))+"^2*"+string(var(2))+"^2"); } if((m==7)&&!e) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^1[7]:"+string(var(1))+"^3+"+string(var(1))+"*"+string(var(2))+"^3+"+string(var(1))+"^2*"+string(var(2))+"^2"); } if(m==8) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^2[8]:"+string(var(1))+"^3+"+string(var(2))+"^5+"+string(var(1))+"^2*"+string(var(2))+"^2"); } if(m==10) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^1[8]:"+string(var(1))+"^3+"+string(var(2))+"^5+"+string(var(1))+"^2*"+string(var(2))+"^3"); } if((m==9)&&e) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^0[6]:"+string(var(1))+"^3+"+string(var(2))+"^4"); } if((m==9)&&!e) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^0[7]:"+string(var(1))+"^3+"+string(var(1))+"*"+string(var(2))+"^3"); } if(m==12) { return("The given function defines a simple singularity. The tjurina number is "+string(m)+". E^0[8]:"+string(var(1))+"^3+"+string(var(2))+"^5"); } } else { return( "The given function defines not a simple singularity"); } } } if(size(L[1])==3) { setring R; return("The given function defines a simple singularity. The tjurina number is "+string(m)+". D["+string(m)+"]:"+string(var(1))+"^2*"+string(var(2))+"+"+string(var(2))+"^"+string(m-1)+""); } if(size(L[1])==4) { setring R; return("The given function defines a simple singularity. The tjurina number is "+string(m)+". D[4]:"+string(var(1))+"^2*"+string(var(2))+"+"+string(var(1))+"^3"); } } } if(c>=3) { return( "The given function defines not a simple singularity. The tjurina number is "+string(m)+"."); } } // ends classifyCeq1 example { "EXAMPLE:"; echo=2; ring R=5,(x,y),ds; classifyCeq1(x2y+y22); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc GDsplitting(poly f) { // the result of the splitting lemma (myMorsesplitting) in a special ring of 2 variables // input a poly f of order >=2 // output ring S=char(basering),(x,y),ds; and a poly f in ^3 in S with the following properties: // f + a sum of squares of further variables is contact equivalentt to the input polynomial def R=basering; intvec t; int b,i; b=tjurina(f); f=myMorsesplitting(f,b); t=forv(findVar(f)); ring S=char(basering),(x,y),ds; ideal M; M[t[1]]=var(1); M[t[2]]=var(2); i=1; if((i!=t[1])&&(i!=t[2])) { M[i]=0; } map phi=R,M; poly f=phi(f); export(f); setring(R); return(S); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc myMorsesplitting(poly f,int b) { // splitting lemma // input poly f=f(x(1),...,x(n)) jet(f,2)!=0 // output a polynomial in 2 variables of order >=3 such that a sum of squares of the remaining variables plus this // polynomial is contact equivalent to the input polynomial intvec w; f=simplify(jet(f,b),1); while(jet(f,2)!=0) { w=findlead(f); if(w[1]==w[2]) { f=splitting_one(f,w[1],b); } else { f=splitting_two(f,w[1],w[2],b); } } return(f); } example { "EXAMPLE:"; echo=2; ring R=3,(x,y,z,u,v),ds; poly f=x2+x3z+u2+v2+z3+y11; myMorsesplitting(f,30); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc findlead(poly f) { // input poly f=x(i)^2+h or poly f=x(i)*x(j)+h , h of order >=2 // output intvec w w[1]=i,w[2]=i or w[1]=i ,w[2]=j intvec v=leadexp(f); int i,k,n; intvec w; n=nvars(basering); for(i=1;i<=n;i++) { if(v[i]==2) { w[1]=i; w[2]=i; break; } if(v[i]==1) { k++; w[k]=i; } } return(w); } example { "EXAMPLE:"; echo=2; ring R=3,(x,y,z,u,v),ds; poly f=x2+x3z+u2+v2+z3+y11; findlead(f); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc splitting_one(poly p, int i, int b) { // assumes that p=x_i^2+h, no x_i^2 in h, h of order >=2 // returns q(x_1,??x_i-1,x_i+1,...,x_n) such that x_i^2 +q is right equivalent to p mod // ^b if(b<2){b=2;} def R=basering; ideal M=maxideal(1); map phi; poly q=jet((p-var(i)^2)/var(i),b); while(q!=0) { p=quickSubst(p,var(i)-1/2*q,i,b); q=jet((p-var(i)^2)/var(i),b); } return(simplify(jet(p,b)-var(i)^2,1)); //make the leading coefficient 1 } example { "EXAMPLE:"; echo=2; ring R=3,(x,y,z,u,v),ds; poly f=x2+y3+z4+xy3+u2+v2; splitting_one(f,1,18); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc splitting_two(poly p, int i, int j, int b) { // assumes that p=x_i*x_j+h, no x_i^2 in h, h of order >=2 // returns q(x_1,???,x_i-1,x_i+1,...,x_j-1,x_j+1,...,x_n) such that x_i*x_j +q is right equivalent to p mod // ^b if(b<2){b=2;} def R=basering; ideal M=maxideal(1); map phi; poly q=jet((p-var(i)*var(j))/var(i),b); while(q!=0) { p=quickSubst(p,var(j)-q,j,b); q=jet((p-var(i)*var(j))/var(i),b); } return(simplify(substitute(jet(p,b),var(j),0),1)); //make the leading coefficient 1 } example { "EXAMPLE:"; echo=2; ring R=5,(u,v,w,s,t),ds; poly f=uv+t2+u4s+u11+v7+s9+w8; splitting_two(f,1,2,128); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc quickSubst(poly h, poly r, int i, int b) { //=== assume h, r is in Q[x_1,...,x_n], computes jet(h(x_i=r),b) h=jet(h,b); r=jet(r,b); matrix M=coef(h,var(i)); poly q = 1; int j,k,d; intvec v; d=deg(M[1,1]); v[d+1]=1; for(k = 2; k <= ncols(M); k++) { v[deg(M[1,k])+1]=1; } h=0; for(k=1;k<=d+1;k++) { if(v[k]==1) { h=h+jet(q*M[2,ncols(M)-j],b); j++; } q=jet(q*r,b); } return(h); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc findVar(poly p) { // input poly f // output intvec v v[i]=0 if f is not depending on var(i) and v[j]=1 if f is depending on var(j) intvec v; int i,n; n=nvars(basering); for(i=1;i<=n;i++) { if(subst(p,var(i),0)==p) { v[i]=0; } else { v[i]=1; } } return(v); } example { "EXAMPLE:"; echo=2; ring R=3,(x,y,z,u,v),ds; poly f=y3+u5; findlead(f); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc forv(intvec v) { //returns the places of v which are different from zero intvec w; int i,j; j=1; for(i=1;i<=nvars(basering);i++) { if(v[i]!=0) { w[j]=i; j++; } } return(w); } /////////////////////////////////////////// char p=2 //////////////////////////////////////////////////////////////////////////// static proc classifyCeq2(poly p) //====Classification of hypersurface singularities in Characteristic p=2. { // input poly p // output The normal form to which f is contact equvalent or the function is not simple. def R=basering; int t=tjurina(p); list T; if(t==-1) { return("The given function defines not an isolated singularity"); } int b=t+1; p=SPILPRO(p,b); list L=findVAR(p); if(L[2]>=4) { return("The given function defines not a simple singularity. The Tjurina Number is "+string(t)+". "); } if(L[2]==1) { def S=redvar2(p); setring S; string a="The given function defines an isolated Singularity. The Tjurina number is "+string(t)+". A_"+string(leadexp(p)[1]-1)+":xy+z"+string(leadexp(p)[1])+"."; setring R; return(a); } if(jet(p,2)==0) { if(L[2]==3) { return("The given function defines not a simple singularity. The Tjurina Number is "+string(t)+". "); } def S=redvar2(p); setring S; string a=curCeq2(p); setring R; return(a); } else { if(L[2]==3) { int B=t div 2+1; p=splitting_SQUA(p,B); def S=redvar2(p); setring S; string a=surCeq2(p); setring R; return(a); } p=splitting_SQUA(p,b); def S=redvar2(p); setring S; string a=curCeq2(p); setring R; return(a); } } example { "EXAMPLE:"; echo=2; ring r=2,(x,y,z,w,t,v),ds; poly f=xy+zw+t5+v3; classifyCeq2(f); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc SPILPRO(poly p,int B) { //Splitting lemma in characteristic 2 //input a polynomial f and a bound B //output a polynomial q, the result of the splitting lemma applied to f up to the order B int i,j; def R=basering; int n=nvars(R); poly q=splittingLchar2(p); list T=FindPRO(q); while(size(T)!=0) { i=T[1]; j=T[2]; q=splitting_two2(q,i,j,B); T=FindPRO(q); } return(q); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc surCeq2(poly f) //====Classification of Surface Singularaties in case when p=2 { //===input a funation defined in the ring whose Characteristic is 2. //===output is a Normal Form to which Given function is contact equivalent or function is not simple. def R=basering; int n=nvars(R); list L; int k=tjurina(f); if(k==-1) { return("The given function defines not an isolated singularity."); } return(surEsing(f)); } example { "EXAMPLE:"; echo=2; ring R=2,(x,y,z),Ds; surCeq(xy+y2+yz+x2y+xy2+xyz+z21+xz21); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc surEsing(poly f) //====Classifcation of Ek singularities. { //===input: A function which is an isolated singularity. //===output: Normal form to which given function is contact equivalent. list M; def R=basering; f=formf(f); poly p=jet(f,2); int k=tjurina(f); list L=factorize(p); poly g=subst(f,leadmonom(L[1][2]),0); poly j=jet(g,3)-jet(g,2); poly C=f-g; C=C/leadmonom(L[1][2]); poly h=subst(C,leadmonom(L[1][2]),0); h=jet(h,2); poly h1=j+h*leadmonom(L[1][2]); if(h!=0) { list P=factorize(h1); list N=factorize(j); if((size(P[1])==2)&&(size(P[2])==2)&&(P[2][2]==1)&&(N[2][2]==3)) { if(k==6) { return(" The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^1[6]:z2+x3+y2z+xyz."); } if(k==8) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^0[6]:z2+x3+y2z."); } } if(((size(P[1])==4)&&(size(P[2])==4))||((size(N[1])==4)&&(size(N[2])==4))) { if(k==8) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D[4]:z2+x2y+xy2."); } if(k==6) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^1[4]:z2+x2y+xy2+xyz."); } } if((size(P[1])<=3)&&(size(P[2])<=3)) { if(k==6) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^1[5]:z2+x2y+y2z+xyz."); } if(k==8) { if(size(lengthBL(f))==4) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^3[7]:z2+x3+xy3+xyz."); } else { if(size(lengthBL(f))==5) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^4[8]:z2+x3+y5+xyz."); } else { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^0[5]:z2+x2y+y2z."); } } } } list Q=factorize(j); if((size(Q[1])==3)&&(size(Q[2])==3)) { return(surDsing(f)); } else { if(k==10) { if(size(lengthBL(f))==4) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^2[7]:z2+x3+xy3+y3z."); } if(size(lengthBL(f))==5) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^3[8]:z2+x3+y5+y3z."); } } if(k==12) { if(size(lengthBL(f))==4) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^1[7]:z2+x3+xy3+xy3z."); } if(size(lengthBL(f))==5) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^2[8]:z2+x3+y5+xy2z."); } } if(k==14) { if(size(lengthBL(f))==4) { retrun("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^0[7]:z2+x3+xy3."); } if(size(lengthBL(f))==5) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^1[8]:z2+x3+y5+xy3z."); } } if(k==16) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^0[8]:z2+x3+y5."); } } } if(h==0) { list P=factorize(j); if((size(P[1])==2)&&(size(P[2])==2)&&((P[2][2])==1)) { if(k==6) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^1[6]:z2+x3+y2z+xyz."); } if(k==8) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^0[6]:z2+x3+y2z."); } } if((size(P[1])==4)&&(size(P[2])==4)) { if(k==8) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^0[4]:z2+x2y+xy2."); } if(k==6) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^1[4]:z2+x2y+xy2+xyz."); } } if((size(P[1])==3)&&(size(P[2])==3)) { if(((P[2][2])==1)&&((P[2][3])==1)) { if(k==6) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^1[5]:z2+x2y+y2z+xyz."); } if(k==8) { if(size(lengthBL(f))==4) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^3[7]:z2+x3+xy3+xyz."); } else { if(size(lengthBL(f))==5) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^4[8]:z2+x3+y5+xyz."); } else { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^0[5]:z2+x2y+y2z."); } } } } } if((size(P[1])==2)&&((P[2][2])==3)) { if(k==10) { if(size(lengthBL(f))==4) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^2[7]:z2+x3+xy3+y3z."); } if(size(lengthBL(f))==5) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^3[8]:z2+x3+y5+y3z."); } } if(k==12) { if(size(lengthBL(f))==4) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^1[7]:z2+x3+xy3+xy3z."); } if(size(lengthBL(f))==5) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^2[8]:z2+x3+y5+xy2z."); } } if(k==14) { if(size(lengthBL(f))==4) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^0[7]:z2+x3+xy3."); } if(size(lengthBL(f))==5) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^1[8]:z2+x3+y5+xy3z."); } } if(k==16) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^0[8]:z2+x3+y5."); } } return(surDsing(f)); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc surDsing(poly f) //====Classification of Dk singularaties======================== { //===input: A function which is an isolated singularity. //===output: Normal form to which given function is contact equivalent. def R=basering; int n=nvars(R); f=formf(f); int k=tjurina(f); list M=factorize(jet(f,2)); poly g=subst(f,leadmonom(M[1][2]),0); poly j=jet(g,3); if(j==0) { return("The given function defines not a simple singularity. The Tjurina Number is "+string(k)+"."); } list P=factorize(j); if((size(P[1])==4)&&(size(P[2])==4)) { if(k==8) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^0 [4]:z2+x2y+xy2."); } if(k==6) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^1 [4]:z2+x2y+xy2+xyz."); } } if((size(P[1])==3)&&(size(P[2])==3)) { poly q=BlowUpO(f); if((tjurina(f)-tjurina(q))==4) { list Q=whichSUR(f); j=subst(Q[2],leadmonom(M[1][2]),0); poly j1=jet(j,3); list L=factorize(j1); if((size(L[1])==4)&&(size(L[2])==4)) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^0 ["+string(tjurina(f) div 2)+"]:z2+x2y+xy"+string(tjurina(f) div 4)+". "); } if((size(L[1])==3)&&(size(L[2])==3)) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^0 ["+string((tjurina(f) div 2)+1)+"]:z2+x2y+y"+string(tjurina(f) div 4)+"z."); } } if((tjurina(f)-tjurina(q))==2) { list Q=whichSUR(f); if(Q[1]==8){Q[2]=BlowUpO(Q[2]);} j=subst(Q[2],leadmonom(M[1][2]),0); poly j1=jet(j,3); list L=factorize(j1); if((size(L[1])==4)&&(size(L[2])==4)) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^"+string(findSUR(f))+" ["+string((tjurina(f)+2*findSUR(f)) div 2)+"]:z2+x2y+xy^"+string((tjurina(f)+2*findSUR(f)) div 4)+"+ xy"+string(((tjurina(f)+2*findSUR(f)) div 4)-findSUR(f))+" z."); } if((size(L[1])==3)&&(size(L[2])==3)) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^"+string(findRSUR(f))+" ["+string(((tjurina(f)+2*findRSUR(f)) div 2)+1)+"]:z2+x2y+y"+string((tjurina(f)+2*findRSUR(f)) div 4)+"z+xy"+string(((tjurina(f)+2*findRSUR(f)) div 4)-findRSUR(f))+"z."); } } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc formf(poly f) //=====Transform jet(f,2) in to the polynomial var(3)^2. //=====This is the case when We are in Dk and Ek surface singularaties. { poly j=jet(f,2); list L=factorize(j); def r=basering; if(leadmonom(L[1][2])==var(1)) { f=subst(f,var(1),L[1][2]); map phi=r,var(3),var(2),var(1); return(phi(f)); } if(leadmonom(L[1][2])==var(2)) { f=subst(f,var(2),L[1][2]); map phi=r,var(1),var(3),var(2); return(phi(f)); } if(leadmonom(L[1][2])==var(3)) { return(f); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc whichSUR(poly f) //====This procedure is required to separate the Surface Case D_2m from D_2m+1 as discribes in [2]. { int d=tjurina(f); list L; while(1) { f=BlowUpO(f); d=tjurina(f); if((d==6)||(d==8)) { L[1]=d; L[2]=f; return(L); } } return(d); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc findSUR(poly f)//D2m,r //====Number of blowup required in order either to get the difference equal to 4 or the Tjurina number is less than 6. { int a, r,b; while(1) { r++; a=tjurina(f); if(a<=1) { return(r); } f=BlowUpO(f); b=tjurina(f); if((a-b)==4) { if(b==2) { return(r); } return(r-1); } if(b<6) { return(r-1); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc findRSUR(poly f)//D2m+1,r //====Calculate the number of blow ups required by a polynomial in order to get the difference 4. { int a, r,b; while(1) { r++; a=tjurina(f); if(a==2) { return(r); } f=BlowUpO(f); b=tjurina(f); if((a-b)==4) { return(r-1); } if(b<6) { return(r); } } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc BlowUpO(poly f) //====Gives the procedure of Blowing up ingeneral { //=== input f smooth or isolated singularity at zero //=== output var(1) or poly with isolated singularity at zero, the transformation //=== of the singularity of the blowing up to zero def R=basering; def S=changeord(list(list("ds",1:nvars(basering)))); setring S; int n=nvars(basering); int i,t,c,d,e,j,k; poly f=imap(R,f); if(deg(lead(f))<=1){setring R;return(var(1));} poly p; def T=changeord(list(list("lp",1:nvars(basering)))); setring T; list L; map phi,psi; ideal mphi, mpsi,sing; poly p,q,m,l; poly h=var(1); //=========== blow up======================================================= for(i=1;i<=n;i++) { mphi=var(i)*maxideal(1); mphi[i]=var(i); phi=S,mphi; p=phi(f); q=p/var(i); while(size(p)==size(q)) { p=q; q=q/var(i); } //=============== p is the strict transform var(i) exceptional divisor ==== //=============== analysis of singularities ================================ sing=jacob(p),p,var(i); sing=radical(sing); option(redSB); sing=std(sing); if(dim(sing)>0){ERROR("not simple");} sing=std(simplify(sing,1)); if(dim(sing)==0) { if(vdim(sing)==1) { mpsi=std(maxideal(1)); for(k=1;k<=n;k++){mpsi[k]=var(k)-sing[n-k+1][2];} psi=T,mpsi; p=psi(p); } else { //this can only happen in case of a D-singularity L=minAssGTZ(sing); d=0; for(j=1;j<=size(L);j++) { sing=std(L[j]); sing=std(simplify(sing,1)); if(vdim(sing)!=1){ERROR("something is wrong in blowUpO");} mpsi=std(maxideal(1)); for(k=1;k<=n;k++){mpsi[k]=var(k)-sing[n-k+1][2];} psi=T,mpsi; m=psi(p); setring S; p=imap(T,m); e=tjurina(p); setring T; if(e>d) { d=e; l=m; } } p=l; } setring S; p=imap(T,p); c=tjurina(p); setring T; if(c>t) { t=c; h=p; } } } setring R; poly h=imap(T,h); return(h); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc lengthBL(poly f) //====Return the list of Tjurina numbers of each blowing up in the resolution before it becomes smooth. { list L; int i=1; int d=tjurina(f); while(d>=2) { f=BlowUpO(f); L[i]=d; d=tjurina(f); i=i+1; } return(L); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc curCeq2(poly f) //====Classification of Curves in Case when p=2. { int c; int k; number m,a,b; ideal I; int d; k=tjurina(f); if(k==-1) { return("The given function defines not an isolated singularity"); } if(deg(lead(f))==2) { poly f1=jet(f,2); list T=factorize(f1); if(size(T[1])==3) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". A1:x2+xy."); } if(size(T[1])==2) { poly g=BlowUpO(f); if((tjurina(f)-tjurina(g))==4) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". A["+string(k div 2)+"]:x2+y "+string(tjurina(f) div 2+1)+". where r=0. "); } else { d=whichtru(f); if(d==1) { if((k mod 4)==0) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". A["+string(2*(tjurina(f) div 2)-1)+"]:x2+xy"+string(tjurina(f) div 2)+"."); } else { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". A["+string((2*(tjurina(f)+1) div 2)-1)+"]:x2+xy"+string((tjurina(f)+1) div 2)+"."); } } if(d==0) { if((findR(f) mod 2)==0) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". A^"+string(findR(f))+" ["+string(2*((tjurina(f)+2*findR(f)) div 4))+"]:x2+y"+string(((tjurina(f)+2*findR(f)) div 2)+1)+"+xy"+string(((tjurina(f)+2*findR(f)) div 2)-findR(f))+"."); } if((findR(f) mod 2)!=0) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". A^"+string(findR(f))+" ["+string(2*(((tjurina(f)+1)+2*findR(f)) div 4))+"]:x2+y"+string((((tjurina(f)+1)+2*findR(f)) div 2)+1)+"+xy"+string((((tjurina(f)+1)+2*findR(f)) div 2)-findR(f))+"."); } } } } } if(deg(lead(f))==3) { if(jet(f,3)==0) {return("The given function defines not a simple Singularity. The Tjurina number is "+string(tjurina(f))+".")} poly f1=jet(f,3); list L=factorize(f1); if(size(L[1])==4) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D[4]:x2y+xy2."); } if(size(L[1])==3) { poly g=BlowUpO(f); if((tjurina(f)-tjurina(g))==8) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^0["+string((tjurina(f) div 2)+1)+"]:x2y+y"+string(tjurina(f) div 2)+". where m="+string(tjurina(f)/4)+"."); } else { if(whichtru(f)==1) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D["+string(tjurina(f))+"]:x2y+xy"+string(tjurina(f) div 2)+". "); } if(whichtru(f)==0) { if((findRD(f) mod 2)==0) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^"+string(findRD(f))+"["+string(2*((tjurina(f) div 2+findRD(f)) div 2)+1)+"]:x2y+y"+string((tjurina(f) div 2+findRD(f)))+"+xy"+string((tjurina(f) div 2+findRD(f))-findRD(f))+" where even r="+string(findRD(f))+"."); } else { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". D^"+string(findRD(f))+"["+string(2*(((tjurina(f)+1) div 2+findRD(f)) div 2)+1)+"]:x2y+y"+string(((tjurina(f)+1) div 2+findRD(f)))+"+xy"+string(((tjurina(f)+1) div 2+findRD(f))-findRD(f))+",odd r="+string(findRD(f))+"."); } } } } a=leadcoef(f); b=leadcoef(f-lead(f)); f=subst(f,var(1),1/a*(var(1)-a*b*var(2))); I=var(1),var(2)^2; I=std(I^3); if(reduce(f,I)!=0) { if(k==6) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^1[6]:x3+y4+xy3."); } if(k==7) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E[7]:x3+xy3."); } if(k==8) { poly t=BlowUpO(f); if(tjurina(t)==0) { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E^0[6]:x3+y4."); } else { return("The given function defines an isolated Singularity. The Tjurina number is "+string(tjurina(f))+". E[8]:x3+y5."); } } } else {return("The given function defines not a simple singularity. The Tjurina number is "+string(tjurina(f))+".");} } if(deg(lead(f))>3) { return("The given function defines not a simple singularity. The Tjurina number is "+string(tjurina(f))+"."); } } example { "EXAMPLE:"; echo=2; ring R=2,(x,y),Ds; curCeq2(x3+x2y+xy2+y3+xy3+y4); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc whichtru(poly f) //====Gives the information that we do successive blowups and the last singularaty before becoming smmoth has Tjurina //====number 1 if not than returns 0.(returns either a singularaty or smooth surve)============ { int d=tjurina(f); while(1) { f=BlowUpO(f); d=tjurina(f); if(d==1) { return(d); } if(d==0) { return(d); } } return(d); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc findR(poly f) //====Find the number of blowups required by polynomial such that //====difference between two consecutive blowups become 4 //====this procedure find the value of r in case of Ak singularaties as in [1]. { int a, r,b; while(1) { r++; a=tjurina(f); if(a<=1) { return(-1); } f=BlowUpO(f); b=tjurina(f); if((a-b)==4) { return(r-1); } } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc findRD(poly p) //=====Find the number of blowups required by polynomial such //=====that difference between two consecutive blowups become 4 //=====this procedure find the value of r in case of Dk singularaties as in [1]. { int k=tjurina(p); poly q=BlowUpO(p); int t=tjurina(q); int r; if((k mod 4)==0) { r=findR(BlowUpO(p))+2; return(r); } if((k mod 4 !=0)&&(t mod 4==0)) { if(t!=0) { r=findR(BlowUpO(p))+1; return(r); } } if((k mod 2)==0) { r=findR(BlowUpO(p))+2; return(r); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc splitting_SQUA(poly p, int b) { // assumes that p=x_i^2+h, h of order >=3 // returns q(x_1,??,x_n) such that x_i^2 +q is right equivalent to p mod // ^b and x_i is only linear in q def R=basering; int n=nvars(R); ideal M=maxideal(1); int j; map phi; p=jet(p,b); p=simplify(p,1); list T=FindSQUA(p); int i=T[1]; poly q=p/var(i)^2; while(q!=1) { for(j=1;j<=n;j++) { M[j]=var(j)*q; } phi=R,M; p=phi(p); p=p*inverseUnit(q,b); p=jet(p,b); q=p/var(i)^2; } return(p); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc splitting_two2(poly p, int i, int j, int b) { // assumes that p=x_i*x_j+h, no x_i^2, no in h, h of order >=2 // returns q(x_1,??x_i-1,x_i+1,...,x_j-1,x_j+1,...,x_n) such that x_i*x_j +q is right equivalent to p mod // ^b if(b<2){b=2;} def R=basering; poly q=jet((p-var(i)*var(j))/var(i),b); while(q!=0) { p=quickSubst2(p,var(j)-q,j,b); q=jet((p-var(i)*var(j))/var(i),b); } return(simplify(substitute(jet(p,b),var(j),0),1)); //make the leading coefficient 1 } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc quickSubst2(poly h, poly r, int i, int b) { //=== assume h, r is in Q[x_1,...,x_n], computes jet(h(x_i=r),b) h=jet(h,b); r=jet(r,b); matrix M=coef(h,var(i)); poly q = 1; int j,k,d; intvec v; d=deg(M[1,1]); v[d+1]=1; for(k = 2; k <= ncols(M); k++) { v[deg(M[1,k])+1]=1; } h=0; for(k=1;k<=d+1;k++) { if(v[k]==1) { h=h+jet(q*M[2,ncols(M)-j],b); j++; } q=jet(q*r,b); } return(h); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc FindPRO(poly f) { //input the polynomial // output is a list T where T[1]=the first variable which appear as product in the quadraic form. // T[2]=the second variable which appear as product with the var(T[1]) in the quadraic form. def R=basering; int n=nvars(R); int i,j,k; list T; for(i=1;i<=n;i++) { for(k=i+1;k<=n;k++) { for(j=1;j<=size(f);j++) { if(leadmonom(f[j])==var(i)*var(k)) { T[1]=i; T[2]=k; return(T); } } } } return(T); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc FindSQUA(poly f) { //input the polynomial // output is a list T where T[1]=the first variable which appears as a square in the quadraic part of f. // T[2]= the number of squares appearing in the quadraic part of f. def R=basering; int n=nvars(R); int i,j,k; list T; for(i=1;i<=n;i++) { for(j=1;j<=size(f);j++) { if(leadmonom(f[j])==var(i)^2) { k++; T[1]=i; T[2]=k; return(T); } } } return(T); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc findVAR(poly f) { //input: a poly f //output a list L=v,k v an intvec, v[i]=0, if depends on var(i), v[i]=1 else //k is the number of variables occurring in f intvec v; int i,k;int n=nvars(basering); list L; for(i=1;i<=n;i++) { if(f==subst(f,var(i),0)) { v[i]=1; } else { v[i]=0; k++; } } L=v,k; return(L); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc redvar2(poly p) { //input a polynomial depending on x_i_1,...,x_i_k //output a new ring with k variables containing the polynomial def R=basering; int n=nvars(R); list N=findVAR(p); int m=N[2]; intvec v=N[1]; int l; int i; if(n==m) { def S=R; if(defined(h)) { kill h; } poly h; export h; } else { def S=defring("2",m,"u","ds"); setring S; ideal M; for(i=1;i<=n;i++) { if(v[i]==1) { M[i]=0; } else { l++; M[i]=var(l); } } map phi=R,M; poly p=phi(p); export p; setring R; } return(S); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc inverseUnit(poly q,int b) { //input a polynomial q with non-zero constant part //output the inverse of q up to order b as a power series number c=leadcoef(q); q=q/c; int i; poly u=1; poly a=q-1; poly s=-a; for(i=1;i<=b;i++) { u=u+s; s=s*a; } return(u/c); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc splittingLchar2(poly f) { //the quadratic part of the splitting lemma in characteristic 2 //input: poly f //output: a polynomial right equivalent to the input polynomial such that the quadratic part is in normal form poly p=jet(f,2); if(p==0){return(f);} if(!homog(p)){return(jet(f,1));} def R=basering; def S=changeord(list(list("lp",1:nvars(basering)))); setring S; ideal ma=maxideal(1); number a; int c=ringlist(S)[1][1]; poly f=imap(R,f); poly p=imap(R,p); poly h,q; intvec v=leadexp(p); int i,j,k; intvec w; for(k=1;k<=size(v);k++) { if(v[k]!=0){w[size(w)+1]=k;} } i=w[2]; if(size(w)==3){j=w[3];} if(j>0) { a=1/leadcoef(p); ma[j]=a*(var(j)+(p-lead(p))/var(i)); map phi=S,ma; p=phi(p); f=phi(f); q=(p-lead(p))/var(j); ma=maxideal(1); ma[i]=var(i)+q; phi=S,ma; f=phi(f); h=splittingLchar2(f-var(i)*var(j)); if(jet(h,2)==0) { setring R; f=imap(S,f); return(f); } v=leadexp(h); for(k=1;k<=size(v);k++) { if(v[k]!=0){break;} } if(v[k]==2) { ma=maxideal(1); ma[i]=var(j); ma[j]=var(k); ma[k]=var(i); phi=S,ma; h=phi(h); f=h+var(j)*var(k); } else { f=h+var(i)*var(j); } setring R; f=imap(S,f); return(f); } a= leadcoef(p)^(c div 2); ma[i]=1/a*var(i); map phi=S,ma; p=phi(p); f=phi(f); q=p/var(i); if(size(q)==1) { if(p==var(i)^2) { setring R; f=imap(S,f); return(f); } h=splittingLchar2(f-var(i)^2); p=jet(h,2); v=leadexp(p); h=h+var(i)^2; for(k=1;k<=size(v);k++) { if(v[k]!=0){j=k;break;} } if(v[j]==2) { ma=maxideal(1); ma[i]=var(i)+var(j); phi=S,ma; h=phi(h); h=splittingLchar2(h); } setring R; f=imap(S,h); return(f); } else { q=q-lead(q); v=leadexp(q); for(k=1;k<=size(v);k++) { if(v[k]!=0){j=k;break;} } ma=maxideal(1); ma[j]=1/leadcoef(q)*(var(j)+q-lead(q)); phi=S,ma; f=phi(f); ma=maxideal(1); ma[j]=var(i); ma[i]=var(j); phi=S,ma; f=phi(f); p=jet(f,2); if(leadmonom(p)==var(i)^2) { f=phi(f); p=jet(f,2); ma=maxideal(1); ma[i]=p/var(j)-var(j); phi=S,ma; f=phi(f); h=splittingLchar2(f-var(i)^2-var(i)*var(j)-var(j)^2); p=jet(h,2); f=var(i)^2+var(i)*var(j)+var(j)^2+h; if(p!=0) { v=leadexp(p); for(k=1;k<=size(v);k++) { if(v[k]!=0){break;} } if(v[k]==2) { ma=maxideal(1); ma[k]=var(i)+var(k); phi=S,ma; f=phi(f); setring R; f=imap(S,f); return(splittingLchar2(f)); } setring R; f=imap(S,f); return(f); } else //we return (x_i)^2+x_i*x_j+(x_j)^2 since we need a field extension { //to transform it to x_i*x_j setring R; f=imap(S,f); return(f); } } setring R; f=imap(S,f); return(splittingLchar2(f)); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////// /* =============================== Examples for characteristic 2 ========================================== ring r=2,(x,y,z,w,t,v),ds; poly p=xy+zw+t5+v3; classifyCeq(p); map phi=r,v,t,w,z,y,x; poly c=1+x+y+z; poly q=c*p; q=phi(q); q=zw+tv+x3+zw2+zwt+zwv+wtv+t2v+tv2+x3w+x3t+x3v+y5+y5w+y5t+y5v; classifyCeq(q); poly p=ztv+x3+zw2+zwt+zwv+wtv+tv2+tv2+x3w+x3t+x3v+xy3+xy3w+xy3v; classifyCeq(p); poly p=zw+tv+x3+zw2+zwt+wtv+t2v+tv2+x3w+x3t+x3v+y4+y4w+y4t+y4v; classifyCeq(p);//E^0[6] poly p=zw+tv+x3+zw2+zwt+zwv+wtv+t2v+tv2+x3w+x3t+x3v+xy3+y4+xy3w+xy3t+xy3v+y4w+y4t+y4v; classifyCeq(p);//E^1[6] poly p=y2+zw+tv+y2w+y2t+y2v+zw2+zwt+zwv+wtv+t2v+tv2+x11+x11w+x11t+x11v; classifyCeq(p);//A[10] r=0; poly p=zw+tv+xy2+zw2+zwv+zwt+wtv+t2v+tv2+xy2w+xy2t+xy2v+x14y+x14yw+x14yt+x14yv+x26+x26w+x26t+x26v; classifyCeq(p); ring r=2,(x,y,z,t,w,u,v),Ds; ideal I=z+t,x+t+w,v,y,u,t,w+z; det(jacob(I)); map phi=r,I; poly a=1+x+u+v; poly p=xy+zt+wu+v19; poly q=a*p; poly j=phi(q); classifyCeq(j); classifyCeq(p); poly p=x2+yz+tw+u3+v2x; classifyCeq(p); poly q=a*p; poly j=phi(q); classifyCeq(j); poly p=xy+zw+t2+u2v+v19u; classifyCeq(p); poly q=a*p; poly j=phi(q); classifyCeq(j); poly p=xy+zw+t2+u2v+v5t+uvt; classifyCeq(p); poly q=a*p; poly j=phi(q); classifyCeq(j); poly p=xy+zw+t2+u2v+v5u+uvt; classifyCeq(p); poly q=a*p; poly j=phi(q); classifyCeq(j); ring r=2,(x,y,z,t,w,u,v,e),Ds; ideal I=x+y+z+t+w,y+z+t+w,e,v,u,t,w,z; map si=r,I; poly p=xy+zt+wu+v2+e81; poly j=si(p); classifyCeq(j); poly p=xy+zt+wu+v2+e81+e^(80-12)*v; classifyCeq(p); poly j=si(p); classifyCeq(j); poly p=xy+zt+wu+v2e+e60+e31v; classifyCeq(p); poly p=xy+zt+wu+v2e+e60+e59v; poly j=si(p); classifyCeq(j); =============================== Examples for characteristic > 2 ======================================== ring R=3,(x,y,z,u,v,w,s,t),ds; ideal M=maxideal(1); M[3]=x-y+z+u+w-s+t; poly f=u3+v4+u2v2+x2+y2+z2+s2+t2+w2; classifyCeq(f); map phi=R,M; f=phi(f); classifyCeq(f); f=u2+y32+s2+t2+v2+x2+z2+w2; classifyCeq(f); map phi=R,M; f=phi(f); classifyCeq(f); f=v2w+w61+x2+y2+z2+t2+z2+s2+u2; classifyCeq(f); f=phi(f); classifyCeq(f); f=u2+v2+w2+s2+t2-x2y+xy2+z6+y11+xy11+x14+z53; // f is of corank=3 classifyCeq(f); f=x3+y4+xy5+s2+t2; classifyCeq(f); f=u3+v5+u2v2+x2+y2+z2+t2+s2+w2; classifyCeq(f); ideal M=maxideal(1); M[2]=x+y+2s+t; map phi=R,M; f=phi(f); classifyCeq(f); ring R=3,(u,v,w,s,t),ds; poly f=w2s+s21+u2+v2+t2; classifyCeq(f); ideal M=maxideal(1); M[3]=u+2v+w+2t+2s; map phi=R,M; f=phi(f); classifyCeq(f); ring R=5,(x,y,z,u,v,w,s,t),dp; poly f=v2w+w61+x2+y2+z2+t2+z2+s2+u2; classifyCeq(f); */ singular-4.0.3+ds/Singular/LIB/classifyci.lib000066400000000000000000000636321266270727000210020ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////////// version=="version classifyci.lib 4.0.0.0 Jun_2013 "; // $Id: 3490b4512206c608167dc0874d4c2066225031b8 $ category="Singularities"; info=" LIBRARY: classifyci.lib Isolated complete intersection singularities in characteristic 0 AUTHORS: Gerhard Pfister pfister@mathematik.uni-kl.de Deeba Afzal deebafzal@gmail.com OVERVIEW: A library for classifying isolated complete intersection singularities for the base field of characteristic 0 and for computing weierstrass semigroup of the space curve.Isolated complete intersection singularities were classified by M.Giusti [1] for the base field of characteristic 0. Algorithm for the semigroup of a space curve singularity is given in [2]. REFERENCES: [1] Giusti,M:Classification des singularities isolees simples d'intersections completes, C,R.Acad.Sci.Paris Ser.A-B 284(1977),167-169. [2] Castellanos,A.,Castellanos,J.,2005:Algorithm for the semigroup of a space curve singularity. Semigroup Forum 70,44-66. PROCEDURES: classifyicis(I); Isolated simple complete intersection singularities for the base field of charateristic 0 Semigroup(I); Weierstrass semigroup of the space curve given by equations "; LIB "classify.lib"; LIB "classify_aeq.lib"; LIB "poly.lib"; LIB "curvepar.lib"; LIB "algebra.lib"; //////////////////////////////////////////////////////////////////////////////// proc classifyicis(ideal I) "USAGE: classifyicis(I); I ideal ASSUME: I is given by two generators PURPOSE:Check whether the ideal defines a complete intersection singularity or not RETURN: String type in the classification of Giusti,M @* or The given singularity is not simple EXAMPLE: example classifyicis; shows an example " { def R=basering; def SS=changeord(list(list("ds",nvars(R))),R); setring SS; ideal I=imap(R,I); string re; if(char(basering)==0) { re=ICIS12(I); } if(char(basering)!=0) { re="The characteristic of basering should be 0"; } setring R; return(re); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y,z),ds; ideal I=x2+yz,xy+z4; classifyicis(I); } //////////////////////////////////////////////////////////////////////////////// static proc ICIS12(ideal I) { int n=nvars(basering); if(n==2) { return(zerodim_ICIS(I)); } if(n==3) { return(onedim_ICIS(I)); } if(n>=4) { return("The given singularity is not simple"); } } //////////////////////////////////////////////////////////////////////////////// static proc zerodim_ICIS(ideal I) "USAGE: zerodim_ICIS(l); I is an ideal ASSUME: I is given by two generators PURPOSE: Check whether the ideal defines a complete intersection singularity of dimension zero or not RETURN: String type in the classification of Giusti,M, of the 0-dimensional complete inetersection @* or The given singularity is not simple EXAMPLE: example zerodim_ICIS; shows an example " { def R=basering; poly g,h,r; ideal J; int a,b,c,d; map phi; list L; string re; // g=g[0]+g[1] where ord(g[1])>=3 ,g[0] can be zero // h=h[0]+h[1] where ord(h[1])>=3 ,h[0] can be zero d=vdim(std(I)); if(d==-1) { return("The given singularity is not simple"); } a=ord(I[1]); b=ord(I[2]); if((a>=3)&&(b>=3)) { //start case1 return("The given singularity is not simple"); } // end case 1 if((a==2&&b>=3)||(a>=3&&b==2)) // start case 2 { if(a==2) { g=I[1]; h=I[2]; } if(b==2) { g=I[2]; h=I[1]; } L=factorize(jet(g,2)); if(size(L[1])==3) { re=findwhichF(g,h,L); return(re); } // end size(L[1]=3) if((size(L[1])==2)&&(L[2][2]==2)) { // start (size(L[1])==2)&&(L[2][2]==2) // case (x2,h); r=L[1][2]; if(size(r)==2) // ax+by goes to x { matrix M3=coef(r,var(1)); M3=subst(M3,var(2),1); matrix A[2][2]=M3[2,1],M3[2,2],0,1; matrix B=inverse(A); phi=R,B[1,1]*var(1)+B[1,2]*var(2),B[2,1]*var(1)+B[2,2]*var(2); g=phi(g); h=phi(h); J=(g,h); } // end size(r)=2 if(size(r)==1) // jet(g,2)=ax2 or by2 goes to x2 { if(leadmonom(r)==var(1)) { phi=R,var(1)/leadcoef(r),var(2); g=phi(g); h=phi(h); } if(leadmonom(r)==var(2)) { phi=R,var(2)/leadcoef(r),var(1); g=phi(g); h=phi(h); } J=(g,h); } // end size(r)=1 c=milnor(g); if((d>=7)&&(c==2)) { //"I-series"; if(d mod(2)==0) { return("I_"+string(d-1)+":(x2+y3,y"+string(d div 2)+")"); } if(d mod(2)!=0) { return("I_"+string(d-1)+":(x2+y3,xy"+string((d-3) div 2)+")"); } } if(d==6) { return("G_5:(x2,y3)"); } ring R1=0,(var(2),var(1)),ds; setring R1; ideal J=imap(R,J); poly h1=reduce(J[2],std(J[1]),d); poly h2=leadmonom(h1); int ss=deg(h2)-1; if((h2==var(1)^4)&&((c>=3)||(c==-1))) { setring R; return("G_7:(x2,y4)"); } if((h2==var(2)*var(1)^2)&&((c>=3)||(c==-1))) { setring R; return("H_"+string(d-1)+":(x2+y"+string(d-4)+",xy2)"); } setring R; return("The given singularity is not simple"); } // end (size(L[1])==2)&&(L[2][2]==2) if((size(L[1])==2)&&(L[2][2]==1)) { def S=factorExt(g); setring S; poly h=imap(R,h); // poly g=imap(R,g); we need not S has already g re= findwhichF(g,h,L); setring R; return(re); } } // end case 2 if((a==2)&&(b==2)) // start case 3 { g=I[1]; h=I[2]; poly Q=testDiv(jet(h,2),jet(g,2)); if(Q!=0) { I=(g,h-Q*g); return(zerodim_ICIS(I)); } if(Q==0) { L=factorize(jet(g,2)); if(size(L[1])==3) { re=findwhichF(g,h,L); return(re); } if((size(L[1])==2)&&(L[2][2]==1)) { def S=factorExt(g); setring S; poly h=imap(R,h); re=findwhichF(g,h,L); setring R; return(re); } L=factorize(jet(h,2)); if(size(L[1])==3) { re=findwhichF(h,g,L); return(re); } if((size(L[1])==2)&&(L[2][2]==1)) { def S=factorExt(h); setring S; poly g=imap(R,g); re=findwhichF(h,g,L); setring R; return(re); } else { // there exist a s.t g[0]+ah[0] has two different factors. int e=Finda(g,h); I=(g+e*h,h); re=zerodim_ICIS(I); return(re); } } } // end case 3 } // proc example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; ideal I=x2+8xy+16y2+y3,xy7+4y8; zerodim_ICIS(I); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc Finda(poly g,poly h) "USAGE: Finda(g,h); g,h are polynomials PURPOSE: Find a such that jet(g,2)+a*jet(h,2) has two different factors RETURN: integer a { // find a s.t jet(g,2)+a*jet(h,2) has two different factors. int o; list L=factorize(jet(h,2)); if(L[2][2]==1){return(0);} poly r= jet(g,2); list T=factorize(r); while(T[2][2]!=1) { o++; r= r+jet(h,2); T=factorize(r); } return(o); } /* ring R=0,(x,y),ds; poly g=x2+xy3; poly h=y2+x3+y7; finda(g,h); */ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc testDiv(poly f,poly g) "USAGE: testDiv(f,g); f,g are polynomials ASSUME: I is given by two generators PURPOSE: Check whether f divides g or not. RETURN: poly h(quotient) if f divides g @* 0 if f does not divide g { poly h=f/g; if(f-h*g==0) { return(h); } return(0); } /* ring R=0,(x,y,ds; poly f=x2+y2; poly g=3x2+3y2 testDiv(f,g); */ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static proc findwhichF(poly g,poly h,list L) "USAGE: findwhichF(g,h,L); g,h are polynomials,L list of factors of jet(g,2) RETURN: string type F^n,p_n+p-1 in the classification of Giusti,M { // return("F^n,p_n+p-1") def R=basering; matrix M,N; ideal J; map si; list T; string rem; // in each case we want to transform jet(g,2) which has two factors to xy // and then find std and know about the type of "F^n,p_n+p-1" if((size(L[1][2])==2)&&(size(L[1][3])==2)) { M=coef(L[1][2],var(1)); N=coef(L[1][3],var(1)); matrix A[2][2]=M[2,1],M[2,2],N[2,1],N[2,2]; A=subst(A,var(1),1,var(2),1); matrix B=inverse(A); si=R,B[1,1]*var(1)+B[1,2]*var(2),B[2,1]*var(1)+B[2,2]*var(2); g=si(g); h=si(h); J=(g,h); J=std(J); // if g and h both of order 2 no problem in that case because deg(J[2])=2 so lead(J[2])=x2,y2,xy does not matter T[1]=deg(lead(J[2])); T[2]=deg(lead(J[3]))-1; rem="F^"+string(T[1])+","+string(T[2])+"_"+string(T[1]+T[2]-1)+":(xy,x"+string(T[1])+"+y"+string(T[2])+")"; return(rem); } if((size(L[1][2])==2)&&(size(L[1][3])==1)) { // two cases 1- jet(g,2)=(ax+by)*cx, 2- jet(g,2)=(ax+by)*cy if(leadmonom(L[1][3])==var(1)) { M=coef(L[1][2],var(1)); M=subst(M,var(2),1); si=R,var(1),-M[2,1]/M[2,2]*var(1)+var(2); g=si(g); h=si(h); J=(g,h); J=std(J); T[1]=deg(lead(J[2])); T[2]=deg(lead(J[3]))-1; rem="F^"+string(T[1])+","+string(T[2])+"_"+string(T[1]+T[2]-1)+":(xy,x"+string(T[1])+"+y"+string(T[2])+")"; return(rem); } if(leadmonom(L[1][3])==var(2)) { M=coef(L[1][2],var(1)); M=subst(M,var(2),1); matrix A[2][2]=M[2,1],M[2,2],0,1; matrix B=inverse(A); si=R,B[1,1]*var(1)+B[1,2]*var(2),B[2,1]*var(1)+B[2,2]*var(2); g=si(g); h=si(h); J=(g,h); J=std(J); T[1]=deg(lead(J[2])); T[2]=deg(lead(J[3]))-1; rem="F^"+string(T[1])+","+string(T[2])+"_"+string(T[1]+T[2]-1)+":(xy,x"+string(T[1])+"+y"+string(T[2])+")"; return(rem); } } else { J=(g,h); J=std(J); T[1]=deg(lead(J[2])); T[2]=deg(lead(J[3]))-1; rem="F^"+string(T[1])+","+string(T[2])+"_"+string(T[1]+T[2]-1)+":(xy,x"+string(T[1])+"+y"+string(T[2])+")"; return(rem); } } /* ring R=0,(x,y),ds; poly g=xy+y2+y4; poly h=x4+4x3y+6x2y2+4xy3+y4+y7+xy7; L=factorize(jet(g,2),2); findwhichF(g,h,L); */ //////////////////////////////////////////////////////////////////////////////// static proc factorExt(poly g) "USAGE: procExt(g); jet(g,2) is an irreducible polynomial PURPOSE: Find the field extension in which jet(g,2) has two different factors RETURN: ring S in which jet(g,2) has factors { def R=basering; g=simplify(g,1); poly f=jet(g,2); list L=factorize(f); if(L[2][2]==1) { ring S=(0,t),(var(1),var(2)),ds; poly f=fetch(R,f); poly g=fetch(R,g); minpoly=t2+leadcoef(f/(var(1)*var(2)))*t+leadcoef(f/var(2)^2); list L=factorize(f); export L; export g; } else { def S=R; export L; } setring R; return(S); } /* ring R=0,(x,y),ds; poly g=x2=y2+x4+xy11; factorExt(g); */ //////////////////////////////////////////////////////////////////////////////// static proc onedim_ICIS(ideal I) "USAGE: onedim_ICIS(l); I is an ideal ASSUME: I is given by two generators PURPOSE: Check whether the ideal defines a complete intersection singularity of dimension 1 or not RETURN: String type in the classification of Giusti,M, of 1-dimesnional complete inetersection singualrity @* or The given singularity is not simple EXAMPLE: example onedim_ICIS; shows an example " { int m,t,r; poly g1,g2,f1,f2; string rem; list A,B; f1=I[1]; f2=I[2]; // I=nf_icis(I); m=genericmilnor(I); t=tjurina(I); if(m==-1) { return("The given singularity is not simple"); } if(m!=t) // in ICIS milnor=tjurina { return("The given singularity is not simple"); } g1=jet(f1,2); g2=jet(f2,2); if((ord(g1)==1)||(ord(g2)==1)){return(arnoldsimple(I,m));} if(g1==0) { return("The given singularity is not simple"); } if(g2==0) { return("The given singularity is not simple"); } rem=typejet2(g1,g2); if(rem=="type1") { return("S_5:(x2+y2+z2,yz)"); } if(rem=="type2") { return("S_"+string(m)+":(x2+y2+z"+string(m-3)+",yz)"); } if(rem=="type3") { if(m==7) { return("T_7:(x2+y3+z3,yz)"); } if(m==8) { return("T_8:(x2+y3+z4,yz)"); } if(m==9) { B=Semigroup(I); B=changeType(B); A=list(list(2,5),list(2,3)); if(compLL(A,B)) { return("T_9:(x2+y3+z5,yz)"); } } return("The given singularity is not simple"); } if(rem=="type4") { if(m==7) { return("U_7:(x2+yz,xy+z3)"); } if(m==8) { return("U_8:(x2+yz+z3,xy)"); } if(m==9) { return("U_9:(x2+yz,xy+z4)"); } return("The given singularity is not simple"); } if(rem=="type5") { if(m==8) { return("W_8:(x2+z3,y2+xz)"); } if(m==9) { return("W_9:(x2+yz2,y2+xz)"); } return("The given singularity is not simple"); } if(rem=="type6") { if(m==9) { return("Z_9:(x2+z3,y2+z3)"); } if(m==10) { return("Z_10:(x2+yz2,y2+z3)"); } return("The given singularity is not simple"); } if(rem=="not simple") { return("The given singularity is not simple"); } } example { "EXAMPLE:"; echo=2; ring R=0,(x,y,z),ds; ideal I=x2+8xy+16y2+2xz+8yz+z2+yz2+9z3,y2+xz+22yz+82z2; onedim_ICIS(I); } //////////////////////////////////////////////////////////////////////////////// static proc arnoldsimple(ideal I,int m) "USAGE: arnoldsimple(I,m); I is an ideal, m is an integer greater or equal to milnor number of the ideal I ASSUME: I is given by two generators and one of the generator of the ideal I is of order 1 PURPOSE: check whether the ideal defines a hypersurface simple complete intersection singularity or not RETURN: string type in the classification of Arnold, @* or The given singularity is not simple EXAMPLE: example arnoldsimple; shows an example " { //if one generator is of order 1 we reduce case to hypersurface case def R=basering; if(ord(I[1])==1) { poly g=specialNF(I[2],I[1],m); ring S=0,(var(2),var(3)),ds; setring S; poly g=imap(R,g); string dd=complexSingType(g); int e=modality(g); setring R; if(e==0) { return(dd); } if(e!=0) { return( "The given singularity is not simple"); } } if(ord(I[2])==1) { I=I[2],I[1]; return(arnoldsimple(I,m)); } } example { "EXAMPLE:"; echo=2; ring R=0,(x,y,z),ds; ideal I=x+y2,y3+z4+xy11; arnoldsimple(I,6); } //////////////////////////////////////////////////////////////////////////////// static proc specialNF(poly g,poly f,int m) "USAGE: specialNF(g,f); g,f are polynomials, m is an integer greater or equal to milnor number of the ideal I=(g,h) ASSUME: f is of order 1 and f=x+higher RETURN: poly g not involving x (Using implicit fn thm) { poly k; list T=linearpart(g,f); f=T[1]; g=T[2]; poly h=var(1)-f; while(1) { g=subst(g,var(1),h); k=jet(g,m); if(diff(k,var(1))==0) { break; } } return(k); } /* ring R=0,(x,y,z),ds; poly f=x+y2; poly g=y3+z4+xy11; speciaNF(g,f,6); */ //////////////////////////////////////////////////////////////////////////////// static proc linearpart(poly g,poly f) // f=linear part+higher,g output list T,T[1]=x+higher term,T[2]=g "USAGE: specialNF(g,f); g,f are polynomials ASSUME: f=lineat part+higher that is f is of order 1 RETURN: list T, T[1]=x+higher and T[2]=g' { def R=basering; poly i,j,k; list T; i=diff(jet(f,1),var(1)); j=diff(jet(f,1),var(2)); k=diff(jet(f,1),var(3)); if(i!=0) { ideal M=maxideal(1); M[1]=(var(1)-((j*var(2)+k*var(3))/leadcoef(f)))/leadcoef(f); map phi=R,M; f=phi(f); g=phi(g); } if(i==0) { if(j!=0) { map phi=R,var(2),var(1),var(3); f=phi(f); g=phi(g); return(linearpart(g,f)); } if(k!=0) { map phi=R,var(3),var(2),var(1); f=phi(f); g=phi(g); return(linearpart(g,f)); } } T[1]=f; T[2]=g; return(T); } /* ring R=0,(x,y,z),ds; poly f=x+2y+y2; poly g=y3+z4+zy11; lineatpart(g,f); */ //////////////////////////////////////////////////////////////////////////////// static proc typejet2(poly g1,poly g2) "USAGE: typejet2(g1,g2); g1,g2 are polynomials ASSUME: g1,g2 are homogenous polynomials of degree 2 PURPOSE: Check whether (g1,g2) is a quadratic form in the list of Guisti or not RETURN: string type for the quadratic forms appearing in Guist's list @* or not simple { def R=basering; ideal I=(g1,g2); def S=absPrimdecGTZ(I); setring S; list L,T; int e,i,j; intvec a,a1; L=primary_decomp; for(j=1;j<=size(L);j++) { if(dim(std(L[j][1]))!=2) { return("not simple"); } } T=absolute_primes; for(i=1;i<=size(T);i++) { e=e+T[i][2]; } if(e==4) { setring R; return("type1"); } if(e==3) { setring R; return("type2"); } if(e==2) { ideal J=std(L[1][1]); ideal J1=std(L[2][1]); a=hilbPoly(J); a1=hilbPoly(J1); if((a[2]==2)&&(a1[2]==2)) { setring R; return("type3"); } if(((a[2]==3)&&(a1[2]==1))||((a[2]==1)&&(a1[2]==3))) //||(a[2]==1)&&(a1[2]==3)) { setring R; return("type4"); } } if(e==1) { setring R; // I lies in R and zero in S1 ideal JJ=radical(I); JJ=JJ^3; ideal JJJ=reduce(JJ,std(I)); if(size(JJJ)==0) { return("type6"); } if(size(JJJ)!=0) { return("type5"); } } setring R; return("not simple"); } /* ring R=0,(x,y,z),ds; poly g1=x2+yz; poly g2=xy; typejet2(g1,g2); */ //////////////////////////////////////////////////////////////////////////////// static proc compL(list L,list M) { int l,m,i,j; l=size(L); m=size(M); if(l!=m) {return(0);} for(i=1;i<=m;i++) { if(L[i]!=M[i]) {return(0);} } return(1); } //////////////////////////////////////////////////////////////////////////////// static proc compLL(list L,list M) "USAGE: compLL(L,M); L, M are lists PURPOSE: Check whether the lists are equal or not RETURN: 1 if both lists are equal upto a permutation @* 0 if both are not equal { int l,m,i,j,s; l=size(L); m=size(M); if(l!=m) {return(0);} for(i=1;i<=m;i++) { for(j=1;j<=m;j++) { if(compL(L[i],M[j])) { s++; break; } } } if(s==m) {return(1);} if(s!=m) { return(0); } } /* ring R=0,(x,y,z),ds; list L=(1),(2,3),(2,5); list T=(2,3),(1),(2,5); compLL(L,T); */ //////////////////////////////////////////////////////////////////////////////// static proc changeType(list L) "USAGE: changeType(L); L is a list of intvectors PURPOSE: Change the list of intvectors to the list of lists RETURN: List of lists { int i,j; list T; for(i=1;i<=size(L);i++) { list S; for(j=1;j<=size(L[i]);j++) { S[j]=L[i][j]; } T[size(T)+1]=S; kill S; } return(T); } /* ring R=0,(x,y,z),ds; list B=(4,6,7); changeType(B); */ //////////////////////////////////////////////////////////////////////////////// static proc genericmilnor(ideal I) "USAGE: genericmilnor(l); I is an ideal PURPOSE: Computes the milnor number of generic linear combination of the ideal I RETURN: Milnor number of I if it is finite @* or -1 if it is not finite { int m=milnor(I); int i,a,b; if(m>=0) { return(m); } def R=basering; def R1=changechar(32003,R); setring R1; ideal I; while(i<10) { i++; a=random(-100,100); b=random(-100,100); while(a==0) { a=random(-100,100); } while(b==0) { b=random(-100,100); } I=imap(R,I); I[1]=a*I[1]+b*I[2]; m=milnor(I); if(m>=0) { setring R; return(m); } } setring R; return(-1); } /* ring R=0,(x,y,z),ds; ideal I=x2+z3,y2+z3; genericmilnor(I); */ //////////////////////////////////////////////////////////////////////////////// proc Semigroup(ideal I) "USAGE: Semigroup(l); I is an ideal PURPOSE: Computes the semigroup of the ideal I corresponding to each branch RETURN: list of semigroup of ideal I corresponding to each branch EXAMPLE: Semigroup; shows an example " { list L=facstd(I); list RE,JE,PE; if(size(L)==1) { RE=CurveRes(L[1]); RE=semi_group(RE); return(RE); } ideal J,K; list T,T1,T2,T3,T4,T5,H; int i,j,l; for(i=1;i<=size(L);i++) { RE=CurveRes(radical(L[i])) ; T1[i]=semi_group(RE); for(j=i+1;j<=size(L);j++) { JE=CurveRes(radical(L[j])); T2[j]=semi_group(JE); J=L[i]+L[j]; if(dim(std(J))!=1) { break; } K=slocus(J); if(K[1]==1) { T3=1;} else { PE=CurveRes(radical(J)); T3=semi_group(PE); } T4=commonpartlists(T1[i],T3); T5=commonpartlists(T2[j],T3); if(compLL(T4,T5)) { T1[i]=del(T1[i],T4); } } for(l=1;l<=size(T1[i]);l++) { H[size(H)+1]=T1[i][l]; } } return(H); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y,z),ds; ideal I=x2+y3+z5,yz; Semigroup(I); } //////////////////////////////////////////////////////////////////////////////// static proc del(list L,list M) "USAGE: del(L,M); L and M are two lists PURPOSE: Delete common part of list M from List L RETURN: list L { int i,j; for(i=1;i<=size(M);i++) { for(j=1;j<=size(L);j++) { if(compL(L[j],M[i])) {L=delete(L,j);} } } return(L); } //////////////////////////////////////////////////////////////////////////////// static proc commonpartlists(list L,list M) "USAGE: commonpart(L,M); L and M are two lists PURPOSE: Computes the intersetion of two list RETURN: list T { list T; int i,m,l,j,k; m=size(M); l=size(L); if(l>=m) { for(i=1;i<=m;i++) { for(j=1;j<=l;j++) { if(compLL(M[i],L[j])) { T[k+1]=M[i]; k++; } } } } return(T); } //////////////////////////////////////////////////////////////////////////////// static proc semi_group(list H) "USAGE: semi_group(H); H list COMPUTE:Weierstrass semigroup of space curve C,which is given by an ideal RETURN: list A , which gives generators set of the Weierstrass semigroup corresponding to each irreducible component of C { int i,d,u,v,w,k; int j=1; int e=1; def R=basering; list A; string mpo; list LL; for(k=1;k<=size(H);k++) { LL=CurveParam(H[k]); def S=LL[1]; setring S; list TT; for(i=1;i<=size(Param);i++) { d=deg(Param[i][2]); TT=Param[i]; mpo=string(Param[i][2]); ring S1=(0,a),(t),ds; setring S1; execute("minpoly="+mpo+";"); list TT=imap(S,TT); list T; ideal J1; for(u=1;u<=size(TT[1]);u++) { J1[u]=TT[1][u]; } J1=simplify(J1,2); J1=sagbiAlg(J1); w=Classify_aeq::ConductorBound(J1); J1=lead(J1); list TTT; for(v=1;v<=size(J1);v++) { TTT[v]=J1[v]; } for(j=1;j<=d;j++) { T=WSemigroup(TTT,w); A[e]=T[1]; // intersted only in semigroup e++; } setring S; kill S1; kill T; } setring R; kill S; } return(A); } //==============================Examples====================================== /* //=========Examples of Isolated simple complete intersection singularities====== ring R=0,(x,y),ds; ideal M=maxideal(1); //====================== ideal I=x2+y3,xy11; M[1]=x; M[2]=x+3y+xy; map phi=R,M; I=phi(I); classifyicis(I); //====================== ideal I=xy,x5+y4; M[1]=x+4y; M[2]=y; map phi=R,M; I=phi(I); classifyicis(I); //====================== ideal I=x2,y4; M[1]=x+xy2; M[2]=x+y+x2+y2; map phi=R,M; I=phi(I); classifyicis(I) //=========================================== ideal I=x2+y11,x2y3+xy4; classifyicis(I); //====================== ring S=0,(u,v),dp; ideal N=maxideal(1); //====================== ideal J=u2+v7,uv2; N[1]=u+3v+uv+u3v; N[2]=v; map si=S,N; J=si(J); classifyicis(J); //====================== ideal J=u2+v2+uv5+v11,uv4+v5; classifyicis(I); //=========================================== ring R=0,(x,y,z),ds; ideal M=maxideal(1); //====================== ideal I=x2+y3+z5,yz; classifyicis(I); //====================== ideal I=x2+z3,y2+z3; classificis(I); //====================== ideal I=x2+yz+z3,xy; M[3]=x+4y+3z+x2y; map phi=R,M; I=phi(I); classifyicis(I); //====================== ideal I=x2+y3+z6,yz+xy3; classifyicis(I); //============================================ ideal I=x2+z3,y2+xz; M[2]=x+3y; map phi=R,M; I=phi(I); classifyicis(I); //============================================ ring S=0,(u,v,w),ds; ideal M=maxideal(1); ideal I=u2+vw+w3,uv; M[1]=u+3v+3vw+w2; map phi=S,M; I=phi(I); classifyicis(I); //==========Examples of Semigroup of the space curves==================== ring R=0,(x,y,z),ds; ideal I=xy+z3,xz+z2y2+y6; Semigroup(I); //====================== ideal I=xy,xz+z3+z2y3+y11; Semigroup(I); //====================== ideal I=xy+z4,xz+y6+yz2; Semigroup(I); //====================== ideal I=xy+z2,x2+z2y+5y4; Semigroup(I); //====================== ideal I=x2+yz2,y2+z3; Semigroup(I); //====================== ideal I=x2+yz,xy+z4; Semigroup(I); //====================== ideal I=xy,xz+z3+z2y5+2y15; Semigroup(I); //====================== ideal I=xy,xz+z3+zy9; Semigroup(I); //====================== */ singular-4.0.3+ds/Singular/LIB/compregb.lib000066400000000000000000000126171266270727000204440ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version compregb.lib 4.0.0.0 Jun_2013 "; // $Id: 95e4c7dacb9b13daa2efb154f66ace0d4fef37dc $ category="General purpose"; info=" LIBRARY: compregb.lib experimental implementation for comprehensive Groebner systems AUTHOR: Akira Suzuki (http://kurt.scitec.kobe-u.ac.jp/~sakira/CGBusingGB/) () OVERVIEW: see \"A Simple Algorithm to compute Comprehensive Groebner Bases using Groebner Bases\" by Akira Suzuki and Yosuke Sato for details. PROCEDURES: cgs(polys,vars,pars,R1,R2); comprehensive Groebner systems base2str(G); pretty print of the result G KEYWORDS: comprehensive Groebner system "; /////////////////////////////////////////////////////////////////////////////// // global variables are the followings: // Parameters, Variables, VMinDPoly, // RingAll, RingVar; /////////////////////////////////////////////////////////////////////////////// static proc setup_special_dpolys() { poly VMinDPoly = Variables[size(Variables)]; export(VMinDPoly); } static proc newcasebasis(poly Case, ideal Basis) { list CB = Case, Basis; return(CB); } static proc contains(poly Vari, list Varis) { int l = size(Varis); for (int i = 1; i <= l; i ++) { if (Vari == Varis[i]) { return(1); } } return(0); } static proc polys_heads(list PolyL) { int i, j; int length = size(PolyL); if (!length) { return(PolyL); } setring(RingVar); list PolyL = imap(RingAll, PolyL); list HCoefs = list(); length = size(PolyL); for (i = 1; i <= length; i ++) { HCoefs = insert(HCoefs, leadcoef(PolyL[i])); } setring(RingAll); list HCoefs = imap(RingVar, HCoefs); list CoefL; ideal CoefLsub; poly Coef; for (i = 1; i <= length; i ++) { Coef = HCoefs[i]; if (typeof(Coef) == "poly") { CoefLsub = factorize(Coef, 1); for (j = 1; j <= size(CoefLsub); j ++) { if (CoefLsub[j] > 1) { CoefL = insert(CoefL, CoefLsub[j]); } } } } for (i = 1; i <= size(CoefL); i ++) { Coef = CoefL[i]; for (j = i + 1; j <= size(CoefL); j ++) { if (Coef == CoefL[j]) { CoefL = delete(CoefL, j); j --; } } } return(CoefL); } static proc polys_restrict_v(ideal Polys) { return(polys_separate_v_p(Polys)[0]); } static proc polys_restrict_p(ideal Polys) { return(polys_separate_v_p(Polys)[1]); } static proc polys_separate_v_p(ideal Polys) { list R_v, R_p; poly P; int length = size(Polys); for (int i = 1; i <= length; i ++) { P = Polys[i]; if (P < VMinDPoly) { R_p = insert(R_p, P); } else { R_v = insert(R_v, P); } } return(R_v, R_p); } static proc cgs_main(ideal Polys) { ideal F; list FP, FV, HFact, Bases; poly H; int i; // F = groebner(Polys); F = slimgb(Polys); if (F[1] == 1) { return(list()); } FV, FP = polys_separate_v_p(F); HFact = polys_heads(FV); int HFL = size(HFact); H = 1; for (i = 1; i <= HFL; i ++) { H = H * HFact[i]; } Bases = insert(Bases, list(H, F)); for (i = 1; i <= HFL; i ++) { // print("paras:" + string(FP)); // print("ideal:" + string(HFact[i])); Bases = cgs_main(F + ideal(HFact[i])) + Bases; } return(Bases); } proc cgs(ideal Polys, list Vars, list Paras,def RingVar,def RingAll) "USAGE: cgs(Polys,Vars,Paras,RingVar,RingAll); Polys an ideal, Vars, the list of variables, Paras the list of parameters, RingVar the ring with Paras as parameters, RingAll the ring with Paras as variables (RingAll should be the current ring) RETURN: a list L of lists L[i] of a polynomial and an ideal: L[i][1] the polynomial giving the condition on the parameters L[i][2] the Groebner basis for this case EXAMPLE: example cgs; shows an example " { option(redSB); list Parameters = Paras; list Variables = Vars; poly VMinDPoly = Vars[size(Vars)]; export(Parameters, Variables, VMinDPoly); export(RingVar, RingAll); setring(RingAll); list G = cgs_main(Polys); keepring(RingAll); return(G); } example { "EXAMPLE:";echo=2; ring RingVar=(0,a,b),(x,y,t),lp; ring RingAll=0,(x,y,t,a,b),(lp(3),dp); ideal polys=x^3-a,y^4-b,x+y-t; list vars=x,y,t; list paras=a,b; list G = cgs(polys,vars,paras,RingVar,RingAll); G; } proc basis2str(list B) { string Str; ideal Factors; int i; Str = "("; Factors = factorize(B[1], 1); for (i = 1; i <= size(Factors); i ++) { Str = Str + "(" + string(Factors[i]) + ")"; } Str = Str + "!=0,"; list FV, FP; FV, FP = polys_separate_v_p(B[2]); for (i = 1; i <= size(FP); i ++) { Str = Str + string(FP[i]) + "=0,"; } if (size(Str) > 1) { Str = Str[1, size(Str) - 1] + ")["; } else { Str = "()["; } if (size(FV)) { for (i = 1; i <= size(FV); i ++) { Str = Str + string(FV[i]) + ","; } Str = Str[1, size(Str) - 1] + "]"; } else { Str += "]"; } return(Str); } proc bases2str(list Bases) { string Str; int i; Str = ""; for (i = 1; i <= size(Bases); i ++) { Str = Str + basis2str(Bases[i]) + newline; } return(Str); } /* ring RingVar=(0,a,b),(x,y,t),lp; ring RingAll=0,(x,y,t,a,b),(lp(3),dp); ideal polys=x^3-a,y^4-b,x+y-t; list vars=x,y,t; list paras=a,b; list G = cgs(polys,vars,paras,RingVar,RingAll); bases2str(G); */ singular-4.0.3+ds/Singular/LIB/control.lib000066400000000000000000001272731266270727000203330ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////// version="version control.lib 4.0.0.0 Jun_2013 "; // $Id: 018a6cff8b41a26f7eb46724ad9d483956bfb9aa $ category="System and Control Theory"; info=" LIBRARY: control.lib Algebraic analysis tools for System and Control Theory AUTHORS: Oleksandr Iena, yena@mathematik.uni-kl.de @* Markus Becker, mbecker@mathematik.uni-kl.de @* Viktor Levandovskyy, levandov@mathematik.uni-kl.de SUPPORT: Forschungsschwerpunkt 'Mathematik und Praxis' (Project of Dr. E. Zerz and V. Levandovskyy), University of Kaiserslautern PROCEDURES: control(R); analysis of controllability-related properties of R (using Ext modules) controlDim(R); analysis of controllability-related properties of R (using dimension) autonom(R); analysis of autonomy-related properties of R (using Ext modules) autonomDim(R); analysis of autonomy-related properties of R (using dimension) leftKernel(R); a left kernel of R rightKernel(R); a right kernel of R leftInverse(R); a left inverse of R rightInverse(R); a right inverse of R colrank(M); a column rank of M as of matrix genericity(M); analysis of the genericity of parameters canonize(L); Groebnerification for modules in the output of control or autonomy procs iostruct(R); computes an IO-structure of behavior given by a module R findTorsion(R, I); generators of the submodule of a module R, annihilated by the ideal I controlExample(s); set up an example from the mini database inside of the library view(); well-formatted output of lists, modules and matrices "; LIB "homolog.lib"; LIB "poly.lib"; LIB "primdec.lib"; LIB "matrix.lib"; //--------------------------------------------------------------- static proc Opt_Our() "USAGE: Opt_Our(); RETURN: intvec, where previous options are stored PURPOSE: save previous options and set customized options " { intvec v; v=option(get); option(redSB); option(redTail); return (v); } //------------------------------------------------------------------------- static proc space(int n) "USAGE:spase(n); n is an integer (number of needed spaces) RETURN: string consisting of n spaces NOTE: the procedure is used in the procedure 'view' to have a better formatted output "{ int i; string s=""; for(i=1;i<=n;i++) { s=s+" "; } return(s); } //----------------------------------------------------------------------------- proc view(def M) "USAGE: view(M); M is of any type RETURN: no return value PURPOSE: procedure for (well-) formatted output of modules, matrices, lists of modules, matrices; shows everything even if entries are long NOTE: in case of other types( not 'module', 'matrix', 'list') works just as standard 'print' procedure EXAMPLE: example view; shows an example " { // to be replaced with something more feasible if ( (typeof(M)=="module")||(typeof(M)=="matrix") ) { int @R=nrows(M); int @C=ncols(M); int i; int j; list MaxLength=list(); int Size=0; int max; string s; for(i=1;i<=@C;i++) { max=0; for(j=1;j<=@R;j++) { Size=size( string( M[j,i] ) ); if( Size>max ) { max=Size; } } MaxLength[i] = max; } for(i=1;i<=@R;i++) { s=""; for(j=1;j<@C;j++) { s=s+string(M[i,j])+space( MaxLength[j]-size( string( M[i,j] ) ) ) +","; } s=s+string(M[i,j])+space( MaxLength[j]-size( string( M[i,j] ) ) ); if (i!=@R) { s=s+","; } print(s); } return(); } if(typeof(M)=="list") { int sz=size(M); int i; for(i=1;i<=sz;i++) { view(M[i]); print(""); } return(); } print(M); return(); } example {"EXAMPLE:";echo = 2; ring r; list L; matrix M[1][3] = x2+x,y3-y,z5-4z+7; L[1] = "a matrix:"; L[2] = M; L[3] = "an ideal:"; L[4] = ideal(M); view(L); } //-------------------------------------------------------------------------- proc rightKernel(matrix M) "USAGE: rightKernel(M); M a matrix RETURN: module PURPOSE: computes the right kernel of matrix M (a module of all elements v such that Mv=0) EXAMPLE: example rightKernel; shows an example "{ return(modulo(M,std(0))); } example {"EXAMPLE:";echo = 2; ring r = 0,(x,y,z),dp; matrix M[1][3] = x,y,z; print(M); matrix R = rightKernel(M); print(R); // check: print(M*R); } //------------------------------------------------------------------------- proc leftKernel(matrix M) "USAGE: leftKernel(M); M a matrix RETURN: module PURPOSE: computes left kernel of matrix M (a module of all elements v such that vM=0) EXAMPLE: example leftKernel; shows an example " { return( transpose( modulo( transpose(M),std(0) ) ) ); } example {"EXAMPLE:";echo = 2; ring r= 0,(x,y,z),dp; matrix M[3][1] = x,y,z; print(M); matrix L = leftKernel(M); print(L); // check: print(L*M); } //------------------------------------------------------------------------ proc leftInverse(module M) "USAGE: leftInverse(M); M a module RETURN: module PURPOSE: computes such a matrix L, that LM = Id; EXAMPLE: example leftInverse; shows an example NOTE: exists only in the case when M is free submodule " { // it works also for the NC case; int NCols = ncols(M); module Id = freemodule(NCols); module N = transpose(M); intvec old_opt=Opt_Our(); Id = std(Id); matrix T; // check the correctness (Id \subseteq M) // via dimension: dim (M) = -1! int d = dim_Our(N); if (d != -1) { // No left inverse exists return(matrix(0)); } matrix T2 = lift(N, Id); T2 = transpose(T2); option(set,old_opt); // set the options back return(T2); } example { "EXAMPLE:";echo =2; // a trivial example: ring r = 0,(x,z),dp; matrix M[2][1] = 1,x2z; print(M); print( leftInverse(M) ); kill r; // derived from the example TwoPendula: ring r=(0,m1,m2,M,g,L1,L2),Dt,dp; matrix U[3][1]; U[1,1]=(-L2)*Dt^4+(g)*Dt^2; U[2,1]=(-L1)*Dt^4+(g)*Dt^2; U[3,1]=(L1*L2)*Dt^4+(-g*L1-g*L2)*Dt^2+(g^2); module M = module(U); module L = leftInverse(M); print(L); // check print(L*M); } //----------------------------------------------------------------------- proc rightInverse(module R) "USAGE: rightInverse(M); M a module RETURN: module PURPOSE: computes such a matrix L, that ML = Id EXAMPLE: example rightInverse; shows an example NOTE: exists only in the case when M is free submodule " { // for comm case it suffices if (isCommutative()) { return(transpose(leftInverse(transpose(R)))); } // for noncomm def save = basering; def sop = opposite(save); setring sop; module Mop = oppose(save,R); Mop = transpose(Mop); module L = leftInverse(Mop); setring save; module L = oppose(sop,L); L = transpose(L); return(matrix(L)); } example { "EXAMPLE:";echo =2; // a trivial example: ring r = 0,(x,z),dp; matrix M[1][2] = 1,x2+z; print(M); print( rightInverse(M) ); kill r; // derived from the TwoPendula example: ring r=(0,m1,m2,M,g,L1,L2),Dt,dp; matrix U[1][3]; U[1,1]=(-L2)*Dt^4+(g)*Dt^2; U[1,2]=(-L1)*Dt^4+(g)*Dt^2; U[1,3]=(L1*L2)*Dt^4+(-g*L1-g*L2)*Dt^2+(g^2); module M = module(U); module L = rightInverse(M); print(L); // check print(M*L); } //----------------------------------------------------------------------- static proc dim_Our(module R) { int d; if (attrib(R,"isSB")<>1) { R = std(R); } d = dim(R); return(d); } //----------------------------------------------------------------------- static proc Ann_Our(module R) { return(Ann(R)); } //----------------------------------------------------------------------- static proc Ext_Our(int i, module R, list #) { // mimicking 'Ext_R' from homolog.lib int ExtraArg = ( size(#)>0 ); if (ExtraArg) { return( Ext_R(i,R,#[1]) ); } else { return( Ext_R(i,R) ); } } //------------------------------------------------------------------------ static proc is_zero_Our { //just a copy of 'is_zero' from "poly.lib" patched with GKdim int d = dim_Our(std(#[1])); int a = ( d==-1 ); if( size(#) >1 ) { list L=a,d; return(L); } return(a); // return( is_zero(R) ) ; } //------------------------------------------------------------------------ static proc control_output(int i, int NVars, module R, module Ext_1, list Gen) "USAGE: control_output(i, NVars, R, Ext_1), PURPOSE: where @* i is integer (number of first nonzero Ext or a number of variables in a basering + 1 in case that all the Exts are zero), @* NVars: integer, number of variables in a base ring, @* R: module R (cokernel representation), @* Ext_1: module, the first Ext(its cokernel representation) RETURN: list with all the contollability properties of the system which is to be returned in 'control' procedure NOTE: this procedure is used in 'control' procedure "{ // TODO: NVars to be replaced with the global hom. dimension of basering!!! // Is not clear what to do with gl.dim of qrings string DofS = "dimension of the system:"; string Fn = "number of first nonzero Ext:"; string Gen_mes = "Parameter constellations which might lead to a non-controllable system:"; module RK = rightKernel(R); int d=dim_Our(std(transpose(R))); if (i==1) { return( list ( Fn, i, "not controllable , image representation for controllable part:", RK, "kernel representation for controllable part:", leftKernel( RK ), "obstruction to controllability", Ext_1, "annihilator of torsion module (of obstruction to controllability)", Ann_Our(Ext_1), DofS, d ) ); } if(i>NVars) { return( list( Fn, -1, "strongly controllable(flat), image representation:", RK, "left inverse to image representation:", leftInverse(RK), DofS, d, Gen_mes, Gen) ); } // //now i<=NVars // if( (i==2) ) { return( list( Fn, i, "controllable, not reflexive, image representation:", RK, DofS, d, Gen_mes, Gen) ); } if( (i>=3) ) { return( list ( Fn, i, "reflexive, not strongly controllable, image representation:", RK, DofS, d, Gen_mes, Gen) ); } } //------------------------------------------------------------------------- proc control(module R) "USAGE: control(R); R a module (R is the matrix of the system of equations to be investigated) RETURN: list PURPOSE: compute the list of all the properties concerning controllability of the system (behavior), represented by the matrix R NOTE: the properties and corresponding data like controllability, flatness, dimension of the system, degree of controllability, kernel and image representations, genericity of parameters, obstructions to controllability, annihilator of torsion submodule and left inverse are investigated EXAMPLE: example control; shows an example " { int i; int NVars=nvars(basering); // TODO: NVars to be replaced with the global hom. dimension of basering!!! int ExtIsZero; intvec v=Opt_Our(); module R_std=std(R); module Ext_1 = std(Ext_Our(1,R_std)); ExtIsZero=is_zero_Our(Ext_1); i=1; while( (ExtIsZero) && (i<=NVars) ) { i++; ExtIsZero = is_zero_Our( Ext_Our(i,R_std) ); } matrix T=lift(R,R_std); list l=genericity(T); option(set,v); return( control_output( i, NVars, R, Ext_1, l ) ); } example {"EXAMPLE:";echo = 2; // a WindTunnel example ring A = (0,a, omega, zeta, k),(D1, delta),dp; module R; R = [D1+a, -k*a*delta, 0, 0], [0, D1, -1, 0], [0, omega^2, D1+2*zeta*omega, -omega^2]; R=transpose(R); view(R); view(control(R)); } //-------------------------------------------------------------------------- proc controlDim(module R) "USAGE: controlDim(R); R a module (R is the matrix of the system of equations to be investigated) RETURN: list PURPOSE: computes list of all the properties concerning controllability of the system (behavior), represented by the matrix R EXAMPLE: example controlDim; shows an example NOTE: the properties and corresponding data like controllability, flatness, dimension of the system, degree of controllability, kernel and image representations, genericity of parameters, obstructions to controllability, annihilator of torsion submodule and left inverse are investigated. @* This procedure is analogous to 'control' but uses dimension calculations. @* The implemented approach works for full row rank matrices only (the check is done automatically). " { if( nrows(R) != colrank(transpose(R)) ) { return ("controlDim cannot be applied, since R does not have full row rank"); } intvec v = Opt_Our(); module R_std = std(R); int d = dim_Our(R_std); int NVars = nvars(basering); int i = NVars-d; module Ext_1 = std(Ext_Our(1,R_std)); matrix T = lift(R,R_std); list l = genericity(T); option(set, v); return( control_output( i, NVars, R, Ext_1, l)); } example {"EXAMPLE:";echo = 2; //a WindTunnel example ring A = (0,a, omega, zeta, k),(D1, delta),dp; module R; R = [D1+a, -k*a*delta, 0, 0], [0, D1, -1, 0], [0, omega^2, D1+2*zeta*omega, -omega^2]; R=transpose(R); view(R); view(controlDim(R)); } //------------------------------------------------------------------------ proc colrank(module M) "USAGE: colrank(M); M a matrix/module RETURN: int PURPOSE: compute the column rank of M as of matrix NOTE: this procedure uses Bareiss algorithm "{ // NOte continued: // which might not terminate in some cases module M_red = bareiss(M)[1]; int NCols_red = ncols(M_red); return (NCols_red); } example {"EXAMPLE: ";echo = 2; // de Rham complex ring r=0,(D(1..3)),dp; module R; R=[0,-D(3),D(2)], [D(3),0,-D(1)], [-D(2),D(1),0]; R=transpose(R); colrank(R); } //------------------------------------------------------------------------ static proc autonom_output( int i, int NVars, module RC, int R_rank ) "USAGE: proc autonom_output(i, NVars, RC, R_rank) i: integer, number of first nonzero Ext or just number of variables in a base ring + 1 in case that all the Exts are zero NVars: integer, number of variables in a base ring RC: module, kernel-representation of controllable part of the system R_rank: integer, column rank of the representation matrix PURPOSE: compute all the autonomy properties of the system which is to be returned in 'autonom' procedure RETURN: list NOTE: this procedure is used in 'autonom' procedure " { int d=NVars-i;//that is the dimension of the system string DofS="dimension of the system:"; string Fn = "number of first nonzero Ext:"; if(i==0) { return( list( Fn, i, "not autonomous", "kernel representation for controllable part", RC, "column rank of the matrix", R_rank, DofS, d ) ); } if( i>NVars ) { return( list( Fn, -1, "trivial", DofS, d ) ); } // //now i<=NVars // if( i==1 ) // in case that NVars==1 there is no sense to consider the notion // of strongly autonomous behavior, because it does not imply // that system is overdetermined in this case { return( list ( Fn, i, "autonomous, not overdetermined", DofS, d ) ); } if( i==NVars ) { return( list( Fn, i, "strongly autonomous(fin. dimensional),in particular overdetermined", DofS, d) ); } if( iv[i+1]) { temp=v[i]; v[i]=v[i+1]; v[i+1]=temp; b=1; } } } P=R[v]; //generate P for(i=1;i<=NCols;i++) //generate Q { if(elementof(i,v)==1) { i++; continue; } Q=Q,R[i]; } Q=simplify(Q,2); string s="The following components have been chosen as outputs: "; return (list(s,v,P,Q)); } example {"EXAMPLE:";echo = 2; //Example Antenna ring r = (0, K1, K2, Te, Kp, Kc),(Dt, delta), (c,dp); module RR; RR = [Dt, -K1, 0, 0, 0, 0, 0, 0, 0], [0, Dt+K2/Te, 0, 0, 0, 0, -Kp/Te*delta, -Kc/Te*delta, -Kc/Te*delta], [0, 0, Dt, -K1, 0, 0, 0, 0, 0], [0, 0, 0, Dt+K2/Te, 0, 0, -Kc/Te*delta, -Kp/Te*delta, -Kc/Te*delta], [0, 0, 0, 0, Dt, -K1, 0, 0, 0], [0, 0, 0, 0, 0, Dt+K2/Te, -Kc/Te*delta, -Kc/Te*delta, -Kp/Te*delta]; module R = transpose(RR); view(iostruct(R)); } //--------------------------------------------------------------- static proc smdeg(matrix N) "USAGE: smdeg( N ); N a matrix RETURN: intvec PURPOSE: returns an intvec of length 2 with the index of an element of N with smallest degree " { int n = nrows(N); int m = ncols(N); int d,d_temp; intvec v; int i,j; // counter if (N==0) { v = 1,1; return(v); } for (i=1; i<=n; i++) // hier wird ein Element ausgewaehlt(!=0) und mit dessen Grad gestartet { for (j=1; j<=m; j++) { if( deg(N[i,j])!=-1 ) { d=deg(N[i,j]); break; } } if (d != -1) { break; } } for(i=1; i<=n; i++) { for(j=1; j<=m; j++) { d_temp = deg(N[i,j]); if ( (d_temp < d) && (N[i,j]!=0) ) { d=d_temp; } } } for (i=1; i<=n; i++) { for (j=1; j<=m;j++) { if ( (deg(N[i,j]) == d) && (N[i,j]!=0) ) { v = i,j; return(v); } } } } //--------------------------------------------------------------- static proc NoNon0Pol(vector v) "USAGE: NoNon0Pol(v), v a vector RETURN: int PURPOSE: returns 1, if there is only one non-zero element in v and 0 else "{ int i,j; int n = nrows(v); for( j=1; j<=n; j++) { if (v[j] != 0) { i++; } } if ( i!=1 ) { i=0; } return(i); } //--------------------------------------------------------------- static proc extgcd_Our(poly p, poly q) { ideal J; //for extgcd-computations matrix T; //----------"------------ list L; // the extgcd-command has a bug in versions before 2-0-7 if ( system("version")<=2006 ) { J = p,q; // J = N[k-1,k-1],N[k,k]; //J is of type ideal L[1] = liftstd(J,T); //T is of type matrix if(J[1]==p) //this is just for the case the SINGULAR swaps the // two elements due to ordering { L[2] = T[1,1]; L[3] = T[2,1]; } else { L[2] = T[2,1]; L[3] = T[1,1]; } } else { L=extgcd(p,q); // L=extgcd(N[k-1,k-1],N[k,k]); //one can use this line if extgcd-bug is fixed } return(L); } static proc normalize_Our(matrix N, matrix Q) "USAGE: normalize_Our(N,Q), N, Q are two matrices PURPOSE: normalizes N and divides the columns of Q through the leading coefficients of the columns of N RETURN: normalized matrix N and altered Q(according to the scheme mentioned in purpose). If number of columns of N and Q do not coincide, N and Q are returned unchanged NOTE: number of columns of N and Q must coincide. " { if(ncols(N) != ncols(Q)) { return (N,Q); } module M = module(N); module S = module(Q); int NCols = ncols(N); number n; for(int i=1;i<=NCols;i++) { n = leadcoef(M[i]); if( n != 0 ) { M[i]=M[i]/n; S[i]=S[i]/n; } } N = matrix(M); Q = matrix(S); return (N,Q); } //--------------------------------------------------------------- proc oldsmith( module M ) "USAGE: oldsmith(M); M a module/matrix PURPOSE: computes the Smith normal form of a matrix RETURN: a list of length 4 with the following entries: @* [1]: the Smith normal form S of M, @* [2]: the rank of M, @* [3]: a unimodular matrix U, @* [4]: a unimodular matrix V, such that U*M*V=S. An warning is returned when no Smith form exists. NOTE: Older experimental implementation. The Smith form only exists over PIDs (principal ideal domains). Use global ordering for computations! " { if (nvars(basering)>1) //if more than one variable, return empty list { string s="The Smith-Form only exists for principal ideal domains"; return (s); } matrix N = matrix(M); //Typecasting int n = nrows(N); int m = ncols(N); matrix P = unitmat(n); //left transformation matrix matrix Q = unitmat(m); //right transformation matrix int k, i, j, deg_temp; poly tmp; vector v; list L; //for extgcd-computation intmat f[1][n]; //to save degrees matrix lambda[1][n]; //to save leadcoefficients intmat g[1][m]; //to save degrees matrix mu[1][m]; //to save leadcoefficients int ii; //counter while ((k!=n) && (k!=m) ) { k++; while ((k<=n) && (k<=m)) //outer while-loop for column-operations { while(k<=m ) //inner while-loop for row-operations { if( (n>m) && (k < n) && (kn) { break; } if(NoNon0Pol(transpose(N)[k])==1) { break; } tmp=leadcoef(N[k,k]); deg_temp=ord(N[k,k]); //ord outputs the leading degree of N[k][k] for(ii=k+1;ii<=m;ii++) { mu[1,ii]=leadcoef(N[k,ii])/tmp; g[1,ii]=deg(N[k,ii])-deg_temp; } for(ii=k+1;ii<=m;ii++) { N=addcol(N,k,-mu[1,ii]*var(1)^g[1,ii],ii); Q=addcol(Q,k,-mu[1,ii]*var(1)^g[1,ii],ii); N,Q=normalize_Our(N,Q); } } if( (k!=1) && (knur wenn string in liste dann verbatim { t=L[i]; if(nr_loop==1) { write(l,"\\begin\{center\}"); write(l,"\\begin\{verbatim\}"); } write(l,t); if(nr_loop==0) { write(l,"\\par"); } if(nr_loop==1) { write(l,"\\end\{verbatim\}"); write(l,"\\end\{center\}"); } break; } if(typeof(L[i])=="module") { texobj(name,matrix(L[i])); break; } if(typeof(L[i])=="list") { list_tex(L[i],name,l,1); break; } write(l,"\\begin\{center\}"); texobj(name,L[i]); write(l,"\\end\{center\}"); write(l,"\\par"); break; } } } } example { "EXAMPLE:";echo = 2; } //--------------------------------------------------------------- proc verbatim_tex(string s, link l) "USAGE: verbatim_tex(s,l), where s is a string and l a link PURPOSE: writes the content of s in verbatim-environment in the file specified by link RETURN: nothing " { write(l,"\\begin{verbatim}"); write(l,s); write(l,"\\end{verbatim}"); write(l,"\\par"); } example { "EXAMPLE:";echo = 2; } //--------------------------------------------------------------- proc findTorsion(module R, ideal TAnn) "USAGE: findTorsion(R, I); R an ideal/matrix/module, I an ideal RETURN: module PURPOSE: computes the Groebner basis of the submodule of R, annihilated by I NOTE: especially helpful, when I is the annihilator of the t(R) - the torsion submodule of R. In this case, the result is the explicit presentation of t(R) as the submodule of R EXAMPLE: example findTorsion; shows an example " { // motivation: let R be a module, // TAnn is the annihilator of t(R)\subset R // compute the generators of t(R) explicitly ideal AS = TAnn; module S = R; if (attrib(S,"isSB")<>1) { S = std(S); } if (attrib(AS,"isSB")<>1) { AS = std(AS); } int nc = ncols(S); module To = quotient(S,AS); To = std(NF(To,S)); return(To); } example { "EXAMPLE:";echo = 2; // Flexible Rod ring A = 0,(D1, D2), (c,dp); module R= [D1, -D1*D2, -1], [2*D1*D2, -D1-D1*D2^2, 0]; module RR = transpose(R); list L = control(RR); // here, we have the annihilator: ideal LAnn = D1; // = L[10] module Tr = findTorsion(RR,LAnn); print(RR); // the module itself print(Tr); // generators of the torsion submodule } proc controlExample(string s) "USAGE: controlExample(s); s a string RETURN: ring PURPOSE: set up an example from the mini database by initalizing a ring and a module in a ring NOTE: in order to see the list of available examples, execute @code{controlExample(\"show\");} @* To use an example, one has to do the following. Suppose one calls the ring, where the example will be activated, A. Then, by executing @* @code{def A = controlExample(\"Antenna\");} and @code{setring A;}, @* A will become a basering from the example \"Antenna\" with the predefined system module R (transposed). After that one can just execute @code{control(R);} respectively @code{autonom(R);} to perform the control resp. autonomy analysis of R. EXAMPLE: example controlExample; shows an example "{ list E, S, D; // E=official name, S=synonym, D=description E[1] = "Cauchy1"; S[1] = "cauchy1"; D[1] = "1-dimensional Cauchy equation"; E[2] = "Cauchy2"; S[2] = "cauchy2"; D[2] = "2-dimensional Cauchy equation"; E[3] = "Control1"; S[3] = "control1"; D[3] = "example of a simple noncontrollable system"; E[4] = "Control2"; S[4] = "control2"; D[4] = "example of a simple controllable system"; E[5] = "Antenna"; S[5] = "antenna"; D[5] = "antenna"; E[6] = "Einstein"; S[6] = "einstein"; D[6] = "Einstein equations in vacuum"; E[7] = "FlexibleRod"; S[7] = "flexible rod"; D[7] = "flexible rod"; E[8] = "TwoPendula"; S[8] = "two pendula"; D[8] = "two pendula mounted on a cart"; E[9] = "WindTunnel"; S[9] = "wind tunnel";D[9] = "wind tunnel"; E[10] = "Zerz1"; S[10] = "zerz1"; D[10] = "example from the lecture of Eva Zerz"; // all the examples so far int i; if ( (s=="show") || (s=="Show") ) { print("The list of examples:"); for (i=1; i<=size(E); i++) { printf("name: %s, desc: %s", E[i],D[i]); } return(); } string t; for (i=1; i<=size(E); i++) { if ( (s==E[i]) || (s==S[i]) ) { t = "def @A = ex"+E[i]+"();"; execute(t); return(@A); } } "No example found"; return(); } example { "EXAMPLE:";echo = 2; controlExample("show"); // let us see all available examples: def B = controlExample("TwoPendula"); // let us set up a particular example setring B; print(R); } //---------------------------------------------------------- // //Some example rings with defined systems //---------------------------------------------------------- //autonomy: // //---------------------------------------------------------- static proc exCauchy1() { ring @r=0,(s1,s2),dp; module R= [s1,-s2], [s2, s1]; R=transpose(R); export R; return(@r); } //---------------------------------------------------------- static proc exCauchy2() { ring @r=0,(s1,s2,s3,s4),dp; module R= [s1,-s2], [s2, s1], [s3,-s4], [s4, s3]; R=transpose(R); export R; return(@r); } //---------------------------------------------------------- static proc exZerz1() { ring @r=0,(d1,d2),dp; module R=[d1^2-d2], [d2^2-1]; R=transpose(R); export R; return(@r); } //---------------------------------------------------------- //control //---------------------------------------------------------- static proc exControl1() { ring @r=0,(s1,s2,s3),dp; module R=[0,-s3,s2], [s3,0,-s1]; R=transpose(R); export R; return(@r); } //---------------------------------------------------------- static proc exControl2() { ring @r=0,(s1,s2,s3),dp; module R=[0,-s3,s2], [s3,0,-s1], [-s2,s1,0]; R=transpose(R); export R; return(@r); } //---------------------------------------------------------- static proc exAntenna() { ring @r = (0, K1, K2, Te, Kp, Kc),(Dt, delta), dp; module R; R = [Dt, -K1, 0, 0, 0, 0, 0, 0, 0], [0, Dt+K2/Te, 0, 0, 0, 0, -Kp/Te*delta, -Kc/Te*delta, -Kc/Te*delta], [0, 0, Dt, -K1, 0, 0, 0, 0, 0], [0, 0, 0, Dt+K2/Te, 0, 0, -Kc/Te*delta, -Kp/Te*delta, -Kc/Te*delta], [0, 0, 0, 0, Dt, -K1, 0, 0, 0], [0, 0, 0, 0, 0, Dt+K2/Te, -Kc/Te*delta, -Kc/Te*delta, -Kp/Te*delta]; R=transpose(R); export R; return(@r); } //---------------------------------------------------------- static proc exEinstein() { ring @r = 0,(D(1..4)),dp; module R = [D(2)^2+D(3)^2-D(4)^2, D(1)^2, D(1)^2, -D(1)^2, -2*D(1)*D(2), 0, 0, -2*D(1)*D(3), 0, 2*D(1)*D(4)], [D(2)^2, D(1)^2+D(3)^2-D(4)^2, D(2)^2, -D(2)^2, -2*D(1)*D(2), -2*D(2)*D(3), 0, 0, 2*D(2)*D(4), 0], [D(3)^2, D(3)^2, D(1)^2+D(2)^2-D(4)^2, -D(3)^2, 0, -2*D(2)*D(3), 2*D(3)*D(4), -2*D(1)*D(3), 0, 0], [D(4)^2, D(4)^2, D(4)^2, D(1)^2+D(2)^2+D(3)^2, 0, 0, -2*D(3)*D(4), 0, -2*D(2)*D(4), -2*D(1)*D(4)], [0, 0, D(1)*D(2), -D(1)*D(2), D(3)^2-D(4)^2, -D(1)*D(3), 0, -D(2)*D(3), D(1)*D(4), D(2)*D(4)], [D(2)*D(3), 0, 0, -D(2)*D(3),-D(1)*D(3), D(1)^2-D(4)^2, D(2)*D(4), -D(1)*D(2), D(3)*D(4), 0], [D(3)*D(4), D(3)*D(4), 0, 0, 0, -D(2)*D(4), D(1)^2+D(2)^2, -D(1)*D(4), -D(2)*D(3), -D(1)*D(3)], [0, D(1)*D(3), 0, -D(1)*D(3), -D(2)*D(3), -D(1)*D(2), D(1)*D(4), D(2)^2-D(4)^2, 0, D(3)*D(4)], [D(2)*D(4), 0, D(2)*D(4), 0, -D(1)*D(4), -D(3)*D(4), -D(2)*D(3), 0, D(1)^2+D(3)^2, -D(1)*D(2)], [0, D(1)*D(4), D(1)*D(4), 0, -D(2)*D(4), 0, -D(1)*D(3), -D(3)*D(4), -D(1)*D(2), D(2)^2+D(3)^2]; R=transpose(R); export R; return(@r); } //---------------------------------------------------------- static proc exFlexibleRod() { ring @r = 0,(D1, delta), dp; module R; R = [D1, -D1*delta, -1], [2*D1*delta, -D1-D1*delta^2, 0]; R=transpose(R); export R; return(@r); } //---------------------------------------------------------- static proc exTwoPendula() { ring @r=(0,m1,m2,M,g,L1,L2),Dt,dp; module R = [m1*L1*Dt^2, m2*L2*Dt^2, -1, (M+m1+m2)*Dt^2], [m1*L1^2*Dt^2-m1*L1*g, 0, 0, m1*L1*Dt^2], [0, m2*L2^2*Dt^2-m2*L2*g, 0, m2*L2*Dt^2]; R=transpose(R); export R; return(@r); } //---------------------------------------------------------- static proc exWindTunnel() { ring @r = (0,a, omega, zeta, k),(D1, delta),dp; module R = [D1+a, -k*a*delta, 0, 0], [0, D1, -1, 0], [0, omega^2, D1+2*zeta*omega, -omega^2]; R=transpose(R); export R; return(@r); } /* noncomm examples for leftInverse/rightInverse: LIB "jacobson.lib"; ring w = 0,(x,d),Dp; def W=nc_algebra(1,1); setring W; matrix m[3][3]=[d2,d+1,0],[d+1,0,d3-x2*d],[2d+1, d3+d2, d2]; list J=jacobson(m,0); leftInverse(J[3]); // exist rightInverse(J[3]); leftInverse(J[1]); // zero rightInverse(J[1]); list JJ = jacobson(J[1],0); leftInverse(JJ[3]); // exist rightInverse(JJ[3]); leftInverse(JJ[1]); // exist rightInverse(JJ[1]); leftInverse(JJ[2]); // zero rightInverse(JJ[2]); */ singular-4.0.3+ds/Singular/LIB/crypto.lib000066400000000000000000002647061266270727000201760ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version crypto.lib 4.0.0.1 Aug_2014 "; // $Id: dfb2cb269d4d1328eba1d57527e2e2fafd159acf $ category="Teaching"; info=" LIBRARY: crypto.lib Procedures for teaching cryptography AUTHORS: Gerhard Pfister, pfister@mathematik.uni-kl.de @* David Brittinger, dativ@gmx.net OVERVIEW: The library contains procedures to compute the discrete logarithm, primality-tests, factorization included elliptic curves. The library is intended to be used for teaching purposes but not for serious computations. Sufficiently high printlevel allows to control each step, thus illustrating the algorithms at work. PROCEDURES: decimal(s); number corresponding to the hexadecimal number s eexgcdN(L) T with sum_i L[i]*T[i]=T[n+1]=gcd(L[1],...,L[n]) lcmN(a,b) compute lcm(a,b) powerN(m,d,n) compute m^d mod n chineseRem(T,L) compute x such that x = T[i] mod L[i] Jacobi(a,n) the generalized Legendre symbol of a and n primList(n) the list of all primes <=n primL(q) first primes p_1,...,p_r such that q=2;i--) { if((d mod i)==0){return(powerN(m,d div i,n)^i);} } return(m*powerN(m,d-1,n)); } for(i=12;i>=2;i--) { if((d mod i)==0) { bigint rr=powerN(m,d div i,n)^i mod n; if (rr<0) { rr=rr+n;} return(rr); } } return(m*powerN(m,d-1,n) mod n); } example { "EXAMPLE:"; echo = 2; powerN(24,15,7); } proc chineseRem(list T,list L) "USAGE: chineseRem(T,L); RETURN: x such that x = T[i] mod L[i] NOTE: chinese remainder theorem EXAMPLE:example chineseRem; shows an example " { int i; int n=size(L); bigint N=1; for(i=1;i<=n;i++) { N=N*L[i]; } list M; for(i=1;i<=n;i++) { M[i]=N div L[i]; } list S=eexgcdN(M); bigint x; for(i=1;i<=n;i++) { x=x+S[i]*M[i]*T[i]; } x=x mod N; return(x); } example { "EXAMPLE:"; echo = 2; chineseRem(list(24,15,7),list(2,3,5)); } proc Jacobi(bigint a, bigint n) "USAGE: Jacobi(a,n); RETURN: the generalized Legendre symbol NOTE: if n is an odd prime then Jacobi(a,n)=0,1,-1 if n|a, a=x^2 mod n,else EXAMPLE:example Jacobi; shows an example " { int i; int z=1; bigint t=1; bigint k; if((((n-1) div 2) mod 2)!=0){z=-1;} if(a<0){return(z*Jacobi(-a,n));} a=a mod n; if(n==1){return(1);} if(a==0){return(0);} while(a!=0) { while((a mod 2)==0) { a=a div 2; if(((n mod 8)==3)||((n mod 8)==5)){t=-t;} } k=a;a=n;n=k; if(((a mod 4)==3)&&((n mod 4)==3)){t=-t;} a=a mod n; } if (n==1){return(t);} return(0); } example { "EXAMPLE:"; echo = 2; Jacobi(13580555397810650806,5792543); } proc primList(int n) "USAGE: primList(n); RETURN: the list of all primes <=n EXAMPLE:example primList; shows an example " { int i,j; list re; re[1]=2; re[2]=3; for(i=5;i<=n;i=i+2) { j=1; while(j<=size(re)) { if((i mod re[j])==0){break;} j++; } if(j==size(re)+1){re[size(re)+1]=i;} } return(re); } example { "EXAMPLE:"; echo = 2; list L=primList(100); size(L); L[size(L)]; } proc primL(bigint q) "USAGE: primL(q); RETURN: list of the first primes p_1,...,p_r such that q>p_1*...*p_(r-1) and q=0) { return(bigint((numerator(x)-(bigint(numerator(x)) mod bigint(denominator(x))))) div bigint(denominator(x))); } else { return(bigint((numerator(x)-(bigint(numerator(x)) mod bigint(denominator(x)+denominator(x))))) div bigint(denominator(x))); } } example { "EXAMPLE:"; echo = 2; ring r=0,x,dp; intPart(7/3); } proc intRoot(bigint mm) "USAGE: intRoot(m); RETURN: the integral part of the square root of m EXAMPLE:example intRoot; shows an example " { ring R = 0,@x,dp; number m=mm; number x=1; number t=x^2; number s=(x+1)^2; while(((m>t)&&(m>s))||((mm) { s=(x-1)^2; } else { s=(x+1)^2; } } if(t>m){return(bigint(x-1));} if(s==m){return(bigint(x+1));} return(bigint(x)); } example { "EXAMPLE:"; echo = 2; intRoot(20); } proc squareRoot(bigint a, bigint p) "USAGE: squareRoot(a,p); RETURN: the square root of a in Z/p, p prime NOTE: assumes the Jacobi symbol is 1 or p=2. EXAMPLE:example squareRoot; shows an example " { if(p==2){return(a);} if((a mod p)==0){return(0);} if (a<0) { a=a+p; } if(powerN(a,p-1,p)!=1) { "p is not prime"; return(bigint(-5)); } bigint n=random(1,2147483647) mod p; if(n==0){n=n+1;} bigint j=Jacobi(n,p); if(j==0) { "p is not prime"; return(bigint(-5)); } if(j==1) { return(squareRoot(a,p)); } bigint q=p-1; bigint e=0; bigint two=2; bigint z,m,t; while((q mod 2)==0) { e=e+1; q=q div 2; } bigint y=powerN(n,q,p); bigint r=e; bigint x=powerN(a,(q-1) div 2,p); bigint b=a*x^2 mod p; x=a*x mod p; while(((b-1) mod p)!=0) { m=0;z=b; while(((z-1) mod p)!=0) { z=z^2 mod p; m=m+1; } t=powerN(y,powerN(two,r-m-1,p),p); y=t^2 mod p; r=m; x=x*t mod p; b=b*y mod p; } return(x); } example { "EXAMPLE:"; echo = 2; squareRoot(8315890421938608,32003); } proc solutionsMod2(bigintmat MM) "USAGE: solutionsMod2(M); RETURN: an intmat containing a basis of the vector space of solutions of the linear system of equations defined by M over the prime field of characteristic 2 EXAMPLE:example solutionsMod2; shows an example " { ring Rhelp=2,z,(c,dp); int i,j; matrix M[nrows(MM)][ncols(MM)]; for(i=1;i<=nrows(MM);i++) { for(j=1;j<=ncols(MM);j++) { M[i,j]=MM[i,j]; } } matrix S=syz(M); intmat v[nrows(S)][ncols(S)]; for(i=1;i<=nrows(S);i++) { for(j=1;j<=ncols(S);j++) { if(S[i,j]==1){v[i,j]=1;} } } return(v); } example { "EXAMPLE:"; echo = 2; bigintmat M[3][3]=1,2,3,4,5,6,7,6,5; solutionsMod2(M); } proc powerX(int q, int i, ideal I) "USAGE: powerX(q,i,I); RETURN: the q-th power of the i-th variable modulo I ASSUME: I is a standard basis EXAMPLE:example powerX; shows an example " { if(q<=181){return(reduce(var(i)^int(q),I));} if((q mod 5)==0){return(reduce(powerX(q div 5,i,I)^5,I));} if((q mod 4)==0){return(reduce(powerX(q div 4,i,I)^4,I));} if((q mod 3)==0){return(reduce(powerX(q div 3,i,I)^3,I));} if((q mod 2)==0){return(reduce(powerX(q div 2,i,I)^2,I));} return(reduce(var(i)*powerX(q-1,i,I),I)); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),dp; powerX(100,2,std(ideal(x3-1,y2-x))); } //====================================================================== //=========================== Discrete Logarithm ======================= //====================================================================== //============== Shank's baby step - giant step ======================== proc babyGiant(bigint b, bigint y, bigint p) "USAGE: babyGiant(b,y,p); RETURN: the discrete logarithm x: b^x=y mod p NOTE: This procedure works based on Shank's baby step - giant step method. EXAMPLE:example babyGiant; shows an example " { int i,j,m; list l; bigint h=1; bigint x; //choose m minimal such that m^2>p for(i=1;i<=p;i++){if(i^2>p) break;} m=i; //baby-step: compute the table y*b^i for 1<=i<=m for(i=1;i<=m;i++){l[i]=y*b^i mod p;} //giant-step: compute b^(m+j), 1<=j<=m and search in the baby-step table //for an i with y*b^i=b^(m*j). If found then x=m*j-i bigint g=b^m mod p; while(j=1;j--) { if(x[i]==x[j]) { s=(e[j]-e[i]) mod (p-1); t=(f[i]-f[j]) mod (p-1); if(s!=0) { i=0; } else { e[1]=0; f[1]=random(0,2147483629) mod (p-1); x[1]=powerN(b,f[1],p); i=1; } break; } } } list w=extgcd(s,p-1); bigint u=w[2]; bigint d=w[1]; bigint a=(t*u div d) mod (p-1); bigint pn=powerN(b,a,p); if (pn<0) { pn=pn+p;} while(powerN(b,a,p)!=y) { a=(a+(p-1) div d) mod (p-1); if (a<0) { a=a+p-1; } } return(a); } example { "EXAMPLE:"; echo = 2; bigint b=2; bigint y=10; bigint p=101; rho(b,y,p); } //==================================================================== //====================== Primality Tests ============================= //==================================================================== //================================= Miller-Rabin ===================== proc MillerRabin(bigint n, int k) "USAGE: MillerRabin(n,k); RETURN: 1 if n is prime, 0 else NOTE: probabilistic test of Miller-Rabin with k loops to test if n is prime. Using the theorem: If n is prime, n-1=2^s*r, r odd, then powerN(a,r,n)=1 or powerN(a,r*2^i,n)=-1 for some i EXAMPLE:example MillerRabin; shows an example " { if(n<0){n=-n;} if((n==2)||(n==3)){return(1);} if((n mod 2)==0){return(0);} int i; bigint a,b,j,r,s; r=n-1; s=0; while((r mod 2)==0) { s=s+1; r=r div 2; } while(iN . N is prime if and only if for each prime factor p of A we can find a_p such that a_p^(N-1)=1 mod N and gcd(a_p^((N-1)/p)-1,N)=1 EXAMPLE:example PocklingtonLehmer; shows an example " { bigint m=intRoot(N); if(size(#)>0) { list S=PollardRho(N-1,10000,1,#); } else { list S=PollardRho(N-1,10000,1); } int i,j; bigint A=1; bigint p,a,g; list PA; list re; while(im){break;} while(1) { p=p*S[i+1]; if(((N-1) mod p)==0) { A=A*p; } else { break; } } i++; } if(A<=m) { A=N div A; PA=list(S[size(S)]); } for(i=1;i<=size(PA);i++) { a=1; while(a0) { L=#; } for(i=1;i<=size(L);i++) { if((n mod L[i])==0) { re[size(re)+1]=L[i]; while((n mod L[i])==0) { n=n div L[i]; } } if(n==1){return(re);} } int e=size(re); //here the rho-algorithm starts bigint a,d,x,y; while(n>1) { a=random(2,2147483629); x=random(2,2147483629); y=x; d=1; i=0; while(i1) { re[size(re)+1]=d; while((n mod d)==0) { n=n div d; } break; } if(i==k) { re[size(re)+1]=n; n=1; } } } if(allFactors) //want to obtain all prime factors { i=e; while(iB) break; while(w*P[i]<=B) { w=w*P[i]; } k=k*w; } bigint a=random(2,2147483629); bigint d=gcd(powerN(a,k,n)-1,n); if((d>1)&&(d2)&&(Jacobi(n,p)==-1)){i++;continue;}//n is no quadratic rest mod p j=1; while(j<=p) { if(j>2*c+1) break; f=S[j][2]; v=S[j][3]; s=0; while((f mod p)==0) { s++; f=f div p; } if(s) { S[j][2]=f; v[i]=s; S[j][3]=v; l=j; while(l+p<=2*c+1) { l=l+p; f=S[l][2]; v=S[l][3]; s=0; while((f mod p)==0) { s++; f=f div p; } S[l][2]=f; v[i]=s; S[l][3]=v; } } j++; } } list T; for(j=1;j<=2*c+1;j++) { if((S[j][2]==1)||(S[j][2]==-1)) { T[size(T)+1]=S[j]; } } //the system of equations for the exponents {l_s} for the f(s) such //product f(s)^l_s is a square (l_s are 1 or 0) bigintmat M[k+1][size(T)]; for(j=1;j<=size(T);j++) { if(T[j][2]==-1){M[1,j]=1;} for(i=1;i<=k;i++) { M[i+1,j]=T[j][3][i]; } } intmat G=solutionsMod2(M); //construction of x and y such that x^2=y^2 mod n and d=gcd(x-y,n) //y=square root of product f(s)^l_s //x=product s+m bigint x=1; bigint y=1; for(i=1;i<=ncols(G);i++) { kill v; intvec v; v[k]=0; for(j=1;j<=size(T);j++) { x=x*T[j][1]^G[j,i] mod n; if((T[j][2]==-1)&&(G[j,i]==1)){y=-y;} v=v+G[j,i]*T[j][3]; } for(l=1;l<=k;l++) { y=y*B[l]^(v[l] div 2) mod n; } d=gcd(x-y,n); if((d>1)&&(d0) { s=#[1]; } else { s=1; } while(k1) { if(K[size(K)][2]!=K[size(K)-1][2]) { d=gcd(K[size(K)][2],K[size(K)-1][2]); if(ellipticMult(q,a,b,K[size(K)],d)[3]==0) { K[size(K)][2]=K[size(K)-1][2]; } } } i=int(m); break; } } i=i+1; Q=ellipticAdd(q,a,b,mP,Q); } k++; } if(size(K)>0) { int te=1; for(i=1;i<=size(K)-1;i++) { if(K[size(K)][2]!=K[i][2]) { if(ellipticMult(q,a,b,K[i],K[size(K)][2])[3]!=0) { te=0; break; } } } if(te) { return(K[size(K)][2]); } } return(ShanksMestre(q,a,b,s)); } example { "EXAMPLE:"; echo = 2; ShanksMestre(32003,71,602); } //==================== Schoof's algorithm ============================= proc Schoof(bigint N,bigint a, bigint b) "USAGE: Schoof(N,a,b); RETURN: the number of points of the elliptic curve defined by y^2=x^3+a*x+b over Z/N NOTE: algorithm of Schoof EXAMPLE:example Schoof; shows an example " { int pr=printlevel; //test for ellictic curve bigint D=4*a^3+27*b^2; bigint G=gcd(D,N); if(G==N){ERROR("not an elliptic curve");} if(G!=1){ERROR("not a prime");} //=== small N // if((N<=500)&&(pr<5)){return(countPoints(int(N),a,b));} //=== the general case bigint q=intRoot(4*N); list L=primL(2*q); int r=size(L); list T; int i,j; for(j=1;j<=r;j++) { T[j]=(testElliptic(int(N),a,b,L[j])+int(q)) mod L[j]; } if(pr>=5) { "==================================================================="; "Chinese remainder :"; for(i=1;i<=size(T);i++) { " x =",T[i]," mod ",L[i]; } "gives t+ integral part of the square root of q (to be positive)"; chineseRem(T,L); "we obtain t = ",chineseRem(T,L)-q; "==================================================================="; } bigint t=chineseRem(T,L)-q; return(N+1-t); } example { "EXAMPLE:"; echo = 2; Schoof(32003,71,602); } /* needs 518 sec Schoof(2147483629,17,3567); 2147168895 */ proc generateG(number a,number b, int m) "USAGE: generateG(a,b,m); RETURN: m-th division polynomial NOTE: generate the so-called division polynomials, i.e., the recursively defined polynomials p_m=generateG(a,b,m) in Z[x, y] such that, for a point (x:y:1) on the elliptic curve defined by y^2=x^3+a*x+b over Z/N the point@* m*P=(x-(p_(m-1)*p_(m+1))/p_m^2 :(p_(m+2)*p_(m-1)^2-p_(m-2)*p_(m+1)^2)/4y*p_m^3 :1) and m*P=0 if and only if p_m(P)=0 EXAMPLE:example generateG; shows an example " { if(m==0){return(poly(0));} if(m==1){return(poly(1));} if(m==2){return(2*var(1));} if(m==3){return(3*var(2)^4+6*a*var(2)^2+12*b*var(2)-a^2);} if(m==4) { return(4*var(1)*(var(2)^6+5*a*var(2)^4+20*b*var(2)^3-5*a^2*var(2)^2 -4*a*b*var(2)-8*b^2-a^3)); } if((m mod 2)==0) { return((generateG(a,b,m div 2+2)*generateG(a,b,m div 2-1)^2 -generateG(a,b,m div 2-2)*generateG(a,b,m div 2+1)^2) *generateG(a,b,m div 2)/(2*var(1))); } return(generateG(a,b,(m-1) div 2+2)*generateG(a,b,(m-1) div 2)^3 -generateG(a,b,(m-1) div 2-1)*generateG(a,b,(m-1) div 2+1)^3); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),dp; generateG(7,15,4); } static proc testElliptic(int q,bigint aa,bigint bb,int l) "USAGE: testElliptic(q,a,b,l); RETURN: an integer t, the trace of the Frobenius NOTE: the kernel for the Schoof algorithm: looks for the t such that for all points (x:y:1) in C[l]={P in C | l*P=0},C the elliptic curve defined by y^2=x^3+a*x+b over Z/q with group structure induced by 0=(0:1:0), (x:y:1)^(q^2)-t*(x:y:1)^q -ql*(x:y:1)=(0:1:0), ql= q mod l, trace of Frobenius. EXAMPLE:example testElliptic; shows an example " { int pr=printlevel; ring S=q,(y,x),(L(100000),lp); number a=aa; number b=bb; poly F=y2-x3-a*x-b; // the curve C poly G=generateG(a,b,l); ideal I=std(ideal(F,G)); // the points C[l] poly xq=powerX(q,2,I); poly yq=powerX(q,1,I); poly xq2=reduce(subst(xq,x,xq,y,yq),I); poly yq2=reduce(subst(yq,x,xq,y,yq),I); ideal J; int ql=q mod l; if(ql==0){ERROR("q is not prime");} int t; poly F1,F2,G1,G2,P1,P2,Q1,Q2,H1,H2,L1,L2; if(pr>=5) { "==================================================================="; "q=",q; "l=",l; "q mod l=",ql; "the Groebner basis for C[l]:";I; "x^q mod I = ",xq; "x^(q^2) mod I = ",xq2; "y^q mod I = ",yq; "y^(q^2) mod I = ",yq2; pause(); } //==== l=2 ============================================================= if(l==2) { xq=powerX(q,2,std(x3+a*x+b)); J=std(ideal(xq-x,x3+a*x+b)); if(deg(J[1])==0){t=1;} if(pr>=5) { "==================================================================="; "the case l=2"; "the gcd(x^q-x,x^3+ax+b)=",J[1]; pause(); } return(t); } //=== (F1/G1,F2/G2)=[ql](x,y) ========================================== if(ql==1) { F1=x;G1=1;F2=y;G2=1; } else { G1=reduce(generateG(a,b,ql)^2,I); F1=reduce(x*G1-generateG(a,b,ql-1)*generateG(a,b,ql+1),I); G2=reduce(4*y*generateG(a,b,ql)^3,I); F2=reduce(generateG(a,b,ql+2)*generateG(a,b,ql-1)^2 -generateG(a,b,ql-2)*generateG(a,b,ql+1)^2,I); } if(pr>=5) { "==================================================================="; "the point ql*(x,y)=(F1/G1,F2/G2)"; "F1=",F1; "G1=",G1; "F2=",F2; "G2=",G2; pause(); } //==== the case t=0 : the equations for (x,y)^(q^2)=-[ql](x,y) === J[1]=xq2*G1-F1; J[2]=yq2*G2+F2; if(pr>=5) { "==================================================================="; "the case t=0 mod l"; "the equations for (x,y)^(q^2)=-[ql](x,y) :"; J; "the test, if they vanish for all points in C[l]:"; reduce(J,I); pause(); } //=== test if all points of C[l] satisfy (x,y)^(q^2)=-[ql](x,y) //=== if so: t mod l =0 is returned if(size(reduce(J,I))==0){return(0);} //==== test for (x,y)^(q^2)=[ql](x,y) for some point J=xq2*G1-F1,yq2*G2-F2; J=std(J+I); if(pr>=5) { "==================================================================="; "test if (x,y)^(q^2)=[ql](x,y) for one point"; "if so, the Frobenius has an eigenvalue 2ql/t: (x,y)^q=(2ql/t)*(x,y)"; "it follows that t^2=4q mod l"; "if w is one square root of q mod l"; "t =2w mod l or -2w mod l "; "-------------------------------------------------------------------"; "the equations for (x,y)^(q^2)=[ql](x,y) :"; xq2*G1-F1,yq2*G2-F2; "the test if one point satisfies them"; J; pause(); } if(deg(J[1])>0) { int w=int(squareRoot(q,l)); //=== +/-2w mod l zurueckgeben, wenn (x,y)^q=+/-[w](x,y) //==== the case t>0 : (Q1/P1,Q2/P2)=[w](x,y) ============== if(w==1) { Q1=x;P1=1;Q2=y;P2=1; } else { P1=reduce(generateG(a,b,w)^2,I); Q1=reduce(x*G1-generateG(a,b,w-1)*generateG(a,b,w+1),I); P2=reduce(4*y*generateG(a,b,w)^3,I); Q2=reduce(generateG(a,b,w+2)*generateG(a,b,w-1)^2 -generateG(a,b,w-2)*generateG(a,b,w+1)^2,I); } J=xq*P1-Q1,yq*P2-Q2; J=std(I+J); if(pr>=5) { "==================================================================="; "the Frobenius has an eigenvalue, one of the roots of w^2=q mod l:"; "one root is:";w; "test, if it is the eigenvalue (if not it must be -w):"; "the equations for (x,y)^q=w*(x,y)";I;xq*P1-Q1,yq*P2-Q2; "the Groebner basis"; J; pause(); } if(deg(J[1])>0){return(2*w mod l);} return(-2*w mod l); } //==== the case t>0 : (Q1/P1,Q2/P2)=(x,y)^(q^2)+[ql](x,y) ===== P1=reduce(G1*G2^2*(F1-xq2*G1)^2,I); Q1=reduce((F2-yq2*G2)^2*G1^3-F1*G2^2*(F1-xq2*G1)^2-xq2*P1,I); P2=reduce(P1*G2*(F1-xq2*G1),I); Q2=reduce((xq2*P1-Q1)*(F2-yq2*G2)*G1-yq2*P2,I); if(pr>=5) { "we are in the general case:"; "(x,y)^(q^2)!=ql*(x,y) and (x,y)^(q^2)!=-ql*(x,y) "; "the point (Q1/P1,Q2/P2)=(x,y)^(q^2)+[ql](x,y)"; "Q1=",Q1; "P1=",P1; "Q2=",Q2; "P2=",P2; pause(); } while(t<(l-1) div 2) { t++; //==== (H1/L1,H2/L2)=[t](x,y)^q =============================== if(t==1) { H1=xq;L1=1; H2=yq;L2=1; } else { H1=x*generateG(a,b,t)^2-generateG(a,b,t-1)*generateG(a,b,t+1); H1=subst(H1,x,xq,y,yq); H1=reduce(H1,I); L1=generateG(a,b,t)^2; L1=subst(L1,x,xq,y,yq); L1=reduce(L1,I); H2=generateG(a,b,t+2)*generateG(a,b,t-1)^2 -generateG(a,b,t-2)*generateG(a,b,t+1)^2; H2=subst(H2,x,xq,y,yq); H2=reduce(H2,I); L2=4*y*generateG(a,b,t)^3; L2=subst(L2,x,xq,y,yq); L2=reduce(L2,I); } J=Q1*L1-P1*H1,Q2*L2-P2*H2; if(pr>=5) { "we test now the different t, 00) { d=#[1]; } while(i<=d) { L=ellipticRandomCurve(N); if(L[3]>1){return(L[3]);} //the discriminant was not invertible P=list(0,L[2],1); j=0; M=1; while(jB) break; while(w*S[j](4-th root(N) +1)^2 - m*P=0=(0:1:0) - (m/q)*P=(x:y:z) and z a unit in Z/N Then N is prime. EXAMPLE:example ECPP; shows an example " { list L,S,P; bigint m,q; int i; bigint n=intRoot(intRoot(N)); n=(n+1)^2; //lower bound for q while(1) { L=ellipticRandomCurve(N); //a random elliptic curve C m=ShanksMestre(N,L[1],L[2],3); //number of points of the curve C S=PollardRho(m,10000,1); //factorization of m for(i=1;i<=size(S);i++) //search for q between the primes { q=S[i]; if(n0;i--) { if(s[i]=="a"){v[i]=0;} if(s[i]=="b"){v[i]=1;} if(s[i]=="c"){v[i]=2;} if(s[i]=="d"){v[i]=3;} if(s[i]=="e"){v[i]=4;} if(s[i]=="f"){v[i]=5;} if(s[i]=="g"){v[i]=6;} if(s[i]=="h"){v[i]=7;} if(s[i]=="i"){v[i]=8;} if(s[i]=="j"){v[i]=9;} if(s[i]=="k"){v[i]=10;} if(s[i]=="l"){v[i]=11;} if(s[i]=="m"){v[i]=12;} if(s[i]=="n"){v[i]=13;} if(s[i]=="o"){v[i]=14;} if(s[i]=="p"){v[i]=15;} if(s[i]=="q"){v[i]=16;} if(s[i]=="r"){v[i]=17;} if(s[i]=="s"){v[i]=18;} if(s[i]=="t"){v[i]=19;} if(s[i]=="u"){v[i]=20;} if(s[i]=="v"){v[i]=21;} if(s[i]=="w"){v[i]=22;} if(s[i]=="x"){v[i]=23;} if(s[i]=="y"){v[i]=24;} if(s[i]=="z"){v[i]=25;} if(s[i]==" "){v[i]=26;} } for(i=1;i<=size(s);i++) { n=n+v[i]*t^(i-1); } return(n); } static proc numberToWord(bigint n) { int i,j; string v; list s; bigint t=27; bigint mm; bigint nn=n; while(nn>t) { j++; mm=nn mod t; s[j]=mm; nn=(nn-mm) div t; } j++; s[j]=nn; for(i=1;i<=j;i++) { if(s[i]==0){v=v+"a";} if(s[i]==1){v=v+"b";} if(s[i]==2){v=v+"c";} if(s[i]==3){v=v+"d";} if(s[i]==4){v=v+"e";} if(s[i]==5){v=v+"f";} if(s[i]==6){v=v+"g";} if(s[i]==7){v=v+"h";} if(s[i]==8){v=v+"i";} if(s[i]==9){v=v+"j";} if(s[i]==10){v=v+"k";} if(s[i]==11){v=v+"l";} if(s[i]==12){v=v+"m";} if(s[i]==13){v=v+"n";} if(s[i]==14){v=v+"o";} if(s[i]==15){v=v+"p";} if(s[i]==16){v=v+"q";} if(s[i]==17){v=v+"r";} if(s[i]==18){v=v+"s";} if(s[i]==19){v=v+"t";} if(s[i]==20){v=v+"u";} if(s[i]==21){v=v+"v";} if(s[i]==22){v=v+"w";} if(s[i]==23){v=v+"x";} if(s[i]==24){v=v+"y";} if(s[i]==25){v=v+"z";} if(s[i]==26){v=v+" ";} } return(v); } proc code(string s) "USAGE: code(s); s a string ASSUME: s contains only small letters and space COMPUTE: a bigint, RSA-coding of the string s RETURN: return RSA-coding of the string s as string EXAMPLE: code; shows an example " { ring r=0,x,dp; bigint p=398075086424064937397125500550386491199064362342526708406385189575946388957261768583317; bigint q=472772146107435302536223071973048224632914695302097116459852171130520711256363590397527; bigint n=p*q; bigint phi=(p-1)*(q-1); bigint e=1234567891; //bigint d=extgcd(e,phi)[2]; bigint m=wordToNumber(s); bigint c=powerN(m,e,n); string cc=string(c); return(cc); } example {"EXAMPLE:"; echo = 2; string s="i go to school"; code(s); } proc decodeString(string g) "USAGE: decodeString(s); s a string ASSUME: s is a string of a bigint, the output of code COMPUTE: a string, RSA-decoding of the string s RETURN: return RSA-decoding of the string s as string EXAMPLE: decodeString; shows an example " { bigint p=398075086424064937397125500550386491199064362342526708406385189575946388957261768583317; bigint q=472772146107435302536223071973048224632914695302097116459852171130520711256363590397527; bigint n=p*q; bigint phi=(p-1)*(q-1); bigint e=1234567891; bigint d=extgcd(e,phi)[2]; execute("bigint c="+g+";"); bigint f=powerN(c,d,n); string s=numberToWord(f); return(s); } example {"EXAMPLE:"; echo = 2; string s="78638618599886548153321853785991541374544958648147340831959482696082179852616053583234149080198937632782579537867262780982185252913122030800897193851413140758915381848932565"; string t=decodeString(s); t; } /*---------------------------------------------------------------------------- * set stuff * -------------------------------------------------------------------------*/ static proc set_multiply_list_content(list h) "USAGE: set_multiply_list_content(h) RETURN: An integer c als product of all elements in h EXAMPLE: example set_multiply_list_content; shows an example; " { int c = 1; for (int i=1;i<=size(h);i++) { c = c*h[i]; } return(c); } example { "EXAMPLE:"; echo = 2; list h=2,4,5; set_multiply_list_content(h); } static proc set_delete_certain_element(list a, int e) "USAGE: set_delete_certain_element(a,e) RETURN: A list a without element e. If e was not in the list before, a will not be changed EXAMPLE: example set_delete_certain_element; shows an example. " { list output_list = a; for (int i=1;i<=size(a);i++) { if (a[i]==e) { output_list = delete(output_list,i); } } return(output_list); } example { "EXAMPLE:"; echo = 2; list h=2,4,5; set_delete_certain_element(h,4); set_delete_certain_element(h,10); } static proc set_bubblesort_int(list output_list) "USAGE: set_bubblesort_int(output_list) RETURN: An ascending sorted list with integer values. EXAMPLE: set_bubblesort_int; shows an example. " { output_list = bubblesort(output_list); //Cast every value into an integer for (int i=1; i<=size(output_list);i++) { output_list[i] = int(output_list[i]); } return(output_list); } example { "EXAMPLE:"; echo = 2; list output_list=10,4,5,24,9; set_bubblesort_int(output_list); } static proc set_is_set(list a) "USAGE: set_is_set(a) RETURN: 1 if the list is a set, 0 the list contains any duplicated elements EXAMPLE: set_is_set; shows an example. " { int i,v; for (v=1; v<=size(a); v++) { for (i=v+1; i<=size(a); i++) { if (a[i]==a[v]) { return(0); } } } return(1); } example { "EXAMPLE:"; echo = 2; list set = 1,5,10,2; list noset = 1,5,10,2,5; set_is_set(set); set_is_set(noset); } static proc set_contains(list a, int e) "USAGE: set_contains(a,e) RETURN: 1 if the list contains e, 0 otherwise EXAMPLE: set_contains; shows an example. " { for (int v=1; v<=size(a); v++) { if (a[v]==e) { return(1); } } return(0); } example { "EXAMPLE:"; echo = 2; list set = 1,5,10,2; set_contains(set,5); set_contains(set,40); } static proc set_delete_duplicates(list a) "USAGE: set_delete_duplicates(a) RETURN: a list a without any duplicated elements EXAMPLE: set_delete_duplicates; shows an example. " { int i; list output_list = a[1]; for (i=1; i<=size(a); i++) { if (set_contains(output_list,a[i])==0) { output_list = insert(output_list,a[i]); } } return(output_list); } example { "EXAMPLE:"; echo = 2; list set = 1,5,10,2,10,5; set_delete_duplicates(set); } static proc set_equals(list a,list b) "USAGE: set_equals(a, b) RETURN: 1 if the lists are equal from a set-structure standpoint, 0 otherwise EXAMPLE: set_equals; shows an example. " { //Checks if the lists have the same length if (size(a)!=size(b)) { return(0); } //Sorts the lists a = set_bubblesort_int(a); b = set_bubblesort_int(b); //Checks every single element of both lists for (int i=1; i<=size(a); i++) { if (a[i]!=b[i]) { return(0); } } return(1); } example { "EXAMPLE:"; echo = 2; list set1 = 1,5,10,2; list set2 = 10,2,5,1; list set3 = 1,5,9,2; set_equals(set1,set2); set_equals(set1,set3); } static proc set_insert(list a, int e) "USAGE: set_insert(a,e) RETURN: list a containing element e EXAMPLE: set_insert; shows an example. " { if(set_contains(a,e)) { return(a); } else { a=insert(a,e); return(a); } } example { "EXAMPLE:"; echo = 2; list set = 1,5,10,2; set_insert(set,5); set_insert(set,22); } static proc set_union(list a, list b) "USAGE: set_union(a, b) RETURN: list a as union of a and b EXAMPLE: set_union; shows an example. " { for (int i=1; i<=size(b); i++) { if (set_contains(a,b[i])==0) { a = insert(a,b[i]); } } return(a); } example { "EXAMPLE:"; echo = 2; list set1 = 1,5,10,2; list set2 = 5,10,93,58,29; set_union(set1,set2); } static proc set_section(list a, list b) "USAGE: set_section(a, b) RETURN: list output_list as intersection of a and b EXAMPLE: set_section; shows an example. " { list output_list; for (int i=1; i<=size(a); i++) { if (set_contains(b,a[i])==1) { output_list = insert(output_list,a[i]); } } return(output_list); } example { "EXAMPLE:"; echo = 2; list set1 = 1,5,10,2; list set2 = 5,10,93,58,29; set_section(set1,set2); } static proc set_list_delete_duplicates(list a) "USAGE: set_list_delete_duplicates(a) RETURN: list output_list with no duplicated lists EXAMPLE: set_list_delete_duplicates; shows an example. " { int v; int i; int counter; int out_size; list output_list=insert(output_list,a[1]); //Create a new list and try to insert every list element from a into that list. If a list is already inserted into the //new list, do nothing. for (i=2; i<=size(a); i++) { out_size = size(output_list); counter = 0; for (v=1; v<=out_size; v++) { if (set_equals(output_list[v],a[i])==1) { counter++; } } if (counter==0) { output_list = insert(output_list,a[i]); } } return(output_list); } example { "EXAMPLE:"; echo = 2; list set1 = 1,5,10,2; list set2 = 1,10,2,5; list set3 = 1,2,3; list superset = set1,set2,set3; set_list_delete_duplicates(superset); } static proc set_construct_increasing_set(int maxelement) "USAGE: set_construct_increasing_set(maxelement) RETURN: list output_list with increasing elements from 1 to maxelement EXAMPLE: set_construct_increasing_set; shows an example. " { list output_list; for (int i=1; i<=maxelement; i++) { output_list = insert(output_list, i); } return(output_list); } example { "EXAMPLE:"; echo = 2; set_construct_increasing_set(10); } static proc set_addtoall(list a, int element) "USAGE: set_addtoall(a,alement) RETURN: Transformed list with e_i+element for every element e_i in list a EXAMPLE: set_addtoall; shows an example. " { list output_list; int c; for (int i=1; i<=size(a); i++) { c = a[i]+element; output_list = insert(output_list,c); } return(set_turn(output_list)); } example { "EXAMPLE:"; echo = 2; list set = 1,5,10,2; set_addtoall(set,5); } static proc set_turn(list a) "USAGE: set_turn(a) RETURN: Turned list a EXAMPLE: set_turn; shows an example. " { list output_list; for (int i=1; i<=size(a); i++) { output_list[size(a)+1-i] = a[i]; } return(output_list); } example { "EXAMPLE:"; echo = 2; list set = 1,5,10; set_turn(set); } static proc set_subset_set(list a) "USAGE: set_subset_set(a) RETURN: Set of subsets EXAMPLE: set_subset_set; shows an example. " { int v; int choice; list output_list; list start = a[1]; list insertion_list; int output_length; output_list = insert(output_list,start); for (int i=2; i<=size(a); i++) { choice = 0; start = a[i]; output_list = insert(output_list,start); output_length = size(output_list); for (v=2; v<=output_length; v++) { insertion_list = set_insert(output_list[v],a[i]); output_list = insert(output_list, insertion_list,size(output_list)); } } return(output_list); } example { "EXAMPLE:"; echo = 2; list set = 1,5,10; set_subset_set(set); } /* ----------------------------------------------------------------- * knapsack_utilities: Utility functions needed for knapsack * -----------------------------------------------------------------*/ proc calculate_ordering(bigint num1, bigint primitive, bigint mod1) "USAGE: calculate_ordering(num1, primitive, mod1) RETURN: x so that primitive^x == num1 mod mod1 EXAMPLE: example calculate_ordering; shows an example; " { for (int i=1;i<=int((mod1-2));i++) { if ((primitive^i%mod1)==num1) { return(i); } } return(0); } example { "EXAMPLE:"; echo = 2; bigint mod1 = 33; bigint primitive = 14; bigint num1 = 5; calculate_ordering(num1,primitive,mod1); } proc is_primitive_root(bigint primitive, bigint mod1) "USAGE: is_primitive_root(primitive, mod1) RETURN: 1 if primitive is a primitive root modulo mod1, 0 otherwise EXAMPLE: example is_primitive_root; shows an example; " { list output_list; for (int i=1;i<=int((mod1-1));i++) { output_list = set_insert(output_list,int((primitive^i%mod1))); } if (bigint(size(output_list))==bigint(mod1-1)) { return(1); } else { return(0); } } example { "EXAMPLE:"; echo = 2; is_primitive_root(3,7); is_primitive_root(2,7); } proc find_first_primitive_root(bigint mod1) "USAGE: find_first_primitive_root(mod1) RETURN: First primitive root modulo mod1, 0 if no root can be found. EXAMPLE: example find_first_primitive_root; shows an example; " { for (int i=0;i<=int(mod1-1);i++) { if (is_primitive_root(bigint(i),mod1)==1) { return(i); } } return(0); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,lp; find_first_primitive_root(7); find_first_primitive_root(557); } proc binary_add(list binary_list) "USAGE: binary_add(binary_list) RETURN: binary encoded list, increased by 1 EXAMPLE: example binary_add; shows an example; " { int residual=1; int position = size(binary_list); while((residual==1)&&(position!=0)) { if(binary_list[position]==0) { binary_list[position]=1; residual=0; } else { binary_list[position]=0; position--; } } if (position==0) { binary_list = insert(binary_list,1); } return(binary_list); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,lp; list binary_list = 1,0,1,1,1; binary_add(binary_list); } proc inverse_modulus(int num, int mod1) "USAGE: inverse_modulus(num, mod1) RETURN: inverse element of num modulo mod1 EXAMPLE: example inverse_modulus; shows an example; " { if (num>=mod1) { return(0); } else { for (int i=1;i1;i--) { if(n%i==0) { prime1 = 0; } } return(prime1); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,lp; is_prime(10); is_prime(7); } proc find_biggest_index(list a) "USAGE: find_biggest_index( a) RETURN: Returns the index of the biggest element of a EXAMPLE: example find_biggest_index; shows an example; " { list sortedlist = bubblesort(a); return(find_index(a,sortedlist[1])); } proc find_index(list a, bigint e) "USAGE: find_index(a, e) RETURN: Returns the list index of element e in list a. Returns 0 if e is not in a EXAMPLE: example find_index; shows an example; " { for(int i=1;i<=size(a);i++) { if (bigint(a[i])==e) { return(i); } } return(0); } example { "EXAMPLE:"; echo = 2; list a = 1,5,20,6,37; find_index(a,20); find_index(a,6); find_index(a,100); } /* ------------------------------------------------------------------ * Knapsack Algorithmus such as solving several knapsack problems, * kryptographic algorithms and algorithms for creatings suitable knapsacks * ---------------------------------------------------------------- */ proc subset_sum01(list knapsack, int solution) "USAGE: subset_sum01(knapsack,solution) RETURN: binary list of the positions of the elements included in the subset sum or 0 if no solution exists NOTE: This will return the first solution of the ssk-problem, given be the smallest binary encoding. It wont return several solutions if they exist EXAMPLE: example subset_sum01; shows an example; " { int i; int v; int comparable; //Check if the knapsack is a set if (set_is_set(knapsack)==1) { //Create a binary list full of zeroes list binary_list; for (i=1;i<=size(knapsack);i++) { binary_list = insert(binary_list,0); } binary_list = binary_add(binary_list); for(i=1;i<=2^(size(knapsack));i++) { comparable = 0; //Create the Subset-Sum for the actual binary coding of binary_list for (v=1;v<=size(knapsack);v++) { comparable = comparable+knapsack[v]*binary_list[v]; } //Check if the sum equals the solution if (comparable==solution) { return(binary_list); } else { binary_list = binary_add(binary_list); } } return(0); } else { return(0); } } example { "EXAMPLE:"; echo = 2; list h=1,4,7,32; subset_sum01(h,20); subset_sum01(h,11); subset_sum01(h,33); } proc subset_sum02(list knapsack, int sol) "USAGE: subset_sum02(knapsack,sol) RETURN: binary list of the positions of the elements included in the subset sum or 0 if no solution exists EXAMPLE: example subset_sum02; shows an example; " { list summands; int calcu; int i; //Create a sorted copy of the knapsack, calling it worksack list worksack = set_bubblesort_int(knapsack); int counter = 1; while((counter<=size(worksack))&&(sol>0)) { //Try to substract an element of the knapsack from the capacity. Create a list with all the summands used calcu = sol-worksack[counter]; if (calcu>=0) { sol = sol-worksack[counter]; summands = insert(summands,int(worksack[counter])); } counter++; } if(sol>0) { return(0); } //Get the index of the summands of the original knapsack and change the bits in the binary list wich will be the solution list binary_list; for (i=1;i<=size(knapsack);i++) { binary_list = insert(binary_list,0); } for (i=1; i<=size(knapsack);i++) { if (set_contains(summands,knapsack[i])==1) { binary_list[i]=1; } } return(binary_list); } example { "EXAMPLE:"; echo = 2; list h=1,4,7,32; subset_sum02(h,20); subset_sum02(h,11); subset_sum02(h,33); } proc unbounded_knapsack(list knapsack, list profit, int capacity) "USAGE: unbounded_knapsack(knapsack,profit,capacity) RETURN: list of maximum profit of each iteration. For example, output_list[2] contains the maximum profit that can be achieved if the knapsack has capacity 2. EXAMPLE: unbounded_knapsack; shows an example; " { int i; int v; list output_list; for (i=1;i<=capacity+1;i++) { output_list = insert(output_list,0); } for (i=1;i<=capacity+1;i++) { for(v=1;v<=size(knapsack);v++) { if (knapsack[v]0) { y_list = nolist; for (i=1;i<=size(E);i++) { //Create all possible elements of y_i (y_list). minimax_list will be replaced of an empty list in each iteration minmax_list = nolist; for (v=1; v<=size(capacities);v++) { if (set_contains(E,v)==1) { minmax_list = insert(minmax_list, bigint(capacities[v])/bigint(m[v,E[i]])); } } //Sort the elements so that it is easy to pick the smallest one minmax_list = bubblesort(minmax_list); //insert Element y_i into y_list, wich is the smallest of (b_i/w_ij) like in the PECH algorithm description. y_list = insert(y_list,minmax_list[size(minmax_list)],size(y_list)); } //Check if all y_i in y_list are smaller than 1. If so, every additional selection will exceed the capacity and the algorithm stops. checkint=0; for(i=1;i<=size(y_list);i++) { if (y_list[i]>=1) { checkint=1; } } if (checkint==0) { return(output_list); } //Find the index of the selection and update the binary output_list minmax_list = nolist; for (i=1;i<=size(E);i++) { minmax_list = insert(minmax_list, profits[E[i]]*y_list[i],size(minmax_list)); } index = find_biggest_index(minmax_list); output_list[E[index]]=1; //Update the capacities by substracting the weights of the selection for (i=1;i<=size(capacities);i++) { capacities[i] = capacities[i]- m[i,E[index]]; } E = set_delete_certain_element(E,index); } return(output_list); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,lp; matrix m[3][3] = 1,4,10,7,8,3,1,9,7; list c = 12,17,10; list p = 3,2,5; multidimensional_knapsack(m,c,p); } proc naccache_stern_generation(int key, int primenum) "USAGE: naccache_stern_generation(key, primenum) RETURN: a hard knapsack list EXAMPLE: example naccache_stern_generation; shows an example; " { //Check if primenum is a prime and the gcd-Condition holds if ((is_prime(primenum)==0)||(gcd(key,(primenum-1))!=1)) { return(0); } else { int i; int p; list primelist; int primecounter=2; //Generate the knapsack containing the smallest prime numbers so that primenum exceeds the product of all of them while(set_multiply_list_content(primelist)=1;i--) { new_element = calculate_ordering(knapsack[i],primitive,mod1); output_list = insert(output_list,int(new_element)); } return(output_list); } example { "EXAMPLE:"; echo = 2; //Please note that the values for primenum and hardknapsack have been obtained from the example of naccache_stern_generation and naccache_stern_encryption! list knapsack = 2,3,5,7; int mod1 = 211; int primitive = 2; m_merkle_hellman_transformation(knapsack,primitive,mod1); } proc m_merkle_hellman_encryption(list knapsack, list message) "USAGE: m_merkle_hellman_encryption(knapsack, message) RETURN: an encrypted message as integer NOTE: This works in the same way as merkle_hellman_encryption. The additional function is created to keep consistency with the needed functions for every kryptosystem. EXAMPLE: example m_merkle_hellman_encryption; shows an example; " { return(merkle_hellman_encryption(knapsack,message)); } example { "EXAMPLE:"; echo = 2; //Please note that the values for primenum and hardknapsack have been obtained from the example of m_merkle_hellman_transformation! list knapsack = 1,43,132,139; list message = 1,0,0,1; m_merkle_hellman_encryption(knapsack,message); } proc m_merkle_hellman_decryption(list knapsack, bigint primitive, bigint mod1, int message) "USAGE: m_merkle_hellman_decryption(knapsack, primitive, mod1, message) RETURN: decrypted binary list EXAMPLE: example merkle_hellman_decryption; shows an example; " { //Convert message int factorizing = int((primitive^message)%mod1); int i; //Create binary list of length of the knapsack, containing zeroes. list binary_list; for (i=1;i<=size(knapsack);i++) { binary_list = insert(binary_list,0); } //factorize the converted message, mark the factor positions in knapsack as bits in binary_list for (i=1;i<=size(knapsack);i++) { if(factorizing%knapsack[i]==0) { binary_list[i]=1; } } return(binary_list); } example { "EXAMPLE:"; echo = 2; //Please note that the values have been obtained from the example of m_merkle_hellman_encryption and m_merkle_hellman_transformation! list knapsack = 2,3,5,7; int message = 140; bigint primitive = 2; bigint mod1 = 211; m_merkle_hellman_decryption(knapsack,primitive,mod1,message); } proc merkle_hellman_transformation(list knapsack, int key, int mod1) "USAGE: merkle_hellman_transformation(knapsack, key, mod1) RETURN: hard knapsack EXAMPLE: example merkle_hellman_transformation; shows an example; " { list output_list; int new_element; //transform every element in the knapsack with normal strong modular multiplication for (int i=size(knapsack);i>=1;i--) { new_element=knapsack[i]*key%mod1; output_list = insert(output_list,new_element); } return(output_list); } example { "EXAMPLE:"; echo = 2; list knapsack = 1,3,5,12; int key = 3; int mod1 = 23; merkle_hellman_transformation(knapsack,key,mod1); } proc merkle_hellman_encryption(list knapsack, list message) "USAGE: merkle_hellman_encryption(knapsack, message) RETURN: encrypted integer EXAMPLE: example merkle_hellman_encryption; shows an example; " { int solution = 0; if (size(knapsack)!=size(message)||(set_is_set(knapsack)==0)) { return(0); } else { for (int i=1;i<=size(knapsack);i++) { solution = solution+knapsack[i]*message[i]; } return(solution); } } example { "EXAMPLE:"; echo = 2; //Please note that the values have been obtained from the example of merkle_hellman_transformation! list hardknapsack =3,9,15,13; list message = 0,1,0,1; merkle_hellman_encryption(hardknapsack,message); } proc merkle_hellman_decryption(list knapsack, int key, int mod1, int message) "USAGE: merkle_hellman_decryption(knapsack, key, mod1, message) RETURN: decrypted binary list EXAMPLE: example merkle_hellman_decryption; shows an example; " { int new_element; int t = inverse_modulus(key,mod1); int transformed_message; list binary_list; if ((set_is_set(knapsack)==1)&&(key=1;i--) { new_element=knapsack[i]*t%mod1; easy_knapsack = insert(easy_knapsack,new_element); } //solve the easy knapsack problem with subset_sum01 or subset_sum02 transformed_message = (message*t)%mod1; transformed_message; binary_list = subset_sum01(easy_knapsack,transformed_message); return(binary_list) } else { return(0) } } example { "EXAMPLE:"; echo = 2; //Please note that the values have been obtained from the example of merkle_hellman_decryption and merkle_hellman_transformation! list hardknapsack =3,9,15,13; int key = 3; int message = 22; int mod1 = 23; merkle_hellman_decryption(hardknapsack, key, mod1, message); } proc super_increasing_knapsack(int ksize) "USAGE: super_increasing_knapsack(ksize) RETURN: super-increasing knapsack list EXAMPLE: super_increasing_knapsack; shows an example; " { list output_list = insert(output_list,1); int next_element; for (int i=2; i<=ksize; i++) { next_element = calculate_max_sum(output_list)+1; output_list = insert(output_list,next_element); } return(output_list); } example { "EXAMPLE:"; echo = 2; super_increasing_knapsack(10); } proc h_increasing_knapsack(int ksize, int h) "USAGE: h_increasing_knapsack(ksize, h) RETURN: h-increasing knapsack list EXAMPLE: h_increasing_knapsack; shows an example; " { int v; if (ksize<=h+1) { return(set_turn(super_increasing_knapsack(ksize))) } else { list out = set_turn(super_increasing_knapsack(h+1)); int next_element; for (int i=h+2; i<=ksize; i++) { next_element = 0; for (v=i-h; v<=i-1; v++) { next_element = next_element+out[v]; } next_element++; out = insert(out,next_element,size(out)); } return(out); } } example { "EXAMPLE:"; echo = 2; h_increasing_knapsack(10,5); } proc injective_knapsack(int ksize, int kmaxelement) "USAGE: injective_knapsack(ksize, kmaxelement) RETURN: list of injective knapsacks with maximal element kmaxelement and size ksize EXAMPLE: injective_knapsack; shows an example; " { //Create a List of size ksize with the greatest possible elements keeping the set structure list list_of_lists; list A = insert(A,kmaxelement); int i; for (i=2;i<=ksize;i++) { A = insert(A,kmaxelement-(i-1)); } A = set_turn(A); list_of_lists = insert(list_of_lists,A); //Create all possible sets containing the possible elements of A int residual; int position; while(A[1]==kmaxelement) { residual=3; position = ksize; while((residual!=0)) { if(A[position]==1) { A[position]=kmaxelement-position+1; residual=1; position--; } else { A[position]=A[position]-1; residual=0; } } //Insert the list into the overall list if its a set if (set_is_set(A)==1) { list_of_lists = insert(list_of_lists,A); } } //delete the first element since it is smaller than kmaxelement list_of_lists = delete(list_of_lists,1); //delete duplicates list_of_lists = set_list_delete_duplicates(list_of_lists); //Check if the remaining knapsacks are injective list output_list; for(i=1;i<=size(list_of_lists);i++) { if (set_is_injective(list_of_lists[i])==1) { output_list=insert(output_list,list_of_lists[i]); } } return(output_list); } example { "EXAMPLE:"; echo = 2; injective_knapsack(3,9); } proc calculate_max_sum(list a) "USAGE: calculate_max_sum(a) RETURN: sum of all elements in a EXAMPLE: calculate_max_sum; shows an example; " { int sum = a[1]; for (int i=2; i<=size(a);i++) { sum = sum+a[i]; } return(sum); } example { "EXAMPLE:"; echo = 2; list a = 1,5,3,2,12; calculate_max_sum(a); } proc set_is_injective(list a) "USAGE: set_is_injective(a) RETURN: 1 if a is injective, 0 otherwise EXAMPLE: set_is_injective; shows an example; " { //Create all subsets of the set a list subsum = set_subset_set(a); list checklist=calculate_max_sum(subsum[1]); int calculator; for (int i=2; i<=size(subsum);i++) { //calculate the maximal subset_sum for every subset. Check if there are duplicated subset_sums. If so, a is not injective calculator = calculate_max_sum(subsum[i]); if (set_contains(checklist, calculator)) { return(0); } else { checklist = insert(checklist,calculator); } } return(1); } example { "EXAMPLE:"; echo = 2; list inj = 1,5,7,41; list non_inj = 1,2,3,4; set_is_injective(inj); set_is_injective(non_inj); } proc is_h_injective(list a, int h) "USAGE: is_h_injective(a, h) RETURN: 1 if a is h-injective, 0 otherwise EXAMPLE: is_h_injective; shows an example; " { //Create all sets of subsets list subsetlist = set_subset_set(a); list h_subsetlist; //delete every list with elements more than h+1 since they are not needed to check h-injectivity for (int i=1; i<=size(subsetlist); i++) { if(size(subsetlist[i])<=h) { h_subsetlist = insert(h_subsetlist,subsetlist[i]); } } //Check if the remaining max_sums do not occure more than once list checklist=calculate_max_sum(h_subsetlist[1]); int calculator; for (i=2; i<=size(h_subsetlist);i++) { calculator = calculate_max_sum(h_subsetlist[i]); if (set_contains(checklist, calculator)==1) { return(0); } else { checklist = insert(checklist,calculator); } } return(1); } example { "EXAMPLE:"; echo = 2; list h_inj = 1,2,4,10,17; is_h_injective(h_inj,3); //1+2+4+10=17 is_h_injective(h_inj,4); } proc is_fix_injective(list a) "USAGE: is_fix_injective(a) RETURN: 1 if a is fix-injective, 0 otherwise EXAMPLE: is_fix_injective; shows an example; " { //Generation of the list-list-list list subsetlist = set_subset_set(a); list alreadycreatedlist; list listoflists; list emptylist1; list worklist; int i; int v; list checklist; int calculator; int set_destination; //create list of lists wich contain the lists of a certain length as elements for (i = 1; i<= size(subsetlist); i++) { //Determine the size of the acutal list to choose where to insert it in the listoflists set_destination = size(subsetlist[i]); if (set_contains(alreadycreatedlist,set_destination)==1) { //There is already an element with the same set size, so just insert it listoflists[set_destination] = insert(listoflists[set_destination],subsetlist[i]); } else { //There is not yet an element with the same set size, so create a new one listoflists[set_destination] = insert(emptylist1,subsetlist[i]); alreadycreatedlist = set_insert(alreadycreatedlist,set_destination ); } } //Check for injectivity of each seperate list. Works as in injectivity or h-injectivity for (v=1; v<=size(listoflists); v++) { worklist = listoflists[v]; checklist=calculate_max_sum(worklist[1]); for (i=2; i<=size(worklist); i++) { calculator = calculate_max_sum(worklist[i]); if (set_contains(checklist, calculator)==1) { return(0); } else { checklist = insert(checklist,calculator); } } } return(1); } example { "EXAMPLE:"; echo = 2; //this is fix-injective because 17=10+2+4+1 with different numbers of addens. list fix_inj = 1,2,4,10,17; //this is not fix-injective because 4+1=2+3. list not_fix_inj = 1,2,3,4; is_fix_injective(fix_inj); is_fix_injective(not_fix_inj); } proc three_elements(list out, int iterations) "USAGE: three_elements(out, iterations) RETURN: Injective_knapsack created with the three elements method EXAMPLE: three_elements; shows an example; " { int a; int b; int c; int subsum; int adden = 1; int condition = 0; out = set_turn(out); if (set_is_injective(out)==0) { return(0); } else { for (int i=1; i<=iterations; i++) { while(condition==0) { subsum = calculate_max_sum(out); a = 2*subsum+adden; b = a+subsum+adden; c = b+subsum+1; if ((a+b)>(c+subsum)) { condition=1; } else { adden++; } } adden =1; condition=0; out=set_insert(out, a); out=set_insert(out, b); out=set_insert(out, c); } return(out); } } example { "EXAMPLE:"; echo = 2; //this is fix-injective because 17=10+2+4+1 with different numbers of addens. list super_increasing = 1,2,4,10,20; list a = three_elements(super_increasing,2); a; set_is_injective(a); } /* //=============================================================== //======= Example for DSA ===================================== //=============================================================== Suppose a file test is given.It contains "Oscar". //Hash-function MD5 under Linux md5sum test 8edfe37dae96cfd2466d77d3884d4196 //================================================================ ring R=0,x,dp; number q=2^19+21; //524309 number o=2*3*23*number(7883)*number(16170811); number p=o*q+1; //9223372036869000547 number b=2; number g=power(2,o,p); //8308467587808723131 number a=111111; number A=power(g,a,p); //8566038811843553785 number h =decimal("8edfe37dae96cfd2466d77d3884d4196"); //189912871665444375716340628395668619670 h= h mod q; //259847 number k=123456; number ki=exgcd(k,q)[1]; //50804 //inverse von k mod q number r= power(g,k,p) mod q; //76646 number s=ki*(h+a*r) mod q; //2065 //========== signatur is (r,s)=(76646,2065) ===================== //==================== verification ============================ number si=exgcd(s,q)[1]; //inverse von s mod q number e1=si*h mod q; number e2=si*r mod q; number rr=((power(g,e1,p)*power(A,e2,p)) mod p) mod q; //76646 //=============================================================== //======= Example for knapsack ================================ //=============================================================== ring R=(5^5,t),x,dp; R; // # ground field : 3125 // primitive element : t // minpoly : 1*t^5+4*t^1+2*t^0 // number of vars : 1 // block 1 : ordering dp // : names x // block 2 : ordering C proc findEx(number n, number g) { int i; for(i=0;i<=size(basering)-1;i++) { if(g^i==n){return(i);} } } number g=t^3; //choice of the primitive root findEx(t+1,g); //2091 findEx(t+2,g); //2291 findEx(t+3,g); //1043 intvec b=1,2091,2291,1043; // k=4 int z=199; intvec v=1043+z,1+z,2091+z,2291+z; //permutation pi=(0123) v; 1242,200,2290,2490 //(1101)=(e_3,e_2,e_1,e_0) //encoding 2490+2290+1242=6022 und 1+1+0+1=3 //(6022,3) decoding: c-z*c'=6022-199*3=5425 ring S=5,x,dp; poly F=x5+4x+2; poly G=reduce((x^3)^5425,std(F)); G; //x3+x2+x+1 factorize(G); //[1]: // _[1]=1 // _[2]=x+1 // _[3]=x-2 // _[4]=x+2 //[2]: // 1,1,1,1 //factors x+1,x+2,x+3, i.e. (1110)=(e_pi(3),e_pi(2),e_pi(1),e_pi(0)) //pi(0)=1,pi(1)=2,pi(2)=3,pi(3)=0 gives: (1101) */ singular-4.0.3+ds/Singular/LIB/curvepar.lib000066400000000000000000001165641266270727000205030ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////////// version="version curvepar.lib 4.0.0.0 Jun_2013 "; // $Id: 6132b803aac5fe11ce68c0a516c601f9ce70e756 $ category="Singularity Theory"; info=" LIBRARY: curvepar.lib Resolution of space curve singularities, semi-group AUTHOR: Gerhard Pfister email: pfister@mathematik.uni-kl.de Nil Sahin email: e150916@metu.edu.tr Maryna Viazovska email: viazovsk@mathematik.uni-kl.de SEE ALSO: spcurve_lib PROCEDURES: BlowingUp(f,I,l); BlowingUp of V(I) at the point 0; CurveRes(I); Resolution of V(I) CurveParam(I); Parametrization of algebraic branches of V(I) WSemigroup(X,b); Weierstrass semigroup of the curve primparam(x,y,c); HN matrix of parametrization(x(t),y(t)) MultiplicitySequence(I); Multiplicity sequences of the branches of plane curve V(I) CharacteristicExponents(I); Characteristic exponents of the branches of plane curve V(I) IntersectionMatrix(I); Intersection Matrix of the branches of plane curve V(I) ContactMatrix(I); Contact Matrix of the branches of plane curve V(I) plainInvariants(I); Invariants of the branches of plane curve V(I) "; LIB "sing.lib"; LIB "primdec.lib"; LIB "linalg.lib"; LIB "ring.lib"; LIB "alexpoly.lib"; LIB "matrix.lib"; ////////////////////////////////////////////////////////////// //----------Resolution of singular curve--------------------// ////////////////////////////////////////////////////////////// proc BlowingUp(poly f,ideal I,list l,list #) "USAGE: BlowingUp(f,I,l); f=poly b=ideal l=list ASSUME: The basering is r=0,(x(1..n),a),dp f is an irrreducible polynomial in k[a], I is an ideal of a curve(if we consider a as a parameter) COMPUTE: Blowing-up of the curve at point 0. RETURN: list C of charts. Each chart C[i] is a list of size 5 (reps. 6 in case of plane curves) C[i][1] is an integer j. It shows, which standard chart do we consider. C[i][2] is an irreducible poly g in k[a]. It is a minimal polynomial for the new parameter. C[i][3] is an ideal H in k[a]. c_i=F_i(a_new) for i=1..n, a_old=H[n+1](a_new). C[i][4] is a map teta:k[x(1)..x(n),a]-->k[x(1)..x(n),a] from the new curve to the old one. x(1)-->x(j)*x(1) . . . x(j)-->x(j) . . . x(n)-->x(j)*(c_n+x(n)) C[i][5] is an ideal J of a new curve. J=teta(I). C[i][6] is the list of exceptional divisors in the chart EXAMPLE: example BlowingUp; shows an example" { def r=basering; int n=nvars(r)-1; ring r1=(0,a),(x(1..n)),ds; number f=leadcoef(imap(r,f)); minpoly=f; ideal I=imap(r,I); ideal locI=std(I); ideal J=tangentcone(I); setring r; ideal J=imap(r1,J); ideal locI=imap(r1,locI); int j; int i; list C,E; list C1; ideal B; poly g; ideal F; poly b,p; list Z; list Z1; ideal D; map teta; ideal D1; map teta1; int k,e; ideal I1; ideal I2; int ind; list w=mlist(l,n); for(j=1;j<=n;j++) { B=J; for(i=1;i0) { E=#; E=teta(E); for(e=1;e<=size(E);e++) { p=E[e]; while(subst(p,x(w[j]),0)==0) { p=p/x(w[j]); } if((deg(E[e])>0)&&(deg(p)==0)) { E[e]=size(E); } else { E[e]=p; } } E[size(E)+1]=x(w[j]); C1[6]=E; } else { C1[6]=list(x(w[j])); } } C=insert(C,C1); } } return(C); } example { "EXAMPLE:";echo = 2; ring r=0,(x(1..3),a),dp; poly f=a2+1; ideal i=x(1)^2+a*x(2)^3,x(3)^2-x(2); list l=1,3,2; list B=BlowingUp(f,i,l); B; } //============= ACHTUNG ZeroIdeal ueberarbeiten / minAssGTZ rein ======================== ////////////////////////////////////////////////////////////////////////////////////////// static proc ZeroIdeal(ideal J) "USAGE: ZeroIdeal(J); J=ideal ASSUME: J is a zero-dimensional ideal in k[x(1),...,x(n)]. COMPUTE: Primary decomposition of radical(J). Each prime ideal J[i] has the form: x(1)-f[1](b),...,x(n)-f[n](b), f(b)=0, f irreducible for some b=x(1)*a(1)+...+x(n)*a(n), a(i) in k. RETURN: list Z of lists. Each list Z[k] is a list of size 3 Z[k][1] is a poly f(b) Z[k][2] is an ideal H, H[n]=f[n], Z[k][3] is a poly x(1)*a(1)+...+x(n)*a(n) EXAMPLE:" { intvec opt = option(get); def r=basering; int n=nvars(r); if(dim(std(J))!=0){return(0);} ring s=0,(x(1..n)),lp; ideal A; ideal S; int i; int j; for(i=1;i<=n;i++) {A[i]=x(i);} map phi=r,A; ideal J=phi(J); ideal I=radical(J); list D=zerodec(I); list Z; ideal H; intvec w; intvec v; int ind; ideal T; map tau; int q; list u; ideal Di; poly h; for(i=1;i<=size(D);i++) { option(redSB); ind=0;q=n; while(ind==0 and q>0) { for(j=1;j<=n;j++){T[j]=x(j);} T[q]=x(n); T[n]=x(q); tau=s,T; Di=D[i]; S=std(tau(Di)); ind=1; v=leadexp(S[1]); if(leadmonom(S[1])!=x(n)^v[n]){ind=0;} for(j=2;j<=n;j++) { if(leadmonom(S[j])!=x(n-j+1)){ind=0;} H[n-j+1]= -S[j]/leadcoef(S[j])+x(n-j+1); v=leadexp(H[n-j+1]); if(leadcoef(H[n-j+1])*leadmonom(H[n-j+1])!=leadcoef(H[n-j+1])*x(n)^v[n]) {ind=0;} } if(ind==1) { u[1]=S[1]; H[n]=x(n); H[n]=H[q]; H[q]=x(n); u[2]=H; u[3]=x(q); Z[i]=u; } q--; } if(ind==0) { vector a; while(ind==0) { h=x(n); for(j=1;j<=n-1;j++){a=a+random(-10,10)*gen(j);h=h+a[j]*x(j);} T=subst(S,x(n),h); option(redSB); T=std(T); ind=1; w=leadexp(T[1]); if(leadmonom(T[1])!=x(n)^w[n]){ind=0;} for(j=2;j<=n;j++) { if(leadmonom(T[j])!=x(n-j+1)){ind=0;} H[n-j+1]= -T[j]/leadcoef(T[j])+x(n-j+1); w=leadexp(H[n-j+1]); if(leadmonom(H[n-j+1])*leadcoef(H[n-j+1])!=leadcoef(H[n-j+1])*x(n)^w[n]) {ind=0;} } if(ind==1) { list l; l[1]=T[1]; H[n]=x(n);h=x(n); for(j=1;j<=n-1;j++){H[n]=H[n]+a[j]*H[j];h=h-a[j]*x(j);} l[2]=H; l[3]=h; Z[i]=l; } } } } setring r; ideal A; list Z; for(i=1;i<=n;i++) {A[i]=var(i);} map psi=s,A; Z=psi(Z); option(set, opt); return(Z); } ///////////////////////////////////////////////////////////////////////////////////////////// //assume that the basering is k[x(1),...,x(n),a] static proc main(ideal I,ideal Psi,poly f,list m,list l,list HN,intvec v,list HI,list #) { def s=basering; int i,z; int j; list C,E,resTree; list C1; list C2; list C3; list l1; C2[8]=HI; list m1; list HN1; ideal J; map psi; intvec w; z=(SmoothTest(I,f)==1); if((nvars(basering)==3)&&z&&(size(#)>0)) { z=transversalTest(I,f,#); } if(z) { C2[1]=I; C2[2]=Psi; C2[3]=f; C2[4]=m; C2[5]=l; C2[6]=HN; if(nvars(basering)==3) { if(size(#)>0) { C2[9]=#; } C2[7]=v; } //C2[8][size(C2[8])+1]=list(C2[7],C2[9]); C[1]=C2; } if(!z) { int mm=mmult(I,f); m1=insert(m,mm,size(m)); if(nvars(basering)==3) { if(size(#)>0) { E=#; C1=BlowingUp(f,I,l,E); } else { C1=BlowingUp(f,I,l); } } else { C1=BlowingUp(f,I,l); } for(j=1;j<=size(C1);j++) { C2[1]=C1[j][5]; J=C1[j][4]; psi=s,J; C2[2]=psi(Psi); C2[3]=C1[j][2]; C2[4]=m1; l1=insert(l,C1[j][1],size(l)); C2[5]=l1; HN1=psi(HN); HN1=insert(HN1,C1[j][3],size(HN1)-1); C2[6]=HN1; if(deg(C2[3])>1) { w=v,-j; } else { w=v,j; } C2[7]=w; if(nvars(basering)==3) { C2[9]=C1[j][6]; C2[8][size(C2[8])+1]=list(C2[7],C2[9]); C3=main(C2[1],C2[2],C2[3],C2[4],C2[5],C2[6],C2[7],C2[8],C2[9]); C=C+C3; } else { C3=main(C2[1],C2[2],C2[3],C2[4],C2[5],C2[6],C2[7],C2[8]); C=C+C3; } } } return(C); } //////////////////////////////////////////////////////////////////////////////////////////////// static proc transversalTest(ideal I,poly f,list L) { def r=basering; int n=nvars(r)-1; int i; ring r1=(0,a),(x(1..n)),ds; number f=leadcoef(imap(r,f)); minpoly=f; ideal I=imap(r,I); list L=imap(r,L); ideal K=jet(L[size(L)],deg(lead(L[size(L)]))); ideal T=1; if(size(L)>1) { for(i=1;i<=size(L)-1;i++) { if(subst(L[i],x(1),0,x(2),0)==0) break; } if(i<=size(L)-1) { T=jet(L[i],deg(lead(L[i]))); } } ideal J=jet(I[1],deg(lead(I[1]))); setring r; ideal J=imap(r1,J); ideal K=imap(r1,K); ideal T=imap(r1,T); int m=size(reduce(J,std(K)))+size(reduce(K,std(J))); if(m) { m=size(reduce(J+K+T,std(ideal(x(1),x(2))))); } return(m); } //////////////////////////////////////////////////////////////////////////////////////////////// static proc SmoothTest(ideal I,poly f) //Assume I is a radical ideal of dimension 1 in a ring k[x(1..n),a] //Returns 1 if a curve V(I) is smooth at point 0 and returns 0 otherwise { int ind; int l; def t=basering; int n=nvars(t)-1; ring r1=(0,a),(x(1..n)),dp; number f=leadcoef(imap(t,f)); minpoly=f; ideal I=imap(t,I); matrix M=jacob(I); for(l=1;l<=n;l++){M=subst(M,x(l),0);} if(mat_rk(M)==(n-1)){ind=1;} return(ind); } //////////////////////////////////////////////////////////////////////////////////////////////// proc CurveRes(ideal I) "USAGE: CurveRes(I); I ideal ASSUME: The basering is r=0,(x(1..n)) V(I) is a curve with a singular point 0. COMPUTE: Resolution of the curve V(I). RETURN: a ring R=basering+k[a] Ring R contains a list Resolve Resolve is a list of charts Each Resolve[i] is a list of size 6 Resolve[i][1] is an ideal J of a new curve. J=teta(I). Resolve[i][2] ideal which represents the map teta:k[x(1)..x(n),a]-->k[x(1)..x(n),a] from the new curve to the old one. Resolve[i][3] is an irreducible poly g in k[a]. It is a minimal polynomial for the new parameter a. deg(g) gives the number of branches in Resolve[i] Resolve[i][4] sequence of multiplicities (sum over all branches in Resolve as long as they intersect each other !) Resolve[i][5] is a list of integers l. It shows, which standard charts we considered. Resolve[i][6] HN matrix Resolve[i][7] (only for plane curves) the development of exceptional divisors the entries correspond to the i-th blowing up. The first entry is an intvec. The first negative entry gives the splitting of the (over Q irreducible) branches. The second entry is a list of the exceptional divisors. If the entry is an integer i, it says that the divisor is not visible in this chart after the i-th blowing up. EXAMPLE: example CurveRes; shows an example" { def r=basering; int n=nvars(r); ring s=0,(x(1..n),a),dp; ideal A; int i; int j; for(i=1;i<=n;i++){A[i]=x(i);} map phi=r,A; ideal I=phi(I); poly f=a; list l; list m; list HN=x(1); ideal psi; for(i=1;i<=n;i++){psi[i]=x(i);} psi[n+1]=a; intvec v; list L,Resolve; if(n==2) { ideal J=factorize(I[1],1); list resolve; for(int k=1;k<=size(J);k++) { I=J[k]; resolve=main(I,psi,f,m,l,HN,v,L); for(i=1;i<=size(resolve);i++) { resolve[i][6]=delete(resolve[i][6],size(resolve[i][6])); if(size(resolve[i])>=9){resolve[i]=delete(resolve[i],9);} resolve[i]=delete(resolve[i],7); } if(k==1){Resolve=resolve;} else{Resolve=Resolve+resolve;} } } else { Resolve=main(I,psi,f,m,l,HN,v,L); for(i=1;i<=size(Resolve);i++) { Resolve[i][6]=delete(Resolve[i][6],size(Resolve[i][6])); Resolve[i]=delete(Resolve[i],8); } } export(Resolve); return(s); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; ideal i=x2-y3,z2-y5; def s=CurveRes(i); setring s; Resolve; } ////////////////////////////////////////////////////////////////// static proc mlist(list l,int n) { list N; list M; int i; int j; for(i=1;i<=n;i++) {M[i]=i;} N=l+M; for(i=1;i<=size(N)-1;i++) { j=i+1; while(j<=size(N)) { if(N[i]==N[j]){N=delete(N,j);} else {j++;} } } return(N); } ///////////////////////////////////////////////////////////////////// //Assume that the basering is k[x(1..n),a] static proc mmult(ideal I,poly f) { def r=basering; int n=nvars(r)-1; ring r1=(0,a),(x(1..n)),ds; number f=leadcoef(imap(r,f)); minpoly=f; ideal I=imap(r,I); int m=mult(std(I)); return(m); } ////////////////////////////////////////////////////////////// //--------Parametrization of smooth curve-------------------// ////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //computes jacobian matrix, considering x(1..n) as variables and a(1..m) as parameters static proc mjacob(ideal I) { def r=basering; int n=nvars(r); int k=size(I); matrix M[k][n]; int i; int j; int l; for(i=1;i<=k;i++) { for(j=1;j<=n;j++) { M[i,j]=diff(I[i],x(j)); for(l=1;l<=n;l++){M[i,j]=subst(M[i,j],x(l),0);} } } return(M); } ////////////////////////////////////////////////////////// static proc mmi(matrix M,int n) { ideal l; int k=nrows(M); int i; int j; for(i=1;i<=k;i++) { l[i]=0; for(j=1;j<=n;j++) { l[i]=l[i]+x(j)*M[i,j]; } } l=std(l); int t=size(l); i=1; int mi=0; while( mi==0 and i<=n-1) { if(diff(l[i],x(n-i))!=0){mi=n-i+1;} else{i++;} } if(mi==0){mi=1;} matrix Mi[k][n-1]; for(i=1;i<=k;i++) { for(j=1;j<=mi-1;j++) { Mi[i,j]=M[i,j]; } for(j=mi;j<=n-1;j++) { Mi[i,j]=M[i,j+1]; } } list lmi=mi,Mi; return(lmi); } ////////////////////////////////////////////////////////// static proc mC(matrix Mi,int n) { int k=nrows(Mi); ideal c; int i,j; for(i=1;i<=n-1;i++) { c[i]=0; for(j=1;j<=k;j++) { c[i]=c[i]+y(j)*Mi[j,i]; } } c=std(c); return(c); } ////////////////////////////////////////////////////////// static proc mmF(ideal C, matrix Mi,int n,int k) { int s=size(C); intvec mf; int p=0; int t=0; int i; int j; int v=0; for(i=s;i>0;i--) { p=t; j=1; while(t==p and p+j<=k) { if(diff(C[i],y(p+j))==0){j++;} if(diff(C[i],y(p+j))!=0){t=p+j;v++;mf[v]=t;} } } matrix B[n-1][n-1]; for(i=1;i<=n-1;i++) { for(j=1;j<=n-1;j++) { B[i,j]=Mi[ mf[i],j]; } } list mmf=mf,B; return(mmf); } ///////////////////////////////////////////////////// static proc cparam(ideal I,poly f,int n,int m,int N) { def r=basering; ring s=(0,a),(x(1..n)),lp; number f=leadcoef(imap(r,f)); minpoly=f; ideal I=imap(r,I); matrix M=mjacob(I); list l0=mmi(M,n); int mi=l0[1]; matrix Mi=l0[2]; int k=nrows(Mi); ring q=(0,a),(y(1..k)),lp; number f=leadcoef(imap(r,f)); minpoly=f; matrix Mi=imap(s,Mi); ideal D=mC(Mi,n); list l1=mmF(D,Mi,n,k); intvec mf=l1[1]; matrix B=l1[2]; setring s; matrix B=imap(q,B); matrix C=inverse(B); int i; int j; ideal P; for(i=1;i0) { if(size(L[i-G[j]])>0) { for(t=1;t<=size(L[i-G[j]]);t++) { v=L[i-G[j]][t]; p=1; for(q=1;q0){p=0;} } if(p==1){v[j]=v[j]+1;L[i]=insert(L[i],v);} } } } } if(size(L[i])>0){s1=1;} s=s1*(s+1); s1=0; i++; } intvec Gmin; int jmin=1; for(j=1;j<=k;j++) { if(size(L[G[j]])==size(L1[G[j]]) && G[j]0) { for(j=1;j<=size(L[i]);j++) { v=L[i][j]; v[k+1]=0; L[i][j]=v; } } } intvec w; w[k+1]=1; L[g]=insert(L[g],w); int s=0; int s1=0; i=1; while(i<=b and s0) { if(size(L[i-g])>0) { for(j=1;j<=size(L[i-g]);j++) { v=L[i-g][j]; v[k+1]=v[k+1]+1; L[i]=insert(L[i],v); } } } if(size(L[i])>0){s1=1;} s=s1*(s+1); s1=0; i++; } int b1=i-1; list M=L,b1; return(M); } /////////////////////////////////////////////////////////////////////////////////////////// proc WSemigroup(list X,int b0) "USAGE: WSemigroup(X,b0); X a list of polinomials in one vaiable, say t. b0 an integer COMPUTE: Weierstrass semigroup of space curve C,which is given by a parametrization X[1](t),...,X[k](t), till the bound b0. ASSUME: b0 is greater then conductor RETURN: list M of size 5. M[1]= list of integers, which are minimal generators set of the Weierstrass semigroup. M[2]=integer, conductor of the Weierstrass semigroup. M[3]=intvec, all elements of the Weierstrass semigroup till some bound b, which is greather than conductor. WARNING: works only over the ring with one variable with ordering ds EXAMPLE: example WSemigroup; shows an example" { int k=size(X); intvec G; int i,i2; poly t=var(1); poly h; int g; for(i=1;i<=k;i++) {G[i]=ord(X[i]);} for(i=1;iG[i2]) { g=G[i];G[i]=G[i2];G[i2]=g; h=X[i];X[i]=X[i2];X[i2]=h; } } } list U=Semi(G,b0); list L=U[1]; int b=U[2]; G=U[3]; int k1=size(G); list N; list l; for(i=1;i<=b;i++){N[i]=l;} int j; for(j=b0;j>b;j--){L=delete(L,j);} poly p; int s; int e; for(i=1;i<=b;i++) { for(j=1;j<=size(L[i]);j++) { p=1; for(s=1;s<=k;s++) { for(e=1;e<=L[i][j][s];e++) { p=p*X[s]; p=jet(p,b); } } N[i]=insert(N[i],p); } } int j1; int j2; list M; poly c1; poly c2; poly f; int m; int b1; ideal I; matrix C; matrix C1; int q; int i1; i=1; while(i<=b) { for(j1=2;j1<=size(N[i]);j1++) { for(j2=1;j2=0) { if(size(N[m])==0) { N[m]=insert(N[m],f); if(size(L[m])==0) { M=AddElem(L,b,k,m,G[1]); L=M[1]; b1=M[2]; G[k1+1]=m; X[k+1]=f; N[m]=insert(N[m],f); k=k+1; k1=k1+1; if(b1b1;s--){N=delete(N,s);} for(s=size(L);s>b1;s--){L=delete(L,s);} } b=b1; } } else { for(q=1;q<=size(N[m]);q++){I[q]=N[m][q];} I[size(N[m])+1]=f; C=coeffs(I,t); C1=gauss_col(C); if(C1[size(N[m])+1]!=0){N[m]=insert(N[m],f);} } } } } i++; } intvec S; j=1; for(i=1;i<=b;i++) { if(size(L[i])>0){S[j]=i;j++;} } U=Semi(G,b); G=U[3]; list Q=G,b-G[1]+1,S; return(Q); } example { "EXAMPLE:";echo=2; ring r=0,(t),ds; list X=t4,t5+t11,t9+2*t7; list L=WSemigroup(X,30); L; } //////////////////////////////////////////////////////////////////////////////////////////// static proc quickSubst(poly h, poly r, poly s,ideal I) { //=== computes h(r,s) mod I for h in Q[x(1),x(2),a] attrib(I,"isSB",1); if((r==x(1))&&(s==x(2))){return(reduce(h,I));} poly q1 = 1; poly q2 = 1; poly q3 = 1; int i,j,e1,e2,e3; list L,L1,L2,L3; if(r==x(1)) { matrix M=coeffs(h,x(2)); L[1]=1; for(i=2;i<=nrows(M);i++) { q2 = reduce(q2*s,I); L[i]=q2; } i=1; h=0; while(i <= nrows(M)) { if(M[i,1]!=0) { h=h+M[i,1]*L[i]; } i++; } h=reduce(h,I); return(h); } if(s==x(2)) { matrix M=coeffs(h,x(1)); L[1]=1; for(i=2;i<=nrows(M);i++) { q1 = reduce(q1*r,I); L[i]=q1; } i=1; h=0; while(i <= nrows(M)) { if(M[i,1]!=0) { h=h+M[i,1]*L[i]; } i++; } h=reduce(h,I); return(h); } for(i=1;i<=size(h);i++) { if(leadexp(h[i])[1]>e1){e1=leadexp(h[i])[1];} if(leadexp(h[i])[2]>e2){e2=leadexp(h[i])[2];} if(leadexp(h[i])[3]>e3){e3=leadexp(h[i])[3];} } for(i = 1; i <= size(h); i++) { L[i] = list(leadcoef(h[i]),leadexp(h[i])); } L1[1]=1; L2[1]=1; L3[1]=1; for(i=1;i<=e1;i++) { q1 = reduce(q1*r,I); L1[i+1]=q1; } for(i=1;i<=e2;i++) { q2 = reduce(q2*s,I); L2[i+1]=q2; } for(i=1;i<=e3;i++) { q3 = reduce(q3*var(3),I); L3[i+1]=q3; } int m=size(L); i = 1; h = 0; while(i <= m) { h=h+L[i][1]*L1[L[i][2][1]+1]*L2[L[i][2][2]+1]*L3[L[i][2][3]+1]; i++; } h=reduce(h,I); return(h); } static proc semi2char(intvec v) { intvec k=v[1..2]; intvec w=v[1]; int i,j,p,q; for(i=2;i1) { list v; while(ord(y)>=ord(x)) { F=divide(y,x,c); if(ord(F)==0) { v=insert(v,subst(F,t,0),size(v)); y=F-subst(F,t,0); } else { v=insert(v,0,size(v)); y=F; } } v=insert(v,t,size(v)); L=insert(L,transform(v),size(L)); z=x; x=y; y=z; kill v; } if(ord(x)==1) { list v; while(i=k){break;} } return(i); } ////////////////////////////////////////////////////////////////////// proc MultiplicitySequence(ideal i) "USAGE: MultiplicitySequence(i); i ideal ASSUME: i is the defining ideal of a (reducible) plane curve singularity. RETURN: list X of charts. Each chart contains the multiplicity sequence of the corresponding branch. EXAMPLE: example MultiplicitySequence; shows an example " { def s=CurveParam(i); setring s; int j,k; def r1=converter(Param); setring r1; list Y=hne; list X; for(j=1;j<=size(Y);j++) { for(k=1;k<=Y[j][5];k++) { X=insert(X,multsequence(Y[j]),size(X)); } } return(X); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),ds; ideal i=x14-x4y7-y11; MultiplicitySequence(i); } ///////////////////////////////////////////////////////////////////////// proc IntersectionMatrix(ideal i) "USAGE: IntersectionMatrix(i); i ideal ASSUME: i is the defining ideal of a (reducible) plane curve singularity. RETURN: intmat of the intersection multiplicities of the branches. EXAMPLE: example IntersectionMatrix; shows an example " { def s=CurveParam(i); setring s; int j,k; def r1=converter(Param); setring r1; list Y=hne; return(intermat(Y)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),ds; ideal i=x14-x4y7-y11; IntersectionMatrix(i); } /////////////////////////////////////////////////////////////////////////// proc CharacteristicExponents(ideal i) "USAGE: CharacteristicExponents(i); i ideal ASSUME: i is the defining ideal of a (reducible) plane curve singularity. RETURN: list X of charts. Each chart contains the characteristic exponents of the corresponding branch. EXAMPLE: example CharacteristicExponents; shows an example " { def s=CurveParam(i); setring s; int j,k; def r1=converter(Param); setring r1; list X; list Y=hne; for(j=1;j<=size(Y);j++) { for(k=1;k<=Y[j][5];k++) { X=insert(X,invariants(Y[j])[1],size(X)); } } return(X); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),ds; ideal i=x14-x4y7-y11; CharacteristicExponents(i); } ///////////////////////////////////////////////////////////////////////////// static proc contactNumber(int a,intvec v1,intvec v2) { //==== a is the intersection multiplicity of the branches //==== v1,v2 are the multiplicity sequences int i,c,d; if(size(v1)>size(v2)) { for(i=size(v2)+1;i<=size(v1);i++) { v2[i]=1; } } if(size(v1)=1;i--) { if(gcd(m,leadexp(f[i])[1])==1) { i=i-1; break; } else { m=gcd(m,leadexp(f[i])[1]); } } return(2*leadexp(f[i+1])[1]); } singular-4.0.3+ds/Singular/LIB/deRham.lib000066400000000000000000005477211266270727000200570ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version derham.lib 4.0.0.0 Jun_2013 "; category="Noncommutative"; info=" LIBRARY: deRham.lib Computation of deRham cohomology AUTHORS: Cornelia Rottner, rottner@mathematik.uni-kl.de OVERVIEW: A library for computing the de Rham cohomology of complements of complex affine varieties. REFERENCES: [OT] Oaku, T.; Takayama, N.: Algorithms of D-modules - restriction, tensor product, localzation, and local cohomology groups}, J. Pure Appl. Algebra 156, 267-308 (2001) [R] Rottner, C.: Computing de Rham Cohomology,diploma thesis (2012)@* [W1] Walther, U.: Algorithmic computation of local cohomology modules and the local cohomological dimension of algebraic varieties}, J. Pure Appl. Algebra 139, 303-321 (1999)@* [W2] Walther, U.: Algorithmic computation of de Rham Cohomology of Complements of Complex Affine Varieties}, J. Symbolic Computation 29, 796-839 (2000)@* [W3] Walther, U.: Computing the cup product structure for complements of complex affine varieties, J. Pure Appl. Algebra 164, 247-273 (2001) PROCEDURES: deRhamCohomology(list[,opt]); computes the de Rham cohomology MVComplex(list); computes the Mayer-Vietoris complex "; LIB "nctools.lib"; LIB "matrix.lib"; LIB "qhmoduli.lib"; LIB "general.lib"; //LIB "dmod.lib"; LIB "bfun.lib"; LIB "dmodapp.lib"; LIB "poly.lib"; LIB "schreyer.lib"; LIB "dmodloc.lib"; //////////////////////////////////////////////////////////////////////////////////// proc deRhamCohomology(list L,list #) "USAGE: deRhamCohomology(L[,choices]); L a list consisting of polynomials, choices optional list consisting of one up to three strings @* The optional strings may be one of the strings@* -'noCE': compute quasi-isomorphic complexes without using Cartan-Eilenberg resolutionsq@* -'Vdres': compute quasi-isomorphic complexes using Cartan-Eilenberg resolutions; the CE resolutions are computed via V__d-homogenization and without using Schreyer's method @* -'Sres': compute quasi-isomorphic complexes using Cartan-Eilenberg resolutions in the homogenized Weyl algebra via Schreyer's method@* one of the strings@* -'iterativeloc': compute localizations by factorizing the polynomials and sucessive localization of the factors @* -'no iterativeloc': compute localizations by directly localizing the product@* and one of the strings -'onlybounds': computes bounds for the minimal and maximal interger roots of the global b-function -'exactroots' computes the minimal and maximal integer root of the global b-function The default is 'noCE', 'iterativeloc' and 'onlybounds'. ASSUME: -The basering must be a polynomial ring over the field of rational numbers@* RETURN: list, where the ith entry is the (i-1)st de Rham cohomology group of the complement of the complex affine variety given by the polynomials in L EXAMPLE:example deRhamCohomology; shows an example " { intvec saveoptions=option(get); intvec i1,i2; option(none); int recursiveloc=1; int i,j,nr,nc; def R=basering; poly islcm, forlcm; int n=nvars(R); int le=size(L)+n; string Syzstring="noCE"; int onlybounds=1; int diffforms; for (i=1; i<=size(#); i++) { if (#[i]=="Sres") { Syzstring="Sres"; } if (#[i]=="Vdres") { Syzstring="Vdres"; } if (#[i]=="noiterativeloc") { recursiveloc=0; } if (#[i]=="exactroots") { onlybounds=0; } if (#[i]=="diffforms") { diffforms=1; } } for (i=1; i<=size(L); i++) { if (L[i]==0) { L=delete(L,i); i=i-1; } } if (size(L)==0) { return (list(0));//////////////////////////////////////////////////////////////////stimmt das jetzt?!?????????????????????????????????? } for (i=1; i<= size(L); i++) { if (leadcoef(L[i])-L[i]==0) { return(list(1)); ///////////////////////////////////////////////////////////////stimmt das jetzt?!???????????????????????????????????? } } if (size(L)==0) { /*the complement of the variety given by the input is the whole space*/ return(list(1)); } for (i=1; i<=size(L); i++) { if (typeof(L[i])!="poly") { print("The input list must consist of polynomials"); return(); } } if (size(L)==1 and Syzstring=="noCE") { Syzstring="Sres"; } /* 1st step: compute the Mayer-Vietoris Complex and its Fourier transform*/ def W=MVComplex(L,recursiveloc);//new ring that contains the MV complex setring W; list fortoVdstrict=MV; if (diffforms==0) { ideal IFourier=var(n+1); for (i=2;i<=n;i++) { IFourier=IFourier,var(n+i); } for (i=1; i<=n;i++) { IFourier=IFourier,-var(i); } map cFourier=W,IFourier; matrix sup; for (i=1; i<=size(MV); i++) { sup=fortoVdstrict[i]; /*takes the Fourier transform of the MV complex*/ fortoVdstrict[i]=cFourier(sup); } } /* 2nd step: Compute a V_d-strict free complex that is quasi-isomorphic to the complex fortoVdstrict The 1st entry of the list rem will be the quasi-isomorphic complex, the 2nd entry contains the cohomology modules and is needed for the computation of the global b-function*/ if (Syzstring=="noCE") { list rem=quasiisomorphicVdComplex(fortoVdstrict,diffforms); list quasiiso=rem[3]; } else { list rem=toVdStrictFreeComplex(fortoVdstrict,Syzstring,diffforms); if (diffforms==1) { list quasiiso=list(matrix(1,1,1)); } } list newcomplex=rem[1]; //////////////////////////////////////////////////////////////////////////////////// /* 3rd step: Compute the bounds for the minimal and maximal integer root of the global b-function of newcomplex(i.e. compute the lcm of the b-functions of its cohomology modules)(if onlybouns=1). Else we compute the minimal and maximal integer root. If we compute only the bounds, we omit additional Groebner basis computations. However this leads to a higher-dimensional truncated complex. Note that the cohomology modules are already contained in rem[2]. minmaxk[1] and minmaxk[2] will contain the bounds resp exact roots.*/ if (diffforms==1) { list minmaxk=exactGlobalBFunIntegration(rem[2]); } else { if (onlybounds==1) { list minmaxk=globalBFun(rem[2],Syzstring); } else { list minmaxk=exactGlobalBFun(rem[2],Syzstring); } } if (size(minmaxk)==0) { return (0); } ///////////////////////////////////////////////////////////////////////////Bis hierhin angepasst /*4th step: Truncate the complex D_n/(x_1,...,x_n)\otimes C, (where C=(C^i[m^i],d^i) is given by newcomplex, i.e. C^i=D_n^newcomplex[3*i-2], m^i=newcomplex[3*i-1], d^i=newcomplex[3*i]), using Thm 5.7 in [W1]: The truncated module D_n/(x_1,..,x_n)\otimes C[i] is generated by the set (0,...,P_(i_j),0,...), where P_(i_j) is a monomial in C[D(1),...,D(n)] and if it is placed in component k it holds that minmaxk[1]-m^i[k]<=deg(P_(i_j))<=minmaxk[2]-m^i[k]*/ int k,l; list truncatedcomplex,shorten,upto; for (i=1; i<=size(newcomplex) div 3; i++) { shorten[3*i-1]=list(); for (j=1; j<=size(newcomplex[3*i-1]); j++) { /*shorten[3*i-1][j][k]=minmaxk[k]-m^i[j]+1 (for k=1,2) if this value is positive otherwise we will set it to be list(); .- we added +1, because we will use a list, where we put in position l polys of degree l+1*/ shorten[3*i-1][j]=list(minmaxk[1]-newcomplex[3*i-1][j]+1); if (diffforms==1) { shorten[3*i-1][j][1]=1; } shorten[3*i-1][j][2]=minmaxk[2]-newcomplex[3*i-1][j]+1; upto[size(upto)+1]=shorten[3*i-1][j][2]; if (shorten[3*i-1][j][2]<=0) { shorten[3*i-1][j]=list(); } else { if (shorten[3*i-1][j][1]<=0) { shorten[3*i-1][j][1]=1; } } } } int iupto=Max(upto);//maximal degree +1 of the polynomials we have to consider if (iupto<=0) { return(list(0)); } list allpolys; /*allpolys[i] will consist list of all monomials in D(1),...,D(n) of degree i-1*/ allpolys[1]=list(1); list minvar; list keepv; minvar[1]=list(1); for (i=1; i<=iupto-1; i++) { allpolys[i+1]=list(); minvar[i+1]=list(); for (k=1; k<=size(allpolys[i]); k++) { for (j=minvar[i][k]; j<=nvars(W) div 2; j++) { if (diffforms==0) { allpolys[i+1][size(allpolys[i+1])+1]=allpolys[i][k]*D(j); } else { allpolys[i+1][size(allpolys[i+1])+1]=allpolys[i][k]*x(j); } minvar[i+1][size(minvar[i+1])+1]=j; } } } list keepformatrix,sizetruncom,fortrun,fst; int count,stc; intvec v,forin; matrix subm; list keepcount; list passendespoly; /*now we compute the truncation*/ for (i=1; i<=size(newcomplex) div 3; i++) { /*truncatedcomplex[2*i-1] will contain all the generators for the truncation of D_n/(x(1),..,x(n))\otimes C[i]*/ truncatedcomplex[2*i-1]=list(); sizetruncom[2*i-1]=list(); sizetruncom[2*i]=list(); passendespoly[i]=list(); /*truncatedcomplex[2*i] will be the map trunc(D_n/(x(1),..,x(n))\otimes C[i]) ->trunc(D_n/(x(1),..,x(n))\otimes C[i+1])*/ truncatedcomplex[2*i]=newcomplex[3*i]; v=0;count=0; sizetruncom[2*i][1]=0; for (j=1; j<=newcomplex[3*i-2]; j++) { if (size(shorten[3*i-1][j])!=0) { fortrun=sublist(allpolys,shorten[3*i-1][j][1],shorten[3*i-1][j][2]); truncatedcomplex[2*i-1][size(truncatedcomplex[2*i-1])+1]=fortrun[1]; for (k=1; k<=size(fortrun[1]); k++) { for (l=1; l<=size(fortrun[1][k]); l++) { passendespoly[i][size(passendespoly[i])+1]=list(fortrun[1][k][l][1],j); } } count=count+fortrun[2]; fst=list(int(shorten[3*i-1][j][1])-1,int(shorten[3*i-1][j][2])-1); sizetruncom[2*i-1][size(sizetruncom[2*i-1])+1]=fst; sizetruncom[2*i][size(sizetruncom[2*i])+1]=count; if (v!=0) { v[size(v)+1]=j; } else { v[1]=j; } } } if (v!=0) { keepv[i]=v; subm=submat(truncatedcomplex[2*i],v,1..ncols(truncatedcomplex[2*i])); truncatedcomplex[2*i]=subm; if (i!=1) { i1=1..nrows(truncatedcomplex[2*(i-1)]); subm=submat(truncatedcomplex[2*(i-1)],i1,v); truncatedcomplex[2*(i-1)]=subm; } } else { keepv[i]=list(); truncatedcomplex[2*i]=matrix(0,1,ncols(truncatedcomplex[2*i])); if (i!=1) { nr=nrows(truncatedcomplex[2*(i-1)]); truncatedcomplex[2*(i-1)]=matrix(0,nr,1); } } } list keeptruncatedcomplex=truncatedcomplex; matrix M; int st,pi,pj; poly ptc; int b,d,ideg,kplus,lplus; int z; poly form,lform,nform; /*computation of the maps*/ if (diffforms==1) { def ConvWeyl=makeConverseWeyl(nvars(basering) div 2); setring ConvWeyl; poly form,lform,nform; poly ptc; list truncatedcomplex; matrix M; ideal I=x(1); for (i=2; i<=nvars(basering) div 2; i++) { I=I,var(nvars(basering) div 2 + i); } for (i=1; i<=nvars(basering) div 2; i++) { I=I,var(i); } map transtc=W,I; truncatedcomplex=transtc(truncatedcomplex); } for (i=1; i=0) { nr=ideg+1; st=size(truncatedcomplex[2*(i+1)-1][l][nr]); for (d=1; d<=st;d++) { nc=2*(i+1)-1; ptc=truncatedcomplex[nc][l][ideg+1][d][1]; if (leadmonom(lform)==ptc) { nr=2*i-1; pi=truncatedcomplex[nr][k][j][b][2]; pi=pi+sizetruncom[2*i][k]; nc=2*(i+1)-1; nr=ideg+1; pj=truncatedcomplex[nc][l][nr][d][2]; pj=pj+sizetruncom[2*(i+1)][l]; M[pi,pj]=leadcoef(lform); break; } } } // } form=form-lform; } } } } } } truncatedcomplex[2*i]=M; truncatedcomplex[2*i-1]=sizetruncom[2*i][size(sizetruncom[2*i])]; } truncatedcomplex[2*i-1]=sizetruncom[2*i][size(sizetruncom[2*i])]; if (truncatedcomplex[2*i-1]!=0) { truncatedcomplex[2*i]=matrix(0,truncatedcomplex[2*i-1],1); } if (diffforms==1) { setring W; truncatedcomplex=imap(ConvWeyl,truncatedcomplex); } setring R; list truncatedcomplex=imap(W,truncatedcomplex); /*computes the cohomology of the complex (D^i,d^i) given by truncatedcomplex, i.e. D^i=C^truncatedcomplex[2*i-1] and d^i=truncatedcomplex[2*i]*/ if (diffforms==0) { list derhamhom=findCohomology(truncatedcomplex,le); option(set,saveoptions); return (derhamhom); } list outall=findCohomologyDiffForms(truncatedcomplex,le); setring W; list dimanddiff=imap(R,outall); list alldiffforms=dimanddiff[2]; while(size(alldiffforms)size(generators)) { generators=insert(generators,list()); } while (size(dimanddiff[1])>size(quasiiso)) { quasiiso=insert(quasiiso,list()); } int keepsign; list derhamdiff; list doublecom=makeDoubleComplex(newcomplexmod,omegacomplex,quasiiso,generators); matrix diffform; int stopping; int p; matrix convert; list interim; list correspondingposition; list allforms=list(); for (i=1; i<=size(newdiffforms); i++) { derhamdiff[i]=list(); allforms[i]=list(); for (j=1; j<=size(newdiffforms[i]); j++) { allforms[i][j]=list(); keepsign=1; derhamdiff[i][j]=0; diffform=newdiffforms[i][j];//Zeilenform correspondingposition=doublecom[i][1];//needed fpr transformation process interim=transferDiffforms(diffform,correspondingposition); if (size(interim)!=0) { allforms[i][j][size(allforms[i][j])+1]=interim; } stopping=0; p=1; for (k=i; k<=size(newdiffforms); k++) { keepsign=(-1)*keepsign; if (stopping==0) { if (size(doublecom[k][p][2])==0) { stopping=1; } else { if (size(doublecom[k+1][p][3])!=0) { diffform=diffform*doublecom[k][p][2];//Spaltenform if (diffform!=matrix(0,nrows(diffform),ncols(diffform))) { diffform=findPreimage(doublecom[k+1][p][3],transpose(diffform));//Zeilenform correspondingposition=doublecom[k+1][p+1];//needed for transformation process interim=transferDiffforms(keepsign*diffform,correspondingposition); if (size(interim)!=0) { allforms[i][j][size(allforms[i][j])+1]=interim; } p=p+1; } else { stopping=1; } } else { stopping=1; } } } } } } setring R; list allforms=fetch(W,allforms); option(set,saveoptions); return (allforms); } example { "EXAMPLE:"; ring r = 0,(x,y,z),dp; list L=(xy,xz); deRhamCohomology(L); } //////////////////////////////////////////////////////////////////////////////////// //COMPUTATION OF THE MAYER-VIETORIS COMPLEX //////////////////////////////////////////////////////////////////////////////////// proc MVComplex(list L,list #) "USAGE:MVComplex(L); L a list of polynomials ASSUME: -Basering is a polynomial ring with n vwariables and rational coefficients -L is a list of non-constant polynomials RETURN: ring W: the nth Weyl algebra @* W contains a list MV, which represents the Mayer-Vietrois complex (C^i,d^i) of the polynomials contained in L as follows:@* the C^i are given by D_n^ncols(C[2*i-1])/im(C[2*i-1]) and the differentials d^i are given by C[2*i] EXAMPLE:example MVComplex; shows an example " { /* We follow algorithm 3.2.5 in [R],if #!=0 we use also Remark 3.2.6 in [R] for an additional iterative localization*/ def R=basering; int i; int iterative=1; if (size(#)!=0) { iterative=#[1]; } for (i=1; i<=size(L); i++) { if (L[i]==0) { print("localization with respect to 0 not possible"); return(); } if (leadcoef(L[i])-L[i]==0) { print("polynomials must be non-constant"); return(); } } if (iterative==1) { /*compute the localizations by factorizing the polynomials and iterative localization of the factors */ for (i=1; i<=size(L); i++) { L[i]=factorize(L[i],1); } } int r=size(L); int n=nvars(basering); int le=size(L)+n; /*construct the ring Ws*/ def W=makeWeyl(n); setring W; list man=ringlist(W); if (n==1) { man[2][1]="x(1)"; man[2][2]="D(1)"; def Wi=ring(man); setring Wi; kill W; def W=Wi; setring W; list man=ringlist(W); } man[2][size(man[2])+1]="s";; man[3][3]=man[3][2]; man[3][2]=list("dp",intvec(1)); matrix N=UpOneMatrix(size(man[2])); man[5]=N; matrix M[1][1]; man[6]=transpose(concat(transpose(concat(man[6],M)),M)); def Ws=ring(man); setring Ws; int j,k,l,c; list L=fetch(R,L); list Cech; ideal J=var(1+n); for (i=2; i<=n; i++) { J=J,var(i+n); } Cech[1]=list(J); list Theta, remminroots; Theta[1]=list(list(list(),1,1)); list rem,findminintroot,diffmaps; int minroot,st,sk; intvec k1; poly fred,forfetch; matrix subm; int rmr; if (iterative==0) {/*computation of the modules of the MV complex*/ for (i=1; i<=r; i++) { findminintroot=list(); Cech[i+1]=list(); Theta[i+1]=list(); k1=1; for (j=1; j<=i; j++) { k1[size(k1)+1]=size(Theta[j+1]); for (k=1; k<=k1[j]; k++) { Theta[j+1][size(Theta[j+1])+1]=list(Theta[j][k][1]+list(i)); Theta[j+1][size(Theta[j+1])][2]=Theta[j][k][2]*L[i]; /*We compute the s-parametric annihilator J(s) and the b-function of the polynomial L[i] and Cech[i][k] to localize the module D_n/(D(1),...,D(n))[L[i]^(-1)]\otimes D_n^c/im(Cech[i][k]), where c=ncols(Cech[i][k]) and the im(Cech[i][k]) is generated by the rows of the matrix. If we plug the minimal integer root r(or a smaller integer value)in J(s), then D_n^ncols(J(s))/im(J(r)) is isomorphic to the above localization*/ rem=SannfsIBM(L[i],Cech[j][k]); Cech[j+1][size(Cech[j+1])+1]=rem[1]; findminintroot[size(findminintroot)+1]=rem[2]; } } /* we compute the minimal root of all b-functions of L[i] computed above, because we want to plug in the same root r in all s-parametric annihilators we computed for L[i] ->this will ensure we can compute the maps of the MV complex*/ minroot=minIntRootD(findminintroot); for (j=1; j<=i; j++) { for (k=1; k<=k1[j]; k++) { sk=size(Cech[j+1])+1-k; Cech[j+1][size(Cech[j+1])+1-k]=subst(Cech[j+1][sk],s,minroot); } } remminroots[i]=minroot; } Cech=delete(Cech,1); Theta=delete(Theta,1); list zw; poly reme; /*computation of the maps of the MV complex*/ for (i=1; ithis will ensure we can compute the maps of the MV complex*/ minroot=minIntRootD(findminintroot); for (j=1; j<=i; j++) { for (k=1; k<=k1[j]; k++) { st=size(Cech[j+1])+1-k; Cech[j+1][st]=subst(Cech[j+1][st],s,minroot); } } if (c==1) { remminroots[i]=list(); } remminroots[i][c]=minroot; } } Cech=delete(Cech,1); Theta=delete(Theta,1); list zw; poly reme; /*maps of the MV Complex*/ for (i=1; iD_n^(r_1)/im(M_1)-> D_n^(r_2)/im(M_2)->...->D_n^(r_s)->0 with differentials f_i, where im(M_i) is generated by the rows of M_i. In particular it hold:@* - The M_i are m_i x r_i-matrices and the f_iare r_i x r_(i+1)-matrices @* -the image of M_1*f_i is contained in the image of M_(i+1) @* d is an integer between 1 and n. If no value for d is given, it is assumed to be n @* df is an optional int, if df equals 1 a \tilde(V_d)-strict complex will be computed (instead of a V_d-strict one) (for a definition see [W3]) RETURN: list of the form (L_1,L_2), were L_1 and L_2 are lists @* L_1 is of the form (i_(-n-1),g_(-n-1),m_(-n-1),...,i_s,g_s,m_s) such that:@* -the i_j are integers, the g_j are i_j x i_(j+1)-matrices, the m_j intvecs of size i_j@* -D_n^(i_(-n-1))[m_(-n-1)]->...->D_n^(i_s)[m_s]->0 is a V_d-strict complex with differentials m_i that is quasi-isomorphic to the complex given by L@* L_2 is of the form (H_1,n_1,...,H_s,n_s), where the H_i are matrices and the n_i are shift vectors such that:@* -coker(H_i) is the ith cohomology group of the complex given by L_1@* -the n_i are the shift vectors of the coker(H_i) THEORY: We follow Proposition 3.2 and Corollary 3.3 in [W3] " { int tilde; if (size(#)!=0) { tilde=#[1]; } def B=basering; int n=nvars(B) div 2 + 1;//+1 muesste stimmen! bitte kontrollieren! int d=nvars(B) div 2; int r=size(L) div 2; int lonc=n+r; int Kiold=0; matrix kerold; // matrix kernew=out[r][2][2]; matrix kernew=diag(1,ncols(L[size(L)-1])); module mL; int i; int k; matrix testm; int Kinew=nrows(kernew); int Jiold=0; int Jinew=0; matrix Niold; matrix Ninew; list newcomplex; int Aiold=Kinew; matrix savediv; newcomplex[3*lonc-2]=Kinew; newcomplex[3*lonc-1]=intvec(0:Kinew); newcomplex[3*lonc]=matrix(0,Kinew,1); list quasiiso; quasiiso[lonc]=diag(1,Kinew); matrix invimage; matrix keralpha; intvec v; int j; matrix sc; matrix fnc; int indk; int indj; int Aiold; list saveres; matrix Liplus; for (i=r-1; i>=0; i--) { indk=0; indj=0; Kiold=Kinew; kerold=kernew; if (i!=0) { // kernew=divdr(L[2*i],L[2*i+1],1); kernew=divdr(L[2*i],L[2*i+1]); mL=slimgb(transpose(L[2*i-1])); for (k=1; k<=nrows(kernew); k++) { testm=reduce(transpose(submat(kernew,k,intvec(1..ncols(kernew)))),mL); if (testm==matrix(0,nrows(testm),ncols(testm))) { kernew=transpose(deletecol(transpose(kernew),k)); k=k-1; } } Kinew=nrows(kernew); if (kernew==matrix(0,nrows(kernew),ncols(kernew))) { Kinew=0; indk=1; } } else { Kinew=0; indk=1; } Jiold=Jinew; Niold=Ninew; keralpha=transpose(syz(transpose(newcomplex[3*(i+n)+3]))); if (i!=0) { invimage=divdr(quasiiso[n+i+1],transpose(concat(transpose(L[2*i]),transpose(L[2*i+1])))); Ninew=vdStrictIntersect(keralpha,invimage,newcomplex[3*(n+i+1)-1],tilde);////////////// } else { invimage=divdr(quasiiso[n+i+1],L[2*i+1]); saveres=vdStrictIntersectPlus(keralpha,invimage,newcomplex[3*(n+i+1)-1],tilde);//////////////////////// ///////////////////BIS HIERHIN VERALLGEMEINERT//////////////////////////////////////////////////////////////////// Ninew=saveres[1]; } Jinew=nrows(Ninew); if (Ninew==matrix(0,nrows(Ninew),ncols(Ninew))) { Jinew=0; indk=1; } newcomplex[3*(n+i)-2]=Kinew+Jinew; v=0; if (indk==0) { v=(0:Kinew); if (indj==0) { fnc=transpose(concat(transpose(matrix(0,Kinew,Kiold+Jiold)),transpose(Ninew))); } else { fnc=matrix(0,Kinew,Kiold+Jiold); } } else { if (indj==0) { fnc=Ninew; } else { fnc=matrix(0,1,Kiold+Jiold); newcomplex[3*(n+i)-2]=1; } } Aiold=Jinew+Kinew; if (Aiold==0) { Aiold=1; } newcomplex[3*(n+i)]=fnc; for (j=1; j<=Jinew; j++) { if (tilde==0) { v[Kinew+j]=VdDeg(submat(Ninew,j,(1..ncols(Ninew))),nvars(B) div 2,newcomplex[3*(n+i)+2]); } else { v[Kinew+j]=VdDegTilde(submat(Ninew,j,(1..ncols(Ninew))),nvars(B) div 2,newcomplex[3*(n+i)+2]); } } newcomplex[3*(n+i)-1]=v; if (i==0) { quasiiso[n+i]=matrix(0,Jinew,1); } else { if (indj==0) { sc=submat(fnc,intvec(Kinew+1..nrows(fnc)),intvec(1..ncols(fnc)))*quasiiso[n+i+1]; Liplus=transpose(concat(transpose(L[2*i]),transpose(L[2*i+1]))); sc=matrixLift(Liplus,sc);//stimmt das jetzt sc=submat(sc,intvec(1..nrows(sc)),intvec(1..nrows(L[2*i]))); if (indk==0) { //pi=kernew quasiiso[n+i]=transpose(concat(transpose(kernew),transpose(sc))); } else { quasiiso[n+i]=sc; } } else { if (indk==0) { quasiiso[n+i]=kernew; } else { quasiiso[n+i]=matrix(0,1,ncols(kernew)); } } } } for (i=1; i<=n-1; i++) { quasiiso[n-i]=list(); if (size(saveres[2][i])!=0) { newcomplex[3*(n-i)]=saveres[2][i]; newcomplex[3*(n-i)-2]=nrows(saveres[2][i]); v=0; for (j=1; j<=newcomplex[3*(n-i)-2]; j++) { if (tilde==0) { v[j]=VdDeg(submat(saveres[2][i],j,(1..ncols(saveres[2][i]))),nvars(B) div 2, newcomplex[3*(n-i)+2]); } else { v[j]=VdDegTilde(submat(saveres[2][i],j,(1..ncols(saveres[2][i]))),nvars(B) div 2, newcomplex[3*(n-i)+2]); } } newcomplex[3*(n-i)-1]=v; } else { newcomplex[3*(n-i)]=matrix(0,1,1); if (newcomplex[3*(n-i)+1]!=0) { newcomplex[3*(n-i)]=matrix(0,1,newcomplex[3*(n-i)+1]); } newcomplex[3*(n-i)-2]=int(0); newcomplex[3*(n-i)-1]=intvec(0); } } list result; result[1]=newcomplex; result[2]=list(); list forsep; for (i=1; i<=size(L) div 2+1; i++) { forsep[2*i]=newcomplex[3*(n+i-1)]; forsep[2*i-1]=matrix(0,1,nrows(forsep[2*i])); } forsep=shortExactPieces(forsep); list listofHis; matrix forVd; for (i=1; i<=size(L) div 2; i++) { v=0; listofHis[i]=list(forsep[i+1][1][5]); forVd=forsep[i+1][2][2]; for (j=1; j<=nrows(forVd); j++) { if (tilde==0) { v[j]=VdDeg(submat(forVd,j,intvec(1..ncols(forVd))),nvars(B) div 2, newcomplex[3*(n+i)-1]); } else { v[j]=VdDegTilde(submat(forVd,j,intvec(1..ncols(forVd))),nvars(B) div 2, newcomplex[3*(n+i)-1]); } } listofHis[i][2]=v; } result[2]=listofHis; result[3]=quasiiso; return(result); } //////////////////////////////////////////////////////////////////////////////////// static proc vdStrictIntersect(matrix M, matrix N, intvec v, int tilde) { def B=basering; option(returnSB);// alternative:erst intersect und dann SB-Berechung mit slimgb if (tilde==0) { def HomWeyl=makeHomogenizedWeyl(nvars(B) div 2,v); } else { def HomWeyl=makeHomogenizedWeylTilde(nvars(B) div 2,v); } setring HomWeyl; matrix M=fetch(B,M); matrix N=fetch(B,N); M=nHomogenize(M); N=nHomogenize(N); matrix vdintersection=transpose(intersect(transpose(M),transpose(N))); vdintersection=subst(vdintersection,h,1); setring B; matrix vdintersection=fetch(HomWeyl,vdintersection); option(noreturnSB); return(vdintersection); } //////////////////////////////////////////////////////////////////////////////////// static proc vdStrictIntersectPlus(matrix M, matrix N, intvec v, int tilde) { def B=basering; int n=nvars(B) div 2; matrix vdint=transpose(intersect(transpose(M),transpose(N))); if (tilde==0) { def HomWeyl=makeHomogenizedWeyl(nvars(B) div 2,v); } else { def HomWeyl=makeHomogenizedWeylTilde(nvars(B) div 2,v); } setring HomWeyl; matrix vdint=fetch(B,vdint); matrix N=fetch(B,N); vdint=nHomogenize(vdint); intvec i1; intvec i2; int i; int nr; int nc; def ringofSyz=Sres(transpose(vdint),n);//////////////////////////////////////////////////////////////// setring ringofSyz; matrix vdint=transpose(matrix(RES[2])); vdint=subst(vdint,h,1); int logens=ncols(vdint)+1; int omitemptylist; matrix zerom; list rofA; for (i=3; i<=n+3; i++)////////////////////////////////////////////////////////////////////////////n und si muessen noch definiert werden { if (size(RES)>=i) { zerom=matrix(0,nrows(matrix(RES[i])),ncols(matrix(RES[i]))); if (RES[i]!=zerom) { rofA[i-2]=(matrix(RES[i])); if (i==3) { if (nrows(rofA[i-2])-logens+1!=nrows(vdint)) { //build the resolution nr=nrows(vdint)+logens-1; nc=ncols(rofA[i-2]); rofA[i-2]=matrix(rofA[i-2],nr,nc); } } if (i!=3) { if (nrows(rofA[i-2])-logens+1!=nrows(rofA[i-3])) { nr=nrows(rofA[i-3])+logens-1; nc=ncols(rofA[i-2]); rofA[i-2]=matrix(rofA[i-2],nr,nc); } } i1=intvec(logens..nrows(rofA[i-2])); i2=intvec(1..ncols(rofA[i-2])); rofA[i-2]=transpose(submat(rofA[i-2],i1,i2)); logens=logens+ncols(rofA[i-2]); rofA[i-2]=subst(rofA[i-2],h,1); } else { rofA[i-2]=list(); } } else { rofA[i-2]=list(); } } if(size(rofA[1])==0) { omitemptylist=1; } setring B; vdint=fetch(ringofSyz,vdint); if (omitemptylist!=1) { list rofA=fetch(ringofSyz,rofA); } kill HomWeyl; kill ringofSyz; return(list(vdint,rofA)); } //////////////////////////////////////////////////////////////////////////////////// static proc toVdStrictFreeComplex(list L,string Syzstring,list #) "USAGE: toVdStrictFreeComplex(L, Syzstring [,d]); L a list of the form (M_1,f_1,...,M_s,f_s), where the M_i and f_i are matrices, Syzstring a string, d an optional integer ASSUME: Basering is the Weyl algebra D_n @* (M_1,f_1,...,M_s,f_s) represents a complex 0->D_n^(r_1)/im(M_1)-> D_n^(r_2)/im(M_2)->...->D_n^(r_s)->0 with differentials f_i, where im(M_i) is generated by the rows of M_i. In particular it hold:@* - The M_i are m_i x r_i-matrices and the f_iare r_i x r_(i+1)-matrices @* -the image of M_1*f_i is contained in the image of M_(i+1) @* d is an optional integer which indices in the case size(L)=2, whether a V_d-strict or \tilde(V_d)-strict will be computed@* Syzstring is either: @* -'Sres' (computes the resolutions and Groebner bases in the homogenized Weyl algebra using Schreyer's method)@* or @* -'Vdres' (computes the resolutions via V_d-homogenization and without Schreyer's method)@* RETURN: list of the form (L_1,L_2), were L_1 and L_2 are lists @* L_1 is of the form (i_(-n-1),g_(-n-1),m_(-n-1),...,i_s,g_s,m_s) such that:@* -the i_j are integers, the g_j are i_j x i_(j+1)-matrices, the m_j intvecs of size i_j@* -D_n^(i_(-n-1))[m_(-n-1)]->...->D_n^(i_s)[m_s]->0 is a V_d-strict complex with differentials m_i that is quasi-isomorphic to the complex given by L@* L_2 is of the form (H_1,n_1,...,H_s,n_s), where the H_i are matrices and the n_i are shift vectors such that:@* -coker(H_i) is the ith cohomology group of the complex given by L_1@* -the n_i are the shift vectors of the coker(H_i) THEORY: We follow Algorithm 3.8 in [W2] " { def B=basering; int n=nvars(B) div 2+2; int d=nvars(B) div 2; intvec v; list out, outall; int i,j,k,indi,nc,nr; matrix mem; intvec i1,i2; int tilde; if (size(#)!=0) { for (i=1; i<=size(#); i++) { if (typeof(#[i])=="int") { tilde=#[i]; } } } /* If size(L)=2, our complex consists for only one non-trivial module. Therefore, we just have to compute a V_d-strict resolution of this module.*/ if (size(L)==2) { v=(0:ncols(L[1])); out[3*n-1]=v; out[3*n-2]=ncols(L[1]); out[3*n]=L[2]; if (Syzstring=="Vdres") { /*if Syzstring="Vdres", we compute a V_d-strict Groebner basis of L[1] using F-homogenization (Prop. 3.9 in [OT]); then we compute the syzygies and make them V_d-strict using Prop 3.9[OT] and so on*/ out[3*n-3]=VdStrictGB(L[1],d,v); for (i=n-1; i>=1; i--) { out[3*i-2]=nrows(out[3*i]); v=0; for (j=1; j<=out[3*i-2]; j++) { mem=submat(out[3*i],j,intvec(1..ncols(out[3*i]))); v[j]=VdDeg(mem,d, out[3*i+2]);//next shift vector } out[3*i-1]=v; if (i!=1) { /*next step in the resolution*/ out[3*i-3]=transpose(syz(transpose(out[3*i]))); if (out[3*i-3]!=matrix(0,nrows(out[3*i-3]),ncols(out[3*i-3]))) { /*makes the resolution V_d-strict*/ out[3*i-3]=VdStrictGB(out[3*i-3],d,out[3*i-1]); } else { /*resolution is already computed*/ out[3*i-3]=matrix(0,1,ncols(out[3*i-3])); out[3*i-4]=intvec(0); out[3*i-5]=int(0); for (j=i-2; j>=1; j--) { out[3*j]=matrix(0,1,1); out[3*j-1]=intvec(0); out[3*j-2]=int(0); } break; } } } } else { /*in the case Syzstring!="Vdres" we compute the resolution in the homogenized Weyl algebra using Thm 9.10 in[OT]*/ if (tilde==0) { def HomWeyl=makeHomogenizedWeyl(d); } else { def HomWeyl=makeHomogenizedWeylTilde(d); } setring HomWeyl; list L=fetch(B,L); L[1]=nHomogenize(L[1]); list out=fetch(B,out); out[3*n-3]=L[1]; /*computes a ring with a list RES; RES is a V_d-strict resolution of L[1]*/ def ringofSyz=Sres(transpose(L[1]),d); setring ringofSyz; int logens=2; matrix mem; list out=fetch(HomWeyl,out); out[3*n-3]=transpose(matrix(RES[2])); out[3*n-3]=subst(out[3*n-3],h,1); for (i=n-1; i>=1; i--) { out[3*i-2]=nrows(out[3*i]); v=0; for (j=1; j<=out[3*i-2]; j++) { mem=submat(out[3*i],j,intvec(1..ncols(out[3*i]))); if (tilde==0) { v[j]=VdDeg(mem,d, out[3*i+2]); } else { v[j]=VdDegTilde(mem,d, out[3*i+2]); } } out[3*i-1]=v;//shift vector such that the resolution RES is V_d-strict if (i!=1) { indi=0; if (size(RES)>=n-i+2) { nr=nrows(matrix(RES[n-i+2])); mem=matrix(0,nr,ncols(matrix(RES[n-i+2]))); if (matrix(RES[n-i+2])!=mem) { indi=1; out[3*i-3]=(matrix(RES[n-i+2])); if (nrows(out[3*i-3])-logens+1!=nrows(out[3*i])) { mem=out[3*i-3]; out[3*i-3]=matrix(mem,nrows(mem)+logens-1,ncols(mem)); } mem=out[3*i-3]; i1=intvec(logens..nrows(mem)); mem=submat(mem,i1,intvec(1..ncols(mem))); out[3*i-3]=transpose(mem); out[3*i-3]=subst(out[3*i-3],h,1); logens=logens+ncols(out[3*i-3]); } } if(indi==0) { out[3*i-3]=matrix(0,1,nrows(out[3*i])); out[3*i-4]=intvec(0); out[3*i-5]=int(0); for (j=i-2; j>=1; j--) { out[3*j]=matrix(0,1,1); out[3*j-1]=intvec(0); out[3*j-2]=int(0); } break; } } } setring B; out=fetch(ringofSyz,out);//contains the V_d-strict resolution kill ringofSyz; } outall[1]=out; outall[2]=list(list(out[3*n-3],out[3*n-1])); return(outall); } /*case size(L)>2: We compute a quasi-isomorphic free complex following Alg 3.8 in [W2]*/ /* We denote the complex given by L as (C^i,d^i). We start by computing in the proc shortExaxtPieces representations for the short exact sequences B^i->Z^i->H^i and Z^i->C^i->B^(i+1), where the B^i, Z^i and H^i are coboundaries, cocycles and cohomology groups, respectively.*/ out=shortExactPieces(L); list rem; /* shortExactpiecesToVdStrict makes the sequences B^i->Z^i->H^i and Z^i->C^i->B^(i+1) V_d-strict*/ rem=shortExactPiecesToVdStrict(out,d,Syzstring); /*VdStrictDoubleComplexes computes V_d-strict resolutions over the seqeunces from proc shortExactPiecesToVdstrict*/ out=VdStrictDoubleComplexes(rem[1],d,Syzstring); for (i=1;i<=size(out); i++) { rem[2][i][1]=out[i][1][5][1]; rem[2][i][2]=out[i][1][8][1]; } /* AssemblingDoubleComplexes puts the resolution of the C^i (from the sequences Z^i->C^i->B^(i+1)) together to obtain a Cartan-Eilenberg resolution of (C^i,d^i)*/ out=assemblingDoubleComplexes(out); /*the proc totalComplex takes the total complex of the double complex from the proc assemblingDoubleComplexes*/ out=totalComplex(out); outall[1]=out; outall[2]=rem[2];//contains the cohomology groups and their shift vectors return (outall); } //////////////////////////////////////////////////////////////////////////////////// static proc sublist(list L,int m,int n) { list out; int i; int j; int count; for (i=m; i<=n; i++) { out[size(out)+1]=list(); for (j=1; j<=size(L[i]); j++) { count=count+1; out[size(out)][j]=list(L[i][j],count); } } list o=list(out,count); return(o); } //////////////////////////////////////////////////////////////////////////////////// static proc LMSubset(list L,list M, list #) { int i; int j=1; if (size(#)==0) { list position=(M[size(M)],(-1)^(size(L))); } else { list position=(M[size(M)],1); } for (i=1; i<=size(L); i++) { if (L[i]!=M[j]) { if (L[i]!=M[i+1] or j!=i) { return (L[i],0); } else { if (size(#)==0) { position=(M[i],(-1)^(i-1)); } else { position=(M[i],(-1)^(size(L)+1-i)); } j=j+1; } } j=j+1; } return (position); } //////////////////////////////////////////////////////////////////////////////////// static proc shortExactPieces(list L) { /*we follow Section 3.3 in [W2]*/ /* we assume that L=(M_1,f_1,...,M_s,f_s) defines the complex C=(C^i,d^i) as in the procedure toVdstrictcomplex*/ matrix Bnew= divdr(L[2],L[3]); matrix Bold=Bnew; matrix Z=divdr(Bnew,L[1]); list bzh,zcb; bzh=list(list(),list(),Z,unitmat(ncols(Z)),Z); zcb=(Z, Bnew, L[1], unitmat(ncols(L[1])), Bnew); list sep; /* the list sep will be of size s such that -sep[i]=(sep[i][1],sep[i][2]) is a list of two lists -sep[i][1]=(B^i,f^(BZi),Z^i,f_^(ZHi),H^i) such that coker(B^i)->coker(Z^i) ->coker(H^i) represents the short exact seqeuence B^i(C)->Z^i(C)->H^i(C) -sep[i][2]=(Z^i,f^(ZCi),C^i,f^(CBi),B^(i+1)) such that coker(Z^i)->coker(C^i)-> coker(B^(i+1)) represents the short exact seqeuence Z^i(C)->C^i->B^(i+1)(C)*/ sep[1]=list(bzh,zcb); int i; list out; for (i=3; i<=size(L)-2; i=i+2) { /*the proc bzhzcb computes representations for the short exact seqeunces */ out=bzhzcb(Bold, L[i-1] , L[i], L[i+1], L[i+2]); sep[size(sep)+1]=out[1]; Bold=out[2]; } bzh=(divdr(L[size(L)-2], L[size(L)-1]),L[size(L)-2], L[size(L)-1]); bzh[4]=unitmat(ncols(L[size(L)-1])); bzh[5]=transpose(concat(transpose(L[size(L)-2]),transpose(L[size(L)-1]))); zcb=(L[size(L)-1], unitmat(ncols(L[size(L)-1])), L[size(L)-1],list(),list()); sep[size(sep)+1]=list(bzh,zcb); return(sep); } //////////////////////////////////////////////////////////////////////////////////// static proc bzhzcb (matrix Bold,matrix f0,matrix C1,matrix f1,matrix C2) { matrix Bnew=divdr(f1,C2); matrix Z= divdr(Bnew,C1); matrix lift1= matrixLift(Bnew,f0); matrix H=transpose(concat(transpose(lift1),transpose(Z))); list bzh=(Bold, lift1, Z, unitmat(ncols(Z)),H); list zcb=(Z, Bnew, C1, unitmat(ncols(C1)),Bnew); list out=(list(bzh, zcb), Bnew); return(out); } //////////////////////////////////////////////////////////////////////////////////// static proc shortExactPiecesToVdStrict(list C,int d,list #) {/* We transform the short exact pieces from procedure shortExactPieces to V_d- strict short exact sequences. For this, we use Algorithm 3.11 and Lemma 4.2 in [W2].*/ /* If we compute our Groebner bases in the homogenized Weyl algebra, we already compute some resolutions it omit additional Groebner basis computations later on.*/ int s =size(C);int i; int j; string Syzstring="Sres"; intvec v=0:ncols(C[s][1][5]); if (size(#)!=0) { for (i=1; i<=size(#); i++) { if (typeof(#[i])=="string") { Syzstring=#[i]; } if (typeof(#[i])=="intvec") { v=#[i]; } } } list out; list forout; if (Syzstring=="Vdres") { out[s]=list(toVdStrictSequence(C[s][1],d,v, Syzstring,s)); } else { forout=toVdStrictSequence(C[s][1],d,v, Syzstring,s); list resolutionofA=forout[9]; list resolutionofC=forout[10]; forout=delete(forout,10); forout=delete(forout,9); out[s]=list(forout); for (i=1; i<=size(resolutionofC); i++) { out[s][1][5][i+1]=resolutionofC[i];//save the resolutions out[s][1][1][i+1]=resolutionofA[i]; } } out[s][2]=list(list(out[s][1][3][1])); out[s][2][2]=list(unitmat(ncols(out[s][1][3][1]))); out[s][2][3]=list(out[s][1][3][1]); out[s][2][4]=list(list()); out[s][2][5]=list(list()); out[s][2][6]=list(out[s][1][7][1]); out[s][2][7]=list(out[s][2][6][1]); out[s][2][8]=list(list()); list resolutionofD; list resolutionofF; for (i=s-1; i>=2; i--) { C[i][2][5]=out[i+1][1][1][1]; forout=toVdStrictSequences(C[i],d,out[i+1][1][6][1],Syzstring,s); if (Syzstring=="Sres") { resolutionofD=forout[3];//save the resolutions resolutionofF=forout[4]; forout=delete(forout,4); forout=delete(forout,3); } out[i]=forout; if(Syzstring=="Sres") { for (j=2; j<=size(out[i+1][1][1]); j++) { out[i][2][5][j]=out[i+1][1][1][j]; } for (j=1; j<=size(resolutionofD);j++) { out[i][1][1][j+1]=resolutionofD[j]; out[i][1][5][j+1]=resolutionofF[j]; } } } out[1]=list(list());//initalize our list C[1][2][5]=out[2][1][1][1]; /*Compute the last V_d-strict seqeunce*/ if (Syzstring=="Vdres") { out[1][2]=toVdStrictSequence(C[1][2],d,out[2][1][6][1],Syzstring,s,"J_Agiv"); } else { forout=toVdStrictSequence(C[1][2],d,out[2][1][6][1],Syzstring,s,"J_Agiv"); out[1][2]=delete(forout,9); list resolutionofA2=forout[9]; for (i=1; i<=size(out[2][1][1]); i++) { /*put the modules for the resolutions in the right spot*/ out[1][2][5][i]=out[2][1][1][i]; } for (i=1; i<=size(resolutionofA2); i++) { out[1][2][1][i+1]=resolutionofA2[i]; } } out[1][1][3]=list(out[1][2][1][1]); out[1][1][5]=list(out[1][2][1][1]); out[1][1][4]=list(unitmat(ncols(out[1][1][3][1]))); out[1][1][7]=list(out[1][2][6][1]); out[1][1][8]=list(out[1][2][6][1]); out[1][1][1]=list(list()); out[1][1][2]=list(list()); out[1][1][6]=list(list()); if (Syzstring=="Sres") { for (i=1; i<=size(out[1][2][1]); i++) { out[1][1][3][i]=out[1][2][1][i]; out[1][1][5][i]=out[1][2][1][i]; } } list Hi; for (i=1; i<=size(out); i++) { Hi[i]=list(out[i][1][5][1],out[i][1][8][1]); } list outall; outall[1]=out; outall[2]=Hi; return(outall); } //////////////////////////////////////////////////////////////////////////////////// static proc toVdStrictSequence(list C,int n,intvec v,string Syzstring,int si,list #) { /*this is the Algorithm 3.11 in [W2]*/ int omitemptylist; int lengthofres=si+n-1; int i,j,logens; def B=basering; matrix bi=slimgb(transpose(C[5])); /* Computation of a V_d-strict Groebner basis of C[5]: -if Syzstring=="Vdres" this is done using the method of weighted homogenization (Prop. 3.9 [OT]) -else we use the homogenized Weyl algebra for Groebner basis computations (Prop 9.9 [OT]), in this case we already compute someresolutions (Thm. 9.10 [OT]) to omit extra Groebner basis computations later on*/ int nr,nc; intvec i1,i2; if (Syzstring=="Vdres") { if(size(#)==0) { matrix J_C=VdStrictGB(C[5],n,list(v)); } else { matrix J_C=C[5];//C[5] is already a V_d-strict Groebner basis } } else { if (size(#)==0) { matrix MC=C[5]; def HomWeyl=makeHomogenizedWeyl(nvars(B) div 2, v); setring HomWeyl; matrix J_C=fetch(B,MC); J_C=nHomogenize(J_C); /*computation of V_d-strict resolution of C[5]->needed for proc VdstrictDoubleComplexes*/ def ringofSyz=Sres(transpose(J_C),lengthofres); setring ringofSyz; matrix J_C=transpose(matrix(RES[2])); J_C=subst(J_C,h,1); logens=ncols(J_C)+1; matrix zerom; list rofC;//will contain resolution of C for (i=3; i<=n+si+1; i++) { if (size(RES)>=i) { zerom=matrix(0,nrows(matrix(RES[i])),ncols(matrix(RES[i]))); if (RES[i]!=zerom) { rofC[i-2]=(matrix(RES[i])); if (i==3) { if (nrows(rofC[i-2])-logens+1!=nrows(J_C)) { //build the resolution nr=nrows(J_C)+logens-1; nc=ncols(rofC[i-2]); rofC[i-2]=matrix(rofC[i-2],nr,nc); } } if (i!=3) { if (nrows(rofC[i-2])-logens+1!=nrows(rofC[i-3])) { nr=nrows(rofC[i-3])+logens-1; nc=ncols(rofC[i-2]); rofC[i-2]=matrix(rofC[i-2],nr,nc); } } i1=intvec(logens..nrows(rofC[i-2])); i2=intvec(1..ncols(rofC[i-2])); rofC[i-2]=transpose(submat(rofC[i-2],i1,i2)); logens=logens+ncols(rofC[i-2]); rofC[i-2]=subst(rofC[i-2],h,1); } else { rofC[i-2]=list(); } } else { rofC[i-2]=list(); } } if(size(rofC[1])==0) { omitemptylist=1; } setring B; matrix J_C=fetch(ringofSyz,J_C); if (omitemptylist!=1) { list rofC=fetch(ringofSyz,rofC); } omitemptylist=0; kill HomWeyl; kill ringofSyz; } else { matrix J_C=C[5];//C[5] is already a V_d-strict Groebner basis } } /* we compute a V_d-strict Groebner basis for C[3]*/ matrix J_A=C[1]; matrix f_CB=C[4]; matrix f_ACB=transpose(concat(transpose(C[2]),transpose(f_CB))); matrix J_AC=divdr(f_ACB,C[3]); matrix P=matrixLift(J_AC * prodr(ncols(C[1]),ncols(C[5])) ,J_C); list storePi; matrix Pi[1][ncols(J_AC)]; for (i=1; i<=nrows(J_C); i++) { for (j=1; j<=nrows(J_AC);j++) { Pi=Pi+P[i,j]*submat(J_AC,j,intvec(1..ncols(J_AC))); } storePi[i]=Pi; Pi=0; } /*we compute the shift vector for C[1]*/ intvec m_a; list findMin; int comMin; for (i=1; i<=ncols(J_A); i++) { for (j=1; j<=size(storePi);j++) { if (storePi[j][1,i]!=0) { comMin=VdDeg(storePi[j]*prodr(ncols(J_A),ncols(C[5])),n,v); comMin=comMin-VdDeg(storePi[j][1,i],n,intvec(0)); findMin[size(findMin)+1]=comMin; } } if (size(findMin)!=0) { m_a[i]=Min(findMin); findMin=list(); } else { m_a[i]=0; } } matrix zero[ncols(J_A)][ncols(J_C)]; matrix g_AB=concat(unitmat(ncols(J_A)),zero); matrix g_BC= transpose(concat(transpose(zero),transpose(unitmat(ncols(J_C))))); intvec m_b=m_a,v; /* computation of a V_d-strict Groebner basis of C[1] (and resolution if Syzstring=='Vdres') */ if (Syzstring=="Vdres") { J_A=VdStrictGB(J_A,n,m_a); } else { def HomWeyl=makeHomogenizedWeyl(nvars(B) div 2, m_a); setring HomWeyl; matrix J_A=fetch(B,J_A); J_A=nHomogenize(J_A); def ringofSyz=Sres(transpose(J_A),lengthofres); setring ringofSyz; matrix J_A=transpose(matrix(RES[2])); matrix zerom; J_A=subst(J_A,h,1); logens=ncols(J_A)+1; list rofA; for (i=3; i<=n+si+1; i++) { if (size(RES)>=i) { zerom=matrix(0,nrows(matrix(RES[i])),ncols(matrix(RES[i]))); if (RES[i]!=zerom) { rofA[i-2]=matrix(RES[i]);// resolution for C[1] if (i==3) { if (nrows(rofA[i-2])-logens+1!=nrows(J_A)) { nr=nrows(J_A)+logens-1; nc=ncols(rofA[i-2]); rofA[i-2]=matrix(rofA[i-2],nr,nc); } } if (i!=3) { if (nrows(rofA[i-2])-logens+1!=nrows(rofA[i-3])) { nr=nrows(rofA[i-3])+logens-1; nc=ncols(rofA[i-2]); rofA[i-2]=matrix(rofA[i-2],nr,nc); } } i1=intvec(logens..nrows(rofA[i-2])); i2=intvec(1..ncols(rofA[i-2])); rofA[i-2]=transpose(submat(rofA[i-2],i1,i2)); logens=logens+ncols(rofA[i-2]); rofA[i-2]=subst(rofA[i-2],h,1); } else { rofA[i-2]=list(); } } else { rofA[i-2]=list(); } } if(size(rofA[1])==0) { omitemptylist=1; } setring B; J_A=fetch(ringofSyz,J_A); if (omitemptylist!=1) { list rofA=fetch(ringofSyz,rofA); } omitemptylist=0; kill HomWeyl; kill ringofSyz; } J_AC=transpose(storePi[1]); for (i=2; i<= size(storePi); i++) { J_AC=concat(J_AC, transpose(storePi[i])); } J_AC=transpose(concat(transpose(matrix(J_A,nrows(J_A),nrows(J_AC))),J_AC)); list Vdstrict=(list(J_A),list(g_AB),list(J_AC),list(g_BC),list(J_C),list(m_a)); Vdstrict[7]=list(m_b); Vdstrict[8]=list(v); if(Syzstring=="Sres") { Vdstrict[9]=rofA; if(size(#)==0) { Vdstrict[10]=rofC; } } return (Vdstrict); } //////////////////////////////////////////////////////////////////////////////////// static proc toVdStrictSequences (list L,int d,intvec v,string Syzstring,int sizeL) { /* this is Argorithm 3.11 combined with Lemma 4.2 in [W2] for two short exact pieces. We asume that we are given two sequences of the form coker(L[i][1])-> coker(L[i][3])->coker(L[i][5]) with differentials L[i][2] and L[i][4] such that L[1][3]=L[2][1].We are going to transform them to V_d-strict sequences J_D->J_A->J_F and J_A->J_B->J_C*/ int omitemptylist; int lengthofres=sizeL+d-1; int logens; def B=basering; matrix J_F=L[1][5]; matrix J_D=L[1][1]; matrix f_FA=L[1][4]; /*We find new presentations coker(J_DF) and coker(J_DFC) for L[1][4]=L[2][1] and L[2][4],resp. such that ncols(L[i][1])+ncols(L[i][5])=ncols(L[i][3]) */ matrix f_DFA=transpose(concat(transpose(L[1][2]),transpose(f_FA))); matrix J_DF=divdr(f_DFA,L[1][3]);//coker(J_DF) is isomorphic to coker(L[2][1]); matrix J_C=L[2][5]; matrix f_CB=L[2][4]; matrix f_DFCB=transpose(concat(transpose(f_DFA*L[2][2]),transpose(f_CB))); matrix J_DFC=divdr(f_DFCB,L[2][3]);//coker(J_DFC) are coker(L[2][3)]) isomorphic /* find a shift vector on the range of J_F such that the first sequence is exact*/ matrix P=matrixLift(J_DFC*prodr(ncols(J_DF),ncols(L[2][5])),J_C); list storePi; matrix Pi[1][ncols(J_DFC)]; int i; int j; for (i=1; i<=nrows(J_C); i++) { for (j=1; j<=nrows(J_DFC);j++) { Pi=Pi+P[i,j]*submat(J_DFC,j,intvec(1..ncols(J_DFC))); } storePi[i]=Pi; Pi=0; } intvec m_a; list findMin; list noMin; int comMin; int nr,nc; intvec i1,i2; for (i=1; i<=ncols(J_DF); i++) { for (j=1; j<=size(storePi);j++) { if (storePi[j][1,i]!=0) { comMin=VdDeg(storePi[j]*prodr(ncols(J_DF),ncols(J_C)),d,v); comMin=comMin-VdDeg(storePi[j][1,i],d,intvec(0)); findMin[size(findMin)+1]=comMin; } } if (size(findMin)!=0) { m_a[i]=Min(findMin);// shift vector for L[2][1] findMin=list(); noMin[i]=0; } else { noMin[i]=1; } } if (size(m_a) < ncols(J_DF)) { m_a[ncols(J_DF)]=0; } intvec m_f=m_a[ncols(J_D)+1..size(m_a)]; /* Computation of a V_d-strict Groebner basis of J_F=L[1][5]: if Syzstring=="Vdres" this is done using the method of weighted homogenization (Prop. 3.9 [OT]) else we use the homogenized Weyl algerba for Groebner basis computations (Prop 9.9 [OT]), in this case we already compute resolutions (Thm. 9.10 in [OT]) to omit extra Groebner basis computations later on*/ if (Syzstring=="Vdres") { J_F=VdStrictGB(J_F,d,m_f); } else { def HomWeyl=makeHomogenizedWeyl(nvars(B) div 2, m_f); setring HomWeyl; matrix J_F=fetch(B,J_F); J_F=nHomogenize(J_F); def ringofSyz=Sres(transpose(J_F),lengthofres); setring ringofSyz; matrix J_F=transpose(matrix(RES[2])); J_F=subst(J_F,h,1); logens=ncols(J_F)+1; list rofF; for (i=3; i<=d+sizeL+1; i++) { if (size(RES)>=i) { if (RES[i]!=matrix(0,nrows(matrix(RES[i])),ncols(matrix(RES[i])))) { rofF[i-2]=(matrix(RES[i]));// resolution for J_F if (i==3) { if (nrows(rofF[i-2])-logens+1!=nrows(J_F)) { nr=nrows(J_F)+logens-1; nc=ncols(rofF[i-2]); rofF[i-2]=matrix(rofF[i-2],nr,nc); } } if (i!=3) { if (nrows(rofF[i-2])-logens+1!=nrows(rofF[i-3])) { nr=nrows(rofF[i-3])+logens-1; rofF[i-2]=matrix(rofF[i-2],nr,ncols(rofF[i-2])); } } i1=intvec(logens..nrows(rofF[i-2])); i2=intvec(1..ncols(rofF[i-2])); rofF[i-2]=transpose(submat(rofF[i-2],i1,i2)); logens=logens+ncols(rofF[i-2]); rofF[i-2]=subst(rofF[i-2],h,1); } else { rofF[i-2]=list(); } } else { rofF[i-2]=list(); } } if(size(rofF[1])==0) { omitemptylist=1; } setring B; J_F=fetch(ringofSyz,J_F); if (omitemptylist!=1) { list rofF=fetch(ringofSyz,rofF); } omitemptylist=0; kill HomWeyl; kill ringofSyz; } /*find shift vectors on the range of J_D*/ P=matrixLift(J_DF * prodr(ncols(L[1][1]),ncols(L[1][5])) ,J_F); list storePinew; matrix Pidf[1][ncols(J_DF)]; for (i=1; i<=nrows(J_F); i++) { for (j=1; j<=nrows(J_DF);j++) { Pidf=Pidf+P[i,j]*submat(J_DF,j,intvec(1..ncols(J_DF))); } storePinew[i]=Pidf; Pidf=0; } intvec m_d; for (i=1; i<=ncols(J_D); i++) { for (j=1; j<=size(storePinew);j++) { if (storePinew[j][1,i]!=0) { comMin=VdDeg(storePinew[j]*prodr(ncols(J_D),ncols(L[1][5])),d,m_f); comMin=comMin-VdDeg(storePinew[j][1,i],d,intvec(0)); findMin[size(findMin)+1]=comMin; } } if (size(findMin)!=0) { if (noMin[i]==0) { m_d[i]=Min(insert(findMin,m_a[i])); m_a[i]=m_d[i]; } else { m_d[i]=Min(findMin); m_a[i]=m_d[i]; } } else { m_d[i]=m_a[i]; } findMin=list(); } /* compute a V_d-strict Groebner basis (and resolution of J_D if Syzstring!='Vdres') for J_D*/ if (Syzstring=="Vdres") { J_D=VdStrictGB(J_D,d,m_d); } else { def HomWeyl=makeHomogenizedWeyl(nvars(B) div 2, m_d); setring HomWeyl; matrix J_D=fetch(B,J_D); J_D=nHomogenize(J_D); def ringofSyz=Sres(transpose(J_D),lengthofres); setring ringofSyz; matrix J_D=transpose(matrix(RES[2])); J_D=subst(J_D,h,1); logens=ncols(J_D)+1; list rofD; for (i=3; i<=d+sizeL+1; i++) { if (size(RES)>=i) { if (RES[i]!=matrix(0,nrows(matrix(RES[i])),ncols(matrix(RES[i])))) { rofD[i-2]=(matrix(RES[i]));// resolution for J_D if (i==3) { if (nrows(rofD[i-2])-logens+1!=nrows(J_D)) { nr=nrows(J_D)+logens-1; rofD[i-2]=matrix(rofD[i-2],nr,ncols(rofD[i-2])); } } if (i!=3) { if (nrows(rofD[i-2])-logens+1!=nrows(rofD[i-3])) { nr=nrows(rofD[i-3])+logens-1; rofD[i-2]=matrix(rofD[i-2],nr,ncols(rofD[i-2])); } } i1=intvec(logens..nrows(rofD[i-2])); i2=intvec(1..ncols(rofD[i-2])); rofD[i-2]=transpose(submat(rofD[i-2],i1,i2)); logens=logens+ncols(rofD[i-2]); rofD[i-2]=subst(rofD[i-2],h,1); } else { rofD[i-2]=list(); } } else { rofD[i-2]=list(); } } if(size(rofD[1])==0) { omitemptylist=1; } setring B; J_D=fetch(ringofSyz,J_D); if (omitemptylist!=1) { list rofD=fetch(ringofSyz,rofD); } omitemptylist=0; kill HomWeyl; kill ringofSyz; } /* compute new matrices for J_A and J_B such that their rows form a V_d-strict Groebner basis and nrows(J_A)=nrows(J_D)+nrows(J_F) and nrows(J_B)=nrows(J_A)+nrows(J_C)*/ J_DF=transpose(storePinew[1]); for (i=2; i<=nrows(J_F); i++) { J_DF=concat(J_DF,transpose(storePinew[i])); } J_DF=transpose(concat(transpose(matrix(J_D,nrows(J_D),nrows(J_DF))),J_DF)); J_DFC=transpose(storePi[1]); for (i=2; i<=nrows(J_C); i++) { J_DFC=concat(J_DFC,transpose(storePi[i])); } J_DFC=transpose(concat(transpose(matrix(J_DF,nrows(J_DF),nrows(J_DFC))),J_DFC)); intvec m_b=m_a,v; matrix zero[ncols(J_D)][ncols(J_F)]; matrix g_DA=concat(unitmat(ncols(J_D)),zero); matrix g_AF=transpose(concat(transpose(zero),unitmat(ncols(J_F)))); matrix zero1[ncols(J_DF)][ncols(J_C)]; matrix g_AB=concat(unitmat(ncols(J_DF)),zero1); matrix g_BC=transpose(concat(transpose(zero1),unitmat(ncols(J_C)))); list out; out[1]=list(list(J_D),list(g_DA),list(J_DF),list(g_AF),list(J_F)); out[1]=out[1]+list(list(m_d),list(m_a),list(m_f)); out[2]=list(list(J_DF),list(g_AB),list(J_DFC),list(g_BC),list(J_C)); out[2]=out[2]+list(list(m_a),list(m_b),list(v)); if (Syzstring=="Sres") { out[3]=rofD; out[4]=rofF; } return(out); } //////////////////////////////////////////////////////////////////////////////////// static proc VdStrictDoubleComplexes(list L,int d,string Syzstring) { /* We compute V_d-strict resolutions over the V_d-strict short exact pieces from the procedure shortExactPiecesToVdStrict. We use Algorithms 3.14 and 3.15 in [W2]*/ int i,k,c,j,l,totaldeg,comparedegs,SBcom,verk; intvec fordegs; intvec n_b,i1,i2; matrix rem,forML,subm,zerom,unitm,subm2; matrix J_B; list store; int t=size(L)+d; int vd1,vd2,nr,nc; def B=basering; int n=nvars(B) div 2; intvec v; list forhW; if (Syzstring=="Sres") { /*we already computed some of the resolutions in the procedure shortExactPiecesToVdStrict*/ matrix Pold,Pnew,Picombined; intvec containsndeg; matrix Pinew; for (k=1; k<=(size(L)+d-1); k++) { L[1][1][1][k+1]=list(); L[1][1][2][k+1]=list(); L[1][1][6][k+1]=list(); } L[1][1][6][size(L)+d+1]=list(); matrix mem; for (i=2; i<=d+size(L)+1; i++) {; v=0; if(size(L[1][1][3][i-1])!=0) { if(i!=d+size(L)+1) { /*horizontal differential*/ L[1][1][4][i-1]=unitmat(nrows(L[1][1][3][i-1])); } for (j=1; j<=nrows(L[1][1][3][i-1]); j++) { mem=submat(L[1][1][3][i-1],j,intvec(1..ncols(L[1][1][3][i-1]))); v[j]=VdDeg(mem,d,L[1][1][7][i-1]); } L[1][1][7][i]=v;//new shift vector L[1][1][8][i]=v; L[1][2][6][i]=v; } else { if (i!=d+size(L)+1) { L[1][1][4][i-1]=list(); } L[1][1][7][i]=list(); L[1][1][8][i]=list(); L[1][2][6][i]=list(); } } if (size(L[1][1][3][d+size(L)])!=0) { /*horizontal differential*/ L[1][1][4][d+size(L)]=unitmat(nrows(L[1][1][3][d+size(L)])); } else { L[1][1][4][d+size(L)]=list(); } for (k=1; k coker(L[k][2][3][1])->coker(L[k][2][5][1]) using the resolution obtained for coker(L[k][1][3][1]). L[k][2][i][j] will be the jth module in the resolution of L[k][2][i][1] for i=1,3,5. L[k][2][i+5][j] will be the jth shift vector in the resolution of L[k][2][i][1](this holds also for the case Syzstring=="Vdres")*/ for (i=2; i<=d+size(L); i++) { v=0; if (size(L[k][2][5][i-1])!=0) { for (j=1; j<=nrows(L[k][2][5][i-1]); j++) { i1=intvec(1..ncols(L[k][2][5][i-1])); mem=submat(L[k][2][5][i-1],j,i1); v[j]=VdDeg(mem,d,L[k][2][8][i-1]); } /*next shift vector in th resolution of coker(L[k][2][5][1])*/ L[k][2][8][i]=v; } else { L[k][2][8][i]=list(); } /* we build step by step a resolution for coker(L[k][2][5][1]) using the resolutions of coker(L[k][2][1][1]) and coker(L[k][2][5][1])*/ if (size(L[k][2][5][i])!=0) { if (size(L[k][2][1][i])!=0 or size(L[k][2][1][i-1])!=0) { L[k][2][3][i]=transpose(syz(transpose(L[k][2][3][i-1]))); nr= nrows(L[k][2][1][i-1]); nc=ncols(L[k][2][5][i]); Pold=matrixLift(L[k][2][3][i]*prodr(nr,nc), L[k][2][5][i]); matrix Pi[1][ncols(L[k][2][3][i])]; for (l=1; l<=nrows(L[k][2][5][i]); l++) { for (j=1; j<=nrows(L[k][2][3][i]); j++) { i2=intvec(1..ncols(L[k][2][3][i])); Pi=Pi+Pold[l,j]*submat(L[k][2][3][i],j,i2); } if (l==1) { Picombined=transpose(Pi); } else { Picombined=concat(Picombined,transpose(Pi)); } Pi=0; } kill Pi; Picombined=transpose(Picombined); if (size(L[k][2][1][i])!=0) { if (i==2) { containsndeg=(0:ncols(L[k][2][1][1])); } containsndeg=nDeg(L[k][2][1][i-1],containsndeg); forhW=list(L[k][2][6][i],containsndeg); def HomWeyl=makeHomogenizedWeyl(n,forhW); setring HomWeyl; list L=fetch(B,L); matrix M=L[k][2][1][i]; module Mmod; list forM=nHomogenize(M,containsndeg,1); M=forM[1]; totaldeg=forM[2]; kill forM; matrix Maorig=fetch(B,Picombined); matrix Ma=submat(Maorig,(1..nrows(Maorig)),(1..ncols(M))); matrix mem,subm,zerom; matrix Pinew; M=transpose(M); SBcom=0; for (l=1; l<=nrows(Ma); l++) { zerom=matrix(0,1,(ncols(Maorig)-ncols(Ma))); i1=(ncols(Ma)+1..ncols(Maorig)); if (submat(Maorig,l,i1)==zerom) { for (cc=1; cc<=ncols(Ma); cc++) { Maorig[l,cc]=0; } } i2=(ncols(Ma)+1..ncols(Maorig)); i1=(1..ncols(Ma)); if (VdDeg(submat(Maorig,l,i1),d,L[k][2][6][i])> VdDeg(submat(Maorig,l,i2),d,L[k][2][8][i]) and submat(Maorig,l,i1)!=matrix(0,1,ncols(Ma))) { /*V_d-Grad is to big--> we make it smaller using Vdnormal form computations*/ if (SBcom==0) { Mmod=slimgb(M); M=Mmod; SBcom=1; } //print("Reduzierung des V_d-Grades(Stelle1)"); i2=(ncols(Ma)+1..ncols(Maorig)); vd1=VdDeg(submat(Maorig,l,i2),d,L[k][2][8][i]); mem=submat(Ma,l,(1..ncols(Ma))); mem=nHomogenize(mem,containsndeg); mem=h^totaldeg*mem; mem=transpose(mem); mem=reduce(mem,Mod);////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// matrix jt=transpose(subst(mem,h,1)); setring B; matrix jt=fetch(HomWeyl,jt); matrix need=fetch(HomWeyl,Maorig); need=submat(need,l,(1..ncols(need))); i1=L[k][2][6][i]; i2=L[k][2][8][i]; jt=VdNormalForm(need,L[k][2][1][i],d,i1,i2); setring HomWeyl; mem=fetch(B,jt); mem=transpose(mem); if (l==1) { Pinew=mem; } else { Pinew=concat(Pinew,mem); } vd2=VdDeg(transpose(mem),d,L[k][2][6][i]); if (vd2>vd1 and mem!=matrix(0,nrows(mem),ncols(mem))) {//should not happen!! //print("Reduzierung fehlgeschlagen!!(Stelle1)"); } } else { if (l==1) { Pinew=transpose(submat(Ma,l,(1..ncols(Ma)))); } else { subm=transpose(submat(Ma,l,(1..ncols(Ma)))); Pinew=concat(Pinew,subm); } } } Pinew=subst(Pinew,h,1); Pinew=transpose(Pinew); setring B; Pinew=fetch(HomWeyl,Pinew); kill HomWeyl; L[k][2][3][i]=concat(Pinew,L[k][2][5][i]); subm=transpose(L[k][2][3][i]); subm=concat(transpose(L[k][2][1][i]),subm); L[k][2][3][i]=transpose(subm); } else { L[k][2][3][i]=Picombined; } L[k+1][1][1][i]=L[k][2][5][i]; nr=nrows(L[k][2][1][i-1]); nc=ncols(L[k][2][5][i]); L[k][2][2][i]=concat(unitmat(nr),matrix(0,nr,nc)); L[k][2][4][i]=prodr(nrows(L[k][2][1][i-1]),nc); v=L[k][2][6][i],L[k][2][8][i]; L[k][2][7][i]=v; L[k+1][1][6][i]=L[k][2][8][i]; } else { L[k][2][3][i]=L[k][2][5][i]; L[k][2][2][i]=list(); L[k][2][7][i]=L[k][2][8][i]; L[k][2][4][i]=unitmat(nrows(L[k][2][5][i-1])); L[k+1][1][6][i]=L[k][2][8][i]; L[k+1][1][1][i]=L[k][2][5][i]; } } else { if (size(L[k][2][1][i])!=0) { if (size(L[k][2][5][i-1])!=0) { nr=nrows(L[k][2][5][i-1]); L[k][2][3][i]=concat(L[k][2][1][i],matrix(0,1,nr)); v=L[k][2][6][i],L[k][2][8][i]; L[k][2][7][i]=v; nc=nrows(L[k][2][1][i-1]); L[k][2][2][i]=concat(unitmat(nc),matrix(0,nc,nr)); L[k][2][4][i]=prodr(nrows(L[k][2][1][i-1]),nr); } else { L[k][2][3][i]=L[k][2][1][i]; L[k][2][7][i]=L[k][2][6][i]; L[k][2][2][i]=unitmat(nrows(L[k][2][1][i-1])); L[k][2][4][i]=list(); } L[k+1][1][1][i]=L[k][2][5][i]; L[k+1][1][6][i]=L[k][2][8][i]; } else { L[k][2][3][i]=list(); if (size(L[k][2][6][i])!=0) { if (size(L[k][2][8][i])!=0) { v=L[k][2][6][i],L[k][2][8][i]; L[k][2][7][i]=v; nr=nrows(L[k][2][1][i-1]); nc=nrows(L[k][2][5][i-1]); L[k][2][2][i]=concat(unitmat(nc),matrix(0,nr,nc)); L[k][2][4][i]=prodr(nr,nrows(L[k][2][5][i-1])); } else { L[k][2][7][i]=L[k][2][6][i]; L[k][2][2][i]=unitmat(nrows(L[k][2][1][i-1])); L[k][2][4][i]=list(); } } else { if (size(L[k][2][8][i])!=0) { L[k][2][7][i]=L[k][2][8][i]; L[k][2][2][i]=list(); L[k][2][4][i]=unitmat(nrows(L[k][2][5][i-1])); } else { L[k][2][7][i]=list(); L[k][2][2][i]=list(); L[k][2][4][i]=list(); } } L[k+1][1][1][i]=L[k][2][5][i]; L[k+1][1][6][i]=L[k][2][8][i]; } } } i=d+size(L)+1; v=0; if (size(L[k][2][5][i-1])!=0) { for (j=1; j<=nrows(L[k][2][5][i-1]); j++) { mem=submat(L[k][2][5][i-1],j,intvec(1..ncols(L[k][2][5][i-1]))); v[j]=VdDeg(mem,d,L[k][2][8][i-1]); } L[k][2][8][i]=v; if (size(L[k][2][6][i])!=0) { v=L[k][2][6][i],L[k][2][8][i]; L[k][2][7][i]=v; } else { L[k][2][7][i]=L[k][2][8][i]; } } else { L[k][2][8][i]=list(); L[k][2][7][i]=L[k][2][6][i]; } L[k+1][1][6][i]=L[k][2][8][i]; /* now we build V_d-strict resolutions for the sequences coker(L[k+1][1][1][1])->coker(L[k+1][1][3][1])->coker(L[k+1][1][5][i]) using the resolutions for coker(L[k][2][5][1]) we just obtained (works exactly the same as above)*/ for (i=2; i<=d+size(L); i++) { v=0; if (size(L[k+1][1][5][i-1])!=0) { for (j=1; j<=nrows(L[k+1][1][5][i-1]); j++) { i1=intvec(1..ncols(L[k+1][1][5][i-1])); mem=submat(L[k+1][1][5][i-1],j,i1); v[j]=VdDeg(mem,d,L[k+1][1][8][i-1]); } L[k+1][1][8][i]=v; } else { L[k+1][1][8][i]=list(); } if (size(L[k+1][1][5][i])!=0) { if (size(L[k+1][1][1][i])!=0 or size(L[k+1][1][1][i-1])!=0) { L[k+1][1][3][i]=transpose(syz(transpose(L[k+1][1][3][i-1]))); nr=nrows(L[k+1][1][1][i-1]); nc=ncols(L[k+1][1][5][i]); Pold=matrixLift(L[k+1][1][3][i]*prodr(nr,nc),L[k+1][1][5][i]); matrix Pi[1][ncols(L[k+1][1][3][i])]; for (l=1; l<=nrows(L[k+1][1][5][i]); l++) { for (j=1; j<=nrows(L[k+1][1][3][i]); j++) { i2=intvec(1..ncols(L[k+1][1][3][i])); Pi=Pi+Pold[l,j]*submat(L[k+1][1][3][i],j,i2); } if (l==1) { Picombined=transpose(Pi); } else { Picombined=concat(Picombined,transpose(Pi)); } Pi=0; } kill Pi; Picombined=transpose(Picombined); if(size(L[k+1][1][1][i])!=0) { if (i==2) { containsndeg=(0:ncols(L[k+1][1][1][i-1])); } containsndeg=nDeg(L[k+1][1][1][i-1],containsndeg); forhW=list(L[k+1][1][6][i], containsndeg); def HomWeyl=makeHomogenizedWeyl(n,forhW); setring HomWeyl; list L=fetch(B,L); matrix M=L[k+1][1][1][i]; module Mmod; list forM=nHomogenize(M,containsndeg,1); M=forM[1]; totaldeg=forM[2]; kill forM; matrix Maorig=fetch(B,Picombined); matrix Ma=submat(Maorig,(1..nrows(Maorig)),(1..ncols(M))); Ma=nHomogenize(Ma,containsndeg); matrix mem,subm,zerom,subm2; matrix Pinew; M=transpose(M); SBcom=0; for (l=1; l<=nrows(Ma); l++) { i2=(ncols(Ma)+1..ncols(Maorig)); nc=ncols(Maorig)-ncols(Ma); if (submat(Maorig,l,i2)==matrix(0,1,nc)) { for (cc=1; cc<=ncols(Ma); cc++) { Maorig[l,cc]=0; } } i1=(1..ncols(Ma)); i2=L[k+1][1][8][i]; subm=submat(Maorig,l,i1); subm2=submat(Maorig,l,(ncols(Ma)+1..ncols(Maorig))); if (VdDeg(subm,d,L[k+1][1][6][i])>VdDeg(subm2,d,i2) and subm!=matrix(0,1,ncols(Ma))) { //print("Reduzierung des Vd-Grades (Stelle2)"); if (SBcom==0) { Mmod=slimgb(M); M=Mmod; SBcom=1; } vd1=VdDeg(subm2,d,L[k+1][1][8][i]); mem=submat(Ma,l,(1..ncols(Ma))); mem=nHomogenize(mem,containsndeg); mem=h^totaldeg*mem; mem=transpose(mem); mem=reduce(mem,Mmod); if (l==1) { Pinew=mem; } else { Pinew=concat(Pinew,mem); } vd2=VdDeg(transpose(mem),d,L[k+1][1][6][i]); if (vd2>vd1 and mem!=matrix(0,nrows(mem),ncols(mem))) {//should not happen //print("Reduzierung fehlgeschlagen!!!!(Stelle2)"); } } else { if (l==1) { Pinew=transpose(submat(Ma,l,(1..ncols(Ma)))); } else { subm=transpose(submat(Ma,l,(1..ncols(Ma)))); Pinew=concat(Pinew,subm); } } } Pinew=subst(Pinew,h,1); Pinew=transpose(Pinew); setring B; Pinew=fetch(HomWeyl,Pinew); kill HomWeyl; L[k+1][1][3][i]=concat(Pinew,L[k+1][1][5][i]); subm=transpose(L[k+1][1][1][i]); subm2=transpose(L[k+1][1][3][i]); L[k+1][1][3][i]=transpose(concat(subm,subm2)); } else { L[k+1][1][3][i]=Picombined; } L[k+1][2][1][i]=L[k+1][1][3][i]; nr=nrows(L[k+1][1][1][i-1]); nc=ncols(L[k+1][1][5][i]); L[k+1][1][2][i]=concat(unitmat(nr),matrix(0,nr,nc)); L[k+1][1][4][i]=prodr(nr,nc); v=L[k+1][1][6][i],L[k+1][1][8][i]; L[k+1][1][7][i]=v; L[k+1][2][6][i]=L[k+1][1][7][i]; } else { L[k+1][1][3][i]=L[k+1][1][5][i]; L[k+1][1][2][i]=list(); L[k+1][1][4][i]=unitmat(nrows(L[k+1][1][5][i-1])); L[k+1][1][7][i]=L[k+1][1][8][i]; L[k+1][2][6][i]=L[k+1][1][7][i]; L[k+1][2][1][i]=L[k+1][1][3][i]; } } else { if (size(L[k+1][1][1][i])!=0) { if (size(L[k+1][1][5][i-1])!=0) { zerom=matrix(0,1,nrows(L[k+1][1][5][i-1])); L[k+1][1][3][i]=concat(L[k+1][1][1][i],zerom); v=L[k+1][1][6][i],L[k+1][1][8][i]; L[k+1][1][7][i]=v; nr=nrows(L[k+1][1][1][i-1]); nc=nrows(L[k+1][1][5][i-1]); L[k+1][1][2][i]=concat(unitmat(nr),matrix(0,nr,nc)); L[k+1][1][4][i]=prodr(nr,nc); } else { L[k+1][1][3][i]=L[k+1][1][1][i]; L[k+1][1][7][i]=L[k+1][1][6][i]; L[k+1][1][2][i]=unitmat(nrows(L[k+1][1][1][i-1])); L[k+1][1][4][i]=list(); } L[k+1][2][1][i]=L[k+1][1][3][i]; L[k+1][2][6][i]=L[k+1][1][7][i]; } else { L[k+1][1][3][i]=list(); if (size(L[k+1][1][6][i])!=0) { if (size(L[k+1][1][8][i])!=0) { v=L[k+1][1][6][i],L[k+1][1][8][i]; L[k+1][1][7][i]=v; nr=nrows(L[k+1][1][1][i-1]); nc=nrows(L[k+1][1][5][i-1]); L[k+1][1][2][i]=concat(unitmat(nr),matrix(0,nr,nc)); L[k+1][1][4][i]=prodr(nr,nrows(L[k+1][1][5][i-1])); } else { L[k+1][1][7][i]=L[k+1][1][6][i]; L[k+1][1][2][i]=unitmat(nrows(L[k+1][1][1][i-1])); L[k+1][1][4][i]=list(); } } else { if (size(L[k+1][1][8][i])!=0) { L[k+1][1][7][i]=L[k+1][1][8][i]; L[k+1][1][2][i]=list(); L[k+1][1][4][i]=unitmat(nrows(L[k+1][1][5][i-1])); } else { L[k+1][1][7][i]=list(); L[k+1][1][2][i]=list(); L[k+1][1][4][i]=list(); } } L[k+1][2][1][i]=L[k+1][1][3][i]; L[k+1][2][6][i]=L[k+1][1][7][i]; } } } i=size(L)+d+1; v=0; if (size(L[k+1][1][5][i-1])!=0) { for (j=1; j<=nrows(L[k+1][1][5][i-1]); j++) { i1=intvec(1..ncols(L[k+1][1][5][i-1])); mem=submat(L[k+1][1][5][i-1],j,i1); v[j]=VdDeg(mem,d,L[k+1][1][8][i-1]); } L[k+1][1][8][i]=v; if (size(L[k+1][1][6][i])!=0) { v=L[k+1][1][6][i],L[k+1][1][8][i]; L[k+1][1][7][i]=v; } else { L[k+1][1][7][i]=L[k+1][1][8][i]; } } else { L[k+1][1][8][i]=list(); L[k+1][1][7][i]=L[k+1][1][8][i]; } L[k+1][2][6][i]=L[k+1][1][7][i]; } for (k=1; k<=(size(L)+d); k++) { L[size(L)][2][5][k]=list(); L[size(L)][2][4][k]=list(); L[size(L)][2][8][k]=list(); L[size(L)][2][3][k]=L[size(L)][2][1][k]; L[size(L)][2][7][k]=L[size(L)][2][6][k]; } L[size(L)][2][7][size(L)+d+1]=L[size(L)][2][6][size(L)+d+1]; L[size(L)][2][8][size(L)+d+1]=list(); /* building the resolution of the last short exact piece*/ for (i=2; i<=d+size(L); i++) { v=0; if(size(L[size(L)][2][1][i-1])!=0) { L[size(L)][2][2][i]=unitmat(nrows(L[size(L)][2][1][i-1])); } else { L[size(L)][2][2][i-1]=list(); } } return(L); } /*case Syzstring=="Vdres"*/ list forVd; for (k=1; k<=(size(L)+d); k++)//????? { /* we compute a V_d-strict resolution for the first short exact piece*/ L[1][1][1][k+1]=list(); L[1][1][2][k+1]=list(); L[1][1][6][k+1]=list(); if (size(L[1][1][3][k])!=0) { for (i=1; i<=nrows(L[1][1][3][k]); i++) { rem=submat(L[1][1][3][k],i,(1..ncols(L[1][1][3][k]))); n_b[i]=VdDeg(rem,d,L[1][1][7][k]); } J_B=transpose(syz(transpose(L[1][1][3][k]))); L[1][1][7][k+1]=n_b; L[1][1][8][k+1]=n_b; L[1][1][4][k+1]=unitmat(nrows(L[1][1][3][k])); if (J_B!=matrix(0,nrows(J_B),ncols(J_B))) { J_B=VdStrictGB(J_B,d,n_b); L[1][1][3][k+1]=J_B; L[1][1][5][k+1]=J_B; } else { L[1][1][3][k+1]=list(); L[1][1][5][k+1]=list(); } n_b=0; } else { L[1][1][3][k+1]=list(); L[1][1][5][k+1]=list(); L[1][1][7][k+1]=list(); L[1][1][8][k+1]=list(); L[1][1][4][k+1]=list(); } /* we compute step by step V_d-strict resolutions over coker(L[i][2][1][1])->coker(L[i][2][3][1])->coker(L[i][2][1][5]) and coker(L[i+1][1][1][1])->coker(L[i+1][1][3][1])->coker(L[i+1][1][1][5]) using the already computed resolutions for coker(L[i][2][1][1])= coker(L[i][1][3][1]) and coker(L[i+1][1][1][1])=coker(L[i][2][5][1])*/ for (i=1; i=0) for the seqeunce coker(L[1][2][3][1])->...->coker(L[size(L)][2][3][1])*/ list out; int i,j,k,l,oldj,newj,nr,nc; for (i=1; i<=size(L); i++) { out[i]=list(list()); out[i][1][1]=ncols(L[i][2][3][1]);//rank of module P^i_0 if (size(L[i][2][5][1])!=0) { /*horizontal differential P^i_0->P^(i+1)_0*/ nc=ncols(L[i][2][5][1]); out[i][1][4]=prodr(ncols(L[i][2][3][1])-ncols(L[i][2][5][1]),nc); } else { /*horizontal differential P^i_0->0*/ out[i][1][4]=matrix(0,ncols(L[i][2][3][1]),1); } oldj=newj; for (j=1; j<=size(L[i][2][3]);j++) { out[i][j][2]=L[i][2][7][j];//shift vector of P^i_{j-1} if (size(L[i][2][3][j])==0) { newj =j; break; } out[i][j+1]=list(); out[i][j+1][1]=nrows(L[i][2][3][j]);//rank of the module P^i_j out[i][j+1][3]=L[i][2][3][j];//vertical differential P^i_j->P^(i+1)_j if (size(L[i][2][5][j])!=0) { //horizonal differential P^i_j->P^(i-1)_j nr=nrows(L[i][2][3][j])-nrows(L[i][2][5][j]); out[i][j+1][4]=(-1)^j*prodr(nr,nrows(L[i][2][5][j])); } else { /*horizontal differential P^i_j->P^(i-1)_j*/ out[i][j+1][4]=matrix(0,nrows(L[i][2][3][j]),1); } if(j==size(L[i][2][3])) { out[i][j+1][2]=L[i][2][7][j+1];//shift vector of P^i_j newj=j+1; } } if (i>1) { for (k=1; k<=Min(list(oldj,newj)); k++) { /*horizonal differential P^(i-1)_(k-1)->P^i_(k-1)*/ nr=nrows(out[i-1][k][4]); out[i-1][k][4]=matrix(out[i-1][k][4],nr,out[i][k][1]); } for (k=newj+1; k<=oldj; k++) { /*no differential needed*/ out[i-1][k]=delete(out[i-1][k],4); } } } return (out); } //////////////////////////////////////////////////////////////////////////////////// static proc totalComplex(list L); { /* Input is the output of assemblingDoubleComplexes. We obtain a complex C^1[m^1]->...->C^(r)[m^r] with differentials d^i and shift vectors m^i (where C^r is placed in degree size(L)-1). This complex is dercribed in the list out as follows: rank(C^i)=out[3*i-2]; m_i=out[3*i-1] and d^i=out[3*i]*/ list out;intvec rem1;intvec v; list remsize; int emp; int i; int j; int c; int d; matrix M; int k; int l; int n=nvars(basering) div 2; list K; for (i=1; i<=n+1; i++) { K[i]=list(); } L=K+L; for (i=1; i<=size(L); i++) { emp=0; if (size(L[i])!=0) { out[3*i-2]=L[i][1][1]; v=L[i][1][1]; rem1=L[i][1][2]; emp=1; } else { out[3*i-2]=0; v=0; } for (j=i+1; j<=size(L); j++) { if (size(L[j])>=j-i+1) { out[3*i-2]=out[3*i-2]+L[j][j-i+1][1]; if (emp==0) { rem1=L[j][j-i+1][2]; emp=1; } else { rem1=rem1,L[j][j-i+1][2]; } v[size(v)+1]=L[j][j-i+1][1]; } else { v[size(v)+1]=0; } } out[3*i-1]=rem1; v[size(v)+1]=0; remsize[i]=v; } int o1; int o2; for (i=1; i<=size(L)-1; i++) { o1=1; o2=1; if (size(out[3*i-2])!=0) { o1=out[3*i-2]; } if (size(out[3*i+1])!=0) { o2=out[3*i+1]; } M=matrix(0,o1,o2); if (size(L[i])!=0) { if (size(L[i][1][4])!=0) { M=matrix(L[i][1][4],o1,o2); } } c=remsize[i][1]; for (j=i+1; j<=size(L); j++) { if (remsize[i][j-i+1]!=0) { for (k=c+1; k<=c+remsize[i][j-i+1]; k++) { for (l=d+1; l<=d+remsize[i+1][j-i];l++) { M[k,l]=L[j][j-i+1][3][(k-c),(l-d)]; } } d=d+remsize[i+1][j-i]; if (remsize[i+1][j-i+1]!=0) { for (k=c+1; k<=c+remsize[i][j-i+1]; k++) { for (l=d+1; l<=d+remsize[i+1][j-i+1];l++) { M[k,l]=L[j][j-i+1][4][k-c,l-d]; } } c=c+remsize[i][j-i+1]; } } else { d=d+remsize[i+1][j-i]; } } out[3*i]=M; d=0; c=0; } out[3*size(L)]=matrix(0,out[3*size(L)-2],1); return (out); } //////////////////////////////////////////////////////////////////////////////////// //COMPUTATION OF THE BLOBAL B-FUNCTION //////////////////////////////////////////////////////////////////////////////////// static proc globalBFun(list L,list #) { /*We assume that the basering is the nth Weyl algebra and that L=(L[1],...,L[s]), where L[i]=(L[i][1],L[i][2]) and L[i][1] is a m_i x n_i-matrix and L[i][2] an intvec of size n_i. We compute bounds for the minimal and maximal integer roots of the b-functions of coker(L[i][1])[L[i][2]], where L[i][2] is the shift vector (cf. Def. 6.1.1 in [R]) by combining Algorithm 6.1.6 in [R] and the method of principal intersection (cf. Remark 6.1.7 in [R] 2012). This works ONLY IF ALL B-FUNCTIONS ARE NON-ZERO, but this is the case since this proc is only called from the procedure deRhamCohomology and the input comes originally from the procedure toVdstrictFreeComplex*/ if (size(#)==0)//# may contain the Syzstring { string Syzstring="Sres"; } else { string Syzstring=#[1]; } int i,j; def W=basering; int n=nvars(W) div 2; list G0; ideal I; for (j=1; j<=size(L); j++) { G0[j]=list(); for (i=1; i<=ncols(L[j][1]); i++) { G0[j][i]=I; } } list out; ideal I; poly f; intvec i1; for (j=1; j<=size(L); j++) { /*if the shift vector L[j][2] is non-zero we have to compute a V_d-strict Groebner basis of L[j][1] with respect to the zero shift; otherwise L[i][1] is already a V_d-strict Groebner basis, because it was obtained by the procedure toVdStrictFreeComplex*/ if (L[j][2]!=intvec(0:size(L[j][2])) or Syzstring=="noCE") { if (Syzstring=="Vdres") { L[j][1]=VdStrictGB(L[j][1],n); } else { def HomWeyl=makeHomogenizedWeyl(n); setring HomWeyl; list L=fetch(W,L); L[j][1]=nHomogenize(L[j][1]); L[j][1]=transpose(matrix(slimgb(transpose(L[j][1])))); L[j][1]=subst(L[j][1],h,1); setring W; L=fetch(HomWeyl,L); kill HomWeyl; } } for (i=1; i<=ncols(L[j][1]); i++) { G0[j][i]=I; } for (i=1; i<=nrows(L[j][1]); i++) { /*computes the terms of maximal V_d-degree of the biggest non-zero component of submat(L[j][1],i,(1..ncols(L[j][1])))*/ i1=(1..ncols(L[j][1])); out=VdDeg(submat(L[j][1],i,i1),n,intvec(0:size(L[j][2])),1); // f=L[j][1][i,out[2]]; G0[j][out[2]]=G0[j][out[2]],out[1]; G0[j][out[2]]=compress(G0[j][out[2]]); } } list save; int l; list weights; /*bFctIdealModified computes the intersection of G0[j][i] and x(1)D(1)+...+x(n)D(n) using the method of principal intersection*/ for (j=1; j<=size(G0); j++) { for (i=1; i<=size(G0[j]); i++) { G0[j][i]=bFctIdealModified(G0[j][i]); } for (i=1; i<=size(G0[j]); i++) { weights=list(); if (size(G0[j][i])!=0) { for (l=i; l<=size(G0[j]); l++) { weights[size(weights)+1]=L[j][2][l]; } G0[j][i]=list(G0[j][i][1]+Min(weights),G0[j][i][2]+Max(weights)); } } } list allmin; list allmax; for (j=1; j<=size(G0); j++) { for (i=1; i<=size(G0[j]); i++) { if (size(G0[j][i])!=0) { allmin[size(allmin)+1]=G0[j][i][1]; allmax[size(allmax)+1]=G0[j][i][2]; } } } list minmax=list(Min(allmin),Max(allmax)); return(minmax); } //////////////////////////////////////////////////////////////////////////////////// static proc exactGlobalBFun(list L,list #) { /*We assume that the basering is the nth Weyl algebra and that L=(L[1],...,L[s]), where L[i]=(L[i][1],L[i][2]) and L[i][1] is a m_i x n_i-matrix and L[i][2] an intvec of size n_i. We compute bounds for the minimal and maximal integer roots of the b-functions of coker(L[i][1])[L[i][2]], where L[i][2] is the shift vector (cf. Def. 6.1.1 in [R]) by combining Algorithm 6.1.6 in [R] and the method of principal intersection (cf. Remark 6.1.7 in [R] 2012). This works ONLY IF ALL B-FUNCTIONS ARE NON-ZERO, but this is the case since this proc is only called from the procedure deRhamCohomology and the input comes originally from the procedure toVdstrictFreeComplex*/ if (size(#)==0)//# may contain the Syzstring { string Syzstring="Sres"; } else { string Syzstring=#[1]; } int i,j,k; def W=basering; int n=nvars(W) div 2; list G0; ideal I; for (j=1; j<=size(L); j++) { G0[j]=list(); for (i=1; i<=ncols(L[j][1]); i++) { G0[j][i]=I; } } list out; matrix M; ideal I; poly f; intvec i1; for (j=1; j<=size(L); j++) { M=L[j][1]; /*if the shift vector L[j][2] is non-zero we have to compute a V_d-strict Groebner basis of L[j][1] with respect to the zero shift; otherwise L[i][1] is already a V_d-strict Groebner basis, because it was obtained by the procedure toVdStrictFreeComplex*/ for (k=1; k<=ncols(L[j][1]); k++) { L[j][1]=permcol(M,1,k); if (Syzstring=="Vdres") { L[j][1]=VdStrictGB(L[j][1],n); } else { def HomWeyl=makeHomogenizedWeyl(n); setring HomWeyl; list L=fetch(W,L); L[j][1]=nHomogenize(L[j][1]); L[j][1]=transpose(matrix(slimgb(transpose(L[j][1])))); L[j][1]=subst(L[j][1],h,1); setring W; L=fetch(HomWeyl,L); kill HomWeyl; } for (i=1; i<=nrows(L[j][1]); i++) { /*computes the terms of maximal V_d-degree of the biggest non-zero component of submat(L[j][1],i,(1..ncols(L[j][1])))*/ i1=(1..ncols(L[j][1])); out=VdDeg(submat(L[j][1],i,i1),n,intvec(0:size(L[j][2])),1); if (out[2]==1) { G0[j][k]=G0[j][k],out[1]; G0[j][k]=compress(G0[j][k]); } } } } list save; int l; list weights; /*bFctIdealModified computes the intersection of G0[j][i] and x(1)D(1)+...+x(n)D(n) using the method of principal intersection*/ for (j=1; j<=size(G0); j++) { for (i=1; i<=size(G0[j]); i++) { G0[j][i]=bFctIdealModified(G0[j][i]); } for (i=1; i<=size(G0[j]); i++) { if (size(G0[j][i])!=0) { G0[j][i]=list(G0[j][i][1]+L[j][2][i],G0[j][i][2]+L[j][2][i]); } } } list allmin; list allmax; for (j=1; j<=size(G0); j++) { for (i=1; i<=size(G0[j]); i++) { if (size(G0[j][i])!=0) { allmin[size(allmin)+1]=G0[j][i][1]; allmax[size(allmax)+1]=G0[j][i][2]; } } } list minmax=list(Min(allmin),Max(allmax)); return(minmax); } //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// static proc exactGlobalBFunIntegration(list L,list #) { /*We assume that the basering is the nth Weyl algebra and that L=(L[1],...,L[s]), where L[i]=(L[i][1],L[i][2]) and L[i][1] is a m_i x n_i-matrix and L[i][2] an intvec of size n_i. We compute bounds for the minimal and maximal integer roots of the b-functions of coker(L[i][1])[L[i][2]], where L[i][2] is the shift vector (cf. Def. 6.1.1 in [R]) by combining Algorithm 6.1.6 in [R] and the method of principal intersection (cf. Remark 6.1.7 in [R] 2012). This works ONLY IF ALL B-FUNCTIONS ARE NON-ZERO, but this is the case since this proc is only called from the procedure deRhamCohomology and the input comes originally from the procedure toVdstrictFreeComplex*/ string Syzstring="Sres"; int i,j,k; def W=basering; int n=nvars(W) div 2; // def C=makeConverseWeyl(n); // setring C; // ideal Jn=x(1); // for (i=2; i<=nvars(basering) div 2; i++) // { // Jn=Jn,var(nvars(basering) div 2 + i); // } // for (i=1; i<=nvars(basering) div 2; i++) // { // Jn=Jn,var(i); // } // map transtc=W,Jn; // list L=transtc(L); list G0; ideal I; for (j=1; j<=size(L); j++) { G0[j]=list(); for (i=1; i<=ncols(L[j][1]); i++) { G0[j][i]=I; } } list out; matrix M; ideal I; poly f; intvec i1; for (j=1; j<=size(L); j++) { M=L[j][1]; /*if the shift vector L[j][2] is non-zero we have to compute a V_d-strict Groebner basis of L[j][1] with respect to the zero shift; otherwise L[i][1] is already a V_d-strict Groebner basis, because it was obtained by the procedure toVdStrictFreeComplex*/ for (k=1; k<=ncols(L[j][1]); k++) { L[j][1]=permcol(M,1,k); def HomWeyl=makeHomogenizedWeylTilde(n); setring HomWeyl; list L=fetch(W,L); L[j][1]=nHomogenize(L[j][1]); L[j][1]=transpose(matrix(slimgb(transpose(L[j][1])))); L[j][1]=subst(L[j][1],h,1); setring W; L=fetch(HomWeyl,L); kill HomWeyl; for (i=1; i<=nrows(L[j][1]); i++) { /*computes the terms of maximal V_d-degree of the biggest non-zero component of submat(L[j][1],i,(1..ncols(L[j][1])))*/ i1=(1..ncols(L[j][1])); out=VdDegTilde(submat(L[j][1],i,i1),n,intvec(0:size(L[j][2])),1);//hier koennte es evtl noch einen Fehler geben!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! f=L[j][1][i,out[2]]; if (out[2]==1) { G0[j][k]=G0[j][k],out[1]; G0[j][k]=compress(G0[j][k]); } } } } list save; int l; list weights; /*bFctIdealModified computes the intersection of G0[j][i] and x(1)D(1)+...+x(n)D(n) using the method of principal intersection*/ for (j=1; j<=size(G0); j++) { for (i=1; i<=size(G0[j]); i++) { G0[j][i]=bFctIdealModified(G0[j][i],1); } for (i=1; i<=size(G0[j]); i++) { if (size(G0[j][i])!=0) { G0[j][i]=list(G0[j][i][1]+L[j][2][i],G0[j][i][2]+L[j][2][i]); } } } list allmin; list allmax; for (j=1; j<=size(G0); j++) { for (i=1; i<=size(G0[j]); i++) { if (size(G0[j][i])!=0) { allmin[size(allmin)+1]=G0[j][i][1]; allmax[size(allmax)+1]=G0[j][i][2]; } } } list minmax=list(Min(allmin),Max(allmax)); return(minmax); } //////////////////////////////////////////////////////////////////////////////////// static proc bFctIdealModified (ideal I, list #) {/*modified version of the procedure bfunIdeal from bfun.lib*/ int tilde; if (size(#)!=0) { tilde=#[1]; } def B= basering; int n = nvars(B) div 2; intvec w=(1:n); // if (tilde==0) // { I= initialIdealW(I,-w,w); // } // else // { // I= initialIdealW(I,w,-w); // } poly s; int i; if (tilde==0) { for (i=1; i<=n; i++) { s=s+x(i)*D(i); } } else { for (i=1; i<=n; i++) { s=s-D(i)*x(i); } } /*pIntersect computes the intersection on s and I*/ vector b = pIntersect(s,I); list RL = ringlist(B); RL = RL[1..4]; RL[2] = list(safeVarName("s")); RL[3] = list(list("dp",intvec(1)),list("C",intvec(0))); def @S = ring(RL); setring @S; vector b = imap(B,b); poly bs = vec2poly(b); ring r=0,s,dp; poly bs=imap(@S,bs); /*find minimal and maximal integer root*/ ideal allfac=factorize(bs,1); list allfacs; for (i=1; i<=ncols(allfac); i++) { allfacs[i]=allfac[i]; } number testzero; list zeros; for (i=1; i<=size(allfacs); i++) { if (deg(allfacs[i])==1) { testzero=number(subst(allfacs[i],s,0))/leadcoef(allfacs[i]); if (testzero-int(testzero)==0) { zeros[size(zeros)+1]=int(-1)*int(testzero); } } } if (size(zeros)!=0) { list minmax=(Min(zeros),Max(zeros)); } else { list minmax=list(); } setring B; return(minmax); } //////////////////////////////////////////////////////////////////////////////////// static proc safeVarName (string s) {/* from the library "bfun.lib"*/ string S = "," + charstr(basering) + "," + varstr(basering) + ","; s = "," + s + ","; while (find(S,s) <> 0) { s[1] = "@"; s = "," + s; } s = s[2..size(s)-1]; return(s) } //////////////////////////////////////////////////////////////////////////////////// static proc globalBFunOT(list L,list #) { /*this proc is currently not used since globalBFun computes the same output and is faster, however globalBFun works only for non-zero b-functions!*/ /*We assume that the basering is the nth Weyl algebra and that L=(L[1],...,L[s]), where L[i]=(L[i][1],L[i][2]) and L[i][1] is a m_i x n_i-matrix and L[i][2] an intvec of size n_i. We compute bounds for the minimal and maximal integer roots of the b-functions of coker(L[i][1])[L[i][2]], where L[i][2] is the shift vector (cf. Def. 6.1.1 in [R]) using Algorithm 6.1.6 in [R].*/ if (size(#)==0) { string Syzstring="Sres"; } else { string Syzstring=#[1]; } int i; int j; def W=basering; int n=nvars(W) div 2; list G0; ideal I; intvec i1; for (j=1; j<=size(L); j++) { G0[j]=list(); for (i=1; i<=ncols(L[j][1]); i++) { G0[j][i]=I; } } list out; for (j=1; j<=size(L); j++) { if (L[j][2]!=intvec(0:size(L[j][2]))) { if (Syzstring=="Vdres") { L[j][1]=VdStrictGB(L[j][1],n); } else { def HomWeyl=makeHomogenizedWeyl(n); setring HomWeyl; list L=fetch(W,L); L[j][1]=nHomogenize(L[j][1]); L[j][1]=transpose(matrix(slimgb(transpose(L[j][1])))); L[j][1]=subst(L[j][1],h,1); setring W; L=fetch(HomWeyl,L); kill HomWeyl; } } for (i=1; i<=nrows(L[j][1]); i++) { i1=(1..ncols(L[j][1])); out=VdDeg(submat(L[j][1],i,i1),n,intvec(0:size(L[j][2])),1); G0[j][out[2]][size(G0[j][out[2]])+1]=(out[1]); } } list Data=ringlist(W); for (i=1; i<=n; i++) { Data[2][2*n+i]=Data[2][i]; Data[2][3*n+i]=Data[2][n+i]; Data[2][i]="v("+string(i)+")"; Data[2][n+i]="w("+string(i)+")"; } Data[3][1][1]="M"; intvec mord=(0:16*n^2); mord[1..2*n]=(1:2*n); mord[6*n+1..8*n]=(1:2*n); for (i=0; i<=2*n-2; i++) { mord[(3+i)*4*n-i]=-1; mord[(2*n+2+i)*4*n-2*n-i]=-1; } Data[3][1][2]=mord; matrix Ones=UpOneMatrix(4*n); Data[5]=Ones; matrix con[2*n][2*n]; Data[6]=transpose(concat(con,transpose(concat(con,Data[6])))); def Wuv=ring(Data); setring Wuv; list G0=imap(W,G0); list G3; poly lterm;intvec lexp; list G1,G2,LL; intvec e,f; int kapp,k,l; poly h; ideal I; for (l=1; l<=size(G0); l++) { G1[l]=list(); G2[l]=list(); G3[l]=list(); for (i=1; i<=size(G0[l]); i++) { for (j=1; j<=ncols(G0[l][i]);j++) { G0[l][i][j]=mHom(G0[l][i][j]); } for (j=1; j<=nvars(Wuv) div 4; j++) { G0[l][i][size(G0[l][i])+1]=1-v(j)*w(j); } G1[l][i]=slimgb(G0[l][i]); G2[l][i]=I; G3[l][i]=list(); for (j=1; j<=ncols(G1[l][i]); j++) { e=leadexp(G1[l][i][j]); f=e[1..2*n]; if (f==intvec(0:(2*n))) { for (k=1; k<=n; k++) { kapp=-e[2*n+k]+e[3*n+k]; if (kapp>0) { G1[l][i][j]=(x(k)^kapp)*G1[l][i][j]; } if (kapp<0) { G1[l][i][j]=(D(k)^(-kapp))*G1[l][i][j]; } } G2[l][i][size(G2[l][i])+1]=G1[l][i][j]; G3[l][i][size(G3[l][i])+1]=list(); while (G1[l][i][j]!=0) { lterm=lead(G1[l][i][j]); G1[l][i][j]=G1[l][i][j]-lterm; lexp=leadexp(lterm); lexp=lexp[2*n+1..3*n]; LL=list(lexp,leadcoef(lterm)); G3[l][i][size(G3[l][i])][size(G3[l][i][size(G3[l][i])])+1]=LL; } } } } } ring r=0,(s(1..n)),dp; ideal I; map G3forr=Wuv,I; list G3=G3forr(G3); poly fs,gs; int a; list G4; for (l=1; l<=size(G3); l++) { G4[l]=list(); for (i=1; i<=size(G3[l]);i++) { G4[l][i]=I; for (j=1; j<=size(G3[l][i]); j++) { fs=0; for (k=1; k<=size(G3[l][i][j]); k++) { gs=1; for (a=1; a<=n; a++) { if (G3[l][i][j][k][1][a]!=0) { gs=gs*permuteVar(list(G3[l][i][j][k][1][a]),a); } } gs=gs*G3[l][i][j][k][2]; fs=fs+gs; } G4[l][i]=G4[l][i],fs; } } } if (n==1) { ring rnew=0,t,dp; } else { ring rnew=0,(t,s(2..n)),dp; } ideal Iformap; Iformap[1]=t; poly forel=1; for (i=2; i<=n; i++) { Iformap[1]=Iformap[1]-s(i); Iformap[i]=s(i); forel=forel*s(i); } map rtornew=r,Iformap; list G4=rtornew(G4); list getintvecs=fetch(W,L); ideal J; option(redSB); for (l=1; l<=size(G4); l++) { J=1; for (i=1; i<=size(G4[l]); i++) { G4[l][i]=eliminate(G4[l][i],forel); J=intersect(J,G4[l][i]); } G4[l]=poly(std(J)[1]); } list minmax; list mini=list(); list maxi=list(); list L=fetch(W,L); for (i=1; i<=size(G4); i++) { minmax[i]=minIntRootD(G4[i],1); if (size(minmax[i])!=0) { mini=insert(mini,minmax[i][1]+Min(L[i][2])); maxi=insert(maxi,minmax[i][2]+Max(L[i][2])); } } mini=Min(mini); maxi=Max(maxi); minmax=list(mini[1],maxi[1]); option(none); return(minmax); } //////////////////////////////////////////////////////////////////////////////////// //COMPUTATION OF THE COHOMOLOGY //////////////////////////////////////////////////////////////////////////////////// static proc findCohomology(list L,int le) { /*computes the cohomology of the complex (D^i,d^i) given by D^i=C^L[2*i-1] and d^i=L[2*i]*/ def R=basering; ring r=0,(x),dp; list L=imap(R,L); list out; int i, ker, im; matrix S; option(returnSB); option(redSB); for (i=2; i<=size(L); i=i+2) { if (L[i-1]==0) { out[i div 2]=0; im=0; } else { S=matrix(syz(transpose(L[i]))); if (S!=matrix(0,nrows(S),ncols(S))) { ker=ncols(S); out[i div 2]=ker-im; im=L[i-1]-ker; } else { out[i div 2]=0;////achtung geaendert??????????????????????????????????????????????????!!!!!!!!!!!!!!!!!!!!!!!!!war mal out[i-1] im=L[i-1]; } } } option(none); while (size(out)>le) { out=delete(out,1); } setring R; return(out); } //////////////////////////////////////////////////////////////////////////////////// static proc findCohomologyDiffForms(list L,int le) { /*computes the cohomology of the complex (D^i,d^i) given by D^i=C^L[2*i-1] and d^i=L[2*i]*/ def R=basering; list outdiffforms=list(var(1)); ring r=0,(x),dp; list L=imap(R,L); list out; list outdiffforms; int i, ker, im, j; matrix S; matrix concreteimage=matrix(0); module concreteimagemod=concreteimage; option(returnSB); option(redSB); matrix redS; for (i=2; i<=size(L); i=i+2) { if (L[i-1]==0) { out[i div 2]=0; im=0; concreteimage=matrix(0); concreteimagemod=concreteimage; outdiffforms[i div 2]=list(); } else { S=matrix(transpose(syz(transpose(L[i])))); if (S!=matrix(0,nrows(S),ncols(S))) { ker=nrows(S); out[i div 2]=ker-im; if(out[i div 2]==0) { outdiffforms[i div 2]=list(); } else { outdiffforms[i div 2]=list(); if (concreteimage==matrix(0)) { for (j=1; j<=nrows(S); j++) { outdiffforms[ i div 2][j]=submat(S,j,intvec(1..ncols(S))); } } else { redS=transpose(std(reduce(transpose(S),concreteimagemod))); for (j=1; j<=nrows(redS); j++) { if (submat(redS,j, intvec(1..ncols(redS)))!=matrix(0,1,ncols(redS))) { outdiffforms[i div 2][size(outdiffforms[i div 2])+1]=submat(redS,j, intvec(1..ncols(redS))); } } } } im=L[i-1]-ker; concreteimagemod=std(transpose(L[i])); concreteimage=concreteimagemod; concreteimage=transpose(concreteimage); //concreteimage=transpose(std(transpose(L[i])));//Achtung:hier wieder das Problem mit no Standard basis!!!!!!!!!!!!! } else { out[i div 2]=0; outdiffforms[i div 2]=0; im=L[i-1]; concreteimagemod=std(transpose(L[i])); concreteimage=concreteimagemod; concreteimage=transpose(concreteimage); //concreteimage=transpose(std(transpose(L[i]))); } } } option(none); while (size(out)>le) { out=delete(out,1); outdiffforms=delete(outdiffforms,1); } setring R; outdiffforms=imap(r,outdiffforms); list outall=list(out,outdiffforms); option(noredSB); option(noreturnSB); return(outall); } //////////////////////////////////////////////////////////////////////////////////// //AUXILIARY PROCEDURES //////////////////////////////////////////////////////////////////////////////////// static proc findPreimage(matrix m, matrix n) { def W=basering;//input wird in spaltenform angenommen, output in zeilenform list rl=ringlist(W); list rlnew=rl; rlnew[3][1]=rl[3][2]; rlnew[3][2]=rl[3][1]; def Wnew=ring(rlnew); setring Wnew; matrix m=imap(W,m); matrix n=imap(W,n); def Opp=opposite(Wnew); setring Opp; matrix m=oppose(Wnew,m); matrix n=oppose(Wnew,n); option(redSB); //matrix m=imap(W,m); // matrix n=imap(W,n); int i; matrix preim; if (n!=matrix(0,nrows(n),ncols(n))) { matrix con=concat(m,n); matrix s=syz(con); for (i=1; i<=ncols(s); i++) { if (s[nrows(s),i]==1) { preim=(-1)*submat(s,1..ncols(m),i); break; } } } else { matrix s=syz(m); preim=submat(s,1..ncols(m),1); } option(noredSB); setring Wnew; matrix preim=oppose(Opp,preim); setring W; matrix preim=imap(Wnew,preim); return(transpose(preim)); } //////////////////////////////////////////////////////////////////////////////////// static proc divdr(matrix m,matrix n, list #) { if (n!=matrix(0,nrows(n),ncols(n))) { m=transpose(m); n=transpose(n); matrix con=concat(m,n); matrix s=syz(con); s=submat(s,1..ncols(m),1..ncols(s)); s=transpose(compress(s)); } else { matrix s=transpose(syz(transpose(m))); } int i; matrix g; matrix sm; if (size(#)!=0) { for (i=1; i<=nrows(s); i++) { g=deletecol(transpose(s),i); sm=transpose(submat(s,i,intvec(1..ncols(s)))); sm=reduce(sm,slimgb(g)); if (sm==matrix(0,nrows(sm),ncols(sm))) { s=g; s=transpose(s); i=i-1; } } } return(s); } //////////////////////////////////////////////////////////////////////////////////// static proc matrixLift(matrix M,matrix N) { intvec v=option(get); option(none); matrix l=transpose(lift(transpose(M),transpose(N))); option(set,v); return(l); } //////////////////////////////////////////////////////////////////////////////////// static proc VdStrictGB (matrix M,int d,list #) "USAGE:VdStrictGB(M,d[,v]); M a matrix, d an integer, v an optional intvec ASSUME:-basering is the nth Weyl algebra D_n @* -1<=d<=n @* -v (if given) is the shift vector on the range of M (in particular, size(v)=ncols(M)); otherwise v is assumed to be the zero shift vector RETURN:matrix N; the rows of N form a V_d-strict Groebner basis with respect to v for the module generated by the rows of M " { if (M==matrix(0,nrows(M),ncols(M))) { return (matrix(0,1,ncols(M))); } intvec op=option(get); def W =basering; int ncM=ncols(M); list Data=ringlist(W); Data[2]=list("nhv")+Data[2]; Data[3][3]=Data[3][1]; Data[3][1]=list("dp",intvec(1)); matrix re[size(Data[2])][size(Data[2])]=UpOneMatrix(size(Data[2])); Data[5]=re; int k,l; Data[6]=transpose(concat(matrix(0,1,1),transpose(concat(matrix(0,1,1),Data[6])))); def Whom=ring(Data);// D_n[nhv] with the new commuative variable nhv setring Whom; matrix Mnew=imap(W,M); intvec v; if (size(#)!=0) { v=#[1]; } if (size(v) < ncM) { v=v,0:(ncM-size(v)); } Mnew=homogenize(Mnew, d, v);//homogenization of M with respect to the new variable Mnew=transpose(Mnew); Mnew=slimgb(Mnew);// computes a Groebner basis of the homogenzition of M Mnew=subst(Mnew,nhv,1);// substitution of 1 gives V_d-strict Groebner basis of M Mnew=compress(Mnew); Mnew=transpose(Mnew); setring W; M=imap(Whom,Mnew); option(set,op); return(M); } //////////////////////////////////////////////////////////////////////////////////// static proc VdNormalForm(matrix F,matrix M,int d,intvec v,list #) "USAGE:VdNormalForm(F,M,d,v[,w]); F and M matrices, d int, v intvec, w an optional intvec ASSUME:-basering is the nth Weyl algebra D_n @* -F a n_1 x n_2-matrix and M a m_1 x m_2-matrix with m_2<=n_2 @* -d is an integer between 1 and n @* -v is a shift vector for D_n^(m_2) and hence size(v)=m_2 @* -w is a shift vector for D_n^(m_1-m_2) and hence size(v)=m_1-m_2 @* RETURN:a n_1 x n_2-matrix N such that:@* -If no optional intvec w is given:(N[i,1],..,N[i,m_2]) is a V_d-strict normal form of (F[i,1],...,F[i,m_2]) with respect to a V_d-strict Groebner basis of the rows of M and the shift vector v -If w is given:(N[i,1],..,N[i,m_2]) is chosen such that Vddeg((N[i,1],...,N[i,m_2])[v])<=Vddeg((F[i,m_2+1],...,F[i,m_1])[v]); -N[i,j]=F[i,j] for j>m_2 " { int SBcom; def W =basering; int c=ncols(M); matrix keepF=F; if (size(#)!=0) { intvec w=#[1]; } F=submat(F,intvec(1..nrows(F)),intvec(1..c)); list Data=ringlist(W); Data[2]=list("nhv")+Data[2]; Data[3][3]=Data[3][1]; Data[3][1]=list("dp",intvec(1)); matrix re[size(Data[2])][size(Data[2])]=UpOneMatrix(size(Data[2])); Data[5]=re; int k,l,nr,nc; matrix rep[size(Data[2])][size(Data[2])]; for (l=size(Data[2])-1;l>=1; l--) { for (k=l-1; k>=1;k--) { rep[k+1,l+1]=Data[6][k,l]; } } Data[6]=rep; def Whom=ring(Data);//new ring D_n[nvh] this new commuative variable nhv setring Whom; matrix Mnew=imap(W,M); list forMnew=homogenize(Mnew,d,v,1);//commputes homogenization of M; Mnew=forMnew[1]; int rightexp=forMnew[2]; matrix Fnew=imap(W,F); matrix keepF=imap(W,keepF); matrix Fb; int cc; intvec i1,i2; matrix zeromat,subm1,subm2,zeromat2; for (l=1; l<=nrows(Fnew); l++) { if (size(#)!=0) { subm2=submat(keepF,l,((ncols(Fnew)+1)..ncols(keepF))); zeromat2=matrix(0,1,ncols(subm2)); if (submat(keepF,l,((ncols(Fnew)+1)..ncols(keepF)))==zeromat2) { for (cc=1; cc<=ncols(Fnew); c++) { Fnew[l,cc]=0; } } i1=intvec(1..ncols(Fnew)); subm1=submat(Fnew,l,i1); subm2=submat(keepF,l,(ncols(Fnew)+1)..ncols(keepF)); zeromat=matrix(0,1,ncols(Fnew)); if (VdDegnhv(subm1,d,v)>VdDegnhv(subm2,d,w) and submat(Fnew,l,intvec(1..ncols(Fnew)))!=zeromat) { //print("Reduzierung des V_d-Grades noetig"); /*We need to reduce the V_d-degree. First we homogenize the lth row of Fnew*/ Fb=homogenize(subm1,d,v)*(nhv^rightexp); if (SBcom==0) { /*computes a V_d-strict standard basis*/ Mnew=slimgb(transpose(Mnew));// SBcom=1; } /*computes a V_d-strict normal form for FB*/ Fb=transpose(reduce(transpose(Fb),Mnew)); if (VdDegnhv(Fb,d,v)> VdDegnhv(subm2,d,w) and Fb!=matrix(0,nrows(Fb),ncols(Fb)))//should not happen { //print("Reduzierung fehlgeschlagen!!!!!!!!!!!!!!!!"); } } else { /*condition on V_ddeg already satisfied -> no normal form computation is needed*/ Fb=submat(Fnew,l,intvec(1..ncols(Fnew))); } } else { Fb=homogenize(submat(Fnew,l,intvec(1..ncols(Fnew))),d,v); if (SBcom==0) { Mnew=slimgb(transpose(Mnew));// computes a V_d-strict Groebner basis SBcom=1; } Fb=transpose(reduce(transpose(Fb),Mnew));//normal form } for (k=1; k<=ncols(Fnew);k++) { Fnew[l,k]=Fb[1,k]; } } Fnew=subst(Fnew,nhv,1);//obtain normal form in D_n setring W; F=imap(Whom,Fnew); return(F); } //////////////////////////////////////////////////////////////////////////////////// static proc homogenize (matrix M,int d,intvec v,list #) { /* we compute the F[v]-homogenization of each row of M (cf. Def. 3.4 in [OT])*/ if (M==matrix(0,nrows(M),ncols(M))) { return(M); } int i,l,s, kmin, nhvexp; poly f; intvec vnm; list findmin,maxnhv,rempoly,remk,rem1,rem2; int n=(nvars(basering)-1) div 2; for (int k=1; k<=nrows(M); k++) { for (l=1; l<=ncols (M); l++) { f=M[k,l]; s=size(f); for (i=1; i<=s; i++) { vnm=leadexp(f); vnm=vnm[n+2..n+d+1]-vnm[2..d+1]; kmin=sum(vnm)+v[l]; rem1[size(rem1)+1]=lead(f); rem2[size(rem2)+1]=kmin; findmin=insert(findmin,kmin); f=f-lead(f); } rempoly[l]=rem1; remk[l]=rem2; rem1=list(); rem2=list(); } if (size(findmin)!=0) { kmin=Min(findmin); } for (l=1; l<=ncols(M); l++) { if (M[k,l]!=0) { M[k,l]=0; for (i=1; i<=size(rempoly[l]);i++) { nhvexp=remk[l][i]-kmin; M[k,l]=M[k,l]+nhv^(nhvexp)*rempoly[l][i]; maxnhv[size(maxnhv)+1]=nhvexp; } } } rempoly=list(); remk=list(); findmin=list(); } maxnhv=Max(maxnhv); nhvexp=maxnhv[1]; if (size(#)!=0) { return(list(M,nhvexp));//only needed for normal form computations } return(M); } //////////////////////////////////////////////////////////////////////////////////// static proc soldr (matrix M,matrix N) { /* We compute a ncols(M) x nrows(M)-matrix C such that C[i,1]M_1+...+C[i,nrows(M)]M_(nrows(M))= e_i mod im(N), where e_i is the ith basis element on the range of M, M_j denotes the jth row of M and im(N) is generated by the rows of N */ int n=nrows(M); int q=ncols(M); matrix S=concat(transpose(M),transpose(N)); def W=basering; list Data=ringlist(W); list Save=Data[3]; Data[3]=list(list("c",0),list("dp",intvec(1..nvars(W)))); def Wmod=ring(Data); setring Wmod; matrix Smod=imap(W,S); matrix E[q][1]; matrix Smod2,Smodnew; option(returnSB); int i,j; for (i=1;i<=q;i++) { E[i,1]=1; Smod2=concat(E,Smod); Smod2=syz(Smod2); E[i,1]=0; for (j=1;j<=ncols(Smod2);j++) { if (Smod2[1,j]==1) { Smodnew=concat(Smodnew,(-1)*(submat(Smod2,intvec(2..n+1),j))); break; } } } Smodnew=transpose(submat(Smodnew,intvec(1..n),intvec(2..q+1))); setring W; matrix Snew=imap(Wmod,Smodnew); option(none); return (Snew); } //////////////////////////////////////////////////////////////////////////////////// static proc prodr (int k,int l) { if (k==0) { matrix P=unitmat(l); return (P); } matrix O[l][k]; matrix P=transpose(concat(O,unitmat(l))); return (P); } //////////////////////////////////////////////////////////////////////////////////// static proc VdDeg(matrix M,int d,intvec v,list #) { /* We assume that the basering it the nth Weyl algebra and that M is a 1 x r- matrix. We compute the V_d-deg of M with respect to the shift vector v, i.e V_ddeg(M)=max (V_ddeg(M_i)+v[i]), where k=V_ddeg(M_i) if k is the minimal integer, such that M_i can be expressed as a sum of operators x(1)^(a_1)*...*x(n)^(a_n)*D(1)^(b_1)*...*D(n)^(b_n) with a_1+..+a_d+k>=b_1+..+b_d*/ int i, j, etoint; int n=nvars(basering) div 2; intvec e; list findmax; int c=ncols(M); poly l; list positionpoly,positionVd; for (i=1; i<=c; i++) { positionpoly[i]=list(); positionVd[i]=list(); while (M[1,i]!=0) { l=lead(M[1,i]); positionpoly[i][size(positionpoly[i])+1]=l; e=leadexp(l); e=-e[1..d]+e[n+1..n+d]; e=sum(e)+v[i]; etoint=e[1]; positionVd[i][size(positionVd[i])+1]=etoint; findmax[size(findmax)+1]=etoint; M[1,i]=M[1,i]-l; } } if (size(findmax)!=0) { int maxVd=Max(findmax); if (size(#)==0) { return (maxVd); } } else // M is 0-modul { return(int(0)); } l=0; for (i=c; i>=1; i--) { for (j=1; j<=size(positionVd[i]); j++) { if (positionVd[i][j]==maxVd) { l=l+positionpoly[i][j]; } } if (l!=0) { /*returns the largest component that has maximal V_d-degree and its terms of maximal V_d-deg (needed for globalBFun)*/ return (list(l,i)); } } } //////////////////////////////////////////////////////////////////////////////////// static proc VdDegTilde(matrix M,int d,intvec v,list #) { /* We assume that the basering it the nth Weyl algebra and that M is a 1 x r- matrix. We compute the \tilde(V_d)-deg of M with respect to the shift vector v, i.e \tilde(V_d)deg(M)=max (\tilde(V_d)deg(M_i)+v[i]), where k=\tilde(V_d)deg(M_i) if k is the minimal integer, such that M_i can be expressed as a sum of operators x(1)^(a_1)*...*x(n)^(a_n)*D(1)^(b_1)*...*D(n)^(b_n) with a_1+..+a_d<=b_1+..+b_d+k*/ int i, j, etoint; int n=nvars(basering) div 2; intvec e; list findmax; int c=ncols(M); poly l; list positionpoly,positionVd; for (i=1; i<=c; i++) { positionpoly[i]=list(); positionVd[i]=list(); while (M[1,i]!=0) { l=lead(M[1,i]); positionpoly[i][size(positionpoly[i])+1]=l; e=leadexp(l); e=e[1..d]-e[n+1..n+d]; e=sum(e)+v[i]; etoint=e[1]; positionVd[i][size(positionVd[i])+1]=etoint; findmax[size(findmax)+1]=etoint; M[1,i]=M[1,i]-l; } } if (size(findmax)!=0) { int maxVd=Max(findmax); if (size(#)==0) { return (maxVd); } } else // M is 0-modul { return(int(0)); } l=0; for (i=c; i>=1; i--) { for (j=1; j<=size(positionVd[i]); j++) { if (positionVd[i][j]==maxVd) { l=l+positionpoly[i][j]; } } if (l!=0) { /*returns the largest component that has maximal V_d-degree and its terms of maximal V_d-deg (needed for globalBFun)*/ return (list(l,i)); } } } //////////////////////////////////////////////////////////////////////////////////// static proc VdDegnhv(matrix M,int d,intvec v,list #) { /* As the procedure VdDeg, but the basering is the nth Weyl algebra with a commutative variable nhv*/ int i,j,etoint; int n=nvars(basering) div 2; intvec e; int etoint; list findmax; int c=ncols(M); poly l; list positionpoly; list positionVd; for (i=1; i<=c; i++) { positionpoly[i]=list(); positionVd[i]=list(); while (M[1,i]!=0) { l=lead(M[1,i]); positionpoly[i][size(positionpoly[i])+1]=l; e=leadexp(l); e=-e[2..d+1]+e[n+2..n+d+1]; e=sum(e)+v[i]; etoint=e[1]; positionVd[i][size(positionVd[i])+1]=etoint; findmax[size(findmax)+1]=etoint; M[1,i]=M[1,i]-l; } } if (size(findmax)!=0) { int maxVd=Max(findmax); if (size(#)==0) { return (maxVd); } } else // M is 0-modul { return(int(0)); } } //////////////////////////////////////////////////////////////////////////////////// static proc deletecol(matrix M,int l) { if (ncols(M)==1) { return(M); } int s=ncols(M); if (l==1) { M=submat(M,(1..nrows(M)),(2..ncols(M))); return(M); } if (l==s) { M=submat(M,(1..nrows(M)),(1..(ncols(M)-1))); return(M); } intvec v=(1..(l-1)),((l+1)..s); M=submat(M,(1..nrows(M)),v); return(M); } //////////////////////////////////////////////////////////////////////////////////// static proc mHom(poly f) {/*for globalBFunOT*/ poly g; poly l; poly add; intvec e; list minint; list remf; int i; int j; int n=nvars(basering) div 4; if (f==0) { return(f); } while (f!=0) { l=lead(f); e=leadexp(l); remf[size(remf)+1]=list(); remf[size(remf)][1]=l; for (i=1; i<=n; i++) { remf[size(remf)][i+1]=-e[2*n+i]+e[3*n+i]; if (size(minint)=2) { if (typeof(#[2])=="intvec") { intvec n=#[2]; for (i=1; i<=size(n); i++) { w[size(w)+1]=n[i]; } RL[3]=insert(RL[3],list("am",w)); } else { RL[3]=insert(RL[3],list("a",w)); } } else { RL[3]=insert(RL[3],list("a",w)); } /*this ordering is needed for globalBFun and globalBFunOT*/ list saveord=RL[3][3]; RL[3][3]=RL[3][4]; RL[3][4]=saveord; intvec notforh=(1:(size(RL[3][4][2])-1)); RL[3][4][2]=notforh; RL[3][5]=list("dp",1); def @@R=ring(RL); return(@@R); } /////////////////////////////////////////////////////////////////////////////////// static proc homogenizedWeyl (int tilde,list #) { /*modified version of the procedure Weyl() from the library nctools.lib*/ /*Creates a homogenized Weyl algebra structure on the basering. We assume n=nvars(basering) is odd. The first (n-1)/2 variables will be treated as the x(i), the next (n-1)/2 as the corresponding differentials D(i) and the last as the homogenization variable h, i.e. it holds x(i)*D(i)=D(i)*x(1)+h^2. If # contains on intvec v, we assign weight v[i] to the ith module component.*/ string rname=nameof(basering); if ( rname == "basering") // i.e. no ring has been set yet { "You have to call the procedure from the ring"; return(); } int nv = nvars(basering); int N = (nv-1) div 2; if (((nv-1) % 2) != 0) { "Cannot create homogenized Weyl structure for an even number of generators"; return(); } matrix @D[nv][nv]; int i; for ( i=1; i<=N; i++ ) { @D[i,N+i]=h^2; } def @R = nc_algebra(1,@D); setring @R; list RL=ringlist(@R); intvec v; /*we need this ordering for Groebner basis computations*/ if (tilde==0) { for (i=1; i<=N; i++) { v[i]=-1; v[N+i]=1; } } else { for (i=1; i<=N; i++) { v[i]=1; v[N+i]=-1; } } v[nv]=0; /* we assign weights to module components*/ if (size(#)!=0) { if (typeof(#[1])=="intvec") { intvec m=#[1]; for (i=1; i<=size(m); i++) { v[size(v)+1]=m[i];//assigns weight m[i] to the ith module component } RL[3]=insert(RL[3],list("am",v)); } else { RL[3]=insert(RL[3],list("a",v)); } } else { RL[3]=insert(RL[3],list("a",v)); } intvec w=(1:nv); if (size(#)>=2) { if (typeof(#[2])=="intvec") { intvec n=#[2]; for (i=1; i<=size(n); i++) { w[size(w)+1]=n[i]; } RL[3]=insert(RL[3],list("am",w)); } else { RL[3]=insert(RL[3],list("a",w)); } } else { RL[3]=insert(RL[3],list("a",w)); } /*this ordering is needed for globalBFun and globalBFunOT*/ list saveord=RL[3][3]; RL[3][3]=RL[3][4]; RL[3][4]=saveord; intvec notforh=(1:(size(RL[3][4][2])-1)); RL[3][4][2]=notforh; RL[3][5]=list("dp",1); def @@R=ring(RL); return(@@R); } //////////////////////////////////////////////////////////////////////////////////// static proc nHomogenize (matrix M,list #) { /* # may contain an intvec v, if no intvec is given, we assume that v=(0:ncols(M)) We compute the h[v]-homogenization of the rows of M as in Definition 9.2 [OT]*/ int l; poly f; int s; int i; intvec vnm;int kmin; list findmax; int n=(nvars(basering)-1) div 2; list rempoly; list remk; list rem1; list rem2; list maxhexp; int hexp; intvec v=(0:ncols(M)); if (size(#)!=0) { if (typeof(#[1])=="intvec") { v=#[1]; } } if (size(v)1) { list forreturn=M,hexp; return(forreturn); } return(M); } //////////////////////////////////////////////////////////////////////////////////// static proc nDeg (matrix M,intvec m) {/*we compute an intvec n such that n[i]=max(deg(M[i,j])+m[j]|M[i,j]!=0) (where deg stands for the total degree) if (M[i,j]!=0 for some j) and n[i]=0 else*/ int i; int j; intvec n; list L; for (i=1; i<=nrows(M); i++) { L=list(); for (j=1; j<=ncols(M); j++) { if (M[i,j]!=0) { L=insert(L,deg(M[i,j])+m[j]); } } if (size(L)==0) { n[i]=0; } else { n[i]=Max(L); } } return(n); } //////////////////////////////////////////////////////////////////////////////////// static proc minIntRootD(list L,list #) "USAGE:minIntRootD(L [,M]); L list, M optinonal list ASSUME:L a list of univariate polynomials with rational coefficients @* the variable of the polynomial is s if size(#)==0 (needed for proc MVComplex) and t else (needed for globalBFun) RETURN:-if size(#)==0: int i, where i is an integer root of one of the polynomials and it is minimal with respect to that property@* -if size(#)!=0: list L=(i,j), where i is as above and j is an integer root of one of the polynomials and is maximal with respect to that property (if an integer root exists) or L=list() else " { def B=basering; if (size(#)==0) { ring rnew=0,s,dp; } else { ring rnew=0,t,dp; } list L=imap(B,L); int i; int j; number isint; list possmin; ideal allfac; list allfacs; for (i=1; i<=size(L); i++) { allfac=factorize(L[i],1); for (j=1; j<=ncols(allfac); j++) { allfacs[j]=allfac[j]; } for (j=1; j<=size(allfacs); j++) { if (deg(allfacs[j])==1) { isint=number(subst(allfacs[j],var(1),0)/leadcoef(allfacs[j])); if (isint-int(isint)==0) { possmin[size(possmin)+1]=int(isint); } } } allfacs=list(); } int zerolist; if (size(possmin)!=0) { int miniroot=(-1)*Max(possmin); int maxiroot=(-1)*Min(possmin); } else { zerolist=1; } setring B; if (size(#)==0) { return(miniroot); } else { if (zerolist==0) { return(list(miniroot,maxiroot)); } else { return(list()); } } } //////////////////////////////////////////////////////////////////////////////////// proc converseWeyl(list #) { string rname=nameof(basering); int @chr = 0; int nv = nvars(basering); int N = nv div 2; matrix @D[nv][nv]; int i; for ( i=1; i<=N; i++) { @D[i,N+i]=-1; } def @R = nc_algebra(1,@D); return(@R); } //////////////////////////////////////////////////////////////////////////////////// proc makeConverseWeyl(int n, list #) { if (n==1) { ring @rr = 0,(D(1),x(1)),dp; } else { ring @rr = 0,(D(1..n),x(1..n)),dp; } setring @rr; def @rrr = converseWeyl(); return(@rrr); } //////////////////////////////////////////////////////////////////////////////////// proc makeOmega(int n) { def R=basering; int i; int j,k,l; list omega; omega[1]=list(list(list())); omega[2]=list(); for (i=1; i<=n; i++) { omega[2][i]=list(i); } for (i=2; i<=n; i++) { omega[i+1]=list(); for (j=1; j<=size(omega[i]); j++) { if (omega[i][j][size(omega[i][j])]n) {print("ERRORcombinations");} if (m==n) {result[size(result)+1]=lis(m);return(result);} if (m==0) {result[size(result)+1]=list();return(result);} list temp=combinations(m-1,n-1); for (int i=1; i<=size(temp); i++) { temp[i]=temp[i]+list(n); } result=combinations(m,n-1)+temp; return(result); } /////////////////////////////////////////////////////////////////////////////// // the polynomial for Sala's restrictions static proc p_poly(int n, int a, int b) { poly f; for (int i=0; i<=n-1; i++) { f=f+Z(a)^i*Z(b)^(n-1-i); } return(f); } /////////////////////////////////////////////////////////////////////////////// proc sysCRHT (int n, list defset, int e, int q, int m, list #) "USAGE: sysCRHT(n,defset,e,q,m,[k]); n,e,q,m,k are int, defset list of int's @format - n length of the cyclic code, - defset is a list representing the defining set, - e the error-correcting capacity, - q field size - m degree extension of the splitting field, - if k>0 additional equations representing the fact that every two error positions are either different or at least one of them is zero @end format RETURN: the ring to work with the CRHT-ideal (with Sala's additions), containig an ideal with name 'crht' THEORY: Based on 'defset' of the given cyclic code, the procedure constructs the corresponding Cooper-Reed-Heleseth-Truong ideal 'crht'. With its help one can solve the decoding problem. For basics of the method @ref{Cooper philosophy}. SEE ALSO: sysNewton, sysBin EXAMPLE: example sysCRHT; shows an example " { int r=size(defset); ring @crht=(q,a),(Y(e..1),Z(1..e),X(r..1)),lp; ideal crht; int i,j; poly sum; int k; if ( size(#) > 0) { k = #[1]; } //---------------------- add check equations -------------------------- for (i=1; i<=r; i++) { sum=0; for (j=1; j<=e; j++) { sum=sum+Y(j)*Z(j)^defset[i]; } crht[i]=sum-X(i); } //--------------------- field equations on syndromes ------------------ for (i=1; i<=r; i++) { crht=crht,X(i)^(q^m)-X(i); } //------ restrictions on error-locations: n-th roots of unity ---------- for (i=1; i<=e; i++) { crht=crht,Z(i)^(n+1)-Z(i); } for (i=1; i<=e; i++) { crht=crht,Y(i)^(q-1)-1; } //--------- add Sala's additional conditions if necessary -------------- if ( k > 0 ) { for (i=1; i<=e; i++) { for (j=i+1; j<=e; j++) { crht=crht,Z(i)*Z(j)*p_poly(n,i,j); } } } export crht; return(@crht); } example { "EXAMPLE:"; echo=2; // binary cyclic [15,7,5] code with defining set (1,3) intvec v = option(get); list defset=1,3; // defining set int n=15; // length int e=2; // error-correcting capacity int q=2; // basefield size int m=4; // degree extension of the splitting field int sala=1; // indicator to add additional equations def A=sysCRHT(n,defset,e,q,m); setring A; A; // shows the ring we are working in print(crht); // the CRHT-ideal option(redSB); ideal red_crht=std(crht); // reduced Groebner basis print(red_crht); //============================ A=sysCRHT(n,defset,e,q,m,sala); setring A; print(crht); // CRHT-ideal with additional equations from Sala option(redSB); ideal red_crht=std(crht); // reduced Groebner basis print(red_crht); red_crht[5]; // general error-locator polynomial for this code option(set,v); } /////////////////////////////////////////////////////////////////////////////// proc sysCRHTMindist (int n, list defset, int w) "USAGE: sysCRHTMindist(n,defset,w); n,w are int, defset is list of int's @format - n length of the cyclic code, - defset is a list representing the defining set, - w is a candidate for the minimum distance @end format RETURN: the ring to work with the Sala's ideal for the minimum distance containing the ideal with name 'crht_md' THEORY: Based on 'defset' of the given cyclic code, the procedure constructs the corresponding Cooper-Reed-Heleseth-Truong ideal 'crht_md'. With its help one can find minimum distance of the code in the binary case. For basics of the method @ref{Cooper philosophy}. EXAMPLE: example sysCRHTMindist; shows an example " { int r=size(defset); ring @crht_md=2,Z(1..w),lp; ideal crht_md; int i,j; poly sum; //------------ add check equations -------------- for (i=1; i<=r; i++) { sum=0; for (j=1; j<=w; j++) { sum=sum+Z(j)^defset[i]; } crht_md[i]=sum; } //----------- locations are n-th roots of unity ------------ for (i=1; i<=w; i++) { crht_md=crht_md,Z(i)^n-1; } //------------ adding conditions on locations being different ------------ for (i=1; i<=w; i++) { for (j=i+1; j<=w; j++) { crht_md=crht_md,Z(i)*Z(j)*p_poly(n,i,j); } } export crht_md; return(@crht_md); } example { "EXAMPLE:"; echo=2; intvec v = option(get); // binary cyclic [15,7,5] code with defining set (1,3) list defset=1,3; // defining set int n=15; // length int d=5; // candidate for the minimum distance def A=sysCRHTMindist(n,defset,d); setring A; A; // shows the ring we are working in print(crht_md); // the Sala's ideal for mindist option(redSB); ideal red_crht_md=std(crht_md); print(red_crht_md); // reduced Groebner basis option(set,v); } /////////////////////////////////////////////////////////////////////////////// // slightly modified mod function static proc mod_ (int n, int m) { n=n mod m; if (n<=0){ return(n+m);} return(n); } /////////////////////////////////////////////////////////////////////////////// proc sysNewton (int n, list defset, int t, int q, int m, list #) "USAGE: sysNewton (n,defset,t,q,m,[tr]); n,t,q,m,tr int, defset is list int's @format - n is length, - defset is the defining set, - t is the number of errors, - q is basefield size, - m is degree extension of the splitting field, - if tr>0 it indicates that Newton identities in triangular form should be constructed @end format RETURN: the ring to work with the generalized Newton identities (in triangular form if applicable) containing the ideal with name 'newton' THEORY: Based on 'defset' of the given cyclic code, the procedure constructs the corresponding ideal 'newton' with the generalized Newton identities. With its help one can solve the decoding problem. For basics of the method @ref{Generalized Newton identities}. SEE ALSO: sysCRHT, sysBin EXAMPLE: example sysNewton; shows an example " { string s="ring @newton=("+string(q)+",a),("; int i,j; int flag; int tr; if (size(#)>0) { tr=#[1]; } for (i=n; i>=1; i--) { for (j=1; j<=size(defset); j++) { flag=1; if (i==defset[j]) { flag=0; break; } } if (flag) { s=s+"S("+string(i)+"),"; } } s=s+"sigma(1.."+string(t)+"),"; for (i=size(defset); i>=2; i--) { s=s+"S("+string(defset[i])+"),"; } s=s+"S("+string(defset[1])+")),lp;"; execute(s); ideal newton; poly sum; //------------ generate generalized Newton identities ---------- if (tr) { for (i=1; i<=t; i++) { sum=0; for (j=1; j<=i-1; j++) { sum=sum+sigma(j)*S(i-j); } newton=newton,S(i)+sum+number(i)*sigma(i); } } else { for (i=1; i<=t; i++) { sum=0; for (j=1; j<=t; j++) { sum=sum+sigma(j)*S(mod_(i-j,n)); } newton=newton,S(i)+sum; } } for (i=1; i<=n-t; i++) { sum=0; for (j=1; j<=t; j++) { sum=sum+sigma(j)*S(t+i-j); } newton=newton,S(t+i)+sum; } //----------- add field equations on sigma's -------------- for (i=1; i<=t; i++) { newton=newton,sigma(i)^(q^m)-sigma(i); } //----------- add conjugacy relations ------------------ for (i=1; i<=n; i++) { newton=newton,S(i)^q-S(mod_(q*i,n)); } newton=simplify(newton,2); export newton; return(@newton); } example { "EXAMPLE:"; echo = 2; // Newton identities for a binary 3-error-correcting cyclic code of //length 31 with defining set (1,5,7) int n=31; // length list defset=1,5,7; //defining set int t=3; // number of errors int q=2; // basefield size int m=5; // degree extension of the splitting field int tr=1; // indicator of triangular form of Newton identities def A=sysNewton(n,defset,t,q,m); setring A; A; // shows the ring we are working in print(newton); // generalized Newton identities //=============================== A=sysNewton(n,defset,t,q,m,tr); setring A; print(newton); // generalized Newton identities in triangular form } /////////////////////////////////////////////////////////////////////////////// // forms a list of special combinations needed for computation of Waring's //function static proc combinations_sum (int m, int n) { list result; list comb=combinations(m-1,n+m-1); int i,j,flag,count; list interm=comb; for (i=1; i<=size(comb); i++) { interm[i][1]=comb[i][1]-1; for (j=2; j<=m-1; j++) { interm[i][j]=comb[i][j]-comb[i][j-1]-1; } interm[i][m]=n+m-comb[i][m-1]-1; flag=1; count=2; while ((flag)&&(count<=m)) { if (interm[i][count] mod count != 0) {flag=0;} count++; } if (flag) { for (j=2; j<=m; j++) { interm[i][j]=interm[i][j] div j; } result[size(result)+1]=interm[i]; } } return(result); } /////////////////////////////////////////////////////////////////////////////// //if n=q^e*m, m and n are coprime, then return e static proc exp_count (int n, int q) { int flag=1; int result=0; while(flag) { if (n mod q != 0) {flag=0;} else {n=n div q; result++;} } return(result); } /////////////////////////////////////////////////////////////////////////////// proc sysBin (int v, list Q, int n, list #) "USAGE: sysBin (v,Q,n,[odd]); v,n,odd are int, Q is list of int's @format - v a number if errors, - Q is a defining set of the code, - n the length, - odd is an additional parameter: if set to 1, then the defining set is enlarged by odd elements, which are 2^(some power)*(some elment in the def.set) mod n @end format RETURN: the ring with the resulting system called 'bin' THEORY: Based on Q of the given cyclic code, the procedure constructs the corresponding ideal 'bin' with the use of the Waring function. With its help one can solve the decoding problem. For basics of the method @ref{Generalized Newton identities}. SEE ALSO: sysNewton, sysCRHT EXAMPLE: example sysBin; shows an example " { int odd; if (size(#)>0) { odd=#[1]; } //ring r=2,(sigma(1..v),S(1..n)),(lp(v),dp(n)); ring r=2,(S(1..n),sigma(1..v)),lp; list cyclot; ideal result; int i,j,k,s; list comb; poly sum_, mon; int count1, count2, upper, coef_, flag, gener; list Q_update; if (odd==1) { for (i=1; i<=n; i++) { cyclot[i]=0; } for (i=1; i<=size(Q); i++) { flag=1; gener=Q[i]; while(flag) { cyclot[gener]=1; gener=2*gener mod n; if (gener == Q[i]) {flag=0;} } } for (i=1; i<=n; i++) { if ((cyclot[i] == 1)&&(i mod 2 == 1)) {Q_update[size(Q_update)+1]=i;} } } else { Q_update=Q; } //---- form polynomials for the Bin system via Waring's function --------- for (i=1; i<=size(Q_update); i++) { comb=combinations_sum(v,Q_update[i]); sum_=0; for (k=1; k<=size(comb); k++) { upper=0; for (j=1; j<=v; j++) { upper=upper+comb[k][j]; } count1=0; for (j=2; j<=upper-1; j++) { count1=count1+exp_count(j,2); } count1=count1+exp_count(Q_update[i],2); count2=0; for (j=1; j<=v; j++) { for (s=2; s<=comb[k][j]; s++) { count2=count2+exp_count(s,2); } } if (count1count2) {coef_=0;} if (count1 == count2) {coef_=1;} mon=1; for (j=1; j<=v; j++) { mon=mon*sigma(j)^(comb[k][j]); } sum_=sum_+coef_*mon; } result=result,S(Q_update[i])-sum_; } ideal bin=simplify(result,2); export bin; return(r); } example { "EXAMPLE:"; echo = 2; // [31,16,7] quadratic residue code list l=1,5,7,9,19,25; // we do not need even synromes here def A=sysBin(3,l,31); setring A; print(bin); } /////////////////////////////////////////////////////////////////////////////// proc encode (matrix x, matrix g) "USAGE: encode (x, g); x a row vector (message), and g a generator matrix RETURN: corresponding codeword EXAMPLE: example encode; shows an example " { if (nrows(x)>1) {print("ERRORencode1!");} if (ncols(x)!=nrows(g)) {print("ERRORencode2!");} return(x*g); } example { "EXAMPLE:"; echo = 2; ring r=2,x,dp; matrix x[1][4]=1,0,1,0; matrix g[4][7]=1,0,0,0,0,1,1, 0,1,0,0,1,0,1, 0,0,1,0,1,1,1, 0,0,0,1,1,1,0; //encode x with the generator matrix g print(encode(x,g)); } /////////////////////////////////////////////////////////////////////////////// proc syndrome (matrix h, matrix c) "USAGE: syndrome (h, c); h a check matrix, c a row vector (codeword) RETURN: corresponding syndrome EXAMPLE: example syndrome; shows an example " { if (nrows(c)>1) {print("ERRORsyndrome1!");} if (ncols(c)!=ncols(h)) {print("ERRORsyndrome2!");} return(h*transpose(c)); } example { "EXAMPLE:"; echo = 2; ring r=2,x,dp; matrix x[1][4]=1,0,1,0; matrix g[4][7]=1,0,0,0,0,1,1, 0,1,0,0,1,0,1, 0,0,1,0,1,1,1, 0,0,0,1,1,1,0; //encode x with the generator matrix g matrix c=encode(x,g); // disturb c[1,3]=0; //compute syndrome //corresponding check matrix matrix check[3][7]=1,0,0,1,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1,1,1; print(syndrome(check,c)); c[1,3]=1; //now c is a codeword print(syndrome(check,c)); } /////////////////////////////////////////////////////////////////////////////// // (coordinatewise) star product of two vectors static proc star(matrix m, int i, int j) { matrix result[ncols(m)][1]; for (int k=1; k<=ncols(m); k++) { result[k,1]=m[i,k]*m[j,k]; } return(result); } /////////////////////////////////////////////////////////////////////////////// proc sysQE(matrix check, matrix y, int t, list #) "USAGE: sysQE(check,y,t,[fieldeq,formal]);check,y matrix;t,fieldeq,formal int @format - check is a parity check matrix of the code - y is a received word, - t the number of errors to be corrected, - if fieldeq=1, then field equations are added, - if formal=0, field equations on (known) syndrome variables are not added, in order to add them (note that the exponent should be equal to the number of elements in the INITIAL alphabet) one needs to set formal>0 for the exponent @end format RETURN: the ring to work with together with the resulting system called 'qe' THEORY: Based on 'check' of the given linear code, the procedure constructs the corresponding ideal that gives an opportunity to compute unknown syndrome of the received word y. After computing the unknown syndromes one is able to solve the decoding problem. For basics of the method @ref{Decoding method based on quadratic equations}. SEE ALSO: sysFL EXAMPLE: example sysQE; shows an example " { int fieldeq; int formal; if (size(#)>0) { fieldeq=#[1]; } if (size(#)>1) { formal=#[2]; } def br=basering; list rl=ringlist(br); int red=nrows(check); int n=ncols(check); int q=rl[1][1]; if (formal==0) { ring work=(q,a),(V(1..t),U(1..n)),dp; } else { ring work=(q,a),(V(1..t),U(1..n),s(1..red)),(dp(t),lp(n),dp(red)); } matrix check=imap(br,check); matrix y=imap(br,y); matrix h_full=genMDSMat(n,a); matrix h=submat(h_full,1..red,1..n); if (nrows(y)!=1) {print("ERROR1Pell");} if (ncols(y)!=n) {print("ERROR2Pell");} ideal result; list c; list a; list tmp,tmp2; int i,j,l,k; number sum,prod,sig; poly sum1,sum2,sum3; for (i=1; i<=n; i++) { c[i]=tmp; } matrix transf=inverse(transpose(h_full)); //------ expression matrix of check vectors w.r.t. the MDS basis ----------- for (i=1; i<=red ; i++) { a[i]=transpose(submat(check,i..i,1..n)); a[i]=transf*a[i]; } //----------- compute the structure constants ------------------------ matrix te[n][1]; for (i=1; i<=n; i++) { for (j=1; j<=t+1; j++) { if ((j0) { e=#[1]; } option(redSB); def br=basering; matrix h_full=genMDSMat(n,a); matrix z[1][ncols(h_full)]; //------------------ determine error-correction capacity ------------------- for (i=1; i<=ncodes; i++) { setring br; h=randomCheck(redun,n,1); "check matrix:"; print(h); if (e>0) { t=e; } else { tmp=mindist(h); dist=tmp; printf("d= %p",dist); t=(dist-1) div 2; } //------------- generate the template system ---------------------- def A=sysQE(h,z,t); setring A; matrix word,y,rec; ideal sys2,sys3; matrix h=imap(br,h); matrix g=dual_code(h); ideal sys=qe; print("The system is generated"); //------ modify the template according to every received word -------------- for (j=1; j<=ntrials; j++) { word=randomvector(n-redun,1); y=encode(transpose(word),g); print("Codeword:"); print(y); rec=errorRand(y,t,1); print("Received word:"); print(rec); sys2=add_synd(rec,h,redun,sys); option(redSB); sys3=std(sys2); print("The Groebenr basis of the QE system:"); print(sys3); } kill A; option(set,vopt); } } example { "EXAMPLE:"; echo = 2; int q=32; int n=25; int redun=n-11; int t=redun+1; ring r=(q,a),x,dp; // correct 2 errors in 2 random binary codes, 3 trials each decodeRandom(n,redun,2,3,2); } /////////////////////////////////////////////////////////////////////////////// proc decodeCode(matrix check, int ntrials, list #) "USAGE: decodeCode(check, ntrials, [e]); check matrix, ntrials,e int @format - check is a parity check matrix for the code, - ntrials is the number of received vectors per code to be corrected. - If e is given it sets the correction capacity explicitly. It should be used in case one expects some lower bound, otherwise the procedure tries to compute the real minimum distance to find out the error-correction capacity @end format RETURN: nothing; EXAMPLE: example decodeCode; shows an example " { intvec vopt = option(get); int n=ncols(check); int redun=nrows(check); int i,j; matrix h; int dist, t; ideal sys; int tmp; int e; if (size(#)>0) { e=#[1]; } option(redSB); def br=basering; matrix h_full=genMDSMat(n,a); matrix z[1][ncols(h_full)]; setring br; h=check; "check matrix:"; print(h); //------------------ determine error-correction capacity ------------------- if (e>0) { t=e; } else { tmp=mindist(h); dist=tmp; printf("d= %p",dist); t=(dist-1) div 2; } //------------- generate the template system ---------------------- def A=sysQE(h,z,t); setring A; matrix word,y,rec; ideal sys2,sys3; matrix h=imap(br,h); matrix g=dual_code(h); ideal sys=qe; print("The system is generated"); //--- modify the template according to every received word --------------- for (j=1; j<=ntrials; j++) { word=randomvector(n-redun,1); y=encode(transpose(word),g); print("Codeword:"); print(y); rec=errorRand(y,t,1); print("Received word:"); print(rec); sys2=add_synd(rec,h,redun,sys); option(redSB); sys3=std(sys2); print("Groebner basis of the QE system:"); print(sys3); } option(set,vopt); } example { "EXAMPLE:"; echo = 2; int q=32; int n=25; int redun=n-11; int t=redun+1; ring r=(q,a),x,dp; matrix check=randomCheck(redun,n,1); // correct 2 errors in using the code above, 3 trials decodeCode(check,3,2); } /////////////////////////////////////////////////////////////////////////////// // adding syndrome values to the template system static proc add_synd (matrix rec, matrix check, int redun, ideal sys) { ideal result=sys; matrix s[redun][1]=syndrome(check,rec); for (int i=1; i<=redun; i++) { result[i]=result[i]-s[i,1]; } return(result); } /////////////////////////////////////////////////////////////////////////////// // evaluate a polynomial at a given point static proc ev (poly f, matrix p) { if (ncols(p)>1) {ERROR("not a column vector");}; int m=size(p); poly temp=f; for (int i=1; i<=m; i++) { temp=subst(temp,var(i),p[i,1]); } return(number(temp)); } /////////////////////////////////////////////////////////////////////////////// // return index of an element in the ideal where it does not vanish at the //given point static proc find_index (ideal G, matrix p) { if (ncols(p)>1) {ERROR("not a column vector");}; int i=1; int n=size(G); while(i<=n) { if (ev(G[i],p)!=0) {return(i);} i++; } return(-1); } /////////////////////////////////////////////////////////////////////////////// // convert ideal to list static proc ideal2list (ideal id) { list l; for (int i=1; i<=size(id); i++) { l[i]=id[i]; } return(l); } /////////////////////////////////////////////////////////////////////////////// // convert list to ideal static proc list2ideal (list l) { ideal id; for (int i=1; i<=size(l); i++) { id[i]=l[i]; } return(id); } /////////////////////////////////////////////////////////////////////////////// // check whether given polynomial is divisible by some leading monomial of the //ideal static proc divisible (poly m, ideal G) { for (int i=1; i<=size(G); i++) { if (m/leadmonom(G[i])!=0) {return(1);} } return(0); } /////////////////////////////////////////////////////////////////////////////// proc vanishId (list points) "USAGE: vanishId (points); point is a list of matrices 'points' is a list of points for which the vanishing ideal is to be constructed RETURN: Vanishing ideal corresponding to the given set of points EXAMPLE: example vanishId; shows an example " { int m=size(points[1]); int n=size(points); ideal G=1; int i,k,j; list temp; poly h,cur; //------------- proceed according to Farr-Gao algorithm ---------------- for (k=1; k<=n; k++) { i=find_index(G,points[k]); cur=G[i]; for(j=i+1; j<=size(G); j++) { G[j]=G[j]-ev(G[j],points[k])/ev(G[i],points[k])*G[i]; } G=simplify(G,2); temp=ideal2list(G); temp=delete(temp,i); G=list2ideal(temp); for (j=1; j<=m; j++) { if (!divisible(var(j)*leadmonom(cur),G)) { attrib(G,"isSB",1); h=NF((var(j)-points[k][j,1])*cur,G); temp=ideal2list(G); temp=insert(temp,h); G=list2ideal(temp); G=sort(G)[1]; } } } attrib(G,"isSB",1); return(G); } example { "EXAMPLE:"; echo = 2; ring r=3,(x(1..3)),dp; //generate all 3-vectors over GF(3) list points=pointsGen(3,1); list points2=convPoints(points); //grasps the first 11 points list p=graspList(points2,1,11); print(p); //construct the vanishing ideal ideal id=vanishId(p); print(id); } /////////////////////////////////////////////////////////////////////////////// // construct the list of all vectors of length m with elements in p^e, where p // is theharacteristic proc pointsGen (int m, int e) { if (e>1) { list result; int count=1; int i,j; list l=ringlist(basering); int charac=l[1][1]; number a=par(1); list tmp; for (i=1; i<=charac^(e*m); i++) { result[i]=tmp; } if (m==1) { result[count][m]=0; count++; for (j=1; j<=charac^(e)-1; j++) { result[count][m]=a^j; count++; } return(result); } list prev=pointsGen(m-1,e); for (i=1; i<=size(prev); i++) { result[count]=prev[i]; result[count][m]=0; count++; for (j=1; j<=charac^(e)-1; j++) { result[count]=prev[i]; result[count][m]=a^j; count++; } } return(result); } if (e==1) { list result; int count=1; int i,j; list l=ringlist(basering); int charac=l[1][1]; list tmp; for (i=1; i<=charac^m; i++) { result[i]=tmp; } if (m==1) { for (j=0; j<=charac-1; j++) { result[count][m]=number(j); count++; } return(result); } list prev=pointsGen(m-1,e); for (i=1; i<=size(prev); i++) { for (j=0; j<=charac-1; j++) { result[count]=prev[i]; result[count][m]=number(j); count++; } } return(result); } } /////////////////////////////////////////////////////////////////////////////// // convert list to a column vector static proc list2vec (list l) { matrix m[size(l)][1]; for (int i=1; i<=size(l); i++) { m[i,1]=l[i]; } return(m); } /////////////////////////////////////////////////////////////////////////////// // convert all the point in the list with list2vec proc convPoints (list points) { for (int i=1; i<=size(points); i++) { points[i]=list2vec(points[i]); } return(points); } /////////////////////////////////////////////////////////////////////////////// // extracts elements from l in the range m..n proc graspList (list l, int m, int n) { list result; int count=1; for (int i=m; i<=n; i++) { result[count]=l[i]; count++; } return(result); } /////////////////////////////////////////////////////////////////////////////// // "characteristic" polynomial static proc xi_gen (matrix p, int e, int s) { poly prod=1; list rl=ringlist(basering); int charac=rl[1][1]; int l; for (l=1; l<=s; l++) { prod=prod*(1-(var(l)-p[l,1])^(charac^e-1)); } return(prod); } /////////////////////////////////////////////////////////////////////////////// // generating polynomials in Fitzgerald-Lax construction static proc gener_funcs (matrix check, list points, int e, ideal id, int s) { int n=ncols(check); if (n!=size(points)) {ERROR("Incompatible sizes of check and points");} ideal xi; int i,j; for (i=1; i<=n; i++) { xi[i]=xi_gen(points[i],e,s); } ideal result; int m=nrows(check); poly sum; for (i=1; i<=m; i++) { sum=0; for (j=1; j<=n; j++) { sum=sum+check[i,j]*xi[j]; } result[i]=NF(sum,id); } return(result); } /////////////////////////////////////////////////////////////////////////////// proc sysFL (matrix check, matrix y, int t, int e, int s) "USAGE: sysFL (check,y,t,e,s); check,y matrix, t,e,s int @format - check is a parity check matrix of the code, - y is a received word, - t the number of errors to correct, - e is the extension degree, - s is the dimension of the point for the vanishing ideal @end format RETURN: the system of Fitzgerald-Lax for the given decoding problem THEORY: Based on 'check' of the given linear code, the procedure constructs the corresponding ideal constructed with a generalization of Cooper's philosophy. For basics of the method @ref{Fitzgerald-Lax method}. SEE ALSO: sysQE EXAMPLE: example sysFL; shows an example " { list rl=ringlist(basering); int charac=rl[1][1]; int n=ncols(check); int m=nrows(check); list points=pointsGen(s,e); list points2=convPoints(points); list p=graspList(points2,1,n); ideal id=vanishId(p,e); ideal funcs=gener_funcs(check,p,e,id,s); ideal result; poly temp; int i,j,k; //--------------- add vanishing realtions --------------------- for (i=1; i<=t; i++) { for (j=1; j<=size(id); j++) { temp=id[j]; for (k=1; k<=s; k++) { temp=subst(temp,var(k),x_var(i,k,s)); } result=result,temp; } } //--------------- add field equations -------------------- for (i=1; i<=t; i++) { for (k=1; k<=s; k++) { result=result,x_var(i,k,s)^(charac^e)-x_var(i,k,s); } } for (i=1; i<=t; i++) { result=result,e(i)^(charac^e-1)-1; } result=simplify(result,8); //--------------- add check realtions -------------------- poly sum; matrix syn[m][1]=syndrome(check,y); for (i=1; i<=size(funcs); i++) { sum=0; for (j=1; j<=t; j++) { temp=funcs[i]; for (k=1; k<=s; k++) { temp=subst(temp,var(k),x_var(j,k,s)); } sum=sum+temp*e(j); } result=result,sum-syn[i,1]; } result=simplify(result,2); points=points2; export points; return(result); } example { "EXAMPLE:"; echo = 2; intvec vopt = option(get); list l=FLpreprocess(3,1,11,2,""); def r=l[1]; setring r; int s_work=l[2]; //the check matrix of [11,6,5] ternary code matrix h[5][11]=1,0,0,0,0,1,1,1,-1,-1,0, 0,1,0,0,0,1,1,-1,1,0,-1, 0,0,1,0,0,1,-1,1,0,1,-1, 0,0,0,1,0,1,-1,0,1,-1,1, 0,0,0,0,1,1,0,-1,-1,1,1; matrix g=dual_code(h); matrix x[1][6]; matrix y[1][11]=encode(x,g); //disturb with 2 errors matrix rec[1][11]=errorInsert(y,list(2,4),list(1,-1)); //the Fitzgerald-Lax system ideal sys=sysFL(h,rec,2,1,s_work); print(sys); option(redSB); ideal red_sys=std(sys); red_sys; // read the solutions from this redGB // the points are (0,0,1) and (0,1,0) with error values 1 and -1 resp. // use list points to find error positions; points; option(set,vopt); } /////////////////////////////////////////////////////////////////////////////// // preprocessing steps for the Fitzgerald-Lax scheme proc FLpreprocess (int p, int e, int n, int t, string minp) { ring r1=p,x,dp; int s=1; while(p^(s*e)=1; i--) { var_ord[count]=string("x("+string(i)+")"); count++; } for (i=t; i>=1; i--) { var_ord[count]=string("e("+string(i)+")"); count++; for (j=s; j>=1; j--) { var_ord[count]=string("x1("+string(s*(i-1)+j)+")"); count++; } } list rl; list tmp; if (e>1) { rl[1]=tmp; rl[1][1]=p; rl[1][2]=tmp; rl[1][2][1]=string("a"); rl[1][3]=tmp; rl[1][3][1]=tmp; rl[1][3][1][1]=string("lp"); rl[1][3][1][2]=1; rl[1][4]=ideal(0); } else { rl[1]=p; } rl[2]=var_ord; rl[3]=tmp; rl[3][1]=tmp; rl[3][1][1]=string("lp"); intvec v=1; for (i=1; i<=size(var_ord)-1; i++) { v=v,1; } rl[3][1][2]=v; rl[3][2]=tmp; rl[3][2][1]=string("C"); rl[3][2][2]=intvec(0); rl[4]=ideal(0); def r2=ring(rl); setring r2; list l=ringlist(r2); if (e>1) { execute(string("poly f="+minp)); ideal id=f; l[1][4]=id; } def r=ring(l); setring r; return(list(r,s)); } /////////////////////////////////////////////////////////////////////////////// // imitating two indeces static proc x_var (int i, int j, int s) { return(x1(s*(i-1)+j)); } /////////////////////////////////////////////////////////////////////////////// // random vector of length n with entries from p^e, p the characteristic static proc randomvector(int n, int e) { int i; matrix result[n][1]; for (i=1; i<=n; i++) { result[i,1]=asElement(random_prime_vector(e)); } return(result); } /////////////////////////////////////////////////////////////////////////////// // "convert" representation of an element from the field extension from vector //to an elelemnt static proc asElement(list l) { number s; int i; number w=1; if (size(l)>1) {w=par(1);} for (i=0; i<=size(l)-1; i++) { s=s+w^i*l[i+1]; } return(s); } /////////////////////////////////////////////////////////////////////////////// // random vector of length n with entries from p, p the characteristic static proc random_prime_vector (int n) { list rl=ringlist(basering); int i, charac; for (i=2; i<=rl[1][1]; i++) { if (rl[1][1] mod i ==0) { break; } } charac=i; list l; for (i=1; i<=n; i++) { l=l+list(random(0,charac-1)); } return(l); } /////////////////////////////////////////////////////////////////////////////// proc decodeRandomFL(int n, int redun, int p, int e, int t, int ncodes, int ntrials, string minpol) "USAGE: decodeRandomFL(redun,p,e,n,t,ncodes,ntrials,minpol); @format - n is length of codes generated, - redun = redundancy of codes generated, - p is the characteristic, - e is the extension degree, - t is the number of errors to correct, - ncodes is the number of random codes to be processed, - ntrials is the number of received vectors per code to be corrected, - minpol: due to some pecularities of SINGULAR one needs to provide minimal polynomial for the extension explicitly @end format RETURN: nothing EXAMPLE: example decodeRandomFL; shows an example " { intvec vopt = option(get); list l=FLpreprocess(p,e,n,t,minpol); def r=l[1]; int s_work=l[2]; export(s_work); setring r; int i,j; matrix h, g, word, y, rec; ideal sys, sys2, sys3; option(redSB); matrix z[1][n]; for (i=1; i<=ncodes; i++) { h=randomCheck(redun,n,e); g=dual_code(h); //---------------- generate the template system ----------------------- sys=sysFL(h,z,t,e,s_work); //------ modifying the template according to the received word --------- for (j=1; j<=ntrials; j++) { word=randomvector(n-redun,1); y=encode(transpose(word),g); print("Codeword:"); print(y); rec=errorRand(y,t,e); print("Received word"); print(rec); sys2=LF_add_synd(rec,h,sys); sys3=std(sys2); print("Groebner basis of the FL system:"); print(sys3); } } option(set,vopt); } example { "EXAMPLE:"; echo = 2; // correcting one error for one random binary code of length 25, // redundancy 14; 10 words are processed decodeRandomFL(25,14,2,1,1,1,10,""); } /////////////////////////////////////////////////////////////////////////////// // add syndrome values to the template system in FL static proc LF_add_synd (matrix rec, matrix check, ideal sys) { int redun=nrows(check); ideal result=sys; matrix s[redun][1]=syndrome(check,rec); for (int i=size(sys)-redun+1; i<=size(sys); i++) { result[i]=result[i]-s[i-size(sys)+redun,1]; } return(result); } /* ////////////// SOME RELATIVELY EASY EXAMPLES ////////////// /////////////////// THAT RUN AROUND ONE MINUTE //////////////// "EXAMPLE:"; echo = 2; int q=128; int n=120; int redun=n-30; ring r=(q,a),x,dp; decodeRandom(n,redun,1,1,6); int q=128; int n=120; int redun=n-20; ring r=(q,a),x,dp; decodeRandom(n,redun,1,1,9); int q=128; int n=120; int redun=n-10; ring r=(q,a),x,dp; decodeRandom(n,redun,1,1,19); int q=256; int n=150; int redun=n-10; ring r=(q,a),x,dp; decodeRandom(n,redun,1,1,22); ////////////// SOME HARD EXAMPLES ////////////////////// ////// THAT MAYBE WILL BE DOABLE LATER /////////////// 1.) These random instances are not doable in <=1000 sec. "EXAMPLE:"; echo = 2; int q=128; int n=120; int redun=n-40; ring r=(q,a),x,dp; decodeRandom(n,redun,1,1,6); redun=n-30; decodeRandom(n,redun,1,1,8); redun=n-20; decodeRandom(n,redun,1,1,12); redun=n-10; decodeRandom(n,redun,1,1,24); int q=256; int n=150; int redun=n-10; ring r=(q,a),x,dp; decodeRandom(n,redun,1,1,26); 2.) Generic decoding is hard! int q=32; int n=31; int redun=n-16; int t=3; ring r=(q,a),(V(1..n),U(n..1),s(redun..1)),(dp(n),lp(n),dp(redun)); matrix check[redun][n]= 1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1, 0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0, 0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1, 0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0, 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0, 1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0, 1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, 1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0,1, 0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1, 0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,1,1,0,1,1,0,0,0,1,0,1,0,0,1,0,0,1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0, 0,1,0,1,0,0,1,0,0,1; matrix rec[1][n]; def A=sysQE(check,rec,t,1,2); setring A; print(qe); ideal red_qe=stdfglm(qe); */ singular-4.0.3+ds/Singular/LIB/decomp.lib000066400000000000000000001324771266270727000201240ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////// version="version decomp.lib 4.0.0.0 Jun_2013 "; // $Id: 6bfa7a1841ebda249c7957bf6dba5c0da562ab52 $ // last changed 21.5.12 C.G. reversal wieder eingefuegt (standalone) category = "general"; info = " LIBRARY: decomp.lib Functional Decomposition of Polynomials AUTHOR: Christian Gorzel, University of Muenster email: gorzelc@math.uni-muenster.de OVERVIEW: @texinfo This library implements functional uni-multivariate decomposition of multivariate polynomials. A (multivariate) polynomial f is a composite if it can be written as @math{g \\circ h} where g is univariate and h is multivariate, where @math{\\deg(g), \\deg(h)>1}. Uniqueness for monic polynomials is up to linear coordinate change @tex $g\\circ h = g(x/c -d) \\circ c(h(x)+d)$. @end tex If f is a composite, then @code{decompose(f);} returns an ideal (g,h); such that @math{\\deg(g) < \\deg(f)} is maximal, (@math{\\deg(h)\\geq 2}). The polynomial h is, by the maximality of @math{\\deg(g)}, not a composite. The polynomial g is univariate in the (first) variable vvar of f, such that deg_vvar(f) is maximal. @code{decompose(f,1);} computes a full decomposition, i.e. if f is a composite, then an ideal @math{(g_1,\\dots ,g_m,h)} is returned, where @math{g_i} are univariate and each entry is primitive such that @math{f=g_1\\circ \\dots \\circ g_m\\circ h}. If f is not a composite, for instance if @math{\\deg(f)} is prime, then @code{decompose(f);} returns f. The command @code{decompose} is the inverse: @code{compose(decompose(f,1))==f}. Recall, that Chebyshev polynomials of the first kind commute by composition. @* The decomposition algorithms work in the tame case, that is if char(basering)=0 or p:=char(basering) > 0 but deg(g) is not divisible by p. Additionally, it works for monic polynomials over @math{Z} and in some cases for monic polyomials over coefficient rings. @* See @code{is_composite} for examples. (It also works over the reals but there it seems not be numerical stable.) @* More information on the univariate resp. multivariate case. @* Univariate decomposition is created, with the additional assumption @math{\\deg(g), \\deg(h)>1}. @* A multivariate polynomial f is a composite, if f can be written as @math{g \\circ h}, where @math{g} is a univariate polynomial and @math{h} is multivariate. Note, that unlike in the univariate case, the polynomial @math{h} may be of degree @math{1}. @* E.g. @math{f = (x+y)^2+ 2(x+y) +1} is the composite of @math{g = x^2+2x+1} and @math{h = x+y}. @* If @code{nvars(basering)>1}, then, by default, a single-variable multivariate polynomial is not considered to be the same as in the one-variable polynomial ring; it will always be decomposed. That is: @* @code{> ring r1=0,x,dp;} @* @code{> decompose(x3+2x+1);} @* @code{x3+2x+1} @* but: @* @code{> ring r2=0,(x,y),dp;} @* @code{> decompose(x3+2x+1);} @* @code{_[1]=x3+2x+1} @* @code{_[2]=x} @* In particular: @* @code{is_composite(x3+2x+1)==1;} in @code{ring r1} but @* @code{is_composite(x3+2x+1)==0;} in @code{ring r2}. @* This is justified by interpreting the polynomial decomposition as an affine Stein factorization of the mapping @math{f:k^n \\to k, n\\geq 2}. The behaviour can changed by the some global variables. @code{int DECMETH;} choose von zur Gathen's or Kozen-Landau's method. @* @code{int MINS;} compute f = g o h, such that h(0) = 0. @* @code{int IMPROVE;} simplify the coefficients of g and h if f is not monic. @* @code{int DEGONE;} single-variable multivariate are considered uni-variate. @* See @code{decompopts;} for more information. Additional information is displayed if @code{printlevel > 0}. @end texinfo REFERENCES: @texinfo @tex D. Kozen, S. Landau: Polynomial Decomposition Algorithms, \\par \\quad \\qquad J. Symb. Comp. (1989), 7, 445-456. \\par J. von zu Gathen: Functional Decomposition of Polynomials: the Tame Case,\\par \\quad \\qquad J. Symb. Comp. (1990), 9, 281-299. \\par J. von zur Gathen, J. Gerhard: Modern computer algebra, \\par \\quad \\qquad Cambridge University Press, Cambridge, 2003. @end tex @end texinfo PROCEDURES: // decompunivmonic(f,r); // decompmultivmonic(f,var,s); decompopts([\"reset\"]); displays resp. resets global options decompose(f[,1]); [complete] functional decomposition of poly f is_composite(f); predicate, is f a composite polynomial? chebyshev(n[,1]); the nth Chebyshev polynomial of the first kind compose(f1,..,fn); compose f1 (f2 (...(fn))), f_i polys of ideal AUXILIARY PROCEDURES: makedistinguished(f,var); transforms f to a var-distinguished polynomial // divisors(n[,1]); intvec [increasing] of the divisors d of n // gcdv(v); the gcd of the entries in intvec v // maxdegs(f); maximal degree for each variable of the poly f // randomintvec(n,a,b[,1]); random intvec size n, [non-zero] entries in {a,b} KEYWORDS: Functional decomposition "; /* decompunivpoly(poly f,list #) // f = goh; r = deg g, s = deg h; Ablauf ist: decompose(f) | check whether f is the composite by a monomial | check whether f is univariate | transformation to a distinguished polynomial decompmultivmonic(f,vvar,r) decompunivmonic(f,r) // detect vvar by maxdegs |lift univariate decomposition | back-transformation | fulldecompose, iterate | decompuniv for g */ /////////////////////////////////////////////////////////////////////////////// proc decompopts(list #) "USAGE: decompopts(); or decompopts(\"reset\"); RETURN: nothing NOTE: @texinfo in the first case, it shows the setting of the control parameters;@* in the second case, it kills the user-defined control parameters and@* resets to the default setting which will then be diplayed. @* @* int DECMETH; Method for computing the univariate decomposition@* 0 : (default) Kozen-Landau @* 1 : von zur Gathen @* int IMPROVE Choice of coefficients for the decomposition @* @math{(g_1,\ldots,g_l,h)} of a non-monic polynomials f. @* 0 : leadcoef(@math{g_1}) = leadcoef(@math{f}) and @math{g_2,\ldots,g_l,h} are monic @* 1 : (default), content(@math{g_i}) = 1 @* int MINS @* @math{f=g\circ h, (g_1,\ldots,g_m,h)} of a non-monic polynomials f.@* 0 : g(0) = f(0), h(0) = 0 [ueberlegen fuer complete] @* 1 : (default), g(0)=0, h(0) = f(0) @* 2 : Tschirnhaus @* int DECORD; The order in which the decomposition will be computed@* 0 : minfirst @* 1 : (default) maxfirst @* int DEGONE; decompose also polynomials built on linear ones @* 0 : (default) @* 1 : @end texinfo EXAMPLE: example decompopts; shows an example " { /* siehe Erlaeuterungen, globale Variablen wie im Header angegeben, suchen mit CTRL-S Top:: diese eintragen */ if (size(#)) { if (string(#[1]) == "reset") { if (defined(DECMETH)) {kill DECMETH;} // if (defined(DECORD)) {kill DECORD;} if (defined(MINS)) {kill MINS;} if (defined(IMPROVE)) {kill IMPROVE;} } } if (voice==2) { ""; " === Global variables for decomp.lib === "; ""; if (!defined(DECMETH)) {" -- DECMETH (int) not defined, implicitly 1";} else { if (DECMETH!=0 and DECMETH!=1) { DECMETH=1; } " -- DECMETH =", DECMETH; } /* if (!defined(DECORD)) {" -- DECORD (int) not defined, implicitly 1";} else { if (DECORD!=0 and DECORD!=1) { DECORD=1; } " -- (int) DECORD =", DECORD; } */ if (!defined(MINS)) {" -- MINS (int) not defined, implicitly 0";} else { if (MINS!=0 and MINS!=1) { MINS = 0; } " -- (int) MINS =", MINS; } if (!defined(IMPROVE)) {" -- IMPROVE (int) not defined, implicitly 1";} else { if (IMPROVE!=0 and IMPROVE!=1) { IMPROVE=1; } " -- (int) IMPROVE =", IMPROVE; } } } example; { "EXAMPLE:"; echo =2; decompopts(); } /////////////////////////////////////////////////////////////////////////////// //static proc decompmonom(poly f, list #) "USAGE: decompmonom(f[,vvar]); f poly, vvar poly PURPOSE: compute a maximal decomposition in case that f = g o h, where g is univariate and h is a single monomial RETURN: ideal, (g,h); g univariate, h monomial if such a decomposition exist, poly, the input, otherwise ASSUME: f is non-constant EXAMPLE: example decompmonom; shows an example " { int i,k; poly g; poly vvar = var(1); if (size(#)) { vvar = var(rvar(#[1])); } //poly vvar = maxdeg(f); poly zeropart = jet(f,0); poly ff = f - zeropart; int mindeg = -deg(ff,-1:nvars(basering)); poly minff = jet(ff,mindeg); if (size(minff)>1) { return(f); } intvec minv = leadexp(minff); minv = minv/gcdv(minv); for (i=1;i<=size(ff);i++) { k = divintvecs(leadexp(ff[i]),minv); if (k==0) { return(f); } else { g = g + leadcoef(ff[i])*vvar^k; } } g = g + zeropart; dbprint("* Sucessfully multivariate decomposed by a monomial"+newline); return(ideal(g,monomial(minv))); } example { "EXAMPLE:"; echo =2; ring r = 0,(x,y),dp; poly f = subst((x2+x3)^150,x,x2y3); decompmonom(f); ring rxyz = 0,(x,y,z),dp; poly g = 1+x2+x3+x5; poly G = subst(g,x,x7y5z3); ideal I = decompmonom(G^50); I[2]; } /////////////////////////////////////////////////////////////////////////////// static proc divintvecs(intvec v,intvec w) "USAGE: divintvecs(v,w); v,w intvec, w!=0 RETURN: int, k if v = k*w, 0 otherwise NOTE: if w==0, then an Error message occurs EXAMPLE: example divintevcs; shows an example " { if (w==0) { ERROR("// Error: proc divintvecs: the second argument has to be non-zero."); return(0); } int i=1; while (w[i]==0) { i++; } int k = v[i] div w[i]; if (v == k*w) { return(k); } else { return(0); } } example { "EXAMPLE:"; echo =2; intvec v = 1,2,3; intvec w = 2,4,6; divintvecs(w,v); divintvecs(intvec(3,2,9),v); } /////////////////////////////////////////////////////////////////////////////// static proc gcdv(intvec v) "USAGE: gcdv(v); intvec v RETURN: int, the gcd of the entries in v NOTE: if v=0, then gcdv(v)=1 @* this is different from Singular's builtin gcd, where gcd(0,0)==0 EXAMPLE: example gcdv; shows an example " { int ggt; int i,n; ggt = v[1]; for (i=2;i<=size(v);i++) { ggt = gcd(ggt,v[i]); } if (ggt==0) { ggt = 1; } return(ggt); } example { "EXAMPLE:"; echo =2; intvec v = 6,15,21; gcdv(v); gcdv(0:3); } /////////////////////////////////////////////////////////////////////////////// static proc divisors(int n,list #) "USAGE: divisors(n); n int divisors(n,1); n int RETURN: intvec, the positive divisors of n @* in decreasing order (default) @* in increasing order in the second case EXAMPLE: example divisors; shows an example " { int i,j; intvec v = 1; list l = primefactors(n); list primesl = l[1]; list multl = l[2]; for (i=1;i<=size(primesl);i++) { for (j=1;j<=multl[i];j++) { v = v,primesl[i]*v;} } ring rhelp =0,x,dp; // sort the intvec poly h; for(i=1;i<=size(v);i++) { h = h+x^v[i]; } v=0; for(i=1;i<=size(h);i++) { v[i]=leadexp(h[i])[1]; } if (size(#)) { return(intvec(v[size(v)..1])); } return(v); } example { "EXAMPLE:"; echo = 2; divisors(30); divisors(-24,1); } /////////////////////////////////////////////////////////////////////////////// // // Dies wirkt sich nur aus wenn Brueche vorhanden sind?! // Laeuft dann so statt cleardenom usw. problemlos ueber Z,Z_m // ansehen. // static proc improvecoef(poly g0,poly h0,number lc) "USAGE: improvecoef(g0,h0,lc); g0, h0 poly; lc number RETURN: poly, poly, number ASSUME: global ordering EXAMPLE: example improvecoef; shows an example " { int Zcoefs = find(charstr(basering),"integer"); poly vvar = var(univariate(g0)); number lch0 = leadcoef(h0); number denom; if (Zcoefs and lch0<0) // da cleardenom fuer integer buggy ist. { h0 = h0/(-1); denom = -1; } else { h0 = cleardenom(h0); denom = leadcoef(h0)/lch0; } g0 = subst(g0,vvar,1/denom*vvar); g0 = lc*g0; lc = leadcoef(g0); g0= 1/lc*g0; return(g0,h0,lc); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; poly g = 3x2+5x; poly h = 4x3+2/3x; number lc = 7; improvecoef(g,h,lc); } /////////////////////////////////////////////////////////////////////////////// proc compose(list #) "USAGE: compose(f1,...,fn); f1,...,fn poly compose(I); I ideal, @* ASSUME: the ideal consists of n=ncols(I) >= 1 entries, @* where I[1],...,I[n-1] are univariate in the same variable @* but I[n] may be multivariate. RETURN: poly, the composition I[1](I[2](...I[n])) NOTE: this procedure is the inverse of decompose EXAMPLE: example compose; shows some examples SEE: decompose " { def d = basering; // Ohne dies kommt es zu Fehler, wenn auf Toplevel // ring r definiert ist. ideal I = ideal(#[1..size(#)]); int n=ncols(I); poly f=I[1]; map phisubst; ideal phiid = maxideal(1); int varnum = univariate(f); if (varnum<0) { " // the first polynomial is a constant"; return(f); } if (varnum==0 and n>1) { " // the first polynomial is not univariate"; return(f); } // Hier noch einen Test ergaenzen poly vvar = var(varnum); for(int i=2;i<=n;i++) { phiid[varnum]=I[i]; // phisubst=d,phiid; phisubst=basering,phiid; f = phisubst(f); } return(f); } example { "EXAMPLE:"; echo =2; ring r = 0,(x,y),dp; compose(x3+1,x2,y3+x); // or the input as one ideal compose(ideal(x3+1,x2,x3+y)); } /////////////////////////////////////////////////////////////////////////////// proc is_composite(poly f) "USAGE: is_composite(f); f poly RETURN: int @* 1, if f is decomposable @* 0, if f is not decomposable @* -1, if char(basering)>0 and deg(f) is divisible by char(basering) but no decomposition has been found. NOTE: The last case means that it could exist a decomposition f=g o h with char(basering)|deg(g), but this wild case cannot be decided by the algorithm.@* Some additional information will be displayed when called by the user. EXAMPLE: example is_composite; shows some examples " { int d = deg(f,nvars(basering)); int cb = char(basering); if (d<1) { " The polynomial is constant "; return(0); } if (d==1) { " The polynomial is linear "; return(0); } if (nvars(basering)==1 and d==prime(d)) { " The degree is prime."; return(0); } if (nvars(basering)>1 and univariate(f)) // and not(defined(DEGONE)) { return(1); } // else try to decompose int nc = ncols(ideal(decompose(f))); if (cb > 0) // check the not covered wild case { if ((d mod cb == 0) and (nc == 1)) { if (voice==2) { "// -- Warning: wild case, cannot decide whether the polynomial has a"; "// -- decomposition goh with deg(g) divisible by char(basering) = " + string(cb) + "."; } return(-1); } } // in the tame case, decompose gives the correct result return(nc>1); } example { "EXAMPLE:"; echo =2; ring r0 = 0,x,dp; is_composite(x4+5x2+6); // biquadratic polynomial is_composite(2x2+x+1); // prime degree // ----------------------------------------------------------------------- // polynomial ring with several variables ring R = 0,(x,y),dp; // ----------------------------------------------------------------------- // single-variable multivariate polynomials is_composite(2x+1); is_composite(2x2+x+1); // ----------------------------------------------------------------------- // prime characteristic ring r7 = 7,x,dp; is_composite(compose(ideal(x2+x,x14))); // is_composite(x14+x7); is_composite(compose(ideal(x14+x,x2))); // is_composite(x14+x2); } /////////////////////////////////////////////////////////////////////////////// proc decompose(poly f,list #) "USAGE: decompose(f); f poly decompose(f,1); f poly RETURN: poly, the input, if f is not a composite ideal, if the input is a composite NOTE: computes a full decomposition if called by the second variant EXAMPLE: example decompose; shows some examples SEE: compose " { if (!defined(IMPROVE)){ int IMPROVE = 1; } if (!defined(MINFIRST)){ int MINFIRST = 0; } int fulldecompose; if (size(#)) { // cf. ERROR-msg in randomintvec if (typeof(#[1])=="int") { fulldecompose = (#[1]==1); } } int m,iscomposed; int globalord = 1; ideal I; // --- preparatory stuff ---------------------------------------------------- // The degree is not independent of the term order int n = deg(f,1:nvars(basering)); int varnum = univariate(f); // to avoid transformation if f is univariate // if (deg(f)<=1) {return(f);} //steigt automatisch bei der for-schleife aus m = 2 if (n==prime(n) and nvars(basering)==1 // or (varnum>0 and nvars(basering)) ) {return(f);} if (varnum<0) { ERROR("// -- Error proc decompoly: the polynomial is constant."); } //-------------------------------------------------------------------------- int minfirst = MINFIRST!=0; list mdeg; intvec maxdegv,degcand; // -- switch to global order, necessary for division -- // Weiter nach oben if (typeof(attrib(basering,"global"))!="int") { globalord = 0; } else { globalord = attrib(basering,"global"); } if (!globalord) { def d = basering; list ll = ringlist(basering); ll[3] = list(list("dp",1:nvars(basering)),list("C",0)); def rneu = ring(ll); setring rneu; poly f = fetch(d,f); ideal I; } // ----------------------------------------------------------------------- map phiback; poly f0,g0,h0,vvar; number lc; ideal J; // wird erst in fulldecompose benoetigt // --- Determine the candidates for deg(g) a decreasing sequence of divisors poly lf = jet(f,n)-jet(f,n-1); //"lf = ",lf; if (size(lf)==1) // the leading homogeneous part is a monomial { degcand = divisors(gcdv(leadexp(lf))); } else { degcand = divisors(n); // Das ist absteigend } if(printlevel>0) {degcand;} // --- preparatory steps for the multivariate case ------------------------- if (varnum>0) // -- univariate polynomial { vvar = var(varnum); f0 = f; // save f } else // i.e. multivariate (varnum==0),the case varnum < 0 is excluded above { // -- find variable with maximal degree mdeg = maxdegs(f); maxdegv = mdeg[2]; varnum = maxdegv[2]; vvar = var(varnum); phiback = maxideal(1); // special case, the polynomial is a composite of a single monomial //20.6.10 if (qhweight(f)!=0) { I = decompmonom(f,vvar); } iscomposed = size(I)>1; if (iscomposed) // 3.6.11 - dies decompmonom { //I; ideal J = decompunivmonic(I[1],deg(I[1])); I[2]= subst(J[2],vvar,I[2]); I[1] = J[1]; //I; } if (!iscomposed) // -- transform into a distinguished polynomial { f0,phiback = makedistinguished(f,vvar); } } // ------ Start computation ------------------------------------------------ // -- normalize and save the leading coefficient lc = 1; //f0; //"vvar = ",vvar; // --- 11.4.11 hier auch noch gewichteten Grad beruecksichtigen ? -- if (!iscomposed) { lc = leadcoef(coeffs(f0,vvar)[deg(f0)+1,1]); } // 20.6.10 // if Z, Z_m, and f is not monic (and content !=1) // if (f0/lc*lc!=f0) if (find(charstr(basering),"integer") and not(lc==1 or lc==-1)) // 6.4.11 { ERROR("// -- Error proc decompose: Can not decompose non-monic polynomial over Z!"); } if (lc!=1){ f0 = 1/number(lc)*f0;} // --- normalize the polynomial // -- Now the input is prepared to be monic and vvar-distinguished //---------------------------------------------------------------- m = 1; // --- Special case: a multivariate can be composite of a linear polynom if (univariate(f) and nvars(basering)==1) // 11.8.09 d.h. { // --- if univariate ---------------------------------------- if(minfirst) {degcand = divisors(n,1);} // dies ist aufsteigend m = 2; // skip first entry } // if decomposed as the decomposition with a monomial // then skip the multivariate process // 20.6.10 detected as decompmonomial if (iscomposed) { degcand = 1; } if (printlevel>0 and !iscomposed) { "* Degree candidates are", degcand; } // -- check succesively for each candidate // whether f is decomposable with deg g = r for(;m1) { iscomposed = 1; break; } } // -- all candidates have be checked but f is primitive if(!iscomposed) { if (!globalord) { setring d; } // restore old ring dbprint("** not decomposable: linear / not tame / prime degree --"); return(f); } // -- the monic vvar-distinguished polynomial f0 is decomposed ------- // -- retransformation for the multivariate case --------------------- g0,h0 = I; if (!univariate(f)) { h0 = phiback(h0);} if (IMPROVE) { g0,h0,lc=improvecoef(g0,h0,lc);} // ueber switch I = h0; // -- Full decomposition: try to decompose g further ------------------ if (fulldecompose) { dbprint(newline+"** Compute a complete decomposition"); while (iscomposed) { iscomposed=0; degcand=divisors(deg(g0,1:nvars(basering))); // absteigend if (printlevel> 0) { "** Degree candidates are now: ", degcand; } for (m=2;m1; if (iscomposed) { if (IMPROVE) { g0,h0,lc=improvecoef(g0,h0,lc); } // ueber switch I = h0,I; break; } } } dbprint("** completely decomposed"+newline); } I = lc*g0,I; if (!globalord) { setring d; I = fetch(rneu,I); } return(I); } example { "EXAMPLE:"; echo =2; ring r2 = 0,(x,y),dp; decompose(((x3+2y)^6+x3+2y)^4); // complete decomposition decompose(((x3+2y)^6+x3+2y)^4,1); // ----------------------------------------------------------------------- // decompose over the integers ring rZ = integer,x,dp; decompose(compose(ideal(x3,x2+2x,x3+2)),1); // ----------------------------------------------------------------------- // prime characteristic ring r7 = 7,x,dp; decompose(compose(ideal(x2+x,x7))); // tame case // ----------------------------------------------------------------------- decompose(compose(ideal(x7+x,x2))); // wild case // ----------------------------------------------------------------------- ring ry = (0,y),x,dp; // y is now a parameter compose(x2+yx+5,x5-2yx3+x); decompose(_); // Usage of variable IMPROVE ideal J = x2+10x, 64x7-112x5+56x3-7x, 4x3-3x; decompose(compose(J),1); int IMPROVE=0; exportto(Decomp,IMPROVE); decompose(compose(J),1); } /////////////////////////////////////////////////////////////////////////////// /* ring rt =(0,t),x,dp; poly f = 36*x6+12*x4+15*x3+x2+5/2*x+(-t); decompose(f); */ // Dies gibt stets ein ideal zurueck, wenn f composite ist // gibt das polynom zurueck, wenn es primitiv ist // static proc decompmultivmonic(poly f,poly vvar,int r) "USAGE: decompmultivmonic(f,vvar,r); f,vvar poly; r int RETURN: ideal, I = ideal(g,h) if f = g o h with deg(g) = r@* poly f, if f is not a composite or char(basering) divides r ASSUME: f is monic and distinguished w.r.t. vvar, 1<=r<=deg(f) is a divisor of deg(f) and char(basering) does not divide r. EXAMPLE: example decompmultivmonic; shows an example " { def d = basering; int i,isprimitive; int m = nvars(basering); int n = deg(f); int varnum = rvar(vvar); intvec v = 1:m; // weight-vector for jet v[varnum]=0; int s = n div r; // r = deg g; s = deg h; poly f0 = f; poly h,h0,g,gp,fgp,k,t,u; ideal I,rem,phiid; list l; map phisubst; // -- entscheidet intern, abhaengig von der Anzahl der Ringvariablen, // -- ob f0 primitive ist. // " r = ",r; if (s*r!=n) { ERROR("// -- Error proc decompmultivmonic: r = "+string(r)+ " does not divide deg(f) = "+string(n)+"."); } int cb = char(basering); // oder dies in decompunivmonic if (cb>0) { if (r mod cb == 0) { if (voice == 2) { "// Warning: wild case in characteristic " + string(cb) + ". We cannot decide"; "// whether a decomposition goh with deg(g) = " + string(r)+ " exists.";""; } return(f); } } //--------------------------------------------------------------------------- for (i=1;i<=m;i++) { if (i!=varnum) {f0 = subst(f0,var(i),0);} } //" f0 = ",f0; // f0 ist nun das univariate // 24.3.09 // 11.8.09 nochmals ansehen if (r==deg(f0)) // the case of a linear multivarcomposite { dbprint("** try to decompose in linear h, deg g = "+string(r)); I = f0,vvar; // Das ist hier wichtig } else // find decomposition of the univariate f0 { I = decompunivmonic(f0,r); // dbprint(" ** monic decomposed");//" I = ";I; isprimitive=(deg(I[2])==1); if (isprimitive) {return(f);} } //---- proceed in the multivariate case //---- lift the univariate decomposition if (!univariate(f)) { dbprint("* Lift the univariate decomposition"); g,h0 = I; k = h0; gp = diff(g,vvar); // -- This is substitution ---- // t = substitute(gp,vvar,h0); phiid = maxideal(1); phiid[varnum]=h0; phisubst=basering,phiid; t = phisubst(gp); // -- substitution ende fgp = 1; i = 0; while(fgp!=0) { i++; // -- This is substitution ---- //gp = substitute(g,vvar,k); phiid[varnum]=k; phisubst=basering,phiid; gp = phisubst(g); // -- substitution ende fgp = f - gp; u = jet(fgp,i,v) - jet(fgp,i-1,v); // oder mit reduce(maxideal(x)) l = division(u,t); // die kleineren Terme abschneiden rem = l[2]; u = l[1][1,1]; // the factor if (rem!=0) { isprimitive = 1; break; } k = k + u; } h = k; I = g,h; //"decomposed as ="; //I; } if (isprimitive) { dbprint(">>> not multivariate decomposed"+newline); return(f); } else { dbprint("* Sucessfully multivariate decomposed"+newline); return(I); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),lp; poly f = 3xy4 + 2xy2 + x5y3 + x + y6; decompmultivmonic(f,y,2); ring rx = 0,x,lp; decompmultivmonic(x8,x,4); } /////////////////////////////////////////////////////////////////////////////// //static proc decompunivmonic(poly f,int r) "USAGE: decompunivmonic(f,r); f poly, r int RETURN: ideal, (g,h) such that f = goh and deg(g) = r poly f, if such a decomposition does not exist. ASSUME: f is univariate, r is a divisor of deg(f) @* and char(basering) does not divide r in case that char(basering) > 0. global order of the basering is assumed. EXAMPLE: example decompunivmonic; shows an example " { int d = deg(f); int s; // r = deg g; s = deg h; int minf,mins; int iscomposed = 1; if (!defined(MINS)) { int MINS = 0; } if (!defined(DECMETH)) { int DECMETH = 1; } int savedecmeth = DECMETH; int Zcoefs =charstr(basering)=="integer";//find(charstr(basering),"integer"); number cf; poly h,g; ideal I; matrix cc; // --- Check input and create the results for the simple cases if (deg(f)<1){return(ideal(f,var(1)));} // wird dies aufgerufen? //------------------------- int varnum = univariate(f); if (varnum==0) { "// -- The polynomial is not univariate"; return(f); } poly vvar = var(varnum); I = f,vvar; if (leadcoef(f)!=1) { "// -- Error proc decompunivmonic: the polynomial is not monic."; return(f); } /* Dies einklammern, wenn (x+1)^2 zerlegt werden sollte // aus decompose heraus, wird dies gar nicht aufgerufen! if (deg(f)==1 or deg(f)==prime(deg(f))) { "// -- The polynomial is not a composite."; return(I); } */ /* ---------------------------------------------------- */ s = d div r; if (d!=s*r) { ERROR("// -- Error proc decompunivmonic: the second argument does not divide deg f."); } int cb = char(basering); if (cb>0) { if (r mod cb ==0) { "wild case: cannot determine a decomposition"; return(I); } } // ------------------------------------------------------------------------- // The Newton iteration only works over coefficient *fields* // Therefore use in this case the Kozen-Landau method i.e. set DECMETH = 1; if (savedecmeth==0 and Zcoefs) { DECMETH=1; } // -- Start the computation ---------------------------------------------- dbprint("* STEP 1: Determine h"); dbprint(" d = deg f = " +string(n) + " f = goh"," r = deg g = "+string(r), " s = deg h = " +string(s)); int tt = timer; if(DECMETH==1) { // Kozen-Landau dbprint("* Kozen-Landau method"); // Determine ord(f); //cc = coef(f,vvar); // extract coefficents of f //print(cc); read(""); // dbprint("time: "+string(timer-tt)); tt = timer; // minf = deg(cc[1,ncols(cc)]); // 11.8.09 Doch OK. minf = -deg(f,-1:nvars(basering)); // this is local ord 15.3.10 // oder: mins = 1; if (minf) { .. dies .. } mins = (minf div r) + (minf mod r) > 0; // i.e. ceil(minf/r) if (mins==0 and MINS) { mins=1; } // omit the constant term i.e. h(0) = 0 dbprint("** min f = "+string(minf) + " | min s = "+string(mins) + " | s-mins = "+ string(s-mins)); // Dies wird wohl nicht benoetigt. // int minr= (minf div s) + ((minf mod s)>0); // ceil dbprint("** extract the coeffs "); cc = coeffs(f,vvar); dbprint("time: "+ string(timer -tt)); h = vvar^s; for (int j=1;j<=s-mins;j++) { /* timer = 1;H = Power(h,r); "Power H"; timer; timer = 1;G = h^r; "h^r"; timer; */ cf = (number(cc[d-j+1,1])-number(coeffs(h^r,vvar)[d-j+1,1])); // d-j+1,"cf =",cf, " r= ",r; // dbprint("*** "+ string(d-j+1) + " cf = "+string(cf) + " r= "+string(r)); if (Zcoefs) { if (bigint(cf) mod r != 0) { iscomposed = 0; break; }} cf = cf/r; //else { cf = cf/r; } h = h + cf*vvar^(s-j); // " h = ",h; } } else { dbprint("* von zur Gathen-method"); // "f=",f; h = reversal(newtonrroot(reversal(f,d),r,s+!MINS),s,vvar); // verdreht OK // " h = ",h; dbprint("* END STEP 1: time: "+string(timer -tt)); } DECMETH=savedecmeth; // restore the original method if (iscomposed == 0) { dbprint("** Failed in STEP 1: not decomposed with deg h = "+string(s)+newline); return(I); } // -- Step 2: try to rewrite f as a sum of powers of h --- dbprint("* STEP 2: Determine g"); poly H = h^r; int dalt = r; int ds; number c; while (d >= 0) // i.e. f!=0 { //dbprint("d = ",d); ds = d div s; if (ds * s !=d) // d mod s != 0, i.e. remaining f is a power of h { iscomposed = 0; break; } c = leadcoef(f); g = g + c*vvar^ds; H = division(H,h^(dalt - ds))[1][1,1]; // 10.3.10 // H = H / h^(dalt - ds); f = f - c*H; //"f = ",f; dalt = ds; d = deg(f); } dbprint("* END STEP 2: time: "+string(timer -tt)); if (iscomposed) { dbprint("** Sucessfully univariate decomposed with deg g = "+string(r)+newline); I = g,h; } else { dbprint("** Failed in STEP 2: not decomposed with deg g = "+string(r)+newline); } return(I); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),dp; decompunivmonic((x2+x+1)^3,3); decompunivmonic((x2+x)^3,3); decompunivmonic((y2+y+1)^3,3); } /////////////////////////////////////////////////////////////////////////////// // aus polyaux.lib proc reversal(poly f,list #) "USAGE: reversal(f); f poly reversal(f,k); f poly, k int reversal(f,k,vvar); f poly, k int, vvar poly (a ring variable) RETURN: poly, the reversal x^k*f(1/x) of the input f ASSUME: f is univariate and that k>=deg(f) @* since no negative exponents are possible in Singular @* if k0 @* @* reversal is only idempotent, @* if called twice with the deg(f) as second argument EXAMPLE: example reversal; shows an example " { int k = 0; poly vvar = var(1); if (size(#)) { k = #[1] - deg(f) ; if (k<0) { k=0; } if (size(#)==2){ // check whether second optional argument vvar = var(univariate(#[2])); // is a ring variable } } int varnum = univariate(f); if (varnum==0) { ERROR("// -- the input is not univariate."); } if (varnum<0) { // the polynomial is constant return(f*vvar^k); } def d = basering; list l = ringlist(d); list varl = l[2]; varl = insert(varl,"@z",size(varl)); l[2] = varl; def rnew = ring(l); setring rnew; poly f = fetch(d,f); f = subst(homog(f,@z),var(varnum),1,@z,var(varnum))*var(varnum)^k; setring d; f = fetch(rnew,f); return(f); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; poly f = x3+2x+5; reversal(f); // the same as reversal(f,3); reversal(f,5); poly g = x3+2x; reversal(g); // Not idempotent reversal(reversal(g)); // idempotent reversal(reversal(g,deg(g)),deg(g)); // or for short // reversal(reversal(g),deg(g)); } /////////////////////////////////////////////////////////////////////////////// // aus polyaux.lib proc newtonrroot(poly f,int r,int l) "USAGE: newtonrroot(f,r,l); f poly; r int; l int RETURN: poly h, the solution of h^r = f modulo vvar^l ASSUME: f(0) = 1 NOTE: this uses p-adic Newton iteration. It is the adaption of Algorithm 9.22@* of von zur Gathen & Gerhard p. 264 for the special case: phi = Y^r - f EXAMPLE: example newtonrroot; shows some examples " { // phi = Y^r - f poly g = 1; // start polynomial poly s = 1/number(r); // initial solution int i = 2; //"s initial",s; while(i 0, then there exist polynomials of degree d>=p, e.g. @math{(p-1)x^p y + xy^p}, that cannot be transformed to a vvar-distinguished polynomial. @* In this case, *p random trials will be made and the proc may leave with an ERROR message. EXAMPLE: example makedistinguished; shows some examples " { def d = basering; // eigentlich ueberfluessig // wg Bug mit example part map phi; // erforderlich ideal Db= maxideal(1); int n,b = nvars(basering),1; intvec v= 0:n; intvec w =v; int varnum = rvar(vvar); w[varnum]=1; // weight vector for deg poly g = f; int degg = deg(g); int count = 1; // limit the number of trials in char(p) > 0 //int count =2*char(basering); while(deg(g,w)!=degg and (count-2*char(basering))) // do a transformation { v = randomintvec(n,-b,b,1); // n non-zero entries v[varnum] = 0; phi = d,ideal(matrix(maxideal(1),n,1) + var(varnum)*v); // transformation; g = phi(f); b++; // increase the range for the random values // count--; count++; } if (deg(g,w)!=degg) { ERROR("it could not be transform to a "+string(vvar)+"-distinguished polynomial."); } Db = ideal(matrix(maxideal(1),n,1) - var(varnum)*v); // back transformation return(g,Db); } example { "EXAMPLE:"; int randval = system("--random"); // store initial value system("--random",0815); echo = 2; ring r = 0,(x,y),dp; poly g; map phi; // ----------------------------------------------------------------------- // Example 1: poly f = 3xy4 + 2xy2 + x5y3 + x + y6; // degree 8 // make the polynomial y-distinguished g, phi = makedistinguished(f,y); g; phi; // to reverse the transformation apply the map f == phi(g); // ----------------------------------------------------------------------- // Example 2: // The following polynomial is already x-distinguished f = x6+y4+xy; g,phi = makedistinguished(f,x); g; // f is left unchanged phi; // the transformation is the identity. echo = 1; system("--random",randval); // reset random generator // ----------------------------------------------------------------------- echo = 2; // Example 3: // polynomials which cannot be transformed // If p=char(basering)>0, then (p-1)*x^p*y + x*y^p factorizes completely // in linear factors, since (p-1)*x^p+x equiv 0 on F_p. Hence, // such polynomials cannot be transformed to a distinguished polynomial. ring r3 = 3,(x,y),dp; makedistinguished(2x3y+xy3,y); } /////////////////////////////////////////////////////////////////////////////// static proc maxdegs(poly f) "USAGE: maxdegs(f); f poly RETURN: list of two intvecs _[1] intvec: degree for variable i, 1<=i<=nvars(basering) @* _[2] intvec: max of _[1], index of first variable with this max degree EXAMPLE: example maxdegs; shows an example " { int i,n; intvec degs,maxdeg; list l; n = nvars(basering); for (i=1;i<=n;i++) { degs[i] = nrows(coeffs(f,var(i)))-1; if (degs[i] > maxdeg) { maxdeg[1] = degs[i]; maxdeg[2] = i; } } return(list(degs,maxdeg)); } example { "EXAMPLE:"; echo =2; ring r = 0,(x,y,z),lp; poly f = 3xy4 + 2xy2 + x5y3 + xz6 + y6; maxdegs(f); } /////////////////////////////////////////////////////////////////////////////// proc chebyshev(int n,list #) "USAGE: chebyshev(n); n int, n >= 0 chebyshev(n,c); n int, n >= 0, c number, c!=0 RETURN: poly, the [monic] nth Chebyshev polynomial of the first kind. @* The polynomials are defined in the first variable, say x, of the basering. NOTE: @texinfo The (generalized) Chebyshev polynomials of the first kind can be defined by the recursion: @tex $C_0 = c,\ C_1 = x,\ C_n = 2/c\cdot x\cdot C_{n-1}-C_{n-2},\ n \geq 2,c\neq 0$. @end tex @end texinfo These polynomials commute by composition: @math{C_m \circ C_n = C_n\circ C_m}. @* For c=1, we obtain the standard (non monic) Chebyshev polynomials @math{T_n} which satisfy @math{T_n(x) = \cos(n \cdot \arccos(x))}. @* For c=2 (default), we obtain the monic Chebyshev polynomials @math{P_n} which satisfy the relation @math{P_n(x+ 1/x) = x^n+ 1/x^n}. @* By default the monic Chebyshev polynomials are returned: @math{P_n =}@code{chebyshev(n)} and @math{T_n=}@code{chebyshev(n,1)}.@* It holds @math{P_n(x) = 2\cdot T_n(x/2)} and more generally @math{C_n(c\cdot x) = c\cdot T_n(x)} @* That is @code{subst(chebyshev(n,c),var(1),c*var(1))= c*chebyshev(n,1)}. If @code{char(basering) = 2}, then @math{C_0 = 1, C_1 = x, C_2 = 1, C_3 = x}, and so on. EXAMPLE: example chebyshev; shows some examples " { number startv = 2; if (size(#)){ startv = #[1]; } if (startv == 0) { startv = 1; } poly f0,f1 = startv,var(1); poly fneu,falt = f1,f0; poly fh; if (n<=0) {return(f0);} if (n==1) {return(f1);} for(int i=2;i<=n;i++) { fh = 2/startv*var(1)*fneu - falt; // fh = 2*var(1)*fneu - falt; falt = fneu; fneu = fh; } return(fh); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,lp; // The monic Chebyshev polynomials chebyshev(0); chebyshev(1); chebyshev(2); chebyshev(3); // These polynomials commute compose(chebyshev(2),chebyshev(6)) == compose(chebyshev(6),chebyshev(2)); // The standard Chebyshev polynomials chebyshev(0,1); chebyshev(1,1); chebyshev(2,1); chebyshev(3,1); // ----------------------------------------------------------------------- // The relation for the various Chebyshev polynomials 5*chebyshev(3,1)==subst(chebyshev(3,5),x,5x); // ----------------------------------------------------------------------- // char 2 case ring r2 = 2,x,dp; chebyshev(2); chebyshev(3); } /////////////////////////////////////////////////////////////////////////////// /* // Examples for decomp.lib ring r02 = 0,(x,y),dp; decompose(compose(x6,chebyshev(4),x2+y3+x5y7),1); int MINS = 0; decompose((xy+1)^7); //_[1]=x7 //_[2]=xy+1 decompose((x2y3+1)^7); //_[1]=y7 //_[2]=x2y3+1 MINS = 1; ring r01 = 0,x,dp; decompose((x+1)^7); //x7+7x6+21x5+35x4+35x3+21x2+7x+1 decompunivmonic((x+1)^7,7); //_[1]=x7 //_[2]=x+1 int MINS =1; decompunivmonic((x+1)^7,7); //_[1]=x7+7x6+21x5+35x4+35x3+21x2+7x+1 //_[2]=x // -- Example ------------- // Comparision Kozen-Landau vs. von zur Gathen ring r02 = 0,(x,y),dp; // printlevel = 5; decompopts("reset"); poly F = compose(x6,chebyshev(4)+3,8x2+y3+7x5y7+2); deg(F); timer = 1;decompose(F,1);timer; int MINS = 1; timer = 1;decompose(F,1);timer; int IMPROVE =0; timer = 1;decompose(F,1);timer; decompopts("reset"); int DECMETH = 0; // von zur Gathen timer = 1;decompose(F,1);timer; decompopts("reset"); // -- Example ------------- ring rZ10 = (integer,10),x,dp; chebyshev(2); //x2+8 chebyshev(3); //x3+7x compose(chebyshev(2),chebyshev(3)); //x6+4x4+9x2+8 decompose(_); int MINS =1; decompose(compose(chebyshev(2),chebyshev(3))); compose(_); decompopts("reset"); // -- Example ------------- ring rT =(0,y),x,dp; compose(x2,x3+y,(y+1)*x2); //(y6+6y5+15y4+20y3+15y2+6y+1)*x12+(2y4+6y3+6y2+2y)*x6+(y2) decompose(_,1); //_[1]=(y6+6y5+15y4+20y3+15y2+6y+1)*x2 //_[2]=x3+(y)/(y3+3y2+3y+1) //_[3]=x2 int MINS =1; compose(x2,x3+y,(y+1)*x2); //(y6+6y5+15y4+20y3+15y2+6y+1)*x12+(2y4+6y3+6y2+2y)*x6+(y2) decompose(_,1); //_[1]=(y6+6y5+15y4+20y3+15y2+6y+1)*x2+(2y4+6y3+6y2+2y)*x+(y2) //_[2]=x3 //_[3]=x2 //ring rt =(0,t),x,dp; //compose(x2+tx+5,x5-2tx3+x); //x10+(-4t)*x8+(4t2+2)*x6+(t)*x5+(-4t)*x4+(-2t2)*x3+x2+(t)*x+5 decompose(_); //_[1]=x2+(-1/4t2+5) //_[2]=x5+(-2t)*x3+x+(1/2t) int IMPROVE = 1; compose(x2+tx+5,x5-2tx3+x); //x10+(-4t)*x8+(4t2+2)*x6+(t)*x5+(-4t)*x4+(-2t2)*x3+x2+(t)*x+5 decompose(_); //_[1]=x2+(-1/4t2+5) //_[2]=x5+(-2t)*x3+x+(1/2t) int IMPROVE = 0; compose(x2+tx+5,x5-2tx3+x); //x10+(-4t)*x8+(4t2+2)*x6+(t)*x5+(-4t)*x4+(-2t2)*x3+x2+(t)*x+5 decompose(_); //_[1]=x2+(-1/4t2+5) //_[2]=x5+(-2t)*x3+x+(1/2t) int MINS = 1; compose(x2+tx+5,x5-2tx3+x); //x10+(-4t)*x8+(4t2+2)*x6+(t)*x5+(-4t)*x4+(-2t2)*x3+x2+(t)*x+5 decompose(_); //_[1]=x2+(t)*x+5 //_[2]=x5+(-2t)*x3+x */ /////////////////////////////////////////////////////////////////////////////// // --- End of decomp.lib --------------------------------------------------- // /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/deflation.lib000066400000000000000000000671161266270727000206170ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version deflation.lib 4.0.2.0 30.03.2015 "; // $Id: b90f2975b975dd9ceb012aefb8b5c3d24f5cdfd7 $ category="Numerical Analysis"; info=" LIBRARY: deflation.lib Various deflation methods AUTHOR: Adrian Koch (kocha at rhrk.uni-kl.de) REFERENCES: - Jonathan Hauenstein, Bernard Mourrain, Agnes Szanto; Certifying isolated singular points and their multiplicity structure - Jonathan Hauenstein, Charles Wampler; Isosingular Sets and Deflation; published in Foundations of Computational Mathematics, Volume 13, Issue 3, 2013, on pages 371-403 - Anton Leykin, Jan Verschelde, Ailing Zhao; Newtons method with deflation for isolated singularities of polynomial systems; published in Theoretical Computer Science, Volume 359, 2006, on pages 111-122 PROCEDURES: deflateHMS(F,ro,co,[..]); deflation algorithm by Hauenstein, Mourrain, and Szanto deflateHW1(F,ro,co); isosingular deflation: uses determinants - by Hauenstein and Wampler deflateHW2(F,rk,[..]); isosingular deflation: strong, intrinsic - by Hauenstein and Wampler deflateLVZ(F,rk,[..]); deflation algorithm by Leykin, Verschelde, and Zhao KEYWORDS: deflation "; LIB "linalg.lib"; LIB "primdec.lib"; ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////// Method C ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// static proc getLambda(matrix A, matrix B) { //computes the composite matrix whose columns we use to augment the original //polynomial system matrix C=-adjoint(A)*B; int c=ncols(C); matrix L=transpose(C); L=concat(L,diag(1,c)); return(transpose(L)); } static proc process_choice_for_i(int a, int c) { //a contains the choice, c is the maximum element of the set i = 1,...,c //if a is -1, returns random value between 1 and c //if a is 0, returns c //if a > c, returns c //if 1< a = 1) { return(a); } } if(a > c) { return(c); } ERROR("Input (to control the choice of which element of i to use) invalid." + " Must be an integer >= -1"); } static proc append_var_list(int nv, list RL, list VN) { //nv the number of new variables, RL the ringlist, VN the new variable names and, //possibly, the no brackets option int nb; if(VN[1] == "no parentheses") { nb=1; VN=delete(VN,1); } int i; list vl; if(size(VN) < nv) { string st=VN[1]; if(nb == 0) { for(i=1; i<=nv; i++) { vl=vl+list(st+"("+string(i)+")"); } } if(nb == 1) { for(i=1; i<=nv; i++) { vl=vl+list(st+string(i)); } } } if(size(VN) >= nv) { for(i=1; i<=nv; i++) { vl=vl+list(VN[i]); } } RL[2]=RL[2]+vl; return(RL); } static proc remove_constants(ideal H); { //remove contants and scalar multiples from H H=1,H; H=simplify(H,2+4+8); H=H[2..size(H)]; return(H); } static proc exhaust_options(ideal F, int a, matrix la, matrix J) { int i; int c=ncols(la); matrix N[nrows(la)][1]; ideal H; int sF=size(F); for(i=1; i<=c; i++) { if(i == a) { //we already checked that one i++; continue; } N=submat(la,1..nrows(la),i); H=ideal(J*N); H=remove_constants(H); F=F,H; F=simplify(F,14); if(size(F) > sF){ return(F); } } print("Deflation unsuccessful: return value is the (possibly simplified) original system."); return(F); } proc deflateHMS(ideal F, intvec ro, intvec co, list #) "USAGE: deflateHMS(F, ro, co [, m [, S ]]); ideal F: system of polynomial equations intvecs ro and co: contain the row (respectively column) indices of a full rank submatrix of the Jacobian of F at the point at which you want to deflate F (if the rank is 0, make ro and co equal to the intvec containing only 0) integer m: parameter influencing a choice made in the algorithm string (or list of strings) S: parameter(s) influencing the output RETURN: ring: a ring containing the ideal AUGF, representing the augmented system REMARK: This deflation method augments the given polynomial system to a system which is defined in the original ring. However, if the rank is 0, we add additional variables representing the entries of a random column vector L of length nv, where nv is the number of variables of the original polynomial ring. The system F is then augmented by the entries of J*L, where J is the Jacobian of F. We use these additional variables, instead of just choosing some random numbers, so that the user would have full control over the type of random numbers: one can just substitute the variables later on. For more information about this deflation method see section 3 of Jonathan Hauenstein, Bernard Mourrain, Agnes Szanto; Certifying isolated singular points and their multiplicity structure. We use the integer c as defined in that paper. During the algorithm, we have to choose a subset of {1,...,c}, which is then used to generate the augmentation of F. In this implementation, we only use subsets containing exactly one element. The choice can be controlled by the optional argument m. NOTE: The optional argument m controls which element of {1,...,c} will be chosen during the procedure: if m is -1, the procedure chooses a random value between 1 and c if m is 0, the procedure chooses c if m > c, the procedure chooses c if 1< m 0) { chi=#[1]; } if(size(#) <= 1) { list VN="L"; } if(size(#) == 2) { list VN=#[2]; } if(size(#) > 2) { list VN=delete(#,1); } F=simplify(F,2+4+8); matrix J=jacob(F); int nv=nvars(basering); def br=basering; list RL=ringlist(br); if( ro[1]*co[1] == 0 ) { //ie if the rank is 0 //then we need a random vector //so we construct a ring with additional variables, such that the random values //can be chosen later on and substituted for these variables RL=append_var_list(nv,RL,VN); def bigR=ring(RL); setring bigR; matrix N[nv][1]; int i; for(i=1; i<=nv; i++) { N[i,1]=var(nv+i); } matrix J=imap(br,J); J=J*N; ideal AUGF=imap(br,F); AUGF=AUGF,ideal(J); //int CHNG=nv; export(AUGF); //export(CHNG); return(bigR); } else { intvec cc=complementary_ro_co_vecs(co,ncols(J)); matrix A=submat(J,ro,co); matrix B=submat(J,ro,cc); matrix la=getLambda(A,B); int i=process_choice_for_i(chi,ncols(la)); matrix N[nrows(la)][1]=submat(la,1..nrows(la),i); ideal H=ideal(J*N); H=remove_constants(H); int sF=size(F); F=F,H; F=simplify(F,14); //gets rid of zero generators and copies of earlier listed generators //and polys which are scalar multiples of earlier listed polys if(size(F) == sF) { //we did not add a polynomial which is not 0 and not a scalar multiple //of an earlier listed polynomial F=exhaust_options(F,i,la,J); } def outR=ring(RL); setring outR; ideal AUGF=imap(br,F); //int CHNG=0; export(AUGF); //export(CHNG); return(outR); } } example { "EXAMPLE:"; echo=2; ring ojika3=0,(x,y,z),dp; ideal F=x+y+z-1, 2x3+5y2-10z+5z3+5, 2x+2y+z2-1; intvec ro=1,2; intvec co=1,3; def R1=deflateHMS(F,ro,co); R1; setring R1; AUGF; ring cbms1=0,(x,y,z),dp; ideal F=x3-yz, y3-xz, z3-xy; ro=0; co=0; int m=-1; def R2=deflateHMS(F,ro,co,m,"L"); R2; setring R2; AUGF; } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////// Method B ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// static proc complementary_ro_co_vecs(intvec v, int m) { intvec c; intvec b; int j; b[m]=0; int i; for(i=1; i<=size(v); i++) { b[v[i]]=1; } for(i=1; i<=m; i++) { if(b[i] == 0) { j++; c[j]=i; } } return(c); } static proc certain_submats(matrix M, intvec ro, intvec co) { //ro and co the row ,respectively column, indices of the matrix we want to have as //part of the returned submatrices list S; intvec rn, cn;//the row and column indices used to obtain the next submatrix intvec rc=complementary_ro_co_vecs(ro,nrows(M)); intvec cc=complementary_ro_co_vecs(co,ncols(M)); int sr=size(ro)+1; int sc=size(co)+1; int i,j; for(i=1; i<=size(rc); i++) { rn=ro; rn[sr]=rc[i]; for(j=1; j<=size(cc); j++) { cn=co; cn[sc]=cc[j]; S = S + list(submat(M,rn,cn)); } } return(S); } static proc det_augment(ideal F, intvec ro, intvec co) { //returns the polynomials with which we want to augment F //namely the determinants of all r+1 x r+1 submatrices of the Jacobian of F //containing the r x r submatrix specified by ro and co matrix J=jacob(F); if(ro[1]*co[1] == 0) { //meaning the rank is 0 //then return the 1x1 minors, that is the entries of J return(ideal(J)); } list S=certain_submats(J,ro,co); ideal A=det(S[1]); int i; for(i=2; i<=size(S); i++) { A=A,det(S[i]); } return(A); } proc deflateHW1(ideal F, intvec ro, intvec co) "USAGE: deflateHW1(F, ro, co); ideal F: system of polynomial equations intvecs ro and co: contain the row (respectively column) indices of a full rank submatrix of the Jacobian of F at the point at which you want to deflate F (if the rank is 0, make ro and co equal to the intvec containing only 0) RETURN: ideal: an augmented polynomial system ASSUME: ro and co have the same number of elements, say rk. REMARK: This deflation method adds to F the determinants of the (rk+1) x (rk+1) submatrices of the Jacobian of F containing the rows and columns specified in ro and co EXAMPLE: example deflateHW1; shows an example " { //does one iteration of deflation, then returns the augmented system //ro and co the row, respectively column, indices of the matrix we want to have as //part of the submatrices we use to augment F ideal A=det_augment(F,ro,co); F=F,A; F=simplify(F,2+4+8);//erases the zeroes, copies, scalar multiples return(F); } example { "EXAMPLE:"; echo=2; ring ojika3=0,(x,y,z),dp; ideal F=x+y+z-1, 2x3+5y2-10z+5z3+5, 2x+2y+z2-1; intvec ro=1,2;//number of elements is rk=2 intvec co=1,3; ideal AUGF=deflateHW1(F,ro,co);//considers 3x3 submatrices of the Jacobian J of F, //that is J itself AUGF; //the only polynomial we added is the determinant of J det(jacob(F)); } ////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////// strong intrinsic deflation ///////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// static proc makeB(int N, int d) { //fills an NxN matrix with newly added variables //column by column, from left to right, each column from top to bottom matrix B[N][N]; int i,j; for(j=1; j<=N; j++) { for(i=1; i<=N; i++) { B[i,j]=var(N+(N-d)*d+(j-1)*N+i); } } return(B); } static proc makeIX(int N, int d) { //constructs the composite matrix which has the identity matrix on top and //Xi on the bottom. Xi is filled with the newly added variables; column by column, //from left to right, each column from top to bottom matrix I=diag(1,d); matrix X[N-d][d]; int i,j; for(j=1; j<=d; j++) { for(i=1; i<=N-d; i++) { X[i,j]=var(N+(j-1)*(N-d)+i); } } I=concat(I,transpose(X)); I=transpose(I); return(I); } proc deflateHW2(ideal F, int rk, list #) "USAGE: deflateHW2(F, rk [, SXi, SB]); ideal F: system of polynomial equations int rk: the rank of the Jacobian of F at the point at which you want to deflate strings (or lists of strings) SXi, SB: parameters influencing the output RETURN: ring: a ring containing the ideal AUGF, representing the augmented system REMARK: This deflation method augments the given polynomial system to a system which is defined in the original ring if rk = 0. If rk > 0, the augmented system is defined in an extended ring and a random matrix B is used in the computations. More precisely: - rk*(nv-rk) new variables are added to the original ring - the random matrix B has dimensions nv*nv NOTE: If rk = 0: the returned ring R is the same as the basering. If rk > 0: the returned ring R is the basering plus additional variables. More precisely, we add rk*(nv-rk) + nv*nv variables, where nv is the number of variables in the basering. They have the following purpose: - the first rk*(nv-rk) correspond to the new variables of the extended ring ( lets say that these variables are called Xi_1,...,Xi_(rk*(nv-rk)) ) - the last nv*nv variables correspond to the entries of the random matrix B This way, you have more options: you can substitute the variables corresponding to the entries of B by random numbers you generated yourself. With the optional arguments you can influence the names that will be given to the additional variables. If you give any optional arguments, you should give exactly two of them. The first controls the names of the Xi_j, the second the names of the entries of B. If an optional argument is of type string, say \"X\", then the variable names controlled by this argument will be X(1),...,X(# of variables). If an optional argument is given as a list of strings, it should be of the following form: [\"no parentheses\",] s_1 [,...,s_n]. If the list consists of two elements \"no parentheses\" and \"X\", the variables are named as above, but without the parentheses. If the list contains enough strings, that is if you specify strings s_1,...,s_n with n=rk*(nv-rk) or n=nv*nv (depending on which of the variable names are being controlled), then exactly these strings will be used as the names of the variables. (If you specify less than n names, only s_1 is used. If you specify more than n, only s_1,...,s_n are used.) The procedure does not check for naming conflicts prior to defining the extended ring, so please make sure that there are none. If no optional arguments are given, the new variables are named X(1),...,X(rk+1), the entries of B are named B(1),...,B(nv*(rk+1)). As for the order in which B is filled with variables: - B is filled with variables column by column, from left to right, filling the columns from top to bottom EXAMPLE: example deflateHW2; shows an example " { list vnb="B"; list vnxi="X"; if(size(#) > 0) { if(size(#) > 2) { ERROR("Too many optional arguments (there should be exactly two, if any)."); } if(size(#) == 1) { ERROR("Too few optional arguments (there should be exactly two, if any)."); } if(typeof(#[1]) != typeof(#[2])) { //ERROR("The optional arguments must be of the same type."); } vnb=#[2]; vnxi=#[1]; } matrix J=jacob(F); int N=ncols(J);//number of variables int d=N-rk; int nv=nvars(basering); def br=basering; list RL=ringlist(br); if( rk > 0 ) { RL=append_var_list((N-d)*d,RL,vnxi); RL=append_var_list(N*N,RL,vnb); def bigR=ring(RL); setring bigR; matrix J=imap(br,J); matrix B=makeB(N,d); matrix IX=makeIX(N,d); J=J*B*IX; ideal AUGF=imap(br,F); AUGF=AUGF,ideal(J); AUGF=simplify(AUGF,2+4+8);//remove zeroes, copies, scalar multiples export(AUGF); return(bigR); } if( rk == 0 ) { def outR=ring(RL); setring outR; matrix J=imap(br,J); ideal AUGF=imap(br,F); AUGF=AUGF,ideal(J); AUGF=simplify(AUGF,2+4+8); export(AUGF); return(outR); } } example { "EXAMPLE:"; echo=2; ring ojika3=0,(x,y,z),dp; ideal F=x+y+z-1, 2x3+5y2-10z+5z3+5, 2x+2y+z2-1; int rk=2; list L="X",list("no parentheses", "B"); def R=deflateHW2(F,rk,L); R; setring R; AUGF; } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////// Method A ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// proc deflateLVZ(ideal F, int rk, list #) "USAGE: deflateLVZ(F, rk [, Sl, SB, Sh]); ideal F: system of polynomial equations int rk: the rank of the Jacobian of F at the point at which you want to deflate strings (or lists of strings) Sl, SB, Sh: parameters influencing the output RETURN: ring: a ring containing the ideal AUGF, representing the augmented system REMARK: This deflation method augments the given polynomial system to a system defined in an extended polynomial ring (new variables: lambda_i), and uses two random elements in its computations: a matrix B and a (column) vector h. More precisely: - the original polynomial ring is extended by rk+1 variables - the random matrix B has dimensions nv x rk+1, where nv is the number of variables in the original ring - the random vector h has length rk+1 NOTE: The returned ring R is the same as the basering plus additional variables. More precisely, we add (nv+2)*(rk+1) variables, where nv is the number of variables in the basering. They have the following purpose: - the first rk+1 correspond to the variables lambda_i of the extended ring - the next nv*(rk+1) variables correspond to the entries of the random matrix B - the last rk+1 variables correspond to the entries of the random vector h This way, the user has more options: he can substitute the variables corresponding to the random elements by random numbers he generated himself. With the optional arguments you can influence the names that will be given to the additional variables. If you give any optional arguments, you should give exactly three of them. The first controls the names of the lambda_i, the second the names of the entries of B, and the third controls the names given to the entries of h. If an optional argument is of type string, say \"X\", then the variable names controlled by this argument will be X(1),...,X(# of variables). If an optional argument is given as a list of strings, it should be of the following form: [\"no parentheses\",] s_1 [,...,s_n]. If the list consists of two elements \"no parentheses\" and \"X\", the variables are named as above, but without the parentheses. If the list contains enough strings, that is if you specify strings s_1,...,s_n with n=rk+1 or n=nv*(rk+1) (depending on which of the variable names are being controlled), then exactly these strings will be used as the names of the variables. (If you specify less than n names, only s_1 is used. If you specify more than n, only s_1,...,s_n are used.) The procedure does not check for naming conflicts prior to defining the extended ring, so please make sure that there are none. If no optional arguments are given, the new variables are named l(1),...,l(rk+1), the entries of B are named B(1),...,B(nv*(rk+1)), and the entries of h are named h(1),...,h(rk+1). As for the order in which B and h are filled with variables: - B is filled with variables column by column, from left to right, filling the columns from top to bottom - the column vector h is filled from top to bottom EXAMPLE: example deflateLVZ; shows an example " { if(size(#) != 3) { if(size(#) != 0) { ERROR("If any optional arguments are given, there have to be exactly three of them."); } list Vl="l"; list VB="B"; list Vh="h"; } if(size(#) == 3) { list Vl=#[1]; list VB=#[2]; list Vh=#[3]; } matrix J=jacob(F); def br=basering; list RL=ringlist(basering); int nv=nvars(basering); RL=append_var_list(rk+1,RL,Vl); RL=append_var_list( nv*(rk+1) ,RL,VB); RL=append_var_list(rk+1,RL,Vh); def outr=ring(RL); setring outr; matrix J=imap(br,J); ideal F=imap(br,F); matrix B[nv][rk+1]; int ii,jj; for(jj=1; jj<=rk+1; jj++) { for(ii=1; ii<=nv; ii++) { B[ii,jj]=var( nv+rk+1 + (jj - 1)*(rk+1) + ii ); } } matrix la[rk+1][1]; for(ii=1; ii<=rk+1; ii++) { la[ii,1]=var( nv + ii ); } matrix h[rk+1][1]; for(ii=1; ii<=rk+1; ii++) { h[ii,1]=var( nv+rk+1 + nv*(rk+1) + ii ); } matrix C=J*B; ideal G=ideal(C*la); matrix H=transpose(la)*h; kill h; poly h=H[1,1]-1; ideal AUGF=F,G,h; export(AUGF); return(outr); } example { "EXAMPLE:"; echo=2; ring ojika3=0,(x,y,z),dp; ideal F=x+y+z-1, 2x3+5y2-10z+5z3+5, 2x+2y+z2-1; int rk=2; list L="l",list("no parentheses", "B"), list("ha","he","ho"); def R=deflateLVZ(F,rk,L); R; setring R; AUGF; } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////// Examples ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// //These are some benchmark-examples. You can find most of them in the literature listed //under references. //Every examples listed consists of a polynomial system of equations and one ore two //points at which we want to deflate the system. The examples which are given //exactly can be handled with Singular (that is, symbolically). However, the purpose of //the procedures in this library is to use information which was computed numerically //- such as the (numerical) rank of the Jacobian of the polynomial system at a certain //point - //and then do symbolical manipulations of the polynomial system in order to deflate it. //For the Cyclic-9 problem, for example, you will probably want to compute the necessary //information numerically. /* ring cbms1=0,(x,y,z),dp; list p=0,0,0; ideal F=x3-yz, y3-xz, z3-xy; ring cbms2=0,(x,y,z),dp; list p=0,0,0; ideal F=x3-3x2y+3xy2-y3-z2, z3-3z2x+3zx2-x3-y2, y3-3y2z+3yz2-z3-x2; ring mth191=0,(x,y,z),dp; list p=0,1,0; ideal F=x3+y2+z2-1, x2+y3+z2-1, x2+y2+z3-1; ring decker2=0,(x,y),dp; list p=0,0; ideal F=x+y3, x2y-y4; ring ojika2=0,(x,y,z),dp; list p=0,0,1; list q=1,0,0; ideal F=x2+y+z-1, x+y2+z-1, x+y+z2-1; ring ojika3=0,(x,y,z),dp; list p=0,0,1; list q=poly(-5)/2,poly(5)/2,1; ideal F=x+y+z-1, 2x3+5y2-10z+5z3+5, 2x+2y+z2-1; ring caprasse=(0,a),(x,y,z,w),dp; minpoly=a2+3; list p=2,-a,2,a; ideal F=-x3z + 4xy2z + 4x2yw + 2y3w + 4x2 - 10y2 + 4xz - 10yw + 2, -xz3 + 4yz2w + 4xzw2 + 2yw3 + 4xz + 4z2 - 10yw - 10w2 + 2, y2z + 2xyw - 2x - z, 2yzw + xw2 - x - 2z; ring KSS=0,x(1..5),dp; int i; ideal F; poly f; poly g=sum(maxideal(1)); for(i=1; i<=5; i++) { f=var(i)^2 + g - 2*var(i) - 4; F=F,f; } F=simplify(F,2); list p=1,1,1,1,1; ring C9=(0,I),(x0,x1,x2,x3,x4,x5,x6,x7,x8),dp; ideal F=x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8, x0*x1 + x1*x2 + x2*x3 + x3*x4 + x4*x5 + x5*x6 + x6*x7 + x7*x8 + x8*x0, x0*x1*x2 + x1*x2*x3 + x2*x3*x4 + x3*x4*x5 + x4*x5*x6 + x5*x6*x7 + x6*x7*x8 + x7*x8*x0 + x8*x0*x1, x0*x1*x2*x3 + x1*x2*x3*x4 + x2*x3*x4*x5 + x3*x4*x5*x6 + x4*x5*x6*x7 + x5*x6*x7*x8 + x6*x7*x8*x0 + x7*x8*x0*x1 + x8*x0*x1*x2, x0*x1*x2*x3*x4 + x1*x2*x3*x4*x5 + x2*x3*x4*x5*x6 + x3*x4*x5*x6*x7 + x4*x5*x6*x7*x8 + x5*x6*x7*x8*x0 + x6*x7*x8*x0*x1 + x7*x8*x0*x1*x2 + x8*x0*x1*x2*x3, x0*x1*x2*x3*x4*x5 + x1*x2*x3*x4*x5*x6 + x2*x3*x4*x5*x6*x7 + x3*x4*x5*x6*x7*x8 + x4*x5*x6*x7*x8*x0 + x5*x6*x7*x8*x0*x1 + x6*x7*x8*x0*x1*x2 + x7*x8*x0*x1*x2*x3 + x8*x0*x1*x2*x3*x4, x0*x1*x2*x3*x4*x5*x6 + x1*x2*x3*x4*x5*x6*x7 + x2*x3*x4*x5*x6*x7*x8 + x3*x4*x5*x6*x7*x8*x0 + x4*x5*x6*x7*x8*x0*x1 + x5*x6*x7*x8*x0*x1*x2 + x6*x7*x8*x0*x1*x2*x3 + x7*x8*x0*x1*x2*x3*x4 + x8*x0*x1*x2*x3*x4*x5, x0*x1*x2*x3*x4*x5*x6*x7 + x1*x2*x3*x4*x5*x6*x7*x8 + x2*x3*x4*x5*x6*x7*x8*x0 + x3*x4*x5*x6*x7*x8*x0*x1 + x4*x5*x6*x7*x8*x0*x1*x2 + x5*x6*x7*x8*x0*x1*x2*x3 + x6*x7*x8*x0*x1*x2*x3*x4 + x7*x8*x0*x1*x2*x3*x4*x5 + x8*x0*x1*x2*x3*x4*x5*x6, x0*x1*x2*x3*x4*x5*x6*x7*x8 - 1; poly z0= poly(-9396926) - 3520201*I; z0=z0/10000000; poly z1=poly(-24601472) - 8954204*I; z1=z1/10000000; poly z2= poly(-3589306) - 1306401*I; z2=z2/10000000; list p=z0,z1,z2,z0,-z2,-z1,z0,-z2,-z1; ring DZ1=0,(x,y,z,w),dp; list p=0,0,0,0; ideal F=x4-yzw, y4-xzw, z4-xyw, w4-xyz; ring DZ2=0,(x,y,z),dp; list p=0,0,-1; ideal F=x4, x2y+y4, z+z2-7x3-8x2; */ singular-4.0.3+ds/Singular/LIB/deform.lib000066400000000000000000000766121266270727000201270ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version deform.lib 4.0.0.0 Jun_2013 "; // $Id: ee339cdeaa126e4730b57eed609001d8214797a8 $ category="Singularities"; info=" LIBRARY: deform.lib Miniversal Deformation of Singularities and Modules AUTHOR: Bernd Martin, email: martin@math.tu-cottbus.de PROCEDURES: versal(Fo[,d,any]) miniversal deformation of isolated singularity Fo mod_versal(Mo,I,[,d,any]) miniversal deformation of module Mo modulo ideal I lift_kbase(N,M); lifting N into standard kbase of M lift_rel_kb(N,M[,kbM,p]) relative lifting N into a kbase of M "; LIB "inout.lib"; LIB "general.lib"; LIB "matrix.lib"; LIB "homolog.lib"; LIB "sing.lib"; /////////////////////////////////////////////////////////////////////////////// proc versal (ideal Fo,list #) "USAGE: versal(Fo[,d,any]); Fo=ideal, d=int, any=list COMPUTE: miniversal deformation of Fo up to degree d (default d=100), RETURN: list L of 4 rings: L[1] extending the basering Po by new variables given by \"A,B,..\" (deformation parameters); the new variables precede the old ones, the ordering is the product of \"ls\" and \"ord(Po)\" @* L[2] = L[1]/Fo extending Qo=Po/Fo, @* L[3] = the embedding ring of the versal base space, @* L[4] = L[1]/Js extending L[3]/Js. @* In the ring L[1] the following matrices are stored: @*Js = giving the versal base space (obstructions), @*Fs = giving the versal family of Fo, @*Rs = giving the lifting of Ro=syz(Fo). If d is defined (!=0), it computes up to degree d. @*If 'any' is defined and any[1] is no string, interactive version. @*Otherwise 'any' is interpreted as a list of predefined strings: \"my\",\"param\",\"order\",\"out\": @* (\"my\" internal prefix, \"param\" is a letter (e.g. \"A\") for the name of the first parameter or (e.g. \"A(\") for index parameter variables, \"order\" ordering string for ring extension), \"out\" name of output file). NOTE: printlevel < 0 no additional output, printlevel >=0,1,2,.. informs you, what is going on; this proc uses 'execute'. EXAMPLE:example versal; shows an example " { //------- prepare ------------------------------------------------------------- string str,@param,@order,@my,@out,@degrees; int @d,d_max,@t1,t1',@t2,@colR,ok_ann,@smooth,@noObstr,@size,@j; int p = printlevel-voice+3; int time = timer; intvec @iv,@jv,@is_qh,@degr; d_max = 100; @my = ""; @param="A"; @order="ds"; @out="no"; @size = size(#); if( @size>0 ) { if (#[1]>0) { d_max = #[1];} } if( @size>1 ) { if(typeof(#[2])!="string") { string @active; @my,@param,@order,@out = interact1(); } else { @my = #[2]; if (@size>2) {@param = #[3];} if (@size>3) {@order = #[4];} if (@size>4) {@out = #[5];} } } string myPx = @my+"Px"; string myQx = @my+"Qx"; string myOx = @my+"Ox"; string mySo = @my+"So"; Fo = simplify(Fo,10); @is_qh = qhweight(Fo); int @rowR= size(Fo); def Po = basering; setring Po; poly X_s = product(maxideal(1)); //------- reproduce T_12 ----------------------------------------------------- list Ls = T_12(Fo,1); matrix Ro = Ls[6]; // syz(i) matrix InfD = Ls[5]; // matrix of inf. deformations matrix PreO = Ls[7]; // representation of (Syz/Kos)* module PreO'= std(PreO); module PreT = Ls[2]; // representation of modT_2 (sb) if(dim(PreT)==0) { matrix kbT_2 = kbase(PreT); // kbase of T_2 } else { matrix kbT_2 ; // kbase of T_2 : empty } @t1 = Ls[3]; // vdim of T_1 @t2 = Ls[4]; // vdim of T_2 kill Ls; t1' = @t1; if( @t1==0) { dbprint(p,"// rigid!"); return(list());} if( @t2==0) { @smooth=1; dbprint(p,"// smooth base space");} dbprint(p,"// ready: T_1 and T_2"); @colR = ncols(Ro); //----- test: quasi-homogeneous, choice of inf. def.-------------------------- @degrees = homog_test(@is_qh,matrix(Fo),InfD); @jv = 1..@t1; if (@degrees!="") { dbprint(p-1,"// T_1 is quasi-homogeneous represented with weight-vector", @degrees); } if (defined(@active)) { "// matrix of infinitesimal deformations:";print(InfD); "// weights of infinitesimal deformations ( empty ='not qhomog'):"; @degrees; matrix dummy; InfD,dummy,t1' = interact2(InfD,@jv);kill dummy; } //---- create new rings and objects ------------------------------------------ list list_of_rings=get_rings(Fo,t1',1,@order,@param); def `myPx`= list_of_rings[1]; def `myQx`= list_of_rings[2]; def `myOx`= list_of_rings[3]; def `mySo`= list_of_rings[4]; kill list_of_rings; setring `myPx`; @jv=0; @jv[t1']=0; @jv=@jv+1; @jv[nvars(basering)]=0; //weight-vector for calculating //rel-jet with resp to def-para ideal Io = imap(Po,Fo); ideal J,m_J,tid; attrib(J,"isSB",1); matrix Fo = matrix(Io); //initial equations matrix homF = kohom(Fo,@colR); matrix Ro = imap(Po,Ro); matrix homR = transpose(Ro); matrix homFR= concat(homR,homF); module hom' = std(homFR); matrix Js[1][@t2]; matrix F_R,Fs,Rs,Fn,Rn; export Js,Fs,Rs; matrix Mon[t1'][1]=maxideal(1); Fn = transpose(imap(Po,InfD)*Mon); //infinitesimal deformations Fs = Fo + Fn; dbprint(p-1,"// infinitesimal deformation: Fs: ",Fs); Rn = (-1)*lift(Fo,Fs*Ro); //infinit. relations Rs = Ro + Rn; F_R = Fs*Rs; tid = 0 + ideal(F_R); if (tid[1]==0) {d_max=1;} //finished ? setring `myOx`; matrix Fs,Rs,Cup,Cup',F_R,homFR,New,Rn,Fn; module hom'; ideal null,tid; attrib(null,"isSB",1); setring `myQx`; poly X_s = imap(Po,X_s); matrix Cup,Cup',MASS; ideal tid,null; attrib(null,"isSB",1); ideal J,m_J; attrib(J,"isSB",1); attrib(m_J,"isSB",1); matrix PreO = imap(Po,PreO); module PreO'= imap(Po,PreO'); attrib(PreO',"isSB",1); module PreT = imap(Po,PreT); attrib(PreT,"isSB",1); matrix kbT_2 = imap(Po,kbT_2); matrix Mon = fetch(`myPx`,Mon); matrix F_R = fetch(`myPx`,F_R); matrix Js[1][@t2]; //------- start the loop ------------------------------------------------------ for (@d=2;@d<=d_max;@d=@d+1) { if( @t1==0) {break}; dbprint(p,"// start computation in degree "+string(@d)+"."); dbprint(p-3,">>> TIME = "+string(timer-time)); dbprint(p-3,"==> memory = "+string(kmemory())+"k"); //------- compute obstruction-vector ----------------------------------------- if (@smooth) { @noObstr=1;} else { Cup = jet(F_R,@d,@jv); Cup = matrix(reduce(ideal(Cup),m_J),@colR,1); Cup = jet(Cup,@d,@jv); } //------- express obstructions in kbase of T_2 ------------------------------- if ( @noObstr==0 ) { Cup' = reduce(Cup,PreO'); tid = simplify(ideal(Cup'),10); if(tid[1]!=0) { dbprint(p-4,"// *"); Cup=Cup-Cup'; } Cup = lift(PreO,Cup); MASS = lift_rel_kb(Cup,PreT,kbT_2,X_s); dbprint(p-3,"// next MASSEY-products:",MASS-jet(MASS,@d-1,@jv)); if (MASS==transpose(Js)) { @noObstr=1;dbprint(p-1,"// no obstruction"); } else { @noObstr=0; } } //------- obtain equations of base space -------------------------------------- if ( @noObstr==0 ) { Js = transpose(MASS); dbprint(p-2,"// next equation of base space:", simplify(ideal(Js),10)); setring `myPx`; Js = imap(`myQx`,Js); degBound = @d+1; J = std(ideal(Js)); m_J = std(J*ideal(Mon)); degBound = 0; //--------------- obtain new base-ring ---------------------------------------- if(defined(`myOx`)) {kill `myOx`;} qring `myOx` = J; matrix Fs,Rs,F_R,Cup,Cup',homFR,New,Rn,Fn; module hom'; ideal null,tid; attrib(null,"isSB",1); } //---------------- lift equations F and relations R --------------------------- setring `myOx`; Fs = fetch(`myPx`,Fs); Rs = fetch(`myPx`,Rs); F_R = Fs*Rs; F_R = matrix(reduce(ideal(F_R),null)); tid = 0 + ideal(F_R); if (tid[1]==0) { dbprint(p-1,"// finished"); break;} Cup = (-1)*transpose(jet(F_R,@d,@jv)); homFR = fetch(`myPx`,homFR); hom' = fetch(`myPx`,hom'); attrib(hom',"isSB",1); Cup' = simplify(reduce(Cup,hom'),10); tid = simplify(ideal(Cup'),10); if (tid[1]!=0) { dbprint(p-4,"// #"); Cup=Cup-Cup'; } New = lift(homFR,Cup); Rn = matrix(ideal(New[1+@rowR..nrows(New),1]),@rowR,@colR); Fn = matrix(ideal(New[1..@rowR,1]),1,@rowR); Fs = Fs+Fn; Rs = Rs+Rn; F_R = Fs*Rs; tid = 0+reduce(ideal(F_R),null); //---------------- fetch results into other rings ----------------------------- setring `myPx`; Fs = fetch(`myOx`,Fs); Rs = fetch(`myOx`,Rs); F_R = Fs*Rs; setring `myQx`; F_R = fetch(`myPx`,F_R); m_J = fetch(`myPx`,m_J); attrib(m_J,"isSB",1); J = fetch(`myPx`,J); attrib(J,"isSB",1); Js = fetch(`myPx`,Js); tid = fetch(`myOx`,tid); if (tid[1]==0) { dbprint(p-1,"// finished");break;} } //--------- end loop and final output ---------------------------------------- setring `myPx`; if (@out!="no") { string out = @out+"_"+string(@d); "// writing file "+out+" with matrix Js, matrix Fs, matrix Rs ready for reading in rings "+myPx+" or "+myQx; write(out,"matrix Js[1][",@t2,"]=",Js,";matrix Fs[1][",@rowR,"]=",Fs, ";matrix Rs[",@rowR,"][",@colR,"]=",Rs,";"); } dbprint(p-3,">>> TIME = "+string(timer-time)); if (@is_qh != 0) { @degr = qhweight(ideal(Js)); @degr = @degr[1..t1']; dbprint(p-1,"// quasi-homogeneous weights of miniversal base",@degr); } dbprint(p-1, "// ___ Equations of miniversal base space ___",Js, "// ___ Equations of miniversal total space ___",Fs); dbprint(p,""," // 'versal' returned a list, say L, of four rings. In L[1] are stored: // as matrix Fs: Equations of total space of the miniversal deformation, // as matrix Js: Equations of miniversal base space, // as matrix Rs: syzygies of Fs mod Js. // To access these data, type def Px=L[1]; setring Px; print(Fs); print(Js); print(Rs); // L[2] = L[1]/Fo extending Qo=Po/Fo, // L[3] = the embedding ring of the versal base space, // L[4] = L[1]/Js extending L[3]/Js. "); return(list(`myPx`,`myQx`,`mySo`,`myOx`)); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 0; ring r1 = 0,(x,y,z,u,v),ds; matrix m[2][4] = x,y,z,u,y,z,u,v; ideal Fo = minor(m,2); // cone over rational normal curve of degree 4 list L=versal(Fo); L; def Px=L[1]; setring Px; // ___ Equations of miniversal base space ___: Js;""; // ___ Equations of miniversal total space ___: Fs;""; } /////////////////////////////////////////////////////////////////////////////// proc mod_versal(matrix Mo, ideal I, list #) "USAGE: mod_versal(Mo,Io[,d,any]); Io=ideal, Mo=module, d=int, any =list COMPUTE: miniversal deformation of coker(Mo) over Qo=Po/Io, Po=basering; RETURN: list L of 4 rings: L[1] extending the basering Po by new variables given by \"A,B,..\" (deformation parameters); the new variables precede the old ones, the ordering is the product of \"ls\" and \"ord(Po)\" @* L[2] = L[1]/Io extending Qo, @* L[3] = the embedding ring of the versal base space, @* L[4] = L[1]/(Io+Js) ring of the versal deformation of coker(Ms). @* In the ring L[1] the following matrices are stored: @*Js = giving the versal base space (obstructions), @*Fs = giving the versal family of Mo, @*Rs = giving the lifting of syzygies Lo=syz(Mo). If d is defined (!=0), it computes up to degree d. @*If 'any' is defined and any[1] is no string, interactive version. @*Otherwise 'any' is interpreted as a list of predefined strings: \"my\",\"param\",\"order\",\"out\": @* (\"my\" internal prefix, \"param\" is a letter (e.g. \"A\") for the name of the first parameter or (e.g. \"A(\") for index parameter variables, \"order\" ordering string for ring extension), \"out\" name of output file). NOTE: printlevel < 0 no additional output, printlevel >=0,1,2,.. informs you, what is going on, this proc uses 'execute'. EXAMPLE:example mod_versal; shows an example " { //------- prepare ------------------------------------------------------------- intvec save_opt=option(get); option(cancelunit); string str,@param,@order,@my,@out,@degrees; int @d,d_max,f0,f1,f2,e1,e1',e2,ok_ann,@smooth,@noObstr,@size,@j; int p = printlevel-voice+3; int time = timer; intvec @iv,@jv,@is_qh,@degr; d_max = 100; @my = ""; @param="A"; @order="ds"; @out="no"; @size = size(#); if( @size>0 ) { d_max = #[1]; } if( @size>1 ) { if(typeof(#[2])!="string") { string @active; @my,@param,@order,@out = interact1(); } else { @my = #[2]; if (@size>2) {@param = #[3];} if (@size>3) {@order = #[4];} if (@size>4) {@out = #[5];} } } string myPx = @my+"Px"; string myQx = @my+"Qx"; string myOx = @my+"Ox"; string mySo = @my+"So"; @is_qh = qhweight(I); def Po = basering; setring Po; poly X_s = product(maxideal(1)); //-------- compute Ext's ------------------------------------------------------ I = std(I); qring Qo = I; matrix Mo = fetch(Po,Mo); list Lo = compute_ext(Mo,p); f0,f1,f2,e1,e2,ok_ann=Lo[1]; matrix Ls,kb1,lift1 = Lo[2],Lo[3],Lo[4]; matrix kb2,C',D' = Lo[5][2],Lo[5][3],Lo[5][5]; module ex2,Co,Do = Lo[5][1],Lo[5][4],Lo[5][6]; kill Lo; dbprint(p,"// ready: Ext1 and Ext2"); //----- test: quasi-homogeneous, choice of inf. def.-------------------------- @degrees = homog_test(@is_qh,Mo,kb1); e1' = e1; @jv = 1..e1; if (@degrees != "") { dbprint(p-1,"// Ext1 is quasi-homogeneous represented: "+@degrees); } if (defined(@active)) { "// kbase of Ext1:"; print(kb1); "// weights of kbase of Ext1 ( empty = 'not qhomog')";@degrees; kb1,lift1,e1' = interact2(kb1,@jv,lift1); } //-------- get new rings and objects ------------------------------------------ setring Po; list list_of_rings=get_rings(I,e1',0,@order,@param); def `myPx`= list_of_rings[1]; def `myQx`= list_of_rings[2]; def `myOx`= list_of_rings[3]; def `mySo`= list_of_rings[4]; kill list_of_rings; setring `myPx`; ideal J,m_J; ideal I_J = imap(Po,I); ideal Io = I_J; matrix Mon[e1'][1] = maxideal(1); matrix Ms = imap(Qo,Mo); matrix Ls = imap(Qo,Ls); matrix Js[1][e2]; setring `myQx`; ideal J,I_J,tet,null; attrib(null,"isSB",1); ideal m_J = fetch(`myPx`,m_J); attrib(m_J,"isSB",1); @jv=0; @jv[e1] = 0; @jv = @jv+1; @jv[nvars(`myPx`)] = 0; matrix Ms = imap(Qo,Mo); export(Ms); matrix Ls = imap(Qo,Ls); export(Ls); matrix Js[e2][1]; export(Js); matrix MASS; matrix Mon = fetch(`myPx`,Mon); matrix Mn,Ln,ML,Cup,Cup',Lift; matrix C' = imap(Qo,C'); module Co = imap(Qo,Co); attrib(Co,"isSB",1); module ex2 = imap(Qo,ex2); attrib(ex2,"isSB",1); matrix D' = imap(Qo,D'); module Do = imap(Qo,Do); attrib(Do,"isSB",1); matrix kb2 = imap(Qo,kb2); matrix kb1 = imap(Qo,kb1); matrix lift1= imap(Qo,lift1); poly X_s = imap(Po,X_s); intvec intv = e1',e1,f0,f1,f2; Ms,Ls= get_inf_def(Ms,Ls,kb1,lift1,X_s); kill kb1,lift1; dbprint(p-1,"// infinitesimal extension",Ms); //----------- start the loop -------------------------------------------------- for (@d=2;@d<=d_max;@d=@d+1) { dbprint(p-3,">>> time = "+string(timer-time)); dbprint(p-3,"==> memory = "+string(memory(0)/1000)+ ", allocated = "+string(memory(1)/1000)); dbprint(p,"// start deg = "+string(@d)); //-------- get obstruction ---------------------------------------------------- Cup = matrix(ideal(Ms*Ls),f0*f2,1); Cup = jet(Cup,@d,@jv); Cup = reduce(ideal(Cup),m_J); Cup = jet(Cup,@d,@jv); //-------- express obstruction in kbase --------------------------------------- Cup' = reduce(Cup,Do); tet = simplify(ideal(Cup'),10); if (tet[1]!=0) { dbprint(p-4,"// *"); Cup = Cup-Cup'; } Cup = lift(D',Cup); if (ok_ann) { MASS = lift_rel_kb(Cup,ex2,kb2,X_s);} else { MASS = reduce(Cup,ex2);} dbprint(p-3,"// next MATRIC-MASSEY-products", MASS-jet(MASS,@d-1,@jv)); if ( MASS==transpose(Js)) { @noObstr = 1;dbprint(p-1,"//no obstruction"); } else { @noObstr = 0; } //-------- obtain equations of base space ------------------------------------- if (@noObstr == 0) { Js = MASS; dbprint(p-2,"// next equation of base space:",simplify(ideal(Js),10)); setring `myPx`; Js = imap(`myQx`,Js); degBound=@d+1; J = std(ideal(Js)); m_J = std(ideal(Mon)*J); degBound=0; I_J = Io,J; attrib(I_J,"isSB",1); //-------- obtain new base ring ----------------------------------------------- if (defined(`myOx`)) {kill `myOx`;} qring `myOx` = I_J; ideal null,tet; attrib(null,"isSB",1); matrix Ms = imap(`myQx`,Ms); matrix Ls = imap(`myQx`,Ls); matrix Mn,Ln,ML,Cup,Cup',Lift; matrix C' = imap(Qo,C'); module Co = imap(Qo,Co); attrib(Co,"isSB",1); module ex2 = imap(Qo,ex2); attrib(ex2,"isSB",1); matrix kb2 = imap(Qo,kb2); poly X_s = imap(Po,X_s); } //-------- get lifts ---------------------------------------------------------- setring `myOx`; ML = matrix(reduce(ideal(Ms*Ls),null),f0,f2); Cup = matrix(ideal(ML),f0*f2,1); Cup = jet(Cup,@d,@jv); Cup'= reduce(Cup,Co); tet = simplify(ideal(Cup'),10); if (tet[1]!=0) { dbprint(p-4,"// #"); Cup = Cup-Cup'; } Lift = lift(C',Cup); Mn = matrix(ideal(Lift),f0,f1); Ln = matrix(ideal(Lift[f0*f1+1..nrows(Lift),1]),f1,f2); Ms = Ms-Mn; Ls = Ls-Ln; dbprint(p-3,"// next extension of Mo",Mn); dbprint(p-3,"// next extension of syz(Mo)",Ln); ML = reduce(ideal(Ms*Ls),null); //--------- test: finished ---------------------------------------------------- tet = simplify(ideal(ML),10); if (tet[1]==0) { dbprint(p-1,"// finished in degree ",@d);} //---------fetch results into Qx and Px --------------------------------------- setring `myPx`; Ms = fetch(`myOx`,Ms); Ls = fetch(`myOx`,Ls); setring `myQx`; Ms = fetch(`myOx`,Ms); Ls = fetch(`myOx`,Ls); ML = Ms*Ls; ML = matrix(reduce(ideal(ML),null),f0,f2); tet = imap(`myOx`,tet); if (tet[1]==0) { break;} } //------- end of loop, final output ------------------------------------------- if (@out != "no") { string out = @out+"_"+string(@d); "// writing file '"+out+"' with matrix Js, matrix Ms, matrix Ls ready for reading in rings "+myPx+" or "+myQx; write(out,"matrix Js[1][",e2,"]=",Js,";matrix Ms[",f0,"][",f1,"]=",Ms, ";matrix Ls[",f1,"][",f2,"]=",Ls,";"); } dbprint(p-3,">>> TIME = "+string(timer-time)); if (@is_qh != 0) { @degr = qhweight(ideal(Js)); @degr = @degr[1..e1']; dbprint(p-1,"// quasi-homogeneous weights of miniversal base",@degr); } dbprint(p," // 'mod_versal' returned a list, say L, of four rings. In L[2] are stored: // as matrix Ms: presentation matrix of the deformed module, // as matrix Ls: lifted syzygies, // as matrix Js: Equations of total space of miniversal deformation // To access these data, type def Qx=L[2]; setring Qx; print(Ms); print(Ls); print(Js); "); option(set,save_opt); return(list(`myPx`,`myQx`,`mySo`,`myOx`)); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring Ro = 0,(x,y),wp(3,4); ideal Io = x4+y3; matrix Mo[2][2] = x2,y,-y2,x2; list L = mod_versal(Mo,Io); def Qx=L[2]; setring Qx; print(Ms); print(Ls); print(Js); printlevel = p; if (defined(Px)) {kill Px,Qx,So;} } /////////////////////////////////////////////////////////////////////////////// proc kill_rings(list #) "USAGE: kill_rings([string]); RETURN: nothing, but kills exported rings generated by procedures 'versal' and 'mod_versal' with optional prefix 'string' NOTE: obsolete " { string my,br; if (size(#)>0) { my = #[1];} string na=nameof(basering); br = my+"Qx"; if (defined(`br`)) { kill `br`;} br = my+"Px"; if (defined(`br`)) { kill `br`;} br = my+"So"; if (defined(`br`)) { kill `br`;} br = my+"Ox"; if (defined(`br`)) { kill `br`;} br = my+"Sx"; if (defined(`br`)) { kill `br`} //Namespaces: br = my+"Qx"; if (defined(Top::`br`)) { kill Top::`br`;} br = my+"Ox"; if (defined(Top::`br`)) { kill Top::`br`;} br = my+"Px"; if (defined(Ring::`br`)) { kill Ring::`br`;} br = my+"So"; if (defined(Ring::`br`)) { kill Ring::`br`;} if (defined(basering)==0) { "// choose new basering?"; listvar(Top,ring); } return(); } /////////////////////////////////////////////////////////////////////////////// proc compute_ext(matrix Mo,int p) " Sub-procedure: obtain Ext1 and Ext2 and other objects used by mod_versal " { int l,f0,f1,f2,f3,e1,e2,ok_ann; module Co,Do,ima,ex1,ex2; matrix M0,M1,M2,ker,kb1,lift1,kb2,A,B,C,D; //------- resM --------------------------------------------------------------- list resM = nres(Mo,3); M0 = resM[1]; M1 = resM[2]; M2 = resM[3]; kill resM; f0 = nrows(M0); f1 = ncols(M0); f2 = ncols(M1); f3 = ncols(M2); //------ compute Ext^2 ------------------------------------------------------ B = kohom(M0,f3); A = kontrahom(M2,f0); D = modulo(A,B); Do = std(D); ima = kohom(M0,f2),kontrahom(M1,f0); ex2 = modulo(D,ima); ex2 = std(ex2); e2 = vdim(ex2); kb2 = kbase(ex2); dbprint(p,"// vdim (Ext^2) = "+string(e2)); //------ test: max = Ann(Ext2) ----------------------------------------------- for (l=1;l<=e2;l=l+1) { ok_ann = ok_ann+ord(kb2[l]); } if (ok_ann==0) { e2 =nrows(ex2); dbprint(p,"// Ann(Ext2) is maximal"); } //------ compute Ext^1 ------------------------------------------------------- B = kohom(M0,f2); A = kontrahom(M1,f0); ker = modulo(A,B); ima = kohom(M0,f1),kontrahom(M0,f0); ex1 = modulo(ker,ima); ex1 = std(ex1); e1 = vdim(ex1); dbprint(p,"// vdim (Ext^1) = "+string(e1)); kb1 = kbase(ex1); kb1 = ker*kb1; C = concat(A,B); Co = std(C); //------ compute the liftings of Ext^1 --------------------------------------- lift1 = A*kb1; lift1 = lift(B,lift1); intvec iv = f0,f1,f2,e1,e2,ok_ann; list L' = ex2,kb2,C,Co,D,Do; return(iv,M1,kb1,lift1,L'); } /////////////////////////////////////////////////////////////////////////////// static proc get_rings(ideal Io,int e1,int switch, list #) " Sub-procedure: creating ring-extensions, returned as a list of 4 rings " { def Po = basering; string my; string my_ord = "ds"; string my_var = "A"; if (size(#)>1) { my_ord = #[1]; my_var = #[2]; } def my_Px=extendring(e1,my_var,my_ord); setring my_Px; ideal Io = imap(Po,Io); attrib(Io,"isSB",1); qring my_Qx = Io; if (switch) { setring my_Px; qring my_Ox = std(ideal(0)); } else { def my_Ox = my_Qx; } def my_So=defring(charstr(Po),e1,my_var,my_ord); setring my_So; list erg=list(my_Px,my_Qx,my_Ox,my_So); return(erg); } /////////////////////////////////////////////////////////////////////////////// proc get_inf_def(list #) " Sub-procedure: compute infinitesimal family of a module and its syzygies from a kbase of Ext1 and its lifts " { matrix Ms = #[1]; matrix Ls = #[2]; matrix kb1 = #[3]; matrix li1 = #[4]; int e1,f0,f1,f2; poly X_s = #[5]; e1 = ncols(kb1); f0 = nrows(Ms); f1 = nrows(Ls); f2 = ncols(Ls); int l; for (l=1;l<=e1;l=l+1) { Ms = Ms + var(l)*matrix(ideal(kb1[l]),f0,f1); Ls = Ls - var(l)*matrix(ideal(li1[l]),f1,f2); } return(Ms,Ls); } ////////////////////////////////////////////////////////////////////////////// proc lift_rel_kb (module N, module M, list #) "USAGE: lift_rel_kb(N,M[,kbaseM,p]); ASSUME: [p a monomial ] or the product of all variables N, M modules of same rank, M depending only on variables not in p and vdim(M) is finite in this ring, [ kbaseM the kbase of M in the subring given by variables not in p ] @* warning: these assumptions are not checked by the procedure RETURN: matrix A, whose j-th columns present the coeff's of N[j] in kbaseM, i.e. kbaseM*A = reduce(N,std(M)) EXAMPLE: example lift_rel_kb; shows examples " { poly p = product(maxideal(1)); M = std(M); matrix A; if (size(#)>0) { p=#[2]; module kbaseM=#[1];} else { if (vdim(M)<=0) { "// vdim(M) not finite";return(A);} module kbaseM = kbase(M); } N = reduce(N,M); if (simplify(N,10)[1]==[0]) {return(A);} A = coeffs(N,kbaseM,p); return(A); } example { "EXAMPLE:"; echo=2; ring r=0,(A,B,x,y),dp; module M = [x2,xy],[xy,y3],[y2],[0,x]; module kbaseM = [1],[x],[xy],[y],[0,1],[0,y],[0,y2]; poly f=xy; module N = [AB,BBy],[A3xy+x4,AB*(1+y2)]; matrix A = lift_rel_kb(N,M,kbaseM,f); print(A); "TEST:"; print(matrix(kbaseM)*A-matrix(reduce(N,std(M)))); } /////////////////////////////////////////////////////////////////////////////// proc lift_kbase (def N,def M) "USAGE: lift_kbase(N,M); N,M=poly/ideal/vector/module RETURN: matrix A, coefficient matrix expressing N as linear combination of k-basis of M. Let the k-basis have k elements and size(N)=c columns. Then A satisfies: matrix(reduce(N,std(M)),k,c) = matrix(kbase(std(M)))*A ASSUME: dim(M)=0 and the monomial ordering is a well ordering or the last block of the ordering is c or C EXAMPLE: example lift_kbase; shows an example " { return(lift_rel_kb(N,M)); } example {"EXAMPLE:"; echo=2; ring R=0,(x,y),ds; module M=[x2,xy],[y2,xy],[0,xx],[0,yy]; module N=[x3+xy,x],[x,x+y2]; print(M); module kb=kbase(std(M)); print(kb); print(N); matrix A=lift_kbase(N,M); print(A); matrix(reduce(N,std(M)),nrows(kb),ncols(A)) - matrix(kbase(std(M)))*A; } /////////////////////////////////////////////////////////////////////////////// proc interact1 () " Sub_procedure: asking for and reading your input-strings " { string my = "@"; string str,out,my_ord,my_var; my_ord = "ds"; my_var = "A"; "INPUT: name of output-file (ENTER = no output, do not use \"my\"!)"; str = read(""); if (size(str)>1) { out = str[1..size(str)-1];} else { out = "no";} "INPUT: prefix-string of ring-extension (ENTER = '@')"; str = read(""); if ( size(str) > 1 ) { my = str[1..size(str)-1]; } "INPUT:parameter-string (give a letter corresponding to first new variable followed by the next letters, or 'T(' - a letter + '(' - getting a string of indexed variables) (ENTER = A) :"; str = read(""); if (size(str)>1) { my_var=str[1..size(str)-1]; } "INPUT:order-string (local or weighted!) (ENTER = ds) :"; str = read(""); if (size(str)>1) { my_ord=str[1..size(str)-1]; } if( find(my_ord,"s")+find(my_ord,"w") == 0 ) { "// ordering must be an local! changed into 'ds'"; my_ord = "ds"; } return(my,my_var,my_ord,out); } /////////////////////////////////////////////////////////////////////////////// proc interact2 (matrix A, intvec col_vec, list #) " Sub-procedure: asking for and reading your input " { module B,C; matrix D; int flag; if (size(#)>0) { D=#[1];flag=1;} int t1 = ncols(A); ">>Do you want all deformations? (ENTER=yes)"; string str = read(""); if ((size(str)>1) and (str<>"yes")) { ">> Choose columns of the matrix"; ">> (Enter = all columns)"; "INPUT (number of columns to use as integer-list 'i_1,i_2,.. ,i_t' ):"; string columnes = read(""); // improved: CL // ========================================================== // old: if (size(columnes)<2) {columnes=string(col_vec);} // t1 = size(columnes)/2; // new: if (columnes=="") { intvec vvvv=1..ncols(A); } else { execute("intvec vvvv="+columnes); } t1=size(vvvv); // ========================================================== int l,l1; for (l=1;l<=t1;l=l+1) { // old: execute("l1= "+columnes[2*l-1]+";"); l1=vvvv[l]; B[l] = A[l1]; if(flag) { C[l]=D[l1];} } A = matrix(B,nrows(A),ncols(B)); D = matrix(C,nrows(D),ncols(C)); } return(A,D,t1); } /////////////////////////////////////////////////////////////////////////////// proc negative_part(intvec iv) " RETURNS intvec of indices of jv having negative entries (or iv, if non) " { intvec jv; int l,k; for (l=1;l<=size(iv);l=l+1) { if (iv[l]<0) { k = k+1; jv[k]=l; } } if (jv==0) {jv=1; dbprint(printlevel-1,"// empty negative part, return all ");} return(jv); } /////////////////////////////////////////////////////////////////////////////// proc find_ord(matrix A, intvec w_vec) " Sub-proc: return martix ord(a_ij) with respect to weight_vec, or 0 if A non-qh " { int @r = nrows(A); int @c = ncols(A); int i,j; def br = basering; def nr=changeord(list(list("wp",w_vec))); setring nr; matrix A = imap(br,A); intmat degA[@r][@c]; if (homog(ideal(A))) { for (i=1;i<=@r;i=i+1) { for(j=1;j<=@c;j=j+1) { degA[i,j]=ord(A[i,j]); } } } setring br; if (defined(nr)) { kill nr; } return(degA); } /////////////////////////////////////////////////////////////////////////////// proc homog_test(intvec w_vec, matrix Mo, matrix A) " Sub proc: return relative weight string of columns of A with respect to the given w_vec and to Mo, or \"\" if not qh NOTE: * means weight is not determined " { int k,l; intvec tv; string @nv; int @r = nrows(A); int @c = ncols(A); A = concat(matrix(ideal(Mo),@r,1),A); intmat a = find_ord(A,w_vec); intmat b[@r][@c]; for (l=1;l<=@c;l=l+1) { for (k=1;k<=@r;k=k+1) { if (A[k,l+1]!=0) { b[k,l] = a[k,l+1]-a[k,1];} } tv = 0; for (k=1;k<=@r;k=k+1) { if (A[k,l+1]*A[k,1]!=0) {tv = tv,b[k,l];} } if (size(tv)>1) { k = tv[2]; tv = tv[2..size(tv)]; tv = tv -k; if (tv==0) { @nv = @nv+string(-k)+",";} else {return("");} } else { @nv = @nv+"*,";} } @nv = @nv[1..size(@nv)-1]; return(@nv); } /////////////////////////////////////////////////////////////////////////////// proc homog_t(intvec d_vec, matrix Fo, matrix A) " Sub-procedure: Computing relative (with respect to flatten(Fo)) weight_vec of columns of A (return zero if Fo or A not qh) " { Fo = matrix(Fo,nrows(A),1); A = concat(Fo,A); A = transpose(A); def br = basering; def nr=changeord(list(list("wp",d_vec))); setring nr; module A = fetch(br,A); intvec dv; int l = homog(A) ; if (l==0) { setring br; kill Top::nr; if (defined(nr)) { kill nr; } return(l); } dv = attrib(A,"isHomog"); l = dv[1]; dv = dv[2..size(dv)]; dv = dv-l; setring br; kill Top::nr; if (defined(nr)) { kill nr; } return(dv); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/divisors.lib000066400000000000000000000543111266270727000205050ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version divisors.lib 4.0.0.0 Jun_2013 "; // $Id: 8ead4ff58e5d5010e160616239d1c259e7f041d3 $ category = "Commutative Algebra"; info=" LIBRARY: divisors.lib Divisors and P-Divisors AUTHORS: Janko Boehm boehm@mathematik.uni-kl.de @* Lars Kastner kastner@math.fu-berlin.de @* Benjamin Lorenz blorenz@math.uni-frankfurt.de @* Hans Schoenemann hannes@mathematik.uni-kl.de @* Yue Ren ren@mathematik.uni-kl.de OVERVIEW: We implement a class divisor on an algebraic variety and methods for computing with them. Divisors are represented by tuples of ideals defining the positive and the negative part. In particular, we implement the group structure on divisors, computing global sections and testing linear equivalence. In addition to this we provide a class formaldivisor which implements integer formal sums of divisors (not necessarily prime). A formal divisor can be evaluated to a divisor, and a divisor can be decomposed into a formal sum. Finally we provide a class pdivisor which implements polyhedral formal sums of divisors (P-divisors) where the coefficients are assumed to be polyhedra with fixed tail cone. There is a function to evaluate a P-divisor on a vector in the dual of the tail cone. The result will be a formal divisor. REFERENCES: For the class divisor we closely follow Macaulay2's tutorial on divisors. PROCEDURES: makeDivisor(ideal,ideal) create a divisor divisorplus(divisor,divisor) add two divisors multdivisor(int,divisor) multiply a divisor by an interger negativedivisor(divisor) compute the negative of the divisor normalForm(divisor) normal form of a divisor isEqualDivisor(divisor,divisor) test whether two divisors are equal globalSections(divisor) compute the global sections of a divisor degreeDivisor(divisor) degree of a divisor linearlyEquivalent(divisor,divisor) test whether two divisors a linearly equivalent effective(divisor) compute an effective divisor linearly equivalent to a divisor makeFormalDivisor(list) make a formal integer sum of divisors evaluateFormalDivisor(formaldivisor) evalutate a formal sum of divisors to a divisor formaldivisorplus(formaldivisor,formaldivisor) add two formal divisors negativeformaldivisor(formaldivisor) compute the negative of the formal divisor multformaldivisor(int,formaldivisor) multiply a formal divisor by an interger degreeFormalDivisor(formaldivisor) degree of a formal divisor makePDivisor(List) make a formal polyhedral sum of divisors evaluatePDivisor(pdivisor,intvec) evaluate a polyhedral divisor to an integer formal divisor pdivisorplus(pdivisor,pdivisor) add two polyhedral divisors "; //////////////////////////////////////////////////////////////////////////////// LIB "primdec.lib"; proc mod_init() { LIB"gfanlib.so"; newstruct("divisor","ideal den,ideal num"); newstruct("formaldivisor","list summands"); newstruct("pdivisor","list summands, cone tail"); system("install","divisor","print",divisor_print,1); system("install","divisor","+",divisorplus,2); system("install","divisor","*",proxymultdivisor,2); system("install","formaldivisor","print",formaldivisor_print,1); system("install","formaldivisor","+",formaldivisorplus,2); system("install","formaldivisor","*",proxymultformaldivisor,2); system("install","pdivisor","+",pdivisorplus,2); } proc divisor_print(divisor D) "USAGE: divisor_print(D); D; D = divisor. @* ASSUME: D is a divisor. RETURN: Will print D. KEYWORDS: divisors EXAMPLE: example divisor_print; shows an example " { "("+string(D.num)+") - ("+string(D.den)+")"; } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor P = makeDivisor(ideal(x,z),ideal(1)); P; } proc formaldivisor_print(formaldivisor fD) "USAGE: formaldivisor_print(D); D; D = formaldivisor. @* ASSUME: fD is a formaldivisor. RETURN: Will print fD. KEYWORDS: divisors EXAMPLE: example formaldivisor_print; shows an example " { int i; string s; list L=fD.summands; list cd; int c; divisor d; string linebreak = " "; for (i=1; i<=size(L); i++) { cd=L[i]; c=cd[1]; d=cd[2]; if (i>1 && c>=0) { s = s + "+"; } s = s + string(c)+"*( ("+string(d.num)+") - ("+string(d.den)+") )"; if (i!=size(L)) { s = s + linebreak; } } s; } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor P = makeDivisor(ideal(x,z),ideal(1)); P; } //////////////////////////////////////////////////////////////////////////////// // divisors as numerator and denomiator ideals proc makeDivisor(ideal I, ideal J) "USAGE: makeDivisor(I ,J); I = ideal, J = ideal. @* ASSUME: I and J are ideals in a qring Q of a smooth irreducible variety X such that any ideal in Q satisfies the S2 condition. RETURN: a divisor on X THEORY: The procedure will eliminate all components which are not of codimension 1. The S2 condition requires that every proper nonzero principal ideal has pure codimension 1. KEYWORDS: divisors EXAMPLE: example makeDivisor; shows an example " { divisor C; C.num = purify1(I); C.den = purify1(J); return(C); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor P = makeDivisor(ideal(x,z),ideal(1)); } proc divisorplus(divisor A, divisor B) "USAGE: divisorplus(A ,B); A + B; A = divisor, B = divisor. @* ASSUME: A and B are divisors on X. RETURN: a divisor on X THEORY: The procedure will compute the product of the numerator and denominator ideals, respectively. KEYWORDS: divisors EXAMPLE: example divisorplus; shows an example " { return(makeDivisor(interred(A.num*B.num),interred(A.den*B.den))); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); A+B; } proc multdivisor(int n, divisor A) "USAGE: multdivisor(n ,A); A*n; n = integer, A = divisor.@* ASSUME: n is an integer and A is a divisor on X. RETURN: a divisor on X THEORY: The procedure will compute the n-th power of the numerator and denominator ideals, respectively. KEYWORDS: divisors EXAMPLE: example multdivisor; shows an example " { if (n<0) {return(multdivisor(-n,negativedivisor(A)));} return(makeDivisor(interred((A.num)^n),interred((A.den)^n))); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); A; divisor D = multdivisor(4,A); D; A*4; } /*** * For operator overloading, which needs a procedure which takes a divisor first * and integer second. **/ proc proxymultdivisor(divisor A, int n) { if (n<0) {return(multdivisor(-n,negativedivisor(A)));} return(makeDivisor(interred((A.num)^n),interred((A.den)^n))); } proc negativedivisor(divisor A) "USAGE: negativedivisor(A); A*(-1); A = divisor.@* ASSUME: A is a divisor on X. RETURN: a divisor on X THEORY: The procedure will interchange the numerator and denominator ideals. KEYWORDS: divisors EXAMPLE: example negativedivisor; shows an example " { divisor B; B.num=A.den; B.den=A.num; return(B); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); A; divisor D = negativedivisor(A); D; } proc normalForm(divisor A) "USAGE: normalForm(A); A = divisor.@* ASSUME: A is a divisor on X. RETURN: different representative of the same divisor on X THEORY: The procedure will cancel common components of numerator and denominator. KEYWORDS: divisors EXAMPLE: example normalForm; shows an example " { divisor B; B.num=quotient(A.num,A.den); B.den=quotient(A.den,A.num); return(B); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); divisor D = (A+B)+multdivisor(-1,B); D; normalForm(D); } static proc isEqualIdeal(ideal A,ideal B){ return((size(NF(A,std(B)))==0) && (size(NF(B,std(A)))==0)); } proc isEqualDivisor(divisor A,divisor B) "USAGE: isEqualDivisor(A,B); A = divisor, B = divisor.@* ASSUME: A and B are divisors on X. RETURN: int 0 or 1, checks equality of A and B. THEORY: The procedure will compute the normal forms of A and B and compare. KEYWORDS: divisors EXAMPLE: example isEqualDivisor; shows an example " { A=normalForm(A); B=normalForm(B); return((isEqualIdeal(A.num,B.num)) && (isEqualIdeal(A.den,B.den))); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); divisor D = (A+B)+multdivisor(-1,B); isEqualDivisor(A,D); } static proc purify1(ideal I) { I = simplify(I,2); if (I[1]==0){ERROR("expected a non-zero ideal");} ideal f = I[1]; return(minbase(quotient(f,quotient(f,I)))); } static proc basis(ideal I,int d) { I=simplify(jet(intersect(I,maxideal(d)),d),2); return(I)} //basis(ideal(x,y^3),2); proc globalSections(divisor D) "USAGE: globalSections(A); A = divisor.@* ASSUME: A is a divisor on X. RETURN: a list with a basis of the space of global sections of D. THEORY: We assume that the qring of X satisfies the S2-condition and that X is smooth. We compute sat((f*J) : I) /f where D = (I)-(J). KEYWORDS: divisors EXAMPLE: example globalSections; shows an example " { poly f =(simplify(D.num,2))[1]; ideal LD = basis(purify1(quotient(f*D.den,D.num)),deg(f)); list L = simplify(LD,2),f; return(L); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor P = makeDivisor(ideal(x,z),ideal(1)); divisor D = multdivisor(4,P); globalSections(D); } static proc sectionIdeal(poly f, poly g, divisor D){ return(purify1(quotient(quotient(f*D.num,g), D.den))); } proc degreeDivisor(divisor A) "USAGE: degreeDivisor(A); A = divisor.@* ASSUME: A is a divisor on X. RETURN: The degree of A. THEORY: We compute difference of the degrees of the numerator and denominator ideals. KEYWORDS: divisors EXAMPLE: example degreeDivisor; shows an example " { return( mult(std(A.num))-mult(std(A.den))); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor P = makeDivisor(ideal(x,z),ideal(1)); degreeDivisor(P); } proc linearlyEquivalent(divisor A, divisor B) "USAGE: linearlyEquivalent(A,B); A = divisor, B = divisor.@* ASSUME: A and B are divisors on X. RETURN: list if A and B a linearly equivalent and int 0 otherwise. THEORY: Checks whether A-B is principle. If yes, returns a list L=(f,g) where A - B = (f/g). KEYWORDS: divisors EXAMPLE: example linearlyEquivalent; shows an example " { divisor F = normalForm(divisorplus(A,negativedivisor(B))); list LB = globalSections(F); if (size(LB[1])!=1) {return(0);} ideal V = sectionIdeal(LB[1][1,1],LB[2],F); if (isEqualIdeal(V,ideal(1))==1) {return(list(LB[1][1,1],LB[2]));} return(0); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); linearlyEquivalent(A,B); linearlyEquivalent(multdivisor(2,A),multdivisor(2,B)); } proc effective(divisor A) "USAGE: effective(A); A = divisor.@* ASSUME: A is a divisor on X which is linearly equivalent to an effective divisor. RETURN: divisor on X. THEORY: We compute an effective divisor linearly equivalent to A. KEYWORDS: divisors EXAMPLE: example effective; shows an example " { list LB = globalSections(A); if (size(LB[1])==0) {ERROR("the divisor is not linearly equivalent to an effective divisor");} ideal V = sectionIdeal(LB[1][1,1],LB[2],A); return(makeDivisor(V,ideal(1))); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); divisor D = divisorplus(multdivisor(2,B),negativedivisor(A)); effective(D); } //////////////////////////////////////////////////////////////////////////////// // formal sums of divisors proc makeFormalDivisor(list L) "USAGE: makeFormalDivisor(L); L = list.@* ASSUME: L is a list of tuples of an integer and a divisor. RETURN: a formal divisor on X THEORY: Represents an integer formal sum of divisors. KEYWORDS: divisors EXAMPLE: example makeFormalDivisor; shows an example " { formaldivisor C; C.summands = L; return(C); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); makeFormalDivisor(list(list(-5,A),list(2,B))); } proc evaluateFormalDivisor(formaldivisor D) "USAGE: evaluateFormalDivisor(D); D = formal divisor.@* ASSUME: D is a formal divisor on X. RETURN: a divisor on X THEORY: Will evaluate the formal sum. KEYWORDS: divisors EXAMPLE: example evaluateFormalDivisor; shows an example " { list L = D.summands; if (size(L)==0) {return(makeDivisor(ideal(1),ideal(1)));} int i; divisor E = multdivisor(L[1][1],L[1][2]); for ( i=2; i <= size(L); i++ ) { E = divisorplus(E, multdivisor(L[i][1],L[i][2])); } return(E); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); formaldivisor fE= makeFormalDivisor(list(list(-5,A),list(2,B))); evaluateFormalDivisor(fE); } static proc position(divisor I,list L){ int i; for (i=1; i <=size(L); i++){ if (isEqualDivisor(I,L[i][2])==1) {return(i);} } return(0);} proc formaldivisorplus(formaldivisor A, formaldivisor B) "USAGE: formaldivisorplus(A ,B); A + B; A = formaldivisor, B = formaldivisor. @* ASSUME: A and B are formal divisors on X. RETURN: a formal divisor on X THEORY: The procedure will add the formal sums. KEYWORDS: divisors EXAMPLE: example formaldivisorplus; shows an example " { formaldivisor C; int i,p; int j=1; list L; list LA=A.summands; list LB=B.summands; for (i=1; i<=size(LA);i++){ p=position(LA[i][2],L); if (p==0) { L[j]=list(); L[j][2]=LA[i][2]; L[j][1]=LA[i][1]; j=j+1; } else { L[p][1]=L[p][1]+LA[i][1]; }; } for (i=1; i<=size(LB);i++){ p=position(LB[i][2],L); if (p==0) { L[j]=list(); L[j][2]=LB[i][2]; L[j][1]=LB[i][1]; j=j+1; } else { L[p][1]=L[p][1]+LB[i][1]; }; } //C.summands = (A.summands)+(B.summands); return(L); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); divisor C = makeDivisor(ideal(x-z,y),ideal(1)); formaldivisor fE= makeFormalDivisor(list(list(-5,A),list(2,B))); formaldivisor fE2= makeFormalDivisor(list(list(-5,A),list(2,C))); formaldivisorplus(fE,fE2); } proc degreeFormalDivisor(formaldivisor A) "USAGE: degreeFormalDivisor(A); A = formaldivisor.@* ASSUME: A is a formaldivisor on X. RETURN: The degree of A. THEORY: We compute degrees of the summands and return the weighted sum. KEYWORDS: divisors EXAMPLE: example degreeFormalDivisor; shows an example " { int i,s; list L = A.summands; for (i=1;i<=size(L);i++){ s=s+L[i][1]*degreeDivisor(L[i][2]); } return(s); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); formaldivisor fE= makeFormalDivisor(list(list(-5,A),list(2,B))); degreeFormalDivisor(fE); } proc multformaldivisor(int n,formaldivisor A) "USAGE: multformaldivisor(n ,A); A*n; n = integer, A = formaldivisor.@* ASSUME: n is an integer and A is a formal divisor on X. RETURN: a formal divisor on X THEORY: The procedure will multiply the formal sum with n. KEYWORDS: divisors EXAMPLE: example multformaldivisor; shows an example " { formaldivisor B; list L=A.summands; int i; for (i=1;i<=size(L);i++){ L[i][1]=n*L[i][1]; } B.summands=L; return(B); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); formaldivisor fE= makeFormalDivisor(list(list(-5,A),list(2,B))); fE*2; } /*** * For operator overloading, which needs a procedure which takes a divisor first * and integer second. **/ proc proxymultformaldivisor(formaldivisor A, int n) { formaldivisor B; list L=A.summands; int i; for (i=1;i<=size(L);i++){ L[i][1]=n*L[i][1]; } B.summands=L; return(B); } proc negativeformaldivisor(formaldivisor A) "USAGE: negativeformaldivisor(A); A = formaldivisor.@* ASSUME: A is a formaldivisor on X. RETURN: a formal divisor on X THEORY: The procedure will change the signs of the coefficients. KEYWORDS: divisors EXAMPLE: example negativeformaldivisor; shows an example " { formaldivisor B; list L=A.summands; int i; for (i=1;i<=size(L);i++){ L[i][1]=-L[i][1]; } B.summands=L; return(B); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); formaldivisor fE= makeFormalDivisor(list(list(-5,A),list(2,B))); negativeformaldivisor(fE); } static proc primDecDivisor(divisor D) "decompose a divisor into a formal divisor of primary divisors" { formaldivisor E; ideal I = D.num; ideal J = D.den; list L; int i; int j = 1; list LI = primdecGTZ(I); for (i=1;i<=size(LI);i++){ LI[i][2]; L[j]=list(1,makeDivisor(LI[i][1],ideal(1))); j=j+1; }; list LJ = primdecGTZ(J); for (i=1;i<=size(LJ);i++){ LJ[i][2]; L[j]=list(-1,makeDivisor(LJ[i][1],ideal(1))); j=j+1; }; E.summands=L; return(E);} //////////////////////////////////////////////////////////////////////////////// // P-divisors proc makePDivisor(list L) "USAGE: makePDivisor(L); L = list.@* ASSUME: L is a list of tuples of a integral polyhedron and a divisor such that all polyhedra have the same tail cone. RETURN: a pdivisor on X THEORY: Represents an polyhedral formal sum of divisors. KEYWORDS: divisors, polyhedra EXAMPLE: example makePDivisor; shows an example " { pdivisor P; list CP = decomposePolyhedron(L[1][1]); P.tail = CP[1]; list LP; LP[1]=list(CP[2],L[1][2]); int i; for (i=2; i<=size(L);i++){ CP = decomposePolyhedron(L[i][1]); if (!(CP[1]==P.tail)) {ERROR("All P-coefficients should have the same tail cone");} LP[i]=list(CP[2],L[i][2]); } P.summands = LP; return(P); } example { "EXAMPLE:"; ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); intmat M[4][4]= 1,4,0,0, 1,0,3,0, 0,0,0,2, 1,1,1,1; polytope PP = polytopeViaPoints(M); makePDivisor(list(list(PP,A),list(PP,B))); } static proc decomposePolyhedron(polytope P){ intmat rays = vertices(P); intmat rays2 = rays; int i,j; for (i=1; i<=nrows(rays);i++){ if (rays[i,1]==1) { for (j=1; j<=ncols(rays);j++){ rays[i,j]=0; } } else { for (j=1; j<=ncols(rays);j++){ rays2[i,j]=0; } } } cone C = coneViaPoints(rays); polytope C2 = polytopeViaPoints(rays2); return(list(C,C2)); } proc evaluatePDivisor(pdivisor D,intvec v) "USAGE: evaluatePDivisor(D,v); D = pdivisor, v = intvec.@* ASSUME: D is a polyhedral divisor on X and v is a point in the dual of the tailcone of the coefficients. RETURN: a formal divisor on X THEORY: Will evaluate the polyhedral sum to an integer formal sum. KEYWORDS: divisors, polyhedra EXAMPLE: example evaluatePDivisor; shows an example " { formaldivisor vD; list L = D.summands; cone C = D.tail; cone dC = dualCone(C); list vL; int i; intvec vv = 0,v; if (!(containsInSupport(dC,vv))) {ERROR("the linear form given should be in the dual tail cone");} for (i=1; i<=size(L);i++){ vL[i]=list(); vL[i][2]=L[i][2]; vL[i][1]=Polymake::minimalValue(L[i][1],vv); } vD.summands = vL; return(vD);} example { "EXAMPLE:"; LIB("polymake.so"); ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); intmat M[4][4]= 1,4,0,0, 1,0,3,0, 0,0,0,2, 1,1,1,1; polytope PP = polytopeViaPoints(M); pdivisor pD = makePDivisor(list(list(PP,A),list(PP,B))); intvec v=1,1,1; evaluatePDivisor(pD,v); } proc pdivisorplus(pdivisor A, pdivisor B) "USAGE: pdivisorplus(A ,B); A + B; A = pdivisor, B = pdivisor. @* ASSUME: A and B are polyhedral divisors on X. RETURN: a pdivisor on X THEORY: The procedure will add the polyhedral formal sums by doing Minkowski sums. KEYWORDS: divisors, polyhedra EXAMPLE: example pdivisorplus; shows an example " { pdivisor C; int i,p; int j=1; if (!(A.tail==B.tail)) {ERROR("tail cones should be equal");} list L; list LA=A.summands; list LB=B.summands; for (i=1; i<=size(LA);i++){ p=position(LA[i][2],L); if (p==0) { L[j]=list(); L[j][2]=LA[i][2]; L[j][1]=LA[i][1]; j=j+1; } else { L[p][1]=Polymake::minkowskiSum(L[p][1],LA[i][1]); }; } for (i=1; i<=size(LB);i++){ p=position(LB[i][2],L); if (p==0) { L[j]=list(); L[j][2]=LB[i][2]; L[j][1]=LB[i][1]; j=j+1; } else { L[p][1]=Polymake::minkowskiSum(L[p][1],LB[i][1]); }; } C.summands = L; C.tail = A.tail; return(C); } example { "EXAMPLE:"; LIB("polymake.so"); ring r=31991,(x,y,z),dp; ideal I = y^2*z - x*(x-z)*(x+3*z); qring Q = std(I); divisor A = makeDivisor(ideal(x,z),ideal(1)); divisor B = makeDivisor(ideal(x,y),ideal(1)); intmat M[4][4]= 1,4,0,0, 1,0,3,0, 0,0,0,2, 1,1,1,1; polytope PP = polytopeViaPoints(M); pdivisor pD = makePDivisor(list(list(PP,A),list(PP,B))); pdivisorplus(pD,pD); } singular-4.0.3+ds/Singular/LIB/dmod.lib000066400000000000000000005151171266270727000175740ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version dmod.lib 4.0.0.0 Jun_2013 "; // $Id: fdf5b6f3b02e493b87f10bbefd609d3fd77c04ad $ category="Noncommutative"; info=" LIBRARY: dmod.lib Algorithms for algebraic D-modules AUTHORS: Viktor Levandovskyy, levandov@math.rwth-aachen.de @* Jorge Martin Morales, jorge@unizar.es OVERVIEW: Let K be a field of characteristic 0. Given a polynomial ring @* R = K[x_1,...,x_n] and a polynomial F in R, @* one is interested in the R[1/F]-module of rank one, generated by @* the symbol F^s for a symbolic discrete variable s. @* In fact, the module R[1/F]*F^s has a structure of a D(R)[s]-module, where D(R) @* is an n-th Weyl algebra K and @* D(R)[s] = D(R) tensored with K[s] over K. @* Constructively, one needs to find a left ideal I = I(F^s) in D(R), such @* that K[x_1,...,x_n,1/F]*F^s is isomorphic to D(R)/I as a D(R)-module. @* We often write just D for D(R) and D[s] for D(R)[s]. @* One is interested in the following data: @* - Ann F^s = I = I(F^s) in D(R)[s], denoted by LD in the output @* - global Bernstein polynomial in K[s], denoted by bs, @* - its minimal integer root s0, the list of all roots of bs, which are known @* to be rational, with their multiplicities, which is denoted by BS @* - Ann F^s0 = I(F^s0) in D(R), denoted by LD0 in the output @* (LD0 is a holonomic ideal in D(R)) @* - Ann^(1) F^s in D(R)[s], denoted by LD1 (logarithmic derivations) @* - an operator in D(R)[s], denoted by PS, such that the functional equality @* PS*F^(s+1) = bs*F^s holds in K[x_1,...,x_n,1/F]*F^s. REFERENCES: @* We provide the following implementations of algorithms: @* (OT) the classical Ann F^s algorithm from Oaku and Takayama (Journal of @* Pure and Applied Math., 1999), @* (LOT) Levandovskyy's modification of the Oaku-Takayama algorithm (ISSAC 2007) @* (BM) the Ann F^s algorithm by Briancon and Maisonobe (Remarques sur @* l'ideal de Bernstein associe a des polynomes, preprint, 2002) @* (LM08) V. Levandovskyy and J. Martin-Morales, ISSAC 2008 @* (C) Countinho, A Primer of Algebraic D-Modules, @* (SST) Saito, Sturmfels, Takayama 'Groebner Deformations of Hypergeometric @* Differential Equations', Springer, 2000 Guide: @* - Ann F^s = I(F^s) = LD in D(R)[s] can be computed by Sannfs [BM, OT, LOT] @* - Ann^(1) F^s in D(R)[s] can be computed by Sannfslog @* - global Bernstein polynomial bs in K[s] can be computed by bernsteinBM @* - Ann F^s0 = I(F^s0) = LD0 in D(R) can be computed by annfs0, annfs, annfsBM, @* annfsOT, annfsLOT, annfs2, annfsRB etc. @* - all the relevant data to F^s (LD, LD0, bs, PS) are computed by operatorBM @* - operator PS can be computed via operatorModulo or operatorBM @* @* - annihilator of F^{s1} for a number s1 is computed with annfspecial @* - annihilator of F_1^s_1 * ... * F_p^s_p is computed with annfsBMI @* - computing the multiplicity of a rational number r in the Bernstein poly @* of a given ideal goes with checkRoot @* - check, whether a given univariate polynomial divides the Bernstein poly @* goes with checkFactor PROCEDURES: annfs(F[,S,eng]); compute Ann F^s0 in D and Bernstein polynomial for a poly F annfspecial(I, F, m, n); compute Ann F^n from Ann F^s for a polynomial F and a number n Sannfs(F[,S,eng]); compute Ann F^s in D[s] for a polynomial F Sannfslog(F[,eng]); compute Ann^(1) F^s in D[s] for a polynomial F bernsteinBM(F[,eng]); compute global Bernstein polynomial for a polynomial F (algorithm of Briancon-Maisonobe) bernsteinLift(I,F [,eng]); compute a possible multiple of Bernstein polynomial via lift-like procedure operatorBM(F[,eng]); compute Ann F^s, Ann F^s0, BS and PS for a polynomial F (algorithm of Briancon-Maisonobe) operatorModulo(F, I, b); compute PS via the modulo approach annfsParamBM(F[,eng]); compute the generic Ann F^s (algorithm by Briancon and Maisonobe) and exceptional parametric constellations for a polynomial F with parametric coefficients annfsBMI(F[,eng]); compute Ann F^s and Bernstein ideal for a polynomial F=f1*..*fP (multivariate algorithm of Briancon-Maisonobe) checkRoot(F,a[,S,eng]); check if a given rational is a root of the global Bernstein polynomial of F and compute its multiplicity SannfsBFCT(F[,eng]); compute Ann F^s in D[s] for a polynomial F (algorithm of Briancon-Maisonobe, other output ordering) annfs0(I,F [,eng]); compute Ann F^s0 in D and Bernstein polynomial from the known Ann F^s in D[s] annfs2(I,F [,eng]); compute Ann F^s0 in D and Bernstein polynomial from the known Ann F^s in D[s] by using a trick of Noro annfsRB(I,F [,eng]); compute Ann F^s0 in D and Bernstein polynomial from the known Ann F^s in D[s] by using Jacobian ideal checkFactor(I,F,q[,eng]); check whether a polynomial q in K[s] is a factor of the global Bernstein polynomial of F from the known Ann F^s in D[s] arrange(p); create a poly, describing a full hyperplane arrangement reiffen(p,q); create a poly, describing a Reiffen curve isHolonomic(M); check whether a module is holonomic convloc(L); replace global orderings with local in the ringlist L minIntRoot(P,fact); minimal integer root among the roots of a maximal ideal P isRational(n); check whether n is a rational number SEE ALSO: bfun_lib, dmodapp_lib, dmodvar_lib, gmssing_lib KEYWORDS: D-module; D-module structure; left annihilator ideal; Bernstein-Sato polynomial; global Bernstein-Sato polynomial; Weyl algebra; Bernstein operator; logarithmic annihilator ideal; parametric annihilator; root of Bernstein-Sato polynomial; hyperplane arrangement; Oaku-Takayama algorithm; Briancon-Maisonobe algorithm; LOT algorithm "; // reworked by JM+VL on 9.3.2010: Sannfslog // added by VL on 2.3.2010: bernsteinLift // ****** commented out for better readability by VL on 2.3.2010 // annfsBM(F[,eng]); compute Ann F^s0 in D and Bernstein polynomial for a polynomial F (algorithm of Briancon-Maisonobe) // annfsLOT(F[,eng]); compute Ann F^s0 in D and Bernstein polynomial for a polynomial F (Levandovskyy modification of the Oaku-Takayama algorithm) // annfsOT(F[,eng]); compute Ann F^s0 in D and Bernstein polynomial for a polynomial F (algorithm of Oaku-Takayama) // SannfsBM(F[,eng]); compute Ann F^s in D[s] for a polynomial F (algorithm of Briancon-Maisonobe) // SannfsLOT(F[,eng]); compute Ann F^s in D[s] for a polynomial F (Levandovskyy modification of the Oaku-Takayama algorithm) // SannfsOT(F[,eng]); compute Ann F^s in D[s] for a polynomial F (algorithm of Oaku-Takayama) // checkRoot1(I,F,a[,eng]); check whether a rational is a root of the global Bernstein polynomial of F from the known Ann F^s in D[s] // checkRoot2(I,F,a[,eng]); check whether a rational is a root of the global Bernstein polynomial of F and compute its multiplicity from the known Ann F^s in D[s] LIB "matrix.lib"; // for submat LIB "nctools.lib"; // makeModElimRing etc. LIB "elim.lib"; // for nselect LIB "qhmoduli.lib"; // for Max LIB "gkdim.lib"; LIB "gmssing.lib"; LIB "control.lib"; // for genericity LIB "dmodapp.lib"; // for e.g. engine LIB "poly.lib"; proc testdmodlib() { /* tests all procs for consistency */ /* adding the new proc, add it here */ "MAIN PROCEDURES:"; example annfs; example Sannfs; example Sannfslog; example bernsteinBM; example operatorBM; example annfspecial; example annfsParamBM; example annfsBMI; example checkRoot; example annfs0; example annfs2; example annfsRB; example annfs2; example operatorModulo; "SECONDARY D-MOD PROCEDURES:"; example annfsBM; example annfsLOT; example annfsOT; example SannfsBM; example SannfsLOT; example SannfsOT; example SannfsBFCT; example checkRoot1; example checkRoot2; example checkFactor; } // new top-level procedures proc annfs(poly F, list #) "USAGE: annfs(f [,S,eng]); f a poly, S a string, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[1/f]*f^s with the algorithm @* given in S and with the Groebner basis engine given in ''eng'' NOTE: activate the output ring with the @code{setring} command. @* String S; S can be one of the following: @* 'bm' (default) - for the algorithm of Briancon and Maisonobe, @* 'ot' - for the algorithm of Oaku and Takayama, @* 'lot' - for the Levandovskyy's modification of the algorithm of OT. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise and by default @code{slimgb} is used. @* In the output ring: @* - the ideal LD (which is a Groebner basis) is the needed D-module structure, @* - the list BS contains roots and multiplicities of a BS-polynomial of f. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example annfs; shows examples " { int eng = 0; int chs = 0; // choice string algo = "bm"; string st; if ( size(#)>0 ) { if ( typeof(#[1]) == "string" ) { st = string(#[1]); if ( (st == "BM") || (st == "Bm") || (st == "bM") ||(st == "bm")) { algo = "bm"; chs = 1; } if ( (st == "OT") || (st == "Ot") || (st == "oT") || (st == "ot")) { algo = "ot"; chs = 1; } if ( (st == "LOT") || (st == "lOT") || (st == "Lot") || (st == "lot")) { algo = "lot"; chs = 1; } if (chs != 1) { // incorrect value of S print("Incorrect algorithm given, proceed with the default BM"); algo = "bm"; } // second arg if (size(#)>1) { // exists 2nd arg if ( typeof(#[2]) == "int" ) { // the case: given alg, given engine eng = int(#[2]); } else { eng = 0; } } else { // no second arg eng = 0; } } else { if ( typeof(#[1]) == "int" ) { // the case: default alg, engine eng = int(#[1]); // algo = "bm"; //is already set } else { // incorr. 1st arg algo = "bm"; } } } // size(#)=0, i.e. there is no algorithm and no engine given // eng = 0; algo = "bm"; //are already set // int ppl = printlevel-voice+2; int old_printlevel = printlevel; printlevel=printlevel+1; def save = basering; if ( algo=="ot") { def @A = annfsOT(F,eng); } else { if ( algo=="lot") { def @A = annfsLOT(F,eng); } else { // bm = default def @A = annfsBM(F,eng); } } printlevel = old_printlevel; return(@A); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = z*x^2+y^3; def A = annfs(F); // here, the default BM algorithm will be used setring A; // the Weyl algebra in (x,y,z,Dx,Dy,Dz) LD; //the annihilator of F^{-1} over A BS; // roots with multiplicities of BS polynomial } proc Sannfs(poly F, list #) "USAGE: Sannfs(f [,S,eng]); f a poly, S a string, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[f^s] with the algorithm @* given in S and with the Groebner basis engine given in eng NOTE: activate the output ring with the @code{setring} command. @* The value of a string S can be @* 'bm' (default) - for the algorithm of Briancon and Maisonobe, @* 'lot' - for the Levandovskyy's modification of the algorithm of OT, @* 'ot' - for the algorithm of Oaku and Takayama. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. @* In the output ring: @* - the ideal LD is the needed D-module structure. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example Sannfs; shows examples " { int eng = 0; int chs = 0; // choice string algo = "bm"; string st; if ( size(#)>0 ) { if ( typeof(#[1]) == "string" ) { st = string(#[1]); if ( (st == "BM") || (st == "Bm") || (st == "bM") ||(st == "bm")) { algo = "bm"; chs = 1; } if ( (st == "OT") || (st == "Ot") || (st == "oT") || (st == "ot")) { algo = "ot"; chs = 1; } if ( (st == "LOT") || (st == "lOT") || (st == "Lot") || (st == "lot")) { algo = "lot"; chs = 1; } if (chs != 1) { // incorrect value of S print("Incorrect algorithm given, proceed with the default BM"); algo = "bm"; } // second arg if (size(#)>1) { // exists 2nd arg if ( typeof(#[2]) == "int" ) { // the case: given alg, given engine eng = int(#[2]); } else { eng = 0; } } else { // no second arg eng = 0; } } else { if ( typeof(#[1]) == "int" ) { // the case: default alg, engine eng = int(#[1]); // algo = "bm"; //is already set } else { // incorr. 1st arg algo = "bm"; } } } // size(#)=0, i.e. there is no algorithm and no engine given // eng = 0; algo = "bm"; //are already set // int ppl = printlevel-voice+2; printlevel=printlevel+1; def save = basering; if ( algo=="ot") { def @A = SannfsOT(F,eng); } else { if ( algo=="lot") { def @A = SannfsLOT(F,eng); } else { // bm = default def @A = SannfsBM(F,eng); } } printlevel=printlevel-1; return(@A); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = Sannfs(F); // here, the default BM algorithm will be used setring A; LD; } proc Sannfslog (poly F, list #) "USAGE: Sannfslog(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[1/f]*f^s NOTE: activate the output ring with the @code{setring} command. @* In the output ring D[s], the ideal LD1 is generated by the elements @* in Ann F^s in D[s], coming from logarithmic derivations. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example Sannfslog; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } int ppl = printlevel-voice+2; def save = basering; int N = nvars(basering); int Nnew = 2*N+1; int i; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether vars have admissible names list Name = RL[2]; for (i=1; i<=N; i++) { if (Name[i] == "s") { ERROR("Variable names should not include s"); } } // the ideal I ideal I = -F, jacob(F); dbprint(ppl,"// -1-1- starting the computation of syz(-F,_Dx(F))"); dbprint(ppl-1, I); matrix M = syz(I); M = transpose(M); // it is more usefull working with columns dbprint(ppl,"// -1-2- the module syz(-F,_Dx(F)) has been computed"); dbprint(ppl-1, M); // ------------ the ring @R ------------ // _x, _Dx, s; elim.ord for _x,_Dx. // now, create the names for new vars list DName; for (i=1; i<=N; i++) { DName[i] = "D"+Name[i]; // concat } tmp[1] = "s"; list NName; NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); s = "iv="; for (i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s[size(s)] = ","; s = s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2]=iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -2-1- the ring @R(_x,_Dx,s) is ready"); dbprint(ppl-1, @R); matrix M = imap(save,M); // now, create the vector [-s,_Dx] vector v = [-s]; // now s is a variable for (i=1; i<=N; i++) { v = v + var(i+N)*gen(i+1); } ideal J = ideal(M*v); // make leadcoeffs positive for (i=1; i<= ncols(J); i++) { if ( leadcoef(J[i])<0 ) { J[i] = -J[i]; } } ideal LD1 = J; kill J; export LD1; return(@R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),Dp; poly F = x4+y5+x*y4; printlevel = 0; def A = Sannfslog(F); setring A; LD1; } // JM+VL: output ring restructured into "normal" // proc Sannfslog (poly F, list #) // "USAGE: Sannfslog(f [,eng]); f a poly, eng an optional int // RETURN: ring // PURPOSE: compute the D-module structure of basering[1/f]*f^s // NOTE: activate the output ring with the @code{setring} command. // @* In the output ring D[s], the ideal LD1 is generated by the elements // @* in Ann F^s in D[s], coming from logarithmic derivations. // @* If eng <>0, @code{std} is used for Groebner basis computations, // @* otherwise, and by default @code{slimgb} is used. // DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, // @* if @code{printlevel}>=2, all the debug messages will be printed. // EXAMPLE: example Sannfslog; shows examples // " // { // int eng = 0; // if ( size(#)>0 ) // { // if ( typeof(#[1]) == "int" ) // { // eng = int(#[1]); // } // } // int ppl = printlevel-voice+2; // def save = basering; // int N = nvars(basering); // int Nnew = 2*N+1; // int i; // string s; // list RL = ringlist(basering); // list L, Lord; // list tmp; // intvec iv; // L[1] = RL[1]; // char // L[4] = RL[4]; // char, minpoly // // check whether vars have admissible names // list Name = RL[2]; // for (i=1; i<=N; i++) // { // if (Name[i] == "s") // { // ERROR("Variable names should not include s"); // } // } // // the ideal I // ideal I = -F, jacob(F); // dbprint(ppl,"// -1-1- starting the computation of syz(-F,_Dx(F))"); // dbprint(ppl-1, I); // matrix M = syz(I); // M = transpose(M); // it is more usefull working with columns // dbprint(ppl,"// -1-2- the module syz(-F,_Dx(F)) has been computed"); // dbprint(ppl-1, M); // // ------------ the ring @R ------------ // // _x, _Dx, s; elim.ord for _x,_Dx. // // now, create the names for new vars // list DName; // for (i=1; i<=N; i++) // { // DName[i] = "D"+Name[i]; // concat // } // tmp[1] = "s"; // list NName; // for (i=1; i<=N; i++) // { // NName[2*i-1] = Name[i]; // NName[2*i] = DName[i]; // //NName[2*i-1] = DName[i]; // //NName[2*i] = Name[i]; // } // NName[Nnew] = tmp[1]; // L[2] = NName; // tmp = 0; // // block ord (a(1,1),a(0,0,1,1),...,dp); // //list("a",intvec(1,1)), list("a",intvec(0,0,1,1)), ... // tmp[1] = "a"; // string // for (i=1; i<=N; i++) // { // iv[2*i-1] = 1; // iv[2*i] = 1; // tmp[2] = iv; iv = 0; // intvec // Lord[i] = tmp; // } // //list("dp",intvec(1,1,1,1,1,...)) // s = "iv="; // for (i=1; i<=Nnew; i++) // { // s = s+"1,"; // } // s[size(s)]=";"; // execute(s); // kill s; // tmp[1] = "dp"; // string // tmp[2] = iv; // intvec // Lord[N+1] = tmp; // //list("C",intvec(0)) // tmp[1] = "C"; // string // iv = 0; // tmp[2] = iv; // intvec // Lord[N+2] = tmp; // tmp = 0; // L[3] = Lord; // // we are done with the list. Now add a Plural part // def @R@ = ring(L); // setring @R@; // matrix @D[Nnew][Nnew]; // for (i=1; i<=N; i++) // { // @D[2*i-1,2*i]=1; // //@D[2*i-1,2*i]=-1; // } // def @R = nc_algebra(1,@D); // setring @R; // kill @R@; // dbprint(ppl,"// -2-1- the ring @R(_x,_Dx,s) is ready"); // dbprint(ppl-1, @R); // matrix M = imap(save,M); // // now, create the vector [-s,_Dx] // vector v = [-s]; // now s is a variable // for (i=1; i<=N; i++) // { // v = v + var(2*i)*gen(i+1); // //v = v + var(2*i-1)*gen(i+1); // } // ideal J = ideal(M*v); // // make leadcoeffs positive // for (i=1; i<= ncols(J); i++) // { // if ( leadcoef(J[i])<0 ) // { // J[i] = -J[i]; // } // } // ideal LD1 = J; // kill J; // export LD1; // return(@R); // } // example // { // "EXAMPLE:"; echo = 2; // ring r = 0,(x,y),Dp; // poly F = x^4+y^5+x*y^4; // printlevel = 0; // def A = Sannfslog(F); // setring A; // LD1; // } // alternative code for SannfsBM, renamed from annfsBM to ALTannfsBM // is superfluos - will not be included in the official documentation static proc ALTannfsBM (poly F, list #) "USAGE: ALTannfsBM(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the annihilator ideal of f^s in D[s], where D is the Weyl @* algebra, according to the algorithm by Briancon and Maisonobe NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD is the annihilator of f^s. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example ALTannfsBM; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); int Nnew = 2*N+2; int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; //char L[4] = RL[4]; //char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "t"; RName[2] = "s"; for (i=1; i<=N; i++) { for(j=1; j<=size(RName); j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include t,s"); } } } // now, create the names for new vars list DName; for (i=1; i<=N; i++) { DName[i] = "D"+Name[i]; //concat } tmp[1] = "t"; tmp[2] = "s"; list NName = tmp + Name + DName; L[2] = NName; // Name, Dname will be used further kill NName; // block ord (lp(2),dp); tmp[1] = "lp"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill s; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=t; for(i=1; i<=N; i++) { @D[2+i,N+2+i]=1; } // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); ideal I = t*F+s; poly p; for(i=1; i<=N; i++) { p = t; //t p = diff(F,var(2+i))*p; I = I, var(N+2+i) + p; } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of t in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1); kill I,J; dbprint(ppl,"// -1-3- t is eliminated"); dbprint(ppl-1, K); //K is without t // create Dn[s], where Dn is the ordinary Weyl Algebra, and put the result into it, // thus creating the ring @R2 // keep: N, i,j,s, tmp, RL setring save; Nnew = 2*N+1; // list RL = ringlist(save); //is defined earlier kill Lord, tmp, iv; L = 0; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2] // DName is defined earlier tmp[1] = "s"; list NName = Name + DName + tmp; L[2] = NName; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)] = ";"; execute(s); kill s; tmp = 0; tmp[1] = "dp"; //string tmp[2] = iv; //intvec Lord[1] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal K = imap(@R,K); option(redSB); //dbprint(ppl,"// -2-2- the final cosmetic std"); //K = engine(K,eng); //std does the job too // total cleanup kill @R; ideal LD = K; export LD; return(@R2); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z,w),Dp; poly F = x^3+y^3+z^2*w; printlevel = 0; def A = ALTannfsBM(F); setring A; LD; } proc bernsteinBM(poly F, list #) "USAGE: bernsteinBM(f [,eng]); f a poly, eng an optional int RETURN: list (of roots of the Bernstein polynomial b and their multiplicies) PURPOSE: compute the global Bernstein-Sato polynomial for a hypersurface, @* defined by f, according to the algorithm by Briancon and Maisonobe NOTE: If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example bernsteinBM; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); int Nnew = 2*N+2; int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; //char L[4] = RL[4]; //char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "t"; RName[2] = "s"; for (i=1; i<=N; i++) { for(j=1; j<=size(RName); j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include t,s"); } } } // now, create the names for new vars list DName; for (i=1; i<=N; i++) { DName[i] = "D"+Name[i]; //concat } tmp[1] = "t"; tmp[2] = "s"; list NName = tmp + Name + DName; L[2] = NName; // Name, Dname will be used further kill NName; // block ord (lp(2),dp); tmp[1] = "lp"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill s; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=t; for(i=1; i<=N; i++) { @D[2+i,N+2+i]=1; } // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); ideal I = t*F+s; poly p; for(i=1; i<=N; i++) { p = t; //t p = diff(F,var(2+i))*p; I = I, var(N+2+i) + p; } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of t in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1); kill I,J; dbprint(ppl,"// -1-3- t is eliminated"); dbprint(ppl-1, K); //K is without t // ----------- the ring @R2 ------------ // _x, _Dx,s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL setring save; Nnew = 2*N+1; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var tmp[1] = "s"; // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); string s = "iv="; for (i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; //string tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; //string s[size(s)] = ","; s = s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); MM = 0,s,MM; map R01 = @R, MM; ideal K = R01(K); kill @R, R01; poly F = imap(save,F); K = K,F; dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2"); dbprint(ppl-1, K); ideal M = engine(K,eng); ideal K2 = nselect(M,1..Nnew-1); kill K,M; dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2"); dbprint(ppl-1, K2); // the ring @R3 and the search for minimal negative int s ring @R3 = 0,s,dp; dbprint(ppl,"// -3-1- the ring @R3(s) is ready"); ideal K3 = imap(@R2,K2); kill @R2; poly p = K3[1]; dbprint(ppl,"// -3-2- factorization"); list P = factorize(p); //with constants and multiplicities ideal bs; intvec m; //the Bernstein polynomial is monic, so we are not interested in constants for (i=2; i<= size(P[1]); i++) //we delete P[1][1] and P[2][1] { bs[i-1] = P[1][i]; m[i-1] = P[2][i]; } // "--------- b-function factorizes into ---------"; P; //int sP = minIntRoot(bs,1); //dbprint(ppl,"// -3-3- minimal integer root found"); //dbprint(ppl-1, sP); // convert factors to a list of their roots and multiplicities bs = normalize(bs); bs = -subst(bs,s,0); setring save; ideal bs = imap(@R3,bs); kill @R3; list BS = bs,m; return(BS); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z,w),Dp; poly F = x^3+y^3+z^2*w; printlevel = 0; bernsteinBM(F); } // some changes proc annfsBM (poly F, list #) "USAGE: annfsBM(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[1/f]*f^s, according @* to the algorithm by Briancon and Maisonobe NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD (which is a Groebner basis) is the needed D-module structure, @* which is obtained by substituting the minimal integer root of a Bernstein @* polynomial into the s-parametric ideal; @* - the list BS is the list of roots and multiplicities of a Bernstein polynomial of f. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example annfsBM; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); int Nnew = 2*N+2; int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; //char L[4] = RL[4]; //char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "t"; RName[2] = "s"; for (i=1; i<=N; i++) { for(j=1; j<=size(RName); j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include t,s"); } } } // now, create the names for new vars list DName; for (i=1; i<=N; i++) { DName[i] = "D"+Name[i]; //concat } tmp[1] = "t"; tmp[2] = "s"; list NName = tmp + Name + DName; L[2] = NName; // Name, Dname will be used further kill NName; // block ord (lp(2),dp); tmp[1] = "lp"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill s; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=t; for(i=1; i<=N; i++) { @D[2+i,N+2+i]=1; } // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); ideal I = t*F+s; poly p; for(i=1; i<=N; i++) { p = t; //t p = diff(F,var(2+i))*p; I = I, var(N+2+i) + p; } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of t in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1); kill I,J; dbprint(ppl,"// -1-3- t is eliminated"); dbprint(ppl-1, K); //K is without t setring save; // ----------- the ring @R2 ------------ // _x, _Dx,s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL Nnew = 2*N+1; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var tmp[1] = "s"; // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); string s = "iv="; for (i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; //string tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; //string s[size(s)] = ","; s = s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); MM = 0,s,MM; map R01 = @R, MM; ideal K = R01(K); poly F = imap(save,F); K = K,F; dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2"); dbprint(ppl-1, K); ideal M = engine(K,eng); ideal K2 = nselect(M,1..Nnew-1); kill K,M; dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2"); dbprint(ppl-1, K2); // the ring @R3 and the search for minimal negative int s ring @R3 = 0,s,dp; dbprint(ppl,"// -3-1- the ring @R3(s) is ready"); ideal K3 = imap(@R2,K2); poly p = K3[1]; dbprint(ppl,"// -3-2- factorization"); list P = factorize(p); //with constants and multiplicities ideal bs; intvec m; //the Bernstein polynomial is monic, so we are not interested in constants for (i=2; i<= size(P[1]); i++) //we ignore P[1][1] (constant) and P[2][1] (its mult.) { bs[i-1] = P[1][i]; m[i-1] = P[2][i]; } // "--------- b-function factorizes into ---------"; P; int sP = minIntRoot(bs,1); dbprint(ppl,"// -3-3- minimal integer root found"); dbprint(ppl-1, sP); // convert factors to a list of their roots bs = normalize(bs); bs = -subst(bs,s,0); list BS = bs,m; //TODO: sort BS! // --------- substitute s found in the ideal --------- // --------- going back to @R and substitute --------- setring @R; ideal K2 = subst(K,s,sP); kill K; // create the ordinary Weyl algebra and put the result into it, // thus creating the ring @R4 // keep: N, i,j,s, tmp, RL setring save; Nnew = 2*N; // list RL = ringlist(save); //is defined earlier kill Lord, tmp, iv; L = 0; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]M // DName is defined earlier list NName = Name + DName; L[2] = NName; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)] = ";"; execute(s); kill s; tmp = 0; tmp[1] = "dp"; //string tmp[2] = iv; //intvec Lord[1] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R4@ = ring(L); setring @R4@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R4 = nc_algebra(1,@D); setring @R4; kill @R4@; dbprint(ppl,"// -4-1- the ring @R4(_x,_Dx) is ready"); dbprint(ppl-1, @R4); ideal K4 = imap(@R,K2); intvec saveopt=option(get); option(redSB); dbprint(ppl,"// -4-2- the final cosmetic std"); K4 = engine(K4,eng); //std does the job too // total cleanup kill @R; kill @R2; list BS = imap(@R3,BS); export BS; kill @R3; ideal LD = K4; export LD; option(set,saveopt); return(@R4); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = z*x^2+y^3; printlevel = 0; def A = annfsBM(F); setring A; LD; BS; } // replacing s with -s-1 => data is shorter // analogue of annfs0 proc annfs2(ideal I, poly F, list #) "USAGE: annfs2(I, F [,eng]); I an ideal, F a poly, eng an optional int RETURN: ring PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra, @* based on the output of Sannfs-like procedure @* annfs2 uses shorter expressions in the variable s (the idea of Noro). NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD (which is a Groebner basis) is the annihilator of f^s, @* - the list BS contains the roots with multiplicities of the BS polynomial. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise and by default @code{slimgb} is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example annfs2; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } def @R2 = basering; // we're in D_n[s], where the elim ord for s is set ideal J = NF(I,std(F)); // make leadcoeffs positive int i; J = subst(J,s,-s-1); for (i=1; i<= ncols(J); i++) { if (leadcoef(J[i]) <0 ) { J[i] = -J[i]; } } J = J,F; ideal M = engine(J,eng); int Nnew = nvars(@R2); ideal K2 = nselect(M,1..Nnew-1); int ppl = printlevel-voice+2; dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering"); dbprint(ppl-1, K2); // the ring @R3 and the search for minimal negative int s ring @R3 = 0,s,dp; dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready"); ideal K3 = imap(@R2,K2); poly p = K3[1]; dbprint(ppl,"// -2-2- factorization"); // ideal P = factorize(p,1); //without constants and multiplicities // "--------- b-function factorizes into ---------"; P; // convert factors to the list of their roots with mults // assume all factors are linear // ideal BS = normalize(P); // BS = subst(BS,s,0); // BS = -BS; list P = factorize(p); //with constants and multiplicities ideal bs; intvec m; //the Bernstein polynomial is monic, so we are not interested in constants for (i=2; i<= size(P[1]); i++) //we delete P[1][1] and P[2][1] { bs[i-1] = P[1][i]; bs[i-1] = subst(bs[i-1],s,-s-1); m[i-1] = P[2][i]; } int sP = minIntRoot(bs,1); bs = normalize(bs); bs = -subst(bs,s,0); dbprint(ppl,"// -2-3- minimal integer root found"); dbprint(ppl-1, sP); //TODO: sort BS! // --------- substitute s found in the ideal --------- // --------- going back to @R and substitute --------- setring @R2; K2 = subst(I,s,sP); // create the ordinary Weyl algebra and put the result into it, // thus creating the ring @R5 // keep: N, i,j,s, tmp, RL Nnew = Nnew - 1; // former 2*N; // list RL = ringlist(save); // is defined earlier // kill Lord, tmp, iv; list L = 0; list Lord, tmp; intvec iv; list RL = ringlist(basering); L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]M // DName is defined earlier list NName; // = RL[2]; // skip the last var 's' for (i=1; i<=Nnew; i++) { NName[i] = RL[2][i]; } L[2] = NName; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)] = ";"; execute(s); tmp = 0; tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; kill s; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R4@ = ring(L); setring @R4@; int N = Nnew div 2; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R4 = nc_algebra(1,@D); setring @R4; kill @R4@; dbprint(ppl,"// -3-1- the ring @R4 is ready"); dbprint(ppl-1, @R4); ideal K4 = imap(@R2,K2); option(redSB); dbprint(ppl,"// -3-2- the final cosmetic std"); K4 = engine(K4,eng); // std does the job too // total cleanup ideal bs = imap(@R3,bs); kill @R3; list BS = bs,m; export BS; ideal LD = K4; export LD; return(@R4); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = SannfsBM(F); setring A; LD; poly F = imap(r,F); def B = annfs2(LD,F); setring B; LD; BS; } // try to replace s with -s-1 => data is shorter as in annfs2 // and use what Macaulay2 people call reduceB strategy, that is add // not F but Tjurina ideal ; the resulting B-function // has to be multiplied with (s+1) at the very end proc annfsRB(ideal I, poly F, list #) "USAGE: annfsRB(I, F [,eng]); I an ideal, F a poly, eng an optional int RETURN: ring PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra, @* based on the output of Sannfs like procedure NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD (which is a Groebner basis) is the annihilator of f^s, @* - the list BS contains the roots with multiplicities of a Bernstein polynomial of f. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise and by default @code{slimgb} is used. @* This procedure uses in addition to F its Jacobian ideal. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example annfsRB; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } def @R2 = basering; int ppl = printlevel-voice+2; // we're in D_n[s], where the elim ord for s is set // switch to comm. ring in X's and compute the GB of Tjurina ideal dbprint(ppl,"// -1-0- creating K[x] and Tjurina ideal"); list nL = ringlist(@R2); list temp,t2; temp[1] = nL[1]; temp[4] = nL[4]; int @n = int((nvars(@R2)-1) div 2); // # of x's int i; for (i=1; i<=@n; i++) { t2[i] = nL[2][i]; } temp[2] = t2; t2 = 0; t2[1] = nL[3][1]; // more weights than vars? t2[2] = nL[3][3]; temp[3] = t2; def @R22 = ring(temp); setring @R22; poly F = imap(@R2,F); ideal J = F; for (i=1; i<=@n; i++) { J = J, diff(F,var(i)); } J = engine(J,eng); dbprint(ppl,"// -1-1- finished computing the GB of Tjurina ideal"); dbprint(ppl-1, J); setring @R2; ideal JF = imap(@R22,J); kill @R22; attrib(JF,"isSB",1); // embedded comm ring is used ideal J = NF(I,JF); dbprint(ppl,"// -1-2- finished computing the NF of I w.r.t. Tjurina ideal"); dbprint(ppl-1, J2); // make leadcoeffs positive J = subst(J,s,-s-1); for (i=1; i<= ncols(J); i++) { if (leadcoef(J[i]) <0 ) { J[i] = -J[i]; } } J = J,JF; ideal M = engine(J,eng); int Nnew = nvars(@R2); ideal K2 = nselect(M,1..Nnew-1); dbprint(ppl,"// -2-0- _x,_Dx are eliminated in basering"); dbprint(ppl-1, K2); // the ring @R3 and the search for minimal negative int s ring @R3 = 0,s,dp; dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready"); ideal K3 = imap(@R2,K2); poly p = K3[1]; p = s*p; // mult with the lost (s+1) factor dbprint(ppl,"// -2-2- factorization"); // ideal P = factorize(p,1); //without constants and multiplicities // "--------- b-function factorizes into ---------"; P; // convert factors to the list of their roots with mults // assume all factors are linear // ideal BS = normalize(P); // BS = subst(BS,s,0); // BS = -BS; list P = factorize(p); //with constants and multiplicities ideal bs; intvec m; //the Bernstein polynomial is monic, so we are not interested in constants for (i=2; i<= size(P[1]); i++) //we delete P[1][1] and P[2][1] { bs[i-1] = P[1][i]; bs[i-1] = subst(bs[i-1],s,-s-1); m[i-1] = P[2][i]; } int sP = minIntRoot(bs,1); bs = normalize(bs); bs = -subst(bs,s,0); dbprint(ppl,"// -2-3- minimal integer root found"); dbprint(ppl-1, sP); //TODO: sort BS! // --------- substitute s found in the ideal --------- // --------- going back to @R and substitute --------- setring @R2; K2 = subst(I,s,sP); // create the ordinary Weyl algebra and put the result into it, // thus creating the ring @R5 // keep: N, i,j,s, tmp, RL Nnew = Nnew - 1; // former 2*N; // list RL = ringlist(save); // is defined earlier // kill Lord, tmp, iv; list L = 0; list Lord, tmp; intvec iv; list RL = ringlist(basering); L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]M // DName is defined earlier list NName; // = RL[2]; // skip the last var 's' for (i=1; i<=Nnew; i++) { NName[i] = RL[2][i]; } L[2] = NName; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)] = ";"; execute(s); tmp = 0; tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; kill s; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R4@ = ring(L); setring @R4@; int N = Nnew div 2; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R4 = nc_algebra(1,@D); setring @R4; kill @R4@; dbprint(ppl,"// -3-1- the ring @R4 is ready"); dbprint(ppl-1, @R4); ideal K4 = imap(@R2,K2); intvec saveopt=option(get); option(redSB); dbprint(ppl,"// -3-2- the final cosmetic std"); K4 = engine(K4,eng); // std does the job too // total cleanup ideal bs = imap(@R3,bs); kill @R3; list BS = bs,m; export BS; ideal LD = K4; export LD; option(set,saveopt); return(@R4); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = SannfsBM(F); setring A; LD; // s-parametric ahhinilator poly F = imap(r,F); def B = annfsRB(LD,F); setring B; LD; BS; } proc operatorBM(poly F, list #) "USAGE: operatorBM(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the B-operator and other relevant data for Ann F^s, @* using e.g. algorithm by Briancon and Maisonobe for Ann F^s and BS. NOTE: activate the output ring with the @code{setring} command. In the output ring D[s] @* - the polynomial F is the same as the input, @* - the ideal LD is the annihilator of f^s in Dn[s], @* - the ideal LD0 is the needed D-mod structure, where LD0 = LD|s=s0, @* - the polynomial bs is the global Bernstein polynomial of f in the variable s, @* - the list BS contains all the roots with multiplicities of the global Bernstein polynomial of f, @* - the polynomial PS is an operator in Dn[s] such that PS*f^(s+1) = bs*f^s. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise and by default @code{slimgb} is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example operatorBM; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); int Nnew = 2*N+2; int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; //char L[4] = RL[4]; //char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "t"; RName[2] = "s"; for (i=1; i<=N; i++) { for(j=1; j<=size(RName); j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include t,s"); } } } // now, create the names for new vars list DName; for (i=1; i<=N; i++) { DName[i] = "D"+Name[i]; //concat } tmp[1] = "t"; tmp[2] = "s"; list NName = tmp + Name + DName; L[2] = NName; // Name, Dname will be used further kill NName; // block ord (lp(2),dp); tmp[1] = "lp"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill s; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=t; for(i=1; i<=N; i++) { @D[2+i,N+2+i]=1; } // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); ideal I = t*F+s; poly p; for(i=1; i<=N; i++) { p = t; //t p = diff(F,var(2+i))*p; I = I, var(N+2+i) + p; } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of t in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1); kill I,J; dbprint(ppl,"// -1-3- t is eliminated"); dbprint(ppl-1, K); //K is without t setring save; // ----------- the ring @R2 ------------ // _x, _Dx,s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL Nnew = 2*N+1; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var tmp[1] = "s"; // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); string s = "iv="; for (i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; //string tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; //string s[size(s)] = ","; s = s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); MM = 0,s,MM; map R01 = @R, MM; ideal K = R01(K); poly F = imap(save,F); K = K,F; dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2"); dbprint(ppl-1, K); ideal M = engine(K,eng); ideal K2 = nselect(M,1..Nnew-1); kill K,M; dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2"); dbprint(ppl-1, K2); // the ring @R3 and the search for minimal negative int s ring @R3 = 0,s,dp; dbprint(ppl,"// -3-1- the ring @R3(s) is ready"); ideal K3 = imap(@R2,K2); kill @R2; poly p = K3[1]; dbprint(ppl,"// -3-2- factorization"); list P = factorize(p); //with constants and multiplicities ideal bs; intvec m; //the Bernstein polynomial is monic, so we are not interested in constants for (i=2; i<= size(P[1]); i++) //we delete P[1][1] and P[2][1] { bs[i-1] = P[1][i]; m[i-1] = P[2][i]; } // "--------- b-function factorizes into ---------"; P; int sP = minIntRoot(bs,1); dbprint(ppl,"// -3-3- minimal integer root found"); dbprint(ppl-1, sP); // convert factors to a list of their roots with multiplicities bs = normalize(bs); bs = -subst(bs,s,0); list BS = bs,m; //TODO: sort BS! // --------- substitute s found in the ideal --------- // --------- going back to @R and substitute --------- setring @R; ideal K2 = subst(K,s,sP); // create Dn[s], where Dn is the ordinary Weyl algebra, and put the result into it, // thus creating the ring @R4 // keep: N, i,j,s, tmp, RL setring save; Nnew = 2*N+1; // list RL = ringlist(save); //is defined earlier kill Lord, tmp, iv; L = 0; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2] // DName is defined earlier tmp[1] = "s"; list NName = Name + DName + tmp; L[2] = NName; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)] = ";"; execute(s); kill s; tmp = 0; tmp[1] = "dp"; //string tmp[2] = iv; //intvec Lord[1] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R4@ = ring(L); setring @R4@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R4 = nc_algebra(1,@D); setring @R4; kill @R4@; dbprint(ppl,"// -4-1- the ring @R4(_x,_Dx,s) is ready"); dbprint(ppl-1, @R4); ideal LD0 = imap(@R,K2); ideal LD = imap(@R,K); kill @R; poly bs = imap(@R3,p); list BS = imap(@R3,BS); kill @R3; bs = normalize(bs); poly F = imap(save,F); dbprint(ppl,"// -4-2- starting the computation of PS via lift"); //better liftstd, I didn't knot it works also for Plural, liftslimgb? // liftstd may give extra coeffs in the resulting ideal matrix T = lift(F+LD,bs); poly PS = T[1,1]; dbprint(ppl,"// -4-3- an operator PS found, PS*f^(s+1) = b(s)*f^s"); dbprint(ppl-1,PS); intvec saveopt=option(get); option(redSB); dbprint(ppl,"// -4-4- the final cosmetic std"); LD0 = engine(LD0,eng); //std does the job too LD = engine(LD,eng); export F,LD,LD0,bs,BS,PS; option(set,saveopt); return(@R4); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = operatorBM(F); setring A; F; // the original polynomial itself LD; // generic annihilator LD0; // annihilator bs; // normalized Bernstein poly BS; // roots and multiplicities of the Bernstein poly PS; // the operator, s.t. PS*F^{s+1} = bs*F^s mod LD reduce(PS*F-bs,LD); // check the property of PS } // more interesting: // ring r = 0,(x,y,z,w),Dp; // poly F = x^3+y^3+z^2*w; // need: (c,<) ordering for such comp's proc operatorModulo(poly F, ideal I, poly b) "USAGE: operatorModulo(f,I,b); f a poly, I an ideal, b a poly RETURN: poly PURPOSE: compute the B-operator from the polynomial f, @* ideal I = Ann f^s and Bernstein-Sato polynomial b @* using modulo i.e. kernel of module homomorphism NOTE: The computations take place in the ring, similar to the one @* returned by Sannfs procedure. @* Note, that operator is not completely reduced wrt Ann f^{s+1}. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example operatorModulo; shows examples " { int ppl = printlevel-voice+2; def save = basering; // change the ordering on the currRing def mering = makeModElimRing(save); setring mering; poly b = imap(save, b); poly F = imap(save, F); ideal I = imap(save, I); matrix N = matrix(I); // ann f^s // matrix K = hom_kernel(AA,M,N); // option(noreturnSB)? /// matrix K = modulo(AA,N); // too slow: do it with slim! module M = b,-F; dbprint(ppl,"starting modulo computation"); module K = moduloSlim(M,N); dbprint(ppl,"finished modulo computation"); // K = transpose(K); // matrix M[3][s+2] = F,-b,I[1..s], 1,0:(s+1),0,1,0:(s); // module GM = slimgb(M); // module GMT = transpose(G); // GMT = GMT[2],GMT[3]; // modulo matrix // module K = GMT[2]; // GMT = transpose(GMT); // K = transpose(K); // matrix K = GMT; ////////////////////////////////////////////////// // now select those elts whose 0's entry is nonzero // if there is constant => done // if not => compute GB and get it module L; ideal J; int i; poly t; number n; for(i=1; i<=ncols(K); i++) { if (K[1,i]!=0) { L = L,K[i]; if ( leadmonom(K[1,i]) == 1) { t = K[2,i]; n = leadcoef(K[1,i]); t = t/n; break; // return(t); } } } if (n!=0) { // constant found setring save; poly t = imap(mering,t); kill mering; return(t); } dbprint(ppl,"no explicit constant. Start one more GB computation"); // else: compute GB and do the same L = L[2..ncols(L)]; K = slimgb(L); dbprint(ppl,"finished GB computation"); for(i=1; i<=ncols(K); i++) { if (K[1,i]!=0) { if ( leadmonom(K[1,i]) == 1) { t = K[2,i]; n = leadcoef(K[1,i]); t = t/n; // break; setring save; poly t = imap(mering,t); kill mering; return(t); } } } // we are here if no constant found "ERROR: must never get here!"; return(0); // for(i=1; i<=nrows(K); i++) // { // if (K[i,2]!=0) // { // if ( leadmonom(K[i,2]) == 1) // { // t = K[i,1]; // n = leadcoef(K[i,2]); // t = t/n; // // J = J, K[i][2]; // break; // } // } // } // ideal J = groebner(subst(I,s,s+1)); // for NF // t = NF(t,J); // "candidate:"; t; // J = subst(J,s,s-1); // // test: // if ( NF(t*F-b,J) !=0) // { // "Problem: PS does not work on F"; // } // return(t); } example { "EXAMPLE:"; echo = 2; // LIB "dmod.lib"; option(prot); option(mem); ring r = 0,(x,y),Dp; poly F = x^3+y^3+x*y^3; def A = Sannfs(F); // here we get LD = ann f^s setring A; poly F = imap(r,F); def B = annfs0(LD,F); // to obtain BS polynomial list BS = imap(B,BS); poly bs = fl2poly(BS,"s"); poly PS = operatorModulo(F,LD,bs); LD = groebner(LD); PS = NF(PS,subst(LD,s,s+1));; // reduction modulo Ann s^{s+1} size(PS); lead(PS); reduce(PS*F-bs,LD); // check the defining property of PS } proc annfsParamBM (poly F, list #) "USAGE: annfsParamBM(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the generic Ann F^s and exceptional parametric constellations @* of a polynomial with parametric coefficients with the BM algorithm NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD is the D-module structure oa Ann F^s @* - the ideal Param contains special parameters as entries @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example annfsParamBM; shows examples " { //PURPOSE: compute the list of all possible Bernstein-Sato polynomials for a polynomial with parametric coefficients, according to the algorithm by Briancon and Maisonobe // @* - the list BS is the list of roots and multiplicities of a Bernstein polynomial of f. // ***** not implented yet **** int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); int Nnew = 2*N+2; int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; //char L[4] = RL[4]; //char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "t"; RName[2] = "s"; for (i=1; i<=N; i++) { for(j=1; j<=size(RName); j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include t,s"); } } } // now, create the names for new vars list DName; for (i=1; i<=N; i++) { DName[i] = "D"+Name[i]; //concat } tmp[1] = "t"; tmp[2] = "s"; list NName = tmp + Name + DName; L[2] = NName; // Name, Dname will be used further kill NName; // block ord (lp(2),dp); tmp[1] = "lp"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill s; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=t; for(i=1; i<=N; i++) { @D[2+i,N+2+i]=1; } // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); ideal I = t*F+s; poly p; for(i=1; i<=N; i++) { p = t; //t p = diff(F,var(2+i))*p; I = I, var(N+2+i) + p; } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of t in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1); dbprint(ppl,"// -1-3- t is eliminated"); dbprint(ppl-1, K); //K is without t // ----- looking for special parameters ----- dbprint(ppl,"// -2-1- starting the computation of the transformation matrix (via lift)"); J = normalize(J); matrix T = lift(I,J); //try also with liftstd kill I,J; dbprint(ppl,"// -2-2- the transformation matrix has been computed"); dbprint(ppl-1, T); //T is the transformation matrix dbprint(ppl,"// -2-3- genericity does the job"); list lParam = genericity(T); int ip = size(lParam); int cip; string sParam; if (sParam[1]=="-") { sParam=""; } //genericity returns "-" // if no parameters exist in a basering for (cip=1; cip <= ip; cip++) { sParam = sParam + "," +lParam[cip]; } if (size(sParam) >=2) { sParam = sParam[2..size(sParam)]; // removes the 1st colon } export sParam; kill T; dbprint(ppl,"// -2-4- the special parameters has been computed"); dbprint(ppl, sParam); // create Dn[s], where Dn is the ordinary Weyl Algebra, and put the result into it, // thus creating the ring @R2 // keep: N, i,j,s, tmp, RL setring save; Nnew = 2*N+1; // list RL = ringlist(save); //is defined earlier kill Lord, tmp, iv; L = 0; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]M // DName is defined earlier tmp[1] = "s"; list NName = Name + DName + tmp; L[2] = NName; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)] = ";"; execute(s); kill s; tmp = 0; tmp[1] = "dp"; //string tmp[2] = iv; //intvec Lord[1] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -3-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal K = imap(@R,K); kill @R; intvec saveopt=option(get); option(redSB); dbprint(ppl,"// -3-2- the final cosmetic std"); K = engine(K,eng); //std does the job too ideal LD = K; export LD; if (sParam[1] == ",") { sParam = sParam[2..size(sParam)]; } // || ((sParam[1] == " ") && (sParam[2] == ","))) execute("ideal Param ="+sParam+";"); export Param; kill sParam; option(set,saveopt); return(@R2); } example { "EXAMPLE:"; echo = 2; ring r = (0,a,b),(x,y),Dp; poly F = x^2 - (y-a)*(y-b); printlevel = 0; def A = annfsParamBM(F); setring A; LD; Param; setring r; poly G = x2-(y-a)^2; // try the exceptional value b=a of parameters def B = annfsParamBM(G); setring B; LD; Param; } // *** the following example is nice, but too complicated for the documentation *** // ring r = (0,a),(x,y,z),Dp; // poly F = x^4+y^4+z^2+a*x*y*z; // printlevel = 2; //0 // def A = annfsParamBM(F); // setring A; // LD; // Param; proc annfsBMI(ideal F, list #) "USAGE: annfsBMI(F [,eng,met,us]); F an ideal, eng, met, us optional ints RETURN: ring PURPOSE: compute two kinds of Bernstein-Sato ideals, associated to @* f = F[1]*..*F[P], with the multivariate algorithm by Briancon and Maisonobe. NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD is the annihilator of F[1]^s_1*..*F[P]^s_p, @* - the list or ideal BS is a Bernstein-Sato ideal of a polynomial f = F[1]*..*F[P]. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. @* If met <0, the B-Sigma ideal (cf. Castro and Ucha, @* 'On the computation of Bernstein-Sato ideals', 2005) is computed. @* If 0 < met < P, then the ideal B_P (cf. the paper) is computed. @* Otherwise, and by default, the ideal B (cf. the paper) is computed. @* If us<>0, then syzygies-driven method is used. @* If the output ideal happens to be principal, the list of factors @* with their multiplicities is returned instead of the ideal. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example annfsBMI; shows examples " { int eng = 0; int met = 0; int usesyz = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } if ( size(#)>1 ) { if ( typeof(#[2]) == "int" ) { met = int(#[2]); } } if ( size(#)>2 ) { if ( typeof(#[3]) == "int" ) { usesyz = int(#[3]); } } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); //if F has some generators which are zero, int P = ncols(I); int P = size(F); if (P < ncols(F)) { F = simplify(F,2); } P = size(F); if (P == 0) { ERROR("zero ideal in the input"); } int Nnew = 2*N+2*P; int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; //char L[4] = RL[4]; //char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; for (j=1; j<=P; j++) { RName[j] = "t("+string(j)+")"; RName[j+P] = "s("+string(j)+")"; } for(i=1; i<=N; i++) { for(j=1; j<=size(RName); j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include t(i),s(i)"); } } } // now, create the names for new vars list DName; for(i=1; i<=N; i++) { DName[i] = "D"+Name[i]; //concat } list NName = RName + Name + DName; L[2] = NName; // Name, Dname will be used further kill NName; // block ord (lp(P),dp); tmp[1] = "lp"; //string s = "iv="; for (i=1; i<=2*P; i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; //string s = "iv="; for (i=1; i<=Nnew; i++) //actually i<=2*N { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill s; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; for (i=1; i<=P; i++) { @D[i,i+P] = t(i); } for(i=1; i<=N; i++) { @D[2*P+i,2*P+N+i] = 1; } // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(_t,_s,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I ideal F = imap(save,F); ideal I = t(1)*F[1]+s(1); for (j=2; j<=P; j++) { I = I, t(j)*F[j]+s(j); } poly p,q; for (i=1; i<=N; i++) { p=0; for (j=1; j<=P; j++) { q = t(j); q = diff(F[j],var(2*P+i))*q; p = p + q; } I = I, var(2*P+N+i) + p; } // -------- the ideal I is ready ---------- if (usesyz) { dbprint(ppl,"// -1-1-1 adding syzygy-driven elements to the ideal"); // -- form the extended Jacobian matrix; do the comps over K[x] setring save; module JC = module(transpose(jacob(F))); // NxP for (j=1; j<=P; j++) { JC[j] = JC[j] + F[j]*gen(N+j); } // matrix JAC[N+P][P]; dbprint(ppl,"// -1-1-2 computing syzygies of the extended Jacobian matrix over K[_x]"); dbprint(ppl-1, matrix(JC)); matrix SJ = transpose(syz(transpose(JC))); //or of std(syz)? dbprint(ppl,"// -1-1-3 finished computing syzygies of the ext Jacobian matrix over K[_x]"); dbprint(ppl-1, matrix(SJ)); setring @R; // add generators: first N comps d_i, then P comps s_j matrix SJ = imap(save, SJ); poly pi; for (i=1; i<=nrows(SJ); i++) { pi = 0; for (j=1; j<=N; j++) { pi = pi + SJ[i,j]*var(2*P+N+j); } for (j=1; j<=P; j++) { pi = pi + SJ[i,N+j]*s(j); } dbprint(ppl-1, "// -1-1-4 adding element:" + string(pi)); I = I, pi; } } dbprint(ppl,"// -1-2- starting the elimination of "+string(t(1..P))+" in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1..P); kill I,J; dbprint(ppl,"// -1-3- all t(i) are eliminated"); dbprint(ppl-1, K); //K is without t(i) // ----------- the ring @R2 ------------ // _x, _Dx,s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL setring save; Nnew = 2*N+P; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; //char L[4] = RL[4]; //char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var for (j=1; j<=P; j++) { tmp[j] = "s("+string(j)+")"; } // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); string s = "iv="; for (i=1; i<=Nnew-P; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; //string tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; //string s[size(s)] = ","; for (j=1; j<=P; j++) { s = s+"1,"; } s[size(s)]=";"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,_s) is ready"); dbprint(ppl-1, @R2); // ideal MM = maxideal(1); // MM = 0,s,MM; // map R01 = @R, MM; // ideal K = R01(K); ideal F = imap(save,F); // maybe ideal F = R01(I); ? ideal K = imap(@R,K); // maybe ideal K = R01(I); ? if (met <0) { //K = K,F; // to compute Bsigma (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha) K = K,F; dbprint(ppl,"// -2-1-1 computing the ideal B-Sigma from Castro-Ucha"); } if ( (met>0) && (met<=ncols(F) ) ) { /* compute the ideal B_met */ //j=2; // for example //K = K,F[j]; // to compute Bj (see "On the computation of Bernstein-Sato ideals"; Castro, Ucha) dbprint(ppl,"// -2-1-1 computing the ideal B_i from Castro-Ucha"); K = K, F[met]; } if ( ( met == 0) || (met > ncols(F) ) ) { // that is met ==0 or met> ncols(F) /* compute the ideal B */ poly f=1; for (j=1; j<=P; j++) { f = f*F[j]; } K = K,f; // to compute B (Bernstein-Sato ideal) dbprint(ppl,"// -2-1-1 computing the ideal B from Castro-Ucha"); } dbprint(ppl,"// -2-2- starting the elimination of _x,_Dx in @R2"); dbprint(ppl-1, K); ideal M = engine(K,eng); ideal K2 = nselect(M,1..Nnew-P); kill K,M; dbprint(ppl,"// -2-3- _x,_Dx are eliminated in @R2"); dbprint(ppl-1, K2); // the ring @R3 and factorize ring @R3 = 0,s(1..P),dp; dbprint(ppl,"// -3-1- the ring @R3(_s) is ready"); ideal K3 = imap(@R2,K2); if (ncols(K3)==1) { poly p = K3[1]; dbprint(ppl,"// -3-2- the Bernstein ideal is principal"); dbprint(ppl,"// -3-2-1- factorization"); // Warning: now P is an integer list Q = factorize(p); //with constants and multiplicities ideal bs; intvec m; for (i=2; i<=size(Q[1]); i++) //we delete Q[1][1] and Q[2][1] { bs[i-1] = Q[1][i]; m[i-1] = Q[2][i]; } // "--------- Q-ideal factorizes into ---------"; list(bs,m); list BS = bs,m; } else { // conjecture for some ideals: the Bernstein ideal is principal dbprint(ppl,"// -3-2- the Bernstein ideal is not principal"); ideal BS = K3; } // create the ring @R4(_x,_Dx,_s) and put the result into it, // _x, _Dx,s; ord "dp". // keep: N, i,j,s, tmp, RL setring save; Nnew = 2*N+P; // list RL = ringlist(save); //is defined earlier kill Lord, tmp, iv; L = 0; list Lord, tmp; intvec iv; L[1] = RL[1]; //char L[4] = RL[4]; //char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var for (j=1; j<=P; j++) { tmp[j] = "s("+string(j)+")"; } // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); kill s; kill NName; tmp[1] = "dp"; //string tmp[2] = iv; //intvec Lord[1] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R4@ = ring(L); setring @R4@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R4 = nc_algebra(1,@D); setring @R4; kill @R4@; dbprint(ppl,"// -4-1- the ring @R4i(_x,_Dx,_s) is ready"); dbprint(ppl-1, @R4); ideal K4 = imap(@R,K); intvec saveopt=option(get); option(redSB); dbprint(ppl,"// -4-2- the final cosmetic std"); K4 = engine(K4,eng); //std does the job too // total cleanup kill @R; kill @R2; def BS = imap(@R3,BS); export BS; kill @R3; ideal LD = K4; export LD; option(set,saveopt); return(@R4); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),Dp; ideal F = x,y,x+y; printlevel = 0; // *1* let us compute the B ideal def A = annfsBMI(F); setring A; LD; // annihilator BS; // Bernstein-Sato ideal // *2* now, let us compute B-Sigma ideal setring r; def Sigma = annfsBMI(F,0,-1); setring Sigma; print(matrix(lead(LD))); // compact form of leading // monomials from the annihilator BS; // Bernstein-Sato B-Sigma ideal: it is principal, // so factors and multiplicities are returned // *3* and now, let us compute B-i ideal setring r; def Bi = annfsBMI(F,0,3); // that is F[3]=x+y is taken setring Bi; print(matrix(lead(LD))); // compact form of leading // monomials from the annihilator BS; // the B_3 ideal: it is principal, so factors // and multiplicities are returned } proc annfsOT(poly F, list #) "USAGE: annfsOT(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[1/f]*f^s, @* according to the algorithm by Oaku and Takayama NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD (which is a Groebner basis) is the needed D-module structure, @* which is obtained by substituting the minimal integer root of a Bernstein @* polynomial into the s-parametric ideal; @* - the list BS contains roots with multiplicities of a Bernstein polynomial of f. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example annfsOT; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); int Nnew = 2*(N+2); int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "u"; RName[2] = "v"; RName[3] = "t"; RName[4] = "Dt"; for(i=1;i<=N;i++) { for(j=1; j<=size(RName);j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include u,v,t,Dt"); } } } // now, create the names for new vars tmp[1] = "u"; tmp[2] = "v"; list UName = tmp; list DName; for(i=1;i<=N;i++) { DName[i] = "D"+Name[i]; // concat } tmp = 0; tmp[1] = "t"; tmp[2] = "Dt"; list NName = UName + tmp + Name + DName; L[2] = NName; tmp = 0; // Name, Dname will be used further kill UName; kill NName; // block ord (a(1,1),dp); tmp[1] = "a"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for(i=1;i<=Nnew;i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[3,4]=1; for(i=1; i<=N; i++) { @D[4+i,N+4+i]=1; } // @D[N+3,2*(N+2)]=1; old t,Dt stuff // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); ideal I = u*F-t,u*v-1; poly p; for(i=1; i<=N; i++) { p = u*Dt; // u*Dt p = diff(F,var(4+i))*p; I = I, var(N+4+i) + p; } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of u,v in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1..2); dbprint(ppl,"// -1-3- u,v are eliminated"); dbprint(ppl-1, K); // K is without u,v setring save; // ------------ new ring @R2 ------------------ // without u,v and with the elim.ord for t,Dt // tensored with the K[s] // keep: N, i,j,s, tmp, RL Nnew = 2*N+2+1; // list RL = ringlist(save); // is defined earlier L = 0; // kill L; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]; list RName; RName[1] = "t"; RName[2] = "Dt"; // now, create the names for new var (here, s only) tmp[1] = "s"; // DName is defined earlier list NName = RName + Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (a(1,1),dp); tmp[1] = "a"; iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with a(1,1,1,1)... tmp[1] = "dp"; s = "iv="; for(i=1; i<= Nnew; i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill NName; tmp[2] = iv; Lord[2] = tmp; // extra block for s // tmp[1] = "dp"; iv = 1; // s[size(s)]= ","; s = s + "1,1,1;"; execute(s); tmp[2] = iv; // Lord[3] = tmp; kill s; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now, add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; @D[1,2] = 1; for(i=1; i<=N; i++) { @D[2+i,2+N+i] = 1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); MM = 0,0,MM; map R01 = @R, MM; ideal K = R01(K); // ideal K = imap(@R,K); // names of vars are important! poly G = t*Dt+s+1; // s is a variable here K = NF(K,std(G)),G; // -------- the ideal K_(@R2) is ready ---------- dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2"); dbprint(ppl-1, K); ideal M = engine(K,eng); ideal K2 = nselect(M,1..2); dbprint(ppl,"// -2-3- t,Dt are eliminated"); dbprint(ppl-1, K2); // dbprint(ppl-1+1," -2-4- std of K2"); // option(redSB); option(redTail); K2 = std(K2); // K2; // without t,Dt, and with s // -------- the ring @R3 ---------- // _x, _Dx, s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL setring save; Nnew = 2*N+1; // list RL = ringlist(save); // is defined earlier // kill L; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]; // now, create the names for new var (here, s only) tmp[1] = "s"; // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (a(1,1...),dp); string s = "iv="; for(i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); tmp[1] = "a"; // string tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s[size(s)]=","; s= s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R3@ = ring(L); setring @R3@; matrix @D[Nnew][Nnew]; for(i=1; i<=N; i++) { @D[i,N+i]=1; } def @R3 = nc_algebra(1,@D); setring @R3; kill @R3@; dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready"); dbprint(ppl-1, @R3); ideal MM = maxideal(1); MM = 0,0,MM; map R12 = @R2, MM; ideal K = R12(K2); poly F = imap(save,F); K = K,F; dbprint(ppl,"// -3-2- starting the elimination of _x,_Dx in @R3"); dbprint(ppl-1, K); ideal M = engine(K,eng); ideal K3 = nselect(M,1..Nnew-1); dbprint(ppl,"// -3-3- _x,_Dx are eliminated in @R3"); dbprint(ppl-1, K3); // the ring @R4 and the search for minimal negative int s ring @R4 = 0,(s),dp; dbprint(ppl,"// -4-1- the ring @R4 is ready"); ideal K4 = imap(@R3,K3); poly p = K4[1]; dbprint(ppl,"// -4-2- factorization"); //// ideal P = factorize(p,1); // without constants and multiplicities list P = factorize(p); // with constants and multiplicities ideal bs; intvec m; // the Bernstein polynomial is monic, so we are not interested in constants for (i=2; i<=size(P[1]); i++) // we delete P[1][1] and P[2][1] { bs[i-1] = P[1][i]; m[i-1] = P[2][i]; } // "------ b-function factorizes into ----------"; P; //// int sP = minIntRoot(P, 1); int sP = minIntRoot(bs,1); dbprint(ppl,"// -4-3- minimal integer root found"); dbprint(ppl-1, sP); // convert factors to a list of their roots // assume all factors are linear //// ideal BS = normalize(P); //// BS = subst(BS,s,0); //// BS = -BS; bs = normalize(bs); bs = subst(bs,s,0); bs = -bs; list BS = bs,m; // TODO: sort BS! // ------ substitute s found in the ideal ------ // ------- going back to @R2 and substitute -------- setring @R2; ideal K3 = subst(K2,s,sP); // create the ordinary Weyl algebra and put the result into it, // thus creating the ring @R5 // keep: N, i,j,s, tmp, RL setring save; Nnew = 2*N; // list RL = ringlist(save); // is defined earlier kill Lord, tmp, iv; L = 0; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]; // DName is defined earlier list NName = Name + DName; L[2] = NName; // dp ordering; string s = "iv="; for(i=1;i<=Nnew;i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); tmp = 0; tmp[1] = "dp"; // string tmp[2] = iv; //intvec Lord[1] = tmp; kill s; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R5@ = ring(L); setring @R5@; matrix @D[Nnew][Nnew]; for(i=1; i<=N; i++) { @D[i,N+i]=1; } def @R5 = nc_algebra(1,@D); setring @R5; kill @R5@; dbprint(ppl,"// -5-1- the ring @R5 is ready"); dbprint(ppl-1, @R5); ideal K5 = imap(@R2,K3); intvec saveopt=option(get); option(redSB); dbprint(ppl,"// -5-2- the final cosmetic std"); K5 = engine(K5,eng); // std does the job too // total cleanup kill @R; kill @R2; kill @R3; //// ideal BS = imap(@R4,BS); list BS = imap(@R4,BS); export BS; ideal LD = K5; kill @R4; export LD; option(set,saveopt); return(@R5); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^2+y^3+z^5; printlevel = 0; def A = annfsOT(F); setring A; LD; BS; } proc SannfsOT(poly F, list #) "USAGE: SannfsOT(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the @* 1st step of the algorithm by Oaku and Takayama in the ring D[s] NOTE: activate the output ring with the @code{setring} command. @* In the output ring D[s], the ideal LD (which is NOT a Groebner basis) @* is the needed D-module structure. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example SannfsOT; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); int Nnew = 2*(N+2); int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "u"; RName[2] = "v"; RName[3] = "t"; RName[4] = "Dt"; for(i=1;i<=N;i++) { for(j=1; j<=size(RName);j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include u,v,t,Dt"); } } } // now, create the names for new vars tmp[1] = "u"; tmp[2] = "v"; list UName = tmp; list DName; for(i=1;i<=N;i++) { DName[i] = "D"+Name[i]; // concat } tmp = 0; tmp[1] = "t"; tmp[2] = "Dt"; list NName = UName + tmp + Name + DName; L[2] = NName; tmp = 0; // Name, Dname will be used further kill UName; kill NName; // block ord (a(1,1),dp); tmp[1] = "a"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for(i=1;i<=Nnew;i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[3,4]=1; for(i=1; i<=N; i++) { @D[4+i,N+4+i]=1; } // @D[N+3,2*(N+2)]=1; old t,Dt stuff // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(u,v,t,Dt,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); ideal I = u*F-t,u*v-1; poly p; for(i=1; i<=N; i++) { p = u*Dt; // u*Dt p = diff(F,var(4+i))*p; I = I, var(N+4+i) + p; } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of u,v in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1..2); dbprint(ppl,"// -1-3- u,v are eliminated"); dbprint(ppl-1, K); // K is without u,v setring save; // ------------ new ring @R2 ------------------ // without u,v and with the elim.ord for t,Dt // tensored with the K[s] // keep: N, i,j,s, tmp, RL Nnew = 2*N+2+1; // list RL = ringlist(save); // is defined earlier L = 0; // kill L; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]; list RName; RName[1] = "t"; RName[2] = "Dt"; // now, create the names for new var (here, s only) tmp[1] = "s"; // DName is defined earlier list NName = RName + Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (a(1,1),dp); tmp[1] = "a"; iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with a(1,1,1,1)... tmp[1] = "dp"; s = "iv="; for(i=1; i<= Nnew; i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill NName; tmp[2] = iv; Lord[2] = tmp; // extra block for s // tmp[1] = "dp"; iv = 1; // s[size(s)]= ","; s = s + "1,1,1;"; execute(s); tmp[2] = iv; // Lord[3] = tmp; kill s; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now, add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; @D[1,2] = 1; for(i=1; i<=N; i++) { @D[2+i,2+N+i] = 1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(t,Dt,_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); MM = 0,0,MM; map R01 = @R, MM; ideal K = R01(K); // ideal K = imap(@R,K); // names of vars are important! poly G = t*Dt+s+1; // s is a variable here K = NF(K,std(G)),G; // -------- the ideal K_(@R2) is ready ---------- dbprint(ppl,"// -2-2- starting the elimination of t,Dt in @R2"); dbprint(ppl-1, K); ideal M = engine(K,eng); ideal K2 = nselect(M,1..2); dbprint(ppl,"// -2-3- t,Dt are eliminated"); dbprint(ppl-1, K2); K2 = engine(K2,eng); setring save; // ----------- the ring @R3 ------------ // _x, _Dx,s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL Nnew = 2*N+1; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var tmp[1] = "s"; // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); string s = "iv="; for (i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s[size(s)] = ","; s = s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2]=iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R3@ = ring(L); setring @R3@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R3 = nc_algebra(1,@D); setring @R3; kill @R3@; dbprint(ppl,"// -3-1- the ring @R3(_x,_Dx,s) is ready"); dbprint(ppl-1, @R3); ideal MM = maxideal(1); MM = 0,s,MM; map R01 = @R2, MM; ideal K2 = R01(K2); // total cleanup ideal LD = K2; // make leadcoeffs positive for (i=1; i<= ncols(LD); i++) { if (leadcoef(LD[i]) <0 ) { LD[i] = -LD[i]; } } export LD; kill @R; kill @R2; return(@R3); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = SannfsOT(F); setring A; LD; } proc SannfsBM(poly F, list #) "USAGE: SannfsBM(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the @* 1st step of the algorithm by Briancon and Maisonobe in the ring D[s]. NOTE: activate the output ring with the @code{setring} command. @* In the output ring D[s], the ideal LD (which is NOT a Groebner basis) is @* the needed D-module structure. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example SannfsBM; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); int Nnew = 2*N+2; int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "t"; RName[2] = "s"; for(i=1;i<=N;i++) { for(j=1; j<=size(RName);j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include t,s"); } } } // now, create the names for new vars list DName; for(i=1;i<=N;i++) { DName[i] = "D"+Name[i]; // concat } tmp[1] = "t"; tmp[2] = "s"; list NName = tmp + Name + DName; L[2] = NName; // Name, Dname will be used further kill NName; // block ord (lp(2),dp); tmp[1] = "lp"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for(i=1;i<=Nnew;i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill s; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=t; for(i=1; i<=N; i++) { @D[2+i,N+2+i]=1; } // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(t,s,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); ideal I = t*F+s; poly p; for(i=1; i<=N; i++) { p = t; // t p = diff(F,var(2+i))*p; I = I, var(N+2+i) + p; } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of t in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1); dbprint(ppl,"// -1-3- t is eliminated"); dbprint(ppl-1, K); // K is without t K = engine(K,eng); // std does the job too // now, we must change the ordering // and create a ring without t, Dt // setring S; // ----------- the ring @R3 ------------ // _x, _Dx,s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL Nnew = 2*N+1; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; list L=imap(save,L); list RL=imap(save,RL); L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var tmp[1] = "s"; // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); string s = "iv="; for (i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s[size(s)] = ","; s = s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2]=iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); MM = 0,s,MM; map R01 = @R, MM; ideal K = R01(K); // total cleanup ideal LD = K; // make leadcoeffs positive for (i=1; i<= ncols(LD); i++) { if (leadcoef(LD[i]) <0 ) { LD[i] = -LD[i]; } } export LD; kill @R; return(@R2); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = SannfsBM(F); setring A; LD; } static proc safeVarName (string s, list #) { string S; int cv = 1; if (size(#)>1) { if (#[1]=="v") { cv = 0; S = varstr(basering); } if (#[1]=="c") { cv = 0; S = charstr(basering); } } if (cv) { S = charstr(basering) + "," + varstr(basering); } S = "," + S + ","; s = "," + s + ","; while (find(S,s) <> 0) { s[1] = "@"; s = "," + s; } s = s[2..size(s)-1]; return(s) } proc SannfsBFCT(poly F, list #) "USAGE: SannfsBFCT(f [,a,b,c]); f a poly, a,b,c optional ints RETURN: ring PURPOSE: compute a Groebner basis either of Ann(f^s)+ or of @* Ann(f^s)+ in D[s] NOTE: Activate the output ring with the @code{setring} command. @* This procedure, unlike SannfsBM, returns the ring D[s] with an anti- @* elimination ordering for s. @* The output ring contains an ideal @code{LD}, being a Groebner basis @* either of Ann(f^s)+, if a=0 (and by default), or of @* Ann(f^s)+, otherwise. @* Here, f_i stands for the i-th partial derivative of f. @* If b<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. @* If c<>0, @code{std} is used for Groebner basis computations of @* ideals when I is already a Groebner basis of . @* Otherwise, and by default the engine determined by the switch b is @* used. Note that in the case c<>0, the choice for b will be @* overwritten only for the types of ideals mentioned above. @* This means that if b<>0, specifying c has no effect. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example SannfsBFCT; shows examples " { int addPD,eng,stdsum; if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { addPD = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { eng = int(#[2]); } if (size(#)>2) { if (typeof(#[3])=="int" || typeof(#[3])=="number") { stdsum = int(#[3]); } } } } int ppl = printlevel-voice+2; def save = basering; int N = nvars(save); intvec optSave = option(get); int i,j; list RL = ringlist(save); // ----- step 1: compute syzigies intvec iv; list L,Lord; iv = 1:N; Lord[1] = list("dp",iv); iv = 0; Lord[2] = list("C",iv); L = RL; L[3] = Lord; def @RM = ring(L); kill L,Lord; setring @RM; option(redSB); option(redTail); def RM = makeModElimRing(@RM); setring RM; poly F = imap(save,F); ideal J = jacob(F); J = F,J; dbprint(ppl,"// -1-1- Starting the computation of syz(F,_Dx(F))"); dbprint(ppl-1, J); module M = syz(J); dbprint(ppl,"// -1-2- The module syz(F,_Dx(F)) has been computed"); dbprint(ppl-1, M); dbprint(ppl,"// -1-3- Starting GB computation of syz(F,_Dx(F))"); M = engine(M,eng); dbprint(ppl,"// -1-4- GB computation finished"); dbprint(ppl-1, M); // ----- step 2: compute part of Ann(F^s) setring save; option(set,optSave); module M = imap(RM,M); kill optSave,RM; // ----- create D[s] int Nnew = 2*N+1; list L, Lord; // ----- keep char, minpoly L[1] = RL[1]; L[4] = RL[4]; // ----- create names for new vars list Name = RL[2]; string newVar@s = safeVarName("s"); if (newVar@s[1] == "@") { print("Name s already assigned to parameter/ringvar."); print("Using " + newVar@s + " instead.") } list DName; for (i=1; i<=N; i++) { DName[i] = safeVarName("D" + Name[i]); } L[2] = list(newVar@s) + Name + DName; // ----- create ordering // --- anti-elimination ordering for s iv = 1; Lord[1] = list("dp",iv); iv = 1:(2*N); Lord[2] = list("dp",iv); iv = 0; Lord[3] = list("C",iv); L[3] = Lord; // ----- create commutative ring def @Ds = ring(L); kill L,Lord; setring @Ds; // ----- create nc relations matrix Drel[Nnew][Nnew]; for (i=1; i<=N; i++) { Drel[i+1,N+1+i] = 1; } def Ds = nc_algebra(1,Drel); setring Ds; kill @Ds; dbprint(ppl,"// -2-1- The ring D[s] is ready"); dbprint(ppl-1, Ds); matrix M = imap(save,M); vector v = var(1)*gen(1); for (i=1; i<=N; i++) { v = v + var(i+1+N)*gen(i+1); //[s,_Dx] } ideal J = transpose(M)*v; kill M,v; dbprint(ppl,"// -2-2- Compute part of Ann(F^s)"); dbprint(ppl-1, J); J = engine(J,eng); dbprint(ppl,"// -2-3- GB computation finished"); dbprint(ppl-1, J); // ----- step 3: the full annihilator // ----- create D setring save; Nnew = 2*N+2; list L, Lord; // ----- keep char, minpoly L[1] = RL[1]; L[4] = RL[4]; // ----- create vars string newVar@t = safeVarName("t"); L[2] = list(newVar@t,newVar@s) + DName + Name; // ----- create ordering for elimination of t // block ord (lp(2),dp); iv = 1,1; Lord[1] = list("lp",iv); iv = 1:Nnew; Lord[2] = list("dp",iv); iv = 0; Lord[3] = list("C",iv); L[3] = Lord; def @Dts = ring(L); kill RL,L,Lord,Name,DName,newVar@s,newVar@t; setring @Dts; // ----- create nc relations matrix Drel[Nnew][Nnew]; Drel[1,2] = var(1); for(i=1; i<=N; i++) { Drel[2+i,N+2+i]=-1; } def Dts = nc_algebra(1,Drel); setring Dts; kill @Dts; dbprint(ppl,"// -3-1- The ring D is ready"); dbprint(ppl-1, Dts); // ----- create the ideal I following BM poly F = imap(save,F); ideal I = var(1)*F + var(2); // = t*F + s poly p; for(i=1; i<=N; i++) { p = var(1)*diff(F,var(N+2+i)) + var(2+i); // = t*F_i + D_i I[i+1] = p; } // ----- add already computed part to it ideal MM = var(2); // s for (i=1; i<=N; i++) { MM[1+i] = var(2+N+i); // _x MM[1+N+i] = var(2+i); // _Dx } map Ds2Dts = Ds,MM; ideal J = Ds2Dts(J); attrib(J,"isSB",1); kill MM,Ds2Dts; // ----- start the elimination dbprint(ppl,"// -3-2- Starting the elimination of t in D"); dbprint(ppl-1, I); if (stdsum || eng <> 0) { I = std(J,I); } else { I = J,I; I = engine(I,eng); } kill J; I = nselect(I,1); dbprint(ppl,"// -3-3- t is eliminated"); dbprint(ppl-1, I); // I is without t // ----- step 4: add F // ----- back to D[s] setring Ds; ideal MM = 0,var(1); // 0,s for (i=1; i<=N; i++) { MM[2+i] = var(1+N+i); // _Dx MM[2+N+i] = var(1+i); // _x } map Dts2Ds = Dts, MM; ideal LD = Dts2Ds(I); kill J,Dts,Dts2Ds,MM; dbprint(ppl,"// -4-1- Starting cosmetic Groebner computation"); LD = engine(LD,eng); dbprint(ppl,"// -4-2- Finished cosmetic Groebner computation"); dbprint(ppl-1, LD); // ----- use reduction trick as Macaulay2 does: compute b(s)/(s+1) by adding all partial derivations also ideal J; if (addPD) { setring @RM; poly F = imap(save,F); ideal J = jacob(F); J = F,J; dbprint(ppl,"// -4-2-1- Start GB computation "); J = engine(J,eng); dbprint(ppl,"// -4-2-2- Finished GB computation "); dbprint(ppl-1, J); setring Ds; J = imap(@RM,J); attrib(J,"isSB",1); dbprint(ppl,"// -4-3- Start GB computations for Ann f^s + "); } else { J = imap(save,F); dbprint(ppl,"// -4-3- Start GB computations for Ann f^s + "); } kill @RM; // ----- the really hard part if (stdsum || eng <> 0) { LD = std(LD,J); } else { LD = LD,J; LD = engine(LD,eng); } if (addPD) { dbprint(ppl,"// -4-4- Finished GB computations for Ann f^s + "); } else { dbprint(ppl,"// -4-4- Finished GB computations for Ann f^s + "); } dbprint(ppl-1, LD); export LD; return(Ds); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z,w),Dp; poly F = x^3+y^3+z^3*w; // compute Ann(F^s)+ using slimgb only def A = SannfsBFCT(F); setring A; A; LD; // the Bernstein-Sato poly of F: vec2poly(pIntersect(s,LD)); // a fancier example: def R = reiffen(4,5); setring R; RC; // the Reiffen curve in 4,5 // compute Ann(RC^s)+ // using std for GB computations of ideals // where I is already a GB of // and slimgb for other ideals def B = SannfsBFCT(RC,1,0,1); setring B; // the Bernstein-Sato poly of RC: (s-1)*vec2poly(pIntersect(s,LD)); } proc SannfsBFCTstd(poly F, list #) "USAGE: SannfsBFCTstd(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute Ann f^s and Groebner basis of Ann f^s+f in D[s] NOTE: activate the output ring with the @code{setring} command. @* This procedure, unlike SannfsBM, returns a ring with the degrevlex @* ordering in all variables. @* In the ring D[s], the ideal LD (which IS a Groebner basis) is the needed ideal. @* In this procedure @code{std} is used for Groebner basis computations. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example SannfsBFCTstd; shows examples " { // DEBUG INFO: ordering on the output ring = dp, // use std(K,F); for reusing the std property of K int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); int Nnew = 2*N+2; int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "@t"; RName[2] = "@s"; for(i=1;i<=N;i++) { for(j=1; j<=size(RName);j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include @t,@s"); } } } // now, create the names for new vars list DName; for(i=1;i<=N;i++) { DName[i] = "D"+Name[i]; // concat } tmp[1] = "t"; tmp[2] = "s"; list NName = tmp + DName + Name ; L[2] = NName; // Name, Dname will be used further kill NName; // block ord (lp(2),dp); tmp[1] = "lp"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for(i=1;i<=Nnew;i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); kill s; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=t; for(i=1; i<=N; i++) { @D[2+i,N+2+i]=-1; } // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(t,s,_Dx,_x) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); ideal I = t*F+s; poly p; for(i=1; i<=N; i++) { p = t; // t p = diff(F,var(N+2+i))*p; I = I, var(2+i) + p; } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of t in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1); dbprint(ppl,"// -1-3- t is eliminated"); dbprint(ppl-1, K); // K is without t K = engine(K,eng); // std does the job too // now, we must change the ordering // and create a ring without t // setring S; // ----------- the ring @R3 ------------ // _Dx,_x,s; +fast ord ! // keep: N, i,j,s, tmp, RL Nnew = 2*N+1; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; list L=imap(save,L); list RL=imap(save,RL); L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var tmp[1] = "s"; // DName is defined earlier list NName = DName + Name + tmp; L[2] = NName; tmp = 0; // just dp // block ord (dp(N),dp); string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; kill s; kill NName; tmp[1] = "C"; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=-1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_Dx,_x,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); MM = 0,s,MM; map R01 = @R, MM; ideal K = R01(K); // total cleanup poly F = imap(save, F); // ideal LD = K,F; dbprint(ppl,"// -2-2- start GB computations for Ann f^s + f"); // dbprint(ppl-1, LD); ideal LD = std(K,F); // LD = engine(LD,eng); dbprint(ppl,"// -2-3- finished GB computations for Ann f^s + f"); dbprint(ppl-1, LD); // make leadcoeffs positive for (i=1; i<= ncols(LD); i++) { if (leadcoef(LD[i]) <0 ) { LD[i] = -LD[i]; } } export LD; kill @R; return(@R2); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z,w),Dp; poly F = x^3+y^3+z^3*w; printlevel = 0; def A = SannfsBFCT(F); setring A; intvec v = 1,2,3,4,5,6,7,8; // are there polynomials, depending on s only? nselect(LD,v); // a fancier example: def R = reiffen(4,5); setring R; v = 1,2,3,4; RC; // the Reiffen curve in 4,5 def B = SannfsBFCT(RC); setring B; // Are there polynomials, depending on s only? nselect(LD,v); // It is not the case. Are there leading monomials in s only? nselect(lead(LD),v); } // use a finer ordering proc SannfsLOT(poly F, list #) "USAGE: SannfsLOT(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the @* Levandovskyy's modification of the algorithm by Oaku and Takayama in D[s] NOTE: activate the output ring with the @code{setring} command. @* In the ring D[s], the ideal LD (which is NOT a Groebner basis) is @* the needed D-module structure. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example SannfsLOT; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); // int Nnew = 2*(N+2); int Nnew = 2*(N+1)+1; //removed u,v; added s int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; // RName[1] = "u"; // RName[2] = "v"; RName[1] = "t"; RName[2] = "Dt"; for(i=1;i<=N;i++) { for(j=1; j<=size(RName);j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include t,Dt"); } } } // now, create the names for new vars // tmp[1] = "u"; // tmp[2] = "v"; // list UName = tmp; list DName; for(i=1;i<=N;i++) { DName[i] = "D"+Name[i]; // concat } tmp = 0; tmp[1] = "t"; tmp[2] = "Dt"; list SName ; SName[1] = "s"; // list NName = tmp + Name + DName + SName; list NName = tmp + SName + Name + DName; L[2] = NName; tmp = 0; // Name, Dname will be used further // kill UName; kill NName; // block ord (a(1,1),dp); tmp[1] = "a"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with a(0,0,1) tmp[1] = "a"; // string iv = 0,0,1; tmp[2] = iv; //intvec Lord[2] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for(i=1;i<=Nnew;i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); tmp[2] = iv; Lord[3] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[4] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=1; for(i=1; i<=N; i++) { @D[3+i,N+3+i]=1; } // ADD [s,t]=-t, [s,Dt]=Dt @D[1,3] = -var(1); @D[2,3] = var(2); // @D[N+3,2*(N+2)]=1; old t,Dt stuff // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(t,Dt,s,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); // ideal I = u*F-t,u*v-1; ideal I = F-t; poly p; for(i=1; i<=N; i++) { // p = u*Dt; // u*Dt p = Dt; p = diff(F,var(3+i))*p; I = I, var(N+3+i) + p; } // I = I, var(1)*var(2) + var(Nnew) +1; // reduce it with t-f!!! // t*Dt + s +1 reduced with t-f gives f*Dt + s I = I, F*var(2) + var(3); // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of t,Dt in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1..2); dbprint(ppl,"// -1-3- t,Dt are eliminated"); dbprint(ppl-1, K); // K is without t, Dt K = engine(K,eng); // std does the job too // now, we must change the ordering // and create a ring without t, Dt setring save; // ----------- the ring @R3 ------------ // _x, _Dx,s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL Nnew = 2*N+1; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var tmp[1] = "s"; // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); // string s is already defined s = "iv="; for (i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s[size(s)] = ","; s = s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2]=iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); // MM = 0,s,MM; MM = 0,0,s,MM[1..size(MM)-1]; map R01 = @R, MM; ideal K = R01(K); // total cleanup ideal LD = K; // make leadcoeffs positive for (i=1; i<= ncols(LD); i++) { if (leadcoef(LD[i]) <0 ) { LD[i] = -LD[i]; } } export LD; kill @R; return(@R2); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = SannfsLOT(F); setring A; LD; } /* proc SannfsLOTold(poly F, list #) "USAGE: SannfsLOT(f [,eng]); f a poly, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to the Levandovskyy's modification of the algorithm by Oaku and Takayama in the ring D[s], where D is the Weyl algebra NOTE: activate the output ring with the @code{setring} command. @* In the ring D[s], the ideal LD (which is NOT a Groebner basis) is the needed D-module structure. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example SannfsLOT; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } // returns a list with a ring and an ideal LD in it int ppl = printlevel-voice+2; // printf("plevel :%s, voice: %s",printlevel,voice); def save = basering; int N = nvars(basering); // int Nnew = 2*(N+2); int Nnew = 2*(N+1)+1; //removed u,v; added s int i,j; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; // RName[1] = "u"; // RName[2] = "v"; RName[1] = "t"; RName[2] = "Dt"; for(i=1;i<=N;i++) { for(j=1; j<=size(RName);j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include t,Dt"); } } } // now, create the names for new vars // tmp[1] = "u"; // tmp[2] = "v"; // list UName = tmp; list DName; for(i=1;i<=N;i++) { DName[i] = "D"+Name[i]; // concat } tmp = 0; tmp[1] = "t"; tmp[2] = "Dt"; list SName ; SName[1] = "s"; // list NName = UName + tmp + Name + DName; list NName = tmp + Name + DName + SName; L[2] = NName; tmp = 0; // Name, Dname will be used further // kill UName; kill NName; // block ord (a(1,1),dp); tmp[1] = "a"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for(i=1;i<=Nnew;i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=1; for(i=1; i<=N; i++) { @D[2+i,N+2+i]=1; } // ADD [s,t]=-t, [s,Dt]=Dt @D[1,Nnew] = -var(1); @D[2,Nnew] = var(2); // @D[N+3,2*(N+2)]=1; old t,Dt stuff // L[5] = matrix(UpOneMatrix(Nnew)); // L[6] = @D; def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(t,Dt,_x,_Dx,s) is ready"); dbprint(ppl-1, @R); // create the ideal I poly F = imap(save,F); // ideal I = u*F-t,u*v-1; ideal I = F-t; poly p; for(i=1; i<=N; i++) { // p = u*Dt; // u*Dt p = Dt; p = diff(F,var(2+i))*p; I = I, var(N+2+i) + p; } // I = I, var(1)*var(2) + var(Nnew) +1; // reduce it with t-f!!! // t*Dt + s +1 reduced with t-f gives f*Dt + s I = I, F*var(2) + var(Nnew); // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of t,Dt in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1..2); dbprint(ppl,"// -1-3- t,Dt are eliminated"); dbprint(ppl-1, K); // K is without t, Dt K = engine(K,eng); // std does the job too // now, we must change the ordering // and create a ring without t, Dt setring save; // ----------- the ring @R3 ------------ // _x, _Dx,s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL Nnew = 2*N+1; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var tmp[1] = "s"; // DName is defined earlier list NName = Name + DName + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); // string s is already defined s = "iv="; for (i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s[size(s)] = ","; s = s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2]=iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); MM = 0,s,MM; map R01 = @R, MM; ideal K = R01(K); // total cleanup ideal LD = K; // make leadcoeffs positive for (i=1; i<= ncols(LD); i++) { if (leadcoef(LD[i]) <0 ) { LD[i] = -LD[i]; } } export LD; kill @R; return(@R2); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = SannfsLOTold(F); setring A; LD; } */ proc annfsLOT(poly F, list #) "USAGE: annfsLOT(F [,eng]); F a poly, eng an optional int RETURN: ring PURPOSE: compute the D-module structure of basering[1/f]*f^s, according to @* the Levandovskyy's modification of the algorithm by Oaku and Takayama NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD (which is a Groebner basis) is the needed D-module structure, @* which is obtained by substituting the minimal integer root of a Bernstein @* polynomial into the s-parametric ideal; @* - the list BS contains the roots with multiplicities of BS polynomial of f. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise and by default @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example annfsLOT; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } printlevel=printlevel+1; def save = basering; def @A = SannfsLOT(F,eng); setring @A; poly F = imap(save,F); def B = annfs0(LD,F,eng); return(B); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = z*x^2+y^3; printlevel = 0; def A = annfsLOT(F); setring A; LD; BS; } proc annfs0(ideal I, poly F, list #) "USAGE: annfs0(I, F [,eng]); I an ideal, F a poly, eng an optional int RETURN: ring PURPOSE: compute the annihilator ideal of f^s in the Weyl Algebra, based @* on the output of Sannfs-like procedure NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD (which is a Groebner basis) is the annihilator of f^s, @* - the list BS contains the roots with multiplicities of BS polynomial of f. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise and by default @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example annfs0; shows examples " { int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } def @R2 = basering; // we're in D_n[s], where the elim ord for s is set ideal J = NF(I,std(F)); // make leadcoeffs positive int i; for (i=1; i<= ncols(J); i++) { if (leadcoef(J[i]) <0 ) { J[i] = -J[i]; } } J = J,F; ideal M = engine(J,eng); int Nnew = nvars(@R2); ideal K2 = nselect(M,1..Nnew-1); int ppl = printlevel-voice+2; dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering"); dbprint(ppl-1, K2); // the ring @R3 and the search for minimal negative int s ring @R3 = 0,s,dp; dbprint(ppl,"// -2-1- the ring @R3 i.e. K[s] is ready"); ideal K3 = imap(@R2,K2); poly p = K3[1]; dbprint(ppl,"// -2-2- factorization"); // ideal P = factorize(p,1); //without constants and multiplicities // "--------- b-function factorizes into ---------"; P; // convert factors to the list of their roots with mults // assume all factors are linear // ideal BS = normalize(P); // BS = subst(BS,s,0); // BS = -BS; list P = factorize(p); //with constants and multiplicities ideal bs; intvec m; //the Bernstein polynomial is monic, so we are not interested in constants for (i=2; i<= size(P[1]); i++) //we delete P[1][1] and P[2][1] { bs[i-1] = P[1][i]; m[i-1] = P[2][i]; } int sP = minIntRoot(bs,1); bs = normalize(bs); bs = -subst(bs,s,0); dbprint(ppl,"// -2-3- minimal integer root found"); dbprint(ppl-1, sP); //TODO: sort BS! // --------- substitute s found in the ideal --------- // --------- going back to @R and substitute --------- setring @R2; K2 = subst(I,s,sP); // create the ordinary Weyl algebra and put the result into it, // thus creating the ring @R5 // keep: N, i,j,s, tmp, RL Nnew = Nnew - 1; // former 2*N; // list RL = ringlist(save); // is defined earlier // kill Lord, tmp, iv; list L = 0; list Lord, tmp; intvec iv; list RL = ringlist(basering); L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]M // DName is defined earlier list NName; // = RL[2]; // skip the last var 's' for (i=1; i<=Nnew; i++) { NName[i] = RL[2][i]; } L[2] = NName; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)] = ";"; execute(s); tmp = 0; tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; kill s; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R4@ = ring(L); setring @R4@; int N = Nnew div 2; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R4 = nc_algebra(1,@D); setring @R4; kill @R4@; dbprint(ppl,"// -3-1- the ring @R4 is ready"); dbprint(ppl-1, @R4); ideal K4 = imap(@R2,K2); intvec saveopt=option(get); option(redSB); dbprint(ppl,"// -3-2- the final cosmetic std"); K4 = engine(K4,eng); // std does the job too // total cleanup ideal bs = imap(@R3,bs); kill @R3; list BS = bs,m; export BS; ideal LD = K4; export LD; option(set,saveopt); return(@R4); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = SannfsBM(F); setring A; // alternatively, one can use SannfsOT or SannfsLOT LD; poly F = imap(r,F); def B = annfs0(LD,F); setring B; LD; BS; } // proc annfsgms(poly F, list #) // "USAGE: annfsgms(f [,eng]); f a poly, eng an optional int // ASSUME: f has an isolated critical point at 0 // RETURN: ring // PURPOSE: compute the D-module structure of basering[1/f]*f^s // NOTE: activate the output ring with the @code{setring} command. In this ring, // @* - the ideal LD is the needed D-mod structure, // @* - the ideal BS is the list of roots of a Bernstein polynomial of f. // @* If eng <>0, @code{std} is used for Groebner basis computations, // @* otherwise (and by default) @code{slimgb} is used. // @* If printlevel=1, progress debug messages will be printed, // @* if printlevel>=2, all the debug messages will be printed. // EXAMPLE: example annfsgms; shows examples // " // { // LIB "gmssing.lib"; // int eng = 0; // if ( size(#)>0 ) // { // if ( typeof(#[1]) == "int" ) // { // eng = int(#[1]); // } // } // int ppl = printlevel-voice+2; // // returns a ring with the ideal LD in it // def save = basering; // // compute the Bernstein polynomial from gmssing.lib // list RL = ringlist(basering); // // in the descr. of the ordering, replace "p" by "s" // list NL = convloc(RL); // // create a ring with the ordering, converted to local // def @LR = ring(NL); // setring @LR; // poly F = imap(save, F); // ideal B = bernstein(F)[1]; // // since B may not contain (s+1) [following gmssing.lib] // // add it! // B = B,-1; // B = simplify(B,2+4); // erase zero and repeated entries // // find the minimal integer value // int S = minIntRoot(B,0); // dbprint(ppl,"// -0- minimal integer root found"); // dbprint(ppl-1,S); // setring save; // int N = nvars(basering); // int Nnew = 2*(N+2); // int i,j; // string s; // // list RL = ringlist(basering); // list L, Lord; // list tmp; // intvec iv; // L[1] = RL[1]; // char // L[4] = RL[4]; // char, minpoly // // check whether vars have admissible names // list Name = RL[2]; // list RName; // RName[1] = "u"; // RName[2] = "v"; // RName[3] = "t"; // RName[4] = "Dt"; // for(i=1;i<=N;i++) // { // for(j=1; j<=size(RName);j++) // { // if (Name[i] == RName[j]) // { // ERROR("Variable names should not include u,v,t,Dt"); // } // } // } // // now, create the names for new vars // // tmp[1] = "u"; tmp[2] = "v"; tmp[3] = "t"; tmp[4] = "Dt"; // list UName = RName; // list DName; // for(i=1;i<=N;i++) // { // DName[i] = "D"+Name[i]; // concat // } // list NName = UName + Name + DName; // L[2] = NName; // tmp = 0; // // Name, Dname will be used further // kill UName; // kill NName; // // block ord (a(1,1),dp); // tmp[1] = "a"; // string // iv = 1,1; // tmp[2] = iv; //intvec // Lord[1] = tmp; // // continue with dp 1,1,1,1... // tmp[1] = "dp"; // string // s = "iv="; // for(i=1; i<=Nnew; i++) // need really all vars! // { // s = s+"1,"; // } // s[size(s)]= ";"; // execute(s); // tmp[2] = iv; // Lord[2] = tmp; // tmp[1] = "C"; // iv = 0; // tmp[2] = iv; // Lord[3] = tmp; // tmp = 0; // L[3] = Lord; // // we are done with the list // def @R = ring(L); // setring @R; // matrix @D[Nnew][Nnew]; // @D[3,4] = 1; // t,Dt // for(i=1; i<=N; i++) // { // @D[4+i,4+N+i]=1; // } // // L[5] = matrix(UpOneMatrix(Nnew)); // // L[6] = @D; // nc_algebra(1,@D); // dbprint(ppl,"// -1-1- the ring @R is ready"); // dbprint(ppl-1,@R); // // create the ideal // poly F = imap(save,F); // ideal I = u*F-t,u*v-1; // poly p; // for(i=1; i<=N; i++) // { // p = u*Dt; // u*Dt // p = diff(F,var(4+i))*p; // I = I, var(N+4+i) + p; // Dx, Dy // } // // add the relations between t,Dt and s // // I = I, t*Dt+1+S; // // -------- the ideal I is ready ---------- // dbprint(ppl,"// -1-2- starting the elimination of u,v in @R"); // ideal J = engine(I,eng); // ideal K = nselect(J,1..2); // dbprint(ppl,"// -1-3- u,v are eliminated in @R"); // dbprint(ppl-1,K); // without u,v: not yet our answer // //----- create a ring with elim.ord for t,Dt ------- // setring save; // // ------------ new ring @R2 ------------------ // // without u,v and with the elim.ord for t,Dt // // keep: N, i,j,s, tmp, RL // Nnew = 2*N+2; // // list RL = ringlist(save); // is defined earlier // kill Lord,tmp,iv, RName; // L = 0; // list Lord, tmp; // intvec iv; // L[1] = RL[1]; // char // L[4] = RL[4]; // char, minpoly // // check whether vars have admissible names -> done earlier // // list Name = RL[2]; // list RName; // RName[1] = "t"; // RName[2] = "Dt"; // // DName is defined earlier // list NName = RName + Name + DName; // L[2] = NName; // tmp = 0; // // block ord (a(1,1),dp); // tmp[1] = "a"; // string // iv = 1,1; // tmp[2] = iv; //intvec // Lord[1] = tmp; // // continue with dp 1,1,1,1... // tmp[1] = "dp"; // string // s = "iv="; // for(i=1;i<=Nnew;i++) // { // s = s+"1,"; // } // s[size(s)]= ";"; // execute(s); // kill s; // kill NName; // tmp[2] = iv; // Lord[2] = tmp; // tmp[1] = "C"; // iv = 0; // tmp[2] = iv; // Lord[3] = tmp; // tmp = 0; // L[3] = Lord; // // we are done with the list // // Add: Plural part // def @R2 = ring(L); // setring @R2; // matrix @D[Nnew][Nnew]; // @D[1,2]=1; // for(i=1; i<=N; i++) // { // @D[2+i,2+N+i]=1; // } // nc_algebra(1,@D); // dbprint(ppl,"// -2-1- the ring @R2 is ready"); // dbprint(ppl-1,@R2); // ideal MM = maxideal(1); // MM = 0,0,MM; // map R01 = @R, MM; // ideal K2 = R01(K); // // add the relations between t,Dt and s // // K2 = K2, t*Dt+1+S; // poly G = t*Dt+S+1; // K2 = NF(K2,std(G)),G; // dbprint(ppl,"// -2-2- starting elimination for t,Dt in @R2"); // ideal J = engine(K2,eng); // ideal K = nselect(J,1..2); // dbprint(ppl,"// -2-3- t,Dt are eliminated"); // dbprint(ppl-1,K); // // "------- produce a final result --------"; // // ----- create the ordinary Weyl algebra and put // // ----- the result into it // // ------ create the ring @R5 // // keep: N, i,j,s, tmp, RL // setring save; // Nnew = 2*N; // // list RL = ringlist(save); // is defined earlier // kill Lord, tmp, iv; // // kill L; // L = 0; // list Lord, tmp; // intvec iv; // L[1] = RL[1]; // char // L[4] = RL[4]; // char, minpoly // // check whether vars have admissible names -> done earlier // // list Name = RL[2]; // // DName is defined earlier // list NName = Name + DName; // L[2] = NName; // // dp ordering; // string s = "iv="; // for(i=1;i<=2*N;i++) // { // s = s+"1,"; // } // s[size(s)]= ";"; // execute(s); // tmp = 0; // tmp[1] = "dp"; // string // tmp[2] = iv; //intvec // Lord[1] = tmp; // kill s; // tmp[1] = "C"; // iv = 0; // tmp[2] = iv; // Lord[2] = tmp; // tmp = 0; // L[3] = Lord; // // we are done with the list // // Add: Plural part // def @R5 = ring(L); // setring @R5; // matrix @D[Nnew][Nnew]; // for(i=1; i<=N; i++) // { // @D[i,N+i]=1; // } // nc_algebra(1,@D); // dbprint(ppl,"// -3-1- the ring @R5 is ready"); // dbprint(ppl-1,@R5); // ideal K5 = imap(@R2,K); // option(redSB); // dbprint(ppl,"// -3-2- the final cosmetic std"); // K5 = engine(K5,eng); // std does the job too // // total cleanup // kill @R; // kill @R2; // ideal LD = K5; // ideal BS = imap(@LR,B); // kill @LR; // export BS; // export LD; // return(@R5); // } // example // { // "EXAMPLE:"; echo = 2; // ring r = 0,(x,y,z),Dp; // poly F = x^2+y^3+z^5; // def A = annfsgms(F); // setring A; // LD; // print(matrix(BS)); // } proc convloc(list @NL) "USAGE: convloc(L); L a list RETURN: list PURPOSE: convert a ringlist L into another ringlist, @* where all the 'p' orderings are replaced with the 's' orderings, e.g. @code{dp} by @code{ds}. ASSUME: L is a result of a ringlist command EXAMPLE: example convloc; shows examples " { list NL = @NL; // given a ringlist, returns a new ringlist, // where all the p-orderings are replaced with s-ord's int i,j,k,found; int nblocks = size(NL[3]); for(i=1; i<=nblocks; i++) { for(j=1; j<=size(NL[3][i]); j++) { if (typeof(NL[3][i][j]) == "string" ) { found = 0; for (k=1; k<=size(NL[3][i][j]); k++) { if (NL[3][i][j][k]=="p") { NL[3][i][j][k]="s"; found = 1; // printf("replaced at %s,%s,%s",i,j,k); } } } } } return(NL); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(Dp(2),dp(1)); list L = ringlist(r); list N = convloc(L); def rs = ring(N); setring rs; rs; } proc annfspecial(ideal I, poly F, int mir, number n) "USAGE: annfspecial(I,F,mir,n); I an ideal, F a poly, int mir, number n RETURN: ideal PURPOSE: compute the annihilator ideal of F^n in the Weyl Algebra @* for the given rational number n ASSUME: The basering is D[s] and contains 's' explicitly as a variable, @* the ideal I is the Ann F^s in D[s] (obtained with e.g. SannfsBM), @* the integer 'mir' is the minimal integer root of the BS polynomial of F, @* and the number n is rational. NOTE: We compute the real annihilator for any rational value of n (both @* generic and exceptional). The implementation goes along the lines of @* the Algorithm 5.3.15 from Saito-Sturmfels-Takayama. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example annfspecial; shows examples " { if (!isRational(n)) { "ERROR: n must be a rational number!"; } int ppl = printlevel-voice+2; // int mir = minIntRoot(L[1],0); int ns = rvar("s"); if (!ns) { ERROR("Variable s expected in the ideal AnnFs"); } int d; ideal P = subst(I,var(ns),n); if (denominator(n) == 1) { // n is fraction-free d = int(numerator(n)); if ( (!d) && (n!=0)) { ERROR("no parametric special values are allowed"); } d = d - mir; if (d>0) { dbprint(ppl,"// -1-1- starting syzygy computations"); matrix J[1][1] = F^d; dbprint(ppl-1,"// -1-1-1- of the polynomial ideal"); dbprint(ppl-1,J); matrix K[1][size(I)] = subst(I,var(ns),mir); dbprint(ppl-1,"// -1-1-2- modulo ideal:"); dbprint(ppl-1, K); module M = modulo(J,K); dbprint(ppl-1,"// -1-1-3- getting the result:"); dbprint(ppl-1, M); P = P, ideal(M); dbprint(ppl,"// -1-2- finished syzygy computations"); } else { dbprint(ppl,"// -1-1- d<=0, no syzygy computations needed"); dbprint(ppl-1,"// -1-2- for d ="); dbprint(ppl-1, d); } } // also the else case: d<=0 or n is not an integer dbprint(ppl,"// -2-1- starting final Groebner basis"); P = groebner(P); dbprint(ppl,"// -2-2- finished final Groebner basis"); return(P); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly F = x3-y2; def B = annfs(F); setring B; minIntRoot(BS[1],0); // So, the minimal integer root is -1 setring r; def A = SannfsBM(F); setring A; poly F = x3-y2; annfspecial(LD,F,-1,3/4); // generic root annfspecial(LD,F,-1,-2); // integer but still generic root annfspecial(LD,F,-1,1); // exceptional root } /* //static proc new_ex_annfspecial() { //another example for annfspecial: x3+y3+z3 ring r = 0,(x,y,z),dp; poly F = x3+y3+z3; def B = annfs(F); setring B; minIntRoot(BS[1],0); // So, the minimal integer root is -1 setring r; def A = SannfsBM(F); setring A; poly F = x3+y3+z3; annfspecial(LD,F,-1,3/4); // generic root annfspecial(LD,F,-1,-2); // integer but still generic root annfspecial(LD,F,-1,1); // exceptional root } */ proc minIntRoot(ideal P, int fact) "USAGE: minIntRoot(P, fact); P an ideal, fact an int RETURN: int PURPOSE: minimal integer root of a maximal ideal P NOTE: if fact==1, P is the result of some 'factorize' call, @* else P is treated as the result of bernstein::gmssing.lib @* in both cases without constants and multiplicities EXAMPLE: example minIntRoot; shows examples " { // ideal P = factorize(p,1); // or ideal P = bernstein(F)[1]; intvec vP; number nP; int i; if ( fact ) { // the result comes from "factorize" P = normalize(P); // now leadcoef = 1 // TODO: hunt for units and kill then !!! P = matrix(lead(P))-P; // nP = leadcoef(P[i]-lead(P[i])); // for 1 var only, extract the coeff } else { // bernstein deletes -1 usually P = P, -1; } // for both situations: // now we have an ideal of fractions of type "number" int sP = size(P); for(i=1; i<=sP; i++) { nP = leadcoef(P[i]); if ( (nP - int(nP)) == 0 ) { vP = vP,int(nP); } } if ( size(vP)>=2 ) { vP = vP[2..size(vP)]; } sP = -Max(-vP); if (sP == 0) { "Warning: zero root present!"; } return(sP); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),ds; poly f1 = x*y*(x+y); ideal I1 = bernstein(f1)[1]; // a local Bernstein poly I1; minIntRoot(I1,0); poly f2 = x2-y3; ideal I2 = bernstein(f2)[1]; I2; minIntRoot(I2,0); // now we illustrate the behaviour of factorize // together with a global ordering ring r2 = 0,x,dp; poly f3 = 9*(x+2/3)*(x+1)*(x+4/3); //global b-polynomial of f1=x*y*(x+y) ideal I3 = factorize(f3,1); I3; minIntRoot(I3,1); // and a more interesting situation ring s = 0,(x,y,z),ds; poly f = x3 + y3 + z3; ideal I = bernstein(f)[1]; I; minIntRoot(I,0); } proc isHolonomic(def M) "USAGE: isHolonomic(M); M an ideal/module/matrix RETURN: int, 1 if M is holonomic over the base ring, and 0 otherwise ASSUME: basering is a Weyl algebra in characteristic 0 PURPOSE: check whether M is holonomic over the base ring NOTE: M is holonomic if 2*dim(M) = dim(R), where R is the base ring; dim stands for Gelfand-Kirillov dimension EXAMPLE: example isHolonomic; shows examples " { // char>0 or qring if ( (size(ideal(basering)) >0) || (char(basering) >0) ) { ERROR("Basering is inappropriate: characteristic>0 or qring present"); } if (!isWeyl(basering)) { ERROR("Basering is not a Weyl algebra"); } if ( (typeof(M) != "ideal") && (typeof(M) != "module") && (typeof(M) != "matrix") ) { // print(typeof(M)); ERROR("an argument of type ideal/module/matrix expected"); } if (attrib(M,"isSB")!=1) { M = engine(M,0); } int dimR = gkdim(std(0)); int dimM = gkdim(M); return( (dimR==2*dimM) ); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),dp; poly F = x*y*(x+y); def A = annfsBM(F,0); setring A; LD; isHolonomic(LD); ideal I = std(LD[1]); I; isHolonomic(I); } proc reiffen(int p, int q) "USAGE: reiffen(p, q); int p, int q RETURN: ring PURPOSE: set up the polynomial, describing a Reiffen curve NOTE: activate the output ring with the @code{setring} command and @* find the curve as a polynomial RC. @* A Reiffen curve is defined as RC = x^p + y^q + xy^{q-1}, q >= p+1 >= 5 EXAMPLE: example reiffen; shows examples " { // we allow also other numbers, p \geq 1, q\geq 1 // a Reiffen curve is defined as // F = x^p + y^q +x*y^{q-1}, q \geq p+1 \geq 5 // ASSUME: q >= p+1 >= 5. Otherwise an error message is returned // if ( (p<4) || (q<5) || (q-p<1) ) // { // ERROR("Some of conditions p>=4, q>=5 or q>=p+1 is not satisfied!"); // } if ( (p<1) || (q<1) ) { ERROR("Some of conditions p>=1, q>=1 is not satisfied!"); } ring @r = 0,(x,y),dp; poly RC = y^q +x^p + x*y^(q-1); export RC; return(@r); } example { "EXAMPLE:"; echo = 2; def r = reiffen(4,5); setring r; RC; } proc arrange(int p) "USAGE: arrange(p); int p RETURN: ring PURPOSE: set up the polynomial, describing a hyperplane arrangement NOTE: must be executed in a commutative ring ASSUME: basering is present and it is commutative EXAMPLE: example arrange; shows examples " { int UseBasering = 0 ; if (p<2) { ERROR("p>=2 is required!"); } if ( nameof(basering)!="basering" ) { if (p > nvars(basering)) { ERROR("too big p"); } else { def @r = basering; UseBasering = 1; } } else { // no basering found ERROR("no basering found!"); // ring @r = 0,(x(1..p)),dp; } int i,j,sI; poly q = 1; list ar; ideal tmp; tmp = ideal(var(1)); ar[1] = tmp; for (i = 2; i<=p; i++) { // add i-nary sums to the product ar = indAR(ar,i); } for (i = 1; i<=p; i++) { tmp = ar[i]; sI = size(tmp); for (j = 1; j<=sI; j++) { q = q*tmp[j]; } } if (UseBasering) { return(q); } // poly AR = q; export AR; // return(@r); } example { "EXAMPLE:"; echo = 2; ring X = 0,(x,y,z,t),dp; poly q = arrange(3); factorize(q,1); } proc checkRoot(poly F, number a, list #) "USAGE: checkRoot(f,alpha [,S,eng]); poly f, number alpha, string S, int eng RETURN: int ASSUME: Basering is a commutative ring, alpha is a positive rational number. PURPOSE: check whether a negative rational number -alpha is a root of the global @* Bernstein-Sato polynomial of f and compute its multiplicity, @* with the algorithm given by S and with the Groebner basis engine given by eng. NOTE: The annihilator of f^s in D[s] is needed and hence it is computed with the @* algorithm by Briancon and Maisonobe. The value of a string S can be @* 'alg1' (default) - for the algorithm 1 of [LM08] @* 'alg2' - for the algorithm 2 of [LM08] @* Depending on the value of S, the output of type int is: @* 'alg1': 1 only if -alpha is a root of the global Bernstein-Sato polynomial @* 'alg2': the multiplicity of -alpha as a root of the global Bernstein-Sato @* polynomial of f. If -alpha is not a root, the output is 0. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise (and by default) @code{slimgb} is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example checkRoot; shows examples " { int eng = 0; int chs = 0; // choice string algo = "alg1"; string st; if ( size(#)>0 ) { if ( typeof(#[1]) == "string" ) { st = string(#[1]); if ( (st == "alg1") || (st == "ALG1") || (st == "Alg1") ||(st == "aLG1")) { algo = "alg1"; chs = 1; } if ( (st == "alg2") || (st == "ALG2") || (st == "Alg2") || (st == "aLG2")) { algo = "alg2"; chs = 1; } if (chs != 1) { // incorrect value of S print("Incorrect algorithm given, proceed with the default alg1"); algo = "alg1"; } // second arg if (size(#)>1) { // exists 2nd arg if ( typeof(#[2]) == "int" ) { // the case: given alg, given engine eng = int(#[2]); } else { eng = 0; } } else { // no second arg eng = 0; } } else { if ( typeof(#[1]) == "int" ) { // the case: default alg, engine eng = int(#[1]); // algo = "alg1"; //is already set } else { // incorr. 1st arg algo = "alg1"; } } } // size(#)=0, i.e. there is no algorithm and no engine given // eng = 0; algo = "alg1"; //are already set // int ppl = printlevel-voice+2; // check assume: a is positive rational number if (!isRational(a)) { ERROR("rational root expected for checking"); } if (numerator(a) < 0 ) { ERROR("expected positive -alpha"); // the following is more user-friendly but less correct // print("proceeding with the negated root"); // a = -a; } printlevel=printlevel+1; def save = basering; def @A = SannfsBM(F); setring @A; poly F = imap(save,F); number a = imap(save,a); if ( algo=="alg1") { int output = checkRoot1(LD,F,a,eng); } else { if ( algo=="alg2") { int output = checkRoot2(LD,F,a,eng); } } printlevel=printlevel-1; return(output); } example { "EXAMPLE:"; echo = 2; printlevel=0; ring r = 0,(x,y),Dp; poly F = x^4+y^5+x*y^4; checkRoot(F,11/20); // -11/20 is a root of bf poly G = x*y; checkRoot(G,1,"alg2"); // -1 is a root of bg with multiplicity 2 } proc checkRoot1(ideal I, poly F, number a, list #) "USAGE: checkRoot1(I,f,alpha [,eng]); ideal I, poly f, number alpha, int eng ASSUME: Basering is D[s], I is the annihilator of f^s in D[s], @* that is basering and I are the output of Sannfs-like procedure, @* f is a polynomial in K[x] and alpha is a rational number. RETURN: int, 1 if -alpha is a root of the Bernstein-Sato polynomial of f PURPOSE: check, whether alpha is a root of the global Bernstein-Sato polynomial of f NOTE: If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise (and by default) @code{slimgb} is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example checkRoot1; shows examples " { // to check: alpha is rational (has char 0 check inside) if (!isRational(a)) { "ERROR: alpha must be a rational number!"; } // no qring if ( size(ideal(basering)) >0 ) { "ERROR: no qring is allowed"; } int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } int ppl = printlevel-voice+2; dbprint(ppl,"// -0-1- starting the procedure checkRoot1"); def save = basering; int N = nvars(basering); int Nnew = N-1; int n = Nnew div 2; int i; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether basering is D[s]=K(_x,_Dx,s) list Name = RL[2]; // for (i=1; i<=n; i++) // { // if ( bracket(var(i+n),var(i))!=1 ) // { // ERROR("basering should be D[s]=K(_x,_Dx,s)"); // } // } if ( Name[N]!="s" ) { ERROR("the last variable of basering should be s"); } // now, create the new vars list NName; for (i=1; i<=Nnew; i++) { NName[i] = Name[i]; } L[2] = NName; kill Name,NName; // block ord (dp); tmp[1] = "dp"; // string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); kill s; tmp[2] = iv; Lord[1] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; for (i=1; i<=n; i++) { @D[i,i+n]=1; } def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(_x,_Dx) is ready"); dbprint(ppl-1, S); // create the ideal K = ann_D[s](f^s)_{s=-alpha} + < f > setring save; ideal K = subst(I,s,-a); dbprint(ppl,"// -1-2- the variable s has been substituted by "+string(-a)); dbprint(ppl-1, K); K = NF(K,std(F)); // make leadcoeffs positive for (i=1; i<=ncols(K); i++) { if ( leadcoef(K[i])<0 ) { K[i] = -K[i]; } } K = K,F; // ------------ the ideal K is ready ------------ setring @R; ideal K = imap(save,K); dbprint(ppl,"// -1-3- starting the computation of a Groebner basis of K in @R"); dbprint(ppl-1, K); ideal G = engine(K,eng); dbprint(ppl,"// -1-4- the Groebner basis has been computed"); dbprint(ppl-1, G); return(G[1]!=1); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),Dp; poly F = x^4+y^5+x*y^4; printlevel = 0; def A = Sannfs(F); setring A; poly F = imap(r,F); checkRoot1(LD,F,31/20); // -31/20 is not a root of bs checkRoot1(LD,F,11/20); // -11/20 is a root of bs } proc checkRoot2 (ideal I, poly F, number a, list #) "USAGE: checkRoot2(I,f,a [,eng]); I an ideal, f a poly, alpha a number, eng an optional int ASSUME: I is the annihilator of f^s in D[s], basering is D[s], @* that is basering and I are the output os Sannfs-like procedure, @* f is a polynomial in K[_x] and alpha is a rational number. RETURN: int, the multiplicity of -alpha as a root of the BS polynomial of f. PURPOSE: check whether a rational number alpha is a root of the global Bernstein- @* Sato polynomial of f and compute its multiplicity from the known Ann F^s in D[s] NOTE: If -alpha is not a root, the output is 0. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise (and by default) @code{slimgb} is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example checkRoot2; shows examples " { // to check: alpha is rational (has char 0 check inside) if (!isRational(a)) { "ERROR: alpha must be a rational number!"; } // no qring if ( size(ideal(basering)) >0 ) { "ERROR: no qring is allowed"; } int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } int ppl = printlevel-voice+2; dbprint(ppl,"// -0-1- starting the procedure checkRoot2"); def save = basering; int N = nvars(basering); int n = (N-1) div 2; int i; string s; list RL = ringlist(basering); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether basering is D[s]=K(_x,_Dx,s) list Name = RL[2]; for (i=1; i<=n; i++) { if ( bracket(var(i+n),var(i))!=1 ) { ERROR("basering should be D[s]=K(_x,_Dx,s)"); } } if ( Name[N]!="s" ) { ERROR("the last variable of basering should be s"); } // now, create the new vars L[2] = Name; kill Name; // block ord (dp); tmp[1] = "dp"; // string s = "iv="; for (i=1; i<=N; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); kill s; tmp[2] = iv; Lord[1] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[N][N]; for (i=1; i<=n; i++) { @D[i,i+n]=1; } def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(_x,_Dx,s) is ready"); dbprint(ppl-1, @R); // now, continue with the algorithm ideal I = imap(save,I); poly F = imap(save,F); number a = imap(save,a); ideal II = NF(I,std(F)); // make leadcoeffs positive for (i=1; i<=ncols(II); i++) { if ( leadcoef(II[i])<0 ) { II[i] = -II[i]; } } ideal J,G; int m; // the output (multiplicity) dbprint(ppl,"// -2- starting the bucle"); for (i=0; i<=n; i++) // the multiplicity has to be <= n { // create the ideal Ji = ann_D[s](f^s) + < f, (s+alpha)^{i+1} > // (s+alpha)^i in Ji <==> -alpha is a root with multiplicity >= i J = II,F,(s+a)^(i+1); // ------------ the ideal Ji is ready ----------- dbprint(ppl,"// -2-"+string(i+1)+"-1- starting the computation of a Groebner basis of J"+string(i)+" in @R"); dbprint(ppl-1, J); G = engine(J,eng); dbprint(ppl,"// -2-"+string(i+1)+"-2- the Groebner basis has been computed"); dbprint(ppl-1, G); if ( NF((s+a)^i,G)==0 ) { dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has not multiplicity "+string(i+1)); m = i; break; } dbprint(ppl,"// -2-"+string(i+1)+"-3- the number "+string(-a)+" has multiplicity at least "+string(i+1)); } dbprint(ppl,"// -3- the bucle has finished"); return(m); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x*y*z; printlevel = 0; def A = Sannfs(F); setring A; poly F = imap(r,F); checkRoot2(LD,F,1); // -1 is a root of bs with multiplicity 3 checkRoot2(LD,F,1/3); // -1/3 is not a root } proc checkFactor(ideal I, poly F, poly q, list #) "USAGE: checkFactor(I,f,qs [,eng]); I an ideal, f a poly, qs a poly, eng an optional int ASSUME: checkFactor is called from the basering, created by Sannfs-like proc, @* that is, from the Weyl algebra in x1,..,xN,d1,..,dN tensored with K[s]. @* The ideal I is the annihilator of f^s in D[s], that is the ideal, computed @* by Sannfs-like procedure (usually called LD there). @* Moreover, f is a polynomial in K[x1,..,xN] and qs is a polynomial in K[s]. RETURN: int, 1 if qs is a factor of the global Bernstein polynomial of f and 0 otherwise PURPOSE: check whether a univariate polynomial qs is a factor of the @* Bernstein-Sato polynomial of f without explicit knowledge of the latter. NOTE: If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise (and by default) @code{slimgb} is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example checkFactor; shows examples " { // ASSUME too complicated, cannot check it. int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } int ppl = printlevel-voice+2; def @R2 = basering; int N = nvars(@R2); int i; // we're in D_n[s], where the elim ord for s is set dbprint(ppl,"// -0-1- starting the procedure checkFactor"); dbprint(ppl,"// -1-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); // create the ideal J = ann_D[s](f^s) + < f,q > ideal J = NF(I,std(F)); // make leadcoeffs positive for (i=1; i<=ncols(J); i++) { if ( leadcoef(J[i])<0 ) { J[i] = -J[i]; } } J = J,F,q; // ------------ the ideal J is ready ----------- dbprint(ppl,"// -1-2- starting the elimination of _x,_Dx in @R2"); dbprint(ppl-1, J); ideal G = engine(J,eng); ideal K = nselect(G,1..N-1); kill J,G; dbprint(ppl,"// -1-3- _x,_Dx are eliminated"); dbprint(ppl-1, K); //q is a factor of bs if and only if K = < q > //K = normalize(K); //q = normalize(q); //return( (K[1]==q) ); return( NF(K[1],std(q))==0 ); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),Dp; poly F = x^4+y^5+x*y^4; printlevel = 0; def A = Sannfs(F); setring A; poly F = imap(r,F); checkFactor(LD,F,20*s+31); // -31/20 is not a root of bs checkFactor(LD,F,20*s+11); // -11/20 is a root of bs checkFactor(LD,F,(20*s+11)^2); // the multiplicity of -11/20 is 1 } static proc indAR(list L, int n) "USAGE: indAR(L,n); list L, int n RETURN: list PURPOSE: computes arrangement inductively, using L and @* var(n) as the next variable ASSUME: L has a structure of an arrangement EXAMPLE: example indAR; shows examples " { if ( (n<2) || (n>nvars(basering)) ) { ERROR("incorrect n"); } int sl = size(L); list K; ideal tmp; poly @t = L[sl][1] + var(n); //1 elt K[sl+1] = ideal(@t); tmp = L[1]+var(n); K[1] = tmp; tmp = 0; int i,j,sI; ideal I; for(i=sl; i>=2; i--) { I = L[i-1]; sI = size(I); for(j=1; j<=sI; j++) { I[j] = I[j] + var(n); } tmp = L[i],I; K[i] = tmp; I = 0; tmp = 0; } kill I; kill tmp; return(K); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z,t,v),dp; list L; L[1] = ideal(x); list K = indAR(L,2); K; list M = indAR(K,3); M; M = indAR(M,4); M; } proc isRational(number n) "USAGE: isRational(n); n number RETURN: int PURPOSE: determine whether n is a rational number, @* that is it does not contain parameters. ASSUME: ground field is of characteristic 0 EXAMPLE: example indAR; shows examples " { if (char(basering) != 0) { ERROR("The ground field must be of characteristic 0!"); } number dn = denominator(n); number nn = numerator(n); return( ((int(dn)==dn) && (int(nn)==nn)) ); } example { "EXAMPLE:"; echo = 2; ring r = (0,a),(x,y),dp; number n1 = 11/73; isRational(n1); number n2 = (11*a+3)/72; isRational(n2); } proc bernsteinLift(ideal I, poly F, list #) "USAGE: bernsteinLift(I, F [,eng]); I an ideal, F a poly, eng an optional int RETURN: list PURPOSE: compute the (multiple of) Bernstein-Sato polynomial with lift-like method, @* based on the output of Sannfs-like procedure NOTE: the output list contains the roots with multiplicities of the candidate @* for being Bernstein-Sato polynomial of f. @* If eng <>0, @code{std} is used for Groebner basis computations, @* otherwise and by default @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example bernsteinLift; shows examples " { // assume: s is the last variable! check in the code int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "int" ) { eng = int(#[1]); } } def @R2 = basering; int Nnew = nvars(@R2); int N = Nnew div 2; int ppl = printlevel-voice+2; // we're in D_n[s], where the elim ord for s is set // create D_n(s) // create the ordinary Weyl algebra and put the result into it, // keep: N, i,j,s, tmp, RL Nnew = Nnew - 1; // former 2*N; list L = 0; list Lord, tmp; intvec iv; int i; list RL = ringlist(basering); // if we work over alg. extension => problem! if (size(RL[1]) > 1) { ERROR("cannot work over algebraic field extension"); } tmp[1] = RL[1]; // char tmp[2] = list("s"); tmp[3] = list(list("lp",int(1))); tmp[4] = ideal(0); L[1] = tmp; // field tmp = 0; L[4] = RL[4]; // factor ideal // check whether vars have admissible names -> done earlier // list Name = RL[2]M // DName is defined earlier list NName; // = RL[2]; // skip the last var 's' for (i=1; i<=Nnew; i++) { NName[i] = RL[2][i]; } L[2] = NName; // (c, ) ordering: tmp[1] = "c"; iv = 0; tmp[2] = iv; Lord[1] = tmp; tmp=0; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)] = ";"; execute(s); tmp = 0; tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[2] = tmp; kill s; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R4@ = ring(L); setring @R4@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R4 = nc_algebra(1,@D); setring @R4; kill @R4@; dbprint(ppl,"// -3-1- the ring K(s) is ready"); dbprint(ppl-1, @R4); // map things correctly, using names ideal J = imap(@R2, I), imap(@R2,F); module M; // make leadcoeffs positive for (i=1; i<= ncols(J); i++) { if (J[i]!=0) { M[i] = J[i]*gen(1) + gen(1+i); } } dbprint(ppl,"// -3-2- starting GB of the assoc. module M"); M = engine(M,eng); dbprint(ppl,"// -3-3- finished GB of the assoc. module M"); dbprint(ppl-1, M); // now look for (1) entry with 1st comp nonzero // determine whether there are several 1st comps nonzero module M2; for (i=1; i<= ncols(M); i++) { if (M[1,i]!=0) { M2 = M2, M[i]; } } M2 = simplify(M2,2); // skip 0s if (ncols(M2) > 1) { dbprint(ppl,"// -*- more than 1 element with nonzero leading component"); option(redSB); option(redTail); // set them back? M2 = interred(M2); if (ncols(M2) > 1) { ERROR("more than one leading component after interred: assume violation!"); } if (leadexp(M2[1]) != 0) { ERROR("nonconstant entry after interred: assume violation!"); } } // now there's only one el-t with leadcomp<>0 vector V = M2[1]; number bcand = leadcoef(V[1]); // 1st component V=V-V[1]; number ct = content(V); // content of the cofactors poly CF = ct*V[ncols(J)]; // polynomial in K[s], cofactor to F dbprint(ppl,"// -3-4- the cofactor candidate found"); dbprint(ppl-1,CF); dbprint(ppl,"// -3-5- the entry as it is"); dbprint(ppl-1,bcand); bcand = bcand*ct; // a product of both dbprint(ppl,"// -3-6- the content of the rest vector"); dbprint(ppl-1,ct); ring @R3 = 0,s,dp; dbprint(ppl,"// -4-1- the ring @R3 i.e. K[s] is ready"); poly bcand = imap(@R4,bcand); dbprint(ppl,"// -4-2- factorization"); list P = factorize(bcand); //with constants and multiplicities ideal bs; intvec m; //the Bernstein polynomial is monic, so we are not interested in constants for (i=2; i<= size(P[1]); i++) //we delete P[1][1] and P[2][1] { bs[i-1] = P[1][i]; m[i-1] = P[2][i]; } bs = normalize(bs); bs = -subst(bs,s,0); // to get roots only setring @R2; // the ring the story started with ideal bs = imap(@R3,bs); // intvec m is global intvec mm = m; m = 0; kill @R3; // kills m as well.... list @L = list(bs, mm); // look for (2) return the GB of syzygies? return(@L); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),Dp; poly F = x^3+y^3+z^3; printlevel = 0; def A = Sannfs(F); setring A; LD; poly F = imap(r,F); list L = bernsteinLift(LD,F); L; poly bs = fl2poly(L,"s"); bs; // the candidate for Bernstein-Sato polynomial } /// ****** EXAMPLES ************ /* //static proc exCheckGenericity() { LIB "control.lib"; ring r = (0,a,b,c),x,dp; poly p = (x-a)*(x-b)*(x-c); def A = annfsBM(p); setring A; ideal J = slimgb(LD); matrix T = lift(LD,J); T = normalize(T); genericity(T); // Ann =x^3*Dx+3*x^2*t*Dt+(-a-b-c)*x^2*Dx+(-2*a-2*b-2*c)*x*t*Dt+3*x^2+(a*b+a*c+b*c)*x*Dx+(a*b+a*c+b*c)*t*Dt+(-2*a-2*b-2*c)*x+(-a*b*c)*Dx+(a*b+a*c+b*c) // genericity: g = a2-ab-ac+b2-bc+c2 =0 // g = (a -(b+c)/2)^2 + (3/4)*(b-c)^2; // g ==0 <=> a=b=c // indeed, Ann = (x-a)^2*(x*Dx+3*t*Dt+(-a)*Dx+3) // -------------------------------------------- // BUT a direct computation shows // when a=b=c, // Ann = x*Dx+3*t*Dt+(-a)*Dx+3 } //static proc exOT_17() { // Oaku-Takayama, p.208 ring R = 0,(x,y),dp; poly F = x^3-y^2; // x^2+x*y+y^2; option(prot); option(mem); // option(redSB); def A = annfsOT(F,0); setring A; LD; gkdim(LD); // a holonomic check // poly F = x^3-y^2; // = x^7 - y^5; // x^3-y^4; // x^5 - y^4; } //static proc exOT_16() { // Oaku-Takayama, p.208 ring R = 0,(x),dp; poly F = x*(1-x); option(prot); option(mem); // option(redSB); def A = annfsOT(F,0); setring A; LD; gkdim(LD); // a holonomic check } //static proc ex_bcheck() { ring R = 0,(x,y),dp; poly F = x*y*(x+y); option(prot); option(mem); int eng = 0; // option(redSB); def A = annfsOT(F,eng); setring A; LD; } //static proc ex_bcheck2() { ring R = 0,(x,y),dp; poly F = x*y*(x+y); int eng = 0; def A = annfsBM(F,eng); setring A; LD; } //static proc ex_BMI() { // a hard example ring r = 0,(x,y),Dp; poly F1 = (x2-y3)*(x3-y2); poly F2 = (x2-y3)*(xy4+y5+x4); ideal F = F1,F2; def A = annfsBMI(F); setring A; LD; BS; } //static proc ex2_BMI() { // this example was believed to be intractable in 2005 by Gago-Vargas, Castro and Ucha ring r = 0,(x,y),Dp; option(prot); option(mem); ideal F = x2+y3,x3+y2; printlevel = 2; def A = annfsBMI(F); setring A; LD; BS; } //static proc ex_operatorBM() { ring r = 0,(x,y,z,w),Dp; poly F = x^3+y^3+z^2*w; printlevel = 0; def A = operatorBM(F); setring A; F; // the original polynomial itself LD; // generic annihilator LD0; // annihilator bs; // normalized Bernstein poly BS; // root and multiplicities of the Bernstein poly PS; // the operator, s.t. PS*F^{s+1} = bs*F^s mod LD reduce(PS*F-bs,LD); // check the property of PS } */ singular-4.0.3+ds/Singular/LIB/dmodapp.lib000066400000000000000000002576031266270727000203000ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version dmodapp.lib 4.0.0.0 Jun_2013 "; // $Id: 4e5f6ce782684ec3dbec89249bef19d03d8948f1 $ category="Noncommutative"; info=" LIBRARY: dmodapp.lib Applications of algebraic D-modules AUTHORS: Viktor Levandovskyy, levandov@math.rwth-aachen.de @* Daniel Andres, daniel.andres@math.rwth-aachen.de Support: DFG Graduiertenkolleg 1632 'Experimentelle und konstruktive Algebra' OVERVIEW: Let K be a field of characteristic 0, R = K[x1,...,xN] and D be the Weyl algebra in variables x1,...,xN,d1,...,dN. In this library there are the following procedures for algebraic D-modules: @* - given a cyclic representation D/I of a holonomic module and a polynomial F in R, it is proved that the localization of D/I with respect to the mult. closed set of all powers of F is a holonomic D-module. Thus we aim to compute its cyclic representaion D/L for an ideal L in D. The procedures for the localization are DLoc, SDLoc and DLoc0. @* - annihilator in D of a given polynomial F from R as well as of a given rational function G/F from Quot(R). These can be computed via procedures annPoly resp. annRat. @* - Groebner bases with respect to weights (according to (SST), given an arbitrary integer vector containing weights for variables, one computes the homogenization of a given ideal relative to this vector, then one computes a Groebner basis and returns the dehomogenization of the result), initial forms and initial ideals in Weyl algebras with respect to a given weight vector can be computed with GBWeight, inForm, initialMalgrange and initialIdealW. @* - restriction and integration of a holonomic module D/I. Suppose I annihilates a function F(x1,...,xn). Our aim is to compute an ideal J directly from I, which annihilates @* - F(0,...,0,xk,...,xn) in case of restriction or @* - the integral of F with respect to x1,...,xm in case of integration. The corresponding procedures are restrictionModule, restrictionIdeal, integralModule and integralIdeal. @* - characteristic varieties defined by ideals in Weyl algebras can be computed with charVariety and charInfo. @* - appelF1, appelF2 and appelF4 return ideals in parametric Weyl algebras, which annihilate corresponding Appel hypergeometric functions. REFERENCES: @* (SST) Saito, Sturmfels, Takayama 'Groebner Deformations of Hypergeometric Differential Equations', Springer, 2000 @* (OTW) Oaku, Takayama, Walther 'A Localization Algorithm for D-modules', Journal of Symbolic Computation, 2000 @* (OT) Oaku, Takayama 'Algorithms for D-modules', Journal of Pure and Applied Algebra, 1998 PROCEDURES: annPoly(f); computes annihilator of a polynomial f in the corr. Weyl algebra annRat(f,g); computes annihilator of rational function f/g in corr. Weyl algebra DLoc(I,f); computes presentation of localization of D/I wrt symbolic power f^s SDLoc(I,f); computes generic presentation of the localization of D/I wrt f^s DLoc0(I,f); computes presentation of localization of D/I wrt f^s based on SDLoc GBWeight(I,u,v[,a,b]); computes Groebner basis of I wrt a weight vector initialMalgrange(f[,s,t,v]); computes Groebner basis of initial Malgrange ideal initialIdealW(I,u,v[,s,t]); computes initial ideal of wrt a given weight inForm(f,w); computes initial form of poly/ideal wrt a weight restrictionIdeal(I,w[,eng,m,G]); computes restriction ideal of I wrt w restrictionModule(I,w[,eng,m,G]); computes restriction module of I wrt w integralIdeal(I,w[,eng,m,G]); computes integral ideal of I wrt w integralModule(I,w[,eng,m,G]); computes integral module of I wrt w deRhamCohom(f[,eng,m]); computes basis of n-th de Rham cohom. group deRhamCohomIdeal(I[,w,eng,m,G]); computes basis of n-th de Rham cohom. group charVariety(I); computes characteristic variety of the ideal I charInfo(I); computes char. variety, singular locus and primary decomp. isFsat(I,F); checks whether the ideal I is F-saturated appelF1(); creates an ideal annihilating Appel F1 function appelF2(); creates an ideal annihilating Appel F2 function appelF4(); creates an ideal annihilating Appel F4 function fourier(I[,v]); applies Fourier automorphism to ideal inverseFourier(I[,v]); applies inverse Fourier automorphism to ideal bFactor(F); computes the roots of irreducible factors of an univariate poly intRoots(L); dismisses non-integer roots from list in bFactor format poly2list(f); decomposes the polynomial f into a list of terms and exponents fl2poly(L,s); reconstructs a monic univariate polynomial from its factorization insertGenerator(id,p[,k]); inserts an element into an ideal/module deleteGenerator(id,k); deletes the k-th element from an ideal/module engine(I,i); computes a Groebner basis with the algorithm specified by i isInt(n); checks whether number n is actually an int sortIntvec(v); sorts intvec KEYWORDS: D-module; annihilator of polynomial; annihilator of rational function; D-localization; localization of D-module; D-restriction; restriction of D-module; D-integration; integration of D-module; characteristic variety; Appel function; Appel hypergeometric function SEE ALSO: bfun_lib, dmod_lib, dmodvar_lib, gmssing_lib "; /* Changelog 21.09.10 by DA: - restructured library for better readability - new / improved procs: - toolbox: isInt, intRoots, sortIntvec - GB wrt weights: GBWeight, initialIdealW rewritten using GBWeight - restriction/integration: restrictionX, integralX where X in {Module, Ideal}, fourier, inverseFourier, deRhamCohom, deRhamCohomIdeal - characteristic variety: charVariety, charInfo - added keywords for features - reformated help strings and examples in existing procs - added SUPPORT in header - added reference (OT) 04.10.10 by DA: - incorporated suggestions by Oleksandr Motsak, among other: - bugfixes for fl2poly, sortIntvec, annPoly, GBWeight - enhanced functionality for deleteGenerator, inForm 11.10.10 by DA: - procedure bFactor now sorts the roots using new static procedure sortNumberIdeal 17.03.11 by DA: - bugfixes for inForm with polynomial input, typo in restrictionIdealEngine 06.06.12 by DA: - bugfix and documentation in deRhamCohomIdeal, output and documentation in deRhamCohom - changed charVariety: no homogenization is needed - changed inForm: code is much simpler using jet */ LIB "bfun.lib"; // for pIntersect etc LIB "dmod.lib"; // for SannfsBM etc LIB "general.lib"; // for sort LIB "gkdim.lib"; LIB "nctools.lib"; // for isWeyl etc LIB "poly.lib"; LIB "primdec.lib"; // for primdecGKZ LIB "qhmoduli.lib"; // for Max LIB "sing.lib"; // for slocus /////////////////////////////////////////////////////////////////////////////// // testing for consistency of the library: proc testdmodapp() { example annPoly; example annRat; example DLoc; example SDLoc; example DLoc0; example GBWeight; example initialMalgrange; example initialIdealW; example inForm; example restrictionIdeal; example restrictionModule; example integralIdeal; example integralModule; example deRhamCohom; example deRhamCohomIdeal; example charVariety; example charInfo; example isFsat; example appelF1; example appelF2; example appelF4; example fourier; example inverseFourier; example bFactor; example intRoots; example poly2list; example fl2poly; example insertGenerator; example deleteGenerator; example engine; example isInt; example sortIntvec; } // general assumptions //////////////////////////////////////////////////////// static proc dmodappAssumeViolation() { // char K <> 0 or qring if ( (size(ideal(basering)) >0) || (char(basering) >0) ) { ERROR("Basering is inappropriate: characteristic>0 or qring present"); } return(); } static proc dmodappMoreAssumeViolation() { // char K <> 0, qring dmodappAssumeViolation(); // no Weyl algebra if (isWeyl() == 0) { ERROR("Basering is not a Weyl algebra"); } // wrong sequence of vars int i,n; n = nvars(basering) div 2; for (i=1; i<=n; i++) { if (bracket(var(i+n),var(i))<>1) { ERROR(string(var(i+n))+" is not a differential operator for " +string(var(i))); } } return(); } static proc safeVarName (string s, string cv) // assumes 's' to be a valid variable name // returns valid var name string @@..@s { string S; if (cv == "v") { S = "," + "," + varstr(basering) + ","; } if (cv == "c") { S = "," + "," + charstr(basering) + ","; } if (cv == "cv") { S = "," + charstr(basering) + "," + varstr(basering) + ","; } s = "," + s + ","; while (find(S,s) <> 0) { s[1] = "@"; s = "," + s; } s = s[2..size(s)-1]; return(s) } static proc intLike (def i) { string str = typeof(i); if (str == "int" || str == "number" || str == "bigint") { return(1); } else { return(0); } } // toolbox //////////////////////////////////////////////////////////////////// proc engine(def I, int i) "USAGE: engine(I,i); I ideal/module/matrix, i an int RETURN: the same type as I PURPOSE: compute the Groebner basis of I with the algorithm, chosen via i NOTE: By default and if i=0, slimgb is used; otherwise std does the job. EXAMPLE: example engine; shows examples " { /* std - slimgb mix */ def J; // ideal J; if (i==0) { J = slimgb(I); } else { // without options -> strange! (ringlist?) intvec v = option(get); option(redSB); option(redTail); J = std(I); option(set, v); } return(J); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),Dp; ideal I = y*(x3-y2),x*(x3-y2); engine(I,0); // uses slimgb engine(I,1); // uses std } proc poly2list (poly f) "USAGE: poly2list(f); f a poly RETURN: list of exponents and corresponding terms of f PURPOSE: converts a poly to a list of pairs consisting of intvecs (1st entry) @* and polys (2nd entry), where the i-th pair contains the exponent of the @* i-th term of f and the i-th term (with coefficient) itself. EXAMPLE: example poly2list; shows examples " { list l; int i = 1; if (f == 0) // just for the zero polynomial { l[1] = list(leadexp(f), lead(f)); } else { l[size(f)] = list(); // memory pre-allocation while (f != 0) { l[i] = list(leadexp(f), lead(f)); f = f - lead(f); i++; } } return(l); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; poly F = x; poly2list(F); ring r2 = 0,(x,y),dp; poly F = x2y+5xy2; poly2list(F); poly2list(0); } proc fl2poly(list L, string s) "USAGE: fl2poly(L,s); L a list, s a string RETURN: poly PURPOSE: reconstruct a monic polynomial in one variable from its factorization ASSUME: s is a string with the name of some variable and @* L is supposed to consist of two entries: @* - L[1] of the type ideal with the roots of a polynomial @* - L[2] of the type intvec with the multiplicities of corr. roots EXAMPLE: example fl2poly; shows examples " { if (rvar(s)==0) { ERROR(s+ " is no variable in the basering"); } poly x = var(rvar(s)); poly P = 1; ideal RR = L[1]; int sl = ncols(RR); intvec IV = L[2]; if (sl <> nrows(IV)) { ERROR("number of roots doesn't match number of multiplicites"); } for(int i=1; i<=sl; i++) { if (IV[i] > 0) { P = P*((x-RR[i])^IV[i]); } else { printf("Ignored the root with incorrect multiplicity %s",string(IV[i])); } } return(P); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z,s),Dp; ideal I = -1,-4/3,0,-5/3,-2; intvec mI = 2,1,2,1,1; list BS = I,mI; poly p = fl2poly(BS,"s"); p; factorize(p,2); } proc insertGenerator (list #) "USAGE: insertGenerator(id,p[,k]); @* id an ideal/module, p a poly/vector, k an optional int RETURN: of the same type as id PURPOSE: inserts p into id at k-th position and returns the enlarged object NOTE: If k is given, p is inserted at position k, otherwise (and by default), @* p is inserted at the beginning (k=1). SEE ALSO: deleteGenerator EXAMPLE: example insertGenerator; shows examples " { if (size(#) < 2) { ERROR("insertGenerator has to be called with at least 2 arguments (ideal/module,poly/vector)"); } string inp1 = typeof(#[1]); if (inp1 == "ideal" || inp1 == "module") { def id = #[1]; } else { ERROR("first argument has to be of type ideal or module"); } string inp2 = typeof(#[2]); if (inp2 == "poly" || inp2 == "vector") { def f = #[2]; } else { ERROR("second argument has to be of type poly/vector"); } if (inp1 == "ideal" && inp2 == "vector") { ERROR("second argument has to be a polynomial if first argument is an ideal"); } // don't check module/poly combination due to auto-conversion // if (inp1 == "module" && inp2 == "poly") // { // ERROR("second argument has to be a vector if first argument is a module"); // } int n = ncols(id); int k = 1; // default if (size(#)>=3) { if (intLike(#[3])) { k = int(#[3]); if (k<=0) { ERROR("third argument has to be positive"); } } else { ERROR("third argument has to be of type int"); } } execute(inp1 +" J;"); if (k == 1) { J = f,id; } else { if (k>n) { J = id; J[k] = f; } else // 1 "ideal" && inp1 <> "module") { ERROR("first argument has to be of type ideal or module"); } execute(inp1 +" J;"); int n = ncols(id); if (n == 1 && k == 1) { return(J); } if (k<=0 || k>n) { ERROR("second argument has to be in the range 1,...,"+string(n)); } J[n-1] = 0; // preinit if (k == 1) { J = id[2..n]; } else { if (k == n) { J = id[1..n-1]; } else { J[1..k-1] = id[1..k-1]; J[k..n-1] = id[k+1..n]; } } return(J); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; ideal I = x^2,y^3,z^4; deleteGenerator(I,2); module M = [x,y,z],[x2,y2,z2],[x3,y3,z3]; print(deleteGenerator(M,2)); M = M[1]; deleteGenerator(M,1); } static proc sortNumberIdeal (ideal I) // sorts ideal of constant polys (ie numbers), returns according permutation { int i; int nI = ncols(I); intvec dI; for (i=nI; i>0; i--) { dI[i] = int(denominator(leadcoef(I[i]))); } int lcmI = lcm(dI); for (i=nI; i>0; i--) { dI[i] = int(lcmI*leadcoef(I[i])); } intvec perm = sortIntvec(dI)[2]; return(perm); } example { "EXAMPLE:"; echo = 2; ring r = 0,s,dp; ideal I = -9/20,-11/20,-23/20,-19/20,-1,-13/10,-27/20,-13/20,-21/20,-17/20, -11/10,-9/10,-7/10; // roots of BS poly of reiffen(4,5) intvec v = sortNumberIdeal(I); v; I[v]; } proc bFactor (poly F) "USAGE: bFactor(f); f poly RETURN: list of ideal and intvec and possibly a string PURPOSE: tries to compute the roots of a univariate poly f NOTE: The output list consists of two or three entries: @* roots of f as an ideal, their multiplicities as intvec, and, @* if present, a third one being the product of all irreducible factors @* of degree greater than one, given as string. @* If f is the zero polynomial or if f has no roots in the ground field, @* this is encoded as root 0 with multiplicity 0. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example bFactor; shows examples " { int ppl = printlevel - voice +2; def save = basering; ideal LI = variables(F); list L; int i = size(LI); if (i>1) { ERROR("poly has to be univariate")} if (i == 0) { dbprint(ppl,"// poly is constant"); L = list(ideal(0),intvec(0),string(F)); return(L); } poly v = LI[1]; L = ringlist(save); L = L[1..4]; L[2] = list(string(v)); L[3] = list(list("dp",intvec(1)),list("C",intvec(0))); def @S = ring(L); setring @S; poly ir = 1; poly F = imap(save,F); list L = factorize(F); ideal I = L[1]; intvec m = L[2]; ideal II; intvec mm; for (i=2; i<=ncols(I); i++) { if (deg(I[i]) > 1) { ir = ir * I[i]^m[i]; } else { II[size(II)+1] = I[i]; mm[size(II)] = m[i]; } } II = normalize(II); II = subst(II,var(1),0); II = -II; intvec perm = sortNumberIdeal(II); II = II[perm]; mm = mm[perm]; if (size(II)>0) { dbprint(ppl,"// found roots"); dbprint(ppl-1,string(II)); } else { dbprint(ppl,"// found no roots"); } L = list(II,mm); if (ir <> 1) { dbprint(ppl,"// found irreducible factors"); ir = cleardenom(ir); dbprint(ppl-1,string(ir)); L = L + list(string(ir)); } else { dbprint(ppl,"// no irreducible factors found"); } setring save; L = imap(@S,L); return(L); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; bFactor((x^2-1)^2); bFactor((x^2+1)^2); bFactor((y^2+1/2)*(y+9)*(y-7)); bFactor(1); bFactor(0); } proc isInt (number n) "USAGE: isInt(n); n a number RETURN: int, 1 if n is an integer or 0 otherwise PURPOSE: check whether given object of type number is actually an int NOTE: Parameters are treated as integers. EXAMPLE: example isInt; shows an example " { number d = denominator(n); if (d<>1) { return(0); } else { return(1); } } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; number n = 4/3; isInt(n); n = 11; isInt(n); } proc intRoots (list l) "USAGE: isInt(L); L a list RETURN: list PURPOSE: extracts integer roots from a list given in @code{bFactor} format ASSUME: The input list must be given in the format of @code{bFactor}. NOTE: Parameters are treated as integers. SEE ALSO: bFactor EXAMPLE: example intRoots; shows an example " { int wronginput; int sl = size(l); if (sl>0) { if (typeof(l[1])<>"ideal"){wronginput = 1;} if (sl>1) { if (typeof(l[2])<>"intvec"){wronginput = 1;} if (sl>2) { if (typeof(l[3])<>"string"){wronginput = 1;} if (sl>3){wronginput = 1;} } } } if (sl<2){wronginput = 1;} if (wronginput) { ERROR("Given list has wrong format."); } int i,j; ideal l1 = l[1]; int n = ncols(l1); j = 1; ideal I; intvec v; for (i=1; i<=n; i++) { if (size(l1[j])>1) // poly not number { ERROR("Ideal in list has wrong format."); } if (isInt(leadcoef(l1[i]))) { I[j] = l1[i]; v[j] = l[2][i]; j++; } } return(list(I,v)); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; list L = bFactor((x-4/3)*(x+3)^2*(x-5)^4); L; intRoots(L); } proc sortIntvec (intvec v) "USAGE: sortIntvec(v); v an intvec RETURN: list of two intvecs PURPOSE: sorts an intvec NOTE: In the output list L, the first entry consists of the entries of v @* satisfying L[1][i] >= L[1][i+1]. The second entry is a permutation @* such that v[L[2]] = L[1]. @* Unlike in the procedure @code{sort}, zeros are not dismissed. SEE ALSO: sort EXAMPLE: example sortIntvec; shows examples " { int i; intvec vpos,vzero,vneg,vv,sortv,permv; list l; for (i=1; i<=nrows(v); i++) { if (v[i]>0) { vpos = vpos,i; } else { if (v[i]==0) { vzero = vzero,i; } else // v[i]<0 { vneg = vneg,i; } } } if (size(vpos)>1) { vpos = vpos[2..size(vpos)]; vv = v[vpos]; l = sort(vv); vv = l[1]; vpos = vpos[l[2]]; sortv = vv[size(vv)..1]; permv = vpos[size(vv)..1]; } if (size(vzero)>1) { vzero = vzero[2..size(vzero)]; permv = permv,vzero; sortv = sortv,0:size(vzero); } if (size(vneg)>1) { vneg = vneg[2..size(vneg)]; vv = -v[vneg]; l = sort(vv); vv = -l[1]; vneg = vneg[l[2]]; sortv = sortv,vv; permv = permv,vneg; } if (permv[1]==0) { sortv = sortv[2..size(sortv)]; permv = permv[2..size(permv)]; } return(list(sortv,permv)); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; intvec v = -1,0,1,-2,0,2; list L = sortIntvec(v); L; v[L[2]]; v = -3,0; sortIntvec(v); v = 0,-3; sortIntvec(v); } // F-saturation /////////////////////////////////////////////////////////////// proc isFsat(ideal I, poly F) "USAGE: isFsat(I, F); I an ideal, F a poly RETURN: int, 1 if I is F-saturated and 0 otherwise PURPOSE: checks whether the ideal I is F-saturated NOTE: We check indeed that Ker(D--> F--> D/I) is 0, where D is the basering. EXAMPLE: example isFsat; shows examples " { /* checks whether I is F-saturated, that is Ke (D -F-> D/I) is 0 */ /* works in any algebra */ /* for simplicity : later check attrib */ /* returns 1 if I is F-sat */ if (attrib(I,"isSB")!=1) { I = groebner(I); } matrix @M = matrix(I); matrix @F[1][1] = F; def S = modulo(module(@F),module(@M)); S = NF(S,I); S = groebner(S); return( (gkdim(S) == -1) ); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly G = x*(x-y)*y; def A = annfs(G); setring A; poly F = x3-y2; isFsat(LD,F); ideal J = LD*F; isFsat(J,F); } // annihilators /////////////////////////////////////////////////////////////// proc annRat(poly g, poly f) "USAGE: annRat(g,f); f, g polynomials RETURN: ring (a Weyl algebra) containing an ideal 'LD' PURPOSE: compute the annihilator of the rational function g/f in the @* corresponding Weyl algebra ASSUME: basering is commutative and over a field of characteristic 0 NOTE: Activate the output ring with the @code{setring} command. @* In the output ring, the ideal 'LD' (in Groebner basis) is the @* annihilator of g/f. @* The algorithm uses the computation of Ann(f^{-1}) via D-modules, @* see (SST). DISPLAY: If printlevel =1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. SEE ALSO: annPoly EXAMPLE: example annRat; shows examples " { // assumption check dmodappAssumeViolation(); if (!isCommutative()) { ERROR("Basering must be commutative."); } // assumptions: f is not a constant if (f==0) { ERROR("the denominator f cannot be zero"); } if ((leadexp(f) == 0) && (size(f) < 2)) { // f = const, so use annPoly g = g/f; def @R = annPoly(g); return(@R); } // computes the annihilator of g/f def save = basering; int ppl = printlevel-voice+2; dbprint(ppl,"// -1-[annRat] computing the ann f^s"); def @R1 = SannfsBM(f); setring @R1; poly f = imap(save,f); int i,mir; int isr = 0; // checkRoot1(LD,f,1); // roots are negative, have to enter positive int if (!isr) { // -1 is not the root // find the m.i.r iteratively mir = 0; for(i=nvars(save)+1; i>=1; i--) { isr = checkRoot1(LD,f,i); if (isr) { mir =-i; break; } } if (mir ==0) { ERROR("No integer root found! Aborting computations, inform the authors!"); } // now mir == i is m.i.r. } else { // -1 is the m.i.r mir = -1; } dbprint(ppl,"// -2-[annRat] the minimal integer root is "); dbprint(ppl-1, mir); // use annfspecial dbprint(ppl,"// -3-[annRat] running annfspecial "); ideal AF = annfspecial(LD,f,mir,-1); // ann f^{-1} // LD = subst(LD,s,j); // LD = engine(LD,0); // modify the ring: throw s away // output ring comes from SannfsBM list U = ringlist(@R1); list tmp; // variables for(i=1; i<=size(U[2])-1; i++) { tmp[i] = U[2][i]; } U[2] = tmp; tmp = 0; tmp[1] = U[3][1]; // x,Dx block tmp[2] = U[3][3]; // module block U[3] = tmp; tmp = 0; tmp = U[1],U[2],U[3],U[4]; def @R2 = ring(tmp); setring @R2; // now supply with Weyl algebra relations int N = nvars(@R2) div 2; matrix @D[2*N][2*N]; for(i=1; i<=N; i++) { @D[i,N+i]=1; } def @R3 = nc_algebra(1,@D); setring @R3; dbprint(ppl,"// - -[annRat] ring without s is ready:"); dbprint(ppl-1,@R3); poly g = imap(save,g); matrix G[1][1] = g; matrix LL = matrix(imap(@R1,AF)); kill @R1; kill @R2; dbprint(ppl,"// -4-[annRat] running modulo"); ideal LD = modulo(G,LL); dbprint(ppl,"// -4-[annRat] running GB on the final result"); LD = engine(LD,0); export LD; return(@R3); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly g = 2*x*y; poly f = x^2 - y^3; def B = annRat(g,f); setring B; LD; // Now, compare with the output of Macaulay2: ideal tst = 3*x*Dx + 2*y*Dy + 1, y^3*Dy^2 - x^2*Dy^2 + 6*y^2*Dy + 6*y, 9*y^2*Dx^2*Dy-4*y*Dy^3+27*y*Dx^2+2*Dy^2, 9*y^3*Dx^2-4*y^2*Dy^2+10*y*Dy -10; option(redSB); option(redTail); LD = groebner(LD); tst = groebner(tst); print(matrix(NF(LD,tst))); print(matrix(NF(tst,LD))); // So, these two answers are the same } proc annPoly(poly f) "USAGE: annPoly(f); f a poly RETURN: ring (a Weyl algebra) containing an ideal 'LD' PURPOSE: compute the complete annihilator ideal of f in the corresponding @* Weyl algebra ASSUME: basering is commutative and over a field of characteristic 0 NOTE: Activate the output ring with the @code{setring} command. @* In the output ring, the ideal 'LD' (in Groebner basis) is the @* annihilator. DISPLAY: If printlevel =1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. SEE ALSO: annRat EXAMPLE: example annPoly; shows examples " { // assumption check dmodappAssumeViolation(); if (!isCommutative()) { ERROR("Basering must be commutative."); } // computes a system of linear PDEs with polynomial coeffs for f def save = basering; list L = ringlist(save); list Name = L[2]; int N = nvars(save); int i; for (i=1; i<=N; i++) { Name[N+i] = safeVarName("D"+Name[i],"cv"); // concat } L[2] = Name; def @R = ring(L); setring @R; def @@R = Weyl(); setring @@R; kill @R; matrix M[1][N]; for (i=1; i<=N; i++) { M[1,i] = var(N+i); } matrix F[1][1] = imap(save,f); def I = modulo(module(F),module(M)); ideal LD = I; LD = groebner(LD); export LD; return(@@R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; poly f = x^2*z - y^3; def A = annPoly(f); setring A; // A is the 3rd Weyl algebra in 6 variables LD; // the Groebner basis of annihilator gkdim(LD); // must be 3 = 6/2, since A/LD is holonomic module NF(Dy^4, LD); // must be 0 since Dy^4 clearly annihilates f poly f = imap(r,f); NF(LD*f,std(ideal(Dx,Dy,Dz))); // must be zero if LD indeed annihilates f } // localizations ////////////////////////////////////////////////////////////// proc DLoc(ideal I, poly F) "USAGE: DLoc(I, f); I an ideal, f a poly RETURN: list of ideal and list ASSUME: the basering is a Weyl algebra PURPOSE: compute the presentation of the localization of D/I w.r.t. f^s NOTE: In the output list L, @* - L[1] is an ideal (given as Groebner basis), the presentation of the @* localization, @* - L[2] is a list containing roots with multiplicities of Bernstein @* polynomial of (D/I)_f. DISPLAY: If printlevel =1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example DLoc; shows examples " { /* runs SDLoc and DLoc0 */ /* assume: run from Weyl algebra */ dmodappAssumeViolation(); if (!isWeyl()) { ERROR("Basering is not a Weyl algebra"); } int old_printlevel = printlevel; printlevel=printlevel+1; def @R = basering; def @R2 = SDLoc(I,F); setring @R2; poly F = imap(@R,F); def @R3 = DLoc0(LD,F); setring @R3; ideal bs = BS[1]; intvec m = BS[2]; setring @R; ideal LD0 = imap(@R3,LD0); ideal bs = imap(@R3,bs); list BS; BS[1] = bs; BS[2] = m; kill @R3; printlevel = old_printlevel; return(list(LD0,BS)); } example; { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def R = Weyl(); setring R; // Weyl algebra in variables x,y,Dx,Dy poly F = x2-y3; ideal I = (y^3 - x^2)*Dx - 2*x, (y^3 - x^2)*Dy + 3*y^2; // I = Dx*F, Dy*F; // I is not holonomic, since its dimension is not 4/2=2 gkdim(I); list L = DLoc(I, x2-y3); L[1]; // localized module (R/I)_f is isomorphic to R/LD0 L[2]; // description of b-function for localization } proc DLoc0(ideal I, poly F) "USAGE: DLoc0(I, f); I an ideal, f a poly RETURN: ring (a Weyl algebra) containing an ideal 'LD0' and a list 'BS' PURPOSE: compute the presentation of the localization of D/I w.r.t. f^s, @* where D is a Weyl Algebra, based on the output of procedure SDLoc ASSUME: the basering is similar to the output ring of SDLoc procedure NOTE: activate the output ring with the @code{setring} command. In this ring, @* - the ideal LD0 (given as Groebner basis) is the presentation of the @* localization, @* - the list BS contains roots and multiplicities of Bernstein @* polynomial of (D/I)_f. DISPLAY: If printlevel =1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example DLoc0; shows examples " { dmodappAssumeViolation(); /* assume: to be run in the output ring of SDLoc */ /* doing: add F, eliminate vars*Dvars, factorize BS */ /* analogue to annfs0 */ def @R2 = basering; // we're in D_n[s], where the elim ord for s is set ideal J = NF(I,std(F)); // make leadcoeffs positive int i; for (i=1; i<= ncols(J); i++) { if (leadcoef(J[i]) <0 ) { J[i] = -J[i]; } } J = J,F; ideal M = groebner(J); int Nnew = nvars(@R2); ideal K2 = nselect(M,1..Nnew-1); int ppl = printlevel-voice+2; dbprint(ppl,"// -1-1- _x,_Dx are eliminated in basering"); dbprint(ppl-1, K2); // the ring @R3 and the search for minimal negative int s ring @R3 = 0,s,dp; dbprint(ppl,"// -2-1- the ring @R3 = K[s] is ready"); ideal K3 = imap(@R2,K2); poly p = K3[1]; dbprint(ppl,"// -2-2- attempt the factorization"); list PP = factorize(p); //with constants and multiplicities ideal bs; intvec m; //the Bernstein polynomial is monic, so // we are not interested in constants for (i=2; i<= size(PP[1]); i++) //we delete P[1][1] and P[2][1] { bs[i-1] = PP[1][i]; m[i-1] = PP[2][i]; } ideal bbs; int srat=0; int HasRatRoots = 0; int sP; for (i=1; i<= size(bs); i++) { if (deg(bs[i]) == 1) { bbs = bbs,bs[i]; } } if (size(bbs)==0) { dbprint(ppl-1,"// -2-3- factorization: no rational roots"); // HasRatRoots = 0; HasRatRoots = 1; // s0 = -1 then sP = -1; // todo: return ideal with no subst and a b-function unfactorized } else { // exist rational roots dbprint(ppl-1,"// -2-3- factorization: rational roots found"); HasRatRoots = 1; // dbprint(ppl-1,bbs); bbs = bbs[2..ncols(bbs)]; ideal P = bbs; dbprint(ppl-1,P); srat = size(bs) - size(bbs); // define minIntRoot on linear factors or find out that it doesn't exist intvec vP; number nP; P = normalize(P); // now leadcoef = 1 P = ideal(matrix(lead(P))-matrix(P)); sP = size(P); int cnt = 0; for (i=1; i<=sP; i++) { nP = leadcoef(P[i]); if ( (nP - int(nP)) == 0 ) { cnt++; vP[cnt] = int(nP); } } // if ( size(vP)>=2 ) // { // vP = vP[2..size(vP)]; // } if ( size(vP)==0 ) { // no roots! dbprint(ppl,"// -2-4- no integer root, setting s0 = -1"); sP = -1; // HasRatRoots = 0; // older stuff, here we do substitution HasRatRoots = 1; } else { HasRatRoots = 1; sP = -Max(-vP); dbprint(ppl,"// -2-4- minimal integer root found"); dbprint(ppl-1, sP); // int sP = minIntRoot(bbs,1); // P = normalize(P); // bs = -subst(bs,s,0); if (sP >=0) { dbprint(ppl,"// -2-5- nonnegative root, setting s0 = -1"); sP = -1; } else { dbprint(ppl,"// -2-5- the root is negative"); } } } if (HasRatRoots) { setring @R2; K2 = subst(I,s,sP); // IF min int root exists -> // create the ordinary Weyl algebra and put the result into it, // thus creating the ring @R5 // ELSE : return the same ring with new objects // keep: N, i,j,s, tmp, RL Nnew = Nnew - 1; // former 2*N; // list RL = ringlist(save); // is defined earlier // kill Lord, tmp, iv; list L = 0; list Lord, tmp; intvec iv; list RL = ringlist(basering); L[1] = RL[1]; L[4] = RL[4]; //char, minpoly // check whether vars have admissible names -> done earlier // list Name = RL[2]M // DName is defined earlier list NName; // = RL[2]; // skip the last var 's' for (i=1; i<=Nnew; i++) { NName[i] = RL[2][i]; } L[2] = NName; // dp ordering; string s = "iv="; for (i=1; i<=Nnew; i++) { s = s+"1,"; } s[size(s)] = ";"; execute(s); tmp = 0; tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; kill s; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[2] = tmp; tmp = 0; L[3] = Lord; // we are done with the list // Add: Plural part def @R4@ = ring(L); setring @R4@; int N = Nnew div 2; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R4 = nc_algebra(1,@D); setring @R4; kill @R4@; dbprint(ppl,"// -3-1- the ring @R4 is ready"); dbprint(ppl-1, @R4); ideal K4 = imap(@R2,K2); intvec vopt = option(get); option(redSB); dbprint(ppl,"// -3-2- the final cosmetic std"); K4 = groebner(K4); // std does the job too option(set,vopt); // total cleanup setring @R2; ideal bs = imap(@R3,bs); bs = -normalize(bs); // "-" for getting correct coeffs! bs = subst(bs,s,0); kill @R3; setring @R4; ideal bs = imap(@R2,bs); // only rationals are the entries list BS; BS[1] = bs; BS[2] = m; export BS; // list LBS = imap(@R3,LBS); // list BS; BS[1] = sbs; BS[2] = m; // BS; // export BS; ideal LD0 = K4; export LD0; return(@R4); } else { /* SHOULD NEVER GET THERE */ /* no rational/integer roots */ /* return objects in the copy of current ring */ setring @R2; ideal LD0 = I; poly BS = normalize(K2[1]); export LD0; export BS; return(@R2); } } example; { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def R = Weyl(); setring R; // Weyl algebra in variables x,y,Dx,Dy poly F = x2-y3; ideal I = (y^3 - x^2)*Dx - 2*x, (y^3 - x^2)*Dy + 3*y^2; // I = Dx*F, Dy*F; // moreover I is not holonomic, since its dimension is not 2 = 4/2 gkdim(I); // 3 def W = SDLoc(I,F); setring W; // creates ideal LD in W = R[s] def U = DLoc0(LD, x2-y3); setring U; // compute in R LD0; // Groebner basis of the presentation of localization BS; // description of b-function for localization } proc SDLoc(ideal I, poly F) "USAGE: SDLoc(I, f); I an ideal, f a poly RETURN: ring (basering extended by a new variable) containing an ideal 'LD' PURPOSE: compute a generic presentation of the localization of D/I w.r.t. f^s ASSUME: the basering D is a Weyl algebra over a field of characteristic 0 NOTE: Activate this ring with the @code{setring} command. In this ring, @* the ideal LD (given as Groebner basis) is the presentation of the @* localization. DISPLAY: If printlevel =1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example SDLoc; shows examples " { /* analogue to Sannfs */ /* printlevel >=4 gives debug info */ /* assume: we're in the Weyl algebra D in x1,x2,...,d1,d2,... */ dmodappAssumeViolation(); if (!isWeyl()) { ERROR("Basering is not a Weyl algebra"); } def save = basering; /* 1. create D as in LOT */ /* ordering: eliminate t,dt */ int ppl = printlevel-voice+2; int N = nvars(save); N = N div 2; int Nnew = 2*N + 3; // t,Dt,s int i,j; string s; list RL = ringlist(save); list L, Lord; list tmp; intvec iv; L[1] = RL[1]; // char L[4] = RL[4]; // char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; RName[1] = "@t"; RName[2] = "@Dt"; RName[3] = "@s"; for(i=1;i<=N;i++) { for(j=1; j<=size(RName);j++) { if (Name[i] == RName[j]) { ERROR("Variable names should not include @t,@Dt,@s"); } } } // now, create the names for new vars tmp = 0; tmp[1] = "@t"; tmp[2] = "@Dt"; list SName ; SName[1] = "@s"; list NName = tmp + Name + SName; L[2] = NName; tmp = 0; kill NName; // block ord (a(1,1),dp); tmp[1] = "a"; // string iv = 1,1; tmp[2] = iv; //intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s = "iv="; for(i=1;i<=Nnew;i++) { s = s+"1,"; } s[size(s)]= ";"; execute(s); tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2] = iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; @D[1,2]=1; for(i=1; i<=N; i++) { @D[2+i,N+2+i]=1; } // ADD [s,t]=-t, [s,Dt]=Dt @D[1,Nnew] = -var(1); @D[2,Nnew] = var(2); def @R = nc_algebra(1,@D); setring @R; kill @R@; dbprint(ppl,"// -1-1- the ring @R(@t,@Dt,_x,_Dx,@s) is ready"); dbprint(ppl-1, @R); poly F = imap(save,F); ideal I = imap(save,I); dbprint(ppl-1, "the ideal after map:"); dbprint(ppl-1, I); poly p = 0; for(i=1; i<=N; i++) { p = diff(F,var(2+i))*@Dt + var(2+N+i); dbprint(ppl-1, p); I = subst(I,var(2+N+i),p); dbprint(ppl-1, var(2+N+i)); p = 0; } I = I, @t - F; // t*Dt + s +1 reduced with t-f gives f*Dt + s I = I, F*var(2) + var(Nnew); // @s // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of @t,@Dt in @R"); dbprint(ppl-1, I); // ideal J = engine(I,eng); ideal J = groebner(I); dbprint(ppl-1,"// -1-2-1- result of the elimination of @t,@Dt in @R"); dbprint(ppl-1, J);; ideal K = nselect(J,1..2); dbprint(ppl,"// -1-3- @t,@Dt are eliminated"); dbprint(ppl-1, K); // K is without t, Dt K = groebner(K); // std does the job too // now, we must change the ordering // and create a ring without t, Dt setring save; // ----------- the ring @R3 ------------ // _x, _Dx,s; elim.ord for _x,_Dx. // keep: N, i,j,s, tmp, RL Nnew = 2*N+1; kill Lord, tmp, iv, RName; list Lord, tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; // char, minpoly // check whether vars hava admissible names -> done earlier // now, create the names for new var tmp[1] = "s"; list NName = Name + tmp; L[2] = NName; tmp = 0; // block ord (dp(N),dp); // string s is already defined s = "iv="; for (i=1; i<=Nnew-1; i++) { s = s+"1,"; } s[size(s)]=";"; execute(s); tmp[1] = "dp"; // string tmp[2] = iv; // intvec Lord[1] = tmp; // continue with dp 1,1,1,1... tmp[1] = "dp"; // string s[size(s)] = ","; s = s+"1;"; execute(s); kill s; kill NName; tmp[2] = iv; Lord[2] = tmp; tmp[1] = "C"; iv = 0; tmp[2]=iv; Lord[3] = tmp; tmp = 0; L[3] = Lord; // we are done with the list. Now add a Plural part def @R2@ = ring(L); setring @R2@; matrix @D[Nnew][Nnew]; for (i=1; i<=N; i++) { @D[i,N+i]=1; } def @R2 = nc_algebra(1,@D); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R2(_x,_Dx,s) is ready"); dbprint(ppl-1, @R2); ideal MM = maxideal(1); MM = 0,s,MM; map R01 = @R, MM; ideal K = R01(K); // total cleanup ideal LD = K; // make leadcoeffs positive for (i=1; i<= ncols(LD); i++) { if (leadcoef(LD[i]) <0 ) { LD[i] = -LD[i]; } } export LD; kill @R; return(@R2); } example; { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def R = Weyl(); // Weyl algebra on the variables x,y,Dx,Dy setring R; poly F = x2-y3; ideal I = Dx*F, Dy*F; // note, that I is not holonomic, since it's dimension is not 2 gkdim(I); // 3, while dim R = 4 def W = SDLoc(I,F); setring W; // = R[s], where s is a new variable LD; // Groebner basis of s-parametric presentation } // Groebner basis wrt weights and initial ideal business ////////////////////// proc GBWeight (ideal I, intvec u, intvec v, list #) "USAGE: GBWeight(I,u,v [,s,t,w]); @* I ideal, u,v intvecs, s,t optional ints, w an optional intvec RETURN: ideal, Groebner basis of I w.r.t. the weights u and v ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 @* and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). PURPOSE: computes a Groebner basis with respect to given weights NOTE: The weights u and v are understood as weight vectors for x(i) and D(i), @* respectively. According to (SST), one computes the homogenization of a @* given ideal relative to (u,v), then one computes a Groebner basis and @* returns the dehomogenization of the result. @* If s<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. @* If t<>0, a matrix ordering is used for Groebner basis computations, @* otherwise, and by default, a block ordering is used. @* If w is given and consists of exactly 2*n strictly positive entries, @* w is used for constructing the weighted homogenized Weyl algebra, @* see Noro (2002). Otherwise, and by default, the homogenization weight @* (1,...,1) is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example GBWeight; shows examples " { dmodappMoreAssumeViolation(); int ppl = printlevel - voice +2; def save = basering; int n = nvars(save) div 2; int whichengine = 0; // default int methodord = 0; // default intvec homogweights = 1:(2*n); // default if (size(#)>0) { if (intLike(#[1])) { whichengine = int(#[1]); } if (size(#)>1) { if (intLike(#[2])) { methodord = int(#[2]); } if (size(#)>2) { if (typeof(#[3])=="intvec") { if (size(#[3])==2*n && allPositive(#[3])==1) { homogweights = #[3]; } else { print("// Homogenization weight vector must consist of positive entries and be"); print("// of size " + string(n) + ". Using weight (1,...,1)."); } } } } } // 1. create homogenized Weyl algebra // 1.1 create ordering int i; list RL = ringlist(save); int N = 2*n+1; intvec uv = u,v,0; homogweights = homogweights,1; list Lord = list(list("a",homogweights)); list C0 = list("C",intvec(0)); if (methodord == 0) // default: blockordering { Lord[5] = C0; Lord[4] = list("lp",intvec(1)); Lord[3] = list("dp",intvec(1:(N-1))); Lord[2] = list("a",uv); } else // M() ordering { intmat @Ord[N][N]; @Ord[1,1..N] = uv; @Ord[2,1..N] = 1:(N-1); for (i=1; i<=N-2; i++) { @Ord[2+i,N - i] = -1; } dbprint(ppl-1,"// the ordering matrix:",@Ord); Lord[2] = list("M",intvec(@Ord)); Lord[3] = C0; } // 1.2 the homog var list Lvar = RL[2]; Lvar[N] = safeVarName("h","cv"); // 1.3 create commutative ring list L@@Dh = RL; L@@Dh = L@@Dh[1..4]; L@@Dh[2] = Lvar; L@@Dh[3] = Lord; def @Dh = ring(L@@Dh); kill L@@Dh; setring @Dh; // 1.4 create non-commutative relations matrix @relD[N][N]; for (i=1; i<=n; i++) { @relD[i,n+i] = var(N)^(homogweights[i]+homogweights[n+i]); } def Dh = nc_algebra(1,@relD); setring Dh; kill @Dh; dbprint(ppl-1,"// computing in ring",Dh); // 2. Compute the initial ideal ideal I = imap(save,I); I = homog(I,var(N)); // 2.1 the hard part: Groebner basis computation dbprint(ppl, "// starting Groebner basis computation with engine: "+string(whichengine)); I = engine(I, whichengine); dbprint(ppl, "// finished Groebner basis computation"); dbprint(ppl-1, "// ideal before dehomogenization is " +string(I)); I = subst(I,var(N),1); // dehomogenization setring save; I = imap(Dh,I); kill Dh; return(I); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def D2 = Weyl(); setring D2; ideal I = 3*x^2*Dy+2*y*Dx,2*x*Dx+3*y*Dy+6; intvec u = -2,-3; intvec v = -u; GBWeight(I,u,v); ideal J = std(I); GBWeight(J,u,v); // same as above u = 0,1; GBWeight(I,u,v); } proc inForm (def I, intvec w) "USAGE: inForm(I,w); I ideal or poly, w intvec RETURN: ideal, generated by initial forms of generators of I w.r.t. w, or @* poly, initial form of input poly w.r.t. w PURPOSE: computes the initial form of an ideal or a poly w.r.t. the weight w NOTE: The size of the weight vector must be equal to the number of variables @* of the basering. EXAMPLE: example inForm; shows examples " { string inp1 = typeof(I); if ((inp1 <> "ideal") && (inp1 <> "poly")) { ERROR("first argument has to be an ideal or a poly"); } if (size(w) != nvars(basering)) { ERROR("weight vector has wrong dimension"); } ideal II = I; int j; poly g; ideal J; for (j=1; j<=ncols(II); j++) { g = II[j]; J[j] = g - jet(g,deg(g,w)-1,w); } if (inp1 == "ideal") { return(J); } else { return(J[1]); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def D = Weyl(); setring D; poly F = 3*x^2*Dy+2*y*Dx; poly G = 2*x*Dx+3*y*Dy+6; ideal I = F,G; intvec w1 = -1,-1,1,1; intvec w2 = -1,-2,1,2; intvec w3 = -2,-3,2,3; inForm(I,w1); inForm(I,w2); inForm(I,w3); inForm(F,w1); } proc initialIdealW(ideal I, intvec u, intvec v, list #) "USAGE: initialIdealW(I,u,v [,s,t,w]); @* I ideal, u,v intvecs, s,t optional ints, w an optional intvec RETURN: ideal, GB of initial ideal of the input ideal wrt the weights u and v ASSUME: The basering is the n-th Weyl algebra in characteristic 0 and for all @* 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the @* sequence of variables is given by x(1),...,x(n),D(1),...,D(n), @* where D(i) is the differential operator belonging to x(i). PURPOSE: computes the initial ideal with respect to given weights. NOTE: u and v are understood as weight vectors for x(1..n) and D(1..n) @* respectively. @* If s<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. @* If t<>0, a matrix ordering is used for Groebner basis computations, @* otherwise, and by default, a block ordering is used. @* If w is given and consists of exactly 2*n strictly positive entries, @* w is used as homogenization weight. @* Otherwise, and by default, the homogenization weight (1,...,1) is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example initialIdealW; shows examples " { // assumption check in GBWeight int ppl = printlevel - voice + 2; printlevel = printlevel + 1; I = GBWeight(I,u,v,#); printlevel = printlevel - 1; intvec uv = u,v; I = inForm(I,uv); int eng; if (size(#)>0) { if(typeof(#[1])=="int" || typeof(#[1])=="number") { eng = int(#[1]); } } dbprint(ppl,"// starting cosmetic Groebner basis computation"); I = engine(I,eng); dbprint(ppl,"// finished cosmetic Groebner basis computation"); return(I); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def D2 = Weyl(); setring D2; ideal I = 3*x^2*Dy+2*y*Dx,2*x*Dx+3*y*Dy+6; intvec u = -2,-3; intvec v = -u; initialIdealW(I,u,v); ideal J = std(I); initialIdealW(J,u,v); // same as above u = 0,1; initialIdealW(I,u,v); } proc initialMalgrange (poly f,list #) "USAGE: initialMalgrange(f,[,a,b,v]); f poly, a,b optional ints, v opt. intvec RETURN: ring, Weyl algebra induced by basering, extended by two new vars t,Dt PURPOSE: computes the initial Malgrange ideal of a given polynomial w.r.t. the @* weight vector (-1,0...,0,1,0,...,0) such that the weight of t is -1 @* and the weight of Dt is 1. ASSUME: The basering is commutative and over a field of characteristic 0. NOTE: Activate the output ring with the @code{setring} command. @* The returned ring contains the ideal 'inF', being the initial ideal @* of the Malgrange ideal of f. @* Varnames of the basering should not include t and Dt. @* If a<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. @* If b<>0, a matrix ordering is used for Groebner basis computations, @* otherwise, and by default, a block ordering is used. @* If a positive weight vector v is given, the weight @* (d,v[1],...,v[n],1,d+1-v[1],...,d+1-v[n]) is used for homogenization @* computations, where d denotes the weighted degree of f. @* Otherwise and by default, v is set to (1,...,1). See Noro (2002). DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example initialMalgrange; shows examples " { dmodappAssumeViolation(); if (!isCommutative()) { ERROR("Basering must be commutative."); } int ppl = printlevel - voice + 2; def save = basering; int n = nvars(save); int i; int whichengine = 0; // default int methodord = 0; // default intvec u0 = 1:n; // default if (size(#)>0) { if (intLike(#[1])) { whichengine = int(#[1]); } if (size(#)>1) { if (intLike(#[2])) { methodord = int(#[2]); } if (size(#)>2) { if ((typeof(#[3])=="intvec") && (size(#[3])==n) && (allPositive(#[3])==1)) { u0 = #[3]; } } } } list RL = ringlist(save); RL = RL[1..4]; // if basering is commutative nc_algebra list C0 = list("C",intvec(0)); // 1. create homogenization weights // 1.1. get the weighted degree of f list Lord = list(list("wp",u0),C0); list L@r = RL; L@r[3] = Lord; def r = ring(L@r); kill L@r,Lord; setring r; poly f = imap(save,f); int d = deg(f); setring save; kill r; // 1.2 the homogenization weights intvec homogweights = d; homogweights[n+2] = 1; for (i=1; i<=n; i++) { homogweights[i+1] = u0[i]; homogweights[n+2+i] = d+1-u0[i]; } // 2. create extended Weyl algebra int N = 2*n+2; // 2.1 create names for vars string vart = safeVarName("t","cv"); string varDt = safeVarName("D"+vart,"cv"); while (varDt <> "D"+vart) { vart = safeVarName("@"+vart,"cv"); varDt = safeVarName("D"+vart,"cv"); } list Lvar; Lvar[1] = vart; Lvar[n+2] = varDt; for (i=1; i<=n; i++) { Lvar[i+1] = string(var(i)); Lvar[i+n+2] = safeVarName("D" + string(var(i)),"cv"); } // 2.2 create ordering list Lord = list(list("dp",intvec(1:N)),C0); // 2.3 create the (n+1)-th Weyl algebra list L@D = RL; L@D[2] = Lvar; L@D[3] = Lord; def @D = ring(L@D); kill L@D; setring @D; def D = Weyl(); setring D; kill @D; dbprint(ppl,"// the (n+1)-th Weyl algebra :" ,D); // 3. compute the initial ideal // 3.1 create the Malgrange ideal poly f = imap(save,f); ideal I = var(1)-f; for (i=1; i<=n; i++) { I = I, var(n+2+i)+diff(f,var(i+1))*var(n+2); } // I = engine(I,whichengine); // todo efficient to compute GB wrt dp first? // 3.2 computie the initial ideal intvec w = 1,0:n; printlevel = printlevel + 1; I = initialIdealW(I,-w,w,whichengine,methodord,homogweights); printlevel = printlevel - 1; ideal inF = I; attrib(inF,"isSB",1); export(inF); setring save; return(D); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = x^2+y^3+x*y^2; def D = initialMalgrange(f); setring D; inF; setring r; intvec v = 3,2; def D2 = initialMalgrange(f,1,1,v); setring D2; inF; } // restriction and integration //////////////////////////////////////////////// static proc restrictionModuleEngine (ideal I, intvec w, list #) // returns list L with 2 entries of type ideal // L[1]=basis of free module, L[2]=generating system of submodule // #=eng,m,G; eng=engine; m=min int root of bfctIdeal(I,w); G=GB of I wrt (-w,w) { dmodappMoreAssumeViolation(); if (!isHolonomic(I)) { ERROR("Given ideal is not holonomic"); } int l0,l0set,Gset; ideal G; int whichengine = 0; // default if (size(#)>0) { if (intLike(#[1])) { whichengine = int(#[1]); } if (size(#)>1) { if (intLike(#[2])) { l0 = int(#[2]); l0set = 1; } if (size(#)>2) { if (typeof(#[3])=="ideal") { G = #[3]; Gset = 1; } } } } int ppl = printlevel; int i,j,k; int n = nvars(basering) div 2; if (w == 0:size(w)) { ERROR("weight vector must not be zero"); } if (size(w)<>n) { ERROR("weight vector must have exactly " + string(n) + " entries"); } for (i=1; i<=n; i++) { if (w[i]<0) { ERROR("weight vector must not have negative entries"); } } intvec ww = -w,w; if (!Gset) { G = GBWeight(I,-w,w,whichengine); dbprint(ppl,"// found GB wrt weight " +string(w)); dbprint(ppl-1,"// " + string(G)); } if (!l0set) { ideal inG = inForm(G,ww); inG = engine(inG,whichengine); poly s = 0; for (i=1; i<=n; i++) { s = s + w[i]*var(i)*var(i+n); } vector v = pIntersect(s,inG); list L = bFactor(vec2poly(v)); dbprint(ppl,"// found b-function of given ideal wrt weight " + string(w)); dbprint(ppl-1,"// roots: "+string(L[1])); dbprint(ppl-1,"// multiplicities: "+string(L[2])); kill inG,v,s; L = intRoots(L); // integral roots of b-function if (L[2]==0:size(L[2])) // no integral roots { return(list(ideal(0),ideal(0))); } intvec v; for (i=1; i<=ncols(L[1]); i++) { v[i] = int(L[1][i]); } l0 = Max(v); dbprint(ppl,"// maximal integral root is " +string(l0)); kill L,v; } if (l0 < 0) // maximal integral root is < 0 { return(list(ideal(0),ideal(0))); } intvec m; for (i=ncols(G); i>0; i--) { m[i] = deg(G[i],ww); } dbprint(ppl,"// weighted degree of generators of GB is " +string(m)); def save = basering; list RL = ringlist(save); RL = RL[1..4]; list Lvar; j = 1; intvec neww; for (i=1; i<=n; i++) { if (w[i]>0) { Lvar[j] = string(var(i+n)); neww[j] = w[i]; j++; } } list Lord; Lord[1] = list("dp",intvec(1:n)); Lord[2] = list("C", intvec(0)); RL[2] = Lvar; RL[3] = Lord; def r = ring(RL); kill Lvar, Lord, RL; setring r; ideal B; list Blist; intvec mm = l0,-m+l0; for (i=0; i<=Max(mm); i++) { B = weightKB(std(0),i,neww); Blist[i+1] = B; } setring save; list Blist = imap(r,Blist); ideal ff = maxideal(1); for (i=1; i<=n; i++) { if (w[i]<>0) { ff[i] = 0; } } map f = save,ff; ideal B,M; poly p; for (i=1; i<=size(G); i++) { for (j=1; j<=l0-m[i]+1; j++) { B = Blist[j]; for (k=1; k<=ncols(B); k++) { p = B[k]*G[i]; p = f(p); M[size(M)+1] = p; } } } ideal Bl0 = Blist[1..(l0+1)]; dbprint(ppl,"// found basis of free module"); dbprint(ppl-1,"// " + string(Bl0)); dbprint(ppl,"// found generators of submodule"); dbprint(ppl-1,"// " + string(M)); return(list(Bl0,M)); } static proc restrictionModuleOutput (ideal B, ideal N, intvec w, int eng, string str) // returns ring, which contains module "str" { int n = nvars(basering) div 2; int i,j; def save = basering; // 1: create new ring list RL = ringlist(save); RL = RL[1..4]; list V = RL[2]; poly prodvar = 1; int zeropresent; j = 0; for (i=1; i<=n; i++) { if (w[i]<>0) { V = delete(V,i-j); V = delete(V,i-2*j-1+n); j = j+1; prodvar = prodvar*var(i)*var(i+n); } else { zeropresent = 1; } } if (!zeropresent) // restrict/integrate all vars, return input ring { def newR = save; } else { RL[2] = V; V = list(); V[1] = list("C", intvec(0)); V[2] = list("dp",intvec(1:(2*size(ideal(w))))); RL[3] = V; def @D = ring(RL); setring @D; def newR = Weyl(); setring save; kill @D; } // 2. get coker representation of module module M = coeffs(N,B,prodvar); if (zeropresent) { setring newR; module M = imap(save,M); } M = engine(M,eng); M = prune(M); M = engine(M,eng); execute("module " + str + " = M;"); execute("export(" + str + ");"); setring save; return(newR); } proc restrictionModule (ideal I, intvec w, list #) "USAGE: restrictionModule(I,w,[,eng,m,G]); @* I ideal, w intvec, eng and m optional ints, G optional ideal RETURN: ring (a Weyl algebra) containing a module 'resMod' ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 @* and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). @* Further, assume that I is holonomic and that w is n-dimensional with @* non-negative entries. PURPOSE: computes the restriction module of a holonomic ideal to the subspace @* defined by the variables corresponding to the non-zero entries of the @* given intvec NOTE: The output ring is the Weyl algebra defined by the zero entries of w. @* It contains a module 'resMod' being the restriction module of I wrt w. @* If there are no zero entries, the input ring is returned. @* If eng<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. @* The minimal integer root of the b-function of I wrt the weight (-w,w) @* can be specified via the optional argument m. @* The optional argument G is used for specifying a Groebner Basis of I @* wrt the weight (-w,w), that is, the initial form of G generates the @* initial ideal of I wrt the weight (-w,w). @* Further note, that the assumptions on m and G (if given) are not @* checked. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example restrictionModule; shows examples " { list L = restrictionModuleEngine(I,w,#); int eng; if (size(#)>0) { if (intLike(#[1])) { eng = int(#[1]); } } def newR = restrictionModuleOutput(L[1],L[2],w,eng,"resMod"); return(newR); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,x,b,Da,Dx,Db),dp; def D3 = Weyl(); setring D3; ideal I = a*Db-Dx+2*Da, x*Db-Da, x*Da+a*Da+b*Db+1, x*Dx-2*x*Da-a*Da, b*Db^2+Dx*Da-Da^2+Db, a*Dx*Da+2*x*Da^2+a*Da^2+b*Dx*Db+Dx+2*Da; intvec w = 1,0,0; def rm = restrictionModule(I,w); setring rm; rm; print(resMod); } static proc restrictionIdealEngine (ideal I, intvec w, string cf, list #) { int eng; if (size(#)>0) { if(intLike(#[1])) { eng = int(#[1]); } } def save = basering; if (cf == "restriction") { def newR = restrictionModule(I,w,#); setring newR; matrix M = resMod; kill resMod; } if (cf == "integral") { def newR = integralModule(I,w,#); setring newR; matrix M = intMod; kill intMod; } int i,r,c; r = nrows(M); c = ncols(M); ideal J; if (r == 1) // nothing to do { J = M; } else { matrix zm[r-1][1]; // zero matrix matrix v[r-1][1]; for (i=1; i<=c; i++) { if (M[1,i]<>0) { v = M[2..r,i]; if (v == zm) { J[size(J)+1] = M[1,i]; } } } } J = engine(J,eng); if (cf == "restriction") { ideal resIdeal = J; export(resIdeal); } if (cf == "integral") { ideal intIdeal = J; export(intIdeal); } setring save; return(newR); } proc restrictionIdeal (ideal I, intvec w, list #) "USAGE: restrictionIdeal(I,w,[,eng,m,G]); @* I ideal, w intvec, eng and m optional ints, G optional ideal RETURN: ring (a Weyl algebra) containing an ideal 'resIdeal' ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 @* and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). @* Further, assume that I is holonomic and that w is n-dimensional with @* non-negative entries. PURPOSE: computes the restriction ideal of a holonomic ideal to the subspace @* defined by the variables corresponding to the non-zero entries of the @* given intvec NOTE: The output ring is the Weyl algebra defined by the zero entries of w. @* It contains an ideal 'resIdeal' being the restriction ideal of I wrt w. @* If there are no zero entries, the input ring is returned. @* If eng<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. @* The minimal integer root of the b-function of I wrt the weight (-w,w) @* can be specified via the optional argument m. @* The optional argument G is used for specifying a Groebner basis of I @* wrt the weight (-w,w), that is, the initial form of G generates the @* initial ideal of I wrt the weight (-w,w). @* Further note, that the assumptions on m and G (if given) are not @* checked. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example restrictionIdeal; shows examples " { def rm = restrictionIdealEngine(I,w,"restriction",#); return(rm); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,x,b,Da,Dx,Db),dp; def D3 = Weyl(); setring D3; ideal I = a*Db-Dx+2*Da, x*Db-Da, x*Da+a*Da+b*Db+1, x*Dx-2*x*Da-a*Da, b*Db^2+Dx*Da-Da^2+Db, a*Dx*Da+2*x*Da^2+a*Da^2+b*Dx*Db+Dx+2*Da; intvec w = 1,0,0; def D2 = restrictionIdeal(I,w); setring D2; D2; resIdeal; } proc fourier (ideal I, list #) "USAGE: fourier(I[,v]); I an ideal, v an optional intvec RETURN: ideal PURPOSE: computes the Fourier transform of an ideal in a Weyl algebra ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 @* and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). NOTE: The Fourier automorphism is defined by mapping x(i) to -D(i) and @* D(i) to x(i). @* If v is an intvec with entries ranging from 1 to n, the Fourier @* transform of I restricted to the variables given by v is computed. SEE ALSO: inverseFourier EXAMPLE: example fourier; shows examples " { dmodappMoreAssumeViolation(); intvec v; if (size(#)>0) { if(typeof(#[1])=="intvec") { v = #[1]; } } int n = nvars(basering) div 2; int i; if(v <> 0:size(v)) { v = sortIntvec(v)[1]; for (i=1; in) { ERROR("Entries of intvec must range from 1 to "+string(n)); } m[v[i]] = -var(v[i]+n); m[v[i]+n] = var(v[i]); } map F = basering,m; ideal FI = F(I); return(FI); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def D2 = Weyl(); setring D2; ideal I = x*Dx+2*y*Dy+2, x^2*Dx+y*Dx+2*x; intvec v = 2; fourier(I,v); fourier(I); } proc inverseFourier (ideal I, list #) "USAGE: inverseFourier(I[,v]); I an ideal, v an optional intvec RETURN: ideal PURPOSE: computes the inverse Fourier transform of an ideal in a Weyl algebra ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 @* and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). NOTE: The Fourier automorphism is defined by mapping x(i) to -D(i) and @* D(i) to x(i). @* If v is an intvec with entries ranging from 1 to n, the inverse Fourier @* transform of I restricted to the variables given by v is computed. SEE ALSO: fourier EXAMPLE: example inverseFourier; shows examples " { dmodappMoreAssumeViolation(); intvec v; if (size(#)>0) { if(typeof(#[1])=="intvec") { v = #[1]; } } int n = nvars(basering) div 2; int i; if(v <> 0:size(v)) { v = sortIntvec(v)[1]; for (i=1; in) { ERROR("Entries of intvec must range between 1 and "+string(n)); } m[v[i]] = var(v[i]+n); m[v[i]+n] = -var(v[i]); } map F = basering,m; ideal FI = F(I); return(FI); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def D2 = Weyl(); setring D2; ideal I = x*Dx+2*y*Dy+2, x^2*Dx+y*Dx+2*x; intvec v = 2; ideal FI = fourier(I); inverseFourier(FI); } proc integralModule (ideal I, intvec w, list #) "USAGE: integralModule(I,w,[,eng,m,G]); @* I ideal, w intvec, eng and m optional ints, G optional ideal RETURN: ring (a Weyl algebra) containing a module 'intMod' ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 @* and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). @* Further, assume that I is holonomic and that w is n-dimensional with @* non-negative entries. PURPOSE: computes the integral module of a holonomic ideal w.r.t. the subspace @* defined by the variables corresponding to the non-zero entries of the @* given intvec NOTE: The output ring is the Weyl algebra defined by the zero entries of w. @* It contains a module 'intMod' being the integral module of I wrt w. @* If there are no zero entries, the input ring is returned. @* If eng<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. @* Let F(I) denote the Fourier transform of I w.r.t. w. @* The minimal integer root of the b-function of F(I) w.r.t. the weight @* (-w,w) can be specified via the optional argument m. @* The optional argument G is used for specifying a Groebner Basis of F(I) @* wrt the weight (-w,w), that is, the initial form of G generates the @* initial ideal of F(I) w.r.t. the weight (-w,w). @* Further note, that the assumptions on m and G (if given) are not @* checked. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example integralModule; shows examples " { int l0,l0set,Gset; ideal G; int whichengine = 0; // default if (size(#)>0) { if (intLike(#[1])) { whichengine = int(#[1]); } if (size(#)>1) { if (intLike(#[2])) { l0 = int(#[2]); l0set = 1; } if (size(#)>2) { if (typeof(#[3])=="ideal") { G = #[3]; Gset = 1; } } } } int ppl = printlevel; int i; int n = nvars(basering) div 2; intvec v; for (i=1; i<=n; i++) { if (w[i]>0) { if (v == 0:size(v)) { v[1] = i; } else { v[size(v)+1] = i; } } } ideal FI = fourier(I,v); dbprint(ppl,"// computed Fourier transform of given ideal"); dbprint(ppl-1,"// " + string(FI)); list L; if (l0set) { if (Gset) // l0 and G given { L = restrictionModuleEngine(FI,w,whichengine,l0,G); } else // l0 given, G not { L = restrictionModuleEngine(FI,w,whichengine,l0); } } else // nothing given { L = restrictionModuleEngine(FI,w,whichengine); } ideal B,N; B = inverseFourier(L[1],v); N = inverseFourier(L[2],v); def newR = restrictionModuleOutput(B,N,w,whichengine,"intMod"); return(newR); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,b,Dx,Db),dp; def D2 = Weyl(); setring D2; ideal I = x*Dx+2*b*Db+2, x^2*Dx+b*Dx+2*x; intvec w = 1,0; def im = integralModule(I,w); setring im; im; print(intMod); } proc integralIdeal (ideal I, intvec w, list #) "USAGE: integralIdeal(I,w,[,eng,m,G]); @* I ideal, w intvec, eng and m optional ints, G optional ideal RETURN: ring (a Weyl algebra) containing an ideal 'intIdeal' ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 @* and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). @* Further, assume that I is holonomic and that w is n-dimensional with @* non-negative entries. PURPOSE: computes the integral ideal of a holonomic ideal w.r.t. the subspace @* defined by the variables corresponding to the non-zero entries of the @* given intvec. NOTE: The output ring is the Weyl algebra defined by the zero entries of w. @* It contains ideal 'intIdeal' being the integral ideal of I w.r.t. w. @* If there are no zero entries, the input ring is returned. @* If eng<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. @* The minimal integer root of the b-function of I wrt the weight (-w,w) @* can be specified via the optional argument m. @* The optional argument G is used for specifying a Groebner basis of I @* wrt the weight (-w,w), that is, the initial form of G generates the @* initial ideal of I wrt the weight (-w,w). @* Further note, that the assumptions on m and G (if given) are not @* checked. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example integralIdeal; shows examples " { def im = restrictionIdealEngine(I,w,"integral",#); return(im); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,b,Dx,Db),dp; def D2 = Weyl(); setring D2; ideal I = x*Dx+2*b*Db+2, x^2*Dx+b*Dx+2*x; intvec w = 1,0; def D1 = integralIdeal(I,w); setring D1; D1; intIdeal; } proc deRhamCohomIdeal (ideal I, list #) "USAGE: deRhamCohomIdeal (I[,w,eng,k,G]); @* I ideal, w optional intvec, eng and k optional ints, G optional ideal RETURN: ideal ASSUME: The basering is the n-th Weyl algebra D over a field of characteristic @* zero and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). @* Further, assume that I is of special kind, namely let f in K[x] and @* consider the module K[x,1/f]f^m, where m is smaller than or equal to @* the minimal integer root of the Bernstein-Sato polynomial of f. @* Since this module is known to be a holonomic D-module, it has a cyclic @* presentation D/I. PURPOSE: computes a basis of the n-th de Rham cohomology group of the complement @* of the hypersurface defined by f NOTE: The elements of the basis are of the form f^m*p, where p runs over the @* entries of the returned ideal. @* If I does not satisfy the assumptions described above, the result might @* have no meaning. Note that I can be computed with @code{annfs}. @* If w is an intvec with exactly n strictly positive entries, w is used @* in the computation. Otherwise, and by default, w is set to (1,...,1). @* If eng<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. @* Let F(I) denote the Fourier transform of I wrt w. @* An integer smaller than or equal to the minimal integer root of the @* b-function of F(I) wrt the weight (-w,w) can be specified via the @* optional argument k. @* The optional argument G is used for specifying a Groebner Basis of F(I) @* wrt the weight (-w,w), that is, the initial form of G generates the @* initial ideal of F(I) wrt the weight (-w,w). @* Further note, that the assumptions on I, k and G (if given) are not @* checked. THEORY: (SST) pp. 232-235 DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. SEE ALSO: deRhamCohom EXAMPLE: example deRhamCohomIdeal; shows examples " { intvec w = 1:(nvars(basering) div 2); int l0,l0set,Gset; ideal G; int whichengine = 0; // default if (size(#)>0) { if (typeof(#[1])=="intvec") { if (allPositive(#[1])==1) { w = #[1]; } else { print("// Entries of intvec must be strictly positive"); print("// Using weight " + string(w)); } if (size(#)>1) { if (intLike(#[2])) { whichengine = int(#[2]); } if (size(#)>2) { if (intLike(#[3])) { l0 = int(#[3]); l0set = 1; } if (size(#)>3) { if (typeof(#[4])=="ideal") { G = #[4]; Gset = 1; } } } } } } int ppl = printlevel; int i,j; int n = nvars(basering) div 2; intvec v; for (i=1; i<=n; i++) { if (w[i]>0) { if (v == 0:size(v)) { v[1] = i; } else { v[size(v)+1] = i; } } } ideal FI = fourier(I,v); dbprint(ppl,"// computed Fourier transform of given ideal"); dbprint(ppl-1,"// " + string(FI)); list L; if (l0set) { if (Gset) // l0 and G given { L = restrictionModuleEngine(FI,w,whichengine,l0,G); } else // l0 given, G not { L = restrictionModuleEngine(FI,w,whichengine,l0); } } else // nothing given { L = restrictionModuleEngine(FI,w,whichengine); } ideal B,N; B = inverseFourier(L[1],v); N = inverseFourier(L[2],v); dbprint(ppl,"// computed integral module of given ideal"); dbprint(ppl-1,"// " + string(B)); dbprint(ppl-1,"// " + string(N)); ideal DR; poly p; poly Dt = 1; for (i=1; i<=n; i++) { Dt = Dt*var(i+n); } N = simplify(N,2+8); printlevel = printlevel-1; N = linReduceIdeal(N); N = simplify(N,2+8); for (i=1; i<=size(B); i++) { p = linReduce(B[i],N); if (p<>0) { DR[size(DR)+1] = B[i]*Dt; j=1; while ((j0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. @* If m is given, it is assumed to be less than or equal to the minimal @* integer root of the Bernstein-Sato polynomial of f. This assumption is @* not checked. If not specified, m is set to the minimal integer root of @* the Bernstein-Sato polynomial of f. THEORY: (SST) pp. 232-235 DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. SEE ALSO: deRhamCohomIdeal EXAMPLE: example deRhamCohom; shows example " { int ppl = printlevel - voice + 2; def save = basering; int n = nvars(save); intvec w = 1:n; int eng,l0,l0given; if (size(#)>0) { if (typeof(#[1])=="intvec") { w = #[1]; } if (size(#)>1) { if(intLike(#[2])) { eng = int(#[2]); } if (size(#)>2) { if(intLike(#[3])) { l0 = int(#[3]); l0given = 1; } } } } if (!isCommutative()) { ERROR("Basering must be commutative."); } int i; dbprint(ppl,"// Computing s-parametric annihilator Ann(f^s)..."); def A = Sannfs(f); setring A; dbprint(ppl,"// ...done"); dbprint(ppl-1,"// Got: " + string(LD)); poly f = imap(save,f); if (!l0given) { dbprint(ppl,"// Computing b-function of given poly..."); ideal LDf = LD,f; LDf = engine(LDf,eng); vector v = pIntersect(var(2*n+1),LDf); // BS poly of f list BS = bFactor(vec2poly(v)); dbprint(ppl,"// ...done"); dbprint(ppl-1,"// roots: " + string(BS[1])); dbprint(ppl-1,"// multiplicities: " + string(BS[2])); BS = intRoots(BS); intvec iv; for (i=1; i<=ncols(BS[1]); i++) { iv[i] = int(BS[1][i]); } l0 = Min(iv); kill v,iv,BS,LDf; } dbprint(ppl,"// Computing Ann(f^" + string(l0) + ")..."); LD = annfspecial(LD,f,l0,l0); // Ann(f^l0) // create new ring without s list RL = ringlist(A); RL = RL[1..4]; list Lt = RL[2]; Lt = delete(Lt,2*n+1); RL[2] = Lt; Lt = RL[3]; Lt = delete(Lt,2); RL[3] = Lt; def @B = ring(RL); setring @B; def B = Weyl(); setring B; kill @B; ideal LD = imap(A,LD); LD = engine(LD,eng); dbprint(ppl,"// ...done"); dbprint(ppl-1,"// Got: " + string(LD)); kill A; ideal DRJ = deRhamCohomIdeal(LD,w,eng); list DR = DRJ,l0; export(DR); setring save; return(B); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; poly f = x^3+y^3+z^3; def A = deRhamCohom(f); // we see that the K-dim is 2 setring A; DR; } // Appel hypergeometric functions ///////////////////////////////////////////// proc appelF1() "USAGE: appelF1(); RETURN: ring (a parametric Weyl algebra) containing an ideal 'IAppel1' PURPOSE: defines the ideal in a parametric Weyl algebra, @* which annihilates Appel F1 hypergeometric function NOTE: The output ring is a parametric Weyl algebra. It contains an ideal @* 'IAappel1' annihilating Appel F1 hypergeometric function. @* See (SST) p. 48. EXAMPLE: example appelF1; shows example " { // Appel F1, d = b', SST p.48 ring @r = (0,a,b,c,d),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp); def @S = Weyl(); setring @S; ideal IAppel1 = (x*Dx)*(x*Dx+y*Dy+c-1) - x*(x*Dx+y*Dy+a)*(x*Dx+b), (y*Dy)*(x*Dx+y*Dy+c-1) - y*(x*Dx+y*Dy+a)*(y*Dy+d), (x-y)*Dx*Dy - d*Dx + b*Dy; export IAppel1; kill @r; return(@S); } example { "EXAMPLE:"; echo = 2; def A = appelF1(); setring A; IAppel1; } proc appelF2() "USAGE: appelF2(); RETURN: ring (a parametric Weyl algebra) containing an ideal 'IAppel2' PURPOSE: defines the ideal in a parametric Weyl algebra, @* which annihilates Appel F2 hypergeometric function NOTE: The output ring is a parametric Weyl algebra. It contains an ideal @* 'IAappel2' annihilating Appel F2 hypergeometric function. @* See (SST) p. 85. EXAMPLE: example appelF2; shows example " { // Appel F2, c = b', SST p.85 ring @r = (0,a,b,c),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp); def @S = Weyl(); setring @S; ideal IAppel2 = (x*Dx)^2 - x*(x*Dx+y*Dy+a)*(x*Dx+b), (y*Dy)^2 - y*(x*Dx+y*Dy+a)*(y*Dy+c); export IAppel2; kill @r; return(@S); } example { "EXAMPLE:"; echo = 2; def A = appelF2(); setring A; IAppel2; } proc appelF4() "USAGE: appelF4(); RETURN: ring (a parametric Weyl algebra) containing an ideal 'IAppel4' PURPOSE: defines the ideal in a parametric Weyl algebra, @* which annihilates Appel F4 hypergeometric function NOTE: The output ring is a parametric Weyl algebra. It contains an ideal @* 'IAappel4' annihilating Appel F4 hypergeometric function. @* See (SST) p. 39. EXAMPLE: example appelF4; shows example " { // Appel F4, d = c', SST, p. 39 ring @r = (0,a,b,c,d),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp); def @S = Weyl(); setring @S; ideal IAppel4 = Dx*(x*Dx+c-1) - (x*Dx+y*Dy+a)*(x*Dx+y*Dy+b), Dy*(y*Dy+d-1) - (x*Dx+y*Dy+a)*(x*Dx+y*Dy+b); export IAppel4; kill @r; return(@S); } example { "EXAMPLE:"; echo = 2; def A = appelF4(); setring A; IAppel4; } // characteric variety //////////////////////////////////////////////////////// proc charVariety(ideal I, list #) "USAGE: charVariety(I [,eng]); I an ideal, eng an optional int RETURN: ring (commutative) containing an ideal 'charVar' PURPOSE: computes an ideal whose zero set is the characteristic variety of I in @* the sense of D-module theory ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 @* and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). NOTE: The output ring is commutative. It contains an ideal 'charVar'. @* If eng<>0, @code{std} is used for Groebner basis computations, @* otherwise, and by default, @code{slimgb} is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. SEE ALSO: charInfo EXAMPLE: example charVariety; shows examples " { // assumption check is done in GBWeight int eng; if (size(#)>0) { if (intLike(#[1])) { eng = int(#[1]); } } int ppl = printlevel - voice + 2; def save = basering; int n = nvars(save) div 2; intvec uv = (0:n),(1:n); list RL = ringlist(save); list L = RL[3]; L = insert(L,list("a",uv)); RL[3] = L; // TODO printlevel def Ra = ring(RL); setring Ra; dbprint(ppl,"// Starting Groebner basis computation..."); ideal I = imap(save,I); I = engine(I,eng); dbprint(ppl,"// ... done."); dbprint(ppl-1,"// Got: " + string(I)); setring save; RL = ringlist(save); RL = RL[1..4]; def newR = ring(RL); setring newR; ideal charVar = imap(Ra,I); charVar = inForm(charVar,uv); // charVar = groebner(charVar); export(charVar); setring save; return(newR); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),Dp; poly F = x3-y2; printlevel = 0; def A = annfs(F); setring A; // Weyl algebra LD; // the annihilator of F def CA = charVariety(LD); setring CA; CA; // commutative ring charVar; dim(std(charVar)); // hence I is holonomic } proc charInfo(ideal I) "USAGE: charInfo(I); I an ideal RETURN: ring (commut.) containing ideals 'charVar','singLoc' and list 'primDec' PURPOSE: computes characteristic variety of I (in the sense of D-module theory), @* its singular locus and primary decomposition ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 @* and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 @* holds, i.e. the sequence of variables is given by @* x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator @* belonging to x(i). NOTE: In the output ring, which is commutative: @* - the ideal 'charVar' is the characteristic variety char(I), @* - the ideal 'SingLoc' is the singular locus of char(I), @* - the list 'primDec' is the primary decomposition of char(I). DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example charInfo; shows examples " { int ppl = printlevel - voice + 2; def save = basering; dbprint(ppl,"// computing characteristic variety..."); def A = charVariety(I); setring A; dbprint(ppl,"// ...done"); dbprint(ppl-1,"// Got: " + string(charVar)); dbprint(ppl,"// computing singular locus..."); ideal singLoc = slocus(charVar); singLoc = groebner(singLoc); dbprint(ppl,"// ...done"); dbprint(ppl-1,"// Got: " + string(singLoc)); dbprint(ppl,"// computing primary decomposition..."); list primDec = primdecGTZ(charVar); dbprint(ppl,"// ...done"); //export(charVar,singLoc,primDec); export(singLoc,primDec); setring save; return(A); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),Dp; poly F = x3-y2; printlevel = 0; def A = annfs(F); setring A; // Weyl algebra LD; // the annihilator of F def CA = charInfo(LD); setring CA; CA; // commutative ring charVar; // characteristic variety singLoc; // singular locus primDec; // primary decomposition } // examples /////////////////////////////////////////////////////////////////// /* static proc exCusp() { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def R = Weyl(); setring R; poly F = x2-y3; ideal I = (y^3 - x^2)*Dx - 2*x, (y^3 - x^2)*Dy + 3*y^2; // I = Dx*F, Dy*F; def W = SDLoc(I,F); setring W; LD; def U = DLoc0(LD,x2-y3); setring U; LD0; BS; // the same with DLoc: setring R; DLoc(I,F); } static proc exWalther1() { // p.18 Rem 3.10 ring r = 0,(x,Dx),dp; def R = nc_algebra(1,1); setring R; poly F = x; ideal I = x*Dx+1; def W = SDLoc(I,F); setring W; LD; ideal J = LD, x; eliminate(J,x*Dx); // must be [1]=s // agree! // the same result with Dloc0: def U = DLoc0(LD,x); setring U; LD0; BS; } static proc exWalther2() { // p.19 Rem 3.10 cont'd ring r = 0,(x,Dx),dp; def R = nc_algebra(1,1); setring R; poly F = x; ideal I = (x*Dx)^2+1; def W = SDLoc(I,F); setring W; LD; ideal J = LD, x; eliminate(J,x*Dx); // must be [1]=s^2+2*s+2 // agree! // the same result with Dloc0: def U = DLoc0(LD,x); setring U; LD0; BS; // almost the same with DLoc setring R; DLoc(I,F); } static proc exWalther3() { // can check with annFs too :-) // p.21 Ex 3.15 LIB "nctools.lib"; ring r = 0,(x,y,z,w,Dx,Dy,Dz,Dw),dp; def R = Weyl(); setring R; poly F = x2+y2+z2+w2; ideal I = Dx,Dy,Dz,Dw; def W = SDLoc(I,F); setring W; LD; ideal J = LD, x2+y2+z2+w2; eliminate(J,x*y*z*w*Dx*Dy*Dz*Dw); // must be [1]=s^2+3*s+2 // agree ring r2 = 0,(x,y,z,w),dp; poly F = x2+y2+z2+w2; def Z = annfs(F); setring Z; LD; BS; // the same result with Dloc0: setring W; def U = DLoc0(LD,x2+y2+z2+w2); setring U; LD0; BS; // the same result with DLoc: setring R; DLoc(I,F); } static proc ex_annRat() { // more complicated example for annRat ring r = 0,(x,y,z),dp; poly f = x3+y3+z3; // mir = -2 poly g = x*y*z; def A = annRat(g,f); setring A; } */ singular-4.0.3+ds/Singular/LIB/dmodloc.lib000066400000000000000000002034371266270727000202710ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////// version="version dmodloc.lib 4.0.0.0 Jun_2013 "; // $Id: e233149e51dff5b4406ed3429c90bfb8fb48a558 $ category="Noncommutative"; info=" LIBRARY: dmodloc.lib Localization of algebraic D-modules and applications AUTHOR: Daniel Andres, daniel.andres@math.rwth-aachen.de Support: DFG Graduiertenkolleg 1632 `Experimentelle und konstruktive Algebra' OVERVIEW: Let I be a left ideal in the n-th polynomial Weyl algebra D=K[x] and let f be a polynomial in K[x]. If D/I is a holonomic module over D, it is known that the localization of D/I at f is also holonomic. The procedure @code{Dlocalization} computes an ideal J in D such that this localization is isomorphic to D/J as D-modules. If one regards I as an ideal in the rational Weyl algebra as above, K(x)*I, and intersects with K[x], the result is called the Weyl closure of I. The procedures @code{WeylClosure} (if I has finite holonomic rank) and @code{WeylClosure1} (if I is in the first Weyl algebra) can be used for computations. As an application of the Weyl closure, the procedure @code{annRatSyz} computes a holonomic part of the annihilator of a rational function by computing certain syzygies. The full annihilator can be obtained by taking the Weyl closure of the result. If one regards the left ideal I as system of linear PDEs, one can find its polynomial solutions with @code{polSol} (if I is holonomic) or @code{polSolFiniteRank} (if I is of finite holonomic rank). Rational solutions can be obtained with @code{ratSol}. The procedure @code{bfctBound} computes a possible multiple of the b-function for f^s*u at a generic root of f. Here, u stands for [1] in D/I. This library also offers the procedures @code{holonomicRank} and @code{DsingularLocus} to compute the holonomic rank and the singular locus of the D-module D/I. REFERENCES: (OT) T. Oaku, N. Takayama: `Algorithms for D-modules', Journal of Pure and Applied Algebra, 1998. @* (OTT) T. Oaku, N. Takayama, H. Tsai: `Polynomial and rational solutions of holonomic systems', Journal of Pure and Applied Algebra, 2001. @* (OTW) T. Oaku, N. Takayama, U. Walther: `A Localization Algorithm for D-modules', Journal of Symbolic Computation, 2000. @* (Tsa) H. Tsai: `Algorithms for algebraic analysis', PhD thesis, 2000. PROCEDURES: Dlocalization(I,f[,k,e]); computes the localization of a D-module WeylClosure(I); computes the Weyl closure of an ideal in the Weyl algebra WeylClosure1(L); computes the Weyl closure of operator in first Weyl algebra holonomicRank(I); computes the holonomic rank of I DsingularLocus(I); computes the singular locus of a D-module polSol(I[,w,m]); computes basis of polynomial solutions to the given system polSolFiniteRank(I[,w]); computes basis of polynomial solutions to given system ratSol(I); computes basis of rational solutions to the given system bfctBound(I,f[,primdec]); computes multiple of b-function for f^s*u annRatSyz(f,g[,db,eng]); computes part of annihilator of rational function g/f dmodGeneralAssumptionCheck(); check general assumptions extendWeyl(S); extends basering (Weyl algebra) by given vars polyVars(f,v); checks whether f contains only variables indexed by v monomialInIdeal(I); computes all monomials appearing in generators of ideal vars2pars(v); converts variables specified by v into parameters minIntRoot2(L); finds minimal integer root in a list of roots maxIntRoot(L); finds maximal integer root in a list of roots dmodAction(id,f[,v]); computes the natural action of a D-module on K[x] dmodActionRat(id,w); computes the natural action of a D-module on K(x) simplifyRat(v); simplifies rational function addRat(v,w); adds rational functions multRat(v,w); multiplies rational functions diffRat(v,j); derives rational function commRing(); deletes non-commutative relations from ring rightNFWeyl(id,k); computes right NF wrt right ideal (var(k)) in Weyl algebra KEYWORDS: D-module; holonomic rank; singular locus of D-module; D-localization; localization of D-module; characteristic variety; Weyl closure; polynomial solutions; rational solutions; annihilator of rational function SEE ALSO: bfun_lib, dmod_lib, dmodapp_lib, dmodvar_lib, gmssing_lib "; /* CHANGELOG: 12.11.12: bugfixes, updated docu 17.12.12: updated docu, removed redundant procedure killTerms */ LIB "bfun.lib"; // for pIntersect etc LIB "dmodapp.lib"; // for GBWeight, charVariety etc LIB "nctools.lib"; // for Weyl, isWeyl etc // TODO uncomment this once chern.lib is ready // LIB "chern.lib"; // for orderedPartition // testing for consistency of the library ///////////////////////////////////// static proc testdmodloc() { example dmodGeneralAssumptionCheck; example safeVarName; example extendWeyl; example polyVars; example monomialInIdeal; example vars2pars; example minIntRoot2; example maxIntRoot; example dmodAction; example dmodActionRat; example simplifyRat; example addRat; example multRat; example diffRat; example commRing; example holonomicRank; example DsingularLocus; example rightNFWeyl; example Dlocalization; example WeylClosure1; example WeylClosure; example polSol; example polSolFiniteRank; example ratSol; example bfctBound; example annRatSyz; } // tools ////////////////////////////////////////////////////////////////////// proc dmodGeneralAssumptionCheck () " USAGE: dmodGeneralAssumptionCheck(); RETURN: nothing, but checks general assumptions on the basering NOTE: This procedure checks the following conditions on the basering R and prints an error message if any of them is violated: @* - R is the n-th Weyl algebra over a field of characteristic 0, @* - R is not a qring, @* - for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). EXAMPLE: example dmodGeneralAssumptionCheck; shows examples " { // char K <> 0, qring if ( (size(ideal(basering)) >0) || (char(basering) >0) ) { ERROR("Basering is inappropriate: characteristic>0 or qring present"); } // no Weyl algebra if (isWeyl() == 0) { ERROR("Basering is not a Weyl algebra"); } // wrong sequence of vars int i,n; n = nvars(basering) div 2; for (i=1; i<=n; i++) { if (bracket(var(i+n),var(i))<>1) { ERROR(string(var(i+n))+" is not a differential operator for " +string(var(i))); } } return(); } example { "EXAMPLE"; echo=2; ring r = 0,(x,D),dp; dmodGeneralAssumptionCheck(); // prints error message def W = Weyl(); setring W; dmodGeneralAssumptionCheck(); // returns nothing } static proc safeVarName (string s) " USAGE: safeVarName(s); s string RETURN: string, returns s if s is not the name of a par/var of basering and `@' + s otherwise EXAMPLE: example safeVarName; shows examples " { string S = "," + charstr(basering) + "," + varstr(basering) + ","; s = "," + s + ","; while (find(S,s) <> 0) { s[1] = "@"; s = "," + s; } s = s[2..size(s)-1]; return(s); } example { "EXAMPLE:"; echo = 2; ring r = (0,a),(w,@w,x,y),dp; safeVarName("a"); safeVarName("x"); safeVarName("z"); safeVarName("w"); } proc extendWeyl (def newVars) " USAGE: extendWeyl(S); S string or list of strings ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). RETURN: ring, Weyl algebra extended by vars given by S EXAMPLE: example extendWeyl; shows examples " { dmodGeneralAssumptionCheck(); int i,s; string inpt = typeof(newVars); list L; if (inpt=="string") { s = 1; L = newVars; } else { if (inpt=="list") { s = size(newVars); if (s<1) { ERROR("No new variables specified."); } for (i=1; i<=s; i++) { if (typeof(newVars[i]) <> "string") { ERROR("Entries of input list must be of type string."); } } L = newVars; } else { ERROR("Expected string or list of strings as input."); } } def save = basering; int n = nvars(save) div 2; list RL = ringlist(save); RL = RL[1..4]; list Ltemp = L; for (i=s; i>0; i--) { Ltemp[n+s+i] = "D" + newVars[i]; } for (i=n; i>0; i--) { Ltemp[s+i] = RL[2][i]; Ltemp[n+2*s+i] = RL[2][n+i]; } RL[2] = Ltemp; Ltemp = list(); Ltemp[1] = list("dp",intvec(1:(2*n+2*s))); Ltemp[2] = list("C",intvec(0)); RL[3] = Ltemp; kill Ltemp; def @Dv = ring(RL); setring @Dv; def Dv = Weyl(); setring save; return(Dv); } example { "EXAMPLE:"; echo = 2; ring @D2 = 0,(x,y,Dx,Dy),dp; def D2 = Weyl(); setring D2; def D3 = extendWeyl("t"); setring D3; D3; list L = "u","v"; def D5 = extendWeyl(L); setring D5; D5; } proc polyVars (poly f, intvec v) " USAGE: polyVars(f,v); f poly, v intvec RETURN: int, 1 if f contains only variables indexed by v, 0 otherwise EXAMPLE: example polyVars; shows examples " { ideal varsf = variables(f); // vars contained in f ideal V; int i; int n = nvars(basering); for (i=1; i<=nrows(v); i++) { if ( (v[i]<0) || (v[i]>n) ) { ERROR("var(" + string(v[i]) + ") out of range"); } V[i] = var(v[i]); } attrib(V,"isSB",1); ideal N = NF(varsf,V); N = simplify(N,2); if (N[1]==0) { return(1); } else { return(0); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; poly f = y^2+zy; intvec v = 1,2; polyVars(f,v); // does f depend only on x,y? v = 2,3; polyVars(f,v); // does f depend only on y,z? } proc monomialInIdeal (ideal I) " USAGE: monomialInIdeal(I); I ideal RETURN: ideal consisting of all monomials appearing in generators of ideal EXAMLPE: example monomialInIdeal; shows examples " { // returns ideal consisting of all monomials appearing in generators of ideal I = simplify(I,2+8); int i; poly p; ideal M; for (i=1; i<=size(I); i++) { p = I[i]; while (p<>0) { M[size(M)+1] = leadmonom(p); p = p - lead(p); } } M = simplify(M,4+2); return(M); } example { "EXAMPLE"; echo=2; ring r = 0,(x,y),dp; ideal I = x2+5x3y7, x-x2-6xy; monomialInIdeal(I); } proc vars2pars (intvec v) " USAGE: vars2pars(v); v intvec ASSUME: The basering is commutative. RETURN: ring with variables specified by v converted into parameters EXAMPLE: example vars2pars; shows examples " { if (isCommutative() == 0) { ERROR("The basering must be commutative."); } v = sortIntvec(v)[1]; int sv = size(v); if ( (v[1]<1) || (v[sv]<1) ) { ERROR("Expected entries of intvec in the range 1.."+string(n)); } def save = basering; int i,j,n; n = nvars(save); list RL = ringlist(save); list Lp,Lv,L1; if (typeof(RL[1]) == "list") { L1 = RL[1]; Lp = L1[2]; } else { L1[1] = RL[1]; L1[4] = ideal(0); } j = sv; for (i=1; i<=n; i++) { if (j>0) { if (v[j]==i) { Lp[size(Lp)+1] = string(var(i)); j--; } else { Lv[size(Lv)+1] = string(var(i)); } } else { Lv[size(Lv)+1] = string(var(i)); } } RL[2] = Lv; L1[2] = Lp; L1[3] = list(list("lp",intvec(1:size(Lp)))); RL[1] = L1; L1 = list(); L1[1] = list("dp",intvec(1:sv)); L1[2] = list("C",intvec(0)); RL[3] = L1; // RL; def R = ring(RL); return(R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z,a,b,c),dp; intvec v = 4,5,6; def R = vars2pars(v); setring R; R; v = 1,2; def RR = vars2pars(v); setring RR; RR; } static proc minMaxIntRoot (list L, string minmax) { int win; if (size(L)>1) { if ( (typeof(L[1])<>"ideal") || (typeof(L[2])<>"intvec") ) { win = 1; } } else { win = 1; } if (win) { ERROR("Expected list in the format of bFactor"); } if (size(L)>2) { if ( (L[3]=="1") || (L[3]=="0") ) { print("// Warning: Constant poly. Returning 0."); return(int(0)); } } ideal I = L[1]; int i,k,b; if (minmax=="min") { i = ncols(I); k = -1; b = 0; } else // minmax=="max" { i = 1; k = 1; b = ncols(I); } for (; k*i"poly") && (inp1<>"ideal")) { ERROR("Expected first argument to be poly or ideal but received "+inp1); } intvec posXD = 1..nvars(basering); if (size(#)>0) { if (typeof(#[1])=="intvec") { posXD = #[1]; } } if ((size(posXD) mod 2)<>0) { ERROR("Even number of variables expected.") } int n = (size(posXD)) div 2; int i,j,k,l; ideal resI = id; int sid = ncols(resI); intvec v; poly P,h; for (l=1; l<=sid; l++) { P = resI[l]; resI[l] = 0; for (i=1; i<=size(P); i++) { v = leadexp(P[i]); h = f; for (j=1; j<=n; j++) { for (k=1; k<=v[posXD[j+n]]; k++) // action of Dx { h = diff(h,var(posXD[j])); } h = h*var(posXD[j])^v[posXD[j]]; // action of x } h = leadcoef(P[i])*h; resI[l] = resI[l] + h; } } if (inp1 == "ideal") { return(resI); } else { return(resI[1]); } } example { ring r = 0,(x,y,z),dp; poly f = x^2*z - y^3; def A = annPoly(f); setring A; poly f = imap(r,f); dmodAction(LD,f); poly P = y*Dy+3*z*Dz-3; dmodAction(P,f); dmodAction(P[1],f); } static proc checkRatInput (vector I) { // check for valid input int wrginpt; if (nrows(I)<>2) { wrginpt = 1; } else { if (I[2] == 0) { wrginpt = 1; } } if (wrginpt) { ERROR("Vector must consist of exactly two components, second one not 0"); } return(); } proc dmodActionRat(def id, vector w) " USAGE: dmodActionRat(id,w); id ideal or poly, f vector ASSUME: The basering is the n-th Weyl algebra W over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). @* Further, assume that w has exactly two components, second one not 0, and that w does not contain any D(i). RETURN: same type as id, the result of the natural D-module action of id on the rational function w[1]/w[2] EXAMPLE: example dmodActionRat; shows examples " { string inp1 = typeof(id); if ( (inp1<>"poly") && (inp1<>"ideal") ) { ERROR("Expected first argument to be poly or ideal but received " + inp1); } checkRatInput(w); poly f = w[1]; finKx(f); f = w[2]; finKx(f); def save = basering; def r = commRing(); setring r; ideal I = imap(save,id); vector w = imap(save,w); int i,j,k,l; int n = nvars(basering) div 2; int sid = ncols(I); intvec v; poly P; vector h,resT; module resL; for (l=1; l<=sid; l++) { P = I[l]; resT = [0,1]; for (i=1; i<=size(P); i++) { v = leadexp(P[i]); h = w; for (j=1; j<=n; j++) { for (k=1; k<=v[j+n]; k++) // action of Dx { h = diffRat(h,j); } h = h + h[1]*(var(j)^v[j]-1)*gen(1); // action of x } h = h + (leadcoef(P[i])-1)*h[1]*gen(1); resT = addRat(resT,h); } resL[l] = resT; } setring save; module resL = imap(r,resL); return(resL); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = 2*x; poly g = y; def A = annRat(f,g); setring A; poly f = imap(r,f); poly g = imap(r,g); vector v = [f,g]; // represents f/g // x and y act by multiplication dmodActionRat(x,v); dmodActionRat(y,v); // Dx and Dy act by partial derivation dmodActionRat(Dx,v); dmodActionRat(Dy,v); dmodActionRat(x*Dx+y*Dy,v); setring r; f = 2*x*y; g = x^2 - y^3; def B = annRat(f,g); setring B; poly f = imap(r,f); poly g = imap(r,g); vector v = [f,g]; dmodActionRat(LD,v); // hence LD is indeed the annihilator of f/g } static proc arithmeticRat (vector I, vector J, string op, list #) { // op = "+": return I+J // op = "*": return I*J // op = "s": return simplified I // op = "d": return diff(I,var(#[1])) int isComm = isCommutative(); if (!isComm) { def save = basering; def r = commRing(); setring r; ideal m = maxideal(1); map f = save,m; vector I = f(I); vector J = f(J); } vector K; poly p; if (op == "s") { p = gcd(I[1],I[2]); K = (I[1]/p)*gen(1) + (I[2]/p)*gen(2); } else { if (op == "+") { I = arithmeticRat(I,vector(0),"s"); J = arithmeticRat(J,vector(0),"s"); p = lcm(I[2],J[2]); K = (I[1]*p/I[2] + J[1]*p/J[2])*gen(1) + p*gen(2); } else { if (op == "*") { K = (I[1]*J[1])*gen(1) + (I[2]*J[2])*gen(2); } else { if (op == "d") { int j = #[1]; K = (diff(I[1],var(j))*I[2] - I[1]*diff(I[2],var(j)))*gen(1)+ (I[2]^2)*gen(2); } } } K = arithmeticRat(K,vector(0),"s"); } if (!isComm) { setring save; vector K = imap(r,K); } return(K); } proc simplifyRat (vector J) " USAGE: simplifyRat(v); v vector ASSUME: Assume that v has exactly two components, second one not 0. RETURN: vector, representing simplified rational function v[1]/v[2] NOTE: Possibly present non-commutative relations of the basering are ignored. EXAMPLE: example simplifyRat; shows examples " { checkRatInput(J); return(arithmeticRat(J,vector(0),"s")); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; vector v = [x2-1,x+1]; simplifyRat(v); simplifyRat(v) - [x-1,1]; } proc addRat (vector I, vector J) " USAGE: addRat(v,w); v,w vectors ASSUME: Assume that v,w have exactly two components, second ones not 0. RETURN: vector, representing rational function (v[1]/v[2])+(w[1]/w[2]) NOTE: Possibly present non-commutative relations of the basering are ignored. EXAMPLE: example addRat; shows examples " { checkRatInput(I); checkRatInput(J); return(arithmeticRat(I,J,"+")); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; vector v = [x,y]; vector w = [y,x]; addRat(v,w); addRat(v,w) - [x2+y2,xy]; } proc multRat (vector I, vector J) " USAGE: multRat(v,w); v,w vectors ASSUME: Assume that v,w have exactly two components, second ones not 0. RETURN: vector, representing rational function (v[1]/v[2])*(w[1]/w[2]) NOTE: Possibly present non-commutative relations of the basering are ignored. EXAMPLE: example multRat; shows examples " { checkRatInput(I); checkRatInput(J); return(arithmeticRat(I,J,"*")); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; vector v = [x,y]; vector w = [y,x]; multRat(v,w); multRat(v,w) - [1,1]; } proc diffRat (vector I, int j) " USAGE: diffRat(v,j); v vector, j int ASSUME: Assume that v has exactly two components, second one not 0. RETURN: vector, representing rational function derivative of rational function (v[1]/v[2]) w.r.t. var(j) NOTE: Possibly present non-commutative relations of the basering are ignored. EXAMPLE: example diffRat; shows examples " { checkRatInput(I); if ( (j<1) || (j>nvars(basering)) ) { ERROR("Second argument must be in the range 1.."+string(nvars(basering))); } return(arithmeticRat(I,vector(0),"d",j)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; vector v = [x,y]; diffRat(v,1); diffRat(v,1) - [1,y]; diffRat(v,2); diffRat(v,2) - [-x,y2]; } proc commRing () " USAGE: commRing(); RETURN: ring, basering without non-commutative relations EXAMPLE: example commRing; shows examples " { list RL = ringlist(basering); if (size(RL)<=4) { return(basering); } RL = RL[1..4]; def r = ring(RL); return(r); } example { "EXAMPLE:"; echo = 2; def W = makeWeyl(3); setring W; W; def W2 = commRing(); setring W2; W2; ring r = 0,(x,y),dp; def r2 = commRing(); // same as r setring r2; r2; } // TODO remove this proc once chern.lib is ready static proc orderedPartition(int n, list #) " USUAGE: orderedPartition(n,a); n,a positive ints orderedPartition(n,w); n positive int, w positive intvec RETURN: list of intvecs PURPOSE: Computes all partitions of n of length a, if the second argument is an int, or computes all weighted partitions w.r.t. w of n of length size(w) if the second argument is an intvec. In both cases, zero parts are included. EXAMPLE: example orderedPartition; shows an example " { int a,wrongInpt,intInpt; intvec w = 1; if (size(#)>0) { if (typeof(#[1]) == "int") { a = #[1]; intInpt = 1; } else { if (typeof(#[1]) == "intvec") { w = #[1]; a = size(w); } else { wrongInpt = 1; } } } else { wrongInpt = 1; } if (wrongInpt) { ERROR("Expected second argument of type int or intvec."); } kill wrongInpt; if (n==0 && a>0) { return(list(0:a)); } if (n<=0 || a<=0 || allPositive(w)==0) { ERROR("Positive arguments expected."); } int baseringdef; if (defined(basering)) // if a basering is defined, it should be saved for later use { def save = basering; baseringdef = 1; } ring r = 0,(x(1..a)),dp; // all variables for partition of length a ideal M; if (intInpt) { M = maxideal(n); // all monomials of total degree n } else { M = weightKB(ideal(0),n,w); // all monomials of total weighted degree n } list L; int i; for (i = 1; i <= ncols(M); i++) {L = insert(L,leadexp(M[i]));} // the leadexp corresponds to a partition if (baseringdef) // sets the old ring as basering again { setring save; } return(L); //returns the list of partitions } example { "EXAMPLE"; echo = 2; orderedPartition(4,2); orderedPartition(5,3); orderedPartition(2,4); orderedPartition(8,intvec(2,3)); orderedPartition(7,intvec(2,2)); // no such partition } // applications of characteristic variety ///////////////////////////////////// proc holonomicRank (ideal I, list #) " USAGE: holonomicRank(I[,e]); I ideal, e optional int ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). RETURN: int, the holonomic rank of I REMARKS: The holonomic rank of I is defined to be the K(x(1..n))-dimension of the module W/WI, where W is the rational Weyl algebra K(x(1..n)). If this dimension is infinite, -1 is returned. NOTE: If e<>0, @code{std} is used for Groebner basis computations, otherwise (and by default) @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. EXAMPLE: example holonomicRank; shows examples " { // assumption check is done by charVariety int ppl = printlevel - voice + 2; int eng; if (size(#)>0) { if(typeof(#[1])=="int") { eng = #[1]; } } def save = basering; dbprint(ppl ,"// Computing characteristic variety..."); def grD = charVariety(I); setring grD; // commutative ring dbprint(ppl ,"// ...done."); dbprint(ppl-1,"// " + string(charVar)); int n = nvars(save) div 2; intvec v = 1..n; def R = vars2pars(v); setring R; ideal J = imap(grD,charVar); dbprint(ppl ,"// Starting GB computation..."); J = engine(J,0); // use slimgb dbprint(ppl ,"// ...done."); dbprint(ppl-1,"// " + string(J)); int d = vdim(J); setring save; return(d); } example { "EXAMPLE:"; echo = 2; // (OTW), Example 8 ring r3 = 0,(x,y,z,Dx,Dy,Dz),dp; def D3 = Weyl(); setring D3; poly f = x^3-y^2*z^2; ideal I = f^2*Dx+3*x^2, f^2*Dy-2*y*z^2, f^2*Dz-2*y^2*z; // I annihilates exp(1/f) holonomicRank(I); } proc DsingularLocus (ideal I) " USAGE: DsingularLocus(I); I ideal ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). RETURN: ideal, describing the singular locus of the D-module D/I NOTE: If printlevel>=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed EXAMPLE: example DsingularLocus; shows examples " { // assumption check is done by charVariety int ppl = printlevel - voice + 2; def save = basering; dbprint(ppl ,"// Computing characteristic variety..."); def grD = charVariety(I); setring grD; dbprint(ppl ,"// ...done"); dbprint(ppl-1,"// " + string(charVar)); poly pDD = 1; ideal IDD; int i; int n = nvars(basering) div 2; for (i=1; i<=n; i++) { pDD = pDD*var(i+n); IDD[i] = var(i+n); } dbprint(ppl ,"// Computing saturation..."); ideal S = sat(charVar,IDD)[1]; dbprint(ppl ,"// ...done"); dbprint(ppl-1,"// " + string(S)); dbprint(ppl ,"// Computing elimination..."); S = eliminate(S,pDD); dbprint(ppl ,"// ...done"); dbprint(ppl-1,"// " + string(S)); dbprint(ppl ,"// Computing radical..."); S = radical(S); dbprint(ppl ,"// ...done"); dbprint(ppl-1,"// " + string(S)); setring save; ideal S = imap(grD,S); return(S); } example { "EXAMPLE:"; echo = 2; // (OTW), Example 8 ring @D3 = 0,(x,y,z,Dx,Dy,Dz),dp; def D3 = Weyl(); setring D3; poly f = x^3-y^2*z^2; ideal I = f^2*Dx + 3*x^2, f^2*Dy-2*y*z^2, f^2*Dz-2*y^2*z; // I annihilates exp(1/f) DsingularLocus(I); } // localization /////////////////////////////////////////////////////////////// static proc finKx(poly f) { int n = nvars(basering) div 2; intvec iv = 1..n; if (polyVars(f,iv) == 0) { ERROR("Given poly may not contain differential operators."); } return(); } proc rightNFWeyl (def id, int k) " USAGE: rightNFWeyl(id,k); id ideal or poly, k int ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). RETURN: same type as id, the right normal form of id with respect to the principal right ideal generated by the k-th variable NOTE: No Groebner basis computation is used. EXAMPLE: example rightNFWeyl; shows examples. " { dmodGeneralAssumptionCheck(); string inpt = typeof(id); if (inpt=="ideal" || inpt=="poly") { ideal I = id; } else { ERROR("Expected first input to be of type ideal or poly."); } def save = basering; int n = nvars(save) div 2; if (0>k || k>2*n) { ERROR("Expected second input to be in the range 1.."+string(2*n)+"."); } int i,j; if (k>n) // var(k) = Dx(k-n) { // switch var(k),var(k-n) list RL = ringlist(save); matrix rel = RL[6]; rel[k-n,k] = -1; RL = RL[1..4]; list L = RL[2]; string str = L[k-n]; L[k-n] = L[k]; L[k] = str; RL[2] = L; def @W = ring(RL); kill L,RL,str; ideal @mm = maxideal(1); setring @W; matrix rel = imap(save,rel); def W = nc_algebra(1,rel); setring W; ideal @mm = imap(save,@mm); map mm = save,@mm; ideal I = mm(I); i = k-n; } else // var(k) = x(k) { def W = save; i = k; } for (j=1; j<=ncols(I); j++) { I[j] = subst(I[j],var(i),0); } setring save; I = imap(W,I); if (inpt=="poly") { return(I[1]); } else { return(I); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,Dx,Dy),dp; def W = Weyl(); setring W; ideal I = x^3*Dx^3, y^2*Dy^2, x*Dy, y*Dx; rightNFWeyl(I,1); // right NF wrt principal right ideal x*W rightNFWeyl(I,3); // right NF wrt principal right ideal Dx*W rightNFWeyl(I,2); // right NF wrt principal right ideal y*W rightNFWeyl(I,4); // right NF wrt principal right ideal Dy*W poly p = x*Dx+1; rightNFWeyl(p,1); // right NF wrt principal right ideal x*W } // TODO check OTW for assumptions on holonomicity proc Dlocalization (ideal J, poly f, list #) " USAGE: Dlocalization(I,f[,k,e]); I ideal, f poly, k,e optional ints ASSUME: The basering is the n-th Weyl algebra over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). @* Further, assume that f does not contain any D(i) and that I is holonomic on K^n\V(f). RETURN: ideal or list, computes an ideal J such that D/J is isomorphic to D/I localized at f as D-modules. If k<>0, a list consisting of J and an integer m is returned, such that f^m represents the natural map from D/I to D/J. Otherwise (and by default), only the ideal J is returned. REMARKS: It is known that a localization at f of a holonomic D-module is again a holonomic D-module. @* Reference: (OTW) NOTE: If e<>0, @code{std} is used for Groebner basis computations, otherwise (and by default) @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. SEE ALSO: DLoc, SDLoc, DLoc0 EXAMPLE: example Dlocalization; shows examples " { dmodGeneralAssumptionCheck(); finKx(f); int ppl = printlevel - voice + 2; int outList,eng; if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { outList = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { eng = int(#[2]); } } } int i,j; def save = basering; int n = nvars(save) div 2; def Dv = extendWeyl(safeVarName("v")); setring Dv; poly f = imap(save,f); ideal phiI; for (i=n; i>0; i--) { phiI[i+n] = var(i+n+2)-var(1)^2*bracket(var(i+n+2),f)*var(n+2); phiI[i] = var(i+1); } map phi = save,phiI; ideal J = phi(J); J = J, 1-f*var(1); // TODO original J has to be holonomic only on K^n\V(f), not on all of K^n // does is suffice to show that new J is holonomic on Dv?? if (isHolonomic(J) == 0) { ERROR("Module is not holonomic."); } intvec w = 1; w[n+1]=0; ideal G = GBWeight(J,w,-w,eng); dbprint(ppl ,"// found GB wrt weight " +string(-w)); dbprint(ppl-1,"// " + string(G)); intvec ww = w,-w; ideal inG = inForm(G,ww); inG = engine(inG,eng); poly s = var(1)*var(n+2); // s=v*Dv vector intersecvec = pIntersect(s,inG); s = vec2poly(intersecvec); s = subst(s,var(1),-var(1)-1); list L = bFactor(s); dbprint(ppl ,"// found b-function"); dbprint(ppl-1,"// roots: "+string(L[1])); dbprint(ppl-1,"// multiplicities: "+string(L[2])); kill inG,intersecvec,s; // TODO: use maxIntRoot L = intRoots(L); // integral roots of b-function if (L[2]==0:size(L[2])) // no integral roots { setring save; return(ideal(1)); } intvec iv; for (i=1; i<=ncols(L[1]); i++) { iv[i] = int(L[1][i]); } int l0 = Max(iv); dbprint(ppl,"// maximal integral root is " +string(l0)); kill L,iv; intvec degG; ideal Gk; for (j=1; j<=ncols(G); j++) { degG[j] = deg(G[j],ww); for (i=0; i<=l0-degG[j]; i++) { Gk[ncols(Gk)+1] = var(1)^i*G[j]; } } Gk = rightNFWeyl(Gk,n+2); dbprint(ppl,"// found right normalforms"); module M = coeffs(Gk,var(1)); setring save; def mer = makeModElimRing(save); setring mer; module M = imap(Dv,M); kill Dv; M = engine(M,eng); dbprint(ppl ,"// found GB of free module of rank " + string(l0+1)); dbprint(ppl-1,"// " + string(M)); M = prune(M); setring save; matrix M = imap(mer,M); kill mer; int ro = nrows(M); int co = ncols(M); ideal I; if (ro == 1) // nothing to do { I = M; } else { matrix zm[ro-1][1]; // zero matrix matrix v[ro-1][1]; for (i=1; i<=co; i++) { v = M[1..ro-1,i]; if (v == zm) { I[size(I)+1] = M[ro,i]; } } } if (outList<>0) { return(list(I,l0+2)); } else { return(I); } } example { "EXAMPLE:"; echo = 2; // (OTW), Example 8 ring r = 0,(x,y,z,Dx,Dy,Dz),dp; def W = Weyl(); setring W; poly f = x^3-y^2*z^2; ideal I = f^2*Dx+3*x^2, f^2*Dy-2*y*z^2, f^2*Dz-2*y^2*z; // I annihilates exp(1/f) ideal J = Dlocalization(I,f); J; Dlocalization(I,f,1); // The natural map D/I -> D/J is given by 1/f^2 } // Weyl closure /////////////////////////////////////////////////////////////// static proc orderFiltrationD1 (poly f) { // returns list of ideal and intvec // ideal contains x-parts, intvec corresponding degree in Dx poly g,h; g = f; ideal I; intvec v,w,u; w = 0,1; int i,j; i = 1; while (g<>0) { h = inForm(g,w); I[i] = 0; for (j=1; j<=size(h); j++) { v = leadexp(h[j]); u[i] = v[2]; v[2] = 0; I[i] = I[i] + leadcoef(h[j])*monomial(v); } g = g-h; i++; } return(list(I,u)); } static proc kerLinMapD1 (ideal W, poly L, poly p) { // computes kernel of right multiplication with L viewed // as homomorphism of K-vector spaces span(W) -> D1/p*D1 // assume p in K[x], basering is K ideal G,K; G = std(p); list l; int i,j; // first, compute the image of span(W) if (simplify(W,2)[1] == 0) { return(K); // = 0 } for (i=1; i<=size(W); i++) { l = orderFiltrationD1(W[i]*L); K[i] = 0; for (j=1; j<=size(l[1]); j++) { K[i] = K[i] + NF(l[1][j],G)*var(2)^(l[2][j]); } } // now, we get the kernel by linear algebra l = linReduceIdeal(K,1); i = ncols(l[1]) - size(l[1]); if (i<>0) { K = module(W)*l[2]; K = K[1..i]; } else { K = 0; } return(K); } static proc leftDivisionKxD1 (poly p, poly L) { // basering is D1 = K // p in K[x] // compute p^(-1)*L if p is a left divisor of L // if (rightNF(L,ideal(p))<>0) // { // ERROR("First poly is not a right factor of second poly"); // } def save = basering; list l = orderFiltrationD1(L); ideal l1 = l[1]; ring r = 0,x,dp; ideal l1 = fetch(save,l1); poly p = fetch(save,p); int i; for (i=1; i<=ncols(l1); i++) { l1[i] = division(l1[i],p)[1][1,1]; } setring save; ideal I = fetch(r,l1); poly f; for (i=1; i<=ncols(I); i++) { f = f + I[i]*var(2)^(l[2][i]); } return(f); } proc WeylClosure1 (poly L) " USAGE: WeylClosure1(L); L a poly ASSUME: The basering is the first Weyl algebra D=K over a field K of characteristic 0. RETURN: ideal, the Weyl closure of the principal left ideal generated by L REMARKS: The Weyl closure of a left ideal I in the Weyl algebra D is defined to be the intersection of I regarded as left ideal in the rational Weyl algebra K(x) with the polynomial Weyl algebra D. @* Reference: (Tsa), Algorithm 1.2.4 NOTE: If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. SEE ALSO: WeylClosure EXAMPLE: example WeylClosure1; shows examples " { dmodGeneralAssumptionCheck(); // assumption check int ppl = printlevel - voice + 2; def save = basering; intvec w = 0,1; // for order filtration poly p = inForm(L,w); ring @R = 0,var(1),dp; ideal mm = var(1),1; map m = save,mm; ideal @p = m(p); poly p = @p[1]; poly g = gcd(p,diff(p,var(1))); if (g == 1) { g = p; } ideal facp = factorize(g,1); // g is squarefree, constants aren't interesting dbprint(ppl-1, "// squarefree part of highest coefficient w.r.t. order filtration:"); dbprint(ppl-1, "// " + string(facp)); setring save; p = imap(@R,p); // 1-1 extend basering by parameter and introduce new var t=x*d list RL = ringlist(save); RL = RL[1..4]; list l; l[1] = int(0); l[2] = list(safeVarName("a")); l[3] = list(list("lp",intvec(1))); l[4] = ideal(0); RL[1] = l; l = RL[2] + list(safeVarName("t")); RL[2] = l; l = list(); l[1] = list("dp",intvec(1,1)); l[2] = list("dp",intvec(1)); l[3] = list("C",intvec(0)); RL[3] = l; def @Wat = ring(RL); kill RL,l; setring @Wat; matrix relD[3][3]; relD[1,2] = 1; relD[1,3] = var(1); relD[2,3] = -var(2); def Wat = nc_algebra(1,relD); setring Wat; kill @Wat; // 1-2 rewrite L using Euler operators ideal mm = var(1)+par(1),var(2); map m = save,mm; poly L = m(L); w = -1,1,0; // for Bernstein filtration int i = 1; ideal Q; poly p = L; intvec d; while (p<>0) { Q[i] = inForm(p,w); p = p - Q[i]; d[i] = -deg(Q[i],w); i++; } ideal S = std(var(1)*var(2)-var(3)); Q = NF(Q,S); dbprint(ppl, "// found Euler representation of operator"); dbprint(ppl-1,"// " + string(Q)); Q = subst(Q,var(1),1); Q = subst(Q,var(2),1); // 1-3 prepare for algebraic extensions with minpoly = facp[i] list RL = ringlist(Wat); RL = RL[1..4]; list l; l = string(var(3)); RL[2] = l; l = list(); l[1] = list("dp",intvec(1)); l[2] = list("C",intvec(0)); RL[3] = l; mm = par(1); m = @R,par(1); ideal facp = m(facp); kill @R,m,mm,l,S; intvec maxroots,testroots; int sq = size(Q); string strQ = "ideal Q = " + string(Q) + ";"; // TODO do it without string workaround when issue with maps from // transcendental to algebraic extension fields is fixed int j,maxr; // 2-1 get max int root of lowest nonzero entry of Q in algebraic extension for (i=1; i<=size(facp); i++) { testroots = 0; def Ra = ring(RL); setring Ra; ideal mm = 1,1,var(1); map m = Wat,mm; ideal facp = m(facp); minpoly = leadcoef(facp[i]); execute(strQ); if (simplify(Q,2)[1] == poly(0)) { break; } j = 1; while (j0:size(LR[2])) // there are integral roots { for (j=1; j<=ncols(LR[1]); j++) { testroots[j] = int(LR[1][j]); } maxr = Max(testroots); if(maxr<0) { maxr = 0; } maxroots[i] = maxroots[i] + maxr; } kill LR; setring Wat; kill Ra; } maxr = Max(maxroots); // 3-1 build basis of vectorspace setring save; ideal KB; for (i=0; iD/pD KB = kerLinMapD1(KB,L,p); dbprint(ppl,"// got kernel"); dbprint(ppl-1, "// " + string(KB)); // 4-1 get (1/p)*f*L where f in KB for (i=1; i<=ncols(KB); i++) { KB[i] = leftDivisionKxD1(p,KB[i]*L); } KB = L,KB; // 4-2 done return(KB); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,Dx),dp; def W = Weyl(); setring W; poly L = (x^3+2)*Dx-3*x^2; WeylClosure1(L); L = (x^4-4*x^3+3*x^2)*Dx^2+(-6*x^3+20*x^2-12*x)*Dx+(12*x^2-32*x+12); WeylClosure1(L); } proc WeylClosure (ideal I) " USAGE: WeylClosure(I); I an ideal ASSUME: The basering is the n-th Weyl algebra W over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). @* Moreover, assume that the holonomic rank of W/I is finite. RETURN: ideal, the Weyl closure of I REMARKS: The Weyl closure of a left ideal I in the Weyl algebra W is defined to be the intersection of I regarded as left ideal in the rational Weyl algebra K(x(1..n)) with the polynomial Weyl algebra W. @* Reference: (Tsa), Algorithm 2.2.4 NOTE: If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. SEE ALSO: WeylClosure1 EXAMPLE: example WeylClosure; shows examples " { // assumption check dmodGeneralAssumptionCheck(); if (holonomicRank(I)==-1) { ERROR("Input is not of finite holonomic rank."); } int ppl = printlevel - voice + 2; int eng = 0; // engine def save = basering; dbprint(ppl ,"// Starting to compute singular locus..."); ideal sl = DsingularLocus(I); sl = simplify(sl,2); dbprint(ppl ,"// ...done."); dbprint(ppl-1,"// " + string(sl)); if (sl[1] == 0) // can never get here { ERROR("Can't find polynomial in K[x] vanishing on singular locus."); } poly f = sl[1]; dbprint(ppl ,"// Found poly vanishing on singular locus: " + string(f)); dbprint(ppl ,"// Starting to compute localization..."); list L = Dlocalization(I,f,1); ideal G = L[1]; dbprint(ppl ,"// ...done."); dbprint(ppl-1,"// " + string(G)); dbprint(ppl ,"// Starting to compute kernel of localization map..."); if (eng == 0) { G = moduloSlim(f^L[2],G); } else { G = modulo(f^L[2],G); } dbprint(ppl ,"// ...done."); return(G); } example { "EXAMPLE:"; echo = 2; // (OTW), Example 8 ring r = 0,(x,y,z,Dx,Dy,Dz),dp; def D3 = Weyl(); setring D3; poly f = x^3-y^2*z^2; ideal I = f^2*Dx + 3*x^2, f^2*Dy-2*y*z^2, f^2*Dz-2*y^2*z; // I annihilates exp(1/f) WeylClosure(I); } // solutions to systems of PDEs /////////////////////////////////////////////// proc polSol (ideal I, list #) " USAGE: polSol(I[,w,m]); I ideal, w optional intvec, m optional int ASSUME: The basering is the n-th Weyl algebra W over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). @* Moreover, assume that I is holonomic. RETURN: ideal, a basis of the polynomial solutions to the given system of linear PDEs with polynomial coefficients, encoded via I REMARKS: If w is given, w should consist of n strictly negative entries. Otherwise and by default, w is set to -1:n. In this case, w is used as weight vector for the computation of a b-function. @* If m is given, m is assumed to be the minimal integer root of the b-function of I w.r.t. w. Note that this assumption is not checked. @* Reference: (OTT), Algorithm 2.4 NOTE: If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. SEE ALSO: polSolFiniteRank, ratSol EXAMPLE: example polSol; shows examples " { dmodGeneralAssumptionCheck(); int ppl = printlevel - voice + 2; int mr,mrgiven; def save = basering; int n = nvars(save); intvec w = -1:(n div 2); if (size(#)>0) { if (typeof(#[1])=="intvec") { if (allPositive(-#[1])) { w = #[1]; } } if (size(#)>1) { if (typeof(#[2])=="int") { mr = #[2]; mrgiven = 1; } } } // Step 1: the b-function list L; if (!mrgiven) { if (!isHolonomic(I)) { ERROR("Ideal is not holonomic. Try polSolFiniteRank."); } dbprint(ppl,"// Computing b-function..."); L = bfctIdeal(I,w); dbprint(ppl,"// ...done."); dbprint(ppl-1,"// Roots: " + string(L[1])); dbprint(ppl-1,"// Multiplicities: " + string(L[2])); mr = minIntRoot2(L); dbprint(ppl,"// Minimal integer root is " + string(mr) + "."); } if (mr>0) { return(ideal(0)); } // Step 2: get the form of a solution f int i; L = list(); for (i=0; i<=-mr; i++) { L = L + orderedPartition(i,-w); } ideal mons; for (i=1; i<=size(L); i++) { mons[i] = monomial(L[i]); } kill L; mons = simplify(mons,2+4); // L might contain lots of 0s by construction ring @C = (0,@c(1..size(mons))),dummyvar,dp; def WC = save + @C; setring WC; ideal mons = imap(save,mons); poly f; for (i=1; i<=size(mons); i++) { f = f + par(i)*mons[i]; } // Step 3: determine values of @c(i) by equating coefficients ideal I = imap(save,I); I = dmodAction(I,f,1..n); ideal M = monomialInIdeal(I); matrix CC = coeffs(I,M); int j; ideal C; for (i=1; i<=nrows(CC); i++) { f = 0; for (j=1; j<=ncols(CC); j++) { f = f + CC[i,j]; } C[size(C)+1] = f; } // Step 3.1: solve a linear system ring rC = 0,(@c(1..size(mons))),dp; ideal C = imap(WC,C); matrix M = coeffs(C,maxideal(1)); module MM = leftKernel(M); setring WC; module MM = imap(rC,MM); // Step 3.2: return the solution ideal F = ideal(MM*transpose(mons)); setring save; ideal F = imap(WC,F); return(F); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,Dx,Dy),dp; def W = Weyl(); setring W; poly tx,ty = x*Dx, y*Dy; ideal I = // Appel F1 with parameters (2,-3,-2,5) tx*(tx+ty+4)-x*(tx+ty+2)*(tx-3), ty*(tx+ty+4)-y*(tx+ty+2)*(ty-2), (x-y)*Dx*Dy+2*Dx-3*Dy; intvec w = -1,-1; polSol(I,w); } static proc ex_polSol() { ring r = 0,(x,y,Dx,Dy),dp; def W = Weyl(); setring W; poly tx,ty = x*Dx, y*Dy; ideal I = // Appel F1 with parameters (2,-3,-2,5) tx*(tx+ty+4)-x*(tx+ty+2)*(tx-3), ty*(tx+ty+4)-y*(tx+ty+2)*(ty-2), (x-y)*Dx*Dy+2*Dx-3*Dy; intvec w = -5,-7; // the following gives a bug polSol(I,w); // this is due to a bug in weightKB, see ticket #339 // http://www.singular.uni-kl.de:8002/trac/ticket/339 } proc polSolFiniteRank (ideal I, list #) " USAGE: polSolFiniteRank(I[,w]); I ideal, w optional intvec ASSUME: The basering is the n-th Weyl algebra W over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). @* Moreover, assume that I is of finite holonomic rank. RETURN: ideal, a basis of the polynomial solutions to the given system of linear PDEs with polynomial coefficients, encoded via I REMARKS: If w is given, w should consist of n strictly negative entries. Otherwise and by default, w is set to -1:n. In this case, w is used as weight vector for the computation of a b-function. @* Reference: (OTT), Algorithm 2.6 NOTE: If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. SEE ALSO: polSol, ratSol EXAMPLE: example polSolFiniteRank; shows examples " { dmodGeneralAssumptionCheck(); if (holonomicRank(I)==-1) { ERROR("Ideal is not of finite holonomic rank."); } int ppl = printlevel - voice + 2; int n = nvars(basering) div 2; int eng; intvec w = -1:(n div 2); if (size(#)>0) { if (typeof(#[1])=="intvec") { if (allPositive(-#[1])) { w = #[1]; } } } dbprint(ppl,"// Computing initial ideal..."); ideal J = initialIdealW(I,-w,w); dbprint(ppl,"// ...done."); dbprint(ppl,"// Computing Weyl closure..."); J = WeylClosure(J); J = engine(J,eng); dbprint(ppl,"// ...done."); poly s; int i; for (i=1; i<=n; i++) { s = s + w[i]*var(i)*var(i+n); } dbprint(ppl,"// Computing intersection..."); vector v = pIntersect(s,J); list L = bFactor(vec2poly(v)); dbprint(ppl-1,"// roots: " + string(L[1])); dbprint(ppl-1,"// multiplicities: " + string(L[2])); dbprint(ppl,"// ...done."); int mr = minIntRoot2(L); int pl = printlevel; printlevel = printlevel + 1; ideal K = polSol(I,w,mr); printlevel = printlevel - 1; return(K); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,Dx,Dy),dp; def W = Weyl(); setring W; poly tx,ty = x*Dx, y*Dy; ideal I = // Appel F1 with parameters (2,-3,-2,5) tx*(tx+ty+4)-x*(tx+ty+2)*(tx-3), ty*(tx+ty+4)-y*(tx+ty+2)*(ty-2), (x-y)*Dx*Dy+2*Dx-3*Dy; intvec w = -1,-1; polSolFiniteRank(I,w); } static proc twistedIdeal(ideal I, poly f, intvec k, ideal F) { // I subset D_n, f in K[x], F = factorize(f,1), size(k) = size(F), k[i]>0 def save = basering; int n = nvars(save) div 2; int i,j; intvec a,v,w; w = (0:n),(1:n); for (i=1; i<=size(I); i++) { a[i] = deg(I[i],w); } ring FD = 0,(fd(1..n)),dp; def @@WFD = save + FD; setring @@WFD; poly f = imap(save,f); list RL = ringlist(basering); RL = RL[1..4]; list L = RL[3]; v = (1:(2*n)),((deg(f)+1):n); L = insert(L,list("a",v)); RL[3] = L; def @WFD = ring(RL); setring @WFD; poly f = imap(save,f); matrix Drel[3*n][3*n]; for (i=1; i<=n; i++) { Drel[i,i+n] = 1; // [D,x] Drel[i,i+2*n] = f; // [fD,x] for (j=1; j<=n; j++) { Drel[i+n,j+2*n] = -diff(f,var(i))*var(j+n); // [fD,D] Drel[j+2*n,i+2*n] = diff(f,var(i))*var(j+2*n) - diff(f,var(j))*var(i+2*n); // [fD,fD] } } def WFD = nc_algebra(1,Drel); setring WFD; kill @WFD,@@WFD; ideal I = imap(save,I); poly f = imap(save,f); for (i=1; i<=size(I); i++) { I[i] = f^(a[i])*I[i]; } ideal S; for (i=1; i<=n; i++) { S[size(S)+1] = var(i+2*n) - f*var(i+n); } S = slimgb(S); I = NF(I,S); if (select1(I,intvec((n+1)..2*n))[1] <> 0) { // should never get here ERROR("Something's wrong. Please inform the author."); } setring save; ideal mm = maxideal(1); poly s; for (i=1; i<=n; i++) { s = f*var(i+n); for (j=1; j<=size(F); j++) { s = s + k[j]*(f/F[j])*bracket(var(i+n),F[j]); } mm[i+2*n] = s; } map m = WFD,mm; ideal J = m(I); return(J); } example { "EXAMPLE"; echo=2; ring r = 0,(x,y,Dx,Dy),dp; def W = Weyl(); setring W; poly tx,ty = x*Dx, y*Dy; ideal I = // Appel F1 with parameters (3,-1,1,1) is a solution tx*(tx+ty)-x*(tx+ty+3)*(tx-1), ty*(tx+ty)-y*(tx+ty+3)*(ty+1); kill tx,ty; poly f = x^3*y^2-x^2*y^3-x^3*y+x*y^3+x^2*y-x*y^2; ideal F = x-1,x,-x+y,y-1,y; intvec k = -1,-1,-1,-3,-1; ideal T = twistedIdeal(I,f,k,F); // TODO change the ordering of WFD // introduce new var f?? //paper: poly fx = diff(f,x); poly fy = diff(f,y); poly fDx = f*Dx; poly fDy = f*Dy; poly fd(1) = fDx; poly fd(2) = fDy; ideal K= (x^2-x^3)*(fDx)^2+x*((1-3*x)*f-(1-x)*y*fy-(1-x)*x*fx)*(fDx) +x*(1-x)*y*(fDy)*(fDx)+x*y*f*(fDy)+3*x*f^2, (y^2-y^3)*(fDy)^2+y*((1-5*y)*f-(1-y)*x*fx-(1-y)*y*fy)*(fDy) +y*(1-y)*x*(fDx)*(fDy)-y*x*f*(fDx)-3*y*f^2; } proc ratSol (ideal I) " USAGE: ratSol(I); I ideal ASSUME: The basering is the n-th Weyl algebra W over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). @* Moreover, assume that I is holonomic. RETURN: module, a basis of the rational solutions to the given system of linear PDEs with polynomial coefficients, encoded via I Note that each entry has two components, the first one standing for the enumerator, the second one for the denominator. REMARKS: Reference: (OTT), Algorithm 3.10 NOTE: If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. SEE ALSO: polSol, polSolFiniteRank EXAMPLE: example ratSol; shows examples " { dmodGeneralAssumptionCheck(); if (!isHolonomic(I)) { ERROR("Ideal is not holonomic."); } int ppl = printlevel - voice + 2; def save = basering; dbprint(ppl,"// computing singular locus..."); ideal S = DsingularLocus(I); dbprint(ppl,"// ...done."); poly f = S[1]; dbprint(ppl,"// considering poly " + string(f)); int n = nvars(save) div 2; list RL = ringlist(save); RL = RL[1..4]; list L = RL[2]; L = list(L[1..n]); RL[2] = L; L = list(); L[1] = list("dp",intvec(1:n)); L[2] = list("C",intvec(0)); RL[3] = L; def rr = ring(RL); setring rr; poly f = imap(save,f); ideal F = factorize(f,1); // not interested in multiplicities dbprint(ppl,"// with irreducible factors " + string(F)); setring save; ideal F = imap(rr,F); kill rr,RL; int i; intvec k; ideal FF = 1,1; dbprint(ppl,"// computing b-functions of irreducible factors..."); for (i=1; i<=size(F); i++) { dbprint(ppl,"// considering " + string(F[i]) + "..."); L = bfctBound(I,F[i]); if (size(L) == 3) // bfct is constant { dbprint(ppl,"// ...got " + string(L[3])); if (L[3] == "1") { return(0); // TODO type // no rational solutions } else // should never get here { ERROR("Oops, something went wrong. Please inform the author."); } } else { dbprint(ppl,"// ...got roots " + string(L[1])); dbprint(ppl,"// with multiplicities " + string(L[2])); k[i] = -maxIntRoot(L)-1; if (k[i] < 0) { FF[2] = FF[2]*F[i]^(-k[i]); } else { FF[1] = FF[1]*F[i]^(k[i]); } } } vector v = FF[1]*gen(1) + FF[2]*gen(2); kill FF; dbprint(ppl,"// ...done"); ideal twI = twistedIdeal(I,f,k,F); intvec w = -1:n; dbprint(ppl,"// computing polynomial solutions of twisted system..."); if (isHolonomic(twI)) { ideal P = polSol(twI,w); } else { ideal P = polSolFiniteRank(twI,w); } module M; vector vv; for (i=1; i<=ncols(P); i++) { vv = P[i]*gen(1) + 1*gen(2); M[i] = multRat(v,vv); } dbprint(ppl,"// ...done"); return (M); } example { "EXAMPLE"; echo=2; ring r = 0,(x,y,Dx,Dy),dp; def W = Weyl(); setring W; poly tx,ty = x*Dx, y*Dy; ideal I = // Appel F1 with parameters (3,-1,1,1) is a solution tx*(tx+ty)-x*(tx+ty+3)*(tx-1), ty*(tx+ty)-y*(tx+ty+3)*(ty+1); module M = ratSol(I); // We obtain a basis of the rational solutions to I represented by a // module / matrix with two rows. // Each column of the matrix represents a rational function, where // the first row correspond to the enumerator and the second row to // the denominator. print(M); } proc bfctBound (ideal I, poly f, list #) " USAGE: bfctBound (I,f[,primdec]); I ideal, f poly, primdec optional string ASSUME: The basering is the n-th Weyl algebra W over a field of characteristic 0 and for all 1<=i<=n the identity var(i+n)*var(i)=var(i)*var(i+1)+1 holds, i.e. the sequence of variables is given by x(1),...,x(n),D(1),...,D(n), where D(i) is the differential operator belonging to x(i). @* Moreover, assume that I is holonomic. RETURN: list of roots (of type ideal) and multiplicities (of type intvec) of a multiple of the b-function for f^s*u at a generic root of f. Here, u stands for [1] in D/I. REMARKS: Reference: (OTT), Algorithm 3.4 NOTE: This procedure requires to compute a primary decomposition in a commutative ring. The optional string primdec can be used to specify the algorithm to do so. It may either be `GTZ' (Gianni, Trager, Zacharias) or `SY' (Shimoyama, Yokoyama). By default, `GTZ' is used. @* If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. SEE ALSO: bernstein, bfct, bfctAnn EXAMPLE: example bfctBound; shows examples " { dmodGeneralAssumptionCheck(); finKx(f); if (!isHolonomic(I)) { ERROR("Ideal is not holonomic."); } int ppl = printlevel - voice + 2; string primdec = "GTZ"; if (size(#)>1) { if (typeof(#[1])=="string") { if ( (#[1]=="SY") || (#[1]=="sy") || (#[1]=="Sy") ) { primdec = "SY"; } else { if ( (#[1]<>"GTZ") && (#[1]<>"gtz") && (#[1]<>"Gtz") ) { print("// Warning: optional string may either be `GTZ' or `SY',"); print("// proceeding with `GTZ'."); primdec = "GTZ"; } } } } def save = basering; int n = nvars(save) div 2; // step 1 ideal mm = maxideal(1); def Wt = extendWeyl(safeVarName("t")); setring Wt; poly f = imap(save,f); ideal mm = imap(save,mm); int i; for (i=1; i<=n; i++) { mm[i+n] = var(i+n+2) + bracket(var(i+n+2),f)*var(n+2); } map m = save,mm; ideal I = m(I); I = I, var(1)-f; // step 2 intvec w = 1,(0:n); dbprint(ppl ,"// Computing initial ideal..."); I = initialIdealW(I,-w,w); dbprint(ppl ,"// ...done."); dbprint(ppl-1,"// " + string(I)); // step 3: rewrite I using Euler operator t*Dt list RL = ringlist(Wt); RL = RL[1..4]; list L = RL[2] + list(safeVarName("s")); // s=t*Dt RL[2] = L; L = list(); L[1] = list("dp",intvec(1:(2*n+2))); L[2] = list("dp",intvec(1)); L[3] = list("C",intvec(0)); RL[3] = L; def @Wts = ring(RL); kill L,RL; setring @Wts; matrix relD[2*n+3][2*n+3]; relD[1,2*n+3] = var(1); relD[n+2,2*n+3] = -var(n+2); for (i=1; i<=n+1; i++) { relD[i,n+i+1] = 1; } def Wts = nc_algebra(1,relD); setring Wts; ideal I = imap(Wt,I); kill Wt,@Wts; ideal S = var(1)*var(n+2)-var(2*n+3); attrib(S,"isSB",1); dbprint(ppl ,"// Computing Euler representation..."); // I = NF(I,S); int d; intvec ww = 0:(2*2+2); ww[1] = -1; ww[n+2] = 1; for (i=1; i<=size(I); i++) { d = deg(I[i],ww); if (d>0) { I[i] = var(1)^d*I[i]; } if (d<0) { d = -d; I[i] = var(n+2)^d*I[i]; } } I = NF(I,S); // now there are no t,Dt in I, only s dbprint(ppl ,"// ...done."); I = subst(I,var(2*n+3),-var(2*n+3)-1); ring Ks = 0,s,dp; def Ws = save + Ks; setring Ws; ideal I = imap(Wts,I); kill Wts; poly DD = 1; for (i=1; i<=n; i++) { DD = DD * var(n+i); } dbprint(ppl ,"// Eliminating differential operators..."); ideal J = eliminate(I,DD); // J subset K[x,s] dbprint(ppl ,"// ...done."); dbprint(ppl-1,"// " + string(J)); list RL = ringlist(Ws); RL = RL[1..4]; list L = RL[2]; L = list(L[1..n]) + list(L[2*n+1]); RL[2] = L; L = list(); L[1] = list("dp",intvec(1:(n+1))); L[2] = list("C",intvec(0)); RL[3] = L; def Kxs = ring(RL); setring Kxs; ideal J = imap(Ws,J); dbprint(ppl ,"// Computing primary decomposition with engine " + primdec + "..."); if (primdec == "GTZ") { list P = primdecGTZ(J); } else { list P = primdecSY(J); } dbprint(ppl ,"// ...done."); dbprint(ppl-1,"// " + string(P)); ideal GP,Qix,rad,B; poly f = imap(save,f); vector v; for (i=1; i<=size(P); i++) { dbprint(ppl ,"// Considering primary component " + string(i) + " of " + string(size(P)) + "..."); dbprint(ppl ,"// Intersecting with K[x] and computing radical..."); GP = std(P[i][1]); Qix = eliminate(GP,var(n+1)); // subset K[x] rad = radical(Qix); rad = std(rad); dbprint(ppl ,"// ...done."); dbprint(ppl-1,"// " + string(rad)); if (rad[1]==0 || NF(f,rad)==0) { dbprint(ppl ,"// Intersecting with K[s]..."); v = pIntersect(var(n+1),GP); B[size(B)+1] = vec2poly(v,n+1); dbprint(ppl ,"// ...done."); dbprint(ppl-1,"// " + string(B[size(B)])); } dbprint(ppl ,"// ...done."); } f = lcm(B); // =lcm(B[1],...,B[size(B)]) list bb = bFactor(f); setring save; list bb = imap(Kxs,bb); return(bb); } example { "EXAMPLE"; echo=2; ring r = 0,(x,y,Dx,Dy),dp; def W = Weyl(); setring W; poly tx,ty = x*Dx, y*Dy; ideal I = // Appel F1 with parameters (2,-3,-2,5) tx*(tx+ty+4)-x*(tx+ty+2)*(tx-3), ty*(tx+ty+4)-y*(tx+ty+2)*(ty-2), (x-y)*Dx*Dy+2*Dx-3*Dy; kill tx,ty; poly f = x-1; bfctBound(I,f); } //TODO check f/g or g/f, check Weyl closure of result proc annRatSyz (poly f, poly g, list #) " USAGE: annRatSyz(f,g[,db,eng]); f, g polynomials, db,eng optional integers ASSUME: The basering is commutative and over a field of characteristic 0. RETURN: ring (a Weyl algebra) containing an ideal `LD', which is (part of) the annihilator of the rational function g/f in the corresponding Weyl algebra REMARKS: This procedure uses the computation of certain syzygies. One can obtain the full annihilator by computing the Weyl closure of the ideal LD. NOTE: Activate the output ring with the @code{setring} command. In the output ring, the ideal `LD' (in Groebner basis) is (part of) the annihilator of g/f. @* If db>0 is given, operators of order up to db are considered, otherwise, and by default, a minimal holonomic solution is computed. @* If eng<>0, @code{std} is used for Groebner basis computations, otherwise, and by default, @code{slimgb} is used. @* If printlevel =1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. SEE ALSO: annRat, annPoly EXAMPLE: example annRatSyz; shows examples " { // check assumptions if (!isCommutative()) { ERROR("Basering must be commutative."); } if ( (size(ideal(basering)) >0) || (char(basering) >0) ) { ERROR("Basering is inappropriate: characteristic>0 or qring present."); } if (g == 0) { ERROR("Second polynomial must not be zero."); } int db,eng; if (size(#)>0) { if (typeof(#[1]) == "int") { db = int(#[1]); } if (size(#)>1) { if (typeof(#[2]) == "int") { eng = int(#[1]); } } } int ppl = printlevel - voice + 2; vector I = f*gen(1)+g*gen(2); checkRatInput(I); int i,j; def R = basering; int n = nvars(R); list RL = ringlist(R); RL = RL[1..4]; list Ltmp = RL[2]; for (i=1; i<=n; i++) { Ltmp[i+n] = safeVarName("D" + Ltmp[i]); } RL[2] = Ltmp; Ltmp = list(); Ltmp[1] = list("dp",intvec(1:2*n)); Ltmp[2] = list("C",intvec(0)); RL[3] = Ltmp; kill Ltmp; def @D = ring(RL); setring @D; def D = Weyl(); setring D; ideal DD = 1; ideal Dcd,Dnd,LD,tmp; Dnd = 1; module DS; poly DJ; kill @D; setring R; module Rnd,Rcd; Rnd[1] = I; vector RJ; ideal L = I[1]; module RS; poly p,pnew; pnew = I[2]; int k,c; while(1) { k++; setring R; dbprint(ppl,"// Testing order: " + string(k)); Rcd = Rnd; Rnd = 0; setring D; Dcd = Dnd; Dnd = 0; dbprint(ppl-1,"// Current members of the annihilator: " + string(LD)); setring R; c = size(Rcd); p = pnew; for (i=1; i<=c; i++) { for (j=1; j<=n; j++) { RJ = diffRat(Rcd[i],j); setring D; DJ = Dcd[i]*var(n+j); tmp = Dnd,DJ; if (size(Dnd) <> size(simplify(tmp,4))) // new element { Dnd[size(Dnd)+1] = DJ; setring R; Rnd[size(Rnd)+1] = RJ; pnew = lcm(pnew,RJ[2]); } else // already have DJ in Dnd { setring R; } } } p = pnew/p; for (i=1; i<=size(L); i++) { L[i] = p*L[i]; } for (i=1; i<=size(Rnd); i++) { L[size(L)+1] = pnew/Rnd[i][2]*Rnd[i][1]; } RS = syz(L); setring D; DD = DD,Dnd; setring R; if (RS <> 0) { setring D; DS = imap(R,RS); LD = ideal(transpose(DS)*transpose(DD)); } else { setring D; } LD = engine(LD,eng); // test if we're done if (db<=0) { if (isHolonomic(LD)) { break; } } else { if (k==db) { break; } } } export(LD); setring R; return(D); } example { "EXAMPLE:"; echo = 2; // printlevel = 3; ring r = 0,(x,y),dp; poly f = 2*x*y; poly g = x^2 - y^3; def A = annRatSyz(f,g); // compute a holonomic solution setring A; A; LD; setring r; def B = annRatSyz(f,g,5); // compute a solution up to degree 5 setring B; LD; // this is the full annihilator as we will check below setring r; def C = annRat(f,g); setring C; LD; // the full annihilator ideal BLD = imap(B,LD); NF(LD,std(BLD)); } singular-4.0.3+ds/Singular/LIB/dmodvar.lib000066400000000000000000000551121266270727000202770ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////// version="version dmodvar.lib 4.0.0.0 Jun_2013 "; // $Id: 5f4182bc9a1f305c14810c5e6997252b8713607b $ category="Noncommutative"; info=" LIBRARY: dmodvar.lib Algebraic D-modules for varieties AUTHORS: Daniel Andres, daniel.andres@math.rwth-aachen.de @* Viktor Levandovskyy, levandov@math.rwth-aachen.de @* Jorge Martin-Morales, jorge@unizar.es Support: DFG Graduiertenkolleg 1632 'Experimentelle und konstruktive Algebra' OVERVIEW: Let K be a field of characteristic 0. Given a polynomial ring R = K[x_1,...,x_n] and polynomials f_1,...,f_r in R, define F = f_1*...*f_r and F^s = f_1^s_1*...*f_r^s_r for symbolic discrete (that is shiftable) variables s_1,..., s_r. The module R[1/F]*F^s has the structure of a D-module, where D = D(R) tensored with S over K, where @* - D(R) is the n-th Weyl algebra K @* - S is the universal enveloping algebra of gl_r, generated by s_i = s_{ii}. @* One is interested in the following data: @* - the left ideal Ann F^s in D, usually denoted by LD in the output @* - global Bernstein polynomial in one variable s = s_1+...+s_r, denoted by bs, @* - its minimal integer root s0, the list of all roots of bs, which are known to be negative rational numbers, with their multiplicities, which is denoted by BS @* - an r-tuple of operators in D, denoted by PS, such that the functional equality sum(k=1 to k=r) P_k*f_k*F^s = bs*F^s holds in R[1/F]*F^s. REFERENCES: (BMS06) Budur, Mustata, Saito: Bernstein-Sato polynomials of arbitrary varieties (2006). @* (ALM09) Andres, Levandovskyy, Martin-Morales: Principal Intersection and Bernstein-Sato Polynomial of an Affine Variety (2009). PROCEDURES: bfctVarIn(F[,L]); computes the roots of the Bernstein-Sato polynomial b(s) of the variety V(F) using initial ideal approach bfctVarAnn(F[,L]); computes the roots of the Bernstein-Sato polynomial b(s) of the variety V(F) using Sannfs approach SannfsVar(F[,O,e]); computes the annihilator of F^s in the ring D makeMalgrange(F[,ORD]); creates the Malgrange ideal, associated with F = F[1],..,F[P] SEE ALSO: bfun_lib, dmod_lib, dmodapp_lib, gmssing_lib KEYWORDS: D-module; D-module structure; Bernstein-Sato polynomial for variety; global Bernstein-Sato polynomial for variety; Weyl algebra; parametric annihilator for variety; Budur-Mustata-Saito approach; initial ideal approach "; /* // Static procs: // coDim(I); compute the codimension of the leading ideal of I // dmodvarAssumeViolation() // ORDstr2list (ORD, NN) // smallGenCoDim(I,k) */ /* CHANGELOG 11.10.10 by DA: - reformated help strings - simplified code - add and use of safeVarName - renamed makeIF to makeMalgrange */ LIB "bfun.lib"; // for pIntersect LIB "dmodapp.lib"; // for isCommutative etc. /////////////////////////////////////////////////////////////////////////////// // testing for consistency of the library: proc testdmodvarlib () { example makeMalgrange; example bfctVarIn; example bfctVarAnn; example SannfsVar; } // example coDim; /////////////////////////////////////////////////////////////////////////////// static proc dmodvarAssumeViolation() { // char K = 0, no qring if ( (size(ideal(basering)) >0) || (char(basering) >0) ) { ERROR("Basering is inappropriate: characteristic>0 or qring present"); } return(); } static proc safeVarName (string s, string cv) // assumes 's' to be a valid variable name // returns valid var name string @@..@s { string S; if (cv == "v") { S = "," + "," + varstr(basering) + ","; } if (cv == "c") { S = "," + "," + charstr(basering) + ","; } if (cv == "cv") { S = "," + charstr(basering) + "," + varstr(basering) + ","; } s = "," + s + ","; while (find(S,s) <> 0) { s[1] = "@"; s = "," + s; } s = s[2..size(s)-1]; return(s) } // da: in smallGenCoDim(), rewritten using mstd business static proc coDim (ideal I) "USAGE: coDim (I); I an ideal RETURN: int PURPOSE: computes the codimension of the ideal generated by the leading monomials of the given generators of the ideal. This is also the codimension of the ideal if it is represented by a standard basis. NOTE: The codimension of an ideal I means the number of variables minus the Krull dimension of the basering modulo I. EXAMPLE: example coDim; shows examples " { int n = nvars(basering); int d = dim(I); // to insert: check whether I is in GB return(n-d); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),Dp; ideal I = x^2+y^3, z; coDim(std(I)); } static proc ORDstr2list (string ORD, int NN) { /* convert an ordering defined in NN variables in the */ /* string form into the same ordering in the list form */ string st; st = "ring @Z = 0,z(1.." + string(NN) + "),"; st = st + ORD + ";"; execute(st); kill st; list L = ringlist(@Z)[3]; kill @Z; return(L); } proc SannfsVar (ideal F, list #) "USAGE: SannfsVar(F [,ORD,eng]); F an ideal, ORD an optional string, eng an optional int RETURN: ring (Weyl algebra tensored with U(gl_P)), containing an ideal LD PURPOSE: compute the D-module structure of D*f^s where f = F[1]*...*F[P] and D is the Weyl algebra D tensored with K=U(gl_P), according to the generalized algorithm by Briancon and Maisonobe for affine varieties ASSUME: The basering is commutative and over a field of characteristic 0. NOTE: Activate the output ring D with the @code{setring} command. In the ring D, the ideal LD is the needed D-module structure. @* The value of ORD must be an elimination ordering in D for Dt written in the string form, otherwise the result may have no meaning. By default ORD = '(a(1..(P)..1),a(1..(P+P^2)..1),dp)'. @* If eng<>0, @code{std} is used for Groebner basis computations, otherwise, and by default @code{slimgb} is used. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example SannfsVar; shows examples " { dmodvarAssumeViolation(); if (!isCommutative()) { ERROR("Basering must be commutative"); } def save = basering; int N = nvars(basering); int P = ncols(F); //ncols better than size, since F[i] could be zero // P is needed for default ORD int i,j,k,l; // st = "(a(1..(P)..1),a(1..(P+P^2)..1),dp)"; string st = "(a(" + string(1:P); st = st + "),a(" + string(1:(P+P^2)); st = st + "),dp)"; // default values string ORD = st; int eng = 0; if ( size(#)>0 ) { if ( typeof(#[1]) == "string" ) { ORD = string(#[1]); // second arg if (size(#)>1) { // exists 2nd arg if ( typeof(#[2]) == "int" ) { // the case: given ORD, given engine eng = int(#[2]); } } } else { if ( typeof(#[1]) == "int" ) { // the case: default ORD, engine given eng = int(#[1]); // ORD = "(a(1..(P)..1),a(1..(P+P^2)..1),dp)"; //is already set } else { // incorr. 1st arg ORD = string(st); } } } // size(#)=0, i.e. there is no elimination ordering and no engine given // eng = 0; ORD = "(a(1..(P)..1),a(1..(P^2)..1),dp)"; //are already set int ppl = printlevel-voice+2; // returns a list with a ring and an ideal LD in it // save, N, P and the indices are already defined int Nnew = 2*N+P+P^2; list RL = ringlist(basering); list L; L[1] = RL[1]; //char L[4] = RL[4]; //char, minpoly // check whether vars have admissible names list Name = RL[2]; list RName; // (i,j) <--> (i-1)*p+j for (i=1; i<=P; i++) { RName[i] = safeVarName("Dt("+string(i)+")","cv"); for (j=1; j<=P; j++) { RName[P+(i-1)*P+j] = safeVarName("s("+string(i)+")("+string(j)+")","cv"); } } // now, create the names for new vars list DName; for(i=1; i<=N; i++) { DName[i] = safeVarName("D"+Name[i],"cv"); //concat } list NName = RName + Name + DName; L[2] = NName; // Name, Dname will be used further kill NName; //block ord (a(1..(P)..1),a(1..(P+P^2)..1),dp); //export Nnew; L[3] = ORDstr2list(ORD,Nnew); // we are done with the list def @R@ = ring(L); setring @R@; matrix @D[Nnew][Nnew]; // kronecker(i,j) equals (i==j) // (i,j) <--> (i-1)*p+j for (i=1; i<=P; i++) { for (j=1; j<=P; j++) { for (k=1; k<=P; k++) { //[sij,Dtk] = djk*Dti // @D[k,P+(i-1)*P+j] = (j==k)*Dt(i); @D[k,P+(i-1)*P+j] = (j==k)*var(i); for (l=1; l<=P; l++) { if ( (i-k)*P < l-j ) { //[sij,skl] = djk*sil - dil*skj // @D[P+(i-1)*P+j,P+(k-1)*P+l] = -(j==k)*s(i)(l) + (i==l)*s(k)(j); @D[P+(i-1)*P+j,P+(k-1)*P+l] = -(j==k)*var(i*P+l) + (i==l)*var(k*P+j); } } } } } for (i=1; i<=N; i++) { //[Dx,x]=1 @D[P+P^2+i,P+P^2+N+i] = 1; } def @R = nc_algebra(1,@D); setring @R; //@R@ will be used further dbprint(ppl,"// -1-1- the ring @R(_Dt,_s,_x,_Dx) is ready"); dbprint(ppl-1, @R); // create the ideal I // (i,j) <--> (i-1)*p+j ideal F = imap(save,F); ideal I; for (i=1; i<=P; i++) { for (j=1; j<=P; j++) { // I[(i-1)*P+j] = Dt(i)*F[j] + s(i)(j); I[(i-1)*P+j] = var(i)*F[j] + var(i*P+j); } } poly p,q; for (i=1; i<=N; i++) { p=0; for (j=1; j<=P; j++) { // q = Dt(j); q = var(j); q = q*diff(F[j],var(P+P^2+i)); p = p + q; } I = I, p + var(P+P^2+N+i); } // -------- the ideal I is ready ---------- dbprint(ppl,"// -1-2- starting the elimination of Dt(i) in @R"); dbprint(ppl-1, I); ideal J = engine(I,eng); ideal K = nselect(J,1..P); kill I,J; dbprint(ppl,"// -1-3- all Dt(i) are eliminated"); dbprint(ppl-1, K); //K is without Dt(i) // ----------- the ring @R2(_s,_x,_Dx) ------------ //come back to the ring save, recover L and remove all Dt(i) //L[1],L[4] do not change setring save; list Lord, tmp; // variables tmp = L[2]; Lord = tmp[P+1..Nnew]; L[2] = Lord; // ordering // st = "(a(1..(P^2)..1),dp)"; st = "(a(" + string(1:P^2); st = st + "),dp)"; tmp = ORDstr2list(st,Nnew-P); L[3] = tmp; def @R2@ = ring(L); kill L; // we are done with the list setring @R2@; matrix tmpM,LordM; // non-commutative relations intvec iv = P+1..Nnew; tmpM = imap(@R@,@D); kill @R@; LordM = submat(tmpM,iv,iv); matrix @D2 = LordM; def @R2 = nc_algebra(1,@D2); setring @R2; kill @R2@; dbprint(ppl,"// -2-1- the ring @R(_s,_x,_Dx) is ready"); dbprint(ppl-1, @R2); ideal K = imap(@R,K); kill @R; dbprint(ppl,"// -2-2- starting cosmetic Groebner basis computation"); dbprint(ppl-1, K); K = engine(K,eng); dbprint(ppl,"// -2-3- the cosmetic Groebner basis has been computed"); dbprint(ppl-1,K); ideal LD = K; attrib(LD,"isSB",1); export LD; return(@R2); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),Dp; ideal F = x^3, y^5; //ORD = "(a(1,1),a(1,1,1,1,1,1),dp)"; //eng = 0; def A = SannfsVar(F); setring A; A; LD; } proc bfctVarAnn (ideal F, list #) "USAGE: bfctVarAnn(F[,gid,eng]); F an ideal, gid,eng optional ints RETURN: list of an ideal and an intvec PURPOSE: computes the roots of the Bernstein-Sato polynomial and their multiplicities for an affine algebraic variety defined by F = F[1],..,F[r]. ASSUME: The basering is commutative and over a field in char 0. NOTE: In the output list, the ideal contains all the roots and the intvec their multiplicities. @* If gid<>0, the ideal is used as given. Otherwise, and by default, a heuristically better suited generating set is used. @* If eng<>0, @code{std} is used for GB computations, otherwise, and by default, @code{slimgb} is used. @* Computational remark: The time of computation can be very different depending on the chosen generators of F, although the result is always the same. @* Further note that in this proc, the annihilator of f^s in D[s] is computed and then a system of linear equations is solved by linear reductions in order to find the minimal polynomial of S = s(1)(1) + ... + s(P)(P). The resulted is shifted by 1-codim(Var(F)) following (BMS06). DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel=2, all the debug messages will be printed. EXAMPLE: example bfctVarAnn; shows examples " { dmodvarAssumeViolation(); if (!isCommutative()) { ERROR("Basering must be commutative"); } int gid = 0; // default int eng = 0; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { gid = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { eng = int(#[2]); } } } def save = basering; int ppl = printlevel - voice + 2; printlevel = printlevel+1; list L = smallGenCoDim(F,gid); F = L[1]; int cd = L[2]; kill L; def @R2 = SannfsVar(F,eng); printlevel = printlevel-1; int sF = size(F); // no 0 in F setring @R2; // we are in D[s] and LD is a std of SannfsVar(F) ideal F = imap(save,F); ideal GF = std(F); ideal J = NF(LD,GF); J = J, F; dbprint(ppl,"// -3-1- starting Groebner basis of ann F^s + F "); dbprint(ppl-1,J); ideal K = engine(J,eng); dbprint(ppl,"// -3-2- finished Groebner basis of ann F^s + F "); dbprint(ppl-1,K); poly S; int i; for (i=1; i<=sF; i++) { // S = S + s(i)(i); S = S + var((i-1)*sF+i); } dbprint(ppl,"// -4-1- computing the minimal polynomial of S"); dbprint(ppl-1,"S = "+string(S)); vector M = pIntersect(S,K); dbprint(ppl,"// -4-2- the minimal polynomial has been computed"); ring @R3 = 0,s,dp; vector M = imap(@R2,M); poly p = vec2poly(M); dbprint(ppl-1,p); dbprint(ppl,"// -5-1- codimension of the variety"); dbprint(ppl-1,cd); dbprint(ppl,"// -5-2- shifting BS(s)=minpoly(s-codim+1)"); p = subst(p,var(1),var(1)-cd+1); dbprint(ppl-1,p); dbprint(ppl,"// -5-3- factorization of the minimal polynomial"); list BS = bFactor(p); setring save; list BS = imap(@R3,BS); kill @R2,@R3; return(BS); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),Dp; ideal F = x^2+y^3, z; bfctVarAnn(F); } proc makeMalgrange (ideal F, list #) "USAGE: makeMalgrange(F [,ORD]); F an ideal, ORD an optional string RETURN: ring (Weyl algebra) containing an ideal IF PURPOSE: create the ideal by Malgrange associated with F = F[1],...,F[P]. NOTE: Activate the output ring with the @code{setring} command. In this ring, the ideal IF is the ideal by Malgrange corresponding to F. @* The value of ORD must be an arbitrary ordering in K<_t,_x,_Dt,_Dx> written in the string form. By default ORD = 'dp'. DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example makeMalgrange; shows examples " { string ORD = "dp"; if ( size(#)>0 ) { if ( typeof(#[1]) == "string" ) { ORD = string(#[1]); } } int ppl = printlevel-voice+2; def save = basering; int N = nvars(save); int P = ncols(F); int Nnew = 2*P+2*N; int i,j; string st; list RL = ringlist(save); list L,Lord; list tmp; intvec iv; L[1] = RL[1]; L[4] = RL[4]; //check whether vars have admissible names list Name = RL[2]; list TName, DTName; for (i=1; i<=P; i++) { TName[i] = safeVarName("t("+string(i)+")","cv"); DTName[i] = safeVarName("Dt("+string(i)+")","cv"); } //now, create the names for new vars list DName; for (i=1; i<=N; i++) { DName[i] = safeVarName("D"+Name[i],"cv"); //concat } list NName = TName + Name + DTName + DName; L[2] = NName; // Name, Dname will be used further kill NName, TName, Name, DTName, DName; // ORD already set, default ord dp; L[3] = ORDstr2list(ORD,Nnew); // we are done with the list def @R@ = ring(L); setring @R@; def @R = Weyl(); setring @R; kill @R@; //dbprint(ppl,"// -1-1- the ring @R(_t,_x,_Dt,_Dx) is ready"); //dbprint(ppl-1, @R); // create the ideal I ideal F = imap(save,F); ideal I; for (j=1; j<=P; j++) { // I[j] = t(j) - F[j]; I[j] = var(j) - F[j]; } poly p,q; for (i=1; i<=N; i++) { p=0; for (j=1; j<=P; j++) { // q = Dt(j); q = var(P+N+j); q = diff(F[j],var(P+i))*q; p = p + q; } I = I, p + var(2*P+N+i); } // -------- the ideal I is ready ---------- ideal IF = I; export IF; return(@R); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),Dp; ideal I = x^2+y^3, z; def W = makeMalgrange(I); setring W; W; IF; } proc bfctVarIn (ideal I, list #) "USAGE: bfctVarIn(I [,a,b,c]); I an ideal, a,b,c optional ints RETURN: list of ideal and intvec PURPOSE: computes the roots of the Bernstein-Sato polynomial and their multiplicities for an affine algebraic variety defined by I. ASSUME: The basering is commutative and over a field of characteristic 0. @* Varnames of the basering do not include t(1),...,t(r) and Dt(1),...,Dt(r), where r is the number of entries of the input ideal. NOTE: In the output list, say L, @* - L[1] of type ideal contains all the rational roots of a b-function, @* - L[2] of type intvec contains the multiplicities of above roots, @* - optional L[3] of type string is the part of b-function without rational roots. @* Note, that a b-function of degree 0 is encoded via L[1][1]=0, L[2]=0 and L[3] is 1 (for nonzero constant) or 0 (for zero b-function). @* If a<>0, the ideal is used as given. Otherwise, and by default, a heuristically better suited generating set is used to reduce computation time. @* If b<>0, @code{std} is used for GB computations in characteristic 0, otherwise, and by default, @code{slimgb} is used. @* If c<>0, a matrix ordering is used for GB computations, otherwise, and by default, a block ordering is used. @* Further note, that in this proc, the initial ideal of the multivariate Malgrange ideal defined by I is computed and then a system of linear equations is solved by linear reductions following the ideas by Noro. The result is shifted by 1-codim(Var(F)) following (BMS06). DISPLAY: If printlevel=1, progress debug messages will be printed, @* if printlevel>=2, all the debug messages will be printed. EXAMPLE: example bfctVarIn; shows examples " { dmodvarAssumeViolation(); if (!isCommutative()) { ERROR("Basering must be commutative"); } int ppl = printlevel - voice + 2; int idealasgiven = 0; // default int whicheng = 0; // default int whichord = 0; // default if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { idealasgiven = int(#[1]); } if (size(#)>1) { if (typeof(#[2])=="int" || typeof(#[2])=="number") { whicheng = int(#[2]); } if (size(#)>2) { if (typeof(#[3])=="int" || typeof(#[3])=="number") { whichord = int(#[3]); } } } } def save = basering; int i; int n = nvars(basering); // step 0: get small generating set I = simplify(I,2); list L = smallGenCoDim(I,idealasgiven); I = L[1]; int c = L[2]; kill L; // step 1: setting up the multivariate Malgrange ideal int r = size(I); def D = makeMalgrange(I); setring D; dbprint(ppl-1,"// Computing in " + string(n+r) + "-th Weyl algebra:", D); dbprint(ppl-1,"// The Malgrange ideal: ", IF); // step 2: compute the b-function of the Malgrange ideal w.r.t. approriate weights intvec w = 1:r; w[r+n] = 0; dbprint(ppl,"// Computing the b-function of the Malgrange ideal..."); list L = bfctIdeal(IF,w,whicheng,whichord); dbprint(ppl,"// ... done."); dbprint(ppl-1,"// The b-function: ",L); // step 3: shift the result ring S = 0,s,dp; list L = imap(D,L); kill D; if (size(L)==2) { ideal B = L[1]; ideal BB; int nB = ncols(B); for (i=nB; i>0; i--) { BB[i] = -B[nB-i+1]+c-r-1; } L[1] = BB; } else // should never get here: BS poly has non-rational roots { string str = L[3]; L = delete(L,3); str = "poly @b = (" + str + ")*(" + string(fl2poly(L,"s")) + ");"; execute(str); poly b = subst(@b,s,-s+c-r-1); L = bFactor(b); } setring save; list L = imap(S,L); return(L); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),dp; ideal F = x^2+y^3, z; list L = bfctVarIn(F); L; } static proc smallGenCoDim (ideal I, int Iasgiven) { // call from K[x], returns list L // L[1]=I or L[1]=smaller generating set of I // L[2]=codimension(I) int ppl = printlevel - voice + 2; int n = nvars(basering); int c; if (attrib(I,"isSB")) { c = n - dim(I); if (!Iasgiven) { list L = mstd(I); } } else { def save = basering; list RL = ringlist(save); list @ord; @ord[1] = list("dp", intvec(1:n)); @ord[2] = list("C", intvec(0)); RL[3] = @ord; kill @ord; if (size(RL)>4) // commutative G-algebra present { RL = RL[1..4]; } def R = ring(RL); kill RL; setring R; ideal I = imap(save,I); if (!Iasgiven) { list L = mstd(I); c = n - dim(L[1]); setring save; list L = imap(R,L); } else { I = std(I); c = n - dim(I); setring save; } kill R; } if (!Iasgiven) { if (size(L[2]) < size(I)) { I = L[2]; dbprint(ppl,"// Found smaller generating set of the given variety: ", I); } else { dbprint(ppl,"// Have not found smaller generating set of the given variety."); } } dbprint(ppl-1,"// The codim of the given variety is " + string(c) + "."); if (!defined(L)) { list L; } L[1] = I; L[2] = c; return(L); } /* // Some more examples static proc TXcups() { "EXAMPLE:"; echo = 2; //TX tangent space of X=V(x^2+y^3) ring R = 0,(x0,x1,y0,y1),Dp; ideal F = x0^2+y0^3, 2*x0*x1+3*y0^2*y1; printlevel = 0; //ORD = "(a(1,1),a(1,1,1,1,1,1),dp)"; //eng = 0; def A = SannfsVar(F); setring A; LD; } static proc ex47() { ring r7 = 0,(x0,x1,y0,y1),dp; ideal I = x0^2+y0^3, 2*x0*x1+3*y0^2*y1; bfctVarIn(I); // second ex - too big ideal J = x0^4+y0^5, 4*x0^3*x1+5*y0^4*y1; bfctVarIn(J); } static proc ex48() { ring r8 = 0,(x1,x2,x3),dp; ideal I = x1^3-x2*x3, x2^2-x1*x3, x3^2-x1^2*x2; bfctVarIn(I); } static proc ex49 () { ring r9 = 0,(z1,z2,z3,z4),dp; ideal I = z3^2-z2*z4, z2^2*z3-z1*z4, z2^3-z1*z3; bfctVarIn(I); } static proc ex410() { LIB "toric.lib"; ring r = 0,(z(1..7)),dp; intmat A[3][7]; A = 6,4,2,0,3,1,0,0,1,2,3,0,1,0,0,0,0,0,1,1,2; ideal I = toric_ideal(A,"pt"); I = std(I); //ideal I = z(6)^2-z(3)*z(7), z(5)*z(6)-z(2)*z(7), z(5)^2-z(1)*z(7), // z(4)*z(5)-z(3)*z(6), z(3)*z(5)-z(2)*z(6), z(2)*z(5)-z(1)*z(6), // z(3)^2-z(2)*z(4), z(2)*z(3)-z(1)*z(4), z(2)^2-z(1)*z(3); bfctVarIn(I,1); // no result yet } */ singular-4.0.3+ds/Singular/LIB/elim.lib000066400000000000000000000754011266270727000175740ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version elim.lib 4.0.0.1 Jan_2014 "; // $Id: a6da1d3bce92babf2df6bbdb98cac0228cf05c77 $ category="Commutative Algebra"; info=" LIBRARY: elim.lib Elimination, Saturation and Blowing up PROCEDURES: blowup0(j[,s1,s2]) create presentation of blownup ring of ideal j elimRing(p) create ring with block ordering for elimating vars in p elim(id,..) variables .. eliminated from id (ideal/module) elim1(id,p) variables .. eliminated from id (different algorithm) elim2(id,..) variables .. eliminated from id (different algorithm) nselect(id,v) select generators not containing variables given by v sat(id,j) saturated quotient of ideal/module id by ideal j select(id,v) select generators containing all variables given by v select1(id,v) select generators containing one variable given by v (parameters in square brackets [] are optional) "; LIB "inout.lib"; LIB "general.lib"; LIB "poly.lib"; LIB "ring.lib"; /////////////////////////////////////////////////////////////////////////////// proc blowup0 (ideal J,ideal C, list #) "USAGE: blowup0(J,C [,W]); J,C,W ideals @* C = ideal of center of blowup, J = ideal to be blown up, W = ideal of ambient space ASSUME: inclusion of ideals : W in J, J in C. If not, the procedure replaces J by J+W and C by C+J+W RETURN: a ring, say B, containing the ideals C,J,W and the ideals @* - bR (ideal defining the blown up basering) @* - aS (ideal of blown up ambient space) @* - eD (ideal of exceptional divisor) @* - tT (ideal of total transform) @* - sT (ideal of strict transform) @* - bM (ideal of the blowup map from basering to B) @* such that B/bR is isomorphic to the blowup ring BC. PURPOSE: compute the projective blowup of the basering in the center C, the exceptional locus, the total and strict tranform of J, and the blowup map. The projective blowup is a presentation of the blowup ring BC = R[C] = R + t*C + t^2*C^2 + ... (also called Rees ring) of the ideal C in the ring basering R. THEORY: If basering = K[x1,...,xn] and C = then let B = K[x1,...,xn,y1,...,yk] and aS the preimage in B of W under the map B -> K[x1,...,xn,t], xi -> xi, yi -> t*fi. aS is homogeneous in the variables yi and defines a variety Z=V(aS) in A^n x P^(k-1), the ambient space of the blowup of V(W). The projection Z -> A^n is an isomorphism outside the preimage of the center V(C) in A^n and is called the blowup of the center. The preimage of V(C) is called the exceptional set, the preimage of V(J) is called the total transform of V(J). The strict transform is the closure of (total transform minus the exceptional set). @* If C = then aS = and Z is the blowup of A^n in 0, the exceptional set is P^(k-1). NOTE: The procedure creates a new ring with variables y(1..k) and x(1..n) where n=nvars(basering) and k=ncols(C). The ordering is a block ordering where the x-block has the ordering of the basering and the y-block has ordering dp if C is not homogeneous resp. the weighted ordering wp(b1,...bk) if C is homogeneous with deg(C[i])=bi. SEE ALSO:blowUp, blowUp2 EXAMPLE: example blowup0; shows examples "{ def br = basering; list l = ringlist(br); int n,k,i = nvars(br),ncols(C),0; ideal W; if (size(#) !=0) { W = #[1];} J = J,W; //J = interred(J+W); //------------------------- create rings for blowup ------------------------ //Create rings tr = K[x(1),...,x(n),t] and nr = K[x(1),...,x(n),y(1),...,y(k)] //and map Bl: nr --> tr, x(i)->x(i), y(i)->t*fi. //Let ord be the ordering of the basering. //We change the ringlist l by changing l[2] and l[3] //For K[t,x(1),...,x(n),t] // - l[2]: the variables to x(1),...,x(n),t // - l[3]: the ordering to a block ordering (ord,dp(1)) //For K[x(1),...,x(n),y(1),...,y(k)] // - l[2]: the variables to x(1),...,x(n),y(1),...,y(k), // - l[3]: the ordering to a block ordering (ord,dp) if C is // not homogeneous or to (ord,wp(b1,...bk),ord) if C is // homogeneous with deg(C[i])=bi; //--------------- create tr = K[x(1),...,x(n),t] --------------------------- int s = size(l[3]); for ( i=n; i>=1; i--) { l[2][i]="x("+string(i)+")"; } l[2]=insert(l[2],"t",n); l[3]=insert(l[3],list("dp",1),s-1); def tr = ring(l); //--------------- create nr = K[x(1),...,x(n),y(1),...,y(k)] --------------- l[2]=delete(l[2],n+1); l[3]=delete(l[3],s); for ( i=k; i>=1; i--) { l[2][n+i]="y("+string(i)+")"; } //---- change l[3]: l[3][s+1] = l[3][s]; // save the module ordering of the basering intvec w=1:k; intvec v; // containing the weights for the varibale if( homog(C) ) { for( i=k; i>=1; i--) { v[i]=deg(C[i]); } if (v != w) { l[3][s]=list("wp",v); } else { l[3][s]=list("dp",v); } } else { v=1:k; l[3][s]=list("dp",v); } def nr = ring(l); //-------- create blowup map Bl: nr --> tr, x(i)->x(i), y(i)->t*fi --------- setring tr; ideal C = fetch(br,C); ideal bl = x(1..n); for( i=1; i<=k; i++) { bl = bl,t*C[i]; } map Bl = nr,bl; ideal Z; //------------------ compute blown up objects and return ------------------- setring nr; ideal bR = preimage(tr,Bl,Z); //ideal of blown up affine space A^n ideal C = fetch(br,C); ideal J = fetch(br,J); ideal W = fetch(br,W); ideal aS = interred(bR+W); //ideal of ambient space ideal tT = interred(J+bR+W); //ideal of total transform ideal eD = interred(C+J+bR+W); //ideal of exceptional divisor ideal sT = sat(tT,C)[1]; //ideal of strict transform ideal bM = x(1..n); //ideal of blowup map br --> nr export(bR,C,J,W,aS,tT,eD,sT,bM); return(nr); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = x2+y3; ideal C = x,y; //center of blowup def B1 = blowup0(f,C); setring B1; aS; //ideal of blown up ambient space tT; //ideal of total transform of f sT; //ideal of strict transform of f eD; //ideal of exceptional divisor bM; //ideal of blowup map r --> B1 ring R = 0,(x,y,z),ds; poly f = y2+x3+z5; ideal C = y2,x,z; ideal W = z-x; def B2 = blowup0(f,C,W); setring B2; B2; //weighted ordering bR; //ideal of blown up R aS; //ideal of blown up R/W sT; //strict transform of f eD; //ideal of exceptional divisor //Note that the different affine charts are {y(i)=1} } ////////////////////////////////////////////////////////////////////////////// proc elimRing ( poly vars, list #) "USAGE: elimRing(vars [,w,str]); vars = product of variables to be eliminated (type poly), w = intvec (specifying weights for all variables), str = string either \"a\" or \"b\" (default: w=ringweights, str=\"a\") RETURN: a list, say L, with R:=L[1] a ring and L[2] an intvec. The ordering in R is an elimination ordering for the variables appearing in vars depending on \"a\" resp. \"b\". Let w1 (resp. w2) be the intvec of weights of the variables to be eliminated (resp. not to be eliminated). The monomial ordering of R has always 2 blocks, the first block corresponds to the (given) variables to be eliminated. @* If str = \"a\" the first block is a(w1,0..0) and the second block is wp(w) resp. ws(w) if the first variable not to be eliminated is local. @* If str = \"b\" the 1st block has ordering wp(w1) and the 2nd block is wp(w2) resp. ws(w2) if the first variable not to be eliminated is local. @* If the basering is a quotient ring P/Q, then R is also a quotient ring with Q replaced by a standard basis of Q w.r.t. the new ordering (parameters are not touched). @* The intvec L[2] is the intvec of variable weights (or the given w) with weights <= 0 replaced by 1. PURPOSE: Prepare a ring for eliminating vars from an ideal/moduel by computing a standard basis in R with a fast monomial ordering. This procedure is used by the procedure elim. EXAMPLE: example elimRing; shows an example " { def BR = basering; int nvarBR = nvars(BR); list BRlist = ringlist(BR); //------------------ set resp. compute ring weights ---------------------- int ii; intvec @w; //to store weights of all variables @w[nvarBR] = 0; @w = @w + 1; //initialize @w as 1..1 string str = "a"; //default for specifying elimination ordering if (size(#) == 0) //default values { @w = ringweights(BR); //compute the ring weights (proc from ring.lib) } if (size(#) == 1) { if ( typeof(#[1]) == "intvec" ) { @w = #[1]; //take the given weights } if ( typeof(#[1]) == "string" ) { str = #[1]; //string for specifying elimination ordering } } if (size(#) >= 2) { if ( typeof(#[1]) == "intvec" and typeof(#[2]) == "string" ) { @w = #[1]; //take the given weights str = #[2]; //string for specifying elimination ordering } if ( typeof(#[1]) == "string" and typeof(#[2]) == "intvec" ) { str = #[1]; //string for specifying elimination ordering @w = #[2]; //take the given weights } } for ( ii=1; ii<=size(@w); ii++ ) { if ( @w[ii] <= 0 ) { @w[ii] = 1; //replace non-positive weights by 1 } } //------ get variables to be eliminated together with their weights ------- intvec w1,w2; //for ringweights of first (w1) and second (w2) block list v1,v2; //for variables of first (to be liminated) and second block for( ii=1; ii<=nvarBR; ii++ ) { if( vars/var(ii)==0 ) //treat variables not to be eliminated { w2 = w2,@w[ii]; v2 = v2+list(string(var(ii))); if ( ! defined(local) ) { int local = (var(ii) < 1); } } else { w1 = w1,@w[ii]; v1 = v1+list(string(var(ii))); } } if ( size(w1) <= 1 ) { return(BR); } if ( size(w2) <= 1 ) { ERROR("## elimination of all variables is not possible"); } w1 = w1[2..size(w1)]; w2 = w2[2..size(w2)]; BRlist[2] = v1 + v2; //put variables to be eliminated in front //-------- create elimination ordering with two blocks and weights --------- //Assume that the first r of the n variables are to be eliminated. //Then, in case of an a-ordering (default), the new ring ordering will be //of the form (a(1..1,0..0),dp) with r 1's and n-r 0's or (a(w1,0..0),wp(@w)) //if there are varaible weights which are not 1. //In the case of a b-ordering the ordering will be a block ordering with two //blocks of the form (dp(r),dp(n-r)) resp. (wp(w1),dp(w2)) list B3; //this will become the list for new ordering //----- b-ordering case: if ( str == "b" ) { if( w1==1 ) //weights for vars to be eliminated are all 1 { B3[1] = list("dp", w1); } else { B3[1] = list("wp", w1); } if( w2==1 ) //weights for vars not to be eliminated are all 1 { if ( local ) { B3[2] = list("ds", w2); } else { B3[2] = list("dp", w2); } } else { if ( local ) { B3[2] = list("ws", w2); } else { B3[2] = list("wp", w2); } } } //----- a-ordering case: else { //define first the second block if( @w==1 ) //weights for all vars are 1 { if ( local ) { B3[2] = list("ls", @w); } else { B3[2] = list("dp", @w); } } else { if ( local ) { B3[2] = list("ws", @w); } else { B3[2] = list("wp", @w); } } //define now the first a-block of the form a(w1,0..0) intvec @v; @v[nvarBR] = 0; @v = @v+w1; B3[1] = list("a", @v); } BRlist[3] = B3; //----------- put module ordering always at the end and return ------------- BRlist[3] = insert(BRlist[3],list("C",intvec(0)),size(B3)); def eRing = ring(quotientList(BRlist)); list result = eRing, @w; return (result); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z,u,v),(c,lp); def P = elimRing(yu); P; intvec w = 1,1,3,4,5; elimRing(yu,w); ring S = (0,a),(x,y,z,u,v),ws(1,2,3,4,5); minpoly = a2+1; qring T = std(ideal(x+y2+v3,(x+v)^2)); def Q = elimRing(yv)[1]; setring Q; Q; } /////////////////////////////////////////////////////////////////////////////// proc elim (def id, list #) "USAGE: elim(id,arg[,s]); id ideal/module, arg can be either an intvec v or a product p of variables (type poly), s a string determining the method which can be \"slimgb\" or \"std\" or, additionally, \"withWeigts\". RETURN: ideal/module obtained from id by eliminating either the variables with indices appearing in v or the variables appearing in p. Works also in a qring. METHOD: elim uses elimRing to create a ring with an elimination ordering for the variables to be eliminated and then applies std if \"std\" is given, or slimgb if \"slimgb\" is given, or a heuristically chosen method. @* If the variables in the basering have weights these weights are used in elimRing. If a string \"withWeigts\" as (optional) argument is given @sc{Singular} computes weights for the variables to make the input as homogeneous as possible. @* The method is different from that used by eliminate and elim1; depending on the example, any of these commands can be faster. NOTE: No special monomial ordering is required, i.e. the ordering can be local or mixed. The result is a SB with respect to the ordering of the second block used by elimRing. E.g. if the first var not to be eliminated is global, resp. local, this ordering is dp, resp. ds (or wp, resp. ws, with the given weights for these variables). If printlevel > 0 the ring for which the output is a SB is shown. SEE ALSO: eliminate, elim1 EXAMPLE: example elim; shows an example " { if (size(#) == 0) { ERROR("## specify variables to be eliminated"); } int pr = printlevel - voice + 2; //for ring display if printlevel > 0 def BR = basering; intvec save_opt=option(get); list lER; //for list returned by elimRing //-------------------------------- check input ------------------------------- poly vars; int ne; //for number of vars to be eliminated int ii; if (size(#) > 0) { if ( typeof(#[1]) == "poly" ) { vars = #[1]; for( ii=1; ii<=nvars(BR); ii++ ) { if ( vars/var(ii) != 0) { ne++; } } } if ( typeof(#[1]) == "intvec" or typeof(#[1]) == "int") { ne = size(#[1]); vars=1; for( ii=1; ii<=ne; ii++ ) { vars=vars*var(#[1][ii]); } } } string method; //for "std" or "slimgb" or "withWeights" if (size(#) >= 2) { if ( typeof(#[2]) == "string" ) { if ( #[2] == "withWeights" ) { intvec @w = weight(id); //computation of weights } if ( #[2] == "std" ) { method = "std"; } if ( #[2] == "slimgb" ) { method = "slimgb"; } } else { ERROR("expected `elim(ideal,intvec[,string])`"); } if (size(#) == 3) { if ( typeof(#[3]) == "string" ) { if ( #[3] == "withWeights" ) { intvec @w = weight(id); //computation of weights } if ( #[3] == "std" ) { method = "std"; } if ( #[3] == "slimgb" ) { method = "slimgb"; } } } if ( method == "" ) { ERROR("expected \"std\" or \"slimgb\" or \"withWeights\" as the optional string parameters"); } } //-------------- create new ring and map objects to new ring ------------------ if ( defined(@w) ) { lER = elimRing(vars,@w); //in this case lER[2] = @w } else { lER = elimRing(vars); intvec @w = lER[2]; //in this case w is the intvec of //variable weights as computed in elimRing } def ER = lER[1]; setring ER; def id = imap(BR,id); poly vars = imap(BR,vars); //---------- now eliminate in new ring and map back to old ring --------------- //if possible apply std(id,hi,w) where hi is the first hilbert function //of id with respect to the weights w. If w is not defined (i.e. good weights //@w are computed then id is only approximately @w-homogeneous and //the hilbert driven std cannot be used directly; however, stdhilb //homogenizes first and applies the hilbert driven std to the homogenization option(redThrough); if (typeof(id)=="matrix") { id = matrix(stdhilb(module(id),method,@w)); } else { id = stdhilb(id,method,@w); } //### Todo: hier sollte id = groebner(id, "hilb"); verwendet werden. //da z.Zt. (Jan 09) groebener bei extra Gewichtsvektor a(...) aber stets std //aufruft und ausserdem "withWeigts" nicht kennt, ist groebner(id, "hilb") //zunaechst nicht aktiviert. Ev. nach Ueberarbeitung von groebner aktivieren id = nselect(id,1..ne); if ( pr > 0 ) { "// result is a SB in the following ring:"; ER; } option(set,save_opt); setring BR; return(imap(ER,id)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,u,v,w),dp; ideal i=x-u,y-u2,w-u3,v-x+y3; elim(i,3..4); elim(i,uv); int p = printlevel; printlevel = 2; elim(i,uv,"withWeights","slimgb"); printlevel = p; ring S = (0,a),(x,y,z,u,v),ws(1,2,3,4,5); minpoly = a2+1; qring T = std(ideal(ax+y2+v3,(x+v)^2)); ideal i=x-u,y-u2,az-u3,v-x+ay3; module m=i*gen(1)+i*gen(2); m=elim(m,xy); show(m); } /////////////////////////////////////////////////////////////////////////////// proc elim2 (def id, intvec va) "USAGE: elim2(id,v); id ideal/module, v intvec RETURNS: ideal/module obtained from id by eliminating variables in v NOTE: no special monomial ordering is required, result is a SB with respect to ordering dp (resp. ls) if the first var not to be eliminated belongs to a -p (resp. -s) blockordering This proc uses 'execute' or calls a procedure using 'execute'. SEE ALSO: elim1, eliminate, elim EXAMPLE: example elim2; shows examples " { //---- get variables to be eliminated and create string for new ordering ------ int ii; poly vars=1; for( ii=1; ii<=size(va); ii++ ) { vars=vars*var(va[ii]); } if( attrib(basering,"global")) { string ordering = "),dp;"; } else { string ordering = "),ls;"; } string mpoly=string(minpoly); //-------------- create new ring and map objects to new ring ------------------ def br = basering; string str = "ring @newr = ("+charstr(br)+"),("+varstr(br)+ordering; execute(str); if (mpoly!="0") { execute("minpoly="+mpoly+";"); } def i = imap(br,id); poly vars = imap(br,vars); //---------- now eliminate in new ring and map back to old ring --------------- i = eliminate(i,vars); setring br; return(imap(@newr,i)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,u,v,w),dp; ideal i=x-u,y-u2,w-u3,v-x+y3; elim2(i,3..4); module m=i*gen(1)+i*gen(2); m=elim2(m,3..4);show(m); } /////////////////////////////////////////////////////////////////////////////// proc elim1 (def id, list #) "USAGE: elim1(id,arg); id ideal/module, arg can be either an intvec v or a product p of variables (type poly) RETURN: ideal/module obtained from id by eliminating either the variables with indices appearing in v or the variables appearing in p METHOD: elim1 calls eliminate but in a ring with ordering dp (resp. ls) if the first var not to be eliminated belongs to a -p (resp. -s) ordering. NOTE: no special monomial ordering is required. This proc uses 'execute' or calls a procedure using 'execute'. SEE ALSO: elim, eliminate EXAMPLE: example elim1; shows examples " { def br = basering; if ( size(ideal(br)) != 0 ) { ERROR ("elim1 cannot eliminate in a qring"); } //------------- create product vars of variables to be eliminated ------------- poly vars; int ii; if (size(#) > 0) { if ( typeof(#[1]) == "poly" ) { vars = #[1]; } if ( typeof(#[1]) == "intvec" or typeof(#[1]) == "int") { vars=1; for( ii=1; ii<=size(#[1]); ii++ ) { vars=vars*var(#[1][ii]); } } } //---- get variables to be eliminated and create string for new ordering ------ for( ii=1; ii<=nvars(basering); ii++ ) { if( vars/var(ii)==0 ) { poly p = 1+var(ii); break;} } if( ord(p)==0 ) { string ordering = "),ls;"; } if( ord(p)>0 ) { string ordering = "),dp;"; } //-------------- create new ring and map objects to new ring ------------------ string str = "ring @newr = ("+charstr(br)+"),("+varstr(br)+ordering; execute(str); def id = fetch(br,id); poly vars = fetch(br,vars); //---------- now eliminate in new ring and map back to old ring --------------- id = eliminate(id,vars); setring br; return(imap(@newr,id)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,t,s,z),dp; ideal i=x-t,y-t2,z-t3,s-x+y3; elim1(i,ts); module m=i*gen(1)+i*gen(2); m=elim1(m,3..4); show(m); } /////////////////////////////////////////////////////////////////////////////// proc nselect (def id, intvec v) "USAGE: nselect(id,v); id = ideal, module or matrix, v = intvec RETURN: generators (or columns) of id not containing the variables with index an entry of v SEE ALSO: select, select1 EXAMPLE: example nselect; shows examples " { if (typeof(id) != "ideal") { if (typeof(id)=="module" || typeof(id)=="matrix") { module id1 = module(id); } else { ERROR("// *** input must be of type ideal or module or matrix"); } } else { ideal id1 = id; } int j,k; int n,m = size(v), ncols(id1); for( k=1; k<=m; k++ ) { for( j=1; j<=n; j++ ) { if( size(id1[k]/var(v[j]))!=0 ) { id1[k]=0; break; } } } if(typeof(id)=="matrix") { return(matrix(simplify(id1,2))); } return(simplify(id1,2)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,t,s,z),(c,dp); ideal i=x-y,y-z2,z-t3,s-x+y3; nselect(i,3); module m=i*(gen(1)+gen(2)); m; nselect(m,3..4); nselect(matrix(m),3..4); } /////////////////////////////////////////////////////////////////////////////// proc sat (def id, ideal j) "USAGE: sat(id,j); id=ideal/module, j=ideal RETURN: list of an ideal/module [1] and an integer [2]: [1] = saturation of id with respect to j (= union_(k=1...) of id:j^k) [2] = saturation exponent (= min( k | id:j^k = id:j^(k+1) )) NOTE: [1] is a standard basis in the basering DISPLAY: saturation exponent during computation if printlevel >=1 EXAMPLE: example sat; shows an example "{ int ii,kk; def i=id; id=std(id); int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) while( ii<=size(i) ) { dbprint(p-1,"// compute quotient "+string(kk+1)); i=quotient(id,j); for( ii=1; ii<=size(i); ii++ ) { if( reduce(i[ii],id,1)!=0 ) break; } id=std(i); kk++; } dbprint(p-1,"// saturation becomes stable after "+string(kk-1)+" iteration(s)",""); list L = id,kk-1; return (L); } example { "EXAMPLE:"; echo = 2; int p = printlevel; ring r = 2,(x,y,z),dp; poly F = x5+y5+(x-y)^2*xyz; ideal j = jacob(F); sat(j,maxideal(1)); printlevel = 2; sat(j,maxideal(2)); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc select (def id, intvec v) "USAGE: select(id,n[,m]); id = ideal/module/matrix, v = intvec RETURN: generators/columns of id containing all variables with index an entry of v NOTE: use 'select1' for selecting generators/columns containing at least one of the variables with index an entry of v SEE ALSO: select1, nselect EXAMPLE: example select; shows examples " { if (typeof(id) != "ideal") { if (typeof(id)=="module" || typeof(id)=="matrix") { module id1 = module(id); } else { ERROR("// *** input must be of type ideal or module or matrix"); } } else { ideal id1 = id; } int j,k; int n,m = size(v), ncols(id1); for( k=1; k<=m; k++ ) { for( j=1; j<=n; j++ ) { if( size(id1[k]/var(v[j]))==0) { id1[k]=0; break; } } } if(typeof(id)=="matrix") { return(matrix(simplify(id1,2))); } return(simplify(id1,2)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,t,s,z),(c,dp); ideal i=x-y,y-z2,z-t3,s-x+y3; ideal j=select(i,1); j; module m=i*(gen(1)+gen(2)); m; select(m,1..2); select(matrix(m),1..2); } /////////////////////////////////////////////////////////////////////////////// proc select1 (def id, intvec v) "USAGE: select1(id,v); id = ideal/module/matrix, v = intvec RETURN: generators/columns of id containing at least one of the variables with index an entry of v NOTE: use 'select' for selecting generators/columns containing all variables with index an entry of v SEE ALSO: select, nselect EXAMPLE: example select1; shows examples " { if (typeof(id) != "ideal") { if (typeof(id)=="module" || typeof(id)=="matrix") { module id1 = module(id); module I; } else { ERROR("// *** input must be of type ideal or module or matrix"); } } else { ideal id1 = id; ideal I; } int j,k; int n,m = size(v), ncols(id1); for( k=1; k<=m; k++ ) { for( j=1; j<=n; j++ ) { if( size(subst(id1[k],var(v[j]),0)) != size(id1[k]) ) { I = I,id1[k]; break; } } } if(typeof(id)=="matrix") { return(matrix(simplify(I,2))); } return(simplify(I,2)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,t,s,z),(c,dp); ideal i=x-y,y-z2,z-t3,s-x+y3; ideal j=select1(i,1);j; module m=i*(gen(1)+gen(2)); m; select1(m,1..2); select1(matrix(m),1..2); } /* /////////////////////////////////////////////////////////////////////////////// // EXAMPLEs /////////////////////////////////////////////////////////////////////////////// // Siehe auch file 'tst-elim' mit grossem Beispiel; example blowup0; example elimRing; example elim; example elim1; example nselect; example sat; example select; example select1; //=========================================================================== // Rationale Normalkurve vom Grad d im P^d bzw. im A^d: //homogen s:t -> (t^d:t^(d-1)s: ...: s^d), inhomogen t ->(t^d:t^(d-1): ...:t) //------------------- 1. Homogen: //Varianten der Methode int d = 5; ring R = 0,(s,t,x(0..d)),dp; ideal I; for( int ii=0; ii<=d; ii++) {I = I,ideal(x(ii)-t^(d-ii)*s^ii); } int tt = timer; ideal eI = elim(I,1..2,"std"); ideal eI = elim(I,1..2,"slimgb"); ideal eI = elim(I,st,"withWeights"); ideal eI = elim(I,st,"std","withWeights"); //komplizierter int d = 50; ring R = 0,(s,t,x(0..d)),dp; ideal I; for( int ii=0; ii<=d; ii++) {I = I,ideal(x(ii)-t^(d-ii)*s^ii); } int tt = timer; ideal eI = elim(I,1..2); //56(44)sec (slimgb 22(17),hilb 33(26)) timer-tt; tt = timer; ideal eI = elim1(I,1..2); //71(53)sec timer-tt; tt = timer; ideal eI = eliminate(I,st); //70(51)sec (wie elim1) timer-tt; timer-tt; tt = timer; ideal eI = elim(I,1..2,"withWeights"); //190(138)sec //(weights73(49), slimgb43(33), hilb71(53) timer-tt; //------------------- 2. Inhomogen int d = 50; ring r = 0,(t,x(0..d)),dp; ideal I; for( int ii=0; ii<=d; ii++) {I = I+ideal(x(ii)-t^(d-ii)); } int tt = timer; ideal eI = elim(I,1,); //20(15)sec (slimgb13(10), hilb6(5)) ideal eI = elim(I,1,"std"); //17sec (std 11, hilb 6) timer-tt; tt = timer; ideal eI = elim1(I,t); //8(6)sec timer-tt; tt = timer; ideal eI = eliminate(I,t); //7(6)sec timer-tt; timer-tt; tt = timer; ideal eI = elim(I,1..1,"withWeights"); //189(47)sec //(weights73(42), slimgb43(1), hilb70(2) timer-tt; //=========================================================================== // Zufaellige Beispiele, homogen system("random",37); ring R = 0,x(1..6),lp; ideal I = sparseid(4,3); int tt = timer; ideal eI = elim(I,1); //108(85)sec (slimgb 29(23), hilb79(61) timer-tt; tt = timer; ideal eI = elim(I,1,"std"); //(139)sec (std 77, hilb 61) timer-tt; tt = timer; ideal eI = elim1(I,1); //(nach 45 min abgebrochen) timer-tt; tt = timer; ideal eI = eliminate(I,x(1)); //(nach 45 min abgebrochen) timer-tt; tt = timer; // Zufaellige Beispiele, inhomogen system("random",37); ring R = 32003,x(1..5),dp; ideal I = sparseid(4,2,3); option(prot,redThrough); intvec w = 1,1,1,1,1,1; int tt = timer; ideal eI = elim(I,1,w); //(nach 5min abgebr.) hilb schlaegt nicht zu timer-tt; tt = timer; //BUG!!!!!! int tt = timer; ideal eI = elim(I,1); //(nach 5min abgebr.) hilb schlaegt nicht zu timer-tt; tt = timer; //BUG!!!!!! ideal eI = elim1(I,1); //8(7.8)sec timer-tt; tt = timer; ideal eI = eliminate(I,x(1)); //8(7.8)sec timer-tt; tt = timer; BUG!!!! // Zufaellige Beispiele, inhomogen, lokal system("random",37); ring R = 32003,x(1..6),ds; ideal I = sparseid(4,1,2); option(prot,redThrough); int tt = timer; ideal eI = elim(I,1); //(haengt sich auf) timer-tt; tt = timer; ideal eI = elim1(I,1); //(0)sec !!!!!! timer-tt; tt = timer; ideal eI = eliminate(I,x(1)); //(ewig mit ...., abgebrochen) timer-tt; tt = timer; ring R1 =(32003),(x(1),x(2),x(3),x(4),x(5),x(6)),(a(1,0,0,0,0,0),ds,C); ideal I = imap(R,I); I = std(I); //(haengt sich auf) !!!!!!! ideal eI = elim(I,1..1,"withWeights"); //(47)sec (weights42, slimgb1, hilb2) timer-tt; ring R1 =(32003),(x(1),x(2),x(3),x(4),x(5),x(6)),(a(1,0,0,0,0,0),ds,C); ideal I = imap(R,I); I = std(I); //(haengt sich auf) !!!!!!! ideal eI = elim(I,1..1,"withWeights"); //(47)sec (weights42, slimgb1, hilb2) timer-tt; */ singular-4.0.3+ds/Singular/LIB/ellipticcovers.lib000066400000000000000000000405201266270727000216670ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version ellipticcovers.lib 4.0.0.0 Dec_2013 "; category="Commutative Algebra"; info=" LIBRARY: ellipticCovers.lib Gromov-Witten numbers of elliptic curves AUTHORS: J. Boehm, boehm @ mathematik.uni-kl.de A. Buchholz, buchholz @ math.uni-sb.de H. Markwig hannah @ math.uni-sb.de OVERVIEW: We implement a formula for computing the number of covers of elliptic curves. It has beed obtained by proving mirror symmetry for arbitrary genus by tropical methods in [BBM]. A Feynman graph of genus g is a trivalent, connected graph of genus g (with 2g-2 vertices and 3g-3 edges). The branch type b=(b_1,...,b_(3g-3)) of a stable map is the multiplicity of the the edge i over a fixed base point. Given a Feynman graph G and a branch type b, we obtain the number N_(G,b) of stable maps of branch type b from a genus g curve of topological type G to the elliptic curve by computing a path integral over a rational function. The path integral is computed as a residue. The sum of N_(G,b) over all branch types b of sum d gives N_(G,d)*|Aut(G)|, with the Gromov-Witten invariant N_(G,d) of degree d stable maps from a genus g curve of topological type G to the elliptic curve. The sum of N_(G,d) over all such graphs gives the usual Gromov-Witten invariant N_(g,d) of degree d stable maps from a genus g curve to the elliptic curve. The key function computing the numbers N_(G,b) and N_(G,d) is gromovWitten. REFERENCES: [BBM] J. Boehm, A. Buchholz, H. Markwig: Tropical mirror symmetry for elliptic curves, arXiv:1309.5893 (2013). KEYWORDS: tropical geometry; mirror symmetry; tropical mirror symmetry; Gromov-Witten invariants; elliptic curves; propagator; Feynman graph; path integral TYPES: graph PROCEDURES: makeGraph(list, list) generate a graph from a list of vertices and a lsit of edges printGraph(graph) print procedure for graphs propagator(list,int) propagator factor of degree d in the quotient of two variables, or propagator for fixed graph and branch type computeConstant(number, number) constant coefficient in the Laurent series expansion of a rational function in a given variable evalutateIntegral(number, list) path integral for a given propagator and ordered sequence of variables gromovWitten(number) sum of path integrals for a given propagator over all orderings of the variables, or Gromov Witten invariant for a given graph and a fixed branch type, or list of Gromov Witten invariants for a given graph and all branch types computeGromovWitten(graph, int, int) compute the Gromov Witten invariants for a given graph and some branch types generatingFunction (graph, int) multivariate generating function for the Gromov Witten invariants of a graph up to fixed degree partitions(int, int) partitions of an integer into a fixed number of summands permute(list) all permutations of a list lsum(list) sum of the elements of a list "; LIB "parallel.lib"; proc mod_init() { newstruct("graph","list vertices, list edges"); newstruct("Net","list rows"); system("install","graph","print",printGraph,1); system("install","Net","print",printNet,1); system("install","Net","+",catNet,2); } static proc catNet(Net N, Net M) { list L; list LN=N.rows; list LM=M.rows; int widthN=size(LN[1]); int widthM=size(LM[1]); int nm=max(size(LN),size(LM)); for (int j=1; j<=nm; j++) { if (j>size(LN)){LN[j]=emptyString(widthN);} if (j>size(LM)){LM[j]=emptyString(widthM);} L[j]=LN[j]+LM[j]; } Net NM; NM.rows=L; return(NM);} static proc netList(list L1) { Net N=net("["); for (int j=1; j<=size(L1)-1; j++) { N=N+net(L1[j])+net(", "); } N=N+net(L1[size(L1)])+net("]"); return(N); } static proc printNet(Net N) { list L = N.rows; for (int j=1; j<=size(L); j++) { print(L[j]); } } static proc net(def M){ if (typeof(M)=="list"){ return(netList(M)); } Net N; list L; L[1]=string(M); N.rows=L; return(N);} proc printGraph(graph G) "USAGE: printGraph(G); G graph@* ASSUME: G is a graph. THEORY: This is the print function used by Singular to print a graph. KEYWORDS: graph EXAMPLE: example printGraph; shows an example " { print(netList(G.edges)); print("Graph with "+string(size(G.vertices))+" vertices and "+string(size(G.edges))+" edges") } example { "EXAMPLE:"; echo=2; ring R=(0,x1,x2,x3,x4),(q1,q2,q3,q4,q5,q6),dp; graph G = makeGraph(list(1,2,3,4),list(list(1,3),list(1,2),list(1,2),list(2,4),list(3,4),list(3,4))); G; } proc makeGraph(list v, list e) "USAGE: makeGraph(v,e); v list, e list@* ASSUME: v is a list of integers, e is a list of two element lists of v. RETURN: graph with vertices v and edges e THEORY: Creates a graph from a list of vertices and edges. The vertices can be any type. KEYWORDS: graph EXAMPLE: example printGraph; shows an example " { graph G; G.vertices = v; G.edges = e; return(G); } example { "EXAMPLE:"; echo=2; ring R=(0,x1,x2,x3,x4),(q1,q2,q3,q4,q5,q6),dp; graph G = makeGraph(list(1,2,3,4),list(list(1,3),list(1,2),list(1,2),list(2,4),list(3,4),list(3,4))); G; } proc propagator(def xy, def d) "USAGE: propagator(xy,d); xy list, d int@* propagator(G,b); G graph, b list@* ASSUME: xy is a list of two numbers x and y in a rational function field, d non-negative integer.@* G is a Feynman graph, a is a list of integers of length equal to the number of edges of G.@* We assume that the coefficient ring has one rational variable for each vertex of G. RETURN: number, the propagator associated to the input data. THEORY: If xy and d are specified, then the function returns x^2*y^2/(x^2-y^2)^2) for d=0, which is a associated to an edge with vertices x and y not passing above the base point. For d>0 it returns the sum of (j*x^(4*j)+j*y^(4*j))/(x*y)^(2*j) over all divisors j of d, which is associated to an edge with vertices x and y passing with multiplicity d above the base point. Essentially the variables x and y stand for the position of the base points. In the second way of using this function, G is a Feynman graph and b is a branch type over a fixed base point of a cover with source G and target an elliptic curve. It returns the product of propagator(list(v[i],w[i]),b[i]) over all edges i with multiplicity b[i] over the base point and vertices v[i] and w[i]. KEYWORDS: elliptic curve EXAMPLE: example propagator; shows an example " { if ((typeof(xy)=="list")||(typeof(d)=="int")) { number x = xy[1]; number y = xy[2]; if (d<0) {ERROR("expected non-negative degree");} if (d==0) {return(x^2*y^2/(x^2-y^2)^2);} number p=0; for (int j=1; j<=d; j++){ if (d%j==0){p=p+(j*x^(4*j)+j*y^(4*j))/(x*y)^(2*j);} } return(p); } if ((typeof(xy)=="graph")||(typeof(d)=="list")) { list xl = ringlist(basering)[1][2]; list ed = xy.edges; number f=1; for (int j=1; j<=size(ed); j++){ execute("number xx1 = "+xl[ed[j][1]]); execute("number xx2 = "+xl[ed[j][2]]); f=f*propagator(list(xx1,xx2),d[j]); kill xx1; kill xx2; } return(f); } if ((typeof(xy)=="graph")||(typeof(d)=="int")) { } ERROR("wrong input type");} example { "EXAMPLE:"; echo=2; ring R=(0,x1,x2,x3,x4),(q1,q2,q3,q4,q5,q6),dp; graph G = makeGraph(list(1,2,3,4),list(list(1,3),list(1,2),list(1,2),list(2,4),list(3,4),list(3,4))); propagator(list(x1,x2),0); propagator(list(x1,x2),2); propagator(G,list(1,1,1,0,0,0)); } proc computeConstant(number f,number xx) "USAGE: computeConstant(f,x); f number, x number@* ASSUME: f is a number in a rational function field, x is a variable of the field.@* RETURN: number, the constant coefficient of the Laurent series of f in the variable x. THEORY: Computes the constant coefficient of the Laurent series by iterative differentiation. KEYWORDS: Laurent series EXAMPLE: example computeConstant; shows an example " { int tst=0; number ff=f; int k; int j; poly de; while (tst==0){ ff=f*xx^k; for (j=1; j<=k; j++){ ff=diff(ff,xx)/j; } de = subst(denominator(ff),xx,0); if (de!=0){ poly nu = subst(numerator(ff),xx,0); return(number(nu/de)); } k=k+1; } ERROR("error in computeConstant");} example { "EXAMPLE:"; echo=2; ring R=(0,x1,x2,x3,x4),(q1,q2,q3,q4,q5,q6),dp; graph G = makeGraph(list(1,2,3,4),list(list(1,3),list(1,2),list(1,2),list(2,4),list(3,4),list(3,4))); number P = propagator(G,list(1,1,1,0,0,0)); computeConstant(P,x2); } proc evaluateIntegral(number P, list xL) "USAGE: evaluateIntegral(P,xx); P number, xx list@* ASSUME: P is a number in a rational function field, xx is a list of variables of the field@* RETURN: number, the constant coefficient of the Laurent series of f in the variables in the list xx. THEORY: Computes the constant coefficient of the Laurent series iteratively for the elements of xx. In the setting of covers of elliptic curves this is the path integral over the propagator divided by the product of all variables (corresponding to the vertices) computed as a residue. KEYWORDS: residue; Laurent series EXAMPLE: example evaluateIntegral; shows an example " { number p = P; for(int j=1; j<=size(xL); j++){ p=computeConstant(p,xL[j]); } return(p);} example { "EXAMPLE:"; echo=2; ring R=(0,x1,x2,x3,x4),(q1,q2,q3,q4,q5,q6),dp; graph G = makeGraph(list(1,2,3,4),list(list(1,3),list(1,2),list(1,2),list(2,4),list(3,4),list(3,4))); number p = propagator(G,list(0,2,1,0,0,1)); evaluateIntegral(p,list(x1,x3,x4,x2)); } proc permute (list N) "USAGE: permute(N); N list@* ASSUME: N is a list@* RETURN: list with all permutations of N. THEORY: Computes all permutations of N. This will eventually be deleted and become a more efficient kernel function. KEYWORDS: permutations EXAMPLE: example permute; shows an example " { int i,j,k; list L,L1; if (size(N)==1){ return(list(N)); } else { k=1; for (i=1; i<=size(N); i++){ L=permute(delete(N,i)); for (j=1; j<=size(L); j++){ L1[k]=L[j]+list(N[i]); k=k+1; } } } return(L1);} example { "EXAMPLE:"; echo=2; ring R=(0,x1,x2,x3,x4),(q),dp; permute(list(x1,x2,x3,x4)); } proc partitions(int n, int a) "USAGE: partitions(n,a); n int, a int@* ASSUME: n and a are positive integers@* RETURN: list of all partitions of a into n summands. THEORY: Computes all partitions of a into n summands. This may eventually be deleted and become a more efficient kernel function. KEYWORDS: partitions EXAMPLE: example partitions; shows an example " { ring R = 2,(x(1..n)),dp; ideal I = maxideal(a); list L; for (int j=1;j<=size(I);j++){ L[j]=leadexp(I[j]); } return(L);} example { "EXAMPLE:"; echo=2; partitions(3,7); } proc gromovWitten(def P,list #) "USAGE: gromovWitten(P); P number@* gromovWitten(G,d); G graph, d int@* gromovWitten(G,b); G graph, b list@* ASSUME: P is a propagator, or @* G is a Feynman graph and d a non-negative integer, or@* G is a Feynman graph and b is a list of integers of length equal to the number of edges of G@* We assume that the coefficient ring has one rational variable for each vertex of G.@* RETURN: Gromov-Witten invariant. THEORY: Computes @* - the Gromov-Witten invariant of a given propagator P, or @* - the invariant N_(G,d)*|Aut(G)| where d is the degree of the covering, or @* - the number N_(G,b) of coverings with source G and target an elliptic curves with branch type a over a fixed base point (that is, the i-th edge passes over the base point with multiplicity b[i]).@* KEYWORDS: Gromov-Witten invariants; elliptic curves; coverings; Hurwitz numbers EXAMPLE: example gromovWitten; shows an example " { if (typeof(P)=="number") { list xl = ringlist(basering)[1][2]; int j; for(j=1; j<=size(xl); j++){ execute("number n= "+xl[j]); xl[j]=n; kill n; } list pxl = permute(xl); number p = 0; for(j=1; j<=size(pxl); j++){ p=p+evaluateIntegral(P,pxl[j]); } return(p); } if (typeof(P)=="graph"){ if (size(#)>1){ return(gromovWitten(propagator(P,#))); } else { int d =#[1]; list pa = partitions(size(P.edges),d); list re; int ti; for (int j=1; j<=size(pa); j++) { ti=timer; re[j]=gromovWitten(propagator(P,pa[j])); ti=timer-ti; //print(string(j)+" / "+string(size(pa))+" "+string(pa[j])+" "+string(re[j])+" "+string(sum(re))+" "+string(ti)); } return(lsum(re)); } } } example { "EXAMPLE:"; echo=2; ring R=(0,x1,x2,x3,x4),(q1,q2,q3,q4,q5,q6),dp; graph G = makeGraph(list(1,2,3,4),list(list(1,3),list(1,2),list(1,2),list(2,4),list(3,4),list(3,4))); number P = propagator(G,list(0,2,1,0,0,1)); gromovWitten(P); gromovWitten(G,list(0,2,1,0,0,1)); gromovWitten(G,2); } proc computeGromovWitten(graph P,int d, int st, int en, list #) "USAGE: computeGromovWitten(G, d, st, en [, vb] ); G graph, d int, st int, en int, optional: vb int@* ASSUME: G is a Feynman graph, d a non-negative integer, st specified the start- and en the end partition in the list pa = partition(d). Specifying a positive optional integer vb leads to intermediate printout.@* We assume that the coefficient ring has one rational variable for each vertex of G.@* RETURN: list L, where L[i] is gromovWitten(G,pa[i]) and all others are zero. THEORY: This function does essentially the same as the function gromovWitten, but is designed for handling complicated examples. Eventually it will also run in parallel.@* KEYWORDS: Gromov-Witten invariants; elliptic curves; coverings; Hurwitz numbers EXAMPLE: example computeGromovWitten; shows an example " { number s =0; list pararg; list re; list pa = partitions(size(P.edges),d); int vb=0; if (size(#)>0){vb=#[1];} int ti; if (vb>0){print(size(pa));} for (int j=1; j<=size(pa); j++) { if ((j>=st)&(j<=en)){ ti=timer; //pararg[j]=list(propagator(G,pa[j])); re[j]=gromovWitten(propagator(P,pa[j])); ti=timer-ti; if (vb>0){print(string(j)+" / "+string(size(pa))+" "+string(pa[j])+" "+string(re[j])+" "+string(lsum(re))+" "+string(ti));} } else {re[j]=s;} } //list re = parallelWaitAll("gromovWitten", pararg, list(list(list(2)))); return(re); } example { "EXAMPLE:"; echo=2; ring R=(0,x1,x2,x3,x4),(q1,q2,q3,q4,q5,q6),dp; graph G = makeGraph(list(1,2,3,4),list(list(1,3),list(1,2),list(1,2),list(2,4),list(3,4),list(3,4))); partitions(6,2); computeGromovWitten(G,2,3,7); computeGromovWitten(G,2,3,7,1); } proc lsum(list L) "USAGE: lsum(L); L list@* ASSUME: L is a list of things with the binary operator + defined.@* RETURN: The sum of the elements of L. THEORY: Sums the elements of a list. Eventually this will be deleted and become a more efficient kernel function.@* EXAMPLE: example lsum; shows an example " { execute(typeof(L[1])+" s"); for(int j=1; j<=size(L); j++){ s=s+L[j]; } return(s);} example { "EXAMPLE:"; echo=2; list L = 1,2,3,4,5; lsum(L); } proc generatingFunction(graph G, int d) "USAGE: generatingFunction(G, d); G graph, d int@* ASSUME: G is a Feynman graph, d a non-negative integer. The basering has one polynomial variable for each edge, and the coefficient ring has one rational variable for each vertex.@* RETURN: poly. THEORY: This function compute the multivariate generating function of all Gromov-Witten invariants up to degree d, that is, the sum of all gromovWitten(G,b)*q^b.@* KEYWORDS: generating function; Gromov-Witten invariants; elliptic curves; coverings; Hurwitz numbers EXAMPLE: example generatingFunction; shows an example " { poly s =0; int j,jj; list pa,L; for (j=1; j<=d; j++){ pa = partitions(size(G.edges),j); L = computeGromovWitten(G,j,1,size(pa)); for (jj=1; jj<=size(pa); jj++) { s=s+L[jj]*monomial(pa[jj]); } } return(s);} example { "EXAMPLE:"; echo=2; ring R=(0,x1,x2),(q1,q2,q3),dp; graph G = makeGraph(list(1,2),list(list(1,2),list(1,2),list(1,2))); generatingFunction(G,3); } singular-4.0.3+ds/Singular/LIB/equising.lib000066400000000000000000001526261266270727000204770ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////// version="version equising.lib 4.0.0.0 Jun_2013 "; // $Id: f8f820b12fc9a0a6f835f66d8ffaf7ef15cd9405 $ category="Singularities"; info=" LIBRARY: equising.lib Equisingularity Stratum of a Family of Plane Curves AUTHOR: Christoph Lossen, lossen@mathematik.uni-kl.de Andrea Mindnich, mindnich@mathematik.uni-kl.de PROCEDURES: tau_es(f); codim of mu-const stratum in semi-universal def. base esIdeal(f); (Wahl's) equisingularity ideal of f esStratum(F[,m,L]); equisingularity stratum of a family F isEquising(F[,m,L]); tests if a given deformation is equisingular control_Matrix(M); computes list of blowing-up data "; LIB "hnoether.lib"; LIB "poly.lib"; LIB "elim.lib"; LIB "deform.lib"; LIB "sing.lib"; //////////////////////////////////////////////////////////////////////////////// // // The following (static) procedures are used by esComputation // //////////////////////////////////////////////////////////////////////////////// // COMPUTES a weight vector. x and y get weight 1 and all other // variables get weight 0. static proc xyVector() { intvec iv ; iv[nvars(basering)]=0 ; iv[rvar(x)] =1; iv[rvar(y)] =1; return (iv); } //////////////////////////////////////////////////////////////////////////////// // exchanges the variables x and y in the polynomial f static proc swapXY(poly f) { def r_base = basering; ideal MI = maxideal(1); MI[rvar(x)]=y; MI[rvar(y)]=x; map phi = r_base, MI; f=phi(f); return (f); } //////////////////////////////////////////////////////////////////////////////// // computes m-jet w.r.t. the variables x,y (other variables weighted 0 static proc m_Jet(poly F,int m); { intvec w=xyVector(); poly Fd=jet(F,m,w); return(Fd); } //////////////////////////////////////////////////////////////////////////////// // computes the 4 control matrices (input is multsequence(L)) proc control_Matrix(list M); "USAGE: control_Matrix(L); L list ASSUME: L is the output of multsequence(hnexpansion(f)). RETURN: list M of 4 intmat's: @format M[1] contains the multiplicities at the respective infinitely near points p[i,j] (i=step of blowup+1, j=branch) -- if branches j=k,...,k+m pass through the same p[i,j] then the multiplicity is stored in M[1][k,j], while M[1][k+1]=...=M[1][k+m]=0. M[2] contains the number of branches meeting at p[i,j] (again, the information is stored according to the above rule) M[3] contains the information about the splitting of M[1][i,j] with respect to different tangents of branches at p[i,j] (information is stored only for minimal j>=k corresponding to a new tangent direction). The entries are the sum of multiplicities of all branches with the respective tangent. M[4] contains the maximal sum of higher multiplicities for a branch passing through p[i,j] ( = degree Bound for blowing up) @end format NOTE: the branches are ordered in such a way that only consecutive branches can meet at an infinitely near point. @* the final rows of the matrices M[1],...,M[3] is (1,1,1,...,1), and correspond to infinitely near points such that the strict transforms of the branches are smooth and intersect the exceptional divisor transversally. SEE ALSO: multsequence EXAMPLE: example control_Matrix; shows an example " { int i,j,k,dummy; dummy=0; for (j=1;j<=ncols(M[2]);j++) { dummy=dummy+M[1][nrows(M[1])-1,j]-M[1][nrows(M[1]),j]; } intmat S[nrows(M[1])+dummy][ncols(M[1])]; intmat T[nrows(M[1])+dummy][ncols(M[1])]; intmat U[nrows(M[1])+dummy][ncols(M[1])]; intmat maxDeg[nrows(M[1])+dummy][ncols(M[1])]; for (i=1;i<=nrows(M[2]);i++) { dummy=1; for (j=1;j<=ncols(M[2]);j++) { for (k=dummy;k1) { U[i-1,dummy]=U[i-1,dummy]+M[1][i-1,k]; } } dummy=k; } } // adding an extra row (in some cases needed to control ES-Stratum // computation) for (i=nrows(M[1]);i<=nrows(S);i++) { for (j=1;j<=ncols(M[2]);j++) { S[i,j]=1; T[i,j]=1; U[i,j]=1; } } // Computing the degree Bounds to be stored in M[4]: for (i=1;i<=nrows(S);i++) { dummy=1; for (j=1;j<=ncols(S);j++) { for (k=dummy;k=2;i--) { for (j=1;j<=ncols(S);j++) { maxDeg[i-1,j]=maxDeg[i-1,j]+maxDeg[i,j]; } } list L=S,T,U,maxDeg; return(L); } //////////////////////////////////////////////////////////////////////////////// // matrix of higher tangent directions: // returns list: 1) tangent directions // 2) swapping information (x <--> y) static proc inf_Tangents(list L,int s); // L aus hnexpansion, { int nv=nvars(basering); matrix M; matrix B[s][size(L)]; intvec V; intmat Mult=multsequence(L)[1]; int i,j,k,counter,e; for (k=1;k<=size(L);k++) { V[k]=L[k][3]; // switch: 0 --> tangent 2nd parameter // 1 --> tangent 1st parameter e=0; M=L[k][1]; counter=1; B[counter,k]=M[1,1]; for (i=1;i<=nrows(M);i++) { for (j=2;j<=ncols(M);j++) { counter=counter+1; if (M[i,j]==var(nv-1)) { if (i<>nrows(M)) { B[counter,k]=M[i,j]; j=ncols(M)+1; // goto new row of HNmatrix... if (counter<>s) { if (counter+1<=nrows(Mult)) { e=Mult[counter-1,k]-Mult[counter,k]-Mult[counter+1,k]; } else { e=Mult[counter-1,k]-Mult[counter,k]-1; } } } else { B[counter,k]=0; j=ncols(M)+1; // goto new row of HNmatrix... } } else { if (e<=0) { B[counter,k]=M[i,j]; } else // point is still proximate to an earlier point { B[counter,k]=y; // marking proximity (without swap....) if (counter+1<=nrows(Mult)) { e=e-Mult[counter+1,k]; } else { e=e-1; } } } if (counter==s) // given number of points determined { j=ncols(M)+1; i=nrows(M)+1; // leave procedure } } } } L=B,V; return(L); } //////////////////////////////////////////////////////////////////////////////// // compute "good" upper bound for needed number of help variables // static proc Determine_no_b(intmat U,matrix B) // U is assumed to be 3rd output of control_Matrix // B is assumed to be 1st output of inf_Tangents { int nv=nvars(basering); int i,j,counter; for (j=1;j<=ncols(U);j++) { for (i=1;i<=nrows(U);i++) { if (U[i,j]>1) { if (B[i,j]<>var(nv-1) and B[i,j]<>var(nv)) { counter=counter+1; } } } } counter=counter+ncols(U); return(counter); } //////////////////////////////////////////////////////////////////////////////// // compute number of infinitely near free points corresponding to non-zero // entries in control_Matrix[1] (except first row) // static proc no_freePoints(intmat Mult,matrix B) // Mult is assumed to be 1st output of control_Matrix // U is assumed to be 3rd output of control_Matrix // B is assumed to be 1st output of inf_Tangents { int i,j,k,counter; for (j=1;j<=ncols(Mult);j++) { for (i=2;i<=nrows(Mult);i++) { if (Mult[i,j]>=1) { if (B[i-1,j]<>x and B[i-1,j]<>y) { counter=counter+1; } } } } return(counter); } /////////////////////////////////////////////////////////////////////////////// // COMPUTES string(minpoly) and substitutes the parameter by newParName static proc makeMinPolyString (string newParName) { int i; string parName = parstr(basering); int parNameSize = size(parName); string oldMinPolyStr = string (minpoly); int minPolySize = size(oldMinPolyStr); string newMinPolyStr = ""; for (i=1;i <= minPolySize; i++) { if (oldMinPolyStr[i,parNameSize] == parName) { newMinPolyStr = newMinPolyStr + newParName; i = i + parNameSize-1; } else { newMinPolyStr = newMinPolyStr + oldMinPolyStr[i]; } } return(newMinPolyStr); } /////////////////////////////////////////////////////////////////////////////// // // DEFINES: A new basering, "myRing", // with new names for the parameters and variables. // The new names for the parameters are a(1..k), // and t(1..s),x,y for the variables // The ring ordering is ordStr. // NOTE: This proc uses 'execute'. static proc createMyRing_new(poly p_F, string ordStr, string minPolyStr, int no_b) { def r_old = basering; int chara = char(basering); string charaStr; int i; string helpStr; int nDefParams = nvars(r_old)-2; ideal qIdeal = ideal(basering); if ((npars(basering)==0) and (minPolyStr=="")) { helpStr = "ring myRing1 =" + string(chara)+ ", (t(1..nDefParams), x, y),("+ ordStr +");"; execute(helpStr); } else { charaStr = charstr(basering); if ((charaStr == string(chara) + "," + parstr(basering)) or (minPolyStr<>"")) { if (minPolyStr<>"") { helpStr = "ring myRing1 = (" + string(chara) + ",a), (t(1..nDefParams), x, y),(" + ordStr + ");"; execute(helpStr); execute (minPolyStr); } else // no minpoly given { helpStr = "ring myRing1 = (" + string(chara) + ",a(1..npars(basering)) ), (t(1..nDefParams), x, y),(" + ordStr + ");"; execute(helpStr); } } else { // ground field is of type (p^k,a).... i = find (charaStr,","); helpStr = "ring myRing1 = (" + charaStr[1,i] + "a), (t(1..nDefParams), x, y),(" + ordStr + ");"; execute (helpStr); } } ideal mIdeal = maxideal(1); ideal qIdeal = fetch(r_old, qIdeal); poly p_F = fetch(r_old, p_F); export p_F,mIdeal; // Extension by no_b auxiliary variables if (no_b>0) { if (npars(basering) == 0) { ordStr = "(dp("+string(no_b)+"),"+ordStr+")"; helpStr = "ring myRing =" + string(chara)+ ", (b(1..no_b), t(1..nDefParams), x, y)," + ordStr +";"; execute(helpStr); } else { charaStr = charstr(basering); if (charaStr == string(chara) + "," + parstr(basering)) { if (minpoly !=0) { ordStr = "(dp(" + string(no_b) + ")," + ordStr + ")"; minPolyStr = makeMinPolyString("a"); helpStr = "ring myRing = (" + string(chara) + ",a), (b(1..no_b), t(1..nDefParams), x, y)," + ordStr + ";"; execute(helpStr); helpStr = "minpoly =" + minPolyStr + ";"; execute (helpStr); } else // no minpoly given { ordStr = "(dp(" + string(no_b) + ")," + ordStr + ")"; helpStr = "ring myRing = (" + string(chara) + ",a(1..npars(basering)) ), (b(1..no_b), t(1..nDefParams), x, y)," + ordStr + ";"; execute(helpStr); } } else { i = find (charaStr,","); ordStr = "(dp(" + string(no_b) + ")," + ordStr + ")"; helpStr = "ring myRing = (" + charaStr[1,i] + "a), (b(1..no_b), t(1..nDefParams), x, y)," + ordStr + ";"; execute (helpStr); } } ideal qIdeal = imap(myRing1, qIdeal); if(size(qIdeal) != 0) { def r_base = basering; setring r_base; kill myRing; qring myRing = std(qIdeal); } poly p_F = imap(myRing1, p_F); ideal mIdeal = imap(myRing1, mIdeal); export p_F,mIdeal; kill myRing1; } else { if(size(qIdeal) != 0) { def r_base = basering; setring r_base; kill myRing1; qring myRing = std(qIdeal); poly p_F = imap(myRing1, p_F); ideal mIdeal = imap(myRing1, mIdeal); export p_F,mIdeal; } else { def myRing=myRing1; } kill myRing1; } setring r_old; return(myRing); } //////////////////////////////////////////////////////////////////////////////// // returns list of coef, leadmonomial // static proc determine_coef (poly Fm) { def r_base = basering; // is assumed to be the result of createMyRing int chara = char(basering); string charaStr; int i; string minPolyStr = ""; string helpStr = ""; if (npars(basering) == 0) { helpStr = "ring myRing1 =" + string(chara)+ ", (y,x),ds;"; execute(helpStr); } else { charaStr = charstr(basering); if (charaStr == string(chara) + "," + parstr(basering)) { if (minpoly !=0) { minPolyStr = makeMinPolyString("a"); helpStr = "ring myRing1 = (" + string(chara) + ",a), (y,x),ds;"; execute(helpStr); helpStr = "minpoly =" + minPolyStr + ";"; execute (helpStr); } else // no minpoly given { helpStr = "ring myRing1 = (" + string(chara) + ",a(1..npars(basering)) ), (y,x),ds;"; execute(helpStr); } } else { i = find (charaStr,","); helpStr = " ring myRing1 = (" + charaStr[1,i] + "a), (y,x),ds;"; execute (helpStr); } } poly f=imap(r_base,Fm); poly g=leadmonom(f); setring r_base; poly g=imap(myRing1,g); kill myRing1; def M=coef(Fm,xy); for (i=1; i<=ncols(M); i++) { if (M[1,i]==g) { poly h=M[2,i]; // determine coefficient of leading monomial (in K[t]) i=ncols(M)+1; } } return(list(h,g)); } /////////////////////////////////////////////////////////////////////////////// // RETURNS: 1, if p_f = 0 or char(basering) divides the order of p_f // or p_f is not squarefree. // 0, otherwise static proc checkPoly (poly p_f) { int i_print = printlevel - voice + 3; int i_ord; if (p_f == 0) { print("Input is a 'deformation' of the zero polynomial!"); return(1); } i_ord = mindeg1(p_f); if (number(i_ord) == 0) { print("Characteristic of coefficient field " +"divides order of zero-fiber !"); return(1); } if (squarefree(p_f) != p_f) { print("Original polynomial (= zero-fiber) is not reduced!"); return(1); } return(0); } //////////////////////////////////////////////////////////////////////////////// static proc make_ring_small(ideal J) // returns varstr for new ring, the map and the number of vars { attrib(J,"isSB",1); int counter=0; ideal newmap; string newvar=""; for (int i=1; i<=nvars(basering); i++) { if (reduce(var(i),J)<>0) { newmap[i]=var(i); if (newvar=="") { newvar=newvar+string(var(i)); counter=counter+1; } else { newvar=newvar+","+string(var(i)); counter=counter+1; } } else { newmap[i]=0; } } list L=newvar,newmap,counter; attrib(J,"isSB",0); return(L); } /////////////////////////////////////////////////////////////////////////////// // The following procedure is called by esStratum (typ=0), resp. by // isEquising (typ=1) /////////////////////////////////////////////////////////////////////////////// static proc esComputation (int typ, poly p_F, list #) { intvec ov=option(get); // store options set at beginning option(redSB); // Initialize variables int branch=1; int blowup=1; int auxVar=1; int nVars; intvec upper_bound, upper_bound_old, fertig, soll; list blowup_string; int i_print= printlevel-voice+2; int no_b, number_of_branches, swapped; int i,j,k,m, counter, dummy; string helpStr = ""; string ordStr = ""; string MinPolyStr = ""; if (nvars(basering)<=2) { print("family is trivial (no deformation parameters)!"); if (typ==1) //isEquising { option(set,ov); return(1); } else { option(set,ov); return(list(ideal(0),0)); } } if (size(#)>0) { if (typeof(#[1])=="int") { def artin_bd=#[1]; // compute modulo maxideal(artin_bd) if (artin_bd <= 1) { print("Do you really want to compute over Basering/maxideal(" +string(artin_bd)+") ?"); print("No computation performed !"); if (typ==1) //isEquising { option(set,ov); return(1); } else { option(set,ov); return(list(ideal(0),int(1))); } } if (size(#)>1) { if (typeof(#[2])=="list") { def @L=#[2]; // is assumed to be the Hamburger-Noether matrix } } } else { if (typeof(#)=="list") { def @L=#; // is assumed to be the Hamburger-Noether matrix } } } int ring_is_changed; def old_ring=basering; if(defined(@L)<=0) { // define a new ring without deformation-parameters and change to it: string str; string minpolyStr = string(minpoly); str = " ring HNERing = (" + charstr(basering) + "), (x,y), ls;"; execute (str); if (minpolyStr!="0") {str = "minpoly ="+ minpolyStr+";";execute(str);} ring_is_changed=1; // Basering changed to HNERing (variables x,y, with ls ordering) k=nvars(old_ring); matrix Map_Phi[1][k]; Map_Phi[1,k-1]=x; Map_Phi[1,k]=y; map phi=old_ring,Map_Phi; poly f=phi(p_F); // Heuristics: if x,y are transversal parameters then computation of HNE // can be much faster when exchanging variables...! if (2*size(coeffs(f,x))0) { setring old_ring; option(set,ov); return(0); } } F(1)=p_F; // and reduce the remaining terms in F(1): bl_Map(1)=maxideal(1); attrib(J,"isSB",1); bl_Map(1)=reduce(bl_Map(1),J); attrib(J,"isSB",0); phi=myRing,bl_Map(1); F(1)=phi(F(1)); // simplify F(1) attrib(J,"isSB",1); F(1)=reduce(F(1),J); attrib(J,"isSB",0); // now we compute the m-jet: Fm=m_Jet(F(1),m); G=1; counter=branch; k=upper_bound[branch]; F_save=F(1); // is truncated differently in the following loop while(counter<=k) { F(counter)=m_Jet(F_save,maxDeg[blowup,counter]); if (V[counter]==0) // 2nd ring variable is tangent to this branch { G=G*(y-(b(auxVar)+B[blowup,counter])*x)^(M[3][blowup,counter]); } else // 1st ring variable is tangent to this branch { G=G*(x-(b(auxVar)+B[blowup,counter])*y)^(M[3][blowup,counter]); F(counter)=swapXY(F(counter)); } bl_Map(counter)=maxideal(1); bl_Map(counter)[nvars(basering)]=xy+(b(auxVar)+B[blowup,counter])*x; bNodes[counter]=b(auxVar); auxVar=auxVar+1; upper_bound[counter]=counter+M[2][blowup+1,counter]-1; counter=counter+M[2][blowup+1,counter]; } list LeadDataFm=determine_coef(Fm); def LeadDataG=coef(G,xy); for (i=1; i<=ncols(LeadDataG); i++) { if (LeadDataG[1,i]==LeadDataFm[2]) { poly LeadG = LeadDataG[2,i]; // determine the coefficient of G i=ncols(LeadDataG)+1; } } G=LeadDataFm[1]*G-LeadG*Fm; // leading terms in y should cancel... coef_Mat = coef(G,xy); Jnew=coef_Mat[2,1..ncols(coef_Mat)]; // simplification of Jnew if (defined(artin_bd)) // the artin_bd-th power of the maxideal of // deformation parameters can be cutted off { Jnew=jet(Jnew,artin_bd-1); } Jnew=interred(Jnew); if (defined(artin_bd)) { Jnew=jet(Jnew,artin_bd-1); } J=J,Jnew; if (typ==1) // isEquising { if(ideal(nselect(J,1..no_b))<>0) { setring old_ring; option(set,ov); return(0); } } while (fertig<>soll and blowup1) { if (M[3][blowup-1,branch]==1 and ((B[blowup,branch]<>x and B[blowup,branch]<>y) or (blowup==nrows(M[3])) )) { fertig[branch]=1; dbprint(i_print,"// 1 branch finished"); } } if (branch<=upper_bound_old[branch] and fertig[branch]<>1) { for (i=branch;i>=1;i--) { if (M[1][blowup-1,i]<>0) { m=M[1][blowup-1,i]; // multiplicity before blowup i=0; } } // we blow up the branch and take the strict transform: attrib(J,"isSB",1); bl_Map(branch)=reduce(bl_Map(branch),J); attrib(J,"isSB",0); phi=myRing,bl_Map(branch); F(branch)=phi(F(branch))/x^m; // simplify F attrib(Jnew,"isSB",1); F(branch)=reduce(F(branch),Jnew); attrib(Jnew,"isSB",0); m=M[1][blowup,branch]; // multiplicity after blowup Fm=m_Jet(F(branch),m); // homogeneous part of lowest degree // we check for Fm=F[k]*...*F[k+s] where // // F[j]=(y-b'(j)*x)^m(j), respectively F[j]=(-b'(j)*y+x)^m(j) // // according to the entries m(j)= M[3][blowup,j] and // b'(j) mod m_A = B[blowup,j] // computed from the HNE of the special fibre of the family: G=1; counter=branch; k=upper_bound[branch]; F_save=F(branch); while(counter<=k) { F(counter)=m_Jet(F_save,maxDeg[blowup,counter]); if (B[blowup,counter]<>x and B[blowup,counter]<>y) { G=G*(y-(b(auxVar)+B[blowup,counter])*x)^(M[3][blowup,counter]); bl_Map(counter)=maxideal(1); bl_Map(counter)[nvars(basering)]= xy+(b(auxVar)+B[blowup,counter])*x; bNodes[counter]=b(auxVar); auxVar=auxVar+1; } else { if (B[blowup,counter]==x) { G=G*x^(M[3][blowup,counter]); // branch has tangent x !! F(counter)=swapXY(F(counter)); // will turn x to y for blow up bl_Map(counter)=maxideal(1); bl_Map(counter)[nvars(basering)]=xy; } else { G=G*y^(M[3][blowup,counter]); // tangent has to be y bl_Map(counter)=maxideal(1); bl_Map(counter)[nvars(basering)]=xy; } bNodes[counter]=0; } upper_bound[counter]=counter+M[2][blowup+1,counter]-1; counter=counter+M[2][blowup+1,counter]; } G=determine_coef(Fm)[1]*G-Fm; // leading terms in y should cancel coef_Mat = coef(G,xy); Jnew=coef_Mat[2,1..ncols(coef_Mat)]; if (defined(artin_bd)) // the artin_bd-th power of the maxideal of // deformation parameters can be cutted off { Jnew=jet(Jnew,artin_bd-1); } // simplification of J Jnew=interred(Jnew); J=J,Jnew; if (typ==1) // isEquising { if (defined(artin_bd)) { J=jet(Jnew,artin_bd-1); } if(ideal(nselect(J,1..no_b))<>0) { setring old_ring; option(set,ov); return(0); } } } } if (number_of_branches>=2) { J=interred(J); if (typ==1) // isEquising { if (defined(artin_bd)) { J=jet(Jnew,artin_bd-1); } if(ideal(nselect(J,1..no_b))<>0) { setring old_ring; option(set,ov); return(0); } } } } // Computation for all equimultiple sections being trivial (I^s(f)) ideal Jtriv=J; for (i=1;i<=no_b; i++) { if (reduce(b(i),std(bNodes))!=0){ Jtriv=subst(Jtriv,b(i),0); } } Jtriv=std(Jtriv); dbprint(i_print,"// "); dbprint(i_print,"// Elimination starts:"); dbprint(i_print,"// -------------------"); poly gg; int b_left=no_b; for (i=1;i<=no_b; i++) { attrib(J,"isSB",1); gg=reduce(b(i),J); if (gg==0) { b_left = b_left-1; // another b(i) has to be 0 } J = subst(J, b(i), gg); attrib(J,"isSB",0); } J=simplify(J,10); if (typ==1) // isEquising { if (defined(artin_bd)) { J=jet(Jnew,artin_bd-1); } if(ideal(nselect(J,1..no_b))<>0) { setring old_ring; option(set,ov); return(0); } } //new CL 11/06: check in which equations b(k) appears and remove those b(k) // which appear in exactly one of the equations (by removing this // equation) dbprint(i_print,"// "); dbprint(i_print,"// Remove superfluous equations:"); dbprint(i_print,"// -----------------------------"); int Z,App_in; ideal J_Tmp; int ncJ=ncols(J); intmat Mdet[ncJ][1]; for (Z=1;Z<=ncJ;Z++){ Mdet[Z,1]=Z; } for (i=1;i<=no_b; i++) { ideal b_appears_in(i); // Eintraege sind spaeter 1 oder 0 intmat b_app_in(i)[1][ncJ]; // Eintraege sind spaeter 1 oder 0 b_appears_in(i)[ncJ]=0; J_Tmp = matrix(J)-subst(J,b(i),0); for (Z=1; Z<=ncJ; Z++) { if (J_Tmp[Z]<>0) { // b(i) appear in J_Tmp[Z] b_appears_in(i)[Z]=1; b_app_in(i)[1,Z]=1; } } if (size(b_appears_in(i))==1) { //b(i) appears only in one J_Tmp[Z] App_in = (b_app_in(i)*Mdet)[1,1]; // determines Z J[App_in]=0; b_appears_in(i)[App_in]=0; b_app_in(i)[1,App_in]=0; } } for (i=1;i<=no_b; i++) { if (size(b_appears_in(i))==1) { //b(i) appears only in one J_Tmp[Z] App_in = (b_app_in(i)*Mdet)[1,1]; // determines Z J[App_in]=0; b_appears_in(i)[App_in]=0; b_app_in(i)[1,Z]=1; i=0; } } Jtriv = nselect(Jtriv,1..no_b); ideal J_no_b = nselect(J,1..no_b); if (size(J) > size(J_no_b)) { dbprint(i_print,"// std computation started"); // some b(i) didn't appear in linear conditions and have to be eliminated if (defined(artin_bd)) { // first we make the ring smaller (removing variables, which are // forced to 0 by J list LL=make_ring_small(J); ideal Shortmap=LL[2]; minPolyStr = ""; if (minpoly !=0) { minPolyStr = "minpoly = "+string(minpoly); } ordStr = "dp(" + string(b_left) + "),dp"; ideal qId = ideal(basering); helpStr = "ring Shortring = (" + charstr(basering) + "),("+ LL[1] +") , ("+ ordStr +");"; execute(helpStr); execute(minPolyStr); // ring has changed to "Shortring" ideal MM=maxideal(artin_bd); MM=subst(MM,x,0); MM=subst(MM,y,0); MM=simplify(MM,2); dbprint(i_print-1,"// maxideal("+string(artin_bd)+") has " +string(size(MM))+" elements"); dbprint(i_print-1,"//"); // we change to the qring mod m^artin_bd // first, we have to check if we were in a qring when starting ideal qId = imap(myRing, qId); if (size(qId) == 0) { attrib(MM,"isSB",1); qring QQ=MM; } else { qId=qId,MM; qring QQ = std(qId); } ideal Shortmap=imap(myRing,Shortmap); map phiphi=myRing,Shortmap; ideal J=phiphi(J); option(redSB); J=std(J); J=nselect(J,1..no_b); setring myRing; // back to "myRing" J=nselect(J,1..no_b); Jnew=imap(QQ,J); J=J,Jnew; J=interred(J); if (defined(artin_bd)){ J=jet(J,artin_bd-1); } } else { J=std(J); J=nselect(J,1..no_b); if (defined(artin_bd)){ J=jet(J,artin_bd-1); } } } dbprint(i_print,"// finished"); dbprint(i_print,"// "); minPolyStr = "";option(set,ov); if (minpoly !=0) { minPolyStr = "minpoly = "+string(minpoly); } kill HNEring; if (typ==1) // isEquising { if (defined(artin_bd)) { J=jet(Jnew,artin_bd-1); } if(J<>0) { setring old_ring; option(set,ov); return(0); } else { setring old_ring; option(set,ov); return(1); } } setring old_ring; // we are back in the original ring if (npars(myRing)<>0) { ideal qIdeal = ideal(basering); helpStr = "ring ESSring = (" + string(char(basering))+ "," + parstr(myRing) + ") , ("+ varstr(basering)+") , ("+ ordstr(basering) +");"; execute(helpStr); execute(minPolyStr); // basering has changed to ESSring ideal qIdeal = fetch(old_ring, qIdeal); if(qIdeal != 0) { def r_base = basering; kill ESSring; qring ESSring = std(qIdeal); } kill qIdeal; ideal SSS; for (int ii=1;ii<=nvars(basering);ii++) { SSS[ii+no_b]=var(ii); } map phi=myRing,SSS; // b(i) variables are mapped to zero ideal ES=phi(J); ideal ES_all_triv=phi(Jtriv); kill phi; if (defined(p_F)<=0) { poly p_F=fetch(old_ring,p_F); export(p_F); } export(ES); export(ES_all_triv); setring old_ring; dbprint(i_print+2," // 'esStratum' created a list M of a ring and an integer. // To access the ideal defining the equisingularity stratum, type: def ESSring = M[1]; setring ESSring; ES; "); option(set,ov); return(list(ESSring,0)); } else { // no new ring definition necessary ideal SSS; for (int ii=1;ii<=nvars(basering);ii++) { SSS[ii+no_b]=var(ii); } map phi=myRing,SSS; // b(i) variables are mapped to zero ideal ES=phi(J); ideal ES_all_triv=phi(Jtriv); kill phi; setring old_ring; dbprint(i_print,"// output of 'esStratum' is a list consisting of: // _[1][1] = ideal defining the equisingularity stratum // _[1][2] = ideal defining the part of the equisingularity stratum // where all equimultiple sections are trivial // _[2] = 0"); option(set,ov); return(list(list(ES,ES_all_triv),0)); } } //////////////////////////////////////////////////////////////////////////////// proc tau_es (poly f,list #) "USAGE: tau_es(f); f poly ASSUME: f is a reduced bivariate polynomial, the basering has precisely two variables, is local and no qring. RETURN: int, the codimension of the mu-const stratum in the semi-universal deformation base. NOTE: printlevel>=1 displays additional information. When called with any additional parameter, the computation of the Milnor number is avoided (no check for NND). SEE ALSO: esIdeal, tjurina, invariants EXAMPLE: example tau_es; shows an example. " { int i,j,k,s; int slope_x, slope_y, upper; int i_print = printlevel - voice + 3; string MinPolyStr; // some checks first if ( nvars(basering)<>2 ) { print("// basering has not the correct number (two) of variables !"); print("// computation stopped"); return(0); } if ( mult(std(1+var(1)+var(2))) <> 0) { print("// basering is not local !"); print("// computation stopped"); return(0); } if (mult(std(f))<=1) { // f is rigid return(0); } if ( deg(squarefree(f))!=deg(f) ) { print("// input polynomial was not reduced"); print("// try squarefree(f); first"); return(0); } def old_ring=basering; execute("ring @myRing=("+charstr(basering)+"),("+varstr(basering)+"),ds;"); poly f=imap(old_ring,f); ideal Jacobi_Id = jacob(f); // check for A_k singularity // ---------------------------------------- if (mult(std(f))==2) { dbprint(i_print-1,"// "); dbprint(i_print-1,"// polynomial defined A_k singularity"); dbprint(i_print-1,"// "); return( vdim(std(Jacobi_Id)) ); } // check for D_k singularity // ---------------------------------------- if (mult(std(f))==3 and size(factorize(jet(f,3))[1])>=3) { dbprint(i_print,"// "); dbprint(i_print,"// polynomial defined D_k singularity"); dbprint(i_print,"// "); ideal ES_Id = f, jacob(f); return( vdim(std(Jacobi_Id))); } if (size(#)==0) { // check if Newton polygon non-degenerate // ---------------------------------------- Jacobi_Id=std(Jacobi_Id); int mu = vdim(Jacobi_Id); poly f_tilde=f+var(1)^mu+var(2)^mu; //to obtain convenient Newton-polygon list NP=newtonpoly(f_tilde); dbprint(i_print-1,"// Newton polygon:"); dbprint(i_print-1,NP); dbprint(i_print-1,""); if(is_NND(f,mu,NP)) // f is Newton non-degenerate { upper=NP[1][2]; ideal ES_Id= x^k*y^upper; dbprint(i_print-1,"polynomial is Newton non-degenerate"); dbprint(i_print-1,""); k=0; for (i=1;i<=size(NP)-1;i++) { slope_x=NP[i+1][1]-NP[i][1]; slope_y=NP[i][2]-NP[i+1][2]; for (k=NP[i][1]+1; k<=NP[i+1][1]; k++) { while ( slope_x*upper + slope_y*k >= slope_x*NP[i][2] + slope_y*NP[i][1]) { upper=upper-1; } upper=upper+1; ES_Id=ES_Id, x^k*y^upper; } } ES_Id=std(ES_Id); dbprint(i_print-2,"ideal of monomials above Newton bd. is generated by:"); dbprint(i_print-2,ES_Id); ideal ESfix_Id = ES_Id, f, maxideal(1)*jacob(f); ES_Id = ES_Id, Jacobi_Id; ES_Id = std(ES_Id); dbprint(i_print-1,"// "); dbprint(i_print-1,"// Equisingularity ideal is computed!"); dbprint(i_print-1,""); return(vdim(ES_Id)); } else { dbprint(i_print-1,"polynomial is Newton degenerate !"); dbprint(i_print-1,""); } } // for Newton degenerate polynomials, we compute the HN expansion, and // count the number of free points ..... dbprint(i_print-1,"// "); dbprint(i_print-1,"// Compute HN expansion"); dbprint(i_print-1,"// ---------------------"); i=printlevel; printlevel=printlevel-5; if (2*size(coeffs(f,x))0) { typ=1; } // I^s is also computed int i,k,s; int slope_x, slope_y, upper; int i_print = printlevel - voice + 3; string MinPolyStr; // some checks first if ( nvars(basering)<>2 ) { print("// basering has not the correct number (two) of variables !"); print("// computation stopped"); return(list(0,0)); } if ( mult(std(1+var(1)+var(2))) <> 0) { print("// basering is not local !"); print("// computation stopped"); return(list(0,0)); } if (mult(std(f))<=1) { // f is rigid if (typ==0) { return(list(ideal(1),ideal(1))); } else { return(list(ideal(1),ideal(1),ideal(1))); } } if ( deg(squarefree(f))!=deg(f) ) { print("// input polynomial was not squarefree"); print("// try squarefree(f); first"); return(list(0,0)); } if (char(basering)<>0) { if (mult(std(f)) mod char(basering)==0) { print("// characteristic of ground field divides " + "multiplicity of polynomial !"); print("// computation stopped"); return(list(0,0)); } } // check for A_k singularity // ---------------------------------------- if (mult(std(f))==2) { dbprint(i_print,"// "); dbprint(i_print,"// polynomial defined A_k singularity"); dbprint(i_print,"// "); ideal ES_Id = f, jacob(f); ES_Id = interred(ES_Id); ideal ESfix_Id = f, maxideal(1)*jacob(f); ESfix_Id= interred(ESfix_Id); if (typ==0) // only for computation of I^es and I^es_fix { return( list(ES_Id,ESfix_Id) ); } else { return( list(ES_Id,ESfix_Id,ES_Id) ); } } // check for D_k singularity // ---------------------------------------- if (mult(std(f))==3 and size(factorize(jet(f,3))[1])>=3) { dbprint(i_print,"// "); dbprint(i_print,"// polynomial defined D_k singularity"); dbprint(i_print,"// "); ideal ES_Id = f, jacob(f); ES_Id = interred(ES_Id); ideal ESfix_Id = f, maxideal(1)*jacob(f); ESfix_Id= interred(ESfix_Id); if (typ==0) // only for computation of I^es and I^es_fix { return( list(ES_Id,ESfix_Id) ); } else { return( list(ES_Id,ESfix_Id,ES_Id) ); } } // check if Newton polygon non-degenerate // ---------------------------------------- int mu = milnor(f); poly f_tilde=f+var(1)^mu+var(2)^mu; //to obtain a convenient Newton-polygon list NP=newtonpoly(f_tilde); dbprint(i_print-1,"// Newton polygon:"); dbprint(i_print-1,NP); dbprint(i_print-1,""); if(is_NND(f,mu,NP)) // f is Newton non-degenerate { upper=NP[1][2]; ideal ES_Id= x^k*y^upper; dbprint(i_print,"polynomial is Newton non-degenerate"); dbprint(i_print,""); k=0; for (i=1;i<=size(NP)-1;i++) { slope_x=NP[i+1][1]-NP[i][1]; slope_y=NP[i][2]-NP[i+1][2]; for (k=NP[i][1]+1; k<=NP[i+1][1]; k++) { while ( slope_x*upper + slope_y*k >= slope_x*NP[i][2] + slope_y*NP[i][1]) { upper=upper-1; } upper=upper+1; ES_Id=ES_Id, x^k*y^upper; } } ES_Id=std(ES_Id); dbprint(i_print-1,"ideal of monomials above Newton bd. is generated by:"); dbprint(i_print-1,ES_Id); ideal ESfix_Id = ES_Id, f, maxideal(1)*jacob(f); ES_Id = ES_Id, f, jacob(f); dbprint(i_print,"// "); dbprint(i_print,"// equisingularity ideal is computed!"); if (typ==0) { return(list(ES_Id,ESfix_Id)); } else { return(list(ES_Id,ESfix_Id,ES_Id)); } } else { dbprint(i_print,"polynomial is Newton degenerate !"); dbprint(i_print,""); } def old_ring=basering; dbprint(i_print,"// "); dbprint(i_print,"// versal deformation with triv. section"); dbprint(i_print,"// ====================================="); dbprint(i_print,"// "); ideal JJ=maxideal(1)*jacob(f); ideal kbase_versal=kbase(std(JJ)); s=size(kbase_versal); string ring_versal="ring @Px = ("+charstr(basering)+"),(t(1.."+string(s)+")," +varstr(basering)+"),(ds("+string(s)+")," +ordstr(basering)+");"; MinPolyStr = string(minpoly); execute(ring_versal); if (MinPolyStr<>"0") { MinPolyStr = "minpoly="+MinPolyStr; execute(MinPolyStr); } // basering has changed to @Px poly F=imap(old_ring,f); ideal kbase_versal=imap(old_ring,kbase_versal); for (i=1; i<=s; i++) { F=F+var(i)*kbase_versal[i]; } dbprint(i_print-1,F); dbprint(i_print-1,""); ideal ES_Id,ES_Id_all_triv; poly Ftriv=F; dbprint(i_print,"// "); dbprint(i_print,"// Compute equisingularity Stratum over Spec(C[t]/t^2)"); dbprint(i_print,"// ==================================================="); dbprint(i_print,"// "); list M=esStratum(F,2); dbprint(i_print,"// finished"); dbprint(i_print,"// "); if (M[2]==1) // error occured during esStratum computation { print("Some error has occured during the computation"); return(list(0,0)); } if ( typeof(M[1])=="list" ) { int defpars = nvars(basering)-2; poly Fred,Ftrivred; poly g; F=reduce(F,std(M[1][1])); Ftriv=reduce(Ftriv,std(M[1][2])); for (i=1; i<=defpars; i++) { Fred=reduce(F,std(var(i))); Ftrivred=reduce(Ftriv,std(var(i))); g=subst(F-Fred,var(i),1); ES_Id=ES_Id, g; F=Fred; g=subst(Ftriv-Ftrivred,var(i),1); ES_Id_all_triv=ES_Id_all_triv, g; Ftriv=Ftrivred; } setring old_ring; // back to original ring ideal ES_Id = imap(@Px,ES_Id); ES_Id = interred(ES_Id); ideal ES_Id_all_triv = imap(@Px,ES_Id_all_triv); ES_Id_all_triv = interred(ES_Id_all_triv); ideal ESfix_Id = ES_Id, f, maxideal(1)*jacob(f); ES_Id = ES_Id, f, jacob(f); ES_Id_all_triv = ES_Id_all_triv, f, jacob(f); if (typ==0) { return(list(ES_Id,ESfix_Id)); } else { return(list(ES_Id,ESfix_Id,ES_Id_all_triv)); } } else { def AuxRing=M[1]; dbprint(i_print,"// "); dbprint(i_print,"// change ring to ESSring"); setring AuxRing; // contains p_F, ES int defpars = nvars(basering)-2; poly Fred,Fredtriv; poly g; ideal ES_Id,ES_Id_all_triv; poly p_Ftriv=p_F; p_F=reduce(p_F,std(ES)); p_Ftriv=reduce(p_Ftriv,std(ES_all_triv)); for (i=1; i<=defpars; i++) { Fred=reduce(p_F,std(var(i))); Fredtriv=reduce(p_Ftriv,std(var(i))); g=subst(p_F-Fred,var(i),1); ES_Id=ES_Id, g; p_F=Fred; g=subst(p_Ftriv-Fredtriv,var(i),1); ES_Id_all_triv=ES_Id_all_triv, g; p_Ftriv=Fredtriv; } dbprint(i_print,"// "); dbprint(i_print,"// back to the original ring"); setring old_ring; // back to original ring ideal ES_Id = imap(AuxRing,ES_Id); ES_Id = interred(ES_Id); ideal ES_Id_all_triv = imap(AuxRing,ES_Id_all_triv); ES_Id_all_triv = interred(ES_Id_all_triv); kill @Px; kill AuxRing; ideal ESfix_Id = ES_Id, f, maxideal(1)*jacob(f); ES_Id = ES_Id, f, jacob(f); ES_Id_all_triv = ES_Id_all_triv, f, jacob(f); dbprint(i_print,"// "); dbprint(i_print,"// equisingularity ideal is computed!"); if (typ==0) { return(list(ES_Id,ESfix_Id)); } else { return(list(ES_Id,ESfix_Id,ES_Id_all_triv)); } } } example { "EXAMPLE:"; echo=2; ring r=0,(x,y),ds; poly f=x7+y7+(x-y)^2*x2y2; list K=esIdeal(f); option(redSB); // Wahl's equisingularity ideal: std(K[1]); ring rr=0,(x,y),ds; poly f=x4+4x3y+6x2y2+4xy3+y4+2x2y15+4xy16+2y17+xy23+y24+y30+y31; list K=esIdeal(f); vdim(std(K[1])); // the latter should be equal to: tau_es(f); } /////////////////////////////////////////////////////////////////////////////// proc esStratum (poly p_F, list #) "USAGE: esStratum(F[,m,L]); F poly, m int, L list ASSUME: F defines a deformation of a reduced bivariate polynomial f and the characteristic of the basering does not divide mult(f). @* If nv is the number of variables of the basering, then the first nv-2 variables are the deformation parameters. @* If the basering is a qring, ideal(basering) must only depend on the deformation parameters. COMPUTE: equations for the stratum of equisingular deformations with fixed (trivial) section. RETURN: list l: either consisting of a list and an integer, where @format l[1][1]=ideal defining the equisingularity stratum l[1][2]=ideal defining the part of the equisingularity stratum where all equimultiple sections through the non-nodes of the reduced total transform are trivial sections l[2]=1 if some error has occured, l[2]=0 otherwise; @end format or consisting of a ring and an integer, where @format l[1]=ESSring is a ring extension of basering containing the ideal ES (describing the ES-stratum), the ideal ES_all_triv (describing the part with trival equimultiple sections) and the polynomial p_F=F, l[2]=1 if some error has occured, l[2]=0 otherwise. @end format NOTE: L is supposed to be the output of hnexpansion (with the given ordering of the variables appearing in f). @* If m is given, the ES Stratum over A/maxideal(m) is computed. @* This procedure uses @code{execute} or calls a procedure using @code{execute}. printlevel>=2 displays additional information. SEE ALSO: esIdeal, isEquising KEYWORDS: equisingularity stratum EXAMPLE: example esStratum; shows examples. " { list l=esComputation (0,p_F,#); return(l); } example { "EXAMPLE:"; echo=2; int p=printlevel; printlevel=1; ring r = 0,(a,b,c,d,e,f,g,x,y),ds; poly F = (x2+2xy+y2+x5)+ax+by+cx2+dxy+ey2+fx3+gx4; list M = esStratum(F); M[1][1]; printlevel=3; // displays additional information esStratum(F,2) ; // ES-stratum over Q[a,b,c,d,e,f,g] / ^2 ideal I = f-fa,e+b; qring q = std(I); poly F = imap(r,F); esStratum(F); printlevel=p; } /////////////////////////////////////////////////////////////////////////////// proc isEquising (poly p_F, list #) "USAGE: isEquising(F[,m,L]); F poly, m int, L list ASSUME: F defines a deformation of a reduced bivariate polynomial f and the characteristic of the basering does not divide mult(f). @* If nv is the number of variables of the basering, then the first nv-2 variables are the deformation parameters. @* If the basering is a qring, ideal(basering) must only depend on the deformation parameters. COMPUTE: tests if the given family is equisingular along the trivial section. RETURN: int: 1 if the family is equisingular, 0 otherwise. NOTE: L is supposed to be the output of hnexpansion (with the given ordering of the variables appearing in f). @* If m is given, the family is considered over A/maxideal(m). @* This procedure uses @code{execute} or calls a procedure using @code{execute}. printlevel>=2 displays additional information. EXAMPLE: example isEquising; shows examples. " { int check=esComputation (1,p_F,#); return(check); } example { "EXAMPLE:"; echo=2; ring r = 0,(a,b,x,y),ds; poly F = (x2+2xy+y2+x5)+ay3+bx5; isEquising(F); ideal I = ideal(a); qring q = std(I); poly F = imap(r,F); isEquising(F); ring rr=0,(A,B,C,x,y),ls; poly f=x7+y7+(x-y)^2*x2y2; poly F=f+A*y*diff(f,x)+B*x*diff(f,x); isEquising(F); isEquising(F,2); // computation over Q[a,b] / ^2 } /* Examples: LIB "equising.lib"; ring r = 0,(x,y),ds; poly p1 = y^2+x^3; poly p2 = p1^2+x5y; poly p3 = p2^2+x^10*p1; poly p=p3^2+x^20*p2; p; list L=versal(p); def Px=L[1]; setring Px; poly F=Fs[1,1]; int t=timer; list M=esStratum(F); timer-t; //-> 3 LIB "equising.lib"; option(prot); printlevel=2; ring r=0,(x,y),ds; poly f=(x-yx+y2)^2-(y+x)^31; list L=versal(f); def Px=L[1]; setring Px; poly F=Fs[1,1]; int t=timer; list M=esStratum(F); timer-t; //-> 233 LIB "equising.lib"; printlevel=2; option(prot); timer=1; ring r=0,(x,y),ls; poly f=(x4-y4)^2-x10; list L=versal(f); def Px=L[1]; setring Px; poly F=Fs[1,1]; int t=timer; list M=esStratum(F,3); timer-t; //-> 8 LIB "equising.lib"; printlevel=2; timer=1; ring rr=0,(x,y),ls; poly f=x7+y7+(x-y)^2*x2y2; list K=esIdeal(f); // tau_es vdim(std(K[1])); //-> 22 // tau_es_fix vdim(std(K[2])); //-> 24 LIB "equising.lib"; printlevel=2; timer=1; ring rr=0,(x,y),ls; poly f=x7+y7+(x-y)^2*x2y2+x2y4; // Newton non-deg. list K=esIdeal(f); // tau_es vdim(std(K[1])); //-> 21 // tau_es_fix vdim(std(K[2])); //-> 23 LIB "equising.lib"; ring r=0,(w,v),ds; poly f=w2-v199; list L=hnexpansion(f); list LL=versal(f); def Px=LL[1]; setring Px; list L=imap(r,L); poly F=Fs[1,1]; list M=esStratum(F,2,L); LIB "equising.lib"; printlevel=2; timer=1; ring rr=0,(A,B,C,x,y),ls; poly f=x7+y7+(x-y)^2*x2y2; poly F=f+A*y*diff(f,x)+B*x*diff(f,x)+C*diff(f,y); list M=esStratum(F,6); std(M[1][1]); // standard basis of equisingularity ideal LIB "equising.lib"; printlevel=2; timer=1; ring rr=0,(x,y),ls; poly f=x20+y7+(x-y)^2*x2y2+x2y4; // Newton non-degenerate list K=esIdeal(f); K; ring rr=0,(x,y),ls; poly f=x6y-3x4y4-x4y5+3x2y7-x4y6+2x2y8-y10+2x2y9-y11+x2y10-y12-y13; list K=esIdeal(f); list L=versal(f); def Px=L[1]; setring Px; poly F=Fs[1,1]; list M=esStratum(F,2); LIB "equising.lib"; ring R=0,(A,B,C,D,x,y),ds; poly f=x6y-3x4y4-x4y5+3x2y7-x4y6+2x2y8-y10+2x2y9-y11+x2y10-y12-y13; poly F=f+Ax9+Bx7y2+Cx9y+Dx8y2; list M=esStratum(F,2); LIB "equising.lib"; printlevel=2; ring rr=0,(x,y),ls; poly f=x6y-3x4y4-x4y5+3x2y7-x4y6+2x2y8-y10+2x2y9-y11+x2y10-y12-y13; list K=esIdeal(f); vdim(std(K[1])); //-> 51 tau_es(f); //-> 51 printlevel=3; f=f*(y-x2)*(y2-x3)*(x-y5); int t=timer; list L=esIdeal(f); vdim(std(L[1])); //-> 99 timer-t; //-> 42 t=timer; tau_es(f); //-> 99 timer-t; //-> 23 LIB "equising.lib"; printlevel=3; ring rr=0,(x,y),ds; poly f=x4+4x3y+6x2y2+4xy3+y4+2x2y15+4xy16+2y17+xy23+y24+y30+y31; list K=esIdeal(f); vdim(std(K[1])); //-> 68 tau_es(f); //-> 68 list L=versal(f); def Px=L[1]; setring Px; poly F=Fs[1,1]; list M=esStratum(F); timer-t; //-> 0 */ singular-4.0.3+ds/Singular/LIB/ffsolve.lib000066400000000000000000000657241266270727000203210ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////// version="version ffsolve.lib 4.0.0.0 Jun_2013 "; // $Id: 9064848ad4fde0b46f250803b95b27cab099b5f7 $ category="Symbolic-numerical solving"; info=" LIBRARY: ffsolve.lib multivariate equation solving over finite fields AUTHOR: Gergo Gyula Borus, borisz@borisz.net KEYWORDS: multivariate equations; finite field PROCEDURES: ffsolve(); finite field solving using heuristically chosen method PEsolve(); solve system of multivariate equations over finite field simplesolver(); solver using modified exhausting search GBsolve(); multivariate solver using Groebner-basis XLsolve(); multivariate polynomial solver using linearization ZZsolve(); solve system of multivariate equations over finite field "; LIB "presolve.lib"; LIB "general.lib"; LIB "ring.lib"; LIB "standard.lib"; LIB "matrix.lib"; //////////////////////////////////////////////////////////////////// proc ffsolve(ideal equations, list #) "USAGE: ffsolve(I[, L]); I ideal, L list of strings RETURN: list L, the common roots of I as ideal ASSUME: basering is a finite field of type (p^n,a) " { list solutions, lSolvers, tempsols; int i,j, k,n, R, found; ideal factors, linfacs; poly lp; // check assumptions if(npars(basering)>1) { ERROR("Basering must have at most one parameter"); } if(char(basering)==0) { ERROR("Basering must have finite characteristic"); } if(hasGFCoefficient(basering)) { ERROR("not implemented for Galois fields"); } if(size(#)) { if(size(#)==1 and typeof(#[1])=="list") { lSolvers = #[1]; } else { lSolvers = #; } } else { if(deg(equations) == 2) { lSolvers = "XLsolve", "PEsolve", "simplesolver", "GBsolve", "ZZsolve"; } else { lSolvers = "PEsolve", "simplesolver", "GBsolve", "ZZsolve", "XLsolve"; } if(deg(equations) == 1) { lSolvers = "GBsolve"; } } n = size(lSolvers); R = random(1, n*(3*n+1) div 2); string solver; for(i=1;i0) { factors=factorize(equations[i],1); for(j=1; j<=ncols(factors); j++) { if(deg(factors[j])==1) { linfacs[size(linfacs)+1] = factors[j]; } } if(deg(linfacs[1])>0) { found=1; break; } } } // if there is, collect its the linear factors if(found) { // substitute the root and call recursively ideal neweqs, invmapideal, ti; map invmap; for(k=1; k<=ncols(linfacs); k++) { lp = linfacs[k]; neweqs = reduce(equations, lp); intvec varexp = leadexp(lp); def original_ring = basering; def newRing = clonering(nvars(original_ring)-1); setring newRing; ideal mappingIdeal; j=1; for(i=1; i<=size(varexp); i++) { if(varexp[i]) { mappingIdeal[i] = 0; } else { mappingIdeal[i] = var(j); j++; } } map recmap = original_ring, mappingIdeal; list tsols = ffsolve(recmap(neweqs), lSolvers); if(size(tsols)==0) { tsols = list(ideal(1)); } setring original_ring; j=1; for(i=1;i<=size(varexp);i++) { if(varexp[i]==0) { invmapideal[j] = var(i); j++; } } invmap = newRing, invmapideal; tempsols = invmap(tsols); // combine the solutions for(j=1; j<=size(tempsols); j++) { ti = std(tempsols[j]+lp); if(deg(ti)>0) { solutions = insert(solutions,ti); } } } } else { execute("solutions="+solver+"(equations);") ; } return(solutions); } example { "EXAMPLE:";echo=2; ring R = (2,a),x(1..3),lp; minpoly=a2+a+1; ideal I; I[1]=x(1)^2*x(2)+(a)*x(1)*x(2)^2+(a+1); I[2]=x(1)^2*x(2)*x(3)^2+(a)*x(1); I[3]=(a+1)*x(1)*x(3)+(a+1)*x(1); ffsolve(I); } //////////////////////////////////////////////////////////////////// proc PEsolve(ideal L, list #) "USAGE: PEsolve(I[, i]); I ideal, i optional integer solve I (system of multivariate equations) over a finite field using an equvalence property when i is not given or set to 2, otherwise if i is set to 0 then check whether common roots exists RETURN: list if optional parameter is not given or set to 2, integer if optional is set to 0 ASSUME: basering is a finite field of type (p^n,a) NOTE: When the optional parameter is set to 0, speoff only checks if I has common roots, then return 1, otherwise return 0. " { int mode, i,j; list results, rs, start; poly g; // check assumptions if(npars(basering)>1) { ERROR("Basering must have at most one parameter"); } if(char(basering)==0) { ERROR("Basering must have finite characteristic"); } if(hasGFCoefficient(basering)) { ERROR("not implemented for Galois fields"); } if( size(#) > 0 ) { mode = #[1]; } else { mode = 2; } L = simplify(L,15); g = productOfEqs( L ); if(g == 0) { if(mode==0) { return(0); } return( list() ); } if(g == 1) { list vectors = every_vector(); for(j=1; j<=size(vectors); j++) { ideal res; for(i=1; i<=nvars(basering); i++) { res[i] = var(i)-vectors[j][i]; } results[size(results)+1] = std(res); } return( results ); } if( mode == 0 ) { return( 1 ); } else { for(i=1; i<=nvars(basering); i++) { start[i] = 0:order_of_extension(); } if( mode == 1) { results[size(results)+1] = melyseg(g, start); } else { while(1) { start = melyseg(g, start); if( size(start) > 0 ) { ideal res; for(i=1; i<=nvars(basering); i++) { res[i] = var(i)-vec2elm(start[i]); } results[size(results)+1] = std(res); start = increment(start); }else{ break; } } } } return(results); } example { "EXAMPLE:";echo=2; ring R = (2,a),x(1..3),lp; minpoly=a2+a+1; ideal I; I[1]=x(1)^2*x(2)+(a)*x(1)*x(2)^2+(a+1); I[2]=x(1)^2*x(2)*x(3)^2+(a)*x(1); I[3]=(a+1)*x(1)*x(3)+(a+1)*x(1); PEsolve(I); } //////////////////////////////////////////////////////////////////// proc simplesolver(ideal E) "USAGE: simplesolver(I); I ideal solve I (system of multivariate equations) over a finite field by exhausting search RETURN: list L, the common roots of I as ideal ASSUME: basering is a finite field of type (p^n,a) " { int i,j,k,t, correct; list solutions = list(std(ideal())); list partial_solutions; ideal partial_system, curr_sol, curr_sys, factors; poly univar_poly; E = E+defaultIdeal(); // check assumptions if(npars(basering)>1) { ERROR("Basering must have at most one parameter"); } if(char(basering)==0) { ERROR("Basering must have finite characteristic"); } if(hasGFCoefficient(basering)) { ERROR("not implemented for Galois fields"); } for(k=1; k<=nvars(basering); k++) { partial_solutions = list(); for(i=1; i<=size(solutions); i++) { partial_system = reduce(E, solutions[i]); for(j=1; j<=ncols(partial_system); j++) { if(univariate(partial_system[j])>0) { univar_poly = partial_system[j]; break; } } factors = factorize(univar_poly,1); for(j=1; j<=ncols(factors); j++) { if(deg(factors[j])==1) { curr_sol = std(solutions[i]+ideal(factors[j])); curr_sys = reduce(E, curr_sol); correct = 1; for(t=1; t<=ncols(curr_sys); t++) { if(deg(curr_sys[t])==0) { correct = 0; break; } } if(correct) { partial_solutions = insert(partial_solutions, curr_sol); } } } } solutions = partial_solutions; } return(solutions); } example { "EXAMPLE:";echo=2; ring R = (2,a),x(1..3),lp; minpoly=a2+a+1; ideal I; I[1]=x(1)^2*x(2)+(a)*x(1)*x(2)^2+(a+1); I[2]=x(1)^2*x(2)*x(3)^2+(a)*x(1); I[3]=(a+1)*x(1)*x(3)+(a+1)*x(1); simplesolver(I); } //////////////////////////////////////////////////////////////////// proc GBsolve(ideal equation_system) "USAGE: GBsolve(I); I ideal solve I (system of multivariate equations) over an extension of Z/p by Groebner basis methods RETURN: list L, the common roots of I as ideal ASSUME: basering is a finite field of type (p^n,a) " { int i,j, prop, newelement, number_new_vars; ideal ls; list results, slvbl, linsol, ctrl, new_sols, varinfo; ideal I, linear_solution, unsolved_part, univar_part, multivar_part, unsolved_vars; intvec unsolved_var_nums; string new_vars; // check assumptions if(npars(basering)>1) { ERROR("Basering must have at most one parameter"); } if(char(basering)==0) { ERROR("Basering must have finite characteristic"); } if(hasGFCoefficient(basering)) { ERROR("not implemented for Galois fields"); } def original_ring = basering; if(npars(basering)==1) { int prime_coeff_field=0; string minpolystr = "minpoly="+ get_minpoly_str(size(original_ring),parstr(original_ring,1))+";" ; } else { int prime_coeff_field=1; } option(redSB); equation_system = simplify(equation_system,15); ideal standard_basis = std(equation_system); list basis_factors = facstd(standard_basis); if( basis_factors[1][1] == 1) { return(results) }; for(i=1; i<= size(basis_factors); i++) { prop = 0; for(j=1; j<=size(basis_factors[i]); j++) { if( univariate(basis_factors[i][j])>0 and deg(basis_factors[i][j])>1) { prop =1; break; } } if(prop == 0) { ls = solvelinearpart( basis_factors[i] ); if(ncols(ls) == nvars(basering) ) { ctrl, newelement = add_if_new(ctrl, ls); if(newelement) { results = insert(results, ls); } } else { slvbl = insert(slvbl, list(basis_factors[i],ls) ); } } } if(size(slvbl)<>0) { for(int E = 1; E<= size(slvbl); E++) { I = slvbl[E][1]; linear_solution = slvbl[E][2]; attrib(I,"isSB",1); unsolved_part = reduce(I,linear_solution); univar_part = ideal(); multivar_part = ideal(); for(i=1; i<=ncols(I); i++) { if(univariate(I[i])>0) { univar_part = univar_part+I[i]; } else { multivar_part = multivar_part+I[i]; } } varinfo = varaibles(univar_part); unsolved_vars = varinfo[3]; unsolved_var_nums = varinfo[4]; number_new_vars = ncols(unsolved_vars); new_vars = "@y(1.."+string(number_new_vars)+")"; def R_new = changevar(new_vars, original_ring); setring R_new; if( !prime_coeff_field ) { execute(minpolystr); } ideal mapping_ideal; for(i=1; i<=size(unsolved_var_nums); i++) { mapping_ideal[unsolved_var_nums[i]] = var(i); } map F = original_ring, mapping_ideal; ideal I_new = F( multivar_part ); list sol_new; int unsolvable = 0; sol_new = simplesolver(I_new); if( size(sol_new) == 0) { unsolvable = 1; } setring original_ring; if(unsolvable) { list sol_old = list(); } else { map G = R_new, unsolved_vars; new_sols = G(sol_new); for(i=1; i<=size(new_sols); i++) { ideal sol = new_sols[i]+linear_solution; sol = std(sol); ctrl, newelement = add_if_new(ctrl, sol); if(newelement) { results = insert(results, sol); } kill sol; } } kill G; kill R_new; } } return( results ); } example { "EXAMPLE:";echo=2; ring R = (2,a),x(1..3),lp; minpoly=a2+a+1; ideal I; I[1]=x(1)^2*x(2)+(a)*x(1)*x(2)^2+(a+1); I[2]=x(1)^2*x(2)*x(3)^2+(a)*x(1); I[3]=(a+1)*x(1)*x(3)+(a+1)*x(1); GBsolve(I); } //////////////////////////////////////////////////////////////////// proc XLsolve(ideal I, list #) "USAGE: XLsolve(I[, d]); I ideal, d optional integer solve I (system of multivariate polynomials) with a variant of the linearization technique, multiplying the polynomials with monomials of degree at most d (default is 2) RETURN: list L of the common roots of I as ideals ASSUME: basering is a finite field of type (p^n,a)" { int i,j,k, D; int SD = deg(I); list solutions; if(size(#)) { if(typeof(#[1])=="int") { D = #[1]; } } else { D = 2; } list lMonomialsForMultiplying = monomialsOfDegreeAtMost(D+SD); int m = ncols(I); list extended_system; list mm; for(k=1; k<=size(lMonomialsForMultiplying)-SD; k++) { mm = lMonomialsForMultiplying[k]; for(i=1; i<=m; i++) { for(j=1; j<=size(mm); j++) { extended_system[size(extended_system)+1] = reduce(I[i]*mm[j], defaultIdeal()); } } } ideal new_system = I; for(i=1; i<=size(extended_system); i++) { new_system[m+i] = extended_system[i]; } ideal reduced_system = linearReduce( new_system, lMonomialsForMultiplying); solutions = simplesolver(reduced_system); return(solutions); } example { "EXAMPLE:";echo=2; ring R = (2,a),x(1..3),lp; minpoly=a2+a+1; ideal I; I[1]=(a)*x(1)^2+x(2)^2+(a+1); I[2]=(a)*x(1)^2+(a)*x(1)*x(3)+(a)*x(2)^2+1; I[3]=(a)*x(1)*x(3)+1; I[4]=x(1)^2+x(1)*x(3)+(a); XLsolve(I, 3); } //////////////////////////////////////////////////////////////////// proc ZZsolve(ideal I) "USAGE: ZZsolve(I); I ideal solve I (system of multivariate equations) over a finite field by mapping the polynomials to a single univariate polynomial over extension of the basering RETURN: list, the common roots of I as ideal ASSUME: basering is a finite field of type (p^n,a) " { int i, j, nv, numeqs,r,l,e; def original_ring = basering; // check assumptions if(npars(basering)>1) { ERROR("Basering must have at most one parameter"); } if(char(basering)==0) { ERROR("Basering must have finite characteristic"); } if(hasGFCoefficient(basering)) { ERROR("not implemented for Galois fields"); } nv = nvars(original_ring); numeqs = ncols(I); l = numeqs % nv; if( l == 0) { r = numeqs div nv; } else { r = (numeqs div nv) +1; } list list_of_equations; for(i=1; i<=r; i++) { list_of_equations[i] = ideal(); } for(i=0; i0 ) { univar_monoms = univar_monoms + list(monomials[j]); } else { mixed_monoms = mixed_monoms + list(monomials[j]); } } return(univar_monoms + mixed_monoms); } static proc melyseg(poly g, list start) { list gsub = g; int i = 1; while( start[1][1] <> char(basering) ) { gsub[i+1] = subst( gsub[i], var(i), vec2elm(start[i])); if( gsub[i+1] == 0 ) { list new = increment(start,i); for(int l=1; l<=size(start); l++) { if(start[l]<>new[l]) { i = l; break; } } start = new; } else { if(i == nvars(basering)) { return(start); }else{ i++; } } } return(list()); } static proc productOfEqs(ideal I) { //system("--no-warn", 1); ideal eqs = sort_ideal(I); int i,q; poly g = 1; q = size(basering); ideal I = defaultIdeal(); for(i=1; i<=size(eqs); i++) { if(g==0){return(g);} g = reduce(g*(eqs[i]^(q-1)-1), I); } return( g ); } static proc clonering(list #) { def original_ring = basering; int n = nvars(original_ring); int prime_field=npars(basering); if(prime_field) { string minpolystr = "minpoly="+ get_minpoly_str(size(original_ring),parstr(original_ring,1))+";" ; } if(size(#)) { int newvars = #[1]; } else { int newvars = nvars(original_ring); } string newvarstr = "v(1.."+string(newvars)+")"; def newring = changevar(newvarstr, original_ring); setring newring; if( prime_field ) { execute(minpolystr); } return(newring); } static proc defaultIdeal() { ideal I; for(int i=1; i<=nvars(basering); i++) { I[i] = var(i)^size(basering)-var(i); } return( std(I) ); } static proc order_of_extension() { int oe=1; list rl = ringlist(basering); if( size(rl[1]) <> 1) { oe = deg( subst(minpoly,par(1),var(1)) ); } return(oe); } static proc vec2elm(intvec v) { number g = 1; if(npars(basering) == 1) { g=par(1); } number e=0; int oe = size(v); for(int i=1; i<=oe; i++) { e = e+v[i]*g^(oe-i); } return(e); } static proc increment(list l, list #) { int c, i, j, oe; oe = order_of_extension(); c = char(basering); if( size(#) == 1 ) { i = #[1]; } else { i = size(l); } l[i] = nextVec(l[i]); while( l[i][1] == c && i>1 ) { l[i] = 0:oe; i--; l[i] = nextVec(l[i]); } if( i < size(l) ) { for(j=i+1; j<=size(l); j++) { l[j] = 0:oe; } } return(l); } static proc nextVec(intvec l) { int c, i, j; i = size(l); c = char(basering); l[i] = l[i] + 1; while( l[i] == c && i>1 ) { l[i] = 0; i--; l[i] = l[i] + 1; } return(l); } static proc every_vector() { list element, list_of_elements; for(int i=1; i<=nvars(basering); i++) { element[i] = 0:order_of_extension(); } while(size(list_of_elements) < size(basering)^nvars(basering)) { list_of_elements = list_of_elements + list(element); element = increment(element); } for(int i=1; i<=size(list_of_elements); i++) { for(int j=1; j<=size(list_of_elements[i]); j++) { list_of_elements[i][j] = vec2elm(list_of_elements[i][j]); } } return(list_of_elements); } static proc num2int(number a) { int N=0; if(order_of_extension() == 1) { N = int(a); if(N<0) { N = N + char(basering); } } else { ideal C = coeffs(subst(a,par(1),var(1)),var(1)); for(int i=1; i<=ncols(C); i++) { int c = int(C[i]); if(c<0) { c = c + char(basering); } N = N + c*char(basering)^(i-1); } } return(N); } static proc get_minpoly_str(int size_of_ring, string parname) { def original_ring = basering; ring new_ring = (size_of_ring, A),x,lp; string S = string(minpoly); string SMP; if(S=="0") { SMP = SMP+parname; } else { for(int i=1; i<=size(S); i++) { if(S[i]=="A") { SMP = SMP+parname; } else { SMP = SMP+S[i]; } } } return(SMP); } static proc sort_ideal(ideal I) { ideal OI; int i,j,M; poly P; M = ncols(I); OI = I; for(i=2; i<=M; i++) { j=i; while(size(OI[j-1])>size(OI[j])) { P = OI[j-1]; OI[j-1] = OI[j]; OI[j] = P; j--; if(j==1) break; } } return(OI); } static proc add_if_new(list L, ideal I) { int i, newelement; poly P; I=std(I); for(i=1; i<=nvars(basering); i++) { P = P + reduce(var(i),I)*var(1)^(i-1); } newelement=1; for(i=1; i<=size(L); i++) { if(L[i]==P) { newelement=0; break; } } if(newelement) { L = insert(L, P); } return(L,newelement); } static proc Z_get_minpoly(int size_of_ring, string parname) { def original_ring = basering; ring new_ring = (size_of_ring, A),x,lp; string S = string(minpoly); string SMP; if(S=="0") { SMP = SMP+parname; } else { for(int i=1; i<=size(S); i++) { if(S[i]=="A") { SMP = SMP+parname; } else { SMP = SMP+S[i]; } } } return(SMP); } static proc Z_phi(ideal I) { poly f; for(int i=1; i<= ncols(I); i++) { f = f+I[i]*@y^(i-1); } return(f); } static proc Z_default_ideal(int number_of_variables, int q) { ideal DI; for(int i=1; i<=number_of_variables; i++) { DI[i] = var(i)^q-var(i); } return(std(DI)); } singular-4.0.3+ds/Singular/LIB/findifs.lib000066400000000000000000000442261266270727000202710ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version findifs.lib 4.0.0.0 Jun_2013 "; // $Id: d56248604e0535012373faef7e0ad53393269302 $ category="System and Control Theory"; info=" LIBRARY: findifs.lib Tools for the finite difference schemes AUTHORS: Viktor Levandovskyy, levandov@math.rwth-aachen.de OVERVIEW: We provide the presentation of difference operators in a polynomial, semi-factorized and a nodal form. Running @code{findifs_example();} will demonstrate, how we generate finite difference schemes of linear PDEs from given approximations. Theory: The method we use have been developed by V. Levandovskyy and Bernd Martin. The computation of a finite difference scheme of a given single linear partial differential equation with constant coefficients with a given approximation rules boils down to the computation of a Groebner basis of a submodule of a free module with respect to the ordering, eliminating module components. Support: SpezialForschungsBereich F1301 of the Austrian FWF PROCEDURES: findifs_example(); containes a guided explanation of our approach decoef(P,n); decompose polynomial P into summands with respect to the number n difpoly2tex(S,P[,Q]); present the difference scheme in the nodal form exp2pt(P[,L]); convert a polynomial M into the TeX format, in nodal form texcoef(n); converts the number n into TeX npar(n); search for 'n' among the parameters and returns its number magnitude(P); compute the square of the magnitude of a complex expression replace(s,what,with); replace in s all the substrings with a given string xchange(w,a,b); exchange two substrings in a given string SEE ALSO: latex_lib, finitediff_lib "; LIB "latex.lib"; LIB "poly.lib"; proc tst_findif() { example decoef; example difpoly2tex; example exp2pt; example texcoef; example npar; example magnitude; example replace; example xchange; } // static procs: // par2tex(s); convert special characters to TeX in s // mon2pt(P[,L]); convert a monomial M into the TeX format, in nodal form // 1. GLOBAL ASSUME: in the ring we have first Tx, then Tt: [FIXED, not needed anymore]! // 2. map vars other than Tx,Tt to parameters instead or just ignore them [?] // 3. clear the things with brackets // 4. todo: content resp lcmZ, gcdZ proc xchange(string where, string a, string b) "USAGE: xchange(w,a,b); w,a,b strings RETURN: string PURPOSE: exchanges substring 'a' with a substring 'b' in the string w NOTE: EXAMPLE: example xchange; shows examples "{ // replaces a<->b in where // assume they are of the same size [? seems to work] string s = "H"; string t; t = replace(where,a,s); t = replace(t,b,a); t = replace(t,s,b); return(t); } example { " EXAMPLE:"; echo=2; ring r = (0,dt,dh,A),Tt,dp; poly p = (Tt*dt+dh+1)^2+2*A; string s = texpoly("",p); s; string t = xchange(s,"dh","dt"); t; } static proc par2tex(string s) "USAGE: par2tex(s); s a string RETURN: string PURPOSE: converts special characters to TeX in s NOTE: the convention is the following: 'Tx' goes to 'T_x', 'dx' to '\\tri x' (the same for dt, dy, dz), 'theta', 'ro', 'A', 'V' are converted to greek letters. EXAMPLE: example par2tex; shows examples "{ // can be done with the help of latex_lib // s is a tex string with a poly // replace theta with \theta // A with \lambda // dt with \tri t // dh with \tri h // Tx with T_x, Ty with T_y // Tt with T_t // V with \nu // ro with \rho // dx with \tri x // dy with \tri y string t = s; t = replace(t,"Tt","T_t"); t = replace(t,"Tx","T_x"); t = replace(t,"Ty","T_y"); t = replace(t,"dt","\\tri t"); t = replace(t,"dh","\\tri h"); t = replace(t,"dx","\\tri x"); t = replace(t,"dy","\\tri y"); t = replace(t,"theta","\\theta"); t = replace(t,"A","\\lambda"); t = replace(t,"V","\\nu"); t = replace(t,"ro","\\rho"); return(t); } example { " EXAMPLE:"; echo=2; ring r = (0,dt,theta,A),Tt,dp; poly p = (Tt*dt+theta+1)^2+2*A; string s = texfactorize("",p); s; par2tex(s); string T = texfactorize("",p*(-theta*A)); par2tex(T); } proc replace(string s, string what, string with) "USAGE: replace(s,what,with); s,what,with strings RETURN: string PURPOSE: replaces in 's' all the substrings 'what' with substring 'with' NOTE: EXAMPLE: example replace; shows examples "{ // clear: replace in s, "what" with "with" int ss = size(s); int cn = find(s,what); if ( (cn==0) || (cn>ss)) { return(s); } int gn = 0; // global counter int sw = size(what); int swith = size(with); string out=""; string tmp; gn = 0; while(cn!=0) { // "cn:"; cn; // "gn"; gn; tmp = ""; if (cn>gn) { tmp = s[gn..cn-1]; } // "tmp:";tmp; // out = out+tmp+" "+with; out = out+tmp+with; // "out:";out; gn = cn + sw; if (gn>ss) { // ( (gn>ss) || ((sw>1) && (gn >= ss)) ) // no need to append smth return(out); } // if (gn == ss) // { // } cn = find(s,what,gn); } // and now, append the rest of s // out = out + " "+ s[gn..ss]; out = out + s[gn..ss]; return(out); } example { " EXAMPLE:"; echo=2; ring r = (0,dt,theta),Tt,dp; poly p = (Tt*dt+theta+1)^2+2; string s = texfactorize("",p); s; s = replace(s,"Tt","T_t"); s; s = replace(s,"dt","\\tri t"); s; s = replace(s,"theta","\\theta"); s; } proc exp2pt(poly P, list #) "USAGE: exp2pt(P[,L]); P poly, L an optional list of strings RETURN: string PURPOSE: convert a polynomial M into the TeX format, in nodal form ASSUME: coefficients must not be fractional NOTE: an optional list L contains a string, which will replace the default value 'u' for the discretized function EXAMPLE: example exp2pt; shows examples "{ // given poly in vars [now Tx,Tt are fixed], // create Tex expression for points of lattice // coeffs must not be fractional string varnm = "u"; if (size(#) > 0) { if (typeof(#[1])=="string") { varnm = string(#[1]); } } // varnm; string rz,mz; while (P!=0) { mz = mon2pt(P,varnm); if (mz[1]=="-") { rz = rz+mz; } else { rz = rz + "+" + mz; } P = P-lead(P); } rz = rz[2..size(rz)]; return(rz); } example { " EXAMPLE:"; echo=2; ring r = (0,dh,dt),(Tx,Tt),dp; poly M = (4*dh*Tx^2+1)*(Tt-1)^2; print(exp2pt(M)); print(exp2pt(M,"F")); } static proc mon2pt(poly M, string V) "USAGE: mon2pt(M,V); M poly, V a string RETURN: string PURPOSE: convert a monomial M into the TeX format, nodal form EXAMPLE: example mon2pt; shows examples "{ // searches for Tx, then Tt // monomial to the lattice point conversion // c*X^a*Y^b --> c*U^{n+a}_{j+b} number cM = leadcoef(M); intvec e = leadexp(M); // int a = e[2]; // convention: first Tx, then Tt // int b = e[1]; int i; int a , b, c = 0,0,0; int ia,ib,ic = 0,0,0; int nv = nvars(basering); string s; for (i=1; i<=nv ; i++) { s = string(var(i)); if (s=="Tt") { a = e[i]; ia = i;} if (s=="Tx") { b = e[i]; ib = i;} if (s=="Ty") { c = e[i]; ic = i;} } // if (ia==0) {"Error:Tt not found!"; return("");} // if (ib==0) {"Error:Tx not found!"; return("");} // if (ic==0) {"Error:Ty not found!"; return("");} // string tc = texobj("",c); // why not texpoly? string tc = texcoef(cM); string rs; if (cM==-1) { rs = "-"; } if (cM^2 != 1) { // we don't need 1 or -1 as coeffs // rs = clTex(tc)+" "; // rs = par2tex(rmDol(tc))+" "; rs = par2tex(tc)+" "; } // a = 0 or b = 0 rs = rs + V +"^{n"; if (a!=0) { rs = rs +"+"+string(a); } rs = rs +"}_{j"; if (b!=0) { rs = rs +"+"+string(b); } if (c!=0) { rs = rs + ",k+"; rs = rs + string(c); } rs = rs +"}"; return(rs); } example { "EXAMPLE:"; echo=2; ring r = (0,dh,dt),(Tx,Tt),dp; poly M = (4*dh^2-dt)*Tx^3*Tt; print(mon2pt(M,"u")); poly N = ((dh-dt)/(dh+dt))*Tx^2*Tt^2; print(mon2pt(N,"f")); ring r2 = (0,dh,dt),(Tx,Ty,Tt),dp; poly M = (4*dh^2-dt)*Tx^3*Ty^2*Tt; print(mon2pt(M,"u")); } proc npar(number n) "USAGE: npar(n); n a number RETURN: int PURPOSE: searches for 'n' among the parameters and returns its number EXAMPLE: example npar; shows examples "{ // searches for n amongst parameters // and returns its number int i,j=0,0; list L = ringlist(basering); list M = L[1][2]; // pars string sn = string(n); sn = sn[2..size(sn)-1]; for (i=1; i<=size(M);i++) { if (M[i] == sn) { j = i; } } if (j==0) { "Incorrect parameter"; } return(j); } example { "EXAMPLE:"; echo=2; ring r = (0,dh,dt,theta,A),t,dp; npar(dh); number T = theta; npar(T); npar(dh^2); } proc decoef(poly P, number n) "USAGE: decoef(P,n); P a poly, n a number RETURN: ideal PURPOSE: decompose polynomial P into summands with respect to the presence of the number n in the coefficients NOTE: n is usually a parameter with no power EXAMPLE: example decoef; shows examples "{ // decomposes polynomial into summands // w.r.t. the presence of a number n in coeffs // returns ideal def br = basering; int i,j=0,0; int pos = npar(n); if ((pos==0) || (P==0)) { return(0); } pos = pos + nvars(basering); // map all pars except to vars, provided no things are in denominator number con = content(P); con = numerator(con); P = cleardenom(P); //destroys content! P = con*P; // restore the numerator part of the content list M = ringlist(basering); list L = M[1..4]; list Pars = L[1][2]; list Vars = L[2] + Pars; L[1] = L[1][1]; // characteristic L[2] = Vars; // for non-comm things: don't need nc but graded algebra // list templ; // L[5] = templ; // L[6] = templ; def @R = ring(L); setring @R; poly P = imap(br,P); poly P0 = subst(P,var(pos),0); poly P1 = P - P0; ideal I = P0,P1; setring br; ideal I = imap(@R,I); kill @R; // check: P0+P1==P poly Q = I[1]+I[2]; if (P!=Q) { "Warning: problem in decoef"; } return(I); // substract the pure part from orig and check if n is remained there } example { " EXAMPLE:"; echo=2; ring r = (0,dh,dt),(Tx,Tt),dp; poly P = (4*dh^2-dt)*Tx^3*Tt + dt*dh*Tt^2 + dh*Tt; decoef(P,dt); decoef(P,dh); } proc texcoef(number n) "USAGE: texcoef(n); n a number RETURN: string PURPOSE: converts the number n into TeX format NOTE: if n is a polynomial, texcoef adds extra brackets and performs some space substitutions EXAMPLE: example texcoef; shows examples "{ // makes tex from n // and uses substitutions // if n is a polynomial, adds brackets number D = denominator(n); int DenIsOne = 0; if ( D==number(1) ) { DenIsOne = 1; } string sd = texpoly("",D); sd = rmDol(sd); sd = par2tex(sd); number N = numerator(n); string sn = texpoly("",N); sn = rmDol(sn); sn = par2tex(sn); string sout=""; int i; int NisPoly = 0; if (DenIsOne) { sout = sn; for(i=1; i<=size(sout); i++) { if ( (sout[i]=="+") || (sout[i]=="-") ) { NisPoly = 1; } } if (NisPoly) { sout = "("+sout+")"; } } else { sout = "\\frac{"+sn+"}{"+sd+"}"; } return(sout); } example { " EXAMPLE:"; echo=2; ring r = (0,dh,dt),(Tx,Tt),dp; number n1,n2,n3 = dt/(4*dh^2-dt),(dt+dh)^2, 1/dh; n1; texcoef(n1); n2; texcoef(n2); n3; texcoef(n3); } static proc rmDol(string s) { // removes $s and _no_ (s on appearance int i = size(s); if (s[1] == "$") { s = s[2..i]; i--;} if (s[1] == "(") { s = s[2..i]; i--;} if (s[i] == "$") { s = s[1..i-1]; i--;} if (s[i] == ")") { s = s[1..i-1];} return(s); } proc difpoly2tex(ideal S, list P, list #) "USAGE: difpoly2tex(S,P[,Q]); S an ideal, P and optional Q are lists RETURN: string PURPOSE: present the difference scheme in the nodal form ASSUME: ideal S is the result of @code{decoef} procedure NOTE: a list P may be empty or may contain parameters, which will not appear in denominators @* an optional list Q represents the part of the scheme, depending on other function, than the major part EXAMPLE: example difpoly2tex; shows examples " { // S = sum s_i = orig diff poly or // the result of decoef // P = list of pars (numbers) not to be divided with, may be empty // # is an optional list of polys, repr. the part dep. on "f", not on "u" // S = simplify(S,2); // destroys the leadcoef // rescan S and remove 0s from it int i; ideal T; int ss = ncols(S); int j=1; for(i=1; i<=ss; i++) { if (S[i]!=0) { T[j]=S[i]; j++; } } S = T; ss = j-1; int GotF = 1; list F; if (size(#)>0) { F = #; if ( (size(F)==1) && (F[1]==0) ) { GotF = 0; } } else { GotF = 0; } int sf = size(F); ideal SC; int sp = size(P); intvec np; int GotP = 1; if (sp==0) { GotP = 0; } if (sp==1) { if (P[1]==0) { GotP = 0; } } if (GotP) { for (i=1; i<=sp; i++) { np[i] = npar(P[i])+ nvars(basering); } } for (i=1; i<=ss; i++) { SC[i] = leadcoef(S[i]); } if (GotF) { for (i=1; i<=sf; i++) { SC[ss+i] = leadcoef(F[i]); } } def br = basering; // map all pars except to vars, provided no things are in denominator list M = ringlist(basering); list L = M[1..4]; // erase nc part list Pars = L[1][2]; list Vars = L[2] + Pars; L[1] = L[1][1]; // characteristic L[2] = Vars; def @R = ring(L); setring @R; ideal SC = imap(br,SC); if (GotP) { for (i=1; i<=sp; i++) { SC = subst(SC,var(np[i]),1); } } poly q=1; q = lcm(q,SC); setring br; poly q = imap(@R,q); number lq = leadcoef(q); // lq; number tmp; string sout=""; string vname = "u"; for (i=1; i<=ss; i++) { tmp = leadcoef(S[i]); S[i] = S[i]/tmp; tmp = tmp/lq; sout = sout +"+ "+texcoef(tmp)+"\\cdot ("+exp2pt(S[i])+")"; } if (GotF) { vname = "p"; //"f"; for (i=1; i<=sf; i++) { tmp = leadcoef(F[i]); F[i] = F[i]/tmp; tmp = tmp/lq; sout = sout +"+ "+texcoef(tmp)+"\\cdot ("+exp2pt(F[i],vname)+")"; } } sout = sout[3..size(sout)]; //rm first + return(sout); } example { "EXAMPLE:"; echo=2; ring r = (0,dh,dt,V),(Tx,Tt),dp; poly M = (4*dh*Tx+dt)^2*(Tt-1) + V*Tt*Tx; ideal I = decoef(M,dt); list L; L[1] = V; difpoly2tex(I,L); poly G = V*dh^2*(Tt-Tx)^2; difpoly2tex(I,L,G); } proc magnitude(poly P) "USAGE: magnitude(P); P a poly RETURN: poly PURPOSE: compute the square of the magnitude of a complex expression ASSUME: i is the variable of a basering EXAMPLE: example magnitude; shows examples " { // check whether i is present among the vars list L = ringlist(basering)[2]; // vars int j; int cnt = 0; for(j=size(L);j>0;j--) { if (L[j] == "i") { cnt = 1; break; } } if (!cnt) { ERROR("a variable called i is expected in basering"); } // i is present, check that i^2+1=0; // if (NF(i^2+1,std(0)) != 0) // { // "Warning: i^2+1=0 does not hold. Reduce the output manually"; // } poly re = subst(P,i,0); poly im = (P - re)/i; return(re^2+im^2); } example { "EXAMPLE:"; echo=2; ring r = (0,d),(g,i,sin,cos),dp; poly P = d*i*sin - g*cos +d^2*i; NF( magnitude(P), std(i^2+1) ); } static proc clTex(string s) // removes beginning and ending $'s { string t; if (size(s)>2) { // why -3? t = s[2..(size(s)-3)]; } return(t); } static proc simfrac(poly up, poly down) { // simplifies a fraction up/down // into the form up/down = RT[1] + RT[2]/down list LL = division(up,down); list RT; RT[1] = LL[1][1,1]; // integer part RT[2] = L[2][1]; // new numerator return(RT); } proc findifs_example() "USAGE: findifs_example(); RETURN: nothing (demo) PURPOSE: demonstration of our approach and this library EXAMPLE: example findifs_example; shows examples " { "* Equation: u_tt - A^2 u_xx -B^2 u_yy = 0; A,B are constants"; "* we employ three central differences"; "* the vector we act on is (u_xx, u_yy, u_tt, u)^T"; "* Set up the ring: "; "ring r = (0,A,B,dt,dx,dy),(Tx,Ty,Tt),(c,dp);"; ring r = (0,A,B,dt,dx,dy),(Tx,Ty,Tt),(c,dp); "* Set up the matrix with equation and approximations: "; "matrix M[4][4] ="; " // direct equation:"; " -A^2, -B^2, 1, 0,"; " // central difference u_tt"; " 0, 0, -dt^2*Tt, (Tt-1)^2,"; " // central difference u_xx"; " -dx^2*Tx, 0, 0, (Tx-1)^2,"; " // central difference u_yy"; " 0, -dy^2*Ty, 0, (Ty-1)^2;"; matrix M[4][4] = // direct equation: -A^2, -B^2, 1, 0, // central difference u_tt 0, 0, -dt^2*Tt, (Tt-1)^2, // central difference u_xx -dx^2*Tx, 0, 0, (Tx-1)^2, // central difference u_yy 0, -dy^2*Ty, 0, (Ty-1)^2; //========================================= // CHECK THE CORRECTNESS OF EQUATIONS AS INPUT: ring rX = (0,A,B,dt,dx,dy,Tx,Ty,Tt),(Uxx, Uyy,Utt, U),(c,Dp); matrix M = imap(r,M); vector X = [Uxx, Uyy, Utt, U]; "* Print the differential form of equations: "; print(M*X); // END CHECK //========================================= setring r; "* Perform the elimination of module components:"; " module R = transpose(M);"; " module S = std(R);"; module R = transpose(M); module S = std(R); " * See the result of Groebner bases: generators are columns"; " print(S);"; print(S); " * So, only the first column has its nonzero element in the last component"; " * Hence, this polynomial is the scheme"; " poly p = S[4,1];" ; poly p = S[4,1]; // by elimination of module components " print(p); "; print(p); list L; L[1]=A;L[2] = B; ideal I = decoef(p,dt); // make splitting w.r.t. the appearance of dt "* Create the nodal of the scheme in TeX format: "; " ideal I = decoef(p,dt);"; " difpoly2tex(I,L);"; difpoly2tex(I,L); // the nodal form of the scheme in TeX "* Preparations for the semi-factorized form: "; poly pi1 = subst(I[2],B,0); poly pi2 = I[2] - pi1; " poly pi1 = subst(I[2],B,0);"; " poly pi2 = I[2] - pi1;"; "* Show the semi-factorized form of the scheme: 1st summand"; " factorize(I[1]); "; factorize(I[1]); // semi-factorized form of the scheme: 1st summand "* Show the semi-factorized form of the scheme: 2nd summand"; " factorize(pi1);"; factorize(pi1); // semi-factorized form of the scheme: 2nd summand "* Show the semi-factorized form of the scheme: 3rd summand"; " factorize(pi1);"; factorize(pi2); // semi-factorized form of the scheme: 3rd summand } example { "EXAMPLE:"; echo=1; findifs_example(); } singular-4.0.3+ds/Singular/LIB/finitediff.lib000066400000000000000000001222671266270727000207600ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version finitediff.lib 4.0.0.0 Jun_2013 "; // $Id: ed2686c3ffb984de38bf8e376c5e1ec8c5b5ec4b $ category="Teaching"; info=" LIBRARY: finitediff.lib procedures to compute finite difference schemes for linear differential equations AUTHOR: Christian Dingler OVERVIEW: @texinfo Using @code{qepcad}/@code{qepcadsystem} from this library requires the program @code{qepcad} to be installed. You can download @code{qepcad} from @uref{http://www.usna.edu/Users/cs/qepcad/INSTALL/IQ.html} @end texinfo PROCEDURES: visualize(f); shows a scheme in index-notation u(D[,#]); gives some vector; depends on @derivatives scheme([v1,..,vn]); computes the finite difference scheme defined by v1,..,vn laxfrT(Ut,U,space); Lax-Friedrich-approximation for the time-direction laxfrX(Ux,U,space); Lax-Friedrich-approximation for the space-direction forward(U1,U2,VAR); forward-approximation backward(U1,U2,VAR); backward-approximation central1st(U1,U2,VAR); central-approximation of first order central2nd(U1,U2,VAR); central-approximation of second order trapezoid(U1,U2,VAR); trapezoid-approximation midpoint(U1,U2,VAR); midpoint-approximation pyramid(U1,U2,VAR); pyramid-approximation setinitials(variable,der[,#]); constructs and sets the basering for further computations errormap(f); performs the Fouriertransformation of a poly matrixsystem(M,A); gives the scheme of a pde-system as one matrix timestep(M); gives the several timelevels of a scheme derived from a pde-system fouriersystem(M,A); performs the Fouriertransformation of a matrix scheme PartitionVar(f,n); partitions a poly into the var(n)-part and the rest ComplexValue(f); computes the complex value of f, var(1) being the imaginary unit VarToPar(f); substitute var(i) by par(i) ParToVar(f); substitute par(i) by var(i) qepcad(f); ask QEPCAD for equivalent constraints to f<1 qepcadsystem(l); ask QEPCAD for equivalent constraints to all eigenvals of some matrices being <1 "; LIB "ring.lib"; LIB "general.lib"; LIB "standard.lib"; LIB "linalg.lib"; LIB "matrix.lib"; LIB "poly.lib"; LIB "teachstd.lib"; LIB "qhmoduli.lib"; /////////////////////////////////////////////////////////////////////// static proc getit(module M) { int nderiv=pos(U,@derivatives); def M2=groebner(M); module N1=gen(nderiv); def N2=intersect(M2,N1); def S=N2[1][nderiv]; return(S); } /////////////////////////////////////////////////////////////////////// proc visualize(poly f) "USAGE: visualize(f); f of type poly. RETURN: type string; translates the polynomial form of a finite difference scheme into an indexed one as often seen in literature EXAMPLE: example visualize; shows an example " { def n=size(f); string str; intvec v; if (n>0) { int i; int j; for(i=1;i<=n;i++) { intvec w=leadexp(f); for(j=1;j<=size(@variables);j++) { v[j]=w[j+1]; } if(i==1) { str=print(leadcoef(f),"%s")+"*"+"U("+print(v,"%s")+")"; } else { str=str+"+"+print(leadcoef(f),"%s")+"*"+"U("+print(v,"%s")+")"; } kill w; f=f-lead(f); } } return(str); } example { "EXAMPLE:";echo=2; list D="Ux","Ut","U"; list P="a"; list V="t","x"; setinitials(V,D,P); scheme(u(Ut)+a*u(Ux),trapezoid(Ux,U,x),backward(Ut,U,t)); visualize(_); } /////////////////////////////////// static proc imageideal() { def n=size(@variables)-1; ideal IDEAL=var(1),var(2); int j; for(j=1;j<=n;j++) { ideal II=var(2+j+n)+var(1)*var(2+2*n+j); IDEAL=IDEAL+II; kill II; } return(IDEAL); } ///////////////////////////////////// proc u(string D,list #) "USAGE: u(D[,#]); D a string that occurs in the list of @derivatives, # an optional list of integers. RETURN: type vector; gives the vector, that corresponds with gen(n)*m, where m is the monomial defined by # EXAMPLE: example u; shows an example " { def n=size(#); def nv=nvars(basering)-1; int nn; if(nv<=n) { nn=nv; } else { nn=n; } int index=pos(D,@derivatives); poly g=1; if(nn>=1) { int j; for(j=1;j<=nn;j++) { int nnn; nnn=int(#[j]); g=var(1+j)**nnn*g; kill nnn; } return(gen(index)*g); } else { return(gen(index)*g); } } example { "EXAMPLE:";echo=2; list D="Ux","Uy","Ut","U"; list P="a","b"; list V="t","x","y"; setinitials(V,D,P); u(Ux); u(Ux,2,3,7); u(Uy)+u(Ut)-u(Ux); u(U)*234-dx*dt*dy*3*u(Uy); } ///////////////////////////////////////////////////////// static proc pos(string D,list L) { int j; int index=-1; def n=size(L); for(j=1;j<=n;j++) { if(D==L[j]) { index=j; } } return(index); } /////////////////////////////////// static proc re(list L) { def n=size(L); int j; for(j=1;j<=n;j++) { string s="string "+print(L[j],"%s")+"="+"nameof("+print(L[j],"%s")+")"+";"; execute(s); kill s; exportto(Top,`L[j]`); } } /////////////////////////////////////////////// proc scheme(list #) "USAGE: scheme([v1,..,vn]); v1,..,vn of type vector RETURN: poly PURPOSE: performs substitutions by the means of Groebner basis computation of the submodule, generated by the input vectors, then intersects the intermediate result with the suitable component in order to get a finite difference scheme NOTE: works only for a single PDE, for the case of a system use @code{matrixsystem} EXAMPLE: example scheme; shows an example " { def N=size(#); if(N==0) { if(defined(M)==1) { kill M; module M; } else { module M; } } else { int j; if(defined(M)==1) { kill M; module M; for(j=1;j<=N;j++) { M=M+#[j]; } } else { module M; for(j=1;j<=N;j++) { M=M+#[j]; } } } def S=getit(M); matrix mat[1][1]=S; list l=timestep(mat); poly f=l[2][1,1]; return(f); } example { "EXAMPLE:";echo=2; list D="Ux","Ut","U"; list P="a"; list V="t","x"; setinitials(V,D,P); def s1=scheme(u(Ut)+a*u(Ux),backward(Ux,U,x),forward(Ut,U,t)); s1; } //////////////////////// static proc diffpar(poly ff) { def gg=print(ff,"%s"); def str="d"+gg; return(`str`); } //////////////////////// proc laxfrT(string Ut, string U, poly space) "USAGE: laxfrT(U1,U2,var); U1, U2 are the names of occuring derivatives, var is a variable in the basering; RETURN: type vector; gives a predefined approximation of the Lax-Friedrich-approximation for the derivation in the timevariable as often used in literature; NOTE: see also laxfrX, setinitials, scheme; Warning: laxfrT is not to be interchanged with laxfrX EXAMPLE: example laxfrT; shows an example " { poly time=var(2); poly dtime=diffpar(time); poly dspace=diffpar(space); def v=dtime*space*u(Ut)-time*space*u(U)+1/2*(space**2*u(U)+u(U)); return(v); } example { "EXAMPLE:";echo=2; list D="Ux","Ut","U"; list P="a"; list V="t","x"; setinitials(V,D,P); laxfrT(Ux,U,x); } //////////////////////// proc laxfrX(string Ux, string U, poly space) "USAGE: laxfrX(U1,U2,var); U1, U2 are the names of occuring derivatives, var is a variable in the basering; RETURN: type vector; gives a predefined approximation of the Lax-Friedrich-approximation for the derivation in one of the spatial variables as often used in literature; NOTE: see also laxfrT, setinitials, scheme; Warning: laxfrX is not to be interchanged with laxfrT EXAMPLE: example laxfrX; shows an example " { poly dspace = diffpar(space); def v=2*dspace*space*u(Ux)-(space**2-1)*u(U); return(v); } example { "EXAMPLE:";echo=2; list D="Ux","Ut","U"; list P="a"; list V="t","x"; setinitials(V,D,P); laxfrX(Ux,U,x); } //////////////////////// proc forward(string U1,string U2,poly VAR) "USAGE: forward(U1,U2,var); U1, U2 are the names of occuring derivatives, var is a variable in the basering; RETURN: type vector; gives a predefined approximation of the forward approximation as often used in literature; NOTE: see also laxfrT,setinitials,scheme; EXAMPLE: example forward; shows an example " { if(pos(U1,@derivatives)n2) { return(n1); } else { return(n2); } } //////////////////////////////////// static proc minimal(int n1, int n2) { return(-maximal(-n1,-n2)); } //////////////////////////////////// static proc MatrixEntry(int n, intvec v) { int j; int entry; int spavar=size(@variables)-1; for(j=1;j<=spavar;j++) { entry=entry+v[j]*n**(spavar-j); } entry=entry+1; return(entry); } ////////////////////////////////// static proc CompareVec(intvec ToTest, intvec Reference)//1 if ToTest>=Reference, 0 else { int i; for(i=1;i<=size(@variables)-1;i++) { if(ToTest[i+2]size(@variables) or size(Matrices)!=size(Approx)) { ERROR("Check number of variables: it must hold #(matrices)<= #(spatial variables)+1 !!! "); } if(size(Matrices)!=size(Approx)) { ERROR("Every variable needs EXACTLY ONE approximation rule, i.e. #(first argument) =#(second argument) ! "); } ideal Mon=leadmonomial(Approx[1]); int N=size(Matrices); int i; for(i=2;i<=N;i++) { Mon=Mon,leadmonomial(Approx[i]); } kill i; poly LCM=lcm(Mon); matrix M[nrows(Matrices[1])][ncols(Matrices[1])]; int i; for(i=1;i<=size(Matrices);i++) { M=M+(LCM/leadmonomial(Approx[i]))*normalize(Approx[i])[size(@derivatives)]*Matrices[i]; } kill i; return(M); } example { "EXAMPLE:";echo=2; list D="Ut","Ux","Uy","U"; list V="t","x","y"; list P="a","b"; setinitials(V,D,P); list Mat=unitmat(2),unitmat(2); list Appr=forward(Ut,U,t),forward(Ux,U,x); matrixsystem(Mat,Appr); } ////////////////////////////////// proc timestep(matrix M) "USAGE: timestep(M); M a square matrix with polynomials over the basering as entries; RETURN: type list; gives two matrices M1,M2 that are the splitting of M with respect to the degree of the variable t in the entries, where the first list-entry M1 consists of the polynomials of the highest timelevel and M2 of the lower levels in the form: M=0 => M1=M2, i.e. M1-M2=M NOTE: intended to be used for the finite-difference-scheme-construction and partition into the several time steps EXAMPLE: example timestep; shows an example " { int N=nrows(M); int i; int maxdegT; for(i=1;i<=N;i++) { int j; for(j=1;j<=N;j++) { poly f=M[i,j]; int k; for(k=1;k<=size(f);k++) { if(leadexp(M[i,j])[2]>maxdegT) { maxdegT=leadexp(M[i,j])[2]; } f=f-lead(f); } kill f; kill k; } kill j; } kill i; matrix highT[nrows(M)][nrows(M)]; vector leftside=0; int GenIndex=0; int i; for(i=1;i<=N;i++) { int j; for(j=1;j<=N;j++) { poly f=M[i,j]; int k; for(k=1;k<=size(f)+1;k++) { if(leadexp(f)[2]==maxdegT) { GenIndex++; highT[i,j]=highT[i,j]+lead(f); leftside=leftside+highT[i,j]*gen(GenIndex); } f=f-lead(f); } kill k; kill f; } kill j; } kill i; matrix tUpper=highT; matrix tLower=-1*(M-tUpper); tUpper=tUpper/content(leftside); tLower=tLower/content(leftside); list L=tUpper,tLower; return(L); } example { "EXAMPLE:"; echo=2; list D="Ut","Ux","Uy","U"; list V="t","x","y"; list P="a","b"; setinitials(V,D,P); list Mat=unitmat(2),unitmat(2); list Apr=forward(Ut,U,t),forward(Ux,U,x); matrixsystem(Mat,Apr); timestep(_); } ////////////////////////////////// proc fouriersystem(list Matrices, list Approx) "USAGE: fouriersystem(M,A); M a list of matrices, A a list of approximations; RETURN: type list; each entry is some matrix obtained by performing the substitution of the single approximations into the system of pde's, partitioning the equation into the several timesteps and fouriertransforming these parts EXAMPLE: example fouriersystem; shows an example " { matrix M=matrixsystem(Matrices,Approx); matrix T1=timestep(M)[1]; matrix T0=timestep(M)[2]; int i; for(i=1;i<=nrows(M);i++) { int j; for(j=1;j<=nrows(M);j++) { T1[i,j]=errormap(T1[i,j]); T1[i,j]=VarToPar(T1[i,j]); T0[i,j]=errormap(T0[i,j]); T0[i,j]=VarToPar(T0[i,j]); } kill j; } kill i; ideal EV1=eigenvals(T1)[1]; ideal EV0=eigenvals(T0)[1]; list L=list(T1,T0),list(EV1,EV0); def N1=size(EV1); def N0=size(EV0); list CV1; list CV0; int i; for(i=1;i<=N1;i++) { CV1[i]=VarToPar(EV1[i]); if(content(CV1[i])==CV1[i]) { CV1[i]=content(CV1[i]); CV1[i]=VarToPar(ComplexValue(numerator(CV1[i])))/VarToPar(ComplexValue(denominator(CV1[i]))); } } kill i; int i; for(i=1;i<=N0;i++) { CV0[i]=VarToPar(EV0[i]); if(content(CV0[i])==CV0[i]) { CV0[i]=content(CV0[i]); CV0[i]=VarToPar(ComplexValue(numerator(CV0[i])))/VarToPar(ComplexValue(denominator(CV0[i]))); } } kill i; list CV=list(CV1,CV0); L=L,CV; return(L); } example { "EXAMPLE:"; echo = 2; list D="Ut","Ux","Uy","U"; list V="t","x","y"; list P="a","b"; setinitials(V,D,P); matrix M[2][2]=0,-a,-a,0; list Mat=unitmat(2),M; list Appr=forward(Ut,U,t),trapezoid(Ux,U,x); def s=fouriersystem(Mat,Appr);s; } ////////////////////////////////// proc PartitionVar(poly f,int n) "USAGE: PartitionVar(f); f a poly in the basering; RETURN: type poly; gives back a list L=f1,f2 obtained by the partition of f into two parts f1,f2 with deg_var_n(f1) >0 deg_var_n(f2)=0 EXAMPLE: example PartitionVar; shows an example " { if(n>=nvars(basering)) { ERROR("this variable does not exist in the current basering"); } int i; poly partition=0; poly g=f; for(i=1;i<=size(f);i++) { if(leadexp(g)[n]!=0) { partition=partition+lead(g); } g=g-lead(g); } list L=partition,f-partition; return(L); } example { "EXAMPLE:"; echo = 2; list D="Ut","Ux","Uy","U"; list V="t","x","y"; list P="a","b"; setinitials(V,D,P);////does not show the ring, since there is no output basering;///does show the ring poly f=t**3*cx**2-cy**2*dt+i**3*sx; PartitionVar(f,1); ////i is the first variable } ////////////////////////////////// proc ComplexValue(poly f) "USAGE: ComplexValue(f); f a poly in the basering; RETURN: type poly; gives back the formal complex-value of f, where var(1) is redarded as the imaginary unit. Does only make sence, if the proc is executed before -> nvars <= npars EXAMPLE: example ComplexValue; shows an example " { poly g=ParToVar(f); def L=PartitionVar(g,1); poly f1=subst(L[1],var(1),1); poly f2=L[2]; poly result=reduce(f1**2+f2**2,std(0)); return(result); } example { "EXAMPLE:"; echo = 2; list D="Ut","Ux","Uy","U"; list V="t","x","y"; list P="a","b"; setinitials(V,D,P);////does not show the ring, as there is no output basering;///does show the ring poly f=t**3*cx**2-cy**2*dt+i**3*sx; f; ComplexValue(f); } ////////////////////////////////// proc VarToPar(poly f) "USAGE: VarToPar(f); f a poly in the basering; RETURN: type poly; gives back the poly obtained by substituting var(i) by par(i), for all variables. Does only make sence, if the proc is executed before -> nvars <= npars; EXAMPLE: example VarToPar; shows an example " { int N=nvars(basering); int i; def g=f; for(i=1;i<=N;i++) { g=subst(g,var(i),par(i)); } return(g); } example { "EXAMPLE:"; echo = 2; list D="Ut","Ux","Uy","U"; list V="t","x","y"; list P="a","b"; setinitials(V,D,P);////does not show the ring, as there is no output basering;///does show the ring poly f=t**3*cx**2-cy**2*dt+i**3*sx; f; VarToPar(f); } ///////////////////////////////////// proc ParToVar(poly f) "USAGE: ParToVar(f); f a poly in the basering; RETURN: type poly; gives back the poly obtained by substituting par(i) by var(i), for the first nvars(basering parameters. Does only make sence, if setinitials is executed before -> nvars <= npars. Is the opposite action to VarToPar, see example ParToVar; EXAMPLE: example ParToVar; shows an example " { int N=nvars(basering); int i; number g=number(VarToPar(f)); number denom=denominator(g); g=denom*g; def gg=subst(g,par(1),var(1)); for(i=2;i<=N;i++) { gg=subst(gg,par(i),var(i)); } return(gg/denom); } example { "EXAMPLE:"; echo = 2; list D="Ut","Ux","Uy","U"; list V="t","x","y"; list P="a","b"; setinitials(V,D,P);////does not show the ring, as there is no output basering;///does show the ring poly f=t**3*cx**2-cy**2*dt+i**3*sx/dt*dx; f; def g=VarToPar(f); g; def h=ParToVar(g); h==f; } ///////////////////////////////////////// proc qepcad(poly f) "USAGE: qepcad(f); f a poly in the basering; RETURN: type list; gives back some constraints that are equivalent to f<1 (computed by QEPCAD); EXAMPLE: example qepcad; shows an example " { // how to test, whether QEPCAD is installed? createQCfilter(); // creates/overwrites qepcadfilter.pl system("sh","rm -f QEPCAD-out"); system("sh","rm -f QEPCAD-in"); if(denominator(content(f))==1) { poly g=f-1; } else { if(f==content(f)) { poly g=f*denominator(content(f))-1*denominator(content(f)); g=ParToVar(g); g=reduce(g,std(0)); } else { poly g=cleardenom(f)-1/content(f); g=ParToVar(g); g=reduce(g,std(0)); } } string in="QEPCAD-in"; string out="QEPCAD-out"; link l1=in; link l2=out; string s1="[trial]"; //description string s2=varlist(); //the variables string s3=nfreevars(); //number of free variables string s4=aquantor()+"["+writepoly(g)+rel()+"]."; //the input prenex formula string s5=projection(); string s6=projection(); string s7=choice(); string s8=solution(); write(l1,s1,s2,s3,s4,s5,s6,s7,s8); system("sh","qepcad < QEPCAD-in | qepcadfilter.pl > QEPCAD-out"); string output=read(out); print(output,"%s"); if(size(output)==0) { return("Try manually"); //maybe too few cells } if(find(output,"FALSE")!=0) { return("FALSE"); } if(find(output,"WARNING")!=0) { return("WARNING! Try manually"); } else { string strpolys=findthepoly(output); list lpolys=listpolynew(strpolys); return(lpolys); } system("sh","rm -f QEPCAD-out"); system("sh","rm -f QEPCAD-in"); } example { "EXAMPLE:"; echo = 2; list D="Ux","Ut","U"; list P="a"; list V="t","x"; setinitials(V,D,P); def s1=scheme(u(Ut)+a*u(Ux),laxfrX(Ux,U,x),laxfrT(Ut,U,x)); s1; def s2=errormap(s1); s2; def s3=ComplexValue(s2);s3; qepcad(s3); } /////////////////////////////////////////// proc createQCfilter() { // writes the following to the file qepcadfilter.pl // is there already such a file? remove it! system("sh","rm -f qepcadfilter.pl"); link l=":w qepcadfilter.pl"; write(l, "#!/usr/bin/perl"); write(l, "$flag = 0;"); write(l, "$res = \"\";"); write(l,"while(<>)"); write(l,"{ if ($_ =~ /Warning|WARNING|warning|Error|error|ERROR/) { print $_; }"); write(l,"elsif ($_ =~ /An\ equivalent/) { $flag = 1; }"); write(l,"elsif ($flag == 1 && $_ ne \"\n\") { print $_; $flag = 0; } }"); } /////////////////////////////////////////// proc qepcadsystem(list l) "USAGE: qepcadsytem(f); l a list; RETURN: list PURPOSE: gives back some constraints that are equivalent to the eigenvalues of the matrices in the list l being < 1 (computed by QEPCAD) EXAMPLE: example qepcadsystem; shows an example " { // how to test, whether QEPCAD is installed? createQCfilter(); // creates/overwrites qepcadfilter.pl system("sh","rm -f QEPCAD-out"); system("sh","rm -f QEPCAD-in"); string in="QEPCAD-in"; string out="QEPCAD-out"; link l1=in; link l2=out; string s1="[trial]"; //description string s2=varlist(); //the variables string s3=nfreevars(); //number of free variables string thepolys; int n2=size(l[2]); int count; int i; list lpolys; int j; for(j=1;j<=n2;j++) { count++; poly g2=ParToVar(l[2][j]); if(denominator(content(g2))==1) { lpolys[count]=writepoly(ParToVar(reduce(g2-1,std(0))))+rel(); } else { if(g2==content(g2)) { g2=g2*denominator(content(g2))-1*denominator(content(g2)); g2=ParToVar(g2); g2=reduce(g2,std(0)); lpolys[count]=writepoly(g2)+rel(); } else { lpolys[count]=writepoly(reduce(ParToVar(cleardenom(g2)-1/content(g2)),std(0)))+rel(); } } kill g2; } kill j; int k; for(k=1;k<=size(lpolys);k++) { thepolys=thepolys+lpolys[k]; if(k QEPCAD-out"); string output=read(out); print(output,"%s"); if(size(output)==0) { ERROR("Try manually"); //maybe too few cells } if(find(output,"FALSE")!=0) { ERROR("FALSE"); } if(find(output,"WARNING")!=0) { ERROR("WARNING! Try manually"); } else { string strpolys=findthepoly(output); list llpolys=listpolynew(strpolys); return(llpolys); } system("sh","rm -f QEPCAD-out"); system("sh","rm -f QEPCAD-in"); } example { "EXAMPLE:"; echo = 2; list D="Ut","Ux","Uy","U"; list V="t","x","y"; list P="a","b"; setinitials(V,D,P); matrix M[2][2]=0,-a,-a,0; list Mat=unitmat(2),M; list Appr=forward(Ut,U,t),forward(Ux,U,x); //matrixsystem(Mat,Appr); //timestep(_); fouriersystem(Mat,Appr); qepcadsystem(_[2]); } /////////////////////////////////////////// static proc substbracketstar(string s) { int i; int k; int index=1; string finish=s; for(k=1;k<=size(s);k++) { if(finish[1]=="(" or finish[1]=="*" or finish[1]==" ") { kill finish; index=index+1; string finish=s[index..size(s)]; } } for(i=1;i<=size(finish);i++) { if(finish[i]=="*" or finish[i]=="(" or finish[i]== ")") { finish[i]=" "; } } return(finish); } //////////////////////////////////// static proc distribution(string SUM, string MON) { string sum=substbracketstar(SUM); string mon=substbracketstar(MON); string result; list signs; list p; int i; int j; int init; for(i=2;i<=size(sum);i++) { if(sum[i]=="+" or sum[i]=="-") { j++; p[j]=i; } } if(j==0) { if(sum[1]!="-") { result=sum+" "+" "+mon; result="+"+" "+result; } else { result=sum+" "+mon; } } else { int l; int anfang; if(sum[1]=="-") { result="-"+" "+result; anfang=2; } else { result="+"+" "+result; if(sum[1]=="+") { anfang=2; } else { anfang=1; } } for(l=1;l<=j;l++) { string a; int k; for(k=anfang;k<=p[l]-1;k++) { a=a+sum[k]; } result=result+" "+a+" "+mon+" "+sum[p[l]]; anfang=p[l]+1; kill a; kill k; } if(p[j]0"; int i; for(i=2;i<=n2;i++) { string s=" /\\"+" "+substbracketstar(print(par(n1+i),"%s"))+" >0"; assumption=assumption+" "+s; kill s; } assumption=assumption+" ]"+newline+"go"; return(assumption); } /////////////////////////////////////////////////////// static proc projection() { string s="go"; return(s); } /////////////////////////////////////////////////////// static proc choice() { string s="go"; return(s); } /////////////////////////////////////////////////////// static proc solution() { string s="go"; return(s); } /////////////////////////////////////////////////////// static proc nfreevars() { int n=npars(basering)-size(@variables)-1; string no=print(n,"%s"); return(no); } ///////////////////////////////////////////////////////// static proc aquantor() { string s="(A "+print(var(2),"%s")+")"; return(s); } //////////////////////////////////////////////////////// static proc rel() { return("<0"); } ///////////////////////////////////////////////////////// static proc rm() { system("sh","rm -f dummy"); system("sh","rm -f QEPCAD-in"); } //////////////////////////////////////////////////////// static proc findthepoly(string word) { int init=1; int index=find(word,newline); if(index==size(word) or index== 0) { return(word); } else { while(index","==>","<==";///these can occur in QEPCAD int i; for(i=1;i<=size(thesigns);i++) { list l=TestAndDelete(p,thesigns[i]); p=l[1]; v=addintvec(v,l[2]); kill l; } intvec w=rightorder(v); int N=size(v); list lstrings; if(size(w)==1 and w[1]==0) { N=0; lstrings[1]=p; } else { string s1=p[1..w[1]-1]; lstrings[1]=s1; int j; for(j=1;j1) { linterim[i]="*"; } else { linterim[i]=word[i]; } strpoly=strpoly+print(linterim[i],"%s"); } strpoly=strpoly+";"; execute(strpoly); return(f); } ////////////////////////////////////////////////// static proc rightorder(intvec v) ////////////orders the entries of an intvec from small to bigger { list ldown=intveclist(v); list lup; intvec v1; int counter; int min; int i; for(i=1;i<=size(v);i++) { min=Min(listintvec(ldown)); lup[i]=min; counter=listfind(ldown,min); ldown=delete(ldown,counter); } intvec result=listintvec(lup); return(result); } ///////////////////////////////////////////////// static proc listfind(list l, int n) //////gives the position of n in l, 0 if not found { int i; intvec counter; int j=1; for(i=1;i<=size(l);i++) { if(n==l[i]) { counter[j]=i; j++; } } int result=Min(counter); return(result); } ////////////////////////////////////////////////// static proc cutoffrel(string str) /////////cut off the relations "/=,<= etc." from output-string { list rels="<=",">=","<",">","/=","="; //these are all of qepcad's relations int i; list l; for(i=1;i<=size(rels);i++) { l[i]=find(str,rels[i]); } intvec v=listintvec(l); v=addintvec(v,v); int position=Min(v); string result; if(position==0) { result=str; } else { result=str[1..position-1]; } return(result); } ////////////////////////////////////////////////// static proc addintvec(intvec v1, intvec v2) ///////concatenates two intvecs and deletes occurring zeroentries, output intvec { list lresult; int i; list l1; list l2; for(i=1;i<=size(v1);i++) { l1[i]=v1[i]; } kill i; int k; for(k=1;k<=size(v2);k++) { l2[k]=v2[k]; } lresult=l1+l2; intvec result; int j; int counter=1; for(j=1;j<=size(lresult);j++) { if(lresult[j]!=0) { result[counter]=lresult[j]; counter++; } } return(result); } ///////////////////////////////////////////////// static proc intveclist(intvec v) //////returns the intvec as list { list l; int i; for(i=size(v);i>=1;i--) { l[i]=v[i]; } return(l); } ////////////////////////////////////////////////// static proc listintvec(list l) //////////returns the list as intvec: only integer-entries allowed { intvec v; int i; for(i=size(l);i>=1;i--) { v[i]=l[i]; } return(v); } ////////////////////////////////////////////////// static proc TestAndDelete(string str, string booleansign) { int decide=find(str,booleansign); intvec v; v[1]=decide; while(decide!=0 and decide 0 RETURNS: the i-th cyclotomic polynomial (type ) as one in the first ring variable THEORY: x^i-1 is divided by the j-th cyclotomic polynomial where j takes on the value of proper divisors of i EXAMPLE: example cyclotomic; shows an example " { if (i<=0) { "ERROR: the input should be > 0."; return(); } poly v1=var(1); if (i==1) { return(v1-1); // 1-st cyclotomic polynomial } poly min=v1^i-1; matrix s[1][2]; min=min/(v1-1); // dividing by the 1-st cyclotomic // polynomial int j=2; int n; poly c; int flag=1; while(2*j<=i) // there are no proper divisors of i { if ((i%j)==0) // greater than i/2 { if (flag==1) { n=j; // n stores the first proper divisor of } // i > 1 flag=0; c=cyclotomic(j); // recursive computation s=min,c; s=matrix(syz(ideal(s))); // dividing min=s[2,1]; } if (n*j==i) // the earliest possible point to break { break; } j++; } min=min/leadcoef(min); // making sure that the leading return(min); // coefficient is 1 } example { "EXAMPLE:"; echo=2; ring R=0,(x,y,z),dp; print(cyclotomic(25)); } proc group_reynolds (list #) "USAGE: group_reynolds(G1,G2,...[,v]); G1,G2,...: nxn generating a finite matrix group, v: an optional ASSUME: n is the number of variables of the basering, g the number of group elements RETURN: a , the first list element will be a gxn representing the Reynolds operator if we are in the non-modular case; if the characteristic is >0, minpoly==0 and the finite group non-cyclic the second list element is an giving the lowest common multiple of the matrix group elements' order (used in molien); in general all other list elements are nxn listing all elements of the finite group DISPLAY: information if v does not equal 0 THEORY: The entire matrix group is generated by getting all left products of generators with the new elements from the last run through the loop (or the generators themselves during the first run). All the ones that have been generated before are thrown out and the program terminates when no new elements found in one run. Additionally each time a new group element is found the corresponding ring mapping of which the Reynolds operator is made up is generated. They are stored in the rows of the first return value. EXAMPLE: example group_reynolds; shows an example " { int ch=char(basering); // the existance of the Reynolds operator // is dependent on the characteristic of // the base field int gen_num; // number of generators //------------------------ making sure the input is okay --------------------- if (typeof(#[size(#)])=="int") { if (size(#)==1) { "ERROR: there are no matrices given among the parameters"; return(); } int v=#[size(#)]; gen_num=size(#)-1; } else // last parameter is not { int v=0; // no information is default gen_num=size(#); } if (typeof(#[1])<>"matrix") { "ERROR: The parameters must be a list of matrices and maybe an "; return(); } int n=nrows(#[1]); if (n<>nvars(basering)) { "ERROR: the number of variables of the basering needs to be the same"; " as the dimension of the matrices"; return(); } if (n<>ncols(#[1])) { "ERROR: matrices need to be square and of the same dimensions"; return(); } matrix vars=matrix(maxideal(1)); // creating an nx1-matrix containing the vars=transpose(vars); // variables of the ring - matrix REY=#[1]*vars; // calculating the first ring mapping - // REY will contain the Reynolds // operator - matrix G(1)=#[1]; // G(k) are elements of the group - if (ch<>0 && minpoly==0 && gen_num<>1) // finding out of which order the { matrix I=diag(1,n); // group element is matrix TEST=G(1); int o1=1; int o2; while (TEST<>I) { TEST=TEST*G(1); o1++; } } int i=1; // -------------- doubles among the generators should be avoided ------------- for (int j=2;j<=gen_num;j++) // this loop adds the parameters to the { // group, leaving out doubles and // checking whether the parameters are // compatible with the task of the // procedure if (not(typeof(#[j])=="matrix")) { "ERROR: The parameters must be a list of matrices and maybe an "; return(); } if ((n!=nrows(#[j])) or (n!=ncols(#[j]))) { "ERROR: matrices need to be square and of the same dimensions"; return(); } if (unique(G(1..i),#[j])) { i++; matrix G(i)=#[j]; if (ch<>0 && minpoly==0) // finding out of which order the group { TEST=G(i); // element is o2=1; while (TEST<>I) { TEST=TEST*G(i); o2++; } o1=o1*o2 div gcd(o1,o2); // lowest common multiple of the element } // orders - REY=concat(REY,#[j]*vars); // adding ring homomorphisms to REY } } int g=i; // G(1)..G(i) are generators without // doubles - g generally is the number // of elements in the group so far - j=i; // j is the number of new elements that // we use as factors int k, m, l; if (v) { ""; " Generating the entire matrix group and the Reynolds operator..."; ""; } // -------------- main loop that finds all the group elements ---------------- while (1) { l=0; // l is the number of products we get in // one going for (m=g-j+1;m<=g;m++) { for (k=1;k<=i;k++) { l=l+1; matrix P(l)=G(k)*G(m); // possible new element } } j=0; for (k=1;k<=l;k++) { if (unique(G(1..g),P(k))) { j++; // a new factor for next run g++; matrix G(g)=P(k); // a new group element - if (ch<>0 && minpoly==0 && i<>1) // finding out of which order the { TEST=G(g); //group element is o2=1; while (TEST<>I) { TEST=TEST*G(g); o2++; } o1=o1*o2 div gcd(o1,o2); // lowest common multiple of the element } // orders - REY=concat(REY,P(k)*vars); // adding new mapping to REY if (v) { " Group element ",g," has been found."; } } kill P(k); } if (j==0) // when we didn't add any new elements { break; // in one run through the while loop } // we are done } if (v) { if (g<=i) { " There are only ",g," group elements."; } ""; } REY=transpose(REY); // when we evaluate the Reynolds operator // later on, we actually want 1xn // matrices if (ch<>0) { if ((g%ch)==0) { if (voice==2) { "WARNING: The characteristic of the coefficient field divides the group order."; " Proceed without the Reynolds operator!"; } else { if (v) { " The characteristic of the base field divides the group order."; " We have to continue without Reynolds operator..."; ""; } } kill REY; matrix REY[1][1]=0; return(list(REY,G(1..g))); } if (minpoly==0) { if (i>1) { return(list(REY,o1,G(1..g))); } return(list(REY,G(1..g))); } } if (v) { " Done generating the group and the Reynolds operator."; ""; } return(list(REY,G(1..g))); } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); print(L[1]); print(L[2..size(L)]); } /////////////////////////////////////////////////////////////////////////////// // Returns i such that root^i==n, i.e. it heavily relies on the right input. /////////////////////////////////////////////////////////////////////////////// proc exponent(number n, number root) { int i=0; while((n/root^i)<>1) { i++; } return(i); } /////////////////////////////////////////////////////////////////////////////// proc molien (list #) "USAGE: molien(G1,G2,...[,ringname,lcm,flags]); G1,G2,...: nxn , all elements of a finite matrix group, ringname: a giving a name for a new ring of characteristic 0 for the Molien series in case of prime characteristic, lcm: an giving the lowest common multiple of the elements' orders in case of prime characteristic, minpoly==0 and a non-cyclic group, flags: an optional with three components: if the first element is not equal to 0 characteristic 0 is simulated, i.e. the Molien series is computed as if the base field were characteristic 0 (the user must choose a field of large prime characteristic, e.g. 32003), the second component should give the size of intervals between canceling common factors in the expansion of the Molien series, 0 (the default) means only once after generating all terms, in prime characteristic also a negative number can be given to indicate that common factors should always be canceled when the expansion is simple (the root of the extension field does not occur among the coefficients) ASSUME: n is the number of variables of the basering, G1,G2... are the group elements generated by group_reynolds(), lcm is the second return value of group_reynolds() RETURN: in case of characteristic 0 a 1x2 giving enumerator and denominator of Molien series; in case of prime characteristic a ring with the name `ringname` of characteristic 0 is created where the same Molien series (named M) is stored DISPLAY: information if the third component of flags does not equal 0 THEORY: In characteristic 0 the terms 1/det(1-xE) for all group elements of the Molien series are computed in a straight forward way. In prime characteristic a Brauer lift is involved. The returned matrix gives enumerator and denominator of the expanded version where common factors have been canceled. EXAMPLE: example molien; shows an example " { def br=basering; // the Molien series depends on the int ch=char(br); // characteristic of the coefficient // field - int g; // size of the group //---------------------- making sure the input is okay ----------------------- if (typeof(#[size(#)])=="intvec") { if (size(#[size(#)])==3) { int mol_flag=#[size(#)][1]; if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0))) { "ERROR: the second component of should be >=0" return(); } int interval=#[size(#)][2]; int v=#[size(#)][3]; } else { "ERROR: should have three components"; return(); } if (ch<>0) { if (typeof(#[size(#)-1])=="int") { int r=#[size(#)-1]; if (typeof(#[size(#)-2])<>"string") { "ERROR: In characteristic p>0 a must be given for the name of a new"; " ring where the Molien series can be stored"; return(); } else { if (#[size(#)-2]=="") { "ERROR: may not be empty"; return(); } string newring=#[size(#)-2]; g=size(#)-3; } } else { if (typeof(#[size(#)-1])<>"string") { "ERROR: In characteristic p>0 a must be given for the name of a new"; " ring where the Molien series can be stored"; return(); } else { if (#[size(#)-1]=="") { "ERROR: may not be empty"; return(); } string newring=#[size(#)-1]; g=size(#)-2; int r=g; } } } else // then ist not needed { g=size(#)-1; } } else // last parameter is not { int v=0; // no information is default int mol_flag=0; // computing of Molien series is default int interval=0; if (ch<>0) { if (typeof(#[size(#)])=="int") { int r=#[size(#)]; if (typeof(#[size(#)-1])<>"string") { "ERROR: in characteristic p>0 a must be given for the name of a new"; " ring where the Molien series can be stored"; return(); } else { if (#[size(#)-1]=="") { "ERROR: may not be empty"; return(); } string newring=#[size(#)-1]; g=size(#)-2; } } else { if (typeof(#[size(#)])<>"string") { "ERROR: in characteristic p>0 a must be given for the name of a new"; " ring where the Molien series can be stored"; return(); } else { if (#[size(#)]=="") { "ERROR: may not be empty"; return(); } string newring=#[size(#)]; g=size(#)-1; int r=g; } } } else { g=size(#); } } if (ch<>0) { if ((g div r)*r<>g) { "ERROR: should divide the group order." return(); } } if (ch<>0) { if ((g%ch)==0) { if (voice==2) { "WARNING: The characteristic of the coefficient field divides the group"; " order. Proceed without the Molien series!"; } else { if (v) { " The characteristic of the base field divides the group order."; " We have to continue without Molien series..."; ""; } } } if (minpoly<>0 && mol_flag==0) { if (voice==2) { "WARNING: It is impossible for this program to calculate the Molien series"; " for finite groups over extension fields of prime characteristic."; } else { if (v) { " Since it is impossible for this program to calculate the Molien series for"; " invariant rings over extension fields of prime characteristic, we have to"; " continue without it."; ""; } } return(); } } //---------------------------------------------------------------------------- if (not(typeof(#[1])=="matrix")) { "ERROR: the parameters must be a list of matrices and maybe an "; return(); } int n=nrows(#[1]); if (n<>nvars(br)) { "ERROR: the number of variables of the basering needs to be the same"; " as the dimension of the square matrices"; return(); } if (v && voice<>2) { ""; " Generating the Molien series..."; ""; } if (v && voice==2) { ""; } //------------- calculating Molien series in characteristic 0 ---------------- if (ch==0) // when ch==0 we can calculate the Molien { matrix I=diag(1,n); // series in any case - poly v1=maxideal(1)[1]; // the Molien series will be in terms of // the first variable of the current // ring - matrix M[1][2]; // M will contain the Molien series - M[1,1]=0; // M[1,1] will be the numerator - M[1,2]=1; // M[1,2] will be the denominator - matrix s; // will help us canceling in the // fraction poly p; // will contain the denominator of the // new term of the Molien series //------------ computing 1/det(1+xE) for all E in the group ------------------ for (int j=1;j<=g;j++) { if (not(typeof(#[j])=="matrix")) { "ERROR: the parameters must be a list of matrices and maybe an "; return(); } if ((n<>nrows(#[j])) or (n<>ncols(#[j]))) { "ERROR: matrices need to be square and of the same dimensions"; return(); } p=det(I-v1*#[j]); // denominator of new term - M[1,1]=M[1,1]*p+M[1,2]; // expanding M[1,1]/M[1,2] + 1/p M[1,2]=M[1,2]*p; if (interval<>0) // canceling common terms of denominator { if ((j div interval)*interval==j or j==g) // and enumerator - { s=matrix(syz(ideal(M))); // once gcd() is faster than syz() these M[1,1]=-s[2,1]; // three lines should be replaced by the M[1,2]=s[1,1]; // following three // p=gcd(M[1,1],M[1,2]); // M[1,1]=M[1,1]/p; // M[1,2]=M[1,2]/p; } } if (v) { " Term ",j," of the Molien series has been computed."; } } if (interval==0) // canceling common terms of denominator { // and enumerator - s=matrix(syz(ideal(M))); // once gcd() is faster than syz() these M[1,1]=-s[2,1]; // three lines should be replaced by the M[1,2]=s[1,1]; // following three // p=gcd(M[1,1],M[1,2]); // M[1,1]=M[1,1]/p; // M[1,2]=M[1,2]/p; } map slead=br,ideal(0); s=slead(M); M[1,1]=1/s[1,1]*M[1,1]; // numerator and denominator have to have M[1,2]=1/s[1,2]*M[1,2]; // a constant term of 1 if (v) { ""; " We are done calculating the Molien series."; ""; } return(M); } //---- calculating Molien series in prime characteristic with Brauer lift ---- if (ch<>0 && mol_flag==0) { if (g<>1) { matrix G(1..g)=#[1..g]; if (interval<0) { string Mstring; } //------ preparing everything for Brauer lifts into characteristic 0 --------- ring Q=0,x,dp; // we want to extend our ring as well as // the ring of rational numbers Q to // contain r-th primitive roots of unity // in order to factor characteristic // polynomials of group elements into // linear factors and lift eigenvalues to // characteristic 0 - poly minq=cyclotomic(r); // minq now contains the size-of-group-th // cyclotomic polynomial of Q, it is // irreducible there ring `newring`=(0,e),x,dp; map f=Q,ideal(e); minpoly=number(f(minq)); // e is now a r-th primitive root of // unity - kill Q; // no longer needed - poly p=1; // used to build the denominator of the // new term in the Molien series matrix s[1][2]; // used for canceling - matrix M[1][2]=0,1; // will contain Molien series - ring v1br=char(br),x,dp; // we calculate the r-th cyclotomic poly minp=cyclotomic(r); // polynomial of the base field and pick minp=factorize(minp)[1][2]; // an irreducible factor of it - if (deg(minp)==1) // in this case the base field contains { ring bre=char(br),x,dp; // r-th roots of unity already map f1=v1br,ideal(0); number e=-number((f1(minp))); // e is a r-th primitive root of unity } else { ring bre=(char(br),e),x,dp; map f1=v1br,ideal(e); minpoly=number(f1(minp)); // e is a r-th primitive root of unity } map f2=br,ideal(0); // we need f2 to map our group elements // to this new extension field bre matrix xI=diag(x,n); poly p; // used for the characteristic polynomial // to factor - list L; // will contain the linear factors of the ideal F; // characteristic polynomial of the group intvec C; // elements and their powers int i, j, k; // -------------- finding all the terms of the Molien series ----------------- for (i=1;i<=g;i++) { setring br; if (not(typeof(#[i])=="matrix")) { "ERROR: the parameters must be a list of matrices and maybe an "; return(); } if ((n<>nrows(#[i])) or (n<>ncols(#[i]))) { "ERROR: matrices need to be square and of the same dimensions"; return(); } setring bre; p=det(xI-f2(G(i))); // characteristic polynomial of G(i) L=factorize(p); F=L[1]; C=L[2]; for (j=2;j<=ncols(F);j++) { F[j]=-1*(F[j]-x); // F[j] is now an eigenvalue of G(i), // it is a power of a primitive r-th root // of unity - k=exponent(number(F[j]),e); // F[j]==e^k setring `newring`; p=p*(1-x*(e^k))^C[j]; // building the denominator of the new setring bre; // term } // ----------- // k=0; // while(kg) { Mstring=string(M); for (j=1;j<=size(Mstring);j++) { if (Mstring[j]=="e") { interval=0; break; } } } if (interval<>0) { s=matrix(syz(ideal(M))); // once gcd() is faster than syz() M[1,1]=-s[2,1]; // these three lines should be M[1,2]=s[1,1]; // replaced by the following three // p=gcd(M[1,1],M[1,2]); // M[1,1]=M[1,1]/p; // M[1,2]=M[1,2]/p; } else { interval=-1; } } else { if (interval<>0) // canceling common terms of denominator { if ((i div interval)*interval==i or i==g) // and enumerator { s=matrix(syz(ideal(M))); // once gcd() is faster than syz() M[1,1]=-s[2,1]; // these three lines should be M[1,2]=s[1,1]; // replaced by the following three // p=gcd(M[1,1],M[1,2]); // M[1,1]=M[1,1]/p; // M[1,2]=M[1,2]/p; } } } p=1; setring bre; if (v) { " Term ",i," of the Molien series has been computed."; } } if (v) { ""; } setring `newring`; if (interval==0) // canceling common terms of denominator { // and enumerator - s=matrix(syz(ideal(M))); // once gcd() is faster than syz() these M[1,1]=-s[2,1]; // three lines should be replaced by the M[1,2]=s[1,1]; // following three // p=gcd(M[1,1],M[1,2]); // M[1,1]=M[1,1]/p; // M[1,2]=M[1,2]/p; } map slead=`newring`,ideal(0); s=slead(M); // forcing the constant term of numerator M[1,1]=1/s[1,1]*M[1,1]; // and denominator to be 1 M[1,2]=1/s[1,2]*M[1,2]; kill slead; kill s; kill p; } else // if the group only contains an identity { ring `newring`=0,x,dp; // element, it is very easy to calculate matrix M[1][2]=1,(1-x)^n; // the Molien series } export(`newring`); // we keep the ring where we computed the export M; // Molien series in such that we can setring br; // keep it if (v) { " We are done calculating the Molien series."; ""; } } else // i.e. char<>0 and mol_flag<>0, the user { // has specified that we are dealing with // a ring of large characteristic which // can be treated like a ring of // characteristic 0; we'll avoid the // Brauer lifts //----------------------- simulating characteristic 0 ------------------------ string chst=charstr(br); for (int i=1;i<=size(chst);i++) { if (chst[i]==",") { break; } } //----------------- generating ring of characteristic 0 ---------------------- if (minpoly==0) { if (i>size(chst)) { execute("ring "+newring+"=0,("+varstr(br)+"),("+ordstr(br)+")"); } else { chst=chst[i..size(chst)]; execute ("ring "+newring+"=(0"+chst+"),("+varstr(br)+"),("+ordstr(br)+")"); } } else { string minp=string(minpoly); minp=minp[2..size(minp)-1]; chst=chst[i..size(chst)]; execute("ring "+newring+"=(0"+chst+"),("+varstr(br)+"),("+ordstr(br)+")"); execute("minpoly="+minp); } matrix I=diag(1,n); poly v1=maxideal(1)[1]; // the Molien series will be in terms of // the first variable of the current // ring - matrix M[1][2]; // M will contain the Molien series - M[1,1]=0; // M[1,1] will be the numerator - M[1,2]=1; // M[1,2] will be the denominator - matrix s; // will help us canceling in the // fraction poly p; // will contain the denominator of the // new term of the Molien series int j; string links, rechts; //----------------- finding all terms of the Molien series ------------------- for (i=1;i<=g;i++) { setring br; if (not(typeof(#[i])=="matrix")) { "ERROR: the parameters must be a list of matrices and maybe an "; return(); } if ((n<>nrows(#[i])) or (n<>ncols(#[i]))) { "ERROR: matrices need to be square and of the same dimensions"; return(); } string stM(i)=string(#[i]); for (j=1;j<=size(stM(i));j++) { if (stM(i)[j]==" ") { links=stM(i)[1..j-1]; rechts=stM(i)[j+1..size(stM(i))]; stM(i)=links+rechts; } } setring `newring`; execute("matrix G(i)["+string(n)+"]["+string(n)+"]="+stM(i)); p=det(I-v1*G(i)); // denominator of new term - M[1,1]=M[1,1]*p+M[1,2]; // expanding M[1,1]/M[1,2] + 1/p M[1,2]=M[1,2]*p; if (interval<>0) // canceling common terms of denominator { if ((i div interval)*interval==i or i==g) // and enumerator { s=matrix(syz(ideal(M))); // once gcd() is faster than syz() these M[1,1]=-s[2,1]; // three lines should be replaced by the M[1,2]=s[1,1]; // following three // p=gcd(M[1,1],M[1,2]); // M[1,1]=M[1,1]/p; // M[1,2]=M[1,2]/p; } } if (v) { " Term ",i," of the Molien series has been computed."; } } if (interval==0) // canceling common terms of denominator { // and enumerator - s=matrix(syz(ideal(M))); // once gcd() is faster than syz() these M[1,1]=-s[2,1]; // three lines should be replaced by the M[1,2]=s[1,1]; // following three // p=gcd(M[1,1],M[1,2]); // M[1,1]=M[1,1]/p; // M[1,2]=M[1,2]/p; } map slead=`newring`,ideal(0); s=slead(M); M[1,1]=1/s[1,1]*M[1,1]; // numerator and denominator have to have M[1,2]=1/s[1,2]*M[1,2]; // a constant term of 1 if (v) { ""; " We are done calculating the Molien series."; ""; } kill G(1..g), s, slead, p, v1, I; export `newring`; // we keep the ring where we computed the export M; // the Molien series such that we can setring br; // keep it } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; " note the case of prime characteristic"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); matrix M=molien(L[2..size(L)]); print(M); ring S=3,(x,y,z),dp; string newring="alksdfjlaskdjf"; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); molien(L[2..size(L)],newring); setring Finvar::alksdfjlaskdjf; print(M); setring S; kill Finvar::alksdfjlaskdjf; } /////////////////////////////////////////////////////////////////////////////// proc reynolds_molien (list #) "USAGE: reynolds_molien(G1,G2,...[,ringname,flags]); G1,G2,...: nxn generating a finite matrix group, ringname: a giving a name for a new ring of characteristic 0 for the Molien series in case of prime characteristic, flags: an optional with three components: if the first element is not equal to 0 characteristic 0 is simulated, i.e. the Molien series is computed as if the base field were characteristic 0 (the user must choose a field of large prime characteristic, e.g. 32003) the second component should give the size of intervals between canceling common factors in the expansion of the Molien series, 0 (the default) means only once after generating all terms, in prime characteristic also a negative number can be given to indicate that common factors should always be canceled when the expansion is simple (the root of the extension field does not occur among the coefficients) ASSUME: n is the number of variables of the basering, G1,G2... are the group elements generated by group_reynolds(), g is the size of the group RETURN: a gxn representing the Reynolds operator is the first return value and in case of characteristic 0 a 1x2 giving enumerator and denominator of Molien series is the second one; in case of prime characteristic a ring with the name `ringname` of characteristic 0 is created where the same Molien series (named M) is stored DISPLAY: information if the third component of flags does not equal 0 THEORY: The entire matrix group is generated by getting all left products of the generators with new elements from the last run through the loop (or the generators themselves during the first run). All the ones that have been generated before are thrown out and the program terminates when are no new elements found in one run. Additionally each time a new group element is found the corresponding ring mapping of which the Reynolds operator is made up is generated. They are stored in the rows of the first return value. In characteristic 0 the terms 1/det(1-xE) is computed whenever a new element E is found. In prime characteristic a Brauer lift is involved and the terms are only computed after the entire matrix group is generated (to avoid the modular case). The returned matrix gives enumerator and denominator of the expanded version where common factors have been canceled. EXAMPLE: example reynolds_molien; shows an example " { def br=basering; // the Molien series depends on the int ch=char(br); // characteristic of the coefficient // field int gen_num; //------------------- making sure the input is okay -------------------------- if (typeof(#[size(#)])=="intvec") { if (size(#[size(#)])==3) { int mol_flag=#[size(#)][1]; if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0))) { "ERROR: the second component of the should be >=0"; return(); } int interval=#[size(#)][2]; int v=#[size(#)][3]; } else { "ERROR: should have three components"; return(); } if (ch<>0) { if (typeof(#[size(#)-1])<>"string") { "ERROR: in characteristic p a must be given for the name"; " of a new ring where the Molien series can be stored"; return(); } else { if (#[size(#)-1]=="") { "ERROR: may not be empty"; return(); } string newring=#[size(#)-1]; gen_num=size(#)-2; } } else // then ist not needed { gen_num=size(#)-1; } } else // last parameter is not { int v=0; // no information is default int interval; int mol_flag=0; // computing of Molien series is default if (ch<>0) { if (typeof(#[size(#)])<>"string") { "ERROR: in characteristic p a must be given for the name"; " of a new ring where the Molien series can be stored"; return(); } else { if (#[size(#)]=="") { "ERROR: may not be empty"; return(); } string newring=#[size(#)]; gen_num=size(#)-1; } } else { gen_num=size(#); } } // ----------------- computing the terms with Brauer lift -------------------- if (ch<>0 && mol_flag==0) { list L=group_reynolds(#[1..gen_num],v); if (L[1]==0) { if (voice==2) { "WARNING: The characteristic of the coefficient field divides the group order."; " Proceed without the Reynolds operator or the Molien series!"; return(); } if (v) { " The characteristic of the base field divides the group order."; " We have to continue without Reynolds operator or the Molien series..."; return(); } } if (minpoly<>0) { if (voice==2) { "WARNING: It is impossible for this program to calculate the Molien series"; " for finite groups over extension fields of prime characteristic."; return(L[1]); } else { if (v) { " Since it is impossible for this program to calculate the Molien series for"; " invariant rings over extension fields of prime characteristic, we have to"; " continue without it."; return(L[1]); } } } if (typeof(L[2])=="int") { molien(L[3..size(L)],newring,L[2],intvec(mol_flag,interval,v)); } else { molien(L[2..size(L)],newring,intvec(mol_flag,interval,v)); } return(L[1]); } //----------- computing Molien series in the straight forward way ------------ if (ch==0) { if (typeof(#[1])<>"matrix") { "ERROR: the parameters must be a list of matrices and maybe an "; return(); } int n=nrows(#[1]); if (n<>nvars(br)) { "ERROR: the number of variables of the basering needs to be the same"; " as the dimension of the matrices"; return(); } if (n<>ncols(#[1])) { "ERROR: matrices need to be square and of the same dimensions"; return(); } matrix vars=matrix(maxideal(1)); // creating an nx1-matrix containing the vars=transpose(vars); // variables of the ring - matrix A(1)=#[1]*vars; // calculating the first ring mapping - // A(1) will contain the Reynolds // operator - poly v1=vars[1,1]; // the Molien series will be in terms of // the first variable of the current // ring matrix I=diag(1,n); matrix A(2)[1][2]; // A(2) will contain the Molien series - A(2)[1,1]=1; // A(2)[1,1] will be the numerator matrix G(1)=#[1]; // G(k) are elements of the group - A(2)[1,2]=det(I-v1*(G(1))); // A(2)[1,2] will be the denominator - matrix s; // will help us canceling in the // fraction poly p; // will contain the denominator of the // new term of the Molien series int i=1; for (int j=2;j<=gen_num;j++) // this loop adds the parameters to the { // group, leaving out doubles and // checking whether the parameters are // compatible with the task of the // procedure if (not(typeof(#[j])=="matrix")) { "ERROR: the parameters must be a list of matrices and maybe an "; return(); } if ((n!=nrows(#[j])) or (n!=ncols(#[j]))) { "ERROR: matrices need to be square and of the same dimensions"; return(); } if (unique(G(1..i),#[j])) { i++; matrix G(i)=#[j]; A(1)=concat(A(1),#[j]*vars); // adding ring homomorphisms to A(1) - p=det(I-v1*#[j]); // denominator of new term - A(2)[1,1]=A(2)[1,1]*p+A(2)[1,2]; // expanding A(2)[1,1]/A(2)[1,2] +1/p A(2)[1,2]=A(2)[1,2]*p; if (interval<>0) // canceling common terms of denominator { if ((i div interval)*interval==i) // and enumerator { s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() these A(2)[1,1]=-s[2,1]; // three lines should be replaced by the A(2)[1,2]=s[1,1]; // following three // p=gcd(A(2)[1,1],A(2)[1,2]); // A(2)[1,1]=A(2)[1,1]/p; // A(2)[1,2]=A(2)[1,2]/p; } } } } int g=i; // G(1)..G(i) are generators without // doubles - g generally is the number // of elements in the group so far - j=i; // j is the number of new elements that // we use as factors int k, m, l; if (v) { ""; " Generating the entire matrix group. Whenever a new group element is found,"; " the corresponding ring homomorphism of the Reynolds operator and the"; " corresponding term of the Molien series is generated."; ""; } //----------- computing 1/det(I-xE) whenever a new element E is found -------- while (1) { l=0; // l is the number of products we get in // one going for (m=g-j+1;m<=g;m=m+1) { for (k=1;k<=i;k++) { l++; matrix P(l)=G(k)*G(m); // possible new element } } j=0; for (k=1;k<=l;k++) { if (unique(G(1..g),P(k))) { j++; // a new factor for next run g++; matrix G(g)=P(k); // a new group element - A(1)=concat(A(1),P(k)*vars); // adding new mapping to A(1) p=det(I-v1*P(k)); // denominator of new term A(2)[1,1]=A(2)[1,1]*p+A(2)[1,2]; A(2)[1,2]=A(2)[1,2]*p; // expanding A(2)[1,1]/A(2)[1,2] + 1/p - if (interval<>0) // canceling common terms of denominator { if ((g div interval)*interval==g) // and enumerator { s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() A(2)[1,1]=-s[2,1]; // these three lines should be replaced A(2)[1,2]=s[1,1]; // by the following three // p=gcd(A(2)[1,1],A(2)[1,2]); // A(2)[1,1]=A(2)[1,1]/p; // A(2)[1,2]=A(2)[1,2]/p; } } if (v) { " Group element ",g," has been found."; } } kill P(k); } if (j==0) // when we didn't add any new elements { break; // in one run through the while loop } // we are done } if (v) { if (g<=i) { " There are only ",g," group elements."; } ""; } A(1)=transpose(A(1)); // when we evaluate the Reynolds operator // later on, we actually want 1xn // matrices if (interval==0) // canceling common terms of denominator { // and enumerator - s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() A(2)[1,1]=-s[2,1]; // these three lines should be replaced A(2)[1,2]=s[1,1]; // by the following three // p=gcd(A(2)[1,1],A(2)[1,2]); // A(2)[1,1]=A(2)[1,1]/p; // A(2)[1,2]=A(2)[1,2]/p; } if (interval<>0) // canceling common terms of denominator { if ((g div interval)*interval<>g) // and enumerator { s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() A(2)[1,1]=-s[2,1]; // these three lines should be replaced A(2)[1,2]=s[1,1]; // by the following three // p=gcd(A(2)[1,1],A(2)[1,2]); // A(2)[1,1]=A(2)[1,1]/p; // A(2)[1,2]=A(2)[1,2]/p; } } map slead=br,ideal(0); s=slead(A(2)); A(2)[1,1]=1/s[1,1]*A(2)[1,1]; // numerator and denominator have to have A(2)[1,2]=1/s[1,2]*A(2)[1,2]; // a constant term of 1 if (v) { " Now we are done calculating Molien series and Reynolds operator."; ""; } return(A(1..2)); } //------------------------ simulating characteristic 0 ----------------------- else // if ch<>0 and mol_flag<>0 { if (typeof(#[1])<>"matrix") { "ERROR: the parameters must be a list of matrices and maybe an "; return(); } int n=nrows(#[1]); if (n<>nvars(br)) { "ERROR: the number of variables of the basering needs to be the same"; " as the dimension of the matrices"; return(); } if (n<>ncols(#[1])) { "ERROR: matrices need to be square and of the same dimensions"; return(); } matrix vars=matrix(maxideal(1)); // creating an nx1-matrix containing the vars=transpose(vars); // variables of the ring - matrix A(1)=#[1]*vars; // calculating the first ring mapping - // A(1) will contain the Reynolds // operator string chst=charstr(br); for (int i=1;i<=size(chst);i++) { if (chst[i]==",") { break; } } if (minpoly==0) { if (i>size(chst)) { execute("ring "+newring+"=0,("+varstr(br)+"),("+ordstr(br)+")"); } else { chst=chst[i..size(chst)]; execute ("ring "+newring+"=(0"+chst+"),("+varstr(br)+"),("+ordstr(br)+")"); } } else { string minp=string(minpoly); minp=minp[2..size(minp)-1]; chst=chst[i..size(chst)]; execute("ring "+newring+"=(0"+chst+"),("+varstr(br)+"),("+ordstr(br)+")"); execute("minpoly="+minp); } poly v1=var(1); // the Molien series will be in terms of // the first variable of the current // ring matrix I=diag(1,n); int o; setring br; matrix G(1)=#[1]; string links, rechts; string stM(1)=string(#[1]); for (o=1;o<=size(stM(1));o++) { if (stM(1)[o]==" ") { links=stM(1)[1..o-1]; rechts=stM(1)[o+1..size(stM(1))]; stM(1)=links+rechts; } } setring `newring`; execute("matrix G(1)["+string(n)+"]["+string(n)+"]="+stM(1)); matrix A(2)[1][2]; // A(2) will contain the Molien series - A(2)[1,1]=1; // A(2)[1,1] will be the numerator A(2)[1,2]=det(I-v1*(G(1))); // A(2)[1,2] will be the denominator - matrix s; // will help us canceling in the // fraction poly p; // will contain the denominator of the // new term of the Molien series i=1; for (int j=2;j<=gen_num;j++) // this loop adds the parameters to the { // group, leaving out doubles and // checking whether the parameters are // compatible with the task of the // procedure setring br; if (not(typeof(#[j])=="matrix")) { "ERROR: the parameters must be a list of matrices and maybe an "; return(); } if ((n!=nrows(#[j])) or (n!=ncols(#[j]))) { "ERROR: matrices need to be square and of the same dimensions"; return(); } if (unique(G(1..i),#[j])) { i++; matrix G(i)=#[j]; A(1)=concat(A(1),G(i)*vars); // adding ring homomorphisms to A(1) string stM(i)=string(G(i)); for (o=1;o<=size(stM(i));o++) { if (stM(i)[o]==" ") { links=stM(i)[1..o-1]; rechts=stM(i)[o+1..size(stM(i))]; stM(i)=links+rechts; } } setring `newring`; execute("matrix G(i)["+string(n)+"]["+string(n)+"]="+stM(i)); p=det(I-v1*G(i)); // denominator of new term - A(2)[1,1]=A(2)[1,1]*p+A(2)[1,2]; // expanding A(2)[1,1]/A(2)[1,2] +1/p A(2)[1,2]=A(2)[1,2]*p; if (interval<>0) // canceling common terms of denominator { if ((i div interval)*interval==i) // and enumerator { s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() these A(2)[1,1]=-s[2,1]; // three lines should be replaced by the A(2)[1,2]=s[1,1]; // following three // p=gcd(A(2)[1,1],A(2)[1,2]); // A(2)[1,1]=A(2)[1,1]/p; // A(2)[1,2]=A(2)[1,2]/p; } } setring br; } } int g=i; // G(1)..G(i) are generators without // doubles - g generally is the number // of elements in the group so far - j=i; // j is the number of new elements that // we use as factors int k, m, l; if (v) { ""; " Generating the entire matrix group. Whenever a new group element is found,"; " the corresponding ring homomorphism of the Reynolds operator and the"; " corresponding term of the Molien series is generated."; ""; } // taking all elements in a ring of characteristic 0 and computing the terms // of the Molien series there while (1) { l=0; // l is the number of products we get in // one going for (m=g-j+1;m<=g;m++) { for (k=1;k<=i;k++) { l++; matrix P(l)=G(k)*G(m); // possible new element } } j=0; for (k=1;k<=l;k++) { if (unique(G(1..g),P(k))) { j++; // a new factor for next run g++; matrix G(g)=P(k); // a new group element - A(1)=concat(A(1),G(g)*vars); // adding new mapping to A(1) string stM(g)=string(G(g)); for (o=1;o<=size(stM(g));o++) { if (stM(g)[o]==" ") { links=stM(g)[1..o-1]; rechts=stM(g)[o+1..size(stM(g))]; stM(g)=links+rechts; } } setring `newring`; execute("matrix G(g)["+string(n)+"]["+string(n)+"]="+stM(g)); p=det(I-v1*G(g)); // denominator of new term A(2)[1,1]=A(2)[1,1]*p+A(2)[1,2]; A(2)[1,2]=A(2)[1,2]*p; // expanding A(2)[1,1]/A(2)[1,2] + 1/p - if (interval<>0) // canceling common terms of denominator { if ((g div interval)*interval==g) // and enumerator { s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() A(2)[1,1]=-s[2,1]; // these three lines should be replaced A(2)[1,2]=s[1,1]; // by the following three // p=gcd(A(2)[1,1],A(2)[1,2]); // A(2)[1,1]=A(2)[1,1]/p; // A(2)[1,2]=A(2)[1,2]/p; } } if (v) { " Group element ",g," has been found."; } setring br; } kill P(k); } if (j==0) // when we didn't add any new elements { break; // in one run through the while loop } // we are done } if (v) { if (g<=i) { " There are only ",g," group elements."; } ""; } A(1)=transpose(A(1)); // when we evaluate the Reynolds operator // later on, we actually want 1xn // matrices setring `newring`; if (interval==0) // canceling common terms of denominator { // and enumerator - s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() A(2)[1,1]=-s[2,1]; // these three lines should be replaced A(2)[1,2]=s[1,1]; // by the following three // p=gcd(A(2)[1,1],A(2)[1,2]); // A(2)[1,1]=A(2)[1,1]/p; // A(2)[1,2]=A(2)[1,2]/p; } if (interval<>0) // canceling common terms of denominator { if ((g div interval)*interval<>g) // and enumerator { s=matrix(syz(ideal(A(2)))); // once gcd() is faster than syz() A(2)[1,1]=-s[2,1]; // these three lines should be replaced A(2)[1,2]=s[1,1]; // by the following three // p=gcd(A(2)[1,1],A(2)[1,2]); // A(2)[1,1]=A(2)[1,1]/p; // A(2)[1,2]=A(2)[1,2]/p; } } map slead=`newring`,ideal(0); s=slead(A(2)); A(2)[1,1]=1/s[1,1]*A(2)[1,1]; // numerator and denominator have to have A(2)[1,2]=1/s[1,2]*A(2)[1,2]; // a constant term of 1 if (v) { " Now we are done calculating Molien series and Reynolds operator."; ""; } matrix M=A(2); kill G(1..g), s, slead, p, v1, I, A(2); export `newring`; // we keep the ring where we computed the export M; // the Molien series such that we can setring br; // keep it return(A(1)); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; " note the case of prime characteristic"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; matrix REY,M=reynolds_molien(A); print(REY); print(M); ring S=3,(x,y,z),dp; string newring="Qadjoint"; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; matrix REY=reynolds_molien(A,newring); print(REY); setring Finvar::Qadjoint; print(M); setring S; kill Finvar::Qadjoint; } /////////////////////////////////////////////////////////////////////////////// proc partial_molien (matrix M, int n, list #) "USAGE: partial_molien(M,n[,p]); M: a 1x2 , n: an indicating number of terms in the expansion, p: an optional ASSUME: M is the return value of molien or the second return value of reynolds_molien, p ought to be the second return value of a previous run of partial_molien and avoids recalculating known terms RETURN: n terms (type ) of the partial expansion of the Molien series (first n if there is no third parameter given, otherwise the next n terms depending on a previous calculation) and an intermediate result (type ) of the calculation to be used as third parameter in a next run of partial_molien THEORY: The following calculation is implemented: @format (1+a1x+a2x^2+...+anx^n)/(1+b1x+b2x^2+...+bmx^m)=(1+(a1-b1)x+... (1+b1x+b2x^2+...+bmx^m) ----------------------- (a1-b1)x+(a2-b2)x^2+... (a1-b1)x+b1(a1-b1)x^2+... @end format EXAMPLE: example partial_molien; shows an example " { poly A(2); // A(2) will contain the return value of // the intermediate result if (char(basering)<>0) { "ERROR: you have to change to a basering of characteristic 0, one in"; " which the Molien series is defined"; } if (ncols(M)==2 && nrows(M)==1 && n>0 && size(#)<2) { def br=basering; // keeping track of the old ring map slead=br,ideal(0); matrix s=slead(M); if (s[1,1]<>1 || s[1,2]<>1) { "ERROR: the constant terms of enumerator and denominator are not 1"; return(); } if (size(#)==0) { A(2)=M[1,1]; // if a third parameter is not given, the // intermediate result from the last run // corresponds to the numerator - we need } // its smallest term else { if (typeof(#[1])=="poly") { A(2)=#[1]; // if a third term is given we 'start' } // with its smallest term else { "ERROR: as third parameter expected"; return(); } } poly A(1)=M[1,2]; // denominator of Molien series (for now) string mp=string(minpoly); execute("ring R=("+charstr(br)+"),("+varstr(br)+"),ds;"); if (mp!="0") { execute("minpoly=number("+mp+");"); } poly A(1)=0; // A(1) will contain the sum of n terms - poly min; // min will be our smallest term - poly A(2)=fetch(br,A(2)); // fetching A(2) and M[1,2] into R poly den=fetch(br,A(1)); for (int i=1; i<=n; i++) // getting n terms and adding them up { min=lead(A(2)); A(1)=A(1)+min; A(2)=A(2)-min*den; } setring br; // moving A(1) and A(2) back in the A(1)=fetch(R,A(1)); // actual ring for output A(2)=fetch(R,A(2)); return(A(1..2)); } else { "ERROR: the first parameter has to be a 1x2-matrix, i.e. the matrix"; " returned by the procedure 'reynolds_molien', the second one"; " should be > 0 and there should be no more than 3 parameters;" return(); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; matrix REY,M=reynolds_molien(A); poly p(1..2); p(1..2)=partial_molien(M,5); p(1); p(1..2)=partial_molien(M,5,p(2)); p(1); } /////////////////////////////////////////////////////////////////////////////// proc evaluate_reynolds (matrix REY, ideal I) "USAGE: evaluate_reynolds(REY,I); REY: a representing the Reynolds operator, I: an arbitrary ASSUME: REY is the first return value of group_reynolds() or reynolds_molien() RETURNS: image of the polynomials defining I under the Reynolds operator (type ) NOTE: the characteristic of the coefficient field of the polynomial ring should not divide the order of the finite matrix group THEORY: REY has been constructed in such a way that each row serves as a ring mapping of which the Reynolds operator is made up. EXAMPLE: example evaluate_reynolds; shows an example " { def br=basering; int n=nvars(br); if (ncols(REY)==n) { int m=nrows(REY); // we need m to 'cut' the ring // homomorphisms 'out' of REY and to // divide by the group order in the end int num_poly=ncols(I); matrix MI=matrix(I); matrix MiI[1][num_poly]; map pREY; matrix rowREY[1][n]; for (int i=1;i<=m;i++) { rowREY=REY[i,1..n]; pREY=br,ideal(rowREY); // f is now the i-th ring homomorphism MiI=pREY(MI)+MiI; } MiI=(1/number(m))*MiI; return(ideal(MiI)); } else { "ERROR: the number of columns in the should be the same as the"; " number of variables in the basering; in fact it should be first"; " return value of group_reynolds() or reynolds_molien()."; return(); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); ideal I=x2,y2,z2; print(evaluate_reynolds(L[1],I)); } /////////////////////////////////////////////////////////////////////////////// proc invariant_basis (int g,list #) "USAGE: invariant_basis(g,G1,G2,...); g: an indicating of which degree (>0) the homogeneous basis shoud be, G1,G2,...: generating a finite matrix group RETURNS: the basis (type ) of the space of invariants of degree g THEORY: A general polynomial of degree g is generated and the generators of the matrix group applied. The difference ought to be 0 and this way a system of linear equations is created. It is solved by computing syzygies. EXAMPLE: example invariant_basis; shows an example " { if (g<=0) { "ERROR: the first parameter should be > 0"; return(); } def br=basering; ideal vars = maxideal(1); ideal mon=sort(maxideal(g))[1]; // needed for constructing a general int m=ncols(mon); // homogeneous polynomial of degree g mon=sort(mon,intvec(m..1))[1]; int a=size(#); int i; int n=nvars(br); int DGB = degBound; //---------------------- checking that the input is ok ----------------------- for (i=1;i<=a;i++) { if (typeof(#[i])=="matrix") { if (nrows(#[i])==n && ncols(#[i])==n) { matrix G(i)=#[i]; } else { "ERROR: the number of variables of the base ring needs to be the same"; " as the dimension of the square matrices"; return(); } } else { "ERROR: the last parameters should be a list of matrices"; return(); } } //---------------------------------------------------------------------------- ring tmpR = char(br),(p(1..m)),dp; def T = br+tmpR; setring T; // execute("ring T=("+charstr(br)+"),("+varstr(br)+",p(1..m)),lp;"); // p(1..m) are the general coefficients of the general polynomial of degree g ideal vars = fetch(br,vars); map f; ideal mon=imap(br,mon); poly P=0; for (i=m;i>=1;i--) { P=P+p(i)*mon[i]; // P is the general polynomial } ideal I; // will help substituting variables in P // by linear combinations of variables - poly Pnew,temp; // Pnew is P with substitutions - matrix S[m*a][m]; // will contain system of linear // equations int j,k; //------------------- building the system of linear equations ---------------- for (i=1;i<=a;i++) { I=ideal(matrix(vars)*transpose(imap(br,G(i)))); I=I,p(1..m); f=T,I; Pnew=f(P); for (j=1;j<=m;j++) { temp=P/mon[j]-Pnew/mon[j]; for (k=1;k<=m;k++) { S[m*(i-1)+j,k]=temp/p(k); } } } //---------------------------------------------------------------------------- setring br; map f=T,ideal(0); matrix S=f(S); degBound=1; matrix s=matrix(syz(S)); // s contains a basis of the space of // solutions - ideal I=ideal(matrix(mon)*s); // I contains a basis of homogeneous if (I[1]<>0) // invariants of degree d { for (i=1;i<=ncols(I);i++) { I[i]=I[i]/leadcoef(I[i]); // setting leading coefficients to 1 } } degBound=DGB; return(I); } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; print(invariant_basis(2,A)); } /////////////////////////////////////////////////////////////////////////////// proc invariant_basis_reynolds (matrix REY,int d,list #) "USAGE: invariant_basis_reynolds(REY,d[,flags]); REY: a representing the Reynolds operator, d: an indicating of which degree (>0) the homogeneous basis shoud be, flags: an optional with two entries: its first component gives the dimension of the space (default <0 meaning unknown) and its second component is used as the number of polynomials that should be mapped to invariants during one call of evaluate_reynolds if the dimension of the space is unknown or the number such that number x dimension polynomials are mapped to invariants during one call of evaluate_reynolds ASSUME: REY is the first return value of group_reynolds() or reynolds_molien() and flags[1] given by partial_molien RETURN: the basis (type ) of the space of invariants of degree d THEORY: Monomials of degree d are mapped to invariants with the Reynolds operator. A linearly independent set is generated with the help of minbase. EXAMPLE: example invariant_basis_reynolds; shows an example " { //---------------------- checking that the input is ok ----------------------- if (d<=0) { " ERROR: the second parameter should be > 0"; return(); } if (size(#)>1) { " ERROR: there should be at most three parameters"; return(); } if (size(#)==1) { if (typeof(#[1])<>"intvec") { " ERROR: the third parameter should be of type "; return(); } if (size(#[1])<>2) { " ERROR: there should be two components in "; return(); } else { int cd=#[1][1]; int step_fac=#[1][2]; } if (step_fac<=0) { " ERROR: the second component of should be > 0"; return(); } if (cd==0) { return(ideal(0)); } } else { int step_fac=1; int cd=-1; } if (ncols(REY)<>nvars(basering)) { "ERROR: the number of columns in the should be the same as the"; " number of variables in the basering; in fact it should be first"; " return value of group_reynolds() or reynolds_molien()."; return(); } //---------------------------------------------------------------------------- ideal mon=sort(maxideal(d))[1]; int DEGB = degBound; degBound=d; int j=ncols(mon); mon=sort(mon,intvec(j..1))[1]; ideal B; // will contain the basis if (cd<0) { if (step_fac>j) // all of mon will be mapped to { B=evaluate_reynolds(REY,mon); // invariants at once B=minbase(B); degBound=DEGB; return(B); } } else { if (step_fac*cd>j) // all of mon will be mapped to { B=evaluate_reynolds(REY,mon); // invariants at once B=minbase(B); degBound=DEGB; return(B); } } int i,k; int upper_bound=0; int lower_bound=0; ideal part_mon; // a part of mon of size step_fac*cd while (1) { lower_bound=upper_bound+1; if (cd<0) { upper_bound=upper_bound+step_fac; } else { upper_bound=upper_bound+step_fac*cd; } if (upper_bound>j) { upper_bound=j; } part_mon=mon[lower_bound..upper_bound]; B=minbase(B+evaluate_reynolds(REY,part_mon)); if ((ncols(B)==cd and B[1]<>0) or upper_bound==j) { degBound=DEGB; return(B); } } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; intvec flags=0,1,0; matrix REY,M=reynolds_molien(A,flags); flags=8,6; print(invariant_basis_reynolds(REY,6,flags)); } /////////////////////////////////////////////////////////////////////////////// // This procedure generates linearly independent invariant polynomials of // degree d that do not reduce to 0 modulo the primary invariants. It does this // by applying the Reynolds operator to the monomials returned by kbase(sP,d). // The result is used when computing secondary invariants. /////////////////////////////////////////////////////////////////////////////// proc sort_of_invariant_basis (ideal sP,matrix REY,int d,int step_fac) { ideal mon=kbase(sP,d); int DEGB=degBound; degBound=d; int j=ncols(mon); int i; mon=sort(mon,intvec(j..1))[1]; ideal B; // will contain the "sort of basis" if (step_fac>j) { B=compress(evaluate_reynolds(REY,mon)); for (i=1;i<=ncols(B);i++) // those are taken our that are o mod sP { if (reduce(B[i],sP)==0) { B[i]=0; } } B=minbase(B); // here are the linearly independent ones degBound=DEGB; return(B); } int upper_bound=0; int lower_bound=0; ideal part_mon; // parts of mon while (1) { lower_bound=upper_bound+1; upper_bound=upper_bound+step_fac; if (upper_bound>j) { upper_bound=j; } part_mon=mon[lower_bound..upper_bound]; part_mon=compress(evaluate_reynolds(REY,part_mon)); for (i=1;i<=ncols(part_mon);i++) { if (reduce(part_mon[i],sP)==0) { part_mon[i]=0; } } B=minbase(B+part_mon); // here are the linearly independent ones if (upper_bound==j) { degBound=DEGB; return(B); } } } /////////////////////////////////////////////////////////////////////////////// // Procedure returning the succeeding vector after vec. It is used to list // all the vectors of Z^n with first nonzero entry 1. They are listed by // increasing sum of the absolute value of their entries. /////////////////////////////////////////////////////////////////////////////// proc next_vector(intmat vec) { int n=ncols(vec); // p: >0, n: <0, p0: >=0, n0: <=0 for (int i=1;i<=n;i++) // finding out which is the first { if (vec[1,i]<>0) // component <>0 { break; } } intmat new[1][n]; if (i>n) // 0,...,0 --> 1,0....,0 { new[1,1]=1; return(new); } if (i==n) // 0,...,1 --> 1,1,0,...,0 { new[1,1..2]=1,1; return(new); } if (i==n-1) { if (vec[1,n]==0) // 0,...,0,1,0 --> 0,...,0,1 { new[1,n]=1; return(new); } if (vec[1,n]>0) // 0,..,0,1,p --> 0,...,0,1,-p { new[1,1..n]=vec[1,1..n-1],-vec[1,n]; return(new); } new[1,1..2]=1,1-vec[1,n]; // 0,..,0,1,n --> 1,1-n,0,..,0 return(new); } if (i>1) { intmat temp[1][n-i+1]=vec[1,i..n]; // 0,...,0,1,*,...,* --> 1,*,...,* temp=next_vector(temp); new[1,i..n]=temp[1,1..n-i+1]; return(new); } // case left: 1,*,...,* for (i=2;i<=n;i++) { if (vec[1,i]>0) // make first positive negative and { vec[1,i]=-vec[1,i]; // return return(vec); } else { vec[1,i]=-vec[1,i]; // make all negatives before positives } // positive } for (i=2;i<=n-1;i++) // case: 1,p,...,p after 1,n,...,n { if (vec[1,i]>0) { vec[1,2]=vec[1,i]-1; // shuffleing things around... if (i>2) // same sum of absolute values of entries { vec[1,i]=0; } vec[1,i+1]=vec[1,i+1]+1; return(vec); } } // case left: 1,0,...,0 --> 1,1,0,...,0 new[1,2..3]=1,vec[1,n]; // and: 1,0,...,0,1 --> 0,1,1,0,...,0 return(new); } /////////////////////////////////////////////////////////////////////////////// // Maps integers to elements of the base field. It is only called if the base // field is of prime characteristic. If the base field has q elements // (depending on minpoly) 1..q is mapped to those q elements. /////////////////////////////////////////////////////////////////////////////// proc int_number_map (int i) { int p=char(basering); if (minpoly==0) // if no minpoly is given, we have p { i=i%p; // elements in the field return(number(i)); } int d=pardeg(minpoly); if (i<0) { int bool=1; i=(-1)*i; } i=i%p^d; // base field has p^d elements - number a=par(1); // a is the root of the minpoly - we have number out=0; // to construct a linear combination of int j=1; // a^k int k; while (1) { if (i0. /////////////////////////////////////////////////////////////////////////////// proc p_search (int n,int d,ideal B,int cd,ideal P,ideal sP,int i,int dif,int dB,ideal CI) { def br=basering; degBound=0; matrix vec(1)[1][cd]; // starting with 0-vector - intmat new[1][cd]; // the coefficients for the next // combination - matrix pnew[1][cd]; // new needs to be mapped into br - int counter=1; // counts the vectors int j; int p=char(br); if (minpoly<>0) { int ext_deg=pardeg(minpoly); // field has p^d elements } else { int ext_deg=1; // field has p^d elements } poly test_poly; // the linear combination to test int test_dim; ring R=0,x,dp; // just to calculate next variable // bound - number bound=(number(p)^(ext_deg*cd)-1)/(number(p)^ext_deg-1)+1; // this is how many linearly independent // vectors of size cd exist having // entries in the base field of br setring br; intvec h; // Hilbert series int k=i+1; if (ncols(B)bound) // otherwise, we are done { setring br; new=next_vector(new); for (j=1;j<=cd;j++) { pnew[1,j]=int_number_map(new[1,j]); // mapping an integer into br } if (unique(vec(1..counter),pnew)) //checking whether we tried pnew before { counter++; matrix vec(counter)=pnew; // keeping track of the ones we tried - test_poly=(vec(counter)*tB)[1,1]; // linear combination - // degBound=dB; TEST=sP+ideal(test_poly); attrib(TEST,"isSB",1); test_dim=dim(TEST); // degBound=0; if (n-test_dim==k) // the dimension has been lowered by one { sP=TEST; setring R; break; } // degBound=dB; //TEST=std(sP+ideal(test_poly)); // should soon to be replaced by next // line TEST=std(sP,test_poly); // or, better: // TEST=std(sP,test_poly,h); // Hilbert driven std-calculation test_dim=dim(TEST); // degBound=0; if (n-test_dim==k) // the dimension has been lowered by one { sP=TEST; setring R; break; } } setring R; } if (number(counter)<=bound) { setring br; P[k]=test_poly; // test_poly ist added to primary } // invariants else { setring br; CI=CI[1..size(CI)-1]; return(P,sP,CI,dB-d+1); } k++; } return(P,sP,CI,dB); } /////////////////////////////////////////////////////////////////////////////// proc primary_char0 (matrix REY,matrix M,list #) "USAGE: primary_char0(REY,M[,v]); REY: a representing the Reynolds operator, M: a 1x2 representing the Molien series, v: an optional ASSUME: REY is the first return value of group_reynolds or reynolds_molien and M the one of molien or the second one of reynolds_molien DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring THEORY: Bases of homogeneous invariants are generated successively and those are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see paper \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_char0; shows an example " { degBound=0; if (char(basering)<>0) { "ERROR: primary_char0 should only be used with rings of characteristic 0."; return(); } //----------------- checking input and setting verbose mode ------------------ if (size(#)>1) { "ERROR: primary_char0 can only have three parameters."; return(); } if (size(#)==1) { if (typeof(#[1])<>"int") { "ERROR: The third parameter should be of type ."; return(); } else { int v=#[1]; } } else { int v=0; } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(REY)<>n) { "ERROR: First parameter ought to be the Reynolds operator." return(); } if (ncols(M)<>2 or nrows(M)<>1) { "ERROR: Second parameter ought to be the Molien series." return(); } //---------------------------------------------------------------------------- if (v && voice<>2) { " We can start looking for primary invariants..."; ""; } if (v && voice==2) { ""; } //------------------------- initializing variables --------------------------- int dB; poly p(1..2); // p(1) will be used for single terms of // the partial expansion, p(2) to store p(1..2)=partial_molien(M,1); // the intermediate result - poly v1=var(1); // we need v1 to split off coefficients // in the partial expansion of M (which // is in terms of the first variable) - int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,sPplus,CI,B; // P: will contain primary invariants, // Pplus: P+B, CI: a complete // intersection with the same Hilbert // function as P ideal sP=groebner(P); dB=1; // used as degree bound int i=0; //-------------- loop that searches for primary invariants ------------------ while(1) // repeat until n primary invariants are { // found - p(1..2)=partial_molien(M,1,p(2)); // next term of the partial expansion - d=deg(p(1)); // degree where we'll search - cd=int(coef(p(1),v1)[2,1]); // dimension of the homogeneous space of // inviarants of degree d if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis_reynolds(REY,d,intvec(cd,6)); // basis of invariants of // degree d if (B[1]<>0) { Pplus=P+B; sPplus=groebner(Pplus); newdim=dim(sPplus); dif=n-i-newdim; } else { dif=0; } if (dif<>0) // we have to find dif new primary { // invariants if (cd<>dif) { P,sP,CI,dB=search(n,d,B,cd,P,sP,i,dif,dB,CI); // searching for dif invariants } else // i.e. we can take all of B { for(j=i+1;j<=i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; sP=sPplus; } if (v) { for (j=1;j<=dif;j++) { " We find: "+string(P[i+j]); } } i=i+dif; if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } return(matrix(P)); } } // done with degree d } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; matrix REY,M=reynolds_molien(A); matrix P=primary_char0(REY,M); print(P); } /////////////////////////////////////////////////////////////////////////////// proc primary_charp (matrix REY,string ring_name,list #) "USAGE: primary_charp(REY,ringname[,v]); REY: a representing the Reynolds operator, ringname: a giving the name of a ring where the Molien series is stored, v: an optional ASSUME: REY is the first return value of group_reynolds or reynolds_molien and ringname gives the name of a ring of characteristic 0 that has been created by molien or reynolds_molien DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring THEORY: Bases of homogeneous invariants are generated successively and those are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see paper \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_charp; shows an example " { degBound=0; // ---------------- checking input and setting verbose mode ------------------- if (char(basering)==0) { "ERROR: primary_charp should only be used with rings of characteristic p>0."; return(); } if (size(#)>1) { "ERROR: primary_charp can only have three parameters."; return(); } if (size(#)==1) { if (typeof(#[1])<>"int") { "ERROR: The third parameter should be of type ."; return(); } else { int v=#[1]; } } else { int v=0; } def br=basering; int n=nvars(br); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(REY)<>n) { "ERROR: First parameter ought to be the Reynolds operator." return(); } if (typeof(`ring_name`)<>"ring") { "ERROR: Second parameter ought to be ring where "; " the Molien series is stored."; return(); } //---------------------------------------------------------------------------- if (v && voice<>2) { " We can start looking for primary invariants..."; ""; } if (v && voice==2) { ""; } //----------------------- initializing variables ----------------------------- int dB; setring `ring_name`; // the Molien series is stores here - poly p(1..2); // p(1) will be used for single terms of // the partial expansion, p(2) to store p(1..2)=partial_molien(M,1); // the intermediate result - poly v1=var(1); // we need v1 to split off coefficients // in the partial expansion of M (which // is in terms of the first variable) setring br; int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,sPplus,CI,B; // P: will contain primary invariants, // Pplus: P+B, CI: a complete // intersection with the same Hilbert // function as P ideal sP=groebner(P); dB=1; // used as degree bound int i=0; //---------------- loop that searches for primary invariants ----------------- while(1) // repeat until n primary invariants are { // found setring `ring_name`; p(1..2)=partial_molien(M,1,p(2)); // next term of the partial expansion - d=deg(p(1)); // degree where we'll search - cd=int(coef(p(1),v1)[2,1]); // dimension of the homogeneous space of // inviarants of degree d setring br; if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis_reynolds(REY,d,intvec(cd,6)); // basis of invariants of // degree d if (ncols(B)0) { Pplus=P+B; sPplus=groebner(Pplus); newdim=dim(sPplus); dif=n-i-newdim; } else { dif=0; } if (dif<>0) // we have to find dif new primary { // invariants if (cd<>dif) { P,sP,CI,dB=p_search(n,d,B,cd,P,sP,i,dif,dB,CI); } else // i.e. we can take all of B { for(j=i+1;j>i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; sP=sPplus; } if (v) { for (j=1;j<=size(P)-i;j++) { " We find: "+string(P[i+j]); } } i=size(P); if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } return(matrix(P)); } } // done with degree d } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into char 3)"; echo=2; ring R=3,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); string newring="alskdfj"; molien(L[2..size(L)],newring); matrix P=primary_charp(L[1],newring); kill Finvar::`newring`; print(P); } /////////////////////////////////////////////////////////////////////////////// proc primary_char0_no_molien (matrix REY, list #) "USAGE: primary_char0_no_molien(REY[,v]); REY: a representing the Reynolds operator, v: an optional ASSUME: REY is the first return value of group_reynolds or reynolds_molien DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring and an listing some of the degrees where no non-trivial homogeneous invariants are to be found THEORY: Bases of homogeneous invariants are generated successively and those are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see paper \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_char0_no_molien; shows an example " { degBound=0; //-------------- checking input and setting verbose mode --------------------- if (char(basering)<>0) { "ERROR: primary_char0_no_molien should only be used with rings of"; " characteristic 0."; return(); } if (size(#)>1) { "ERROR: primary_char0_no_molien can only have two parameters."; return(); } if (size(#)==1) { if (typeof(#[1])<>"int") { "ERROR: The second parameter should be of type ."; return(); } else { int v=#[1]; } } else { int v=0; } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(REY)<>n) { "ERROR: First parameter ought to be the Reynolds operator." return(); } //---------------------------------------------------------------------------- if (v && voice<>2) { " We can start looking for primary invariants..."; ""; } if (v && voice==2) { ""; } //----------------------- initializing variables ----------------------------- int dB; int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,CI,B; // P: will contain primary invariants, // Pplus: P+B, CI: a complete // intersection with the same Hilbert // function as P ideal sP=groebner(P); dB=1; // used as degree bound - d=0; // initializing int i=0; intvec deg_vector; //------------------ loop that searches for primary invariants --------------- while(1) // repeat until n primary invariants are { // found - d++; // degree where we'll search if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis_reynolds(REY,d,intvec(-1,6)); // basis of invariants of // degree d if (B[1]<>0) { Pplus=P+B; newdim=dim(groebner(Pplus)); dif=n-i-newdim; } else { dif=0; deg_vector=deg_vector,d; } if (dif<>0) // we have to find dif new primary { // invariants cd=size(B); if (cd<>dif) { P,sP,CI,dB=search(n,d,B,cd,P,sP,i,dif,dB,CI); } else // i.e. we can take all of B { for(j=i+1;j<=i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; sP=groebner(P); } if (v) { for (j=1;j<=dif;j++) { " We find: "+string(P[i+j]); } } i=i+dif; if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } if (deg_vector==0) { return(matrix(P)); } else { return(matrix(P),compress(deg_vector)); } } } // done with degree d else { if (v) { " None here..."; } } } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); list l=primary_char0_no_molien(L[1]); print(l[1]); } /////////////////////////////////////////////////////////////////////////////// proc primary_charp_no_molien (matrix REY, list #) "USAGE: primary_charp_no_molien(REY[,v]); REY: a representing the Reynolds operator, v: an optional ASSUME: REY is the first return value of group_reynolds or reynolds_molien DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring and an listing some of the degrees where no non-trivial homogeneous invariants are to be found THEORY: Bases of homogeneous invariants are generated successively and those are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see paper \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_charp_no_molien; shows an example " { degBound=0; //----------------- checking input and setting verbose mode ------------------ if (char(basering)==0) { "ERROR: primary_charp_no_molien should only be used with rings of"; " characteristic p>0."; return(); } if (size(#)>1) { "ERROR: primary_charp_no_molien can only have two parameters."; return(); } if (size(#)==1) { if (typeof(#[1])<>"int") { "ERROR: The second parameter should be of type ."; return(); } else { int v=#[1]; } } else { int v=0; } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(REY)<>n) { "ERROR: First parameter ought to be the Reynolds operator." return(); } //---------------------------------------------------------------------------- if (v && voice<>2) { " We can start looking for primary invariants..."; ""; } if (v && voice==2) { ""; } //-------------------- initializing variables -------------------------------- int dB; int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,sPplus,CI,B; // P: will contain primary invariants, // Pplus: P+B, CI: a complete // intersection with the same Hilbert // function as P ideal sP=groebner(P); dB=1; // used as degree bound - d=0; // initializing int i=0; intvec deg_vector; //------------------ loop that searches for primary invariants --------------- while(1) // repeat until n primary invariants are { // found - d++; // degree where we'll search if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis_reynolds(REY,d,intvec(-1,6)); // basis of invariants of // degree d if (B[1]<>0) { Pplus=P+B; sPplus=groebner(Pplus); newdim=dim(sPplus); dif=n-i-newdim; } else { dif=0; deg_vector=deg_vector,d; } if (dif<>0) // we have to find dif new primary { // invariants cd=size(B); if (cd<>dif) { P,sP,CI,dB=p_search(n,d,B,cd,P,sP,i,dif,dB,CI); } else // i.e. we can take all of B { for(j=i+1;j<=i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; sP=sPplus; } if (v) { for (j=1;j<=size(P)-i;j++) { " We find: "+string(P[i+j]); } } i=size(P); if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } if (deg_vector==0) { return(matrix(P)); } else { return(matrix(P),compress(deg_vector)); } } } // done with degree d else { if (v) { " None here..."; } } } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into char 3)"; echo=2; ring R=3,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); list l=primary_charp_no_molien(L[1]); print(l[1]); } /////////////////////////////////////////////////////////////////////////////// proc primary_charp_without (list #) "USAGE: primary_charp_without(G1,G2,...[,v]); G1,G2,...: generating a finite matrix group, v: an optional DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring THEORY: Bases of homogeneous invariants are generated successively and those are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see paper \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). No Reynolds operator or Molien series is used. EXAMPLE: example primary_charp_without; shows an example " { degBound=0; //--------------------- checking input and setting verbose mode -------------- if (char(basering)==0) { "ERROR: primary_charp_without should not be used with rings of"; " characteristic 0."; return(); } if (size(#)==0) { "ERROR: There are no parameters."; return(); } if (typeof(#[size(#)])=="int") { int v=#[size(#)]; int gen_num=size(#)-1; if (gen_num==0) { "ERROR: There are no generators of a finite matrix group given."; return(); } } else { int v=0; int gen_num=size(#); } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get for (int i=1;i<=gen_num;i++) { if (typeof(#[i])=="matrix") { if (nrows(#[i])<>n or ncols(#[i])<>n) { "ERROR: The number of variables of the base ring needs to be the same"; " as the dimension of the square matrices"; return(); } } else { "ERROR: The first parameters should be a list of matrices"; return(); } } //---------------------------------------------------------------------------- if (v && voice==2) { ""; } //---------------------------- initializing variables ------------------------ int dB; int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // by the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,sPplus,CI,B; // P: will contain primary invariants, // Pplus: P+B, CI: a complete // intersection with the same Hilbert // function as P ideal sP=groebner(P); dB=1; // used as degree bound - d=0; // initializing i=0; intvec deg_vector; //-------------------- loop that searches for primary invariants ------------- while(1) // repeat until n primary invariants are { // found - d++; // degree where we'll search if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis(d,#[1..gen_num]); // basis of invariants of degree d if (B[1]<>0) { Pplus=P+B; sPplus=groebner(Pplus); newdim=dim(sPplus); dif=n-i-newdim; } else { dif=0; deg_vector=deg_vector,d; } if (dif<>0) // we have to find dif new primary { // invariants cd=size(B); if (cd<>dif) { P,sP,CI,dB=p_search(n,d,B,cd,P,sP,i,dif,dB,CI); } else // i.e. we can take all of B { for(j=i+1;j<=i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; sP=sPplus; } if (v) { for (j=1;j<=size(P)-i;j++) { " We find: "+string(P[i+j]); } } i=size(P); if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } return(matrix(P)); } } // done with degree d else { if (v) { " None here..."; } } } } example { "EXAMPLE:"; echo=2; ring R=2,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; matrix P=primary_charp_without(A); print(P); } /////////////////////////////////////////////////////////////////////////////// proc primary_invariants (list #) "USAGE: primary_invariants(G1,G2,...[,flags]); G1,G2,...: generating a finite matrix group, flags: an optional with three entries, if the first one equals 0 (also the default), the programme attempts to compute the Molien series and Reynolds operator, if it equals 1, the programme is told that the Molien series should not be computed, if it equals -1 characteristic 0 is simulated, i.e. the Molien series is computed as if the base field were characteristic 0 (the user must choose a field of large prime characteristic, e.g. 32003) and if the first one is anything else, it means that the characteristic of the base field divides the group order, the second component should give the size of intervals between canceling common factors in the expansion of the Molien series, 0 (the default) means only once after generating all terms, in prime characteristic also a negative number can be given to indicate that common factors should always be canceled when the expansion is simple (the root of the extension field occurs not among the coefficients) DISPLAY: information about the various stages of the programme if the third flag does not equal 0 RETURN: primary invariants (type ) of the invariant ring and if computable Reynolds operator (type ) and Molien series (type ) or ring name (type string) where the Molien series can be found in the char p case; if the first flag is 1 and we are in the non-modular case then an is returned giving some of the degrees where no non-trivial homogeneous invariants can be found THEORY: Bases of homogeneous invariants are generated successively and those are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see paper \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_invariants; shows an example " { // ----------------- checking input and setting flags ------------------------ if (size(#)==0) { "ERROR: There are no parameters."; return(); } int ch=char(basering); // the algorithms depend very much on the // characteristic of the ground field int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get int gen_num; int mol_flag,v; if (typeof(#[size(#)])=="intvec") { if (size(#[size(#)])<>3) { "ERROR: should have three entries."; return(); } gen_num=size(#)-1; mol_flag=#[size(#)][1]; if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag==-1))) { "ERROR: the second component of should be >=0"; return(); } int interval=#[size(#)][2]; v=#[size(#)][3]; if (gen_num==0) { "ERROR: There are no generators of a finite matrix group given."; return(); } } else { gen_num=size(#); mol_flag=0; int interval=0; v=0; } for (int i=1;i<=gen_num;i++) { if (typeof(#[i])=="matrix") { if (nrows(#[i])<>n or ncols(#[i])<>n) { "ERROR: The number of variables of the base ring needs to be the same"; " as the dimension of the square matrices"; return(); } } else { "ERROR: The first parameters should be a list of matrices"; return(); } } //---------------------------------------------------------------------------- if (mol_flag==0) { if (ch==0) { matrix REY,M=reynolds_molien(#[1..gen_num],intvec(mol_flag,interval,v)); // one will contain Reynolds operator and // the other enumerator and denominator // of Molien series matrix P=primary_char0(REY,M,v); return(P,REY,M); } else { list L=group_reynolds(#[1..gen_num],v); if (L[1]<>0) // testing whether we are in the modular { string newring="aksldfalkdsflkj"; // case if (minpoly==0) { if (v) { " We are dealing with the non-modular case."; } if (typeof(L[2])=="int") { molien(L[3..size(L)],newring,L[2],intvec(mol_flag,interval,v)); } else { molien(L[2..size(L)],newring,intvec(mol_flag,interval,v)); } matrix P=primary_charp(L[1],newring,v); return(P,L[1],newring); } else { if (v) { " Since it is impossible for this programme to calculate the Molien series for"; " invariant rings over extension fields of prime characteristic, we have to"; " continue without it."; ""; } list l=primary_charp_no_molien(L[1],v); if (size(l)==2) { return(l[1],L[1],l[2]); } else { return(l[1],L[1]); } } } else // the modular case { if (v) { " There is also no Molien series, we can make use of..."; ""; " We can start looking for primary invariants..."; ""; } return(primary_charp_without(#[1..gen_num],v)); } } } if (mol_flag==1) // the user wants no calculation of the { list L=group_reynolds(#[1..gen_num],v); // Molien series if (ch==0) { list l=primary_char0_no_molien(L[1],v); if (size(l)==2) { return(l[1],L[1],l[2]); } else { return(l[1],L[1]); } } else { if (L[1]<>0) // testing whether we are in the modular { list l=primary_charp_no_molien(L[1],v); // case if (size(l)==2) { return(l[1],L[1],l[2]); } else { return(l[1],L[1]); } } else // the modular case { if (v) { " We can start looking for primary invariants..."; ""; } return(primary_charp_without(#[1..gen_num],v)); } } } if (mol_flag==-1) { if (ch==0) { "ERROR: Characteristic 0 can only be simulated in characteristic p>>0."; return(); } list L=group_reynolds(#[1..gen_num],v); string newring="aksldfalkdsflkj"; molien(L[2..size(L)],newring,intvec(1,interval,v)); matrix P=primary_charp(L[1],newring,v); return(P,L[1],newring); } else // the user specified that the { if (ch==0) // characteristic divides the group order { "ERROR: The characteristic cannot divide the group order when it is 0."; return(); } if (v) { ""; } return(primary_charp_without(#[1..gen_num],v)); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=primary_invariants(A); print(L[1]); } /////////////////////////////////////////////////////////////////////////////// // This procedure finds dif primary invariants in degree d. It returns all // primary invariants found so far. The coefficients lie in a field of // characteristic 0. /////////////////////////////////////////////////////////////////////////////// proc search_random (int n,int d,ideal B,int cd,ideal P,int i,int dif,int dB,ideal CI,int max) { string answer; degBound=0; int j,k,test_dim,flag; matrix test_matrix[1][dif]; // the linear combination to test intvec h; // Hilbert series for (j=i+1;j<=i+dif;j++) { CI=CI+ideal(var(j)^d); // homogeneous polynomial of the same // degree as the one we're looking for // is added } ideal TEST; // h=hilb(std(CI),1); dB=dB+dif*(d-1); // used as degBound while (1) { test_matrix=matrix(B)*random(max,cd,dif); // degBound=dB; TEST=P+ideal(test_matrix); attrib(TEST,"isSB",1); test_dim=dim(TEST); // degBound=0; if (n-test_dim==i+dif) { break; } // degBound=dB; test_dim=dim(groebner(TEST)); // test_dim=dim(std(TEST,h)); // Hilbert driven std-calculation // degBound=0; if (n-test_dim==i+dif) { break; } else { "HELP: The ",dif," random combination(s) of the ",cd," basis elements with"; " coefficients in the range from -",max," to ",max," did not lower the"; " dimension by ",dif,". You can abort, try again or give a new range:"; answer=""; while (answer<>"n " && answer<>"y ") { " Do you want to abort (y/n)?"; answer=read(""); } if (answer=="y ") { flag=1; break; } answer=""; while (answer<>"n " && answer<>"y ") { " Do you want to try again (y/n)?"; answer=read(""); } if (answer=="n ") { flag=1; while (flag) { " Give a new > ",max," that bounds the range of coefficients:"; answer=read(""); for (j=1;j<=size(answer)-1;j++) { for (k=0;k<=9;k++) { if (answer[j]==string(k)) { break; } } if (k>9) { flag=1; break; } flag=0; } if (not(flag)) { execute("test_dim="+string(answer[1..size(answer)])); if (test_dim<=max) { flag=1; } else { max=test_dim; } } } } } } if (not(flag)) { P[(i+1)..(i+dif)]=test_matrix[1,1..dif]; } return(P,CI,dB); } /////////////////////////////////////////////////////////////////////////////// // This procedure finds at most dif primary invariants in degree d. It returns // all primary invariants found so far. The coefficients lie in the field of // characteristic p>0. /////////////////////////////////////////////////////////////////////////////// proc p_search_random (int n,int d,ideal B,int cd,ideal P,int i,int dif,int dB,ideal CI,int max) { string answer; degBound=0; int j,k,test_dim,flag; matrix test_matrix[1][dif]; // the linear combination to test intvec h; // Hilbert series ideal TEST; while (dif>0) { for (j=i+1;j<=i+dif;j++) { CI=CI+ideal(var(j)^d); // homogeneous polynomial of the same // degree as the one we're looking for // is added } // h=hilb(std(CI),1); dB=dB+dif*(d-1); // used as degBound test_matrix=matrix(B)*random(max,cd,dif); // degBound=dB; TEST=P+ideal(test_matrix); attrib(TEST,"isSB",1); test_dim=dim(TEST); // degBound=0; if (n-test_dim==i+dif) { break; } // degBound=dB; test_dim=dim(groebner(TEST)); // test_dim=dim(std(TEST,h)); // Hilbert driven std-calculation // degBound=0; if (n-test_dim==i+dif) { break; } else { "HELP: The ",dif," random combination(s) of the ",cd," basis elements with"; " coefficients in the range from -",max," to ",max," did not lower the"; " dimension by ",dif,". You can abort, try again, lower the number of"; " combinations searched for by 1 or give a larger coefficient range:"; answer=""; while (answer<>"n " && answer<>"y ") { " Do you want to abort (y/n)?"; answer=read(""); } if (answer=="y ") { flag=1; break; } answer=""; while (answer<>"n " && answer<>"y ") { " Do you want to try again (y/n)?"; answer=read(""); } if (answer=="n ") { answer=""; while (answer<>"n " && answer<>"y ") { " Do you want to lower the number of combinations by 1 (y/n)?"; answer=read(""); } if (answer=="y ") { dif=dif-1; } else { flag=1; while (flag) { " Give a new > ",max," that bounds the range of coefficients:"; answer=read(""); for (j=1;j<=size(answer)-1;j++) { for (k=0;k<=9;k++) { if (answer[j]==string(k)) { break; } } if (k>9) { flag=1; break; } flag=0; } if (not(flag)) { execute("test_dim="+string(answer[1..size(answer)])); if (test_dim<=max) { flag=1; } else { max=test_dim; } } } } } } CI=CI[1..i]; dB=dB-dif*(d-1); } if (dif && not(flag)) { P[(i+1)..(i+dif)]=test_matrix[1,1..dif]; } if (dif && flag) { P[n+1]=0; } return(P,CI,dB); } /////////////////////////////////////////////////////////////////////////////// proc primary_char0_random (matrix REY,matrix M,int max,list #) "USAGE: primary_char0_random(REY,M,r[,v]); REY: a representing the Reynolds operator, M: a 1x2 representing the Molien series, r: an where -|r| to |r| is the range of coefficients of the random combinations of bases elements, v: an optional ASSUME: REY is the first return value of group_reynolds or reynolds_molien and M the one of molien or the second one of reynolds_molien DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring THEORY: Bases of homogeneous invariants are generated successively and random linear combinations are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_char0_random; shows an example " { degBound=0; if (char(basering)<>0) { "ERROR: primary_char0_random should only be used with rings of"; " characteristic 0."; return(); } //----------------- checking input and setting verbose mode ------------------ if (size(#)>1) { "ERROR: primary_char0_random can only have four parameters."; return(); } if (size(#)==1) { if (typeof(#[1])<>"int") { "ERROR: The fourth parameter should be of type ."; return(); } else { int v=#[1]; } } else { int v=0; } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(REY)<>n) { "ERROR: First parameter ought to be the Reynolds operator." return(); } if (ncols(M)<>2 or nrows(M)<>1) { "ERROR: Second parameter ought to be the Molien series." return(); } //---------------------------------------------------------------------------- if (v && voice<>2) { " We can start looking for primary invariants..."; ""; } if (v && voice==2) { ""; } //------------------------- initializing variables --------------------------- int dB; poly p(1..2); // p(1) will be used for single terms of // the partial expansion, p(2) to store p(1..2)=partial_molien(M,1); // the intermediate result - poly v1=var(1); // we need v1 to split off coefficients // in the partial expansion of M (which // is in terms of the first variable) - int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,CI,B; // P: will contain primary invariants, // Pplus: P+B,CI: a complete // intersection with the same Hilbert // function as P - dB=1; // used as degree bound int i=0; //-------------- loop that searches for primary invariants ------------------ while(1) // repeat until n primary invariants are { // found - p(1..2)=partial_molien(M,1,p(2)); // next term of the partial expansion - d=deg(p(1)); // degree where we'll search - cd=int(coef(p(1),v1)[2,1]); // dimension of the homogeneous space of // inviarants of degree d if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis_reynolds(REY,d,intvec(cd,6)); // basis of invariants of // degree d if (B[1]<>0) { Pplus=P+B; newdim=dim(groebner(Pplus)); dif=n-i-newdim; } else { dif=0; } if (dif<>0) // we have to find dif new primary { // invariants if (cd<>dif) { P,CI,dB=search_random(n,d,B,cd,P,i,dif,dB,CI,max); // searching for } // dif invariants - else // i.e. we can take all of B { for(j=i+1;j>i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; } if (ncols(P)==i) { "WARNING: The return value is not a set of primary invariants, but"; " polynomials qualifying as the first ",i," primary invariants."; return(matrix(P)); } if (v) { for (j=1;j<=dif;j++) { " We find: "+string(P[i+j]); } } i=i+dif; if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } return(matrix(P)); } } // done with degree d } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; matrix REY,M=reynolds_molien(A); matrix P=primary_char0_random(REY,M,1); print(P); } /////////////////////////////////////////////////////////////////////////////// proc primary_charp_random (matrix REY,string ring_name,int max,list #) "USAGE: primary_charp_random(REY,ringname,r[,v]); REY: a representing the Reynolds operator, ringname: a giving the name of a ring where the Molien series is stored, r: an where -|r| to |r| is the range of coefficients of the random combinations of bases elements, v: an optional ASSUME: REY is the first return value of group_reynolds or reynolds_molien and ringname gives the name of a ring of characteristic 0 that has been created by molien or reynolds_molien DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring THEORY: Bases of homogeneous invariants are generated successively and random linear combinations are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_charp_random; shows an example " { degBound=0; // ---------------- checking input and setting verbose mode ------------------ if (char(basering)==0) { "ERROR: primary_charp_random should only be used with rings of"; " characteristic p>0."; return(); } if (size(#)>1) { "ERROR: primary_charp_random can only have four parameters."; return(); } if (size(#)==1) { if (typeof(#[1])<>"int") { "ERROR: The fourth parameter should be of type ."; return(); } else { int v=#[1]; } } else { int v=0; } def br=basering; int n=nvars(br); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(REY)<>n) { "ERROR: First parameter ought to be the Reynolds operator." return(); } if (typeof(`ring_name`)<>"ring") { "ERROR: Second parameter ought to the name of a ring where the Molien"; " is stored."; return(); } //---------------------------------------------------------------------------- if (v && voice<>2) { " We can start looking for primary invariants..."; ""; } if (v && voice==2) { ""; } //----------------------- initializing variables ----------------------------- int dB; setring `ring_name`; // the Molien series is stores here - poly p(1..2); // p(1) will be used for single terms of // the partial expansion, p(2) to store p(1..2)=partial_molien(M,1); // the intermediate result - poly v1=var(1); // we need v1 to split off coefficients // in the partial expansion of M (which // is in terms of the first variable) setring br; int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,CI,B; // P: will contain primary invariants, // Pplus: P+B, CI: a complete // intersection with the same Hilbert // function as P - dB=1; // used as degree bound int i=0; //---------------- loop that searches for primary invariants ----------------- while(1) // repeat until n primary invariants are { // found setring `ring_name`; p(1..2)=partial_molien(M,1,p(2)); // next term of the partial expansion - d=deg(p(1)); // degree where we'll search - cd=int(coef(p(1),v1)[2,1]); // dimension of the homogeneous space of // inviarants of degree d setring br; if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis_reynolds(REY,d,intvec(cd,6)); // basis of invariants of // degree d if (B[1]<>0) { Pplus=P+B; newdim=dim(groebner(Pplus)); dif=n-i-newdim; } else { dif=0; } if (dif<>0) // we have to find dif new primary { // invariants if (cd<>dif) { P,CI,dB=p_search_random(n,d,B,cd,P,i,dif,dB,CI,max); } else // i.e. we can take all of B { for(j=i+1;j>i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; } if (ncols(P)==n+1) { "WARNING: The first return value is not a set of primary invariants,"; " but polynomials qualifying as the first ",i," primary invariants."; return(matrix(P)); } if (v) { for (j=1;j<=size(P)-i;j++) { " We find: "+string(P[i+j]); } } i=size(P); if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } return(matrix(P)); } } // done with degree d } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into char 3)"; echo=2; ring R=3,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); string newring="alskdfj"; molien(L[2..size(L)],newring); matrix P=primary_charp_random(L[1],newring,1); kill Finvar::`newring`; print(P); } /////////////////////////////////////////////////////////////////////////////// proc primary_char0_no_molien_random (matrix REY, int max, list #) "USAGE: primary_char0_no_molien_random(REY,r[,v]); REY: a representing the Reynolds operator, r: an where -|r| to |r| is the range of coefficients of the random combinations of bases elements, v: an optional ASSUME: REY is the first return value of group_reynolds or reynolds_molien DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring and an listing some of the degrees where no non-trivial homogeneous invariants are to be found THEORY: Bases of homogeneous invariants are generated successively and random linear combinations are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_char0_no_molien_random; shows an example " { degBound=0; //-------------- checking input and setting verbose mode --------------------- if (char(basering)<>0) { "ERROR: primary_char0_no_molien_random should only be used with rings of"; " characteristic 0."; return(); } if (size(#)>1) { "ERROR: primary_char0_no_molien_random can only have three parameters."; return(); } if (size(#)==1) { if (typeof(#[1])<>"int") { "ERROR: The third parameter should be of type ."; return(); } else { int v=#[1]; } } else { int v=0; } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(REY)<>n) { "ERROR: First parameter ought to be the Reynolds operator." return(); } //---------------------------------------------------------------------------- if (v && voice<>2) { " We can start looking for primary invariants..."; ""; } if (v && voice==2) { ""; } //----------------------- initializing variables ----------------------------- int dB; int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,CI,B; // P: will contain primary invariants, // Pplus: P+B, CI: a complete // intersection with the same Hilbert // function as P - dB=1; // used as degree bound - d=0; // initializing int i=0; intvec deg_vector; //------------------ loop that searches for primary invariants --------------- while(1) // repeat until n primary invariants are { // found - d++; // degree where we'll search if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis_reynolds(REY,d,intvec(-1,6)); // basis of invariants of // degree d if (B[1]<>0) { Pplus=P+B; newdim=dim(groebner(Pplus)); dif=n-i-newdim; } else { dif=0; deg_vector=deg_vector,d; } if (dif<>0) // we have to find dif new primary { // invariants cd=size(B); if (cd<>dif) { P,CI,dB=search_random(n,d,B,cd,P,i,dif,dB,CI,max); } else // i.e. we can take all of B { for(j=i+1;j<=i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; } if (ncols(P)==i) { "WARNING: The first return value is not a set of primary invariants,"; " but polynomials qualifying as the first ",i," primary invariants."; return(matrix(P)); } if (v) { for (j=1;j<=dif;j++) { " We find: "+string(P[i+j]); } } i=i+dif; if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } if (deg_vector==0) { return(matrix(P)); } else { return(matrix(P),compress(deg_vector)); } } } // done with degree d else { if (v) { " None here..."; } } } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); list l=primary_char0_no_molien_random(L[1],1); print(l[1]); } /////////////////////////////////////////////////////////////////////////////// proc primary_charp_no_molien_random (matrix REY, int max, list #) "USAGE: primary_charp_no_molien_random(REY,r[,v]); REY: a representing the Reynolds operator, r: an where -|r| to |r| is the range of coefficients of the random combinations of bases elements, v: an optional ASSUME: REY is the first return value of group_reynolds or reynolds_molien DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring and an listing some of the degrees where no non-trivial homogeneous invariants are to be found THEORY: Bases of homogeneous invariants are generated successively and random linear combinations are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_charp_no_molien_random; shows an example " { degBound=0; //----------------- checking input and setting verbose mode ------------------ if (char(basering)==0) { "ERROR: primary_charp_no_molien_random should only be used with rings of"; " characteristic p>0."; return(); } if (size(#)>1) { "ERROR: primary_charp_no_molien_random can only have three parameters."; return(); } if (size(#)==1) { if (typeof(#[1])<>"int") { "ERROR: The third parameter should be of type ."; return(); } else { int v=#[1]; } } else { int v=0; } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(REY)<>n) { "ERROR: First parameter ought to be the Reynolds operator." return(); } //---------------------------------------------------------------------------- if (v && voice<>2) { " We can start looking for primary invariants..."; ""; } if (v && voice==2) { ""; } //-------------------- initializing variables -------------------------------- int dB; int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,CI,B; // P: will contain primary invariants, // Pplus: P+B, CI: a complete // intersection with the same Hilbert // function as P - dB=1; // used as degree bound - d=0; // initializing int i=0; intvec deg_vector; //------------------ loop that searches for primary invariants --------------- while(1) // repeat until n primary invariants are { // found - d++; // degree where we'll search if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis_reynolds(REY,d,intvec(-1,6)); // basis of invariants of // degree d if (B[1]<>0) { Pplus=P+B; newdim=dim(groebner(Pplus)); dif=n-i-newdim; } else { dif=0; deg_vector=deg_vector,d; } if (dif<>0) // we have to find dif new primary { // invariants cd=size(B); if (cd<>dif) { P,CI,dB=p_search_random(n,d,B,cd,P,i,dif,dB,CI,max); } else // i.e. we can take all of B { for(j=i+1;j<=i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; } if (ncols(P)==n+1) { "WARNING: The first return value is not a set of primary invariants,"; " but polynomials qualifying as the first ",i," primary invariants."; return(matrix(P)); } if (v) { for (j=1;j<=size(P)-i;j++) { " We find: "+string(P[i+j]); } } i=size(P); if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } if (deg_vector==0) { return(matrix(P)); } else { return(matrix(P),compress(deg_vector)); } } } // done with degree d else { if (v) { " None here..."; } } } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into char 3)"; echo=2; ring R=3,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=group_reynolds(A); list l=primary_charp_no_molien_random(L[1],1); print(l[1]); } /////////////////////////////////////////////////////////////////////////////// proc primary_charp_without_random (list #) "USAGE: primary_charp_without_random(G1,G2,...,r[,v]); G1,G2,...: generating a finite matrix group, r: an where -|r| to |r| is the range of coefficients of the random combinations of bases elements, v: an optional DISPLAY: information about the various stages of the programme if v does not equal 0 RETURN: primary invariants (type ) of the invariant ring THEORY: Bases of homogeneous invariants are generated successively and random linear combinations are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). No Reynolds operator or Molien series is used. EXAMPLE: example primary_charp_without_random; shows an example " { degBound=0; //--------------------- checking input and setting verbose mode -------------- if (char(basering)==0) { "ERROR: primary_charp_without_random should only be used with rings of"; " characteristic 0."; return(); } if (size(#)<2) { "ERROR: There are too few parameters."; return(); } if (typeof(#[size(#)])=="int" && typeof(#[size(#)-1])=="int") { int v=#[size(#)]; int max=#[size(#)-1]; int gen_num=size(#)-2; if (gen_num==0) { "ERROR: There are no generators of a finite matrix group given."; return(); } } else { if (typeof(#[size(#)])=="int") { int max=#[size(#)]; int v=0; int gen_num=size(#)-1; } else { "ERROR: The last parameter should be an ."; return(); } } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get for (int i=1;i<=gen_num;i++) { if (typeof(#[i])=="matrix") { if (nrows(#[i])<>n or ncols(#[i])<>n) { "ERROR: The number of variables of the base ring needs to be the same"; " as the dimension of the square matrices"; return(); } } else { "ERROR: The first parameters should be a list of matrices"; return(); } } //---------------------------------------------------------------------------- if (v && voice==2) { ""; } //---------------------------- initializing variables ------------------------ int dB; int j,d,cd,newdim,dif; // d: current degree, cd: dimension of // space of invariants of degree d, // newdim: dimension the ideal generated // the primary invariants plus basis // elements, dif=n-i-newdim, i.e. the // number of new primary invairants that // should be added in this degree - ideal P,Pplus,CI,B; // P: will contain primary invariants, // Pplus: P+B, CI: a complete // intersection with the same Hilbert // function as P - dB=1; // used as degree bound - d=0; // initializing i=0; intvec deg_vector; //-------------------- loop that searches for primary invariants ------------- while(1) // repeat until n primary invariants are { // found - d++; // degree where we'll search if (v) { " Computing primary invariants in degree ",d,":"; } B=invariant_basis(d,#[1..gen_num]); // basis of invariants of degree d if (B[1]<>0) { Pplus=P+B; newdim=dim(groebner(Pplus)); dif=n-i-newdim; } else { dif=0; deg_vector=deg_vector,d; } if (dif<>0) // we have to find dif new primary { // invariants cd=size(B); if (cd<>dif) { P,CI,dB=p_search_random(n,d,B,cd,P,i,dif,dB,CI,max); } else // i.e. we can take all of B { for(j=i+1;j<=i+dif;j++) { CI=CI+ideal(var(j)^d); } dB=dB+dif*(d-1); P=Pplus; } if (ncols(P)==n+1) { "WARNING: The first return value is not a set of primary invariants,"; " but polynomials qualifying as the first ",i," primary invariants."; return(matrix(P)); } if (v) { for (j=1;j<=size(P)-i;j++) { " We find: "+string(P[i+j]); } } i=size(P); if (i==n) // found all primary invariants { if (v) { ""; " We found all primary invariants."; ""; } return(matrix(P)); } } // done with degree d else { if (v) { " None here..."; } } } } example { "EXAMPLE:"; echo=2; ring R=2,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; matrix P=primary_charp_without_random(A,1); print(P); } /////////////////////////////////////////////////////////////////////////////// proc primary_invariants_random (list #) "USAGE: primary_invariants_random(G1,G2,...,r[,flags]); G1,G2,...: generating a finite matrix group, r: an where -|r| to |r| is the range of coefficients of the random combinations of bases elements, flags: an optional with three entries, if the first one equals 0 (also the default), the programme attempts to compute the Molien series and Reynolds operator, if it equals 1, the programme is told that the Molien series should not be computed, if it equals -1 characteristic 0 is simulated, i.e. the Molien series is computed as if the base field were characteristic 0 (the user must choose a field of large prime characteristic, e.g. 32003) and if the first one is anything else, it means that the characteristic of the base field divides the group order, the second component should give the size of intervals between canceling common factors in the expansion of the Molien series, 0 (the default) means only once after generating all terms, in prime characteristic also a negative number can be given to indicate that common factors should always be canceled when the expansion is simple (the root of the extension field does not occur among the coefficients) DISPLAY: information about the various stages of the programme if the third flag does not equal 0 RETURN: primary invariants (type ) of the invariant ring and if computable Reynolds operator (type ) and Molien series (type ), if the first flag is 1 and we are in the non-modular case then an is returned giving some of the degrees where no non-trivial homogeneous invariants can be found THEORY: Bases of homogeneous invariants are generated successively and random linear combinations are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). EXAMPLE: example primary_invariants_random; shows an example " { // ----------------- checking input and setting flags ------------------------ if (size(#)<2) { "ERROR: There are too few parameters."; return(); } int ch=char(basering); // the algorithms depend very much on the // characteristic of the ground field int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get int gen_num; int mol_flag,v; if (typeof(#[size(#)])=="intvec" && typeof(#[size(#)-1])=="int") { if (size(#[size(#)])<>3) { "ERROR: should have three entries."; return(); } gen_num=size(#)-2; mol_flag=#[size(#)][1]; if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0))) { "ERROR: the second component of should be >=0"; return(); } int interval=#[size(#)][2]; v=#[size(#)][3]; int max=#[size(#)-1]; if (gen_num==0) { "ERROR: There are no generators of a finite matrix group given."; return(); } } else { if (typeof(#[size(#)])=="int") { gen_num=size(#)-1; mol_flag=0; int interval=0; v=0; int max=#[size(#)]; } else { "ERROR: If the two last parameters are not and , the last"; " parameter should be an ."; return(); } } for (int i=1;i<=gen_num;i++) { if (typeof(#[i])=="matrix") { if (nrows(#[i])<>n or ncols(#[i])<>n) { "ERROR: The number of variables of the base ring needs to be the same"; " as the dimension of the square matrices"; return(); } } else { "ERROR: The first parameters should be a list of matrices"; return(); } } //---------------------------------------------------------------------------- if (mol_flag==0) { if (ch==0) { matrix REY,M=reynolds_molien(#[1..gen_num],intvec(0,interval,v)); // one will contain Reynolds operator and // the other enumerator and denominator // of Molien series matrix P=primary_char0_random(REY,M,max,v); return(P,REY,M); } else { list L=group_reynolds(#[1..gen_num],v); if (L[1]<>0) // testing whether we are in the modular { string newring="aksldfalkdsflkj"; // case if (minpoly==0) { if (v) { " We are dealing with the non-modular case."; } if (typeof(L[2])=="int") { molien(L[3..size(L)],newring,L[2],intvec(0,interval,v)); } else { molien(L[2..size(L)],newring,intvec(0,interval,v)); } matrix P=primary_charp_random(L[1],newring,max,v); return(P,L[1],newring); } else { if (v) { " Since it is impossible for this programme to calculate the Molien series for"; " invariant rings over extension fields of prime characteristic, we have to"; " continue without it."; ""; } list l=primary_charp_no_molien_random(L[1],max,v); if (size(l)==2) { return(l[1],L[1],l[2]); } else { return(l[1],L[1]); } } } else // the modular case { if (v) { " There is also no Molien series, we can make use of..."; ""; " We can start looking for primary invariants..."; ""; } return(primary_charp_without_random(#[1..gen_num],max,v)); } } } if (mol_flag==1) // the user wants no calculation of the { list L=group_reynolds(#[1..gen_num],v); // Molien series if (ch==0) { list l=primary_char0_no_molien_random(L[1],max,v); if (size(l)==2) { return(l[1],L[1],l[2]); } else { return(l[1],L[1]); } } else { if (L[1]<>0) // testing whether we are in the modular { list l=primary_charp_no_molien_random(L[1],max,v); // case if (size(l)==2) { return(l[1],L[1],l[2]); } else { return(l[1],L[1]); } } else // the modular case { if (v) { " We can start looking for primary invariants..."; ""; } return(primary_charp_without_random(#[1..gen_num],max,v)); } } } if (mol_flag==-1) { if (ch==0) { "ERROR: Characteristic 0 can only be simulated in characteristic p>>0."; return(); } list L=group_reynolds(#[1..gen_num],v); string newring="aksldfalkdsflkj"; if (typeof(L[2])=="int") { molien(L[3..size(L)],newring,L[2],intvec(0,interval,v)); } else { molien(L[2..size(L)],newring,intvec(0,interval,v)); } matrix P=primary_charp_random(L[1],newring,max,v); return(P,L[1],newring); } else // the user specified that the { if (ch==0) // characteristic divides the group order { "ERROR: The characteristic cannot divide the group order when it is 0."; return(); } if (v) { ""; } return(primary_charp_without_random(#[1..gen_num],max,v)); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=primary_invariants_random(A,1); print(L[1]); } /////////////////////////////////////////////////////////////////////////////// proc concat_intmat(intmat A,intmat B) { int n=nrows(A); int m1=ncols(A); int m2=ncols(B); intmat C[n][m1+m2]; C[1..n,1..m1]=A[1..n,1..m1]; C[1..n,m1+1..m1+m2]=B[1..n,1..m2]; return(C); } /////////////////////////////////////////////////////////////////////////////// proc power_products(intvec deg_vec,int d) "USAGE: power_products(dv,d); dv: an giving the degrees of homogeneous polynomials, d: the degree of the desired power products RETURN: a size(dv)*m where each column ought to be interpreted as containing the exponents of the corresponding polynomials. The product of the powers is then homogeneous of degree d. EXAMPLE: example power_products; shows an example " { ring R=0,x,dp; if (d<=0) { "ERROR: The may not be <= 0"; return(); } int d_neu,j,nc; int s=size(deg_vec); intmat PP[s][1]; intmat TEST[s][1]; for (int i=1;i<=s;i++) { if (i<0) { "ERROR: The entries of may not be <= 0"; return(); } d_neu=d-deg_vec[i]; if (d_neu>0) { intmat PPd_neu=power_products(intvec(deg_vec[i..s]),d_neu); if (size(ideal(PPd_neu))<>0) { nc=ncols(PPd_neu); intmat PPd_neu_gross[s][nc]; PPd_neu_gross[i..s,1..nc]=PPd_neu[1..s-i+1,1..nc]; for (j=1;j<=nc;j++) { PPd_neu_gross[i,j]=PPd_neu_gross[i,j]+1; } PP=concat_intmat(PP,PPd_neu_gross); kill PPd_neu_gross; } kill PPd_neu; } if (d_neu==0) { intmat PPd_neu[s][1]; PPd_neu[i,1]=1; PP=concat_intmat(PP,PPd_neu); kill PPd_neu; } } if (matrix(PP)<>matrix(TEST)) { PP=compress(PP); } return(PP); } example { "EXAMPLE:"; echo=2; intvec dv=5,5,5,10,10; print(power_products(dv,10)); print(power_products(dv,7)); } /////////////////////////////////////////////////////////////////////////////// static proc old_secondary_char0 (matrix P, matrix REY, matrix M, list #) "USAGE: secondary_char0(P,REY,M[,v]); P: a 1xn with primary invariants, REY: a gxn representing the Reynolds operator, M: a 1x2 giving numerator and denominator of the Molien series, v: an optional ASSUME: n is the number of variables of the basering, g the size of the group, REY is the 1st return value of group_reynolds(), reynolds_molien() or the second one of primary_invariants(), M the return value of molien() or the second one of reynolds_molien() or the third one of primary_invariants() RETURN: secondary invariants of the invariant ring (type ) and irreducible secondary invariants (type ) DISPLAY: information if v does not equal 0 THEORY: The secondary invariants are calculated by finding a basis (in terms of monomials) of the basering modulo the primary invariants, mapping those to invariants with the Reynolds operator and using these images or their power products such that they are linearly independent modulo the primary invariants (see paper \"Some Algorithms in Invariant Theory of Finite Groups\" by Kemper and Steel (1997)). " { def br=basering; degBound=0; //----------------- checking input and setting verbose mode ------------------ if (char(br)<>0) { "ERROR: secondary_char0 should only be used with rings of characteristic 0."; return(); } int i; if (size(#)>0) { if (typeof(#[size(#)])=="int") { int v=#[size(#)]; } else { int v=0; } } else { int v=0; } int n=nvars(br); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(P)<>n) { "ERROR: The first parameter ought to be the matrix of the primary"; " invariants." return(); } if (ncols(REY)<>n) { "ERROR: The second parameter ought to be the Reynolds operator." return(); } if (ncols(M)<>2 or nrows(M)<>1) { "ERROR: The third parameter ought to be the Molien series." return(); } if (v && voice==2) { ""; } int j, m, counter; //- finding the polynomial giving number and degrees of secondary invariants - poly p=1; for (j=1;j<=n;j++) // calculating the denominator of the { p=p*(1-var(1)^deg(P[j])); // Hilbert series of the ring generated } // by the primary invariants - matrix s[1][2]=M[1,1]*p,M[1,2]; // s is used for canceling s=matrix(syz(ideal(s))); p=s[2,1]; // the polynomial telling us where to // search for secondary invariants map slead=br,ideal(0); p=1/slead(p)*p; // smallest term of p needs to be 1 if (v) { " Polynomial telling us where to look for secondary invariants:"; " "+string(p); ""; } matrix dimmat=coeffs(p,var(1)); // dimmat will contain the number of // secondary invariants, we need to find // of a certain degree - m=nrows(dimmat); // m-1 is the highest degree if (v) { "In degree 0 we have: 1"; ""; } //-------------------------- initializing variables -------------------------- intmat PP; poly pp; int k; intvec deg_vec; ideal sP=groebner(ideal(P)); ideal TEST,B,IS; ideal S=1; // 1 is the first secondary invariant - //--------------------- generating secondary invariants ---------------------- for (i=2;i<=m;i++) // going through dimmat - { if (int(dimmat[i,1])<>0) // when it is == 0 we need to find 0 { // elements in the current degree (i-1) if (v) { "Searching in degree ",i-1,", we need to find ",int(dimmat[i,1])," invariant(s)..."; } TEST=sP; counter=0; // we'll count up to degvec[i] if (IS[1]<>0) { PP=power_products(deg_vec,i-1); // finding power products of irreducible } // secondary invariants if (size(ideal(PP))<>0) { for (j=1;j<=ncols(PP);j++) // going through all the power products { pp=1; for (k=1;k<=nrows(PP);k++) { pp=pp*IS[1,k]^PP[k,j]; } if (reduce(pp,TEST)<>0) { S=S,pp; counter++; if (v) { " We find: "+string(pp); } if (int(dimmat[i,1])<>counter) { // TEST=std(TEST+ideal(NF(pp,TEST))); // should be replaced by next // line soon TEST=std(TEST,pp); } else { break; } } } } if (int(dimmat[i,1])<>counter) { B=sort_of_invariant_basis(sP,REY,i-1,int(dimmat[i,1])*6); // B contains // images of kbase(sP,i-1) under the // Reynolds operator that are linearly // independent and that don't reduce to // 0 modulo sP - if (counter==0 && ncols(B)==int(dimmat[i,1])) // then we can take all of { S=S,B; // B IS=IS+B; if (deg_vec[1]==0) { deg_vec=i-1; if (v) { " We find: "+string(B[1]); } for (j=2;j<=int(dimmat[i,1]);j++) { deg_vec=deg_vec,i-1; if (v) { " We find: "+string(B[j]); } } } else { for (j=1;j<=int(dimmat[i,1]);j++) { deg_vec=deg_vec,i-1; if (v) { " We find: "+string(B[j]); } } } } else { j=0; // j goes through all of B - while (int(dimmat[i,1])<>counter) // need to find dimmat[i,1] { // invariants that are linearly // independent modulo TEST j++; if (reduce(B[j],TEST)<>0) // B[j] should be added { S=S,B[j]; IS=IS+ideal(B[j]); if (deg_vec[1]==0) { deg_vec[1]=i-1; } else { deg_vec=deg_vec,i-1; } counter++; if (v) { " We find: "+string(B[j]); } if (int(dimmat[i,1])<>counter) { //TEST=std(TEST+ideal(NF(B[j],TEST))); // should be replaced by // next line TEST=std(TEST,B[j]); } } } } } if (v) { ""; } } } if (v) { " We're done!"; ""; } return(matrix(S),matrix(IS)); } /////////////////////////////////////////////////////////////////////////////// proc secondary_char0 (matrix P, matrix REY, matrix M, list #) "USAGE: secondary_char0(P,REY,M[,v][,\"old\"]); @* P: a 1xn with homogeneous primary invariants, where n is the number of variables of the basering; @* REY: a gxn representing the Reynolds operator, where g the size of the corresponding group; @* M: a 1x2 giving numerator and denominator of the Molien series; @* v: an optional ; @* \"old\": if this string occurs as (optional) parameter, then an old version of secondary_char0 is used (for downward compatibility) ASSUME: The characteristic of basering is zero; REY is the 1st return value of group_reynolds(), reynolds_molien() or the second one of primary_invariants(); @* M is the return value of molien() or the second one of reynolds_molien() or the third one of primary_invariants() RETURN: Homogeneous secondary invariants and irreducible secondary invariants of the invariant ring (both type ) DISPLAY: Information on the progress of the computations if v is an integer different from 0. THEORY: The secondary invariants are calculated by finding a basis (in terms of monomials) of the basering modulo the primary invariants, mapping those to invariants with the Reynolds operator. Among these images or their power products we pick secondary invariants using Groebner basis techniques (see S. King: Fast Computation of Secondary Invariants). The size of this set can be read off from the Molien series. NOTE: Secondary invariants are not uniquely determined by the given data. Specifically, the output of secondary_char0(P,REY,M,\"old\") will differ from the output of secondary_char0(P,REY,M). However, the ideal generated by the irreducible homogeneous secondary invariants will be the same in both cases. @* There are three internal parameters \"pieces\", \"MonStep\" and \"IrrSwitch\". The default values of the parameters should be fine in most cases. However, in some cases, different values may provide a better balance of memory consumption (smaller values) and speed (bigger values). SEE ALSO: irred_secondary_char0; EXAMPLE: example secondary_char0; shows an example " { //---------- Internal parameters, whose choice might improve the performance ----- int pieces = 3; // For generating reducible secondaries, blocks of #pieces# secondaries // are formed. // If this parameter is small, the memory consumption will decrease. int MonStep = 15; // The Reynolds operator is applied to blocks of #MonStep# monomials. // If this parameter is small, the memory consumption will decrease. int IrrSwitch = 7; // Up to degree #IrrSwitch#-1, we use a method for generating // irreducible secondaries that tends to produce a smaller output // (which is good for subsequent computations). However, this method // needs to much memory in high degrees, and so we use a sparser method // from degree #IrrSwitch# on. def br=basering; //----------------- checking input and setting verbose mode ------------------ if (char(br)<>0) { "ERROR: secondary_char0 can only be used with rings of characteristic 0."; " Try secondary_charp"; return(); } int i; if (size(#)>0) { if (typeof(#[1])=="int") { int v=#[1]; } else { int v=0; } } else { int v=0; } if (size(#)>0) { if (typeof(#[size(#)])=="string") { if (#[size(#)]=="old") { if (typeof(#[1])=="int") { matrix S,IS = old_secondary_char0(P,REY,M,#[1]); return(S,IS); } else { matrix S,IS = old_secondary_char0(P,REY,M); return(S,IS); } } else { "ERROR: If the last optional parameter is a string, it should be \"old\"."; return(matrix(ideal()),matrix(ideal())); } } } int n=nvars(br); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(P)<>n) { "ERROR: The first parameter ought to be the matrix of the primary"; " invariants."; return(); } if (ncols(REY)<>n) { "ERROR: The second parameter ought to be the Reynolds operator."; return(); } if (ncols(M)<>2 or nrows(M)<>1) { "ERROR: The third parameter ought to be the Molien series."; return(); } if (v && voice==2) { ""; } int j, m, counter, irrcounter; //- finding the polynomial giving number and degrees of secondary invariants - poly p=1; for (j=1;j<=n;j++) // calculating the denominator of the { p=p*(1-var(1)^deg(P[j])); // Hilbert series of the ring generated } // by the primary invariants - matrix s[1][2]=M[1,1]*p,M[1,2]; // s is used for canceling s=matrix(syz(ideal(s))); p=s[2,1]; // the polynomial telling us where to // search for secondary invariants map slead=br,ideal(0); p=1/slead(p)*p; // smallest [constant] term of // p needs to be 1 matrix dimmat=coeffs(p,var(1)); // dimmat will contain the number of // secondary invariants, we need to find // of a certain degree - m=nrows(dimmat); // m-1 is the highest degree if (v) { "We need to find"; for (j=1;j<=m;j++) { if (int(dimmat[j,1])<>1) { int(dimmat[j,1]), "secondary invariants in degree",j-1; } else { "1 secondary invariant in degree",j-1; } } } if (v) { "In degree 0 we have: 1"; ""; } //-------------------------- initializing variables -------------------------- ideal ProdCand; // contains products of secondary invariants, // i.e., candidates for reducible sec. inv. ideal Mul1,Mul2; int dgb=degBound; degBound = 0; intvec saveopt=option(get); option(redSB); ideal sP = groebner(ideal(P)); // This is the only explicit Groebner basis computation! ideal Reductor,SaveRed; // sP union Reductor is a Groebner basis up to degree i-1 ideal sP_Reductor; // will contain sP union Reductor. int sPOffset = ncols(sP); int SizeSave; list SSort; // sec. inv. first sorted by degree and then sorted by the // minimal degree of a non-constant invariant factor. list ISSort; // irr. sec. inv. sorted by degree int NrIS; poly helpP; ideal helpI; ideal Indicator; // will tell us which candidates for sec. inv. we can choose int helpint; int k,k2,k3,minD; int ii; int saveAttr; ideal mon,B,IS; // IS will contain all irr. sec. inv. for (i=1;i0) // when it is == 0 we need to find no { // elements in the current degree (i-1) if (v) { "Searching in degree ",i-1,", we need to find ",int(dimmat[i,1]), " invariant(s)..."; " Looking for Power Products..."; } sP_Reductor = sP; counter = 0; // we'll count up to dimmat[i,1] Reductor = ideal(0); helpint = 0; SaveRed = Reductor; SizeSave = 0; attrib(Reductor,"isSB",1); attrib(SaveRed,"isSB",1); // We start searching for reducible secondary invariants in degree i-1, i.e., those // that are power products of irreducible secondary invariants. // It suffices to restrict the search at products of one _irreducible_ sec. inv. (Mul1) // with some sec. inv. (Mul2). // Moreover, we avoid to consider power products twice since we take a product // into account only if the minimal degree of a non-constant invariant factor in "Mul2" is not // smaller than the degree of "Mul1". for (k=1;k"none") { Mul1 = ISSort[k]; } else { Mul1 = ideal(0); } if ((int(dimmat[i-k,1])>0) && (Mul1[1]<>0)) { for (minD=k;minD=k2*pieces) { for (k3=1;k3<=pieces;k3++) { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3]; } } else { for (k3=1;k3<=(attrib(SSort[i-k-1][minD],"size") mod pieces);k3++) { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3]; } } ProdCand = simplify(Mul1*Mul2,4); // sP union SaveRed union Reductor is a homogeneous Groebner basis // up to degree i-1. Indicator = reduce(ProdCand,sP_Reductor); // If Indicator[ii]<>0 then ProdCand[ii] can be taken as secondary invariant. if (size(Indicator)<>0) { for (ii=1;ii<=ncols(ProdCand);ii++) // going through all the power products { helpP = Indicator[ii]; if (helpP <> 0) { counter++; saveAttr = attrib(SSort[i-1][k],"size")+1; SSort[i-1][k][saveAttr] = ProdCand[ii]; // By construction, this is a _reducible_ s.i. attrib(SSort[i-1][k],"size",saveAttr); if (v) { " We found",counter, "of", int(dimmat[i,1]),"secondaries in degree",i-1; } if (int(dimmat[i,1])<>counter) { Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; sP_Reductor[sPOffset+SizeSave] = helpP; attrib(sP_Reductor, "isSB",1); // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a // homogeneous polynomial of degree i-1 then G union NF(p,G) is // a homogeneous Groebner basis up to degree i-1. Hence, sP_Reductor // is a homog. GB up to degree i-1. attrib(SaveRed, "isSB",1); attrib(Reductor, "isSB",1); } else { break; } } } } } } } } NrIS = int(dimmat[i,1])-counter; // The remaining NrIS sec. inv. are irreducible! if (NrIS>0) // need more than all the power products { if (v) { " There are ",NrIS,"irreducible secondary invariants in degree ", i-1; } mon = kbase(sP_Reductor,i-1); ii = ncols(mon); if ((i>IrrSwitch) or (ii>200)) // use sparse algorithm { if (ii+counter==int(dimmat[i,1])) // then we can use all of mon { B=normalize(evaluate_reynolds(REY,mon)); IS=IS+B; saveAttr = attrib(SSort[i-1][i-1],"size")+ii; SSort[i-1][i-1] = SSort[i-1][i-1] + B; attrib(SSort[i-1][i-1],"size", saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1] = ISSort[i-1] + B; } else { ISSort[i-1] = B; } if (v) {" We found all",NrIS,"irreducibles in degree ",i-1;} } else { irrcounter=0; j=0; // j goes through all of mon - // Compare the comments on the computation of reducible sec. inv.! while (counter <> int(dimmat[i,1])) { if ((j mod MonStep) == 0) { if ((j+MonStep) <= ii) { ideal tmp = normalize(evaluate_reynolds(REY,ideal(mon[j+1..j+MonStep]))); B[j+1..j+MonStep] = tmp[1..MonStep]; tmp = reduce(tmp,sP_Reductor); Indicator[j+1..j+MonStep] = tmp[1..MonStep]; kill tmp; } else { ideal tmp = normalize(evaluate_reynolds(REY,ideal(mon[j+1..ii]))); B[j+1..ii] = tmp[1..ii-j]; tmp = reduce(tmp,sP_Reductor); Indicator[j+1..ii] = tmp[1..ii-j]; kill tmp; } } j++; helpP = Indicator[j]; if (helpP <>0) // B[j] should be added { counter++; irrcounter++; IS=IS,B[j]; saveAttr = attrib(SSort[i-1][i-1],"size")+1; SSort[i-1][i-1][saveAttr] = B[j]; attrib(SSort[i-1][i-1],"size",saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1][irrcounter] = B[j]; } else { ISSort[i-1] = ideal(B[j]); } if (v) { " We found", irrcounter,"of", NrIS ,"irr. sec. inv. in degree ",i-1; } Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); sP_Reductor[sPOffset+SizeSave] = helpP; attrib(sP_Reductor, "isSB",1); } B[j]=0; Indicator[j]=0; } } } // if i>IrrSwitch else // use fast algorithm { B=sort_of_invariant_basis(sP_Reductor,REY,i-1,int(dimmat[i,1])*6); // B contains // images of kbase(sP,i-1) under the // Reynolds operator that are linearly // independent if (counter==0 && ncols(B)==int(dimmat[i,1])) // then we can take all of B { IS=IS+B; saveAttr = attrib(SSort[i-1][i-1],"size")+int(dimmat[i,1]); SSort[i-1][i-1] = SSort[i-1][i-1] + B; attrib(SSort[i-1][i-1],"size", saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1] = ISSort[i-1] + B; } else { ISSort[i-1] = B; } if (v) {" We found all",NrIS,"irreducibles in degree ",i-1;} } else { irrcounter=0; j=0; // j goes through all of B - // Compare the comments on the computation of reducible sec. inv.! Indicator = reduce(B,sP_Reductor); while (int(dimmat[i,1])<>counter) { j++; helpP = Indicator[j]; if (helpP <>0) // B[j] should be added { counter++; irrcounter++; IS=IS,B[j]; saveAttr = attrib(SSort[i-1][i-1],"size")+1; SSort[i-1][i-1][saveAttr] = B[j]; attrib(SSort[i-1][i-1],"size",saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1][irrcounter] = B[j]; } else { ISSort[i-1] = ideal(B[j]); } if (v) { " We found", irrcounter,"of", NrIS,"irr. sec. inv. in degree ",i-1; } Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); sP_Reductor[sPOffset+SizeSave] = helpP; attrib(sP_Reductor, "isSB",1); } B[j]=0; Indicator[j]=0; } } } // i<=IrrSwitch } // Computation of irreducible secondaries if (v) { ""; } } // if (int(dimmat[i,1])<>0) } // for i if (v) { " We're done!"; ""; } degBound = dgb; // Prepare return: int TotalNumber; for (k=1;k<=m;k++) { TotalNumber = TotalNumber + int(dimmat[k,1]); } matrix S[1][TotalNumber]; S[1,1]=1; j=1; for (k=1;k with homogeneous primary invariants, where n is the number of variables of the basering; @* REY: a gxn representing the Reynolds operator, where g the size of the corresponding group; @* M: a 1x2 giving numerator and denominator of the Molien series; @* v: an optional ; @* \"PP\": if this string occurs as (optional) parameter, then in all degrees power products of irr. sec. inv. will be computed. RETURN: Irreducible homogeneous secondary invariants of the invariant ring (type ) ASSUME: We are in the non-modular case, i.e., the characteristic of the basering does not divide the group order; REY is the 1st return value of group_reynolds(), reynolds_molien() or the second one of primary_invariants(); M is the return value of molien() or the second one of reynolds_molien() or the third one of primary_invariants() DISPLAY: Information on the progress of computations if v does not equal 0 THEORY: The secondary invariants are calculated by finding a basis (in terms of monomials) of the basering modulo the primary invariants, mapping those to invariants with the Reynolds operator. Among these images or their power products we pick secondary invariants using Groebner basis techniques (see S. King: Fast Computation of Secondary Invariants). The size of this set can be read off from the Molien series. Here, only irreducible secondary invariants are explicitly computed, which saves time and memory. @* Moreover, if no irr. sec. inv. in degree d-1 have been found and unless the last optional paramter \"PP\" is used, a Groebner basis of primary invariants and irreducible secondary invariants up to degree d-2 is computed, which allows to detect irr. sec. inv. in degree d without computing power products. @* There are three internal parameters \"pieces\", \"MonStep\" and \"IrrSwitch\". The default values of the parameters should be fine in most cases. However, in some cases, different values may provide a better balance of memory consumption (smaller values) and speed (bigger values). SEE ALSO: secondary_char0 KEYWORDS: irreducible secondary invariant EXAMPLE: example irred_secondary_char0; shows an example " { //---------- Internal parameters, whose choice might improve the performance ----- int pieces = 3; // For generating reducible secondaries, blocks of #pieces# secondaries // are formed. // If this parameter is small, the memory consumption will decrease. int MonStep = 15; // The Reynolds operator is applied to blocks of #MonStep# monomials. // If this parameter is small, the memory consumption will decrease. int IrrSwitch = 7; // Up to degree #IrrSwitch#-1, or if there are few monomials in kbase(sP,i-1), // we use a method for generating irreducible secondaries that tends to // produce a smaller output (which is good for subsequent computations). // However, this method needs to much memory in high degrees, and so we // use a sparser method from degree #IrrSwitch# upwards. def br=basering; //----------------- checking input and setting verbose mode ------------------ if (char(br)<>0) { "ERROR: irred_secondary_char0 can only be used with rings of characteristic 0."; " Try irred_secondary_charp"; return(); } int i; if (size(#)>0) { if (typeof(#[1])=="int") { int v=#[1]; } else { int v=0; } } else { int v=0; } int UsePP; if (size(#)>0) { if (typeof(#[size(#)])=="string") { if (#[size(#)]=="PP") { UsePP = 1; } else { "ERROR: If the last optional parameter is a string, it should be \"PP\"."; return(matrix(ideal()),matrix(ideal())); } } } int n=nvars(br); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(P)<>n) { "ERROR: The first parameter ought to be the matrix of the primary"; " invariants." return(); } if (ncols(REY)<>n) { "ERROR: The second parameter ought to be the Reynolds operator." return(); } if (ncols(M)<>2 or nrows(M)<>1) { "ERROR: The third parameter ought to be the Molien series." return(); } if (v && voice==2) { ""; } int j, m, counter, irrcounter; //- finding the polynomial giving number and degrees of secondary invariants - poly p=1; for (j=1;j<=n;j++) // calculating the denominator of the { p=p*(1-var(1)^deg(P[j])); // Hilbert series of the ring generated } // by the primary invariants - matrix s[1][2]=M[1,1]*p,M[1,2]; // s is used for canceling s=matrix(syz(ideal(s))); p=s[2,1]; // the polynomial telling us where to // search for secondary invariants map slead=br,ideal(0); p=1/slead(p)*p; // smallest [constant] term of // p needs to be 1 matrix dimmat=coeffs(p,var(1)); // dimmat will contain the number of // secondary invariants, we need to find // of a certain degree - m=nrows(dimmat); // m-1 is the highest degree if (v) { "There are"; for (j=1;j<=m;j++) { if (int(dimmat[j,1])<>1) { int(dimmat[j,1]), "secondary invariants in degree",j-1; } else { "1 secondary invariant in degree",j-1; } } } if (v) { "In degree 0 we have: 1"; ""; } //-------------------------- initializing variables -------------------------- ideal ProdCand; // contains products of secondary invariants, // i.e., candidates for reducible sec. inv. ideal Mul1,Mul2; int dgb=degBound; degBound = 0; option(redSB); ideal sP = groebner(ideal(P)); ideal TotalReductor = sP; // will eventually be groebner(ideal(P)+IS) ideal sP_Reductor; // will contain sP union Reductor. int sPOffset = ncols(sP); int LastNewIS=-10; // if the Last New Irr. Sec. was found in degree i-2 then // we compute TotalReductor again int NoPP; // It NoPP==1, we must not use Power Products ideal Reductor,SaveRed; // sP union Reductor is a Groebner basis up to degree i-1 int SizeSave; list RedSSort; // sec. Inv. reduced by sP, sorted first by degree and then // by the minimal degree of a non-constant invariant factor list RedISSort; // irr. sec. Inv. reduced by sP, sorted by degree poly helpP; ideal helpI; ideal Indicator; // will tell us which candidates for sec. inv. we can choose ideal ReducedCandidates; int helpint; int k,k2,k3,minD; int ii; int saveAttr; ideal mon,B,IS; // IS will contain all irr. sec. inv. for (i=1;i0) // when it is == 0 we need to find no { // elements in the current degree (i-1) if (v) { "Searching in degree ",i-1,". There are ", int(dimmat[i,1])," secondary invariant(s)..."; } counter = 0; // we'll count up to dimmat[i,1] Reductor = ideal(0); helpint = 0; SaveRed = Reductor; SizeSave = 0; attrib(Reductor,"isSB",1); attrib(SaveRed,"isSB",1); // Case A: We use PP if ( NoPP==0 ) { if (v) { " Looking for Power Products..."; } sP_Reductor = sP; // We start searching for reducible secondary invariants in degree i-1, i.e., those // that are power products of irreducible secondary invariants. // It suffices to restrict the search at products of one _irreducible_ sec. inv. (Mul1) // with some sec. inv. (Mul2). // Moreover, we avoid to consider power products twice since we take a product // into account only if the minimal degree of a non-constant invariant factor in "Mul2" is not // smaller than the degree of "Mul1". // Finally, as we are not interested in the reducible sec. inv., we will only // work with their reduction modulo sP --- this allows to detect a secondary invariant // without to actually compute it! for (k=1;k"none") { Mul1 = RedISSort[k]; } else { Mul1 = ideal(0); } if ((int(dimmat[i-k,1])>0) && (Mul1[1]<>0)) { for (minD=i-k-1;minD>0;minD--) { if (int(dimmat[i,1])==counter) { break; } for (k2=1;k2 <= ((attrib(RedSSort[i-k-1][minD],"size")-1) div pieces)+1; k2++) { if (int(dimmat[i,1])==counter) { break; } Mul2=ideal(0); if (attrib(RedSSort[i-k-1][minD],"size")>=k2*pieces) { for (k3=1;k3<=pieces;k3++) { Mul2[k3] = RedSSort[i-k-1][minD][((k2-1)*pieces)+k3]; } } else { for (k3=1;k3<=(attrib(RedSSort[i-k-1][minD],"size") mod pieces);k3++) { Mul2[k3] = RedSSort[i-k-1][minD][((k2-1)*pieces)+k3]; } } ProdCand = simplify(Mul1*Mul2,4); ReducedCandidates = reduce(ProdCand,sP); // sP union SaveRed union Reductor is a homogeneous Groebner basis // up to degree i-1. // We first reduce by sP (which is fixed, so we can do it once for all), // then by SaveRed resp. by Reductor (which is modified during // the computations). Indicator = reduce(ReducedCandidates,SaveRed); // If Indicator[ii]==0 then ReducedCandidates it the reduction // of an invariant that is in the algebra generated by primary // invariants and previously computed secondary invariants. // Otherwise ReducedCandidates[ii] is the reduction of an invariant // that we can take as secondary invariant. if (size(Indicator)<>0) { for (ii=1;ii<=ncols(ProdCand);ii++) // going through all the power products { helpP = Indicator[ii]; if (helpP <> 0) { counter++; saveAttr = attrib(RedSSort[i-1][k],"size")+1; RedSSort[i-1][k][saveAttr] = ReducedCandidates[ii]; // By construction, this is the reduction of a reducible s.i. // of degree i-1. attrib(RedSSort[i-1][k],"size",saveAttr); if (v) { " We found reducible sec. inv. number ",counter; } if (int(dimmat[i,1])<>counter) { Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; sP_Reductor[sPOffset+SizeSave] = helpP; attrib(sP_Reductor, "isSB",1); // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a // homogeneous polynomial of degree i-1 then G union NF(p,G) is // a homogeneous Groebner basis up to degree i-1. Hence, sP_Reductor // is a homog. GB up to degree i-1. attrib(SaveRed, "isSB",1); attrib(Reductor, "isSB",1); } else { break; } } // new reducible sec. inv. found } // loop through ProdCand } // if there is some reducible sec. inv. attrib(SaveRed, "isSB",1); attrib(Reductor, "isSB",1); } } } } TotalReductor = sP_Reductor; } // if NoPP==0 else { //if (v) {" We don't compute Power Products!"; } // Instead of computing Power Products, we can compute a Groebner basis of the ideal // generated by the primary and previously found irr. sec. invariants up to degree i-2. An invariant // polynomial of degree i-1 belongs to this ideal if and only if it belongs to the sub-algebra // generated by primary and irreducible secondary invariants up to degree i-2. // Hence, if we find an invariant outside this ideal, it is an irreducible secondary // invariant of degree i-1. } // dealing with reducible sec. inv. // The remaining sec. inv. are irreducible! // Reason: If we use PP, TotalReductor detects the <

>-module generated by // all secondaries // If we don't, TotalReductor detects the algebra <

> if (int(dimmat[i,1])<>counter) // need more than all the power products // or work without power products { if (v) { " Looking for irreducible secondary invariants in degree ", i-1; } mon = kbase(TotalReductor,i-1); ii = ncols(mon); if (mon[1]<>0) { if ((i>IrrSwitch) or (ii>200)) // use sparse algorithm { if (NoPP==0 && ii+counter==int(dimmat[i,1])) // then we can use all of mon { B=normalize(evaluate_reynolds(REY,mon)); IS=IS+B; saveAttr = attrib(RedSSort[i-1][i-1],"size")+ii; RedSSort[i-1][i-1] = RedSSort[i-1][i-1] + NF(B,sP); attrib(RedSSort[i-1][i-1],"size", saveAttr); if (typeof(RedISSort[i-1]) <> "none") { RedISSort[i-1] = RedISSort[i-1] + NF(B,sP); } else { RedISSort[i-1] = NF(B,sP); } if (v) {" We found ",size(B)," irred. sec. inv.";} } else { irrcounter=0; j=0; // j goes through all of mon - // Compare the comments on the computation of reducible sec. inv.! while (j < ii) // we will break the loop if counter==int(dimmat[i,1]) { if ((j mod MonStep) == 0) { if ((j+MonStep) <= ii) { ideal tmp = normalize(evaluate_reynolds(REY,ideal(mon[j+1..j+MonStep]))); B[j+1..j+MonStep] = tmp[1..MonStep]; if (NoPP == 0) // we are still working with PowerProducts, // hence, we need to store NF(sec.inv.,sP) { tmp = reduce(tmp,sP); ReducedCandidates[j+1..j+MonStep] = tmp[1..MonStep]; tmp = reduce(tmp,SaveRed); } else { tmp = reduce(tmp,TotalReductor); } Indicator[j+1..j+MonStep] = tmp[1..MonStep]; kill tmp; } else { ideal tmp = normalize(evaluate_reynolds(REY,ideal(mon[j+1..ii]))); B[j+1..ii] = tmp[1..ii-j]; if (NoPP == 0) { tmp = reduce(tmp,sP); ReducedCandidates[j+1..ii] = tmp[1..ii-j]; tmp = reduce(tmp,SaveRed); } else { tmp = reduce(tmp,TotalReductor); } Indicator[j+1..ii] = tmp[1..ii-j]; kill tmp; } } j++; helpP = Indicator[j]; if (helpP <>0) // B[j] should be added { counter++; irrcounter++; IS=IS,B[j]; saveAttr = attrib(RedSSort[i-1][i-1],"size")+1; if (NoPP==0) // we will still be working with Power Products { RedSSort[i-1][i-1][saveAttr] = ReducedCandidates[j]; attrib(RedSSort[i-1][i-1],"size",saveAttr); if (typeof(RedISSort[i-1]) <> "none") { RedISSort[i-1][irrcounter] = ReducedCandidates[j]; } else { RedISSort[i-1] = ideal(ReducedCandidates[j]); } } if (v) { " We found irred. sec. inv. number ",irrcounter; } Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); attrib(Reductor, "isSB",1); LastNewIS = i-1; if (int(dimmat[i,1])==counter) { break; } } mon[j]=0; B[j]=0; ReducedCandidates[j]=0; Indicator[j]=0; } } } // if i>IrrSwitch else // use fast algorithm { B=sort_of_invariant_basis(TotalReductor,REY,i-1,int(dimmat[i,1])*6); // B is a linearly independent set of reynolds // images of monomials that do not occur // as leading monomials of the ideal spanned // by primary and previously found irreducible // secondary invariants. if (NoPP==0 && ncols(B)+counter==int(dimmat[i,1])) // then we can take all of B { IS=IS+B; saveAttr = attrib(RedSSort[i-1][i-1],"size")+int(dimmat[i,1]); RedSSort[i-1][i-1] = RedSSort[i-1][i-1] + B; attrib(RedSSort[i-1][i-1],"size", saveAttr); if (typeof(RedISSort[i-1]) <> "none") { RedISSort[i-1] = RedISSort[i-1] + B; } else { RedISSort[i-1] = B; } if (v) {" We found ",size(B)," irred. sec. inv.";} } else { irrcounter=0; j=0; // j goes through all of B // Compare the comments on the computation of reducible sec. inv.! ReducedCandidates = reduce(B,sP); Indicator = reduce(ReducedCandidates,SaveRed); while (int(dimmat[i,1])<>counter) // need to find dimmat[i,1] { // invariants that are linearly independent j++; helpP = Indicator[j]; if (helpP <>0) // B[j] should be added { NoPP=0; // i.e., TotalReductor needs to be re-computed counter++; irrcounter++; IS=IS,B[j]; saveAttr = attrib(RedSSort[i-1][i-1],"size")+1; RedSSort[i-1][i-1][saveAttr] = ReducedCandidates[j]; attrib(RedSSort[i-1][i-1],"size",saveAttr); if (typeof(RedISSort[i-1]) <> "none") { RedISSort[i-1][irrcounter] = ReducedCandidates[j]; } else { RedISSort[i-1] = ideal(ReducedCandidates[j]); } if (v) { " We found irred. sec. inv. number ",irrcounter; } Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); attrib(Reductor, "isSB",1); LastNewIS = i-1; if (int(dimmat[i,1])==counter) { break; } } B[j]=0; ReducedCandidates[j]=0; Indicator[j]=0; } } } // i<=IrrSwitch } // if mon[1]<>0 } // Computation of irreducible secondaries if (v) { ""; } } } if (v) { " We're done!"; ""; } degBound = dgb; return(matrix(compress(IS))); } example { "EXAMPLE: S. King"; echo=2; ring r= 0, (a,b,c,d,e,f),dp; matrix A1[6][6] = 0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0; matrix A2[6][6] = 0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,0,0,0; list L = primary_invariants(A1,A2); matrix IS = irred_secondary_char0(L[1],L[2],L[3],0); IS; } /////////////////////////////////////////////////////////////////////////////// proc old_secondary_charp (matrix P, matrix REY, string ring_name, list #) "USAGE: secondary_charp(P,REY,ringname[,v]); P: a 1xn with primary invariants, REY: a gxn representing the Reynolds operator, ringname: a giving the name of a ring of characteristic 0 where the Molien series is stored, v: an optional ASSUME: n is the number of variables of the basering, g the size of the group, REY is the 1st return value of group_reynolds(), reynolds_molien() or the second one of primary_invariants(), `ringname` is a ring of char 0 that has been created by molien() or reynolds_molien() or primary_invariants() RETURN: secondary invariants of the invariant ring (type ) and irreducible secondary invariants (type ) DISPLAY: information if v does not equal 0 THEORY: Secondary invariants are calculated by finding a basis (in terms of monomials) of the basering modulo primary invariants, mapping those to invariants with the Reynolds operator and using these images or their power products such that they are linearly independent modulo the primary invariants (see paper \"Some Algorithms in Invariant Theory of Finite Groups\" by Kemper and Steel (1997)). EXAMPLE: example secondary_charp; shows an example " { def br=basering; degBound=0; //---------------- checking input and setting verbose mode ------------------- if (char(br)==0) { "ERROR: secondary_charp should only be used with rings of characteristic p>0."; return(); } int i; if (size(#)>0) { if (typeof(#[size(#)])=="int") { int v=#[size(#)]; } else { int v=0; } } else { int v=0; } int n=nvars(br); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(P)<>n) { "ERROR: The first parameter ought to be the matrix of the primary"; " invariants." return(); } if (ncols(REY)<>n) { "ERROR: The second parameter ought to be the Reynolds operator." return(); } if (typeof(`ring_name`)<>"ring") { "ERROR: The should give the name of the ring where the Molien." " series is stored."; return(); } if (v && voice==2) { ""; } int j, m, counter, d; intvec deg_dim_vec; //- finding the polynomial giving number and degrees of secondary invariants - for (j=1;j<=n;j++) { deg_dim_vec[j]=deg(P[j]); } setring `ring_name`; poly p=1; for (j=1;j<=n;j++) // calculating the denominator of the { p=p*(1-var(1)^deg_dim_vec[j]); // Hilbert series of the ring generated } // by the primary invariants - matrix s[1][2]=M[1,1]*p,M[1,2]; // s is used for canceling s=matrix(syz(ideal(s))); p=s[2,1]; // the polynomial telling us where to // search for secondary invariants map slead=basering,ideal(0); p=1/slead(p)*p; // smallest term of p needs to be 1 if (v) { " Polynomial telling us where to look for secondary invariants:"; " "+string(p); ""; } matrix dimmat=coeffs(p,var(1)); // dimmat will contain the number of // secondary invariants, we need to find // of a certain degree - m=nrows(dimmat); // m-1 is the highest degree deg_dim_vec=1; for (j=2;j<=m;j++) { deg_dim_vec=deg_dim_vec,int(dimmat[j,1]); } if (v) { "In degree 0 we have: 1"; ""; } //------------------------ initializing variables ---------------------------- setring br; intmat PP; poly pp; int k; intvec deg_vec; ideal sP=groebner(ideal(P)); ideal TEST,B,IS; ideal S=1; // 1 is the first secondary invariant //------------------- generating secondary invariants ------------------------ for (i=2;i<=m;i++) // going through deg_dim_vec - { if (deg_dim_vec[i]<>0) // when it is == 0 we need to find 0 { // elements in the current degree (i-1) if (v) { "Searching in degree ",i-1,", we need to find ",deg_dim_vec[i]," invariant(s)..."; } TEST=sP; counter=0; // we'll count up to degvec[i] if (IS[1]<>0) { PP=power_products(deg_vec,i-1); // generating power products of } // irreducible secondary invariants if (size(ideal(PP))<>0) { for (j=1;j<=ncols(PP);j++) // going through all of those { pp=1; for (k=1;k<=nrows(PP);k++) { pp=pp*IS[1,k]^PP[k,j]; } if (reduce(pp,TEST)<>0) { S=S,pp; counter++; if (v) { " We find: "+string(pp); } if (deg_dim_vec[i]<>counter) { //TEST=std(TEST+ideal(NF(pp,TEST))); // should be soon replaced by // next line TEST=std(TEST,pp); } else { break; } } } } if (deg_dim_vec[i]<>counter) { B=sort_of_invariant_basis(sP,REY,i-1,deg_dim_vec[i]*6); // B contains // images of kbase(sP,i-1) under the // Reynolds operator that are linearly // independent and that don't reduce to // 0 modulo sP - if (counter==0 && ncols(B)==deg_dim_vec[i]) // then we can add all of B { S=S,B; IS=IS+B; if (deg_vec[1]==0) { deg_vec=i-1; if (v) { " We find: "+string(B[1]); } for (j=2;j<=deg_dim_vec[i];j++) { deg_vec=deg_vec,i-1; if (v) { " We find: "+string(B[j]); } } } else { for (j=1;j<=deg_dim_vec[i];j++) { deg_vec=deg_vec,i-1; if (v) { " We find: "+string(B[j]); } } } } else { j=0; // j goes through all of B - while (deg_dim_vec[i]<>counter) // need to find deg_dim_vec[i] { // invariants that are linearly // independent modulo TEST j++; if (reduce(B[j],TEST)<>0) // B[j] should be added { S=S,B[j]; IS=IS+ideal(B[j]); if (deg_vec[1]==0) { deg_vec[1]=i-1; } else { deg_vec=deg_vec,i-1; } counter++; if (v) { " We find: "+string(B[j]); } if (deg_dim_vec[i]<>counter) { //TEST=std(TEST+ideal(NF(B[j],TEST))); // should be soon replaced // by next line TEST=std(TEST,B[j]); } } } } } if (v) { ""; } } } if (v) { " We're done!"; ""; } if (ring_name=="aksldfalkdsflkj") { kill `ring_name`; } return(matrix(S),matrix(IS)); } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7 (changed into char 3)"; echo=2; ring R=3,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=primary_invariants(A); matrix S,IS=secondary_charp(L[1..size(L)]); print(S); print(IS); } /////////////////////////////////////////////////////////////////////////////// proc secondary_charp (matrix P, matrix REY, string ring_name, list #) "USAGE: secondary_charp(P,REY,ringname[,v][,\"old\"]); @* P: a 1xn with homogeneous primary invariants, where n is the number of variables of the basering; @* REY: a gxn representing the Reynolds operator, where g the size of the corresponding group; @* ringname: a giving the name of a ring of characteristic 0 containing a 1x2 M giving numerator and denominator of the Molien series; @* v: an optional ; @* \"old\": if this string occurs as (optional) parameter, then an old version of secondary_char0 is used (for downward compatibility) ASSUME: The characteristic of basering is not zero; REY is the 1st return value of group_reynolds(), reynolds_molien() or the second one of primary_invariants(); @* `ringname` is the name of a ring of characteristic 0 that has been created by molien() or reynolds_molien() or primary_invariants() RETURN: secondary invariants of the invariant ring (type ) and irreducible secondary invariants (type ) DISPLAY: information if v does not equal 0 THEORY: The secondary invariants are calculated by finding a basis (in terms of monomials) of the basering modulo the primary invariants, mapping those to invariants with the Reynolds operator. Among these images or their power products we pick secondary invariants using Groebner basis techniques (see S. King: Fast Computation of Secondary Invariants). The size of this set can be read off from the Molien series. EXAMPLE: example secondary_charp; shows an example " { //---------- Internal parameters, whose choice might improve the performance ----- int pieces = 3; // For generating reducible secondaries, blocks of #pieces# secondaries // are formed. // If this parameter is small, the memory consumption will decrease. int MonStep = 15; // The Reynolds operator is applied to blocks of #MonStep# monomials. // If this parameter is small, the memory consumption will decrease. int IrrSwitch = 7; // Up to degree #IrrSwitch#-1, we use a method for generating // irreducible secondaries that tends to produce a smaller output // (which is good for subsequent computations). However, this method // needs to much memory in high degrees, and so we use a sparser method // from degree #IrrSwitch# on. def br=basering; //---------------- checking input and setting verbose mode ------------------- if (char(br)==0) { "ERROR: secondary_charp should only be used with rings of characteristic p>0."; return(); } int i; if (size(#)>0) { if (typeof(#[size(#)])=="int") { int v=#[size(#)]; } else { int v=0; } } else { int v=0; } if (size(#)>0) { if (typeof(#[size(#)])=="string") { if (#[size(#)]=="old") { if (typeof(#[1])=="int") { matrix S,IS = old_secondary_charp(P,REY,ring_name,#[1]); return(S,IS); } else { matrix S,IS = old_secondary_charp(P,REY,ring_name); return(S,IS); } } else { "ERROR: If the last optional parameter is a string, it should be \"old\"."; return(matrix(ideal()),matrix(ideal())); } } } int n=nvars(br); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(P)<>n) { "ERROR: The first parameter ought to be the matrix of the primary"; " invariants." return(); } if (ncols(REY)<>n) { "ERROR: The second parameter ought to be the Reynolds operator." return(); } if (typeof(`ring_name`)<>"ring") { "ERROR: The should give the name of the ring where the Molien." " series is stored."; return(); } if (v && voice==2) { ""; } int j, m, counter, irrcounter, d; intvec deg_dim_vec; //- finding the polynomial giving number and degrees of secondary invariants - for (j=1;j<=n;j++) { deg_dim_vec[j]=deg(P[j]); } setring `ring_name`; poly p=1; for (j=1;j<=n;j++) // calculating the denominator of the { p=p*(1-var(1)^deg_dim_vec[j]); // Hilbert series of the ring generated } // by the primary invariants - matrix s[1][2]=M[1,1]*p,M[1,2]; // s is used for canceling s=matrix(syz(ideal(s))); p=s[2,1]; // the polynomial telling us where to // search for secondary invariants map slead=basering,ideal(0); p=1/slead(p)*p; // smallest term of p needs to be 1 matrix dimmat=coeffs(p,var(1)); // dimmat will contain the number of // secondary invariants, we need to find // of a certain degree - m=nrows(dimmat); // m-1 is the highest degree if (v) { "We need to find"; for (j=1;j<=m;j++) { if (int(dimmat[j,1])<>1) { int(dimmat[j,1]), "secondary invariants in degree",j-1; } else { "1 secondary invariant in degree",j-1; } } } deg_dim_vec=1; for (j=2;j<=m;j++) { deg_dim_vec=deg_dim_vec,int(dimmat[j,1]); // i.e., deg_dim_vec[i] = dimmat[i-1,1], // which is the number of secondaries in degree i-1 } if (v) { "In degree 0 we have: 1"; ""; } //------------------------ initializing variables ---------------------------- setring br; ideal ProdCand; // contains products of secondary invariants, // i.e., candidates for reducible sec. inv. ideal Mul1,Mul2; int dgb=degBound; degBound = 0; intvec saveopt=option(get); option(redSB); ideal sP = groebner(ideal(P)); // This is the only explicit Groebner basis computation! ideal Reductor,SaveRed; // sP union Reductor is a Groebner basis up to degree i-1 ideal sP_Reductor; // will contain sP union Reductor. int sPOffset = ncols(sP); int SizeSave; list SSort; // sec. inv. first sorted by degree and then sorted by the // minimal degree of a non-constant invariant factor. list ISSort; // irr. sec. inv. sorted by degree int NrIS; poly helpP; ideal helpI; ideal Indicator; // will tell us which candidates for sec. inv. we can choose ideal ReducedCandidates; int helpint; int k,k2,k3,minD; int ii; int saveAttr; ideal mon,B,IS; // IS will contain all irr. sec. inv. for (i=1;i0) // when it is == 0 we need to find no { // elements in the current degree (i-1) if (v) { "Searching in degree ",i-1,", we need to find ",deg_dim_vec[i], " invariant(s)..."; " Looking for Power Products..."; } counter = 0; // we'll count up to deg_dim_vec[i] Reductor = ideal(0); sP_Reductor = sP; helpint = 0; SaveRed = Reductor; SizeSave = 0; attrib(Reductor,"isSB",1); attrib(SaveRed,"isSB",1); // We start searching for reducible secondary invariants in degree i-1, i.e., those // that are power products of irreducible secondary invariants. // It suffices to restrict the search at products of one _irreducible_ sec. inv. (Mul1) // with some sec. inv. (Mul2). // Moreover, we avoid to consider power products twice since we take a product // into account only if the minimal degree of a non-constant invariant factor in "Mul2" is not // smaller than the degree of "Mul1". for (k=1;k"none") { Mul1 = ISSort[k]; } else { Mul1 = ideal(0); } if ((deg_dim_vec[i-k]>0) && (Mul1[1]<>0)) { for (minD=k;minD=k2*pieces) { for (k3=1;k3<=pieces;k3++) { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3]; } } else { for (k3=1;k3<=(attrib(SSort[i-k-1][minD],"size") mod pieces);k3++) { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3]; } } ProdCand = simplify(Mul1*Mul2,4); ReducedCandidates = reduce(ProdCand,sP); // sP union SaveRed union Reductor is a homogeneous Groebner basis // up to degree i-1. // We first reduce by sP (which is fixed, so we can do it once for all), // then by SaveRed resp. by Reductor (which is modified during // the computations). Indicator = reduce(ReducedCandidates,SaveRed); // If Indicator[ii]==0 then ReducedCandidates it the reduction // of an invariant that is in the algebra generated by primary // invariants and previously computed secondary invariants. // Otherwise ProdCand[ii] can be taken as secondary invariant. if (size(Indicator)<>0) { for (ii=1;ii<=ncols(ProdCand);ii++) // going through all the power products { helpP = Indicator[ii]; if (helpP <> 0) { counter++; saveAttr = attrib(SSort[i-1][k],"size")+1; SSort[i-1][k][saveAttr] = ProdCand[ii]; // By construction, this is a _reducible_ s.i. attrib(SSort[i-1][k],"size",saveAttr); if (v) { " We found", counter, "of", deg_dim_vec[i], "secondaries in degree",i-1; } if (deg_dim_vec[i]<>counter) { Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; sP_Reductor[sPOffset+SizeSave] = helpP; attrib(sP_Reductor, "isSB",1); // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a // homogeneous polynomial of degree i-1 then G union NF(p,G) is // a homogeneous Groebner basis up to degree i-1. Hence, sP_Reductor // is a homog. GB up to degree i-1. SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); } else { break; } } } } } } } } NrIS = deg_dim_vec[i]-counter; // The remaining NrIS sec. inv. are irreducible! if (NrIS>0) // need more than all the power products { if (v) { " There are ",NrIS,"irreducible secondary invariants in degree ", i-1; } mon = kbase(sP_Reductor,i-1); ii = ncols(mon); if ((i>IrrSwitch) or (ii>200)) // use sparse algorithm { if (counter==0 && ncols(mon)==deg_dim_vec[i]) // then we can use all of mon { B=normalize(evaluate_reynolds(REY,mon)); IS=IS+B; saveAttr = attrib(SSort[i-1][i-1],"size")+deg_dim_vec[i]; SSort[i-1][i-1] = SSort[i-1][i-1] + B; attrib(SSort[i-1][i-1],"size", saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1] = ISSort[i-1] + B; } else { ISSort[i-1] = B; } if (v) {" We found all",NrIS,"irreducibles in degree ",i-1;} } else { irrcounter=0; j=0; // j goes through all of mon - // Compare the comments on the computation of reducible sec. inv.! while (deg_dim_vec[i]<>counter) { if ((j mod MonStep) == 0) { if ((j+MonStep) <= ii) { ideal tmp = normalize(evaluate_reynolds(REY,ideal(mon[j+1..j+MonStep]))); B[j+1..j+MonStep] = tmp[1..MonStep]; tmp = reduce(tmp,sP); ReducedCandidates[j+1..j+MonStep] = tmp[1..MonStep]; tmp = reduce(tmp,SaveRed); Indicator[j+1..j+MonStep] = tmp[1..MonStep]; kill tmp; } else { ideal tmp = normalize(evaluate_reynolds(REY,ideal(mon[j+1..ii]))); B[j+1..ii] = tmp[1..ii-j]; tmp = reduce(tmp,sP); ReducedCandidates[j+1..ii] = tmp[1..ii-j]; tmp = reduce(tmp,SaveRed); Indicator[j+1..ii] = tmp[1..ii-j]; kill tmp; } } j++; helpP = Indicator[j]; if (helpP <>0) // B[j] should be added { counter++; irrcounter++; IS=IS,B[j]; saveAttr = attrib(SSort[i-1][i-1],"size")+1; SSort[i-1][i-1][saveAttr] = B[j]; attrib(SSort[i-1][i-1],"size",saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1][irrcounter] = B[j]; } else { ISSort[i-1] = ideal(B[j]); } if (v) { " We found", irrcounter,"of", NrIS ,"irr. sec. inv. in degree ",i-1; } Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); } B[j]=0; ReducedCandidates[j]=0; Indicator[j]=0; } } } // if i>IrrSwitch else // use fast algorithm { B=sort_of_invariant_basis(sP,REY,i-1,deg_dim_vec[i]*6); // B contains // images of kbase(sP,i-1) under the // Reynolds operator that are linearly // independent if (counter==0 && ncols(B)==deg_dim_vec[i]) // then we can take all of B { IS=IS+B; saveAttr = attrib(SSort[i-1][i-1],"size")+deg_dim_vec[i]; SSort[i-1][i-1] = SSort[i-1][i-1] + B; attrib(SSort[i-1][i-1],"size", saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1] = ISSort[i-1] + B; } else { ISSort[i-1] = B; } if (v) {" We found all",NrIS,"irreducibles in degree ",i-1;} } else { irrcounter=0; j=0; // j goes through all of B - // Compare the comments on the computation of reducible sec. inv.! ReducedCandidates = reduce(B,sP); Indicator = reduce(ReducedCandidates,SaveRed); while (deg_dim_vec[i]<>counter) { j++; helpP = Indicator[j]; if (helpP <>0) // B[j] should be added { counter++; irrcounter++; IS=IS,B[j]; saveAttr = attrib(SSort[i-1][i-1],"size")+1; SSort[i-1][i-1][saveAttr] = B[j]; attrib(SSort[i-1][i-1],"size",saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1][irrcounter] = B[j]; } else { ISSort[i-1] = ideal(B[j]); } if (v) { " We found", irrcounter,"of", NrIS ,"irr. sec. inv. in degree ",i-1; } Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); } B[j]=0; ReducedCandidates[j]=0; Indicator[j]=0; } } } // i<=IrrSwitch } // Computation of irreducible secondaries if (v) { ""; } } // if (deg_dim_vec[i]<>0) } // for i if (v) { " We're done!"; ""; } degBound = dgb; // Prepare return: int TotalNumber; for (k=1;k<=m;k++) { TotalNumber = TotalNumber + deg_dim_vec[k]; } matrix S[1][TotalNumber]; S[1,1]=1; j=1; for (k=1;k with primary invariants, REY: a gxn representing the Reynolds operator, deg_vec: an optional listing some degrees where no non-trivial homogeneous invariants can be found, v: an optional ASSUME: n is the number of variables of the basering, g the size of the group, REY is the 1st return value of group_reynolds(), reynolds_molien() or the second one of primary_invariants(), deg_vec is the second return value of primary_char0_no_molien(), primary_charp_no_molien(), primary_char0_no_molien_random() or primary_charp_no_molien_random() RETURN: secondary invariants of the invariant ring (type ) DISPLAY: information if v does not equal 0 THEORY: Secondary invariants are calculated by finding a basis (in terms of monomials) of the basering modulo primary invariants, mapping those to invariants with the Reynolds operator and using these images as candidates for secondary invariants. We have the Reynolds operator, hence, we are in the non-modular case. Therefore, the invariant ring is Cohen-Macaulay, hence the number of secondary invariants is the product of the degrees of primary invariants divided by the group order. NOTE: should usually be faster and of more useful functionality. SEE ALSO: secondary_and_irreducibles_no_molien EXAMPLE: example secondary_no_molien; shows an example " { int MonStep = 15; // The Reynolds operator is applied to blocks of #MonStep# monomials. // If this parameter is small, the memory consumption will decrease. int IrrSwitch = 7; // Up to degree #IrrSwitch#-1, we use a method for generating // irreducible secondaries that tends to produce a smaller output // (which is good for subsequent computations). However, this method // needs to much memory in high degrees, and so we use a sparser method // from degree #IrrSwitch# on. int i; def br=basering; //------------------ checking input and setting verbose ---------------------- if (size(#)==1 or size(#)==2) { if (typeof(#[size(#)])=="int") { if (size(#)==2) { if (typeof(#[size(#)-1])=="intvec") { intvec deg_vec=#[size(#)-1]; } else { "ERROR: the third parameter should be an "; return(); } } int v=#[size(#)]; } else { if (size(#)==1) { if (typeof(#[size(#)])=="intvec") { intvec deg_vec=#[size(#)]; int v=0; } else { "ERROR: the third parameter should be an "; return(); } } else { "ERROR: wrong list of parameters"; return(); } } } else { if (size(#)>2) { "ERROR: there are too many parameters"; return(); } int v=0; } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(P)<>n) { "ERROR: The first parameter ought to be the matrix of the primary"; " invariants." return(); } if (ncols(REY)<>n) { "ERROR: The second parameter ought to be the Reynolds operator."; return(); } if (char(br)<>0) { if (nrows(REY) mod char(br) == 0) { "ERROR: We need to be in the non-modular case."; return(); } } else { "WARNING: In char 0, secondary_char0 should be faster."; } if (v && voice==2) { ""; } int j, m, d; int max=1; for (j=1;j<=n;j++) { max=max*deg(P[j]); } max=max div nrows(REY); if (v) { " We need to find ",max," secondary invariants."; ""; "In degree 0 we have: 1"; ""; } //------------------------- initializing variables --------------------------- int dgb = degBound; degBound=0; ideal sP=groebner(ideal(P)); ideal Reductor,SaveRed; // sP union Reductor is a Groebner basis up to degree i-1 int SizeSave; poly helpP; ideal helpI; ideal Indicator; // will tell us which candidates for sec. inv. we can choose ideal ReducedCandidates; int helpint; int k2,k3,minD; int ii; int saveAttr; ideal mon,B; ideal S=1; // 1 is the first secondary invariant int counter=1; i=0; if (defined(deg_vec)<>voice) { intvec deg_vec; } int k=1; //--------------------- generating secondary invariants ---------------------- while (counter<>max) { i++; Reductor = ideal(0); helpint = 0; SaveRed = Reductor; SizeSave = 0; attrib(Reductor,"isSB",1); attrib(SaveRed,"isSB",1); if (deg_vec[k]<>i) { if (v) { "Searching in degree ",i,"..."; } mon = kbase(sP,i); ii = ncols(mon); if ((i>IrrSwitch) or (ii>200)) // use sparse algorithm { j=0; // j goes through all of mon - // Compare the comments on the computation of reducible sec. inv.! while ((j0) // B[j] should be added { counter++; S[counter] = B[j]; if (v) { " We found sec. inv. number ",counter," in degree ",i; } if (counter == max) {break;} Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); } B[j]=0; ReducedCandidates[j]=0; Indicator[j]=0; } } // if i>IrrSwitch else // use fast algorithm { B=sort_of_invariant_basis(sP,REY,i,max); // B contains images of // kbase(sP,i) under the Reynolds // operator that are linearly independent // and that don't reduce to 0 modulo sP j=0; // j goes through all of B - // Compare the comments on the computation of reducible sec. inv.! ReducedCandidates = reduce(B,sP); Indicator = reduce(ReducedCandidates,SaveRed); ii = ncols(Indicator); while ((j0) // B[j] should be added { counter++; S[counter] = B[j]; if (v) { " We found sec. inv. number ",counter," in degree ",i; } if (counter == max) {break;} Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); } B[j]=0; ReducedCandidates[j]=0; Indicator[j]=0; } } // i<=IrrSwitch } else // if deg_vec[k]=i: { if (size(deg_vec)==k) { k=1; } else { k++; } } } if (v) { ""; } if (v) { " We're done!"; ""; } degBound = dgb; return(matrix(S)); } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=3,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=primary_invariants(A,intvec(1,1,0)); // In that example, there are no secondary invariants // in degree 1 or 2. matrix S=secondary_no_molien(L[1..2],intvec(1,2),1); print(S); } /////////////////////////////////////////////////////////////////////////////// proc secondary_and_irreducibles_no_molien (matrix P, matrix REY, list #) "USAGE: secondary_and_irreducibles_no_molien(P,REY[,deg_vec,v]); P: a 1xn with primary invariants, REY: a gxn representing the Reynolds operator, deg_vec: an optional listing some degrees where no non-trivial homogeneous invariants can be found, v: an optional ASSUME: n is the number of variables of the basering, g the size of the group, REY is the 1st return value of group_reynolds(), reynolds_molien() or the second one of primary_invariants() RETURN: secondary invariants of the invariant ring (type ) and irreducible secondary invariants (type ) DISPLAY: information if v does not equal 0 THEORY: Secondary invariants are calculated by finding a basis (in terms of monomials) of the basering modulo primary invariants, mapping those to invariants with the Reynolds operator. Among these images or their power products we pick secondary invariants using Groebner basis techniques (see S. King: Fast Computation of Secondary Invariants). We have the Reynolds operator, hence, we are in the non-modular case. Therefore, the invariant ring is Cohen-Macaulay, hence the number of secondary invariants is the product of the degrees of primary invariants divided by the group order. SEE ALSO: secondary_no_molien EXAMPLE: example secondary_and_irreducibles_no_molien; shows an example " { int pieces = 3; // For generating reducible secondaries, blocks of #pieces# secondaries // are formed. // If this parameter is small, the memory consumption will decrease. int MonStep = 15; // The Reynolds operator is applied to blocks of #MonStep# monomials. // If this parameter is small, the memory consumption will decrease. int IrrSwitch = 7; // Up to degree #IrrSwitch#-1, we use a method for generating // irreducible secondaries that tends to produce a smaller output // (which is good for subsequent computations). However, this method // needs to much memory in high degrees, and so we use a sparser method // from degree #IrrSwitch# on. int i; def br=basering; //------------------ checking input and setting verbose ---------------------- if (size(#)==1 or size(#)==2) { if (typeof(#[size(#)])=="int") { if (size(#)==2) { if (typeof(#[size(#)-1])=="intvec") { intvec deg_vec=#[size(#)-1]; } else { "ERROR: the third parameter should be an "; return(); } } int v=#[size(#)]; } else { if (size(#)==1) { if (typeof(#[size(#)])=="intvec") { intvec deg_vec=#[size(#)]; int v=0; } else { "ERROR: the third parameter should be an "; return(); } } else { "ERROR: wrong list of parameters"; return(); } } } else { if (size(#)>2) { "ERROR: there are too many parameters"; return(); } int v=0; } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(P)<>n) { "ERROR: The first parameter ought to be the matrix of the primary"; " invariants." return(); } if (ncols(REY)<>n) { "ERROR: The second parameter ought to be the Reynolds operator."; return(); } if (char(br)<>0) { if (nrows(REY) mod char(br) == 0) { "ERROR: We need to be in the non-modular case."; return(); } } else { "WARNING: In char 0, secondary_char0 should be faster."; } if (v && voice==2) { ""; } int j, m, d; int max=1; for (j=1;j<=n;j++) { max=max*deg(P[j]); } max=max div nrows(REY); if (v) { " We need to find ",max," secondary invariants."; ""; "In degree 0 we have: 1"; ""; } //-------------------------- initializing variables -------------------------- ideal ProdCand; // contains products of secondary invariants, // i.e., candidates for reducible sec. inv. ideal Mul1,Mul2; int dgb=degBound; degBound = 0; intvec saveopt=option(get); option(redSB); ideal sP = groebner(ideal(P)); // This is the only explicit Groebner basis computation! ideal Reductor,SaveRed; // sP union Reductor is a Groebner basis up to degree i-1 int SizeSave; list SSort; // sec. inv. first sorted by degree and then sorted by the // minimal degree of a non-constant invariant factor. list ISSort; // irr. sec. inv. sorted by degree poly helpP; ideal helpI; ideal Indicator; // will tell us which candidates for sec. inv. we can choose ideal ReducedCandidates; int helpint; int k,k2,k3,minD; int ii; int saveAttr; ideal mon,B,IS; // IS will contain all irr. sec. inv. int counter=1; int irrcounter; i=1; // the degree under consideration is i-1 SSort[i] = list(); for (k=1;k<=i;k++) { SSort[i][k]=ideal(); attrib(SSort[i][k],"size",0); } if (defined(deg_vec)<>voice) { intvec deg_vec; } int l=1; //------------------- generating secondary invariants ------------------------ while (counter<>max) { i++; SSort[i] = list(); for (k=1;k<=i;k++) { SSort[i][k]=ideal(); attrib(SSort[i][k],"size",0); } if (deg_vec[l]<>i-1) { if (v) { "Searching in degree ",i-1; " Looking for Power Products..."; } Reductor = ideal(0); helpint = 0; SaveRed = Reductor; SizeSave = 0; attrib(Reductor,"isSB",1); attrib(SaveRed,"isSB",1); // We start searching for reducible secondary invariants in degree i-1, i.e., those // that are power products of irreducible secondary invariants. // It suffices to restrict the search at products of one _irreducible_ sec. inv. (Mul1) // with some sec. inv. (Mul2). // Moreover, we avoid to consider power products twice since we take a product // into account only if the minimal degree of a non-constant invariant factor in "Mul2" is not // smaller than the degree of "Mul1". for (k=1;k"none") { Mul1 = ISSort[k]; } else { Mul1 = ideal(0); } if (Mul1[1]<>0) { for (minD=k;minD=k2*pieces) { for (k3=1;k3<=pieces;k3++) { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3]; } } else { for (k3=1;k3<=(attrib(SSort[i-k-1][minD],"size") mod pieces);k3++) { Mul2[k3] = SSort[i-k-1][minD][((k2-1)*pieces)+k3]; } } ProdCand = simplify(Mul1*Mul2,4); ReducedCandidates = reduce(ProdCand,sP); // sP union SaveRed union Reductor is a homogeneous Groebner basis // up to degree i-1. // We first reduce by sP (which is fixed, so we can do it once for all), // then by SaveRed resp. by Reductor (which is modified during // the computations). Indicator = reduce(ReducedCandidates,SaveRed); // If Indicator[ii]==0 then ReducedCandidates it the reduction // of an invariant that is in the algebra generated by primary // invariants and previously computed secondary invariants. // Otherwise ProdCand[ii] can be taken as secondary invariant. if (size(Indicator)<>0) { for (ii=1;ii<=ncols(ProdCand);ii++) // going through all the power products { helpP = Indicator[ii]; if (helpP <> 0) { counter++; saveAttr = attrib(SSort[i-1][k],"size")+1; SSort[i-1][k][saveAttr] = ProdCand[ii]; // By construction, this is a _reducible_ s.i. attrib(SSort[i-1][k],"size",saveAttr); if (v) { " We found sec. inv. number",counter, "in degree",i-1; } if (max<>counter) { Reductor = ideal(helpP); // Lemma: If G is a homogeneous Groebner basis up to degree i-1 and p is a // homogeneous polynomial of degree i-1 then G union NF(p,G) is // a homogeneous Groebner basis up to degree i-1. attrib(Reductor, "isSB",1); // if Reductor becomes too large, we reduce the whole of Indicator by // it, save it in SaveRed, and work with a smaller Reductor. This turns // out to save a little time. Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); } else { break; } } } } } } } } // The remaining sec. inv. are irreducible! if (max<>counter) { if (v) { " Looking for irreducible secondary invariants in degree ", i-1; } mon = kbase(sP,i-1); ii = ncols(mon); if ((i>IrrSwitch) or (ii>200)) // use sparse algorithm { irrcounter=0; j=0; // j goes through all of mon - // Compare the comments on the computation of reducible sec. inv.! while ((jcounter)) { if ((j mod MonStep) == 0) { if ((j+MonStep) <= ii) { ideal tmp = normalize(evaluate_reynolds(REY,ideal(mon[j+1..j+MonStep]))); B[j+1..j+MonStep] = tmp[1..MonStep]; tmp = reduce(tmp,sP); ReducedCandidates[j+1..j+MonStep] = tmp[1..MonStep]; tmp = reduce(tmp,SaveRed); Indicator[j+1..j+MonStep] = tmp[1..MonStep]; kill tmp; } else { ideal tmp = normalize(evaluate_reynolds(REY,ideal(mon[j+1..ii]))); B[j+1..ii] = tmp[1..ii-j]; tmp = reduce(tmp,sP); ReducedCandidates[j+1..ii] = tmp[1..ii-j]; tmp = reduce(tmp,SaveRed); Indicator[j+1..ii] = tmp[1..ii-j]; kill tmp; } } j++; helpP = Indicator[j]; if (helpP <>0) // B[j] should be added { counter++; irrcounter++; IS=IS,B[j]; saveAttr = attrib(SSort[i-1][i-1],"size")+1; SSort[i-1][i-1][saveAttr] = B[j]; attrib(SSort[i-1][i-1],"size",saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1][irrcounter] = B[j]; } else { ISSort[i-1] = ideal(B[j]); } if (v) { " We found irreducible sec. inv. number", irrcounter, "in degree", i-1; } if (counter == max) { break; } Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); } B[j]=0; ReducedCandidates[j]=0; Indicator[j]=0; } } // if i>IrrSwitch else // use fast algorithm { B=sort_of_invariant_basis(sP,REY,i-1,max); // B contains // images of kbase(sP,i-1) under the // Reynolds operator that are linearly // independent irrcounter=0; j=0; // j goes through all of B - // Compare the comments on the computation of reducible sec. inv.! ReducedCandidates = reduce(B,sP); Indicator = reduce(ReducedCandidates,SaveRed); ii = ncols(Indicator); while ((jcounter)) { j++; helpP = Indicator[j]; if (helpP <>0) // B[j] should be added { counter++; irrcounter++; IS=IS,B[j]; saveAttr = attrib(SSort[i-1][i-1],"size")+1; SSort[i-1][i-1][saveAttr] = B[j]; attrib(SSort[i-1][i-1],"size",saveAttr); if (typeof(ISSort[i-1]) <> "none") { ISSort[i-1][irrcounter] = B[j]; } else { ISSort[i-1] = ideal(B[j]); } if (v) { " We found irreducible sec. inv. number", irrcounter, "in degree", i-1; } Reductor = ideal(helpP); attrib(Reductor, "isSB",1); Indicator=reduce(Indicator,Reductor); SizeSave++; SaveRed[SizeSave] = helpP; attrib(SaveRed, "isSB",1); } if (max == counter) { break;} B[j]=0; ReducedCandidates[j]=0; Indicator[j]=0; } } // i<=IrrSwitch } // Computation of irreducible secondaries if (v) { ""; } } // if (deg_vec[l]<>i-1) else { if (size(deg_vec)==l) { l=1; } else { l++; } } } // while counter <> max if (v) { ""; } if (v) { " We're done!"; ""; } degBound = dgb; // Prepare return: matrix S[1][max]; S[1,1]=1; j=1; k=1; while (j<>max) { for (k2=1;k2<=k;k2++) { if (typeof(attrib(SSort[k][k2],"size"))=="int") { for (i=1;i<=attrib(SSort[k][k2],"size");i++) { j++; S[1,j] = SSort[k][k2][i]; } SSort[k][k2]=ideal(); } } k++; } return(S,matrix(compress(IS))); } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=3,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=primary_invariants(A,intvec(1,1,0)); // In that example, there are no secondary invariants // in degree 1 or 2. matrix S,IS=secondary_and_irreducibles_no_molien(L[1..2],intvec(1,2),1); print(S); print(IS); } /////////////////////////////////////////////////////////////////////////////// proc irred_secondary_no_molien (matrix P, matrix REY, list #) "USAGE: irred_secondary_no_molien(P,REY[,deg_vec,v]); P: a 1xn with primary invariants, REY: a gxn representing the Reynolds operator, deg_vec: an optional listing some degrees where no irreducible secondary invariants can be found, v: an optional ASSUME: n is the number of variables of the basering, g the size of the group, REY is the 1st return value of group_reynolds(), reynolds_molien() or the second one of primary_invariants() RETURN: Irreducible secondary invariants of the invariant ring (type ) DISPLAY: information if v does not equal 0 THEORY: Irred. secondary invariants are calculated by finding a basis (in terms of monomials) of the basering modulo primary and previously found secondary invariants, mapping those to invariants with the Reynolds operator. Among these images we pick secondary invariants, using Groebner basis techniques. SEE ALSO: irred_secondary_char0 EXAMPLE: example irred_secondary_no_molien; shows an example " { int MonStep = 29; def br=basering; //------------------ checking input and setting verbose ---------------------- if (size(#)==1 or size(#)==2) { if (typeof(#[size(#)])=="int") { if (size(#)==2) { if (typeof(#[size(#)-1])=="intvec") { intvec deg_vec=#[size(#)-1]; } else { "ERROR: the third parameter should be an "; return(); } } int v=#[size(#)]; } else { if (size(#)==1) { if (typeof(#[size(#)])=="intvec") { intvec deg_vec=#[size(#)]; int v=0; } else { "ERROR: the third parameter should be an "; return(); } } else { "ERROR: wrong list of parameters"; return(); } } } else { if (size(#)>2) { "ERROR: there are too many parameters"; return(); } int v=0; } int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get if (ncols(P)<>n) { "ERROR: The first parameter ought to be the matrix of the primary"; " invariants." return(); } if (ncols(REY)<>n) { "ERROR: The second parameter ought to be the Reynolds operator."; return(); } if (char(br)<>0) { if (nrows(REY) mod char(br) == 0) { "ERROR: We need to be in the non-modular case."; return(); } } if (v && voice==2) { ""; } if (defined(deg_vec)<>voice) { intvec deg_vec; } int l=1; //-------------------------- initializing variables -------------------------- int dgb = degBound; degBound = 0; int d,block, counter, totalcount, monsize,i,j, fin,hlp; poly helpP,lmp; block = 1; ideal mon, MON, Inv, IS,RedInv, NewIS, NewReductor; int NewIScounter; ideal sP = slimgb(ideal(P)); int Max = vdim(sP); if (Max<0) { ERROR("The first parameter ought to be a matrix of primary invariants."); } ideal sIS = sP; // sIS will be a Groebner basis up to degree d of P+irred. sec. inv. while (totalcount < Max) { d++; if (deg_vec[l]<>d) { if (v) { "Searching irred. sec. inv. in degree ",d; } NewIS = ideal(); NewIScounter=0; MON = kbase(sP,d); mon = kbase(sIS,d); monsize=ncols(mon); totalcount = totalcount + ncols(MON); if (mon[1]<>0) { if (v) { " We have ",monsize," candidates for irred. secondaries";} block=0; // Loops through the monomials while (block0) { counter++; // found new irr. sec. inv.! if (v) { " We found irr. sec. inv. number ",counter," in degree ",d; } IS[counter] = Inv[block]; sIS = sIS,helpP; attrib(sIS,"isSB",1); NewIScounter++; NewIS[NewIScounter] = helpP; mon[block]=0; Inv[block]=0; RedInv[block]=0; NewReductor[1]=helpP; attrib(NewReductor,"isSB",1); RedInv = reduce(RedInv,NewReductor); } } // loop through monomials } // if mon[1]<>0 if (totalcount < Max) { if (NewIScounter==0) { if (fin==0) { degBound = 0; sIS = groebner(sIS); fin=1; } } else { degBound = d+1; sIS = groebner(sIS+NewIS); degBound = 0; fin = 0; } } attrib(sIS,"isSB",1); } // if degree d is not excluded by deg_vec else { if (size(deg_vec)==l) { l=1; } else { l++; } } } // loop through degree degBound = dgb; return(matrix(IS)); } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=3,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=primary_invariants(A,intvec(1,1,0)); // In that example, there are no secondary invariants // in degree 1 or 2. matrix IS=irred_secondary_no_molien(L[1..2],intvec(1,2),1); print(IS); } /////////////////////////////////////////////////////////////////////////////// proc secondary_not_cohen_macaulay (matrix P, list #) "USAGE: secondary_not_cohen_macaulay(P,G1,G2,...[,v]); P: a 1xn with primary invariants, G1,G2,...: nxn generating a finite matrix group, v: optional ASSUME: n is the number of variables of the basering RETURN: secondary invariants of the invariant ring (type ) DISPLAY: information on the progress of computation if v does not equal 0 THEORY: Secondary invariants are generated following \"Generating Invariant Rings of Finite Groups over Arbitrary Fields\" by Kemper (1996). EXAMPLE: example secondary_not_cohen_macaulay; shows an example " { int i, j; int v; degBound=0; def br=basering; int n=nvars(br); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get - if (size(#)>0) // checking input and setting verbose { if (typeof(#[size(#)])=="int") { int gen_num=size(#)-1; v=#[size(#)]; if (gen_num==0) { "ERROR: There are no generators of the finite matrix group given."; return(); } for (i=1;i<=gen_num;i++) { if (typeof(#[i])<>"matrix") { "ERROR: These parameters should be generators of the finite matrix group."; return(); } if ((n<>nrows(#[i])) or (n<>ncols(#[i]))) { "ERROR: matrices need to be square and of the same dimensions"; return(); } } } else { int gen_num=size(#); for (i=1;i<=gen_num;i++) { if (typeof(#[i])<>"matrix") { "ERROR: These parameters should be generators of the finite matrix group."; return(); } if ((n<>nrows(#[i])) or (n<>ncols(#[i]))) { "ERROR: matrices need to be square and of the same dimensions"; return(); } } } } else { "ERROR: There are no generators of the finite matrix group given."; return(); } if (ncols(P)<>n) { "ERROR: The first parameter ought to be the matrix of the primary"; " invariants." return(); } if (v && voice==2) { ""; } // ring alskdfalkdsj=0,x,dp; // matrix M[1][2]=1,(1-x)^n; // export alskdfalkdsj; // export M; // we look at our primary invariants as // setring br; // such of the subgroup that only // matrix REY=matrix(maxideal(1)); // contains the identity, this means that // ch does not divide the order anymore, // this means that we can make use of the // Molien series again - M[1,1]/M[1,2] is // the Molien series of that group, we // now calculate the secondary invariants // of this subgroup in the usual fashion // where the primary invariants are the // ones from the bigger group if (v) { " First, get secondary invariants for the trivial action, with respect to"; " the primary invariants found previously. By the graded Nakayama lemma,"; " this means to compute the standard monomials for the ideal generated by"; " the primary invariants."; ""; } ideal GP = groebner(ideal(P)); if (dim(GP)<>0) { "ERROR: The ideal spanned by primary invariants of a finite group"; " always is of dimension zero."; return(); } matrix trivialS = matrix(kbase(GP));// , trivialIS=secondary_charp(P,REY,"alskdfalkdsj",v); // kill trivialIS; // kill alskdfalkdsj; // now we have those secondary invariants int k=ncols(trivialS); // k is the number of the secondary // invariants, we just calculated if (v) { " We calculate secondary invariants from the ones found for the trivial"; " subgroup."; ""; } map f; // used to let generators act on // secondary invariants with respect to // the trivial group - matrix M(1)[gen_num][k]; // M(1) will contain a module ideal B; for (i=1;i<=gen_num;i++) { B=ideal(matrix(maxideal(1))*transpose(#[i])); // image of the various // variables under the i-th generator - f=br,B; // the corresponding mapping - B=f(trivialS)-trivialS; // these relations should be 0 - M(1)[i,1..k]=B[1..k]; // we will look for the syzygies of M(1) } // intvec save_opts=option(get); // option(returnSB,redSB); // module M(2)=syz(M(1)); // nres(M(1),2)[2]; // option(set,save_opts); if (v) { "Syzygies of the \"trivial\" secondaries"; } module M(2)=nres(M(1),2)[2]; int m=ncols(M(2)); // number of generators of the module // M(2) - // the following steps calculates the intersection of the module M(2) with // the algebra A^k where A denote the subalgebra of the usual polynomial // ring, generated by the primary invariants // generate a ring where we can do elimination // in order to make it weighted homogeneous, we choose appropriate weights if (v) { "By elimination: Intersect with the invariant ring"; } intvec dv = degvec(ideal(P)),1; ring newR = char(br), (y(1..n),h),(a(dv),dp); def R = br + newR; setring R; matrix P=fetch(br,P); // primary invariants in the new ring ideal ElimP; for (i=1;i<=n;i++) { ElimP[i]=y(i)-P[1,i]; } def RHilb = newR+br; // the new variables only appear linearly, so that block order wouldn't hurt setring RHilb; ideal ElimP=imap(R,ElimP); intvec EPvec = hilb(groebner(ElimP),1,degvec(maxideal(1))); setring R; ideal GElimP = std(ElimP,EPvec,degvec(maxideal(1))); attrib(GElimP,"isSB",1); int newN = ncols(GElimP); matrix M[k][m+k*newN]; M[1..k,1..m]=matrix(imap(br,M(2))); // will contain a module - for (i=1;i<=newN;i++) { for (j=1;j<=k;j++) { M[j,m+(i-1)*k+j]=GElimP[i]; // y(i)-P[1,i]; } } M=elim2(module(M),1..n); // eliminating x(1..n), std-calculation // is done internally - //M=std(module(M)); // we have already an elimination ordering //M=nselect(M,1..n); M=homog(module(M),h); // homogenize for 'minbase' M=minbase(module(M)); ideal substitute; for (i=1;i<=n;i++) { substitute[i]=var(i); } substitute = substitute,ideal(P),1; map f=R,substitute; // replacing y(1..n) by primary // invariants and h by 1 - M=f(M); // we can't directly map from R to br setring br; // if there is a minpoly. module M(3)=imap(R,M); // M(2) is the new module m=ncols(M(3)); matrix S[1][m]; S=matrix(trivialS)*matrix(M(3)); // S now contains the secondary // invariants for (i=1; i<=m;i++) { S[1,i]=S[1,i]/leadcoef(S[1,i]); // making elements nice } S=sort(ideal(S))[1]; if (v) { " These are the secondary invariants: "; for (i=1;i<=m;i++) { " "+string(S[1,i]); } ""; " We're done!"; ""; } if ((v or (voice==2)) && (m>1)) { " WARNING: The invariant ring might not have a Hironaka decomposition"; " if the characteristic of the coefficient field divides the"; " group order."; } return(matrix(S)); } example { "EXAMPLE:"; echo=2; ring R=2,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; list L=primary_invariants(A); matrix S=secondary_not_cohen_macaulay(L[1],A); print(S); } /////////////////////////////////////////////////////////////////////////////// proc invariant_ring (list #) "USAGE: invariant_ring(G1,G2,...[,flags]); G1,G2,...: generating a finite matrix group, flags: an optional with three entries: if the first one equals 0, the program attempts to compute the Molien series and Reynolds operator, if it equals 1, the program is told that the Molien series should not be computed, if it equals -1 characteristic 0 is simulated, i.e. the Molien series is computed as if the base field were characteristic 0 (the user must choose a field of large prime characteristic, e.g. 32003) and if the first one is anything else, it means that the characteristic of the base field divides the group order (i.e. it will not even be attempted to compute the Reynolds operator or Molien series), the second component should give the size of intervals between canceling common factors in the expansion of Molien series, 0 (the default) means only once after generating all terms, in prime characteristic also a negative number can be given to indicate that common factors should always be canceled when the expansion is simple (the root of the extension field occurs not among the coefficients) RETURN: primary and secondary invariants for any matrix representation of a finite group DISPLAY: information about the various stages of the program if the third flag does not equal 0 THEORY: Bases of homogeneous invariants are generated successively and those are chosen as primary invariants that lower the dimension of the ideal generated by the previously found invariants (see \"Generating a Noetherian Normalization of the Invariant Ring of a Finite Group\" by Decker, Heydtmann, Schreyer (1998)). In the non-modular case secondary invariants are calculated by finding a basis (in terms of monomials) of the basering modulo the primary invariants, mapping to invariants with the Reynolds operator and using those or their power products such that they are linearly independent modulo the primary invariants (see \"Some Algorithms in Invariant Theory of Finite Groups\" by Kemper and Steel (1997)). In the modular case they are generated according to \"Generating Invariant Rings of Finite Groups over Arbitrary Fields\" by Kemper (1996). EXAMPLE: example invariant_ring; shows an example " { if (size(#)==0) { "ERROR: There are no generators given."; return(); } int ch=char(basering); // the algorithms depend very much on the // characteristic of the ground field - int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get int gen_num; int mol_flag, v; //------------------- checking input and setting flags ----------------------- if (typeof(#[size(#)])=="intvec") { if (size(#[size(#)])<>3) { "ERROR: The should have three entries."; return(); } gen_num=size(#)-1; mol_flag=#[size(#)][1]; if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0))) { "ERROR: the second component of should be >=0"; return(); } int interval=#[size(#)][2]; v=#[size(#)][3]; } else { gen_num=size(#); mol_flag=0; int interval=0; v=0; } //---------------------------------------------------------------------------- if (mol_flag==0) // calculation Molien series will be { if (ch==0) // attempted - { matrix REY,M=reynolds_molien(#[1..gen_num],intvec(0,interval,v)); // one // will contain Reynolds operator and the // other enumerator and denominator of // Molien series matrix P=primary_char0(REY,M,v); matrix S,IS=secondary_char0(P,REY,M,v); return(P,S,IS); } else { list L=group_reynolds(#[1..gen_num],v); if (L[1]<>0) // testing whether we are in the modular { string newring="aksldfalkdsflkj"; // case if (minpoly==0) { if (v) { " We are dealing with the non-modular case."; } if (typeof(L[2])=="int") { molien(L[3..size(L)],newring,L[2],intvec(0,interval,v)); } else { molien(L[2..size(L)],newring,intvec(0,interval,v)); } matrix P=primary_charp(L[1],newring,v); matrix S,IS=secondary_charp(P,L[1],newring,v); if (defined(aksldfalkdsflkj)==2) { kill aksldfalkdsflkj; } return(P,S,IS); } else { if (v) { " Since it is impossible for this programme to calculate the Molien series for"; " invariant rings over extension fields of prime characteristic, we have to"; " continue without it."; ""; } list l=primary_charp_no_molien(L[1],v); if (size(l)==2) { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],l[2],v); } else { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],v); } return(l[1],S,IS); } } else // the modular case { if (v) { " There is also no Molien series or Reynolds operator, we can make use of..."; ""; " We can start looking for primary invariants..."; ""; } matrix P=primary_charp_without(#[1..gen_num],v); matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v); return(P,S); } } } if (mol_flag==1) // the user wants no calculation of the { list L=group_reynolds(#[1..gen_num],v); // Molien series if (ch==0) { list l=primary_char0_no_molien(L[1],v); if (size(l)==2) { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],l[2],v); } else { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],v); } return(l[1],S,IS); } else { if (L[1]<>0) // testing whether we are in the modular { list l=primary_charp_no_molien(L[1],v); // case if (size(l)==2) { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],l[2],v); } else { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],v); } return(l[1],S,IS); } else // the modular case { if (v) { " We can start looking for primary invariants..."; ""; } matrix P=primary_charp_without(#[1..gen_num],v); matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v); return(P,S); } } } if (mol_flag==-1) { if (ch==0) { "ERROR: Characteristic 0 can only be simulated in characteristic p>>0. "; return(); } list L=group_reynolds(#[1..gen_num],v); string newring="aksldfalkdsflkj"; if (typeof(L[2])=="int") { molien(L[3..size(L)],newring,L[2],intvec(1,interval,v)); } else { molien(L[2..size(L)],newring,intvec(1,interval,v)); } matrix P=primary_charp(L[1],newring,v); matrix S,IS=secondary_charp(P,L[1],newring,v); kill aksldfalkdsflkj; return(P,S,IS); } else // the user specified that the { if (ch==0) // characteristic divides the group order { "ERROR: The characteristic cannot divide the group order when it is 0. "; return(); } if (v) { ""; } matrix P=primary_charp_without(#[1..gen_num],v); matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v); return(L[1],S); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; matrix P,S,IS=invariant_ring(A); print(P); print(S); print(IS); } /////////////////////////////////////////////////////////////////////////////// proc invariant_ring_random (list #) "USAGE: invariant_ring_random(G1,G2,...,r[,flags]); G1,G2,...: generating a finite matrix group, r: an where -|r| to |r| is the range of coefficients of random combinations of bases elements that serve as primary invariants, flags: an optional with three entries: if the first equals 0, the program attempts to compute the Molien series and Reynolds operator, if it equals 1, the program is told that the Molien series should not be computed, if it equals -1 characteristic 0 is simulated, i.e. the Molien series is computed as if the base field were characteristic 0 (the user must choose a field of large prime characteristic, e.g. 32003) and if the first one is anything else, then the characteristic of the base field divides the group order (i.e. we will not even attempt to compute the Reynolds operator or Molien series), the second component should give the size of intervals between canceling common factors in the expansion of the Molien series, 0 (the default) means only once after generating all terms, in prime characteristic also a negative number can be given to indicate that common factors should always be canceled when the expansion is simple (the root of the extension field does not occur among the coefficients) RETURN: primary and secondary invariants for any matrix representation of a finite group DISPLAY: information about the various stages of the program if the third flag does not equal 0 THEORY: is the same as for invariant_ring except that random combinations of basis elements are chosen as candidates for primary invariants and hopefully they lower the dimension of the previously found primary invariants by the right amount. EXAMPLE: example invariant_ring_random; shows an example " { if (size(#)<2) { "ERROR: There are too few parameters."; return(); } int ch=char(basering); // the algorithms depend very much on the // characteristic of the ground field int n=nvars(basering); // n is the number of variables, as well // as the size of the matrices, as well // as the number of primary invariants, // we should get int gen_num; int mol_flag, v; //------------------- checking input and setting flags ----------------------- if (typeof(#[size(#)])=="intvec" && typeof(#[size(#)-1])=="int") { if (size(#[size(#)])<>3) { "ERROR: should have three entries."; return(); } gen_num=size(#)-2; mol_flag=#[size(#)][1]; if (#[size(#)][2]<0 && (ch==0 or (ch<>0 && mol_flag<>0))) { "ERROR: the second component of should be >=0"; return(); } int interval=#[size(#)][2]; v=#[size(#)][3]; int max=#[size(#)-1]; if (gen_num==0) { "ERROR: There are no generators of a finite matrix group given."; return(); } } else { if (typeof(#[size(#)])=="int") { gen_num=size(#)-1; mol_flag=0; int interval=0; v=0; int max=#[size(#)]; } else { "ERROR: If the two last parameters are not and , the last"; " parameter should be an ."; return(); } } for (int i=1;i<=gen_num;i++) { if (typeof(#[i])=="matrix") { if (nrows(#[i])<>n or ncols(#[i])<>n) { "ERROR: The number of variables of the base ring needs to be the same"; " as the dimension of the square matrices"; return(); } } else { "ERROR: The first parameters should be a list of matrices"; return(); } } //---------------------------------------------------------------------------- if (mol_flag==0) { if (ch==0) { matrix REY,M=reynolds_molien(#[1..gen_num],intvec(0,interval,v)); // one // will contain Reynolds operator and the // other enumerator and denominator of // Molien series matrix P=primary_char0_random(REY,M,max,v); matrix S,IS=secondary_char0(P,REY,M,v); return(P,S,IS); } else { list L=group_reynolds(#[1..gen_num],v); if (L[1]<>0) // testing whether we are in the modular { string newring="aksldfalkdsflkj"; // case if (minpoly==0) { if (v) { " We are dealing with the non-modular case."; } if (typeof(L[2])=="int") { molien(L[3..size(L)],newring,L[2],intvec(0,interval,v)); } else { molien(L[2..size(L)],newring,intvec(0,interval,v)); } matrix P=primary_charp_random(L[1],newring,max,v); matrix S,IS=secondary_charp(P,L[1],newring,v); if (voice==2) { kill aksldfalkdsflkj; } return(P,S,IS); } else { if (v) { " Since it is impossible for this programme to calculate the Molien series for"; " invariant rings over extension fields of prime characteristic, we have to"; " continue without it."; ""; } list l=primary_charp_no_molien_random(L[1],max,v); if (size(l)==2) { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],l[2],v); } else { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],v); } return(l[1],S,IS); } } else // the modular case { if (v) { " There is also no Molien series, we can make use of..."; ""; " We can start looking for primary invariants..."; ""; } matrix P=primary_charp_without_random(#[1..gen_num],max,v); matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v); return(P,S); } } } if (mol_flag==1) // the user wants no calculation of the { list L=group_reynolds(#[1..gen_num],v); // Molien series if (ch==0) { list l=primary_char0_no_molien_random(L[1],max,v); if (size(l)==2) { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],l[2],v); } else { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],v); } return(l[1],S,IS); } else { if (L[1]<>0) // testing whether we are in the modular { list l=primary_charp_no_molien_random(L[1],max,v); // case if (size(l)==2) { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],l[2],v); } else { matrix S,IS=secondary_and_irreducibles_no_molien(l[1],L[1],v); } return(l[1],S,IS); } else // the modular case { if (v) { " We can start looking for primary invariants..."; ""; } matrix P=primary_charp_without_random(#[1..gen_num],max,v); matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v); return(L[1],S); } } } if (mol_flag==-1) { if (ch==0) { "ERROR: Characteristic 0 can only be simulated in characteristic p>>0. "; return(); } list L=group_reynolds(#[1..gen_num],v); string newring="aksldfalkdsflkj"; if (typeof(L[2])=="int") { molien(L[3..size(L)],newring,L[2],intvec(mol_flag,interval,v)); } else { molien(L[2..size(L)],newring,intvec(mol_flag,interval,v)); } matrix P=primary_charp_random(L[1],newring,max,v); matrix S,IS=secondary_charp(P,L[1],newring,v); kill aksldfalkdsflkj; return(P,S,IS); } else // the user specified that the { if (ch==0) // characteristic divides the group order { "ERROR: The characteristic cannot divide the group order when it is 0. "; return(); } if (v) { ""; } matrix P=primary_charp_without_random(#[1..gen_num],max,v); matrix S=secondary_not_cohen_macaulay(P,#[1..gen_num],v); return(L[1],S); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix A[3][3]=0,1,0,-1,0,0,0,0,-1; matrix P,S,IS=invariant_ring_random(A,1); print(P); print(S); print(IS); } /////////////////////////////////////////////////////////////////////////////// proc orbit_variety (matrix F,string newring) "USAGE: orbit_variety(F,s); F: a 1xm defing an invariant ring, s: a giving the name for a new ring RETURN: a Groebner basis (type , named G) for the ideal defining the orbit variety (i.e. the syzygy ideal) in the new ring (named `s`) THEORY: The ideal of algebraic relations of the invariant ring generators is calculated, then the variables of the original ring are eliminated and the polynomials that are left over define the orbit variety EXAMPLE: example orbit_variety; shows an example " { if (newring=="") { "ERROR: the second parameter may not be an empty "; return(); } if (nrows(F)==1) { def br=basering; int n=nvars(br); int m=ncols(F); string mp=string(minpoly); execute("ring R=("+charstr(br)+"),("+varstr(br)+",y(1..m)),dp;"); if (mp!="0") { execute("minpoly=number("+mp+");"); } ideal I=ideal(imap(br,F)); for (int i=1;i<=m;i++) { I[i]=I[i]-y(i); } I=elim(I,1..n); execute("ring "+newring+"=("+charstr(br)+"),(y(1..m)),dp(m);"); if (mp!="0") { execute("minpoly=number("+mp+");"); } ideal vars; for (i=2;i<=n;i++) { vars[i]=0; } vars=vars,y(1..m); map emb=R,vars; ideal G=emb(I); kill emb, vars, R; keepring `newring`; return(); } else { "ERROR: the may only have one row"; return(); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.3.7:"; echo=2; ring R=0,(x,y,z),dp; matrix F[1][7]=x2+y2,z2,x4+y4,1,x2z-1y2z,xyz,x3y-1xy3; string newring="E"; orbit_variety(F,newring); print(G); basering; } /////////////////////////////////////////////////////////////////////////////// static proc degvec(ideal I) "USAGE: degvec(I); I an . RETURN: the of degrees of the generators of I. " { intvec v; for (int j = 1;j<=ncols(I);j++) { v[j]=deg(I[j]); } return(v); } /////////////////////////////////////////////////////////////////////////////// proc rel_orbit_variety(ideal I,matrix F,list #) "USAGE: rel_orbit_variety(I,F[,s]); @* I: an invariant under the action of a group, @* F: a 1xm defining the invariant ring of this group. @* s: optional ; if s is present then (for downward compatibility) the old procedure is called, and in this case s gives the name of a new . RETURN: Without optional string s, a list L of two rings is returned. @* The ring L[1] carries a weighted degree order with variables y(1..m), the weight of y(k) equal to the degree of the k-th generators F[1,k] of the invariant ring. L[1] contains a Groebner basis (type , named G) of the ideal defining the relative orbit variety with respect to I. @* The ring L[2] has the variables of the basering together with y(1..m) and carries a block order: The first block is the order of the basering, the second is the weighted degree order occuring in L[1]. L[2] contains G and a Groebner basis (type , named Conv) such that if p is any invariant polynomial expressed in the variables of the basering then reduce(p,Conv) is a polynomial in the new variables y(1..m) such that evaluation at the generators of the invariant ring yields p. This can be used to avoid the application of (see @ref{algebra_containment}). @* For the case of optional string s, the function is equivalent to @ref{relative_orbit_variety}. THEORY: A Groebner basis of the ideal of algebraic relations of the invariant ring generators is calculated, then one of the basis elements plus the ideal generators. The variables of the original ring are eliminated and the polynomials that are left define the relative orbit variety with respect to I. The elimination is done by a weighted blockorder that has the advantage of dealing with quasi-homogeneous ideals. NOTE: We provide the ring L[1] for the sake of downward compatibility, since it is closer to the ring returned by relative_orbit_variety than L[2]. However, L[1] carries a weighted degree order, whereas the ring returned by relative_orbit_variety is lexicographically ordered. SEE ALSO: relative_orbit_variety EXAMPLE: example rel_orbit_variety; shows an example. " { if (size(#)>0) { if (typeof(#[1])=="string") { relative_orbit_variety(I,F,#[1]); keepring basering; return(); } else { "ERROR: the third parameter may either be empty or a ."; return(); } } degBound=0; if (nrows(F)==1) { option(redSB,noredTail); def br=basering; int n=nvars(br); int m=ncols(F); // In the following ring definition, any elimination order would work. list rlist = ringlist(br); int i; for (i=1;i<=m;i++) { rlist[2][n+i]="y("+string(i)+")"; } rlist[3][size(rlist[3])+1] = rlist[3][size(rlist[3])]; rlist[3][size(rlist[3])-1][1] = "wp"; rlist[3][size(rlist[3])-1][2] = degvec(ideal(F)); def newring = ring(rlist); list smallrlist; smallrlist[1]=rlist[1]; smallrlist[2]=list(); for (i=1;i<=m;i++) { smallrlist[2][i]="y("+string(i)+")"; } smallrlist[3]=list(); smallrlist[3][1]=list(); smallrlist[3][1][1] = "wp"; smallrlist[3][1][2] = degvec(ideal(F)); smallrlist[3][2] = rlist[3][size(rlist[3])]; smallrlist[4] = rlist[4]; def smallring = ring(smallrlist); setring(newring); ideal J=ideal(imap(br,F)); ideal I=imap(br,I); for (i=1;i<=m;i++) { J[i]=J[i]-y(i); } // We chose the weighted block order since this makes J quasi-homogeneous! ideal Conv=groebner(J); J=Conv,I; J=groebner(J); ideal vars; vars[n]=0; vars=vars,y(1..m); map emb=newring,vars; ideal G=emb(J); J=matrix(J)-G; for (i=1;i<=ncols(G);i++) { if (J[i]<>0) { G[i]=0; } } G=compress(G); vars=ideal(); for (i=2;i<=n;i++) { vars[i]=0; } vars=vars,y(1..m); emb=newring,vars; G=compress(emb(G)); export(G); export(Conv); setring(smallring); ideal G = compress(imap(newring,G)); export(G); list L; L[1]=smallring; L[2]=newring; dbprint( printlevel-voice+3," // 'rel_orbit_variety' created a list of two rings. // If L is the name of that list, you can access // the first ring by // def R = L[1]; setring R; // (similarly for the second ring)"); return(L); } else { "ERROR: the may only have one row"; return(); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.6.3:"; echo=2; ring R=0,(x,y,z),dp; matrix F[1][3]=x+y+z,xy+xz+yz,xyz; ideal I=x2+y2+z2-1,x2y+y2z+z2x-2x-2y-2z,xy2+yz2+zx2-2x-2y-2z; list L = rel_orbit_variety(I,F); def AllR = L[2]; setring(AllR); print(G); print(Conv); basering; } /////////////////////////////////////////////////////////////////////////////// proc relative_orbit_variety(ideal I,matrix F,string newring) "USAGE: relative_orbit_variety(I,F,s); I: an invariant under the action of a group, @* F: a 1xm defining the invariant ring of this group, @* s: a giving a name for a new ring RETURN: The procedure ends with a new ring named s. It contains a Groebner basis (type , named G) for the ideal defining the relative orbit variety with respect to I in the new ring. THEORY: A Groebner basis of the ideal of algebraic relations of the invariant ring generators is calculated, then one of the basis elements plus the ideal generators. The variables of the original ring are eliminated and the polynomials that are left define the relative orbit variety with respect to I. NOTE: This procedure is now replaced by rel_orbit_variety (see @ref{rel_orbit_variety}), which uses a different elemination order that should usually allow faster computations. SEE ALSO: rel_orbit_variety EXAMPLE: example relative_orbit_variety; shows an example " { if (newring=="") { "ERROR: the third parameter may not be empty a "; return(); } degBound=0; if (nrows(F)==1) { def br=basering; int n=nvars(br); int m=ncols(F); string mp=string(minpoly); execute("ring R=("+charstr(br)+"),("+varstr(br)+",y(1..m)),lp;"); if (mp!="0") { execute("minpoly=number("+mp+");"); } ideal J=ideal(imap(br,F)); ideal I=imap(br,I); for (int i=1;i<=m;i++) { J[i]=J[i]-y(i); } J=std(J); J=J,I; option(redSB); J=std(J); ideal vars; //for (i=1;i<=n;i=i+1) //{ vars[i]=0; //} vars[n]=0; vars=vars,y(1..m); map emb=R,vars; ideal G=emb(J); J=matrix(J)-G; for (i=1;i<=ncols(G);i++) { if (J[i]<>0) { G[i]=0; } } G=compress(G); execute("ring "+newring+"=("+charstr(br)+"),(y(1..m)),lp;"); if (mp!="0") { execute("minpoly=number("+mp+");"); } ideal vars; for (i=2;i<=n;i++) { vars[i]=0; } vars=vars,y(1..m); map emb=R,vars; ideal G=emb(G); kill vars, emb; keepring `newring`; return(); } else { "ERROR: the may only have one row"; return(); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.6.3:"; echo=2; ring R=0,(x,y,z),dp; matrix F[1][3]=x+y+z,xy+xz+yz,xyz; ideal I=x2+y2+z2-1,x2y+y2z+z2x-2x-2y-2z,xy2+yz2+zx2-2x-2y-2z; string newring="E"; relative_orbit_variety(I,F,newring); print(G); basering; } /////////////////////////////////////////////////////////////////////////////// proc image_of_variety(ideal I,matrix F) "USAGE: image_of_variety(I,F); @* I: an arbitray , @* F: a 1xm defining an invariant ring of some matrix group RETURN: The defining the image under that group of the variety defined by I THEORY: rel_orbit_variety(I,F) is called and the newly introduced @* variables in the output are replaced by the generators of the @* invariant ring. This ideal in the original variables defines the image @* of the variety defined by I EXAMPLE: example image_of_variety; shows an example " { if (nrows(F)==1) { def br=basering; int n=nvars(br); list L = rel_orbit_variety(I,F); def newring=L[2]; setring(newring); ideal F=imap(br,F); for (int i=1;i<=n;i++) { F=0,F; } map emb2=newring,F; ideal trafo = compress(emb2(G)); setring br; return(imap(newring,trafo)); } else { "ERROR: the may only have one row"; return(); } } example { "EXAMPLE: Sturmfels: Algorithms in Invariant Theory 2.6.8:"; echo=2; ring R=0,(x,y,z),dp; matrix F[1][3]=x+y+z,xy+xz+yz,xyz; ideal I=xy; print(image_of_variety(I,F)); } /////////////////////////////////////////////////////////////////////////////// static proc GetMatrix(list GEN) { matrix M[nvars(basering)][nvars(basering)]; int i,j; for (i=1;i<=size(GEN);i++) { for (j=1;j and is formed by monomials of degree d. Per is a list of ideals providing a permutation of the ring variables. ASSUME: mon contains at least the minimal monomial in each orbit sum of degree d under the permutation group given by Per. RETURN: an whose generators are the orbit sums of degree d under the permutation group given by Per. SEE ALSO: invariant_algebra_perm KEYWORDS: orbit sum EXAMPLE: example orbit_sums; shows an example " { //----------------- checking input ------------------ mon=simplify(mon,2); // remove 0 if (not homog(sum(mon))) { "ERROR: Monomials in the first parameter must be of the same degree."; return(); } int k,k2; for (k=1;k<=ncols(mon);k++) { if (leadmonom(mon[k])!=mon[k]) { "ERROR: The first parameter must be formed by monomials."; return(); } } for (k2=1;k2<=size(M);k2++) { if (typeof(M[k2])!="ideal") { "ERROR: The second parameter must be a list of ideals providing a "; " permutation of the ring variables."; return(); } if ((ncols(M[k2])!=nvars(basering)) or (ncols(M[k2])!=ncols(simplify(M[k2],6))) or (M[k2][1]==0)) { "ERROR: The second parameter must be a list of ideals providing a "; " permutation of the ring variables."; return(); } for (k=1;k<=ncols(M[k2]);k++) { if ((leadmonom(M[k2][k])!=M[k2][k]) or (deg(M[k2][k])!=1)) { "ERROR: The second parameter must be a list of ideals providing a "; " permutation of the ring variables."; return(); } } } //--------------- preparing steps ------------------- int dgb = degBound; degBound = 0; def br = basering; ideal tmpI; int g; // rings that allow fast permutation of variables with >fetch< and >imap< for (g=1;g<=size(M);g++) { list tmpL(g); execute("ring tmpR("+string(g)+") = "+charstr(br)+", ("+string(M[g])+"),("+ordstr(br)+")"); ideal tmpI; poly OrbitS; list L(g); setring(br); } // Remove non-minimal monomials. // Strategy: If m1, m2 are monomials related by a group generator // then remember only the smaller of the two. // This is where we use the assumption on mon! for (g=1;g<=size(M);g++) { setring tmpR(g); tmpI=fetch(br,mon); setring br; tmpI=imap(tmpR(g),tmpI); for (k=1;k<=ncols(mon);k++) { if ( mon[k]!=0) { if (tmpI[k] < mon[k]) { mon[k]=0; } else { if (tmpI[k]>mon[k]) { mon=NF(mon,std(tmpI[k])); } } } } } mon=simplify(mon,2); // main part: form orbits list L,newL; // contains partial orbits for (k=1;k<=ncols(mon);k++) { L[k]=ideal(mon[k]); attrib(L[k],"isSB",1); } newL=L; poly tmp; int GenOK, j,i; poly OrbitS=mon[1]; mon[1]=0; int countOrbits; ideal AllOrbits; while (1) // apply all generators to the monomials that have been found // in the preceding step { GenOK = 0; for (g=1;g<=size(M);g++) // Generator g is applied to partial orbits { setring tmpR(g); L(g)=fetch(br,newL); setring br; tmpL(g)=imap(tmpR(g),L(g)); } for (k=1;k<=size(L);k++) { if (L[k][1]!=0) // if the orbit was not fused or completed before { newL[k] = tmpL(1)[k]; for (g=2;g<=size(M);g++) { newL[k] = newL[k]+tmpL(g)[k]; } newL[k] = simplify(NF(newL[k],L[k]),2); attrib(newL[k],"isSB",1); if (newL[k][1] != 0) // i.e., the Orbit is not complete under all generators yet { GenOK=-1; L[k] = L[k],newL[k]; attrib(L[k],"isSB",1); // fuse orbits: for (k2=k+1;k2<=size(L);k2++) { if (size(NF(newL[k2],L[k]))!=size(newL[k2])) { L[k] = L[k]+L[k2]; attrib(L[k],"isSB",1); newL[k] = newL[k]+newL[k2]; attrib(newL[k],"isSB",1); L[k2]=ideal(0); newL[k2]=ideal(0); } } // fuse orbits } // the orbit was not complete yet else { countOrbits++; AllOrbits[countOrbits]=sum(L[k]); L[k]=ideal(0); newL[k]=ideal(0); } // the orbit was complete } // if orbit was not yet fused/completed before } // loop through partial orbits if (GenOK == 0) // i.e., all orbits are complete, so we can break the iteration { break; } } // iterate degBound = dgb; return(AllOrbits); } example { "EXAMPLE: orbit sums in degree 2 under the action of the alternating group;"; " it doesn't matter that we are in the modular case"; echo=2; ring R=3,(a,b,c,d),dp; list Per=ideal(b,c,a,d),ideal(a,c,d,b); ideal orb=orbit_sums(kbase(std(0),2),Per); orb; } /////////////////////////////////////////////////////////////////////////////// proc invariant_algebra_perm (list #) "USAGE: invariant_algebra_perm(GEN[,v]); @* GEN: a list of generators of a permutation group. It is given in disjoint cycle form, where trivial cycles can be omitted; e.g., the generator (1,2)(3,4)(5) is given by . @* v: an optional RETURN: A minimal homogeneous generating set of the invariant ring of the group presented by GEN, type ASSUME: We are in the non-modular case, i.e., the characteristic of the basering does not divide the group order. Note that the function does not verify whether this assumption holds or not DISPLAY: Information on the progress of computations if v does not equal 0 THEORY: We do an incremental search in increasing degree d. Generators of the invariant ring are found among the orbit sums of degree d. The generators are chosen by Groebner basis techniques (see S. King: Minimal generating sets of non-modular invariant rings of finite groups). NOTE: invariant_algebra_perm should not be used in rings with weighted orders. SEE ALSO: invariant_algebra_reynolds KEYWORDS: invariant ring minimal generating set permutation group EXAMPLE: example invariant_algebra_perm; shows an example " { //----------------- checking input and setting verbose mode ------------------ if (size(#)==0) { "ERROR: There are no parameters given."; return(); } if (typeof(#[size(#)])=="int") { int v=#[size(#)]; list GEN=#[1..size(#)-1]; } else { int v=0; list GEN=#; } int i,j,k,k2; list TST; for (i=1;i<=size(GEN);i++) { if (typeof(GEN[i])!="list") { "ERROR: The permutation group must be given by generators in"; " disjoint cycle presentation"; return(); } for (j=1;j<=size(GEN[i]);j++) { if (typeof(GEN[i][j])!="list") { "ERROR: The permutation group must be given by generators in"; " disjoint cycle presentation"; return(); } for (k=1;k<=size(GEN[i][j]);k++) { if (typeof(GEN[i][j][k])!="int") { "ERROR: The permutation group must be given by generators in"; " disjoint cycle presentation"; return(); } } } TST=sort(sum(sum(GEN[i])))[1]; if (TST[1]<=0) { "ERROR: The permutation group must be given by generators in"; " disjoint cycle presentation"; return(); } for (k2=1;k2nvars(basering))) { "ERROR: The permutation group must be given by generators in"; " disjoint cycle presentation"; return(); } } } //-------------- starting computation ------------------------- list GRP = GetGroup(GEN); def br=basering; int dgb = degBound; degBound = 0; int counter, totalcount, OrbSize, NextCand, sGoffset, fin,MaxD,LastGDeg; ideal OrbSums, RedSums, NewReductor; poly helpP,lmp; // Transform the matrices generating the group into ring maps int maxG = size(GRP); matrix vars=transpose(matrix(maxideal(1))); ideal tmpI; int g; list M; // M provides maps corresponding to the group generators: for (i=1;i<=maxG;i++) { tmpI = ideal(GRP[i]*vars); M[i] = tmpI; } ideal G; // G will contain homog. alg.generators poly Inv; ideal mon; ideal sG = std(G); int d=1; while ((fin==0) or (d<=MaxD)) { if (v) { "Searching generators in degree",d; } counter = 0; // counts generators in degree d OrbSums = orbit_sums(kbase(sG,d),M); OrbSize = ncols(OrbSums); if (v) { " We have ",OrbSize," orbit sums of degree ",d; } RedSums = reduce(OrbSums,sG); sGoffset=ncols(sG); // loop through orbit_sum, and select generators among them for (i=1;i<=OrbSize;i++) { helpP = RedSums[i]; if (helpP<>0) { counter++; // found new inv. algebra generator! totalcount++; if (v) { " We found generator number ",totalcount, " in degree ",d; } G[totalcount] = OrbSums[i]; sG[sGoffset+counter] = helpP; attrib(sG,"isSB",1); NewReductor[1]=helpP; attrib(NewReductor,"isSB",1); RedSums = reduce(RedSums,NewReductor); LastGDeg=d; } // found new generator } // loop through orbit sums if ((MaxD>0) and (d==MaxD)) { if (v) { "We went beyond the degree bound, so we are done!"; } break; } d++; // Prepare computations of the next degree if (LastGDeg==d-2) { degBound=0; if (v) {"Presumably all generators have been found";} sG = groebner(sG); fin = 0; } if (LastGDeg==d-1) { degBound=d; if (v) { "Computing Groebner basis up to the new degree",d; } sG = groebner(sG); attrib(sG,"isSB",1); fin = 0; } if ((fin==0) and (dim(sG)==0)) { MaxD = maxdeg1(kbase(sG)); if (v) { if (MaxD>=d) {"We found the degree bound",MaxD; } else {"We found the degree bound",d-1;} } if (MaxD representing the Reynolds operator of a finite matrix group, where g ist the group order and n is the number of variables of the basering; @* v: an optional RETURN: A minimal homogeneous generating set of the invariant ring, type ASSUME: We are in the non-modular case, i.e., the characteristic of the basering does not divide the group order; REY is the 1st return value of group_reynolds(), reynolds_molien() or the second one of primary_invariants() DISPLAY: Information on the progress of computations if v does not equal 0 THEORY: We do an incremental search in increasing degree d. Generators of the invariant ring are found among the Reynolds images of monomials of degree d. The generators are chosen by Groebner basis techniques (see S. King: Minimal generating sets of non-modular invariant rings of finite groups). NOTE: invariant_algebra_reynolds should not be used in rings with weighted orders. SEE ALSO: invariant_algebra_perm KEYWORDS: invariant ring minimal generating set matrix group EXAMPLE: example invariant_algebra_reynolds; shows an example " { int MonStep = 10; int v; if (size(#)) { if (typeof(#[1])=="int") { v=#[1]; } } def br=basering; int dgb = degBound; degBound = 0; int block, counter, totalcount, monsize,i,j, sGoffset, fin,MaxD,LastGDeg; poly helpP,lmp; block = 1; ideal mon, MON, Inv, G; // G will contain homog. alg.generators ideal RedInv, NewG, NewReductor; int NewGcounter; intvec dimvec; ideal sG = std(G); int d=1; dimvec[d] = dim(sG); while ((fin==0) or (d<=MaxD)) { NewG = ideal(); NewGcounter=0; mon = kbase(sG,d); sGoffset=ncols(sG); monsize = ncols(mon); if (mon[1]<>0) { if (v) { " We have ",monsize, " relevant monomials in degree ",d;} block=0; // Loops through the monomials while (block0) { counter++; // found new inv. algebra generator! if (v) { " We found generator number ",counter," in degree ",d; } G[counter] = Inv[block]; sG[sGoffset+counter] = helpP; attrib(sG,"isSB",1); NewGcounter++; NewG[NewGcounter] = helpP; mon[block]=0; Inv[block]=0; RedInv[block]=0; NewReductor[1]=helpP; attrib(NewReductor,"isSB",1); RedInv = reduce(RedInv,NewReductor); LastGDeg=d; } } // loop through monomials } // if mon[1]<>0 if ((MaxD>0) and (d==MaxD)) { if (v) { "We went beyond the degree bound, so we are done!"; } break; } d++; // Prepare computations of the next degree if (LastGDeg==d-2) { degBound=0; if (v) {"Presumably all generators have been found";} sG = groebner(sG); fin = 0; } if (LastGDeg==d-1) { degBound=d; if (v) { "Computing Groebner basis up to the new degree",d; } sG = groebner(sG); attrib(sG,"isSB",1); fin = 0; } if ((fin==0) and (dim(sG)==0)) { MaxD = maxdeg1(kbase(sG)); if (v) { if (MaxD>=d) {"We found the degree bound",MaxD; } else {"We found the degree bound",d-1;} } if (MaxD attrib(basering,"uptodeg")) {ERROR("Specified degree bound exceeds ring parameter!");} int i; for (i = 1; i <= size(L); i++) {if (entryViolation(L[i], attrib(basering,"lV"))) {ERROR("Not allowed monomial/intvec found!");} } return(); } static proc createStartMat(int d, int n) "USAGE: createStartMat(d,n); d, n integers RETURN: intmat PURPOSE:Creating the intmat with all normal monomials in n variables and of degree d to start with NOTE: d has to be > 0 " {intmat M[(n^d)][d]; int i1,i2,i3,i4; for (i1 = 1; i1 <= d; i1++) //Spalten {i2 = 1; //durchlaeuft Zeilen while (i2 <= (n^d)) {for (i3 = 1; i3 <= n; i3++) {for (i4 = 1; i4 <= (n^(i1-1)); i4++) { M[i2,i1] = i3; i2 = i2 + 1; } } } } return(M); } static proc createStartMat1(int n, intmat M) "USAGE: createStartMat1(n,M); n an integer, M an intmat RETURN: intmat, with all variables except those in M " {int i; intvec V,Vt; V = M[(1..nrows(M)),1]; for (i = 1; i <= size(V); i++) {if (isInVec(i,V) == 0) {Vt = Vt,i;}} if (Vt == 0) {intmat S; return(S);} else {Vt = Vt[2..size(Vt)]; intmat S [size(Vt)][1]; S[1..size(Vt),1] = Vt; return(S);} } static proc entryViolation(intmat M, int n) "PURPOSE:checks, if all entries in M are variable-related " {if ((nrows(M) == 1) && (ncols(M) == 1)) {if (M[1,1] == 0){return(0);}} int i,j; for (i = 1; i <= nrows(M); i++) {for (j = 1; j <= ncols(M); j++) {if(!((1<=M[i,j])&&(M[i,j]<=n))) {return(1);}} } return(0); } static proc findDimen(intvec V, int n, list L, intvec P, list #) "USAGE: findDimen(V,n,L,P,degbound); V,P intvecs, n, an integer, L a list, @* degbound an optional integer RETURN: int PURPOSE:Computing the K-dimension of the quotient algebra " {int degbound = 0; if (size(#) > 0) {if (#[1] > 0) {degbound = #[1];}} int dimen,i,j,w,it; intvec Vt,Vt2; module M; if (degbound == 0) {for (i = 1; i <= n; i++) {Vt = V, i; w = 0; for (j = 1; j<= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M) == 0) {return(0);} else {M = simplify(M,2); for (i = 1; i <= size(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++){Vt[j] = int(leadcoef(M[i][j]));} dimen = dimen + 1 + findDimen(Vt,n,L,P); } return(dimen); } } else {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");} if (size(V) == degbound) {return(0);} for (i = 1; i <= n; i++) {Vt = V, i; w = 0; for (j = 1; j<= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M) == 0) {return(0);} else {M = simplify(M,2); for (i = 1; i <= size(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++){Vt[j] = int(leadcoef(M[i][j]));} dimen = dimen + 1 + findDimen(Vt,n,L,P,degbound); } return(dimen); } } } static proc findCycle(intvec V, list L, intvec P, int n, int ld, module M) "USAGE: RETURN: int, 1 if Ufn-graph contains a cycle, or 0 otherwise PURPOSE:Searching the Ufnarovskij graph for cycles " {int i,j,w,r;intvec Vt,Vt2; int it, it2; if (size(V) < ld) {for (i = 1; i <= n; i++) {Vt = V,i; w = 0; for (j = 1; j <= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {r = findCycle(Vt,L,P,n,ld,M);} if (r == 1) {break;} } return(r); } else {j = size(M); if (j > 0) { intmat Mt[j][nrows(M)]; for (it = 1; it <= j; it++) { for(it2 = 1; it2 <= nrows(M);it2++) {Mt[it,it2] = int(leadcoef(M[it2,it]));} } Vt = V[(size(V)-ld+1)..size(V)]; //Mt; type(Mt);Vt;type(Vt); if (isInMat(Vt,Mt) > 0) {return(1);} else {vector Vtt; for (it =1; it <= size(Vt); it++) {Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; for (i = 1; i <= n; i++) {Vt = V,i; w = 0; for (j = 1; j <= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; //L[j]; type(L[j]);Vt2;type(Vt2); if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {r = findCycle(Vt,L,P,n,ld,M);} if (r == 1) {break;} } return(r); } } else { Vt = V[(size(V)-ld+1)..size(V)]; vector Vtt; for (it = 1; it <= size(Vt); it++) {Vtt = Vtt + Vt[it]*gen(it);} M = Vtt; kill Vtt; for (i = 1; i <= n; i++) {Vt = V,i; w = 0; for (j = 1; j <= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; //L[j]; type(L[j]);Vt2;type(Vt2); if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {r = findCycle(Vt,L,P,n,ld,M);} if (r == 1) {break;} } return(r); } } } static proc findHCoeff(intvec V,int n,list L,intvec P,intvec H,list #) "USAGE: findHCoeff(V,n,L,P,H,degbound); L a list of intmats, degbound an integer RETURN: intvec PURPOSE:Computing the coefficient of the Hilbert series (upto degree degbound) NOTE: Starting with a part of the Hilbert series we change the coefficient @* depending on how many basis elements we found on the actual branch " {int degbound = 0; if (size(#) > 0){if (#[1] > 0){degbound = #[1];}} int i,w,j,it; int h1 = 0; intvec Vt,Vt2,H1; module M; if (degbound == 0) {for (i = 1; i <= n; i++) {Vt = V, i; w = 0; for (j = 1; j<= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M) == 0) {return(H);} else {M = simplify(M,2); for (i = 1; i <= size(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++) {Vt[j] = int(leadcoef(M[i][j]));} h1 = h1 + 1; H1 = findHCoeff(Vt,n,L,P,H1); } if (size(H1) < (size(V)+2)) {H1[(size(V)+2)] = h1;} else {H1[(size(V)+2)] = H1[(size(V)+2)] + h1;} H1 = H1 + H; return(H1); } } else {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");} if (size(V) == degbound) {return(H);} for (i = 1; i <= n; i++) {Vt = V, i; w = 0; for (j = 1; j<= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M) == 0) {return(H);} else {M = simplify(M,2); for (i = 1; i <= size(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++) {Vt[j] = int(leadcoef(M[i][j]));} h1 = h1 + 1; H1 = findHCoeff(Vt,n,L,P,H1,degbound); } if (size(H1) < (size(V)+2)) { H1[(size(V)+2)] = h1;} else {H1[(size(V)+2)] = H1[(size(V)+2)] + h1;} H1 = H1 + H; return(H1); } } } static proc findHCoeffMis(intvec V, int n, list L, intvec P, list R,list #) "USAGE: findHCoeffMis(V,n,L,P,R,degbound); degbound an optional integer, L a @* list of Intmats, R RETURN: list PURPOSE:Computing the coefficients of the Hilbert series and the Mistletoes all @* at once " {int degbound = 0; if (size(#) > 0) {if (#[1] > 0) {degbound = #[1];}} int i,w,j,h1; intvec Vt,Vt2,H1; int it; module M; if (degbound == 0) {for (i = 1; i <= n; i++) {Vt = V, i; w = 0; for (j = 1; j<= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M) == 0) {if (size(R) < 2){R[2] = list(V);} else {R[2] = R[2] + list(V);} return(R);} else {M = simplify(M,2); for (i = 1; i <= size(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++) {Vt[j] = int(leadcoef(M[i][j]));} if (size(R[1]) < (size(V)+2)) { R[1][(size(V)+2)] = 1;} else {R[1][(size(V)+2)] = R[1][(size(V)+2)] + 1;} R = findHCoeffMis(Vt,n,L,P,R); } return(R); } } else {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");} if (size(V) == degbound) {if (size(R) < 2){R[2] = list (V);} else{R[2] = R[2] + list (V);} return(R); } for (i = 1; i <= n; i++) {Vt = V, i; w = 0; for (j = 1; j<= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M) == 0) {if (size(R) < 2){R[2] = list(V);} else {R[2] = R[2] + list(V);} return(R);} else {M = simplify(M,2); for (i = 1; i <= ncols(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++) {Vt[j] = int(leadcoef(M[i][j]));} if (size(R[1]) < (size(V)+2)) { R[1][(size(V)+2)] = 1;} else {R[1][(size(V)+2)] = R[1][(size(V)+2)] + 1;} R = findHCoeffMis(Vt,n,L,P,R,degbound); } return(R); } } } static proc findMisDim(intvec V,int n,list L,intvec P,list R,list #) "USAGE: RETURN: list PURPOSE:Computing the K-dimension and the Mistletoes all at once " {int degbound = 0; if (size(#) > 0) {if (#[1] > 0) {degbound = #[1];}} int dimen,i,j,w; intvec Vt,Vt2; int it; module M; if (degbound == 0) {for (i = 1; i <= n; i++) {Vt = V, i; w = 0; for (j = 1; j<= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M) == 0) {if (size(R) < 2){R[2] = list (V);} else{R[2] = R[2] + list(V);} return(R); } else {M = simplify(M,2); for (i = 1; i <= size(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++){Vt[j] = int(leadcoef(M[i][j]));} R[1] = R[1] + 1; R = findMisDim(Vt,n,L,P,R); } return(R); } } else {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");} if (size(V) == degbound) {if (size(R) < 2){R[2] = list (V);} else{R[2] = R[2] + list (V);} return(R); } for (i = 1; i <= n; i++) {Vt = V, i; w = 0; for (j = 1; j<= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M) == 0) {if (size(R) < 2){R[2] = list (V);} else{R[2] = R[2] + list(V);} return(R); } else {M = simplify(M,2); for (i = 1; i <= size(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++){Vt[j] = int(leadcoef(M[i][j]));} R[1] = R[1] + 1; R = findMisDim(Vt,n,L,P,R,degbound); } return(R); } } } static proc findmistletoes(intvec V, int n, list L, intvec P, list #) "USAGE: findmistletoes(V,n,L,P,degbound); V a normal word, n the number of @* variables, L the GB, P the occuring degrees, @* and degbound the (optional) degreebound RETURN: list PURPOSE:Computing mistletoes starting in V NOTE: V has to be normal w.r.t. L, it will not be checked for being so " {int degbound = 0; if (size(#) > 0) {if (#[1] > 0) {degbound = #[1];}} list R; intvec Vt,Vt2; int it; int i,j; module M; if (degbound == 0) {int w; for (i = 1; i <= n; i++) {Vt = V,i; w = 0; for (j = 1; j <= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0) {w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M)==0) {R = V; return(R);} else {M = simplify(M,2); for (i = 1; i <= size(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++){Vt[j] = int(leadcoef(M[i][j]));} R = R + findmistletoes(Vt,n,L,P); } return(R); } } else {if (size(V) > degbound) {ERROR("monomial exceeds degreebound");} if (size(V) == degbound) {R = V; return(R);} int w; for (i = 1; i <= n; i++) {Vt = V,i; w = 0; for (j = 1; j <= size(P); j++) {if (P[j] <= size(Vt)) {Vt2 = Vt[(size(Vt)-P[j]+1)..size(Vt)]; if (isInMat(Vt2,L[j]) > 0){w = 1; break;} } } if (w == 0) {vector Vtt; for (it = 1; it <= size(Vt); it++){Vtt = Vtt + Vt[it]*gen(it);} M = M,Vtt; kill Vtt; } } if (size(M) == 0) {R = V; return(R);} else {M = simplify(M,2); for (i = 1; i <= ncols(M); i++) {kill Vt; intvec Vt; for (j =1; j <= size(M[i]); j++) {Vt[j] = int(leadcoef(M[i][j]));} //Vt; typeof(Vt); size(Vt); R = R + findmistletoes(Vt,n,L,P,degbound); } return(R); } } } static proc isInList(intvec V, list L) "USAGE: isInList(V,L); V an intvec, L a list of intvecs RETURN: int PURPOSE:Finding the position of V in L, returns 0, if V is not in M " {int i,n; n = 0; for (i = 1; i <= size(L); i++) {if (L[i] == V) {n = i; break;}} return(n); } static proc isInMat(intvec V, intmat M) "USAGE: isInMat(V,M);V an intvec, M an intmat RETURN: int PURPOSE:Finding the position of V in M, returns 0, if V is not in M " {if (size(V) <> ncols(M)) {return(0);} int i; intvec Vt; for (i = 1; i <= nrows(M); i++) {Vt = M[i,1..ncols(M)]; if ((V-Vt) == 0){return(i);} } return(0); } static proc isInVec(int v,intvec V) "USAGE: isInVec(v,V); v an integer,V an intvec RETURN: int PURPOSE:Finding the position of v in V, returns 0, if v is not in V " {int i,n; n = 0; for (i = 1; i <= size(V); i++) {if (V[i] == v) {n = i; break;}} return(n); } proc ivL2lpI(list L) "USAGE: ivL2lpI(L); L a list of intvecs RETURN: ideal PURPOSE:Transforming a list of intvecs into an ideal of Letterplace monomials. @* For the encoding of the variables see the overview. ASSUME: - Intvec corresponds to a Letterplace monomial @* - basering has to be a Letterplace ring EXAMPLE: example ivL2lpI; shows examples " {checkAssumptions(0,L); int i; ideal G; poly p; for (i = 1; i <= size(L); i++) {p = iv2lp(L[i]); G[(size(G) + 1)] = p; } return(G); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; def R = makeLetterplaceRing(5);// constructs a Letterplace ring setring R; //sets basering to Letterplace ring intvec u = 1,1,2; intvec v = 2,1,3; intvec w = 3,1,1; // u = x^2y, v = yxz, w = zx^2 in intvec representation list L = u,v,w; ivL2lpI(L);// invokes the procedure, returns the ideal containing u,v,w } proc iv2lp(intvec I) "USAGE: iv2lp(I); I an intvec RETURN: poly PURPOSE:Transforming an intvec into the corresponding Letterplace polynomial @* For the encoding of the variables see the overview. ASSUME: - Intvec corresponds to a Letterplace monomial @* - basering has to be a Letterplace ring NOTE: - Assumptions will not be checked! EXAMPLE: example iv2lp; shows examples " {if (I[1] == 0) {return(1);} int i = size(I); if (i > attrib(basering,"uptodeg")) {ERROR("polynomial exceeds degreebound");} int j; poly p = 1; for (j = 1; j <= i; j++) {if (I[j] > 0) { p = lpMult(p,var(I[j]));}} //ignore zeroes, because they correspond to 1 return(p); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; //sets basering to Letterplace ring intvec u = 1,1,2; intvec v = 2,1,3; intvec w = 3,1,1; // u = x^2y, v = yxz, w = zx^2 in intvec representation iv2lp(u); // invokes the procedure and returns the corresponding poly iv2lp(v); iv2lp(w); } proc iv2lpList(list L) "USAGE: iv2lpList(L); L a list of intmats RETURN: ideal PURPOSE:Converting a list of intmats into an ideal of corresponding monomials @* The rows of the intmat corresponds to an intvec, which stores the @* monomial. @* For the encoding of the variables see the overview. ASSUME: - The rows of each intmat in L must correspond to a Letterplace monomial @* - basering has to be a Letterplace ring EXAMPLE: example iv2lpList; shows examples " {checkAssumptions(0,L); ideal G; int i; for (i = 1; i <= size(L); i++){G = G + iv2lpMat(L[i]);} return(G); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring intmat u[3][1] = 1,1,2; intmat v[1][3] = 2,1,3; intmat w[2][3] = 3,1,1,2,3,1; // defines intmats of different size containing intvec representations of // monomials as rows list L = u,v,w; print(u); print(v); print(w); // shows the intmats contained in L iv2lpList(L); // returns the corresponding monomials as an ideal } proc iv2lpMat(intmat M) "USAGE: iv2lpMat(M); M an intmat RETURN: ideal PURPOSE:Converting an intmat into an ideal of the corresponding monomials. @* The rows of the intmat corresponds to an intvec, which stores the @* monomial. @* For the encoding of the variables see the overview. ASSUME: - The rows of M must correspond to Letterplace monomials @* - basering has to be a Letterplace ring EXAMPLE: example iv2lpMat; shows examples " {list L = M; checkAssumptions(0,L); kill L; ideal G; poly p; int i; intvec I; for (i = 1; i <= nrows(M); i++) { I = M[i,1..ncols(M)]; p = iv2lp(I); G[size(G)+1] = p; } return(G); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring intmat u[3][1] = 1,1,2; intmat v[1][3] = 2,1,3; intmat w[2][3] = 3,1,1,2,3,1; // defines intmats of different size containing intvec representations of // monomials as rows iv2lpMat(u); // returns the monomials contained in u iv2lpMat(v); // returns the monomials contained in v iv2lpMat(w); // returns the monomials contained in w } proc lpId2ivLi(ideal G) "USAGE: lpId2ivLi(G); G an ideal RETURN: list PURPOSE:Transforming an ideal into the corresponding list of intvecs. @* For the encoding of the variables see the overview. ASSUME: - basering has to be a Letterplace ring EXAMPLE: example lpId2ivLi; shows examples " {int i,j,k; list M; checkAssumptions(0,M); for (i = 1; i <= size(G); i++) {M[i] = lp2iv(G[i]);} return(M); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal L = x(1)*x(2),y(1)*y(2),x(1)*y(2)*x(3); lpId2ivLi(L); // returns the corresponding intvecs as a list } proc lp2iv(poly p) "USAGE: lp2iv(p); p a poly RETURN: intvec PURPOSE:Transforming a monomial into the corresponding intvec. @* For the encoding of the variables see the overview. ASSUME: - basering has to be a Letterplace ring NOTE: - Assumptions will not be checked! EXAMPLE: example lp2iv; shows examples " {p = normalize(lead(p)); intvec I; int i,j; if (deg(p) > attrib(basering,"uptodeg")) {ERROR("Monomial exceeds degreebound");} if (p == 1) {return(I);} if (p == 0) {ERROR("Monomial is not allowed to equal zero");} intvec lep = leadexp(p); for ( i = 1; i <= attrib(basering,"lV"); i++) {if (lep[i] == 1) {I = i; break;}} for (i = (attrib(basering,"lV")+1); i <= size(lep); i++) {if (lep[i] == 1) { j = (i mod attrib(basering,"lV")); if (j == 0) {I = I,attrib(basering,"lV");} else {I = I,j;} } else { if (lep[i] > 1) {ERROR("monomial has a not allowed multidegree");}} } if (I[1] == 0) {ERROR("monomial has a not allowed multidegree");} return(I); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring poly p = x(1)*x(2)*z(3); poly q = y(1)*y(2)*x(3)*x(4); poly w= z(1)*y(2)*x(3)*z(4)*z(5); // p,q,w are some polynomials we want to transform into their // intvec representation lp2iv(p); lp2iv(q); lp2iv(w); } proc lp2ivId(ideal G) "USAGE: lp2ivId(G); G an ideal RETURN: list PURPOSE:Converting an ideal into an list of intmats, @* the corresponding intvecs forming the rows. @* For the encoding of the variables see the overview. ASSUME: - basering has to be a Letterplace ring EXAMPLE: example lp2ivId; shows examples " {G = normalize(lead(G)); intvec I; list L; checkAssumptions(0,L); int i,md; for (i = 1; i <= size(G); i++) { if (md <= deg(G[i])) {md = deg(G[i]);}} while (size(G) > 0) {ideal Gt; for (i = 1; i <= ncols(G); i++) {if (md == deg(G[i])) {Gt = Gt + G[i]; G[i] = 0;}} if (size(Gt) > 0) {G = simplify(G,2); intmat M [size(Gt)][md]; for (i = 1; i <= size(Gt); i++) {M[i,1..md] = lp2iv(Gt[i]);} L = insert(L,M); kill M; kill Gt; md = md - 1; } else {kill Gt; md = md - 1;} } return(L); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring poly p = x(1)*x(2)*z(3); poly q = y(1)*y(2)*x(3)*x(4); poly w = z(1)*y(2)*x(3)*z(4); // p,q,w are some polynomials we want to transform into their // intvec representation ideal G = p,q,w; // define the ideal containing p,q and w lp2ivId(G); // and return the list of intmats for this ideal } // -----------------main procedures---------------------- proc ivDHilbert(list L, int n, list #) "USAGE: ivDHilbert(L,n[,degbound]); L a list of intmats, n an integer, @* degbound an optional integer RETURN: list PURPOSE:Computing the K-dimension and the Hilbert series ASSUME: - basering is a Letterplace ring @* - all rows of each intmat correspond to a Letterplace monomial @* for the encoding of the variables see the overview @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If L is the list returned, then L[1] is an integer corresponding to the @* dimension, L[2] is an intvec which contains the coefficients of the @* Hilbert series @* - If degbound is set, there will be a degree bound added. By default there @* is no degree bound @* - n is the number of variables @* - If I = L[2] is the intvec returned, then I[k] is the (k-1)-th coefficient of @* the Hilbert series. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example ivDHilbert; shows examples " {int degbound = 0; if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] > 0){degbound = #[1];}}} checkAssumptions(degbound,L); intvec H; int i,dimen; H = ivHilbert(L,n,degbound); for (i = 1; i <= size(H); i++){dimen = dimen + H[i];} L = dimen,H; return(L); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring R; setring R; // sets basering to Letterplace ring //some intmats, which contain monomials in intvec representation as rows intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3] = 1,2,1; intmat J1 [1][2] = 1,1; intmat J2 [2][3] = 2,1,2,1,2,1; print(I1); print(I2); print(J1); print(J2); list G = I1,I2; // ideal, which is already a Groebner basis list I = J1,J2; // ideal, which is already a Groebner basis //the procedure without a degree bound ivDHilbert(G,2); // the procedure with degree bound 5 ivDHilbert(I,2,5); } proc ivDHilbertSickle(list L, int n, list #) "USAGE: ivDHilbertSickle(L,n[,degbound]); L a list of intmats, n an integer, @* degbound an optional integer RETURN: list PURPOSE:Computing K-dimension, Hilbert series and mistletoes ASSUME: - basering is a Letterplace ring. @* - All rows of each intmat correspond to a Letterplace monomial. @* for the encoding of the variables see the overview @* - If you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If L is the list returned, then L[1] is an integer, L[2] is an intvec @* which contains the coefficients of the Hilbert series and L[3] @* is a list, containing the mistletoes as intvecs. @* - If degbound is set, a degree bound will be added. By default there @* is no degree bound. @* - n is the number of variables. @* - If I = L[2] is the intvec returned, then I[k] is the (k-1)-th @* coefficient of the Hilbert series. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example ivDHilbertSickle; shows examples " {int degbound = 0; if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] > 0){degbound = #[1];}}} checkAssumptions(degbound,L); int i,dimen; list R; R = ivSickleHil(L,n,degbound); for (i = 1; i <= size(R[1]); i++){dimen = dimen + R[1][i];} R[3] = R[2]; R[2] = R[1]; R[1] = dimen; return(R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring R; setring R; // sets basering to Letterplace ring //some intmats, which contain monomials in intvec representation as rows intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3] = 1,2,1; intmat J1 [1][2] = 1,1; intmat J2 [2][3] = 2,1,2,1,2,1; print(I1); print(I2); print(J1); print(J2); list G = I1,I2;// ideal, which is already a Groebner basis list I = J1,J2; // ideal, which is already a Groebner basis ivDHilbertSickle(G,2); // invokes the procedure without a degree bound ivDHilbertSickle(I,2,3); // invokes the procedure with degree bound 3 } proc ivDimCheck(list L, int n) "USAGE: ivDimCheck(L,n); L a list of intmats, n an integer RETURN: int, 0 if the dimension is finite, or 1 otherwise PURPOSE:Decides, whether the K-dimension is finite or not ASSUME: - basering is a Letterplace ring @* - All rows of each intmat correspond to a Letterplace monomial @* For the encoding of the variables see the overview. NOTE: - n is the number of variables EXAMPLE: example ivDimCheck; shows examples " {checkAssumptions(0,L); int i,r; intvec P,H; for (i = 1; i <= size(L); i++) {P[i] = ncols(L[i]); if (P[i] == 1) {if (isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}} } if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");} kill H; intmat S; int sd,ld; intvec V; sd = P[1]; ld = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];} if (P[i] > ld) {ld = P[i];} } sd = (sd - 1); ld = ld - 1; if (ld == 0) { return(allVars(L,P,n));} if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} module M; for (i = 1; i <= nrows(S); i++) {V = S[i,1..ncols(S)]; if (findCycle(V,L,P,n,ld,M)) {r = 1; break;} } return(r); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring R; setring R; // sets basering to Letterplace ring //some intmats, which contain monomials in intvec representation as rows intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3] = 1,2,1; intmat J1 [1][2] = 1,1; intmat J2 [2][3] = 2,1,2,1,2,1; print(I1); print(I2); print(J1); print(J2); list G = I1,I2;// ideal, which is already a Groebner basis list I = J1,J2; // ideal, which is already a Groebner basis and which ivDimCheck(G,2); // invokes the procedure, factor is of finite K-dimension ivDimCheck(I,2); // invokes the procedure, factor is not of finite K-dimension } proc ivHilbert(list L, int n, list #) "USAGE: ivHilbert(L,n[,degbound]); L a list of intmats, n an integer, @* degbound an optional integer RETURN: intvec, containing the coefficients of the Hilbert series PURPOSE:Computing the Hilbert series ASSUME: - basering is a Letterplace ring. @* - all rows of each intmat correspond to a Letterplace monomial @* for the encoding of the variables see the overview @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If degbound is set, a degree bound will be added. By default there @* is no degree bound. @* - n is the number of variables. @* - If I is returned, then I[k] is the (k-1)-th coefficient of the Hilbert @* series. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example ivHilbert; shows examples " {int degbound = 0; if (size(#) > 0) {if (typeof(#[1])=="int"){if (#[1] > 0) {degbound = #[1];}}} intvec P,H; int i; for (i = 1; i <= size(L); i++) {P[i] = ncols(L[i]); if (P[i] == 1) {if ( isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}} } if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");} H[1] = 1; checkAssumptions(degbound,L); if (degbound == 0) {int sd; intmat S; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(H);} for (i = 1; i <= sd; i++) {H = H,(n^i);} for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; H = findHCoeff(St,n,L,P,H); kill St; } return(H); } else {for (i = 1; i <= size(P); i++) {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}} int sd; intmat S; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(H);} for (i = 1; i <= sd; i++) {H = H,(n^i);} for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; H = findHCoeff(St,n,L,P,H,degbound); kill St; } return(H); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring R; setring R; // sets basering to Letterplace ring //some intmats, which contain monomials in intvec representation as rows intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3] = 1,2,1; intmat J1 [1][2] = 1,1; intmat J2 [2][3] = 2,1,2,1,2,1; print(I1); print(I2); print(J1); print(J2); list G = I1,I2; // ideal, which is already a Groebner basis list I = J1,J2; // ideal, which is already a Groebner basis ivHilbert(G,2); // invokes the procedure without any degree bound ivHilbert(I,2,5); // invokes the procedure with degree bound 5 } proc ivKDim(list L, int n, list #) "USAGE: ivKDim(L,n[,degbound]); L a list of intmats, @* n an integer, degbound an optional integer RETURN: int, the K-dimension of A/ PURPOSE:Computing the K-dimension of A/ ASSUME: - basering is a Letterplace ring. @* - all rows of each intmat correspond to a Letterplace monomial @* for the encoding of the variables see the overview @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If degbound is set, a degree bound will be added. By default there @* is no degree bound. @* - n is the number of variables. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example ivKDim; shows examples " {int degbound = 0; if (size(#) > 0) {if (typeof(#[1])=="int"){if (#[1] > 0) {degbound = #[1];}}} intvec P,H; int i; for (i = 1; i <= size(L); i++) {P[i] = ncols(L[i]); if (P[i] == 1) {if ( isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}} } if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");} kill H; checkAssumptions(degbound,L); if (degbound == 0) {int sd; int dimen = 1; intmat S; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(dimen);} for (i = 1; i <= sd; i++) {dimen = dimen +(n^i);} for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; dimen = dimen + findDimen(St,n,L,P); kill St; } return(dimen); } else {for (i = 1; i <= size(P); i++) {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}} int sd; int dimen = 1; intmat S; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(dimen);} for (i = 1; i <= sd; i++) {dimen = dimen +(n^i);} for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; dimen = dimen + findDimen(St,n,L,P, degbound); kill St; } return(dimen); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring R; setring R; // sets basering to Letterplace ring //some intmats, which contain monomials in intvec representation as rows intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3] = 1,2,1; intmat J1 [1][2] = 1,1; intmat J2 [2][3] = 2,1,2,1,2,1; print(I1); print(I2); print(J1); print(J2); list G = I1,I2; // ideal, which is already a Groebner basis list I = J1,J2; // ideal, which is already a Groebner basis ivKDim(G,2); // invokes the procedure without any degree bound ivKDim(I,2,5); // invokes the procedure with degree bound 5 } proc ivMis2Base(list M) "USAGE: ivMis2Base(M); M a list of intvecs RETURN: ideal, a K-base of the given algebra PURPOSE:Computing the K-base out of given mistletoes ASSUME: - The mistletoes have to be ordered lexicographically -> OrdMisLex. @* Otherwise there might some elements missing. @* - basering is a Letterplace ring. @* - mistletoes are stored as intvecs, as described in the overview EXAMPLE: example ivMis2Base; shows examples " { //checkAssumptions(0,M); intvec L,A; if (size(M) == 0){ERROR("There are no mistletoes, so it appears your dimension is infinite!");} if (isInList(L,M) > 0) {print("1 is a mistletoe, therefore 1 is the only basis element"); return(list(intvec(0)));} int i,j,d,s; list Rt; Rt[1] = intvec(0); L = M[1]; for (i = size(L); 1 <= i; i--) {Rt = insert(Rt,intvec(L[1..i]));} for (i = 2; i <= size(M); i++) {A = M[i]; L = M[i-1]; s = size(A); if (s > size(L)) {d = size(L); for (j = s; j > d; j--) {Rt = insert(Rt,intvec(A[1..j]));} A = A[1..d]; } if (size(L) > s){L = L[1..s];} while (A <> L) {Rt = insert(Rt, intvec(A)); if (size(A) > 1) {A = A[1..(size(A)-1)]; L = L[1..(size(L)-1)]; } else {break;} } } return(Rt); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring R; setring R; // sets basering to Letterplace ring intvec i1 = 1,2; intvec i2 = 2,1,2; // the mistletoes are xy and yxy, which are already ordered lexicographically list L = i1,i2; ivMis2Base(L); // returns the basis of the factor algebra } proc ivMis2Dim(list M) "USAGE: ivMis2Dim(M); M a list of intvecs RETURN: int, the K-dimension of the given algebra PURPOSE:Computing the K-dimension out of given mistletoes ASSUME: - The mistletoes have to be ordered lexicographically -> OrdMisLex. @* Otherwise the returned value may differ from the K-dimension. @* - basering is a Letterplace ring. @* - mistletoes are stored as intvecs, as described in the overview EXAMPLE: example ivMis2Dim; shows examples " {checkAssumptions(0,M); intvec L; if (size(M) == 0){ERROR("There are no mistletoes, so it appears your dimension is infinite!");} if (isInList(L,M) > 0) {print("1 is a mistletoe, therefore dim = 1"); return(1);} int i,j,d,s; d = 1 + size(M[1]); for (i = 1; i < size(M); i++) {j = 1; s = size(M[i]); if (s > size(M[i+1])){s = size(M[i+1]);} while ((M[i][j] == M[i+1][j]) && (j <= s)){j = j + 1;} d = d + size(M[i+1])- j + 1; } return(d); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring R; setring R; // sets basering to Letterplace ring intvec i1 = 1,2; intvec i2 = 2,1,2; // the mistletoes are xy and yxy, which are already ordered lexicographically list L = i1,i2; ivMis2Dim(L); // returns the dimension of the factor algebra } proc ivOrdMisLex(list M) "USAGE: ivOrdMisLex(M); M a list of intvecs RETURN: list, containing the ordered intvecs of M PURPOSE:Orders a given set of mistletoes lexicographically ASSUME: - basering is a Letterplace ring. @* - intvecs correspond to monomials, as explained in the overview NOTE: - This is preprocessing, it's not needed if the mistletoes are returned @* from the sickle algorithm. @* - Each entry of the list returned is an intvec. EXAMPLE: example ivOrdMisLex; shows examples " {checkAssumptions(0,M); return(sort(M)[1]); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring intvec i1 = 1,2,1; intvec i2 = 2,2,1; intvec i3 = 1,1; intvec i4 = 2,1,1,1; // the corresponding monomials are xyx,y^2x,x^2,yx^3 list M = i1,i2,i3,i4; M; ivOrdMisLex(M);// orders the list of monomials } proc ivSickle(list L, int n, list #) "USAGE: ivSickle(L,n,[degbound]); L a list of intmats, n an int, degbound an @* optional integer RETURN: list, containing intvecs, the mistletoes of A/ PURPOSE:Computing the mistletoes for a given Groebner basis L, given by intmats ASSUME: - basering is a Letterplace ring. @* - all rows of each intmat correspond to a Letterplace monomial @* as explained in the overview @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If degbound is set, a degree bound will be added. By default there @* is no degree bound. @* - n is the number of variables. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example ivSickle; shows examples " {list M; int degbound = 0; if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] > 0){degbound = #[1];}}} int i; intvec P,H; for (i = 1; i <= size(L); i++) {P[i] = ncols(L[i]); if (P[i] == 1) {if (isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}} } if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");} kill H; checkAssumptions(degbound,L); if (degbound == 0) {intmat S; int sd; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(list (intvec(0)));} for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; M = M + findmistletoes(St,n,L,P); kill St; } return(M); } else {for (i = 1; i <= size(P); i++) {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}} intmat S; int sd; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(list (intvec(0)));} for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; M = M + findmistletoes(St,n,L,P,degbound); kill St; } return(M); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring //some intmats, which contain monomials in intvec representation as rows intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3] = 1,2,1; intmat J1 [1][2] = 1,1; intmat J2 [2][3] = 2,1,2,1,2,1; print(I1); print(I2); print(J1); print(J2); list G = I1,I2; // ideal, which is already a Groebner basis list I = J1,J2; // ideal, which is already a Groebner basis ivSickle(G,2); // invokes the procedure without any degree bound ivSickle(I,2,5); // invokes the procedure with degree bound 5 } proc ivSickleDim(list L, int n, list #) "USAGE: ivSickleDim(L,n[,degbound]); L a list of intmats, n an integer, degbound @* an optional integer RETURN: list PURPOSE:Computing mistletoes and the K-dimension ASSUME: - basering is a Letterplace ring. @* - all rows of each intmat correspond to a Letterplace monomial @* as explained in the overview @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If L is the list returned, then L[1] is an integer, L[2] is a list, @* containing the mistletoes as intvecs. @* - If degbound is set, a degree bound will be added. By default there @* is no degree bound. @* - n is the number of variables. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example ivSickleDim; shows examples " {list M; int degbound = 0; if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] > 0){degbound = #[1];}}} int i,dimen; list R; intvec P,H; for (i = 1; i <= size(L); i++) {P[i] = ncols(L[i]); if (P[i] == 1) {if (isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial, dimension equals zero");}} } if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");} kill H; checkAssumptions(degbound,L); if (degbound == 0) {int sd; dimen = 1; intmat S; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(list(dimen,list(intvec(0))));} for (i = 1; i <= sd; i++) {dimen = dimen +(n^i);} R[1] = dimen; for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; R = findMisDim(St,n,L,P,R); kill St; } return(R); } else {for (i = 1; i <= size(P); i++) {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}} int sd; dimen = 1; intmat S; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(list(dimen,list(intvec(0))));} for (i = 1; i <= sd; i++) {dimen = dimen +(n^i);} R[1] = dimen; for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; R = findMisDim(St,n,L,P,R,degbound); kill St; } return(R); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring //some intmats, which contain monomials in intvec representation as rows intmat I1 [2][2] = 1,1,2,2; intmat I2 [1][3] = 1,2,1; intmat J1 [1][2] = 1,1; intmat J2 [2][3] = 2,1,2,1,2,1; print(I1); print(I2); print(J1); print(J2); list G = I1,I2;// ideal, which is already a Groebner basis list I = J1,J2; // ideal, which is already a Groebner basis ivSickleDim(G,2); // invokes the procedure without any degree bound ivSickleDim(I,2,5); // invokes the procedure with degree bound 5 } proc ivSickleHil(list L, int n, list #) "USAGE:ivSickleHil(L,n[,degbound]); L a list of intmats, n an integer, @* degbound an optional integer RETURN: list PURPOSE:Computing the mistletoes and the Hilbert series ASSUME: - basering is a Letterplace ring. @* - all rows of each intmat correspond to a Letterplace monomial @* as explained in the overview @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If L is the list returned, then L[1] is an intvec, L[2] is a list, @* containing the mistletoes as intvecs. @* - If degbound is set, a degree bound will be added. By default there @* is no degree bound. @* - n is the number of variables. @* - If I = L[1] is the intvec returned, then I[k] is the (k-1)-th @* coefficient of the Hilbert series. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example ivSickleHil; shows examples " {int degbound = 0; if (size(#) > 0) {if (typeof(#[1])=="int"){if (#[1] > 0) {degbound = #[1];}}} intvec P,H; int i; list R; for (i = 1; i <= size(L); i++) {P[i] = ncols(L[i]); if (P[i] == 1) {if ( isInMat(H,L[i]) > 0) {ERROR("Quotient algebra is trivial");}} } if (size(L) == 0) {ERROR("GB is empty, quotient algebra corresponds to free algebra");} H[1] = 1; checkAssumptions(degbound,L); if (degbound == 0) {int sd; intmat S; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(list(H,list(intvec (0))));} for (i = 1; i <= sd; i++) {H = H,(n^i);} R[1] = H; kill H; for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; R = findHCoeffMis(St,n,L,P,R); kill St; } return(R); } else {for (i = 1; i <= size(P); i++) {if (P[i] > degbound) {ERROR("degreebound is too small, GB contains elements of higher degree");}} int sd; intmat S; sd = P[1]; for (i = 2; i <= size(P); i++) {if (P[i] < sd) {sd = P[i];}} sd = (sd - 1); if (sd == 0) { for (i = 1; i <= size(L); i++){if (ncols(L[i]) == 1){S = createStartMat1(n,L[i]); break;}}} else {S = createStartMat(sd,n);} if (intvec(S) == 0) {return(list(H,list(intvec(0))));} for (i = 1; i <= sd; i++) {H = H,(n^i);} R[1] = H; kill H; for (i = 1; i <= nrows(S); i++) {intvec St = S[i,1..ncols(S)]; R = findHCoeffMis(St,n,L,P,R,degbound); kill St; } return(R); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring //some intmats, which contain monomials in intvec representation as rows intmat I1[2][2] = 1,1,2,2; intmat I2[1][3] = 1,2,1; intmat J1[1][2] = 1,1; intmat J2[2][3] = 2,1,2,1,2,1; print(I1); print(I2); print(J1); print(J2); list G = I1,I2;// ideal, which is already a Groebner basis list I = J1,J2; // ideal, which is already a Groebner basis ivSickleHil(G,2); // invokes the procedure without any degree bound ivSickleHil(I,2,5); // invokes the procedure with degree bound 5 } proc lpDHilbert(ideal G, list #) "USAGE: lpDHilbert(G[,degbound,n]); G an ideal, degbound, n optional integers RETURN: list PURPOSE:Computing K-dimension and Hilbert series, starting with a lp-ideal ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If L is the list returned, then L[1] is an integer corresponding to the @* dimension, L[2] is an intvec which contains the coefficients of the @* Hilbert series @* - If degbound is set, there will be a degree bound added. 0 means no @* degree bound. Default: attrib(basering,uptodeg). @* - n can be set to a different number of variables. @* Default: n = attrib(basering, lV). @* - If I = L[2] is the intvec returned, then I[k] is the (k-1)-th @* coefficient of the Hilbert series. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example lpDHilbert; shows examples " {int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV"); if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}} if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}} list L; L = lp2ivId(normalize(lead(G))); return(ivDHilbert(L,n,degbound)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a //Groebner basis lpDHilbert(G,5,2); // invokes procedure with degree bound 5 and 2 variables // note that the optional parameters are not necessary, due to the finiteness // of the K-dimension of the factor algebra lpDHilbert(G); // procedure with ring parameters lpDHilbert(G,0); // procedure without degreebound } proc lpDHilbertSickle(ideal G, list #) "USAGE: lpDHilbertSickle(G[,degbound,n]); G an ideal, degbound, n optional @* integers RETURN: list PURPOSE:Computing K-dimension, Hilbert series and mistletoes at once ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If L is the list returned, then L[1] is an integer, the K-dimension, @* L[2] is an intvec, the Hilbert series and L[3] is an ideal, @* the mistletoes @* - If degbound is set, there will be a degree bound added. 0 means no @* degree bound. Default: attrib(basering,uptodeg). @* - n can be set to a different number of variables. @* Default: n = attrib(basering, lV). @* - If I = L[1] is the intvec returned, then I[k] is the (k-1)-th @* coefficient of the Hilbert series. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example lpDHilbertSickle; shows examples " {int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV"); if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}} if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}} list L; L = lp2ivId(normalize(lead(G))); L = ivDHilbertSickle(L,n,degbound); L[3] = ivL2lpI(L[3]); return(L); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a //Groebner basis lpDHilbertSickle(G,5,2); //invokes procedure with degree bound 5 and 2 variables // note that the optional parameters are not necessary, due to the finiteness // of the K-dimension of the factor algebra lpDHilbertSickle(G); // procedure with ring parameters lpDHilbertSickle(G,0); // procedure without degreebound } proc lpHilbert(ideal G, list #) "USAGE: lpHilbert(G[,degbound,n]); G an ideal, degbound, n optional integers RETURN: intvec, containing the coefficients of the Hilbert series PURPOSE:Computing the Hilbert series ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If degbound is set, there will be a degree bound added. 0 means no @* degree bound. Default: attrib(basering,uptodeg). @* - n is the number of variables, which can be set to a different number. @* Default: attrib(basering, lV). @* - If I is returned, then I[k] is the (k-1)-th coefficient of the Hilbert @* series. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example lpHilbert; shows examples " {int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV"); if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}} if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}} list L; L = lp2ivId(normalize(lead(G))); return(ivHilbert(L,n,degbound)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a //Groebner basis lpHilbert(G,5,2); // invokes procedure with degree bound 5 and 2 variables // note that the optional parameters are not necessary, due to the finiteness // of the K-dimension of the factor algebra lpDHilbert(G); // procedure with ring parameters lpDHilbert(G,0); // procedure without degreebound } proc lpDimCheck(ideal G) "USAGE: lpDimCheck(G); RETURN: int, 1 if K-dimension of the factor algebra is infinite, 0 otherwise PURPOSE:Checking a factor algebra for finiteness of the K-dimension ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. EXAMPLE: example lpDimCheck; shows examples " {int n = attrib(basering,"lV"); list L; ideal R; R = normalize(lead(G)); L = lp2ivId(R); return(ivDimCheck(L,n)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // Groebner basis ideal I = x(1)*x(2), y(1)*x(2)*y(3), x(1)*y(2)*x(3); // Groebner basis lpDimCheck(G); // invokes procedure, factor algebra is of finite K-dimension lpDimCheck(I); // invokes procedure, factor algebra is of infinite Kdimension } proc lpKDim(ideal G, list #) "USAGE: lpKDim(G[,degbound, n]); G an ideal, degbound, n optional integers RETURN: int, the K-dimension of the factor algebra PURPOSE:Computing the K-dimension of a factor algebra, given via an ideal ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If degbound is set, there will be a degree bound added. 0 means no @* degree bound. Default: attrib(basering, uptodeg). @* - n is the number of variables, which can be set to a different number. @* Default: attrib(basering, lV). @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example lpKDim; shows examples " {int degbound = attrib(basering, "uptodeg");int n = attrib(basering, "lV"); if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}} if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}} list L; L = lp2ivId(normalize(lead(G))); return(ivKDim(L,n,degbound)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a Groebner basis lpKDim(G); //procedure invoked with ring parameters // the factor algebra is finite, so the degree bound given by the Letterplace // ring is not necessary lpKDim(G,0); // procedure without any degree bound } proc lpMis2Base(ideal M) "USAGE: lpMis2Base(M); M an ideal RETURN: ideal, a K-basis of the factor algebra PURPOSE:Computing a K-basis out of given mistletoes ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - M contains only monomials NOTE: - The mistletoes have to be ordered lexicographically -> OrdMisLex. EXAMPLE: example lpMis2Base; shows examples " {list L; L = lpId2ivLi(M); return(ivL2lpI(ivMis2Base(L))); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal L = x(1)*y(2),y(1)*x(2)*y(3); // ideal containing the mistletoes lpMis2Base(L); // returns the K-basis of the factor algebra } proc lpMis2Dim(ideal M) "USAGE: lpMis2Dim(M); M an ideal RETURN: int, the K-dimension of the factor algebra PURPOSE:Computing the K-dimension out of given mistletoes ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - M contains only monomials NOTE: - The mistletoes have to be ordered lexicographically -> OrdMisLex. EXAMPLE: example lpMis2Dim; shows examples " {list L; L = lpId2ivLi(M); return(ivMis2Dim(L)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal L = x(1)*y(2),y(1)*x(2)*y(3); // ideal containing the mistletoes lpMis2Dim(L); // returns the K-dimension of the factor algebra } proc lpOrdMisLex(ideal M) "USAGE: lpOrdMisLex(M); M an ideal of mistletoes RETURN: ideal, containing the mistletoes, ordered lexicographically PURPOSE:A given set of mistletoes is ordered lexicographically ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. NOTE: This is preprocessing, it is not needed if the mistletoes are returned @* from the sickle algorithm. EXAMPLE: example lpOrdMisLex; shows examples " {return(ivL2lpI(sort(lpId2ivLi(M))[1]));} example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal M = x(1)*y(2)*x(3), y(1)*y(2)*x(3), x(1)*x(2), y(1)*x(2)*x(3)*x(4); // some monomials lpOrdMisLex(M); // orders the monomials lexicographically } proc lpSickle(ideal G, list #) "USAGE: lpSickle(G[,degbound,n]); G an ideal, degbound, n optional integers RETURN: ideal PURPOSE:Computing the mistletoes of K[X]/ ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If degbound is set, there will be a degree bound added. 0 means no @* degree bound. Default: attrib(basering,uptodeg). @* - n is the number of variables, which can be set to a different number. @* Default: attrib(basering, lV). @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example lpSickle; shows examples " {int degbound = attrib(basering,"uptodeg"); int n = attrib(basering, "lV"); if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}} if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}} list L; ideal R; R = normalize(lead(G)); L = lp2ivId(R); L = ivSickle(L,n,degbound); R = ivL2lpI(L); return(R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a //Groebner basis lpSickle(G); //invokes the procedure with ring parameters // the factor algebra is finite, so the degree bound given by the Letterplace // ring is not necessary lpSickle(G,0); // procedure without any degree bound } proc lpSickleDim(ideal G, list #) "USAGE: lpSickleDim(G[,degbound,n]); G an ideal, degbound, n optional integers RETURN: list PURPOSE:Computing the K-dimension and the mistletoes ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If L is the list returned, then L[1] is an integer, the K-dimension, @* L[2] is an ideal, the mistletoes. @* - If degbound is set, there will be a degree bound added. 0 means no @* degree bound. Default: attrib(basering,uptodeg). @* - n is the number of variables, which can be set to a different number. @* Default: attrib(basering, lV). @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example lpSickleDim; shows examples " {int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV"); if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}} if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}} list L; L = lp2ivId(normalize(lead(G))); L = ivSickleDim(L,n,degbound); L[2] = ivL2lpI(L[2]); return(L); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a //Groebner basis lpSickleDim(G); // invokes the procedure with ring parameters // the factor algebra is finite, so the degree bound given by the Letterplace // ring is not necessary lpSickleDim(G,0); // procedure without any degree bound } proc lpSickleHil(ideal G, list #) "USAGE: lpSickleHil(G); RETURN: list PURPOSE:Computing the Hilbert series and the mistletoes ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: - If L is the list returned, then L[1] is an intvec, corresponding to the @* Hilbert series, L[2] is an ideal, the mistletoes. @* - If degbound is set, there will be a degree bound added. 0 means no @* degree bound. Default: attrib(basering,uptodeg). @* - n is the number of variables, which can be set to a different number. @* Default: attrib(basering, lV). @* - If I = L[1] is the intvec returned, then I[k] is the (k-1)-th @* coefficient of the Hilbert series. @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example lpSickleHil; shows examples " {int degbound = attrib(basering,"uptodeg");int n = attrib(basering, "lV"); if (size(#) > 0){if (typeof(#[1])=="int"){if (#[1] >= 0){degbound = #[1];}}} if (size(#) > 1){if (typeof(#[1])=="int"){if (#[2] > 0){n = #[2];}}} list L; L = lp2ivId(normalize(lead(G))); L = ivSickleHil(L,n,degbound); L[2] = ivL2lpI(L[2]); return(L); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // ideal G contains a //Groebner basis lpSickleHil(G); // invokes the procedure with ring parameters // the factor algebra is finite, so the degree bound given by the Letterplace // ring is not necessary lpSickleHil(G,0); // procedure without any degree bound } proc sickle(ideal G, list #) "USAGE: sickle(G[,m, d, h, degbound]); G an ideal; m,d,h,degbound optional @* integers RETURN: list PURPOSE:Allowing the user to access all procs with one command ASSUME: - basering is a Letterplace ring. G is a Letterplace ideal. @* - if you specify a different degree bound degbound, @* degbound <= attrib(basering,uptodeg) should hold. NOTE: The returned object will always be a list, but the entries of the @* returned list may be very different @* case m=1,d=1,h=1: see lpDHilbertSickle @* case m=1,d=1,h=0: see lpSickleDim @* case m=1,d=0,h=1: see lpSickleHil @* case m=1,d=0,h=0: see lpSickle (this is the default case) @* case m=0,d=1,h=1: see lpDHilbert @* case m=0,d=1,h=0: see lpKDim @* case m=0,d=0,h=1: see lpHilbert @* case m=0,d=0,h=0: returns an error @* - If degbound is set, there will be a degree bound added. 0 means no @* degree bound. Default: attrib(basering,uptodeg). @* - If the K-dimension is known to be infinite, a degree bound is needed EXAMPLE: example sickle; shows examples " {int m,d,h,degbound; m = 1; d = 0; h = 0; degbound = attrib(basering,"uptodeg"); if (size(#) > 0) {if (typeof(#[1])=="int"){if (#[1] < 1) {m = 0;}}} if (size(#) > 1) {if (typeof(#[1])=="int"){if (#[2] > 0) {d = 1;}}} if (size(#) > 2) {if (typeof(#[1])=="int"){if (#[3] > 0) {h = 1;}}} if (size(#) > 3) {if (typeof(#[1])=="int"){if (#[4] >= 0) {degbound = #[4];}}} if (m == 1) {if (d == 0) {if (h == 0) {return(lpSickle(G,degbound,attrib(basering,"lV")));} else {return(lpSickleHil(G,degbound,attrib(basering,"lV")));} } else {if (h == 0) {return(lpSickleDim(G,degbound,attrib(basering,"lV")));} else {return(lpDHilbertSickle(G,degbound,attrib(basering,"lV")));} } } else {if (d == 0) {if (h == 0) {ERROR("You request to do nothing, so relax and do so");} else {return(lpHilbert(G,degbound,attrib(basering,"lV")));} } else {if (h == 0) {return(lpKDim(G,degbound,attrib(basering,"lV")));} else {return(lpDHilbert(G,degbound,attrib(basering,"lV")));} } } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; def R = makeLetterplaceRing(5); // constructs a Letterplace ring setring R; // sets basering to Letterplace ring ideal G = x(1)*x(2), y(1)*y(2),x(1)*y(2)*x(3); // G contains a Groebner basis sickle(G,1,1,1); // computes mistletoes, K-dimension and the Hilbert series sickle(G,1,0,0); // computes mistletoes only sickle(G,0,1,0); // computes K-dimension only sickle(G,0,0,1); // computes Hilbert series only } /////////////////////////////////////////////////////////////////////////////// proc tst_fpadim() { example ivDHilbert; example ivDHilbertSickle; example ivDimCheck; example ivHilbert; example ivKDim; example ivMis2Base; example ivMis2Dim; example ivOrdMisLex; example ivSickle; example ivSickleHil; example ivSickleDim; example lpDHilbert; example lpDHilbertSickle; example lpHilbert; example lpDimCheck; example lpKDim; example lpMis2Base; example lpMis2Dim; example lpOrdMisLex; example lpSickle; example lpSickleHil; example lpSickleDim; example sickle; example ivL2lpI; example iv2lp; example iv2lpList; example iv2lpMat; example lp2iv; example lp2ivId; example lpId2ivLi; } /* Here are some examples one may try. Just copy them into your console. These are relations for braid groups, up to degree d: LIB "fpadim.lib"; ring r = 0,(x,y,z),dp; int d =10; // degree def R = makeLetterplaceRing(d); setring R; ideal I = y(1)*x(2)*y(3) - z(1)*y(2)*z(3), x(1)*y(2)*x(3) - z(1)*x(2)*y(3), z(1)*x(2)*z(3) - y(1)*z(2)*x(3), x(1)*x(2)*x(3) + y(1)*y(2)*y(3) + z(1)*z(2)*z(3) + x(1)*y(2)*z(3); option(prot); option(redSB);option(redTail);option(mem); ideal J = system("freegb",I,d,3); lpDimCheck(J); sickle(J,1,1,1,d);//Computes mistletoes, K-dimension and the Hilbert series LIB "fpadim.lib"; ring r = 0,(x,y,z),dp; int d =11; // degree def R = makeLetterplaceRing(d); setring R; ideal I = y(1)*x(2)*y(3) - z(1)*y(2)*z(3), x(1)*y(2)*z(3) - z(1)*x(2)*y(3), z(1)*x(2)*z(3) - y(1)*z(2)*x(3), x(1)*x(2)*x(3) + y(1)*y(2)*y(3) + z(1)*z(2)*z(3) + x(1)*y(2)*z(3); option(prot); option(redSB);option(redTail);option(mem); ideal J = system("freegb",I,d,3); lpDimCheck(J); sickle(J,1,1,1,d); LIB "fpadim.lib"; ring r = 0,(x,y,z),dp; int d = 6; // degree def R = makeLetterplaceRing(d); setring R; ideal I = y(1)*x(2)*y(3) - z(1)*y(2)*z(3), x(1)*y(2)*x(3) - z(1)*x(2)*y(3), z(1)*x(2)*z(3) - y(1)*z(2)*x(3), x(1)*x(2)*x(3) -2*y(1)*y(2)*y(3) + 3*z(1)*z(2)*z(3) -4*x(1)*y(2)*z(3) + 5*x(1)*z(2)*z(3)- 6*x(1)*y(2)*y(3) +7*x(1)*x(2)*z(3) - 8*x(1)*x(2)*y(3); option(prot); option(redSB);option(redTail);option(mem); ideal J = system("freegb",I,d,3); lpDimCheck(J); sickle(J,1,1,1,d); */ /* Here are some examples, which can also be found in [studzins]: // takes up to 880Mb of memory LIB "fpadim.lib"; ring r = 0,(x,y,z),dp; int d =10; // degree def R = makeLetterplaceRing(d); setring R; ideal I = z(1)*z(2)*z(3)*z(4) + y(1)*x(2)*y(3)*x(4) - x(1)*y(2)*y(3)*x(4) - 3*z(1)*y(2)*x(3)*z(4), x(1)*x(2)*x(3) + y(1)*x(2)*y(3) - x(1)*y(2)*x(3), z(1)*y(2)*x(3)-x(1)*y(2)*z(3) + z(1)*x(2)*z(3); option(prot); option(redSB);option(redTail);option(mem); ideal J = system("freegb",I,d,nvars(r)); lpDimCheck(J); sickle(J,1,1,1,d); // dimension is 24872 LIB "fpadim.lib"; ring r = 0,(x,y,z),dp; int d =10; // degree def R = makeLetterplaceRing(d); setring R; ideal I = x(1)*y(2) + y(1)*z(2), x(1)*x(2) + x(1)*y(2) - y(1)*x(2) - y(1)*y(2); option(prot); option(redSB);option(redTail);option(mem); ideal J = system("freegb",I,d,3); lpDimCheck(J); sickle(J,1,1,1,d); */ singular-4.0.3+ds/Singular/LIB/freegb.lib000066400000000000000000002450651266270727000201050ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version freegb.lib 4.0.0.0 Jun_2013 "; // $Id: 60903f7719c53dc5b53ffb17de37a0b3053e6181 $ category="Noncommutative"; info=" LIBRARY: freegb.lib Compute two-sided Groebner bases in free algebras via @* letterplace AUTHORS: Viktor Levandovskyy, viktor.levandovskyy@math.rwth-aachen.de @* Grischa Studzinski, grischa.studzinski@math.rwth-aachen.de OVERVIEW: For the theory, see chapter 'Letterplace' in the @sc{Singular} Manual PROCEDURES: makeLetterplaceRing(d); creates a ring with d blocks of shifted original @* variables letplaceGBasis(I); computes two-sided Groebner basis of a letterplace ideal I @* up to a degree bound lpNF(f,I); normal form of f with respect to ideal I freeGBasis(L, n); computes two-sided Groebner basis of an ideal, encoded via @* list L, up to degree n setLetterplaceAttributes(R,d,b); supplies ring R with the letterplace structure lpMult(f,g); letterplace multiplication of letterplace polynomials shiftPoly(p,i); compute the i-th shift of letterplace polynomial p lpPower(f,n); natural power of a letterplace polynomial lp2lstr(K, s); convert letter-place ideal to a list of modules lst2str(L[, n]); convert a list (of modules) into polynomials in free algebra mod2str(M[, n]); convert a module into a polynomial in free algebra vct2str(M[, n]); convert a vector into a word in free algebra lieBracket(a,b[, N]); compute Lie bracket ab-ba of two letterplace polynomials serreRelations(A,z); compute the homogeneous part of Serre's relations @* associated to a generalized Cartan matrix A fullSerreRelations(A,N,C,P,d); compute the ideal of all Serre's relations @* associated to a generalized Cartan matrix A isVar(p); check whether p is a power of a single variable ademRelations(i,j); compute the ideal of Adem relations for i<2j in char 0 SEE ALSO: fpadim_lib, LETTERPLACE "; // this library computes two-sided GB of an ideal // in a free associative algebra // a monomial is encoded via a vector V // where V[1] = coefficient // V[1+i] = the corresponding symbol LIB "qhmoduli.lib"; // for Max LIB "bfun.lib"; // for inForm proc tstfreegb() { /* tests all procs for consistency */ /* adding the new proc, add it here */ example makeLetterplaceRing; example letplaceGBasis; example freeGBasis; example setLetterplaceAttributes; /* secondary */ example lpMult; example shiftPoly; example lpPower; example lp2lstr; example lst2str; example mod2str; example vct2str; example lieBracket; example serreRelations; example fullSerreRelations; example isVar; example ademRelations; } proc setLetterplaceAttributes(def R, int uptodeg, int lV) "USAGE: setLetterplaceAttributes(R, d, b); R a ring, b,d integers RETURN: ring with special attributes set PURPOSE: sets attributes for a letterplace ring: @* 'isLetterplaceRing' = true, 'uptodeg' = d, 'lV' = b, where @* 'uptodeg' stands for the degree bound, @* 'lV' for the number of variables in the block 0. NOTE: Activate the resulting ring by using @code{setring} " { if (uptodeg*lV != nvars(R)) { ERROR("uptodeg and lV do not agree on the basering!"); } // Set letterplace-specific attributes for the output ring! attrib(R, "uptodeg", uptodeg); attrib(R, "lV", lV); attrib(R, "isLetterplaceRing", 1); return (R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp; def R = setLetterplaceAttributes(r, 4, 2); setring R; attrib(R,"isLetterplaceRing"); lieBracket(x(1),y(1),2); } // obsolete? static proc lshift(module M, int s, string varing, def lpring) { // FINALLY IMPLEMENTED AS A PART OT THE CODE // shifts a polynomial from the ring R to s positions // M lives in varing, the result in lpring // to be run from varing int i, j, k, sm, sv; vector v; // execute("setring "+lpring); setring lpring; poly @@p; ideal I; execute("setring "+varing); sm = ncols(M); for (i=1; i<=s; i++) { // modules, e.g. free polynomials for (j=1; j<=sm; j++) { //vectors, e.g. free monomials v = M[j]; sv = size(v); sp = "@@p = @@p + "; for (k=2; k<=sv; k++) { sp = sp + string(v[k])+"("+string(k-1+s)+")*"; } sp = sp + string(v[1])+";"; // coef; setring lpring; // execute("setring "+lpring); execute(sp); execute("setring "+varing); } setring lpring; // execute("setring "+lpring); I = I,@@p; @@p = 0; } setring lpring; //execute("setring "+lpring); export(I); // setring varing; execute("setring "+varing); } static proc skip0(vector v) { // skips zeros in a vector, producing another vector if ( (v[1]==0) || (v==0) ) { return(vector(0)); } int sv = nrows(v); int sw = size(v); if (sv == sw) { return(v); } int i; int j=1; vector w; for (i=1; i<=sv; i++) { if (v[i] != 0) { w = w + v[i]*gen(j); j++; } } return(w); } proc lst2str(list L, list #) "USAGE: lst2str(L[,n]); L a list of modules, n an optional integer RETURN: list (of strings) PURPOSE: convert a list (of modules) into polynomials in free algebra EXAMPLE: example lst2str; shows examples NOTE: if an optional integer is not 0, stars signs are used in multiplication " { // returns a list of strings // being sentences in words built from L // if #[1] = 1, use * between generators int useStar = 0; if ( size(#)>0 ) { if ( typeof(#[1]) != "int") { ERROR("Second argument of type int expected"); } if (#[1]) { useStar = 1; } } int i; int s = size(L); if (s<1) { return(list(""));} list N; for(i=1; i<=s; i++) { if ((typeof(L[i]) == "module") || (typeof(L[i]) == "matrix") ) { N[i] = mod2str(L[i],useStar); } else { "module or matrix expected in the list"; return(N); } } return(N); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp(1),dp(2)); module M = [-1,x,y],[-7,y,y],[3,x,x]; module N = [1,x,y,x,y],[-2,y,x,y,x],[6,x,y,y,x,y]; list L; L[1] = M; L[2] = N; lst2str(L); lst2str(L[1],1); } proc mod2str(module M, list #) "USAGE: mod2str(M[,n]); M a module, n an optional integer RETURN: string PURPOSE: convert a module into a polynomial in free algebra EXAMPLE: example mod2str; shows examples NOTE: if an optional integer is not 0, stars signs are used in multiplication " { if (size(M)==0) { return(""); } // returns a string // a sentence in words built from M // if #[1] = 1, use * between generators int useStar = 0; if ( size(#)>0 ) { if ( typeof(#[1]) != "int") { ERROR("Second argument of type int expected"); } if (#[1]) { useStar = 1; } } int i; int s = ncols(M); string t; string mp; for(i=1; i<=s; i++) { mp = vct2str(M[i],useStar); if (mp[1] == "-") { t = t + mp; } else { if (mp != "") { t = t + "+" + mp; } } } if (t[1]=="+") { t = t[2..size(t)]; // remove first "+" } return(t); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp); module M = [1,x,y,x,y],[-2,y,x,y,x],[6,x,y,y,x,y]; mod2str(M); mod2str(M,1); } proc vct2str(vector v, list #) "USAGE: vct2str(v[,n]); v a vector, n an optional integer RETURN: string PURPOSE: convert a vector into a word in free algebra EXAMPLE: example vct2str; shows examples NOTE: if an optional integer is not 0, stars signs are used in multiplication " { if (v==0) { return(""); } // if #[1] = 1, use * between generators int useStar = 0; if ( size(#)>0 ) { if (#[1]) { useStar = 1; } } int ppl = printlevel-voice+2; // for a word, encoded by v // produces a string for it v = skip0(v); if (v==0) { return(string(""));} number cf = leadcoef(v[1]); int s = size(v); string vs,vv,vp,err; int i,j,p,q; for (i=1; i<=s-1; i++) { p = isVar(v[i+1]); if (p==0) { err = "Error: monomial expected at nonzero position " + string(i+1); ERROR(err+" in vct2str"); // dbprint(ppl,err); // return("_"); } if (p==1) { if (useStar && (size(vs) >0)) { vs = vs + "*"; } vs = vs + string(v[i+1]); } else //power { vv = string(v[i+1]); q = find(vv,"^"); if (q==0) { q = find(vv,string(p)); if (q==0) { err = "error in find for string "+vv; dbprint(ppl,err); return("_"); } } // q>0 vp = vv[1..q-1]; for(j=1;j<=p;j++) { if (useStar && (size(vs) >0)) { vs = vs + "*"; } vs = vs + vp; } } } string scf; if (cf == -1) { scf = "-"; } else { scf = string(cf); if ( (cf == 1) && (size(vs)>0) ) { scf = ""; } } if (useStar && (size(scf) >0) && (scf!="-") ) { scf = scf + "*"; } vs = scf + vs; return(vs); } example { "EXAMPLE:"; echo = 2; ring r = (0,a),(x,y3,z(1)),dp; vector v = [-7,x,y3^4,x2,z(1)^3]; vct2str(v); vct2str(v,1); vector w = [-7a^5+6a,x,y3,y3,x,z(1),z(1)]; vct2str(w); vct2str(w,1); } proc isVar(poly p) "USAGE: isVar(p); poly p RETURN: int PURPOSE: check, whether leading monomial of p is a power of a single variable @* from the basering. Returns the exponent or 0 if p is multivariate. EXAMPLE: example isVar; shows examples " { // checks whether p is a variable indeed // if it's a power of a variable, returns the power if (p==0) { return(0); } //"p=0"; poly q = leadmonom(p); if ( (p-lead(p)) !=0 ) { return(0); } // "p-lm(p)>0"; intvec v = leadexp(p); int s = size(v); int i=1; int cnt = 0; int pwr = 0; for (i=1; i<=s; i++) { if (v[i] != 0) { cnt++; pwr = v[i]; } } // "cnt:"; cnt; if (cnt==1) { return(pwr); } else { return(0); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; poly f = xy+1; isVar(f); poly g = y^3; isVar(g); poly h = 7*x^3; isVar(h); poly i = 1; isVar(i); } // new conversion routines static proc id2words(ideal I, int d) { // NOT FINISHED // input: ideal I of polys in letter-place notation // in the ring with d real vars // output: the list of strings: associative words // extract names of vars int i,m,n; string s; string place = "(1)"; list lv; for(i=1; i<=d; i++) { s = string(var(i)); // get rid of place n = find(s, place); if (n>0) { s = s[1..n-1]; } lv[i] = s; } poly p,q; for (i=1; i<=ncols(I); i++) { if (I[i] != 0) { p = I[i]; while (p!=0) { q = leadmonom(p); } } } return(lv); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(1),z(1),x(2),y(2),z(2)),dp; ideal I = x(1)*y(2) -z(1)*x(2); id2words(I,3); } static proc mono2word(poly p, int d) { } proc letplaceGBasis(ideal I) "USAGE: letplaceGBasis(I); I an ideal RETURN: ideal ASSUME: basering is a Letterplace ring, an ideal consists of Letterplace @* polynomials PURPOSE: compute the two-sided Groebner basis of an ideal I via Letterplace @* algorithm NOTE: the degree bound for this computation is read off the letterplace @* structure of basering EXAMPLE: example letplaceGBasis; shows examples " { if (lpAssumeViolation()) { ERROR("Incomplete Letterplace structure on the basering!"); } int ppl = printlevel-voice+2; def save = basering; // assumes of the ring have been checked // run the computation - it will test assumes on the ideal int uptodeg = attrib(save,"uptodeg"); int lV = attrib(save,"lV"); dbprint(ppl,"start computing GB"); ideal J = system("freegb",I,uptodeg,lV); dbprint(ppl,"finished computing GB"); dbprint(ppl-1,"the result is:"); dbprint(ppl-1,J); return(J); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp(1),dp(2)); int degree_bound = 5; def R = makeLetterplaceRing(5); setring R; ideal I = -x(1)*y(2)-7*y(1)*y(2)+3*x(1)*x(2), x(1)*y(2)*x(3)-y(1)*x(2)*y(3); ideal J = letplaceGBasis(I); J; // now transfom letterplace polynomials into strings of words lp2lstr(J,r); // export an object called @code{@LN} to the ring r setring r; // change to the ring r lst2str(@LN,1); } // given the element -7xy^2x, it is represented as [-7,x,y^2,x] or as [-7,x,y,y,x] // use the orig ord on (x,y,z) and expand it blockwise to (x(i),y(i),z(i)) // the correspondences: // monomial in K <<--->> vector in R // polynomial in K <<--->> list of vectors (matrix/module) in R // ideal in K <<--->> list of matrices/modules in R // 1. form a new ring // 2. NOP // 3. compute GB -> with the kernel stuff // 4. skip shifted elts (check that no such exist?) // 5. go back to orig vars, produce strings/modules // 6. return the result proc freeGBasis(list LM, int d) "USAGE: freeGBasis(L, d); L a list of modules, d an integer RETURN: ring ASSUME: L has a special form. Namely, it is a list of modules, where - each generator of every module stands for a monomial times coefficient in @* free algebra, - in such a vector generator, the 1st entry is a nonzero coefficient from the @* ground field - and each next entry hosts a variable from the basering. PURPOSE: compute the two-sided Groebner basis of an ideal, encoded by L @* in the free associative algebra, up to degree d NOTE: Apply @code{lst2str} to the output in order to obtain a better readable @* presentation EXAMPLE: example freeGBasis; shows examples " { // d = up to degree, will be shifted to d+1 if (d<1) {"bad d"; return(0);} int ppl = printlevel-voice+2; string err = ""; int i,j,s; def save = basering; // determine max no of places in the input int slm = size(LM); // numbers of polys in the ideal int sm; intvec iv; module M; for (i=1; i<=slm; i++) { // modules, e.g. free polynomials M = LM[i]; sm = ncols(M); for (j=1; j<=sm; j++) { //vectors, e.g. free monomials iv = iv, size(M[j])-1; // 1 place is reserved by the coeff } } int D = Max(iv); // max size of input words if (d2) { // there are s-1 blocks int nb = s-1; tmp = LR[3][s]; // module ord for (i=1; i<=D; i++) { for (j=1; j<=nb; j++) { LR[3][i*nb+j] = LR[3][j]; } } // size(LR[3]); LR[3][nb*(D+1)+1] = tmp; } L[3] = LR[3]; def @R = ring(L); setring @R; ideal I; poly @p; s = size(OrigNames); // "s:";s; // convert LM to canonical vectors (no powers) setring save; kill M; // M was defined earlier module M; slm = size(LM); // numbers of polys in the ideal int sv,k,l; vector v; // poly p; string sp; setring @R; poly @@p=0; setring save; for (l=1; l<=slm; l++) { // modules, e.g. free polynomials M = LM[l]; sm = ncols(M); // in intvec iv the sizes are stored // modules, e.g. free polynomials for (j=1; j<=sm; j++) { //vectors, e.g. free monomials v = M[j]; sv = size(v); // "sv:";sv; sp = "@@p = @@p + "; for (k=2; k<=sv; k++) { sp = sp + string(v[k])+"("+string(k-1)+")*"; } sp = sp + string(v[1])+";"; // coef; setring @R; execute(sp); setring save; } setring @R; // "@@p:"; @@p; I = I,@@p; @@p = 0; setring save; } kill sp; // 3. compute GB setring @R; dbprint(ppl,"computing GB"); ideal J = system("freegb",I,d,nvars(save)); // ideal J = slimgb(I); dbprint(ppl,J); // 4. skip shifted elts ideal K = select1(J,1..s); // s = size(OrigNames) dbprint(ppl,K); dbprint(ppl, "done with GB"); // K contains vars x(1),...z(1) = images of originals // 5. go back to orig vars, produce strings/modules if (K[1] == 0) { "no reasonable output, GB gives 0"; return(0); } int sk = size(K); int sp, sx, a, b; intvec x; poly p,q; poly pn; // vars in 'save' setring save; module N; list LN; vector V; poly pn; // test and skip exponents >=2 setring @R; for(i=1; i<=sk; i++) { p = K[i]; while (p!=0) { q = lead(p); // "processing q:";q; x = leadexp(q); sx = size(x); for(k=1; k<=sx; k++) { if ( x[k] >= 2 ) { err = "skip: the value x[k] is " + string(x[k]); dbprint(ppl,err); // return(0); K[i] = 0; p = 0; q = 0; break; } } p = p - q; } } K = simplify(K,2); sk = size(K); for(i=1; i<=sk; i++) { // setring save; // V = 0; setring @R; p = K[i]; while (p!=0) { q = lead(p); err = "processing q:" + string(q); dbprint(ppl,err); x = leadexp(q); sx = size(x); pn = leadcoef(q); setring save; pn = imap(@R,pn); V = V + leadcoef(pn)*gen(1); for(k=1; k<=sx; k++) { if (x[k] ==1) { a = k div s; // block number=a+1, a!=0 b = k % s; // remainder // printf("a: %s, b: %s",a,b); if (b == 0) { // that is it's the last var in the block b = s; a = a-1; } V = V + var(b)*gen(a+2); } // else // { // printf("error: the value x[k] is %s", x[k]); // return(0); // } } err = "V: " + string(V); dbprint(ppl,err); // printf("V: %s", string(V)); N = N,V; V = 0; setring @R; p = p - q; pn = 0; } setring save; LN[i] = simplify(N,2); N = 0; } setring save; return(LN); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp(1),dp(2)); // ring r = 0,(x,y,z),(a(3,0,2), dp(2)); module M = [-1,x,y],[-7,y,y],[3,x,x]; // stands for free poly -xy - 7yy - 3xx module N = [1,x,y,x],[-1,y,x,y]; // stands for free poly xyx - yxy list L; L[1] = M; L[2] = N; // list of modules stands for an ideal in free algebra lst2str(L); // list to string conversion of input polynomials def U = freeGBasis(L,5); // 5 is the degree bound lst2str(U); } static proc crs(list LM, int d) "USAGE: crs(L, d); L a list of modules, d an integer RETURN: ring PURPOSE: create a ring and shift the ideal EXAMPLE: example crs; shows examples " { // d = up to degree, will be shifted to d+1 if (d<1) {"bad d"; return(0);} int ppl = printlevel-voice+2; string err = ""; int i,j,s; def save = basering; // determine max no of places in the input int slm = size(LM); // numbers of polys in the ideal int sm; intvec iv; module M; for (i=1; i<=slm; i++) { // modules, e.g. free polynomials M = LM[i]; sm = ncols(M); for (j=1; j<=sm; j++) { //vectors, e.g. free monomials iv = iv, size(M[j])-1; // 1 place is reserved by the coeff } } int D = Max(iv); // max size of input words if (d2) { // there are s-1 blocks int nb = s-1; tmp = LR[3][s]; // module ord for (i=1; i<=D; i++) { for (j=1; j<=nb; j++) { LR[3][i*nb+j] = LR[3][j]; } } // size(LR[3]); LR[3][nb*(D+1)+1] = tmp; } L[3] = LR[3]; def @R = ring(L); setring @R; ideal I; poly @p; s = size(OrigNames); // "s:";s; // convert LM to canonical vectors (no powers) setring save; kill M; // M was defined earlier module M; slm = size(LM); // numbers of polys in the ideal int sv,k,l; vector v; // poly p; string sp; setring @R; poly @@p=0; setring save; for (l=1; l<=slm; l++) { // modules, e.g. free polynomials M = LM[l]; sm = ncols(M); // in intvec iv the sizes are stored for (i=0; i<=d-iv[l]; i++) { // modules, e.g. free polynomials for (j=1; j<=sm; j++) { //vectors, e.g. free monomials v = M[j]; sv = size(v); // "sv:";sv; sp = "@@p = @@p + "; for (k=2; k<=sv; k++) { sp = sp + string(v[k])+"("+string(k-2+i)+")*"; } sp = sp + string(v[1])+";"; // coef; setring @R; execute(sp); setring save; } setring @R; // "@@p:"; @@p; I = I,@@p; @@p = 0; setring save; } } setring @R; export I; return(@R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp(1),dp(2)); module M = [-1,x,y],[-7,y,y],[3,x,x]; module N = [1,x,y,x],[-1,y,x,y]; list L; L[1] = M; L[2] = N; lst2str(L); def U = crs(L,5); setring U; U; I; } static proc polylen(ideal I) { // returns the ideal of length of polys int i; intvec J; number s = 0; for(i=1;i<=ncols(I);i++) { J[i] = size(I[i]); s = s + J[i]; } printf("the sum of length %s",s); // print(s); return(J); } // new: uniting both mLR1 (homog) and mLR2 (nonhomog) proc makeLetterplaceRing(int d, list #) "USAGE: makeLetterplaceRing(d [,h]); d an integer, h an optional integer RETURN: ring PURPOSE: creates a ring with the ordering, used in letterplace computations NOTE: if h is given and nonzero, the pure homogeneous letterplace block @* ordering will be used. EXAMPLE: example makeLetterplaceRing; shows examples " { int use_old_mlr = 0; if ( size(#)>0 ) { if (( typeof(#[1]) == "int" ) || ( typeof(#[1]) == "poly" ) ) { poly x = poly(#[1]); if (x!=0) { use_old_mlr = 1; } } } if (use_old_mlr) { def @A = makeLetterplaceRing1(d); } else { def @A = makeLetterplaceRing2(d); } return(@A); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp(1),dp(2)); def A = makeLetterplaceRing(2); setring A; A; attrib(A,"isLetterplaceRing"); attrib(A,"uptodeg"); // degree bound attrib(A,"lV"); // number of variables in the main block setring r; def B = makeLetterplaceRing(2,1); // to compare: setring B; B; } //proc freegbRing(int d) static proc makeLetterplaceRing1(int d) "USAGE: makeLetterplaceRing1(d); d an integer RETURN: ring PURPOSE: creates a ring with a special ordering, suitable for @* the use of homogeneous letterplace (d blocks of shifted original variables) EXAMPLE: example makeLetterplaceRing1; shows examples " { // d = up to degree, will be shifted to d+1 if (d<1) {"bad d"; return(0);} int uptodeg = d; int lV = nvars(basering); int ppl = printlevel-voice+2; string err = ""; int i,j,s; def save = basering; int D = d-1; list LR = ringlist(save); list L, tmp; L[1] = LR[1]; // ground field L[4] = LR[4]; // quotient ideal tmp = LR[2]; // varnames s = size(LR[2]); for (i=1; i<=D; i++) { for (j=1; j<=s; j++) { tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")"; } } for (i=1; i<=s; i++) { tmp[i] = string(tmp[i])+"("+string(1)+")"; } L[2] = tmp; list OrigNames = LR[2]; // ordering: d blocks of the ord on r // try to get whether the ord on r is blockord itself // TODO: make L(2) ordering! exponent is maximally 2 s = size(LR[3]); if (s==2) { // not a blockord, 1 block + module ord tmp = LR[3][s]; // module ord for (i=1; i<=D; i++) { LR[3][s-1+i] = LR[3][1]; } LR[3][s+D] = tmp; } if (s>2) { // there are s-1 blocks int nb = s-1; tmp = LR[3][s]; // module ord for (i=1; i<=D; i++) { for (j=1; j<=nb; j++) { LR[3][i*nb+j] = LR[3][j]; } } // size(LR[3]); LR[3][nb*(D+1)+1] = tmp; } L[3] = LR[3]; def @R = ring(L); // setring @R; // int uptodeg = d; int lV = nvars(basering); // were defined before def @@R = setLetterplaceAttributes(@R,uptodeg,lV); return (@@R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp(1),dp(2)); def A = makeLetterplaceRing1(2); setring A; A; attrib(A,"isLetterplaceRing"); attrib(A,"uptodeg"); // degree bound attrib(A,"lV"); // number of variables in the main block } static proc makeLetterplaceRing2(int d) "USAGE: makeLetterplaceRing2(d); d an integer RETURN: ring PURPOSE: creates a ring with a special ordering, suitable for @* the use of non-homogeneous letterplace NOTE: the matrix for the ordering looks as follows: first row is 1,1,...,1 @* then there come 'd' blocks of shifted original variables EXAMPLE: example makeLetterplaceRing2; shows examples " { // ToDo future: inherit positive weights in the orig ring // complain on nonpositive ones // d = up to degree, will be shifted to d+1 if (d<1) {"bad d"; return(0);} int uptodeg = d; int lV = nvars(basering); int ppl = printlevel-voice+2; string err = ""; int i,j,s; def save = basering; int D = d-1; list LR = ringlist(save); list L, tmp, tmp2, tmp3; L[1] = LR[1]; // ground field L[4] = LR[4]; // quotient ideal tmp = LR[2]; // varnames s = size(LR[2]); for (i=1; i<=D; i++) { for (j=1; j<=s; j++) { tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")"; } } for (i=1; i<=s; i++) { tmp[i] = string(tmp[i])+"("+string(1)+")"; } L[2] = tmp; list OrigNames = LR[2]; // ordering: one 1..1 a above // ordering: d blocks of the ord on r // try to get whether the ord on r is blockord itself // TODO: make L(2) ordering! exponent is maximally 2 s = size(LR[3]); if (s==2) { // not a blockord, 1 block + module ord tmp = LR[3][s]; // module ord for (i=1; i<=d; i++) { LR[3][s-1+i] = LR[3][1]; } // LR[3][s+D] = tmp; LR[3][s+1+D] = tmp; LR[3][1] = list("a",intvec(1: int(d*lV))); // deg-ord } if (s>2) { // there are s-1 blocks int nb = s-1; tmp = LR[3][s]; // module ord to place at the very end tmp2 = LR[3]; tmp2 = tmp2[1..nb]; tmp3[1] = list("a",intvec(1: int(d*lV))); // deg-ord, insert as the 1st for (i=1; i<=d; i++) { tmp3 = tmp3 + tmp2; } tmp3 = tmp3 + list(tmp); LR[3] = tmp3; // for (i=1; i<=d; i++) // { // for (j=1; j<=nb; j++) // { // // LR[3][i*nb+j+1]= LR[3][j]; // LR[3][i*nb+j+1]= tmp2[j]; // } // } // // size(LR[3]); // LR[3][(s-1)*d+2] = tmp; // LR[3] = list("a",intvec(1: int(d*lV))) + LR[3]; // deg-ord, insert as the 1st // remove everything behind nb*(D+1)+1 ? // tmp = LR[3]; // LR[3] = tmp[1..size(tmp)-1]; } L[3] = LR[3]; def @R = ring(L); // setring @R; // int uptodeg = d; int lV = nvars(basering); // were defined before def @@R = setLetterplaceAttributes(@R,uptodeg,lV); return (@@R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp(1),dp(2)); def A = makeLetterplaceRing2(2); setring A; A; attrib(A,"isLetterplaceRing"); attrib(A,"uptodeg"); // degree bound attrib(A,"lV"); // number of variables in the main block } // P[s;sigma] approach static proc makeLetterplaceRing3(int d) "USAGE: makeLetterplaceRing1(d); d an integer RETURN: ring PURPOSE: creates a ring with a special ordering, representing @* the original P[s,sigma] (adds d blocks of shifted s) ASSUME: basering is a letterplace ring NOTE: experimental status EXAMPLE: example makeLetterplaceRing1; shows examples " { // d = up to degree, will be shifted to d+1 if (d<1) {"bad d"; return(0);} int uptodeg = d; int lV = nvars(basering); int ppl = printlevel-voice+2; string err = ""; int i,j,s; def save = basering; int D = d-1; list LR = ringlist(save); list L, tmp; L[1] = LR[1]; // ground field L[4] = LR[4]; // quotient ideal tmp = LR[2]; // varnames tmp[size(tmp)+1] = "s"; // add s's // string newSname = "@s"; s = size(LR[2]); for (i=1; i<=D; i++) { for (j=1; j<=s; j++) { tmp[i*s+j] = string(tmp[j])+"("+string(i+1)+")"; } } // the final index is D*s+s = (D+1)*s = degBound*s for (i=1; i<=d; i++) { tmp[FIndex + i] = string(newSname)+"("+string(i)+")"; } L[2] = tmp; list OrigNames = LR[2]; // ordering: d blocks of the MODIFIED ord on r // try to get whether the ord on r is blockord itself // TODO: make L(2) ordering! exponent is maximally 2 s = size(LR[3]); // assume: basering was a letterplace, so get its block tmp = LR[3][1]; // ASSUME: it's a nice block // modify it // add (0,..,0,1) ... as antiblock part intvec iv; list ttmp, tmp1; for (i=1; i<=d; i++) { // the position to hold 1: iv = intvec( gen( i*(lV+1)-1 ) ); ttmp[1] = "a"; ttmp[2] = iv; tmp1[i] = ttmp; } // finished: antiblock part //TOCONTINUE if (s==2) { // not a blockord, 1 block + module ord tmp = LR[3][s]; // module ord for (i=1; i<=D; i++) { LR[3][s-1+i] = LR[3][1]; } LR[3][s+D] = tmp; } if (s>2) { // there are s-1 blocks int nb = s-1; tmp = LR[3][s]; // module ord for (i=1; i<=D; i++) { for (j=1; j<=nb; j++) { LR[3][i*nb+j] = LR[3][j]; } } // size(LR[3]); LR[3][nb*(D+1)+1] = tmp; } L[3] = LR[3]; def @R = ring(L); // setring @R; // int uptodeg = d; int lV = nvars(basering); // were defined before def @@R = setLetterplaceAttributes(@R,uptodeg,lV); return (@@R); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp(1),dp(2)); def A = makeLetterplaceRing3(2); setring A; A; attrib(A,"isLetterplaceRing"); attrib(A,"uptodeg"); // degree bound attrib(A,"lV"); // number of variables in the main block } /* EXAMPLES: //static proc ex_shift() { LIB "freegb.lib"; ring r = 0,(x,y,z),(dp(1),dp(2)); module M = [-1,x,y],[-7,y,y],[3,x,x]; module N = [1,x,y,x],[-1,y,x,y]; list L; L[1] = M; L[2] = N; lst2str(L); def U = crs(L,5); setring U; U; I; poly p = I[2]; // I[8]; p; system("stest",p,7,7,3); // error -> the world is ok poly q1 = system("stest",p,1,7,3); //ok poly q6 = system("stest",p,6,7,3); //ok system("btest",p,3); //ok system("btest",q1,3); //ok system("btest",q6,3); //ok } //static proc test_shrink() { LIB "freegb.lib"; ring r =0,(x,y,z),dp; int d = 5; def R = makeLetterplaceRing(d); setring R; poly p1 = x(1)*y(2)*z(3); poly p2 = x(1)*y(4)*z(5); poly p3 = x(1)*y(1)*z(3); poly p4 = x(1)*y(2)*z(2); poly p5 = x(3)*z(5); poly p6 = x(1)*y(1)*x(3)*z(5); poly p7 = x(1)*y(2)*x(3)*y(4)*z(5); poly p8 = p1+p2+p3+p4+p5 + p6 + p7; p1; system("shrinktest",p1,3); p2; system("shrinktest",p2,3); p3; system("shrinktest",p3,3); p4; system("shrinktest",p4,3); p5; system("shrinktest",p5,3); p6; system("shrinktest",p6,3); p7; system("shrinktest",p7,3); p8; system("shrinktest",p8,3); poly p9 = p1 + 2*p2 + 5*p5 + 7*p7; p9; system("shrinktest",p9,3); } //static proc ex2() { option(prot); LIB "freegb.lib"; ring r = 0,(x,y),dp; module M = [-1,x,y],[3,x,x]; // 3x^2 - xy def U = freegb(M,7); lst2str(U); } //static proc ex_nonhomog() { option(prot); LIB "freegb.lib"; ring r = 0,(x,y,h),dp; list L; module M; M = [-1,y,y],[1,x,x,x]; // x3-y2 L[1] = M; M = [1,x,h],[-1,h,x]; // xh-hx L[2] = M; M = [1,y,h],[-1,h,y]; // yh-hy L[3] = M; def U = freegb(L,4); lst2str(U); // strange elements in the basis } //static proc ex_nonhomog_comm() { option(prot); LIB "freegb.lib"; ring r = 0,(x,y),dp; module M = [-1,y,y],[1,x,x,x]; def U = freegb(M,5); lst2str(U); } //static proc ex_nonhomog_h() { option(prot); LIB "freegb.lib"; ring r = 0,(x,y,h),(a(1,1),dp); module M = [-1,y,y,h],[1,x,x,x]; // x3 - y2h def U = freegb(M,6); lst2str(U); } //static proc ex_nonhomog_h2() { option(prot); LIB "freegb.lib"; ring r = 0,(x,y,h),(dp); list L; module M; M = [-1,y,y,h],[1,x,x,x]; // x3 - y2h L[1] = M; M = [1,x,h],[-1,h,x]; // xh - hx L[2] = M; M = [1,y,h],[-1,h,y]; // yh - hy L[3] = M; def U = freeGBasis(L,3); lst2str(U); // strange answer CHECK } //static proc ex_nonhomog_3() { option(prot); LIB "./freegb.lib"; ring r = 0,(x,y,z),(dp); list L; module M; M = [1,z,y],[-1,x]; // zy - x L[1] = M; M = [1,z,x],[-1,y]; // zx - y L[2] = M; M = [1,y,x],[-1,z]; // yx - z L[3] = M; lst2str(L); list U = freegb(L,4); lst2str(U); // strange answer CHECK } //static proc ex_densep_2() { option(prot); LIB "freegb.lib"; ring r = (0,a,b,c),(x,y),(Dp); // deglex module M = [1,x,x], [a,x,y], [b,y,x], [c,y,y]; lst2str(M); list U = freegb(M,5); lst2str(U); // a=b is important -> finite basis!!! module M = [1,x,x], [a,x,y], [a,y,x], [c,y,y]; lst2str(M); list U = freegb(M,5); lst2str(U); } // END COMMENTED EXAMPLES */ // 1. form a new ring // 2. produce shifted generators // 3. compute GB // 4. skip shifted elts // 5. go back to orig vars, produce strings/modules // 6. return the result static proc freegbold(list LM, int d) "USAGE: freegbold(L, d); L a list of modules, d an integer RETURN: ring PURPOSE: compute the two-sided Groebner basis of an ideal, encoded by L in the free associative algebra, up to degree d EXAMPLE: example freegbold; shows examples " { // d = up to degree, will be shifted to d+1 if (d<1) {"bad d"; return(0);} int ppl = printlevel-voice+2; string err = ""; int i,j,s; def save = basering; // determine max no of places in the input int slm = size(LM); // numbers of polys in the ideal int sm; intvec iv; module M; for (i=1; i<=slm; i++) { // modules, e.g. free polynomials M = LM[i]; sm = ncols(M); for (j=1; j<=sm; j++) { //vectors, e.g. free monomials iv = iv, size(M[j])-1; // 1 place is reserved by the coeff } } int D = Max(iv); // max size of input words if (d2) { // there are s-1 blocks int nb = s-1; tmp = LR[3][s]; // module ord for (i=1; i<=D; i++) { for (j=1; j<=nb; j++) { LR[3][i*nb+j] = LR[3][j]; } } // size(LR[3]); LR[3][nb*(D+1)+1] = tmp; } L[3] = LR[3]; def @R = ring(L); setring @R; ideal I; poly @p; s = size(OrigNames); // "s:";s; // convert LM to canonical vectors (no powers) setring save; kill M; // M was defined earlier module M; slm = size(LM); // numbers of polys in the ideal int sv,k,l; vector v; // poly p; string sp; setring @R; poly @@p=0; setring save; for (l=1; l<=slm; l++) { // modules, e.g. free polynomials M = LM[l]; sm = ncols(M); // in intvec iv the sizes are stored for (i=0; i<=d-iv[l]; i++) { // modules, e.g. free polynomials for (j=1; j<=sm; j++) { //vectors, e.g. free monomials v = M[j]; sv = size(v); // "sv:";sv; sp = "@@p = @@p + "; for (k=2; k<=sv; k++) { sp = sp + string(v[k])+"("+string(k-1+i)+")*"; } sp = sp + string(v[1])+";"; // coef; setring @R; execute(sp); setring save; } setring @R; // "@@p:"; @@p; I = I,@@p; @@p = 0; setring save; } } kill sp; // 3. compute GB setring @R; dbprint(ppl,"computing GB"); // ideal J = groebner(I); ideal J = slimgb(I); dbprint(ppl,J); // 4. skip shifted elts ideal K = select1(J,1..s); // s = size(OrigNames) dbprint(ppl,K); dbprint(ppl, "done with GB"); // K contains vars x(1),...z(1) = images of originals // 5. go back to orig vars, produce strings/modules if (K[1] == 0) { "no reasonable output, GB gives 0"; return(0); } int sk = size(K); int sp, sx, a, b; intvec x; poly p,q; poly pn; // vars in 'save' setring save; module N; list LN; vector V; poly pn; // test and skip exponents >=2 setring @R; for(i=1; i<=sk; i++) { p = K[i]; while (p!=0) { q = lead(p); // "processing q:";q; x = leadexp(q); sx = size(x); for(k=1; k<=sx; k++) { if ( x[k] >= 2 ) { err = "skip: the value x[k] is " + string(x[k]); dbprint(ppl,err); // return(0); K[i] = 0; p = 0; q = 0; break; } } p = p - q; } } K = simplify(K,2); sk = size(K); for(i=1; i<=sk; i++) { // setring save; // V = 0; setring @R; p = K[i]; while (p!=0) { q = lead(p); err = "processing q:" + string(q); dbprint(ppl,err); x = leadexp(q); sx = size(x); pn = leadcoef(q); setring save; pn = imap(@R,pn); V = V + leadcoef(pn)*gen(1); for(k=1; k<=sx; k++) { if (x[k] ==1) { a = k div s; // block number=a+1, a!=0 b = k % s; // remainder // printf("a: %s, b: %s",a,b); if (b == 0) { // that is it's the last var in the block b = s; a = a-1; } V = V + var(b)*gen(a+2); } // else // { // printf("error: the value x[k] is %s", x[k]); // return(0); // } } err = "V: " + string(V); dbprint(ppl,err); // printf("V: %s", string(V)); N = N,V; V = 0; setring @R; p = p - q; pn = 0; } setring save; LN[i] = simplify(N,2); N = 0; } setring save; return(LN); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),(dp(1),dp(2)); module M = [-1,x,y],[-7,y,y],[3,x,x]; module N = [1,x,y,x],[-1,y,x,y]; list L; L[1] = M; L[2] = N; lst2str(L); def U = freegbold(L,5); lst2str(U); } /* begin older procs and tests static proc sgb(ideal I, int d) { // new code // map x_i to x_i(1) via map() //LIB "freegb.lib"; def save = basering; //int d =7;// degree int nv = nvars(save); def R = makeLetterplaceRing(d); setring R; int i; ideal Imap; for (i=1; i<=nv; i++) { Imap[i] = var(i); } //ideal I = x(1)*y(2), y(1)*x(2)+z(1)*z(2); ideal I = x(1)*x(2),x(1)*y(2) + z(1)*x(2); option(prot); //option(teach); ideal J = system("freegb",I,d,nv); } static proc checkCeq() { ring r = 0,(x,y),Dp; def A = makeLetterplaceRing(4); setring A; A; // I = x2-xy ideal I = x(1)*x(2) - x(1)*y(2), x(2)*x(3) - x(2)*y(3), x(3)*x(4) - x(3)*y(4); ideal C = x(2)-x(1),x(3)-x(2),x(4)-x(3),y(2)-y(1),y(3)-y(2),y(4)-y(3); ideal K = I,C; groebner(K); } static proc exHom1() { // we start with // z*y - x, z*x - y, y*x - z LIB "freegb.lib"; LIB "elim.lib"; ring r = 0,(x,y,z,h),dp; list L; module M; M = [1,z,y],[-1,x,h]; // zy - xh L[1] = M; M = [1,z,x],[-1,y,h]; // zx - yh L[2] = M; M = [1,y,x],[-1,z,h]; // yx - zh L[3] = M; lst2str(L); def U = crs(L,4); setring U; I = I, y(2)*h(3)+z(2)*x(3), y(3)*h(4)+z(3)*x(4), y(2)*x(3)-z(2)*h(3), y(3)*x(4)-z(3)*h(4); I = simplify(I,2); ring r2 = 0,(x(0..4),y(0..4),z(0..4),h(0..4)),dp; ideal J = imap(U,I); // ideal K = homog(J,h); option(redSB); option(redTail); ideal L = groebner(J); //(K); ideal LL = sat(L,ideal(h))[1]; ideal M = subst(LL,h,1); M = simplify(M,2); setring U; ideal M = imap(r2,M); lst2str(U); } static proc test1() { LIB "freegb.lib"; ring r = 0,(x,y),Dp; int d = 10; // degree def R = makeLetterplaceRing(d); setring R; ideal I = x(1)*x(2) - y(1)*y(2); option(prot); option(teach); ideal J = system("freegb",I,d,2); J; } static proc test2() { LIB "freegb.lib"; ring r = 0,(x,y),Dp; int d = 10; // degree def R = makeLetterplaceRing(d); setring R; ideal I = x(1)*x(2) - x(1)*y(2); option(prot); option(teach); ideal J = system("freegb",I,d,2); J; } static proc test3() { LIB "freegb.lib"; ring r = 0,(x,y,z),dp; int d =5; // degree def R = makeLetterplaceRing(d); setring R; ideal I = x(1)*y(2), y(1)*x(2)+z(1)*z(2); option(prot); option(teach); ideal J = system("freegb",I,d,3); } static proc schur2-3() { // nonhomog: // h^4-10*h^2+9,f*e-e*f+h, h*2-e*h-2*e,h*f-f*h+2*f // homogenized with t // h^4-10*h^2*t^2+9*t^4,f*e-e*f+h*t, h*2-e*h-2*e*t,h*f-f*h+2*f*t, // t*h - h*t, t*f - f*t, t*e - e*t } end older procs and tests */ proc ademRelations(int i, int j) "USAGE: ademRelations(i,j); i,j int RETURN: ring (and exports ideal) ASSUME: there are at least i+j variables in the basering PURPOSE: compute the ideal of Adem relations for i<2j in characteristic 0 @* the ideal is exported under the name AdemRel in the output ring EXAMPLE: example ademRelations; shows examples " { // produces Adem relations for i<2j in char 0 // assume: 0= 2*j) ) { ERROR("arguments out of range"); return(0); } ring @r = 0,(s(i+j..0)),lp; poly p,q; number n; int ii = i div 2; int k; // k=0 => s(0)=1 n = binomial(j-1,i); q = n*s(i+j)*s(0); // printf("k=0, term=%s",q); p = p + q; for (k=1; k<= ii; k++) { n = binomial(j-k-1,i-2*k); q = n*s(i+j-k)*s(k);; // printf("k=%s, term=%s",k,q); p = p + q; } poly AdemRel = p; export AdemRel; return(@r); } example { "EXAMPLE:"; echo = 2; def A = ademRelations(2,5); setring A; AdemRel; } /* 1,1: 0 1,2: s(3)*s(0) == s(3) -> def for s(3):=s(1)s(2) 2,1: adm 2,2: s(3)*s(1) == s(1)s(2)s(1) 1,3: 0 ( since 2*s(4)*s(0) = 0 mod 2) 3,1: adm 2,3: s(5)*s(0)+s(4)*s(1) == s(5)+s(4)*s(1) 3,2: 0 3,3: s(5)*s(1) 1,4: 3*s(5)*s(0) == s(5) -> def for s(5):=s(1)*s(4) 4,1: adm 2,4: 3*s(6)*s(0)+s(5)*s(1) == s(6) + s(5)*s(1) == s(6) + s(1)*s(4)*s(1) 4,2: adm 4,3: s(5)*s(2) 3,4: s(7)*s(0)+2*s(6)*s(1) == s(7) -> def for s(7):=s(3)*s(4) 4,4: s(7)*s(1)+s(6)*s(2) */ /* s1,s2: s1*s1 =0, s2*s2 = s1*s2*s1 */ /* try char 0: s1,s2: s1*s1 =0, s2*s2 = s1*s2*s1, s(1)*s(3)== s(1)*s(1)*s(3) == 0 = 2*s(4) ->def for s(4) hence 2==0! only in char 2 */ // Adem rels modulo 2 are interesting static proc stringpoly2lplace(string s) { // decomposes sentence into terms s = replace(s,newline,""); // get rid of newlines s = replace(s," ",""); // get rid of empties //arith symbols: +,- // decompose into words with coeffs list LS; int i,j,ie,je,k,cnt; // s[1]="-" situation if (s[1]=="-") { LS = stringpoly2lplace(string(s[2..size(s)])); LS[1] = string("-"+string(LS[1])); return(LS); } i = find(s,"-",2); // i==1 might happen if the 1st symbol coeff is negative j = find(s,"+"); list LL; if (i==j) { "return a monomial"; // that is both are 0 -> s is a monomial LS[1] = s; return(LS); } if (i==0) { "i==0 situation"; // no minuses at all => pluses only cnt++; LS[cnt] = string(s[1..j-1]); s = s[j+1..size(s)]; while (s!= "") { j = find(s,"+"); cnt++; if (j==0) { LS[cnt] = string(s); s = ""; } else { LS[cnt] = string(s[1..j-1]); s = s[j+1..size(s)]; } } return(LS); } if (j==0) { "j==0 situation"; // no pluses at all except the lead coef => the rest are minuses only cnt++; LS[cnt] = string(s[1..i-1]); s = s[i..size(s)]; while (s!= "") { i = find(s,"-",2); cnt++; if (i==0) { LS[cnt] = string(s); s = ""; } else { LS[cnt] = string(s[1..i-1]); s = s[i..size(s)]; } } return(LS); } // now i, j are nonzero if (i>j) { "i>j situation"; // + comes first, at place j cnt++; // "cnt:"; cnt; "j:"; j; LS[cnt] = string(s[1..j-1]); s = s[j+1..size(s)]; LL = stringpoly2lplace(s); LS = LS + LL; kill LL; return(LS); } else { "j>i situation"; // - might come first, at place i if (i>1) { cnt++; LS[cnt] = string(s[1..i-1]); s = s[i..size(s)]; } else { // i==1-> minus at leadcoef ie = find(s,"-",i+1); je = find(s,"+",i+1); if (je == ie) { "ie=je situation"; //monomial cnt++; LS[cnt] = s; return(LS); } if (je < ie) { "jetstnum.out"; k = system("sh",t); if (k!=0) { ERROR("Problems running Singular"); } int i = system("sh", "grep error tstnum.out > /dev/NULL"); if (i!=0) { // no error: s is a number i = 1; } k = system("sh","rm tstnum.tst tstnum.out > /dev/NULL"); return(i); } example { "EXAMPLE:"; echo = 2; ring r = (0,a),x,dp; string s = "a^2+7*a-2"; testnumber(s); s = "b+a"; testnumber(s); } static proc str2lplace(string s) { // converts a word (monomial) with coeff into letter-place // string: coef*var1^exp1*var2^exp2*...varN^expN s = strpower2rep(s); // expand powers if (size(s)==0) { return(0); } int i,j,k,insC; string a,b,c,d,t; // 1. get coeff i = find(s,"*"); if (i==0) { return(s); } list VN; c = s[1..i-1]; // incl. the case like (-a^2+1) int tn = testnumber(c); if (tn == 0) { // failed test if (c[1]=="-") { // two situations: either there's a negative number t = c[2..size(c)]; if (testnumber(t)) { //a negative number // nop here } else { // a variable times -1 c = "-1"; j++; VN[j] = t; //string(c[2..size(c)]); insC = 1; } } else { // just a variable with coeff 1 j++; VN[j] = string(c); c = "1"; insC = 1; } } // get vars t = s; // t = s[i+1..size(s)]; k = size(t); //j = 0; while (k>0) { t = t[i+1..size(t)]; //next part i = find(t,"*"); // next * if (i==0) { // last monomial j++; VN[j] = t; k = size(t); break; } b = t[1..i-1]; // print(b); j++; VN[j] = b; k = size(t); } VN = addplaces(VN); VN[size(VN)+1] = string(c); return(VN); } example { "EXAMPLE:"; echo = 2; ring r = (0,a),(f2,f1),dp; str2lplace("-2*f2^2*f1^2*f2"); str2lplace("-f1*f2"); str2lplace("(-a^2+7a)*f1*f2"); } static proc strpower2rep(string s) { // makes x*x*x*x out of x^4 ., rep statys for repetitions // looks for "-" problem // exception: "-" as coeff string ex,t; int i,j,k; i = find(s,"^"); // first ^ if (i==0) { return(s); } // no ^ signs if (s[1] == "-") { // either -coef or -1 // got the coeff: i = find(s,"*"); if (i==0) { // no *'s => coef == -1 or s == -23 i = size(s)+1; } t = string(s[2..i-1]); // without "-" if ( testnumber(t) ) { // a good number t = strpower2rep(string(s[2..size(s)])); t = "-"+t; return(t); } else { // a variable t = strpower2rep(string(s[2..size(s)])); t = "-1*"+ t; return(t); } } // the case when leadcoef is a number in () if (s[1] == "(") { i = find(s,")",2); // must be nonzero t = s[2..i-1]; if ( testnumber(t) ) { // a good number } else {"strpower2rep: bad number as coef";} ex = string(s[i+2..size(s)]); // 2 because of * ex = strpower2rep(ex); t = "("+t+")*"+ex; return(t); } i = find(s,"^"); // first ^ j = find(s,"*",i+1); // next * == end of ^ if (j==0) { ex = s[i+1..size(s)]; } else { ex = s[i+1..j-1]; } execute("int @exp = " + ex + ";"); //@exp = exponent // got varname for (k=i-1; k>0; k--) { if (s[k] == "*") break; } string varn = s[k+1..i-1]; // "varn:"; varn; string pref; if (k>0) { pref = s[1..k]; // with * on the k-th place } // "pref:"; pref; string suf; if ( (j>0) && (j+1 <= size(s)) ) { suf = s[j+1..size(s)]; // without * on the 1st place } // "suf:"; suf; string toins; for (k=1; k<=@exp; k++) { toins = toins + varn+"*"; } // "toins: "; toins; if (size(suf) == 0) { toins = toins[1..size(toins)-1]; // get rid of trailing * } else { suf = strpower2rep(suf); } ex = pref + toins + suf; return(ex); // return(strpower2rep(ex)); } example { "EXAMPLE:"; echo = 2; ring r = (0,a),(x,y,z,t),dp; strpower2rep("-x^4"); strpower2rep("-2*x^4*y^3*z*t^2"); strpower2rep("-a^2*x^4"); } proc lieBracket(poly a, poly b, list #) "USAGE: lieBracket(a,b[,N]); a,b letterplace polynomials, N an optional integer RETURN: poly ASSUME: basering has a letterplace ring structure PURPOSE:compute the Lie bracket [a,b] = ab - ba between letterplace polynomials NOTE: if N>1 is specified, then the left normed bracket [a,[...[a,b]]]] is @* computed. EXAMPLE: example lieBracket; shows examples " { if (lpAssumeViolation()) { // ERROR("Either 'uptodeg' or 'lV' global variables are not set!"); ERROR("Incomplete Letterplace structure on the basering!"); } // alias ppLiebr; //if int N is given compute [a,[...[a,b]]]] left normed bracket poly q; int N=1; if (size(#)>0) { if (typeof(#[1])=="int") { N = int(#[1]); } } if (N<=0) { return(q); } while (b!=0) { q = q + pmLiebr(a,lead(b)); b = b - lead(b); } int i; if (N >1) { for(i=1; i<=N; i++) { q = lieBracket(a,q); } } return(q); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp; def R = setLetterplaceAttributes(r,4,2); // supply R with letterplace structure setring R; poly a = x(1)*y(2); poly b = y(1); lieBracket(a,b); lieBracket(x(1),y(1),2); } static proc pmLiebr(poly a, poly b) { // a poly, b mono poly s; while (a!=0) { s = s + mmLiebr(lead(a),lead(b)); a = a - lead(a); } return(s); } proc shiftPoly(poly a, int i) "USAGE: shiftPoly(p,i); p letterplace poly, i int RETURN: poly ASSUME: basering has letterplace ring structure PURPOSE: compute the i-th shift of letterplace polynomial p EXAMPLE: example shiftPoly; shows examples " { // shifts a monomial a by i // calls pLPshift(p,sh,uptodeg,lVblock); if (lpAssumeViolation()) { ERROR("Incomplete Letterplace structure on the basering!"); } int uptodeg = attrib(basering,"uptodeg"); int lV = attrib(basering,"lV"); if (deg(a) + i > uptodeg) { ERROR("degree bound violated by the shift!"); } return(system("stest",a,i,uptodeg,lV)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; int uptodeg = 5; int lV = 3; def R = makeLetterplaceRing(uptodeg); setring R; poly f = x(1)*z(2)*y(3) - 2*z(1)*y(2) + 3*x(1); shiftPoly(f,1); shiftPoly(f,2); } static proc mmLiebr(poly a, poly b) { // a,b, monomials a = lead(a); b = lead(b); int sa = deg(a); int sb = deg(b); poly v = a*shiftPoly(b,sa) - b*shiftPoly(a,sb); return(v); } static proc test_shift() { LIB "freegb.lib"; ring r = 0,(a,b),dp; int d =5; def R = makeLetterplaceRing(d); setring R; int uptodeg = d; int lV = 2; def R = setLetterplaceAttributes(r,uptodeg,2); // supply R with letterplace structure setring R; poly p = mmLiebr(a(1),b(1)); poly p = lieBracket(a(1),b(1)); } proc serreRelations(intmat A, int zu) "USAGE: serreRelations(A,z); A an intmat, z an int RETURN: ideal ASSUME: basering has a letterplace ring structure and @* A is a generalized Cartan matrix with integer entries PURPOSE: compute the ideal of Serre's relations associated to A EXAMPLE: example serreRelations; shows examples " { // zu = 1 -> with commutators [f_i,f_j]; zu == 0 without them // suppose that A is cartan matrix // then Serre's relations are // (ad f_j)^{1-A_{ij}} ( f_i) int ppl = printlevel-voice+2; int n = ncols(A); // hence n variables int i,j,k,el; poly p,q; ideal I; for (i=1; i<=n; i++) { for (j=1; j<=n; j++) { el = 1 - A[i,j]; // printf("i:%s, j: %s, l: %s",i,j,l); dbprint(ppl,"i, j, l: ",i,j,el); // if ((i!=j) && (l >0)) // if ( (i!=j) && ( ((zu ==0) && (l >=2)) || ((zu ==1) && (l >=1)) ) ) if ((i!=j) && (el >0)) { q = lieBracket(var(j),var(i)); dbprint(ppl,"first bracket: ",q); // if (l >=2) // { for (k=1; k<=el-1; k++) { q = lieBracket(var(j),q); dbprint(ppl,"further bracket:",q); } // } } if (q!=0) { I = I,q; q=0;} } } I = simplify(I,2); return(I); } example { "EXAMPLE:"; echo = 2; intmat A[3][3] = 2, -1, 0, -1, 2, -3, 0, -1, 2; // G^1_2 Cartan matrix ring r = 0,(f1,f2,f3),dp; int uptodeg = 5; def R = makeLetterplaceRing(uptodeg); setring R; ideal I = serreRelations(A,1); I = simplify(I,1+2+8); I; } /* setup for older example: intmat A[2][2] = 2, -1, -1, 2; // sl_3 == A_2 ring r = 0,(f1,f2),dp; int uptodeg = 5; int lV = 2; */ proc fullSerreRelations(intmat A, ideal rNegative, ideal rCartan, ideal rPositive, int uptodeg) "USAGE: fullSerreRelations(A,N,C,P,d); A an intmat, N,C,P ideals, d an int RETURN: ring (and ideal) PURPOSE: compute the inhomogeneous Serre's relations associated to A in given @* variable names ASSUME: three ideals in the input are of the same sizes and contain merely @* variables which are interpreted as follows: N resp. P stand for negative @* resp. positive roots, C stand for Cartan elements. d is the degree bound for @* letterplace ring, which will be returned. @* The matrix A is a generalized Cartan matrix with integer entries @* The result is the ideal called 'fsRel' in the returned ring. EXAMPLE: example fullSerreRelations; shows examples " { /* SerreRels on rNeg and rPos plus Cartans etc. */ int ppl = printlevel -voice+2; /* ideals must be written in variables: assume each term is of degree 1 */ int i,j,k; int N = nvars(basering); def save = basering; int comFlag = 0; /* assume: (size(rNegative) == size(rPositive)) */ /* assume: (size(rNegative) == size(rCartan)) i.e. nonsimple Cartans */ if ( (size(rNegative) != size(rPositive)) || (size(rNegative) != size(rCartan)) ) { ERROR("All input ideals must be of the same size"); } // if (size(rNegative) != size(rPositive)) // { // ERROR("The 1st and the 3rd input ideals must be of the same size"); // } /* assume: 2*size(rNegative) + size(rCartan) >= nvars(basering) */ i = 2*size(rNegative) + size(rCartan); if (i>N) { ERROR("The total number of elements in input ideals must not exceed the dimension of the ground ring"); } if (i < N) { comFlag = N-i; // so many elements will commute "Warning: some elements will be treated as mutually commuting"; } /* extract varnames from input ideals */ intvec iNeg = varIdeal2intvec(rNegative); intvec iCartan = varIdeal2intvec(rCartan); intvec iPos = varIdeal2intvec(rPositive); /* for each vector in rNeg and rPositive, go into the corr. ring and create SerreRels */ /* rNegative: */ list L = ringlist(save); def LPsave = makeLetterplaceRing2(uptodeg); setring save; list LNEG = L; list tmp; /* L[1] field as is; L[2] vars: a subset; L[3] ordering: dp, L[4] as is */ for (i=1; i<=size(iNeg); i++) { tmp[i] = string(var(iNeg[i])); } LNEG[2] = tmp; LNEG[3] = list(list("dp",intvec(1:size(iNeg))), list("C",0)); def RNEG = ring(LNEG); setring RNEG; def RRNEG = makeLetterplaceRing2(uptodeg); setring RRNEG; ideal I = serreRelations(A,1); I = simplify(I,1+2+8); setring LPsave; ideal srNeg = imap(RRNEG,I); dbprint(ppl,"0-1 ideal of negative relations is ready"); dbprint(ppl-1,srNeg); setring save; kill L,tmp,RRNEG,RNEG, LNEG; /* rPositive: */ list L = ringlist(save); list LPOS = L; list tmp; /* L[1] field as is; L[2] vars: a subset; L[3] ordering: dp, L[4] as is */ for (i=1; i<=size(iPos); i++) { tmp[i] = string(var(iPos[i])); } LPOS[2] = tmp; LPOS[3] = list(list("dp",intvec(1:size(iPos))), list("C",0)); def RPOS = ring(LPOS); setring RPOS; def RRPOS = makeLetterplaceRing2(uptodeg); setring RRPOS; ideal I = serreRelations(A,1); I = simplify(I,1+2+8); setring LPsave; ideal srPos = imap(RRPOS,I); dbprint(ppl,"0-2 ideal of positive relations is ready"); dbprint(ppl-1,srPos); setring save; kill L,tmp,RRPOS,RPOS, LPOS; string sMap = "ideal Mmap ="; for (i=1; i<=nvars(save); i++) { sMap = sMap + string(var(i)) +"(1),"; } sMap[size(sMap)] = ";"; /* cartans: h_j h_i = h_i h_j */ setring LPsave; ideal ComCartan; for (i=1; ij */ ideal ComPosNeg; // assume: #Neg=#Pos for (i=1; i=2 setring @R; for(i=1; i<=sk; i++) { p = K[i]; while (p!=0) { q = lead(p); // "processing q:";q; x = leadexp(q); sx = size(x); for(k=1; k<=sx; k++) { if ( x[k] >= 2 ) { err = "skip: the value x[k] is " + string(x[k]); dbprint(ppl,err); // return(0); K[i] = 0; p = 0; q = 0; break; } } p = p - q; } } K = simplify(K,2); sk = size(K); for(i=1; i<=sk; i++) { // setring save; // V = 0; setring @R; p = K[i]; while (p!=0) { q = lead(p); err = "processing q:" + string(q); dbprint(ppl,err); x = leadexp(q); sx = size(x); pn = leadcoef(q); setring save; pn = imap(@R,pn); V = V + leadcoef(pn)*gen(1); for(k=1; k<=sx; k++) { if (x[k] ==1) { a = k div s; // block number=a+1, a!=0 b = k % s; // remainder // printf("a: %s, b: %s",a,b); if (b == 0) { // that is it's the last var in the block b = s; a = a-1; } V = V + var(b)*gen(a+2); } } err = "V: " + string(V); dbprint(ppl,err); // printf("V: %s", string(V)); N = N,V; V = 0; setring @R; p = p - q; pn = 0; } setring save; LN[i] = simplify(N,2); N = 0; } setring save; list @LN = LN; export @LN; // return(LN); } example { "EXAMPLE:"; echo = 2; intmat A[2][2] = 2, -1, -1, 2; // sl_3 == A_2 ring r = 0,(f1,f2),dp; def R = makeLetterplaceRing(3); setring R; ideal I = serreRelations(A,1); lp2lstr(I,r); setring r; lst2str(@LN,1); } static proc strList2poly(list L) { // list L comes from sent2lplace (which takes a polynomial as input) // each entry of L is a sublist with the coef on the last place int s = size(L); int t; int i,j; list M; poly p,q; string Q; for(i=1; i<=s; i++) { M = L[i]; t = size(M); // q = M[t]; // a constant Q = string(M[t]); for(j=1; j deg(_,w) for the length // shrink the result => don't need to decompose polys // since the shift is big enough // indeed it's better to have that // ASSUME: both f and g are quasi-homogeneous if (lpAssumeViolation()) { ERROR("Incomplete Letterplace structure on the basering!"); } intvec w = 1:nvars(basering); int sf = deg(f,w); // VL Oct 2010: we need rather length than degree int sg = deg(g,w); // esp. in the case of weighted ordering int uptodeg = attrib(basering, "uptodeg"); if (sf+sg > uptodeg) { ERROR("degree bound violated by the product!"); } // if (sf>1) { sf = sf -1; } poly v = f*shiftPoly(g,sf); // bug, reported by Simon King: in nonhomog case [solved] // we need to shrink return( system("shrinktest",v,attrib(basering, "lV")) ); } example { "EXAMPLE:"; echo = 2; // define a ring in letterplace form as follows: ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp; def R = setLetterplaceAttributes(r,4,2); // supply R with letterplace structure setring R; poly a = x(1)*y(2)+x(1)+y(1); poly b = y(1)+3; lpMult(b,a); lpMult(a,b); } proc lpPower(poly f, int n) "USAGE: lpPower(f,n); f letterplace polynomial, int n RETURN: poly ASSUME: basering has a letterplace ring structure PURPOSE: compute the letterplace form of f^n EXAMPLE: example lpPower; shows examples " { if (n<0) { ERROR("the power must be a natural number!"); } if (n==0) { return(poly(1)); } if (n==1) { return(f); } int i; poly p = 1; for(i=1; i<= n; i++) { p = lpMult(p,f); } return(p); } example { "EXAMPLE:"; echo = 2; // define a ring in letterplace form as follows: ring r = 0,(x(1),y(1),x(2),y(2),x(3),y(3),x(4),y(4)),dp; def R = setLetterplaceAttributes(r,4,2); // supply R with letterplace structure setring R; poly a = x(1)*y(2) + y(1); poly b = y(1) - 1; lpPower(a,2); lpPower(b,4); } // new: lp normal from by using shift-invariant data by Grischa Studzinski ///////////////////////////////////////////////////////// // ASSUMPTIONS: every polynomial is an element of V', //@* else there wouldn't be an dvec representation //Mainprocedure for the user proc lpNF(poly p, ideal G) "USAGE: lpNF(p,G); f letterplace polynomial, ideal I RETURN: poly PURPOSE: computation of the normalform of p with respect to G ASSUME: p is a Letterplace polynomial, G is a set Letterplace polynomials, being a Letterplace Groebner basis (no check for this will be done) NOTE: Strategy: take the smallest monomial wrt ordering for reduction @* For homogenous ideals the shift does not matter @* For non-homogenous ideals the first shift will be the smallest monomial EXAMPLE: example lpNF; shows examples " {if ((p==0) || (size(G) == 0)){return(p);} checkAssumptions(p,G); G = sort(G)[1]; list L = makeDVecI(G); return(normalize(lpNormalForm1(p,G,L))); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; int d =5; // degree def R = makeLetterplaceRing(d); setring R; ideal I = y(1)*x(2)*y(3) - z(1)*y(2)*z(3), x(1)*y(2)*x(3) - z(1)*x(2)*y(3), z(1)*x(2)*z(3) - y(1)*z(2)*x(3), x(1)*x(2)*x(3) + y(1)*y(2)*y(3) + z(1)*z(2)*z(3) + x(1)*y(2)*z(3); ideal J = letplaceGBasis(I); // compute a Letterplace Groebner basis poly p = y(1)*x(2)*y(3)*z(4)*y(5) - y(1)*z(2)*z(3)*y(4) + z(1)*y(2)*z(3); poly q = z(1)*x(2)*z(3)*y(4)*z(5) - y(1)*z(2)*x(3)*y(4)*z(5); lpNF(p,J); lpNF(q,J); } //procedures to convert monomials into the DVec representation, all static //////////////////////////////////////////////////////// static proc getExpVecs(ideal G) "USUAGE: getExpVecs(G); RETURN: list of intvecs PURPOSE: convert G into a list of intvecs, corresponding to the exponent vector @* of the leading monomials of G " {int i; list L; for (i = 1; i <= size(G); i++) {L[i] = leadexp(G[i]); } return(L); } static proc delSupZero(intvec I) "USUAGE:delSupZero(I); RETURN: intvec PURPOSE: Deletes superfluous zero blocks of an exponent vector ASSUME: Intvec is an exponent vector of a letterplace monomial contained in V' " {if (I==intvec(0)) {return(intvec(0));} int j,k,l; int n = attrib(basering,"lV"); int d = attrib(basering,"uptodeg"); intvec w; j = 1; while (j <= d) {w = I[1..n]; if (w<>intvec(0)){break;} else {I = I[(n+1)..(n*d)]; d = d-1; j++;} } for (j = 1; j <= d; j++) {l=(j-1)*n+1; k= j*n; w = I[l..k]; if (w==intvec(0)){w = I[1..(l-1)]; return(w);}//if a zero block is found there are only zero blocks left, //otherwise there would be a hole in the monomial // shrink should take care that this will not happen } return(I); } static proc delSupZeroList(list L) "USUAGE:delSupZeroList(L); L a list, containing intvecs RETURN: list, containing intvecs PURPOSE: Deletes all superfluous zero blocks for a list of exponent vectors ASSUME: All intvecs are exponent vectors of letterplace monomials contained in V' " {int i; for (i = size(L); 0 < i; i--){L[i] = delSupZero(L[i]);} return(L); } static proc makeDVec(intvec V) "USUAGE:makeDVec(V); RETURN: intvec PURPOSE: Converts an modified exponent vector into an Dvec NOTE: Superfluos zero blocks must have been deleted befor using this procedure " {int i,j,k,r1,r2; intvec D; int n = attrib(basering,"lV"); k = size(V) div n; r1 = 0; r2 = 0; for (i=1; i<= k; i++) {for (j=(1+((i-1)*n)); j <= (i*n); j++) {if (V[j]>0){r2 = j - ((i-1)*n); j = (j mod n); break;} } D[size(D)+1] = r1+r2; if (j == 0) {r1 = 0;} else{r1= n-j;} } D = D[2..size(D)]; return(D); } static proc makeDVecL(list L) "USUAGE:makeDVecL(L); L, a list containing intvecs RETURN: list, containing intvecs ASSUME: " {int i; list R; for (i=1; i <= size(L); i++) {R[i] = makeDVec(L[i]);} return(R); } static proc makeDVecI(ideal G) "USUAGE:makeDVecI(G); RETURN:list, containing intvecs PURPOSE:computing the DVec representation for lead(G) ASSUME: " {list L = delSupZeroList(getExpVecs(G)); return(makeDVecL(L)); } //procedures, which are dealing with the DVec representation, all static static proc dShiftDiv(intvec V, intvec W) "USUAGE: dShiftDiv(V,W); RETURN: a list,containing integers, or -1, if no shift of W divides V PURPOSE: find all possible shifts s, such that s.W|V ASSUME: V,W are DVecs of monomials contained in V' " {if(size(V)1) {T[2..size(W)] = V[(i+1)..(size(W)+i-1)];} if (T-W == 0) {R[size(R)+1] = i-1;} } if (size(R)>0) {return(R);} else {return(list(-1));} } //the actual normalform procedure, if a user want not to presort the ideal, just make it not static static proc lpNormalForm1(poly p, ideal G, list L) "USUAGE:lpNormalForm1(p,G); RETURN:poly PURPOSE:computation of the normalform of p w.r.t. G ASSUME: p is a Letterplace polynomial, G is a set of Letterplace polynomials NOTE: Taking the first possible reduction " { if (deg(p) <1) {return(p);} else { int i; int s; intvec V = makeDVec(delSupZero(leadexp(p))); for (i = 1; i <= size(L); i++) {s = dShiftDiv(V, L[i])[1]; if (s <> -1) {p = lpReduce(p,G[i],s); p = lpNormalForm1(p,G,L); break; } } p = p[1] + lpNormalForm1(p-p[1],G,L); return(p); } } //secundary procedures, all static static proc getlpCoeffs(poly q, poly p) " " {list R; poly m; intvec cq,t,lv,rv,bla; int n = attrib(basering,"lV"); int d = attrib(basering,"uptodeg"); int i; m = p/q; cq = leadexp(m); for (i = 1; i<= d; i++) {bla = cq[((i-1)*n+1)..(i*n)]; if (bla == 0) {lv = cq[1..i*n]; cq = cq[(i*n+1)..(d*n)]; break;} } d = size(cq) div n; for (i = 1; i<= d; i++) {bla = cq[((i-1)*n+1)..(i*n)]; if (bla <> 0){rv = cq[((i-1)*n+1)..(d*n)]; break;} } return(list(monomial(lv),monomial(rv))); } static proc lpReduce(poly p, poly g, int s) "NOTE: shift can not exceed the degree bound, because s*g | p " {poly l,r,qt; int i; g = shiftPoly(g,s); list K = getlpCoeffs(lead(g),lead(p)); l = K[1]; r = K[2]; kill K; for (i = 1; i <= size(g); i++) {qt = qt + lpMult(lpMult(l,g[i]),r); } return((leadcoef(qt)*p - leadcoef(p)*qt)); } static proc lpShrink(poly p) " " {int n; if (typeof(attrib(basering,"isLetterplaceRing"))=="int") {n = attrib(basering,"lV"); return(system("shrinktest",p,n)); } else {ERROR("Basering is not a Letterplace ring!");} } static proc checkAssumptions(poly p, ideal G) " " {checkLPRing(); checkAssumptionPoly(p); checkAssumptionIdeal(G); return(); } static proc checkLPRing(); " " {if (typeof(attrib(basering,"isLetterplaceRing"))=="string") {ERROR("Basering is not a Letterplace ring!");} return(); } static proc checkAssumptionIdeal(ideal G) "PURPOSE:Check if all elements of ideal are elements of V' " {ideal L = lead(normalize(G)); int i; for (i = 1; i <= ncols(G); i++) {if (!isContainedInVp(G[i])) {ERROR("Ideal containes elements not contained in V'");}} return(); } static proc checkAssumptionPoly(poly p) "PURPOSE:Check if p is an element of V' " {poly l = lead(normalize(p)); if (!isContainedInVp(l)) {ERROR("Polynomial is not contained in V'");} return(); } static proc isContainedInVp(poly p) "PURPOSE: Check monomial for holes in the places " {int r = 0; intvec w; intvec l = leadexp(p); int n = attrib(basering,"lV"); int d = attrib(basering,"uptodeg"); int i,j,c,c1; while (1 <= d) {w = l[1..n]; if (w<>intvec(0)){break;} else {l = l[(n+1)..(n*d)]; d = d-1;} } while (1 <= d) {for (j = 1; j <= n; j++) {if (l[j]<>0) {if (c1<>0){return(0);} if (c<>0){return(0);} if (l[j]<>1){return(0);} c=1; } } if (c == 0){c1=1;if (1 < d){l = l[(n+1)..(n*d)]; d = d-1;} else {d = d -1;}} else {c = 0; if (1 < d){l = l[(n+1)..(n*d)]; d = d-1;} else {d = d -1;}} } return(1); } // under development for Roberto static proc extractLinearPart(module M) { /* returns vectors from a module whose max leadexp is 1 */ /* does not take place nonlinearity into account yet */ /* use rather kernel function isinV to get really nonlinear things */ int i; int s = ncols(M); int answer = 1; vector v; module Ret; for(i=1; i<=s; i++) { if ( isLinearVector(M[i]) ) { Ret = Ret, M[i]; } } Ret = simplify(Ret,2); return(Ret); } // under development for Roberto static proc isLinearVector(vector v) { /* returns true iff max leadexp is 1 */ int i,j,k; intvec w; int s = size(v); poly p; int answer = 1; for(i=1; i<=s; i++) { p = v[i]; while (p != 0) { w = leadexp(p); j = Max(w); if (j >=2) { answer = 0; return(answer); } p = p-lead(p); } } return(answer); } // // the following is to determine a shift of a mono/poly from the // // interface // proc whichshift(poly p, int numvars) // { // // numvars = number of vars of the orig free algebra // // assume: we are in the letterplace ring // // takes monomial on the input // poly q = lead(p); // intvec v = leadexp(v); // if (v==0) { return(int(0)); } // int sv = size(v); // int i=1; // while ( (v[i]==0) && (i=-26 and n<=26 and n!=0 ) { string alpha = "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,"+ "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,"+ "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,"+ "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"; int ii; int aa; for(ii=1; ii<=51; ii=ii+2) { if( alpha[ii]==s ) { aa=ii; } } if ( aa==0) { for(ii=105; ii<=155; ii=ii+2) { if( alpha[ii]==s ) { aa=ii; } } } if( aa!=0 ) { string out; if (n > 0) { out = alpha[aa,2*(n)-1]; return (out); } if (n < 0) { string beta = "z,y,x,w,v,u,t,s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,"+ "z,y,x,w,v,u,t,s,r,q,p,o,n,m,l,k,j,i,h,g,f,e,d,c,b,a,"+ "Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,"+ "Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A"; if ( aa < 52 ) { aa=52-aa; } if ( aa > 104 ) { aa=260-aa; } out = beta[aa,2*(-n)-1]; return (out); } } } } example { "EXAMPLE:"; echo = 2; A_Z("c",5); A_Z("Z",-5); string sR = "ring R = (0,"+A_Z("A",6)+"),("+A_Z("a",10)+"),dp;"; sR; execute(sR); R; } /////////////////////////////////////////////////////////////////////////////// proc ASCII (list #) "USAGE: ASCII([n,m]); n,m= integers (32 <= n <= m <= 126) RETURN: string of printable ASCII characters (no native language support)@* ASCII(): string of all ASCII characters with its numbers,@* ASCII(n): n-th ASCII character@* ASCII(n,m): n-th up to m-th ASCII character (inclusive) EXAMPLE: example ASCII; shows an example " { string s1 = " ! \" # $ % & ' ( ) * + , - . 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 / 0 1 2 3 4 5 6 7 8 9 : ; < = 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 > ? @ A B C D E F G H I J K L 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 M N O P Q R S T U V W X Y Z [ 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 \\ ] ^ _ ` a b c d e f g h i j 92 93 94 95 96 97 98 99 100 101 102 103 104 105 10 k l m n o p q r s t u v w x y 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 z { | } ~ 122 123 124 125 126 "; string s2 = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; if ( size(#) == 0 ) { return(s1); } if ( size(#) == 1 ) { return( s2[#[1]-31] ); } if ( size(#) == 2 ) { return( s2[#[1]-31,#[2]-#[1]+1] ); } } example { "EXAMPLE:"; echo = 2; ASCII();""; ASCII(42); ASCII(32,126); } /////////////////////////////////////////////////////////////////////////////// proc absValue(def c) "USAGE: absValue(c); c int, number or poly RETURN: absValue(c); the absolute value of c NOTE: absValue(c)=c if c>=0; absValue=-c if c<=0. @* So the function can be applied to any type, for which comparison @* operators are defined. EXAMPLE: example absValue; shows an example " { if (c>=0) { return(c); } else { return(-c); } } example { "EXAMPLE:"; echo = 2; ring r1 = 0,x,dp; absValue(-2002); poly f=-4; absValue(f); } /////////////////////////////////////////////////////////////////////////////// proc binomial (int n, int k) "USAGE: binomial(n,k); n,k integers RETURN: binomial(n,k); binomial coefficient n choose k EXAMPLE: example binomial; shows an example " { bigint l; bigint r=1; bigint kk=k; bigint nn=n; if ( k > n-k ) { k = n-k; } if ( k<=0 or k>n ) //trivial cases { r = (k==0)*r; } for (l=1; l<=kk; l=l+1 ) { r=r*(nn+1-l)/l; } return(r); } example { "EXAMPLE:"; echo = 2; binomial(200,100);""; //type bigint int n,k = 200,100; bigint b1 = binomial(n,k); ring r = 0,x,dp; poly b2 = coeffs((x+1)^n,x)[k+1,1]; //coefficient of x^k in (x+1)^n b1-b2; //b1 and b2 should coincide } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc factorial (int n) "USAGE: factorial(n); n integer RETURN: factorial(n): n! of type bigint. SEE ALSO: prime EXAMPLE: example factorial; shows an example " { bigint r=1; //------------------------------ computation -------------------------------- for (int l=2; l<=n; l++) { r=r*l; } return(r); } example { "EXAMPLE:"; echo = 2; factorial(37); } /////////////////////////////////////////////////////////////////////////////// proc fibonacci (int n) "USAGE: fibonacci(n); n,p integers RETURN: fibonacci(n): nth Fibonacci number, f(0)=f(1)=1, f(i+1)=f(i-1)+f(i) @* - computed in characteristic 0, of type bigint SEE ALSO: prime EXAMPLE: example fibonacci; shows an example " { bigint f,g,h=1,1,1; //------------------------------ computation -------------------------------- for (int ii=3; ii<=n; ii++) { h = f+g; f = g; g = h; } return(h); } example { "EXAMPLE:"; echo = 2; fibonacci(42); } /////////////////////////////////////////////////////////////////////////////// proc kmemory (list #) "USAGE: kmemory([n,[v]]); n,v integers RETURN: memory in kilobyte of type bigint @* n=0: memory used by active variables (same as no parameters) @* n=1: total memory allocated by Singular DISPLAY: detailed information about allocated and used memory if v!=0 NOTE: kmemory uses internal function 'memory' to compute kilobyte, and is the same as 'memory' for n!=0,1,2 EXAMPLE: example kmemory; shows an example " { int n; int verb; if (size(#) != 0) { n=#[1]; if (size(#) >1) { verb=#[2]; } } if ( verb != 0) { if ( n==0) { dbprint(printlevel-voice+3, "// memory used, at the moment, by active variables (kilobyte):"); } if ( n==1 ) { dbprint(printlevel-voice+3, "// total memory allocated, at the moment, by SINGULAR (kilobyte):"); } } return ((memory(n)+1023) div 1024); } example { "EXAMPLE:"; echo = 2; kmemory(); kmemory(1,1); } /////////////////////////////////////////////////////////////////////////////// proc killall "USAGE: killall(); (no parameter) killall(\"type_name\"); killall(\"not\", \"type_name\"); RETURN: killall(); kills all user-defined variables except loaded procedures, no return value. @* - killall(\"type_name\"); kills all user-defined variables, of type \"type_name\" @* - killall(\"not\", \"type_name\"); kills all user-defined variables, except those of type \"type_name\" and except loaded procedures @* - killall(\"not\", \"name_1\", \"name_2\", ...); kills all user-defined variables, except those of name \"name_i\" and except loaded procedures NOTE: killall should never be used inside a procedure EXAMPLE: example killall; shows an example AND KILLS ALL YOUR VARIABLES " { list @marie=names(Top); int j, no_kill, @joni; for ( @joni=1; @joni<=size(#); @joni++) { if (typeof(#[@joni]) != "string") { ERROR("Need string as " + string(@joni) + "th argument"); } } // kills all user-defined variables but not loaded procedures if( size(#)==0 ) { for ( @joni=size(@marie); @joni>0; @joni-- ) { if( @marie[@joni]!="LIB" and typeof(`@marie[@joni]`)!="proc" and typeof(`@marie[@joni]`)!="package") { kill `@marie[@joni]`; } } } else { // kills all user-defined variables if( size(#)==1 ) { // of type proc if( #[1] == "proc" ) { for ( @joni=size(@marie); @joni>0; @joni-- ) { if( (@marie[@joni]!="General") and (@marie[@joni]!="Top") and (@marie[@joni]!="killall") and (@marie[@joni]!="LIB") and ((typeof(`@marie[@joni]`)=="package") or (typeof(`@marie[@joni]`)=="proc"))) { if (defined(`@marie[@joni]`)) {kill `@marie[@joni]`;} } if (!defined(@joni)) break; } if (defined(General)) { @marie=names(General); for ( @joni=size(@marie); @joni>0; @joni-- ) { if(@marie[@joni]!="killall" and typeof(`@marie[@joni]`)=="proc") { kill General::`@marie[@joni]`; } } kill General::killall; } } else { // other types for ( @joni=size(@marie); @joni>2; @joni-- ) { if(typeof(`@marie[@joni]`)==#[1] and @marie[@joni]!="LIB" and typeof(`@marie[@joni]`)!="proc") { kill `@marie[@joni]`; } } } } else { // kills all user-defined variables whose name or type is not #i for ( @joni=size(@marie); @joni>2; @joni-- ) { if ( @marie[@joni] != "LIB" && @marie[@joni] != "Top" && typeof(`@marie[@joni]`) != "proc") { no_kill = 0; for (j=2; j<= size(#); j++) { if (typeof(`@marie[@joni]`)==#[j] or @marie[@joni] == #[j]) { no_kill = 1; break; } } if (! no_kill) { kill `@marie[@joni]`; } } if (!defined(@joni)) break; } } } } example { "EXAMPLE:"; echo = 2; ring rtest; ideal i=x,y,z; string str="hi"; int j = 3; export rtest,i,str,j; //this makes the local variables global listvar(); killall("ring"); // kills all rings listvar(); killall("not", "int"); // kills all variables except int's (and procs) listvar(); killall(); // kills all vars except loaded procs listvar(); } /////////////////////////////////////////////////////////////////////////////// proc number_e (int n) "USAGE: number_e(n); n integer RETURN: Euler number e=exp(1) up to n decimal digits (no rounding) @* - of type string if no basering of char 0 is defined @* - of type number if a basering of char 0 is defined DISPLAY: decimal format of e if printlevel > 0 (default:printlevel=0 ) NOTE: procedure uses algorithm of A.H.J. Sale EXAMPLE: example number_e; shows an example " { int i,m,s,t; intvec u,e; u[n+2]=0; e[n+1]=0; e=e+1; if( defined(basering) ) { if( char(basering)==0 ) { number r=2; t=1; } } string result = "2."; for( i=1; i<=n+1; i=i+1 ) { e = e*10; for( m=n+1; m>=1; m=m-1 ) { s = e[m]+u[m+1]; u[m] = s div (m+1); e[m] = s%(m+1); } result = result+string(u[1]); if( t==1 ) { r = r+number(u[1])/number(10)^i; } } if( t==1 ) { dbprint(printlevel-voice+2,"// "+result[1,n+1]); return(r); } return(result[1,n+1]); } example { "EXAMPLE:"; echo = 2; number_e(30);""; ring R = 0,t,lp; number e = number_e(30); e; } /////////////////////////////////////////////////////////////////////////////// proc number_pi (int n) "USAGE: number_pi(n); n positive integer RETURN: pi (area of unit circle) up to n decimal digits (no rounding) @* - of type string if no basering of char 0 is defined, @* - of type number, if a basering of char 0 is defined DISPLAY: decimal format of pi if printlevel > 0 (default:printlevel=0 ) NOTE: procedure uses algorithm of S. Rabinowitz EXAMPLE: example number_pi; shows an example " { int i,m,t,e,q,N; intvec r,p,B,Prelim; string result,prelim; N = (10*n) div 3 + 2; p[N+1]=0; p=p+2; r=p; for( i=1; i<=N+1; i=i+1 ) { B[i]=2*i-1; } if( defined(basering) ) { if( char(basering)==0 ) { number pi; number pri; t=1; } } for( i=0; i<=n; i=i+1 ) { p = r*10; e = p[N+1]; for( m=N+1; m>=2; m=m-1 ) { r[m] = e%B[m]; q = e div B[m]; e = q*(m-1)+p[m-1]; } r[1] = e%10; q = e div 10; if( q!=10 and q!=9 ) { result = result+prelim; Prelim = q; prelim = string(q); } if( q==9 ) { Prelim = Prelim,9; prelim = prelim+"9"; } if( q==10 ) { Prelim = (Prelim+1)-((Prelim+1) div 10)*10; for( m=size(Prelim); m>0; m=m-1) { prelim[m] = string(Prelim[m]); } result = result+prelim; if( t==1 ) { pi=pi+pri; } Prelim = 0; prelim = "0"; } if( t==1 ) { pi=pi+number(q)/number(10)^i; } } result = result,prelim[1]; result = "3."+result[2,n-1]; if( t==1 ) { dbprint(printlevel-voice+2,"// "+result); return(pi); } return(result); } example { "EXAMPLE:"; echo = 2; number_pi(11);""; ring r = (real,10),t,dp; number pi = number_pi(11); pi; } /////////////////////////////////////////////////////////////////////////////// proc primes (int n, int m) "USAGE: primes(n,m); n,m integers RETURN: intvec, consisting of all primes p, prime(n)<=p<=m, in increasing order if n<=m, resp. prime(m)<=p<=n, in decreasing order if m=2, else 2 EXAMPLE: example primes; shows an example " { int change; if ( n>m ) { change=n; n=m ; m=change; change=1; } int q,p = prime(m),prime(n); intvec v = q; q = q-1; while ( q>=p ) { q = prime(q); v = q,v; q = q-1; } if ( change==1 ) { v = v[size(v)..1]; } return(v); } example { "EXAMPLE:"; echo = 2; primes(50,100);""; intvec v = primes(37,1); v; } /////////////////////////////////////////////////////////////////////////////// proc product (def id, list #) "USAGE: product(id[,v]); id ideal/vector/module/matrix/intvec/intmat/list, v intvec (default: v=1..number of entries of id) ASSUME: list members can be multiplied. RETURN: The product of all entries of id [with index given by v] of type depending on the entries of id. NOTE: If id is not a list, id is treated as a list of polys resp. integers. A module m is identified with the corresponding matrix M (columns of M generate m). @* If v is outside the range of id, we have the empty product and the result will be 1 (of type int). EXAMPLE: example product; shows an example " { //-------------------- initialization and special feature --------------------- int n,j,tt; string ty; //will become type of id list l; // We wish to allow something like product(x(1..10)) if x(1),...,x(10) are // variables. x(1..10) is a list of polys and enters the procedure with // id=x(1) and # a list with 9 polys, #[1]= x(2),...,#[9]= x(10). Hence, in // this case # is never empty. If an additional intvec v is given, // it is added to #, so we have to separate it first and make // the rest a list which has to be multiplied. int s = size(#); if( s!=0 ) { if ( typeof(#[s])=="intvec" or typeof(#[s])=="int") { intvec v = #[s]; tt=1; s=s-1; if ( s>0 ) { # = #[1..s]; } } } if ( s>0 ) { l = list(id)+#; kill id; list id = l; //case: id = list ty = "list"; n = size(id); } else { ty = typeof(id); if( ty == "list" ) { n = size(id); } } //------------------------------ reduce to 3 cases --------------------------- if( ty=="poly" or ty=="ideal" or ty=="vector" or ty=="module" or ty=="matrix" ) { ideal i = ideal(matrix(id)); kill id; ideal id = i; //case: id = ideal n = ncols(id); } if( ty=="int" or ty=="intvec" or ty=="intmat" ) { if ( ty == "int" ) { intmat S =id; } else { intmat S = intmat(id); } intvec i = S[1..nrows(S),1..ncols(S)]; kill id; intvec id = i; //case: id = intvec n = size(id); } //--------------- consider intvec v and empty product ----------------------- if( tt!=0 ) { for (j=1; j<=size(v); j++) { if ( v[j] <= 0 or v[j] > n ) //v outside range of id { return(1); //empty product is 1 } } id = id[v]; //consider part of id } //corresponding to v //--------------------- special case: one factor is zero --------------------- if ( typeof(id) == "ideal") { if( size(id) < ncols(id) ) { poly f; return(f); } } //-------------------------- finally, multiply objects ----------------------- n = size(id); def f(1) = id[1]; for( j=2; j<=n; j=j+1 ) { def f(j)=f(j-1)*id[j]; } return(f(n)); } example { "EXAMPLE:"; echo = 2; ring r= 0,(x,y,z),dp; ideal m = maxideal(1); product(m); product(m[2..3]); matrix M[2][3] = 1,x,2,y,3,z; product(M); intvec v=2,4,6; product(M,v); intvec iv = 1,2,3,4,5,6,7,8,9; v=1..5,7,9; product(iv,v); intmat A[2][3] = 1,1,1,2,2,2; product(A,3..5); } /////////////////////////////////////////////////////////////////////////////// proc sort (def id, list #) "USAGE: sort(id[,v,o,n]); id = ideal/module/intvec/list @* sort may be called with 1, 2 or 3 arguments in the following way: @* sort(id[,v,n]); v=intvec of positive integers, n=integer, @* sort(id[,o,n]); o=string (any allowed ordstr of a ring), n=integer RETURN: a list l of two elements: @format l[1]: object of same type as input but sorted in the following way: - if id=ideal/module: generators of id are sorted w.r.t. intvec v (id[v[1]] becomes 1-st, id[v[2]] 2-nd element, etc.). If no v is present, id is sorted w.r.t. ordering o (if o is given) or w.r.t. actual monomial ordering (if no o is given): NOTE: generators with SMALLER(!) leading term come FIRST (e.g. sort(id); sorts backwards to actual monomial ordering) - if id=list or intvec: sorted w.r.t. < (indep. of other arguments) - if n!=0 the ordering is inverse, i.e. w.r.t. v(size(v)..1) default: n=0 l[2]: intvec, describing the permutation of the input (hence l[2]=v if v is given (with positive integers)) @end format NOTE: If v is given id may be any simply indexed object (e.g. any list or string); if v[i]<0 and i<=size(id) v[i] is set internally to i; entries of v must be pairwise distinct to get a permutation id. Zero generators of ideal/module are deleted If 'o' is given, the input is sorted by considering leading terms w.r.t. the new ring ordering given by 'o' EXAMPLE: example sort; shows an example " { int ii,jj,s,n = 0,0,1,0; string id_typ=typeof(id); if ((id_typ!="ideal") and (id_typ!="module") and (id_typ!="matrix") and (id_typ!="list") and (id_typ!="intvec")) { return (id,0); } intvec v; if ( defined(basering) ) { def P = basering; } if ( size(#)==0 and (typeof(id)=="ideal" or typeof(id)=="module" or typeof(id)=="matrix")) { id = simplify(id,2); for ( ii=1; ii=1 and (typeof(id)=="ideal" or typeof(id)=="module" or typeof(id)=="matrix") ) { if ( typeof(#[1])=="string" ) { execute("ring r1 =("+charstr(P)+"),("+varstr(P)+"),("+#[1]+");"); def i = imap(P,id); v = sortvec(i); setring P; n=2; } } if ( typeof(id)=="intvec" or typeof(id)=="list" ) { int Bn,Bi,Bj,Bb; intvec pivot; for(Bi=size(id);Bi>0;Bi--) { pivot[Bi]=Bi; } while(Bj==0) { Bi++; Bj=1; for(Bn=1;Bn<=size(id)-Bi;Bn++) { if(id[pivot[Bn]]>id[pivot[Bn+1]]) { Bb=pivot[Bn]; pivot[Bn]=pivot[Bn+1]; pivot[Bn+1]=Bb; Bj=0; } } } def Br=id; for(Bi=size(id);Bi>0;Bi--) { Br[Bi]=id[pivot[Bi]]; } return(list(Br,pivot)); } if ( size(#)!=0 and n==0 ) { v = #[1]; } if( size(#)==2 ) { if ( #[2] != 0 ) { v = v[size(v)..1]; } } s = size(v); if( size(id) < s ) { s = size(id); } def m = id; if ( size(m) != 0 ) { for ( jj=1; jj<=s; jj++) { if ( v[jj]<=0 ) { v[jj]=jj; } m[jj] = id[v[jj]]; } } if ( v == 0 ) { v = 1; } list L=m,v; return(L); } example { "EXAMPLE:"; echo = 2; ring r0 = 0,(x,y,z,t),lp; ideal i = x3,z3,xyz; sort(i); //sorts using lex ordering, smaller polys come first sort(i,3..1); sort(i,"ls")[1]; //sort w.r.t. negative lex ordering intvec v =1,10..5,2..4;v; sort(v)[1]; // sort v lexicographically sort(v,"Dp",1)[1]; // sort v w.r.t (total sum, reverse lex) // Note that in general: lead(sort(M)) != sort(lead(M)), e.g: module M = [0, 1, 1, 0], [1, 0, 0, 1]; M; sort(lead(M), "c, dp")[1]; lead(sort(M, "c, dp")[1]); // In order to sort M wrt a NEW ordering by considering OLD leading // terms use one of the following equivalent commands: module( M[ sort(lead(M), "c,dp")[2] ] ); sort( M, sort(lead(M), "c,dp")[2] )[1]; // BUG: Please, don't use this sort for integer vectors or lists // with them if there can be negative integers! // TODO: for some HiWi sort(3..-3)[1]; sort(list(-v, v))[1]; } /////////////////////////////////////////////////////////////////////////////// static proc lsum (int n, list l) { if (n>10) { return( lsum(n div 2,list(l[1..(n div 2)])) + lsum(n-n div 2, list(l[(n div 2+1)..n])) ); } else { def Summe=l[1]; for (int i=2;i<=n;i++) { Summe=Summe+l[i]; } return(Summe); } } /////////////////////////////////////////////////////////////////////////////// proc sum (def id, list #) "USAGE: sum(id[,v]); id ideal/vector/module/matrix/intvec/intmat/list, v intvec (default: v=1..number of entries of id) ASSUME: list members can be added. RETURN: The sum of all entries of id [with index given by v] of type depending on the entries of id. NOTE: If id is not a list, id is treated as a list of polys resp. integers. A module m is identified with the corresponding matrix M (columns of M generate m). @* If v is outside the range of id, we have the empty sum and the result will be 0 (of type int). EXAMPLE: example sum; shows an example " { //-------------------- initialization and special feature --------------------- int n,j,tt; string ty; // will become type of id list l; // We wish to allow something like sum(x(1..10)) if x(1),...,x(10) are // variables. x(1..10) is a list of polys and enters the procedure with // id=x(1) and # a list with 9 polys, #[1]= x(2),...,#[9]= x(10). Hence, in // this case # is never empty. If an additional intvec v is given, // it is added to #, so we have to separate it first and make // the rest a list which has to be added. int s = size(#); if( s!=0 ) { if ( typeof(#[s])=="intvec" or typeof(#[s])=="int") { intvec v = #[s]; tt=1; s=s-1; if ( s>0 ) { # = #[1..s]; } } } if ( s>0 ) { l = list(id)+#; kill id; list id = l; //case: id = list ty = "list"; } else { ty = typeof(id); } //------------------------------ reduce to 3 cases --------------------------- if( ty=="poly" or ty=="ideal" or ty=="vector" or ty=="module" or ty=="matrix" ) { //case: id = ideal ideal i = ideal(matrix(id)); kill id; ideal id = simplify(i,2); //delete 0 entries } if( ty=="int" or ty=="intvec" or ty=="intmat" ) { //case: id = intvec if ( ty == "int" ) { intmat S =id; } else { intmat S = intmat(id); } intvec i = S[1..nrows(S),1..ncols(S)]; kill id; intvec id = i; } //------------------- consider intvec v and empty sum ----------------------- if( tt!=0 ) { for (j=1; j<=size(v); j++) { if ( v[j] <= 0 or v[j] > size(id) ) //v outside range of id { return(0); //empty sum is 0 } } id = id[v]; //consider part of id } //corresponding to v //-------------------------- finally, add objects --------------------------- n = size(id); if (n>10) { return( lsum(n div 2,list(id[1..(n div 2)])) + lsum(n-n div 2, list(id[(n div 2+1)..n])) ); } else { def Summe=id[1]; for (int lauf=2;lauf<=n;lauf++) { Summe=Summe+id[lauf]; } return(Summe); } } example { "EXAMPLE:"; echo = 2; ring r1 = 0,(x,y,z),dp; vector pv = [xy,xz,yz,x2,y2,z2]; sum(pv); sum(pv,2..5); matrix M[2][3] = 1,x,2,y,3,z; intvec w=2,4,6; sum(M,w); intvec iv = 1,2,3,4,5,6,7,8,9; sum(iv,2..4); iv = intvec(1..100); sum(iv); ring r2 = 0,(x(1..10)),dp; sum(x(3..7),intvec(1,3,5)); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc watchdog(int i, string cmd) "USAGE: watchdog(i,cmd); i integer, cmd string RETURN: Result of cmd, if the result can be computed in i seconds. Otherwise the computation is interrupted after i seconds, the string "Killed" is returned and the global variable 'watchdog_interrupt' is defined. NOTE: * the current basering should not be watchdog_rneu, since watchdog_rneu will be killed * if there are variable names of the structure x(i) all polynomials have to be put into eval(...) in order to be interpreted correctly * a second Singular process is started by this procedure EXAMPLE: example watchdog; shows an example " { if (defined(basering)) { string rname=nameof(basering); def rsave=basering; } if (defined(watchdog_rneu)) { kill watchdog_rneu; } if ( i > 0 ) { // fork, get the pid of the child and send it the command link l_fork="ssi:fork"; open(l_fork); execute("write(l_fork,quote(" + cmd + "));"); list L=l_fork; int j=waitfirst(L,i*1000); // check, whether we have a result, and return it if (j==1) { def result = read(l_fork); if (defined(rsave)) { if (nameof(basering)!=rname) { def watchdog_rneu=basering; setring rsave; if (!defined(result)) { def result=fetch(watchdog_rneu,result); } } } if(defined(watchdog_interrupt)) { kill watchdog_interrupt; } } else { string result="Killed"; if(!defined(watchdog_interrupt)) { int watchdog_interrupt=1; export watchdog_interrupt; } } close(l_fork); return(result); } else { ERROR("First argument of watchdog has to be a positive integer."); } } example { "EXAMPLE:"; echo=2; proc sleep(int s) {return(system("sh","sleep "+string(s)));} watchdog(1,"sleep(5)"); watchdog(10,"sleep(5)"); } /////////////////////////////////////////////////////////////////////////////// proc deleteSublist(intvec v,list l) "USAGE: deleteSublist(v,l); intvec v; list l where the entries of the integer vector v correspond to the positions of the elements to be deleted RETURN: list without the deleted elements EXAMPLE: example deleteSublist; shows an example" { list k; int i,j,skip; j=1; skip=0; intvec vs=sort(v)[1]; for ( i=1 ; i <=size(vs) ; i++) { while ((j+skip) < vs[i]) { k[j] = l[j+skip]; j++; } skip++; } if(vs[size(vs)] 32003) { q = 32003; } } if (defined(basering) == 0) { mark=1; ring r = 0,x,dp; } def I = ideal(matrix(J)); poly p = product(maxideal(1)); matrix Coef=coef(I[1],p); ideal id, jd, rest; intvec v,re; list result,l; for(ii=2; ii<=ncols(I); ii++) { Coef=concat(Coef,coef(I[ii],p)); } id = Coef[2,1..ncols(Coef)]; id = simplify(id,6); for (ii=1; ii<=size(id); ii++) { l = primefactors(number(id[ii]),q); list jdl=l[1]; jd = jd,jdl[1..size(jdl)]; kill jdl; rest=rest, l[3]; } jd = simplify(jd,6); for (ii=1; ii<=size(jd); ii++) { v[ii]=int(jd[ii]); } v = sort(v)[1]; rest = simplify(rest,6); id = sort(id)[1]; if (mark) { for (ii=1; ii<=size(rest); ii++) { re[ii] = int(rest[ii]); } result = v,re; } else { result = v,rest; } return(result); } example { "EXAMPLE:"; echo = 2; primecoeffs(intvec(7*8*121,7*8));""; ring r = 0,(b,c,t),dp; ideal I = -13b6c3t+4b5c4t,-10b4c2t-5b4ct2; primecoeffs(I); } /////////////////////////////////////////////////////////////////////////////// proc timeFactorize(poly i,list #) "USAGE: timeFactorize(p,d); poly p , integer d RETURN: factorize(p) if the factorization finished after d-1 seconds otherwhise f is considered to be irreducible EXAMPLE: example timeFactorize; shows an example " { def P=basering; if (size(#) > 0) { if ((typeof(#[1]) == "int")&&(#[1])) { int wait = #[1]; int j = 10; string bs = nameof(basering); link l_fork = "ssi:fork"; open(l_fork); write(l_fork, quote(timeFactorize(eval(i)))); // sleep in small intervalls for appr. one second if (wait > 0) { while(j < 1000000) { if (status(l_fork, "read", "ready", j)) {break;} j = j + j; } } // sleep in intervalls of one second from now on j = 1; while (j < wait) { if (status(l_fork, "read", "ready", 1000000)) {break;} j = j + 1; } if (status(l_fork, "read", "ready")) { def result = read(l_fork); if (bs != nameof(basering)) { def PP = basering; setring P; def result = imap(PP, result); kill PP; } close(l_fork); } else { list result; intvec v=1,1; result[1]=list(1,i); result[2]=v; close(l_fork); } return (result); } } return(factorH(i)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),dp; poly p=((x2+y3)^2+xy6)*((x3+y2)^2+x10y); p=p^2; //timeFactorize(p,2); //timeFactorize(p,20); } proc timeStd(ideal i,list #) "USAGE: timeStd(i,d), i ideal, d integer RETURN: std(i) if the standard basis computation finished after d-1 seconds and i otherwhise EXAMPLE: example timeStd; shows an example " { def P=basering; if (size(#) > 0) { if ((typeof(#[1]) == "int")&&(#[1])) { int wait = #[1]*1000; string bs = nameof(basering); link l_fork = "ssi:fork"; open(l_fork); write(l_fork, quote(std(eval(i)))); list L=l_fork; int j=waitfirst(L,wait); if (j==0) // timeout { ideal result=i; } else { def result = read(l_fork); if (bs != nameof(basering)) { def PP = basering; setring P; def result = imap(PP, result); kill PP; } } close(l_fork); return (result); } } return(std(i)); } example { "EXAMPLE:"; echo = 2; ring r=32003,(a,b,c,d,e),dp; int n=7; ideal i= a^n-b^n, b^n-c^n, c^n-d^n, d^n-e^n, a^(n-1)*b+b^(n-1)*c+c^(n-1)*d+d^(n-1)*e+e^(n-1)*a; def i1=timeStd(i,1); def i2=timeStd(i,20); listvar(); } proc factorH(poly p) "USAGE: factorH(p) p poly RETURN: factorize(p) NOTE: changes variables to make the last variable the principal one in the multivariate factorization and factorizes then the polynomial EXAMPLE: example factorH; shows an example " { def R=basering; int i,j; int n=1; int d=nrows(coeffs(p,var(1))); for(i=1;i<=nvars(R);i++) { j=nrows(coeffs(p,var(i))); if(d>j) { n=i; d=j; } } ideal ma=maxideal(1); //die letzte Variable ist die Hauptvariable ma[nvars(R)]=var(n); ma[n]=var(nvars(R)); map phi=R,ma; list fac=factorize(phi(p)); list re=phi(fac); return(re); } example { "EXAMPLE:"; echo = 2; system("random",992851144); ring r=32003,(x,y,z,w,t),lp; poly p=y2w9+yz7t-yz5w4-z2w4t4-w8t3; factorize(p); //fast system("random",992851262); //factorize(p); //slow system("random",992851262); factorH(p); } singular-4.0.3+ds/Singular/LIB/gitfan.lib000066400000000000000000000305021266270727000201070ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////// version="version gitfan.lib 4.0.2.0 Apr_2015 "; // $Id: c630def1ba7f290eb2f5cd73c376c8852cfeea24 $ category="Algebraic Geometry"; info=" LIBRARY: gitfan.lib Compute GIT-fans. AUTHORS: Janko Boehm boehm@mathematik.uni-kl.de @* Simon Keicher keicher@mail.mathematik.uni-tuebingen.de @* Yue Ren ren@mathematik.uni-kl.de OVERVIEW: This library computes GIT-fans, torus orbits and GKZ-fans. It uses the package 'gfanlib' by Anders N. Jensen and some algorithms have been outsourced to C++ to improve the performance. Check https://github.com/skeicher/gitfan_singular for updates. KEYWORDS: library; gitfan; GIT; geometric invariant theory; quotients PROCEDURES: afaces(ideal); Returns a list of intvecs that correspond to all a-faces gitCone(ideal,bigintmat,bigintmat); Returns the GIT-cone around the given weight vector w gitFan(ideal,bigintmat); Returns the GIT-fan of the H-action defined by Q on V(a) gkzFan(bigintmat); Returns the GKZ-fan of the matrix Q isAface(ideal,intvec); Checks whether intvec corresponds to an ideal-face orbitCones(ideal,bigintmat); Returns the list of all projected a-faces "; LIB "parallel.lib"; // for parallelWaitAll //////////////////////////////////////////////////// proc mod_init() { LIB"gfanlib.so"; } static proc int2face(int n, int r) { int k = r-1; intvec v; int n0 = n; while(n0 > 0) { while(2^k > n0) { k--; //v[size(v)+1] = 0; } v = k+1,v; n0 = n0 - 2^k; k--; } v = v[1..size(v)-1]; return(v); } ///////////////////////////////// proc isAface(ideal a, intvec gam0) "USAGE: isAface(a,gam0); a: ideal, gam0:intvec PURPOSE: Checks whether the face of the positive orthant, that is spanned by all i-th unit vectors, where i ranges amongst the entries of gam0, is an a-face. RETURN: int EXAMPLE: example isaface; shows an example " { poly pz; // special case: gam0 is the zero-cone: if (size(gam0) == 1 and gam0[1] == 0) { ideal G; // is an a-face if and only if RL0(0,...,0) = const // set all entries to 0: int i; for (int k = 1; k <= ncols(a); k++) { pz = subst(a[k], var(1), 0); for (i = 2; i <= nvars(basering); i++) { pz = subst(pz, var(i), 0); } G = G, pz; } G = std(G); // monomial inside?: if(1 == G) { return(0); } return(1); } // ring is too big: Switch to KK[T_i; e_i\in gam0] instead: def R = basering; string initNewRing = "ring Rgam0 = 0,("; for (int i=1; i 1) { return(1); // true } return(0); // false } example { echo = 2; ring R = 0,(T(1..4)),dp; ideal I = T(1)*T(2)-T(4); intvec w = 1,4; intvec v = 1,2,4; isAface(I,w); // should be 0 "-----------"; isAface(I,v); // should be 1 } //////////////////////////////////////////////////// proc afacesPart(ideal a, int d, int start, int end, int r) { intvec gam0; int i; list AF; for(i = start; i <= end; i++) { if(i < 2^r) { gam0 = int2face(i,r); // take gam0 only if it has // at least d rays: if(size(gam0) >= d) { if (isAface(a,gam0)) { AF[size(AF) + 1] = gam0; } } } } return(AF); } //////////////////////////////////////////////////// proc afaces(ideal a, list #) "USAGE: afaces(a, b, c); a: ideal, d: int, c: int PURPOSE: Returns a list of all a-faces (represented by intvecs). Moreover, it is possible to specify a dimensional bound b, upon which only cones of that dimension and above are returned. Lastly, as the computation is parallizable, one can specify c, the number of cores to be used by the computation. RETURN: a list of intvecs EXAMPLE: example afaces; shows an example " { int d = 1; int ncores = 1; if ((size(#) > 0) and (typeof(#[1]) == "int")) { d = #[1]; } if ((size(#) > 1) and (typeof(#[2]) == "int")) { ncores = #[2]; } list AF; intvec gam0; int r = nvars(basering); // check if 0 is an a-face: gam0 = 0; if (isAface(a,gam0)) { AF[size(AF) + 1] = gam0; } // check for other a-faces: // make ncores processes: int step = 2^r div ncores; int i; list args; for(int k = 0; k < ncores; k++) { args[size(args) + 1] = list(a, d, k * step + 1, (k+1) * step, r); } string command = "afacesPart"; list out = parallelWaitAll(command, args); // do remaining ones: for(i = ncores * step +1; i < 2^r; i++) { "another one needed"; gam0 = int2face(i,r); // take gam0 only if it has // at least d rays: if(size(gam0) >= d) { if (isAface(a,gam0)) { AF[size(AF) + 1] = gam0; } } } // read out afaces of out into AF: for(i = 1; i <= size(out); i++) { AF = AF + out[i]; } return(AF); } example { echo = 2; ring R = 0,T(1..3),dp; ideal a = T(1)+T(2)+T(3); list F = afaces(a,3,4); print(F); print(size(F)); // 2nd ex // ring R2 = 0,T(1..3),dp; ideal a2 = T(2)^2*T(3)^2+T(1)*T(3); list F2 = afaces(a2,3,4); print(F2); print(size(F2)); // 3rd ex // ring R3 = 0,T(1..3),dp; ideal a3 = 0; list F3 = afaces(a3,3,4); print(F3); print(size(F3)); // bigger example // ring R = 0,T(1..15),dp; ideal a = T(1)*T(10)-T(2)*T(7)+T(3)*T(6), T(1)*T(11)-T(2)*T(8)+T(4)*T(6), T(1)*T(12)-T(2)*T(9)+T(5)*T(6), T(1)*T(13)-T(3)*T(8)+T(4)*T(7), T(1)*T(14)-T(3)*T(9)+T(5)*T(7), T(1)*T(15)-T(4)*T(9)+T(5)*T(8), T(2)*T(13)-T(3)*T(11)+T(4)*T(10), T(2)*T(14)-T(3)*T(12)+T(5)*T(10), T(2)*T(15)-T(4)*T(12)+T(5)*T(11), T(3)*T(15)-T(4)*T(14)+T(5)*T(13), T(6)*T(13)-T(7)*T(11)+T(8)*T(10), T(6)*T(14)-T(7)*T(12)+T(9)*T(10), T(6)*T(15)-T(8)*T(12)+T(9)*T(11), T(7)*T(15)-T(8)*T(14)+T(9)*T(13), T(10)*T(15)-T(11)*T(14)+T(12)*T(13); int t = timer; list F4 = afaces(a,0,2); print(size(F4)); timer - t; int t = timer; list F4 = afaces(a,0); print(size(F4)); timer - t; } /////////////////////////////////////// proc orbitCones(ideal a, bigintmat Q, list #) "USAGE: orbitCones(a, Q, b, c); a: ideal, Q: bigintmat, b: int, c: int PURPOSE: Returns a list consisting of all cones Q(gam0) where gam0 is an a-face. Moreover, it is possible to specify a dimensional bound b, upon which only cones of that dimension and above are returned. Lastly, as the computation is parallizable, one can specify c, the number of cores to be used by the computation. RETURN: a list of cones EXAMPLE: example orbitCones; shows an example " { list AF; if((size(#) > 1) and (typeof(#[2]) == "int")) { AF = afaces(a, nrows(Q), #[2]); } else { AF = afaces(a, nrows(Q)); } int dimensionBound = 0; if((size(#) > 0) and (typeof(#[1]) == "int")) { dimensionBound = #[1]; } list OC; intvec gam0; int j; for(int i = 1; i <= size(AF); i++) { gam0 = AF[i]; if(gam0 == 0) { bigintmat M[1][nrows(Q)]; } else { bigintmat M[size(gam0)][nrows(Q)]; for (j = 1; j <= size(gam0); j++) { M[j,1..ncols(M)] = Q[1..nrows(Q),gam0[j]]; } } cone c = coneViaPoints(M); if((dimension(c) >= dimensionBound) and (!(listContainsCone(OC, c)))) { OC[size(OC)+1] = c; } kill M, c; } return(OC); } example { echo=2; intmat Q[3][4] = 1,0,1,0, 0,1,0,1, 0,0,1,1; ring R = 0,T(1..4),dp; ideal a = 0; orbitCones(a, Q); } /////////////////////////////////////// proc gitCone(ideal a, bigintmat Q, bigintmat w) "USAGE: gitCone(a, Q, w); a: ideal, Q:bigintmat, w:bigintmat PURPOSE: Returns the GIT-cone lambda(w), i.e. the intersection of all orbit cones containing the vector w. NOTE: call this only if you are interested in a single GIT-cone. RETURN: a cone. EXAMPLE: example gitCone; shows an example " { list OC = orbitCones(a, Q); cone lambda = nrows(Q); for(int i = 1; i <= size(OC); i++) { cone c = OC[i]; if(containsInSupport(c, w)) { lambda = convexIntersection(lambda, c); } kill c; } return(lambda); } example { echo=2; intmat Q[3][4] = 1,0,1,0, 0,1,0,1, 0,0,1,1; ring R = 0,T(1..4),dp; ideal a = 0; bigintmat w[1][3] = 3,3,1; cone lambda = gitCone(a, Q, w); rays(lambda); bigintmat w2[1][3] = 1,1,1; cone lambda2 = gitCone(a, Q, w2); rays(lambda2); } ///////////////////////////////////// proc gitFan(ideal a, bigintmat Q, list #) "USAGE: gitFan(a, Q); a: ideal, Q:bigintmat PURPOSE: Returns the GIT-fan of the H-action defined by Q on V(a). An optional third parameter of type 'int' is interpreted as the number of CPU-cores you would like to use. Note that 'system("--cpus");' returns the number of cpu available in your system. RETURN: a fan. EXAMPLE: example gitFan; shows an example " { list OC = orbitCones(a, Q, #); fan f = refineCones(OC, Q); return(f); } example { echo=2; intmat Q[3][4] = 1,0,1,0, 0,1,0,1, 0,0,1,1; ring R = 0,T(1..4),dp; ideal a = 0; gitFan(a, Q); // 2nd example // kill Q; intmat Q[3][6] = 1,1,0,0,-1,-1, 0,1,1,-1,-1,0, 1,1,1,1,1,1; ring R = 0,T(1..6),dp; ideal a = T(1)*T(6) + T(2)*T(5) + T(3)*T(4); int t = rtimer; fan F = gitFan(a, Q); t = rtimer - t; int tt = rtimer; fan F = gitFan(a, Q, 4); tt = rtimer - tt; t; tt; "--------"; kill R, Q, t, tt; // next example // ring R = 0,T(1..10),dp; ideal a = T(5)*T(10)-T(6)*T(9)+T(7)*T(8), T(1)*T(9)-T(2)*T(7)+T(4)*T(5), T(1)*T(8)-T(2)*T(6)+T(3)*T(5), T(1)*T(10)-T(3)*T(7)+T(4)*T(6), T(2)*T(10)-T(3)*T(9)+T(4)*T(8); bigintmat Q[4][10] = 1,0,0,0,1,1,1,0,0,0, 0,1,0,0,1,0,0,1,1,0, 0,0,1,0,0,1,0,1,0,1, 0,0,0,1,0,0,1,0,1,1; int t = rtimer; fan F = gitFan(a, Q); t = rtimer - t; int tt = rtimer; fan F = gitFan(a, Q, 4); tt = rtimer - tt; t; tt; "--------"; kill R, Q, t, tt; // next example // ring R = 0,T(1..15),dp; ideal a = T(1)*T(10)-T(2)*T(7)+T(3)*T(6), T(1)*T(11)-T(2)*T(8)+T(4)*T(6), T(1)*T(12)-T(2)*T(9)+T(5)*T(6), T(1)*T(13)-T(3)*T(8)+T(4)*T(7), T(1)*T(14)-T(3)*T(9)+T(5)*T(7), T(1)*T(15)-T(4)*T(9)+T(5)*T(8), T(2)*T(13)-T(3)*T(11)+T(4)*T(10), T(2)*T(14)-T(3)*T(12)+T(5)*T(10); bigintmat Q[5][15] = 1,0,0,0,0,1,1,1,1,0,0,0,0,0,0, 0,1,0,0,0,1,0,0,0,1,1,1,0,0,0, 0,0,1,0,0,0,1,0,0,1,0,0,1,1,0, 0,0,0,1,0,0,0,1,0,0,1,0,1,0,1, 0,0,0,0,1,0,0,0,1,0,0,1,0,1,1; int t = rtimer; fan F = gitFan(a, Q); t = rtimer - t; int tt = rtimer; fan F = gitFan(a, Q, 4); tt = rtimer - tt; t; tt; } ///////////////////////////////////// // Computes all simplicial orbit cones // w.r.t. the 0-ideal: static proc simplicialToricOrbitCones(bigintmat Q) { intvec gam0; list OC; cone c; int r = ncols(Q); int j; for(int i = 1; i < 2^r; i++ ) { gam0 = int2face(i,r); // each simplicial cone is generated by // exactly nrows(Q) many columns of Q: if(size(gam0) == nrows(Q)) { bigintmat M[size(gam0)][nrows(Q)]; for(j = 1; j <= size(gam0); j++) { M[j,1..ncols(M)] = Q[1..nrows(Q),gam0[j]]; } c = coneViaPoints(M); if((dimension(c) == nrows(Q)) and (!(listContainsCone(OC, c)))) { OC[size(OC)+1] = c; } kill M; } } return(OC); } ///////////////////////////////////// proc gkzFan(bigintmat Q) "USAGE: gkzFan(Q); a: ideal, Q:bigintmat PURPOSE: Returns the GKZ-fan of the matrix Q. RETURN: a fan. EXAMPLE: example gkzFan; shows an example " { // only difference to gitFan: // it suffices to consider all faces // that are simplicial: list OC = simplicialToricOrbitCones(Q); fan f = refineCones(OC, Q); return(f); } example { echo=2; intmat Q[3][4] = 1,0,1,0, 0,1,0,1, 0,0,1,1; gkzFan(Q); } singular-4.0.3+ds/Singular/LIB/gkdim.lib000066400000000000000000000052701266270727000177360ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version gkdim.lib 4.0.0.0 Jun_2013 "; // $Id: 9bd3587a6b567e4bb5339de91ac3afe94d3aeb31 $ category="Noncommutative"; info=" LIBRARY: gkdim.lib Procedures for calculating the Gelfand-Kirillov dimension AUTHORS: Lobillo, F.J., jlobillo@ugr.es @* Rabelo, C., crabelo@ugr.es Support: 'Metodos algebraicos y efectivos en grupos cuanticos', BFM2001-3141, MCYT, Jose Gomez-Torrecillas (Main researcher). NOTE: The built-in command @code{dim}, executed for a module in @plural, computes the Gelfand-Kirillov dimension. PROCEDURES: GKdim(M); Gelfand-Kirillov dimension computation of the factor-module, whose presentation is given by the matrix M. "; /////////////////////////////////////////////////////////////////////////////////// static proc idGKdim(ideal I) "USAGE: idGKdim(I), I is a left ideal RETURN: int, the Gelfand-Kirillov dimension of the R/I NOTE: uses the dim procedure, if the factor-module is zero, -1 is returned " { if (attrib(I,"isSB")<>1) { I=std(I); } int d = dim(I); // if (d==-1) {d++;} // The GK-dimension of a finite dimensional module is zero // levandov: but for consistency, GKdim(std(1)) == -1, // mimicking the behaviour of dim() procedure. return (d); } /////////////////////////////////////////////////////////////////////////////// proc GKdim(list L) "USAGE: GKdim(L); L is a left ideal/module/matrix RETURN: int PURPOSE: compute the Gelfand-Kirillov dimension of the factor-module, whose presentation is given by L, e.g. R^r/L NOTE: if the factor-module is zero, -1 is returned EXAMPLE: example GKdim; shows examples " { def M = L[1]; int d = -1; if (typeof(M)=="ideal") { d=idGKdim(M); } else { if (typeof(M)=="matrix") { module N = module(M); kill M; module M = N; } if (typeof(M)=="module") { if (attrib(M,"isSB")<>1) { M=std(M); } d=dim(M); } else { ERROR("The input must be an ideal, a module or a matrix."); } } return (d); } example { "EXAMPLE:";echo=2; ring R = 0,(x,y,z),Dp; matrix C[3][3]=0,1,1,0,0,-1,0,0,0; matrix D[3][3]=0,0,0,0,0,x; def r = nc_algebra(C,D); setring r; r; ideal I=x; GKdim(I); ideal J=x2,y; GKdim(J); module M=[x2,y,1],[x,y2,0]; GKdim(M); ideal A = x,y,z; GKdim(A); ideal B = 1; GKdim(B); GKdim(ideal(0)) == nvars(basering); // should be true, i.e., evaluated to 1 } /////////////////////////////////////////////////////////////////////////////// proc gkdim(list L) { return(GKdim(L)); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/gmspoly.lib000066400000000000000000000307021266270727000203330ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version gmspoly.lib 4.0.0.0 Jun_2013 "; // $Id: 3c735c6f40c59642aa84612e0da4c2cd7b7e4176 $ category="Singularities"; info=" LIBRARY: gmspoly.lib Gauss-Manin System of Tame Polynomials AUTHOR: Mathias Schulze, mschulze at mathematik.uni-kl.de OVERVIEW: A library for computing the Gauss-Manin system of a cohomologically tame polynomial f. Schulze's algorithm [Sch05], based on Sabbah's theory [Sab98], is used to compute a good basis of (the Brieskorn lattice of) the Gauss-Manin system and the differential operation of f in terms of this basis. In addition, there is a test for tameness in the sense of Broughton. Tame polynomials can be considered as an affine algebraic analogue of local analytic isolated hypersurface singularities. They have only finitely many citical points, and those at infinity do not give rise to atypical values in a sense depending on the precise notion of tameness considered. Well-known notions of tameness like tameness, M-tameness, Malgrange-tameness, and cohomological tameness, and their relations, are reviewed in [Sab98,8]. For ordinary tameness, see Broughton [Bro88,3]. Sabbah [Sab98] showed that the Gauss-Manin system, the D-module direct image of the structure sheaf, of a cohomologically tame polynomial carries a similar structure as in the isolated singularity case, coming from a Mixed Hodge structure on the cohomology of the Milnor (typical) fibre (see gmssing.lib). The data computed by this library encodes the differential structure of the Gauss-Manin system, and the Mixed Hodge structure of the Milnor fibre over the complex numbers. As a consequence, it yields the Hodge numbers, spectral pairs, and monodromy at infinity. REFERENCES: [Bro88] S. Broughton: Milnor numbers and the topology of polynomial hypersurfaces. Inv. Math. 92 (1988) 217-241. [Sab98] C. Sabbah: Hypergeometric periods for a tame polynomial. arXiv.org math.AG/9805077. [Sch05] M. Schulze: Good bases for tame polynomials. J. Symb. Comp. 39,1 (2005), 103-126. PROCEDURES: isTame(f); test whether the polynomial f is tame goodBasis(f); good basis of Brieskorn lattice of cohom. tame polynomial f SEE ALSO: gmssing_lib KEYWORDS: tame polynomial; Gauss-Manin system; Brieskorn lattice; mixed Hodge structure; V-filtration; weight filtration; monodromy; spectrum; spectral pairs; good basis "; LIB "linalg.lib"; LIB "ring.lib"; /////////////////////////////////////////////////////////////////////////////// static proc mindegree(matrix A) { int d=0; while(A/var(1)^(d+1)*var(1)^(d+1)==A) { d++; } return(d); } /////////////////////////////////////////////////////////////////////////////// static proc maxdegree(matrix A) { int d=0; matrix N[nrows(A)][ncols(A)]; while(A/var(1)^(d+1)!=N) { d++; } return(d); } /////////////////////////////////////////////////////////////////////////////// proc isTame(poly f) "USAGE: isTame(f); poly f ASSUME: basering has no variables named w(1),w(2),... RETURN: @format int k= 1; if f is tame in the sense of Broughton [Bro88,3] 0; if f is not tame @end format REMARKS: procedure implements Proposition 3.1 in [Bro88] KEYWORDS: tame polynomial EXAMPLE: example isTame; shows examples " { int d=vdim(std(jacob(f))); def @X=basering; int n=nvars(@X); ring ext_ring=0,(w(1..n)),dp; setring @X; def @WX=changechar(ringlist(ext_ring)); setring @WX; kill ext_ring; ideal J=jacob(imap(@X,f)); int i; for(i=1;i<=n;i++) { J[i]=J[i]+w(i); } int D=vdim(std(J)); setring(@X); kill @WX; return(d>0&&d==D); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),dp; isTame(x2y+x); isTame(x3+y3+xy); } /////////////////////////////////////////////////////////////////////////////// static proc chart(matrix A) { A=ideal(homog(transpose(ideal(A)),var(2))); def r=basering; map h=r,1,var(1); return(h(A)); } /////////////////////////////////////////////////////////////////////////////// static proc pidbasis(module M0,module M) { int m=nrows(M); int n=ncols(M); module L,N; module T=freemodule(m); while(matrix(L)!=matrix(M)) { L=M; M=T,M; N=transpose(std(transpose(M))); T=N[1..m]; M=N[m+1..ncols(N)]; M=freemodule(n),transpose(M); N=std(transpose(M)); N=transpose(simplify(N,1)); M=N[n+1..ncols(N)]; M=transpose(M); } if(maxdegree(M)>0) { print(" ? module not free"); return(module()); } attrib(M,"isSB",1); N=lift(T,simplify(reduce(M0,M),2)); return(N); } /////////////////////////////////////////////////////////////////////////////// static proc vfiltmat(matrix B,int d) { int mu=ncols(B); module V=freemodule(mu); module V0=var(1)^(d-1)*freemodule(mu); attrib(V0,"isSB",1); module V1=B; option(redSB); while(size(reduce(V1,V0))>0) { V=std(V0+V1); V0=var(1)^(d-1)*V; attrib(V0,"isSB",1); V1=B*matrix(V1)-var(1)^d*diff(matrix(V1),var(1)); } option("noredSB"); B=lift(V0,B*matrix(V)-var(1)^d*diff(matrix(V),var(1))); list l=eigenvals(B); def e0,s0=l[1..2]; module U; int i,j,i0,j0,i1,j1,k; for(k=int(e0[ncols(e0)]-e0[1]);k>=1;k--) { U=0; for(i=1;i<=ncols(e0);i++) { U=U+syz(power(jet(B,0)-e0[i],s0[i])); } B=lift(U,B*U); V=V*U; for(i0,i=1,1;i0<=ncols(e0);i0++) { for(i1=1;i1<=s0[i0];i1,i=i1+1,i+1) { for(j0,j=1,1;j0<=ncols(e0);j0++) { for(j1=1;j1<=s0[j0];j1,j=j1+1,j+1) { if(leadcoef(e0[i0]-e0[1])>=1&&leadcoef(e0[j0]-e0[1])<1) { B[i,j]=B[i,j]/var(1); } if(leadcoef(e0[i0]-e0[1])<1&&leadcoef(e0[j0]-e0[1])>=1) { B[i,j]=B[i,j]*var(1); } } } } } for(i0,i=1,1;i0<=ncols(e0);i0++) { if(leadcoef(e0[i0]-e0[1])>=1) { for(i1=1;i1<=s0[i0];i1,i=i1+1,i+1) { B[i,i]=B[i,i]-1; V[i]=V[i]*var(1); } e0[i0]=e0[i0]-1; } else { i=i+s0[i0]; } } l=spnf(list(e0,s0)); e0,s0=l[1..2]; } U=0; for(i=1;i<=ncols(e0);i++) { U=U+syz(power(jet(B,0)-e0[i],s0[i])); } B=lift(U,B*U); V=V*U; d=mindegree(V); V=V/var(1)^d; B=B+d*matrix(freemodule(mu)); for(i=ncols(e0);i>=1;i--) { e0[i]=e0[i]+d; } return(e0,s0,V,B); } /////////////////////////////////////////////////////////////////////////////// static proc spec(ideal e0,intvec s0,module V,matrix B) { int mu=ncols(B); int i,j,k; int d=maxdegree(V); int d0=d; V=chart(V); module U=std(V); while(size(reduce(var(1)^d*freemodule(mu),U))>0) { d++; } if(d>d0) { k=d-d0; B=B-k*freemodule(mu); for(i=1;i<=ncols(e0);i++) { e0[i]=e0[i]-k; } } module G=lift(V,var(1)^d*freemodule(mu)); G=std(G); G=simplify(G,1); ideal e; intvec s; e[mu]=0; for(j,k=1,1;j<=ncols(e0);j++) { for(i=s0[j];i>=1;i,k=i-1,k+1) { e[k]=e0[j]; s[k]=j; } } ideal a; a[mu]=0; for(i=1;i<=mu;i++) { a[i]=leadcoef(e[leadexp(G[i])[nvars(basering)+1]])+leadexp(G[i])[1]; } return(a,e0,e,s,V,B,G); } /////////////////////////////////////////////////////////////////////////////// static proc fsplit(ideal e0,ideal e,intvec s,module V,matrix B,module G) { int mu=ncols(e); int i,j,k; number n,n0; vector v,v0; list F; for(i=ncols(e0);i>=1;i--) { F[i]=module(matrix(0,mu,1)); } for(i=mu;i>=1;i--) { v=G[i]; v0=lead(v); n0=leadcoef(e[leadexp(v0)[nvars(basering)+1]])+leadexp(v0)[1]; v=v-lead(v); while(v!=0) { n=leadcoef(e[leadexp(v)[nvars(basering)+1]])+leadexp(v)[1]; if(n==n0) { v0=v0+lead(v); v=v-lead(v); } else { v=0; } } j=s[leadexp(v0)[nvars(basering)+1]]; F[j]=F[j]+v0; } matrix B0=jet(B,0); module U,U0,U1,U2; matrix N; for(i=size(F);i>=1;i--) { N=B0-e0[i]; U0=0; while(size(F[i])>0) { k=0; U1=jet(F[i],0); while(size(U1)>0) { for(j=ncols(U1);j>=1;j--) { if(size(reduce(U1[j],std(U0)))>0) { U0=U1[j]+U0; } } U1=N*U1; k++; } F[i]=module(F[i]/var(1)); } U=U0+U; } V=V*U; G=lift(U,G); B=lift(U,B*U); return(e,V,B,G); } /////////////////////////////////////////////////////////////////////////////// static proc glift(ideal e,module V,matrix B,module G) { int mu=ncols(e); int d=maxdegree(B); B=chart(B); G=std(G); G=simplify(G,1); int i,j,k; ideal v; for(i=mu;i>=1;i--) { v[i]=e[leadexp(G[i])[nvars(basering)+1]]+leadexp(G[i])[1]; } number c; matrix g[mu][1]; matrix m[mu][1]; matrix a[mu][1]; matrix A[mu][mu]; module M=var(1)^d*G; module N=var(1)*B*matrix(G)+var(1)^(d+2)*diff(matrix(G),var(1)); while(size(N)>0) { j=mu; for(k=mu-1;k>=1;k--) { if(N[k]>N[j]) { j=k; } } i=mu; while(leadexp(M[i])[nvars(basering)+1]!=leadexp(N[j])[nvars(basering)+1]) { i--; } k=leadexp(N[j])[1]-leadexp(M[i])[1]; if(k==0||i==j) { c=leadcoef(N[j])/leadcoef(M[i]); A[i,j]=A[i,j]+c*var(1)^k; N[j]=N[j]-c*var(1)^k*M[i]; } else { c=leadcoef(N[j])/leadcoef(M[i])/(1-k-leadcoef(v[i])+leadcoef(v[j])); G[j]=G[j]+c*var(1)^(k-1)*G[i]; M[j]=M[j]+c*var(1)^(k-1)*M[i]; g=c*var(1)^(k-1)*G[i]; N[j]=N[j]+(var(1)*B*g+var(1)^(d+2)*diff(g,var(1)))[1]; m=M[i]; a=transpose(A)[j]; N=N-c*var(1)^(k-1)*m*transpose(a); } } G=V*G; G=G/var(1)^mindegree(G); return(G,A); } /////////////////////////////////////////////////////////////////////////////// proc goodBasis(poly f) "USAGE: goodBasis(f); poly f ASSUME: f is cohomologically tame in the sense of Sabbah [Sab98,8] RETURN: @format ring R; basering with new variable s ideal b; [matrix(b)] is a good basis of the Brieskorn lattice matrix A; A(s)=A0+s*A1 and t[matrix(b)]=[matrix(b)](A(s)+s^2*(d/ds)) @end format REMARKS: procedure implements Algorithm 6 in [Sch05] KEYWORDS: tame polynomial; Gauss-Manin system; Brieskorn lattice; mixed Hodge structure; V-filtration; weight filtration; monodromy; spectrum; spectral pairs; good basis SEE ALSO: gmssing_lib EXAMPLE: example goodBasis; shows examples " { def @X=basering; int n=nvars(@X); ideal J=jacob(f); if(vdim(std(J))<=0) { ERROR("input is not cohomologically tame"); } int i,j,k,l; ideal X=maxideal(1); string c="ring @XS=0,(s,"+varstr(@X)+"),(C,dp(1),dp(n));"; execute(c); poly f=imap(@X,f); ideal J=imap(@X,J); ideal JS=std(J+var(1)); ideal b0=kbase(JS); int mu=ncols(b0); ideal X=imap(@X,X); ideal b; matrix A; module B,B0; ideal K,L,M=1,J,1; ideal K0,L0,M0=X,X,X; module K1,L1,K2,L2; module LL1; for(i=1;i<=deg(f)-1;i++) { M=M,M0; M0=M0*X; } ring @S=0,(s,t),(dp,C); number a0; ideal a; int d; ideal e,e0; intvec s,s0; matrix A,B; module V,G; while(2*a0!=mu*n) { setring(@XS); B=0; while(size(B)k) { k++; K=K,K0; K0=K0*X; B=0; while(size(B)==0||size(B)>mu) { l++; for(i=1;i<=size(L0);i++) { for(j=1;j<=n;j++) { L=L,J[j]*L0[i]-var(1)*diff(L0[i],var(j+1)); } } L0=L0*X; M=M,M0; M0=M0*X; K1=coeffs(K,K,product(X)); L1=std(coeffs(L,M,product(X))); LL1=jet(lead(L1),0); attrib(LL1,"isSB",1); K2=simplify(reduce(K1,LL1),2); L2=intersect(K2,L1); B=pidbasis(K2,L2); } B0=std(coeffs(reduce(matrix(K,nrows(K),nrows(B))*B,JS),b0)); b=matrix(K,nrows(K),nrows(B))*B; } A=lift(B,reduce(coeffs(f*b+var(1)^2*diff(b,var(1)),M,product(X)),L1)); d=maxdegree(A); A=chart(A); setring(@S); e0,s0,V,B=vfiltmat(imap(@XS,A),d); a,e0,e,s,V,B,G=spec(e0,s0,V,B); a0=leadcoef(a[1]); for(i=2;i<=mu;i++) { a0=a0+leadcoef(a[i]); } } G,A=glift(fsplit(e0,e,s,V,B,G)); setring(@XS); b=matrix(b)*imap(@S,G); A=imap(@S,A); export(b,A); kill @S; setring(@X); return(@XS); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y,z),dp; poly f=x+y+z+x2y2z2; def Rs=goodBasis(f); setring(Rs); b; print(jet(A,0)); print(jet(A/var(1),0)); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/gmssing.lib000066400000000000000000001140741266270727000203150ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version gmssing.lib 4.0.0.0 Jun_2013 "; // $Id: 22524a91064015541e57d856baa142d98178ecca $ category="Singularities"; info=" LIBRARY: gmssing.lib Gauss-Manin System of Isolated Singularities AUTHOR: Mathias Schulze, mschulze at mathematik.uni-kl.de OVERVIEW: A library for computing invariants related to the Gauss-Manin system of an isolated hypersurface singularity. REFERENCES: [Sch01] M. Schulze: Algorithms for the Gauss-Manin connection. J. Symb. Comp. 32,5 (2001), 549-564. [Sch02] M. Schulze: The differential structure of the Brieskorn lattice. In: A.M. Cohen et al.: Mathematical Software - ICMS 2002. World Scientific (2002). [Sch03] M. Schulze: Monodromy of Hypersurface Singularities. Acta Appl. Math. 75 (2003), 3-13. [Sch04] M. Schulze: A normal form algorithm for the Brieskorn lattice. J. Symb. Comp. 38,4 (2004), 1207-1225. PROCEDURES: gmsring(t,s); Gauss-Manin system of t with variable s gmsnf(p,K); Gauss-Manin normal form of p gmscoeffs(p,K); Gauss-Manin basis representation of p bernstein(t); Bernstein-Sato polynomial of t monodromy(t); Jordan data of complex monodromy of t spectrum(t); singularity spectrum of t sppairs(t); spectral pairs of t vfilt(t); V-filtration of t on Brieskorn lattice vwfilt(t); weighted V-filtration of t on Brieskorn lattice tmatrix(t); matrix of t w.r.t. good basis of Brieskorn lattice endvfilt(V); endomorphism V-filtration on Jacobian algebra sppnf(a,w[,m]); spectral pairs normal form of (a,w[,m]) sppprint(spp); print spectral pairs spp spadd(sp1,sp2); sum of spectra sp1 and sp2 spsub(sp1,sp2); difference of spectra sp1 and sp2 spmul(sp0,k); linear combination of spectra sp spissemicont(sp[,opt]); semicontinuity test of spectrum sp spsemicont(sp0,sp[,opt]); semicontinuous combinations of spectra sp0 in sp spmilnor(sp); Milnor number of spectrum sp spgeomgenus(sp); geometrical genus of spectrum sp spgamma(sp); gamma invariant of spectrum sp SEE ALSO: mondromy_lib, spectrum_lib, gmspoly_lib, dmod_lib KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice; mixed Hodge structure; V-filtration; weight filtration; Bernstein-Sato polynomial; monodromy; spectrum; spectral pairs; good basis "; LIB "linalg.lib"; /////////////////////////////////////////////////////////////////////////////// static proc stdtrans(ideal I) { def @R=basering; string os=ordstr(@R); int j=find(os,",C"); if(j==0) { j=find(os,"C,"); } if(j==0) { j=find(os,",c"); } if(j==0) { j=find(os,"c,"); } if(j>0) { os[j..j+1]=" "; } execute("ring @S="+charstr(@R)+",(gmspoly,"+varstr(@R)+"),(c,dp,"+os+");"); ideal I=homog(imap(@R,I),gmspoly); module M=transpose(transpose(I)+freemodule(ncols(I))); M=std(M); setring(@R); execute("map h=@S,1,"+varstr(@R)+";"); module M=h(M); for(int i=ncols(M);i>=1;i--) { for(j=ncols(M);j>=1;j--) { if(M[i][1]==0) { M[i]=0; } if(i!=j&&M[j][1]!=0) { if(lead(M[i][1])/lead(M[j][1])!=0) { M[i]=0; } } } } M=transpose(simplify(M,2)); I=ideal(M[1]); attrib(I,"isSB",1); M=M[2..ncols(M)]; module U=transpose(M); return(list(I,U)); } /////////////////////////////////////////////////////////////////////////////// proc gmsring(poly t,string s) "USAGE: gmsring(t,s); poly t, string s ASSUME: characteristic 0; local degree ordering; isolated critical point 0 of t RETURN: @format ring G; Gauss-Manin system of t with variable s poly gmspoly=t; ideal gmsjacob; Jacobian ideal of t ideal gmsstd; standard basis of Jacobian ideal matrix gmsmatrix; matrix(gmsjacob)*gmsmatrix==matrix(gmsstd) ideal gmsbasis; monomial vector space basis of Jacobian algebra int Gmssing::gmsmaxdeg; maximal weight of variables @end format NOTE: gmsbasis is a C[[s]]-basis of H'' and [t,s]=s^2 KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice EXAMPLE: example gmsring; shows examples " { def @R=basering; if(charstr(@R)!="0") { ERROR("characteristic 0 expected"); } for(int i=nvars(@R);i>=1;i--) { if(var(i)>1) { ERROR("local ordering expected"); } } ideal dt=jacob(t); list l=stdtrans(dt); ideal g=l[1]; if(vdim(g)<=0) { if(vdim(g)==0) { ERROR("singularity at 0 expected"); } else { ERROR("isolated critical point 0 expected"); } } matrix B=l[2]; ideal m=kbase(g); int gmsmaxdeg; for(i=nvars(@R);i>=1;i--) { if(deg(var(i))>gmsmaxdeg) { gmsmaxdeg=deg(var(i)); } } string os=ordstr(@R); int j=find(os,",C"); if(j==0) { j=find(os,"C,"); } if(j==0) { j=find(os,",c"); } if(j==0) { j=find(os,"c,"); } if(j>0) { os[j..j+1]=" "; } execute("ring G="+string(charstr(@R))+",("+s+","+varstr(@R)+"),(ws("+ string(deg(highcorner(g))+2*gmsmaxdeg)+"),"+os+",c);"); poly gmspoly=imap(@R,t); ideal gmsjacob=imap(@R,dt); ideal gmsstd=imap(@R,g); matrix gmsmatrix=imap(@R,B); ideal gmsbasis=imap(@R,m); attrib(gmsstd,"isSB",1); export gmspoly,gmsjacob,gmsstd,gmsmatrix,gmsbasis,gmsmaxdeg; return(G); } example { "EXAMPLE:"; echo=2; ring @R=0,(x,y),ds; poly t=x5+x2y2+y5; def G=gmsring(t,"s"); setring(G); gmspoly; print(gmsjacob); print(gmsstd); print(gmsmatrix); print(gmsbasis); Gmssing::gmsmaxdeg; } /////////////////////////////////////////////////////////////////////////////// proc gmsnf(ideal p,int K) "USAGE: gmsnf(p,K); poly p, int K ASSUME: basering returned by gmsring RETURN: list nf; ideal nf[1]; projection of p to C[[s]] mod s^(K+1) ideal nf[2]; p==nf[1]+nf[2] NOTE: computation can be continued by setting p=nf[2] KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice EXAMPLE: example gmsnf; shows examples " { if(system("with","gms")) { return(system("gmsnf",p,gmsstd,gmsmatrix,(K+1)*deg(var(1))-2*gmsmaxdeg,K)); } intvec v=1; v[nvars(basering)]=0; int k; ideal r,q; r[ncols(p)]=0; q[ncols(p)]=0; poly s; int i,j; for(k=ncols(p);k>=1;k--) { while(p[k]!=0&°(lead(p[k]),v)<=K) { i=1; s=lead(p[k])/lead(gmsstd[i]); while(i(K+1)*deg(var(1))-2*gmsmaxdeg&& deg(lead(p[k]),v)<=K) { q[k]=q[k]+lead(p[k]); p[k]=p[k]-lead(p[k]); } } q[k]=q[k]+p[k]; } return(list(r,q)); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; def G=gmsring(t,"s"); setring(G); list l0=gmsnf(gmspoly,0); print(l0[1]); list l1=gmsnf(gmspoly,1); print(l1[1]); list l=gmsnf(l0[2],1); print(l[1]); } /////////////////////////////////////////////////////////////////////////////// proc gmscoeffs(ideal p,int K) "USAGE: gmscoeffs(p,K); poly p, int K ASSUME: basering constructed by gmsring RETURN: @format list l; matrix l[1]; C[[s]]-basis representation of p mod s^(K+1) ideal l[2]; p==matrix(gmsbasis)*l[1]+l[2] @end format NOTE: computation can be continued by setting p=l[2] KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice EXAMPLE: example gmscoeffs; shows examples " { list l=gmsnf(p,K); ideal r,q=l[1..2]; poly v=1; for(int i=2;i<=nvars(basering);i++) { v=v*var(i); } matrix C=coeffs(r,gmsbasis,v); return(list(C,q)); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; def G=gmsring(t,"s"); setring(G); list l0=gmscoeffs(gmspoly,0); print(l0[1]); list l1=gmscoeffs(gmspoly,1); print(l1[1]); list l=gmscoeffs(l0[2],1); print(l[1]); } /////////////////////////////////////////////////////////////////////////////// static proc mindegree(matrix A) { int d=-1; int i,j; for(i=nrows(A);i>=1;i--) { for(j=ncols(A);j>=1;j--) { if(d==-1||(ord(A[i,j])-1)) { d=ord(A[i,j]); } } } return(d); } /////////////////////////////////////////////////////////////////////////////// static proc maxdegree(matrix A) { int d=-1; int i,j; for(i=nrows(A);i>=1;i--) { for(j=ncols(A);j>=1;j--) { if(deg(A[i,j])>d) { d=deg(A[i,j]); } } } return(d); } /////////////////////////////////////////////////////////////////////////////// static proc saturate() { int mu=ncols(gmsbasis); ideal r=gmspoly*gmsbasis; matrix A0[mu][mu],C; module H0; module H,H1=freemodule(mu),freemodule(mu); int k=-1; list l; dbprint(printlevel-voice+2,"// compute saturation of H''"); while(size(reduce(H,std(H0*var(1))))>0) { dbprint(printlevel-voice+2,"// compute matrix A of t"); k++; dbprint(printlevel-voice+2,"// k="+string(k)); l=gmscoeffs(r,k); C,r=l[1..2]; A0=A0+C; dbprint(printlevel-voice+2,"// compute saturation step"); H0=H; H1=jet(module(A0*H1+var(1)^2*diff(matrix(H1),var(1))),k); H=H*var(1)+H1; } A0=A0-k*var(1); dbprint(printlevel-voice+2,"// compute basis of saturation of H''"); H=std(H0); dbprint(printlevel-voice+2,"// transform H'' to saturation of H''"); H0=division(freemodule(mu)*var(1)^k,H,k*deg(var(1)))[1]; return(A0,r,H,H0,k); } /////////////////////////////////////////////////////////////////////////////// static proc tjet(matrix A0,ideal r,module H,int K0,int K) { dbprint(printlevel-voice+2,"// compute matrix A of t"); dbprint(printlevel-voice+2,"// k="+string(K0+K+1)); list l=gmscoeffs(r,K0+K+1); matrix C; C,r=l[1..2]; A0=A0+C; dbprint(printlevel-voice+2,"// transform A to saturation of H''"); matrix A=division(A0*H+var(1)^2*diff(matrix(H),var(1)),H, (K+1)*deg(var(1)))[1]/var(1); return(A,A0,r); } /////////////////////////////////////////////////////////////////////////////// static proc eigenval(matrix A0,ideal r,module H,int K0) { dbprint(printlevel-voice+2, "// compute eigenvalues e with multiplicities m of A1"); matrix A; A,A0,r=tjet(A0,r,H,K0,0); list l=eigenvals(A); def e,m=l[1..2]; dbprint(printlevel-voice+2,"// e="+string(e)); dbprint(printlevel-voice+2,"// m="+string(m)); return(e,m,A0,r); } /////////////////////////////////////////////////////////////////////////////// static proc transform(matrix A,matrix A0,ideal r,module H,module H0,ideal e, intvec m,int K0,int K,int opt) { int mu=ncols(gmsbasis); int i,j,k; intvec d; d[ncols(e)]=0; if(opt) { dbprint(printlevel-voice+2, "// compute rounded maximal differences d of e"); for(i=1;i<=ncols(e);i++) { d[i]=int(e[ncols(e)]-e[i]); } } else { dbprint(printlevel-voice+2, "// compute maximal integer differences d of e"); for(i=1;id[i]) { d[i]=k; } if(-k>d[j]) { d[j]=-k; } } } } } dbprint(printlevel-voice+2,"// d="+string(d)); for(i,k=1,0;i<=size(d);i++) { if(k0) { int i0,j0,i1,j1; list l; while(k>0) { dbprint(printlevel-voice+2,"// transform to separate eigenvalues"); U=0; for(i=1;i<=ncols(e);i++) { U=U+syz(power(jet(A,0)-e[i],m[i])); } V=inverse(U); A=V*A*U; H=H*U; H0=V*H0; dbprint(printlevel-voice+2,"// transform to reduce maximum of d by 1"); for(i0,i=1,1;i0<=ncols(e);i0++) { for(i1=1;i1<=m[i0];i1,i=i1+1,i+1) { for(j0,j=1,1;j0<=ncols(e);j0++) { for(j1=1;j1<=m[j0];j1,j=j1+1,j+1) { if(d[i0]==0&&d[j0]>=1) { A[i,j]=A[i,j]*var(1); } if(d[i0]>=1&&d[j0]==0) { A[i,j]=A[i,j]/var(1); } } } } } H0=transpose(H0); for(i0,i=1,1;i0<=ncols(e);i0++) { if(d[i0]>=1) { for(i1=1;i1<=m[i0];i1,i=i1+1,i+1) { H[i]=H[i]*var(1); } d[i0]=d[i0]-1; } else { for(i1=1;i1<=m[i0];i1,i=i1+1,i+1) { A[i,i]=A[i,i]-1; H0[i]=H0[i]*var(1); } e[i0]=e[i0]-1; } } H0=transpose(H0); l=sppnf(list(e,d,m)); e,d,m=l[1..3]; k--; K0++; } A=jet(A,K); } dbprint(printlevel-voice+2,"// transform to separate eigenvalues"); U=0; for(i=1;i<=ncols(e);i++) { U=U+syz(power(jet(A,0)-e[i],m[i])); } V=inverse(U); A=V*A*U; H=H*U; H0=V*H0; return(A,A0,r,H,H0,e,m,K0); } /////////////////////////////////////////////////////////////////////////////// proc bernstein(poly t) "USAGE: bernstein(t); poly t ASSUME: characteristic 0; local degree ordering; isolated critical point 0 of t RETURN: @format list bs; Bernstein-Sato polynomial b(s) of t ideal bs[1]; number bs[1][i]; i-th root of b(s) intvec bs[2]; int bs[2][i]; multiplicity of i-th root of b(s) @end format KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice; Bernstein-Sato polynomial EXAMPLE: example bernstein; shows examples " { def @R=basering; int n=nvars(@R)-1; def @G=gmsring(t,"s"); setring(@G); matrix A; module U0; ideal e; intvec m; def A0,r,H,H0,K0=saturate(); A,A0,r=tjet(A0,r,H,K0,0); list l=minipoly(A); e,m=l[1..2]; e=-e; l=spnf(spadd(list(e,m),list(ideal(-1),intvec(1)))); setring(@R); list l=imap(@G,l); kill @G,gmsmaxdeg; return(l); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; bernstein(t); } /////////////////////////////////////////////////////////////////////////////// proc monodromy(poly t) "USAGE: monodromy(t); poly t ASSUME: characteristic 0; local degree ordering; isolated critical point 0 of t RETURN: @format list l; Jordan data jordan(M) of monodromy matrix exp(-2*pi*i*M) ideal l[1]; number l[1][i]; eigenvalue of i-th Jordan block of M intvec l[2]; int l[2][i]; size of i-th Jordan block of M intvec l[3]; int l[3][i]; multiplicity of i-th Jordan block of M @end format SEE ALSO: mondromy_lib, linalg_lib KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice; monodromy EXAMPLE: example monodromy; shows examples " { def @R=basering; int n=nvars(@R)-1; def @G=gmsring(t,"s"); setring(@G); matrix A; module U0; ideal e; intvec m; def A0,r,H,H0,K0=saturate(); e,m,A0,r=eigenval(A0,r,H,K0); A,A0,r,H,H0,e,m,K0=transform(A,A0,r,H,H0,e,m,K0,0,0); list l=jordan(A,e,m); setring(@R); list l=imap(@G,l); kill @G,gmsmaxdeg; return(l); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; monodromy(t); } /////////////////////////////////////////////////////////////////////////////// proc spectrum(poly t) "USAGE: spectrum(t); poly t ASSUME: characteristic 0; local degree ordering; isolated critical point 0 of t RETURN: @format list sp; singularity spectrum of t ideal sp[1]; number sp[1][i]; i-th spectral number intvec sp[2]; int sp[2][i]; multiplicity of i-th spectral number @end format SEE ALSO: spectrum_lib KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice; mixed Hodge structure; V-filtration; spectrum EXAMPLE: example spectrum; shows examples " { list l=vwfilt(t); return(spnf(list(l[1],l[3]))); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; spprint(spectrum(t)); } /////////////////////////////////////////////////////////////////////////////// proc sppairs(poly t) "USAGE: sppairs(t); poly t ASSUME: characteristic 0; local degree ordering; isolated critical point 0 of t RETURN: @format list spp; spectral pairs of t ideal spp[1]; number spp[1][i]; V-filtration index of i-th spectral pair intvec spp[2]; int spp[2][i]; weight filtration index of i-th spectral pair intvec spp[3]; int spp[3][i]; multiplicity of i-th spectral pair @end format SEE ALSO: spectrum_lib KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice; mixed Hodge structure; V-filtration; weight filtration; spectrum; spectral pairs EXAMPLE: example sppairs; shows examples " { list l=vwfilt(t); return(list(l[1],l[2],l[3])); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; sppprint(sppairs(t)); } /////////////////////////////////////////////////////////////////////////////// proc vfilt(poly t) "USAGE: vfilt(t); poly t ASSUME: characteristic 0; local degree ordering; isolated critical point 0 of t RETURN: @format list v; V-filtration on H''/s*H'' ideal v[1]; number v[1][i]; V-filtration index of i-th spectral number intvec v[2]; int v[2][i]; multiplicity of i-th spectral number list v[3]; module v[3][i]; vector space of i-th graded part in terms of v[4] ideal v[4]; monomial vector space basis of H''/s*H'' ideal v[5]; standard basis of Jacobian ideal @end format SEE ALSO: spectrum_lib KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice; mixed Hodge structure; V-filtration; spectrum EXAMPLE: example vfilt; shows examples " { list l=vwfilt(t); return(spnf(list(l[1],l[3],l[4]))+list(l[5],l[6])); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; vfilt(t); } /////////////////////////////////////////////////////////////////////////////// proc vwfilt(poly t) "USAGE: vwfilt(t); poly t ASSUME: characteristic 0; local degree ordering; isolated critical point 0 of t RETURN: @format list vw; weighted V-filtration on H''/s*H'' ideal vw[1]; number vw[1][i]; V-filtration index of i-th spectral pair intvec vw[2]; int vw[2][i]; weight filtration index of i-th spectral pair intvec vw[3]; int vw[3][i]; multiplicity of i-th spectral pair list vw[4]; module vw[4][i]; vector space of i-th graded part in terms of vw[5] ideal vw[5]; monomial vector space basis of H''/s*H'' ideal vw[6]; standard basis of Jacobian ideal @end format SEE ALSO: spectrum_lib KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice; mixed Hodge structure; V-filtration; weight filtration; spectrum; spectral pairs EXAMPLE: example vwfilt; shows examples " { def @R=basering; int n=nvars(@R)-1; def @G=gmsring(t,"s"); setring(@G); int mu=ncols(gmsbasis); matrix A; ideal e; intvec m; def A0,r,H,H0,K0=saturate(); e,m,A0,r=eigenval(A0,r,H,K0); A,A0,r,H,H0,e,m,K0=transform(A,A0,r,H,H0,e,m,K0,0,1); dbprint(printlevel-voice+2,"// compute weight filtration basis"); list l=jordanbasis(A,e,m); def U,v=l[1..2]; kill l; vector u0; int v0; int i,j,k,l; for(k,l=1,1;l<=ncols(e);k,l=k+m[l],l+1) { for(i=k+m[l]-1;i>=k+1;i--) { for(j=i-1;j>=k;j--) { if(v[i]>v[j]) { v0=v[i];v[i]=v[j];v[j]=v0; u0=U[i];U[i]=U[j];U[j]=u0; } } } } dbprint(printlevel-voice+2,"// transform to weight filtration basis"); matrix V=inverse(U); A=V*A*U; dbprint(printlevel-voice+2,"// compute standard basis of H''"); H=H*U; H0=std(V*H0); dbprint(printlevel-voice+2,"// compute spectral pairs"); ideal a; intvec w; for(i=1;i<=mu;i++) { j=leadexp(H0[i])[nvars(basering)+1]; a[i]=A[j,j]+ord(H0[i]) div deg(var(1))-1; w[i]=v[j]+n; } H=H*H0; H=simplify(jet(H/var(1)^(mindegree(H) div deg(var(1))),0),1); kill l; list l=sppnf(list(a,w,H))+list(gmsbasis,gmsstd); setring(@R); list l=imap(@G,l); kill @G,gmsmaxdeg; attrib(l[5],"isSB",1); return(l); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; vwfilt(t); } /////////////////////////////////////////////////////////////////////////////// static proc fsplit(ideal e0,intvec m0,matrix A,module H,module H0) { int mu=ncols(gmsbasis); dbprint(printlevel-voice+2,"// compute standard basis of H''"); H0=std(H0); H0=simplify(H0,1); dbprint(printlevel-voice+2,"// compute Hodge filtration"); int i,j,k; ideal e; intvec m; e[mu]=0; for(i=1;i<=ncols(e0);i++) { for(j=m0[i];j>=1;j--) { k++; e[k]=e0[i]; m[k]=i; } } number n,n0; vector v,v0; list F; for(i=ncols(e0);i>=1;i--) { F[i]=module(matrix(0,mu,1)); } for(i=mu;i>=1;i--) { v=H0[i]; v0=lead(v); n0=leadcoef(e[leadexp(v0)[nvars(basering)+1]])+leadexp(v0)[1]; v=v-lead(v); while(v!=0) { n=leadcoef(e[leadexp(v)[nvars(basering)+1]])+leadexp(v)[1]; if(n==n0) { v0=v0+lead(v); v=v-lead(v); } else { v=0; } } j=m[leadexp(v0)[nvars(basering)+1]]; F[j]=F[j]+v0; } dbprint(printlevel-voice+2,"// compute splitting of Hodge filtration"); matrix A0=jet(A,0); module U,U0,U1,U2; matrix N; for(i=size(F);i>=1;i--) { N=A0-e0[i]; U0=0; while(size(F[i])>0) { U1=jet(F[i],0); k=0; while(size(U1)>0) { for(j=ncols(U1);j>=1;j--) { if(size(reduce(U1[j],std(U0)))>0) { U0=U0+U1[j]; } } U1=N*U1; k++; } F[i]=module(F[i]/var(1)); } U=U0+U; } dbprint(printlevel-voice+2,"// transform to Hodge splitting basis"); H=H*U; H0=lift(U,H0); A=lift(U,A*U); return(e,A,H,H0); } /////////////////////////////////////////////////////////////////////////////// static proc glift(ideal e,matrix A,module H,module H0,int K) { poly s=var(1); int mu=ncols(gmsbasis); dbprint(printlevel-voice+2,"// compute standard basis of H''"); H0=std(H0); H0=simplify(H0,1); int i,j,k; ideal v; for(i=mu;i>=1;i--) { v[i]=e[leadexp(H0[i])[nvars(basering)+1]]+leadexp(H0[i])[1]; } dbprint(printlevel-voice+2, "// compute matrix A0 of t w.r.t. good basis H0 of H''"); number c; matrix h0[mu][1]; matrix m[mu][1]; matrix a0[mu][1]; matrix A0[mu][mu]; module M=H0; module N=jet(s*A*matrix(H0)+s^2*diff(matrix(H0),s),K+1); while(size(N)>0) { j=mu; for(k=mu-1;k>=1;k--) { if(N[k]>N[j]) { j=k; } } i=mu; while(leadexp(M[i])[nvars(basering)+1]!=leadexp(N[j])[nvars(basering)+1]) { i--; } k=leadexp(N[j])[1]-leadexp(M[i])[1]; if(k==0||i==j) { dbprint(printlevel-voice+3,"// compute A0["+string(i)+","+string(j)+"]"); c=leadcoef(N[j])/leadcoef(M[i]); A0[i,j]=A0[i,j]+c*s^k; N[j]=jet(N[j]-c*s^k*M[i],K+1); } else { dbprint(printlevel-voice+3, "// reduce H0["+string(j)+"] with H0["+string(i)+"]"); c=leadcoef(N[j])/leadcoef(M[i])/(1-k-leadcoef(v[i])+leadcoef(v[j])); H0[j]=H0[j]+c*s^(k-1)*H0[i]; M[j]=M[j]+c*s^(k-1)*M[i]; h0=c*s^(k-1)*H0[i]; N[j]=N[j]+jet(s*A*h0+s^2*diff(h0,s),K+1)[1]; m=M[i]; a0=transpose(A0)[j]; N=N-jet(c*s^(k-1)*m*transpose(a0),K+1); } } H0=H*H0; H0=H0/var(1)^(mindegree(H0) div deg(var(1))); return(A0,H0); } /////////////////////////////////////////////////////////////////////////////// proc tmatrix(poly t) "USAGE: tmatrix(t); poly t ASSUME: characteristic 0; local degree ordering; isolated critical point 0 of t RETURN: @format list l=A0,A1,T,M; matrix A0,A1; t=A0+s*A1+s^2*(d/ds) on H'' w.r.t. C[[s]]-basis M*T module T; C-basis of C^mu ideal M; monomial C-basis of H''/sH'' @end format KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice; mixed Hodge structure; V-filtration; weight filtration; monodromy; spectrum; spectral pairs; good basis EXAMPLE: example tmatrix; shows examples " { def @R=basering; int n=nvars(@R)-1; def @G=gmsring(t,"s"); setring(@G); int mu=ncols(gmsbasis); matrix A; module U0; ideal e; intvec m; def A0,r,H,H0,K0=saturate(); e,m,A0,r=eigenval(A0,r,H,K0); A,A0,r,H,H0,e,m,K0=transform(A,A0,r,H,H0,e,m,K0,K0+int(e[ncols(e)]-e[1]),1); A,H0=glift(fsplit(e,m,A,H,H0),K0); A0=jet(A,0); A=jet(A/var(1),0); list l=A0,A,H0,gmsbasis; setring(@R); list l=imap(@G,l); kill @G,gmsmaxdeg; return(l); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; list l=tmatrix(t); print(l[1]); print(l[2]); print(l[3]); print(l[4]); } /////////////////////////////////////////////////////////////////////////////// proc endvfilt(list v) "USAGE: endvfilt(v); list v ASSUME: v returned by vfilt RETURN: @format list ev; V-filtration on Jacobian algebra ideal ev[1]; number ev[1][i]; i-th V-filtration index intvec ev[2]; int ev[2][i]; i-th multiplicity list ev[3]; module ev[3][i]; vector space of i-th graded part in terms of ev[4] ideal ev[4]; monomial vector space basis of Jacobian algebra ideal ev[5]; standard basis of Jacobian ideal @end format KEYWORDS: singularities; Gauss-Manin system; Brieskorn lattice; mixed Hodge structure; V-filtration; endomorphism filtration EXAMPLE: example endvfilt; shows examples " { def a,d,V,m,g=v[1..5]; attrib(g,"isSB",1); int mu=ncols(m); module V0=V[1]; for(int i=2;i<=size(V);i++) { V0=V0,V[i]; } dbprint(printlevel-voice+2,"// compute multiplication in Jacobian algebra"); list M; module U=freemodule(ncols(m)); for(i=ncols(m);i>=1;i--) { M[i]=division(coeffs(reduce(m[i]*m,g,U),m)*V0,V0)[1]; } int j,k,i0,j0,i1,j1; number b0=number(a[1]-a[ncols(a)]); number b1,b2; matrix M0; module L; list v0=freemodule(ncols(m)); ideal a0=b0; list l; while(b0=1;j--) { for(i=ncols(a);i>=1;i--) { b2=number(a[i]-a[j]); if(b2>b0&&b2=2;k--) { l=l+list(ideal()); } dbprint(printlevel-voice+2,"// collect conditions for EV["+string(b0)+"]"); j=ncols(a); j0=mu; while(j>=1) { i0=1; i=1; while(i1) { l[k]=l[k],M0[1..i0-1,j0-d[j]+1..j0]; } } j0=j0-d[j]; j--; } dbprint(printlevel-voice+2,"// compose condition matrix"); L=transpose(module(l[1])); for(k=2;k<=ncols(m);k++) { L=L,transpose(module(l[k])); } dbprint(printlevel-voice+2,"// compute kernel of condition matrix"); v0=v0+list(syz(L)); a0=a0,b0; } dbprint(printlevel-voice+2,"// compute graded parts"); option(redSB); for(i=1;i0) { v1=v1+list(v0[i]); d1=d1,size(v0[i]); a1=a1,a0[i]; } i++; } return(list(a1,d1,v1,m,g)); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly t=x5+x2y2+y5; endvfilt(vfilt(t)); } /////////////////////////////////////////////////////////////////////////////// proc sppnf(list sp) "USAGE: sppnf(list(a,w[,m])); ideal a, intvec w, intvec m ASSUME: ncols(a)==size(w)==size(m) RETURN: order (a[i][,w[i]]) with multiplicity m[i] lexicographically EXAMPLE: example sppnf; shows examples " { ideal a=sp[1]; intvec w=sp[2]; int n=ncols(a); intvec m; list V; module v; int i,j; for(i=3;i<=size(sp);i++) { if(typeof(sp[i])=="intvec") { m=sp[i]; } if(typeof(sp[i])=="module") { v=sp[i]; for(j=n;j>=1;j--) { V[j]=module(v[j]); } } if(typeof(sp[i])=="list") { V=sp[i]; } } if(m==0) { for(i=n;i>=1;i--) { m[i]=1; } } int k; ideal a0; intvec w0,m0; list V0; number a1; int w1,m1; for(i=n;i>=1;i--) { if(m[i]!=0) { for(j=i-1;j>=1;j--) { if(m[j]!=0) { if(number(a[i])>number(a[j])|| (number(a[i])==number(a[j])&&w[i]0) { v=V[i]; V[i]=V[j]; V[j]=v; } } if(number(a[i])==number(a[j])&&w[i]==w[j]) { m[i]=m[i]+m[j]; m[j]=0; if(size(V)>0) { V[i]=V[i]+V[j]; } } } } k++; a0[k]=a[i]; w0[k]=w[i]; m0[k]=m[i]; if(size(V)>0) { V0[k]=V[i]; } } } if(size(V0)>0) { n=size(V0); module U=std(V0[n]); for(i=n-1;i>=1;i--) { V0[i]=simplify(reduce(V0[i],U),1); if(i>=2) { U=std(U+V0[i]); } } } if(k>0) { sp=a0,w0,m0; if(size(V0)>0) { sp[4]=V0; } } return(sp); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; list sp=list(ideal(-1/2,-3/10,-3/10,-1/10,-1/10,0,1/10,1/10,3/10,3/10,1/2), intvec(2,1,1,1,1,1,1,1,1,1,0)); sppprint(sppnf(sp)); } /////////////////////////////////////////////////////////////////////////////// proc sppprint(list spp) "USAGE: sppprint(spp); list spp RETURN: string s; spectral pairs spp EXAMPLE: example sppprint; shows examples " { string s; for(int i=1;inumber(sp2[1][i2])) { s[i]=sp2[1][i2]; m[i]=sp2[2][i2]; i++; i2++; } else { if(sp1[2][i1]+sp2[2][i2]!=0) { s[i]=sp1[1][i1]; m[i]=sp1[2][i1]+sp2[2][i2]; i++; } i1++; i2++; } } } else { s[i]=sp1[1][i1]; m[i]=sp1[2][i1]; i++; i1++; } } else { s[i]=sp2[1][i2]; m[i]=sp2[2][i2]; i++; i2++; } } return(list(s,m)); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; list sp1=list(ideal(-1/2,-3/10,-1/10,0,1/10,3/10,1/2),intvec(1,2,2,1,2,2,1)); spprint(sp1); list sp2=list(ideal(-1/6,1/6),intvec(1,1)); spprint(sp2); spprint(spadd(sp1,sp2)); } /////////////////////////////////////////////////////////////////////////////// proc spsub(list sp1,list sp2) "USAGE: spsub(sp1,sp2); list sp1, list sp2 RETURN: list sp; difference of spectra sp1 and sp2 EXAMPLE: example spsub; shows examples " { return(spadd(sp1,spmul(sp2,-1))); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; list sp1=list(ideal(-1/2,-3/10,-1/10,0,1/10,3/10,1/2),intvec(1,2,2,1,2,2,1)); spprint(sp1); list sp2=list(ideal(-1/6,1/6),intvec(1,1)); spprint(sp2); spprint(spsub(sp1,sp2)); } /////////////////////////////////////////////////////////////////////////////// proc spmul(list #) "USAGE: spmul(sp0,k); list sp0, int[vec] k RETURN: list sp; linear combination of spectra sp0 with coefficients k EXAMPLE: example spmul; shows examples " { if(size(#)==2) { if(typeof(#[1])=="list") { if(typeof(#[2])=="int") { return(list(#[1][1],#[1][2]*#[2])); } if(typeof(#[2])=="intvec") { list sp0=list(ideal(),intvec(0)); for(int i=size(#[2]);i>=1;i--) { sp0=spadd(sp0,spmul(#[1][i],#[2][i])); } return(sp0); } } } return(list(ideal(),intvec(0))); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; list sp=list(ideal(-1/2,-3/10,-1/10,0,1/10,3/10,1/2),intvec(1,2,2,1,2,2,1)); spprint(sp); spprint(spmul(sp,2)); list sp1=list(ideal(-1/6,1/6),intvec(1,1)); spprint(sp1); list sp2=list(ideal(-1/3,0,1/3),intvec(1,2,1)); spprint(sp2); spprint(spmul(list(sp1,sp2),intvec(1,2))); } /////////////////////////////////////////////////////////////////////////////// proc spissemicont(list sp,list #) "USAGE: spissemicont(sp[,1]); list sp, int opt RETURN: @format int k= 1; if sum of sp is positive on all intervals [a,a+1) [and (a,a+1)] 0; if sum of sp is negative on some interval [a,a+1) [or (a,a+1)] @end format EXAMPLE: example spissemicont; shows examples " { int opt=0; if(size(#)>0) { if(typeof(#[1])=="int") { opt=1; } } int i,j,k; i=1; while(i<=size(sp[2])-1) { j=i+1; k=0; while(j+1<=size(sp[2])&&number(sp[1][j])<=number(sp[1][i])+1) { if(opt==0||number(sp[1][j])1) { l0=spsemicont(sp0,list(sp[1..size(sp)-1])); for(i=1;i<=size(l0);i++) { if(size(l)>0) { j=1; while(j1) { return(l); } else { return(list(intvec(k-1))); } } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; list sp0=list(ideal(-1/2,-3/10,-1/10,0,1/10,3/10,1/2),intvec(1,2,2,1,2,2,1)); spprint(sp0); list sp1=list(ideal(-1/6,1/6),intvec(1,1)); spprint(sp1); list sp2=list(ideal(-1/3,0,1/3),intvec(1,2,1)); spprint(sp2); list sp=sp1,sp2; list l=spsemicont(sp0,sp); l; spissemicont(spsub(sp0,spmul(sp,l[1]))); spissemicont(spsub(sp0,spmul(sp,l[1]-1))); spissemicont(spsub(sp0,spmul(sp,l[1]+1))); } /////////////////////////////////////////////////////////////////////////////// proc spmilnor(list sp) "USAGE: spmilnor(sp); list sp RETURN: int mu; Milnor number of spectrum sp EXAMPLE: example spmilnor; shows examples " { return(sum(sp[2])); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; list sp=list(ideal(-1/2,-3/10,-1/10,0,1/10,3/10,1/2),intvec(1,2,2,1,2,2,1)); spprint(sp); spmilnor(sp); } /////////////////////////////////////////////////////////////////////////////// proc spgeomgenus(list sp) "USAGE: spgeomgenus(sp); list sp RETURN: int g; geometrical genus of spectrum sp EXAMPLE: example spgeomgenus; shows examples " { int g=0; int i=1; while(i+1<=size(sp[2])&&number(sp[1][i])<=number(0)) { g=g+sp[2][i]; i++; } if(i==size(sp[2])&&number(sp[1][i])<=number(0)) { g=g+sp[2][i]; } return(g); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; list sp=list(ideal(-1/2,-3/10,-1/10,0,1/10,3/10,1/2),intvec(1,2,2,1,2,2,1)); spprint(sp); spgeomgenus(sp); } /////////////////////////////////////////////////////////////////////////////// proc spgamma(list sp) "USAGE: spgamma(sp); list sp RETURN: number gamma; gamma invariant of spectrum sp EXAMPLE: example spgamma; shows examples " { int i,j; number g=0; for(i=1;i<=ncols(sp[1]);i++) { for(j=1;j<=sp[2][i];j++) { g=g+(number(sp[1][i])-number(nvars(basering)-2)/2)^2; } } g=-g/4+sum(sp[2])*number(sp[1][ncols(sp[1])]-sp[1][1])/48; return(g); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; list sp=list(ideal(-1/2,-3/10,-1/10,0,1/10,3/10,1/2),intvec(1,2,2,1,2,2,1)); spprint(sp); spgamma(sp); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/graal.lib000066400000000000000000001044311266270727000177300ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version graal.lib 4.0.2.1 26.03.2015 "; // $Id: edb2a43e302b0b2ea2ad329148d6d68f0f7f6bf0 $ category="Commutative Algebra"; info=" LIBRARY: graal.lib localization at prime ideals and their associated graded rings AUTHOR: Magdaleen Marais, magdaleen@aims.ac.za Yue Ren, ren@mathematik.uni-kl.de OVERVIEW: This library is on a computational treatment of localizations at prime ideals and their associated graded rings based on a work of Mora. Not only does it construct a ring isomorphic to the localization of an affine coordinate ring at a prime ideal, the algorithms in this library aim to exploit the topology in the localization by computing first and foremost in the associated graded ring and lifting the result to the localization afterwards. Features include a check for regularity and the resolution of ideals. REFERENCES: Mora, Teo: La queste del Saint Gr_a(A_L): A computational approach to local algebra Marais, Magdaleen and Ren, Yue: Mora's holy graal: Algorithms for computing in localizations at prime ideals PROCEDURES: graalMixed(ideal L[,int t]); contruct graalBearer dimensionOfLocalization(def L); dimension of the localization A_L of A at L systemOfParametersOfLocalization(def L); system of parameter of the localization A_L of A at L isLocalizationRegular(def L); test if localization A_L of A at L is regular warkedPreimageStd(warkedModule wM); std for warkedModule resolutionInLocalization(ideal I, def L); the resolution of I*A_L "; LIB "general.lib"; // for watchdog LIB "poly.lib"; // for hilbPoly LIB "standard.lib"; // for res proc mod_init() { /*** * graalBearer is a structure that contains those objects * of the intermediate steps to computing the associated graded algebra * that are worth saving for future computations. These are: * * ring A affine coordinate ring * ideal L ideal cutting out the subvariety * int s number of generators of L * ring Q polynomial ring of the ambient space * ideal H ideal such that A=Q/H * ideal J preimage of L * qring Q0y Q^0[Y1,...,Ys] * ideal scriptI , where f1,...,fs are the generators of L * qring Al the ring A_L = Q0y/scriptI * qring Ky K[Y1,...,Ys], where K quotient field of A/L * ideal scriptIin I_in * qring Graal associated graded ring, isomorphic to Ky/scriptIin * map ina Al -> Graal, maps standard basis of ideals * to standard basis of their respective initial ideals **/ newstruct("graalBearer","int s, qring A, ideal L, ring Q, ideal H, ideal J, ring Q0, ideal J0, ring Q0y, ideal scriptI, qring Al, qring Ky, ideal scriptIin, map Q0yToKy, qring Graal, map ina"); system("install","graalBearer","print",graalBearer_print,1); /*** * warkedModule is a structure built to hold two corresponding modules in Ay and Ky respectively. * More precisely, it contains space for: * graalBearer Gr a graalBearer containing all relevant global structures * module modQ0y a module M over Q0y * module stdmodQ0y a standard basis of M with respect to the weight w * matrix qQ0y a transformation matrix over Q0y such that * stdmodAy = qQ0y*modQ0y * module modKy a module M_in over Ky * module stdmodKy a standard basis of M_in * matrix qKy a transformation Matrix over Ky such that * stdmodKy = qKy*modKy * intvec w an intvec containing the weights on M * Note: "wark" is a scots noun for building **/ newstruct("warkedModule","graalBearer Gr, module modQ0y, module stdmodQ0y, matrix qQ0y, module modKy, module stdmodKy, matrix qKy, intvec w"); system("install","warkedModule","print",warkedModule_print,1); /*** * markedResolution is a structure built to hold two corresponding resolutions in Al and Graal respectively. * More precisely, it contains space for: * graalBearer Gr a graalBearer containing all relevant global structures * ideal idealAl a standard basis of an ideal I in Al * resolution resAl a resolution of I over Al * resolution resGraal a resolution of inI, the initial ideal of I over Graal * list weight a list containing weights on the modules in resAl **/ newstruct("markedResolution","graalBearer Gr, ideal idealAl, resolution resAl, resolution resGraal, list weight"); system("install","markedResolution","print",markedResolution_print,1); } /////////////////////////////////////////////////////////////////////////////// /*** * returns the number of Y, each of them corresponding to a generator of J. * we assume that the Ys are written in the first non-"c" block of our ordering, * for example (Y(1..s),X(1..n)),(c,ds(s),dp(n)) * or (Y(1..s),X(1..n)),(ds(s),c,dp(n)) * but not (X(1..n),Y(1..s)),(c,dp(s),ds(n)). **/ static proc numberOfYs() { list L = ringlist(basering); if (L[3][1][1]!="c") { return(size(ringlist(basering)[3][1][2])); } else { return(size(ringlist(basering)[3][2][2])); } } static proc yinitial(def F, list #) { int s; if (size(#)>0 && typeof(#[1])=="int") { s = #[1]; } else { s = numberOfYs(); } if (typeof(F)=="poly") { int k = size(F); poly inF = F[1]; intvec expv = leadexp(F); int d = sum(intvec(expv[1..s])); for (int i=2; i<=k; i++) { expv = leadexp(F[i]); if (sum(intvec(expv[1..s])) == d) { inF = inF + F[i]; } else { break; } } return(inF); } if (typeof(F)=="ideal") { int k = size(F); ideal inF = yinitial(F[1]); for (int i=2; i<=k; i++) { inF[i] = yinitial(F[i],s); } return(inF); } } /*** * suppose X(1),...,X(n) are the variables in the ring containing g, * checks whether g contains the variables X(1),...,X(n-1). **/ static proc containsVariablesApartFromLast(poly g) { intvec expv; int d; int s = nvars(basering)-1; int i,j; for (j=1; j<=size(g); j++) { expv = leadexp(g[j]); for (i=1; i<=s; i++) { if (expv[i] > 0) { return(i); } } } return(0); } /*** * assuming that the ordering is lexicographical, * checks whether m is in general position with repect to it. **/ static proc isInGeneralPosition(ideal m) { int n = nvars(basering); if (n == 1) { return(1); } int k = size(m); if (k == n) { m = sort(m)[1]; poly g; for (int i=2; i<=k; i++) { g = m[i]; if (leadmonom(g)!=var(k-i+1) || containsVariablesApartFromLast(g-lead(g))) { return(0); } } g = m[1]; if (containsVariablesApartFromLast(g)) { return(0); } return(1); } return(0); } /*** * finds a transformation of the last variable * which maps m into general position with respect to the lexicographical ordering lp. * returns the image of the last variable under the transformation and the image of m. **/ static proc findGeneralPosition(ideal m) { list L = ringlist(basering); int newRing = 0; if (L[3][1][1]!="lp" || L[3][1][2]!=nvars(basering)) { def origin = basering; execute("ring ringForGeneralPosition = ("+charstr(basering)+"),("+varstr(basering)+"),lp;"); ideal m = fetch(origin,m); newRing = 1; } ideal mGeneralPosition = std(m); int n = nvars(basering); poly p = var(n); while (!isInGeneralPosition(mGeneralPosition)) { // apply generic coordinate change to the last variable, // m -> mGeneralPosition, X_n |-> p // until mGeneraliPosition is indeed in general position. p = randomLast(5)[n]; mGeneralPosition = subst(m,var(n),p); mGeneralPosition = std(mGeneralPosition); } if (newRing == 1) { setring origin; ideal mGeneralPosition = fetch(ringForGeneralPosition,mGeneralPosition); poly p = fetch(ringForGeneralPosition,p); } return(p,mGeneralPosition); } /*** * tries for t seconds to find a transformation of the last variable, * which maps m into general position with respect to the lexicographical ordering lp. * if successful, returns the image of the last variable as well as the image of m. * if unsuccessful, returns (0,0) instead. **/ static proc tryFindingGeneralPosition(ideal m, int t) { def p, mgp; p, mgp = watchdog(t,"findGeneralPosition(ideal("+string(m)+"))"); if (typeof(p)=="string") { return(0,0); } return(p,mgp); } /*** * if mgp is in general position with respect to the lexicographical ordering lp, * sorts the generators such that their order is * X(1) - g(1) * X(2) - g(2) * ... * X(n-1) - g(n-1) * g(n), * where g(1),...,g(n-1) are polynomials in X(n). **/ static proc sortIdealInGeneralPosition(ideal mgp) { int k = size(mgp); ideal sortedMgp; sortedMgp[k]=0; ASSUME(1,size(mgp)==nvars(basering)); for (int i=1; i<=k; i++) { poly g = mgp[i]; int j = containsVariablesApartFromLast(g); if (j>0) { sortedMgp[j] = g; } else { sortedMgp[k] = g; } kill g; kill j; } return(sortedMgp); } /*** * if mgp is in general position with respect to the lexicographical ordering lp, * and sorted (see above), returns g(1),...,g(n-1). **/ static proc getImagesOfPreviousX(ideal mgp) { def origin = basering; def getImagesRing = changeord(list(list("lp",nvars(basering)))); setring getImagesRing; ideal mgp = fetch(origin,mgp); int k = size(mgp); ideal imagesOfPreviousX; imagesOfPreviousX[k]=0; for (int i=1; i<=k; i++) { poly g = mgp[i]; ASSUME(1,leadexp(g)[i]==1); if (g!=0) { g = (lead(g)-g)/leadcoef(g); } imagesOfPreviousX[i] = g; kill g; } setring origin; ideal imagesOfPreviousX = fetch(getImagesRing,imagesOfPreviousX); return (imagesOfPreviousX); } proc graalMixed(ideal L, list #) " USAGE: graalMixed(L,t); L ideal, t int (optional) RETURN: graalBearer with all the necessary structures for our machinery if t specified and t>0, puts an upper time limit on finding a necessary transformation to map an intermediate ideal into general position. NOTE: assumes that the current basering is a domain and that L is a prime ideal. EXAMPLE: example graalMixed; shows an example " { graalBearer Gr; /*** * store ring A and ideal L **/ Gr.A = qring(basering); Gr.L = L; int s = size(L); Gr.s = s; /*** * construct ring Q and ideals H,J **/ ideal H = ringlist(Gr.A)[4]; execute("ring Q = "+string(Gr.A)+";"); ideal H = fetch(Gr.A,H); H = sort(std(H))[1]; ideal J = fetch(Gr.A,L) + H; J = sort(std(J))[1]; Gr.Q = Q; Gr.H = H; Gr.J = J; /*** * construct ring Q0 and ideal J0 **/ intvec maxIndepSet = indepSet(std(J)); int trdeg = sum(maxIndepSet); int i; int n = nvars(Q); if (trdeg > 0) { string pars = ","; string vars; for (i=1; i<=n; i++) { if (maxIndepSet[i]>0) { pars = pars + string(var(i)) + ","; } else { vars = vars + string(var(i)) + ","; } } pars = pars[1..size(pars)-1]; vars = vars[1..size(vars)-1]; } else { string pars; string vars = varstr(basering); } execute("ring Q0 = ("+charstr(basering)+pars+"),("+vars+"),dp;"); ideal J0 = imap(Q,J); Gr.Q0 = Q0; Gr.J0 = J0; /*** * push J0 into general position **/ if (size(#)==0) { poly p; ideal mgp; p, mgp = findGeneralPosition(J0); } else { if ((#[1]==1) && (typeof(#[1])=="int")) { polg p; ideal mgp; p, mgp = tryFindingGeneralPosition(J0,#[1]); if (p == 0) { ERROR("timeout during computation of minimal polynomial"); return(Gr); } } else { ERROR("graal: unexpected optional paramemters"); return(Gr); } } n = nvars(Q0); mgp = sortIdealInGeneralPosition(mgp); ideal imageOfX = getImagesOfPreviousX(mgp); imageOfX[n] = p; for (i=1; i0) // { G = G, par(j2); j2++; } // else // { G = G, imageOfX[j1]; j1++; } } map Q0yToKy = Q0y,G; Gr.Q0yToKy = Q0yToKy; ideal scriptIin = Q0yToKy(inI); ASSUME(2,isStandardBasis(scriptIin)); scriptIin = std(scriptIin); Gr.Ky = qring(Ky); Gr.scriptIin = scriptIin; /*** * construct Graal **/ qring Graal = scriptIin; Gr.Graal = qring(Graal); map in_a = Al,imap(Ky,G); Gr.ina = in_a; return(Gr); } example { "EXAMPLE:"; echo = 2; // see [Mora] Example 6.5 ring Q = 0,(x,y,z),dp; ideal H = y2-xz; qring A = std(H); ideal L = x3-yz,x2y-z2; graalBearer Gr = graalMixed(L); Gr; } /*** * a print routine for graalBearers, * will overwrite the default print routine for newstructs **/ proc graalBearer_print(graalBearer Gr) { def A=Gr.A; setring A; "affine coordinate ring: "; " "+string(Gr.A); ideal quotientIdeal = ringlist(Gr.A)[4]; if (quotientIdeal != 0) { " mod <"+string(quotientIdeal)+">"; } ""; "ideal defining the subvariety: "; " <"+string(Gr.L)+">";""; def Al = Gr.Al; setring Al; "Al: "; " "+string(Gr.Al); ideal quotientIdeal = ringlist(basering)[4]; if (quotientIdeal != 0) { " mod <"+string(quotientIdeal)+">"; } kill quotientIdeal; def Graal = Gr.Graal; setring Graal; "graal: "; " "+string(Gr.Graal); ideal quotientIdeal = ringlist(basering)[4]; if (quotientIdeal != 0) { " mod <"+string(quotientIdeal)+">"; } kill quotientIdeal; " where "; setring Gr.A; for (int i=1; i<=Gr.s; i++) { " Y("+string(i)+") represents generator "+string(Gr.L[i]); } setring Al; list L = ringlist(basering); int yEnd = size(L[3][1][2]); ideal xAll; int n = nvars(basering); for (i=1; yEnd+i<=n; i++) { xAll[i] = var(yEnd+i); } string inaPrint = " and "+string(xAll)+" in Al are mapped to "; kill L; kill xAll; setring Graal; map ina = Gr.ina; ideal xAllImages; for (i=1; yEnd+i<=n; i++) { xAllImages[i] = ina[yEnd+i]; } inaPrint + string(xAllImages)+" in Graal"; kill ina; kill xAllImages; } /*** * a print routine for warkedModules, * will overwrite the default print routine for newstructs **/ proc warkedModule_print(warkedModule wM) { graalBearer Gr = wM.Gr; def Q0y = Gr.Q0y; setring Q0y; ideal quotientIdeal = ringlist(basering)[4]; "module over Q^0[Y] = "+string(basering)+" / <"+string(quotientIdeal)+">:"; print(matrix(wM.modQ0y)); "standard basis:"; print(matrix(wM.stdmodQ0y)); def Ky = Gr.Ky; setring Ky; ideal quotientIdeal = ringlist(basering)[4]; "module over K[Y] = "+string(basering)+" / <"+string(quotientIdeal)+">:"; print(matrix(wM.modKy)); "weights on the unit vectors: "+string(wM.w); } /*** * a print routine for markedModules, * will overwrite the default print routine for newstructs **/ proc markedModule_print(markedModule M) { graalBearer Gr = M.Gr; def Ay = Gr.Ky; setring Ay; module G = M.G; "module over Ay:"; print(G); def Ky = Gr.Graal; setring Ky; module H = M.H; "module over Ky:"; print(H); } proc dimensionOfLocalization(def L) " USAGE: dimensionOfLocalization(L); L ideal or graalBearer RETURN: int, the dimension of the localization A_L of A at L. EXAMPLE: example dimensionOfLocalization; shows an example " { if (typeof(L)=="ideal") { graalBearer Gr = graalMixed(L); return(dimensionOfLocalization(Gr)); } if (typeof(L)=="graalBearer") { graalBearer Gr = L; def Ky = Gr.Ky; setring Ky; ideal scriptIin = Gr.scriptIin; return(dim(scriptIin)); } ERROR("dimensionOfLocalization: unexpected parameters"); return(0); } example { "EXAMPLE:"; echo = 2; ring Q = 0,(X(1),X(2)),dp; ideal H = X(2)^2-(X(1)-1)*X(1)*(X(1)+1); ideal J = std(X(1),X(2)); qring A = std(H); ideal L = fetch(Q,J); graalBearer Gr = graalMixed(L); // def fA = Gr.fA; setring fA; dimensionOfLocalization(Gr); // = 1 } proc systemOfParametersOfLocalization(def L) " USAGE: systemOfParametersOfLocalization(def L); L ideal or graalBearer RETURN: ideal, a system of parameter of the localization A_L of A at L. EXAMPLE: example systemOfParameterOfLocalization; shows an example " { if (typeof(L)=="ideal") { graalBearer Gr = graalMixed(L); return(systemOfParametersOfIdealInLocalization(I, Gr)); } if (typeof(L)=="graalBearer") { graalBearer Gr = L; def Ky = Gr.Ky; setring Ky; int delta = dimensionOfLocalization(Gr); int s = Gr.s; int i,j; ideal H1 = Gr.scriptIin; for (i=1; i<=delta; i++) { poly lambda(i); for (j=1; j<=s; j++) { int c(i)(j) = random(0,10000); lambda(i) = lambda(i) + c(i)(j)*Y(j); } H1 = H1 + lambda(i); } H1 = std(H1); while (dim(H1) != 0) { H1 = Gr.scriptIin; for (i=1; i<=delta; i++) { for (j=1; j<=s; j++) { c(i)(j) = random(0,10000); lambda(i) = lambda(i) + c(i)(j)*Y(j); } H1 = H1 + lambda(i); } H1 = std(H1); } def Q = Gr.Q; setring Q; ideal J = Gr.J; ideal ret; for (i=1; i<=delta; i++) { poly a(i); for (j=1; j<=s; j++) { a(i) = a(i)+c(i)(j)*J[i]; } ret = ret + a(i); } def A = Gr.A; setring A; return(std(fetch(Q,ret))); } ERROR("systemOfParametersOfLocalization: unexpected parameters"); return(0); } example { "EXAMPLE:"; echo = 2; ring Q = 0,(X(1),X(2)),dp; ideal H = X(2)^2-(X(1)-1)*X(1)*(X(1)+1); ideal J = X(1),X(2); qring A = std(H); ideal L = fetch(Q,J); graalBearer Gr = graalMixed(L); systemOfParametersOfLocalization(Gr); // = 1 } /*** * returns true, if g only contains the last variuable. * returns false otherwise. **/ static proc isPolyInLastVariable(poly g) { int k = size(g); int n = nvars(basering); for (int i=1; i<=k; i++) { intvec v = leadexp(g[i]); v = v[1..n-1]; if (sum(v)>0) { return (0); } } return (1); } proc isLocalizationRegular(def L) " USAGE: isLocalizationRegular(def L); L ideal or graalBearer RETURN: int, 1 if the localization A_L of A at L is regular, 0 otherwise. EXAMPLE: example isLocalizationRegular; shows an example " { if (typeof(L)=="ideal") { graalBearer Gr = graalMixed(L); return(isLocalizationRegular(Gr)); } if (typeof(L)=="graalBearer") { graalBearer Gr = L; def Ky = Gr.Ky; setring Ky; ideal sscriptIin = Gr.scriptIin; option(redSB); sscriptIin = std(sscriptIin); option(noredSB); int i,j; poly gi; intvec expv; int s = Gr.s; for (i=1; i<=size(sscriptIin); i++) { gi = sscriptIin[i]; if (!isPolyInLastVariable(gi)) { for (j=1; j<=size(gi); j++) { expv = leadexp(gi[i]); if (sum(intvec(expv[1..s])) != 1) { return(0); } } } } return(1); } ERROR("isLocalizationRegular: unexpected parameters"); return(0); } example { "EXAMPLE:"; echo = 2; ring Q = 0,(X(1),X(2)),dp; ideal H = X(2)^2-(X(1)-1)*X(1)*(X(1)+1); ideal J = X(1),X(2); qring A = std(H); ideal L = fetch(Q,J); graalBearer Gr = graalMixed(L); isLocalizationRegular(Gr); // = 1 } /*** * returns the degree in Y **/ static proc yDeg(poly g, list #) { int s; if (size(#)>0 && typeof(#[1])=="int") { s = #[1]; } else { s = numberOfYs(); } intvec v = leadexp(g); int d = 0; for (int i=1; i<=s; i++) { d = d+v[i]; } return (d); } /*** * normalizes g such that LT_>(g)=Y^\alpha for some \alpha\in\NN^n. **/ static proc normalizeInY(vector g, graalBearer Gr, list #) { def origin = basering; int s; if (size(#)>0 && typeof(#[1])=="int") { s = #[1]; } else { s = numberOfYs(); } // get the coefficient before Y in the leading term // first isolate the first non-zero component and computes its degree in Y poly cg; for (int i = 1; i<=nrows(g); i++) { if (g[i]!=0) { cg = g[i]; break; } } int d = yDeg(cg,s); // next, sum all terms with the same degree in Y poly c = cg[1]; for (i = 2; i<=size(g); i++) { if (yDeg(cg[i],s)==d) { c = c+cg[i]; } } // and substitute all Y with 1 for (i=1; i<=s; i++) { c = subst(c,var(i),1); } def Q0 = Gr.Q0; setring Q0; ideal J0 = Gr.J0; ideal J0withC = imap(origin,c), J0; list L = division(1,J0withC); ASSUME(1,L[2]==0); poly a = L[1][1,1]; kill J0; kill J0withC; kill L; setring origin; poly a = imap(Q0,a); ideal scriptI = Gr.scriptI; g = reduce(a*g,scriptI); return (a,g); } /*** * removes all zero columns in matrix(G), * and removes the corresponding columns in Q, if they exist. **/ static proc removeZeroColumns(module G, matrix Q) { ASSUME(1,ncols(G)>ncols(Q)); module Gprime; matrix Qprime[nrows(Q)][ncols(Q)]; int newSizeG = 0; int newSizeQ = 0; for (int i=1; i<=ncols(G); i++) { if (G[i]!=0) { newSizeG++; Gprime[newSizeG] = G[i]; if (i<=ncols(Q)) { newSizeQ++; Qprime[1..nrows(Q),newSizeQ] = Q[1..nrows(Q),i]; } } } matrix QQprime[nrows(Q)][newSizeQ] = Qprime[1..nrows(Q),1..newSizeQ]; return (Gprime,QQprime); } proc warkedPreimageStd(warkedModule wM) " USAGE: warkedPreimageStd(wM); M warkedModule RETURN: given wM consisting of: - wM.Gr a graalBearer containing all relevant global structures - wM.modQ0y generating set G of a module M over Q0y - wM.stdmodQ0y empty - wM.qQ0y empty - wM.modKy corresponding generating set H of M_in over Ky - wM.stdmodKy empty - wM.qKy empty - wM.w weights on M returns the same warkedModule, except following differences: - wM.stdmodQ0y contains a subset G such that for any standard basis L of the kernel G + L is a standard basis of modQ0y + kernel - wM.qQ0y contains a transformation matrix such that stdmodAy = QAy*modQ0y - wM.stdmodKy contains a standardbasis of modKy - wM.qKy contains a transformation matrix such that stdmodKy = QKy*modKy NOTE: the standard basis of modAy is computed by lifting a corresponding Groebner basis of modKy EXAMPLE: example warkedPreimageStd; shows an example " { ASSUME(1,checkCorrespondence(wM)); graalBearer Gr = wM.Gr; // intvec w = wM.w; def Ky = Gr.Ky; setring Ky; module H = wM.modKy; /* add generators of the kernel to H */ int l = ncols(H); int k = nrows(H); int i,j; ideal scriptIin = Gr.scriptIin; H = H+freemodule(k)*scriptIin; /* compute a standard basis of H * and a corresponding transformation matrix */ matrix Qdash; module Hdash = liftstd(H,Qdash); /* drop factors before elements of scriptIin * and single out all elements of Hdash * whose leading monomial does not lie in scriptIin */ matrix QQ[l][size(Hdash)]; int ncolsQQ = 0; module redLHdash = reduce(lead(Hdash),lead(scriptIin)); for (i=1; i<=size(Hdash); i++) { if (redLHdash[i] != 0) { ncolsQQ++; QQ[1..l,ncolsQQ] = Qdash[1..l,i]; } } matrix Q[l][ncolsQQ] = QQ[1..l,1..ncolsQQ]; wM.qKy = Q; wM.stdmodKy = Hdash; def Q0y = Gr.Q0y; setring Q0y; module G = wM.modQ0y; matrix Q = imap(Ky,Q); ideal scriptI = Gr.scriptI; module Gdash = reduce(matrix(G)*Q,scriptI); poly a; for (i=1; i<=size(Gdash); i++) { a,Gdash[i] = normalizeInY(Gdash[i],Gr); Q[1..l,i] = a*Q[1..l,i]; } ASSUME(1,isStandardBases(Gdash)); Gdash = Gdash + freemodule(k)*scriptI; Gdash = simplify(Gdash,32); Gdash,Q = removeZeroColumns(Gdash,Q); wM.qQ0y = Q; wM.stdmodQ0y = Gdash; return(wM); } example { "EXAMPLE:"; echo = 2; ring Q = 0,(x,y,z),dp; ideal H = y2-xz; qring A = std(H); ideal L = x3-yz,x2y-z2; graalBearer Gr = graalMixed(L); def Q0y = Gr.Q0y; setring Q0y; module M = (Y(1)*y+y^2-1)*gen(1)+(Y(2)*z+z^2-1)*gen(2), Y(1)*y*gen(1)+Y(2)*z*gen(2); /* This is M: */ print(matrix(M)); intvec w = 1,1,1; warkedModule wM; wM.Gr = Gr; wM.modQ0y = M; wM.w = w; def Ky = Gr.Ky; setring Ky; module Min = (y^2-1)*gen(1)+(z^2-1)*gen(2),Y(1)*y*gen(1)+Y(2)*z*gen(2); /* This is M_in: */ print(matrix(Min)); wM.modKy = Min; /* warkedPreimageStd yields the same standard basis as std: */ warkedModule wN = warkedPreimageStd(wM); wN; setring Q0y; module stdM = std(M); print(matrix(stdM)); } proc markedResolution_print(markedResolution mr) { graalBearer Gr = mr.Gr; "resolution over Al:"; def Al = Gr.Al; setring Al; resolution resAl = mr.resAl; resAl; for (int i=1; i<=ressize(resAl); i++) { "k="+string(i); print(module(resAl[i])); ""; } "resolution over Graal:"; def Graal = Gr.Graal; setring Graal; resolution resGraal = mr.resGraal; resGraal; for (i=1; i<=ressize(resGraal); i++) { "k="+string(i); print(module(resGraal[i])); ""; } } /*** * returns the size of a resolution. **/ static proc ressize(resolution res) { for (int i=1; i<=size(res); i++) { if (res[i]==0) { return (i-1); } } return (size(res)); } /*** * given rh consisting of: * - rh.Gr a graalBearer containing all relevant global structures * - rh.idealAl a standard basis of an ideal I in Al * - rh.resAl a resolution with only a single entry, * generators of I corresponding to the generators of inI * - rh.resGraal a resolution of inI, the initial ideal inI of I over Graal * - rh.weights an empty list of weights for the modules in resAl * liftRes lifts the given resolution of inI to a resolution of I **/ static proc liftRes(markedResolution rh) { graalBearer Gr = rh.Gr; /* before anything initiate a list with the generators of I for the resolution over Al and read out the resolution over Graal */ def Al = Gr.Al; setring Al; ideal I = rh.idealAl; list resAl = I; def Graal = Gr.Graal; setring Graal; resolution resGraal = rh.resGraal; int k = ressize(resGraal); ideal inI = resGraal[1]; /* before lifting the first segment of the resolution, find suitable preimages of the generators of I and inI */ int i = 1; def Ky = Gr.Ky; setring Ky; ideal scriptIin = Gr.scriptIin; ASSUME(1,reduce(std(scriptIin),scriptIin)==0); // check whether it is standard basis attrib(scriptIin,"isSB",1); // and set corresponding flag to 1 ideal H(i) = imap(Graal,inI); ASSUME(1,lead(H(i))==lead(reduce(H(i),scriptIin))); // H(i) should already be in reduced form, // since inI was a standard basis def Q0y = Gr.Q0y; setring Q0y; ideal scriptI = Gr.scriptI; ASSUME(1,reduce(std(scriptI),scriptI)==0); // check whether it is standard basis attrib(scriptI,"isSB",1); // and set corresponding flag to 1 ideal G(i) = imap(Al,I); ASSUME(1,lead(G(i))==lead(reduce(G(i),scriptI))); // G(i) should already be in reduced form, // since I was a standard basis /* lifting the first segment of the resolution, * i.e. syzygies of the generators Theta of inI to * syzygies of the generators Delta of I */ /* note that I already is already in standard bases form, * which is why G(i)+scriptI is a standard bases */ /* next, we need a standard basis of the preimage of I */ setring Q0y; ideal Gdash(i) = G(i) + scriptI; ASSUME(2,isStandardBasis(Gdash(i))); attrib(Gdash(i),"isSB",1); matrix Q(i)[size(G(i))][size(Gdash(i))]; for (int j=1; j<=size(G(i)); j++) { Q(i)[j,j]=1; } for (i=2; i<=k; i++) { setring Graal; module syzTheta = resGraal[i]; // pick homogeneous representatives of hs eta in syzTheta setring Ky; module H(i) = imap(Graal,syzTheta); H(i) = reduce(H(i),scriptIin); // lift them to gs in Q0y, substitute elements of G for the unit vectors // and reduce the result setring Q0y; module G(i) = imap(Ky,H(i)); module R = matrix(G(i-1))*matrix(G(i)); R = reduce(R,scriptI); // compute a standard representation of the remainder // with respect to G' list L = division(R,Gdash(i-1)); matrix D = L[1]; ASSUME(1,L[2]==0); ASSUME(1,isDiagonalMatrixOfOnes(L[3])); // correct the gs by our result matrix QD = Q(i-1)*D; G(i) = module(matrix(G(i))-QD); setring Al; resAl[i] = imap(Q0y,G(i)); // extend it to standard basis GDash(i) // and transformation matrix for next step warkedModule wM; wM.Gr = Gr; setring Ky; wM.modKy = H(i); setring Q0y; wM.modQ0y = G(i); wM = warkedPreimageStd(wM); matrix Q(i) = wM.qQ0y; module Gdash(i) = wM.modQ0y; // cleanup setring Graal; kill syzTheta; setring Q0y; kill R; kill L; kill D; kill QD; } setring Al; rh.resAl = resolution(resAl); return(rh); } /*** * Given two ideals with the same generators modulo ordering * returns an intvec that respresents a permutation of the generators **/ static proc getPermutation(ideal I1, ideal I2) { ASSUME(1,size(I1)==size(I2)); int i,j; intvec perm; for (i=1; i<=size(I1); i++) { for (j=1; j<=size(I2); j++) { if (I1[i]==I2[j]) { perm[i] = j; } } } for (i=1; i<=size(perm); i++) { ASSUME(1,perm[i]>0); } return(perm); } /*** * Given an intvec representing a permutation, * permutes the generators of the ideal. **/ static proc permuteGenerators(ideal I, intvec perm) { ASSUME(1,size(I)==size(perm)); ideal J; for (int i=1; i<=size(perm); i++) { J[i]=I[perm[i]]; } return (J); } proc resolutionInLocalization(ideal I, def L) " USAGE: resolutionInLocalization(I,L); I ideal, L ideal or graalBearer RETURN: the resolution of I*A_L, where A_L is the localization of the current basering (possibly a quotient ring) at a prime ideal L. EXAMPLE: example resolutionInLocalization; shows an example " { if (typeof(L)=="ideal") { graalBearer Gr = graalMixed(L); return(resolutionInLocalization(I,Gr)); } if (typeof(L)=="graalBearer") { graalBearer Gr = L; def origin = basering; def Al = Gr.Al; setring Al; ideal I = imap(origin,I); I = std(I); int s = Gr.s; markedResolution mr; mr.idealAl = I; ideal inI = yinitial(I,s); def Graal = Gr.Graal; setring Graal; ideal inI = Gr.ina(inI); ASSUME(1,isStandardBasis(inI)); attrib(inI,"isSB",1); resolution resInI = res(inI,0); resInI = minres(resInI); mr.Gr = Gr; mr.resGraal = resInI; ideal inJ = resInI[1]; intvec perm = getPermutation(inI,inJ); setring Al; mr.idealAl = permuteGenerators(I,perm); mr = liftRes(mr); return(mr); } ERROR("resolutionInLocalization: unexpected parameters"); return(0); } example { "EXAMPLE:"; echo = 2; ring Q = 0,(x,y,z,w),dp; ideal circle = (x-1)^2+y^2-3,z; ideal twistedCubic = xz-y2,yw-z2,xw-yz,z; ideal I = std(intersect(circle,twistedCubic)); // the resolution is more complicated due to the twisted cubic res(I,0); // however if we localize outside of the twisted cubic, // it should become very easy again. ideal L = std(I+ideal(x-1)); graalBearer Gr = graalMixed(L); Gr; markedResolution mr = resolutionInLocalization(I,Gr); mr; } /*** * debug code **/ static proc isConstantUnit(poly p) { return(cleardenom(p)==1); } static proc isConstantMultiple(vector v, vector w) { module M = v,w; M = simplify(M,8); if (M[2]!=0) { return(0); } return(1); } static proc checkColumnsUpToUnits(matrix M, matrix N) { if ((ncols(M)!=ncols(N)) && (nrows(M)!=nrows(N))) { return(0); } if (nrows(M)==0) { return(1); } int i,j; vector v,w; poly p,q; for (i=ncols(M); i>0; i--) { v = M[i]; w = N[i]; if (!isConstantMultiple(v,w)) { return(0); } } return(1); } /*** * returns 1, if wM.modAy and wM.modKy correspond to each other * and wm.stdmodAy and wm.stdmodKy correspond to each other. * returns 0 otherwise. **/ static proc checkCorrespondence(warkedModule wM) { return (1); graalBearer Gr = wM.Gr; intvec w = wM.w; def Ky = Gr.Ky; setring Ky; map Q0yToKy = Gr.Q0yToKy; def Q0y = Gr.Q0y; setring Q0y; module G1 = wM.modQ0y; if (G1 != 0) { G1 = vectorInitial(G1,w); setring Ky; module H10 = wM.modKy; if (H10 != 0) { module H11 = Q0yToKy(G1); if (matrix(H10)!=matrix(H11)) { return(0); } } setring Q0y; } module G2 = wM.stdmodQ0y; if (G2 != 0) { G2 = vectorInitial(G2,w); setring Ky; module H20 = wM.stdmodKy; if (H20 != 0) { module H21 = Q0yToKy(G2); if (matrix(H20)!=matrix(H21)) { return(0); } } } return(1); } /*** * checks whether U is a diagonal matrix consisting of 1's **/ static proc isDiagonalMatrixOfOnes(matrix U) { if (nrows(U)!=ncols(U)) { return(0); } int j,j; for (i=1; i<=nrows(U); i++) { for (j=1; j<=ncols(U); j++) { if (i==j && U[i,j]!=number(1)) { return(0); } if (i!=j && U[i,j]!=number(0)) { return(0); } } } return(1); } /*** * returns 1 if I is a standard basis, returns 0 otherwise, **/ static proc isStandardBasis(ideal I) { ideal LI = lead(std(I)); attrib(LI,"isSB",1); ideal LII = lead(I); attrib(LII,"isSB",1); /* checks whether lead(I) generates the leading ideal */ if (simplify(reduce(LI,LII),2)!=0) { ERROR("isStandardBasis: input ideal no standard basis!"); return(0); } /* the following case should never happen mathematically, * left the check for sake of completeness */ if (simplify(reduce(LII,LI),2)!=0) { ERROR("isStandardBasis: input ideal no standard basis!"); return(0); } return(1); } singular-4.0.3+ds/Singular/LIB/gradedModules.lib000066400000000000000000006150541266270727000214310ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////// version="version gradedModules.lib 4.0.1.1 Jan_2015 "; // $Id: e400e25eb0c8c5acc597207025d0a22e1143469d $ category="Commutative Algebra"; info=" LIBRARY: gradedModules.lib Operations with graded modules/matrices/resolutions AUTHORS: Oleksandr Motsak , where U=motsak, D=mathematik.uni-kl.de @* Hanieh Keneshlou KEYWORDS: graded modules, graded homomorphisms, syzygies OVERVIEW: The library contains several procedures for constructing and manipulating graded modules/matrices/resolutions. Basics about graded objects can be found in [DL]. Throughout this library graded objects are graded maps, that is, matrices with polynomials, together with grading weights for source and destination. Graded modules are implicitly given as coker of a graded map. Note that in special cases we may also consider submodules in S^r generated by columns of a graded polynomial matrix (or a graded map). NOTE: set assumeLevel to positive integer value in order to auto-check all assumptions. We denote the current basering by S. REFERENCES: [DL] Decker, W., Lossen, Ch.: Computing in Algebraic Geometry, Springer, 2006 PROCEDURES: grobj(M,w[,d]) construct a graded object (map) given by matrix M grtest(A) check whether A is a valid graded object grdeg(M) compute graded degrees of columns of the map M grview(M) view the graded structure of map M grshift(M,d) shift graded module coker(M) by +d grzero() presentation of S(0)^1 grtwist(r,d) presentation of S(d)^r grtwists(v) presentation of S(v[1])+...+S(v[size(v)]) grsum(M,N) direct sum of two graded modules coker(M) + coker(N) grpower(M,p) direct p-th power of graded module coker(M) grtranspose(M) un-ordered graded transpose of map M grgens(M) try to compute submodule generators of coker(M) grpres(F) presentation of submodule generated by columns of F grorder(M) reorder cols/rows of M for correct graded-block-structure grtranspose1(M) reordered graded transpose of map M TestGRRes(n,I) compute/order/transpose a graded resolution of ideal I KeneshlouMatrixPresentation(v) build some presentation with intvec v grsyz(M) syzygy of Im(M) grres(M,l[,m]) resolution of Im(M) of length l... minimal? grlift(A,B) graded lift, gens! grprod(A,B) composition of graded maps (product of matrices?) grgroebner(M) Groebner Basis of Im(M) as a graded object grconcat(M,N) sum of maps into the same target module grrndmat(s,d[,p,b]) generate random matrix compatible with src and dst gradings grrndmap(S,D[,p,b]) generate random 0-deg homomorphism src(S) -> src(D) grrndmap2(S,D[,p,b]) generate random 0-deg homomorphism dst(S) -> dst(D) grlifting(A,B) RND! chain lifting grlifting2(A,B) RND! chain lifting mappingcone(M,N) mapping cone? grlifting3(A,B) RND! chain lifting? probably wrong one mappingcone3(A,B) mapping cone3? grrange(M) get the row-weightings grneg(A) graded object given by -A matrixpres(a) matrix presentation of direct sum of Omega^{a[i]}(i) "; // grisequal(A,B) check whether A is exactly eqal to B? TODO: isomorphic! LIB "matrix.lib"; // ? ////////////////////////////////////////////////////////////////////////////////////////////////////////// // . view graded module/map // . reorder graded resolution // . transpose graded module/map? // draw helpers static proc repeat(int n, string c) { string r = ""; while( n > 0 ){ r = r + c; n--; } return(r); } static proc pad(int m, string s, string c){ string r = s; while( size(r) < m ){ r = c + r; } return(r); } static proc mstring( int m, string c){ if( m < 0 ) { return (c); }; return (string(m)); } static proc grsumstr(string R, intvec v) "direct sum_i=1^size R(-v[i]), for source and targets of graded objects" { int n = size(v); if (n == 0) { return ("0"); } ASSUME(0, n > 0 ); if (R == "") { R = nameof(basering); } ASSUME(0, defined(R) && (R != "") ); v = -v; // NOTE: due to Mathematical meanings of Singular data int lst = v[1]; int cnt = 1; string p = R; if( lst != 0 ) { p = p + "(" + string(lst) + ")"; } int k, d; for (k = 2; k <= n; k++ ) { d = v[k]; if( d == lst ) { cnt = cnt + 1; } else { if (cnt > 1){ p = p + "^" + string(cnt); } cnt = 1; lst = d; p = p + " + " + R; if( lst != 0 ) { p = p + "(" + string(lst) + ")"; } } } if (cnt > 1){ p = p + "^" + string(cnt); } return (p); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; def E = grtwist(2, 0); def v = grrange(E); // grdeg(E); grsumstr("", v ); } // view helper static proc draw ( intmat D, int d ) { // print(D); return (); int nc = ncols(D); int nr = nrows(D); int s, r, c; int max = 0; // get maximum string-length among all {D[r,c]} for (r = nr; r > 0; r-- ) { for (c = nc; c > 0; c-- ) { s = size( string(D[r, c]) ); if( max < s ) { max = s; } } } max = max + 1; string head = ""; string foot = ""; string middle = ""; for ( c = d+1; c < (nc-d); c++ ) { head = head + pad(max, string(D[1 , c]), ".") + " "; foot = foot + pad(max, string(D[nr, c]), " ") + " "; } // last head/foot enties: head = head + pad(max, string(D[1 , c]), "."); foot = foot + pad(max, string(D[nr, c]), " "); // head/foot dash lines: string dash = "-"; string dash2 = "="; dash = repeat( (nc - 2*d) - 1 , repeat(max, dash) + " " ) + repeat(max, dash) + " "; // dash = repeat( (max + 1) * (nc - 2*d) , dash ); dash2 = repeat( (nc - 2*d) - 1 , repeat(max, dash2) + " " ) + repeat(max, dash2) + " "; // dash2 = repeat( (max + 1) * (nc - 2*d) , dash2); for ( r = d+1; r <= (nr-d); r++ ) { middle = middle + pad(max, string(D[r,1]), " ") + " :"; for ( c = d+1; c < (nc-d); c++ ) { middle = middle + pad(max, mstring(D[r,c], "-"), " ") + " "; } middle = middle + pad(max, mstring(D[r,nc-d], "-"), " ") + " |" + pad(max, string(D[r,nc]), ".") + newline; } string corner_id = repeat(max, "."); string corner = repeat(max, " "); // print everything all at once: print ( corner + " " + head + " ." + corner_id + newline + corner + " " + dash + "+" + corner_id + newline + middle + corner + " " + dash2 + " " + corner + newline + corner + " " + foot + " " + corner ); } proc grview(N) "USAGE: grview(M), graded object M RETURN: nothing PURPOSE: print the degree/grading data about the GRADED matrix/module/ideal/mapping object M ASSUME: M must be graded EXAMPLE: example grview; shows an example " { // if( size(N) == 0 ) { return (); } string msg = "Graded"; string lst; string arrow = " <- "; string R = nameof(basering); if( typeof( N ) == "list" ) // TODO: find a better DS for graded resolutions / chain map !? { int n = size(N); ASSUME(0, n > 0); string msg1 = ""; if( size(R) >= 2 ) { msg1 = msg1 + "(let R:="+R+")"; R = "R"; // !!! } msg1 = msg1 + ": " ; list arr; arr[n] = list(); int exact = (1==1); int i = 1; ASSUME(1, grtest(N[i])); string dst = grsumstr(R, grrange(N[i])); string src = grsumstr(R, grdeg(N[i])); arr[i] = list(dst, src); i = i + 1; while( i <= n ) { ASSUME(1, grtest(N[i])); dst = grsumstr(R, grrange(N[i])); if( exact && (src != dst) ) { // "src: [" + src+ "] != [" + dst + "] :(!!"; exact = (1==0); } src = grsumstr(R, grdeg(N[i])); arr[i] = list(dst, src); i = i + 1; }; string o = ""; if( exact ) { // complex? msg = msg + " resolution" + msg1; o = "d"; for( i = 1; i <= n; i++ ) { msg = msg + newline + arr[i][1] + " <-- "+o+"_" + string(i) + " --"; }; msg = msg + newline + arr[n][2]; msg = msg + ", given by maps: "; } else { // print(arr); msg = msg + "-object collection"; o = "o"; // for( i = 1; i <= n; i++ ) // { // msg = msg + newline + arr[i][1] + " <-- "+o+"_" + string(i) + " -- " + arr[i][2]; // }; msg = msg + ", given by the following maps (named here as "+o+"_[1 .. "+string(n)+"]): "; } print(msg); for( i = 1; i <= size(N); i++ ) { print( o+"_" + string(i) + " :" ); grview( N[i] ); }; return (); } // typeof( N ) ; attrib( N ); grrange(N); ASSUME(1, grtest(N) ); msg = msg + " homomorphism"; if( size(R) >= 2 ) { msg = msg + "(let R:="+R+")" ; R = "R"; } msg = msg + ": "; intvec gr = grrange(N); // grading weights? string dst = grsumstr(R, gr); intvec G = grdeg(N); string src = grsumstr(R, G); if( ncols(N) == 0 ) { src = "0"; } lst = msg; if( (size(lst) + size(dst) + size(src) + 4) > 80 ) { if( (size(lst) + size(dst)) > 80 ) { msg = msg + newline; lst = ""; } msg = msg + dst + arrow; lst = lst + dst + arrow; if( (size(lst) + size(src)) > 80 ) { msg = msg + newline; lst = ""; } msg = msg + src; lst = lst + src; } else { msg = msg + dst + arrow + src; lst = lst + dst + arrow + src; } if( size(lst) > 70 ) { msg = msg + newline; } // lst = ""; msg = msg + ", given by "; // lst = lst + ", given by "; int nc = ncols(N); int nr = nrows(N); if( size(N) == 0 ) { msg = msg + "zero ("+ string(nr); if( nr == nc ) { msg = msg + "^2"; } else { msg = msg + " x " + string(nc); } print( msg+") matrix." ); } else { ASSUME(0, nc > 0); matrix M = module(N); int r,c; int d = 1; // number of extra cols/rows for extra info around the central degree(N) block in D intmat D[nr+2*d][nc+2*d]; for( c = nc; c > 0; c-- ) { D[1, c+d] = c; // top row indeces D[nr+2*d, c+d] = G[c]; // deg(v) + gr[ leadexp(v)[m] ]; // bottom row with computed column induced degrees } for( r = nr; r > 0; r-- ) { D[r+d, 1] = gr[r]; // left-most column with grading data for( c = nc; c > 0; c-- ) { D[r+d, c+d] = deg(M[r, c]); // central block with degrees (-1 means zero entry) } D[r+d, nc+2*d] = r; // right-most block with indeces } if( nr == nc) // square matrix // detect diagonal? { for (c = nr; c > 0; c-- ) { M[c,c] = 0; } if( size(module(M)) == 0 ) { msg = msg + "a diagonal matrix"; } else { msg = msg + "a square matrix"; } } else { msg = msg + "a matrix"; } print(msg + ", with degrees: " ); draw(D, d); // print it nicely! } } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module A = grobj( module([x+y, x, 0, 0], [0, x+y, y, 0]), intvec(0,0,0,1) ); grview(A); module B = grobj( module([0,x,y]), intvec(15,1,1) ); grview(B); module D = grsum( grsum(grpower(A,2), grtwist(1,1)), grsum(grtwist(1,2), grpower(B,2)) ); grview(D); ring R = 0,(w,x,y,z), dp; def I = grobj( ideal(y2-xz, xy-wz, x2z-wyz), intvec(0) ); list res1 = grres(I, 0); // non-minimal grview(res1); print(betti(res1,0), "betti"); list res2 = grres(grshift(I, -10), 0, 1); // minimal! grview(res2); print(betti(res2,0), "betti"); } static proc issorted( intvec g, int s ) { g = s * g; // "g: ", g; int i = size(g); for(; i > 1; i--) { if( (g[i] - g[i-1]) < 0 ) { return (0); } } return (1); } static proc mysort( intvec gr, int s ) " computes the permutation P of gr, such that (s*gr)[P] is ascendingly sorted NOTE: looks like a bubble sort (was taken from sort) and modified to ensure stability! TODO: replace with some kernel function if this turns out to be inefficient!! " { gr = s * gr; int m = size(gr); intvec pivot; int Bi; // compute reordering permutation pivot such that gr[pivot] is (stably) sorted for(Bi=m; Bi>0; Bi--) { pivot[Bi]=Bi; } // pivot = Id_m for starters int Bn,Bb; int P, D; int Bj = 0; int flag = 0; // Bi == 0 while(Bj==0) { Bi++; Bj=1; for(Bn=1; Bn <= (m-Bi); Bn++) { D = (gr[pivot[Bn]] - gr[pivot[Bn+1]]); // sort gr P = (D > 0) or ( (D == 0) && ((pivot[Bn]-pivot[Bn+1]) > 0) ); // stability!? if(P) { Bb=pivot[Bn]; pivot[Bn]=pivot[Bn+1]; pivot[Bn+1]=Bb; Bj=0; flag = 1; } } } ASSUME(1, issorted(intvec(gr[pivot]), 1)); return (pivot); } proc grdeg(M) "USAGE: grdeg(M), graded object M RETURN: intvec of degrees PURPOSE: graded degrees of columns (generators) of M, describing the source of M ASSUME: M must be a graded object (matrix/module/ideal/mapping) NOTE: if M has zero cols it shoud have attrib(M,'degHomog') set. EXAMPLE: example grdeg; shows an example " { ASSUME(1, grtest(M) ); if ( typeof(attrib(M, "degHomog")) == "intvec" ) { def t = attrib(M, "degHomog"); // graded degrees if( size(t) == 0 ){ return (t); } // ZERO! ASSUME(2, ncols(M) == size(t) ); return (t); } if( ncols(M) == 0 ) { return (0:0); } // FIXME: Why??? ASSUME(0, ncols(M) > 0); ASSUME(0, ncols(M) == size(M) ); def w = grrange(M); // grading weights? if( size(M) == 0 ){ return (w); } // TODO: Q@Wolfram!??? int m = ncols(M); // m > 0 in Singular! int n = nvars(basering) + 1; // index of mod. column in the leadexp module L = lead(M[1..m]); // leading module-terms for input column vectors intvec d = deg(L[1..m]); // their degrees intvec c = leadexp(L[1..m])[n]; // their module-components // w = intvec(-6665), w; // 0????? intvec gr = w[c]; // + 1]; // weights????? gr = gr + d; // finally we compute their graded degrees return (gr); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module A = grobj( module([x+y, x, 0, 0], [0, x+y, y, 0]), intvec(0,0,0,1) ); grview(A); module B = grobj( module([0,x,y]), intvec(15,1,1) ); grview(B); module D = grsum( grsum(grpower(A,2), grtwist(1,1)), grsum(grtwist(1,2), grpower(B,2)) ); grview(D); grdeg(D); def D10 = grshift(D, 10); grview(D10); grdeg(D10); } static proc reorder(def M, int s) " Reorder gens of M: compute graded degrees and the permutation to sort them " { // input should be graded: ASSUME(1, grtest(M) ); intvec w = grrange(M); // grading weights intvec gr = grdeg( M ); // intvec d = deg(M[1..nocls(M)]); // no need to deal with un-weighted degrees??! intvec pivot = mysort(gr, s); // grades & ordering permutation for N. gr[pivot] should be sorted! ASSUME(1, issorted(gr[pivot], s)); module N = grobj(module(M[pivot]), w, intvec(gr[pivot])); // reorder the starting ideal/module // "reorder: "; grview(N); return (N, intvec(gr[pivot])); } proc grtranspose1(def M) "USAGE: grtranspose1(M), graded object or list M RETURN: same as input PURPOSE: graded transpose of graded object or chain complex M ASSUME: M must be a graded object or a list of graded objects EXAMPLE: example grtranspose1; shows an example " { if( typeof( M ) == "list" ) { if( size(M) == 0 ) { return (); } int j = size(M); int i = 1; // TODO: extra grading argument??? while( i < j ) { if( size(M[i]) == 0 ){ break; } ASSUME(0, typeof(grrange(M[i])) == "intvec"); i++; } if( size(M[i]) == 0 ) { i--; } j = i; i = 1; list L; while( j > 0 ) { // grview(M[i]); L[j] = grtranspose1( grobj( M[i], grrange(M[i])) ); // grview(L[j]); if( (i > 1) && (j > 0) ) { // grview(L[j+1]); ASSUME(2, size( module( matrix(L[j])*matrix(L[j+1]) ) ) == 0 ); }; // grview(L[j]); j--; i++; }; return (L); // ? } ////// // "a"; grview(M); ASSUME(1, grtest(M) ); intvec d; module N; (N,d) = reorder(M, -1); kill M; module M = grobj(transpose(N), -d, -grrange(N)); // "b"; grview(M); kill N,d; module N; intvec d; // reverse order: (N,d) = reorder(M, 1); kill M; // "e"; grview( N ); ASSUME(1, issorted( grrange(N), 1) ); ASSUME(1, issorted(grdeg(N), 1) ); return (N); } example { "EXAMPLE:"; echo = 2; "Surface Name: 'k3.d10.g9.quart2' in P^4"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp; ideal J = x3yz2+31/15x2y2z2-7231xy3z2+99/37y4z2+28/95x3z3+97/32x2yz3+13247xy2z3+12717y3z3-113/31x2z4-61/30xyz4-6844y2z4+104/3xz5-13849yz5+43/39z6+13061x3yzu-8463x2y2zu+94/69xy3zu-8/61y4zu-13297x3z2u+7217x2yz2u-7830xy2z2u-75/14y3z2u+2839x2z3u-14657xyz3u-52/7y2z3u-6/89xz4u-6169yz4u+44/7z5u-98/33x3yu2+41/30x2y2u2-65/98xy3u2+122/13y4u2+9906x3zu2-11587x2yzu2+17/53xy2zu2+6504y3zu2+49/106x2z2u2+11480xyz2u2+97/71y2z2u2+12560xz3u2-114/83yz3u2-13761z4u2-67/112x3u3-18/49x2yu3+21/67xy2u3-44/43y3u3+123/116x2zu3+4459xyzu3-13841y2zu3-805xz2u3-1382yz2u3-5293z3u3+133x2u4-122/79xyu4+9724y2u4+61/24xzu4+113/119yzu4-19/108z2u4+15893xu5+57/22yu5+4600zu5-618u6-27/53x3yzv+44/103x2y2zv-142xy3zv+19/84y4zv+105/8x3z2v+10532x2yz2v-75/74xy2z2v-70/19y3z2v+31/80x2z3v-481xyz3v+47/30y2z3v+14318xz4v+51/28yz4v-15/113z5v-46/17x3yuv-99/100x2y2uv-106/5xy3uv+14384y4uv+7/100x3zuv-15/64x2yzuv-6976xy2zuv+12051y3zuv-67/42x2z2uv-2627xyz2uv-49/104y2z2uv+77/16xz3uv+15766yz3uv+85/117z4uv-107/101x3u2v-6699x2yu2v+2443xy2u2v-27/28y3u2v+11945x2zu2v-14467xyzu2v-4873y2zu2v-63/124xz2u2v-8270yz2u2v+11900z3u2v+47/14x2u3v+53/8xyu3v-10/51y2u3v-87/119xzu3v+114/73yzu3v+86/57z2u3v+52/63xu4v-11587yu4v+1/18zu4v-121/109u5v+116/11x3yv2+19/108x2y2v2-31/3xy3v2-43/9y4v2-81/100x3zv2-7728x2yzv2-1037xy2zv2+24/101y3zv2-61/103x2z2v2-8/51xyz2v2+117/109y2z2v2+98/23xz3v2+1646yz3v2-3356z4v2+105/59x3uv2+117/31x2yuv2+519xy2uv2+12633y3uv2+25/6x2zuv2-963xyzuv2-49/23y2zuv2-116/25xz2uv2+14146yz2uv2+11480z3uv2-95/8x2u2v2-10928xyu2v2-51/23y2u2v2-12770xzu2v2-92/91yzu2v2+3872z2u2v2+3183xu3v2+6871yu3v2+90/37zu3v2+10019u4v2-69/88x3v3-1398x2yv3-97/72xy2v3-46/97y3v3+107/14x2zv3-20/89xyzv3-11367y2zv3+120/29xz2v3-86/81yz2v3+107/69z3v3-39/17x2uv3+83/11xyuv3+169y2uv3-11/71xzuv3-22/17yzuv3-14862z2uv3-13009xu2v3-101/12yu2v3+10617zu2v3+2567u3v3-23/85x2v4+27/50xyv4+113/51y2v4+97/16xzv4+4438yzv4-11857z2v4+14580xuv4-6426yuv4+9421zuv4-10585u2v4+14670xv5+1807yv5+10298zv5-116/53uv5+7869v6,x3yzu+31/15x2y2zu-7231xy3zu+99/37y4zu+28/95x3z2u+97/32x2yz2u+13247xy2z2u+12717y3z2u-113/31x2z3u-61/30xyz3u-6844y2z3u+104/3xz4u-13849yz4u+43/39z5u-124/43x3yu2-90/13x2y2u2-13244xy3u2-78/73y4u2+118/43x3zu2+37/67x2yzu2-10426xy2zu2+2412y3zu2-32/113x2z2u2+35/104xyz2u2+3952y2z2u2+9028xz3u2-1990yz3u2-59/109z4u2+15499x3u3+116/23x2yu3+95/58xy2u3+8/47y3u3+59/109x2zu3-29xyzu3+12412y2zu3+20/81xz2u3+2200yz2u3-13809z3u3+3889x2u4-8136xyu4+8922y2u4-4/121xzu4+82/113yzu4-65/23z2u4+101/53xu5+103/113yu5-99/118zu5-9524u6-2749x3yzv-7814x2y2zv+73/113xy3zv+9937y4zv-59/62x3z2v-23/12x2yz2v-10245xy2z2v+7130y3z2v-4427x2z3v+6656xyz3v+3448y2z3v-46/79xz4v+1611yz4v+8453z5v+12013x3yuv+49/17x2y2uv-4/115xy3uv-121/91y4uv-63/29x3zuv+64/7x2yzuv-8785xy2zuv-87/14y3zuv+36/121x2z2uv+9525xyz2uv+4215y2z2uv-17/13xz3uv-117/125yz3uv+101/122z4uv+42/37x3u2v-8747x2yu2v-105/79xy2u2v+10799y3u2v-58/49x2zu2v-8/75xyzu2v-67/49y2zu2v-38/11xz2u2v+53/27yz2u2v+113/52z3u2v+18/59x2u3v+71/106xyu3v+47/2y2u3v-4594xzu3v+95/4yzu3v-121/46z2u3v-55/62xu4v-101/72yu4v+40/53zu4v+15227u5v-15553x3yv2+29/94x2y2v2-4076xy3v2-7133y4v2+27/125x3zv2+33/29x2yzv2-63/95xy2zv2+9166y3zv2-480x2z2v2+9941xyz2v2+107/46y2z2v2+13018xz3v2+53/98yz3v2+92/35z4v2+17/30x3uv2+77/95x2yuv2+11/67xy2uv2+8262y3uv2+65/11x2zuv2+2567xyzuv2-33/94y2zuv2+85/92xz2uv2+103/25yz2uv2-27/100z3uv2+13210x2u2v2-109/90xyu2v2+141y2u2v2-124/51xzu2v2-3/109yzu2v2-4910z2u2v2+205xu3v2+14357yu3v2+85/57zu3v2-109/28u4v2-68/39x3v3+10545x2yv3-2176xy2v3-8743y3v3+15111x2zv3+25/119xyzv3+8/103y2zv3-6046xz2v3+8658yz2v3+106/5z3v3-31/126x2uv3-7762xyuv3+2315y2uv3+124/67xzuv3-77/104yzuv3+95/71z2uv3+69/119xu2v3+13069yu2v3-8620zu2v3+105/41u3v3-15772x2v4-11212xyv4-61/36y2v4+38/125xzv4-15860yzv4+8/63z2v4+7519xuv4-94/41yuv4+45/32zuv4+9417u2v4-71/35xv5-6287yv5+6481zv5+106/99uv5+3/41v6,-8036x3yu2+7966x2y2u2-151xy3u2-14/111y4u2-111/76x3zu2-102/11x2yzu2+7956xy2zu2-7397y3zu2-113/16x2z2u2-8049xyz2u2+7230y2z2u2+3978xz3u2-36/113yz3u2-8147z4u2-107/83x3u3+78/97x2yu3+12700xy2u3+11/72y3u3+88/31x2zu3-63/40xyzu3+101/35y2zu3-220xz2u3+3/103yz2u3-49/45z3u3-21/113x2u4+104/123xyu4+98/47y2u4-56/61xzu4-87/50yzu4+5913z2u4-120/17xu5+64/11yu5-109/80zu5+10371u6-118/25x3yzv+58/99x2y2zv-5/64xy3zv+7/46y4zv-49/103x3z2v-77/106x2yz2v-44/7xy2z2v-7559y3z2v-17/35x2z3v+948xyz3v-15043y2z3v-3576xz4v-2/109yz4v+74/11z5v+6436x3yuv+7316x2y2uv+29/5xy3uv-1326y4uv+34/49x3zuv-122/27x2yzuv-632xy2zuv+46/49y3zuv-13463x2z2uv-808xyz2uv-17/32y2z2uv-13149xz3uv-117/88yz3uv-45/79z4uv-65/94x3u2v+6/67x2yu2v+34/39xy2u2v-14026y3u2v+42/107x2zu2v-3287xyzu2v-70/43y2zu2v+29/104xz2u2v-47/18yz2u2v-11038z3u2v+6262x2u3v-5255xyu3v-7/10y2u3v+7065xzu3v+5608yzu3v+4675z2u3v-73/90xu4v-15822yu4v-71/63zu4v+110/97u5v-69/5x3yv2+4315x2y2v2-124/45xy3v2-79/16y4v2-10739x3zv2-93/46x2yzv2+12499xy2zv2-73/86y3zv2+6367x2z2v2-12876xyz2v2-306y2z2v2-89xz3v2-70/51yz3v2+13120z4v2+61/57x3uv2+14782x2yuv2-91/9xy2uv2-2625y3uv2+14747x2zuv2-5899xyzuv2-12944y2zuv2-47/14xz2uv2-4551yz2uv2-99/101z3uv2-12618x2u2v2+1507xyu2v2-11951y2u2v2+68/49xzu2v2+49/39yzu2v2-56/103z2u2v2-31/85xu3v2-32/49yu3v2-65/14zu3v2+15/7u4v2+5749x3v3-3667x2yv3-107/29xy2v3+11301y3v3+95/18x2zv3-121/74xyzv3+75/26y2zv3+101/98xz2v3-111/76yz2v3-11335z3v3-15923x2uv3-36/83xyuv3-4134y2uv3-87/118xzuv3-41/11yzuv3+104/61z2uv3+12583xu2v3-50/23yu2v3-31/44zu2v3-29/23u3v3+108/107x2v4-8216xyv4-5009y2v4+101/26xzv4-9779yzv4+71/74z2v4-3358xuv4+83/84yuv4-34/39zuv4+44/47u2v4-112/83xv5+113/74yv5+82/79zv5-115/99uv5+12/109v6,-x4y-31/15x3y2+7231x2y3-99/37xy4-28/95x4z-53/107x3yz-4623x2y2z+5300xy3z-41/111y4z+12205x3z2+113/120x2yz2+54/49xy2z2-85/63y3z2+104/89x2z3-52/121xyz3-22/49y2z3+14367xz4+71/93yz4+55/56z5-5/81x4u-67/81x3yu-83/13x2y2u+98/55xy3u+15289y4u-94/111x3zu+40/29x2yzu-16/59xy2zu-107/14y3zu+2965x2z2u-459xyz2u-2/47y2z2u+35/22xz3u+119/39yz3u-12180z4u-13679x3u2+1534x2yu2+11305xy2u2-62/9y3u2-68/39x2zu2+11/90xyzu2-36/101y2zu2-2896xz2u2-15114yz2u2-49/114z3u2+19/16x2u3-11401xyu3-109/3y2u3+67/80xzu3+53/92yzu3+2894z2u3+119/74xu4+407yu4-65/53zu4+95/94u5-9309x4v+21/40x3yv+1436x2y2v+2194xy3v+6994y4v-116/81x3zv+13/2x2yzv-12/13xy2zv-23/84y3zv-61/83x2z2v+2023xyz2v+19/40y2z2v+43/26xz3v-59/113yz3v-47/53z4v+15580x3uv+21x2yuv+113/97xy2uv-15419y3uv-15243x2zuv+5128xyzuv-34/47y2zuv+13206xz2uv-4833yz2uv+107/91z3uv-1693x2u2v+54/53xyu2v-86/67y2u2v+98/9xzu2v+86/17yzu2v+64/89z2u2v+25/113xu3v+7884yu3v+14089zu3v-12027u4v-9471x3v2-36/85x2yv2-21/13xy2v2+15888y3v2+76/109x2zv2+4547xyzv2+115/12y2zv2-11/107xz2v2+6764yz2v2-8321z3v2+84/101x2uv2-202xyuv2+3251y2uv2+91/4xzuv2+7124yzuv2-53/81z2uv2+47/84xu2v2-8833yu2v2+117/14zu2v2-3/113u3v2+126/97x2v3-78/115xyv3+68/63y2v3-34/109xzv3+5913yzv3+6226z2v3-2365xuv3+91/120yuv3+14120zuv3-69/8u2v3+71/12xv4-13094yv4-7262zv4-33uv4+5367v5,-9533x4y-318x3y2+8/49x2y3+83/29xy4+13129y5+221x4z+115/48x3yz+12508x2y2z+97/52xy3z+11479y4z+8941x3z2+104/109x2yz2+9191xy2z2+103/64y3z2+10584x2z3-7728xyz3+3979y2z3+15/82xz4+5409yz4-1326z5+3756x4u-57/62x3yu+63/47x2y2u-14600xy3u+159y4u-11/4x3zu-113/57x2yzu-26/125xy2zu-32/87y3zu-10/21x2z2u+12927xyz2u-73/62y2z2u+115/99xz3u-13/3yz3u-126/25z4u-3969x3u2-122/57x2yu2-5003xy2u2-100/117y3u2-71/30x2zu2+7356xyzu2-2211y2zu2+31/40xz2u2-6722yz2u2-139z3u2+4426x2u3+1/115xyu3-72/85y2u3+15260xzu3+7938yzu3+4/115z2u3-33/89xu4+31/108yu4-50/83zu4+14/107u5+24/95x4v-113/17x3yv+81/14x2y2v-9957xy3v-10075y4v-122/113x3zv+65/118x2yzv-96/29xy2zv-19/41y3zv+113/35x2z2v+121/31xyz2v-9/68y2z2v+91/45xz3v-23/116yz3v-67/99z4v-5355x3uv-3112x2yuv-12824xy2uv-58/123y3uv-13/22x2zuv-19/85xyzuv-121/24y2zuv-14093xz2uv+99/95yz2uv+89/50z3uv+13096x2u2v-109/120xyu2v+121/61y2u2v+80/41xzu2v-39yzu2v-8/99z2u2v+5/17xu3v+112/69yu3v+14346zu3v-7173u4v+125/13x3v2+43/53x2yv2-78/103xy2v2-109/111y3v2+33/13x2zv2-15333xyzv2+87/49y2zv2-7212xz2v2+7729yz2v2-86/123z3v2-119/103x2uv2-71/122xyuv2-81/113y2uv2+6133xzuv2+55/72yzuv2+69/31z2uv2+12828xu2v2+94/15yu2v2-7588zu2v2+21/41u3v2-8712x2v3+74/9xyv3-11/87y2v3+1446xzv3-3/95yzv3-87/55z2v3-717xuv3-110/97yuv3-13/113zuv3-95/81u2v3-37/68xv4+5112yv4-56/11zv4-6/115uv4+7910v5,25/42x4y-42/79x3y2-59/21x2y3+2736xy4-107/115x4z-203x3yz+47/101x2y2z+7686xy3z-63/64y4z+103/57x3z2-12082x2yz2+11/102xy2z2-83/43y3z2+13/49x2z3-2685xyz3+123/44y2z3+31/12xz4+126/83yz4+14745z5+83/37x4u+7362x3yu-14615x2y2u-14109xy3u+49/47y4u+1929x3zu+83/71x2yzu-13640xy2zu-97/58y3zu-11141x2z2u-61/49xyz2u-3745y2z2u-74/21xz3u+3493yz3u-7540z4u-103/118x3u2-43/32x2yu2-9200xy2u2-23/65y3u2+15895x2zu2-13924xyzu2-14291y2zu2-11039xz2u2-31/37yz2u2-101/93z3u2-39/83x2u3-4536xyu3-78/47y2u3+75/44xzu3-24/121yzu3-81/113z2u3-81/89xu4+15825yu4-4111zu4+5850u5-12534x4v-69/94x3yv-10076x2y2v+3952xy3v+25/12y4v+21/34x3zv+11002x2yzv-54xy2zv+20/23y3zv+4991x2z2v+549xyz2v+2687y2z2v-110/9xz3v+11359yz3v+49/24z4v+62/107x3uv-27/41x2yuv-17/52xy2uv-10972y3uv+12/103x2zuv-318xyzuv-77/40y2zuv-114/53xz2uv+17/28yz2uv-8084z3uv+85/36x2u2v+7/100xyu2v-5772y2u2v-89/114xzu2v-40/121yzu2v+3340z2u2v+36/113xu3v-38/93yu3v+2519zu3v-7084u4v+8136x3v2-55/23x2yv2+27/7xy2v2+74/39y3v2+63/16x2zv2-8661xyzv2+2/91y2zv2+3773xz2v2-75/122yz2v2+447z3v2-59/109x2uv2-119/9xyuv2-67/49y2uv2-11334xzuv2-10482yzuv2-60/91z2uv2+94/65xu2v2-108/17yu2v2-69/70zu2v2-23/20u3v2+8/115x2v3+29/41xyv3+8/15y2v3-95/6xzv3-9714yzv3+2550z2v3-121/80xuv3+67/18yuv3+43/5zuv3+23/124u2v3-12509xv4-104/79yv4-73/21zv4-1238uv4+9038v5,94/107x4y+47/14x3y2-6362x2y3-20/59xy4-43/120y5-3028x4z-15141x3yz-2028x2y2z+84/115xy3z-3024y4z+2811x3z2+47/45x2yz2+121/101xy2z2-100/57y3z2+8/115x2z3+1/101xyz3-13/112y2z3+3618xz4+88/67yz4-52/63z5+102/97x4u-12/89x3yu-102x2y2u-3846xy3u-61/86y4u+85/54x3zu+78/29x2yzu-13381xy2zu-49/95y3zu-77/2x2z2u-5784xyz2u+1557y2z2u-9163xz3u-114/121yz3u-57/103z4u+36/31x3u2-9062x2yu2-23/111xy2u2+7362y3u2-7671x2zu2+14945xyzu2+7901y2zu2+51/5xz2u2-109/48yz2u2+7696z3u2+11280x2u3-44/57xyu3-13736y2u3-13458xzu3-14723yzu3-707z2u3+899xu4-10381yu4+99/25zu4-7788u5-237x4v+45/43x3yv-7666x2y2v-4/109xy3v+4303y4v-13107x3zv-108/91x2yzv-7707xy2zv-73/47y3zv+61/118x2z2v-11/65xyz2v+2970y2z2v-104/37xz3v-15408yz3v-64/55z4v+47/113x3uv+2185x2yuv+7941xy2uv-61/37y3uv+6482x2zuv-11/70xyzuv+83/110y2zuv-109/83xz2uv-86/95yz2uv-7583z3uv+83/45x2u2v+89/38xyu2v-2/11y2u2v+3577xzu2v+124/125yzu2v-1151z2u2v+109/85xu3v+70/13yu3v+37/104zu3v-210u4v+51/29x3v2-104/111x2yv2+105/58xy2v2-13459y3v2-80/79x2zv2-3006xyzv2-115/16y2zv2+8208xz2v2+35/38yz2v2+49/27z3v2-1647x2uv2+10482xyuv2-34/93y2uv2+97/18xzuv2+101/20yzuv2+1711z2uv2+91/36xu2v2-96/23yu2v2+7006zu2v2+86/31u3v2-10734x2v3-43/18xyv3-4597y2v3-11174xzv3-7334yzv3+7/96z2v3+4/97xuv3-5/82yuv3-15600zuv3-69/94u2v3-71/25xv4+21/97yv4+117/23zv4-6557uv4-67/83v5,8164x4y+19/73x3y2-1592x2y3-28/87xy4-63/103x4z+11/42x3yz-52/67x2y2z-13766xy3z+11378y4z+10/37x3z2+115/41x2yz2+11/100xy2z2-49/40y3z2+86/111x2z3+124/5xyz3-25/79y2z3-14525xz4+11380yz4-53/42z5-12169x4u-14/51x3yu+68/33x2y2u-3/62xy3u-31/22y4u-74/93x3zu+12924x2yzu-103/123xy2zu-74/97y3zu-2789x2z2u-95/32xyz2u+45/13y2z2u+40/71xz3u+49/110yz3u+34/75z4u+9829x3u2-59/92x2yu2+106/65xy2u2+123/86y3u2+7133x2zu2-73/46xyzu2-7/29y2zu2-937xz2u2-65/67yz2u2-88/111z3u2-61/119x2u3+975xyu3-54/7y2u3-37/33xzu3+61/59yzu3+51/115z2u3+117/43xu4+8506yu4+13941zu4-14945u5-115/63x4v-14237x3yv-74/87x2y2v+104/47xy3v-95/104y4v+11535x3zv-119/75x2yzv-44xy2zv+11299y3zv-21/113x2z2v-2852xyz2v+95/77y2z2v-75/19xz3v-4864yz3v-79/88z4v+139x3uv-10068x2yuv+2049xy2uv+7515y3uv+97/56x2zuv+109/113xyzuv+7778y2zuv-71/11xz2uv-80/19yz2uv+55/59z3uv-69/98x2u2v-15679xyu2v+114/11y2u2v+69/65xzu2v+879yzu2v+45/104z2u2v+47/97xu3v-1373yu3v+15885zu3v+11121u4v-5042x3v2+4/25x2yv2-8607xy2v2-25/33y3v2+93/55x2zv2+68xyzv2-4167y2zv2+14180xz2v2-115/47yz2v2-81/67z3v2-12099x2uv2+34/107xyuv2+122/59y2uv2+775xzuv2-91yzuv2-85/96z2uv2-59/95xu2v2+174yu2v2+11/16zu2v2+66/37u3v2-121/36x2v3+6070xyv3-83/52y2v3-121/59xzv3-55/12yzv3+8088z2v3-20/29xuv3+76/125yuv3-10858zuv3+1833u2v3-103/50xv4+76/93yv4-119/18zv4+37/114uv4+51/7v5,85/56x4y-7839x3y2+12/37x2y3+6558xy4-8191x4z+115/7x3yz+81/23x2y2z-4121xy3z-1131y4z-23/37x3z2-71/32x2yz2+30/97xy2z2+5070y3z2-49/123x2z3+103/88xyz3-45/19y2z3+5132xz4+7277yz4+1896z5-103/75x4u-12020x3yu+12337x2y2u+6248xy3u+14290y4u-87/44x3zu-5364x2yzu-11801xy2zu-59/37y3zu+34/109x2z2u-14482xyz2u-10338y2z2u+118/73xz3u+7/8yz3u+158z4u+10590x3u2-5182x2yu2+83/62xy2u2+11557y3u2-92/119x2zu2-37/94xyzu2+5383y2zu2-365xz2u2+7/62yz2u2-7965z3u2-10/43x2u3+119/101xyu3-113/83y2u3-121/41xzu3+61/104yzu3+37/60z2u3-74/95xu4-113/66yu4-205zu4+4787u5-94/93x4v+14871x3yv-14723x2y2v+10730xy3v+112/17y4v-35/19x3zv-3487x2yzv-65/43xy2zv-7445y3zv-79/124x2z2v+7423xyz2v+91/2y2z2v+91/34xz3v-6970yz3v-50/113z4v+75/43x3uv-127x2yuv+11978xy2uv+48/113y3uv+113/62x2zuv-8941xyzuv-101/112y2zuv-5737xz2uv-31/123yz2uv+9490z3uv+19/92x2u2v-107/73xyu2v-23/121y2u2v+38/65xzu2v-672yzu2v+13/77z2u2v+46/119xu3v-103/18yu3v+107/59zu3v-52/21u4v-94/87x3v2-74/31x2yv2-9/22xy2v2-2896y3v2+113/3x2zv2-5386xyzv2-11391y2zv2+42/97xz2v2+77/64yz2v2-1610z3v2-102/43x2uv2+124/39xyuv2+14829y2uv2+88/113xzuv2-10411yzuv2-51/43z2uv2-36/121xu2v2+9487yu2v2-5589zu2v2+4335u3v2-5/91x2v3+6084xyv3-56/39y2v3-84/101xzv3-81/85yzv3-6521z2v3-2432xuv3+14317yuv3-43/82zuv3+121/8u2v3+14783xv4-92/45yv4+112/27zv4-8410uv4+31/105v5,-6691x4y-10158x3y2-5372x2y3+4132xy4+106/9y5+15600x4z-803x3yz+43/29x2y2z+9/91xy3z-92/61y4z+4807x3z2-12562x2yz2+14234xy2z2-91/17y3z2-91/30x2z3-10615xyz3-4206y2z3-29/45xz4-11/86yz4-115/9z5+125/112x4u+52/59x3yu+92/49x2y2u+121/85xy3u-51/14y4u-73/48x3zu-1/110x2yzu+12/65xy2zu+15045y3zu+12826x2z2u-123/89xyz2u+9465y2z2u-67/31xz3u-5080yz3u-7944z4u-107/72x3u2+1473x2yu2+7965xy2u2+15753y3u2-95/98x2zu2-9827xyzu2-25/53y2zu2-83/54xz2u2-13217yz2u2-117/110z3u2+230x2u3-12120xyu3+11/36y2u3-2071xzu3+109/59yzu3+6909z2u3-15/64xu4+45/82yu4-3091zu4-15711u5+5957x4v-45/86x3yv+26/29x2y2v-40/57xy3v+25/43y4v+126/37x3zv-38/33x2yzv+65/109xy2zv-33/68y3zv-7287x2z2v-4842xyz2v+35/118y2z2v+6157xz3v-97/89yz3v-91/50z4v-70/27x3uv+32/9x2yuv+78/125xy2uv+38/7y3uv-3214x2zuv-68/101xyzuv+87/55y2zuv-69/98xz2uv+5805yz2uv+41/102z3uv-43/54x2u2v-42/73xyu2v-13/49y2u2v+11864xzu2v+121/37yzu2v-100/109z2u2v-12609xu3v-9114yu3v-8746zu3v+11659u4v+3799x3v2-9581x2yv2+60/91xy2v2+2029y3v2+12075x2zv2+210xyzv2-1/22y2zv2+17/58xz2v2+1212yz2v2+118/27z3v2-3571x2uv2-3139xyuv2-23/100y2uv2-1240xzuv2+71/49yzuv2-21/103z2uv2-110/71xu2v2-40/77yu2v2-103/29zu2v2+10737u3v2+2828x2v3+14/39xyv3+7564y2v3+113/50xzv3+38/79yzv3+59/66z2v3+2726xuv3+91/94yuv3-15730zuv3-13408u2v3-97/42xv4+54/29yv4-33/73zv4+4823uv4+57/71v5,-14556x3yz-9751x2y2z-45/28xy3z+85/23y4z+5623x3z2+5369x2yz2-19/60xy2z2-36/5y3z2-95/36x2z3+5862xyz3-5/93y2z3+2949xz4+11357yz4-5679z5-52/45x3yu+4448x2y2u-9/22xy3u+2427y4u+3296x3zu+16/39x2yzu+53/57xy2zu+15/41y3zu+9473x2z2u+37xyz2u-58/69y2z2u-23/56xz3u-13/90yz3u-54/29z4u-41/67x3u2+10258x2yu2+23/44xy2u2-12952y3u2+2124x2zu2-1677xyzu2+12911y2zu2+22/45xz2u2+17/84yz2u2+5910z3u2+4782x2u3+119/39xyu3-17/84y2u3-120/91xzu3+35/59yzu3+17/77z2u3-4467xu4-77/4yu4-26/53zu4-3580u5-11977x3yv-118/77x2y2v+6040xy3v+9724y4v-47/5x3zv+59/101x2yzv+1212xy2zv-7/121y3zv+93/53x2z2v-56/23xyz2v-4470y2z2v+110/111xz3v-41/99yz3v-81/10z4v-71/24x3uv+26/115x2yuv+59/39xy2uv-10029y3uv+11748x2zuv+5749xyzuv+6887y2zuv+38/3xz2uv-116/61yz2uv-55/118z3uv+105/22x2u2v+70/87xyu2v-28/13y2u2v-109/123xzu2v-102/47yzu2v-52/71z2u2v+101/95xu3v+51/16yu3v+15/97zu3v-78/125u4v+35/46x3v2-9526x2yv2+10781xy2v2-119/44y3v2-23/10x2zv2+59/29xyzv2-15144y2zv2+29/120xz2v2-53/126yz2v2-93/85z3v2+53/8x2uv2-487xyuv2-12143y2uv2+13825xzuv2+55/6yzuv2-4250z2uv2+4237xu2v2-109/9yu2v2+67/53zu2v2+82/33u3v2+8660x2v3+15046xyv3-79/84y2v3-10310xzv3+110yzv3-7636z2v3+57/92xuv3-22/119yuv3-95/103zuv3+5138u2v3+123/49xv4-7587yv4+30/41zv4-124/121uv4+54/71v5,-29/60x4y-108/77x3y2-109/37x2y3-3619xy4+109/6x4z-37/67x3yz+53/45x2y2z+5291xy3z-2927y4z+34/5x3z2+87/17x2yz2+100/89xy2z2-114/29y3z2-4057x2z3-1/42xyz3-14/61y2z3-398xz4-122/73yz4+66/37z5+99/37x4u-5691x3yu-8778x2y2u+17/115xy3u+51/113y4u-71/101x3zu+85/91x2yzu-92/9xy2zu-3442y3zu+109/26x2z2u+50/37xyz2u+77/94y2z2u+16/35xz3u+9985yz3u+5/102z4u-5932x3u2+89/125x2yu2-895xy2u2-12455y3u2-630x2zu2-64/47xyzu2+25/9y2zu2+7906xz2u2+6827yz2u2+9808z3u2-113/118x2u3+79/8xyu3+9484y2u3+62/39xzu3+6/85yzu3-23/49z2u3-93/115xu4-11/93yu4-15177zu4-13/2u5-7623x4v-103/73x3yv-96/115x2y2v+39/76xy3v+80/79y4v+43/68x3zv+45/97x2yzv+101/87xy2zv+4632y3zv-918x2z2v+8248xyz2v-4276y2z2v+8853xz3v-39/61yz3v-121/87z4v+9968x3uv+473x2yuv+117/56xy2uv-19/21y3uv+121/119x2zuv+3/98xyzuv-65/42y2zuv-3723xz2uv+7/34yz2uv-112/87z3uv+103x2u2v+25/41xyu2v-14459y2u2v-56/41xzu2v-59/81yzu2v-109/102z2u2v-87/16xu3v-13011yu3v+49/123zu3v+106/89u4v-61/51x3v2+14107x2yv2+8035xy2v2-8853y3v2+5723x2zv2+123/53xyzv2-9727y2zv2-102/83xz2v2+1111yz2v2-15745z3v2+83/118x2uv2-57/35xyuv2-48/73y2uv2-28/37xzuv2-27/97yzuv2-27/58z2uv2+71/93xu2v2+117/8yu2v2+12344zu2v2-2497u3v2-118/71x2v3-11/19xyv3+21/104y2v3+32/113xzv3+15544yzv3+31/18z2v3+5909xuv3-67/58yuv3+27/35zuv3+115/9u2v3+79/13xv4+6722yv4-37/114zv4-71/124uv4+4657v5,-77/61x4y-88/101x3y2+93/88x2y3-11/70xy4+9806y5+7896x4z-4699x3yz+55/122x2y2z-63/122xy3z-125/74y4z+47/45x3z2+101/17x2yz2+92/47xy2z2+69/82y3z2+12402x2z3+113/98xyz3-101/33y2z3-15376xz4+47/71yz4-73/10z5+65/74x4u-14409x3yu-14478x2y2u+13593xy3u+102/97y4u+39/62x3zu-34/125x2yzu-83/9xy2zu+45/113y3zu+14484x2z2u-15293xyz2u-26/55y2z2u-958xz3u+67/35yz3u-93/19z4u+25/16x3u2+107/52x2yu2-4599xy2u2-86/51y3u2-9885x2zu2-77/47xyzu2+33/65y2zu2+90/109xz2u2-61/26yz2u2+6198z3u2-38/37x2u3-13935xyu3-142y2u3-64/5xzu3-7228yzu3+1251z2u3+1556xu4+117/121yu4-92/35zu4+99/92u5+13493x4v+12654x3yv+32/101x2y2v-11118xy3v+43/51y4v-575x3zv+103/21x2yzv+85/24xy2zv+1788y3zv+85/3x2z2v-64/25xyz2v+57/35y2z2v+37/120xz3v-69/110yz3v+48/49z4v+55/114x3uv-6439x2yuv+31/51xy2uv-90/49y3uv-45/104x2zuv-12018xyzuv+6/119y2zuv+40/63xz2uv+20/91yz2uv+50/43z3uv+1/26x2u2v-109/47xyu2v+99/7y2u2v+72/83xzu2v+61/118yzu2v+3530z2u2v+6146xu3v+117yu3v-9921zu3v-8708u4v-10/47x3v2-15294x2yv2-7336xy2v2+1/66y3v2-3057x2zv2+74/123xyzv2+146y2zv2-103/34xz2v2-117/76yz2v2+8472z3v2-7/92x2uv2+10033xyuv2+43/53y2uv2+4694xzuv2-49/2yzuv2-71/73z2uv2-125/17xu2v2-9817yu2v2+7218zu2v2+6897u3v2-19/90x2v3+11899xyv3-11779y2v3-5456xzv3+17/42yzv3+15340z2v3+12/7xuv3+9580yuv3-502zuv3-14069u2v3-4371xv4+14452yv4-9423zv4-117/122uv4+1126v5,49/108x4-39/4x3y-67/21x2y2-8/69xy3-9779y4+57/14x3z-11145x2yz+6928xy2z-7824y3z+1/79x2z2+5173xyz2-62/15y2z2-123/112xz3+88/79yz3+1/125z4+57/23x3u-11856x2yu-7444xy2u+115/8y3u-11133x2zu+71/73xyzu-7941y2zu+69/65xz2u+22/75yz2u+65/121z3u+9471x2u2+9167xyu2+51/59y2u2+12835xzu2+15047yzu2+11102z2u2-10059xu3+19/28yu3+65/21zu3-39/28u4-3/73x3v+94/61x2yv+8778xy2v-12922y3v-8711x2zv-37/97xyzv+14270y2zv+4487xz2v-59/112yz2v-14183z3v+15553x2uv+3579xyuv+114/91y2uv-4/97xzuv+13/85yzuv-89/15z2uv+58/75xu2v-34/7yu2v-90/61zu2v+90/101u3v-14673x2v2+90/19xyv2-45/37y2v2+23/49xzv2-71/11yzv2+119/8z2v2+89/10xuv2+109/91yuv2+36/49zuv2-7/31u2v2-40/113xv3-21/121yv3+9910zv3+33/14uv3-23/79v4,93/70x4-43/125x3y+9582x2y2+7565xy3-11511y4-3/79x3z-36/107x2yz-2038xy2z+879y3z-4700x2z2+103/14xyz2+102/79y2z2-67/68xz3-44/25yz3+105/79z4-29/24x3u-74/83x2yu+67/43xy2u+49/12y3u-115/11x2zu+23/67xyzu-61/27y2zu+12257xz2u+14068yz2u+23/15z3u+607x2u2+73/8xyu2+14237y2u2-13/33xzu2+110/71yzu2+41/101z2u2+5708xu3+88/67yu3+1460zu3-2472u4-1629x3v-51/70x2yv-88/73xy2v-36/97y3v+38/11x2zv+15899xyzv+54/19y2zv+9460xz2v-5150yz2v+3462z3v+5522x2uv-19/123xyuv+14871y2uv+53/5xzuv-7535yzuv-13430z2uv+107/47xu2v-8307yu2v-55/79zu2v-11945u3v-16/83x2v2+115/48xyv2+12389y2v2+11545xzv2-25/26yzv2-3755z2v2+4724xuv2-31/21yuv2+7872zuv2+89/45u2v2+87/47xv3+7625yv3+13494zv3-15376uv3-25/126v4; def I = grobj( groebner(J), intvec(0) ); // ASSUME: no zero entries in J! ASSUME(0, grtest(I)); "Input degrees: "; grview(I); def RR = grres(I, 0, 1); list L = RR; " = Non-minimal betti numbers: "; print(betti(L, 0), "betti"); "Graded (original) structure of 'res(Input,0)': "; grview(L); "Graded transpose of the previous resolution "; list LLL = grtranspose1( L ); grview( LLL ); "Its non-minimal betti numbers: "; print(betti(LLL, 0), "betti"); } proc grorder(def M) "USAGE: grorder(M), graded object or list M RETURN: same as input PURPOSE: reorder/transform graded object or chain complex M into block form ASSUME: M must be a graded object or a list of graded objects EXAMPLE: example grorder; shows an example " { if( typeof(M) == "list" ) { // TODO: extra grading argument??? if( size(M) == 0 ) { return (); } int j = size(M); int i = 1; while( i < j ) { if( size(M[i]) == 0 ){ break; } ASSUME(0, typeof(grrange(M[i])) == "intvec"); i++; } if( size(M[i]) == 0 ) { i--; } list L; module Z = 0; L[i] = Z; j = i; while( i > 0 ) { // "i: ", i; "A"; grview(M[i]); L[i] = grorder( grobj( M[i], grrange(M[i])) ); // "B"; grview(L[i]); if( i < j ) { ASSUME(2, size( module( matrix(transpose(L[i+1]))*matrix(transpose(L[i])) ) ) == 0 ); }; i--; }; return (L); // ? } ASSUME(1, grtest(M) ); // "a"; grview(M); intvec d; module N; (N,d) = reorder(M, 1); kill M; module M = grobj(transpose(N), -d, -grrange(N)); kill N,d; // "b"; grview(M); module N; intvec d; // reverse order: (N,d) = reorder(M, -1); kill M; module M = grobj(transpose(N), -d, -grrange(N)); // "c"; grview(M); ASSUME(1, issorted(grrange(M), 1) ); ASSUME(1, issorted(grdeg(M), 1) ); return (M); } example { "EXAMPLE:"; echo = 2; "Surface Name: 'rat.d10.g9.quart2' in P^4"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp; ideal J = x3yu2-48/11x2y2u2-8356xy3u2+35/121y4u2+31/66x3zu2-54/83x2yzu2-61/18xy2zu2+11526y3zu2+7372x2z2u2-91/60xyz2u2-95/97y2z2u2-45/71xz3u2+71/115yz3u2+25/54z4u2-61/102x3u3-12668x2yu3+6653xy2u3+41/54y3u3+87/50x2zu3-5004xyzu3+13924y2zu3+2310xz2u3-93/14yz2u3-2/93z3u3-97/125x2u4-58/11xyu4+46/73y2u4-4417xzu4+60/101yzu4+56/75z2u4-113/118xu5+115/4yu5-40zu5-8554u6-54/83x3yuv-9770x2y2uv-590xy3uv+15/49y4uv+94/69x3zuv+121/105x2yzuv+95/88xy2zuv+3186y3zuv+11/6x2z2uv-44/81xyz2uv+637y2z2uv+109/121xz3uv-33yz3uv-94/115z4uv-49/95x3u2v-11/109x2yu2v+45/113xy2u2v+97/84y3u2v+5257x2zu2v+99/49xyzu2v+12584y2zu2v-4294xz2u2v+1137yz2u2v-58/69z3u2v-4749x2u3v+120/97xyu3v-31/103y2u3v+62/97xzu3v-107/74yzu3v+53/59z2u3v+91/33xu4v+1291yu4v+23/34zu4v+58/77u5v+16/17x3yv2-750x2y2v2+86/89xy3v2+123/46y4v2+53/123x3zv2-61/99x2yzv2+12389xy2zv2+10419y3zv2+43/11x2z2v2-146xyz2v2-116/51y2z2v2+13/62xz3v2-5524yz3v2-111/118z4v2-56/55x3uv2-3038x2yuv2+14/27xy2uv2-43/64y3uv2+3385x2zuv2+25/11xyzuv2+92/41y2zuv2+28/113xz2uv2-2049yz2uv2+89/37z3uv2-13094x2u2v2-2774xyu2v2+15474y2u2v2-15791xzu2v2-71/116yzu2v2+77/41z2u2v2-83/68xu3v2-33/106yu3v2+71/37zu3v2-41/17u4v2+12052x3v3+1906x2yv3+13825xy2v3+80/7y3v3-125/96x2zv3-9661xyzv3+85/116y2zv3-72/91xz2v3+13/112yz2v3-126/97z3v3-1637x2uv3+34/103xyuv3+3844y2uv3+77/10xzuv3+6359yzuv3-11185z2uv3-124/121xu2v3+66/91yu2v3-14636zu2v3-1051u3v3+9/64x2v4-12924xyv4-119/41y2v4+74/23xzv4+1622yzv4+73/37z2v4-60/101xuv4+111/22yuv4-45/124zuv4+59/37u2v4-66/37xv5-71/99yv5+12409zv5-113/64uv5-5267v6,-x4y-22/79x3y2-125/42x2y3-116/7xy4+98/111y5-31/66x4z-118/75x3yz+110/93x2y2z-43/92xy3z-788y4z-7372x3z2-2701x2yz2-67/124xy2z2-117/62y3z2+45/71x2z3-8396xyz3-10343y2z3-25/54xz4+30/59yz4+61/102x4u+11736x3yu+12726x2y2u+41/118xy3u-15832y4u-87/50x3zu-130x2yzu+41/8xy2zu-10300y3zu-2310x2z2u-101/5xyz2u+6205y2z2u+2/93xz3u+8679yz3u+97/125x3u2-43/37x2yu2-39/80xy2u2+12139y3u2+4417x2zu2+4294xyzu2+11/58y2zu2-56/75xz2u2+8338yz2u2+113/118x2u3-10190xyu3-37/16y2u3+40xzu3+74/23yzu3+8554xu4+115/22yu4-39/79x4v+61/72x3yv+8048x2y2v-9201xy3v+16/121y4v+113/93x3zv+109/75x2yzv+12700xy2zv-10607y3zv+50/11x2z2v+1223xyz2v-103/79y2z2v-123/58xz3v+31/26yz3v-15/122z4v+122/25x3uv-99/17x2yuv+1723xy2uv-38/121y3uv+11016x2zuv-25/102xyzuv-14970y2zuv-61/6xz2uv-14981yz2uv+15900z3uv+3268x2u2v-75/19xyu2v-1436y2u2v-1764xzu2v-57/41yzu2v+12741z2u2v-14615xu3v+119/61yu3v-115/119zu3v+10501u4v-8502x3v2-51/76x2yv2-6281xy2v2+17/49y3v2-106/7x2zv2+63/101xyzv2-27/95y2zv2-1606xz2v2+9245yz2v2+1912z3v2+11155x2uv2+223xyuv2-13/18y2uv2+110/43xzuv2+76/81yzuv2-6291z2uv2+1400xu2v2-95/23yu2v2-9701zu2v2+106/105u3v2+72/47x2v3-13118xyv3+14409y2v3+37/86xzv3+44/69yzv3-325z2v3+113/71xuv3+16/81yuv3+6/19zuv3-119/39u2v3-89/9xv4+72/53yv4+112/55zv4-8587uv4-6604v5,-x3y2+48/11x2y3+8356xy4-35/121y5-12750x3yz+100/111x2y2z+45/74xy3z+99/74y4z-6/7x3z2-47/67x2yz2+11465xy2z2-11865y3z2+7776x2z3+124/45xyz3-98/115y2z3+117/85xz4-59/120yz4-8748z5+61/102x3yu+12668x2y2u-6653xy3u-41/54y4u+13408x3zu-2185x2yzu-1240xy2zu+1161y3zu+44/27x2z2u-11164xyz2u-13388y2z2u-107/13xz3u+90/71yz3u+4204z4u+97/125x2yu2+58/11xy2u2-46/73y3u2+55/48x2zu2+121/31xyzu2+126/61y2zu2-55/69xz2u2+5988yz2u2+3755z3u2+113/118xyu3-115/4y2u3+3390xzu3-5762yzu3+30/61z2u3+8554yu4-14317zu4+99/116x3yv-113/119x2y2v+50/23xy3v-37/79y4v-8668x3zv+14049x2yzv+111/35xy2zv+61/28y3zv-10171x2z2v+68/21xyz2v+2023y2z2v-9/109xz3v+8520yz3v-2683z4v-13547x3uv+28/65x2yuv-5988xy2uv+61/111y3uv+12314x2zuv+29/44xyzuv+6141y2zuv+11280xz2uv+79/22yz2uv-38/111z3uv+19/51x2u2v+5093xyu2v-10291y2u2v-5009xzu2v-111/49yzu2v+3813z2u2v-61/37xu3v+15914yu3v-3218zu3v-12915u4v-118/101x3v2-7/57x2yv2+13128xy2v2+11606y3v2+42/101x2zv2-54/17xyzv2-43/49y2zv2-119/110xz2v2+9742yz2v2-43/4z3v2-55/8x2uv2-29/88xyuv2+12042y2uv2+101/37xzuv2-57/62yzuv2+106/97z2uv2+38/83xu2v2+8152yu2v2-5492zu2v2-47/79u3v2+15112x2v3+69/44xyv3-6/71y2v3+113/54xzv3-13210yzv3-707z2v3-119/8xuv3+3845yuv3-19/20zuv3+4852u2v3+15761xv4-12372yv4+74/69zv4-2100uv4-12833v5,-x3yz+48/11x2y2z+8356xy3z-35/121y4z-31/66x3z2+54/83x2yz2+61/18xy2z2-11526y3z2-7372x2z3+91/60xyz3+95/97y2z3+45/71xz4-71/115yz4-25/54z5+15/52x3yu+6039x2y2u+74/99xy3u-17/40y4u+29/50x3zu-7775x2yzu+6368xy2zu+14170y3zu+52/41x2z2u+7003xyz2u-5787y2z2u-101/37xz3u-23/28yz3u-20/63z4u+41/77x3u2+8650x2yu2-15922xy2u2-16/83y3u2+7278x2zu2+31/30xyzu2-2/107y2zu2+35/122xz2u2+85/58yz2u2-757z3u2+2/101x2u3+86/17xyu3+95/59y2u3+123/22xzu3-6869yzu3-9311z2u3-105/97xu4+5699yu4+15925zu4+13528u5-154x3yv+4187x2y2v+56/107xy3v-15932y4v-5137x3zv-37/56x2yzv+9401xy2zv+92/123y3zv-79/97x2z2v+9201xyz2v+19/53y2z2v+107/20xz3v+17/77yz3v-15306z4v+3215x3uv-79/117x2yuv-9/76xy2uv-6352y3uv+93/13x2zuv-65/89xyzuv-115/4y2zuv-34/57xz2uv+39/107yz2uv+31/9z3uv+107/48x2u2v+2632xyu2v+29/96y2u2v-125/89xzu2v+29/113yzu2v+3940z2u2v-116/111xu3v+6145yu3v-105/62zu3v+101/17u4v-9281x3v2-49/107x2yv2-12154xy2v2+4/19y3v2-114/71x2zv2-15/118xyzv2+4372y2zv2+45/121xz2v2+46/111yz2v2+6614z3v2+17x2uv2+10806xyuv2-10617y2uv2-25/111xzuv2-116/27yzuv2-7/58z2uv2-686xu2v2+3/13yu2v2-17/49zu2v2-40/107u3v2+47/90x2v3-83/43xyv3-6326y2v3+49/64xzv3+113/76yzv3-122/73z2v3+10232xuv3-116/109yuv3-1990zuv3+70/51u2v3-118/19xv4-27/55yv4+21/19zv4-23/57uv4-11721v5,-3399x4y+1849x3y2-3/29x2y3+28/87xy4+10/29y5-9788x4z-49/73x3yz+13829x2y2z+118/73xy3z+13129y4z-618x3z2+92/13x2yz2+101/117xy2z2-162y3z2+24/5x2z3-29/74xyz3+2687y2z3-74/39xz4+2/57yz4+68/73x4u-13787x3yu-11659x2y2u+14729xy3u+92/53y4u+15/71x3zu-62/15x2yzu+21/85xy2zu+4938y3zu-120/37x2z2u-77/102xyz2u-4785y2z2u-83/70xz3u-12128yz3u-13592z4u-123/20x3u2+2607x2yu2+40/19xy2u2+6361y3u2-3091x2zu2+89/113xyzu2+149y2zu2-2890xz2u2-8374yz2u2+11886z3u2-49/43x2u3-9854xyu3-6943y2u3+10743xzu3-122/45yzu3-13902z2u3-103/19xu4-48/59yu4+27/86zu4+46/35u5-117/17x4v-15/7x3yv+8409x2y2v-83/28xy3v+86/35y4v+37/45x3zv+4/3x2yzv+35/38xy2zv+4015y3zv-49/111x2z2v-1260xyz2v-25/33y2z2v+116/19xz3v+93/8yz3v+5755z4v-25/89x3uv-11669x2yuv-64/107xy2uv+2993y3uv+7767x2zuv-17/95xyzuv-103/80y2zuv-14576xz2uv+80/47yz2uv+25/107z3uv+103/2x2u2v+125/117xyu2v-2/89y2u2v-5298xzu2v-50/27yzu2v-71/53z2u2v+2652xu3v+15761yu3v+2124zu3v+11/82u4v+100/63x3v2+4180x2yv2+11/39xy2v2-1221y3v2+108/125x2zv2+97/126xyzv2-7698y2zv2+13984xz2v2+1342yz2v2-84/121z3v2-26/73x2uv2-14/15xyuv2-22/37y2uv2-71/82xzuv2+12430yzuv2+103/52z2uv2-13095xu2v2+10114yu2v2-8/73zu2v2-33/97u3v2+83/105x2v3+22/45xyv3-7961y2v3-9654xzv3-54/55yzv3-3/71z2v3-10148xuv3-117/98yuv3+101/102zuv3-606u2v3+97/43xv4-68/21yv4+63/16zv4+42/17uv4+5834v5,-3399x3y2-32/113x2y3+14/99xy4+15001y5-121/115x3yz+4604x2y2z+7/2xy3z+9532y4z-3267x3z2+97/118x2yz2-14238xy2z2-80/21y3z2-12332x2z3-19/69xyz3+116/15y2z3-103/32xz4+15340yz4+10509z5+112/109x3yu-97x2y2u-40/11xy3u+90/29y4u-95/106x3zu-114/67x2yzu+113/48xy2zu+12080y3zu-44x2z2u+18/17xyz2u-4814y2z2u-103/100xz3u-96/61yz3u-205z4u-87/82x3u2-97/108x2yu2+3230xy2u2+104/83y3u2+41/86x2zu2+116/49xyzu2-59/110y2zu2+14/59xz2u2-6962yz2u2-2185z3u2+59/91x2u3+2497xyu3+3/37y2u3-13010xzu3+6/83yzu3-11448z2u3+13/72xu4-69/62yu4-2869zu4+23/73u5-20/43x3yv+5074x2y2v+28/125xy3v-2706y4v+13010x3zv-17/109x2yzv+21/4xy2zv+59/93y3zv-2406x2z2v+117/11xyz2v-14978y2z2v+70/89xz3v-33/7yz3v-13676z4v-13690x3uv+9825x2yuv-117/107xy2uv+12760y3uv-93/98x2zuv-113/64xyzuv+113/103y2zuv-9748xz2uv+11016yz2uv-10729z3uv+90/13x2u2v-13/47xyu2v-11/39y2u2v+20/69xzu2v+5531yzu2v+125/49z2u2v-11025xu3v-9621yu3v+113/109zu3v+4710u4v-107/7x3v2+110/119x2yv2-10025xy2v2-6644y3v2-5041x2zv2+5/96xyzv2+11472y2zv2-5128xz2v2+2927yz2v2+121/18z3v2-125/89x2uv2+12936xyuv2-71/47y2uv2+34/47xzuv2-75/103yzuv2-2654z2uv2-2350xu2v2-7707yu2v2+47/72zu2v2-952u3v2-21/67x2v3+58/37xyv3-8757y2v3+3615xzv3+44/123yzv3-13027z2v3-9/10xuv3+75/43yuv3+115/18zuv3+8071u2v3-26/3xv4-67/65yv4+14186zv4-41/122uv4+33/28v5,-3399x3yz-32/113x2y2z+14/99xy3z+15001y4z-9788x3z2+37/96x2yz2+7743xy2z2+31/55y3z2-618x2z3-8171xyz3+82/109y2z3+24/5xz4+88/85yz4-74/39z5-13165x3yu+3407x2y2u-12509xy3u-23/45y4u-11774x3zu-10/67x2yzu+69/79xy2zu-10/123y3zu-7636x2z2u+83/32xyz2u+51/112y2z2u+19/8xz3u+9309yz3u-44/49z4u+4089x3u2-374x2yu2-919xy2u2+98/107y3u2+2776x2zu2+85/26xyzu2+31/13y2zu2-103/82xz2u2+35/76yz2u2+59/45z3u2+2950x2u3+27/44xyu3+88/71y2u3+7/114xzu3-72/77yzu3+12917z2u3-34/67xu4-85/82yu4-55/84zu4+4690u5+11/42x3yv-19/125x2y2v-8288xy3v+9199y4v-12929x3zv+13357x2yzv-4903xy2zv-584y3zv-10/33x2z2v+59/113xyz2v+103/92y2z2v+101/69xz3v+8708yz3v-8/7z4v+13560x3uv-43/49x2yuv-121/98xy2uv+75/79y3uv-39x2zuv-88/69xyzuv-89/78y2zuv+110/67xz2uv+61/4yz2uv-98/45z3uv+82/7x2u2v-85/41xyu2v+6548y2u2v+9367xzu2v-59/81yzu2v-14408z2u2v+2363xu3v-80/11yu3v-50/17zu3v-14799u4v-53/21x3v2+9437x2yv2-117/80xy2v2+81/85y3v2-8/45x2zv2-6428xyzv2+15126y2zv2+68/89xz2v2+7/122yz2v2+9639z3v2+113/4x2uv2-8678xyuv2-104/45y2uv2-79/90xzuv2+39/101yzuv2-7234z2uv2-28/43xu2v2+1251yu2v2-97/56zu2v2+17/41u3v2+107/24x2v3+2747xyv3+9933y2v3-4199xzv3+53/83yzv3+6364z2v3-5456xuv3+618yuv3-123/55zuv3+2375u2v3+63/76xv4-115/106yv4-8811zv4-31/75uv4+10/109v5,13/89x4y+77/31x3y2+36/83x2y3-11411xy4+6936y5-12223x4z+7400x3yz+33/118x2y2z-12146xy3z+108/79y4z+82/99x3z2-9877x2yz2-79/70xy2z2-19/123y3z2-1491x2z3+7953xyz3-43/126y2z3+60/17xz4+98/57yz4-13317x4u-77/27x3yu-6811x2y2u-69/61xy3u+6144y4u+5404x3zu+121/120x2yzu-91/23xy2zu-71/106y3zu+1435x2z2u-120/13xyz2u-12019y2z2u-68/7xz3u-113/82yz3u+11526z4u-8706x3u2-89/53x2yu2-14804xy2u2+120/107y3u2+71/94x2zu2-1/70xyzu2+1532y2zu2+4470xz2u2+13/60yz2u2-115/102z3u2-82/21x2u3+27/121xyu3-4439y2u3-101/47xzu3-3186yzu3-106/101z2u3-10169xu4+19/58yu4-96/73zu4-7959u5-10526x4v-107/92x3yv+47/6x2y2v-23/43xy3v-69/62y4v+59/65x3zv-28/95x2yzv+5479xy2zv-39/77y3zv+11/69x2z2v-11713xyz2v+43/79y2z2v-15602xz3v+16/73yz3v-13952z4v+61/82x3uv-2219x2yuv-91/106xy2uv+5/37y3uv-148x2zuv+31/51xyzuv+18/101y2zuv+97/68xz2uv-73/32yz2uv+47/2z3uv+2/41x2u2v-13009xyu2v-7/60y2u2v+15779xzu2v+72/7yzu2v-11/73z2u2v-119/44xu3v-9067yu3v+3249zu3v+61/51u4v+12525x3v2-118/9x2yv2-3270xy2v2-4/25y3v2-5075x2zv2+77/40xyzv2-89/65y2zv2+17/58xz2v2-15609yz2v2+95/54z3v2-75/79x2uv2-4907xyuv2+12418y2uv2-57/17xzuv2-8746yzuv2+13/95z2uv2-124/67xu2v2+16/13yu2v2+28/23zu2v2-10847u3v2-645x2v3+106/75xyv3+6/115y2v3-8495xzv3+58/35yzv3-9398z2v3-101/72xuv3-71/20yuv3-124/65zuv3-8971u2v3+27/28xv4+12/29yv4-4276zv4+10858uv4+29/12v5,13/89x3y2+12068x2y3-15543xy4-77/79y5+6626x3yz+64/53x2y2z-6/23xy3z-47/125y4z+14403x3z2-43/78x2yz2-31/115xy2z2+94/59y3z2-118/117x2z3-11229xyz3+2268y2z3-116/85xz4+25/58yz4+3085z5+59/27x3yu+67/82x2y2u+11/6xy3u+103/47y4u-63/80x3zu-81/47x2yzu+7760xy2zu-115/56y3zu-10/17x2z2u+101/5xyz2u+15634y2z2u+1/107xz3u-9282yz3u+43/62z4u+62/55x3u2+100/113x2yu2-9205xy2u2-46/13y3u2+43/96x2zu2+10159xyzu2+692y2zu2+859xz2u2-19/74yz2u2+123/47z3u2-9/20x2u3-11391xyu3-2375y2u3+109/24xzu3-57/53yzu3-925z2u3-82/45xu4+97/34yu4+13/82zu4-108/29u5+63/10x3yv+38/17x2y2v-19/115xy3v+3150y4v+22/69x3zv+26/57x2yzv+110/27xy2zv+87/77y3zv+85/18x2z2v+39/47xyz2v-48/17y2z2v-7/27xz3v-13/100yz3v-11662z4v-17/8x3uv+37/11x2yuv+29/11xy2uv-109/88y3uv-2817x2zuv-61/44xyzuv+10/31y2zuv+10010xz2uv+51/86yz2uv-97/83z3uv-89/96x2u2v+4030xyu2v-58/77y2u2v-114/43xzu2v-37/10yzu2v-2011z2u2v+14483xu3v-109/101yu3v+121/102zu3v-79/92u4v+15113x3v2+10781x2yv2-14259xy2v2-113/48y3v2-7/94x2zv2-17/74xyzv2-5/117y2zv2-59/75xz2v2+13188yz2v2+103/43z3v2+4/125x2uv2-52/59xyuv2+85/92y2uv2-1/46xzuv2-9106yzuv2-83/11z2uv2-23/94xu2v2+6742yu2v2-35/107zu2v2-14596u3v2-117/43x2v3+1026xyv3+90/19y2v3+14671xzv3-101/100yzv3+6962z2v3+61/68xuv3+108/37yuv3-4157zuv3-3974u2v3+15677xv4+8661yv4+8459zv4-16/23uv4-37/119v5,13/89x3yz+12068x2y2z-15543xy3z-77/79y4z-12223x3z2-13941x2yz2+115/84xy2z2+13/98y3z2+82/99x2z3+7751xyz3+122/17y2z3-1491xz4+1327yz4+60/17z5+15363x3yu+9780x2y2u+19/117xy3u-1924y4u-14600x3zu+46/41x2yzu-5466xy2zu-73/12y3zu+10838x2z2u-8302xyz2u-89/113y2z2u+53/69xz3u-9224yz3u+47/33z4u-7399x3u2+89/77x2yu2+9312xy2u2-41/80y3u2-732x2zu2-6781xyzu2-8608y2zu2-9270xz2u2-117/58yz2u2-115/68z3u2-48/31x2u3-9067xyu3+97/107y2u3+73/57xzu3-2719yzu3-110/59z2u3-37/86xu4-15796yu4-61/4zu4-115/72u5+6161x3yv+4134x2y2v+677xy3v-8375y4v+1150x3zv+1551x2yzv+4157xy2zv+112/87y3zv+8171x2z2v+6040xyz2v+15651y2z2v-7/66xz3v-47/61yz3v+77/64z4v+14848x3uv+48/119x2yuv-9534xy2uv-117/95y3uv+5/4x2zuv+122xyzuv+90/31y2zuv-41/26xz2uv+31/30yz2uv-10428z3uv-9896x2u2v-71/21xyu2v-55/38y2u2v-29/22xzu2v-11092yzu2v+39/122z2u2v+93/73xu3v+22/49yu3v-21/106zu3v+56u4v+8565x3v2-1695x2yv2+2/17xy2v2+1/78y3v2-113/71x2zv2-41/100xyzv2+55/14y2zv2+15286xz2v2+17/53yz2v2+126/71z3v2-79/87x2uv2+109/97xyuv2-28/31y2uv2-6533xzuv2+22/5yzuv2-10449z2uv2+10830xu2v2-15516yu2v2+28/57zu2v2-81/22u3v2+4198x2v3+5667xyv3-7133y2v3-8408xzv3+11066yzv3-26/125z2v3-808xuv3+95/54yuv3-64/17zuv3-5267u2v3-15333xv4+42/89yv4+63/85zv4+119/113uv4-2011v5,5583x4y+1725x3y2-8652x2y3-91/25xy4-8495x4z-13731x3yz+9298x2y2z-41/111xy3z-15503y4z-13805x3z2+3962x2yz2-2/63xy2z2+3314y3z2+2522x2z3-10/87xyz3-408y2z3+7/16xz4+69/22yz4-7254z5-59/21x4u+115/7x3yu-1718x2y2u+7851xy3u+2632y4u-82/3x3zu+37/86x2yzu+101/113xy2zu+6747y3zu-109/113x2z2u+7399xyz2u+24/103y2z2u+89/9xz3u-14630yz3u+15066z4u-12561x3u2+113/115x2yu2+87/97xy2u2-126/67y3u2-48/7x2zu2+123/103xyzu2-11/107y2zu2-2747xz2u2+8158yz2u2-3/107z3u2+41/6x2u3+12767xyu3+3873y2u3+74/83xzu3-55/119yzu3-24/83z2u3+55xu4-7/95yu4+57/44zu4+2/101u5-6928x4v-121/57x3yv+111/104x2y2v+946xy3v-29y4v+3057x3zv-14/25x2yzv+43/31xy2zv-105/2y3zv+2336x2z2v+61/77xyz2v-7880y2z2v+5/58xz3v+10593yz3v+7094z4v+63/59x3uv-5/69x2yuv-11/81xy2uv-4157y3uv+73/65x2zuv-1676xyzuv-2376y2zuv-85/63xz2uv-95/2yz2uv-14903z3uv-119/110x2u2v-115/24xyu2v+125/9y2u2v+106/87xzu2v-13/12yzu2v-4/19z2u2v+7838xu3v-43/111yu3v+7/113zu3v-12500u4v+7743x3v2-2023x2yv2-85/83xy2v2+49/41y3v2+20/87x2zv2+3932xyzv2-77/6y2zv2+47/90xz2v2-15580yz2v2+39/4z3v2-61/8x2uv2+2518xyuv2+29/98y2uv2+11057xzuv2-18/107yzuv2+708z2uv2+14720xu2v2-3175yu2v2-113/59zu2v2-14735u3v2+7/69x2v3-4029xyv3+54/91y2v3+12372xzv3+67/2yzv3+8856z2v3-2178xuv3+995yuv3+64/95zuv3+4039u2v3-37/44xv4+23/17yv4-3035zv4-103/124uv4+69/64v5,-5583x3y2-1725x2y3+8652xy4+91/25y5+6201x3yz-73/49x2y2z-3844xy3z+10548y4z-11057x3z2-105/122x2yz2+31/53xy2z2+79/89y3z2-24/101x2z3+107/119xyz3-126y2z3+8164xz4+2/77yz4-51/8z5-14941x3yu-106x2y2u+8695xy3u+125/62y4u+4328x3zu+29/117x2yzu-6249xy2zu-2791y3zu+67/49x2z2u-38/29xyz2u+122/41y2z2u+10603xz3u-3029yz3u+5578z4u+14754x3u2-108/79x2yu2+4408xy2u2-12401y3u2-1426x2zu2-1741xyzu2-83/86y2zu2+79/95xz2u2+122/121yz2u2+81/2z3u2-1172x2u3-41/68xyu3-70/3y2u3+24/107xzu3+120/79yzu3+18/119z2u3-65/122xu4+1018yu4+22/107zu4+15189u5+5/8x3yv-12060x2y2v+3/62xy3v-227y4v+60/41x3zv-123/115x2yzv+110/123xy2zv+12864y3zv-86/121x2z2v-69/94xyz2v+14/79y2z2v+118/45xz3v+10842yz3v-37/58z4v+100/69x3uv-47/65x2yuv-7/67xy2uv-93/100y3uv-6262x2zuv-4/75xyzuv+2082y2zuv-9117xz2uv+12450yz2uv-84/67z3uv+123/26x2u2v-51/89xyu2v+19/74y2u2v-104/77xzu2v+318yzu2v+12402z2u2v+95/8xu3v-81/26yu3v-4486zu3v+3872u4v+72/91x3v2-83/63x2yv2+93/92xy2v2-15924y3v2-53/62x2zv2+6046xyzv2+1408y2zv2+60/107xz2v2-1150yz2v2-126/19z3v2-7429x2uv2+2554xyuv2+3602y2uv2+10738xzuv2-57/64yzuv2+86/69z2uv2+8172xu2v2+91/113yu2v2+92/65zu2v2+118/37u3v2+47/83x2v3+12750xyv3+10851y2v3+4216xzv3+6/101yzv3-108z2v3+2920xuv3-101/102yuv3-157zuv3+7742u2v3-7234xv4-2/111yv4+59/33zv4-93/91uv4+24/19v5,1592x4y+75/121x3y2+40/19x2y3-2651xy4+9934x4z+245x3yz+11665x2y2z+30/41xy3z+1823y4z+89/88x3z2-105/46x2yz2+79/58xy2z2-4191y3z2-76/61x2z3-21/32xyz3-9516y2z3-14896xz4-85/77yz4+51/109z5+61/30x4u-10/101x3yu+11796x2y2u+76/101xy3u+123/88y4u-5932x3zu-11857x2yzu+7128xy2zu-45/79y3zu+119/18x2z2u+9/74xyz2u+7042y2z2u-1114xz3u-11/82yz3u-1466z4u-6/85x3u2+27/106x2yu2+14246xy2u2-6216y3u2+47/6x2zu2-45/59xyzu2+89/41y2zu2+41/80xz2u2-7583yz2u2-75/113z3u2-14808x2u3-10873xyu3-90/67y2u3-11081xzu3-7369yzu3-7131z2u3-1402xu4-15386yu4-108/73zu4-5039u5+120/113x4v+10617x3yv-50/87x2y2v-2395xy3v-20/69y4v-8587x3zv+12960x2yzv-41/50xy2zv-13844y3zv-65/32x2z2v-77/122xyz2v-85/66y2z2v+13/100xz3v-20/51yz3v-13676z4v+76/97x3uv+1046x2yuv-8059xy2uv-117/59y3uv-29/105x2zuv+7287xyzuv-107/119y2zuv-35/118xz2uv+79/86yz2uv-2211z3uv+5448x2u2v+62/35xyu2v-2275y2u2v+29/121xzu2v-1674yzu2v-56/43z2u2v-3377xu3v-43/110yu3v+23/10zu3v-24/61u4v+121/53x3v2-4745x2yv2-57/64xy2v2+9554y3v2-12741x2zv2+10449xyzv2+37/108y2zv2+8621xz2v2-11/57yz2v2+1566z3v2+125/49x2uv2-121/118xyuv2+109/84y2uv2-335xzuv2+10167yzuv2-59/109z2uv2-103/119xu2v2+43/13yu2v2-73/87zu2v2+2037u3v2+13002x2v3+83/48xyv3-10713y2v3+1026xzv3-105/64yzv3-37/6z2v3+14779xuv3-6448yuv3+19/69zuv3-1/110u2v3+10010xv4+79/12yv4+12/19zv4-35/61uv4-11/57v5,-1592x3y2-75/121x2y3-40/19xy4+2651y5+39/121x3yz+122/77x2y2z-114/31xy3z+1544y4z+2/3x3z2-10271x2yz2-8373xy2z2+56/61y3z2+55/48x2z3-116xyz3-25/7y2z3-108/113xz4-34/53yz4+5548z5-122x3yu-9690x2y2u+43/87xy3u-5/19y4u+97/54x3zu-17/19x2yzu+4355xy2zu+12/5y3zu-1/100x2z2u+12754xyz2u+13600y2z2u+17/45xz3u-12091yz3u+5145z4u-63/64x3u2-84/31x2yu2-97/41xy2u2+7/13y3u2-79/62x2zu2-80/103xyzu2-69/14y2zu2+119/4xz2u2-35/87yz2u2-13840z3u2+14101x2u3+7952xyu3-1857y2u3-9861xzu3+3180yzu3+75/107z2u3-250xu4-15134yu4+4717zu4-2/41u5+22/27x3yv-8983x2y2v+10520xy3v-113/2y4v+10/73x3zv-1986x2yzv-110/13xy2zv+1550y3zv+32/111x2z2v-111/35xyz2v+101/98y2z2v+8045xz3v-2/89yz3v+2924z4v-79/11x3uv-15178x2yuv+10874xy2uv+54/11y3uv-8950x2zuv+70/53xyzuv-2403y2zuv-8249xz2uv+6935yz2uv+20/89z3uv+885x2u2v-76/71xyu2v-4/17y2u2v-31/52xzu2v-4/99yzu2v+10333z2u2v-93/104xu3v+82/101yu3v-71/37zu3v+9397u4v-15/112x3v2-6614x2yv2+119/2xy2v2+88/119y3v2+306x2zv2+2790xyzv2+10992y2zv2-115/74xz2v2-14711yz2v2+11612z3v2-1788x2uv2-75/97xyuv2+79/30y2uv2+99/59xzuv2-11439yzuv2-121/113z2uv2+108/37xu2v2+37/36yu2v2-3/65zu2v2-55/42u3v2+13/100x2v3-209xyv3-1272y2v3-117/68xzv3+63/94yzv3+32/59z2v3+1013xuv3-3463yuv3+6946zuv3-37/86u2v3+67/117xv4+85/28yv4-3024zv4-82/9uv4-32/65v5,-35/52x4y-12140x3y2+23/83x2y3+69/5xy4-80/79y5+120/43x4z-11865x3yz-3487x2y2z+53/59xy3z+53/102y4z-14083x3z2-14430x2yz2-2442xy2z2-33/104y3z2-91/38x2z3+4/87xyz3-26/57y2z3+4097xz4-9/122yz4+6364z5+9634x4u-97/95x3yu-46/99x2y2u+3847xy3u+121/106y4u+12765x3zu-5292x2yzu+1607xy2zu-67/121y3zu-12/35x2z2u+4/55xyz2u-17/27y2z2u+91/122xz3u-23/31yz3u+65/49z4u+73/46x3u2-124/27x2yu2-9933xy2u2+46/75y3u2+53/114x2zu2+3503xyzu2-14147y2zu2-11283xz2u2+11889yz2u2+99/104z3u2+3117x2u3+12624xyu3-10060y2u3+2193xzu3-80/47yzu3-77/13z2u3+11/31xu4-47/90yu4+49/48zu4-2/105u5-92/61x4v+7443x3yv+35/76x2y2v+114/67xy3v-73/126y4v+97/107x3zv+9464x2yzv+10869xy2zv+15718y3zv-37/33x2z2v+124/13xyz2v-11/26y2z2v-61/40xz3v+91/100yz3v-18/103z4v+60/29x3uv+21/125x2yuv-11117xy2uv+11748y3uv-16/117x2zuv+18/103xyzuv-1711y2zuv+1872xz2uv-109/123yz2uv-18/113z3uv-26/103x2u2v+14140xyu2v+11065y2u2v+8686xzu2v-5/111yzu2v+30/101z2u2v-10501xu3v-36/113yu3v-73/74zu3v+12753u4v-43/52x3v2-76/15x2yv2-5793xy2v2+18/13y3v2+1/79x2zv2+84/23xyzv2-172y2zv2+86/77xz2v2+15/37yz2v2+11835z3v2-6482x2uv2+94/113xyuv2+10727y2uv2-102/41xzuv2+15914yzuv2-12973z2uv2-9038xu2v2-13107yu2v2+1533zu2v2+12549u3v2-13528x2v3+903xyv3+23/114y2v3-123/64xzv3-81/5yzv3+111/103z2v3+4734xuv3-33/20yuv3-7954zuv3-2478u2v3+15518xv4-6723yv4-14/31zv4-3482uv4+10919v5,-3/94x4y-12936x3y2+2/11x2y3+32/23xy4-15921y5+61/93x4z+82/111x3yz-93/2x2y2z-6659xy3z-97/90y4z+402x3z2-14586x2yz2-121/39xy2z2+68/7y3z2+1212x2z3-2980xyz3+49/52y2z3-72/89xz4+92/47yz4+8478z5+2733x4u-103/89x3yu+1166x2y2u-7/53xy3u-106/23y4u+677x3zu+907x2yzu+7891xy2zu-9014y3zu+76/47x2z2u+49/116xyz2u-49/78y2z2u+12261xz3u+118/105yz3u-126/13z4u-8812x3u2-97/120x2yu2-9534xy2u2+92/5y3u2-54/71x2zu2+94/103xyzu2+2256y2zu2+4182xz2u2-5798yz2u2-31/115z3u2-73/98x2u3+15822xyu3+1004y2u3-578xzu3+9494yzu3-6779z2u3+14506xu4+10/121yu4+58/27zu4-2817u5-19/119x4v+7128x3yv+75/64x2y2v-65/109xy3v+5129y4v-53/55x3zv+54/125x2yzv-3009xy2zv+6144y3zv+15601x2z2v+123/55xyz2v-58/77y2z2v-56/61xz3v+121/10yz3v-103/86z4v-93/25x3uv+94/123x2yuv-25/107xy2uv+14807y3uv+65/7x2zuv+87/44xyzuv+6605y2zuv+23/99xz2uv-413yz2uv-17/15z3uv-79/46x2u2v+15240xyu2v-42/67y2u2v+8932xzu2v-5888yzu2v-4204z2u2v+7002xu3v-36/97yu3v-1634zu3v+61/102u4v-14/33x3v2-6520x2yv2+9004xy2v2-67/36y3v2-7/8x2zv2-24/11xyzv2-9373y2zv2+1556xz2v2-79/74yz2v2-6691z3v2+108x2uv2-76/61xyuv2+220y2uv2-1191xzuv2-4/9yzuv2+4546z2uv2+12205xu2v2+9/22yu2v2+64/93zu2v2-44/125u3v2+292x2v3+41/74xyv3+16/79y2v3-15892xzv3+5733yzv3+6796z2v3-42/55xuv3+71/79yuv3-19/104zuv3-38/15u2v3+6436xv4+28/15yv4+87/55zv4+2270uv4-30/41v5,-117/4x3y+97/122x2y2-3618xy3+6566y4+97/113x3z-12634x2yz+9865xy2z-1764y3z+114/31x2z2+5006xyz2+7/44y2z2-15040xz3+8/125yz3+11134z4-12980x3u-79/41x2yu-79/98xy2u+89/65y3u-1217x2zu+89/87xyzu+83/66y2zu+115/11xz2u+123/107yz2u+10920z3u-86/73x2u2-11/94xyu2-14054y2u2+6752xzu2-123/124yzu2+12129z2u2-13310xu3-52/63yu3+12847zu3-1545u4-11064x3v+11499x2yv-37/64xy2v+50/103y3v+123/94x2zv-126xyzv-111/44y2zv+95/14xz2v+113/83yz2v-77/103z3v+41/64x2uv+91/90xyuv-4932y2uv+103/31xzuv+62/63yzuv+1161z2uv-99/106xu2v-3181yu2v-11741zu2v-33/8u3v-3/118x2v2-9369xyv2+527y2v2-113/39xzv2-88/49yzv2-113/101z2v2+95/68xuv2-5930yuv2-20/43zuv2+7/41u2v2+109/93xv3-107/61yv3-8352zv3-5255uv3+12021v4,-2159x4-94/3x3y-4602x2y2+1609xy3+10721y4+28/9x3z-99/35x2yz+1/110xy2z+113/114y3z-118/75x2z2-103/93xyz2-68/67y2z2+13687xz3-1531yz3+61/107z4+6076x3u+9004x2yu+2211xy2u+110/53y3u+47/102x2zu+8495xyzu-9238y2zu+57/121xz2u-8543yz2u+8/19z3u-13527x2u2-13293xyu2+1138y2u2+26/115xzu2+78/53yzu2-12556z2u2+7299xu3+70/19yu3-14687zu3+13559u4+113/9x3v-85/126x2yv-83/3xy2v-3/46y3v+1814x2zv+28/79xyzv+103/51y2zv+78/31xz2v-14387yz2v+1/88z3v+116/75x2uv-101/59xyuv-70/3y2uv+109/71xzuv+13/88yzuv-147z2uv-113/76xu2v-9661yu2v+13855zu2v-6162u3v-1857x2v2-8208xyv2-4634y2v2-6178xzv2-7352yzv2-8247z2v2-113/15xuv2+99/40yuv2+21/97zuv2+11/37u2v2-6605xv3+8964yv3+35/121zv3+8543uv3-6008v4; def I = grobj( groebner(J), intvec(0) ); // ASSUME: no zero entries in J! ASSUME(0, grtest(I)); "Input degrees: "; grview(I); def RR = grres(I, 0, 1); list L = RR; " = Non-minimal betti numbers: "; print(betti(L, 0), "betti"); "Graded reordered structure of 'res(Input,0)': "; grview(grorder(L)); } proc TestGRRes(Name, J) "USAGE: TestGRRes(name, I), string name, ideal I RETURN: nothing PURPOSE: compute/test/output/order/transpose a graded resolution of I EXAMPLE: example TestGRRes; shows an example " { "=============================================="; ""; "=== Example: [", Name, "]"; " = Ring: ", string(basering); def I = grobj( groebner(J), intvec(0) ); // ASSUME: no zero entries in J! ASSUME(0, grtest(I)); // " = Input degrees: "; grview(I); " ! Resolution via 'grres': "; def R = grres(I, 0, 1); // sres, lres: no grading! // nres, mres - graded (with attrib(, "isHomog")) " = Non-minimal betti numbers: "; print(betti(R, 0), "betti"); list L = R ; // SRES_list(R); // " = Degrees of maps: "; grview(L); // MUST BE GRADED!!! " = Degrees of (ordered) maps: "; def LL = grorder(L); // MUST BE GRADED // ordres(L, intvec(0)); // ? grview( LL ); " = TRANSPOSE'd complex: %%%%%%%%%%%%%%"; list LLL = grtranspose1( LL ); // resolution RR = LLL; print(betti(LLL, 0), "betti"); grview( LLL ); ""; // "=============================================="; kill L, R; } example { "EXAMPLE:"; echo = 2; // if( defined(assumeLevel) ){ int assumeLevel0 = assumeLevel; } else { int assumeLevel; export(assumeLevel); }; assumeLevel = 5; // store the state of aL // note: data from random generation 2 string Name = "castelnuovo"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = 5153xy2-98/23y3-101/51xyz+33/41y2z+99/79xz2+7136yz2-106/111z3+119/53xyu+34/57y2u-77/92xzu+84/73yzu-109/78z2u-27/56xu2+10023yu2+82/103zu2-34/25u3+3/2xyv-68/25y2v+12721xzv+4/63yzv-73/21z2v-7291xuv-91/53yuv-4/79zuv-34/91u2v-122/53xv2+123/70yv2-64/73zv2+44/65uv2+14/31v3,xy2-15202y3+10613xyz+13640y2z-107/103xz2+5292yz2+19/119z3-10042xyu+2770y2u+7957xzu+14008yzu+92/121z2u-92/51xu2+1178yu2+1/117zu2-12726u3+82/101xyv-92/17y2v-107/56xzv+14233yzv+79/28z2v+51/50xuv-31/5yuv+95/91zuv+19/108u2v+12151xv2-69/110yv2+37/89zv2-63/116uv2-88/23v3,-5153x2+37/23xy+8706y2-13160xz+68/115yz+5548z2-22/61xu-113/98yu+11818zu+2114u2-101/97xv+89/22yv-3355zv-113/5uv-5521v2;TestGRRes(Name, I); kill R, Name, @p; ""; string Name = "ell.d8.g7"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = x2y2-47/69xy3+6059y4+78/85x2yz+55/124xy2z+13641y3z+8/17x2z2+7817xyz2-2746y2z2+85/124xz3+87yz3+13182z4+109/93x2yu-69/17xy2u+12089y3u+8769x2zu-53/36xyzu-14834y2zu+123/23xz2u+103/77yz2u-2344z3u-43/104x2u2-6198xyu2+47/115y2u2-39/19xzu2-29/24yzu2+51/89z2u2-65/37xu3-95/94yu3+11302zu3-53/57u4-2874x2yv+4347xy2v-25/77y3v+13819x2zv+29/34xyzv+474y2zv+33/107xz2v-3517yz2v+10617z3v+1834x2uv+54/113xyuv-8751y2uv+111/70xzuv-66/61yzuv+9195z2uv-14289xu2v-13/110yu2v+103/9zu2v+5113u3v+116/89x2v2+15142xyv2+13078y2v2-38/41xzv2-13/113yzv2-12824z2v2-57/11xuv2-114/17yuv2-125/31zuv2+11939u2v2+44/13xv3+56/69yv3+12/125zv3+643uv3+3530v4,-3454x2y-1285xy2-6182y3-8/69x2z+9/19xyz+64/49y2z+98/67xz2-13809yz2+21/44z3+77/47x2u+748xyu-41/77y2u+7318xzu+4217yzu+12562z2u-98/69xu2-14/85yu2+119/46zu2-61/121u3+5582x2v+108/77xyv-93/4y2v-65/49xzv-4135yzv+2477z2v+11114xuv+85/14yuv+51/125zuv-7572u2v-115/52xv2-7647yv2+4647zv2-5684uv2-1/55v3,3454x3-6645x2y-43/34xy2+14590y3+8/11x2z-117/112xyz+109/54y2z+6566xz2+23/57yz2-13078z3+95/61x2u+67/40xyu-4544y2u-95/72xzu-8/103yzu+100/77z2u+23/63xu2+69/61yu2-94/105zu2+8619u3+68/123x2v+8/117xyv+101/77y2v+124/125xzv+17/84yzv+23/67z2v+18/59xuv+3216yuv-77/59zuv-9/50u2v+96/109xv2-2491yv2+14089zv2+14067uv2-56/113v3;TestGRRes(Name, I); kill R, Name, @p; ""; string Name = "ell.d7.g6"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = 4971xy3+3/101y4-12318xy2z-12835y3z+97/98xyz2+63y2z2-8056xz3+23/91yz3-9662z4-7398xy2u+69/71y3u-53/68xyzu-49/67y2zu-113/122xz2u-9/61yz2u+71/88z3u+11358xyu2-38/29y2u2-10232xzu2+14490yzu2+2274z2u2+3501xu3+10427yu3-109/38zu3-99/5u4-6605xy2v-1555y3v-648xyzv-2083y2zv-61/41xz2v+75/17yz2v-69/55z3v-6104xyuv-9582y2uv+69/2xzuv-12551yzuv+47/49z2uv-118/13xu2v+34/105yu2v+105/41zu2v+6533u3v+122/25xyv2+2/43y2v2+16/61xzv2+11524yzv2+113/99z2v2-71/26xuv2+7809yuv2-4865zuv2-2122u2v2+53/118xv3-13209yv3-11106zv3-49/79uv3+3006v4,xy3+15492y4-13742xy2z+112/117y3z+6/47xyz2+28/41y2z2+71/111xz3+49/57yz3-61/44z4-11759xy2u+4242y3u-109/18xyzu+2260y2zu-6873xz2u-41/112yz2u+12574z3u-10939xyu2+119/38y2u2-62/33xzu2-3699yzu2+2651z2u2-13194xu3-15185yu3-11/116zu3-61/83u4-10094xy2v+13/4y3v-74/73xyzv+43/20y2zv-11547xz2v+53/43yz2v-92/93z3v+32/41xyuv+118/33y2uv-121/39xzuv-15913yzuv+53/11z2uv+97/76xu2v+85/29yu2v-5183zu2v+8520u3v+121/28xyv2+64/51y2v2-15810xzv2+1/43yzv2-6160z2v2+13988xuv2+9/40yuv2+123/4zuv2+15024u2v2+73/95xv3+80/97yv3+57/25zv3-109/81uv3-121/87v4,-4971x2+14389xy+1607y2+59/119xz+12020yz+103/122z2+8894xu+7091yu+54/19zu-50/77u2+28/25xv-113/56yv+68/29zv-14620uv+79/107v2;TestGRRes(Name, I); kill R, Name, @p; ""; string Name = "k3.d7.g5"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = -97/108x2y-31/118xy2-73/61y3-79/14x2z-15930xyz-2324y2z+1842xz2+656yz2-8852z3-89/38x2u-102/43xyu+14719y2u+70/67xzu+7335yzu+27/56z2u-10744xu2-55/83yu2+120/73zu2+120/61u3-126/125x2v+691xyv-15385y2v+117/16xzv-17/97yzv+80/121z2v-48/119xuv+21/34yuv-103/65zuv-49/32u2v-41/42xv2+11/75yv2-502zv2-7583uv2+26/69v3,97/108x3+77/114x2y+71/21xy2+13679y3-1645x2z-1/33xyz-79/7y2z-52/53xz2+11940yz2-5800z3+109/13x2u-115/64xyu-125/56y2u-2365xzu+2103yzu+56/87z2u-84/79xu2+107/106yu2-79/70zu2-419u3+5354x2v+92/53xyv-32/19y2v+11/74xzv+4193yzv+45/79z2v-113/72xuv+17/71yuv+11164zuv-17/33u2v+103/66xv2+55/79yv2+118/15zv2-2646uv2+57/106v3,x3-61/113x2y-64/21xy2-107/8y3-13/60x2z+43/35xyz+41/114y2z-13683xz2-5829yz2+71/38z3+90/17x2u-39/29xyu+42/5y2u-61/55xzu+111/77yzu-87/100z2u+10735xu2-83/91yu2-4884zu2-7965u3-65/12x2v+109/86xyv+10606y2v-14164xzv-6678yzv+83/18z2v-93/10xuv+120/49yuv-1592zuv-8710u2v-73/57xv2+10762yv2-2956zv2-89/63uv2-12/7v3;TestGRRes(Name, I); kill R, Name, @p; ""; string Name = "rat.d8.g6"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = -19/125x2y2-87/119xy3-97/21y4+36/53x2yz+2069xy2z-59/50y3z-65/33x2z2-14322xyz2+79/60y2z2-9035xz3-14890yz3+87/47z4-23/48x2yu+45/44xy2u+1972y3u+79/118x2zu-5173xyzu+115/121y2zu+1239xz2u-115/17yz2u-15900z3u-78/95x2u2+67/101xyu2-12757y2u2+12752xzu2+68/21yzu2+103/90z2u2-12917xu3+97/92yu3-24/49zu3-13/79u4-51/61x2yv-3103xy2v+77/117y3v+73/115x2zv-79/33xyzv+123/110y2zv+11969xz2v-31/95yz2v-123/95z3v-105/124x2uv+12624xyuv+2/63y2uv+6579xzuv+13/62yzuv+4388z2uv-12747xu2v-26/105yu2v-78/61zu2v-125/53u3v-5/71xyv2+62/77y2v2+21/44xzv2-9806yzv2+3/91z2v2+361xuv2+568yuv2+2926zuv2+53/38u2v2-14523yv3+2082zv3+113/115uv3,108/73x2y2+4028xy3+38/43y4-1944x2yz+39/80xy2z+8/109y3z+52/27x2z2+103/45xyz2+5834y2z2+63/101xz3+107/80yz3+1178z4-1/6x2yu+78/25xy2u-21/43y3u+50/71x2zu-14693xyzu+15074y2zu+9/103xz2u-7396yz2u-14493z3u+93/25x2u2+61/4xyu2-11306y2u2-79/81xzu2+59/82yzu2-5/106z2u2+89/71xu3-34/11yu3+15/103zu3-115/52u4-54/65x2yv+67/16xy2v-7/68y3v-10/13x2zv+32/85xyzv+1/91y2zv+107/118xz2v+7594yz2v-98/103z3v+9919x2uv-965xyuv+53/34y2uv+119/11xzuv-3400yzuv-8329z2uv+75/98xu2v-24yu2v+55/87zu2v-82/71u3v-73/115x2v2+85/19xyv2-213y2v2-7704xzv2-15347yzv2+14960z2v2+15065xuv2-125/17yuv2+32/83zuv2-14/73u2v2-21/44xv3+79/2yv3-61/32zv3+46/119uv3-2082v4,9/20x2y2+113/71xy3-88/65y4+9983x2yz-6722xy2z+87/68y3z+1893x2z2+65/32xyz2+51/55y2z2-102/53xz3+58/5yz3-7187z4-96/7x2yu-14/87xy2u-3532y3u+95/54x2zu+19/65xyzu-6728y2zu+31/121xz2u+73/106yz2u-91/5z3u-12928x2u2+707xyu2-55/48y2u2-96/25xzu2+15869yzu2-20/107z2u2-10030xu3-13786yu3-122/9zu3+19/59u4-7/52x2yv+101/74xy2v+83/6y3v-91/55x2zv-5266xyzv+85/61y2zv+126/95xz2v+56/51yz2v+13073z3v-50/21x2uv-13553xyuv-116/53y2uv+68/71xzuv-111/98yzuv-11037z2uv+68/121xu2v-124/53yu2v+54/55zu2v+5862u3v+12318x2v2-119/29xyv2+101/17y2v2-51/40xzv2-82/33yzv2-30/41z2v2-29/52xuv2+7817yuv2+8121zuv2-28/99u2v2+1125xv3-73/55yv3-14141zv3+8742uv3-1203v4,x2y2+11357xy3+295y4+144x2yz-31/54xy2z+89/119y3z+1/46x2z2+29/26xyz2+1384y2z2+1461xz3+113/91yz3+9494z4-7/32x2yu+12850xy2u-3626y3u-33/106x2zu-7/60xyzu-5935y2zu-8597xz2u+5527yz2u+1708z3u+6182x2u2-15780xyu2+4669y2u2-38/69xzu2+8412yzu2+9265z2u2-5679xu3-67/18yu3-34/67zu3-7178u4+113/56x2yv-3669xy2v+17/113y3v-87/35x2zv-4871xyzv-111/11y2zv-1131xz2v-72/13yz2v+838z3v-115/4x2uv+3395xyuv-43/68y2uv-82/13xzuv+7042yzuv-88/119z2uv+100/19xu2v+24/11yu2v+89/3zu2v+7395u3v-119/109x2v2+1/104xyv2+18/25y2v2+700xzv2-59/9yzv2-92/87z2v2+2486xuv2-67/103yuv2+1469zuv2-101/91u2v2-79/33xv3+10838yv3+81/4zv3-11843uv3+7204v4,19/125x3-15698x2y-22/117xy2-95/107y3+2027x2z-7750xyz+85/104y2z-15326xz2+31/101yz2+67/81z3-7879x2u-112/115xyu+124/81y2u+99/61xzu-7458yzu+40/33z2u-1502xu2+6591yu2-7/73zu2-42/95u3+93/83x2v-15/112xyv-84/95y2v+35/36xzv+5/24yzv-12768z2v+13232xuv-76/103yuv-79/52zuv-7217u2v+75/92xv2-49/64yv2+17/14zv2-6109uv2+1695v3;TestGRRes(Name, I); kill R, Name, @p; ""; string Name = "k3.d14.g19"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = x4y2+52/25x3y3+73/79x2y4+33/83xy5-116/65y6+23/39x4yz-45/11x3y2z-45/16x2y3z+73/8xy4z+107/70y5z+115/8x4z2-4619x3yz2+13504x2y2z2+9/118xy3z2-113/64y4z2+10731x3z3-7/13x2yz3-26/17xy2z3+3/59y3z3-4602x2z4+71/44xyz4-66/43y2z4-37/70xz5-6988yz5-123/29z6-6158x4yu+9171x3y2u+71/122x2y3u-119/73xy4u-15409y5u+85/3x4zu+104/59x3yzu-3336x2y2zu-50/107xy3zu-10232y4zu-8965x3z2u-2736x2yz2u+4/61xy2z2u+49/92y3z2u+13261x2z3u+64/31xyz3u-89/70y2z3u+11080xz4u+10139yz4u+13653z5u+34/25x4u2-5678x3yu2+43/13x2y2u2+4119xy3u2+72/109y4u2-77/64x3zu2+15044x2yzu2+97/53xy2zu2+9036y3zu2-10599x2z2u2-107/126xyz2u2+43/12y2z2u2-4690xz3u2-43/75yz3u2-15886z4u2-113/7x3u3-242x2yu3+85/19xy2u3-20/57y3u3+109/37x2zu3+6103xyzu3-51/43y2zu3-89/92xz2u3-14/87yz2u3+59/111z3u3-40/63x2u4+113/86xyu4-17/109y2u4-11039xzu4+107/31yzu4+121/47z2u4-123/5xu5+83/97yu5+110/23zu5-122/83u6-15/17x4yv+96/65x3y2v-1491x2y3v+3885xy4v+26/87y5v-51/89x4zv-123/88x3yzv-2315x2y2zv-4119xy3zv-3390y4zv-68/5x3z2v-57/67x2yz2v-116/77xy2z2v+109/54y3z2v+23/89x2z3v+19/77xyz3v+32/107y2z3v-85/121xz4v+9325yz4v+87/32z5v-65/81x4uv-39/19x3yuv+4671x2y2uv+54/77xy3uv+8/47y4uv+1194x3zuv+5/14x2yzuv+1151xy2zuv+90/103y3zuv-55/8x2z2uv-44/101xyz2uv-4713y2z2uv-1/7xz3uv+13344yz3uv-11451z4uv-101/108x3u2v+42/55x2yu2v+4810xy2u2v-3/40y3u2v+4699x2zu2v+114/53xyzu2v+49/116y2zu2v-9/74xz2u2v-84/109yz2u2v-119/97z3u2v+15282x2u3v-109/71xyu3v+2490y2u3v-119/47xzu3v+43/40yzu3v-105/86z2u3v-101/70xu4v+10041yu4v-93/53zu4v+4204u5v+83/43x4v2+15199x3yv2+26/43x2y2v2-6627xy3v2+59/113y4v2+10482x3zv2-8354x2yzv2-78/79xy2zv2+7126y3zv2+68/25x2z2v2+94/59xyz2v2+83/45y2z2v2-59/60xz3v2+15768yz3v2+15/29z4v2-43/100x3uv2-11939x2yuv2+1832xy2uv2+29/6y3uv2+115/76x2zuv2+51/106xyzuv2+7/23y2zuv2+19/107xz2uv2-13797yz2uv2+16/109z3uv2-7519x2u2v2+3472xyu2v2-28/107y2u2v2-11283xzu2v2+12707yzu2v2+54/47z2u2v2+1841xu3v2-3037yu3v2+9239zu3v2+3729u4v2+7476x3v3+59/81x2yv3-49/85xy2v3-91/60y3v3+20/77x2zv3-2761xyzv3+4245y2zv3+97/75xz2v3+42/121yz2v3+1822z3v3-97/16x2uv3-47/10xyuv3-11222y2uv3-2194xzuv3+116/21yzuv3+118/47z2uv3-89/23xu2v3+7317yu2v3-10812zu2v3+70/13u3v3-5855x2v4-9755xyv4+14875y2v4+59/117xzv4-33/109yzv4+48/59z2v4+62/57xuv4-56/73yuv4-3601zuv4+2155u2v4-77/107xv5+12478yv5+7028zv5-3652uv5+81/28v6,-50/87x4yz-2298x3y2z+9266x2y3z-55/16xy4z+31/76y5z+13/46x4z2-11/100x3yz2+90/119x2y2z2-65/54xy3z2-102/77y4z2-76/109x3z3-6558x2yz3-60/19xy2z3-17/113y3z3-74/43x2z4+8092xyz4-13313y2z4-13/107xz5-47/82yz5+5501z6+39/17x4yu-11/13x3y2u-4407x2y3u+89/117xy4u+118/101y5u-37/57x4zu+100/33x3yzu-99/46x2y2zu-2772xy3zu-75/94y4zu-6429x3z2u-7628x2yz2u+10112xy2z2u+85/32y3z2u-4068x2z3u+81/95xyz3u+97/89y2z3u-12700xz4u+19/113yz4u+14306z5u+13878x4u2-22/21x3yu2+107/41x2y2u2-16/97xy3u2-2426y4u2-12247x3zu2+71/41x2yzu2+16/69xy2zu2+37/113y3zu2-12195x2z2u2-8354xyz2u2-6177y2z2u2-10139xz3u2+9118yz3u2-113/115z4u2-8042x3u3+37/97x2yu3+7/30xy2u3+90/73y3u3-14676x2zu3+630xyzu3+7824y2zu3-5947xz2u3-12019yz2u3+99/19z3u3+17/117x2u4+1943xyu4-47/45y2u4-79/98xzu4+46/119yzu4-98/25z2u4-20/69xu5+45/28yu5-123/14zu5-20/29u6+83/41x4yv+32/19x3y2v+5/107x2y3v+9/95xy4v+35/33y5v+14385x4zv+2237x3yzv+109/11x2y2zv-6489xy3zv-96/107y4zv+1749x3z2v+23/64x2yz2v+105/17xy2z2v+11/70y3z2v-4677x2z3v-4/119xyz3v+8243y2z3v-7538xz4v-45/58yz4v+1768z5v-10804x4uv-102/89x3yuv-80/17x2y2uv-103/66xy3uv-14/55y4uv-5981x3zuv+2/35x2yzuv+24/71xy2zuv-17/62y3zuv-59/52x2z2uv+468xyz2uv+61/110y2z2uv-1265xz3uv-11317yz3uv+15610z4uv+61/116x3u2v+1972x2yu2v+26/121xy2u2v+9787y3u2v-91/62x2zu2v+101/65xyzu2v-85/111y2zu2v+99/95xz2u2v-125/51yz2u2v+10324z3u2v+95/73x2u3v-705xyu3v-6165y2u3v+2215xzu3v-109/12yzu3v+72/95z2u3v-149xu4v+14154yu4v+412zu4v+2747u5v+113/25x4v2+5988x3yv2-119/107x2y2v2-70/41xy3v2+2891y4v2+85/103x3zv2-9398x2yzv2-116/117xy2zv2-12527y3zv2-8408x2z2v2-76/47xyz2v2+13729y2z2v2-65/77xz3v2+23/94yz3v2+61/77z4v2+18/121x3uv2-8520x2yuv2+103/34xy2uv2+17/40y3uv2+23/104x2zuv2+7/29xyzuv2-5908y2zuv2-7791xz2uv2-12032yz2uv2+125/82z3uv2-89/126x2u2v2+22/75xyu2v2-118/67y2u2v2+34/29xzu2v2+30/109yzu2v2-64/37z2u2v2-113/87xu3v2+110/109yu3v2+81/23zu3v2-40/99u4v2-14204x3v3+5939x2yv3-7749xy2v3+2924y3v3-3662x2zv3-51/122xyzv3-7218y2zv3-13482xz2v3+12673yz2v3-9675z3v3+6567x2uv3-14008xyuv3+14242y2uv3-4310xzuv3+757yzuv3-9110z2uv3+27/14xu2v3-81/40yu2v3-42/29zu2v3+7287u3v3+119/94x2v4-11926xyv4-82/117y2v4+4138xzv4-67/70yzv4+79/49z2v4-113/50xuv4+102/113yuv4-4791zuv4-11/97u2v4-19/18xv5+6866yv5+63/101zv5+4646uv5-374v6,109/29x4yz+94/43x3y2z-13879x2y3z-53/73xy4z+9074y5z+846x4z2-107/44x3yz2+62/71x2y2z2-121/68xy3z2+14200y4z2-78/89x3z3+51/94x2yz3+123/5xy2z3-731y3z3-15645x2z4-91/25xyz4+39/17y2z4+10343xz5-14671yz5+101/71z6+10467x4yu-3/64x3y2u+75/31x2y3u-43/66xy4u-118/55y5u+7/25x4zu-59/95x3yzu+11830x2y2zu-76/121xy3zu+95/72y4zu-121/53x3z2u+120/7x2yz2u-7033xy2z2u+89/2y3z2u+86/47x2z3u-13/99xyz3u-1447y2z3u+6253xz4u-9082yz4u-4518z5u+31/111x4u2+68/79x3yu2-3532x2y2u2+61/94xy3u2+1210y4u2-11697x3zu2-9386x2yzu2-8263xy2zu2+11759y3zu2+113/118x2z2u2-6488xyz2u2+41/30y2z2u2-15179xz3u2-10848yz3u2-14/51z4u2-13/123x3u3-21/10x2yu3-4018xy2u3-11558y3u3-68/13x2zu3+41/119xyzu3-94/31y2zu3+97/101xz2u3+2551yz2u3+51/73z3u3-10862x2u4-44/125xyu4+113/13y2u4-5704xzu4+65/116yzu4-9578z2u4-95/58xu5+8033yu5-79/124zu5-107/76u6+7293x4yv+15260x3y2v+32/35x2y3v+8519xy4v-50/83y5v+83/40x4zv-6104x3yzv+83/121x2y2zv+230xy3zv+9/50y4zv+1507x3z2v-75/112x2yz2v-20/7xy2z2v-12689y3z2v-75/112x2z3v-8673xyz3v+79/69y2z3v-12453xz4v-4805yz4v-125/11z5v-22/97x4uv-11396x3yuv+67/88x2y2uv-75/122xy3uv-30/29y4uv-837x3zuv-71/12x2yzuv+37/77xy2zuv+78/59y3zuv-13742x2z2uv+13080xyz2uv+643y2z2uv-7517xz3uv-15577yz3uv+52/75z4uv+12922x3u2v-14629x2yu2v-10188xy2u2v-5113y3u2v+67/51x2zu2v-15273xyzu2v-13388y2zu2v+121/109xz2u2v-64/83yz2u2v+69/20z3u2v-117/44x2u3v-7091xyu3v-118/45y2u3v+73/26xzu3v-117/38yzu3v+1448z2u3v+71/19xu4v-12698yu4v+107/81zu4v+21/43u5v-94/79x4v2-1660x3yv2-15179x2y2v2-10/71xy3v2+9523y4v2+6/115x3zv2-15x2yzv2+15142xy2zv2+6157y3zv2+5/79x2z2v2+126/47xyz2v2+14/107y2z2v2+35/11xz3v2-65/51yz3v2-7246z4v2-2652x3uv2-79/69x2yuv2-21/59xy2uv2-14050y3uv2-89/81x2zuv2+91/55xyzuv2-7501y2zuv2-7688xz2uv2-73/102yz2uv2-27/13z3uv2-2186x2u2v2+120/31xyu2v2+45/43y2u2v2-101/16xzu2v2-69/83yzu2v2-12658z2u2v2-7658xu3v2-53/103yu3v2+11620zu3v2+672u4v2-10795x3v3+10972x2yv3-7178xy2v3+81/2y3v3+67/43x2zv3-113/12xyzv3-3947y2zv3-17/5xz2v3-102/49yz2v3-67/26z3v3+5/6x2uv3-95/4xyuv3+2582y2uv3+72/23xzuv3+8490yzuv3-46/111z2uv3+224xu2v3+658yu2v3-98/89zu2v3+7954u3v3+87/35x2v4+7260xyv4+91/40y2v4+11611xzv4+9076yzv4+6444z2v4-8/95xuv4-12845yuv4+86/61zuv4-59/113u2v4-115/84xv5-116/41yv5-119/62zv5+15120uv5-37/51v6,21/122x4yz-9662x3y2z-11556x2y3z+67/18xy4z-10712y5z-4891x4z2+113/118x3yz2-94/83x2y2z2+61/90xy3z2+108/101y4z2+9905x3z3+12/29x2yz3+13047xy2z3-55/46y3z3+59/88x2z4+59/78xyz4+11951y2z4-1357xz5-75/77yz5+15673z6+40/113x4yu+9/55x3y2u-62/83x2y3u+65/111xy4u+4184y5u-9578x4zu+124/17x3yzu+91/85x2y2zu-1/66xy3zu+4184y4zu+101/77x3z2u-12238x2yz2u-5394xy2z2u+82/9y3z2u-73/113x2z3u+3736xyz3u+52/81y2z3u+10426xz4u+11/120yz4u+89/123z5u-99/74x4u2-9/46x3yu2-57/29x2y2u2-24/125xy3u2+115/119y4u2-10/103x3zu2-66/17x2yzu2-662xy2zu2-31/17y3zu2-56/27x2z2u2-4728xyz2u2-86/59y2z2u2-19/34xz3u2+61/13yz3u2-14093z4u2-9068x3u3-115/94x2yu3+15912xy2u3-79/66y3u3-3631x2zu3+1074xyzu3-113/105y2zu3-89/109xz2u3-80/91yz2u3+119/12z3u3+19/87x2u4-42/25xyu4+116/55y2u4+10/77xzu4+74/79yzu4-77/81z2u4-90/121xu5-43/31yu5+107/122zu5+76/113u6+60/17x4yv-6269x3y2v-124/75x2y3v+89/48xy4v-69/2y5v+8832x4zv+13984x3yzv+35/29x2y2zv-65/88xy3zv+53/74y4zv-55/79x3z2v-104/105x2yz2v+50/29xy2z2v-118/119y3z2v-25/88x2z3v+69/82xyz3v-56/69y2z3v-10495xz4v-73/50yz4v+1872z5v-62/19x4uv+99/89x3yuv+3156x2y2uv+5804xy3uv+85/91y4uv+10928x3zuv-4/83x2yzuv+2839xy2zuv+11/38y3zuv+55/126x2z2uv+15613xyz2uv+69/28y2z2uv+75/17xz3uv+115/51yz3uv-111/68z4uv-9781x3u2v+2/105x2yu2v-29/10xy2u2v+90/53y3u2v-12840x2zu2v+85/71xyzu2v-91/80y2zu2v+15904xz2u2v-82/69yz2u2v-32/75z3u2v-91/2x2u3v-77/61xyu3v-9757y2u3v-97/52xzu3v-32/9yzu3v-7457z2u3v-113/100xu4v-13367yu4v-16zu4v+17/53u5v+90/103x4v2-9338x3yv2-42/61x2y2v2+57/124xy3v2-17/6y4v2+6201x3zv2+75/8x2yzv2+13205xy2zv2-21/23y3zv2+6724x2z2v2-1646xyz2v2-3/41y2z2v2+13206xz3v2+14595yz3v2+3100z4v2-94/107x3uv2+106/99x2yuv2+53/24xy2uv2-10113y3uv2+13103x2zuv2+121/124xyzuv2-104/103y2zuv2+59/62xz2uv2+13343yz2uv2-73/72z3uv2-35/123x2u2v2+91/33xyu2v2+75/58y2u2v2-69/73xzu2v2-15760yzu2v2+684z2u2v2-12551xu3v2-99/79yu3v2+74/87zu3v2+9255u4v2-9727x3v3+1222x2yv3+31/115xy2v3+37/50y3v3-86/125x2zv3-5/82xyzv3+7/2y2zv3+69/88xz2v3-25/119yz2v3-120/101z3v3-48/113x2uv3-25/97xyuv3-14896y2uv3+13431xzuv3+13246yzuv3+7556z2uv3-103/111xu2v3+13/108yu2v3+9471zu2v3+31/114u3v3-121/23x2v4-65/69xyv4+66/95y2v4+30/59xzv4-111/40yzv4+55/4z2v4+114/121xuv4+7610yuv4-9205zuv4+85/81u2v4-88/59xv5-4248yv5+95/91zv5+156uv5-71/90v6,7698x4y-93/32x3y2+95/37x2y3+29/104xy4+10/23y5-11774x4z+4544x3yz-9/85x2y2z-45/49xy3z+110/41y4z-44/91x3z2-6083x2yz2+116/111xy2z2+47/68y3z2-11603x2z3-4229xyz3-13462y2z3-31/19xz4+4222yz4-700z5-34/11x4u-20/17x3yu-2471x2y2u-11235xy3u+13259y4u-111x3zu-109x2yzu-89/61xy2zu-28/11y3zu+74/97x2z2u+5554xyz2u+75/47y2z2u-68/77xz3u+15754yz3u-7/51z4u-53/98x3u2+9699x2yu2-9/104xy2u2+64/87y3u2-95/4x2zu2-595xyzu2+4/19y2zu2-18/95xz2u2-13449yz2u2+2931z3u2-11155x2u3-83/29xyu3+7830y2u3+108/91xzu3+13161yzu3+37/42z2u3-16/79xu4-10604yu4-15832zu4+40/39u5-6020x4v+910x3yv+13/110x2y2v+7/86xy3v-97/101y4v-3286x3zv+80/91x2yzv+12467xy2zv+115/99y3zv+79/60x2z2v-8/19xyz2v+105/71y2z2v+60/119xz3v-71/15yz3v+15272z4v-7397x3uv+125/7x2yuv-9507xy2uv+5301y3uv-5605x2zuv-32/35xyzuv-5523y2zuv+67/88xz2uv+15144yz2uv+3/8z3uv-33/56x2u2v+37/29xyu2v+49/19y2u2v-10604xzu2v+37/44yzu2v-8754z2u2v+4184xu3v-56/89yu3v-23/32zu3v+74/101u4v-23/123x3v2-13803x2yv2+54/95xy2v2+9751y3v2+55/119x2zv2+75/32xyzv2+10091y2zv2+1108xz2v2-13283yz2v2+98/111z3v2+5/109x2uv2+28/79xyuv2-95/6y2uv2-7880xzuv2-12659yzuv2+14820z2uv2+4279xu2v2+79/51yu2v2-67/49zu2v2+11207u3v2+85/54x2v3-78/43xyv3-3/95y2v3-86/65xzv3+1/114yzv3+27/74z2v3-102/31xuv3-11/59yuv3-33/29zuv3-3/110u2v3-8455xv4+77/100yv4-6225zv4-70/9uv4-10939v5,-7698x5-16/39x4y+51/61x3y2+59/33x2y3+12841xy4-11040y5+14163x4z-79/55x3yz-83/18x2y2z+121/67xy3z+52/35y4z+26/15x3z2+12770x2yz2-67/15xy2z2-12895y3z2-11/16x2z3-82/45xyz3+2446y2z3+116/9xz4+6/61yz4+83/98z5+9973x4u+67/101x3yu+25/19x2y2u+7517xy3u-59/117y4u-1/86x3zu-10/119x2yzu+2552xy2zu-2448y3zu-112/45x2z2u+35/71xyz2u+12328y2z2u+124/65xz3u-15531yz3u-39/16z4u+4678x3u2-44/103x2yu2-9303xy2u2+59/20y3u2-45/97x2zu2+2707xyzu2+65/61y2zu2+75/68xz2u2+2853yz2u2-12748z3u2-17/18x2u3-115/121xyu3+72/71y2u3-12194xzu3-14204yzu3-63/17z2u3+5772xu4-99/16yu4-51/43zu4+49/43u5-2588x4v+89/44x3yv+32/107x2y2v-117/76xy3v-84/115y4v+113/30x3zv-13/68x2yzv+15120xy2zv-59/28y3zv+61/52x2z2v+12390xyz2v+11436y2z2v+109/40xz3v+40/61yz3v+65/31z4v+12764x3uv+15885x2yuv-11299xy2uv-113/66y3uv+2887x2zuv-918xyzuv+12579y2zuv+39/10xz2uv-119/53yz2uv-62/115z3uv-10887x2u2v+115/122xyu2v-8863y2u2v-30/79xzu2v-26/5yzu2v+15294z2u2v-15701xu3v-11/19yu3v+25/14zu3v-48/55u4v+1341x3v2-4973x2yv2+55/117xy2v2-1787y3v2-115/57x2zv2+28/29xyzv2-184y2zv2+11738xz2v2-8375yz2v2-5962z3v2+52/55x2uv2+17/48xyuv2-103/52y2uv2-53/25xzuv2-101/3yzuv2-123/35z2uv2-14815xu2v2-103/14yu2v2-68/81zu2v2-81/22u3v2-121/56x2v3-12609xyv3+5555y2v3+8/17xzv3-741yzv3-73/103z2v3-12550xuv3-17/78yuv3+7817zuv3+6534u2v3-15384xv4+1807yv4-4677zv4-101/115uv4-83/19v5,-53/83x5+107/75x4y+26/51x3y2+45/109x2y3-3009xy4-27/61y5+16/85x4z-14859x3yz-20/27x2y2z+6326xy3z-4508y4z-10006x3z2-11979x2yz2+8579xy2z2+14669y3z2+67/79x2z3-2551xyz3-61/124y2z3+83/10xz4+12698yz4+15/113z5+123/86x4u-77/6x3yu+15113x2y2u+79/117xy3u-115/88y4u+101/95x3zu+56/13x2yzu-25/62xy2zu+1955y3zu+70/33x2z2u+7470xyz2u-2148y2z2u-14263xz3u-3962yz3u+47/35z4u+441x3u2+14944x2yu2-2/77xy2u2+68/23y3u2-121/43x2zu2-14321xyzu2-35/32y2zu2+34/21xz2u2+11645yz2u2+7131z3u2-3615x2u3-2748xyu3-15200y2u3+81/101xzu3+39/64yzu3-3967z2u3-10346xu4+55/18yu4-8/9zu4+33/68u5-13957x4v+31/116x3yv+58/81x2y2v+36/71xy3v-5706y4v-95/48x3zv+3214x2yzv+14729xy2zv+71/109y3zv+15365x2z2v-5109xyz2v-20/107y2z2v-6/11xz3v+74/55yz3v-76/11z4v+41/72x3uv+7215x2yuv-18/59xy2uv+1741y3uv+7698x2zuv-7299xyzuv+12127y2zuv+7/93xz2uv+71/8yz2uv-123/73z3uv+13657x2u2v-98/13xyu2v+11818y2u2v+22/23xzu2v-3038yzu2v+68/61z2u2v-7173xu3v-7460yu3v+3540zu3v+27/20u4v-37/41x3v2+20x2yv2+107/82xy2v2-2237y3v2+9827x2zv2+124/27xyzv2-18/5y2zv2-77/24xz2v2-10231yz2v2-32/7z3v2-11980x2uv2-36/35xyuv2+8618y2uv2+3174xzuv2-123/2yzuv2-117/38z2uv2+117/115xu2v2+70/3yu2v2-3144zu2v2+815u3v2-116/85x2v3+98/41xyv3-648y2v3-38/5xzv3-9/125yzv3+8710z2v3+48/31xuv3+101/109yuv3+70/11zuv3-51/4u2v3-76/59xv4-93/52yv4+15291zv4+4/55uv4+64/59v5,568x5+4355x4y+48/5x3y2+33/7x2y3-53/111xy4+1749y5-23/4x4z-98/69x3yz-47/56x2y2z-8519xy3z-5/113y4z+11488x3z2+79/21x2yz2+11/89xy2z2-64/83y3z2-15697x2z3-67/86xyz3+11545y2z3+3336xz4-106/39yz4+15466z5+15202x4u-34/63x3yu-121/72x2y2u+1/52xy3u+10800y4u+4993x3zu-55/112x2yzu-26/51xy2zu-114/125y3zu+113/2x2z2u-87/88xyz2u-91/107y2z2u-65/6xz3u+15415yz3u+1373z4u-27/86x3u2-76/93x2yu2+9/22xy2u2+16/91y3u2+10326x2zu2-61/84xyzu2-28/99y2zu2+87/14xz2u2-88/45yz2u2+60/59z3u2-13/60x2u3-10824xyu3-121/119y2u3+14919xzu3-81/25yzu3+11233z2u3+14676xu4-8474yu4+12211zu4+32/83u5+57/52x4v+10/13x3yv-277x2y2v-6961xy3v-4594y4v-13439x3zv-1/30x2yzv-118/43xy2zv-62/15y3zv+76/15x2z2v+3805xyz2v-26/15y2z2v+3081xz3v+662yz3v+13856z4v+107/30x3uv+6063x2yuv+100/37xy2uv+110/107y3uv-10346x2zuv-67/44xyzuv-93/29y2zuv+17/89xz2uv-57/104yz2uv-68/91z3uv+3804x2u2v-75/107xyu2v-11842y2u2v-103/57xzu2v-37/18yzu2v+10795z2u2v-90/31xu3v+14200yu3v+97/124zu3v+5256u4v+52/101x3v2-94/107x2yv2-12841xy2v2+77/72y3v2+93/74x2zv2+7033xyzv2+87/76y2zv2-15415xz2v2-15164yz2v2-14749z3v2+86/53x2uv2+14707xyuv2+9443y2uv2+118/5xzuv2-81/2yzuv2+43/57z2uv2+59/83xu2v2-121/79yu2v2+4449zu2v2-50/63u3v2+79/31x2v3+95/32xyv3+125/107y2v3-9165xzv3+3151yzv3+5006z2v3+45/19xuv3-5194yuv3-82/11zuv3+121/15u2v3-10265xv4-99/118yv4-3162zv4-16/29uv4-37/4v5;TestGRRes(Name, I); kill R, Name, @p; ""; string Name = "k3.d11.g11.ss0"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = 38/41x4y+116/67x3y2+6547x2y3-50/71xy4+13/89y5+63/22x4z-12151x3yz-3400x2y2z-52/45xy3z+9027y4z+5420x3z2+6983x2yz2-3285xy2z2-47/2y3z2-137x2z3+40/51xyz3+111/40y2z3-97/93xz4+918yz4-7492z5-122/49x4u-123/47x3yu-95/32x2y2u-83/36xy3u-125/77y4u-9824x3zu-51/115x2yzu-83/18xy2zu-19/20y3zu-117/98x2z2u+885xyz2u-20/97y2z2u+69/55xz3u-11/82yz3u+93/47z4u-97/113x3u2-83/48x2yu2+12868xy2u2-4932y3u2-97/114x2zu2-121/116xyzu2-79/108y2zu2-27/68xz2u2+116/19yz2u2+10019z3u2-6268x2u3+5/31xyu3+13810y2u3-120/37xzu3-33/124yzu3-31/41z2u3+79/50xu4+71/59yu4+110/81zu4-27/53u5-12764x4v-7/22x3yv+15253x2y2v-67/29xy3v+15620y4v-1202x3zv+56/57x2yzv-99xy2zv-29/28y3zv-15010x2z2v-101/16xyz2v+11110y2z2v+7300xz3v+58/95yz3v+10228z4v+65/57x3uv+9/2x2yuv+116/27xy2uv+7960y3uv-11/8x2zuv+59/23xyzuv+19/26y2zuv+14327xz2uv-14671yz2uv+126/101z3uv+69/83x2u2v+14041xyu2v-73/90y2u2v+11/108xzu2v-5492yzu2v-3858z2u2v-2840xu3v+15365yu3v+28/113zu3v+149u4v-94/85x3v2-32/123x2yv2-1409xy2v2-8233y3v2+851x2zv2-7458xyzv2-10713y2zv2-18/11xz2v2-15/47yz2v2-32/97z3v2+39/68x2uv2-10832xyuv2+39/59y2uv2-12211xzuv2+66/71yzuv2+121/115z2uv2-65/101xu2v2+82/11yu2v2-78/103zu2v2-10128u3v2-100/33x2v3-29/28xyv3+61/29y2v3-5266xzv3+1953yzv3+5799z2v3+13/77xuv3-2680yuv3-57/98zuv3+56/125u2v3+121/42xv4+47/111yv4+2590zv4-60/53uv4+43/61v5,8057x5+3453x4y-71/57x3y2+14017x2y3+89/28xy4-15/44y5+10785x4z-14385x3yz-112/31x2y2z+29/42xy3z+162y4z-12837x3z2+31/33x2yz2+105/74xy2z2+97/59y3z2-23/61x2z3-246xyz3+65/93y2z3+1/54xz4+6/25yz4+96x4u-41/74x3yu+15120x2y2u-1465xy3u-47/42y4u+11/80x3zu-84/55x2yzu+12120xy2zu+84/65y3zu+496x2z2u-29/24xyz2u+3753y2z2u-2608xz3u+11/123yz3u+7955z4u-11390x3u2+37/79x2yu2+3230xy2u2-72/83y3u2-87/74x2zu2-11620xyzu2+8276y2zu2+608xz2u2-7002yz2u2-7897z3u2-65/97x2u3-37/3xyu3+7/43y2u3+37/20xzu3+97/28yzu3+98/19z2u3-47/45xu4-49/109yu4-53/89zu4-66/125u5+7516x4v-1097x3yv+15928x2y2v-12128xy3v-12988y4v-23/7x3zv+5146x2yzv+9/28xy2zv-1816y3zv+115/42x2z2v+11840xyz2v+40/119y2z2v-66/85xz3v-8269yz3v-59/45z4v-114/37x3uv-126/55x2yuv-31/24xy2uv-19/9y3uv+77/3x2zuv+14268xyzuv-4133y2zuv-11603xz2uv-55/83yz2uv-5/61z3uv-13069x2u2v+4387xyu2v+94/77y2u2v-111/79xzu2v-31/61yzu2v-26/53z2u2v-13/103xu3v-27/91yu3v-100/57zu3v-104/111u4v+77/15x3v2+100/69x2yv2-1664xy2v2+14971y3v2-67/45x2zv2-55/27xyzv2+13/98y2zv2-958xz2v2+3/68yz2v2+34/65z3v2+10771x2uv2+19/106xyuv2-84/125y2uv2+4723xzuv2-10707yzuv2+50/103z2uv2+1766xu2v2+110/3yu2v2-58/51zu2v2-16/105u3v2-70/111x2v3+83/103xyv3-104/83y2v3-2394xzv3+91/109yzv3-11779z2v3+111/80xuv3+41/109yuv3+71/77zuv3+110/31u2v3+8933xv4-109/113yv4-56/87zv4-120/7uv4-107/57v5,-38/41x5-116/67x4y-6547x3y2+50/71x2y3-13/89xy4-43/79x4z+1342x3yz+14316x2y2z+737xy3z+15/44y4z+124/79x3z2-67/13x2yz2+79/104xy2z2-162y3z2-109/120x2z3+4540xyz3-97/59y2z3+3772xz4-65/93yz4-6/25z5-13041x4u-90/89x3yu+107/36x2y2u+43/46xy3u-11755y4u+12017x3zu-97/58x2yzu+5592xy2zu-11967y3zu+24/79x2z2u-63/83xyz2u-7367y2z2u-62/79xz3u+55/64yz3u-67/18z4u-672x3u2+19/77x2yu2-100/63xy2u2-23/56y3u2+61/78x2zu2+120/67xyzu2+48/107y2zu2+5855xz2u2+9877yz2u2+6940z3u2+12754x2u3+12989xyu3-123/106y2u3+59/88xzu3-3400yzu3-8976z2u3+43/21xu4-86/111yu4+2/29zu4+57/31u5+79/48x4v+95/56x3yv+3056x2y2v-13681xy3v+13735y4v-122/91x3zv+79/74x2yzv+21/47xy2zv+12060y3zv-12314x2z2v+64/17xyz2v-57/52y2z2v-57/86xz3v+15436yz3v+9387z4v+3345x3uv+2/109x2yuv-13978xy2uv+5604y3uv+11645x2zuv+2633xyzuv+15505y2zuv+10/99xz2uv+14409yz2uv+8127z3uv+99/104x2u2v+14440xyu2v+37/43y2u2v-9707xzu2v+9171yzu2v-656z2u2v+3723xu3v+4/19yu3v+109/76zu3v-8740u4v+2121x3v2+34/11x2yv2-89/61xy2v2-26/21y3v2+111/22x2zv2+88/41xyzv2+119/99y2zv2+108/77xz2v2+9279yz2v2-45/116z3v2+71/107x2uv2+25/76xyuv2-112/121y2uv2-18/71xzuv2-84/125yzuv2+496z2uv2+96/113xu2v2-964yu2v2-73/4zu2v2+103/95u3v2+9962x2v3+38/39xyv3-15120y2v3+11747xzv3+2/123yzv3+14829z2v3-6538xuv3-52/63yuv3-83/107zuv3+73/37u2v3-4183xv4+11/103yv4+83/119zv4+94/31uv4-19/98v5,-12092x5-2411x4y+3922x3y2+117/41x2y3+95/22xy4+45/19x4z-5881x3yz+97/80x2y2z-4981xy3z-21/67y4z+9068x3z2+1/11x2yz2-109/65xy2z2+22/117y3z2-7823x2z3-76/75xyz3-34/25y2z3-79/5xz4-60/37yz4-87/100z5+58/83x4u-36/61x3yu+79/76x2y2u+502xy3u+4988y4u+43/38x3zu-4/107x2yzu-48/11xy2zu+11685y3zu-15002x2z2u-97/17xyz2u+93/2y2z2u-35/71xz3u+43/83yz3u-69/26z4u+119/6x3u2-87/14x2yu2-29/109xy2u2-36/97y3u2-116/119x2zu2+4610xyzu2-33/58y2zu2+121/25xz2u2-125/121yz2u2-35/121z3u2-8975x2u3+9014xyu3+14845y2u3-10277xzu3+75/124yzu3-10/83z2u3-73/69xu4+46/85yu4-4971zu4-113/4u5+9321x4v+109/19x3yv+11/17x2y2v+6672xy3v+16/99y4v+8092x3zv+1725x2yzv+80/41xy2zv+2445y3zv+4/99x2z2v+69/101xyz2v+13182y2z2v-10090xz3v+3817yz3v+106/79z4v-71/89x3uv+110/107x2yuv-56/19xy2uv-708y3uv-108/97x2zuv-11889xyzuv+9744y2zuv-24/121xz2uv-10711yz2uv+3182z3uv-22/35x2u2v+81/44xyu2v-40/31y2u2v-13494xzu2v+47/80yzu2v+71/52z2u2v-6214xu3v-5144yu3v-115/49zu3v-109/19u4v+8621x3v2-62/79x2yv2-102/103xy2v2-8174y3v2+13689x2zv2+15544xyzv2-107/73y2zv2+120/73xz2v2+19/56yz2v2-4544z3v2-824x2uv2-2/17xyuv2+67/78y2uv2-54/85xzuv2+31/51yzuv2-59/19z2uv2+50/7xu2v2+5762yu2v2+79/64zu2v2-3729u3v2+12212x2v3+1833xyv3+12543y2v3+11974xzv3-11/17yzv3-75/74z2v3+26/3xuv3-37/36yuv3-7683zuv3+14069u2v3+12261xv4+12489yv4+1657zv4+10781uv4-46/3v5,12092x4z+2411x3yz-3922x2y2z-117/41xy3z-95/22y4z+11164x3z2+6625x2yz2+112/75xy2z2+1533y3z2+60/101x2z3-173xyz3+15913y2z3+14954xz4-5022yz4+12391z5-38/41x4u-116/67x3yu-6547x2y2u+50/71xy3u-13/89y4u-12/55x3zu-10086x2yzu+6782xy2zu-111/89y3zu-52/85x2z2u+9744xyz2u+9553y2z2u-15590xz3u+76/13yz3u+5938z4u+42/11x3u2-25/116x2yu2+2554xy2u2-12842y3u2-3/88x2zu2+102/113xyzu2-10298y2zu2-32/69xz2u2+9709yz2u2+8775z3u2-9937x2u3+5128xyu3-56/75y2u3+12493xzu3-7/39yzu3-41/24z2u3-125/49xu4-15745yu4-1005zu4+16/55u5-7566x3zv+14010x2yzv+51/23xy2zv+37/113y3zv+9/14x2z2v+2251xyz2v+10076y2z2v-106/69xz3v-4060yz3v+3379z4v-11120x3uv-9744x2yuv+50/17xy2uv+7065y3uv-70/37x2zuv+10016xyzuv+47/86y2zuv+6928xz2uv-11190yz2uv-11611z3uv+15042x2u2v-52/105xyu2v+2185y2u2v-76/67xzu2v-57/104yzu2v-7610z2u2v-3912xu3v+1/48yu3v-24/109zu3v+3287u4v+17/96x2zv2+29/76xyzv2+15768y2zv2+8410xz2v2-116/41yz2v2+89/48z3v2+15119x2uv2-11840xyuv2-89/43y2uv2+10115xzuv2+93/101yzuv2+33/62z2uv2+11864xu2v2-14582yu2v2+95/53zu2v2-8816u3v2+35/43xzv3+75/107yzv3+13515z2v3-38/67xuv3+83/71yuv3+113/51zuv3-80/111u2v3+49/5zv4+13850uv4,14959x5-3/13x4y+97/37x3y2+14586x2y3-71/120xy4-10158x4z+59/50x3yz-101/96x2y2z+118/47xy3z-65/83y4z+49/66x3z2-107/18x2yz2-2/47xy2z2+104/63y3z2-121/43x2z3+9552xyz3-113/36y2z3+4699xz4+55/53yz4+16/109z5-3576x4u-103/52x3yu-8299x2y2u+1585xy3u+3377y4u+15336x3zu-119/24x2yzu-19/68xy2zu-65/11y3zu-17/117x2z2u+788xyz2u+73/115y2z2u-46/93xz3u-108/7yz3u+3774z4u-14034x3u2-15420x2yu2-5128xy2u2+83/55y3u2+17/5x2zu2+13098xyzu2+96/29y2zu2-54/115xz2u2+4/5yz2u2+2747z3u2+56/83x2u3-1545xyu3+14384y2u3+7787xzu3-69/64yzu3-27/20z2u3-17/15xu4+46/13yu4-44/41zu4-14876u5+10090x4v+184x3yv+125/44x2y2v-13987xy3v+104/123y4v+24/35x3zv+77/95x2yzv+162xy2zv+31/113y3zv-94/51x2z2v-14750xyz2v-110/101y2z2v+3224xz3v-12389yz3v-77/57z4v-7340x3uv+48/79x2yuv-55/71xy2uv-65/57y3uv+13981x2zuv+76/73xyzuv-41/22y2zuv-10847xz2uv+3230yz2uv+37/14z3uv+64/47x2u2v-89/97xyu2v-608y2u2v-93/112xzu2v-22yzu2v+7158z2u2v-120/31xu3v-13481yu3v-97/37zu3v-113/87u4v-35/19x3v2+79/53x2yv2-1037xy2v2-29/63y3v2+5990x2zv2-3380xyzv2-17/126y2zv2-40/121xz2v2-15041yz2v2+3779z3v2+13583x2uv2+11/73xyuv2+2762y2uv2-16/49xzuv2-40/93yzuv2-37/75z2uv2+13312xu2v2+4407yu2v2+5449zu2v2+3013u3v2+86/73x2v3-37/66xyv3-73/15y2v3+75/107xzv3-63/31yzv3-97/99z2v3+11234xuv3+37/92yuv3+47/27zuv3+121/26u2v3-15690xv4+73/40yv4-12281zv4+6014uv4-92/83v5,-12092x4y-2411x3y2+3922x2y3+117/41xy4+95/22y5+14327x4z+3699x3yz+18/85x2y2z-56/53xy3z-31/16y4z+5371x3z2+73/69x2yz2+65/34xy2z2-59/49y3z2+23/37x2z3-9067xyz3+79/37y2z3-17/50xz4+8412yz4+110/39z5-36/125x4u-20/51x3yu-28/123x2y2u-4482xy3u+4217y4u+8/19x3zu+9/77x2yzu-10526xy2zu+76/79y3zu-12494x2z2u-50/13xyz2u-98/123y2z2u-23/19xz3u+1491yz3u-50/109z4u-67/62x3u2+68/47x2yu2-38/99xy2u2-4891y3u2+68/113x2zu2-73/35xyzu2-2384y2zu2+71/109xz2u2-68/39yz2u2-94/125z3u2+120/121x2u3-20/39xyu3+435y2u3-23/14xzu3-39/97yzu3+75/23z2u3+71/30xu4-8426yu4+125/7zu4+11/46u5-2334x4v+9113x3yv-1060x2y2v+12839xy3v+9876y4v-8395x3zv-79/82x2yzv+89/79xy2zv+805y3zv-7473x2z2v+80/89xyz2v+105/52y2z2v-54/103xz3v-2102yz3v+19/117z4v-1326x3uv-8963x2yuv-12/13xy2uv+11798y3uv-80/7x2zuv+519xyzuv-58/67y2zuv+14572xz2uv+8426yz2uv-66/47z3uv-574x2u2v+12480xyu2v-41/89y2u2v-111/83xzu2v-58/37yzu2v-15255z2u2v+31/97xu3v-89/113yu3v+15475zu3v-3982u4v+51/8x3v2+9547x2yv2-8060xy2v2-195y3v2-5/21x2zv2-2411xyzv2+65/12y2zv2-5410xz2v2+3844yz2v2+3/61z3v2-62/101x2uv2+53/19xyuv2-6567y2uv2+11302xzuv2+123/37yzuv2-107/118z2uv2-29/79xu2v2-91/40yu2v2+40/99zu2v2-12274u3v2-47/124x2v3+12752xyv3+11039y2v3-115/43xzv3+44/79yzv3-37/28z2v3+5364xuv3+14510yuv3+3024zuv3-40/3u2v3+71/122xv4+12024yv4+10/93zv4-4183uv4+11229v5,-51/74x4y-99/61x3y2-10442x2y3+6943xy4-15040y5+126/97x4z+101/41x3yz+4018x2y2z+98/61xy3z+87/34y4z+75/52x3z2-109/70x2yz2-81/71xy2z2+8231y3z2+78/49x2z3+53/69xyz3+70/71y2z3+48/23xz4-6678yz4+14913z5-32/97x4u+78/55x3yu+11669x2y2u-58/75xy3u-61/64y4u+118/35x3zu-125/28x2yzu-125/79xy2zu-49/23y3zu-14966x2z2u-34/19xyz2u-53/126y2z2u+13854xz3u-2177yz3u+9962z4u+15886x3u2+47/38x2yu2+10992xy2u2-111/31y3u2-79/21x2zu2-14524xyzu2-3442y2zu2-45/86xz2u2+53/3yz2u2+8738z3u2+9062x2u3+3872xyu3+56/61y2u3-6255xzu3-104/107yzu3+9858z2u3+7891xu4-11114yu4+67/37zu4-15307u5-108/7x4v+11586x3yv+19/4x2y2v+14404xy3v-99/116y4v+124/33x3zv-73/17x2yzv+77/115xy2zv-4537y3zv+9949x2z2v+101/111xyz2v+6634y2z2v-11818xz3v+23/52yz3v-63z4v+7/6x3uv-13686x2yuv+15879xy2uv+4731y3uv+107/82x2zuv+104/119xyzuv-56/67y2zuv-21/5xz2uv-24/41yz2uv-125/108z3uv+58/77x2u2v+79/49xyu2v+82/19y2u2v-82/117xzu2v-8/61yzu2v+210z2u2v+27/25xu3v+71/111yu3v-14500zu3v-15/2u4v-113/108x3v2+40/31x2yv2+89/69xy2v2-8271y3v2+111/20x2zv2+1/31xyzv2-51/101y2zv2+3967xz2v2+79/32yz2v2-6893z3v2-1060x2uv2+38/5xyuv2+21/20y2uv2-79/34xzuv2+15/118yzuv2+25/106z2uv2+97/20xu2v2+6/67yu2v2+113/120zu2v2+13/3u3v2+1800x2v3-97/15xyv3-12712y2v3+49/118xzv3+5/63yzv3+234z2v3-97/123xuv3+13/88yuv3+8/103zuv3-38/97u2v3-15634xv4+18/25yv4-7517zv4+115/103uv4-56/23v5,-123/61x5+4/87x4y-15558x3y2+78/5x2y3-31/83xy4+9742x4z+23/125x3yz+1865x2y2z+56/125xy3z-4/33y4z-54/71x3z2-113/84x2yz2+37/75xy2z2+6/23y3z2-28/123x2z3+31/112xyz3-15736y2z3-106/111xz4+46/109yz4-29/10z5-28/117x4u+15892x3yu+8096x2y2u-91/29xy3u+57/92y4u+96/31x3zu+166x2yzu+2654xy2zu-11662y3zu+1565x2z2u+9017xyz2u+121/4y2z2u-29/115xz3u+9828yz3u-15873z4u-5354x3u2+118/19x2yu2+88/95xy2u2+68/19y3u2-7/110x2zu2-109/37xyzu2-45/74y2zu2+12579xz2u2-6659yz2u2+10257z3u2+7229x2u3+39/67xyu3-108/19y2u3-58/9xzu3-29/81yzu3-1461z2u3+23/43xu4-8/19yu4-44zu4+100/109u5+121/51x4v-20/39x3yv-85/121x2y2v+73/61xy3v+103/50y4v+7334x3zv+52/125x2yzv-14/55xy2zv+106/103y3zv-4079x2z2v+109/57xyz2v+123/28y2z2v-21/83xz3v+3/31yz3v-9826z4v+89/77x3uv-79/35x2yuv+8767xy2uv+83/11y3uv+113/36x2zuv-57/68xyzuv+1675y2zuv+10873xz2uv+84/11yz2uv+89/110z3uv-5834x2u2v-121/97xyu2v+49/66y2u2v-103/95xzu2v+14863yzu2v+119/94z2u2v+44/35xu3v-15429yu3v-9302zu3v-73/12u4v-77/86x3v2-121/46x2yv2+48/13xy2v2+68/115y3v2+58/63x2zv2+58/117xyzv2-16/7y2zv2-76/39xz2v2+41/103yz2v2-8042z3v2-59/5x2uv2+3277xyuv2-120/107y2uv2-5/84xzuv2-30/103yzuv2+31/71z2uv2-1593xu2v2-4668yu2v2+5749zu2v2+38/43u3v2+26/17x2v3+1894xyv3+62/17y2v3-4851xzv3-10816yzv3+62/55z2v3+1366xuv3-70/11yuv3+90/43zuv3-115/57u2v3-10886xv4+1987yv4-78/25zv4+110/29uv4+4694v5,47/12x5+64/29x4y-113/70x3y2+15185x2y3-52/81xy4+67/28x4z-4220x3yz-9239x2y2z+10/117xy3z-5609y4z-4439x3z2-61/91x2yz2+15282xy2z2+8165y3z2-19/109x2z3+123/94xyz3+62/49y2z3+77/2xz4-1/37yz4-1202z5-14940x4u+13396x3yu-6/5x2y2u-91/50xy3u+115/118y4u-455x3zu-2755x2yzu+14353xy2zu+11/53y3zu+115/57x2z2u+86/49xyz2u+43y2z2u+5247xz3u+4438yz3u+109/16z4u-3113x3u2-15629x2yu2-15664xy2u2-115/57y3u2+3/103x2zu2-3723xyzu2+89/17y2zu2-59/56xz2u2+19/123yz2u2+43/14z3u2+103/14x2u3+106/31xyu3-13591y2u3-71/43xzu3+74/119yzu3-36/113z2u3-73/96xu4-31/120yu4-105/76zu4-37/34u5-58/23x4v-11111x3yv+5888x2y2v+14867xy3v+8608y4v-2829x3zv-31/120x2yzv+6306xy2zv+5913y3zv+35/6x2z2v+75/104xyz2v+33/41y2z2v-15317xz3v-31/49yz3v-7300z4v+2214x3uv-91/46x2yuv+10949xy2uv-3/82y3uv-16/27x2zuv-14175xyzuv-13/19y2zuv-21/65xz2uv+148yz2uv+14615z3uv-43/6x2u2v-4133xyu2v+33/49y2u2v-1299xzu2v+96/53yzu2v-12667z2u2v-86/113xu3v+10437yu3v-53/13zu3v-15678u4v-53/121x3v2-20/49x2yv2+3813xy2v2+10006y3v2+15644x2zv2-99/7xyzv2-42/13y2zv2-124/57xz2v2+73/70yz2v2+110/107z3v2-97/22x2uv2-125/116xyuv2+92/93y2uv2-12120xzuv2+143yzuv2-15344z2uv2+13225xu2v2+17/104yu2v2+1212zu2v2-7685u3v2-81/4x2v3+10328xyv3-21/19y2v3+13407xzv3-1/118yzv3+59/88z2v3+965xuv3-93/43yuv3-76/85zuv3-81/86u2v3-6949xv4+9205yv4-7777zv4+15020uv4+8845v5,3079x5-28/11x4y+117/88x3y2-89/115x2y3+40/13xy4+13407y5+3942x4z+30/121x3yz-2922x2y2z-71/74xy3z-103/114y4z-89/59x3z2+12255x2yz2+44/109xy2z2+13778y3z2+103/110x2z3-73/95xyz3+8049y2z3+10042xz4-101/35yz4-1636z5-53/27x4u+130x3yu-5989x2y2u+67/109xy3u+4601y4u-12943x3zu-86/75x2yzu+5837xy2zu+107/104y3zu+2396x2z2u-25/58xyz2u+29/110y2z2u+10526xz3u-7/45yz3u-9105z4u-64/35x3u2+64/105x2yu2+113/24xy2u2-5955y3u2+20/91x2zu2+119/78xyzu2+83/8y2zu2+125/103xz2u2+83/101yz2u2+14895z3u2-118/93x2u3-19/23xyu3+100/53y2u3-92/59xzu3+34/89yzu3+9417z2u3-6626xu4-36/65yu4+119/82zu4+8761u5-15340x4v-89/115x3yv+89/85x2y2v+33/74xy3v-8088y4v+29/16x3zv-6581x2yzv-88/85xy2zv-12/11y3zv-58/19x2z2v+12219xyz2v-100/119y2z2v+116/53xz3v-67/94yz3v+13/5z4v+236x3uv+107/96x2yuv+115/113xy2uv-7860y3uv+15064x2zuv+29/59xyzuv-7/103y2zuv-71/66xz2uv-103/79yz2uv-83/4z3uv-77/23x2u2v+7/37xyu2v+106/103y2u2v+3/50xzu2v+125/17yzu2v-15620z2u2v+6424xu3v-12832yu3v+58/53zu3v-3893u4v+25/124x3v2-99/61x2yv2-61/10xy2v2-103/39y3v2-9764x2zv2+123/23xyzv2-83/126y2zv2+13541xz2v2+73/106yz2v2+1172z3v2-14333x2uv2+7/72xyuv2-41/25y2uv2-42/31xzuv2+7/12yzuv2-9744z2uv2-15518xu2v2-121/5yu2v2-7/115zu2v2+75/14u3v2-9/67x2v3+10248xyv3+5738y2v3+71/13xzv3-43/24yzv3+9/94z2v3-113/16xuv3-27/25yuv3-50/11zuv3+41/49u2v3+10896xv4-46/43yv4-58/15zv4-5671uv4-61/9v5,6254x5-95/34x4y-7133x3y2+111/38x2y3-43/19xy4-104/111y5+92/51x4z+11826x3yz+3453x2y2z+5703xy3z+13099y4z-73/79x3z2-69/11x2yz2-15727xy2z2+98/115y3z2-10548x2z3-14452xyz3-5138y2z3-138xz4+46/109yz4-5419z5+73/6x4u-63/5x3yu+31/60x2y2u-11963xy3u+6161y4u-2311x3zu+104/105x2yzu+10873xy2zu+8165y3zu-17/83x2z2u-18/91xyz2u+13544y2z2u+36/121xz3u-8704yz3u+46/7z4u+11392x3u2+133x2yu2+7460xy2u2+8831y3u2+144x2zu2-79/47xyzu2-70/113y2zu2+7369xz2u2-11234yz2u2-19/52z3u2+9830x2u3+13/41xyu3+1985y2u3-22/15xzu3-5449yzu3+5967z2u3+9321xu4+13078yu4-97/3zu4+4079u5-5700x4v+5013x3yv-10774x2y2v-13183xy3v-20/109y4v-106/65x3zv+49/117x2yzv-67/17xy2zv-13917y3zv+9457x2z2v+95/67xyz2v-108/65y2z2v+65/77xz3v-11235yz3v+125/104z4v+17/117x3uv+6355x2yuv+5/36xy2uv-117/31y3uv-1225x2zuv+117/53xyzuv-7/26y2zuv+87/46xz2uv+33/76yz2uv-82/73z3uv-34/39x2u2v+9/22xyu2v+83/11y2u2v+13740xzu2v-108/11yzu2v-9627z2u2v-32/95xu3v-7966yu3v-12400zu3v-111/91u4v+47/11x3v2-10/27x2yv2-5257xy2v2-85/19y3v2-3/62x2zv2+12660xyzv2-37/110y2zv2+10980xz2v2+73/29yz2v2+87/92z3v2-73/90x2uv2-77/25xyuv2+66/31y2uv2-23/96xzuv2-3169yzuv2+125/71z2uv2+9/11xu2v2+6550yu2v2-15163zu2v2+10810u3v2+96/79x2v3+196xyv3-95/94y2v3+15146xzv3+14695yzv3+97/80z2v3+13047xuv3-44/79yuv3-43/41zuv3+40/57u2v3-8369xv4+12/5yv4+77/100zv4-53/79uv4-53/86v5,-122/49x5-3959x4y-7277x3y2+41/93x2y3+39/59xy4-91/68x4z+37/11x3yz+11561x2y2z-5297xy3z+53/14y4z-17/122x3z2+5470x2yz2+14889xy2z2-123/49y3z2+131x2z3+13/43xyz3-82/37y2z3-106/91xz4+11066yz4-72/13z5+15904x4u+44/47x3yu+10450x2y2u+86/41xy3u-40/41y4u+17/92x3zu-81/29x2yzu-40/101xy2zu+103/59y3zu-29/72x2z2u+17/123xyz2u+38/3y2z2u+3358xz3u-69/97yz3u+7627z4u+15451x3u2+5371x2yu2-9009xy2u2-62/35y3u2-44/75x2zu2+13188xyzu2+50/51y2zu2+53/93xz2u2-6796yz2u2-13/6z3u2+39/62x2u3-22/71xyu3-32/97y2u3+43/14xzu3-9/37yzu3-48/125z2u3+100/103xu4+13286yu4+6246zu4-26/107u5-15634x4v+112/9x3yv+54/109x2y2v+23/93xy3v+101/13y4v+79/84x3zv+5290x2yzv-52/29xy2zv-109/111y3zv+107/88x2z2v+10186xyz2v+122/97y2z2v-8370xz3v-108/47yz3v+6311z4v-1126x3uv+51/10x2yuv+9201xy2uv-111/119y3uv+105/58x2zuv-74/23xyzuv-130y2zuv-99/28xz2uv+24/65yz2uv-111/49z3uv-4961x2u2v-23/42xyu2v-32/101y2u2v+48/83xzu2v-13001yzu2v-31/86z2u2v+85/91xu3v+4019yu3v-10/43zu3v+11/105u4v+9790x3v2+73/78x2yv2+63/50xy2v2+35/2y3v2-52/119x2zv2+13680xyzv2-46/55y2zv2+89/12xz2v2-23/82yz2v2-107/85z3v2-20/79x2uv2-85/111xyuv2+31/95y2uv2-13xzuv2+5661yzuv2+9399z2uv2+73/75xu2v2+4782yu2v2-5440zu2v2+45/64u3v2-1484x2v3+1/54xyv3+43/115y2v3+139xzv3-47/85yzv3-103/43z2v3+48/97xuv3+67/15yuv3-69/95zuv3-67/90u2v3+6540xv4+6276yv4-9756zv4-10/121uv4+118/63v5,x5+13/23x4y-10277x3y2-81/107x2y3+18/97xy4+193x4z-206x3yz+1473x2y2z-3907xy3z+9620y4z-11603x3z2+7430x2yz2-3745xy2z2-23/55y3z2-31/13x2z3-115/51xyz3+54/5y2z3+107/6xz4+8432yz4-23/71z5-21/79x4u-7130x3yu-55/46x2y2u+61/113xy3u+11/95y4u-31/125x3zu+47/80x2yzu+12/79xy2zu-51/112y3zu-28/75x2z2u+1962xyz2u-12942y2z2u-93/37xz3u-7/9yz3u+81/7z4u-79/62x3u2+98/29x2yu2-113/36xy2u2-59/51y3u2-5931x2zu2+8/29xyzu2-22/117y2zu2-12146xz2u2+12607yz2u2-8748z3u2-11878x2u3-6xyu3-11798y2u3+97/111xzu3+122/3yzu3+10228z2u3-99/67xu4-8058yu4+116/43zu4-6801u5-7565x4v-21/58x3yv-23/90x2y2v-111/49xy3v+62/3y4v-118/109x3zv-91/27x2yzv-2256xy2zv-6909y3zv+47/126x2z2v+397xyz2v-65/103y2z2v+106/43xz3v-43/9yz3v+4502z4v+5383x3uv-19/48x2yuv+91/92xy2uv-15545y3uv+11204x2zuv+7609xyzuv-125/44y2zuv+15/7xz2uv-4157yz2uv+27/10z3uv+70/67x2u2v+5/121xyu2v-12337y2u2v-12417xzu2v+46/113yzu2v+27/89z2u2v-9419xu3v-59/47yu3v+52/97zu3v+71/56u4v+56/123x3v2+122/73x2yv2+100/103xy2v2+43/8y3v2+99/98x2zv2-14242xyzv2-93/38y2zv2+61/109xz2v2-21/125yz2v2+80/23z3v2+11603x2uv2-1734xyuv2-55/73y2uv2+5/89xzuv2+77/100yzuv2-71/38z2uv2+41/47xu2v2+981yu2v2+11/41zu2v2-8983u3v2+98/59x2v3+105/97xyv3-6372y2v3+12829xzv3+79/96yzv3+110/57z2v3+8495xuv3-11228yuv3-2396zuv3-101/9u2v3-71/39xv4-11746yv4-43/96zv4+64/55uv4-769v5,122/49x4y+3959x3y2+7277x2y3-41/93xy4-39/59y5+32/97x4z+97/96x3yz-43/116x2y2z+19/30xy3z+18/17y4z+39/122x3z2-98/99x2yz2+23/65xy2z2-50/103y3z2-11445x2z3+111/119xyz3-82/67y2z3+49/15xz4+59/74yz4+87/124z5+97/113x3yu+59/113x2y2u-17/16xy3u-1892y4u-15886x3zu+75/124x2yzu-13/108xy2zu+14203y3zu+13871x2z2u+24xyz2u+1483y2z2u-34/91xz3u+51/29yz3u+88/107z4u+6268x2yu2+13776xy2u2+1935y3u2-9062x2zu2-4534xyzu2+9553y2zu2-8429xz2u2-11141yz2u2-89/88z3u2-79/50xyu3-121/15y2u3-7891xzu3-27/94yzu3+96/71z2u3+27/53yu4+15307zu4-775x4v-2648x3yv-2095x2y2v+7594xy3v+12989y4v-17/29x3zv+11801x2yzv+32/45xy2zv-55/73y3zv+9756x2z2v+6886xyz2v+5939y2z2v+39/23xz3v+2632yz3v+77/6z4v+36/121x3uv-76/55x2yuv+5296xy2uv-32/47y3uv-125/84x2zuv-30/67xyzuv-14914y2zuv+73/23xz2uv+123/101yz2uv+49/43z3uv-76/71x2u2v+79/50xyu2v+38/7y2u2v-5262xzu2v-5211yzu2v+2/95z2u2v-3570xu3v-9280yu3v+32/91zu3v+1089u4v-73/33x3v2-3931x2yv2-21/113xy2v2+191y3v2-93/2x2zv2-75/47xyzv2+16/115y2zv2+120/23xz2v2+23/114yz2v2-115/108z3v2-103/12x2uv2+20/107xyuv2+28/11y2uv2+23/42xzuv2-15290yzuv2+3651z2uv2-9566xu2v2-113/68yu2v2+7705zu2v2-12261u3v2+9882x2v3-8520xyv3+14858y2v3+200xzv3+14/73yzv3+45/53z2v3-4/113xuv3-11327yuv3+59/51zuv3-13869u2v3-33/29xv4-13026yv4+4236zv4+10782uv4+2817v5,-123/61x4y+4/87x3y2-15558x2y3+78/5xy4-31/83y5+10267x4z-29/21x3yz+2197x2y2z-57/98xy3z+121/31y4z-1310x3z2+9386x2yz2-37/50xy2z2-1767y3z2-489x2z3-117/31xyz3+13576y2z3-50/9xz4-47/77yz4+53/89z5-57/11x4u-8374x3yu+104/103x2y2u+29/12xy3u+7368y4u+102/37x3zu+10508x2yzu+28xy2zu-14484y3zu-240x2z2u-115/114xyz2u+97/74y2z2u+105/11xz3u+125/46yz3u-6746z4u+3454x3u2+14656x2yu2-82/111xy2u2+13130y3u2+121/58x2zu2-42/11xyzu2-89/81y2zu2+68/49xz2u2+8243yz2u2-11615z3u2-40/87x2u3+80/39xyu3+14735y2u3+10706xzu3-2448yzu3+64/51z2u3+4514xu4+658yu4-39/49zu4+21/23u5+11/105x4v-108x3yv-31/98x2y2v-73/64xy3v+205y4v-15348x3zv-13734x2yzv-52/11xy2zv+5897y3zv+106/27x2z2v+9613xyz2v+81/59y2z2v+1172xz3v+3716yz3v-3581z4v+50x3uv+81/38x2yuv+84/109xy2uv-34/69y3uv-58/35x2zuv-23/105xyzuv+43/78y2zuv-57/31xz2uv+98/37yz2uv+11/96z3uv+147x2u2v+11414xyu2v+5/96y2u2v+19/77xzu2v+1274yzu2v+4/63z2u2v-4396xu3v+7060yu3v+5044zu3v-102/121u4v+67/25x3v2-13601x2yv2+68/65xy2v2+82/77y3v2-8394x2zv2-13318xyzv2+71/104y2zv2-75/107xz2v2+39/100yz2v2+11229z3v2+113/84x2uv2-2988xyuv2-9616y2uv2-41/50xzuv2+3/34yzuv2-12322z2uv2-120/11xu2v2+4/75yu2v2+12562zu2v2-92/39u3v2+1497x2v3+80/103xyv3+15/64y2v3-16/109xzv3-85/81yzv3-52/81z2v3-23/49xuv3+1295yuv3+13460zuv3+52/73u2v3-24/5xv4+11079yv4-25/57zv4-119/47uv4-7/120v5,123/61x4z-4/87x3yz+15558x2y2z-78/5xy3z+31/83y4z-2966x3z2+73/89x2yz2+75/112xy2z2+51/29y3z2-46/47x2z3+3812xyz3-8592y2z3+7582xz4+113/92yz4-11815z5+34/111x3zu-25/63x2yzu+115/79xy2zu+36/115y3zu-17/38x2z2u+7906xyz2u-108/71y2z2u+7541xz3u-12683yz3u-111/110z4u-107/24x2zu2-70/9xyzu2+42/113y2zu2-75xz2u2+64/101yz2u2+65/106z3u2-118/97xzu3+12960yzu3-918z2u3-72/113zu4+17/73x4v+15/17x3yv-22/91x2y2v+78/121xy3v+9/77y4v-91/102x3zv+15814x2yzv-12480xy2zv+1177y3zv-7/40x2z2v+47/69xyz2v-2847y2z2v+987xz3v-1954yz3v+43/97z4v-7692x3uv-109/44x2yuv-94/111xy2uv+84/17y3uv+13682x2zuv+64/7xyzuv-13069y2zuv+92/67xz2uv-109/84yz2uv-93/56z3uv-5368x2u2v-93/101xyu2v-118/43y2u2v-40/57xzu2v-58/55yzu2v+84/19z2u2v+4/9xu3v-540yu3v+11588zu3v-93/25u4v-85/89x3v2-1800x2yv2-40/51xy2v2-7293y3v2+15927x2zv2-33/106xyzv2+25/98y2zv2-13657xz2v2+43/37yz2v2+79/115z3v2-74/11x2uv2+29/114xyuv2-50/69y2uv2+252xzuv2-65/69yzuv2-88/5z2uv2+4418xu2v2-6634yu2v2-9854zu2v2-20/73u3v2+94/11x2v3+1430xyv3+1/41y2v3+21/101xzv3-68/59yzv3-9515z2v3+55/8xuv3-12014yuv3+57/73zuv3-97/58u2v3-124/91xv4+5575yv4-5470zv4+15340uv4+123/7v5,-14327x4y-14863x3y2+3913x2y3+4595xy4+75/77y5-5371x3yz+86/123x2y2z-84/115xy3z-117/100y4z-23/37x2yz2-82/125xy2z2+2426y3z2+17/50xyz3+11188y2z3-110/39yz4-126/97x4u-85/41x3yu-22/25x2y2u-10619xy3u+3473y4u-75/52x3zu-121/37x2yzu+48/125xy2zu+7246y3zu-78/49x2z2u+106/3xyz2u-50/59y2z2u-48/23xz3u+79/111yz3u-14913z4u+31/87x3u2+101/84x2yu2-14270xy2u2-116/83y3u2-15/86x2zu2-3946xyzu2+17/23y2zu2+11/2xz2u2-6992yz2u2-118/77z3u2+68/87x2u3-101/70xyu3-5015y2u3-134xzu3-13479yzu3-103/19z2u3-24/61xu4+35/83yu4-15310zu4-10610u5-22/41x4v-120/91x3yv-10964x2y2v-44/31xy3v+65/122y4v-29/47x3zv+2889x2yzv+43/63xy2zv-47/9y3zv+14/41x2z2v-58/57xyz2v-67/9y2z2v+20/33xz3v+32/87yz3v-113/114z4v+31/19x3uv-7367x2yuv+11612xy2uv-27/62y3uv-47/2x2zuv-28/15xyzuv-6682y2zuv+14672xz2uv+4043yz2uv-2529z3uv-39/115x2u2v+17/4xyu2v+49/39y2u2v+15437xzu2v+91/40yzu2v+14140z2u2v-18/107xu3v-49/5yu3v-88/115zu3v-77/82u4v+1398x3v2+7/111x2yv2+1081xy2v2+6822y3v2-19/100x2zv2-19/9xyzv2+116/83y2zv2+123xz2v2-37/54yz2v2+83/32z3v2-23/82x2uv2-17/45xyuv2-10206y2uv2+20/11xzuv2-29/43yzuv2-61/77z2uv2-15878xu2v2-39/44yu2v2+19/41zu2v2+35/88u3v2+2955x2v3-87/115xyv3-16/17y2v3-107/34xzv3+80/91yzv3+112/69z2v3+109/107xuv3+85/28yuv3-68/121zuv3+2654u2v3-64/55xv4-37/60yv4+69/7zv4+66/85uv4+5754v5,-36/35x4u+12883x3yu+49/120x2y2u-4628xy3u-75/118y4u+65/93x3zu+5754x2yzu-41/62xy2zu+328y3zu-43/49x2z2u+98/107xyz2u+9/16y2z2u+15504xz3u-94/39yz3u-7028z4u-74/81x3u2+3486x2yu2+110/31xy2u2+7609y3u2-17/113x2zu2-71/78xyzu2-49/102y2zu2-2012xz2u2-4935yz2u2+459z3u2+6/53x2u3-12342xyu3-4432y2u3-95/23xzu3+11567yzu3+23/84z2u3-78/19xu4+57/10yu4+37/92zu4+11049u5-70/83x4v-34/69x3yv-9309x2y2v+10247xy3v-119/89y4v-13641x3zv+7018x2yzv+33/95xy2zv+8545y3zv+8410x2z2v-119/33xyz2v-31/44y2z2v-15/79xz3v+49/2yz3v+15796z4v-8/61x3uv-4248x2yuv+1419xy2uv-7061y3uv-12022x2zuv+5656xyzuv+101/51y2zuv-6255xz2uv+8208yz2uv-25/31z3uv-55/64x2u2v+35/88xyu2v+7627y2u2v-15213xzu2v-125/47yzu2v+716z2u2v-13163xu3v-12319yu3v+9945zu3v-122/123u4v-55/112x3v2-14498x2yv2-8389xy2v2+31/24y3v2-48/61x2zv2-10781xyzv2-51/43y2zv2-47/38xz2v2+73/88yz2v2+3185z3v2+41/11x2uv2+53/15xyuv2+35/94y2uv2-2/81xzuv2-109/55yzuv2-12412z2uv2+8/67xu2v2-79/101yu2v2+61/76zu2v2-119/47u3v2+100/7x2v3-56/81xyv3+21/82y2v3+87/52xzv3-85/57yzv3-13804z2v3-106/31xuv3+12534yuv3-93/7zuv3-14/27u2v3+85/11xv4-13639yv4-119/76zv4+59/111uv4-3220v5,975x4y+104/33x3y2-106/65x2y3+66/23xy4+59/86y5+73/72x3yz+33/92x2y2z+41/19xy3z-14775y4z-99/23x2yz2+3753xy2z2+71/41y3z2-92/5xyz3+6199y2z3+125yz4-5129x4u+112/123x3yu+19/2x2y2u-2647xy3u-35/89y4u-31/54x3zu+72/37x2yzu-121/52xy2zu-111/68y3zu+3697x2z2u+128xyz2u+14200y2z2u-27/53xz3u+59/78yz3u-22/45z4u-123/38x3u2+102/53x2yu2-49/57xy2u2+5449y3u2-2572x2zu2+3/2xyzu2+9486y2zu2+6/125xz2u2+45/2yz2u2-19/55z3u2-14525x2u3+83/18xyu3+123/56y2u3-12494xzu3-15240yzu3-28/117z2u3-20/93xu4-10552yu4-79/50zu4+107/33u5-11945x4v-86/85x3yv-115/62x2y2v+1874xy3v+96/13y4v+11797x3zv+15569x2yzv+6118xy2zv-106/103y3zv+117/40x2z2v+13729xyz2v-4329y2z2v+2102xz3v-77/27yz3v-73/25z4v+79/50x3uv+115/58x2yuv-1/111xy2uv-14589y3uv-10733x2zuv-83/65xyzuv+1735y2zuv-104/31xz2uv+99/97yz2uv+23/60z3uv+4021x2u2v+15801xyu2v+4183y2u2v-173xzu2v-100/51yzu2v-79/123z2u2v-8262xu3v-9744yu3v+28/37zu3v+5/111u4v-91/124x3v2+100/123x2yv2+113/96xy2v2-67/50y3v2+101/6x2zv2+3452xyzv2+9281y2zv2+53/22xz2v2-4861yz2v2+8899z3v2+91/23x2uv2+13924xyuv2-4/75y2uv2+59/4xzuv2-214yzuv2-114/49z2uv2+14285xu2v2+85/27yu2v2-99/5zu2v2-74/33u3v2+8313x2v3-96/71xyv3+41/69y2v3-97/31xzv3-6935yzv3-102/29z2v3+67/82xuv3+35/9yuv3-33/95zuv3+6316u2v3-6800xv4-93/4yv4-6367zv4+75/56uv4-13460v5;TestGRRes(Name, I); kill R, Name, @p; ""; string Name = "ell.d10.g9"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = -44/83x3y2-51/22x2y3+104/11xy4+38/119y5+22/87x3yz-27/61x2y2z-49/121xy3z-60/43y4z+124/65x3z2+39/107x2yz2-10379xy2z2-86/125y3z2+33/8x2z3+3501xyz3+53/9y2z3-69/106xz4+441yz4-19/126z5+12584x3yu+21/104x2y2u+12937xy3u-113/108y4u+13758x3zu+4991x2yzu+5360xy2zu-11946y3zu-2442x2z2u-9336xyz2u+9027y2z2u-112/37xz3u+14035yz3u-8230z4u+58/83x3u2+9675x2yu2+29/114xy2u2+10729y3u2+11/23x2zu2+3609xyzu2+7065y2zu2-2477xz2u2+32/37yz2u2-109/89z3u2-68/109x2u3-107/45xyu3-65/53y2u3+12249xzu3-11480yzu3+4/119z2u3+4418xu4+11875yu4-6961zu4+2678u5-76/71x3yv-87/4x2y2v+119/27xy3v+20/31y4v+122/65x3zv-116/61x2yzv-10976xy2zv-5720y3zv-12559x2z2v-109/102xyz2v-123/121y2z2v-18/73xz3v-89/124yz3v-50/109z4v-113/50x3uv+31/79x2yuv-14121xy2uv+11/123y3uv-3754x2zuv-1676xyzuv-117/113y2zuv-11336xz2uv-35/44yz2uv-116/21z3uv+10245x2u2v+17/4xyu2v-6432y2u2v-12632xzu2v+80/47yzu2v-9/115z2u2v-2607xu3v-79/82yu3v-71/63zu3v+71/102u4v-5212x3v2-2079x2yv2+104/107xy2v2+50/19y3v2+14719x2zv2-7/115xyzv2-113/6y2zv2+123/100xz2v2+22/9yz2v2+15772z3v2-10/111x2uv2-35/52xyuv2-8041y2uv2-17/38xzuv2-11677yzuv2+54/67z2uv2+7941xu2v2-8500yu2v2-147zu2v2-101/68u3v2+7864x2v3-120/61xyv3+13984y2v3+81/101xzv3-79/20yzv3-95/7z2v3-19/89xuv3-5837yuv3+112/95zuv3+119/87u2v3-51/50xv4-85/16yv4+3/44zv4+5109uv4-9320v5,44/83x4y+7230x3y2-110/69x2y3+5570xy4+87y5-103/18x4z+93/70x3yz+75/37x2y2z-61xy3z+7367y4z+5/31x3z2+9111x2yz2-97/44xy2z2+28/55y3z2+89/12x2z3+1832xyz3-15162y2z3+81/100xz4+52/9yz4-3/17z5+23/118x4u+101/55x3yu-33/47x2y2u-149xy3u+7961y4u-7891x3zu-81/14x2yzu+10246xy2zu+51/125y3zu+43/64x2z2u-68/37xyz2u+11/5y2z2u+5578xz3u-5440yz3u+61/118z4u-4318x3u2-69x2yu2-15141xy2u2+12/13y3u2+12180x2zu2-67/6xyzu2-18/121y2zu2+738xz2u2-91/115yz2u2+105/8z3u2-14085x2u3-5451xyu3+91/79y2u3-43/113xzu3-36/11yzu3-89/122z2u3+101/59xu4-125/117yu4-113/25zu4+63/118u5+13/106x4v+11326x3yv+2583x2y2v+14291xy3v+11795y4v-9923x3zv+10823x2yzv+30/31xy2zv-6558y3zv+89/20x2z2v-111/109xyz2v+10420y2z2v-81/44xz3v-76/3yz3v-31/55z4v+3423x3uv+47/80x2yuv-7843xy2uv-15365y3uv+978x2zuv+73/24xyzuv-2/39y2zuv-28/75xz2uv+1849yz2uv-10885z3uv+120/91x2u2v+9293xyu2v-8837y2u2v+109/105xzu2v+7/93yzu2v+4076z2u2v-106/5xu3v+8053yu3v-90zu3v+8598u4v+81/76x3v2-103/42x2yv2-6873xy2v2+49/73y3v2+8447x2zv2+3846xyzv2+107/126y2zv2+2145xz2v2+53/105yz2v2-62/75z3v2-11/35x2uv2+7066xyuv2+69/59y2uv2-53/64xzuv2+8587yzuv2+58/125z2uv2-15386xu2v2+9/121yu2v2+14966zu2v2-2518u3v2-37/56x2v3-11840xyv3-23/47y2v3+110/81xzv3-81yzv3+2719z2v3-65/118xuv3-1221yuv3-33/82zuv3-106/15u2v3+39/112xv4+13479yv4-126/109zv4-2251uv4+8907v5,-10723x3yz+16/79x2y2z+62/49xy3z-5204y4z-49/3x3z2+91/71x2yz2+77/3xy2z2-88/43y3z2-13949x2z3-9045xyz3+109/16y2z3-89/62xz4-15674yz4-10313z5-6773x3yu+124/61x2y2u-7483xy3u+18/23y4u-5136x3zu-3/31x2yzu-11796xy2zu-56/57y3zu-68/95x2z2u-7917xyz2u+1349y2z2u-17/56xz3u+14713yz3u-7938z4u+3104x3u2+14197x2yu2-15411xy2u2-14704y3u2+24/77x2zu2+78/19xyzu2-23/51y2zu2+98/61xz2u2+60/71yz2u2-103/51z3u2-103/42x2u3+15/79xyu3+101/62y2u3-15165xzu3+83/5yzu3-61/60z2u3+7/78xu4-3907yu4+6635zu4-12205u5-388x3yv+63/59x2y2v+88/109xy3v-13978y4v+80/53x3zv+645x2yzv+117/25xy2zv-81/53y3zv+43/72x2z2v+27/8xyz2v-10620y2z2v-13547xz3v-8282yz3v+13426z4v-58/119x3uv+480x2yuv-15697xy2uv-25/58y3uv-115x2zuv-46/123xyzuv-22/13y2zuv-88/105xz2uv-111/62yz2uv+3415z3uv-117/77x2u2v+18/29xyu2v-80/91y2u2v+7851xzu2v-11079yzu2v+39/50z2u2v+14917xu3v+1131yu3v+13259zu3v-122/25u4v-109/37x3v2+7/78x2yv2-73/13xy2v2-5623y3v2+11389x2zv2+63/68xyzv2+28/27y2zv2+69/112xz2v2-10851yz2v2+15829z3v2+86/51x2uv2+2298xyuv2+17/103y2uv2-97/2xzuv2+1/5yzuv2-104/119z2uv2+2/95xu2v2+11655yu2v2-42/65zu2v2+37/26u3v2-12355x2v3+35xyv3+20/7y2v3+8032xzv3+9572yzv3+11508z2v3+10858xuv3+115/81yuv3+10973zuv3+10832u2v3+33/101xv4-71/88yv4+67/18zv4-15473uv4+11/107v5,-28/81x3y2-126/61x2y3-70/23xy4+14521y5-3/55x3yz-100/107x2y2z-10724xy3z+2013y4z+1241x3z2+61/104x2yz2+3577xy2z2-2748y3z2-15718x2z3+106/5xyz3-41/93y2z3-95/61xz4-1/30yz4-73/4z5-59/56x3yu-14867x2y2u-11840xy3u+7444y4u-38/41x3zu-153x2yzu-2654xy2zu+73/83y3zu+6940x2z2u-1241xyz2u+79/17y2z2u-39/35xz3u-4590yz3u+8/109z4u+73/34x3u2+15609x2yu2+12721xy2u2-95/31y3u2+33/14x2zu2+77/65xyzu2-14476y2zu2+73/101xz2u2-73/101yz2u2+92/5z3u2-71/94x2u3-97/33xyu3+125/82y2u3+10213xzu3-6039yzu3-87/61z2u3-14084xu4-43/7yu4+3169zu4+4248u5+100/101x3yv+624x2y2v-4023xy3v-87/65y4v-2971x3zv-8/21x2yzv+8171xy2zv-7776y3zv-55/104x2z2v+96/113xyz2v-7318y2z2v+9436xz3v+42/41yz3v-115/14z4v-2550x3uv+82/29x2yuv+3830xy2uv+71/97y3uv-98/67x2zuv-4319xyzuv+33/49y2zuv-123/49xz2uv-35/62yz2uv-85/6z3uv-10726x2u2v+98/85xyu2v+24/43y2u2v-1382xzu2v+39/109yzu2v-36/71z2u2v+15911xu3v-38/35yu3v+2079zu3v+123/29u4v+4369x3v2-59/126x2yv2-11066xy2v2+110/117y3v2+14815x2zv2-19/49xyzv2-29/10y2zv2+41/38xz2v2-96/55yz2v2+686z3v2+67/30x2uv2+123/23xyuv2-52/25y2uv2-55xzuv2-23/89yzuv2-89/77z2uv2+9906xu2v2-12766yu2v2-104/7zu2v2+6533u3v2-65/97x2v3+57/2xyv3-11084y2v3+13/81xzv3-23/7yzv3-122/111z2v3+224xuv3+5112yuv3+103/30zuv3+78/43u2v3+4811xv4+6171yv4-3422zv4-1589uv4-5541v5,28/81x4y-39/88x3y2-101/87x2y3+11/10xy4+29/44y5-21/94x4z-100/81x3yz+123/73x2y2z+5440xy3z-15190y4z+14140x3z2+74/27x2yz2+92/15xy2z2+8048y3z2-95/64x2z3-60/89xyz3-11/118y2z3+56/15xz4+102/31yz4-1571z5-2598x4u-4426x3yu+2148x2y2u-95/11xy3u-6701y4u-12741x3zu-1179x2yzu+1671xy2zu-93/10y3zu-77/78x2z2u-35/101xyz2u-41/89y2z2u+1556xz3u+13/121yz3u+1288z4u-53/89x3u2-3/109x2yu2-12018xy2u2-5219y3u2+86/49x2zu2-1/84xyzu2+86/113y2zu2-85/123xz2u2+94/85yz2u2-10590z3u2-99/38x2u3+2696xyu3+107/13y2u3-144xzu3+8/69yzu3-107/33z2u3-117/53xu4+1924yu4+75/7zu4+98/113u5+13120x4v-7308x3yv+49/85x2y2v+55/64xy3v-4634y4v+9344x3zv-126/121x2yzv+23/81xy2zv+5086y3zv-4215x2z2v+2442xyz2v-9336y2z2v-43/44xz3v+114/109yz3v+10963z4v-2/111x3uv-5/126x2yuv-41/56xy2uv+47/79y3uv+74x2zuv-15011xyzuv+11187y2zuv-104/115xz2uv-94/67yz2uv+6674z3uv-5/78x2u2v-123/79xyu2v+7/36y2u2v+79/97xzu2v-55/62yzu2v-121/3z2u2v+109/4xu3v+9102yu3v-9526zu3v+8388u4v-47/98x3v2+14967x2yv2+5139xy2v2+83/16y3v2-15926x2zv2+8971xyzv2-15679y2zv2+8686xz2v2+13783yz2v2-57/103z3v2-73/100x2uv2-106/119xyuv2-98/113y2uv2+12096xzuv2+14898yzuv2+115/61z2uv2-125/119xu2v2+6048yu2v2+1/102zu2v2+31/125u3v2+7/27x2v3+64/123xyv3+2569y2v3+113/96xzv3-7216yzv3+2236z2v3-7127xuv3-38/17yuv3+94/73zuv3+708u2v3+87/88xv4-15428yv4-41/64zv4-55/86uv4-41/89v5,109/21x3yz-8388x2y2z-17/10xy3z-14404y4z+12672x3z2+73/52x2yz2+13291xy2z2+118/57y3z2+6159x2z3+4294xyz3-35/92y2z3-55/116xz4+83/64yz4-40/81z5-21/88x3yu-23/58x2y2u+83/118xy3u+12766y4u-45/101x3zu-38/71x2yzu+13/14xy2zu+50y3zu-2123x2z2u-61/102xyz2u+7/111y2z2u+48/121xz3u-15030yz3u-16/21z4u-34/121x3u2+34/111x2yu2+7/48xy2u2+1018y3u2-90/71x2zu2+10585xyzu2-117/56y2zu2+15739xz2u2-37/123yz2u2+4841z3u2-3527x2u3+107/77xyu3+14476y2u3-53/14xzu3-44/41yzu3+83/99z2u3+57/83xu4+1763yu4+3291zu4-2214u5+4710x3yv+4019x2y2v+106/103xy3v-33/67y4v-65/74x3zv-19/36x2yzv+83/97xy2zv+3597y3zv+76/25x2z2v-2159xyz2v+73/67y2z2v-68/55xz3v+36/29yz3v+96/55z4v-7809x3uv-101/51x2yuv+107/99xy2uv+3452y3uv-32/63x2zuv-61/125xyzuv+700y2zuv+14/45xz2uv-10/27yz2uv-64/109z3uv-12507x2u2v-3286xyu2v-8787y2u2v+11244xzu2v-7142yzu2v+51/52z2u2v-11/15xu3v+14/15yu3v-71/78zu3v+12840u4v+1676x3v2-7/22x2yv2+13461xy2v2+91/17y3v2-211x2zv2+2520xyzv2+37/91y2zv2+57/43xz2v2+79/61yz2v2+126/5z3v2+15390x2uv2+2521xyuv2-9728y2uv2-31/100xzuv2-67/120yzuv2-2/89z2uv2+3/40xu2v2-123/5yu2v2+95/44zu2v2+55/82u3v2+61/73x2v3+4656xyv3-59/61y2v3+53/5xzv3+81/19yzv3+7838z2v3-30xuv3-24/7yuv3-88/67zuv3-97/109u2v3+1/32xv4-7809yv4+115/33zv4+95/9uv4-51/31v5,10723x3yu-16/79x2y2u-62/49xy3u+5204y4u+49/3x3zu-91/71x2yzu-77/3xy2zu+88/43y3zu+13949x2z2u+9045xyz2u-109/16y2z2u+89/62xz3u+15674yz3u+10313z4u+12767x3u2-3679x2yu2+115/94xy2u2-95/72y3u2+83/126x2zu2+3070xyzu2+44/91y2zu2+105/53xz2u2-12618yz2u2-13345z3u2+61/47x2u3+108/25xyu3-3/17y2u3-76/71xzu3-36yzu3+96/47z2u3-7291xu4+7566yu4+1445zu4-48/79u5-4731x3yv+35/38x2y2v+26/47xy3v-6365y4v-15522x3zv+6045x2yzv+121/111xy2zv-15013y3zv+4541x2z2v+12683xyz2v+21/61y2z2v+96/29xz3v+98/57yz3v+57/112z4v+1027x3uv+220x2yuv+63/122xy2uv-6828y3uv+21/92x2zuv-13076xyzuv+4327y2zuv+65/107xz2uv-109/120yz2uv+46/87z3uv-13/102x2u2v+20/61xyu2v-41/47y2u2v-7345xzu2v+125/42yzu2v+124/49z2u2v-118/115xu3v+53/36yu3v-15/56zu3v+107/76u4v-13479x3v2+104/73x2yv2+5583xy2v2+12198y3v2-10858x2zv2+244xyzv2+15876y2zv2-38/123xz2v2+93/122yz2v2+82/15z3v2-35x2uv2-90/103xyuv2-16/73y2uv2+5638xzuv2-39/35yzuv2-82/39z2uv2+39/106xu2v2-3530yu2v2+7014zu2v2-9/16u3v2+105/46x2v3+1/9xyv3-10361y2v3+3039xzv3-5956yzv3+750z2v3-2053xuv3+27/112yuv3+4/121zuv3-13/108u2v3-70/33xv4-115/108yv4-59/61zv4-10442uv4-17/39v5,-80/61x3y2+68/57x2y3-35/101xy4+19/75y5+635x3yz+287x2y2z-31/49xy3z+89/93y4z-20/41x3z2-10544x2yz2+14618xy2z2-92/49y3z2+33/86x2z3-1/121xyz3-9325y2z3+2/67xz4-49/106yz4+15003z5+67/49x3yu-15884x2y2u-11/9xy3u+9349y4u+63/20x3zu+79/25x2yzu-23/77xy2zu+99/20y3zu-8233x2z2u-5/84xyz2u+71/97y2z2u+124/43xz3u-64/101yz3u-13567z4u-59/84x3u2+55/94x2yu2+7962xy2u2+36/95y3u2+5/8x2zu2+104/27xyzu2+59/12y2zu2+8231xz2u2-138yz2u2-8432z3u2+25/37x2u3+19/97xyu3+55/97y2u3+12659xzu3+27/119yzu3-101/6z2u3+69/103xu4-111/124yu4+96/107zu4-97/5u5+11725x3yv+16/105x2y2v-79/16xy3v-43/107y4v+17/54x3zv-12757x2yzv+7/124xy2zv-93/73y3zv+69/22x2z2v+73/40xyz2v+15350y2z2v+108/65xz3v+190yz3v+4395z4v+14431x3uv+8x2yuv+6264xy2uv+38/41y3uv-15601x2zuv-6559xyzuv-4074y2zuv+8619xz2uv+83/28yz2uv+15701z3uv-35/37x2u2v+75/62xyu2v+9293y2u2v-32/123xzu2v-64/15yzu2v+101/106z2u2v-13/111xu3v+89/37yu3v+49/36zu3v-78/125u4v+32/87x3v2-15591x2yv2-637xy2v2+31/61y3v2+39/41x2zv2-15874xyzv2-12988y2zv2+37/109xz2v2-18/119yz2v2-7257z3v2+97/16x2uv2+21/29xyuv2+81/95y2uv2-109/34xzuv2-35/27yzuv2+13439z2uv2-55/81xu2v2-23/90yu2v2-79/37zu2v2-60/103u3v2+41/24x2v3-95/54xyv3-104/25y2v3-27/97xzv3+43/52yzv3+82/65z2v3+15/82xuv3+1/44yuv3+65/119zuv3-5/32u2v3-1039xv4+39/31yv4-2847zv4-35/123uv4+59/20v5,80/61x4y-116/11x3y2-79/103x2y3-10762xy4-67/101y5+83/38x4z+61/10x3yz+31/8x2y2z-107/103xy3z-85/113y4z-3/97x3z2+6296x2yz2+47/86xy2z2+15041y3z2+14353x2z3+1990xyz3+15780y2z3-92/43xz4+64/47yz4-108/7z5+88/49x4u+98/57x3yu-41/44x2y2u+92/119xy3u+43/71y4u+14335x3zu+58/7x2yzu-79/39xy2zu-3487y3zu+56/83x2z2u-75/73xyz2u-7173y2z2u-99/64xz3u-51/65yz3u+11138z4u+8299x3u2+47/116x2yu2+98/95xy2u2+117/53y3u2-123/46x2zu2+125/74xyzu2-82/19y2zu2-4508xz2u2+49/29yz2u2-3337z3u2-109/7x2u3+103/41xyu3+28/13y2u3-6790xzu3-8289yzu3+59/41z2u3+15888xu4-9252yu4+10/99zu4+1485u5-101/23x4v-6626x3yv+19/25x2y2v-73/49xy3v-17/14y4v-33/46x3zv+109/58x2yzv+1/44xy2zv+8/65y3zv+5700x2z2v+16/69xyz2v+18/37y2z2v+3905xz3v+84/95yz3v+83/65z4v-700x3uv-8/7x2yuv+3184xy2uv-8373y3uv+106/115x2zuv+68/125xyzuv-2829y2zuv-38/41xz2uv+101/19yz2uv+66/97z3uv-47/7x2u2v+21/97xyu2v+9/74y2u2v+57/55xzu2v-107/89yzu2v-14157z2u2v-1693xu3v+9/10yu3v-53/114zu3v-10049u4v+9871x3v2+14318x2yv2-8447xy2v2+10730y3v2-98/87x2zv2-3822xyzv2+38/39y2zv2+111/59xz2v2-4603yz2v2+35/69z3v2-161x2uv2-73/48xyuv2-58/79y2uv2+71/63xzuv2+1832yzuv2+7891z2uv2-13900xu2v2+113/31yu2v2-7626zu2v2-1223u3v2-33/94x2v3-49/20xyv3+20/113y2v3-47/15xzv3+109/32yzv3-49/95z2v3+92/17xuv3-16/99yuv3-10817zuv3+3754u2v3-94/9xv4-67/79yv4+12659zv4+101/117uv4+113/17v5,-3756x3yz-24/35x2y2z-29/112xy3z+7944y4z-8968x3z2+62/115x2yz2-38/101xy2z2+28/39y3z2+61/49x2z3-88/119xyz3-119/87y2z3-7/123xz4-4935yz4-1239z5+8x3yu-68/7x2y2u+11910xy3u+5043y4u+7293x3zu-121/47x2yzu+8/77xy2zu-53/109y3zu+15439x2z2u-6359xyz2u-81/109y2z2u-3423xz3u+12246yz3u-1382z4u-2355x3u2+12015x2yu2-79/38xy2u2-14798y3u2+623x2zu2+47/113xyzu2+11457y2zu2+5127xz2u2-9/16yz2u2-70/41z3u2+107/112x2u3-73/49xyu3-38/15y2u3+8748xzu3-5150yzu3-94/67z2u3+10449xu4-993yu4-53/6zu4+46/79u5+59/46x3yv+7/44x2y2v+11979xy3v+78/61y4v+69/109x3zv-424x2yzv+3267xy2zv-82/17y3zv+15/92x2z2v-106/121xyz2v-32/37y2z2v+15746xz3v+97/30yz3v-7/29z4v-9484x3uv+64/45x2yuv-75xy2uv+14513y3uv-11/103x2zuv-82/3xyzuv+8740y2zuv-67/101xz2uv+584yz2uv+15/121z3uv+11669x2u2v+51/112xyu2v+124/101y2u2v+106/17xzu2v+3108yzu2v-67/118z2u2v+6866xu3v+5705yu3v-68/77zu3v-89/98u4v+14035x3v2-1896x2yv2+107/99xy2v2+46/49y3v2+109/29x2zv2-14831xyzv2-13871y2zv2+61/62xz2v2-35/9yz2v2+61/40z3v2+101/115x2uv2-14723xyuv2+13811y2uv2+66/13xzuv2-9031yzuv2-118/77z2uv2-86/121xu2v2-10616yu2v2-60/107zu2v2+123/85u3v2-92/47x2v3+23/98xyv3-5986y2v3-8636xzv3+63/89yzv3+1899z2v3+117/19xuv3-65/41yuv3+2817zuv3-1578u2v3-35/82xv4+2155yv4+7844zv4-40/67uv4-16/111v5,-4394x3y2-8801x2y3+12722xy4+15341y5+85/73x3yz+3786x2y2z-156xy3z-11841y4z-93/47x3z2+79/20x2yz2+79/99xy2z2+10343y3z2-631x2z3+7178xyz3-4119y2z3+15660xz4+14318yz4+1/69z5-9/85x3yu-59/33x2y2u-4250xy3u-9233y4u-103/75x3zu-72/53x2yzu+50/7xy2zu+6476y3zu-37/114x2z2u-5/7xyz2u-13/93y2z2u+7262xz3u+40/93yz3u-5837z4u-13/116x3u2+12622x2yu2+2615xy2u2-235y3u2+99/115x2zu2+101/9xyzu2+83/28y2zu2+14490xz2u2+119/96yz2u2-11229z3u2+41/86x2u3+14636xyu3-88/45y2u3-9311xzu3-8967yzu3-71/105z2u3+56/53xu4+14093yu4+115zu4+118/67u5-95/54x3yv-11922x2y2v-101/117xy3v-15245y4v-3849x3zv+100x2yzv+101/64xy2zv+82/5y3zv-53/52x2z2v-26/67xyz2v+17/72y2z2v+33/41xz3v-91/82yz3v-29/12z4v+73/126x3uv+109/73x2yuv-28/55xy2uv-51/29y3uv+17/35x2zuv+108/67xyzuv+81/2y2zuv+95/101xz2uv-57/8yz2uv-7142z3uv-8230x2u2v-91/107xyu2v-51/11y2u2v+67/125xzu2v-59/17yzu2v+23/121z2u2v+14520xu3v+2632yu3v+10602zu3v+19/75u4v-98/115x3v2-13270x2yv2+23/28xy2v2-97/24y3v2+18/37x2zv2+2394xyzv2+9634y2zv2-12683xz2v2-4723yz2v2+93/11z3v2+76/15x2uv2-7066xyuv2-3496y2uv2-31/33xzuv2+23/114yzuv2+75/4z2uv2+6637xu2v2+5/31yu2v2-220zu2v2-15145u3v2-16/57x2v3+994xyv3+13/111y2v3-35/111xzv3-1460yzv3-13818z2v3-12748xuv3+6/19yuv3+3481zuv3+4768u2v3+31/83xv4-21/34yv4-117/95zv4+7890uv4-5747v5,4394x4y+25/118x3y2+27/122x2y3-1/20xy4-21/58y5+7367x4z+11281x3yz+2518x2y2z-55/92xy3z+7/17y4z-6716x3z2+116/11x2yz2+67/35xy2z2+14506y3z2-70/17x2z3-92/125xyz3-11235y2z3+28/79xz4+6770yz4+13311z5-12323x4u-36x3yu-74/35x2y2u+28/11xy3u-14140y4u+29/76x3zu+10357x2yzu-13657xy2zu-65/9y3zu+8/49x2z2u-186xyz2u+7854y2z2u+20/111xz3u+53/20yz3u-4420z4u-49x3u2+106/73x2yu2-57/112xy2u2-1767y3u2-67/36x2zu2+97/31xyzu2-4/15y2zu2-27/119xz2u2-6837yz2u2+81/88z3u2-803x2u3-14237xyu3+116/45y2u3+74/53xzu3-44/23yzu3+7957z2u3+2551xu4-5262yu4-3014zu4+115/98u5+46/39x4v+71/2x3yv+13841x2y2v-12/7xy3v+7491y4v+19/67x3zv-21/82x2yzv+29/92xy2zv+124/123y3zv+4436x2z2v+4318xyz2v-14/111y2z2v+105/118xz3v+12883yz3v-105/22z4v-124/109x3uv-107/103x2yuv+7/4xy2uv-114/121y3uv-74/69x2zuv-5025xyzuv-114/97y2zuv-5872xz2uv+24/95yz2uv-49/88z3uv-21/29x2u2v+121/52xyu2v+721y2u2v+119/67xzu2v+85/48yzu2v+50/67z2u2v+24/53xu3v+32/115yu3v-2809zu3v+2966u4v+5211x3v2-190x2yv2+2551xy2v2+2895y3v2+124/63x2zv2-6160xyzv2+71/122y2zv2+8635xz2v2-9/28yz2v2+193z3v2+9/119x2uv2-110/101xyuv2-11713y2uv2-6363xzuv2+61/93yzuv2-10139z2uv2+89/96xu2v2+94/103yu2v2+61/93zu2v2-61/78u3v2-67/22x2v3+15674xyv3-121/5y2v3+121/76xzv3+15523yzv3-93/88z2v3+8667xuv3-11344yuv3-97/108zuv3-14490u2v3+10228xv4-18/107yv4-54/37zv4-2193uv4+14370v5,-103/79x3yz-16/41x2y2z+114/83xy3z-104/85y4z+14/37x3z2-3023x2yz2+723xy2z2-7/55y3z2-82/85x2z3-33/83xyz3+109/119y2z3-13119xz4-4627yz4-35/37z5-11662x3yu+121/57x2y2u-7212xy3u+59/83y4u+2149x3zu-30/13x2yzu+125/119xy2zu+79/23y3zu-3/88x2z2u+7168xyz2u-10717y2z2u+112/33xz3u-10509yz3u+121/56z4u+125/88x3u2-115/121x2yu2+49/4xy2u2-27/88y3u2-2867x2zu2-43/85xyzu2-4734y2zu2-37/114xz2u2-2/43yz2u2+106/95z3u2-108/35x2u3+4531xyu3-19/44y2u3-73/27xzu3+59/117yzu3+25/9z2u3-65/89xu4+81/20yu4+5365zu4+1733u5-2363x3yv-10326x2y2v-5/24xy3v-17/106y4v-14412x3zv+6361x2yzv+10187xy2zv-76/101y3zv+4991x2z2v+14252xyz2v-107/18y2z2v+4857xz3v-13162yz3v+1088z4v-3/64x3uv-14/113x2yuv+96/41xy2uv-76/103y3uv+8924x2zuv-11/30xyzuv-4493y2zuv+3070xz2uv+10/41yz2uv-35/51z3uv+4318x2u2v+15309xyu2v+107/101y2u2v-1748xzu2v+11082yzu2v+29/90z2u2v-19/8xu3v+107/64yu3v+3039zu3v-21/59u4v+14/87x3v2+16/59x2yv2+77/9xy2v2+3679y3v2+53/113x2zv2+97/80xyzv2-899y2zv2+10016xz2v2-10049yz2v2+29/10z3v2+43/7x2uv2-5919xyuv2-7/34y2uv2+42/85xzuv2+102/23yzuv2-8300z2uv2+125/2xu2v2-1700yu2v2-107/21zu2v2+12942u3v2-3054x2v3-87/53xyv3+4745y2v3+52/83xzv3-11747yzv3-119/64z2v3-5987xuv3+2016yuv3-2889zuv3+4535u2v3-1588xv4-27/5yv4+8541zv4-15581uv4-3/119v5,-x3y2-7492x2y3+118/35xy4-43/5y5-2479x3yz-8522x2y2z-105/26xy3z-103/18y4z+5868x3z2-10040x2yz2-50/81xy2z2+3378y3z2-71/44x2z3-12323xyz3-25/44y2z3+12979xz4-15146yz4+5962z5+8852x3yu-39/77x2y2u-9554xy3u-14590y4u+61/84x3zu-2295x2yzu-5969xy2zu+14241y3zu-29/74x2z2u+107/17xyz2u+107y2z2u-14/99xz3u+109/93yz3u-73/41z4u-9170x3u2+8877x2yu2-109/118xy2u2+65/36y3u2+122/93x2zu2-15020xyzu2+33/50y2zu2-11/46xz2u2-91/116yz2u2-47/10z3u2-34/57x2u3-90/79xyu3+12760y2u3+81/71xzu3+1436yzu3+14839z2u3+6598xu4-12418yu4-47/59zu4-1357u5+6/91x3yv-46/21x2y2v+100/53xy3v-69/125y4v+98x3zv-63/23x2yzv+96/121xy2zv+12/11y3zv-37/120x2z2v-37/106xyz2v-25/122y2z2v-13657xz3v+79/47yz3v+15519z4v+45/46x3uv+73/100x2yuv-5361xy2uv-39/101y3uv+1161x2zuv-105/22xyzuv+79/34y2zuv+96/31xz2uv-20/51yz2uv-2683z3uv-122/125x2u2v-66/109xyu2v-6357y2u2v-3021xzu2v+86/33yzu2v-105/8z2u2v+95/22xu3v-9046yu3v+69/83zu3v-3166u4v+91/115x3v2+9661x2yv2-8757xy2v2+79/23y3v2+125/107x2zv2+6133xyzv2+8975y2zv2-38/103xz2v2-120/43yz2v2+59/124z3v2-9252x2uv2+27/64xyuv2+99/80y2uv2+125/28xzuv2-60/109yzuv2-73/107z2uv2-15162xu2v2+91/71yu2v2-89/122zu2v2-1/9u3v2+40/117x2v3-71/41xyv3+10502y2v3-5618xzv3-995yzv3-117/112z2v3-15185xuv3-4470yuv3-13/4zuv3-14631u2v3-5804xv4-15527yv4-47/87zv4+5084uv4-64/11v5,x4y+46/47x3y2+13/47x2y3-13553xy4-5/59y5-15/76x4z+370x3yz+15/56x2y2z-8199xy3z+17/37y4z+32/47x3z2-26/29x2yz2-1/109xy2z2+68/77y3z2-88/123x2z3-1397xyz3-90y2z3+117/80xz4+14919yz4+11248z5+1742x4u-6060x3yu+97/38x2y2u+54/53xy3u-26/45y4u-315x3zu+9/76x2yzu+113/14xy2zu-28/79y3zu-109/14x2z2u+53/54xyz2u-213y2z2u-18/11xz3u-12129yz3u+6321z4u-13361x3u2+109/81x2yu2+37/84xy2u2-19/69y3u2+82/31x2zu2-20/41xyzu2-13135y2zu2-52/99xz2u2-12942yz2u2-8237z3u2-12377x2u3-41/43xyu3+13143y2u3-6701xzu3-98/53yzu3+97/43z2u3+1570xu4-41/5yu4-7/86zu4+306u5-7920x4v+76/53x3yv-91/73x2y2v-49/64xy3v+12976y4v-1787x3zv-95/123x2yzv-10033xy2zv-83/100y3zv-17/112x2z2v+1060xyz2v-121/54y2z2v+25/77xz3v+23/73yz3v-3576z4v+41/98x3uv+15265x2yuv+9014xy2uv-86/33y3uv-83/51x2zuv-15747xyzuv+11/16y2zuv-12110xz2uv-15554yz2uv-7654z3uv+68/53x2u2v+1673xyu2v-123/64y2u2v-3/19xzu2v+29/34yzu2v-5457z2u2v+51/58xu3v-4242yu3v-70/67zu3v+7159u4v+8620x3v2-9381x2yv2+52/79xy2v2-73/113y3v2+83/22x2zv2-1445xyzv2+6524y2zv2-122xz2v2-107/85yz2v2-1240z3v2+1710x2uv2-101/59xyuv2-2950y2uv2-12343xzuv2-79/27yzuv2-5/26z2uv2+89/68xu2v2-14985yu2v2+8382zu2v2-5109u3v2-12322x2v3-97/106xyv3-86/23y2v3+115/11xzv3-45/2yzv3-79/110z2v3+7472xuv3-17/71yuv3+1659zuv3-4468u2v3-85/47xv4+11/73yv4-1700zv4-32/51uv4+7855v5,62/49x4-125/36x3y+2x2y2+56/39xy3+7307y4-42/43x3z+83/42x2yz-11648xy2z-43/106y3z-49/109x2z2-95/28xyz2-194y2z2+71/95xz3-83/59yz3-66/95z4-1/51x3u-82/21x2yu+121/103xy2u-11106y3u-55/91x2zu+55/119xyzu-123/79y2zu-20/11xz2u+6943yz2u+69z3u+5908x2u2-56/89xyu2-13119y2u2+32/115xzu2+11412yzu2+63/50z2u2+73/85xu3-12527yu3+1991zu3+26/33u4+79/91x3v-10/27x2yv+20/117xy2v-49/102y3v+98/33x2zv+115/76xyzv+12412y2zv-47/48xz2v+121/113yz2v+105/26z3v-10954x2uv+10730xyuv+15721y2uv-101/63xzuv-32/19yzuv+67/71z2uv+77/45xu2v+27/98yu2v-670zu2v-13396u3v-55/119x2v2-7890xyv2-101/7y2v2-9563xzv2+3/95yzv2+4857z2v2+9397xuv2+3/116yuv2-12257zuv2-79/49u2v2+11697xv3+26/19yv3+4885zv3-53/22uv3-8355v4;TestGRRes(Name, I); kill R, Name, @p; ""; string Name = "k3.d10.g9.quart2"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = x3yz2+31/15x2y2z2-7231xy3z2+99/37y4z2+28/95x3z3+97/32x2yz3+13247xy2z3+12717y3z3-113/31x2z4-61/30xyz4-6844y2z4+104/3xz5-13849yz5+43/39z6+13061x3yzu-8463x2y2zu+94/69xy3zu-8/61y4zu-13297x3z2u+7217x2yz2u-7830xy2z2u-75/14y3z2u+2839x2z3u-14657xyz3u-52/7y2z3u-6/89xz4u-6169yz4u+44/7z5u-98/33x3yu2+41/30x2y2u2-65/98xy3u2+122/13y4u2+9906x3zu2-11587x2yzu2+17/53xy2zu2+6504y3zu2+49/106x2z2u2+11480xyz2u2+97/71y2z2u2+12560xz3u2-114/83yz3u2-13761z4u2-67/112x3u3-18/49x2yu3+21/67xy2u3-44/43y3u3+123/116x2zu3+4459xyzu3-13841y2zu3-805xz2u3-1382yz2u3-5293z3u3+133x2u4-122/79xyu4+9724y2u4+61/24xzu4+113/119yzu4-19/108z2u4+15893xu5+57/22yu5+4600zu5-618u6-27/53x3yzv+44/103x2y2zv-142xy3zv+19/84y4zv+105/8x3z2v+10532x2yz2v-75/74xy2z2v-70/19y3z2v+31/80x2z3v-481xyz3v+47/30y2z3v+14318xz4v+51/28yz4v-15/113z5v-46/17x3yuv-99/100x2y2uv-106/5xy3uv+14384y4uv+7/100x3zuv-15/64x2yzuv-6976xy2zuv+12051y3zuv-67/42x2z2uv-2627xyz2uv-49/104y2z2uv+77/16xz3uv+15766yz3uv+85/117z4uv-107/101x3u2v-6699x2yu2v+2443xy2u2v-27/28y3u2v+11945x2zu2v-14467xyzu2v-4873y2zu2v-63/124xz2u2v-8270yz2u2v+11900z3u2v+47/14x2u3v+53/8xyu3v-10/51y2u3v-87/119xzu3v+114/73yzu3v+86/57z2u3v+52/63xu4v-11587yu4v+1/18zu4v-121/109u5v+116/11x3yv2+19/108x2y2v2-31/3xy3v2-43/9y4v2-81/100x3zv2-7728x2yzv2-1037xy2zv2+24/101y3zv2-61/103x2z2v2-8/51xyz2v2+117/109y2z2v2+98/23xz3v2+1646yz3v2-3356z4v2+105/59x3uv2+117/31x2yuv2+519xy2uv2+12633y3uv2+25/6x2zuv2-963xyzuv2-49/23y2zuv2-116/25xz2uv2+14146yz2uv2+11480z3uv2-95/8x2u2v2-10928xyu2v2-51/23y2u2v2-12770xzu2v2-92/91yzu2v2+3872z2u2v2+3183xu3v2+6871yu3v2+90/37zu3v2+10019u4v2-69/88x3v3-1398x2yv3-97/72xy2v3-46/97y3v3+107/14x2zv3-20/89xyzv3-11367y2zv3+120/29xz2v3-86/81yz2v3+107/69z3v3-39/17x2uv3+83/11xyuv3+169y2uv3-11/71xzuv3-22/17yzuv3-14862z2uv3-13009xu2v3-101/12yu2v3+10617zu2v3+2567u3v3-23/85x2v4+27/50xyv4+113/51y2v4+97/16xzv4+4438yzv4-11857z2v4+14580xuv4-6426yuv4+9421zuv4-10585u2v4+14670xv5+1807yv5+10298zv5-116/53uv5+7869v6,x3yzu+31/15x2y2zu-7231xy3zu+99/37y4zu+28/95x3z2u+97/32x2yz2u+13247xy2z2u+12717y3z2u-113/31x2z3u-61/30xyz3u-6844y2z3u+104/3xz4u-13849yz4u+43/39z5u-124/43x3yu2-90/13x2y2u2-13244xy3u2-78/73y4u2+118/43x3zu2+37/67x2yzu2-10426xy2zu2+2412y3zu2-32/113x2z2u2+35/104xyz2u2+3952y2z2u2+9028xz3u2-1990yz3u2-59/109z4u2+15499x3u3+116/23x2yu3+95/58xy2u3+8/47y3u3+59/109x2zu3-29xyzu3+12412y2zu3+20/81xz2u3+2200yz2u3-13809z3u3+3889x2u4-8136xyu4+8922y2u4-4/121xzu4+82/113yzu4-65/23z2u4+101/53xu5+103/113yu5-99/118zu5-9524u6-2749x3yzv-7814x2y2zv+73/113xy3zv+9937y4zv-59/62x3z2v-23/12x2yz2v-10245xy2z2v+7130y3z2v-4427x2z3v+6656xyz3v+3448y2z3v-46/79xz4v+1611yz4v+8453z5v+12013x3yuv+49/17x2y2uv-4/115xy3uv-121/91y4uv-63/29x3zuv+64/7x2yzuv-8785xy2zuv-87/14y3zuv+36/121x2z2uv+9525xyz2uv+4215y2z2uv-17/13xz3uv-117/125yz3uv+101/122z4uv+42/37x3u2v-8747x2yu2v-105/79xy2u2v+10799y3u2v-58/49x2zu2v-8/75xyzu2v-67/49y2zu2v-38/11xz2u2v+53/27yz2u2v+113/52z3u2v+18/59x2u3v+71/106xyu3v+47/2y2u3v-4594xzu3v+95/4yzu3v-121/46z2u3v-55/62xu4v-101/72yu4v+40/53zu4v+15227u5v-15553x3yv2+29/94x2y2v2-4076xy3v2-7133y4v2+27/125x3zv2+33/29x2yzv2-63/95xy2zv2+9166y3zv2-480x2z2v2+9941xyz2v2+107/46y2z2v2+13018xz3v2+53/98yz3v2+92/35z4v2+17/30x3uv2+77/95x2yuv2+11/67xy2uv2+8262y3uv2+65/11x2zuv2+2567xyzuv2-33/94y2zuv2+85/92xz2uv2+103/25yz2uv2-27/100z3uv2+13210x2u2v2-109/90xyu2v2+141y2u2v2-124/51xzu2v2-3/109yzu2v2-4910z2u2v2+205xu3v2+14357yu3v2+85/57zu3v2-109/28u4v2-68/39x3v3+10545x2yv3-2176xy2v3-8743y3v3+15111x2zv3+25/119xyzv3+8/103y2zv3-6046xz2v3+8658yz2v3+106/5z3v3-31/126x2uv3-7762xyuv3+2315y2uv3+124/67xzuv3-77/104yzuv3+95/71z2uv3+69/119xu2v3+13069yu2v3-8620zu2v3+105/41u3v3-15772x2v4-11212xyv4-61/36y2v4+38/125xzv4-15860yzv4+8/63z2v4+7519xuv4-94/41yuv4+45/32zuv4+9417u2v4-71/35xv5-6287yv5+6481zv5+106/99uv5+3/41v6,-8036x3yu2+7966x2y2u2-151xy3u2-14/111y4u2-111/76x3zu2-102/11x2yzu2+7956xy2zu2-7397y3zu2-113/16x2z2u2-8049xyz2u2+7230y2z2u2+3978xz3u2-36/113yz3u2-8147z4u2-107/83x3u3+78/97x2yu3+12700xy2u3+11/72y3u3+88/31x2zu3-63/40xyzu3+101/35y2zu3-220xz2u3+3/103yz2u3-49/45z3u3-21/113x2u4+104/123xyu4+98/47y2u4-56/61xzu4-87/50yzu4+5913z2u4-120/17xu5+64/11yu5-109/80zu5+10371u6-118/25x3yzv+58/99x2y2zv-5/64xy3zv+7/46y4zv-49/103x3z2v-77/106x2yz2v-44/7xy2z2v-7559y3z2v-17/35x2z3v+948xyz3v-15043y2z3v-3576xz4v-2/109yz4v+74/11z5v+6436x3yuv+7316x2y2uv+29/5xy3uv-1326y4uv+34/49x3zuv-122/27x2yzuv-632xy2zuv+46/49y3zuv-13463x2z2uv-808xyz2uv-17/32y2z2uv-13149xz3uv-117/88yz3uv-45/79z4uv-65/94x3u2v+6/67x2yu2v+34/39xy2u2v-14026y3u2v+42/107x2zu2v-3287xyzu2v-70/43y2zu2v+29/104xz2u2v-47/18yz2u2v-11038z3u2v+6262x2u3v-5255xyu3v-7/10y2u3v+7065xzu3v+5608yzu3v+4675z2u3v-73/90xu4v-15822yu4v-71/63zu4v+110/97u5v-69/5x3yv2+4315x2y2v2-124/45xy3v2-79/16y4v2-10739x3zv2-93/46x2yzv2+12499xy2zv2-73/86y3zv2+6367x2z2v2-12876xyz2v2-306y2z2v2-89xz3v2-70/51yz3v2+13120z4v2+61/57x3uv2+14782x2yuv2-91/9xy2uv2-2625y3uv2+14747x2zuv2-5899xyzuv2-12944y2zuv2-47/14xz2uv2-4551yz2uv2-99/101z3uv2-12618x2u2v2+1507xyu2v2-11951y2u2v2+68/49xzu2v2+49/39yzu2v2-56/103z2u2v2-31/85xu3v2-32/49yu3v2-65/14zu3v2+15/7u4v2+5749x3v3-3667x2yv3-107/29xy2v3+11301y3v3+95/18x2zv3-121/74xyzv3+75/26y2zv3+101/98xz2v3-111/76yz2v3-11335z3v3-15923x2uv3-36/83xyuv3-4134y2uv3-87/118xzuv3-41/11yzuv3+104/61z2uv3+12583xu2v3-50/23yu2v3-31/44zu2v3-29/23u3v3+108/107x2v4-8216xyv4-5009y2v4+101/26xzv4-9779yzv4+71/74z2v4-3358xuv4+83/84yuv4-34/39zuv4+44/47u2v4-112/83xv5+113/74yv5+82/79zv5-115/99uv5+12/109v6,-x4y-31/15x3y2+7231x2y3-99/37xy4-28/95x4z-53/107x3yz-4623x2y2z+5300xy3z-41/111y4z+12205x3z2+113/120x2yz2+54/49xy2z2-85/63y3z2+104/89x2z3-52/121xyz3-22/49y2z3+14367xz4+71/93yz4+55/56z5-5/81x4u-67/81x3yu-83/13x2y2u+98/55xy3u+15289y4u-94/111x3zu+40/29x2yzu-16/59xy2zu-107/14y3zu+2965x2z2u-459xyz2u-2/47y2z2u+35/22xz3u+119/39yz3u-12180z4u-13679x3u2+1534x2yu2+11305xy2u2-62/9y3u2-68/39x2zu2+11/90xyzu2-36/101y2zu2-2896xz2u2-15114yz2u2-49/114z3u2+19/16x2u3-11401xyu3-109/3y2u3+67/80xzu3+53/92yzu3+2894z2u3+119/74xu4+407yu4-65/53zu4+95/94u5-9309x4v+21/40x3yv+1436x2y2v+2194xy3v+6994y4v-116/81x3zv+13/2x2yzv-12/13xy2zv-23/84y3zv-61/83x2z2v+2023xyz2v+19/40y2z2v+43/26xz3v-59/113yz3v-47/53z4v+15580x3uv+21x2yuv+113/97xy2uv-15419y3uv-15243x2zuv+5128xyzuv-34/47y2zuv+13206xz2uv-4833yz2uv+107/91z3uv-1693x2u2v+54/53xyu2v-86/67y2u2v+98/9xzu2v+86/17yzu2v+64/89z2u2v+25/113xu3v+7884yu3v+14089zu3v-12027u4v-9471x3v2-36/85x2yv2-21/13xy2v2+15888y3v2+76/109x2zv2+4547xyzv2+115/12y2zv2-11/107xz2v2+6764yz2v2-8321z3v2+84/101x2uv2-202xyuv2+3251y2uv2+91/4xzuv2+7124yzuv2-53/81z2uv2+47/84xu2v2-8833yu2v2+117/14zu2v2-3/113u3v2+126/97x2v3-78/115xyv3+68/63y2v3-34/109xzv3+5913yzv3+6226z2v3-2365xuv3+91/120yuv3+14120zuv3-69/8u2v3+71/12xv4-13094yv4-7262zv4-33uv4+5367v5,-9533x4y-318x3y2+8/49x2y3+83/29xy4+13129y5+221x4z+115/48x3yz+12508x2y2z+97/52xy3z+11479y4z+8941x3z2+104/109x2yz2+9191xy2z2+103/64y3z2+10584x2z3-7728xyz3+3979y2z3+15/82xz4+5409yz4-1326z5+3756x4u-57/62x3yu+63/47x2y2u-14600xy3u+159y4u-11/4x3zu-113/57x2yzu-26/125xy2zu-32/87y3zu-10/21x2z2u+12927xyz2u-73/62y2z2u+115/99xz3u-13/3yz3u-126/25z4u-3969x3u2-122/57x2yu2-5003xy2u2-100/117y3u2-71/30x2zu2+7356xyzu2-2211y2zu2+31/40xz2u2-6722yz2u2-139z3u2+4426x2u3+1/115xyu3-72/85y2u3+15260xzu3+7938yzu3+4/115z2u3-33/89xu4+31/108yu4-50/83zu4+14/107u5+24/95x4v-113/17x3yv+81/14x2y2v-9957xy3v-10075y4v-122/113x3zv+65/118x2yzv-96/29xy2zv-19/41y3zv+113/35x2z2v+121/31xyz2v-9/68y2z2v+91/45xz3v-23/116yz3v-67/99z4v-5355x3uv-3112x2yuv-12824xy2uv-58/123y3uv-13/22x2zuv-19/85xyzuv-121/24y2zuv-14093xz2uv+99/95yz2uv+89/50z3uv+13096x2u2v-109/120xyu2v+121/61y2u2v+80/41xzu2v-39yzu2v-8/99z2u2v+5/17xu3v+112/69yu3v+14346zu3v-7173u4v+125/13x3v2+43/53x2yv2-78/103xy2v2-109/111y3v2+33/13x2zv2-15333xyzv2+87/49y2zv2-7212xz2v2+7729yz2v2-86/123z3v2-119/103x2uv2-71/122xyuv2-81/113y2uv2+6133xzuv2+55/72yzuv2+69/31z2uv2+12828xu2v2+94/15yu2v2-7588zu2v2+21/41u3v2-8712x2v3+74/9xyv3-11/87y2v3+1446xzv3-3/95yzv3-87/55z2v3-717xuv3-110/97yuv3-13/113zuv3-95/81u2v3-37/68xv4+5112yv4-56/11zv4-6/115uv4+7910v5,25/42x4y-42/79x3y2-59/21x2y3+2736xy4-107/115x4z-203x3yz+47/101x2y2z+7686xy3z-63/64y4z+103/57x3z2-12082x2yz2+11/102xy2z2-83/43y3z2+13/49x2z3-2685xyz3+123/44y2z3+31/12xz4+126/83yz4+14745z5+83/37x4u+7362x3yu-14615x2y2u-14109xy3u+49/47y4u+1929x3zu+83/71x2yzu-13640xy2zu-97/58y3zu-11141x2z2u-61/49xyz2u-3745y2z2u-74/21xz3u+3493yz3u-7540z4u-103/118x3u2-43/32x2yu2-9200xy2u2-23/65y3u2+15895x2zu2-13924xyzu2-14291y2zu2-11039xz2u2-31/37yz2u2-101/93z3u2-39/83x2u3-4536xyu3-78/47y2u3+75/44xzu3-24/121yzu3-81/113z2u3-81/89xu4+15825yu4-4111zu4+5850u5-12534x4v-69/94x3yv-10076x2y2v+3952xy3v+25/12y4v+21/34x3zv+11002x2yzv-54xy2zv+20/23y3zv+4991x2z2v+549xyz2v+2687y2z2v-110/9xz3v+11359yz3v+49/24z4v+62/107x3uv-27/41x2yuv-17/52xy2uv-10972y3uv+12/103x2zuv-318xyzuv-77/40y2zuv-114/53xz2uv+17/28yz2uv-8084z3uv+85/36x2u2v+7/100xyu2v-5772y2u2v-89/114xzu2v-40/121yzu2v+3340z2u2v+36/113xu3v-38/93yu3v+2519zu3v-7084u4v+8136x3v2-55/23x2yv2+27/7xy2v2+74/39y3v2+63/16x2zv2-8661xyzv2+2/91y2zv2+3773xz2v2-75/122yz2v2+447z3v2-59/109x2uv2-119/9xyuv2-67/49y2uv2-11334xzuv2-10482yzuv2-60/91z2uv2+94/65xu2v2-108/17yu2v2-69/70zu2v2-23/20u3v2+8/115x2v3+29/41xyv3+8/15y2v3-95/6xzv3-9714yzv3+2550z2v3-121/80xuv3+67/18yuv3+43/5zuv3+23/124u2v3-12509xv4-104/79yv4-73/21zv4-1238uv4+9038v5,94/107x4y+47/14x3y2-6362x2y3-20/59xy4-43/120y5-3028x4z-15141x3yz-2028x2y2z+84/115xy3z-3024y4z+2811x3z2+47/45x2yz2+121/101xy2z2-100/57y3z2+8/115x2z3+1/101xyz3-13/112y2z3+3618xz4+88/67yz4-52/63z5+102/97x4u-12/89x3yu-102x2y2u-3846xy3u-61/86y4u+85/54x3zu+78/29x2yzu-13381xy2zu-49/95y3zu-77/2x2z2u-5784xyz2u+1557y2z2u-9163xz3u-114/121yz3u-57/103z4u+36/31x3u2-9062x2yu2-23/111xy2u2+7362y3u2-7671x2zu2+14945xyzu2+7901y2zu2+51/5xz2u2-109/48yz2u2+7696z3u2+11280x2u3-44/57xyu3-13736y2u3-13458xzu3-14723yzu3-707z2u3+899xu4-10381yu4+99/25zu4-7788u5-237x4v+45/43x3yv-7666x2y2v-4/109xy3v+4303y4v-13107x3zv-108/91x2yzv-7707xy2zv-73/47y3zv+61/118x2z2v-11/65xyz2v+2970y2z2v-104/37xz3v-15408yz3v-64/55z4v+47/113x3uv+2185x2yuv+7941xy2uv-61/37y3uv+6482x2zuv-11/70xyzuv+83/110y2zuv-109/83xz2uv-86/95yz2uv-7583z3uv+83/45x2u2v+89/38xyu2v-2/11y2u2v+3577xzu2v+124/125yzu2v-1151z2u2v+109/85xu3v+70/13yu3v+37/104zu3v-210u4v+51/29x3v2-104/111x2yv2+105/58xy2v2-13459y3v2-80/79x2zv2-3006xyzv2-115/16y2zv2+8208xz2v2+35/38yz2v2+49/27z3v2-1647x2uv2+10482xyuv2-34/93y2uv2+97/18xzuv2+101/20yzuv2+1711z2uv2+91/36xu2v2-96/23yu2v2+7006zu2v2+86/31u3v2-10734x2v3-43/18xyv3-4597y2v3-11174xzv3-7334yzv3+7/96z2v3+4/97xuv3-5/82yuv3-15600zuv3-69/94u2v3-71/25xv4+21/97yv4+117/23zv4-6557uv4-67/83v5,8164x4y+19/73x3y2-1592x2y3-28/87xy4-63/103x4z+11/42x3yz-52/67x2y2z-13766xy3z+11378y4z+10/37x3z2+115/41x2yz2+11/100xy2z2-49/40y3z2+86/111x2z3+124/5xyz3-25/79y2z3-14525xz4+11380yz4-53/42z5-12169x4u-14/51x3yu+68/33x2y2u-3/62xy3u-31/22y4u-74/93x3zu+12924x2yzu-103/123xy2zu-74/97y3zu-2789x2z2u-95/32xyz2u+45/13y2z2u+40/71xz3u+49/110yz3u+34/75z4u+9829x3u2-59/92x2yu2+106/65xy2u2+123/86y3u2+7133x2zu2-73/46xyzu2-7/29y2zu2-937xz2u2-65/67yz2u2-88/111z3u2-61/119x2u3+975xyu3-54/7y2u3-37/33xzu3+61/59yzu3+51/115z2u3+117/43xu4+8506yu4+13941zu4-14945u5-115/63x4v-14237x3yv-74/87x2y2v+104/47xy3v-95/104y4v+11535x3zv-119/75x2yzv-44xy2zv+11299y3zv-21/113x2z2v-2852xyz2v+95/77y2z2v-75/19xz3v-4864yz3v-79/88z4v+139x3uv-10068x2yuv+2049xy2uv+7515y3uv+97/56x2zuv+109/113xyzuv+7778y2zuv-71/11xz2uv-80/19yz2uv+55/59z3uv-69/98x2u2v-15679xyu2v+114/11y2u2v+69/65xzu2v+879yzu2v+45/104z2u2v+47/97xu3v-1373yu3v+15885zu3v+11121u4v-5042x3v2+4/25x2yv2-8607xy2v2-25/33y3v2+93/55x2zv2+68xyzv2-4167y2zv2+14180xz2v2-115/47yz2v2-81/67z3v2-12099x2uv2+34/107xyuv2+122/59y2uv2+775xzuv2-91yzuv2-85/96z2uv2-59/95xu2v2+174yu2v2+11/16zu2v2+66/37u3v2-121/36x2v3+6070xyv3-83/52y2v3-121/59xzv3-55/12yzv3+8088z2v3-20/29xuv3+76/125yuv3-10858zuv3+1833u2v3-103/50xv4+76/93yv4-119/18zv4+37/114uv4+51/7v5,85/56x4y-7839x3y2+12/37x2y3+6558xy4-8191x4z+115/7x3yz+81/23x2y2z-4121xy3z-1131y4z-23/37x3z2-71/32x2yz2+30/97xy2z2+5070y3z2-49/123x2z3+103/88xyz3-45/19y2z3+5132xz4+7277yz4+1896z5-103/75x4u-12020x3yu+12337x2y2u+6248xy3u+14290y4u-87/44x3zu-5364x2yzu-11801xy2zu-59/37y3zu+34/109x2z2u-14482xyz2u-10338y2z2u+118/73xz3u+7/8yz3u+158z4u+10590x3u2-5182x2yu2+83/62xy2u2+11557y3u2-92/119x2zu2-37/94xyzu2+5383y2zu2-365xz2u2+7/62yz2u2-7965z3u2-10/43x2u3+119/101xyu3-113/83y2u3-121/41xzu3+61/104yzu3+37/60z2u3-74/95xu4-113/66yu4-205zu4+4787u5-94/93x4v+14871x3yv-14723x2y2v+10730xy3v+112/17y4v-35/19x3zv-3487x2yzv-65/43xy2zv-7445y3zv-79/124x2z2v+7423xyz2v+91/2y2z2v+91/34xz3v-6970yz3v-50/113z4v+75/43x3uv-127x2yuv+11978xy2uv+48/113y3uv+113/62x2zuv-8941xyzuv-101/112y2zuv-5737xz2uv-31/123yz2uv+9490z3uv+19/92x2u2v-107/73xyu2v-23/121y2u2v+38/65xzu2v-672yzu2v+13/77z2u2v+46/119xu3v-103/18yu3v+107/59zu3v-52/21u4v-94/87x3v2-74/31x2yv2-9/22xy2v2-2896y3v2+113/3x2zv2-5386xyzv2-11391y2zv2+42/97xz2v2+77/64yz2v2-1610z3v2-102/43x2uv2+124/39xyuv2+14829y2uv2+88/113xzuv2-10411yzuv2-51/43z2uv2-36/121xu2v2+9487yu2v2-5589zu2v2+4335u3v2-5/91x2v3+6084xyv3-56/39y2v3-84/101xzv3-81/85yzv3-6521z2v3-2432xuv3+14317yuv3-43/82zuv3+121/8u2v3+14783xv4-92/45yv4+112/27zv4-8410uv4+31/105v5,-6691x4y-10158x3y2-5372x2y3+4132xy4+106/9y5+15600x4z-803x3yz+43/29x2y2z+9/91xy3z-92/61y4z+4807x3z2-12562x2yz2+14234xy2z2-91/17y3z2-91/30x2z3-10615xyz3-4206y2z3-29/45xz4-11/86yz4-115/9z5+125/112x4u+52/59x3yu+92/49x2y2u+121/85xy3u-51/14y4u-73/48x3zu-1/110x2yzu+12/65xy2zu+15045y3zu+12826x2z2u-123/89xyz2u+9465y2z2u-67/31xz3u-5080yz3u-7944z4u-107/72x3u2+1473x2yu2+7965xy2u2+15753y3u2-95/98x2zu2-9827xyzu2-25/53y2zu2-83/54xz2u2-13217yz2u2-117/110z3u2+230x2u3-12120xyu3+11/36y2u3-2071xzu3+109/59yzu3+6909z2u3-15/64xu4+45/82yu4-3091zu4-15711u5+5957x4v-45/86x3yv+26/29x2y2v-40/57xy3v+25/43y4v+126/37x3zv-38/33x2yzv+65/109xy2zv-33/68y3zv-7287x2z2v-4842xyz2v+35/118y2z2v+6157xz3v-97/89yz3v-91/50z4v-70/27x3uv+32/9x2yuv+78/125xy2uv+38/7y3uv-3214x2zuv-68/101xyzuv+87/55y2zuv-69/98xz2uv+5805yz2uv+41/102z3uv-43/54x2u2v-42/73xyu2v-13/49y2u2v+11864xzu2v+121/37yzu2v-100/109z2u2v-12609xu3v-9114yu3v-8746zu3v+11659u4v+3799x3v2-9581x2yv2+60/91xy2v2+2029y3v2+12075x2zv2+210xyzv2-1/22y2zv2+17/58xz2v2+1212yz2v2+118/27z3v2-3571x2uv2-3139xyuv2-23/100y2uv2-1240xzuv2+71/49yzuv2-21/103z2uv2-110/71xu2v2-40/77yu2v2-103/29zu2v2+10737u3v2+2828x2v3+14/39xyv3+7564y2v3+113/50xzv3+38/79yzv3+59/66z2v3+2726xuv3+91/94yuv3-15730zuv3-13408u2v3-97/42xv4+54/29yv4-33/73zv4+4823uv4+57/71v5,-14556x3yz-9751x2y2z-45/28xy3z+85/23y4z+5623x3z2+5369x2yz2-19/60xy2z2-36/5y3z2-95/36x2z3+5862xyz3-5/93y2z3+2949xz4+11357yz4-5679z5-52/45x3yu+4448x2y2u-9/22xy3u+2427y4u+3296x3zu+16/39x2yzu+53/57xy2zu+15/41y3zu+9473x2z2u+37xyz2u-58/69y2z2u-23/56xz3u-13/90yz3u-54/29z4u-41/67x3u2+10258x2yu2+23/44xy2u2-12952y3u2+2124x2zu2-1677xyzu2+12911y2zu2+22/45xz2u2+17/84yz2u2+5910z3u2+4782x2u3+119/39xyu3-17/84y2u3-120/91xzu3+35/59yzu3+17/77z2u3-4467xu4-77/4yu4-26/53zu4-3580u5-11977x3yv-118/77x2y2v+6040xy3v+9724y4v-47/5x3zv+59/101x2yzv+1212xy2zv-7/121y3zv+93/53x2z2v-56/23xyz2v-4470y2z2v+110/111xz3v-41/99yz3v-81/10z4v-71/24x3uv+26/115x2yuv+59/39xy2uv-10029y3uv+11748x2zuv+5749xyzuv+6887y2zuv+38/3xz2uv-116/61yz2uv-55/118z3uv+105/22x2u2v+70/87xyu2v-28/13y2u2v-109/123xzu2v-102/47yzu2v-52/71z2u2v+101/95xu3v+51/16yu3v+15/97zu3v-78/125u4v+35/46x3v2-9526x2yv2+10781xy2v2-119/44y3v2-23/10x2zv2+59/29xyzv2-15144y2zv2+29/120xz2v2-53/126yz2v2-93/85z3v2+53/8x2uv2-487xyuv2-12143y2uv2+13825xzuv2+55/6yzuv2-4250z2uv2+4237xu2v2-109/9yu2v2+67/53zu2v2+82/33u3v2+8660x2v3+15046xyv3-79/84y2v3-10310xzv3+110yzv3-7636z2v3+57/92xuv3-22/119yuv3-95/103zuv3+5138u2v3+123/49xv4-7587yv4+30/41zv4-124/121uv4+54/71v5,-29/60x4y-108/77x3y2-109/37x2y3-3619xy4+109/6x4z-37/67x3yz+53/45x2y2z+5291xy3z-2927y4z+34/5x3z2+87/17x2yz2+100/89xy2z2-114/29y3z2-4057x2z3-1/42xyz3-14/61y2z3-398xz4-122/73yz4+66/37z5+99/37x4u-5691x3yu-8778x2y2u+17/115xy3u+51/113y4u-71/101x3zu+85/91x2yzu-92/9xy2zu-3442y3zu+109/26x2z2u+50/37xyz2u+77/94y2z2u+16/35xz3u+9985yz3u+5/102z4u-5932x3u2+89/125x2yu2-895xy2u2-12455y3u2-630x2zu2-64/47xyzu2+25/9y2zu2+7906xz2u2+6827yz2u2+9808z3u2-113/118x2u3+79/8xyu3+9484y2u3+62/39xzu3+6/85yzu3-23/49z2u3-93/115xu4-11/93yu4-15177zu4-13/2u5-7623x4v-103/73x3yv-96/115x2y2v+39/76xy3v+80/79y4v+43/68x3zv+45/97x2yzv+101/87xy2zv+4632y3zv-918x2z2v+8248xyz2v-4276y2z2v+8853xz3v-39/61yz3v-121/87z4v+9968x3uv+473x2yuv+117/56xy2uv-19/21y3uv+121/119x2zuv+3/98xyzuv-65/42y2zuv-3723xz2uv+7/34yz2uv-112/87z3uv+103x2u2v+25/41xyu2v-14459y2u2v-56/41xzu2v-59/81yzu2v-109/102z2u2v-87/16xu3v-13011yu3v+49/123zu3v+106/89u4v-61/51x3v2+14107x2yv2+8035xy2v2-8853y3v2+5723x2zv2+123/53xyzv2-9727y2zv2-102/83xz2v2+1111yz2v2-15745z3v2+83/118x2uv2-57/35xyuv2-48/73y2uv2-28/37xzuv2-27/97yzuv2-27/58z2uv2+71/93xu2v2+117/8yu2v2+12344zu2v2-2497u3v2-118/71x2v3-11/19xyv3+21/104y2v3+32/113xzv3+15544yzv3+31/18z2v3+5909xuv3-67/58yuv3+27/35zuv3+115/9u2v3+79/13xv4+6722yv4-37/114zv4-71/124uv4+4657v5,-77/61x4y-88/101x3y2+93/88x2y3-11/70xy4+9806y5+7896x4z-4699x3yz+55/122x2y2z-63/122xy3z-125/74y4z+47/45x3z2+101/17x2yz2+92/47xy2z2+69/82y3z2+12402x2z3+113/98xyz3-101/33y2z3-15376xz4+47/71yz4-73/10z5+65/74x4u-14409x3yu-14478x2y2u+13593xy3u+102/97y4u+39/62x3zu-34/125x2yzu-83/9xy2zu+45/113y3zu+14484x2z2u-15293xyz2u-26/55y2z2u-958xz3u+67/35yz3u-93/19z4u+25/16x3u2+107/52x2yu2-4599xy2u2-86/51y3u2-9885x2zu2-77/47xyzu2+33/65y2zu2+90/109xz2u2-61/26yz2u2+6198z3u2-38/37x2u3-13935xyu3-142y2u3-64/5xzu3-7228yzu3+1251z2u3+1556xu4+117/121yu4-92/35zu4+99/92u5+13493x4v+12654x3yv+32/101x2y2v-11118xy3v+43/51y4v-575x3zv+103/21x2yzv+85/24xy2zv+1788y3zv+85/3x2z2v-64/25xyz2v+57/35y2z2v+37/120xz3v-69/110yz3v+48/49z4v+55/114x3uv-6439x2yuv+31/51xy2uv-90/49y3uv-45/104x2zuv-12018xyzuv+6/119y2zuv+40/63xz2uv+20/91yz2uv+50/43z3uv+1/26x2u2v-109/47xyu2v+99/7y2u2v+72/83xzu2v+61/118yzu2v+3530z2u2v+6146xu3v+117yu3v-9921zu3v-8708u4v-10/47x3v2-15294x2yv2-7336xy2v2+1/66y3v2-3057x2zv2+74/123xyzv2+146y2zv2-103/34xz2v2-117/76yz2v2+8472z3v2-7/92x2uv2+10033xyuv2+43/53y2uv2+4694xzuv2-49/2yzuv2-71/73z2uv2-125/17xu2v2-9817yu2v2+7218zu2v2+6897u3v2-19/90x2v3+11899xyv3-11779y2v3-5456xzv3+17/42yzv3+15340z2v3+12/7xuv3+9580yuv3-502zuv3-14069u2v3-4371xv4+14452yv4-9423zv4-117/122uv4+1126v5,49/108x4-39/4x3y-67/21x2y2-8/69xy3-9779y4+57/14x3z-11145x2yz+6928xy2z-7824y3z+1/79x2z2+5173xyz2-62/15y2z2-123/112xz3+88/79yz3+1/125z4+57/23x3u-11856x2yu-7444xy2u+115/8y3u-11133x2zu+71/73xyzu-7941y2zu+69/65xz2u+22/75yz2u+65/121z3u+9471x2u2+9167xyu2+51/59y2u2+12835xzu2+15047yzu2+11102z2u2-10059xu3+19/28yu3+65/21zu3-39/28u4-3/73x3v+94/61x2yv+8778xy2v-12922y3v-8711x2zv-37/97xyzv+14270y2zv+4487xz2v-59/112yz2v-14183z3v+15553x2uv+3579xyuv+114/91y2uv-4/97xzuv+13/85yzuv-89/15z2uv+58/75xu2v-34/7yu2v-90/61zu2v+90/101u3v-14673x2v2+90/19xyv2-45/37y2v2+23/49xzv2-71/11yzv2+119/8z2v2+89/10xuv2+109/91yuv2+36/49zuv2-7/31u2v2-40/113xv3-21/121yv3+9910zv3+33/14uv3-23/79v4,93/70x4-43/125x3y+9582x2y2+7565xy3-11511y4-3/79x3z-36/107x2yz-2038xy2z+879y3z-4700x2z2+103/14xyz2+102/79y2z2-67/68xz3-44/25yz3+105/79z4-29/24x3u-74/83x2yu+67/43xy2u+49/12y3u-115/11x2zu+23/67xyzu-61/27y2zu+12257xz2u+14068yz2u+23/15z3u+607x2u2+73/8xyu2+14237y2u2-13/33xzu2+110/71yzu2+41/101z2u2+5708xu3+88/67yu3+1460zu3-2472u4-1629x3v-51/70x2yv-88/73xy2v-36/97y3v+38/11x2zv+15899xyzv+54/19y2zv+9460xz2v-5150yz2v+3462z3v+5522x2uv-19/123xyuv+14871y2uv+53/5xzuv-7535yzuv-13430z2uv+107/47xu2v-8307yu2v-55/79zu2v-11945u3v-16/83x2v2+115/48xyv2+12389y2v2+11545xzv2-25/26yzv2-3755z2v2+4724xuv2-31/21yuv2+7872zuv2+89/45u2v2+87/47xv3+7625yv3+13494zv3-15376uv3-25/126v4;TestGRRes(Name, I); kill R, Name, @p; ""; string Name = "rat.d10.g9.quart2"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp;ideal I = x3yu2-48/11x2y2u2-8356xy3u2+35/121y4u2+31/66x3zu2-54/83x2yzu2-61/18xy2zu2+11526y3zu2+7372x2z2u2-91/60xyz2u2-95/97y2z2u2-45/71xz3u2+71/115yz3u2+25/54z4u2-61/102x3u3-12668x2yu3+6653xy2u3+41/54y3u3+87/50x2zu3-5004xyzu3+13924y2zu3+2310xz2u3-93/14yz2u3-2/93z3u3-97/125x2u4-58/11xyu4+46/73y2u4-4417xzu4+60/101yzu4+56/75z2u4-113/118xu5+115/4yu5-40zu5-8554u6-54/83x3yuv-9770x2y2uv-590xy3uv+15/49y4uv+94/69x3zuv+121/105x2yzuv+95/88xy2zuv+3186y3zuv+11/6x2z2uv-44/81xyz2uv+637y2z2uv+109/121xz3uv-33yz3uv-94/115z4uv-49/95x3u2v-11/109x2yu2v+45/113xy2u2v+97/84y3u2v+5257x2zu2v+99/49xyzu2v+12584y2zu2v-4294xz2u2v+1137yz2u2v-58/69z3u2v-4749x2u3v+120/97xyu3v-31/103y2u3v+62/97xzu3v-107/74yzu3v+53/59z2u3v+91/33xu4v+1291yu4v+23/34zu4v+58/77u5v+16/17x3yv2-750x2y2v2+86/89xy3v2+123/46y4v2+53/123x3zv2-61/99x2yzv2+12389xy2zv2+10419y3zv2+43/11x2z2v2-146xyz2v2-116/51y2z2v2+13/62xz3v2-5524yz3v2-111/118z4v2-56/55x3uv2-3038x2yuv2+14/27xy2uv2-43/64y3uv2+3385x2zuv2+25/11xyzuv2+92/41y2zuv2+28/113xz2uv2-2049yz2uv2+89/37z3uv2-13094x2u2v2-2774xyu2v2+15474y2u2v2-15791xzu2v2-71/116yzu2v2+77/41z2u2v2-83/68xu3v2-33/106yu3v2+71/37zu3v2-41/17u4v2+12052x3v3+1906x2yv3+13825xy2v3+80/7y3v3-125/96x2zv3-9661xyzv3+85/116y2zv3-72/91xz2v3+13/112yz2v3-126/97z3v3-1637x2uv3+34/103xyuv3+3844y2uv3+77/10xzuv3+6359yzuv3-11185z2uv3-124/121xu2v3+66/91yu2v3-14636zu2v3-1051u3v3+9/64x2v4-12924xyv4-119/41y2v4+74/23xzv4+1622yzv4+73/37z2v4-60/101xuv4+111/22yuv4-45/124zuv4+59/37u2v4-66/37xv5-71/99yv5+12409zv5-113/64uv5-5267v6,-x4y-22/79x3y2-125/42x2y3-116/7xy4+98/111y5-31/66x4z-118/75x3yz+110/93x2y2z-43/92xy3z-788y4z-7372x3z2-2701x2yz2-67/124xy2z2-117/62y3z2+45/71x2z3-8396xyz3-10343y2z3-25/54xz4+30/59yz4+61/102x4u+11736x3yu+12726x2y2u+41/118xy3u-15832y4u-87/50x3zu-130x2yzu+41/8xy2zu-10300y3zu-2310x2z2u-101/5xyz2u+6205y2z2u+2/93xz3u+8679yz3u+97/125x3u2-43/37x2yu2-39/80xy2u2+12139y3u2+4417x2zu2+4294xyzu2+11/58y2zu2-56/75xz2u2+8338yz2u2+113/118x2u3-10190xyu3-37/16y2u3+40xzu3+74/23yzu3+8554xu4+115/22yu4-39/79x4v+61/72x3yv+8048x2y2v-9201xy3v+16/121y4v+113/93x3zv+109/75x2yzv+12700xy2zv-10607y3zv+50/11x2z2v+1223xyz2v-103/79y2z2v-123/58xz3v+31/26yz3v-15/122z4v+122/25x3uv-99/17x2yuv+1723xy2uv-38/121y3uv+11016x2zuv-25/102xyzuv-14970y2zuv-61/6xz2uv-14981yz2uv+15900z3uv+3268x2u2v-75/19xyu2v-1436y2u2v-1764xzu2v-57/41yzu2v+12741z2u2v-14615xu3v+119/61yu3v-115/119zu3v+10501u4v-8502x3v2-51/76x2yv2-6281xy2v2+17/49y3v2-106/7x2zv2+63/101xyzv2-27/95y2zv2-1606xz2v2+9245yz2v2+1912z3v2+11155x2uv2+223xyuv2-13/18y2uv2+110/43xzuv2+76/81yzuv2-6291z2uv2+1400xu2v2-95/23yu2v2-9701zu2v2+106/105u3v2+72/47x2v3-13118xyv3+14409y2v3+37/86xzv3+44/69yzv3-325z2v3+113/71xuv3+16/81yuv3+6/19zuv3-119/39u2v3-89/9xv4+72/53yv4+112/55zv4-8587uv4-6604v5,-x3y2+48/11x2y3+8356xy4-35/121y5-12750x3yz+100/111x2y2z+45/74xy3z+99/74y4z-6/7x3z2-47/67x2yz2+11465xy2z2-11865y3z2+7776x2z3+124/45xyz3-98/115y2z3+117/85xz4-59/120yz4-8748z5+61/102x3yu+12668x2y2u-6653xy3u-41/54y4u+13408x3zu-2185x2yzu-1240xy2zu+1161y3zu+44/27x2z2u-11164xyz2u-13388y2z2u-107/13xz3u+90/71yz3u+4204z4u+97/125x2yu2+58/11xy2u2-46/73y3u2+55/48x2zu2+121/31xyzu2+126/61y2zu2-55/69xz2u2+5988yz2u2+3755z3u2+113/118xyu3-115/4y2u3+3390xzu3-5762yzu3+30/61z2u3+8554yu4-14317zu4+99/116x3yv-113/119x2y2v+50/23xy3v-37/79y4v-8668x3zv+14049x2yzv+111/35xy2zv+61/28y3zv-10171x2z2v+68/21xyz2v+2023y2z2v-9/109xz3v+8520yz3v-2683z4v-13547x3uv+28/65x2yuv-5988xy2uv+61/111y3uv+12314x2zuv+29/44xyzuv+6141y2zuv+11280xz2uv+79/22yz2uv-38/111z3uv+19/51x2u2v+5093xyu2v-10291y2u2v-5009xzu2v-111/49yzu2v+3813z2u2v-61/37xu3v+15914yu3v-3218zu3v-12915u4v-118/101x3v2-7/57x2yv2+13128xy2v2+11606y3v2+42/101x2zv2-54/17xyzv2-43/49y2zv2-119/110xz2v2+9742yz2v2-43/4z3v2-55/8x2uv2-29/88xyuv2+12042y2uv2+101/37xzuv2-57/62yzuv2+106/97z2uv2+38/83xu2v2+8152yu2v2-5492zu2v2-47/79u3v2+15112x2v3+69/44xyv3-6/71y2v3+113/54xzv3-13210yzv3-707z2v3-119/8xuv3+3845yuv3-19/20zuv3+4852u2v3+15761xv4-12372yv4+74/69zv4-2100uv4-12833v5,-x3yz+48/11x2y2z+8356xy3z-35/121y4z-31/66x3z2+54/83x2yz2+61/18xy2z2-11526y3z2-7372x2z3+91/60xyz3+95/97y2z3+45/71xz4-71/115yz4-25/54z5+15/52x3yu+6039x2y2u+74/99xy3u-17/40y4u+29/50x3zu-7775x2yzu+6368xy2zu+14170y3zu+52/41x2z2u+7003xyz2u-5787y2z2u-101/37xz3u-23/28yz3u-20/63z4u+41/77x3u2+8650x2yu2-15922xy2u2-16/83y3u2+7278x2zu2+31/30xyzu2-2/107y2zu2+35/122xz2u2+85/58yz2u2-757z3u2+2/101x2u3+86/17xyu3+95/59y2u3+123/22xzu3-6869yzu3-9311z2u3-105/97xu4+5699yu4+15925zu4+13528u5-154x3yv+4187x2y2v+56/107xy3v-15932y4v-5137x3zv-37/56x2yzv+9401xy2zv+92/123y3zv-79/97x2z2v+9201xyz2v+19/53y2z2v+107/20xz3v+17/77yz3v-15306z4v+3215x3uv-79/117x2yuv-9/76xy2uv-6352y3uv+93/13x2zuv-65/89xyzuv-115/4y2zuv-34/57xz2uv+39/107yz2uv+31/9z3uv+107/48x2u2v+2632xyu2v+29/96y2u2v-125/89xzu2v+29/113yzu2v+3940z2u2v-116/111xu3v+6145yu3v-105/62zu3v+101/17u4v-9281x3v2-49/107x2yv2-12154xy2v2+4/19y3v2-114/71x2zv2-15/118xyzv2+4372y2zv2+45/121xz2v2+46/111yz2v2+6614z3v2+17x2uv2+10806xyuv2-10617y2uv2-25/111xzuv2-116/27yzuv2-7/58z2uv2-686xu2v2+3/13yu2v2-17/49zu2v2-40/107u3v2+47/90x2v3-83/43xyv3-6326y2v3+49/64xzv3+113/76yzv3-122/73z2v3+10232xuv3-116/109yuv3-1990zuv3+70/51u2v3-118/19xv4-27/55yv4+21/19zv4-23/57uv4-11721v5,-3399x4y+1849x3y2-3/29x2y3+28/87xy4+10/29y5-9788x4z-49/73x3yz+13829x2y2z+118/73xy3z+13129y4z-618x3z2+92/13x2yz2+101/117xy2z2-162y3z2+24/5x2z3-29/74xyz3+2687y2z3-74/39xz4+2/57yz4+68/73x4u-13787x3yu-11659x2y2u+14729xy3u+92/53y4u+15/71x3zu-62/15x2yzu+21/85xy2zu+4938y3zu-120/37x2z2u-77/102xyz2u-4785y2z2u-83/70xz3u-12128yz3u-13592z4u-123/20x3u2+2607x2yu2+40/19xy2u2+6361y3u2-3091x2zu2+89/113xyzu2+149y2zu2-2890xz2u2-8374yz2u2+11886z3u2-49/43x2u3-9854xyu3-6943y2u3+10743xzu3-122/45yzu3-13902z2u3-103/19xu4-48/59yu4+27/86zu4+46/35u5-117/17x4v-15/7x3yv+8409x2y2v-83/28xy3v+86/35y4v+37/45x3zv+4/3x2yzv+35/38xy2zv+4015y3zv-49/111x2z2v-1260xyz2v-25/33y2z2v+116/19xz3v+93/8yz3v+5755z4v-25/89x3uv-11669x2yuv-64/107xy2uv+2993y3uv+7767x2zuv-17/95xyzuv-103/80y2zuv-14576xz2uv+80/47yz2uv+25/107z3uv+103/2x2u2v+125/117xyu2v-2/89y2u2v-5298xzu2v-50/27yzu2v-71/53z2u2v+2652xu3v+15761yu3v+2124zu3v+11/82u4v+100/63x3v2+4180x2yv2+11/39xy2v2-1221y3v2+108/125x2zv2+97/126xyzv2-7698y2zv2+13984xz2v2+1342yz2v2-84/121z3v2-26/73x2uv2-14/15xyuv2-22/37y2uv2-71/82xzuv2+12430yzuv2+103/52z2uv2-13095xu2v2+10114yu2v2-8/73zu2v2-33/97u3v2+83/105x2v3+22/45xyv3-7961y2v3-9654xzv3-54/55yzv3-3/71z2v3-10148xuv3-117/98yuv3+101/102zuv3-606u2v3+97/43xv4-68/21yv4+63/16zv4+42/17uv4+5834v5,-3399x3y2-32/113x2y3+14/99xy4+15001y5-121/115x3yz+4604x2y2z+7/2xy3z+9532y4z-3267x3z2+97/118x2yz2-14238xy2z2-80/21y3z2-12332x2z3-19/69xyz3+116/15y2z3-103/32xz4+15340yz4+10509z5+112/109x3yu-97x2y2u-40/11xy3u+90/29y4u-95/106x3zu-114/67x2yzu+113/48xy2zu+12080y3zu-44x2z2u+18/17xyz2u-4814y2z2u-103/100xz3u-96/61yz3u-205z4u-87/82x3u2-97/108x2yu2+3230xy2u2+104/83y3u2+41/86x2zu2+116/49xyzu2-59/110y2zu2+14/59xz2u2-6962yz2u2-2185z3u2+59/91x2u3+2497xyu3+3/37y2u3-13010xzu3+6/83yzu3-11448z2u3+13/72xu4-69/62yu4-2869zu4+23/73u5-20/43x3yv+5074x2y2v+28/125xy3v-2706y4v+13010x3zv-17/109x2yzv+21/4xy2zv+59/93y3zv-2406x2z2v+117/11xyz2v-14978y2z2v+70/89xz3v-33/7yz3v-13676z4v-13690x3uv+9825x2yuv-117/107xy2uv+12760y3uv-93/98x2zuv-113/64xyzuv+113/103y2zuv-9748xz2uv+11016yz2uv-10729z3uv+90/13x2u2v-13/47xyu2v-11/39y2u2v+20/69xzu2v+5531yzu2v+125/49z2u2v-11025xu3v-9621yu3v+113/109zu3v+4710u4v-107/7x3v2+110/119x2yv2-10025xy2v2-6644y3v2-5041x2zv2+5/96xyzv2+11472y2zv2-5128xz2v2+2927yz2v2+121/18z3v2-125/89x2uv2+12936xyuv2-71/47y2uv2+34/47xzuv2-75/103yzuv2-2654z2uv2-2350xu2v2-7707yu2v2+47/72zu2v2-952u3v2-21/67x2v3+58/37xyv3-8757y2v3+3615xzv3+44/123yzv3-13027z2v3-9/10xuv3+75/43yuv3+115/18zuv3+8071u2v3-26/3xv4-67/65yv4+14186zv4-41/122uv4+33/28v5,-3399x3yz-32/113x2y2z+14/99xy3z+15001y4z-9788x3z2+37/96x2yz2+7743xy2z2+31/55y3z2-618x2z3-8171xyz3+82/109y2z3+24/5xz4+88/85yz4-74/39z5-13165x3yu+3407x2y2u-12509xy3u-23/45y4u-11774x3zu-10/67x2yzu+69/79xy2zu-10/123y3zu-7636x2z2u+83/32xyz2u+51/112y2z2u+19/8xz3u+9309yz3u-44/49z4u+4089x3u2-374x2yu2-919xy2u2+98/107y3u2+2776x2zu2+85/26xyzu2+31/13y2zu2-103/82xz2u2+35/76yz2u2+59/45z3u2+2950x2u3+27/44xyu3+88/71y2u3+7/114xzu3-72/77yzu3+12917z2u3-34/67xu4-85/82yu4-55/84zu4+4690u5+11/42x3yv-19/125x2y2v-8288xy3v+9199y4v-12929x3zv+13357x2yzv-4903xy2zv-584y3zv-10/33x2z2v+59/113xyz2v+103/92y2z2v+101/69xz3v+8708yz3v-8/7z4v+13560x3uv-43/49x2yuv-121/98xy2uv+75/79y3uv-39x2zuv-88/69xyzuv-89/78y2zuv+110/67xz2uv+61/4yz2uv-98/45z3uv+82/7x2u2v-85/41xyu2v+6548y2u2v+9367xzu2v-59/81yzu2v-14408z2u2v+2363xu3v-80/11yu3v-50/17zu3v-14799u4v-53/21x3v2+9437x2yv2-117/80xy2v2+81/85y3v2-8/45x2zv2-6428xyzv2+15126y2zv2+68/89xz2v2+7/122yz2v2+9639z3v2+113/4x2uv2-8678xyuv2-104/45y2uv2-79/90xzuv2+39/101yzuv2-7234z2uv2-28/43xu2v2+1251yu2v2-97/56zu2v2+17/41u3v2+107/24x2v3+2747xyv3+9933y2v3-4199xzv3+53/83yzv3+6364z2v3-5456xuv3+618yuv3-123/55zuv3+2375u2v3+63/76xv4-115/106yv4-8811zv4-31/75uv4+10/109v5,13/89x4y+77/31x3y2+36/83x2y3-11411xy4+6936y5-12223x4z+7400x3yz+33/118x2y2z-12146xy3z+108/79y4z+82/99x3z2-9877x2yz2-79/70xy2z2-19/123y3z2-1491x2z3+7953xyz3-43/126y2z3+60/17xz4+98/57yz4-13317x4u-77/27x3yu-6811x2y2u-69/61xy3u+6144y4u+5404x3zu+121/120x2yzu-91/23xy2zu-71/106y3zu+1435x2z2u-120/13xyz2u-12019y2z2u-68/7xz3u-113/82yz3u+11526z4u-8706x3u2-89/53x2yu2-14804xy2u2+120/107y3u2+71/94x2zu2-1/70xyzu2+1532y2zu2+4470xz2u2+13/60yz2u2-115/102z3u2-82/21x2u3+27/121xyu3-4439y2u3-101/47xzu3-3186yzu3-106/101z2u3-10169xu4+19/58yu4-96/73zu4-7959u5-10526x4v-107/92x3yv+47/6x2y2v-23/43xy3v-69/62y4v+59/65x3zv-28/95x2yzv+5479xy2zv-39/77y3zv+11/69x2z2v-11713xyz2v+43/79y2z2v-15602xz3v+16/73yz3v-13952z4v+61/82x3uv-2219x2yuv-91/106xy2uv+5/37y3uv-148x2zuv+31/51xyzuv+18/101y2zuv+97/68xz2uv-73/32yz2uv+47/2z3uv+2/41x2u2v-13009xyu2v-7/60y2u2v+15779xzu2v+72/7yzu2v-11/73z2u2v-119/44xu3v-9067yu3v+3249zu3v+61/51u4v+12525x3v2-118/9x2yv2-3270xy2v2-4/25y3v2-5075x2zv2+77/40xyzv2-89/65y2zv2+17/58xz2v2-15609yz2v2+95/54z3v2-75/79x2uv2-4907xyuv2+12418y2uv2-57/17xzuv2-8746yzuv2+13/95z2uv2-124/67xu2v2+16/13yu2v2+28/23zu2v2-10847u3v2-645x2v3+106/75xyv3+6/115y2v3-8495xzv3+58/35yzv3-9398z2v3-101/72xuv3-71/20yuv3-124/65zuv3-8971u2v3+27/28xv4+12/29yv4-4276zv4+10858uv4+29/12v5,13/89x3y2+12068x2y3-15543xy4-77/79y5+6626x3yz+64/53x2y2z-6/23xy3z-47/125y4z+14403x3z2-43/78x2yz2-31/115xy2z2+94/59y3z2-118/117x2z3-11229xyz3+2268y2z3-116/85xz4+25/58yz4+3085z5+59/27x3yu+67/82x2y2u+11/6xy3u+103/47y4u-63/80x3zu-81/47x2yzu+7760xy2zu-115/56y3zu-10/17x2z2u+101/5xyz2u+15634y2z2u+1/107xz3u-9282yz3u+43/62z4u+62/55x3u2+100/113x2yu2-9205xy2u2-46/13y3u2+43/96x2zu2+10159xyzu2+692y2zu2+859xz2u2-19/74yz2u2+123/47z3u2-9/20x2u3-11391xyu3-2375y2u3+109/24xzu3-57/53yzu3-925z2u3-82/45xu4+97/34yu4+13/82zu4-108/29u5+63/10x3yv+38/17x2y2v-19/115xy3v+3150y4v+22/69x3zv+26/57x2yzv+110/27xy2zv+87/77y3zv+85/18x2z2v+39/47xyz2v-48/17y2z2v-7/27xz3v-13/100yz3v-11662z4v-17/8x3uv+37/11x2yuv+29/11xy2uv-109/88y3uv-2817x2zuv-61/44xyzuv+10/31y2zuv+10010xz2uv+51/86yz2uv-97/83z3uv-89/96x2u2v+4030xyu2v-58/77y2u2v-114/43xzu2v-37/10yzu2v-2011z2u2v+14483xu3v-109/101yu3v+121/102zu3v-79/92u4v+15113x3v2+10781x2yv2-14259xy2v2-113/48y3v2-7/94x2zv2-17/74xyzv2-5/117y2zv2-59/75xz2v2+13188yz2v2+103/43z3v2+4/125x2uv2-52/59xyuv2+85/92y2uv2-1/46xzuv2-9106yzuv2-83/11z2uv2-23/94xu2v2+6742yu2v2-35/107zu2v2-14596u3v2-117/43x2v3+1026xyv3+90/19y2v3+14671xzv3-101/100yzv3+6962z2v3+61/68xuv3+108/37yuv3-4157zuv3-3974u2v3+15677xv4+8661yv4+8459zv4-16/23uv4-37/119v5,13/89x3yz+12068x2y2z-15543xy3z-77/79y4z-12223x3z2-13941x2yz2+115/84xy2z2+13/98y3z2+82/99x2z3+7751xyz3+122/17y2z3-1491xz4+1327yz4+60/17z5+15363x3yu+9780x2y2u+19/117xy3u-1924y4u-14600x3zu+46/41x2yzu-5466xy2zu-73/12y3zu+10838x2z2u-8302xyz2u-89/113y2z2u+53/69xz3u-9224yz3u+47/33z4u-7399x3u2+89/77x2yu2+9312xy2u2-41/80y3u2-732x2zu2-6781xyzu2-8608y2zu2-9270xz2u2-117/58yz2u2-115/68z3u2-48/31x2u3-9067xyu3+97/107y2u3+73/57xzu3-2719yzu3-110/59z2u3-37/86xu4-15796yu4-61/4zu4-115/72u5+6161x3yv+4134x2y2v+677xy3v-8375y4v+1150x3zv+1551x2yzv+4157xy2zv+112/87y3zv+8171x2z2v+6040xyz2v+15651y2z2v-7/66xz3v-47/61yz3v+77/64z4v+14848x3uv+48/119x2yuv-9534xy2uv-117/95y3uv+5/4x2zuv+122xyzuv+90/31y2zuv-41/26xz2uv+31/30yz2uv-10428z3uv-9896x2u2v-71/21xyu2v-55/38y2u2v-29/22xzu2v-11092yzu2v+39/122z2u2v+93/73xu3v+22/49yu3v-21/106zu3v+56u4v+8565x3v2-1695x2yv2+2/17xy2v2+1/78y3v2-113/71x2zv2-41/100xyzv2+55/14y2zv2+15286xz2v2+17/53yz2v2+126/71z3v2-79/87x2uv2+109/97xyuv2-28/31y2uv2-6533xzuv2+22/5yzuv2-10449z2uv2+10830xu2v2-15516yu2v2+28/57zu2v2-81/22u3v2+4198x2v3+5667xyv3-7133y2v3-8408xzv3+11066yzv3-26/125z2v3-808xuv3+95/54yuv3-64/17zuv3-5267u2v3-15333xv4+42/89yv4+63/85zv4+119/113uv4-2011v5,5583x4y+1725x3y2-8652x2y3-91/25xy4-8495x4z-13731x3yz+9298x2y2z-41/111xy3z-15503y4z-13805x3z2+3962x2yz2-2/63xy2z2+3314y3z2+2522x2z3-10/87xyz3-408y2z3+7/16xz4+69/22yz4-7254z5-59/21x4u+115/7x3yu-1718x2y2u+7851xy3u+2632y4u-82/3x3zu+37/86x2yzu+101/113xy2zu+6747y3zu-109/113x2z2u+7399xyz2u+24/103y2z2u+89/9xz3u-14630yz3u+15066z4u-12561x3u2+113/115x2yu2+87/97xy2u2-126/67y3u2-48/7x2zu2+123/103xyzu2-11/107y2zu2-2747xz2u2+8158yz2u2-3/107z3u2+41/6x2u3+12767xyu3+3873y2u3+74/83xzu3-55/119yzu3-24/83z2u3+55xu4-7/95yu4+57/44zu4+2/101u5-6928x4v-121/57x3yv+111/104x2y2v+946xy3v-29y4v+3057x3zv-14/25x2yzv+43/31xy2zv-105/2y3zv+2336x2z2v+61/77xyz2v-7880y2z2v+5/58xz3v+10593yz3v+7094z4v+63/59x3uv-5/69x2yuv-11/81xy2uv-4157y3uv+73/65x2zuv-1676xyzuv-2376y2zuv-85/63xz2uv-95/2yz2uv-14903z3uv-119/110x2u2v-115/24xyu2v+125/9y2u2v+106/87xzu2v-13/12yzu2v-4/19z2u2v+7838xu3v-43/111yu3v+7/113zu3v-12500u4v+7743x3v2-2023x2yv2-85/83xy2v2+49/41y3v2+20/87x2zv2+3932xyzv2-77/6y2zv2+47/90xz2v2-15580yz2v2+39/4z3v2-61/8x2uv2+2518xyuv2+29/98y2uv2+11057xzuv2-18/107yzuv2+708z2uv2+14720xu2v2-3175yu2v2-113/59zu2v2-14735u3v2+7/69x2v3-4029xyv3+54/91y2v3+12372xzv3+67/2yzv3+8856z2v3-2178xuv3+995yuv3+64/95zuv3+4039u2v3-37/44xv4+23/17yv4-3035zv4-103/124uv4+69/64v5,-5583x3y2-1725x2y3+8652xy4+91/25y5+6201x3yz-73/49x2y2z-3844xy3z+10548y4z-11057x3z2-105/122x2yz2+31/53xy2z2+79/89y3z2-24/101x2z3+107/119xyz3-126y2z3+8164xz4+2/77yz4-51/8z5-14941x3yu-106x2y2u+8695xy3u+125/62y4u+4328x3zu+29/117x2yzu-6249xy2zu-2791y3zu+67/49x2z2u-38/29xyz2u+122/41y2z2u+10603xz3u-3029yz3u+5578z4u+14754x3u2-108/79x2yu2+4408xy2u2-12401y3u2-1426x2zu2-1741xyzu2-83/86y2zu2+79/95xz2u2+122/121yz2u2+81/2z3u2-1172x2u3-41/68xyu3-70/3y2u3+24/107xzu3+120/79yzu3+18/119z2u3-65/122xu4+1018yu4+22/107zu4+15189u5+5/8x3yv-12060x2y2v+3/62xy3v-227y4v+60/41x3zv-123/115x2yzv+110/123xy2zv+12864y3zv-86/121x2z2v-69/94xyz2v+14/79y2z2v+118/45xz3v+10842yz3v-37/58z4v+100/69x3uv-47/65x2yuv-7/67xy2uv-93/100y3uv-6262x2zuv-4/75xyzuv+2082y2zuv-9117xz2uv+12450yz2uv-84/67z3uv+123/26x2u2v-51/89xyu2v+19/74y2u2v-104/77xzu2v+318yzu2v+12402z2u2v+95/8xu3v-81/26yu3v-4486zu3v+3872u4v+72/91x3v2-83/63x2yv2+93/92xy2v2-15924y3v2-53/62x2zv2+6046xyzv2+1408y2zv2+60/107xz2v2-1150yz2v2-126/19z3v2-7429x2uv2+2554xyuv2+3602y2uv2+10738xzuv2-57/64yzuv2+86/69z2uv2+8172xu2v2+91/113yu2v2+92/65zu2v2+118/37u3v2+47/83x2v3+12750xyv3+10851y2v3+4216xzv3+6/101yzv3-108z2v3+2920xuv3-101/102yuv3-157zuv3+7742u2v3-7234xv4-2/111yv4+59/33zv4-93/91uv4+24/19v5,1592x4y+75/121x3y2+40/19x2y3-2651xy4+9934x4z+245x3yz+11665x2y2z+30/41xy3z+1823y4z+89/88x3z2-105/46x2yz2+79/58xy2z2-4191y3z2-76/61x2z3-21/32xyz3-9516y2z3-14896xz4-85/77yz4+51/109z5+61/30x4u-10/101x3yu+11796x2y2u+76/101xy3u+123/88y4u-5932x3zu-11857x2yzu+7128xy2zu-45/79y3zu+119/18x2z2u+9/74xyz2u+7042y2z2u-1114xz3u-11/82yz3u-1466z4u-6/85x3u2+27/106x2yu2+14246xy2u2-6216y3u2+47/6x2zu2-45/59xyzu2+89/41y2zu2+41/80xz2u2-7583yz2u2-75/113z3u2-14808x2u3-10873xyu3-90/67y2u3-11081xzu3-7369yzu3-7131z2u3-1402xu4-15386yu4-108/73zu4-5039u5+120/113x4v+10617x3yv-50/87x2y2v-2395xy3v-20/69y4v-8587x3zv+12960x2yzv-41/50xy2zv-13844y3zv-65/32x2z2v-77/122xyz2v-85/66y2z2v+13/100xz3v-20/51yz3v-13676z4v+76/97x3uv+1046x2yuv-8059xy2uv-117/59y3uv-29/105x2zuv+7287xyzuv-107/119y2zuv-35/118xz2uv+79/86yz2uv-2211z3uv+5448x2u2v+62/35xyu2v-2275y2u2v+29/121xzu2v-1674yzu2v-56/43z2u2v-3377xu3v-43/110yu3v+23/10zu3v-24/61u4v+121/53x3v2-4745x2yv2-57/64xy2v2+9554y3v2-12741x2zv2+10449xyzv2+37/108y2zv2+8621xz2v2-11/57yz2v2+1566z3v2+125/49x2uv2-121/118xyuv2+109/84y2uv2-335xzuv2+10167yzuv2-59/109z2uv2-103/119xu2v2+43/13yu2v2-73/87zu2v2+2037u3v2+13002x2v3+83/48xyv3-10713y2v3+1026xzv3-105/64yzv3-37/6z2v3+14779xuv3-6448yuv3+19/69zuv3-1/110u2v3+10010xv4+79/12yv4+12/19zv4-35/61uv4-11/57v5,-1592x3y2-75/121x2y3-40/19xy4+2651y5+39/121x3yz+122/77x2y2z-114/31xy3z+1544y4z+2/3x3z2-10271x2yz2-8373xy2z2+56/61y3z2+55/48x2z3-116xyz3-25/7y2z3-108/113xz4-34/53yz4+5548z5-122x3yu-9690x2y2u+43/87xy3u-5/19y4u+97/54x3zu-17/19x2yzu+4355xy2zu+12/5y3zu-1/100x2z2u+12754xyz2u+13600y2z2u+17/45xz3u-12091yz3u+5145z4u-63/64x3u2-84/31x2yu2-97/41xy2u2+7/13y3u2-79/62x2zu2-80/103xyzu2-69/14y2zu2+119/4xz2u2-35/87yz2u2-13840z3u2+14101x2u3+7952xyu3-1857y2u3-9861xzu3+3180yzu3+75/107z2u3-250xu4-15134yu4+4717zu4-2/41u5+22/27x3yv-8983x2y2v+10520xy3v-113/2y4v+10/73x3zv-1986x2yzv-110/13xy2zv+1550y3zv+32/111x2z2v-111/35xyz2v+101/98y2z2v+8045xz3v-2/89yz3v+2924z4v-79/11x3uv-15178x2yuv+10874xy2uv+54/11y3uv-8950x2zuv+70/53xyzuv-2403y2zuv-8249xz2uv+6935yz2uv+20/89z3uv+885x2u2v-76/71xyu2v-4/17y2u2v-31/52xzu2v-4/99yzu2v+10333z2u2v-93/104xu3v+82/101yu3v-71/37zu3v+9397u4v-15/112x3v2-6614x2yv2+119/2xy2v2+88/119y3v2+306x2zv2+2790xyzv2+10992y2zv2-115/74xz2v2-14711yz2v2+11612z3v2-1788x2uv2-75/97xyuv2+79/30y2uv2+99/59xzuv2-11439yzuv2-121/113z2uv2+108/37xu2v2+37/36yu2v2-3/65zu2v2-55/42u3v2+13/100x2v3-209xyv3-1272y2v3-117/68xzv3+63/94yzv3+32/59z2v3+1013xuv3-3463yuv3+6946zuv3-37/86u2v3+67/117xv4+85/28yv4-3024zv4-82/9uv4-32/65v5,-35/52x4y-12140x3y2+23/83x2y3+69/5xy4-80/79y5+120/43x4z-11865x3yz-3487x2y2z+53/59xy3z+53/102y4z-14083x3z2-14430x2yz2-2442xy2z2-33/104y3z2-91/38x2z3+4/87xyz3-26/57y2z3+4097xz4-9/122yz4+6364z5+9634x4u-97/95x3yu-46/99x2y2u+3847xy3u+121/106y4u+12765x3zu-5292x2yzu+1607xy2zu-67/121y3zu-12/35x2z2u+4/55xyz2u-17/27y2z2u+91/122xz3u-23/31yz3u+65/49z4u+73/46x3u2-124/27x2yu2-9933xy2u2+46/75y3u2+53/114x2zu2+3503xyzu2-14147y2zu2-11283xz2u2+11889yz2u2+99/104z3u2+3117x2u3+12624xyu3-10060y2u3+2193xzu3-80/47yzu3-77/13z2u3+11/31xu4-47/90yu4+49/48zu4-2/105u5-92/61x4v+7443x3yv+35/76x2y2v+114/67xy3v-73/126y4v+97/107x3zv+9464x2yzv+10869xy2zv+15718y3zv-37/33x2z2v+124/13xyz2v-11/26y2z2v-61/40xz3v+91/100yz3v-18/103z4v+60/29x3uv+21/125x2yuv-11117xy2uv+11748y3uv-16/117x2zuv+18/103xyzuv-1711y2zuv+1872xz2uv-109/123yz2uv-18/113z3uv-26/103x2u2v+14140xyu2v+11065y2u2v+8686xzu2v-5/111yzu2v+30/101z2u2v-10501xu3v-36/113yu3v-73/74zu3v+12753u4v-43/52x3v2-76/15x2yv2-5793xy2v2+18/13y3v2+1/79x2zv2+84/23xyzv2-172y2zv2+86/77xz2v2+15/37yz2v2+11835z3v2-6482x2uv2+94/113xyuv2+10727y2uv2-102/41xzuv2+15914yzuv2-12973z2uv2-9038xu2v2-13107yu2v2+1533zu2v2+12549u3v2-13528x2v3+903xyv3+23/114y2v3-123/64xzv3-81/5yzv3+111/103z2v3+4734xuv3-33/20yuv3-7954zuv3-2478u2v3+15518xv4-6723yv4-14/31zv4-3482uv4+10919v5,-3/94x4y-12936x3y2+2/11x2y3+32/23xy4-15921y5+61/93x4z+82/111x3yz-93/2x2y2z-6659xy3z-97/90y4z+402x3z2-14586x2yz2-121/39xy2z2+68/7y3z2+1212x2z3-2980xyz3+49/52y2z3-72/89xz4+92/47yz4+8478z5+2733x4u-103/89x3yu+1166x2y2u-7/53xy3u-106/23y4u+677x3zu+907x2yzu+7891xy2zu-9014y3zu+76/47x2z2u+49/116xyz2u-49/78y2z2u+12261xz3u+118/105yz3u-126/13z4u-8812x3u2-97/120x2yu2-9534xy2u2+92/5y3u2-54/71x2zu2+94/103xyzu2+2256y2zu2+4182xz2u2-5798yz2u2-31/115z3u2-73/98x2u3+15822xyu3+1004y2u3-578xzu3+9494yzu3-6779z2u3+14506xu4+10/121yu4+58/27zu4-2817u5-19/119x4v+7128x3yv+75/64x2y2v-65/109xy3v+5129y4v-53/55x3zv+54/125x2yzv-3009xy2zv+6144y3zv+15601x2z2v+123/55xyz2v-58/77y2z2v-56/61xz3v+121/10yz3v-103/86z4v-93/25x3uv+94/123x2yuv-25/107xy2uv+14807y3uv+65/7x2zuv+87/44xyzuv+6605y2zuv+23/99xz2uv-413yz2uv-17/15z3uv-79/46x2u2v+15240xyu2v-42/67y2u2v+8932xzu2v-5888yzu2v-4204z2u2v+7002xu3v-36/97yu3v-1634zu3v+61/102u4v-14/33x3v2-6520x2yv2+9004xy2v2-67/36y3v2-7/8x2zv2-24/11xyzv2-9373y2zv2+1556xz2v2-79/74yz2v2-6691z3v2+108x2uv2-76/61xyuv2+220y2uv2-1191xzuv2-4/9yzuv2+4546z2uv2+12205xu2v2+9/22yu2v2+64/93zu2v2-44/125u3v2+292x2v3+41/74xyv3+16/79y2v3-15892xzv3+5733yzv3+6796z2v3-42/55xuv3+71/79yuv3-19/104zuv3-38/15u2v3+6436xv4+28/15yv4+87/55zv4+2270uv4-30/41v5,-117/4x3y+97/122x2y2-3618xy3+6566y4+97/113x3z-12634x2yz+9865xy2z-1764y3z+114/31x2z2+5006xyz2+7/44y2z2-15040xz3+8/125yz3+11134z4-12980x3u-79/41x2yu-79/98xy2u+89/65y3u-1217x2zu+89/87xyzu+83/66y2zu+115/11xz2u+123/107yz2u+10920z3u-86/73x2u2-11/94xyu2-14054y2u2+6752xzu2-123/124yzu2+12129z2u2-13310xu3-52/63yu3+12847zu3-1545u4-11064x3v+11499x2yv-37/64xy2v+50/103y3v+123/94x2zv-126xyzv-111/44y2zv+95/14xz2v+113/83yz2v-77/103z3v+41/64x2uv+91/90xyuv-4932y2uv+103/31xzuv+62/63yzuv+1161z2uv-99/106xu2v-3181yu2v-11741zu2v-33/8u3v-3/118x2v2-9369xyv2+527y2v2-113/39xzv2-88/49yzv2-113/101z2v2+95/68xuv2-5930yuv2-20/43zuv2+7/41u2v2+109/93xv3-107/61yv3-8352zv3-5255uv3+12021v4,-2159x4-94/3x3y-4602x2y2+1609xy3+10721y4+28/9x3z-99/35x2yz+1/110xy2z+113/114y3z-118/75x2z2-103/93xyz2-68/67y2z2+13687xz3-1531yz3+61/107z4+6076x3u+9004x2yu+2211xy2u+110/53y3u+47/102x2zu+8495xyzu-9238y2zu+57/121xz2u-8543yz2u+8/19z3u-13527x2u2-13293xyu2+1138y2u2+26/115xzu2+78/53yzu2-12556z2u2+7299xu3+70/19yu3-14687zu3+13559u4+113/9x3v-85/126x2yv-83/3xy2v-3/46y3v+1814x2zv+28/79xyzv+103/51y2zv+78/31xz2v-14387yz2v+1/88z3v+116/75x2uv-101/59xyuv-70/3y2uv+109/71xzuv+13/88yzuv-147z2uv-113/76xu2v-9661yu2v+13855zu2v-6162u3v-1857x2v2-8208xyv2-4634y2v2-6178xzv2-7352yzv2-8247z2v2-113/15xuv2+99/40yuv2+21/97zuv2+11/37u2v2-6605xv3+8964yv3+35/121zv3+8543uv3-6008v4;TestGRRes(Name, I); kill R, Name, @p; ""; // if( defined(assumeLevel0) ){ assumeLevel = assumeLevel0; } else { kill assumeLevel; } // restore the state of aL } ///////////////////////////////////////////////////////// proc grzero() "USAGE: grzero() RETURN: graded object representing S(0)^1 PURPOSE: compute presentation of S(0)^1 EXAMPLE: example grzero; shows an example " { return ( grobj(freemodule(0), intvec(0:0), intvec(0:0)) ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; grview( grobj(freemodule(0), intvec(0:0), intvec(0:0)) ); grview( grobj(freemodule(0), intvec(0:0)) ); grview( grzero() ); // def M = grpower( grshift( grzero(), 3), 2 ); grview(M); } proc grtwists(intvec v) "USAGE: grtwists(v), intvec v RETURN: graded object representing S(v[1]) + ... + S(v[size(v)]) PURPOSE: compute presentation of S(v[1]) + ... + S(v[size(v)]) EXAMPLE: example grtwists; shows an example " { matrix m[size(v)][0]; return( grobj(m, -v) ); // will set the rank as well } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; grview( grtwists ( intvec(-4, 1, 6 )) ); grview( grtwists ( intvec(0:0) ) ); } proc grtwist(int a, int d) "USAGE: grtwist(a,d), int a, d RETURN: graded object representing S(d)^a PURPOSE: compute presentation of S(d)^a EXAMPLE: example grtwist; shows an example " { ASSUME(0, a > 0); def Z = grtwists( intvec(d:a) ); // will set the rank as well // ASSUME(2, grisequal(Z, grpower( grshift(grzero(), d), a ) )); // optional check return(Z); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; // grview(grpower( grshift(grzero(), 10), 5 ) ); grview( grtwist (5, 10) ); } proc grpower(def A, int p) "USAGE: grpower(A, p), graded object A, int p > 0 RETURN: graded direct power A^p PURPOSE: compute the graded direct power A^p NOTE: the power p must be positive EXAMPLE: example grpower; shows an example " { if(p==0){ ERROR("Sorry, we don't know what is A^0!?!?"); } // grzero!? ASSUME(0, p > 0); ASSUME(1, grtest(A) ); if(p==1){ return(A); } def N = grsum(A,A); if(p==2){ return(N); } // TODO: replace recursion with a loop! // see http://en.wikipedia.org/wiki/Exponentiation_by_squaring if((p%2)==0) { return ( grpower(N, p div 2) ); } else { return ( grsum( A, grpower(N, (p-1) div 2) )); } } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module A = grobj( module([x+y, x, 0], [0, x+y, y]), intvec(1,1,1) ); grview(A); module B = grobj( module([x,y]), intvec(2,2) ); grview(B); module D = grsum( grpower(A,2), grpower(B,2) ); print(D); homog(D); grview(D); } proc grsum(A,B) "USAGE: grsum(A, B), graded objects A and B RETURN: graded direct sum of input objects PURPOSE: compute the graded direct sum of A and B EXAMPLE: example grsum; shows an example " { ASSUME(1, grtest(A) ); ASSUME(1, grtest(B) ); intvec a = grrange(A); intvec b = grrange(B); intvec c = a,b; if( (ncols(B)>0) && (size(B)>0) ) { int r = nrows(A); module T = align(module(B), r); // T; print(T); nrows(T); // BUG!!!! module S = module(A), T; } else { def S = A; } intvec da = grdeg(A); intvec db = grdeg(B); intvec dc = da, db; def SS = grobj(S, c, dc); ASSUME(0, size( grrange(SS) ) == (size(a) + size(b)) ); ASSUME(0, size( grdeg(SS) ) == (size(da) + size(db)) ); ASSUME(0, ncols( SS ) == size( grdeg(SS) ) ); ASSUME(0, nrows( SS ) == size( grrange(SS) ) ); return(SS); } example { "EXAMPLE:"; echo = 2; // if( defined(assumeLevel) ){ int assumeLevel0 = assumeLevel; } else { int assumeLevel; export(assumeLevel); }; assumeLevel = 5; ring r=32003,(x,y,z),dp; module A = grobj( module([x+y, x, 0, 0], [0, x+y, y, 0]), intvec(0,0,0,1) ); grview(A); module B = grobj( module([0,x,y]), intvec(15,1,1) ); grview(B); module C = grsum(A,B); print(C); homog(C); grview(C); module D = grsum( grsum(grpower(A,2), grtwist(1,1)), grsum(grtwist(1,2), grpower(B,2)) ); print(D); homog(D); grview(D); module F = grobj( module([x,y,0]), intvec(1,1,5) ); grview(F); module T = grsum( F, grsum( grtwist(1, 10), B ) ); grview(T); // if( defined(assumeLevel0) ){ assumeLevel = assumeLevel0; } else { kill assumeLevel; } // restore the state of aL } proc grshift( def M, int d) "USAGE: grshift(A, d), graded objects A, int d RETURN: shifted graded object PURPOSE: shift the grading on A by d: A(i) -> A(i+d) EXAMPLE: example grshift; shows an example " { ASSUME(1, grtest(M) ); intvec a = grrange(M); intvec t = grdeg(M); if( size(a) == 0 && size(t) == 0 ) { "!! Warning: shifting '0 <- 0' leaves it as it unchanged!"; return (M); } a = a - intvec(d:size(a)); t = t - intvec(d:size(t)); return (grobj(M, a, t)); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module A = grobj( module([x+y, x, 0, 0], [0, x+y, y, 0]), intvec(0,0,0,1) ); grview(A); module S = grshift( A, 6); grview(S); grview( grshift( grzero(), 100 ) ); // does nothing... } proc grisequal (def A, def B) "USAGE: grisequal(A, B), graded objects A and B RETURN: 1 if A == B as graded objects, 0 otherwise PURPOSE: test the equality of two graded object NOTE: A and B should be literarly the same at the moment. TODO? EXAMPLE: example grisequal; shows an example " { ASSUME(1, grtest(A) ); ASSUME(1, grtest(B) ); int ra = nrows(A); int rb = nrows(B); intvec wa = grrange(A); intvec wb = grrange(B); if( (ra != rb) || (ncols(A) != ncols(B)) ){ return (0); } // TODO: ??? intvec da = grdeg(A); intvec db = grdeg(B); return ( (da == db) && (wa == wb) && (size(module(matrix(A) - matrix(B))) == 0) ); // TODO: ??? } example { "EXAMPLE:"; echo = 2; // TODO } proc grobj(def A, intvec w, list #) "USAGE: grobj(M, w[, d]), matrix/ideal/module M, intvec w, d RETURN: graded object with matrix presentation M, row weighting w [and total graded degrees d of columns] PURPOSE: create a valid graded object with a given matrix presentation, weighting [and total graded degrees (in case of zero columns)] EXAMPLE: example grobj; shows an example " { ASSUME(0, size(w) >= nrows(A) ); module M = module(A); attrib( M, "rank", size(w) ); attrib( M, "isHomog", w ); intvec @ww = 0:0; if( size(#) > 0 ) { ASSUME(0, typeof(#[1]) == "intvec" ); @ww = intvec( #[1] ); if( size(@ww) != ncols(M) ) { if( (size(M) == 0) && (ncols(M) <= 1) && (size(w) == 0) && (size(@ww) > 0) ) { matrix m[size(w)][size(@ww)]; M = module(m); attrib( M, "isHomog", w ); } } ASSUME(0, size(@ww) == ncols(M) ); } else { if( size(M) == ncols(M) ) /* no zero cols? */ { @ww = grdeg(M); // let us compute them all :) } else { if( (ncols(M) == 1) && (size(M) == 0) ) { M = freemodule(0); } attrib( M, "rank", size(w) ); attrib( M, "isHomog", w ); // ASSUME(0, /* PROBLEM WITH ZERO COLUMNS / THEIR DEGREES! */ (ncols(M) == 0) ); } } // type(@ww); type(M); ASSUME(0, size(@ww) == ncols(M) ); // ?! attrib(M, "degHomog", @ww); ASSUME(0, grtest(M) ); return (M); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; def A = grobj( module([x+y, x, 0, 0], [0, x+y, y, 0]), intvec(0,0,0,1) ); grview(A); def F = grobj( module([x,y,0]), intvec(1,1,5) ); grview(F); int d = 666; // zero can have any degree... def Z = grobj( module([x,0], [0,0,0], [0, y]), intvec(1,2,3), intvec(2, d, 3) ); grview(Z); print(Z); attrib(Z); grrange(Z); // module weights attrib(Z, "degHomog"); // total degrees // Zero object: matrix z[3][0]; grview( grobj( z, intvec(1,2,3) ) ); grview( grobj( freemodule(0), intvec(1,2,3) ) ); matrix z1[0][3]; grview( grobj( z1, 0:0, intvec(1,2,3) ) ); grview( grobj( freemodule(0), 0:0, intvec(1,2,3) ) ); matrix z0[0][0]; grview( grobj( z0, 0:0 ) ); grview( grobj( freemodule(0), 0:0 ) ); } proc grtest(def N, list #) "USAGE: grtest(M[,b]), anyting M, optionally int b RETURN: 1 if M is a valid graded object, 0 otherwise PURPOSE: validate a graded object. Print an invalid object message if b is not given NOTE: M should be an ideal or module or matrix, with weighting attribute 'isHomog' and optionally total graded degrees attribute 'degHomog'. Attributes should be compatible with the presentation matrix. EXAMPLE: example grtest; shows an example " { int b = (size(#) == 0); string t = typeof(N); if( (t != "ideal") && (t != "module") && (t != "matrix") ) { if(b) { " ? grtest: Input should be something like a matrix!"; }; return (0); }; if ( typeof(attrib(N,"isHomog")) != "intvec" ) { if(b) { type(N); attrib(N); " ? grtest: Input must be graded!"; }; return (0); }; intvec gr = grrange(N); // grading weights... if ( nrows(N) != size(gr) ) { if(b) { " ? grtest: Input has wrong number of rows!"; }; return (0); }; if( ncols(N) == 0 ) // zero-column matrix? { return(1); } // if( attrib(N, "rank") != size(gr) ){ return (0); } // wrong rank :( if ( typeof(attrib(N, "degHomog")) == "intvec" ) { intvec T = attrib(N, "degHomog"); // graded degrees if( (ncols(N) == 1) && (size(T) == 0) && (size(N) == 0) ) { // if(b) { "Input seems to be a valid graded ZERO-arrow!"; }; return (1); } if ( ncols(N) != size(T) ) { if(b) { " ? grtest: Input has wrong number of cols!"; }; return (0); }; int k = nvars(basering) + 1; // index of mod. column in the leadexp module L = lead(module(N)); vector v; // checking T for non-zero N[i] int i = size(T); for (; i > 0; i-- ) { v = L[i]; if( v != 0 ) { if( (deg(v) + gr[ leadexp(v)[k] ]) != T[i] ) { if(b) { " ? grtest: Input has wrong total grade of " + string(i) + "-th column!"; }; return (0); }; // wrong T[i] } } // TODO: check t on nonzero cols... } else { if( ncols(N) != size(N) ) { if(b) { " ? grtest: Input should have exclusively non-zero columns, please give total grades otherwise!"; }; return (0); }; } if( !homog(N) ) { if(b) { " ? grtest: Input should be graded homogenous!"; }; return (0); }; // if(b) { "Input seems to be a valid graded object (map)!"; }; return (1); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; // the following calls will fail due to tests in grtest: grobj( module([x+y, x, 0, 0], [0, x+y, y, 0]), intvec(0,0,0,0) ); // enough row weights // grobj( module([x+y, x, 0, 0], [0, x+y, y, 0]), intvec(0,0) ); // not enough row weights // grobj( module([x,0], [0,0,0], [0, y]), intvec(1,2,3) ); // zero column needs (otherwise optional) total degrees grobj( module([x,0], [0,0,0], [0, y]), intvec(1,2,3), intvec(2, 10, 3) ); // compatible total degrees (on non-zero columns) // grobj( module([x,0], [0,0,0], [0, y]), intvec(1,2,3), intvec(2-1, 10, 3+1) ); // incompatible total degrees (on both non-zero columns) } static proc align( def A, int d) "analog of align kernel command for older Singular versions this is static since it should not be used by @code{align}-able (newer) Singular releases. Note that this proc does not care about any attributes (of A) " { ASSUME(0, d >= 0 ); if( d == 0 ) { return (A); } if( ncols(A) == 0 ) { matrix B[nrows(A) + d][0]; return (B); } module T; T[d] = 0; T = T, module(transpose(A)); return( module(transpose(T)) ); } example { "EXAMPLE:"; echo = 2; ring r; matrix m[2][0]; type( align(m, 3) ); matrix m[0][2]; type( align(m, 3) ); } proc grgroebner(A) "USAGE: grgroebner(M), graded object M RETURN: graded object PURPOSE: compute graded groebner basis of M EXAMPLE: example grgroebner; shows an example " { ASSUME(1, grtest(A)); return ( grobj( groebner(A), grrange(A) ) ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module A = grobj( module([x+y, x, 0, 0], [0, x+y, y, 0]), intvec(0,0,0,1) ); grview(A); module B = grgroebner(A); grview(B); } proc grsyz(A) "USAGE: grsyz(M), graded object M RETURN: graded object PURPOSE: compute graded syzygy of M EXAMPLE: example grsyz; shows an example " { ASSUME(1, grtest(A)); return( grobj( syz(A), grdeg(A) ) ); // if( size(syz(A)) == 0 ) : zero syzygy? // return( grtwists( -grdeg(A) ) ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module A = grgroebner( grobj( module([x+y, x, 0, 3], [0, x+y, y, 2], [y, y, z, 1]), intvec(0,0,0,1) ) ); grview(A); grview(grsyz(A)); module X = grgroebner( grobj( module([x]), intvec(2) ) ); grview(X); // syzygy module should be zero! grview(grsyz(X)); } proc grprod(A, B) "USAGE: grprod(M, N), graded objects M and N RETURN: graded object PURPOSE: compute graded product M * N (as composition of maps) EXAMPLE: example grprod; shows an example " { ASSUME(1, grtest(A)); ASSUME(1, grtest(B)); intvec a = grdeg(A); intvec b = grrange(B); ASSUME(0, (size(a) == size(b)) && (a == b)); // == for intvec :( return ( grobj( A*B, grrange(A), grdeg(B) ) ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module A = grobj( module([x+y, x, 0, 3], [0, x+y, y, 2], [y, y, z, 1]), intvec(0,0,0,1) ); grview(A); A = grgroebner(A); grview(A); module B = grsyz(A); grview(B); print(B); module D = grprod( A, B ); grview(D); print(D); // must be all zeroes due to syzygy property! ASSUME(0, size(D) == 0); } // TODO: think about a proper data structure for a graded resolution!? proc grres(def A, int l, list #) "USAGE: grres(M, l[, b]), graded object M, int l, int b RETURN: graded resolution = list of graded objects PURPOSE: compute graded resolution of M (of length l) and minimise it if b was given EXAMPLE: example grres; shows an example " { ASSUME(0, l >= 0); ASSUME(1, grtest(A)); intvec v = grrange(A); int b = (size(#) > 0); if(b) { list r = res(A, l, #[1]); } else { list r = res(A, l); } l = size(r); int i; for ( i = 1; i <= l; i++ ) { if( size(r[i]) == 0 ) { r[i] = grobj(freemodule(0), v); // grtwists(-v); i++; break; } r[i] = grobj(r[i], v); v = grdeg(r[i]); } i = i-1; return( list(r[1..i]) ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module A = grobj( module([x+y, x, 0, 3], [0, x+y, y, 2], [y, y, z, 1]), intvec(0,0,0,1) ); grview(A); module B = grgroebner(A); grview(B); "graded resolution of B: "; def C = grres(B, 0); grview(C); int i; int l = size(C); "D^2 == 0: "; for (i = 1; i < l; i++ ) { i; grview( grprod(C[i], C[i+1]) ); } } proc grtranspose(def M) "USAGE: grtranspose(M), graded object M RETURN: graded object PURPOSE: graded transpose of M NOTE: no reordering is performend by this procedure EXAMPLE: example grtranspose; shows an example " { ASSUME(1, grtest(M) ); return ( grobj(transpose(M), -grdeg(M), -grrange(M)) ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module M = grtwists( intvec(-2, 0, 4, 4) ); grview(M); module N = grsyz( grtranspose( M ) ); grview(N); module L = grtranspose(N); grview( L ); module K = grsyz( L ); grview(K); // Corner cases: 0 <- 0! module Z = grzero(); grview(Z); grview( grtranspose( Z ) ); // Corner cases: * <- 0 matrix M1[3][0]; module Z1 = grobj( M1, intvec(-1, 0, 1) ); grview(Z1); grview( grtranspose( Z1 ) ); // Corner cases: 0 <- * matrix M2[0][3]; module Z2 = grobj( M2, 0:0, intvec(-1, 0, 1) ); grview(Z2); grview( grtranspose( Z2 ) ); } proc grgens(def M) "USAGE: grgens(M), graded object M (map) RETURN: graded object PURPOSE: try compute graded generators of coker(M) and return them as columns of a graded map. NOTE: presentation of resulting generated submodule may be different to M! EXAMPLE: example grgens; shows an example " { ASSUME(1, grtest(M) ); module N = grtranspose( grsyz( grtranspose(M) ) ); // ASSUME(3, grisequal( grgroebner(M), grgroebner( grpres( N ) ) ) ); // FIXME: not always true!? return ( N ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module M = grtwists( intvec(-2, 0, 4, 4) ); grview(M); module N = grgens(M); grview( N ); print(N); // fine == M module A = grobj( module([x+y, x, 0, 3], [0, x+y, y, 2], [y, y, z, 1]), intvec(0,0,0,1) ); A = grgroebner(A); grview(A); module B = grgens(A); grview( B ); print(B); // Ups :( != A grview( grgens( grzero() ) ); } proc grpres(def M) "USAGE: grpres(M), graded object M (submodule gens) RETURN: graded module (via coker) PURPOSE: compute graded presentation matrix of submodule generated by columns of M EXAMPLE: example grpres; shows an example " { ASSUME(1, grtest(M) ); def N = grsyz(M); // ASSUME(3, grisequal( M, grgens( N ) ) ); return ( N ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; def A = grgroebner( grobj( module([x+y, x, 0, 3], [0, x+y, y, 2], [y, y, z, 1]), intvec(0,0,0,1) ) ); grview(A); "graded transpose: "; def B = grtranspose(A); grview( B ); print(B); "... syzygy: "; def C = grsyz(B); grview(C); "... transposed: "; def D = grtranspose(C); grview( D ); print (D); "... and back to presentation: "; def E = grsyz( D ); grview(E); print(E); def F = grgens( E ); grview(F); print(F); def G = grpres( F ); grview(G); print(G); def M = grtwists( intvec(-2, 0, 4, 4) ); grview(M); def N = grgens(M); grview( N ); print(N); def L = grpres( N ); grview( L ); print(L); } LIB "random.lib"; // for sparsepoly proc grrndmat(intvec w, intvec v, list #) "USAGE: grrndmat(src,dst[,p,b]), intvec src, dst[, int p, b] RETURN: matrix of polynomials PURPOSE: generate random matrix compatible with src and dst gradings NOTE: optional arguments p, b are for 'sparsepoly' (by default: 75%, 30000). TODO: this is experimental at the moment! EXAMPLE: example grrndmat; shows an example " { // defaults for sparsepoly int p = 75; int b = 30000; if ( size(#) > 0 ) { ASSUME( 0, (typeof(#[1]) == "int") || (typeof(#[1]) == "bigint") ); p = #[1]; if ( size(#) > 1 ) { ASSUME( 0, (typeof(#[2]) == "int") || (typeof(#[2]) == "bigint") ); b = #[2]; } } int n = size(v); // destination: rows! int m = size(w); // source: cols matrix M[n][m]; int r,c; intvec ww; for( c = m; c > 0; c-- ) { ww = v - intvec(w[c]:n); for( r = n; r > 0; r-- ) { if( ww[r] >= 0) { M[r,c] = sparsepoly(ww[r], ww[r], p, b); } } } return(M); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; print( grrndmat( intvec(0, 1), intvec(1, 2, 3) ) ); } // TODO: remove the following? proc KeneshlouMatrixPresentation(intvec a) "USAGE: KeneshlouMatrixPresentation(intvec a), intvec a. RETURN: graded object PURPOSE: matrix presentation for direct sum of omega^a[i](i) in form of a graded object EXAMPLE: example KeneshlouMatrixPresentation; shows an example " { int n = size(a)-1; // ring r = 32003,(x(0..n)),dp; ASSUME(0, nvars(basering)==(n+1)); int i,j; // find first nonzero exponent a_i for(i=1;i<=size(a);i++) { if(a[i]!=0) {break; }; } // all zeroes? if(i>size(a)) {return (grzero()); }; for(i=2;i<=n;i++) { if(a[i]!=0) {break; }; } module N; if(i>n) { // no middle part if(a[1]>0) { N=grtwist(a[1],0); if(a[n+1]>0) { N=grsum(N,grtwist(a[n+1],-1));} } else { N=grtwist(a[n+1],-1);} return (N); // grorder(N)); } else // i <= n: middle part is present, a_i != 0 { // a = a1 ... | i:2, a_2 ..... i: n, a_n | .... i: n+1a_(n+1) j = i - 1; module I = maxideal(1); attrib(I,"isHomog", intvec(0)); list L = mres(I, 0); // TODO: use grres() instead!!! list kos = grorder(L); // make sure that graded maps are represented by blocks corresponding to the betti diagram? def S = grpower(grshift(grobj( kos[j+2], attrib(kos[j+2], "isHomog")), j), a[i]); i++; for(; i <= n; i++) { if(a[i]==0) { i++; continue; } j = i - 1; S = grsum( S, grpower(grshift( grobj( kos[j+2], attrib(kos[j+2], "isHomog")), j), a[i]) ); } // S is the middle (non-zero) part if(a[1] > 0 ) { N=grsum(grtwist(a[1],0), S); } else { N = S;} if(a[n+1] > 0 ) { N=grsum(N, grtwist(a[n+1],-1)); } return ((N)); // return (grorder(N)); } } example { "EXAMPLE:"; echo = 2; ring r = 32003,(x(0..4)),dp; def N1 = KeneshlouMatrixPresentation(intvec(2,0,0,0,0)); grview(N1); def N2 = KeneshlouMatrixPresentation(intvec(0,0,0,0,3)); grview(N2); def N = KeneshlouMatrixPresentation(intvec(2,0,0,0,3)); grview(N); def M1 = KeneshlouMatrixPresentation(intvec(0,1,0,0,0)); grview(M1); def M2 = KeneshlouMatrixPresentation(intvec(0,1,1,0,0)); grview(M2); def M3 = KeneshlouMatrixPresentation(intvec(0,0,0,1,0)); grview(M3); def M = KeneshlouMatrixPresentation(intvec(1,1,1,0,0)); grview(M); } proc grconcat(A,B) "USAGE: grconcat(A, B), graded objects A and B, dst(A) == dst(B) =: dst RETURN: graded object PURPOSE: construct src(A) + src(B) -----> dst given by (A|B) EXAMPLE: example grconcat; shows an example " { ASSUME(1, grtest(A)); ASSUME(1, grtest(B)); ASSUME(0, grrange(A)==grrange(B)); intvec v = grrange(A); intvec w=grdeg(A),grdeg(B); return(grobj(concat(A,B),v,w)); } example { "EXAMPLE:"; echo = 2; ring r; module R=grobj(module([x,y,z]),intvec(0:3)); grview(R); module S=grobj(module([x,0,y],[xy,zy+x2,0]),intvec(0:3)); grview(S); def Q=grconcat(R,S); grview(Q); } proc grlift(A, B) "USAGE: grlift(M, N), graded objects M and N RETURN: transformation matrix (graded object???) PURPOSE: compute graded matrix which the generators of submodule Im(N) in terms of Im(M). EXAMPLE: example grlift; shows an example " { ASSUME(1, grtest(A)); ASSUME(1, grtest(B)); ASSUME(0, grrange(A) == grrange(B)); // matrix T; module AA = liftstd(A, T); // AA = module(A*T) // matrix U; matrix L =lift(A,B/*,U*/); // module(B*U) = module(matrix(A)*L) return(grobj(L, grdeg(A), grdeg(B))); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module P=grobj(module([xy,0,xz]),intvec(0,1,0)); grview(P); module D=grobj(module([y,0,z],[x2+y2,z,0]),intvec(0,1,0)); grview(D); def G=grlift(D,P); grview(G); ASSUME(0, grisequal( grprod(D, G), P) ); } proc grrange(M) "USAGE: grrange(M), graded object M RETURN: intvec PURPOSE: get weights of module units, thus describing the target of M EXAMPLE: example grrange; shows an example " { // ASSUME(1, grtest(M)); // Leads to recursive call due to grtest... return( attrib(M, "isHomog") ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module Z = grobj(freemodule(0),intvec(0:0),intvec(0:0)); grrange(Z); grdeg(Z); grview(Z); module P=grobj(module([xy,0,xz]),intvec(0,1,0)); grrange(P); grdeg(P); grview(P); } proc grlift0(M, N, alpha1) "USAGE: grlift0(M, N, alpha1) TODO! PURPOSE: generic random alpha0 : coker(M) -> coker(N) from random alpha1 NOTE: this proc can work only if some assumptions are fulfilled (due to Wolfram)! e.g. at the end of a resolution for the source module... " { ASSUME(1, grtest(M)); ASSUME(1, grtest(N)); ASSUME(0, grdeg(M) == grdeg(alpha1) ); ASSUME(0, grdeg(N) == grrange(alpha1) ); return( grtranspose( grlift( grtranspose( M ), grtranspose( grprod( N, alpha1 ) ) ) ) ); // alpha0! } example { "EXAMPLE:"; echo = 2; ring S = 0, (x(0..3)), dp; list kos = grres(grobj(maxideal(1), intvec(0)), 0); print( betti(kos), "betti"); grview(kos); // source module: // module M = grshift(kos[4], 2); // phi, Syz_3(K(2)) def M = KeneshlouMatrixPresentation(intvec(0,0,1,0)); // grview( grres(M, 0) ); grview(M); // destination module: // module N = grshift(kos[3], 1); // psi, Syz_2(K(1)) def N = KeneshlouMatrixPresentation(intvec(0,1,0,0)); // grview( grres(N, 0) ); grview(N); // random graded of degree 0, homomorphism of free presentations: // alpha1: src(M) -> src (N) def alpha1 = grrndmap( M, N ); // alpha1 grview(alpha1); // random graded of degree 0, homomorphism of free presentations: // alpha0: dst(M) -> dst (N) def alpha0 = grlift0(M, N, alpha1); grview(alpha0); } proc grlifting(M,N) "USAGE: grlifting(M,N), graded objects M and N RETURN: map of chain complexes (as a list) PURPOSE: construct a map of chain complexes between free resolutions of Img(M) and Img(N). EXAMPLE: example grlifting; shows an example " { ASSUME(1, grtest(M)); ASSUME(1, grtest(N)); list rM=grres(M,0,1); list rN=grres(N,0,1); int i,j,k; for(i=1;i<=size(rM);i++) { if(size(rM[i])==0){break;} } for(j=1;j<=size(rN);j++) { if(size(rN[j])==0){break;} } int t=min(i,j); ASSUME(0, t >= 2); list P; "t: ", t; P[1]= grrndmap( rM[1], rN[1] ); // alpha1 if(t==2){return(P[1]);} for(k=2; k<=t; k++) { P[k] = grlift( grprod(P[k-1],rM[k]), rN[k] ); grview(P[k]); } return(P); } example { "EXAMPLE:"; echo = 2; /* ring r=32003,(x,y,z),dp; module P=grobj(module([xy,0,xz]),intvec(0,1,0)); grview(P); module D=grobj(module([y,0,z],[x2+y2,z,0]),intvec(0,1,0)); grview(D); def G=grlifting(D,P); grview(G); kill r; ring r=32003,(x,y,z),dp; module D=grobj(module([y,0,z],[x2+y2,z,0], [z3, xy, xy2]),intvec(0,1,0)); D = grgroebner(D); grview( grres(D, 0)); def G=grlifting(D, D); grview(G); */ ring S = 0, (x(0..3)), dp; list kos = grres(grobj(maxideal(1), intvec(0)), 0); print( betti(kos), "betti"); grview(kos); // module M = grshift(kos[4], 2); // phi, Syz_3(K(2)) def M = KeneshlouMatrixPresentation(intvec(0,0,1,0)); grview( grres(M, 0) ); // module N = grshift(kos[3], 1); // psi, Syz_2(K(1)) def N = KeneshlouMatrixPresentation(intvec(0,1,0,0)); grview( grres(N, 0) ); grlifting(M, N); // grview(G); // def G=grlifting( grgens(M), grgens(N) ); grview(G); } proc mappingcone(M,N) "USAGE: mappingcone(M,N), M,N graded objects RETURN: chain complex (as a list) PURPOSE: construct a free resolution of the cokernel of a random map between Img(M), and Img(N). EXAMPLE: example mappingcone; shows an example " { ASSUME(1, grtest(M)); ASSUME(1, grtest(N)); list P=grlifting(M,N); list rM=grres(M,1); list rN=grres(N,1); int i; list T; T[1]=grconcat(P[1],rN[2]); for(i=2;i<=size(P);i++) { intvec v=grrange(rM[i]); intvec w=grdeg(rN[i+1]); int r=size(v); int s=size(w); module zero = (0:s); module A=grconcat(P[i],rN[i+1]); module B=grobj(zero,v,w); module C=grconcat(-rM[i],B); module D=grconcat(grtranspose(C), grtranspose(A)); T[i]=grtranspose(D); } return(T); } example { "EXAMPLE:"; echo = 2; ring r=32003, (x(0..4)),dp; def A=KeneshlouMatrixPresentation(intvec(0,0,0,0,3)); def M=grgens(A); grview(M); def B=KeneshlouMatrixPresentation(intvec(0,1,0,0,0)); def N=grgens(B); grview(N); def R=grlifting(M,N); grview(R); def T=mappingcone(M,N); grview(T); def U=grtranspose(T[1]); resolution G=mres(U,0); print(betti(G),"betti"); ideal I=groebner(flatten(G[2])); resolution GI=mres(I,0); print(betti(GI),"betti"); } // correct proc grrndmap(def S, def D, list #) "USAGE: grrndmap(S,D), graded objects S and D RETURN: graded object PURPOSE: construct a random 0-deg graded homomorphism src(S) -> src(D) EXAMPLE: example grrndmap; shows an example " { ASSUME(1, grtest(S) ); ASSUME(1, grtest(D) ); // "src: "; grview(S);"dst: "; grview(D); intvec v = -grdeg(S); // source intvec w = -grdeg(D); // destination return (grobj(grrndmat(v, w, #), -w, -v ) ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module D=grobj(module([y,0,z],[x2+y2,z,0]),intvec(0,1,0)); grview(D); module S=grobj(module([x,0,y],[xy,zy+x2,0]),intvec(0,0,0)); grview(S); def H=grrndmap(D,S); grview(H); } proc grrndmap2(def D, def S, list #) "USAGE: grrndmap2(D,S), graded objects S and D RETURN: graded object PURPOSE: construct a random 0-deg graded homomorphism between target of D and S. EXAMPLE: example grrndmap2; shows an example " { ASSUME(1, grtest(D) ); ASSUME(1, grtest(S) ); intvec v = -grrange(D); // source intvec w = -grrange(S); // target return (grobj(grrndmat(v, w, #), -w, -v ) ); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),dp; module D=grobj(module([y,0,z],[x2+y2,z,0]),intvec(0,1,0)); grview(D); module S=grobj(module([x,0,y],[xy,zy+x2,0]),intvec(0,0,0)); grview(S); def G=grrndmap2(D,S); grview(G); } // A f2 f3 // 0<---M<----F0<----F1<----F2<----F3<---- // |p1 |p2 // // 0<---N<----G0<----G1<----G2<----G3<---- // B(g1) g2 g3 // proc grlifting2(A,B) "USAGE: grlifting2(A,B), graded objects A and B (matrices defining maps) RETURN: map of chain complexes (as a list) PURPOSE: construct a map of chain complexes between free resolution of M=coker(A) and N=coker(B). EXAMPLE: example grlifting2; shows an example " { ASSUME(1, grtest(A)); ASSUME(1, grtest(B)); list rM=grres(A,0); list rN=grres(B,0); int i,j,k; list P; // find first zero matrix in rM for(i=1;i<=size(rM);i++) { if(size(rM[i])==0){break;} } // find first zero matrix in rN for(j=1;j<=size(rN);j++) { if(size(rN[j])==0){break;} } int t=min(i,j); P[1]=grrndmap2(A,B); // A(or B)=0 if(t==1){return(P[1])}; for(k=2;k<=t;k++) { def E=grprod(P[k-1],rM[k-1]); P[k]=grlift(rN[k-1],E); // ----------> /* let yi=(pi)o(fi); to take grlift(gi,yi) we should have img(yi) is contained in img(gi)=ker(gi-1),i.e (gi-1)oyi=0. we have (gi-1)oyi=(gi-1)o(pi)o(fi)=(pi-1)o(fi-1)ofi=0 */ } return(P); } example { "EXAMPLE:"; echo = 2; ring r; module P=grobj(module([xy,0,xz]),intvec(0,1,0)); grview(P); module D=grobj(module([y,0,z],[x2+y2,z,0]),intvec(0,1,0)); grview(D); module PP = grpres(P); grview(PP); module DD = grpres(D); grview(DD); def T=grlifting2(DD,PP); T; // def Z=grlifting2(P,D); Z; // WRONG!!! } /* // -f1 0 -f2 0 // (p1 g1) p2 g2 p3 g3 // G0<-----F0+G1<------F1+G2<-------F2+G3<----- proc mappingcone2(A,B) "USAGE: mappingcone2(A,B), graded objects A and B (matrices defining maps) RETURN: chain complex (as a list) PURPOSE: construct the free resolution of a cokernel of a random map between M=coker(A), and N=coker(B) EXAMPLE: example mappingcone2; " { ASSUME(1, grtest(A)); ASSUME(1, grtest(B)); list P=grlifting2(A,B); list rM=grres(A,1); list rN=grres(B,1); int i; list T; T[1]=grconcat(P[1],rN[1]); for(i=2;i<=size(P);i++) { intvec v=grrange(rM[i-1]); intvec w=grdeg(rN[i]); int r=size(v); int s=size(w); matrix zero[r][s]; module A=grconcat(P[i],rN[i]); module B=grobj(zero,v,w); module C=grconcat( grneg( rM[i-1] ) ,B); module D=grconcat(grtranspose(C), grtranspose(A)); T[i]=grtranspose(D); } return(T); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x(0..4)),dp; def I=maxideal(1); module R=grobj(module(I), intvec(0)); resolution FR=mres(R,0); print(betti(FR,0),"betti"); module K=grobj(module(FR[1]),intvec(-1),intvec(0:5)); grview(K); module S=grsyz(K); grview(S); S; module SS = grpres(S); module B=grobj(module([1,0,0],[0,1,0],[0,0,1]),intvec(1,1,1),intvec(1,1,1)); // module B=grobj(module([1],[0,1],[0,0,1],[0,0,0,1], [0,0,0,0,1]),intvec(0:5)); grview(B); B; module BB = grpres(B); def Z=grlifting2(SS,BB);Z; def G=mappingcone2(SS,BB);G; } */ proc grlifting3(A,B) "TODO: grlifting4 was newer and had more documentation than this proc, but was removed... Please verify and update! " { ASSUME(1, grtest(A)); ASSUME(1, grtest(B)); list rM = grres(A,0,1); print( betti(rM), "betti"); list rN = grres(B,0,1); print( betti(rN), "betti"); int i,j,k; for(i=1;i<=size(rM);i++) { if(size(rM[i])==0){break;} } for(j=1;j<=size(rN);j++) { if(size(rN[j])==0){break;} } int t=min(i,j); list P; "t: ", t; // grview(rM[t]); grview(rN[t]); P[t]= grrndmap2(rM[t],rN[t]); grview(P[t]); if(t==1){return(P)}; for(k=t-1; k>=1; k--) { "k: ", k; // grview(rM[k]); grview(rN[k]); // def C = grtranspose(rM[k]); def T= grprod(rN[k],P[k+1]); // def tT = grtranspose(T); P[k]= grlift0( rM[k], rN[k], P[k+1] ); // grtranspose(grlift(C,tT)); grview(P[k]); } return(P); } example {"EXAMPLE:"; echo = 2; ring r=32003, x(0..4),dp; def A=grtwist(3,1); grview(A); def T=KeneshlouMatrixPresentation(intvec(0,1,0,0,0)); grview(T); def F=grlifting3(T,A); grview(F); def R=KeneshlouMatrixPresentation(intvec(0,0,0,2,0)); def S=KeneshlouMatrixPresentation(intvec(1,2,0,0,0)); def H=grlifting3(R, S); // grview(H); // 2nd module does not lie in the first: // def H=grlifting3(S, R); //def I=KeneshlouMatrixPresentation(intvec(2,3,0,6,2)); //def J=KeneshlouMatrixPresentation(intvec(4,0,1,2,1)); //def N=grlifting3(I,J); grview(N); } proc grneg(A) "USAGE: grneg(A), graded object A RETURN: graded object PURPOSE: graded map defined by -A EXAMPLE: example grneg; shows an example " { ASSUME(1, grtest(A)); return( grobj(-A, grrange(A), grdeg(A)) ); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; def A=grobj([x2,yz,xyz],intvec(1,1,0)); grview(A); def F=grneg(A); grview(F); } // -f1 0 -f2 0 // (p1 g1) p2 g2 p3 g3 //G0<-----F0+G1<------F1+G2<-------F2+G3<----- proc mappingcone3(A,B) "USAGE: mappingcone3(A,B), graded objects A and B (matrices defining maps) RETURN: chain complex (as a list) PURPOSE: construct a free resolution of the cokernel of a random map between M=coker(A), and N=coker(B) EXAMPLE: example mappingcone3; shows an example " { ASSUME(1, grtest(A)); ASSUME(1, grtest(B)); list P=grlifting3(A,B); list rM=grres(A,0,1); list rN=grres(B,0,1); int i; list T; T[1]=grconcat(P[1],rN[1]); for(i=2;i<=size(P);i++) { intvec v= grrange(rM[i-1]); intvec w=grdeg(rN[i]); int r=size(v); int s=size(w); matrix zero[r][s]; // ASSUME( 0, grtest(P[i]) ); // ASSUME( 0, grtest(rN[i]) ); module A=grconcat(P[i],rN[i]); module B=grobj(zero,v,w); module C=grconcat( grneg( rM[i-1] ) ,B); module D=grconcat(grtranspose(C), grtranspose(A)); T[i]=grtranspose(D); kill A, B, C, D, v, w, r, s, zero; } return(T); } example { "EXAMPLE:"; echo = 2; ring r=32003,x(0..4),dp; def A=KeneshlouMatrixPresentation(intvec(0,0,0,0,3)); grview(A); def T= KeneshlouMatrixPresentation(intvec(0,1,0,0,0)); grview(T); def F=grlifting3(A,T); grview(F); // BUG in the proc def G=mappingcone3(A,T); grview(G); /* module W=grtranspose(G[1]); resolution U=mres(W,0); print(betti(U,0),"betti"); // ? ideal P=groebner(flatten(U[2])); resolution L=mres(P,0); print(betti(L),"betti"); */ def R=KeneshlouMatrixPresentation(intvec(0,0,0,2,0)); grview(R); def S=KeneshlouMatrixPresentation(intvec(1,2,0,0,0)); grview(S); def H=grlifting3(R,S); grview(H); // BUG in the proc def G=mappingcone3(R,S); def I=KeneshlouMatrixPresentation(intvec(2,3,0,6,2)); def J=KeneshlouMatrixPresentation(intvec(4,0,1,2,1)); // def N=grlifting3(I,J); // 2nd module does not lie in the first: // def NN=mappingcone3(I,J); // ???????? } // TODO: Please decide between KeneshlouMatrixPresentation and matrixpres, and replace one with the other! proc matrixpres(intvec a) "USAGE: matrixpres(a), intvec a RETURN: graded object PURPOSE: matrix presentation for direct sum of omega^a[i](i) in form of a graded object EXAMPLE: example matrixpres; shows an example " { int n = size(a)-1; // ring r = 32003,(x(0..n)),dp; ASSUME(0, nvars(basering)==(n+1)); int i,j; // find first nonzero exponent a_i for(i=1;i<=size(a);i++) { if(a[i]!=0) {break; }; } // all zeroes? if(i>size(a)) {return (grzero()); }; for(i=2;i<=n;i++) { if(a[i]!=0) {break; }; } module N; if(i>n) { // no middle part if(a[1]>0) { N=grtwist(a[1],-1); if(a[n+1]>0) { N=grsum(N,grtwist(a[n+1],0));} } else { N=grtwist(a[n+1],0);} return (N); // grorder(N)); } else // i <= n: middle part is present, a_i != 0 { // a = a1 ... | i:2, a_2 ..... i: n, a_n | .... i: n+1a_(n+1) module I = maxideal(1); attrib(I,"isHomog", intvec(0)); list L = mres(I, 0); list kos = grorder(L); // make sure that graded maps are represented by blocks corresponding to the betti diagram? int j=size(a)-i; def S = grpower(grshift(grobj( kos[j+2], attrib(kos[j+2], "isHomog")),j ), a[i]); i++; for(; i <= n; i++) { if(a[i]==0) { i++; continue; } int j=size(a)-i; S = grsum( S, grpower(grshift( grobj( kos[j+2], attrib(kos[j+2], "isHomog")), j), a[i]) ); } // S is the middle (non-zero) part if(a[1] > 0 ) { N=grsum(grtwist(a[1],-1), S); } else { N = S;} if(a[n+1] > 0 ) { N=grsum(N, grtwist(a[n+1],0)); } return ((N)); // return (grorder(N)); } } example { "EXAMPLE:"; echo = 2; ring r = 32003,(x(0..4)),dp; def R=matrixpres(intvec(1,4,0,0,0)); grview(R); def S=matrixpres(intvec(0,0,3,0,0)); grview(S); def N1 = matrixpres(intvec(2,0,0,0,0)); grview(N1); def N2 = matrixpres(intvec(0,0,0,0,3)); grview(N2); def N = matrixpres(intvec(2,0,0,0,3)); grview(N); def M1 = matrixpres(intvec(0,1,0,0,0)); grview(M1); def M2 = matrixpres(intvec(0,1,1,0,0)); grview(M2); def M3 = matrixpres(intvec(0,0,0,1,0)); grview(M3); def M = matrixpres(intvec(1,1,1,0,0)); grview(M); } singular-4.0.3+ds/Singular/LIB/graphics.lib000066400000000000000000000235231266270727000204440ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version graphics.lib 4.0.0.0 Jun_2013 "; // $Id: 36a4d2e5c43fecf40662744669851fd85cbbd2b1 $ category="Visualization"; info=" LIBRARY: graphics.lib Procedures to use Graphics with Mathematica AUTHOR: Christian Gorzel, gorzelc@math.uni-muenster.de PROCEDURES: staircase(fname,I); Mathematica text for displaying staircase of I mathinit(); string for loading Mathematica's ImplicitPlot mplot(fname,I[# s]); Mathematica text for various plots "; /////////////////////////////////////////////////////////////////////////////// proc staircase(string fname,ideal I) "USAGE: staircase(s,I); s a string, I ideal in two variables RETURN: string with Mathematica input for displaying staircase diagrams of an ideal I, i.e. exponent vectors of the initial ideal of I NOTE: ideal I should be given by a standard basis. Let s=\"\" and copy and paste the result into a Mathematica notebook. EXAMPLE: example staircase; shows an example " { intvec v; int maxx, maxy; list l; string s; string el; if(nvars(basering)!=2) { "-- Error: need two variables "; return(); } if (not(attrib(I,"isSB"))) { " -- Warning: Ideal should be a standardbasis "; newline; } for(int i=1; i<=ncols(I); i++) { if (i>1) { el = el + ",";} v = leadexp(I[i]); if (v[1] > maxx) { maxx = v[1];} if (v[2] > maxy) { maxy = v[2];} el = el + "{" + string(v) + "}"; } el = "{" + el + "}"; maxx = maxx + 3; maxy = maxy + 3; s = newline + "Show[Graphics[{" + newline + "{GrayLevel[0.5],Map[Rectangle[#,{" + string(maxx) + "," + string(maxy) + "}] &, " + el + "]}," + newline + "{PointSize[0.03], Map[Point," + el + "]}," + newline + "Table[Circle[{i,j},0.1],{i,0," + string(maxx) + "},{j,0," + string(maxy) + "}]}," + newline + " Axes->True,AspectRatio->Automatic]]"; s = s + endstr(fname); return(s); } example { "EXAMPLE:"; echo =2; ring r0 = 0,(x,y),ls; ideal I = -1x2y6-1x4y2, 7x6y5+1/2x7y4+6x4y6; staircase("",std(I)); ring r1 = 0,(x,y),dp; ideal I = fetch(r0,I); staircase("",std(I)); ring r2 = 0,(x,y),wp(2,3); ideal I = fetch(r0,I); staircase("",std(I)); // Paste the output into a Mathematica notebook // active evalutation of the cell with SHIFT RETURN } /////////////////////////////////////////////////////////////////////////////// proc mathinit() "USAGE: mathinit(); RETURN: initializing string for loading Mathematica's ImplicitPlot EXAMPLE: example mathinit; shows an example " { // write("init.m","<< Graphics`ImplicitPlot`"); return("<< Graphics`ImplicitPlot`"); } example { "EXAMPLE:"; echo =2; mathinit(); // Paste the output into a Mathematica notebook // active evalutation of the cell with SHIFT RETURN } /////////////////////////////////////////////////////////////////////////////// static proc checkshort() { ring @r; } static proc determvars(ideal I) // determine the variables which are in the ideal I { intvec v; int i,j,k; k=1; for(j=1;j<=size(I);j++) { for(i=1;i<=nvars(basering);i++) { if(I[j]!=subst(I[j],var(i),0)) {v[k] = i; k++;} } } ring @r=0,x,ls; poly f; for(i=1;i<=size(v);i++) // sort VARS { f = f + x^v[i]; } v=0; for (i=1;i<=size(f);i++) {v[i]=leadexp(f[i])[1];} return(v); } /////////////////////////////////////////////////////////////////////////////// static proc endstr(string filename) { int i; string suffix,cmd,name; if(size(filename)) { for (i=size(filename);i;i--) { if (filename[i] == ".") {break;} } if (i>0) { suffix = filename[i,size(filename)-i+1]; name = ">" + filename[1,i-1]+ ".m"; } else { print("--Error: Suffix of filename incorrect"); return("");} // if (suffix ==".m") { cmd = "Display[\" " + filename + "\",% ]";} if (suffix ==".mps") { cmd = "Display[\" " + filename + "\",%] ";} if (suffix ==".ps") { cmd = "Display[\" ! psfix > " + filename + "\", %]";} if (suffix ==".eps") { cmd = "Display[\" ! psfix -epsf > " + filename + "\", %]";} } return(newline + cmd); } /////////////////////////////////////////////////////////////////////////////// proc mplot(string fname,ideal I,list #) "USAGE: mplot(fname, I [,I1,I2,..,s] ); fname=string; I,I1,I2,..=ideals, s=string representing the plot region.@* Use the ideals I1,I2,.. in order to produce multiple plots (they need to have the same number of entries as I!). RETURN: string, text with Mathematica commands to display a plot NOTE: The plotregion is defaulted to -1,1 around zero. For implicit given curves enter first the string returned by procedure mathinit into Mathematica in order to load ImplicitPlot. The following conventions for I are used: @format - ideal with 2 entries in one variable means a parametrised plane curve, - ideal with 3 entries in one variable means a parametrised space curve, - ideal with 3 entries in two variables means a parametrised surface, - ideal with 2 entries in two variables means an implicit curve given as I[1]==I[2], - ideal with 1 entry (or one polynomial) in two variables means an implicit curve given as f == 0, @end format EXAMPLE: example mplot; shows an example " { int i,j,k,mapping; int planecurve,spacecurve,implcrv,surface; intvec VARS,v; string xpart,ypart,zpart = "-1,1","-1,1","All"; string pstring,actstring,xname,yname,str,closing; string basr = nameof(basering); ideal J; if (ncols(I)>3) { "-- Error: can only draw upto dimension 3"; return(""); } ring @r = 0,(s,t),lp; ideal @J,@I; setring(`basr`); // def d = basering; // d; // listvar(d); str = newline; VARS = determvars(I); // "VARS: ";VARS; if (size(VARS)>2 or VARS==0) { "-- Error: Need some variables, but can only draw in 2 or 3 dimensions"; return(""); } if (size(matrix(I))==1 and size(VARS)==2) { i =size(I[1]); //I[2]=I[1][(i/ 2 + 1)..i]; I[2]; // I[1]=I[1][1..(i/ 2)]; I[1]; I[2]=0; } if (size(matrix(I))==2) { if (size(VARS)==1) {planecurve=1; str = str + "ParametricPlot[";} if (size(VARS)==2) {implcrv=1; str = str + "ImplicitPlot[";} } if (size(matrix(I))==3) { if (size(VARS)==1) {spacecurve=1;} if (size(VARS)==2) {surface=1;} str = str + "ParametricPlot3D["; } short = 0; pstring = string(I); // switch to another ring if necessary checkshort(); // "short: "; short; if (short!=1) // construct a map { mapping = 1; setring @r; @J = 0; for(i=1;i<=size(VARS);i++) { @J[VARS[i]]=var(i);} map phi = (`basr`,@J); @I = phi(I); short =0; pstring = string(@I); setring `basr`; } i = find(pstring,newline); while(i) {pstring[i]=" "; i = find(pstring,newline,i); } if (implcrv) { i = find(pstring,","); pstring = pstring[1,i-1] + "==" + pstring[i+1,size(pstring)-i]; } else { pstring = "{" + pstring + "}";} // "mapping "; mapping; if (mapping) { xname = "s"; if (size(VARS)==2) {yname="t";} } else { xname = varstr(VARS[1]); if (size(VARS)==2) {yname=varstr(VARS[2]);} } j =1; for(k=1;k<=size(#);k++) { if (typeof(#[k])=="ideal" or typeof(#[k])=="poly") { //#[k] = ideal(#[k]); v = determvars(#[k]); J = #[k]; short =0; if (size(matrix(J))==1 and size(VARS)==2 and implcrv) { i =size(J[1]); // J[2]=J[1][(i/ 2 + 1)..i]; // J[1]=J[1][1..(i/ 2)]; J[2] =0; } if ((v!= VARS) or (size(J)!=size(I))) { print("--Error: ---- "); return(); } else { if (mapping) { setring @r; short =0; actstring = string(phi(J)); setring(`basr`); } else {actstring = string(J);} i = find(actstring,newline); while(i) { actstring[i]=" "; i = find(actstring,newline,i); } if (implcrv) {i = find(actstring,","); actstring = actstring[1,i-1]+ "==" + actstring[i+1,size(actstring)-i]; pstring = pstring + "," + actstring; } else { pstring = pstring + ",{" + actstring +"}"; } } } if (typeof(#[k])=="string") { if (j==3) {zpart = #[k];j++;} if (j==2) {ypart = #[k];j++;} if (j==1) {xpart = #[k];j++;} } } if (spacecurve or planecurve or implcrv) { str = str + "{" + pstring + "},{" + xname + "," + xpart + "}";} if (implcrv and (j==3)) {str = str + ",{" + yname + "," + ypart + "}";} if (surface) { str = str + "{" + pstring + "},{" + xname + "," + xpart + "},{" + yname + "," + ypart + "}";} if (planecurve) {closing = "," + newline +" AspectRatio->Automatic";} if (implcrv) {closing = "," + newline + " AxesLabel->{\"" + varstr(VARS[1]) + "\",\"" + varstr(VARS[2]) + "\"}";} if (spacecurve) { closing = "," + newline + " ViewPoint->{1.3,-2.4,2}";} if (surface) {closing = "," +newline + " Boxed->True, Axes->True, ViewPoint->{1.3,-2.4,2}";} str = str + closing + "];" + endstr(fname); return(str); } example { "EXAMPLE:"; echo =2; // --------- plane curves ------------ ring rr0 = 0,x,dp; export rr0; ideal I = x3 + x, x2; ideal J = x2, -x+x3; mplot("",I,J,"-2,2"); // Paste the output into a Mathematica notebook // active evalutation of the cell with SHIFT RETURN pause("Hit RETURN to continue"); // --------- space curves -------------- I = x3,-1/10x3+x2,x2; mplot("",I); // Paste the output into a Mathematica notebook // active evalutation of the cell with SHIFT RETURN pause("Hit RETURN to continue"); // ----------- surfaces ------------------- ring rr1 = 0,(x,y),dp; export rr1; ideal J = xy,y,x2; mplot("",J,"-2,1","1,2"); // Paste the output into a Mathematica notebook // active evalutation of the cell with SHIFT RETURN kill rr0,rr1; } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/grobcov.lib000066400000000000000000004275521266270727000203170ustar00rootroot00000000000000// version="version grobcov.lib 4.0.2.0 Jul_2015 "; // $Id: 53a8fb2ee05d14670a58e7cad32bc15f054511d9 $ // version L; July_2015; category="General purpose"; info=" LIBRARY: grobcov.lib Groebner Cover for parametric ideals. Comprehensive Groebner Systems, Groebner Cover, Canonical Forms, Parametric Polynomial Systems, Dynamic Geometry, Loci, Envelop, Constructible sets. See A. Montes A, M. Wibmer, \"Groebner Bases for Polynomial Systems with parameters\", Journal of Symbolic Computation 45 (2010) 1391-1425. (http://www-ma2.upc.edu/~montes/). AUTHORS: Antonio Montes , Hans Schoenemann. OVERVIEW: In 2010, the library was designed to contain Montes-Wibmer's algorithms for compute the canonical Groebner Cover of a parametric ideal as described in the paper: Montes A., Wibmer M., \"Groebner Bases for Polynomial Systems with parameters\". Journal of Symbolic Computation 45 (2010) 1391-1425. The central routine is grobcov. Given a parametric ideal, grobcov outputs its Canonical Groebner Cover, consisting of a set of pairs of (basis, segment). The basis (after normalization) is the reduced Groebner basis for each point of the segment. The segments are disjoint, locally closed and correspond to constant lpp (leading power product) of the basis, and are represented in canonical prime representation. The segments are disjoint and cover the whole parameter space. The output is canonical, it only depends on the given parametric ideal and the monomial order. This is much more than a simple Comprehensive Groebner System. The algorithm grobcov allows options to solve partially the problem when the whole automatic algorithm does not finish in reasonable time. grobcov uses a first algorithm cgsdr that outputs a disjoint reduced Comprehensive Groebner System with constant lpp. For this purpose, in this library, the implemented algorithm is Kapur-Sun-Wang algorithm, because it is the most efficient algorithm known for this purpose. D. Kapur, Y. Sun, and D.K. Wang. \"A New Algorithm for Computing Comprehensive Groebner Systems\". Proceedings of ISSAC'2010, ACM Press, (2010), 29-36. The library has evolved to include new applications of the Groebner Cover, and new theoretical developments have been done. The actual version also includes a routine (ConsLevels) for computing the canonical form of a constructible set, given as a union of locally closed sets. It is used in the new version for the computation of loci and envelops. It determines the canonical locally closed level sets of a constructuble. They will be described in a forthcoming paper: J.M. Brunat, A. Montes, \"Computing the canonical representation of constructible sets\". Submited to Mathematics in Computer Science. July 2015. A new set of routines (locus, locusdg, locusto) has been included to compute loci of points. The routines are used in the Dynamic Geometry software Geogebra. They are described in: Abanades, Botana, Montes, Recio: \''An Algebraic Taxonomy for Locus Computation in Dynamic Geometry\''. Computer-Aided Design 56 (2014) 22-33. Recently also routines for computing the envelop of a family of curves (enverlop, envelopdg), to be used in Dynamic Geometry, has been included and will be described in a forthcoming paper: Abanades, Botana, Montes, Recio: \''Envelops in Dynamic Geometry using the Groebner cover\''. This version was finished on 31/07/2015 NOTATIONS: All given and determined polynomials and ideals are in the @* basering Q[a][x]; (a=parameters, x=variables) @* After defining the ring, the main routines @* grobcov, cgsdr, @* generate the global rings @* @R (Q[a][x]), @* @P (Q[a]), @* @RP (Q[x,a]) @* that are used inside and killed before the output. PROCEDURES: grobcov(F); Is the basic routine giving the canonical Groebner Cover of the parametric ideal F. This routine accepts many options, that allow to obtain results even when the canonical computation does not finish in reasonable time. cgsdr(F); Is the procedure for obtaining a first disjoint, reduced Comprehensive Groebner System that is used in grobcov, that can also be used independently if only the CGS is required. It is a more efficient routine than buildtree (the own routine of 2010 that is no more used). Now, KSW algorithm is used. pdivi(f,F); Performs a pseudodivision of a parametric polynomial by a parametric ideal. pnormalf(f,E,N); Reduces a parametric polynomial f over V(E) \ V(N) ( E is the null ideal and N the non-null ideal ) over the parameters. Crep(N,M); Computes the canonical C-representation of V(N) \ V(M). Prep(N,M); Computes the canonical P-representation of V(N) \ V(M). PtoCrep(L) Starting from the canonical Prep of a locally closed set computes its Crep. extend(GC); When the grobcov of an ideal has been computed with the default option ('ext',0) and the explicit option ('rep',2) (which is not the default), then one can call extend (GC) (and options) to obtain the full representation of the bases. With the default option ('ext',0) only the generic representation of the bases are computed, and one can obtain the full representation using extend. ConsLevels(L); Given a list L of locally closed sets, it returns the canonical levels of the constructible set of the union of them, as well as the levels of the complement. It is described in the paper J.M. Brunat, A. Montes, \"Computing the canonical representation of constructible sets\". Submited to Mathematics in Computer Science. July 2015. locus(G); Special routine for determining the geometrical locus of points verifying given conditions. Given a parametric ideal J with parameters (x,y) and variables (x_1,..,xn), representing the system determining the locus of points (x,y) who verify certain properties, one can apply locus to the output of grobcov(J), locus determines the different classes of locus components. described in the paper: \"An Algebraic Taxonomy for Locus Computation in Dynamic Geometry\", M. Abanades, F. Botana, A. Montes, T. Recio, Computer-Aided Design 56 (2014) 22-33. The components can be 'Normal', 'Special', 'Accumulation', 'Degenerate'. The output are the components is given in P-canonical form It also detects automatically a possible point that is to be avoided by the mover, whose coordinates must be the last two coordinates in the definition of the ring. If such a point is detected, then it eliminates the segments of the grobcov depending on the point that is to be avoided. locusdg(G); Is a special routine that determines the 'Relevant' components of the locus in dynamic geometry. It is to be called to the output of locus and selects from it the useful components. envelop(F,C); Special routine for determining the envelop of a family of curves F in Q[x,y][x_1,..xn] depending on a ideal of constraints C in Q[x_1,..,xn]. It detemines the different components as well as its type: 'Normal', 'Special', 'Accumulation', 'Degenerate'. And it also classifies the Special components, determining the zero dimensional antiimage of the component and verifying if the component is a special curve of the family or not. It calls internally first grobcov and then locus with special options to obtain the complete result. The taxonomy that it provides, as well as the algorithms involved will be described in a forthcoming paper: Abanades, Botana, Montes, Recio: \''Envelops in Dynamic Geometry using the Gr\"obner cover\''. envelopdg(ev); Is a special routine to determine the 'Relevant' components of the envelop of a family of curves to be used in Dynamic Geometry. It must be called to the output of envelop(F,C). locusto(L); Transforms the output of locus, locusdg, envelop and envelopdg into a string that can be reed from different computational systems. SEE ALSO: compregb_lib "; LIB "primdec.lib"; LIB "qhmoduli.lib"; // ************ Begin of the grobcov library ********************* // Library grobcov.lib // (Groebner Cover): // Release 0: (public) // Initial data: 21-1-2008 // Uses buildtree for cgsdr // Final data: 3-7-2008 // Release 2: (private) // Initial data: 6-9-2009 // Last version using buildtree for cgsdr // Final data: 25-10-2011 // Release B: (private) // Initial data: 1-7-2012 // Uses both buildtree and KSW for cgsdr // Final data: 4-9-2012 // Release G: (public) // Initial data: 4-9-2012 // Uses KSW algorithm for cgsdr // Final data: 21-11-2013 // Release L: (public) // New routine ConsLevels: 10-7-2015 // Updated locus: 10-7-2015 (uses Conslevels) // New routines for computing the envelop of a family of curves: 22-1-2015 // Final data: 22-7-2015 //*************Auxiliary routines************** // elimintfromideal: elimine the constant numbers from an ideal // (designed for W, nonnull conditions) // Input: ideal J // Output:ideal K with the elements of J that are non constants, in the // ring K[x1,..,xm] static proc elimintfromideal(ideal J) { int i; int j=0; ideal K; if (size(J)==0){return(ideal(0));} for (i=1;i<=ncols(J);i++){if (size(variables(J[i])) !=0){j++; K[j]=J[i];}} return(K); } // delfromideal: deletes the i-th polynomial from the ideal F // Works in any kind of ideal static proc delfromideal(ideal F, int i) { int j; ideal G; if (size(F)1) { for(j=1;j<=i-1;j++) { L[size(L)+1]=l[j]; } } for(j=i+1;j<=size(l);j++) { L[size(L)+1]=l[j]; } return(L); } // eliminates repeated elements form an ideal or matrix or module or intmat or bigintmat static proc elimrepeated(F) { int i; int nt; if (typeof(F)=="ideal"){nt=ncols(F);} else{nt=size(F);} def FF=F; FF=F[1]; for (i=2;i<=nt;i++) { if (not(memberpos(F[i],FF)[1])) { FF[size(FF)+1]=F[i]; } } return(FF); } // equalideals // Input: ideals F and G; // Output: 1 if they are identical (the same polynomials in the same order) // 0 else static proc equalideals(ideal F, ideal G) { int i=1; int t=1; if (size(F)!=size(G)){return(0);} while ((i<=size(F)) and (t)) { if (F[i]!=G[i]){t=0;} i++; } return(t); } // returns 1 if the two lists of ideals are equal and 0 if not static proc equallistideals(list L, list M) { int t; int i; if (size(L)!=size(M)){return(0);} else { t=1; if (size(L)>0) { i=1; while ((t) and (i<=size(L))) { if (equalideals(L[i],M[i])==0){t=0;} i++; } } return(t); } } // idcontains // Input: ideal p, ideal q // Output: 1 if p contains q, 0 otherwise // If the routine is to be called from the top, a previous call to // setglobalrings() is needed. static proc idcontains(ideal p, ideal q) { int t; int i; t=1; i=1; def P=p; def Q=q; attrib(P,"isSB",1); poly r; while ((t) and (i<=size(Q))) { r=reduce(Q[i],P); if (r!=0){t=0;} i++; } return(t); } // selectminideals // given a list of ideals returns the list of integers corresponding // to the minimal ideals in the list // Input: L (list of ideals) // Output: the list of integers corresponding to the minimal ideals in L // Works in Q[u_1,..,u_m] static proc selectminideals(list L) { list P; int i; int j; int t; if(size(L)==0){return(L)}; if(size(L)==1){P[1]=1; return(P);} for (i=1;i<=size(L);i++) { t=1; j=1; while ((t) and (j<=size(L))) { if (i!=j) { if(idcontains(L[i],L[j])==1) { t=0; } } j++; } if (t){P[size(P)+1]=i;} } return(P); } // Auxiliary routine // elimconstfac: eliminate the factors in the polynom f that are in Q[a] // Input: // poly f: // list L: of components of the segment // Output: // poly f2 where the factors of f in Q[a] that are non-null on any component // have been dropped from f static proc elimconstfac(poly f) { int cond; int i; int j; int t; if (f==0){return(f);} def RR=basering; setring(@R); def ff=imap(RR,f); def l=factorize(ff,0); poly f1=1; for(i=2;i<=size(l[1]);i++) { f1=f1*(l[1][i])^(l[2][i]); } setring(RR); def f2=imap(@R,f1); return(f2); }; static proc memberpos(f,J) //"USAGE: memberpos(f,J); // (f,J) expected (polynomial,ideal) // or (int,list(int)) // or (int,intvec) // or (intvec,list(intvec)) // or (list(int),list(list(int))) // or (ideal,list(ideal)) // or (list(intvec), list(list(intvec))). // Works in any kind of ideals //RETURN: The list (t,pos) t int; pos int; // t is 1 if f belongs to J and 0 if not. // pos gives the position in J (or 0 if f does not belong). //EXAMPLE: memberpos; shows an example" { int pos=0; int i=1; int j; int t=0; int nt; if (typeof(J)=="ideal"){nt=ncols(J);} else{nt=size(J);} if ((typeof(f)=="poly") or (typeof(f)=="int")) { // (poly,ideal) or // (poly,list(poly)) // (int,list(int)) or // (int,intvec) i=1; while(i<=nt) { if (f==J[i]){return(list(1,i));} i++; } return(list(0,0)); } else { if ((typeof(f)=="intvec") or ((typeof(f)=="list") and (typeof(f[1])=="int"))) { // (intvec,list(intvec)) or // (list(int),list(list(int))) i=1; t=0; pos=0; while((i<=nt) and (t==0)) { t=1; j=1; if (size(f)!=size(J[i])){t=0;} else { while ((j<=size(f)) and t) { if (f[j]!=J[i][j]){t=0;} j++; } } if (t){pos=i;} i++; } if (t){return(list(1,pos));} else{return(list(0,0));} } else { if (typeof(f)=="ideal") { // (ideal,list(ideal)) i=1; t=0; pos=0; while((i<=nt) and (t==0)) { t=1; j=1; if (ncols(f)!=ncols(J[i])){t=0;} else { while ((j<=ncols(f)) and t) { if (f[j]!=J[i][j]){t=0;} j++; } } if (t){pos=i;} i++; } if (t){return(list(1,pos));} else{return(list(0,0));} } else { if ((typeof(f)=="list") and (typeof(f[1])=="intvec")) { // (list(intvec),list(list(intvec))) i=1; t=0; pos=0; while((i<=nt) and (t==0)) { t=1; j=1; if (size(f)!=size(J[i])){t=0;} else { while ((j<=size(f)) and t) { if (f[j]!=J[i][j]){t=0;} j++; } } if (t){pos=i;} i++; } if (t){return(list(1,pos));} else{return(list(0,0));} } } } } } //example //{ "EXAMPLE:"; echo = 2; // list L=(7,4,5,1,1,4,9); // memberpos(1,L); //} // Auxiliary routine // pos // Input: intvec p of zeros and ones // Output: intvec W of the positions where p has ones. static proc pos(intvec p) { int i; intvec W; int j=1; for (i=1; i<=size(p); i++) { if (p[i]==1){W[j]=i; j++;} } return(W); } // Input: // A,B: lists of ideals // Output: // 1 if both lists of ideals are equal, or 0 if not static proc equallistsofideals(list A, list B) { int i; int tes=0; if (size(A)!=size(B)){return(tes);} tes=1; i=1; while(tes==1 and i<=size(A)) { if (equalideals(A[i],B[i])==0){tes=0; return(tes);} i++; } return(tes); } // Input: // A,B: lists of P-rep, i.e. of the form [p_i,[p_{i1},..,p_{ij_i}]] // Output: // 1 if both lists of P-reps are equal, or 0 if not static proc equallistsA(list A, list B) { int tes=0; if(equalideals(A[1],B[1])==0){return(tes);} tes=equallistsofideals(A[2],B[2]); return(tes); } // Input: // A,B: lists lists of of P-rep, i.e. of the form [[p_1,[p_{11},..,p_{1j_1}]] .. [p_i,[p_{i1},..,p_{ij_i}]] // Output: // 1 if both lists of lists of P-rep are equal, or 0 if not static proc equallistsAall(list A,list B) { int i; int tes; if(size(A)!=size(B)){return(tes);} tes=1; i=1; while(tes and i<=size(A)) { tes=equallistsA(A[i],B[i]); i++; } return(tes); } // idint: ideal intersection // in the ring @P. // it works in an extended ring // input: two ideals in the ring @P // output the intersection of both (is not a GB) static proc idint(ideal I, ideal J) { def RR=basering; ring T=0,t,lp; def K=T+RR; setring(K); def Ia=imap(RR,I); def Ja=imap(RR,J); ideal IJ; int i; for(i=1;i<=size(Ia);i++){IJ[i]=t*Ia[i];} for(i=1;i<=size(Ja);i++){IJ[size(Ia)+i]=(1-t)*Ja[i];} ideal eIJ=eliminate(IJ,t); setring(RR); return(imap(K,eIJ)); } //purpose ideal intersection called in @R and computed in @P static proc idintR(ideal N, ideal M) { def RR=basering; setring(@P); def Np=imap(RR,N); def Mp=imap(RR,M); def Jp=idint(Np,Mp); setring(RR); return(imap(@P,Jp)); } // Auxiliary routine // comb: the list of combinations of elements (1,..n) of order p static proc comb(int n, int p) { list L; list L0; intvec c; intvec d; int i; int j; int last; if ((n<0) or (n=g static proc lesspol(poly f, poly g) { if (leadmonom(f) static proc incquotient(ideal N, poly f) { poly g; int i; ideal Nb; ideal Na=N; if (size(Na)==1) { g=gcd(Na[1],f); if (g!=1) { Na[1]=Na[1]/g; } attrib(Na,"IsSB",1); return(Na); } def P=basering; poly @t; ring H=0,@t,lp; def HP=H+P; setring(HP); def fh=imap(P,f); def Nh=imap(P,N); ideal Nht; for (i=1;i<=size(Nh);i++) { Nht[i]=Nh[i]*@t; } attrib(Nht,"isSB",1); def fht=(1-@t)*fh; option(redSB); Nht=std(Nht,fht); ideal Nc; ideal v; for (i=1;i<=size(Nht);i++) { v=variables(Nht[i]); if(memberpos(@t,v)[1]==0) { Nc[size(Nc)+1]=Nht[i]/fh; } } setring(P); ideal HH; def Nd=imap(HP,Nc); Nb=Nd; option(redSB); Nb=std(Nd); return(Nb); } // Auxiliary routine to define an order for ideals // Returns 1 if the ideal a is shoud precede ideal b by sorting them in idbefid order // 2 if the the contrary happen // 0 if the order is not relevant static proc idbefid(ideal a, ideal b) { poly fa; poly fb; poly la; poly lb; int te=1; int i; int j; int na=size(a); int nb=size(b); int nm; if (na<=nb){nm=na;} else{nm=nb;} for (i=1;i<=nm; i++) { fa=a[i]; fb=b[i]; while((fa!=0) or (fb!=0)) { la=lead(fa); lb=lead(fb); fa=fa-la; fb=fb-lb; la=leadmonom(la); lb=leadmonom(lb); if(leadmonom(la+lb)!=la){return(1);} else{if(leadmonom(la+lb)!=lb){return(2);}} } } if(nanb){return(2);} else{return(0);} } } // sort a list of ideals using idbefid static proc sortlistideals(list L) { int i; int j; int n; ideal a; ideal b; list LL=L; list NL; int k; int te; i=1; while(size(LL)>0) { k=1; for(j=2;j<=size(LL);j++) { te=idbefid(LL[k],LL[j]); if (te==2){k=j;} } NL[size(NL)+1]=LL[k]; n=size(LL); if (n>1){LL=elimfromlist(LL,k);} else{LL=list();} } return(NL); } // Crep // Computes the C-representation of V(N) \ V(M). // input: // ideal N (null ideal) (not necessarily radical nor maximal) // ideal M (hole ideal) (not necessarily containing N) // output: // the list (a,b) of the canonical ideals // the Crep of V(N) \ V(M) // Assumed to be called in the ring @R // Works on the ring @P proc Crep(ideal N, ideal M) "USAGE: Crep(N,M); Input: ideal N (null ideal) (not necessarily radical nor maximal) ideal M (hole ideal) (not necessarily containing N) RETURN: The canonical C-representation of the locally closed set. [ P,Q ], a pair of radical ideals with P included in Q, representing the set V(P) \ V(Q) = V(N) \ V(M) NOTE: Operates in a ring R=Q[a] (a=parameters) KEYWORDS: locally closed set, canoncial form EXAMPLE: Crep; shows an example" { list l; ideal Np=std(N); if (equalideals(Np,ideal(1))) { l=ideal(1),ideal(1); return(l); } int i; list L; ideal Q=Np+M; ideal P=ideal(1); L=minGTZ(Np); for(i=1;i<=size(L);i++) { if(idcontains(L[i],Q)==0) { P=intersect(P,L[i]); } } P=std(P); Q=std(radical(Q+P)); list T=P,Q; return(T); } example { "EXAMPLE:"; echo = 2; if(defined(Grobcov::@P)){kill Grobcov::@R; kill Grobcov::@P; kill Grobcov::@RP;} ring R=0,(x,y,z),lp; short=0; ideal E=x*(x^2+y^2+z^2-25); ideal N=x*(x-3),y-4; def Cr=Crep(E,N); Cr; def L=Prep(E,N); L; def Cr1=PtoCrep(L); Cr1; } // Prep // Computes the P-representation of V(N) \ V(M). // input: // ideal N (null ideal) (not necessarily radical nor maximal) // ideal M (hole ideal) (not necessarily containing N) // output: // the ((p_1,(p_11,p_1k_1)),..,(p_r,(p_r1,p_rk_r))); // the Prep of V(N) \ V(M) // Assumed to be called in the ring @R // Works on the ring @P proc Prep(ideal N, ideal M) "USAGE: Prep(N,M); Input: ideal N (null ideal) (not necessarily radical nor maximal) ideal M (hole ideal) (not necessarily containing N) RETURN: The canonical P-representation of the locally closed set V(N) \ V(M) Output: [ Comp_1, .. , Comp_s ] where Comp_i=[p_i,[p_i1,..,p_is_i]] NOTE: Operates in a ring R=Q[a] (a=parameters) KEYWORDS: Locally closed set, Canoncial form EXAMPLE: Prep; shows an example" { int te; if (N[1]==1) { return(list(list(ideal(1),list(ideal(1))))); } int i; int j; list L0; list Ni=minGTZ(N); list prep; for(j=1;j<=size(Ni);j++) { option(redSB); Ni[j]=std(Ni[j]); } list Mij; for (i=1;i<=size(Ni);i++) { Mij=minGTZ(Ni[i]+M); for(j=1;j<=size(Mij);j++) { option(redSB); Mij[j]=std(Mij[j]); } if ((size(Mij)==1) and (equalideals(Ni[i],Mij[1])==1)){;} else { prep[size(prep)+1]=list(Ni[i],Mij); } } //"T_abans="; prep; if (size(prep)==0){prep=list(list(ideal(1),list(ideal(1))));} //"T_Prep="; prep; //def Lout=CompleteA(prep,prep); //"T_Lout="; Lout; return(prep); } example { "EXAMPLE:"; echo = 2; if(defined(Grobcov::@P)){kill Grobcov::@R; kill Grobcov::@P; kill Grobcov::@RP;} short=0; ring R=0,(x,y,z),lp; ideal E=x*(x^2+y^2+z^2-25); ideal N=x*(x-3),y-4; Prep(E,N); } // PtoCrep // Computes the C-representation from the P-representation. // input: // list ((p_1,(p_11,p_1k_1)),..,(p_r,(p_r1,p_rk_r))); // the P-representation of V(N) \ V(M) // output: // list (ideal ida, ideal idb) // the C-representaion of V(N) \ V(M) = V(ida) \ V(idb) // Assumed to be called in the ring @R // Works on the ring @P proc PtoCrep(list L) "USAGE: PtoCrep(L) Input L: list [ Comp_1, .. , Comp_s ] where Comp_i=[p_i,[p_i1,..,p_is_i] ], is the P-representation of a locally closed set V(N) \ V(M) RETURN: The canonical C-representation of the locally closed set [ P,Q ], a pair of radical ideals with P included in Q, representing the set V(P) \ V(Q) NOTE: Operates in a ring R=Q[a] (a=parameters) KEYWORDS: locally closed set, canoncial form EXAMPLE: PtoCrep; shows an example" { int te; def RR=basering; if(defined(@P)){te=1; setring(@P); list Lp=imap(RR,L);} else { te=0; def Lp=L;} def La=PtoCrep0(Lp); if(te==1) {setring(RR); def LL=imap(@P,La);} if(te==0){def LL=La;} return(LL); } example { "EXAMPLE:"; echo = 2; if(defined(Grobcov::@P)){kill Grobcov::@R; kill Grobcov::@P; kill Grobcov::@RP;} short=0; ring R=0,(x,y,z),lp; // (P,Q) represents a locally closed set ideal P=x^3+x*y^2+x*z^2-25*x; ideal Q=y-4,x*z,x^2-3*x; // Now compute the P-representation= def L=Prep(P,Q); L; // Now compute the C-representation= def J=PtoCrep(L); J; // Now come back recomputing the P-represetation of the C-representation= Prep(J[1],J[2]); } // PtoCrep0 // Computes the C-representation from the P-representation. // input: // list ((p_1,(p_11,p_1k_1)),..,(p_r,(p_r1,p_rk_r))); // the P-representation of V(N) \ V(M) // output: // list (ideal ida, ideal idb) // the C-representation of V(N) \ V(M) = V(ida) \ V(idb) // Works in a ring Q[u_1,..,u_m] and is called on it. static proc PtoCrep0(list L) { int te=0; def Lp=L; int i; int j; ideal ida=ideal(1); ideal idb=ideal(1); list Lb; ideal N; for (i=1;i<=size(Lp);i++) { option(returnSB); N=Lp[i][1]; ida=intersect(ida,N); Lb=Lp[i][2]; for(j=1;j<=size(Lb);j++) { idb=intersect(idb,Lb[j]); } } //idb=radical(idb); def La=list(ida,idb); return(La); } // input: F a parametric ideal in Q[a][x] // output: a rComprehensive Groebner System disjoint and reduced. // It uses Kapur-Sun-Wang algorithm, and with the options // can compute the homogenization before (('can',0) or ( 'can',1)) // and dehomogenize the result. proc cgsdr(ideal F, list #) "USAGE: cgsdr(F); F: ideal in Q[a][x] (a=parameters, x=variables) to be discussed. To compute a disjoint, reduced Comprehensive Groebner System (CGS). cgsdr is the starting point of the fundamental routine grobcov. Inside grobcov it is used with options 'can' set to 0,1 and not with options ('can',2). It is to be used if only a disjoint reduced CGS is required. Options: To modify the default options, pairs of arguments -option name, value- of valid options must be added to the call. Options: \"can\",0-1-2: The default value is \"can\",2. In this case no homogenization is done. With option (\"can\",0) the given basis is homogenized, and with option (\"can\",1) the whole given ideal is homogenized before computing the cgs and dehomogenized after. with option (\"can\",0) the homogenized basis is used with option (\"can\",1) the homogenized ideal is used with option (\"can\",2) the given basis is used \"null\",ideal E: The default is (\"null\",ideal(0)). \"nonnull\",ideal N: The default (\"nonnull\",ideal(1)). When options \"null\" and/or \"nonnull\" are given, then the parameter space is restricted to V(E) \ V(N). \"comment\",0-1: The default is (\"comment\",0). Setting (\"comment\",1) will provide information about the development of the computation. \"out\",0-1: 1 (default) the output segments are given as as difference of varieties. 0: the output segments are given in P-representation and the segments grouped by lpp With options (\"can\",0) and (\"can\",1) the option (\"out\",1) is set to (\"out\",0) because it is not compatible. One can give none or whatever of these options. With the default options (\"can\",2,\"out\",1), only the Kapur-Sun-Wang algorithm is computed. This is very efficient but is only the starting point for the computation of grobcov. When grobcov is computed, the call to cgsdr inside uses specific options that are more expensive ("can",0-1,"out",0). RETURN: Returns a list T describing a reduced and disjoint Comprehensive Groebner System (CGS), With option (\"out\",0) the segments are grouped by leading power products (lpp) of the reduced Groebner basis and given in P-representation. The returned list is of the form: ( (lpp, (num,basis,segment),...,(num,basis,segment),lpp), ..,, (lpp, (num,basis,segment),...,(num,basis,segment),lpp) ) The bases are the reduced Groebner bases (after normalization) for each point of the corresponding segment. The third element of each lpp segment is the lpp of the used ideal in the CGS as a string: with option (\"can\",0) the homogenized basis is used with option (\"can\",1) the homogenized ideal is used with option (\"can\",2) the given basis is used With option (\"out\",1) (default) only KSW is applied and segments are given as difference of varieties and are not grouped The returned list is of the form: ( (E,N,B),..(E,N,B) ) E is the null variety N is the nonnull variety segment = V(E) \ V(N) B is the reduced Groebner basis NOTE: The basering R, must be of the form Q[a][x], (a=parameters, x=variables), and should be defined previously, and the ideal defined on R. KEYWORDS: CGS, disjoint, reduced, Comprehensive Groebner System EXAMPLE: cgsdr; shows an example" { int te; def RR=basering; if(defined(@P)){te=1;} else{te=0; setglobalrings();} // INITIALIZING OPTIONS int i; int j; def E=ideal(0); def N=ideal(1); int comment=0; int can=2; int out=1; poly f; ideal B; int start=timer; list L=#; for(i=1;i<=size(L) div 2;i++) { if(L[2*i-1]=="null"){E=L[2*i];} else { if(L[2*i-1]=="nonnull"){N=L[2*i];} else { if(L[2*i-1]=="comment"){comment=L[2*i];} else { if(L[2*i-1]=="can"){can=L[2*i];} else { if(L[2*i-1]=="out"){out=L[2*i];} } } } } } //if(can==2){out=1;} B=F; if ((printlevel) and (comment==0)){comment=printlevel;} if((can<2) and (out>0)){"Option out,1 is not compatible with can,0,1"; out=0;} // DEFINING OPTIONS list LL; LL[1]="can"; LL[2]=can; LL[3]="comment"; LL[4]=comment; LL[5]="out"; LL[6]=out; LL[7]="null"; LL[8]=E; LL[9]="nonnull"; LL[10]=N; if(comment>=1) { string("Begin cgsdr with options: ",LL); } int ish; for (i=1;i<=size(B);i++){ish=ishomog(B[i]); if(ish==0){break;};} if (ish) { if(comment>0){string("The given system is homogneous");} def GS=KSW(B,LL); //can=0; } else { // ACTING DEPENDING ON OPTIONS if(can==2) { // WITHOUT HOMOHGENIZING if(comment>0){string("Option of cgsdr: do not homogenize");} def GS=KSW(B,LL); setglobalrings(); } else { if(can==1) { // COMPUTING THE HOMOGOENIZED IDEAL if(comment>=1){string("Homogenizing the whole ideal: option can=1");} list RRL=ringlist(RR); RRL[3][1][1]="dp"; def Pa=ring(RRL[1]); list Lx; Lx[1]=0; Lx[2]=RRL[2]+RRL[1][2]; Lx[3]=RRL[1][3]; Lx[4]=RRL[1][4]; RRL[1]=0; def D=ring(RRL); def RP=D+Pa; setring(RP); def B1=imap(RR,B); option(redSB); B1=std(B1); setring(RR); def B2=imap(RP,B1); } else { // (can=0) if(comment>0){string("Homogenizing the basis: option can=0");} def B2=B; } // COMPUTING HOMOGENIZED CGS poly @t; ring H=0,@t,dp; def RH=RR+H; setring(RH); setglobalrings(); def BH=imap(RR,B2); def LH=imap(RR,LL); for (i=1;i<=size(BH);i++) { BH[i]=homog(BH[i],@t); } if (comment>=2){string("Homogenized system = "); BH;} def GSH=KSW(BH,LH); setglobalrings(); // DEHOMOGENIZING THE RESULT if(out==0) { for (i=1;i<=size(GSH);i++) { GSH[i][1]=subst(GSH[i][1],@t,1); for(j=1;j<=size(GSH[i][2]);j++) { GSH[i][2][j][2]=subst(GSH[i][2][j][2],@t,1); } } } else { for (i=1;i<=size(GSH);i++) { GSH[i][3]=subst(GSH[i][3],@t,1); GSH[i][7]=subst(GSH[i][7],@t,1); } } setring(RR); def GS=imap(RH,GSH); } setglobalrings(); if(out==0) { for (i=1;i<=size(GS);i++) { GS[i][1]=postredgb(mingb(GS[i][1])); for(j=1;j<=size(GS[i][2]);j++) { GS[i][2][j][2]=postredgb(mingb(GS[i][2][j][2])); } } } else { for (i=1;i<=size(GS);i++) { if(GS[i][2]==1) { GS[i][3]=postredgb(mingb(GS[i][3])); if (typeof(GS[i][7])=="ideal") { GS[i][7]=postredgb(mingb(GS[i][7]));} } } } } if(te==0){kill @P; kill @R; kill @RP;} return(GS); } example { "EXAMPLE:"; echo = 2; // Casas conjecture for degree 4: ring R=(0,a0,a1,a2,a3,a4),(x1,x2,x3),dp; short=0; ideal F=x1^4+(4*a3)*x1^3+(6*a2)*x1^2+(4*a1)*x1+(a0), x1^3+(3*a3)*x1^2+(3*a2)*x1+(a1), x2^4+(4*a3)*x2^3+(6*a2)*x2^2+(4*a1)*x2+(a0), x2^2+(2*a3)*x2+(a2), x3^4+(4*a3)*x3^3+(6*a2)*x3^2+(4*a1)*x3+(a0), x3+(a3); cgsdr(F); } // input: internal routine called by cgsdr at the end to group the // lpp segments and improve the output // output: grouped segments by lpp obtained in cgsdr static proc grsegments(list T) { int i; list L; list lpp; list lp; list ls; int n=size(T); lpp[1]=T[n][1]; L[1]=list(lpp[1],list(list(T[n][2],T[n][3],T[n][4]))); if (n>1) { for (i=1;i<=size(T)-1;i++) { lp=memberpos(T[n-i][1],lpp); if(lp[1]==1) { ls=L[lp[2]][2]; ls[size(ls)+1]=list(T[n-i][2],T[n-i][3],T[n-i][4]); L[lp[2]][2]=ls; } else { lpp[size(lpp)+1]=T[n-i][1]; L[size(L)+1]=list(T[n-i][1],list(list(T[n-i][2],T[n-i][3],T[n-i][4]))); } } } return(L); } // LCUnion // Given a list of the P-representations of locally closed segments // for which we know that the union is also locally closed // it returns the P-representation of its union // input: L list of segments in P-representation // ((p_j^i,(p_j1^i,...,p_jk_j^i | j=1..t_i)) | i=1..s ) // where i represents a segment // output: P-representation of the union // ((P_j,(P_j1,...,P_jk_j | j=1..t))) static proc LCUnion(list LL) { def RR=basering; setring(@P); def L=imap(RR,LL); int i; int j; int k; list H; list C; list T; list L0; list P0; list P; list Q0; list Q; for (i=1;i<=size(L);i++) { for (j=1;j<=size(L[i]);j++) { P0[size(P0)+1]=L[i][j][1]; L0[size(L0)+1]=intvec(i,j); } } Q0=selectminideals(P0); for (i=1;i<=size(Q0);i++) { Q[i]=L0[Q0[i]]; P[i]=L[Q[i][1]][Q[i][2]]; } // P is the list of the maximal components of the union // with the corresponding initial holes. // Q is the list of intvec positions in L of the first element of the P's // Its elements give (num of segment, num of max component (=min ideal)) for (k=1;k<=size(Q);k++) { H=P[k][2]; // holes of P[k][1] for (i=1;i<=size(L);i++) { if (i!=Q[k][1]) { for (j=1;j<=size(L[i]);j++) { C[size(C)+1]=L[i][j]; } } } T[size(T)+1]=list(Q[k],P[k][1],addpart(H,C)); } setring(RR); def TT=imap(@P,T); return(TT); } // Auxiliary routine // called by LCUnion to modify the holes of a primepart of the union // by the addition of the segments that do not correspond to that part // Works on @P ring. // Input: // H=(p_i1,..,p_is) the holes of a component to be transformed by the addition of // the segments C that do not correspond to that component // C=((q_1,(q_11,..,q_1l_1),pos1),..,(q_k,(q_k1,..,q_kl_k),posk)) // posi=(i,j) position of the component // the list of segments to be added to the holes static proc addpart(list H, list C) { list Q; int i; int j; int k; int l; int t; int t1; Q=H; intvec notQ; list QQ; list addq; // @Q2=list of (i,j) positions of the components that have been aded to some hole of the maximal ideals // plus those of the components added to the holes. ideal q; i=1; while (i<=size(Q)) { if (memberpos(i,notQ)[1]==0) { q=Q[i]; t=1; j=1; while ((t) and (j<=size(C))) { if (equalideals(q,C[j][1])) { // \\ @Q2[size(@Q2)+1]=C[j][3]; t=0; for (k=1;k<=size(C[j][2]);k++) { t1=1; l=1; while((t1) and (l<=size(Q))) { if ((l!=i) and (memberpos(l,notQ)[1]==0)) { if (idcontains(C[j][2][k],Q[l])) { t1=0; } } l++; } if (t1) { addq[size(addq)+1]=C[j][2][k]; // \\ @Q2[size(@Q2)+1]=C[j][3]; } } if((size(notQ)==1) and (notQ[1]==0)){notQ[1]=i;} else {notQ[size(notQ)+1]=i;} } j++; } if (size(addq)>0) { for (k=1;k<=size(addq);k++) { Q[size(Q)+1]=addq[k]; } kill addq; list addq; } } i++; } for (i=1;i<=size(Q);i++) { if(memberpos(i,notQ)[1]==0) { QQ[size(QQ)+1]=Q[i]; } } if (size(QQ)==0){QQ[1]=ideal(1);} return(addpartfine(QQ,C)); } // Auxiliary routine called by addpart to finish the modification of the holes of a primepart // of the union by the addition of the segments that do not correspond to // that part. // Works on @P ring. static proc addpartfine(list H, list C0) { //"T_H="; H; int i; int j; int k; int te; intvec notQ; int l; list sel; int used; intvec jtesC; if ((size(H)==1) and (equalideals(H[1],ideal(1)))){return(H);} if (size(C0)==0){return(H);} list newQ; list nQ; list Q; list nQ1; list Q0; def Q1=H; //Q1=sortlistideals(Q1,idbefid); def C=C0; while(equallistideals(Q0,Q1)==0) { Q0=Q1; i=0; Q=Q1; kill notQ; intvec notQ; while(i1) { FF=precombint(LL); } for (k=1;k<=size(lpp);k++) { kill L; list L; for (j=1;j<=size(LCU);j++) { L[j]=list(LCU[j][2],LCU[j][1][k]); } if (size(LCU)>1) { B[k]=combine(L,FF); } else{B[k]=L[1][2];} } } else{B=BB;} for(j=1;j<=size(B);j++) { B[j]=pnormalf(B[j],crep[1],crep[2]); } S[i]=list(lpp,B,prep,crep,lpph); if(comment>=1) { lpi[size(lpi)+1]=string("[",i,"]"); lpi[size(lpi)+1]=S[i][1]; } } if(comment>=1) { string("Time in LCUnion + combine = ",timer-start); if(comment>=2){string("lpp=",lpi)}; } if(defined(@P)==1){kill @P; kill @RP; kill @R;} return(S); } // grobcov // input: // ideal F: a parametric ideal in Q[a][x], (a=parameters, x=variables). // list #: (options) list("null",N,"nonnull",W,"can",0-1,ext",0-1, "rep",0-1-2) // where // N is the null conditions ideal (if desired) // W is the ideal of non-null conditions (if desired) // The value of \"can\"i s 1 by default and can be set to 0 if we do not // need to obtain the canonical GC, but only a GC. // The value of \"ext\" is 0 by default and so the generic representation // of the bases is given. It can be set to 1, and then the full // representation of the bases is given. // The value of \"rep\" is 0 by default, and then the segments // are given in canonical P-representation. It can be set to 1 // and then they are given in canonical C-representation. // If it is set to 2, then both representations are given. // output: // list S: ((lpp,basis,(idp_1,(idp_11,..,idp_1s_1))), .. // (lpp,basis,(idp_r,(idp_r1,..,idp_rs_r))) ) where // each element of S corresponds to a lpp-segment // given by the lpp, the basis, and the P-representation of the segment proc grobcov(ideal F,list #) "USAGE: grobcov(F); This is the fundamental routine of the library. It computes the Groebner cover of a parametric ideal. See Montes A., Wibmer M., \"Groebner Bases for Polynomial Systems with parameters\". JSC 45 (2010) 1391-1425.) The Groebner Cover of a parametric ideal consist of a set of pairs(S_i,B_i), where the S_i are disjoint locally closed segments of the parameter space, and the B_i are the reduced Groebner bases of the ideal on every point of S_i. The ideal F must be defined on a parametric ring Q[a][x]. (a=parameters, x=variables) Options: To modify the default options, pair of arguments -option name, value- of valid options must be added to the call. Options: \"null\",ideal E: The default is (\"null\",ideal(0)). \"nonnull\",ideal N: The default is (\"nonnull\",ideal(1)). When options \"null\" and/or \"nonnull\" are given, then the parameter space is restricted to V(E) \ V(N). \"can\",0-1: The default is (\"can\",1). With the default option the homogenized ideal is computed before obtaining the Groebner Cover, so that the result is the canonical Groebner Cover. Setting (\"can\",0) only homogenizes the basis so the result is not exactly canonical, but the computation is shorter. \"ext\",0-1: The default is (\"ext\",0). With the default (\"ext\",0), only the generic representation of the bases is computed (single polynomials, but not specializing to non-zero for every point of the segment. With option (\"ext\",1) the full representation of the bases is computed (possible sheaves) and sometimes a simpler result is obtained, but the computation is more time consuming. \"rep\",0-1-2: The default is (\"rep\",0) and then the segments are given in canonical P-representation. Option (\"rep\",1) represents the segments in canonical C-representation, and option (\"rep\",2) gives both representations. \"comment\",0-3: The default is (\"comment\",0). Setting \"comment\" higher will provide information about the development of the computation. One can give none or whatever of these options. RETURN: The list ( (lpp_1,basis_1,segment_1,lpph_1), ... (lpp_s,basis_s,segment_s,lpph_s) ) The lpp are constant over a segment and correspond to the set of lpp of the reduced Groebner basis for each point of the segment. The lpph corresponds to the lpp of the homogenized ideal and is different for each segment. It is given as a string, and shown only for information. With the default option \"can\",1, the segments have different lpph. Basis: to each element of lpp corresponds an I-regular function given in full representation (by option (\"ext\",1)) or in generic representation (default option (\"ext\",0)). The I-regular function is the corresponding element of the reduced Groebner basis for each point of the segment with the given lpp. For each point in the segment, the polynomial or the set of polynomials representing it, if they do not specialize to 0, then after normalization, specializes to the corresponding element of the reduced Groebner basis. In the full representation at least one of the polynomials representing the I-regular function specializes to non-zero. With the default option (\"rep\",0) the representation of the segment is the P-representation. With option (\"rep\",1) the representation of the segment is the C-representation. With option (\"rep\",2) both representations of the segment are given. The P-representation of a segment is of the form ((p_1,(p_11,..,p_1k1)),..,(p_r,(p_r1,..,p_rkr)) representing the segment Union_i ( V(p_i) \ ( Union_j V(p_ij) ) ), where the p's are prime ideals. The C-representation of a segment is of the form (E,N) representing V(E) \ V(N), and the ideals E and N are radical and N contains E. NOTE: The basering R, must be of the form Q[a][x], (a=parameters, x=variables), and should be defined previously. The ideal must be defined on R. KEYWORDS: Groebner cover, parametric ideal, canonical, discussion of parametric ideal. EXAMPLE: grobcov; shows an example" { list S; int i; int ish=1; list GBR; list BR; int j; int k; ideal idp; ideal idq; int s; ideal ext; list SS; ideal E; ideal N; int canop; int extop; int repop; int comment=0; int m; def RR=basering; setglobalrings(); list L0=#; int out=0; L0[size(L0)+1]="res"; L0[size(L0)+1]=ideal(1); // default options int start=timer; E=ideal(0); N=ideal(1); canop=1; // canop=0 for homogenizing the basis but not the ideal (not canonical) // canop=1 for working with the homogenized ideal repop=0; // repop=0 for representing the segments in Prep // repop=1 for representing the segments in Crep // repop=2 for representing the segments in Prep and Crep extop=0; // extop=0 if only generic representation of the bases are to be computed // extop=1 if the full representation of the bases are to be computed for(i=1;i<=size(L0) div 2;i++) { if(L0[2*i-1]=="can"){canop=L0[2*i];} else { if(L0[2*i-1]=="ext"){extop=L0[2*i];} else { if(L0[2*i-1]=="rep"){repop=L0[2*i];} else { if(L0[2*i-1]=="null"){E=L0[2*i];} else { if(L0[2*i-1]=="nonnull"){N=L0[2*i];} else { if (L0[2*i-1]=="comment"){comment=L0[2*i];} } } } } } } if(not((canop==0) or (canop==1))) { string("Option can = ",canop," is not supported. It is changed to can = 1"); canop=1; } for(i=1;i<=size(L0) div 2;i++) { if(L0[2*i-1]=="can"){L0[2*i]=canop;} } if ((printlevel) and (comment==0)){comment=printlevel;} list LL; LL[1]="can"; LL[2]=canop; LL[3]="comment"; LL[4]=comment; LL[5]="out"; LL[6]=0; LL[7]="null"; LL[8]=E; LL[9]="nonnull"; LL[10]=N; LL[11]="ext"; LL[12]=extop; LL[13]="rep"; LL[14]=repop; if (comment>=1) { string("Begin grobcov with options: ",LL); } kill S; def S=gcover(F,LL); // NOW extend if(extop) { S=extend(S,LL); } else { // NOW representation of the segments by option repop list Si; list nS; if(repop==0) { for(i=1;i<=size(S);i++) { Si=list(S[i][1],S[i][2],S[i][3],S[i][5]); nS[size(nS)+1]=Si; } kill S; def S=nS; } else { if(repop==1) { for(i=1;i<=size(S);i++) { Si=list(S[i][1],S[i][2],S[i][4],S[i][5]); nS[size(nS)+1]=Si; } kill S; def S=nS; } else { for(i=1;i<=size(S);i++) { Si=list(S[i][1],S[i][2],S[i][3],S[i][4],S[i][5]); nS[size(nS)+1]=Si; } kill S; def S=nS; } } } if (comment>=1) { string("Time in grobcov = ", timer-start); string("Number of segments of grobcov = ", size(S)); } if(defined(@P)==1){kill @R; kill @P; kill @RP;} return(S); } example { "EXAMPLE:"; echo = 2; // Casas conjecture for degree 4: ring R=(0,a0,a1,a2,a3,a4),(x1,x2,x3),dp; short=0; ideal F=x1^4+(4*a3)*x1^3+(6*a2)*x1^2+(4*a1)*x1+(a0), x1^3+(3*a3)*x1^2+(3*a2)*x1+(a1), x2^4+(4*a3)*x2^3+(6*a2)*x2^2+(4*a1)*x2+(a0), x2^2+(2*a3)*x2+(a2), x3^4+(4*a3)*x3^3+(6*a2)*x3^2+(4*a1)*x3+(a0), x3+(a3); grobcov(F); } // Input. GC the grobcov of an ideal in generic representation of the // bases computed with option option ("rep",2). // Output The grobcov in full representation. // Option ("comment",1) shows the time. // Can be called from the top proc extend(list GC, list #); "USAGE: extend(GC); The default option of grobcov provides the bases in generic representation (the I-regular functions of the bases ara given by a single polynomial. It can specialize to zero for some points of the segments, but in general, it is sufficient for many pouposes. Nevertheless the I-regular functions allow a full representation given bey a set of polynomials specializing to the value of the function (after normalization) or to zero, but at least one of the polynomials specializes to non-zero. The full representation can be obtained by computing the grobcov with option \"ext\",1. The default option is \"ext\",0. With option \"ext\",1 the computation can be much more time consuming, even if the result can be simpler. Alternatively, one can compute the full representation of the bases after computing grobcov with the defaoult option \"ext\",0 and the option \"rep\",2, that outputs both the Prep and the Crep of the segments and then call \"extend\" to the output. RETURN: When calling extend(grobcov(S,\"rep\",2)) the result is of the form ( (lpp_1,basis_1,segment_1,lpph_1), ... (lpp_s,basis_s,segment_s,lpph_s) ) where each function of the basis can be given by an ideal of representants. NOTE: The basering R, must be of the form Q[a][x], (a=parameters, x=variables), and should be defined previously. The ideal must be defined on R. KEYWORDS: Groebner cover, parametric ideal, canonical, discussion of parametric ideal, full representation. EXAMPLE: extend; shows an example" { list L=#; list S=GC; ideal idp; ideal idq; int i; int j; int m; int s; m=0; i=1; while((i<=size(S)) and (m==0)) { if(typeof(S[i][2])=="list"){m=1;} i++; } if(m==1){"Warning! grobcov has already extended bases"; return(S);} if(size(GC[1])!=5){"Warning! extend make sense only when grobcov has been called with options 'rep',2,'ext',0"; " "; return();} int repop=0; int start3=timer; int comment; for(i=1;i<=size(L) div 2;i++) { if(L[2*i-1]=="comment"){comment=L[2*i];} else { if(L[2*i-1]=="rep"){repop=L[2*i];} } } poly leadc; poly ext; int te=0; list SS; def R=basering; if (defined(@R)){te=1;} else{setglobalrings();} // Now extend for (i=1;i<=size(S);i++) { m=size(S[i][2]); for (j=1;j<=m;j++) { idp=S[i][4][1]; idq=S[i][4][2]; if (size(idp)>0) { leadc=leadcoef(S[i][2][j]); kill ext; def ext=extend0(S[i][2][j],idp,idq); if (typeof(ext)=="poly") { S[i][2][j]=pnormalf(ext,idp,idq); } else { if(size(ext)==1) { S[i][2][j]=ext[1]; } else { kill SS; list SS; for(s=1;s<=size(ext);s++) { ext[s]=pnormalf(ext[s],idp,idq); } for(s=1;s<=size(S[i][2]);s++) { if(s!=j){SS[s]=S[i][2][s];} else{SS[s]=ext;} } S[i][2]=SS; } } } } } // NOW representation of the segments by option repop list Si; list nS; if (repop==0) { for(i=1;i<=size(S);i++) { Si=list(S[i][1],S[i][2],S[i][3],S[i][5]); nS[size(nS)+1]=Si; } S=nS; } else { if (repop==1) { for(i=1;i<=size(S);i++) { Si=list(S[i][1],S[i][2],S[i][4],S[i][5]); nS[size(nS)+1]=Si; } S=nS; } else { for(i=1;i<=size(S);i++) { Si=list(S[i][1],S[i][2],S[i][3],S[i][4],S[i][5]); nS[size(nS)+1]=Si; } } } if(comment>=1){string("Time in extend = ",timer-start3);} if(te==0){kill @R; kill @RP; kill @P;} return(S); } example { "EXAMPLE:"; echo = 2; ring R=(0,a0,b0,c0,a1,b1,c1),(x), dp; short=0; ideal S=a0*x^2+b0*x+c0, a1*x^2+b1*x+c1; def GCS=grobcov(S,"rep",2); GCS; def FGC=extend(GCS,"rep",0); // Full representation= FGC; } // Auxiliary routine // nonzerodivisor // input: // poly g in Q[a], // list P=(p_1,..p_r) representing a minimal prime decomposition // output // poly f such that f notin p_i for all i and // g-f in p_i for all i such that g notin p_i static proc nonzerodivisor(poly gr, list Pr) { def RR=basering; setring(@P); def g=imap(RR,gr); def P=imap(RR,Pr); int i; int k; list J; ideal F; def f=g; ideal Pi; for (i=1;i<=size(P);i++) { option(redSB); Pi=std(P[i]); //attrib(Pi,"isSB",1); if (reduce(g,Pi,1)==0){J[size(J)+1]=i;} } for (i=1;i<=size(J);i++) { F=ideal(1); for (k=1;k<=size(P);k++) { if (k!=J[i]) { F=idint(F,P[k]); } } f=f+F[1]; } setring(RR); def fr=imap(@P,f); return(fr); } // Auxiliary routine // deltai // input: // int i: // list LPr: (p1,..,pr) of prime components of an ideal in Q[a] // output: // list (fr,fnr) of two polynomials that are equal on V(pi) // and fr=0 on V(P) \ V(pi), and fnr is nonzero on V(pj) for all j. static proc deltai(int i, list LPr) { def RR=basering; setring(@P); def LP=imap(RR,LPr); int j; poly p; def F=ideal(1); poly f; poly fn; ideal LPi; for (j=1;j<=size(LP);j++) { if (j!=i) { F=idint(F,LP[j]); } } p=0; j=1; while ((p==0) and (j<=size(F))) { LPi=LP[i]; attrib(LPi,"isSB",1); p=reduce(F[j],LPi); j++; } f=F[j-1]; fn=nonzerodivisor(f,LP); setring(RR); def fr=imap(@P,f); def fnr=imap(@P,fn); return(list(fr,fnr)); } // Auxiliary routine // combine // input: a list of pairs ((p1,P1),..,(pr,Pr)) where // ideal pi is a prime component // poly Pi is the polynomial in Q[a][x] on V(pi)\ V(Mi) // (p1,..,pr) are the prime decomposition of the lpp-segment // list crep =(ideal ida,ideal idb): the Crep of the segment. // list Pci of the intersecctions of all pj except the ith one // output: // poly P on an open and dense set of V(p_1 int ... p_r) static proc combine(list L, ideal F) { // ATTENTION REVISE AND USE Pci and F int i; poly f; f=0; for(i=1;i<=size(L);i++) { f=f+F[i]*L[i][2]; } // f=elimconstfac(f); f=primepartZ(f); return(f); } //Auxiliary routine // nullin // input: // poly f: a polynomial in Q[a] // ideal P: an ideal in Q[a] // called from ring @R // output: // t: with value 1 if f reduces modulo P, 0 if not. static proc nullin(poly f,ideal P) { int t; def RR=basering; setring(@P); def f0=imap(RR,f); def P0=imap(RR,P); attrib(P0,"isSB",1); if (reduce(f0,P0,1)==0){t=1;} else{t=0;} setring(RR); return(t); } // Auxiliary routine // monoms // Input: A polynomial f // Output: The list of leading terms static proc monoms(poly f) { list L; poly lm; poly lc; poly lp; poly Q; poly mQ; def p=f; int i=1; while (p!=0) { lm=lead(p); p=p-lm; lc=leadcoef(lm); lp=leadmonom(lm); L[size(L)+1]=list(lc,lp); i++; } return(L); } // Auxiliary routine called by extend // extend0 // input: // poly f: a generic polynomial in the basis // ideal idp: such that ideal(S)=idp // ideal idq: such that S=V(idp) \ V(idq) //// NW the list of ((N1,W1),..,(Ns,Ws)) of red-rep of the grouped //// segments in the lpp-segment NO MORE USED // output: static proc extend0(poly f, ideal idp, ideal idq) { matrix CC; poly Q; list NewMonoms; int i; int j; poly fout; ideal idout; list L=monoms(f); int nummonoms=size(L)-1; Q=L[1][1]; if (nummonoms==0){return(f);} for (i=2;i<=size(L);i++) { CC=matrix(extendcoef(L[i][1],Q,idp,idq)); NewMonoms[i-1]=list(CC,L[i][2]); } if (nummonoms==1) { for(j=1;j<=ncols(NewMonoms[1][1]);j++) { fout=NewMonoms[1][1][2,j]*L[1][2]+NewMonoms[1][1][1,j]*NewMonoms[1][2]; //fout=pnormalf(fout,idp,W); if(ncols(NewMonoms[1][1])>1){idout[j]=fout;} } if(ncols(NewMonoms[1][1])==1){return(fout);} else{return(idout);} } else { list cfi; list coefs; for (i=1;i<=nummonoms;i++) { kill cfi; list cfi; for(j=1;j<=ncols(NewMonoms[i][1]);j++) { cfi[size(cfi)+1]=NewMonoms[i][1][2,j]; } coefs[i]=cfi; } def indexpolys=findindexpolys(coefs); for(i=1;i<=size(indexpolys);i++) { fout=L[1][2]; for(j=1;j<=nummonoms;j++) { fout=fout+(NewMonoms[j][1][1,indexpolys[i][j]])/(NewMonoms[j][1][2,indexpolys[i][j]])*NewMonoms[j][2]; } fout=cleardenom(fout); if(size(indexpolys)>1){idout[i]=fout;} } if (size(indexpolys)==1){return(fout);} else{return(idout);} } } // Auxiliary routine // findindexpolys // input: // list coefs=( (q11,..,q1r_1),..,(qs1,..,qsr_1) ) // of denominators of the monoms // output: // list ind=(v_1,..,v_t) of intvec // each intvec v=(i_1,..,is) corresponds to a polynomial in the sheaf // that will be built from it in extend procedure. static proc findindexpolys(list coefs) { int i; int j; intvec numdens; for(i=1;i<=size(coefs);i++) { numdens[i]=size(coefs[i]); } def RR=basering; setring(@P); def coefsp=imap(RR,coefs); ideal cof; list combpolys; intvec v; int te; list mp; for(i=1;i<=size(coefsp);i++) { cof=ideal(0); for(j=1;j<=size(coefsp[i]);j++) { cof[j]=factorize(coefsp[i][j],3); } coefsp[i]=cof; } for(j=1;j<=size(coefsp[1]);j++) { v[1]=j; te=1; for (i=2;i<=size(coefsp);i++) { mp=memberpos(coefsp[1][j],coefsp[i]); if(mp[1]) { v[i]=mp[2]; } else{v[i]=0;} } combpolys[j]=v; } combpolys=reform(combpolys,numdens); setring(RR); return(combpolys); } // Auxiliary routine // extendcoef: given Q,P in Q[a] where P/Q specializes on an open and dense subset // of the whole V(p1 int...int pr), it returns a basis of the module // of all syzygies equivalent to P/Q, static proc extendcoef(poly P, poly Q, ideal idp, ideal idq) { def RR=basering; setring(@P); def PL=ringlist(@P); PL[3][1][1]="dp"; def P1=ring(PL); setring(P1); ideal idp0=imap(RR,idp); option(redSB); qring q=std(idp0); poly P0=imap(RR,P); poly Q0=imap(RR,Q); ideal PQ=Q0,-P0; module C=syz(PQ); setring(@P); def idp1=imap(RR,idp); def idq1=imap(RR,idq); def C1=matrix(imap(q,C)); def redC=selectregularfun(C1,idp1,idq1); setring(RR); def CC=imap(@P,redC); return(CC); } // Auxiliary routine // selectregularfun // input: // list L of the polynomials matrix CC // (we assume that one of them is non-null on V(N) \ V(M)) // ideal N, ideal M: ideals representing the locally closed set V(N) \ V(M) // assume to work in @P static proc selectregularfun(matrix CC, ideal NN, ideal MM) { int numcombused; def RR=basering; setring(@P); def C=imap(RR,CC); def N=imap(RR,NN); def M=imap(RR,MM); if (ncols(C)==1){return(C);} int i; int j; int k; list c; intvec ci; intvec c0; intvec c1; list T; list T0; list T1; list LL; ideal N1;ideal M1; int te=0; for(i=1;i<=ncols(C);i++) { if((C[1,i]!=0) and (C[2,i]!=0)) { if(c0==intvec(0)){c0[1]=i;} else{c0[size(c0)+1]=i;} } } def C1=submat(C,1..2,c0); for (i=1;i<=ncols(C1);i++) { c=comb(ncols(C1),i); for(j=1;j<=size(c);j++) { ci=c[j]; numcombused++; if(i==1){N1=N+C1[2,j]; M1=M;} if(i>1) { kill c0; intvec c0 ; kill c1; intvec c1; c1=ci[size(ci)]; for(k=1;k0) { if(notfree[1]==0){notfree[1]=combpolys[j][i];} else{notfree[size(notfree)+1]=combpolys[j][i];} } } kill free1; intvec free1; for(j=1;j<=numdens[i];j++) { if(memberpos(j,notfree)[1]==0) { if(free1[1]==0){free1[1]=j;} else{free1[size(free1)+1]=j;} } free[i]=free1; } } list amplcombp; list aux; for(i=1;i<=size(combp0);i++) { v=combp0[i]; kill amplcombp; list amplcombp; amplcombp[1]=intvec(v[1]); for(j=2;j<=size(v);j++) { if(v[j]!=0) { for(k=1;k<=size(amplcombp);k++) { w=amplcombp[k]; w[size(w)+1]=v[j]; amplcombp[k]=w; } } else { kill aux; list aux; for(k=1;k<=size(amplcombp);k++) { for(l=1;l<=size(free[j]);l++) { w=amplcombp[k]; w[size(w)+1]=free[j][l]; aux[size(aux)+1]=w; } } amplcombp=aux; } } for(j=1;j<=size(amplcombp);j++) { combp1[size(combp1)+1]=amplcombp[j]; } } return(combp1); } // Auxiliary routine // precombint // input: L: list of ideals (works in @P) // output: F0: ideal of polys. F0[i] is a poly in the intersection of // all ideals in L except in the ith one, where it is not. // L=(p1,..,ps); F0=(f1,..,fs); // F0[i] \in intersect_{j#i} p_i static proc precombint(list L) { int i; int j; int tes; def RR=basering; setring(@P); list L0; list L1; list L2; list L3; ideal F; L0=imap(RR,L); L1[1]=L0[1]; L2[1]=L0[size(L0)]; for (i=2;i<=size(L0)-1;i++) { L1[i]=intersect(L1[i-1],L0[i]); L2[i]=intersect(L2[i-1],L0[size(L0)-i+1]); } L3[1]=L2[size(L2)]; for (i=2;i<=size(L0)-1;i++) { L3[i]=intersect(L1[i-1],L2[size(L0)-i]); } L3[size(L0)]=L1[size(L1)]; for (i=1;i<=size(L3);i++) { option(redSB); L3[i]=std(L3[i]); } for (i=1;i<=size(L3);i++) { tes=1; j=0; while((tes) and (j0) { for (i=1;i<=size(L) div 2;i++) { if (L[2*i-1]=="null"){E=L[2*i];} else { if (L[2*i-1]=="nonnull"){N=L[2*i];} else { if (L[2*i-1]=="comment"){comment=L[2*i];} else { if (L[2*i-1]=="out"){out=L[2*i];} } } } } } if (comment>0){string("Begin KSW with null = ",E," nonnull = ",N);} def CG=KSW0(F,E,N,comment); if (comment>0) { string("Number of segments in KSW (total) = ",size(CG)); string("Time in KSW = ",timer-start); } if(out==0) { CG=KSWtocgsdr(CG); CG=groupKSWsegments(CG); if (comment>0) { string("Number of lpp segments = ",size(CG)); string("Time in KSW + group + Prep = ",timer-start); } } if(defined(@P)){kill @P; kill @R; kill @RP;} return(CG); } // Auxiliary routine // sqf // This is for releases of Singular before 3-5-1 // proc sqf(poly f) // { // def RR=basering; // setring(@P); // def ff=imap(RR,f); // def G=sqrfree(ff); // poly fff=1; // int i; // for (i=1;i<=size(G);i++) // { // fff=fff*G[i]; // } // setring(RR); // def ffff=imap(@P,fff); // return(ffff); // } // Auxiliary routine // sqf static proc sqf(poly f) { def RR=basering; setring(@P); def ff=imap(RR,f); poly fff=sqrfree(ff,3); setring(RR); def ffff=imap(@P,fff); return(ffff); } // Auxiliary routine // KSW0: Kapur-Sun-Wang algorithm for computing a CGS, called by KSW // Input: // F: parametric ideal to be discussed // Options: // The ideal must be defined on C[parameters][variables] // Output: static proc KSW0(ideal F, ideal E, ideal N, int comment) { def R=basering; int i; int j; list emp; list CGS; ideal N0; for (i=1;i<=size(N);i++) { N0[i]=sqf(N[i]); } ideal E0; for (i=1;i<=size(E);i++) { E0[i]=sqf(leadcoef(E[i])); } setring(@P); ideal E1=imap(R,E0); E1=std(E1); ideal N1=imap(R,N0); N1=std(N1); setring(R); E0=imap(@P,E1); N0=imap(@P,N1); if (inconsistent(E0,N0)==1) { return(emp); } setring(@RP); def FRP=imap(R,F); def ERP=imap(R,E); FRP=FRP+ERP; option(redSB); def GRP=std(FRP); setring(R); def G=imap(@RP,GRP); if (memberpos(1,G)[1]==1) { if(comment>1){"Basis 1 is found"; E; N;} list KK; KK[1]=list(E0,N0,ideal(1)); return(KK); } ideal Gr; ideal Gm; ideal GM; for (i=1;i<=size(G);i++) { if (variables(G[i])[1]==0){Gr[size(Gr)+1]=G[i];} else{Gm[size(Gm)+1]=G[i];} } ideal Gr0; for (i=1;i<=size(Gr);i++) { Gr0[i]=sqf(Gr[i]); } Gr=elimrepeated(Gr0); ideal GrN; for (i=1;i<=size(Gr);i++) { for (j=1;j<=size(N0);j++) { GrN[size(GrN)+1]=sqf(Gr[i]*N0[j]); } } if (inconsistent(E,GrN)){;} else { if(comment>1){"Basis 1 is found in a branch with arguments"; E; GrN;} CGS[size(CGS)+1]=list(E,GrN,ideal(1)); } if (inconsistent(Gr,N0)){return(CGS);} GM=Gm; Gm=MDBasis(Gm); ideal H; for (i=1;i<=size(Gm);i++) { H[i]=sqf(leadcoef(Gm[i])); } H=facvar(H); poly h=sqf(LCMLC(H)); if(comment>1){"H = "; H; "h = "; h;} ideal Nh=N0; if(size(N0)==0){Nh=h;} else { for (i=1;i<=size(N0);i++) { Nh[i]=sqf(N0[i]*h); } } if (inconsistent(Gr,Nh)){;} else { CGS[size(CGS)+1]=list(Gr,Nh,Gm); } poly hc=1; list KS; ideal GrHi; for (i=1;i<=size(H);i++) { kill GrHi; ideal GrHi; Nh=N0; if (i>1){hc=sqf(hc*H[i-1]);} for (j=1;j<=size(N0);j++){Nh[j]=sqf(N0[j]*hc);} if (equalideals(Gr,ideal(0))==1){GrHi=H[i];} else {GrHi=Gr,H[i];} // else {for (j=1;j<=size(Gr);j++){GrHi[size(GrHi)+1]=Gr[j]*H[i];}} if(comment>1){"Call to KSW with arguments "; GM; GrHi; Nh;} KS=KSW0(GM,GrHi,Nh,comment); for (j=1;j<=size(KS);j++) { CGS[size(CGS)+1]=KS[j]; } if(comment>1){"CGS after KSW = "; CGS;} } return(CGS); } // Auxiliary routine // KSWtocgsdr static proc KSWtocgsdr(list L) { int i; list CG; ideal B; ideal lpp; int j; list NKrep; for(i=1;i<=size(L);i++) { B=redgbn(L[i][3],L[i][1],L[i][2]); lpp=ideal(0); for(j=1;j<=size(B);j++) { lpp[j]=leadmonom(B[j]); } NKrep=KtoPrep(L[i][1],L[i][2]); CG[i]=list(lpp,B,NKrep); } return(CG); } // Auxiliary routine // KtoPrep // Computes the P-representaion of a K-representation (N,W) of a set // input: // ideal E (null conditions) // ideal N (non-null conditions ideal) // output: // the ((p_1,(p_11,..,p_1k_1)),..,(p_r,(p_r1,..,p_rk_r))); // the Prep of V(N) \ V(W) static proc KtoPrep(ideal N, ideal W) { int i; int j; if (N[1]==1) { L0[1]=list(ideal(1),list(ideal(1))); return(L0); } def RR=basering; setring(@P); ideal B; int te; poly f; ideal Np=imap(RR,N); ideal Wp=imap(RR,W); list L; list L0; list T0; L0=minGTZ(Np); for(j=1;j<=size(L0);j++) { option(redSB); L0[j]=std(L0[j]); } for(i=1;i<=size(L0);i++) { if(inconsistent(L0[i],Wp)==0) { B=L0[i]+Wp; T0=minGTZ(B); option(redSB); for(j=1;j<=size(T0);j++) { T0[j]=std(T0[j]); } L[size(L)+1]=list(L0[i],T0); } } setring(RR); def LL=imap(@P,L); return(LL); } // Auxiliary routine // groupKSWsegments // input: the list of vertices of KSW // output: the same terminal vertices grouped by lpp static proc groupKSWsegments(list T) { int i; int j; list L; list lpp; list lppor; list kk; lpp[1]=T[1][1]; j=1; lppor[1]=intvec(1); for(i=2;i<=size(T);i++) { kk=memberpos(T[i][1],lpp); if(kk[1]==0){j++; lpp[j]=T[i][1]; lppor[j]=intvec(i);} else{lppor[kk[2]][size(lppor[kk[2]])+1]=i;} } list ll; for (j=1;j<=size(lpp);j++) { kill ll; list ll; for(i=1;i<=size(lppor[j]);i++) { ll[size(ll)+1]=list(i,T[lppor[j][i]][2],T[lppor[j][i]][3]); } L[j]=list(lpp[j],ll,string(lpp[j])); } return(L); } //********************* End KapurSunWang ************************* //********************* Begin ConsLevels *************************** static proc zeroone(int n) { list L; list L2; intvec e; intvec e2; intvec e3; int j; if(n==1) { e[1]=0; L[1]=e; e[1]=1; L[2]=e; return(L); } if(n>1) { L=zeroone(n-1); for(j=1;j<=size(L);j++) { e2=L[j]; e3=e2; e3[size(e3)+1]=0; L2[size(L2)+1]=e3; e3=e2; e3[size(e3)+1]=1; L2[size(L2)+1]=e3; } } return(L2); } // Auxiliary routine // subsets: the list of subsets of (1,..n) static proc subsets(int n) { list L; list L1; int i; int j; L=zeroone(n); intvec e; intvec e1; for(i=1;i<=size(L);i++) { e=L[i]; kill e1; intvec e1; for(j=1;j<=n;j++) { if(e[n+1-j]==1) { if(e1==intvec(0)){e1[1]=j;} else{e1[size(e1)+1]=j}; } } L1[i]=e1; } return(L1); } // Input a list A of locally closed sets in C-rep // Output a list B of a simplified list of A static proc SimplifyUnion(list A) { int i; int j; list L=A; int n=size(L); if(n<2){return(A);} for(i=1;i<=size(L);i++) { for(j=1;j<=size(L);j++) { if(i != j) { if(equalideals(L[i][2],L[j][1])==1) { L[i][2]=L[j][2]; } } } } ideal T=ideal(1); intvec v; for(i=1;i<=size(L);i++) { if(equalideals(L[i][2],ideal(1))) { v[size(v)+1]=i; T=intersect(T,L[i][1]); } } if(size(v)>0) { for(i=1; i<=size(v);i++) { j=v[size(v)+1-i]; L=elimfromlist(L, j); } } if(equalideals(T,ideal(1))==0){L[size(L)+1]=list(std(T),ideal(1))}; //string("T_n=",n," new n0",size(L)); return(L); } // Input: list(A) // A is a list of locally closed sets in Crep. A=[[P1,Q1],[P2,Q2],..,[Pr,Qr]] // whose union is a constructible set from // Output list [Lev,C]: // where Lev is the Crep of the canonical first level of A, and // C is the complement of the first level Lev wrt to the closure of A. The elements are given in Crep, static proc FirstLevel(list A) { int n=size(A); list T=zeroone(n); ideal P; ideal Q; list Cb; ideal Cc=ideal(1); int i; int j; intvec t; ideal Z=ideal(1); list C; for(i=1;i<=size(A);i++) { Z=intersect(Z,A[i][1]); } for(i=2; i<=size(T);i++) { t=T[i]; P=ideal(1); Q=ideal(0); for(j=1;j<=n;j++) { if(t[n+1-j]==1) { Q=Q+A[j][2]; } else { P=intersect(P,A[j][1]); } } //"T_Q="; Q; "T_P="; P; Cb=Crep(Q,P); //"T_Cb="; Cb; if(Cb[1][1]<>1) { C[size(C)+1]=Cb; Cc=intersect(Cc,Cb[1]); } } list Lev=list(Z,Cc); //Crep(Z,Cc); if(size(C)>1){C=SimplifyUnion(C);} return(list(Lev,C)); } // Input: list(A) // A is a list of locally closed sets in Crep. A=[[P1,Q1],[P2,Q2],..,[Pr,Qr]] // whose union is a constructible set from which the algorithm computes its canonical form. // Output: // list [L,C] where // where L is the list of canonical levels of A, // and C is the list of canonical levels of the complement of A wrt to the closure of A. // All locally closed sets are given in Crep. // L=[[1,[p1,p2],[3,[p3,p4],..,[2r-1,[p_{2r-1},p_2r]]]] is the list of levels of A in Crep. // C=[[2,p2,p3],[4,[p4,p5],..,[2s,[p_{2s},p_{2s+1}]]] is the list of levels of C, // the complement of S wrt the closure of A, in Crep. proc ConsLevels(list A) "USAGE: ConsLevels(A); A is a list of locally closed sets in Crep. A=[[P1,Q1],[P2,Q2],..,[Pr,Qr]] whose union is a constructible set from which the algorithm computes its canonical form. RETURN: A list with two elements: [L,C] where L is the list of canonical levels of A, and C is the list of canonical levels of the complement of A wrt to the closure of A. All locally closed sets are given in Crep. L=[[1,[p1,p2],[3,[p3,p4],..,[2r-1,[p_{2r-1},p_2r]]]] C=[[2,p2,p3],[4,[p4,p5],..,[2s,[p_{2s},p_{2s+1}]]] NOTE: The basering R, must be of the form Q[a] KEYWORDS: locally closed set, constructible set EXAMPLE: ConsLevels; shows an example" { list L; list C; int i; list B; list T; for(i=1; i<=size(A);i++) { T=Crep(A[i][1],A[i][2]); B[size(B)+1]=T; } int level=0; list K; while(size(B)>0) { level++; K=FirstLevel(B); if(level mod 2==1){L[size(L)+1]=list(level,K[1]);} else{C[size(C)+1]=list(level,K[1]);} //"T_L="; L; //"T_C="; C; B=K[2]; //"T_size(B)="; size(B); } return(list(L,C)); } example { "EXAMPLE:"; echo = 2; // Example of ConsLevels with nice geometrical interpretetion and 2 levels if (defined(R)){kill R;} if (defined(@P)){kill @P; kill @R; kill @RP;} ring R=0,(x,y,z),lp; short=0; ideal P1=x*(x^2+y^2+z^2-1); ideal Q1=z,x^2+y^2-1; ideal P2=y,x^2+z^2-1; ideal Q2=z*(z+1),y,x*(x+1); list Cr1=Crep(P1,Q1); list Cr2=Crep(P2,Q2); list L=list(Cr1,Cr2); L; // ConsLevels(L)= ConsLevels(L); //---------------------------------------------------------------------- // Begin Problem S93 // Automatic theorem proving // Generalized Steiner-Lehmus Theorem // A.Montes, T.Recio // Bisector of A(-1,0) = Bisector of B(1,0) varying C(a,b) if(defined(R1)){kill R1;} ring R1=(0,a,b),(x1,y1,x2,y2,p,r),dp; ideal S93=(a+1)^2+b^2-(p+1)^2, (a-1)^2+b^2-(1-r)^2, a*y1-b*x1-y1+b, a*y2-b*x2+y2-b, -2*y1+b*x1-(a+p)*y1+b, 2*y2+b*x2-(a+r)*y2-b, (x1+1)^2+y1^2-(x2-1)^2-y2^2; short=0; def GC93=grobcov(S93,"nonnull",ideal(b),"rep",1); //"grobcov(S93,'nonnull',ideal(b),"rep",1)="; GC93; list L0; for(int i=1;i<=size(GC93);i++) { L0[size(L0)+1]=GC93[i][3]; } def GC93ab=grobcov(S93,"nonnull",ideal(a*b),"rep",1); ring RR=0,(a,b),lp; list L1; L1=imap(R1,L0); // L1=Total elements of the grobcov(S93,'nonnull',ideal(b),'rep',1) to be added= L1; // Adding all the elements of grobcov(S93,'nonnull',ideal(b),'rep',1)= ConsLevels(L1); } //**************************** End ConsLevels ****************** //******************** Begin locus ****************************** // indepparameters // Auxiliary routine to detect 'Special' components of the locus // Input: ideal B // Output: // 1 if the solutions of the ideal do not depend on the parameters // 0 if they depend static proc indepparameters(ideal B) { def R=basering; ideal v=variables(B); setring @RP; def BP=imap(R,B); def vp=imap(R,v); ideal varpar=variables(BP); int te; te=equalideals(vp,varpar); setring(R); if(te){return(1);} else{return(0);} } // dimP0: Auxiliary routine // if the dimension in @P of an ideal in the parameters has dimension 0 then it returns 0 // else it retuns 1 static proc dimP0(ideal N) { def R=basering; setring(@P); int te=1; def NP=imap(R,N); attrib(NP,"IsSB",1); int d=dim(std(NP)); if(d==0){te=0;} setring(R); return(te); } // Takes a list of intvec and sorts it and eliminates repeated elements. // Auxiliary routine static proc sortpairs(L) { def L1=sort(L); def L2=elimrepeated(L1[1]); return(L2); } // Eliminates the pairs of L1 that are also in L2. // Auxiliary routine static proc minuselements(list L1,list L2) { int i; list L3; for (i=1;i<=size(L1);i++) { if(not(memberpos(L1[i],L2)[1])){L3[size(L3)+1]=L1[i];} } return(L3); } // NorSing // Input: // ideal B: the basis of a component of the grobcov // ideal E: the top of the component (assumed to be of dimension > 0 (single equation) // ideal N: the holes of the component // Output: // int d: the dimension of B on the variables reduced by the holes. // if d>0 then the component is 'Normal' // if d==0 then the component is 'Singular' static proc NorSing(ideal B, ideal E, ideal N, list #) { int i; int j; int Fenv=0; int env; int dd; list DD=#; def RR=basering; int moverdim=2; int version=0; int nv=nvars(RR); if(nv<4){version=1;} int d; poly F; for(i=1;i<=(size(DD) div 2);i++) { if(DD[2*i-1]=="movdim"){moverdim=DD[2*i];} if(DD[2*i-1]=="version"){version=DD[2*i];} if(DD[2*i-1]=="family"){F=DD[2*i];} } if(F!=0){Fenv=1;} //"T_B="; B; "E="; E; "N="; N; list L0; if(dimP0(E)==0){L0=2,"Normal";} // 2 es fals pero ha de ser >0 encara que sigui 0 else { if(version==0) { //"T_B="; B; // Computing std(B+E,plex(x,y,x1,..xn)) one can detect if there is a first part // independent of parameters giving the variables with dimension 0 dd=indepparameters(B); if (dd==1){d=0; L0=d,string(B),determineF(B,F,E);} else{d=1; L0=2,"Normal";} } else { def RH=ringlist(RR); //"T_RH="; RH; def H=RH; H[1]=0; H[2]=RH[1][2]+RH[2]; int n=size(H[2]); intvec ll; for(i=1;i<=n;i++) { ll[i]=1; } H[3][1][1]="lp"; H[3][1][2]=ll; def RRH=ring(H); setring(RRH); ideal BH=imap(RR,B); ideal EH=imap(RR,E); ideal NH=imap(RR,N); if(Fenv==1){poly FH=imap(RR,F);} for(i=1;i<=size(EH);i++){BH[size(BH)+1]=EH[i];} BH=std(BH); // MOLT COSTOS!!! ideal G; ideal r; poly q; for(i=1;i<=size(BH);i++) { r=factorize(BH[i],1); q=1; for(j=1;j<=size(r);j++) { if((pdivi(r[j],NH)[1] != 0) or (equalideals(ideal(NH),ideal(1)))) { q=q*r[j]; } } if(q!=1){G[size(G)+1]=q;} } setring RR; def GG=imap(RRH,G); ideal GGG; if(defined(L0)){kill L0; list L0;} for(i=1;i<=size(GG);i++) { if(indepparameters(GG[i])){GGG[size(GGG)+1]=GG[i];} } GGG=std(GGG); ideal GLM; for(i=1;i<=size(GGG);i++) { GLM[i]=leadmonom(GGG[i]); } attrib(GLM,"IsSB",1); d=dim(std(GLM)); string antiim=string(GGG); L0=d,antiim; if(d==0) { //" ";string("Antiimage of Special component = ", GGG); if(Fenv==1) { L0[3]=determineF(GGG,F,E); } } else { L0[2]="Normal"; } } } return(L0); } static proc determineF(ideal A,poly F,ideal E) { int env; int i; def RR=basering; def RH=ringlist(RR); def H=RH; H[1]=0; H[2]=RH[1][2]+RH[2]; int n=size(H[2]); intvec ll; for(i=1;i<=n;i++) { ll[i]=1; } H[3][1][1]="lp"; H[3][1][2]=ll; def RRH=ring(H); //" ";string("Antiimage of Special component = ", GGG); setring(RRH); list LL; def AA=imap(RR,A); def FH=imap(RR,F); def EH=imap(RR,E); ideal M=std(AA+FH); def rh=reduce(EH,M); if(rh==0){env=1;} else{env=0;} setring RR; //L0[3]=env; return(env); } // DimPar // Auxilliary routine to NorSing determining the dimension of a parametric ideal // Does not use @P and define it directly because is assumes that // variables and parameters have been inverted static proc DimPar(ideal E) { def RRH=basering; def RHx=ringlist(RRH); def Prin=ring(RHx[1]); setring(Prin); def E2=std(imap(RRH,E)); def d=dim(E2); setring RRH; return(d); } // locus0(G): Private routine used by locus (the public routine), that // builds the diferent components. // input: The output G of the grobcov (in generic representation, which is the default option) // Options: The algorithm allows the following options ar pair of arguments: // "movdim", d : by default movdim is 2 but it can be set to other values // "version", v : There are two versions of the algorithm. ('version',1) is // a full algorithm that always distinguishes correctly between 'Normal' // and 'Special' components, whereas ('version',0) can decalre a component // as 'Normal' being really 'Special', but is more effective. By default ('version',1) // is used when the number of variables is less than 4 and 0 if not. // The user can force to use one or other version, but it is not recommended. // "system", ideal F: if the initial systrem is passed as an argument. This is actually not used. // "comments", c: by default it is 0, but it can be set to 1. // Usually locus problems have mover coordinates, variables and tracer coordinates. // The mover coordinates are to be placed as the last variables, and by default, // its number is 2. If one consider locus problems in higer dimensions, the number of // mover coordinates (placed as the last variables) is to be given as an option. // output: // list, the canonical P-representation of the Normal and Non-Normal locus: // The Normal locus has two kind of components: Normal and Special. // The Non-normal locus has two kind of components: Accumulation and Degenerate. // This routine is compemented by locus that calls it in order to eliminate problems // with degenerate points of the mover. // The output components are given as // ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k) // The components are given in canonical P-representation of the subset. // If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level // gives the depth of the component. static proc locus0(list GG, list #) { int te=0; int t1=1; int t2=1; int i; def R=basering; //if(defined(@P)==1){te=1; kill @P; kill @R; kill @RP; } //setglobalrings(); // Options list DD=#; int moverdim=nvars(R); int version=0; int nv=nvars(R); if(nv<4){version=1;} int comment=0; ideal Fm; poly F; for(i=1;i<=(size(DD) div 2);i++) { if(DD[2*i-1]=="movdim"){moverdim=DD[2*i];} if(DD[2*i-1]=="version"){version=DD[2*i];} if(DD[2*i-1]=="system"){Fm=DD[2*i];} if(DD[2*i-1]=="comment"){comment=DD[2*i];} if(DD[2*i-1]=="family"){F=DD[2*i];} } list HHH; if (GG[1][1][1]==1 and GG[1][2][1]==1 and GG[1][3][1][1][1]==0 and GG[1][3][1][2][1]==1){return(HHH);} list G1; list G2; def G=GG; list Q1; list Q2; int d; int j; int k; t1=1; for(i=1;i<=size(G);i++) { attrib(G[i][1],"IsSB",1); d=locusdim(G[i][2],moverdim); if(d==0){G1[size(G1)+1]=G[i];} else { if(d>0){G2[size(G2)+1]=G[i];} } } if(size(G1)==0){t1=0;} if(size(G2)==0){t2=0;} setring(@RP); if(t1) { list G1RP=imap(R,G1); } else {list G1RP;} list P1RP; ideal B; for(i=1;i<=size(G1RP);i++) { kill B; ideal B; for(k=1;k<=size(G1RP[i][3]);k++) { attrib(G1RP[i][3][k][1],"IsSB",1); G1RP[i][3][k][1]=std(G1RP[i][3][k][1]); for(j=1;j<=size(G1RP[i][2]);j++) { B[j]=reduce(G1RP[i][2][j],G1RP[i][3][k][1]); } P1RP[size(P1RP)+1]=list(G1RP[i][3][k][1],G1RP[i][3][k][2],B); } } setring(R); ideal h; if(t1) { def P1=imap(@RP,P1RP); for(i=1;i<=size(P1);i++) { for(j=1;j<=size(P1[i][3]);j++) { h=factorize(P1[i][3][j],1); P1[i][3][j]=h[1]; for(k=2;k<=size(h);k++) { P1[i][3][j]=P1[i][3][j]*h[k]; } } } } else{list P1;} ideal BB; int dd; list NS; for(i=1;i<=size(P1);i++) { NS=NorSing(P1[i][3],P1[i][1],P1[i][2][1],DD); dd=NS[1]; if(dd==0){P1[i][3]=NS;} //"Special"; else{P1[i][3]="Normal";} } list P2; for(i=1;i<=size(G2);i++) { for(k=1;k<=size(G2[i][3]);k++) { P2[size(P2)+1]=list(G2[i][3][k][1],G2[i][3][k][2]); } } list l; for(i=1;i<=size(P1);i++){Q1[i]=l; Q1[i][1]=P1[i];} P1=Q1; for(i=1;i<=size(P2);i++){Q2[i]=l; Q2[i][1]=P2[i];} P2=Q2; setring(@P); ideal J; if(t1==1) { def C1=imap(R,P1); def L1=AddLocus(C1); } else{list C1; list L1; kill P1; list P1;} if(t2==1) { def C2=imap(R,P2); def L2=AddLocus(C2); } else{list L2; list C2; kill P2; list P2;} for(i=1;i<=size(L2);i++) { J=std(L2[i][2]); d=dim(J); // AQUI if(d==0) { L2[i][4]=string("Accumulation",L2[i][4]); } else{L2[i][4]=string("Degenerate",L2[i][4]);} } list LN; if(t1==1) { for(i=1;i<=size(L1);i++){LN[size(LN)+1]=L1[i];} } if(t2==1) { for(i=1;i<=size(L2);i++){LN[size(LN)+1]=L2[i];} } setring(R); def L=imap(@P,LN); for(i=1;i<=size(L);i++){if(size(L[i][2])==0){L[i][2]=ideal(1);}} //if(te==0){kill @R; kill @RP; kill @P;} list LL; for(i=1;i<=size(L);i++) { if(typeof(L[i][4])=="list") {L[i][4][1]="Special";} l[1]=L[i][2]; l[2]=L[i][3]; l[3]=L[i][4]; l[4]=L[i][5]; L[i]=l; } return(L); } // locus(G): Special routine for determining the locus of points // of geometrical constructions. // input: The output G of the grobcov (in generic representation, which is the default option for grobcov) // output: // list, the canonical P-representation of the Normal and Non-Normal locus: // The Normal locus has two kind of components: Normal and Special. // The Non-normal locus has two kind of components: Accumulation and Degenerate. // Normal components: for each point in the component, // the number of solutions in the variables is finite, and // the solutions depend on the point in the component if the component is not 0-dimensional. // Special components: for each point in the component, // the number of solutions in the variables is finite, // the component is not 0-dimensional, but the solutions do not depend on the // values of the parameters in the component. // Accumlation points: are 0-dimensional components for which it exist // an infinite number of solutions. // Degenerate components: are components of dimension greater than 0 for which // for every point in the component there exist infinite solutions. // The output components are given as // ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k) // The components are given in canonical P-representation of the subset. // If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level // gives the depth of the component of the constructible set. proc locus(list GG, list #) "USAGE: locus(G) The input must be the grobcov of a parametrical ideal in Q[a][x], (a=parameters, x=variables). In fact a must be the tracer coordinates and x the mover coordinates and other auxiliary ones. Special routine for determining the locus of points of geometrical constructions. Given a parametric ideal J representing the system determining the locus of points (a) who verify certain properties, the call to locus on the output of grobcov( J ) determines the different classes of locus components, following the taxonomy defined in Abanades, Botana, Montes, Recio: \"An Algebraic Taxonomy for Locus Computation in Dynamic Geometry\". Computer-Aided Design 56 (2014) 22-33. The components can be Normal, Special, Accumulation, Degenerate. OPTIONS: The algorithm allows the following options as pair of arguments: \"movdim\", d : by default movdim is 2 but it can be set to other values, and represents the number of mever variables. they should be given as the last variables of the ring. \"version\", v : There are two versions of the algorithm. (\"version\",1) is a full algorithm that always distinguishes correctly between 'Normal' and 'Special' components, whereas \("version\",0) can decalre a component as 'Normal' being really 'Special', but is more effective. By default (\"version\",1) is used when the number of variables is less than 4 and 0 if not. The user can force to use one or other version, but it is not recommended. \"system\", ideal F: if the initial system is passed as an argument. This is actually not used. \"comments\", c: by default it is 0, but it can be set to 1. Usually locus problems have mover coordinates, variables and tracer coordinates. The mover coordinates are to be placed as the last variables, and by default, its number is 2. If one consider locus problems in higer dimensions, the number of mover coordinates (placed as the last variables) is to be given as an option. RETURN: The locus. The output is a list of the components ( C_1,.. C_n ) where C_i = (p_i,(p_i1,..p_is_i), type_i,l evel_i ) and type_i can be 'Normal', 'Special', Accumulation', 'Degenerate'. The 'Special' components return more information, namely the antiimage of the component, that is 0-dimensional for these kind of components. Normal components: for each point in the component, the number of solutions in the variables is finite, and the solutions depend on the point in the component. Special components: for each point in the component, the number of solutions in the variables is finite. The antiimage of the component is 0-dimensional. Accumlation points: are 0-dimensional components whose antiimage is not zero-dimansional. Degenerate components: are components of dimension greater than 0 whose antiimage is not-zero-diemansional. The components are given in canonical P-representation. The levels of a class of locus are 1, because they represent locally closed. sets. NOTE: It can only be called after computing the grobcov of the parametrical ideal in generic representation ('ext',0), which is the default. The basering R, must be of the form Q[a_1,..,a_m][x_1,..,x_n]. KEYWORDS: geometrical locus, locus, loci. EXAMPLE: locus; shows an example" { int tes=0; int i; def R=basering; if(defined(@P)==1){tes=1; kill @P; kill @R; kill @RP;} setglobalrings(); // Options list DD=#; int moverdim=nvars(R); int version=0; int nv=nvars(R); if(nv<4){version=1;} int comment=0; ideal Fm; for(i=1;i<=(size(DD) div 2);i++) { if(DD[2*i-1]=="movdim"){moverdim=DD[2*i];} if(DD[2*i-1]=="version"){version=DD[2*i];} if(DD[2*i-1]=="system"){Fm=DD[2*i];} if(DD[2*i-1]=="comment"){comment=DD[2*i];} if(DD[2*i-1]=="family"){poly F=DD[2*i];} } int j; int k; def B0=GG[1][2]; def H0=GG[1][3][1][1]; if (equalideals(B0,ideal(1)) or (equalideals(H0,ideal(0))==0)) { return(locus0(GG,DD)); } else { int n=nvars(R); ideal vmov=var(n-1),var(n); ideal N; intvec xw; intvec yw; for(i=1;i<=n-1;i++){xw[i]=0;} xw[n]=1; for(i=1;i<=n;i++){yw[i]=0;} yw[n-1]=1; poly px; poly py; int te=1; i=1; while( te and i<=size(B0)) { if((deg(B0[i],xw)==1) and (deg(B0[i])==1)){px=B0[i]; te=0;} i++; } i=1; te=1; while( te and i<=size(B0)) { if((deg(B0[i],yw)==1) and (deg(B0[i])==1)){py=B0[i]; te=0;} i++; } N=px,py; te=indepparameters(N); if(te) { string("locus detected that the mover must avoid point (",N,") in order to obtain the correct locus"); // eliminates segments of GG where N is contained in the basis list nGP; def GP=GG; ideal BP; for(j=1;j<=size(GP);j++) { te=1; k=1; BP=GP[j][2]; while((te==1) and (k<=size(N))) { if(pdivi(N[k],BP)[1]!=0){te=0;} k++; } if(te==0){nGP[size(nGP)+1]=GP[j];} } } else{"Warning! Problem with more than one mover. Not able to solve it."; list L; return(L);} } def LL=locus0(nGP,DD); kill @RP; kill @P; kill @R; return(LL); } example { "EXAMPLE:"; echo = 2; ring R=(0,a,b),(x,y),dp; short=0; // Concoid ideal S96=x^2+y^2-4,(b-2)*x-a*y+2*a,(a-x)^2+(b-y)^2-1; // System S96= S96; locus(grobcov(S96)); kill R; // ******************************************** ring R=(0,a,b),(x4,x3,x2,x1),dp; short=0; ideal S=(x1-3)^2+(x2-1)^2-9, (4-x2)*(x3-3)+(x1-3)*(x4-1), (3-x1)*(x3-x1)+(4-x2)*(x4-x2), (4-x4)*a+(x3-3)*b+3*x4-4*x3, (a-x1)^2+(b-x2)^2-(x1-x3)^2-(x2-x4)^2; // System S= S; locus(grobcov(S)); kill R; //******************************************** ring R=(0,x,y),(x1,x2),dp; short=0; ideal S=-(x - 5)*(x1 - 1) - (x2 - 2)*(y - 2), (x1 - 5)^2 + (x2 - 2)^2 - 4, -2*(x - 5)*(x2 - 2) + 2*(x1 - 5)*(y - 2); // System S= S; locus(grobcov(S)); } // locusdg(G): Special routine for determining the locus of points // of geometrical constructions. Given a parametric ideal J with // parameters (a_1,..a_m) and variables (x_1,..,xn), // representing the system determining // the locus of points (a_1,..,a_m) who verify certain // properties, computing the grobcov G of // J and applying to it locus, determines the different // classes of locus components. The components can be // Normal, Special, Accumulation point, Degenerate. // The output are the components given in P-canonical form // of at most 4 constructible sets: Normal, Special, Accumulation, // Degenerate. // The description of the algorithm and definitions is // given in a forthcoming paper by Abanades, Botana, Montes, Recio. // Usually locus problems have mover coordinates, variables and tracer coordinates. // The mover coordinates are to be placed as the last variables, and by default, // its number is 2. If onw consider locus problems in higer dimensions, the number of // mover coordinates (placed as the last variables) is to be given as an option. // // input: The output of locus(G); // output: // list, the canonical P-representation of the Normal and Non-Normal locus: // The Normal locus has two kind of components: Normal and Special. // The Non-normal locus has two kind of components: Accumulation and Degenerate. // Normal components: for each point in the component, // the number of solutions in the variables is finite, and // the solutions depend on the point in the component if the component is not 0-dimensional. // Special components: for each point in the component, // the number of solutions in the variables is finite, // the component is not 0-dimensional, but the solutions do not depend on the // values of the parameters in the component. // Accumlation points: are 0-dimensional components for which it exist // an infinite number of solutions. // Degenerate components: are components of dimension greater than 0 for which // for every point in the component there exist infinite solutions. // The output components are given as // ((p1,(p11,..p1s_1),type_1,level_1),..,(pk,(pk1,..pks_k),type_k,level_k) // The components are given in canonical P-representation of the subset. // If all levels of a class of locus are 1, then the set is locally closed. Otherwise the level // gives the depth of the component of the constructible set. proc locusdg(list L) "USAGE: locusdg(L) The call must be locusdg(locus(grobcov(S))). RETURN: The output is the list of the 'Relevant' components of the locus in Dynamic Geometry:(C1,..,C:m), where C_i= ( p_i,(p_i1,..p_is_i), 'Relevant', level_i ) The 'Relevant' components are the 'Normal' and 'Accumulation' components of the locus. (See help for locus). NOTE: It can only be called after computing the locus. Calling sequence: locusdg(locus(grobcov(S))); KEYWORDS: geometrical locus, locus, loci, dynamic geometry EXAMPLE: locusdg; shows an example" { list LL; int i; for(i=1;i<=size(L);i++) { if(typeof(L[i][3])=="string") { if((L[i][3]=="Normal") or (L[i][3]=="Accumulation")){L[i][3]="Relevant"; LL[size(LL)+1]=L[i];} } } return(LL); } example { "EXAMPLE:"; echo = 2; ring R=(0,a,b),(x,y),dp; short=0; // Concoid ideal S96=x^2+y^2-4,(b-2)*x-a*y+2*a,(a-x)^2+(b-y)^2-1; // System S96= S96; locus(grobcov(S96)); locusdg(locus(grobcov(S96))); kill R; //******************************************** ring R=(0,a,b),(x4,x3,x2,x1),dp; ideal S=(x1-3)^2+(x2-1)^2-9, (4-x2)*(x3-3)+(x1-3)*(x4-1), (3-x1)*(x3-x1)+(4-x2)*(x4-x2), (4-x4)*a+(x3-3)*b+3*x4-4*x3, (a-x1)^2+(b-x2)^2-(x1-x3)^2-(x2-x4)^2; short=0; locus(grobcov(S)); locusdg(locus(grobcov(S))); kill R; //******************************************** ring R=(0,x,y),(x1,x2),dp; short=0; ideal S=-(x - 5)*(x1 - 1) - (x2 - 2)*(y - 2), (x1 - 5)^2 + (x2 - 2)^2 - 4, -2*(x - 5)*(x2 - 2) + 2*(x1 - 5)*(y - 2); locus(grobcov(S)); locusdg(locus(grobcov(S))); } // locusto: Transforms the output of locus, locusdg, envelop and envelopdg // into a string that can be reed from different computational systems. // input: // list L: The output of locus // output: // string s: The output of locus converted to a string readable by other programs proc locusto(list L) "USAGE: locusto(L); The argument must be the output of locus or locusdg or envelop or envelopdg. It transforms the output into a string in standard form readable in many languages (Geogebra). RETURN: The locus in string standard form NOTE: It can only be called after computing either - locus(grobcov(F)) -> locusto( locus(grobcov(F)) ) - locusdg(locus(grobcov(F))) -> locusto( locusdg(locus(grobcov(F))) ) - envelop(F,C) -> locusto( envelop(F,C) ) -envelopdg(envelop(F,C)) -> locusto( envelopdg(envelop(F,C)) ) KEYWORDS: geometrical locus, locus, loci. EXAMPLE: locusto; shows an example" { int i; int j; int k; string s="["; string sf="]"; string st=s+sf; if(size(L)==0){return(st);} ideal p; ideal q; for(i=1;i<=size(L);i++) { s=string(s,"[["); for (j=1;j<=size(L[i][1]);j++) { s=string(s,L[i][1][j],","); } s[size(s)]="]"; s=string(s,",["); for(j=1;j<=size(L[i][2]);j++) { s=string(s,"["); for(k=1;k<=size(L[i][2][j]);k++) { s=string(s,L[i][2][j][k],","); } s[size(s)]="]"; s=string(s,","); } s[size(s)]="]"; s=string(s,"]"); if(size(L[i])>=3) { s=string(s,",["); if(typeof(L[i][3])=="string") { s=string(s,string(L[i][3]),"]]"); } else { for(k=1;k<=size(L[i][3]);k++) { s=string(s,"[",L[i][3][k],"],"); } s[size(s)]="]"; s=string(s,"]"); } } if(size(L[i])>=4) { s[size(s)]=","; s=string(s,string(L[i][4]),"],"); } s[size(s)]="]"; s=string(s,","); } s[size(s)]="]"; return(s); } example { "EXAMPLE:"; echo = 2; ring R=(0,x,y),(x1,y1),dp; short=0; ideal S=x1^2+y1^2-4,(y-2)*x1-x*y1+2*x,(x-x1)^2+(y-y1)^2-1; locusto(locus(grobcov(S))); locusto(locusdg(locus(grobcov(S)))); kill R; //******************************************** // 1. Take a fixed line l: x1-y1=0 and consider // the family F of a lines parallel to l passing through the mover point M // 2. Consider a circle x1^2+x2^2-25, and a mover point M(x1,x2) on it. // 3. Compute the envelop of the family of lines. ring R=(0,x,y),(x1,y1),lp; poly F=(y-y1)-(x-x1); ideal C=x1^2+y1^2-25; short=0; // Curves Family F= F; // Conditions C= C; locusto(envelop(F,C)); locusto(envelopdg(envelop(F,C))); kill R; //******************************************** // Steiner Deltoid // 1. Consider the circle x1^2+y1^2-1=0, and a mover point M(x1,y1) on it. // 2. Consider the triangle A(0,1), B(-1,0), C(1,0). // 3. Consider lines passing through M perpendicular to two sides of ABC triangle. // 4. Obtain the envelop of the lines above. ring R=(0,x,y),(x1,y1,x2,y2),lp; ideal C=(x1)^2+(y1)^2-1, x2+y2-1, x2-y2-x1+y1; matrix M[3][3]=x,y,1,x2,y2,1,x1,0,1; poly F=det(M); short=0; // Curves Family F= F; // Conditions C= C; locusto(envelop(F,C)); locusto(envelopdg(envelop(F,C))); } // Auxiliary routine // locusdim // input: // B: ideal, a basis of a segment of the grobcov // dgdim: int, the dimension of the mover (for locus) // by default dgdim is equal to the number of variables static proc locusdim(ideal B, list #) { def R=basering; int dgdim; int nv=nvars(R); if (size(#)>0){dgdim=#[1];} else {dgdim=nv;} int d; list v; ideal vi; int i; for(i=1;i<=dgdim;i++) { v[size(v)+1]=varstr(nv-dgdim+i); vi[size(v)+1]=var(nv-dgdim+i); } ideal B0; for(i=1;i<=size(B);i++) { if(subset(variables(B[i]),vi)) { B0[size(B0)+1]=B[i]; } } def RR=ringlist(R); def RR0=RR; RR0[2]=v; def R0=ring(RR0); setring(R0); def B0r=imap(R,B0); B0r=std(B0r); d=dim(B0r); setring R; return(d); } static proc norspec(ideal F) { def RR=basering; def Rx=ringlist(RR); def Rx=ringlist(RR); def @P=ring(Rx[1]); list Lx; Lx[1]=0; Lx[2]=Rx[2]+Rx[1][2]; Lx[3]=Rx[1][3]; Lx[4]=Rx[1][4]; Rx[1]=0; def D=ring(Rx); def @RP=D+@P; exportto(Top,@R); // global ring Q[a][x] exportto(Top,@P); // global ring Q[a] exportto(Top,@RP); // global ring K[x,a] with product order setring(RR); } // envelop // Input: n arguments // poly F: the polynomial defining the family of curves in ring R=0,(x,y),(x1,..,xn),lp; // ideal C=g1,..,g_{n-1}: the set of constraints // Output: the components of the envolvent; proc envelop(poly F, ideal C, list #) "USAGE: envelop(F,C); The first argument F must be the family of curves of which on want to compute the envelop. The second argument C must be the ideal of conditions over the variables, and should contain as polynomials as the number of variables -1. RETURN: The components of the envelop with its taxonomy: The taxonomy distinguishes 'Normal', 'Special', 'Accumulation', 'Degenerate' components. In the case of 'Special' components, it also outputs the antiimage of the component and an integer (0-1). If the integer is 0 the component is not a curve of the family and is not considered as 'Relevant' by the envelopdg routine applied to it, but is considered as 'Relevant' if the integer is 1. NOTE: grobcov is called internally. The basering R, must be of the form Q[a][x] (a=parameters, x=variables). KEYWORDS: geometrical locus, locus, loci, envelop EXAMPLE: envelop; shows an example" { int tes=0; int i; int j; def R=basering; if(defined(@P)==1){tes=1; kill @P; kill @R; kill @RP;} setglobalrings(); // Options list DD=#; int moverdim=nvars(R); int version=0; int nv=nvars(R); if(nv<4){version=1;} int comment=0; ideal Fm; for(i=1;i<=(size(DD) div 2);i++) { if(DD[2*i-1]=="movdim"){moverdim=DD[2*i];} if(DD[2*i-1]=="version"){version=DD[2*i];} if(DD[2*i-1]=="system"){Fm=DD[2*i];} if(DD[2*i-1]=="comment"){comment=DD[2*i];} } int n=nvars(R); list v; for(i=1;i<=n;i++){v[size(v)+1]=var(i);} def MF=jacob(F); def TMF=transpose(MF); def Mg=MF; def TMg=TMF; for(i=1;i<=n-1;i++) { Mg=jacob(C[i]); TMg=transpose(Mg); TMF=concat(TMF,TMg); } poly J=det(TMF); ideal S=ideal(F)+C+ideal(J); DD[size(DD)+1]="family"; DD[size(DD)+1]=F; def G=grobcov(S,DD); def L=locus(G, DD); return(L); } example { "EXAMPLE:"; echo = 2; // Steiner Deltoid // 1. Consider the circle x1^2+y1^2-1=0, and a mover point M(x1,y1) on it. // 2. Consider the triangle A(0,1), B(-1,0), C(1,0). // 3. Consider lines passing through M perpendicular to two sides of ABC triangle. // 4. Obtain the envelop of the lines above. ring R=(0,x,y),(x1,y1,x2,y2),lp; ideal C=(x1)^2+(y1)^2-1, x2+y2-1, x2-y2-x1+y1; matrix M[3][3]=x,y,1,x2,y2,1,x1,0,1; poly F=det(M); short=0; // Curves Family F= F; // Conditions C= C; def Env=envelop(F,C); Env; } // envelopdg // Input: list L: the output of envelop(poly F, ideal C, list #) // Output: the relevant components of the envolvent in dynamic geometry; proc envelopdg(list L) "USAGE: envelopdg(L); The input list L must be the output of the call to the routine 'envolop' of the family of curves RETURN: The relevant components of the envelop in Dynamic Geometry. 'Normal' and 'Accumulation' components are always considered 'Relevant'. 'Special' components of the envelop outputs three objects in its characterization: 'Special', the antiimage ideal, and the integer 0 or 1, that indicates that the given component is formed (1) or is not formed (0) by curves of the family. Only if yes, 'envelopdg' considers the component as 'Relevant' . NOTE: It must be called to the output of the 'envelop' routine. The basering R, must be of the form Q[a,b,..][x,y,..]. KEYWORDS: geometrical locus, locus, loci, envelop. EXAMPLE: envelop; shows an example" { list LL; list Li; int i; for(i=1;i<=size(L);i++) { if(typeof(L[i][3])=="string") { if((L[i][3]=="Normal") or (L[i][3]=="Accumulation")){Li=L[i]; Li[3]="Relevant"; LL[size(LL)+1]=Li;} } else { if(typeof(L[i][3])=="list") { if(L[i][3][3]==1) { Li=L[i]; Li[3]="Relevant"; LL[size(LL)+1]=Li; } } } } return(LL); } example { "EXAMPLE:"; echo = 2; // 1. Take a fixed line l: x1-y1=0 and consider // the family F of a lines parallel to l passing through the mover point M // 2. Consider a circle x1^2+x2^2-25, and a mover point M(x1,x2) on it. // 3. Compute the envelop of the family of lines. ring R=(0,x,y),(x1,y1),lp; short=0; poly F=(y-y1)-(x-x1); ideal C=x1^2+y1^2-25; short=0; // Curves Family F= F; // Conditions C= C; envelop(F,C); envelopdg(envelop(F,C)); } // AddLocus: auxilliary routine for locus0 that computes the components of the constructible: // Input: the list of locally closed sets to be added, each with its type as third argument // L=[ [LC[11],,,LC[1k_1], .., [LC[r1],,,LC[rk_r] ] where // LC[1]=[p1,[p11,..,p1k],typ] // Output: the list of components of the constructible union of the L, with the type of the corresponding top // and the level of the constructible // L4= [[v1,p1,[p11,..,p1l],typ_1,level]_1 ,.. [vs,ps,[ps1,..,psl],typ_s,level_s] static proc AddLocus(list L) { // int te0=0; // def RR=basering; // if(defined(@P)){te0=1; def Rx=@R; kill @P; setring RR;} list L1; int i; int j; list L2; list L3; list l1; list l2; intvec v; for(i=1; i<=size(L); i++) { for(j=1;j<=size(L[i]);j++) { l1[1]=L[i][j][1]; l1[2]=L[i][j][2]; l2[1]=l1[1]; if(size(L[i][j])>2){l2[3]=L[i][j][3];} v[1]=i; v[2]=j; l2[2]=v; L1[size(L1)+1]=l1; L2[size(L2)+1]=l2; } } L3=LocusConsLevels(L1); list L4; int level; ideal p1; ideal pp1; int t; int k; int k0; string typ; list l4; for(i=1;i<=size(L3);i++) { level=L3[i][1]; for(j=1;j<=size(L3[i][2]);j++) { p1=L3[i][2][j][1]; t=1; k=1; while((t==1) and (k<=size(L2))) { pp1=L2[k][1]; if(equalideals(p1,pp1)){t=0; k0=k;} k++; } if(t==0) { v=L2[k0][2]; } else{"ERROR p1 NOT FOUND";} l4[1]=v; l4[2]=p1; l4[3]=L3[i][2][j][2]; l4[5]=level; if(size(L2[k0])>2){l4[4]=L2[k0][3];} L4[size(L4)+1]=l4; } } return(L4); } // Input L: list of components in P-rep to be added // [ [[p_1,[p_11,..,p_1,r1]],..[p_k,[p_k1,..,p_kr_k]] ] // Output: // list of lists of levels of the different locally closed sets of // the canonical P-rep of the constructible. // [ [level_1,[ [Comp_11,..Comp_1r_1] ] ], .. , // [level_s,[ [Comp_s1,..Comp_sr_1] ] // ] // where level_i=i, Comp_ij=[ p_i,[p_i1,..,p_it_i] ] is a prime component. // LocusConsLevels: given a set of components of locally closed sets in P-representation, it builds the // canonical P-representation of the corresponding constructible set of its union, // including levels it they are. static proc LocusConsLevels(list L) { list Lc; list Sc; int i; for(i=1;i<=size(L);i++) { Sc=PtoCrep(list(L[i])); Lc[size(Lc)+1]=Sc; } list S=ConsLevels(Lc)[1]; list Sout; list Lev; for(i=1;i<=size(S);i++) { Lev=list(i,Prep(S[i][2][1],S[i][2][2])); Sout[size(Sout)+1]=Lev; } return(Sout); } //********************* End locus **************************** singular-4.0.3+ds/Singular/LIB/groups.lib000066400000000000000000000707731266270727000201740ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version groups.lib 4.0.0.0 Jun_2013 "; // $Id: 0662b22472659602115c9b5d297e7c6c9391575b $ category="Applications"; info=" LIBRARY: groups.lib Finite Group Theory AUTHORS: Gert-Martin Greuel, email: greuel@mathematik.uni-kl.de @* Gerhard Pfister, email: pfister@mathematik.uni-kl.de PROCEDURES: noSolution(I) I an ideal in a polynomial ring over Z[x1..xn] returns a list l of primes <=32003 such that 1 is in IZ/p[x1..xn] for p not in l or an ERROR if this is wrong or not decided. " /* // ===================== A Problem in Finite Group Theory =================== // Posed by Boris Kunyavskii, Bar-Ilan University, Tel Aviv // // For any word w in X,Y,X^(-1),Y^(-1) consider the sequence U_n // of words (depending on w) inductively // U_1 = w // U_n+1 = [X*U_n*X^(-1),Y*U_n*Y^(-1)] // with // [X,Y] = X*Y*X^(-1)*Y^(-1) (the commutator) // Conjecture (1): // (by B. Plotkin, slightly modified): // A finite group G is solvable <==> // there is an n >= 1 such that U_n(x,y) = 1 for all x,y in G // and for any of the 4 following words // w1 = X^(-1)*Y*X*Y^(-1)*X // w2 = X^(-2)*Y^(-1)*X // w3 = Y^(-2)*X^(-1)*X // w4 = X*Y^(-2)*X^(-1)*Y*X^(-1) // // (These words remained as possibly good words by a computer search // through about 10 000 candidates, by Fritz Grunewald) // ==> is clear // The minimal finite non-solvable groups (i.e. every proper subgroup is // solvable) have been classified by Thompson in 1968, they are: // // 1. PSL(2,p) (p=5 or p=+-2 (mod 5), p!=3) // 2. PSL(2,2^p) // 3. PSL(2,3^p) (p odd) // 4. Sz(2^p) (p odd) (Suzuki group) // 5. PSL(3,3) // // In view of this result Conjecture (1) is equivalent to // // Conjecture (2): // Let G be one of the groups above, then, for at least one of the 4 words w // above there are x,y in G such that 1 != U_n(x,y) = U_n+1(x,y) for some n. // (then U_n(x,y) != 1 for all n by definitionof U_n) // We give a computer aided proof, using SINGULAR, of Conjecture (2) for // the groups 1. - 3. (up to checking for a small, explicit number of primes) // Hence only the Suzuki groups have to be checked. // // We show: 1 != U_1(x,y) = U_2(x,y) for word w1 and some x,y in G // We need: // Theory // - simple facts from algebraic geometry, singularity theory, finite fields // - theorem of Lang-Weil, estimating the number of rational points on an // absolutely irreducible projective curve C defined over Z (g=genus): // if q >= N(g) ==> #C(F_q) != 0 // (N(g) = 4g^2 -2, g arithmetic genus) // SINGULAR // - Groebner basis (elimination), multivariate factorization, resolution of // plane curve singularities (Hamburger Noether developement), primary // decomposition */ LIB "standard.lib"; LIB "general.lib"; LIB "matrix.lib"; /////////////////////////////////////////////////////////////////////////////// static proc splitS1(ideal I,int s,list #) "USAGE: splitS1(I,s[,l]) I ideal, s integer, l list of ideals COMPUTE: Factorizes the generators of I. If for one generator f=f1*f2 and fi=ni*gi^ri, ni an integer and gi a polynomial, then compute a standardbasis of I1=I,g1 and I2=I,g2, if this can be done in < s seconds. Then apply splitS to I1 and I2 and continue in the same way. The procedure stops if no generator can be factorized. RETURN: A list L of ideals and prime numbers L[1]: A list of ideals such that the radical of the intersection of these ideals coincides with the radical of I If the optional list l of the input is not empty then the ideals of L[1] which contain an ideal of l are canceled. L[2]: A list of prime numbers appearing as factors of the ni. NOTE: The computation avoids division by integers (by using option(contentSB)) hence the result is correct modulo any prime number which does not appear in the list L[2]. EXAMPLE: example splitS1; shows an example " { option(redSB); option(contentSB); int j,k,e; int i=1; int l=attrib(I,"isSB"); ideal J; list re,fac,te,pr,qr,w; number n; poly p; re=#; if(deg(I[1])==0){return(list(re+list(std(I)),qr));} fac=factorize(I[1]); while((size(fac[1])==2)&&(i2) { w=squarefreeP(number(fac[1][1])); n=w[1]; qr=insResult(qr,w[2]); for(j=2;j<=size(fac[1]);j++) { I[i]=fac[1][j]; attrib(I,"isSB",1); e=1; k=0; while(k2) { w=squarefreeP(number(fac[1][1])); n=w[1]; qr=insResult(qr,w[2]); for(j=2;j<=size(fac[1]);j++) { I[i]=fac[1][j]; attrib(I,"isSB",1); e=1; k=0; while(k0)) { "split again"; K=sort(q[1])[1]; J=K[1..20+4*k]; pr=splitS(J,5); q=pr[1]; qr=insResult(qr,pr[2]); size(q);"out"; for(j=1;j<=size(q);j++) { if(deg(q[j][1])==0) { pr=contentS(q[j]); q[j]=pr[1]; qr=insResult(qr,pr[2]); } else { pr=simpliFy(q[j]+K); q[j]=pr[1]; qr=insResult(qr,pr[2]); pr=contentS(q[j]); q[j]=pr[1]; qr=insResult(qr,pr[2]); } } } if((size(q)==1)&&(deg(q[1][1])>0)) { n++; "split again"; K=q[1]; J=shortid_L(K,3+n); pr=splitS1(J,5); if(size(pr[1])>1) { q=pr[1]; qr=insResult(qr,pr[2]); size(q);"out"; for(j=1;j<=size(q);j++) { if(deg(q[j][1])==0) { pr=contentS(q[j]); q[j]=pr[1]; qr=insResult(qr,pr[2]); } else { pr=simpliFy(q[j]+K); q[j]=pr[1]; qr=insResult(qr,pr[2]); pr=contentS(q[j]); q[j]=pr[1]; qr=insResult(qr,pr[2]); } } } } if(size(q)>1) { count++; } else { if(deg(q[1][1])>0) { q[1]=changeOrdTest(q[1]); } } p=p+q; } else { pr=primefactors(number(K[1])); qr=insResult(qr,pr[1]); } } l=p; kill p; } l; for(i=1;i<=size(l);i++) { if(deg(l[i][1])>0){l;ERROR("not ready");} pr=primefactors(number(l[i][1])); if(pr[3]!=1){pr;ERROR("not ready");} qr=insResult(qr,pr[1]); } return(qr); } example { "EXAMPLE:"; echo = 2; ring r=0,x,dp; list qr=2,5,7; ideal i=181x-181,11x+11; list pr=i; finalSplit(pr,qr); } /////////////////////////////////////////////////////////////////////////////// proc noSolution(ideal I) "USAGE: noSolution(I) I ideal RETURN: list l of primes <=32003 such that 1 is in IZ/p[x1..xn] for p not in l or an ERROR if this is wrong or not decided. EXAMPLE: example noSolution; shows an example " { int s=1; int t=30; option(redThrough); option(contentSB); ideal J=shortid_L(I,3); ideal K; number n; "first splitting"; int i,j,k; list l,p,q,re,pr,qr; pr=splitS(J,s); l=pr[1]; qr=pr[2]; size(l); for(i=1;i<=size(l);i++) { if(deg(l[i][1])==0) { K=l[i][1]; } else { pr=simpliFy(I+l[i]); J=pr[1]; qr=insResult(qr,pr[2]); pr=contentS(J); J=pr[1]; qr=insResult(qr,pr[2]); K=timeStd(J,1); } if(deg(K[1])==0) { n=number(K[1]); pr=primefactors(n); if(pr[3]!=1) { J=changeOrdTest(J); p=p+list(J); } else { qr=insResult(qr,pr[1]); } } else { pr=contentS(K); p=p+list(pr[1]); qr=insResult(qr,pr[2]); } } "trivial splitting 1"; pr=trivialSplit(p,3); p=pr[1]; qr=insResult(qr,pr[2]); size(p); "second splitting"; for(i=1;i<=size(p);i++) { i; if(size(p[i])0) { i; pr=simpliFy(re[i]); J=pr[1]; qr=insResult(qr,pr[2]); "in splitting"; J=shortid_L(J,3); pr=splitS(J,s); l=pr[1]; if(size(l)==1) { "split again"; pr=simpliFy(re[i]); J=pr[1]; qr=insResult(qr,pr[2]); J=J[1..t]; pr=splitS(J,s); l=pr[1]; qr=insResult(qr,pr[2]); } else { qr=insResult(qr,pr[2]); } size(l); "out"; for(j=1;j<=size(l);j++) { pr=contentS(l[j]); l[j]=pr[1]; qr=insResult(qr,pr[2]); pr=simpliFy(re[i]+l[j]); J=pr[1]; qr=insResult(qr,pr[2]); K=timeStd(J,10); if(deg(K[1])==0) { n=number(K[1]); pr=primefactors(n); if(pr[3]!=1) { pr=contentS(J); J=pr[1]; qr=insResult(qr,pr[2]); J=changeOrdTest(J); q=q+list(J); } else { qr=insResult(qr,pr[1]); } } else { pr=contentS(K); qr=insResult(qr,pr[2]); q=q+list(pr[1]); } } } else { i; pr=primefactors(number(re[i][1])); qr=insResult(qr,pr[1]); } } "jetzt geht es los"; return(finalSplit(q,qr)); } example { "EXAMPLE:"; echo = 2; ring r=0,x,dp; ideal i=181x-181,11x+11; noSolution(i); } /////////////////////////////////////////////////////////////////////////////// static proc changeOrdTest(ideal I) { def R=basering; if(deg(I[1])==0){return(I);} def RR=changeord(list(list("dp",1:nvars(basering)))); setring RR; ideal I=imap(R,I); ideal K=timeStd(I,5); if(deg(K[1])==0) { number n=number(K[1]); if(primefactors(n)[3]==1) { I=K; } } setring R; I=imap(RR,I); kill RR; return(I); } /////////////////////////////////////////////////////////////////////////////// static proc trivialSplit(list p,int depth, list #) "USAGE: trivialSplit(p,s) p list of ideals, s integer the number of iterations COMPUTE: Factorizes the monomials among the generators of I. If one monomial contains the variables x1,..xr, then I1=I(x1=0),...,Ir=I(xr=0) is considered. Then apply trivialSplit to I1 ...Ir and continue in the same way s times. RETURN: A list L of ideals and prime numbers L[1]: A list of ideals such that the radical of the intersection of these ideals at x1=...=xr=0 coincides with the radical of I at x1=...=xr=0. L[2]: A list of prime numbers appearing as factors of the monomials. NOTE: The computation avoids division by integers hence the result is correct modulo any prime number which does not appear in the list L[2]. EXAMPLE: example trivialSplit; shows an example " { list re,l,pr,qr; int i,k; ideal J,K,T,Ke; number n; if(size(p)==0){return(list(p,qr));} if(depth<=0){return(list(p,qr));} if(size(#)>0) { T=#[1]; } else { T=1; } for(k=1;k<=size(p);k++) { pr=simpliFy(p[k]); p[k]=pr[1]; qr=insResult(qr,pr[2]); J=shortid_L(p[k],1); if((size(J)>0)&&(deg(J[1])>=1)) { pr=splitS1(J,10); l=pr[1]; qr=insResult(qr,pr[2]); for(i=1;i<=size(l);i++) { Ke=l[i]; l[i]=trivialSimplify(p[k],l[i]); pr=simpliFy(l[i]); l[i]=pr[1]; qr=insResult(qr,pr[2]); K=timeStd(l[i],1); attrib(K,"isSB",1); if(deg(K[1])==0) { n=number(K[1]); if(primefactors(n)[3]!=1) { l[i]=changeOrdTest(l[i]); pr=trivialSplit(l[i],depth-1,T); re=re+pr[1]; qr=insResult(qr,pr[2]); } else { l[i]=K; //neu } } else { if(size(reduce(trivialSimplify(T,Ke),K))!=0) { pr=trivialSplit(K,depth-1,trivialSimplify(T,Ke)); re=re+pr[1]; qr=insResult(qr,pr[2]); } } T=intersect(T,Ke); } } else { J=timeStd(p[k],5); if(deg(J[1])==0) { n=number(J[1]); if(primefactors(n)[3]!=1) { p[k]=changeOrdTest(p[k]); re=re+list(p[k]); } else { re=re+list(J); } } else { re=re+list(J); } } } return(list(re,qr)); } example { "EXAMPLE:"; echo = 2; ring r=0,(b,s,t,u,v,w,x,y,z),dp; ideal i= bv+su, bw+tu, sw+tv, by+sx, bz+tx, sz+ty, uy+vx, uz+wx, vz+wy, bvz; trivialSplit(i,2); } /////////////////////////////////////////////////////////////////////////////// static proc trivialSimplify(ideal I, ideal J) "USAGE: trivialSimplify(I,J); I,J ideals, J generated by variables RETURN: ideal K = eliminate(I,m) m the product of variables of J EXAMPLE: example trivialSimplify; shows an example " { int i; for(i=1;i<=size(J);i++){I=subst(I,J[i],0);} return(simplify(I,2)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,w,t,u),dp; ideal i= t,u, x3+y2+2z, x2+3y, x2+y2+z2, w2+z+u; ideal j=t,u; trivialSimplify(i,j); } /////////////////////////////////////////////////////////////////////////////// static proc simpliFy(ideal J,list #) "USAGE: simpliFy(id); id ideal RETURN: ideal I = eliminate(Id,m) m is a product of variables which are in linear equations involved in the generators of id EXAMPLE: example simpliFy; shows an example " { ideal I=J; if(size(#)!=0){I=#[1];} def R=basering; matrix M=jacob(I); ideal ma=maxideal(1); int i,j,k; map phi; list pr,re; for(i=1;i<=nrows(M);i++) { for(j=1;j<=ncols(M);j++) { if((deg(M[i,j])==0)&&(deg(I[i])==1)) { ma[j]=(-1/M[i,j])*(I[i]-M[i,j]*var(j)); pr=primefactors(number(M[i,j])); if(pr[3]>1){pr[3];ERROR("number too big in simpliFy");} re=insResult(re,pr[1]); phi=R,ma; I=phi(I); J=phi(J); for(k=1;k<=ncols(I);k++) { I[k]=cleardenom(I[k]); } M=jacob(I); } } } J=simplify(J,2); for(i=1;i<=size(J);i++) { if(deg(J[i])==0){J=std(J);break;} J[i]=cleardenom(J[i]); } return(list(J,re)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,w),dp; ideal i= x3+y2+2z, x2+3y, x2+y2+z2, w2+z; simpliFy(i); } /////////////////////////////////////////////////////////////////////////////// static proc squarefreeP(number n) "USAGE: squarefreeP(n); n number RETURN: list l of numbers. l[2] contains all prime factors of n less then 32003, l[1] is the part of m which has prime factors greater then 32003 EXAMPLE: example squarefreeP; shows an example " { list re; if(n<0){n=-n;} if(n==1){return(list(n,re));} list pr=primefactors(n); int i; number m=number(pr[3][1]); re=insResult(re,pr[1]); return(list(m,re)); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; squarefreeP(123456789100); } /////////////////////////////////////////////////////////////////////////////// static proc contentS(ideal I) "USAGE: contentS(I); I ideal RETURN: list l l[1] the ideal I. Te generators of I are the generators of the input ideal devided by the part of the content which have prime factors less then 32003. l[2] contains the prime numbers which occured in the division EXAMPLE: example contentS; shows an example " { option(contentSB); int i,k; number n,m; list pr,re; for(i=1;i<=size(I);i++) { n=leadcoef(I[i]); if(n<0){n=-n;} if(n>1) { pr=primefactors(n); if(n<=32003) { m=n; } else { m=number(pr[1][1])^pr[2][1]; for(k=2;k<=size(pr[1]);k++) { m=m*number(pr[1][k])^pr[2][k]; } } I[i]=cleardenom(I[i]/m); re=insResult(re,pr[1]); } } return(list(I,re)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; ideal I=2x+2,3y+3x,1234567891x+1234567891; contentS(I); } /////////////////////////////////////////////////////////////////////////////// static proc insResult(list r,#) { if(size(#)==0){return(r);} if(size(r)==0){r[1]=1;} int i,j; for(i=1;i<=size(#);i++) { j=1; while((#[i]>r[j])&&(jr[j]){r=insert(r,#[i],j);} if(#[i]= 1 && n1 <= nV && n2 >= 1 && n2 <= nV); if(n1 < 1 || n1 > nV || n2 < 1 || n2 > nV) { print("//Erorr: The perturbed degree is wrong!!"); print("// It must be between 1 and " + string(nV)); return(); } /* we use ring with ordering (a(...),lp,C) */ list OSCTW = OrderStringalp_NP("al", #); string ord_str = OSCTW[2]; intvec curr_weight = OSCTW[3]; /* original weight vector */ intvec target_weight = OSCTW[4]; /* terget weight vector */ kill OSCTW; option(redSB); def xR = basering; execute("ring ostR = ("+charstr(xR)+"),("+varstr(xR)+"),"+ord_str+";"); def old_ring = basering; //print("//** help ring = " + string(basering)); ideal G = fetch(xR, Go); G = system("MAltwalk1", G, n1, n2, curr_weight, target_weight); setring xR; //kill Go; keepring basering; ideal result = fetch(old_ring, G); attrib(result,"isSB",1); return (result); } proc fwalk(ideal Go, list #) "SYNTAX: fwalk(ideal i); fwalk(ideal i, intvec v, intvec w); TYPE: ideal PURPOSE: compute the standard basis of the ideal w.r.t. the lexicographical ordering or a weighted-lex ordering, calculated via the fractal walk algorithm. SEE ALSO: std, stdfglm, groebner, gwalk, pwalk, twalk, awalk1, awalk2 KEYWORDS: The fractal walk algorithm EXAMPLE: example fwalk; shows an example" { /* we use ring with ordering (a(...),lp,C) */ list OSCTW = OrderStringalp_NP("al", #); string ord_str = OSCTW[2]; intvec curr_weight = OSCTW[3]; /* original weight vector */ intvec target_weight = OSCTW[4]; /* target weight vector */ kill OSCTW; option(redSB); def xR = basering; execute("ring ostR = ("+charstr(xR)+"),("+varstr(xR)+"),"+ord_str+";"); def old_ring = basering; //print("//** help ring = " + string(basering)); ideal G = fetch(xR, Go); int reduction=1; int printout=0; G = system("Mfwalk", G, curr_weight, target_weight, reduction, printout); setring xR; //kill Go; keepring basering; ideal result = fetch(old_ring, G); attrib(result,"isSB",1); return (result); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(z,y,x), lp; ideal I = y3+xyz+y2z+xz3, 3+xy+x2y+y2z; fwalk(I); } proc awalk2(ideal Go, list #) "SYNTAX: awalk2(ideal i); awalk2(ideal i, intvec v, intvec w); TYPE: ideal PURPOSE: compute the standard basis of the ideal, calculated via the second alternative algorithm from the ordering \"(a(v),lp)\", \"dp\" or \"Dp\" to the ordering \"(a(w),lp)\" or \"(a(1,0,...,0),lp)\". SEE ALSO: std, stdfglm, groebner, gwalk, pwalk, fwalk, twalk, awalk1 KEYWORDS: Groebner walk EXAMPLE: example awalk2; shows an example" { /* we use ring with ordering (a(...),lp,C) */ list OSCTW = OrderStringalp_NP("al", #);//"dp" string ord_str = OSCTW[2]; intvec curr_weight = OSCTW[3]; /* original weight vector */ intvec target_weight = OSCTW[4]; /* terget weight vector */ kill OSCTW; option(redSB); def xR = basering; execute("ring ostR = ("+charstr(xR)+"),("+varstr(xR)+"),"+ord_str+";"); def old_ring = basering; //print("//** help ring = " + string(basering)); ideal G = fetch(xR, Go); G = system("MAltwalk2", G, curr_weight, target_weight); setring xR; //kill Go; keepring basering; ideal result = fetch(old_ring, G); attrib(result,"isSB",1); return (result); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(z,y,x), lp; ideal I = y3+xyz+y2z+xz3, 3+xy+x2y+y2z; awalk2(I); } proc pwalk(ideal Go, int n1, int n2, list #) "SYNTAX: pwalk(int d, ideal i, int n1, int n2); pwalk(int d, ideal i, int n1, int n2, intvec v, intvec w); TYPE: ideal PURPOSE: compute the standard basis of the ideal, calculated via the perturbation walk algorithm from the ordering \"(a(v),lp)\", \"dp\" or \"Dp\" to the ordering \"(a(w),lp)\" or \"(a(1,0,...,0),lp)\" with a perturbation degree n, m for v and w, resp. SEE ALSO: std, stdfglm, groebner, gwalk, fwalk, twalk, awalk1, awalk2 KEYWORDS: Perturbation walk EXAMPLE: example pwalk; shows an example" { int nV = nvars(basering); //assume(n1 >= 1 && n1 <= nV && n2 >= 1 && n2 <= nV); if(n1 < 1 || n1 > nV || n2 < 1 || n2 > nV) { print("//Erorr: The perturbed degree is wrong!!"); print("// It must be between 1 and " + string(nV)); return(); } /* we use ring with ordering (a(...),lp,C) */ list OSCTW = OrderStringalp_NP("al", #); int nP = OSCTW[1]; string ord_str = OSCTW[2]; intvec curr_weight = OSCTW[3]; /* original weight vector */ intvec target_weight = OSCTW[4]; /* terget weight vector */ kill OSCTW; option(redSB); def xR = basering; execute("ring ostR = ("+charstr(xR)+"),("+varstr(xR)+"),"+ord_str+";"); def old_ring = basering; ideal G = fetch(xR, Go); int reduction=1; int printout=0; G = system("Mpwalk",G,n1,n2,curr_weight,target_weight,nP,reduction,printout); setring xR; //kill Go; //unused keepring basering; ideal result = fetch(old_ring, G); attrib(result,"isSB",1); return (result); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(z,y,x), lp; ideal I = y3+xyz+y2z+xz3, 3+xy+x2y+y2z; pwalk(I,2,2); } proc twalk(ideal Go, list #) "SYNTAX: twalk(ideal i); twalk(ideal i, intvec v, intvec w); TYPE: ideal PURPOSE: compute the standard basis of the ideal w.r.t. the ordering \"(a(w),lp)\" or \"(a(1,0,...,0),lp)\", calculated via the Tran algorithm. SEE ALSO: std, stdfglm, groebner, gwalk, pwalk, fwalk, awalk1, awalk2 KEYWORDS: The Tran algorithm EXAMPLE: example twalk; shows an example" { list L = OrderStringalp_NP("al", #); int nP = L[1]; /* we use ring with ordering (a(...),lp,C) */ string ord_str = L[2]; intvec curr_weight = L[3]; intvec target_weight = L[4]; kill L; option(redSB); def xR = basering; execute("ring ostR = ("+charstr(xR)+"),("+varstr(xR)+"),"+ord_str+";"); def old_ring = basering; //print("//** help ring = " + string(basering)); ideal G = fetch(xR, Go); G = system("TranMImprovwalk", G, curr_weight, target_weight, nP); setring xR; //kill Go; keepring basering; ideal result = fetch(old_ring, G); attrib(result,"isSB",1); return (result); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(z,y,x), lp; ideal I = y3+xyz+y2z+xz3, 3+xy+x2y+y2z; twalk(I); } singular-4.0.3+ds/Singular/LIB/hdepth.lib000066400000000000000000000105711266270727000201170ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version hdepth.lib 4.0.0.0 Jun_2013"; // category="Commutative Algebra"; info=" LIBRARY: hdepth.lib Procedures for computing hdepth_1 AUTHORS: Popescu, A., popescu@mathematik.uni-kl.de SEE ALSO: 'An algorithm to compute the Hilbert depth', Adrian Popescu, arxiv/AC/1307.6084 KEYWORDS: hdepth, library PROCEDURES: hdepth(M [,debug]); hdepth_1 computation of a module M (wrt Z-grading) hdepth_p(g, d, debug) the minimum number t <= d s.t. 1/g^t is positive "; /////////////////////////////////////////////////////////////////////////////////// static proc myinverse(poly p, int bound) "USAGE: myinverse(p,bound), p polynomial in one variable with p(0) nonzero, bound a nonnegative integer RETURN: poly, the inverse of the poly p in the power series ring till order bound " { if(bound<=1) { ERROR("My inverse : negative bound in the inverse"); } if(p == 0) { ERROR("My inverse : p is 0"); } poly original; original = p; if(leadcoef(p) == 0) { ERROR("My inverse : the power series is not a unit."); } poly q = 1/p[1]; poly res = q; p = q * (p[1] - jet(p,bound)); poly s = p; while(p != 0) { res = res + q * p; p = jet(p*s,bound); } //TEST if(jet(original*res,bound) != poly(1)) { ERROR("Myinverse does not work properly."); } return(res); } /////////////////////////////////////////////////////////////////////////////////// static proc hilbconstruct(intvec v) "USAGE: hilbconstruct(v), v is the result of hilb(M,2) RETURN: poly, the Hilbert Series of M AASUME: the ring when called is R = 0,t,ds; " { poly f; int i; for(i=0;i 0"); } example { "EXAMPLE:";echo=2; ring R = 0,t,ds; poly f = 2-3t-2t2+2t3+4t4; hdepth_p(f,5,0); hdepth_p(f,5,1); } /////////////////////////////////////////////////////////////////////////////// proc hdepth(module M, list #) "USAGE: hdepth(M [,debug]); M is a module, if one want to print the steps debug = 0 RETURN: int PURPOSE: compute the hdepth_1 of a module M EXAMPLE: example hdepth; shows examples " { int debug; if(size(#)>0) { if(typeof(#[1])=="int") {debug = #[1];} } else {debug = 1;} M = std(M); int d=nvars(basering)-dim(M); intvec v=hilb(M,2); ring R = 0,t,ds; poly hp=hilbconstruct(v); if(debug == 0) {"dim =",d;} return(hdepth_p(hp,d,debug)); } example { "EXAMPLE:";echo=2; ring R = 0,(x(1..10)),dp; ideal i=maxideal(1); module M=i; hdepth(M); hdepth(M,0); hdepth(M,1); } singular-4.0.3+ds/Singular/LIB/help.cnf000066400000000000000000000057551266270727000176030ustar00rootroot00000000000000# Singular help browser file # each line which start with an # is a comment # each other line defines a (possible) help browser # the format of the entries is: !! #---------------------------------------------------- # known requirements: # x- requires singular.idx # i- requires singular.hlp # h- requires html dir # D- requires the enviroment variable DISPLAY # E:executable:- requires the named exectable # O:`uname -m`-`uname -s`:- requires the named uname # (ubuntu has an open completely different from open on OsX) #---------------------------------------------------- # shell commands substitute the following: # %h: the local html file (in the form file://localhost/some/dir/sing_123.htm) # %f: the local html file (in the form /some/dir/sing_123.htm) # %H: the www html file # (in the form http://www.singular.uni-kl.de/some/dir/sing_123.htm) # %i: the complete path of singular.hlp # %n: the info node # %v: Singular version (in the form 4-0-0) #---------------------------------------------------- # the default help browsers builtin, dummy and emacs are always # available and should NOT be mentioned here #---------------------------------------------------- htmlview!xDhE:htmlview:!htmlview %h & mac!xhE:open:O:x86_64-Darwin:!open %f & mac-net!xE:open:O:x86_64-Darwin:!open %H & mozilla!xDhE:mozilla:!(mozilla -remote "openURL(%h)")||(mozilla %h) & firefox!xDhE:firefox:!firefox %h & konqueror!xDhE:konqueror:!konqueror %h & galeon!xDhE:galeon:!galeon -n %h & netscape!xDhE:netscape:!(netscape -remote "openURL(%h)")||(netscape %h) & cygwin!xhE:cygstart:!cygstart "%h" & cygwin-www!E:cygstart:!cygstart "%H" & safari!xhE:/Applications/Safari.app:!open -a /Applications/Safari.app %h tkinfo!xDiE:tkinfo:!tkinfo '(%i)%n' & xinfo!xDiE:xterm:E:info:!xterm -e info -f %i --node='%n' & info!xiE:info:!info -f %i --node='%n' lynx!xhE:lynx:!lynx %h #---------------------------------------------------------------- # dummy versions for pure online help mac-www!E:open:O:x86_64-Darwin:!open http://www.singular.uni-kl.de/Manual/%v/ & mozilla-www!DE:mozilla:!(mozilla -remote "openURL(http://www.singular.uni-kl.de/Manual/%v/)")||(mozilla http://www.singular.uni-kl.de/Manual/%v/) & firefox-www-idx!xDE:firefox:!firefox %H & firefox-www!DE:firefox:!firefox http://www.singular.uni-kl.de/Manual/%v/ & konqueror-www-idx!xDE:konqueror:!konqueror %H & konqueror-www!DE:konqueror:!konqueror http://www.singular.uni-kl.de/Manual/%v/ & galeon-www-idx!xDE:galeon:!galeon -n %H & galeon-www!DE:galeon:!galeon -n http://www.singular.uni-kl.de/Manual/%v/ & netscape-www!DE:netscape:!(netscape -remote "openURL(http://www.singular.uni-kl.de/Manual/%v/)")||(netscape http://www.singular.uni-kl.de/Manual/%v/) & safari-www-idx!xE:/Applications/Safari.app:!open -a /Applications/Safari.app %H safari-www!E:/Applications/Safari.app:!open -a /Applications/Safari.app http://www.singular.uni-kl.de/Manual/%v/ lynx-www-idx!xE:lynx:!lynx %H lynx-www!E:lynx:!lynx http://www.singular.uni-kl.de/Manual/%v/ singular-4.0.3+ds/Singular/LIB/hess.lib000066400000000000000000001544351266270727000176150ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////// version="on hess.lib 4.0.1.0 Oct_2014 $"; //$Id: 01c3eb3624e186a5bb537a0f6ca762fa4d051af4 $ category="Hess"; info=" LIBRARY: hess.lib Riemann-Roch space of divisors on function fields and curves AUTHORS: I. Stenger: stenger@mathematik.uni-kl.de OVERVIEW: Let f be an absolutely irreducible polynomial in two variables x,y. Assume that f is monic as a polynomial in y. Let F = Quot(k[x,y]/f) be the function field defined by f. Define O_F = IntCl(k[x],F) and O_(F,inf) = IntCl(k[1/x],F). We represent a divisor D on F by two fractional ideals I and J of O_F and O_(F,inf), respectively. The Riemann-Roch space L(D) is then the intersection of I^(-1) and J^(-1). PROCEDURES: RiemannRochHess() Computes a vector space basis of the Riemann-Roch space of a divisor "; LIB "integralbasis.lib"; LIB "qhmoduli.lib"; LIB "dmodloc.lib"; LIB "modstd.lib"; LIB "matrix.lib"; LIB "absfact.lib"; ///////////////////////////////////////////////////////////////////// ///////////////////// Main Procedure //////////////////////////////// //__________________________________________________________________ proc RiemannRochHess(poly f,list divisorD,string s) "USAGE: RiemannRochHess(f,divisorD,s); f polynomial, divisorD list, s string NOTE: All fractional ideals must represented by a list of size two. The first element is an ideal of k[x,y] and the second element the common denominator, i.e, a polynomial of k[x]. ASSUME: The base ring R must be a ring in two variables, say x,y, or three variables, say x,y,z. If nvars(R) = 2: - f is an absolutely irreducible polynomial, monic as a polynomial in y. - List divisorD describes a divisor D of F = Quot(k[x,y]/f). If (s = "ideals") D is given in ideal representation, i.e., divisorD is a list of size 2. divisorD[1] is the finite ideal of D, i.e., the fractional ideal of D of IntCl(k[x],F). divisorD[2] is the infinite ideal of D, i.e, the fractional ideal of D of IntCl(k[1/x],F). If (s = "free") D is given in free representation, i.e., divisorD is a list of size 2, containing the finite and infinite places of D with exponents. divisorD[i], i = 1,2, is a list. Each element of the list is again a list. The first entry is a fractional ideal, and the second an integer, the exponent of the place. If nvars(R) = 3: - f is an absolutely irreducible homogeneous polynomial describing the projective plane curve corresponding to the function field F. We assume that the dehomogenization of f w.r.t. z is monic as a polynomial in y. List divisorD describes a divisor D of F. If (s = "ideals") D is given in ideal representation, i.e., divisorD is a list of size 2. divisorD[1] is an ideal of the base ring representing the positive divisor of D and divisorD[2] is an ideal of the base ring representing the negative divisor. (i.e. D = (I) -(J)). If (s = "free") D is given in free representation, i.e., divisorD is a list of places of D. D[i][1] is an prime ideal and D[i][2] an integer, the exponent of the place. RETURN: A vector space basis of the Riemann-Roch space of D, stored in a list RRBasis. The list RRBasis contains a list, say rbasis, and a polynomial, say den. The basis of L(D) consists of all rational functions g/den, where g is an element of rbasis. EXAMPLE: exampleRiemannRochHess; shows an example " { int i,j; if ( (nvars(basering) != 2) && (nvars(basering) != 3) ) { ERROR("Basering must have two or three variables."); } int pr; // the affine case - no transformation needed if (nvars(basering) == 2) { def R_aff = basering; poly f_aff = f; } //the projective case, dehomogenize the input polynomial //and change to the affine ring if (nvars(basering) == 3) { if (homog(f)==0) { ERROR("Input polynomial must be homogeneous."); } pr = 1; def R = basering; list rlpr = ringlist(R); rlpr[2] = list(var(1),var(2)); rlpr[3] = list(list("dp",1:2),list("C",0)); def R_aff = ring(rlpr); // corresponding affine ring poly f_aff = subst(f,var(3),1); setring R_aff; poly f_aff = imap(R,f_aff); } //Checking assumptions ////////////////////////////////////////////////////////////// // No parameters or algebraic numbers are allowed. if(npars(R_aff) >0) { ERROR("No parameters or algebraic extensions are allowed in the base ring."); } // The polynomial f must be monic in the 2-th variable. matrix cs = coeffs(f_aff, var(2)); if(cs[size(cs),1] != 1) { ERROR("The input polynomial must be monic as a polynomial in the second variable."); } // The polynomial f must be irreducible. if (char(R_aff) == 0) { if(isIrreducible(f_aff) == 0) { ERROR("The input polynomial must be irreducible."); } } //Defining ring for the reduction //////////////////////////////////////////////////////////// list rl=ringlist(R_aff); rl[2] = list(var(1)); rl[3] = list(list("lp",1),list("C",0)); def Rone = ring(rl); //Compute the integral bases //////////////////////////////////////////////////////////// //integral basis of IntCL(k[x],F); list FinBasis = integralBasis(f_aff,2); // integral basis of IntCL(k[1/x],F) list Infin; list InfBasis; if(pr) // computes the geometric places of infinity as well { Infin = maxorderInfinite(f_aff,1); InfBasis = Infin[1]; } else { list Infin = maxorderInfinite(f_aff); InfBasis = Infin[1]; } if (printlevel >= 3) { "Integral basis of the maximal finite order:","";FinBasis;pause();""; "Integral basis of the maximal infinite order:";"";InfBasis;pause();""; } //Compute the Ideal representation //////////////////////////////////////////////////////////// list Fin, Inf; if ( s == "ideals") // the divisor is given by two ideals { if(pr == 1) // geometric case: the divisor is given by two homogeneous // ideals I,J representing two effective divisors, // transform the divisor in two fractional ideals // Fin and Inf { setring R; list FinBasis = imap(R_aff,FinBasis); list Infin = imap(R_aff,Infin); // the transformed divisor divisorD = divisorTrans(f,divisorD,FinBasis,Infin,"ideals"); setring R_aff; list divisorD = imap(R,divisorD); } Fin = divisorD[1]; Inf = divisorD[2]; } if (s == "free") // the divisor is given by a list of places { if (pr) { setring R; list FinBasis = imap(R_aff,FinBasis); list Infin = imap(R_aff,Infin); divisorD = divisorTrans(f,divisorD,FinBasis,Infin,"free"); setring R_aff; list divisorD = imap(R,divisorD); } // computes the ideal representation from the free rep. divisorD = Free2IdealRepresentation(f_aff,FinBasis,InfBasis,divisorD); Fin = divisorD[1]; Inf = divisorD[2]; } //Compute free bases for I and J //////////////////////////////////////////////////////////// Fin = freeGenerators(f_aff,FinBasis,Fin,1); Inf = freeGenerators(f_aff,InfBasis,Inf,2); if (printlevel >= 3) { "Integral basis of the finite ideal I:";"";Fin;pause();""; "Integral basis of the infinite ideal J:";"";Inf;pause();""; } //Compute free bases for I^(-1) and J^(-1) //////////////////////////////////////////////////////////// Fin = inverseIdeal(f_aff,FinBasis,Fin,1); Inf = inverseIdeal(f_aff,InfBasis,Inf,2); if (printlevel >= 3) { "Integral basis of the inverse ideal of I:";"";Fin;pause();""; "Integral basis of the inverse ideal of J:";"";Inf;pause();""; } //Compute the transition matrix //////////////////////////////////////////////////////////// list T = transmatrix(f_aff,Inf,Fin); //Reduce the transition matrix //////////////////////////////////////////////////////////// setring Rone; list T = imap(R_aff,T); poly denT = T[2]; list reducedT = redmatrix(T[1]); matrix redT = reducedT[1]; //reduced matrix matrix trafoT = reducedT[2]; // transformation matrix //Compute the k[x]-invariants d_j //////////////////////////////////////////////////////////// list Dcoef = computeInvariants(redT,denT); if (printlevel >= 3) { "List of k[x]-invariants:";"";Dcoef;pause();""; } //Compute the transformed basis of I^(-1) //////////////////////////////////////////////////////////// setring R_aff; matrix trafoT = imap(Rone,trafoT); // compute the basis // (v_1,...,v_n) = ((v_1)',...,(v_n)')*trafoT, // where {v_i} basis of I^(-1) list final = multiplyMatrixList(trafoT,Fin[1]); if (printlevel >= 3) { "Transformed basis of I^(-1):";"";list(final,Fin[2]);pause();""; } //Compute a k-basis of L(D) //////////////////////////////////////////////////////////// number lcDen = leadcoef(Fin[2]); list rrbasis; int counter; poly ftemp; for (i=1;i<=size(Dcoef);i++) { for (j=0; j<=(-Dcoef[i]); j++) { counter++; ftemp = (var(1)^j*final[i])/lcDen; ftemp = ftemp*(1/content(ftemp)); rrbasis[counter]= ftemp; } } list RRbasis = rrbasis, Fin[2]/lcDen; if (pr) { setring R; list RRbasis = imap(R_aff,RRbasis); return(RRbasis); } return(RRbasis); } example { "EXAMPLE:"; echo=2; ring R = 0,(x,y),dp; poly f = y^2*(y-1)^3-x^5; list A1 = list(ideal(x,y-1),1),2; list A2 = list(ideal(y^2-y+1,x),1),3; list A3 = list(ideal(1,y-x),x),-2; list D = A1,A2; list E = list(A3); RiemannRochHess(f,list(D,E),"free"); ring S = 0,(x,y,z),dp; poly f = y^2*(y-1)^3-x^5; f = homog(f,z); ideal P1 = x,y-z; ideal P2 = y^2-yz+z^2,x; ideal P3 = x-y,z; list B1 = P1,2; list B2 = P2,3; list B3 = P3,-2; list Ddivisor = B1,B2,B3; RiemannRochHess(f,Ddivisor,"free"); ideal I = intersect(P1^2,P2^3); ideal J = P3^2; RiemannRochHess(f,list(I,J),"ideals"); } //////////////////////////////////////////////////////////////////// ///////////////////// Essential Static Procedures ////////////////// //_________________________________________________________________ static proc matrixrep(poly f,list intbasis,list A) "USAGE: matrixrep(f,intbasis,A);f poly,intbasis list,A list ASSUME: The base ring R must be a ring in two variables, say x,y, and f must be monic as polynomial in the second variable. List intbasis contains an integral basis (w1,...,wn) of IntCl(k[x],F) or of IntCl(k[1/x],F). List A contains two polynomials which represent an element of Quot(R[x]). RETURN: A list, say repmatrix, containing two elements. repmatrix[1] is a matrix, say M, with entries in k[x], and repmatrix[2] a polynomial, say d, such that M_a := M/d is a representation matrix of a, i.e. a*(w1,..,wn) = (w1,..,wn)*M_a " { def Rbase = basering; list rl = ringlist(Rbase); rl[2] = list(var(2), var(1)); rl[3] = list(list("lp",1:2),list("C",0)); def Rreduction = ring(rl); // make var(2) > var(1) rl = ringlist(Rbase); rl[1] = list(char(Rbase),list(var(1)),list(list("dp",1)),ideal(0)); rl[2] = list(var(2)); rl[3] = list(list("dp",1),list("C",0)); def QF = ring(rl); // make var(1) transcendental int i,j,k,l; ideal IntBasis = intbasis[1]; poly d = intbasis[2]; int sizeIntBasis = size(IntBasis); setring Rreduction; //var(2) > var(1) list A = imap(Rbase,A); ideal IntBasis = imap(Rbase,IntBasis); ideal fred = std(imap(Rbase,f)); IntBasis = reduce(IntBasis,fred); //coeffiecient matrix w. r. t. the integral basis matrix M = coeffs(IntBasis,var(1)); setring QF; matrix M = imap(Rreduction,M); poly d = imap(Rbase,d); // coefficient matrix with denominator M = 1/d*M; // inverse of the coefficient matrix list L = luinverse(M); setring Rreduction; list multiA; for(i = 1;i<=sizeIntBasis;i++) { multiA[i] = reduce(A[1]*IntBasis[i],fred); } // coefficient matrix w.r.t. A[1]*IntBasis matrix multiM = coeffs(ideal(multiA[1..sizeIntBasis]),var(1)); // for positive characteristic - necessary if all coefficients // reduce to zero if (nrows(multiM)!= sizeIntBasis || ncols(multiM)!= sizeIntBasis) { multiM = zerosM(sizeIntBasis); } setring QF; list A = imap(Rbase,A); matrix multiM = imap(Rreduction,multiM); // multiply the both coefficient matrices matrix D = L[2]*multiM; D = 1/(d*A[2])*D; number a = contentMatrix(D); number numera = numerator(a); number denoma = denominator(a); D = (1/a)*D; setring Rbase; matrix D = imap(QF,D); poly numera = imap(QF,numera); poly denoma = imap(QF,denoma); number lcd= leadcoef(denoma); list repmatrix; repmatrix = list((numera/lcd)*D,denoma/lcd); return(repmatrix); } //__________________________________________________________________ static proc freeGenerators(poly f,list intbasis,list fracIdeal,int opt) "USAGE: freeGenerators(f,intbasis,fracIdeal,opt); f polynomial, intbasis list, fracIdeal list, opt integer ASSUME: The base ring R must be a ring in two variables, say x,y, and f must be monic as polynomial in the second variable. List intbasis contains an integral basis of: - IntCl(k[x],F), if opt = 1; - IntCl(k[1/x],F), if opt = 2; List fracIdeals contains two elements, an ideal I and a polynomial d representing the fractional ideal I/d RETURN: List of size 2, say freeGens, where freeGens[1] is an ideal J and freeGens[2] a polynomial D such that J[1]/D, ..., J[n]/D is a basis of I/d as free k[x]-(opt = 1) resp. k[1/x]-module (opt = 2) " { def Rbase = basering; list rl = ringlist(Rbase); rl[3] = list(list("C",1:2),list("dp",0)); def Rhermite = ring(rl); rl = ringlist(Rbase); rl[2] = list(var(1)); rl[3] = list(list("lp",1),list("C",0)); def Ronevar = ring(rl); // only one variable int i,j,k; ideal I = fracIdeal[1]; list T,polynomialT,denominatorT; for(i=1; i<=size(I);i++) { // compute representation matrices for every generator of I T[i] = matrixrep(f,intbasis,list(I[i],fracIdeal[2])); // list containing only the polynomial matrices polynomialT[i] = T[i][1]; // list containing the corresponding denominators denominatorT[i] = poly(T[i][2]); } poly commonden = lcm(denominatorT[1..size(denominatorT)]); for(i=1; i<=size(polynomialT);i++) { // multiply with common denominator polynomialT[i] = (commonden/denominatorT[i])*polynomialT[i]; } matrix M = concat(polynomialT); if (opt == 1) // compute a k[x]-basis { setring Rhermite; matrix M = imap(Rbase,M); // compute n generators of the big rep. matrix via Groebner basis module Mfinal = std(module(M)); setring Rbase; module Mfinal = imap(Rhermite,Mfinal); matrix P = Mfinal; } else // compute a k[1/x]-basis { list P1 = normalFormInf(list(M,commonden),"free"); matrix P = P1[1]; commonden = P1[2]; } ideal IB = intbasis[1]; list Z = multiplyMatrixList(P,IB); ideal J = ideal(Z[1..size(IB)]); poly gcdJ = idealGcd(J); poly D = intbasis[2]*commonden; poly comgcd = gcd(gcdJ,D); // cancel out common divisor J = J/comgcd; D = D/comgcd; list freeGens = J,D; return(freeGens); } //___________________________________________________________________ static proc inverseIdeal(poly f,list intbasis,list fracIdeal,int opt) "USAGE: inverseIdeal(f,intbasis,fracIdeal,opt); f polynomial, intbasis list, A list, opt integer ASSUME: The base ring R must be a ring in two variables, say x,y, and f must be monic as polynomial in the second variable. List intbasis contains an integral basis of: - IntCl(k[x],F), if opt = 1; - IntCl(k[1/x],F), if opt = 2; List fracIdeal contains two elements, an ideal I and a polynomial d representing the fractional ideal I/d RETURN: A list inverseId of size 2. inverseId[1] contains an ideal, say J, inverseId[2] a polynomial, say D. Then J/D is a free k[x]- (opt = 1) resp. k[1/x]-basis (opt = 2) for the inverse ideal of I/d " { def Rbase = basering; list rl = ringlist(Rbase); rl[2] = list(var(2), var(1)); rl[3] = list(list("lp",1:2),list("C",0)); def Rreduction = ring(rl); // make var(2) > var(1) rl = ringlist(Rbase); rl[2] = list(var(1)); rl[3] = list(list("c",0),list("lp",1)); def Rhelp = ring(rl); // ring with one variable, need for Hermite Normal Form rl = ringlist(Rbase); rl[1] = list(char(Rbase),list(var(1)),list(list("dp",1)),ideal(0)); rl[2] = list(var(2)); rl[3] = list(list("dp",1),list("C",0)); def QF = ring(rl); // make var(1) transcendental int i,j; ideal I = fracIdeal[1]; list T,polynomialT,denominatorT; for(i=1; i<=size(I);i++) { T[i] = matrixrep(f,intbasis,list(I[i],fracIdeal[2])); polynomialT[i] = transpose(T[i][1]); denominatorT[i] = poly(T[i][2]); } poly commonden = lcm(denominatorT[1..size(denominatorT)]); for(i=1; i<=size(polynomialT);i++) { polynomialT[i] = (commonden/denominatorT[i])*polynomialT[i]; } // as in freeGenerators: compute big representation matrix matrix M = concat(polynomialT); if (opt == 1) // inverse ideal in ICl(k[x],F) { setring Rhelp; matrix M = imap(Rbase,M); // computes Hermite Normal Form of the matrix via Groebner basis module TM = std(module(M)); setring Rbase; matrix TM = imap(Rhelp,TM); M = transpose(TM); } else // inverse idal in ICl(K[1/x],F) { list P1 = normalFormInf(list(M,commonden),"inverse"); M = P1[1]; commonden = P1[2]; } ideal IB = intbasis[1]; list Minverse = inverse_B(M); setring QF; list Minverse = imap(Rbase,Minverse); poly commonden = imap(Rbase,commonden); ideal IB = imap(Rbase,IB); matrix invM = (commonden/Minverse[2])*Minverse[1]; ideal Z; poly contZ; int n = size(IB); for (i=1; i<=n; i++) { Z[i]=0; for(j=1; j<=n; j++) { Z[i] = Z[i] + IB[j]*invM[j,i]; } } matrix Z1[1][n] = Z; number a = contentMatrix(Z1); number numera = numerator(a); number denoma = denominator(a); Z = (1/a)*Z; setring Rbase; ideal Z = imap(QF,Z); poly numera = imap(QF,numera); poly denoma = imap(QF,denoma); list inverseId; poly D = gcd(numera,poly(intbasis[2])); inverseId = list(Z*(numera/D),(intbasis[2]/D)*denoma); return(inverseId); } //__________________________________________________________________ static proc transmatrix(poly f,list A,list B) "USAGE: transmatrix(f,A,B); f polynomial, A list, B list ASSUME: The base ring R must be a ring in two variables, say x,y, and f must be monic as polynomial in the second variable. List A (resp. B) consists of two elements. A[1] (resp. B[1]) a list of n elements of k[x], A[2] (resp. B[2]) common denominators such that the corresponding fractions are k(x)-linear independent RETURN: List transm of size 2. transm[1] is a matrix with entries in k[x], say M, and transm[2] a polynomial in k[x], say D, such that (M/D) is the transition matrix from A to B, i.e, A[1]/A[2]*(M/D) = B[1]/B[2] " { def Rbase = basering; list rl = ringlist(Rbase); rl[2] = list(var(2), var(1)); rl[3] = list(list("lp",1:2),list("C",0)); def Rreduction = ring(rl); // make var(2) > var(1) rl = ringlist(Rbase); rl[1] = list(char(Rbase),list(var(1)),list(list("dp",1)),ideal(0)); rl[2] = list(var(2)); rl[3] = list(list("dp",1),list("C",0)); def QF = ring(rl); // make var(1) transcendental ideal a = A[1]; ideal b = B[1]; setring Rreduction; ideal a = imap(Rbase,a); ideal b = imap(Rbase,b); ideal fred = std(imap(Rbase,f)); a = reduce(a,fred); b = reduce(b,fred); // coefficient matrices w.r.t. 1,...,y^(n-1) matrix M_a = coeffs(a,var(1)); matrix M_b = coeffs(b,var(1)); setring QF; list A = imap(Rbase,A); list B = imap(Rbase,B); matrix M_a = imap(Rreduction,M_a); matrix M_b = imap(Rreduction,M_b); poly d_a = A[2]; poly d_b = B[2]; matrix N_a = 1/d_a*M_a; matrix N_b = 1/d_b*M_b; list L = luinverse(N_a); matrix M = L[2]*N_b; number cont = contentMatrix(M); number numer = numerator(cont); number denom = denominator(cont); M = (1/cont)*M; setring Rbase; matrix M = imap(QF,M); poly numer = imap(QF,numer); poly denom = imap(QF,denom); list transm; transm = numer*M,denom; return(transm); } //___________________________________________________________________ static proc maxorderInfinite(poly f, int #) "USAGE: maxorderInfinite(f[,#]); f polynomial, # integer ASSUME: The base ring must be a ring in two variables, say x,y. - f is an irreducible polynomial and the second variable describes the integral element, say y. The degree of f in y is n. - optional integer #. If # is given, then # = 1 and the infinite places of the function field F are computed if Kummer's theorem applies. RETURN: - If # is not given: A list InfBasis of size 1. InfBasis[1] contains an integral basis of IntCl(k[1/x],F), stored in a list with n = [F:k(x)] elements and a common denominator. - If # = 1: A list InfBasis of size 3. InfBasis[1] contains an integral basis of IntCl(k[1/x],F). InfBasis[2] is an integer k. If we set f1 = t^(kn)*f(1/t,y) and define u = y*t^k, then f1 is a monic polynomial in u with coefficients in k[t]. InfBasis[3] a list containing the infinite places of the function field, if the compuation was possible. Else the list is empty. " { def Rbase = basering; int k,l,i; //Necessary rings for substitution ////////////////////////////////////////////////////////////////// list rl = ringlist(Rbase); rl[1] = list(char(Rbase),list("t"),list(list("dp",1)),ideal(0)); rl[2] = list(var(1),var(2),"u"); rl[3] = list(list("dp",1:3),list("C",0)); def Rnew = ring(rl); rl = ringlist(Rbase); rl[2] = list("t","u"); def Rintegral = ring(rl); // ring with the new two variables, for the computation of the integral basis //two additional rings needed for changing t,u back to x,y rl = ringlist(Rbase); rl[2] = list(var(1),var(2),"t","u"); rl[3] = list(list("dp",1:4),list("C",0)); def Rhelp = ring(rl); rl = ringlist(Rbase); rl[1] = list(char(Rbase),list(var(1)),list(list("dp",1)),ideal(0)); rl[2] = list(var(2),"t","u"); rl[3] = list(list("dp",1:3),list("C",0)); def Rhelp1 = ring(rl); //Substitute the variables ////////////////////////////////////////////////////////////////// setring Rnew; //1 additional parameter, 1 add. variable poly f = imap(Rbase,f); poly f1 = subst(f,var(1),(1/t)); // subst. x by 1/t matrix Cf = coeffs(f,var(2)); int n = nrows(Cf)-1; // degree of f in y list degs; for(i=1; i<=n; i++) { // f = y^n + a_(n-1)(x)*y^(n-1)+.... degs[i] = list(i-1,deg(Cf[i,1])); // degs[i] =[i,deg(a_i(x))] } // find the minimum multiple of n such that t^(k*n)*f(1/t,y) // is monic after replacing y*t^k by u while (l==0) { l=1; k=k+1; for(i=1; i<=size(degs); i++) { if(degs[i][2] != -1) // if (a_i(x) != 0) { if((k*n-degs[i][2])<(k*degs[i][1])) { l=0; break; } } } } f1 = f1*t^(k*n); poly v = u/(t^k); poly fintegral = subst(f1,var(2),v); // replace y by u/t^k // compute integral basis of the new polynomial in t,u setring Rintegral; poly fintegral = imap(Rnew,fintegral); list Z = integralBasis(fintegral,2); //Check if Kummer's Theorem apply ////////////////////////////////////////////////////////////////// if (# == 1) { poly fInfinity = substitute(fintegral,t,0); list factors = factorize(fInfinity,2); list degsinf = factors[2]; int kum = 1; for (i=1; i<=size(degsinf[1]);i++) { // check if all exponents are 1 if (degsinf[1][i] != 1) { kum = 0; break; } } if (kum == 0) // check if 1,...,y^{n-1} is an integral basis { if (Z[2] == 1) { kum = 1; for (i = 1; i<=size(Z[1]); i++) { if (Z[1][i] != u^(i-1)) { kum = 0; break; } } } } } //Reverse the substitution ////////////////////////////////////////////////////////////////// setring Rnew; // t as parameter, u as variable list Z = imap(Rintegral,Z); ideal IB = Z[1]; poly d = Z[2]; IB = subst(IB,u,var(2)*(t^k)); d = subst(d,u,var(2)*(t^k)); // replace u by y*t^k if (# == 1) { if (kum == 1) { list factors = imap(Rintegral,factors); list Zfacs = factors[1]; ideal I = substitute(ideal(Zfacs[1..size(Zfacs)]),u,var(2)*(t^k)); Zfacs = I[1..size(I)]; } } setring Rhelp; // t as variable ideal IB = imap(Rnew,IB); poly d = imap(Rnew,d); matrix C = coeffs(IB,t); matrix Cden = coeffs(d,t); int p = nrows(C)-1; // maximum degree of IB in t int pden = nrows(Cden)-1; setring Rhelp1; // var(1) as parameter, t as variable ideal IB = imap(Rhelp,IB); poly d = imap(Rhelp,d); matrix Cden = imap(Rhelp,Cden); IB = subst(IB,t,(1/par(1))); // replace t by 1/x d = subst(d,t,(1/par(1))); IB = IB*par(1)^p; d = d*par(1)^pden; //Compute the infinite places ////////////////////////////////////////////////////////////////// if (# == 1) { if (kum == 1) { list Zfacs = imap(Rnew,Zfacs); list pfacs; for (i=1;i<=size(Zfacs);i++) { pfacs[i]=deg(substitute(Zfacs[i],var(1),1)); Zfacs[i]=ideal(Zfacs[i],t); Zfacs[i]=substitute(Zfacs[i],t,(1/par(1))); Zfacs[i]=list(Zfacs[i]*par(1)^pfacs[i],par(1)^pfacs[i]); } } } setring Rbase; ideal IB = imap(Rhelp1,IB); poly d = imap(Rhelp1,d); poly den; if(p >= pden) { den = d*var(1)^(p-pden); } else { IB = IB*var(1)*(pden-p); den = d; } list final = IB,den; if ( # == 1) { list InfPlaces; if (kum == 1) { list Zfacs = imap(Rhelp1,Zfacs); InfPlaces = Zfacs; list InfBasis = final,k,InfPlaces; return(InfBasis); } else { return(final,k,InfPlaces); } } list InfBasis = list(final); return(InfBasis); } //__________________________________________________________________ static proc redmatrix(matrix A) "USAGE: redmatrix(A); A matrix ASSUME: The basering must be a polynomial ring in one variable, say k[x], A a mxn-matrix with entries in k[x] RETURN: A list containing two matrices, say A' and T such that A' is the reduced matrix of A and T the transformation matrix, i.e., A' = A*T. THEORY: Consider the columns of the matrix A as a basis of a lattice. Denote the column degree of the j-th column by deg(j). Create vectors hc(j) in k^m containing the coefficient of the deg(j)-th power of x of column j. A basis is called reduced if the {hc(j)} are linearly independent. If the basis is non-reduced we proceed reduction steps until the above criterion is satisfied. In a reduction step of column j we add a certain k[x]- combination of the other columns to column j, such that the column-degree decreases. " { if (nvars(basering) != 1) { ERROR("The base ring must be a ring in one variables."); } int m = nrows(A); int n = ncols(A); matrix T = unitmat(m); list d; int i,j,counter; int h = 1; int pos, maxd; while(h) { for (j=1; j<=n; j++) { d[j]=colDegree(A,j); } matrix M[m][n]; for (j=1; j<=n; j++) { for (i=1; i<=m; i++) { M[i,j]=coefficientAt(A,j,d[j])[i]; // computes the hc(j) } } module S = M; matrix N = matrix(syz(M)); if(rank(N)==0) // hc(j) are linearly independent { h=0; } else { h = ncols(N); } list ind; list degind; for (j=1; j<=Min(intvec(1,h));j++) // minimum needed to avoid unnecessary first reduction // step in the reduced case { for (i=1; i<= ncols(M); i++) { if(N[i,j]!=0) { counter++; // position of non-zero entry ind[counter]=i; // degree of non-zero entry degind[counter]=d[i]; } } counter = 0; // determine the maximal column degree maxd = Max(degind); i=0; // find the column, where the maximum is attained while(i<=size(degind)) { i=i+1; if (degind[i] == maxd) { pos = i; break; } } pos = ind[pos]; for (i=1;i<=size(ind);i++) { if (ind[i] != pos) { matrix A1=addcol(A,ind[i],N[ind[i],j]/N[pos,j]*var(1)^(maxd-d[ind[i]]),pos); matrix T1=addcol(T,ind[i],N[ind[i],j]/N[pos,j]*var(1)^(maxd-d[ind[i]]),pos); A=A1; T=T1; kill A1; kill T1; } } kill degind,ind; } kill M,N,S; } list final = A,T; return(final); } //__________________________________________________________________ static proc normalFormInf(list K,string sopt) "USAGE: normalFormInf(K,sopt); K list, sopt string ASSUME: The basering must be a polynomial ring in one variable, say k[x]. K is a list of size 2. K[1] is a matrix, say A, with entries in k[x] and K[2] a polynomial, say den. A/den is a matrix with entries in k[1/x]. sopt is either "free" or "inverse" RETURN: A list, say norFormInf, of size 2. norFormInf[1] is a matrix, say M, and norFormInf[2] a polynomial, say D. The matrix M/D is a normal form of the matrix A/den which is needed for the - if (sopt = "free") computation of an int. basis of an ideal of IntCl[k[1/x],F) - if (sopt = "inverse") computation of a int. basis of the inverse of an ideal of IntCl[k[1/x],F) THEORY For computing a normal form with coefficients. in k[1/x] we have to replace 1/x by another variable, compute the normal with the aid of Groebner bases and reverse the substitution. " { def Rbase = basering; //_____________Necessary rings for substitution___________________ list rl = ringlist(Rbase); rl[1] =list(char(Rbase),list("helppar"),list(list("dp",1)),ideal(0)); def QF = ring(rl); // basering with additional parameter helppar rl = ringlist(Rbase); rl[2] = list(var(1),var(2),"helppar"); rl[3] = list(list("dp",1:3),list("C",0)); def Rhelp = ring(rl); // basering with additional variable helppar rl = ringlist(Rbase); rl[2] = list("helppar"); rl[3] = list(list("c",0),list("lp",1)); def Rhelpinv = ring(rl); // ring with one variable, ordering c rl = ringlist(Rbase); rl[2] = list("helppar"); rl[3] = list(list("C",0),list("lp",1)); def Rhelpfree = ring(rl); // ring with one variable, ordering C setring QF; list K = imap(Rbase, K); matrix A = K[1]; poly den = K[2]; matrix A1 = subst(A,var(1),1/helppar); poly den1 = subst(den, var(1),1/helppar); A1 = (1/den1)*A1; // transform into a polynomial matrix with entries // in k[helppar] number a = contentMatrix(A1); number numera = numerator(a); number denoma = denominator(a); A1 = (1/a)*A1; // A1 matrix with entries in k[helppar] setring Rhelp; matrix A1 = imap(QF,A1); poly numera = imap(QF,numera); poly denoma = imap(QF,denoma); number lcd= leadcoef(denoma); A1 = (numera/lcd)*A1; poly den = denoma/lcd; //_____________Compute a normal form___________________ if (sopt == "inverse") { setring Rhelpinv; matrix A1 = imap(Rhelp,A1); module S = std(module(A1)); A1 = S; list mat; int i; int nc = ncols(A1); // change order of columns to obtain a lower triangular // matrix for(i=1; i<=nc; i++) { mat[i]=A1[nc-i+1]; } A1= concat(mat); setring Rhelp; A1 = imap(Rhelpinv,A1); matrix A = transpose(A1); } if (sopt == "free") { setring Rhelpfree; matrix A1 = imap(Rhelp,A1); module S = std(module(A1)); A1 = S; setring Rhelp; matrix A = imap(Rhelpfree,A1); } //_____________Reverse substitution__________________ intvec v = 1; // change variables back from helppar to x def Rpar = vars2pars(v); setring Rpar; poly den = imap(Rhelp,den); matrix A = imap(Rhelp,A); A = subst(A,helppar,1/par(1)); den = subst(den, helppar,1/par(1)); A = (1/den)*A; number a = contentMatrix(A); number numera = numerator(a); number denoma = denominator(a); A = (1/a)*A; setring Rbase; matrix A = imap(Rpar,A); poly numera = imap(Rpar,numera); poly denoma = imap(Rpar,denoma); number lcd= leadcoef(denoma); list final; final = list((numera/lcd)*A,denoma/lcd); return(final); } ////////////////////////////////////////////////////////////////// ///////////////////// AUXILARY STATIC PROCEDURES ///////////////// //_________________________________________________________________ static proc colDegree(matrix A, int j) "USAGE: colDegree(A,j); A matrix, j integer ASSUME: Base ring must be a polynomial ring in one variable, integer j describes a column of A RETURN: A list, containing the maximum degree occurring in the entries of the j-th column of A and the corresponding row " { if(nvars(basering) != 1) { ERROR("The base ring must be a ring in one variables."); } int d; int nc = ncols(A); int nr = nrows(A); if( j< 1 || j>nc) { ERROR("j doesn't describe a column of the input matrix"); } // ideal of the entries of the j-th column ideal I = A[1..nr,j]; matrix C = coeffs(I,var(1)); // maximal degree occurring in the j-th column d = nrows(C)-1; return(d); } //_________________________________________________________________ static proc coefficientAt(matrix A, int j, int e); "USAGE: coefficientAt(A,j,e); A matrix, j,e intger ASSUME: Base ring is polynomial ring in one variable, j describes a column of A, e non-negative integer smaller or equal to the column degree of the j-th column. RETURN: A list Z of the size of the j-th column: - if A[i,j] has a monomial with degree e, the corresponding coefficient is stored in Z[i] - else Z[i] = 0 " { if(nvars(basering) != 1) { ERROR("The base ring must be a ring in one variables."); } int d,i; int nc = ncols(A); int nr = nrows(A); if (j<1 || j>nc) { ERROR("j doesn't describe a column of the input matrix"); } ideal I = A[1..nr,j]; matrix C = coeffs(I,var(1)); d = nrows(C)-1; list Z; if (e>d || e<0) { ERROR("e negative or larger than the maximum degree"); } for (i=1; i<=ncols(C); i++) { Z[i]=C[e+1,i]; } return(Z); } //__________________________________________________________________ static proc computeInvariants(matrix T,poly denT) "USAGE: computeInvariants(T,denT); T matrix, denT polynomial ASSUME: Base ring has one variable,say x, T/denT is square matrix with entries in k(x) RETURN: The k[x]-invariants of T/denT stored in a list. " { list Dcoef; int i,j; int counter_inv; list S; for (j=1; j<=ncols(T); j++) { S=list(); for(i=1; i<=nrows(T); i++) { if (T[i,j] != 0) { counter_inv++; S[counter_inv]= deg(T[i,j])-deg(denT); } } Dcoef[j] = Max(S); counter_inv = 0; } return(Dcoef); } //__________________________________________________________________ static proc contentMatrix(matrix A) "USAGE: contentMatrix(A); A matrix NOTE: Base ring is allowed to have parameters RETURN: The content of all entries of the matrix A " { def Rbase = basering; int nv = nvars(Rbase); list rl = ringlist(Rbase); rl[2][nv + 1] = "helpv"; rl[3] = list(list("dp",1:(nv+1)),list("C",0)); def Rhelp = ring(rl); setring Rhelp; matrix A = imap(Rbase,A); poly contCol; int i; for (i=1; i<=ncols(A); i++) { contCol = contCol+ content(A[i])*(helpv^i); } number contmat = content(contCol); setring Rbase; number contmat = imap(Rhelp,contmat); return(contmat); } //__________________________________________________________________ static proc idealGcd(ideal A) "USAGE: idealGcd(A); A ideal ASSUME: Ideal in the base ring RETURN: The greatest common divisor of the given generators of I { poly med; poly intermed; int i; med = A[1]; for (i=1; i= 0) { if (size(DFinite[i][1][1]) == 2) { Itmp = DFinite[i][1][1][1]^DFinite[i][2], DFinite[i][1][1][2]^DFinite[i][2]; dtmp = DFinite[i][1][2]^DFinite[i][2]; Ltmp = Itmp,dtmp; } else { Ltmp = powerFracIdeal(DFinite[i][1],DFinite[i][2]); } DFinitePos = multiplyFracIdeals(Ltmp,DFinitePos); } else { if (size(DFinite[i][1][1]) == 2) { Itmp = DFinite[i][1][1][1]^(-DFinite[i][2]), DFinite[i][1][1][2]^(-DFinite[i][2]); dtmp = DFinite[i][1][2]^(-DFinite[i][2]); Ltmp = Itmp,dtmp; } else { Ltmp = powerFracIdeal(DFinite[i][1],-DFinite[i][2]); } DFiniteNeg = multiplyFracIdeals(Ltmp,DFiniteNeg); } } for (i=1;i<=size(DInfinite);i++) { if (DInfinite[i][2]>= 0) { if (size(DInfinite[i][1][1]) == 2) { Itmp = DInfinite[i][1][1][1]^DInfinite[i][2], DInfinite[i][1][1][2]^DInfinite[i][2]; dtmp = DInfinite[i][1][2]^DInfinite[i][2]; Ltmp = Itmp,dtmp; } else { Ltmp = powerFracIdeal(DInfinite[i][1],DInfinite[i][2]); } DInfinitePos = multiplyFracIdeals(Ltmp,DInfinitePos); } else { if (size(DInfinite[i][1][1]) == 2) { Itmp = DInfinite[i][1][1][1]^(-DInfinite[i][2]), DInfinite[i][1][1][2]^(-DInfinite[i][2]); dtmp = DInfinite[i][1][2]^(-DInfinite[i][2]); Ltmp = Itmp,dtmp; } else { Ltmp = powerFracIdeal(DInfinite[i][1],-DInfinite[i][2]); } DInfiniteNeg = multiplyFracIdeals(Ltmp,DInfinitePos); } } DFiniteNeg = freeGenerators(f,FinBasis,DFiniteNeg,1); DFiniteNeg = inverseIdeal(f,FinBasis,DFiniteNeg,1); list Fin = multiplyFracIdeals(DFinitePos,DFiniteNeg); DInfiniteNeg = freeGenerators(f,InfBasis,DInfiniteNeg,2); DInfiniteNeg = inverseIdeal(f,InfBasis,DInfiniteNeg,2); list Inf = multiplyFracIdeals(DInfinitePos,DInfiniteNeg); return(list(Fin,Inf)); } //__________________________________________________________________ static proc divisorTrans(poly f,list D,list FinBasis,list Infin, string s) "USAGE: divisorTrans(f,D,FinBasis,Infin,s); f polynomial, D list FinBasis list, Infin list, s string ASSUME: - f is an absolutely irreducible homogeneous polynomial in three variables, say x,y,z, describing a projective curve - string s is either "ideals" or "free" "ideals": list D contains two ideals, say I and J representing a divisor (I) - (J) "free": list D contains lists, each list a place and a exponent - list FinBasis contains an integral basis of IntCl(k[x],F) - list Infin contains an integral basis of IntCl(k[1/x],F), an integer k and the infinite places of F if their computation was possible RETUN: The corresponding divisor on F in ideal representation (needed for the procedure RiemannRochHess). A list of size 2, say divisortrans. If (s = "ideals"), then the transformed divisor is given in ideal representation. If (s = "free"), then the transformed divisor is given in free representation. THEORY: We compute first the places corresponding to affine points on the curve, i.e. the places in the chart (z=1) For the points at infinity (z=0) we allow only non-singular points. " { def Rbase = basering; int i,j; poly f_aff = subst(f,var(3),1); list rl = ringlist(Rbase); rl[2] = list(var(1),var(2)); rl[3] = list(list("dp",1:2),list("C",0)); def R_aff = ring(rl); // corresponding affine ring // list of all infinite places of F list InfPlaces = Infin[3]; InfPlaces = transformPlacesAtInfinity(f,Infin[2],InfPlaces); //list containing the infinite places of the function field // and the corresponding places in the chart z = 0 of // the projective curve if the computation is possible if (s == "ideals") { ideal I = D[1]; ideal J = D[2]; ideal I1,J1; // ideals corresponding to affine points on the curve (z=1) I1 = sat(I,var(3))[1]; J1 = sat(J,var(3))[1]; ideal Ifin = std(subst(I1,var(3),1)); ideal Jfin = std(subst(J1,var(3),1)); // ideals corresponding to points at infinity (z=0) list InfIdeals; list InfPos = ideal(1),1; list InfNeg = ideal(1),1; list InfTmp; int d; ideal Iinf, Jinf; Iinf = sat(I,I1)[1]; Jinf = sat(J,J1)[1]; if (size(InfPlaces) == 0) { "WARNING: Infinite places have not been computed!" } for (i=1;i<=size(InfPlaces);i++) { if(isIncluded(Iinf,InfPlaces[i][1])) { d = sat(Iinf,InfPlaces[i][1])[2]; InfTmp = powerFracIdeal(InfPlaces[i][2],d); InfPos = multiplyFracIdeals(InfPos,InfTmp); } if (isIncluded(Jinf,InfPlaces[i][1])) { d = sat(Jinf,InfPlaces[i][1])[2]; InfTmp = powerFracIdeal(InfPlaces[i][2],d); InfNeg = multiplyFracIdeals(InfNeg,InfTmp); } } list FinPos = Ifin,1; list FinNeg = Jfin,1; FinNeg = freeGenerators(f_aff,FinBasis,FinNeg,1); FinNeg = inverseIdeal(f_aff,FinBasis,FinNeg,1); list Fin = multiplyFracIdeals(FinPos,FinNeg); InfNeg = freeGenerators(f_aff,Infin[1],InfNeg,2); InfNeg = inverseIdeal(f_aff,Infin[1],InfNeg,2); list Inf = multiplyFracIdeals(InfPos,InfNeg); return(list(Fin,Inf)); } if ( s == "free") { list PlacesFin; list PlacesInf; ideal Itemp; int counter_fin,counter_inf; for (i=1;i<=size(D);i++) { if (reduce(var(3),std(D[i][1])) != 0) { counter_fin++; Itemp = subst(D[i][1],var(3),1); PlacesFin[counter_fin] = list(list(Itemp,1),D[i][2]); D = delete(D,i); i=i-1; } } if (size(InfPlaces) == 0) { "WARNING: Infinite places have not been computed!" PlacesInf[1] = list(list(ideal(1),1),1); } else { for (i=1;i<=size(D);i++) { for(j=1;j<=size(InfPlaces);j++) { if (isEqualId(D[i][1],InfPlaces[j][1])) { counter_inf++; PlacesInf[counter_inf] = list(InfPlaces[i][2],D[i][2]); } } } } return(list(PlacesFin,PlacesInf)); } } //___________________________________________________________________ static proc infPlaces (poly f) // from brnoeth.lib { intvec iv; def base_r=basering; ring r_auxz=char(basering),(x,y,z),lp; poly F=imap(base_r,f); poly f_inf=subst(F,z,0); setring base_r; poly f_inf=imap(r_auxz,f_inf); ideal I=factorize(f_inf,1); // points at infinity as homogeneous // polynomials int s=size(I); int i; list IP_S=list(); // for singular points at infinity list IP_NS=list(); // for non-singular points at infinity int counter_S; int counter_NS; poly aux; for (i=1;i<=s;i=i+1) { aux=subst(I[i],y,1); if (aux==1) { // the point is (1:0:0) setring r_auxz; poly f_yz=subst(F,x,1); if ( subst(subst(diff(f_yz,y),y,0),z,0)==0 && subst(subst(diff(f_yz,z),y,0),z,0)==0 ) { // the point is singular counter_S=counter_S+1; kill f_yz; setring base_r; IP_S[counter_S]=ideal(I[i],var(3)); } else { // the point is non-singular counter_NS=counter_NS+1; kill f_yz; setring base_r; IP_NS[counter_NS]=ideal(I[i],var(3)); } } else { // the point is (a:1:0) | a is root of aux if (deg(aux)==1) { // the point is rational and no field extension is needed setring r_auxz; poly f_xz=subst(F,y,1); poly aux=imap(base_r,aux); number A=-number(subst(aux,x,0)); map phi=r_auxz,x+A,0,z; poly f_origin=phi(f_xz); if ( subst(subst(diff(f_origin,x),x,0),z,0)==0 && subst(subst(diff(f_origin,z),x,0),z,0)==0 ) { // the point is singular counter_S=counter_S+1; kill f_xz,aux,A,phi,f_origin; setring base_r; IP_S[counter_S]=ideal(I[i],var(3)); } else { // the point is non-singular counter_NS=counter_NS+1; kill f_xz,aux,A,phi,f_origin; setring base_r; IP_NS[counter_NS]=ideal(I[i],var(3)); } } else { // the point is non-rational and a field extension with // minpoly=aux is needed ring r_ext=(char(basering),@a),(x,y,z),lp; poly aux=imap(base_r,aux); minpoly=number(subst(aux,x,@a)); poly F=imap(r_auxz,F); poly f_xz=subst(F,y,1); map phi=r_ext,x+@a,0,z; poly f_origin=phi(f_xz); if ( subst(subst(diff(f_origin,x),x,0),z,0)==0 && subst(subst(diff(f_origin,z),x,0),z,0)==0 ) { // the point is singular counter_S=counter_S+1; setring base_r; kill r_ext; IP_S[counter_S]=ideal(I[i],var(3)); } else { // the point is non-singular counter_NS=counter_NS+1; setring base_r; kill r_ext; IP_NS[counter_NS]=ideal(I[i],var(3)); } } } } kill r_auxz; return(list(IP_S,IP_NS)); } //__________________________________________________________________ static proc transformPlacesAtInfinity(poly f,int k,list InfPlacesF) "USAGE: transformPlacesAtInfinity(f,k,InfPlacesF); f polynomial, k integer, InfPlaces list ASSUME: The base ring must be a ring in three variables, say x,y,z. - f is a homogeneous polynomial and - integer k such that if we subst. in f1 = t^(kn)*f(1/t,y) y*t^k by u, then f1 is a monic polynomial in u with coefficients in k[t]. - InfPlacesF is a list containing the infinite places of F, if the computation was possible, else empty RETURN: A list, say places. - If the computation of the infinite places of F was not possible, then places is empty. - Else, places is list of size m, where m is the number of infinite places of F. places[i] is a list of size 2. places[i][1] an geometric place at infinity, i.e. a point in the chart z = 0, and places[i][2] the corresponding infinite place of F. " { list places; // Kummer's Theorem does not apply // no computation of places at infinity possible if (size(InfPlacesF) == 0) { return(places); } // compute the places of f at z = 0 list InfGeo = infPlaces(f); // no singular places at infinity allowed if ( size(InfGeo[1]) != 0 ) { return(places); } // non-singular places list NSPlaces = InfGeo[2]; if (size(NSPlaces) != size(InfPlacesF)) { ERROR("number of infinite places must be the same"); } int i,j; int d, degtmp; ideal Itemp; list Ltemp; if (size(NSPlaces) == 1) { places[1] = list(NSPlaces[1], InfPlacesF[1]); } else { for (i = 1; i<=size(NSPlaces); i++) { if (reduce(var(1),std(NSPlaces[i])) == 0) // (x,z) is a place at infinity { d = 1; Itemp = NSPlaces[i]; // put it on the end of the list NSPlaces[i] = NSPlaces[size(NSPlaces)]; NSPlaces[size(NSPlaces)] = Itemp; break; } } if (d == 0) // (x,z) is not a place at infinity, simply transform the places { for (i = 1; i<= size(NSPlaces); i++) { Itemp = NSPlaces[i]; degtmp = deg(Itemp[1]); Itemp = Itemp[1], var(1)^(k*degtmp -1); Ltemp = Itemp,var(1)^(k*degtmp); places[i] = list(NSPlaces[i],Ltemp); } } else //(x,z) is a place at infinity, no directly transformation // is possible - transform first the other places, the remaining // places must be (x,z) { for (i = 1; i < size(NSPlaces); i++) { Itemp = NSPlaces[i]; degtmp = deg(Itemp[1]); Itemp = Itemp[1], var(1)^(k*degtmp -1); Ltemp = Itemp,var(1)^(k*degtmp); for (j = 1; j <= size(InfPlacesF); j++) { if (Ltemp[2] == InfPlacesF[j][2]) { if (isEqualId(Ltemp[1], InfPlacesF[j][1])) { places[i] = list(NSPlaces[i], Ltemp); InfPlacesF = delete(InfPlacesF,j); } } } } if (size(InfPlacesF) != 1) { ERROR("more than 1 place left - wrong transformation"); } places[size(NSPlaces)] = list(ideal(x,z),InfPlacesF[1]); } } return(places); } singular-4.0.3+ds/Singular/LIB/hnoether.lib000066400000000000000000004621161266270727000204650ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version hnoether.lib 4.0.0.0 Jun_2013 "; // $Id: 1e5aa570b5053f49874c3a563790bb1fbc786a5b $ category="Singularities"; info=" LIBRARY: hnoether.lib Hamburger-Noether (Puiseux) Expansion AUTHORS: Martin Lamm, lamm@mathematik.uni-kl.de Christoph Lossen, lossen@mathematik.uni-kl.de OVERVIEW: A library for computing the Hamburger-Noether expansion (analogue of Puiseux expansion over fields of arbitrary characteristic) of a reduced plane curve singularity following [Campillo, A.: Algebroid curves in positive characteristic, Springer LNM 813 (1980)]. @* The library contains also procedures for computing the (topological) numerical invariants of plane curve singularities. PROCEDURES: hnexpansion(f [,\"ess\"]); Hamburger-Noether (HN) expansion of f develop(f [,n]); HN expansion of irreducible plane curve germs extdevelop(hne,n); extension of the H-N expansion hne of f param(hne [,s]); parametrization of branches described by HN data displayHNE(hne); display HN expansion as an ideal invariants(hne); invariants of f, e.g. the characteristic exponents displayInvariants(hne); display invariants of f multsequence(hne); sequence of multiplicities displayMultsequence(hne); display sequence of multiplicities intersection(hne1,hne2); intersection multiplicity of two local branches is_irred(f); test whether f is irreducible as power series delta(f); delta invariant of f newtonpoly(f); (local) Newton polygon of f is_NND(f); test whether f is Newton non-degenerate stripHNE(hne); reduce amount of memory consumed by hne puiseux2generators(m,n); convert Puiseux pairs to generators of semigroup separateHNE(hne1,hne2); number of quadratic transf. needed for separation squarefree(f); a squarefree divisor of the polynomial f allsquarefree(f,l); the maximal squarefree divisor of the polynomial f further_hn_proc(); show further procedures useful for interactive use KEYWORDS: Hamburger-Noether expansion; Puiseux expansion; curve singularities "; // essdevelop(f); HN expansion of essential branches // multiplicities(hne); multiplicities of blowed up curves /////////////////////////////////////////////////////////////////////////////// LIB "primitiv.lib"; LIB "inout.lib"; LIB "sing.lib"; /////////////////////////////////////////////////////////////////////////////// proc further_hn_proc() "USAGE: further_hn_proc(); NOTE: The library @code{hnoether.lib} contains some more procedures which are not shown when typing @code{help hnoether.lib;}. They may be useful for interactive use (e.g. if you want to do the calculation of an HN development \"by hand\" to see the intermediate results), and they can be enumerated by calling @code{further_hn_proc()}. @* Use @code{help ;} for detailed information about each of them. " { " The following procedures are also part of `hnoether.lib': getnm(f); intersection pts. of Newton polygon with axes T_Transform(f,Q,N); returns f(y,xy^Q)/y^NQ (f: poly, Q,N: int) T1_Transform(f,d,M); returns f(x,y+d*x^M) (f: poly,d:number,M:int) T2_Transform(f,d,M,N,ref); a composition of T1 & T koeff(f,I,J); gets coefficient of indicated monomial of polynomial f redleit(f,S,E); restriction of monomials of f to line (S-E) leit(f,n,m); special case of redleit (for irred. polynomials) testreducible(f,n,m); tests whether f is reducible charPoly(f,M,N); characteristic polynomial of f find_in_list(L,p); find int p in list L get_last_divisor(M,N); last divisor in Euclid's algorithm factorfirst(f,M,N); try to factor f without `factorize' factorlist(L); factorize a list L of polynomials referencepoly(D); a polynomial f s.t. D is the Newton diagram of f"; // static procedures not useful for interactive use: // polytest(f); tests coefficients and exponents of polynomial f // extractHNEs(H,t); extracts output H of HN to output of hnexpansion // HN(f,grenze); recursive subroutine for hnexpansion // constructHNEs(...); subroutine for HN } example { echo=2; further_hn_proc(); } /////////////////////////////////////////////////////////////////////////////// proc getnm (poly f) "USAGE: getnm(f); f bivariate polynomial RETURN: intvec(n,m) : (0,n) is the intersection point of the Newton polygon of f with the y-axis, n=-1 if it doesn't exist (m,0) is its intersection point with the x-axis, m=-1 if this point doesn't exist ASSUME: ring has ordering `ls' or `ds' EXAMPLE: example getnm; shows an example " { // assume being called by develop ==> ring ordering is ls (ds would also work) return(ord(subst(f,var(1),0)),ord(subst(f,var(2),0))); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),ds; poly f = x5+x4y3-y2+y4; getnm(f); } /////////////////////////////////////////////////////////////////////////////// proc leit (poly f, int n, int m) "USAGE: leit(f,n,m); poly f, int n,m RETURN: all monomials on the line from (0,n) to (m,0) in the Newton diagram EXAMPLE: example leit; shows an example " { return(jet(f,m*n,intvec(n,m))-jet(f,m*n-1,intvec(n,m))) } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),ds; poly f = x5+x4y3-y2+y4; leit(f,2,5); } /////////////////////////////////////////////////////////////////////////////// proc testreducible (poly f, int n, int m) "USAGE: testreducible(f,n,m); f poly, n,m int RETURN: 1 if there are points in the Newton diagram below the line (0,n)-(m,0) 0 else EXAMPLE: example testreducible; shows an example " { return(size(jet(f,m*n-1,intvec(n,m))) != 0) } example { "EXAMPLE:"; echo = 2; ring rg=0,(x,y),ls; testreducible(x2+y3-xy4,3,2); } /////////////////////////////////////////////////////////////////////////////// proc T_Transform (poly f, int Q, int N) "USAGE: T_Transform(f,Q,N); f poly, Q,N int RETURN: f(y,xy^Q)/y^NQ if x,y are the ring variables NOTE: this is intended for irreducible power series f EXAMPLE: example T_Transform; shows an example " { map T = basering,var(2),var(1)*var(2)^Q; return(T(f)/var(2)^(N*Q)); } example { "EXAMPLE:"; echo = 2; ring exrg=0,(x,y),ls; export exrg; T_Transform(x3+y2-xy3,1,2); kill exrg; } /////////////////////////////////////////////////////////////////////////////// proc T1_Transform (poly f, number d, int Q) "USAGE: T1_Transform(f,d,Q); f poly, d number, Q int RETURN: f(x,y+d*x^Q) if x,y are the ring variables EXAMPLE: example T1_Transform; shows an example " { map T1 = basering,var(1),var(2)+d*var(1)^Q; return(T1(f)); } example { "EXAMPLE:"; echo = 2; ring exrg=0,(x,y),ls; export exrg; T1_Transform(y2-2xy+x2+x2y,1,1); kill exrg; } /////////////////////////////////////////////////////////////////////////////// proc T2_Transform (poly f_neu, number d, int M, int N, poly refpoly) "USAGE: T2_Transform(f,d,M,N,ref); f poly, d number; M,N int; ref poly RETURN: list: poly T2(f,d',M,N), number d' in \{ d, 1/d \} ASSUME: ref has the same Newton polygon as f (but can be simpler) for this you can e.g. use the proc `referencepoly' or simply f again COMMENT: T2 is a composition of T_Transform and T1_Transform; the exact definition can be found in Rybowicz: `Sur le calcul des places ...' or in Lamm: `Hamburger-Noether-Entwicklung von Kurvensingularitaeten' SEE ALSO: T_Transform, T1_Transform, referencepoly EXAMPLE: example T2_Transform; shows an example " { //---------------------- compute gcd and extgcd of N,M ----------------------- int ggt=gcd(M,N); M=M div ggt; N=N div ggt; list ts=extgcd(M,N); int tau,sigma=ts[2],-ts[3]; int s,t; poly xp=var(1); poly yp=var(2); poly hilf; if (sigma<0) { tau=-tau; sigma=-sigma;} // es gilt: 0<=tau<=N, 0<=sigma<=M, |N*sigma-M*tau| = 1 = ggT(M,N) if (N*sigma < M*tau) { d = 1/d; } //--------------------------- euklid. Algorithmus ---------------------------- int R; int M1,N1=M,N; for ( R=M1%N1; R!=0; ) { M1=N1; N1=R; R=M1%N1;} int Q=M1 div N1; map T1 = basering,xp,yp+d*xp^Q; map Tstar=basering,xp^(N-Q*tau)*yp^tau,xp^(M-sigma*Q)*yp^sigma; if (defined(HNDebugOn)) { "Trafo. T2: x->x^"+string(N-Q*tau)+"*y^"+string(tau)+", y->x^" +string(M-sigma*Q)+"*y^"+string(sigma); "delt =",d,"Q =",Q,"tau,sigma =",tau,sigma; } //------------------- Durchfuehrung der Transformation T2 -------------------- f_neu=Tstar(f_neu); refpoly=Tstar(refpoly); //--- dividiere f_neu so lange durch x & y, wie die Division aufgeht, // benutze ein Referenzpolynom mit gleichem Newtonpolynom wie f_neu zur // Beschleunigung: --- for (hilf=refpoly/xp; hilf*xp==refpoly; hilf=refpoly/xp) {refpoly=hilf; s++;} for (hilf=refpoly/yp; hilf*yp==refpoly; hilf=refpoly/yp) {refpoly=hilf; t++;} f_neu=f_neu/(xp^s*yp^t); return(list(T1(f_neu),d)); } example { "EXAMPLE:"; echo = 2; ring exrg=0,(x,y),ds; export exrg; poly f=y2-2x2y+x6-x5y+x4y2; T2_Transform(f,1/2,4,1,f); T2_Transform(f,1/2,4,1,referencepoly(newtonpoly(f,1))); // if size(referencepoly) << size(f) the 2nd example would be faster referencepoly(newtonpoly(f,1)); kill exrg; } /////////////////////////////////////////////////////////////////////////////// proc koeff (poly f, int I, int J) "USAGE: koeff(f,I,J); f bivariate polynomial, I,J integers RETURN: if f = sum(a(i,j)*x^i*y^j), then koeff(f,I,J)= a(I,J) (of type number) NOTE: J must be in the range of the exponents of the 2nd ring variable EXAMPLE: example koeff; shows an example " { matrix mat = coeffs(coeffs(f,var(2))[J+1,1],var(1)); if (size(mat) <= I) { return(0);} else { return(leadcoef(mat[I+1,1]));} } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),dp; koeff(x2+2xy+3xy2-x2y-2y3,1,2); } /////////////////////////////////////////////////////////////////////////////// proc squarefree (poly f) "USAGE: squarefree(f); f poly ASSUME: f is a bivariate polynomial (in the first 2 ring variables). RETURN: poly, a squarefree divisor of f. NOTE: Usually, the return value is the greatest squarefree divisor, but there is one exception: factors with a p-th root, p the characteristic of the basering, are lost. SEE ALSO: allsquarefree EXAMPLE: example squarefree; shows some examples. " { //----------------- Wechsel in geeigneten Ring & Variablendefinition --------- if (nvars(basering)!=2) { ERROR("basering must have exactly 2 variables for Hnoether::squarefree"); } def altring = basering; int e; int gcd_ok=1; string mipl="0"; if (size(parstr(altring))==1) { mipl=string(minpoly); } //---- test: char = (p^k,a) (-> gcd not implemented) or (p,a) (gcd works) ---- //if ((char(basering)!=0) and (charstr(basering)!=string(char(basering)))) gcd_ok= ! hasGFCoefficient(basering); execute("ring rsqrf = ("+charstr(altring)+"),(x,y),dp;"); if ((gcd_ok!=0) && (mipl!="0")) { execute("minpoly="+mipl+";"); } poly f=fetch(altring,f); poly dif,g,l; if ((char(basering)==0) and (charstr(basering)!=string(char(basering))) and (mipl!="0")) { gcd_ok=0; // since Singular 1.2 gcd no longer implemented } if (gcd_ok!=0) { //--------------------- Berechne f/ggT(f,df/dx,df/dy) ------------------------ dif=diff(f,x); if (dif==0) { g=f; } // zur Beschleunigung else { g=gcd(f,dif); } if (g!=1) { // sonst schon sicher, dass f quadratfrei dif=diff(f,y); if (dif!=0) { g=gcd(g,dif); } } if (g!=1) { e=0; if (g==f) { l=1; } // zur Beschleunigung else { module m=syz(ideal(g,f)); if (deg(m[2,1])>0) { "!! The Singular command 'syz' has returned a wrong result !!"; l=1; // Division f/g muss aufgehen } else { l=m[1,1]; } } } else { e=1; } } else { //------------------- Berechne syz(f,df/dx) oder syz(f,df/dy) ---------------- //-- Achtung: Ist f reduzibel, koennen Faktoren mit Ableitung Null verloren -- //-- gehen! Ist aber nicht weiter schlimm, weil char (p^k,a) nur im irred. -- //-- Fall vorkommen kann. Wenn f nicht g^p ist, wird auf jeden Fall -- //------------------------ ein Faktor gefunden. ------------------------------ dif=diff(f,x); if (dif == 0) { dif=diff(f,y); if (dif==0) { e=2; l=1; } // f is of power divisible by char of basefield else { l=syz(ideal(dif,f))[1,1]; // x^p+y^(p-1) abgedeckt if (subst(f,x,0)==0) { l=l*x; } if (deg(l)==deg(f)) { e=1;} else {e=0;} } } else { l=syz(ideal(dif,f))[1,1]; if (subst(f,y,0)==0) { l=l*y; } if (deg(l)==deg(f)) { e=1;} else {e=0;} } } //--------------- Wechsel in alten Ring und Rueckgabe des Ergebnisses -------- setring altring; if (e==1) { return(f); } // zur Beschleunigung else { poly l=fetch(rsqrf,l); return(l); } } example { "EXAMPLE:"; echo = 2; ring exring=3,(x,y),dp; squarefree((x3+y)^2); squarefree((x+y)^3*(x-y)^2); // Warning: (x+y)^3 is lost squarefree((x+y)^4*(x-y)^2); // result is (x+y)*(x-y) } /////////////////////////////////////////////////////////////////////////////// proc allsquarefree (poly f, poly l) "USAGE : allsquarefree(f,g); f,g poly ASSUME: g is the output of @code{squarefree(f)}. RETURN: the greatest squarefree divisor of f. NOTE : This proc uses factorize to get the missing factors of f not in g and, therefore, may be slow. SEE ALSO: squarefree EXAMPLE: example allsquarefree; shows an example " { //------------------------ Wechsel in geeigneten Ring ------------------------ def altring = basering; string mipl="0"; if (size(parstr(altring))==1) { mipl=string(minpoly); } if ((char(basering)!=0) and (charstr(basering)!=string(char(basering)))) { string tststr=charstr(basering); tststr=tststr[1..find(tststr,",")-1]; //-> "p^k" bzw. "p" if (tststr!=string(char(basering))) { " Sorry -- not implemented for this ring (gcd doesn't work)"; return(l); } } execute("ring rsqrf = ("+charstr(altring)+"),(x,y),dp;"); if (mipl!="0") { execute("minpoly="+mipl+";"); } poly f=fetch(altring,f); poly l=fetch(altring,l); //---------- eliminiere bereits mit squarefree gefundene Faktoren ------------ poly g=l; while (deg(g)!=0) { f=syz(ideal(g,f))[1,1]; // f=f/g; g=gcd(f,l); } // jetzt f=h^p //--------------- Berechne uebrige Faktoren mit factorize -------------------- if (deg(f)>0) { g=1; //*CL old: ideal factf=factorize(f,1); //* for (int i=1; i<=size(factf); i++) { g=g*factf[i]; } ideal factf=factorize(f)[1]; for (int i=2; i<=size(factf); i++) { g=g*factf[i]; } poly testp=squarefree(g); if (deg(testp) 16001 or exponent divisible by 32003, if there is one 0 else (in this case computing a squarefree divisor in characteristic 32003 could make sense) NOTE: this procedure is only useful in characteristic zero, because otherwise there is no appropriate ordering of the leading coefficients " { poly verbrecher=0; intvec leitexp; for (; (f<>0) and (verbrecher==0); f=f-lead(f)) { if ((leadcoef(f)<-16001) or (leadcoef(f)>16001)) {verbrecher=lead(f);} leitexp=leadexp(f); if (( ((leitexp[1] % 32003) == 0) and (leitexp[1]<>0)) or ( ((leitexp[2] % 32003) == 0) and (leitexp[2]<>0)) ) {verbrecher=lead(f);} } return(verbrecher); } ////////////////////////////////////////////////////////////////////////////// proc develop(list #) "USAGE: develop(f [,n]); f poly, n int ASSUME: f is a bivariate polynomial (in the first 2 ring variables) and irreducible as power series (for reducible f use @code{hnexpansion}). RETURN: list @code{L} with: @texinfo @table @asis @item @code{L[1]}; matrix: Each row contains the coefficients of the corresponding line of the Hamburger-Noether expansion (HNE). The end of the line is marked in the matrix by the first ring variable (usually x). @item @code{L[2]}; intvec: indicating the length of lines of the HNE @item @code{L[3]}; int: 0 if the 1st ring variable was transversal (with respect to f), @* 1 if the variables were changed at the beginning of the computation, @* -1 if an error has occurred. @item @code{L[4]}; poly: the transformed polynomial of f to make it possible to extend the Hamburger-Noether development a posteriori without having to do all the previous calculation once again (0 if not needed) @item @code{L[5]}; int: 1 if the curve has exactly one branch (i.e., is irreducible), @* 0 else (i.e., the curve has more than one HNE, or f is not valid). @end table @end texinfo DISPLAY: The (non zero) elements of the HNE (if not called by another proc). NOTE: The optional parameter @code{n} affects only the computation of the LAST line of the HNE. If it is given, the HN-matrix @code{L[1]} will have at least @code{n} columns. @* Otherwise, the number of columns will be chosen minimal such that the matrix contains all necessary information (i.e., all lines of the HNE but the last (which is in general infinite) have place). @* If @code{n} is negative, the algorithm is stopped as soon as the computed information is sufficient for @code{invariants(L)}, but the HN-matrix @code{L[1]} may still contain undetermined elements, which are marked with the 2nd variable (of the basering). @* For time critical computations it is recommended to use @code{ring ...,(x,y),ls} as basering - it increases the algorithm's speed. @* If @code{printlevel>=0} comments are displayed (default is @code{printlevel=0}). SEE ALSO: hnexpansion, extdevelop, displayHNE EXAMPLES: example develop; shows an example example parametrize; shows an example for using the 2nd parameter " { //--------- Abfangen unzulaessiger Ringe: 1) nur eine Unbestimmte ------------ poly f=#[1]; if (size(#) > 1) {int maxspalte=#[2];} else {int maxspalte= 1 ; } if (nvars(basering) < 2) { " Sorry. I need two variables in the ring."; return(list(matrix(maxideal(1)[1]),intvec(0),-1,poly(0),0));} if (nvars(basering) > 2) { dbprint(printlevel-voice+2, " Warning! You have defined too many variables! All variables except the first two will be ignored!" ); } string namex=varstr(1); string namey=varstr(2); list return_error=matrix(maxideal(1)[2]),intvec(0),int(-1),poly(0),int(0); //------------- 2) mehrere Unbestimmte, weitere unzulaessige Ringe ----------- // Wir koennen einheitlichen Rueckgabewert benutzen, aus dem ersichtlich ist, // dass ein Fehler aufgetreten ist: return_error. //---------------------------------------------------------------------------- if (charstr(basering)=="real") { " The algorithm doesn't work with 'real' as coefficient field."; // denn : map from characteristic -1 to -1 not implemented return(return_error); } if ((char(basering)!=0) and (charstr(basering)!=string(char(basering)))) { //-- teste, ob char = (p^k,a) (-> a primitiv; erlaubt) oder (p,a[,b,...]) ---- string tststr=charstr(basering); tststr=tststr[1..find(tststr,",")-1]; //-> "p^k" bzw. "p" int primit=(tststr==string(char(basering))); if (primit!=0) { " Such extensions of Z/p are not implemented."; " Please try (p^k,a) as ground field or use `hnexpansion'."; return(return_error); } } //---- Ende der unzulaessigen Ringe; Ringwechsel in einen guenstigen Ring: --- int ringwechsel=(varstr(basering)!="x,y") or (ordstr(basering)!="ls(2),C"); def altring = basering; if (ringwechsel) { string mipl=string(minpoly); execute("ring guenstig = ("+charstr(altring)+"),(x,y),ls;"); if ((char(basering)==0) && (mipl!="0")) { execute("minpoly="+mipl+";"); }} else { def guenstig=basering; } export guenstig; //-------------------------- Initialisierungen ------------------------------- map m=altring,x,y; if (ringwechsel) { poly f=m(f); } if (defined(HNDebugOn)) {"received polynomial: ",f,", where x =",namex,", y =",namey;} kill m; int M,N,Q,R,l,e,hilf,eps,getauscht,Abbruch,zeile,exponent,Ausgabe; // Werte von Ausgabe: 0 : normale HNE-Matrix, // 1 : Fehler aufgetreten - Matrix (namey) zurueck // 2 : Die HNE ist eine Nullzeile - Matrix (0) zurueck // int maxspalte=1; geaendert: wird jetzt am Anfang gesetzt int minimalHNE=0; // Flag fuer minimale HNE-Berechnung int einzweig=1; // Flag fuer Irreduzibilit"at intvec hqs; // erhaelt die Werte von h(zeile)=Q; if (maxspalte<0) { minimalHNE=1; maxspalte=1; } number c,delt; int p = char(basering); string ringchar=charstr(basering); map xytausch = basering,y,x; if ((p!=0) and (ringchar != string(p))) { // coefficient field is extension of Z/pZ execute("int n_elements="+ ringchar[1,size(ringchar)-size(parstr(basering))-1]+";"); // number of elements of actual ring number generat=par(1); // generator of the coefficient field of the ring } //========= Abfangen von unzulaessigen oder trivialen Eingaben =============== //------------ Nullpolynom oder Einheit im Potenzreihenring: ----------------- if (f == 0) { dbprint(printlevel+1,"The given polynomial is the zero-polynomial !"); Abbruch=1; Ausgabe=1; } else { intvec nm = getnm(f); N = nm[1]; M = nm[2]; // Berechne Schnittpunkte Newtonpolygon mit Achsen if (N == 0) { dbprint(printlevel+1,"The given polynomial is a unit as power series !"); Abbruch=1; Ausgabe=1; } else { if (N == -1) { if ((voice==2) && (printlevel > -1)) { "The HNE is x = 0"; } Abbruch=1; Ausgabe=2; getauscht=1; if (M <> 1) { einzweig=0; } } else { if (M == -1) { if ((voice==2) && (printlevel > -1)) { "The HNE is y = 0"; } Abbruch=1; Ausgabe=2; if (N <> 1) { einzweig=0; } }}} } //--------------------- Test auf Quadratfreiheit ----------------------------- if (Abbruch==0) { //-------- Fall basering==0,... : Wechsel in Ring mit char >0 ---------------- // weil squarefree eine Standardbasis berechnen muss (verwendet Syzygien) // -- wenn f in diesem Ring quadratfrei ist, dann erst recht im Ring guenstig //---------------------------------------------------------------------------- if ((p==0) and (size(charstr(basering))==1)) { int testerg=(polytest(f)==0); ring zweitring = 32003,(x,y),dp; map polyhinueber=guenstig,x,y; // fetch geht nicht poly f=polyhinueber(f); poly test_sqr=squarefree(f); if (test_sqr != f) { if (printlevel>0) { "Most probably the given polynomial is not squarefree. But the test was"; "made in characteristic 32003 and not 0 to improve speed. You can"; "(r) redo the test in char 0 (but this may take some time)"; "(c) continue the development, if you're sure that the polynomial", "IS squarefree"; if (testerg==1) { "(s) continue the development with a squarefree factor (*)";} "(q) or just quit the algorithm (default action)"; "";"Please enter the letter of your choice:"; string str=read("")[1]; } else { string str="r"; } // printlevel <= 0: non-interactive behaviour setring guenstig; map polyhinueber=zweitring,x,y; if (str=="r") { poly test_sqr=squarefree(f); if (test_sqr != f) { if (printlevel>0) { "The given polynomial is in fact not squarefree."; } else { "The given polynomial is not squarefree!"; } "I'll continue with the radical."; if (printlevel>0) { pause("Hit RETURN to continue:"); } f=test_sqr; } else { dbprint(printlevel, "everything is ok -- the polynomial is squarefree in char(k)=0"); } } else { if ((str=="s") and (testerg==1)) { "(*) attention: it could be that the factor is only one in char 32003!"; f=polyhinueber(test_sqr); } else { if (str<>"c") { setring altring;kill guenstig;kill zweitring; return(return_error);} else { "if the algorithm doesn't terminate, you were wrong...";} }} kill zweitring; nm = getnm(f); // N,M haben sich evtl. veraendert N = nm[1]; M = nm[2]; // Berechne Schnittpunkte Newtonpolynom mit Achsen if (defined(HNDebugOn)) {"I continue with the polynomial",f; } } else { setring guenstig; kill zweitring; } } // ------------------- Fall Charakteristik > 0 ------------------------------- else { poly test_sqr=squarefree(f); if (test_sqr == 1) { "The given polynomial is of the form g^"+string(p)+", therefore", "reducible.";"Please try again."; setring altring; kill guenstig; return(return_error);} if (test_sqr != f) { "The given polynomial is not squarefree. I'll continue with the radical."; if (p != 0) {"But if the polynomial contains a factor of the form g^"+string(p)+","; "this factor will be lost.";} if (printlevel>0) { pause("Hit RETURN to continue:"); } f=test_sqr; nm = getnm(f); // N,M haben sich veraendert N = nm[1]; M = nm[2]; // Berechne Schnittpunkte Newtonpolynom mit Achsen if (defined(HNDebugOn)) {"I continue with the polynomial",f; } } } // endelse(p==0) if (N==0) { " Sorry. The remaining polynomial is a unit in the power series ring..."; setring altring;kill guenstig;return(return_error); } //---------------------- gewaehrleiste, dass x transvers ist ----------------- if (M < N) { f = xytausch(f); // Variablentausch : x jetzt transvers getauscht = 1; // den Tausch merken M = M+N; N = M-N; M = M-N; // M, N auch vertauschen } if (defined(HNDebugOn)) { if (getauscht) {"x<->y were exchanged; polynomial is now ",f;} else {"x , y were not exchanged";} "M resp. N are now",M,N; } } // end(if Abbruch==0) ideal a(0); while (Abbruch==0) { //================= Beginn der Schleife (eigentliche Entwicklung) ============ //------------------- ist das Newtonpolygon eine gerade Linie? --------------- if (testreducible(f,N,M)) { dbprint(printlevel+1," The given polynomial is not irreducible"); kill guenstig; setring altring; return(return_error); // Abbruch der Prozedur! } R = M%N; Q = M div N; //-------------------- Fall Rest der Division R = 0 : ------------------------ if (R == 0) { c = koeff(f,0,N); if (c == 0) {"Something has gone wrong! I didn't get N correctly!"; exit;} e = gcd(M,N); //----------------- Test, ob leitf = c*(y^N - delta*x^(m/e))^e ist ----------- if (p==0) { delt = koeff(f,M div e,N - N div e) / (-1*e*c); if (defined(HNDebugOn)) {"quasihomogeneous leading form:", leit(f,N,M)," = ",c,"* (y -",delt,"* x^"+string(M div e)+")^",e," ?";} if (leit(f,N,M) != c*(y^(N div e) - delt*x^(M div e))^e) { dbprint(printlevel+1," The given polynomial is reducible !"); Abbruch=1; Ausgabe=1; } } else { // p!=0 if (e%p != 0) { delt = koeff(f,M div e,N - N div e) / (-1*e*c); if (defined(HNDebugOn)) {"quasihomogeneous leading form:", leit(f,N,M)," = ",c,"* (y -",delt,"* x^"+string(M div e)+")^",e," ?";} if (leit(f,N,M) != c*(y^(N div e) - delt*x^(M div e))^e) { dbprint(printlevel+1," The given polynomial is reducible !"); Abbruch=1; Ausgabe=1; } } else { // e%p == 0 eps = e; for (l = 0; eps%p == 0; l=l+1) { eps=eps div p;} if (defined(HNDebugOn)) {e," -> ",eps,"*",p,"^",l;} delt = koeff(f,(M div e)*p^l,(N div e)*p^l*(eps-1)) / (-1*eps*c); if ((ringchar != string(p)) and (delt != 0)) { //- coeff. field is not Z/pZ => we`ve to correct delta by taking (p^l)th root- if (delt == generat) {exponent=1;} else { if (delt == 1) {exponent=0;} else { exponent=pardeg(delt); //-- an dieser Stelle kann ein Fehler auftreten, wenn wir eine transzendente - //-- Erweiterung von Z/pZ haben: dann ist das hinzuadjungierte Element kein - //-- Erzeuger der mult. Gruppe, d.h. in Z/pZ (a) gibt es i.allg. keinen - //-- Exponenten mit z.B. a2+a = a^exp - //---------------------------------------------------------------------------- }} delt = generat^(extgcd(n_elements-1,p^l)[3]*exponent); } if (defined(HNDebugOn)) {"quasihomogeneous leading form:", leit(f,N,M)," = ",c,"* (y^"+string(N div e),"-",delt,"* x^" +string(M div e)+")^",e," ?";} if (leit(f,N,M) != c*(y^(N div e) - delt*x^(M div e))^e) { dbprint(printlevel+1," The given polynomial is reducible !"); Abbruch=1; Ausgabe=1; } } } if (Abbruch == 0) { f = T1_Transform(f,delt,M div e); dbprint(printlevel-voice+2,"a("+string(zeile)+","+string(Q)+") = " +string(delt)); a(zeile)[Q]=delt; if (defined(HNDebugOn)) {"transformed polynomial: ",f;}} nm=getnm(f); N=nm[1]; M=nm[2]; // Neuberechnung des Newtonpolygons } //--------------------------- Fall R > 0 : ----------------------------------- else { dbprint(printlevel-voice+2, "h("+string(zeile)+ ") ="+string(Q)); hqs[zeile+1]=Q; // denn zeile beginnt mit dem Wert 0 a(zeile)[Q+1]=x; // Markierung des Zeilenendes der HNE maxspalte=maxspalte*((Q+1) < maxspalte) + (Q+1)*((Q+1) >= maxspalte); // Anpassung der Sp.zahl der HNE-Matrix f = T_Transform(f,Q,N); if (defined(HNDebugOn)) {"transformed polynomial: ",f;} zeile=zeile+1; //------------ Bereitstellung von Speicherplatz fuer eine neue Zeile: -------- ideal a(zeile); M=N;N=R; } //--------------- schneidet das Newtonpolygon beide Achsen? ------------------ if (M==-1) { dbprint(printlevel-voice+2,"The HNE is finite!"); a(zeile)[Q+1]=x; // Markiere das Ende der Zeile hqs[zeile+1]=Q; maxspalte=maxspalte*((Q+1) < maxspalte) + (Q+1)*((Q+1) >= maxspalte); if (N <> 1) { einzweig=0; } f=0; // transformiertes Polynom wird nicht mehr gebraucht Abbruch=1; } else {if (M maxspalte) or (minimalHNE==1)) and (size(a(zeile))>0)) //---------------------------------------------------------------------------- // Abbruch, wenn die Matrix so voll ist, dass eine neue Spalte angefangen // werden muesste und die letzte Zeile nicht nur Nullen enthaelt // oder wenn die Matrix nicht voll gemacht werden soll (minimale Information) //---------------------------------------------------------------------------- { Abbruch=1; hqs[zeile+1]=-1; if (maxspalte < ncols(a(zeile))) { maxspalte=ncols(a(zeile));} if ((minimalHNE==1) and (M <= maxspalte)) { // teile param mit, dass Eintraege der letzten Zeile nur teilw. richtig sind:- hqs[zeile+1]=-M; //------------- markiere den Rest der Zeile als unbekannt: ------------------- for (R=M; R <= maxspalte; R++) { a(zeile)[R]=y;} } // R wird nicht mehr gebraucht } //========================= Ende der Schleife ================================ } setring altring; if (Ausgabe == 0) { //-------------------- Ergebnis in den alten Ring transferieren: ------------- map zurueck=guenstig,maxideal(1)[1],maxideal(1)[2]; matrix amat[zeile+1][maxspalte]; ideal uebergabe; for (e=0; e<=zeile; e=e+1) { uebergabe=zurueck(a(e)); if (ncols(uebergabe) > 1) { amat[e+1,1..ncols(uebergabe)]=uebergabe;} else {amat[e+1,1]=uebergabe[1];} } if (ringwechsel) { if (nvars(altring)==2) { f=fetch(guenstig,f); } else { f=zurueck(f); } } } kill guenstig; if ((einzweig==0) && (voice==2) && (printlevel > -1)) { "// Note: The curve is reducible, but we were able to compute a HNE."; "// This means the result is only one of several existing HNE's."; } if (Ausgabe == 0) { return(list(amat,hqs,getauscht,f,einzweig));} if (Ausgabe == 1) { return(return_error);} // error has occurred if (Ausgabe == 2) { return(list(matrix(ideal(0,x)),intvec(1),getauscht, poly(0),einzweig));} // HNE is x=0 or y=0 } example { "EXAMPLE:"; echo = 2; ring exring = 7,(x,y),ds; list Hne=develop(4x98+2x49y7+x11y14+2y14); print(Hne[1]); // therefore the HNE is: // z(-1)= 3*z(0)^7 + z(0)^7*z(1), // z(0) = z(1)*z(2), (there is 1 zero in the 2nd row before x) // z(1) = z(2)^3*z(3), (there are 3 zeroes in the 3rd row) // z(2) = z(3)*z(4), // z(3) = -z(4)^2 + 0*z(4)^3 +...+ 0*z(4)^8 + ?*z(4)^9 + ... // (the missing x in the last line indicates that it is not complete.) Hne[2]; param(Hne); // parametrization: x(t)= -t^14+O(t^21), y(t)= -3t^98+O(t^105) // (the term -t^109 in y may have a wrong coefficient) displayHNE(Hne); } /////////////////////////////////////////////////////////////////////////////// // procedures to extract information out of HNE // /////////////////////////////////////////////////////////////////////////////// proc param (list L, list #) "USAGE: param(L [,s]); L list, s any type (optional) ASSUME: L is the output of @code{develop(f)}, or of @code{extdevelop(develop(f),n)}, or (one entry in) the list of HN data created by @code{hnexpansion(f[,\"ess\"])}. RETURN: If L are the HN data of an irreducible plane curve singularity f: a parametrization for f in the following format: @* - if only the list L is given, the result is an ideal of two polynomials p[1],p[2]: if the HNE was finite then f(p[1],p[2])=0}; if not, the true parametrization will be given by two power series, and p[1],p[2] are truncations of these series.@* - if the optional parameter s is given, the result is a list l: l[1]=param(L) (ideal) and l[2]=intvec with two entries indicating the highest degree up to which the coefficients of the monomials in l[1] are exact (entry -1 means that the corresponding parametrization is exact). If L collects the HN data of a reducible plane curve singularity f, the return value is a list of parametrizations in the respective format. NOTE: If the basering has only 2 variables, the first variable is chosen as indefinite. Otherwise, the 3rd variable is chosen. SEE ALSO: develop, extdevelop KEYWORDS: parametrization EXAMPLE: example param; shows an example example develop; shows another example " { //-------------------------- Initialisierungen ------------------------------- int return_list; if (size(#)>0) { return_list=1; } if (typeof(L[1])=="list") { // output of hnexpansion (> 1 branch) list Ergebnis; for (int i=1; i<=size(L); i++) { dbprint(printlevel-voice+4,"// Parametrization of branch number " +string(i)+" computed."); printlevel=printlevel+1; if (return_list==1) { Ergebnis[i]=param(L[i],1); } else { Ergebnis[i]=param(L[i]); } printlevel=printlevel-1; } return(Ergebnis); } else { matrix m=L[1]; intvec v=L[2]; int switch=L[3]; } if (switch==-1) { "An error has occurred in develop, so there is no HNE."; return(ideal(0,0)); } int fehler,fehlervor,untergrad,untervor,beginn,i,zeile,hilf; if (nvars(basering) > 2) { poly z(size(v)+1)=var(3); } else { poly z(size(v)+1)=var(1); } poly z(size(v)); zeile=size(v); //------------- Parametrisierung der untersten Zeile der HNE ----------------- if (v[zeile] > 0) { fehler=0; // die Parametrisierung wird exakt werden for (i=1; i<=v[zeile]; i++) { z(zeile)=z(zeile)+m[zeile,i]*z(zeile+1)^i; } } else { untervor=1; // = Untergrad der vorhergehenden Zeile if (v[zeile]==-1) { fehler=ncols(m)+1; for (i=1; i<=ncols(m); i++) { z(zeile)=z(zeile)+m[zeile,i]*z(zeile+1)^i; if ((untergrad==0) and (m[zeile,i]!=0)) {untergrad=i;} // = Untergrad der aktuellen Zeile } } else { fehler= -v[zeile]; for (i=1; i<-v[zeile]; i++) { z(zeile)=z(zeile)+m[zeile,i]*z(zeile+1)^i; if ((untergrad==0) and (m[zeile,i]!=0)) {untergrad=i;} } } } //------------- Parametrisierung der restlichen Zeilen der HNE --------------- for (zeile=size(v)-1; zeile>0; zeile--) { poly z(zeile); beginn=0; // Beginn der aktuellen Zeile for (i=1; i<=v[zeile]; i++) { z(zeile)=z(zeile)+m[zeile,i]*z(zeile+1)^i; if ((beginn==0) and (m[zeile,i]!=0)) { beginn=i;} } z(zeile)=z(zeile) + z(zeile+1)^v[zeile] * z(zeile+2); if (beginn==0) { if (fehler>0) { // damit fehler=0 bleibt bei exakter Param. fehlervor=fehler; // Fehler der letzten Zeile fehler=fehler+untergrad*(v[zeile]-1)+untervor; // Fehler dieser Zeile hilf=untergrad; untergrad=untergrad*v[zeile]+untervor; untervor=hilf;} // untervor = altes untergrad } else { fehlervor=fehler; fehler=fehler+untergrad*(beginn-1); untervor=untergrad; untergrad=untergrad*beginn; } } //--------------------- Ausgabe der Fehlerabschaetzung ----------------------- if (switch==0) { if (fehler>0) { if (fehlervor>0) { dbprint(printlevel-voice+4,""+ "// ** Warning: result is exact up to order "+string(fehlervor-1)+ " in "+ string(var(1))+" and "+string(fehler-1)+" in " + string(var(2))+" !"); } else { dbprint(printlevel-voice+4,""+ "// ** Warning: result is exact up to order "+ string(fehler-1)+ " in "+string(var(2))+" !"); } } if (return_list==0) { return(ideal(z(2),z(1))); } else { return(list(ideal(z(2),z(1)),intvec(fehlervor-1,fehler-1))); } } else { if (fehler>0) { if (fehlervor>0) { dbprint(printlevel-voice+4,""+ "// ** Warning: result is exact up to order "+string(fehler-1)+ " in "+ string(var(1))+" and "+string(fehlervor-1)+" in " + string(var(2))+" !"); } else { dbprint(printlevel-voice+4,""+ "// ** Warning: result is exact up to order "+ string(fehler-1)+ " in "+string(var(1))+" !"); } } if (return_list==0) { return(ideal(z(1),z(2))); } else { return(list(ideal(z(1),z(2)),intvec(fehler-1,fehlervor-1))); } } } example { "EXAMPLE:"; echo = 2; ring exring=0,(x,y,t),ds; poly f=x3+2xy2+y2; list Hne=develop(f); list hne_extended=extdevelop(Hne,10); // compare the HNE matrices ... print(Hne[1]); print(hne_extended[1]); // ... and the resulting parametrizations: param(Hne); param(hne_extended); param(hne_extended,0); // An example with more than one branch: list L=hnexpansion(f*(x2+y4)); def HNring = L[1]; setring HNring; param(hne); } /////////////////////////////////////////////////////////////////////////////// proc invariants "USAGE: invariants(INPUT); INPUT list or poly ASSUME: @code{INPUT} is the output of @code{develop(f)}, or of @code{extdevelop(develop(f),n)}, or one entry of the list of HN data computed by @code{hnexpansion(f[,\"ess\"])}. RETURN: list @code{INV} of the following format: @format INV[1]: intvec (characteristic exponents) INV[2]: intvec (generators of the semigroup) INV[3]: intvec (Puiseux pairs, 1st components) INV[4]: intvec (Puiseux pairs, 2nd components) INV[5]: int (degree of the conductor) INV[6]: intvec (sequence of multiplicities) @end format If @code{INPUT} contains no valid HN expansion, the empty list is returned. ASSUME: @code{INPUT} is a bivariate polynomial f, or the output of @code{hnexpansion(f)}, or the list of HN data computed by @code{hnexpansion(f [,\"ess\"])}. RETURN: list @code{INV}, such that @code{INV[i]} coincides with the output of @code{invariants(develop(f[i]))}, where f[i] is the i-th branch of f, and the last entry of @code{INV} contains further invariants of f in the format: @format INV[last][1] : intmat (contact matrix of the branches) INV[last][2] : intmat (intersection multiplicities of the branches) INV[last][3] : int (delta invariant of f) @end format NOTE: In case the Hamburger-Noether expansion of the curve f is needed for other purposes as well it is better to calculate this first with the aid of @code{hnexpansion} and use it as input instead of the polynomial itself. SEE ALSO: hnexpansion, develop, displayInvariants, multsequence, intersection KEYWORDS: characteristic exponents; semigroup of values; Puiseux pairs; conductor, degree; multiplicities, sequence of EXAMPLE: example invariants; shows an example " { //---- INPUT = poly, or HNEring, or hne of reducible curve ----------------- if (typeof(#[1])!="matrix") { if (typeof(#[1])=="poly") { list L=hnexpansion(#[1]); if (typeof(L[1])=="ring") { def altring = basering; def HNring = L[1]; setring HNring; list Ergebnis = invariants(hne); setring altring; kill HNring; return(Ergebnis); } else { return(invariants(L)); } } if (typeof(#[1])=="ring") { def altring = basering; def HNring = #[1]; setring HNring; list Ergebnis = invariants(hne); setring altring; kill HNring; return(Ergebnis); } if (typeof(#[1])=="list") { list hne=#; list Ergebnis; for (int lauf=1;lauf<=size(hne);lauf++) { Ergebnis[lauf]=invariants(hne[lauf]); } // Calculate the intersection matrix and the intersection multiplicities. intmat contact[size(hne)][size(hne)]; intmat intersectionmatrix[size(hne)][size(hne)]; int Lauf; for (lauf=1;lauf<=size(hne);lauf++) { for (Lauf=lauf+1;Lauf<=size(hne);Lauf++) { contact[lauf,Lauf]=separateHNE(hne[lauf],hne[Lauf]); contact[Lauf,lauf]=contact[lauf,Lauf]; intersectionmatrix[lauf,Lauf]=intersection(hne[lauf],hne[Lauf]); intersectionmatrix[Lauf,lauf]=intersectionmatrix[lauf,Lauf]; } } // Calculate the delta invariant. int inters; int del=Ergebnis[size(hne)][5] div 2; for(lauf=1;lauf<=size(hne)-1;lauf++) { del=del+Ergebnis[lauf][5] div 2; for(Lauf=lauf+1;Lauf<=size(hne);Lauf++) { inters=inters+intersectionmatrix[lauf,Lauf]; } } del=del+inters; list LAST=contact,intersectionmatrix,del; Ergebnis[size(hne)+1]=LAST; return(Ergebnis); } } //-------------------------- Initialisierungen ------------------------------- matrix m=#[1]; intvec v=#[2]; int switch=#[3]; list ergebnis; if (switch==-1) { "An error has occurred in develop, so there is no HNE."; return(ergebnis); } intvec beta,s,svorl,ordnung,multseq,mpuiseux,npuiseux,halbgr; int genus,zeile,i,j,k,summe,conductor,ggT; string Ausgabe; int nc=ncols(m); int nr=nrows(m); ordnung[nr]=1; // alle Indizes muessen (gegenueber [Ca]) um 1 erhoeht werden, // weil 0..r nicht als Wertebereich erlaubt ist (aber nrows(m)==r+1) //---------------- Bestimme den Untergrad der einzelnen Zeilen --------------- for (zeile=nr; zeile>1; zeile--) { if ((size(ideal(m[zeile,1..nc])) > 1) or (zeile==nr)) { // keine Nullzeile k=1; while (m[zeile,k]==0) {k++;} ordnung[zeile-1]=k*ordnung[zeile]; // vgl. auch Def. von untergrad in genus++; // proc param svorl[genus]=zeile;} // werden gerade in umgekehrter Reihenfolge abgelegt else { ordnung[zeile-1]=v[zeile]*ordnung[zeile]+ordnung[zeile+1]; }} //----------------- charakteristische Exponenten (beta) ---------------------- s[1]=1; for (k=1; k <= genus; k++) { s[k+1]=svorl[genus-k+1];} // s[2]==s(1), u.s.w. beta[1]=ordnung[1]; //charakt. Exponenten: Index wieder verschoben for (k=1; k <= genus; k++) { summe=0; for (i=1; i <= s[k]; i++) {summe=summe+v[i]*ordnung[i];} beta[k+1]=summe+ordnung[s[k]]+ordnung[s[k]+1]-ordnung[1]; } //--------------------------- Puiseuxpaare ----------------------------------- int produkt=1; for (i=1; i<=genus; i++) { ggT=gcd(beta[1],beta[i+1]*produkt); mpuiseux[i]=beta[i+1]*produkt div ggT; npuiseux[i]=beta[1] div ggT; produkt=produkt*npuiseux[i]; } //---------------------- Grad des Konduktors --------------------------------- summe=1-ordnung[1]; if (genus > 0) { for (i=2; i <= genus+1; i++) { summe=summe + beta[i] * (ordnung[s[i-1]] - ordnung[s[i]]); } // n.b.: Indizierung wieder um 1 verschoben } conductor=summe; //------------------- Erzeuger der Halbgruppe: ------------------------------- halbgr=puiseux2generators(mpuiseux,npuiseux); //------------------- Multiplizitaetensequenz: ------------------------------- k=1; for (i=1; i1)) { tester=tester-1; } if ((multseq[tester]!=1) and (multseq[tester]!=k-tester)) { for (i=k+1; i<=tester+multseq[tester]; i++) { multseq[i]=1; } } //--- Ende T.Keilen --- 06.05.02 //------------------------- Rueckgabe ---------------------------------------- ergebnis=beta,halbgr,mpuiseux,npuiseux,conductor,multseq; return(ergebnis); } example { "EXAMPLE:"; echo = 2; ring exring=0,(x,y),dp; list Hne=develop(y4+2x3y2+x6+x5y); list INV=invariants(Hne); INV[1]; // the characteristic exponents INV[2]; // the generators of the semigroup of values INV[3],INV[4]; // the Puiseux pairs in packed form INV[5] div 2; // the delta-invariant INV[6]; // the sequence of multiplicities // To display the invariants more 'nicely': displayInvariants(Hne); ///////////////////////////// INV=invariants((x2-y3)*(x3-y5)); INV[1][1]; // the characteristic exponents of the first branch INV[2][6]; // the sequence of multiplicities of the second branch print(INV[size(INV)][1]); // the contact matrix of the branches print(INV[size(INV)][2]); // the intersection numbers of the branches INV[size(INV)][3]; // the delta invariant of the curve } /////////////////////////////////////////////////////////////////////////////// proc displayInvariants "USAGE: displayInvariants(INPUT); INPUT list or poly ASSUME: @code{INPUT} is a bivariate polynomial, or the output of @code{develop(f)}, resp. of @code{extdevelop(develop(f),n)}, or (one entry of) the list of HN data computed by @code{hnexpansion(f[,\"ess\"])}. RETURN: none DISPLAY: invariants of the corresponding branch, resp. of all branches, in a better readable form. NOTE: If the Hamburger-Noether expansion of the curve f is needed for other purposes as well it is better to calculate this first with the aid of @code{hnexpansion} and use it as input instead of the polynomial itself. SEE ALSO: invariants, intersection, develop, hnexpansion EXAMPLE: example displayInvariants; shows an example " { // INPUT = polynomial or ring if (typeof(#[1])=="poly") { list L=hnexpansion(#[1]); if (typeof(L[1])=="ring") { def HNring = L[1]; setring HNring; displayInvariants(hne); return(); } else { displayInvariants(L); return(); } } if (typeof(#[1])=="ring") { def HNring = #[1]; setring HNring; displayInvariants(hne); return(); } // INPUT = hne of a plane curve int i,j,k,mul; string Ausgabe; list ergebnis; //-- entferne ueberfluessige Daten zur Erhoehung der Rechengeschwindigkeit: -- #=stripHNE(#); //-------------------- Ausgabe eines Zweiges --------------------------------- if (typeof(#[1])=="matrix") { ergebnis=invariants(#); if (size(ergebnis)!=0) { " characteristic exponents :",ergebnis[1]; " generators of semigroup :",ergebnis[2]; if (size(ergebnis[1])>1) { for (i=1; i<=size(ergebnis[3]); i++) { Ausgabe=Ausgabe+"("+string(ergebnis[3][i])+"," +string(ergebnis[4][i])+")"; }} " Puiseux pairs :",Ausgabe; " degree of the conductor :",ergebnis[5]; " delta invariant :",ergebnis[5] div 2; " sequence of multiplicities:",ergebnis[6]; }} //-------------------- Ausgabe aller Zweige ---------------------------------- else { ergebnis=invariants(#); intmat contact=ergebnis[size(#)+1][1]; intmat intersectionmatrix=ergebnis[size(#)+1][2]; for (j=1; j<=size(#); j++) { " --- invariants of branch number",j,": ---"; " characteristic exponents :",ergebnis[j][1]; " generators of semigroup :",ergebnis[j][2]; Ausgabe=""; if (size(ergebnis[j][1])>1) { for (i=1; i<=size(ergebnis[j][3]); i++) { Ausgabe=Ausgabe+"("+string(ergebnis[j][3][i])+"," +string(ergebnis[j][4][i])+")"; }} " Puiseux pairs :",Ausgabe; " degree of the conductor :",ergebnis[j][5]; " delta invariant :",ergebnis[j][5] div 2; " sequence of multiplicities:",ergebnis[j][6]; ""; } if (size(#)>1) { " -------------- contact numbers : -------------- ";""; Ausgabe="branch | "; for (j=size(#); j>1; j--) { if (size(string(j))==1) { Ausgabe=Ausgabe+" "+string(j)+" "; } else { Ausgabe=Ausgabe+string(j)+" "; } } Ausgabe; Ausgabe="-------+"; for (j=2; jj; k--) { mul=contact[j,k];//separateHNE(#[j],#[k]); for (i=1; i<=5-size(string(mul)); i++) { Ausgabe=Ausgabe+" "; } Ausgabe=Ausgabe+string(mul); if (k>j+1) { Ausgabe=Ausgabe+","; } } Ausgabe; } ""; if (size(#)>1) { " -------------- intersection multiplicities : -------------- ";""; Ausgabe="branch | "; for (j=size(#); j>1; j--) { if (size(string(j))==1) { Ausgabe=Ausgabe+" "+string(j)+" "; } else { Ausgabe=Ausgabe+string(j)+" "; } } Ausgabe; Ausgabe="-------+"; for (j=2; jj; k--) { mul=intersectionmatrix[j,k];//intersection(#[j],#[k]); for (i=1; i<=5-size(string(mul)); i++) { Ausgabe=Ausgabe+" "; } Ausgabe=Ausgabe+string(mul); if (k>j+1) { Ausgabe=Ausgabe+","; } } Ausgabe; } ""; " -------------- delta invariant of the curve : ",ergebnis[size(#)+1][3]; } return(); } example { "EXAMPLE:"; echo = 2; ring exring=0,(x,y),dp; list Hne=develop(y4+2x3y2+x6+x5y); displayInvariants(Hne); } /////////////////////////////////////////////////////////////////////////////// proc multiplicities "USAGE: multiplicities(L); L list ASSUME: L is the output of @code{develop(f)}, or of @code{extdevelop(develop(f),n)}, or one entry in the list @code{hne} in the ring created by @code{hnexpansion(f[,\"ess\"])}. RETURN: intvec of the different multiplicities that occur when successively blowing-up the curve singularity corresponding to f. SEE ALSO: multsequence, develop EXAMPLE: example multiplicities; shows an example " { matrix m=#[1]; intvec v=#[2]; int switch=#[3]; list ergebnis; if (switch==-1) { "An error has occurred in develop, so there is no HNE."; return(intvec(0)); } intvec ordnung; int zeile,k; int nc=ncols(m); int nr=nrows(m); ordnung[nr]=1; //---------------- Bestimme den Untergrad der einzelnen Zeilen --------------- for (zeile=nr; zeile>1; zeile--) { if ((size(ideal(m[zeile,1..nc])) > 1) or (zeile==nr)) { // keine Nullzeile k=1; while (m[zeile,k]==0) {k++;} ordnung[zeile-1]=k*ordnung[zeile]; } else { ordnung[zeile-1]=v[zeile]*ordnung[zeile]+ordnung[zeile+1]; }} return(ordnung); } example { "EXAMPLE:"; echo = 2; int p=printlevel; printlevel=-1; ring r=0,(x,y),dp; multiplicities(develop(x5+y7)); // The first value is the multiplicity of the curve itself, here it's 5 printlevel=p; } /////////////////////////////////////////////////////////////////////////////// proc puiseux2generators (intvec m, intvec n) "USAGE: puiseux2generators(m,n); m,n intvec ASSUME: m, resp. n, represent the 1st, resp. 2nd, components of Puiseux pairs (e.g., @code{m=invariants(L)[3]}, @code{n=invariants(L)[4]}). RETURN: intvec of the generators of the semigroup of values. SEE ALSO: invariants EXAMPLE: example puiseux2generators; shows an example " { intvec beta; int q=1; //------------ glatte Kurve (eigentl. waeren m,n leer): ---------------------- if (m==0) { return(intvec(1)); } //------------------- singulaere Kurve: -------------------------------------- for (int i=1; i<=size(n); i++) { q=q*n[i]; } beta[1]=q; // == q_0 m=1,m; n=1,n; // m[1] ist damit m_0 usw., genau wie beta[1]==beta_0 for (i=2; i<=size(n); i++) { beta[i]=m[i]*q div n[i] - m[i-1]*q + n[i-1]*beta[i-1]; q=q div n[i]; // == q_i } return(beta); } example { "EXAMPLE:"; echo = 2; // take (3,2),(7,2),(15,2),(31,2),(63,2),(127,2) as Puiseux pairs: puiseux2generators(intvec(3,7,15,31,63,127),intvec(2,2,2,2,2,2)); } /////////////////////////////////////////////////////////////////////////////// proc intersection (list hn1, list hn2) "USAGE: intersection(hne1,hne2); hne1, hne2 lists ASSUME: @code{hne1, hne2} represent an HN expansion of an irreducible plane curve singularity (that is, are the output of @code{develop(f)}, or of @code{extdevelop(develop(f),n)}, or one entry of the list of HN data computed by @code{hnexpansion(f[,\"ess\"])}). RETURN: int, the intersection multiplicity of the irreducible plane curve singularities corresponding to @code{hne1} and @code{hne2}. SEE ALSO: hnexpansion, displayInvariants KEYWORDS: intersection multiplicity EXAMPLE: example intersection; shows an example " { //------------------ `intersect' ist schon reserviert ... -------------------- int i,j,s,sum,schnitt,unterschied; matrix a1=hn1[1]; matrix a2=hn2[1]; intvec h1=hn1[2]; intvec h2=hn2[2]; intvec n1=multiplicities(hn1); intvec n2=multiplicities(hn2); if (hn1[3]!=hn2[3]) { //-- die jeweils erste Zeile von hn1,hn2 gehoert zu verschiedenen Parametern - //---------------- d.h. beide Kurven schneiden sich transversal -------------- schnitt=n1[1]*n2[1]; // = mult(hn1)*mult(hn2) } else { //--------- die jeweils erste Zeile gehoert zum gleichen Parameter ----------- unterschied=0; for (s=1; (h1[s]==h2[s]) && (sncols(a2)) { j=ncols(a1); } else { j=ncols(a2); } unterschied=0; if ((h1[s]>0) && (s==size(h1))) { a1[s,h1[s]+1]=0; if (ncols(a1)<=ncols(a2)) { unterschied=1; } } if ((h2[s]>0) && (s==size(h2))) { a2[s,h2[s]+1]=0; if (ncols(a2)<=ncols(a1)) { unterschied=1; } } if (unterschied==1) { // mind. eine HNE war endlich matrix ma1[1][j]=a1[s,1..ncols(a1)]; // und bedarf der Fortsetzung matrix ma2[1][j]=a2[s,1..ncols(a2)]; // mit Nullen } else { if (ncols(a1)>ncols(a2)) { j=ncols(a2); } else { j=ncols(a1); } matrix ma1[1][j]=a1[s,1..j]; // Beschr. auf vergleichbaren matrix ma2[1][j]=a2[s,1..j]; // Teil (der evtl. y's enth.) } for (i=1; (ma1[1,i]==ma2[1,i]) && (i1)) { tester=tester-1; } if((multseq[tester]!=1) and (multseq[tester]!=k-tester)) { for (i=k+1; i<=tester+multseq[tester]; i++) { multseq[i]=1; } } //--- Ende T.Keilen --- 06.05.02 return(multseq); } //---------------------------- mehrere Zweige -------------------------------- else { list HNEs=#; int anzahl=size(HNEs); int maxlength=0; int bisher; intvec schnitt,ones; ones[anzahl]=0; ones=ones+1; // = 1,1,...,1 for (i=1; i= maxlength); maxlength=maxlength*(schnitt[i]+1 < maxlength) + (schnitt[i]+1)*(schnitt[i]+1 >= maxlength); } j=size(multsequence(HNEs[anzahl])); maxlength=maxlength*(j < maxlength) + j*(j >= maxlength); //-------------- Konstruktion der ersten zu berechnenden Matrix --------------- intmat allmults[maxlength][anzahl]; for (i=1; i<=maxlength; i++) { allmults[i,1..anzahl]=ones[1..anzahl]; } for (i=1; i<=anzahl; i++) { ones=multsequence(HNEs[i]); allmults[1..size(ones),i]=ones[1..size(ones)]; } //---------------------- Konstruktion der zweiten Matrix ---------------------- intmat separate[maxlength][anzahl]; for (i=1; i<=maxlength; i++) { k=1; bisher=0; if (anzahl==1) { separate[i,1]=1; } for (j=1; jncols(a2)) { j=ncols(a1); } else { j=ncols(a2); } unterschied=0; if ((h1[s]>0) && (s==size(h1))) { a1[s,h1[s]+1]=0; if (ncols(a1)<=ncols(a2)) { unterschied=1; } } if ((h2[s]>0) && (s==size(h2))) { a2[s,h2[s]+1]=0; if (ncols(a2)<=ncols(a1)) { unterschied=1; } } if (unterschied==1) { // mind. eine HNE war endlich matrix ma1[1][j]=a1[s,1..ncols(a1)]; // und bedarf der Fortsetzung matrix ma2[1][j]=a2[s,1..ncols(a2)]; // mit Nullen } else { if (ncols(a1)>ncols(a2)) { j=ncols(a2); } else { j=ncols(a1); } matrix ma1[1][j]=a1[s,1..j]; // Beschr. auf vergleichbaren matrix ma2[1][j]=a2[s,1..j]; // Teil (der evtl. y's enth.) } for (i=1; (ma1[1,i]==ma2[1,i]) && (i*z(1) x = []*z(1)^2+...+z(1)^<>*z(2) z(1) = []*z(2)^2+...+z(2)^<>*z(3) ....... .......................... z(r-1) = []*z(r)^2+[]*z(r)^3+...... @end example where @code{x},@code{y} are the first 2 variables of the basering. The values of @code{[]} are the coefficients of the Hamburger-Noether matrix, the values of @code{<>} are represented by @code{x} in the HN matrix.@* - if a second argument is given and if the input are the HN data of an irreducible plane curve singularity, return a ring containing an ideal @code{HNE} as described above.@* - if L corresponds to the output of @code{hnexpansion(f)} or to the list of HN data computed by @code{hnexpansion(f[,\"ess\"])}, @code{displayHNE(L[,n])} shows the HNE's of all branches of f in the format described above. The optional parameter is then ignored. NOTE: The 1st line of the above ideal (i.e., @code{HNE[1]}) means that @code{y=[]*z(0)^1+...}, the 2nd line (@code{HNE[2]}) means that @code{x=[]*z(1)^2+...}, so you can see which indeterminate corresponds to which line (it's also possible that @code{x} corresponds to the 1st line and @code{y} to the 2nd). SEE ALSO: develop, hnexpansion EXAMPLE: example displayHNE; shows an example " { if ((typeof(ldev[1])=="list") || (typeof(ldev[1])=="none")) { for (int i=1; i<=size(ldev); i++) { "// Hamburger-Noether development of branch nr."+string(i)+":"; displayHNE(ldev[i]);""; } return(); } //--------------------- Initialisierungen und Ringwechsel -------------------- matrix m=ldev[1]; intvec v=ldev[2]; int switch=ldev[3]; if (switch==-1) { "An error has occurred throughout the expansion, so there is no HNE."; return(ideal(0)); } def altring=basering; ///////////////////////////////////////////////////////// // Change by T. Keilen 08.06.2002 // ring + ring does not work if one ring is an algebraic extension /* if (parstr(basering)!="") { if (charstr(basering)!=string(char(basering))+","+parstr(basering)) { execute ("ring dazu=("+charstr(basering)+"),z(0.."+string(size(v)-1)+"),ls;"); } else { ring dazu=char(altring),z(0..size(v)-1),ls; } } else { ring dazu=char(altring),z(0..size(v)-1),ls; } def displayring=dazu+altring; */ execute("ring displayring=("+charstr(basering)+"),(z(0.."+string(size(v)-1)+"),"+varstr(basering)+"),(ls("+string(size(v))+"),"+ordstr(basering)+");"); // End change by T. Keilen ////////////////////////////////////////////////////////////// setring displayring; map holematrix=altring,0; // mappt nur die Monome vom Grad Null matrix m=holematrix(m); int i,j; // lossen: check the last row for finiteness (06/2004) int rowM=nrows(m); int colM=ncols(m); int undef_bd=v[size(v)]; if ( undef_bd<-1 ){ for (j=-undef_bd; j<=colM; j++) { m[rowM,j]=0; } } //--------------------- Erzeuge Matrix n mit n[i,j]=z(j-1)^i ----------------- matrix n[colM][rowM]; for (j=1; j<=rowM; j++) { for (i=1; i<=colM; i++) { n[i,j]=z(j-1)^i; } } matrix displaymat=m*n; ideal HNE; for (i=1; i=" +string(-undef_bd)+")"; } if (undef_bd==-1) { stHNE(size(v))=stHNE(size(v))+" + ..... (terms of degree >=" +string(colM+1)+")"; } if (switch==0) { stHNE(1) = " "+string(var(size(v)+2))+" = "+stHNE(1); } else { stHNE(1) = " "+string(var(size(v)+1))+" = "+stHNE(1); } stHNE(1); if (ncols(HNE)==1) {return();} if (switch==0) { stHNE(2) = " "+string(var(size(v)+1))+" = "+stHNE(2); } else { stHNE(2) = " "+string(var(size(v)+2))+" = "+stHNE(2); } stHNE(2); for (j=3; j<=ncols(HNE); j++){ stHNE(j)= " "+"z(" +string(j-2)+ ") = "+stHNE(j); stHNE(j); } return(); } if (rowM<2) { HNE[2]=z(0); } if (switch==0) { HNE[1] = HNE[1]-var(size(v)+2); HNE[2] = HNE[2]-var(size(v)+1); } else { HNE[1] = HNE[1]-var(size(v)+1); HNE[2] = HNE[2]-var(size(v)+2); } if (size(#) == 0) { HNE; return(); } if (size(#) != 0) { HNE; export(HNE); return(displayring); } } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),dp; poly f=x3+2xy2+y2; list hn=develop(f); displayHNE(hn); } /////////////////////////////////////////////////////////////////////////////// // procedures for reducible curves // /////////////////////////////////////////////////////////////////////////////// // proc newtonhoehne (poly f) // USAGE: newtonhoehne(f); f poly // ASSUME: basering = ...,(x,y),ds or ls // RETURN: list of intvec(x,y) of coordinates of the newtonpolygon of f // NOTE: This proc is only available in versions of Singular that know the // command system("newton",f); f poly // { // intvec nm = getnm(f); // if ((nm[1]>0) && (nm[2]>0)) { f=jet(f,nm[1]*nm[2],nm); } // list erg=system("newton",f); // int i; list Ausgabe; // for (i=1; i<=size(erg); i++) { Ausgabe[i]=leadexp(erg[i]); } // return(Ausgabe); // } /////////////////////////////////////////////////////////////////////////////// proc newtonpoly (poly f, int #) "USAGE: newtonpoly(f); f poly ASSUME: basering has exactly two variables; @* f is convenient, that is, f(x,0) != 0 != f(0,y). RETURN: list of intvecs (= coordinates x,y of the Newton polygon of f). NOTE: Procedure uses @code{execute}; this can be avoided by calling @code{newtonpoly(f,1)} if the ordering of the basering is @code{ls}. KEYWORDS: Newton polygon EXAMPLE: example newtonpoly; shows an example " { if (size(#)>=1) { if (typeof(#[1])=="int") { // this is done to avoid the "execute" command for procedures in // hnoether.lib def is_ls=#[1]; } } if (defined(is_ls)<=0) { def @Rold=basering; execute("ring @RR=("+charstr(basering)+"),("+varstr(basering)+"),ls;"); poly f=imap(@Rold,f); } intvec A=(0,ord(subst(f,var(1),0))); intvec B=(ord(subst(f,var(2),0)),0); intvec C,H; list L; int abbruch,i; poly hilf; L[1]=A; f=jet(f,A[2]*B[1]-1,intvec(A[2],B[1])); if (defined(is_ls)) { map xytausch=basering,var(2),var(1); } else { map xytausch=@RR,var(2),var(1); } for (i=2; f!=0; i++) { abbruch=0; while (abbruch==0) { C=leadexp(f); if(jet(f,A[2]*C[1]-A[1]*C[2]-1,intvec(A[2]-C[2],C[1]-A[1]))==0) { abbruch=1; } else { f=jet(f,-C[1]-1,intvec(-1,0)); } } hilf=jet(f,A[2]*C[1]-A[1]*C[2],intvec(A[2]-C[2],C[1]-A[1])); H=leadexp(xytausch(hilf)); A=H[2],H[1]; L[i]=A; f=jet(f,A[2]*B[1]-1,intvec(A[2],B[1]-A[1])); } L[i]=B; if (defined(is_ls)) { return(L); } else { setring @Rold; return(L); } } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),ls; poly f=x5+2x3y-x2y2+3xy5+y6-y7; newtonpoly(f); } /////////////////////////////////////////////////////////////////////////////// proc is_NND (poly f, list #) "USAGE: is_NND(f[,mu,NP]); f poly, mu int, NP list of intvecs ASSUME: f is convenient, that is, f(x,0) != 0 != f(0,y);@* mu (optional) is Milnor number of f.@* NP (optional) is output of @code{newtonpoly(f)}. RETURN: int: 1 if f is Newton non-degenerate, 0 otherwise. SEE ALSO: newtonpoly KEYWORDS: Newton non-degenerate; Newton polygon EXAMPLE: example is_NND; shows examples " { int i; int i_print=printlevel-voice+2; if (size(#)==0) { int mu=milnor(f); list NP=newtonpoly(f); } else { if (typeof(#[1])=="int") { def mu=#[1]; def NP=#[2]; for (i=1;i<=size(NP);i++) { if (typeof(NP[i])!="intvec") { print("third input cannot be Newton polygon ==> ignored ") NP=newtonpoly(f); i=size(NP)+1; } } } else { print("second input cannot be Milnor number ==> ignored ") int mu=milnor(f); NP=newtonpoly(f); } } // computation of the Newton number: int s=size(NP); int nN=-NP[1][2]-NP[s][1]+1; intmat m[2][2]; for(i=1;i<=s-1;i++) { m=NP[i+1],NP[i]; nN=nN+det(m); } if(mu==nN) { // the Newton-polygon is non-degenerate // REFERENCE? (tfuer mehr als 2 Variable gilt nicht, dass mu=nu impliziert, // dass NP nicht ausgeartet ist!, Siehe KOMMENTAR in equising.lib in esIdeal) return(1); } else { return(0); } } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),ls; poly f=x5+y3; is_NND(f); poly g=(x-y)^5+3xy5+y6-y7; is_NND(g); // if already computed, one should give the Minor number and Newton polygon // as second and third input: int mu=milnor(g); list NP=newtonpoly(g); is_NND(g,mu,NP); } /////////////////////////////////////////////////////////////////////////////// proc charPoly(poly f, int M, int N) "USAGE: charPoly(f,M,N); f bivariate poly, M,N int: length and height of Newton polygon of f, which has to be only one line RETURN: the characteristic polynomial of f EXAMPLE: example charPoly; shows an example " { poly charp; int Np=N div gcd(M,N); f=subst(f,var(1),1); for(charp=0; f<>0; f=f-lead(f)) { charp=charp+leadcoef(f)*var(2)^(leadexp(f)[2] div Np);} return(charp); } example { "EXAMPLE:"; echo = 2; ring exring=0,(x,y),dp; charPoly(y4+2y3x2-yx6+x8,8,4); charPoly(y6+3y3x2-x4,4,6); } /////////////////////////////////////////////////////////////////////////////// proc find_in_list(list L,int p) "USAGE: find_in_list(L,p); L: list of intvec(x,y) (sorted in y: L[1][2]>=L[2][2]), int p >= 0 RETURN: int i: L[i][2]=p if existent; otherwise i with L[i][2]

p; i++) {;} return(i); } example { "EXAMPLE:"; echo = 2; list L = intvec(0,4), intvec(1,2), intvec(2,1), intvec(4,0); find_in_list(L,1); L[find_in_list(L,2)]; } /////////////////////////////////////////////////////////////////////////////// proc get_last_divisor(int M, int N) "USAGE: get_last_divisor(M,N); int M,N RETURN: int Q: M=q1*N+r1, N=q2*r1+r2, ..., ri=Q*r(i+1) (Euclidean alg.) EXAMPLE: example get_last_divisor; shows an example " { int R=M%N; int Q=M div N; while (R!=0) {M=N; N=R; R=M%N; Q=M div N;} return(Q) } example { "EXAMPLE"; echo = 2; ring r=0,(x,y),dp; get_last_divisor(12,10); } /////////////////////////////////////////////////////////////////////////////// proc redleit (poly f,intvec S, intvec E) "USAGE: redleit(f,S,E); f poly, S,E intvec(x,y) S,E are two different points on a line in the Newton diagram of f RETURN: poly g: all monomials of f which lie on or below that line NOTE: The main purpose is that if the line defined by S and E is part of the Newton polygon, the result is the quasihomogeneous leading form of f w.r.t. that line. SEE ALSO: newtonpoly EXAMPLE: example redleit; shows an example " { if (E[1]0) { " The HNE was already exact"; return(l); } else { if (Q==-1) { Q=ncols(m); } else { Q=-Q-1; } } int zeile=nrows(m); int spalten,i,M; ideal lastrow=m[zeile,1..Q]; int ringwechsel=(varstr(basering)!="x,y") or (ordstr(basering)!="ls(2),C"); //------------------------- Ringwechsel, falls noetig ------------------------ if (ringwechsel) { def altring = basering; int p = char(basering); if (charstr(basering)!=string(p)) { string tststr=charstr(basering); tststr=tststr[1..find(tststr,",")-1]; //-> "p^k" bzw. "p" if (tststr==string(p)) { if (size(parstr(basering))>1) { // ring (p,a,..),... execute("ring extdguenstig=("+charstr(basering)+"),(x,y),ls;"); } else { // ring (p,a),... string mipl=string(minpoly); ring extdguenstig=(p,`parstr(basering)`),(x,y),ls; if (mipl!="0") { execute("minpoly="+mipl+";"); } } } else { execute("ring extdguenstig=("+charstr(basering)+"),(x,y),ls;"); } } else { // charstr(basering)== p : no parameter ring extdguenstig=p,(x,y),ls; } export extdguenstig; map hole=altring,x,y; //----- map kann sehr zeitaufwendig sein, daher Vermeidung, wo moeglich: ----- if (nvars(altring)==2) { poly f=fetch(altring,f); } else { poly f=hole(f); } ideal a=hole(lastrow); } else { ideal a=lastrow; } list Newton=newtonpoly(f,1); int M1=Newton[size(Newton)-1][1]; // konstant number delt; if (Newton[size(Newton)-1][2]!=1) { " *** The transformed polynomial was not valid!!";} else { //--------------------- Fortsetzung der HNE ---------------------------------- while (Q delta=-d/c: ------- delt=-koeff(f,M,0)/koeff(f,M1,1); a[Q]=delt; dbprint(printlevel-voice+2,"a("+string(zeile-1)+","+string(Q)+") = "+string(delt)); if (Qncols(m)) { spalten=ncols(lastrow); } else { spalten=ncols(m); } matrix mneu[zeile][spalten]; for (i=1; i= maxspalte); } //------------- schreibe Ausgabe fuer hnezaehler-ten Zweig: ------------------ matrix ma[size(HNEaktu)-2][maxspalte]; for (i=1; i<=(size(HNEaktu)-2); i++) { if (ncols(HNEaktu[i+1]) > 1) { ma[i,1..ncols(HNEaktu[i+1])]=HNEaktu[i+1]; } else { ma[i,1]=HNEaktu[i+1][1];} } Ergebnis[hnezaehler]=list(ma,HNEaktu[1],transvers,HNEaktu[size(HNEaktu)]); kill ma; } return(Ergebnis); } /////////////////////////////////////////////////////////////////////////////// proc factorfirst(poly f, int M, int N) "USAGE : factorfirst(f,M,N); f poly, M,N int RETURN: number d such that f=const*(y^(N/e) - d*x^(M/e))^e, where e=gcd(M,N), 0 if such a d does not exist EXAMPLE: example factorfirst; shows an example " { number c = koeff(f,0,N); number delt; int eps,l; int p=char(basering); string ringchar=charstr(basering); if (c == 0) {"Something has gone wrong! I didn't get N correctly!"; exit;} int e = gcd(M,N); if (p==0) { delt = koeff(f,M div e,N - N div e) / (-1*e*c); } else { if (e%p != 0) { delt = koeff(f,M div e,N - N div e) / (-1*e*c); } else { eps = e; for (l = 0; eps%p == 0; l=l+1) { eps=eps div p;} if (defined(HNDebugOn)) {e," -> ",eps,"*",p,"^",l;} delt = koeff(f,(M div e)*p^l,(N div e)*p^l*(eps-1)) / (-1*eps*c); if ((charstr(basering) != string(p)) and (delt != 0)) { //------ coefficient field is not Z/pZ => (p^l)th root is not identity ------- delt=0; if (defined(HNDebugOn)) { "trivial factorization not implemented for", "parameters---I've to use 'factorize'"; } } } } if (defined(HNDebugOn)) {"quasihomogeneous leading form:",f," = ",c, "* (y^"+string(N div e),"-",delt,"* x^"+string(M div e)+")^",e," ?";} if (f != c*(var(2)^(N div e) - delt*var(1)^(M div e))^e) {return(0);} else {return(delt);} } example { "EXAMPLE:"; echo = 2; ring exring=7,(x,y),dp; factorfirst(2*(y3-3x4)^5,20,15); factorfirst(x14+y7,14,7); factorfirst(x14+x8y3+y7,14,7); } /////////////////////////////////////////////////////////////////////////// proc hnexpansion(poly f,list #) "USAGE: hnexpansion(f[,\"ess\"]); f poly ASSUME: f is a bivariate polynomial (in the first 2 ring variables) RETURN: list @code{L}, containing Hamburger-Noether data of @code{f}: If the computation of the HNE required no field extension, @code{L} is a list of lists @code{L[i]} (corresponding to the output of @code{develop}, applied to a branch of @code{f}, but the last entry being omitted): @texinfo @table @asis @item @code{L[i][1]}; matrix: Each row contains the coefficients of the corresponding line of the Hamburger-Noether expansion (HNE) for the i-th branch. The end of the line is marked in the matrix by the first ring variable (usually x). @item @code{L[i][2]}; intvec: indicating the length of lines of the HNE @item @code{L[i][3]}; int: 0 if the 1st ring variable was transversal (with respect to the i-th branch), @* 1 if the variables were changed at the beginning of the computation, @* -1 if an error has occurred. @item @code{L[i][4]}; poly: the transformed equation of the i-th branch to make it possible to extend the Hamburger-Noether data a posteriori without having to do all the previous calculation once again (0 if not needed). @end table @end texinfo If the computation of the HNE required a field extension, the first entry @code{L[1]} of the list is a ring, in which a list @code{hne} of lists (the HN data, as above) and a polynomial @code{f} (image of @code{f} over the new field) are stored. @* If called with an additional input parameter, @code{hnexpansion} computes only one representative for each class of conjugate branches (over the ground field active when calling the procedure). In this case, the returned list @code{L} always has only two entries: @code{L[1]} is either a list of lists (the HN data) or a ring (as above), and @code{L[2]} is an integer vector (the number of branches in the respective conjugacy classes). NOTE: If f is known to be irreducible as a power series, @code{develop(f)} could be chosen instead to avoid a change of basering during the computations. @* Increasing @code{printlevel} leads to more and more comments. @* Having defined a variable @code{HNDebugOn} leads to a maximum number of comments. SEE ALSO: develop, extdevelop, param, displayHNE EXAMPLE: example hnexpansion; shows an example " { int essential; if (size(#)==1) { essential=1; } int field_ext; def altring=basering; //--------- Falls Ring (p^k,a),...: Wechsel in (p,a),... + minpoly ----------- if ( hasGFCoefficient(basering) ) { string strmip=string(minpoly); string strf=string(f); execute("ring tempr=("+string(char(basering))+","+parstr(basering)+"),(" +varstr(basering)+"),dp;"); execute("minpoly="+strmip+";"); execute("poly f="+strf+";"); field_ext=1; def L=pre_HN(f,essential); if (size(L)==0) { return(list()); } def HNEring=L[1]; setring HNEring; if ((typeof(hne[1])=="ideal")) { return(list()); } if ((voice==2) && (printlevel > -1)) { "// Attention: The parameter",par(1),"may have changed its meaning!"; "// It needs no longer be a generator of the cyclic group of unities!"; } dbprint(printlevel-voice+2, "// result: "+string(size(hne))+" branch(es) successfully computed."); } else { def L=pre_HN(f,essential); if (size(L)==0) { return(list()); } if (L[2]==1) { field_ext=1; } intvec hne_conj=L[3]; def HNEring=L[1]; setring HNEring; if ((typeof(hne[1])=="ideal")) { return(list()); } dbprint(printlevel-voice+2, "// result: "+string(size(hne))+" branch(es) successfully computed."); } // ----- Lossen 10/02 : the branches have to be resorted to be able to // ----- display the multsequence in a nice way if (size(hne)>2) { int i,j,k,m; list dummy; int nbsave; int no_br = size(hne); intmat nbhd[no_br][no_br]; for (i=1;i= nbhd[i,j]) and (k map data to original ring setring altring; if ((npars(altring)==1) and (minpoly!=0)) { ring HNhelpring=char(altring),(a,x,y),ls; list hne=imap(HNEring,hne); setring altring; map mmm=HNhelpring,par(1),var(1),var(2); list hne=mmm(hne); kill mmm,HNhelpring; } else { list hne=fetch(HNEring,hne); } kill HNEring; if (essential==1) { dbprint(printlevel-voice+3,""+ "// No change of ring necessary, return value is a list: // first entry = list : HN expansion of essential branches. // second entry = intvec: numbers of conjugated branches "); return(list(hne,hne_conj)); } else { dbprint(printlevel-voice+3,""+ "// No change of ring necessary, return value is HN expansion."); return(hne); } } } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),dp; // First, an example which requires no field extension: list Hne=hnexpansion(x4-y6); size(Hne); // number of branches displayHNE(Hne); // HN expansion of branches param(Hne[1]); // parametrization of 1st branch param(Hne[2]); // parametrization of 2nd branch // An example which requires a field extension: list L=hnexpansion((x4-y6)*(y2+x4)); def R=L[1]; setring R; displayHNE(hne); basering; setring r; kill R; // Computing only one representative per conjugacy class: L=hnexpansion((x4-y6)*(y2+x4),"ess"); def R=L[1]; setring R; displayHNE(hne); L[2]; // number of branches in respective conjugacy classes } /////////////////////////////////////////////////////////////////////////////// static proc pre_HN (poly f, int essential) "NOTE: This procedure is only for internal use, it is called via hnexpansion RETURN: list: first entry = HNEring (containing list hne, poly f) second entry = 0 if no change of base ring necessary 1 if change of base ring necessary third entry = numbers of conjugates ( if essential = 1 ) if some error has occured, the empty list is returned " { def altring = basering; int p = char(basering); int field_ext; intvec hne_conj; //-------------------- Tests auf Zulaessigkeit von basering ------------------ if (charstr(basering)=="real") { " Singular cannot factorize over 'real' as ground field"; return(list()); } if (size(maxideal(1))<2) { " A univariate polynomial ring makes no sense !"; return(list()); } if (size(maxideal(1))>2) { dbprint(printlevel-voice+2, " Warning: all variables except the first two will be ignored!"); } if (hasGFCoefficient(basering)) { ERROR(" ring of type (p^k,a) not implemented"); //---------------------------------------------------------------------------- // weder primitives Element noch factorize noch map "char p^k" -> "char -p" // [(p^k,a)->(p,a) ground field] noch fetch //---------------------------------------------------------------------------- } //----------------- Definition eines neuen Ringes: HNEring ------------------- string namex=varstr(1); string namey=varstr(2); if ((npars(altring)==0)&&(find(charstr(altring),"real")==0)) { // kein Parameter, nicht 'real' ring HNEring = char(altring),(x,y),ls; map m=altring,x,y; poly f=m(f); export f; kill m; } else { string mipl=string(minpoly); if (mipl=="0") { "// ** WARNING: Algebraic extension of given ground field not possible!"; "// ** We try to develop this polynomial, but if the need for a field"; "// ** extension occurs during the calculation, we cannot proceed with"; "// ** the corresponding branches."; execute("ring HNEring=("+charstr(basering)+"),(x,y),ls;"); } else { string pa=parstr(altring); ring HNhelpring=p,`pa`,dp; execute("poly mipo="+mipl+";"); // Minimalpolynom in Polynom umgewandelt ring HNEring=(p,a),(x,y),ls; map getminpol=HNhelpring,a; mipl=string(getminpol(mipo)); // String umgewandelt mit 'a' als Param. execute("minpoly="+mipl+";"); // "minpoly=poly is not supported" kill HNhelpring; if(defined(getminpol)){ kill getminpol; } } if (nvars(altring)==2) { poly f=fetch(altring,f); export f; } else { if (defined(pa)) { // Parameter hatte vorher anderen Namen als 'a' ring HNhelpring=p,(`pa`,x,y),ls; poly f=imap(altring,f); setring HNEring; map m=HNhelpring,a,x,y; poly f=m(f); kill HNhelpring; } else { map m=altring,x,y; poly f=m(f); } export f; kill m; } } if (defined(HNDebugOn)) {"received polynomial: ",f,", with x =",namex,", y =",namey;} //----------------------- Variablendefinitionen ------------------------------ int Abbruch,i,NullHNEx,NullHNEy; string str; list Newton,hne; // --- changed for SINGULAR 3: --- hne=ideal(0); export hne; //====================== Tests auf Zulaessigkeit des Polynoms ================ //-------------------------- Test, ob Einheit oder Null ---------------------- if (subst(subst(f,x,0),y,0)!=0) { dbprint(printlevel+1, "The given polynomial is a unit in the power series ring!"); setring altring; kill HNEring; return(list()); // there are no HNEs } if (f==0) { dbprint(printlevel+1,"The given polynomial is zero!"); setring altring; kill HNEring; return(list()); // there are no HNEs } //----------------------- Test auf Quadratfreiheit -------------------------- if ((p==0) and (size(charstr(basering))==1)) { //-------- Fall basering==0,... : Wechsel in Ring mit char >0 ---------------- // weil squarefree eine Standardbasis berechnen muss (verwendet Syzygien) // -- wenn f in diesem Ring quadratfrei ist, dann erst recht im Ring HNEring //---------------------------------------------------------------------------- int testerg=(polytest(f)==0); ring zweitring = 32003,(x,y),dp; map polyhinueber=HNEring,x,y; // fetch geht nicht poly f=polyhinueber(f); poly test_sqr=squarefree(f); if (test_sqr != f) { if (printlevel>0) { "Most probably the given polynomial is not squarefree. But the test was"; "made in characteristic 32003 and not 0 to improve speed. You can"; "(r) redo the test in char 0 (but this may take some time)"; "(c) continue the development, if you're sure that the polynomial IS", "squarefree"; if (testerg==1) { "(s) continue the development with a squarefree factor (*)";} "(q) or just quit the algorithm (default action)"; "";"Please enter the letter of your choice:"; str=read("")[1]; // reads one character } else { str="r"; } // printlevel <= 0: non-interactive behaviour setring HNEring; map polyhinueber=zweitring,x,y; if (str=="r") { poly test_sqr=squarefree(f); if (test_sqr != f) { if (printlevel>0) { "The given polynomial is in fact not squarefree."; } else { "The given polynomial is not squarefree!"; } "I'll continue with the radical."; f=test_sqr; } else { dbprint(printlevel, "everything is ok -- the polynomial is squarefree in characteristic 0"); } } else { if ((str=="s") and (testerg==1)) { "(*)attention: it could be that the factor is only one in char 32003!"; f=polyhinueber(test_sqr); } else { if (str<>"c") { setring altring; kill HNEring;kill zweitring; return(list());} else { "if the algorithm doesn't terminate, you were wrong...";} }} kill zweitring; if (defined(HNDebugOn)) {"I continue with the polynomial",f; } } else { setring HNEring; kill zweitring; } } //------------------ Fall Char > 0 oder Ring hat Parameter ------------------- else { poly test_sqr=squarefree(f); if (test_sqr != f) { if (printlevel>0) { if (test_sqr == 1) { "The given polynomial is of the form g^"+string(p)+","; "therefore not squarefree. You can:"; " (q) quit the algorithm (recommended) or"; " (f) continue with the full radical (using a factorization of the"; " pure power part; this could take much time)"; "";"Please enter the letter of your choice:"; str=read("")[1]; if (str<>"f") { str="q"; } } else { "The given polynomial is not squarefree."; if (p != 0) { " You can:"; " (c) continue with a squarefree divisor (but factors of the form g^" +string(p); " are lost; this is recommended, takes no extra time)"; " (f) continue with the full radical (using a factorization of the"; " pure power part; this could take some time)"; " (q) quit the algorithm"; "";"Please enter the letter of your choice:"; str=read("")[1]; if ((str<>"f") && (str<>"q")) { str="c"; } } else { "I'll continue with the radical."; str="c"; } } // endelse (test_sqr!=1) } else { "//** Error: The given polynomial is not squarefree!"; "//** Since the global variable `printlevel' has the value",printlevel, "we stop here."; "// Either call me again with a squarefree polynomial f or assign"; " printlevel=1;"; "// before calling me with a non-squarefree f."; "// If printlevel > 0, I present some possibilities how to proceed."; str="q"; } if (str=="q") { setring altring;kill HNEring; return(list()); } if (str=="c") { f=test_sqr; } if (str=="f") { f=allsquarefree(f,test_sqr); } } if (defined(HNDebugOn)) {"I continue with the polynomial",f; } } //====================== Ende Test auf Quadratfreiheit ======================= if (subst(subst(f,x,0),y,0)!=0) { "The polynomial is a unit in the power series ring. No HNE computed."; setring altring;kill HNEring; return(list()); } //---------------------- Test, ob f teilbar durch x oder y ------------------- if (subst(f,y,0)==0) { f=f/y; NullHNEy=1; } // y=0 is a solution if (subst(f,x,0)==0) { f=f/x; NullHNEx=1; } // x=0 is a solution Newton=newtonpoly(f,1); i=1; Abbruch=0; //---------------------------------------------------------------------------- // finde Eckpkt. des Newtonpolys, der den Teil abgrenzt, fuer den x transvers: // Annahme: Newton ist sortiert, s.d. Newton[1]=Punkt auf der y-Achse, // Newton[letzt]=Punkt auf der x-Achse //---------------------------------------------------------------------------- while ((i=(Newton[i][2]-Newton[i+1][2])) {Abbruch=1;} else {i=i+1;} } int grenze1=Newton[i][2]; int grenze2=Newton[i][1]; //---------------------------------------------------------------------------- // Stelle Ring bereit zur Uebertragung der Daten im Fall einer Koerperer- // weiterung. Definiere Objekte, die spaeter uebertragen werden. // Binde die Listen (azeilen,...) an den Ring (um sie nicht zu ueberschreiben // bei Def. in einem anderen Ring). //---------------------------------------------------------------------------- ring HNE_noparam = char(altring),(a,x,y),ls; poly f; list azeilen=ideal(0); list HNEs=ideal(0); list aneu=ideal(0); list faktoren=ideal(0); ideal deltais; poly delt; //----- hier steht die Anzahl bisher benoetigter Ringerweiterungen drin: ----- int EXTHNEnumber=0; list EXTHNEring; list HNE_RingDATA; int number_of_letztring; setring HNEring; number_of_letztring=0; // ================= Die eigentliche Berechnung der HNE: ===================== // ------- Berechne HNE von allen Zweigen, fuer die x transversal ist: ------- if (defined(HNDebugOn)) {"1st step: Treat Newton polygon until height",grenze1;} if (grenze1>0) { if (EXTHNEnumber>0){ EXTHNEring = EXTHNEring(1..EXTHNEnumber); } HNE_RingDATA = list(HNEring, HNE_noparam, EXTHNEnumber, EXTHNEring, number_of_letztring); list hilflist=HN(HNE_RingDATA,f,grenze1,1,essential,0,hne_conj,1); kill HNEring, HNE_noparam; if (EXTHNEnumber>0) { kill EXTHNEring(1..EXTHNEnumber);} def HNEring = hilflist[1][1]; def HNE_noparam = hilflist[1][2]; EXTHNEnumber = hilflist[1][3]; for (i=1; i<=EXTHNEnumber; i++) { def EXTHNEring(i)=hilflist[1][4][i]; } if (hilflist[2]==0) { setring HNEring; number_of_letztring=0; } else { setring EXTHNEring(hilflist[2]);} if (hilflist[3]==1){field_ext=1;} hne_conj=hilflist[5]; if (number_of_letztring != hilflist[2]) { // Ringwechsel in Prozedur HN map hole=HNE_noparam,transfproc,x,y; setring HNE_noparam; if (not(defined(f))) {poly f;} f=imap(HNEring,f); setring EXTHNEring(EXTHNEnumber); if (not(defined(f))) {poly f; f=hole(f); export f;} else {f=hole(f);} } number_of_letztring = hilflist[2]; kill hilflist; } if (NullHNEy==1) { if ((typeof(hne[1])=="ideal")) { hne=list(); } hne=hne+list(list(matrix(ideal(0,x)),intvec(1),int(0),poly(0))); if (hne_conj==0) { hne_conj=1; } else { hne_conj = hne_conj, 1; } } // --------------- Berechne HNE von allen verbliebenen Zweigen: -------------- if (defined(HNDebugOn)) {"2nd step: Treat Newton polygon until height",grenze2;} if (grenze2>0) { if (EXTHNEnumber>0){ EXTHNEring = EXTHNEring(1..EXTHNEnumber); } if (essential==1) { number_of_letztring=0; } if (number_of_letztring==0) { setring HNEring; } else { setring EXTHNEring(number_of_letztring); } map xytausch=basering,y,x; HNE_RingDATA = list(HNEring, HNE_noparam, EXTHNEnumber, EXTHNEring, number_of_letztring); list hilflist=HN(HNE_RingDATA,xytausch(f),grenze2,1,essential,1,hne_conj,1); kill HNEring, HNE_noparam; if (EXTHNEnumber>0){ kill EXTHNEring(1..EXTHNEnumber); } def HNEring = hilflist[1][1]; def HNE_noparam = hilflist[1][2]; EXTHNEnumber = hilflist[1][3]; for (i=1; i<=EXTHNEnumber; i++) { def EXTHNEring(i)=hilflist[1][4][i]; } if (hilflist[2]==0) { setring HNEring; number_of_letztring=0; } else { setring EXTHNEring(hilflist[2]); number_of_letztring=hilflist[2]; } if (hilflist[3]==1){field_ext=1;} hne_conj=hilflist[5]; kill hilflist; } if (NullHNEx==1) { if ((typeof(hne[1])=="ideal")) { hne=list(); } hne=hne+list(list(matrix(ideal(0,x)),intvec(1),int(1),poly(0))); if (hne_conj==0) { hne_conj=1; } else { hne_conj = hne_conj, 1; } } // --- aufraeumen --- if (defined(HNEakut)){ kill HNEakut,faktoren,deltais,transformiert,teiler,leitf; } if (defined(hilflist)) {kill hilflist;} if (defined(erg)) {kill erg;} if (defined(delt)) {kill delt;} if (defined(azeilen)) { kill azeilen;} if (defined(aneu)) { kill aneu;} if (defined(transfproc)) { kill transfproc;} if (defined(transf)) { kill transf;} if (not(defined(f))) { poly f = imap(HNEring,f); export f; } return(list(basering,field_ext,hne_conj)); } ////////////////////////////////////////////////////////////////////////////// proc essdevelop (poly f) "USAGE: essdevelop(f); f poly NOTE: command is obsolete, use hnexpansion(f,\"ess\") instead. SEE ALSO: hnexpansion, develop, extdevelop, param " { printlevel=printlevel+1; list Ergebnis=hnexpansion(f,1); printlevel=printlevel-1; return(Ergebnis); } /////////////////////////////////////////////////////////////////////////////// static proc HN (list HNE_RingDATA,poly fneu,int grenze,def Aufruf_Ebene, def essential,def getauscht,intvec hne_conj,int conj_factor) "NOTE: This procedure is only for internal use, it is called via pre_HN RETURN: list: first entry = list of HNErings, second entry = number of new base ring (0 for HNEring, -1 for HNE_noparam, i for EXTHNEring(i)) third entry = 0 if no field extension necessary 1 if field extension necessary forth entry = HNEs (only if no change of basering) " { //---------- Variablendefinitionen fuer den unverzweigten Teil: -------------- if (defined(HNDebugOn)) {"procedure HN",Aufruf_Ebene;} int Abbruch,ende,i,j,k,e,M,N,Q,R,zeiger,zeile,zeilevorher,dd,ii; intvec hqs; int field_ext; int ring_changed, hneshift; intvec conjugates,conj2,conj1; list EXTHNEring; def HNEring = HNE_RingDATA[1]; def HNE_noparam = HNE_RingDATA[2]; int EXTHNEnumber = HNE_RingDATA[3]; for (i=1; i<=EXTHNEnumber; i++) { def EXTHNEring(i)=HNE_RingDATA[4][i]; } int number_of_letztring = HNE_RingDATA[5]; if (defined(basering)) { if (number_of_letztring==0) { kill HNEring; def HNEring=basering; } else { kill EXTHNEring(number_of_letztring); def EXTHNEring(number_of_letztring)=basering; } } else { if ( number_of_letztring==0) { setring HNEring; } else { setring EXTHNEring(number_of_letztring); } } if (not(defined(hne))) {list hne;} poly fvorher; list erg=ideal(0); list HNEs=ideal(0); // um die Listen an den Ring zu binden //-------------------- Bedeutung von Abbruch: -------------------------------- //------- 0:keine Verzweigung | 1:Verzweigung,nicht fertig | 2:fertig -------- // // Struktur von HNEs : Liste von Listen L (fuer jeden Zweig) der Form // L[1]=intvec (hqs), L[2],L[3],... ideal (die Zeilen (0,1,...) der HNE) // L[letztes]=poly (transformiertes f) //---------------------------------------------------------------------------- list Newton; number delt; int p = char(basering); // Ringcharakteristik list azeilen=ideal(0); ideal hilfid; intvec hilfvec; // ======================= der unverzweigte Teil: ============================ while (Abbruch==0) { Newton=newtonpoly(fneu,1); zeiger=find_in_list(Newton,grenze); if (Newton[zeiger][2] != grenze) {"Didn't find an edge in the Newton polygon!";} if (zeiger==size(Newton)-1) { if (defined(HNDebugOn)) {"only one relevant side in Newton polygon";} M=Newton[zeiger+1][1]-Newton[zeiger][1]; N=Newton[zeiger][2]-Newton[zeiger+1][2]; R = M%N; Q = M div N; //-------- 1. Versuch: ist der quasihomogene Leitterm reine Potenz ? ------ // (dann geht alles wie im irreduziblen Fall) //------------------------------------------------------------------------- e = gcd(M,N); delt=factorfirst(redleit(fneu,Newton[zeiger],Newton[zeiger+1]) /x^Newton[zeiger][1],M,N); if (delt==0) { if (defined(HNDebugOn)) {" The given polynomial is reducible !";} Abbruch=1; } if (Abbruch==0) { //----------- fneu,zeile retten fuer den Spezialfall (###): ------------- fvorher=fneu;zeilevorher=zeile; if (R==0) { //-------- transformiere fneu mit T1, wenn kein Abbruch nachher: ------ if (N>1) { fneu = T1_Transform(fneu,delt,M div e); } else { ende=1; } if (defined(HNDebugOn)) {"a("+string(zeile)+","+string(Q)+") =",delt;} azeilen[zeile+1][Q]=delt; } else { //------------- R > 0 : transformiere fneu mit T2 --------------------- erg=T2_Transform(fneu,delt,M,N,referencepoly(Newton)); fneu=erg[1];delt=erg[2]; //----- vollziehe Euklid.Alg. nach, um die HN-Matrix zu berechnen: ---- while (R!=0) { if (defined(HNDebugOn)) { "h("+string(zeile)+") =",Q; } hqs[zeile+1]=Q; // denn zeile beginnt mit dem Wert 0 //--------------- markiere das Zeilenende der HNE: ------------------- azeilen[zeile+1][Q+1]=x; zeile=zeile+1; //-------- Bereitstellung von Speicherplatz fuer eine neue Zeile: ---- azeilen[zeile+1]=ideal(0); M=N; N=R; R=M%N; Q=M div N; } if (defined(HNDebugOn)) {"a("+string(zeile)+","+string(Q)+") =",delt;} azeilen[zeile+1][Q]=delt; } if (defined(HNDebugOn)) {"transformed polynomial: ",fneu;} grenze=e; //----------------------- teste Abbruchbedingungen: --------------------- if (subst(fneu,y,0)==0) { // <==> y|fneu dbprint(printlevel-voice+3,"finite HNE of one branch found"); // voice abzufragen macht bei rekursiven procs keinen Sinn azeilen[zeile+1][Q+1]=x; //----- Q wird nur in hqs eingetragen, wenn der Spezialfall nicht // eintritt (siehe unten) ----- Abbruch=2; if (grenze>1) { if (jet(fneu,1,intvec(0,1))==0) { //- jet(...)=alle Monome von fneu, die nicht durch y2 teilbar sind - "THE TEST FOR SQUAREFREENESS WAS BAD!!"; " The polynomial was NOT squarefree!!!";} else { //----------------------- Spezialfall (###): ----------------------- // Wir haben das Problem, dass die HNE eines Zweiges hier abbricht, // aber ein anderer Zweig bis hierher genau die gleiche HNE hat, die // noch weiter geht // Loesung: mache Transform. rueckgaengig und behandle fneu im // Verzweigungsteil //------------------------------------------------------------------ Abbruch=1; fneu=fvorher;zeile=zeilevorher;grenze=Newton[zeiger][2]; }} else {fneu=0;} // fneu nicht mehr gebraucht - spare Speicher if (Abbruch==2) { hqs[zeile+1]=Q; } } // Spezialfall nicht eingetreten else { if (ende==1) { dbprint(printlevel-voice+2,"HNE of one branch found"); Abbruch=2; hqs[zeile+1]=-Q-1;} } } // end(if Abbruch==0) } // end(if zeiger...) else { Abbruch=1;} } // end(while Abbruch==0) // ===================== der Teil bei Verzweigung: =========================== if (Abbruch==1) { //---------- Variablendefinitionen fuer den verzweigten Teil: --------------- poly leitf,teiler,transformiert; list aneu=ideal(0); list faktoren; ideal deltais; list HNEakut=ideal(0); intvec eis; int zaehler,hnezaehler,zl,zl1,M1,N1,R1,Q1,needext; int numberofRingchanges,lastRingnumber,ringischanged,flag; string letztringname; zeiger=find_in_list(Newton,grenze); if (defined(HNDebugOn)) { "Branching part reached---Newton polygon :",Newton; "relevant part until height",grenze,", from",Newton[zeiger],"on"; } azeilen=list(hqs)+azeilen; // hat jetzt Struktur von HNEs: hqs in der 1.Zeile //======= Schleife fuer jede zu betrachtende Seite des Newtonpolygons: ====== for(i=zeiger; inumber_of_letztring)) { // ----- setze ring zurueck fuer neue Kante ----- // ---- (damit konjugierte Zweige erkennbar) ----- hneshift=hneshift+hnezaehler; hnezaehler=0; ring_changed=0; def SaveRing = EXTHNEring(EXTHNEnumber); setring SaveRing; if (not(defined(HNEs))) { // HN wurde zum 2.Mal von pre_HN aufgerufen list HNEs=ideal(0); } for (k=number_of_letztring+1; k<=EXTHNEnumber; k++) { kill EXTHNEring(k);} EXTHNEnumber=number_of_letztring; if (EXTHNEnumber==0) { setring HNEring; } else { setring EXTHNEring(EXTHNEnumber); } if (not(defined(HNEs))) { list HNEs; } HNEs=ideal(0); deltais=0; delt=0; if (defined(zerlege)) { kill zerlege; } } if (defined(HNDebugOn)) { "we consider side",Newton[i],Newton[i+1]; } M=Newton[i+1][1]-Newton[i][1]; N=Newton[i][2]-Newton[i+1][2]; R = M%N; Q = M div N; e=gcd(M,N); needext=1; letztringname=nameof(basering); lastRingnumber=EXTHNEnumber; faktoren=list(ideal(charPoly(redleit(fneu,Newton[i],Newton[i+1]) /(x^Newton[i][1]*y^Newton[i+1][2]),M,N) ), intvec(1)); // = (zu faktoriserendes Poly, 1) conjugates=conj_factor; //-- wechsle so lange in Ringerweiterungen, bis Leitform vollstaendig // in Linearfaktoren zerfaellt ----- for (numberofRingchanges=1; needext==1; numberofRingchanges++) { leitf=redleit(fneu,Newton[i],Newton[i+1])/ (x^Newton[i][1]*y^Newton[i+1][2]); delt=factorfirst(leitf,M,N); needext=0; if (delt==0) { //---------- Sonderbehandlung: faktorisiere einige Polynome ueber Q(a): -- if ((charstr(basering)=="0,a") and (essential==0)) { // ==================================================== // neu CL: 06.10.05 poly CHPOLY=charPoly(leitf,M,N); poly tstpoly; if (defined(faktoren)!=0) { // Test, damit kein Fehler eingebaut (vermutlich nicht notwendig) tstpoly = faktoren[1][1]^faktoren[2][1]; for (k=2; k<=size(faktoren[1]); k++) { tstpoly = tstpoly * faktoren[1][k]^faktoren[2][k]; } tstpoly = CHPOLY-tstpoly*(CHPOLY/tstpoly); kill CHPOLY; } if ((numberofRingchanges>1) and (defined(faktoren)!=0) and (tstpoly==0)) { def L_help=factorlist(faktoren,conjugates); faktoren=L_help[1]; conjugates=L_help[2]; kill L_help; } else { faktoren=factorize(charPoly(leitf,M,N)); conjugates=conj_factor; for (k=2;k<=size(faktoren[2]);k++) {conjugates=conjugates,conj_factor;} } kill tstpoly; // Ende neu (vorher nur else Fall) // ==================================================== } else { //------------------ faktorisiere das charakt. Polynom: ---------------- if ((numberofRingchanges==1) or (essential==0)) { def L_help=factorlist(faktoren,conjugates); faktoren=L_help[1]; conjugates=L_help[2]; kill L_help; } else { // eliminiere alle konjugierten Nullstellen bis auf eine: ideal hilf_id; for (zaehler=1; zaehler<=size(faktoren[1]); zaehler++) { hilf_id=factorize(faktoren[1][zaehler],1); if (size(hilf_id)>1) { poly fac=hilf_id[1]; dd=deg(fac); // Zur Sicherheit: if (deg(fac)==0) { fac=hilf_id[2]; } for (k=2;k<=size(hilf_id);k++) { dd=dd+deg(hilf_id[k]); if (deg(hilf_id[k]) wegwerfen! if (defined(HNDebugOn)) {"factor of leading form found:",teiler;} if (teiler/y2 == 0) { // --> Faktor hat die Form cy+d deltais[zaehler]=-subst(teiler,y,0)/koeff(teiler,0,1); //=-d/c eis[zaehler]=faktoren[2][j]; conj2[zaehler]=conjugates[j]; zaehler++; } else { dbprint(printlevel-voice+2, " Change of basering (field extension) necessary!"); if (defined(HNDebugOn)) { teiler,"is not yet properly factorized!"; } if (needext==0) { poly zerlege=teiler; } needext=1; field_ext=1; } } } // end(for j) } else { deltais=ideal(delt); eis=e; conj2=conj_factor; } if (defined(HNDebugOn)) {"roots of char. poly:";deltais; "with multiplicities:",eis;} if (needext==1) { //--------------------- fuehre den Ringwechsel aus: --------------------- ringischanged=1; if ((size(parstr(basering))>0) && string(minpoly)=="0") { " ** We've had bad luck! The HNE cannot be calculated completely!"; // HNE in transzendenter Erweiterung fehlgeschlagen kill zerlege; ringischanged=0; break; // weiter mit gefundenen Faktoren } if (parstr(basering)=="") { EXTHNEnumber++; def EXTHNEring(EXTHNEnumber) = splitring(zerlege); setring EXTHNEring(EXTHNEnumber); poly transf=0; poly transfproc=0; ring_changed=1; export transfproc; } else { if (numberofRingchanges>1) { // ein Ringwechsel hat nicht gereicht def helpring = splitring(zerlege,list(transf,transfproc,faktoren)); kill EXTHNEring(EXTHNEnumber); def EXTHNEring(EXTHNEnumber)=helpring; setring EXTHNEring(EXTHNEnumber); kill helpring; poly transf=erg[1]; poly transfproc=erg[2]; ring_changed=1; list faktoren=erg[3]; export transfproc; kill erg; } else { if (ring_changed==1) { // in dieser proc geschah schon Ringwechsel EXTHNEnumber++; def EXTHNEring(EXTHNEnumber) = splitring(zerlege,list(a,transfproc)); setring EXTHNEring(EXTHNEnumber); poly transf=erg[1]; poly transfproc=erg[2]; export transfproc; kill erg; } else { // parameter war vorher da EXTHNEnumber++; def EXTHNEring(EXTHNEnumber) = splitring(zerlege,a); setring EXTHNEring(EXTHNEnumber); poly transf=erg[1]; poly transfproc=transf; ring_changed=1; export transfproc; kill erg; }} } //----------------------------------------------------------------------- // transf enthaelt jetzt den alten Parameter des Ringes, der aktiv war // vor Beginn der Schleife (evtl. also ueber mehrere Ringwechsel // weitergereicht), // transfproc enthaelt den alten Parameter des Ringes, der aktiv war zu // Beginn der Prozedur, und der an die aufrufende Prozedur zurueckgegeben // werden muss // transf ist Null, falls der alte Ring keinen Parameter hatte, // das gleiche gilt fuer transfproc //----------------------------------------------------------------------- //---- Neudef. von Variablen, Uebertragung bisher errechneter Daten: ---- poly leitf,teiler,transformiert; list aneu=ideal(0); ideal deltais; number delt; setring HNE_noparam; if (defined(letztring)) { kill letztring; } if (EXTHNEnumber>1) { def letztring=EXTHNEring(EXTHNEnumber-1); } else { def letztring=HNEring; } if (not defined(fneu)) {poly fneu;} fneu=imap(letztring,fneu); if (not defined(f)) {poly f;} f=imap(letztring,f); if (not defined(hne)) {list hne;} hne=imap(letztring,hne); if (not defined(faktoren)) {list faktoren; } faktoren=imap(letztring,faktoren); if (not(defined(azeilen))){list azeilen,HNEs;} azeilen=imap(letztring,azeilen); HNEs=imap(letztring,HNEs); setring EXTHNEring(EXTHNEnumber); if (not(defined(hole))) { map hole; } hole=HNE_noparam,transf,x,y; poly fneu=hole(fneu); if (not defined(faktoren)) { list faktoren; faktoren=hole(faktoren); } if (not(defined(f))) { poly f=hole(f); list hne=hole(hne); export f,hne; } } } // end (while needext==1) bzw. for (numberofRingchanges) if (eis==0) { i++; continue; } if (ringischanged==1) { list erg,HNEakut; // dienen nur zum Sp. von Zwi.erg. ideal hilfid; erg=ideal(0); HNEakut=erg; hole=HNE_noparam,transf,x,y; setring HNE_noparam; if (not(defined(azeilen))){list azeilen,HNEs;} azeilen=imap(letztring,azeilen); HNEs=imap(letztring,HNEs); setring EXTHNEring(EXTHNEnumber); list azeilen=hole(azeilen); list HNEs=hole(HNEs); kill letztring; ringischanged=0; } //============ Schleife fuer jeden gefundenen Faktor der Leitform: ========= for (j=1; j<=size(eis); j++) { //---- Mache Transformation T1 oder T2, trage Daten in HNEs ein, // falls HNE abbricht: ---- //------------------------ Fall R==0: ------------------------------------- if (R==0) { transformiert = T1_Transform(fneu,number(deltais[j]),M div e); if (defined(HNDebugOn)) { "a("+string(zeile)+","+string(Q)+") =",deltais[j]; "transformed polynomial: ",transformiert; } if (subst(transformiert,y,0)==0) { dbprint(printlevel-voice+3,"finite HNE found"); hnezaehler++; //-------- trage deltais[j],x ein in letzte Zeile, fertig: ------------- HNEakut=azeilen+list(poly(0)); // =HNEs[hnezaehler]; hilfid=HNEakut[zeile+2]; hilfid[Q]=deltais[j]; hilfid[Q+1]=x; HNEakut[zeile+2]=hilfid; HNEakut[1][zeile+1]=Q; // aktualisiere Vektor mit den hqs HNEs[hnezaehler]=HNEakut; conj1[hneshift+hnezaehler]=conj2[j]; if (eis[j]>1) { transformiert=transformiert/y; if (subst(transformiert,y,0)==0){"THE TEST FOR SQUAREFREENESS WAS BAD!" +"! The polynomial was NOT squarefree!!!";} else { //--- Spezialfall (###) eingetreten: Noch weitere Zweige vorhanden -- eis[j]=eis[j]-1; } } } } else { //------------------------ Fall R <> 0: --------------------------------- erg=T2_Transform(fneu,number(deltais[j]),M,N,referencepoly(Newton)); transformiert=erg[1];delt=erg[2]; if (defined(HNDebugOn)) {"transformed polynomial: ",transformiert;} if (subst(transformiert,y,0)==0) { dbprint(printlevel-voice+3,"finite HNE found"); hnezaehler++; //---------------- trage endliche HNE in HNEs ein: --------------------- HNEakut=azeilen; // dupliziere den gemeins. Anfang der HNE's zl=2; // (kommt schliesslich nach HNEs[hnezaehler]) //---------------------------------------------------------------------- // Werte von: zeile: aktuelle Zeilennummer der HNE (gemeinsamer Teil) // zl : die HNE spaltet auf; zeile+zl ist der Index fuer die // Zeile des aktuellen Zweigs; (zeile+zl-2) ist die // tatsaechl. Zeilennr. (bei 0 angefangen) der HNE // ([1] <- intvec(hqs), [2] <- 0. Zeile usw.) //---------------------------------------------------------------------- //----- vollziehe Euklid.Alg. nach, um die HN-Matrix zu berechnen: ----- M1=M;N1=N;R1=R;Q1=M1 div N1; while (R1!=0) { if (defined(HNDebugOn)) { "h("+string(zeile+zl-2)+") =",Q1; } HNEakut[1][zeile+zl-1]=Q1; HNEakut[zeile+zl][Q1+1]=x; // markiere das Zeilenende der HNE zl=zl+1; //----- Bereitstellung von Speicherplatz fuer eine neue Zeile: -------- HNEakut[zeile+zl]=ideal(0); M1=N1; N1=R1; R1=M1%N1; Q1=M1 div N1; } if (defined(HNDebugOn)) { "a("+string(zeile+zl-2)+","+string(Q1)+") =",delt; } HNEakut[zeile+zl][Q1] =delt; HNEakut[zeile+zl][Q1+1]=x; HNEakut[1][zeile+zl-1] =Q1; // aktualisiere Vektor mit hqs HNEakut[zeile+zl+1]=poly(0); HNEs[hnezaehler]=HNEakut; conj1[hneshift+hnezaehler]=conj2[j]; //-------------------- Ende der Eintragungen in HNEs ------------------- if (eis[j]>1) { transformiert=transformiert/y; if (subst(transformiert,y,0)==0){"THE TEST FOR SQUAREFREENESS WAS BAD!" +" The polynomial was NOT squarefree!!!";} else { //--- Spezialfall (###) eingetreten: Noch weitere Zweige vorhanden -- eis[j]=eis[j]-1; }} } // endif (subst()==0) } // endelse (R<>0) //========== Falls HNE nicht abbricht: Rekursiver Aufruf von HN: ========== //------------------- Berechne HNE von transformiert ---------------------- if (subst(transformiert,y,0)!=0) { lastRingnumber=EXTHNEnumber; if (EXTHNEnumber>0){ EXTHNEring = EXTHNEring(1..EXTHNEnumber); } HNE_RingDATA = list( HNEring, HNE_noparam, EXTHNEnumber, EXTHNEring, lastRingnumber); if (defined(HNerg)) {kill HNerg;} list HNerg=HN(HNE_RingDATA,transformiert,eis[j],Aufruf_Ebene+1, essential,getauscht,hne_conj,conj2[j]); HNE_RingDATA = HNerg[1]; if (conj1==0) { conj1=HNerg[5]; } else { conj1 = conj1,HNerg[5]; } if (HNerg[3]==1) { field_ext=1; } if (HNerg[2]==lastRingnumber) { // kein Ringwechsel in HN aufgetreten if (not(defined(aneu))) { list aneu; } aneu = HNerg[4]; } else { // Ringwechsel aufgetreten if (defined(HNDebugOn)) {" ring change in HN(",Aufruf_Ebene+1,") detected";} EXTHNEnumber = HNerg[1][3]; for (ii=lastRingnumber+1; ii<=EXTHNEnumber; ii++) { def EXTHNEring(ii)=HNerg[1][4][ii]; } if (HNerg[2]==0) { setring HNEring; } else { setring EXTHNEring(HNerg[2]); } def tempRing=HNerg[4]; def aneu=imap(tempRing,HNEs); kill tempRing; //--- stelle lokale Variablen im neuen Ring wieder her, und rette // gegebenenfalls ihren Inhalt: ---- list erg,faktoren,HNEakut; ideal hilfid; erg=ideal(0); faktoren=erg; HNEakut=erg; poly leitf,teiler,transformiert; map hole=HNE_noparam,transfproc,x,y; setring HNE_noparam; if (lastRingnumber>0) { def letztring=EXTHNEring(lastRingnumber); } else { def letztring=HNEring; } if (not defined(HNEs)) {list HNEs;} HNEs=imap(letztring,HNEs); if (not defined(azeilen)) {list azeilen;} azeilen=imap(letztring,azeilen); if (not defined(deltais)) {ideal deltais;} deltais=imap(letztring,deltais); if (not defined(delt)) {poly delt;} delt=imap(letztring,delt); if (not defined(fneu)) {poly fneu;} fneu=imap(letztring,fneu); if (not defined(f)) {poly f;} f=imap(letztring,f); if (not defined(hne)) {list hne;} hne=imap(letztring,hne); setring EXTHNEring(EXTHNEnumber); list HNEs=hole(HNEs); list azeilen=hole(azeilen); ideal deltais=hole(deltais); number delt=number(hole(delt)); poly fneu=hole(fneu); if (not(defined(f))) { poly f=hole(f); list hne=hole(hne); export f,hne; } } //========== Verknuepfe bisherige HNE mit von HN gelieferten HNEs: ====== if (R==0) { HNEs,hnezaehler=constructHNEs(HNEs,hnezaehler,aneu,azeilen,zeile, deltais,Q,j); kill aneu; } else { for (zaehler=1; zaehler<=size(aneu); zaehler++) { hnezaehler++; HNEakut=azeilen; // dupliziere den gemeinsamen Anfang der HNE's zl=2; // (kommt schliesslich nach HNEs[hnezaehler]) //------------ Trage Beitrag dieser Transformation T2 ein: ------------- //------ Zur Bedeutung von zeile, zl: siehe Kommentar weiter oben ------ //----- vollziehe Euklid.Alg. nach, um die HN-Matrix zu berechnen: ----- M1=M;N1=N;R1=R;Q1=M1 div N1; while (R1!=0) { if (defined(HNDebugOn)) { "h("+string(zeile+zl-2)+") =",Q1; } HNEakut[1][zeile+zl-1]=Q1; HNEakut[zeile+zl][Q1+1]=x; // Markierung des Zeilenendes der HNE zl=zl+1; //----- Bereitstellung von Speicherplatz fuer eine neue Zeile: -------- HNEakut[zeile+zl]=ideal(0); M1=N1; N1=R1; R1=M1%N1; Q1=M1 div N1; } if (defined(HNDebugOn)) { "a("+string(zeile+zl-2)+","+string(Q1)+") =",delt; } HNEakut[zeile+zl][Q1]=delt; //-- Daten aus T2_Transform sind eingetragen; haenge Daten von HN an: -- hilfid=HNEakut[zeile+zl]; for (zl1=Q1+1; zl1<=ncols(aneu[zaehler][2]); zl1++) { hilfid[zl1]=aneu[zaehler][2][zl1]; } HNEakut[zeile+zl]=hilfid; // ------ vorher HNEs[.][zeile+zl]<-aneu[.][2], // jetzt [zeile+zl+1] <- [3] usw.: -------- for (zl1=3; zl1<=size(aneu[zaehler]); zl1++) { HNEakut[zeile+zl+zl1-2]=aneu[zaehler][zl1]; } //--- setze hqs zusammen: HNEs[hnezaehler][1]=HNEs[..][1],aneu[..][1] -- hilfvec=HNEakut[1],aneu[zaehler][1]; HNEakut[1]=hilfvec; //-------- weil nicht geht: liste[1]=liste[1],aneu[zaehler][1] --------- HNEs[hnezaehler]=HNEakut; } // end(for zaehler) kill aneu; } // endelse (R<>0) } // endif (subst()!=0) (weiteres Aufblasen mit HN) } // end(for j) (Behandlung der einzelnen delta_i) // ------------------------- new for essdevelop ---------------------------- if ((essential==1) and (defined(SaveRing))) { // ----- uebertrage Daten in gemeinsame Koerpererweiterung --------------- if (EXTHNEnumber>number_of_letztring) { // ----- fuer aktuelle Kante war Koerpererweiterung erforderlich ------- EXTHNEnumber++; string @miniPol_EXTHNEring(EXTHNEnumber-1) = string(minpoly); setring SaveRing; string @miniPol_SaveRing = string(minpoly); setring HNE_noparam; if (not(defined(a_x))){ map a_x,a_y; poly mp_save, mp_new; } execute("mp_save= " + @miniPol_SaveRing + ";"); execute("mp_new = " + @miniPol_EXTHNEring(EXTHNEnumber-1) + ";" );; if (mp_save==mp_new) { // Sonderfall: wieder gleicher Ring def EXTHNEring(EXTHNEnumber)=SaveRing; setring EXTHNEring(EXTHNEnumber); if (not(defined(f))) {poly f; f=hole(f); export f;} list dummyL=imap(EXTHNEring(EXTHNEnumber-1),HNEs); if (not(defined(HNEs))) { def HNEs=list(); } if ((size(HNEs)==1) and (typeof(HNEs[1])=="ideal")) {HNEs=list();} HNEs[size(HNEs)+1..size(HNEs)+size(dummyL)]=dummyL[1..size(dummyL)]; kill dummyL,SaveRing; } else { // verschiedene Ringe a_x=HNE_noparam,x,0,0; a_y=HNE_noparam,y,0,0; mp_save=a_x(mp_save); // minpoly aus SaveRing mit a --> x mp_new=a_y(mp_new); // minpoly aus SaveRing mit a --> y setring SaveRing; poly mp_new=imap(HNE_noparam,mp_new); list Lfac=factorize(mp_new,1); poly fac=Lfac[1][1]; for (k=2;k<=size(Lfac[1]);k++) { if (deg(Lfac[1][k])0) { if ((size(HNEs)>1) or (typeof(HNEs[1])!="ideal") or (size(HNEs[1])>0)) { if ((typeof(hne[1])=="ideal")) { hne=list(); } hne=hne+extractHNEs(HNEs,getauscht); if (hne_conj==0) { hne_conj=conj1; } else { hne_conj = hne_conj, conj1; } } } } else { // HN wurde rekursiv aufgerufen if (number_of_letztring!=EXTHNEnumber) { // Ringwechsel hatte stattgefunden string mipl_alt = string(minpoly); execute("ring tempRing = ("+charstr(basering)+"),("+varstr(basering)+ "),("+ordstr(basering)+");"); execute("minpoly="+ mipl_alt +";"); list HNEs=imap(EXTHNEring(EXTHNEnumber),HNEs); export HNEs; if (defined(HNDebugOn)) {" ! tempRing defined ! ";} } if (conj1!=0) { hne_conj=conj1; } else { hne_conj=conj_factor; } } if (EXTHNEnumber>0){ EXTHNEring = EXTHNEring(1..EXTHNEnumber); } HNE_RingDATA = list(HNEring, HNE_noparam, EXTHNEnumber, EXTHNEring); if (number_of_letztring==EXTHNEnumber) { return(list(HNE_RingDATA,EXTHNEnumber,field_ext,HNEs,hne_conj)); } else { if (defined(tempRing)) { return(list(HNE_RingDATA,EXTHNEnumber,field_ext,tempRing,hne_conj)); } return(list(HNE_RingDATA,EXTHNEnumber,field_ext,0,hne_conj)); } } /////////////////////////////////////////////////////////////////////////////// static proc constructHNEs (list HNEs,int hnezaehler,list aneu,list azeilen, int zeile,ideal deltais,int Q,int j) "NOTE: This procedure is only for internal use, it is called via HN" { int zaehler,zl; ideal hilfid; list hilflist; intvec hilfvec; for (zaehler=1; zaehler<=size(aneu); zaehler++) { hnezaehler++; // HNEs[hnezaehler]=azeilen; // dupliziere gemeins. Anfang //----------------------- trage neu berechnete Daten ein --------------------- hilfid=azeilen[zeile+2]; hilfid[Q]=deltais[j]; for (zl=Q+1; zl<=ncols(aneu[zaehler][2]); zl++) { hilfid[zl]=aneu[zaehler][2][zl]; } hilflist=azeilen; hilflist[zeile+2]=hilfid; //------------------ haenge uebrige Zeilen von aneu[] an: -------------------- for (zl=3; zl<=size(aneu[zaehler]); zl++) { hilflist[zeile+zl]=aneu[zaehler][zl]; } //--- setze die hqs zusammen: HNEs[hnezaehler][1]=HNEs[..][1],aneu[..][1] ---- if (hilflist[1]==0) { hilflist[1]=aneu[zaehler][1]; } else { hilfvec=hilflist[1],aneu[zaehler][1]; hilflist[1]=hilfvec; } HNEs[hnezaehler]=hilflist; } return(HNEs,hnezaehler); } /////////////////////////////////////////////////////////////////////////////// proc referencepoly (list newton) "USAGE: referencepoly(newton); newton is list of intvec(x,y) which represents points in the Newton diagram (e.g. output of the proc newtonpoly) RETURN: a polynomial which has newton as Newton diagram SEE ALSO: newtonpoly EXAMPLE: example referencepoly; shows an example " { poly f; for (int i=1; i<=size(newton); i++) { f=f+var(1)^newton[i][1]*var(2)^newton[i][2]; } return(f); } example { "EXAMPLE:"; echo = 2; ring exring=0,(x,y),ds; referencepoly(list(intvec(0,4),intvec(2,3),intvec(5,1),intvec(7,0))); } /////////////////////////////////////////////////////////////////////////////// proc factorlist (list L, list #) "USAGE: factorlist(L); L a list in the format of `factorize' RETURN: the nonconstant irreducible factors of L[1][1]^L[2][1] * L[1][2]^L[2][2] *...* L[1][size(L[1])]^... with multiplicities (same format as factorize) SEE ALSO: factorize EXAMPLE: example factorlist; shows an example " { int k; if ((size(#)>=1) and ((typeof(#[1])=="intvec") or (typeof(#[1])=="int"))) { int with_conj = 1; intvec C = #[1]; } else { int with_conj = 0; intvec C = L[2]; } // eine Sortierung der Faktoren eruebrigt sich, weil keine zwei versch. // red.Fakt. einen gleichen irred. Fakt. haben koennen (I.3.27 Diplarb.) int i,gross; list faktoren,hilf; intvec conjugates; ideal hil1,hil2; intvec v,w,hilf_conj; for (i=1; (L[1][i] == jet(L[1][i],0)) && (i1) { v=hilf[2]; faktoren=list(ideal(hil1[2..gross]),intvec(v[2..gross])); conjugates=intvec(hilf_conj[2..gross]); } else { faktoren=hilf; conjugates=hilf_conj; } } else { faktoren=L; conjugates=C; } for (i++; i<=size(L[2]); i++) { //------------------------- linearer Term -- irreduzibel --------------------- if (L[1][i] == jet(L[1][i],1)) { if (L[1][i] != jet(L[1][i],0)) { // konst. Faktoren eliminieren hil1=faktoren[1]; hil1[size(hil1)+1]=L[1][i]; faktoren[1]=hil1; v=faktoren[2],L[2][i]; conjugates=conjugates,C[i]; faktoren[2]=v; } } //----------------------- nichtlinearer Term -- faktorisiere ----------------- else { hilf=factorize(L[1][i]); hilf_conj=C[i]; for (k=2;k<=size(hilf[2]);k++){ hilf_conj=hilf_conj,C[i]; } hilf[2]=hilf[2]*L[2][i]; hil1=faktoren[1]; hil2=hilf[1]; gross=size(hil2); // hil2[1] ist konstant, wird weggelassen: hil1[(size(hil1)+1)..(size(hil1)+gross-1)]=hil2[2..gross]; // ideal+ideal does not work due to simplification; // ideal,ideal not allowed faktoren[1]=hil1; w=hilf[2]; v=faktoren[2],w[2..gross]; conjugates=conjugates,hilf_conj[2..gross]; faktoren[2]=v; } } if (with_conj==0) { return(faktoren); } else { return(list(faktoren,conjugates)); } // for essential development } example { "EXAMPLE:"; echo = 2; ring exring=0,(x,y),ds; list L=list(ideal(x,(x-y)^2*(x+y+1),x+y),intvec(2,2,1)); L; factorlist(L); } /////////////////////////////////////////////////////////////////////////////// proc delta "USAGE: delta(INPUT); INPUT a polynomial defining an isolated plane curve singularity at 0, or the Hamburger-Noether expansion thereof, i.e. the output of @code{develop(f)}, or the output of @code{hnexpansion(f)}, or the list of HN data computed by @code{hnexpansion(f)}. RETURN: int, the delta invariant of the singularity at 0, that is, the vector space dimension of R~/R, (R~ the normalization of the local ring of the singularity). NOTE: In case the Hamburger-Noether expansion of the curve f is needed for other purposes as well it is better to calculate this first with the aid of @code{hnexpansion} and use it as input instead of the polynomial itself. SEE ALSO: deltaLoc, invariants KEYWORDS: delta invariant EXAMPLE: example delta; shows an example " { if (typeof(#[1])=="poly") { // INPUT = polynomial defining the singularity list L=hnexpansion(#[1]); if (typeof(L[1])=="ring") { def altring = basering; def HNring = L[1]; setring HNring; return(delta(hne)); } else { return(delta(L)); } } if (typeof(#[1])=="ring") { // INPUT = HNEring of curve def HNring = #[1]; setring HNring; return(delta(hne)); } if (typeof(#[1])=="matrix") { // INPUT = hne of an irreducible curve return(invariants(#)[5] div 2); } else { // INPUT = hne of a reducible curve list INV=invariants(#); return(INV[size(INV)][3]); } } example { "EXAMPLE:"; echo = 2; ring r = 32003,(x,y),ds; poly f = x25+x24-4x23-1x22y+4x22+8x21y-2x21-12x20y-4x19y2+4x20+10x19y +12x18y2-24x18y-20x17y2-4x16y3+x18+60x16y2+20x15y3-9x16y -80x14y3-10x13y4+36x14y2+60x12y4+2x11y5-84x12y3-24x10y5 +126x10y4+4x8y6-126x8y5+84x6y6-36x4y7+9x2y8-1y9; delta(f); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/homolog.lib000066400000000000000000001707471266270727000203230ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version homolog.lib 4.0.0.0 Jun_2013 "; // $Id: fb8563dc8613f0e553126c18c0dca01d98ec833a $ category="Commutative Algebra"; info=" LIBRARY: homolog.lib Procedures for Homological Algebra AUTHORS: Gert-Martin Greuel, greuel@mathematik.uni-kl.de, @* Bernd Martin, martin@math.tu-cottbus.de @* Christoph Lossen, lossen@mathematik.uni-kl.de PROCEDURES: canonMap(id); the kernel and the cokernel of the canonical map cup(M); cup: Ext^1(M',M') x Ext^1() --> Ext^2() cupproduct(M,N,P,p,q); cup: Ext^p(M',N') x Ext^q(N',P') --> Ext^p+q(M',P') depth(I,M); depth(I,M'), I ideal, M module, M'=coker(M) Ext_R(k,M); Ext^k(M',R), M module, R basering, M'=coker(M) Ext(k,M,N); Ext^k(M',N'), M,N modules, M'=coker(M), N'=coker(N) fitting(M,n); n-th Fitting ideal of M'=coker(M), M module, n int flatteningStrat(M); Flattening stratification of M'=coker(M), M module Hom(M,N); Hom(M',N'), M,N modules, M'=coker(M), N'=coker(N) homology(A,B,M,N); ker(B)/im(A), homology of complex R^k--A->M'--B->N' isCM(M); test if coker(M) is Cohen-Macaulay, M module isFlat(M); test if coker(M) is flat, M module isLocallyFree(M,r); test if coker(M) is locally free of constant rank r isReg(I,M); test if I is coker(M)-sequence, I ideal, M module hom_kernel(A,M,N); ker(M'--A->N') M,N modules, A matrix kohom(A,k); Hom(R^k,A), A matrix over basering R kontrahom(A,k); Hom(A,R^k), A matrix over basering R KoszulHomology(I,M,n); n-th Koszul homology H_n(I,coker(M)), I=ideal tensorMod(M,N); Tensor product of modules M'=coker(M), N'=coker(N) Tor(k,M,N); Tor_k(M',N'), M,N modules, M'=coker(M), N'=coker(N) "; LIB "general.lib"; LIB "deform.lib"; LIB "matrix.lib"; LIB "poly.lib"; LIB "primdec.lib"; /////////////////////////////////////////////////////////////////////////////// proc cup (module M,list #) "USAGE: cup(M,[,any,any]); M=module COMPUTE: cup-product Ext^1(M',M') x Ext^1(M',M') ---> Ext^2(M',M'), where M':=R^m/M, if M in R^m, R basering (i.e. M':=coker(matrix(M))). @* If called with >= 2 arguments: compute symmetrized cup-product ASSUME: all Ext's are finite dimensional RETURN: - if called with 1 argument: matrix, the columns of the output present the coordinates of b_i&b_j with respect to a kbase of Ext^2, where b_1,b_2,... is a kbase of Ext^1 and & denotes cup product;@* - if called with 2 arguments: matrix, the columns of the output present the coordinates of (1/2)(b_i&b_j + b_j&b_i) with respect to a kbase of Ext^2; - if called with 3 arguments: list, @format L[1] = matrix see above (symmetric case, for >=2 arguments) L[2] = matrix of kbase of Ext^1 L[3] = matrix of kbase of Ext^2 @end format NOTE: printlevel >=1; shows what is going on. printlevel >=2; shows result in another representation. @* For computing cupproduct of M itself, apply proc to syz(M)! EXAMPLE: example cup; shows examples " { //---------- initialization --------------------------------------------------- int i,j,k,f0,f1,f2,f3,e1,e2; module M1,M2,A,B,C,ker,ima,ext1,ext2,ext10,ext20; matrix cup[1][0]; matrix kb1,lift1,kb2,mA,mB,mC; ideal tes1,tes2,null; int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //----------------------------------------------------------------------------- //take a resolution of M<--F(0)<--- ... <---F(3) //apply Hom(-,M) and compute the Ext's //----------------------------------------------------------------------------- list resM = nres(M,3); M1 = resM[2]; M2 = resM[3]; f0 = nrows(M); f1 = ncols(M); f2 = ncols(M1); f3 = ncols(M2); tes1 = simplify(ideal(M),10); tes2=simplify(ideal(M1),10); if ((tes1[1]*tes2[1]==0) or (tes1[1]==1) or (tes2[1]==1)) { dbprint(p,"// Ext == 0 , hence 'cup' is the zero-map"); return(@cup); } //------ compute Ext^1 -------------------------------------------------------- B = kohom(M,f2); A = kontrahom(M1,f0); C = intersect(A,B); C = reduce(C,std(null));C = simplify(C,10); ker = lift(A,C)+syz(A); ima = kohom(M,f1); ima = ima + kontrahom(M,f0); ext1 = modulo(ker,ima); ext10 = std(ext1); e1 = vdim(ext10); dbprint(p-1,"// vdim (Ext^1) = "+string(e1)); if (e1 < 0) { "// Ext^1 not of finite dimension"; return(cup); } kb1 = kbase(ext10); kb1 = matrix(ker)*kb1; dbprint(p-1,"// kbase of Ext^1(M,M)", "// - the columns present the kbase elements in Hom(F(1),F(0))", "// - F(*) a free resolution of M",kb1); //------ compute the liftings of Ext^1 ---------------------------------------- mC = matrix(A)*kb1; lift1 =lift(B,mC); dbprint(p-1,"// lift kbase of Ext^1:", "// - the columns present liftings of kbase elements into Hom(F(2),F(1))", "// - F(*) a free resolution of M ",lift1); //------ compute Ext^2 ------------------------------------------------------- B = kohom(M,f3); A = kontrahom(M2,f0); C = intersect(A,B); C = reduce(C,std(null));C = simplify(C,10); ker = lift(A,C)+syz(A); ima = kohom(M,f2); ima = ima + kontrahom(M1,f0); ext2 = modulo(ker,ima); ext20= std(ext2); e2 = vdim(ext20); if (e2<0) { "// Ext^2 not of finite dimension"; return(cup); } dbprint(p-1,"// vdim (Ext^2) = "+string(e2)); kb2 = kbase(ext20); kb2 = matrix(ker)*kb2; dbprint(p-1,"// kbase of Ext^2(M,M)", "// - the columns present the kbase elements in Hom(F(2),F(0))", "// - F(*) is a free resolution of M ",kb2); //------- compute: cup-products of base-elements ----------------------------- for (i=1;i<=e1;i=i+1) { for (j=1;j<=e1;j=j+1) { mA = matrix(ideal(lift1[j]),f1,f2); mB = matrix(ideal(kb1[i]),f0,f1); mC = mB*mA; if (size(#)==0) { //non symmestric mC = matrix(ideal(mC),f0*f2,1); cup= concat(cup,mC); } else //symmetric version { if (j>=i) { if (j>i) { mA = matrix(ideal(lift1[i]),f1,f2); mB = matrix(ideal(kb1[j]),f0,f1); mC = mC+mB*mA;mC=(1/2)*mC; } mC = matrix(ideal(mC),f0*f2,1); cup= concat(cup,mC); } } } } dbprint(p-1,"// matrix of cup-products (in Ext^2)",cup, "////// end level 2 //////"); //------- compute: presentation of base-elements ----------------------------- cup = lift(ker,cup); cup = lift_kbase(cup,ext20); if( p>2 ) { "// the associated matrices of the bilinear mapping 'cup' "; "// corresponding to the kbase elements of Ext^2(M,M) are shown,"; "// i.e. the rows of the final matrix are written as matrix of"; "// a bilinear form on Ext^1 x Ext^1"; matrix BL[e1][e1]; for (k=1;k<=e2;k=k+1) { "//-----component "+string(k)+":"; for (i=1;i<=e1;i=i+1) { for (j=1;j<=e1;j=j+1) { if (size(#)==0) { BL[i,j]=cup[k,j+e1*(i-1)]; } else { if (i<=j) { BL[i,j]=cup[k,j+e1*(i-1)-binomial(i,2)]; BL[j,i]=BL[i,j]; } } } } print(BL); } "////// end level 3 //////"; } if (size(#)>2) { return(cup,kb1,kb2);} else {return(cup);} } example {"EXAMPLE"; echo=2; int p = printlevel; ring rr = 32003,(x,y,z),(dp,C); ideal I = x4+y3+z2; qring o = std(I); module M = [x,y,0,z],[y2,-x3,z,0],[z,0,-y,-x3],[0,z,x,-y2]; print(cup(M)); print(cup(M,1)); // 2nd EXAMPLE (shows what is going on) printlevel = 3; ring r = 0,(x,y),(dp,C); ideal i = x2-y3; qring q = std(i); module M = [-x,y],[-y2,x]; print(cup(M)); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc cupproduct (module M,module N,module P,int p,int q,list #) "USAGE: cupproduct(M,N,P,p,q[,any]); M,N,P modules, p,q integers COMPUTE: cup-product Ext^p(M',N') x Ext^q(N',P') ---> Ext^(p+q)(M',P'), where M':=R^m/M, if M in R^m, R basering (i.e. M':=coker(matrix(M))) ASSUME: all Ext's are of finite dimension RETURN: - if called with 5 arguments: matrix of the associated linear map Ext^p (tensor) Ext^q --> Ext^(p+q), i.e. the columns of present the coordinates of the cup products (b_i & c_j) with respect to a kbase of Ext^p+q (b_i resp. c_j are the chosen bases of Ext^p, resp. Ext^q).@* - if called with 6 arguments: list L, @format L[1] = matrix (see above) L[2] = matrix of kbase of Ext^p(M',N') L[3] = matrix of kbase of Ext^q(N',P') L[4] = matrix of kbase of Ext^p+q(N',P') @end format NOTE: printlevel >=1; shows what is going on. printlevel >=2; shows the result in another representation.@* For computing the cupproduct of M,N itself, apply proc to syz(M), syz(N)! EXAMPLE: example cupproduct; shows examples " { //---------- initialization --------------------------------------------------- int e1,e2,e3,i,j,k,f0,f1,f2; module M1,M2,N1,N2,P1,P2,A,B,C,ker,ima,extMN,extMN0,extMP, extMP0,extNP,extNP0; matrix cup[1][0]; matrix kbMN,kbMP,kbNP,lift1,mA,mB,mC; ideal test1,test2,null; int pp = printlevel-voice+3; // pp=printlevel+1 (default: p=1) //----------------------------------------------------------------------------- //compute resolutions of M and N // M<--F(0)<--- ... <---F(p+q+1) // N<--G(0)<--- ... <---G(q+1) //----------------------------------------------------------------------------- list resM = nres(M,p+q+1); M1 = resM[p]; M2 = resM[p+1]; list resN = nres(N,q+1); N1 = resN[q]; N2 = resN[q+1]; P1 = resM[p+q]; P2 = resM[p+q+1]; //-------test: Ext==0?--------------------------------------------------------- test1 = simplify(ideal(M1),10); test2 = simplify(ideal(N),10); if (test1[1]==0) { dbprint(pp,"//Ext(M,N)=0");return(cup); } test1 = simplify(ideal(N1),10); test2 = simplify(ideal(P),10); if (test1[1]==0) { dbprint(pp,"//Ext(N,P)=0");return(cup); } test1 = simplify(ideal(P1),10); if (test1[1]==0) { dbprint(pp,"//Ext(M,P)=0");return(cup); } //------ compute kbases of Ext's --------------------------------------------- //------ Ext(M,N) test1 = simplify(ideal(M2),10); if (test1[1]==0) { ker = freemodule(ncols(M1)*nrows(N));} else { A = kontrahom(M2,nrows(N)); B = kohom(N,ncols(M2)); C = intersect(A,B); C = reduce(C,std(ideal(0)));C=simplify(C,10); ker = lift(A,C)+syz(A); } ima = kohom(N,ncols(M1)); A = kontrahom(M1,nrows(N)); ima = ima+A; extMN = modulo(ker,ima); extMN0= std(extMN); e1 = vdim(extMN0); dbprint(pp-1,"// vdim Ext(M,N) = "+string(e1)); if (e1 < 0) { "// Ext(M,N) not of finite dimension"; return(cup); } kbMN = kbase(extMN0); kbMN = matrix(ker)*kbMN; dbprint(pp-1,"// kbase of Ext^p(M,N)", "// - the columns present the kbase elements in Hom(F(p),G(0))", "// - F(*),G(*) are free resolutions of M and N",kbMN); //------- Ext(N,P) test1 = simplify(ideal(N2),10); if (test1[1]==0) { ker = freemodule(ncols(N1)*nrows(P)); } else { A = kontrahom(N2,nrows(P)); B = kohom(P,ncols(N2)); C = intersect(A,B); C = reduce(C,std(ideal(0)));C=simplify(C,10); ker = lift(A,C)+syz(A); } ima = kohom(P,ncols(N1)); A = kontrahom(N1,nrows(P)); ima = ima+A; extNP = modulo(ker,ima); extNP0= std(extNP); e2 = vdim(extNP0); dbprint(pp-1,"// vdim Ext(N,P) = "+string(e2)); if (e2 < 0) { "// Ext(N,P) not of finite dimension"; return(cup); } kbNP = kbase(extNP0); kbNP = matrix(ker)*kbNP; dbprint(pp-1,"// kbase of Ext(N,P):",kbNP, "// kbase of Ext^q(N,P)", "// - the columns present the kbase elements in Hom(G(q),H(0))", "// - G(*),H(*) are free resolutions of N and P",kbNP); //------ Ext(M,P) test1 = simplify(ideal(P2),10); if (test1[1]==0) { ker = freemodule(ncols(P1)*nrows(P)); } else { A = kontrahom(P2,nrows(P)); B = kohom(P,ncols(P2)); C = intersect(A,B); C = reduce(C,std(ideal(0)));C=simplify(C,10); ker = lift(A,C)+syz(A); } ima = kohom(P,ncols(P1)); A = kontrahom(P1,nrows(P)); ima = ima+A; extMP = modulo(ker,ima); extMP0= std(extMP); e3 = vdim(extMP0); dbprint(pp-1,"// vdim Ext(M,P) = "+string(e3)); if (e3 < 0) { "// Ext(M,P) not of finite dimension"; return(cup); } kbMP = kbase(extMP0); kbMP = matrix(ker)*kbMP; dbprint(pp-1,"// kbase of Ext^p+q(M,P)", "// - the columns present the kbase elements in Hom(F(p+q),H(0))", "// - F(*),H(*) are free resolutions of M and P",kbMP); //----- lift kbase of Ext(M,N) ------------------------------------------------ lift1 = kbMN; for (i=1;i<=q;i=i+1) { mA = kontrahom(resM[p+i],nrows(resN[i])); mB = kohom(resN[i],ncols(resM[p+i])); lift1 = lift(mB,mA*lift1); } dbprint(pp-1,"// lifting of kbase of Ext^p(M,N)", "// - the columns present liftings of kbase elements"+ " in Hom(F(p+q),G(q))",lift1); //------- compute: cup-products of base-elements ----------------------------- f0 = nrows(P); f1 = ncols(N1); f2 = ncols(resM[p+q]); for (i=1;i<=e1;i=i+1) { for (j=1;j<=e2;j=j+1) { mA = matrix(ideal(lift1[j]),f1,f2); mB = matrix(ideal(kbMP[i]),f0,f1); mC = mB*mA; mC = matrix(ideal(mC),f0*f2,1); cup= concat(cup,mC); } } dbprint(pp-1,"// matrix of cup-products (in Ext^p+q)",cup, "////// end level 2 //////"); //------- compute: presentation of base-elements ----------------------------- cup = lift(ker,cup); cup = lift_kbase(cup,extMP0); //------- special output ------------------------------------------------------ if (pp>2) { "// the associated matrices of the bilinear mapping 'cup' "; "// corresponding to the kbase elements of Ext^p+q(M,P) are shown,"; "// i.e. the rows of the final matrix are written as matrix of"; "// a bilinear form on Ext^p x Ext^q"; matrix BL[e1][e2]; for (k=1;k<=e3;k=k+1) { "//----component "+string(k)+":"; for (i=1;i<=e1;i=i+1) { for (j=1;j<=e2;j=j+1) { BL[i,j]=cup[k,j+e1*(i-1)]; } } print(BL); } "////// end level 3 //////"; } if (size(#)) { return(cup,kbMN,kbNP,kbMP);} else { return(cup); } } example {"EXAMPLE"; echo=2; int p = printlevel; ring rr = 32003,(x,y,z),(dp,C); ideal I = x4+y3+z2; qring o = std(I); module M = [x,y,0,z],[y2,-x3,z,0],[z,0,-y,-x3],[0,z,x,-y2]; print(cupproduct(M,M,M,1,3)); printlevel = 3; list l = (cupproduct(M,M,M,1,3,"any")); show(l[1]);show(l[2]); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc Ext_R (intvec v, module M, list #) "USAGE: Ext_R(v,M[,p]); v int resp. intvec , M module, p int COMPUTE: A presentation of Ext^k(M',R); for k=v[1],v[2],..., M'=coker(M). Let @example 0 <-- M' <-- F0 <-M-- F1 <-- F2 <-- ... @end example be a free resolution of M'. If @example 0 --> F0* -A1-> F1* -A2-> F2* -A3-> ... @end example is the dual sequence, Fi*=Hom(Fi,R), then Ext^k = ker(Ak+1)/im(Ak) is presented as in the following exact sequences: @example R^p --syz(Ak+1)-> Fk* ---Ak+1----> Fk+1* , R^q ----Ext^k---> R^p --syz(Ak+1)-> Fk*/im(Ak). @end example Hence, Ext^k=modulo(syz(Ak+1),Ak) presents Ext^k(M',R). RETURN: - module Ext, a presentation of Ext^k(M',R) if v is of type int@* - a list of Ext^k (k=v[1],v[2],...) if v is of type intvec.@* - In case of a third argument of type int return a list l: @format l[1] = module Ext^k resp. list of Ext^k l[2] = SB of Ext^k resp. list of SB of Ext^k l[3] = matrix resp. list of matrices, each representing a kbase of Ext^k (if finite dimensional) @end format DISPLAY: printlevel >=0: (affine) dimension of Ext^k for each k (default) printlevel >=1: Ak, Ak+1 and kbase of Ext^k in Fk* NOTE: In order to compute Ext^k(M,R) use the command Ext_R(k,syz(M));@* By default, the procedure uses the @code{mres} command. If called with the additional parameter @code{\"sres\"}, the @code{sres} command is used instead.@* If the attribute @code{\"isHomog\"} has been set for the input module, it is also set for the returned module (accordingly). EXAMPLE: example Ext_R; shows an example " { // In case M is known to be a SB, set attrib(M,"isSB",1); in order to // avoid unnecessary SB computations //------------ check for weight vector (graded case) ----------------------- int withWeight; intvec weightM,weightR,ww; if ( typeof(attrib(M,"isHomog"))!="string" ) { weightM=attrib(M,"isHomog"); withWeight=1; } //------------ initialisation ---------------------------------------------- module m1t,m1,m2,m2t,ret,ret0,ker; vector leadCol; matrix kb; module G; list L1,L2,L3,L,K; resolution resm2; int j,k,max,ii,t1,t2,di,leadComp,shift; intvec A1,A2,A3; int s = size(v); max = Max(v); // the maximum integer occurring in intvec v int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) // --------------- Variante mit sres for( ii=1; ii<=size(#); ii++ ) { if (typeof(#[ii])=="int") { // return a list if t2=1 t2=1; } else { if (typeof(#[ii])=="string") { // NOTE: at this writing, sres does not return weights if ( #[ii]=="sres" ) { t1=1; } // use sres instead of mres if t1=1 } } } //----------------- compute resolution of coker(M) ---------------------------- if( max<0 ) { dbprint(p,"// Ext^i=0 for i<0!"); module Result=[1]; if (withWeight==1) { attrib(Result,"isHomog",intvec(0)); } if (s==1) { if (t2==0) { return(Result); } else { return( list(Result,Result,matrix(0)) ); } } list Out, KBOut; for (j=1;j<=s;j++) { Out[j] = Result; KBOut[j] = matrix(0); } if (t2==0) { return(Out); } else { return( list(Out,Out,KBOut) ); } } if( t1==1 ) { // compute resolution via sres command if( attrib(M,"isSB")==0 ) { M=std(M); } list resl = sres(M,max+1); if (withWeight) { // **** // **** at this writing, sres does not return weights, we have to // **** go through the resolution to compute them // **** attrib(resl,"isHomog",weightM); // weightM = weights of M G=resl[1]; attrib(G,"isHomog",weightM); resl[1]=G; weightR=weightM; for (j=2; j<=size(resl); j++) { if (size(G)!=0) { ww=0; for (k=1; k<=ncols(G); k++) { if (size(G[k])==0) { ww[k]=0; } else { leadCol = leadmonom(G[k]); leadComp = nrows(leadCol); ww[k] = deg(leadCol)+weightR[leadComp]; } } G=resl[j]; attrib(G,"isHomog",ww); resl[j]=G; weightR=ww; } } } } else { list resl = mres(M,max+1); if ((withWeight) and (size(M)==0)) { // ***** At this writing: special treatment for zero module needed G=resl[1]; attrib(G,"isHomog",weightM); resl[1]=G; } } for( ii=1; ii<=s; ii++ ) { //----------------- apply Hom(_,R) at k-th place ----------------------------- k=v[ii]; dbprint(p-1,"// Computing Ext^"+string(k)+":"); if( k<0 ) // Ext^k=0 for negative k { dbprint(p-1,"// Ext^i=0 for i<0!"); ret = gen(1); ret0 = std(ret); if (withWeight==1) { attrib(ret,"isHomog",intvec(0)); attrib(ret0,"isHomog",intvec(0)); } L1[ii] = ret; L2[ii] = ret0; L3[ii] = matrix(kbase(ret0)); di=dim(ret0); dbprint(p,"// dimension of Ext^"+string(k)+": "+string(di)); if (di==0) { dbprint(p,"// vdim of Ext^"+string(k)+": "+string(vdim(ret0))); } dbprint(p,""); } else { m2t = resl[k+1]; m2 = transpose(m2t); if ((typeof(attrib(m2t,"isHomog"))!="string" ) && (withWeight)) { // ------------- compute weights for dual ----------------------------- weightR=attrib(m2t,"isHomog"); // -------------------------------------------------------------------- // *** set correct weights (at this writing, shift in resolution // *** is not considered when defining the weights for the // *** modules in the resolution): A1=attrib(M,"isHomog"); A2=attrib(resl[1],"isHomog"); shift=A1[1]-A2[1]; for (j=1; j<=size(weightR); j++) { weightR[j]=weightR[j]+shift; } attrib(m2t,"isHomog",weightR); // -------------------------------------------------------------------- ww=0; for (j=1; j<=nrows(m2); j++) { if (size(m2t[j])==0) { ww[j]=0; } else { leadCol = leadmonom(m2t[j]); leadComp = nrows(leadCol); ww[j] = deg(leadCol)+weightR[leadComp]; } } attrib(m2,"isHomog",-ww); // dualize --> negative weights // -------------------------------------------------------------------- // *** the following should be replaced by the syz command, // *** but syz forgets weights..... resm2 = nres(m2,2); ker = resm2[2]; if ((size(ker)>0) and (size(m2)>0)) { // ------------------------------------------------------------------ // *** set correct weights (at this writing, shift in resolution // *** is not considered when defining the weights for the // *** modules in the resolution): A1=attrib(resm2,"isHomog"); A2=attrib(resm2[1],"isHomog"); A3=attrib(ker,"isHomog"); shift=A1[1]-A2[1]; for (j=1; j<=size(A3); j++) { A3[j]=A3[j]+shift; } // *** set correct weights where weights are undetermined due to // *** zero columns in m2 (read weights from m2t) for (j=1; j<=ncols(m2); j++) { if (size(m2[j])==0) { A3[j]=-weightR[j]; } } attrib(ker,"isHomog",A3); // ------------------------------------------------------------------ } } else { ker = syz(m2); } if( k==0 ) { matrix MMM1[ncols(m2)][1]; m1=MMM1; } else { // k>0 m1t = resl[k]; m1 = transpose(resl[k]); if ((typeof(attrib(m1t,"isHomog"))!="string" ) && (withWeight)) { // ------------- compute weights for dual ----------------------------- weightR=attrib(resl[k],"isHomog"); // ------------------------------------------------------------------ // *** set correct weights (at this writing, shift in resolution // *** is not considered when defining the weights for the // *** modules in the resolution): A1=attrib(M,"isHomog"); A2=attrib(resl[1],"isHomog"); shift=A1[1]-A2[1]; for (j=1; j<=size(weightR); j++) { weightR[j]=weightR[j]+shift; } attrib(m1t,"isHomog",weightR); // ------------------------------------------------------------------ ww=0; for (j=1; j<=nrows(m1); j++) { if (size(m1t[j])==0) { ww[j]=0; } else { leadCol = leadmonom(m1t[j]); leadComp = nrows(leadCol); ww[j] = deg(leadCol)+weightR[leadComp]; } } attrib(m1,"isHomog",-ww); // dualize --> negative weights } } //----------------- presentation of ker(m2)/im(m1) --------------------- if ((k==0) and (size(M)==0)) { ret = M; if (withWeight) { attrib(ret,"isHomog",-weightM); } } else { ret = modulo(ker,m1); } dbprint(p-1, "// Let 0<--coker(M)<--F0<--F1<--F2<--... be a resolution of M,", "// then F"+string(k)+"*-->F"+string(k+1)+"* is given by:",m2, "// and F"+string(k-1)+"*-->F"+string(k)+"* is given by:",m1,""); ret0 = std(ret); di=dim(ret0); dbprint(p,"// dimension of Ext^"+string(k)+": "+string(di)); if (di==0) { dbprint(p,"// vdim of Ext^"+string(k)+": "+string(vdim(ret0))); } dbprint(p,""); if( t2 ) { if( vdim(ret0)>=0 ) { kb = kbase(ret0); if ( size(ker)!=0 ) { kb = matrix(ker)*kb; } dbprint(p-1, "// columns of matrix are kbase of Ext^"+string(k)+" in F" +string(k)+"*:",kb,""); L3[ii] = kb; } L2[ii] = ret0; } L1[ii] = ret; } } if( t2 ) { if( s>1 ) { L = L1,L2,L3; return(L); } else { L = ret,ret0,kb; return(L); } } else { if( s>1 ) { return(L1); } else { return(ret); } } } example {"EXAMPLE:"; echo=2; int p = printlevel; printlevel = 1; ring r = 0,(x,y,z),dp; ideal i = x2y,y2z,z3x; module E = Ext_R(1,i); //computes Ext^1(r/i,r) is_zero(E); qring R = std(x2+yz); intvec v = 0,2; printlevel = 2; //shows what is going on ideal i = x,y,z; //computes Ext^i(r/(x,y,z),r/(x2+yz)), i=0,2 list L = Ext_R(v,i,1); //over the qring R=r/(x2+yz), std and kbase printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc Ext (intvec v, module M, module N, list #) "USAGE: Ext(v,M,N[,any]); v int resp. intvec, M,N modules COMPUTE: A presentation of Ext^k(M',N'); for k=v[1],v[2],... where M'=coker(M) and N'=coker(N). Let @example 0 <-- M' <-- F0 <-M-- F1 <-- F2 <--... , 0 <-- N' <-- G0 <--N- G1 @end example be a free resolution of M', resp. a presentation of N'. Consider the commutative diagram @example 0 0 0 |^ |^ |^ --> Hom(Fk-1,N') -Ak-> Hom(Fk,N') -Ak+1-> Hom(Fk+1,N') |^ |^ |^ --> Hom(Fk-1,G0) -Ak-> Hom(Fk,G0) -Ak+1-> Hom(Fk+1,G0) |^ |^ |C |B Hom(Fk,G1) ------> Hom(Fk+1,G1) (Ak,Ak+1 induced by M and B,C induced by N). @end example Let K=modulo(Ak+1,B), J=module(Ak)+module(C) and Ext=modulo(K,J), then we have exact sequences @example R^p --K-> Hom(Fk,G0) --Ak+1-> Hom(Fk+1,G0)/im(B), R^q -Ext-> R^p --K-> Hom(Fk,G0)/(im(Ak)+im(C)). @end example Hence, Ext presents Ext^k(M',N'). RETURN: - module Ext, a presentation of Ext^k(M',N') if v is of type int@* - a list of Ext^k (k=v[1],v[2],...) if v is of type intvec.@* - In case of a third argument of any type return a list l: @format l[1] = module Ext/list of Ext^k l[2] = SB of Ext/list of SB of Ext^k l[3] = matrix/list of matrices, each representing a kbase of Ext^k (if finite dimensional) @end format DISPLAY: printlevel >=0: dimension, vdim of Ext^k for each k (default). @* printlevel >=1: matrices Ak, Ak+1 and kbase of Ext^k in Hom(Fk,G0) (if finite dimensional) NOTE: In order to compute Ext^k(M,N) use the command Ext(k,syz(M),syz(N)); or: list P=mres(M,2); list Q=mres(N,2); Ext(k,P[2],Q[2]); EXAMPLE: example Ext; shows an example " { //---------- initialisation --------------------------------------------------- int k,max,ii,l,row,col,di; module A,B,C,D,M1,M2,N1,ker,imag,extMN,extMN0; matrix kb; list L1,L2,L3,L,resM,K; ideal test1; intmat Be; int s = size(v); max = Max(v); // the maximum integer occurring in intvec v int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //---------- test: coker(N)=basering, coker(N)=0 ? ---------------------------- if( max<0 ) { dbprint(p,"// Ext^i=0 for i<0!"); return([1]); } N1 = std(N); if( size(N1)==0 ) //coker(N)=basering, in this case proc Ext_R is faster { printlevel=printlevel+1; if( size(#)==0 ) { def E = Ext_R(v,M); printlevel=printlevel-1; return(E); } else { def E = Ext_R(v,M,#[1]); printlevel=printlevel-1; return(E); } } if( dim(N1)==-1 ) //coker(N)=0, all Ext-groups are 0 { dbprint(p-1,"2nd module presents 0, hence Ext^k=0, for all k"); for( ii=1; ii<=s; ii++ ) { k=v[ii]; extMN = gen(1); extMN0 = std(extMN); L1[ii] = extMN; L2[ii] = extMN0; L3[ii] = matrix(kbase(extMN0)); di=dim(extMN0); dbprint(p,"// dimension of Ext^"+string(k)+": "+string(di)); if (di==0) { dbprint(p,"// vdim of Ext^"+string(k)+": "+string(vdim(extMN0))); } dbprint(p,""); } } else { if( size(N1) < size(N) ) { N=N1;} row = nrows(N); //---------- resolution of M ------------------------------------------------- resM = mres(M,max+1); for( ii=1; ii<=s; ii++ ) { k=v[ii]; if( k<0 ) // Ext^k is 0 for negative k { dbprint(p-1,"// Ext^k=0 for k<0!"); extMN = gen(1); extMN0 = std(extMN); L1[ii] = extMN; L2[ii] = extMN0; L3[ii] = matrix(kbase(extMN0)); di=dim(extMN0); dbprint(p,"// dimension of Ext^"+string(k)+": "+string(di)); if (di==0) { dbprint(p,"// vdim of Ext^"+string(k)+": " +string(vdim(extMN0))); } dbprint(p,""); } else { M2 = resM[k+1]; if( k==0 ) { M1=0; } else { M1 = resM[k]; } col = nrows(M2); D = kohom(N,col); //---------- computing homology ---------------------------------------------- imag = kontrahom(M1,row); A = kontrahom(M2,row); B = kohom(N,ncols(M2)); ker = modulo(A,B); imag = imag,D; extMN = modulo(ker,imag); dbprint(p-1,"// Computing Ext^"+string(k)+ " (help Ext; gives an explanation):", "// Let 0<--coker(M)<--F0<--F1<--F2<--... be a resolution of coker(M),", "// and 0<--coker(N)<--G0<--G1 a presentation of coker(N),", "// then Hom(F"+string(k)+",G0)-->Hom(F"+string(k+1)+ ",G0) is given by:",A, "// and Hom(F"+string(k-1)+",G0) + Hom(F"+string(k)+",G1)-->Hom(F" +string(k)+",G0) is given by:",imag,""); extMN0 = std(extMN); di=dim(extMN0); dbprint(p,"// dimension of Ext^"+string(k)+": "+string(di)); if (di==0) { dbprint(p,"// vdim of Ext^"+string(k)+": " +string(vdim(extMN0))); } dbprint(p,""); //---------- more information ------------------------------------------------- if( size(#)>0 ) { if( vdim(extMN0) >= 0 ) { kb = kbase(extMN0); if ( size(ker)!=0) { kb = matrix(ker)*kb; } dbprint(p-1,"// columns of matrix are kbase of Ext^"+ string(k)+" in Hom(F"+string(k)+",G0)",kb,""); if( p>0 ) { for (l=1;l<=ncols(kb);l=l+1) { "// element",l,"of kbase of Ext^"+string(k)+" in Hom(F"+string(k)+",G0)"; "// as matrix: F"+string(k)+"-->G0"; print(matrix(ideal(kb[l]),row,col)); } ""; } L3[ii] = matrix(kb); } L2[ii] = extMN0; } L1[ii] = extMN; } } } if( size(#) ) { if( s>1 ) { L = L1,L2,L3; return(L); } else { L = extMN,extMN0,matrix(kb); return(L); } } else { if( s>1 ) { return(L1); } else { return(extMN); } } } example {"EXAMPLE:"; echo=2; int p = printlevel; printlevel = 1; ring r = 0,(x,y),dp; ideal i = x2-y3; ideal j = x2-y5; list E = Ext(0..2,i,j); // Ext^k(r/i,r/j) for k=0,1,2 over r qring R = std(i); ideal j = fetch(r,j); module M = [-x,y],[-y2,x]; printlevel = 2; module E1 = Ext(1,M,j); // Ext^1(R^2/M,R/j) over R=r/i list l = Ext(4,M,M,1); // Ext^4(R^2/M,R^2/M) over R=r/i printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc Hom (module M, module N, list #) "USAGE: Hom(M,N,[any]); M,N=modules COMPUTE: A presentation of Hom(M',N'), M'=coker(M), N'=coker(N) as follows: let @example F1 --M-> F0 -->M' --> 0, G1 --N-> G0 --> N' --> 0 @end example be presentations of M' and N'. Consider @example 0 0 |^ |^ 0 --> Hom(M',N') ----> Hom(F0,N') ----> Hom(F1,N') |^ |^ (A: induced by M) Hom(F0,G0) --A-> Hom(F1,G0) |^ |^ (B,C:induced by N) |C |B Hom(F0,G1) ----> Hom(F1,G1) @end example Let D=modulo(A,B) and Hom=modulo(D,C), then we have exact sequences @example R^p --D-> Hom(F0,G0) --A-> Hom(F1,G0)/im(B), R^q -Hom-> R^p --D-> Hom(F0,G0)/im(C) --A-> Hom(F1,G0)/im(B). @end example Hence Hom presents Hom(M',N') RETURN: module Hom, a presentation of Hom(M',N'), resp., in case of 3 arguments, a list l (of size <=3): @format - l[1] = Hom - l[2] = SB of Hom - l[3] = kbase of coker(Hom) (if finite dimensional, not 0), represented by elements in Hom(F0,G0) via mapping D @end format DISPLAY: printlevel >=0: (affine) dimension of Hom (default) @* printlevel >=1: D and C and kbase of coker(Hom) in Hom(F0,G0) @* printlevel >=2: elements of kbase of coker(Hom) as matrix :F0-->G0 NOTE: DISPLAY is as described only for a direct call of 'Hom'. Calling 'Hom' from another proc has the same effect as decreasing printlevel by 1. EXAMPLE: example Hom; shows examples " { //---------- initialisation --------------------------------------------------- int l,p,di; matrix kb; module A,B,C,D,homMN,homMN0; list L; //---------- computation of Hom ----------------------------------------------- B = kohom(N,ncols(M)); A = kontrahom(M,nrows(N)); C = kohom(N,nrows(M)); D = modulo(A,B); homMN = modulo(D,C); homMN0= std(homMN); p = printlevel-voice+3; // p=printlevel+1 (default: p=1) di= dim(homMN0); dbprint(p,"// dimension of Hom: "+string(di)); if (di==0) { dbprint(p,"// vdim of Hom: "+string(vdim(homMN0))); } dbprint(p,""); dbprint(p-1, "// given F1 --M-> F0 -->M'--> 0 and G1 --N-> G0 -->N'--> 0,", "// show D = ker( Hom(F0,G0) --> Hom(F1,G0)/im(Hom(F1,G1)->Hom(F1,G0)) )",D, "// show C = im ( Hom(F0,G1) --> Hom(F0,G0) )",C,""); //---------- extra output if size(#)>0 ---------------------------------------- if( size(#)>0 ) { if( vdim(homMN0)>0 ) { kb = kbase(homMN0); kb = matrix(D)*kb; if( p>2 ) { for (l=1;l<=ncols(kb);l=l+1) { "// element",l,"of kbase of Hom in Hom(F0,G0) as matrix: F0-->G0:"; print(matrix(ideal(kb[l]),nrows(N),nrows(M))); } } else { dbprint(p-1,"// columns of matrix are kbase of Hom in Hom(F0,G0)", kb); } L=homMN,homMN0,kb; return(L); } L=homMN,homMN0; return(L); } return(homMN); } example {"EXAMPLE:"; echo = 2; int p = printlevel; printlevel= 1; //in 'example proc' printlevel has to be increased by 1 ring r = 0,(x,y),dp; ideal i = x2-y3,xy; qring q = std(i); ideal i = fetch(r,i); module M = [-x,y],[-y2,x],[x3]; module H = Hom(M,i); print(H); printlevel= 2; list L = Hom(M,i,1);""; printlevel=1; ring s = 3,(x,y,z),(c,dp); ideal i = jacob(ideal(x2+y5+z4)); qring rq=std(i); matrix M[2][2]=xy,x3,5y,4z,x2; matrix N[3][2]=x2,x,y3,3xz,x2z,z; print(M); print(N); list l=Hom(M,N,1); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc homology (matrix A,matrix B,module M,module N,list #) "USAGE: homology(A,B,M,N); COMPUTE: Let M and N be submodules of R^m and R^n presenting M'=R^m/M, N'=R^n/N (R=basering) and let A,B matrices inducing maps @example R^k --A--> R^m --B--> R^n. @end example Compute a presentation of the module @example ker(B)/im(A) := ker(M'/im(A) --B--> N'/im(BM)+im(BA)). @end example If B induces a map M'-->N' (i.e BM=0) and if im(A) is contained in ker(B) (that is, BA=0) then ker(B)/im(A) is the homology of the complex @example R^k--A-->M'--B-->N'. @end example RETURN: module H, a presentation of ker(B)/im(A). NOTE: homology returns a free module of rank m if ker(B)=im(A). EXAMPLE: example homology; shows examples " { module ker,ima; ker = modulo(B,N); ima = A,M; return(modulo(ker,ima)); } example {"EXAMPLE"; echo=2; ring r; ideal id=maxideal(4); qring qr=std(id); module N=maxideal(3)*freemodule(2); module M=maxideal(2)*freemodule(2); module B=[2x,0],[x,y],[z2,y]; module A=M; module H=homology(A,B,M,N); H=std(H); // dimension of homology: dim(H); // vector space dimension: vdim(H); ring s=0,x,ds; qring qs=std(x4); module A=[x]; module B=A; module M=[x3]; module N=M; homology(A,B,M,N); } ////////////////////////////////////////////////////////////////////////////// proc hom_kernel (matrix A,module M,module N) "USAGE: hom_kernel(A,M,N); COMPUTE: Let M and N be submodules of R^m and R^n, presenting M'=R^m/M, N'=R^n/N (R=basering), and let A:R^m-->R^n be a matrix inducing a map A':M'-->N'. Then ker(A,M,N); computes a presentation K of ker(A') as in the commutative diagram: @example ker(A') ---> M' --A'--> N' |^ |^ |^ | | | R^r ---> R^m --A--> R^n |^ |^ |^ |K |M |N | | | R^s ---> R^p -----> R^q @end example RETURN: module K, a presentation of ker(A':coker(M)->coker(N)). EXAMPLE: example hom_kernel; shows examples. " { module M1 = modulo(A,N); return(modulo(M1,M)); } example {"EXAMPLE"; echo=2; ring r; module N=[2x,x],[0,y]; module M=maxideal(1)*freemodule(2); matrix A[2][3]=2x,0,x,y,z2,y; module K=hom_kernel(A,M,N); // dimension of kernel: dim(std(K)); // vector space dimension of kernel: vdim(std(K)); print(K); } /////////////////////////////////////////////////////////////////////////////// proc kohom (matrix M, int j) "USAGE: kohom(A,k); A=matrix, k=integer RETURN: matrix Hom(R^k,A), i.e. let A be a matrix defining a map F1-->F2 of free R-modules, then the matrix of Hom(R^k,F1)-->Hom(R^k,F2) is computed (R=basering). EXAMPLE: example kohom; shows an example. " { if (j==1) { return(M);} if (j>1) { return(tensor(M,diag(1,j))); } else { return(0);} } example {"EXAMPLE:"; echo=2; ring r; matrix n[2][3]=x,y,5,z,77,33; print(kohom(n,3)); } /////////////////////////////////////////////////////////////////////////////// proc kontrahom (matrix M, int j) "USAGE: kontrahom(A,k); A=matrix, k=integer RETURN: matrix Hom(A,R^k), i.e. let A be a matrix defining a map F1-->F2 of free R-modules, then the matrix of Hom(F2,R^k)-->Hom(F1,R^k) is computed (R=basering). EXAMPLE: example kontrahom; shows an example. " { if (j==1) { return(transpose(M));} if (j>1) { return(transpose(tensor(diag(1,j),M)));} else { return(0);} } example {"EXAMPLE:"; echo=2; ring r; matrix n[2][3]=x,y,5,z,77,33; print(kontrahom(n,3)); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc tensorMod(module Phi, module Psi) "USAGE: tensorMod(M,N); M,N modules COMPUTE: presentation matrix A of the tensor product T of the modules M'=coker(M), N'=coker(N): if matrix(M) defines a map M: R^r-->R^s and matrix(N) defines a map N: R^p-->R^q, then A defines a presentation @example R^(sp+rq) --A-> R^(sq) --> T --> 0 . @end example RETURN: matrix A satisfying coker(A) = tensorprod(coker(M),coker(N)) . EXAMPLE: example tensorMod; shows an example. " { int s=nrows(Phi); int q=nrows(Psi); matrix A=tensor(unitmat(s),Psi); matrix B=tensor(Phi,unitmat(q)); matrix R=concat(A,B); return(R); } example {"EXAMPLE:"; echo=2; ring A=0,(x,y,z),dp; matrix M[3][3]=1,2,3,4,5,6,7,8,9; matrix N[2][2]=x,y,0,z; print(M); print(N); print(tensorMod(M,N)); } /////////////////////////////////////////////////////////////////////////////// proc Tor(intvec v, module M, module N, list #) "USAGE: Tor(v,M,N[,any]); v int resp. intvec, M,N modules COMPUTE: a presentation of Tor_k(M',N'), for k=v[1],v[2],... , where M'=coker(M) and N'=coker(N): let @example 0 <-- M' <-- G0 <-M-- G1 0 <-- N' <-- F0 <--N- F1 <-- F2 <--... @end example be a presentation of M', resp. a free resolution of N', and consider the commutative diagram @example 0 0 0 |^ |^ |^ Tensor(M',Fk+1) -Ak+1-> Tensor(M',Fk) -Ak-> Tensor(M',Fk-1) |^ |^ |^ Tensor(G0,Fk+1) -Ak+1-> Tensor(G0,Fk) -Ak-> Tensor(G0,Fk-1) |^ |^ |C |B Tensor(G1,Fk) ----> Tensor(G1,Fk-1) (Ak,Ak+1 induced by N and B,C induced by M). @end example Let K=modulo(Ak,B), J=module(C)+module(Ak+1) and Tor=modulo(K,J), then we have exact sequences @example R^p --K-> Tensor(G0,Fk) --Ak-> Tensor(G0,Fk-1)/im(B), R^q -Tor-> R^p --K-> Tensor(G0,Fk)/(im(C)+im(Ak+1)). @end example Hence, Tor presents Tor_k(M',N'). RETURN: - if v is of type int: module Tor, a presentation of Tor_k(M',N');@* - if v is of type intvec: a list of Tor_k(M',N') (k=v[1],v[2],...);@* - in case of a third argument of any type: list l with @format l[1] = module Tor/list of Tor_k(M',N'), l[2] = SB of Tor/list of SB of Tor_k(M',N'), l[3] = matrix/list of matrices, each representing a kbase of Tor_k(M',N') (if finite dimensional), or 0. @end format DISPLAY: printlevel >=0: (affine) dimension of Tor_k for each k (default). @* printlevel >=1: matrices Ak, Ak+1 and kbase of Tor_k in Tensor(G0,Fk) (if finite dimensional). NOTE: In order to compute Tor_k(M,N) use the command Tor(k,syz(M),syz(N)); or: list P=mres(M,2); list Q=mres(N,2); Tor(k,P[2],Q[2]); EXAMPLE: example Tor; shows an example { //---------- initialisation --------------------------------------------------- int k,max,ii,l,row,col,di; module A,B,C,D,N1,N2,M1,ker,imag,Im,Im1,Im2,f,torMN,torMN0; matrix kb; list L1,L2,L3,L,resN,K; ideal test1; intmat Be; int s = size(v); max = Max(v); // maximum integer occurring in intvec v int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //---------- test: coker(M)=basering, coker(M)=0 ? ---------------------------- if( max<0 ) { dbprint(p,"// Tor_i=0 for i<0!"); return([1]); } M1 = std(M); if( size(M1)==0 or size(N)==0 ) // coker(M)=basering ==> Tor_i=0 for i>0 { dbprint(p-1,"// one of the modules M',N' is free, hence Tor_i=0 for i<>0"); for( ii=1; ii<=s; ii++ ) { k=v[ii]; if (k==0) { torMN=module(tensorMod(M1,N)); } else { torMN = gen(1); } torMN0 = std(torMN); L1[ii] = torMN; L2[ii] = torMN0; L3[ii] = matrix(kbase(torMN0)); di=dim(torMN0); dbprint(p,"// dimension of Tor_"+string(k)+": "+string(di)); if (di==0) { dbprint(p,"// vdim of Tor_"+string(k)+": " +string(vdim(torMN0))); } dbprint(p,""); } if( size(#) ) { if( s>1 ) { L = L1,L2,L3; return(L); } else { L = torMN,torMN0,L3[1]; return(L); } } else { if( s>1 ) { return(L1); } else { return(torMN); } } } if( dim(M1)==-1 ) // coker(M)=0, all Tor's are 0 { dbprint(p-1,"2nd module presents 0, hence Tor_k=0, for all k"); for( ii=1; ii<=s; ii++ ) { k=v[ii]; torMN = gen(1); torMN0 = std(torMN); L1[ii] = torMN; L2[ii] = torMN0; L3[ii] = matrix(kbase(torMN0)); di=dim(torMN0); dbprint(p,"// dimension of Tor_"+string(k)+": "+string(di)); if (di==0) { dbprint(p,"// vdim of Tor_"+string(k)+": " +string(vdim(torMN0))); } dbprint(p,""); } } else { if( size(M1) < size(M) ) { M=M1;} row = nrows(M); //---------- resolution of N ------------------------------------------------- resN = mres(N,max+1); for( ii=1; ii<=s; ii++ ) { k=v[ii]; if( k<0 ) // Tor_k is 0 for negative k { dbprint(p-1,"// Tor_k=0 for k<0!"); torMN = gen(1); torMN0 = std(torMN); L1[ii] = torMN; L2[ii] = torMN0; L3[ii] = matrix(kbase(torMN0)); di=dim(torMN0); dbprint(p,"// dimension of Tor_"+string(k)+": "+string(di)); if (di==0) { dbprint(p,"// vdim of Tor_"+string(k)+": " +string(vdim(torMN0))); } dbprint(p,""); } else { N2 = resN[k+1]; if( k==0 ) { torMN=module(tensorMod(M,N)); } else { N1 = resN[k]; col = ncols(N1); //---------- computing homology ---------------------------------------------- imag = tensor(unitmat(nrows(N1)),M); f = tensor(matrix(N1),unitmat(row)); Im1 = tensor(unitmat(col),M); Im2 = tensor(matrix(N2),unitmat(row)); ker = modulo(f,imag); Im = Im2,Im1; torMN = modulo(ker,Im); dbprint(p-1,"// Computing Tor_"+string(k)+ " (help Tor; gives an explanation):", "// Let 0 <- coker(M) <- G0 <-M- G1 be the present. of coker(M),", "// and 0 <- coker(N) <- F0 <-N- F1 <- F2 <- ... a resolution of", "// coker(N), then Tensor(G0,F"+string(k)+")-->Tensor(G0,F"+ string(k-1)+") is given by:",f, "// and Tensor(G0,F"+string(k+1)+") + Tensor(G1,F"+string(k)+ ")-->Tensor(G0,F"+string(k)+") is given by:",Im,""); } torMN0 = std(torMN); di=dim(torMN0); dbprint(p,"// dimension of Tor_"+string(k)+": "+string(di)); if (di==0) { dbprint(p,"// vdim of Tor_"+string(k)+": " +string(vdim(torMN0))); } dbprint(p,""); //---------- more information ------------------------------------------------- if( size(#)>0 ) { if( vdim(torMN0) >= 0 ) { kb = kbase(torMN0); if ( size(ker)!=0) { kb = matrix(ker)*kb; } dbprint(p-1,"// columns of matrix are kbase of Tor_"+ string(k)+" in Tensor(G0,F"+string(k)+")",kb,""); L3[ii] = matrix(kb); } L2[ii] = torMN0; } L1[ii] = torMN; } } } if( size(#) ) { if( s>1 ) { L = L1,L2,L3; return(L); } else { L = torMN,torMN0,matrix(kb); return(L); } } else { if( s>1 ) { return(L1); } else { return(torMN); } } } example {"EXAMPLE:"; echo=2; int p = printlevel; printlevel = 1; ring r = 0,(x,y),dp; ideal i = x2,y; ideal j = x; list E = Tor(0..2,i,j); // Tor_k(r/i,r/j) for k=0,1,2 over r qring R = std(i); ideal j = fetch(r,j); module M = [x,0],[0,x]; printlevel = 2; module E1 = Tor(1,M,j); // Tor_1(R^2/M,R/j) over R=r/i list l = Tor(3,M,M,1); // Tor_3(R^2/M,R^2/M) over R=r/i printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc fitting(module M, int n) "USAGE: fitting (M,n); M module, n int RETURN: ideal, (standard basis of) n-th Fitting ideal of M'=coker(M). EXAMPLE: example fitting; shows an example " { n=nrows(M)-n; if(n<=0){return(ideal(1));} if((n>nrows(M))||(n>ncols(M))){return(ideal(0));} return(std(minor(M,n))); } example {"EXAMPLE:"; echo=2; ring R=0,x(0..4),dp; matrix M[2][4]=x(0),x(1),x(2),x(3),x(1),x(2),x(3),x(4); print(M); fitting(M,-1); fitting(M,0); fitting(M,1); fitting(M,2); } /////////////////////////////////////////////////////////////////////////////// proc isLocallyFree(matrix S, int r) "USAGE: isLocallyFree(M,r); M module, r int RETURN: 1 if M'=coker(M) is locally free of constant rank r;@* 0 if this is not the case. EXAMPLE: example isLocallyFree; shows an example. " { ideal F=fitting(S,r); ideal G=fitting(S,r-1); if((deg(F[1])==0)&&(size(G)==0)){return(1);} return(0); } example {"EXAMPLE:"; echo=2; ring R=0,(x,y,z),dp; matrix M[2][3]; // the presentation matrix M=x-1,y-1,z,y-1,x-2,x; ideal I=fitting(M,0); // 0-th Fitting ideal of coker(M) qring Q=I; matrix M=fetch(R,M); isLocallyFree(M,1); // as R/I-module, coker(M) is locally free of rk 1 isLocallyFree(M,0); } /////////////////////////////////////////////////////////////////////////////// proc flatteningStrat (module M) "USAGE: flatteningStrat(M); M module RETURN: list of ideals. The list entries L[1],...,L[r] describe the flattening stratification of M'=coker(M): setting L[0]=0, L[r+1]=1, the flattening stratification is given by the open sets Spec(A/V(L[i-1])) \ V(L[i]), i=1,...,r+1 (A = basering). NOTE: for more information see the book 'A Singular Introduction to Commutative Algebra' (by Greuel/Pfister, Springer 2002). EXAMPLE: example flatteningStrat; shows an example " { list l; int v,w; ideal F; while(1) { F=interred(fitting(M,w)); if(F[1]==1){return(l);} if(size(F)!=0){v++;l[v]=F;} w++; } return(l); } example {"EXAMPLE:"; echo=2; ring A = 0,x(0..4),dp; // presentation matrix: matrix M[2][4] = x(0),x(1),x(2),x(3),x(1),x(2),x(3),x(4); list L = flatteningStrat(M); L; } /////////////////////////////////////////////////////////////////////////////// proc isFlat(module M) "USAGE: isFlat(M); M module RETURN: 1 if M'=coker(M) is flat;@* 0 if this is not the case. EXAMPLE: example isFlat; shows an example. " { if (size(ideal(M))==0) {return(1);} int w; ideal F=fitting(M,0); while(size(F)==0) { w++; F=fitting(M,w); } if (deg(std(F)[1])==0) {return(1);} return(0); } example {"EXAMPLE:"; echo=2; ring A = 0,(x,y),dp; matrix M[3][3] = x-1,y,x,x,x+1,y,x2,xy+x+1,x2+y; print(M); isFlat(M); // coker(M) is not flat over A=Q[x,y] qring B = std(x2+x-y); // the ring B=Q[x,y]/ matrix M = fetch(A,M); isFlat(M); // coker(M) is flat over B setring A; qring C = std(x2+x+y); // the ring C=Q[x,y]/ matrix M = fetch(A,M); isFlat(M); // coker(M) is not flat over C } /////////////////////////////////////////////////////////////////////////////// proc flatLocus(module M) "USAGE: flatLocus(M); M module RETURN: ideal I, s.th. complement of V(I) is flat locus of coker(M). NOTE: computation is based on Fitting ideals;@* output is not radical (in general) EXAMPLE: example flatLocus; shows an example " { if (size(ideal(M))==0) {return(ideal(1));} int v,w; ideal F=fitting(M,0); while(size(F)==0) { w++; F=fitting(M,w); } if(size(ideal(basering))>0) { for(v=w+1;v<=nrows(M);v++) { F=F+intersect(fitting(M,v),quotient(ideal(0),fitting(M,v-1))); } } return(interred(F)); } example {"EXAMPLE:"; echo=2; ring R=0,(x,y,z),dp; matrix M[2][3]=x,y,z,0,x3,z3; ideal I=flatLocus(M); // coker(M) is flat outside V(x,yz) I; // computed ideal not radical ideal J=radical(I); J; qring r=std(J); matrix M=fetch(r,M); flatLocus(M); // coker(M) is flat over Spec(Q[x,y,z]/) isFlat(M); // flatness test } /////////////////////////////////////////////////////////////////////////////// proc isReg(ideal I, module N) "USAGE: isReg(I,M); I ideal, M module RETURN: 1 if given (ordered) list of generators for I is coker(M)-sequence;@* 0 if this is not the case. EXAMPLE: example isReg; shows an example. " { int n=nrows(N); int i; while(i=n-v[1]+1) { b=b+binom_int(j,p-1); j--; } intvec w=v-v[1]; w=w[2..size(w)]; b=b+basisNumber(n-v[1],w); return(b); } static proc basisElement(int n,int p,int N) { if(p==1){return(N);} int s,R; while(R20) { ERROR("// too many generators in input ideal"); } if (p>n) { module hom=0; return(hom); } int a = binom_int(n,p-1); // n over p-1 independent of char(basering) int b = binom_int(n,p); matrix N = matrix(M); module ker= freemodule(nrows(N)); if(p!=0) { module im= tensor(unitmat(a),N); module f = tensor(KoszulMap(x,p),unitmat(nrows(N))); ker = modulo(f,im); } module im1 = tensor(unitmat(b),N); module im2 = tensor(KoszulMap(x,p+1),unitmat(nrows(N))); module hom = modulo(ker,im1+im2); hom = prune(hom); return(hom); } example {"EXAMPLE:"; echo=2; ring R=0,x(1..3),dp; ideal x=maxideal(1); module M=0; KoszulHomology(x,M,0); // H_0(x,R), x=(x_1,x_2,x_3) KoszulHomology(x,M,1); // H_1(x,R), x=(x_1,x_2,x_3) qring S=std(x(1)*x(2)); module M=0; ideal x=maxideal(1); KoszulHomology(x,M,1); KoszulHomology(x,M,2); } /////////////////////////////////////////////////////////////////////////////// proc depth(module M,ideal #) "USAGE: depth(M,[I]); M module, I ideal RETURN: int, - if called with 1 argument: the depth of M'=coker(M) w.r.t. the maxideal in the basering (which is then assumed to be local)@* - if called with 2 arguments: the depth of M'=coker(M) w.r.t. the ideal I. NOTE: procedure makes use of KoszulHomology. EXAMPLE: example depth; shows an example. " { ideal m=maxideal(1); int n=size(m); int i; if (size(#)==0) { // depth(M') over local basering while(i,Q[x,y,z]) ring r=0,(x,y,z),ds; // local ring matrix M[2][2]=x,xy,1+yz,0; print(M); depth(M); // depth(maxideal,coker(M)) ideal I=x; depth(M,I); // depth(,coker(M)) I=x+z; depth(M,I); // depth(,coker(M)) } /////////////////////////////////////////////////////////////////////////////// proc isCM(module M) "USAGE: isCM(M); M module RETURN: 1 if M'=coker(M) is Cohen-Macaulay;@* 0 if this is not the case. ASSUME: basering is local. EXAMPLE: example isCM; shows an example " { // test if basering is local: ideal m=maxideal(1); int i; poly f=1; for (i=1; i<=size(m); i++) { f=f+m[i]; } if (ord(f)>0) { print("// basering must be local -- result has no meaning"); return(0); } return(depth(M)==dim(std(Ann(M)))); } example {"EXAMPLE:"; echo=2; ring R=0,(x,y,z),ds; // local ring R = Q[x,y,z]_ module M=xz,yz,z2; isCM(M); // test if R/ is Cohen-Macaulay M=x2+y2,z7; // test if R/ is Cohen-Macaulay isCM(M); } proc canonMap(list #) "USAGE: canonMap(id); id= ideal/module, RETURN: a list L, the kernel in two different representations and @* the cokernel of the canonical map @* M ---> Ext^c_R(Ext^c_R(M,R),R) given by presentations @* Here M is the R-module (R=basering) given by the presentation @* defined by id, i.e. M=R/id resp. M=R^n/id @* c is the codimension of M @* L[1] is the preimage of the kernel in R resp. R^n @* L[2] is a presentation of the kernel @* L[3] is a presentation of the cokernel EXAMPLE: example canonMap; shows an example " { module M=#[1]; int c=nvars(basering)-dim(std(M)); if(c==0) { module K=syz(transpose(M)); module Ke=syz(transpose(K)); module Co=modulo(syz(transpose(syz(K))),transpose(K)); } else { int i; resolution F=mres(M,c+1); module K=syz(transpose(F[c+1])); K=simplify(reduce(K,std(transpose(F[c]))),2); module A=modulo(K,transpose(F[c])); resolution G=nres(A,c+1); for(i=1;i<=c;i++) { K=lift(transpose(F[c-i+1]),K*G[i]); } module Ke=modulo(transpose(K),transpose(G[c])); module Co=modulo(syz(transpose(G[c+1])),transpose(K)+transpose(G[c])); } return(list(Ke,prune(modulo(Ke,M)),prune(Co))); } example { "EXAMPLE:"; echo = 2; ring s=0,(x,y),dp; ideal i = x,y; canonMap(i); ring R = 0,(x,y,z,w),dp; ideal I1 = x,y; ideal I2 = z,w; ideal I = intersect(I1,I2); canonMap(I); module M = syz(I); canonMap(M); ring S = 0,(x,y,z,t),Wp(3,4,5,1); ideal I = x-t3,y-t4,z-t5; ideal J = eliminate(I,t); ring T = 0,(x,y,z),Wp(3,4,5); ideal p = imap(S,J); ideal p2 = p^2; canonMap(p2); } // taken from qhmoduli.lib static proc Max(def data) "USAGE: Max(data); intvec/list of integers PURPOSE: find the maximal integer contained in 'data' RETURN: list ASSUME: 'data' contians only integers and is not empty " { int i; int max = data[1]; for(i = size(data); i>1;i--) { if(data[i] > max) { max = data[i]; } } return(max); } example {"EXAMPLE:"; echo = 2; Max(list(1,2,3)); } singular-4.0.3+ds/Singular/LIB/hyperel.lib000066400000000000000000000606231266270727000203160ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version hyperel.lib 4.0.0.0 Jun_2013 "; // $Id: c5138c4fc23f4b2d2fa03a8f7dfdd92b661521c1 $ category="Teaching"; info=" LIBRARY: hyperel.lib AUTHOR: Markus Hochstetter, markushochstetter@gmx.de NOTE: The library provides procedures for computing with divisors in the jacobian of hyperelliptic curves. In addition procedures are available for computing the rational representation of divisors and vice versa. The library is intended to be used for teaching and demonstrating purposes but not for efficient computations. PROCEDURES: ishyper(h,f) test, if y^2+h(x)y=f(x) is hyperelliptic isoncurve(P,h,f) test, if point P is on C: y^2+h(x)y=f(x) chinrestp(b,moduli) compute polynom x, s.t. x=b[i] mod moduli[i] norm(a,b,h,f) norm of a(x)-b(x)y in IF[C] multi(a,b,c,d,h,f) (a(x)-b(x)y)*(c(x)-d(x)y) in IF[C] ratrep (P,h,f) returns polynomials a,b, s.t. div(a,b)=P divisor(a,b,h,f,[]) computes divisor of a(x)-b(x)y gcddivisor(p,q) gcd of the divisors p and q semidiv(D,h,f) semireduced divisor of the pair of polys D[1], D[2] cantoradd(D,Q,h,f) adding divisors of the hyperell. curve y^2+h(x)y=f(x) cantorred(D,h,f) returns reduced divisor which is equivalent to D double(D,h,f) computes 2*D on y^2+h(x)y=f(x) cantormult(m,D,h,f) computes m*D on y^2+h(x)y=f(x) [parameters in square brackets are optional] "; /////////////////////////////////////////////////////////////////////////////// //=============== Test, if a given curve is hyperelliptic ===================== proc ishyper(poly h, poly f) "USAGE: ishyper(h,f); h,f=poly RETURN: 1 if y^2+h(x)y=f(x) is hyperelliptic, 0 otherwise NOTE: Tests, if y^2+h(x)y=f(x) is a hyperelliptic curve. Curve is defined over basering. Additionally shows error-messages. EXAMPLE: example ishyper; shows an example " { // constructing a copy of the basering (only variable x), // with variables x,y. def R=basering; list l= ringlist(R); list ll=l[2]; ll="x","y"; l[2]=ll; intvec v= l[3][1][2]; v=v,1; l[3][1][2]=v; def s=ring(l); setring s; // test, if y^2 + hy - f is hyperelliptic. int i=1; poly h=imap(R,h); poly f=imap(R,f); poly F=y2 + h*y - f; ideal I=F, diff(F,x) , diff(F,y); ideal J=std(I); if ( J != 1 ) { i=0; "The curve is singular!"; } if ( deg(f) mod 2 != 1 ) { i=0; "The polynomial ",f," has even degree!"; } if ( leadcoef(f) != 1 ) { i=0; "The polynomial ",f," is not monic!"; } if ( 2*deg(h) > deg(f)-1 ) { i=0; "The polynomial ",h," has degree ",deg(h),"!"; } setring(R); return(i); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; ishyper(h,f); } //================= Test, if a given ponit is on the curve ==================== proc isoncurve(list P, poly h, poly f) "USAGE: isoncurve(P,h,f); h,f=poly; P=list RETURN: 1 or 0 (if P is on curve or not) NOTE: Tests, if P=(P[1],P[2]) is on the hyperelliptic curve y^2+h(x)y=f(x). Curve is defined over basering. EXAMPLE: example isoncurve; shows an example " { if ( P[2]^2 + subst(h,var(1),P[1])*P[2] - subst(f,var(1),P[1]) == 0 ) { return(1); } return(0); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; list P=2,3; isoncurve(P,h,f); } //====================== Remainder of a polynomial division =================== proc divrem(poly f,poly g) "USAGE: divrem(f,g); f,g poly RETURN: remainder of the division f/g NOTE: Computes R, s.t. f=a*g + R, and deg(R) < deg(g) EXAMPLE: example divrem; shows an example " { return(reduce(f,std(g))); } example { "EXAMPLE:"; echo = 2; ring R=0,x,dp; divrem(x2+1,x2); } //================ chinese remainder theorem for polynomials ================== proc chinrestp(list b,list moduli) "USAGE: chinrestp(b,moduli); moduli, b, moduli=list of polynomials RETURN: poly x, s.t. x= b[i] mod moduli[i] NOTE: chinese remainder theorem for polynomials EXAMPLE: example chinrestp; shows an example " { int i; int n=size(moduli); poly M=1; for(i=1;i<=n;i++) { M=M*moduli[i]; } list m; for(i=1;i<=n;i++) { m[i]=M/moduli[i]; } list y; for(i=1;i<=n;i++) { y[i]= extgcd(moduli[i],m[i])[3]; } poly B=0; for(i=1;i<=n;i++) { B=B+y[i]*m[i]*b[i]; } B=divrem(B,M); return(B); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; list b=3x-4, -3x2+1, 1, 4; list moduli=(x-2)^2, (x-5)^3, x-1, x-6; chinrestp(b,moduli); } //========================= norm of a polynomial =============================== proc norm(poly a, poly b, poly h, poly f) "USAGE: norm(a,b,h,f); RETURN: norm of a(x)-b(x)y in IF[C] NOTE: The norm is a polynomial in just one variable. Curve C: y^2+h(x)y=f(x) is defined over basering. EXAMPLE: example norm; shows an example " { poly n=a^2+a*b*h-b^2*f; return(n); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; poly a=x2+1; poly b=x; norm(a,b,h,f); } //========== multiplikation of polynomials in the coordinate ring ============= proc multi(poly a, poly b, poly c, poly d, poly h, poly f) "USAGE: multi(a,b,c,d,h,f); RETURN: list L with L[1]-L[2]y=(a(x)-b(x)y)*(c(x)-d(x)y) in IF[C] NOTE: Curve C: y^2+h(x)y=f(x) is defined over basering. EXAMPLE: example multi; shows an example " { poly A=a*c + b*d*f; poly B=b*c +a*d + b*h*d; return (list(A,B)); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; poly h=x; poly f=x5+5x4+6x2+x+3; // hyperelliptic curve y^2 + h*y = f poly a=x2+1; poly b=x; poly c=5; poly d=-x; multi(a,b,c,d,h,f); } //================== polynomial expansion around a point ======================== proc darst(list P,int k, poly h, poly f) "USAGE: darst(P,k,h,f); RETURN: list c of length k NOTE: expansion around point P in IF[C], s.t. y=c[1]+c[2]*(x-P[1]) +...+c[k]*(x-P[1])^k-1 + rest. Curve C:y^2+h(x)y=f(x) is defined over basering. EXAMPLE: example darst; shows an example " { if ( P[2] == -P[2]- subst(h,var(1),P[1])) { ERROR("no special points allowed"); } list c; list r; list n; poly N; c[1]=P[2]; r[1]=list(0,-1,1,0); poly r1,r2,r3,r4; // rational function are represented as (r1 - r2*y) / (r3 - r4*y) for (int i=1; i0) { s=#[1]; } else { s=0; } for (int i=2; i<=size(fa[1]) ; i++) { // searching roots by finding polynomials of degree 1 if ( deg(fa[1][i]) !=1 ) { if (s==0) { "WARNIG: ", fa[1][i], "is irreducible over this field !"; } else { irred=1; } } else { x0=var(1) - fa[1][i]; // finding the y-coordinates; max. 2 y= factorize(var(1)^2 + var(1)*subst(h,var(1),x0) - subst(f,var(1),x0)); if ( deg(y[1][2]) == 1) // if root belongs to point on curve, then... { // compute order of a-b*y in the founded point j=j+1; p[j]=list(x0,var(1)-y[1][2],fa[2][i]); if ( y[2][2]== 1) // ordinary point { j=j+1; p[j]=list(x0 , var(1)-y[1][3] , fa[2][i] ); if (a/(var(1)-x0)^(fa[2][i]) - b/(var(1)-x0)^(fa[2][i]) * p[j][2] ==0 ) { p[j][3]= p[j][3] + ordnung(x0,norm(a/(var(1)-x0)^(fa[2][i]) , b/(var(1)-x0)^(fa[2][i]),h,f)); } if (a/(var(1)-x0)^(fa[2][i]) - b/(var(1)-x0)^(fa[2][i]) * p[j-1][2] ==0 ) { p[j-1][3]=p[j-1][3] + ordnung(x0,norm(a/(var(1)-x0)^(fa[2][i]) , b/(var(1)-x0)^(fa[2][i]),h,f)); } } else // special point { p[j][3]=p[j][3] *2 ; if (a/(var(1)-x0)^(fa[2][i]) - b/(var(1)-x0)^(fa[2][i]) * p[j][2] ==0 ) { p[j][3]=p[j][3] + ordnung(x0,norm(a/(var(1)-x0)^(fa[2][i]) , b/(var(1)-x0)^(fa[2][i]),h,f)); } } } // Norm of a-b*y is reduced by common root of a and b // (is worked off) Norm = Norm/((var(1)-x0)^(ordnung(x0,Norm))); } } // some points are still missing; points for which a and b have no common // roots, but norm(a-b*Y)=0 . fa=factorize(Norm); for ( i=2 ; i<=size(fa[1]) ; i++) { if ( deg(fa[1][i]) !=1) { if (s==0) { "WARNING: ", fa[1][i], "is irreducible over this field !"; } else { irred=1; } } else { x0=var(1) - fa[1][i]; y= factorize(var(1)^2 + var(1)*subst(h,var(1),x0) - subst(f,var(1),x0)); if ( deg(y[1][2]) == 1) // if root belongs to point on curve, then... { if (subst(a,var(1),x0)- subst(b,var(1),x0)* (var(1)-y[1][2]) ==0) { p[size(p)+1]=list(x0,var(1)-y[1][2], ordnung(x0,Norm,h,f)); } if ( y[2][2]== 1) // ordinary point { if (subst(a,var(1),x0)- subst(b,var(1),x0)* (var(1)-y[1][3]) ==0) { p[size(p)+1]=list(x0 , var(1)-y[1][3] , ordnung(x0,Norm,h,f)); } } } } } if (s==0) { return(p); } return(p,irred); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; poly a=(x-1)^2*(x-6); poly b=0; divisor(a,b,h,f,1); } //===================== gcd of two divisors =================================== proc gcddivisor(list p, list q) "USAGE: gcddivisor(p,q); RETURN: list P NOTE: gcd of two divisors EXAMPLE: example gcddivisor; shows an example " { list e; int i,j; for (i=1 ; i<= size(p) ; i++) { for (j=1 ; j<= size(q) ; j++) { if ( p[i][1] == q[j][1] and p[i][2] == q[j][2]) { if ( p[i][3] <= q[j][3] ) { e[size(e)+1]= list (p[i][1] , p[i][2] , p[i][3]); } else { e[size(e)+1]= list (q[j][1] , q[j][2] , q[j][3]); } } } } return(e); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; // two divisors list p=list(-1,-3,1),list(1,1,2); list q=list(1,1,1),list(2,2,1); gcddivisor(p,q); } //========== semireduced divisor from rational representation================= proc semidiv(list D,poly h, poly f) "USAGE: semidiv(D,h,f); RETURN: list P NOTE: important: Divisor D has to be semireduced! Computes semireduced divisor P[1][3]*(P[1][1], P[1][2]) +...+ P[size(P)][3]* *(P[size(P)][1], P[size(P)][2]) - (*)infty=div(D[1],D[2])@* Curve C:y^2+h(x)y=f(x) is defined over basering. EXAMPLE: example semidiv; shows an example " { if ( deg(D[2]) >= deg(D[1]) or divrem(D[2]^2+D[2]*h-f,D[1]) != 0 ) { ERROR("Pair of polynomials doesn't belong to semireduced divisor!"); } list D1,D2; int s1,s2; D1,s1=divisor(D[1],0,h,f,1); D2,s2=divisor(D[2],1,h,f,1); // Only if irreducible polynomials occured in D1 !and! D2 a warning // is necessary. if (s1==1 and s2==1) { "Attention: Perhaps some points were not found over this field!"; } return(gcddivisor(D1,D2)); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; // Divisor list D=x2-1,2x-1; semidiv(D,h,f); } //=============== Cantor's algorithm - composition ============================ proc cantoradd(list D, list Q, poly h, poly f) "USAGE: cantoradd(D,Q,h,f); RETURN: list P NOTE: Cantor's Algorithm - composition important: D and Q have to be semireduced! Computes semireduced divisor div(P[1],P[2])= div(D[1],D[2]) + div(Q[1],Q[2]) The divisors are defined over the basering. Curve C: y^2+h(x)y=f(x) is defined over the basering. EXAMPLE: example cantoradd; shows an example " { poly a; poly b; list e=extgcd(D[1],Q[1]); if ( e[1]==1 ) { a=D[1]*Q[1]; b=divrem( e[2]*D[1]*Q[2] + e[3]*Q[1]*D[2] ,a); return(list(a,b)); } list c=extgcd(e[1],D[2]+Q[2]+h); poly s1=e[2]*c[2]; poly s2=c[2]*e[3]; poly s3=c[3]; a=D[1]*Q[1]/c[1]^2; b=divrem((s1*D[1]*Q[2] + s2*Q[1]*D[2] + s3*(D[2]*Q[2] + f))/c[1],a); return(list(a,b)); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; // two divisors in rational representation list D=x2-1,2x-1; list Q=x2-3x+2,-3x+1; cantoradd(D,Q,h,f); } //==================== Cantor's algorithm - reduction ========================= proc cantorred(list D,poly h,poly f) "USAGE: cantorred(D,h,f); RETURN: list N NOTE: Cantor's algorithm - reduction. important: Divisor D has to be semireduced! Computes reduced divisor div(N[1],N[2])= div(D[1],D[2]).@* The divisors are defined over the basering. Curve C: y^2+h(x)y=f(x) is defined over the basering. EXAMPLE: example cantorred; shows an example " { list N=D; while ( 2*deg(N[1]) > deg(f)-1 ) { N[1]=(f - N[2]*h - N[2]^2)/N[1]; N[2]=divrem(-h-N[2],N[1]); } N[1]=N[1]/leadcoef(N[1]); return(N); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; // semireduced divisor list D=2x4+3x3-3x-2, -x3-2x2+3x+1; cantorred(D,h,f); } //================= doubling a semireduced divisor ============================ proc double(list D, poly h, poly f) "USAGE: double(D,h,f); RETURN: list Q=2*D NOTE: important: Divisor D has to be semireduced! Special case of Cantor's algorithm. Computes reduced divisor div(Q[1],Q[2])= 2*div(D[1],D[2]).@* The divisors are defined over the basering. Curve C:y^2+h(x)y=f(x) is defined over the basering. EXAMPLE: example double; shows an example " { list c=extgcd(D[1], 2*D[2] + h); poly a=D[1]*D[1]/c[1]^2; poly b=divrem((c[2]*D[1]*D[2] + c[3]*(D[2]*D[2] + f))/c[1],a); return(cantorred(list(a,b),h,f)); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; // reduced divisor list D=x2-1,2x-1; double(D,h,f); } //================ multiples of a semireduced divisor ========================= proc cantormult(int m, list D, poly h, poly f) "USAGE: cantormult(m,D,h,f); RETURN: list res=m*D NOTE: important: Divisor D has to be semireduced! Uses repeated doublings for a faster computation of the reduced divisor m*D. Attention: Factor m=int, this means bounded. For m<0 the inverse of m*D is returned. The divisors are defined over the basering. Curve C: y^2+h(x)y=f(x) is defined over the basering. EXAMPLE: example cantormult; shows an example " { list res=1,0; list bas=D; int exp=m; if (exp==0) { return(list(1,0)); } if (exp==1) { return(D); } if (exp==-1) { return(list(D[1],-D[2]-h)) ; } if ( exp < 0) { exp=-exp; } while ( exp > 0 ) { if ( (exp mod 2) !=0 ) { res = cantorred(cantoradd(res,bas,h,f),h,f); exp=exp-1; } bas=double(bas,h,f); exp=exp div 2; } if ( m < 0 ) { res[2]=-res[2]-h; } return(res); } example { "EXAMPLE:"; echo = 2; ring R=7,x,dp; // hyperelliptic curve y^2 + h*y = f poly h=x; poly f=x5+5x4+6x2+x+3; // reduced divisor list D=x2-1,2x-1; cantormult(34,D,h,f); } /* //============================================================================= // In the following you find a large example, which demostrates the use of // the most important procedures. //============================================================================= //---- field with 2^5=32 elements ---- ring r=(2,a),x,dp; minpoly=a5+a2+1; //---- hyperelliptic curve y^2 + hy = f ---- poly h=x2+x; poly f=x5+x3+1; //---- two divisors ---- list l1=list(a30,0,1),list(0,1,1); list l2=list(a30,a16,1),list(1,1,1); //---- their rational representation ---- list D1=ratrep(l1,h,f); D1; //[1]: // x2+(a4+a)*x //[2]: // (a)*x+1 list D2=ratrep(l2,h,f); D2; //[1]: // x2+(a4+a+1)*x+(a4+a) //[2]: // (a3+a2+a+1)*x+(a3+a2+a) //---- back to the point-based-representation ---- semidiv(D1,h,f); //[1]: // [1]: // (a4+a) // [2]: // 0 // [3]: // 1 //[2]: // [1]: // 0 // [2]: // 1 // [3]: // 1 semidiv(D2,h,f); //[1]: // [1]: // (a4+a) // [2]: // (a4+a3+a+1) // [3]: // 1 //[2]: // [1]: // 1 // [2]: // 1 // [3]: // 1 //---- adding D1 and D2 ---- list D12=cantorred(cantoradd(D1,D2,h,f),h,f); D12; //[1]: // x2+x //[2]: // 1 //---- D1+D2 in point-based-representation ---- semidiv(D12,h,f); //[1]: // [1]: // 1 // [2]: // 1 // [3]: // 1 //[2]: // [1]: // 0 // [2]: // 1 // [3]: // 1 //---- D1 + D1 (2 possible ways, same result) ---- cantorred(cantoradd(D1,D1,h,f),h,f); double(D1,h,f); //[1]: // x2+(a3+1) //[2]: // (a4+a3+a+1)*x+(a4+a3+a2+a+1) //---- order of D1 in the jacobian over the basering ---- int i=1; list E=D1; while (E[1] != 1 or E[2] != 0 ) { E= cantorred(cantoradd(E,D1,h,f),h,f); i=i+1; } i; // 482 //---- proof with multiplikation validates the result ---- cantormult(i,D1,h,f); //[1]: // 1 //[2]: // 0 //---- computing the inverse of D1 ---- list d1= cantormult(-1,D1,h,f); d1; //[1]: // x2+(a4+a)*x //[2]: // x2+(a+1)*x+1 //---- proof validates the result ---- cantoradd(d1,D1,h,f); //[1]: // 1 //[2]: // 0 */ singular-4.0.3+ds/Singular/LIB/inout.lib000066400000000000000000000514531266270727000200050ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version inout.lib 4.0.0.0 Jun_2013 "; // $Id: f30ec30553869bbe596da3bd3649a0494e59cc09 $ category="General purpose"; info=" LIBRARY: inout.lib Printing and Manipulating In- and Output PROCEDURES: allprint(list); print list if ALLprint is defined, with pause if >0 lprint(poly/...[,n]); display poly/... fitting to pagewidth [size n] pmat(matrix[,n]); print form-matrix [first n chars of each colum] rMacaulay(string); read Macaulay_1 output and return its @sc{Singular} format show(any); display any object in a compact format showrecursive(id,p); display id recursively with respect to variables in p split(string,n); split given string into lines of length n tab(n); string of n space tabs pause([prompt]); stop the computation until user input (parameters in square brackets [] are optional) "; /////////////////////////////////////////////////////////////////////////////// proc allprint (list #) "USAGE: allprint(L); L list DISPLAY: prints L[1], L[2], ... if an integer with name ALLprint is defined. @* makes \"pause\", if ALLprint > 0 RETURN: no return value EXAMPLE: example allprint; shows an example " { if( defined(ALLprint) ) { int i; for( i=1; i<=size(#); i=i+1 ) { print(#[i]); } if( ALLprint >0 ) { pause(); } } return(); } example { "EXAMPLE:"; echo = 2; ring S; matrix M=matrix(freemodule(2),3,3); int ALLprint; export ALLprint; allprint("M =",M); kill ALLprint; } /////////////////////////////////////////////////////////////////////////////// proc lprint "USAGE: lprint(id[,n]); id poly/ideal/vector/module/matrix, n integer RETURN: string of id in a format fitting into lines of size n, such that no monomial gets destroyed, i.e. the new line starts with + or -; (default: n = pagewidth). NOTE: id is printed columnwise, each column separated by a blank line; hence lprint(transpose(id)); displays a matrix id in a format which can be used as input. EXAMPLE: example lprint; shows an example " { if (size(#)==1) { int n = pagewidth-3; } else {int n = #[2]-3; } matrix M = matrix(#[1]); poly p,h,L; string s1,s,S; int jj,ii,a; for (jj=1; jj<=ncols(M); jj=jj+1) { for (ii=1; ii<=nrows(M); ii=ii+1) { a=2; if (a+size(string(M[ii,jj])) <= n) {s = " "+string(M[ii,jj]);} else { h = lead(M[ii,jj]); p = M[ii,jj] - h; L = lead(p); while (p != 0) { if (a+size(string(h+L)) > n) { s = string(h); if (a != 0) { s = " "+s; } if (a == 0 and s[1] != "-") { s = "+" + s; } a=0; h=0; S=S+newline+s; } h = h + L; p = p - L; L = lead(p); } s = string(h); if (a == 0 and s[1] != "-") { s = "+" + s; } } if (ii != nrows(M)) { s = s+","; S=S+newline+s; } else { if (jj != ncols(M)) { s = s+","; S=S+newline+s+newline;} else { S=S+newline+s; } } } } return(S[2,size(S)-1]); } example { "EXAMPLE:"; echo = 2; ring r= 0,(x,y,z),ds; poly f=((x+y)*(x-y)*(x+z)*(y+z)^2); lprint(f,40); module m = [f*(x-y)],[0,f*(x-y)]; string s=lprint(m); s;""; execute("matrix M[2][2]="+s+";"); //use the string s as input module m1 = transpose(M); //should be the same as m print(matrix(m)-matrix(m1)); } /////////////////////////////////////////////////////////////////////////////// proc pmat (matrix m, list #) "USAGE: pmat(M[,n]); M matrix, n integer RETURN: A string representing M in array format if it fits into pagewidth; if n is given, only the first n characters of each column are shown (n>1 required), where a truncation of a column is indicated by two dots (\'..\') EXAMPLE: example pmat; shows an example " { //------------- main case: input is a matrix, no second argument--------------- string OUT = ""; if ( size(#)==0) { int elems,mlen,slen,c,r; //-------------- count maximal size of each column, and sum up ------------- for ( c=1; c<=ncols(m); c=c+1) { int len(c); for (r=1; r<=nrows(m); r=r+1) { elems = elems+1; string s(elems) = string(m[r,c])+","; slen = size(s(elems)); if ( slen>len(c) ) { len(c) = slen; } } mlen = mlen+len(c); } //---------------------- print all - except last - rows -------------------- string aus; string sep = " "; if (mlen >= pagewidth) { sep = newline; } for (r=1; r1) { string aus,tmp; int c,r; //---------------------- print all - except last - rows -------------------- for ( r=1; r#[1]) { tmp[#[1]-1]="."; tmp[#[1]] ="."; aus=aus+tmp[1,#[1]]+", "; } else { tmp=tmp+","; aus=aus+tmp[1,#[1]+1]+" "; } } OUT=OUT+aus+newline; } //--------------- print last row (no comma after last entry) --------------- aus = ""; for (c=1; c#[1]) { tmp[#[1]-1]="."; tmp[#[1]] ="."; aus=aus+tmp[1,#[1]]+", "; } else { tmp=tmp+","; aus=aus+tmp[1,#[1]+1]+" "; } } tmp=string(m[nrows(m),ncols(m)]); if (size(tmp)>#[1]) { tmp[#[1]-1]="."; tmp[#[1]] ="."; } aus = aus + tmp[1,#[1]]; OUT=OUT+aus; return(OUT); } } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),ls; ideal i= x,z+3y,x+y,z; matrix m[3][3]=i^2; pmat(m); pmat(m,5); } /////////////////////////////////////////////////////////////////////////////// proc rMacaulay "USAGE: rMacaulay(s[,n]); s string, n integer RETURN: A string denoting a file which should be readable by Singular and it should be produced by Macaulay Classic. If a second argument is present the first n lines of the file are deleted (which is useful if the file was produced e.g. by the putstd command of Macaulay). NOTE: This does not always work with 'cut and paste' since the character \ is treated differently EXAMPLE: example rMacaulay; shows an example " { int n; if( size(#)==2 ) { n=#[2]; } string s0 = #[1]; //------------------------ delete first n=#[2] lines -------------------------- int ii=find(s0,newline); int jj; for ( jj=1; jj<=n; jj=jj+1) { s0 = s0[ii+1,size(s0)-ii]; ii = find(s0,newline); } //--------------- delete blanks and 'newline' at start and end ---------------- ii = 1; while( s0[ii]==" " or s0[ii]==newline ) { ii=ii+1; } s0 = s0[ii,size(s0)-ii+1]; ii = size(s0); while ( s0[ii]==" " or s0[ii]==newline) { ii=ii-1; } s0 = s0[1,ii]; //------------------------- make each line a string --------------------------- ii = find(s0,newline); jj=0; int kk; while( ii!=0 ) { jj = jj+1; kk = ii+1; while( s0[kk]==" " or s0[kk]==newline ) { kk=kk+1; } string s(jj) = s0[1,ii-1]; s0 = s0[kk,size(s0)-kk+1]; ii = find(s0,newline); } jj=jj+1; string s(jj) = s0; //------------ delete blanks and \ at end of each string and add , ------------ for( ii=1; ii<=jj; ii=ii+1 ) { kk = 1; while( s(ii)[kk]==" " ) { kk=kk+1; } s(ii) = s(ii)[kk,size(s(ii))-kk+1]; kk = size(s(ii)); while( s(ii)[kk]==" " or s(ii)[kk]=="\\" or s(ii)[kk]==newline ) { kk = kk-1; } s(ii) = s(ii)[1,kk]+","+newline; } //------------------------ replace blanks by , and add up --------------------- int ll; s0 = ""; string s1,s2; for( ii=1; ii<=jj; ii=ii+1 ) { s1 = ""; s2 = s(ii); kk = find(s(ii)," "); ll=kk+1; while( kk!=0 ) { while( s2[ll]==" ") { ll=ll+1; } if( kk!=1 ) { s1=s1+s2[1,kk-1]+","+s2[kk+1,ll-kk]; } if( kk==1 ) { s1 = s1+","+s2[kk+1,ll-kk]; } s2 = s2[ll+1,size(s2)-ll]; kk = find(s2," "); ll=kk+1; } s(ii) = s1+s2; s0 = s0+s(ii); } //---------------------------- replace [] by () ------------------------------- s1 = ""; s2 = s0; ii = find(s2,"["); while( ii!=0 ) { s0 = s0[1,ii-1]+"("+s0[ii+1,size(s0)-ii]; if( ii>2 ) { if(s0[ii-2]!="+" and s0[ii-2]!="-" and s0[ii-2]!="," and s0[ii-2]!=newline) { s0 = s0[1,ii-2]+"*"+s0[ii-1,size(s0)-ii+2]; } } ii = find(s0,"["); } jj = find(s0,"]"); while ( jj!=0 ) { s0 = s0[1,jj-1]+")"+s0[jj+1,size(s0)-jj]; if(s0[jj+1]!="+"and s0[jj+1]!="-" and s0[jj+1]!="," and s0[jj+1]!="*") { s0 = s0[1,jj] + "^" + s0[jj+1,size(s0)-jj]; } jj = find(s0,"]"); } s0 = s0[1,size(s0)-2]; return(s0); } example { "EXAMPLE:"; echo = 2; // Assume there exists a file 'Macid' with the following ideal in // Macaulay format:" // x[0]3-101/74x[0]2x[1]+7371x[0]x[1]2-13/83x[1]3-x[0]2x[2] \ // -4/71x[0]x[1]x[2] // Read this file into Singular and assign it to the string s1 by: // string s1 = read("Macid"); // This is equivalent to"; string s1 = "x[0]3-101/74x[0]2x[1]+7371x[0]x[1]2-13/83x[1]3-x[0]2x[2]-4/71x[0]x[1]x[2]"; rMacaulay(s1); // You may wish to assign s1 to a Singular ideal id: string sid = "ideal id =",rMacaulay(s1),";"; ring r = 0,x(0..3),dp; execute(sid); id; ""; // Now treat a matrix in Macaulay format. Using the execute // command, this could be assinged to a Singular matrix as above. string s2 = " 0 0 0 0 0 a3 0 0 0 0 0 b3 0 0 0 0 0 c3 0 0 0 0 0 d3 0 0 0 0 0 e3 "; rMacaulay(s2); } /////////////////////////////////////////////////////////////////////////////// proc show (def @@id, list #) "USAGE: show(id); id any object of basering or of type ring/qring @* show(R,s); R=ring, s=string (s = name of an object belonging to R) DISPLAY: display id/s in a compact format together with some information RETURN: no return value NOTE: objects of type string, int, intvec, intmat belong to any ring. id may be a ring or a qring. In this case the minimal polynomial is displayed, and, for a qring, also the defining ideal. id may be of type list but the list must not contain a ring. @* show(R,s) does not work inside a procedure! EXAMPLE: example show; shows an example " { //------------- use funny names in order to avoid name conflicts -------------- int @li@, @ii; string @s@,@@s; int @short@=short; short=1; //----------------------------- check syntax ---------------------------------- if( size(#)!= 0 ) { if( typeof(#[1])=="int" ) { @li@=#[1]; } } if ( typeof(@@id)!="list" ) { if( size(#)==0 ) { def @id@ = @@id; } if( size(#)==1 ) { if( typeof(#[1])=="int" ) { def @id@ = @@id; } if( typeof(#[1])=="string" ) { if( typeof(@@id)=="ring") { def @R@ = @@id; setring @R@; def @id@=`#[1]`; } } } } //----------------------- case: @@id is of type list ---------------------------- if ( typeof(@@id)=="list" ) { // @@s = tab(@li@)+"// list, "+string(size(@@id))+" element(s):"; @@s = tab((3*(voice-2)))+"// list, "+string(size(@@id))+" element(s):"; @@s; for ( @ii=1; @ii<=size(@@id); @ii++ ) { if( typeof(@@id[@ii])!="none" ) { def @id(@ii) = @@id[@ii]; tab(3*(voice-2))+"["+string(@ii)+"]:"; // show(@id(@ii),@li@+3*(voice-1)); show(@id(@ii),3*(voice-1)); } else { "["+string(@ii)+"]:"; tab(@li@+2),"//",@@id[@ii]; } } short=@short@; return(); } if( defined(@id@)!=voice ) { "// wrong syntax, type help show;"; return();} //-------------------- case: @id@ belongs to any ring ------------------------- if( typeof(@id@)=="string" or typeof(@id@)=="int" or typeof(@id@)=="intvec" or typeof(@id@)=="intmat" or typeof(@id@)=="list" ) { if( typeof(@id@)!="intmat" ) { @@s = tab(@li@)+"// "+typeof(@id@)+", size "+string(size(@id@)); @@s; } if( typeof(@id@)=="intmat" ) { @@s = tab(@li@)+"// "+typeof(@id@)+", "+string(nrows(@id@))+" rows, " + string(ncols(@id@))+" columns"; @@s; } @id@; short=@short@; return(); } //-------------------- case: @id@ belongs to basering ------------------------- if( typeof(@id@)=="poly" or typeof(@id@)=="ideal" or typeof(@id@)=="matrix" ) { @@s = tab(@li@)+"// "+ typeof(@id@); if( typeof(@id@)=="ideal" ) { @@s=@@s + ", "+string(ncols(@id@))+" generator(s)"; @@s; print(ideal(@id@)); } if( typeof(@id@)=="poly" ) { @@s=@@s + ", "+string(size(@id@))+" monomial(s)"; @@s; print(poly(@id@)); } if( typeof(@id@)=="matrix") { @@s=@@s + ", "+string(nrows(@id@))+"x"+string(ncols(@id@)); @@s; print(matrix(@id@)); } short=@short@; return(); } if( typeof(@id@)=="vector" ) { @@s = tab(@li@)+"// "+typeof(@id@); @@s; print(@id@); short=@short@; return(); } if( typeof(@id@)=="module" ) { @s@=", "+string(ncols(@id@))+" generator(s)"; @@s = tab(@li@)+"// "+ typeof(@id@)+ @s@; @@s; int @n@; for( @n@=1; @n@<=ncols(@id@); @n@=@n@+1 ) { print(@id@[@n@]); } short=@short@; return(); } if( typeof(@id@)=="number" or typeof(@id@)=="resolution" ) { @@s = tab(@li@)+"// ", typeof(@id@); @@s; @id@; short=@short@; return(); } if( typeof(@id@)=="map" ) { def @map = @id@; @@s = tab(@li@)+"// i-th variable of preimage ring is mapped to @map[i]"; @@s; if( size(#)==0 ) { type @map; } if( size(#)==1 ) { if( typeof(#[1])=="int" ) { type @map; } if( typeof(#[1])=="string" ) { type `#[1]`; } } short=@short@; return(); } //---------------------- case: @id@ is a ring/qring --------------------------- if( typeof(@id@)=="ring" ) { setring @id@; string s="("+charstr(@id@)+"),("+varstr(@id@)+"),("+ordstr(@id@)+");"; if( typeof(@id@)=="ring" ) { list na@me@s=names(@id@); @@s = tab(@li@)+"// ring:"; @@s,s; @@s = tab(@li@)+"// minpoly ="; @@s,minpoly; if (size(ideal(@id@))>0) { @@s = tab(@li@)+"// quotient ring from ideal:"; @@s;ideal(@id@); } kill @id@; "// objects belonging to this ring:"; listvar(poly);listvar(ideal); listvar(vector);listvar(module); listvar(map);listvar(matrix); listvar(number);listvar(resolution); for(int names@i=1;names@i<=size(na@me@s);names@i++) { def @hi@lf@=`na@me@s[names@i]`; if ((typeof(@hi@lf@)!="poly") and (typeof(@hi@lf@)!="ideal") and (typeof(@hi@lf@)!="vector") and (typeof(@hi@lf@)!="module") and (typeof(@hi@lf@)!="map") and (typeof(@hi@lf@)!="matrix") and (typeof(@hi@lf@)!="number") and (typeof(@hi@lf@)!="resolution")) { listvar(`na@me@s[names@i]`); } kill @hi@lf@; } } short=@short@; //return(); } } example { "EXAMPLE:"; echo = 2; ring r; show(r); ideal i=x^3+y^5-6*z^3,xy,x3-y2; show(i,3); // introduce 3 space tabs before information vector v=x*gen(1)+y*gen(3); module m=v,2*v+gen(4); list L = i,v,m; show(L); ring S=(0,T),(a,b,c,d),ws(1,2,3,4); minpoly = T^2+1; ideal i=a2+b,c2+T^2*d2; i=std(i); qring Q=i; show(Q); map F=r,a2,b^2,3*c3; show(F); // Apply 'show' to i (which does not belong to the basering) by typing // ring r; ideal i=xy,x3-y2; ring Q; show(r,"i"); } /////////////////////////////////////////////////////////////////////////////// proc showrecursive (def @@id,poly p,list #) "USAGE: showrecursive(id,p[,ord]); id any object of basering, p= product of variables and ord=string (any allowed ordstr) DISPLAY: display 'id' in a recursive format as a polynomial in the variables occuring in p with coefficients in the remaining variables. This is done by mapping to a ring with parameters [and ordering 'ord', if a 3rd argument is present (default: ord=\"dp\")] and applying procedure 'show' RETURN: no return value EXAMPLE: example showrecursive; shows an example " { def P = basering; int ii; string newchar = charstr(P); string neword = "dp"; if( size(#) == 1 ) { neword = #[1]; } string newvar; for( ii=1; ii <= nvars(P); ii++ ) { if( p/var(ii) == 0 ) { newchar = newchar + ","+varstr(ii); } else { newvar = newvar + ","+varstr(ii); } } newvar = newvar[2,size(newvar)-1]; execute("ring newP=("+newchar+"),("+newvar+"),("+neword+");"); def @@id = imap(P,@@id); show(@@id); return(); } example { "EXAMPLE:"; echo=2; ring r=2,(a,b,c,d,x,y),ds; poly f=y+ax2+bx3+cx2y2+dxy3; showrecursive(f,x); showrecursive(f,xy,"lp"); } /////////////////////////////////////////////////////////////////////////////// proc split (string s, list #) "USAGE: split(s[,n]); s string, n integer RETURN: same string, split into lines of length n separated by \ (default: n=pagewidth) NOTE: may be used in connection with lprint EXAMPLE: example split; shows an example " { string line,re; int p,l; if( size(#)==0 ) { int n=pagewidth; } else { int n=#[1]; } if( s[size(s),1] != newline ) { s=s+newline; } l=size(s); while( 1 ) { p=1; l=find(s,newline); line=s[1,l]; while( l>=n ) { re=re+line[p,n-2]+"\\"+newline; p=p+n-2; l=l-n+2; } re=re+line[p,l-1]+"\\"+newline; l=size(line); if( l>=size(s) ) break; s=s[l+1,size(s)-l]; } return (re[1,size(re)-2]); } example { "EXAMPLE:"; echo = 2; ring r= 0,(x,y,z),ds; poly f = (x+y+z)^4; split(string(f),50); split(lprint(f)); } /////////////////////////////////////////////////////////////////////////////// proc tab (int n) "USAGE: tab(n); n integer RETURN: string of n space tabs EXAMPLE: example tab; shows an example " { if( n==0 ) { return(""); } string s=" "; return(s[1,n]); } example { "EXAMPLE:"; echo = 2; for(int n=0; n<=5; n=n+1) { tab(5-n)+"*"+tab(n)+"+"+tab(n)+"*"; } } /////////////////////////////////////////////////////////////////////////////// proc pause(list #) "USAGE: pause([ prompt ]) prompt string RETURN: none PURPOSE: interrupt the execution of commands, displays prompt or pause and waits for user input NOTE: pause is useful in procedures in connection with printlevel to interrupt the computation and to display intermediate results. SEE ALSO: read, printlevel EXAMPLE : example pause; shows an example " { string pr="pause>"; if (size(#)!=0) { pr=#[1]; } pr=read("",pr); } example { "EXAMPLE:"; echo=2; // can only be shown interactively, try the following commands: // pause("press to continue"); // pause(); // In the following pocedure TTT, xxx is printed and the execution of // TTT is stopped until the return-key is pressed, if printlevel>0. // xxx may be any result of a previous computation or a comment, etc: // // proc TTT // { int pp = printlevel-voice+2; //pp=0 if printlevel=0 and if TTT is // .... //not called from another procedure // if( pp>0 ) // { // print( xxx ); // pause("press to continue"); // } // .... // } } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/integralbasis.lib000066400000000000000000000467661266270727000215110ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version integralbasis.lib 4.0.0.0 Jun_2013 "; // $Id: d0a216c867e95ba8d62e1343a552b5572404b936 $ category="Commutative Algebra"; info=" LIBRARY: integralbasis.lib Integral basis in algebraic function fields AUTHORS: J. Boehm, j.boehm at mx.uni-saarland.de @* W. Decker, decker at mathematik.uni-kl.de> @* S. Laplagne, slaplagn at dm.uba.ar @* F. Seelisch, seelisch at mathematik.uni-kl.de OVERVIEW: Given an irreducible polynomial f in two variables defining a plane curve, this library implements an algorithm to compute an integral basis of the integral closure of the affine coordinate ring in the algebraic function field via normalization.@* The user can choose whether the algorithm will do the computation globally or (this is the default) compute in the localization at each component of the singular locus and put everything together. PROCEDURES: integralBasis(f, intVar); Integral basis of an algebraic function field "; LIB "normal.lib"; /////////////////////////////////////////////////////////////////////////////// proc integralBasis(poly f, int intVar, list #) "USAGE: integralBasis(f, intVar); f irreducible polynomial in two variables, intVar integer indicating that the intVar-th variable of the ring is the integral element.@* The base ring must be a ring in two variables, and the polynomial f must be monic as polynomial in the intVar-th variable.@* Optional parameters in list choose (can be entered in any order):@* Parameters for selecting the algorithm:@* - \"global\" -> computes the integral basis by computing the normalization of R/, where R is the base ring.@* - \"local\" -> computes the integral basis by computing the normalization of R/ localized at each component of the singular locus of R/, and then putting everything together. This is the default option.@* Other parameters:@* - \"isIrred\" -> assumes that the input polynomial f is irreducible, and therefore will not check this. If this option is given but f is not irreducible, the output might be wrong.@* - list(\"inputJ\", ideal inputJ) -> takes as initial test ideal the ideal inputJ. This option is only for use in other procedures. Using this option, the result might not be the integral basis.@* (When this option is given, the global option will be used.)@* - list(\"inputC\", ideal inputC) -> takes as initial conductor the ideal inputC. This option is only for use in other procedures. Using this option, the result might not be the integral basis.@* (When this option is given, the global option will be used.)@* RETURN: a list, say l, of size 2. l[1] is an ideal I and l[2] is a polynomial D such that the integral basis is b_0 = I[1] / D, b_1 = I[2] / D, ..., b_{n-1} = I[n] / D.@* That is, the integral closure of k[x] in the algebraic function field k(x,y) is @* k[x] b_0 + k[x] b_1 + ... + k[x] b_{n-1},@* where we assume that x is the transcendental variable, y is the integral element (indicated by intVar), f gives the integral equation and n is the degree of f as a polynomial in y.@* THEORY: We compute the integral basis of the integral closure of k[x] in k(x,y) by computing the normalization of the affine ring k[x,y]/ and converting the k[x,y]-module generators into a k[x]-basis.@* KEYWORDS: integral basis; normalization. SEE ALSO: normal. EXAMPLE: example integralBasis; shows an example " { int i; ideal inputJ = 0; ideal inputC = 0; string algorithm = "local"; // The default option is "local" int checkIrred = 1; //--------------------------- read the input options--------------------------- for ( i=1; i <= size(#); i++ ) { if ( typeof(#[i]) == "string" ) { if (#[i]=="local"){ algorithm = "local"; } if (#[i]=="global"){ algorithm = "global"; } if (#[i]=="isIrred"){ checkIrred = 0; } } if(typeof(#[i]) == "list"){ if(size(#[i]) == 2){ if (#[i][1]=="inputJ"){ if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly")){ inputJ = #[i][2]; algorithm = "global"; } } } if (#[i][1]=="inputC"){ if(size(#[i]) == 2){ if((typeof(#[i][2]) == "ideal") or (typeof(#[i][2]) == "poly")){ inputC = #[i][2]; algorithm = "global"; } } } } } //--------------------------- preliminary checks ------------------------------ // The ring must have two variables. if(nvars(basering) != 2){ ERROR("The base ring must be a ring in two variables."); } // intVar must be either 1 or 2. if((intVar < 0) || (intVar > 2)){ ERROR("The second parameter intVar must be either 1 or 2, indicating the integral variable."); } // No parameters or algebraic numbers are allowed. if(npars(basering) >0){ ERROR("No parameters or algebraic extensions are allowed in the base ring."); } // The polynomial f must be monic in the intVar-th variable. matrix cs = coeffs(f, var(intVar)); if(cs[size(cs),1] != 1){ ERROR("The input polynomial must be monic as a polynomial in the intVar-th variable."); } // The polynomial f must be irreducible. if(checkIrred == 1){ if(factorize(f)[2] != [1,1]){ ERROR("The input polynomial must be irreducible."); } } //--------------------- computing the integral basis -------------------------- return(cancelCF(integralBasisMain(f, algorithm, inputJ, inputC, intVar))); } example { "EXAMPLE:"; printlevel = printlevel+1; echo = 2; ring s = 0,(x,y),dp; poly f = y5-y4x+4y2x2-x4; list l = integralBasis(f, 2); l; // The integral basis of the integral closure of Q[x] in Q(x,y) consists // of the elements of l[1] divided by the polynomial l[2]. echo = 0; printlevel = printlevel-1; } /////////////////////////////////////////////////////////////////////////////// static proc integralBasisMain(poly f, string algorithm, ideal inputJ, ideal inputC, int intVar) // Computes the integral basis of R/, from the normalizaiton of R/. // inputC is the conductor ideal to be used in proc normal. // If inputC = < 0 >, then the default conductor ideal is used (the full // jacobian ideal). // inputJ is the test ideal to be used in proc normal. // If inputJ = < 0 >, then the default test ideal is used (the radical of the // conductor). { int dbg = printlevel - voice + 2; int i, j; int newRing = 0; // If = 1, a new ring with dp ordering was used. def origR = basering; //--------------------- moving to a ring with dp ordering --------------------- if(ordstr(origR) != "dp(2),C"){ // We change to dp ordering. list rl = ringlist(origR); list origOrd = rl[3]; list newOrd = list("dp", intvec(1:nvars(origR))), list("C", 0); rl[3] = newOrd; def R = ring(rl); setring R; poly f = fetch(origR, f); ideal inputJ = fetch(origR, inputJ); ideal inputC = fetch(origR, inputC); newRing = 1; } else { def R = basering; } //-------------------------------- basic data --------------------------------- // The degree of f with respect to the variable intVar ideal I = f; int n = size(coeffs(f, var(intVar))) - 1; // If the integral variable is the first, then the universal denominator // must be a polynomial in the second variable (and viceversa). string conduStr; if(intVar == 1){ conduStr = "var2"; } else { conduStr = "var1"; } list opts = conduStr; //-------------------------- computes the normalization ----------------------- if(algorithm == "local"){ list nor = integralLocal(I, opts); } else { if(inputJ != 0){ opts = insert(opts, list("inputJ", inputJ)); } if(inputC != 0){ opts = insert(opts, list("inputC", inputC)); } list nor = normal(I, opts); } ideal normalGen = nor[2][1]; poly D = normalGen[size(normalGen)]; // The universal denominator //Debug information if(dbg >= 2){ "The universal denominator is: ", D; } //--------------- computes the integral basis from the normalization ---------- // We define a new ring where the integral variable is the first (needed for // reduction) and has the appropiate ordering. list rl = ringlist(R); rl[2] = list(var(intVar), var(3-intVar)); rl[3] = list(list("C", 0), list("lp", intvec(1,1))); def S = ring(rl); setring S; // We map the elements in the previous ring to the new one poly f = imap(R, f); ideal normalGen = imap(R, normalGen); // We create the system of generatos y^i*f_j. list l; ideal red = groebner(f); for(j = 1; j <= size(normalGen); j++){ l[j] = reduce(normalGen[j], red); } for(i = 1; i <= n-1; i++){ for(j = 1; j <= size(normalGen); j++){ l[size(l)+1] = reduce(var(1)^i*normalGen[j], red); } } // To eliminate the redundant elements, we look at the polynomials as // elements of a free module where the coordinates are the coefficients // of the polynomials regarded as polynomials in y. // The groebner basis of the module generated by these elements // gives the desired basis. matrix vecs[n + 1][size(l)]; matrix coeffi[n + 1][2]; for(i = 1; i<= size(l); i++){ coeffi = coeffs(l[i], var(1)); vecs[1..nrows(coeffi), i] = coeffi[1..nrows(coeffi), 1]; } module M = vecs; M = std(M); // We go back to the original ring. setring origR; module M = imap(S, M); if(newRing == 1){ poly D = fetch(R, D); } // We go back from the module to the ring in two variables ideal G; poly g; for(i = 1; i <= size(M); i++){ g = 0; for(j = 0; j <= n; j++){ g = g + M[i][j+1] * var(intVar)^j; } G[i] = g; } // The first element in the output is the ideal of numerators. // The second element is the denominator. list outp = G, D; return(outp); } /////////////////////////////////////////////////////////////////////////////// static proc integralLocal(ideal I, list #){ // Computes the integral basis by localizing at the different components of // the singular locus. int i; int dbg = printlevel - voice + 4; def R = basering; list n; // Output of proc normal ideal norT; // Temporary data. poly denomT; // Temporary data. ideal nor; // Output of normal with the denominator changed to the // common denominator. ideal res; // The full integral basis //--------------------------- read the input options--------------------------- int denomOption = 0; for ( i=1; i <= size(#); i++ ) { if ( typeof(#[i]) == "string" ) { if (#[i]=="var1") {denomOption = 1;} if (#[i]=="var2") {denomOption = 2;} } } //------------------------ singular locus computation ------------------------- // We use a general method that works for any ideal. // For I defined by a single polynomial a simpler method could be used. list IM = mstd(I); I = IM[1]; int d = dim(I); ideal IMin = IM[2]; qring Q = I; // We work in the quotient by the Groebner basis of the ideal I option("redSB"); option("returnSB"); ideal I = fetch(R, I); attrib(I, "isSB", 1); ideal IMin = fetch(R, IMin); if(dbg >= 2){ int t = timer; } ideal J = minor(jacob(IMin), nvars(basering) - d, I); if(dbg >= 2){ "singular locus time: ", timer - t; t = timer; } setring R; ideal J = fetch(Q, J); J = J, I; J = groebner(J); if(dbg >= 2){ "groebner of the singular locus time: ", timer - t; t = timer; } if(dbg >= 2){ "The original singular locus is"; J; } //------------------------ universal denominator ------------------------------ // We could use the LCD of the denominators of each component, but we need // a denominator in the required variable. if(denomOption == 0){ poly condu = getSmallest(J); // Choses the polynomial of smallest degree // of J as universal denominator. } else { poly condu = getOneVar(J, denomOption); } //------------------- components of the singular locus------------------------ list pd = primdecGTZ(J); if(dbg >= 2){ "primary decomposition time:", timer - t; } if(dbg >= 1){ "The number of components of the Singular Locus is ", size(pd); } // The following commented lines are not needed for integral basis, since // all components are maximal. // Computes the maximal components and the components included in them //list comps = maxComps(pd); // For each maximal component, it intersects all the components included in it //list locs = intersectList(comps); //------------------- normalization of each component-------------------------- list opts; for(i = 1; i <= size(pd); i++){ //opts = #; // We use the prime components as test ideals in the normalization. //opts = list(list("inputJ", pd[i][2])); // We use the primary components as conductor in the normalization. opts = list(list("inputC", pd[i][1])); if(dbg >= 2){ t = timer; } n = normal(I, opts); if(dbg >= 2){ "normalization of component ", i, " time: ", timer - t; } if(size(n[2]) > 1){ ERROR("The input polynomial is not irreducible."); } // We add up the normalizations at each localization, to construct the // normalization of the whole ideal. norT = n[2][1]; denomT = norT[size(norT)]; // We change the denominator of the normalization of the localized ring, // to have the same denominator for all the normalizations. nor = changeDenominator(norT, denomT, condu, I); // We sum the result to the previous results. res = res, nor; } res = groebner(res); res[size(res)+1] = condu; // The output follows the output of proc normal, but we don't return the // ring structure, only the generators. (We return 0 instead of the ring.) return(list(0,list(res))); } /////////////////////////////////////////////////////////////////////////////// static proc cancelCF(list IB) "USAGE: cancelCF(IB); IB list of type returned by integralBasis RETURN: list of same type with common factor cancelled. KEYWORDS: greatest common divisor. " { int l = size(IB[1]); poly GrCoDi = IB[2]; int k = l; while((GrCoDi != 1) && (k >=1)) { GrCoDi = gcd(GrCoDi,IB[1][k]); k = k-1; } if(GrCoDi != 1) { for(k = 1; k <= l; k++) { IB[1][k] = IB[1][k]/GrCoDi; } IB[2] = IB[2]/GrCoDi; } return(IB); } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// /* ///////////////////////////////////////////////////////////////////////////// /// Examples for testing the main procedures /// Timings on wawa Sept 30 ///////////////////////////////////////////////////////////////////////////// LIB"integralbasis.lib"; // ------------------------------------------------------- // Example 1 // ------------------------------------------------------- ring r = 0, (x, y), dp; poly f = y5-y4x+4y2x2-x4; integralBasis(f, 2, "global"); // time 0 integralBasis(f, 1); integralBasis(f, 2); // local by default, time 0 normal(f); kill r; // ------------------------------------------------------- // Example 2 // ------------------------------------------------------- ring r = 0, (x, y), dp; poly f = y2-x2*(x+1)^2*(x+2); integralBasis(f, 2, "global"); // time 0 integralBasis(f, 2); // local by default, time 0 integralBasis(f, 2, list(list("inputJ", ideal(x,y)))); kill r; // ------------------------------------------------------- // Example 3 // ------------------------------------------------------- ring RR = 0, (x,y), dp; poly f = 11y7+7y6x+8y5x2-3y4x3-10y3x4-10y2x5-x7-33y6-29y5x-13y4x2+26y3x3; f = f+30y2x4+10yx5+3x6+33y5+37y4x-8y3x2-33y2x3-20yx4-3x5-11y4-15y3x; f = f+13y2x2+10yx3+x4; // 3 OMPs of mult 3, 1 OMP of mult 4 integralBasis(f, 2); f =1/11*f; integralBasis(f, 2, "global"); // time 2 integralBasis(f, 2); // local by default, time 0 kill RR; // ------------------------------------------------------- // Example 4 // ------------------------------------------------------- ring RR = 0, (x,y), dp; poly f = y^20+x*y^13+x^4*y^5+x^5+2*x^4+x^3; integralBasis(f, 2, "global"); // time 0 integralBasis(f, 2); // local by default, time 0 kill RR; // ------------------------------------------------------- // Example 5 // ------------------------------------------------------- ring SS = 0, (u,v,z), dp; poly f = u^6+3*u^4*v^2+3*u^2*v^4+v^6-4*u^4*z^2-34*u^3*v*z^2-7*u^2*v^2*z^2; f = f+12*u*v^3*z^2+6*v^4*z^2+36*u^2*z^4+36*u*v*z^4+9*v^2*z^4; f = subst(f,z,1); ring RR = 0, (x,y), dp; poly f = fetch(SS,f); integralBasis(f, 2); integralBasis(f, 2, "global"); // time 1 integralBasis(f, 2); // local by default, time 0 kill RR, SS; // ------------------------------------------------------- // Example 6 // ------------------------------------------------------- ring SS = 0, (u,v,z), dp; poly f = -24135/322*u^6-532037/6440*u^5*v+139459/560*u^4*v^2; f = f-1464887/12880*u^3*v^3+72187/25760*u^2*v^4+9/8*u*v^5+1/8*v^6; f = f-403511/3220*u^5*z-40817/920*u^4*v*z+10059/80*u^3*v^2*z; f = f-35445/1288*u^2*v^3*z+19/4*u*v^4*z+3/4*v^5*z-20743/805*u^4*z^2; f = f+126379/3220*u^3*v*z^2-423417/6440*u^2*v^2*z^2+11/2*u*v^3*z^2; f = f+3/2*v^4*z^2+3443/140*u^3*z^3+u^2*v*z^3+u*v^2*z^3+v^3*z^3; f = 8/27*subst(f,z,u+v+z); f = subst(f,z,1); ring RR = 0, (x,y), dp; poly f = fetch(SS,f); integralBasis(f, 2, "global"); // time 3 integralBasis(f, 2); // local by default, time 0 kill RR, SS; // ------------------------------------------------------- // Example 8 // ------------------------------------------------------- ring SS = 0, (u,v,z), dp; poly f = 25*u^8+184*u^7*v+518*u^6*v^2+720*u^5*v^3+576*u^4*v^4+282*u^3*v^5; f = f+84*u^2*v^6+14*u*v^7+v^8+244*u^7*z+1326*u^6*v*z+2646*u^5*v^2*z; f = f+2706*u^4*v^3*z+1590*u^3*v^4*z+546*u^2*v^5*z+102*u*v^6*z+8*v^7*z; f = f+854*u^6*z^2+3252*u^5*v*z^2+4770*u^4*v^2*z^2+3582*u^3*v^3*z^2; f = f+1476*u^2*v^4*z^2+318*u*v^5*z^2+28*v^6*z^2+1338*u^5*z^3+3740*u^4*v*z^3; f = f+4030*u^3*v^2*z^3+2124*u^2*v^3*z^3+550*u*v^4*z^3+56*v^5*z^3+1101*u^4*z^4; f = f+2264*u^3*v*z^4+1716*u^2*v^2*z^4+570*u*v^3*z^4+70*v^4*z^4+508*u^3*z^5; f = f+738*u^2*v*z^5+354*u*v^2*z^5+56*v^3*z^5+132*u^2*z^6+122*u*v*z^6; f = f+28*v^2*z^6+18*u*z^7+8*v*z^7+z^8; f = subst(f,z,1); ring RR = 0, (x,y), dp; poly f = fetch(SS,f); integralBasis(f, 2, "global"); // time 95 integralBasis(f, 2); // local by default, time 13 kill RR, SS; // ------------------------------------------------------- // Example 9 // ------------------------------------------------------- ring SS = 0, (u,v,z), dp; poly f = u^10+6*u^9*v-30*u^7*v^3-15*u^6*v^4+u^5*v^5+u^4*v^6+6*u^3*v^7+u^2*v^8; f = f+7*u*v^9+v^10+5*u^9*z+24*u^8*v*z-30*u^7*v^2*z-120*u^6*v^3*z-43*u^5*v^4*z; f = f+5*u^4*v^5*z+20*u^3*v^6*z+10*u^2*v^7*z+29*u*v^8*z+5*v^9*z; f = f+10*u^8*z^2+36*u^7*v*z^2-105*u^6*v^2*z^2-179*u^5*v^3*z^2; f = f-38*u^4*v^4*z^2+25*u^3*v^5*z^2+25*u^2*v^6*z^2+46*u*v^7*z^2; f = f+10*v^8*z^2+10*u^7*z^3+24*u^6*v*z^3-135*u^5*v^2*z^3; f = f-117*u^4*v^3*z^3-u^3*v^4*z^3+25*u^2*v^5*z^3+34*u*v^6*z^3; f = f+10*v^7*z^3+5*u^6*z^4+6*u^5*v*z^4-75*u^4*v^2*z^4-27*u^3*v^3*z^4; f = f+10*u^2*v^4*z^4+11*u*v^5*z^4+5*v^6*z^4+u^5*z^5; f = f-15*u^3*v^2*z^5+u^2*v^3*z^5+u*v^4*z^5+v^5*z^5; f = subst(f,z,1); ring RR = 0, (x,y), dp; poly f = fetch(SS,f); // integralBasis(f, 2, "global"); // fail integralBasis(f, 2); // local by default, time 2 kill RR, SS; */ singular-4.0.3+ds/Singular/LIB/intprog.lib000066400000000000000000000444651266270727000203360ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version intprog.lib 4.0.0.0 Jun_2013 "; // $Id: 559512f5026260600db36a9d4b72968e9eca6e7c $ category="Commutative Algebra"; info=" LIBRARY: intprog.lib Integer Programming with Groebner Basis Methods AUTHOR: Christine Theis, email: ctheis@math.uni-sb.de PROCEDURES: solve_IP(..); procedures for solving Integer Programming problems "; /////////////////////////////////////////////////////////////////////////////// static proc solve_IP_1(intmat A, intvec bx, intvec c, string alg) { intvec v; // to be returned // check arguments as far as necessary // other inconsistencies are detected by the external program if(size(c)!=ncols(A)) { "ERROR: The number of matrix columns does not equal the size of the cost vector."; return(v); } // create first temporary file with which the external program is // called int process=system("pid"); string matrixfile="temp_MATRIX"+string(process); link MATRIX=":w "+matrixfile; open(MATRIX); write(MATRIX,"MATRIX","columns:",ncols(A),"cost vector:"); int i,j; for(j=1;j<=ncols(A);j++) { write(MATRIX,c[j]); } write(MATRIX,"rows:",nrows(A),"matrix:"); for(i=1;i<=nrows(A);i++) { for(j=1;j<=ncols(A);j++) { write(MATRIX,A[i,j]); } } // search for positive row space vector, if required by the // algorithm int found=0; if((alg=="blr") || (alg=="hs")) { for(i=1;i<=nrows(A);i++) { found=i; for(j=1;j<=ncols(A);j++) { if(A[i,j]<=0) { found=0; } } if(found>0) { break; } } if(found==0) { "ERROR: The chosen algorithm needs a positive vector in the row space of the matrix."; close(MATRIX); system("sh","rm -f "+matrixfile); return(v); } write(MATRIX,"positive row space vector:"); for(j=1;j<=ncols(A);j++) { write(MATRIX,A[found,j]); } } close(MATRIX); // create second temporary file for the external program string problemfile="temp_PROBLEM"+string(process); link PROBLEM=":w "+problemfile; open(PROBLEM); write(PROBLEM,"PROBLEM","vector size:",size(bx),"number of instances:",1,"right hand or initial solution vectors:"); for(i=1;i<=size(bx);i++) { write(PROBLEM,bx[i]); } close(PROBLEM); // call external program int dummy=system("sh","solve_IP -alg "+alg+" "+matrixfile+" "+problemfile); // read solution from created file link SOLUTION=":r "+matrixfile+".sol."+alg; string solution=read(SOLUTION); int pos; string s; if(alg=="ct" || alg=="pct") { pos=find(solution,"NO"); if(pos!=0) { "not solvable"; } else { pos=find(solution,"YES"); pos=find(solution,":",pos); pos++; for(j=1;j<=ncols(A);j++) { while(solution[pos]==" " || solution[pos]==newline) { pos++; } s=""; while(solution[pos]!=" " && solution[pos]!=newline) { s=s+solution[pos]; pos++; } execute("v[j]="+s+";"); } } } else { pos=find(solution,"optimal"); pos=find(solution,":",pos); pos++; for(j=1;j<=ncols(A);j++) { while(solution[pos]==" " || solution[pos]==newline) { pos++; } s=""; while(solution[pos]!=" " && solution[pos]!=newline) { s=s+solution[pos]; pos++; } execute("v[j]="+s+";"); } } // delete all created files dummy=system("sh","rm -f "+matrixfile); dummy=system("sh","rm -f "+matrixfile+".GB."+alg); dummy=system("sh","rm -f "+problemfile); dummy=system("sh","rm -f "+matrixfile+".sol."+alg); return(v); } /////////////////////////////////////////////////////////////////////////////// static proc solve_IP_2(intmat A, list bx, intvec c, string alg) { list l;; // to be returned // check arguments as far as necessary // other inconsistencies are detected by the external program if(size(c)!=ncols(A)) { "ERROR: The number of matrix columns does not equal the size of the cost vector."; return(l); } int k; for(k=2;k<=size(bx);k++) { if(size(bx[k])!=size(bx[1])) { "ERROR: The size of all right-hand vectors must be equal."; return(l); } } // create first temporary file with which the external program is // called int process=system("pid"); string matrixfile="temp_MATRIX"+string(process); link MATRIX=":w "+matrixfile; open(MATRIX); write(MATRIX,"MATRIX","columns:",ncols(A),"cost vector:"); int i,j; for(j=1;j<=ncols(A);j++) { write(MATRIX,c[j]); } write(MATRIX,"rows:",nrows(A),"matrix:"); for(i=1;i<=nrows(A);i++) { for(j=1;j<=ncols(A);j++) { write(MATRIX,A[i,j]); } } // search for positive row space vector, if required by the // algorithm int found=0; if((alg=="blr") || (alg=="hs")) { for(i=1;i<=nrows(A);i++) { found=i; for(j=1;j<=ncols(A);j++) { if(A[i,j]<=0) { found=0; } } if(found>0) { break; } } if(found==0) { "ERROR: The chosen algorithm needs a positive vector in the row space of the matrix."; close(MATRIX); system("sh","rm -f "+matrixfile); return(l); } write(MATRIX,"positive row space vector:"); for(j=1;j<=ncols(A);j++) { write(MATRIX,A[found,j]); } } close(MATRIX); // create second temporary file for the external program string problemfile="temp_PROBLEM"+string(process); link PROBLEM=":w "+problemfile; open(PROBLEM); write(PROBLEM,"PROBLEM","vector size:",size(bx[1]),"number of instances:",size(bx),"right hand or initial solution vectors:"); for(k=1;k<=size(bx);k++) { for(i=1;i<=size(bx[1]);i++) { write(PROBLEM,bx[k][i]); } } close(PROBLEM); // call external program int dummy=system("sh","solve_IP -alg "+alg+" "+matrixfile+" "+problemfile); // read solution from created file link SOLUTION=":r "+matrixfile+".sol."+alg; string solution=read(SOLUTION); intvec v; int pos,pos1,pos2; string s; if(alg=="ct" || alg=="pct") { pos=1; for(k=1;k<=size(bx);k++) { pos1=find(solution,"NO",pos); pos2=find(solution,"YES",pos); if(pos1!=0 && (pos1=2; j-- ) { if( rel[j] == w ) //the whole column is zero { j--; continue; } for( i=1; i 1) ) if ( ( (d-d_lead) != 0) || (LExp > 1) || ( (LExp==0) && ((d_lead>1) || (d_lead<-1)) ) ) { return(theta); } if( v[j] == 1) //relation of type var(j)*var(i) = var(i)*var(j) -lambda*var(j) { if (leadcoef(d) < 0) { M[i,2] = j; } else { M[i,3] = j; } } if( v[i]==1 ) //relation of type var(j)*var(i) = var(i)*var(j) -lambda*var(i) { if (leadcoef(d) > 0) { M[j,2] = i; } else { M[j,3] = i; } } } } // from here on, the map is computed for(i=1;i<=NVars;i++) { I=I+var(i); } for(i=1;i<=NVars;i++) { if( M[i,1..3]==(0,0,0) ) { i++; continue; } if( M[i,1]!=0 ) { if( (M[i,2]!=0) && (M[i,3]!=0) ) { I[M[i,1]] = -var(M[i,1]); I[M[i,2]] = var(M[i,3]); I[M[i,3]] = var(M[i,2]); } if( (M[i,2]==0) && (M[i,3]==0) ) { I[M[i,1]] = -var(M[i,1]); } if( ( (M[i,2]!=0) && (M[i,3]==0) )|| ( (M[i,2]!=0) && (M[i,3]==0) ) ) { I[i] = -var(i); } } else { if( (M[i,2]!=0) && (M[i,3]!=0) ) { I[i] = -var(i); I[M[i,2]] = var(M[i,3]); I[M[i,3]] = var(M[i,2]); } else { I[i] = -var(i); } } } return(I); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z,D(1..3)),dp; matrix D[6][6]; D[1,4]=1; D[2,5]=1; D[3,6]=1; def r = nc_algebra(1,D); setring r; ncdetection(); kill r, R; //---------------------------------------- ring R=0,(x,S),dp; def r = nc_algebra(1,-S); setring r; ncdetection(); kill r, R; //---------------------------------------- ring R=0,(x,D(1),S),dp; matrix D[3][3]; D[1,2]=1; D[1,3]=-S; def r = nc_algebra(1,D); setring r; ncdetection(); } static proc In_Poly(poly mm, list l, int NVars) // applies the involution to the polynomial mm // entries of a list l are images of variables under invo // more general than invo_poly; used in many rings setting { int i,j; intvec v; poly pp, zz; poly nn = 0; i = 1; while(mm[i]!=0) { v = leadexp(mm[i]); zz = 1; for( j=NVars; j>=1; j--) { if (v[j]!=0) { pp = l[j]; zz = zz*(pp^v[j]); } } nn = nn + (leadcoef(mm[i])*zz); i++; } return(nn); } static proc Hom_Poly(poly mm, list l, int NVars) // applies the endomorphism to the polynomial mm // entries of a list l are images of variables under endo // should not be replaced by map-based stuff! used in // many rings setting { int i,j; intvec v; poly pp, zz; poly nn = 0; i = 1; while(mm[i]!=0) { v = leadexp(mm[i]); zz = 1; for( j=NVars; j>=1; j--) { if (v[j]!=0) { pp = l[j]; zz = (pp^v[j])*zz; } } nn = nn + (leadcoef(mm[i])*zz); i++; } return(nn); } static proc invo_poly(poly m, map theta) // applies the involution map theta to m, where m=polynomial { // compatibility: ideal l = ideal(theta); int i; list L; for (i=1; i<=size(l); i++) { L[i] = l[i]; } int nv = nvars(basering); return (In_Poly(m,L,nv)); // if (m==0) { return(m); } // int i,j; // intvec v; // poly p,z; // poly n = 0; // i = 1; // while(m[i]!=0) // { // v = leadexp(m[i]); // z =1; // for(j=nvars(basering); j>=1; j--) // { // if (v[j]!=0) // { // p = var(j); // p = theta(p); // z = z*(p^v[j]); // } // } // n = n + (leadcoef(m[i])*z); // i++; // } // return(n); } /////////////////////////////////////////////////////////////////////////////////// proc involution(def m, map theta) "USAGE: involution(m, theta); m is a poly/vector/ideal/matrix/module, theta is a map RETURN: object of the same type as m PURPOSE: applies the involution, presented by theta to the object m THEORY: for an involution theta and two polynomials a,b from the algebra, @* theta(ab) = theta(b) theta(a); theta is linear with respect to the ground field NOTE: This is generalized ''theta(m)'' for data types unsupported by ''map''. EXAMPLE: example involution; shows an example "{ // applies the involution map theta to m, // where m= vector, polynomial, module, matrix, ideal int i,j; intvec v; poly p,z; if (typeof(m)=="poly") { return (invo_poly(m,theta)); } if ( typeof(m)=="ideal" ) { ideal n; for (i=1; i<=size(m); i++) { n[i] = invo_poly(m[i], theta); } return(n); } if (typeof(m)=="vector") { for(i=1; i<=size(m); i++) { m[i] = invo_poly(m[i], theta); } return (m); } if ( (typeof(m)=="matrix") || (typeof(m)=="module")) { matrix n = matrix(m); int @R=nrows(n); int @C=ncols(n); for(i=1; i<=@R; i++) { for(j=1; j<=@C; j++) { if (m[i,j]!=0) { n[i,j] = invo_poly( m[i,j], theta); } } } if (typeof(m)=="module") { return (module(n)); } else // matrix { return(n); } } // if m is not of the supported type: "Error: unsupported argument type!"; return(); } example { "EXAMPLE:";echo = 2; ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring r; // Weyl-Algebra map F = r,x,-d; F(F); // should be maxideal(1) for an involution poly f = x*d^2+d; poly If = involution(f,F); f-If; poly g = x^2*d+2*x*d+3*x+7*d; poly tg = -d*x^2-2*d*x+3*x-7*d; poly Ig = involution(g,F); tg-Ig; ideal I = f,g; ideal II = involution(I,F); II; matrix(I) - involution(II,F); module M = [f,g,0],[g,0,x^2*d]; module IM = involution(M,F); print(IM); print(matrix(M) - involution(IM,F)); } /////////////////////////////////////////////////////////////////////////////////// static proc new_var() //generates a string of new variables { int NVars=nvars(basering); int i,j; // string s="@_1_1"; string s="a11"; for(i=1; i<=NVars; i++) { for(j=1; j<=NVars; j++) { if(i*j!=1) { s = s+ ","+NVAR(i,j); } } } return(s); } static proc NVAR(int i, int j) { // return("@_"+string(i)+"_"+string(j)); return("a"+string(i)+string(j)); } /////////////////////////////////////////////////////////////////////////////////// static proc new_var_special() //generates a string of new variables { int NVars=nvars(basering); int i; // string s="@_1_1"; string s="a11"; for(i=2; i<=NVars; i++) { s = s+ ","+NVAR(i,i); } return(s); } /////////////////////////////////////////////////////////////////////////////////// static proc RelMatr() // returns the matrix of relations // only Lie-type relations x_j x_i= x_i x_j + .. are taken into account { int i,j; int NVars = nvars(basering); matrix Rel[NVars][NVars]; for(i=1; i=2) { J = J, ideal( @@D*@@D-matrix( freemodule(NVars) ) ); // add the condition that homomorphism to square is just identity } if (n==0) { J = J, det(@@D)-@p; // det of non-unipotent matrix is nonzero } J = simplify(J,2); // without extra zeros list mL = minAssGTZ(J); // components not in GB int sL = size(mL); intvec saveopt=option(get); option(redSB); // important for reduced GBs option(redTail); matrix IM = @@D; // map list L = list(); // the answer list TL; ideal tmp = 0; for (i=1; i<=sL; i++)// compute GBs of components { TL = list(); TL[1] = std(mL[i]); tmp = NF( ideal(IM), TL[1] ); TL[2] = matrix(tmp,NVars, NVars); L[i] = TL; } export(L); ideal idJ = J; // debug-comfortable exports matrix matD = @@D; export(idJ); export(matD); option(set,saveopt); return(@@KK); } example { "EXAMPLE:"; echo = 2; def a = makeWeyl(1); setring a; // this algebra is a first Weyl algebra a; def X = findAuto(2); // in contrast to findInvo look for automorphisms setring X; // ring with new variables - unknown coefficients X; size(L); // we have (size(L)) families in the answer // look at matrices, defining linear automorphisms: print(L[1][2]); // a first one: we see it is the identity print(L[2][2]); // and a second possible matrix; it is diagonal // L; // we can take a look on the whole list, too idJ; kill X; kill a; //----------- find all the linear automorphisms -------------------- //----------- use the call findAuto(0) -------------------- ring R = 0,(x,s),dp; def r = nc_algebra(1,s); setring r; // the shift algebra s*x; // the only relation in the algebra is: def Y = findAuto(0); setring Y; size(L); // here, we have 1 parametrized family print(L[1][2]); // here, @p is a nonzero parameter det(L[1][2]-@p); // check whether determinante is zero } proc isAntiEndo(def F) "USAGE: isAntiEndo(F); F is a map from current ring to itself RETURN: integer, 1 if F determines an antiendomorphism of current ring and 0 otherwise ASSUME: F is a map from current ring to itself SEE ALSO: isInvolution, involution, findInvo EXAMPLE: example isAntiEndo; shows examples " { // assumes: // (1) F is from br to br // I don't see how to check it; in case of error it will happen in the body // (2) do not assume: F is linear, F is bijective int n = nvars(basering); int i,j; poly pi,pj,q; int answer=1; ideal @f = ideal(F); list L=@f[1..ncols(@f)]; for (i=1; i=1; j--) { // p = var(j); p = F(p); p = F(p) - var(j); //p = G(p) - p; p = In_Poly(var(j),L,nv); p = In_Poly(p,L,nv) -var(j) ; if (p!=0) { return(0); } } return(1); } example {"EXAMPLE:";echo = 2; def A = makeUsl(2); setring A; map I = A,-e,-f,-h; //correct antiauto involution isInvolution(I); map J = A,3*e,1/3*f,-h; // antiauto but not involution isInvolution(J); map K = A,f,e,-h; // not antiauto isInvolution(K); } singular-4.0.3+ds/Singular/LIB/jacobson.lib000066400000000000000000000734571266270727000204550ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version jacobson.lib 4.0.0.0 Jun_2013 "; // $Id: 89c042d436d3e016d3822e0d61e1c6850ea236de $ category="System and Control Theory"; info=" LIBRARY: jacobson.lib Algorithms for Smith and Jacobson Normal Form AUTHOR: Kristina Schindelar, Kristina.Schindelar@math.rwth-aachen.de, @* Viktor Levandovskyy, levandov@math.rwth-aachen.de OVERVIEW: We work over a ring R, that is an Euclidean principal ideal domain. If R is commutative, we suppose R to be a polynomial ring in one variable. If R is non-commutative, we suppose R to have two variables, say x and d. We treat then the basering as the Ore localization of R with respect to the mult. closed set S = K[x] without 0. Thus, we treat basering as principal ideal ring with d a polynomial variable and x an invertible one. Note, that in computations no division by x will actually happen. Given a rectangular matrix M over R, one can compute unimodular (that is invertible) square matrices U and V, such that U*M*V=D is a diagonal matrix. Depending on the ring, the diagonal entries of D have certain properties. We call a square matrix D as before 'a weak Jacobson normal form of M'. It is known, that over the first rational Weyl algebra K(x), D can be further transformed into a diagonal matrix (1,1,...,1,f,0,..,0), where f is in K(x). We call such a form of D the strong Jacobson normal form. The existence of strong form in not guaranteed if one works with algebra, which is not rational Weyl algebra. REFERENCES: @* [1] N. Jacobson, 'The theory of rings', AMS, 1943. @* [2] Manuel Avelino Insua Hermo, 'Varias perspectives sobre las bases de Groebner : @* Forma normal de Smith, Algorithme de Berlekamp y algebras de Leibniz'. @* PhD thesis, Universidad de Santiago de Compostela, 2005. @* [3] V. Levandovskyy, K. Schindelar 'Computing Jacobson normal form using Groebner bases', @* to appear in Journal of Symbolic Computation, 2010. PROCEDURES: smith(M[,eng1,eng2]); compute the Smith Normal Form of M over commutative ring jacobson(M[,eng]); compute a weak Jacobson Normal Form of M over non-commutative ring divideUnits(L); create ones out of units in the output of smith or jacobson SEE ALSO: control_lib KEYWORDS: Jacobson form; Jacobson normal form; Smith form; Smith normal form; matrix diagonalization "; LIB "poly.lib"; LIB "involut.lib"; // involution LIB "dmodapp.lib"; // engine LIB "qhmoduli.lib"; // Min LIB "latex.lib"; // tex output for printlevel=4 proc tstjacobson() { /* tests all procs for consistency */ example divideUnits; example smith; example jacobson; } proc divideUnits(list L) "USAGE: divideUnits(L); list L RETURN: matrix or list of matrices ASSUME: L is an output of @code{smith} or a @code{jacobson} procedures, that is @* either L contains one rectangular matrix with elements only on the main diagonal @* or L consists of three matrices, where L[1] and L[3] are square invertible matrices @* while L[2] is a rectangular matrix with elements only on the main diagonal PURPOSE: divide out units from the diagonal and reflect this in transformation matrices EXAMPLE: example divideUnits; shows examples " { // check assumptions int s = size(L); if ( (s!=1) && (s!=3) ) { ERROR("The list has neither 1 nor 3 elements"); } // check sizes of matrices if (s==1) { list LL; LL[1] = L[1]; LL[2] = L[1]; L = LL; } // divide units out matrix M = L[2]; int ncM = ncols(M); int nrM = nrows(M); // matrix TM[nrM][nrM]; // m times m matrix matrix TM = matrix(freemodule(nrM)); int i; int nsize = Min(intvec(nrM,ncM)); poly p; number n; intvec lexp; for(i=1; i<=nsize; i++) { p = M[i,i]; lexp = leadexp(p); // TM[i,i] = 1; // check: is p a unit? if (p!=0) { if ( lexp == 0) { // hence p = n*1 n = leadcoef(p); TM[i,i] = 1/n; } } } int ppl = printlevel-voice+2; dbprint(ppl,"divideUnits: extra transformation matrix is: "); dbprint(ppl, TM); L[2] = TM*L[2]; if (s==3) { L[1] = TM*L[1]; return(L); } else { return(L[2]); } } example { "EXAMPLE:"; echo = 2; ring R=(0,m,M,L1,L2,m1,m2,g), D, lp; // two pendula example matrix P[3][4]=m1*L1*D^2,m2*L2*D^2,(M+m1+m2)*D^2,-1, m1*L1^2*D^2-m1*L1*g,0,m1*L1*D^2,0,0, m2*L2^2*D^2-m2*L2*g,m2*L2*D^2,0; list s=smith(P,1); // returns a list with 3 entries print(s[2]); // a diagonal form, close to the Smith form print(s[1]); // U, left transformation matrix list t = divideUnits(s); print(t[2]); // the Smith form of the matrix P print(t[1]); // U', modified left transformation matrix } proc smith(matrix MA, list #) "USAGE: smith(M[, eng1, eng2]); M matrix, eng1 and eng2 are optional integers RETURN: matrix or list of matrices, depending on arguments ASSUME: Basering is a commutative polynomial ring in one variable PURPOSE: compute the Smith Normal Form of M with (optionally) transformation matrices THEORY: Groebner bases are used for the Smith form like in [2] and [3]. NOTE: By default, just the Smith normal form of M is returned. @* If the optional integer @code{eng1} is non-zero, the list {U,D,V} is returned @* where U*M*V = D and the diagonal field entries of D are not normalized. @* The normalization of the latter can be done with the 'divideUnits' procedure. @* U and V above are square unimodular (invertible) matrices. @* Note, that the procedure works for a rectangular matrix M. @* @* The optional integer @code{eng2} determines the Groebner basis engine: @* 0 (default) ensures the use of 'slimgb' , otherwise 'std' is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example smith; shows examples SEE ALSO: divideUnits, jacobson " { def R = basering; // check assume: R must be a polynomial ring in 1 variable setring R; if (nvars(R) >1 ) { ERROR("Basering must have exactly one variable"); } int eng = 0; int BASIS; if ( size(#)>0 ) { eng=1; if (typeof(#[1])=="int") { eng=int(#[1]); // zero can also happen } } if (size(#)==2) { BASIS=#[2]; } else{BASIS=0;} int ROW=ncols(MA); int COL=nrows(MA); //generate a module consisting of the columns of MA module m=MA[1]; int i; for(i=2;i<=ROW;i++) { m=m,MA[i]; } //if MA eqauls the zero matrix give back MA if ( (size(module(m))==0) and (size(transpose(module(m)))==0) ) { module L=freemodule(COL); matrix LM=L; L=freemodule(ROW); matrix RM=L; list RUECK=RM; RUECK=insert(RUECK,MA); RUECK=insert(RUECK,LM); return(RUECK); } if(eng==1) { list rueckLI=diagonal_with_trafo(R,MA,BASIS); list rueckLII=divisibility(rueckLI[2]); matrix CON=divideByContent(rueckLII[2]); list rueckL=CON*rueckLII[1]*rueckLI[1], CON*rueckLII[2], rueckLI[3]*rueckLII[3]; return(rueckL); } else { matrix rueckm=diagonal_without_trafo(R,MA,BASIS); list rueckL=divisibility(rueckm); matrix CON=divideByContent(rueckm); rueckm=CON*rueckL[2]; return(rueckm); } } example { "EXAMPLE:"; echo = 2; ring r = 0,x,Dp; matrix m[3][2]=x, x^4+x^2+21, x^4+x^2+x, x^3+x, 4*x^2+x, x; list s=smith(m,1); print(s[2]); // non-normalized Smith form of m print(s[1]*m*s[3] - s[2]); // check U*M*V = D list t = divideUnits(s); print(t[2]); // the Smith form of m } static proc diagonal_with_trafo(def R, matrix MA, int B) { int ppl = printlevel-voice+2; int BASIS=B; int ROW=ncols(MA); int COL=nrows(MA); module m=MA[1]; int i,j,k; for(i=2;i<=ROW;i++) { m=m,MA[i]; } //add zero rows or columns //add zero rows or columns int adrow=0; for(i=1;i<=COL;i++) { k=0; for(j=1;j<=ROW;j++) { if(MA[i,j]!=0){k=1;} } if(k==0){adrow++;} } m=transpose(m); for(i=1;i<=adrow;i++){m=m,0;} m=transpose(m); list RINGLIST=ringlist(R); list o="C",0; list oo="lp",1; list ORD=o,oo; RINGLIST[3]=ORD; def r=ring(RINGLIST); setring r; //fix the required ordering map MAP=R,var(1); module m=MAP(m); int flag=1; ///////////////counts if the underlying ring is r (flag mod 2 == 1) or ro (flag mod 2 == 0) module TrafoL=freemodule(COL); module TrafoR=freemodule(ROW); module EXL=freemodule(COL); //because we start with transpose(m) module EXR=freemodule(ROW); option(redSB); option(redTail); module STD_EX; module Trafo; int s,st,p,ff; module LT,TSTD; module STD=transpose(m); int finish=0; int fehlpos; list pos; matrix END; matrix ENDSTD; matrix STDFIN; STDFIN=STD; list COMPARE=STDFIN; while(finish==0) { dbprint(ppl,"Going into the while cycle"); if(flag mod 2==1) { STD_EX=EXL,transpose(STD); } else { STD_EX=EXR,transpose(STD); } dbprint(ppl,"Computing Groebner basis: start"); dbprint(ppl-1,STD); STD=engine(STD,BASIS); dbprint(ppl,"Computing Groebner basis: finished"); dbprint(ppl-1,STD); if(flag mod 2==1){s=ROW; st=COL;}else{s=COL; st=ROW;} dbprint(ppl,"Computing Groebner basis for transformation matrix: start"); dbprint(ppl-1,STD_EX); STD_EX=transpose(STD_EX); STD_EX=engine(STD_EX,BASIS); dbprint(ppl,"Computing Groebner basis for transformation matrix: finished"); dbprint(ppl-1,STD_EX); //////// split STD_EX in STD and the transformation matrix STD_EX=transpose(STD_EX); STD=STD_EX[st+1]; LT=STD_EX[1]; ENDSTD=STD_EX; for(i=2; i<=ncols(ENDSTD); i++) { if (i<=st) { LT=LT,STD_EX[i]; } if (i>st+1) { STD=STD,STD_EX[i]; } } STD=transpose(STD); LT=transpose(LT); ////////////////////// compute the transformation matrices if (flag mod 2 ==1) { TrafoL=transpose(LT)*TrafoL; } else { TrafoR=TrafoR*LT; } STDFIN=STD; /////////////////////////////////// check if the D-th row is finished /////////////////////////////////// COMPARE=insert(COMPARE,STDFIN); if(size(COMPARE)>=3) { if(STD==COMPARE[3]){finish=1;} } ////////////////////////////////// change to the opposite module TSTD=transpose(STD); STD=TSTD; flag++; dbprint(ppl,"Finished one while cycle"); } if (flag mod 2!=0) { STD=transpose(STD); } //zero colums to the end matrix STDMM=STD; pos=list(); fehlpos=0; while( size(STD)+fehlpos-ncols(STDMM) < 0) { for(i=1; i<=ncols(STDMM); i++) { ff=0; for(j=1; j<=nrows(STDMM); j++) { if (STD[j,i]==0) { ff++; } } if(ff==nrows(STDMM)) { pos=insert(pos,i); fehlpos++; } } } int fehlposc=fehlpos; module SORT; for(i=1; i<=fehlpos; i++) { SORT=gen(2); for (j=3;j<=ROW;j++) { SORT=SORT,gen(j); } SORT=SORT,gen(1); STD=STD*SORT; TrafoR=TrafoR*SORT; } //zero rows to the end STDMM=transpose(STD); pos=list(); fehlpos=0; while( size(transpose(STD))+fehlpos-ncols(STDMM) < 0) { for(i=1; i<=ncols(STDMM); i++) { ff=0; for(j=1; j<=nrows(STDMM); j++) { if(transpose(STD)[j,i]==0){ ff++;}} if(ff==nrows(STDMM)) { pos=insert(pos,i); fehlpos++; } } } int fehlposr=fehlpos; for(i=1; i<=fehlpos; i++) { SORT=gen(2); for(j=3;j<=COL;j++){SORT=SORT,gen(j);} SORT=SORT,gen(1); SORT=transpose(SORT); STD=SORT*STD; TrafoL=SORT*TrafoL; } setring R; map MAPinv=r,var(1); module STD=MAPinv(STD); module TrafoL=MAPinv(TrafoL); matrix TrafoLM=TrafoL; module TrafoR=MAPinv(TrafoR); matrix TrafoRM=TrafoR; matrix STDM=STD; //Test if(TrafoLM*m*TrafoRM!=STDM){ return(0); } list RUECK=TrafoRM; RUECK=insert(RUECK,STDM); RUECK=insert(RUECK,TrafoLM); return(RUECK); } static proc divisibility(matrix M) { matrix STDM=M; int i,j; int ROW=nrows(M); int COL=ncols(M); module TrafoR=freemodule(COL); module TrafoL=freemodule(ROW); module SORT; matrix TrafoRM=TrafoR; matrix TrafoLM=TrafoL; list posdeg0; int posdeg=0; int act; int Sort=ROW; if(size(std(STDM))!=0) { while( size(transpose(STDM)[Sort])==0 ){Sort--;}} for(i=1;i<=Sort ;i++) { if(leadexp(STDM[i,i])==0){posdeg0=insert(posdeg0,i);posdeg++;} } //entries of degree 0 at the beginning for(i=1; i<=posdeg; i++) { act=posdeg0[i]; SORT=gen(act); for(j=1; j<=COL; j++){if(j!=act){SORT=SORT,gen(j);}} STDM=STDM*SORT; TrafoRM=TrafoRM*SORT; SORT=gen(act); for(j=1; j<=ROW; j++){if(j!=act){SORT=SORT,gen(j);}} STDM=transpose(SORT)*STDM; TrafoLM=transpose(SORT)*TrafoLM; } poly G; module UNITL=freemodule(ROW); matrix GCDL=UNITL; module UNITR=freemodule(COL); matrix GCDR=UNITR; for(i=posdeg+1; i<=Sort; i++) { for(j=i+1; j<=Sort; j++) { GCDL=UNITL; GCDR=UNITR; G=gcd(STDM[i,i],STDM[j,j]); ideal Z=STDM[i,i],STDM[j,j]; matrix T=lift(Z,G); GCDL[i,i]=T[1,1]; GCDL[i,j]=T[2,1]; GCDL[j,i]=-STDM[j,j]/G; GCDL[j,j]=STDM[i,i]/G; GCDR[i,j]=T[2,1]*STDM[j,j]/G; GCDR[j,j]=T[2,1]*STDM[j,j]/G-1; GCDR[j,i]=1; STDM=GCDL*STDM*GCDR; TrafoLM=GCDL*TrafoLM; TrafoRM=TrafoRM*GCDR; } } list RUECK=TrafoRM; RUECK=insert(RUECK,STDM); RUECK=insert(RUECK,TrafoLM); return(RUECK); } static proc diagonal_without_trafo( R, matrix MA, int B) { int ppl = printlevel-voice+2; int BASIS=B; int ROW=ncols(MA); int COL=nrows(MA); module m=MA[1]; int i; for(i=2;i<=ROW;i++) {m=m,MA[i];} list RINGLIST=ringlist(R); list o="C",0; list oo="lp",1; list ORD=o,oo; RINGLIST[3]=ORD; def r=ring(RINGLIST); setring r; //RICHTIGE ORDNUNG MACHEN map MAP=R,var(1); module m=MAP(m); int flag=1; ///////////////counts if the underlying ring is r (flag mod 2 == 1) or ro (flag mod 2 == 0) int act, j, ff; option(redSB); option(redTail); module STD=transpose(m); module TSTD; int finish=0; matrix STDFIN; STDFIN=STD; list COMPARE=STDFIN; while(finish==0) { dbprint(ppl,"Going into the while cycle"); dbprint(ppl,"Computing Groebner basis: start"); dbprint(ppl-1,STD); STD=engine(STD,BASIS); dbprint(ppl,"Computing Groebner basis: finished"); dbprint(ppl-1,STD); STDFIN=STD; /////////////////////////////////// check if the D-th row is finished /////////////////////////////////// COMPARE=insert(COMPARE,STDFIN); if(size(COMPARE)>=3) { if(STD==COMPARE[3]){finish=1;} } ////////////////////////////////// change to the opposite module TSTD=transpose(STD); STD=TSTD; flag++; dbprint(ppl,"Finished one while cycle"); } matrix STDMM=STD; list pos=list(); int fehlpos=0; while( size(STD)+fehlpos-ncols(STDMM) < 0) { for(i=1; i<=ncols(STDMM); i++) { ff=0; for(j=1; j<=nrows(STDMM); j++) { if (STD[j,i]==0) { ff++; } } if(ff==nrows(STDMM)) { pos=insert(pos,i); fehlpos++; } } } int fehlposc=fehlpos; module SORT; for(i=1; i<=fehlpos; i++) { SORT=gen(2); for (j=3;j<=ROW;j++) { SORT=SORT,gen(j); } SORT=SORT,gen(1); STD=STD*SORT; } //zero rows to the end STDMM=transpose(STD); pos=list(); fehlpos=0; while( size(transpose(STD))+fehlpos-ncols(STDMM) < 0) { for(i=1; i<=ncols(STDMM); i++) { ff=0; for(j=1; j<=nrows(STDMM); j++) { if(transpose(STD)[j,i]==0){ ff++;}} if(ff==nrows(STDMM)) { pos=insert(pos,i); fehlpos++; } } } int fehlposr=fehlpos; for(i=1; i<=fehlpos; i++) { SORT=gen(2); for(j=3;j<=COL;j++){SORT=SORT,gen(j);} SORT=SORT,gen(1); SORT=transpose(SORT); STD=SORT*STD; } //add zero rows or columns int adrow=COL-size(transpose(STD)); int adcol=ROW-size(STD); for(i=1;i<=adcol;i++){STD=STD,0;} STD=transpose(STD); for(i=1;i<=adrow;i++){STD=STD,0;} STD=transpose(STD); setring R; map MAPinv=r,var(1); module STD=MAPinv(STD); matrix STDM=STD; return(STDM); } // VL : engine replaced by the one from dmodapp.lib // cases are changed // static proc engine(module I, int i) // { // module J; // if (i==0) // { // J = std(I); // } // if (i==1) // { // J = groebner(I); // } // if (i==2) // { // J = slimgb(I); // } // return(J); // } proc jacobson(matrix MA, list #) "USAGE: jacobson(M, eng); M matrix, eng an optional int RETURN: list ASSUME: Basering is a (non-commutative) ring in two variables. PURPOSE: compute a weak Jacobson normal form of M over the basering THEORY: Groebner bases and involutions are used, following [3] NOTE: A list L of matrices {U,D,V} is returned. That is L[1]*M*L[3]=L[2], @* where L[2] is a diagonal matrix and @* L[1], L[3] are square invertible polynomial (unimodular) matrices. @* Note, that M can be rectangular. @* The optional integer @code{eng2} determines the Groebner basis engine: @* 0 (default) ensures the use of 'slimgb' , otherwise 'std' is used. DISPLAY: If @code{printlevel}=1, progress debug messages will be printed, @* if @code{printlevel}>=2, all the debug messages will be printed. EXAMPLE: example jacobson; shows examples SEE ALSO: divideUnits, smith " { def R = basering; // check assume: R must be a polynomial ring in 2 variables setring R; if ( (nvars(R) !=2 ) ) { ERROR("Basering must have exactly two variables"); } // check if MA is zero matrix and return corr. U,V if ( (size(module(MA))==0) and (size(transpose(module(MA)))==0) ) { int nr = nrows(MA); int nc = ncols(MA); matrix U = matrix(freemodule(nr)); matrix V = matrix(freemodule(nc)); list L; L[1]=U; L[2] = MA; L[3] = V; return(L); } int B=0; if ( size(#)>0 ) { B=1; if (typeof(#[1])=="int") { B=int(#[1]); // zero can also happen } } //change ring list RINGLIST=ringlist(R); list o="C",0; intvec v=0,1; list oo="a",v; v=1,1; list ooo="lp",v; list ORD=o,oo,ooo; RINGLIST[3]=ORD; def r=ring(RINGLIST); setring r; //fix the required ordering map MAP=R,var(1),var(2); matrix M=MAP(MA); module TrafoL, TrafoR; list TRIANGLE; TRIANGLE=triangle(M,B); TrafoL=TRIANGLE[1]; TrafoR=TRIANGLE[3]; module m=TRIANGLE[2]; //back to the ring setring R; map MAPR=r,var(1),var(2); module ma=MAPR(m); matrix MAA=ma; module TL=MAPR(TrafoL); module TR=MAPR(TrafoR); matrix TRR=TR; matrix CON=divideByContent(MAA); list RUECK=CON*TL, CON*MAA, TRR; return(RUECK); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,d),Dp; def R = nc_algebra(1,1); setring R; // the 1st Weyl algebra matrix m[2][2] = d,x,0,d; print(m); list J = jacobson(m); // returns a list with 3 entries print(J[2]); // a Jacobson Form D for m print(J[1]*m*J[3] - J[2]); // check that U*M*V = D /* now, let us do the same for the shift algebra */ ring r2 = 0,(x,s),Dp; def R2 = nc_algebra(1,s); setring R2; // the 1st shift algebra matrix m[2][2] = s,x,0,s; print(m); // matrix of the same for as above list J = jacobson(m); print(J[2]); // a Jacobson Form D, quite different from above print(J[1]*m*J[3] - J[2]); // check that U*M*V = D } //static proc triangle(matrix MA, int B) { int ppl = printlevel-voice+2; map inv=ncdetection(); int ROW=ncols(MA); int COL=nrows(MA); //generate a module consisting of the columns of MA module m=MA[1]; int i,j,s,st,p,k,ff,ex, nz, ii,nextp; for(i=2;i<=ROW;i++) { m=m,MA[i]; } int BASIS=B; //add zero rows or columns int adrow=0; for(i=1;i<=COL;i++) { k=0; for(j=1;j<=ROW;j++) { if(MA[i,j]!=0){k=1;} } if(k==0){adrow++;} } m=transpose(m); for(i=1;i<=adrow;i++){m=m,0;} m=transpose(m); int flag=1; ///////////////counts if the underlying ring is r (flag mod 2 == 1) or ro (flag mod 2 == 0) module TrafoL=freemodule(COL); module TrafoR=freemodule(ROW); module EXL=freemodule(COL); //because we start with transpose(m) module EXR=freemodule(ROW); option(redSB); option(redTail); module STD_EX,LT,TSTD, L, Trafo; module STD=transpose(m); int finish=0; list pos, COM, COM_EX; matrix END, ENDSTD, STDFIN; STDFIN=STD; list COMPARE=STDFIN; string @s; while(finish==0) { dbprint(ppl,"Going into the while cycle"); if(flag mod 2==1){STD_EX=EXL,transpose(STD); ex=2*COL;} else {STD_EX=EXR,transpose(STD); ex=2*ROW;} dbprint(ppl,"Computing Groebner basis: start"); dbprint(ppl-1,STD); STD=engine(STD,BASIS); dbprint(ppl,"Computing Groebner basis: finished"); dbprint(ppl-1,STD); if(flag mod 2==1){s=ROW; st=COL;}else{s=COL; st=ROW;} STD_EX=transpose(STD_EX); dbprint(ppl,"Computing Groebner basis for transformation matrix: start"); dbprint(ppl-1,STD_EX); STD_EX=engine(STD_EX,BASIS); dbprint(ppl,"Computing Groebner basis for transformation matrix: finished"); dbprint(ppl-1,STD_EX); COM=1; COM_EX=1; for(i=2; i<=size(STD); i++) { COM=COM[1..size(COM)],i; COM_EX=COM_EX[1..size(COM_EX)],i; } nz=size(STD_EX)-size(STD); //zero rows in the begining if(size(STD)!=size(STD_EX) ) { for(i=1; i<=size(STD_EX)-size(STD); i++) { COM_EX=0,COM_EX[1..size(COM_EX)]; } } for(i=nz+1; i<=size(STD_EX); i++ ) {if( leadcoef(STD[i-nz])!=leadcoef(STD_EX[i]) ) {STD[i-nz]=leadcoef(STD_EX[i])*STD[i-nz];} } //assign the zero rows in STD_EX for (j=2; j<=nz; j++) { p=0; i=1; while(STD_EX[j-1][i]==0){i++;} p=i-1; nextp=1; k=0; i=1; while(STD_EX[j][i]==0 and i<=p) { k++; i++;} if (k==p){ COM_EX[j]=-1; } } //assign the zero rows in STD for (j=2; j<=size(STD); j++) { i=size(transpose(STD)); while(STD[j-1][i]==0){i--;} p=i; i=size(transpose(STD[j])); while(STD[j][i]==0){i--;} if (i==p){ COM[j]=-1; } } for(j=1; j<=size(COM); j++) { if(COM[j]<0){COM=delete(COM,j);} } for(i=1; i<=size(COM_EX); i++) {ff=0; if(COM_EX[i]==0){ff=1;} else { for(j=1; j<=size(COM); j++) { if(COM_EX[i]==COM[j]){ff=1;} } } if(ff==0){COM_EX[i]=-1;} } L=STD_EX[1]; for(i=2; i<=size(COM_EX); i++) { if(COM_EX[i]!=-1){L=L,STD_EX[i];} } //////// split STD_EX in STD and the transformation matrix L=transpose(L); STD=L[st+1]; LT=L[1]; for(i=2; i<=s+st; i++) { if (i<=st) { LT=LT,L[i]; } if (i>st+1) { STD=STD,L[i]; } } STD=transpose(STD); STDFIN=matrix(STD); COMPARE=insert(COMPARE,STDFIN); LT=transpose(LT); ////////////////////// compute the transformation matrices if (flag mod 2 ==1) { TrafoL=transpose(LT)*TrafoL; dbprint(ppl-1,"Left transformation matrix:"); dbprint(ppl-1,TrafoL); @s = texobj("",matrix(TrafoL)); dbprint(ppl-2,"Left transformation matrix in TeX format:"); dbprint(ppl-2,@s); } else { TrafoR=TrafoR*involution(LT,inv); dbprint(ppl-1,"Right transformation matrix:"); dbprint(ppl-1,matrix(TrafoR)); @s = texobj("",TrafoR); dbprint(ppl-2,"Right transformation matrix in TeX format:"); dbprint(ppl-2,@s); } ///////////////////////// check whether the alg terminated ///////////////// if(size(COMPARE)>=3) { if(STD==COMPARE[3]){finish=1;} } ////////////////////////////////// change to the opposite module dbprint(ppl-1,"Matrix for the next step:"); dbprint(ppl-1,STD); dbprint(ppl-2,"Matrix for the next step in TeX format:"); @s = texobj("",matrix(STD)); dbprint(ppl-2,@s); TSTD=transpose(STD); STD=involution(TSTD,inv); flag++; dbprint(ppl,"Finished one while cycle"); } if (flag mod 2 ==0){ STD = involution(STD,inv);} else { STD = transpose(STD); } list REVERSE=TrafoL,STD,TrafoR; return(REVERSE); } static proc divideByContent(matrix M) { //find first entrie not equal to zero int i,k; k=1; vector CON; for(i=1;i<=ncols(M);i++) { if(leadcoef(M[i])!=0){CON=CON+leadcoef(M[i])*gen(k); k++;} } poly con=content(CON); matrix TL=1/con*freemodule(nrows(M)); return(TL); } /////interesting examples for smith//////////////// /* //static proc Ex_One_wheeled_bicycle() { ring RA=(0,m), D, lp; matrix bicycle[2][3]=(1+m)*D^2, D^2, 1, D^2, D^2-1, 0; list s=smith(bicycle, 1,0); print(s[2]); print(s[1]*bicycle*s[3]-s[2]); } //static proc Ex_RLC-circuit() { ring RA=(0,m,R1,R2,L,C), D, lp; matrix circuit[2][3]=D+1/(R1*C), 0, -1/(R1*C), 0, D+R2/L, -1/L; list s=smith(circuit, 1,0); print(s[2]); print(s[1]*circuit*s[3]-s[2]); } //static proc Ex_two_pendula() { ring RA=(0,m,M,L1,L2,m1,m2,g), D, lp; matrix pendula[3][4]=m1*L1*D^2,m2*L2*D^2,(M+m1+m2)*D^2,-1,m1*L1^2*D^2-m1*L1*g,0,m1*L1*D^2,0,0, m2*L2^2*D^2-m2*L2*g,m2*L2*D^2,0; list s=smith(pendula, 1,0); print(s[2]); print(s[1]*pendula*s[3]-s[2]); } //static proc Ex_linerized_satellite_in_a_circular_equatorial_orbit() { ring RA=(0,m,omega,r,a,b), D, lp; matrix satellite[4][6]= D,-1,0,0,0,0, -3*omega^2,D,0,-2*omega*r,-a/m,0, 0,0,D,-1,0,0, 0,2*omega/r,0,D,0,-b/(m*r); list s=smith(satellite, 1,0); print(s[2]); print(s[1]*satellite*s[3]-s[2]); } //static proc Ex_flexible_one_link_robot() { ring RA=(0,M11,M12,M13,M21,M22,M31,M33,K1,K2), D, lp; matrix robot[3][4]=M11*D^2,M12*D^2,M13*D^2,-1,M21*D^2,M22*D^2+K1,0,0,M31*D^2,0,M33*D^2+K2,0; list s=smith(robot, 1,0); print(s[2]); print(s[1]*robot*s[3]-s[2]); } */ /////interesting examples for jacobson//////////////// /* //static proc Ex_compare_output_with_maple_package_JanetOre() { ring w = 0,(x,d),Dp; def W=nc_algebra(1,1); setring W; matrix m[3][3]=[d2,d+1,0],[d+1,0,d3-x2*d],[2d+1, d3+d2, d2]; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); } // modification for shift algebra { ring w = 0,(x,s),Dp; def W=nc_algebra(1,s); setring W; matrix m[3][3]=[s^2,s+1,0],[s+1,0,s^3-x^2*s],[2*s+1, s^3+s^2, s^2]; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); } //static proc Ex_cyclic() { ring w = 0,(x,d),Dp; def W=nc_algebra(1,1); setring W; matrix m[3][3]=d,0,0,x*d+1,d,0,0,x*d,d; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); } // modification for shift algebra: gives a module with ann = s^2 { ring w = 0,(x,s),Dp; def W=nc_algebra(1,s); setring W; matrix m[3][3]=s,0,0,x*s+1,s,0,0,x*s,s; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); } // yet another modification for shift algebra: gives a module with ann = s // xs+1 is replaced by x*s+s { ring w = 0,(x,s),Dp; def W=nc_algebra(1,s); setring W; matrix m[3][3]=s,0,0,x*s+s,s,0,0,x*s,s; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); } // variations for above setup with shift algebra: // easy but instructive one: see the difference to Weyl case! matrix m[2][2]=s,x,0,s; print(m); // more interesting: matrix n[3][3]=s,x,0,0,s,x,s,0,x; // things blow up matrix m[2][3] = s,x^2*s,x^3*s,s*x^2,s*x+1,(x+1)^3; matrix m[2][3] = s,x^2*s,x^3*s,s*x^2,s*x+1,(x+s)^2; // variation matrix m[2][4] = s,x^2*s,x^3*s,s*x^2,s*x+1,(x+1)^3, (x+s)^2, x*s; // bug (matrix sizes matrix m[3][4] = s,x^2*s,x^3*s,s*x^2,s*x+1,(x+1)^3, (x+s)^2, x*s; // here the last row contains zeros // this one is quite nasty and time consumig matrix m[3][4] = s,x^2*s,x^3*s,s*x^2,s*x+1,(x+1)^3, (x+s)^2, x*s,x,x^2,x^3,s; // example from the paper: ring w = 0,(x,d),Dp; def W=nc_algebra(1,1); setring W; matrix m[2][2]=d^2-1,d+1,d^2+1,d-x; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); ring w2 = 0,(x,s),Dp; def W2=nc_algebra(1,s); setring W2; poly d = s; matrix m[2][2]=d^2-1,d+1,d^2+1,d-x; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); // here, both JNFs are cyclic // another example from the paper: ring w = 0,(x,d),Dp; def W=nc_algebra(1,1); setring W; matrix m[2][2]=-x*d+1, x^2*d, -d, x*d+1; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); ring w2 = 0,(x,s),Dp; def W2=nc_algebra(1,s); setring W2; poly d = s; matrix m[2][2]=-x*d+1, x^2*d, -d, x*d+1; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); // yet another example from the paper, also Middeke ring w = (0,y),(x,d),Dp; def W=nc_algebra(1,1); setring W; matrix m[2][2]=y^2*d^2+d+1, 1, x*d, x^2*d^2+d+y; list J=jacobson(m,0); print(J[1]*m*J[3]); print(J[2]); print(J[1]); print(J[3]); print(J[1]*m*J[3]-J[2]); */ singular-4.0.3+ds/Singular/LIB/kskernel.lib000066400000000000000000000271021266270727000204570ustar00rootroot00000000000000/////////////////////////////////////////////////////////////// version="version kskernel.lib 4.0.0.0 Jun_2013 "; // $Id: e020a13d553fef7586c1f2e634c1fe11b3635ab5 $ category="General purpose"; info=" LIBRARY: kskernel.lib PROCEDURES FOR COMPUTING THE KERNEL OF THE KODAIRA-SPENCER MAP AUTHOR: Tetyana Povalyaeva, povalyae@mathematik.uni-kl.de PROCEDURES: KSker(p,q); kernel of the Kodaira-Spencer map of a versal deformation of an irreducible plane curve singularity KSconvert(M); kernel of the Kodaira-Spencer map in quasihomogeneous variables T with corresponding negative degrees KSlinear(M); matrix of linear terms of the kernel of the Kodaira-Spencer map KScoef(i,j,P,Q,qq); coefficient of the given term in the matrix of kernel of the Kodaira-Spencer map StringF(i,j,p,q); expression in variables T(i) with non-resolved brackets for the further computation of coefficient in the matrix of kernel of the Kodaira-Spencer map "; LIB "general.lib"; //////////////////////////////////////////////////////////////// //-------------------------- ALGORITHM II --------------------- //---------------------------- sub procedure ------------------ // used in sorter proc minim(intmat M, int t) { int m=v[t]; int i,k,done; k=0;done=0; for (i=t+1;iv[i]) { m=v[i];k=i;done=1; } } if (done==1) { for (i=1;i<=3;i++) { done=M[k,i];M[k,i]=M[t,i];M[t,i]=done; } i=v[k];v[k]=v[t];v[t]=i; } return(M); } //---------------------------- sub procedure -------------------- // sorts M by the third row, ascending proc sorter(intmat M) { intvec v; int i; for (i=1;i<=nrows(M);i++) { v[i]=M[i,3]; } export (v); int n=1; while (n<=nrows(M)) { M=minim(M,n); n++; } kill v; return(M); } //---------------------------- sub procedure -------------------- // M is a sorted matrix of triples {i,j,k(i,j)} // returns a list of coefficients of p // w.r.t. the base {x^i y^j,(i,j) in (M[i,j,k])}=B_u proc MonoDec(poly p, matrix M) { poly q=p; intvec V; list C; int nM=nrows(M); //cardinality of B_u vector VC=gen(nM+1); int k=1; int i=1; int j=1; while (q!=0) { V=leadexp(q); while ( !((V[1]==M[k,1]) && (V[2]==M[k,2])) ) { if (k>=nM) { ERROR("error in monomial base"); return(0); } k++; } VC=VC+leadcoef(q)*gen(k); q=q-lead(q); k=1; } VC=VC-gen(nM+1); return(VC); } //----------------------------- main program -------------------- proc KSker (int p,int q) "USAGE: KSker(int p,q); p,q relatively prime integers RETURN: nothing; exports ring KSring, matrix KSkernel and list 'weights'; KSkernel is a matrix of coefficients of the generators of the kernel of Kodaira-Spencer map, 'weights' is a list of degrees for variables T EXAMPLE: example KSker; shows an example " { option(redSB); option(redTail); int c; int i,j; int k=0; list LM; list tmp; for (i=0;i<=p-2;i++) { for (j=0;j<=q-2;j++) { c=(i*q)+(j*p)-(p*q); if (c>0) { k++; tmp[1]=i; tmp[2]=j; tmp[3]=c; // index of T LM[k]=tmp; tmp=0; } } } if (k==0) { "The kernel of the Kodaira-Spencer map equals zero"; return(); } if (k==1) { ring KSring=0,(T(1)),ws(c); matrix KSkernel[1][1]=c*T(1); export(KSring); export(KSkernel); return(); } int cnt=k; // the total number of T's, now k>1 intmat M[k][3]; // matrix with triples (i,j,k) for (i=1; i<=k; i++) { M[i,1] = LM[i][1]; M[i,2] = LM[i][2]; M[i,3] = LM[i][3]; } kill LM; M = sorter(M); // now the third column of M contains ordered ascending values list weights; for (i=1; i<=k; i++) { weights[i] = M[i,3]; // positive weights for Ws ordering M[i,3] = i; } export(weights); ring RT=0,(x,y,T(1..k)),(Ws(q,p),dp); poly F=x^p+y^q; i=0;j=0; for (k=1;k<=cnt;k++) { i = M[k,1]; j = M[k,2]; F = F + T(k)*x^i*y^j; } ideal I = diff(F,x),diff(F,y); I = std(I); k=0; list normal; poly mul; for (i=0;i<=p-2;i++) { for (j=0;j<=q-2;j++) { c = p*q - ((i+2)*q+(j+2)*p); if ( c > 0 ) { mul = x^i*y^j*p*q*F; k++; normal[k] = NF(mul,I); } } } // now we separate T's from (x,y) by treating T's as parameters ring ST=(0,T(1..k)),(x,y),Ws(q,p); setring ST; list Snormal = imap(RT,normal); ideal SI = imap(RT,I); kill RT; SI = std(SI); module L; for (i=1; i<=size(Snormal); i++) { Snormal[i] = NF(Snormal[i],SI); L[i] = MonoDec(Snormal[i],M); if (L[i]==0) // MonoDec has detected non-basis element { "Try reducing the input"; return(0); } } // now L is a module in T's ring KSring=0,(T(1..k)),(C,ws(-weights[1..k])); module TL=imap(ST,L); kill ST; // sort it descendently TL = sort(TL)[1]; // make the coefficients positive if ((leadcoef(TL[1,1])<0) || (leadcoef(TL[k,k])<0)) { TL = -TL;} matrix KSkernel=matrix(TL); export(KSring); export(KSkernel); kill M; return(); } example { "EXAMPLE:"; echo=2; int p=6; int q=7; KSker(p,q); setring Kskernel::KSring; print(KSkernel); } //---------------------------- sub procedure ------------------ // converts T(1..k) to T(w(1),..w(k)), // need global variable "weights" proc KSconvert(matrix M) "USAGE: KSconvert(matrix M); M is a matrix of coefficients of the generators of the kernel of Kodaira-Spencer map in variables T(i) from the basering. To be called after the procedure KSker(p,q) RETURN: nothing; exports ring KSring2 and matrix KSkernel2 within it, such that KSring2 resp. KSkernel2 are in variables T(w) with weights -w. These weights are computed in the procedure KSker(p,q) EXAMPLE: example KSconvert; shows an example " { int s=ncols(M); // the total numbers of T's ring T1=0,(T(1..weights[s])),dp; matrix TM=imap(KSring,M); int i; for (i=s;i>=1;i--) { TM=subst(TM,T(i),T(weights[i])); } string Tw="0,("; string Ww="Ws("; string tempo=""; for (i=1; i<=s; i++) { tempo=string(weights[i]); Tw = Tw+"T("+tempo+"),"; Ww = Ww+"-"+tempo+","; } Tw[size(Tw)] = ")"; Ww[size(Ww)] = ")"; Tw=Tw+","+Ww+";"; execute("ring KSring2="+Tw); matrix KSkernel2=imap(T1,TM); kill T1; export KSring2; export(KSring2); export KSkernel2; return(); } example { "EXAMPLE:"; echo=2; int p=6; int q=7; KSker(p,q); setring Kskernel::KSring; KSconvert(KSkernel); setring Kskernel::KSring2; print(KSkernel2); } proc KSlinear(matrix M) "USAGE: KSlinear(matrix M); computes matrix of linear terms of the kernel of the Kodaira-Spencer map. To be called after the procedure KSker(p,q) RETURN: nothing; but replaces elements of the matrix KSkernel in the ring Ksring with their leading monomials w.r.t. the local ordering (ls) EXAMPLE: example KSlinear; shows an example " { int s=ncols(M); // the total numbers of T's ring T1=0,(T(1..weights[s])),ls; matrix TM=imap(KSring,M); int i; int j; for (i=1; i<=s;i++) { for (j=1; j<=s;j++) { if (TM[i,j]!=0) { TM[i,j]=lead(TM[i,j]); } } } setring KSring; KSkernel=imap(T1,TM); kill T1; } example { "EXAMPLE:"; echo=2; int p=6; int q=7; KSker(p,q); setring Kskernel::KSring; KSlinear(KSkernel); print(KSkernel); } //-------------------------- ALGORITHM I ---------------------- //---------------------------- sub procedure ------------------ proc seq(int p,int q) // computes u,v such that 1<=u<=p-1, qu=1(mod p) // 1<=v<=q-1, pv=1(mod q) { int u=1; int v=1; for(u=1; u<=p-1; u++) { if (((q*u)%p)==1) {break;} } for(v=1; v<=q-1; v++) { if (((p*v)%q)==1) {break;} } return(u,v); } //---------------------------- sub procedure ------------------ // returns maximal number i such that u(i)<=b proc mix(int b, list u) { int result=0; int s=size(u); int w=s; if (s==0) { "size of list is 0"; return(result); } if (b<0 ) { "negative b in MIX"; return(result); } while ((w>1) && (u[w]>b)) { w--;} // min w=1 if (w>1) { return(w); } else // w<=1 { if ( (w==1) && (u[w]> b) ) { w=0; return(w); } } return(w); } //---------------------------- sub procedure ------------------ proc bracket_k(int r, int s) { int b=s-r; int q; int k=1; int SF; F=F+"*("; while (b>0) // simulate repeat ... until b==0 { q=mix(b,u); while (q>0) { b=u[q]-1; if (u[q]==(s-r)) // adding T's of max degree { F=F+"T("+ string(q) +")"+ "+"; } else { if (S[(1+r+u[q])]!="u") { F=F+"T("+ string(q) +")"; bracket_k(r+u[q],s); } } q=mix(b,u); if (q==0) {b=0;} } // end while q>0 SF=size(F); if (F[SF]!="+") { if (SF<=2) { F="";} else { F=F[1..SF-2];} } if (b==0) { break; } // ... until b==0 } F[size(F)]=")"; F=F+"+"; } //---------------------------- sub procedure ------------------ // exports S, l, u proc StringS(int p, int q) { int i=1; int j=0; int e,e1=0,0; string S=""; list l,u=0,0; S="l"; l[1]=0; int a,b=seq(p,q); int k=1; for (k=1;k<=(p*q-2*p-2*q);k++) { e=(e+a)%p; e1=(e1+b)%q; if ( (e==(p-1)) || (e1==(q-1)) ) { S=S+" "; } else { if ((e*q+e1*p) <= (p*q)) { i++; l[i]=k; S=S+"l"; } else { j++; u[j]=k; S=S+"u"; } } } export S; export u; export l; } //---------------------------- main procedures ---------------- proc StringF(int i, int j,int p, int q) "USAGE: StringF(int i,j,p,q); RETURN: nothing; exports string F which contains an expression in variables T(i) with non-resolved brackets EXAMPLE: example StringF; shows an example " { string F; export F;exportto(Top,F); StringS(p,q); bracket_k(l[i],u[j]); F=F[3..(size(F)-2)]; } example { "EXAMPLE:"; echo=2; int p=5; int q=14; int i=2; int j=9; StringF(i,j,p,q); F; } proc KScoef(int i,int j,int P,int Q, list qq); "USAGE: KScoef(int i,j,P,Q, list qq); RETURN: exports ring RC and number C within it. C is the coefficient of the word defined in the list qq, being a part of C[i,j] for x^p+y^q EXAMPLE: example KScoef; shows an example " // qq is a list of integers, representing // monomial T_q[1] * ...* T_q[s] // returns a ring RC in char 0 and number C in it { int s=size(qq); int U,V=seq(P,Q); StringS(P,Q); int n=l[i]; int d=P*Q; int k=1; int m=1; ring RC=0,x,dp; number C=0; number aux=0; int t=0; int e=0; int e1=0; aux = u[(qq[1])]; C = ((-1)^s)*(aux/d); for (k=2; k<=s; k++) { t = u[(qq[k-1])]; e = (U*n)%P; e = e+ ((U*t)%P); e1 = (V*n)%Q; e1 = e1 + ((V*t)%Q); n = n + qq[k-1]; t = u[(qq[k])]; if (e>=(P-1)) { aux = (U*t)%P; aux = aux/P; C = C*aux; } else { if (e1>=(Q-1)) { aux = (V*t)%Q; aux = aux/Q; C = C*aux; } } } export RC;exportto(Top,RC); export C; } example { "EXAMPLE:"; echo=2; int p=5; int q=14; int i=2; int j=9; list L; ring r=0,x,dp; number c; L[1]=3; L[2]=1; L[3]=3; L[4]=2; KScoef(i,j,p,q,L); c=imap(RC,C); c; L[1]=3; L[2]=1; L[3]=2; L[4]=3; KScoef(i,j,p,q,L); c=c+imap(RC,C); c; // it is a coefficient of T1*T2*T3^2 in C[2,9] for x^5+y^14 } singular-4.0.3+ds/Singular/LIB/latex.lib000066400000000000000000002542031266270727000177620ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version latex.lib 4.0.2.0 Sep_2015 "; // $Id: 552aa24c87335acad6ea2d72b2d7a797bfeca6a8 $ category="Visualization"; info=" LIBRARY: latex.lib Typesetting of Singular-Objects in LaTeX2e AUTHOR: Christian Gorzel, gorzelc@math.uni-muenster.de GLOBAL VARIABLES: TeXwidth, TeXnofrac, TeXbrack, TeXproj, TeXaligned, TeXreplace, NoDollars are used to control the typesetting. Call @code{texdemo();} to obtain a LaTeX2e file @code{texlibdemo.tex} explaining the features of @code{latex.lib} and its global variables. @format @code{TeXwidth} (int) -1, 0, 1..9, >9: controls breaking of long polynomials @code{TeXnofrac} (int) flag: write 1/2 instead of \\frac@{1@}@{2@} @code{TeXbrack} (string) \"@{\", \"(\", \"<\", \"|\", empty string: controls brackets around ideals and matrices @code{TeXproj} (int) flag: write \":\" instead of \",\" in vectors @code{TeXaligned} (int) flag: write maps (and ideals) aligned @code{TeXreplace} (list) list entries = 2 strings: replacing symbols @code{NoDollars} (int) flag: suppresses surrounding $ signs @end format PROCEDURES: closetex(fnm) writes closing line for LaTeX-document opentex(fnm) writes header for LaTeX-file fnm tex(fnm) calls LaTeX2e for LaTeX-file fnm texdemo([n]) produces a file explaining the features of this lib texfactorize(fnm,f) creates string in LaTeX-format for factors of polynomial f texmap(fnm,m,r1,r2) creates string in LaTeX-format for map m:r1->r2 texname(fnm,s) creates string in LaTeX-format for identifier texobj(l) creates string in LaTeX-format for any (basic) type texpoly(f,n[,l]) creates string in LaTeX-format for poly texproc(fnm,p) creates string in LaTeX-format of text from proc p texring(fnm,r[,l]) creates string in LaTeX-format for ring/qring rmx(s) removes .aux and .log files of LaTeX-files xdvi(s) calls xdvi for dvi-files (parameters in square brackets [] are optional) (Procedures with file output assume sufficient write permissions when trying to append existing or create new files.) "; LIB "inout.lib"; // only needed for pause(); /////////////////////////////////////////////////////////////////////////////// proc closetex(string fname, list #) "USAGE: closetex(fname); fname string RETURN: nothing; writes a LaTeX2e closing line into file @code{}. NOTE: preceding \">>\" are deleted and suffix \".tex\" (if not given) is added to @code{fname}. EXAMPLE: example closetex; shows an example " { string default = "latex2e"; string s; int i = 1; int flag; if (size(#)) { default = #[1];} if (default=="latex2e" or default == "latex") { s = "\\end{document}"; flag = 1;} if (default=="amstex") {s = "\\enddocument"; flag = 1;} if (default=="tex") {s = "\\bye"; flag = 1;} if (not(flag)) { s = "";} if (size(fname)) { while (fname[i]==">"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} write(fname, s); write(fname," % - Thanks latex.lib and Singular - "); } else {return(s);} } example { "EXAMPLE:"; echo=2; opentex("exmpl"); texobj("exmpl","{\\large \\bf hello}"); closetex("exmpl"); echo=0; } /////////////////////////////////////////////////////////////////////////////// proc tex(string fname, list #) "USAGE: tex(fname); fname string RETURN: nothing; calls latex (LaTeX2e) for compiling the file fname NOTE: preceding \">>\" are deleted and suffix \".tex\" (if not given) is added to @code{fname}. EXAMPLE: example tex; shows an example " { string default = "latex2e"; int retval; int i=1; if (size(#)) {default = string(#[1]);} if (size(fname)) { while (fname[i]==">"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} "calling "+default+" for:",fname,newline; if (default=="latex2e") { retval = system("sh","latex " + fname); } else { retval = system("sh",default + " " + fname); } } else { " // -- Need a filename "; return(); } } example { "EXAMPLE:"; echo =2; ring r; ideal I = maxideal(7); opentex("exp001"); // open latex2e document texobj("exp001","An ideal ",I); closetex("exp001"); tex("exp001"); echo=0; pause("the created files will be deleted after pressing "); system("sh","rm exp001.*"); } /////////////////////////////////////////////////////////////////////////////// proc opentex(string fname, list #) "USAGE: opentex(fname); fname string RETURN: nothing; writes a LaTeX2e header into a new file @code{}. NOTE: preceding \">>\" are deleted and suffix \".tex\" (if not given) is added to @code{fname}. EXAMPLE: example opentex; shows an example " { string default = "latex2e"; string s; int i =1; int flag; if (size(#)) { default = #[1];} if (default == "latex2e") // the default latex2e header { s = "\\documentclass{article}" + newline + "\\usepackage{amsmath,amssymb}" + newline + "%\\setlength{\\textwidth}{390pt}" + newline + "\\parindent=0pt" + newline + "\\newcommand{\\C}{\\mathbb{C}}" + newline + "\\newcommand{\\F}{\\mathbb{F}}" + newline + "\\newcommand{\\N}{\\mathbb{N}}" + newline + // "\\renewcommand{\\P}{{\\Bbb P}}" + newline + "\\newcommand{\\Q}{\\mathbb{Q}}" + newline + "\\newcommand{\\R}{\\mathbb{R}}" + newline + "\\newcommand{\\T}{\\mathbb{T}}" + newline + "\\newcommand{\\Z}{\\mathbb{Z}}" + newline + newline + "\\begin{document}"; flag = 1; } if (default == "latex") { s = "\\documentstyle[12pt,amstex]{article}" + newline + "\\parindent=0pt" + newline + "\\newcommand{\\C}{\\mathbb{C}}" + newline + "\\newcommand{\\F}{\\mathbb{F}}" + newline + "\\newcommand{\\N}{\\mathbb{N}}" + newline + // "\\newcommand{\\P}{\\mathbb{P}}" + newline + "\\newcommand{\\Q}{\\mathbb{Q}}" + newline + "\\newcommand{\\R}{\\mathbb{R}}" + newline + "\\newcommand{\\T}{\\mathbb{T}}" + newline + "\\newcommand{\\Z}{\\mathbb{Z}}" + newline + newline + "\\begin{document}"; flag = 1; } if (default == "amstex") { s = "\\documentstyle{amsppt} " + newline + newline + "\\document"; flag = 1; } if (default == "tex") { s = ""; flag = 1; } if (default == "own") // the proper own header { s = ""; flag = 1; } if (not(flag)) { s = "";} if (size(fname)) { while (fname[i]==">"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} fname = ">" + fname; write(fname,s); } else {return(s);} } example { "EXAMPLE:"; echo=2; opentex("exmpl"); texobj("exmpl","hello"); closetex("exmpl"); } /////////////////////////////////////////////////////////////////////////////// proc texdemo(list #) "USAGE: texdemo(); RETURN: nothing; generates a LaTeX2e file called @code{texlibdemo.tex} explaining the features of @code{latex.lib} and its global variables. " { int TeXdemostart = system("pid"); string fname = "texlibdemo"; if (size(#)) { if (typeof(#[1])=="int") {TeXdemostart = #[1];} } system("--random",TeXdemostart); //if (size(#) ==2) //{ if (typeof(#[2]) == "string") { fname = #[2];} //} if (size(fname)) { if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} } // -------- save global variables --------- if (defined(NoDollars)) {int NoDoll=NoDollars; kill NoDollars;} if (defined(TeXaligned)) {int Teali=TeXaligned; kill TeXaligned;} if (defined(TeXreplace)) {list Terep=TeXreplace; kill TeXreplace;} if (defined(TeXwidth)) {int Tewid=TeXwidth; kill TeXwidth;} if (defined(TeXbrack)) {string Tebra=TeXbrack; kill TeXbrack;} if (defined(TeXnofrac)) {int Tenof=TeXnofrac; kill TeXnofrac;} if (defined(TeXproj)) {int Tepro=TeXproj; kill TeXproj;} // ---------------------------------------- print(" Generating demofile ."); part0(fname); print(" ."); part1(fname); print(" ."); part2(fname); print(" ."); part3(fname); print(" ."); print(" Demofile generated."); if (size(fname)) { print(" Call latex now by tex(\"texlibdemo\");" ); print(" To view the file, call xdvi by xdvi(\"texlibdemo\");" ); // print(" Call latex now by tex(\"" + fname + "\");" ); //print(" To view the file, call xdvi by xdvi(\"" + fname + "\");" ); print(" .log and .aux files may be deleted with rmx(\"texlibdemo\");"); } // -------- save global variables --------- if (defined(NoDoll)) {int NoDollars=NoDoll; export NoDollars; kill NoDoll;} if (defined(Teali)) {int TeXaligned=Teali; export TeXaligned; kill Teali;} if (defined(Terep)) {list TeXreplace=Terep; export TeXreplace; kill Terep;} if (defined(Tewid)) {int TeXwidth=Tewid; export TeXwidth; kill Tewid;} if (defined(Tebra)) {string TeXbrack=Tebra; export TeXbrack; kill Tebra;} if (defined(Tenof)) {int TeXnofrac=Tenof; export TeXnofrac; kill Tenof;} if (defined(Tepro)) {int TeXproj=Tepro; export TeXproj; kill Tepro;} // ---------------------------------------- return(); } /////////////////////////////////////////////////////////////////////////////// proc texfactorize(string fname, poly f, list #) "USAGE: texfactorize(fname,f); fname string, f poly RETURN: if @code{fname=\"\"}: string, f as a product of its irreducible factors@* otherwise: append this string to the file @code{}, and return nothing. NOTE: preceding \">>\" are deleted and suffix \".tex\" (if not given) is added to @code{fname}. EXAMPLE: example texfactorize; shows an example " { def @r = basering; list l; int i,j,k,Tw,TW,ND;; intvec v; string s,t; string D = "$"; poly g; ND = defined(NoDollars); if (!(ND)) {int NoDollars; export NoDollars;} else { D = ""; } TW = defined(TeXwidth); if (TW) {Tw = TeXwidth; TeXwidth = -1;} else {int TeXwidth = -1; export TeXwidth;} l = factorize(f); if (l[1][1]<>1){s = texpoly("",l[1][1]);} if (size(l[1])>1) { if (l[1][1]!=-1 and l[1][1]!=1) { s = texpoly("",l[1][1]); } if (l[1][1]==-1) { s = "-";} } else { s = texpoly("",l[1]); } for(i=2;i<=size(l[1]);i++) { if(size(s) and s!="-"){s = s+"\\cdot ";} g = l[1][i]; v = leadexp(g); k=0; for(j=1;j<=size(v);j++){k = k + v[j];} if(size(g)>1 or (size(g)==1 and k>1)) { t = "(" + texpoly("",l[1][i]) + ")";} else { t = texpoly("",l[1][i]);} if (l[2][i]>1) { t = t+"^{" +string(l[2][i]) + "}";} s = s + t; } if (!(ND)) { kill NoDollars;} // kill Latex:: s = D + s + D; if (TW) {TeXwidth = Tw;} if (!TW) {kill TeXwidth;} // kill Latex:: if(size(fname)) { i=1; while (fname[i]==">"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} write(fname,s); } else{return(s);} } example { "EXAMPLE:"; echo=2; ring r2 = 13,(x,y),dp; poly f = (x+1+y)^2*x3y*(2x-2y)*y12; texfactorize("",f); ring R49 = (7,a),x,dp; minpoly = a2+a+3; poly f = (a24x5+x3)*a2x6*(x+1)^2; f; texfactorize("",f); } /////////////////////////////////////////////////////////////////////////////// proc texmap(string fname, def m, def @r1, def @r2, list #) "USAGE: texmap(fname,m,@r1,@r2); fname string, m string/map, @r1,@r2 rings RETURN: if @code{fname=\"\"}: string, the map m from @r1 to @r2 (preceded by its name if m = string) in TeX-typesetting;@* otherwise: append this string to the file @code{}, and return nothing. NOTE: preceding \">>\" are deleted in @code{fname}, and suffix \".tex\" (if not given) is added to @code{fname}. If m is a string then it has to be the name of an existing map from @r1 to @r2. EXAMPLE: example texmap; shows an example " { int saveDollars= defined(NoDollars); int TX = defined(TeXwidth); int Tw; int i,n; string r1str,r2str, varr1str, varr2str; string mapname,t,s; string D,DD,vrg = "$","$$",","; def @r = basering; def themap; list l1,l2; string rr1,rr2 = "@r1","@r2"; // --- store all actual informations if(TX) { Tw = TeXwidth; TeXwidth = -1;} else { int TeXwidth = -1; export TeXwidth;} if (!(saveDollars)) { int NoDollars; export NoDollars;} if (defined(TeXproj)) {vrg = ":";} if (size(#)) { if (typeof(#[1])=="list") { l1 = #[1]; if(size(#)==2) { l2 = #[2];} } else {l1=#; l2 =#;} } // --- tex the information in preimring r1 setring(@r1); r1str = texring("",@r1,l1); // --- avoid an execute; hence construct an ideal n = nvars(@r1); if (n>1) { t = "\\left(";} ideal @I = var(1); t = t + texpoly("",var(1)); for(i=2;i<=n;i++) { @I = @I + var(i); t = t + vrg + texpoly("",var(i)); } if (n>1) { t = t + "\\right)";} varr1str = t; // --- now the things in ring ring r2 setring(@r2); // listvar(); if (typeof(m)=="string") { themap = `m`; mapname = m; if (defined(TeXreplace)) { //mapname = rp(mapname); // rp ausschreiben ! for(int ii=1;ii<=size(TeXreplace);ii++) { if (TeXreplace[ii][1]==mapname) {mapname= TeXreplace[ii][2]; break;} } } mapname = mapname + ":"; } if (typeof(m)=="map") { themap = m;} r2str = texring("",@r2,l2); ideal @J = themap(@I); n = size(matrix(@J)); if (n>1) { t = " \\left(";} if (!(defined(TeXaligned)) and (n>1)) { t = t + newline + "\\begin{array}{c}" + newline;} t = t + texpoly("",@J[1]); for (i=2;i<=n; i++) {if(defined(TeXaligned)) { t = t + vrg + texpoly("",@J[i]); } else { t = t + "\\\\" + newline + texpoly("",@J[i]);} } if (!(defined(TeXaligned)) and (n>1)) { t = t + newline + "\\end{array}" + newline;} if (n>1) {t = t + "\\right)";} varr2str = t; // --- go back to ring r1 to kill @I setring(@r1); kill @I; // --- now reset the old settings and stick all the information together setring(@r); if (!(saveDollars)) { kill NoDollars;} // kill Latex:: if (TX) {TeXwidth = Tw;} else { kill TeXwidth;} // kill Latex:: if (defined(NoDollars)) { D,DD = "",""; } if (defined(TeXaligned)) { s = D + mapname; s = s + r1str + "\\longrightarrow" + r2str + ", \\ " + varr1str + "\\longmapsto" + varr2str + D; } else { s = DD; s = s + newline + "\\begin{array}{rcc}" + newline; s = s + mapname + r1str + " & \\longrightarrow & " + r2str + "\\\\[2mm]" + newline; s = s + varr1str + " & \\longmapsto & " + newline + varr2str + newline; s = s + "\\end{array}" + newline; s = s + DD; } if (size(fname)) { i=1; while (fname[i]==">"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} write(fname,s); } else {return(s);} } example { echo=0; // -------- prepare for example --------- if (defined(TeXaligned)) {int Teali=TeXaligned; kill TeXaligned;} if (defined(TeXreplace)) {list Terep=TeXreplace; kill TeXreplace;} // -------- the example starts here --------- // "EXAMPLE:"; echo = 2; string fname = "tldemo"; ring @r1=0,(x,y,z),dp; export @r1; ring r2=0,(u,v),dp; map @phi =(@r1,u2,uv -v,v2); export @phi; list TeXreplace; TeXreplace[1] = list("@phi","\\phi"); // @phi --> \phi export TeXreplace; texmap("","@phi",@r1,r2); // standard form // int TeXaligned; export TeXaligned; // map in one line texmap("",@phi,@r1,r2); // kill @r1,TeXreplace,TeXaligned; echo = 0; // // --- restore global variables if previously defined --- if (defined(Teali)) {int TeXaligned=Teali; export TeXaligned; kill Teali;} if (defined(Terep)) {list TeXreplace=Terep; export TeXreplace; kill Terep;} } /////////////////////////////////////////////////////////////////////////////// static proc manipul(string s) { string st; int i,anf,end,op,bigch; int n; if (s[1]=="{") { return(s[2,size(s)-2]);} if (s=="") { return(s);} s = s + newline; // add a terminating sign anf=1; while(s[i]!=newline) { i =anf; while(s[i]<"0" or s[i]>"9" and s[i]!="'" and s[i]!= "_" and s[i]!="~" and s[i]!="(" and s[i]!=")" and s[i]!= "[" and s[i]!=newline) {i++;} if (s[i]==newline){st = st + s[anf,i-anf]; n = n+10*(i-anf); return(st);} st = st + s[anf,i-anf]; // the starting letters if (s[anf]>="A" and s[anf]<="Z") {bigch=1;} if (s[i]=="'") { st = st + "'";i++;} if (s[i]=="~") { st = "\\tilde{" + st + "}"; i++;} if (s[i]=="_") { i++;} if (s[i]=="(") { op =1;i++;} if (s[i]=="[") { anf = i+1; while(s[i]!="]"){i++;} // matrices and vectors st = st + "_{" + s[anf,i-anf] + "}"; n = n+ 5*(i-anf); i++; // besser: while s[i]<> nwline : scan forward: end, return } if (s[i]==newline) {return(st);} anf =i; while (s[i]>="0" and s[i]<="9") {i++;} // parse number after the letters if (bigch and not(op)) { st = st + "^{" + s[anf,i-anf] + "}"; bigch =0;} else { st = st + "_{" + s[anf,i-anf] + "}";} n = n+5*(i-anf); anf =i; // the next text in ( , ) as exponent if (op) { if (s[i]== ","){anf = anf+1;} while(s[i] !=")"){ i++;} if (i<>anf) { st = st + "^{" + s[anf,i-anf] + "}"; n = n +5*(i-anf);} i++; } anf =i; } return(st); } /////////////////////////////////////////////////////////////////////////////// proc texname(string fname, string s) "USAGE: texname(fname,s); fname,s strings RETURN: if @code{fname=\"\"}: the transformed string s, for which the following rules apply: @example s' + \"~\" --> \"\\tilde@{\"+ s' +\"@}\" \"_\" + int --> \"_@{\" + int +\"@}\" \"[\" + s' + \"]\" --> \"_@{\" + s' + \"@}\" \"A..Z\" + int --> \"A..Z\" + \"^@{\" + int + \"@}\" \"a..z\" + int --> \"a..z\" + \"_@{\" + int + \"@}\" \"(\" + int + \",\" + s' + \")\" --> \"_@{\"+ int +\"@}\" + \"^@{\" + s'+\"@}\" @end example Furthermore, strings which begin with a left brace are modified by deleting the first and the last character (which is then assumed to be a right brace). if @code{fname!=\"\"}: append the transformed string s to the file @code{}, and return nothing. NOTE: preceding \">>\" are deleted in @code{fname}, and suffix \".tex\" (if not given) is added to @code{fname}. EXAMPLE: example texname; shows an example " { string st, extr; st=manipul(s); if (size(fname)) { int i=1; while (fname[i]==">"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} write(fname,st); } else {return(st);} } example { "EXAMPLE:"; echo =2; ring r = 0,(x,y),lp; poly f = 3xy4 + 2xy2 + x5y3 + x + y6; texname("","{f(10)}"); texname("","f(10) ="); texname("","n1"); texname("","T1_12"); texname("","g'_11"); texname("","f23"); texname("","M[2,3]"); texname("","A(0,3);"); texname("","E~(3)"); } /////////////////////////////////////////////////////////////////////////////// proc texobj(string fname, list #) "USAGE: texobj(fname,l); fname string, l list RETURN: if @code{fname=\"\"}: string, the entries of l in LaTeX-typesetting;@* otherwise: append this string to the file @code{}, and return nothing. NOTE: preceding \">>\" are deleted in @code{fname}, and suffix \".tex\" (if not given) is added to @code{fname}. EXAMPLE: example texobj; shows an example " { int i,j,k,nr,nc,linear,Tw,Dollars; int ND = defined(NoDollars); int TW = defined(TeXwidth); if(defined(basering)){ poly g,h; matrix M;} string s,t,l,ineq,sg,Iname; string sep= ","; string D,DA,DE = "$","$$"+newline,"$$"; string OB,CB = "(",")"; if (defined(TeXbrack)) {// if (TeXbrack=="(") {OB = "("; CB = ")";} if (TeXbrack=="<") {OB = "<"; CB = ">";} if (TeXbrack=="{") {OB = "{"; CB = "}";} if (TeXbrack=="|") {OB = "|"; CB = "|";} if (TeXbrack=="" ) {OB = "."; CB = ".";} } if (!(TW)) { int TeXwidth = -1; export TeXwidth; } Tw = TeXwidth; if (defined(TeXproj)){ sep = ":";} if(ND) { D,DA,DE="","","";} else {int NoDollars; export NoDollars;} if (size(#)==1) { if (typeof(#[1])=="int" or typeof(#[1])=="intvec" or typeof(#[1])=="vector" or typeof(#[1])=="number" or typeof(#[1])=="bigint" or defined(TeXaligned)) { DA = D; DE = D; } } s = DA; for (k=1; k<=size(#); k++) { def obj = #[k]; if (typeof(obj) == "string") { if (defined(`obj`)) { if (typeof(`obj`)=="ideal") { Iname = obj; def e = `obj`; //convert to correct type ideal kill obj; def obj = e; kill e; } else {s = s + obj + newline;} } else {s = s + obj + newline;} } if (typeof(obj) == "int" or typeof(#[1])=="bigint") { s = s + " " + string(obj) + " ";} if (typeof(obj) == "intvec") { s = s + " ("; for(j=1; j 0 !? ) s = s + "\\begin{array}{rcl}" + newline; for (i=1;i<=size(matrix(obj));i++) { s = s + Iname+ "_{" + string(i) + "} & = & " + texpoly("",obj[i]); if (i1){linear =0; break;} } if (!(linear)) { s = s + "\\begin{array}{rcl}" + newline; for(j=1;j<=size(obj);j++) { h = jet(obj[j],0); // absterm ineq = "=" ; l = texpoly("",obj[j]-h) + " & " + ineq + " & " + texpoly("",-h); if(j1) { if (t[1]!="-" and t[1]!= " " and nc ){sg = "+";} if (t[1]=="-") { sg = "-"; nc =1; t=t[2,size(t)-1];} if (t==" ") {sg ="";} l = l + " & " + sg + " & " + t; } else { l = t;} if (g!=0) {nc = 1;} } l = l + " & " + ineq + " & " + texpoly("",-h); if (j < size(obj)) { l = l + " \\\\";} s = s + l + newline; } // end for (j) s = s + "\\end{array}"; } // end else linear TeXwidth = 0; } // end TeXwidth == 0 else // TeXwidth <> 0 { s = s + "\\left"+ OB; if (defined(TeXaligned)) { s = s + texpoly("",obj,","); } else { s = s + newline + "\\begin{array}{c}" + newline + texpoly("",obj,", \\\\" + newline) + newline + "\\end{array}" + newline; } s = s + "\\right" + CB; } // end TeXwidth <> 0 } // not Iname // s; } if (typeof(obj) == "module") { M = matrix(obj); if (Tw ==0 or Tw > 9) { TeXwidth = -1;} s = s + "\\left" + OB + newline; if (!(defined(TeXaligned))) { // Naechste Zeile nicht notwendig ! // s = s + "\\begin{array}{*{"+ string(ncols(M)) + "}{c}}" + newline; for(j=1;j<=ncols(M);j++) { l = "\\left" + OB + newline + "\\begin{array}{c}" + newline; l = l + texpoly("",ideal(M[1..nrows(M),j]), " \\\\" + newline) + newline + "\\end{array}" +newline + "\\right" + CB + newline; if (j< ncols(M)) { l = l + " , " + newline;} s = s + l ; } } else // TeXaligned { for(j=1;j<=ncols(M);j++) { s = s + "\\left" + OB + newline + texpoly("",ideal(M[1..nrows(M),j]),",") + newline + "\\right" + CB; if (j 9) {TeXwidth = -1;} l = ""; // M = transpose(obj); s = s + "\\left" + OB + newline + "\\begin{array}{*{"+ string(ncols(obj)) + "}{c}" + "}"+ newline; for(i=1;i<=nrows(obj);i++) { l = l + texpoly("",ideal(obj[i,1..ncols(obj)])," & "); if (i"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} write(fname,s); } else {return(s);} } example { echo=0; // -------- prepare for example --------- if (defined(TeXaligned)) {int Teali=TeXaligned; kill TeXaligned;} if (defined(TeXbrack)){string Tebra=TeXbrack; kill TeXbrack;} "EXAMPLE:"; echo = 2; // // -------------- typesetting for polynomials ---------- ring r = 0,(x,y),lp; poly f = x5y3 + 3xy4 + 2xy2 + y6; f; texobj("",f); pause(); // -------------- typesetting for ideals ---------- ideal G = jacob(f); G; texobj("",G); pause(); // -------------- variation of typesetting for ideals ---------- int TeXaligned = 1; export TeXaligned; string TeXbrack = "<"; export TeXbrack; texobj("",G); pause(); kill TeXaligned, TeXbrack; // -------------- typesetting for matrices ---------- matrix J = jacob(G); texobj("",J); pause(); // -------------- typesetting for intmats ---------- intmat m[3][4] = 9,2,4,5,2,5,-2,4,-6,10,-1,2,7; texobj("",m); echo=0; // // --- restore global variables if previously defined --- if (defined(Teali)){int TeXaligned=Teali; export TeXaligned; kill Teali;} if (defined(Tebra)){string TeXbrack=Tebra; export TeXbrack; kill Tebra;} } /////////////////////////////////////////////////////////////////////////////// proc texproc(string fname,string pname) "USAGE: texproc(fname,pname); fname,pname strings ASSUME: @code{`pname`} is a procedure. RETURN: if @code{fname=\"\"}: string, the proc @code{`pname`} in a verbatim environment in LaTeX-typesetting;@* otherwise: append this string to the file @code{}, and return nothing. NOTE: preceding \">>\" are deleted in @code{fname}, and suffix \".tex\" (if not given) is added to @code{fname}.@* EXAMPLE: example texproc; shows an example " { int i,j,k,nl; string @p,s,t; j = 1; if (defined(`pname`)) { if (typeof(`pname`)=="proc") { @p = string(`pname`); nl = find(@p,newline); s = "\\begin{verbatim}" + newline; s = s + "proc " + pname + "("; i = find(@p,"parameter"); // collecting the parameters k = find(@p,"alias"); // and the alias arguments while((i and i < nl) or (k and k < nl)) { if (i and (k==0 or i1){s = s + ",";}; s = s + t; } if (k and (i==0 or k1){s = s + ",";}; s = s + t; } i = find(@p,"parameter",j); k = find(@p,"alias",j); } s = s + ")" + newline; j++; // skip one for the newline i = find(@p,";"+"return();"+newline,j); if (!(i)) { i = find(@p,";"+"RETURN();"+newline,j); } // j kann hier weg s = s + "{" + @p[j,i-j-1] + "}" + newline; s = s + "\\end{verbatim}" + newline; } } else { print(" // -- Error: No such proc defined"); return(); } if(size(fname)) { i=1; while (fname[i]==">"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} write(fname,s); } else{return(s);} } example { "EXAMPLE:"; echo=2; texproc("","texproc"); } /////////////////////////////////////////////////////////////////////////////// static proc tvar(intvec v) { int i,j,ldots; string s; j = 1; s = texpoly("",var(1)); if (nvars(basering)==1) { return(s);} if (nvars(basering)==2) { return(s + "," + texpoly("",var(2)));} if (size(v)==1 and v[1] == 1) {return(s + ",\\ldots,"+ texpoly("",var(nvars(basering))));} if (v[1]==1 and size(v) >1) {j++;} for(i=2;i} and return nothing. NOTE: preceding \">>\" are deleted and suffix \".tex\" (if not given) is added to @code{fname}.@* The optional list L is assumed to be a list of strings which control, for instance the symbol for the field of coefficients.@* For more details call @code{texdemo();} (generates a LaTeX2e file called @code{texlibdemo.tex} which explains all features of @code{texring}). EXAMPLE: example texring; shows an example " { int i,galT,intT,flag,mipo,nopar,Dollars,TB,TA; string ob,cb,cf,en,s,t,savebrack; //opening bracket, closing br, coef.field intvec v; setring r; if (!(defined(NoDollars))){ Dollars = 1; int NoDollars; export NoDollars;} ob,cb = "[","]"; if (find(ordstr(r),"s")) { ob,cb="[[","]]";} if(char(r)==0){cf="\\Q";} if(find(charstr(r),"integer")) // 4.10.10 { intT=1; cf="\\Z"; if (char(r)>0) { cf=cf+"_{"+string(char(r))+"}";} } if(find(charstr(r),"real")){cf="\\R";} if(find(charstr(r),"complex")){cf="\\C"; nopar=1;} // 28.10.06 if(char(r)==prime(char(r))){cf="\\Z_{"+string(char(r))+"}";} if(char(r)>0 and !intT) { i = find(charstr(r),","); if(i) { t= charstr(r)[1,i-1]; galT = (t <> string(char(r))); if (galT) { cf = "\\F_{"+ t + "}";} } } // all other cases are cover already by char(r)=? prime(char) if (size(#)) { if (typeof(#[1])=="list") { # = #[1];} } for (i=1;i<=size(#);i++) { flag =0; if(typeof(#[i])=="string") { if(#[i][1]=="^" or #[i][1]=="_"){en=en+#[i];flag = 1;} if(#[i]=="mipo"){mipo=1; flag = 1;} if(#[i]=="{"){ob,cb="\\{","\\}";flag=1;} if(#[i]=="{{"){ob,cb="\\{\\{","\\}\\}";flag=1;} if(#[i]=="["){ob,cb="[","]";flag=1;} if(#[i]=="[["){ob,cb="[[","]]";flag=1;} if(#[i]=="<"){ob,cb="<",">";flag=1;} if(#[i]=="<<"){ob,cb="{\\ll}","{\\gg}";flag=1;} if(#[i]=="C"){cf="\\C";flag=1;} if(#[i]=="Q"){cf="\\Q";flag=1;} if((#[i]=="k" or #[i]=="K" or #[i]=="R") and !(galT)) {cf=#[i]; flag=1; nopar=1;} if (flag!=1) {cf = #[i];} // for all the cases not covered here e.g Z_(p) } // or Q[i] if ((typeof(#[i])=="intvec") or (typeof(#[i])=="int")){v=#[i];} } s = cf; // now the parameters // t; if(npars(r) and ((t==string(char(r))) or char(r)==0) and !(nopar)) { s = s + "("; // !! mit ideal !! for(i=1;i3) { s = s + tvar(v);} else { s = s + texpoly("",maxideal(1),","); } s = s + cb + en; if (size(ideal(r))>0) /*qring*/ { ideal @I = ideal(r); if (defined(TeXbrack)) { TB =1; savebrack = TeXbrack; if (TeXbrack!= "<" and TeXbrack!="(") { TeXbrack = "<";} } TA = defined(TeXaligned); if (!(TA)) { int TeXaligned; export TeXaligned; } t = texobj("",@I); // @I; // t; if (TB) { TeXbrack = savebrack;} if (!(TA)) { kill TeXaligned;} // kill Latex:: s = s + "/" + t; } if (Dollars) { kill NoDollars; // kill Latex:: s = "$" + s + "$"; } if (size(fname)) { i=1; while (fname[i]==">"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} write(fname,s); } else{return(s);} } example { "EXAMPLE:"; echo=2; ring r0 = 0,(x,y),dp; // char = 0, polynomial ordering texring("",r0); // ring r7 =7,(x(0..2)),ds; // char = 7, local ordering texring("",r7); // ring r1 = 0,(x1,x2,y1,y2),wp(1,2,3,4); texring("",r1); // ring rr = real,(x),dp; // real numbers texring("",rr); // ring rC = complex,x,dp; // complex coefficients texring("",rC); // pause(); ring rabc =(0,t1,t2,t3),(x,y),dp; // ring with parameters texring("",rabc); // ring ralg = (7,a),(x1,x2),ds; // algebraic extension minpoly = a2-a+3; texring("",ralg); texring("",ralg,"mipo"); // ring r49=(49,a),x,dp; // Galois field texring("",r49); // setring r0; // quotient ring ideal i = x2-y3; qring q = std(i); texring("",q); // pause(); // ------------------ additional features ------------------- ring r9 =0,(x(0..9)),ds; texring("",r9,1); texring("",r9,"C","{","^G"); // ring rxy = 0,(x(1..5),y(1..6)),ds; intvec v = 5,6; texring("",rxy,v); } /////////////////////////////////////////////////////////////////////////////// proc rmx(string fname) "USAGE: rmx(fname); fname string RETURN: nothing; removes the @code{.log} and @code{.aux} files associated to the LaTeX file .@* NOTE: If @code{fname} ends by @code{\".dvi\"} or @code{\".tex\"}, the @code{.dvi} or @code{.tex} file will be deleted, too. EXAMPLE: example rmx; shows an example " { int i,suffix= 1,0; int retval; if (size(fname)) { while (fname[i]==">"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>4) { if (fname[size(fname)-3,4]==".tex") { suffix = 2;} if (fname[size(fname)-3,4]==".dvi") { suffix = 1; } if (suffix) { fname = fname[1,size(fname)-4]; } } retval = system("sh","rm " + fname + ".aux"); retval = system("sh","rm " + fname + ".log"); if (suffix==2) {retval = system("sh","command rm -i " + fname +".tex");} if (suffix>=1) {retval = system("sh","command rm -i " + fname +".dvi");} } else {" -- Need a filename "; return(); } } example { "EXAMPLE:"; echo =2; ring r; poly f = x+y+z; opentex("exp001"); // defaulted latex2e document texobj("exp001","A polynom",f); closetex("exp001"); tex("exp001"); rmx("exp001"); // removes aux and log file of exp001 echo = 0; pause("remaining files will be deleted after pressing "); echo = 2; system("sh","rm exp001.*"); } /////////////////////////////////////////////////////////////////////////////// proc xdvi(string fname, list #) "USAGE: xdvi(fname[,style]); fname,style = string RETURN: nothing; displays dvi-file fname.dvi with previewer xdvi NOTE: suffix .dvi may be omitted in fname style captures the program that will be called instead of the default (xdvi) EXAMPLE: example xdvi; shows an example " { int i=1; int retval; string default = "xdvi"; if (size(#)) {default = string(#[1]);} if (size(fname)) { while (fname[i]==">") {i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) { if(fname[size(fname)-3,4]==".tex") {fname = fname[1,size(fname)-4];}} "calling ",default, " for :",fname,newline; if (default=="latex2e") { retval = system("sh","latex " + fname +" &"); } else { retval = system("sh",default + " " + fname +" &"); } } else { " -- Need a filename "; return(); } } example { "EXAMPLE:"; echo = 2; intmat m[3][4] = 9,2,4,5,2,5,-2,4,-6,10,-1,2,7; opentex("exp001"); texobj("exp001","An intmat: ",m); closetex("exp001"); tex("exp001"); xdvi("exp001"); echo = 0; pause("the created files will be deleted after pressing "); echo = 2; system("sh","rm exp001.*"); } /////////////////////////////////////////////////////////////////////////////// static proc parsr(string s) // parse real { string t; if (s=="( Inf)") { return("\\infty",3);} if (s=="( -Inf)") { return("\\-infty",6);} if (s[8]=="-"){t ="-";} if (s[9]<>"0"){t = t + s[9];} if (s[10]<>"0" or s[9]<>"0"){t = t + s[10];} if (size(t)) { if (t=="1") {return(s[1,6]+"\\cdot 10",21);} if (size(t)>1) {return(s[1,6]+"\\cdot 10^{"+t+"}",21+2*size(t));} else {return(s[1,6]+"\\cdot 10^"+t+")",23);} } else { return(s[2,5],12); } } /////////////////////////////////////////////////////////////////////////////// static proc parsg(string s) // parse Galois field { string t; if (s=="1") {return("1",5);} if (short) { t =s[1]; if(size(s)>1) {return(t+"^{" + s[2,size(s)-1] + "}",3+2*(size(s)-1));} else{return(t,5);} } else { return(parselong(s+"!")); } } /////////////////////////////////////////////////////////////////////////////// proc texpoly(string fname,def p,list #) "USAGE: texpoly(fname,p); fname string, p poly RETURN: if @code{fname=\"\"}: string, the polynomial p in LaTeX-typesetting;@* otherwise: append this string to the file @code{}, and return nothing. NOTE: preceding \">>\" are deleted in @code{fname}, and suffix \".tex\" (if not given) is added to @code{fname}. EXAMPLE: example texpoly; shows an example " { def @r = basering; poly f,monom; ideal I; number cfm; string sign,cfmt,pt,s,bg,t,monomt,lnbreak; string sep = newline; int i,b,b2,n, msz,linesz, count,k; int realT, parT, galT, complT; int TW = defined(TeXwidth); int C = 2 + defined(TeXdisplay); string notvalid = "intvec intmat vector matrix module map"; if (typeof(p) == "int") { return(p);} if (typeof(p) == "ring") { " -- Call texring instead "; return();} if (find(notvalid,typeof(p))) { " -- Call texobj instead "; return();} if (typeof(p) == "map") { " -- Call texmap instead "; return();} if (typeof(p) == "proc") { " -- Call texmap instead "; return();} if (typeof(p) == "link" or typeof(p) == "list" or typeof(p) == "resolution") { ERROR(" // -- Object cannot translated into tex "); return();} if (!(defined(TeXdisplay))){ lnbreak = "\\\\[2mm]" + newline;} else { lnbreak = "\\\\" + newline;} if (defined(TeXdisplay)) { bg = "& ";} if (!TW) { int TeXwidth = -1; export TeXwidth;} // -- Type check if (typeof(p)=="string") { if(defined(`p`)) { pt = p + " = "; p = `p`; } } if (typeof(p)=="poly" or typeof(p)=="number") {I = p;} if (typeof(p)=="ideal") { I = p; if(size(#)){ sep = #[1];} } if (size(I)==0) { if (!(defined(NoDollars))){return("$0$");} else {return("0");} } // -- Type check ende //--------------------- //------- set flags: -------------------------------------------------------- if (size(#)) { if (typeof(#[1])=="int") { linesz = #[1];} // if (typeof(#[1])=="string") { linesz = #[1];} } parT = npars(@r); realT = (charstr(@r)=="real"); complT = find(charstr(@r),"complex"); // 28.10.06 if (complT) {parT=0;} i = find(charstr(@r),","); if (i and !realT and !complT) { t = charstr(@r)[1,i-1]; galT = (t <> string(char(@r))); // the char is not the same as the ... } i = 0; //------- parse the polynomial pt = bg; for(k=1;k<=ncols(I);k++) { i = 0; linesz = 0; count =0; sign =""; f = I[k]; if (f==0) { pt = pt + "0";} while(f<>0) { count++; msz = 0; // ------ tex the coefficient monom = lead(f); f = f - monom; cfm = leadcoef(monom); if (cfm*1 != 0) { monom = leadmonom(monom);} // to conform with integer if (defined(TeXreplace)) { short =0;} // this is essential //31.5.07 s = string(monom) + "!"; // add a terminating sign cfmt = ""; cfmt = string(cfm); if (size(cfmt)>1) // check if sign is < 0 { if (cfmt[2]=="-") { cfm = (-1) *cfm; sign = "-";}} if (cfmt[1] == "-") { cfm = (-1) * cfm; sign = "-";} if (cfm!=1 or monom==1) {cfmt = string(cfm);} else {cfmt="";} if (defined(TeXwidth) and TeXwidth > 0 and TeXwidth <9 and count> TeXwidth) { pt = pt + sign + "\\ldots"; break;} // ---------------------------------------- linesz ?? if (size(cfmt)) // parse the coefficient { monomt = cfmt; // (already a good choice for integers) msz = 3*size(cfmt); if(realT) { monomt,msz = parsr(cfmt);} if (galT) { monomt,msz = parsg(cfmt);} b = find(cfmt,"/("); // look if fraction // 31.5.07 if (b==0) { b = -find(cfmt,")/"); } // 1.9.15 b2 = find(cfmt,"/"); // if (b) {b++;} // 31.5.07 n = size(cfmt); if (!(parT) and !(realT) and !(galT)) { if( !(b2) or defined(TeXnofrac)) { monomt = cfmt; msz = 3*size(monomt);} else { monomt = "\\frac{" + cfmt[1,b2-1] + "}{" + cfmt[b2+1,n-b2] + "}"; if (n-2*b2>0) {msz = C*(n-b2);} else {msz = C*b2;} } } if (parT and !(galT)) { monomt,msz = parsp(cfmt,b);} } if (monom!=1 and monomt!="" and parT) // 21.4.10 { monomt = monomt+"\\cdot ";} // at least a blank is needed for TeXreplace // -- now parse the monom if (monom <> 1) { i = 1; if(short) { while(s[i]<>"!") { monomt = monomt + s[i]; i++; b = i; msz = msz + 3; // it was a single lettered var while(s[i]!="!" and s[i]>="0" and s[i]<="9"){i++;} if (i-b) { monomt = monomt + "^{" + s[b,i-b] + "}"; msz = msz + 2*(i-b); } } } else // not short { t,i = parselong(s); monomt = monomt + t; msz = msz + i; } } msz = msz + 6*size(sign); // Wieso mal 6 ?? // string(msz) + " ," + string(linesz) + " " + string(cfm*monom); if (TeXwidth > 10 and (linesz + msz > 3*TeXwidth) and linesz) { pt = pt + lnbreak + bg; linesz = msz; } else { linesz = linesz + msz; } // 3 for sign pt = pt + sign + monomt; sign = "+"; monomt = ""; } if (k"){i++;} fname = fname[i,size(fname)-i+1]; if (size(fname)>=4) // check if filename is ending with ".tex" { if(fname[size(fname)-3,4]!=".tex") {fname = fname +".tex"; } } else {fname = fname + ".tex";} write(fname,pt); } else {return(pt);} } example { "EXAMPLE:"; echo =2; ring r0=0,(x,y,z),dp; poly f = -1x^2 + 2; texpoly("",f); ring rr= real,(x,y,z),dp; texpoly("",2x2y23z); ring r7= 7,(x,y,z),dp; poly f = 2x2y23z; texpoly("",f); ring rab =(0,a,b),(x,y,z),dp; poly f = (-2a2 +b3 -2)/a * x2y4z5 + (a2+1)*x + a+1; f; texpoly("",f); texpoly("",1/(a2+2)*x2+2/b*x+(a+1)/3); } /////////////////////////////////////////////////////////////////////////////// static proc parsp(string cfmt, int b) { string mt, nom,denom; int fl1,fl2,sz1,sz2,msz; if (!(b)) { mt,fl1 = parst(cfmt,0); msz = size(cfmt)-2; if (fl1) { mt = "(" + mt + ")"; msz = msz +1; } } else { if (b>0) { nom,fl1 = parst(cfmt[1,b-1],1); denom,fl2 = parst(cfmt[b+1,size(cfmt)-b],1); } else { b = -b; nom,fl1 = parst(cfmt[1,b],1); denom,fl2 = parst(cfmt[b+2,size(cfmt)-b-1],1); } if (defined(TeXnofrac)) { if(fl1) { nom = "(" + nom + ")"; sz1++;} if(fl2) {denom = "(" + denom + ")"; sz2++;} mt = "(" + nom+ "/"+ denom+ ")"; msz = sz1+sz2 +1; //31.5.07 } else { mt = "\\frac{" + nom + "}{" + denom + "}"; if (sz1-sz2) { msz = 5*sz1;} else {msz = 5*sz2;} } } return(mt,msz); } example {"EXAMPLE:"; echo =2; ring r=(0,a,b),x,dp; int i; poly f = (a2b12 + 23a2 -b13-1)/(a2+2b -1); f; string s; s= string(f); i = find(s,")/("); parsp(s,i); } /////////////////////////////////////////////////////////////////////////////// static proc parst(string s,int sec) // parse parameter // sec parameter to see if in parsp a fraction follows { int i,j =1,-1; int b,k,jj,mz,in; // begin and end, in for index int saveshort=short; string t,c,vn,nom,denom,sg; if (s[1]=="(") { s = s[2,size(s)-2]; } s = s + "!"; if (short) { j = 0; // 31.5.07 while(s[i]<>"!") { b=i; if (s[i]=="+" or s[i]=="-") {j++;} // 31.5.07 while(s[i]>="0" and s[i]<="9" or (s[i]=="+" or s[i]=="-") and s[i]!="!") {i++;} // scan the number t =s[b,i-b]; // if (t=="-1" and s[i]!="!" and s[i]!="-" and s[i]!="+"){t = "-";} if (t=="-1" and (s[i]<="0" or s[i]>="9") and s[i]!= "/" and s[i]!="!") {t = "-";} if (s[i]=="/") { i++; sg = ""; if (t[1]=="+" or t[1]=="-") { nom = t[2,size(t)-1]; sg = t[1]; } else { nom = t;} b =i; while(s[i]>="0" and s[i]<="9") {i++;} denom = s[b,i-b]; if (!(sec) and (!(defined(TeXaligned)))) { t = sg + "\\frac{" + nom + "}{" + denom + "}";} else { t = sg + "(" + nom + "/" + denom + ")"; } } c = c + t; if(s[i]!="!"){c = c + s[i]; i++;} // the parameter b=i; while(s[i]>="0" and s[i]<="9") {i++;} //the exponent if(i-b){ c = c + "^{" + s[b,i-b]+"}";} } } else // if not short .... { while (s[i] <> "!") { b=i; j++; in=0; // 4.10.10 while(s[i]=="-" or s[i]=="+" or (s[i]>="0" and s[i]<="9")){i++;} t = s[b,i-b]; if (t=="-1" and s[i]=="*" ) {t="-";} if (s[i]=="/") { i++; sg = ""; if (t[1]=="+" or t[1]=="-") { nom = t[2,size(t)-1]; sg = t[1]; } else { nom = t;} b =i; while(s[i]>="0" and s[i]<="9") {i++;} denom = s[b,i-b]; if (!(sec) and (!(defined(TeXaligned)))) { t = sg + "\\frac{" + nom + "}{" + denom + "}";} else { t = sg + "(" + nom + "/" + denom + ")"; } } c = c+t; t=""; if (s[i]=="*"){i++;} b=i; // string(s[1,b]); while(s[i]!="+" and s[i]!="-" and s[i]!="!") //pass a monom { // start with letters // alternativ: //in=0; // 4.10.10 while((s[i]>="a" and s[i]<="z") or (s[i]>="A" and s[i]<="Z")){i++;} k = i-b; vn = s[b,k]; if (defined(TeXreplace)) { for (jj=1; jj<= size(TeXreplace);jj++) { if (vn == TeXreplace[jj][1]) {vn = TeXreplace[jj][2]; k=1; if (s[i]=="*") {vn = vn + " ";} break;} //suppose replacing by a single sign } } t = t + vn; mz = mz + 10*k; if (s[i]=="_" or s[i]=="(") {in++; i++;} // the index is coming b = i; while(s[i]>="0" and s[i]<="9"){ i++;} k = i-b; if (k and in<=1) {t = t + "_{";in++;} //and k i.e. there was an index if (k){ t = t +s[b,k];} if(s[i]==")") {i++;} if(k and s[i]!="(" and s[i]!="_"){ t = t + "}";} // index closed if(s[i]=="(" or s[i]=="_") {i++; t = t + ",";in++;} if (s[i]=="^") { i++; b = i; while(s[i]>="0" and s[i]<="9"){ i++;} // for neg. expon. if (b-i) { t = t + "^{" + s[b,i-b] + "}";} } if (i-b > k) { mz = mz + 5*(i-b);} else {mz = mz + 5*k;} if (s[i]=="*"){i++;in=0;} b=i; } c =c+t; } } short = saveshort; return(c,j); } example { "EXAMPLE:"; echo =2; ring r=(0,a,b),x,dp; poly f = (a2b12 + 23a2 -b13-1); f; parst(string(f),0); f =(-a +4b2 -2); f; parst(string(f),0); f = a23; f; parst(string(f),0); f = 2a12b3 -4ab15 +2a4b12 -2; short =0; f; parst(string(f),0); ring r2=(0,a1,b1),x,dp; poly f = 2*a1^12*b1^3 -4*a1*b1^15 +2*a1^4*b1^12 -2; f; parst(string(f),0); } /////////////////////////////////////////////////////////////////////////////// static proc parselong(string s) { int i,j,k,b,mz,in; // in is a counter for indices string t,vn; // varname i = 1; while (s[i] <> "!") { b=i; // -- scan now the letter ... // while(s[i]!="!" and ) // alternativ: while((s[i]>="a" and s[i]<="z") or (s[i]>="A" and s[i]<="Z")) { i++;} // s[i]; i; k = i-b; vn = s[b,k]; if (defined(TeXreplace)) { for (j=1; j<= size(TeXreplace);j++) { if (vn == TeXreplace[j][1]) {vn = TeXreplace[j][2]; k=1; if (s[i]=="*") {vn = vn + " ";} break;} //suppose replacing by a single sign } } t = t + vn; mz = mz + 10*k; if (s[i]=="_" or s[i]=="(") { in++;i++;} // the index is coming b = i; while(s[i]>="0" and s[i]<="9" or s[i]=="-"){ i++;} // "-" for neg indices j = i-b; // if (j){ t = t + "_{" +s[b,j] + "}";} // formely if (j and in<=1) {t = t + "_{";in++;} // and j i.e. there was an index if (j){ t = t +s[b,j];} if(s[i]==")") {i++;} if(j and s[i]!="(" and s[i]!="_"){ t = t + "}";} // index closed if(s[i]=="(" or s[i]=="_") {i++; t = t + ",";in++;} if (s[i]=="^") { i++; b = i; while(s[i]>="0" and s[i]<="9" or s[i]=="-") { i++;} // for neg. expon. if (b-i) { t = t + "^{" + s[b,i-b] + "}";} } if (i-b > j) { mz = mz + 5*(i-b);} else {mz = mz + 5*j;} if (s[i]=="*"){i++;in=0;} } return(t,mz); } example { "EXAMPLE:"; echo =2; ring r =(49,a),x,dp; number f = a13; parsg(string(f)); list TeXreplace; export TeXreplace; TeXreplace[1] = list("b","\\beta"); TeXreplace[2] = list("a","\\alpha"); TeXreplace[3] = list("c","\\gamma"); parselong(string(f)+"!"); } /////////////////////////////////////////////////////////////////////////////// /* obsolete static proc tktex (def d) { // calls appropriate proc from latex lib string typeofd =typeof(d); if (typeofd=="int" or typeofd=="string" or typeofd=="resolution" or typeofd=="map" or typeofd =="list"){ return(d);} if (typeofd=="intvec" or typeofd == "intmat" or typeofd =="vector" or typeofd=="matrix" or typeofd == "module") { return(texobj("",d));} if (typeofd=="ring") { return(texring("",d));} if (typeofd =="ideal") { return(texobj("",d));} if (typeofd=="number" or typeofd=="poly" or typeofd=="ideal") { return(texpoly("",d));} if (typeofd=="link") {return(d);} } */ ///////////////////////////// PART0 ////////////////////////////////////////// static proc part0(string fname) { int texdemopart =0; export texdemopart; // Singular script for generating tldemo.tex string nl = newline; string nl2 = newline + newline; string lb = "\\\\"; string bv = "\\begin{verbatim}" + newline ; string ev = newline + "\\end{verbatim}" +newline ; // "generating part0 of " + fname + nl; opentex(fname); write(fname,"\\newcommand{\\Line}{{}\\par\\noindent\\rule{\\textwidth}{0.25mm}\\\\[1mm]}"); write(fname,"\\centerline{\\textbf{\\large Demo file for latex.lib }}"); // write(fname,"\\centerline{\\textbf{\\large Christian Gorzel }}"); write(fname,"\\centerline{07/10/2010}"); write(fname,"\\vspace{1cm}"); //-- write(fname,"","\\section{Introduction}"); write(fname,"The procedures in \\verb|latex.lib| translate the output of {\\sc Singular} into \\LaTeX \\ text. This document illustrates the functionality of the library."+"\\\\" + nl); write(fname,"\\begin{tabular}{ll}" + nl + "LIBRARY: {\\tt latex.lib} & PROCEDURES FOR TYPESETTING SINGULAR" + "\\\\" + nl + " & OBJECTS IN LATEX2E"+ "\\\\" + nl + "{\\tt closetex(fnm);} & writes closing line for \\LaTeX-document"+ "\\\\" + nl + "{\\tt opentex(fnm);} & writes header for \\LaTeX-file fnm"+ "\\\\" + nl + "{\\tt tex(fnm);} & calls \\LaTeX2e for file fnm"+ "\\\\" + nl + "{\\tt texdemo([n]);} & produces a file explaining the features of this lib"+ "\\\\" + nl + "{\\tt texfactorize(fnm,f);} & creates string in \\LaTeX-format for factors of polynomial f"+ "\\\\" + nl + "{\\tt texmap(fnm,m,r1,r2);} & creates string in \\LaTeX-format for map m:r1$\\rightarrow$r2"+ "\\\\" + nl + "{\\tt texname(fnm,s);} & creates string in \\LaTeX-format for identifier"+ "\\\\" + nl + "{\\tt texobj(l);} & creates string in \\LaTeX-format for any (basic) type"+ "\\\\" + nl + "{\\tt texpoly(f,n[,l]);} & creates string in \\LaTeX-format for poly"+ "\\\\" + nl + "{\\tt texproc(fnm,p);} & creates string in \\LaTeX-format of text from proc p"+ "\\\\" + nl + "{\\tt texring(fnm,r[,l]);} & creates string in \\LaTeX-format for ring/qring"+ "\\\\" + nl + "{\\tt rmx(s);} & removes .aux and .log files of \\LaTeX-files"+ "\\\\" + nl + "{\\tt xdvi(s);} & calls xdvi for dvi-files"+ "\\\\" + nl + " \\end{tabular} " + nl2 + "\\vspace{0.2cm}" + nl2 + "(parameters in square brackets {\\tt [ ]} are optional)"+ "\\\\" + nl2 + "\\vspace{0.2cm}" + nl2 + "The global variables {\\tt TeXwidth}, {\\tt TeXnofrac}, {\\tt TeXbrack}, {\\tt TeXproj}, {\\tt TeXaligned}, {\\tt TeXreplace}, {\\tt NoDollars} are used to control the typesetting: " ); write(fname, bv + " TeXwidth (int) -1, 0, 1..9, >9: controls breaking of long polynomials TeXnofrac (int) flag: write 1/2 instead of \\frac{1}{2} TeXbrack (string) \"{\", \"(\", \"<\", \"|\", empty string: controls brackets around ideals and matrices TeXproj (int) flag: write \":\" instead of \",\" in vectors TeXaligned (int) flag: write mappings (and ideals) aligned TeXreplace (list) list entries = 2 strings: replacing symbols NoDollars (int) flag: suppresses surrounding $ signs " + ev); write(fname,"Notice that none of these global variables are defined when loading \\verb|latex.lib|. A flag variable is set as soon as it is defined."); //% The procs and //% the global variables //----------------------- opentex ----------------------------- write(fname,"","\\section{Opening a \\LaTeX\\ file}"); write(fname,"","In order to create a \\LaTeX\\ document and write a standard header into it, use the following command."+ nl + bv+ "> string fname = \"" + fname + "\";" + nl + "> texopen(fname);" + ev); write(fname,"The variable \\verb|fname| is always the first argument when calling one of the procedures of \\verb|latex.lib|. If this string is the empty string, then the output in not written into a file but displayed on the screen."); //% opentex, defaulted to latex, possibly extension are ... and //% ``own'' pagewidth = 65; int TeXwidth = 100; export TeXwidth; // "part 0 generated " + nl; } //part0 ///////////////////////////// PART1 ////////////////////////////////////////// static proc part1(string fname) { int st = defined(texdemopart); string nl = newline; string nl2 = newline + newline; string lb = "\\\\"; string bv = "\\begin{verbatim}" + newline ; string ev = newline + "\\end{verbatim}" + newline ; if (not(st) or texdemopart>=1) { print(" Call part0 first"); return(); } else { texdemopart=1; } //"Continuing part1 of " + fname + nl; write(fname,"","\\section{Rings, polynomials and ideals}",""); // -1a------ a ring in char 0, short varnames and poly. ordering ---------- write(fname, " A ring in characteristic 0 with short names of variables and polynomial ordering." +nl); ring r0=0,(x,y,z),dp; poly g=-x2y+2y13z+1; write(fname, bv + "> ring r0=0,(x,y,z),dp;" +nl+ "> texring(fname,r0);" + ev); texring(fname,r0); write(fname,nl2); write(fname, bv + "> poly g=-x2y+2y13z+1; g;" + nl + "> texpoly(fname,g);" + ev); texpoly(fname,g); write(fname,"\\\\"+nl); // write(fname,"\\Line"); // -1b------ still in the same ring, a polynomial with rational coefs -------- write(fname, ""," A polynomial with rational coefficients." +nl); write(fname, bv + "> texpoly(fname,g/280);" + ev ); texpoly(fname,g/280); kill r0; write(fname,"\\Line","%-----------------------------------------------------"); // -2-------- a ring in char 7, indexed varnames and series ordering ---------- write(fname, " A ring in characteristic 7 with indexed names of variables and local ordering.",""); ring r1=7,(x1,x2,x3,x4),Ds; poly g=-2*x1+x4-1; write(fname, bv + "> ring r1=7,(x1,x2,x3,x4),Ds;" +nl + "> texring(fname,r1);" + ev); texring(fname,r1); write(fname, bv + "> poly g=-2*x1+x4-1; g;" +nl + "> texpoly(fname,g);" + ev); texpoly(fname,g); write(fname,"\\Line","%-----------------------------------------------------"); // -3-------- a ring in char 0, indexed varnames and local ordering ---------- write(fname, " A ring in characteristic 0 with indexed names of variables and local ordering. " +nl); ring r2=0,(x(1..5),y(1..2)),(ds(5),ls(2)); poly g=-y(1)^3*x(5) +y(1)*x(2); write(fname, bv + "> ring r2=0,(x(1..5),y(1..2)),(ds(5),ls(2));" + nl + "> texring(fname,r2);" + ev); texring(fname,r2); write(fname, bv + "> poly g=-y(1)^3*x(5)+y(1)*x(2); g;" +nl+ string(g) + nl + "> texpoly(fname,g);" + ev ); texpoly(fname,g); write(fname,"\\Line","%-----------------------------------------------------"); // -4-------- a ring in char 0, indexed varnames and weighted ordering ------ write(fname, " A ring in characteristic 0 with indexed names of variables and weighted ordering." +nl); ring r3=0,(x_1,x_2,x_3),wp(3,2,1); poly g=-x_1*x_2+2*x_2*x_3+x_1*x_3; write(fname, bv + "> ring r3=0,(x_1,x_2,x_3),wp(3,2,1);" +nl+ "> texring(fname,r3);" + ev); texring(fname,r3); write(fname, bv + "> poly g=-x_1*x_2+2*x_2*x_3+x_1*x_3; g;" +nl+ string(g) + nl + "> texpoly(fname,g);" + ev ); texpoly(fname,g); write(fname,"\\Line","%-----------------------------------------------------"); // -5-------- a ring with real coeff and matrix ordering ------------------- write(fname, " A ring with real coefficients and matrix ordering. " +nl); ring rr=real,(x,y),M(1,2,3,4); poly g =-1.2e-10*x2+y+1; write(fname, bv + "> ring rr=real,(x,y),M(1,2,3,4);"+nl+ "> texring(fname,rr);"+ ev); texring(fname,rr); write(fname, bv + "> poly g=-1.2e-10*x2+y+1; g;"+nl+ string(g) + nl + "> texpoly(fname,g);" + ev); texpoly(fname,g); write(fname,"\\Line","%-----------------------------------------------------"); // -6a-------- a ring in char 0, and indexed parameters --------- ---------- write(fname, " A ring in characteristic 0 with parameters. " +nl); ring r0t=(0,s,t),(x,y),dp; poly g=8*(-s+2t)/(st+t3)*x+t2*x-1; write(fname, bv + "> ring r0t=(0,s,t),(x,y),dp;" +nl + "> texring(fname,r0t);" + ev); texring(fname,r0t); write(fname, bv + "> poly g=8*(-s+2t)/(st+t3)*x+t2*x-1; g;"+nl+ string(g) +nl + "> texpoly(fname,g);" + ev); texpoly(fname,g); write(fname,"\\Line","%-----------------------------------------------------"); write(fname,"\\newpage"); // -6b------- a ring in char 11003, and indexed parameters --------- ---------- write(fname, " A ring in characteristic 11 and indexed parameters. " +nl); ring rt=(11003,t1,t2,t3),(X,Y),dp; poly g=8*(-t1+t2)/(t1+t3)*X+t2*Y-1; write(fname, bv + "> ring rt=(11003,t1,t2,t3),(X,Y),dp;" +nl + "> texring(fname,rt);" + ev); texring(fname,rt); write(fname, bv + "> poly g=8*(-t1+t2)/(t1+t3)*X+t2*Y-1; g;" + nl+ string(g) +nl + "> texpoly(fname,g);" + ev); texpoly(fname,g); write(fname,"\\Line","%-----------------------------------------------------"); // -7-------- a ring over an algebraic extension in char 7 --------------- write(fname," A ring over an algebraic extension in char 7."); ring ralg = (7,a),x,dp; minpoly = a2-a+3; poly g = -(2a13+a)*x2+a2*x-a+1; write(fname, bv + "> ring ralg=(7,a),x,dp;" +nl + "> minpoly=a2-a+3;" +nl + "> texring(fname,ralg);" + ev); texring(fname,ralg); write(fname, bv + "> poly g=-(2a13+a)*x2+a2*x-a+1; g;"+nl+ string(g) +nl + "> texpoly(fname,g);" + ev ); texpoly(fname,g); write(fname,"\\Line","%-----------------------------------------------------"); // -8-------- the same ring a in 7 ralg, defined with gftables -- F_49 ------- write(fname, " A ring defined with \\verb|gftables|, the same as \\verb|ralg| before, but with primitive element in the Galois field $\\F_{49}$." +nl); ring r49 =(49,a),x,dp; poly g=-(2a13+a)*x2+a2*x-a+1; write(fname, bv + "> ring r49 =(49,a),x,dp;" +nl+ "> texring(fname,r49);" + ev); texring(fname,r49); write(fname, bv + "> poly g=-(2a13+a)*x2+a2*x-a+1; g;" +nl+ string(g) +nl + "> texpoly(fname,g);" + ev); texpoly(fname,g); write(fname,"\\Line","%-----------------------------------------------------"); // -9-------- a ring over the Gaussian numbers ---------- write(fname, " A ring over the Gaussian numbers. " +nl); ring ri=(0,i),(x,y,z),ls; minpoly=i2+1; poly g=-(i+1)*x+2i2y2+i+x; write(fname, bv + "> ring ri=(0,i),(x,y,z),ls;" +nl + "> minpoly=i2+1;" +nl + "> texring(fname,ri);" + ev); texring(fname,ri); write(fname, bv + "> poly g=-(i+1)*x+2i2y2+i+x; g;" +nl+ string(g) +nl + "> texpoly(fname,g);" + ev ); texpoly(fname,g); write(fname,"\\Line","%-----------------------------------------------------"); // -10--------- a quotient ring performed from ---------- write(fname," A quotient ring performed of \\verb|r0| by an ideal."); ring r0=0,(x,y,z),dp; ideal I = x2-y, y+z2, xy; I = std(I); string sI = string(I); qring qr = I; write(fname, bv + "> setring r0; > ideal I=x2-y,y+z2, xy; > I=std(I); > string(I);" + nl + string(sI) + nl + "> qring qr=I; > texring(fname,qr);" + ev ); texring(fname,qr); //write(fname,"\\Line","%-----------------------------------------------------"); // ------------------------- Features for rings write(fname,"","\\subsection{Features for rings}"); write(fname, "In many cases it might be convenient to change the standard typesetting of rings. This can be done by passing additional arguments to \\verb|texring|." +nl); // changing the brackets write(fname,nl,"In order to change the displayed brackets one has to give the desired ones as additional argument (accepted brackets are: \\verb|\"\{\"|, \\verb|\"\{\{\"|,\\verb|\"[\"|,\\verb|\"[[\"|,\\verb|\"<\"|,\\verb|\"<<\"|)."); write(fname, bv + "> texring(fname,rr,\"{{\");" + ev ); texring(fname,rr,"{{"); write(fname, bv + "> texring(fname,r2,\"[\");" + ev ); texring(fname,r2,"["); write(fname,nl+"\\vspace{0.2cm}" + nl2); write(fname,"The brackets around the ideal in a quotient ring can be changed by setting the global variable \\verb|TeXbrack| (see section {\\tt Ideals}).",nl); write(fname, bv + "> string TeXbrack = \"<\";" +nl + "> texring(fname,qr);" + ev ); string TeXbrack = "<"; export TeXbrack; texring(fname,qr); kill TeXbrack; write(fname, bv + "> kill TeXbrack;" + ev); //write(fname,"\\Line","%-----------------------------------------------------"); // changing the ground field // ------------------------------------------------- write(fname, "It is possible to display a ground field different from the actual one by passing any letter in \\LaTeX \\ notation as additional argument. Predefined values are \\verb|\"\\\\C\"|, \\verb|\"\\\\R\"|, \\verb|\"k\"|, \\verb|\"K\"| and \\verb|\"R\"|."+nl+ "If for example a ground field of characteristic 0 should be written as $\\C$ instead of $\\Q$ use this as additional argument.",nl); write(fname, bv + "> texring(fname,r3,\"\\\\C\");" + ev); texring(fname,r3,"\\C"); write(fname,nl+ "\\vspace{0.2cm}" + nl2); write(fname,"The values \\verb|\"k\"|, \\verb|\"K\"|, \\verb|\"R\"| play a special role when the ground field is an algebraic extension. In this case the parameters will be omitted."); write(fname, bv + "> texring(fname,ralg,\"k\");" + ev ); texring(fname, ralg,"k"); write(fname,nl+"\\vspace{0.2cm}" + nl2); write(fname,"If an algebraic extension should be displayed together with its minimal polynomial the optional parameter \\verb|mipo| has to be used."); write(fname, bv + "> texring(fname,ralg,\"mipo\");" + ev ); texring(fname, ralg,"mipo"); write(fname,"\\Line","%-----------------------------------------------------"); // displaying only certain vars write(fname,"By default all variables of a ring will be displayed. It is possible to print only certain variables with $\\ldots$ between them. The positions of the variables which should be displayed have to be passed to \\verb|texring| as an \\verb|intvec|."); write(fname, bv + "> intvec v=5,6; > texring(fname,r2,v);" + ev ); intvec v = 5,6; texring(fname,r2,v); kill v; write(fname, bv + "> kill v;" + ev ); write(fname,nl+ "\\vspace{0.2cm}" + nl2); write(fname,"The first and the last variable will always be printed. In order to print only these it is sufficient to give a 1 as third argument."); write(fname, bv + "> texring(fname,r1,1);" + ev ); texring(fname,r1,1); write(fname,"\\Line","%-----------------------------------------------------"); // invariant ring under a group action write(fname,"If you want for example to display a ring as the invariant ring under a group, additional information starting with \\verb|^| may be added."); write(fname, bv + "> texring(fname,r0,\"^G\");" + ev ); texring(fname, r0,"^G"); write(fname,"\\Line","%-----------------------------------------------------"); // passing several optional arguments at once write(fname,"It is also possible to pass several of the arguments described above at once (in any order)."); write(fname, bv + "> texring(fname,r3,\"\\\\R\",\"{{\",\"^G\");" + ev ); texring(fname, r3,"\\R","{{","^G"); //"end part 1" + nl; } ///////////////////////////// PART2 ////////////////////////////////////////// static proc part2(string fname) { int st = defined(texdemopart); string nl = newline; string nl2 = newline + newline; string lb = "\\\\"; string bv = "\\begin{verbatim}" + newline ; string ev = newline + "\\end{verbatim}" + newline ; // string ev = "\\end{verbatim}" ; if (not(st) or texdemopart>=2) { print(" Call part1 first"); return(); } else { texdemopart=2; } // "Continuing Part2 of " + fname + nl; //-------------------- texfactorize ------------------------------ write(fname,"","\\subsection{Factorized polynomials}"); write(fname,"The command \\verb|texfactorize| calls internally the {\\sc Singular} command \\verb|factorize| and returns the product of the irreducible factors. Note that, at the moment, it is not possible to pass any optional arguments for \\verb|factorize| through \\verb|texfactorize|."); ring r0=0,(x,y,z),dp; poly h=(x+1+y)^2*x3y*(2x-2y)*y12; write(fname, bv + "> setring r0; > poly h=(x+1+y)^2*x3y*(2x-2y)*y12; h;" +nl+ string(h) + nl + "> texfactorize(fname,h);" + ev); texfactorize(fname,h); // setring ralg; ring ralg = (7,a),x,dp; minpoly = a2-a+3; poly h = (a24x5+x3)*a2x6*(x+1)^2; write(fname, bv + "> setring ralg; > poly h=(a24x5+x3)*a2x6*(x+1)^2; h;"+ nl + string(h) + nl + "> texfactorize(fname,h);"+ ev); texfactorize(fname,h); //--------------------- features for polynomials ----------------- write(fname,"","\\subsection{Features for polynomials}"); // TeXreplace // --------------------------------------------- write(fname,"By setting the global variable \\verb|TeXreplace| it is possible to define rules for replacing strings or variable names. \\verb|TeXreplace| has to be a list of twoelemented lists where the first entry is the text which should be replaced by the second entry. This may be applied to replace names of variables, but is also used when calling \\verb|texname| or \\verb|texmap|. Note that it is necessary to write a double backslash \\verb|\\\\\| at the beginning of a \\TeX \\ symbol.",""); write(fname,"Let us denote the primitive element of an algebraic extension by $\\xi$."); list TeXreplace; export TeXreplace; TeXreplace[1] = list("a","\\xi"); // setring r49; ring r49 =(49,a),x,dp; poly g=-(2a13 +a)*x2+a2*x-a+1; write(fname, bv + "> list TeXreplace;" +nl + "> TeXreplace[1]=list(\"a\",\"\\\\xi\");" +nl+ "> setring r49;" +nl+ "> texpoly(fname,g);"+ ev); texpoly(fname,g); write(fname,nl+ "\\vspace{0.2cm}" + nl2); write(fname,"Now let us write $\\lambda$ and $\\mu$ for deformation parameters."); TeXreplace[2]= list("s","\\lambda"); TeXreplace[3]= list("t","\\mu"); // setring(r0t); ring r0t=(0,s,t),(x,y),dp; poly g=8*(-s+2t)/(st+t3)*x+t2*x-1; write(fname, bv + "> TeXreplace[2]=list(\"s\",\"\\\\lambda\");"+nl+ "> TeXreplace[3]=list(\"t\",\"\\\\mu\");"+nl+ "> setring(r0t);"+nl+ "> texpoly(fname,g);"+ ev); texpoly(fname,g); kill TeXreplace; write(fname,nl+ "\\vspace{0.4cm}"); write(fname,nl+"Note that, if \\verb|TeXreplace| is defined, the translation into \\LaTeX code runs a little bit slower, because every polynomial is compiled in the \\verb|non short| mode."+ lb ); write(fname,nl,"\\Line","%-----------------------------------------------------"); //linebreaking TeXwdith //----------------------------------------------------------------------- write(fname,"The global variable \\verb|TeXwidth| controls the wrapping of polynomials; possible values are:" + lb); write(fname, "\\[ " + nl + "\\text{\\tt TeXwidth} = ", "\\begin{cases} ", " -1 & \\text{no line-breaking} \\\\ ", " 0 & \\text{print the polynomial as equation } f=0 \\\\ ", " 1,\\dots,9 & \\text{the first n terms followed by the sign of the next term} \\\\ ", " > 9 & \\text{line break after terms of length n (see below)} ", "\\end{cases}", "\\]",nl); write(fname,"Note that the size of terms is calculated with certain multiplicities.",nl); //---------------------------------------------------------- write(fname,"\\begin{itemize}"); write(fname,"\\item"); write(fname, bv + "> TeXwidth=-1;"+nl+ "> setring r0;"+nl+ "> poly f=g^2;"+nl+ "> texpoly(fname,f);" + ev); setring r0; poly g=-x2y+2y13z+1; poly f=g^2; texpoly(fname,f); write(fname,"\\item"); write(fname, bv + "> TeXwidth=0; > texpoly(fname,f);"+ ev); TeXwidth = 0; texpoly(fname,f); write(fname,"\\item"); write(fname, bv + "> TeXwidth=2; > texpoly(fname,f);"+ ev); TeXwidth=2; texpoly(fname,f); write(fname,"\\item"); write(fname, bv + "> TeXwidth=20;"+nl+ "> texpoly(fname,f);"+ ev); TeXwidth=20; texpoly(fname,f); TeXwidth=-1; write(fname,"\\end{itemize}"); write(fname,"\\Line","%-----------------------------------------------------"); write(fname,"There are two possibilities to convert a polynomial into \\LaTeX{} code: either by using \\verb|texpoly| or by calling \\verb|texobj|. The difference is that \\verb|texpoly| puts the polynomial in text-mode while \\verb|texobj| uses the display mode."+nl+ "The following examples show the different outputs:"); write(fname, bv + "> setring r3; > texpoly(fname,g/180);" + ev); // setring r3; ring r3=0,(x_1,x_2,x_3),wp(3,2,1); poly g=-x_1*x_2+2*x_2*x_3+x_1*x_3; texpoly(fname,g/180); write(fname, bv + "> texobj(fname,g/180); " + ev); texobj(fname,g/180); //write(fname,"Some explanation how it works: if \\verb|texobj| is called for //a polynomial, then it defines a global variable \\verb|TeXdisp| which forces //\\verb|texpoly| to count fraction with space corresponding //the displaymode."+lb,nl2); //---------------------texobj for ideal --------------- write(fname,"","\\subsection{Ideals}"); write(fname,"By default, ideals are displayed as column vectors."); ring r; ideal I=3xz5+x2y3-3z,7xz5+y3z+x-z,-xyz2+4yz+2x; write(fname, bv + "> ring r; // the default ring"+nl+ "> ideal I=3xz5+x2y3-3z,7xz5+y3z+x-z,-xyz2+4yz+2x;"+nl+ "> texobj(fname,I);" + ev); texobj(fname,I); write(fname,"\\Line","%-----------------------------------------------------"); //---------------------------------------------------------------------- write(fname,"If the global variable \\verb|Texaligned| is set then the ideal is displayed as a row vector."); write(fname, bv + "> int TeXaligned; > texobj(fname,I);" + ev); int TeXaligned; export TeXaligned; texobj(fname,I); write(fname,nl+"\\Line","%-----------------------------------------------------"); //---------------------------------------------------------------------- write(fname,"By setting the global variable \\verb|TeXbrack| it is possible to change the brackets."); write(fname, bv + "> string TeXbrack=\"<\";"+nl+ "> texobj(fname,I);"+ ev); string TeXbrack="<"; export TeXbrack; texobj(fname,I); write(fname, bv + "> kill TeXbrack, TeXaligned;" + ev); kill TeXbrack,TeXaligned; write(fname,"\\Line","%-----------------------------------------------------"); //---------------------------------------------------------------------- write(fname, " If \\verb|TeXwidth| is 0, an ideal is displayed as a system of equations."); // ------------- a linear equation system ring r5=0,x(1..5),dp; ideal I=-x(1)+2*x(3)+x(5), x(2)-x(4)+2*x(5)-1, 8*x(1)+x(4)+2; TeXwidth=0; write(fname, bv + "> ring r5=0,x(1..5),dp;"+nl+ "> ideal I=-x(1)+2*x(3)+x(5), x(2)-x(4)+2*x(5)-1, 8*x(1)+x(4)+2;"+nl+ "> TeXwidth=0;"+nl+ "> texobj(fname,I);" + ev); texobj(fname,I); setring r; ideal J=4x4y21+z25y7-y2,x3+y2,y2-z4; write(fname, bv + "> setring r;"+nl+ "> ideal J=4x4y21+z25y7-y2,x3+y2,y2-z4;"+nl+ "> texobj(fname,J);" + ev ); texobj(fname,J); write(fname,"\\Line","%-----------------------------------------------------"); //----------------------------------------------------------------------- write(fname,"Call the ideal by its name and it is printed as follows"); write(fname, bv + "> setring r; > ideal I=3xz5+x2y3-3z,7xz5+y3z+x-z,-xyz2+4yz+2x; > texobj(fname,\"I\");" + ev); setring r; export(I); texobj(fname,"I"); kill I,r; //" end part 2 " + nl; } ///////////////////////////// PART3 ////////////////////////////////////////// static proc part3(string fname) { int st=defined(texdemopart); string nl=newline; string nl2=newline + newline; string lb="\\\\"; string bv=newline+"\\begin{verbatim}"; // string ev = newline + "\\end{verbatim}" + newline ; string ev="\\end{verbatim}" ; if (not(st) or st>=3) { print(" Call part2 first"); return(); } else { texdemopart=3; } // " Continuing part 3 of " + fname + // " : map,matrices,vectors,intvec,intmats,proc"; //---------------------- texmap ------------------------------ write(fname,"","\\section{Typesetting maps between rings}"); write(fname,"By default, maps are displayed in the following way:"); write(fname, bv, "> ring r4=0,(x,y,z),dp; > ring r5=0,(u,v),dp; > map phi=r1,u2,uv -v,v2; > texmap(fname,phi,r4,r5);", ev); ring @r4_h=0,(x,y,z),dp; export @r4_h; ring r5=0,(u,v),dp; map @phi_h=@r4_h,u2,uv -v,v2; export @phi_h; texmap(fname,@phi_h,@r4_h,r5); write(fname,"\\Line","%-----------------------------------------------------"); //-------------------------------------------------------------------- write(fname,"If the global variable \\verb|TeXaligned| is set, then the map is displayed in one line."); write(fname, bv, "> int TeXaligned; > texmap(fname,phi,r4,r5,\"\\\\C\");", ev ); int TeXaligned; export TeXaligned; texmap(fname,@phi_h,@r4_h,r5,"\\C"); write(fname,nl+"\\Line","%-----------------------------------------------------"); //-------------------------------------------------------------------- write(fname,"It is possible to pass the same additional arguments to \\verb|texmap| as to \\verb|texring| (see section {\\tt Rings}). This can be done by calling \\verb|texmap| with two lists as additional parameters, where the first list contains the optional parameters for the source and the second one contains the parameters for the domain. Note that if only one list is present then it is applied to both of the rings."); write(fname, bv, "> texmap(fname,phi,r4,r5,\"\\\\C\",\"{\");", ev ); texmap(fname,@phi_h,@r4_h,r5,"\\C","{"); write(fname,nl+ "\\vspace{0.2cm}" + nl); write(fname,"The next example shows how to format the two rings in different ways."); write(fname, bv, "> texmap(fname,phi,r4,r5,list(),list(\"{\"));", ev ); texmap(fname,@phi_h,@r4_h,r5,list(),list("{")); write(fname,"\\Line","%-----------------------------------------------------"); //-------------------------------------------------------------------- write(fname,"If the map is called by its name then \\verb|texmap| displays, in addition, also the name of the map."); write(fname, bv, "> list TeXreplace; > TeXreplace[1]=list(\"phi\",\"\\\\phi\"); > texmap(fname,\"phi\",r4,r5);", ev); list TeXreplace; TeXreplace[1]=list("@phi_h","\\phi"); export TeXreplace; texmap(fname,"@phi_h",@r4_h,r5); kill @phi_h,@r4_h,r5,TeXreplace,TeXaligned; write(fname, bv, "> kill phi,r4,r5,TeXreplace,TeXaligned;", ev); //% the texobj part write(fname,"","\\section{Typesetting composed data structures}"); //======================================================================= write(fname, "Complex data structures such as matrices, vectors or modules can be displayed by using the procedure \\verb|texobj|."); write(fname,"","\\subsection{Matrices and vectors}"); //======================================================================= write(fname,"The following example shows how to typeset the Hessian of a polynomial."); write(fname, bv, "> ring r; > poly h=2xy3-x2z+x4z7+y4z2; > matrix H=jacob(jacob(h)); > texobj(fname,H);", ev ); ring r; poly h=2xy3-x2z+x4z7+y4z2; matrix H=jacob(jacob(h)); texobj(fname,H); write(fname,"By default, \\verb|vectors| are written as row vectors:"); vector V = H[2]; write(fname, bv, "> vector V=H[2]; > texobj(fname,V);", ev ); texobj(fname,V); write(fname,nl+"\\vspace{0.2cm}"+nl); write(fname,"In order to transpose it, it has to be converted into a matrix."); write(fname, bv, "> texobj(fname,matrix(V));", ev ); texobj(fname,matrix(V)); write(fname,nl+"\\Line","%-----------------------------------------------------"); //------------------------------------------------------------------------ write(fname,"All the features for typesetting polynomials work also for matrices or vectors with polynomial entries."); write(fname,nl+ "\\vspace{0.2cm}" + nl); write(fname,"By setting the global variable \\verb|TeXwidth| it is possible to display only the first terms of the polynomials."); write(fname,bv, "> TeXwidth=1; > texobj(fname,H); > TeXwidth=-1;", ev ); TeXwidth = 1; texobj(fname,H); TeXwidth = -1; write(fname,nl,"\\Line","%-----------------------------------------------------"); //------------------------------------------------------------------------ write(fname,"The flag variable \\verb|TeXnofrac| controls the typesetting of fractions."); write(fname, bv, "> ring R0=0,x,dp; > matrix M[2][3]=1/2, 0, 1/2, 0, 1/3, 2/3; > texobj(fname,M);", ev); ring R0 = 0,x,dp; matrix M[2][3] = 1/2, 0, 1/2, 0, 1/3, 2/3; texobj(fname,M); write(fname,bv, "> int TeXnofrac; > texobj(fname,M);", ev ); int TeXnofrac; export TeXnofrac; texobj(fname,M); kill TeXnofrac; write(fname,bv, "> kill TeXnofrac;", ev ); write(fname,nl,"\\Line","%-----------------------------------------------------"); //------------------------------------------------------------------------ write(fname,"Printing a vector with homogeneous coordinates can be done by setting \\verb|TeXproj|."); write(fname,bv + "> setring r; > int TeXproj; > texobj(fname,V);", ev ); setring r; ideal I=3xz5+x2y3-3z,7xz5+y3z+x-z,-xyz2+4yz+2x; int TeXproj; export TeXproj; texobj(fname,V); kill TeXproj; write(fname, bv, "> kill TeXproj;", ev); write(fname,"","\\subsection{Modules}"); write(fname,"By default, modules are displayed in the following way:"); write(fname, bv, "> setring r; > module md=module(H); > texobj(fname,md);", ev ); setring r; module md = module(H); texobj(fname,md); write(fname,"\\Line","%-----------------------------------------------------"); //------------------------------------------------------------------------ write(fname,"In order to write the generators of a module aligned, the flag variable \\verb|TeXaligned| has to be defined."); write(fname,bv, "> int TeXaligned; > texobj(fname,md);", ev ); int TeXaligned; export TeXaligned; texobj(fname,md); kill TeXaligned; write(fname,bv, "> kill TeXaligned;", ev ); //---------------------------------------------------------------- write(fname,"","\\subsection{Integer matrices and vectors}"); write(fname,"Integer matrices are displayed in the following way."); intmat m[3][4]=-1,3,5,2,-2,8,6,0,2,5,8,7; write(fname, bv, "> intmat m[3][4]=-1,3,5,2,-2,8,6,0,2,5,8,7; > m;" + nl + string(m) + nl + "> texobj(fname,m);", ev ); texobj(fname,m); write(fname,nl+ "\\vspace{0.2cm}" + nl); write(fname,"Integer vectors are displayed as row vectors."); intvec v = 1..4; write(fname, bv, "> intvec v=1..4; > v;" + nl + string(v) + nl + "> texobj(fname,v);", ev ); texobj(fname,v); write(fname,nl+ "\\vspace{0.2cm}" + nl); write(fname,"To typeset the transposed vector, it has to be converted into an integer matrix."+ bv, "> texobj(fname,intmat(v));", ev ); texobj(fname,intmat(v)); write(fname,nl+ "\\vspace{0.2cm}" + nl); write(fname,"The following example shows how to typeset the multiplication of a matrix with a vector."); write(fname, bv, "> texobj(fname,intmat(m*v),\"=\",m,\"*\",intmat(v));", ev ); texobj(fname,intmat(m*v),"=",m,"*",intmat(v)); //----------------------------------------------------------------- write(fname,"\\Line","%-----------------------------------------------------"); write(fname,"Of course, the brackets of a \\verb|intmat| can be changed by setting \\verb|TeXbrack|."); write(fname, bv, "> intmat mat[3][3]=1,2,3,4,5,6,7,8,9; > string TeXbrack=\"|\"; > texobj(fname,mat,\" = \",det(mat)); ", ev ); intmat mat[3][3] = 1,2,3,4,5,6,7,8,9; string TeXbrack = "|"; export TeXbrack; texobj(fname,mat," = ",det(mat)); kill TeXbrack; //----------------------------------texname------------------- //write(fname,"\\section{Names of identifiers}"); //write(fname,"The proc \\verb|texname| is used to write indexed names in a //correct way"+lb,nl); // ------------------------------- texproc ------------------------------- proc milnor_number (poly p) { ideal i = std(jacob(p)); int m_nr = vdim(i); if (m_nr<0) { "//-- not an isolated singularity"; } return(m_nr); } export(milnor_number); write(fname,"","\\section{Typesetting procedures}"); write(fname,"The following procedure allows to include the source code of procedures into a \\LaTeX document."); write(fname, bv, "> texproc(fname,\"milnor\_number\");", ev); texproc(fname,"milnor_number"); kill milnor_number; // ------------------------------ closing the tex file ------------------- write(fname,"","\\section{Closing the \\LaTeX\\ file}"); write(fname,"To close the file use \\verb|closetex(fname);|. It should now contain pure \\LaTeX \\ code and may be compiled with " + "\\verb|tex(fname)| and displayed with \\verb|xdvi(fname)|."); // write(fname,"\\section{Remarks}"); closetex(fname); //"end of part3" + nl; pagewidth =80; kill texdemopart,TeXwidth; } /////////////////////////////////////////////////////////////////////////////// /* texring extended for Z,Z_m,real,complex // Test for new functionality: // texring: ring rZ = integer,x,dp; texring("",rZ); ring rZ8 = (integer,8),x,dp; texring("",rZ8); ring rR = real,x,dp; texring("",rR); ring rR2010 = (real,20,10),x,dp; texring("",rR2010); ring rC = complex,x,dp; texring("",rC); ring rC2010 = (complex,20,10),x,dp; texring("",rC2010); // multi-indexed parameters and variables ring rmultind34 = 0,(a(1..3)(1..4)),dp; texring("",r34); matrix A[3][4] = maxideal(1); texobj("",A); ring rmultind2 = 0,(x1_2,y_1_1,z),ds; texring("",rmultind2); ring rmultind3 = 0,(x(-1..1)(0)(3..4)),ds; texobj("",maxideal(1)); ring rmultind4 = (0,b1(0..2),b2_1(3)),x,ds; texpoly("",par(1)*par(2)*par(3)+par(4)*x); */ // last changed 10/10/10 ///////////////////////// end of latex.lib //////////////////////////////////// singular-4.0.3+ds/Singular/LIB/lejeune.lib000066400000000000000000000422621266270727000202740ustar00rootroot00000000000000////////////////////-*- mode:C++;-*- version="version lejeune.lib 4.0.0.0 Jun_2013 "; // $Id: 12e1a48cb218a96d24dd2632d03eb273769cbd38 $ category="??"; info=" LIBRARY: lejeune.lib Arc space computations AUTHOR: Nadine Cremer, nadine.cremer@gmx.de PROCEDURES: fgset(f,H); returns simultaneously the sets F and G corresponding to H as described by M. Lejeune trunc(f,i); returns the set Tr(i) as described by M. Lejeune "; LIB "ring.lib"; LIB "general.lib"; LIB "primdec.lib"; LIB "standard.lib"; LIB "sing.lib"; ////////////////////////////////////////////////////////////////////// proc trunc (poly f, int i) "USAGE: trunc(f,i); (f polynomial, i integer) CREATE: list, contains lists, each one consisting of two ideals: the first one giving equations, the second one giving inequations for a part of Tr(i). All of them together give a complete description of Tr(i) RETURN: ring, corresponds to f and i, i.e. plugging in a polynomial in t of degree i for each variable of f yields a ring whose variables are the original variables of f, t and the according t-coefficients EXAMPLE: example trunc; shows an example" { def r=basering; // we make sure that we obtain Tr(i), which requires // computations up to m*i, where m is minimal s.th. // x(j)^m in J(f) for each variable x(j) involved in f int m=minpower(f); int mi=m*i; int k; int l=order(f); int s0=mi+1; int s=l*(mi+1); int z1=nvars(r)*(i+1)+2; int z2=nvars(r)*k+1; intvec H=l; // initialization of an intvec H of size m*i for(k=1;k<=mi;k++) { H[k+1]=1; } // this is the ring in which result lies def R1=ringchange(i); setring R1; ideal I,J; list intersec=I,J; // will save the results: list fresult,gresult; list result; // consider all possible H's while(sum(H)<=s) { setring r; def tmp=fgset(f,H); setring R1; intersec=imap(tmp,fgresult); kill tmp; // simplifications intersec[1]=simplifymodd(interred(intersec[1])); intersec[2]=simplifymodd(interred(intersec[2])); //option(redSB); //intersec[1]=std(intersec[1]); //intersec[2]=std(intersec[2]); intersec[1]=simplifymodd(intersec[1]); intersec[2]=simplifymodd(intersec[2]); intersec[1]=simplifymodd(intersec[1]); intersec[2]=simplifymodd(intersec[2]); // remove lists which contain // the same ideal twice and // therefore define the empty // set if(equalitytest(intersec[1],intersec[2])==1) { H=Hnew(H); continue; } intersec[1]=radical(intersec[1]); intersec[2]=radical(intersec[2]); // remove lists which contain // the same ideal twice and // therefore define the empty // set if(equalitytest(intersec[1],intersec[2])==1) { H=Hnew(H); continue; } result=insert(result,intersec); H=Hnew(H); } // output: int u=size(result); newline; " We obtain the following sets of equations and inequations for Tr(" +string(i)+"). In order to be contained in Tr(" +string(i)+"), a point has to fulfill the conditions of one of those set, i.e. it has to be in the zero-set of the first ideal without the zero-set of the second ideal."; newline; string ending; for(k=1;k<=u;k++) { if((k mod 10==1) && (k mod 100!=11)) {ending="st";} else { if((k mod 10==2) && (k mod 100!=12)) {ending="nd";} else { if((k mod 10==3) && (k mod 100!=13)) {ending="rd";} else {ending="th";} } } print(string(k)+ending+" set of equations:"+newline); print(result[k]); newline; } // return the ring return(R1); } example { "EXAMPLE:"; echo=2; def r=basering; poly f=y2-x3; def R=trunc(f,3); setring R; print(result); setring r; def R1=trunc(f,6); setring R1; print(result); } ////////////////////////////////////////////////////////////////////// // // // COMPUTATION OF F AND G SIMULTANEOUSLY // // // ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// proc fgset (poly f,intvec H) "USAGE: fgset(f,H); f polynomial, H integer vector CREATE: list, consists two ideals, the first one giving equations, the second one giving inequations to be satisfied by the set corresponding to H RETURN: ring, corresponds to f and size(H)-1, i.e. plugging in a polynomial in t of degree size(H)-1 for each variable of f yields a ring whose variables are the original variables of f, t and the according t-coefficients EXAMPLE: example fgset; shows an example" { def r=basering; int p; int m0=order(f); int b=size(H); if(H[1]!=m0) // input admissible?! { ERROR("H[1]=ord(f) necessary"); } for(p=1;pnrows(coe)) { fkv=0; } else { fkv=coe[c+v,1]; } m=fkv; J=fkv; for(s=1;s<=k-v+1;s++) // "s<=k-v+1" special for G, ONLY DIFF.! { if(s==k-v+1) // equations for F! { fresultdiff=fresultdiff,J; } power=step^s; u=size(power); for(t=1;t<=u;t++) { diffstep=contract(power[t],m); // actual differentiation J=J,diffstep; } } gresultdiff=gresultdiff,J; } resultdiff=fresultdiff,gresultdiff; export(resultdiff); // exports the result return(R); // return the ring } ////////////////////////////////////////////////////////////////////// // // // CONSTRUCTING THE NEW RING // // // ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// static proc ringchange (int i) "USAGE: ringchange(i); i integer RETURN: ring, extends basering by variables t and #(variables of basering)*i new variables" { def R=changevar(""+varstr(basering)+",t,"+variables_list(nvars(basering),i)+""); return(R); } ////////////////////////////////////////////////////////////////////// static proc variables_list (int k,int i) "USAGE: variables_list(k,i); k,i integer RETURN: string of the names of the additional variables NOTE: called from ringchange, we use this procedure to obtain a convenient shape of the ring created in ringchange" { list l; int s,u; // loop variables string str; for (u=1;u<=k;u++) { for (s=1;s<=i;s++) { str=""+atoz(u)+"("+string(s)+")"; // creates new variables l[(u-1)*i+s]=str; // saves them in a list } } string str1=string(l); // makes the list into a string, return(str1); // (needed for ring change) } ////////////////////////////////////////////////////////////////////// static proc atoz (int n) "USAGE: atoz(n); n integer RETURN: string, the nth letter of the alphabet" { if(1>n>26) { ERROR("n must range between 1 and 26!"); } string s="ring r=0,("+A_Z("a",n)+"),ds;"; execute(s); return (string(var(n))); } ////////////////////////////////////////////////////////////////////// // // // AUXILIARY PROCEDURES // // // ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// static proc diffidealstep (int i, int N) "USAGE: diffidealstep(i,N); i,N integer RETURN: ideal, generated by variables specified by i,N NOTE: called from formaldiff, gives the variables by which is differentiated in a certain step" { ideal I=var(N+1+i); int j; for(j=2;j<=N;j++) { I=I,var(N+1+j*i); } return(I); } ////////////////////////////////////////////////////////////////////// static proc order (poly f) "USAGE: order(f); f polynomial RETURN: int, the multiplicity of V(f) in 0 NOTE: this order partly directs the differentiation in formaldiff and, together with minpower, gives the size of the integer vector in fgset" { poly g=homog(f,var(1)); int k=deg(g); int i; for(i=1;i<=k;i++) { if(jet(f,i)!=0) { return(i); } } } ////////////////////////////////////////////////////////////////////// static proc simplifyvar (ideal I) "USAGE: simplifyvar(I); I ideal RETURN: ideal defining the same zeroset as I: if any generator of I is a power of one single variable, replace it by the variable NOTE: this procedure is supposed to simplify and clarify the output of the calculations made in fgset, trunc a.o. without using radical" { int i,j; int divisornumber=0; int pos; I=simplify(I,6); for(j=1;j<=ncols(I);j++) { if(size(I[j])==1) { for(i=1;i<=nvars(basering);i++) { if(modd(I[j],var(i))==0) { divisornumber++; pos=i; } } } if(divisornumber==1) { I[j]=var(pos); } divisornumber=0; } return(I); } ////////////////////////////////////////////////////////////////////// static proc modd (poly f, poly g) "USAGE: modd(f,g); f,g polynomials RETURN: poly, f mod g modulo operation in the polynomial ring NOTE: called from idealsimplify1 where it is used to simplify a generating set of an ideal" { poly result=f-(f/g)*g; return(result); } ////////////////////////////////////////////////////////////////////// static proc Hnew (intvec H) "USAGE: Hnew(H); H integer vector RETURN: intvec, the vector needed in the following step of trunc" { intvec H1=H; int k; int l=size(H); for(k=0;k<=l-2;k++) { if(H[l-k]=1;j--) // reduce with lower elements { for(i=ncols(I);i>j;i--) { if(I[i]!=0) { I[j]=modd(I[j],I[i]); } } } I=simplify(simplifyvar(I),6); return(I); } ////////////////////////////////////////////////////////////////////// static proc minpower (poly f) "USAGE: minpower(f); f polynomial RETURN: int, the minimal z>=1 s.th. v^z in J(f) for each variable v of the basering NOTE: called from trunc, gives; together with i, the size of the integer vectors to be considered in trunc(f,i)" { ideal J=jacob(f); int s=ncols(J); int control=0; // control if conditions for ny are fulfilled int control1=0; int n=nvars(basering); int ny=1; int i,j; while (control==0) // while var(i)^ny not in J(f)... { for(i=1;i<=n;i++) // consider all variables { control1=0; for(j=1;j<=s;j++) // consider all elements of J { if (modd(var(i)^ny,J[j])==0) // var(i)^ny in J(f)? { control1=1; break; } } if (control1==0) // increment ny if no var(i)^nt in J(f) { ny++; break; } } if (control1==1) // if each step was successful... { control=1; } } return(ny); } static proc equalitytest (ideal I,ideal J) "USAGE: equalitytest(I,J); I,J ideals RETURN: 1, if I=J, 0 else NOTE: we assume I contained in J already" { int s=ncols(J); int i; int p=0; I=std(I); for(i=1;i<=s;i++) { if(reduce(J[i],I)!=0) { p=1; } } if(p==1) { return(0); } else{return(1);} } singular-4.0.3+ds/Singular/LIB/linalg.lib000066400000000000000000001335771266270727000201250ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version linalg.lib 4.0.0.0 Jun_2013 "; // $Id: 1787b6a0cf72603ecf310435b272f9bb3f2de854 $ category="Linear Algebra"; info=" LIBRARY: linalg.lib Algorithmic Linear Algebra AUTHORS: Ivor Saynisch (ivs@math.tu-cottbus.de) @* Mathias Schulze (mschulze@mathematik.uni-kl.de) PROCEDURES: inverse(A); matrix, the inverse of A inverse_B(A); list(matrix Inv,poly p),Inv*A=p*En ( using busadj(A) ) inverse_L(A); list(matrix Inv,poly p),Inv*A=p*En ( using lift ) sym_gauss(A); symmetric gaussian algorithm orthogonalize(A); Gram-Schmidt orthogonalization diag_test(A); test whether A can be diagnolized busadj(A); coefficients of Adj(E*t-A) and coefficients of det(E*t-A) charpoly(A,v); characteristic polynomial of A ( using busadj(A) ) adjoint(A); adjoint of A ( using busadj(A) ) det_B(A); determinant of A ( using busadj(A) ) gaussred(A); gaussian reduction: P*A=U*S, S a row reduced form of A gaussred_pivot(A); gaussian reduction: P*A=U*S, uses row pivoting gauss_nf(A); gaussian normal form of A mat_rk(A); rank of constant matrix A U_D_O(A); P*A=U*D*O, P,D,U,O=permutaion,diag,lower-,upper-triang pos_def(A,i); test symmetric matrix for positive definiteness hessenberg(M); Hessenberg form of M eigenvals(M); eigenvalues with multiplicities of M minipoly(M); minimal polynomial of M spnf(sp); normal form of spectrum sp spprint(sp); print spectrum sp jordan(M); Jordan data of M jordanbasis(M); Jordan basis and weight filtration of M jordanmatrix(jd); Jordan matrix with Jordan data jd jordannf(M); Jordan normal form of M "; LIB "matrix.lib"; LIB "ring.lib"; LIB "elim.lib"; LIB "general.lib"; ////////////////////////////////////////////////////////////////////////////// // help functions ////////////////////////////////////////////////////////////////////////////// static proc const_mat(matrix A) "RETURN: 1 (0) if A is (is not) a constant matrix" { int i; int n=ncols(A); def BR=basering; def @R=changeord(list(list("dp",1:nvars(basering)),list("c",0:1))); setring @R; matrix A=fetch(BR,A); for(i=1;i<=n;i=i+1){ if(deg(lead(A)[i])>=1){ //"input is not a constant matrix"; kill @R; setring BR; return(0); } } kill @R; setring BR; return(1); } ////////////////////////////////////////////////////////////////////////////// static proc red(matrix A,int i,int j) "USAGE: red(A,i,j); A = constant matrix reduces column j with respect to A[i,i] and column i reduces row j with respect to A[i,i] and row i RETURN: matrix " { module m=module(A); if(A[i,i]==0) { m[i]=m[i]+m[j]; m=module(transpose(matrix(m))); m[i]=m[i]+m[j]; m=module(transpose(matrix(m))); } A=matrix(m); m[j]=m[j]-(A[i,j]/A[i,i])*m[i]; m=module(transpose(matrix(m))); m[j]=m[j]-(A[i,j]/A[i,i])*m[i]; m=module(transpose(matrix(m))); return(matrix(m)); } ////////////////////////////////////////////////////////////////////////////// proc inner_product(vector v1,vector v2) "RETURN: inner product " { int k; if (nrows(v2)>nrows(v1)) { k=nrows(v2); } else { k=nrows(v1); } return ((transpose(matrix(v1,k,1))*matrix(v2,k,1))[1,1]); } ///////////////////////////////////////////////////////////////////////////// // user functions ///////////////////////////////////////////////////////////////////////////// proc inverse(matrix A, list #) "USAGE: inverse(A [,opt]); A a square matrix, opt integer RETURN: @format a matrix: - the inverse matrix of A, if A is invertible; - the 1x1 0-matrix if A is not invertible (in the polynomial ring!). There are the following options: - opt=0 or not given: heuristically best option from below - opt=1 : apply std to (transpose(E,A)), ordering (C,dp). - opt=2 : apply interred (transpose(E,A)), ordering (C,dp). - opt=3 : apply lift(A,E), ordering (C,dp). @end format NOTE: parameters and minpoly are allowed; opt=2 is only correct for matrices with entries in a field SEE ALSO: inverse_B, inverse_L EXAMPLE: example inverse; shows an example " { //--------------------------- initialization and check ------------------------ int ii,u,notInvertible,opt; matrix invA; int db = printlevel-voice+3; //used for comments def R = basering; int n = nrows(A); module M = A; intvec v = option(get); //get options to reset it later if ( ncols(A)!=n ) { ERROR("// ** no square matrix"); } //----------------------- choose heurisitically best option ------------------ // This may change later, depending on improvements of the implemantation // at the monent we use if opt=0 or opt not given: // opt = 1 (std) for everything // opt = 2 (interred) for nothing, NOTE: interred is ok for constant matricea // opt = 3 (lift) for nothing // NOTE: interred is ok for constant matrices only (Beispiele am Ende der lib) if(size(#) != 0) {opt = #[1];} if(opt == 0) { if(npars(R) == 0) //no parameters { if( size(ideal(A-jet(A,0))) == 0 ) //constant matrix {opt = 1;} else {opt = 1;} } else {opt = 1;} } //------------------------- change ring if necessary ------------------------- if( ordstr(R) != "C,dp(" + string(nvars(R)) + ")" ) { u=1; string mp = string(minpoly); def @R=changeord(list(list("C",0:1),list("dp",1:nvars(basering)))); setring @R; if (mp != string(minpoly)) { execute("minpoly = " + mp + ";"); } module M = fetch(R,M); } //----------------------------- opt=3: use lift ------------------------------ if( opt==3 ) { module D2; D2 = lift(M,freemodule(n)); if (size(ideal(D2))==0) { //catch error in lift dbprint(db,"// ** matrix is not invertible"); setring R; if (u==1) { kill @R;} return(invA); } } //-------------- opt = 1 resp. opt = 2: use std resp. interred -------------- if( opt==1 or opt==2 ) { option(redSB); module B = freemodule(n),M; if(opt == 2) { module D = interred(transpose(B)); D = transpose(simplify(D,1)); } if(opt == 1) { module D = std(transpose(B)); D = transpose(simplify(D,1)); } module D2 = D[1..n]; module D1 = D[n+1..2*n]; //----------------------- check if matrix is invertible ---------------------- for (ii=1; ii<=n; ii++) { if ( D1[ii] != gen(ii) ) { notInvertible = 1; break; } } } option(set,v); //------------------ return to basering and return result --------------------- if ( u==1 ) { setring R; module D2 = fetch(@R,D2); if( opt==1 or opt==2 ) { module D1 = fetch(@R,D1);} kill @R; } if( notInvertible == 1 ) { // The matrix A seems to be non-invertible. // Note that there are examples, where this is not true but only due to // inexact computations in the field of reals or complex numbers: // ring r = complex, x, dp; // The following matrix has non-zero determinante but seems non-invertible: // matrix A[3][3] = 1,i,i,0,1,2,1,0,1+i; // For this example, inverse_B yields the correct answer. // So, let's use this as a workaround whenever we have this situation: list myList = inverse_B(A); matrix Try = inverse_B(A)[1]; if (myList[2] == poly(1)) { return (Try); } else { dbprint(db,"// ** matrix is not invertible"); return(invA); } } else { return(matrix(D2)); } //matrix invertible with inverse D2 } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),lp; matrix A[3][3]= 1,4,3, 1,5,7, 0,4,17; print(inverse(A));""; matrix B[3][3]= y+1, x+y, y, z, z+1, z, y+z+2,x+y+z+2,y+z+1; print(inverse(B)); print(B*inverse(B)); } ////////////////////////////////////////////////////////////////////////////// proc sym_gauss(matrix A) "USAGE: sym_gauss(A); A = symmetric matrix RETURN: matrix, diagonalisation of A with symmetric gauss algorithm EXAMPLE: example sym_gauss; shows an example" { int i,j; int n=nrows(A); if (ncols(A)!=n) { ERROR("input is not a square matrix"); } if(!const_mat(A)) { ERROR("input is not a constant matrix"); } if(deg(std(A-transpose(A))[1])!=-1) { ERROR("input is not a symmetric matrix"); } for(i=1; i0){ "// rings with parameters not allowed"; return(-1); } //speichern des aktuellen Rings def BR=basering; //setze R[t] execute("ring rt=("+charstr(basering)+"),(@t,"+varstr(basering)+"),lp;"); execute("minpoly="+mp+";"); matrix A=imap(BR,A); intvec z; intvec s; poly X; //characteristisches Polynom poly dXdt; //Ableitung von X nach t ideal g; //ggT(X,dXdt) poly b; //Komponente der Busadjunkten-Matrix matrix E[n][n]; //Einheitsmatrix E=E+1; A=E*@t-A; X=det(A); matrix Xfactors=matrix(factorize(X,1)); //zerfaellt die Matrtix ? int nf=ncols(Xfactors); for(i=1;i<=nf;i++){ if(lead(Xfactors[1,i])>=@t^2){ //" matrix does not split"; setring BR; return(-1); } } dXdt=diff(X,@t); g=std(ideal(gcd(X,dXdt))); //Busadjunkte z=2..n; for(i=1;i<=n;i++){ s=2..n; for(j=1;j<=n;j++){ b=det(submat(A,z,s)); if(0!=reduce(b,g)){ //" matrix not diagonalizable"; setring BR; return(0); } s[j]=j; } z[i]=i; } //"Die Matrix ist diagonalisierbar"; setring BR; return(1); } example { "EXAMPLE:"; echo = 2; ring r=0,(x),dp; matrix A[4][4]=6,0,0,0,0,0,6,0,0,6,0,0,0,0,0,6; print(A); diag_test(A); } ////////////////////////////////////////////////////////////////////////////// proc busadj(matrix A) "USAGE: busadj(A); A = square matrix (of size nxn) RETURN: list L: @format L[1] contains the (n+1) coefficients of the characteristic polynomial X of A, i.e. X = L[1][1]+..+L[1][k]*t^(k-1)+..+(L[1][n+1])*t^n L[2] contains the n (nxn)-matrices Hk which are the coefficients of the busadjoint bA = adjoint(E*t-A) of A, i.e. bA = (Hn-1)*t^(n-1)+...+Hk*t^k+...+H0, ( Hk=L[2][k+1] ) @end format EXAMPLE: example busadj; shows an example" { int k; int n = nrows(A); matrix E = unitmat(n); matrix H[n][n]; matrix B[n][n]; list bA, X, L; poly a; if(ncols(A) != n) { "input is not a square matrix"; return(L); } bA = E; X[1] = 1; for(k=1; k0, det(E*v-A) is diplayed recursively. EXAMPLE: example charpoly; shows an example" { int n = nrows(A); int z = nvars(basering); int i,j; string v; poly X; if(ncols(A) != n) { "// input is not a square matrix"; return(X); } //---------------------- test for correct variable ------------------------- if( size(#)==0 ){ #[1] = varstr(z); } if( typeof(#[1]) == "string") { v = #[1]; } else { "// 2nd argument must be a name of a variable not contained in the matrix"; return(X); } j=-1; for(i=1; i<=z; i++) { if(varstr(i)==v){j=i;} } if(j==-1) { "// "+v+" is not a variable in the basering"; return(X); } if ( size(select1(module(A),j)) != 0 ) { "// matrix must not contain the variable "+v; "// change to a ring with an extra variable, if necessary." return(X); } //-------------------------- compute charpoly ------------------------------ X = det(var(j)*unitmat(n)-A); if( printlevel-voice+2 >0) { showrecursive(X,var(j));} return(X); } example { "EXAMPLE"; echo=2; ring r=0,(x,t),dp; matrix A[3][3]=1,x2,x,x2,6,4,x,4,1; print(A); charpoly(A,"t"); } ////////////////////////////////////////////////////////////////////////////// proc charpoly_B(matrix A, list #) "USAGE: charpoly_B(A[,v]); A square matrix, v string, name of a variable RETURN: poly, the characteristic polynomial det(E*v-A) (default: v=name of last variable) NOTE: A must be constant in the variable v. The computation uses busadj(A). EXAMPLE: example charpoly_B; shows an example" { int i,j; string s,v; list L; int n = nrows(A); poly X = 0; def BR = basering; if(ncols(A) != n){ "// input is not a square matrix"; return(X); } //test for correct variable if( size(#)==0 ){ #[1] = varstr(nvars(BR)); } if( typeof(#[1]) == "string"){ v = #[1]; } else{ "// 2nd argument must be a name of a variable not contained in the matrix"; return(X); } j=-1; for(i=1; i<=nvars(BR); i++){ if(varstr(i)==v){j=i;} } if(j==-1){ "// "+v+" is not a variable in the basering"; return(X); } //var cannot be in A intvec is=0:nvars(BR); is[j]=1; def @R=changeord(list(list("Wp",is))); setring @R; matrix A = imap(BR,A); for(i=1; i<=n; i++){ if(deg(lead(A)[i])>=1){ "// matrix must not contain the variable "+v; kill @R; setring BR; return(X); } } //get coefficients and build the char. poly kill @R; setring BR; L = busadj(A); for(i=1; i<=n+1; i++){ execute("X=X+L[1][i]*"+v+"^"+string(i-1)+";"); } return(X); } example { "EXAMPLE"; echo=2; ring r=0,(x,t),dp; matrix A[3][3]=1,x2,x,x2,6,4,x,4,1; print(A); charpoly_B(A,"t"); } ////////////////////////////////////////////////////////////////////////////// proc adjoint(matrix A) "USAGE: adjoint(A); A = square matrix RETURN: adjoint matrix of A, i.e. Adj*A=det(A)*E NOTE: computation uses busadj(A) EXAMPLE: example adjoint; shows an example" { int n=nrows(A); matrix Adj[n][n]; list L; if(ncols(A) != n) { "// input is not a square matrix"; return(Adj); } L = busadj(A); Adj= (-1)^(n-1)*L[2][1]; return(Adj); } example { "EXAMPLE"; echo=2; ring r=0,(t,x),lp; matrix A[2][2]=1,x2,x,x2+3x; print(A); matrix Adj[2][2]=adjoint(A); print(Adj); //Adj*A=det(A)*E print(Adj*A); } ////////////////////////////////////////////////////////////////////////////// proc inverse_B(matrix A) "USAGE: inverse_B(A); A = square matrix RETURN: list Inv with - Inv[1] = matrix I and - Inv[2] = poly p such that I*A = unitmat(n)*p; NOTE: p=1 if 1/det(A) is computable and p=det(A) if not; the computation uses busadj. SEE ALSO: inverse, inverse_L EXAMPLE: example inverse_B; shows an example" { int i; int n=nrows(A); matrix I[n][n]; poly factor; list L; list Inv; if(ncols(A) != n) { "input is not a square matrix"; return(I); } L=busadj(A); I=module(-L[2][1]); //+-Adj(A) if(reduce(1,std(L[1][1]))==0){ I=I*lift(L[1][1],1)[1][1]; factor=1; } else{ factor=L[1][1];} //=+-det(A) or 1 Inv=insert(Inv,factor); Inv=insert(Inv,matrix(I)); return(Inv); } example { "EXAMPLE"; echo=2; ring r=0,(x,y),lp; matrix A[3][3]=x,y,1,1,x2,y,x,6,0; print(A); list Inv=inverse_B(A); print(Inv[1]); print(Inv[2]); print(Inv[1]*A); } ////////////////////////////////////////////////////////////////////////////// proc det_B(matrix A) "USAGE: det_B(A); A any matrix RETURN: returns the determinant of A NOTE: the computation uses the busadj algorithm EXAMPLE: example det_B; shows an example" { int n=nrows(A); list L; if(ncols(A) != n){ return(0);} L=busadj(A); return((-1)^n*L[1][1]); } example { "EXAMPLE"; echo=2; ring r=0,(x),dp; matrix A[10][10]=random(2,10,10)+unitmat(10)*x; print(A); det_B(A); } ////////////////////////////////////////////////////////////////////////////// proc inverse_L(matrix A) "USAGE: inverse_L(A); A = square matrix RETURN: list Inv representing a left inverse of A, i.e - Inv[1] = matrix I and - Inv[2] = poly p such that I*A = unitmat(n)*p; NOTE: p=1 if 1/det(A) is computable and p=det(A) if not; the computation computes first det(A) and then uses lift SEE ALSO: inverse, inverse_B EXAMPLE: example inverse_L; shows an example" { int n=nrows(A); matrix I; matrix E[n][n]=unitmat(n); poly factor; poly d=1; list Inv; if (ncols(A)!=n){ "// input is not a square matrix"; return(I); } d=det(A); if(d==0){ "// matrix is not invertible"; return(Inv); } // test if 1/det(A) exists if(reduce(1,std(d))!=0){ E=E*d;} I=lift(A,E); if(I==unitmat(n)-unitmat(n)){ //catch error in lift "// matrix is not invertible"; return(Inv); } factor=d; //=det(A) or 1 Inv=insert(Inv,factor); Inv=insert(Inv,I); return(Inv); } example { "EXAMPLE"; echo=2; ring r=0,(x,y),lp; matrix A[3][3]=x,y,1,1,x2,y,x,6,0; print(A); list Inv=inverse_L(A); print(Inv[1]); print(Inv[2]); print(Inv[1]*A); } ////////////////////////////////////////////////////////////////////////////// proc gaussred(matrix A) "USAGE: gaussred(A); A any constant matrix RETURN: list Z: Z[1]=P , Z[2]=U , Z[3]=S , Z[4]=rank(A) gives a row reduced matrix S, a permutation matrix P and a normalized lower triangular matrix U, with P*A=U*S NOTE: This procedure is designed for teaching purposes mainly. The straight forward implementation in the interpreted library is not very efficient (no standard basis computation). EXAMPLE: example gaussred; shows an example" { int i,j,l,k,jp,rang; poly c,pivo; list Z; int n = nrows(A); int m = ncols(A); int mr= n; //max. rang matrix P[n][n] = unitmat(n); matrix U[n][n] = P; if(!const_mat(A)){ "// input is not a constant matrix"; return(Z); } if(n>m){mr=m;} //max. rang for(i=1;i<=mr;i=i+1){ if((i+k)>m){break;} //Test: Diagonalelement=0 if(A[i,i+k]==0){ jp=i;pivo=0; for(j=i+1;j<=n;j=j+1){ c=absValue(A[j,i+k]); if(pivo0 ist A[j,i]=c; // bildet U } rang=i; } for(i=1;i<=mr;i=i+1){ for(j=i+1;j<=n;j=j+1){ U[j,i]=A[j,i]; A[j,i]=0; } } Z=insert(Z,rang); Z=insert(Z,A); Z=insert(Z,U); Z=insert(Z,P); return(Z); } example { "EXAMPLE";echo=2; ring r=0,(x),dp; matrix A[5][4]=1,3,-1,4,2,5,-1,3,1,3,-1,4,0,4,-3,1,-3,1,-5,-2; print(A); list Z=gaussred(A); //construct P,U,S s.t. P*A=U*S print(Z[1]); //P print(Z[2]); //U print(Z[3]); //S print(Z[4]); //rank print(Z[1]*A); //P*A print(Z[2]*Z[3]); //U*S } ////////////////////////////////////////////////////////////////////////////// proc gaussred_pivot(matrix A) "USAGE: gaussred_pivot(A); A any constant matrix RETURN: list Z: Z[1]=P , Z[2]=U , Z[3]=S , Z[4]=rank(A) gives a row reduced matrix S, a permutation matrix P and a normalized lower triangular matrix U, with P*A=U*S NOTE: with row pivoting EXAMPLE: example gaussred_pivot; shows an example" { int i,j,l,k,jp,rang; poly c,pivo; list Z; int n=nrows(A); int m=ncols(A); int mr=n; //max. rang matrix P[n][n]=unitmat(n); matrix U[n][n]=P; if(!const_mat(A)){ "// input is not a constant matrix"; return(Z); } if(n>m){mr=m;} //max. rang for(i=1;i<=mr;i=i+1){ if((i+k)>m){break;} //Pivotisierung pivo=absValue(A[i,i+k]);jp=i; for(j=i+1;j<=n;j=j+1){ c=absValue(A[j,i+k]); if(pivo0 ist A[j,i]=c; // bildet U } rang=i; } for(i=1;i<=mr;i=i+1){ for(j=i+1;j<=n;j=j+1){ U[j,i]=A[j,i]; A[j,i]=0; } } Z=insert(Z,rang); Z=insert(Z,A); Z=insert(Z,U); Z=insert(Z,P); return(Z); } example { "EXAMPLE";echo=2; ring r=0,(x),dp; matrix A[5][4] = 1, 3,-1,4, 2, 5,-1,3, 1, 3,-1,4, 0, 4,-3,1, -3,1,-5,-2; list Z=gaussred_pivot(A); //construct P,U,S s.t. P*A=U*S print(Z[1]); //P print(Z[2]); //U print(Z[3]); //S print(Z[4]); //rank print(Z[1]*A); //P*A print(Z[2]*Z[3]); //U*S } ////////////////////////////////////////////////////////////////////////////// proc gauss_nf(matrix A) "USAGE: gauss_nf(A); A any constant matrix RETURN: matrix; gauss normal form of A (uses gaussred) EXAMPLE: example gauss_nf; shows an example" { list Z; if(!const_mat(A)){ "// input is not a constant matrix"; return(A); } Z = gaussred(A); return(Z[3]); } example { "EXAMPLE";echo=2; ring r = 0,(x),dp; matrix A[4][4] = 1,4,4,7,2,5,5,4,4,1,1,3,0,2,2,7; print(gauss_nf(A)); } ////////////////////////////////////////////////////////////////////////////// proc mat_rk(matrix A) "USAGE: mat_rk(A); A any constant matrix RETURN: int, rank of A EXAMPLE: example mat_rk; shows an example" { list Z; if(!const_mat(A)){ "// input is not a constant matrix"; return(-1); } Z = gaussred(A); return(Z[4]); } example { "EXAMPLE";echo=2; ring r = 0,(x),dp; matrix A[4][4] = 1,4,4,7,2,5,5,4,4,1,1,3,0,2,2,7; mat_rk(A); } ////////////////////////////////////////////////////////////////////////////// proc U_D_O(matrix A) "USAGE: U_D_O(A); constant invertible matrix A RETURN: list Z: Z[1]=P , Z[2]=U , Z[3]=D , Z[4]=O gives a permutation matrix P, a normalized lower triangular matrix U , a diagonal matrix D, and a normalized upper triangular matrix O with P*A=U*D*O NOTE: Z[1]=-1 means that A is not regular (proc uses gaussred) EXAMPLE: example U_D_O; shows an example" { int i,j; list Z,L; int n=nrows(A); matrix O[n][n]=unitmat(n); matrix D[n][n]; if (ncols(A)!=n){ "// input is not a square matrix"; return(Z); } if(!const_mat(A)){ "// input is not a constant matrix"; return(Z); } L=gaussred(A); if(L[4]!=n){ "// input is not an invertible matrix"; Z=insert(Z,-1); //hint for calling procedures return(Z); } D=L[3]; for(i=1; i<=n; i++){ for(j=i+1; j<=n; j++){ O[i,j] = D[i,j]/D[i,i]; D[i,j] = 0; } } Z=insert(Z,O); Z=insert(Z,D); Z=insert(Z,L[2]); Z=insert(Z,L[1]); return(Z); } example { "EXAMPLE";echo=2; ring r = 0,(x),dp; matrix A[5][5] = 10, 4, 0, -9, 8, -3, 6, -6, -4, 9, 0, 3, -1, -9, -8, -4,-2, -6, -10,10, -9, 5, -1, -6, 5; list Z = U_D_O(A); //construct P,U,D,O s.t. P*A=U*D*O print(Z[1]); //P print(Z[2]); //U print(Z[3]); //D print(Z[4]); //O print(Z[1]*A); //P*A print(Z[2]*Z[3]*Z[4]); //U*D*O } ////////////////////////////////////////////////////////////////////////////// proc pos_def(matrix A) "USAGE: pos_def(A); A = constant, symmetric square matrix RETURN: int: 1 if A is positive definit , 0 if not, -1 if unknown EXAMPLE: example pos_def; shows an example" { int j; list Z; int n = nrows(A); matrix H[n][n]; if (ncols(A)!=n){ "// input is not a square matrix"; return(0); } if(!const_mat(A)){ "// input is not a constant matrix"; return(-1); } if(deg(std(A-transpose(A))[1])!=-1){ "// input is not a hermitian (symmetric) matrix"; return(-1); } Z=U_D_O(A); if(Z[1]==-1){ return(0); } //A not regular, therefore not pos. definit H=Z[1]; //es fand Zeilentausch statt: also nicht positiv definit if(deg(std(H-unitmat(n))[1])!=-1){ return(0); } H=Z[3]; for(j=1;j<=n;j=j+1){ if(H[j,j]<=0){ return(0); } //eigenvalue<=0, not pos.definit } return(1); //positiv definit; } example { "EXAMPLE"; echo=2; ring r = 0,(x),dp; matrix A[5][5] = 20, 4, 0, -9, 8, 4, 12, -6, -4, 9, 0, -6, -2, -9, -8, -9, -4, -9, -20, 10, 8, 9, -8, 10, 10; pos_def(A); matrix B[3][3] = 3, 2, 0, 2, 12, 4, 0, 4, 2; pos_def(B); } ////////////////////////////////////////////////////////////////////////////// proc linsolve(matrix A, matrix b) "USAGE: linsolve(A,b); A a constant nxm-matrix, b a constant nx1-matrix RETURN: a 1xm matrix X, solution of inhomogeneous linear system A*X = b return the 0-matrix if system is not solvable NOTE: uses gaussred EXAMPLE: example linsolve; shows an example" { int i,j,k,rc,r; poly c; list Z; int n = nrows(A); int m = ncols(A); int n_b= nrows(b); matrix Ab[n][m+1]; matrix X[m][1]; if(ncols(b)!=1){ "// right hand side b is not a nx1 matrix"; return(X); } if(!const_mat(A)){ "// input hand is not a constant matrix"; return(X); } if(n_b>n){ for(i=n; i<=n_b; i++){ if(b[i,1]!=0){ "// right hand side b not in Image(A)"; return X; } } } if(n_b=1;i=i-1){ j=1; while(Ab[i,j]==0){j=j+1;}// suche Ecke for(;k>j;k=k-1){ X[k]=0;}//springe zur Ecke c=Ab[i,m+1]; //i-te Komponene von b for(j=m;j>k;j=j-1){ c=c-X[j,1]*Ab[i,j]; } if(Ab[i,k]==0){ X[k,1]=1; //willkuerlich } else{ X[k,1]=c/Ab[i,k]; } k=k-1; if(k==0){break;} } }//endif (const b) else{ //b not constant "// !not implemented!"; } return(X); } example { "EXAMPLE";echo=2; ring r=0,(x),dp; matrix A[3][2] = -4,-6, 2, 3, -5, 7; matrix b[3][1] = 10, -5, 2; matrix X = linsolve(A,b); print(X); print(A*X); } ////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // PROCEDURES for Jordan normal form // AUTHOR: Mathias Schulze, email: mschulze@mathematik.uni-kl.de /////////////////////////////////////////////////////////////////////////////// static proc rowcolswap(matrix M,int i,int j) { if(system("with","eigenval")) { return(system("rowcolswap",M,i,j)); } //-------------------------------------------- if(i==j) { return(M); } poly p; for(int k=1;k<=nrows(M);k++) { p=M[i,k]; M[i,k]=M[j,k]; M[j,k]=p; } for(k=1;k<=ncols(M);k++) { p=M[k,i]; M[k,i]=M[k,j]; M[k,j]=p; } return(M); } ////////////////////////////////////////////////////////////////////////////// static proc rowelim(matrix M,int i,int j,int k) { if(system("with","eigenval")) { return(system("rowelim",M,i,j,k)); } // ----------------------- if(jet(M[i,k],0)==0||jet(M[j,k],0)==0) { return(M); } number n=number(jet(M[i,k],0))/number(jet(M[j,k],0)); for(int l=1;l<=ncols(M);l++) { M[i,l]=M[i,l]-n*M[j,l]; } for(l=1;l<=nrows(M);l++) { M[l,j]=M[l,j]+n*M[l,i]; } return(M); } /////////////////////////////////////////////////////////////////////////////// static proc colelim(matrix M,int i,int j,int k) { if(jet(M[k,i],0)==0||jet(M[k,j],0)==0) { return(M); } number n=number(jet(M[k,i],0))/number(jet(M[k,j],0)); for(int l=1;l<=nrows(M);l++) { M[l,i]=M[l,i]-n*M[l,j]; } for(l=1;l<=ncols(M);l++) { M[j,l]=M[j,l]+n*M[i,l]; } return(M); } /////////////////////////////////////////////////////////////////////////////// proc hessenberg(matrix M) "USAGE: hessenberg(M); matrix M ASSUME: M constant square matrix RETURN: matrix H; Hessenberg form of M EXAMPLE: example hessenberg; shows examples " { if(system("with","eigenval")) { return(system("hessenberg",M)); } int n=ncols(M); int i,j; for(int k=1;k=1;i--) { e0=number(jet(l[1][i]/var(1),0)); if(e0!=0) { k++; e[k]=(e0*var(1)-l[1][i])/e0; m[k]=l[2][i]; } } } } return(spnf(list(e,m))); } example { "EXAMPLE:"; echo=2; ring R=0,x,dp; matrix M[3][3]=3,2,1,0,2,1,0,0,3; print(M); eigenvals(M); } /////////////////////////////////////////////////////////////////////////////// proc minipoly(matrix M,list #) "USAGE: minipoly(M); matrix M ASSUME: eigenvalues of M in basefield RETURN: @format list l; minimal polynomial of M ideal l[1]; number l[1][i]; i-th root of minimal polynomial of M intvec l[2]; int l[2][i]; multiplicity of i-th root of minimal polynomial of M @end format EXAMPLE: example minipoly; shows examples " { if(nrows(M)==0) { ERROR("non empty expected"); } if(ncols(M)!=nrows(M)) { ERROR("square matrix expected"); } M=jet(M,0); if(size(#)==0) { #=eigenvals(M); } def e0,m0=#[1..2]; intvec m1; matrix N0,N1; for(int i=1;i<=ncols(e0);i++) { m1[i]=1; N0=M-e0[i]; N1=N0; while(size(syz(N1))=1;j--) { V[j]=module(v[j]); } } if(typeof(sp[i])=="list") { V=sp[i]; } } if(m==0) { for(i=n;i>=1;i--) { m[i]=1; } } int k; ideal a0; intvec m0; list V0; number a1; int m1; for(i=n;i>=1;i--) { if(m[i]!=0) { for(j=i-1;j>=1;j--) { if(m[j]!=0) { if(number(a[i])>number(a[j])) { a1=number(a[i]); a[i]=a[j]; a[j]=a1; m1=m[i]; m[i]=m[j]; m[j]=m1; if(size(V)>0) { v=V[i]; V[i]=V[j]; V[j]=v; } } if(number(a[i])==number(a[j])) { m[i]=m[i]+m[j]; m[j]=0; if(size(V)>0) { V[i]=V[i]+V[j]; } } } } k++; a0[k]=a[i]; m0[k]=m[i]; if(size(V)>0) { V0[k]=V[i]; } } } if(size(V0)>0) { n=size(V0); module U=std(V0[n]); for(i=n-1;i>=1;i--) { V0[i]=simplify(reduce(V0[i],U),1); if(i>=2) { U=std(U+V0[i]); } } } if(k>0) { sp=a0,m0; if(size(V0)>0) { sp[3]=V0; } } return(sp); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; list sp=list(ideal(-1/2,-3/10,-3/10,-1/10,-1/10,0,1/10,1/10,3/10,3/10,1/2)); spprint(spnf(sp)); } /////////////////////////////////////////////////////////////////////////////// proc spprint(list sp) "USAGE: spprint(sp); list sp (helper routine for spnf) RETURN: string s; spectrum sp EXAMPLE: example spprint; shows examples SEE ALSO: gmssing_lib, spnf " { string s; for(int i=1;i0) { ERROR("eigenvalues in coefficient field expected"); return(list()); } } int j,k; matrix N0,N1; module K0; list K; ideal e; intvec s,m; for(i=1;i<=ncols(e0);i++) { N0=M-e0[i]*matrix(freemodule(ncols(M))); N1=N0; K0=0; K=module(); while(size(K0)0) { k++; e[k]=e0[i]; s[k]=j-1; m[k]=2*size(K[j])-size(K[j-1])-size(K[j+1]); } } if(size(K[j])-size(K[j-1])>0) { k++; e[k]=e0[i]; s[k]=j-1; m[k]=size(K[j])-size(K[j-1]); } } return(list(e,s,m)); } example { "EXAMPLE:"; echo=2; ring R=0,x,dp; matrix M[3][3]=3,2,1,0,2,1,0,0,3; print(M); jordan(M); } /////////////////////////////////////////////////////////////////////////////// proc jordanbasis(matrix M,list #) "USAGE: jordanbasis(M); matrix M ASSUME: eigenvalues of M in basefield RETURN: @format list l: module l[1]; inverse(l[1])*M*l[1] in Jordan normal form intvec l[2]; int l[2][i]; weight filtration index of l[1][i] @end format EXAMPLE: example jordanbasis; shows examples " { if(nrows(M)==0) { ERROR("non empty matrix expected"); } if(ncols(M)!=nrows(M)) { ERROR("square matrix expected"); } M=jet(M,0); if(size(#)==0) { #=eigenvals(M); } def e,m=#[1..2]; for(int i=1;i<=ncols(e);i++) { if(deg(e[i])>0) { ERROR("eigenvalues in coefficient field expected"); return(freemodule(ncols(M))); } } int j,k,l,n; matrix N0,N1; module K0,K1; list K; matrix u[ncols(M)][1]; module U; intvec w; for(i=1;i<=ncols(e);i++) { N0=M-e[i]*matrix(freemodule(ncols(M))); N1=N0; K0=0; K=list(); while(size(K0)=1;l--) { for(k=size(K[l]);k>0;k--) { u=K[l][k]; for(j=l;j>=1;j--) { U=U+module(u); n++; w[n]=2*j-l-1; u=N0*u; } } } } return(list(U,w)); } example { "EXAMPLE:"; echo=2; ring R=0,x,dp; matrix M[3][3]=3,2,1,0,2,1,0,0,3; print(M); list l=jordanbasis(M); print(l[1]); print(l[2]); print(inverse(l[1])*M*l[1]); } /////////////////////////////////////////////////////////////////////////////// proc jordanmatrix(list jd) "USAGE: jordanmatrix(list(e,s,m)); ideal e, intvec s, intvec m ASSUME: ncols(e)==size(s)==size(m) RETURN: @format matrix J; Jordan matrix with list(e,s,m)==jordan(J) @end format EXAMPLE: example jordanmatrix; shows examples " { ideal e=jd[1]; intvec s=jd[2]; intvec m=jd[3]; if(ncols(e)!=size(s)||ncols(e)!=size(m)) { ERROR("arguments of equal size expected"); } int i,j,k,l; int n=int((transpose(matrix(s))*matrix(m))[1,1]); matrix J[n][n]; for(k=1;k<=ncols(e);k++) { for(l=1;l<=m[k];l++) { j++; J[j,j]=e[k]; for(i=s[k];i>=2;i--) { J[j+1,j]=1; j++; J[j,j]=e[k]; } } } return(J); } example { "EXAMPLE:"; echo=2; ring R=0,x,dp; ideal e=ideal(2,3); intvec s=1,2; intvec m=1,1; print(jordanmatrix(list(e,s,m))); } /////////////////////////////////////////////////////////////////////////////// proc jordannf(matrix M,list #) "USAGE: jordannf(M); matrix M ASSUME: eigenvalues of M in basefield RETURN: matrix J; Jordan normal form of M EXAMPLE: example jordannf; shows examples " { return(jordanmatrix(jordan(M,#))); } example { "EXAMPLE:"; echo=2; ring R=0,x,dp; matrix M[3][3]=3,2,1,0,2,1,0,0,3; print(M); print(jordannf(M)); } /////////////////////////////////////////////////////////////////////////////// /* /////////////////////////////////////////////////////////////////////////////// // Auskommentierte zusaetzliche Beispiele // /////////////////////////////////////////////////////////////////////////////// // Singular for ix86-Linux version 1-3-10 (2000121517) Dec 15 2000 17:55:12 // Rechnungen auf AMD700 mit 632 MB LIB "linalg.lib"; 1. Sparse integer Matrizen -------------------------- ring r1=0,(x),dp; system("--random", 12345678); int n = 70; matrix m = sparsemat(n,n,50,100); option(prot,mem); int t=timer; matrix im = inverse(m,1)[1]; timer-t; print(im*m); //list l0 = watchdog(100,"inverse("+"m"+",3)"); //bricht bei 100 sec ab und gibt l0[1]: string Killed zurueck //inverse(m,1): std 5sec 5,5 MB //inverse(m,2): interred 12sec //inverse(m,2): lift nach 180 sec 13MB abgebrochen //n=60: linalgorig: 3 linalg: 5 //n=70: linalgorig: 6,7 linalg: 11,12 // aber linalgorig rechnet falsch! 2. Sparse poly Matrizen ----------------------- ring r=(0),(a,b,c),dp; system("--random", 12345678); int n=6; matrix m = sparsematrix(n,n,2,0,50,50,9); //matrix of polys of deg <=2 option(prot,mem); int t=timer; matrix im = inverse(m); timer-t; print(im*m); //inverse(m,1): std 0sec 1MB //inverse(m,2): interred 0sec 1MB //inverse(m,2): lift nach 2000 sec 33MB abgebrochen 3. Sparse Matrizen mit Parametern --------------------------------- //liborig rechnet hier falsch! ring r=(0),(a,b),dp; system("--random", 12345678); int n=7; matrix m = sparsematrix(n,n,1,0,40,50,9); ring r1 = (0,a,b),(x),dp; matrix m = imap(r,m); option(prot,mem); int t=timer; matrix im = inverse(m); timer-t; print(im*m); //inverse(m)=inverse(m,3):15 sec inverse(m,1)=1sec inverse(m,2):>120sec //Bei Parametern vergeht die Zeit beim Normieren! 3. Sparse Matrizen mit Variablen und Parametern ----------------------------------------------- ring r=(0),(a,b),dp; system("--random", 12345678); int n=6; matrix m = sparsematrix(n,n,1,0,35,50,9); ring r1 = (0,a),(b),dp; matrix m = imap(r,m); option(prot,mem); int t=timer; matrix im = inverse(m,3); timer-t; print(im*m); //n=7: inverse(m,3):lange sec inverse(m,1)=1sec inverse(m,2):1sec 4. Ueber Polynomring invertierbare Matrizen ------------------------------------------- LIB"random.lib"; LIB"linalg.lib"; system("--random", 12345678); int n =3; ring r= 0,(x,y,z),(C,dp); matrix A=triagmatrix(n,n,1,0,0,50,2); intmat B=sparsetriag(n,n,20,1); matrix M = A*transpose(B); M=M*transpose(M); M[1,1..ncols(M)]=M[1,1..n]+xyz*M[n,1..ncols(M)]; print(M); //M hat det=1 nach Konstruktion int t=timer; matrix iM=inverse(M); timer-t; print(iM*M); //test //ACHTUNG: Interred liefert i.A. keine Inverse, Gegenbeispiel z.B. //mit n=3 //eifacheres Gegenbeispiel: matrix M = 9yz+3y+3z+2, 9y2+6y+1, 9xyz+3xy+3xz-9z2+2x-6z-1,9xy2+6xy-9yz+x-3y-3z //det M=1, inverse(M,2); ->// ** matrix is not invertible //lead(M); 9xyz*gen(2) 9xy2*gen(2) nicht teilbar! 5. charpoly: ----------- //ring rp=(0,A,B,C),(x),dp; ring r=0,(A,B,C,x),dp; matrix m[12][12]= AC,BC,-3BC,0,-A2+B2,-3AC+1,B2, B2, 1, 0, -C2+1,0, 1, 1, 2C, 0,0, B, -A, -4C, 2A+1,0, 0, 0, 0, 0, 0, 1,0, 2C+1, -4C+1,-A, B+1, 0, B+1, 3B, AB,B2,0, 1,0, 1, 0, 1, A, 0, 1, B+1, 1, 0, 1, 0,0, 1, 0, -C2, 0, 1, 0, 1, 0, 0, 2, 1,2A, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1,1, 2, A, 3B+1,1, B2,1, 1, 0, 1, 0, 1,1, 1, 1, 1, 2, 0, 0, 0, 1, 0, 1, 0,0, 0, 1, 0, 1, 1, 0, 3, 1, 3B,B2+1,0,0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0,0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,1, 3, 3B+1, 0, 1, 1, 1, 0; option(prot,mem); int t=timer; poly q=charpoly(m,"x"); //1sec, charpoly_B 1sec, 16MB timer-t; //1sec, charpoly_B 1sec, 16MB (gleich in r und rp) */ singular-4.0.3+ds/Singular/LIB/locnormal.lib000066400000000000000000000337371266270727000206420ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version locnormal.lib 4.0.0.0 Jun_2013 "; // $Id: d7b9364557cfbbc62149afd7081cf35838b30e95 $ category="Commutative Algebra"; info=" LIBRARY: locnormal.lib Normalization of affine domains using local methods AUTHORS: J. Boehm boehm@mathematik.uni-kl.de W. Decker decker@mathematik.uni-kl.de S. Laplagne slaplagn@dm.uba.ar G. Pfister pfister@mathematik.uni-kl.de S. Steidel steidel@mathematik.uni-kl.de A. Steenpass steenpass@mathematik.uni-kl.de OVERVIEW: Suppose A is an affine domain over a perfect field.@* This library implements a local-to-global strategy for finding the normalization of A. Following [1], the idea is to stratify the singular locus of A, apply the normalization algorithm given in [2] locally at each stratum, and put the local results together. This approach is inherently parallel.@* Furthermore we allow for the optional modular computation of the local results as provided by modnormal.lib. See again [1] for details. REFERENCES: [1] Janko Boehm, Wolfram Decker, Santiago Laplagne, Gerhard Pfister, Stefan Steidel, Andreas Steenpass: Parallel algorithms for normalization, http://arxiv.org/abs/1110.4299, 2011. [2] Gert-Martin Greuel, Santiago Laplagne, Frank Seelisch: Normalization of Rings, Journal of Symbolic Computation 9 (2010), p. 887-901 KEYWORDS: normalization; local methods; modular methods SEE ALSO: normal_lib, modnormal_lib PROCEDURES: locNormal(I, [...]); normalization of R/I using local methods "; LIB "normal.lib"; LIB "sing.lib"; LIB "modstd.lib"; static proc changeDenom(ideal U1, poly c1, poly c2, ideal I){ // Given a ring in the form 1/c1 * U, it computes a new ideal U2 such that the // ring is 1/c2 * U2. // The base ring is R, but the computations are to be done in R / I. int a; // counter def R = basering; qring Q = groebner(I); ideal U1 = fetch(R, U1); poly c1 = fetch(R, c1); poly c2 = fetch(R, c2); ideal U2 = changeDenomQ(U1, c1, c2); setring R; ideal U2 = fetch(Q, U2); return(U2); } /////////////////////////////////////////////////////////////////////////////// static proc changeDenomQ(ideal U1, poly c1, poly c2){ // Given a ring in the form 1/c1 * U, it computes a new U2 st the ring // is 1/c2 * U2. // The base ring is already a quotient ring R / I. int a; // counter ideal U2; poly p; for(a = 1; a <= ncols(U1); a++){ p = lift(c1, c2*U1[a])[1,1]; U2[a] = p; } return(U2); } ///////////////////////////////////////////////////////////////////////////////// proc locNormal(ideal I, list #) "USAGE: locNormal(I [,options]); I = prime ideal, options = list of options. @* Optional parameters in list options (can be entered in any order):@* modular: use a modular approach for the local computations. The number of primes is increased one at a time, starting with 2 primes, until the result stabelizes.@* noVerificication: if the modular approach is used, the result will not be verified. ASSUME: I is a prime ideal (the algorithm will also work for radical ideals as long as the normal command does not detect that the ideal under consideration is not prime). RETURN: a list of an ideal U and a universal denominator d such that U/d is the normalization. REMARKS: We use the local-to-global algorithm given in [1] to compute the normalization of A = R/I, where R is the basering.@* The idea is to stratify the singular locus of A, apply the normalization algorithm given in [2] locally at each stratum, and put the local results together.@* If the option modular is given, the result is returned as a probabilistic result or verified, depending on whether the option noVerificication is used or not.@* The normalization of A is represented as an R-module by returning a list of U and d, where U is an ideal of A and d is an element of A such that U/d is the normalization of A. In fact, U and d are returned as an ideal and a polynomial of the base ring R. REFERENCES: [1] Janko Boehm, Wolfram Decker, Santiago Laplagne, Gerhard Pfister, Stefan Steidel, Andreas Steenpass: Parallel algorithms for normalization, http://arxiv.org/abs/1110.4299, 2011.@* [2] Gert-Martin Greuel, Santiago Laplagne, Frank Seelisch: Normalization of Rings, Journal of Symbolic Computation 9 (2010), p. 887-901 KEYWORDS: normalization; local methods; modular methods. SEE ALSO: normal_lib, modnormal_lib. EXAMPLE: example locNormal; shows an example " { // Computes the normalization by localizing at the different components of the singularity. int i; int totalLocalTime; int dbg = printlevel - voice + 2; def R = basering; int totalTime = timer; intvec LTimer; int t; int printTimings=0; int locmod; for ( i=1; i <= size(#); i++ ) { if ( typeof(#[i]) == "string" ) { if (#[i]=="modular") { locmod = 1;} if (#[i]=="printTimings") { printTimings = 1;} } } // Computes the Singular Locus list IM = mstd(I); I = IM[1]; int d = dim(I); ideal IMin = IM[2]; qring Q = I; // We work in the quotient by the groebner base of the ideal I option("redSB"); option("returnSB"); ideal I = fetch(R, I); attrib(I, "isSB", 1); ideal IMin = fetch(R, IMin); dbprint(dbg, "Computing the jacobian ideal..."); ideal J = minor(jacob(IMin), nvars(basering) - d, I); t=timer; int ch = char(basering); if (ch==0) {J = modStd(J);} else {J = std(J);} if (printTimings==1) {"Time for modStd/std Jacobian "+string(timer-t);} setring R; ideal J = fetch(Q, J); // We compute a universal denominator poly condu = getSmallest(J); J = J, I; if(dbg >= 2){ "Conductor: ", condu; "The original singular locus is"; groebner(J); if(dbg >= 2){pause();} ""; } t=timer; list pd = locIdeals(J); dbprint(dbg,pd); if (printTimings==1) { "Number of maximal components to localize at: ", size(pd); ""; } ideal U; ideal resT; ideal resu; poly denomOld; poly denom; totalLocalTime = timer; int maxLocalTime; list Lnor; list parallelArguments; for(i = 1; i <= size(pd); i++){ parallelArguments[i] = list(pd[i], I, condu, i, locmod, printTimings, #); } list parallelResults = parallelWaitAll("locNormal_parallelTask", parallelArguments); for(i = 1; i <= size(pd); i++){ // We sum the result to the previous results. resu = resu, parallelResults[i][1]; Lnor[i] = parallelResults[i][1]; if(parallelResults[i][2] > maxLocalTime) { maxLocalTime = parallelResults[i][2]; } LTimer[i] = parallelResults[i][2]; } if (printTimings==1) { "List of local times: "; LTimer; "Maximal local time: "+string(maxLocalTime); } totalLocalTime = timer - totalLocalTime; if (printTimings==1) { "Total time local computations: "+string(totalLocalTime); } t=timer; if (ch==0) {resu = modStd(resu);} else {resu = std(resu);} if (printTimings==1) { "Time for combining the local results, modStd/std "+string(timer-t); } totalTime = timer - totalTime; if (printTimings==1) { "Total time locNormal: "+string(totalTime); "Simulated parallel time: "+string(totalTime + maxLocalTime - totalLocalTime); } return(list(resu, condu)); } example { "EXAMPLE:"; ring R = 0,(x,y,z),dp; int k = 4; poly f = (x^(k+1)+y^(k+1)+z^(k+1))^2-4*(x^(k+1)*y^(k+1)+y^(k+1)*z^(k+1)+z^(k+1)*x^(k+1)); f = subst(f,z,3x-2y+1); ring S = 0,(x,y),dp; poly f = imap(R,f); ideal i = f; list L = locNormal(i); } proc locNormal_parallelTask(ideal pdi, ideal I, poly condu, int i, int locmod, int printTimings, list #) { pdi=pdi; int t = timer; list opt = list(list("inputJ", pdi)) + #; if (printTimings==1) { "Local component ",i," of degree "+string(deg(pdi))+" and dimension " +string(dim(pdi)); } list n; ideal norT; poly denomT; if (locmod==1) { n = modNormal(I,1, opt); norT = n[1]; denomT = n[2]; } else { n = normal(I,opt); if(size(n[2]) > 1){ ERROR("Input was not prime..."); } norT = n[2][1]; denomT = norT[size(norT)]; } t = timer-t; // We compute the normalization of I localized at a component of the Singular // Locus if (printTimings==1) { "Output of normalization of component ", i, ": "; norT; ""; } ideal nor = changeDenom(norT, denomT, condu, I); return(list(nor, t)); } static proc locComps(list l) { int d = size(l); int i; int j; intvec m = 1:d; // 1 = maximal ideal ideal IT; // Check for maximal ideals for(i = 1; i0){ k = find(S,dummy); L = size(dummy); if(k+L<=size(S)){ S = S[1,k-1] + origin + S[k+L..size(S)]; } else{S = S[1,k-1] + origin;} } return(S); } proc mathmlRingType(){ string S = charstr(basering); int i = find(S,","); int n; if(i>0){S = S[1,i-1];} if(S=="real" || S =="complex"){return(0)} else{ if (npars(basering)>0) { n=ringlist(basering)[1][1]; if (n!=0 && prime(n)!=n) {return(2);} else {return(1);}} else {return(1);} } } /********************************************************* ** ** ** POLY ** ** ** *********************************************************/ proc mathmlLeadCoef(string s) { string t; int i=1; int u=0; if (s=="1"){return(t);} if (s=="-1"){return("-");} while (i "; while (i<=size(s)) { if (s[i]=="/") {t=t+" ";} else {t=t+s[i];} i=i+1; } t=t+" "; } if (u==0) { if (s[1]=="-") {t=t+"-";s=s[2,size(s)-1];} t=t+""+s+"";} return(t); } proc mathmlVariablesEncoding(string s) { string S; int p; if(s[size(s)]==")"){ p = find(s,"("); S = S + ""+s[1,p-1] + "" + s[p+1,size(s)-p-1]+ ""; } else{ if (size(s)>1) { S = S + ""+s[1] + "" + s[2,size(s)-1]+ "";} else {S=""+s+"";} } return(S); } proc mathmlMonomial(poly a) { string g; intvec d=leadexp(a); list e; for(int q=1;q<=size(variables(a));q++) { e[q]=variables(a)[q]; } int k=1; for(int i=1;i<=size(d);i++) { if (d[i]>0) { g=g+""+mathmlVariablesEncoding(string(e[k]))+""; if (d[i]>1) {g=g+string(d[i]);} g=g+""; k=k+1;} } return(g); } proc mathmlHilf1(poly a,def r) { poly d=a; list l1=ringlist(r); list l12=ringlist(r); for(int i=1;i<=size(l12[1][2]);i++) { l12[2][i]=l12[1][2][i]+"1"; l12[1][2][i]=l12[1][2][i]+"0"; } def w=ring(l12); setring(w); poly f=fetch(r,d); list l12=ringlist(basering); for (i=1;i<=size(l12[1][2]);i++) { f=subst(f,par(i),var(i)); } while (size(l12[2])>size(l12[1][2])) { l12[2]=delete(l12[2],size(l12[1][2])+1); } for (i=1;i<=size(l12[2]);i++) { l12[2][i]=l12[2][i][1,size(l12[2][i])-1]; } l12[1]=l12[1][1]; def w2=ring(l12); setring(w2); keepring(w2); poly f=fetch(w,f); return(f); } proc mathmlHilf(poly a,def r) { string g; def f=mathmlHilf1(a,r); g=g+mathmlPoly(f,basering); return(g); } proc SignumLeadcoef(poly a) { int n=0; def f=mathmlHilf1(a,basering); if (string(leadcoef(f))[1,1]=="-") { n=1; } return(n); } proc mathmlPolyGAL(poly p){ string S; for(int i = 1;i+";} } S = S+ mathmlTermGAL(p[i]); return(S); } proc mathmlTermGAL(poly p){ int b = 0; int B = 0; string S,S1,C,Pname; Pname = ringlist(basering)[1][2][1]; C = string(leadcoef(p)); C = mathmlStringReplace(C,Pname,""); C = mathmlStringReplace(C,"^",""); if (p==-1 || p==1 || p==0) {return(""+string(p)+"");} else { if (C=="-1") {S=S+"-";} else { if (C!="1") {S =S+ ""+Pname+""+C +"";} } S=S+mathmlMonomial(leadmonom(p)); return(S); } } proc mathmlPolyR(poly a) { string S; def origin = basering; if(npars(origin) == 0){ list l = ringlist(basering); l[1][3] = "parTMP"; def ringCOMPLEX = ring(l); setring ringCOMPLEX; poly a = fetch(origin,a); } string S1; string S2; poly d; string s; for (int i=1;i<=size(a);i++) { S2=""; d=a[i]; s=string(leadcoef(d)); if (s[1]=="-" || s[2]=="-") {S=S+"-";d=-1*d;} else {S=S+"+";} S1=mathmlMonomial(leadmonom(d)); if (leadcoef(d)==1) { if (S1=="") {S=S+"1";} } else { s=string(leadcoef(d)); S2=mathmlStringReplace(s,"*1)",")"); S2=mathmlStringReplace(S2,"*",""); if (npars(basering)==1) { if (find(S2,string(par(1)))>0) { S2=mathmlStringReplace(S2,string(par(1)),""); if (size(S2)>0) {S2=S2[1,size(S2)-1]+string(par(1))+")";} else {S2=string(par(1));} } } } S=S+S2+S1; } if (S[1,10]=="+") {S=S[11..size(S)];} return(S); } proc mathmlPolyN(poly a,def r){ string g; number d=leadcoef(a); list l12=ringlist(r); int n=npars(basering); if (n>0) { if (SignumLeadcoef(numerator(d))) { g=g+"-"; d=-d; } if (d!=1) { if (denominator(d)==1) { def f=mathmlHilf1(d,r); if (leadexp(f)==0) {setring r; g=g+mathmlHilf(d,r);} else {setring r; g=g+"("+mathmlHilf(d,r)+")";} } else {g=g+""+mathmlHilf(numerator(d),r)+""+mathmlHilf(denominator(d),r)+"";} } } else { g=g+mathmlLeadCoef(string(leadcoef(a))); } setring(r); if (a==1 || a==-1) {g=g+"1";} g=g+mathmlMonomial(leadmonom(a)); a=a-lead(a); if (a!=0) { if (n==0) {if (poly(leadcoef(a))>0) {g=g+"+";}} else {if (SignumLeadcoef(numerator(leadcoef(a)))==0) {g=g+"+";}} g=g+mathmlPolyN(a,r); } return(g); } proc mathmlPoly(poly d) { string g=""; if (mathmlRingType()==0) {g=g+mathmlPolyR(d);} if (mathmlRingType()==2) {g=g+mathmlPolyGAL(d);} if (mathmlRingType()==1) {g=g+mathmlPolyN(d,basering);} g=g+""; return(g); } example { "EXAMPLE:"; echo=2; string h; ring r = (0,a),(x1,x2),dp; h=h+mathmlPoly(x1+a2)+"
"; h=h+mathmlPoly(x1*x2^3)+"
"; ring r=(0,a,b),(x(1..2)),lp; poly z=(3*a^2-12*b)*x(1)^2*x(2)+(3*a^3-1)*x(2)+x(1)^2-3/5*x(1)+1; h=h+mathmlPoly(z)+"
"; ring r=(0,a),(x,y),lp; poly z=(15*a^3+11*a-2)/(7*a^2+2)*x^2*y^3+13/7*x; h=h+mathmlPoly(z)+"
"; ring r=(13,s(1..2)),(y(1..2)),lp; poly z=(2*s(1)^4)*y(1)^3*y(2)-s(1)*s(2)*y(2)^4+(11*s(1)^3-2*s(2)^2+11*s(1)*s(2))*y(1)^2-s(2)*y(2)-3*y(2)+4; h=h+mathmlPoly(z)+"
"; ring r=(11,y(1..2)),(x(1..3)),lp; poly z=2*x(1)^3*x(3)-(2/(y(1)^2*y(2)^2+3))*x(2)^2; h=h+mathmlPoly(z)+"
"; ring r=integer,(v,x,y),lp; poly z=15*v^2*x^2*y^2-11*x*y; h=h+mathmlPoly(z)+"
"; ring r=(3^4,a),x,lp; poly z=a59*x2+a41; h=h+mathmlPoly(z)+"
"; ring r=real,(x,y),lp; poly z=3.334*x^2*y^3-4*y^2; h=h+mathmlPoly(z)+"
"; ring r=(real,15,a),(x(1..4)),lp; poly z=(5.2+11.11*a)*x(1)*x(4)^4-(2.333+1.344*a)*x(2); h=h+mathmlPoly(z)+"
"; ring r=complex,x,dp; poly z=(3.4-3.5*i)*x^5+(11.4*i)*x^4-3.552*x^3+1; h=h+mathmlPoly(z)+"
"; ring r=(complex,a),(ba,bb,bc),dp; poly z=(3.4-11*a)*ba^2*bb^2+4.555*ba^3; h=h+mathmlPoly(z); viewMathml(h); } /********************************************************* ** ** ** ring ** ** ** *********************************************************/ proc mathmlRing(def r) "USAGE: texRing(r); where r is a ring ASSUME: r is a ring RETURN: lateX-code for the ring r THEORY: KEYWORDS: ring, lateX, teX, tex, latex EXAMPLE: example texRing; shows an example " { setring r; list l,l1,l2; l = ringlist(r); l2 = ringlist(r)[2]; string c,p,P,V,C,S,h; int i,b; int bchar; list l3=l; l3[4]=ideal(0); def w=ring(l3); setring w; list l=fetch(r,l); setring r; //characteristic c = charstr(r); bchar = 0; if(find(c,",") != 0){ c = c[1,find(c,",")-1]; b = 0; if(typeof(l[1][2][1]) != "string" && b==0&& c =="integer"){bchar= 1;b = 1;} if(typeof(l[1][2][1]) != "string" && b==0){bchar = 2;b=1;} if(b==0){ if (mathmlRingType()==2) {bchar = 4;} else {bchar=3;} } } //minimalpolynom p = string(minpoly); //parameters if(bchar==3){ if(p != "0"){P=P+"[";} else{P=P+"(";} for(i=1;i(") {h=h[11..size(h)-10];} P=P + "]/{"+h+"}"; setring(r); } else{P=P+")";} } //variables V = V + "["; for(i = 1;i"+string(l[1][2][1])+""+string(l[1][2][2])+""; } else{C=C+""+""+string(l[1][2][1])+"";} b = 1; } else{C = C + "";b=1;} //Z } if(c == "0" && b == 0){C = C + "";b=1;} //Q if(c == "real" && b == 0){C = C + "";b=1;} //R if(c == "complex" && b == 0){ b=1; if(typeof(l[1][3]) != "none"){ if(l[1][3]!="i"){C = C + "("+l[1][3]+")";} //R(j) else{C = C + "";} } else{C = C + "F"+c+"";} //F/p else {C = C + ""+c+"";b=1;} //Z/p } //epic conclusion if(size(P)!=0){S = S + C+P+V;} else{S=S+C+V;} if (l[4]!=0) { setring w; S=S+"/("; for(int k=1;k<=size(l[4]);k++) { h=mathmlPoly(l[4][k]); h=h[48..size(h)-7]; S=S+h+","; } S=S[1,size(S)-10]+")"; } S = "" + S + ""; return(S); } example { "EXAMPLE:"; echo=2; string h; ring r = 32003,(x,y,z),dp; h=h+mathmlRing(r)+"
"; ring r = 32003,(x(1..10)),dp; h=h+mathmlRing(r)+"
"; ring r = 0,(a,b,c,d),lp; h=h+mathmlRing(r)+"
"; ring r =7,(x,y,z),ds; h=h+mathmlRing(r)+"
"; ring r = 7,(x(1..6)),(lp(3),dp); h=h+mathmlRing(r)+"
"; ring r =0,(x,y,z),(c,wp(2,1,3)); h=h+mathmlRing(r)+"
"; ring r =(7,a,b,c),(x,y,z),Dp; h=h+mathmlRing(r)+"
"; ring r =(7,a),(x,y,z),dp; minpoly = a^2+a+3; h=h+mathmlRing(r)+"
"; ring r =real,(x,y,z),dp; h=h+mathmlRing(r)+"
"; ring r =(real,50),(x,y,z),dp; h=h+mathmlRing(r)+"
"; ring r =(real,10,50),(x,y,z),dp; h=h+mathmlRing(r)+"
"; ring r = (complex,30,j),(x,y,z),dp; h=h+mathmlRing(r)+"
"; ring r =complex,(x,y,z),dp; h=h+mathmlRing(r)+"
"; ring r =7,(x,y,z), dp; h=h+mathmlRing(r)+"
"; ring r =integer,(x,y,z), dp; h=h+mathmlRing(r)+"
"; ring r =(integer, 6, 3),(x,y,z), dp; h=h+mathmlRing(r)+"
"; ring r =(integer, 100),(x,y,z), dp; h=h+mathmlRing(r)+"
"; ring r=(121,a),x,lp; h=h+mathmlRing(r); viewMathml(h); } /********************************************************* ** ** ** map ** ** ** *********************************************************/ proc mathmlMap(map f, list #)"USAGE: texMap(f, #); #[1] source XOR texMap(f),if source == target ASSUME: f is a map, #[1] ring or empty RETURN: lateX-code for the map f THEORY: KEYWORDS: map, lateX, teX, tex, latex EXAMPLE: example texMap; shows an example " { // f: s--->r (rings) || f:s1--->s2 (string) string s1,s2; string h1,h2; string T,S; //variables, output string s2 = mathmlRing(basering); s2 = s2[48,size(s2)-54]; int B = 0; int b = 0; if(nameof(basering)==nameof(preimage(f))){b=1;} def r = basering; if(size(#)!=0){ if(typeof(#[1]) != "ring"){return("ERROR - wrong input. check texMap documentation." );} def s; s = #[1]; setring s; s1 = mathmlRing(s); s1 = s1[48,size(s1)-54]; list l1; for(int k=1;k<=nvars(s);k++){ l1[k] = mathmlVariablesEncoding(string(var(k))); } setring r; for(int i = 1;i<=nvars(s);i++){ h1=mathmlPoly(f[i]); h2=h1[48,size(h1)-54]; T =T+ ""+l1[i]+""+""+""+h2+""; } } else{ if(b==1){ mathmlMap(f,basering); return(); } else{ s1 = "'"+nameof(preimage(f))+"'"; print("For detailed information we need the source"); B = 1; } } S = ""+s1+"" + "" +""+ s2+""+T; S = "" + S + ""; return(S); } example { "EXAMPLE:"; echo=2; string h; ring U = 0,(x,y,z),lp; ring M2 = real,(z(1..3)),lp; setring M2; map f = U,z(1)*z(2)^3,z(1),-z(2); h=h+mathmlMap(f)+"
"; //2nd h=h+mathmlMap(f,U)+"
"; //3rd ring R = real,(x,y,z),lp; map f2 = R,x2,y2,z-x; h=h+string(mathmlMap(f2)); viewMathml(h);} /********************************************************* ** ** ** IDEAL ** ** ** *********************************************************/ proc mathmlIdeal(ideal I)"USAGE: texIdeal(I), where I is an ideal ASSUME: I is an ideal RETURN: lateX-code for the ideal I THEORY: KEYWORDS: ideal, lateX, teX, tex, latex EXAMPLE: example texIdeal; shows an example "{ string S = ""; for(int i = 1;i⟩"; return(S); } example {"EXAMPLE: "; echo=2; ring r = 0,(x,y,z),dp; ideal I = x2,y3,z; viewMathml(mathmlIdeal(I)); } /********************************************************* ** ** ** LIST ** ** ** *********************************************************/ proc mathmlList(list l)"USAGE: texList(l), where l is a list ASSUME: l is a list RETURN: lateX-code for the list l THEORY: KEYWORDS: list, lateX, teX, tex, latex EXAMPLE: example texList; shows an example "{ string tmp; string S = ""; for(int i=1;i}";; return(S); } example {"EXAMPLE:"; echo=2; string h; //int ring r = integer,(x,y,z),dp; list l = 1,2,3; h=h+mathmlList(l)+"
"; //ring ring r2 = real,(a,b,c),dp; ring r3 = complex,(x(1..3)),dp; list l2 = r,r2,r3; h=h+mathmlList(l2)+"
"; //matrix setring r; matrix m1[2][2]=x2y,-xz3,0,17x3z2; matrix m2[2][2]=1,2,3,4; list l3 = m1,m2; h=h+mathmlList(l3); //poly poly p = x2-1; poly p2 = x3-y+z; poly p3 = y3-z7; list l4 = p,p2,p3; //mathmlList(l4); viewMathml(h); } /********************************************************* ** ** ** BIGINT,INT ** ** ** *********************************************************/ proc mathmlBigInt (bigint I){ return(""+string(I)+""); } proc mathmlInt(int I){ return(mathmlBigInt(I)); } /********************************************************* ** ** ** STRING ** ** ** *********************************************************/ proc mathmlString(string m){ return(m); } /********************************************************* ** ** ** NUMBER ** ** ** **requires: mathmlPoly - since there might be a parameter ** *********************************************************/ proc mathmlNumber(number n){ string S; S = mathmlPoly(n); return(S); } /********************************************************* ** ** ** VECTOR, INTVEC ** ** INTMAT, BIGINTMAT, MATRIX ** ** ** *********************************************************/ proc mathmlVector(vector v){ int L = size(v); matrix m[L][1] = v; string S = mathmlMatrix(m); return(S); } proc mathmlIntvec(intvec v){ matrix m = v; string S = mathmlMatrix(m); return(S); } proc mathmlIntmat(intmat M){ matrix m = M; string S = mathmlMatrix(m); return(S); } proc mathmlBigintmat(bigintmat M){ matrix m = M; string S = mathmlMatrix(m); return(S); } proc mathmlMatrix(matrix m){ string s,h; int i=1; int j=1; s=s+"("; while (i<=nrows(m)) { j=1; s=s+""; while (j<=ncols(m)) { h=mathmlPoly(m[i,j]); s=s+""+h[48,size(h)-54]+""; j=j+1; } s=s+""; i=i+1; } s=s+")"; return(s); } /********************************************************* ** ** ** View ** ** ** *********************************************************/ proc viewMathml(string s){ string p = "firefox"; string Sstart = "MathML Examples"; string Send = " "; string S = Sstart + s + Send; write(":w singular_mathml.html", S); system("sh",p+" singular_mathml.html"); } singular-4.0.3+ds/Singular/LIB/matrix.lib000066400000000000000000001166531266270727000201570ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version matrix.lib 4.0.0.0 Jun_2013 "; // $Id: 92849631fbe0c7b8e6b2b1315b241bbd69578007 $ category="Linear Algebra"; info=" LIBRARY: matrix.lib Elementary Matrix Operations PROCEDURES: compress(A); matrix, zero columns from A deleted concat(A1,A2,..); matrix, concatenation of matrices A1,A2,... diag(p,n); matrix, nxn diagonal matrix with entries poly p dsum(A1,A2,..); matrix, direct sum of matrices A1,A2,... flatten(A); ideal, generated by entries of matrix A genericmat(n,m[,id]); generic nxm matrix [entries from id] is_complex(c); 1 if list c is a complex, 0 if not outer(A,B); matrix, outer product of matrices A and B power(A,n); matrix/intmat, n-th power of matrix/intmat A skewmat(n[,id]); generic skew-symmetric nxn matrix [entries from id] submat(A,r,c); submatrix of A with rows/cols specified by intvec r/c symmat(n[,id]); generic symmetric nxn matrix [entries from id] tensor(A,B); matrix, tensor product of matrices A nd B unitmat(n); unit square matrix of size n gauss_col(A); transform a matrix into col-reduced Gauss normal form gauss_row(A); transform a matrix into row-reduced Gauss normal form addcol(A,c1,p,c2); add p*(c1-th col) to c2-th column of matrix A, p poly addrow(A,r1,p,r2); add p*(r1-th row) to r2-th row of matrix A, p poly multcol(A,c,p); multiply c-th column of A with poly p multrow(A,r,p); multiply r-th row of A with poly p permcol(A,i,j); permute i-th and j-th columns permrow(A,i,j); permute i-th and j-th rows rowred(A[,any]); reduction of matrix A with elementary row-operations colred(A[,any]); reduction of matrix A with elementary col-operations linear_relations(E); find linear relations between homogeneous vectors rm_unitrow(A); remove unit rows and associated columns of A rm_unitcol(A); remove unit columns and associated rows of A headStand(A); A[n-i+1,m-j+1]:=A[i,j] symmetricBasis(n,k[,s]); basis of k-th symmetric power of n-dim v.space exteriorBasis(n,k[,s]); basis of k-th exterior power of n-dim v.space symmetricPower(A,k); k-th symmetric power of a module/matrix A exteriorPower(A,k); k-th exterior power of a module/matrix A (parameters in square brackets [] are optional) "; LIB "inout.lib"; LIB "ring.lib"; LIB "random.lib"; LIB "general.lib"; // for sort LIB "nctools.lib"; // for superCommutative /////////////////////////////////////////////////////////////////////////////// proc compress (def A) "USAGE: compress(A); A matrix/ideal/module/intmat/intvec RETURN: same type, zero columns/generators from A deleted (if A=intvec, zero elements are deleted) EXAMPLE: example compress; shows an example " { if( typeof(A)=="matrix" ) { return(matrix(simplify(A,2))); } if( typeof(A)=="intmat" or typeof(A)=="intvec" ) { ring r=0,x,lp; if( typeof(A)=="intvec" ) { intmat C=transpose(A); kill A; intmat A=C; } module m = matrix(A); if ( size(m) == 0) { intmat B; } else { intmat B[nrows(A)][size(m)]; } int i,j; for( i=1; i<=ncols(A); i++ ) { if( m[i]!=[0] ) { j++; B[1..nrows(A),j]=A[1..nrows(A),i]; } } if( defined(C) ) { return(intvec(B)); } return(B); } return(simplify(A,2)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),ds; matrix A[3][4]=1,0,3,0,x,0,z,0,x2,0,z2,0; print(A); print(compress(A)); module m=module(A); show(m); show(compress(m)); intmat B[3][4]=1,0,3,0,4,0,5,0,6,0,7,0; compress(B); intvec C=0,0,1,2,0,3; compress(C); } /////////////////////////////////////////////////////////////////////////////// proc concat (list #) "USAGE: concat(A1,A2,..); A1,A2,... matrices RETURN: matrix, concatenation of A1,A2,.... Number of rows of result matrix is max(nrows(A1),nrows(A2),...) EXAMPLE: example concat; shows an example " { int i; for( i=size(#);i>0; i-- ) { #[i]=module(#[i]); } module B=#[1..size(#)]; return(matrix(B)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),ds; matrix A[3][3]=1,2,3,x,y,z,x2,y2,z2; matrix B[2][2]=1,0,2,0; matrix C[1][4]=4,5,x,y; print(A); print(B); print(C); print(concat(A,B,C)); } /////////////////////////////////////////////////////////////////////////////// proc diag (list #) "USAGE: diag(p,n); p poly, n integer diag(A); A matrix RETURN: diag(p,n): diagonal matrix, p times unit matrix of size n. @* diag(A) : n*m x n*m diagonal matrix with entries all the entries of the nxm matrix A, taken from the 1st row, 2nd row etc of A EXAMPLE: example diag; shows an example " { if( size(#)==2 ) { return(matrix(#[1]*freemodule(#[2]))); } if( size(#)==1 ) { int i; ideal id=#[1]; int n=ncols(id); matrix A[n][n]; for( i=1; i<=n; i++ ) { A[i,i]=id[i]; } } return(A); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),ds; print(diag(xy,4)); matrix A[3][2] = 1,2,3,4,5,6; print(A); print(diag(A)); } /////////////////////////////////////////////////////////////////////////////// proc dsum (list #) "USAGE: dsum(A1,A2,..); A1,A2,... matrices RETURN: matrix, direct sum of A1,A2,... EXAMPLE: example dsum; shows an example " { int i,N,a; list L; for( i=1; i<=size(#); i++ ) { N=N+nrows(#[i]); } for( i=1; i<=size(#); i++ ) { matrix B[N][ncols(#[i])]; B[a+1..a+nrows(#[i]),1..ncols(#[i])]=#[i]; a=a+nrows(#[i]); L[i]=B; kill B; } return(concat(L)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),ds; matrix A[3][3] = 1,2,3,4,5,6,7,8,9; matrix B[2][2] = 1,x,y,z; print(A); print(B); print(dsum(A,B)); } /////////////////////////////////////////////////////////////////////////////// proc flatten (def A) "USAGE: flatten(A); A matrix RETURN: ideal, generated by all entries from A EXAMPLE: example flatten; shows an example " { return(ideal(A)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),ds; matrix A[2][3] = 1,2,x,y,z,7; print(A); flatten(A); } /////////////////////////////////////////////////////////////////////////////// proc genericmat (int n,int m,list #) "USAGE: genericmat(n,m[,id]); n,m=integers, id=ideal RETURN: nxm matrix, with entries from id. NOTE: if id has less than nxm elements, the matrix is filled with 0's, (default: id=maxideal(1)). genericmat(n,m); creates the generic nxm matrix EXAMPLE: example genericmat; shows an example " { if( size(#)==0 ) { ideal id=maxideal(1); } if( size(#)==1 ) { ideal id=#[1]; } if( size(#)>=2 ) { "// give 3 arguments, 3-rd argument must be an ideal"; } matrix B[n][m]=id; return(B); } example { "EXAMPLE:"; echo = 2; ring R = 0,x(1..16),lp; print(genericmat(3,3)); // the generic 3x3 matrix ring R1 = 0,(a,b,c,d),dp; matrix A = genericmat(3,4,maxideal(1)^3); print(A); int n,m = 3,2; ideal i = ideal(randommat(1,n*m,maxideal(1),9)); print(genericmat(n,m,i)); // matrix of generic linear forms } /////////////////////////////////////////////////////////////////////////////// proc is_complex (list c) "USAGE: is_complex(c); c = list of size-compatible modules or matrices RETURN: 1 if c[i]*c[i+1]=0 for all i, 0 if not, hence checking whether the list of matrices forms a complex. NOTE: Ideals are treated internally as 1-line matrices. If printlevel > 0, the position where c is not a complex is shown. EXAMPLE: example is_complex; shows an example " { int i; module @test; for( i=1; i<=size(c)-1; i++ ) { c[i]=matrix(c[i]); c[i+1]=matrix(c[i+1]); @test=c[i]*c[i+1]; if (size(@test)!=0) { dbprint(printlevel-voice+2,"// not a complex at position " +string(i)); return(0); } } return(1); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(x,y,z),ds; ideal i = x4+y5+z6,xyz,yx2+xz2+zy7; list L = nres(i,0); is_complex(L); L[4] = matrix(i); is_complex(L); } /////////////////////////////////////////////////////////////////////////////// proc outer (matrix A, matrix B) "USAGE: outer(A,B); A,B matrices RETURN: matrix, outer (tensor) product of A and B EXAMPLE: example outer; shows an example " { int i,j; list L; int triv = nrows(B)*ncols(B); if( triv==1 ) { return(B[1,1]*A); } else { int N = nrows(A)*nrows(B); matrix C[N][ncols(B)]; for( i=ncols(A);i>0; i-- ) { for( j=1; j<=nrows(A); j++ ) { C[(j-1)*nrows(B)+1..j*nrows(B),1..ncols(B)]=A[j,i]*B; } L[i]=C; } return(concat(L)); } } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),ds; matrix A[3][3]=1,2,3,4,5,6,7,8,9; matrix B[2][2]=x,y,0,z; print(A); print(B); print(outer(A,B)); } /////////////////////////////////////////////////////////////////////////////// proc power (def A, int n) "USAGE: power(A,n); A a square-matrix of type intmat or matrix, n=integer>=0 RETURN: intmat resp. matrix, the n-th power of A NOTE: for A=intmat and big n the result may be wrong because of int overflow EXAMPLE: example power; shows an example " { //---------------------------- type checking ---------------------------------- if( typeof(A)!="matrix" and typeof(A)!="intmat" ) { ERROR("no matrix or intmat!"); } if( ncols(A) != nrows(A) ) { ERROR("not a square matrix!"); } //---------------------------- trivial cases ---------------------------------- int ii; if( n <= 0 ) { if( typeof(A)=="matrix" ) { return (unitmat(nrows(A))); } if( typeof(A)=="intmat" ) { intmat B[nrows(A)][nrows(A)]; for( ii=1; ii<=nrows(A); ii++ ) { B[ii,ii] = 1; } return (B); } } if( n == 1 ) { return (A); } //---------------------------- sub procedure ---------------------------------- proc matpow (def A, int n) { def B = A*A; int ii= 2; int jj= 4; while( jj <= n ) { B=B*B; ii=jj; jj=2*jj; } return(B,n-ii); } //----------------------------- main program ---------------------------------- list L = matpow(A,n); def B = L[1]; ii = L[2]; while( ii>=2 ) { L = matpow(A,ii); B = B*L[1]; ii= L[2]; } if( ii == 0) { return(B); } if( ii == 1) { return(A*B); } } example { "EXAMPLE:"; echo = 2; intmat A[3][3]=1,2,3,4,5,6,7,8,9; print(power(A,3));""; ring r=0,(x,y,z),dp; matrix B[3][3]=0,x,y,z,0,0,y,z,0; print(power(B,3));""; } /////////////////////////////////////////////////////////////////////////////// proc skewmat (int n, list #) "USAGE: skewmat(n[,id]); n integer, id ideal RETURN: skew-symmetric nxn matrix, with entries from id (default: id=maxideal(1)) skewmat(n); creates the generic skew-symmetric matrix NOTE: if id has less than n*(n-1)/2 elements, the matrix is filled with 0's, EXAMPLE: example skewmat; shows an example " { matrix B[n][n]; if( size(#)==0 ) { ideal id=maxideal(1); } else { ideal id=#[1]; } id = id,B[1..n,1..n]; int i,j; for( i=0; i<=n-2; i++ ) { B[i+1,i+2..n]=id[j+1..j+n-i-1]; j=j+n-i-1; } matrix A=transpose(B); B=B-A; return(B); } example { "EXAMPLE:"; echo = 2; ring R=0,x(1..5),lp; print(skewmat(4)); // the generic skew-symmetric matrix ring R1 = 0,(a,b,c),dp; matrix A=skewmat(4,maxideal(1)^2); print(A); int n=3; ideal i = ideal(randommat(1,n*(n-1) div 2,maxideal(1),9)); print(skewmat(n,i)); // skew matrix of generic linear forms kill R1; } /////////////////////////////////////////////////////////////////////////////// proc submat (matrix A, intvec r, intvec c) "USAGE: submat(A,r,c); A=matrix, r,c=intvec RETURN: matrix, submatrix of A with rows specified by intvec r and columns specified by intvec c. EXAMPLE: example submat; shows an example " { matrix B[size(r)][size(c)]=A[r,c]; return(B); } example { "EXAMPLE:"; echo = 2; ring R=32003,(x,y,z),lp; matrix A[4][4]=x,y,z,0,1,2,3,4,5,6,7,8,9,x2,y2,z2; print(A); intvec v=1,3,4; matrix B=submat(A,v,1..3); print(B); } /////////////////////////////////////////////////////////////////////////////// proc symmat (int n, list #) "USAGE: symmat(n[,id]); n integer, id ideal RETURN: symmetric nxn matrix, with entries from id (default: id=maxideal(1)) NOTE: if id has less than n*(n+1)/2 elements, the matrix is filled with 0's, symmat(n); creates the generic symmetric matrix EXAMPLE: example symmat; shows an example " { matrix B[n][n]; if( size(#)==0 ) { ideal id=maxideal(1); } else { ideal id=#[1]; } id = id,B[1..n,1..n]; int i,j; for( i=0; i<=n-1; i++ ) { B[i+1,i+1..n]=id[j+1..j+n-i]; j=j+n-i; } matrix A=transpose(B); for( i=1; i<=n; i++ ) { A[i,i]=0; } B=A+B; return(B); } example { "EXAMPLE:"; echo = 2; ring R=0,x(1..10),lp; print(symmat(4)); // the generic symmetric matrix ring R1 = 0,(a,b,c),dp; matrix A=symmat(4,maxideal(1)^3); print(A); int n=3; ideal i = ideal(randommat(1,n*(n+1) div 2,maxideal(1),9)); print(symmat(n,i)); // symmetric matrix of generic linear forms kill R1; } /////////////////////////////////////////////////////////////////////////////// proc tensor (matrix A, matrix B) "USAGE: tensor(A,B); A,B matrices RETURN: matrix, tensor product of A and B EXAMPLE: example tensor; shows an example " { if (ncols(A)==0) { int q=nrows(A)*nrows(B); matrix D[q][0]; return(D); } int i,j; matrix C,D; for( i=1; i<=nrows(A); i++ ) { C = A[i,1]*B; for( j=2; j<=ncols(A); j++ ) { C = concat(C,A[i,j]*B); } D = concat(D,transpose(C)); } D = transpose(D); return(submat(D,2..nrows(D),1..ncols(D))); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),(c,ds); matrix A[3][3]=1,2,3,4,5,6,7,8,9; matrix B[2][2]=x,y,0,z; print(A); print(B); print(tensor(A,B)); } /////////////////////////////////////////////////////////////////////////////// proc unitmat (int n) "USAGE: unitmat(n); n integer >= 0 RETURN: nxn unit matrix NOTE: needs a basering, diagonal entries are numbers (=1) in the basering EXAMPLE: example unitmat; shows an example " { return(matrix(freemodule(n))); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),lp; print(xyz*unitmat(4)); print(unitmat(5)); } /////////////////////////////////////////////////////////////////////////////// proc gauss_col (matrix A, list #) "USAGE: gauss_col(A[,e]); A a matrix, e any type RETURN: - a matrix B, if called with one argument; B is the complete column- reduced upper-triangular normal form of A if A is constant, (resp. as far as this is possible if A is a polynomial matrix; no division by polynomials). @* - a list L of two matrices, if called with two arguments; L satisfies L[1] = A * L[2] with L[1] the column-reduced form of A and L[2] the transformation matrix. NOTE: * The procedure just applies interred to A with ordering (C,dp). The transformation matrix is obtained by applying 'lift'. This should be faster than the procedure colred. @* * It should only be used with exact coefficient field (there is no pivoting and rounding error treatment). @* * Parameters are allowed. Hence, if the entries of A are parameters, B is the column-reduced form of A over the rational function field. SEE ALSO: colred EXAMPLE: example gauss_col; shows an example " { def R=basering; int u; string mp = string(minpoly); int n = nrows(A); int m = ncols(A); module M = A; intvec v = option(get); //------------------------ change ordering if necessary ---------------------- if( ordstr(R) != ("C,dp("+string(nvars(R))+")") ) { def @R=changeord(list(list("C",0:1),list("dp",1:nvars(R))),R); setring @R; u=1; if (mp!="0") { execute("minpoly="+mp+";");} matrix A = imap(R,A); module M = A; } //------------------------------ start computation --------------------------- option(redSB); M = simplify(interred(M),1); if(size(#) != 0) { module N = lift(A,M); } //--------------- reset ring and options and return -------------------------- if ( u==1 ) { setring R; M=imap(@R,M); if (size(#) != 0) { module N = imap(@R,N); } kill @R; } option(set,v); // M = sort(M,size(M)..1)[1]; A = matrix(M,n,m); if (size(#) != 0) { list L= A,matrix(N,m,m); return(L); } return(matrix(M,n,m)); } example { "EXAMPLE:"; echo = 2; ring r=(0,a,b),(A,B,C),dp; matrix m[8][6]= 0, 2*C, 0, 0, 0, 0, 0, -4*C,a*A, 0, 0, 0, b*B, -A, 0, 0, 0, 0, -A, B, 0, 0, 0, 0, -4*C, 0, B, 2, 0, 0, 2*A, B, 0, 0, 0, 0, 0, 3*B, 0, 0, 2b, 0, 0, AB, 0, 2*A,A, 2a;""; list L=gauss_col(m,1); print(L[1]); print(L[2]); ring S=0,x,(c,dp); matrix A[5][4] = 3, 1, 1, 1, 13, 8, 6,-7, 14,10, 6,-7, 7, 4, 3,-3, 2, 1, 0, 3; print(gauss_col(A)); } /////////////////////////////////////////////////////////////////////////////// proc gauss_row (matrix A, list #) "USAGE: gauss_row(A [,e]); A matrix, e any type RETURN: - a matrix B, if called with one argument; B is the complete row- reduced lower-triangular normal form of A if A is constant, (resp. as far as this is possible if A is a polynomial matrix; no division by polynomials). @* - a list L of two matrices, if called with two arguments; L satisfies transpose(L[2])*A=transpose(L[1]) with L[1] the row-reduced form of A and L[2] the transformation matrix. NOTE: * This procedure just applies gauss_col to the transposed matrix. The transformation matrix is obtained by applying lift. This should be faster than the procedure rowred. @* * It should only be used with exact coefficient field (there is no pivoting and rounding error treatment). @* * Parameters are allowed. Hence, if the entries of A are parameters, B is the row-reduced form of A over the rational function field. SEE ALSO: rowred EXAMPLE: example gauss_row; shows an example " { if(size(#) > 0) { list L = gauss_col(transpose(A),1); return(L); } A = gauss_col(transpose(A)); return(transpose(A)); } example { "EXAMPLE:"; echo = 2; ring r=(0,a,b),(A,B,C),dp; matrix m[6][8]= 0, 0, b*B, -A,-4C,2A,0, 0, 2C,-4C,-A,B, 0, B, 3B,AB, 0,a*A, 0, 0, B, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2A, 0, 0, 0, 0, 0, 0, 2b, A, 0, 0, 0, 0, 0, 0, 0, 2a;""; print(gauss_row(m));""; ring S=0,x,dp; matrix A[4][5] = 3, 1,1,-1,2, 13, 8,6,-7,1, 14,10,6,-7,1, 7, 4,3,-3,3; list L=gauss_row(A,1); print(L[1]); print(L[2]); } /////////////////////////////////////////////////////////////////////////////// proc addcol (matrix A, int c1, poly p, int c2) "USAGE: addcol(A,c1,p,c2); A matrix, p poly, c1, c2 positive integers RETURN: matrix, A being modified by adding p times column c1 to column c2 EXAMPLE: example addcol; shows an example " { int k=nrows(A); A[1..k,c2]=A[1..k,c2]+p*A[1..k,c1]; return(A); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),lp; matrix A[3][3]=1,2,3,4,5,6,7,8,9; print(A); print(addcol(A,1,xy,2)); } /////////////////////////////////////////////////////////////////////////////// proc addrow (matrix A, int r1, poly p, int r2) "USAGE: addrow(A,r1,p,r2); A matrix, p poly, r1, r2 positive integers RETURN: matrix, A being modified by adding p times row r1 to row r2 EXAMPLE: example addrow; shows an example " { int k=ncols(A); A[r2,1..k]=A[r2,1..k]+p*A[r1,1..k]; return(A); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),lp; matrix A[3][3]=1,2,3,4,5,6,7,8,9; print(A); print(addrow(A,1,xy,3)); } /////////////////////////////////////////////////////////////////////////////// proc multcol (matrix A, int c, poly p) "USAGE: multcol(A,c,p); A matrix, p poly, c positive integer RETURN: matrix, A being modified by multiplying column c by p EXAMPLE: example multcol; shows an example " { int k=nrows(A); A[1..k,c]=p*A[1..k,c]; return(A); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),lp; matrix A[3][3]=1,2,3,4,5,6,7,8,9; print(A); print(multcol(A,2,xy)); } /////////////////////////////////////////////////////////////////////////////// proc multrow (matrix A, int r, poly p) "USAGE: multrow(A,r,p); A matrix, p poly, r positive integer RETURN: matrix, A being modified by multiplying row r by p EXAMPLE: example multrow; shows an example " { int k=ncols(A); A[r,1..k]=p*A[r,1..k]; return(A); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),lp; matrix A[3][3]=1,2,3,4,5,6,7,8,9; print(A); print(multrow(A,2,xy)); } /////////////////////////////////////////////////////////////////////////////// proc permcol (matrix A, int c1, int c2) "USAGE: permcol(A,c1,c2); A matrix, c1,c2 positive integers RETURN: matrix, A being modified by permuting columns c1 and c2 EXAMPLE: example permcol; shows an example " { matrix B=A; int k=nrows(B); B[1..k,c1]=A[1..k,c2]; B[1..k,c2]=A[1..k,c1]; return(B); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),lp; matrix A[3][3]=1,x,3,4,y,6,7,z,9; print(A); print(permcol(A,2,3)); } /////////////////////////////////////////////////////////////////////////////// proc permrow (matrix A, int r1, int r2) "USAGE: permrow(A,r1,r2); A matrix, r1,r2 positive integers RETURN: matrix, A being modified by permuting rows r1 and r2 EXAMPLE: example permrow; shows an example " { matrix B=A; int k=ncols(B); B[r1,1..k]=A[r2,1..k]; B[r2,1..k]=A[r1,1..k]; return(B); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),lp; matrix A[3][3]=1,2,3,x,y,z,7,8,9; print(A); print(permrow(A,2,1)); } /////////////////////////////////////////////////////////////////////////////// proc rowred (matrix A,list #) "USAGE: rowred(A[,e]); A matrix, e any type RETURN: - a matrix B, being the row reduced form of A, if rowred is called with one argument. (as far as this is possible over the polynomial ring; no division by polynomials) @* - a list L of two matrices, such that L[1] = L[2] * A with L[1] the row-reduced form of A and L[2] the transformation matrix (if rowred is called with two arguments). ASSUME: The entries of A are in the base field. It is not verified whether this assumption holds. NOTE: * This procedure is designed for teaching purposes mainly. @* * The straight forward Gaussian algorithm is implemented in the library (no standard basis computation). The transformation matrix is obtained by concatenating a unit matrix to A. proc gauss_row should be faster. @* * It should only be used with exact coefficient field (there is no pivoting) over the polynomial ring (ordering lp or dp). @* * Parameters are allowed. Hence, if the entries of A are parameters the computation takes place over the field of rational functions. SEE ALSO: gauss_row EXAMPLE: example rowred; shows an example " { int m,n=nrows(A),ncols(A); int i,j,k,l,rk; poly p; matrix d[m][n]; for (i=1;i<=m;i++) { for (j=1;j<=n;j++) { p = A[i,j]; if (ord(p)==0) { if (deg(p)==0) { d[i,j]=p; } } } } matrix b = A; if (size(#) != 0) { b = concat(b,unitmat(m)); } for (l=1;l<=n;l=l+1) { k = findfirst(ideal(d[l]),rk+1); if (k) { rk = rk+1; b = permrow(b,rk,k); p = b[rk,l]; p = 1/p; b = multrow(b,rk,p); for (i=1;i<=m;i++) { if (rk-i) { b = addrow(b,rk,-b[i,l],i);} } d = 0; for (i=rk+1;i<=m;i++) { for (j=l+1;j<=n;j++) { p = b[i,j]; if (ord(p)==0) { if (deg(p)==0) { d[i,j]=p; } } } } } } d = submat(b,1..m,1..n); if (size(#)) { list L=d,submat(b,1..m,n+1..n+m); return(L); } return(d); } example { "EXAMPLE:"; echo = 2; ring r=(0,a,b),(A,B,C),dp; matrix m[6][8]= 0, 0, b*B, -A,-4C,2A,0, 0, 2C,-4C,-A,B, 0, B, 3B,AB, 0,a*A, 0, 0, B, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2A, 0, 0, 0, 0, 0, 0, 2b, A, 0, 0, 0, 0, 0, 0, 0, 2a;""; print(rowred(m));""; list L=rowred(m,1); print(L[1]); print(L[2]); } /////////////////////////////////////////////////////////////////////////////// proc colred (matrix A,list #) "USAGE: colred(A[,e]); A matrix, e any type RETURN: - a matrix B, being the column reduced form of A, if colred is called with one argument. (as far as this is possible over the polynomial ring; no division by polynomials) @* - a list L of two matrices, such that L[1] = A * L[2] with L[1] the column-reduced form of A and L[2] the transformation matrix (if colred is called with two arguments). ASSUME: The entries of A are in the base field. It is not verified whether this assumption holds. NOTE: * This procedure is designed for teaching purposes mainly. @* * It applies rowred to the transposed matrix. proc gauss_col should be faster. @* * It should only be used with exact coefficient field (there is no pivoting) over the polynomial ring (ordering lp or dp). @* * Parameters are allowed. Hence, if the entries of A are parameters the computation takes place over the field of rational functions. SEE ALSO: gauss_col EXAMPLE: example colred; shows an example " { A = transpose(A); if (size(#)) { list L = rowred(A,1); return(transpose(L[1]),transpose(L[2]));} else { return(transpose(rowred(A)));} } example { "EXAMPLE:"; echo = 2; ring r=(0,a,b),(A,B,C),dp; matrix m[8][6]= 0, 2*C, 0, 0, 0, 0, 0, -4*C,a*A, 0, 0, 0, b*B, -A, 0, 0, 0, 0, -A, B, 0, 0, 0, 0, -4*C, 0, B, 2, 0, 0, 2*A, B, 0, 0, 0, 0, 0, 3*B, 0, 0, 2b, 0, 0, AB, 0, 2*A,A, 2a;""; print(colred(m));""; list L=colred(m,1); print(L[1]); print(L[2]); } ////////////////////////////////////////////////////////////////////////////// proc linear_relations(module M) "USAGE: linear_relations(M); M: a module ASSUME: All non-zero entries of M are homogeneous polynomials of the same positive degree. The base field must be an exact field (not real or complex). It is not checked whether these assumptions hold. RETURN: a maximal module R such that M*R is formed by zero vectors. EXAMPLE: example linear_relations; shows an example. " { int n = ncols(M); def BaseR = basering; def br = changeord(list(list("dp",1:nvars(basering)))); setring br; module M = imap(BaseR,M); ideal vars = maxideal(1); ring tmpR = 0, ('y(1..n)), dp; def newR = br + tmpR; setring newR; module M = imap(br,M); ideal vars = imap(br,vars); attrib(vars,"isSB",1); for (int i = 1; i<=n; i++) { M[i] = M[i] + 'y(i)*gen(1); } M = interred(M); module redM = NF(M,vars); module REL; int sizeREL; int j; for (i=1; i<=n; i++) { if (M[i][1]==redM[i][1]) { //-- relation found! sizeREL++; REL[sizeREL]=0; for (j=1; j<=n; j++) { REL[sizeREL] = REL[sizeREL] + (M[i][1]/'y(j))*gen(j); } } } setring BaseR; return(minbase(imap(newR,REL))); } example { "EXAMPLE:"; echo = 2; ring r = (3,w), (a,b,c,d),dp; minpoly = w2-w-1; module M = [a2,b2],[wab,w2c2+2b2],[(w-2)*a2+wab,wb2+w2c2]; module REL = linear_relations(M); pmat(REL); pmat(M*REL); } ////////////////////////////////////////////////////////////////////////////// static proc findfirst (ideal i,int t) { int n,k; for (n=t;n<=ncols(i);n=n+1) { if (i[n]!=0) { k=n;break;} } return(k); } ////////////////////////////////////////////////////////////////////////////// proc rm_unitcol(matrix A) "USAGE: rm_unitcol(A); A matrix (being row-reduced) RETURN: matrix, obtained from A by deleting unit columns (having just one 1 and else 0 as entries) and associated rows EXAMPLE: example rm_unitcol; shows an example " { int l,j; intvec v; for (j=1;j<=ncols(A);j++) { if (gen(l+1)==module(A)[j]) {l=l+1;} else { v=v,j;} } if (size(v)>1) { v = v[2..size(v)]; return(submat(A,l+1..nrows(A),v)); } else { return(0);} } example { "EXAMPLE:"; echo = 2; ring r=0,(A,B,C),dp; matrix m[6][8]= 0, 0, A, 0, 1,0, 0,0, 0, 0, -C2, 0, 0,0, 1,0, 0, 0, 0,1/2B, 0,0, 0,1, 0, 0, B, -A, 0,2A, 0,0, 2C,-4C, -A, B, 0,B, 0,0, 0, A, 0, 0, 0,0, 0,0; print(rm_unitcol(m)); } ////////////////////////////////////////////////////////////////////////////// proc rm_unitrow (matrix A) "USAGE: rm_unitrow(A); A matrix (being col-reduced) RETURN: matrix, obtained from A by deleting unit rows (having just one 1 and else 0 as entries) and associated columns EXAMPLE: example rm_unitrow; shows an example " { int l,j; intvec v; module M = transpose(A); for (j=1; j <= nrows(A); j++) { if (gen(l+1) == M[j]) { l=l+1; } else { v=v,j; } } if (size(v) > 1) { v = v[2..size(v)]; return(submat(A,v,l+1..ncols(A))); } else { return(0);} } example { "EXAMPLE:"; echo = 2; ring r=0,(A,B,C),dp; matrix m[8][6]= 0,0, 0, 0, 2C, 0, 0,0, 0, 0, -4C,A, A,-C2,0, B, -A, 0, 0,0, 1/2B,-A,B, 0, 1,0, 0, 0, 0, 0, 0,0, 0, 2A,B, 0, 0,1, 0, 0, 0, 0, 0,0, 1, 0, 0, 0; print(rm_unitrow(m)); } ////////////////////////////////////////////////////////////////////////////// proc headStand(matrix M) "USAGE: headStand(M); M matrix RETURN: matrix B such that B[i][j]=M[n-i+1,m-j+1], n=nrows(M), m=ncols(M) EXAMPLE: example headStand; shows an example " { int i,j; int n=nrows(M); int m=ncols(M); matrix B[n][m]; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { B[n-i+1,m-j+1]=M[i,j]; } } return(B); } example { "EXAMPLE:"; echo = 2; ring r=0,(A,B,C),dp; matrix M[2][3]= 0,A, B, A2, B2, C; print(M); print(headStand(M)); } ////////////////////////////////////////////////////////////////////////////// // Symmetric/Exterior powers thanks to Oleksandr Iena for his persistence ;-) proc symmetricBasis(int n, int k, list #) "USAGE: symmetricBasis(n, k[,s]); n int, k int, s string RETURN: ring, poynomial ring containing the ideal \"symBasis\", being a basis of the k-th symmetric power of an n-dim vector space. NOTE: The output polynomial ring has characteristics 0 and n variables named \"S(i)\", where the base variable name S is either given by the optional string argument(which must not contain brackets) or equal to "e" by default. SEE ALSO: exteriorBasis KEYWORDS: symmetric basis EXAMPLE: example symmetricBasis; shows an example" { //------------------------ handle optional base variable name--------------- string S = "e"; if( size(#) > 0 ) { if( typeof(#[1]) != "string" ) { ERROR("Wrong optional argument: must be a string"); } S = #[1]; if( (find(S, "(") + find(S, ")")) > 0 ) { ERROR("Wrong optional argument: must be a string without brackets"); } } //------------------------- create ring container for symmetric power basis- execute("ring @@@SYM_POWER_RING_NAME=(0),("+S+"(1.."+string(n)+")),dp;"); //------------------------- choose symmetric basis ------------------------- ideal symBasis = maxideal(k); //------------------------- export and return ------------------------- export symBasis; return(basering); } example { "EXAMPLE:"; echo = 2; // basis of the 3-rd symmetricPower of a 4-dim vector space: def R = symmetricBasis(4, 3, "@e"); setring R; R; // container ring: symBasis; // symmetric basis: } ////////////////////////////////////////////////////////////////////////////// proc exteriorBasis(int n, int k, list #) "USAGE: exteriorBasis(n, k[,s]); n int, k int, s string RETURN: qring, an exterior algebra containing the ideal \"extBasis\", being a basis of the k-th exterior power of an n-dim vector space. NOTE: The output polynomial ring has characteristics 0 and n variables named \"S(i)\", where the base variable name S is either given by the optional string argument(which must not contain brackets) or equal to "e" by default. SEE ALSO: symmetricBasis KEYWORDS: exterior basis EXAMPLE: example exteriorBasis; shows an example" { //------------------------ handle optional base variable name--------------- string S = "e"; if( size(#) > 0 ) { if( typeof(#[1]) != "string" ) { ERROR("Wrong optional argument: must be a string"); } S = #[1]; if( (find(S, "(") + find(S, ")")) > 0 ) { ERROR("Wrong optional argument: must be a string without brackets"); } } //------------------------- create ring container for symmetric power basis- execute("ring @@@EXT_POWER_RING_NAME=(0),("+S+"(1.."+string(n)+")),dp;"); //------------------------- choose exterior basis ------------------------- def T = superCommutative(); setring T; ideal extBasis = simplify( NF(maxideal(k), std(0)), 1 + 2 + 8 ); //------------------------- export and return ------------------------- export extBasis; return(basering); } example { "EXAMPLE:"; echo = 2; // basis of the 3-rd symmetricPower of a 4-dim vector space: def r = exteriorBasis(4, 3, "@e"); setring r; r; // container ring: extBasis; // exterior basis: } ////////////////////////////////////////////////////////////////////////////// static proc chooseSafeVarName(string prefix, string suffix) "USAGE: give appropreate prefix for variable names RETURN: safe variable name (repeated prefix + suffix) " { string V = varstr(basering); string S = suffix; while( find(V, S) > 0 ) { S = prefix + S; } return(S); } ////////////////////////////////////////////////////////////////////////////// static proc mapPower(int p, module A, int k, def Tn, def Tm) "USAGE: by both symmetric- and exterior-Power" NOTE: everything over the basering! module A (matrix of the map), int k (power) rings Tn is source- and Tm is image-ring with bases resp. Ink and Imk. M = max dim of Image, N - dim. of source SEE ALSO: symmetricPower, exteriorPower" { def save = basering; int n = nvars(save); int M = nrows(A); int N = ncols(A); int i, j; //------------------------- compute matrix of single images ------------------ def Rm = save + Tm; setring Rm; dbprint(p-2, "Temporary Working Ring", Rm); module A = imap(save, A); ideal B; poly t; for( i = N; i > 0; i-- ) { t = 0; for( j = M; j > 0; j-- ) { t = t + A[i][j] * var(n + j); } B[i] = t; } dbprint(p-1, "Matrix of single images", B); //------------------------- compute image --------------------- // apply S^k(A): Tn -> Rm to Source basis vectors Ink: map TMap = Tn, B; ideal C = NF(TMap(Ink), std(0)); dbprint(p-1, "Image Matrix: ", C); //------------------------- write it in Image basis --------------------- ideal Imk = imap(Tm, Imk); module D; poly lm; vector tt; for( i = ncols(C); i > 0; i-- ) { t = C[i]; tt = 0; while( t != 0 ) { lm = leadmonom(t); // lm; for( j = ncols(Imk); j > 0; j-- ) { if( lm / Imk[j] != 0 ) { tt = tt + (lead(t) / Imk[j]) * gen(j); break; } } t = t - lead(t); } D[i] = tt; } //------------------------- map it back and return --------------------- setring save; return( imap(Rm, D) ); } ////////////////////////////////////////////////////////////////////////////// proc symmetricPower(module A, int k) "USAGE: symmetricPower(A, k); A module, k int RETURN: module: the k-th symmetric power of A NOTE: the chosen bases and most of intermediate data will be shown if printlevel is big enough SEE ALSO: exteriorPower KEYWORDS: symmetric power EXAMPLE: example symmetricPower; shows an example" { int p = printlevel - voice + 2; def save = basering; int M = nrows(A); int N = ncols(A); string S = chooseSafeVarName("@", "@_e"); //------------------------- choose source basis ------------------------- def Tn = symmetricBasis(N, k, S); setring Tn; ideal Ink = symBasis; export Ink; dbprint(p-3, "Temporary Source Ring", basering); dbprint(p, "S^k(Source Basis)", Ink); //------------------------- choose image basis ------------------------- def Tm = symmetricBasis(M, k, S); setring Tm; ideal Imk = symBasis; export Imk; dbprint(p-3, "Temporary Image Ring", basering); dbprint(p, "S^k(Image Basis)", Imk); //------------------------- compute and return S^k(A) in chosen bases -- setring save; return(mapPower(p, A, k, Tn, Tm)); } example { "EXAMPLE:"; echo = 2; ring r = (0),(a, b, c, d), dp; r; module B = a*gen(1) + c* gen(2), b * gen(1) + d * gen(2); print(B); // symmetric power over a commutative K-algebra: print(symmetricPower(B, 2)); print(symmetricPower(B, 3)); // symmetric power over an exterior algebra: def g = superCommutative(); setring g; g; module B = a*gen(1) + c* gen(2), b * gen(1) + d * gen(2); print(B); print(symmetricPower(B, 2)); // much smaller! print(symmetricPower(B, 3)); // zero! (over an exterior algebra!) } ////////////////////////////////////////////////////////////////////////////// proc exteriorPower(module A, int k) "USAGE: exteriorPower(A, k); A module, k int RETURN: module: the k-th exterior power of A NOTE: the chosen bases and most of intermediate data will be shown if printlevel is big enough. Last rows will be invisible if zero. SEE ALSO: symmetricPower KEYWORDS: exterior power EXAMPLE: example exteriorPower; shows an example" { int p = printlevel - voice + 2; def save = basering; int M = nrows(A); int N = ncols(A); string S = chooseSafeVarName("@", "@_e"); //------------------------- choose source basis ------------------------- def Tn = exteriorBasis(N, k, S); setring Tn; ideal Ink = extBasis; export Ink; dbprint(p-3, "Temporary Source Ring", basering); dbprint(p, "E^k(Source Basis)", Ink); //------------------------- choose image basis ------------------------- def Tm = exteriorBasis(M, k, S); setring Tm; ideal Imk = extBasis; export Imk; dbprint(p-3, "Temporary Image Ring", basering); dbprint(p, "E^k(Image Basis)", Imk); //------------------------- compute and return E^k(A) in chosen bases -- setring save; return(mapPower(p, A, k, Tn, Tm)); } example { "EXAMPLE:"; echo = 2; ring r = (0),(a, b, c, d, e, f), dp; r; "base ring:"; module B = a*gen(1) + c*gen(2) + e*gen(3), b*gen(1) + d*gen(2) + f*gen(3), e*gen(1) + f*gen(3); print(B); print(exteriorPower(B, 2)); print(exteriorPower(B, 3)); def g = superCommutative(); setring g; g; module A = a*gen(1), b * gen(1), c*gen(2), d * gen(2); print(A); print(exteriorPower(A, 2)); module B = a*gen(1) + c*gen(2) + e*gen(3), b*gen(1) + d*gen(2) + f*gen(3), e*gen(1) + f*gen(3); print(B); print(exteriorPower(B, 2)); print(exteriorPower(B, 3)); } ////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/maxlike.lib000066400000000000000000001015621266270727000202760ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version maxlike.lib 4.0.2.0 30.03.2015 "; //$Id: 1e92ee9258a6ee79be9704ba43bb9951e22b4536 $ category="Algebraic Statistics"; info=" LIBRARY: maxlike.lib Procedures to compute maximum likelihood estimates AUTHOR: Adrian Koch (kocha at rhrk.uni-kl.de) REFERENCES: Lior Pachter, Bernd Sturmfels; Algebraic Statistics for Computational Biology; published by Cambridge University Press PROCEDURES: likeIdeal(I,u); the likelihood ideal with respect to I and u logHessian(I,u); modified Hessian of the loglikelihood function getMaxPoints(Iu,H,prec,[..]); maximum likelihood estimates maxPoints(I,u,prec,[..]); maximum likelihood estimates,combines the procedures above maxPointsProb(I,u,prec,[..]); maximum likelihood estimates and probability distributions KEYWORDS: algebraic statistics; likelihood ideal; maximum likelihood estimate "; LIB "presolve.lib"; LIB "solve.lib";//already loads the matrix.lib LIB "sing.lib"; static proc onesmat(n,m) {//returns an nxm matrix filled with ones matrix M[n][m]; int i,j; for(i=1; i<=n; i++) { for(j=1; j<=m; j++) { M[i,j]=1; } } return(M); } proc likeIdeal(ideal I, intvec u) "USAGE: likeIdeal(I,u); ideal I, intvec u I represents the algebraic statistical model and u is the data vector under considerarion. RETURN: ideal: the likelihood ideal with respect to I and u EXAMPLE: example likeIdeal; shows an example " {//I contains the polys f_i giving the alg.stat.model: theta -> (f1(theta),...,fm(theta)) //this is an implementation of the first part of 3.3 MLE, namely pages 102-104 //i.e. it computes an ideal Iu such that V(Iu) contains all critical points //of the parameter-log-likelihood-function given by the polys in I //(more precisely, V(Iu) is the smallest //variety with that property) (cf. elimination theory) //(I must have the same number of elements as u) def r=basering; int n=nvars(basering); int m=size(I); ring bigring = 0, (t(1..n),z(1..m)), dp; ideal I=fetch(r,I); // here we generate the zf(theta)-part of Ju matrix Z=diag(ideal(z(1..m))); matrix F=diag(I); matrix ZF1=Z*F-diag(1,m); ideal J1=ideal(ZF1); //here we generate the theta-part of Ju matrix O=onesmat(m,m); matrix U=diag(u); matrix UZ=O*U*Z; //compute the derivatives, but take only the submatrix corresponding to the variables //in the original ring (other entries are 0) matrix D=jacob(I); intvec rD=1..nrows(D); intvec cD=1..n; matrix Dsub=submat(D,rD,cD); matrix S=UZ*Dsub; ideal J2=ideal(S); // put the two parts together ideal Ju=J1+J2; poly el=1; int i; for(i=1; i<=m; i++) { el=el*z(i); } ideal Iu=eliminate(Ju,el); setring r; ideal Iu=fetch(bigring,Iu); return(Iu); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y),dp; poly pA = -10x+2y+25; poly pC = 8x-y+25; poly pG = 11x-2y+25; poly pT = -9x+y+25; intvec u = 10,14,15,10; ideal I = pA,pC,pG,pT; ideal L = likeIdeal(I,u); L; } static proc prodideal(ideal I) {//returns the product over all polys in I int n=size(I); int i; poly f=I[1]; for(i=2; i<=n; i++) { f=f*I[i]; } return(f); } proc logHessian(ideal I, intvec u) "USAGE: logHessian(I,u); ideal I, intvec u I represents the algebraic statistical model and u is the data vector under considerarion. RETURN: matrix: a modified version of the Hessian matrix of the loglikelihood function defined by u and (the given generators of) I. NOTE: This matrix has the following property: if it is negative definite at a point, then the actual Hessian is also negative definite at that point. The same holds for positive definiteness. EXAMPLE: example logHessian; shows an example " {//computes the "Hessian" of the loglikelihoodfunction defined by I and u //first we compute the products Fj=prod(f1,...,fm)/fj int m=size(I); int n=nvars(basering); poly F=prodideal(I); ideal Fj; int j; for(j=1; j<=m; j++) { Fj=Fj+ideal(F/I[j]); } //now, we compute the products of the first partial derivatives for each fj matrix J=jacob(I); matrix P[n][n]; list Jprod; int i,k; poly f; for(j=1; j<=m; j++) { for(i=1; i<=n; i++) { for(k=i; k<=n; k++) { f=J[j,i]*J[j,k]; P[i,k]=f; P[k,i]=f; } } Jprod=Jprod+list(P); } //here, we compute the second partial derivatives list secondJ=jacob(jacob(I[1])); for(j=2; j<=m; j++) { secondJ=secondJ+list(jacob(jacob(I[j]))); } //finally, we put everything together to get the "Hessian" matrix H[n][n]; f=0; for(i=1; i<=n; i++) { for(k=i; k<=n; k++) { for(j=1; j<=m; j++) { f=f+u[j]*Fj[j]*(secondJ[j][i,k]*I[j]-Jprod[j][i,k]); } H[i,k]=f; H[k,i]=f; f=0; } } return(H); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y),dp; poly pA = -10x+2y+25; poly pC = 8x-y+25; poly pG = 11x-2y+25; poly pT = -9x+y+25; intvec u = 10,14,15,10; ideal I = pA,pC,pG,pT; matrix H = logHessian(I,u); H; } static proc is_neg_def(matrix H) {//determines whether the given matrix is negative definite //returns 1 if it is, 0 if it isnt matrix M=H-diag(var(1),ncols(H)); poly f=det(M); list S=laguerre_solve(f); //this computes the eigenvalues of H. below, they are checked for neg. definiteness int k; //we now check, whether H is negative definite //if it is, then we will go through the for-loop completely and return 1 at the end //otherwise we return 0 for(k=1; k<=size(S); k++) { if(S[k] >= 0) { return(0); } } return(1); } proc getMaxPoints(ideal Iu, matrix H, int prec, list #) "USAGE: getMaxPoints(Iu, H, prec [, \"nodisplay\"]); ideal Iu, matrix H, int prec, int k Iu the likelihood ideal, H the (modified) Hessian of the considered algebraic statistical model, prec the precision with which to compute the maximum likelihood estimates RETURN: ring: a complex ring R in which you can find the following two lists: - MPOINTS, points in which the loglikelihood function has a local maximum, and - LHESSIANS, the (modified) Hessians at those points also prints out the points in MPOINTS, unless a fourth argument is given NOTE: it is assumed that the likelihood ideal is 0-dimensional EXAMPLE: example getMaxPoints; shows an example " {//goes through the solutions computed by solve and keeps only those which have only //(non-negative) real components //then it plugs the solutions into the "Hessian" and checks whether or not it is //negative definite ideal G=groebner(Iu); def r=basering; int n=nvars(r); def s=solve(G,prec,"nodisplay"); setring s; list L; list entk;//the k-th entry of SOL int c; //will be 1 if we want the entry in our list L, 0 otherwise int k,l; for(k=1; k<=size(SOL); k++) { c=1; entk=SOL[k]; for(l=1; l<=size(entk); l++) { if(impart(entk[l]) != 0)//throw away those with non-zero imaginary part { c=0; break; } if(entk[l] < 0)//and those wich are negative { c=0; break; } } if(c == 1)//is 1 iff all components are real and non-negative { L=L+list(entk); } } ring R=(complex,prec,i),x(1..n),dp; ideal Iu=fetch(r,Iu); list L=fetch(s,L); list Lk;//k-th entry of L matrix H=fetch(r,H); matrix Hsubst; list hessi;//contains the Hessians with solutions plugged in for(k=1; k<=size(L); k++) { Lk=L[k]; Hsubst=H; for(l=1; l<=size(Lk); l++) { Hsubst=subst(Hsubst,x(l),Lk[l]); } hessi=hessi+list(Hsubst); } //now check all elements of hessi and only keep those which are negative definite //also do the respective changes in the list of solutions L list hessi2; list L2; for(k=1; k<=size(L); k++) { if(1) { if(is_neg_def(hessi[k]) == 1) { hessi2=hessi2+list(hessi[k]); L2=L2+list(L[k]); } } } //execute("ring outR =(complex,"+string(prec)+"),(x(1.."+string(n)+")),dp;"); ring outR=(complex,prec),x(1..n),dp; list MPOINTS = imap(R,L2); list LHESSIANS = imap(R,hessi2); export MPOINTS; export LHESSIANS; string display=" // In the ring created by getmaxpoints you can find the lists // MPOINTS, containing points in which the loglikelihood function has a local maximum, and // LHESSIANS, containing the (modified) Hessians at those points. "; if(size(#)==0) { print(MPOINTS); print(display); } return(outR); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y),dp; poly pA = -10x+2y+25; poly pC = 8x-y+25; poly pG = 11x-2y+25; poly pT = -9x+y+25; intvec u = 10,14,15,10; ideal I = pA,pC,pG,pT; ideal L = likeIdeal(I,u); matrix H = logHessian(I,u); def R = getMaxPoints(L, H, 50); setring R; MPOINTS; LHESSIANS; } proc maxPoints(ideal I, intvec u, int prec, list #) "USAGE: maxPoints(I,u,prec [, \"nodisplay\"]); ideal I, intvec u, int prec I represents the algebraic statistical model, u is the data vector under considerarion, and prec is the precision to be used in the computations RETURN: ring: a complex ring R in which you can find the following two lists: - MPOINTS, points in which the loglikelihood function has a local maximum, and - LHESSIANS, the (modified) Hessians at those points also prints out the points in MPOINTS, unless a fourth argument is given NOTE: Just uses likeideal, loghessian and getmaxpoints. EXAMPLE: example maxPoints; shows an example " { ideal Iu=likeIdeal(I,u); return(getMaxPoints(Iu,logHessian(I,u),prec,#)); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y),dp; poly pA = -10x+2y+25; poly pC = 8x-y+25; poly pG = 11x-2y+25; poly pT = -9x+y+25; intvec u = 10,14,15,10; ideal I = pA,pC,pG,pT; def R = maxPoints(I, u, 50); setring R; MPOINTS; LHESSIANS; } proc maxPointsProb(ideal I, intvec u, int prec, list #) "USAGE: maxPointsProb(I,u,prec [, \"nodisplay\"]); ideal I, intvec u, int prec I represents the algebraic statistical model, u is the data vector under considerarion, and prec is the precision to be used in the computations RETURN: ring: a complex ring R in which you can find the following two lists: - MPOINTS, points in which the loglikelihood function has a local maximum, - LHESSIANS, the (modified) Hessians at those points, and - VALS, the resulting probability distributions (that is, the values of the polynomials given by I at the points in MPOINTS). Also prints out the points in MPOINTS, unless a fourth argument is given. NOTE: Does not compute the likelihood ideal via elimination, but rather computes the critical points by projection. EXAMPLE: example maxPointsProb; shows an example " {//as opposed to (get)maxpoints, which first eliminates and then solves, this procedure //solves and then projects //furthermore, it also creates a list of the values the generators of I have at the //points in MPOINTS (that is, a list of the probability distributions) matrix H=logHessian(I,u); def r=basering; int n=nvars(basering); int m=size(I); ring bigring = 0, (t(1..n),z(1..m)), dp; ideal I=fetch(r,I); // here we generate the zf(theta)-part of Ju matrix Z=diag(ideal(z(1..m))); matrix F=diag(I); matrix ZF1=Z*F-diag(1,m); ideal J1=ideal(ZF1); //here we generate the theta-part of Ju matrix O=onesmat(m,m); matrix U=diag(u); matrix UZ=O*U*Z; //compute the derivatives, but take only the submatrix corresponding to the variables //in the original ring (other entries are 0) matrix D=jacob(I); intvec rD=1..nrows(D); intvec cD=1..n; matrix Dsub=submat(D,rD,cD); matrix S=UZ*Dsub; ideal J2=ideal(S); // put the two parts together ideal Ju=J1+J2; def s=solve(Ju,prec,"nodisplay"); setring s; list L; list entk;//the k-th entry of SOL int c; //will be 1 if we want the entry in our list L, 0 otherwise int k,l; for(k=1; k<=size(SOL); k++) { c=1; entk=SOL[k]; entk=entk[1..n]; for(l=1; l<=size(entk); l++) { if(impart(entk[l]) != 0)//throw away those with non-zero imaginary part { c=0; break; } if(entk[l] < 0)//and those wich are negative { c=0; break; } } if(c == 1)//is 1 iff all components are real and non-negative { L=L+list(entk); } } ring R=(complex,prec,i),x(1..n),dp; list L=fetch(s,L); list Lk;//k-th entry of L matrix H=fetch(r,H); matrix Hsubst; list hessi;//contains the Hessians with solutions plugged in for(k=1; k<=size(L); k++) { Lk=L[k]; Hsubst=H; for(l=1; l<=size(Lk); l++) { Hsubst=subst(Hsubst,x(l),Lk[l]); } hessi=hessi+list(Hsubst); } //now check all elements of hessi and only keep those which are neg def //also do the respective changes in the list of solutions L list hessi2; list L2; for(k=1; k<=size(L); k++) { if(1) { if(is_neg_def(hessi[k]) == 1) { hessi2=hessi2+list(hessi[k]); L2=L2+list(L[k]); } } } //Output ideal I=fetch(r,I); list p, vals, VAL; int j; poly f; for(l=1; l<=size(L2); l++) { p=L2[l]; for(j=1; j<=size(I); j++) { f=I[j]; for(k=1; k<=nvars(basering); k++) { f=subst(f,var(k),p[k]); } vals=vals+list(f); } VAL=VAL+list(vals); vals=list(); } //execute("ring outR =(complex,"+string(prec)+"),(x(1.."+string(n)+")),dp;"); ring outR=(complex,prec),x(1..n),dp; list MPOINTS = imap(R,L2); list LHESSIANS = imap(R,hessi2); list VALS = imap(R,VAL); export MPOINTS; export LHESSIANS; export VALS; string display=" // In the ring created by getmaxpoints you can find the lists // MPOINTS, containing points in which the loglikelihood function has a local maximum, // LHESSIANS, containing the (modified) Hessians at those points, and // VALS, containing the probability distributions at those points. "; if(size(#)==0) { print(MPOINTS); print(display); } return(outR); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y),dp; poly pA = -10x+2y+25; poly pC = 8x-y+25; poly pG = 11x-2y+25; poly pT = -9x+y+25; intvec u = 10,14,15,10; ideal I = pA,pC,pG,pT; def R = maxPointsProb(I, u, 50); setring R; MPOINTS; LHESSIANS; VALS; } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// a few more examples ///////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// //Here, we present an example of a data vector for which the likelihood function has more //than one biologically meaningful local maximum. //You can generate DNA sequence data, which has this data vector, using Seq-Gen with the //following input: //Tree: (Taxon1:0.6074796219,Taxon2:4.7911951859,Taxon3:0.5522879636); //Seq-Gen options: -mHKY -l7647 -n1 -z28503 //You can find Seq-Gen at http://tree.bio.ed.ac.uk/software/seqgen/ // //- write(":w ThreeTaxonClaw.tree", //- "(Taxon1:0.6074796219,Taxon2:4.7911951859,Taxon3:0.5522879636);"); //- int i=system("sh", //- "seq-gen -mHKY -l7647 -n1 -z28503 -q < ThreeTaxonClaw.tree > ThreeTaxonC //law.dat"); //- intvec u=getintvec("ThreeTaxonClaw.dat"); // /* proc bad_seq_gen_example() { ring R = 0,(mu1,mu2,mu3),dp; poly f1 = mu1*mu2*mu3 + 3*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f2 = 6*mu1*1/3*(1-mu2)*1/3*(1-mu3) + 6*1/3*(1-mu1)*mu2*1/3*(1-mu3) + 6*1/3*(1-mu1)*1/3*(1-mu2)*mu3 + 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f3 = 3*mu1*mu2*1/3*(1-mu3) + 3*1/3*(1-mu1)*1/3*(1-mu2)*mu3 + 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f4 = 3*mu1*1/3*(1-mu2)*mu3 + 3*1/3*(1-mu1)*mu2*1/3*(1-mu3) + 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f5 = 3*1/3*(1-mu1)*mu2*mu3 + 3*mu1*1/3*(1-mu2)*1/3*(1-mu3) + 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); ideal I = f1,f2,f3,f4,f5; intvec u = 770,2234,1156,2331,1156; maxPoints(I,u,50); } proc bad_seq_gen_example2() {//same example, but a different method of computing the local maxima ring bigring = 0,(mu1,mu2,mu3,z1,z2,z3,z4,z5),dp; poly f1 = mu1*mu2*mu3 + 3*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f2 = 6*mu1*1/3*(1-mu2)*1/3*(1-mu3) + 6*1/3*(1-mu1)*mu2*1/3*(1-mu3) + 6*1/3*(1-mu1)*1/3*(1-mu2)*mu3 + 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f3 = 3*mu1*mu2*1/3*(1-mu3) + 3*1/3*(1-mu1)*1/3*(1-mu2)*mu3 + 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f4 = 3*mu1*1/3*(1-mu2)*mu3 + 3*1/3*(1-mu1)*mu2*1/3*(1-mu3) + 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f5 = 3*1/3*(1-mu1)*mu2*mu3 + 3*mu1*1/3*(1-mu2)*1/3*(1-mu3) + 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); ideal I = f1,f2,f3,f4,f5; intvec u=770,2234,1156,2331,1156; ideal Ju = z1*f1-1, z2*f2-1, z3*f3-1, z4*f4-1, z5*f5-1, u[1]*z1*diff(f1,mu1) + u[2]*z2*diff(f2,mu1) + u[3]*z3*diff(f3,mu1) + u[4]*z4*diff(f4,mu1) + u[5]*z5*diff(f5,mu1), u[1]*z1*diff(f1,mu2) + u[2]*z2*diff(f2,mu2) + u[3]*z3*diff(f3,mu2) + u[4]*z4*diff(f4,mu2) + u[5]*z5*diff(f5,mu2), u[1]*z1*diff(f1,mu3) + u[2]*z2*diff(f2,mu3) + u[3]*z3*diff(f3,mu3) + u[4]*z4*diff(f4,mu3) + u[5]*z5*diff(f5,mu3); ideal Iu = eliminate( Ju, z1*z2*z3*z4*z5 ); ring smallring = 0,(mu1,mu2,mu3),dp; ideal Iu=imap(bigring,Iu); ideal G=groebner(Iu); solve(G,20); ideal I = imap(bigring,I); matrix H = logHessian(I,u); ring complexring=(complex,20),(mu1,mu2,mu3),dp; matrix H = imap(smallring,H); H = subst(H,mu1,0.59152696273711385658); H = subst(H,mu2,0.2529957197544537399); H = subst(H,mu3,0.59152696273711385658); H; matrix M = H-diag(var(1),ncols(H)); laguerre_solve(det(M)); H = imap(smallring,H); H = subst(H,mu1,0.55724214001951940648); H = subst(H,mu2,0.25295468429185774898); H = subst(H,mu3,0.62963746147721704588); H; M = H-diag(var(1),ncols(H)); laguerre_solve(det(M)); H = imap(smallring,H); H = subst(H,mu1,0.62963746147721704588); H = subst(H,mu2,0.25295468429185774898); H = subst(H,mu3,0.55724214001951940648); H; M = H-diag(var(1),ncols(H)); laguerre_solve(det(M)); } */ ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// //These are some of the procedures I used to generate and test examples for my Master //thesis. To use the ones incorporating Seq-Gen, you may have to adjust the shell command //with which Singular calls Seq-Gen. You can find Seq-Gen at //http://tree.bio.ed.ac.uk/software/seqgen/ //As the names of the procedures suggest, we always use the Jukes-Cantor model. //They also tell you which of them use Seq-Gen. /* proc getguaranteedmaxPoints(ideal Iu, matrix H, list #) {//an older version of the procedures above ideal G=groebner(Iu); def r=basering; int n=nvars(r); def s=solve(G,50,"nodisplay"); setring s; list L; list entk;//the k-th entry of SOL int c; //will be 1 if we want the entry in our list L, 0 otherwise int k,l; for(k=1; k<=size(SOL); k++) { c=1; entk=SOL[k]; for(l=1; l<=size(entk); l++) { if(impart(entk[l]) != 0)//throw away those with non-zero imaginary part { c=0; break; } if(entk[l] < 0)//and those wich are negative { c=0; break; } } if(c == 1)//is 1 iff all components are real and non-negative { L=L+list(entk); } } ring R=(complex,50,i),x(1..n),dp; ideal Iu=fetch(r,Iu); list L=fetch(s,L); list Lk;//k-th entry of L matrix H=fetch(r,H); matrix Hsubst; list hessi;//contains the Hessians with solutions plugged in for(k=1; k<=size(L); k++) { Lk=L[k]; Hsubst=H; for(l=1; l<=size(Lk); l++) { Hsubst=subst(Hsubst,x(l),Lk[l]); } hessi=hessi+list(Hsubst); } //now check all elements of hessi and only keep those which arent neg def or indef //also do the respective changes in the list of solutions L list hessi2; list L2; for(k=1; k<=size(L); k++) { if(1) { if(is_neg_def(hessi[k]) == 1) { hessi2=hessi2+list(hessi[k]); L2=L2+list(L[k]); } } } if(size(#)>0) { list L2k; c=0;//counts the number of biologically meaningful parameter vectors int constrhold=1;//will be set to 0 temporarily if the constraints don't hold for(k=1; k<=size(L2); k++) { L2k=L2[k]; for(l=1; l<=size(L2k); l++) { if(L2k[l] <= 1/4) { constrhold=0; break; } if(L2k[l] > 1) { constrhold=0; break; } } if(constrhold == 1) { c++; } constrhold=1; } return(c); } print(L2); } proc getintvec(string linkstr) { //compares the sequences generated by seq-gen and outputs the frequencies //u123, udis, u12, u13 and u23 (so only helpful, when we are considering three taxons) //(distinguishes between the non-sequence-lines of the seq-gen-outputfile and those //with sequences in them by the length of the lines, so use //sequences with at least 20 nucleotides) string st=read(linkstr); string taxon, tax; int i,j; list taxons; //first, get the DNA sequences as strings and store them in the list taxons for (i=1; i<=size(st); i=i+1) { while (st[i]!=newline and i<=size(st)) { taxon=taxon+st[i]; i=i+1; } if (size(taxon)>=20) { for(j=2; j<=size(taxon); j++) { if( (taxon[j-1] == " ") and (taxon[j] != " ") ) { break; } } tax=taxon[j..size(taxon)];//removes the part of the line containing the name //of the taxon: in the textfile generated by seq-gen there are a few spaces //between the name of the taxon and the corresponding sequence taxons=taxons+list(tax); } taxon=""; } //then compare the strings in the list taxons, store the frequencies in the intvec u intvec u=0,0,0,0,0;//u123,udis,u12,u13,u23 for(i=1; i<=size(taxons[1]); i++) { if((taxons[1][i] == taxons[2][i]) and (taxons[2][i] == taxons[3][i])) { u[1]=u[1]+1; i++; continue;//continue does not execute the increment statement of the loop } if(taxons[1][i] == taxons[2][i]) { u[3]=u[3]+1; i++; continue; } if(taxons[1][i] == taxons[3][i]) { u[4]=u[4]+1; i++; continue; } if(taxons[2][i] == taxons[3][i]) { u[5]=u[5]+1; i++; continue; } u[2]=u[2]+1; } return(u); } proc randintvec(int s, int a) {//s the length of the intvecs, a the upper bound of the entries: //computes intvecs of length s and entries between 1 and a intvec u; int i; for(i=1; i<=s; i++) { u[i]=random(1,a); } return(u); } proc checkrandomJC69run(int a, int sta, int up) {//a number of random intvecs to be considered, sta the starting point of random, //up the upper bound of the entries of the intvecs ring r=0,(mu1,mu2,mu3),dp; poly f1=mu1*mu2*mu3+3*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f2=6*mu1*1/3*(1-mu2)*1/3*(1-mu3)+6*1/3*(1-mu1)*mu2*1/3*(1-mu3)+ 6*1/3*(1-mu1)*1/3*(1-mu2)*mu3+6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f3=3*mu1*mu2*1/3*(1-mu3)+3*1/3*(1-mu1)*1/3*(1-mu2)*mu3+ 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f4=3*mu1*1/3*(1-mu2)*mu3+3*1/3*(1-mu1)*mu2*1/3*(1-mu3)+ 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f5=3*1/3*(1-mu1)*mu2*mu3+3*mu1*1/3*(1-mu2)*1/3*(1-mu3)+ 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); ideal I=f1,f2,f3,f4,f5; link lu=":a UsedIntvecsJC69rand.txt"; link lf=":a FailedJC69rand.txt"; system("random",sta); ideal Iu,G; int d, nzd, num; int i; intvec u; int eatoutput; string display, writestr; writestr=newline+newline+"number of random intvecs: "+string(a)+"; random seed: "; writestr=writestr+string(sta)+"; upper bound:"+string(up)+newline; write(lu,writestr); write(lf,writestr); for(i=1; i<=a; i++) { u=randintvec(5,up); writestr=string(u); write(lu,writestr); Iu=likeIdeal(I,u); Iu=std(Iu); //Iu=groebner(Iu); d=dim(Iu); if(d != 0) { nzd++; display="-*-*-*- not 0-dim. for u= "+string(u)+", i= "+string(i)+" -*-*-*-"; print(display); write(lf,display); i++; continue; } eatoutput=getguaranteedmaxPoints(Iu,logHessian(I,u),1); if(eatoutput >= 2) { num++; write(lf,writestr+"; number: "+string(eatoutput)); display="-*-*-*- Failed for u= "+string(u)+", i= "+string(i)+" -*-*-*-"; print(display); display=""; } } display="-------------- i = "+string(i)+" --------------"; display=display+newline+"not zero-dimensional in "+string(nzd)+" cases"+newline; display=display+"no unique maximum in "+string(num)+" cases"+newline; print(display); write(lf,display); close(lu); close(lf); return(nzd,num); } proc checkseqgenJC69run(int a, int sd, int len) {//a number of random intvecs to be considered, sd the random seed for seq-gen, //up the upper bound of the entries of the intvecs ring r=0,(mu1,mu2,mu3),dp; poly f1=mu1*mu2*mu3+3*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f2=6*mu1*1/3*(1-mu2)*1/3*(1-mu3)+6*1/3*(1-mu1)*mu2*1/3*(1-mu3)+ 6*1/3*(1-mu1)*1/3*(1-mu2)*mu3+6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f3=3*mu1*mu2*1/3*(1-mu3)+3*1/3*(1-mu1)*1/3*(1-mu2)*mu3+ 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f4=3*mu1*1/3*(1-mu2)*mu3+3*1/3*(1-mu1)*mu2*1/3*(1-mu3)+ 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); poly f5=3*1/3*(1-mu1)*mu2*mu3+3*mu1*1/3*(1-mu2)*1/3*(1-mu3)+ 6*1/3*(1-mu1)*1/3*(1-mu2)*1/3*(1-mu3); ideal I=f1,f2,f3,f4,f5; link lu=":a UsedIntvecsJC69seqgen.txt"; link lf=":a FailedJC69seqgen.txt"; string readstr="ThreeTaxonClaw.dat"; ideal Iu,G; int d, nzd, num; int i; intvec u; int eatoutput; string display, writestr, shcmd; writestr=newline+newline+"number of seqgened intvecs: "+string(a)+"; random seed: "; writestr=writestr+string(sd)+"; sequence length: "+string(len)+newline; write(lu,writestr); write(lf,writestr); for(i=1; i<=a; i++) { shcmd="seq-gen "; shcmd=shcmd+"-mHKY -l"+string(len)+" -n1 -z"+string(sd); shcmd=shcmd+" -q < ThreeTaxonClaw.tree > ThreeTaxonClaw.dat"; sd++; eatoutput=system("sh",shcmd); u=getintvec(readstr); writestr=string(u); write(lu,writestr); Iu=likeIdeal(I,u); Iu=std(Iu); //Iu=groebner(Iu); d=dim(Iu); if(d != 0) { nzd++; display="-*-*-*- not 0-dim. for u= "+string(u)+", i= "+string(i)+" -*-*-*-"; print(display); write(lf,display); i++; continue; } eatoutput=getguaranteedmaxPoints(Iu,logHessian(I,u),1); if(eatoutput >= 2) { num++; write(lf,writestr+"; number: "+string(eatoutput)); display="-*-*-*- no unique maximum for u= "+ string(u)+", i= "+string(i)+" -*-*-*-"; print(display); display=""; } } display="-------------- i = "+string(i)+" --------------"; display=display+newline+"not zero-dimensional in "+string(nzd)+" cases"+newline; display=display+"no unique maximum in "+string(num)+" cases"+newline; print(display); write(lf,display); close(lu); close(lf); return(nzd,num); } proc randclawtree(int a) { ring r=(complex,10),x,dp; number n1,n2,n3; int n; int i; for(i=1; i<=a; i++) { n=random(1,1000000); n1=number(n)/1000000; n2=number(random(1,1000000-n))/1000000; n3=1-n1-n2; print("(Taxon1:"+string(n1)+",Taxon2:"+string(n2)+",Taxon3:"+string(n3)+");"); } } proc checkrandomJC69writebeginning(int r, int a, int sta, int up) { string writestr=newline+newline+newline+newline+newline+newline; writestr=writestr+"*****************************************************"+newline; writestr=writestr+"starting new loop with the following parameters"+newline; writestr=writestr+"number of runs: "+string(r)+newline; writestr=writestr+"number of intvecs per run: "+string(a)+newline; writestr=writestr+"starting random seed: "+string(sta)+newline; writestr=writestr+"upper bound for the entries of the intvecs: "+string(up)+newline; writestr=writestr+"*****************************************************"; link lu=":a UsedIntvecsJC69rand.txt"; link lf=":a FailedJC69rand.txt"; write(lu,writestr); write(lf,writestr); close(lu); close(lf); } proc checkrandomJC69writeend(int r, int a, int sta, int up, int s, int t) { writestr=newline+newline+newline; writestr=writestr+"*****************************************************"+newline; writestr=writestr+"ending loop with the following parameters"+newline; writestr=writestr+"number of runs: "+string(r)+newline; writestr=writestr+"number of intvecs per run: "+string(a)+newline; writestr=writestr+"starting random seed: "+string(sta)+newline; writestr=writestr+"upper bound for the entries of the intvecs: "+string(up)+newline; writestr=writestr+newline+"in the whole loop, there were a total of"+newline; writestr=writestr+" "+string(s)+" examples with non-zero-dim. likeideal"+newline; writestr=writestr+" "+string(t)+ " examples with more than one biol. meaningful local maximum"; writestr=writestr+newline+"*****************************************************"; write(lu,writestr); write(lf,writestr); close(lu); close(lf); } proc checkrandomJC69loop(int r, int a, int sta, int up, int s, int t) { //r the number of runs, a the number of intvecs per run, sta the starting random //seed, up the upper bound for the entries of the intvecs checkrandomJC69writebeginning(r,a,sta,up); int nzd, num, i, s, t; for(i=1; i<=r; i++) { (nzd,num)=checkrandomJC69run(a,sta,up); sta++; s=s+nzd; t=t+num; } checkrandomJC69writeend(r,a,sta,up,s,t); } proc checkseqgenJC69writebeginning(int r, int a, int sd, int sta, int len, int p) { string writestr=newline+newline+newline+newline+newline+newline; writestr=writestr+"*****************************************************"+newline; writestr=writestr+"starting new loop with the following parameters"+newline; writestr=writestr+"number of runs: "+string(r)+newline; writestr=writestr+"number of intvecs per run: "+string(a)+newline; writestr=writestr+"starting random seed for seqgen: "+string(sd)+newline; writestr=writestr+"starting random seed for random: "+string(sta)+newline; writestr=writestr+"starting length of the generated sequences: "+string(len)+newline; writestr=writestr+"*****************************************************"; link lu=":a UsedIntvecsJC69seqgen.txt"; link lf=":a FailedJC69seqgen.txt"; write(lu,writestr); write(lf,writestr); close(lu); close(lf); } proc checkseqgenJC69writeend(int r, int a, int sd, int sta, int len, int p, int s, int t, intvec ls) { writestr=newline+newline+newline; writestr=writestr+"*****************************************************"+newline; writestr=writestr+"ending loop with the following parameters"+newline; writestr=writestr+"number of runs: "+string(r)+newline; writestr=writestr+"number of intvecs per run: "+string(a)+newline; writestr=writestr+"starting random seed for seqgen: "+string(sd)+newline; writestr=writestr+"starting random seed for random: "+string(sta)+newline; writestr=writestr+"length of the generated sequences: "+string(len)+newline; writestr=writestr+newline+"in the whole loop, there were a total of"+newline; writestr=writestr+" "+string(s)+" examples with non-zero-dim. likeideal"+newline; writestr=writestr+" "+string(t)+ " examples with more than one biol. meaningful local maximum"; writestr=writestr+newline+"*****************************************************"; writestr=writestr+"used lengths:"+newline+string(ls); writestr=writestr+newline+"*****************************************************"; write(lu,writestr); write(lf,writestr); close(lu); close(lf); } proc checkseqgenJC69loop(int r, int a, int sd, int sta, int len, int p) { //r the number of runs, a the number of intvecs per run, sd the starting random //seed, len the starting length, p the amount len will increase (on average) //after each run (via + random(1,2*p-1)) //sta the random seed for random checkseqgenJC69writebeginning(r,a,sd,sta,len,p); system("random",sta); intvec ls; int nzd, num, i, s, t; for(i=1; i<=r; i++) { (nzd,num)=checkseqgenJC69run(a,sd,len); sd++; ls[i]=len; len=len+random(1,2*p-1); s=s+nzd; t=t+num; } checkseqgenJC69writeend(r,a,sd,sta,len,p,s,t,ls); } */ singular-4.0.3+ds/Singular/LIB/modnormal.lib000066400000000000000000000460311266270727000206330ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version modnormal.lib 4.0.0.0 Dec_2013 "; // $Id: 1616152b5bce97c46cfb18c1f9c08a574ad00235 $ category = "Commutative Algebra"; info=" LIBRARY: modnormal.lib Normalization of affine domains using modular methods AUTHORS: J. Boehm boehm@mathematik.uni-kl.de W. Decker decker@mathematik.uni-kl.de S. Laplagne slaplagn@dm.uba.ar G. Pfister pfister@mathematik.uni-kl.de A. Steenpass steenpass@mathematik.uni-kl.de S. Steidel steidel@mathematik.uni-kl.de @* OVERVIEW: Suppose A is an affine domain over a perfect field.@* This library implements a modular strategy for finding the normalization of A. Following [1], the idea is to apply the normalization algorithm given in [2] over finite fields and lift the results via Chinese remaindering and rational reconstruction as described in [3]. This approch is inherently parallel.@* The strategy is available both as a randomized and as a verified algorithm. REFERENCES: [1] Janko Boehm, Wolfram Decker, Santiago Laplagne, Gerhard Pfister, Stefan Steidel, Andreas Steenpass: Parallel algorithms for normalization, preprint, 2011. [2] Gert-Martin Greuel, Santiago Laplagne, Frank Seelisch: Normalization of Rings, Journal of Symbolic Computation 9 (2010), p. 887-901 [3] Janko Boehm, Wolfram Decker, Claus Fieker, Gerhard Pfister: The use of Bad Primes in Rational Reconstruction, preprint, 2012. KEYWORDS: normalization; modular methods SEE ALSO: normal_lib, locnormal_lib PROCEDURES: modNormal(I); normalization of R/I using modular methods "; LIB "poly.lib"; LIB "ring.lib"; LIB "normal.lib"; LIB "modstd.lib"; LIB "parallel.lib"; //////////////////////////////////////////////////////////////////////////////// // Verify the char 0 result L of normalization of I modulo a prime p static proc pTestNormal(ideal I, list L, int p, ideal normalIP) { // We change the characteristic of the ring to p. def R0 = basering; ideal U = L[1]; poly condu=L[2]; list rl = ringlist(R0); rl[1] = p; def @r = ring(rl); setring @r; ideal IP = fetch(R0,I); ideal UP = fetch(R0,U); poly conduP = fetch(R0, condu); ideal outP = fetch(R0,normalIP); poly denOutP = outP[1]; // Check if the universal denominator is valid ideal cOut = conduP*outP; ideal dI = ideal(denOutP) + IP; int inc = size(reduce(cOut, groebner(dI))); if(inc > 0) { "Inclusion is not satisfied. Unlucky prime?"; return(ideal(0)); } return(outComp(UP, outP, conduP, denOutP, IP)) } //////////////////////////////////////////////////////////////////////////////// // Computes the normalization of I in characterisitic p. // Returns an ideal Out such that the normalization mod p is the // module 1/condu * Out static proc modpNormal(ideal I, int p, poly condu,int printTimings,list #) { int tt = timer; int liftRelations; // We change the characteristic of the ring to p. def R0 = basering; list rl = ringlist(R0); rl[1] = p; def @r = ring(rl); int loc; int i; for ( i=1; i <= size(#); i++ ) { if ( typeof(#[i]) == "string" ) { if (#[i]=="inputJ") { loc = 1;ideal J=#[i][2];} } } setring @r; if (loc==1) {ideal JP = fetch(R0,J)}; //int t=timer; ideal IP = groebner(fetch(R0,I)); //"Time for groebner mod p "+string(timer -t); poly conduP = fetch(R0, condu); option(redSB); int t = timer; // We compute the normalization mod p if (loc==0) { //global list l = normal(IP); } else { //local list l = normal(IP,list(list("inputJ", JP))); } if (printTimings==1) {"Time for modular normal: "+string(timer - t);} t = timer; // Currently, the algorithm only works if no splitting occurs during the // normalization process. (For example, if I is prime.) if(size(l[2]) > 1){ ERRROR("Original ideal is not prime (Not implemented.) or unlucky prime"); } ideal outP = l[2][1]; poly denOutP = outP[size(outP)]; // Check if the universal denominator is valid ideal cOut = conduP*outP; ideal dI = ideal(denOutP) + IP; int inc = size(reduce(cOut, groebner(dI))); if(inc > 0) { ERROR("Inclusion is not satisfied. Unlucky prime?"); } // We change the denominator to the universal denominator outP = changeDenominator(outP, denOutP, conduP, IP); if(size(outP) > 1) { ideal JP = conduP, outP[1..size(outP)-1]; } else { ERROR("Normal ring - Special case not fully implemented."); ideal JP = conduP; ideal norid = 0; export norid; def RP = @r; } setring R0; ideal out = fetch(@r, JP); if (printTimings==1) {"Prime: "+string(p);} tt = timer-tt; return(list(out, p, tt)); } // Computes the normalization using modular methods. // Basic algorithm based on modstd. proc modNormal(ideal I, int nPrimes, list #) "USAGE: modNormal(I, n [,options]); I = prime ideal, n = positive integer, options = list of options. @* Optional parameters in list options (can be entered in any order):@* noVerificication: do not verify the result.@* printTimings: print timings.@* int ncores: number of cores to be used (default = 1). ASSUME: I is a prime ideal (the algorithm will also work for radical ideals as long as the normal command does not detect that the ideal under consideration is not prime). RETURN: a list of an ideal U and a universal denominator d such that U/d is the normalization. REMARKS: We use the algorithm given in [1] to compute the normalization of A = R/I where R is the basering. We apply the algorithm for n primes at a time until the result lifted to the rationals is correct modulo one additional prime. Depending on whether the option noVerificication is used or not, the result is returned as a probabilistic result or verified over the rationals.@* The normalization of A is represented as an R-module by returning a list of U and d, where U is an ideal of A and d is an element of A such that U/d is the normalization of A. In fact, U and d are returned as an ideal and a polynomial of the base ring R. KEYWORDS: normalization; modular techniques. SEE ALSO: normal_lib, locnormal_lib. EXAMPLE: example modNormal; shows an example " { int i,noVerif,printTimings; int liftRelations; int ncores = 1; for ( i=1; i <= size(#); i++ ) { if ( typeof(#[i]) == "string" ) { if (#[i]=="noVerification") { noVerif = 1;} if (#[i]=="printTimings") { printTimings = 1;} } if ( typeof(#[i]) == "int" ) { ncores = #[i]; } } int totalTime = timer; intvec LTimer; int t; def R = basering; int j; //-------------------- Initialize the list of primes ------------------------- int n2 = nPrimes; //---Computation of the jacobian ideal and the universal denominator list IM = mstd(I); I = IM[1]; int d = dim(I); ideal IMin = IM[2]; qring Q = I; // We work in the quotient by the groebner base of the ideal I option("redSB"); option("returnSB"); ideal I = fetch(R, I); attrib(I, "isSB", 1); ideal IMin = fetch(R, IMin); dbprint(dbg, "Computing the jacobian ideal..."); ideal J = minor(jacob(IMin), nvars(basering) - d, I); t=timer; J = modStd(J); if (printTimings==1) {"Time for modStd Jacobian "+string(timer-t);} setring R; ideal J = fetch(Q, J); //------------------ We check if the singular locus is empty ------------- if(J[1] == 1) { // The original ring R/I was normal. Nothing to do. return(ideal(1)); } //--- Universal denominator--- poly condu = getSmallest(J); // Choses the polynomial of smallest degree // of J as universal denominator. if (printTimings==1) {"conductor: ", condu;} //-------------- Main standard basis computations in positive ---------------- //---------------------- characteristic start here --------------------------- list resultNormal,currentPrimes; list resultNormalX,currentPrimesX; list LL; ideal ChremLift; ideal Out; list OutCondu; int ptn; int k = 1; int sh; int p; int h; intvec L; bigint N; int totalModularTime; int maxModularTime; int sumMaxModularTime; int sumTotalModularTime; ideal normalIP; I = groebner(I); // Largest prime: 2147483647 // Max prime for gcd: 536870909 // loop increasing the number of primes by n2 until pTest is true list modarguments; list modresults; int lastPrime; while (ptn==0) { L = primeList(I,k*n2+1,intvec(536870627),1); maxModularTime=0; totalModularTime = timer; if (k==1) {sh=0;} else {sh=1;} if (ncores == 1) { for(j = (k-1)*n2+1+sh; j <= k*n2+1; j++) { t = timer; normalIP = modpNormal(I, L[j], condu,printTimings,#)[1]; if(timer - t > maxModularTime) { maxModularTime = timer - t; } LTimer[j] = timer - t; setring R; resultNormalX[j] = normalIP; currentPrimesX[j] = bigint(L[j]); } lastPrime = L[k*n2+1]; } else { for(j = (k-1)*n2+1+sh; j <= k*n2+1; j++) { modarguments[j-(k-1)*n2-sh] = list(I, L[j], condu, printTimings, #); } modresults = parallelWaitAll("modpNormal", modarguments, 0, ncores); for(j = (k-1)*n2+1+sh; j <= k*n2+1; j++) { resultNormalX[j] = modresults[j-(k-1)*n2-sh][1]; currentPrimesX[j] = bigint(modresults[j-(k-1)*n2-sh][2]); LTimer[j] = modresults[j-(k-1)*n2-sh][3]; if(LTimer[j] > maxModularTime) { maxModularTime = LTimer[j]; } } normalIP = resultNormalX[k*n2+1]; lastPrime = modresults[n2-sh+1][2]; } if (printTimings==1) {"List of times for all modular computations so far: "+string(LTimer);} if (printTimings==1) {"Maximal modular time of current step: "+string(maxModularTime);} sumMaxModularTime=sumMaxModularTime+maxModularTime; totalModularTime = timer - totalModularTime; sumTotalModularTime=sumTotalModularTime+totalModularTime; if (printTimings==1) {"Total modular time of current step: "+string(totalModularTime);} resultNormal=delete(resultNormalX,size(resultNormalX)); currentPrimes=delete(currentPrimesX,size(currentPrimesX)); //------------------------ Delete unlucky primes ----------------------------- //------------- unlucky if and only if the leading ideal is wrong ------------ // Polynomials are not homogeneous: h = 0 LL = deleteUnluckyPrimes(resultNormal,currentPrimes,h); resultNormal = LL[1]; currentPrimes = LL[2]; if (printTimings==1) {"Number of lucky primes: ", size(currentPrimes);} //------------------- Now all leading ideals are the same -------------------- //------------------- Lift results to basering via farey --------------------- N = currentPrimes[1]; for(i = 2; i <= size(currentPrimes); i++) { N = N*currentPrimes[i]; } // Chinese remainder ChremLift = chinrem(resultNormal,currentPrimes); // Farey lifting Out = farey(ChremLift,N); OutCondu=Out,condu; // pTest if (pTestNormal(I,OutCondu,lastPrime,normalIP)==0) { if (printTimings==1) {"pTestNormal has failed, increasing the number of primes by "+string(n2);} k=k+1; } else { ptn=1; } } if (printTimings==1) { "Time for all modular computations: "+string(sumTotalModularTime); "Parallel time for all modular computations: "+string(sumMaxModularTime); "Time for randomized normal: "+string(timer - totalTime); "Simulated parallel time for randomized normal: "+string(timer - totalTime + sumMaxModularTime - sumTotalModularTime); } // return the result if no verification if (noVerif==1) { Out[size(Out) + 1] = Out[1]; Out = Out[2..size(Out)]; OutCondu=modStd(Out),condu; return(OutCondu); }; //------------------- Optional tests to ensure correctness -------------------- // Check for finiteness. We do this by checking if the reconstruction of // the ring structure is still valid t = timer; int tVerif=timer; if (printTimings==1) {"Verification:";} setring R; int isNormal = normalCheck(Out, I,printTimings); if(isNormal == 0) { ERROR("Not normal!"); } else { if (printTimings==1) {"Normal!";} } if (printTimings==1) { "Time for verifying normal: "+string(timer - t); "Time for all verification tests: "+string(timer - tVerif); "Simulated parallel time including verfications: "+string(timer - totalTime + sumMaxModularTime - sumTotalModularTime); "Total time: "+string(timer - totalTime); } // We put the denominator at the end // however we return condu anyway Out[size(Out) + 1] = Out[1]; Out = Out[2..size(Out)]; OutCondu=modStd(Out),condu; return(OutCondu); } example { "EXAMPLE:"; ring R = 0,(x,y,z),dp; int k = 4; poly f = (x^(k+1)+y^(k+1)+z^(k+1))^2-4*(x^(k+1)*y^(k+1)+y^(k+1)*z^(k+1)+z^(k+1)*x^(k+1)); f = subst(f,z,3x-2y+1); ring S = 0,(x,y),dp; poly f = imap(R,f); ideal i = f; list L = modNormal(i,1,"noVerification"); } // Computes the Jacobian ideal // I is assumed to be a groebner base static proc jacobIdOne(ideal I,int printTimings) { def R = basering; int d = dim(I); if (printTimings==1) {"Computing the ideal of minors...";} ideal J = minor(jacob(I), nvars(basering) - d, I); if (printTimings==1) {"Computing the modstd of the ideal of minors...";} J = modStd(J); if (printTimings==1) { "Groebner base computed."; "ideal of minors: "; J; } return(J); } // Procedure for comparing timings and outputs between the modular approach // and the classical approach. Remove static to be used. static proc norComp(ideal I, int nPrimes) { // nPrimes is the number of primes to use. int t = timer; list Out2 = modNormal(I, nPrimes,"noVerification"); "Time modNormal: ", timer - t; t = timer; ideal Out1 = normal(I)[2][1]; "Time normal: ", timer - t; "Same output?"; outComp(Out1, Out2[1], Out1[size(Out1)], Out2[2], I); } static proc outComp(ideal Out1, ideal Out2, poly den1, poly den2, ideal I) { I = groebner(I); Out1 = changeDenominator(Out1, den1, den1, I); Out2 = changeDenominator(Out2, den2, den1, I); Out1 = groebner(I+Out1); Out2 = groebner(I+Out2); return((size(reduce(Out1, Out2)) == 0) * (size(reduce(Out2, Out1)) == 0)); } // Make p homogeneous of degree d taking h as the aux variable of deg 1. static proc polyHomogenize(poly p, int d, intvec degs, poly h) { int i; poly q; for(i = 1; i <= size(p); i++) { q = q + p[i]*h^(d-deg(p[i], degs)); } return(q); } // verification procedure static proc normalCheck(ideal U, ideal I,int printTimings) // U / U[1] = output of the normalization { if (printTimings==1) {"normalCheck: computes the new ring structure and checks if the ring is normal";} def R = basering; poly D = U[1]; // universal denominator if (printTimings==1) {"Computing the new ring structure";} list ele = Normal::computeRing(U, I, "noRed"); def origEre = ele[1]; setring origEre; if (printTimings==1) {"Number of variables: ", nvars(basering);} if (printTimings==1) {"Computing the groebner base of the relations...";} norid = modStd(norid); if (printTimings==1) {"Computing the jacobian ideal...";} ideal J = jacobIdOne(norid,printTimings); ideal JI = J + norid; if (printTimings==1) {"Computing the radical...";} ideal JR = radical(JI); poly testP = getSmallest(JR); // Choses the polynomial of smallest degree qring Q = norid; ideal J = fetch(origEre, JR); poly D = fetch(origEre, testP); if (printTimings==1) {"Computing the quotient (DJ : J)...";} ideal oldU = 1; ideal U = quotient(D*J, J); U = groebner(U); // ----------------- Grauer-Remmert criterion check ----------------------- // We check if the equality in Grauert - Remmert criterion is satisfied. int isNormal = Normal::checkInclusions(D*oldU, U); setring R; return(isNormal); } /////////////////////////////////////////////////////////////////////////// // // EXAMPLES // /////////////////////////////////////////////////////////////////////////// /* // plane curves ring r24 = 0,(x,y,z),dp; int k = 2; poly f = (x^(k+1)+y^(k+1)+z^(k+1))^2-4*(x^(k+1)*y^(k+1)+y^(k+1)*z^(k+1)+z^(k+1)*x^(k+1)); f = subst(f,z,2x-y+1); ring s24 = 0,(x,y),dp; poly f = imap(r24,f); ideal i = f; //locNormal(i); modNormal(i,1); ring r24 = 0,(x,y,z),dp; int k = 3; poly f = (x^(k+1)+y^(k+1)+z^(k+1))^2-4*(x^(k+1)*y^(k+1)+y^(k+1)*z^(k+1)+z^(k+1)*x^(k+1)); f = subst(f,z,2x-y+1); ring s24 = 0,(x,y),dp; poly f = imap(r24,f); ideal i = f; //locNormal(i); modNormal(i,1,"noVerification"); ring r24 = 0,(x,y,z),dp; int k = 4; poly f = (x^(k+1)+y^(k+1)+z^(k+1))^2-4*(x^(k+1)*y^(k+1)+y^(k+1)*z^(k+1)+z^(k+1)*x^(k+1)); f = subst(f,z,2x-y+1); ring s24 = 0,(x,y),dp; poly f = imap(r24,f); ideal i = f; //locNormal(i); modNormal(i,1,"noVerification"); ring r24 = 0,(x,y,z),dp; int k = 5; poly f = (x^(k+1)+y^(k+1)+z^(k+1))^2-4*(x^(k+1)*y^(k+1)+y^(k+1)*z^(k+1)+z^(k+1)*x^(k+1)); f = subst(f,z,2x-y+1); ring s24 = 0,(x,y),dp; poly f = imap(r24,f); ideal i = f; //locNormal(i); modNormal(i,1); ring s24 = 0,(x,y),dp; int a=7; ideal i = ((x-1)^a-y^3)*((x+1)^a-y^3)*((x)^a-y^3)*((x-2)^a-y^3)*((x+2)^a-y^3)+y^15; //locNormal(i); modNormal(i,1); ring s24 = 0,(x,y),dp; int a=8; ideal i = ((x-1)^a-y^3)*((x+1)^a-y^3)*((x)^a-y^3)*((x-2)^a-y^3)*((x+2)^a-y^3)+y^15; //locNormal(i); modNormal(i,1); ring s24 = 0,(x,y),dp; int a=9; ideal i = ((x-1)^a-y^3)*((x+1)^a-y^3)*((x)^a-y^3)*((x-2)^a-y^3)*((x+2)^a-y^3)+y^15; //locNormal(i); modNormal(i,1,"noVerification"); ring r=0,(x,y),dp; ideal i=9127158539954x10+3212722859346x8y2+228715574724x6y4-34263110700x4y6 -5431439286x2y8-201803238y10-134266087241x8-15052058268x6y2+12024807786x4y4 +506101284x2y6-202172841y8+761328152x6-128361096x4y2+47970216x2y4-6697080y6 -2042158x4+660492x2y2-84366y4+2494x2-474y2-1; //locNormal(i); modNormal(i,1); // surfaces in A3 ring r7 = 0,(x,y,t),dp; int a=11; ideal i = x*y*(x-y)*(x+y)*(y-1)*t+(x^a-y^2)*(x^10-(y-1)^2); //locNormal(i); modNormal(i,1,"noVerification"); ring r7 = 0,(x,y,t),dp; int a=12; ideal i = x*y*(x-y)*(x+y)*(y-1)*t+(x^a-y^2)*(x^10-(y-1)^2); //locNormal(i); modNormal(i,1,"noVerification"); ring r7 = 0,(x,y,t),dp; int a=13; ideal i = x*y*(x-y)*(x+y)*(y-1)*t+(x^a-y^2)*(x^10-(y-1)^2); //locNormal(i); modNormal(i,1,"noVerification"); ring r22 = 0,(x,y,z),dp; ideal i = z2-(y2-1234x3)^2*(15791x2-y3)*(1231y2-x2*(x+158))*(1357y5-3x11); //locNormal(i); modNormal(i,1,"noVerification"); ring r22 = 0,(x,y,z),dp; ideal i = z2-(y2-1234x3)^3*(15791x2-y3)*(1231y2-x2*(x+158))*(1357y5-3x11); //locNormal(i); modNormal(i,1,"noVerification"); ring r23 = 0,(x,y,z),dp; ideal i = z5-((13x-17y)*(5x2-7y3)*(3x3-2y2)*(19y2-23x2*(x+29)))^2; //locNormal(i); modNormal(i,1,"noVerification"); // curve in A3 ring r23 = 0,(x,y,z),dp; ideal i = z3-(19y2-23x2*(x+29))^2,x3-(11y2-13z2*(z+1)); //locNormal(i); modNormal(i,1,"noVerification"); ring r23 = 0,(x,y,z),dp; ideal i = z3-(19y2-23x2*(x+29))^2,x3-(11y2-13z2*(z+1))^2; //locNormal(i); modNormal(i,1,"noVerification"); // surface in A4 ring r23 = 0,(x,y,z,w),dp; ideal i = z2-(y3-123456w2)*(15791x2-y3)^2, w*z-(1231y2-x*(111x+158)); //locNormal(i); modNormal(i,1,"noVerification"); */ singular-4.0.3+ds/Singular/LIB/modstd.lib000066400000000000000000000456631266270727000201470ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version modstd.lib 4.0.2.0 Aug_2015 "; // $Id: 4b6b912051bdc20f10ea65b7c6b57406b17d96fd $ category="Commutative Algebra"; info=" LIBRARY: modstd.lib Groebner bases of ideals using modular methods AUTHORS: A. Hashemi Amir.Hashemi@lip6.fr G. Pfister pfister@mathematik.uni-kl.de H. Schoenemann hannes@mathematik.uni-kl.de A. Steenpass steenpass@mathematik.uni-kl.de S. Steidel steidel@mathematik.uni-kl.de OVERVIEW: A library for computing Groebner bases of ideals in the polynomial ring over the rational numbers using modular methods. REFERENCES: E. A. Arnold: Modular algorithms for computing Groebner bases. J. Symb. Comp. 35, 403-419 (2003). N. Idrees, G. Pfister, S. Steidel: Parallelization of Modular Algorithms. J. Symb. Comp. 46, 672-684 (2011). PROCEDURES: modStd(I); standard basis of I using modular methods "; LIB "poly.lib"; LIB "modular.lib"; proc modStd(ideal I, list #) "USAGE: modStd(I[, exactness]); I ideal, exactness int RETURN: a standard basis of I NOTE: The procedure computes a standard basis of I (over the rational numbers) by using modular methods. @* An optional parameter 'exactness' can be provided. If exactness = 1, the procedure computes a standard basis of I for sure; if exactness = 0, it computes a standard basis of I with high probability. SEE ALSO: modular EXAMPLE: example modStd; shows an example" { /* read optional parameter */ int exactness = 1; if (size(#) > 0) { /* For compatibility, we only test size(#) > 4. This can be changed to * size(#) > 1 in the future. */ if (size(#) > 4 || typeof(#[1]) != "int") { ERROR("wrong optional parameter"); } exactness = #[1]; } /* save options */ intvec opt = option(get); option(redSB); /* choose the right command */ string command = "groebner"; if (npars(basering) > 0) { command = "Modstd::groebner_norm"; } /* call modular() */ if (exactness) { I = modular(command, list(I), primeTest_std, deleteUnluckyPrimes_std, pTest_std, finalTest_std); } else { I = modular(command, list(I), primeTest_std, deleteUnluckyPrimes_std, pTest_std); } /* return the result */ attrib(I, "isSB", 1); option(set, opt); return(I); } example { "EXAMPLE:"; echo = 2; ring R1 = 0, (x,y,z,t), dp; ideal I = 3x3+x2+1, 11y5+y3+2, 5z4+z2+4; ideal J = modStd(I); J; I = homog(I, t); J = modStd(I); J; ring R2 = 0, (x,y,z), ds; ideal I = jacob(x5+y6+z7+xyz); ideal J = modStd(I, 0); J; ring R3 = 0, x(1..4), lp; ideal I = cyclic(4); ideal J1 = modStd(I, 1); // default ideal J2 = modStd(I, 0); size(reduce(J1, J2)); size(reduce(J2, J1)); } /* compute a normalized GB via groebner() */ static proc groebner_norm(ideal I) { I = simplify(groebner(I), 1); attrib(I, "isSB", 1); return(I); } /* test if the prime p is suitable for the input, i.e. it does not divide * the numerator or denominator of any of the coefficients */ static proc primeTest_std(int p, alias list args) { /* erase zero generators */ ideal I = simplify(args[1], 2); /* clear denominators and count the terms */ ideal J; ideal K; int n = ncols(I); intvec sizes; number cnt; int i; for(i = n; i > 0; i--) { J[i] = cleardenom(I[i]); cnt = leadcoef(J[i])/leadcoef(I[i]); K[i] = numerator(cnt)*var(1)+denominator(cnt); } sizes = size(J[1..n]); /* change to characteristic p */ def br = basering; list lbr = ringlist(br); if (typeof(lbr[1]) == "int") { lbr[1] = p; } else { lbr[1][1] = p; } def rp = ring(lbr); setring(rp); ideal Jp = fetch(br, J); ideal Kp = fetch(br, K); /* test if any coefficient is missing */ if (intvec(size(Kp[1..n])) != 2:n) { setring(br); return(0); } if (intvec(size(Jp[1..n])) != sizes) { setring(br); return(0); } setring(br); return(1); } /* find entries in modresults which come from unlucky primes. * For this, sort the entries into categories depending on their leading * ideal and return the indices in all but the biggest category. */ static proc deleteUnluckyPrimes_std(alias list modresults) { int size_modresults = size(modresults); /* sort results into categories. * each category is represented by three entries: * - the corresponding leading ideal * - the number of elements * - the indices of the elements */ list cat; int size_cat; ideal L; int i; int j; for (i = 1; i <= size_modresults; i++) { L = lead(modresults[i]); attrib(L, "isSB", 1); for (j = 1; j <= size_cat; j++) { if (size(L) == size(cat[j][1]) && size(reduce(L, cat[j][1])) == 0 && size(reduce(cat[j][1], L)) == 0) { cat[j][2] = cat[j][2]+1; cat[j][3][cat[j][2]] = i; break; } } if (j > size_cat) { size_cat++; cat[size_cat] = list(); cat[size_cat][1] = L; cat[size_cat][2] = 1; cat[size_cat][3] = list(i); } } /* find the biggest categories */ int cat_max = 1; int max = cat[1][2]; for (i = 2; i <= size_cat; i++) { if (cat[i][2] > max) { cat_max = i; max = cat[i][2]; } } /* return all other indices */ list unluckyIndices; for (i = 1; i <= size_cat; i++) { if (i != cat_max) { unluckyIndices = unluckyIndices + cat[i][3]; } } return(unluckyIndices); } /* test if 'command' applied to 'args' in characteristic p is the same as 'result' mapped to characteristic p */ static proc pTest_std(string command, alias list args, alias ideal result, int p) { /* change to characteristic p */ def br = basering; list lbr = ringlist(br); if (typeof(lbr[1]) == "int") { lbr[1] = p; } else { lbr[1][1] = p; } def rp = ring(lbr); setring(rp); ideal Ip = fetch(br, args)[1]; ideal Gp = fetch(br, result); attrib(Gp, "isSB", 1); /* test if Ip is in Gp */ int i; for (i = ncols(Ip); i > 0; i--) { if (reduce(Ip[i], Gp, 1) != 0) { setring(br); return(0); } } /* compute command(args) */ execute("Ip = "+command+"(Ip);"); /* test if Gp is in Ip */ for (i = ncols(Gp); i > 0; i--) { if (reduce(Gp[i], Ip, 1) != 0) { setring(br); return(0); } } setring(br); return(1); } /* test if 'result' is a GB of the input ideal */ static proc finalTest_std(string command, alias list args, ideal result) { /* test if args[1] is in result */ attrib(result, "isSB", 1); int i; for (i = ncols(args[1]); i > 0; i--) { if (reduce(args[1][i], result, 1) != 0) { return(0); } } /* test if result is a GB */ ideal G = std(result); if (reduce_parallel(G, result)) { return(0); } return(1); } /* return 1, if I_reduce is _not_ in G_reduce, * 0, otherwise * (same as size(reduce(I_reduce, G_reduce))). * Uses parallelization. */ static proc reduce_parallel(def I_reduce, def G_reduce) { exportto(Modstd, I_reduce); exportto(Modstd, G_reduce); int size_I = ncols(I_reduce); int chunks = Modular::par_range(size_I); intvec range; int i; for (i = chunks; i > 0; i--) { range = Modular::par_range(size_I, i); task t(i) = "Modstd::reduce_task", list(range); } startTasks(t(1..chunks)); waitAllTasks(t(1..chunks)); int result = 0; for (i = chunks; i > 0; i--) { if (getResult(t(i))) { result = 1; break; } } kill I_reduce; kill G_reduce; return(result); } /* compute a chunk of reductions for reduce_parallel */ static proc reduce_task(intvec range) { int result = 0; int i; for (i = range[1]; i <= range[2]; i++) { if (reduce(I_reduce[i], G_reduce, 1) != 0) { result = 1; break; } } return(result); } //////////////////////////////////////////////////////////////////////////////// /* * The following procedures are kept for backward compatibility with the old * version of modstd.lib. As of now (May 2014), they are still needed in * modnormal.lib, modwalk.lib, and symodstd.lib. They can be removed here as * soon as they are not longer needed in these libraries. */ LIB "parallel.lib"; static proc mod_init() { newstruct("idealPrimeTest", "ideal Ideal"); } static proc redFork(ideal I, ideal J, int n) { attrib(J,"isSB",1); return(reduce(I,J,1)); } proc isIncluded(ideal I, ideal J, list #) "USAGE: isIncluded(I,J); I,J ideals RETURN: 1 if J includes I, @* 0 if there is an element f in I which does not reduce to 0 w.r.t. J. EXAMPLE: example isIncluded; shows an example " { def R = basering; setring R; attrib(J,"isSB",1); int i,j,k; if(size(#) > 0) { int n = #[1]; if(n >= ncols(I)) { n = ncols(I); } if(n > 1) { for(i = 1; i <= n - 1; i++) { //link l(i) = "MPtcp:fork"; link l(i) = "ssi:fork"; open(l(i)); write(l(i), quote(redFork(eval(I[ncols(I)-i]), eval(J), 1))); } int t = timer; if(reduce(I[ncols(I)], J, 1) != 0) { for(i = 1; i <= n - 1; i++) { close(l(i)); } return(0); } t = timer - t; if(t > 60) { t = 60; } int i_sleep = system("sh", "sleep "+string(t)); j = ncols(I) - n; while(j >= 0) { for(i = 1; i <= n - 1; i++) { if(status(l(i), "read", "ready")) { if(read(l(i)) != 0) { for(i = 1; i <= n - 1; i++) { close(l(i)); } return(0); } else { if(j >= 1) { write(l(i), quote(redFork(eval(I[j]), eval(J), 1))); j--; } else { k++; close(l(i)); } } } } if(k == n - 1) { j--; } i_sleep = system("sh", "sleep "+string(t)); } return(1); } } for(i = ncols(I); i >= 1; i--) { if(reduce(I[i],J,1) != 0){ return(0); } } return(1); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; ideal I = x+1,x+y+1; ideal J = x+1,y; isIncluded(I,J); isIncluded(J,I); isIncluded(I,J,4); ring R = 0, x(1..5), dp; ideal I1 = cyclic(4); ideal I2 = I1,x(5)^2; isIncluded(I1,I2,4); } proc deleteUnluckyPrimes(list T, list L, int ho, list #) "USAGE: deleteUnluckyPrimes(T,L,ho,#); T/L list of polys/primes, ho integer RETURN: lists T,L(,M),lT with T/L(/M) list of polys/primes(/type of #), lT ideal NOTE: - if ho = 1, the polynomials in T are homogeneous, else ho = 0, @* - lT is prevalent, i.e. the most appearing leading ideal in T EXAMPLE: example deleteUnluckyPrimes; shows an example " { ho = ((ho)||(ord_test(basering) == -1)); int j,k,c; intvec hl,hc; ideal cT,lT,cK; lT = lead(T[size(T)]); attrib(lT,"isSB",1); if(!ho) { for(j = 1; j < size(T); j++) { cT = lead(T[j]); attrib(cT,"isSB",1); if((size(reduce(cT,lT))!=0)||(size(reduce(lT,cT))!=0)) { cK = cT; c++; } } if(c > size(T) div 2){ lT = cK; } } else { hl = hilb(lT,1); for(j = 1; j < size(T); j++) { cT = lead(T[j]); attrib(cT,"isSB",1); hc = hilb(cT,1); if(hl == hc) { for(k = 1; k <= size(lT); k++) { if(lT[k] < cT[k]) { lT = cT; c++; break; } if(lT[k] > cT[k]) { c++; break; } } } else { if(hc < hl){ lT = cT; hl = hilb(lT,1); c++; } } } } int addList; if(size(#) > 0) { list M = #; addList = 1; } j = 1; attrib(lT,"isSB",1); while((j <= size(T))&&(c > 0)) { cT = lead(T[j]); attrib(cT,"isSB",1); if((size(reduce(cT,lT)) != 0)||(size(reduce(lT,cT)) != 0)) { T = delete(T,j); if(j == 1) { L = L[2..size(L)]; if(addList == 1) { M = M[2..size(M)]; } } else { if(j == size(L)) { L = L[1..size(L)-1]; if(addList == 1) { M = M[1..size(M)-1]; } } else { L = L[1..j-1],L[j+1..size(L)]; if(addList == 1) { M = M[1..j-1],M[j+1..size(M)]; } } } j--; } j++; } for(j = 1; j <= size(L); j++) { L[j] = bigint(L[j]); } if(addList == 0) { return(list(T,L,lT)); } if(addList == 1) { return(list(T,L,M,lT)); } } example { "EXAMPLE:"; echo = 2; list L = 2,3,5,7,11; ring r = 0,(y,x),Dp; ideal I1 = 2y2x,y6; ideal I2 = yx2,y3x,x5,y6; ideal I3 = y2x,x3y,x5,y6; ideal I4 = y2x,11x3y,x5; ideal I5 = y2x,yx3,x5,7y6; list T = I1,I2,I3,I4,I5; deleteUnluckyPrimes(T,L,1); list P = poly(x),poly(x2),poly(x3),poly(x4),poly(x5); deleteUnluckyPrimes(T,L,1,P); } proc primeTest(def II, bigint p) { if(typeof(II) == "string") { ideal I = `II`.Ideal; } else { ideal I = II; } I = simplify(I, 2); // erase zero generators int i,j; poly f; number cnt; for(i = 1; i <= size(I); i++) { f = cleardenom(I[i]); if(f == 0) { return(0); } cnt = leadcoef(I[i])/leadcoef(f); if((bigint(numerator(cnt)) mod p) == 0) { return(0); } if((bigint(denominator(cnt)) mod p) == 0) { return(0); } for(j = size(f); j > 0; j--) { if((bigint(leadcoef(f[j])) mod p) == 0) { return(0); } } } return(1); } proc primeList(ideal I, int n, list #) "USAGE: primeList(I,n[,ncores]); ( resp. primeList(I,n[,L,ncores]); ) I ideal, n integer RETURN: the intvec of n greatest primes <= 2147483647 (resp. n greatest primes < L[size(L)] union with L) such that none of these primes divides any coefficient occuring in I NOTE: The number of cores to use can be defined by ncores, default is 1. EXAMPLE: example primeList; shows an example " { intvec L; int i,p; int ncores = 1; //----------------- Initialize optional parameter ncores --------------------- if(size(#) > 0) { if(size(#) == 1) { if(typeof(#[1]) == "int") { ncores = #[1]; # = list(); } } else { ncores = #[2]; } } if(size(#) == 0) { p = 2147483647; while(!primeTest(I,p)) { p = prime(p-1); if(p == 2) { ERROR("no more primes"); } } L[1] = p; } else { L = #[1]; p = prime(L[size(L)]-1); while(!primeTest(I,p)) { p = prime(p-1); if(p == 2) { ERROR("no more primes"); } } L[size(L)+1] = p; } if(p == 2) { ERROR("no more primes"); } if(ncores == 1) { for(i = 2; i <= n; i++) { p = prime(p-1); while(!primeTest(I,p)) { p = prime(p-1); if(p == 2) { ERROR("no more primes"); } } L[size(L)+1] = p; } } else { int neededSize = size(L)+n-1;; list parallelResults; list arguments; int neededPrimes = neededSize-size(L); idealPrimeTest Id; Id.Ideal = I; export(Id); while(neededPrimes > 0) { arguments = list(); for(i = ((neededPrimes div ncores)+1-(neededPrimes%ncores == 0)) *ncores; i > 0; i--) { p = prime(p-1); if(p == 2) { ERROR("no more primes"); } arguments[i] = list("Id", p); } parallelResults = parallelWaitAll("primeTest", arguments, 0, ncores); for(i = size(arguments); i > 0; i--) { if(parallelResults[i]) { L[size(L)+1] = arguments[i][2]; } } neededPrimes = neededSize-size(L); } kill Id; if(size(L) > neededSize) { L = L[1..neededSize]; } } return(L); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; ideal I = 2147483647x+y, z-181; intvec L = primeList(I,10); size(L); L[1]; L[size(L)]; L = primeList(I,5,L); size(L); L[size(L)]; } ////////////////////////////// further examples //////////////////////////////// /* ring r = 0, (x,y,z), lp; poly s1 = 5x3y2z+3y3x2z+7xy2z2; poly s2 = 3xy2z2+x5+11y2z2; poly s3 = 4xyz+7x3+12y3+1; poly s4 = 3x3-4y3+yz2; ideal i = s1, s2, s3, s4; ring r = 0, (x,y,z), lp; poly s1 = 2xy4z2+x3y2z-x2y3z+2xyz2+7y3+7; poly s2 = 2x2y4z+x2yz2-xy2z2+2x2yz-12x+12y; poly s3 = 2y5z+x2y2z-xy3z-xy3+y4+2y2z; poly s4 = 3xy4z3+x2y2z-xy3z+4y3z2+3xyz3+4z2-x+y; ideal i = s1, s2, s3, s4; ring r = 0, (x,y,z), lp; poly s1 = 8x2y2 + 5xy3 + 3x3z + x2yz; poly s2 = x5 + 2y3z2 + 13y2z3 + 5yz4; poly s3 = 8x3 + 12y3 + xz2 + 3; poly s4 = 7x2y4 + 18xy3z2 + y3z3; ideal i = s1, s2, s3, s4; int n = 6; ring r = 0,(x(1..n)),lp; ideal i = cyclic(n); ring s = 0, (x(1..n),t), lp; ideal i = imap(r,i); i = homog(i,t); ring r = 0, (x(1..4),s), (dp(4),dp); poly s1 = 1 + s^2*x(1)*x(3) + s^8*x(2)*x(3) + s^19*x(1)*x(2)*x(4); poly s2 = x(1) + s^8 *x(1)* x(2)* x(3) + s^19* x(2)* x(4); poly s3 = x(2) + s^10*x(3)*x(4) + s^11*x(1)*x(4); poly s4 = x(3) + s^4*x(1)*x(2) + s^19*x(1)*x(3)*x(4) +s^24*x(2)*x(3)*x(4); poly s5 = x(4) + s^31* x(1)* x(2)* x(3)* x(4); ideal i = s1, s2, s3, s4, s5; ring r = 0, (x,y,z), ds; int a = 16; int b = 15; int c = 4; int t = 1; poly f = x^a+y^b+z^(3*c)+x^(c+2)*y^(c-1)+x^(c-1)*y^(c-1)*z3 +x^(c-2)*y^c*(y2+t*x)^2; ideal i = jacob(f); ring r = 0, (x,y,z), ds; int a = 25; int b = 25; int c = 5; int t = 1; poly f = x^a+y^b+z^(3*c)+x^(c+2)*y^(c-1)+x^(c-1)*y^(c-1)*z3 +x^(c-2)*y^c*(y2+t*x)^2; ideal i = jacob(f),f; ring r = 0, (x,y,z), ds; int a = 10; poly f = xyz*(x+y+z)^2 +(x+y+z)^3 +x^a+y^a+z^a; ideal i = jacob(f); ring r = 0, (x,y,z), ds; int a = 6; int b = 8; int c = 10; int alpha = 5; int beta = 5; int t = 1; poly f = x^a+y^b+z^c+x^alpha*y^(beta-5)+x^(alpha-2)*y^(beta-3) +x^(alpha-3)*y^(beta-4)*z^2+x^(alpha-4)*y^(beta-4)*(y^2+t*x)^2; ideal i = jacob(f); */ singular-4.0.3+ds/Singular/LIB/modular.lib000066400000000000000000000246271266270727000203150ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////// version="version modular.lib 4.0.2 May_2015 "; // $Id: 11175274e7170f07c9642eedd11eface43fd4194 $ category="General purpose"; info=" LIBRARY: modular.lib An abstraction layer for modular techniques AUTHOR: Andreas Steenpass, e-mail: steenpass@mathematik.uni-kl.de OVERVIEW: This library is an abstraction layer for modular techniques which are well-known to speed up many computations and to be easy parallelizable. @* The basic idea is to execute some computation modulo several primes and then to lift the result back to characteristic zero via the farey rational map and chinese remaindering. It is thus possible to overcome the often problematic coefficient swell and to run the modular computations in parallel. @* In Singular, modular techniques have been quite successfully employed for several applications. A first implementation was done for Groebner bases in Singular's @ref{modstd_lib}, a pioneering work by Stefan Steidel. Since the algorithm is basically the same for all applications, this library aims at preventing library authors from writing the same code over and over again by providing an appropriate abstraction layer. It also offers one-line commands for ordinary Singular users who want to take advantage of modular techniques for their own calculations. Thus modular techniques can be regarded as a parallel skeleton of their own. @* The terminology (such as 'pTest' and 'finalTest') follows Singular's @ref{modstd_lib} and [1]. REFERENCES: [1] Nazeran Idrees, Gerhard Pfister, Stefan Steidel: Parallelization of Modular Algorithms. Journal of Symbolic Computation 46, 672-684 (2011). http://arxiv.org/abs/1005.5663 SEE ALSO: link, tasks_lib, parallel_lib, modstd_lib, assprimeszerodim_lib KEYWORDS: modular_lib; Modular techniques; Parallelization; Skeletons for parallelization; Distributed computing PROCEDURES: modular(...) execute a command modulo several primes and lift the result back to characteristic zero "; LIB "resources.lib"; LIB "tasks.lib"; LIB "parallel.lib"; static proc mod_init() { string arg_type; export arg_type; if (!defined(Resources)) { LIB "resources.lib"; } int sem_cores = Resources::sem_cores; // the number of processor cores exportto(Modular, sem_cores); } proc modular(string Command, alias list Arguments, list #) "USAGE: modular(command, arguments[, primeTest, deleteUnluckyPrimes, pTest, finalTest, pmax), command string, arguments list, primeTest proc, deleteUnluckyPrimes proc, pTest proc, finalTest proc, pmax int RETURN: the result of @code{command} applied to @code{arguments}, computed using modular methods. NOTE: For the general algorithm and the role of the optional arguments primeTest, deleteUnluckyPrimes, pTest, and finalTest, see @ref{modStd} and the reference given in @ref{modular_lib}. The default for these arguments is that all tests succeed and that all primes are assumed to be lucky. @* The type of the result when @code{command} is applied to @code{arguments} must be either @code{bigint}, @code{ideal}, @code{module}, or @code{matrix}. @* The optional argument pmax is an upper bound for the prime numbers to be used for the modular computations. The default is 2147483647 (largest prime which can be represented as an @code{int} in Singular), or 536870909 (largest prime below 2^29} for baserings with parameters. SEE ALSO: modStd EXAMPLE: example modular; shows an example" { /* check for errors */ if (char(basering) != 0) { ERROR("The characteristic must be zero."); } /* auxiliary variables */ int i; /* set maximal prime number */ int pmax = 2147483647; if (npars(basering) > 0) { pmax = 536870909; // prime(2^29) } /* read optional parameters */ list defaults = list(primeTest_default, deleteUnluckyPrimes_default, pTest_default, finalTest_default, pmax); for (i = 1; i <= size(defaults); i++) { if (typeof(#[i]) != typeof(defaults[i])) { # = insert(#, defaults[i], i-1); } } if (size(#) != size(defaults)) { ERROR("wrong optional parameters"); } proc primeTest = #[1]; proc deleteUnluckyPrimes = #[2]; proc pTest = #[3]; proc finalTest = #[4]; pmax = #[5]; exportto(Modular, primeTest); /* export command and arguments */ exportto(Modular, Command); exportto(Modular, Arguments); /* modular computations */ def result; def result_lift; bigint N = 1; list modresults; list primes; int nAllPrimes; int nNewPrimes; int p; list indices; int ncores_available; while (1) { // compute list of primes if (nAllPrimes == 0) { nNewPrimes = NbModProcs(); } else { ncores_available = system("semaphore", "get_value", sem_cores)+1; if (nAllPrimes < ncores_available) { nNewPrimes = nAllPrimes; } else { nNewPrimes = (nAllPrimes div ncores_available) *ncores_available; } } primes = primeList(nNewPrimes, pmax); pmax = primes[size(primes)]-1; nAllPrimes = nAllPrimes+nNewPrimes; // do computation modulo several primes for (i = size(primes); i > 0; i--) { task t(i) = "Modular::modp", primes[i]; } startTasks(t(1..size(primes))); waitAllTasks(t(1..size(primes))); for (i = size(primes); i > 0; i--) { modresults[i] = getResult(t(i)); killTask(t(i)); kill t(i); } // delete unlucky primes indices = deleteUnluckyPrimes(modresults); for (i = size(indices); i > 0; i--) { modresults = delete(modresults, indices[i]); primes = delete(primes, indices[i]); } // lift result if (N == 1) { result_lift = chinrem(modresults, primes); } else { result_lift = chinrem(list(result_lift)+modresults, list(N)+primes); } modresults = list(); for (i = size(primes); i > 0; i--) { N = N*primes[i]; } // apply farey result = farey_parallel(result_lift, N); // pTest p = prime(random(pmax div 2, pmax-1)); while (!Modular::primeTest(p, Arguments)) { if (p <= 2) { ERROR("no more primes"); } p = prime(random(p div 2, p-1)); } if (!pTest(Command, Arguments, result, p)) { continue; } // finalTest if (finalTest(Command, Arguments, result)) { break; } } /* kill exported data */ kill Command; kill Arguments; kill primeTest; /* return of result */ return(result); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; modular("std", list(I)); } static proc primeList(int n, int pmax) { list primes; int p = pmax; int i; for (i = 1; i <= n; i++) { if (p < 2) { ERROR("no more primes"); } p = prime(p); task t(i) = "Modular::primeList_task", list(p); p--; } startTasks(t(1..n)); waitAllTasks(t(1..n)); int j; for (i = 1; i <= n; i++) { if (getResult(t(i))) { j++; primes[j] = getArguments(t(i))[1]; } killTask(t(i)); } if (j < n) { primes = primes+primeList(n-j, p); } return(primes); } static proc primeList_task(int p) { return(Modular::primeTest(p, Arguments)); } static proc modp(int p) { def br = basering; list lbr = ringlist(br); if (typeof(lbr[1]) == "int") { lbr[1] = p; } else { lbr[1][1] = p; } def rp = ring(lbr); setring(rp); list args = fetch(br, Arguments); execute("def result = "+Command+"("+Tasks::argsToString("args", size(args)) +");"); setring(br); def result = fetch(rp, result); return(result); } static proc primeTest_default(int p, alias list args) { return(1); } static proc deleteUnluckyPrimes_default(alias list modresults) { return(list()); } static proc pTest_default(string command, alias list args, def result, int p) { return(1); } static proc finalTest_default(string command, alias list args, def result) { return(1); } static proc farey_parallel(def farey_arg, bigint farey_N) { arg_type = typeof(farey_arg); if (arg_type != "bigint" && arg_type != "ideal" && arg_type != "module" && arg_type != "matrix") { ERROR("wrong input type"); } if (arg_type == "bigint" || arg_type == "matrix") { return(farey(farey_arg, farey_N)); } // else: farey_arg is an ideal or a module exportto(Modular, farey_arg); exportto(Modular, farey_N); int size_arg = ncols(farey_arg); int chunks = par_range(size_arg); intvec range; int i; for (i = chunks; i > 0; i--) { range = par_range(size_arg, i); task t(i) = "Modular::farey_task", list(range); } startTasks(t(1..chunks)); waitAllTasks(t(1..chunks)); def result = getResult(t(chunks)); for (i = chunks-1; i > 0; i--) { result = getResult(t(i)), result; killTask(t(i)); } kill farey_arg; kill farey_N; return(result); } static proc farey_task(intvec range) { execute("def result = farey("+arg_type+"(farey_arg[range[1]..range[2]])," +" farey_N);"); return(result); } static proc par_range(int N, list #) { int nchunks = 2*getcores(); if (nchunks > N) { nchunks = N; } if (size(#)) { int index = #[1]; intvec range = ((N*(index-1)) div nchunks)+1, (N*index) div nchunks; return(range); } else { return(nchunks); } } static proc NbModProcs() { int available = system("semaphore", "get_value", sem_cores)+1; int nb; if (available < 16) { nb = ((10 div available)+1-(10%available == 0))*available; } else { // gives approx. (log_2(available))^2 int tmp = available; while (tmp > 1) { tmp = tmp div 2; nb++; } // nb = log_2(available) nb = ((2*nb+1)*available) div (2^nb) + (nb-1)^2 - 2; } return(nb); } singular-4.0.3+ds/Singular/LIB/modwalk.lib000066400000000000000000000421241266270727000203000ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version modwalk.lib 4.0.0.0 Jun_2013 "; // $Id: $ category = "Commutative Algebra"; info=" LIBRARY: modwalk.lib Groebner basis convertion AUTHORS: S. Oberfranz oberfran@mathematik.uni-kl.de OVERVIEW: A library for converting Groebner bases of an ideal in the polynomial ring over the rational numbers using modular methods. The procedures are inspired by the following paper: Elizabeth A. Arnold: Modular algorithms for computing Groebner bases. Journal of Symbolic Computation 35, 403-419 (2003). PROCEDURES: modWalk(I,#); standard basis conversion of I by Groebner Walk using modular methods modrWalk(I,radius,#); standard basis conversion of I by Random Walk using modular methods modfWalk(I,#); standard basis conversion of I by Fractal Walk using modular methods modfrWalk(I,radius,#); standard basis conversion of I by Random Fractal Walk using modular methods "; LIB "rwalk.lib"; LIB "grwalk.lib"; LIB "modular.lib"; proc modWalk(ideal I, list #) "USAGE: modWalk(I, [, v, w]); I ideal, v intvec or string, w intvec If v intvec, then I is assumed to be a standard basis with respect to (a(v),lp). If v string, then either v="dp" or v="Dp" and I is assumed to be a standard basis with respect to dp or Dp, respectively. If w is given, then a standard basis with respect to (a(w),lp) will be computed. Otherwise, the output will be a standard basis with respect to lp. If no optional argument is given, I is assumed to be a standard basis with respect to dp and a standard basis with respect to lp will be computed. RETURN: a standard basis of I NOTE: The procedure computes a standard basis of I (over the rational numbers) by using modular methods. SEE ALSO: modular EXAMPLE: example modWalk; shows an example" { /* save options */ intvec opt = option(get); option(redSB); /* call modular() */ if (size(#) > 0) { I = modular("gwalk", list(I,#), primeTest_std, deleteUnluckyPrimes_std, pTest_std, finalTest_std); } else { I = modular("gwalk", list(I), primeTest_std, deleteUnluckyPrimes_std, pTest_std, finalTest_std); } /* return the result */ attrib(I, "isSB", 1); option(set, opt); return(I); } example { "EXAMPLE:"; echo = 2; ring R1 = 0, (x,y,z,t), dp; ideal I = 3x3+x2+1, 11y5+y3+2, 5z4+z2+4; I = std(I); ring R2 = 0, (x,y,z,t), lp; ideal I = fetch(R1, I); ideal J = modWalk(I); J; ring S1 = 0, (a,b,c,d), Dp; ideal I = 5b2, ac2+9d3+3a2+5b, 2a2c+7abd+bcd+4a2, 2ad2+6b2d+7c3+8ad+4c; I = std(I); ring S2 = 0, (c,d,b,a), lp; ideal I = fetch(S1,I); // I is assumed to be a Dp-Groebner basis. // We compute a lp-Groebner basis. ideal J = modWalk(I,"Dp"); J; intvec w = 3,2,1,2; ring S3 = 0, (c,d,b,a), (a(w),lp); ideal I = fetch(S1,I); // I is assumed to be a Dp-Groebner basis. // We compute a (a(w),lp)-Groebner basis. ideal J = modWalk(I,"Dp",w); J; } proc modrWalk(ideal I, int radius, list #) "USAGE: modrWalk(I, radius[, v, w]); I ideal, radius int, pertdeg int, v intvec or string, w intvec If v intvec, then I is assumed to be a standard basis with respect to (a(v),lp). If v string, then either v="dp" or v="Dp" and I is assumed to be a standard basis with respect to dp or Dp, respectively. If w is given, then a standard basis with respect to (a(w),lp) will be computed. Otherwise, the output will be a standard basis with respect to lp. If no optional argument is given, I is assumed to be a standard basis with respect to dp and a standard basis with respect to lp will be computed. RETURN: a standard basis of I NOTE: The procedure computes a standard basis of I (over the rational numbers) by using modular methods. SEE ALSO: modular EXAMPLE: example modrWalk; shows an example" { /* save options */ intvec opt = option(get); option(redSB); /* call modular() */ if (size(#) > 0) { I = modular("rwalk", list(I,radius,1,#), primeTest_std, deleteUnluckyPrimes_std, pTest_std, finalTest_std); } else { I = modular("rwalk", list(I,radius,1), primeTest_std, deleteUnluckyPrimes_std, pTest_std,finalTest_std); } /* return the result */ attrib(I, "isSB", 1); option(set, opt); return(I); } example { "EXAMPLE:"; echo = 2; ring R1 = 0, (x,y,z,t), dp; ideal I = 3x3+x2+1, 11y5+y3+2, 5z4+z2+4; I = std(I); ring R2 = 0, (x,y,z,t), lp; ideal I = fetch(R1, I); int radius = 2; ideal J = modrWalk(I,radius); J; ring S1 = 0, (a,b,c,d), Dp; ideal I = 5b2, ac2+9d3+3a2+5b, 2a2c+7abd+bcd+4a2, 2ad2+6b2d+7c3+8ad+4c; I = std(I); ring S2 = 0, (c,d,b,a), lp; ideal I = fetch(S1,I); // I is assumed to be a Dp-Groebner basis. // We compute a lp-Groebner basis. ideal J = modrWalk(I,radius,"Dp"); J; intvec w = 3,2,1,2; ring S3 = 0, (c,d,b,a), (a(w),lp); ideal I = fetch(S1,I); // I is assumed to be a Dp-Groebner basis. // We compute a (a(w),lp)-Groebner basis. ideal J = modrWalk(I,radius,"Dp",w); J; } proc modfWalk(ideal I, list #) "USAGE: modfWalk(I, [, v, w]); I ideal, v intvec or string, w intvec If v intvec, then I is assumed to be a standard basis with respect to (a(v),lp). If v string, then either v="dp" or v="Dp" and I is assumed to be a standard basis with respect to dp or Dp, respectively. If w is given, then a standard basis with respect to (a(w),lp) will be computed. Otherwise, the output will be a standard basis with respect to lp. If no optional argument is given, I is assumed to be a standard basis with respect to dp and a standard basis with respect to lp will be computed. RETURN: a standard basis of I NOTE: The procedure computes a standard basis of I (over the rational numbers) by using modular methods. SEE ALSO: modular EXAMPLE: example modfWalk; shows an example" { /* save options */ intvec opt = option(get); option(redSB); /* call modular() */ if (size(#) > 0) { I = modular("fwalk", list(I,#), primeTest_std, deleteUnluckyPrimes_std, pTest_std, finalTest_std); } else { I = modular("fwalk", list(I), primeTest_std, deleteUnluckyPrimes_std, pTest_std, finalTest_std); } /* return the result */ attrib(I, "isSB", 1); option(set, opt); return(I); } example { "EXAMPLE:"; echo = 2; ring R1 = 0, (x,y,z,t), dp; ideal I = 3x3+x2+1, 11y5+y3+2, 5z4+z2+4; I = std(I); ring R2 = 0, (x,y,z,t), lp; ideal I = fetch(R1, I); ideal J = modfWalk(I); J; ring S1 = 0, (a,b,c,d), Dp; ideal I = 5b2, ac2+9d3+3a2+5b, 2a2c+7abd+bcd+4a2, 2ad2+6b2d+7c3+8ad+4c; I = std(I); ring S2 = 0, (c,d,b,a), lp; ideal I = fetch(S1,I); // I is assumed to be a Dp-Groebner basis. // We compute a lp-Groebner basis. ideal J = modfWalk(I,"Dp"); J; intvec w = 3,2,1,2; ring S3 = 0, (c,d,b,a), (a(w),lp); ideal I = fetch(S1,I); // I is assumed to be a Dp-Groebner basis. // We compute a (a(w),lp)-Groebner basis. ideal J = modfWalk(I,"Dp",w); J; } proc modfrWalk(ideal I, int radius, list #) "USAGE: modfrWalk(I, radius [, v, w]); I ideal, radius int, v intvec or string, w intvec If v intvec, then I is assumed to be a standard basis with respect to (a(v),lp). If v string, then either v="dp" or v="Dp" and I is assumed to be a standard basis with respect to dp or Dp, respectively. If w is given, then a standard basis with respect to (a(w),lp) will be computed. Otherwise, the output will be a standard basis with respect to lp. If no optional argument is given, I is assumed to be a standard basis with respect to dp and a standard basis with respect to lp will be computed. RETURN: a standard basis of I NOTE: The procedure computes a standard basis of I (over the rational numbers) by using modular methods. SEE ALSO: modular EXAMPLE: example modfrWalk; shows an example" { /* save options */ intvec opt = option(get); option(redSB); /* call modular() */ if (size(#) > 0) { I = modular("frandwalk", list(I,radius,#), primeTest_std, deleteUnluckyPrimes_std, pTest_std, finalTest_std); } else { I = modular("frandwalk", list(I,radius), primeTest_std, deleteUnluckyPrimes_std, pTest_std, finalTest_std); } /* return the result */ attrib(I, "isSB", 1); option(set, opt); return(I); } example { "EXAMPLE:"; echo = 2; ring R1 = 0, (x,y,z,t), dp; ideal I = 3x3+x2+1, 11y5+y3+2, 5z4+z2+4; I = std(I); ring R2 = 0, (x,y,z,t), lp; ideal I = fetch(R1, I); int radius = 2; ideal J = modfrWalk(I,radius); J; ring S1 = 0, (a,b,c,d), Dp; ideal I = 5b2, ac2+9d3+3a2+5b, 2a2c+7abd+bcd+4a2, 2ad2+6b2d+7c3+8ad+4c; I = std(I); ring S2 = 0, (c,d,b,a), lp; ideal I = fetch(S1,I); // I is assumed to be a Dp-Groebner basis. // We compute a lp-Groebner basis. ideal J = modfrWalk(I,radius,"Dp"); J; intvec w = 3,2,1,2; ring S3 = 0, (c,d,b,a), (a(w),lp); ideal I = fetch(S1,I); // I is assumed to be a Dp-Groebner basis. // We compute a (a(w),lp)-Groebner basis. ideal J = modfrWalk(I,radius,"Dp",w); J; } /* test if the prime p is suitable for the input, i.e. it does not divide * the numerator or denominator of any of the coefficients */ static proc primeTest_std(int p, alias list args) { /* erase zero generators */ ideal I = simplify(args[1], 2); /* clear denominators and count the terms */ ideal J; ideal K; int n = ncols(I); intvec sizes; number cnt; int i; for(i = n; i > 0; i--) { J[i] = cleardenom(I[i]); cnt = leadcoef(J[i])/leadcoef(I[i]); K[i] = numerator(cnt)*var(1)+denominator(cnt); } sizes = size(J[1..n]); /* change to characteristic p */ def br = basering; list lbr = ringlist(br); if (typeof(lbr[1]) == "int") { lbr[1] = p; } else { lbr[1][1] = p; } def rp = ring(lbr); setring(rp); ideal Jp = fetch(br, J); ideal Kp = fetch(br, K); /* test if any coefficient is missing */ if (intvec(size(Kp[1..n])) != 2:n) { setring(br); return(0); } if (intvec(size(Jp[1..n])) != sizes) { setring(br); return(0); } setring(br); return(1); } /* find entries in modresults which come from unlucky primes. * For this, sort the entries into categories depending on their leading * ideal and return the indices in all but the biggest category. */ static proc deleteUnluckyPrimes_std(alias list modresults) { int size_modresults = size(modresults); /* sort results into categories. * each category is represented by three entries: * - the corresponding leading ideal * - the number of elements * - the indices of the elements */ list cat; int size_cat; ideal L; int i; int j; for (i = 1; i <= size_modresults; i++) { L = lead(modresults[i]); attrib(L, "isSB", 1); for (j = 1; j <= size_cat; j++) { if (size(L) == size(cat[j][1]) && size(reduce(L, cat[j][1])) == 0 && size(reduce(cat[j][1], L)) == 0) { cat[j][2] = cat[j][2]+1; cat[j][3][cat[j][2]] = i; break; } } if (j > size_cat) { size_cat++; cat[size_cat] = list(); cat[size_cat][1] = L; cat[size_cat][2] = 1; cat[size_cat][3] = list(i); } } /* find the biggest categories */ int cat_max = 1; int max = cat[1][2]; for (i = 2; i <= size_cat; i++) { if (cat[i][2] > max) { cat_max = i; max = cat[i][2]; } } /* return all other indices */ list unluckyIndices; for (i = 1; i <= size_cat; i++) { if (i != cat_max) { unluckyIndices = unluckyIndices + cat[i][3]; } } return(unluckyIndices); } /* test if 'command' applied to 'args' in characteristic p is the same as 'result' mapped to characteristic p */ static proc pTest_std(string command, alias list args, alias ideal result, int p) { /* change to characteristic p */ def br = basering; list lbr = ringlist(br); if (typeof(lbr[1]) == "int") { lbr[1] = p; } else { lbr[1][1] = p; } def rp = ring(lbr); setring(rp); ideal Ip = fetch(br, args)[1]; list Arg = fetch(br, args); string exstr; ideal Gp = fetch(br, result); attrib(Gp, "isSB", 1); /* test if Ip is in Gp */ int i; for (i = ncols(Ip); i > 0; i--) { if (reduce(Ip[i], Gp, 1) != 0) { setring(br); return(0); } } /* compute command(args) */ exstr = "Ip = "+command+" (Ip"; for(i=2; i<=size(Arg); i++) { exstr = exstr+",Arg["+string(eval(i))+"]"; } exstr = exstr+");"; execute(exstr); /* test if Gp is in Ip */ for (i = ncols(Gp); i > 0; i--) { if (reduce(Gp[i], Ip, 1) != 0) { setring(br); return(0); } } setring(br); return(1); } /* test if 'result' is a GB of the input ideal */ static proc finalTest_std(string command, alias list args, ideal result) { /* test if args[1] is in result */ attrib(result, "isSB", 1); int i; for (i = ncols(args[1]); i > 0; i--) { if (reduce(args[1][i], result, 1) != 0) { return(0); } } /* test if result is in args[1]. */ /* args[1] is given by a Groebner basis. Thus we may */ /* reduce the result with respect to args[1]. */ int n=nvars(basering); string ord_str = "dp"; for(i=2; i<=size(args); i++) { if(typeof(args[i]) == "list") { if(typeof(args[i][1]) == "intvec") { ord_str = "(a("+string(args[i][1])+"),lp("+string(n) + "),C)"; break; } if(typeof(args[i][1]) == "string") { if(args[i][1] == "Dp") { ord_str = "Dp"; } break; } } } ideal xI = args[1]; ring xR = basering; execute("ring yR = ("+charstr(xR)+"),("+varstr(xR)+"),"+ord_str+";"); ideal yI = fetch(xR,xI); ideal yresult = fetch(xR,result); attrib(yI, "isSB", 1); for(i=size(yresult); i>0; i--) { if(reduce(yresult[i],yI) != 0) { return(0); } } setring xR; kill yR; /* test if result is a Groebner basis */ link l1="ssi:fork"; open(l1); link l2="ssi:fork"; open(l2); list l=list(l1,l2); write(l1,quote(TestSBred(result))); write(l2,quote(TestSBstd(result))); i=waitfirst(l); if(i==1) { i=read(l1); } else { i=read(l2); } close(l1); close(l2); return(i); } /* return 1, if I_reduce is _not_ in G_reduce, * 0, otherwise * (same as size(reduce(I_reduce, G_reduce))). * Uses parallelization. */ static proc reduce_parallel(def I_reduce, def G_reduce) { exportto(Modwalk, I_reduce); exportto(Modwalk, G_reduce); int size_I = ncols(I_reduce); int chunks = Modular::par_range(size_I); intvec range; int i; for (i = chunks; i > 0; i--) { range = Modular::par_range(size_I, i); task t(i) = "Modwalk::reduce_task", list(range); } startTasks(t(1..chunks)); waitAllTasks(t(1..chunks)); int result = 0; for (i = chunks; i > 0; i--) { if (getResult(t(i))) { result = 1; break; } } kill I_reduce; kill G_reduce; return(result); } /* compute a chunk of reductions for reduce_parallel */ static proc reduce_task(intvec range) { int result = 0; int i; for (i = range[1]; i <= range[2]; i++) { if (reduce(I_reduce[i], G_reduce, 1) != 0) { result = 1; break; } } return(result); } /* test if result is a GB with std*/ static proc TestSBstd(ideal result) { ideal G = std(result); if(reduce_parallel(G,result)) { return(0); } return(1); } /* test if result is a GB by reducing s-polynomials*/ static proc TestSBred(ideal result) { int i,j; for(i=1; i<=size(result); i++) { for(j=i; j<=size(result); j++) { if(reduce(sPolynomial(result[i],result[j]),result)!=0) { return(0); } } } return(1); } /* compute s-polynomial of f and g */ static proc sPolynomial(poly f,poly g) { int i; poly lcmp = 1; intvec lexpf = leadexp(f); intvec lexpg = leadexp(g); for(i=1; i<=nvars(basering); i++) { if(lexpf[i]>=lexpg[i]) { lcmp=lcmp*var(i)**lexpf[i]; } else { lcmp=lcmp*var(i)**lexpg[i]; } } poly fmult=lcmp/leadmonom(f); poly gmult=lcmp/leadmonom(g); poly result=leadcoef(g)*fmult*f-leadcoef(f)*gmult*g; return(result); } singular-4.0.3+ds/Singular/LIB/mondromy.lib000066400000000000000000000666771266270727000205310ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version mondromy.lib 4.0.1.0 Sep_2014 "; // $Id: de231cbef5129df1a9cd4c4307e90286ce1e4fc5 $ category="Singularities"; info=" LIBRARY: mondromy.lib Monodromy of an Isolated Hypersurface Singularity AUTHOR: Mathias Schulze, email: mschulze@mathematik.uni-kl.de OVERVIEW: A library to compute the monodromy of an isolated hypersurface singularity. It uses an algorithm by Brieskorn (manuscripta math. 2 (1970), 103-161) to compute a connection matrix of the meromorphic Gauss-Manin connection up to arbitrarily high order, and an algorithm of Gerard and Levelt (Ann. Inst. Fourier, Grenoble 23,1 (1973), pp. 157-195) to transform it to a simple pole. PROCEDURES: detadj(U); determinant and adjoint matrix of square matrix U invunit(u,n); series inverse of polynomial u up to order n jacoblift(f); lifts f^kappa in jacob(f) with minimal kappa monodromyB(f[,opt]); monodromy of isolated hypersurface singularity f H2basis(f); basis of Brieskorn lattice H'' KEYWORDS: Monodromy; hypersurface singularity; Gauss-Manin connection; Brieskorn lattice SEE ALSO: gmspoly_lib, gmssing_lib "; LIB "ring.lib"; LIB "sing.lib"; LIB "linalg.lib"; /////////////////////////////////////////////////////////////////////////////// static proc pcvladdl(list l1,list l2) { return(system("pcvLAddL",l1,l2)); } static proc pcvpmull(poly p,list l) { return(system("pcvPMulL",p,l)); } static proc pcvmindeg(list #) { return(system("pcvMinDeg",#[1])); } static proc pcvp2cv(list l,int i0,int i1) { return(system("pcvP2CV",l,i0,i1)); } static proc pcvcv2p(list l,int i0,int i1) { return(system("pcvCV2P",l,i0,i1)); } static proc pcvdim(int i0,int i1) { return(system("pcvDim",i0,i1)); } static proc pcvbasis(int i0,int i1) { return(system("pcvBasis",i0,i1)); } /////////////////////////////////////////////////////////////////////////////// static proc min(intvec v) { int m=v[1]; int i; for(i=2;i<=size(v);i++) { if(m>v[i]) { m=v[i]; } } return(m); } /////////////////////////////////////////////////////////////////////////////// static proc max(intvec v) { int m=v[1]; int i; for(i=2;i<=size(v);i++) { if(m=1;i--) { for(j=ncols(m);j>=1;j--) { m[i,j]=m[i,j]/p; } } return(m); } /////////////////////////////////////////////////////////////////////////////// proc codimV(list V,int N) { int codim=pcvdim(0,N); if(size(V)>0) { dbprint(printlevel-voice+2,"//vector space dimension: "+string(codim)); dbprint(printlevel-voice+2, "//number of subspace generators: "+string(size(V))); int t=timer; codim=codim-ncols(interred(module(V[1..size(V)]))); dbprint(printlevel-voice+2,"//codimension: "+string(codim)); } return(codim); } /////////////////////////////////////////////////////////////////////////////// proc quotV(list V,int N) { module Q=freemodule(pcvdim(0,N)); if(size(V)>0) { dbprint(printlevel-voice+2,"//vector space dimension: "+string(nrows(Q))); dbprint(printlevel-voice+2, "//number of subspace generators: "+string(size(V))); int t=timer; Q=interred(reduce(std(Q),std(module(V[1..size(V)])))); } return(list(Q[1..size(Q)])); } /////////////////////////////////////////////////////////////////////////////// proc invunit(poly u,int n) "USAGE: invunit(u,n); u poly, n int ASSUME: The polynomial u is a series unit. RETURN: The procedure returns the series inverse of u up to order n or a zero polynomial if u is no series unit. DISPLAY: The procedure displays comments if printlevel>=1. EXAMPLE: example invunit; shows an example. " { if(pcvmindeg(u)==0) { dbprint(printlevel-voice+2,"//computing inverse..."); int t=timer; poly u0=jet(u,0); u=jet(1-u/u0,n); poly ui=u; poly v=1+u; int i; for(i=n div pcvmindeg(u);i>1;i--) { ui=jet(ui*u,n); v=v+ui; } v=jet(v,n)/u0; dbprint(printlevel-voice+2,"//...inverse computed ["+string(timer-t)+ " secs, "+string((memory(1)+1023)/1024)+" K]"); return(v); } else { print("//no series unit"); return(poly(0)); } } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),dp; invunit(2+x3+xy4,10); } /////////////////////////////////////////////////////////////////////////////// proc detadj(module U) "USAGE: detadj(U); U matrix ASSUME: U is a square matrix with non zero determinant. RETURN: The procedure returns a list with at most 2 entries. If U is not a sqaure matrix, the list is empty. If U is a sqaure matrix, then the first entry is the determinant of U. If U is a square matrix and the determinant of U not zero, then the second entry is the adjoint matrix of U. DISPLAY: The procedure displays comments if printlevel>=1. EXAMPLE: example detadj; shows an example. " { if(nrows(U)==ncols(U)) { dbprint(printlevel-voice+2,"//computing determinant..."); int t=timer; poly detU=det(U); dbprint(printlevel-voice+2,"//...determinant computed ["+string(timer-t)+ " secs, "+string((memory(1)+1023)/1024)+" K]"); if(detU==0) { print("//determinant zero"); return(list(detU)); } else { def br=basering; def pr=changeord(list(list("dp",1:nvars(basering)))); setring pr; matrix U=fetch(br,U); poly detU=fetch(br,detU); dbprint(printlevel-voice+2,"//computing adjoint matrix..."); t=timer; matrix adjU=lift(U,detU*freemodule(nrows(U))); dbprint(printlevel-voice+2,"//...adjoint matrix computed [" +string(timer-t)+" secs, "+string((memory(1)+1023)/1024)+" K]"); setring br; matrix adjU=fetch(pr,adjU); kill pr; } } else { print("//no square matrix"); return(list()); } return(list(detU,adjU)); } example { "EXAMPLE:"; echo=2; ring R=0,x,dp; matrix U[2][2]=1,1+x,1+x2,1+x3; list daU=detadj(U); daU[1]; print(daU[2]); } /////////////////////////////////////////////////////////////////////////////// proc jacoblift(poly f) "USAGE: jacoblift(f); f poly ASSUME: The polynomial f in a series ring (local ordering) defines an isolated hypersurface singularity. RETURN: The procedure returns a list with entries kappa, xi, u of type int, vector, poly such that kappa is minimal with f^kappa in jacob(f), u is a unit, and u*f^kappa=(matrix(jacob(f))*xi)[1,1]. DISPLAY: The procedure displays comments if printlevel>=1. EXAMPLE: example jacoblift; shows an example. " { dbprint(printlevel-voice+2,"//computing kappa..."); int t=timer; ideal jf=jacob(f); ideal sjf=std(jf); int kappa=1; poly fkappa=f; while(reduce(fkappa,sjf)!=0) { dbprint(printlevel-voice+2,"//kappa="+string(kappa)); kappa++; fkappa=fkappa*f; } dbprint(printlevel-voice+2,"//kappa="+string(kappa)); dbprint(printlevel-voice+2,"//...kappa computed ["+string(timer-t)+" secs, " +string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2,"//computing xi..."); t=timer; vector xi=lift(jf,fkappa)[1]; dbprint(printlevel-voice+2,"//...xi computed ["+string(timer-t)+" secs, " +string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2,"//computing u..."); t=timer; poly u=(matrix(jf)*xi)[1,1]/fkappa; dbprint(printlevel-voice+2,"//...u computed ["+string(timer-t)+" secs, " +string((memory(1)+1023)/1024)+" K]"); return(list(kappa,xi,u)); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),ds; poly f=x2y2+x6+y6; jacoblift(f); } /////////////////////////////////////////////////////////////////////////////// static proc getdeltaP1(poly f,int K,int N,int dN) { return(pcvpmull(f^K,pcvbasis(0,N+dN-K*pcvmindeg(f)))); } /////////////////////////////////////////////////////////////////////////////// static proc getdeltaP2(poly f,int N,int dN) { def of,jf=pcvmindeg(f),jacob(f); list b=pcvbasis(N-of+2,N+dN-of+2); list P2; P2[size(b)*((nvars(basering)-1)*nvars(basering)) div 2]=0; int i,j,k,l; intvec alpha; for(k,l=1,1;k<=size(b);k++) { alpha=leadexp(b[k]); for(i=nvars(basering)-1;i>=1;i--) { for(j=nvars(basering);j>i;j--) { P2[l]=alpha[i]*jf[j]*(b[k]/var(i))-alpha[j]*jf[i]*(b[k]/var(j)); l++; } } } return(P2); } /////////////////////////////////////////////////////////////////////////////// static proc getdeltaPe(poly f,list e,int K,int dK) { int k; list Pe,fke; for(k,fke=K,pcvpmull(f^K,e);k=1;j--) { q=jet(e[i]*xi[j],N); if(q!=0) { p=p+diff(q*jet(u,N-pcvmindeg(q)),var(j)); } } nablae=nablae+list(p-jet(fkappa*e[i],N-1)); } return(pcvladdl(Vnablae,pcvp2cv(nablae,prevN,N-prevN))); } /////////////////////////////////////////////////////////////////////////////// static proc MK(poly f,int mu,int kappa,vector xi,poly u, int K,int N,int prevN,list e,list V1,list V2,list Ve,list Vnablae) { dbprint(printlevel-voice+2,"//computing nabla(e)..."); int t=timer; Vnablae=nablaK(f,kappa,xi,u,N,prevN,Vnablae,e); dbprint(printlevel-voice+2,"//...nabla(e) computed ["+string(timer-t) +" secs, "+string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2, "//lifting nabla(e) to C-basis of H''/t^KH''..."); list V=Ve+V1+V2; module W=module(V[1..size(V)]); dbprint(printlevel-voice+2,"//vector space dimension: "+string(nrows(W))); dbprint(printlevel-voice+2,"//number of generators: "+string(ncols(W))); t=timer; matrix C=lift(W,module(Vnablae[1..size(Vnablae)])); dbprint(printlevel-voice+2,"//...nabla(e) lifted ["+string(timer-t) +" secs, "+string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2,"//computing e-lift of nabla(e)..."); t=timer; int i1,i2,j,k; matrix M[mu][mu]; for(j=1;j<=mu;j++) { for(k,i2=0,1;k=1;i--) { for(j=i-1;j>=1;j--) { id=int(l[i]-l[j]); id=max(intvec(id,-id)); mid=max(intvec(id,mid)); } } return(mid); } /////////////////////////////////////////////////////////////////////////////// static proc decmide(matrix M,ideal eM0,list bM0) { matrix M0=jet(M,0); dbprint(printlevel-voice+2, "//computing basis U of generalized eigenspaces of M0..."); int t=timer; int i,j; matrix U,M0e; matrix E=freemodule(nrows(M)); for(i=ncols(eM0);i>=1;i--) { M0e=E; for(j=max(bM0[i]);j>=1;j--) { M0e=M0e*(M0-eM0[i]*E); } U=syz(M0e)+U; } dbprint(printlevel-voice+2,"//...U computed ["+string(timer-t)+" secs, " +string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2,"//transforming M to U..."); t=timer; list daU=detadj(U); daU[2]=(1/number(daU[1]))*daU[2]; M=daU[2]*M*U; dbprint(printlevel-voice+2,"//...M transformed ["+string(timer-t)+" secs, " +string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2, "//computing integer differences of eigenvalues of M0..."); t=timer; int k; intvec ideM0; ideM0[ncols(eM0)]=0; for(i=ncols(eM0);i>=1;i--) { for(j=ncols(eM0);j>=1;j--) { k=int(eM0[i]-eM0[j]); if(k) { if(k>0) { ideM0[i]=max(intvec(k,ideM0[i])); } else { ideM0[j]=max(intvec(-k,ideM0[j])); } } } } for(i,k=size(bM0),nrows(M);i>=1;i--) { for(j=sum(bM0[i]);j>=1;j--) { ideM0[k]=ideM0[i]; k--; } } dbprint(printlevel-voice+2, "//...integer differences of eigenvalues of M0 computed ["+string(timer-t) +" secs, "+string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2,"//transforming M..."); t=timer; for(i=nrows(M);i>=1;i--) { if(!ideM0[i]) { M[i,i]=M[i,i]+1; } for(j=ncols(M);j>=1;j--) { if(ideM0[i]&&!ideM0[j]) { M[i,j]=M[i,j]*var(1); } else { if(!ideM0[i]&&ideM0[j]) { M[i,j]=M[i,j]/var(1); } } } } dbprint(printlevel-voice+2,"//...M transformed ["+string(timer-t)+" secs, " +string((memory(1)+1023)/1024)+" K]"); return(M); } /////////////////////////////////////////////////////////////////////////////// static proc nonqhmonodromy(poly f,int mu,int opt) { dbprint(printlevel-voice+2,"//computing kappa, xi and u with "+ "u*f^kappa=(matrix(jacob(f))*xi)[1,1]..."); list jl=jacoblift(f); def kappa,xi,u=jl[1..3]; dbprint(printlevel-voice+2,"//...kappa, xi and u computed"); dbprint(printlevel-voice+2,"//kappa="+string(kappa)); if(kappa==1) { dbprint(printlevel-voice+2, "//f quasihomogenous with respect to suitable coordinates"); } else { dbprint(printlevel-voice+2, "//f not quasihomogenous for any choice of coordinates"); } dbprint(printlevel-voice+2,"//xi="); dbprint(printlevel-voice+2,xi); dbprint(printlevel-voice+2,"//u="+string(u)); int K,N,prevN; list e,P1,P2,Pe,V1,V2,Ve,Vnablae; dbprint(printlevel-voice+2,"//increasing K and N..."); K,N,P1,P2,Pe,V1,V2,Ve=incK(f,mu,K,1,N,e,P1,P2,Pe,V1,V2,Ve); dbprint(printlevel-voice+2,"//...K and N increased"); dbprint(printlevel-voice+2,"//computing C{f}-basis e of Brieskorn lattice " +"H''=Omega^(n+1)/df^dOmega^(n-1)..."); int t=timer; e=pcvcv2p(quotV(V1+V2,N),0,N); dbprint(printlevel-voice+2,"//...e computed ["+string(timer-t)+" secs, " +string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2,"//e="); dbprint(printlevel-voice+2,e); Pe=e; Ve=pcvp2cv(Pe,0,N); if(kappa==1) { dbprint(printlevel-voice+2, "//computing 0-jet M of e-matrix of t*nabla..."); matrix M=list(MK(f,mu,kappa,xi,u,K,N,prevN,e,V1,V2,Ve,Vnablae))[1]; dbprint(printlevel-voice+2,"//...M computed"); } else { dbprint(printlevel-voice+2, "//computing transformation matrix U to simple pole..."); dbprint(printlevel-voice+2,"//computing t*nabla-stable lattice..."); matrix M,prevU; matrix U=freemodule(mu)*var(1)^((mu-1)*(kappa-1)); int i; dbprint(printlevel-voice+2,"//comparing with previous lattice..."); t=timer; for(i=mu-1;i>=1&&size(reduce(U,std(prevU)))>0;i--) { dbprint(printlevel-voice+2,"//...compared with previous lattice [" +string(timer-t)+" secs, "+string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2,"//increasing K and N..."); K,N,P1,P2,Pe,V1,V2,Ve=incK(f,mu,K,kappa-1,N,e,P1,P2,Pe,V1,V2,Ve); dbprint(printlevel-voice+2,"//...K and N increased"); dbprint(printlevel-voice+2, "//computing (K-1)-jet M of e-matrix of t^kappa*nabla..."); M,prevN,Vnablae=MK(f,mu,kappa,xi,u,K,N,prevN,e,V1,V2,Ve,Vnablae); dbprint(printlevel-voice+2,"//...M computed"); prevU=U; dbprint(printlevel-voice+2,"//enlarging lattice..."); t=timer; U=interred(jet(module(U)+module(var(1)*diff(U,var(1)))+ module(mdivp(M*U,var(1)^(kappa-1))),(kappa-1)*(mu-1))); dbprint(printlevel-voice+2,"//...lattice enlarged ["+string(timer-t) +" secs, "+string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2,"//comparing with previous lattice..."); t=timer; } dbprint(printlevel-voice+2,"//...compared with previous lattice [" +string(timer-t)+" secs, "+string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2,"//...t*nabla-stable lattice computed"); if(ncols(U)>nrows(U)) { dbprint(printlevel-voice+2, "//computing C{f}-basis of t*nabla-stable lattice..."); t=timer; U=minbase(U); dbprint(printlevel-voice+2, "//...C{f}-basis of t*nabla-stable lattice computed ["+string(timer-t) +" secs, "+string((memory(1)+1023)/1024)+" K]"); } U=mdivp(U,var(1)^pcvmindeg(U)); dbprint(printlevel-voice+2,"//...U computed"); dbprint(printlevel-voice+2, "//computing determinant and adjoint matrix of U..."); list daU=detadj(U); poly p=var(1)^min(intvec(pcvmindeg(daU[2]),pcvmindeg(daU[1]))); daU[1]=daU[1]/p; daU[2]=mdivp(daU[2],p); dbprint(printlevel-voice+2, "//...determinant and adjoint matrix of U computed"); if(K1) { dbprint(printlevel-voice+2, "//transforming M/t^kappa to simple pole..."); t=timer; M=mdivp(invunit(daU[1]/var(1)^pcvmindeg(daU[1]),delta)* daU[2]*(var(1)^kappa*diff(U,var(1))+M*U), var(1)^(kappa+pcvmindeg(daU[1])-1)); dbprint(printlevel-voice+2, "//...M/t^kappa transformed to simple pole ["+string(timer-t) +" secs, "+string((memory(1)+1023)/1024)+" K]"); } dbprint(printlevel-voice+2,"//decreasing delta..."); M=decmide(M,eM0,bM0); delta--; dbprint(printlevel-voice+2,"//delta="+string(delta)); while(delta>0) { jd=jordan(M); eM0,bM0=jd[1..2]; M=decmide(M,eM0,bM0); delta--; dbprint(printlevel-voice+2,"//delta="+string(delta)); } dbprint(printlevel-voice+2,"//...delta decreased"); } } dbprint(printlevel-voice+2,"//computing 0-jet M0 of M..."); matrix M0=jet(M,0); dbprint(printlevel-voice+2,"//...M0 computed"); return(M0); } /////////////////////////////////////////////////////////////////////////////// static proc qhmonodromy(poly f,intvec w) { dbprint(printlevel-voice+2,"//computing basis e of Milnor algebra..."); int t=timer; ideal e=kbase(std(jacob(f))); dbprint(printlevel-voice+2,"//...e computed ["+string(timer-t)+" secs, " +string((memory(1)+1023)/1024)+" K]"); dbprint(printlevel-voice+2, "//computing Milnor number mu and quasihomogeneous degree d..."); int mu,d=size(e),(transpose(leadexp(f))*w)[1]; dbprint(printlevel-voice+2,"...mu and d computed"); dbprint(printlevel-voice+2,"//computing te-matrix M of t*nabla..."); matrix M[mu][mu]; int i; for(i=mu;i>=1;i--) { M[i,i]=number((transpose(leadexp(e[i])+1)*w)[1])/d; } dbprint(printlevel-voice+2,"//...M computed"); return(M); } /////////////////////////////////////////////////////////////////////////////// proc monodromyB(poly f, list #) "USAGE: monodromyB(f[,opt]); f poly, opt int ASSUME: The polynomial f in a series ring (local ordering) defines an isolated hypersurface singularity. RETURN: The procedure returns a residue matrix M of the meromorphic Gauss-Manin connection of the singularity defined by f or an empty matrix if the assumptions are not fulfilled. If opt=0 (default), exp(-2*pi*i*M) is a monodromy matrix of f, else, only the characteristic polynomial of exp(-2*pi*i*M) coincides with the characteristic polynomial of the monodromy of f. DISPLAY: The procedure displays more comments for higher printlevel. EXAMPLE: example monodromyB; shows an example. " { int opt; if(size(#)>0) { if(typeof(#[1])=="int") { opt=#[1]; } else { print("\\second parameter no int"); return(); } } dbprint(printlevel-voice+2,"//basering="+string(basering)); int i; for(i=nvars(basering);i>=1;i--) { if(1= 1 ; i --) { if ( size(I[i]) > 1 ) { return (0); } } return (1); } ///////////////////////////////////////////////////////////////////////////// // static proc quotientIdealMon (ideal I,poly f) " USAGE: quotientIdealMon(I,f); I ideal, f polynomial. RETURN: an ideal, the quotient ideal I:(f). ASSUME: I is an ideal generated by a list of monomials and f is a monomial of the basering. " { // Variables int i,j; poly g,generator; intvec v; ideal J; J = 0; int sizI = ncols(I); for (i = 1 ; i <= sizI ; i++) { g = gcd(I[i],f); // Cociente de dos monomios: restamos los exponentes, y en el // denominador va el mcd v = leadexp(I[i]) - leadexp(g); generator = monomial (v); if (membershipMon(generator,J) == 0) { J=J,generator; } } // minimal monomial basis return ( minbase(J) ); } ///////////////////////////////////////////////////////////////////////////// // static proc soporte (poly f) " USAGE: soporte(f); f polynomial. RETURN: 0, if the monomial f is product of more than one variable; otherwise, an integer j, 1<=j<=n, if the monomial f is a power of x(j). ASSUME: f is a monomial of the basering K[x(1)..x(n)]. " { // Variables int i,cont,sop; intvec expf; int nvar = nvars(basering); expf = leadexp(f); cont = 0; // cont va a contar el numero de componentes del vector no nulas. // En sop guardamos el subindice de la componente no nula. for (i = nvar ; i >= 1 ; i--) { if (expf[i] > 0) { cont ++; sop = i; // Si cont > 1 ==> aparece mas de una variable, devolvemos 0 if (cont > 1) { return (0); } } } return(sop); } ///////////////////////////////////////////////////////////////////////////// // static proc irredAux (ideal I) " USAGE: irredAux (I); I ideal. RETURN: 1, if I is irreducible; otherwise, an intvec whose fist entry is the position of a generator which is the product of more than one variable, the next entries are the indexes of those variables. ASSUME: I is a monomial ideal of the basering K[x(1)..x(n)] and it is generated by its minimal monomial generators. NOTE: This procedure is a modification of isirreducibleMon to give more information when ideal is not irreducible. " { // Variables int sizI,i,nvar,j,sum; intvec w,exp; sizI = ncols(I); nvar = nvars(basering); for (i = 1 ; i <= sizI ; i++) { sum = 0; exp = leadexp(I[i]); for (j = 1 ; j <= nvar ; j++) { // Al menos tenemos una variable en cada generador, luego // entramos minimo 1 vez, luego sum >= 1. if (exp[j] <> 0) { sum++; w[sum] = j; } } // Si hay mas de una variable la suma sera mayor que 1; y ya // sabemos que I no es irreducible. if (sum <> 1) { return(i,w); } } return(1); } ////////////////////////////////////////////////////////////////////// // static proc contents (ideal I,ideal J) " USAGE: contents (I,J); I,J ideals. RETURN: 1, if I is contained in J; 0, otherwise. ASSUME: I,J are monomial ideals of the basering. " { // Variables poly f; int i,resp; int n = ncols(I); // Desde que haya un generador que no pertenzca al ideal, ya no se da // el contenido y terminamos. for (i = 1 ; i <= n ; i++) { resp = membershipMon(I[i],J); if (resp == 0) { return(0); } } return(1); } ///////////////////////////////////////////////////////////////////////////// // static proc equal (ideal I,ideal J) " USAGE: equal (I,J); I,J ideals. RETURN: 1, if I and J are the same ideal; 0, otherwise. ASSUME: I,J are monomial ideals of the basering and are defined by their minimal monomial generators. " { // Variables int n,i,j; intvec resps; // Si no tienen el mismo numero de generadores, no pueden ser iguales; ya // que vienen dados por el sistema minimal de generadores. if (size(I) <> size(J)) { return(0); } // Como ambos ideales vienen dados por la base minimal, no vamos a // tener problemas con que comparemos uno de I con otro de J, pues // no puede haber generadores iguales en el mismo ideal. // Si los ordenamos, se puede comparar uno a uno return(matrix( sort(I)[1])==matrix(sort(J)[1])); //n = size(I); //I = sort(I)[1]; //J = sort(J)[1]; //for (i = 1 ; i <= n ; i++) //{ // if (I[i] <> J[i]) // { // return(0); // } //} //return(1); } ///////////////////////////////////////////////////////////////////////////// // static proc radicalAux (ideal I) " USAGE: radicalAux (I); I ideal. RETURN: an ideal, the radical ideal of I ASSUME: I is an irreducible monomial ideal of the basering given by its minimal monomial generators. " { // Cambiamos de anillo int nvar = nvars(basering); // Variables int i,cont; intvec exp; ideal rad; // Como en cada generador aparece solo una variable, y ademas la // la misma variable no va a aparecer dos veces, es suficiente // con sumar los exponentes de todos los generadores para saber que // variables aparecen. int n = ncols(I); for (i = 1 ; i <= n ; i++) { exp = exp + leadexp (I[i]); } cont = 1; for (i = 1 ; i <= nvar ; i++) { if (exp[i] <> 0) { rad[cont] = var(i); cont ++; } } return (rad); } ///////////////////////////////////////////////////////////////////////////// // static proc primAux (ideal I) " USAGE: primAux (I); I ideal. RETURN: 1, if I is primary; otherwise, an intvec, whose first element is 0, the second is the index of one variable such that a power of it does not appear as a generator of I, the rest of the elements are the situation in the ideal of that elements of I which are product of more than one variable. ASSUME: I is a monomial ideal of the basering K[x(1)..x(n)]. NOTE: This procedure detects if the ideal is primary, when the ideal is not primary, it gives some additional information. " { // Variables int control,nvar,i,sub_in,l,j; intvec v,w,exp_gen; // El ideal ya entra generado por el sistema minimal nvar = nvars(basering); int sizI = ncols(I); v[nvar] = 0; int cont = 1; // v = 1 en la posicion en el ideal de variables sueltas, que son // las que no hay que tocar, 0 en las demas. w = posiciones de los // generadores de I que hay que comprobar. for (i = 1 ; i <= sizI ; i++ ) { sub_in = soporte(I[i]); if ( sub_in <> 0) { v[sub_in] = 1; } else { w[cont] = i; cont ++; } } l = size(w); // No hay ningun generador que tenga productos de variables, luego // este ideal ya es primario. if (l == 1 && w[1] == 0) { return (1); } for (i = 1 ; i <= l ; i++) { exp_gen = leadexp(I[w[i]]); // Ahora hay que ver que valor tiene el exponente de los // generadores oportunos en la posicion que es cero dentro del // vector v. for (j = 1 ; j <= nvar ; j++) { if (v[j] == 0) { if (exp_gen[j] <> 0) { return (0,j,w); } } } } // Si hemos llegado hasta aqui hemos recorrido todo el ideal y por tanto // es primario. return (1); } ///////////////////////////////////////////////////////////////////////////// // static proc maxExp (ideal I,intvec v) " USAGE: maxExp (I,v); I ideal, v integer vector. RETURN: an integer, the greatest power of a variable in the minimal monomial set of generators of I. ASSUME: I is a monomial ideal of the basering, v=primAux(I) and the variable considered is v[2]. If the ideal I is primary, it returns 0. NOTE: The elements of the vector shows what variable and what generators we must consider to look for the greatest power of this variable. " { // Variables int n,i,max; intvec exp; // Ponemos el tama?o de v menos 2 porque en el vector v a partir de // la tercera componente es donde tenemos la posicion de los // generadores que tenemos que estudiar. n = size(v)-2; // Buscamos el maximo de la variable que no aparece "sola" en los // generadores del ideal (donde nos indica v). max = 0; for (i = 1 ; i <= n ; i++) { exp = leadexp (I[v[i+2]]); if (exp[v[2]] > max) { max = exp[v[2]]; } } return (max); } ///////////////////////////////////////////////////////////////////////////// // static proc irredundant (list l) " USAGE: irredundant (l); l, list. RETURN: a list such that the intersection of the elements in that list has no redundant component. ASSUME: elements of l are monomial ideals of the basering. " { // Variables int i,j,resp; ideal J; // Recalculamos el tamano de l cuando modificamos la lista (sizl) int sizl = size(l); for (i = 1 ; i <= sizl ; i++) { J = 1; for (j = 1 ; j <= sizl ; j++) { // Hacemos la interseccion de todos los ideales menos uno y // luego se estudia el contenido. if (j <> i) { J = intersect (J,l[j]); } } J = minbase(J); resp = contents(J,l[i]); if (resp == 1) { l = delete (l,i); i--; sizl = size(l); } } return (l); } ///////////////////////////////////////////////////////////////////////////// // static proc alexDif (intvec v,ideal I) " USAGE: alexDif (v,I); v, intvec; I, ideal. RETURN: a list, irreducible monomial ideals whose intersection is the Alexander dual of I with respect to v. ASSUME: I is a monomial ideal of the basering K[x(1),...,x(n)] given by its minimal monomial generators and v is an integer vector with n entries s.t.monomial(v) is a multiple of all minimal monomial generators of I. " { // Cambiamos de anillo int nvar = nvars(basering); // Variables int i,j; intvec exp_I,exp; list l; ideal J; int sizI = ncols(I); // Vamos a tener tantas componentes como generadores minimales tiene el // ideal, por eso el bucle es de 1 a size(I). for (i = 1 ; i <= sizI ; i++) { J = 0; exp_I = leadexp (I[i]); for (j = 1 ; j <= nvar ; j++) { if (exp_I[j] <> 0) { exp[j] = v[j] + 1 - exp_I[j]; J = J, var(j)^exp[j]; } } // Tenemos siempre un cero por la inicializacion de J, entonces // lo quitamos. J = simplify (J,2); l = insert (l,J); } return (l); } ///////////////////////////////////////////////////////////////////////////// // static proc irredPrimary (list l1) " USAGE: irredPrimary (l1); l1, list of ideals. RETURN: a list, primary monomial ideals whose intersection is an irredundant primary decomposition. ASSUME: list l1 is the list of the irredundant irreducible components of a monomial ideal I of the basering. " { // Variables int i,sizl1,sizl2,j; ideal J,K; list l2,l3; //----- irredundant primary decomposition sizl1 = size(l1); for (i = 1 ; i <= sizl1 ; i++) { l2[i] = radicalAux (l1[i]); } sizl2 = size(l2); int sizl2i, sizl2j; // Looking for irreducible components whose radicals are equal. // l1 = irreducible components list // l2 = radical of irreducible components list // l3 = primary components list for (i = 1 ; i <= sizl1 ; i++) { J = l2[i]; sizl2i = size(l2[i]); K = l1[i]; for (j = i+1 ; j <= sizl2 ; j++) { sizl2j = size(l2[j]); if (sizl2i == sizl2j) { if (equal (J,l2[j]) == 1) { K = minbase(intersect (K,l1[j])); l1 = delete (l1,j); sizl1 = size(l1); l2 = delete (l2,j); sizl2 = size(l2); j--; } } } l3 = insert (l3,K); } return (l3); } ///////////////////////////////////////////////////////////////////////////// // static proc isMinimal (ideal I) " USAGE: isMinimal (I); I ideal. RETURN: 1, if the generators of I are the minimal ones; 0 & minimal generators of I, otherwise. ASSUME: I is an ideal of the basering generated by monomials. " { // VARIABLES int i; ideal J; // Quitamos los ceros del sistema de generadores. I = simplify(I,2); int resp = 1; int sizI = ncols(I); // Cambiamos el tamano de I cuando eliminamos generadores for (i = 1 ; i <= sizI ; i++) { if (sizI <> 1) { if (i == 1) { J = I[2..sizI]; } else { if (i > 1 && i < sizI) { J = I[1..i-1], I[i+1..sizI]; } else { J = I[1..sizI-1]; } } // Si quitamos el generador del lugar "i", luego el que // ocupa ahora el lugar "i" es el "i+1", de ahi que restemos // 1 al i para volver al for de manera que recorramos los // generadores como debemos. if (membershipMon(I[i],J) == 1) { resp = 0; I = J; i--; sizI = size(I); } } } if (resp == 1) { return (1); } else { return (0,I); } } ///////////////////////////////////////////////////////////////////////////// // static proc isMonomialGB (ideal I) " USAGE: isMonomialGB (I); I ideal. RETURN: a list, 1 & the minimal generators of I, if I is a monomial ideal; 0, otherwise. ASSUME: I is an ideal of the basering which is not generated by monomials. NOTE: this procedure is NOT Grobner free and should be used only if the ideal has non-monomial generators (use first checkIdeal) " { // Variables int resp; // Si el ideal es cero, no es monomial. if ( size(I) == 0) { return(0); } // Queremos la base de Grobner reducida, para uncidad. intvec save_opt=option(get); option(redSB); // Base de Grobner I = std(I); option(set,save_opt); // Una vez que tenemos la GB, no es mas que comprobar que el ideal // esta generado por monomios. resp = checkIdeal(I); if (resp == 0) { return (0); } else { return (1,I); } } ///////////////////////////////////////////////////////////////////////////// // // Comparing irreducible decompsitions // WARNING: this is not a test, when the answer is 1 and the decompositions // may not coincide but it is fast and easy and when the answer is // 0 the decomposition do not coincide. // proc areEqual(list l1,list l2) { int i,j,sizIdeal; poly generator; ideal l1Ideal,l2Ideal; int sizl1 = size(l1); for (i = 1 ; i <= sizl1 ; i ++) { sizIdeal = size(l1[i]); generator = 1; for (j = 1 ; j <= sizIdeal ; j ++) { generator = generator*l1[i][j]; } l1Ideal[i] = generator; } int sizl2 = size(l2); for (i = 1 ; i <= sizl2 ; i ++) { sizIdeal = size(l2[i]); generator = 1; for (j = 1 ; j <= sizIdeal ; j ++) { generator = generator*l2[i][j]; } l2Ideal[i] = generator; } return (equal(l1Ideal,l2Ideal)); } ///////////////////////////////////////////////////////////////////////////// //-------------------------------------------------------------------------// //----------------------- EXTERNOS ------------------------------------// //-------------------------------------------------------------------------// ///////////////////////////////////////////////////////////////////////////// // proc isMonomial (ideal I) "USAGE: isMonomial (I); I ideal. RETURN: 1, if I is monomial ideal; 0, otherwise. ASSUME: I is an ideal of the basering. EXAMPLE: example isMonomial; shows some examples. " { // Si el ideal es cero, no es monomial. if ( size(I) == 0) { return(0); } // Si ya viene dado por sistema de generadores monomiales, devolvemos 1 if (checkIdeal (I) == 1) { return(1); } // Variables int resp,m,k; // Queremos la base de Grobner reducida, para uncidad. intvec save_opt=option(get); option(redSB); // Hallamos GB I = std(I); option(set,save_opt); // Una vez que tenemos la GB, no es mas que comprobar si el ideal // esta generado por monomios. resp = checkIdeal(I); // Volvemos a dejar el comando "std" devolviendo una GB estandar. return(resp); } example { "EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^3*x*y, w^2*x^2*y^2*z^2 - y^3*z+x^4*z^4*t^4, w*x*y*z*t - w*x^6*y^5*z^4, x^2*z^4*t^3 , w^6*y^4*z^2 + x^2*y^2*z^2; isMonomial(I); ideal J = w^3*x*y + x^3*y^9*t^3, w^2*x^2*y^2*z^2 - y^3*z, w*x*y*z*t - w*x^6*y^5*z^4, x^2*z^4*t^3 + y^4*z^4*t^4, w^6*y^4*z^2 + x^2*y^2*z^2; isMonomial(J); } ///////////////////////////////////////////////////////////////////////////// // proc minbaseMon (ideal I) "USAGE: minbaseMon (I); I ideal. RETURN: an ideal, the minimal monomial generators of I. (-1 if the generators of I are not monomials) ASSUME: I is an ideal generated by a list of monomials of the basering. EXAMPLE: example minbaseMon; shows an example. " { // VARIABLES int i; ideal J; // Si no esta generado por monomios este metodo no vale int control = checkIdeal(I); if (control == 0) { return (-1); } // Quitamos los ceros del sistema de generadores. I = simplify(I,2); int sizI = ncols(I); for (i = 1 ; i <= sizI ; i++) { if (sizI > 1) { if (i == 1) { J = I[2..sizI]; } else { if (i > 1 && i < sizI) { J = I[1..i-1], I[i+1..sizI]; } else { if (i == sizI) { J = I[1..sizI-1]; } } } // Si quitamos el generador del lugar "i", luego el que // ocupa ahora el lugar "i" es el "i+1", de ahi que restemos // 1 al i para volver al for de manera que recorramos los // generadores como debemos. if (membershipMon(I[i],J) == 1) { I = J; i--; sizI = ncols(I); } } } return (I); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^3*x*y, w^2*x^2*y^2*z^2, y^3*z,x^4*z^4*t^4, w*x*y*z*t,w*x^6*y^5*z^4, x^2*z^4*t^3 , w^6*y^4*z^2,x^2*y^2*z^2; minbaseMon(I); } ///////////////////////////////////////////////////////////////////////////// // proc gcdMon (poly f,poly g) "USAGE: gcdMon (f,g); f,g polynomials. RETURN: a monomial, the greatest common divisor of f and g. ASSUME: f and g are monomials of the basering. EXAMPLE: example gcdMon; shows an example. " { if (size(f) <> 1 or size(g) <> 1) { ERROR ("the input must be 2 monomials."); } return(gcd(f,g)); // // Variables // int k; // intvec exp; // int nvar = nvars(basering); // // intput: monomials // // intvec expf = leadexp(f); // intvec expg = leadexp(g); // // Nos quedamos con el menor exponente de cada variable. // for (k = 1 ; k <= nvar ; k++) // { // if (expf[k] <= expg[k]) // { // exp[k] = expf[k]; // } // else // { // exp[k] = expg[k]; // } // } // // Devolvemos el monomio correspondiente al exponente que hemos // // calculado. // return(monomial(exp)); } example {"EXAMPLE:"; echo = 2; ring R = 0,(x,y,z,t),dp; poly f = x^3*z^5*t^2; poly g = y^6*z^3*t^3; gcdMon(f,g); } ///////////////////////////////////////////////////////////////////////////// // proc lcmMon (poly f,poly g) "USAGE: lcmMon (f,g); f,g polynomials. RETURN: a monomial,the least common multiple of f and g. ASSUME: f,g are monomials of the basering. EXAMPLE: example lcmMon; shows an example. " { // Hay que verificar que son monomios if (size(f) <> 1 or size(g) <> 1) { ERROR ("the input must be 2 monomials."); } return(f*g/gcd(f,g)); //// Variables. //int k; //intvec exp; //int nvar = nvars(basering); //// No tenemos mas que tomar el mayor exponente. //intvec expf = leadexp (f); //intvec expg = leadexp (g); //for (k = 1 ; k <= nvar ; k ++) //{ // if (expf[k] <= expg[k]) // { // exp[k] = expg[k]; // } // else // { // exp[k] = expf[k]; // } //} //// Transformamos el vector de exponentes al monomio correspondiente. //return(monomial (exp)); } example {"EXAMPLE:"; echo = 2; ring R = 0,(x,y,z,t),dp; poly f = x^3*z^5*t^2; poly g = y^6*z^3*t^3; lcmMon(f,g); } ////////////////////////////////////////////////////////////////////// // proc membershipMon(poly f,ideal I) "USAGE: membershipMon(f,I); f polynomial, I ideal. RETURN: 1, if f lies in I; 0 otherwise. (-1 if I and f are nonzero and I is not a monomial ideal) ASSUME: I is a monomial ideal of the basering. EXAMPLE: example membershipMon; shows some examples " { // Variables int i,j,resp,k,control; intvec restf; // Si el ideal es cero no es monomial, pero la pertenencia no se da si // el polinomio es no nulo if ( size(I) == 0 && size(f) > 0) { return (0); } // El cero esta en todos los ideales. if (f == 0) { return (1); } // COMPROBACIONES control = checkIdeal(I); if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { // Sabemos que I ya viene dado por el sistema minimal de // generadores, aunque aqui no sea necesario. I = isMon[2]; } } // Quitamos ceros. I = simplify(I,2); int n = ncols(I); int m = size(f); int nvar = nvars(basering); for (i=1 ; i<=m ; i++) { resp = 0; for (j=1 ; j<=n ;j++) { // Vamos termino a termino viendo si son divididos por algun // generador. Trabajamos con los exponentes, pues es mas // simple. restf = leadexp(f) - leadexp(I[j]); for (k=1 ; k<=nvar; k++) { // Si hay una componente negativa es que este generador // no divide. Queremos entonces ir al siguiente // generador. if (restf[k] < 0) { break; } } // Si no ha habido componente nula, hemos encontrado un // divisor para el actual termino de f. En esta situacion // queremos pasar a otro termino de f, no seguir con los // otros generadores. if (k == nvar+1) { resp = 1; break; } } // Si hemos encontrado para el anterior termino, voy al // siguiente; en caso contrario salimos, pues desde que un // termino no sea dividido, f no esta en I. if (resp == 1) { f = f - lead(f); } else { break; } } // Si hemos recorrido todo el bucle, f esta en I. if (i == m+1) { return (1); } return (0); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w*x, x^2, y*z*t, y^5*t; poly f = 3*x^2*y + 6*t^5*z*y^6 - 4*x^2 + 8*w*x^5*y^6 - 10*y^10*t^10; membershipMon(f,I); poly g = 3*w^2*t^3 - 4*y^3*z*t^3 - 2*x^2*y^5*t + 4*x*y^3; membershipMon(g,I); } ////////////////////////////////////////////////////////////////////// // proc intersectMon (ideal I,ideal J) "USAGE: intersectMon (I,J); I,J ideals. RETURN: an ideal, the intersection of I and J. (it returns -1 if I or J are not monomial ideals) ASSUME: I,J are monomial ideals of the basering. NOTE: the minimal monomial generating set is returned. EXAMPLE: example intersectMon; shows some examples " { // Variables ideal K; int i,j,control; list isMon; // El ideal trivial no es monomial. if ( size(I) == 0 || size(J) == 0) { ERROR("one of the ideals is zero, hence not monomial."); } // COMPROBACIONES control = checkIdeal(I); if (control == 0) { isMon = isMonomialGB(I); if (isMon[1] == 0) { ERROR ("the first ideal is not monomial."); } else { // Sabemos que I ya viene dado por el sistema minimal de // generadores, aunque aqui no sea necesario. I = isMon[2]; } } else { // Los generadores son monomiales, hallamos el sistema minimal I = minbase(I); } control = checkIdeal(J); if (control == 0) { isMon = isMonomialGB (J); if (isMon[1] == 0) { ERROR ("the second ideal is not monomial."); } else { // Sabemos que J ya viene dado por el sistema minimal de // generadores, aunque aqui no sea necesario. J = isMon[2]; } } else { // Los generadores son monomiales,hallamos la base minimal J = minbase(J); } // Hemos asegurado que los ideales sean monomiales. // Quitamos ceros de la base para no alargar calculos. int n = ncols(I); int m = ncols(J); // Hallamos el m.c.m.de cada par de generadores de uno y otro ideal // y los a?adimos al ideal interseccion. for (i=1 ; i<=n ; i++) { for (j=1 ; j<=m ; j++) { K = K , lcmMon (I[i],J[j]); } } // Devolvemos el ideal ya dado por la base minimal porque sabemos // que este procedimiento genera muchos generadores redundantes. return(minbase(K)); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^3*x*y,w*x*y*z*t,x^2*y^2*z^2,x^2*z^4*t^3,y^3*z; ideal J = w*x, x^2, y*z*t, y^5*t; intersectMon (I,J); } ////////////////////////////////////////////////////////////////////// // proc quotientMon (ideal I,ideal J) "USAGE: quotientMon (I,J); I,J ideals. RETURN: an ideal, the quotient I:J. (returns -1 if I or J is not monomial) ASSUME: I,J are monomial ideals of the basering. NOTE: the minimal monomial generating set is returned. EXAMPLE: example quotientMon; shows an example. " { // Variables int i,control,n; poly f; list isMon; //COMPROBACIONES if (size(I) == 0 || size(J) == 0) { ERROR("one of the ideals is zero, hence not monomial."); } control = checkIdeal(I); if (control == 0) { isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the first ideal is not monomial."); } else { // Sabemos que I ya viene dado por el sistema minimal de // generadores, aunque aqui no sea necesario. I = isMon[2]; } } else { // Los generadores son monomiales,hallamos sistema minimal I = minbase(I); } control = checkIdeal(J); if (control == 0) { isMon = isMonomialGB (J); if (isMon[1] == 0) { ERROR ("the second ideal is not monomial."); return (-1); } else { // Sabemos que J ya viene dado por el sistema minimal de // generadores, aunque aqui no sea necesario. J = isMon[2]; } } else { // Los generadores son monomiales, hallamos el sistema minimal J = minbase(J); } // Tenemos los ideales dados por su sistema minimal (aunque no es necesario, ahorra // calculos. En K vamos a tener la interseccion de los ideales. ideal K = 1; // ------ Empezamos a hacer el cociente. // Los ideales estan dados por su sistema minimal, con lo que no aparecen ceros. // Luego podemos usar size(J). n = ncols(J); for (i = 1 ; i <= n ; i++) { K = intersect (K ,quotientIdealMon(I,J[i])); } // Aqui tambien surgen muchos generadores que no forman parte de la // base minimal del ideal obtenido. return(minbase(K)); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^3*x*y,w*x*y*z*t,x^2*y^2*z^2,x^2*z^4*t^3,y^3*z; ideal J = w*x, x^2, y*z*t, y^5*t; quotientMon (I,J); } ////////////////////////////////////////////////////////////////////// // proc radicalMon(ideal I) "USAGE: radicalMon(I); I ideal RETURN: an ideal, the radical ideal of the ideal I. (returns -1 if I is not a monomial ideal) ASSUME: I is a monomial ideal of the basering. NOTE: the minimal monomial generating set is returned. EXAMPLE: example radicalMon; shows an example. " { // Cambiamos de anillo int nvar = nvars(basering); // Variables int i,m,j,control; poly f; intvec v; ideal rad_I; // COMPROBACIONES control = checkIdeal(I); // Si el sistema de generadores no esta formado por monomios, hay // que comprobar si el ideal es monomial. if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { I = isMon[2]; // Ya lo tenemos con los generadores monomiales minimales } } else { // Generadores monomiales, hallamos sistema minimal I = minbase(I); } // Ya tenemos el ideal generado por la BASE MINIMAL MONOMIAL m = ncols(I); // Solo hay que poner exponente 1 a todas las variables que tengan // exponente >1. for (i = 1 ; i <= m ; i++) { v = leadexp(I[i]); f = 1; for (j = 1 ; j <= nvar ; j++) { if (v[j] <> 0) { f = f*var(j); } } rad_I = rad_I,f; } // Hay que devolver el ideal dado por la base minimal, pues se // producen muchos generadores redundantes. return( minbase (rad_I)); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^3*x*y,w*x*y*z*t,x^2*y^2*z^2,x^2*z^4*t^3,y^3*z; radicalMon(I); } ////////////////////////////////////////////////////////////////////// // proc isprimeMon (ideal I) "USAGE: isprimeMon (I); I ideal RETURN: 1, if I is prime; 0, otherwise. (returns -1 if I is not a monomial ideal) ASSUME: I is a monomial ideal of the basering. EXAMPLE: example isprimeMon; shows some example. " { // Variables int control,i,j,suma; intvec expin; // COMPROBACIONES control = checkIdeal(I); // Si el sistema de generadores no esta formado por monomios, hay // que comprobar si el ideal es monomial. if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { I = isMon[2]; // Ya lo tenemos con los generadores minimales } } else { // Generadores monomiales, hallamos el sistema minimal I = minbase(I); } // Ya tenemos el ideal generado por la BASE MINIMAL if (maxdeg1(I) == 1) { return (1); } return (0); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w,y,t; isprimeMon (I); ideal J = w,y,t,x*z; isprimeMon (J); } ////////////////////////////////////////////////////////////////////// // proc isprimaryMon (ideal I) "USAGE: isprimaryMon (I); I ideal RETURN: 1, if I is primary; 0, otherwise. (returns -1 if I is not a monomial ideal) ASSUME: I is a monomial ideal of the basering. EXAMPLE: example isprimaryMon; shows some examples " { // Variables int nvar,control,m,l,sub_in,i,j,k; intvec v,w,exp_gen; // COMPROBACIONES control = checkIdeal(I); // Si el sistema de generadores no esta formado por monomios, hay // que comprobar si el ideal es monomial. if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { I = isMon[2]; // Ya lo tenemos con los generadores minimales } } else { // Generadores monomiales, hallamos el sistema minimal I = minbase(I); } // Ya tenemos el ideal generado por la BASE MINIMAL // Usamos la funcion "soporte" que hemos creado, para saber que // variables aparecen en la base de generadores como producto de si // mismas y tambien cuales son los generadores del ideal donde // tenemos que comprobar si aparecen tales variables. nvar = nvars(basering); m = ncols(I); // Inicializo la ultima componente del vector para que contenga a // todas las variables (el subindice de la variable es el lugar // que ocupa como componente de v). v[nvar] = 0; k = 1; // v = 1 en variables solas y 0 en el resto. // w = lugar de los generadores de I que son producto de mas de una variable. for (i = 1 ; i <= m ; i++) { sub_in = soporte(I[i]); // Si soporte <> 0 la variable aparece sola, en caso contrario // el generador es producto de mas de una variable if (sub_in <> 0) { v[sub_in] = 1; } else { w[k] = i; k++; } } // Ahora solo hay que ver que no aparecen variables distintas de // las que tenemos marcadas con 1 en v. l = size(w); // Si w es cero, quiere decir que todos los generadores del ideal // son producto de una sola variable, luego es primario. if (l == 1 && w[1] == 0) { return(1); } // Estudiamos el exponente de los generadores de I oportunos (los // que nos indica w). for (i = 1 ; i <= l ; i++) { exp_gen = leadexp(I[w[i]]); for (j = 1 ; j <= nvar ; j++) { if (v[j] == 0) { if (exp_gen[j] <> 0) { return (0); } } } } // Si hemos recorrido todo el ideal sin que salte el "for" // quiere decir que no se ha contradicho la caracterizacion, // luego el ideal es primario. return(1); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^4,x^3,z^2,t^5,x*t,w*x^2*z; isprimaryMon (I); ideal J = w^4,x^3,z^2,t^5,x*t,w*x^2*z,y^3*t^3; isprimaryMon (J); } ////////////////////////////////////////////////////////////////////// // proc isirreducibleMon (ideal I) "USAGE: isirreducibleMon(I); I ideal RETURN: 1, if I is irreducible; 0, otherwise. (return -1 if I is not a monomial ideal) ASSUME: I is a monomial ideal of the basering. EXAMPLE: example isirreducibleMon; shows some examples " { // Variables intvec v; int n,i,j,sum,control; control = checkIdeal(I); // Si el sistema de generadores no esta formado por monomios, hay // que comprobar si el ideal es monomial. if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { I = isMon[2]; // Ya lo tenemos con los generadores minimales } } else { // Generadores monomiales, hallamos sistema minimal I = minbase(I); } // Ya tenemos el ideal generado por la BASE MINIMAL n = ncols(I); // La funcion soporte devuelve 0 si el monomio es producto de mas // de una variable. Chequeamos generador a generador si el ideal // esta generado por potencias de variables. for (i = 1 ; i <= n ; i ++) { if (soporte(I[i]) == 0) { return(0); } } return (1); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^4,x^3,z^2,t^5; isirreducibleMon (I); ideal J = w^4*x,x^3,z^2,t^5; isirreducibleMon (J); } ////////////////////////////////////////////////////////////////////// // proc isartinianMon (ideal I) "USAGE: isartinianMon(I); I ideal. RETURN: 1, if ideal is artinian; 0, otherwise. (return -1 if ideal I is not a monmomial ideal). ASSUME: I is a monomial ideal of the basering. EXAMPLE: example isartinianMon; shows some examples " { int nvar = nvars(basering); // Declaracion de variables int i,j,k,cont,sizI; intvec v; // COMPROBACIONES int control = checkIdeal(I); // Si el sistema de generadores no esta formado por monomios, hay // que comprobar si el ideal es monomial. if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { I = isMon[2]; // Ya lo tenemos con los generadores minimales } } else { // Generadores monomiales, hallamos sistema minimal I = minbase(I); } // Ya tenemos el ideal generado por la BASE MINIMAL sizI = ncols(I); // Comprobamos que entre los generadores minimales aparece una // potencia de cada. Cuando encontramos un generador que es potencia // de una sola variable aumento contador cont = 0; for (i = 1 ; i <= sizI ; i++) { if (soporte(I[i]) <> 0) { cont ++; // Solo volvemos a evaluar en caso de que hayamos aumentado if (cont == nvar) { // Ya hemos encontrado que todas las variables aparrecen en // el sistema minimal como potencia pura. No queremos seguir // buscando return (1); } } } // Si ha salido, es que faltan variables return(0); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^4,x^3,y^4,z^2,t^6,w^2*x^2*y,w*z*t^4,x^2*y^3,z^2*t^5; isartinianMon (I); ideal J = w^4,x^3,y^4,z^2,w^2*x^2*y,w*z*t^4,x^2*y^3,z^2*t^5; isartinianMon (J); } ////////////////////////////////////////////////////////////////////// // proc isgenericMon (ideal I) "USAGE: isgenericMon(I); I ideal. RETURN: 1, if ideal is generic; 0, otherwise. (return -1 if ideal I is not a monomial ideal) ASSUME: I is a monomial ideal of the basering. EXAMPLE: example isgenericMon; shows some examples. " { int nvar = nvars(basering); // Declaracion de variables int sizI,i,j,k; list exp; // COMPROBACIONES int control = checkIdeal(I); // Si el sistema de generadores no esta formado por monomios, hay // que comprobar si el ideal es monomial. if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { I = isMon[2]; // Ya lo tenemos con los generadores minimales } } else { // Generadores monomiales, hallamos sistema minimal I = minbase(I); } // Ya tenemos el ideal generado por la BASE MINIMAL sizI = ncols(I); // Creamos una lista que tenga los exponentes de todos los // generadores. for (i = 1 ; i <= sizI ; i++) { exp[i] = leadexp(I[i]); } // Ahora hay que ver si alguno se repite, y si uno de ellos // lo hace, ya no es gen?rico. for (i = 1 ; i <= nvar ; i++) { for (j = 1 ; j <= sizI-1 ; j++) { for (k = j+1 ; k <= sizI ; k++) { // Notar que no se pueden repetir si la variable realmente // aparece en el generador, es decir, exponente >1. if (exp[j][i] == exp[k][i] & exp[j][i] <> 0) { return (0); } } } } return (1); } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^4,x^3,y^4,z^2,w^2*x^2*y,w*z*t^4,x*y^3,z*t^5; isgenericMon (I); ideal J = w^4,x^3,y^4,z^3,w^2*x^2*y,w*z*t^4,x*y^3,z^2*t^5; isgenericMon (J); } ////////////////////////////////////////////////////////////////////// // proc dimMon (ideal I) "USAGE: dimMon (I); I ideal RETURN: an integer, the dimension of the affine variety defined by the ideal I. (returns -1 if I is not a monomial ideal) ASSUME: I is a monomial ideal of the basering. EXAMPLE: example dimMon; shows some examples. " { // El ideal trivial no es monomial. if ( size(I) == 0 ) { ERROR("the ideal is zero, hence not monomial."); } // VARIABLES int control,sizSum,sumandos,i,j,k,cont; // COMPROBACIONES control = checkIdeal(I); if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { // Sabemos que I ya viene dado por el sistema minimal de // generadores, aunque aqui no sea necesario. I = isMon[2]; } } attrib(I,"isSB",1); return (dim(I)); // int nvar = nvars(basering); // intvec index,indexAux,vaux,w; // list sum, sumAux; // // La base del ideal tiene que ser la monomial // // Si el ideal es artiniano, es 0-dimensional // if (isartinianMon(I) == 1) // { // return (0); // } // int sizI = ncols(I); // // v(i) = vector con sizI entradas y donde cada entrada "j" se corresponde // // con el exponente del generador "i" en la variable "j" // for (i = 1 ; i <= nvar ; i++) // { // intvec v(i); // for (j = 1 ; j <= sizI ;j++ ) // { // v(i)[j] = leadexp(I[j])[i]; // } // } // // Vamos a guardar en el vector "index" la ultima variable que se ha // // sumado y en cada "sum(i)" el vector suma que se corresponde con la // // entrada "i" del vector index. // // Inicializo los valores de index y de cada sum // w[sizI] = 0; // sum[1] = w; // index[1] = 0; // sizSum = 1; // while ( 1 ) // { // cont = 1; // sumandos ++; // for (i = 1 ; i <= sizSum ; i ++) // { // for (j = index[i] + 1 ; j <= nvar ; j ++) // { // w = sum[i]; // vaux = w + v(j); // // Comprobamos // for (k = 1 ; k <= sizI ; k ++) // { // if (vaux[k] == 0) // { // break; // } // } // if (k == sizI +1) // { // return (nvar - sumandos); // } // if (j <> nvar) // { // sumAux[cont] = vaux; // indexAux[cont] = j; // cont ++; // } // } // } // index = indexAux; // sum = sumAux; // sizSum = size(sumAux); // } } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z,t),lp; ideal I = w^3*x*y,w*x*y*z*t,x^2*y^2*z^2,x^2*z^4*t^3,y^3*z; dimMon (I); ideal J = w^4,x^3,y^4,z^2,t^6,w^2*x^2*y,w*z*t^4,x^2*y^3,z*t^5; dimMon (J); } ///////////////////////////////////////////////////////////////////////////// //-------------------------------------------------------------------------// //----------------------- DESCOMPOSICIONES -----------------------------_// //-------------------------------------------------------------------------// ///////////////////////////////////////////////////////////////////////////// // // METODO 1: Metodo directo para descomp. irreducible (ver Vasconcelos) // ////////////////////////////////////////////////////////////////////// // Este procedimiento calcula la descomposicion en irreducibles de // // un ideal monomial dado por su base minimal de generadores // // haciendo uso de la caracterizacion de ideal monomial irreducible // // (Vasconcelos) // ////////////////////////////////////////////////////////////////////// // static proc irredDec1 (ideal I) { // Variables int i,j,n,resp; list l1,l2; intvec exp,v; ideal J,K; // ----- DESCOMPOSICION IRREDUCIBLE // Inicializamos la lista que va a estar formada por los ideales // que tenemos que comprobar son irreducibles. I = simplify(I,1); l1 = I; while (size(l1) > 0) { for (i = 1 ; i <= size(l1) ; i++) { J = l1[i]; n = ncols(J); l1 = delete(l1,i); // Llamamos a la funcion que va a detectar si el ideal es o // no irreducible, y en caso de no serlo sabemos sobre que // generador y con que variables hay que aplicar el // el resultado teorico. v = irredAux (J); // No irreducible if (size(v) > 1) { // En este caso, v[1] nos indica el generador del ideal // que debemos eliminar. exp = leadexp(J[v[1]]); if (v[1] == 1) { J = J[2..n]; } if (v[1] > 1 && v[1] < n) { J = J[1..v[1]-1],J[v[1]+1..n]; } if (v[1] == n) { J = J[1..n-1]; } // Ahora vamos a introducir los nuevos generadores en // cada uno de los nuevos ideales que generamos. Los // ponemos en la lista en la que comprobamos. for (j = 1 ; j <= size(v)-1 ; j++) { K = J,var(v[j+1])^exp[v[j+1]]; l1 = insert(l1,minbase(K)); } } // Si v[1]=0, el ideal es irreducible y lo introducimos en // la lista l2, que es la que finalmente devolvera las // componentes de la descomposicion. else { l2 = insert(l2,J); } } } // ---- IRREDUNDANTE l2 = irredundant (l2); // La salida es la lista de los ideales irreducibles. return (l2); } ////////////////////////////////////////////////////////////////////// // La siguiente funcion va a obtener una descomposicion primaria // // minimal a partir de la irreducible anterior. // ////////////////////////////////////////////////////////////////////// // static proc primDec1 (ideal I) { // Variables list l1,l2; // ----- DESCOMPOSICION IRREDUCIBLE l1 = irredDec1 (I); // ----- DESCOMPOSICION PRIMARIA l2 = irredPrimary (l1); return (l2); } // // METODO 2: Metodo directo para descomp. primaria (ver Vasconcelos) // ////////////////////////////////////////////////////////////////////// // La siguiente funcion va a calcular una descomposicion primaria // // minimal de un ideal monomial, pero esta vez usando la // // caracterizacion de ideal monomial primario y un resultado que // // hace uso de esta (Vasconcelos). // ////////////////////////////////////////////////////////////////////// // static proc primDec2 (ideal I) { // Variables en el nuevo anillo int i,n,max; list l1,l2; intvec v; ideal J,K; // Vamos a tener dos listas: l1 que va a guardar todos los ideales // que vayamos generando con el resultado citado antes, que seran // los que vamos a comprobar si son primarios; y l2, donde guardamos // aquellos de l1 que verifiquemos son primarios. I = simplify(I,1); l1 = I; while (size(l1) > 0) { for (i = 1 ; i <= size(l1) ; i++) { J = l1[i]; n = ncols(J); l1 = delete (l1,i); // Usamos la funcion que hemos creado para saber si el ideal // es primario. Si no lo es devuelve la variable que crea // conflicto y los generadores del ideal que luego hay que // usar (los que tienen productos de mas de una vble). // Se le llama con el sistema minimal de generadores v = primAux (J); // En caso de no ser primario, hay que buscar el maximo // exponente de la variable que aparece en los generadores // del ideal multiplicada siempre por otras variables, // nunca por si misma. if (v[1] == 0) { max = maxExp(J,v); K = J,var(v[2])^max; l1 = insert (l1,minbase(K)); K = quotientIdealMon(J,var(v[2])^max); // quotientidealMon devuelve sistema minimal de generadores l1 = insert (l1,minbase(K)); } // En caso de ser primario, lo introducimos en la lista // conveniente. else { l2 = insert (l2,J); } } } // ------ IRREDUNDANTE l2 = irredundant (l2); return (l2); } // // METODO 3: via dual de Alexander y doble dual (Miller) // ////////////////////////////////////////////////////////////////////// // Esta funcion calcula la descomposicion irreducible usando el // // dual de Alexander teniendo en cuenta que el dual del dual es el // // ideal de partida (Miller) // ////////////////////////////////////////////////////////////////////// // static proc irredDec3 (ideal I) { int i,n,j; poly lcm; intvec v,exp_I,exp; ideal J; list l; // Hallamos el m.c.m. de los generadores minimales del ideal. n = ncols (I); lcm = I[1]; for ( i = 2 ; i <= n ; i++ ) { lcm = lcmMon (lcm,I[i]); } v = leadexp (lcm); // Calculamos el dual de Alexander. // Hacemos una funcion para este paso porque luego lo volveremos a // utilizar. l = alexDif (v,I); // Tenemos los ideales irreducibles cuya interseccion nos da el dual // de Alexander. Notar que tenemos tantos ideales como generadores // minimales tiene I. // Hallamos la base minimal. J = minbase(intersect(l[1..size(l)])); // Ya solo queda el ultimo paso: hallar de nuevo el dual de // Alexander. Sabemos que este proceso ya devuelve la descomposicion // irreducible irredundante. l = alexDif (v,J); return (l); } ////////////////////////////////////////////////////////////////////// // En este caso hallamos una descomposicion primaria minimal usando // // la irreducible irredundante del procedimiento anterior. // ////////////////////////////////////////////////////////////////////// // static proc primDec3 (ideal I) { // Variables list l1,l2; // ----- DESCOMPOSICION IREDUCIBLE l1 = irredDec3 (I); // ----- DESCOMPOSICION PRIMARIA l2 = irredPrimary (l1); return (l2); } // // METODO 4: via dual de Alexander y cociente (Miller) // ////////////////////////////////////////////////////////////////////// // Vamos a hallar las componentes irreducibles de un ideal monomial // // dado por sus generadores minimales haciendo uso del dual de // // Alexander (con el cociente) (Miller) // ////////////////////////////////////////////////////////////////////// // static proc irredDec4 (ideal I) { // Cambiamos de anillo. int nvar = nvars(basering); // Variables int n,i,j,m,resp; poly lcm; intvec v; ideal J,K; list L; // Calculamos el l.c.m. de los generadores minimales del ideal. n = ncols (I); lcm = I[1]; for ( i = 2 ; i <= n ; i++ ) { lcm = lcmMon (lcm,I[i]); } v = leadexp (lcm); // Hallamos el ideal J = (x(1)^(l(1)+1),...,x(n)^(l(n)+1)). Como // luego, en el procedimiento quotientMon, vamos a hallar la base // minimal de cada ideal, no nos preocupa que tengamos un cero en // el ideal J. for ( i = 1 ; i <= nvar ; i++ ) { J[i] = (var(i))^(v[i]+1); } // Ahora hacemos el cociente oportuno. K = minbase(quotient (J,I)); // Buscamos aquellos generadores de K que no son divisibles por los // generadores de J. Los generadores que son divisibles los hacemos // cero y luego los eliminamos. m = ncols (K); for ( i = 1 ; i <= m ; i++ ) { resp = membershipMon(K[i],J); if ( resp == 1) { K[i] = 0; } } K = simplify (K,2); // Ahora obtenemos las componentes de la descomposicion irreducible, // que estan en correspondencia con los generadores minimales de K. L = alexDif (v,K); // Volvemos al anillo de partida y devolvemos la lista de las // componentes irreducibles irredundantes. return (L); } ////////////////////////////////////////////////////////////////////// // Ahora hallamos una descomposicion primaria irredundante usando // // la ultima funcion para hallar las componentes irreducibles de un // // ideal monomial dado por sus generadores minimales. // ////////////////////////////////////////////////////////////////////// // static proc primDec4 (ideal I) { // Variables list l1,l2; // ----- DESCOMPOSICION IREDUCIBLE l1 = irredDec4 (I); // ----- DESCOMPOSICION PRIMARIA l2 = irredPrimary (l1); return (l2); } // // METODO 5: un misterio!! // ////////////////////////////////////////////////////////////////////// // Este procedimiento halla los elementos maximales de la base // // estandar del ideal, que se correspoenden con las componentes // // irreducibles del ideal 1-1. // ////////////////////////////////////////////////////////////////////// // static proc irredDec5 (ideal I) { int nvar = nvars(basering); //Variables int i,j; ideal K; // Artinianization list artiniano = artinian (I); if (artiniano[1] == 0) { I = artiniano[2]; intvec elimina = artiniano[3]; } // Quotient ideal M = maxideal(1); ideal J = quotient (I,M); // Deleting generators lying in I for (i = 1 ; i <= ncols(J) ; i ++) { if (membershipMon(J[i],I) == 1) { if (i == 1) { J = J[2..ncols(J)]; i --; } else { if (i == ncols(J)) { J = J[1..i-1]; i --; } else { J = J[1..i-1],J[i+1..ncols(J)]; i --; } } } } // Exponents of the ideals are going to form the decomposition int sizJ = ncols(J); for (i = 1 ; i <= sizJ ; i ++ ) { intvec exp(i) = leadexp(J[i]) + 1; } // Deleting artinianization process if (artiniano[1] == 0) { // En elimina estan guardadas las variables que hay que eliminar for (i = 1 ; i <= nvar ; i ++) { if (elimina[i] <> 0) { for (j = 1 ; j <= sizJ ; j ++) { if (exp(j)[i] == elimina[i]) { exp(j)[i] = 0; } } } } } // En exp(i) tengo los exponentes de cada variable de las que aparecen // en cada ideal. list facets; for (i = 1 ; i <= sizJ ; i ++) { J = 0; for (j = 1 ; j <= nvar ; j ++) { if (exp(i)[j] <> 0) { J = J,var(j)^exp(i)[j]; } } J = simplify(J,2); facets[i] = J; } return (facets); } ////////////////////////////////////////////////////////////////////// // Ahora hallamos una descomposicion primaria irredundante usando // // la ultima funcion para hallar las componentes irreducibles de un // // ideal monomial dado por sus generadores minimales. // ////////////////////////////////////////////////////////////////////// // static proc primDec5 (ideal I) { // Variables list l1,l2; // ----- IRREDUCIBLE DECOMPOSITION l1 = irredDec5 (I); // ----- PRIMARY DECOMPOSITION l2 = irredPrimary (l1); return (l2); } // // METODO 6: via complejo de Scarf (Milovsky) // ////////////////////////////////////////////////////////////////////// // Metodo que usa el complejo de Scarf asociado a un ideal monomial // // de k[x(1)..x(n)] (Milowski) // ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // Calcula el maximo exponente de la variable x(i) entre los // // generadores del ideal. // ////////////////////////////////////////////////////////////////////// // static proc maximoExp(ideal I,int i) { // VARIABLES int max,j,k,sizI; intvec exp; sizI = ncols(I); max = 0; for (j = 1 ; j <= sizI ; j ++) { exp = leadexp(I[j]); if ( exp[i] > max) { max = exp[i]; } } return(max); } ////////////////////////////////////////////////////////////////////// // Esta funcion estudia si un ideal monomial dado por su sistema // // minimal de generadores es o no artiniano. En caso de no serlo, // // halla el artiniano mas proximo y ademas devuelve los generadores // // que han sido introducidos. // ////////////////////////////////////////////////////////////////////// // static proc artinian (ideal I) { // Cambiamos de anillo int nvar = nvars(basering); // Declaracion de variables int i,j,k,cont1,cont2,sizI,marcavar,max; intvec v,variablesin,cambio; list nuevo; ideal J; sizI = ncols(I); // Comprobamos que entre los generadores minimales aparece una // potencia de cada cont2 = 0; for (i = 1 ; i <= sizI ; i++) { v = leadexp(I[i]); marcavar = 0; cont1 = 0; for (j = 1 ; j <= nvar ; j++) { if (v[j] <> 0) { cont1 ++; marcavar = j; } } // Si cont1=1 hemos encontrado un generador de los que nos // interesa."variablesin" guarda el indice de las que estan. if (cont1 == 1) { cont2 ++; variablesin[cont2] = marcavar; } } // Notar que como el sistema de generadores es minimal no se // va a repetir la potencia de la misma variable. Por tanto basta // comprobar si cont2 es o no nvar. if (cont2 == nvar) { list output; output[1] = 1; return(output); } else { J = I; // Buscamos las que no estan if (cont2 == 0) { for (i = 1 ; i <= nvar ; i ++) { max = maximoExp(I,i); cambio[i] = max + 1; J = J,var(i)^(max + 1); } } else { for (i = 1 ; i <= nvar ; i++) { for (j = 1 ; j <= cont2 ; j ++) { if (i == variablesin[j]) { cambio[i] = 0; break; } } if (j == cont2 + 1) { max = maximoExp(I,i); cambio[i] = max + 1; J = J,var(i)^(max + 1); } } } list output; output[1] = 0; output[2] = J; output[3] = cambio; return(output); } } ////////////////////////////////////////////////////////////////////// // En este caso vamos primero a chequear si el ideal es o no // // generico y en caso de no serlo vamos a devolver los cambios, // // pues estos son una aplicacion biyectiva. // ////////////////////////////////////////////////////////////////////// // static proc generic (ideal I) { // New ring int nvar = nvars(basering); // VARIABLES int i,j,k; // Cargamos la matriz con los exponentes int sizI = ncols(I); intmat EXP[sizI][nvar]; for (i = 1 ; i <= sizI ; i ++) { // Ordenamos el vector de exponentes oportuno EXP[i,1..nvar] = leadexp(I[i]); } // Ahora tenemos que ordenarla segun la variable que este en conficto. intvec vari,change; intmat NEWEXP = EXP; list aux; int count = 0; for (i = 1 ; i <= nvar ; i ++) { // Buscamos conflicto en la variable x(i), para ello tengo que ordenar // la columna i de EXP vari = EXP[1..sizI,i]; aux = sort(vari); vari = aux[1]; change = aux[2]; for (j = 1 ; j <= sizI - 1 ; j ++) { if (vari[j] > 0) { while (NEWEXP[change[j + count] , i] >= vari[j + 1 + count]) { NEWEXP[change[j + 1 + count] , i] = NEWEXP[change[j + count] , i] + 1; count ++; if (j + 1 + count > sizI) { break; } } } j = j + count; count = 0; } } // Devolvemos tambien la matriz, pues aqui tengo la biyeccion entre los exponentes if (EXP == NEWEXP) { return (1,I); } else { // Hallamos el ideal con los nuevos exponentes intvec expI; for (i = 1 ; i <= sizI ; i ++) { expI = NEWEXP[i,1..nvar]; I[i] = monomial(expI); } return(0,I,EXP,NEWEXP); } } ////////////////////////////////////////////////////////////////////// // Esta funci?n obtiene una descomposicion irreducible del ideal // // monomial a partir de la descomposicion irreducible del idal // // generico que le asociamos. // ////////////////////////////////////////////////////////////////////// // static proc nonGeneric (def EXP,def NEWEXP,def Faces,def sizI) { int nvar = nvars(basering); int sizFaces = size(Faces); // Variables int i,j,k; // Vamos variable a variable intvec exp, newexp; list newFaces; newFaces = Faces; for (i = 1 ; i <= nvar ; i ++) { // comparamos las matrices de exponentes por columnas exp = EXP[1..sizI,i]; newexp = NEWEXP[1..sizI,i]; if (exp <> newexp) { for (j = 1 ; j <= sizI ; j ++) { if (exp[j] <> newexp[j]) { for (k = 1 ; k <= sizFaces ; k ++) { if (Faces[k][i] == newexp[j]) { newFaces[k][i] = exp[j]; } } } } } } return (newFaces); } ////////////////////////////////////////////////////////////////////// // Este procedimiento va a dar una faceta inicial para el complejo // // de Scarf asociado a I, donde I es un ideal monomial artiniano // // y generico (evidentemente I dado por la bse minimal) // ////////////////////////////////////////////////////////////////////// // static proc initialFacet (ideal I) { // Cambiamos de anillo // Queremos usar x(1)..x(n) como variables. int nvar = nvars(basering); // Declaracion de variables. int i,sizJ,j,max,aux,sizK,l, elim; intvec v; list face; // Hacemos una copia de I pues ahora modificaremos el sistema // de generadores. ideal J = I; sizJ = ncols(J); // Para cada variable buscamos el maximo exponente, teniendo en // cuenta que un mismo generador no puede dar dos exponentes. // Vamos a guardar los exponentes en "expIni" intvec expIni; for (i = 1 ; i <= nvar ; i++) { max = 0; for (j = 1 ; j <= sizJ ; j++) { aux = leadexp(J[j])[i]; if (aux > max) { max = aux; elim = j; } } // Guardamos el exponente expIni[i] = max; // Ahora tenemos el maximo de la variable x(i), por lo que // eliminamos el generador en el que la encontramos. // Si queda un generador no hay nada que hacer if (sizJ <> 1) { if (elim <> 1 & elim <> sizJ) { J = J[1..elim-1],J[elim+1..sizJ]; } else { if (elim == 1) { J = J[2..sizJ]; } else { J = J[1..sizJ-1]; } } sizJ = ncols(J); // Eliminamos la variable x(i) en todos los generadores. for (j = 1 ; j <= sizJ ; j++) { v = leadexp(J[j]); if (v [i] <> 0) { v[i] = 0; J[j] = monomial(v); } } // Hallamos el sistema minimal de generadores que // corresponde al ideal que nos ha quedado. J = minbase(J); sizJ = ncols(J); } } // En expIni tenemos los exponentes de los monomios que dan la cara // inicial, ahora hay que buscar en el ideal original a que // generador se corresponde (el ideal es generico) int sizI = ncols(I); for (i = 1 ; i <= nvar ; i ++) { for (j = 1 ; j <= sizI ; j ++) { if (expIni[i] == leadexp(I[j])[i]) { face = insert(face, I[j]); // Si lo encontramos buscamos el siguiente break; } } } return (face); } ////////////////////////////////////////////////////////////////////// // La funcion que sigue devuelve las facetas adyacentes a una dada // // en el complejo de Scarf asociado a I. // ////////////////////////////////////////////////////////////////////// // static proc adyacency (list l1, ideal I) { // Cambiamos de anillo // Queremos usar x(1)..x(n) como variables. int nvar = nvars(basering); // Declaracion de variables. int i,j,cambio,sizI,k,min,m,generador,max; list l2,newl1,w,expI; poly LCM,newLCM; intvec v,newv,expgen; sizI = ncols(I); // Hallamos el lcm de los elementos, e. d., la faceta del // complejo para luego comparar con los nuevos LCM = 1; for (i = 1 ; i <= nvar ; i++) { LCM = lcmMon(LCM,l1[i]); } v = leadexp(LCM); // Calculo los exponentes de los monomios de I for (i = 1 ; i <= sizI ; i++) { expI[i] = leadexp(I[i]); } // Hay que quitar cada elemento de la lista y comprobar si hay o no // cara adyacente al simplice que queda, y en caso de haberla, la // calculamos. for (i = 1 ; i <= nvar ; i++) { newl1 = delete(l1,i); // Hallamos el lcm de los elementos que hay en la nueva lista. newLCM = 1; for (j = 1 ; j <= nvar - 1 ; j++) { newLCM = lcmMon(newLCM,newl1[j]); } // Ahora hay que detectar si alguna variable ha desaparecido // en este LCM. newv = leadexp(newLCM); for (j = 1 ; j <= nvar ; j++) { if (newv[j] == 0) { l2[i] = 0; break; } } if (j == nvar+1) { // Si no ha habido ceros, queremos hallar la cara adyacente, // es decir, buscar un generador que introducido en l1 de una // faceta del complejo. // Comparamos los lcm entre s?, para comprobar en que variable // contribu?a el monomio que hemos eliminado. for (j = 1 ; j <= nvar ; j++) { if (v[j] <> newv[j]) { cambio = j; // Una vez encontrado no hay mas break; } } // Hallamos los exponentes de los monomios que quedan // para ver cual da el exponente en "newv" for (j = 1 ; j <= nvar - 1 ; j++) { w[j] = leadexp(newl1[j]); } for (j = 1 ; j <= nvar ; j++) { for (k = 1 ; k <= nvar - 1 ; k++) { if (newv[cambio] == w[k][cambio]) { cambio = k; break; } } // Si no termino el for con k es que hemos encontrado ya // los que son iguales. if (k <> nvar) { break; } } // Donde contribuye antes, e.d., en "v" for (j = 1 ; j <= nvar ; j++) { if (w[cambio][j] == v[j]) { cambio = j; break; } } // Ahora ya buscamos entre los generadores el nuevo monomio. // Ponemos de tope para encontrar el minimo el maximo de // las variables en el ideal max = 0; for (m = 1 ; m <= sizI ; m ++) { if (expI[m][cambio] > max) { max = expI[m][cambio]; } } min = max; for (j = 1 ; j <= sizI ; j++) { for (k = 1 ; k <= nvar ; k ++) { if (I[j] == l1[k]) { break; } } // El generador no esta en la lista, es de los que hay que // comprobar if (k == nvar +1) { for (m = 1 ; m <= nvar ; m++) { if (m <> cambio) { if (expI[j][m] > newv[m]) { break; } } else { if (expI[j][m] <= newv[m]) { break; } } } // Si termina el bucle cumple las condiciones // oportunas, solo hay que comparar con el // otro que tengamos. if (m == nvar + 1) { if (expI[j][cambio] <= min) { min = expI[j][cambio]; generador = j; } } } } // En la lista ponemos en el lugar "i" el generador que // hay que introducir cuando eliminamos el generador // "i" de la lista de entrada. l2[i] = I[generador]; } } return(l2); } ////////////////////////////////////////////////////////////////////// // Metodo que calcula la descomposicion irreducible de un ideal // // monomial usando el complejo de Scarf (Milowski) // ////////////////////////////////////////////////////////////////////// // static proc ScarfMethod (ideal I) { // Cambiamos de anillo // Queremos usar x(1)..x(n) como variables. int nvar = nvars(basering); // Sabemos que dp siempre es mejor para trabajar, auqque luego para // comparar I y genI vamos a cambiarlo al lexicografico. // Variables int i,j,k,sizl1,sizl,cont1,cont2; int sizI; list auxl,expl1,l1,l,l2,newLCM,expI,expgenI,Faces; poly LCM,mon; intvec v,w,betas; ideal J,genI,artgenI; // Comprobamos si el ideal es generico y artiniano, y, en caso de // no serlo, obtenemos una modificacion de este ideal que si // verifique estas propiedades list genericlist = generic(I); if (genericlist[1] == 0) { genI = genericlist[2]; } else { genI = I; } list artinianization = artinian (genI); if (artinianization[1] == 0) { artgenI = artinianization[2]; } else { artgenI = genI; } // Una vez tenemos el ideal artiniano y generico, podemos hallar // el complejo de Scarf asociado al ideal modificado // Hay que obtener una cara inicial del ideal. list initial = initialFacet(artgenI); // Ahora de cada cara que tengamos en una lista obtenemos sus // caras adyacentes. Hay que tener en cuenta que si una cara la // obtengo como adyacente de otra, cuando calculemos sus adyacentes // sale la anterior, luego hay que evitar repetir. // Guardamos la primera faceta, su LCM LCM = 1; for (i = 1 ; i <= nvar ; i++) { mon = initial[i]; LCM = lcmMon(LCM,mon); } v = leadexp(LCM); // Guardamos la primera faceta Faces[1] = v; int sizfaces = 1; // Lista de monomios que dan las facetas para hallar sus caras // adyacentes l[1] = initial; sizl = 1; // Ahora hayamos las posibles caras maximales adyacentes while (sizl <> 0) { // Hallamos la lista de monomios que hay que introducir // cuando eliminamos cada monomio. auxl = adyacency(l[1],artgenI); cont1 = 1; cont2 = 0; l1 = 0; for (j = 1 ; j <= nvar ; j++) { if (auxl[j] <> 0) { l2 = delete(l[1],j); l1[cont1] = insert(l2,auxl[j],cont1 + cont2 - 1); cont1 ++; } else { cont2 ++; } } // Hallamos los nuevos LCM sizl1 = size(l1); for (i = 1 ; i <= sizl1 ; i++) { newLCM[i] = 1; for (j = 1 ; j <= nvar ; j++) { newLCM[i] = lcmMon(newLCM[i],l1[i][j]); } expl1[i] = leadexp(newLCM[i]); } // Hallamos los LCM de las nuevas caras y eliminamos las que // ya esten en la lista Faces cont1 = 0; cont2 = 0; for (i = 1 ; i <= sizl1 ; i++) { for (j = 1 ; j <= sizfaces ; j++) { v = expl1[i]; w = Faces[j]; if (v == w) { // Si ya esta el LCM en la lista, no queremos // seguir buscando break; } } // Si no ha salido del bucle en "j" es que este LCM // no esta en la lista de las caras, la introducimos if (j == sizfaces + 1) { Faces = insert(Faces,expl1[i],sizfaces + cont1); l = insert(l,l1[i]); cont1 ++; } } l = delete(l,cont1 + 1); sizl = size(l); sizfaces = size(Faces); } // En "Faces" ya tengo los exponentes que luego seran los exponentes // de los ideales que forman la descomposicion. // Deshacemos la artinianizacion intvec elimin = artinianization[3]; if (artinianization[1] == 0) { // En elimina tenemos las variables que hemos introducido // y cual es la potencia // Solo miro las que tengan cambio for (i = 1 ; i <= nvar ; i ++) { if (elimin[i] <> 0) { for (j = 1 ; j <= sizfaces ; j ++) { if (Faces[j][i] == elimin[i]) { Faces[j][i] = 0; } } } } } // Generico sizI = size(I); if (genericlist[1] == 0) { Faces = nonGeneric(genericlist[3],genericlist[4],Faces,sizI); } // Ya tenemos en Faces los exponentes de las componentes // ahora solo hay que obtener los ideales. for (i = 1 ; i <= sizfaces ; i ++) { J = 0; for (j = 1 ; j <= nvar ; j ++) { if (Faces[i][j] <> 0) { J = J,var(j)^(Faces[i][j]); } } J = simplify(J,2); Faces[i] = J; } // Esta es la parte LENTA computacionalmente si el ideal de partida // no es generico if (genericlist[1] == 0) { Faces = irredundant(Faces); } return(Faces); } ////////////////////////////////////////////////////////////////////// // Devuelve una descomposicion primaria minimal de un ideal // // monomial via el complejo de Scarf. // ////////////////////////////////////////////////////////////////////// // static proc scarfMethodPrim (ideal I) { // VARIABLES list l1,l2; // Hallamos la despomposicion irreducible del ideal dado usando // el complejo de Scarf l1 = ScarfMethod (I); // ----- DESCOMPOSICION PRIMARIA l2 = irredPrimary (l1); return (l2); } // // METODO 7: algoritmo de etiquetas (Roune) // ////////////////////////////////////////////////////////////////////// // Las siguientes funciones calculan la descomposicion en // // irreducibles de un ideal monomial. En este caso utilizamos el // // algoritmo de etiquetas de B. Roune. // ////////////////////////////////////////////////////////////////////// // static proc phi (list F) { // Cambiamos de anillo int nvar = nvars(basering); // Variables int sizF,i,j; poly f; list listphi; intvec exp,newexp; // F es una lista de pares, que indica una x(i) etiqueta de una // cara del ideal. Suponemos que F tiene ordenados sus elementos // segun las x(i) sizF = size(F); for (i = 1 ; i <= sizF ; i ++) { f = F[i]; exp = leadexp(f); for (j = 1 ; j <= nvar ; j ++) { if (j <> i) { exp[j] = exp[j] + 1; } } listphi[i] = monomial(exp); } // Ya tenemos la lista de los monomios a los que // luego haremos el "lcm" return (listphi); } ////////////////////////////////////////////////////////////////////// // static proc pi(poly f) { // Cambiamos de anillo int nvar = nvars(basering); int i,sizI; intvec exp; exp = leadexp(f); for (i = nvar ; i > 0 ; i --) { if (exp[i] <> 0) { exp[i] = exp[i] - 1; } } f = monomial(exp); return (f); } ////////////////////////////////////////////////////////////////////// // static proc conditionComplex (intvec posActual,ideal I,ideal S) { int nvar = nvars(basering); // VARIABLES int i,nuevo; list F; // Vemos cual ha sido la ultima incorporacion al ideal, que es el // ultimo dentro de posActual que es distinto de 0. for (i = 1 ; i <= nvar ; i ++) { if (posActual[i] == 0) { break; } } nuevo = i - 1; // No se pueden repetir generadores, se mira que el ultimo que se ha // ha introducido no sea de los que ya tenemos for (i = 1 ; i <= nuevo - 1 ; i ++) { if (posActual[i] == posActual[nuevo]) { return (0); } } // Vemos si la variable oportuna divide al generador if (leadexp(I[i]) == 0) { return (0); } // Caso de que el LCM sea multiplo de los que ya tenemos poly LCM = 1; for (i = 1 ; i <= nuevo ; i ++) { F = insert (F,I[posActual[i]],size(F)); } list phiF = phi(F); for (i = 1 ; i <= nuevo ; i ++) { LCM = lcmMon(phiF[i],LCM); } // Comprobamos si ya tenemos algun divisor del actual if (membershipMon(LCM,S) == 1) { return (0); } // Ahora vemos si la lista esta en el complejo simplicial if (membershipMon(LCM,I) == 1) { if (membershipMon(pi(LCM),I) == 0) { return (1,LCM); } } return (0); } ////////////////////////////////////////////////////////////////////// // static proc findFaces (ideal I) { int nvar = nvars(basering); // Variables int i; ideal S; list condiciones; // Inicializamos valores list F; intvec posActual; posActual[nvar] = 0; int variable = 1; int sizI = ncols(I); while (1) { while (posActual[variable] == sizI) { posActual[variable] = 0; variable --; if (variable == 0) { break; } } // Comprobamos si hemos recorrido todas las posibilidades. Si // es as?, terminamos el while if (variable == 0) { break; } posActual[variable] = posActual[variable] + 1; // Comprobamos las condiciones para saber si los generadores que // tenemos est?n o no en el complejo. condiciones = conditionComplex (posActual,I,S); if (condiciones[1] == 1 ) { if (posActual[nvar] <> 0) { S = S,condiciones[2]; F = insert (F,condiciones[2]); } if (variable < nvar) { variable ++; } } } return (F); } ////////////////////////////////////////////////////////////////////// // La siguiente funcion calcula la descomposicion en irreducibles de// // un ideal monomial artininano usando el algoritmo de etiquetas del// // metodo de Bjarke Roune. // ////////////////////////////////////////////////////////////////////// // static proc labelAlgorithm(ideal I) { int nvar = nvars(basering); // Variables int i,j,sizComponents; list components; // El ideal tiene que ser artininano, si no lo es hacemos el cambio // oportuno para que lo sea (luego se deshace). ideal artI; list artiniano = artinian (I); if (artiniano[1] == 0) { artI = artiniano[2]; intvec elimina = artiniano[3]; } else { artI = I; } // Llamamos a findFaces para que encuentre las caras maximales del // complejo asociado al ideal components = findFaces(artI); sizComponents = size(components); list expComponents; poly f; for (i = 1 ; i <= sizComponents ; i ++) { f = components[i]; expComponents[i] = leadexp(f); } // Deshacemos la artinianizacion if (artiniano[1] == 0) { // En elimina tenemos las variables que hemos introducido // y cual es la potencia // Solo miro las que tengan cambio for (i = 1 ; i <= nvar ; i ++) { if (elimina[i] <> 0) { for (j = 1 ; j <= sizComponents ; j ++) { if (expComponents[j][i] == elimina[i]) { expComponents[j][i] = 0; } } } } } // En exp(i) tengo los exponentes de cada variable de las que aparecen // en cada ideal. ideal J; list facets; for (i = 1 ; i <= sizComponents ; i ++) { J = 0; for (j = 1 ; j <= nvar ; j ++) { if (expComponents[i][j] <> 0) { J = J,var(j)^expComponents[i][j]; } } J = simplify(J,2); facets[i] = J; } return (facets); } ////////////////////////////////////////////////////////////////////// // Devuelve una descomposicion primaria minimal de un ideal monomial// // dado. // ////////////////////////////////////////////////////////////////////// // static proc labelAlgPrim (ideal I) { // VARIABLES list l1,l2; // Hallamos la despomposicion irreducible del ideal dado usando // el complejo de Scarf l1 = labelAlgorithm (I); // ----- DESCOMPOSICION PRIMARIA l2 = irredPrimary (l1); return (l2); } // // METODO 8: Gao-Zhu // ////////////////////////////////////////////////////////////////////// // static proc divide (intvec v, intvec w, int k) { int nvar = nvars(basering); // Variables int i; for (i = nvar ; i > 0 ; i --) { if (i == k) { if (v[i] <> w[i]) { return (0); } } else { if (v[i] >= w[i]) { return (0); } } } return (1); } ////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////// // static proc incrementalAlg (ideal I) { int nvar = nvars(basering); // COMPROBACIONES // Variables int i,sop,j,k,l,m,cont,cont2; intvec beta,dbeta,betaaux,elimina; // El ideal tiene que ser artininano, si no lo es hacemos el cambio // oportuno para que lo sea (luego se deshace). list artiniano = artinian (I); ideal artI; if (artiniano[1] == 0) { artI = artiniano[2]; elimina = artiniano[3]; } else { artI = I; elimina[nvar] = 0; } // Buscamos la primera componente irreducible o, lo que es lo // mismo, aquellos generadores que son potencia de una variable. // Si el tama?o de elimina es nvar es que hemos a?adido todos los // generadores que son potencia luego estar?n todos al final del // ideal. list MinI,componentes; int sizartI = ncols(artI); int sizelimina = size(elimina); for (i = 1 ; i <= nvar ; i ++) { if (elimina[i] == 0) { // Buscamos en el ideal los generadores que nos interesan for (j = 1 ; j <= sizartI ; j ++) { sop = soporte(artI[j]); if (sop <> 0) { beta[sop] = leadexp(artI[j])[sop]; MinI = insert(MinI,leadexp(artI[j])); if (j <> 1 and j <> sizartI) { artI = artI[1..j - 1],artI[j + 1..sizartI]; } else { if (j == 1) { artI = artI[2..sizartI]; } else { artI = artI[1..sizartI - 1]; } } sizartI = ncols(artI); break; } } } else { // Buscamos la que esta al final sop = soporte(artI[sizartI]); beta[sop] = leadexp(artI[sizartI])[sop]; MinI = insert(MinI,leadexp(artI[sizartI])); if (sizartI <> 1) { artI = artI[1..sizartI - 1]; } else { artI = artI[1]; } sizartI = ncols(artI); } } // En beta tenemos la primera componente componentes = insert(componentes,beta); int sizcomponents = size(componentes); int sizMin = size(MinI); // Es mas facil trabajar con los exponentes para nuestro objetivo // Se elige un nuevo generador, que en nuestro caso es un nuevo // exponente. int min,max; intvec expartI; for(i = 1 ; i <= sizartI ; i ++) { expartI = leadexp(artI[1]); if (size(artI) <> 1) { artI = artI[2..size(artI)]; } // Hay que distinguir T_1 y T_2. Para ello se comparar vectores // de la lista actual de generadores con el que se acaba de // introducir. cont2 = 0; for (j = 1 ; j <= sizcomponents ; j ++) { beta = componentes[1 + cont2]; // Si el nuevo generador divide a la componente beta, hay // que buscar las nuevas componentes for (k = 1 ; k <= nvar ; k ++) { if (expartI[k] >= beta[k]) { break; } } // Si el bucle anterior termino, divide y hay que hacer // los cambios. if (k == nvar + 1) { componentes = delete (componentes,1 + cont2); // Buscamos las nuevas componentes calculando las // distancias. Para cada variable busco d(beta,k,l) for (k = 1 ; k <= nvar ; k ++) { betaaux = beta; max = -1; cont = 0; dbeta = 0; for (l = 1 ; l <= nvar ; l ++) { if (l <> k) { min = 32767; cont ++; for (m = 1 ; m <= sizMin ; m ++) { // Estos son de los buenos if (divide(MinI[m],beta,l) == 1) { if (MinI[m][k] < min) { min = MinI[m][k]; } } } dbeta[cont] = min; } } // Aqui ya tenemos d(beta,k,l) para cada k // Hallamos el maximo cuando terminemos for (l = 1 ; l <= cont ; l ++) { if (dbeta[l] > max) { max = dbeta[l]; } } // Condicion para introducir nueva componente if (max < expartI[k]) { betaaux[k] = expartI[k]; componentes = insert(componentes,betaaux,size(componentes)); } } } else { cont2 ++; } } MinI = insert(MinI,expartI); sizMin = size(MinI); sizcomponents = size(componentes); } // Deahacer los cambios de artiniano si se han hecho if (artiniano[1] == 0) { // En elimina tenemos las variables que hemos introducido // y cual es la potencia // Solo miro las que tengan cambio for (i = 1 ; i <= nvar ; i ++) { if (elimina[i] <> 0) { for (j = 1 ; j <= sizcomponents ; j ++) { if (componentes[j][i] == elimina[i]) { componentes[j][i] = 0; } } } } } // En exp(i) tengo los exponentes de cada variable de las que aparecen // en cada ideal. ideal J; list facets; for (i = 1 ; i <= sizcomponents ; i ++) { J = 0; for (j = 1 ; j <= nvar ; j ++) { if (componentes[i][j] <> 0) { J = J,var(j)^componentes[i][j]; } } J = simplify(J,2); facets[i] = J; } return (facets); } ////////////////////////////////////////////////////////////////////// // static proc incrementalAlgPrim (ideal I) { // VARIABLES list l1,l2; // Hallamos la despomposicion irreducible del ideal dado usando // el algoritmo de Gao-Zhu l1 = incrementalAlg (I); // ----- DESCOMPOSICION PRIMARIA l2 = irredPrimary (l1); return (l2); } // // METODO 9: slice algorithm (Roune) // ////////////////////////////////////////////////////////////////////// // SLICE ALGORITHM (B.Roune) // ////////////////////////////////////////////////////////////////////// // static proc divideMon (poly f , poly g) { return (lead(g)/lead(f)!=0); //int nvar = nvars(basering); //intvec expf = leadexp(f); //intvec expg = leadexp(g); //for (int i = 1 ; i <= nvar ; i ++) //{ // if (expf[i] > expg[i]) // { // return (0); // } //} //return (1); } ////////////////////////////////////////////////////////////////////// // static proc pivot (ideal I , poly lcmMin, ideal S) { // I is monomial ideal int sizI = ncols(I); int nvar = nvars(basering); intvec explcmMin = leadexp(lcmMin); // Variables int i,j; // The median estrategy poly p; int cont, exp, median, sizxi, max; intvec xiexp; for (i = 1 ; i <= nvar ; i ++) { if (explcmMin[i] >= 2 ) { // Median exponent of x(i) from intersection(minI,x(i)) cont = 0; for (j = 1 ; j <= sizI ; j ++) { exp = leadexp(I[j])[i]; if (exp > 0) { cont ++; xiexp[cont] = exp; } } xiexp = sort(xiexp)[1]; sizxi = size(xiexp); if (size(xiexp) == 1) { median = xiexp[1] - 1; } else { if (size(xiexp) == 2) { median = xiexp[2] - 1; } else { median = xiexp[(size(xiexp) + 1) div 2]; } } p = var(i)^median; // valid pivot?? if ( membershipMon(p,S) == 0) { return(p); } else { max = maximoExp(S,i); if ( xiexp[sizxi] == max ) { return(var(i)^(max-1)); } } xiexp = 0; } } } ////////////////////////////////////////////////////////////////////// // static proc simplification (def I) { // VARIABLES int i, j, k, cont, numdeleted; intvec isMaximal; int sizI = ncols(I); int nvar = nvars(basering); poly lcmMinI = 1; for (i = 1 ; i <= sizI ; i ++) { lcmMinI = lcmMon(I[i],lcmMinI); } intvec explcmMinI = leadexp(lcmMinI); // Buscamos los elementos que son x(i) maximales. En caso de que // un generador del ideal sea maximal para 2 variables distintas, // ese generador se elimina. isMaximal[sizI] = 0; intvec genexp; for (i = 1 ; i <= sizI ; i ++) { genexp = leadexp(I[i]); cont = 0; for ( j = 1 ; j <= nvar ; j ++) { if (genexp[j] <> 0 && genexp[j] == explcmMinI[j]) { if (cont == 0) { cont ++; isMaximal[i] = j; } else { // Porque cuando encontramos que era maximal para // la primera variable, lo guardamos isMaximal[i] = 0; // Eliminamos del ideal if (i <> 1 && i <> sizI) { I = I[1..i - 1],I[i + 1..sizI]; } else { if (i == 1) { I = I[2..sizI]; } else { I = I[1..sizI - 1]; } } i --; sizI = ncols(I); // Generador i eliminado, miramos el siguiente break; } } } } // En isMaximal[i] tenemos 0 si I[i] no es maximal, // y j si I[i] es maximal en x(j). // Matriz de exponentes de los generadores del ideal intmat expI[sizI][nvar]; for (i = 1 ; i <= sizI ; i++) { expI[i,1..nvar] = leadexp(I[i]); } // Buscamos ahora cota inferior poly lcmMi = 1; poly l,gcdMi; intvec Mi, mincol,expgcd; for (i = 1 ; i <= nvar ; i ++) { Mi = 0; cont = 0; for (j = 1 ; j <= sizI ; j ++) { // De isMaximal solo se usan las entradas que se corresponden con elementos del ideal if (expI[j,i] <> 0) { if (isMaximal[j] == 0 or isMaximal[j] == i) { // Elementos del sistema minimal que estan // en Mi cont ++; Mi[cont] = j; } } } // Si solo hay un elemento en Mi, no hay nada que hacer if (cont > 1) { gcdMi = I[Mi[1]]; // Tenemos los generadores a los que hay que hallar el gcd for (j = 2; j <= cont ; j ++) { gcdMi = gcd(gcdMi,I[Mi[j]]); } } else { if (Mi <> 0) { gcdMi = I[Mi[1]]; } else { // Falta alguna variable return (0,I); } } l = gcdMi/var(i); lcmMi = lcmMon(lcmMi,l); } // Ahora devolvemos la cota inferior, que luego hay que multiplicar // por el monomio que define el corte. // Devolvemos tambien el ideal (por si se ha modificado). return (lcmMi,I); } ////////////////////////////////////////////////////////////////////// // static proc con (ideal I , ideal S , poly q) { int nvar = nvars(basering); // Variables int i; poly piI; int sizI = ncols(I); // Simplification process poly p; list sol; while (1) { // (I,S,q) normal slice? // Como cada vez que introducimos una cota inferior sabemos // que la slice actual es la inner slice (la otra es vacio), // hay que volver a verificar si es normal if ( S <> 0 ) { // m/rad(m) esta en S, para m generador minimal de I?? for (i = 1 ; i <= sizI ; i ++) { piI = pi(I[i]); if (membershipMon(piI,S) == 1) { if (i == 1) { I = I[2..sizI]; } else { if (i == sizI) { I = I[1..sizI - 1]; } else { I = I[1..i - 1],I[i + 1..sizI]; } } sizI = ncols(I); i --; } } } // Buscamos cota inferior, y si es distinta de 1, simplificamos sol = simplification(I); p = sol[1]; if (p == 1) { break; } else { if (p == 0) { break; } else { if (membershipMon(p,I) == 1 ) { break; } } } // Changing slice by simplification I = sol[2]; I = minbase(quotient(I,p)); q = p*q; S = minbase(quotient(S,p)); sizI = ncols(I); } sizI = ncols(I); // (I,S,q) base case? poly lcmMinI; lcmMinI = 1; for (i = 1 ; i <= sizI ; i ++) { lcmMinI = lcmMon(lcmMinI,I[i]); } // a:b generates an intvec of length b with constant entries a intvec one = 1:nvar; if (divideMon(monomial(one),lcmMinI) == 0) { return (0); } if (equal(radicalMon(I),I) == 1) { if (equal(I, maxideal(1)) == 0) { return (0); } else { for (i = 1 ; i <= nvar ; i ++) { q = q * var(i); } return (q); } } // Selecting pivot p = pivot(I,lcmMinI,S); // New slices ideal S1 = minbase(quotient(S,p)); ideal I1 = minbase(quotient(I,p)); ideal S2 = S,p; S2 = minbase(S2); return (con(I1,S1,p*q),con(I,S2,q)); } ////////////////////////////////////////////////////////////////////// // static proc irredDecMonSlice (ideal I) { int nvar = nvars(basering); int sizI = ncols(I); int i,j; // Artinian ideal ideal artI; list artinianization = artinian(I); if (artinianization[1] == 0) { artI = artinianization[2]; } else { artI = I; } // Easy case: 2 variables if (nvar == 2) { artI = sort(artI)[1]; int sizartI = size(artI); for (i = 1 ; i <= sizartI - 1 ; i ++) { components[i] = var(1)^(leadexp[artI[i]][1])*var(2)^(leadexp[artI[i + 1]][2]); } return (components); } ideal irredDec = con (artI,0,1); // Delelting zeros irredDec = simplify(irredDec,2); // Delting, in case, generators intvec elimina; if (artinianization[1] == 0) { elimina = artinianization[3]; } else { elimina = 0; } // Each generator (monomial) corresponds to an ideal list components; poly comp; intvec exp; int sizIrred = size(irredDec); ideal auxIdeal; for (i = 1 ; i <= sizIrred ; i ++) { comp = irredDec[i]; exp = leadexp(comp); for (j = 1 ; j <= nvar ; j ++) { if (exp[j] <> 0) { if (elimina <> 0) { if (exp[j] == elimina[j]) { auxIdeal[j] = 0; } else { auxIdeal[j] = var(j)^exp[j]; } } else { auxIdeal[j] = var(j)^exp[j]; } } } components[i] = simplify(auxIdeal,2); auxIdeal = 0; } return (components); } ////////////////////////////////////////////////////////////////////// // static proc primDecMonSlice (ideal I) { // VARIABLES list l1,l2; // ---- Irreducible decomposition // Slice Method l1 = irredDecMonSlice (I); // ----- Primary decomposition l2 = irredPrimary (l1); return (l2); } ////////////////////////////////////////////////////////////////////// // // // DECOMPOSITIONS // // // ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// // proc irreddecMon "USAGE: irreddecMon (I[,alg]); I ideal, alg string. RETURN: list, the irreducible components of the monomial ideal I. (returns -1 if I is not a monomial ideal). ASSUME: I is a monomial ideal of the basering k[x(1)..x(n)]. NOTE: This procesure returns the irreducible decomposition of I. One may call the procedure with different algorithms using the optional argument 'alg': - the direct method following Vasconcelos' book (alg=vas) - via the Alexander dual and using doble dual (alg=add), - via the Alexander dual and quotients following E. Miller (alg=ad), - the formula of irreducible components (alg=for), - via the Scarf complex following Milowski (alg=mil), - using the label algorihtm of Roune (alg=lr), - using the algorithm of Gao-Zhu (alg=gz). - using the slice algorithm of Roune (alg=sr). EXAMPLE: example irreddecMon; shows some examples. " { // COMPROBACIONES ideal I = #[1]; int control = checkIdeal(I); // Si el sistema de generadores no esta formado por monomios, hay // que comprobar si el ideal es monomial. if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { I = isMon[2]; // Ya lo tenemos con los generadores minimales } } else { // Generadores monomiales, hallamos sistema minimal I = minbase(I); } // Si el ideal es irreducible, devolvemos el mismo if (isirreducibleMon(I) == 1) { return (I); } // Si no me han dado opcion, elijo una yo. if (size(#) == 1) { return (irredDec3(I)); } // Leo la opcion y llamo al procedimiento oportuno else { if (#[2] == "vas") { return (irredDec1(I)); } if (#[2] == "add") { return (irredDec3(I)); } if (#[2] == "ad") { return (irredDec4(I)); } if (#[2] == "for") { return (irredDec5(I)); } if (#[2] == "mil") { return (ScarfMethod(I)); } if (#[2] == "lr") { return (labelAlgorithm(I)); } if (#[2] == "gz") { return (incrementalAlg(I)); } if (#[2] == "sr") { return (irredDecMonSlice(I)); } } } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z),Dp; ideal I = w^3*x*y,w*x*y*z,x^2*y^2*z^2,x^2*z^4,y^3*z; // Vasconcelos irreddecMon (I,"vas"); // Alexander Dual irreddecMon (I,"ad"); // Scarf Complex irreddecMon (I,"mil"); // slice algorithm irreddecMon(I,"sr"); } ////////////////////////////////////////////////////////////////////// // proc primdecMon "USAGE: primdecMon (I[,alg]); I ideal, alg string RETURN: list, the components in a minimal primary decomposition of I. (returns -1 if I is not a monomial ideal). ASSUME: I is a monomial ideal of the basering k[x(1)..x(n)]. NOTE: This procesure returns a minimal primary decomposition of I. One may call the procedure with different algorithms using the optional argument 'alg': - the direct method for a primary decomposition following Vasconcelos' book (alg=vp), - from the irreducible decomposition obtained via the direct method following Vasconcelos' book (alg=vi), - from the irreducible decomposition obtained via the Alexander dual and using doble dual (alg=add), - from the irreducible decomposition obtained via the Alexander dual and quotients following E. Miller (alg=ad), - from the irreducible decomposition obtained via ........ (alg=for), - from the irreducible decomposition obtained via the Scarf complex following Milowski (alg=mil), - from the irreducible decomposition obtained using the label algorihtm of Roune (alg=lr), - from the irreducible decomposition obtained using the algorithm of Gao-Zhu (alg=gz), - from the irreducible decomposition obtained using the slice algorithm of Roune (alg=sr). EXAMPLE: example primdecMon; shows some examples. " { // COMPROBACIONES ideal I = #[1]; int control = checkIdeal(I); // Si el sistema de generadores no esta formado por monomios, hay // que comprobar si el ideal es monomial. if (control == 0) { list isMon = isMonomialGB (I); if (isMon[1] == 0) { ERROR ("the ideal is not monomial."); } else { I = isMon[2]; // Ya lo tenemos con los generadores minimales } } else { // Generadores monomiales, hallamos sistema minimal I = minbase(I); } // Estudiamos si el ideal es o no primario if (isprimaryMon(I) == 1) { return (I); } // Si no me han dado opcion, elijo una yo. if (size(#) == 1) { return(primDec3(I)); } // Leo la opcion y llamo al procedimiento oportuno else { if (#[2] == "vi") { return (primDec1(I)); } if (#[2] == "vp") { return (primDec2(I)); } if (#[2] == "add") { return (primDec3(I)); } if (#[2] == "ad") { return (primDec4(I)); } if (#[2] == "for") { return (primDec5(I)); } if (#[2] == "mil") { return (scarfMethodPrim(I)); } if (#[2] == "lr") { return (labelAlgPrim(I)); } if (#[2] == "gz") { return (incrementalAlgPrim(I)); } if (#[2] == "sr") { return (primDecMonSlice(I)); } } } example {"EXAMPLE:"; echo = 2; ring R = 0,(w,x,y,z),Dp; ideal I = w^3*x*y,w*x*y*z,x^2*y^2*z^2,x^2*z^4,y^3*z; // Vasconcelos para primaria primdecMon(I,"vp"); // Alexander dual primdecMon(I,"add"); // label algorithm primdecMon(I,"lr"); //slice algorithm primdecMon(I,"sr"); } singular-4.0.3+ds/Singular/LIB/mprimdec.lib000066400000000000000000001733551266270727000204550ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version mprimdec.lib 4.0.0.0 Jun_2013 "; // $Id: a661e43a02223401912a8a968a795aef53a9d30a $ category="Commutative Algebra"; info=" LIBRARY: mprimdec.lib PROCEDURES FOR PRIMARY DECOMPOSITION OF MODULES AUTHORS: Alexander Dreyer, dreyer@mathematik.uni-kl.de; adreyer@web.de OVERVIEW: Algorithms for primary decomposition for modules based on the algorithms of Gianni, Trager and Zacharias and Shimoyama and Yokoyama (generalization of the latter suggested by Hans-Gert Graebe, Leipzig ) using elments of primdec.lib REMARK: These procedures are implemented to be used in characteristic 0. @*They also work in positive characteristic >> 0. @*In small characteristic and for algebraic extensions, the procedures via Gianni, Trager, Zacharias may not terminate. PROCEDURES: separator(l); computes a list of separators of prime ideals PrimdecA(N[,i]); (not necessarily minimal) primary decomposition via Shimoyama/Yokoyama (suggested by Graebe) PrimdecB(N,p); (not necessarily minimal) primary decomposition for pseudo-primary ideals modDec(N[,i]); minimal primary decomposition via Shimoyama/Yokoyama (suggested by Graebe) zeroMod(N[,check]); minimal zero-dimensional primary decomposition via Gianni, Trager and Zacharias GTZmod(N[,check]); minimal primary decomposition via Gianni, Trager and Zacharias dec1var(N[,check[,ann]]); primary decomposition for one variable annil(N); the annihilator of M/N in the basering splitting(N[,check[,ann]]); splitting to simpler modules primTest(i[,p]); tests whether i is prime or homogeneous preComp(N,check[,ann]); enhanced Version of splitting indSet(i); lists with varstrings of(in)dependend variables GTZopt(N[,check[,ann]]); a faster version of GTZmod zeroOpt(N[,check[,ann]]); a faster version of zeroMod "; LIB "primdec.lib"; LIB "ring.lib"; ///////////////////////////////////////////////////////////////////////////// // separator(l) // computes a list of separators for a list of prime ideals // it in a generalization of parts of pseudo_prim_dec_i from primdec.lib ///////////////////////////////////////////////////////////////////////////// proc separator (list @L) "USAGE: separator(l); list l of prime ideals RETURN: list sepList; a list of separators of the prime ideals in l, i.e. polynomials p_ij, s.th. p_ij is in l[j], for all l[j] not contained in l[i] but p_ij is not in l[i] EXAMPLE: example separator; shows an example " { ideal p_ij; // generating p_ij in @L[@j], not in @L[@i] list f_i; // generating f_i NOT in @L[@i], but in all @L[@j] int @i,@j,@k; int sizeL=size(@L); poly @tmp; for(@i=1;@i<=sizeL;@i++) { p_ij=0; @L[@i]=std(@L[@i]); for(@j=1;@j<=sizeL;@j++) // compute the separator sep_i // of the i-th component // f_i separates {Pj not incl in Pi} from Pi { if (@i!=@j) // searching for g: not in @L[@i], but @L[@j] { for(@k=1;@k<=ncols(@L[@j]);@k++) { if(NF(@L[@j][@k],@L[@i],1)!=0) { p_ij=p_ij+@L[@j][@k]; break; } } } } @tmp=lcm(p_ij); if(@tmp==0) { @tmp=1; } f_i=f_i+list(@tmp); } return(f_i); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; ideal i=(x2y,xz2,y2z,z3); list l=minAssGTZ(i); list sepL=separator(l); sepL; } ///////////////////////////////////////////////////////////////////////////// // PrimdecA(N[,i]) // computes a primary decomposition, not necessarily minimal, // using a generalization of the algorithm of Shimoyama/Yokoyama, // suggested by Hans-Gerd Graebe, Leipzig // [Hans-Gert Graebe, Minimal Primary Decompostion // and Factorized Groebner Bases, AAECC 8, 265-278 (1997)] ///////////////////////////////////////////////////////////////////////////// proc PrimdecA(module @N, list #) "USAGE: PrimdecA (N[, i]); module N, int i RETURN: list l a (not necessarily minimal) primary decomposition of N computed by a generalized version of the algorithm of Shimoyama/Yokoyama, @*if i!=0 is given, the factorizing Groebner is used to compute the isolated primes EXAMPLE: example PrimdecA; shows an example " { module @M=freemodule(nrows(@N)); // @M=basering^k ideal ann=annil(@N); // the annihilator of @N //////////////////////////////////////////////////////////////// // in the trivial case we avoid to compute anything //////////////////////////////////////////////////////////////// if (ann[1]==1) { return(list()); } //////////////////////////////////////////////////////////////// // Computation of the Associated Primes //////////////////////////////////////////////////////////////// if (ann[1]==0) { list pr=list(ideal(0)); } else { if( (size(#)>0) ){ list pr = minAssChar(ann); // causes message "/ ** redefining @res **" } else{ list pr = minAssGTZ(ann); } } list sp, pprimary; // the separators and the pseudo-primary modules int @i; ideal rest; // for the computation of the remaining components sp=separator(pr); int sizeSp=size(sp); // the number of separators //////////////////////////////////////////////////////////////// // Computation of the pseudo-primary modules // and an ideal rest s.th. @N is the intersection of the // pseudo-primary modules and @N+rest*@M //////////////////////////////////////////////////////////////// for(@i=1;@i<=sizeSp;@i++) { pprimary=pprimary+list(sat(@N,sp[@i])); rest=rest+sp[@i]^pprimary[@i][2]; } list result; // a primary decomposition of @N //////////////////////////////////////////////////////////////// // Extraction of the pseudo-primary modules //////////////////////////////////////////////////////////////// for (@i=1;@i<=size(pprimary);@i++) { result=result+PrimdecB(pprimary[@i][1],pr[@i]); } //////////////////////////////////////////////////////////////// // Computation of remaining components //////////////////////////////////////////////////////////////// result=result+PrimdecA(@N+rest*@M); return(result); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; module N=x*gen(1)+ y*gen(2), x*gen(1)-x2*gen(2); list l=PrimdecA(N); l; } ///////////////////////////////////////////////////////////////////////////// // PrimdecB(N, p) // computes a primary decomposition, not necessarily minimal, // of a pseudo-primary module N with isolated prime p // it is based on extraction in primdec.lib ///////////////////////////////////////////////////////////////////////////// proc PrimdecB(module @N, ideal isoPrim) "USAGE: PrimdecB (N, p); pseudo-primary module N, isolated prime ideal p RETURN: list l a (not necessarily minimal) primary decomposition of N EXAMPLE: example PrimdecB; shows an example " { module @M=freemodule(nrows(@N)); // @M=basering^k ideal ann=annil(@N); // the annihilator of @N //////////////////////////////////////////////////////////////// // the not-that-trivial case of ann==0 //////////////////////////////////////////////////////////////// if(size(ann)==0) { def BAS=basering; execute("ring Rloc=("+charstr(basering)+","+varstr(basering)+"),dummy,("+ordstr(basering)+");"); module @N=imap(BAS, @N); poly @q=prepareSat(@N); setring BAS; poly @q=imap(Rloc, @q); list satu=sat(@N,@q); if(satu[2]==0) { return(list(list(@N,ideal(0)))); } else { return(list(list(satu[1],ideal(0)))+ PrimdecA(@N+(@q^satu[2])*@M)); } } //////////////////////////////////////////////////////////////// // Extraction of the isolated component @N' and // searching for a polynomial @f of minimal degree // s.th. @N=intersect(@N', @N+@f*@M) //////////////////////////////////////////////////////////////// list indSets=indepSet(ann,0); poly @f; if(size(indSets)!=0) //check, whether dim isoPrim !=0 { intvec indVec; // a maximal independent set of variables // modulo isoPrim string @U; // the independent variables string @A; // the dependent variables int @j,@k; int szA; // the size of @A int degf; ideal @g; list polys; int sizePolys; list newPoly; //////////////////////////////////////////////////////////////// // the preparation of the quotient ring //////////////////////////////////////////////////////////////// def BAS=basering; for (@k=1;@k<=size(indSets);@k++) { indVec=indSets[@k]; for (@j=1;@j<=nvars(BAS);@j++) { if (indVec[@j]==1) { @U=@U+varstr(@j)+","; } else { @A=@A+varstr(@j)+","; szA++; } } @U[size(@U)]=")"; // we compute the extractor (w.r.t. @U) execute("ring RAU="+charstr(basering)+",("+@A+@U+",(C,dp("+string(szA)+"),dp);"); module @N=std(imap(BAS,@N)); // this is also a standard basis in (R[U])[A] @A[size(@A)]=")"; execute("ring Rloc=("+charstr(basering)+","+@U+",("+@A+",(C,dp);"); ideal @N=imap(RAU,@N); ideal @h; for(@j=ncols(@N);@j>=1;@j--) { @h[@j]=leadcoef(@N[@j]); // consider I in (R(U))[A] } setring BAS; @g=imap(Rloc,@h); kill RAU,Rloc; @U=""; @A=""; szA=0; @f=lcm(@g); newPoly[1]=@f; polys=polys+newPoly; newPoly=list(); } @f=polys[1]; degf=deg(@f); sizePolys=size(polys); for (@k=2;@k<=sizePolys;@k++) { if (deg(polys[@k]) sat(N,f)=sat(sat(N,f),p) //////////////////////////////////////////////////////////////// list tempList; for(@i=1;@i<=sizePrim;@i++) { tempList=tempList+list(prim[@i][2]); } list sepPrimes=separator(tempList); // the separators of the primes tempList=list(); for(@i=1;@i<=sizePrim;@i++) // compute sat(N,f), for all separators f { tempList=tempList+list(sat(@N,sepPrimes[@i])[1]); } module testMod; @k=0; for(@i=1;@i<=sizePrim;@i++) { testMod=sat(tempList[@i],prim[@i-@k][2])[1]; // computes sat(sat(N,f),p) if (size(NF(testMod,std(tempList[@i]),1))==0) // tests if equal to sat(N,f) { prim=delete(prim,@i-@k); // if yes: the component @k++; // is superfluous } } return(prim); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; module N=x*gen(1)+ y*gen(2), x*gen(1)-x2*gen(2); list l=modDec(N); l; } ///////////////////////////////////////////////////////////////////////////// // zeroMod (N[, check]) // computes a minimal primary decomposition of a zero-dimensional Module // using a generalized version of the algorithm of // Gianni, Trager and Zacharias, suggested by Alexander Dreyer // [Diploma Thesis, University of Kaiserslautern, 2001] ///////////////////////////////////////////////////////////////////////////// proc zeroMod (module @N, list #) "USAGE: zeroMod (N[, check]); zero-dimensional module N[, module check] RETURN: list l the minimal primary decomposition of a zero-dimensional module N, computed by a generalized version of the algorithm of Gianni, Trager and Zacharias NOTE: if the parameter check is given, only components not containing check are computed EXAMPLE: example zeroMod; shows an example " { //////////////////////////////////////////////////////////////// // the module check is needed to compute a minimal decomposition // components containing check are ignored //////////////////////////////////////////////////////////////// if (size(#)>0) { module check=#[1]; if (size(NF(check,std(@N),1))==0) { return(list()); } } else { module check=freemodule(nrows(@N)); } //////////////////////////////////////////////////////////////// // the ordering is changed to lex //////////////////////////////////////////////////////////////// def BAS = basering; def @R=changeord(list(list("lp",1:nvars(basering)))); setring @R; module @N=fetch(BAS,@N); int nVar=nvars(@R); module @M=freemodule(nrows(@N)); // @M=basering^k ideal ann=std(quotient(@N,@M)); // the annihilator of @M/@N int @k; list result, rest; ideal primary, prim; module primMod; //////////////////////////////////////////////////////////////// // the random coordnate change and its inverse //////////////////////////////////////////////////////////////// option(redSB); ideal prepMap=maxideal(1); prepMap[nVar]=0; prepMap[nVar]=(random(100,1,nVar)*transpose(prepMap))[1,1]+var(nVar); map phi=@R,prepMap; prepMap[nVar]=2*var(nVar)-prepMap[nVar]; map invphi=@R,prepMap; ideal @j=std(phi(ann)); list fac=factorize(@j[1],2); // factorization of the 1st elt. in Ann(@N) //////////////////////////////////////////////////////////////// // Case: 1st element irreducible //////////////////////////////////////////////////////////////// if(size(fac[2])==1) { prim=primaryTest(@j,fac[1][1]); prim=invphi(prim); setring BAS; @N=std(@N); ideal prim=std(imap(@R,prim)); kill @R; if(prim!=0) { return(list(list(@N,prim))); } else { return(zeroMod(@N,check)); } } 2; //////////////////////////////////////////////////////////////// // Computation of the - hopefully primary - modules // their annihilators and associated primes //////////////////////////////////////////////////////////////// poly @p, @h; module check; for (@k=1;@k<=size(fac[1]);@k++) { @p=fac[1][@k]^fac[2][@k]; @h=@j[1]/@p; primMod=std(quotient(phi(@N),@h)); check=imap(BAS,check); check=phi(check); if (size(NF(check,primMod,1))>0) { primary=std(@j+@p); // test if the modules were primary and in general position prim=primaryTest(primary,fac[1][@k]); if (prim==0) { rest[size(rest)+1]=invphi(primMod); } else { result[size(result)+1]=list(std(invphi(primMod)),std(invphi(prim))); } } } //////////////////////////////////////////////////////////////// // the bad cases //////////////////////////////////////////////////////////////// for (@k=1; @k<=size(rest);@k++) { result = result+zeroMod(rest[@k],invphi(check)); } option(noredSB); setring BAS; list result=imap(@R, result); kill @R; return(result); } example { "EXAMPLE:"; echo = 2; ring r=0,z,dp; module N=z*gen(1),(z-1)*gen(2),(z+1)*gen(3); list l=zeroMod(N); l; } ///////////////////////////////////////////////////////////////////////////// // GTZmod (N[, check]) // computes a minimal primary decomposition of N // using a generalized version of the algorithm of // Gianni, Trager and Zacharias, suggested by Alexander Dreyer // [Diploma Thesis, University of Kaiserslautern, Germany, 2001] ///////////////////////////////////////////////////////////////////////////// proc GTZmod (module @N, list #) "USAGE: GTZmod (N[, check]); module N[, module check] RETURN: list l the minimal primary decomposition of the module N, computed by a generalized version of the algorithm of Gianni, Trager and Zacharias NOTE: if the parameter check is given, only components not containing check are computed EXAMPLE: example GTZmod; shows an example " { if (size(@N)==0) { return(list(@N,ideal(0))); } //////////////////////////////////////////////////////////////// // the module check is needed to compute a minimal decomposition // components containing check are ignored //////////////////////////////////////////////////////////////// if (size(#)>0) { module check=#[1]; if (size(NF(check,std(@N),1))==0) { return(list()); } } else { module check= freemodule(nrows(@N)); } module @M=freemodule(nrows(@N)); def BAS = basering; int @j; int nVar=nvars(BAS); int @k; string @U; // the independent variables string @A; // the dependent variables @N=std(@N); ideal ann=std(quotient(@N,@M)); // the annihilator of @M/@N //////////////////////////////////////////////////////////////// // the trivial and the zero-dimensional case //////////////////////////////////////////////////////////////// int Ndim=dim(@N); if ((Ndim==0)||(Ndim==-1)) { return(zeroMod(@N, check)); } //////////////////////////////////////////////////////////////// // the not-that-trivial case of ann==0 //////////////////////////////////////////////////////////////// if(size(ann)==0) { execute("ring Rloc=("+charstr(basering)+","+varstr(basering)+"),dummy,("+ordstr(basering)+");"); module @N=imap(BAS, @N); poly @q=prepareSat(@N); setring BAS; poly @q=imap(Rloc, @q); list satu=sat(@N,@q); if(satu[2]==0) { return(list(list(@N,ideal(0)))); } else { check=intersect(check,satu[1]); return(list(list(satu[1],ideal(0)))+GTZmod(@N+(@q^satu[2])*@M,check)); } } //////////////////////////////////////////////////////////////// // the preparation of the quotient ring //////////////////////////////////////////////////////////////// intvec indVec=indepSet(ann); int szA; for (@k=1;@k<=size(indVec);@k++) { if (indVec[@k]==1) { @U=@U+varstr(@k)+","; } else { @A=@A+varstr(@k)+","; szA++; } } @U[size(@U)]=")"; // we compute the extractor (w.r.t. @U) execute("ring RAU="+charstr(basering)+",("+@A+@U+",(C,dp("+string(szA)+"),dp);"); module @N=std(imap(BAS,@N)); // this is also a standard basis in (R[U])[A] @A[size(@A)]=")"; execute("ring Rloc=("+charstr(basering)+","+@U+",("+@A+",(C,dp);"); module @N=imap(RAU,@N); kill RAU; //////////////////////////////////////////////////////////////// // the zero-dimensional decomposition //////////////////////////////////////////////////////////////// list qprim=zeroMod(@N,imap(BAS,check)); //////////////////////////////////////////////////////////////// // preparation for saturation //////////////////////////////////////////////////////////////// poly @q=prepareSat(@N); if (size(qprim)==0) { setring BAS; poly @q=imap(Rloc,@q); kill Rloc; @q=@q^sat(@N,@q)[2]; if (deg(@q)>0) { return(GTZmod(@N+@q*@M,check)); } else { return(list()); } } list @p; for (@k=1;@k<=size(qprim);@k++) { @p[@k]=list(prepareSat(qprim[@k][1]),prepareSat(qprim[@k][2])); } //////////////////////////////////////////////////////////////// // compute the recontractions // back in the original ring //////////////////////////////////////////////////////////////// setring BAS; list @p=imap(Rloc,@p); list qprim=imap(Rloc,qprim); poly @q=imap(Rloc,@q); kill Rloc; for(@k=1;@k<=size(qprim);@k++) { qprim[@k]=list(sat(qprim[@k][1],@p[@k][1])[1], sat(qprim[@k][2],@p[@k][2])[1]); check=intersect(check,qprim[@k][1]); } @q=@q^sat(@N,@q)[2]; if (deg(@q)>0) { qprim=qprim+GTZmod(@N+@q*@M,check); } return(qprim); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; module N=x*gen(1)+ y*gen(2), x*gen(1)-x2*gen(2); list l=GTZmod(N); l; } proc prepareSat(module @N, list #) { int @k; poly @p=leadcoef(@N[1]); for (@k=2;@k<=size(@N);@k++) { @p=lcm_chr(@p,leadcoef(@N[@k])); // @p=@p*leadcoef(@N[@k]); } return(@p); } proc lcm_chr(poly @i, poly @j) { def LBAS = basering; if (npars(basering)==0) { string strg=""; } else { if (nvars(basering)==0) { string strg=parstr(basering); } else { string strg=parstr(basering)+","; } } execute("ring PRing="+string(char(basering))+",("+strg+varstr(basering)+"),dp"); ideal @a=ideal(imap(LBAS,@i),imap(LBAS,@j)); poly @p=lcm(@a); setring LBAS; poly @p=imap(PRing,@p); kill PRing; return(@p); } /////////////////////////////////////////////////////////////////////// // The optimized procedures and procdures needed for this optimization /////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // testit (N, l) // a small procedure, which checks whether // N=intersect(l[1][1],...,l[size(l)][1]) // and whether annil(l[i][1]) is primary // Just for testing the procedures. ///////////////////////////////////////////////////////////////////////////// proc testit (module N, list #) "USAGE: testit (N, l); module N, list l EXAMPLE: example testit; shows an example " { if (size(#)==0) { return() } int i; list l=#; module nn=freemodule(nrows(N)); module M=freemodule(nrows(N)); for(i=1;i<=size(l);i++) { nn=intersect(nn,l[i][1]); if ((size(decomp(quotient(l[i][1],M)))>2)&&(size(l[i][2])>0)) { "nicht primary obwohl erkannt!"; l[i];std(quotient(l[i][1],M));std(radical(quotient(l[i][1],M))); pause(); } } int j,k; j=size(NF(nn,std(N),1)); k=size(NF(N,std(nn),1)); if ((j!=0)||(k!=0)) { "testit fehler!!!"; pause(); } } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; module N=x*gen(1)+ y*gen(2), x*gen(1)-x2*gen(2); list l=GTZmod(N); testit(N,l); } ///////////////////////////////////////////////////////////////////////////// // annil (N) // computes the annihilator of M/N in the basering ///////////////////////////////////////////////////////////////////////////// proc annil (module N) "USAGE: annil(N); modul N RETURN: ideal ann=std(quotient(N,freemodule(nrows(N)))); the annihilator of M/N in the basering NOTE: ann is a std basis in the basering EXAMPLE: example annil; shows an example " { intvec optionsVec=option(get); option (returnSB); ideal ann=quotient(N,freemodule(nrows(N))); attrib (ann, "isSB",1); option (set,optionsVec); return(ann); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; module N=x*gen(1), y*gen(2); ideal ann=annil(N); ann; } ///////////////////////////////////////////////////////////////////////////// // splitting(N[,check[, ann]]) // INPUT: a zero-dimensional module N, module check, ideal ann=annil(N) // splitting computes an list of modules // using the factorization of the elements of annil(N) // s.th. N is equal to the intersections of these modules // A prim test is used to check if the modules are primary // OUTPUT: (l, check) ///////////////////////////////////////////////////////////////////////////// proc splitting (module @N, list #) "USAGE: splitting(N[,check[, ann]]); modul N, module check, ideal ann RETURN: (l, check) list l, module check the elements of l consists of quadruples, where [1] is of type module, [2], [3] and [4] are of type ideal, s.th. the intersection of the modules is equal to the zero-dimensional module N, furthermore l[j][3]=annil(l[j][1]) and l[j][4] contains internal ideal data; if l[j][2]!=0 then the module l[j][1] is primary with associated prime l[j][2], and check=intersect(check, l[j][1]) is computed NOTE: if the parameter check is given, only components not containing check are computed; if ann is given, ann is used instead of annil(N) EXAMPLE: example splitting; shows an example " { ideal ann; module check, @M; int checked; (ann, check, @M,checked)=getData(@N,#); if(checked) { return(list()); } if(size(#)>=3) { ideal splitPrime=#[3]; } else { ideal splitPrime=ann; } list fact, result, splitTemp; int @i,@k,@j,szFact; for (@i=1;@i<=size(ann);@i++) { fact=factorize(ann[@i],2); szFact=size(fact[2]); // if the element is the power of an irreducible element if(szFact==1) { if(vdim(ann)==deg(ann[@i])) { splitPrime=interred(splitPrime+ideal(fact[1][1])); result=result+list(list(@N,splitPrime,ann,splitPrime)); } else { splitPrime=interred(splitPrime+ideal(fact[1][1])); if (homog(splitPrime)) { result=result+list(list(@N,maxideal(1),ann,splitPrime)); } } } else { if(gcdTest(fact[1])) // Case: (f1,...,fk)=(1) { (splitTemp, check)=sp1(@N,fact,check,ann,splitPrime); result=result+splitTemp; } else { // if the element is not irreducible (splitTemp, check)=sp2(@N,fact[1][1],check,ann,splitPrime); result=result+splitTemp; } } } @i=1;@k=size(result); //////////////////////////////////////////////////////////////// // delete multiple Modules //////////////////////////////////////////////////////////////// while (@i<=@k) { @j=1; while(@j<=@i-1) { if (stdModulesEqual(result[@j][1],result[@k][1])) { result=delete(result,@i); @k--;@i--;break; } @j++; } @i++; } list rest; @i=1;@k=size(result); //////////////////////////////////////////////////////////////// // if not primary then split the obtained modules once again //////////////////////////////////////////////////////////////// while (@i<=@k) { if (size(result[@i][2])==0) { rest=rest+list(list(result[@i][1],result[@i][3],result[@i][4])); result=delete(result,@i); @k--;@i--; } else { check=intersect(check,result[@i][1]); } @i++; } for(@i=1;@i<=size(rest);@i++) { (splitTemp,check)=splitting(rest[@i][1],check,rest[@i][2],rest[@i][3]); result=result+splitTemp; } if (size(result)==0) { result=list(list(@N,ideal(0),ann,ann)); } return(result, check); } example { "EXAMPLE:"; echo = 2; ring r=0,z,lp; module N=z*gen(1), (z+1)*gen(2); N=std(N); list l; module check; (l, check)=splitting(N); l; check; } //////////////////////////////////////////////////////////////// // sp1: splits a module as follows // (N+f*g*M)=intersect((N+f*M),(N+g*M)) if (f,g)=(1) //////////////////////////////////////////////////////////////// static proc sp1(module @N,list fact,list #) { ideal ann; module check, @M; int @i; (ann, check, @M, @i)=getData(@N, #); if(size(#)>=3) { ideal splitPrime=#[3]; } else { ideal splitPrime=ann; } list pr; module splitMod; ideal splitAnn, prim, tempPrime; for(@i=1;@i<=size(fact[2]);@i++) { splitMod=std(@N+(fact[1][@i]^fact[2][@i])*@M); if(size(NF(check,splitMod,1))>0) { splitAnn=std(ann,(fact[1][@i]^fact[2][@i])); tempPrime=interred(splitPrime+ideal(fact[1][@i])); prim=primTest(splitAnn,fact[1][@i],tempPrime); pr=pr+list(list(splitMod,prim,splitAnn,tempPrime)); if (size(prim)>0) { check=intersect(check,splitMod); } } } return (pr, check); } //////////////////////////////////////////////////////////////// // sp2: splits a module as follows // N=intersect((N:f),(N+f*M)) //////////////////////////////////////////////////////////////// static proc sp2(module @N, poly p, list #) { ideal ann; module check, @M; int @i; (ann, check, @M, @i)=getData(@N, #); if(size(#)>=3) { ideal splitPrime=#[3]; } else { ideal splitPrime=ann; } list fact=sat(@N, p); list splitList; ideal splitAnn, prim, tempPrime; if (fact[2]>0) { module n1=std(@N+(p^fact[2]*@M)); module n2=fact[1]; if (size(NF(check,n1,1))>0) { splitAnn=std(ann+ideal(p^fact[2])); tempPrime=interred(splitPrime+ideal(p)); prim=primTest(tempPrime); splitList=list(list(n1, prim, splitAnn,tempPrime)); if(size(prim)>0) { check=intersect(check, n1); } } if(size(NF(check,n2,1))>0) { splitAnn=annil(n2); prim=primTest(splitAnn); splitList=splitList+list(list(n2,prim,splitAnn,splitAnn)); if(size(prim)>0) { check=intersect(check, n2); } } return(splitList, check); } else { return (list(list(@N,ideal(0),ideal(0))), check); } } ///////////////////////////////////////////////////////////////////////////// // primeTest(i[, p]) // tests whether i is prime or homogeneous // is both cases radical(i) is returned ///////////////////////////////////////////////////////////////////////////// proc primTest(ideal id, list #) "USAGE: primTest(i[, p]); a zero-dimensional ideal i, irreducible poly p in i RETURN: if i is neither prime nor homogeneous then ideal(0) is returned, otherwise radical(i) EXAMPLE: example primTest; shows an example " { ideal tempPrime; int testTempPrime; if (size(#)>0) { poly @p=#[1]; if(size(#)>1) { tempPrime=#[2]; testTempPrime=1; } } else { poly @p=0; } ideal prim=ideal(0); if((size(#)>0)&&(vdim(id)==deg(@p))) { prim=id; } else { if ((homog(id))||((testTempPrime)&&(homog(tempPrime)))) { prim=maxideal(1); } } return (prim); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),lp; ideal i=x+1,y-1,z; i=std(i); ideal primId=primTest(i,z); primId; i=x,z2,yz,y2; i=std(i); primId=primTest(i); primId; } ///////////////////////////////////////////////////////////////////////////// // preComp(N, check[, ann]) // preComp is an enhanced version of splitting, // but before computing splitting the first element of std(annil(N)) // is factorized and the obtained modules are tested for primarity ///////////////////////////////////////////////////////////////////////////// proc preComp (module @N, list #) "USAGE: preComp(N,check[, ann]); modul N, module check, ideal ann RETURN: (l, check) list l, module check the elements of l consists of a triple with [1] of type module [2] and [3] of type ideal s.th. the intersection of the modules is equal to the zero-dimensional module N, furthermore l[j][3]=annil(l[j][1]) if l[j][2]!=0 then the module l[j][1] is primary with associated prime l[j][2], and check=intersect(check, l[j][1]) is computed NOTE: only components not containing check are computed; if ann is given, ann is used instead of annil(N) EXAMPLE: example preComp; shows an example " { def BAS=basering; def @R=changeord(list(list("C",0:1),list("lp",1:nvars(basering)))); setring @R; module @N=std(imap(BAS,@N)); ideal ann; module check, @M; int @k; (ann, check, @M, @k)=getData(@N,imap(BAS,#),1); list act,primary; ideal primid,helpid; module primmod; //////////////////////////////////////////////////////////////// // the first element of the standardbase is factorized //////////////////////////////////////////////////////////////// if(deg(ann[1])>0) { act=factorize(ann[1],2); } else { setring BAS; module check=imap(@R,check); kill @R; return(list(), check); } //////////////////////////////////////////////////////////////// // with the factors new modules are created // (hopefully the primary decomposition) //////////////////////////////////////////////////////////////// if(size(act[1])>1) // Case: act[1] not irreducible { for(@k=1;@k<=size(act[1]);@k++) { primmod=std(@N+(act[1][@k]^act[2][@k])*@M); if (size(NF(check,primmod,1))>0) { primid=std(ann,act[1][@k]^act[2][@k]); if((act[2][@k]==1)&&(vdim(primid)==deg(act[1][@k]))) { primary = primary+list(list(primmod,primid,primid)); } else { helpid=primid; primid=primaryTest(primid,act[1][@k]); primary = primary+list(list(primmod,primid,helpid)); } } if (size(primid)>0) { check=intersect(check, primmod); } } } else // Case: act[1] irreducible { primid=ann; primmod=@N; if (size(NF(check,primmod,1))>0) { if((act[2][1]==1)&&(vdim(primid)==deg(act[1][1]))) { primary = primary+list(list(primmod,primid,primid)); } else { primid = primaryTest(primid,act[1][1]); primary = primary+list(list(primmod,primid,ann)); } if (size(primid)>0) { check=intersect(check,primmod); } } } if (size(primary)==0) { setring BAS; module check=imap(@R,check); kill @R; return(list(), check); } //////////////////////////////////////////////////////////////// // the modules which are not primary are splitted //////////////////////////////////////////////////////////////// list splitTemp; int sz=size(primary); @k=1; while (@k<=sz) { if (size(primary[@k][2])==0) { (splitTemp, check)=splitting(primary[@k][1],check,primary[@k][3]); primary = delete(primary, @k)+splitTemp; @k--;sz--; } @k++; } setring BAS; list primary=imap(@R,primary); module check=imap(@R,check); kill @R; return(primary,check); } example { "EXAMPLE:"; echo = 2; ring r=0,z,lp; module N=z*gen(1), (z+1)*gen(2); N=std(N); list l; module check; (l, check)=preComp(N,freemodule(2)); l; check; } ///////////////////////////////////////////////////////////////////////////// // indSet(i) // based on independendSet from primdec.lib ///////////////////////////////////////////////////////////////////////////// proc indSet (ideal @j) "USAGE: indSet(i); i ideal RETURN: list with two entries both are lists of new varstrings with the dependent variables, the independent set, the ordstring with the corresp. block ordering, and the integer where the independent set starts in the varstring NOTE: the first entry gives the strings for all maximal independent sets the second gives the strings for the independent sets, which cannot be enhanced EXAMPLE: example indSet; shows an example " { int n,k,di; int jdim=dim(@j); list maxind, rest,hilf; string var1,var2; list v=indepSet(@j,1); for(n=1;n<=size(v);n++) { di=0; var1=""; var2=""; for(k=1;k<=size(v[n]);k++) { if(v[n][k]!=0) { di++; var2=var2+string(var(k))+","; } else { var1=var1+string(var(k))+","; } } if(di>0) { var1=var1[1..size(var1)-1]; var2=var2[1..size(var2)-1]; hilf[1]=var1; hilf[2]=var2; hilf[3]="(C,dp("+string(nvars(basering)-di)+"),dp)"; //"lp("+string(nvars(basering)-di)+"),dp("+string(di)+")"; hilf[4]=di; if(di==jdim) { maxind=maxind+list(hilf); } else { rest=rest+list(hilf); } } else { if(jdim==0) { maxind=maxind+list(varstr(basering),"dummy",ordstr(basering),0); } else { rest=rest+list(varstr(basering),"dummy",ordstr(basering),0); } resu[n]=varstr(basering),ordstr(basering),0; } } return(list(maxind,rest)); } example { "EXAMPLE:"; echo = 2; ring s1=(0,x,y),(a,b,c,d,e,f,g),lp; ideal i=ea-fbg,fa+be,ec-fdg,fc+de; i=std(i); list l=indSet(i); l; } ///////////////////////////////////////////////////////////////////////////// // GTZopt(N[,check[, ann]]) // a faster version of GTZMod ///////////////////////////////////////////////////////////////////////////// proc GTZopt (module @N, list #) "USAGE: GTZopt (N[, check]); module N[, module check] RETURN: list l the minimal primary decomposition of the module N, computed by a generalized and optimized version of the algorithm of Gianni, Trager and Zacharias NOTE: if the parameter check is given, only components not containing check are computed EXAMPLE: example GTZmod; shows an example " { @N=std(@N); if (size(@N)==0) { return(list(@N,ideal(0))); } //////////////////////////////////////////////////////////////// // the module check is needed to compute a minimal decomposition // components containing check are ignored //////////////////////////////////////////////////////////////// ideal ann; module check, @M; int checked; (ann, check, @M, checked)=getData(@N, #); if (checked) { return(list()); } //////////////////////////////////////////////////////////////// // if ann is zero-dimensional and homogeneous // then it is primary with associated prime maxideal(1) //////////////////////////////////////////////////////////////// if((homog(ann)==1)&&(dim(ann)==0)) { return(list(list(@N,maxideal(1)))); } //////////////////////////////////////////////////////////////// // the not-that-trivial case of ann==0 //////////////////////////////////////////////////////////////// def BAS = basering; if(size(ann)==0) //check, whether ann=0 { execute("ring Rloc=("+charstr(basering)+","+varstr(basering)+"),dummy,("+ordstr(basering)+");"); module @N=clrSBmod(imap(BAS, @N)); module @M=freemodule(nrows(@N)); poly @q=prepareSat(@N); setring BAS; poly @q=imap(Rloc, @q); list satu=sat(@N,@q); if(satu[2]==0) { return(list(list(@N,ideal(0)))); } else { check=intersect(check,satu[1]); return(list(list(satu[1],ideal(0)))+GTZopt(@N+(@q^satu[2])*@M,check)); } } int @k1, @k2, @k3, @k4; // the indices for nested for/while loops int nVar=nvars(BAS); int Ndim=dim(@N); //////////////////////////////////////////////////////////////// // Simplification of the modules using // N=N/(a*x_i+b)*M+(a*x_i+b)*M, for (a*x_i+b) in ann //////////////////////////////////////////////////////////////// if (size(#)==0) { ideal fried; @k2=size(ann); for(@k1=1;@k1<=@k2;@k1++) { if(deg(lead(ann[@k1]))==1) { fried[size(fried)+1]=ann[@k1]; } } if(size(fried)==nVar) { return(list(list(@N, ann))); } if(size(fried)>0) { string newva; string newma; for(@k1=1;@k1<=nVar;@k1++) { checked=0; for(@k2=1;@k2<=size(fried);@k2++) { if(leadmonom(fried[@k2])==var(@k1)) { checked=1; break; } } if(checked==0) { newva=newva+string(var(@k1))+","; newma=newma+string(var(@k1))+","; } else { newma=newma+string(var(@k1)-((1/leadcoef(fried[@k2]))*fried[@k2]))+","; } } newva[size(newva)]=")"; newma[size(newma)]=";"; execute("ring @deirf=("+charstr(BAS)+"),("+newva+",(C,lp);"); execute("map @kappa=BAS,"+newma); ideal @j = @kappa(ann); module @N = @kappa(@N); @N=simplify(@N,2); @j=simplify(@j,2); list pr=GTZopt(@N,freemodule(nrows(@N)),@j); setring BAS; list pr=imap(@deirf,pr); for(@k1=1;@k1<=size(pr);@k1++) { pr[@k1][1]=std(pr[@k1][1]+fried*@M); pr[@k1][2]=std(pr[@k1][2]+fried); } return(pr); } } //////////////////////////////////////////////////////////////// // the trivial case //////////////////////////////////////////////////////////////// if(Ndim==-1) { return(list(list(@N,ideal(1)))); } //////////////////////////////////////////////////////////////// // the case of one variable //////////////////////////////////////////////////////////////// if(nVar==1) { return(dec1var(@N)); } //////////////////////////////////////////////////////////////// // the zerodimensional case //////////////////////////////////////////////////////////////// if (Ndim==0) { return(zeroOpt(@N, check, ann)); } //////////////////////////////////////////////////////////////// // the preparation of the quotient ring //////////////////////////////////////////////////////////////// list result; list indep =indSet(ann); poly @q; list @p,primary; ideal @h; int szIndep; for (@k1=1;@k1<=2;@k1++) { szIndep=size(indep[@k1]); for (@k2=1;@k2<=szIndep;@k2++) { execute("ring RAU=("+charstr(basering)+"),("+indep[@k1][@k2][1]+","+indep[@k1][@k2][2]+"),"+indep[@k1][@k2][3]+";"); module @N=std(imap(BAS,@N)); // the standard basis in (R[U])[A] execute("ring Rloc=("+charstr(basering)+","+indep[@k1][@k2][2]+"),("+indep[@k1][@k2][1]+"),(C,dp);"); module @N=imap(RAU,@N); //std in lokalisierung @N=clrSBmod(@N); kill RAU; //////////////////////////////////////////////////////////////// // the zero-dimensional decomposition //////////////////////////////////////////////////////////////// list qprim, preList; module check=imap(BAS, check); (preList,check)=preComp(@N,check); for (@k3=1; @k3<=size(preList); @k3++) { if(size(preList[@k3][2])>0) { qprim=qprim+list(list(preList[@k3][1],preList[@k3][2])); } else { checked=size(qprim); qprim=qprim+zeroOpt(preList[@k3][1], check, preList[@k3][3]); for(@k4=checked+1;@k4<=size(qprim);@k4++) { check=intersect(check, qprim[@k4][1]); } } } // end of for(@k3...) kill preList; //////////////////////////////////////////////////////////////// // Preparation of the saturation of @N //////////////////////////////////////////////////////////////// //poly pp=prepareSat(@N); ideal @h2; for (@k3=1;@k3<=size(@N);@k3++) { @h2[@k3]=leadcoef(@N[@k3]); } if (size(qprim)==0) // there aren't any new components { setring BAS; check=imap(Rloc,check); @h=imap(Rloc,@h2); @q=minSatMod(imap(BAS,@N),@h)[2]; // @q=imap(Rloc,pp)^sat(imap(BAS,@N),imap(Rloc,pp))[2]; kill Rloc; if (deg(@q)>0) { @N=std(@N+@q*@M); ann=std(ideal(ann+@q)); kill qprim; } } else // there are new components { //////////////////////////////////////////////////////////////// // Preparation of the saturation of qprim //////////////////////////////////////////////////////////////// list @p2; for (@k3=1;@k3<=size(qprim);@k3++) { @p2[@k3]=list(prepareSat(qprim[@k3][1]),prepareSat(qprim[@k3][2])); } //////////////////////////////////////////////////////////////// // compute the recontractions // back in the original ring //////////////////////////////////////////////////////////////// setring BAS; @p=imap(Rloc,@p2); primary=imap(Rloc,qprim); @h=imap(Rloc,@h2); kill Rloc; for(@k3=1;@k3<=size(primary);@k3++) { primary[@k3]=list(sat(primary[@k3][1],@p[@k3][1])[1], sat(primary[@k3][2],@p[@k3][2])[1]); check=intersect(check,primary[@k3][1]); } @q=minSatMod(imap(BAS,@N),@h)[2]; result=result+primary; if (deg(@q)>0) { @N=std(@N+@q*@M); ann=std(ideal(ann+@q)); } } // end of else if ((@k1==1)&&(@k2dim(ann))) { break; } } } return(result+GTZopt(@N,check,ann)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; module N=x*gen(1)+ y*gen(2), x*gen(1)-x2*gen(2); list l=GTZopt(N); l; } ///////////////////////////////////////////////////////////////////////////// // dec1var(N[,check[, ann]]) // primary decompostion for a ring with one variable ///////////////////////////////////////////////////////////////////////////// proc dec1var (module @N, list #) "USAGE: dec1var (N); zero-dimensional module N[, module check] RETURN: list l the minimal primary decomposition of a submodule N of R^s if nvars(R)=1 NOTE: if the parameter check is given, only components not containing check are computed EXAMPLE: example zeroMod; shows an example " { ideal ann; module @M, check; int checked; (ann, check, @M, checked)=getData(@N, #); list fac = factorize(ann[1],2); if(size(fac[2])==1) { return(list(list(@N,ann))); } // comp of the primary modules, the primary ideals and the primes poly @h; module primod; list result; int @k; for (@k=1;@k<=size(fac[1]);@k++) { @h=ann[1]/(fac[1][@k]^fac[2][@k]); result =result+list(list(std(quotient(@N,@h)), std(ann,fac[1][@k]))); } return(result); } example { "EXAMPLE:"; echo = 2; ring r=0,z,dp; module N=z*gen(1),(z-1)*gen(2),(z+1)*gen(3); list l=dec1var(N); l; } ///////////////////////////////////////////////////////////////////////////// // zeroOpt(N[,check[, ann]]) // a faster version of zeroMod ///////////////////////////////////////////////////////////////////////////// proc zeroOpt (module @N, list #) "USAGE: zeroOpt (N[, check]); zero-dimensional module N[, module check] RETURN: list l the minimal primary decomposition of a zero-dimensional module N, computed by a generalized and optimized version of the algorithm of Gianni, Trager and Zacharias NOTE: if the parameter check is given, only components not containing check are computed EXAMPLE: example zeroMod; shows an example " { @N=interred(@N); attrib(@N,"isSB",1); //////////////////////////////////////////////////////////////// // the module check is needed to compute a minimal decomposition // components containing check are ignored //////////////////////////////////////////////////////////////// ideal ann; module @M, check; int checked; (ann, check, @M, checked)=getData(@N, #); if (checked) { return(list()); } //////////////////////////////////////////////////////////////// // the ordering is changed to lex //////////////////////////////////////////////////////////////// def BAS = basering; def @R=changeord(list(list("C",0:1),list("lp",1:nvars(basering)))); setring @R; module @N=std(imap(BAS,@N)); module @M=imap(BAS,@M); ideal ann=std(imap(BAS,ann)); module check=imap(BAS,check); //////////////////////////////////////////////////////////////// if(vdim(ann)==deg(ann[1])) // if ann ist prime { list fact=factorize(ann[1],2); int k;ideal id;list result; module hilf; for(k=1;k<=size(fact[1]);k++) { id=ann; hilf=std(@N+(fact[1][k]^fact[2][k])*@M); id[1]=fact[1][k]; if(size(NF(check,hilf,1))>0) { result=result+list(list(hilf,interred(id))); } } setring BAS; list result=imap(@R, result); kill @R; return(result); } if (homog(ann)) // if ann is homogeneous { // then radical(ann)=maxideal(1) if(size(NF(check,@N,1))>0) { setring BAS; kill @R; return (list(list(@N,maxideal(1)))); } else { setring BAS; kill @R; return(list()); } } //////////////////////////////////////////////////////////////// // the random coordnate change and its inverse // furthermore the module is simplified using // N=N/(a*x_i+b)+(a*x_i+b)*M, for a*x_i+b in ann //////////////////////////////////////////////////////////////// int nVar=nvars(@R); int @k, @k1; list result, rest; ideal primary, prim; module primmod; ideal fried; intvec optionsVec=option(get); option(redSB); ideal prepMap = randomLast(100); ideal prepInv=maxideal(1); for(@k=1;@k<=size(ann);@k++) { if(deg(lead(ann[@k]))==1) { fried[size(fried)+1]=ann[@k]; } } if(size(fried)==nVar) { return(list(list(@N, ann))); } if(size(fried)>0) { for(@k=1;@k<@k1;@k1++) { for(@k1=1;@k1<=size(fried);@k1++) { if(leadmonom(fried[@k1])==var(@k)) { prepMap[@k]=var(@k)+((1/leadcoef(fried[@k1]))*(var(@k)-fried[@k1])); prepMap[nVar]=subst(prepMap[nVar],var(@k),0); prepInv[@k]=fried[@k1]; } } } } map phi=@R,prepMap; prepInv[nVar]=2*var(nVar)-prepMap[nVar]; map invphi=@R,prepInv; ideal @j=std(phi(ann)); // factorization of the 1st elt. in Ann(@N) list fac = factorize(@j[1],2); //////////////////////////////////////////////////////////////// // Case: 1st element irreducible //////////////////////////////////////////////////////////////// if(size(fac[2])==1) { prim=primaryTest(@j,fac[1][1]); prim=invphi(prim); setring BAS; @N=std(@N); ideal prim =imap(@R,prim); kill @R; if(prim!=0) { return(list(list(@N,prim))); } else { return(zeroOpt(@N,check)); } } //////////////////////////////////////////////////////////////// // Computation of the - hopefully primary - modules // their annihilators and associated primes //////////////////////////////////////////////////////////////// poly @p, @h; for (@k=1;@k<=size(fac[1]);@k++) { @p=fac[1][@k]^fac[2][@k]; @h=@j[1]/@p; primmod=std(quotient(phi(@N),@h)); check=phi(check); if (size(NF(check,primmod,1))>0) { primary=std(@j+@p); // test if the modules were primary and in general position prim=primTest(primary,fac[1][@k]); if(size(prim)==0) { prim=primaryTest(primary,fac[1][@k]); } if (prim==0) { rest[size(rest)+1]=invphi(primmod); } else { result[size(result)+1]=list(std(invphi(primmod)),std(invphi(prim))); } } } //////////////////////////////////////////////////////////////// // the bad cases //////////////////////////////////////////////////////////////// for (@k=1; @k<=size(rest);@k++) { result = result+zeroOpt(rest[@k],check); } option (set,optionsVec); if(size(result)==0) { setring BAS; kill @R; return(list()); } setring BAS; list result=imap(@R, result); kill @R; return(result); } example { "EXAMPLE:"; echo = 2; ring r=0,z,dp; module N=z*gen(1),(z-1)*gen(2),(z+1)*gen(3); list l=zeroOpt(N); l; } ///////////////////////////////////////////////////////////////////////////// // clrSBmod(N) // Generalization of clearSB from primdec.lib ///////////////////////////////////////////////////////////////////////////// static proc clrSBmod (module @N) "USAGE: clrSBmod(N); N module which is SB ordered by monomial ordering RETURN: module = minimal SB EXAMPLE: example clrSBmod; shows an example " { int @k,@j; list Nsizes; for (@k=1;@k<=size(@N);@k++) { Nsizes[@k]=size(@N[@k]); } module leadVec; int szN=size(@N); @j=0; while(@j0) { leadVec=lead(@N[@j]); attrib(leadVec,"isSB",1); for(@k=@j+1;@k<=szN;@k++) { if(size(NF(lead(@N[@k]),leadVec,1))==0) { if((leadexp(leadVec[1])!=leadexp(@N[@k]))||(Nsizes[@j]<=Nsizes[@k])) { @N[@k]=0; } else { @N[@j]=0; break; } } } } } return(simplify(@N,2)); } example { "EXAMPLE:"; echo = 2; ring r = (0,a,b),(x,y,z),dp; module N1=ax2+y,a2x+y,bx; module N2=clrSBmod(N1); N2; } ///////////////////////////////////////////////////////////////////////////// // minSatMod(N, id) // Generalization of minsat from primdec.lib ///////////////////////////////////////////////////////////////////////////// static proc minSatMod(module Nnew, ideal @h) "USAGE: minSatMod(N, I); module N, ideal I RETURN: list with 2 elements: [1]=sat(N,product(I))[1], [2]=p, the polynomial of minimal degree s.th. [1]=quotient(N,p) EXAMPLE: example minSatMod; shows an example " { int @i,@k; poly @f=1; module Nold; ideal fac; list quotM,@l; for(@i=1;@i<=ncols(@h);@i++) { if(deg(@h[@i])>0) { fac=fac+factorize(@h[@i],1); } } fac=simplify(fac,4); if(size(fac)==0) { @l=Nnew,1; return(@l); } fac=sort(fac)[1]; for(@i=1;@i<=size(fac);@i++) { @f=@f*fac[@i]; } quotM[1]=Nnew; quotM[2]=fac; quotM[3]=@f; @f=1; while(specialModulesEqual(Nold,quotM[1])==0) { if(@k>0) { @f=@f*quotM[3]; } Nold=quotM[1]; quotM=quotMinMod(quotM); @k++; } @l=quotM[1],@f; return(@l); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; module N=xy*gen(1); ideal h=yz,z2; list l=minSatMod(N,h); l; } ///////////////////////////////////////////////////////////////////////////// // quotMinMod(N, fac, f) // Generalization of quotMin from primdec.lib ///////////////////////////////////////////////////////////////////////////// proc quotMinMod(list tsil) { int @i,@j,action; module verg; list @l; poly @g; intvec optionsVec; module laedi=tsil[1]; ideal fac=tsil[2]; poly @f=tsil[3]; optionsVec=option(get); option(returnSB); module star=quotient(laedi,@f); option(set,optionsVec); if(specialModulesEqual(star,laedi)) { @l=star,fac,@f; return(@l); } action=1; while(action==1) { if(size(fac)==1) { action=0; break; } for(@i=1;@i<=size(fac);@i++) { @g=1; verg=laedi; for(@j=1;@j<=size(fac);@j++) { if(@i!=@j) { @g=@g*fac[@j]; } } optionsVec=option(get); option(returnSB); verg=quotient(laedi,@g); option(set,optionsVec); if(specialModulesEqual(verg,star)==1) { @f=@g; fac[@i]=0; fac=simplify(fac,2); break; } if(@i==size(fac)) { action=0; } } } @l=star,fac,@f; return(@l); } ///////////////////////////////////////////////////////////////////////////// // specialModulesEqual(N1,N2) // Generalization of specialIdealsEqual from primdec.lib ///////////////////////////////////////////////////////////////////////////// static proc specialModulesEqual( module k1, module k2) "USAGE: specialModulesEqual(N1, N2) N1, N2 standard bases of modules, s.th. N1 is contained in N2 or vice versa RETURN: int i if (N1==N2) then i=1 else i=0 EXAMPLE: example specialModulesEqual; shows an example " { int @j; if(size(k1)==size(k2)) { for(@j=1;@j<=size(k1);@j++) { if(leadexp(k1[@j])!=leadexp(k2[@j])) { return(0); } } return(1); } return(0); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; module N1=x*freemodule(2); module N2=xy*freemodule(2); int i=specialModulesEqual(N1,N2); i; N2=N1; i=specialModulesEqual(N1,N2); i; } ///////////////////////////////////////////////////////////////////////////// // sat2mod(N,i) // Generalization of sat2 from primdec.lib ///////////////////////////////////////////////////////////////////////////// proc sat2mod (module id, ideal h1) "USAGE: sat2mod(id,j); id ideal, j polynomial RETURN: saturation of id with respect to j (= union_(k=1...) of id:j^k) NOTE: result is a std basis in the basering " { int @k,@i; def @P= basering; if(ordstr(basering)[1,2]!="dp") { execute("ring @Phelp=("+charstr(@P)+"),("+varstr(@P)+"),(C,dp);"); module inew=std(imap(@P,id)); ideal @h=imap(@P,h1); } else { ideal @h=h1; module inew=std(id); } ideal fac; for(@i=1;@i<=ncols(@h);@i++) { if(deg(@h[@i])>0) { fac=fac+factorize(@h[@i],1); } } fac=simplify(fac,4); poly @f=1; if(deg(fac[1])>0) { module iold; for(@i=1;@i<=size(fac);@i++) { @f=@f*fac[@i]; } intvec optionsVec=option(get) option(returnSB); while(specialModulesEqual(iold,inew)==0 ) { iold=inew; if(deg(iold[size(iold)])!=1) { inew=quotient(iold,@f); } else { inew=iold; } @k++; } option(set,optionsVec); @k--; } if(ordstr(@P)[1,2]!="dp") { setring @P; module inew=std(imap(@Phelp,inew)); poly @f=imap(@Phelp,@f); } list L =inew,@f^@k; return (L); } ///////////////////////////////////////////////////////////////////////////// // stdModulesEqual(N1,N2) // Generalization of stdIdealsEqual from primdec.lib ///////////////////////////////////////////////////////////////////////////// static proc stdModulesEqual(module k1, module k2) "USAGE: stdModulesEqual(N1, N2) N1, N2 standard bases of modules, RETURN: int i if (N1==N2) then i=1 else i=0 EXAMPLE: example stdModulesEqual; shows an example " { int @j; if(size(k1)==size(k2)) { for(@j=1;@j<=size(k1);@j++) { if(leadexp(k1[@j])!=leadexp(k2[@j])) { return(0); } } attrib(k2,"isSB",1); if(size(reduce(k1,k2,1))==0) { return(1); } } return(0); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; module N1=x*freemodule(2); module N2=xy*freemodule(2); int i=stdModulesEqual(N1,N2); i; N2=N1; i=stdModulesEqual(N1,N2); i; } ///////////////////////////////////////////////////////////////////////////// // ModulesEqual(N1,N2) // Generalization of IdealsEqual from primdec.lib ///////////////////////////////////////////////////////////////////////////// static proc modulesEqual( module @k, module @j) "USAGE: modulesEqual(N1, N2) N1, N2 modules, RETURN: int i if (N1==N2) then i=1 else i=0 EXAMPLE: example modulesEqual; shows an example " { return(stdModulesEqual(std(@k),std(@j))); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; module N1=x*freemodule(2); module N2=xy*freemodule(2); int i=stdModulesEqual(N1,N2); i; N2=N1; i=modulesEqual(N1,N2); i; } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; module N1=x*freemodule(2); module N2=xy*freemodule(2); int i=modulesEqual(N1,N2); i; N2=N1; i=modulesEqual(N1,N2); i; } static proc getData (module @N, list oldData, list #) "USAGE: getData(N, l[, noCheck]); module N, list l[, int noCheck] RETURN: (ann, check, M, checked) ideal ann, module check, M, int checked if l[1] is contained in N [and noCheck is not given] then checked=1, ann=ideal(0), check=0, M=0; else checked=0, M=freemodule(nrows(N)); check=l[1] (resp. check=M if l is an empty list) and if size(l)>1 then ann=l[2] else ann is the annihilator of M/N. NOTE: ann is a std basis in the basering EXAMPLE: example getData; shows an example " { if (size(oldData)>0) { if ((size(#)==0)&&(size(NF(oldData[1],@N,1))==0)) { return(ideal(0), 0 , 0, 1); } module @M=freemodule(nrows(@N)); if (size(oldData)>1) { ideal ann=oldData[2]; attrib(ann,"isSB",1); } else { ideal ann=annil(@N); } } else { module @M=freemodule(nrows(@N)); oldData[1]=@M; ideal ann=annil(@N); } return(ann, oldData[1], @M, 0); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),lp; module N=x*gen(1),y*gen(2); N=std(N); ideal ann; module check, M; int checked; list l; (ann, check, M, checked)=getData(N,l); ann; check; M; checked; l=list(check,ann); (ann, check, M, checked)=getData(N,l); ann; check; M; checked; l=list(N); (ann, check, M, checked)=getData(N,l); ann; check; M; checked; } singular-4.0.3+ds/Singular/LIB/mregular.lib000066400000000000000000001620251266270727000204630ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version mregular.lib 4.0.0.0 Jun_2013 "; // $Id: 65c9ff28baa31013620d93b4f3033bcb6d5632ad $ category="Commutative Algebra"; info=" LIBRARY: mregular.lib Castelnuovo-Mumford regularity of homogeneous ideals AUTHORS: I.Bermejo, ibermejo@ull.es @* Ph.Gimenez, pgimenez@agt.uva.es @* G.-M.Greuel, greuel@mathematik.uni-kl.de OVERVIEW: A library for computing the Castelnuovo-Mumford regularity of a homogeneous ideal that DOES NOT require the computation of a minimal graded free resolution of the ideal. It also determines depth(basering/ideal) and satiety(ideal). The procedures are based on 3 papers by Isabel Bermejo and Philippe Gimenez: 'On Castelnuovo-Mumford regularity of projective curves' Proc.Amer.Math.Soc. 128(5) (2000), 'Computing the Castelnuovo-Mumford regularity of some subschemes of Pn using quotients of monomial ideals', Proceedings of MEGA-2000, J. Pure Appl. Algebra 164 (2001), and 'Saturation and Castelnuovo-Mumford regularity', Preprint (2004). PROCEDURES: regIdeal(id,[,e]); regularity of homogeneous ideal id depthIdeal(id,[,e]); depth of S/id with S=basering, id homogeneous ideal satiety(id,[,e]); saturation index of homogeneous ideal id regMonCurve(li); regularity of projective monomial curve defined by li NoetherPosition(id); Noether normalization of ideal id is_NP(id); checks whether variables are in Noether position is_nested(id); checks whether monomial ideal id is of nested type "; LIB "general.lib"; LIB "algebra.lib"; LIB "sing.lib"; LIB "poly.lib"; ////////////////////////////////////////////////////////////////////////////// // proc regIdeal (ideal i, list #) " USAGE: regIdeal (i[,e]); i ideal, e integer RETURN: an integer, the Castelnuovo-Mumford regularity of i. (returns -1 if i is not homogeneous) ASSUME: i is a homogeneous ideal of the basering S=K[x(0)..x(n)]. e=0: (default) If K is an infinite field, makes random changes of coordinates. If K is a finite field, works over a transcendental extension. e=1: Makes random changes of coordinates even when K is finite. It works if it terminates, but may result in an infinite loop. After 30 loops, a warning message is displayed and -1 is returned. NOTE: If printlevel > 0 (default = 0), additional info is displayed: dim(S/i), depth(S/i) and end(H^(depth(S/i))(S/i)) are computed, and an upper bound for the a-invariant of S/i is given. The algorithm also determines whether the regularity is attained or not at the last step of a minimal graded free resolution of i, and if the answer is positive, the regularity of the Hilbert function of S/i is given. EXAMPLE: example regIdeal; shows some examples " { //--------------------------- initialisation --------------------------------- int e,ii,jj,H,h,d,time,lastv,sat,firstind; int lastind,ch,nesttest,NPtest,nl,N,acc; intmat ran; def r0 = basering; int n = nvars(r0)-1; if ( size(#) > 0 ) { e = #[1]; } string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,J,K,chcoord,m; poly P; map phi; i = fetch(r0,i); time=rtimer; sbi=std(i); ch=char(r1); //----- Check ideal homogeneous if ( homog(sbi) == 0 ) { "// WARNING from proc regIdeal from lib mregular.lib: // The ideal is not homogeneous!"; return (-1); } I=simplify(lead(sbi),1); attrib(I,"isSB",1); d=dim(I); //----- If the ideal i is not proper: if ( d == -1 ) { dbprint(printlevel-voice+2, "// The ideal i is (1)! // Its Castelnuovo-Mumford regularity is:"); return (0); } //----- If the ideal i is 0: if ( size(I) == 0 ) { dbprint(printlevel-voice+2, "// The ideal i is (0)! // Its Castelnuovo-Mumford regularity is:"); return (0); } //----- When the ideal i is 0-dimensional: if ( d == 0 ) { H=maxdeg1(minbase(quotient(I,maxideal(1))))+1; time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i : 0"); dbprint(printlevel-voice+2, "// Time for computing regularity: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// The Castelnuovo-Mumford regularity of i coincides with its satiety, and // with the regularity of the Hilbert function of S/i. Its value is:"); return (H); } //----- Determine the situation: NT, or NP, or nothing. //----- Choose the method depending on the situation, on the //----- characteristic of the ground field, and on the option argument //----- in order to get the mon. ideal of nested type associated to i if ( e == 1 ) { ch=0; } NPtest=is_NP(I); if ( NPtest == 1 ) { nesttest=is_nested(I); } if ( ch != 0 ) { if ( NPtest == 0 ) { N=d*n-d*(d-1)/2; s = "ring rtr = (ch,t(1..N)),x(0..n),dp;"; execute(s); ideal chcoord,m,i,I; poly P; map phi; i=imap(r1,i); chcoord=select1(maxideal(1),1..(n-d+1)); acc=0; for ( ii = 1; ii<=d; ii++ ) { matrix trex[1][n-d+ii+1]=t((1+acc)..(n-d+ii+acc)),1; m=select1(maxideal(1),1..(n-d+1+ii)); for ( jj = 1; jj<=n-d+ii+1; jj++ ) { P=P+trex[1,jj]*m[jj]; } chcoord[n-d+1+ii]=P; P=0; acc=acc+n-d+ii; kill trex; } phi=rtr,chcoord; I=simplify(lead(std(phi(i))),1); setring r1; I=imap(rtr,I); attrib(I,"isSB",1); } else { if ( nesttest == 0 ) { N=d*(d-1)/2; s = "ring rtr = (ch,t(1..N)),x(0..n),dp;"; execute(s); ideal chcoord,m,i,I; poly P; map phi; i=imap(r1,i); chcoord=select1(maxideal(1),1..(n-d+2)); acc=0; for ( ii = 1; ii<=d-1; ii++ ) { matrix trex[1][ii+1]=t((1+acc)..(ii+acc)),1; m=select1(maxideal(1),(n-d+2)..(n-d+2+ii)); for ( jj = 1; jj<=ii+1; jj++ ) { P=P+trex[1,jj]*m[jj]; } chcoord[n-d+2+ii]=P; P=0; acc=acc+ii; kill trex; } phi=rtr,chcoord; I=simplify(lead(std(phi(i))),1); setring r1; I=imap(rtr,I); attrib(I,"isSB",1); } } } else { if ( NPtest == 0 ) { while ( nl < 30 ) { chcoord=select1(maxideal(1),1..(n-d+1)); nl=nl+1; for ( ii = 1; ii<=d; ii++ ) { ran=random(100,1,n-d+ii); ran=intmat(ran,1,n-d+ii+1); ran[1,n-d+ii+1]=1; m=select1(maxideal(1),1..(n-d+1+ii)); for ( jj = 1; jj<=n-d+ii+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[n-d+1+ii]=P; P=0; } phi=r1,chcoord; dbprint(printlevel-voice+2,"// (1 random change of coord.)"); I=simplify(lead(std(phi(i))),1); attrib(I,"isSB",1); NPtest=is_NP(I); if ( NPtest == 1 ) { break; } } if ( NPtest == 0 ) { "// WARNING from proc regIdeal from lib mregular.lib: // The procedure has entered in 30 loops and could not put the variables // in Noether position: in your example the method using random changes // of coordinates may enter an infinite loop when the field is finite. // Try removing this optional argument."; return (-1); } i=phi(i); nesttest=is_nested(I); } if ( nesttest == 0 ) { while ( nl < 30 ) { chcoord=select1(maxideal(1),1..(n-d+2)); nl=nl+1; for ( ii = 1; ii<=d-1; ii++ ) { ran=random(100,1,ii); ran=intmat(ran,1,ii+1); ran[1,ii+1]=1; m=select1(maxideal(1),(n-d+2)..(n-d+2+ii)); for ( jj = 1; jj<=ii+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[n-d+2+ii]=P; P=0; } phi=r1,chcoord; dbprint(printlevel-voice+2,"// (1 random change of coord.)"); I=simplify(lead(std(phi(i))),1); attrib(I,"isSB",1); nesttest=is_nested(I); if ( nesttest == 1 ) { break; } } if ( nesttest == 0 ) { "// WARNING from proc regIdeal from lib mregular.lib: // The procedure has entered in 30 loops and could not find a monomial // ideal of nested type with the same regularity as your ideal: in your // example the method using random changes of coordinates may enter an // infinite loop when the field is finite. // Try removing this optional argument."; return (-1); } } } // // At this stage, we have obtained a monomial ideal I of nested type // such that reg(i)=reg(I). We now compute reg(I). // //----- When S/i is Cohen-Macaulay: for ( ii = n-d+2; ii <= n+1; ii++ ) { K=K+select(I,ii); } if ( size(K) == 0 ) { s="ring nr = ",charstr(r0),",x(0..n-d),dp;"; execute(s); ideal I; I = imap(r1,I); H=maxdeg1(minbase(quotient(I,maxideal(1))))+1; time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// S/i is Cohen-Macaulay"); dbprint(printlevel-voice+2, "// Dimension of S/i ( = depth(S/i) ): "+string(d)); dbprint(printlevel-voice+2, "// Regularity attained at the last step of m.g.f.r. of i: YES"); dbprint(printlevel-voice+2, "// Regularity of the Hilbert function of S/i: " + string(H-d)); dbprint(printlevel-voice+2, "// Time for computing regularity: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// The Castelnuovo-Mumford regularity of i is:"); return(H); } //----- When d=1: if ( d == 1 ) { H=maxdeg1(simplify(reduce(quotient(I,maxideal(1)),I),2))+1; sat=H; J=subst(I,x(n),1); s = "ring nr = ",charstr(r0),",x(0..n-1),dp;"; execute(s); ideal J=imap(r1,J); attrib(J,"isSB",1); h=maxdeg1(minbase(quotient(J,maxideal(1))))+1; time=rtimer-time; if ( h > H ) { H=h; } // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: 1"); dbprint(printlevel-voice+2, "// Depth of S/i: 0"); dbprint(printlevel-voice+2, "// Satiety of i: "+string(sat)); dbprint(printlevel-voice+2, "// Upper bound for the a-invariant of S/i: end(H^1(S/i)) <= "+ string(h-2)); if ( H == sat ) { dbprint(printlevel-voice+2, "// Regularity attained at the last step of m.g.f.r. of i: YES"); dbprint(printlevel-voice+2, "// Regularity of the Hilbert function of S/i: "+string(H)); } else { dbprint(printlevel-voice+2, "// Regularity attained at the last step of m.g.f.r. of i: NO"); } dbprint(printlevel-voice+2, "// Time for computing regularity: "+ string(time) + " sec."); dbprint(printlevel-voice+2, "// The Castelnuovo-Mumford regularity of i is:"); return(H); } //----- Now d>1 and S/i is not Cohen-Macaulay: // //----- First, determine the last variable really occuring lastv=n-d; h=n; while ( lastv == n-d and h > n-d ) { K=select(I,h+1); if ( size(K) == 0 ) { h=h-1; } else { lastv=h; } } //----- and compute Castelnuovo-Mumford regularity: s = "ring nr = ",charstr(r0),",x(0..lastv),dp;"; execute(s); ideal I,K,KK,LL; I=imap(r1,I); attrib(I,"isSB",1); K=simplify(reduce(quotient(I,maxideal(1)),I),2); H=maxdeg1(K)+1; firstind=H; KK=minbase(subst(I,x(lastv),1)); for ( ii = n-lastv; ii<=d-2; ii++ ) { LL=minbase(subst(I,x(n-ii-1),1)); attrib(LL,"isSB",1); s = "ring mr = ",charstr(r0),",x(0..n-ii-1),dp;"; execute(s); ideal K,KK; KK=imap(nr,KK); attrib(KK,"isSB",1); K=simplify(reduce(quotient(KK,maxideal(1)),KK),2); h=maxdeg1(K)+1; if ( h > H ) { H=h; } setring nr; kill mr; KK=LL; } // We must determine one more sat. index: s = "ring mr = ",charstr(r0),",x(0..n-d),dp;"; execute(s); ideal KK,K; KK=imap(nr,KK); attrib(KK,"isSB",1); K=simplify(reduce(quotient(KK,maxideal(1)),KK),2); h=maxdeg1(K)+1; lastind=h; if ( h > H ) { H=h; } setring nr; kill mr; time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: "+string(d)); dbprint(printlevel-voice+2, "// Depth of S/i: "+string(n-lastv)); dbprint(printlevel-voice+2, "// end(H^"+string(n-lastv)+"(S/i)) = " +string(firstind-n+lastv-1)); dbprint(printlevel-voice+2, "// Upper bound for the a-invariant of S/i: end(H^" +string(d)+"(S/i)) <= "+string(lastind-d-1)); if ( H == firstind ) { dbprint(printlevel-voice+2, "// Regularity attained at the last step of m.g.f.r. of i: YES"); dbprint(printlevel-voice+2, "// Regularity of the Hilbert function of S/i: " +string(H-n+lastv)); } else { dbprint(printlevel-voice+2, "// Regularity attained at the last step of m.g.f.r. of i: NO"); } dbprint(printlevel-voice+2, "// Time for computing regularity: "+ string(time) + " sec."); dbprint(printlevel-voice+2, "// The Castelnuovo-Mumford regularity of i is:"); return(H); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,t,w),dp; ideal i=y2t,x2y-x2z+yt2,x2y2,xyztw,x3z2,y5+xz3w-x2zw2,x7-yt2w4; regIdeal(i); regIdeal(lead(std(i))); // Additional information is displayed if you change printlevel (=1); } //////////////////////////////////////////////////////////////////////////////// /* Out-commented examples: // ring s=0,x(0..5),dp; ideal i=x(2)^2-x(4)*x(5),x(1)*x(2)-x(0)*x(5),x(0)*x(2)-x(1)*x(4), x(1)^2-x(3)*x(5),x(0)*x(1)-x(2)*x(3),x(0)^2-x(3)*x(4); regIdeal(i); // Our procedure works when a min. graded free resol. can // not be computed. In this easy example, regularity can also // be obtained using a m.g.f.r.: nrows(betti(mres(i,0))); ring r1=0,(x,y,z,t),dp; // Ex.2.5 in [Bermejo-Gimenez], Proc.Amer.Math.Soc. 128(5): ideal i = x17y14-y31, x20y13, x60-y36z24-x20z20t20; regIdeal(i); // Ex.2.9 in [Bermejo-Gimenez], Proc.Amer.Math.Soc. 128(5): int k=43; ideal j=x17y14-y31,x20y13,x60-y36z24-x20z20t20,y41*z^k-y40*z^(k+1); regIdeal(j); k=14; j=x17y14-y31,x20y13,x60-y36z24-x20z20t20,y41*z^k-y40*z^(k+1); regIdeal(j); k=22; j=x17y14-y31,x20y13,x60-y36z24-x20z20t20,y41*z^k-y40*z^(k+1); regIdeal(j); k=315; j=x17y14-y31,x20y13,x60-y36z24-x20z20t20,y41*z^k-y40*z^(k+1); regIdeal(j); // Example in Rk.2.10 in [Bermejo-Gimenez], ProcAMS 128(5): ideal h=x2-3xy+5xt,xy-3y2+5yt,xz-3yz,2xt-yt,y2-yz-2yt; regIdeal(h); // The initial ideal is not saturated regIdeal(lead(std(h))); // More examples: i=y4-t3z, x3t-y2z2, x3y2-t2z3, x6-tz5; regIdeal(i); // regIdeal(maxideal(4)); // ring r2=0,(x,y,z,t,w),dp; ideal i = xy-zw,x3-yw2,x2z-y2w,y3-xz2,-y2z3+xw4+tw4+w5,-yz4+x2w3+xtw3+xw4, -z5+x2tw2+x2w3+yw4; regIdeal(i); // ring r3=0,(x,y,z,t,w,u),dp; ideal i=imap(r2,i); regIdeal(i); // Next example is the defining ideal of the 2nd. Veronesean of P3, a variety // in P8 which is arithmetically Cohen-Macaulay: ring r4=0,(a,b,c,d,x(0..9)),dp; ideal i= x(0)-ab,x(1)-ac,x(2)-ad,x(3)-bc,x(4)-bd,x(5)-cd, x(6)-a2,x(7)-b2,x(8)-c2,x(9)-d2; ideal ei=eliminate(i,abcd); ring r5=0,x(0..9),dp; ideal i=imap(r4,ei); regIdeal(i); // Here is an example where the computation of a m.g.f.r. of I costs: ring r8=0,(x,y,z,t,u,a,b),dp; ideal i=u-b40,t-a40,x-a23b17,y-a22b18+ab39,z-a25b15; ideal ei=eliminate(i,ab); // It takes a few seconds to compute the ideal ring r9=0,(x,y,z,t,u),dp; ideal i=imap(r8,ei); regIdeal(i); // This is very fast. // Now you can use mres(i,0) to compute a m.g.f.r. of the ideal! // // The computation of the m.g.f.r. of the following example did not succeed // using the command mres: ring r10=0,(x(0..8),s,t),dp; ideal i=x(0)-st24,x(1)-s2t23,x(2)-s3t22,x(3)-s9t16,x(4)-s11t14,x(5)-s18t7, x(6)-s24t,x(7)-t25,x(8)-s25; ideal ei=eliminate(i,st); ring r11=0,x(0..8),dp; ideal i=imap(r10,ei); regIdeal(i); // More examples where not even sres works: // Be careful: elimination takes some time here, but it succeeds! ring r12=0,(s,t,u,x(0..14)),dp; ideal i=x(0)-st6u8,x(1)-s5t3u7,x(2)-t11u4,x(3)-s9t4u2,x(4)-s2t7u6,x(5)-s7t7u, x(6)-s10t5,x(7)-s4t6u5,x(8)-s13tu,x(9)-s14u,x(10)-st2u12,x(11)-s3t9u3, x(12)-s15,x(13)-t15,x(14)-u15; ideal ei=eliminate(i,stu); size(ei); ring r13=0,x(0..14),dp; ideal i=imap(r12,ei); size(i); regIdeal(i); */ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc depthIdeal (ideal i, list #) " USAGE: depthIdeal (i[,e]); i ideal, e integer RETURN: an integer, the depth of S/i where S=K[x(0)..x(n)] is the basering. (returns -1 if i is not homogeneous or if i=(1)) ASSUME: i is a proper homogeneous ideal. e=0: (default) If K is an infinite field, makes random changes of coordinates. If K is a finite field, works over a transcendental extension. e=1: Makes random changes of coordinates even when K is finite. It works if it terminates, but may result in an infinite loop. After 30 loops, a warning message is displayed and -1 is returned. NOTE: If printlevel > 0 (default = 0), dim(S/i) is also displayed. EXAMPLE: example depthIdeal; shows some examples " { //--------------------------- initialisation --------------------------------- int e,ii,jj,h,d,time,lastv,ch,nesttest,NPtest,nl,N,acc; intmat ran; def r0 = basering; int n = nvars(r0)-1; if ( size(#) > 0 ) { e = #[1]; } string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,J,K,chcoord,m; poly P; map phi; i = fetch(r0,i); time=rtimer; sbi=std(i); ch=char(r1); //----- Check ideal homogeneous if ( homog(sbi) == 0 ) { "// WARNING from proc depthIdeal from lib mregular.lib: // The ideal is not homogeneous!"; return (-1); } I=simplify(lead(sbi),1); attrib(I,"isSB",1); d=dim(I); //----- If the ideal i is not proper: if ( d == -1 ) { "// WARNING from proc depthIdeal from lib mregular.lib: // The ideal i is (1)!"; return (-1); } //----- If the ideal i is 0: if ( size(I) == 0 ) { dbprint(printlevel-voice+2, "// The ideal i is (0)! // The depth of S/i is:"); return (d); } //----- When the ideal i is 0-dimensional: if ( d == 0 ) { time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i : 0 (S/i is Cohen-Macaulay)"); dbprint(printlevel-voice+2, "// Time for computing the depth: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// The depth of S/i is:"); return (0); } //----- Determine the situation: NT, or NP, or nothing. //----- Choose the method depending on the situation, on the //----- characteristic of the ground field, and on the option argument //----- in order to get the mon. ideal of nested type associated to i if ( e == 1 ) { ch=0; } NPtest=is_NP(I); if ( NPtest == 1 ) { nesttest=is_nested(I); } if ( ch != 0 ) { if ( NPtest == 0 ) { N=d*n-d*(d-1)/2; s = "ring rtr = (ch,t(1..N)),x(0..n),dp;"; execute(s); ideal chcoord,m,i,I; poly P; map phi; i=imap(r1,i); chcoord=select1(maxideal(1),1..(n-d+1)); acc=0; for ( ii = 1; ii<=d; ii++ ) { matrix trex[1][n-d+ii+1]=t((1+acc)..(n-d+ii+acc)),1; m=select1(maxideal(1),1..(n-d+1+ii)); for ( jj = 1; jj<=n-d+ii+1; jj++ ) { P=P+trex[1,jj]*m[jj]; } chcoord[n-d+1+ii]=P; P=0; acc=acc+n-d+ii; kill trex; } phi=rtr,chcoord; I=simplify(lead(std(phi(i))),1); setring r1; I=imap(rtr,I); attrib(I,"isSB",1); } else { if ( nesttest == 0 ) { N=d*(d-1)/2; s = "ring rtr = (ch,t(1..N)),x(0..n),dp;"; execute(s); ideal chcoord,m,i,I; poly P; map phi; i=imap(r1,i); chcoord=select1(maxideal(1),1..(n-d+2)); acc=0; for ( ii = 1; ii<=d-1; ii++ ) { matrix trex[1][ii+1]=t((1+acc)..(ii+acc)),1; m=select1(maxideal(1),(n-d+2)..(n-d+2+ii)); for ( jj = 1; jj<=ii+1; jj++ ) { P=P+trex[1,jj]*m[jj]; } chcoord[n-d+2+ii]=P; P=0; acc=acc+ii; kill trex; } phi=rtr,chcoord; I=simplify(lead(std(phi(i))),1); setring r1; I=imap(rtr,I); attrib(I,"isSB",1); } } } else { if ( NPtest == 0 ) { while ( nl < 30 ) { chcoord=select1(maxideal(1),1..(n-d+1)); nl=nl+1; for ( ii = 1; ii<=d; ii++ ) { ran=random(100,1,n-d+ii); ran=intmat(ran,1,n-d+ii+1); ran[1,n-d+ii+1]=1; m=select1(maxideal(1),1..(n-d+1+ii)); for ( jj = 1; jj<=n-d+ii+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[n-d+1+ii]=P; P=0; } phi=r1,chcoord; dbprint(printlevel-voice+2,"// (1 random change of coord.)"); I=simplify(lead(std(phi(i))),1); attrib(I,"isSB",1); NPtest=is_NP(I); if ( NPtest == 1 ) { break; } } if ( NPtest == 0 ) { "// WARNING from proc depthIdeal from lib mregular.lib: // The procedure has entered in 30 loops and could not put the variables // in Noether position: in your example the method using random changes // of coordinates may enter an infinite loop when the field is finite. // Try removing this optional argument."; return (-1); } i=phi(i); nesttest=is_nested(I); } if ( nesttest == 0 ) { while ( nl < 30 ) { chcoord=select1(maxideal(1),1..(n-d+2)); nl=nl+1; for ( ii = 1; ii<=d-1; ii++ ) { ran=random(100,1,ii); ran=intmat(ran,1,ii+1); ran[1,ii+1]=1; m=select1(maxideal(1),(n-d+2)..(n-d+2+ii)); for ( jj = 1; jj<=ii+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[n-d+2+ii]=P; P=0; } phi=r1,chcoord; dbprint(printlevel-voice+2,"// (1 random change of coord.)"); I=simplify(lead(std(phi(i))),1); attrib(I,"isSB",1); nesttest=is_nested(I); if ( nesttest == 1 ) { break; } } if ( nesttest == 0 ) { "// WARNING from proc depthIdeal from lib mregular.lib: // The procedure has entered in 30 loops and could not find a monomial // ideal of nested type with the same depth as your ideal: in your // example the method using random changes of coordinates may enter an // infinite loop when the field is finite. // Try removing this optional argument."; return (-1); } } } // // At this stage, we have obtained a monomial ideal I of nested type // such that depth(S/i)=depth(S/I). We now compute depth(I). // //----- When S/i is Cohen-Macaulay: for ( ii = n-d+2; ii <= n+1; ii++ ) { K=K+select(I,ii); } if ( size(K) == 0 ) { time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: "+string(d)+" (S/i is Cohen-Macaulay)"); dbprint(printlevel-voice+2, "// Time for computing depth: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// The depth of S/i is:"); return(d); } //----- When d=1 (and S/i is not Cohen-Macaulay) ==> depth =0: if ( d == 1 ) { time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: 1"); dbprint(printlevel-voice+2, "// Time for computing depth: "+ string(time) + " sec."); dbprint(printlevel-voice+2, "// The depth of S/i is:"); return(0); } //----- Now d>1 and S/i is not Cohen-Macaulay: // //----- First, determine the last variable really occuring lastv=n-d; h=n; while ( lastv == n-d and h > n-d ) { K=select(I,h+1); if ( size(K) == 0 ) { h=h-1; } else { lastv=h; } } //----- and compute the depth: time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: "+string(d)); dbprint(printlevel-voice+2, "// Time for computing depth: "+ string(time) + " sec."); dbprint(printlevel-voice+2, "// The depth of S/i is:"); return(n-lastv); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,t,w),dp; ideal i=y2t,x2y-x2z+yt2,x2y2,xyztw,x3z2,y5+xz3w-x2zw2,x7-yt2w4; depthIdeal(i); depthIdeal(lead(std(i))); // Additional information is displayed if you change printlevel (=1); } //////////////////////////////////////////////////////////////////////////////// /* Out-commented examples: ring s=0,x(0..5),dp; ideal i=x(2)^2-x(4)*x(5),x(1)*x(2)-x(0)*x(5),x(0)*x(2)-x(1)*x(4), x(1)^2-x(3)*x(5),x(0)*x(1)-x(2)*x(3),x(0)^2-x(3)*x(4); depthIdeal(i); // Our procedure works when a min. graded free resol. can // not be computed. In this easy example, depth can also // be obtained using a m.g.f.r. (Auslander-Buchsbaum formula): nvars(s)-ncols(betti(mres(i,0)))+1; ring r1=0,(x,y,z,t),dp; // Ex.2.5 in [Bermejo-Gimenez], Proc.Amer.Math.Soc. 128(5): ideal i = x17y14-y31, x20y13, x60-y36z24-x20z20t20; depthIdeal(i); // Ex.2.9 in [Bermejo-Gimenez], Proc.Amer.Math.Soc. 128(5): int k=43; ideal j=x17y14-y31,x20y13,x60-y36z24-x20z20t20,y41*z^k-y40*z^(k+1); depthIdeal(j); // Example in Rk.2.10 in [Bermejo-Gimenez], ProcAMS 128(5): ideal h=x2-3xy+5xt,xy-3y2+5yt,xz-3yz,2xt-yt,y2-yz-2yt; depthIdeal(h); // The initial ideal is not saturated depthIdeal(lead(std(h))); // More examples: i=y4-t3z, x3t-y2z2, x3y2-t2z3, x6-tz5; depthIdeal(i); // depthIdeal(maxideal(4)); // ring r2=0,(x,y,z,t,w),dp; ideal i = xy-zw,x3-yw2,x2z-y2w,y3-xz2,-y2z3+xw4+tw4+w5,-yz4+x2w3+xtw3+xw4, -z5+x2tw2+x2w3+yw4; depthIdeal(i); // ring r3=0,(x,y,z,t,w,u),dp; ideal i=imap(r2,i); depthIdeal(i); // Next example is the defining ideal of the 2nd. Veronesean of P3, a variety // in P8 which is arithmetically Cohen-Macaulay: ring r4=0,(a,b,c,d,x(0..9)),dp; ideal i= x(0)-ab,x(1)-ac,x(2)-ad,x(3)-bc,x(4)-bd,x(5)-cd, x(6)-a2,x(7)-b2,x(8)-c2,x(9)-d2; ideal ei=eliminate(i,abcd); ring r5=0,x(0..9),dp; ideal i=imap(r4,ei); depthIdeal(i); // Here is an example where the computation of a m.g.f.r. of I costs: ring r8=0,(x,y,z,t,u,a,b),dp; ideal i=u-b40,t-a40,x-a23b17,y-a22b18+ab39,z-a25b15; ideal ei=eliminate(i,ab); // It takes a few seconds to compute the ideal ring r9=0,(x,y,z,t,u),dp; ideal i=imap(r8,ei); depthIdeal(i); // This is very fast. // Now you can use mres(i,0) to compute a m.g.f.r. of the ideal! // // Another one: ring r10=0,(x(0..8),s,t),dp; ideal i=x(0)-st24,x(1)-s2t23,x(2)-s3t22,x(3)-s9t16,x(4)-s11t14,x(5)-s18t7, x(6)-s24t,x(7)-t25,x(8)-s25; ideal ei=eliminate(i,st); ring r11=0,x(0..8),dp; ideal i=imap(r10,ei); depthIdeal(i); // More examples where not even sres works: // Be careful: elimination takes some time here, but it succeeds! ring r12=0,(s,t,u,x(0..14)),dp; ideal i=x(0)-st6u8,x(1)-s5t3u7,x(2)-t11u4,x(3)-s9t4u2,x(4)-s2t7u6,x(5)-s7t7u, x(6)-s10t5,x(7)-s4t6u5,x(8)-s13tu,x(9)-s14u,x(10)-st2u12,x(11)-s3t9u3, x(12)-s15,x(13)-t15,x(14)-u15; ideal ei=eliminate(i,stu); size(ei); ring r13=0,x(0..14),dp; ideal i=imap(r12,ei); size(i); depthIdeal(i); // */ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc satiety (ideal i, list #) " USAGE: satiety (i[,e]); i ideal, e integer RETURN: an integer, the satiety of i. (returns -1 if i is not homogeneous) ASSUME: i is a homogeneous ideal of the basering S=K[x(0)..x(n)]. e=0: (default) The satiety is computed determining the fresh elements in the socle of i. It works over arbitrary fields. e=1: Makes random changes of coordinates to find a monomial ideal with same satiety. It works over infinite fields only. If K is finite, it works if it terminates, but may result in an infinite loop. After 30 loops, a warning message is displayed and -1 is returned. THEORY: The satiety, or saturation index, of a homogeneous ideal i is the least integer s such that, for all d>=s, the degree d part of the ideals i and isat=sat(i,maxideal(1))[1] coincide. NOTE: If printlevel > 0 (default = 0), dim(S/i) is also displayed. EXAMPLE: example satiety; shows some examples " { //--------------------------- initialisation --------------------------------- int e,ii,jj,h,d,time,lastv,nesttest,NPtest,nl,sat; intmat ran; def r0 = basering; int n = nvars(r0)-1; if ( size(#) > 0 ) { e = #[1]; } string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,K,chcoord,m,KK; poly P; map phi; i = fetch(r0,i); time=rtimer; sbi=std(i); //----- Check ideal homogeneous if ( homog(sbi) == 0 ) { "// WARNING from proc satiety from lib mregular.lib: // The ideal is not homogeneous!"; return (-1); } I=simplify(lead(sbi),1); attrib(I,"isSB",1); d=dim(I); //----- If the ideal i is not proper: if ( d == -1 ) { dbprint(printlevel-voice+2, "// The ideal i is (1)! // Its satiety is:"); return (0); } //----- If the ideal i is 0: if ( size(I) == 0 ) { dbprint(printlevel-voice+2, "// The ideal i is (0)! // Its satiety is:"); return (0); } //----- When the ideal i is 0-dimensional: if ( d == 0 ) { sat=maxdeg1(minbase(quotient(I,maxideal(1))))+1; time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: 0"); dbprint(printlevel-voice+2, "// Time for computing the satiety: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// The satiety of i is:"); return (sat); } //----- When one has option e=1: // //----- Determine the situation: NT, or NP, or nothing. //----- Choose the method depending on the situation in order to //----- get the mon. ideal of nested type associated to i if ( e == 1 ) { NPtest=is_NP(I); if ( NPtest == 0 ) { while ( nl < 30 ) { chcoord=select1(maxideal(1),1..(n-d+1)); nl=nl+1; for ( ii = 1; ii<=d; ii++ ) { ran=random(100,1,n-d+ii); ran=intmat(ran,1,n-d+ii+1); ran[1,n-d+ii+1]=1; m=select1(maxideal(1),1..(n-d+1+ii)); for ( jj = 1; jj<=n-d+ii+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[n-d+1+ii]=P; P=0; } phi=r1,chcoord; dbprint(printlevel-voice+2,"// (1 random change of coord.)"); I=simplify(lead(std(phi(i))),1); attrib(I,"isSB",1); NPtest=is_NP(I); if ( NPtest == 1 ) { break; } } if ( NPtest == 0 ) { "// WARNING from proc satiety from lib mregular.lib: // The procedure has entered in 30 loops and could not put the variables // in Noether position: in your example the method using random changes // of coordinates may enter an infinite loop when the field is finite. // Try removing the optional argument."; return (-1); } i=phi(i); } nesttest=is_nested(I); if ( nesttest == 0 ) { while ( nl < 30 ) { chcoord=select1(maxideal(1),1..(n-d+2)); nl=nl+1; for ( ii = 1; ii<=d-1; ii++ ) { ran=random(100,1,ii); ran=intmat(ran,1,ii+1); ran[1,ii+1]=1; m=select1(maxideal(1),(n-d+2)..(n-d+2+ii)); for ( jj = 1; jj<=ii+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[n-d+2+ii]=P; P=0; } phi=r1,chcoord; dbprint(printlevel-voice+2,"// (1 random change of coord.)"); I=simplify(lead(std(phi(i))),1); attrib(I,"isSB",1); nesttest=is_nested(I); if ( nesttest == 1 ) { break; } } if ( nesttest == 0 ) { "// WARNING from proc satiety from lib mregular.lib: // The procedure has entered in 30 loops and could not find a monomial // ideal of nested type with the same satiety as your ideal: in your // example the method using random changes of coordinates may enter an // infinite loop when the field is finite. // Try removing the optional argument."; return (-1); } } // // At this stage, we have obtained a monomial ideal I of nested type // such that depth(S/i)=depth(S/I). We now compute depth(I). // //----- When S/i is Cohen-Macaulay: // for ( ii = n-d+2; ii <= n+1; ii++ ) { K=K+select(I,ii); } if ( size(K) == 0 ) { time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: "+string(d)); dbprint(printlevel-voice+2, "// Time for computing satiety: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// The satiety of i is:"); return(0); } //----- When d=1 (and S/i is not Cohen-Macaulay) ==> depth =0: if ( d == 1 ) { KK=simplify(reduce(quotient(I,maxideal(1)),I),2); sat=maxdeg1(KK)+1; time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: 1"); dbprint(printlevel-voice+2, "// Time for computing satiety: "+ string(time) + " sec."); dbprint(printlevel-voice+2, "// The satiety of i is:"); return(sat); } //----- Now d>1 and S/i is not Cohen-Macaulay: // //----- First, determine the last variable really occuring lastv=n-d; h=n; while ( lastv == n-d and h > n-d ) { K=select(I,h+1); if ( size(K) == 0 ) { h=h-1; } else { lastv=h; } } //----- and compute the satiety: sat=0; if ( lastv == n ) { KK=simplify(reduce(quotient(I,maxideal(1)),I),2); sat=maxdeg1(KK)+1; } time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: "+string(d)); dbprint(printlevel-voice+2, "// Time for computing satiety: "+ string(time) + " sec."); dbprint(printlevel-voice+2, "// The satiety of i is:"); return(sat); } //---- If no option: direct computation sat=maxdeg1(reduce(quotient(i,maxideal(1)),sbi))+1; time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: "+string(d)+";"); dbprint(printlevel-voice+2, "// Time for computing satiety: "+ string(time) + " sec."); dbprint(printlevel-voice+2, "// The satiety of i is:"); return(sat); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,t,w),dp; ideal i=y2t,x2y-x2z+yt2,x2y2,xyztw,x3z2,y5+xz3w-x2zw2,x7-yt2w4; satiety(i); ideal I=lead(std(i)); satiety(I); // First method: direct computation satiety(I,1); // Second method: doing changes of coordinates // Additional information is displayed if you change printlevel (=1); } //////////////////////////////////////////////////////////////////////////////// /* Out-commented examples: ring s1=0,(x,y,z,t),dp; ideal I=zt3,z2t2,yz2t,xz2t,xy2t,x3y; satiety(I); satiety(I,1); // Another example: ring s2=0,(z,y,x),dp; ideal I=z38,z26y2,z14y4,z12x,z10x5,z8x9,z6x16,z4x23,z2y6,y32; satiety(I); satiety(I,1); // One more: ring s3=0,(s,t,u,x(0..8)),dp; ideal i=x(0)-st6u8,x(1)-s5t3u7,x(2)-t11u4,x(3)-s9t4u2, x(4)-s2t7u6,x(5)-s7t7u,x(6)-s15,x(7)-t15,x(8)-u15; ideal ei=eliminate(i,stu); size(ei); ring s4=0,x(0..8),dp; ideal i=imap(s3,ei); ideal m=maxideal(1); m[8]=m[8]+m[7]; map phi=m; ideal phii=phi(i); ideal nI=lead(std(phii)); ring s5=0,x(0..7),dp; ideal nI=imap(s4,nI); satiety(nI); satiety(nI,1); ideal I1=subst(nI,x(7),1); ring s6=0,x(0..6),dp; ideal I1=imap(s5,I1); satiety(I1); satiety(I1,1); ideal I2=subst(I1,x(6),1); ring s7=0,x(0..5),dp; ideal I2=imap(s6,I2); satiety(I2); satiety(I2,1); // */ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc regMonCurve (list #) " USAGE: regMonCurve (a0,...,an) ; ai integers with a0=0 < a1 < ... < an=:d RETURN: an integer, the Castelnuovo-Mumford regularity of the projective monomial curve C in Pn(K) parametrically defined by x(0) = t^d , x(1) = s^(a1)t^(d-a1) , ..... , x(n) = s^d where K is the field of complex numbers. (returns -1 if a0=0 < a1 < ... < an is not satisfied) ASSUME: a0=0 < a1 < ... < an are integers. NOTES: 1. The defining ideal of the curve C, I in S=K[x(0),...,x(n)], is determined by elimination. 2. The procedure regIdeal has been improved in this case since one knows beforehand that the monomial ideal J=lead(std(I)) is of nested type if the monomial ordering is dp, and that reg(C)=reg(J) (see preprint 'Saturation and Castelnuovo-Mumford regularity' by Bermejo-Gimenez, 2004). 3. If printlevel > 0 (default = 0) additional info is displayed: - It says whether C is arithmetically Cohen-Macaulay or not. - If C is not arith. Cohen-Macaulay, end(H^1(S/I)) is computed and an upper bound for the a-invariant of S/I is given. - It also determines one step of the minimal graded free resolution (m.g.f.r.) of I where the regularity is attained and gives the value of the regularity of the Hilbert function of S/I when reg(I) is attained at the last step of a m.g.f.r. EXAMPLE: example regMonCurve; shows some examples " { //--------------------------- initialisation --------------------------------- int ii,H,h,hh,time,ttime,firstind,lastind; int n = size(#)-1; //------------------ Check assumptions on integers ------------------------- if ( #[1] != 0 ) {"// WARNING from proc regMonCurve from lib mregular.lib: // USAGE: your input must be a list of integers a0,a1,...,an such that // a0=0 < a1 < a2 < ... < an"; return(-1); } for ( ii=1; ii<= n; ii++ ) { if ( #[ii] >= #[ii+1] ) { "// WARNING from proc regMonCurve from lib mregular.lib: // USAGE: your input must be a list of integers a0,a1,...,an such that // a0=0 < a1 < a2 < ... < an"; return(-1); } } ring R=0,(x(0..n),s,t),dp; ideal param,m,i; poly f(0..n); for (ii=0;ii<=n;ii++) { f(ii)=s^(#[n+1]-#[ii+1])*t^(#[ii+1]); param=param+f(ii); } m=subst(maxideal(1),s,0); m=simplify(subst(m,t,0),2); i=matrix(m)-matrix(param); ttime=rtimer; i=eliminate(i,st); ring r=0,(x(1..n),x(0)),dp; ideal i,I; i=imap(R,i); I=minbase(lead(std(i))); attrib(I,"isSB",1); ttime=rtimer-ttime; time=rtimer; ring nr=0,x(1..n),dp; ideal I,K,KK,J; I=imap(r,I); attrib(I,"isSB",1); K=select(I,n); //------------------ Cohen-Macaulay case ------------ if ( size(K) == 0 ) { ring mr=0,x(1..n-1),dp; ideal I=imap(nr,I); H=maxdeg1(minbase(quotient(I,maxideal(1))))+1; time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// The sequence of integers defines a monomial curve C in P" + string(n)); dbprint(printlevel-voice+2, "// C is arithmetically Cohen-Macaulay"); dbprint(printlevel-voice+2, "// Regularity attained at the last step of a m.g.f.r. of I(C)"); dbprint(printlevel-voice+2, "// Regularity of the Hilbert function of S/I(C): " + string(H-2)); dbprint(printlevel-voice+2, "// Time for computing ideal I(C) (by elimination): " + string(ttime) + " sec."); dbprint(printlevel-voice+2, "// Time for computing reg(C) once I(C) has been determined: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// The Castelnuovo-Mumford regularity of C is:"); return(H); } else { KK=simplify(reduce(quotient(I,maxideal(1)),I),2); firstind=maxdeg1(KK)+1; J=subst(I,x(n),1); ring mr=0,x(1..n-1),dp; ideal J=imap(nr,J); lastind=maxdeg1(minbase(quotient(J,maxideal(1))))+1; H=firstind; if ( lastind > H ) { H=lastind; } time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// The sequence of integers defines a monomial curve C in P" + string(n)); dbprint(printlevel-voice+2, "// C is not arithmetically Cohen-Macaulay"); dbprint(printlevel-voice+2, "// end(H^1(S/I(C))) = " +string(firstind-2)); dbprint(printlevel-voice+2, "// Upper bound for the a-invariant of S/I(C): end(H^2(S/I(C))) <= " +string(lastind-3)); if ( H == firstind ) { dbprint(printlevel-voice+2, "// Regularity attained at the last step of a m.g.f.r. of I(C)"); dbprint(printlevel-voice+2, "// Regularity of the Hilbert function of S/I(C): " + string(H-1)); } else { dbprint(printlevel-voice+2, "// Regularity attained at the second last step of a m.g.f.r. of I(C)"); dbprint(printlevel-voice+2, "// (and not attained at the last step)"); } dbprint(printlevel-voice+2, "// Time for computing ideal I(C) (by elimination): " + string(ttime) + " sec."); dbprint(printlevel-voice+2, "// Time for computing reg(C) once I(C) has been determined: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// The Castelnuovo-Mumford regularity of C is:"); return(H); } } example { "EXAMPLE:"; echo = 2; // The 1st example is the twisted cubic: regMonCurve(0,1,2,3); // The 2nd. example is the non arithm. Cohen-Macaulay monomial curve in P4 // parametrized by: x(0)-s6,x(1)-s5t,x(2)-s3t3,x(3)-st5,x(4)-t6: regMonCurve(0,1,3,5,6); // Additional information is displayed if you change printlevel (=1); } //////////////////////////////////////////////////////////////////////////////// /* Out-commented examples: // // The sequence of integers must be strictly increasing regMonCurve(1,4,6,9); regMonCurve(0,3,8,5,23); regMonCurve(0,4,7,7,9); // // A curve in P3 s.t. the regularity is attained at the last step: regMonCurve(0,2,12,15); // // A curve in P4 s.t. the regularity attained at the last but one // but NOT at the last step (Ex. 3.3 Preprint 2004): regMonCurve(0,5,9,11,20); // // A curve in P8 s.t. the m.g.f.r. of the defining ideal is not easily // obtained through m.g.f.r.: regMonCurve(0,1,2,3,9,11,18,24,25); // // A curve in P11 of degree 37: regMonCurve(0,1,2,7,16,17,25,27,28,30,36,37); // It takes some time to compute the eliminated ideal; the computation of // the regularity is then rather fast as one can check using proc regIdeal: ring q=0,(s,t,x(0..11)),dp; ideal i=x(0)-st36,x(1)-s2t35,x(2)-s7t30,x(3)-s16t21,x(4)-s17t20,x(5)-s25t12, x(6)-s27t10,x(7)-s28t9,x(8)-s30t7,x(9)-s36t,x(10)-s37,x(11)-t37; ideal ei=eliminate(i,st); ring qq=0,x(0..11),dp; ideal i=imap(q,ei); regIdeal(i); // // A curve in P14 of degree 55: regMonCurve(0,1,2,7,16,17,25,27,28,30,36,37,40,53,55); // */ /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc NoetherPosition (ideal i) " USAGE: NoetherPosition (i); i ideal RETURN: ideal such that, for the homogeneous linear transformation map phi=S,NoetherPosition(i); one has that K[x(n-d+1),...,x(n)] is a Noether normalization of S/phi(i) where S=K[x(0),...x(n)] is the basering and d=dim(S/i). (returns -1 if i = (0) or (1)). ASSUME: The field K is infinite and i is a nonzero proper ideal. NOTE: 1. It works also if K is a finite field if it terminates, but may result in an infinite loop. If the procedure enters more than 30 loops, -1 is returned and a warning message is displayed.@* 2. If printlevel > 0 (default = 0), additional info is displayed: dim(S/i) and K[x(n-d+1),...,x(n)] are given. EXAMPLE: example NoetherPosition; shows some examples " { //--------------------------- initialisation --------------------------------- int ii,jj,d,time,nl,NPtest; intmat ran; def r0 = basering; ideal K,chcoord; int n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,K,chcoord,m; poly P; map phi; i = fetch(r0,i); time=rtimer; sbi=std(i); I=simplify(lead(sbi),1); attrib(I,"isSB",1); d=dim(I); //----- If the ideal i is not proper: if ( d == -1 ) { "// WARNING from proc NoetherPosition from lib mregular.lib: // The ideal i is (1)!"; return (-1); } //----- If the ideal i is 0: if ( size(I) == 0 ) { "// WARNING from proc NoetherPosition from lib mregular.lib: // The ideal i is (0)!"; return (-1); } //----- When the ideal i is 0-dimensional: if ( d == 0 ) { time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: 0"); dbprint(printlevel-voice+2, "// Time for computing a Noether normalization: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// K is a Noether normalization of S/phi(i)"); dbprint(printlevel-voice+2, "// where the map phi: S --> S is:"); setring r0; return (maxideal(1)); } NPtest=is_NP(I); if ( NPtest == 1 ) { K=x(n-d+1..n); setring r0; K=fetch(r1,K); time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: " + string(d) ); dbprint(printlevel-voice+2, "// Time for computing a Noether normalization: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// K[" + string(K) + "] is a Noether normalization of S/phi(i)"); dbprint(printlevel-voice+2, "// where the map phi: S --> S is:"); return (maxideal(1)); } //---- Otherwise, random change of coordinates and //---- test for Noether normalization. //---- If we were unlucky, another change of coord. will be done: while ( nl < 30 ) { chcoord=select1(maxideal(1),1..(n-d+1)); nl=nl+1; for ( ii = 1; ii<=d; ii++ ) { ran=random(100,1,n-d+ii); ran=intmat(ran,1,n-d+ii+1); ran[1,n-d+ii+1]=1; m=select1(maxideal(1),1..(n-d+1+ii)); for ( jj = 1; jj<=n-d+ii+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[n-d+1+ii]=P; P=0; } phi=r1,chcoord; dbprint(printlevel-voice+2,"// (1 random change of coord.)"); I=simplify(lead(std(phi(i))),1); attrib(I,"isSB",1); NPtest=is_NP(I); if ( NPtest == 1 ) { K=x(n-d+1..n); setring r0; K=fetch(r1,K); chcoord=fetch(r1,chcoord); time=rtimer-time; // Additional information: dbprint(printlevel-voice+2, "// Dimension of S/i: " + string(d) ); dbprint(printlevel-voice+2, "// Time for computing a Noether normalization: " + string(time) + " sec."); dbprint(printlevel-voice+2, "// K[" + string(K) + "] is a Noether normalization of S/phi(i)"); dbprint(printlevel-voice+2, "// where the map phi: S --> S is:"); return (chcoord); } } "// WARNING from proc NoetherPosition from lib mregular.lib: // The procedure has entered in more than 30 loops: in your example // the method may enter an infinite loop over a finite field!"; return (-1); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,t,u),dp; ideal i1=y,z,t,u; ideal i2=x,z,t,u; ideal i3=x,y,t,u; ideal i4=x,y,z,u; ideal i5=x,y,z,t; ideal i=intersect(i1,i2,i3,i4,i5); map phi=r,NoetherPosition(i); phi; ring r5=5,(x,y,z,t,u),dp; ideal i=imap(r,i); map phi=r5,NoetherPosition(i); phi; // Additional information is displayed if you change printlevel (=1); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc is_NP (ideal i) " USAGE: is_NP (i); i ideal RETURN: 1 if K[x(n-d+1),...,x(n)] is a Noether normalization of S/i where S=K[x(0),...x(n)] is the basering, and d=dim(S/i), 0 otherwise. (returns -1 if i=(0) or i=(1)). ASSUME: i is a nonzero proper homogeneous ideal. NOTE: 1. If i is not homogeneous and is_NP(i)=1 then K[x(n-d+1),...,x(n)] is a Noether normalization of S/i. The converse may be wrong if the ideal is not homogeneous. 2. is_NP is used in the procedures regIdeal, depthIdeal, satiety, and NoetherPosition. EXAMPLE: example is_NP; shows some examples " { //--------------------------- initialisation --------------------------------- int ii,d,dz; def r0 = basering; int n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,J; i = fetch(r0,i); sbi=std(i); I=simplify(lead(sbi),1); attrib(I,"isSB",1); d=dim(I); //----- If the ideal i is not proper: if ( d == -1 ) { "// WARNING from proc is_NP from lib mregular.lib: // The ideal i is (1)!"; return (-1); } //----- If the ideal i is 0: if ( size(I) == 0 ) { "// WARNING from proc is_NP from lib mregular.lib: // The ideal i is (0)!"; return (-1); } //----- When the ideal i is 0-dimensional: if ( d == 0 ) { return (1); } //----- Check Noether position J=I; for ( ii = n-d+1; ii <= n; ii++ ) { J=subst(J,x(ii),0); } attrib(J,"isSB",1); dz=dim(J); if ( dz == d ) { return (1); } else { return(0); } } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,t,u),dp; ideal i1=y,z,t,u; ideal i2=x,z,t,u; ideal i3=x,y,t,u; ideal i4=x,y,z,u; ideal i5=x,y,z,t; ideal i=intersect(i1,i2,i3,i4,i5); is_NP(i); ideal ch=x,y,z,t,x+y+z+t+u; map phi=ch; is_NP(phi(i)); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc is_nested (ideal i) " USAGE: is_nested (i); i monomial ideal RETURN: 1 if i is of nested type, 0 otherwise. (returns -1 if i=(0) or i=(1)). ASSUME: i is a nonzero proper monomial ideal. NOTES: 1. The ideal must be monomial, otherwise the result has no meaning (so check this before using this procedure).@* 2. is_nested is used in procedures depthIdeal, regIdeal and satiety.@* 3. When i is a monomial ideal of nested type of S=K[x(0)..x(n)], the a-invariant of S/i coincides with the upper bound obtained using the procedure regIdeal with printlevel > 0. THEORY: A monomial ideal is of nested type if its associated primes are all of the form (x(0),...,x(i)) for some i<=n. (see definition and effective criterion to check this property in the preprint 'Saturation and Castelnuovo-Mumford regularity' by Bermejo-Gimenez, 2004). EXAMPLE: example is_nested; shows some examples " { //--------------------------- initialisation --------------------------------- int ii,d,tev,lastv,h,NPtest; def r0 = basering; int n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal I,K,KK,LL; I = fetch(r0,i); I=minbase(I); attrib(I,"isSB",1); d=dim(I); //----- If the ideal i is not proper: if ( d == -1 ) { "// WARNING from proc is_nested from lib mregular.lib: // The ideal i is (1)!"; return (-1); } //----- If the ideal i is 0: if ( size(I) == 0 ) { "// WARNING from proc is_nested from lib mregular.lib: // The ideal i is (0)!"; return (-1); } //----- When the ideal i is 0-dimensional: if ( d == 0 ) { return (1); } //----- Check Noether position NPtest=is_NP(I); if ( NPtest != 1 ) { return (0); } //----- When ideal is 1-dim. + var. in Noether position -> Nested Type if ( d == 1 ) { return (1); } //----- Determ. of the last variable really occuring lastv=n-d; h=n; while ( lastv == n-d and h > n-d ) { K=select(I,h+1); if ( size(K) == 0 ) { h=h-1; } else { lastv=h; } } //----- Check the second property by evaluation when NP + d>1 KK=subst(I,x(lastv),1); for ( ii = n-lastv; ii<=d-2; ii++ ) { LL=minbase(subst(I,x(n-ii-1),1)); attrib(LL,"isSB",1); tev=size(reduce(KK,LL)); if ( tev > 0 ) { return(0); } KK=LL; } return(1); } example { "EXAMPLE:"; echo = 2; ring s=0,(x,y,z,t),dp; ideal i1=x2,y3; ideal i2=x3,y2,z2; ideal i3=x3,y2,t2; ideal i=intersect(i1,i2,i3); is_nested(i); ideal ch=x,y,z,z+t; map phi=ch; ideal I=lead(std(phi(i))); is_nested(I); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/multigrading.lib000066400000000000000000003332061266270727000213340ustar00rootroot00000000000000// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- // Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab ///////////////////////////////////////////////////////////////// version="version multigrading.lib 4.0.0.0 Jun_2013 "; // $Id: 0d8e623a8e2d845ada617ca8ccf894789fc54926 $ category="Combinatorial Commutative Algebra"; info=" LIBRARY: multigrading.lib Multigraded Rings AUTHORS: Benjamin Bechtold, benjamin.bechtold@googlemail.com @* Rene Birkner, rbirkner@math.fu-berlin.de @* Lars Kastner, lkastner@math.fu-berlin.de @* Simon Keicher, keicher@mail.mathematik.uni-tuebingen.de @* Oleksandr Motsak, U@D, where U={motsak}, D={mathematik.uni-kl.de} @* Anna-Lena Winz, anna-lena.winz@math.fu-berlin.de OVERVIEW: This library allows one to virtually add multigradings to Singular: grade multivariate polynomial rings with arbitrary (fin. gen. Abelian) groups. For more see http://code.google.com/p/convex-singular/wiki/Multigrading For theoretical references see: @* E. Miller, B. Sturmfels: 'Combinatorial Commutative Algebra' and @* M. Kreuzer, L. Robbiano: 'Computational Commutative Algebra'. NOTE: 'multiDegBasis' relies on 4ti2 for computing Hilbert Bases. All groups are finitely generated Abelian PROCEDURES: setBaseMultigrading(M,L); attach multiweights/grading group matrices to the basering getVariableWeights([R]); get matrix of multidegrees of vars attached to a ring getGradingGroup([R]); get grading group attached to a ring getLattice([R[,choice]]); get grading group' lattice attached to a ring (or its NF) createGroup(S,L); create a group generated by S, with relations L createQuotientGroup(L); create a group generated by the unit matrix whith relations L createTorsionFreeGroup(S); create a group generated by S which is torsionfree printGroup(G); print a group isGroup(G); test whether G is a valid group isGroupHomomorphism(L1,L2,A); test wheter A defines a group homomrphism from L1 to L2 isGradedRingHomomorphism(R,f,A); test graded ring homomorph createGradedRingHomomorphism(R,f,A); create a graded ring homomorph setModuleGrading(M,v); attach multiweights of units to a module and return it getModuleGrading(M); get multiweights of module units (attached to M) isSublattice(A,B); test whether A is a sublattice of B imageLattice(P,L); computes an integral basis for P(L) intRank(A); computes the rank of the intmat A kernelLattice(P); computes an integral basis for the kernel of the linear map P. latticeBasis(B); computes an integral basis of the lattice B preimageLattice(P,L); computes an integral basis for the preimage of the lattice L under the linear map P. projectLattice(B); computes a linear map of lattices having the primitive span of B as its kernel. intersectLattices(A,B); computes an integral basis for the intersection of the lattices A and B. isIntegralSurjective(P); test whether the map P of lattices is surjective. isPrimitiveSublattice(A); test whether A generates a primitive sublattice. intInverse(A); computes the integral inverse matrix of the intmat A integralSection(P); for a given linear surjective map P of lattices this procedure returns an integral section of P. primitiveSpan(A); computes a basis for the minimal primitive sublattice that contains the given vectors (by A). factorgroup(G,H); create the group G mod H productgroup(G,H); create the group G x H multiDeg(A); compute the multidegree of A multiDegBasis(d); compute all monomials of multidegree d multiDegPartition(p); compute the multigraded-homogeneous components of p isTorsionFree(); test whether the current multigrading is free isPositive(); test whether the current multigrading is positive isZeroElement(p); test whether p has zero multidegree areZeroElements(M); test whether an integer matrix M considered as a collection of columns has zero multidegree isHomogeneous(a); test whether 'a' is multigraded-homogeneous equalMultiDeg(e1,e2[,V]); test whether e1==e2 in the current multigrading multiDegGroebner(M); compute the multigraded GB/SB of M multiDegSyzygy(M); compute the multigraded syzygies of M multiDegModulo(I,J); compute the multigraded 'modulo' module of I and J multiDegResolution(M,l[,m]); compute the multigraded resolution of M multiDegTensor(m,n); compute the tensor product of multigraded modules m,n multiDegTor(i,m,n); compute the Tor_i(m,n) for multigraded modules m,n defineHomogeneous(p); get a grading group wrt which p becomes homogeneous pushForward(f); find the finest grading on the image ring, homogenizing f gradiator(h); coarsens grading of the ring until h becomes homogeneous hermiteNormalForm(A); compute the Hermite Normal Form of a matrix smithNormalForm(A,#); compute matrices D,P,Q with D=P*A*Q and D is the smith normal form of A hilbertSeries(M); compute the multigraded Hilbert Series of M lll(A); applies LLL(.) of lll.lib which only works for lists on a matrix A (parameters in square brackets [] are optional) KEYWORDS: multigrading, multidegree, multiweights, multigraded-homogeneous, integral linear algebra "; /// evalHilbertSeries(h,v); evaluate hilberts series h by substituting v[i] for t_(i) (too experimentall) // finestMDeg(def r) // newMap(map F, intmat Q, list #) LIB "standard.lib"; // for groebner // LIB "lll.lib"; // for lll_matrix // no need now, right? LIB "matrix.lib"; // for multiDegTor /******************************************************/ static proc concatintmat(intmat A, intmat B) { if ( nrows(A) != nrows(B) ) { ERROR("matrices A and B have different number of rows."); } intmat At = transpose(A); intmat Bt = transpose(B); intmat Ct[nrows(At) + nrows(Bt)][ncols(At)] = At, Bt; return(transpose(Ct)); } /******************************************************/ proc createGradedRingHomomorphism(def src, ideal Im, def A) "USAGE: createGradedRingHomomorphism(R, f, A); ring R, ideal f, group homomorphism A PURPOSE: create a multigraded group ring homomorphism defined by a ring map from R to the current ring, given by generators images f and a group homomorphism A between grading groups RETURN: graded ring homorphism EXAMPLE: example createGradedRingHomomorphism; shows an example " { string isGRH = "isGRH"; if( !isGradedRingHomomorphism(src, Im, A) ) { ERROR("Input data is wrong"); } list h; h[3] = A; // map f = src, Im; h[2] = Im; // f? h[1] = src; attrib(h, isGRH, (1==1)); // mark it "a graded ring homomorphism" return(h); } example { "EXAMPLE:"; echo=2; ring r = 0, (x, y, z), dp; intmat S1[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; intmat L1[3][1] = 0, 0, 0; def G1 = createGroup(S1, L1); // (S1 + L1)/L1 printGroup(G1); setBaseMultigrading(S1, L1); // to change... ring R = 0, (a, b, c), dp; intmat S2[2][3] = 1, 0, 0, 1; intmat L2[2][1] = 0, 2; def G2 = createGroup(S2, L2); printGroup(G2); setBaseMultigrading(S2, L2); // to change... map F = r, a, b, c; intmat A[nrows(L2)][nrows(L1)] = 1, 0, 0, 3, 2, -6; // graded ring homomorphism is given by (compatible): print(F); print(A); isGradedRingHomomorphism(r, ideal(F), A); def h = createGradedRingHomomorphism(r, ideal(F), A); print(h); } /******************************************************/ proc isGradedRingHomomorphism(def src, ideal Im, def A) "USAGE: isGradedRingHomomorphism(R, f, A); ring R, ideal f, group homomorphism A PURPOSE: test a multigraded group ring homomorphism defined by a ring map from R to the current ring, given by generators images f and a group homomorphism A between grading groups RETURN: int, 1 for TRUE, 0 otherwise EXAMPLE: example isGradedRingHomomorphism; shows an example " { def dst = basering; intmat result_degs = multiDeg(Im); // print(result_degs); setring src; intmat input_degs = multiDeg(maxideal(1)); // print(input_degs); def image_degs = A * input_degs; // print( image_degs ); def df = image_degs - result_degs; // print(df); setring dst; return (areZeroElements( df )); } example { "EXAMPLE:"; echo=2; ring r = 0, (x, y, z), dp; intmat S1[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; intmat L1[3][1] = 0, 0, 0; def G1 = createGroup(S1, L1); // (S1 + L1)/L1 printGroup(G1); setBaseMultigrading(S1, L1); // to change... ring R = 0, (a, b, c), dp; intmat S2[2][3] = 1, 0, 0, 1; intmat L2[2][1] = 0, 2; def G2 = createGroup(S2, L2); printGroup(G2); setBaseMultigrading(S2, L2); // to change... map F = r, a, b, c; intmat A[nrows(L2)][nrows(L1)] = 1, 0, 0, 3, 2, -6; // graded ring homomorphism is given by (compatible): print(F); print(A); isGradedRingHomomorphism(r, ideal(F), A); def h = createGradedRingHomomorphism(r, ideal(F), A); print(h); // not a homo.. intmat B[nrows(L2)][nrows(L1)] = 1, 1, 1, 0, 0, 0; print(B); isGradedRingHomomorphism(r, ideal(F), B); // FALSE: there is no such homomorphism! // Therefore: the following command should return an error // createGradedRingHomomorphism(r, ideal(F), B); } proc createQuotientGroup(intmat L) "USAGE: createGroup(L); L is an integer matrix PURPOSE: create the group of the form (I+L)/L, where I is the square identity matrix of size nrows(L) x nrows(L) NOTE: L specifies relations between free generators of Z^nrows(L) RETURN: group EXAMPLE: example createQuotientGroup; shows an example " { int r = nrows(L); int i; intmat S[r][r]; // SQUARE!!! for(i = r; i > 0; i--){ S[i, i] = 1; } return (createGroup(S,L)); } example { "EXAMPLE:"; echo=2; intmat I[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; intmat L[3][2] = 1, 1, 1, 3, 1, 5; // The group Z^3 / L can be constructed as follows: // shortcut: def G = createQuotientGroup(L); printGroup(G); // the general way: def GG = createGroup(I, L); // (I+L)/L printGroup(GG); } proc createTorsionFreeGroup(intmat S) "USAGE: createTorsionFreeGroup(S); S is an integer matrix PURPOSE: create the free subgroup generated by S within the free Abelian group of rank nrows(S) RETURN: group EXAMPLE: example createTorsionFreeGroup; shows an example " { int r = nrows(S); int i; intmat L[r][1] = 0; return (createGroup(S,L)); } example { "EXAMPLE:"; echo=2; // ----------- extreme case ------------ // intmat S[1][3] = 1, -1, 10; // Torsion: intmat L[1][1] = 0; // The free subgroup generated by elements of S within Z^1 // can be constructed as follows: // shortcut: def G = createTorsionFreeGroup(S); printGroup(G); // the general way: def GG = createGroup(S, L); // (S+L)/L printGroup(GG); } /******************************************************/ proc createGroup(intmat S, intmat L) "USAGE: createGroup(S, L); S, L are integer matrices PURPOSE: create the group of the form (S+L)/L, i.e. S specifies generators, L specifies relations. RETURN: group EXAMPLE: example createGroup; shows an example " { string isGroup = "isGroup"; string attrGroupHNF = "hermite"; string attrGroupSNF = "smith"; /* if( size(#) > 0 ) { if( typeof(#[1]) == "intmat" ) { intmat S = #[1]; } else { ERROR("Wrong optional argument: 1"); } if( size(#) > 1 ) { if( typeof(#[2]) == "intmat" ) { intmat L = #[2]; } else { ERROR("Wrong optional argument: 2"); } } } */ if( nrows(L) != nrows(S) ) { ERROR("Incompatible matrices!"); } def H = attrib(L, attrGroupHNF); if( typeof(H) != "intmat") { attrib(L, attrGroupHNF, hermiteNormalForm(L)); } else { kill H; } def HH = attrib(L, attrGroupSNF); if( typeof(HH) != "intmat") { attrib(L, attrGroupSNF, smithNormalForm(L)); } else { kill HH; } list G; // Please, note the order: Generators + Relations: G[1] = S; G[2] = L; // And now a quick-and-dirty fix of Singular inability to handle attribs of attribs: // For the use of a group as an attribute for multigraded rings G[3] = attrib(L, attrGroupHNF); G[4] = attrib(L, attrGroupSNF); attrib(G, isGroup, (1==1)); // mark it "a group" return (G); } example { "EXAMPLE:"; echo=2; intmat S[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; intmat L[3][2] = 1, 1, 1, 3, 1, 5; def G = createGroup(S, L); // (S+L)/L printGroup(G); kill S, L, G; ///////////////////////////////////////////////// intmat S[2][3] = 1, -2, 1, 1, 1, 0; intmat L[2][1] = 0, 2; def G = createGroup(S, L); // (S+L)/L printGroup(G); kill S, L, G; // ----------- extreme case ------------ // intmat S[1][3] = 1, -1, 10; // Torsion: intmat L[1][1] = 0; def G = createGroup(S, L); // (S+L)/L printGroup(G); } /******************************************************/ proc printGroup(def G) "USAGE: printGroup(G); G is a group PURPOSE: prints the group G RETURN: nothing EXAMPLE: example printGroup; shows an example " { "Generators: "; print(G[1]); "Relations: "; print(G[2]); // attrib(G[2]); } example { "EXAMPLE:"; echo=2; intmat S[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; intmat L[3][2] = 1, 1, 1, 3, 1, 5; def G = createGroup(S, L); // (S+L)/L printGroup(G); } /******************************************************/ static proc areIsomorphicGroups(def G, def H) "USAGE: areIsomorphicGroups(G, H); G and H are groups PURPOSE: Check whether G and H define isomorphic groups. RETURN: int, 1 for TRUE, 0 otherwise EXAMPLE: example areIsomorphicGroups; shows an example " { ERROR("areIsomorphicGroups: Not yet implemented!"); return (1); // TRUE } example { "EXAMPLE:"; echo=2; // TODO! } /******************************************************/ proc isGroup(def G) "USAGE: isGroup(G); G a list PURPOSE: checks whether G is a valid group NOTE: G should be created by createGroup (or createQuotientGroup, createTorsionFreeGroup) RETURN: int, 1 if G is a valid group and 0 otherwise EXAMPLE: example isGroup; shows an example " { string isGroup = "isGroup"; // valid? if( typeof(G) != "list" ){ return(0); } def a = attrib(G, isGroup); ///// TODO for Hans: fix attr^2 bug in Singular! // if( !defined(a) ) { return(0); } // if( typeof(a) != "int" ) { return(0); } if( defined(a) ){ if(typeof(a) == "int") { return(a); } } if( (size(G) != 2) && (size(G) != 4) ){ return(0); } if( typeof(G[1]) != "intmat" ){ return(0); } if( typeof(G[2]) != "intmat" ){ return(0); } if( nrows(G[1]) != nrows(G[2]) ){ return(0); } return(1); } example { "EXAMPLE:"; echo=2; intmat S[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; intmat L[3][2] = 1, 1, 1, 3, 1, 5; def G = createGroup(S, L); // (S+L)/L isGroup(G); printGroup(G); } /******************************************************/ proc setBaseMultigrading(intmat M, list #) "USAGE: setBaseMultigrading(M[, G]); M is an integer matrix, G is a group (or lattice) PURPOSE: attaches weights of variables and grading group to the basering. NOTE: M encodes the weights of variables column-wise. RETURN: nothing EXAMPLE: example setBaseMultigrading; shows an example " { string attrMgrad = "mgrad"; string attrGradingGroup = "gradingGroup"; int i = 1; if( size(#) >= i ) { def a = #[i]; if( typeof(a) == "intmat" ) { def L = createGroup(M, a); i++; } if( isGroup(a) ) { def L = a; if( !isSublattice(M, L[1]) ) { ERROR("Multigrading is not contained in the grading group!"); } i++; } if( i == 1 ){ ERROR("Wrong arguments: no group given?"); } kill a; } else { def L = createTorsionFreeGroup(M); } attrib(basering, attrMgrad, M); attrib(basering, attrGradingGroup, L); ideal Q = ideal(basering); // quotient ideal is assumed to be a GB! if( !isHomogeneous(Q, "checkGens") ) // easy now, but would be hard before setting ring attributes! { "Warning: your quotient ideal is not homogenous (multigrading was set anyway)!"; } } example { "EXAMPLE:"; echo=2; ring R = 0, (x, y, z), dp; // Weights of variables intmat M[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; // GradingGroup: intmat L[3][2] = 1, 1, 1, 3, 1, 5; // attaches M & L to R (==basering): setBaseMultigrading(M, L); // Grading: Z^3/L // Weights are accessible via "getVariableWeights()": getVariableWeights(); // Test all possible usages: (getVariableWeights() == M) && (getVariableWeights(R) == M) && (getVariableWeights(basering) == M); // Grading group is accessible via "getLattice()": getLattice(); // Test all possible usages: (getLattice() == L) && (getLattice(R) == L) && (getLattice(basering) == L); // And its hermite NF via getLattice("hermite"): getLattice("hermite"); // Test all possible usages: intmat H = hermiteNormalForm(L); (getLattice("hermite") == H) && (getLattice(R, "hermite") == H) && (getLattice(basering, "hermite") == H); kill L, M; // ----------- isomorphic multigrading -------- // // Weights of variables intmat M[2][3] = 1, -2, 1, 1, 1, 0; // Torsion: intmat L[2][1] = 0, 2; // attaches M & L to R (==basering): setBaseMultigrading(M, L); // Grading: Z + (Z/2Z) // Weights are accessible via "getVariableWeights()": getVariableWeights() == M; // Torsion is accessible via "getLattice()": getLattice() == L; kill L, M; // ----------- extreme case ------------ // // Weights of variables intmat M[1][3] = 1, -1, 10; // Torsion: intmat L[1][1] = 0; // attaches M & L to R (==basering): setBaseMultigrading(M); // Grading: Z^3 // Weights are accessible via "getVariableWeights()": getVariableWeights() == M; // Torsion is accessible via "getLattice()": getLattice() == L; } /******************************************************/ proc getVariableWeights(list #) "USAGE: getVariableWeights([R]) PURPOSE: get associated multigrading matrix for the basering [or R] RETURN: intmat, matrix of multidegrees of variables EXAMPLE: example getVariableWeights; shows an example " { string attrMgrad = "mgrad"; if( size(#) > 0 ) { if( typeof(#[1]) == "ring" ) { def R = #[1]; } else { ERROR("Optional argument must be a ring!"); } } else { def R = basering; } def M = attrib(R, attrMgrad); if( typeof(M) == "intmat"){ return (M); } ERROR( "Sorry no multigrading matrix!" ); } example { "EXAMPLE:"; echo=2; ring R = 0, (x, y, z), dp; // Weights of variables intmat M[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; // Grading group: intmat L[3][2] = 1, 1, 1, 3, 1, 5; // attaches M & L to R (==basering): setBaseMultigrading(M, L); // Grading: Z^3/L // Weights are accessible via "getVariableWeights()": getVariableWeights() == M; kill L, M; // ----------- isomorphic multigrading -------- // // Weights of variables intmat M[2][3] = 1, -2, 1, 1, 1, 0; // Grading group: intmat L[2][1] = 0, 2; // attaches M & L to R (==basering): setBaseMultigrading(M, L); // Grading: Z + (Z/2Z) // Weights are accessible via "getVariableWeights()": getVariableWeights() == M; kill L, M; // ----------- extreme case ------------ // // Weights of variables intmat M[1][3] = 1, -1, 10; // Grading group: intmat L[1][1] = 0; // attaches M & L to R (==basering): setBaseMultigrading(M); // Grading: Z^3 // Weights are accessible via "getVariableWeights()": getVariableWeights() == M; } proc getGradingGroup(list #) "USAGE: getGradingGroup([R]) PURPOSE: get associated grading group RETURN: group, the grading group EXAMPLE: example getGradingGroup; shows an example " { string attrGradingGroup = "gradingGroup"; int i = 1; if( size(#) >= i ) { if( typeof(#[i]) == "ring" ) { def R = #[i]; i++; } } if( i == 1 ) { def R = basering; } def G = attrib(R, attrGradingGroup); if( !isGroup(G) ) { ERROR("Sorry no grading group!"); } return(G); } example { "EXAMPLE:"; echo=2; ring R = 0, (x, y, z), dp; // Weights of variables intmat M[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; // Torsion: intmat L[3][2] = 1, 1, 1, 3, 1, 5; // attaches M & L to R (==basering): setBaseMultigrading(M, L); // Grading: Z^3/L def G = getGradingGroup(); printGroup( G ); G[1] == M; G[2] == L; kill L, M, G; // ----------- isomorphic multigrading -------- // // Weights of variables intmat M[2][3] = 1, -2, 1, 1, 1, 0; // Torsion: intmat L[2][1] = 0, 2; // attaches M & L to R (==basering): setBaseMultigrading(M, L); // Grading: Z + (Z/2Z) def G = getGradingGroup(); printGroup( G ); G[1] == M; G[2] == L; kill L, M, G; // ----------- extreme case ------------ // // Weights of variables intmat M[1][3] = 1, -1, 10; // Torsion: intmat L[1][1] = 0; // attaches M & L to R (==basering): setBaseMultigrading(M); // Grading: Z^3 def G = getGradingGroup(); printGroup( G ); G[1] == M; G[2] == L; kill L, M, G; } /******************************************************/ proc getLattice(list #) "USAGE: getLattice([R[,opt]]) PURPOSE: get associated grading group matrix, i.e. generators (cols) of the grading group RETURN: intmat, the grading group matrix, or its hermite normal form if an optional argument (\"hermiteNormalForm\") is given or smith normal form if an optional argument (\"smith\") is given EXAMPLE: example getLattice; shows an example " { int i = 1; if( size(#) >= i ) { def a = #[i]; if( typeof(a) == "ring" ) { i++; } kill a; } string attrGradingGroupHNF = "hermite"; string attrGradingGroupSNF = "smith"; def G = getGradingGroup(#); // printGroup(G); def T = G[2]; if( size(#) >= i ) { def a = #[i]; if( typeof(a) != "string" ) { ERROR("Sorry wrong arguments!"); } if( a == "hermite" ) { def M = attrib(T, attrGradingGroupHNF); if( typeof(M) != "intmat" ) { if( size(G) > 2 ) { M = G[3]; } else { M = hermiteNormalForm(T); } } return (M); } if( a == "smith" ) { def M = attrib(T, attrGradingGroupSNF); if( typeof(M) != "intmat" ) { if( size(G) > 2 ) { M = G[4]; } else { M = smithNormalForm(T); } } return (M); } } return(T); } example { "EXAMPLE:"; echo=2; ring R = 0, (x, y, z), dp; // Weights of variables intmat M[3][3] = 1, 0, 0, 0, 1, 0, 0, 0, 1; // Torsion: intmat L[3][2] = 1, 1, 1, 3, 1, 5; // attaches M & L to R (==basering): setBaseMultigrading(M, L); // Grading: Z^3/L // Torsion is accessible via "getLattice()": getLattice() == L; // its hermite NF: print(getLattice("hermite")); kill L, M; // ----------- isomorphic multigrading -------- // // Weights of variables intmat M[2][3] = 1, -2, 1, 1, 1, 0; // Torsion: intmat L[2][1] = 0, 2; // attaches M & L to R (==basering): setBaseMultigrading(M, L); // Grading: Z + (Z/2Z) // Torsion is accessible via "getLattice()": getLattice() == L; // its hermite NF: print(getLattice("hermite")); kill L, M; // ----------- extreme case ------------ // // Weights of variables intmat M[1][3] = 1, -1, 10; // Torsion: intmat L[1][1] = 0; // attaches M & L to R (==basering): setBaseMultigrading(M); // Grading: Z^3 // Torsion is accessible via "getLattice()": getLattice() == L; // its hermite NF: print(getLattice("hermite")); } proc getGradedGenerator(def m, int i) "USAGE: getGradedGenerator(M, i), 'M' module/ideal, 'i' int RETURN: returns the i-th generator of M, endowed with the module grading from M EXAMPLE: example getGradedGenerator; shows an example " { if( typeof(m) == "ideal" ) { return (m[i]); } if( typeof(m) == "module" ) { def v = getModuleGrading(m); return ( setModuleGrading(m[i],v) ); } ERROR("m is expected to be an ideal or a module"); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z,w),dp; intmat MM[2][4]= 1,1,1,1, 0,1,3,4; setBaseMultigrading(MM); module M = ideal( xw-yz, x2z-y3, xz2-y2w, yw2-z3); intmat v[2][nrows(M)]= 1, 0; M = setModuleGrading(M, v); isHomogeneous(M); "Multidegrees: "; print(multiDeg(M)); // Let's compute syzygies! def S = multiDegSyzygy(M); S; "Module Units Multigrading: "; print( getModuleGrading(S) ); "Multidegrees: "; print(multiDeg(S)); isHomogeneous(S); // same as S[1] together with the induced module weighting def v = getGradedGenerator(S, 1); print(v); print(setModuleGrading(v)); isHomogeneous(v); isHomogeneous(S[1]); } /******************************************************/ proc getModuleGrading(def m) "USAGE: getModuleGrading(m), 'm' module/vector RETURN: integer matrix of the multiweights of free module generators attached to 'm' EXAMPLE: example getModuleGrading; shows an example " { string attrModuleGrading = "genWeights"; // print(m); typeof(m); attrib(m); def V = attrib(m, attrModuleGrading); if( typeof(V) != "intmat" ) { if( (typeof(m) == "ideal") or (typeof(m) == "poly") ) { intmat M = getVariableWeights(); intmat VV[nrows(M)][1]; return (VV); } ERROR("Sorry: vector or module need module-grading-matrix! See 'getModuleGrading'."); } if( nrows(V) != nrows(getVariableWeights()) ) { ERROR("Sorry wrong height of V: " + string(nrows(V))); } if( ncols(V) < nrows(m) ) { ERROR("Sorry wrong width of V: " + string(ncols(V))); } return (V); } example { "EXAMPLE:"; echo=2; ring R = 0, (x,y), dp; intmat M[2][2]= 1, 1, 0, 2; intmat T[2][5]= 1, 2, 3, 4, 0, 0, 10, 20, 30, 1; setBaseMultigrading(M, T); ideal I = x, y, xy^5; isHomogeneous(I); intmat V = multiDeg(I); print(V); module S = syz(I); print(S); S = setModuleGrading(S, V); getModuleGrading(S) == V; vector v = getGradedGenerator(S, 1); getModuleGrading(v) == V; isHomogeneous(v); print( multiDeg(v) ); isHomogeneous(S); print( multiDeg(S) ); } /******************************************************/ proc setModuleGrading(def m, intmat G) "USAGE: setModuleGrading(m, G), m module/vector, G intmat PURPOSE: attaches the multiweights of free module generators to 'm' WARNING: The method does not verify whether the multigrading makes the module/vector homogeneous. One can do that using isHomogeneous(m). EXAMPLE: example setModuleGrading; shows an example " { string attrModuleGrading = "genWeights"; intmat R = getVariableWeights(); if(nrows(G) != nrows(R)){ ERROR("Incompatible gradings.");} if(ncols(G) < nrows(m)){ ERROR("Multigrading does not fit to module.");} attrib(m, attrModuleGrading, G); return(m); } example { "EXAMPLE:"; echo=2; ring R = 0, (x,y), dp; intmat M[2][2]= 1, 1, 0, 2; intmat T[2][5]= 1, 2, 3, 4, 0, 0, 10, 20, 30, 1; setBaseMultigrading(M, T); ideal I = x, y, xy^5; intmat V = multiDeg(I); // V == M; modulo T print(V); module S = syz(I); S = setModuleGrading(S, V); getModuleGrading(S) == V; print(S); vector v = getGradedGenerator(S, 1); getModuleGrading(v) == V; print( multiDeg(v) ); isHomogeneous(S); print( multiDeg(S) ); } proc multiDegTensor(module m, module n) " USAGE: multiDegTensor(m, n), m,n modules or matrices. PURPOSE: Computes the multigraded tensor product of to multigraded modules. RETURN: A module. EXAMPLE: example multiDegTensor; shows an example " { matrix M = m; matrix N = n; intmat gm = getModuleGrading(m); intmat gn = getModuleGrading(n); int grows = nrows(gm); int mr = nrows(M); int mc = ncols(M); if(rank(M) == 0){ mc = 0;} int nr = nrows(N); int nc = ncols(N); if(rank(N) == 0){ nc = 0;} intmat gresult[nrows(gm)][mr*nr]; matrix result[mr*nr][mr*nc+mc*nr]; int i, j; int column = 1; for(i = 1; i<=mr; i++){ for(j = 1; j<=nr; j++){ gresult[1..grows,(i-1)*nr+j] = gm[1..grows,i]+gn[1..grows,j]; } } //gresult; if( nc!=0 ){ for(i = 1; i<=mr; i++) { result[((i-1)*nr+1)..(i*nr),((i-1)*nc+1)..(i*nc)] = N[1..nr,1..nc]; } } list rownumbers, colnumbers; //print(result); if( mc!=0 ){ for(j = 1; j<=nr; j++) { rownumbers = nr*(0..(mr-1))+j*(1:mr); colnumbers = ((mr*nc+j):mc)+nr*(0..(mc-1)); result[rownumbers[1..mr],colnumbers[1..mc] ] = M[1..mr,1..mc]; } } module res = result; res = setModuleGrading(res, gresult); //getModuleGrading(res); return(res); } example { "EXAMPLE: ";echo=2; ring r = 0,(x),dp; intmat g[2][1]=1,1; setBaseMultigrading(g); matrix m[5][3]=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15; matrix n[3][2]=x,x2,x3,x4,x5,x6; module mm = m; module nn = n; intmat gm[2][5]=1,2,3,4,5,0,0,0,0,0; intmat gn[2][3]=0,0,0,1,2,3; mm = setModuleGrading(mm, gm); nn = setModuleGrading(nn, gn); module mmtnn = multiDegTensor(mm, nn); print(mmtnn); getModuleGrading(mmtnn); LIB "homolog.lib"; module tt = tensorMod(mm,nn); print(tt); kill m, mm, n, nn, gm, gn; matrix m[7][3] = x, x-1,x+2, 3x, 4x, x5, x6, x-7, x-8, 9, 10, 11x, 12 -x, 13x, 14x, x15, (x-4)^2, x17, 18x, 19x, 20x, 21x; matrix n[2][4] = 1, 2, 3, 4, x, x2, x3, x4; module mm = m; module nn = n; print(mm); print(nn); intmat gm[2][7] = 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0; intmat gn[2][2] = 0, 0, 1, 2; mm = setModuleGrading(mm, gm); nn = setModuleGrading(nn, gn); module mmtnn = multiDegTensor(mm, nn); print(mmtnn); getModuleGrading(mmtnn); matrix a = mmtnn; matrix b = tensorMod(mm, nn); print(a-b); } proc multiDegTor(int i, module m, module n) { def res = multiDegResolution(n, 0, 1); //print(res); list l = res; if(size(l) L2 RETURN: int, 1 if A defines the homomorphism and 0 otherwise EXAMPLE: example isGroupHomomorphism; shows an example " { // TODO: L1, L2 if( (ncols(A) != nrows(L1)) or (nrows(A) != nrows(L2)) ) { ERROR("Incompatible sizes!"); } intmat im = A * L1; return (areZeroElements(im, L2)); } example { "EXAMPLE:"; echo=2; intmat L1[4][1]= 0, 0, 0, 2; intmat L2[3][2]= 0, 0, 2, 0, 0, 3; intmat A[3][4] = 1, 2, 3, 0, 7, 0, 0, 0, 1, 2, 0, 3; print( A ); isGroupHomomorphism(L1, L2, A); intmat B[3][4] = 1, 2, 3, 0, 7, 0, 0, 0, 1, 2, 0, 2; print( B ); isGroupHomomorphism(L1, L2, B); // Not a homomorphism! } /******************************************************/ proc isTorsionFree() "USAGE: isTorsionFree() PURPOSE: Determines whether the multigrading attached to the current ring is free. RETURN: boolean, the result of the test EXAMPLE: example isTorsionFree; shows an example " { intmat H = smithNormalForm(getLattice()); // TODO: ?cache it? //****** int i, j; int r = nrows(H); int c = ncols(H); int d = 1; for( i = 1; (i <= c) && (i <= r); i++ ) { for( j = i; (H[j, i] == 0)&&(j < r); j++ ) { } if(H[j, i]!=0) { d=d*H[j, i]; } } if( (d*d)==1 ) { return(1==1); } return(0==1); } example { "EXAMPLE:"; echo=2; ring R = 0,(x,y),dp; intmat M[2][2]= 1,0, 0,1; intmat T[2][5]= 1, 2, 3, 4, 0, 0,10,20,30, 1; setBaseMultigrading(M,T); // Is the resulting group free? isTorsionFree(); kill R, M, T; /////////////////////////////////////////// ring R=0,(x,y,z),dp; intmat A[3][3] = 1,0,0, 0,1,0, 0,0,1; intmat B[3][4]= 3,3,3,3, 2,1,3,0, 1,2,0,3; setBaseMultigrading(A,B); // Is the resulting group free? isTorsionFree(); kill R, A, B; } static proc gcdcomb(int a, int b) { // a; // b; intvec av = a,1,0; intvec bv = b,0,1; intvec save; while(av[1]*bv[1] != 0) { bv = bv - (bv[1] - bv[1]%av[1]) div av[1] * av; save = bv; bv = av; av = save; } if(bv[1] < 0) { bv = -bv; } return(bv); } proc lll(def A) " The lll algorithm of NTL only works for intmat/matrix. This method will convert the input, call lll and return the result in the same format. (list of intvec resp. intmat) " { if(typeof(A) == "list") { int sizeA= size (A); if (sizeA == 0) { return (A); } if (typeof (A [1]) != "intvec") { ERROR("Unrecognized type."); } int columns= size (A [1]); int i; for (i= 2; i <= sizeA; i++) { if (typeof (A[i]) != "intvec") { ERROR("Unrecognized type."); } if (size (A [i]) != columns) { ERROR ("expected equal dimension"); } } int j; intmat m [columns] [sizeA]; for (i= 1; i <= sizeA; i++) { for (j= 1; j <= columns; j++) { m[i,j]= A[i] [j]; } } m= system ("LLL", m); list result; intvec buf; for (i= sizeA; i >=1 ; i--) { buf = intvec (m[i , 1..columns]); result[i]= buf; } return(result); } else { if(typeof(A) == "intmat") { A= system ("LLL", A); return(A); } else { ERROR("Unrecognized type."); } } } example { "EXAMPLE:"; echo=2; ring R = 0,x,dp; intmat m[5][5] = 13,25,37,83,294, 12,-33,9,0,64, 77,12,34,6,1, 43,2,88,91,100, -46,32,37,42,15; lll(m); list l = intvec(13,25,37, 83, 294), intvec(12, -33, 9,0,64), intvec (77,12,34,6,1), intvec (43,2,88,91,100), intvec (-46,32,37,42,15); lll(l); } proc smithNormalForm(intmat A, list #) "USAGE: smithNormalForm(A[,opt]); intmat A PURPOSE: Computes the Smith Normal Form of A RETURN: if no optional argument is given: intmat, the Smith Normal Form of A, otherwise: a list of 3 integer matrices P, D Q, such that D == P*A*Q. EXAMPLE: example smithNormalForm; shows an example " { list l1 = hermiteNormalForm(A, 5); // l1; intmat B = transpose(l1[1]); list l2 = hermiteNormalForm(B, 5); // l2; intmat P = transpose(l2[2]); intmat D = transpose(l2[1]); intmat Q = l1[2]; int cc = ncols(D); int rr = nrows(D); intmat transform; int k = 1; int a, b, c; // D; intvec v; if((cc==1)||(rr==1)){ if(size(#)==0) { return(D); } else { return(list(P,D,Q)); } } while(D[k+1,k+1] !=0){ if(D[k+1,k+1]%D[k,k]!=0){ b = D[k, k]; c = D[k+1, k+1]; v = gcdcomb(D[k,k],D[k+1,k+1]); transform = unitMatrix(cc); transform[k+1,k] = 1; a = -v[3]*D[k+1,k+1] div v[1]; transform[k, k+1] = a; transform[k+1, k+1] = a+1; //det(transform); D = D*transform; Q = Q*transform; //D; transform = unitMatrix(rr); transform[k,k] = v[2]; transform[k,k+1] = v[3]; transform[k+1,k] = -c div v[1]; transform[k+1,k+1] = b div v[1]; D = transform * D; P = transform * P; //" "; //D; //"small transform: ", det(transform); //transform; k=0; } k++; if((k==rr) || (k==cc)){ break; } } //"here is the size ",size(#); if(size(#) == 0){ return(D); } else { return(list(P, D, Q)); } } example { "EXAMPLE:"; echo=2; intmat A[5][7] = 1,0,1,0,-2,9,-71, 0,-24,248,-32,-96,448,-3496, 0,4,-42,4,-8,30,-260, 0,0,0,18,-90,408,-3168, 0,0,0,-32,224,-1008,7872; print( smithNormalForm(A) ); list l = smithNormalForm(A, 5); l; l[1]*A*l[3]; det(l[1]); det(l[3]); } /******************************************************/ proc hermiteNormalForm(intmat A, list #) "USAGE: hermiteNormalForm( A ); PURPOSE: Computes the (lower triangular) Hermite Normal Form of the matrix A by column operations. RETURN: intmat, the Hermite Normal Form of A EXAMPLE: example hermiteNormalForm; shows an example " { int row, column, i, j; int rr = nrows(A); int cc = ncols(A); intvec savev, gcdvec, v1, v2; intmat q = unitMatrix(cc); intmat transform; column = 1; for(row = 1; (row<=rr)&&(column<=cc); row++) { if(A[row,column]==0) { for(j = column; j<=cc; j++) { if(A[row, j]!=0) { transform = unitMatrix(cc); transform[j,j] = 0; transform[column, column] = 0; transform[column,j] = 1; transform[j,column] = 1; q = q*transform; A = A*transform; break; } } } if(A[row,column] == 0) { row++; continue; } for(j = column+1; j<=cc; j++) { if(A[row, j]!=0) { gcdvec = gcdcomb(A[row,column],A[row,j]); // gcdvec; // typeof(A[1..rr,column]); v1 = A[1..rr,column]; v2 = A[1..rr,j]; transform = unitMatrix(cc); transform[j,j] = v1[row] div gcdvec[1]; transform[column, column] = gcdvec[2]; transform[column,j] = -v2[row] div gcdvec[1]; transform[j,column] = gcdvec[3]; q = q*transform; A = A*transform; // A; } } if(A[row,column]<0) { transform = unitMatrix(cc); transform[column,column] = -1; q = q*transform; A = A*transform; } for( j=1; j 0){ return(list(A, q)); } return(A); } example { "EXAMPLE:"; echo=2; intmat M[2][5] = 1, 2, 3, 4, 0, 0,10,20,30, 1; // Hermite Normal Form of M: print(hermiteNormalForm(M)); intmat T[3][4] = 3,3,3,3, 2,1,3,0, 1,2,0,3; // Hermite Normal Form of T: print(hermiteNormalForm(T)); intmat A[4][5] = 1,2,3,2,2, 1,2,3,4,0, 0,5,4,2,1, 3,2,4,0,2; // Hermite Normal Form of A: print(hermiteNormalForm(A)); } proc areZeroElements(intmat m, list #) "USAGE: areZeroElements(D, [T]); intmat D, group T PURPOSE: For a integer matrix D, considered column-wise as a set of integer vecors representing the multidegree of some polynomial or vector this method checks whether all these multidegrees are contained in the grading group group (either set globally or given as an optional argument), i.e. if they all are zero in the multigrading. EXAMPLE: example areZeroElements; shows an example " { int r = nrows(m); int i = ncols(m); intvec v; for( ; i > 0; i-- ) { v = m[1..r, i]; if( !isZeroElement(v, #) ) { return (0); } } return(1); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z),dp; intmat S[2][3]= 1,0,1, 0,1,1; intmat L[2][1]= 2, 2; setBaseMultigrading(S,L); poly a = 1; poly b = xyz; ideal I = a, b; print(multiDeg(I)); intmat m[5][2]=multiDeg(a),multiDeg(b); m=transpose(m); print(multiDeg(a)); print(multiDeg(b)); print(m); areZeroElements(m); intmat LL[2][1]= 1, -1; areZeroElements(m,LL); } /******************************************************/ proc isZeroElement(intvec mdeg, list #) "USAGE: isZeroElement(d, [T]); intvec d, group T PURPOSE: For a integer vector 'd' representing the multidegree of some polynomial or vector this method computes if the multidegree is contained in the grading group group (either set globally or given as an optional argument), i.e. if it is zero in the multigrading. EXAMPLE: example isZeroElement; shows an example " { int i = 1; if( size(#) >= i ) { def a = #[1]; if( typeof(a) == "intmat" ) { intmat H = hermiteNormalForm(a); i++; } if( typeof(a) == "list" ) { list L = a; intmat H = attrib(L, "hermite"); // todo i++; } kill a; } if( i == 1 ) { intmat H = getLattice("hermite"); } int x, k, row; int r = nrows(H); int c = ncols(H); int rr = nrows(mdeg); row = 1; intvec v; for(i=1; (i<=r)&&(row<=r)&&(i<=c); i++) { while((H[row,i]==0)&&(row<=r)) { row++; if(row == (r+1)){ break; } } if(row<=r){ if(H[row,i]!=0) { v = H[1..r,i]; mdeg = mdeg-(mdeg[row]-mdeg[row]%v[row]) div v[row]*v; } } } return( mdeg == 0 ); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z),dp; intmat g[2][3]= 1,0,1, 0,1,1; intmat t[2][1]= -2, 1; intmat tt[2][1]= 1, -1; setBaseMultigrading(g,t); poly a = x10yz; poly b = x8y2z; poly c = x4z2; poly d = y5; poly e = x2y2; poly f = z2; intvec v1 = multiDeg(a) - multiDeg(b); v1; isZeroElement(v1); isZeroElement(v1, tt); intvec v2 = multiDeg(a) - multiDeg(c); v2; isZeroElement(v2); isZeroElement(v2, tt); intvec v3 = multiDeg(e) - multiDeg(f); v3; isZeroElement(v3); isZeroElement(v3, tt); intvec v4 = multiDeg(c) - multiDeg(d); v4; isZeroElement(v4); isZeroElement(v4, tt); } /******************************************************/ proc defineHomogeneous(poly f, list #) "USAGE: defineHomogeneous(f[, G]); polynomial f, integer matrix G PURPOSE: Yields a matrix which has to be appended to the grading group matrix to make the polynomial f homogeneous in the grading by grad. EXAMPLE: example defineHomogeneous; shows an example " { int i = 1; if( size(#) >= i ) { def a = #[1]; if( typeof(a) == "intmat" ) { intmat grad = a; i++; } kill a; } if( i == 1 ) { intmat grad = getVariableWeights(); } intmat newgg[nrows(grad)][size(f)-1]; int j; intvec l = grad*leadexp(f); intvec v; for(i=2; i <= size(f); i++) { v = grad * leadexp(f[i]) - l; for( j=1; j<=size(v); j++) { newgg[j,i-1] = v[j]; } } return(newgg); } example { "EXAMPLE:"; echo=2; ring r =0,(x,y,z),dp; intmat grad[2][3] = 1,0,1, 0,1,1; setBaseMultigrading(grad); poly f = x2y3-z5+x-3zx; intmat M = defineHomogeneous(f); M; defineHomogeneous(f, grad) == M; isHomogeneous(f); setBaseMultigrading(grad, M); isHomogeneous(f); } proc gradiator(def h) "PURPOSE: coarsens the grading of the basering until the polynom or ideal h becomes homogeneous." { if(typeof(h)=="poly"){ intmat W = getVariableWeights(); intmat L = getLattice(); intmat toadd = defineHomogeneous(h); //h; //toadd; if(ncols(toadd) == 0) { return(1==1); } int rr = nrows(W); intmat newL[rr][ncols(L)+ncols(toadd)]; newL[1..rr,1..ncols(L)] = L[1..rr,1..ncols(L)]; newL[1..rr,(ncols(L)+1)..(ncols(L)+ncols(toadd))] = toadd[1..rr,1..ncols(toadd)]; setBaseMultigrading(W,newL); return(1==1); } if(typeof(h)=="ideal"){ int i; def s = (1==1); for(i=1;i<=size(h);i++){ s = s && gradiator(h[i]); } return(s); } return(1==0); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z),dp; intmat g[2][3] = 1,0,1,0,1,1; intmat l[2][1] = 3,0; setBaseMultigrading(g,l); getLattice(); ideal i = -y5+x4, y6+xz, x2y; gradiator(i); getLattice(); isHomogeneous(i); } proc pushForward(map f) "USAGE: pushForward(f); PURPOSE: Computes the finest grading of the image ring which makes the map f a map of graded rings. The group map between the two grading groups is given by transpose( (Id, 0) ). Pay attention that the group spanned by the columns of the grading group matrix may not be a subgroup of the grading group. Still all columns are needed to find the correct image of the preimage gradings. EXAMPLE: example pushForward; shows an example " { int k,i,j; // f; // listvar(); def pre = preimage(f); // "pre: "; pre; intmat oldgrad=getVariableWeights(pre); intmat oldlat=getLattice(pre); int n=nvars(pre); int np=nvars(basering); int p=nrows(oldgrad); int pp=p+np; intmat newgrad[pp][np]; //This will set the finest grading on the image ring. We will proceed by coarsening this grading until f becomes homogeneous. for(i=1;i<=np;i++){ newgrad[p+i,i]=1;} //newgrad; list newlat; intmat toadd; int columns=0; intmat toadd1[pp][n]; intvec v; poly im; for(i=1;i<=p;i++){ for(j=1;j<=n;j++){ toadd1[i,j]=oldgrad[i,j];} } // This will make the images of homogeneous elements homogeneous, namely the variables of the preimage ring. for(i=1;i<=n;i++){ im=f[i]; //im; toadd = defineHomogeneous(im, newgrad); newlat=insert(newlat,toadd); columns=columns+ncols(toadd); v=leadexp(f[i]); for(j=p+1;j<=p+np;j++){ toadd1[j,i]=-v[j-p];} } newlat=insert(newlat,toadd1); columns=columns+ncols(toadd1); //If the image ring is a quotient ring by some ideal, we have to coarsen the grading in order to make the ideal homogeneous. if(size(ideal(basering))>0) { //"Entering qring"; ideal a=ideal(basering); for(i=1;i<=size(a);i++){ toadd = defineHomogeneous(a[i], newgrad); //toadd; columns=columns+ncols(toadd); newlat=insert(newlat,toadd); } } //The grading group of the preimage ring might not have been torsion free. We have to add this torsion to the grading group of the image ring. intmat imofoldlat[pp][ncols(oldlat)]; for(i=1; i<=nrows(oldlat);i++){ for(j=1; j<=ncols(oldlat); j++){ imofoldlat[i,j]=oldlat[i,j]; } } columns=columns+ncols(oldlat); newlat=insert(newlat, imofoldlat); intmat gragr[pp][columns]; columns=0; for(k=1;k<=size(newlat);k++){ for(i=1;i<=pp;i++){ for(j=1;j<=ncols(newlat[k]);j++){gragr[i,j+columns]=newlat[k][i,j];} } columns=columns+ncols(newlat[k]); } //The following is just for reducing the size of the matrices. gragr=hermiteNormalForm(gragr); intmat result[pp][pp]; for(i=1;i<=pp;i++){ for(j=1;j<=pp;j++){result[i,j]=gragr[i,j];} } setBaseMultigrading(newgrad, result); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z),dp; // Setting degrees for preimage ring.; intmat grad[3][3] = 1,0,0, 0,1,0, 0,0,1; setBaseMultigrading(grad); // grading on r: getVariableWeights(); getLattice(); // only for the purpose of this example if( voice > 1 ){ /*keepring(r);*/ export(r); } ring R = 0,(a,b),dp; ideal i = a2-b2+a6-b5+ab3,a7b+b15-ab6+a6b6; // The quotient ring by this ideal will become our image ring.; qring Q = std(i); listvar(); map f = r,-a2b6+b5+a3b+a2+ab,-a2b7-3a2b5+b4+a,a6-b6-b3+a2; f; // TODO: Unfortunately this is not a very spectacular example...: // Pushing forward f: pushForward(f); // due to pushForward we have got new grading on Q getVariableWeights(); getLattice(); // only for the purpose of this example if( voice > 1 ){ kill r; } } /******************************************************/ proc equalMultiDeg(intvec exp1, intvec exp2, list #) "USAGE: equalMultiDeg(exp1, exp2[, V]); intvec exp1, exp2, intmat V PURPOSE: Tests if the exponent vectors of two monomials (given by exp1 and exp2) represent the same multidegree. NOTE: the integer matrix V encodes multidegrees of module components, if module component is present in exp1 and exp2 EXAMPLE: example equalMultiDeg; shows an example " { if( size(exp1) != size(exp2) ) { ERROR("Sorry: we cannot compare exponents comming from a polynomial and a vector yet!"); } if( exp1 == exp2) { return (1==1); } intmat M = getVariableWeights(); if( nrows(exp1) > ncols(M) ) // vectors => last exponent is the module component! { if( (size(#) == 0) or (typeof(#[1])!="intmat") ) { ERROR("Sorry: wrong or missing module-unit-weights-matrix V!"); } intmat V = #[1]; // typeof(V); print(V); int N = ncols(M); int r = nrows(M); intvec d = intvec(exp1[1..N]) - intvec(exp2[1..N]); intvec dm = intvec(V[1..r, exp1[N+1]]) - intvec(V[1..r, exp2[N+1]]); intvec difference = M * d + dm; } else { intvec d = (exp1 - exp2); intvec difference = M * d; } if (isFreeRepresented()) // no grading group!? { return ( difference == 0); } return ( isZeroElement( difference ) ); } example { "EXAMPLE:"; echo=2;printlevel=3; ring r = 0,(x,y,z),dp; intmat g[2][3]= 1,0,1, 0,1,1; intmat t[2][1]= -2, 1; setBaseMultigrading(g,t); poly a = x10yz; poly b = x8y2z; poly c = x4z2; poly d = y5; poly e = x2y2; poly f = z2; equalMultiDeg(leadexp(a), leadexp(b)); equalMultiDeg(leadexp(a), leadexp(c)); equalMultiDeg(leadexp(a), leadexp(d)); equalMultiDeg(leadexp(a), leadexp(e)); equalMultiDeg(leadexp(a), leadexp(f)); equalMultiDeg(leadexp(b), leadexp(c)); equalMultiDeg(leadexp(b), leadexp(d)); equalMultiDeg(leadexp(b), leadexp(e)); equalMultiDeg(leadexp(b), leadexp(f)); equalMultiDeg(leadexp(c), leadexp(d)); equalMultiDeg(leadexp(c), leadexp(e)); equalMultiDeg(leadexp(c), leadexp(f)); equalMultiDeg(leadexp(d), leadexp(e)); equalMultiDeg(leadexp(d), leadexp(f)); equalMultiDeg(leadexp(e), leadexp(f)); } /******************************************************/ static proc isFreeRepresented() "check whether the base muligrading is free (it is zero). " { intmat T = getLattice(); intmat Z[nrows(T)][ncols(T)]; return (T == Z); // no grading group! } /******************************************************/ proc isHomogeneous(def a, list #) "USAGE: isHomogeneous(a[, f]); a polynomial/vector/ideal/module RETURN: boolean, TRUE if a is (multi)homogeneous, and FALSE otherwise EXAMPLE: example isHomogeneous; shows an example " { if( (typeof(a) == "poly") or (typeof(a) == "vector") ) { return ( size(multiDegPartition(a)) <= 1 ) } if( (typeof(a) == "ideal") or (typeof(a) == "module") ) { if(size(#) > 0) { if (#[1] == "checkGens") { def aa; for( int i = ncols(a); i > 0; i-- ) { aa = getGradedGenerator(a, i); if(!isHomogeneous(aa)) { return(0==1); } } return(1==1); } } def g = groebner(a); // !!!! def b, aa; int j; for( int i = ncols(a); i > 0; i-- ) { aa = getGradedGenerator(a, i); b = multiDegPartition(aa); for( j = ncols(b); j > 0; j-- ) { if(NF(b[j],g) != 0) { return(0==1); } } } return(1==1); } } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z),dp; //Grading and Torsion matrices: intmat M[3][3] = 1,0,0, 0,1,0, 0,0,1; intmat T[3][1] = 1,2,3; setBaseMultigrading(M,T); attrib(r); poly f = x-yz; multiDegPartition(f); print(multiDeg(_)); isHomogeneous(f); // f: is not homogeneous poly g = 1-xy2z3; isHomogeneous(g); // g: is homogeneous multiDegPartition(g); kill T; ///////////////////////////////////////////////////////// // new Torsion matrix: intmat T[3][4] = 3,3,3,3, 2,1,3,0, 1,2,0,3; setBaseMultigrading(M,T); f; isHomogeneous(f); multiDegPartition(f); // --------------------- g; isHomogeneous(g); multiDegPartition(g); kill r, T, M; ring R = 0, (x,y,z), dp; intmat A[2][3] = 0,0,1, 3,2,1; intmat T[2][1] = -1, 4; setBaseMultigrading(A, T); isHomogeneous(ideal(x2 - y3 -xy +z, x*y-z, x^3 - y^2*z + x^2 -y^3)); // 1 isHomogeneous(ideal(x2 - y3 -xy +z, x*y-z, x^3 - y^2*z + x^2 -y^3), "checkGens"); isHomogeneous(ideal(x+y, x2 - y2)); // 0 // Degree partition: multiDegPartition(x2 - y3 -xy +z); multiDegPartition(x3 -y2z + x2 -y3 + z + 1); module N = gen(1) + (x+y) * gen(2), z*gen(3); intmat V[2][3] = 0; // 1, 2, 3, 4, 5, 6; // column-wise weights of components!!?? vector v1, v2; v1 = setModuleGrading(N[1], V); v1; multiDegPartition(v1); print( multiDeg(_) ); v2 = setModuleGrading(N[2], V); v2; multiDegPartition(v2); print( multiDeg(_) ); N = setModuleGrading(N, V); isHomogeneous(N); print( multiDeg(N) ); /////////////////////////////////////// V = 1, 2, 3, 4, 5, 6; v1 = setModuleGrading(N[1], V); v1; multiDegPartition(v1); print( multiDeg(_) ); v2 = setModuleGrading(N[2], V); v2; multiDegPartition(v2); print( multiDeg(_) ); N = setModuleGrading(N, V); isHomogeneous(N); print( multiDeg(N) ); /////////////////////////////////////// V = 0, 0, 0, 4, 1, 0; N = gen(1) + x * gen(2), z*gen(3); N = setModuleGrading(N, V); print(N); isHomogeneous(N); print( multiDeg(N) ); v1 = getGradedGenerator(N,1); print(v1); multiDegPartition(v1); print( multiDeg(_) ); N = setModuleGrading(N, V); print(N); isHomogeneous(N); print( multiDeg(N) ); } /******************************************************/ proc multiDeg(def A) "USAGE: multiDeg(A); polynomial/vector/ideal/module A PURPOSE: compute multidegree EXAMPLE: example multiDeg; shows an example " { def a = attrib(A, "grad"); if( typeof(a) == "intvec" || typeof(a) == "intmat" ) { return (a); } intmat M = getVariableWeights(); int N = nvars(basering); if( ncols(M) != N ) { ERROR("Sorry wrong mgrad-size of M: " + string(ncols(M))); } int r = nrows(M); if( (typeof(A) == "vector") or (typeof(A) == "module") ) { intmat V = getModuleGrading(A); if( nrows(V) != r ) { ERROR("Sorry wrong mgrad-size of V: " + string(nrows(V))); } } if( A == 0 ) { intvec v; v[r] = 0; return (v); } intvec m; m[r] = 0; if( typeof(A) == "poly" ) { intvec v = leadexp(A); // v; m = M * v; // We assume homogeneous input! return(m); A = A - lead(A); while( size(A) > 0 ) { v = leadexp(A); // v; m = max( m, M * v, r ); // ???? A = A - lead(A); } return(m); } if( typeof(A) == "vector" ) { intvec v; v = leadexp(A); // v; m = intvec(M * intvec(v[1..N])) + intvec(V[1..r, v[N+1]]); // We assume homogeneous input! return(m); A = A - lead(A); while( size(A) > 0 ) { v = leadexp(A); // v; // intvec(M * intvec(v[1..N])) + intvec(V[1..r, v[N+1]]); m = max( m, intvec(M * intvec(v[1..N])) + intvec(V[1..r, v[N+1]]), r ); // ??? A = A - lead(A); } return(m); } int i, j; intvec d; if( typeof(A) == "ideal" ) { intmat G[ r ] [ ncols(A)]; for( i = ncols(A); i > 0; i-- ) { d = multiDeg( A[i] ); for( j = 1; j <= r; j++ ) // see ticket: 253 { G[j, i] = d[j]; } } return(G); } if( typeof(A) == "module" ) { intmat G[ r ] [ ncols(A)]; vector v; for( i = ncols(A); i > 0; i-- ) { v = getGradedGenerator(A, i); // G[1..r, i] d = multiDeg(v); for( j = 1; j <= r; j++ ) // see ticket: 253 { G[j, i] = d[j]; } } return(G); } } example { "EXAMPLE:"; echo=2; ring r = 0,(x, y), dp; intmat A[2][2] = 1, 0, 0, 1; print(A); intmat Ta[2][1] = 0, 3; print(Ta); // attrib(A, "gradingGroup", Ta); // to think about // "poly:"; setBaseMultigrading(A); multiDeg( x*x, A ); multiDeg( y*y*y, A ); setBaseMultigrading(A, Ta); multiDeg( x*x*y ); multiDeg( y*y*y*x ); multiDeg( x*y + x + 1 ); multiDegPartition(x*y + x + 1); print ( multiDeg(0) ); poly zero = 0; print ( multiDeg(zero) ); // "ideal:"; ideal I = y*x*x, x*y*y*y; print( multiDeg(I) ); print ( multiDeg(ideal(0)) ); print ( multiDeg(ideal(0,0,0)) ); // "vectors:"; intmat B[2][2] = 0, 1, 1, 0; print(B); multiDeg( setModuleGrading(y*y*y*gen(2), B )); multiDeg( setModuleGrading(x*x*gen(1), B )); vector V = x*gen(1) + y*gen(2); V = setModuleGrading(V, B); multiDeg( V ); vector v1 = setModuleGrading([0, 0, 0], B); print( multiDeg( v1 ) ); vector v2 = setModuleGrading([0], B); print( multiDeg( v2 ) ); // "module:"; module D = x*gen(1), y*gen(2); D; D = setModuleGrading(D, B); print( multiDeg( D ) ); module DD = [0, 0],[0, 0, 0]; DD = setModuleGrading(DD, B); print( multiDeg( DD ) ); module DDD = [0, 0]; DDD = setModuleGrading(DDD, B); print( multiDeg( DDD ) ); }; /******************************************************/ proc multiDegPartition(def p) "USAGE: multiDegPartition(def p), p polynomial/vector RETURNS: an ideal/module consisting of multigraded-homogeneous parts of p EXAMPLE: example multiDegPartition; shows an example " { // TODO: What about an ideal or module??? if( typeof(p) == "poly" ) { ideal I; poly mp, t, tt; intmat V; } else { if( typeof(p) == "vector" ) { module I; vector mp, t, tt; intmat V = getModuleGrading(p); } else { ERROR("Wrong ARGUMENT type!"); } } if( size(p) > 1) { intvec m; while( p != 0 ) { m = leadexp(p); mp = lead(p); p = p - lead(p); tt = p; t = 0; while( size(tt) > 0 ) { // TODO: we do not cache matrices (M,T,H,V), which remain the same :( // TODO: we need some low-level procedure with all these arguments...! if( equalMultiDeg( leadexp(tt), m, V ) ) { mp = mp + lead(tt); // "mp", mp; } else { t = t + lead(tt); // "t", t; } tt = tt - lead(tt); } I[size(I)+1] = mp; p = t; } } else { I[1] = p; // single monom } if( typeof(I) == "module" ) { I = setModuleGrading(I, V); } return (I); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z),dp; intmat g[2][3]= 1,0,1, 0,1,1; intmat t[2][1]= -2, 1; setBaseMultigrading(g,t); poly f = x10yz+x8y2z-x4z2+y5+x2y2-z2+x17z3-y6; multiDegPartition(f); vector v = xy*gen(1)-x3y2*gen(2)+x4y*gen(3); intmat B[2][3]=1,-1,-2,0,0,1; v = setModuleGrading(v,B); getModuleGrading(v); multiDegPartition(v, B); } /******************************************************/ static proc unitMatrix(int n) { intmat A[n][n]; for( int i = n; i > 0; i-- ) { A[i,i] = 1; } return (A); } /******************************************************/ static proc finestMDeg(def r) " USAGE: finestMDeg(r); ring r RETURN: ring, r endowed with the finest multigrading TODO: not yet... " { def save = basering; setring (r); // in basering ideal I = ideal(basering); int n = 0; int i; poly p; for( i = ncols(I); i > 0; i-- ) { p = I[i]; if( size(p) > 1 ) { n = n + (size(p) - 1); } else { I[i] = 0; } } int N = nvars(basering); intmat A = unitMatrix(N); if( n > 0) { intmat L[N][n]; // list L; int j = n; for( i = ncols(I); i > 0; i-- ) { p = I[i]; if( size(p) > 1 ) { intvec m0 = leadexp(p); p = p - lead(p); while( size(p) > 0 ) { L[ 1..N, j ] = leadexp(p) - m0; p = p - lead(p); j--; } } } print(L); setBaseMultigrading(A, L); } else { setBaseMultigrading(A); } // ERROR("nope"); // ring T = integer, (x), (C, dp); setring(save); return (r); } example { "EXAMPLE:"; echo=2; ring r = 0,(x, y), dp; qring q = std(x^2 - y); finestMDeg(q); } /******************************************************/ static proc newMap(map F, intmat Q, list #) " USAGE: newMap(F, Q[, P]); map F, intmat Q[, intmat P] PURPOSE: endowe the map F with the integer matrices P [and Q] " { attrib(F, "Q", Q); if( size(#) > 0 and typeof(#[1]) == "intmat" ) { attrib(F, "P", #[1]); } return (F); } /******************************************************/ static proc matrix2intmat( matrix M ) { execute( "intmat A[ "+ string(nrows(M)) + "]["+ string(ncols(M)) + "] = " + string(M) + ";" ); return (A); } /******************************************************/ static proc leftKernelZ(intmat M) "USAGE: leftKernel(M); M a matrix RETURN: module PURPOSE: computes left kernel of matrix M (a module of all elements v such that vM=0) EXAMPLE: example leftKernel; shows an example " { int @bf = 0; if( nameof(basering) != "basering" ) { @bf = 1; def @save@ = basering; } ring r = integer, (x), dp; // basering; module N = matrix((M)); // transpose // print(N); def MM = modulo( N, std(0) ) ; // print(MM); intmat R = ( matrix2intmat( MM ) ); // transpose if( @bf == 1 ) { setring @save@; } kill r; return( R ); } example { "EXAMPLE:"; echo=2; ring r= 0,(x,y,z),dp; matrix M[3][1] = x,y,z; print(M); matrix L = leftKernel(M); print(L); // check: print(L*M); }; /******************************************************/ // the following is taken from "sing4ti2.lib" as we need 'hilbert' from 4ti2 static proc hilbert4ti2intmat(intmat A, list #) "USAGE: hilbert4ti2(A[,i]); @* A=intmat @* i=int ASSUME: - A is a matrix with integer entries which describes the lattice @* as ker(A), if second argument is not present, and @* as the left image Im(A) = {zA : z \in ZZ^k}, if second argument is a positive integer @* - number of variables of basering equals number of columns of A @* (for ker(A)) resp. of rows of A (for Im(A)) CREATE: temporary files sing4ti2.mat, sing4ti2.lat, sing4ti2.mar @* in the current directory (I/O files for communication with 4ti2) NOTE: input rules for 4ti2 also apply to input to this procedure @* hence ker(A)={x|Ax=0} and Im(A)={xA} RETURN: toric ideal specified by Hilbert basis thereof EXAMPLE: example graver4ti2; shows an example " { if( system("sh","which hilbert 2> /dev/null 1> /dev/null") != 0 ) { ERROR("Sorry: cannot find 'hilbert' command from 4ti2. Please install 4ti2!"); } //-------------------------------------------------------------------------- // Initialization and Sanity Checks //-------------------------------------------------------------------------- int i,j; int nr=nrows(A); int nc=ncols(A); string fileending="mat"; if (size(#)!=0) { //--- default behaviour: use ker(A) as lattice //--- if #[1]!=0 use Im(A) as lattice if(typeof(#[1])!="int") { ERROR("optional parameter needs to be integer value"); } if(#[1]!=0) { fileending="lat"; } } //--- we should also be checking whether all entries are indeed integers //--- or whether there are fractions, but in this case the error message //--- of 4ti2 is printed directly //-------------------------------------------------------------------------- // preparing input file for 4ti2 //-------------------------------------------------------------------------- link eing=":w sing4ti2."+fileending; string eingstring=string(nr)+" "+string(nc); write(eing,eingstring); for(i=1;i<=nr;i++) { kill eingstring; string eingstring; for(j=1;j<=nc;j++) { // if(g(A[i,j])>0)||(char(basering)!=0)||(npars(basering)>0)) // { // ERROR("Input to hilbert4ti2 needs to be a matrix with integer entries"); // } eingstring=eingstring+string(A[i,j])+" "; } write(eing, eingstring); } close(eing); //---------------------------------------------------------------------- // calling 4ti2 and converting output // Singular's string is too clumsy for this, hence we first prepare // using standard unix commands //---------------------------------------------------------------------- j=system("sh","hilbert -q sing4ti2 >/dev/null 2>&1"); ////////// be quiet + no loggin!!! j=system("sh", "awk \'BEGIN{ORS=\",\";}{print $0;}\' sing4ti2.hil " + "| sed s/[\\\ \\\t\\\v\\\f]/,/g " + "| sed s/,+/,/g|sed s/,,/,/g " + "| sed s/,,/,/g " + "> sing4ti2.converted" ); //---------------------------------------------------------------------- // reading output of 4ti2 //---------------------------------------------------------------------- link ausg=":r sing4ti2.converted"; //--- last entry ideal(0) is used to tie the list to the basering //--- it will not be processed any further string s = read(ausg); if( defined(keepfiles) <= 0) { j=system("sh",("rm -f sing4ti2.hil sing4ti2.converted sing4ti2."+fileending)); } string ergstr = "intvec erglist = " + s + "0;"; execute(ergstr); // print(erglist); int Rnc = erglist[1]; int Rnr = erglist[2]; intmat R[Rnr][Rnc]; int k = 3; for(i=1;i<=Rnc;i++) { for(j=1;j<=Rnr;j++) { // "i: ", i, ", j: ", j, ", v: ", erglist[k]; R[j, i] = erglist[k]; k = k + 1; } } return (R); //--- get rid of leading entry 0; // toric=toric[2..ncols(toric)]; // return(toric); } // A nice example here is the 3x3 Magic Squares example { "EXAMPLE:"; echo=2; ring r=0,(x1,x2,x3,x4,x5,x6,x7,x8,x9),dp; intmat M[7][9]= 1, 1, 1, -1, -1, -1, 0, 0, 0, 1, 1, 1, 0, 0, 0,-1,-1,-1, 0, 1, 1, -1, 0, 0,-1, 0, 0, 1, 0, 1, 0, -1, 0, 0,-1, 0, 1, 1, 0, 0, 0, -1, 0, 0,-1, 0, 1, 1, 0, -1, 0, 0, 0,-1, 1, 1, 0, 0, -1, 0,-1, 0, 0; hilbert4ti2intmat(M); hermiteNormalForm(M); } ///////////////////////////////////////////////////////////////////////////// static proc getMonomByExponent(intvec exp) { int n = nvars(basering); if( nrows(exp) < n ) { n = nrows(exp); } poly m = 1; int e; for( int i = 1; i <= n; i++ ) { e = exp[i]; if( e < 0 ) { ERROR("Negative exponent!!!"); } m = m * (var(i)^e); } return (m); } /******************************************************/ proc multiDegBasis(intvec d) "USAGE: multiDegBasis(d), multidegree: intvec d ASSUME: current ring is multigraded, monomial ordering is global PURPOSE: compute all monomials of multidegree d EXAMPLE: example multiDegBasis; shows an example " { def R = basering; // setring R; intmat M = getVariableWeights(R); // print(M); int nr = nrows(M); int nc = ncols(M); intmat A[nr][nc+1]; A[1..nr, 1..nc] = M[1..nr, 1..nc]; //typeof(A[1..nr, nc+1]); if( nr==1) { A[1..nr, nc+1]=-d[1]; } else { A[1..nr, nc+1] = -d; } intmat T = getLattice(R); if( isFreeRepresented() ) { intmat B = hilbert4ti2intmat(A); // matrix B = unitMatrix(nrows(T)); } else { int n = ncols(T); nc = ncols(A); intmat AA[nr][nc + 2 * n]; AA[1..nr, 1.. nc] = A[1..nr, 1.. nc]; AA[1..nr, nc + (1.. n)] = T[1..nr, 1.. n]; AA[1..nr, nc + n + (1.. n)] = -T[1..nr, 1.. n]; // print ( AA ); intmat K = leftKernelZ(( AA ) ); // // print(K); intmat KK[nc][ncols(K)] = K[ 1.. nc, 1.. ncols(K) ]; // print(KK); // "!"; intmat B = hilbert4ti2intmat(transpose(KK), 1); // "!"; print(B); } // print(A); int i; int nnr = nrows(B); int nnc = ncols(B); ideal I, J; if(nnc==0){ I=0; return(I); } I[nnc] = 0; J[nnc] = 0; for( i = 1; i <= nnc; i++ ) { // "i: ", i; B[nnr, i]; if( B[nnr, i] == 1) { // intvec(B[1..nnr-1, i]); I[i] = getMonomByExponent(intvec(B[1..nnr-1, i])); } else { if( B[nnr, i] == 0) { // intvec(B[1..nnr-1, i]); J[i] = getMonomByExponent(intvec(B[1..nnr-1, i])); } } // I[i]; } ideal Q = (ideal(basering)); if ( size(Q) > 0 ) { I = NF( I, lead(Q) ); J = NF( J, lead(Q) ); // Global ordering!!! } I = simplify(I, 2); // d J = simplify(J, 2); // d attrib(I, "ZeroPart", J); return (I); // setring ; } example { "EXAMPLE:"; echo=2; ring R = 0, (x, y), dp; intmat g1[2][2]=1,0,0,1; intmat l[2][1]=2,0; intmat g2[2][2]=1,1,1,1; intvec v1=4,0; intvec v2=4,4; intmat g3[1][2]=1,1; setBaseMultigrading(g3); intvec v3=4:1; v3; multiDegBasis(v3); setBaseMultigrading(g1,l); multiDegBasis(v1); setBaseMultigrading(g2); multiDegBasis(v2); intmat M[2][2] = 1, -1, -1, 1; intvec d = -2, 2; setBaseMultigrading(M); multiDegBasis(d); attrib(_, "ZeroPart"); kill R, M, d; ring R = 0, (x, y, z), dp; intmat M[2][3] = 1, -2, 1, 1, 1, 0; intmat L[2][1] = 0, 2; intvec d = 4, 1; setBaseMultigrading(M, L); multiDegBasis(d); attrib(_, "ZeroPart"); kill R, M, d; ring R = 0, (x, y, z), dp; qring Q = std(ideal( y^6+ x*y^3*z-x^2*z^2 )); intmat M[2][3] = 1, 1, 2, 2, 1, 1; // intmat T[2][1] = 0, 2; setBaseMultigrading(M); // BUG???? intvec d = 6, 6; multiDegBasis(d); attrib(_, "ZeroPart"); kill R, Q, M, d; ring R = 0, (x, y, z), dp; qring Q = std(ideal( x*z^3 - y *z^6, x*y*z - x^4*y^2 )); intmat M[2][3] = 1, -2, 1, 1, 1, 0; intmat T[2][1] = 0, 2; intvec d = 4, 1; setBaseMultigrading(M, T); // BUG???? multiDegBasis(d); attrib(_, "ZeroPart"); } proc multiDegSyzygy(def I) "USAGE: multiDegSyzygy(I); I is a ideal or a module PURPOSE: computes the multigraded syzygy module of I RETURNS: module, the syzygy module of I NOTE: generators of I must be multigraded homogeneous EXAMPLE: example multiDegSyzygy; shows an example " { if( isHomogeneous(I, "checkGens") == 0) { ERROR ("Sorry: inhomogeneous input!"); } module S = syz(I); S = setModuleGrading(S, multiDeg(I)); return (S); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z,w),dp; intmat MM[2][4]= 1,1,1,1, 0,1,3,4; setBaseMultigrading(MM); module M = ideal( xw-yz, x2z-y3, xz2-y2w, yw2-z3); intmat v[2][nrows(M)]= 1, 0; M = setModuleGrading(M, v); isHomogeneous(M); "Multidegrees: "; print(multiDeg(M)); // Let's compute syzygies! def S = multiDegSyzygy(M); S; "Module Units Multigrading: "; print( getModuleGrading(S) ); "Multidegrees: "; print(multiDeg(S)); isHomogeneous(S); } proc multiDegModulo(def I, def J) "USAGE: multiDegModulo(I); I, J are ideals or modules PURPOSE: computes the multigraded 'modulo' module of I and J RETURNS: module, see 'modulo' command NOTE: I and J should have the same multigrading, and their generators must be multigraded homogeneous EXAMPLE: example multiDegModulo; shows an example " { if( (isHomogeneous(I, "checkGens") == 0) or (isHomogeneous(J, "checkGens") == 0) ) { ERROR ("Sorry: inhomogeneous input!"); } module K = modulo(I, J); K = setModuleGrading(K, multiDeg(I)); return (K); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z),dp; intmat MM[2][3]= -1,1,1, 0,1,3; setBaseMultigrading(MM); ideal h1 = x, y, z; ideal h2 = x; "Multidegrees: "; print(multiDeg(h1)); // Let's compute modulo(h1, h2): def K = multiDegModulo(h1, h2); K; "Module Units Multigrading: "; print( getModuleGrading(K) ); "Multidegrees: "; print(multiDeg(K)); isHomogeneous(K); } proc multiDegGroebner(def I) "USAGE: multiDegGroebner(I); I is a poly/vector/ideal/module PURPOSE: computes the multigraded standard/groebner basis of I NOTE: I must be multigraded homogeneous RETURNS: ideal/module, the computed basis EXAMPLE: example multiDegGroebner; shows an example " { if( isHomogeneous(I) == 0) { ERROR ("Sorry: inhomogeneous input!"); } def S = groebner(I); if( typeof(I) == "module" or typeof(I) == "vector" ) { S = setModuleGrading(S, getModuleGrading(I)); } return(S); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z,w),dp; intmat MM[2][4]= 1,1,1,1, 0,1,3,4; setBaseMultigrading(MM); module M = ideal( xw-yz, x2z-y3, xz2-y2w, yw2-z3); intmat v[2][nrows(M)]= 1, 0; M = setModuleGrading(M, v); ///////////////////////////////////////////////////////////////////////////// // GB: M = multiDegGroebner(M); M; "Module Units Multigrading: "; print( getModuleGrading(M) ); "Multidegrees: "; print(multiDeg(M)); isHomogeneous(M); ///////////////////////////////////////////////////////////////////////////// // Let's compute Syzygy! def S = multiDegSyzygy(M); S; "Module Units Multigrading: "; print( getModuleGrading(S) ); "Multidegrees: "; print(multiDeg(S)); isHomogeneous(S); ///////////////////////////////////////////////////////////////////////////// // GB: S = multiDegGroebner(S); S; "Module Units Multigrading: "; print( getModuleGrading(S) ); "Multidegrees: "; print(multiDeg(S)); isHomogeneous(S); } /******************************************************/ proc multiDegResolution(def I, int ll, list #) "USAGE: multiDegResolution(I,l,[f]); I is poly/vector/ideal/module; l,f are integers PURPOSE: computes the multigraded resolution of I of the length l, or the whole resolution if l is zero. Returns minimal resolution if an optional argument 1 is supplied NOTE: input must have multigraded-homogeneous generators. The returned list is truncated beginning with the first zero differential. RETURNS: list, the computed resolution EXAMPLE: example multiDegResolution; shows an example " { if( isHomogeneous(I, "checkGens") == 0) { ERROR ("Sorry: inhomogeneous input!"); } def R = res(I, ll, #); list L = R; int l = size(L); def V = getModuleGrading(I); if( (typeof(I) == "module") or (typeof(I) == "vector") ) { L[1] = setModuleGrading(L[1], V); } int i; for( i = 2; i <= l; i++ ) { if( size(L[i]) > 0 ) { L[i] = setModuleGrading( L[i], multiDeg(L[i-1]) ); } else { return (L[1..(i-1)]); } } return (L); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z,w),dp; intmat M[2][4]= 1,1,1,1, 0,1,3,4; setBaseMultigrading(M); module m= ideal( xw-yz, x2z-y3, xz2-y2w, yw2-z3); isHomogeneous(ideal( xw-yz, x2z-y3, xz2-y2w, yw2-z3), "checkGens"); ideal A = xw-yz, x2z-y3, xz2-y2w, yw2-z3; int j; for(j=1; j<=ncols(A); j++) { multiDegPartition(A[j]); } intmat v[2][1]= 1, 0; m = setModuleGrading(m, v); // Let's compute Syzygy! def S = multiDegSyzygy(m); S; "Module Units Multigrading: "; print( getModuleGrading(S) ); "Multidegrees: "; print(multiDeg(S)); ///////////////////////////////////////////////////////////////////////////// S = multiDegGroebner(S); S; "Module Units Multigrading: "; print( getModuleGrading(S) ); "Multidegrees: "; print(multiDeg(S)); ///////////////////////////////////////////////////////////////////////////// list L = multiDegResolution(m, 0, 1); for( j =1; j<=size(L); j++) { "----------------------------------- ", j, " -----------------------------"; L[j]; "Module Multigrading: "; print( getModuleGrading(L[j]) ); "Multigrading: "; print(multiDeg(L[j])); } ///////////////////////////////////////////////////////////////////////////// L = multiDegResolution(maxideal(1), 0, 1); for( j =1; j<=size(L); j++) { "----------------------------------- ", j, " -----------------------------"; L[j]; "Module Multigrading: "; print( getModuleGrading(L[j]) ); "Multigrading: "; print(multiDeg(L[j])); } kill v; def h = hilbertSeries(m); setring h; numerator1; factorize(numerator1); denominator1; factorize(denominator1); numerator2; factorize(numerator2); denominator2; factorize(denominator2); } /******************************************************/ proc hilbertSeries(def I) "USAGE: hilbertSeries(I); I is poly/vector/ideal/module PURPOSE: computes the multigraded Hilbert Series of I NOTE: input must have multigraded-homogeneous generators. Multigrading should be positive. RETURNS: a ring in variables t_(i), s_(i), with polynomials numerator1 and denominator1 and mutually prime numerator2 and denominator2, quotients of which give the series. EXAMPLE: example hilbertSeries; shows an example " { if( !isFreeRepresented() ) { "Things might happen, since we are not free."; //ERROR("SORRY: ONLY TORSION-FREE CASE (POSITIVE GRADING)"); } int i, j, k, v; intmat M = getVariableWeights(); int cc = ncols(M); int n = nrows(M); if( n == 0 ) { ERROR("Error: wrong Variable Weights?"); } list RES = multiDegResolution(I,0,1); int l = size(RES); list L; L[l + 1] = 0; if(typeof(I) == "ideal") { intmat zeros[n][1]; L[1] = zeros; } else { L[1] = getModuleGrading(RES[1]); } for( j = 1; j <= l; j++) { L[j + 1] = multiDeg(RES[j]); } l++; ring R = 0,(t_(1..n),s_(1..n)),dp; ideal units; for( i=n; i>=1; i--) { units[i] = (var(i) * var(n + i) - 1); } qring Q = std(units); // TODO: should not it be a quotient ring depending on Torsion??? // I am not sure about what to do in the torsion case, but since // we want to evaluate the polynomial at certain points to get // a dimension we need uniqueness for this. I think we would lose // this uniqueness if switching to this torsion ring. poly monom, summand, @numerator; poly @denominator = 1; for( i = 1; i <= cc; i++) { monom = 1; for( k = 1; k <= n; k++) { v = M[k,i]; if(v >= 0) { monom = monom * (var(k)^(v)); } else { monom = monom * (var(n+k)^(-v)); } } if( monom == 1) { ERROR("Multigrading not positive."); } @denominator = @denominator * (1 - monom); } for( j = 1; j<= l; j++) { summand = 0; M = L[j]; for( i = 1; i <= ncols(M); i++) { monom = 1; for( k = 1; k <= n; k++) { v = M[k,i]; if( v > 0 ) { monom = monom * (var(k)^v); } else { monom = monom * (var(n+k)^(-v)); } } summand = summand + monom; } @numerator = @numerator - (-1)^j * summand; } if( @denominator == 0 ) { ERROR("Multigrading not positive."); } poly denominator1 = @denominator; poly numerator1 = @numerator; export denominator1; export numerator1; if( @numerator != 0 ) { poly d = gcd(@denominator, @numerator); poly denominator2 = @denominator/d; poly numerator2 = @numerator/d; if( gcd(denominator2, numerator2) != 1 ) { ERROR("Sorry: gcd should be 1 (after dividing out gcd)! Something went wrong!"); } } else { poly denominator2 = @denominator; poly numerator2 = @numerator; } export denominator2; export numerator2; " ------------ "; "This proc returns a ring with polynomials called 'numerator1/2' and 'denominator1/2'!"; "They represent the first and the second Hilbert Series."; "The s_(i)-variables are defined to be the inverse of the t_(i)-variables."; " ------------ "; return(Q); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z,w),dp; intmat g[2][4]= 1,1,1,1, 0,1,3,4; setBaseMultigrading(g); module M = ideal(xw-yz, x2z-y3, xz2-y2w, yw2-z3); intmat V[2][1]= 1, 0; M = setModuleGrading(M, V); def h = hilbertSeries(M); setring h; factorize(numerator2); factorize(denominator2); kill g, h; setring r; intmat g[2][4]= 1,2,3,4, 0,0,5,8; setBaseMultigrading(g); ideal I = x^2, y, z^3; I = std(I); list L = multiDegResolution(I, 0, 1); for( int j = 1; j<=size(L); j++) { "----------------------------------- ", j, " -----------------------------"; L[j]; "Module Multigrading: "; print( getModuleGrading(L[j]) ); "Multigrading: "; print(multiDeg(L[j])); } multiDeg(I); def h = hilbertSeries(I); setring h; factorize(numerator2); factorize(denominator2); kill r, h, g, V; //////////////////////////////////////////////// ring R = 0,(x,y,z),dp; intmat W[2][3] = 1,1, 1, 0,0,-1; setBaseMultigrading(W); ideal I = x3y,yz2,y2z,z4; def h = hilbertSeries(I); setring h; factorize(numerator2); factorize(denominator2); kill R, W, h; //////////////////////////////////////////////// ring R = 0,(x,y,z,a,b,c),dp; intmat W[2][6] = 1,1, 1,1,1,1, 0,0,-1,0,0,0; setBaseMultigrading(W); ideal I = x3y,yz2,y2z,z4; def h = hilbertSeries(I); setring h; factorize(numerator2); factorize(denominator2); kill R, W, h; //////////////////////////////////////////////// // This is example 5.3.9. from Robbianos book. ring R = 0,(x,y,z,w),dp; intmat W[1][4] = 1,1, 1,1; setBaseMultigrading(W); ideal I = z3,y3zw2,x2y4w2xyz2; hilb(std(I)); def h = hilbertSeries(I); setring h; numerator1; denominator1; factorize(numerator2); factorize(denominator2); kill h; //////////////////////////////////////////////// setring R; ideal I2 = x2,y2,z2; I2; hilb(std(I2)); def h = hilbertSeries(I2); setring h; numerator1; denominator1; kill h; //////////////////////////////////////////////// setring R; W = 2,2,2,2; setBaseMultigrading(W); getVariableWeights(); intvec w = 2,2,2,2; hilb(std(I2), 1, w); kill w; def h = hilbertSeries(I2); setring h; numerator1; denominator1; kill h; kill R, W; //////////////////////////////////////////////// ring R = 0,(x),dp; intmat W[1][1] = 1; setBaseMultigrading(W); ideal I; I = 1; I; hilb(std(I)); def h = hilbertSeries(I); setring h; numerator1; denominator1; kill h; //////////////////////////////////////////////// setring R; I = x; I; hilb(std(I)); def h = hilbertSeries(I); setring h; numerator1; denominator1; kill h; //////////////////////////////////////////////// setring R; I = x^5; I; hilb(std(I)); hilb(std(I), 1); def h = hilbertSeries(I); setring h; numerator1; denominator1; kill h; //////////////////////////////////////////////// setring R; I = x^10; I; hilb(std(I)); def h = hilbertSeries(I); setring h; numerator1; denominator1; kill h; //////////////////////////////////////////////// setring R; module M = 1; M = setModuleGrading(M, W); hilb(std(M)); def h = hilbertSeries(M); setring h; numerator1; denominator1; kill h; //////////////////////////////////////////////// setring R; kill M; module M = x^5*gen(1); // intmat V[1][3] = 0; // TODO: this would lead to a wrong result!!!? intmat V[1][1] = 0; // all gen(i) of degree 0! M = setModuleGrading(M, V); hilb(std(M)); def h = hilbertSeries(M); setring h; numerator1; denominator1; kill h; //////////////////////////////////////////////// setring R; module N = x^5*gen(3); kill V; intmat V[1][3] = 0; // all gen(i) of degree 0! N = setModuleGrading(N, V); hilb(std(N)); def h = hilbertSeries(N); setring h; numerator1; denominator1; kill h; //////////////////////////////////////////////// setring R; module S = M + N; S = setModuleGrading(S, V); hilb(std(S)); def h = hilbertSeries(S); setring h; numerator1; denominator1; kill h; kill V; kill R, W; } static proc evalHilbertSeries(def h, intvec v) " TODO evaluate hilbert series h by substibuting v[i] for t_(i) (1/v[i] for s_(i)) return: int (h(v)) " { if( 2*size(v) != nvars(h) ) { ERROR("Wrong input/size!"); } setring h; if( defined(numerator2) and defined(denominator2) ) { poly n = numerator2; poly d = denominator2; } else { poly n = numerator1; poly d = denominator1; } int N = size(v); int i; number k; ideal V; for( i = N; i > 0; i -- ) { k = v[i]; V[i] = var(i) - k; } V = groebner(V); n = NF(n, V); d = NF(d, V); n; d; if( d == 0 ) { ERROR("Sorry: denominator is zero!"); } if( n == 0 ) { return (0); } poly g = gcd(n, d); if( g != leadcoef(g) ) { n = n / g; d = d / g; } n; d; for( i = N; i > 0; i -- ) { "i: ", i; n; d; k = v[i]; k; n = subst(n, var(i), k); d = subst(d, var(i), k); if( k != 0 ) { k = 1/k; n = subst(n, var(N+i), k); d = subst(d, var(N+i), k); } } n; d; if( d == 0 ) { ERROR("Sorry: denominator is zero!"); } if( n == 0 ) { return (0); } poly g = gcd(n, d); if( g != leadcoef(g) ) { n = n / g; d = d / g; } n; d; if( n != leadcoef(n) || d != leadcoef(d) ) { ERROR("Sorry cannot completely evaluate. Partial result: (" + string(n) + ")/(" + string(d) + ")"); } n; d; return (leadcoef(n)/leadcoef(d)); } example { "EXAMPLE:"; echo=2; // TODO! } proc isPositive() "USAGE: isPositive() PURPOSE: Computes whether the multigrading of the ring is positive. For computation theorem 8.6 of the Miller/Sturmfels book is used. RETURNS: true if the multigrading is positive EXAMPLE: example isPositive; shows an example " { ideal I = multiDegBasis(0); ideal J = attrib(I,"ZeroPart"); /* I am not quite sure what this ZeroPart is anymore. I thought it should contain all monomials of degree 0, but then apparently 1 should be contained. It makes sense to exclude 1, but was this also the intention? */ return(J==0); } example { echo = 2; printlevel = 3; ring r = 0,(x,y),dp; intmat A[1][2]=-1,1; setBaseMultigrading(A); isPositive(); intmat B[1][2]=1,1; setBaseMultigrading(B); isPositive(B); } /////////////////////////////////////////////////////////////////////////////// // testing for consistency of the library: proc testMultigradingLib () { example setBaseMultigrading; example setModuleGrading; example getVariableWeights; example getLattice; example getGradingGroup; example getModuleGrading; example multiDeg; example multiDegPartition; example hermiteNormalForm; example isHomogeneous; example isTorsionFree; example pushForward; example defineHomogeneous; example equalMultiDeg; example isZeroElement; example multiDegResolution; "// ******************* example hilbertSeries ************************//"; example hilbertSeries; // example multiDegBasis; // needs 4ti2! "The End!"; } static proc multiDegTruncate(def M, intvec md) { "d: "; print(md); "M: "; module LL = M; // + L for d+1 LL; print(multiDeg(LL)); intmat V = getModuleGrading(M); intvec vi; int s = nrows(M); int r = nrows(V); int i; module L; def B; for (i=s; i>0; i--) { "comp: ", i; vi = V[1..r, i]; "v[i]: "; vi; B = multiDegBasis(md - vi); // ZeroPart is always the same... "B: "; B; L = L, B*gen(i); } L = simplify(L, 2); L = setModuleGrading(L,V); "L: "; L; print(multiDeg(L)); L = multiDegModulo(L, LL); L = multiDegGroebner(L); // L = minbase(prune(L)); "??????????"; print(L); print(multiDeg(L)); V = getModuleGrading(L); // take out other degrees for(i = ncols(L); i > 0; i-- ) { if( !equalMultiDeg( multiDeg(getGradedGenerator(L, i)), md ) ) { L[i] = 0; } } L = simplify(L, 2); L = setModuleGrading(L, V); print(L); print(multiDeg(L)); return(L); } example { "EXAMPLE:"; echo=2; // TODO! ring r = 32003, (x,y), dp; intmat M[2][2] = 1, 0, 0, 1; setBaseMultigrading(M); intmat V[2][1] = 0, 0; "X:"; module h1 = x; h1 = setModuleGrading(h1, V); multiDegTruncate(h1, multiDeg(x)); multiDegTruncate(h1, multiDeg(y)); "XY:"; module h2 = ideal(x, y); h2 = setModuleGrading(h2, V); multiDegTruncate(h2, multiDeg(x)); multiDegTruncate(h2, multiDeg(y)); multiDegTruncate(h2, multiDeg(xy)); } /******************************************************/ /* Some functions on lattices. TODO Tuebingen: - add functionality (see wiki) and - adjust them to work for groups as well.*/ /******************************************************/ /******************************************************/ proc imageLattice(intmat Q, intmat L) "USAGE: imageLattice(Q,L); Q and L are of type intmat PURPOSE: compute an integral basis for the image of the lattice L under the homomorphism of lattices Q. RETURN: intmat EXAMPLE: example imageLattice; shows an example " { intmat Mul = Q*L; intmat LL = latticeBasis(Mul); return(LL); } example { "EXAMPLE:"; echo=2; intmat Q[2][3] = 1,2,3, 3,2,1; intmat L[3][2] = 1,4, 2,5, 3,6; // should be a 2x2 matrix with columns // [2,-14], [0,36] imageLattice(Q,L); } /******************************************************/ proc intRank(intmat A) "USAGE: intRank(A); intmat A PURPOSE: compute the rank of the integral matrix A by computing a hermite normalform. RETURNS: int EXAMPLE: example intRank; shows an example " { intmat B = hermiteNormalForm(A); // get number of zero columns int nzerocols = 0; int j; int i; int iszero; for ( j = 1; j <= ncols(B); j++ ) { iszero = 1; for ( i = 1; i <= nrows(B); i++ ) { if ( B[i,j] != 0 ) { iszero = 0; break; } } if ( iszero == 1 ) { nzerocols++; } } // get number of zero rows int nzerorows = 0; for ( i = 1; i <= nrows(B); i++ ) { iszero = 1; for ( j = 1; j <= ncols(B); j++ ) { if ( B[i,j] != 0 ) { iszero = 0; break; } } if ( iszero == 1 ) { nzerorows++; } } int r = nrows(B) - nzerorows; if ( ncols(B) - nzerocols < r ) { r = ncols(B) - nzerocols; } return(r); } example { "EXAMPLE:"; echo=2; intmat A[3][4] = 1,0,1,0, 1,2,0,0, 0,0,0,0; int r = intRank(A); print(A); print(r); // Should be 2 // another example intmat B[2][2] = 1,2, 1,2; int d = intRank(B); print(B); print(d); // Should be 1 kill A, B, r, d; } /*****************************************************/ proc isSublattice(intmat L, intmat S) "USAGE: isSublattice(L, S); L, S are of tpye intmat PURPOSE: checks whether the lattice created by L is a sublattice of the lattice created by S. The procedure checks whether each generator of L is contained in S. RETURN: integer, 0 if false, 1 if true EXAMPLE: example isSublattice; shows an example " { int a,b,g,i,j,k; intmat Ker; // check whether each column v of L is contained in // the lattice generated by S for ( i = 1; i <= ncols(L); i++ ) { // v is the i-th column of L intvec v; for ( j = 1; j <= nrows(L); j++ ) { v[j] = L[j,i]; } // concatenate B = [S,v] intmat B[nrows(L)][ncols(S) + 1]; for ( a = 1; a <= nrows(S); a++ ) { for ( b = 1; b <= ncols(S); b++ ) { B[a,b] = S[a,b]; } } for ( a = 1; a <= size(v); a++ ) { B[a,ncols(B)] = v[a]; } // check gcd Ker = kernelLattice(B); k = nrows(Ker); list R; // R is the last row for ( j = 1; j <= ncols(Ker); j++ ) { R[j] = Ker[k,j]; } g = R[1]; for ( j = 2; j <= size(R); j++ ) { g = gcd(g,R[j]); } if ( g != 1 and g != -1 ) { return(0); } kill B, v, R; } return(1); } example { "EXAMPLE:"; echo=2; //ring R = 0,(x,y),dp; intmat S2[3][3]= 0, 2, 3, 0, 1, 1, 3, 0, 2; intmat S1[3][2]= 0, 6, 0, 2, 3, 4; isSublattice(S1,S2); // Yes! intmat S3[3][1] = 0, 0, 1; not(isSublattice(S3,S2)); // Yes! } /******************************************************/ proc latticeBasis(intmat B) "USAGE: latticeBasis(B); intmat B PURPOSE: compute an integral basis for the lattice defined by the columns of B. RETURNS: intmat EXAMPLE: example latticeBasis; shows an example " { int n = ncols(B); int r = intRank(B); if ( r == 0 ) { intmat H[nrows(B)][1]; int j; for ( j = 1; j <= nrows(B); j++ ) { H[j,1] = 0; } } else { intmat H = hermiteNormalForm(B);; if (r < n) { // delete columns r+1 to n // should be identical with the function // H = submat(H,1..nrows(H),1..r); // for matrices intmat Hdel[nrows(H)][r]; int k; int m; for ( k = 1; k <= nrows(H); k++ ) { for ( m = 1; m <= r; m++ ) { Hdel[k,m] = H[k,m]; } } H = Hdel; } } return(H); } example { "EXAMPLE:"; echo=2; intmat L[3][3] = 1,4,8, 2,5,10, 3,6,12; intmat B = latticeBasis(L); print(B); // should result in a matrix whose columns generate the same lattice as [1,2,3] and [0,3,6]: // another example intmat C[2][4] = 1,1,2,0, 2,3,4,0; // should result in a matrix whose // colums create the same lattice as // [0,1],[1,0] intmat D = latticeBasis(C); print(D); kill B,L; } /******************************************************/ proc kernelLattice(def P) "USAGE: kernelLattice(P); intmat P PURPOSE: compute a integral basis for the kernel of the homomorphism of lattices defined by the intmat P. RETURNS: intmat EXAMPLE: example kernelLattice; shows an example " { int n = ncols(P); int r = intRank(P); if ( r == 0 ) { intmat U = unitMatrix(n); } else { if ( r == n ) { intmat U[n][1]; // now all entries are zero. } else { list L = hermiteNormalForm(P, "transform"); //hermite(P, "transform"); // now, Hermite = L[1] = A*L[2] intmat U = L[2]; // delete columns 1 to r // should be identical with the function // U = submat(U,1..nrows(U),r+1..); // for matrices intmat Udel[nrows(U)][ncols(U) - r]; int k; int m; for ( k = 1; k <= nrows(U); k++ ) { for ( m = r + 1; m <= ncols(U); m++ ) { Udel[k,m - r] = U[k,m]; } } U = Udel; } } return(U); } example { "EXAMPLE"; echo = 2; intmat LL[3][4] = 1,4,7,10, 2,5,8,11, 3,6,9,12; // should be a 4x2 matrix whose columns // generate the same lattice as [-1,2,-1,0],[2,-3,0,1] intmat B = kernelLattice(LL); print(B); // another example intmat C[2][4] = 1,0,2,0, 0,1,2,0; // should result in a matrix whose // colums create the same lattice as // [-2,-2,1,0], [0,0,0,1] intmat D = kernelLattice(C); print(D); kill B; } /*****************************************************/ proc preimageLattice(def P, def B) " USAGE: preimageLattice(P, B); intmat P, intmat B PURPOSE: compute an integral basis for the preimage of B under the homomorphism of lattices defined by the intmat P. RETURNS: intmat EXAMPLE: example preimageLattice; shows an example " { // concatenate matrices: Con = [P,-B] intmat Con[nrows(P)][ncols(P) + ncols(B)]; int i; int j; for ( i = 1; i <= nrows(Con); i++ ) { for ( j = 1; j <= ncols(P); j++ ) // P first { Con[i,j] = P[i,j]; } } for ( i = 1; i <= nrows(Con); i++ ) { for ( j = 1; j <= ncols(B); j++ ) // now -B { Con[i,ncols(P) + j] = - B[i,j]; } } intmat L = kernelLattice(Con); // delete rows ncols(P)+1 to nrows(L) out of L intmat Del[ncols(P)][ncols(L)]; int k; int m; for ( k = 1; k <= nrows(Del); k++ ) { for ( m = 1; m <= ncols(Del); m++ ) { Del[k,m] = L[k,m]; } } L = latticeBasis(Del); return(L); } example { "EXAMPLE"; echo = 2; intmat P[2][3] = 2,6,10, 4,8,12; intmat B[2][1] = 1, 0; // should be a (3x2)-matrix with columns e.g. [1,1,-1] and [0,3,-2] (the generated lattice should be identical) print(preimageLattice(P,B)); // another example intmat W[3][3] = 1,0,0, 0,1,1, 0,2,0; intmat Z[3][2] = 1,0, 0,1, 0,0; // should be a (3x2)-matrix with columns e.g. [1,0,0] and [0,0,-1] (the generated lattice should be identical) print(preimageLattice(W,Z)); } /******************************************************/ proc isPrimitiveSublattice(intmat A); "USAGE: isPrimitiveSublattice(A); intmat A PURPOSE: check whether the given set of integral vectors in ZZ^m, i.e. the columns of A, generate a primitive sublattice in ZZ^m (a direct summand of ZZ^m). RETURNS: int, where 0 is false and 1 is true. EXAMPLE: example isPrimitiveSublattice; shows an example " { intmat B = smithNormalForm(A); int r = intRank(B); if ( r == 0 ) { return(1); } if ( 1 < B[r,r] ) { return(0); } return(1); } example { "EXAMPLE"; echo = 2; intmat A[3][2] = 1,4, 2,5, 3,6; // should be 0 int b = isPrimitiveSublattice(A); print(b); // another example intmat B[2][2] = 1,0, 0,1; // should be 1 int c = isPrimitiveSublattice(B); print(c); kill A, b, B, c; } /******************************************************/ proc isIntegralSurjective(intmat P); "USAGE: isIntegralSurjective(P); intmat P PURPOSE: test whether the given linear map P of lattices is surjective. RETURNS: int, where 0 is false and 1 is true. EXAMPLE: example isIntegralSurjective; shows an example " { int r = intRank(P); if ( r < nrows(P) ) { return(0); } if ( isPrimitiveSublattice(P) == 1 ) { return(1); } return(0); } example { "EXAMPLE"; echo = 2; intmat A[2][3] = 1,3,5, 2,4,6; // should be 0 int b = isIntegralSurjective(A); print(b); // another example intmat B[2][3] = 1,1,5, 2,3,6; // should be 1 int c = isIntegralSurjective(B); print(c); kill A, b, B, c; } /******************************************************/ proc projectLattice(intmat B) "USAGE: projectLattice(B); intmat B PURPOSE: A set of vectors in ZZ^m is given as the columns of B. Then this function provides a linear map ZZ^m --> ZZ^n having the primitive span of B its kernel. RETURNS: intmat EXAMPLE: example projectLattice; shows an example " { int n = nrows(B); int r = intRank(B); if ( r == 0 ) { intmat U = unitMatrix(n); } else { if ( r == n ) { intmat U[1][n]; // U now is the n-dim zero-vector } else { // we want a matrix with column operations so we transpose intmat BB = transpose(B); list L = hermiteNormalForm(BB, "transform"); intmat U = transpose(L[2]); // delete rows 1 to r intmat Udel[nrows(U) - r][ncols(U)]; int k; int m; for ( k = 1; k <= nrows(U) - r ; k++ ) { for ( m = 1; m <= ncols(U); m++ ) { Udel[k,m] = U[k + r,m]; } } U = Udel; } } return(U); } example { "EXAMPLE"; echo = 2; intmat B[4][2] = 1,5, 2,6, 3,7, 4,8; // should result in a (2x4)-matrix such that the corresponding lattice is created by // [-1, 2], [-2, 3], [-1, 0] and [0, 1] print(projectLattice(B)); // another example intmat BB[4][2] = 1,0, 0,1, 0,0, 0,0; // should result in a (2x4)-matrix such that the corresponding lattice is created by // [0,0],[0,0],[1,0],[0,1] print(projectLattice(BB)); // another example intmat BBB[3][4] = 1,0,1,2, 1,1,0,0, 3,0,0,3; // should result in the (1x3)-matrix that consists of just zeros print(projectLattice(BBB)); } /******************************************************/ proc intersectLattices(intmat A, intmat B) "USAGE: intersectLattices(A, B); intmat A, intmat B PURPOSE: compute an integral basis for the intersection of the lattices A and B. RETURNS: intmat EXAMPLE: example intersectLattices; shows an example " { // concatenate matrices: Con = [A,-B] intmat Con[nrows(A)][ncols(A) + ncols(B)]; int i; int j; for ( i = 1; i <= nrows(Con); i++ ) { for ( j = 1; j <= ncols(A); j++ ) // A first { Con[i,j] = A[i,j]; } } for ( i = 1; i <= nrows(Con); i++ ) { for ( j = 1; j <= ncols(B); j++ ) // now -B { Con[i,ncols(A) + j] = - B[i,j]; } } intmat K = kernelLattice(Con); // delete all rows in K from ncols(A)+1 onwards intmat Bas[ncols(A)][ncols(K)]; for ( i = 1; i <= nrows(Bas); i++ ) { for ( j = 1; j <= ncols(Bas); j++ ) { Bas[i,j] = K[i,j]; } } // take product in order to obtain the intersection intmat S = A * Bas; intmat Cut = hermiteNormalForm(S); //hermite(S); int r = intRank(Cut); if ( r == 0 ) { intmat Cutdel[nrows(Cut)][1]; // is now the zero-vector Cut = Cutdel; } else { // delte columns from r+1 onwards intmat Cutdel[nrows(Cut)][r]; for ( i = 1; i <= nrows(Cutdel); i++ ) { for ( j = 1; j <= r; j++ ) { Cutdel[i,j] = Cut[i,j]; } } Cut = Cutdel; } return(Cut); } example { "EXAMPLE"; echo = 2; intmat A[3][2] = 1,4, 2,5, 3,6; intmat B[3][2] = 6,9, 7,10, 8,11; // should result in a (3x2)-matrix with columns // e.g. [0, 3, 6], [-3, 0, 3] (the lattice should be the same) print(intersectLattices(A,B)); // another example intmat C[2][3] = 1,0,0, 3,2,5; intmat D[2][3] = 4,5,0, 0,5,0; // should result in a (3x2)-matrix whose columns generate the // same lattice as [1,5], [0, 20] print(intersectLattices(C,D)); } //////////////////////////////////// proc intInverse(intmat A); "USAGE: intInverse(A); intmat A PURPOSE: compute the integral inverse of the intmat A. If det(A) is neither 1 nor -1 an error is returned. RETURNS: intmat EXAMPLE: example intInverse; shows an example " { int d = det(A); if ( d * d != 1 ) // is d = 1 or -1? Else: error { ERROR("determinant of the given intmat has to be 1 or -1."); } int c; int i,j; intmat C[nrows(A)][ncols(A)]; intmat Ad; int s; for ( i = 1; i <= nrows(C); i++ ) { for ( j = 1; j <= ncols(C); j++ ) { Ad = intAdjoint(A,i,j); s = 1; if ( ((i + j) % 2) > 0 ) { s = -1; } C[i,j] = d * s * det(Ad); // mult by d is equal to div by det } } C = transpose(C); return(C); } example { "EXAMPLE"; echo = 2; intmat A[3][3] = 1,1,3, 3,2,0, 0,0,1; intmat B = intInverse(A); // should be the unit matrix print(A * B); // another example intmat C[2][2] = 2,1, 3,2; intmat D = intInverse(C); // should be the unit matrix print(C * D); kill A, B, C, D; } /******************************************************/ static proc intAdjoint(intmat A, int indrow, int indcol) "USAGE: intAdjoint(A); intmat A PURPOSE: return the matrix where the given row and column are deleted. RETURNS: intmat EXAMPLE: example intAdjoint; shows an example " { int n = nrows(A); int m = ncols(A); int i, j; intmat B[n - 1][m - 1]; int a, b; for ( i = 1; i < indrow; i++ ) { for ( j = 1; j < indcol; j++ ) { B[i,j] = A[i,j]; } for ( j = indcol + 1; j <= ncols(A); j++ ) { B[i,j - 1] = A[i,j]; } } for ( i = indrow + 1; i <= nrows(A); i++ ) { for ( j = 1; j < indcol; j++ ) { B[i - 1,j] = A[i,j]; } for ( j = indcol+1; j <= ncols(A); j++ ) { B[i - 1,j - 1] = A[i,j]; } } return(B); } example { "EXAMPLE"; echo = 2; intmat A[2][3] = 1,3,5, 2,4,6; intmat B = intAdjoint(A,2,2); print(B); kill A,B; } /******************************************************/ proc integralSection(intmat P); "USAGE: integralSection(P); intmat P PURPOSE: for a given linear surjective map P of lattices this procedure returns an integral section of P. RETURNS: intmat EXAMPLE: example integralSection; shows an example " { int m = nrows(P); int n = ncols(P); if ( m == n ) { intmat U = intInverse(P); } else { intmat U = (hermiteNormalForm(P, "transform"))[2]; // delete columns m+1 to n intmat Udel[nrows(U)][ncols(U) - (n - m)]; int k; int z; for ( k = 1; k <= nrows(U); k++ ) { for ( z = 1; z <= m; z++ ) { Udel[k,z] = U[k,z]; } } U = Udel; } return(U); } example { "EXAMPLE"; echo = 2; intmat P[2][4] = 1,3,4,6, 2,4,5,7; // should be a matrix with two columns // for example: [-2, 1, 0, 0], [3, -3, 0, 1] intmat U = integralSection(P); print(U); print(P * U); kill U; } /******************************************************/ proc factorgroup(G,H) "USAGE: factorgroup(G,H); list G, list H PURPOSE: returns a representation of the factor group G mod H using the first isomorphism thm RETURNS: list EXAMPLE: example factorgroup(G,H); shows an example " { intmat S1 = G[1]; intmat L1 = G[2]; intmat S2 = H[1]; intmat L2 = H[2]; // check whether G,H are subgroups of a common group, i.e. whether L1 and L2 span the same lattice if ( !isSublattice(L1,L2) || !isSublattice(L2,L1)) { ERROR("G and H are not subgroups of a common group."); } // check whether H is a subgroup of G, i.e. whether S2 is a sublattice of S1+L1 intmat B = concatintmat(S1,L1); // check whether this gives the concatinated matrix if ( !isSublattice(S2,B) ) { ERROR("H is not a subgroup of G"); } // use first isomorphism thm to get the factor group intmat L = concatintmat(L1,S2); // check whether this gives the concatinated matrix list GmodH; GmodH[1]=S1; GmodH[2]=L; return(GmodH); } example { "EXAMPLE"; echo = 2; intmat S1[2][2] = 1,0, 0,1; intmat L1[2][1] = 2, 0; intmat S2[2][1] = 1, 0; intmat L2[2][1] = 2, 0; list G = createGroup(S1,L1); list H = createGroup(S2,L2); list N = factorgroup(G,H); print(N); kill G,H,N,S1,L1,S2,L2; } /******************************************************/ proc productgroup(G,H) "USAGE: productgroup(G,H); list G, list H PURPOSE: Returns a representation of the group G x H RETURNS: list EXAMPLE: example productgroup(G,H); shows an example " { intmat S1 = G[1]; intmat L1 = G[2]; intmat S2 = H[1]; intmat L2 = H[2]; intmat OS1[nrows(S1)][ncols(S2)]; intmat OS2[nrows(S2)][ncols(S1)]; intmat OL1[nrows(L1)][ncols(L2)]; intmat OL2[nrows(L2)][ncols(L1)]; // concatinate matrices to get S intmat A = concatintmat(S1,OS1); intmat B = concatintmat(OS2,S2); intmat At = transpose(A); intmat Bt = transpose(B); intmat St = concatintmat(At,Bt); intmat S = transpose(St); // concatinate matrices to get L intmat C = concatintmat(L1,OL1); intmat D = concatintmat(OL2,L2); intmat Ct = transpose(C); intmat Dt = transpose(D); intmat Lt = concatintmat(Ct,Dt); intmat L = transpose(Lt); list GxH; GxH[1]=S; GxH[2]=L; return(GxH); } example { "EXAMPLE"; echo = 2; intmat S1[2][2] = 1,0, 0,1; intmat L1[2][1] = 2, 0; intmat S2[2][2] = 1,0, 0,2; intmat L2[2][1] = 0, 3; list G = createGroup(S1,L1); list H = createGroup(S2,L2); list N = productgroup(G,H); print(N); kill G,H,N,S1,L1,S2,L2; } /******************************************************/ proc primitiveSpan(intmat V); "USAGE: primitiveSpan(V); intmat V PURPOSE: compute an integral basis for the minimal primitive sublattice that contains the given vectors, i.e. the columns of V. RETURNS: int, where 0 is false and 1 is true. EXAMPLE: example primitiveSpan; shows an example " { int n = ncols(V); int m = nrows(V); int r = intRank(V); if ( r == 0 ) { intmat P[m][1]; // this is the m-zero-vector now } else { list L = smithNormalForm(V, "transform"); // L = [A,S,B] where S is the smith-NF and S = A*S*B intmat P = intInverse(L[1]); // print(L); if ( r < m ) { // delete columns r+1 to m in P: intmat Pdel[nrows(P)][r]; int i,j; for ( i = 1; i <= nrows(Pdel); i++ ) { for ( j = 1; j <= ncols(Pdel); j++ ) { Pdel[i,j] = P[i,j]; } } P = Pdel; } } return(P); } example { "EXAMPLE"; echo = 2; intmat V[3][2] = 1,4, 2,5, 3,6; // should return a (3x2)-matrix whose columns // generate the same lattice as [1, 2, 3] and [0, 1, 2] intmat R = primitiveSpan(V); print(R); // another example intmat W[2][2] = 1,0, 0,1; // should return a (2x2)-matrix whose columns // generate the same lattice as [1, 0] and [0, 1] intmat S = primitiveSpan(W); print(S); kill V, R, S, W; } /***********************************************************/ singular-4.0.3+ds/Singular/LIB/ncalg.lib000066400000000000000000037442631266270727000177460ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version ncalg.lib 4.0.0.0 Jun_2013 "; // $Id: a480d0fbd674960ea587aca8205cece0ab43a3f5 $ category="Noncommutative"; info=" LIBRARY: ncalg.lib Definitions of important G- and GR-algebras AUTHORS: Viktor Levandovskyy, levandov@mathematik.uni-kl.de, @* Oleksandr Motsak, U@D, where U={motsak}, D={mathematik.uni-kl.de} CONVENTIONS: This library provides pre-defined important noncommutative algebras. @* For universal enveloping algebras of finite dimensional Lie algebras sl_n, gl_n, g_2 etc. there are functions @code{makeUsl}, @code{makeUgl}, @code{makeUg2} etc. @* For quantized enveloping algebras U_q(sl_2) and U_q(sl_3), there are functions @code{makeQsl2}, @code{makeQsl3}) and for non-standard quantum deformation of so_3, there is the function @code{makeQso3}. @* For bigger algebras we suppress the output of the (lengthy) list of non-commutative relations and provide only the number of these relations instead. PROCEDURES: makeUsl2([p]) create U(sl_2) in the variables (e,f,h) in char p>=0 makeUsl(n[,p]) create U(sl_n) in char p>=0 makeUgl(n,[p]) create U(gl_n) in the variables (e_i_j (1=0 makeUso5([p]) create U(so_5) in the variables (x(i),y(i),H(i)) in char p>=0 makeUso6([p]) create U(so_6) in the variables (x(i),y(i),H(i)) in char p>=0 makeUso7([p]) create U(so_7) in the variables (x(i),y(i),H(i)) in char p>=0 makeUso8([p]) create U(so_8) in the variables (x(i),y(i),H(i)) in char p>=0 makeUso9([p]) create U(so_9) in the variables (x(i),y(i),H(i)) in char p>=0 makeUso10([p]) create U(so_{10}) in the variables (x(i),y(i),H(i)) in char p>=0 makeUso11([p]) create U(so_{11}) in the variables (x(i),y(i),H(i)) in char p>=0 makeUso12([p]) create U(so_{12}) in the variables (x(i),y(i),H(i)) in char p>=0 makeUsp1([p]) create U(sp_1) in the variables (x(i),y(i),H(i)) in char p>=0 makeUsp2([p]) create U(sp_2) in the variables (x(i),y(i),H(i)) in char p>=0 makeUsp3([p]) create U(sp_3) in the variables (x(i),y(i),H(i)) in char p>=0 makeUsp4([p]) create U(sp_4) in the variables (x(i),y(i),H(i)) in char p>=0 makeUsp5([p]) create U(sp_5) in the variables (x(i),y(i),H(i)) in char p>=0 makeUg2([p]) create U(g_2) in the variables (x(i),y(i),Ha,Hb) in char p>=0 makeUf4([p]) create U(f_4) in the variables (x(i),y(i),H(i)) in char p>=0 makeUe6([p]) create U(e_6) in the variables (x(i),y(i),H(i)) in char p>=0 makeUe7([p]) create U(e_7) in the variables (x(i),y(i),H(i)) in char p>=0 makeUe8([p]) create U(e_8) in the variables (x(i),y(i),H(i)) in char p>=0 makeQso3([n]) create U_q(so_3) in the presentation of Klimyk (if int n is given, the quantum parameter will be specialized at the 2n-th root of unity) makeQsl2([n]) preparation for U_q(sl_2) as factor-algebra; if n is specified, the quantum parameter q will be specialized at the n-th root of unity makeQsl3([n]) preparation for U_q(sl_3) as factor-algebra; if n is specified, the quantum parameter q will be specialized at the n-th root of unity Qso3Casimir(n [,m]) returns a list with the (optionally normalized) Casimir elements of U_q(so_3) for the quantum parameter specialized at the 2n-th root of unity GKZsystem(A, sord, alg [,v]) define a ring and a Gelfand-Kapranov-Zelevinsky system of differential equations "; LIB "nctools.lib"; // rootofUnity, LIB "general.lib"; LIB "toric.lib"; // needed for GKZsystem /////////////////////////////////////////////////////////////////////////////// static proc defInt ( list # ) // return 0 or int(#) { int @p = 0; if ( size(#) > 0 ) { if ( typeof( #[1] ) == "int" ) { @p = #[1]; } } return (@p); } /////////////////////////////////////////////////////////////////////////////// proc makeUsl2(list #) "USAGE: makeUsl2([p]), p an optional integer (field characteristic) RETURN: ring PURPOSE: set up the U(sl_2) in the variables e,f,h over the field of char p NOTE: activate this ring with the @code{setring} command SEE ALSO: makeUsl, makeUg2, makeUgl EXAMPLE: example makeUsl2; shows examples "{ int @p = defInt(#); ring @@@rrr=@p,(e,f,h),dp; matrix D[3][3]=0; D[1,2]=-h; D[1,3]=2*e; D[2,3]=-2*f; def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def a=makeUsl2(); setring a; a; } /////////////////////////////////////////////////////////////////////////////// proc makeUsl(int n, list #) "USAGE: makeUsl(n,[p]); n an integer, n>1; p an optional integer (field characteristic) RETURN: ring PURPOSE: set up the U(sl_n) in the variables ( x(i),y(i),h(i) | i=1..n+1) over the field of char p NOTE: activate this ring with the @code{setring} command @* This presentation of U(sl_n) is the standard one, i.e. positive resp. negative roots are denoted by x(i) resp. y(i) and the Cartan elements are denoted by h(i). @* The variables are ordered as x(1),...x(n),y(1),...,y(n),h(1),...h(n). SEE ALSO: makeUsl2, makeUg2, makeUgl, makeQsl3, makeQso3 EXAMPLE: example makeUsl; shows examples "{ if (n<2) { print("Incorrect input"); return(0); } if (n==2) { def @@@a=makeUsl2(#); setring @@@a; return(@@@a); } int @p = defInt(#); ring @@@rr=@p,(x(1..n*(n-1) div 2),y(1..n*(n-1) div 2 ),h(1..n-1)),dp; matrix TMP[n][n]=0; int k,l=1,1; int buf=0; list X,Y,H; for(k=1; k<=n; k++) { for(l=k+1; l<=n; l++) { buf = (l-k-1)*(2*n-l+k) div 2 + k; TMP[k,l] = -1; // for conformance with GAP X[buf] = TMP; TMP = 0; TMP[l,k] = -1; Y[buf] = TMP; TMP=0; } } for(k=1; k<=n-1; k++) { TMP[k,k]=1; TMP[k+1,k+1]=-1; H[k]=TMP; TMP=0; } int i,j=1,1; number p,q=0,0; list V=X+Y+H; int v = size(V); matrix D[v][v]=0; for(k=1; k<=v; k++) { for(l=k+1; l<=v; l++) { TMP=V[l]*V[k]-V[k]*V[l]; for(i=1; i<=n; i++) { for(j=i+1; j<=n; j++) { buf=(j-i-1)*(2*n-j+i) div 2+i; if (TMP[i,j]!=0) { D[k,l]=D[k,l]+(leadcoef(TMP[i,j])/leadcoef(X[buf][i,j]))*x(buf); } if (TMP[j,i]!=0) { D[k,l]=D[k,l]+(leadcoef(TMP[j,i])/leadcoef(Y[buf][j,i]))*y(buf); } } } i=1; while ( (TMP[i,i]==0) && (i1; p an optional int (field characteristic) RETURN: ring PURPOSE: set up the U(gl_n) in the (e_ij (10) { int m = int(#[1]); if (m!=0) { rs = cleardenom(rs); } } cp[1] = rs; for(j=2; j<=NV; j++) { cp[j] = subst(rs,var(1),var(j)); } return(cp); } example { "EXAMPLE:"; echo = 2; def R = makeQso3(5); setring R; list C = Qso3Casimir(5); C; list Cnorm = Qso3Casimir(5,1); Cnorm; } /////////////////////////////////////////////////////////////////////////////// proc makeQsl2(list #) "USAGE: makeQsl2([n]), n an optional int RETURN: ring PURPOSE: define the U_q(sl_2) as a factor-ring of a ring V_q(sl_2) modulo the ideal @code{Qideal} NOTE: the output consists of a ring, presenting V_q(sl_2) together with the ideal called @code{Qideal} in this ring @* activate this ring with the @code{setring} command @* in order to create the U_q(sl_2) from the output, execute the command like @code{qring Usl2q = Qideal;} @* If n is specified, the quantum parameter q will be specialized at the n-th root of unity SEE ALSO: makeUsl, makeQsl3, makeQso3 EXAMPLE: example makeQsl2; shows examples "{ ring r=(0,q),(E,F,Ke,Kf),dp; int @p = defInt(#); if (@p >1) { minpoly = rootofUnity(@p); } matrix C = UpOneMatrix(4);; matrix D[4][4]; C[1,3]=q^2; C[2,3]=1/(q^2); C[1,4]=1/(q^2); C[2,4]=q^2; D[1,2]=(1/(q-(1/q)))*(-Ke+Kf); def @@RR=nc_algebra(C,D); setring @@RR; ideal Qideal = Ke*Kf-1; Qideal = twostd(Qideal); export Qideal; return(@@RR); } example { "EXAMPLE:"; echo = 2; def A = makeQsl2(3); setring A; Qideal; qring Usl2q = Qideal; Usl2q; } /////////////////////////////////////////////////////////////////////////////// proc makeQsl3(list #) "USAGE: makeQsl3([n]), n an optional int RETURN: ring PURPOSE: define the U_q(sl_3) as a factor-ring of a ring V_q(sl_3) modulo the ideal @code{Qideal} NOTE: the output consists of a ring, presenting V_q(sl_3) together with the ideal called @code{Qideal} in this ring @* activate this ring with the @code{setring} command @* in order to create the U_q(sl_3) from the output, execute the command like @code{qring Usl3q = Qideal;} @* If n is specified, the quantum parameter q will be specialized at the n-th root of unity SEE ALSO: makeUsl, makeQsl2, makeQso3 EXAMPLE: example makeQsl3; shows examples "{ int @p = defInt(#); ring @@@rrr=(0, q), (f12, f13, f23, k1, k2, l1, l2, e12, e13, e23), wp(2, 3, 2, 1, 1, 1, 1, 2, 3, 2); if (@p >1) { minpoly = rootofUnity(@p); } int @n = nvars(@@@rrr); matrix C = UpOneMatrix(@n); matrix D[@n][@n]; // some constants number q1 = 1/q; number Q = (q )^2; number Q1 = (q1)^2; // number QQ = Q - Q1; // q2 - 1/(q2) number QQ1= 1 / (Q - Q1); // relations: C[1,2] = Q1; C[2,3] = C[1,2]; C[8,9] = C[1,2]; C[9,10]= C[1,2]; C[1,3] = Q; C[8,10]= C[1,3]; D[1,3] = -q*(f13); D[8,10]= -q*(e13); // V_q(sl_3) D[1,8] = QQ1 * ( (k1) ^ 2 - (l1) ^ 2 ); D[3,10]= QQ1 * ( (k2) ^ 2 - (l2) ^ 2 ); D[2,9] = -QQ1 * ( ((k1)^2)*((k2)^2) - ((l1)^2)*((l2)^2) ); D[2, 8] = q * (f23) * ((k1)^2); D[3, 9] = q * ((k2)^2) * (e12); D[1, 9] = -q1 * ((l1)^2) * (e23); D[2, 10]= -q1 * (f12) * ((l2)^2); // k1 C[ 4, 8 ]= Q1; C[ 4, 9 ]= q1; C[ 4, 10]= q; // l1 C[ 6, 8 ]= Q; C[ 6, 9 ]= q; C[ 6, 10]= q1; // k2 C[ 5, 8 ]= q; C[ 5, 9 ]= q1; C[ 5, 10]= Q1; // l2 C[ 7, 8 ]= q1; C[ 7, 9 ]= q; C[ 7, 10]= Q; // k1 C[ 1, 4 ]= Q1; C[ 2, 4 ]= q1; C[ 3, 4 ]= q; // l1 C[ 1, 6 ]= Q; C[ 2, 6 ]= q; C[ 3, 6 ]= q1; // k2 C[ 1, 5 ]= q; C[ 2, 5 ]= q1; C[ 3, 5 ]= Q1; // l2 C[ 1, 7 ]= q1; C[ 2, 7 ]= q; C[ 3, 7 ]= Q; def @@RR=nc_algebra(C,D); // the V_q(makeUsl3) is done setring @@RR; ideal Qideal = k1*l1-1, k2*l2-1; Qideal = twostd(Qideal); export Qideal; return(@@RR); } example { "EXAMPLE:"; echo = 2; def B = makeQsl3(5); setring B; qring Usl3q = Qideal; Usl3q; } proc GKZsystem(intmat A, string sord, string alg, list #) "USAGE: GKZsystem(A, sord, alg, [,v]); A intmat, sord, alg string, v intvec RETURN: ring PURPOSE: define a ring (Weyl algebra) and create a Gelfand-Kapranov-Zelevinsky (GKZ) system of equations in a ring from the following data: @* @code{A} is an intmat, defining the system, @* @code{sord} is a string with desired term ordering, @* @code{alg} is a string, saying which algorithm to use (exactly like in toric_lib), @* @code{v} is an optional intvec. @* In addition, the ideal called @code{GKZid} containing actual equations is calculated and exported to the ring. NOTE: activate the output ring with the @code{setring} command. This procedure is elaborated by Oleksandr Iena ASSUME: This procedure uses toric_lib and therefore inherits its input requirements: @* possible values for input variable @code{alg} are: \"ect\",\"pt\",\"blr\", \"hs\", \"du\". @* As for the term ordering, it should be a string @code{sord} in @sc{Singular} format like \"lp\",\"dp\", etc. @* Please consult the toric_lib for allowed orderings and more details. SEE ALSO: toric_lib EXAMPLE: example GKZsystem; shows examples "{ int @d = nrows(A); int n = ncols(A); execute("ring r1=0,(d(1..n)),"+sord+";"); ideal I0; if (size(#)==0) { I0 = toric_ideal(A, alg); } else { if ( typeof(#[1]) == "intvec" ) { intvec V = intvec(#[1]); I0 = toric_ideal(A, alg, V); } else { "Wrong type of the optional argument. Intvec expected."; return(); } } string sord2 = "(a(0:" + string(n) + ")," + sord + ")"; execute("ring GR = (0,b(1..@d)),(x(1..n),d(1..n)),"+sord2+";"); def W=Weyl(); setring W; kill GR; int i,j; poly p; ideal I; for (i=1; i<=@d; i++) { p = -b(i); for (j=1; j<=n; j++) { p = p+ A[i,j]*x(j)*d(j); } I = I, p; } I = I, imap(r1,I0); I = simplify(I,2); ideal GKZid = I; export(GKZid); return(W); } example {"EXAMPLE:"; echo = 2; // example 3.1.4 from the [SST] without the vector w intmat A[2][4]=3,2,1,0,0,1,2,3; print(A); def D1 = GKZsystem(A,"lp","ect"); setring D1; D1; print(GKZid); // now, consider A with the vector w=1,1,1,1 intvec v=1,1,1,1; def D2 = GKZsystem(A,"lp","blr",v); setring D2; print(GKZid); } // easier example: 3.1.1 from SST // intmat A[2][3]=2,1,0,0,1,2; /////////////////////////////////////////////////////////////////////////////// // need: real Uso3 in the symmetric presentation // is not isomorphic to Usl2 over R (but C) proc makeUso3(list #) "USAGE: makeUso3([p]), p an optional int PURPOSE: set up the real U(so_3) algebra in the symmetric presentation; if p is specified, RETURN: ring NOTE: activate this ring with the @code{setring} command SEE ALSO: makeUsl, makeUgl, makeUso5 EXAMPLE: example makeUso3; shows examples "{ int @p = defInt(#); ring @@@r=@p,(x,y,z),dp; matrix D[3][3]; D[1,2]=-z; D[1,3]=y; D[2,3]=-x; def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def K = makeUso3(5); setring K; K; } /////////////////////////////////////////////////////////////////////////////// // Algebra: so5(Q) has the type: B2, and defined by: proc makeUso5(list #) "USAGE: makeUso5([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(so_5) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(so_5) is derived from the Chevalley representation of so_5, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUso5; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..4),Y(1..4),H(1..2)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,9] = (2)*var(1); // [ var(9) , var(1) ] D[2,9] = (-1)*var(2); // [ var(9) , var(2) ] D[3,9] = var(3); // [ var(9) , var(3) ] D[1,10] = (-2)*var(1); // [ var(10) , var(1) ] D[2,10] = (2)*var(2); // [ var(10) , var(2) ] D[4,10] = (2)*var(4); // [ var(10) , var(4) ] // H(i) * Y(j): D[5,9] = (-2)*var(5); // [ var(9) , var(5) ] D[6,9] = var(6); // [ var(9) , var(6) ] D[7,9] = (-1)*var(7); // [ var(9) , var(7) ] D[5,10] = (2)*var(5); // [ var(10) , var(5) ] D[6,10] = (-2)*var(6); // [ var(10) , var(6) ] D[8,10] = (-2)*var(8); // [ var(10) , var(8) ] // Y(i) * X(j): D[1,5] = (-1)*var(9); // [ var(5) , var(1) ] D[3,5] = var(2); // [ var(5) , var(3) ] D[2,6] = (-1)*var(10); // [ var(6) , var(2) ] D[3,6] = (-2)*var(1); // [ var(6) , var(3) ] D[4,6] = (-1)*var(3); // [ var(6) , var(4) ] D[1,7] = var(6); // [ var(7) , var(1) ] D[2,7] = (-2)*var(5); // [ var(7) , var(2) ] D[3,7] = (-2)*var(9)+(-1)*var(10); // [ var(7) , var(3) ] D[4,7] = var(2); // [ var(7) , var(4) ] D[2,8] = (-1)*var(7); // [ var(8) , var(2) ] D[3,8] = var(6); // [ var(8) , var(3) ] D[4,8] = (-1)*var(9)+(-1)*var(10); // [ var(8) , var(4) ] // X(i) * X(j): D[1,2] = (-1)*var(3); // [ var(2) , var(1) ] D[2,3] = (2)*var(4); // [ var(3) , var(2) ] // Y(i) * Y(j): D[5,6] = var(7); // [ var(6) , var(5) ] D[6,7] = (-2)*var(8); // [ var(7) , var(6) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUso5(); ncAlgebra; setring ncAlgebra; // ... 28 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: so7(Q) has the type: B3, and defined by: proc makeUso7(list #) "USAGE: makeUso7([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(so_7) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(so_7) is derived from the Chevalley representation of so_7, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUso7; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..9),Y(1..9),H(1..3)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,19] = (2)*var(1); // [ var(19) , var(1) ] D[2,19] = (-1)*var(2); // [ var(19) , var(2) ] D[4,19] = var(4); // [ var(19) , var(4) ] D[5,19] = (-1)*var(5); // [ var(19) , var(5) ] D[6,19] = var(6); // [ var(19) , var(6) ] D[7,19] = (-1)*var(7); // [ var(19) , var(7) ] D[8,19] = var(8); // [ var(19) , var(8) ] D[1,20] = (-1)*var(1); // [ var(20) , var(1) ] D[2,20] = (2)*var(2); // [ var(20) , var(2) ] D[3,20] = (-1)*var(3); // [ var(20) , var(3) ] D[4,20] = var(4); // [ var(20) , var(4) ] D[5,20] = var(5); // [ var(20) , var(5) ] D[8,20] = (-1)*var(8); // [ var(20) , var(8) ] D[9,20] = var(9); // [ var(20) , var(9) ] D[2,21] = (-2)*var(2); // [ var(21) , var(2) ] D[3,21] = (2)*var(3); // [ var(21) , var(3) ] D[4,21] = (-2)*var(4); // [ var(21) , var(4) ] D[7,21] = (2)*var(7); // [ var(21) , var(7) ] D[8,21] = (2)*var(8); // [ var(21) , var(8) ] // H(i) * Y(j): D[10,19] = (-2)*var(10); // [ var(19) , var(10) ] D[11,19] = var(11); // [ var(19) , var(11) ] D[13,19] = (-1)*var(13); // [ var(19) , var(13) ] D[14,19] = var(14); // [ var(19) , var(14) ] D[15,19] = (-1)*var(15); // [ var(19) , var(15) ] D[16,19] = var(16); // [ var(19) , var(16) ] D[17,19] = (-1)*var(17); // [ var(19) , var(17) ] D[10,20] = var(10); // [ var(20) , var(10) ] D[11,20] = (-2)*var(11); // [ var(20) , var(11) ] D[12,20] = var(12); // [ var(20) , var(12) ] D[13,20] = (-1)*var(13); // [ var(20) , var(13) ] D[14,20] = (-1)*var(14); // [ var(20) , var(14) ] D[17,20] = var(17); // [ var(20) , var(17) ] D[18,20] = (-1)*var(18); // [ var(20) , var(18) ] D[11,21] = (2)*var(11); // [ var(21) , var(11) ] D[12,21] = (-2)*var(12); // [ var(21) , var(12) ] D[13,21] = (2)*var(13); // [ var(21) , var(13) ] D[16,21] = (-2)*var(16); // [ var(21) , var(16) ] D[17,21] = (-2)*var(17); // [ var(21) , var(17) ] // Y(i) * X(j): D[1,10] = (-1)*var(19); // [ var(10) , var(1) ] D[4,10] = var(2); // [ var(10) , var(4) ] D[6,10] = var(5); // [ var(10) , var(6) ] D[8,10] = var(7); // [ var(10) , var(8) ] D[2,11] = (-1)*var(20); // [ var(11) , var(2) ] D[4,11] = (-1)*var(1); // [ var(11) , var(4) ] D[5,11] = var(3); // [ var(11) , var(5) ] D[9,11] = var(8); // [ var(11) , var(9) ] D[3,12] = (-1)*var(21); // [ var(12) , var(3) ] D[5,12] = (-2)*var(2); // [ var(12) , var(5) ] D[6,12] = (-2)*var(4); // [ var(12) , var(6) ] D[7,12] = (-1)*var(5); // [ var(12) , var(7) ] D[8,12] = (-1)*var(6); // [ var(12) , var(8) ] D[1,13] = var(11); // [ var(13) , var(1) ] D[2,13] = (-1)*var(10); // [ var(13) , var(2) ] D[4,13] = (-1)*var(19)+(-1)*var(20); // [ var(13) , var(4) ] D[6,13] = var(3); // [ var(13) , var(6) ] D[9,13] = (-1)*var(7); // [ var(13) , var(9) ] D[2,14] = var(12); // [ var(14) , var(2) ] D[3,14] = (-2)*var(11); // [ var(14) , var(3) ] D[5,14] = (-2)*var(20)+(-1)*var(21); // [ var(14) , var(5) ] D[6,14] = (-2)*var(1); // [ var(14) , var(6) ] D[7,14] = var(3); // [ var(14) , var(7) ] D[9,14] = (-1)*var(6); // [ var(14) , var(9) ] D[1,15] = var(14); // [ var(15) , var(1) ] D[3,15] = (-2)*var(13); // [ var(15) , var(3) ] D[4,15] = var(12); // [ var(15) , var(4) ] D[5,15] = (-2)*var(10); // [ var(15) , var(5) ] D[6,15] = (-2)*var(19)+(-2)*var(20)+(-1)*var(21); // [ var(15) , var(6) ] D[8,15] = var(3); // [ var(15) , var(8) ] D[9,15] = var(5); // [ var(15) , var(9) ] D[3,16] = (-1)*var(14); // [ var(16) , var(3) ] D[5,16] = var(12); // [ var(16) , var(5) ] D[7,16] = (-1)*var(20)+(-1)*var(21); // [ var(16) , var(7) ] D[8,16] = (-1)*var(1); // [ var(16) , var(8) ] D[9,16] = var(4); // [ var(16) , var(9) ] D[1,17] = var(16); // [ var(17) , var(1) ] D[3,17] = (-1)*var(15); // [ var(17) , var(3) ] D[6,17] = var(12); // [ var(17) , var(6) ] D[7,17] = (-1)*var(10); // [ var(17) , var(7) ] D[8,17] = (-1)*var(19)+(-1)*var(20)+(-1)*var(21); // [ var(17) , var(8) ] D[9,17] = (-1)*var(2); // [ var(17) , var(9) ] D[2,18] = var(17); // [ var(18) , var(2) ] D[4,18] = (-1)*var(16); // [ var(18) , var(4) ] D[5,18] = (-1)*var(15); // [ var(18) , var(5) ] D[6,18] = var(14); // [ var(18) , var(6) ] D[7,18] = var(13); // [ var(18) , var(7) ] D[8,18] = (-1)*var(11); // [ var(18) , var(8) ] D[9,18] = (-1)*var(19)+(-2)*var(20)+(-1)*var(21); // [ var(18) , var(9) ] // X(i) * X(j): D[1,2] = (-1)*var(4); // [ var(2) , var(1) ] D[1,5] = (-1)*var(6); // [ var(5) , var(1) ] D[1,7] = (-1)*var(8); // [ var(7) , var(1) ] D[2,3] = (-1)*var(5); // [ var(3) , var(2) ] D[2,8] = (-1)*var(9); // [ var(8) , var(2) ] D[3,4] = var(6); // [ var(4) , var(3) ] D[3,5] = (2)*var(7); // [ var(5) , var(3) ] D[3,6] = (2)*var(8); // [ var(6) , var(3) ] D[4,7] = var(9); // [ var(7) , var(4) ] D[5,6] = (2)*var(9); // [ var(6) , var(5) ] // Y(i) * Y(j): D[10,11] = var(13); // [ var(11) , var(10) ] D[10,14] = var(15); // [ var(14) , var(10) ] D[10,16] = var(17); // [ var(16) , var(10) ] D[11,12] = var(14); // [ var(12) , var(11) ] D[11,17] = var(18); // [ var(17) , var(11) ] D[12,13] = (-1)*var(15); // [ var(13) , var(12) ] D[12,14] = (-2)*var(16); // [ var(14) , var(12) ] D[12,15] = (-2)*var(17); // [ var(15) , var(12) ] D[13,16] = (-1)*var(18); // [ var(16) , var(13) ] D[14,15] = (-2)*var(18); // [ var(15) , var(14) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUso7(); ncAlgebra; setring ncAlgebra; // ... 107 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: so9(Q) has the type: B4, and defined by: proc makeUso9(list #) "USAGE: makeUso9([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(so_9) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(so_9) is derived from the Chevalley representation of so_9, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUso9; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..16),Y(1..16),H(1..4)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,33] = (2)*var(1); // [ var(33) , var(1) ] D[2,33] = (-1)*var(2); // [ var(33) , var(2) ] D[5,33] = var(5); // [ var(33) , var(5) ] D[6,33] = (-1)*var(6); // [ var(33) , var(6) ] D[8,33] = var(8); // [ var(33) , var(8) ] D[9,33] = (-1)*var(9); // [ var(33) , var(9) ] D[11,33] = var(11); // [ var(33) , var(11) ] D[12,33] = (-1)*var(12); // [ var(33) , var(12) ] D[13,33] = var(13); // [ var(33) , var(13) ] D[14,33] = (-1)*var(14); // [ var(33) , var(14) ] D[15,33] = var(15); // [ var(33) , var(15) ] D[1,34] = (-1)*var(1); // [ var(34) , var(1) ] D[2,34] = (2)*var(2); // [ var(34) , var(2) ] D[3,34] = (-1)*var(3); // [ var(34) , var(3) ] D[5,34] = var(5); // [ var(34) , var(5) ] D[6,34] = var(6); // [ var(34) , var(6) ] D[7,34] = (-1)*var(7); // [ var(34) , var(7) ] D[9,34] = var(9); // [ var(34) , var(9) ] D[10,34] = (-1)*var(10); // [ var(34) , var(10) ] D[12,34] = var(12); // [ var(34) , var(12) ] D[15,34] = (-1)*var(15); // [ var(34) , var(15) ] D[16,34] = var(16); // [ var(34) , var(16) ] D[2,35] = (-1)*var(2); // [ var(35) , var(2) ] D[3,35] = (2)*var(3); // [ var(35) , var(3) ] D[4,35] = (-1)*var(4); // [ var(35) , var(4) ] D[5,35] = (-1)*var(5); // [ var(35) , var(5) ] D[6,35] = var(6); // [ var(35) , var(6) ] D[7,35] = var(7); // [ var(35) , var(7) ] D[8,35] = var(8); // [ var(35) , var(8) ] D[12,35] = (-1)*var(12); // [ var(35) , var(12) ] D[13,35] = (-1)*var(13); // [ var(35) , var(13) ] D[14,35] = var(14); // [ var(35) , var(14) ] D[15,35] = var(15); // [ var(35) , var(15) ] D[3,36] = (-2)*var(3); // [ var(36) , var(3) ] D[4,36] = (2)*var(4); // [ var(36) , var(4) ] D[6,36] = (-2)*var(6); // [ var(36) , var(6) ] D[8,36] = (-2)*var(8); // [ var(36) , var(8) ] D[10,36] = (2)*var(10); // [ var(36) , var(10) ] D[12,36] = (2)*var(12); // [ var(36) , var(12) ] D[13,36] = (2)*var(13); // [ var(36) , var(13) ] // H(i) * Y(j): D[17,33] = (-2)*var(17); // [ var(33) , var(17) ] D[18,33] = var(18); // [ var(33) , var(18) ] D[21,33] = (-1)*var(21); // [ var(33) , var(21) ] D[22,33] = var(22); // [ var(33) , var(22) ] D[24,33] = (-1)*var(24); // [ var(33) , var(24) ] D[25,33] = var(25); // [ var(33) , var(25) ] D[27,33] = (-1)*var(27); // [ var(33) , var(27) ] D[28,33] = var(28); // [ var(33) , var(28) ] D[29,33] = (-1)*var(29); // [ var(33) , var(29) ] D[30,33] = var(30); // [ var(33) , var(30) ] D[31,33] = (-1)*var(31); // [ var(33) , var(31) ] D[17,34] = var(17); // [ var(34) , var(17) ] D[18,34] = (-2)*var(18); // [ var(34) , var(18) ] D[19,34] = var(19); // [ var(34) , var(19) ] D[21,34] = (-1)*var(21); // [ var(34) , var(21) ] D[22,34] = (-1)*var(22); // [ var(34) , var(22) ] D[23,34] = var(23); // [ var(34) , var(23) ] D[25,34] = (-1)*var(25); // [ var(34) , var(25) ] D[26,34] = var(26); // [ var(34) , var(26) ] D[28,34] = (-1)*var(28); // [ var(34) , var(28) ] D[31,34] = var(31); // [ var(34) , var(31) ] D[32,34] = (-1)*var(32); // [ var(34) , var(32) ] D[18,35] = var(18); // [ var(35) , var(18) ] D[19,35] = (-2)*var(19); // [ var(35) , var(19) ] D[20,35] = var(20); // [ var(35) , var(20) ] D[21,35] = var(21); // [ var(35) , var(21) ] D[22,35] = (-1)*var(22); // [ var(35) , var(22) ] D[23,35] = (-1)*var(23); // [ var(35) , var(23) ] D[24,35] = (-1)*var(24); // [ var(35) , var(24) ] D[28,35] = var(28); // [ var(35) , var(28) ] D[29,35] = var(29); // [ var(35) , var(29) ] D[30,35] = (-1)*var(30); // [ var(35) , var(30) ] D[31,35] = (-1)*var(31); // [ var(35) , var(31) ] D[19,36] = (2)*var(19); // [ var(36) , var(19) ] D[20,36] = (-2)*var(20); // [ var(36) , var(20) ] D[22,36] = (2)*var(22); // [ var(36) , var(22) ] D[24,36] = (2)*var(24); // [ var(36) , var(24) ] D[26,36] = (-2)*var(26); // [ var(36) , var(26) ] D[28,36] = (-2)*var(28); // [ var(36) , var(28) ] D[29,36] = (-2)*var(29); // [ var(36) , var(29) ] // Y(i) * X(j): D[1,17] = (-1)*var(33); // [ var(17) , var(1) ] D[5,17] = var(2); // [ var(17) , var(5) ] D[8,17] = var(6); // [ var(17) , var(8) ] D[11,17] = var(9); // [ var(17) , var(11) ] D[13,17] = var(12); // [ var(17) , var(13) ] D[15,17] = var(14); // [ var(17) , var(15) ] D[2,18] = (-1)*var(34); // [ var(18) , var(2) ] D[5,18] = (-1)*var(1); // [ var(18) , var(5) ] D[6,18] = var(3); // [ var(18) , var(6) ] D[9,18] = var(7); // [ var(18) , var(9) ] D[12,18] = var(10); // [ var(18) , var(12) ] D[16,18] = var(15); // [ var(18) , var(16) ] D[3,19] = (-1)*var(35); // [ var(19) , var(3) ] D[6,19] = (-1)*var(2); // [ var(19) , var(6) ] D[7,19] = var(4); // [ var(19) , var(7) ] D[8,19] = (-1)*var(5); // [ var(19) , var(8) ] D[14,19] = var(12); // [ var(19) , var(14) ] D[15,19] = var(13); // [ var(19) , var(15) ] D[4,20] = (-1)*var(36); // [ var(20) , var(4) ] D[7,20] = (-2)*var(3); // [ var(20) , var(7) ] D[9,20] = (-2)*var(6); // [ var(20) , var(9) ] D[10,20] = (-1)*var(7); // [ var(20) , var(10) ] D[11,20] = (-2)*var(8); // [ var(20) , var(11) ] D[12,20] = (-1)*var(9); // [ var(20) , var(12) ] D[13,20] = (-1)*var(11); // [ var(20) , var(13) ] D[1,21] = var(18); // [ var(21) , var(1) ] D[2,21] = (-1)*var(17); // [ var(21) , var(2) ] D[5,21] = (-1)*var(33)+(-1)*var(34); // [ var(21) , var(5) ] D[8,21] = var(3); // [ var(21) , var(8) ] D[11,21] = var(7); // [ var(21) , var(11) ] D[13,21] = var(10); // [ var(21) , var(13) ] D[16,21] = (-1)*var(14); // [ var(21) , var(16) ] D[2,22] = var(19); // [ var(22) , var(2) ] D[3,22] = (-1)*var(18); // [ var(22) , var(3) ] D[6,22] = (-1)*var(34)+(-1)*var(35); // [ var(22) , var(6) ] D[8,22] = (-1)*var(1); // [ var(22) , var(8) ] D[9,22] = var(4); // [ var(22) , var(9) ] D[14,22] = (-1)*var(10); // [ var(22) , var(14) ] D[16,22] = var(13); // [ var(22) , var(16) ] D[3,23] = var(20); // [ var(23) , var(3) ] D[4,23] = (-2)*var(19); // [ var(23) , var(4) ] D[7,23] = (-2)*var(35)+(-1)*var(36); // [ var(23) , var(7) ] D[9,23] = (-2)*var(2); // [ var(23) , var(9) ] D[10,23] = var(4); // [ var(23) , var(10) ] D[11,23] = (-2)*var(5); // [ var(23) , var(11) ] D[14,23] = (-1)*var(9); // [ var(23) , var(14) ] D[15,23] = (-1)*var(11); // [ var(23) , var(15) ] D[1,24] = var(22); // [ var(24) , var(1) ] D[3,24] = (-1)*var(21); // [ var(24) , var(3) ] D[5,24] = var(19); // [ var(24) , var(5) ] D[6,24] = (-1)*var(17); // [ var(24) , var(6) ] D[8,24] = (-1)*var(33)+(-1)*var(34)+(-1)*var(35); // [ var(24) , var(8) ] D[11,24] = var(4); // [ var(24) , var(11) ] D[15,24] = (-1)*var(10); // [ var(24) , var(15) ] D[16,24] = (-1)*var(12); // [ var(24) , var(16) ] D[2,25] = var(23); // [ var(25) , var(2) ] D[4,25] = (-2)*var(22); // [ var(25) , var(4) ] D[6,25] = var(20); // [ var(25) , var(6) ] D[7,25] = (-2)*var(18); // [ var(25) , var(7) ] D[9,25] = (-2)*var(34)+(-2)*var(35)+(-1)*var(36); // [ var(25) , var(9) ] D[11,25] = (-2)*var(1); // [ var(25) , var(11) ] D[12,25] = var(4); // [ var(25) , var(12) ] D[14,25] = var(7); // [ var(25) , var(14) ] D[16,25] = (-1)*var(11); // [ var(25) , var(16) ] D[4,26] = (-1)*var(23); // [ var(26) , var(4) ] D[7,26] = var(20); // [ var(26) , var(7) ] D[10,26] = (-1)*var(35)+(-1)*var(36); // [ var(26) , var(10) ] D[12,26] = (-1)*var(2); // [ var(26) , var(12) ] D[13,26] = (-1)*var(5); // [ var(26) , var(13) ] D[14,26] = var(6); // [ var(26) , var(14) ] D[15,26] = var(8); // [ var(26) , var(15) ] D[1,27] = var(25); // [ var(27) , var(1) ] D[4,27] = (-2)*var(24); // [ var(27) , var(4) ] D[5,27] = var(23); // [ var(27) , var(5) ] D[7,27] = (-2)*var(21); // [ var(27) , var(7) ] D[8,27] = var(20); // [ var(27) , var(8) ] D[9,27] = (-2)*var(17); // [ var(27) , var(9) ] D[11,27] = (-2)*var(33)+(-2)*var(34)+(-2)*var(35)+(-1)*var(36); // [ var(27) , var(11) ] D[13,27] = var(4); // [ var(27) , var(13) ] D[15,27] = var(7); // [ var(27) , var(15) ] D[16,27] = var(9); // [ var(27) , var(16) ] D[2,28] = var(26); // [ var(28) , var(2) ] D[4,28] = (-1)*var(25); // [ var(28) , var(4) ] D[9,28] = var(20); // [ var(28) , var(9) ] D[10,28] = (-1)*var(18); // [ var(28) , var(10) ] D[12,28] = (-1)*var(34)+(-1)*var(35)+(-1)*var(36); // [ var(28) , var(12) ] D[13,28] = (-1)*var(1); // [ var(28) , var(13) ] D[14,28] = (-1)*var(3); // [ var(28) , var(14) ] D[16,28] = var(8); // [ var(28) , var(16) ] D[1,29] = var(28); // [ var(29) , var(1) ] D[4,29] = (-1)*var(27); // [ var(29) , var(4) ] D[5,29] = var(26); // [ var(29) , var(5) ] D[10,29] = (-1)*var(21); // [ var(29) , var(10) ] D[11,29] = var(20); // [ var(29) , var(11) ] D[12,29] = (-1)*var(17); // [ var(29) , var(12) ] D[13,29] = (-1)*var(33)+(-1)*var(34)+(-1)*var(35)+(-1)*var(36); // [ var(29) , var(13) ] D[15,29] = (-1)*var(3); // [ var(29) , var(15) ] D[16,29] = (-1)*var(6); // [ var(29) , var(16) ] D[3,30] = var(28); // [ var(30) , var(3) ] D[6,30] = (-1)*var(26); // [ var(30) , var(6) ] D[7,30] = (-1)*var(25); // [ var(30) , var(7) ] D[9,30] = var(23); // [ var(30) , var(9) ] D[10,30] = var(22); // [ var(30) , var(10) ] D[12,30] = (-1)*var(19); // [ var(30) , var(12) ] D[14,30] = (-1)*var(34)+(-2)*var(35)+(-1)*var(36); // [ var(30) , var(14) ] D[15,30] = (-1)*var(1); // [ var(30) , var(15) ] D[16,30] = var(5); // [ var(30) , var(16) ] D[1,31] = var(30); // [ var(31) , var(1) ] D[3,31] = var(29); // [ var(31) , var(3) ] D[7,31] = (-1)*var(27); // [ var(31) , var(7) ] D[8,31] = (-1)*var(26); // [ var(31) , var(8) ] D[10,31] = var(24); // [ var(31) , var(10) ] D[11,31] = var(23); // [ var(31) , var(11) ] D[13,31] = (-1)*var(19); // [ var(31) , var(13) ] D[14,31] = (-1)*var(17); // [ var(31) , var(14) ] D[15,31] = (-1)*var(33)+(-1)*var(34)+(-2)*var(35)+(-1)*var(36); // [ var(31) , var(15) ] D[16,31] = (-1)*var(2); // [ var(31) , var(16) ] D[2,32] = var(31); // [ var(32) , var(2) ] D[5,32] = (-1)*var(30); // [ var(32) , var(5) ] D[6,32] = var(29); // [ var(32) , var(6) ] D[8,32] = (-1)*var(28); // [ var(32) , var(8) ] D[9,32] = (-1)*var(27); // [ var(32) , var(9) ] D[11,32] = var(25); // [ var(32) , var(11) ] D[12,32] = var(24); // [ var(32) , var(12) ] D[13,32] = (-1)*var(22); // [ var(32) , var(13) ] D[14,32] = var(21); // [ var(32) , var(14) ] D[15,32] = (-1)*var(18); // [ var(32) , var(15) ] D[16,32] = (-1)*var(33)+(-2)*var(34)+(-2)*var(35)+(-1)*var(36); // [ var(32) , var(16) ] // X(i) * X(j): D[1,2] = (-1)*var(5); // [ var(2) , var(1) ] D[1,6] = (-1)*var(8); // [ var(6) , var(1) ] D[1,9] = (-1)*var(11); // [ var(9) , var(1) ] D[1,12] = (-1)*var(13); // [ var(12) , var(1) ] D[1,14] = (-1)*var(15); // [ var(14) , var(1) ] D[2,3] = (-1)*var(6); // [ var(3) , var(2) ] D[2,7] = (-1)*var(9); // [ var(7) , var(2) ] D[2,10] = (-1)*var(12); // [ var(10) , var(2) ] D[2,15] = (-1)*var(16); // [ var(15) , var(2) ] D[3,4] = (-1)*var(7); // [ var(4) , var(3) ] D[3,5] = var(8); // [ var(5) , var(3) ] D[3,12] = (-1)*var(14); // [ var(12) , var(3) ] D[3,13] = (-1)*var(15); // [ var(13) , var(3) ] D[4,6] = var(9); // [ var(6) , var(4) ] D[4,7] = (2)*var(10); // [ var(7) , var(4) ] D[4,8] = var(11); // [ var(8) , var(4) ] D[4,9] = (2)*var(12); // [ var(9) , var(4) ] D[4,11] = (2)*var(13); // [ var(11) , var(4) ] D[5,7] = (-1)*var(11); // [ var(7) , var(5) ] D[5,10] = (-1)*var(13); // [ var(10) , var(5) ] D[5,14] = var(16); // [ var(14) , var(5) ] D[6,10] = var(14); // [ var(10) , var(6) ] D[6,13] = (-1)*var(16); // [ var(13) , var(6) ] D[7,9] = (2)*var(14); // [ var(9) , var(7) ] D[7,11] = (2)*var(15); // [ var(11) , var(7) ] D[8,10] = var(15); // [ var(10) , var(8) ] D[8,12] = var(16); // [ var(12) , var(8) ] D[9,11] = (2)*var(16); // [ var(11) , var(9) ] // Y(i) * Y(j): D[17,18] = var(21); // [ var(18) , var(17) ] D[17,22] = var(24); // [ var(22) , var(17) ] D[17,25] = var(27); // [ var(25) , var(17) ] D[17,28] = var(29); // [ var(28) , var(17) ] D[17,30] = var(31); // [ var(30) , var(17) ] D[18,19] = var(22); // [ var(19) , var(18) ] D[18,23] = var(25); // [ var(23) , var(18) ] D[18,26] = var(28); // [ var(26) , var(18) ] D[18,31] = var(32); // [ var(31) , var(18) ] D[19,20] = var(23); // [ var(20) , var(19) ] D[19,21] = (-1)*var(24); // [ var(21) , var(19) ] D[19,28] = var(30); // [ var(28) , var(19) ] D[19,29] = var(31); // [ var(29) , var(19) ] D[20,22] = (-1)*var(25); // [ var(22) , var(20) ] D[20,23] = (-2)*var(26); // [ var(23) , var(20) ] D[20,24] = (-1)*var(27); // [ var(24) , var(20) ] D[20,25] = (-2)*var(28); // [ var(25) , var(20) ] D[20,27] = (-2)*var(29); // [ var(27) , var(20) ] D[21,23] = var(27); // [ var(23) , var(21) ] D[21,26] = var(29); // [ var(26) , var(21) ] D[21,30] = (-1)*var(32); // [ var(30) , var(21) ] D[22,26] = (-1)*var(30); // [ var(26) , var(22) ] D[22,29] = var(32); // [ var(29) , var(22) ] D[23,25] = (-2)*var(30); // [ var(25) , var(23) ] D[23,27] = (-2)*var(31); // [ var(27) , var(23) ] D[24,26] = (-1)*var(31); // [ var(26) , var(24) ] D[24,28] = (-1)*var(32); // [ var(28) , var(24) ] D[25,27] = (-2)*var(32); // [ var(27) , var(25) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUso9(); ncAlgebra; setring ncAlgebra; // ... 264 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: so11(Q) has the type: B5, and defined by: proc makeUso11(list #) "USAGE: makeUso11([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(so_{11}) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(so_{11}) is derived from the Chevalley representation of so_{11}, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUso11; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..25),Y(1..25),H(1..5)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,51] = (2)*var(1); // [ var(51) , var(1) ] D[2,51] = (-1)*var(2); // [ var(51) , var(2) ] D[6,51] = var(6); // [ var(51) , var(6) ] D[7,51] = (-1)*var(7); // [ var(51) , var(7) ] D[10,51] = var(10); // [ var(51) , var(10) ] D[11,51] = (-1)*var(11); // [ var(51) , var(11) ] D[14,51] = var(14); // [ var(51) , var(14) ] D[15,51] = (-1)*var(15); // [ var(51) , var(15) ] D[17,51] = var(17); // [ var(51) , var(17) ] D[18,51] = (-1)*var(18); // [ var(51) , var(18) ] D[20,51] = var(20); // [ var(51) , var(20) ] D[21,51] = (-1)*var(21); // [ var(51) , var(21) ] D[22,51] = var(22); // [ var(51) , var(22) ] D[23,51] = (-1)*var(23); // [ var(51) , var(23) ] D[24,51] = var(24); // [ var(51) , var(24) ] D[1,52] = (-1)*var(1); // [ var(52) , var(1) ] D[2,52] = (2)*var(2); // [ var(52) , var(2) ] D[3,52] = (-1)*var(3); // [ var(52) , var(3) ] D[6,52] = var(6); // [ var(52) , var(6) ] D[7,52] = var(7); // [ var(52) , var(7) ] D[8,52] = (-1)*var(8); // [ var(52) , var(8) ] D[11,52] = var(11); // [ var(52) , var(11) ] D[12,52] = (-1)*var(12); // [ var(52) , var(12) ] D[15,52] = var(15); // [ var(52) , var(15) ] D[16,52] = (-1)*var(16); // [ var(52) , var(16) ] D[18,52] = var(18); // [ var(52) , var(18) ] D[19,52] = (-1)*var(19); // [ var(52) , var(19) ] D[21,52] = var(21); // [ var(52) , var(21) ] D[24,52] = (-1)*var(24); // [ var(52) , var(24) ] D[25,52] = var(25); // [ var(52) , var(25) ] D[2,53] = (-1)*var(2); // [ var(53) , var(2) ] D[3,53] = (2)*var(3); // [ var(53) , var(3) ] D[4,53] = (-1)*var(4); // [ var(53) , var(4) ] D[6,53] = (-1)*var(6); // [ var(53) , var(6) ] D[7,53] = var(7); // [ var(53) , var(7) ] D[8,53] = var(8); // [ var(53) , var(8) ] D[9,53] = (-1)*var(9); // [ var(53) , var(9) ] D[10,53] = var(10); // [ var(53) , var(10) ] D[12,53] = var(12); // [ var(53) , var(12) ] D[13,53] = (-1)*var(13); // [ var(53) , var(13) ] D[16,53] = var(16); // [ var(53) , var(16) ] D[21,53] = (-1)*var(21); // [ var(53) , var(21) ] D[22,53] = (-1)*var(22); // [ var(53) , var(22) ] D[23,53] = var(23); // [ var(53) , var(23) ] D[24,53] = var(24); // [ var(53) , var(24) ] D[3,54] = (-1)*var(3); // [ var(54) , var(3) ] D[4,54] = (2)*var(4); // [ var(54) , var(4) ] D[5,54] = (-1)*var(5); // [ var(54) , var(5) ] D[7,54] = (-1)*var(7); // [ var(54) , var(7) ] D[8,54] = var(8); // [ var(54) , var(8) ] D[9,54] = var(9); // [ var(54) , var(9) ] D[10,54] = (-1)*var(10); // [ var(54) , var(10) ] D[11,54] = var(11); // [ var(54) , var(11) ] D[14,54] = var(14); // [ var(54) , var(14) ] D[16,54] = (-1)*var(16); // [ var(54) , var(16) ] D[18,54] = (-1)*var(18); // [ var(54) , var(18) ] D[19,54] = var(19); // [ var(54) , var(19) ] D[20,54] = (-1)*var(20); // [ var(54) , var(20) ] D[21,54] = var(21); // [ var(54) , var(21) ] D[22,54] = var(22); // [ var(54) , var(22) ] D[4,55] = (-2)*var(4); // [ var(55) , var(4) ] D[5,55] = (2)*var(5); // [ var(55) , var(5) ] D[8,55] = (-2)*var(8); // [ var(55) , var(8) ] D[11,55] = (-2)*var(11); // [ var(55) , var(11) ] D[13,55] = (2)*var(13); // [ var(55) , var(13) ] D[14,55] = (-2)*var(14); // [ var(55) , var(14) ] D[16,55] = (2)*var(16); // [ var(55) , var(16) ] D[18,55] = (2)*var(18); // [ var(55) , var(18) ] D[20,55] = (2)*var(20); // [ var(55) , var(20) ] // H(i) * Y(j): D[26,51] = (-2)*var(26); // [ var(51) , var(26) ] D[27,51] = var(27); // [ var(51) , var(27) ] D[31,51] = (-1)*var(31); // [ var(51) , var(31) ] D[32,51] = var(32); // [ var(51) , var(32) ] D[35,51] = (-1)*var(35); // [ var(51) , var(35) ] D[36,51] = var(36); // [ var(51) , var(36) ] D[39,51] = (-1)*var(39); // [ var(51) , var(39) ] D[40,51] = var(40); // [ var(51) , var(40) ] D[42,51] = (-1)*var(42); // [ var(51) , var(42) ] D[43,51] = var(43); // [ var(51) , var(43) ] D[45,51] = (-1)*var(45); // [ var(51) , var(45) ] D[46,51] = var(46); // [ var(51) , var(46) ] D[47,51] = (-1)*var(47); // [ var(51) , var(47) ] D[48,51] = var(48); // [ var(51) , var(48) ] D[49,51] = (-1)*var(49); // [ var(51) , var(49) ] D[26,52] = var(26); // [ var(52) , var(26) ] D[27,52] = (-2)*var(27); // [ var(52) , var(27) ] D[28,52] = var(28); // [ var(52) , var(28) ] D[31,52] = (-1)*var(31); // [ var(52) , var(31) ] D[32,52] = (-1)*var(32); // [ var(52) , var(32) ] D[33,52] = var(33); // [ var(52) , var(33) ] D[36,52] = (-1)*var(36); // [ var(52) , var(36) ] D[37,52] = var(37); // [ var(52) , var(37) ] D[40,52] = (-1)*var(40); // [ var(52) , var(40) ] D[41,52] = var(41); // [ var(52) , var(41) ] D[43,52] = (-1)*var(43); // [ var(52) , var(43) ] D[44,52] = var(44); // [ var(52) , var(44) ] D[46,52] = (-1)*var(46); // [ var(52) , var(46) ] D[49,52] = var(49); // [ var(52) , var(49) ] D[50,52] = (-1)*var(50); // [ var(52) , var(50) ] D[27,53] = var(27); // [ var(53) , var(27) ] D[28,53] = (-2)*var(28); // [ var(53) , var(28) ] D[29,53] = var(29); // [ var(53) , var(29) ] D[31,53] = var(31); // [ var(53) , var(31) ] D[32,53] = (-1)*var(32); // [ var(53) , var(32) ] D[33,53] = (-1)*var(33); // [ var(53) , var(33) ] D[34,53] = var(34); // [ var(53) , var(34) ] D[35,53] = (-1)*var(35); // [ var(53) , var(35) ] D[37,53] = (-1)*var(37); // [ var(53) , var(37) ] D[38,53] = var(38); // [ var(53) , var(38) ] D[41,53] = (-1)*var(41); // [ var(53) , var(41) ] D[46,53] = var(46); // [ var(53) , var(46) ] D[47,53] = var(47); // [ var(53) , var(47) ] D[48,53] = (-1)*var(48); // [ var(53) , var(48) ] D[49,53] = (-1)*var(49); // [ var(53) , var(49) ] D[28,54] = var(28); // [ var(54) , var(28) ] D[29,54] = (-2)*var(29); // [ var(54) , var(29) ] D[30,54] = var(30); // [ var(54) , var(30) ] D[32,54] = var(32); // [ var(54) , var(32) ] D[33,54] = (-1)*var(33); // [ var(54) , var(33) ] D[34,54] = (-1)*var(34); // [ var(54) , var(34) ] D[35,54] = var(35); // [ var(54) , var(35) ] D[36,54] = (-1)*var(36); // [ var(54) , var(36) ] D[39,54] = (-1)*var(39); // [ var(54) , var(39) ] D[41,54] = var(41); // [ var(54) , var(41) ] D[43,54] = var(43); // [ var(54) , var(43) ] D[44,54] = (-1)*var(44); // [ var(54) , var(44) ] D[45,54] = var(45); // [ var(54) , var(45) ] D[46,54] = (-1)*var(46); // [ var(54) , var(46) ] D[47,54] = (-1)*var(47); // [ var(54) , var(47) ] D[29,55] = (2)*var(29); // [ var(55) , var(29) ] D[30,55] = (-2)*var(30); // [ var(55) , var(30) ] D[33,55] = (2)*var(33); // [ var(55) , var(33) ] D[36,55] = (2)*var(36); // [ var(55) , var(36) ] D[38,55] = (-2)*var(38); // [ var(55) , var(38) ] D[39,55] = (2)*var(39); // [ var(55) , var(39) ] D[41,55] = (-2)*var(41); // [ var(55) , var(41) ] D[43,55] = (-2)*var(43); // [ var(55) , var(43) ] D[45,55] = (-2)*var(45); // [ var(55) , var(45) ] // Y(i) * X(j): D[1,26] = (-1)*var(51); // [ var(26) , var(1) ] D[6,26] = var(2); // [ var(26) , var(6) ] D[10,26] = var(7); // [ var(26) , var(10) ] D[14,26] = var(11); // [ var(26) , var(14) ] D[17,26] = var(15); // [ var(26) , var(17) ] D[20,26] = var(18); // [ var(26) , var(20) ] D[22,26] = var(21); // [ var(26) , var(22) ] D[24,26] = var(23); // [ var(26) , var(24) ] D[2,27] = (-1)*var(52); // [ var(27) , var(2) ] D[6,27] = (-1)*var(1); // [ var(27) , var(6) ] D[7,27] = var(3); // [ var(27) , var(7) ] D[11,27] = var(8); // [ var(27) , var(11) ] D[15,27] = var(12); // [ var(27) , var(15) ] D[18,27] = var(16); // [ var(27) , var(18) ] D[21,27] = var(19); // [ var(27) , var(21) ] D[25,27] = var(24); // [ var(27) , var(25) ] D[3,28] = (-1)*var(53); // [ var(28) , var(3) ] D[7,28] = (-1)*var(2); // [ var(28) , var(7) ] D[8,28] = var(4); // [ var(28) , var(8) ] D[10,28] = (-1)*var(6); // [ var(28) , var(10) ] D[12,28] = var(9); // [ var(28) , var(12) ] D[16,28] = var(13); // [ var(28) , var(16) ] D[23,28] = var(21); // [ var(28) , var(23) ] D[24,28] = var(22); // [ var(28) , var(24) ] D[4,29] = (-1)*var(54); // [ var(29) , var(4) ] D[8,29] = (-1)*var(3); // [ var(29) , var(8) ] D[9,29] = var(5); // [ var(29) , var(9) ] D[11,29] = (-1)*var(7); // [ var(29) , var(11) ] D[14,29] = (-1)*var(10); // [ var(29) , var(14) ] D[19,29] = var(16); // [ var(29) , var(19) ] D[21,29] = var(18); // [ var(29) , var(21) ] D[22,29] = var(20); // [ var(29) , var(22) ] D[5,30] = (-1)*var(55); // [ var(30) , var(5) ] D[9,30] = (-2)*var(4); // [ var(30) , var(9) ] D[12,30] = (-2)*var(8); // [ var(30) , var(12) ] D[13,30] = (-1)*var(9); // [ var(30) , var(13) ] D[15,30] = (-2)*var(11); // [ var(30) , var(15) ] D[16,30] = (-1)*var(12); // [ var(30) , var(16) ] D[17,30] = (-2)*var(14); // [ var(30) , var(17) ] D[18,30] = (-1)*var(15); // [ var(30) , var(18) ] D[20,30] = (-1)*var(17); // [ var(30) , var(20) ] D[1,31] = var(27); // [ var(31) , var(1) ] D[2,31] = (-1)*var(26); // [ var(31) , var(2) ] D[6,31] = (-1)*var(51)+(-1)*var(52); // [ var(31) , var(6) ] D[10,31] = var(3); // [ var(31) , var(10) ] D[14,31] = var(8); // [ var(31) , var(14) ] D[17,31] = var(12); // [ var(31) , var(17) ] D[20,31] = var(16); // [ var(31) , var(20) ] D[22,31] = var(19); // [ var(31) , var(22) ] D[25,31] = (-1)*var(23); // [ var(31) , var(25) ] D[2,32] = var(28); // [ var(32) , var(2) ] D[3,32] = (-1)*var(27); // [ var(32) , var(3) ] D[7,32] = (-1)*var(52)+(-1)*var(53); // [ var(32) , var(7) ] D[10,32] = (-1)*var(1); // [ var(32) , var(10) ] D[11,32] = var(4); // [ var(32) , var(11) ] D[15,32] = var(9); // [ var(32) , var(15) ] D[18,32] = var(13); // [ var(32) , var(18) ] D[23,32] = (-1)*var(19); // [ var(32) , var(23) ] D[25,32] = var(22); // [ var(32) , var(25) ] D[3,33] = var(29); // [ var(33) , var(3) ] D[4,33] = (-1)*var(28); // [ var(33) , var(4) ] D[8,33] = (-1)*var(53)+(-1)*var(54); // [ var(33) , var(8) ] D[11,33] = (-1)*var(2); // [ var(33) , var(11) ] D[12,33] = var(5); // [ var(33) , var(12) ] D[14,33] = (-1)*var(6); // [ var(33) , var(14) ] D[19,33] = (-1)*var(13); // [ var(33) , var(19) ] D[23,33] = var(18); // [ var(33) , var(23) ] D[24,33] = var(20); // [ var(33) , var(24) ] D[4,34] = var(30); // [ var(34) , var(4) ] D[5,34] = (-2)*var(29); // [ var(34) , var(5) ] D[9,34] = (-2)*var(54)+(-1)*var(55); // [ var(34) , var(9) ] D[12,34] = (-2)*var(3); // [ var(34) , var(12) ] D[13,34] = var(5); // [ var(34) , var(13) ] D[15,34] = (-2)*var(7); // [ var(34) , var(15) ] D[17,34] = (-2)*var(10); // [ var(34) , var(17) ] D[19,34] = (-1)*var(12); // [ var(34) , var(19) ] D[21,34] = (-1)*var(15); // [ var(34) , var(21) ] D[22,34] = (-1)*var(17); // [ var(34) , var(22) ] D[1,35] = var(32); // [ var(35) , var(1) ] D[3,35] = (-1)*var(31); // [ var(35) , var(3) ] D[6,35] = var(28); // [ var(35) , var(6) ] D[7,35] = (-1)*var(26); // [ var(35) , var(7) ] D[10,35] = (-1)*var(51)+(-1)*var(52)+(-1)*var(53); // [ var(35) , var(10) ] D[14,35] = var(4); // [ var(35) , var(14) ] D[17,35] = var(9); // [ var(35) , var(17) ] D[20,35] = var(13); // [ var(35) , var(20) ] D[24,35] = (-1)*var(19); // [ var(35) , var(24) ] D[25,35] = (-1)*var(21); // [ var(35) , var(25) ] D[2,36] = var(33); // [ var(36) , var(2) ] D[4,36] = (-1)*var(32); // [ var(36) , var(4) ] D[7,36] = var(29); // [ var(36) , var(7) ] D[8,36] = (-1)*var(27); // [ var(36) , var(8) ] D[11,36] = (-1)*var(52)+(-1)*var(53)+(-1)*var(54); // [ var(36) , var(11) ] D[14,36] = (-1)*var(1); // [ var(36) , var(14) ] D[15,36] = var(5); // [ var(36) , var(15) ] D[21,36] = (-1)*var(13); // [ var(36) , var(21) ] D[23,36] = (-1)*var(16); // [ var(36) , var(23) ] D[25,36] = var(20); // [ var(36) , var(25) ] D[3,37] = var(34); // [ var(37) , var(3) ] D[5,37] = (-2)*var(33); // [ var(37) , var(5) ] D[8,37] = var(30); // [ var(37) , var(8) ] D[9,37] = (-2)*var(28); // [ var(37) , var(9) ] D[12,37] = (-2)*var(53)+(-2)*var(54)+(-1)*var(55); // [ var(37) , var(12) ] D[15,37] = (-2)*var(2); // [ var(37) , var(15) ] D[16,37] = var(5); // [ var(37) , var(16) ] D[17,37] = (-2)*var(6); // [ var(37) , var(17) ] D[19,37] = var(9); // [ var(37) , var(19) ] D[23,37] = (-1)*var(15); // [ var(37) , var(23) ] D[24,37] = (-1)*var(17); // [ var(37) , var(24) ] D[5,38] = (-1)*var(34); // [ var(38) , var(5) ] D[9,38] = var(30); // [ var(38) , var(9) ] D[13,38] = (-1)*var(54)+(-1)*var(55); // [ var(38) , var(13) ] D[16,38] = (-1)*var(3); // [ var(38) , var(16) ] D[18,38] = (-1)*var(7); // [ var(38) , var(18) ] D[19,38] = var(8); // [ var(38) , var(19) ] D[20,38] = (-1)*var(10); // [ var(38) , var(20) ] D[21,38] = var(11); // [ var(38) , var(21) ] D[22,38] = var(14); // [ var(38) , var(22) ] D[1,39] = var(36); // [ var(39) , var(1) ] D[4,39] = (-1)*var(35); // [ var(39) , var(4) ] D[6,39] = var(33); // [ var(39) , var(6) ] D[8,39] = (-1)*var(31); // [ var(39) , var(8) ] D[10,39] = var(29); // [ var(39) , var(10) ] D[11,39] = (-1)*var(26); // [ var(39) , var(11) ] D[14,39] = (-1)*var(51)+(-1)*var(52)+(-1)*var(53)+(-1)*var(54); // [ var(39) , var(14) ] D[17,39] = var(5); // [ var(39) , var(17) ] D[22,39] = (-1)*var(13); // [ var(39) , var(22) ] D[24,39] = (-1)*var(16); // [ var(39) , var(24) ] D[25,39] = (-1)*var(18); // [ var(39) , var(25) ] D[2,40] = var(37); // [ var(40) , var(2) ] D[5,40] = (-2)*var(36); // [ var(40) , var(5) ] D[7,40] = var(34); // [ var(40) , var(7) ] D[9,40] = (-2)*var(32); // [ var(40) , var(9) ] D[11,40] = var(30); // [ var(40) , var(11) ] D[12,40] = (-2)*var(27); // [ var(40) , var(12) ] D[15,40] = (-2)*var(52)+(-2)*var(53)+(-2)*var(54)+(-1)*var(55); // [ var(40) , var(15) ] D[17,40] = (-2)*var(1); // [ var(40) , var(17) ] D[18,40] = var(5); // [ var(40) , var(18) ] D[21,40] = var(9); // [ var(40) , var(21) ] D[23,40] = var(12); // [ var(40) , var(23) ] D[25,40] = (-1)*var(17); // [ var(40) , var(25) ] D[3,41] = var(38); // [ var(41) , var(3) ] D[5,41] = (-1)*var(37); // [ var(41) , var(5) ] D[12,41] = var(30); // [ var(41) , var(12) ] D[13,41] = (-1)*var(28); // [ var(41) , var(13) ] D[16,41] = (-1)*var(53)+(-1)*var(54)+(-1)*var(55); // [ var(41) , var(16) ] D[18,41] = (-1)*var(2); // [ var(41) , var(18) ] D[19,41] = (-1)*var(4); // [ var(41) , var(19) ] D[20,41] = (-1)*var(6); // [ var(41) , var(20) ] D[23,41] = var(11); // [ var(41) , var(23) ] D[24,41] = var(14); // [ var(41) , var(24) ] D[1,42] = var(40); // [ var(42) , var(1) ] D[5,42] = (-2)*var(39); // [ var(42) , var(5) ] D[6,42] = var(37); // [ var(42) , var(6) ] D[9,42] = (-2)*var(35); // [ var(42) , var(9) ] D[10,42] = var(34); // [ var(42) , var(10) ] D[12,42] = (-2)*var(31); // [ var(42) , var(12) ] D[14,42] = var(30); // [ var(42) , var(14) ] D[15,42] = (-2)*var(26); // [ var(42) , var(15) ] D[17,42] = (-2)*var(51)+(-2)*var(52)+(-2)*var(53)+(-2)*var(54)+(-1)*var(55); // [ var(42) , var(17) ] D[20,42] = var(5); // [ var(42) , var(20) ] D[22,42] = var(9); // [ var(42) , var(22) ] D[24,42] = var(12); // [ var(42) , var(24) ] D[25,42] = var(15); // [ var(42) , var(25) ] D[2,43] = var(41); // [ var(43) , var(2) ] D[5,43] = (-1)*var(40); // [ var(43) , var(5) ] D[7,43] = var(38); // [ var(43) , var(7) ] D[13,43] = (-1)*var(32); // [ var(43) , var(13) ] D[15,43] = var(30); // [ var(43) , var(15) ] D[16,43] = (-1)*var(27); // [ var(43) , var(16) ] D[18,43] = (-1)*var(52)+(-1)*var(53)+(-1)*var(54)+(-1)*var(55); // [ var(43) , var(18) ] D[20,43] = (-1)*var(1); // [ var(43) , var(20) ] D[21,43] = (-1)*var(4); // [ var(43) , var(21) ] D[23,43] = (-1)*var(8); // [ var(43) , var(23) ] D[25,43] = var(14); // [ var(43) , var(25) ] D[4,44] = var(41); // [ var(44) , var(4) ] D[8,44] = (-1)*var(38); // [ var(44) , var(8) ] D[9,44] = (-1)*var(37); // [ var(44) , var(9) ] D[12,44] = var(34); // [ var(44) , var(12) ] D[13,44] = var(33); // [ var(44) , var(13) ] D[16,44] = (-1)*var(29); // [ var(44) , var(16) ] D[19,44] = (-1)*var(53)+(-2)*var(54)+(-1)*var(55); // [ var(44) , var(19) ] D[21,44] = (-1)*var(2); // [ var(44) , var(21) ] D[22,44] = (-1)*var(6); // [ var(44) , var(22) ] D[23,44] = var(7); // [ var(44) , var(23) ] D[24,44] = var(10); // [ var(44) , var(24) ] D[1,45] = var(43); // [ var(45) , var(1) ] D[5,45] = (-1)*var(42); // [ var(45) , var(5) ] D[6,45] = var(41); // [ var(45) , var(6) ] D[10,45] = var(38); // [ var(45) , var(10) ] D[13,45] = (-1)*var(35); // [ var(45) , var(13) ] D[16,45] = (-1)*var(31); // [ var(45) , var(16) ] D[17,45] = var(30); // [ var(45) , var(17) ] D[18,45] = (-1)*var(26); // [ var(45) , var(18) ] D[20,45] = (-1)*var(51)+(-1)*var(52)+(-1)*var(53)+(-1)*var(54)+(-1)*var(55); // [ var(45) , var(20) ] D[22,45] = (-1)*var(4); // [ var(45) , var(22) ] D[24,45] = (-1)*var(8); // [ var(45) , var(24) ] D[25,45] = (-1)*var(11); // [ var(45) , var(25) ] D[2,46] = var(44); // [ var(46) , var(2) ] D[4,46] = var(43); // [ var(46) , var(4) ] D[9,46] = (-1)*var(40); // [ var(46) , var(9) ] D[11,46] = (-1)*var(38); // [ var(46) , var(11) ] D[13,46] = var(36); // [ var(46) , var(13) ] D[15,46] = var(34); // [ var(46) , var(15) ] D[18,46] = (-1)*var(29); // [ var(46) , var(18) ] D[19,46] = (-1)*var(27); // [ var(46) , var(19) ] D[21,46] = (-1)*var(52)+(-1)*var(53)+(-2)*var(54)+(-1)*var(55); // [ var(46) , var(21) ] D[22,46] = (-1)*var(1); // [ var(46) , var(22) ] D[23,46] = (-1)*var(3); // [ var(46) , var(23) ] D[25,46] = var(10); // [ var(46) , var(25) ] D[1,47] = var(46); // [ var(47) , var(1) ] D[4,47] = var(45); // [ var(47) , var(4) ] D[6,47] = var(44); // [ var(47) , var(6) ] D[9,47] = (-1)*var(42); // [ var(47) , var(9) ] D[13,47] = var(39); // [ var(47) , var(13) ] D[14,47] = (-1)*var(38); // [ var(47) , var(14) ] D[17,47] = var(34); // [ var(47) , var(17) ] D[19,47] = (-1)*var(31); // [ var(47) , var(19) ] D[20,47] = (-1)*var(29); // [ var(47) , var(20) ] D[21,47] = (-1)*var(26); // [ var(47) , var(21) ] D[22,47] = (-1)*var(51)+(-1)*var(52)+(-1)*var(53)+(-2)*var(54)+(-1)*var(55); // [ var(47) , var(22) ] D[24,47] = (-1)*var(3); // [ var(47) , var(24) ] D[25,47] = (-1)*var(7); // [ var(47) , var(25) ] D[3,48] = var(46); // [ var(48) , var(3) ] D[7,48] = (-1)*var(44); // [ var(48) , var(7) ] D[8,48] = var(43); // [ var(48) , var(8) ] D[11,48] = (-1)*var(41); // [ var(48) , var(11) ] D[12,48] = (-1)*var(40); // [ var(48) , var(12) ] D[15,48] = var(37); // [ var(48) , var(15) ] D[16,48] = var(36); // [ var(48) , var(16) ] D[18,48] = (-1)*var(33); // [ var(48) , var(18) ] D[19,48] = var(32); // [ var(48) , var(19) ] D[21,48] = (-1)*var(28); // [ var(48) , var(21) ] D[23,48] = (-1)*var(52)+(-2)*var(53)+(-2)*var(54)+(-1)*var(55); // [ var(48) , var(23) ] D[24,48] = (-1)*var(1); // [ var(48) , var(24) ] D[25,48] = var(6); // [ var(48) , var(25) ] D[1,49] = var(48); // [ var(49) , var(1) ] D[3,49] = var(47); // [ var(49) , var(3) ] D[8,49] = var(45); // [ var(49) , var(8) ] D[10,49] = (-1)*var(44); // [ var(49) , var(10) ] D[12,49] = (-1)*var(42); // [ var(49) , var(12) ] D[14,49] = (-1)*var(41); // [ var(49) , var(14) ] D[16,49] = var(39); // [ var(49) , var(16) ] D[17,49] = var(37); // [ var(49) , var(17) ] D[19,49] = var(35); // [ var(49) , var(19) ] D[20,49] = (-1)*var(33); // [ var(49) , var(20) ] D[22,49] = (-1)*var(28); // [ var(49) , var(22) ] D[23,49] = (-1)*var(26); // [ var(49) , var(23) ] D[24,49] = (-1)*var(51)+(-1)*var(52)+(-2)*var(53)+(-2)*var(54)+(-1)*var(55); // [ var(49) , var(24) ] D[25,49] = (-1)*var(2); // [ var(49) , var(25) ] D[2,50] = var(49); // [ var(50) , var(2) ] D[6,50] = (-1)*var(48); // [ var(50) , var(6) ] D[7,50] = var(47); // [ var(50) , var(7) ] D[10,50] = (-1)*var(46); // [ var(50) , var(10) ] D[11,50] = var(45); // [ var(50) , var(11) ] D[14,50] = (-1)*var(43); // [ var(50) , var(14) ] D[15,50] = (-1)*var(42); // [ var(50) , var(15) ] D[17,50] = var(40); // [ var(50) , var(17) ] D[18,50] = var(39); // [ var(50) , var(18) ] D[20,50] = (-1)*var(36); // [ var(50) , var(20) ] D[21,50] = var(35); // [ var(50) , var(21) ] D[22,50] = (-1)*var(32); // [ var(50) , var(22) ] D[23,50] = var(31); // [ var(50) , var(23) ] D[24,50] = (-1)*var(27); // [ var(50) , var(24) ] D[25,50] = (-1)*var(51)+(-2)*var(52)+(-2)*var(53)+(-2)*var(54)+(-1)*var(55); // [ var(50) , var(25) ] // X(i) * X(j): D[1,2] = (-1)*var(6); // [ var(2) , var(1) ] D[1,7] = (-1)*var(10); // [ var(7) , var(1) ] D[1,11] = (-1)*var(14); // [ var(11) , var(1) ] D[1,15] = (-1)*var(17); // [ var(15) , var(1) ] D[1,18] = (-1)*var(20); // [ var(18) , var(1) ] D[1,21] = (-1)*var(22); // [ var(21) , var(1) ] D[1,23] = (-1)*var(24); // [ var(23) , var(1) ] D[2,3] = (-1)*var(7); // [ var(3) , var(2) ] D[2,8] = (-1)*var(11); // [ var(8) , var(2) ] D[2,12] = (-1)*var(15); // [ var(12) , var(2) ] D[2,16] = (-1)*var(18); // [ var(16) , var(2) ] D[2,19] = (-1)*var(21); // [ var(19) , var(2) ] D[2,24] = (-1)*var(25); // [ var(24) , var(2) ] D[3,4] = (-1)*var(8); // [ var(4) , var(3) ] D[3,6] = var(10); // [ var(6) , var(3) ] D[3,9] = (-1)*var(12); // [ var(9) , var(3) ] D[3,13] = (-1)*var(16); // [ var(13) , var(3) ] D[3,21] = (-1)*var(23); // [ var(21) , var(3) ] D[3,22] = (-1)*var(24); // [ var(22) , var(3) ] D[4,5] = (-1)*var(9); // [ var(5) , var(4) ] D[4,7] = var(11); // [ var(7) , var(4) ] D[4,10] = var(14); // [ var(10) , var(4) ] D[4,16] = (-1)*var(19); // [ var(16) , var(4) ] D[4,18] = (-1)*var(21); // [ var(18) , var(4) ] D[4,20] = (-1)*var(22); // [ var(20) , var(4) ] D[5,8] = var(12); // [ var(8) , var(5) ] D[5,9] = (2)*var(13); // [ var(9) , var(5) ] D[5,11] = var(15); // [ var(11) , var(5) ] D[5,12] = (2)*var(16); // [ var(12) , var(5) ] D[5,14] = var(17); // [ var(14) , var(5) ] D[5,15] = (2)*var(18); // [ var(15) , var(5) ] D[5,17] = (2)*var(20); // [ var(17) , var(5) ] D[6,8] = (-1)*var(14); // [ var(8) , var(6) ] D[6,12] = (-1)*var(17); // [ var(12) , var(6) ] D[6,16] = (-1)*var(20); // [ var(16) , var(6) ] D[6,19] = (-1)*var(22); // [ var(19) , var(6) ] D[6,23] = var(25); // [ var(23) , var(6) ] D[7,9] = (-1)*var(15); // [ var(9) , var(7) ] D[7,13] = (-1)*var(18); // [ var(13) , var(7) ] D[7,19] = var(23); // [ var(19) , var(7) ] D[7,22] = (-1)*var(25); // [ var(22) , var(7) ] D[8,13] = var(19); // [ var(13) , var(8) ] D[8,18] = (-1)*var(23); // [ var(18) , var(8) ] D[8,20] = (-1)*var(24); // [ var(20) , var(8) ] D[9,10] = var(17); // [ var(10) , var(9) ] D[9,12] = (2)*var(19); // [ var(12) , var(9) ] D[9,15] = (2)*var(21); // [ var(15) , var(9) ] D[9,17] = (2)*var(22); // [ var(17) , var(9) ] D[10,13] = (-1)*var(20); // [ var(13) , var(10) ] D[10,19] = var(24); // [ var(19) , var(10) ] D[10,21] = var(25); // [ var(21) , var(10) ] D[11,13] = var(21); // [ var(13) , var(11) ] D[11,16] = var(23); // [ var(16) , var(11) ] D[11,20] = (-1)*var(25); // [ var(20) , var(11) ] D[12,15] = (2)*var(23); // [ var(15) , var(12) ] D[12,17] = (2)*var(24); // [ var(17) , var(12) ] D[13,14] = (-1)*var(22); // [ var(14) , var(13) ] D[14,16] = var(24); // [ var(16) , var(14) ] D[14,18] = var(25); // [ var(18) , var(14) ] D[15,17] = (2)*var(25); // [ var(17) , var(15) ] // Y(i) * Y(j): D[26,27] = var(31); // [ var(27) , var(26) ] D[26,32] = var(35); // [ var(32) , var(26) ] D[26,36] = var(39); // [ var(36) , var(26) ] D[26,40] = var(42); // [ var(40) , var(26) ] D[26,43] = var(45); // [ var(43) , var(26) ] D[26,46] = var(47); // [ var(46) , var(26) ] D[26,48] = var(49); // [ var(48) , var(26) ] D[27,28] = var(32); // [ var(28) , var(27) ] D[27,33] = var(36); // [ var(33) , var(27) ] D[27,37] = var(40); // [ var(37) , var(27) ] D[27,41] = var(43); // [ var(41) , var(27) ] D[27,44] = var(46); // [ var(44) , var(27) ] D[27,49] = var(50); // [ var(49) , var(27) ] D[28,29] = var(33); // [ var(29) , var(28) ] D[28,31] = (-1)*var(35); // [ var(31) , var(28) ] D[28,34] = var(37); // [ var(34) , var(28) ] D[28,38] = var(41); // [ var(38) , var(28) ] D[28,46] = var(48); // [ var(46) , var(28) ] D[28,47] = var(49); // [ var(47) , var(28) ] D[29,30] = var(34); // [ var(30) , var(29) ] D[29,32] = (-1)*var(36); // [ var(32) , var(29) ] D[29,35] = (-1)*var(39); // [ var(35) , var(29) ] D[29,41] = var(44); // [ var(41) , var(29) ] D[29,43] = var(46); // [ var(43) , var(29) ] D[29,45] = var(47); // [ var(45) , var(29) ] D[30,33] = (-1)*var(37); // [ var(33) , var(30) ] D[30,34] = (-2)*var(38); // [ var(34) , var(30) ] D[30,36] = (-1)*var(40); // [ var(36) , var(30) ] D[30,37] = (-2)*var(41); // [ var(37) , var(30) ] D[30,39] = (-1)*var(42); // [ var(39) , var(30) ] D[30,40] = (-2)*var(43); // [ var(40) , var(30) ] D[30,42] = (-2)*var(45); // [ var(42) , var(30) ] D[31,33] = var(39); // [ var(33) , var(31) ] D[31,37] = var(42); // [ var(37) , var(31) ] D[31,41] = var(45); // [ var(41) , var(31) ] D[31,44] = var(47); // [ var(44) , var(31) ] D[31,48] = (-1)*var(50); // [ var(48) , var(31) ] D[32,34] = var(40); // [ var(34) , var(32) ] D[32,38] = var(43); // [ var(38) , var(32) ] D[32,44] = (-1)*var(48); // [ var(44) , var(32) ] D[32,47] = var(50); // [ var(47) , var(32) ] D[33,38] = (-1)*var(44); // [ var(38) , var(33) ] D[33,43] = var(48); // [ var(43) , var(33) ] D[33,45] = var(49); // [ var(45) , var(33) ] D[34,35] = (-1)*var(42); // [ var(35) , var(34) ] D[34,37] = (-2)*var(44); // [ var(37) , var(34) ] D[34,40] = (-2)*var(46); // [ var(40) , var(34) ] D[34,42] = (-2)*var(47); // [ var(42) , var(34) ] D[35,38] = var(45); // [ var(38) , var(35) ] D[35,44] = (-1)*var(49); // [ var(44) , var(35) ] D[35,46] = (-1)*var(50); // [ var(46) , var(35) ] D[36,38] = (-1)*var(46); // [ var(38) , var(36) ] D[36,41] = (-1)*var(48); // [ var(41) , var(36) ] D[36,45] = var(50); // [ var(45) , var(36) ] D[37,40] = (-2)*var(48); // [ var(40) , var(37) ] D[37,42] = (-2)*var(49); // [ var(42) , var(37) ] D[38,39] = var(47); // [ var(39) , var(38) ] D[39,41] = (-1)*var(49); // [ var(41) , var(39) ] D[39,43] = (-1)*var(50); // [ var(43) , var(39) ] D[40,42] = (-2)*var(50); // [ var(42) , var(40) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUso11(); ncAlgebra; setring ncAlgebra; // ... 523 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: sp1(Q) has the type: C1, and defined by: proc makeUsp1(list #) "USAGE: makeUsp1([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(sp_1) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(sp_1) is derived from the Chevalley representation of sp_1, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUsp1; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..1),Y(1..1),H(1..1)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,3] = (2)*var(1); // [ var(3) , var(1) ] // H(i) * Y(j): D[2,3] = (-2)*var(2); // [ var(3) , var(2) ] // Y(i) * X(j): D[1,2] = (-1)*var(3); // [ var(2) , var(1) ] // X(i) * X(j): // Y(i) * Y(j): def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUsp1(); setring ncAlgebra; ncAlgebra; } //////////////////////////////////////////////////////////////////// // Algebra: sp2(Q) has the type: C2, and defined by: proc makeUsp2(list #) "USAGE: makeUsp2([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(sp_2) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(sp_2) is derived from the Chevalley representation of sp_2, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUsp2; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..4),Y(1..4),H(1..2)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,9] = (2)*var(1); // [ var(9) , var(1) ] D[2,9] = (-2)*var(2); // [ var(9) , var(2) ] D[4,9] = (2)*var(4); // [ var(9) , var(4) ] D[1,10] = (-1)*var(1); // [ var(10) , var(1) ] D[2,10] = (2)*var(2); // [ var(10) , var(2) ] D[3,10] = var(3); // [ var(10) , var(3) ] // H(i) * Y(j): D[5,9] = (-2)*var(5); // [ var(9) , var(5) ] D[6,9] = (2)*var(6); // [ var(9) , var(6) ] D[8,9] = (-2)*var(8); // [ var(9) , var(8) ] D[5,10] = var(5); // [ var(10) , var(5) ] D[6,10] = (-2)*var(6); // [ var(10) , var(6) ] D[7,10] = (-1)*var(7); // [ var(10) , var(7) ] // Y(i) * X(j): D[1,5] = (-1)*var(9); // [ var(5) , var(1) ] D[3,5] = (-2)*var(2); // [ var(5) , var(3) ] D[4,5] = (-1)*var(3); // [ var(5) , var(4) ] D[2,6] = (-1)*var(10); // [ var(6) , var(2) ] D[3,6] = var(1); // [ var(6) , var(3) ] D[1,7] = (-2)*var(6); // [ var(7) , var(1) ] D[2,7] = var(5); // [ var(7) , var(2) ] D[3,7] = (-1)*var(9)+(-2)*var(10); // [ var(7) , var(3) ] D[4,7] = var(1); // [ var(7) , var(4) ] D[1,8] = (-1)*var(7); // [ var(8) , var(1) ] D[3,8] = var(5); // [ var(8) , var(3) ] D[4,8] = (-1)*var(9)+(-1)*var(10); // [ var(8) , var(4) ] // X(i) * X(j): D[1,2] = var(3); // [ var(2) , var(1) ] D[1,3] = (2)*var(4); // [ var(3) , var(1) ] // Y(i) * Y(j): D[5,6] = (-1)*var(7); // [ var(6) , var(5) ] D[5,7] = (-2)*var(8); // [ var(7) , var(5) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUsp2(); setring ncAlgebra; ncAlgebra; } //////////////////////////////////////////////////////////////////// // Algebra: sp3(Q) has the type: C3, and defined by: proc makeUsp3(list #) "USAGE: makeUsp3([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(sp_3) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(sp_3) is derived from the Chevalley representation of sp_3, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUsp3; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..9),Y(1..9),H(1..3)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,19] = (2)*var(1); // [ var(19) , var(1) ] D[2,19] = (-1)*var(2); // [ var(19) , var(2) ] D[4,19] = var(4); // [ var(19) , var(4) ] D[5,19] = (-1)*var(5); // [ var(19) , var(5) ] D[6,19] = var(6); // [ var(19) , var(6) ] D[7,19] = (-2)*var(7); // [ var(19) , var(7) ] D[9,19] = (2)*var(9); // [ var(19) , var(9) ] D[1,20] = (-1)*var(1); // [ var(20) , var(1) ] D[2,20] = (2)*var(2); // [ var(20) , var(2) ] D[3,20] = (-2)*var(3); // [ var(20) , var(3) ] D[4,20] = var(4); // [ var(20) , var(4) ] D[6,20] = (-1)*var(6); // [ var(20) , var(6) ] D[7,20] = (2)*var(7); // [ var(20) , var(7) ] D[8,20] = var(8); // [ var(20) , var(8) ] D[2,21] = (-1)*var(2); // [ var(21) , var(2) ] D[3,21] = (2)*var(3); // [ var(21) , var(3) ] D[4,21] = (-1)*var(4); // [ var(21) , var(4) ] D[5,21] = var(5); // [ var(21) , var(5) ] D[6,21] = var(6); // [ var(21) , var(6) ] // H(i) * Y(j): D[10,19] = (-2)*var(10); // [ var(19) , var(10) ] D[11,19] = var(11); // [ var(19) , var(11) ] D[13,19] = (-1)*var(13); // [ var(19) , var(13) ] D[14,19] = var(14); // [ var(19) , var(14) ] D[15,19] = (-1)*var(15); // [ var(19) , var(15) ] D[16,19] = (2)*var(16); // [ var(19) , var(16) ] D[18,19] = (-2)*var(18); // [ var(19) , var(18) ] D[10,20] = var(10); // [ var(20) , var(10) ] D[11,20] = (-2)*var(11); // [ var(20) , var(11) ] D[12,20] = (2)*var(12); // [ var(20) , var(12) ] D[13,20] = (-1)*var(13); // [ var(20) , var(13) ] D[15,20] = var(15); // [ var(20) , var(15) ] D[16,20] = (-2)*var(16); // [ var(20) , var(16) ] D[17,20] = (-1)*var(17); // [ var(20) , var(17) ] D[11,21] = var(11); // [ var(21) , var(11) ] D[12,21] = (-2)*var(12); // [ var(21) , var(12) ] D[13,21] = var(13); // [ var(21) , var(13) ] D[14,21] = (-1)*var(14); // [ var(21) , var(14) ] D[15,21] = (-1)*var(15); // [ var(21) , var(15) ] // Y(i) * X(j): D[1,10] = (-1)*var(19); // [ var(10) , var(1) ] D[4,10] = (-1)*var(2); // [ var(10) , var(4) ] D[6,10] = (-1)*var(5); // [ var(10) , var(6) ] D[8,10] = (-2)*var(7); // [ var(10) , var(8) ] D[9,10] = (-1)*var(8); // [ var(10) , var(9) ] D[2,11] = (-1)*var(20); // [ var(11) , var(2) ] D[4,11] = var(1); // [ var(11) , var(4) ] D[5,11] = (-2)*var(3); // [ var(11) , var(5) ] D[7,11] = (-1)*var(5); // [ var(11) , var(7) ] D[8,11] = (-1)*var(6); // [ var(11) , var(8) ] D[3,12] = (-1)*var(21); // [ var(12) , var(3) ] D[5,12] = var(2); // [ var(12) , var(5) ] D[6,12] = var(4); // [ var(12) , var(6) ] D[1,13] = (-1)*var(11); // [ var(13) , var(1) ] D[2,13] = var(10); // [ var(13) , var(2) ] D[4,13] = (-1)*var(19)+(-1)*var(20); // [ var(13) , var(4) ] D[6,13] = (-2)*var(3); // [ var(13) , var(6) ] D[8,13] = (-1)*var(5); // [ var(13) , var(8) ] D[9,13] = (-1)*var(6); // [ var(13) , var(9) ] D[2,14] = (-2)*var(12); // [ var(14) , var(2) ] D[3,14] = var(11); // [ var(14) , var(3) ] D[5,14] = (-1)*var(20)+(-2)*var(21); // [ var(14) , var(5) ] D[6,14] = var(1); // [ var(14) , var(6) ] D[7,14] = var(2); // [ var(14) , var(7) ] D[8,14] = var(4); // [ var(14) , var(8) ] D[1,15] = (-1)*var(14); // [ var(15) , var(1) ] D[3,15] = var(13); // [ var(15) , var(3) ] D[4,15] = (-2)*var(12); // [ var(15) , var(4) ] D[5,15] = var(10); // [ var(15) , var(5) ] D[6,15] = (-1)*var(19)+(-1)*var(20)+(-2)*var(21); // [ var(15) , var(6) ] D[8,15] = var(2); // [ var(15) , var(8) ] D[9,15] = var(4); // [ var(15) , var(9) ] D[2,16] = (-1)*var(14); // [ var(16) , var(2) ] D[5,16] = var(11); // [ var(16) , var(5) ] D[7,16] = (-1)*var(20)+(-1)*var(21); // [ var(16) , var(7) ] D[8,16] = var(1); // [ var(16) , var(8) ] D[1,17] = (-2)*var(16); // [ var(17) , var(1) ] D[2,17] = (-1)*var(15); // [ var(17) , var(2) ] D[4,17] = (-1)*var(14); // [ var(17) , var(4) ] D[5,17] = var(13); // [ var(17) , var(5) ] D[6,17] = var(11); // [ var(17) , var(6) ] D[7,17] = var(10); // [ var(17) , var(7) ] D[8,17] = (-1)*var(19)+(-2)*var(20)+(-2)*var(21); // [ var(17) , var(8) ] D[9,17] = var(1); // [ var(17) , var(9) ] D[1,18] = (-1)*var(17); // [ var(18) , var(1) ] D[4,18] = (-1)*var(15); // [ var(18) , var(4) ] D[6,18] = var(13); // [ var(18) , var(6) ] D[8,18] = var(10); // [ var(18) , var(8) ] D[9,18] = (-1)*var(19)+(-1)*var(20)+(-1)*var(21); // [ var(18) , var(9) ] // X(i) * X(j): D[1,2] = var(4); // [ var(2) , var(1) ] D[1,5] = var(6); // [ var(5) , var(1) ] D[1,7] = var(8); // [ var(7) , var(1) ] D[1,8] = (2)*var(9); // [ var(8) , var(1) ] D[2,3] = var(5); // [ var(3) , var(2) ] D[2,5] = (2)*var(7); // [ var(5) , var(2) ] D[2,6] = var(8); // [ var(6) , var(2) ] D[3,4] = (-1)*var(6); // [ var(4) , var(3) ] D[4,5] = var(8); // [ var(5) , var(4) ] D[4,6] = (2)*var(9); // [ var(6) , var(4) ] // Y(i) * Y(j): D[10,11] = (-1)*var(13); // [ var(11) , var(10) ] D[10,14] = (-1)*var(15); // [ var(14) , var(10) ] D[10,16] = (-1)*var(17); // [ var(16) , var(10) ] D[10,17] = (-2)*var(18); // [ var(17) , var(10) ] D[11,12] = (-1)*var(14); // [ var(12) , var(11) ] D[11,14] = (-2)*var(16); // [ var(14) , var(11) ] D[11,15] = (-1)*var(17); // [ var(15) , var(11) ] D[12,13] = var(15); // [ var(13) , var(12) ] D[13,14] = (-1)*var(17); // [ var(14) , var(13) ] D[13,15] = (-2)*var(18); // [ var(15) , var(13) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUsp3(); ncAlgebra; setring ncAlgebra; // ... 107 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: sp4(Q) has the type: C4, and defined by: proc makeUsp4(list #) "USAGE: makeUsp4([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(sp_4) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(sp_4) is derived from the Chevalley representation of sp_4, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUsp4; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..16),Y(1..16),H(1..4)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,33] = (2)*var(1); // [ var(33) , var(1) ] D[2,33] = (-1)*var(2); // [ var(33) , var(2) ] D[5,33] = var(5); // [ var(33) , var(5) ] D[6,33] = (-1)*var(6); // [ var(33) , var(6) ] D[8,33] = var(8); // [ var(33) , var(8) ] D[9,33] = (-1)*var(9); // [ var(33) , var(9) ] D[11,33] = var(11); // [ var(33) , var(11) ] D[12,33] = (-1)*var(12); // [ var(33) , var(12) ] D[13,33] = var(13); // [ var(33) , var(13) ] D[14,33] = (-2)*var(14); // [ var(33) , var(14) ] D[16,33] = (2)*var(16); // [ var(33) , var(16) ] D[1,34] = (-1)*var(1); // [ var(34) , var(1) ] D[2,34] = (2)*var(2); // [ var(34) , var(2) ] D[3,34] = (-1)*var(3); // [ var(34) , var(3) ] D[5,34] = var(5); // [ var(34) , var(5) ] D[6,34] = var(6); // [ var(34) , var(6) ] D[7,34] = (-1)*var(7); // [ var(34) , var(7) ] D[9,34] = var(9); // [ var(34) , var(9) ] D[10,34] = (-2)*var(10); // [ var(34) , var(10) ] D[13,34] = (-1)*var(13); // [ var(34) , var(13) ] D[14,34] = (2)*var(14); // [ var(34) , var(14) ] D[15,34] = var(15); // [ var(34) , var(15) ] D[2,35] = (-1)*var(2); // [ var(35) , var(2) ] D[3,35] = (2)*var(3); // [ var(35) , var(3) ] D[4,35] = (-2)*var(4); // [ var(35) , var(4) ] D[5,35] = (-1)*var(5); // [ var(35) , var(5) ] D[6,35] = var(6); // [ var(35) , var(6) ] D[8,35] = var(8); // [ var(35) , var(8) ] D[9,35] = (-1)*var(9); // [ var(35) , var(9) ] D[10,35] = (2)*var(10); // [ var(35) , var(10) ] D[11,35] = (-1)*var(11); // [ var(35) , var(11) ] D[12,35] = var(12); // [ var(35) , var(12) ] D[13,35] = var(13); // [ var(35) , var(13) ] D[3,36] = (-1)*var(3); // [ var(36) , var(3) ] D[4,36] = (2)*var(4); // [ var(36) , var(4) ] D[6,36] = (-1)*var(6); // [ var(36) , var(6) ] D[7,36] = var(7); // [ var(36) , var(7) ] D[8,36] = (-1)*var(8); // [ var(36) , var(8) ] D[9,36] = var(9); // [ var(36) , var(9) ] D[11,36] = var(11); // [ var(36) , var(11) ] // H(i) * Y(j): D[17,33] = (-2)*var(17); // [ var(33) , var(17) ] D[18,33] = var(18); // [ var(33) , var(18) ] D[21,33] = (-1)*var(21); // [ var(33) , var(21) ] D[22,33] = var(22); // [ var(33) , var(22) ] D[24,33] = (-1)*var(24); // [ var(33) , var(24) ] D[25,33] = var(25); // [ var(33) , var(25) ] D[27,33] = (-1)*var(27); // [ var(33) , var(27) ] D[28,33] = var(28); // [ var(33) , var(28) ] D[29,33] = (-1)*var(29); // [ var(33) , var(29) ] D[30,33] = (2)*var(30); // [ var(33) , var(30) ] D[32,33] = (-2)*var(32); // [ var(33) , var(32) ] D[17,34] = var(17); // [ var(34) , var(17) ] D[18,34] = (-2)*var(18); // [ var(34) , var(18) ] D[19,34] = var(19); // [ var(34) , var(19) ] D[21,34] = (-1)*var(21); // [ var(34) , var(21) ] D[22,34] = (-1)*var(22); // [ var(34) , var(22) ] D[23,34] = var(23); // [ var(34) , var(23) ] D[25,34] = (-1)*var(25); // [ var(34) , var(25) ] D[26,34] = (2)*var(26); // [ var(34) , var(26) ] D[29,34] = var(29); // [ var(34) , var(29) ] D[30,34] = (-2)*var(30); // [ var(34) , var(30) ] D[31,34] = (-1)*var(31); // [ var(34) , var(31) ] D[18,35] = var(18); // [ var(35) , var(18) ] D[19,35] = (-2)*var(19); // [ var(35) , var(19) ] D[20,35] = (2)*var(20); // [ var(35) , var(20) ] D[21,35] = var(21); // [ var(35) , var(21) ] D[22,35] = (-1)*var(22); // [ var(35) , var(22) ] D[24,35] = (-1)*var(24); // [ var(35) , var(24) ] D[25,35] = var(25); // [ var(35) , var(25) ] D[26,35] = (-2)*var(26); // [ var(35) , var(26) ] D[27,35] = var(27); // [ var(35) , var(27) ] D[28,35] = (-1)*var(28); // [ var(35) , var(28) ] D[29,35] = (-1)*var(29); // [ var(35) , var(29) ] D[19,36] = var(19); // [ var(36) , var(19) ] D[20,36] = (-2)*var(20); // [ var(36) , var(20) ] D[22,36] = var(22); // [ var(36) , var(22) ] D[23,36] = (-1)*var(23); // [ var(36) , var(23) ] D[24,36] = var(24); // [ var(36) , var(24) ] D[25,36] = (-1)*var(25); // [ var(36) , var(25) ] D[27,36] = (-1)*var(27); // [ var(36) , var(27) ] // Y(i) * X(j): D[1,17] = (-1)*var(33); // [ var(17) , var(1) ] D[5,17] = (-1)*var(2); // [ var(17) , var(5) ] D[8,17] = (-1)*var(6); // [ var(17) , var(8) ] D[11,17] = (-1)*var(9); // [ var(17) , var(11) ] D[13,17] = (-1)*var(12); // [ var(17) , var(13) ] D[15,17] = (-2)*var(14); // [ var(17) , var(15) ] D[16,17] = (-1)*var(15); // [ var(17) , var(16) ] D[2,18] = (-1)*var(34); // [ var(18) , var(2) ] D[5,18] = var(1); // [ var(18) , var(5) ] D[6,18] = (-1)*var(3); // [ var(18) , var(6) ] D[9,18] = (-1)*var(7); // [ var(18) , var(9) ] D[12,18] = (-2)*var(10); // [ var(18) , var(12) ] D[14,18] = (-1)*var(12); // [ var(18) , var(14) ] D[15,18] = (-1)*var(13); // [ var(18) , var(15) ] D[3,19] = (-1)*var(35); // [ var(19) , var(3) ] D[6,19] = var(2); // [ var(19) , var(6) ] D[7,19] = (-2)*var(4); // [ var(19) , var(7) ] D[8,19] = var(5); // [ var(19) , var(8) ] D[10,19] = (-1)*var(7); // [ var(19) , var(10) ] D[12,19] = (-1)*var(9); // [ var(19) , var(12) ] D[13,19] = (-1)*var(11); // [ var(19) , var(13) ] D[4,20] = (-1)*var(36); // [ var(20) , var(4) ] D[7,20] = var(3); // [ var(20) , var(7) ] D[9,20] = var(6); // [ var(20) , var(9) ] D[11,20] = var(8); // [ var(20) , var(11) ] D[1,21] = (-1)*var(18); // [ var(21) , var(1) ] D[2,21] = var(17); // [ var(21) , var(2) ] D[5,21] = (-1)*var(33)+(-1)*var(34); // [ var(21) , var(5) ] D[8,21] = (-1)*var(3); // [ var(21) , var(8) ] D[11,21] = (-1)*var(7); // [ var(21) , var(11) ] D[13,21] = (-2)*var(10); // [ var(21) , var(13) ] D[15,21] = (-1)*var(12); // [ var(21) , var(15) ] D[16,21] = (-1)*var(13); // [ var(21) , var(16) ] D[2,22] = (-1)*var(19); // [ var(22) , var(2) ] D[3,22] = var(18); // [ var(22) , var(3) ] D[6,22] = (-1)*var(34)+(-1)*var(35); // [ var(22) , var(6) ] D[8,22] = var(1); // [ var(22) , var(8) ] D[9,22] = (-2)*var(4); // [ var(22) , var(9) ] D[12,22] = (-1)*var(7); // [ var(22) , var(12) ] D[14,22] = (-1)*var(9); // [ var(22) , var(14) ] D[15,22] = (-1)*var(11); // [ var(22) , var(15) ] D[3,23] = (-2)*var(20); // [ var(23) , var(3) ] D[4,23] = var(19); // [ var(23) , var(4) ] D[7,23] = (-1)*var(35)+(-2)*var(36); // [ var(23) , var(7) ] D[9,23] = var(2); // [ var(23) , var(9) ] D[10,23] = var(3); // [ var(23) , var(10) ] D[11,23] = var(5); // [ var(23) , var(11) ] D[12,23] = var(6); // [ var(23) , var(12) ] D[13,23] = var(8); // [ var(23) , var(13) ] D[1,24] = (-1)*var(22); // [ var(24) , var(1) ] D[3,24] = var(21); // [ var(24) , var(3) ] D[5,24] = (-1)*var(19); // [ var(24) , var(5) ] D[6,24] = var(17); // [ var(24) , var(6) ] D[8,24] = (-1)*var(33)+(-1)*var(34)+(-1)*var(35); // [ var(24) , var(8) ] D[11,24] = (-2)*var(4); // [ var(24) , var(11) ] D[13,24] = (-1)*var(7); // [ var(24) , var(13) ] D[15,24] = (-1)*var(9); // [ var(24) , var(15) ] D[16,24] = (-1)*var(11); // [ var(24) , var(16) ] D[2,25] = (-1)*var(23); // [ var(25) , var(2) ] D[4,25] = var(22); // [ var(25) , var(4) ] D[6,25] = (-2)*var(20); // [ var(25) , var(6) ] D[7,25] = var(18); // [ var(25) , var(7) ] D[9,25] = (-1)*var(34)+(-1)*var(35)+(-2)*var(36); // [ var(25) , var(9) ] D[11,25] = var(1); // [ var(25) , var(11) ] D[12,25] = var(3); // [ var(25) , var(12) ] D[14,25] = var(6); // [ var(25) , var(14) ] D[15,25] = var(8); // [ var(25) , var(15) ] D[3,26] = (-1)*var(23); // [ var(26) , var(3) ] D[7,26] = var(19); // [ var(26) , var(7) ] D[10,26] = (-1)*var(35)+(-1)*var(36); // [ var(26) , var(10) ] D[12,26] = var(2); // [ var(26) , var(12) ] D[13,26] = var(5); // [ var(26) , var(13) ] D[1,27] = (-1)*var(25); // [ var(27) , var(1) ] D[4,27] = var(24); // [ var(27) , var(4) ] D[5,27] = (-1)*var(23); // [ var(27) , var(5) ] D[7,27] = var(21); // [ var(27) , var(7) ] D[8,27] = (-2)*var(20); // [ var(27) , var(8) ] D[9,27] = var(17); // [ var(27) , var(9) ] D[11,27] = (-1)*var(33)+(-1)*var(34)+(-1)*var(35)+(-2)*var(36); // [ var(27) , var(11) ] D[13,27] = var(3); // [ var(27) , var(13) ] D[15,27] = var(6); // [ var(27) , var(15) ] D[16,27] = var(8); // [ var(27) , var(16) ] D[2,28] = (-2)*var(26); // [ var(28) , var(2) ] D[3,28] = (-1)*var(25); // [ var(28) , var(3) ] D[6,28] = (-1)*var(23); // [ var(28) , var(6) ] D[7,28] = var(22); // [ var(28) , var(7) ] D[9,28] = var(19); // [ var(28) , var(9) ] D[10,28] = var(18); // [ var(28) , var(10) ] D[12,28] = (-1)*var(34)+(-2)*var(35)+(-2)*var(36); // [ var(28) , var(12) ] D[13,28] = var(1); // [ var(28) , var(13) ] D[14,28] = var(2); // [ var(28) , var(14) ] D[15,28] = var(5); // [ var(28) , var(15) ] D[1,29] = (-1)*var(28); // [ var(29) , var(1) ] D[3,29] = (-1)*var(27); // [ var(29) , var(3) ] D[5,29] = (-2)*var(26); // [ var(29) , var(5) ] D[7,29] = var(24); // [ var(29) , var(7) ] D[8,29] = (-1)*var(23); // [ var(29) , var(8) ] D[10,29] = var(21); // [ var(29) , var(10) ] D[11,29] = var(19); // [ var(29) , var(11) ] D[12,29] = var(17); // [ var(29) , var(12) ] D[13,29] = (-1)*var(33)+(-1)*var(34)+(-2)*var(35)+(-2)*var(36); // [ var(29) , var(13) ] D[15,29] = var(2); // [ var(29) , var(15) ] D[16,29] = var(5); // [ var(29) , var(16) ] D[2,30] = (-1)*var(28); // [ var(30) , var(2) ] D[6,30] = (-1)*var(25); // [ var(30) , var(6) ] D[9,30] = var(22); // [ var(30) , var(9) ] D[12,30] = var(18); // [ var(30) , var(12) ] D[14,30] = (-1)*var(34)+(-1)*var(35)+(-1)*var(36); // [ var(30) , var(14) ] D[15,30] = var(1); // [ var(30) , var(15) ] D[1,31] = (-2)*var(30); // [ var(31) , var(1) ] D[2,31] = (-1)*var(29); // [ var(31) , var(2) ] D[5,31] = (-1)*var(28); // [ var(31) , var(5) ] D[6,31] = (-1)*var(27); // [ var(31) , var(6) ] D[8,31] = (-1)*var(25); // [ var(31) , var(8) ] D[9,31] = var(24); // [ var(31) , var(9) ] D[11,31] = var(22); // [ var(31) , var(11) ] D[12,31] = var(21); // [ var(31) , var(12) ] D[13,31] = var(18); // [ var(31) , var(13) ] D[14,31] = var(17); // [ var(31) , var(14) ] D[15,31] = (-1)*var(33)+(-2)*var(34)+(-2)*var(35)+(-2)*var(36); // [ var(31) , var(15) ] D[16,31] = var(1); // [ var(31) , var(16) ] D[1,32] = (-1)*var(31); // [ var(32) , var(1) ] D[5,32] = (-1)*var(29); // [ var(32) , var(5) ] D[8,32] = (-1)*var(27); // [ var(32) , var(8) ] D[11,32] = var(24); // [ var(32) , var(11) ] D[13,32] = var(21); // [ var(32) , var(13) ] D[15,32] = var(17); // [ var(32) , var(15) ] D[16,32] = (-1)*var(33)+(-1)*var(34)+(-1)*var(35)+(-1)*var(36); // [ var(32) , var(16) ] // X(i) * X(j): D[1,2] = var(5); // [ var(2) , var(1) ] D[1,6] = var(8); // [ var(6) , var(1) ] D[1,9] = var(11); // [ var(9) , var(1) ] D[1,12] = var(13); // [ var(12) , var(1) ] D[1,14] = var(15); // [ var(14) , var(1) ] D[1,15] = (2)*var(16); // [ var(15) , var(1) ] D[2,3] = var(6); // [ var(3) , var(2) ] D[2,7] = var(9); // [ var(7) , var(2) ] D[2,10] = var(12); // [ var(10) , var(2) ] D[2,12] = (2)*var(14); // [ var(12) , var(2) ] D[2,13] = var(15); // [ var(13) , var(2) ] D[3,4] = var(7); // [ var(4) , var(3) ] D[3,5] = (-1)*var(8); // [ var(5) , var(3) ] D[3,7] = (2)*var(10); // [ var(7) , var(3) ] D[3,9] = var(12); // [ var(9) , var(3) ] D[3,11] = var(13); // [ var(11) , var(3) ] D[4,6] = (-1)*var(9); // [ var(6) , var(4) ] D[4,8] = (-1)*var(11); // [ var(8) , var(4) ] D[5,7] = var(11); // [ var(7) , var(5) ] D[5,10] = var(13); // [ var(10) , var(5) ] D[5,12] = var(15); // [ var(12) , var(5) ] D[5,13] = (2)*var(16); // [ var(13) , var(5) ] D[6,7] = var(12); // [ var(7) , var(6) ] D[6,9] = (2)*var(14); // [ var(9) , var(6) ] D[6,11] = var(15); // [ var(11) , var(6) ] D[7,8] = (-1)*var(13); // [ var(8) , var(7) ] D[8,9] = var(15); // [ var(9) , var(8) ] D[8,11] = (2)*var(16); // [ var(11) , var(8) ] // Y(i) * Y(j): D[17,18] = (-1)*var(21); // [ var(18) , var(17) ] D[17,22] = (-1)*var(24); // [ var(22) , var(17) ] D[17,25] = (-1)*var(27); // [ var(25) , var(17) ] D[17,28] = (-1)*var(29); // [ var(28) , var(17) ] D[17,30] = (-1)*var(31); // [ var(30) , var(17) ] D[17,31] = (-2)*var(32); // [ var(31) , var(17) ] D[18,19] = (-1)*var(22); // [ var(19) , var(18) ] D[18,23] = (-1)*var(25); // [ var(23) , var(18) ] D[18,26] = (-1)*var(28); // [ var(26) , var(18) ] D[18,28] = (-2)*var(30); // [ var(28) , var(18) ] D[18,29] = (-1)*var(31); // [ var(29) , var(18) ] D[19,20] = (-1)*var(23); // [ var(20) , var(19) ] D[19,21] = var(24); // [ var(21) , var(19) ] D[19,23] = (-2)*var(26); // [ var(23) , var(19) ] D[19,25] = (-1)*var(28); // [ var(25) , var(19) ] D[19,27] = (-1)*var(29); // [ var(27) , var(19) ] D[20,22] = var(25); // [ var(22) , var(20) ] D[20,24] = var(27); // [ var(24) , var(20) ] D[21,23] = (-1)*var(27); // [ var(23) , var(21) ] D[21,26] = (-1)*var(29); // [ var(26) , var(21) ] D[21,28] = (-1)*var(31); // [ var(28) , var(21) ] D[21,29] = (-2)*var(32); // [ var(29) , var(21) ] D[22,23] = (-1)*var(28); // [ var(23) , var(22) ] D[22,25] = (-2)*var(30); // [ var(25) , var(22) ] D[22,27] = (-1)*var(31); // [ var(27) , var(22) ] D[23,24] = var(29); // [ var(24) , var(23) ] D[24,25] = (-1)*var(31); // [ var(25) , var(24) ] D[24,27] = (-2)*var(32); // [ var(27) , var(24) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUsp4(); ncAlgebra; setring ncAlgebra; // ... 264 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: sp5(Q) has the type: C5, and defined by: proc makeUsp5(list #) "USAGE: makeUsp5([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(sp_5) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(sp_5) is derived from the Chevalley representation of sp_5, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUsp5; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..25),Y(1..25),H(1..5)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,51] = (2)*var(1); // [ var(51) , var(1) ] D[2,51] = (-1)*var(2); // [ var(51) , var(2) ] D[6,51] = var(6); // [ var(51) , var(6) ] D[7,51] = (-1)*var(7); // [ var(51) , var(7) ] D[10,51] = var(10); // [ var(51) , var(10) ] D[11,51] = (-1)*var(11); // [ var(51) , var(11) ] D[14,51] = var(14); // [ var(51) , var(14) ] D[15,51] = (-1)*var(15); // [ var(51) , var(15) ] D[17,51] = var(17); // [ var(51) , var(17) ] D[18,51] = (-1)*var(18); // [ var(51) , var(18) ] D[20,51] = var(20); // [ var(51) , var(20) ] D[21,51] = (-1)*var(21); // [ var(51) , var(21) ] D[22,51] = var(22); // [ var(51) , var(22) ] D[23,51] = (-2)*var(23); // [ var(51) , var(23) ] D[25,51] = (2)*var(25); // [ var(51) , var(25) ] D[1,52] = (-1)*var(1); // [ var(52) , var(1) ] D[2,52] = (2)*var(2); // [ var(52) , var(2) ] D[3,52] = (-1)*var(3); // [ var(52) , var(3) ] D[6,52] = var(6); // [ var(52) , var(6) ] D[7,52] = var(7); // [ var(52) , var(7) ] D[8,52] = (-1)*var(8); // [ var(52) , var(8) ] D[11,52] = var(11); // [ var(52) , var(11) ] D[12,52] = (-1)*var(12); // [ var(52) , var(12) ] D[15,52] = var(15); // [ var(52) , var(15) ] D[16,52] = (-1)*var(16); // [ var(52) , var(16) ] D[18,52] = var(18); // [ var(52) , var(18) ] D[19,52] = (-2)*var(19); // [ var(52) , var(19) ] D[22,52] = (-1)*var(22); // [ var(52) , var(22) ] D[23,52] = (2)*var(23); // [ var(52) , var(23) ] D[24,52] = var(24); // [ var(52) , var(24) ] D[2,53] = (-1)*var(2); // [ var(53) , var(2) ] D[3,53] = (2)*var(3); // [ var(53) , var(3) ] D[4,53] = (-1)*var(4); // [ var(53) , var(4) ] D[6,53] = (-1)*var(6); // [ var(53) , var(6) ] D[7,53] = var(7); // [ var(53) , var(7) ] D[8,53] = var(8); // [ var(53) , var(8) ] D[9,53] = (-1)*var(9); // [ var(53) , var(9) ] D[10,53] = var(10); // [ var(53) , var(10) ] D[12,53] = var(12); // [ var(53) , var(12) ] D[13,53] = (-2)*var(13); // [ var(53) , var(13) ] D[18,53] = (-1)*var(18); // [ var(53) , var(18) ] D[19,53] = (2)*var(19); // [ var(53) , var(19) ] D[20,53] = (-1)*var(20); // [ var(53) , var(20) ] D[21,53] = var(21); // [ var(53) , var(21) ] D[22,53] = var(22); // [ var(53) , var(22) ] D[3,54] = (-1)*var(3); // [ var(54) , var(3) ] D[4,54] = (2)*var(4); // [ var(54) , var(4) ] D[5,54] = (-2)*var(5); // [ var(54) , var(5) ] D[7,54] = (-1)*var(7); // [ var(54) , var(7) ] D[8,54] = var(8); // [ var(54) , var(8) ] D[10,54] = (-1)*var(10); // [ var(54) , var(10) ] D[11,54] = var(11); // [ var(54) , var(11) ] D[12,54] = (-1)*var(12); // [ var(54) , var(12) ] D[13,54] = (2)*var(13); // [ var(54) , var(13) ] D[14,54] = var(14); // [ var(54) , var(14) ] D[15,54] = (-1)*var(15); // [ var(54) , var(15) ] D[16,54] = var(16); // [ var(54) , var(16) ] D[17,54] = (-1)*var(17); // [ var(54) , var(17) ] D[18,54] = var(18); // [ var(54) , var(18) ] D[20,54] = var(20); // [ var(54) , var(20) ] D[4,55] = (-1)*var(4); // [ var(55) , var(4) ] D[5,55] = (2)*var(5); // [ var(55) , var(5) ] D[8,55] = (-1)*var(8); // [ var(55) , var(8) ] D[9,55] = var(9); // [ var(55) , var(9) ] D[11,55] = (-1)*var(11); // [ var(55) , var(11) ] D[12,55] = var(12); // [ var(55) , var(12) ] D[14,55] = (-1)*var(14); // [ var(55) , var(14) ] D[15,55] = var(15); // [ var(55) , var(15) ] D[17,55] = var(17); // [ var(55) , var(17) ] // H(i) * Y(j): D[26,51] = (-2)*var(26); // [ var(51) , var(26) ] D[27,51] = var(27); // [ var(51) , var(27) ] D[31,51] = (-1)*var(31); // [ var(51) , var(31) ] D[32,51] = var(32); // [ var(51) , var(32) ] D[35,51] = (-1)*var(35); // [ var(51) , var(35) ] D[36,51] = var(36); // [ var(51) , var(36) ] D[39,51] = (-1)*var(39); // [ var(51) , var(39) ] D[40,51] = var(40); // [ var(51) , var(40) ] D[42,51] = (-1)*var(42); // [ var(51) , var(42) ] D[43,51] = var(43); // [ var(51) , var(43) ] D[45,51] = (-1)*var(45); // [ var(51) , var(45) ] D[46,51] = var(46); // [ var(51) , var(46) ] D[47,51] = (-1)*var(47); // [ var(51) , var(47) ] D[48,51] = (2)*var(48); // [ var(51) , var(48) ] D[50,51] = (-2)*var(50); // [ var(51) , var(50) ] D[26,52] = var(26); // [ var(52) , var(26) ] D[27,52] = (-2)*var(27); // [ var(52) , var(27) ] D[28,52] = var(28); // [ var(52) , var(28) ] D[31,52] = (-1)*var(31); // [ var(52) , var(31) ] D[32,52] = (-1)*var(32); // [ var(52) , var(32) ] D[33,52] = var(33); // [ var(52) , var(33) ] D[36,52] = (-1)*var(36); // [ var(52) , var(36) ] D[37,52] = var(37); // [ var(52) , var(37) ] D[40,52] = (-1)*var(40); // [ var(52) , var(40) ] D[41,52] = var(41); // [ var(52) , var(41) ] D[43,52] = (-1)*var(43); // [ var(52) , var(43) ] D[44,52] = (2)*var(44); // [ var(52) , var(44) ] D[47,52] = var(47); // [ var(52) , var(47) ] D[48,52] = (-2)*var(48); // [ var(52) , var(48) ] D[49,52] = (-1)*var(49); // [ var(52) , var(49) ] D[27,53] = var(27); // [ var(53) , var(27) ] D[28,53] = (-2)*var(28); // [ var(53) , var(28) ] D[29,53] = var(29); // [ var(53) , var(29) ] D[31,53] = var(31); // [ var(53) , var(31) ] D[32,53] = (-1)*var(32); // [ var(53) , var(32) ] D[33,53] = (-1)*var(33); // [ var(53) , var(33) ] D[34,53] = var(34); // [ var(53) , var(34) ] D[35,53] = (-1)*var(35); // [ var(53) , var(35) ] D[37,53] = (-1)*var(37); // [ var(53) , var(37) ] D[38,53] = (2)*var(38); // [ var(53) , var(38) ] D[43,53] = var(43); // [ var(53) , var(43) ] D[44,53] = (-2)*var(44); // [ var(53) , var(44) ] D[45,53] = var(45); // [ var(53) , var(45) ] D[46,53] = (-1)*var(46); // [ var(53) , var(46) ] D[47,53] = (-1)*var(47); // [ var(53) , var(47) ] D[28,54] = var(28); // [ var(54) , var(28) ] D[29,54] = (-2)*var(29); // [ var(54) , var(29) ] D[30,54] = (2)*var(30); // [ var(54) , var(30) ] D[32,54] = var(32); // [ var(54) , var(32) ] D[33,54] = (-1)*var(33); // [ var(54) , var(33) ] D[35,54] = var(35); // [ var(54) , var(35) ] D[36,54] = (-1)*var(36); // [ var(54) , var(36) ] D[37,54] = var(37); // [ var(54) , var(37) ] D[38,54] = (-2)*var(38); // [ var(54) , var(38) ] D[39,54] = (-1)*var(39); // [ var(54) , var(39) ] D[40,54] = var(40); // [ var(54) , var(40) ] D[41,54] = (-1)*var(41); // [ var(54) , var(41) ] D[42,54] = var(42); // [ var(54) , var(42) ] D[43,54] = (-1)*var(43); // [ var(54) , var(43) ] D[45,54] = (-1)*var(45); // [ var(54) , var(45) ] D[29,55] = var(29); // [ var(55) , var(29) ] D[30,55] = (-2)*var(30); // [ var(55) , var(30) ] D[33,55] = var(33); // [ var(55) , var(33) ] D[34,55] = (-1)*var(34); // [ var(55) , var(34) ] D[36,55] = var(36); // [ var(55) , var(36) ] D[37,55] = (-1)*var(37); // [ var(55) , var(37) ] D[39,55] = var(39); // [ var(55) , var(39) ] D[40,55] = (-1)*var(40); // [ var(55) , var(40) ] D[42,55] = (-1)*var(42); // [ var(55) , var(42) ] // Y(i) * X(j): D[1,26] = (-1)*var(51); // [ var(26) , var(1) ] D[6,26] = (-1)*var(2); // [ var(26) , var(6) ] D[10,26] = (-1)*var(7); // [ var(26) , var(10) ] D[14,26] = (-1)*var(11); // [ var(26) , var(14) ] D[17,26] = (-1)*var(15); // [ var(26) , var(17) ] D[20,26] = (-1)*var(18); // [ var(26) , var(20) ] D[22,26] = (-1)*var(21); // [ var(26) , var(22) ] D[24,26] = (-2)*var(23); // [ var(26) , var(24) ] D[25,26] = (-1)*var(24); // [ var(26) , var(25) ] D[2,27] = (-1)*var(52); // [ var(27) , var(2) ] D[6,27] = var(1); // [ var(27) , var(6) ] D[7,27] = (-1)*var(3); // [ var(27) , var(7) ] D[11,27] = (-1)*var(8); // [ var(27) , var(11) ] D[15,27] = (-1)*var(12); // [ var(27) , var(15) ] D[18,27] = (-1)*var(16); // [ var(27) , var(18) ] D[21,27] = (-2)*var(19); // [ var(27) , var(21) ] D[23,27] = (-1)*var(21); // [ var(27) , var(23) ] D[24,27] = (-1)*var(22); // [ var(27) , var(24) ] D[3,28] = (-1)*var(53); // [ var(28) , var(3) ] D[7,28] = var(2); // [ var(28) , var(7) ] D[8,28] = (-1)*var(4); // [ var(28) , var(8) ] D[10,28] = var(6); // [ var(28) , var(10) ] D[12,28] = (-1)*var(9); // [ var(28) , var(12) ] D[16,28] = (-2)*var(13); // [ var(28) , var(16) ] D[19,28] = (-1)*var(16); // [ var(28) , var(19) ] D[21,28] = (-1)*var(18); // [ var(28) , var(21) ] D[22,28] = (-1)*var(20); // [ var(28) , var(22) ] D[4,29] = (-1)*var(54); // [ var(29) , var(4) ] D[8,29] = var(3); // [ var(29) , var(8) ] D[9,29] = (-2)*var(5); // [ var(29) , var(9) ] D[11,29] = var(7); // [ var(29) , var(11) ] D[13,29] = (-1)*var(9); // [ var(29) , var(13) ] D[14,29] = var(10); // [ var(29) , var(14) ] D[16,29] = (-1)*var(12); // [ var(29) , var(16) ] D[18,29] = (-1)*var(15); // [ var(29) , var(18) ] D[20,29] = (-1)*var(17); // [ var(29) , var(20) ] D[5,30] = (-1)*var(55); // [ var(30) , var(5) ] D[9,30] = var(4); // [ var(30) , var(9) ] D[12,30] = var(8); // [ var(30) , var(12) ] D[15,30] = var(11); // [ var(30) , var(15) ] D[17,30] = var(14); // [ var(30) , var(17) ] D[1,31] = (-1)*var(27); // [ var(31) , var(1) ] D[2,31] = var(26); // [ var(31) , var(2) ] D[6,31] = (-1)*var(51)+(-1)*var(52); // [ var(31) , var(6) ] D[10,31] = (-1)*var(3); // [ var(31) , var(10) ] D[14,31] = (-1)*var(8); // [ var(31) , var(14) ] D[17,31] = (-1)*var(12); // [ var(31) , var(17) ] D[20,31] = (-1)*var(16); // [ var(31) , var(20) ] D[22,31] = (-2)*var(19); // [ var(31) , var(22) ] D[24,31] = (-1)*var(21); // [ var(31) , var(24) ] D[25,31] = (-1)*var(22); // [ var(31) , var(25) ] D[2,32] = (-1)*var(28); // [ var(32) , var(2) ] D[3,32] = var(27); // [ var(32) , var(3) ] D[7,32] = (-1)*var(52)+(-1)*var(53); // [ var(32) , var(7) ] D[10,32] = var(1); // [ var(32) , var(10) ] D[11,32] = (-1)*var(4); // [ var(32) , var(11) ] D[15,32] = (-1)*var(9); // [ var(32) , var(15) ] D[18,32] = (-2)*var(13); // [ var(32) , var(18) ] D[21,32] = (-1)*var(16); // [ var(32) , var(21) ] D[23,32] = (-1)*var(18); // [ var(32) , var(23) ] D[24,32] = (-1)*var(20); // [ var(32) , var(24) ] D[3,33] = (-1)*var(29); // [ var(33) , var(3) ] D[4,33] = var(28); // [ var(33) , var(4) ] D[8,33] = (-1)*var(53)+(-1)*var(54); // [ var(33) , var(8) ] D[11,33] = var(2); // [ var(33) , var(11) ] D[12,33] = (-2)*var(5); // [ var(33) , var(12) ] D[14,33] = var(6); // [ var(33) , var(14) ] D[16,33] = (-1)*var(9); // [ var(33) , var(16) ] D[19,33] = (-1)*var(12); // [ var(33) , var(19) ] D[21,33] = (-1)*var(15); // [ var(33) , var(21) ] D[22,33] = (-1)*var(17); // [ var(33) , var(22) ] D[4,34] = (-2)*var(30); // [ var(34) , var(4) ] D[5,34] = var(29); // [ var(34) , var(5) ] D[9,34] = (-1)*var(54)+(-2)*var(55); // [ var(34) , var(9) ] D[12,34] = var(3); // [ var(34) , var(12) ] D[13,34] = var(4); // [ var(34) , var(13) ] D[15,34] = var(7); // [ var(34) , var(15) ] D[16,34] = var(8); // [ var(34) , var(16) ] D[17,34] = var(10); // [ var(34) , var(17) ] D[18,34] = var(11); // [ var(34) , var(18) ] D[20,34] = var(14); // [ var(34) , var(20) ] D[1,35] = (-1)*var(32); // [ var(35) , var(1) ] D[3,35] = var(31); // [ var(35) , var(3) ] D[6,35] = (-1)*var(28); // [ var(35) , var(6) ] D[7,35] = var(26); // [ var(35) , var(7) ] D[10,35] = (-1)*var(51)+(-1)*var(52)+(-1)*var(53); // [ var(35) , var(10) ] D[14,35] = (-1)*var(4); // [ var(35) , var(14) ] D[17,35] = (-1)*var(9); // [ var(35) , var(17) ] D[20,35] = (-2)*var(13); // [ var(35) , var(20) ] D[22,35] = (-1)*var(16); // [ var(35) , var(22) ] D[24,35] = (-1)*var(18); // [ var(35) , var(24) ] D[25,35] = (-1)*var(20); // [ var(35) , var(25) ] D[2,36] = (-1)*var(33); // [ var(36) , var(2) ] D[4,36] = var(32); // [ var(36) , var(4) ] D[7,36] = (-1)*var(29); // [ var(36) , var(7) ] D[8,36] = var(27); // [ var(36) , var(8) ] D[11,36] = (-1)*var(52)+(-1)*var(53)+(-1)*var(54); // [ var(36) , var(11) ] D[14,36] = var(1); // [ var(36) , var(14) ] D[15,36] = (-2)*var(5); // [ var(36) , var(15) ] D[18,36] = (-1)*var(9); // [ var(36) , var(18) ] D[21,36] = (-1)*var(12); // [ var(36) , var(21) ] D[23,36] = (-1)*var(15); // [ var(36) , var(23) ] D[24,36] = (-1)*var(17); // [ var(36) , var(24) ] D[3,37] = (-1)*var(34); // [ var(37) , var(3) ] D[5,37] = var(33); // [ var(37) , var(5) ] D[8,37] = (-2)*var(30); // [ var(37) , var(8) ] D[9,37] = var(28); // [ var(37) , var(9) ] D[12,37] = (-1)*var(53)+(-1)*var(54)+(-2)*var(55); // [ var(37) , var(12) ] D[15,37] = var(2); // [ var(37) , var(15) ] D[16,37] = var(4); // [ var(37) , var(16) ] D[17,37] = var(6); // [ var(37) , var(17) ] D[19,37] = var(8); // [ var(37) , var(19) ] D[21,37] = var(11); // [ var(37) , var(21) ] D[22,37] = var(14); // [ var(37) , var(22) ] D[4,38] = (-1)*var(34); // [ var(38) , var(4) ] D[9,38] = var(29); // [ var(38) , var(9) ] D[13,38] = (-1)*var(54)+(-1)*var(55); // [ var(38) , var(13) ] D[16,38] = var(3); // [ var(38) , var(16) ] D[18,38] = var(7); // [ var(38) , var(18) ] D[20,38] = var(10); // [ var(38) , var(20) ] D[1,39] = (-1)*var(36); // [ var(39) , var(1) ] D[4,39] = var(35); // [ var(39) , var(4) ] D[6,39] = (-1)*var(33); // [ var(39) , var(6) ] D[8,39] = var(31); // [ var(39) , var(8) ] D[10,39] = (-1)*var(29); // [ var(39) , var(10) ] D[11,39] = var(26); // [ var(39) , var(11) ] D[14,39] = (-1)*var(51)+(-1)*var(52)+(-1)*var(53)+(-1)*var(54); // [ var(39) , var(14) ] D[17,39] = (-2)*var(5); // [ var(39) , var(17) ] D[20,39] = (-1)*var(9); // [ var(39) , var(20) ] D[22,39] = (-1)*var(12); // [ var(39) , var(22) ] D[24,39] = (-1)*var(15); // [ var(39) , var(24) ] D[25,39] = (-1)*var(17); // [ var(39) , var(25) ] D[2,40] = (-1)*var(37); // [ var(40) , var(2) ] D[5,40] = var(36); // [ var(40) , var(5) ] D[7,40] = (-1)*var(34); // [ var(40) , var(7) ] D[9,40] = var(32); // [ var(40) , var(9) ] D[11,40] = (-2)*var(30); // [ var(40) , var(11) ] D[12,40] = var(27); // [ var(40) , var(12) ] D[15,40] = (-1)*var(52)+(-1)*var(53)+(-1)*var(54)+(-2)*var(55); // [ var(40) , var(15) ] D[17,40] = var(1); // [ var(40) , var(17) ] D[18,40] = var(4); // [ var(40) , var(18) ] D[21,40] = var(8); // [ var(40) , var(21) ] D[23,40] = var(11); // [ var(40) , var(23) ] D[24,40] = var(14); // [ var(40) , var(24) ] D[3,41] = (-2)*var(38); // [ var(41) , var(3) ] D[4,41] = (-1)*var(37); // [ var(41) , var(4) ] D[8,41] = (-1)*var(34); // [ var(41) , var(8) ] D[9,41] = var(33); // [ var(41) , var(9) ] D[12,41] = var(29); // [ var(41) , var(12) ] D[13,41] = var(28); // [ var(41) , var(13) ] D[16,41] = (-1)*var(53)+(-2)*var(54)+(-2)*var(55); // [ var(41) , var(16) ] D[18,41] = var(2); // [ var(41) , var(18) ] D[19,41] = var(3); // [ var(41) , var(19) ] D[20,41] = var(6); // [ var(41) , var(20) ] D[21,41] = var(7); // [ var(41) , var(21) ] D[22,41] = var(10); // [ var(41) , var(22) ] D[1,42] = (-1)*var(40); // [ var(42) , var(1) ] D[5,42] = var(39); // [ var(42) , var(5) ] D[6,42] = (-1)*var(37); // [ var(42) , var(6) ] D[9,42] = var(35); // [ var(42) , var(9) ] D[10,42] = (-1)*var(34); // [ var(42) , var(10) ] D[12,42] = var(31); // [ var(42) , var(12) ] D[14,42] = (-2)*var(30); // [ var(42) , var(14) ] D[15,42] = var(26); // [ var(42) , var(15) ] D[17,42] = (-1)*var(51)+(-1)*var(52)+(-1)*var(53)+(-1)*var(54)+(-2)*var(55); // [ var(42) , var(17) ] D[20,42] = var(4); // [ var(42) , var(20) ] D[22,42] = var(8); // [ var(42) , var(22) ] D[24,42] = var(11); // [ var(42) , var(24) ] D[25,42] = var(14); // [ var(42) , var(25) ] D[2,43] = (-1)*var(41); // [ var(43) , var(2) ] D[4,43] = (-1)*var(40); // [ var(43) , var(4) ] D[7,43] = (-2)*var(38); // [ var(43) , var(7) ] D[9,43] = var(36); // [ var(43) , var(9) ] D[11,43] = (-1)*var(34); // [ var(43) , var(11) ] D[13,43] = var(32); // [ var(43) , var(13) ] D[15,43] = var(29); // [ var(43) , var(15) ] D[16,43] = var(27); // [ var(43) , var(16) ] D[18,43] = (-1)*var(52)+(-1)*var(53)+(-2)*var(54)+(-2)*var(55); // [ var(43) , var(18) ] D[20,43] = var(1); // [ var(43) , var(20) ] D[21,43] = var(3); // [ var(43) , var(21) ] D[23,43] = var(7); // [ var(43) , var(23) ] D[24,43] = var(10); // [ var(43) , var(24) ] D[3,44] = (-1)*var(41); // [ var(44) , var(3) ] D[8,44] = (-1)*var(37); // [ var(44) , var(8) ] D[12,44] = var(33); // [ var(44) , var(12) ] D[16,44] = var(28); // [ var(44) , var(16) ] D[19,44] = (-1)*var(53)+(-1)*var(54)+(-1)*var(55); // [ var(44) , var(19) ] D[21,44] = var(2); // [ var(44) , var(21) ] D[22,44] = var(6); // [ var(44) , var(22) ] D[1,45] = (-1)*var(43); // [ var(45) , var(1) ] D[4,45] = (-1)*var(42); // [ var(45) , var(4) ] D[6,45] = (-1)*var(41); // [ var(45) , var(6) ] D[9,45] = var(39); // [ var(45) , var(9) ] D[10,45] = (-2)*var(38); // [ var(45) , var(10) ] D[13,45] = var(35); // [ var(45) , var(13) ] D[14,45] = (-1)*var(34); // [ var(45) , var(14) ] D[16,45] = var(31); // [ var(45) , var(16) ] D[17,45] = var(29); // [ var(45) , var(17) ] D[18,45] = var(26); // [ var(45) , var(18) ] D[20,45] = (-1)*var(51)+(-1)*var(52)+(-1)*var(53)+(-2)*var(54)+(-2)*var(55); // [ var(45) , var(20) ] D[22,45] = var(3); // [ var(45) , var(22) ] D[24,45] = var(7); // [ var(45) , var(24) ] D[25,45] = var(10); // [ var(45) , var(25) ] D[2,46] = (-2)*var(44); // [ var(46) , var(2) ] D[3,46] = (-1)*var(43); // [ var(46) , var(3) ] D[7,46] = (-1)*var(41); // [ var(46) , var(7) ] D[8,46] = (-1)*var(40); // [ var(46) , var(8) ] D[11,46] = (-1)*var(37); // [ var(46) , var(11) ] D[12,46] = var(36); // [ var(46) , var(12) ] D[15,46] = var(33); // [ var(46) , var(15) ] D[16,46] = var(32); // [ var(46) , var(16) ] D[18,46] = var(28); // [ var(46) , var(18) ] D[19,46] = var(27); // [ var(46) , var(19) ] D[21,46] = (-1)*var(52)+(-2)*var(53)+(-2)*var(54)+(-2)*var(55); // [ var(46) , var(21) ] D[22,46] = var(1); // [ var(46) , var(22) ] D[23,46] = var(2); // [ var(46) , var(23) ] D[24,46] = var(6); // [ var(46) , var(24) ] D[1,47] = (-1)*var(46); // [ var(47) , var(1) ] D[3,47] = (-1)*var(45); // [ var(47) , var(3) ] D[6,47] = (-2)*var(44); // [ var(47) , var(6) ] D[8,47] = (-1)*var(42); // [ var(47) , var(8) ] D[10,47] = (-1)*var(41); // [ var(47) , var(10) ] D[12,47] = var(39); // [ var(47) , var(12) ] D[14,47] = (-1)*var(37); // [ var(47) , var(14) ] D[16,47] = var(35); // [ var(47) , var(16) ] D[17,47] = var(33); // [ var(47) , var(17) ] D[19,47] = var(31); // [ var(47) , var(19) ] D[20,47] = var(28); // [ var(47) , var(20) ] D[21,47] = var(26); // [ var(47) , var(21) ] D[22,47] = (-1)*var(51)+(-1)*var(52)+(-2)*var(53)+(-2)*var(54)+(-2)*var(55); // [ var(47) , var(22) ] D[24,47] = var(2); // [ var(47) , var(24) ] D[25,47] = var(6); // [ var(47) , var(25) ] D[2,48] = (-1)*var(46); // [ var(48) , var(2) ] D[7,48] = (-1)*var(43); // [ var(48) , var(7) ] D[11,48] = (-1)*var(40); // [ var(48) , var(11) ] D[15,48] = var(36); // [ var(48) , var(15) ] D[18,48] = var(32); // [ var(48) , var(18) ] D[21,48] = var(27); // [ var(48) , var(21) ] D[23,48] = (-1)*var(52)+(-1)*var(53)+(-1)*var(54)+(-1)*var(55); // [ var(48) , var(23) ] D[24,48] = var(1); // [ var(48) , var(24) ] D[1,49] = (-2)*var(48); // [ var(49) , var(1) ] D[2,49] = (-1)*var(47); // [ var(49) , var(2) ] D[6,49] = (-1)*var(46); // [ var(49) , var(6) ] D[7,49] = (-1)*var(45); // [ var(49) , var(7) ] D[10,49] = (-1)*var(43); // [ var(49) , var(10) ] D[11,49] = (-1)*var(42); // [ var(49) , var(11) ] D[14,49] = (-1)*var(40); // [ var(49) , var(14) ] D[15,49] = var(39); // [ var(49) , var(15) ] D[17,49] = var(36); // [ var(49) , var(17) ] D[18,49] = var(35); // [ var(49) , var(18) ] D[20,49] = var(32); // [ var(49) , var(20) ] D[21,49] = var(31); // [ var(49) , var(21) ] D[22,49] = var(27); // [ var(49) , var(22) ] D[23,49] = var(26); // [ var(49) , var(23) ] D[24,49] = (-1)*var(51)+(-2)*var(52)+(-2)*var(53)+(-2)*var(54)+(-2)*var(55); // [ var(49) , var(24) ] D[25,49] = var(1); // [ var(49) , var(25) ] D[1,50] = (-1)*var(49); // [ var(50) , var(1) ] D[6,50] = (-1)*var(47); // [ var(50) , var(6) ] D[10,50] = (-1)*var(45); // [ var(50) , var(10) ] D[14,50] = (-1)*var(42); // [ var(50) , var(14) ] D[17,50] = var(39); // [ var(50) , var(17) ] D[20,50] = var(35); // [ var(50) , var(20) ] D[22,50] = var(31); // [ var(50) , var(22) ] D[24,50] = var(26); // [ var(50) , var(24) ] D[25,50] = (-1)*var(51)+(-1)*var(52)+(-1)*var(53)+(-1)*var(54)+(-1)*var(55); // [ var(50) , var(25) ] // X(i) * X(j): D[1,2] = var(6); // [ var(2) , var(1) ] D[1,7] = var(10); // [ var(7) , var(1) ] D[1,11] = var(14); // [ var(11) , var(1) ] D[1,15] = var(17); // [ var(15) , var(1) ] D[1,18] = var(20); // [ var(18) , var(1) ] D[1,21] = var(22); // [ var(21) , var(1) ] D[1,23] = var(24); // [ var(23) , var(1) ] D[1,24] = (2)*var(25); // [ var(24) , var(1) ] D[2,3] = var(7); // [ var(3) , var(2) ] D[2,8] = var(11); // [ var(8) , var(2) ] D[2,12] = var(15); // [ var(12) , var(2) ] D[2,16] = var(18); // [ var(16) , var(2) ] D[2,19] = var(21); // [ var(19) , var(2) ] D[2,21] = (2)*var(23); // [ var(21) , var(2) ] D[2,22] = var(24); // [ var(22) , var(2) ] D[3,4] = var(8); // [ var(4) , var(3) ] D[3,6] = (-1)*var(10); // [ var(6) , var(3) ] D[3,9] = var(12); // [ var(9) , var(3) ] D[3,13] = var(16); // [ var(13) , var(3) ] D[3,16] = (2)*var(19); // [ var(16) , var(3) ] D[3,18] = var(21); // [ var(18) , var(3) ] D[3,20] = var(22); // [ var(20) , var(3) ] D[4,5] = var(9); // [ var(5) , var(4) ] D[4,7] = (-1)*var(11); // [ var(7) , var(4) ] D[4,9] = (2)*var(13); // [ var(9) , var(4) ] D[4,10] = (-1)*var(14); // [ var(10) , var(4) ] D[4,12] = var(16); // [ var(12) , var(4) ] D[4,15] = var(18); // [ var(15) , var(4) ] D[4,17] = var(20); // [ var(17) , var(4) ] D[5,8] = (-1)*var(12); // [ var(8) , var(5) ] D[5,11] = (-1)*var(15); // [ var(11) , var(5) ] D[5,14] = (-1)*var(17); // [ var(14) , var(5) ] D[6,8] = var(14); // [ var(8) , var(6) ] D[6,12] = var(17); // [ var(12) , var(6) ] D[6,16] = var(20); // [ var(16) , var(6) ] D[6,19] = var(22); // [ var(19) , var(6) ] D[6,21] = var(24); // [ var(21) , var(6) ] D[6,22] = (2)*var(25); // [ var(22) , var(6) ] D[7,9] = var(15); // [ var(9) , var(7) ] D[7,13] = var(18); // [ var(13) , var(7) ] D[7,16] = var(21); // [ var(16) , var(7) ] D[7,18] = (2)*var(23); // [ var(18) , var(7) ] D[7,20] = var(24); // [ var(20) , var(7) ] D[8,9] = var(16); // [ var(9) , var(8) ] D[8,12] = (2)*var(19); // [ var(12) , var(8) ] D[8,15] = var(21); // [ var(15) , var(8) ] D[8,17] = var(22); // [ var(17) , var(8) ] D[9,10] = (-1)*var(17); // [ var(10) , var(9) ] D[9,11] = (-1)*var(18); // [ var(11) , var(9) ] D[9,14] = (-1)*var(20); // [ var(14) , var(9) ] D[10,13] = var(20); // [ var(13) , var(10) ] D[10,16] = var(22); // [ var(16) , var(10) ] D[10,18] = var(24); // [ var(18) , var(10) ] D[10,20] = (2)*var(25); // [ var(20) , var(10) ] D[11,12] = var(21); // [ var(12) , var(11) ] D[11,15] = (2)*var(23); // [ var(15) , var(11) ] D[11,17] = var(24); // [ var(17) , var(11) ] D[12,14] = (-1)*var(22); // [ var(14) , var(12) ] D[14,15] = var(24); // [ var(15) , var(14) ] D[14,17] = (2)*var(25); // [ var(17) , var(14) ] // Y(i) * Y(j): D[26,27] = (-1)*var(31); // [ var(27) , var(26) ] D[26,32] = (-1)*var(35); // [ var(32) , var(26) ] D[26,36] = (-1)*var(39); // [ var(36) , var(26) ] D[26,40] = (-1)*var(42); // [ var(40) , var(26) ] D[26,43] = (-1)*var(45); // [ var(43) , var(26) ] D[26,46] = (-1)*var(47); // [ var(46) , var(26) ] D[26,48] = (-1)*var(49); // [ var(48) , var(26) ] D[26,49] = (-2)*var(50); // [ var(49) , var(26) ] D[27,28] = (-1)*var(32); // [ var(28) , var(27) ] D[27,33] = (-1)*var(36); // [ var(33) , var(27) ] D[27,37] = (-1)*var(40); // [ var(37) , var(27) ] D[27,41] = (-1)*var(43); // [ var(41) , var(27) ] D[27,44] = (-1)*var(46); // [ var(44) , var(27) ] D[27,46] = (-2)*var(48); // [ var(46) , var(27) ] D[27,47] = (-1)*var(49); // [ var(47) , var(27) ] D[28,29] = (-1)*var(33); // [ var(29) , var(28) ] D[28,31] = var(35); // [ var(31) , var(28) ] D[28,34] = (-1)*var(37); // [ var(34) , var(28) ] D[28,38] = (-1)*var(41); // [ var(38) , var(28) ] D[28,41] = (-2)*var(44); // [ var(41) , var(28) ] D[28,43] = (-1)*var(46); // [ var(43) , var(28) ] D[28,45] = (-1)*var(47); // [ var(45) , var(28) ] D[29,30] = (-1)*var(34); // [ var(30) , var(29) ] D[29,32] = var(36); // [ var(32) , var(29) ] D[29,34] = (-2)*var(38); // [ var(34) , var(29) ] D[29,35] = var(39); // [ var(35) , var(29) ] D[29,37] = (-1)*var(41); // [ var(37) , var(29) ] D[29,40] = (-1)*var(43); // [ var(40) , var(29) ] D[29,42] = (-1)*var(45); // [ var(42) , var(29) ] D[30,33] = var(37); // [ var(33) , var(30) ] D[30,36] = var(40); // [ var(36) , var(30) ] D[30,39] = var(42); // [ var(39) , var(30) ] D[31,33] = (-1)*var(39); // [ var(33) , var(31) ] D[31,37] = (-1)*var(42); // [ var(37) , var(31) ] D[31,41] = (-1)*var(45); // [ var(41) , var(31) ] D[31,44] = (-1)*var(47); // [ var(44) , var(31) ] D[31,46] = (-1)*var(49); // [ var(46) , var(31) ] D[31,47] = (-2)*var(50); // [ var(47) , var(31) ] D[32,34] = (-1)*var(40); // [ var(34) , var(32) ] D[32,38] = (-1)*var(43); // [ var(38) , var(32) ] D[32,41] = (-1)*var(46); // [ var(41) , var(32) ] D[32,43] = (-2)*var(48); // [ var(43) , var(32) ] D[32,45] = (-1)*var(49); // [ var(45) , var(32) ] D[33,34] = (-1)*var(41); // [ var(34) , var(33) ] D[33,37] = (-2)*var(44); // [ var(37) , var(33) ] D[33,40] = (-1)*var(46); // [ var(40) , var(33) ] D[33,42] = (-1)*var(47); // [ var(42) , var(33) ] D[34,35] = var(42); // [ var(35) , var(34) ] D[34,36] = var(43); // [ var(36) , var(34) ] D[34,39] = var(45); // [ var(39) , var(34) ] D[35,38] = (-1)*var(45); // [ var(38) , var(35) ] D[35,41] = (-1)*var(47); // [ var(41) , var(35) ] D[35,43] = (-1)*var(49); // [ var(43) , var(35) ] D[35,45] = (-2)*var(50); // [ var(45) , var(35) ] D[36,37] = (-1)*var(46); // [ var(37) , var(36) ] D[36,40] = (-2)*var(48); // [ var(40) , var(36) ] D[36,42] = (-1)*var(49); // [ var(42) , var(36) ] D[37,39] = var(47); // [ var(39) , var(37) ] D[39,40] = (-1)*var(49); // [ var(40) , var(39) ] D[39,42] = (-2)*var(50); // [ var(42) , var(39) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUsp5(); ncAlgebra; setring ncAlgebra; // ... 523 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: so6(Q) has the type: D3, and defined by: proc makeUso6(list #) "USAGE: makeUso6([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(so_6) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(so_6) is derived from the Chevalley representation of so_6, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUso6; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..6),Y(1..6),H(1..3)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,13] = (2)*var(1); // [ var(13) , var(1) ] D[2,13] = (-1)*var(2); // [ var(13) , var(2) ] D[3,13] = (-1)*var(3); // [ var(13) , var(3) ] D[4,13] = var(4); // [ var(13) , var(4) ] D[5,13] = var(5); // [ var(13) , var(5) ] D[1,14] = (-1)*var(1); // [ var(14) , var(1) ] D[2,14] = (2)*var(2); // [ var(14) , var(2) ] D[4,14] = var(4); // [ var(14) , var(4) ] D[5,14] = (-1)*var(5); // [ var(14) , var(5) ] D[6,14] = var(6); // [ var(14) , var(6) ] D[1,15] = (-1)*var(1); // [ var(15) , var(1) ] D[3,15] = (2)*var(3); // [ var(15) , var(3) ] D[4,15] = (-1)*var(4); // [ var(15) , var(4) ] D[5,15] = var(5); // [ var(15) , var(5) ] D[6,15] = var(6); // [ var(15) , var(6) ] // H(i) * Y(j): D[7,13] = (-2)*var(7); // [ var(13) , var(7) ] D[8,13] = var(8); // [ var(13) , var(8) ] D[9,13] = var(9); // [ var(13) , var(9) ] D[10,13] = (-1)*var(10); // [ var(13) , var(10) ] D[11,13] = (-1)*var(11); // [ var(13) , var(11) ] D[7,14] = var(7); // [ var(14) , var(7) ] D[8,14] = (-2)*var(8); // [ var(14) , var(8) ] D[10,14] = (-1)*var(10); // [ var(14) , var(10) ] D[11,14] = var(11); // [ var(14) , var(11) ] D[12,14] = (-1)*var(12); // [ var(14) , var(12) ] D[7,15] = var(7); // [ var(15) , var(7) ] D[9,15] = (-2)*var(9); // [ var(15) , var(9) ] D[10,15] = var(10); // [ var(15) , var(10) ] D[11,15] = (-1)*var(11); // [ var(15) , var(11) ] D[12,15] = (-1)*var(12); // [ var(15) , var(12) ] // Y(i) * X(j): D[1,7] = (-1)*var(13); // [ var(7) , var(1) ] D[4,7] = (-1)*var(2); // [ var(7) , var(4) ] D[5,7] = (-1)*var(3); // [ var(7) , var(5) ] D[2,8] = (-1)*var(14); // [ var(8) , var(2) ] D[4,8] = var(1); // [ var(8) , var(4) ] D[6,8] = var(5); // [ var(8) , var(6) ] D[3,9] = (-1)*var(15); // [ var(9) , var(3) ] D[5,9] = var(1); // [ var(9) , var(5) ] D[6,9] = var(4); // [ var(9) , var(6) ] D[1,10] = (-1)*var(8); // [ var(10) , var(1) ] D[2,10] = var(7); // [ var(10) , var(2) ] D[4,10] = (-1)*var(13)+(-1)*var(14); // [ var(10) , var(4) ] D[6,10] = (-1)*var(3); // [ var(10) , var(6) ] D[1,11] = (-1)*var(9); // [ var(11) , var(1) ] D[3,11] = var(7); // [ var(11) , var(3) ] D[5,11] = (-1)*var(13)+(-1)*var(15); // [ var(11) , var(5) ] D[6,11] = (-1)*var(2); // [ var(11) , var(6) ] D[2,12] = var(11); // [ var(12) , var(2) ] D[3,12] = var(10); // [ var(12) , var(3) ] D[4,12] = (-1)*var(9); // [ var(12) , var(4) ] D[5,12] = (-1)*var(8); // [ var(12) , var(5) ] D[6,12] = (-1)*var(13)+(-1)*var(14)+(-1)*var(15); // [ var(12) , var(6) ] // X(i) * X(j): D[1,2] = var(4); // [ var(2) , var(1) ] D[1,3] = var(5); // [ var(3) , var(1) ] D[2,5] = (-1)*var(6); // [ var(5) , var(2) ] D[3,4] = (-1)*var(6); // [ var(4) , var(3) ] // Y(i) * Y(j): D[7,8] = (-1)*var(10); // [ var(8) , var(7) ] D[7,9] = (-1)*var(11); // [ var(9) , var(7) ] D[8,11] = var(12); // [ var(11) , var(8) ] D[9,10] = var(12); // [ var(10) , var(9) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUso6(); ncAlgebra; setring ncAlgebra; // ... 60 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: so8(Q) has the type: D4, and defined by: proc makeUso8(list #) "USAGE: makeUso8([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(so_8) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(so_8) is derived from the Chevalley representation of so_8, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUso8; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..12),Y(1..12),H(1..4)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,25] = (2)*var(1); // [ var(25) , var(1) ] D[2,25] = (-1)*var(2); // [ var(25) , var(2) ] D[5,25] = var(5); // [ var(25) , var(5) ] D[6,25] = (-1)*var(6); // [ var(25) , var(6) ] D[7,25] = (-1)*var(7); // [ var(25) , var(7) ] D[8,25] = var(8); // [ var(25) , var(8) ] D[9,25] = var(9); // [ var(25) , var(9) ] D[10,25] = (-1)*var(10); // [ var(25) , var(10) ] D[11,25] = var(11); // [ var(25) , var(11) ] D[1,26] = (-1)*var(1); // [ var(26) , var(1) ] D[2,26] = (2)*var(2); // [ var(26) , var(2) ] D[3,26] = (-1)*var(3); // [ var(26) , var(3) ] D[4,26] = (-1)*var(4); // [ var(26) , var(4) ] D[5,26] = var(5); // [ var(26) , var(5) ] D[6,26] = var(6); // [ var(26) , var(6) ] D[7,26] = var(7); // [ var(26) , var(7) ] D[11,26] = (-1)*var(11); // [ var(26) , var(11) ] D[12,26] = var(12); // [ var(26) , var(12) ] D[2,27] = (-1)*var(2); // [ var(27) , var(2) ] D[3,27] = (2)*var(3); // [ var(27) , var(3) ] D[5,27] = (-1)*var(5); // [ var(27) , var(5) ] D[6,27] = var(6); // [ var(27) , var(6) ] D[7,27] = (-1)*var(7); // [ var(27) , var(7) ] D[8,27] = var(8); // [ var(27) , var(8) ] D[9,27] = (-1)*var(9); // [ var(27) , var(9) ] D[10,27] = var(10); // [ var(27) , var(10) ] D[11,27] = var(11); // [ var(27) , var(11) ] D[2,28] = (-1)*var(2); // [ var(28) , var(2) ] D[4,28] = (2)*var(4); // [ var(28) , var(4) ] D[5,28] = (-1)*var(5); // [ var(28) , var(5) ] D[6,28] = (-1)*var(6); // [ var(28) , var(6) ] D[7,28] = var(7); // [ var(28) , var(7) ] D[8,28] = (-1)*var(8); // [ var(28) , var(8) ] D[9,28] = var(9); // [ var(28) , var(9) ] D[10,28] = var(10); // [ var(28) , var(10) ] D[11,28] = var(11); // [ var(28) , var(11) ] // H(i) * Y(j): D[13,25] = (-2)*var(13); // [ var(25) , var(13) ] D[14,25] = var(14); // [ var(25) , var(14) ] D[17,25] = (-1)*var(17); // [ var(25) , var(17) ] D[18,25] = var(18); // [ var(25) , var(18) ] D[19,25] = var(19); // [ var(25) , var(19) ] D[20,25] = (-1)*var(20); // [ var(25) , var(20) ] D[21,25] = (-1)*var(21); // [ var(25) , var(21) ] D[22,25] = var(22); // [ var(25) , var(22) ] D[23,25] = (-1)*var(23); // [ var(25) , var(23) ] D[13,26] = var(13); // [ var(26) , var(13) ] D[14,26] = (-2)*var(14); // [ var(26) , var(14) ] D[15,26] = var(15); // [ var(26) , var(15) ] D[16,26] = var(16); // [ var(26) , var(16) ] D[17,26] = (-1)*var(17); // [ var(26) , var(17) ] D[18,26] = (-1)*var(18); // [ var(26) , var(18) ] D[19,26] = (-1)*var(19); // [ var(26) , var(19) ] D[23,26] = var(23); // [ var(26) , var(23) ] D[24,26] = (-1)*var(24); // [ var(26) , var(24) ] D[14,27] = var(14); // [ var(27) , var(14) ] D[15,27] = (-2)*var(15); // [ var(27) , var(15) ] D[17,27] = var(17); // [ var(27) , var(17) ] D[18,27] = (-1)*var(18); // [ var(27) , var(18) ] D[19,27] = var(19); // [ var(27) , var(19) ] D[20,27] = (-1)*var(20); // [ var(27) , var(20) ] D[21,27] = var(21); // [ var(27) , var(21) ] D[22,27] = (-1)*var(22); // [ var(27) , var(22) ] D[23,27] = (-1)*var(23); // [ var(27) , var(23) ] D[14,28] = var(14); // [ var(28) , var(14) ] D[16,28] = (-2)*var(16); // [ var(28) , var(16) ] D[17,28] = var(17); // [ var(28) , var(17) ] D[18,28] = var(18); // [ var(28) , var(18) ] D[19,28] = (-1)*var(19); // [ var(28) , var(19) ] D[20,28] = var(20); // [ var(28) , var(20) ] D[21,28] = (-1)*var(21); // [ var(28) , var(21) ] D[22,28] = (-1)*var(22); // [ var(28) , var(22) ] D[23,28] = (-1)*var(23); // [ var(28) , var(23) ] // Y(i) * X(j): D[1,13] = (-1)*var(25); // [ var(13) , var(1) ] D[5,13] = (-1)*var(2); // [ var(13) , var(5) ] D[8,13] = (-1)*var(6); // [ var(13) , var(8) ] D[9,13] = (-1)*var(7); // [ var(13) , var(9) ] D[11,13] = (-1)*var(10); // [ var(13) , var(11) ] D[2,14] = (-1)*var(26); // [ var(14) , var(2) ] D[5,14] = var(1); // [ var(14) , var(5) ] D[6,14] = (-1)*var(3); // [ var(14) , var(6) ] D[7,14] = (-1)*var(4); // [ var(14) , var(7) ] D[12,14] = (-1)*var(11); // [ var(14) , var(12) ] D[3,15] = (-1)*var(27); // [ var(15) , var(3) ] D[6,15] = var(2); // [ var(15) , var(6) ] D[8,15] = var(5); // [ var(15) , var(8) ] D[10,15] = var(7); // [ var(15) , var(10) ] D[11,15] = var(9); // [ var(15) , var(11) ] D[4,16] = (-1)*var(28); // [ var(16) , var(4) ] D[7,16] = var(2); // [ var(16) , var(7) ] D[9,16] = var(5); // [ var(16) , var(9) ] D[10,16] = var(6); // [ var(16) , var(10) ] D[11,16] = var(8); // [ var(16) , var(11) ] D[1,17] = (-1)*var(14); // [ var(17) , var(1) ] D[2,17] = var(13); // [ var(17) , var(2) ] D[5,17] = (-1)*var(25)+(-1)*var(26); // [ var(17) , var(5) ] D[8,17] = (-1)*var(3); // [ var(17) , var(8) ] D[9,17] = (-1)*var(4); // [ var(17) , var(9) ] D[12,17] = var(10); // [ var(17) , var(12) ] D[2,18] = (-1)*var(15); // [ var(18) , var(2) ] D[3,18] = var(14); // [ var(18) , var(3) ] D[6,18] = (-1)*var(26)+(-1)*var(27); // [ var(18) , var(6) ] D[8,18] = var(1); // [ var(18) , var(8) ] D[10,18] = (-1)*var(4); // [ var(18) , var(10) ] D[12,18] = var(9); // [ var(18) , var(12) ] D[2,19] = (-1)*var(16); // [ var(19) , var(2) ] D[4,19] = var(14); // [ var(19) , var(4) ] D[7,19] = (-1)*var(26)+(-1)*var(28); // [ var(19) , var(7) ] D[9,19] = var(1); // [ var(19) , var(9) ] D[10,19] = (-1)*var(3); // [ var(19) , var(10) ] D[12,19] = var(8); // [ var(19) , var(12) ] D[1,20] = (-1)*var(18); // [ var(20) , var(1) ] D[3,20] = var(17); // [ var(20) , var(3) ] D[5,20] = (-1)*var(15); // [ var(20) , var(5) ] D[6,20] = var(13); // [ var(20) , var(6) ] D[8,20] = (-1)*var(25)+(-1)*var(26)+(-1)*var(27); // [ var(20) , var(8) ] D[11,20] = (-1)*var(4); // [ var(20) , var(11) ] D[12,20] = (-1)*var(7); // [ var(20) , var(12) ] D[1,21] = (-1)*var(19); // [ var(21) , var(1) ] D[4,21] = var(17); // [ var(21) , var(4) ] D[5,21] = (-1)*var(16); // [ var(21) , var(5) ] D[7,21] = var(13); // [ var(21) , var(7) ] D[9,21] = (-1)*var(25)+(-1)*var(26)+(-1)*var(28); // [ var(21) , var(9) ] D[11,21] = (-1)*var(3); // [ var(21) , var(11) ] D[12,21] = (-1)*var(6); // [ var(21) , var(12) ] D[3,22] = var(19); // [ var(22) , var(3) ] D[4,22] = var(18); // [ var(22) , var(4) ] D[6,22] = (-1)*var(16); // [ var(22) , var(6) ] D[7,22] = (-1)*var(15); // [ var(22) , var(7) ] D[10,22] = (-1)*var(26)+(-1)*var(27)+(-1)*var(28); // [ var(22) , var(10) ] D[11,22] = var(1); // [ var(22) , var(11) ] D[12,22] = (-1)*var(5); // [ var(22) , var(12) ] D[1,23] = (-1)*var(22); // [ var(23) , var(1) ] D[3,23] = var(21); // [ var(23) , var(3) ] D[4,23] = var(20); // [ var(23) , var(4) ] D[8,23] = (-1)*var(16); // [ var(23) , var(8) ] D[9,23] = (-1)*var(15); // [ var(23) , var(9) ] D[10,23] = var(13); // [ var(23) , var(10) ] D[11,23] = (-1)*var(25)+(-1)*var(26)+(-1)*var(27)+(-1)*var(28); // [ var(23) , var(11) ] D[12,23] = var(2); // [ var(23) , var(12) ] D[2,24] = (-1)*var(23); // [ var(24) , var(2) ] D[5,24] = var(22); // [ var(24) , var(5) ] D[6,24] = var(21); // [ var(24) , var(6) ] D[7,24] = var(20); // [ var(24) , var(7) ] D[8,24] = (-1)*var(19); // [ var(24) , var(8) ] D[9,24] = (-1)*var(18); // [ var(24) , var(9) ] D[10,24] = (-1)*var(17); // [ var(24) , var(10) ] D[11,24] = var(14); // [ var(24) , var(11) ] D[12,24] = (-1)*var(25)+(-2)*var(26)+(-1)*var(27)+(-1)*var(28); // [ var(24) , var(12) ] // X(i) * X(j): D[1,2] = var(5); // [ var(2) , var(1) ] D[1,6] = var(8); // [ var(6) , var(1) ] D[1,7] = var(9); // [ var(7) , var(1) ] D[1,10] = var(11); // [ var(10) , var(1) ] D[2,3] = var(6); // [ var(3) , var(2) ] D[2,4] = var(7); // [ var(4) , var(2) ] D[2,11] = var(12); // [ var(11) , var(2) ] D[3,5] = (-1)*var(8); // [ var(5) , var(3) ] D[3,7] = (-1)*var(10); // [ var(7) , var(3) ] D[3,9] = (-1)*var(11); // [ var(9) , var(3) ] D[4,5] = (-1)*var(9); // [ var(5) , var(4) ] D[4,6] = (-1)*var(10); // [ var(6) , var(4) ] D[4,8] = (-1)*var(11); // [ var(8) , var(4) ] D[5,10] = (-1)*var(12); // [ var(10) , var(5) ] D[6,9] = (-1)*var(12); // [ var(9) , var(6) ] D[7,8] = (-1)*var(12); // [ var(8) , var(7) ] // Y(i) * Y(j): D[13,14] = (-1)*var(17); // [ var(14) , var(13) ] D[13,18] = (-1)*var(20); // [ var(18) , var(13) ] D[13,19] = (-1)*var(21); // [ var(19) , var(13) ] D[13,22] = (-1)*var(23); // [ var(22) , var(13) ] D[14,15] = (-1)*var(18); // [ var(15) , var(14) ] D[14,16] = (-1)*var(19); // [ var(16) , var(14) ] D[14,23] = (-1)*var(24); // [ var(23) , var(14) ] D[15,17] = var(20); // [ var(17) , var(15) ] D[15,19] = var(22); // [ var(19) , var(15) ] D[15,21] = var(23); // [ var(21) , var(15) ] D[16,17] = var(21); // [ var(17) , var(16) ] D[16,18] = var(22); // [ var(18) , var(16) ] D[16,20] = var(23); // [ var(20) , var(16) ] D[17,22] = var(24); // [ var(22) , var(17) ] D[18,21] = var(24); // [ var(21) , var(18) ] D[19,20] = var(24); // [ var(20) , var(19) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUso8(); ncAlgebra; setring ncAlgebra; // ... 180 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: so10(Q) has the type: D5, and defined by: proc makeUso10(list #) "USAGE: makeUso10([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(so_{10}) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(so_{10}) is derived from the Chevalley representation of so_{10}, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUso10; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..20),Y(1..20),H(1..5)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,41] = (2)*var(1); // [ var(41) , var(1) ] D[2,41] = (-1)*var(2); // [ var(41) , var(2) ] D[6,41] = var(6); // [ var(41) , var(6) ] D[7,41] = (-1)*var(7); // [ var(41) , var(7) ] D[10,41] = var(10); // [ var(41) , var(10) ] D[11,41] = (-1)*var(11); // [ var(41) , var(11) ] D[12,41] = (-1)*var(12); // [ var(41) , var(12) ] D[14,41] = var(14); // [ var(41) , var(14) ] D[15,41] = var(15); // [ var(41) , var(15) ] D[16,41] = (-1)*var(16); // [ var(41) , var(16) ] D[17,41] = var(17); // [ var(41) , var(17) ] D[18,41] = (-1)*var(18); // [ var(41) , var(18) ] D[19,41] = var(19); // [ var(41) , var(19) ] D[1,42] = (-1)*var(1); // [ var(42) , var(1) ] D[2,42] = (2)*var(2); // [ var(42) , var(2) ] D[3,42] = (-1)*var(3); // [ var(42) , var(3) ] D[6,42] = var(6); // [ var(42) , var(6) ] D[7,42] = var(7); // [ var(42) , var(7) ] D[8,42] = (-1)*var(8); // [ var(42) , var(8) ] D[9,42] = (-1)*var(9); // [ var(42) , var(9) ] D[11,42] = var(11); // [ var(42) , var(11) ] D[12,42] = var(12); // [ var(42) , var(12) ] D[13,42] = (-1)*var(13); // [ var(42) , var(13) ] D[16,42] = var(16); // [ var(42) , var(16) ] D[19,42] = (-1)*var(19); // [ var(42) , var(19) ] D[20,42] = var(20); // [ var(42) , var(20) ] D[2,43] = (-1)*var(2); // [ var(43) , var(2) ] D[3,43] = (2)*var(3); // [ var(43) , var(3) ] D[4,43] = (-1)*var(4); // [ var(43) , var(4) ] D[5,43] = (-1)*var(5); // [ var(43) , var(5) ] D[6,43] = (-1)*var(6); // [ var(43) , var(6) ] D[7,43] = var(7); // [ var(43) , var(7) ] D[8,43] = var(8); // [ var(43) , var(8) ] D[9,43] = var(9); // [ var(43) , var(9) ] D[10,43] = var(10); // [ var(43) , var(10) ] D[16,43] = (-1)*var(16); // [ var(43) , var(16) ] D[17,43] = (-1)*var(17); // [ var(43) , var(17) ] D[18,43] = var(18); // [ var(43) , var(18) ] D[19,43] = var(19); // [ var(43) , var(19) ] D[3,44] = (-1)*var(3); // [ var(44) , var(3) ] D[4,44] = (2)*var(4); // [ var(44) , var(4) ] D[7,44] = (-1)*var(7); // [ var(44) , var(7) ] D[8,44] = var(8); // [ var(44) , var(8) ] D[9,44] = (-1)*var(9); // [ var(44) , var(9) ] D[10,44] = (-1)*var(10); // [ var(44) , var(10) ] D[11,44] = var(11); // [ var(44) , var(11) ] D[12,44] = (-1)*var(12); // [ var(44) , var(12) ] D[13,44] = var(13); // [ var(44) , var(13) ] D[14,44] = var(14); // [ var(44) , var(14) ] D[15,44] = (-1)*var(15); // [ var(44) , var(15) ] D[16,44] = var(16); // [ var(44) , var(16) ] D[17,44] = var(17); // [ var(44) , var(17) ] D[3,45] = (-1)*var(3); // [ var(45) , var(3) ] D[5,45] = (2)*var(5); // [ var(45) , var(5) ] D[7,45] = (-1)*var(7); // [ var(45) , var(7) ] D[8,45] = (-1)*var(8); // [ var(45) , var(8) ] D[9,45] = var(9); // [ var(45) , var(9) ] D[10,45] = (-1)*var(10); // [ var(45) , var(10) ] D[11,45] = (-1)*var(11); // [ var(45) , var(11) ] D[12,45] = var(12); // [ var(45) , var(12) ] D[13,45] = var(13); // [ var(45) , var(13) ] D[14,45] = (-1)*var(14); // [ var(45) , var(14) ] D[15,45] = var(15); // [ var(45) , var(15) ] D[16,45] = var(16); // [ var(45) , var(16) ] D[17,45] = var(17); // [ var(45) , var(17) ] // H(i) * Y(j): D[21,41] = (-2)*var(21); // [ var(41) , var(21) ] D[22,41] = var(22); // [ var(41) , var(22) ] D[26,41] = (-1)*var(26); // [ var(41) , var(26) ] D[27,41] = var(27); // [ var(41) , var(27) ] D[30,41] = (-1)*var(30); // [ var(41) , var(30) ] D[31,41] = var(31); // [ var(41) , var(31) ] D[32,41] = var(32); // [ var(41) , var(32) ] D[34,41] = (-1)*var(34); // [ var(41) , var(34) ] D[35,41] = (-1)*var(35); // [ var(41) , var(35) ] D[36,41] = var(36); // [ var(41) , var(36) ] D[37,41] = (-1)*var(37); // [ var(41) , var(37) ] D[38,41] = var(38); // [ var(41) , var(38) ] D[39,41] = (-1)*var(39); // [ var(41) , var(39) ] D[21,42] = var(21); // [ var(42) , var(21) ] D[22,42] = (-2)*var(22); // [ var(42) , var(22) ] D[23,42] = var(23); // [ var(42) , var(23) ] D[26,42] = (-1)*var(26); // [ var(42) , var(26) ] D[27,42] = (-1)*var(27); // [ var(42) , var(27) ] D[28,42] = var(28); // [ var(42) , var(28) ] D[29,42] = var(29); // [ var(42) , var(29) ] D[31,42] = (-1)*var(31); // [ var(42) , var(31) ] D[32,42] = (-1)*var(32); // [ var(42) , var(32) ] D[33,42] = var(33); // [ var(42) , var(33) ] D[36,42] = (-1)*var(36); // [ var(42) , var(36) ] D[39,42] = var(39); // [ var(42) , var(39) ] D[40,42] = (-1)*var(40); // [ var(42) , var(40) ] D[22,43] = var(22); // [ var(43) , var(22) ] D[23,43] = (-2)*var(23); // [ var(43) , var(23) ] D[24,43] = var(24); // [ var(43) , var(24) ] D[25,43] = var(25); // [ var(43) , var(25) ] D[26,43] = var(26); // [ var(43) , var(26) ] D[27,43] = (-1)*var(27); // [ var(43) , var(27) ] D[28,43] = (-1)*var(28); // [ var(43) , var(28) ] D[29,43] = (-1)*var(29); // [ var(43) , var(29) ] D[30,43] = (-1)*var(30); // [ var(43) , var(30) ] D[36,43] = var(36); // [ var(43) , var(36) ] D[37,43] = var(37); // [ var(43) , var(37) ] D[38,43] = (-1)*var(38); // [ var(43) , var(38) ] D[39,43] = (-1)*var(39); // [ var(43) , var(39) ] D[23,44] = var(23); // [ var(44) , var(23) ] D[24,44] = (-2)*var(24); // [ var(44) , var(24) ] D[27,44] = var(27); // [ var(44) , var(27) ] D[28,44] = (-1)*var(28); // [ var(44) , var(28) ] D[29,44] = var(29); // [ var(44) , var(29) ] D[30,44] = var(30); // [ var(44) , var(30) ] D[31,44] = (-1)*var(31); // [ var(44) , var(31) ] D[32,44] = var(32); // [ var(44) , var(32) ] D[33,44] = (-1)*var(33); // [ var(44) , var(33) ] D[34,44] = (-1)*var(34); // [ var(44) , var(34) ] D[35,44] = var(35); // [ var(44) , var(35) ] D[36,44] = (-1)*var(36); // [ var(44) , var(36) ] D[37,44] = (-1)*var(37); // [ var(44) , var(37) ] D[23,45] = var(23); // [ var(45) , var(23) ] D[25,45] = (-2)*var(25); // [ var(45) , var(25) ] D[27,45] = var(27); // [ var(45) , var(27) ] D[28,45] = var(28); // [ var(45) , var(28) ] D[29,45] = (-1)*var(29); // [ var(45) , var(29) ] D[30,45] = var(30); // [ var(45) , var(30) ] D[31,45] = var(31); // [ var(45) , var(31) ] D[32,45] = (-1)*var(32); // [ var(45) , var(32) ] D[33,45] = (-1)*var(33); // [ var(45) , var(33) ] D[34,45] = var(34); // [ var(45) , var(34) ] D[35,45] = (-1)*var(35); // [ var(45) , var(35) ] D[36,45] = (-1)*var(36); // [ var(45) , var(36) ] D[37,45] = (-1)*var(37); // [ var(45) , var(37) ] // Y(i) * X(j): D[1,21] = (-1)*var(41); // [ var(21) , var(1) ] D[6,21] = (-1)*var(2); // [ var(21) , var(6) ] D[10,21] = (-1)*var(7); // [ var(21) , var(10) ] D[14,21] = (-1)*var(11); // [ var(21) , var(14) ] D[15,21] = (-1)*var(12); // [ var(21) , var(15) ] D[17,21] = (-1)*var(16); // [ var(21) , var(17) ] D[19,21] = (-1)*var(18); // [ var(21) , var(19) ] D[2,22] = (-1)*var(42); // [ var(22) , var(2) ] D[6,22] = var(1); // [ var(22) , var(6) ] D[7,22] = (-1)*var(3); // [ var(22) , var(7) ] D[11,22] = (-1)*var(8); // [ var(22) , var(11) ] D[12,22] = (-1)*var(9); // [ var(22) , var(12) ] D[16,22] = (-1)*var(13); // [ var(22) , var(16) ] D[20,22] = (-1)*var(19); // [ var(22) , var(20) ] D[3,23] = (-1)*var(43); // [ var(23) , var(3) ] D[7,23] = var(2); // [ var(23) , var(7) ] D[8,23] = (-1)*var(4); // [ var(23) , var(8) ] D[9,23] = (-1)*var(5); // [ var(23) , var(9) ] D[10,23] = var(6); // [ var(23) , var(10) ] D[18,23] = (-1)*var(16); // [ var(23) , var(18) ] D[19,23] = (-1)*var(17); // [ var(23) , var(19) ] D[4,24] = (-1)*var(44); // [ var(24) , var(4) ] D[8,24] = var(3); // [ var(24) , var(8) ] D[11,24] = var(7); // [ var(24) , var(11) ] D[13,24] = var(9); // [ var(24) , var(13) ] D[14,24] = var(10); // [ var(24) , var(14) ] D[16,24] = var(12); // [ var(24) , var(16) ] D[17,24] = var(15); // [ var(24) , var(17) ] D[5,25] = (-1)*var(45); // [ var(25) , var(5) ] D[9,25] = var(3); // [ var(25) , var(9) ] D[12,25] = var(7); // [ var(25) , var(12) ] D[13,25] = var(8); // [ var(25) , var(13) ] D[15,25] = var(10); // [ var(25) , var(15) ] D[16,25] = var(11); // [ var(25) , var(16) ] D[17,25] = var(14); // [ var(25) , var(17) ] D[1,26] = (-1)*var(22); // [ var(26) , var(1) ] D[2,26] = var(21); // [ var(26) , var(2) ] D[6,26] = (-1)*var(41)+(-1)*var(42); // [ var(26) , var(6) ] D[10,26] = (-1)*var(3); // [ var(26) , var(10) ] D[14,26] = (-1)*var(8); // [ var(26) , var(14) ] D[15,26] = (-1)*var(9); // [ var(26) , var(15) ] D[17,26] = (-1)*var(13); // [ var(26) , var(17) ] D[20,26] = var(18); // [ var(26) , var(20) ] D[2,27] = (-1)*var(23); // [ var(27) , var(2) ] D[3,27] = var(22); // [ var(27) , var(3) ] D[7,27] = (-1)*var(42)+(-1)*var(43); // [ var(27) , var(7) ] D[10,27] = var(1); // [ var(27) , var(10) ] D[11,27] = (-1)*var(4); // [ var(27) , var(11) ] D[12,27] = (-1)*var(5); // [ var(27) , var(12) ] D[18,27] = var(13); // [ var(27) , var(18) ] D[20,27] = (-1)*var(17); // [ var(27) , var(20) ] D[3,28] = (-1)*var(24); // [ var(28) , var(3) ] D[4,28] = var(23); // [ var(28) , var(4) ] D[8,28] = (-1)*var(43)+(-1)*var(44); // [ var(28) , var(8) ] D[11,28] = var(2); // [ var(28) , var(11) ] D[13,28] = (-1)*var(5); // [ var(28) , var(13) ] D[14,28] = var(6); // [ var(28) , var(14) ] D[18,28] = var(12); // [ var(28) , var(18) ] D[19,28] = var(15); // [ var(28) , var(19) ] D[3,29] = (-1)*var(25); // [ var(29) , var(3) ] D[5,29] = var(23); // [ var(29) , var(5) ] D[9,29] = (-1)*var(43)+(-1)*var(45); // [ var(29) , var(9) ] D[12,29] = var(2); // [ var(29) , var(12) ] D[13,29] = (-1)*var(4); // [ var(29) , var(13) ] D[15,29] = var(6); // [ var(29) , var(15) ] D[18,29] = var(11); // [ var(29) , var(18) ] D[19,29] = var(14); // [ var(29) , var(19) ] D[1,30] = (-1)*var(27); // [ var(30) , var(1) ] D[3,30] = var(26); // [ var(30) , var(3) ] D[6,30] = (-1)*var(23); // [ var(30) , var(6) ] D[7,30] = var(21); // [ var(30) , var(7) ] D[10,30] = (-1)*var(41)+(-1)*var(42)+(-1)*var(43); // [ var(30) , var(10) ] D[14,30] = (-1)*var(4); // [ var(30) , var(14) ] D[15,30] = (-1)*var(5); // [ var(30) , var(15) ] D[19,30] = var(13); // [ var(30) , var(19) ] D[20,30] = var(16); // [ var(30) , var(20) ] D[2,31] = (-1)*var(28); // [ var(31) , var(2) ] D[4,31] = var(27); // [ var(31) , var(4) ] D[7,31] = (-1)*var(24); // [ var(31) , var(7) ] D[8,31] = var(22); // [ var(31) , var(8) ] D[11,31] = (-1)*var(42)+(-1)*var(43)+(-1)*var(44); // [ var(31) , var(11) ] D[14,31] = var(1); // [ var(31) , var(14) ] D[16,31] = (-1)*var(5); // [ var(31) , var(16) ] D[18,31] = (-1)*var(9); // [ var(31) , var(18) ] D[20,31] = var(15); // [ var(31) , var(20) ] D[2,32] = (-1)*var(29); // [ var(32) , var(2) ] D[5,32] = var(27); // [ var(32) , var(5) ] D[7,32] = (-1)*var(25); // [ var(32) , var(7) ] D[9,32] = var(22); // [ var(32) , var(9) ] D[12,32] = (-1)*var(42)+(-1)*var(43)+(-1)*var(45); // [ var(32) , var(12) ] D[15,32] = var(1); // [ var(32) , var(15) ] D[16,32] = (-1)*var(4); // [ var(32) , var(16) ] D[18,32] = (-1)*var(8); // [ var(32) , var(18) ] D[20,32] = var(14); // [ var(32) , var(20) ] D[4,33] = var(29); // [ var(33) , var(4) ] D[5,33] = var(28); // [ var(33) , var(5) ] D[8,33] = (-1)*var(25); // [ var(33) , var(8) ] D[9,33] = (-1)*var(24); // [ var(33) , var(9) ] D[13,33] = (-1)*var(43)+(-1)*var(44)+(-1)*var(45); // [ var(33) , var(13) ] D[16,33] = var(2); // [ var(33) , var(16) ] D[17,33] = var(6); // [ var(33) , var(17) ] D[18,33] = (-1)*var(7); // [ var(33) , var(18) ] D[19,33] = (-1)*var(10); // [ var(33) , var(19) ] D[1,34] = (-1)*var(31); // [ var(34) , var(1) ] D[4,34] = var(30); // [ var(34) , var(4) ] D[6,34] = (-1)*var(28); // [ var(34) , var(6) ] D[8,34] = var(26); // [ var(34) , var(8) ] D[10,34] = (-1)*var(24); // [ var(34) , var(10) ] D[11,34] = var(21); // [ var(34) , var(11) ] D[14,34] = (-1)*var(41)+(-1)*var(42)+(-1)*var(43)+(-1)*var(44); // [ var(34) , var(14) ] D[17,34] = (-1)*var(5); // [ var(34) , var(17) ] D[19,34] = (-1)*var(9); // [ var(34) , var(19) ] D[20,34] = (-1)*var(12); // [ var(34) , var(20) ] D[1,35] = (-1)*var(32); // [ var(35) , var(1) ] D[5,35] = var(30); // [ var(35) , var(5) ] D[6,35] = (-1)*var(29); // [ var(35) , var(6) ] D[9,35] = var(26); // [ var(35) , var(9) ] D[10,35] = (-1)*var(25); // [ var(35) , var(10) ] D[12,35] = var(21); // [ var(35) , var(12) ] D[15,35] = (-1)*var(41)+(-1)*var(42)+(-1)*var(43)+(-1)*var(45); // [ var(35) , var(15) ] D[17,35] = (-1)*var(4); // [ var(35) , var(17) ] D[19,35] = (-1)*var(8); // [ var(35) , var(19) ] D[20,35] = (-1)*var(11); // [ var(35) , var(20) ] D[2,36] = (-1)*var(33); // [ var(36) , var(2) ] D[4,36] = var(32); // [ var(36) , var(4) ] D[5,36] = var(31); // [ var(36) , var(5) ] D[11,36] = (-1)*var(25); // [ var(36) , var(11) ] D[12,36] = (-1)*var(24); // [ var(36) , var(12) ] D[13,36] = var(22); // [ var(36) , var(13) ] D[16,36] = (-1)*var(42)+(-1)*var(43)+(-1)*var(44)+(-1)*var(45); // [ var(36) , var(16) ] D[17,36] = var(1); // [ var(36) , var(17) ] D[18,36] = var(3); // [ var(36) , var(18) ] D[20,36] = (-1)*var(10); // [ var(36) , var(20) ] D[1,37] = (-1)*var(36); // [ var(37) , var(1) ] D[4,37] = var(35); // [ var(37) , var(4) ] D[5,37] = var(34); // [ var(37) , var(5) ] D[6,37] = (-1)*var(33); // [ var(37) , var(6) ] D[13,37] = var(26); // [ var(37) , var(13) ] D[14,37] = (-1)*var(25); // [ var(37) , var(14) ] D[15,37] = (-1)*var(24); // [ var(37) , var(15) ] D[16,37] = var(21); // [ var(37) , var(16) ] D[17,37] = (-1)*var(41)+(-1)*var(42)+(-1)*var(43)+(-1)*var(44)+(-1)*var(45); // [ var(37) , var(17) ] D[19,37] = var(3); // [ var(37) , var(19) ] D[20,37] = var(7); // [ var(37) , var(20) ] D[3,38] = (-1)*var(36); // [ var(38) , var(3) ] D[7,38] = var(33); // [ var(38) , var(7) ] D[8,38] = var(32); // [ var(38) , var(8) ] D[9,38] = var(31); // [ var(38) , var(9) ] D[11,38] = (-1)*var(29); // [ var(38) , var(11) ] D[12,38] = (-1)*var(28); // [ var(38) , var(12) ] D[13,38] = (-1)*var(27); // [ var(38) , var(13) ] D[16,38] = var(23); // [ var(38) , var(16) ] D[18,38] = (-1)*var(42)+(-2)*var(43)+(-1)*var(44)+(-1)*var(45); // [ var(38) , var(18) ] D[19,38] = var(1); // [ var(38) , var(19) ] D[20,38] = (-1)*var(6); // [ var(38) , var(20) ] D[1,39] = (-1)*var(38); // [ var(39) , var(1) ] D[3,39] = (-1)*var(37); // [ var(39) , var(3) ] D[8,39] = var(35); // [ var(39) , var(8) ] D[9,39] = var(34); // [ var(39) , var(9) ] D[10,39] = var(33); // [ var(39) , var(10) ] D[13,39] = (-1)*var(30); // [ var(39) , var(13) ] D[14,39] = (-1)*var(29); // [ var(39) , var(14) ] D[15,39] = (-1)*var(28); // [ var(39) , var(15) ] D[17,39] = var(23); // [ var(39) , var(17) ] D[18,39] = var(21); // [ var(39) , var(18) ] D[19,39] = (-1)*var(41)+(-1)*var(42)+(-2)*var(43)+(-1)*var(44)+(-1)*var(45); // [ var(39) , var(19) ] D[20,39] = var(2); // [ var(39) , var(20) ] D[2,40] = (-1)*var(39); // [ var(40) , var(2) ] D[6,40] = var(38); // [ var(40) , var(6) ] D[7,40] = (-1)*var(37); // [ var(40) , var(7) ] D[10,40] = var(36); // [ var(40) , var(10) ] D[11,40] = var(35); // [ var(40) , var(11) ] D[12,40] = var(34); // [ var(40) , var(12) ] D[14,40] = (-1)*var(32); // [ var(40) , var(14) ] D[15,40] = (-1)*var(31); // [ var(40) , var(15) ] D[16,40] = (-1)*var(30); // [ var(40) , var(16) ] D[17,40] = var(27); // [ var(40) , var(17) ] D[18,40] = (-1)*var(26); // [ var(40) , var(18) ] D[19,40] = var(22); // [ var(40) , var(19) ] D[20,40] = (-1)*var(41)+(-2)*var(42)+(-2)*var(43)+(-1)*var(44)+(-1)*var(45); // [ var(40) , var(20) ] // X(i) * X(j): D[1,2] = var(6); // [ var(2) , var(1) ] D[1,7] = var(10); // [ var(7) , var(1) ] D[1,11] = var(14); // [ var(11) , var(1) ] D[1,12] = var(15); // [ var(12) , var(1) ] D[1,16] = var(17); // [ var(16) , var(1) ] D[1,18] = var(19); // [ var(18) , var(1) ] D[2,3] = var(7); // [ var(3) , var(2) ] D[2,8] = var(11); // [ var(8) , var(2) ] D[2,9] = var(12); // [ var(9) , var(2) ] D[2,13] = var(16); // [ var(13) , var(2) ] D[2,19] = var(20); // [ var(19) , var(2) ] D[3,4] = var(8); // [ var(4) , var(3) ] D[3,5] = var(9); // [ var(5) , var(3) ] D[3,6] = (-1)*var(10); // [ var(6) , var(3) ] D[3,16] = var(18); // [ var(16) , var(3) ] D[3,17] = var(19); // [ var(17) , var(3) ] D[4,7] = (-1)*var(11); // [ var(7) , var(4) ] D[4,9] = (-1)*var(13); // [ var(9) , var(4) ] D[4,10] = (-1)*var(14); // [ var(10) , var(4) ] D[4,12] = (-1)*var(16); // [ var(12) , var(4) ] D[4,15] = (-1)*var(17); // [ var(15) , var(4) ] D[5,7] = (-1)*var(12); // [ var(7) , var(5) ] D[5,8] = (-1)*var(13); // [ var(8) , var(5) ] D[5,10] = (-1)*var(15); // [ var(10) , var(5) ] D[5,11] = (-1)*var(16); // [ var(11) , var(5) ] D[5,14] = (-1)*var(17); // [ var(14) , var(5) ] D[6,8] = var(14); // [ var(8) , var(6) ] D[6,9] = var(15); // [ var(9) , var(6) ] D[6,13] = var(17); // [ var(13) , var(6) ] D[6,18] = (-1)*var(20); // [ var(18) , var(6) ] D[7,13] = (-1)*var(18); // [ var(13) , var(7) ] D[7,17] = var(20); // [ var(17) , var(7) ] D[8,12] = (-1)*var(18); // [ var(12) , var(8) ] D[8,15] = (-1)*var(19); // [ var(15) , var(8) ] D[9,11] = (-1)*var(18); // [ var(11) , var(9) ] D[9,14] = (-1)*var(19); // [ var(14) , var(9) ] D[10,13] = (-1)*var(19); // [ var(13) , var(10) ] D[10,16] = (-1)*var(20); // [ var(16) , var(10) ] D[11,15] = (-1)*var(20); // [ var(15) , var(11) ] D[12,14] = (-1)*var(20); // [ var(14) , var(12) ] // Y(i) * Y(j): D[21,22] = (-1)*var(26); // [ var(22) , var(21) ] D[21,27] = (-1)*var(30); // [ var(27) , var(21) ] D[21,31] = (-1)*var(34); // [ var(31) , var(21) ] D[21,32] = (-1)*var(35); // [ var(32) , var(21) ] D[21,36] = (-1)*var(37); // [ var(36) , var(21) ] D[21,38] = (-1)*var(39); // [ var(38) , var(21) ] D[22,23] = (-1)*var(27); // [ var(23) , var(22) ] D[22,28] = (-1)*var(31); // [ var(28) , var(22) ] D[22,29] = (-1)*var(32); // [ var(29) , var(22) ] D[22,33] = (-1)*var(36); // [ var(33) , var(22) ] D[22,39] = (-1)*var(40); // [ var(39) , var(22) ] D[23,24] = (-1)*var(28); // [ var(24) , var(23) ] D[23,25] = (-1)*var(29); // [ var(25) , var(23) ] D[23,26] = var(30); // [ var(26) , var(23) ] D[23,36] = (-1)*var(38); // [ var(36) , var(23) ] D[23,37] = (-1)*var(39); // [ var(37) , var(23) ] D[24,27] = var(31); // [ var(27) , var(24) ] D[24,29] = var(33); // [ var(29) , var(24) ] D[24,30] = var(34); // [ var(30) , var(24) ] D[24,32] = var(36); // [ var(32) , var(24) ] D[24,35] = var(37); // [ var(35) , var(24) ] D[25,27] = var(32); // [ var(27) , var(25) ] D[25,28] = var(33); // [ var(28) , var(25) ] D[25,30] = var(35); // [ var(30) , var(25) ] D[25,31] = var(36); // [ var(31) , var(25) ] D[25,34] = var(37); // [ var(34) , var(25) ] D[26,28] = (-1)*var(34); // [ var(28) , var(26) ] D[26,29] = (-1)*var(35); // [ var(29) , var(26) ] D[26,33] = (-1)*var(37); // [ var(33) , var(26) ] D[26,38] = var(40); // [ var(38) , var(26) ] D[27,33] = var(38); // [ var(33) , var(27) ] D[27,37] = (-1)*var(40); // [ var(37) , var(27) ] D[28,32] = var(38); // [ var(32) , var(28) ] D[28,35] = var(39); // [ var(35) , var(28) ] D[29,31] = var(38); // [ var(31) , var(29) ] D[29,34] = var(39); // [ var(34) , var(29) ] D[30,33] = var(39); // [ var(33) , var(30) ] D[30,36] = var(40); // [ var(36) , var(30) ] D[31,35] = var(40); // [ var(35) , var(31) ] D[32,34] = var(40); // [ var(34) , var(32) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUso10(); ncAlgebra; setring ncAlgebra; // ... 390 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: so12(Q) has the type: D6, and defined by: proc makeUso12(list #) "USAGE: makeUso12([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(so_{12}) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(so_{12}) is derived from the Chevalley representation of so_{12}, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUso12; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..30),Y(1..30),H(1..6)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,61] = (2)*var(1); // [ var(61) , var(1) ] D[2,61] = (-1)*var(2); // [ var(61) , var(2) ] D[7,61] = var(7); // [ var(61) , var(7) ] D[8,61] = (-1)*var(8); // [ var(61) , var(8) ] D[12,61] = var(12); // [ var(61) , var(12) ] D[13,61] = (-1)*var(13); // [ var(61) , var(13) ] D[17,61] = var(17); // [ var(61) , var(17) ] D[18,61] = (-1)*var(18); // [ var(61) , var(18) ] D[19,61] = (-1)*var(19); // [ var(61) , var(19) ] D[21,61] = var(21); // [ var(61) , var(21) ] D[22,61] = var(22); // [ var(61) , var(22) ] D[23,61] = (-1)*var(23); // [ var(61) , var(23) ] D[25,61] = var(25); // [ var(61) , var(25) ] D[26,61] = (-1)*var(26); // [ var(61) , var(26) ] D[27,61] = var(27); // [ var(61) , var(27) ] D[28,61] = (-1)*var(28); // [ var(61) , var(28) ] D[29,61] = var(29); // [ var(61) , var(29) ] D[1,62] = (-1)*var(1); // [ var(62) , var(1) ] D[2,62] = (2)*var(2); // [ var(62) , var(2) ] D[3,62] = (-1)*var(3); // [ var(62) , var(3) ] D[7,62] = var(7); // [ var(62) , var(7) ] D[8,62] = var(8); // [ var(62) , var(8) ] D[9,62] = (-1)*var(9); // [ var(62) , var(9) ] D[13,62] = var(13); // [ var(62) , var(13) ] D[14,62] = (-1)*var(14); // [ var(62) , var(14) ] D[15,62] = (-1)*var(15); // [ var(62) , var(15) ] D[18,62] = var(18); // [ var(62) , var(18) ] D[19,62] = var(19); // [ var(62) , var(19) ] D[20,62] = (-1)*var(20); // [ var(62) , var(20) ] D[23,62] = var(23); // [ var(62) , var(23) ] D[24,62] = (-1)*var(24); // [ var(62) , var(24) ] D[26,62] = var(26); // [ var(62) , var(26) ] D[29,62] = (-1)*var(29); // [ var(62) , var(29) ] D[30,62] = var(30); // [ var(62) , var(30) ] D[2,63] = (-1)*var(2); // [ var(63) , var(2) ] D[3,63] = (2)*var(3); // [ var(63) , var(3) ] D[4,63] = (-1)*var(4); // [ var(63) , var(4) ] D[7,63] = (-1)*var(7); // [ var(63) , var(7) ] D[8,63] = var(8); // [ var(63) , var(8) ] D[9,63] = var(9); // [ var(63) , var(9) ] D[10,63] = (-1)*var(10); // [ var(63) , var(10) ] D[11,63] = (-1)*var(11); // [ var(63) , var(11) ] D[12,63] = var(12); // [ var(63) , var(12) ] D[14,63] = var(14); // [ var(63) , var(14) ] D[15,63] = var(15); // [ var(63) , var(15) ] D[16,63] = (-1)*var(16); // [ var(63) , var(16) ] D[20,63] = var(20); // [ var(63) , var(20) ] D[26,63] = (-1)*var(26); // [ var(63) , var(26) ] D[27,63] = (-1)*var(27); // [ var(63) , var(27) ] D[28,63] = var(28); // [ var(63) , var(28) ] D[29,63] = var(29); // [ var(63) , var(29) ] D[3,64] = (-1)*var(3); // [ var(64) , var(3) ] D[4,64] = (2)*var(4); // [ var(64) , var(4) ] D[5,64] = (-1)*var(5); // [ var(64) , var(5) ] D[6,64] = (-1)*var(6); // [ var(64) , var(6) ] D[8,64] = (-1)*var(8); // [ var(64) , var(8) ] D[9,64] = var(9); // [ var(64) , var(9) ] D[10,64] = var(10); // [ var(64) , var(10) ] D[11,64] = var(11); // [ var(64) , var(11) ] D[12,64] = (-1)*var(12); // [ var(64) , var(12) ] D[13,64] = var(13); // [ var(64) , var(13) ] D[17,64] = var(17); // [ var(64) , var(17) ] D[20,64] = (-1)*var(20); // [ var(64) , var(20) ] D[23,64] = (-1)*var(23); // [ var(64) , var(23) ] D[24,64] = var(24); // [ var(64) , var(24) ] D[25,64] = (-1)*var(25); // [ var(64) , var(25) ] D[26,64] = var(26); // [ var(64) , var(26) ] D[27,64] = var(27); // [ var(64) , var(27) ] D[4,65] = (-1)*var(4); // [ var(65) , var(4) ] D[5,65] = (2)*var(5); // [ var(65) , var(5) ] D[9,65] = (-1)*var(9); // [ var(65) , var(9) ] D[10,65] = var(10); // [ var(65) , var(10) ] D[11,65] = (-1)*var(11); // [ var(65) , var(11) ] D[13,65] = (-1)*var(13); // [ var(65) , var(13) ] D[14,65] = var(14); // [ var(65) , var(14) ] D[15,65] = (-1)*var(15); // [ var(65) , var(15) ] D[16,65] = var(16); // [ var(65) , var(16) ] D[17,65] = (-1)*var(17); // [ var(65) , var(17) ] D[18,65] = var(18); // [ var(65) , var(18) ] D[19,65] = (-1)*var(19); // [ var(65) , var(19) ] D[20,65] = var(20); // [ var(65) , var(20) ] D[21,65] = var(21); // [ var(65) , var(21) ] D[22,65] = (-1)*var(22); // [ var(65) , var(22) ] D[23,65] = var(23); // [ var(65) , var(23) ] D[25,65] = var(25); // [ var(65) , var(25) ] D[4,66] = (-1)*var(4); // [ var(66) , var(4) ] D[6,66] = (2)*var(6); // [ var(66) , var(6) ] D[9,66] = (-1)*var(9); // [ var(66) , var(9) ] D[10,66] = (-1)*var(10); // [ var(66) , var(10) ] D[11,66] = var(11); // [ var(66) , var(11) ] D[13,66] = (-1)*var(13); // [ var(66) , var(13) ] D[14,66] = (-1)*var(14); // [ var(66) , var(14) ] D[15,66] = var(15); // [ var(66) , var(15) ] D[16,66] = var(16); // [ var(66) , var(16) ] D[17,66] = (-1)*var(17); // [ var(66) , var(17) ] D[18,66] = (-1)*var(18); // [ var(66) , var(18) ] D[19,66] = var(19); // [ var(66) , var(19) ] D[20,66] = var(20); // [ var(66) , var(20) ] D[21,66] = (-1)*var(21); // [ var(66) , var(21) ] D[22,66] = var(22); // [ var(66) , var(22) ] D[23,66] = var(23); // [ var(66) , var(23) ] D[25,66] = var(25); // [ var(66) , var(25) ] // H(i) * Y(j): D[31,61] = (-2)*var(31); // [ var(61) , var(31) ] D[32,61] = var(32); // [ var(61) , var(32) ] D[37,61] = (-1)*var(37); // [ var(61) , var(37) ] D[38,61] = var(38); // [ var(61) , var(38) ] D[42,61] = (-1)*var(42); // [ var(61) , var(42) ] D[43,61] = var(43); // [ var(61) , var(43) ] D[47,61] = (-1)*var(47); // [ var(61) , var(47) ] D[48,61] = var(48); // [ var(61) , var(48) ] D[49,61] = var(49); // [ var(61) , var(49) ] D[51,61] = (-1)*var(51); // [ var(61) , var(51) ] D[52,61] = (-1)*var(52); // [ var(61) , var(52) ] D[53,61] = var(53); // [ var(61) , var(53) ] D[55,61] = (-1)*var(55); // [ var(61) , var(55) ] D[56,61] = var(56); // [ var(61) , var(56) ] D[57,61] = (-1)*var(57); // [ var(61) , var(57) ] D[58,61] = var(58); // [ var(61) , var(58) ] D[59,61] = (-1)*var(59); // [ var(61) , var(59) ] D[31,62] = var(31); // [ var(62) , var(31) ] D[32,62] = (-2)*var(32); // [ var(62) , var(32) ] D[33,62] = var(33); // [ var(62) , var(33) ] D[37,62] = (-1)*var(37); // [ var(62) , var(37) ] D[38,62] = (-1)*var(38); // [ var(62) , var(38) ] D[39,62] = var(39); // [ var(62) , var(39) ] D[43,62] = (-1)*var(43); // [ var(62) , var(43) ] D[44,62] = var(44); // [ var(62) , var(44) ] D[45,62] = var(45); // [ var(62) , var(45) ] D[48,62] = (-1)*var(48); // [ var(62) , var(48) ] D[49,62] = (-1)*var(49); // [ var(62) , var(49) ] D[50,62] = var(50); // [ var(62) , var(50) ] D[53,62] = (-1)*var(53); // [ var(62) , var(53) ] D[54,62] = var(54); // [ var(62) , var(54) ] D[56,62] = (-1)*var(56); // [ var(62) , var(56) ] D[59,62] = var(59); // [ var(62) , var(59) ] D[60,62] = (-1)*var(60); // [ var(62) , var(60) ] D[32,63] = var(32); // [ var(63) , var(32) ] D[33,63] = (-2)*var(33); // [ var(63) , var(33) ] D[34,63] = var(34); // [ var(63) , var(34) ] D[37,63] = var(37); // [ var(63) , var(37) ] D[38,63] = (-1)*var(38); // [ var(63) , var(38) ] D[39,63] = (-1)*var(39); // [ var(63) , var(39) ] D[40,63] = var(40); // [ var(63) , var(40) ] D[41,63] = var(41); // [ var(63) , var(41) ] D[42,63] = (-1)*var(42); // [ var(63) , var(42) ] D[44,63] = (-1)*var(44); // [ var(63) , var(44) ] D[45,63] = (-1)*var(45); // [ var(63) , var(45) ] D[46,63] = var(46); // [ var(63) , var(46) ] D[50,63] = (-1)*var(50); // [ var(63) , var(50) ] D[56,63] = var(56); // [ var(63) , var(56) ] D[57,63] = var(57); // [ var(63) , var(57) ] D[58,63] = (-1)*var(58); // [ var(63) , var(58) ] D[59,63] = (-1)*var(59); // [ var(63) , var(59) ] D[33,64] = var(33); // [ var(64) , var(33) ] D[34,64] = (-2)*var(34); // [ var(64) , var(34) ] D[35,64] = var(35); // [ var(64) , var(35) ] D[36,64] = var(36); // [ var(64) , var(36) ] D[38,64] = var(38); // [ var(64) , var(38) ] D[39,64] = (-1)*var(39); // [ var(64) , var(39) ] D[40,64] = (-1)*var(40); // [ var(64) , var(40) ] D[41,64] = (-1)*var(41); // [ var(64) , var(41) ] D[42,64] = var(42); // [ var(64) , var(42) ] D[43,64] = (-1)*var(43); // [ var(64) , var(43) ] D[47,64] = (-1)*var(47); // [ var(64) , var(47) ] D[50,64] = var(50); // [ var(64) , var(50) ] D[53,64] = var(53); // [ var(64) , var(53) ] D[54,64] = (-1)*var(54); // [ var(64) , var(54) ] D[55,64] = var(55); // [ var(64) , var(55) ] D[56,64] = (-1)*var(56); // [ var(64) , var(56) ] D[57,64] = (-1)*var(57); // [ var(64) , var(57) ] D[34,65] = var(34); // [ var(65) , var(34) ] D[35,65] = (-2)*var(35); // [ var(65) , var(35) ] D[39,65] = var(39); // [ var(65) , var(39) ] D[40,65] = (-1)*var(40); // [ var(65) , var(40) ] D[41,65] = var(41); // [ var(65) , var(41) ] D[43,65] = var(43); // [ var(65) , var(43) ] D[44,65] = (-1)*var(44); // [ var(65) , var(44) ] D[45,65] = var(45); // [ var(65) , var(45) ] D[46,65] = (-1)*var(46); // [ var(65) , var(46) ] D[47,65] = var(47); // [ var(65) , var(47) ] D[48,65] = (-1)*var(48); // [ var(65) , var(48) ] D[49,65] = var(49); // [ var(65) , var(49) ] D[50,65] = (-1)*var(50); // [ var(65) , var(50) ] D[51,65] = (-1)*var(51); // [ var(65) , var(51) ] D[52,65] = var(52); // [ var(65) , var(52) ] D[53,65] = (-1)*var(53); // [ var(65) , var(53) ] D[55,65] = (-1)*var(55); // [ var(65) , var(55) ] D[34,66] = var(34); // [ var(66) , var(34) ] D[36,66] = (-2)*var(36); // [ var(66) , var(36) ] D[39,66] = var(39); // [ var(66) , var(39) ] D[40,66] = var(40); // [ var(66) , var(40) ] D[41,66] = (-1)*var(41); // [ var(66) , var(41) ] D[43,66] = var(43); // [ var(66) , var(43) ] D[44,66] = var(44); // [ var(66) , var(44) ] D[45,66] = (-1)*var(45); // [ var(66) , var(45) ] D[46,66] = (-1)*var(46); // [ var(66) , var(46) ] D[47,66] = var(47); // [ var(66) , var(47) ] D[48,66] = var(48); // [ var(66) , var(48) ] D[49,66] = (-1)*var(49); // [ var(66) , var(49) ] D[50,66] = (-1)*var(50); // [ var(66) , var(50) ] D[51,66] = var(51); // [ var(66) , var(51) ] D[52,66] = (-1)*var(52); // [ var(66) , var(52) ] D[53,66] = (-1)*var(53); // [ var(66) , var(53) ] D[55,66] = (-1)*var(55); // [ var(66) , var(55) ] // Y(i) * X(j): D[1,31] = (-1)*var(61); // [ var(31) , var(1) ] D[7,31] = (-1)*var(2); // [ var(31) , var(7) ] D[12,31] = (-1)*var(8); // [ var(31) , var(12) ] D[17,31] = (-1)*var(13); // [ var(31) , var(17) ] D[21,31] = (-1)*var(18); // [ var(31) , var(21) ] D[22,31] = (-1)*var(19); // [ var(31) , var(22) ] D[25,31] = (-1)*var(23); // [ var(31) , var(25) ] D[27,31] = (-1)*var(26); // [ var(31) , var(27) ] D[29,31] = (-1)*var(28); // [ var(31) , var(29) ] D[2,32] = (-1)*var(62); // [ var(32) , var(2) ] D[7,32] = var(1); // [ var(32) , var(7) ] D[8,32] = (-1)*var(3); // [ var(32) , var(8) ] D[13,32] = (-1)*var(9); // [ var(32) , var(13) ] D[18,32] = (-1)*var(14); // [ var(32) , var(18) ] D[19,32] = (-1)*var(15); // [ var(32) , var(19) ] D[23,32] = (-1)*var(20); // [ var(32) , var(23) ] D[26,32] = (-1)*var(24); // [ var(32) , var(26) ] D[30,32] = (-1)*var(29); // [ var(32) , var(30) ] D[3,33] = (-1)*var(63); // [ var(33) , var(3) ] D[8,33] = var(2); // [ var(33) , var(8) ] D[9,33] = (-1)*var(4); // [ var(33) , var(9) ] D[12,33] = var(7); // [ var(33) , var(12) ] D[14,33] = (-1)*var(10); // [ var(33) , var(14) ] D[15,33] = (-1)*var(11); // [ var(33) , var(15) ] D[20,33] = (-1)*var(16); // [ var(33) , var(20) ] D[28,33] = (-1)*var(26); // [ var(33) , var(28) ] D[29,33] = (-1)*var(27); // [ var(33) , var(29) ] D[4,34] = (-1)*var(64); // [ var(34) , var(4) ] D[9,34] = var(3); // [ var(34) , var(9) ] D[10,34] = (-1)*var(5); // [ var(34) , var(10) ] D[11,34] = (-1)*var(6); // [ var(34) , var(11) ] D[13,34] = var(8); // [ var(34) , var(13) ] D[17,34] = var(12); // [ var(34) , var(17) ] D[24,34] = (-1)*var(20); // [ var(34) , var(24) ] D[26,34] = (-1)*var(23); // [ var(34) , var(26) ] D[27,34] = (-1)*var(25); // [ var(34) , var(27) ] D[5,35] = (-1)*var(65); // [ var(35) , var(5) ] D[10,35] = var(4); // [ var(35) , var(10) ] D[14,35] = var(9); // [ var(35) , var(14) ] D[16,35] = var(11); // [ var(35) , var(16) ] D[18,35] = var(13); // [ var(35) , var(18) ] D[20,35] = var(15); // [ var(35) , var(20) ] D[21,35] = var(17); // [ var(35) , var(21) ] D[23,35] = var(19); // [ var(35) , var(23) ] D[25,35] = var(22); // [ var(35) , var(25) ] D[6,36] = (-1)*var(66); // [ var(36) , var(6) ] D[11,36] = var(4); // [ var(36) , var(11) ] D[15,36] = var(9); // [ var(36) , var(15) ] D[16,36] = var(10); // [ var(36) , var(16) ] D[19,36] = var(13); // [ var(36) , var(19) ] D[20,36] = var(14); // [ var(36) , var(20) ] D[22,36] = var(17); // [ var(36) , var(22) ] D[23,36] = var(18); // [ var(36) , var(23) ] D[25,36] = var(21); // [ var(36) , var(25) ] D[1,37] = (-1)*var(32); // [ var(37) , var(1) ] D[2,37] = var(31); // [ var(37) , var(2) ] D[7,37] = (-1)*var(61)+(-1)*var(62); // [ var(37) , var(7) ] D[12,37] = (-1)*var(3); // [ var(37) , var(12) ] D[17,37] = (-1)*var(9); // [ var(37) , var(17) ] D[21,37] = (-1)*var(14); // [ var(37) , var(21) ] D[22,37] = (-1)*var(15); // [ var(37) , var(22) ] D[25,37] = (-1)*var(20); // [ var(37) , var(25) ] D[27,37] = (-1)*var(24); // [ var(37) , var(27) ] D[30,37] = var(28); // [ var(37) , var(30) ] D[2,38] = (-1)*var(33); // [ var(38) , var(2) ] D[3,38] = var(32); // [ var(38) , var(3) ] D[8,38] = (-1)*var(62)+(-1)*var(63); // [ var(38) , var(8) ] D[12,38] = var(1); // [ var(38) , var(12) ] D[13,38] = (-1)*var(4); // [ var(38) , var(13) ] D[18,38] = (-1)*var(10); // [ var(38) , var(18) ] D[19,38] = (-1)*var(11); // [ var(38) , var(19) ] D[23,38] = (-1)*var(16); // [ var(38) , var(23) ] D[28,38] = var(24); // [ var(38) , var(28) ] D[30,38] = (-1)*var(27); // [ var(38) , var(30) ] D[3,39] = (-1)*var(34); // [ var(39) , var(3) ] D[4,39] = var(33); // [ var(39) , var(4) ] D[9,39] = (-1)*var(63)+(-1)*var(64); // [ var(39) , var(9) ] D[13,39] = var(2); // [ var(39) , var(13) ] D[14,39] = (-1)*var(5); // [ var(39) , var(14) ] D[15,39] = (-1)*var(6); // [ var(39) , var(15) ] D[17,39] = var(7); // [ var(39) , var(17) ] D[24,39] = var(16); // [ var(39) , var(24) ] D[28,39] = (-1)*var(23); // [ var(39) , var(28) ] D[29,39] = (-1)*var(25); // [ var(39) , var(29) ] D[4,40] = (-1)*var(35); // [ var(40) , var(4) ] D[5,40] = var(34); // [ var(40) , var(5) ] D[10,40] = (-1)*var(64)+(-1)*var(65); // [ var(40) , var(10) ] D[14,40] = var(3); // [ var(40) , var(14) ] D[16,40] = (-1)*var(6); // [ var(40) , var(16) ] D[18,40] = var(8); // [ var(40) , var(18) ] D[21,40] = var(12); // [ var(40) , var(21) ] D[24,40] = var(15); // [ var(40) , var(24) ] D[26,40] = var(19); // [ var(40) , var(26) ] D[27,40] = var(22); // [ var(40) , var(27) ] D[4,41] = (-1)*var(36); // [ var(41) , var(4) ] D[6,41] = var(34); // [ var(41) , var(6) ] D[11,41] = (-1)*var(64)+(-1)*var(66); // [ var(41) , var(11) ] D[15,41] = var(3); // [ var(41) , var(15) ] D[16,41] = (-1)*var(5); // [ var(41) , var(16) ] D[19,41] = var(8); // [ var(41) , var(19) ] D[22,41] = var(12); // [ var(41) , var(22) ] D[24,41] = var(14); // [ var(41) , var(24) ] D[26,41] = var(18); // [ var(41) , var(26) ] D[27,41] = var(21); // [ var(41) , var(27) ] D[1,42] = (-1)*var(38); // [ var(42) , var(1) ] D[3,42] = var(37); // [ var(42) , var(3) ] D[7,42] = (-1)*var(33); // [ var(42) , var(7) ] D[8,42] = var(31); // [ var(42) , var(8) ] D[12,42] = (-1)*var(61)+(-1)*var(62)+(-1)*var(63); // [ var(42) , var(12) ] D[17,42] = (-1)*var(4); // [ var(42) , var(17) ] D[21,42] = (-1)*var(10); // [ var(42) , var(21) ] D[22,42] = (-1)*var(11); // [ var(42) , var(22) ] D[25,42] = (-1)*var(16); // [ var(42) , var(25) ] D[29,42] = var(24); // [ var(42) , var(29) ] D[30,42] = var(26); // [ var(42) , var(30) ] D[2,43] = (-1)*var(39); // [ var(43) , var(2) ] D[4,43] = var(38); // [ var(43) , var(4) ] D[8,43] = (-1)*var(34); // [ var(43) , var(8) ] D[9,43] = var(32); // [ var(43) , var(9) ] D[13,43] = (-1)*var(62)+(-1)*var(63)+(-1)*var(64); // [ var(43) , var(13) ] D[17,43] = var(1); // [ var(43) , var(17) ] D[18,43] = (-1)*var(5); // [ var(43) , var(18) ] D[19,43] = (-1)*var(6); // [ var(43) , var(19) ] D[26,43] = var(16); // [ var(43) , var(26) ] D[28,43] = var(20); // [ var(43) , var(28) ] D[30,43] = (-1)*var(25); // [ var(43) , var(30) ] D[3,44] = (-1)*var(40); // [ var(44) , var(3) ] D[5,44] = var(39); // [ var(44) , var(5) ] D[9,44] = (-1)*var(35); // [ var(44) , var(9) ] D[10,44] = var(33); // [ var(44) , var(10) ] D[14,44] = (-1)*var(63)+(-1)*var(64)+(-1)*var(65); // [ var(44) , var(14) ] D[18,44] = var(2); // [ var(44) , var(18) ] D[20,44] = (-1)*var(6); // [ var(44) , var(20) ] D[21,44] = var(7); // [ var(44) , var(21) ] D[24,44] = (-1)*var(11); // [ var(44) , var(24) ] D[28,44] = var(19); // [ var(44) , var(28) ] D[29,44] = var(22); // [ var(44) , var(29) ] D[3,45] = (-1)*var(41); // [ var(45) , var(3) ] D[6,45] = var(39); // [ var(45) , var(6) ] D[9,45] = (-1)*var(36); // [ var(45) , var(9) ] D[11,45] = var(33); // [ var(45) , var(11) ] D[15,45] = (-1)*var(63)+(-1)*var(64)+(-1)*var(66); // [ var(45) , var(15) ] D[19,45] = var(2); // [ var(45) , var(19) ] D[20,45] = (-1)*var(5); // [ var(45) , var(20) ] D[22,45] = var(7); // [ var(45) , var(22) ] D[24,45] = (-1)*var(10); // [ var(45) , var(24) ] D[28,45] = var(18); // [ var(45) , var(28) ] D[29,45] = var(21); // [ var(45) , var(29) ] D[5,46] = var(41); // [ var(46) , var(5) ] D[6,46] = var(40); // [ var(46) , var(6) ] D[10,46] = (-1)*var(36); // [ var(46) , var(10) ] D[11,46] = (-1)*var(35); // [ var(46) , var(11) ] D[16,46] = (-1)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(46) , var(16) ] D[20,46] = var(3); // [ var(46) , var(20) ] D[23,46] = var(8); // [ var(46) , var(23) ] D[24,46] = (-1)*var(9); // [ var(46) , var(24) ] D[25,46] = var(12); // [ var(46) , var(25) ] D[26,46] = (-1)*var(13); // [ var(46) , var(26) ] D[27,46] = (-1)*var(17); // [ var(46) , var(27) ] D[1,47] = (-1)*var(43); // [ var(47) , var(1) ] D[4,47] = var(42); // [ var(47) , var(4) ] D[7,47] = (-1)*var(39); // [ var(47) , var(7) ] D[9,47] = var(37); // [ var(47) , var(9) ] D[12,47] = (-1)*var(34); // [ var(47) , var(12) ] D[13,47] = var(31); // [ var(47) , var(13) ] D[17,47] = (-1)*var(61)+(-1)*var(62)+(-1)*var(63)+(-1)*var(64); // [ var(47) , var(17) ] D[21,47] = (-1)*var(5); // [ var(47) , var(21) ] D[22,47] = (-1)*var(6); // [ var(47) , var(22) ] D[27,47] = var(16); // [ var(47) , var(27) ] D[29,47] = var(20); // [ var(47) , var(29) ] D[30,47] = var(23); // [ var(47) , var(30) ] D[2,48] = (-1)*var(44); // [ var(48) , var(2) ] D[5,48] = var(43); // [ var(48) , var(5) ] D[8,48] = (-1)*var(40); // [ var(48) , var(8) ] D[10,48] = var(38); // [ var(48) , var(10) ] D[13,48] = (-1)*var(35); // [ var(48) , var(13) ] D[14,48] = var(32); // [ var(48) , var(14) ] D[18,48] = (-1)*var(62)+(-1)*var(63)+(-1)*var(64)+(-1)*var(65); // [ var(48) , var(18) ] D[21,48] = var(1); // [ var(48) , var(21) ] D[23,48] = (-1)*var(6); // [ var(48) , var(23) ] D[26,48] = (-1)*var(11); // [ var(48) , var(26) ] D[28,48] = (-1)*var(15); // [ var(48) , var(28) ] D[30,48] = var(22); // [ var(48) , var(30) ] D[2,49] = (-1)*var(45); // [ var(49) , var(2) ] D[6,49] = var(43); // [ var(49) , var(6) ] D[8,49] = (-1)*var(41); // [ var(49) , var(8) ] D[11,49] = var(38); // [ var(49) , var(11) ] D[13,49] = (-1)*var(36); // [ var(49) , var(13) ] D[15,49] = var(32); // [ var(49) , var(15) ] D[19,49] = (-1)*var(62)+(-1)*var(63)+(-1)*var(64)+(-1)*var(66); // [ var(49) , var(19) ] D[22,49] = var(1); // [ var(49) , var(22) ] D[23,49] = (-1)*var(5); // [ var(49) , var(23) ] D[26,49] = (-1)*var(10); // [ var(49) , var(26) ] D[28,49] = (-1)*var(14); // [ var(49) , var(28) ] D[30,49] = var(21); // [ var(49) , var(30) ] D[3,50] = (-1)*var(46); // [ var(50) , var(3) ] D[5,50] = var(45); // [ var(50) , var(5) ] D[6,50] = var(44); // [ var(50) , var(6) ] D[14,50] = (-1)*var(36); // [ var(50) , var(14) ] D[15,50] = (-1)*var(35); // [ var(50) , var(15) ] D[16,50] = var(33); // [ var(50) , var(16) ] D[20,50] = (-1)*var(63)+(-1)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(50) , var(20) ] D[23,50] = var(2); // [ var(50) , var(23) ] D[24,50] = var(4); // [ var(50) , var(24) ] D[25,50] = var(7); // [ var(50) , var(25) ] D[28,50] = (-1)*var(13); // [ var(50) , var(28) ] D[29,50] = (-1)*var(17); // [ var(50) , var(29) ] D[1,51] = (-1)*var(48); // [ var(51) , var(1) ] D[5,51] = var(47); // [ var(51) , var(5) ] D[7,51] = (-1)*var(44); // [ var(51) , var(7) ] D[10,51] = var(42); // [ var(51) , var(10) ] D[12,51] = (-1)*var(40); // [ var(51) , var(12) ] D[14,51] = var(37); // [ var(51) , var(14) ] D[17,51] = (-1)*var(35); // [ var(51) , var(17) ] D[18,51] = var(31); // [ var(51) , var(18) ] D[21,51] = (-1)*var(61)+(-1)*var(62)+(-1)*var(63)+(-1)*var(64)+(-1)*var(65); // [ var(51) , var(21) ] D[25,51] = (-1)*var(6); // [ var(51) , var(25) ] D[27,51] = (-1)*var(11); // [ var(51) , var(27) ] D[29,51] = (-1)*var(15); // [ var(51) , var(29) ] D[30,51] = (-1)*var(19); // [ var(51) , var(30) ] D[1,52] = (-1)*var(49); // [ var(52) , var(1) ] D[6,52] = var(47); // [ var(52) , var(6) ] D[7,52] = (-1)*var(45); // [ var(52) , var(7) ] D[11,52] = var(42); // [ var(52) , var(11) ] D[12,52] = (-1)*var(41); // [ var(52) , var(12) ] D[15,52] = var(37); // [ var(52) , var(15) ] D[17,52] = (-1)*var(36); // [ var(52) , var(17) ] D[19,52] = var(31); // [ var(52) , var(19) ] D[22,52] = (-1)*var(61)+(-1)*var(62)+(-1)*var(63)+(-1)*var(64)+(-1)*var(66); // [ var(52) , var(22) ] D[25,52] = (-1)*var(5); // [ var(52) , var(25) ] D[27,52] = (-1)*var(10); // [ var(52) , var(27) ] D[29,52] = (-1)*var(14); // [ var(52) , var(29) ] D[30,52] = (-1)*var(18); // [ var(52) , var(30) ] D[2,53] = (-1)*var(50); // [ var(53) , var(2) ] D[5,53] = var(49); // [ var(53) , var(5) ] D[6,53] = var(48); // [ var(53) , var(6) ] D[8,53] = (-1)*var(46); // [ var(53) , var(8) ] D[16,53] = var(38); // [ var(53) , var(16) ] D[18,53] = (-1)*var(36); // [ var(53) , var(18) ] D[19,53] = (-1)*var(35); // [ var(53) , var(19) ] D[20,53] = var(32); // [ var(53) , var(20) ] D[23,53] = (-1)*var(62)+(-1)*var(63)+(-1)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(53) , var(23) ] D[25,53] = var(1); // [ var(53) , var(25) ] D[26,53] = var(4); // [ var(53) , var(26) ] D[28,53] = var(9); // [ var(53) , var(28) ] D[30,53] = (-1)*var(17); // [ var(53) , var(30) ] D[4,54] = (-1)*var(50); // [ var(54) , var(4) ] D[9,54] = var(46); // [ var(54) , var(9) ] D[10,54] = var(45); // [ var(54) , var(10) ] D[11,54] = var(44); // [ var(54) , var(11) ] D[14,54] = (-1)*var(41); // [ var(54) , var(14) ] D[15,54] = (-1)*var(40); // [ var(54) , var(15) ] D[16,54] = (-1)*var(39); // [ var(54) , var(16) ] D[20,54] = var(34); // [ var(54) , var(20) ] D[24,54] = (-1)*var(63)+(-2)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(54) , var(24) ] D[26,54] = var(2); // [ var(54) , var(26) ] D[27,54] = var(7); // [ var(54) , var(27) ] D[28,54] = (-1)*var(8); // [ var(54) , var(28) ] D[29,54] = (-1)*var(12); // [ var(54) , var(29) ] D[1,55] = (-1)*var(53); // [ var(55) , var(1) ] D[5,55] = var(52); // [ var(55) , var(5) ] D[6,55] = var(51); // [ var(55) , var(6) ] D[7,55] = (-1)*var(50); // [ var(55) , var(7) ] D[12,55] = (-1)*var(46); // [ var(55) , var(12) ] D[16,55] = var(42); // [ var(55) , var(16) ] D[20,55] = var(37); // [ var(55) , var(20) ] D[21,55] = (-1)*var(36); // [ var(55) , var(21) ] D[22,55] = (-1)*var(35); // [ var(55) , var(22) ] D[23,55] = var(31); // [ var(55) , var(23) ] D[25,55] = (-1)*var(61)+(-1)*var(62)+(-1)*var(63)+(-1)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(55) , var(25) ] D[27,55] = var(4); // [ var(55) , var(27) ] D[29,55] = var(9); // [ var(55) , var(29) ] D[30,55] = var(13); // [ var(55) , var(30) ] D[2,56] = (-1)*var(54); // [ var(56) , var(2) ] D[4,56] = (-1)*var(53); // [ var(56) , var(4) ] D[10,56] = var(49); // [ var(56) , var(10) ] D[11,56] = var(48); // [ var(56) , var(11) ] D[13,56] = var(46); // [ var(56) , var(13) ] D[16,56] = (-1)*var(43); // [ var(56) , var(16) ] D[18,56] = (-1)*var(41); // [ var(56) , var(18) ] D[19,56] = (-1)*var(40); // [ var(56) , var(19) ] D[23,56] = var(34); // [ var(56) , var(23) ] D[24,56] = var(32); // [ var(56) , var(24) ] D[26,56] = (-1)*var(62)+(-1)*var(63)+(-2)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(56) , var(26) ] D[27,56] = var(1); // [ var(56) , var(27) ] D[28,56] = var(3); // [ var(56) , var(28) ] D[30,56] = (-1)*var(12); // [ var(56) , var(30) ] D[1,57] = (-1)*var(56); // [ var(57) , var(1) ] D[4,57] = (-1)*var(55); // [ var(57) , var(4) ] D[7,57] = (-1)*var(54); // [ var(57) , var(7) ] D[10,57] = var(52); // [ var(57) , var(10) ] D[11,57] = var(51); // [ var(57) , var(11) ] D[16,57] = (-1)*var(47); // [ var(57) , var(16) ] D[17,57] = var(46); // [ var(57) , var(17) ] D[21,57] = (-1)*var(41); // [ var(57) , var(21) ] D[22,57] = (-1)*var(40); // [ var(57) , var(22) ] D[24,57] = var(37); // [ var(57) , var(24) ] D[25,57] = var(34); // [ var(57) , var(25) ] D[26,57] = var(31); // [ var(57) , var(26) ] D[27,57] = (-1)*var(61)+(-1)*var(62)+(-1)*var(63)+(-2)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(57) , var(27) ] D[29,57] = var(3); // [ var(57) , var(29) ] D[30,57] = var(8); // [ var(57) , var(30) ] D[3,58] = (-1)*var(56); // [ var(58) , var(3) ] D[8,58] = var(54); // [ var(58) , var(8) ] D[9,58] = (-1)*var(53); // [ var(58) , var(9) ] D[13,58] = var(50); // [ var(58) , var(13) ] D[14,58] = var(49); // [ var(58) , var(14) ] D[15,58] = var(48); // [ var(58) , var(15) ] D[18,58] = (-1)*var(45); // [ var(58) , var(18) ] D[19,58] = (-1)*var(44); // [ var(58) , var(19) ] D[20,58] = (-1)*var(43); // [ var(58) , var(20) ] D[23,58] = var(39); // [ var(58) , var(23) ] D[24,58] = (-1)*var(38); // [ var(58) , var(24) ] D[26,58] = var(33); // [ var(58) , var(26) ] D[28,58] = (-1)*var(62)+(-2)*var(63)+(-2)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(58) , var(28) ] D[29,58] = var(1); // [ var(58) , var(29) ] D[30,58] = (-1)*var(7); // [ var(58) , var(30) ] D[1,59] = (-1)*var(58); // [ var(59) , var(1) ] D[3,59] = (-1)*var(57); // [ var(59) , var(3) ] D[9,59] = (-1)*var(55); // [ var(59) , var(9) ] D[12,59] = var(54); // [ var(59) , var(12) ] D[14,59] = var(52); // [ var(59) , var(14) ] D[15,59] = var(51); // [ var(59) , var(15) ] D[17,59] = var(50); // [ var(59) , var(17) ] D[20,59] = (-1)*var(47); // [ var(59) , var(20) ] D[21,59] = (-1)*var(45); // [ var(59) , var(21) ] D[22,59] = (-1)*var(44); // [ var(59) , var(22) ] D[24,59] = (-1)*var(42); // [ var(59) , var(24) ] D[25,59] = var(39); // [ var(59) , var(25) ] D[27,59] = var(33); // [ var(59) , var(27) ] D[28,59] = var(31); // [ var(59) , var(28) ] D[29,59] = (-1)*var(61)+(-1)*var(62)+(-2)*var(63)+(-2)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(59) , var(29) ] D[30,59] = var(2); // [ var(59) , var(30) ] D[2,60] = (-1)*var(59); // [ var(60) , var(2) ] D[7,60] = var(58); // [ var(60) , var(7) ] D[8,60] = (-1)*var(57); // [ var(60) , var(8) ] D[12,60] = var(56); // [ var(60) , var(12) ] D[13,60] = (-1)*var(55); // [ var(60) , var(13) ] D[17,60] = var(53); // [ var(60) , var(17) ] D[18,60] = var(52); // [ var(60) , var(18) ] D[19,60] = var(51); // [ var(60) , var(19) ] D[21,60] = (-1)*var(49); // [ var(60) , var(21) ] D[22,60] = (-1)*var(48); // [ var(60) , var(22) ] D[23,60] = (-1)*var(47); // [ var(60) , var(23) ] D[25,60] = var(43); // [ var(60) , var(25) ] D[26,60] = (-1)*var(42); // [ var(60) , var(26) ] D[27,60] = var(38); // [ var(60) , var(27) ] D[28,60] = (-1)*var(37); // [ var(60) , var(28) ] D[29,60] = var(32); // [ var(60) , var(29) ] D[30,60] = (-1)*var(61)+(-2)*var(62)+(-2)*var(63)+(-2)*var(64)+(-1)*var(65)+(-1)*var(66); // [ var(60) , var(30) ] // X(i) * X(j): D[1,2] = var(7); // [ var(2) , var(1) ] D[1,8] = var(12); // [ var(8) , var(1) ] D[1,13] = var(17); // [ var(13) , var(1) ] D[1,18] = var(21); // [ var(18) , var(1) ] D[1,19] = var(22); // [ var(19) , var(1) ] D[1,23] = var(25); // [ var(23) , var(1) ] D[1,26] = var(27); // [ var(26) , var(1) ] D[1,28] = var(29); // [ var(28) , var(1) ] D[2,3] = var(8); // [ var(3) , var(2) ] D[2,9] = var(13); // [ var(9) , var(2) ] D[2,14] = var(18); // [ var(14) , var(2) ] D[2,15] = var(19); // [ var(15) , var(2) ] D[2,20] = var(23); // [ var(20) , var(2) ] D[2,24] = var(26); // [ var(24) , var(2) ] D[2,29] = var(30); // [ var(29) , var(2) ] D[3,4] = var(9); // [ var(4) , var(3) ] D[3,7] = (-1)*var(12); // [ var(7) , var(3) ] D[3,10] = var(14); // [ var(10) , var(3) ] D[3,11] = var(15); // [ var(11) , var(3) ] D[3,16] = var(20); // [ var(16) , var(3) ] D[3,26] = var(28); // [ var(26) , var(3) ] D[3,27] = var(29); // [ var(27) , var(3) ] D[4,5] = var(10); // [ var(5) , var(4) ] D[4,6] = var(11); // [ var(6) , var(4) ] D[4,8] = (-1)*var(13); // [ var(8) , var(4) ] D[4,12] = (-1)*var(17); // [ var(12) , var(4) ] D[4,20] = var(24); // [ var(20) , var(4) ] D[4,23] = var(26); // [ var(23) , var(4) ] D[4,25] = var(27); // [ var(25) , var(4) ] D[5,9] = (-1)*var(14); // [ var(9) , var(5) ] D[5,11] = (-1)*var(16); // [ var(11) , var(5) ] D[5,13] = (-1)*var(18); // [ var(13) , var(5) ] D[5,15] = (-1)*var(20); // [ var(15) , var(5) ] D[5,17] = (-1)*var(21); // [ var(17) , var(5) ] D[5,19] = (-1)*var(23); // [ var(19) , var(5) ] D[5,22] = (-1)*var(25); // [ var(22) , var(5) ] D[6,9] = (-1)*var(15); // [ var(9) , var(6) ] D[6,10] = (-1)*var(16); // [ var(10) , var(6) ] D[6,13] = (-1)*var(19); // [ var(13) , var(6) ] D[6,14] = (-1)*var(20); // [ var(14) , var(6) ] D[6,17] = (-1)*var(22); // [ var(17) , var(6) ] D[6,18] = (-1)*var(23); // [ var(18) , var(6) ] D[6,21] = (-1)*var(25); // [ var(21) , var(6) ] D[7,9] = var(17); // [ var(9) , var(7) ] D[7,14] = var(21); // [ var(14) , var(7) ] D[7,15] = var(22); // [ var(15) , var(7) ] D[7,20] = var(25); // [ var(20) , var(7) ] D[7,24] = var(27); // [ var(24) , var(7) ] D[7,28] = (-1)*var(30); // [ var(28) , var(7) ] D[8,10] = var(18); // [ var(10) , var(8) ] D[8,11] = var(19); // [ var(11) , var(8) ] D[8,16] = var(23); // [ var(16) , var(8) ] D[8,24] = (-1)*var(28); // [ var(24) , var(8) ] D[8,27] = var(30); // [ var(27) , var(8) ] D[9,16] = (-1)*var(24); // [ var(16) , var(9) ] D[9,23] = var(28); // [ var(23) , var(9) ] D[9,25] = var(29); // [ var(25) , var(9) ] D[10,12] = (-1)*var(21); // [ var(12) , var(10) ] D[10,15] = (-1)*var(24); // [ var(15) , var(10) ] D[10,19] = (-1)*var(26); // [ var(19) , var(10) ] D[10,22] = (-1)*var(27); // [ var(22) , var(10) ] D[11,12] = (-1)*var(22); // [ var(12) , var(11) ] D[11,14] = (-1)*var(24); // [ var(14) , var(11) ] D[11,18] = (-1)*var(26); // [ var(18) , var(11) ] D[11,21] = (-1)*var(27); // [ var(21) , var(11) ] D[12,16] = var(25); // [ var(16) , var(12) ] D[12,24] = (-1)*var(29); // [ var(24) , var(12) ] D[12,26] = (-1)*var(30); // [ var(26) , var(12) ] D[13,16] = (-1)*var(26); // [ var(16) , var(13) ] D[13,20] = (-1)*var(28); // [ var(20) , var(13) ] D[13,25] = var(30); // [ var(25) , var(13) ] D[14,19] = (-1)*var(28); // [ var(19) , var(14) ] D[14,22] = (-1)*var(29); // [ var(22) , var(14) ] D[15,18] = (-1)*var(28); // [ var(18) , var(15) ] D[15,21] = (-1)*var(29); // [ var(21) , var(15) ] D[16,17] = var(27); // [ var(17) , var(16) ] D[17,20] = (-1)*var(29); // [ var(20) , var(17) ] D[17,23] = (-1)*var(30); // [ var(23) , var(17) ] D[18,22] = (-1)*var(30); // [ var(22) , var(18) ] D[19,21] = (-1)*var(30); // [ var(21) , var(19) ] // Y(i) * Y(j): D[31,32] = (-1)*var(37); // [ var(32) , var(31) ] D[31,38] = (-1)*var(42); // [ var(38) , var(31) ] D[31,43] = (-1)*var(47); // [ var(43) , var(31) ] D[31,48] = (-1)*var(51); // [ var(48) , var(31) ] D[31,49] = (-1)*var(52); // [ var(49) , var(31) ] D[31,53] = (-1)*var(55); // [ var(53) , var(31) ] D[31,56] = (-1)*var(57); // [ var(56) , var(31) ] D[31,58] = (-1)*var(59); // [ var(58) , var(31) ] D[32,33] = (-1)*var(38); // [ var(33) , var(32) ] D[32,39] = (-1)*var(43); // [ var(39) , var(32) ] D[32,44] = (-1)*var(48); // [ var(44) , var(32) ] D[32,45] = (-1)*var(49); // [ var(45) , var(32) ] D[32,50] = (-1)*var(53); // [ var(50) , var(32) ] D[32,54] = (-1)*var(56); // [ var(54) , var(32) ] D[32,59] = (-1)*var(60); // [ var(59) , var(32) ] D[33,34] = (-1)*var(39); // [ var(34) , var(33) ] D[33,37] = var(42); // [ var(37) , var(33) ] D[33,40] = (-1)*var(44); // [ var(40) , var(33) ] D[33,41] = (-1)*var(45); // [ var(41) , var(33) ] D[33,46] = (-1)*var(50); // [ var(46) , var(33) ] D[33,56] = (-1)*var(58); // [ var(56) , var(33) ] D[33,57] = (-1)*var(59); // [ var(57) , var(33) ] D[34,35] = (-1)*var(40); // [ var(35) , var(34) ] D[34,36] = (-1)*var(41); // [ var(36) , var(34) ] D[34,38] = var(43); // [ var(38) , var(34) ] D[34,42] = var(47); // [ var(42) , var(34) ] D[34,50] = (-1)*var(54); // [ var(50) , var(34) ] D[34,53] = (-1)*var(56); // [ var(53) , var(34) ] D[34,55] = (-1)*var(57); // [ var(55) , var(34) ] D[35,39] = var(44); // [ var(39) , var(35) ] D[35,41] = var(46); // [ var(41) , var(35) ] D[35,43] = var(48); // [ var(43) , var(35) ] D[35,45] = var(50); // [ var(45) , var(35) ] D[35,47] = var(51); // [ var(47) , var(35) ] D[35,49] = var(53); // [ var(49) , var(35) ] D[35,52] = var(55); // [ var(52) , var(35) ] D[36,39] = var(45); // [ var(39) , var(36) ] D[36,40] = var(46); // [ var(40) , var(36) ] D[36,43] = var(49); // [ var(43) , var(36) ] D[36,44] = var(50); // [ var(44) , var(36) ] D[36,47] = var(52); // [ var(47) , var(36) ] D[36,48] = var(53); // [ var(48) , var(36) ] D[36,51] = var(55); // [ var(51) , var(36) ] D[37,39] = (-1)*var(47); // [ var(39) , var(37) ] D[37,44] = (-1)*var(51); // [ var(44) , var(37) ] D[37,45] = (-1)*var(52); // [ var(45) , var(37) ] D[37,50] = (-1)*var(55); // [ var(50) , var(37) ] D[37,54] = (-1)*var(57); // [ var(54) , var(37) ] D[37,58] = var(60); // [ var(58) , var(37) ] D[38,40] = (-1)*var(48); // [ var(40) , var(38) ] D[38,41] = (-1)*var(49); // [ var(41) , var(38) ] D[38,46] = (-1)*var(53); // [ var(46) , var(38) ] D[38,54] = var(58); // [ var(54) , var(38) ] D[38,57] = (-1)*var(60); // [ var(57) , var(38) ] D[39,46] = var(54); // [ var(46) , var(39) ] D[39,53] = (-1)*var(58); // [ var(53) , var(39) ] D[39,55] = (-1)*var(59); // [ var(55) , var(39) ] D[40,42] = var(51); // [ var(42) , var(40) ] D[40,45] = var(54); // [ var(45) , var(40) ] D[40,49] = var(56); // [ var(49) , var(40) ] D[40,52] = var(57); // [ var(52) , var(40) ] D[41,42] = var(52); // [ var(42) , var(41) ] D[41,44] = var(54); // [ var(44) , var(41) ] D[41,48] = var(56); // [ var(48) , var(41) ] D[41,51] = var(57); // [ var(51) , var(41) ] D[42,46] = (-1)*var(55); // [ var(46) , var(42) ] D[42,54] = var(59); // [ var(54) , var(42) ] D[42,56] = var(60); // [ var(56) , var(42) ] D[43,46] = var(56); // [ var(46) , var(43) ] D[43,50] = var(58); // [ var(50) , var(43) ] D[43,55] = (-1)*var(60); // [ var(55) , var(43) ] D[44,49] = var(58); // [ var(49) , var(44) ] D[44,52] = var(59); // [ var(52) , var(44) ] D[45,48] = var(58); // [ var(48) , var(45) ] D[45,51] = var(59); // [ var(51) , var(45) ] D[46,47] = (-1)*var(57); // [ var(47) , var(46) ] D[47,50] = var(59); // [ var(50) , var(47) ] D[47,53] = var(60); // [ var(53) , var(47) ] D[48,52] = var(60); // [ var(52) , var(48) ] D[49,51] = var(60); // [ var(51) , var(49) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUso12(); ncAlgebra; setring ncAlgebra; // ... 714 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: f4(Q) has the type: F4, and defined by: proc makeUf4(list #) "USAGE: makeUf4([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(f_4) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(f_4) is derived from the Chevalley representation of f_4, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUe8 EXAMPLE: example makeUf4; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..24),Y(1..24),H(1..4)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,49] = (2)*var(1); // [ var(49) , var(1) ] D[3,49] = (-1)*var(3); // [ var(49) , var(3) ] D[5,49] = var(5); // [ var(49) , var(5) ] D[7,49] = (-1)*var(7); // [ var(49) , var(7) ] D[8,49] = var(8); // [ var(49) , var(8) ] D[9,49] = (-1)*var(9); // [ var(49) , var(9) ] D[10,49] = (-2)*var(10); // [ var(49) , var(10) ] D[11,49] = var(11); // [ var(49) , var(11) ] D[13,49] = (-2)*var(13); // [ var(49) , var(13) ] D[15,49] = (2)*var(15); // [ var(49) , var(15) ] D[16,49] = (-2)*var(16); // [ var(49) , var(16) ] D[18,49] = (2)*var(18); // [ var(49) , var(18) ] D[19,49] = (-1)*var(19); // [ var(49) , var(19) ] D[20,49] = (2)*var(20); // [ var(49) , var(20) ] D[21,49] = var(21); // [ var(49) , var(21) ] D[2,50] = (2)*var(2); // [ var(50) , var(2) ] D[4,50] = (-1)*var(4); // [ var(50) , var(4) ] D[6,50] = var(6); // [ var(50) , var(6) ] D[7,50] = (-1)*var(7); // [ var(50) , var(7) ] D[8,50] = (-1)*var(8); // [ var(50) , var(8) ] D[9,50] = var(9); // [ var(50) , var(9) ] D[10,50] = (-1)*var(10); // [ var(50) , var(10) ] D[11,50] = var(11); // [ var(50) , var(11) ] D[12,50] = (-1)*var(12); // [ var(50) , var(12) ] D[13,50] = var(13); // [ var(50) , var(13) ] D[14,50] = var(14); // [ var(50) , var(14) ] D[15,50] = (-1)*var(15); // [ var(50) , var(15) ] D[18,50] = var(18); // [ var(50) , var(18) ] D[23,50] = (-1)*var(23); // [ var(50) , var(23) ] D[24,50] = var(24); // [ var(50) , var(24) ] D[1,51] = (-1)*var(1); // [ var(51) , var(1) ] D[3,51] = (2)*var(3); // [ var(51) , var(3) ] D[4,51] = (-2)*var(4); // [ var(51) , var(4) ] D[5,51] = var(5); // [ var(51) , var(5) ] D[6,51] = (-2)*var(6); // [ var(51) , var(6) ] D[8,51] = (-1)*var(8); // [ var(51) , var(8) ] D[10,51] = (2)*var(10); // [ var(51) , var(10) ] D[11,51] = (-1)*var(11); // [ var(51) , var(11) ] D[12,51] = var(12); // [ var(51) , var(12) ] D[13,51] = (2)*var(13); // [ var(51) , var(13) ] D[14,51] = var(14); // [ var(51) , var(14) ] D[17,51] = (-1)*var(17); // [ var(51) , var(17) ] D[19,51] = var(19); // [ var(51) , var(19) ] D[20,51] = (-2)*var(20); // [ var(51) , var(20) ] D[22,51] = (2)*var(22); // [ var(51) , var(22) ] D[2,52] = (-1)*var(2); // [ var(52) , var(2) ] D[3,52] = (-1)*var(3); // [ var(52) , var(3) ] D[4,52] = (2)*var(4); // [ var(52) , var(4) ] D[5,52] = (-1)*var(5); // [ var(52) , var(5) ] D[6,52] = var(6); // [ var(52) , var(6) ] D[7,52] = var(7); // [ var(52) , var(7) ] D[8,52] = var(8); // [ var(52) , var(8) ] D[13,52] = (-1)*var(13); // [ var(52) , var(13) ] D[14,52] = (-1)*var(14); // [ var(52) , var(14) ] D[16,52] = var(16); // [ var(52) , var(16) ] D[17,52] = var(17); // [ var(52) , var(17) ] D[18,52] = (-1)*var(18); // [ var(52) , var(18) ] D[20,52] = var(20); // [ var(52) , var(20) ] D[22,52] = (-1)*var(22); // [ var(52) , var(22) ] D[23,52] = var(23); // [ var(52) , var(23) ] // H(i) * Y(j): D[25,49] = (-2)*var(25); // [ var(49) , var(25) ] D[27,49] = var(27); // [ var(49) , var(27) ] D[29,49] = (-1)*var(29); // [ var(49) , var(29) ] D[31,49] = var(31); // [ var(49) , var(31) ] D[32,49] = (-1)*var(32); // [ var(49) , var(32) ] D[33,49] = var(33); // [ var(49) , var(33) ] D[34,49] = (2)*var(34); // [ var(49) , var(34) ] D[35,49] = (-1)*var(35); // [ var(49) , var(35) ] D[37,49] = (2)*var(37); // [ var(49) , var(37) ] D[39,49] = (-2)*var(39); // [ var(49) , var(39) ] D[40,49] = (2)*var(40); // [ var(49) , var(40) ] D[42,49] = (-2)*var(42); // [ var(49) , var(42) ] D[43,49] = var(43); // [ var(49) , var(43) ] D[44,49] = (-2)*var(44); // [ var(49) , var(44) ] D[45,49] = (-1)*var(45); // [ var(49) , var(45) ] D[26,50] = (-2)*var(26); // [ var(50) , var(26) ] D[28,50] = var(28); // [ var(50) , var(28) ] D[30,50] = (-1)*var(30); // [ var(50) , var(30) ] D[31,50] = var(31); // [ var(50) , var(31) ] D[32,50] = var(32); // [ var(50) , var(32) ] D[33,50] = (-1)*var(33); // [ var(50) , var(33) ] D[34,50] = var(34); // [ var(50) , var(34) ] D[35,50] = (-1)*var(35); // [ var(50) , var(35) ] D[36,50] = var(36); // [ var(50) , var(36) ] D[37,50] = (-1)*var(37); // [ var(50) , var(37) ] D[38,50] = (-1)*var(38); // [ var(50) , var(38) ] D[39,50] = var(39); // [ var(50) , var(39) ] D[42,50] = (-1)*var(42); // [ var(50) , var(42) ] D[47,50] = var(47); // [ var(50) , var(47) ] D[48,50] = (-1)*var(48); // [ var(50) , var(48) ] D[25,51] = var(25); // [ var(51) , var(25) ] D[27,51] = (-2)*var(27); // [ var(51) , var(27) ] D[28,51] = (2)*var(28); // [ var(51) , var(28) ] D[29,51] = (-1)*var(29); // [ var(51) , var(29) ] D[30,51] = (2)*var(30); // [ var(51) , var(30) ] D[32,51] = var(32); // [ var(51) , var(32) ] D[34,51] = (-2)*var(34); // [ var(51) , var(34) ] D[35,51] = var(35); // [ var(51) , var(35) ] D[36,51] = (-1)*var(36); // [ var(51) , var(36) ] D[37,51] = (-2)*var(37); // [ var(51) , var(37) ] D[38,51] = (-1)*var(38); // [ var(51) , var(38) ] D[41,51] = var(41); // [ var(51) , var(41) ] D[43,51] = (-1)*var(43); // [ var(51) , var(43) ] D[44,51] = (2)*var(44); // [ var(51) , var(44) ] D[46,51] = (-2)*var(46); // [ var(51) , var(46) ] D[26,52] = var(26); // [ var(52) , var(26) ] D[27,52] = var(27); // [ var(52) , var(27) ] D[28,52] = (-2)*var(28); // [ var(52) , var(28) ] D[29,52] = var(29); // [ var(52) , var(29) ] D[30,52] = (-1)*var(30); // [ var(52) , var(30) ] D[31,52] = (-1)*var(31); // [ var(52) , var(31) ] D[32,52] = (-1)*var(32); // [ var(52) , var(32) ] D[37,52] = var(37); // [ var(52) , var(37) ] D[38,52] = var(38); // [ var(52) , var(38) ] D[40,52] = (-1)*var(40); // [ var(52) , var(40) ] D[41,52] = (-1)*var(41); // [ var(52) , var(41) ] D[42,52] = var(42); // [ var(52) , var(42) ] D[44,52] = (-1)*var(44); // [ var(52) , var(44) ] D[46,52] = var(46); // [ var(52) , var(46) ] D[47,52] = (-1)*var(47); // [ var(52) , var(47) ] // Y(i) * X(j): D[1,25] = (-1)*var(49); // [ var(25) , var(1) ] D[5,25] = (-1)*var(3); // [ var(25) , var(5) ] D[8,25] = (-1)*var(7); // [ var(25) , var(8) ] D[11,25] = (-1)*var(9); // [ var(25) , var(11) ] D[12,25] = (-2)*var(10); // [ var(25) , var(12) ] D[14,25] = (-2)*var(13); // [ var(25) , var(14) ] D[15,25] = (-1)*var(12); // [ var(25) , var(15) ] D[17,25] = (-2)*var(16); // [ var(25) , var(17) ] D[18,25] = (-1)*var(14); // [ var(25) , var(18) ] D[20,25] = (-1)*var(17); // [ var(25) , var(20) ] D[21,25] = (-1)*var(19); // [ var(25) , var(21) ] D[2,26] = (-1)*var(50); // [ var(26) , var(2) ] D[6,26] = (-1)*var(4); // [ var(26) , var(6) ] D[9,26] = (-1)*var(7); // [ var(26) , var(9) ] D[11,26] = (-1)*var(8); // [ var(26) , var(11) ] D[13,26] = (-1)*var(10); // [ var(26) , var(13) ] D[14,26] = (-1)*var(12); // [ var(26) , var(14) ] D[18,26] = (-1)*var(15); // [ var(26) , var(18) ] D[24,26] = var(23); // [ var(26) , var(24) ] D[3,27] = (-1)*var(51); // [ var(27) , var(3) ] D[5,27] = var(1); // [ var(27) , var(5) ] D[7,27] = (-2)*var(4); // [ var(27) , var(7) ] D[9,27] = (-2)*var(6); // [ var(27) , var(9) ] D[10,27] = (-1)*var(7); // [ var(27) , var(10) ] D[12,27] = (-1)*var(8); // [ var(27) , var(12) ] D[13,27] = (-1)*var(9); // [ var(27) , var(13) ] D[14,27] = (-1)*var(11); // [ var(27) , var(14) ] D[19,27] = (-1)*var(17); // [ var(27) , var(19) ] D[21,27] = (-2)*var(20); // [ var(27) , var(21) ] D[22,27] = (-1)*var(21); // [ var(27) , var(22) ] D[4,28] = (-1)*var(52); // [ var(28) , var(4) ] D[6,28] = var(2); // [ var(28) , var(6) ] D[7,28] = var(3); // [ var(28) , var(7) ] D[8,28] = var(5); // [ var(28) , var(8) ] D[16,28] = (-1)*var(13); // [ var(28) , var(16) ] D[17,28] = (-1)*var(14); // [ var(28) , var(17) ] D[20,28] = (-1)*var(18); // [ var(28) , var(20) ] D[23,28] = var(22); // [ var(28) , var(23) ] D[1,29] = (-1)*var(27); // [ var(29) , var(1) ] D[3,29] = var(25); // [ var(29) , var(3) ] D[5,29] = (-1)*var(49)+(-1)*var(51); // [ var(29) , var(5) ] D[8,29] = (-2)*var(4); // [ var(29) , var(8) ] D[11,29] = (-2)*var(6); // [ var(29) , var(11) ] D[12,29] = (-1)*var(7); // [ var(29) , var(12) ] D[14,29] = (-1)*var(9); // [ var(29) , var(14) ] D[15,29] = (-1)*var(8); // [ var(29) , var(15) ] D[18,29] = (-1)*var(11); // [ var(29) , var(18) ] D[19,29] = (2)*var(16); // [ var(29) , var(19) ] D[21,29] = var(17); // [ var(29) , var(21) ] D[22,29] = var(19); // [ var(29) , var(22) ] D[2,30] = (-1)*var(28); // [ var(30) , var(2) ] D[4,30] = var(26); // [ var(30) , var(4) ] D[6,30] = (-1)*var(50)+(-1)*var(52); // [ var(30) , var(6) ] D[9,30] = var(3); // [ var(30) , var(9) ] D[11,30] = var(5); // [ var(30) , var(11) ] D[16,30] = var(10); // [ var(30) , var(16) ] D[17,30] = var(12); // [ var(30) , var(17) ] D[20,30] = var(15); // [ var(30) , var(20) ] D[24,30] = (-1)*var(22); // [ var(30) , var(24) ] D[3,31] = (-2)*var(28); // [ var(31) , var(3) ] D[4,31] = var(27); // [ var(31) , var(4) ] D[7,31] = (-1)*var(51)+(-2)*var(52); // [ var(31) , var(7) ] D[8,31] = var(1); // [ var(31) , var(8) ] D[9,31] = (2)*var(2); // [ var(31) , var(9) ] D[10,31] = var(3); // [ var(31) , var(10) ] D[12,31] = var(5); // [ var(31) , var(12) ] D[16,31] = var(9); // [ var(31) , var(16) ] D[17,31] = var(11); // [ var(31) , var(17) ] D[19,31] = (-1)*var(14); // [ var(31) , var(19) ] D[21,31] = (-2)*var(18); // [ var(31) , var(21) ] D[23,31] = (-1)*var(21); // [ var(31) , var(23) ] D[1,32] = (-1)*var(31); // [ var(32) , var(1) ] D[4,32] = var(29); // [ var(32) , var(4) ] D[5,32] = (-2)*var(28); // [ var(32) , var(5) ] D[7,32] = var(25); // [ var(32) , var(7) ] D[8,32] = (-1)*var(49)+(-1)*var(51)+(-2)*var(52); // [ var(32) , var(8) ] D[11,32] = (2)*var(2); // [ var(32) , var(11) ] D[12,32] = var(3); // [ var(32) , var(12) ] D[15,32] = var(5); // [ var(32) , var(15) ] D[17,32] = var(9); // [ var(32) , var(17) ] D[19,32] = (2)*var(13); // [ var(32) , var(19) ] D[20,32] = var(11); // [ var(32) , var(20) ] D[21,32] = var(14); // [ var(32) , var(21) ] D[23,32] = var(19); // [ var(32) , var(23) ] D[2,33] = (-1)*var(31); // [ var(33) , var(2) ] D[3,33] = (-2)*var(30); // [ var(33) , var(3) ] D[6,33] = var(27); // [ var(33) , var(6) ] D[7,33] = (2)*var(26); // [ var(33) , var(7) ] D[9,33] = (-2)*var(50)+(-1)*var(51)+(-2)*var(52); // [ var(33) , var(9) ] D[11,33] = var(1); // [ var(33) , var(11) ] D[13,33] = var(3); // [ var(33) , var(13) ] D[14,33] = var(5); // [ var(33) , var(14) ] D[16,33] = (-1)*var(7); // [ var(33) , var(16) ] D[17,33] = (-1)*var(8); // [ var(33) , var(17) ] D[19,33] = var(12); // [ var(33) , var(19) ] D[21,33] = (2)*var(15); // [ var(33) , var(21) ] D[24,33] = var(21); // [ var(33) , var(24) ] D[3,34] = (-1)*var(31); // [ var(34) , var(3) ] D[7,34] = var(27); // [ var(34) , var(7) ] D[10,34] = (-1)*var(51)+(-1)*var(52); // [ var(34) , var(10) ] D[12,34] = var(1); // [ var(34) , var(12) ] D[13,34] = var(2); // [ var(34) , var(13) ] D[16,34] = (-1)*var(6); // [ var(34) , var(16) ] D[19,34] = var(11); // [ var(34) , var(19) ] D[22,34] = (-1)*var(18); // [ var(34) , var(22) ] D[23,34] = var(20); // [ var(34) , var(23) ] D[1,35] = (-1)*var(33); // [ var(35) , var(1) ] D[2,35] = (-1)*var(32); // [ var(35) , var(2) ] D[5,35] = (-2)*var(30); // [ var(35) , var(5) ] D[6,35] = var(29); // [ var(35) , var(6) ] D[8,35] = (2)*var(26); // [ var(35) , var(8) ] D[9,35] = var(25); // [ var(35) , var(9) ] D[11,35] = (-1)*var(49)+(-2)*var(50)+(-1)*var(51)+(-2)*var(52); // [ var(35) , var(11) ] D[14,35] = var(3); // [ var(35) , var(14) ] D[17,35] = (-1)*var(7); // [ var(35) , var(17) ] D[18,35] = var(5); // [ var(35) , var(18) ] D[19,35] = (-2)*var(10); // [ var(35) , var(19) ] D[20,35] = (-1)*var(8); // [ var(35) , var(20) ] D[21,35] = (-1)*var(12); // [ var(35) , var(21) ] D[24,35] = (-1)*var(19); // [ var(35) , var(24) ] D[1,36] = (-2)*var(34); // [ var(36) , var(1) ] D[3,36] = (-1)*var(32); // [ var(36) , var(3) ] D[5,36] = (-1)*var(31); // [ var(36) , var(5) ] D[7,36] = var(29); // [ var(36) , var(7) ] D[8,36] = var(27); // [ var(36) , var(8) ] D[10,36] = var(25); // [ var(36) , var(10) ] D[12,36] = (-1)*var(49)+(-2)*var(51)+(-2)*var(52); // [ var(36) , var(12) ] D[14,36] = (2)*var(2); // [ var(36) , var(14) ] D[15,36] = var(1); // [ var(36) , var(15) ] D[17,36] = (-2)*var(6); // [ var(36) , var(17) ] D[19,36] = (-1)*var(9); // [ var(36) , var(19) ] D[21,36] = var(11); // [ var(36) , var(21) ] D[22,36] = var(14); // [ var(36) , var(22) ] D[23,36] = (-1)*var(17); // [ var(36) , var(23) ] D[2,37] = (-1)*var(34); // [ var(37) , var(2) ] D[3,37] = (-1)*var(33); // [ var(37) , var(3) ] D[9,37] = var(27); // [ var(37) , var(9) ] D[10,37] = var(26); // [ var(37) , var(10) ] D[13,37] = (-1)*var(50)+(-1)*var(51)+(-1)*var(52); // [ var(37) , var(13) ] D[14,37] = var(1); // [ var(37) , var(14) ] D[16,37] = var(4); // [ var(37) , var(16) ] D[19,37] = (-1)*var(8); // [ var(37) , var(19) ] D[22,37] = var(15); // [ var(37) , var(22) ] D[24,37] = (-1)*var(20); // [ var(37) , var(24) ] D[1,38] = (-2)*var(37); // [ var(38) , var(1) ] D[2,38] = (-1)*var(36); // [ var(38) , var(2) ] D[3,38] = (-1)*var(35); // [ var(38) , var(3) ] D[5,38] = (-1)*var(33); // [ var(38) , var(5) ] D[9,38] = var(29); // [ var(38) , var(9) ] D[11,38] = var(27); // [ var(38) , var(11) ] D[12,38] = (2)*var(26); // [ var(38) , var(12) ] D[13,38] = var(25); // [ var(38) , var(13) ] D[14,38] = (-1)*var(49)+(-2)*var(50)+(-2)*var(51)+(-2)*var(52); // [ var(38) , var(14) ] D[17,38] = (2)*var(4); // [ var(38) , var(17) ] D[18,38] = var(1); // [ var(38) , var(18) ] D[19,38] = var(7); // [ var(38) , var(19) ] D[21,38] = (-1)*var(8); // [ var(38) , var(21) ] D[22,38] = (-1)*var(12); // [ var(38) , var(22) ] D[24,38] = var(17); // [ var(38) , var(24) ] D[1,39] = (-1)*var(36); // [ var(39) , var(1) ] D[5,39] = (-1)*var(32); // [ var(39) , var(5) ] D[8,39] = var(29); // [ var(39) , var(8) ] D[12,39] = var(25); // [ var(39) , var(12) ] D[15,39] = (-1)*var(49)+(-1)*var(51)+(-1)*var(52); // [ var(39) , var(15) ] D[18,39] = var(2); // [ var(39) , var(18) ] D[20,39] = (-1)*var(6); // [ var(39) , var(20) ] D[21,39] = (-1)*var(9); // [ var(39) , var(21) ] D[22,39] = (-1)*var(13); // [ var(39) , var(22) ] D[23,39] = var(16); // [ var(39) , var(23) ] D[4,40] = (-1)*var(37); // [ var(40) , var(4) ] D[6,40] = var(34); // [ var(40) , var(6) ] D[7,40] = var(33); // [ var(40) , var(7) ] D[9,40] = (-1)*var(31); // [ var(40) , var(9) ] D[10,40] = (-1)*var(30); // [ var(40) , var(10) ] D[13,40] = var(28); // [ var(40) , var(13) ] D[16,40] = (-1)*var(50)+(-1)*var(51)+(-2)*var(52); // [ var(40) , var(16) ] D[17,40] = var(1); // [ var(40) , var(17) ] D[19,40] = (-1)*var(5); // [ var(40) , var(19) ] D[23,40] = (-1)*var(15); // [ var(40) , var(23) ] D[24,40] = var(18); // [ var(40) , var(24) ] D[1,41] = (-2)*var(40); // [ var(41) , var(1) ] D[4,41] = (-1)*var(38); // [ var(41) , var(4) ] D[6,41] = var(36); // [ var(41) , var(6) ] D[7,41] = var(35); // [ var(41) , var(7) ] D[8,41] = var(33); // [ var(41) , var(8) ] D[9,41] = (-1)*var(32); // [ var(41) , var(9) ] D[11,41] = (-1)*var(31); // [ var(41) , var(11) ] D[12,41] = (-2)*var(30); // [ var(41) , var(12) ] D[14,41] = (2)*var(28); // [ var(41) , var(14) ] D[16,41] = var(25); // [ var(41) , var(16) ] D[17,41] = (-1)*var(49)+(-2)*var(50)+(-2)*var(51)+(-4)*var(52); // [ var(41) , var(17) ] D[19,41] = var(3); // [ var(41) , var(19) ] D[20,41] = var(1); // [ var(41) , var(20) ] D[21,41] = (-1)*var(5); // [ var(41) , var(21) ] D[23,41] = var(12); // [ var(41) , var(23) ] D[24,41] = (-1)*var(14); // [ var(41) , var(24) ] D[1,42] = (-1)*var(38); // [ var(42) , var(1) ] D[2,42] = (-1)*var(39); // [ var(42) , var(2) ] D[5,42] = (-1)*var(35); // [ var(42) , var(5) ] D[11,42] = var(29); // [ var(42) , var(11) ] D[14,42] = var(25); // [ var(42) , var(14) ] D[15,42] = var(26); // [ var(42) , var(15) ] D[18,42] = (-1)*var(49)+(-1)*var(50)+(-1)*var(51)+(-1)*var(52); // [ var(42) , var(18) ] D[20,42] = var(4); // [ var(42) , var(20) ] D[21,42] = var(7); // [ var(42) , var(21) ] D[22,42] = var(10); // [ var(42) , var(22) ] D[24,42] = (-1)*var(16); // [ var(42) , var(24) ] D[3,43] = (-1)*var(41); // [ var(43) , var(3) ] D[5,43] = (2)*var(40); // [ var(43) , var(5) ] D[7,43] = (-1)*var(38); // [ var(43) , var(7) ] D[8,43] = (2)*var(37); // [ var(43) , var(8) ] D[9,43] = var(36); // [ var(43) , var(9) ] D[10,43] = var(35); // [ var(43) , var(10) ] D[11,43] = (-2)*var(34); // [ var(43) , var(11) ] D[12,43] = (-1)*var(33); // [ var(43) , var(12) ] D[13,43] = (-1)*var(32); // [ var(43) , var(13) ] D[14,43] = var(31); // [ var(43) , var(14) ] D[16,43] = (-1)*var(29); // [ var(43) , var(16) ] D[17,43] = var(27); // [ var(43) , var(17) ] D[19,43] = (-1)*var(49)+(-2)*var(50)+(-3)*var(51)+(-4)*var(52); // [ var(43) , var(19) ] D[21,43] = var(1); // [ var(43) , var(21) ] D[22,43] = (-1)*var(5); // [ var(43) , var(22) ] D[23,43] = (-1)*var(8); // [ var(43) , var(23) ] D[24,43] = var(11); // [ var(43) , var(24) ] D[1,44] = (-1)*var(41); // [ var(44) , var(1) ] D[4,44] = (-1)*var(42); // [ var(44) , var(4) ] D[6,44] = var(39); // [ var(44) , var(6) ] D[8,44] = var(35); // [ var(44) , var(8) ] D[11,44] = (-1)*var(32); // [ var(44) , var(11) ] D[15,44] = (-1)*var(30); // [ var(44) , var(15) ] D[17,44] = var(25); // [ var(44) , var(17) ] D[18,44] = var(28); // [ var(44) , var(18) ] D[20,44] = (-1)*var(49)+(-1)*var(50)+(-1)*var(51)+(-2)*var(52); // [ var(44) , var(20) ] D[21,44] = var(3); // [ var(44) , var(21) ] D[23,44] = (-1)*var(10); // [ var(44) , var(23) ] D[24,44] = var(13); // [ var(44) , var(24) ] D[1,45] = (-1)*var(43); // [ var(45) , var(1) ] D[3,45] = (-2)*var(44); // [ var(45) , var(3) ] D[5,45] = var(41); // [ var(45) , var(5) ] D[7,45] = (-2)*var(42); // [ var(45) , var(7) ] D[8,45] = var(38); // [ var(45) , var(8) ] D[9,45] = (2)*var(39); // [ var(45) , var(9) ] D[11,45] = (-1)*var(36); // [ var(45) , var(11) ] D[12,45] = var(35); // [ var(45) , var(12) ] D[14,45] = (-1)*var(32); // [ var(45) , var(14) ] D[15,45] = (-1)*var(33); // [ var(45) , var(15) ] D[17,45] = (-1)*var(29); // [ var(45) , var(17) ] D[18,45] = var(31); // [ var(45) , var(18) ] D[19,45] = var(25); // [ var(45) , var(19) ] D[20,45] = var(27); // [ var(45) , var(20) ] D[21,45] = (-2)*var(49)+(-2)*var(50)+(-3)*var(51)+(-4)*var(52); // [ var(45) , var(21) ] D[22,45] = var(3); // [ var(45) , var(22) ] D[23,45] = var(7); // [ var(45) , var(23) ] D[24,45] = (-1)*var(9); // [ var(45) , var(24) ] D[3,46] = (-1)*var(45); // [ var(46) , var(3) ] D[5,46] = var(43); // [ var(46) , var(5) ] D[10,46] = (-1)*var(42); // [ var(46) , var(10) ] D[12,46] = var(38); // [ var(46) , var(12) ] D[13,46] = var(39); // [ var(46) , var(13) ] D[14,46] = (-1)*var(36); // [ var(46) , var(14) ] D[15,46] = (-1)*var(37); // [ var(46) , var(15) ] D[18,46] = var(34); // [ var(46) , var(18) ] D[19,46] = (-1)*var(29); // [ var(46) , var(19) ] D[21,46] = var(27); // [ var(46) , var(21) ] D[22,46] = (-1)*var(49)+(-1)*var(50)+(-2)*var(51)+(-2)*var(52); // [ var(46) , var(22) ] D[23,46] = (-1)*var(4); // [ var(46) , var(23) ] D[24,46] = var(6); // [ var(46) , var(24) ] D[4,47] = var(46); // [ var(47) , var(4) ] D[7,47] = (-1)*var(45); // [ var(47) , var(7) ] D[8,47] = var(43); // [ var(47) , var(8) ] D[10,47] = var(44); // [ var(47) , var(10) ] D[12,47] = (-1)*var(41); // [ var(47) , var(12) ] D[15,47] = var(40); // [ var(47) , var(15) ] D[16,47] = (-1)*var(39); // [ var(47) , var(16) ] D[17,47] = var(36); // [ var(47) , var(17) ] D[19,47] = (-1)*var(32); // [ var(47) , var(19) ] D[20,47] = (-1)*var(34); // [ var(47) , var(20) ] D[21,47] = var(31); // [ var(47) , var(21) ] D[22,47] = (-1)*var(28); // [ var(47) , var(22) ] D[23,47] = (-1)*var(49)+(-1)*var(50)+(-2)*var(51)+(-3)*var(52); // [ var(47) , var(23) ] D[24,47] = (-1)*var(2); // [ var(47) , var(24) ] D[2,48] = var(47); // [ var(48) , var(2) ] D[6,48] = (-1)*var(46); // [ var(48) , var(6) ] D[9,48] = var(45); // [ var(48) , var(9) ] D[11,48] = (-1)*var(43); // [ var(48) , var(11) ] D[13,48] = (-1)*var(44); // [ var(48) , var(13) ] D[14,48] = var(41); // [ var(48) , var(14) ] D[16,48] = var(42); // [ var(48) , var(16) ] D[17,48] = (-1)*var(38); // [ var(48) , var(17) ] D[18,48] = (-1)*var(40); // [ var(48) , var(18) ] D[19,48] = var(35); // [ var(48) , var(19) ] D[20,48] = var(37); // [ var(48) , var(20) ] D[21,48] = (-1)*var(33); // [ var(48) , var(21) ] D[22,48] = var(30); // [ var(48) , var(22) ] D[23,48] = (-1)*var(26); // [ var(48) , var(23) ] D[24,48] = (-1)*var(49)+(-2)*var(50)+(-2)*var(51)+(-3)*var(52); // [ var(48) , var(24) ] // X(i) * X(j): D[1,3] = var(5); // [ var(3) , var(1) ] D[1,7] = var(8); // [ var(7) , var(1) ] D[1,9] = var(11); // [ var(9) , var(1) ] D[1,10] = var(12); // [ var(10) , var(1) ] D[1,12] = (2)*var(15); // [ var(12) , var(1) ] D[1,13] = var(14); // [ var(13) , var(1) ] D[1,14] = (2)*var(18); // [ var(14) , var(1) ] D[1,16] = var(17); // [ var(16) , var(1) ] D[1,17] = (2)*var(20); // [ var(17) , var(1) ] D[1,19] = var(21); // [ var(19) , var(1) ] D[2,4] = var(6); // [ var(4) , var(2) ] D[2,7] = var(9); // [ var(7) , var(2) ] D[2,8] = var(11); // [ var(8) , var(2) ] D[2,10] = var(13); // [ var(10) , var(2) ] D[2,12] = var(14); // [ var(12) , var(2) ] D[2,15] = var(18); // [ var(15) , var(2) ] D[2,23] = (-1)*var(24); // [ var(23) , var(2) ] D[3,4] = var(7); // [ var(4) , var(3) ] D[3,6] = var(9); // [ var(6) , var(3) ] D[3,7] = (2)*var(10); // [ var(7) , var(3) ] D[3,8] = var(12); // [ var(8) , var(3) ] D[3,9] = (2)*var(13); // [ var(9) , var(3) ] D[3,11] = var(14); // [ var(11) , var(3) ] D[3,17] = var(19); // [ var(17) , var(3) ] D[3,20] = var(21); // [ var(20) , var(3) ] D[3,21] = (2)*var(22); // [ var(21) , var(3) ] D[4,5] = (-1)*var(8); // [ var(5) , var(4) ] D[4,13] = var(16); // [ var(13) , var(4) ] D[4,14] = var(17); // [ var(14) , var(4) ] D[4,18] = var(20); // [ var(18) , var(4) ] D[4,22] = (-1)*var(23); // [ var(22) , var(4) ] D[5,6] = var(11); // [ var(6) , var(5) ] D[5,7] = var(12); // [ var(7) , var(5) ] D[5,8] = (2)*var(15); // [ var(8) , var(5) ] D[5,9] = var(14); // [ var(9) , var(5) ] D[5,11] = (2)*var(18); // [ var(11) , var(5) ] D[5,16] = (-1)*var(19); // [ var(16) , var(5) ] D[5,17] = (-1)*var(21); // [ var(17) , var(5) ] D[5,19] = (-2)*var(22); // [ var(19) , var(5) ] D[6,10] = (-1)*var(16); // [ var(10) , var(6) ] D[6,12] = (-1)*var(17); // [ var(12) , var(6) ] D[6,15] = (-1)*var(20); // [ var(15) , var(6) ] D[6,22] = var(24); // [ var(22) , var(6) ] D[7,9] = (-2)*var(16); // [ var(9) , var(7) ] D[7,11] = (-1)*var(17); // [ var(11) , var(7) ] D[7,14] = var(19); // [ var(14) , var(7) ] D[7,18] = var(21); // [ var(18) , var(7) ] D[7,21] = (2)*var(23); // [ var(21) , var(7) ] D[8,9] = (-1)*var(17); // [ var(9) , var(8) ] D[8,11] = (-2)*var(20); // [ var(11) , var(8) ] D[8,13] = (-1)*var(19); // [ var(13) , var(8) ] D[8,14] = (-1)*var(21); // [ var(14) , var(8) ] D[8,19] = (-2)*var(23); // [ var(19) , var(8) ] D[9,12] = (-1)*var(19); // [ var(12) , var(9) ] D[9,15] = (-1)*var(21); // [ var(15) , var(9) ] D[9,21] = (-2)*var(24); // [ var(21) , var(9) ] D[10,11] = (-1)*var(19); // [ var(11) , var(10) ] D[10,18] = var(22); // [ var(18) , var(10) ] D[10,20] = (-1)*var(23); // [ var(20) , var(10) ] D[11,12] = var(21); // [ var(12) , var(11) ] D[11,19] = (2)*var(24); // [ var(19) , var(11) ] D[12,14] = (-2)*var(22); // [ var(14) , var(12) ] D[12,17] = (2)*var(23); // [ var(17) , var(12) ] D[13,15] = (-1)*var(22); // [ var(15) , var(13) ] D[13,20] = var(24); // [ var(20) , var(13) ] D[14,17] = (-2)*var(24); // [ var(17) , var(14) ] D[15,16] = (-1)*var(23); // [ var(16) , var(15) ] D[16,18] = (-1)*var(24); // [ var(18) , var(16) ] // Y(i) * Y(j): D[25,27] = (-1)*var(29); // [ var(27) , var(25) ] D[25,31] = (-1)*var(32); // [ var(31) , var(25) ] D[25,33] = (-1)*var(35); // [ var(33) , var(25) ] D[25,34] = (-1)*var(36); // [ var(34) , var(25) ] D[25,36] = (-2)*var(39); // [ var(36) , var(25) ] D[25,37] = (-1)*var(38); // [ var(37) , var(25) ] D[25,38] = (-2)*var(42); // [ var(38) , var(25) ] D[25,40] = (-1)*var(41); // [ var(40) , var(25) ] D[25,41] = (-2)*var(44); // [ var(41) , var(25) ] D[25,43] = (-1)*var(45); // [ var(43) , var(25) ] D[26,28] = (-1)*var(30); // [ var(28) , var(26) ] D[26,31] = (-1)*var(33); // [ var(31) , var(26) ] D[26,32] = (-1)*var(35); // [ var(32) , var(26) ] D[26,34] = (-1)*var(37); // [ var(34) , var(26) ] D[26,36] = (-1)*var(38); // [ var(36) , var(26) ] D[26,39] = (-1)*var(42); // [ var(39) , var(26) ] D[26,47] = var(48); // [ var(47) , var(26) ] D[27,28] = (-1)*var(31); // [ var(28) , var(27) ] D[27,30] = (-1)*var(33); // [ var(30) , var(27) ] D[27,31] = (-2)*var(34); // [ var(31) , var(27) ] D[27,32] = (-1)*var(36); // [ var(32) , var(27) ] D[27,33] = (-2)*var(37); // [ var(33) , var(27) ] D[27,35] = (-1)*var(38); // [ var(35) , var(27) ] D[27,41] = (-1)*var(43); // [ var(41) , var(27) ] D[27,44] = (-1)*var(45); // [ var(44) , var(27) ] D[27,45] = (-2)*var(46); // [ var(45) , var(27) ] D[28,29] = var(32); // [ var(29) , var(28) ] D[28,37] = (-1)*var(40); // [ var(37) , var(28) ] D[28,38] = (-1)*var(41); // [ var(38) , var(28) ] D[28,42] = (-1)*var(44); // [ var(42) , var(28) ] D[28,46] = var(47); // [ var(46) , var(28) ] D[29,30] = (-1)*var(35); // [ var(30) , var(29) ] D[29,31] = (-1)*var(36); // [ var(31) , var(29) ] D[29,32] = (-2)*var(39); // [ var(32) , var(29) ] D[29,33] = (-1)*var(38); // [ var(33) , var(29) ] D[29,35] = (-2)*var(42); // [ var(35) , var(29) ] D[29,40] = var(43); // [ var(40) , var(29) ] D[29,41] = var(45); // [ var(41) , var(29) ] D[29,43] = (2)*var(46); // [ var(43) , var(29) ] D[30,34] = var(40); // [ var(34) , var(30) ] D[30,36] = var(41); // [ var(36) , var(30) ] D[30,39] = var(44); // [ var(39) , var(30) ] D[30,46] = (-1)*var(48); // [ var(46) , var(30) ] D[31,33] = (2)*var(40); // [ var(33) , var(31) ] D[31,35] = var(41); // [ var(35) , var(31) ] D[31,38] = (-1)*var(43); // [ var(38) , var(31) ] D[31,42] = (-1)*var(45); // [ var(42) , var(31) ] D[31,45] = (-2)*var(47); // [ var(45) , var(31) ] D[32,33] = var(41); // [ var(33) , var(32) ] D[32,35] = (2)*var(44); // [ var(35) , var(32) ] D[32,37] = var(43); // [ var(37) , var(32) ] D[32,38] = var(45); // [ var(38) , var(32) ] D[32,43] = (2)*var(47); // [ var(43) , var(32) ] D[33,36] = var(43); // [ var(36) , var(33) ] D[33,39] = var(45); // [ var(39) , var(33) ] D[33,45] = (2)*var(48); // [ var(45) , var(33) ] D[34,35] = var(43); // [ var(35) , var(34) ] D[34,42] = (-1)*var(46); // [ var(42) , var(34) ] D[34,44] = var(47); // [ var(44) , var(34) ] D[35,36] = (-1)*var(45); // [ var(36) , var(35) ] D[35,43] = (-2)*var(48); // [ var(43) , var(35) ] D[36,38] = (2)*var(46); // [ var(38) , var(36) ] D[36,41] = (-2)*var(47); // [ var(41) , var(36) ] D[37,39] = var(46); // [ var(39) , var(37) ] D[37,44] = (-1)*var(48); // [ var(44) , var(37) ] D[38,41] = (2)*var(48); // [ var(41) , var(38) ] D[39,40] = var(47); // [ var(40) , var(39) ] D[40,42] = var(48); // [ var(42) , var(40) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUf4(); ncAlgebra; setring ncAlgebra; // ... 552 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: e6(Q) has the type: E6, and defined by: proc makeUe6(list #) "USAGE: makeUe6([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(e_6) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(e_6) is derived from the Chevalley representation of e_6, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUe6; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..36),Y(1..36),H(1..6)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,73] = (2)*var(1); // [ var(73) , var(1) ] D[3,73] = (-1)*var(3); // [ var(73) , var(3) ] D[7,73] = var(7); // [ var(73) , var(7) ] D[9,73] = (-1)*var(9); // [ var(73) , var(9) ] D[12,73] = var(12); // [ var(73) , var(12) ] D[13,73] = (-1)*var(13); // [ var(73) , var(13) ] D[15,73] = (-1)*var(15); // [ var(73) , var(15) ] D[17,73] = var(17); // [ var(73) , var(17) ] D[18,73] = var(18); // [ var(73) , var(18) ] D[19,73] = (-1)*var(19); // [ var(73) , var(19) ] D[21,73] = (-1)*var(21); // [ var(73) , var(21) ] D[22,73] = var(22); // [ var(73) , var(22) ] D[23,73] = var(23); // [ var(73) , var(23) ] D[24,73] = (-1)*var(24); // [ var(73) , var(24) ] D[25,73] = (-1)*var(25); // [ var(73) , var(25) ] D[26,73] = var(26); // [ var(73) , var(26) ] D[27,73] = var(27); // [ var(73) , var(27) ] D[28,73] = (-1)*var(28); // [ var(73) , var(28) ] D[30,73] = var(30); // [ var(73) , var(30) ] D[31,73] = (-1)*var(31); // [ var(73) , var(31) ] D[33,73] = var(33); // [ var(73) , var(33) ] D[2,74] = (2)*var(2); // [ var(74) , var(2) ] D[4,74] = (-1)*var(4); // [ var(74) , var(4) ] D[8,74] = var(8); // [ var(74) , var(8) ] D[9,74] = (-1)*var(9); // [ var(74) , var(9) ] D[10,74] = (-1)*var(10); // [ var(74) , var(10) ] D[12,74] = (-1)*var(12); // [ var(74) , var(12) ] D[13,74] = var(13); // [ var(74) , var(13) ] D[14,74] = var(14); // [ var(74) , var(14) ] D[15,74] = (-1)*var(15); // [ var(74) , var(15) ] D[16,74] = (-1)*var(16); // [ var(74) , var(16) ] D[17,74] = var(17); // [ var(74) , var(17) ] D[18,74] = (-1)*var(18); // [ var(74) , var(18) ] D[19,74] = var(19); // [ var(74) , var(19) ] D[20,74] = var(20); // [ var(74) , var(20) ] D[21,74] = (-1)*var(21); // [ var(74) , var(21) ] D[22,74] = var(22); // [ var(74) , var(22) ] D[23,74] = (-1)*var(23); // [ var(74) , var(23) ] D[25,74] = var(25); // [ var(74) , var(25) ] D[27,74] = var(27); // [ var(74) , var(27) ] D[35,74] = (-1)*var(35); // [ var(74) , var(35) ] D[36,74] = var(36); // [ var(74) , var(36) ] D[1,75] = (-1)*var(1); // [ var(75) , var(1) ] D[3,75] = (2)*var(3); // [ var(75) , var(3) ] D[4,75] = (-1)*var(4); // [ var(75) , var(4) ] D[7,75] = var(7); // [ var(75) , var(7) ] D[8,75] = (-1)*var(8); // [ var(75) , var(8) ] D[9,75] = var(9); // [ var(75) , var(9) ] D[10,75] = (-1)*var(10); // [ var(75) , var(10) ] D[13,75] = var(13); // [ var(75) , var(13) ] D[14,75] = (-1)*var(14); // [ var(75) , var(14) ] D[15,75] = var(15); // [ var(75) , var(15) ] D[16,75] = (-1)*var(16); // [ var(75) , var(16) ] D[19,75] = var(19); // [ var(75) , var(19) ] D[20,75] = (-1)*var(20); // [ var(75) , var(20) ] D[21,75] = var(21); // [ var(75) , var(21) ] D[25,75] = var(25); // [ var(75) , var(25) ] D[26,75] = (-1)*var(26); // [ var(75) , var(26) ] D[29,75] = var(29); // [ var(75) , var(29) ] D[30,75] = (-1)*var(30); // [ var(75) , var(30) ] D[32,75] = var(32); // [ var(75) , var(32) ] D[33,75] = (-1)*var(33); // [ var(75) , var(33) ] D[34,75] = var(34); // [ var(75) , var(34) ] D[2,76] = (-1)*var(2); // [ var(76) , var(2) ] D[3,76] = (-1)*var(3); // [ var(76) , var(3) ] D[4,76] = (2)*var(4); // [ var(76) , var(4) ] D[5,76] = (-1)*var(5); // [ var(76) , var(5) ] D[7,76] = (-1)*var(7); // [ var(76) , var(7) ] D[8,76] = var(8); // [ var(76) , var(8) ] D[9,76] = var(9); // [ var(76) , var(9) ] D[10,76] = var(10); // [ var(76) , var(10) ] D[11,76] = (-1)*var(11); // [ var(76) , var(11) ] D[12,76] = var(12); // [ var(76) , var(12) ] D[16,76] = var(16); // [ var(76) , var(16) ] D[19,76] = (-1)*var(19); // [ var(76) , var(19) ] D[22,76] = (-1)*var(22); // [ var(76) , var(22) ] D[24,76] = var(24); // [ var(76) , var(24) ] D[25,76] = (-1)*var(25); // [ var(76) , var(25) ] D[26,76] = var(26); // [ var(76) , var(26) ] D[27,76] = (-1)*var(27); // [ var(76) , var(27) ] D[28,76] = var(28); // [ var(76) , var(28) ] D[30,76] = var(30); // [ var(76) , var(30) ] D[34,76] = (-1)*var(34); // [ var(76) , var(34) ] D[35,76] = var(35); // [ var(76) , var(35) ] D[4,77] = (-1)*var(4); // [ var(77) , var(4) ] D[5,77] = (2)*var(5); // [ var(77) , var(5) ] D[6,77] = (-1)*var(6); // [ var(77) , var(6) ] D[8,77] = (-1)*var(8); // [ var(77) , var(8) ] D[9,77] = (-1)*var(9); // [ var(77) , var(9) ] D[10,77] = var(10); // [ var(77) , var(10) ] D[11,77] = var(11); // [ var(77) , var(11) ] D[12,77] = (-1)*var(12); // [ var(77) , var(12) ] D[13,77] = (-1)*var(13); // [ var(77) , var(13) ] D[14,77] = var(14); // [ var(77) , var(14) ] D[15,77] = var(15); // [ var(77) , var(15) ] D[17,77] = (-1)*var(17); // [ var(77) , var(17) ] D[18,77] = var(18); // [ var(77) , var(18) ] D[19,77] = var(19); // [ var(77) , var(19) ] D[22,77] = var(22); // [ var(77) , var(22) ] D[28,77] = (-1)*var(28); // [ var(77) , var(28) ] D[30,77] = (-1)*var(30); // [ var(77) , var(30) ] D[31,77] = var(31); // [ var(77) , var(31) ] D[32,77] = (-1)*var(32); // [ var(77) , var(32) ] D[33,77] = var(33); // [ var(77) , var(33) ] D[34,77] = var(34); // [ var(77) , var(34) ] D[5,78] = (-1)*var(5); // [ var(78) , var(5) ] D[6,78] = (2)*var(6); // [ var(78) , var(6) ] D[10,78] = (-1)*var(10); // [ var(78) , var(10) ] D[11,78] = var(11); // [ var(78) , var(11) ] D[14,78] = (-1)*var(14); // [ var(78) , var(14) ] D[15,78] = (-1)*var(15); // [ var(78) , var(15) ] D[16,78] = var(16); // [ var(78) , var(16) ] D[18,78] = (-1)*var(18); // [ var(78) , var(18) ] D[19,78] = (-1)*var(19); // [ var(78) , var(19) ] D[20,78] = var(20); // [ var(78) , var(20) ] D[21,78] = var(21); // [ var(78) , var(21) ] D[22,78] = (-1)*var(22); // [ var(78) , var(22) ] D[23,78] = var(23); // [ var(78) , var(23) ] D[24,78] = (-1)*var(24); // [ var(78) , var(24) ] D[25,78] = var(25); // [ var(78) , var(25) ] D[26,78] = (-1)*var(26); // [ var(78) , var(26) ] D[27,78] = var(27); // [ var(78) , var(27) ] D[28,78] = var(28); // [ var(78) , var(28) ] D[29,78] = (-1)*var(29); // [ var(78) , var(29) ] D[30,78] = var(30); // [ var(78) , var(30) ] D[32,78] = var(32); // [ var(78) , var(32) ] // H(i) * Y(j): D[37,73] = (-2)*var(37); // [ var(73) , var(37) ] D[39,73] = var(39); // [ var(73) , var(39) ] D[43,73] = (-1)*var(43); // [ var(73) , var(43) ] D[45,73] = var(45); // [ var(73) , var(45) ] D[48,73] = (-1)*var(48); // [ var(73) , var(48) ] D[49,73] = var(49); // [ var(73) , var(49) ] D[51,73] = var(51); // [ var(73) , var(51) ] D[53,73] = (-1)*var(53); // [ var(73) , var(53) ] D[54,73] = (-1)*var(54); // [ var(73) , var(54) ] D[55,73] = var(55); // [ var(73) , var(55) ] D[57,73] = var(57); // [ var(73) , var(57) ] D[58,73] = (-1)*var(58); // [ var(73) , var(58) ] D[59,73] = (-1)*var(59); // [ var(73) , var(59) ] D[60,73] = var(60); // [ var(73) , var(60) ] D[61,73] = var(61); // [ var(73) , var(61) ] D[62,73] = (-1)*var(62); // [ var(73) , var(62) ] D[63,73] = (-1)*var(63); // [ var(73) , var(63) ] D[64,73] = var(64); // [ var(73) , var(64) ] D[66,73] = (-1)*var(66); // [ var(73) , var(66) ] D[67,73] = var(67); // [ var(73) , var(67) ] D[69,73] = (-1)*var(69); // [ var(73) , var(69) ] D[38,74] = (-2)*var(38); // [ var(74) , var(38) ] D[40,74] = var(40); // [ var(74) , var(40) ] D[44,74] = (-1)*var(44); // [ var(74) , var(44) ] D[45,74] = var(45); // [ var(74) , var(45) ] D[46,74] = var(46); // [ var(74) , var(46) ] D[48,74] = var(48); // [ var(74) , var(48) ] D[49,74] = (-1)*var(49); // [ var(74) , var(49) ] D[50,74] = (-1)*var(50); // [ var(74) , var(50) ] D[51,74] = var(51); // [ var(74) , var(51) ] D[52,74] = var(52); // [ var(74) , var(52) ] D[53,74] = (-1)*var(53); // [ var(74) , var(53) ] D[54,74] = var(54); // [ var(74) , var(54) ] D[55,74] = (-1)*var(55); // [ var(74) , var(55) ] D[56,74] = (-1)*var(56); // [ var(74) , var(56) ] D[57,74] = var(57); // [ var(74) , var(57) ] D[58,74] = (-1)*var(58); // [ var(74) , var(58) ] D[59,74] = var(59); // [ var(74) , var(59) ] D[61,74] = (-1)*var(61); // [ var(74) , var(61) ] D[63,74] = (-1)*var(63); // [ var(74) , var(63) ] D[71,74] = var(71); // [ var(74) , var(71) ] D[72,74] = (-1)*var(72); // [ var(74) , var(72) ] D[37,75] = var(37); // [ var(75) , var(37) ] D[39,75] = (-2)*var(39); // [ var(75) , var(39) ] D[40,75] = var(40); // [ var(75) , var(40) ] D[43,75] = (-1)*var(43); // [ var(75) , var(43) ] D[44,75] = var(44); // [ var(75) , var(44) ] D[45,75] = (-1)*var(45); // [ var(75) , var(45) ] D[46,75] = var(46); // [ var(75) , var(46) ] D[49,75] = (-1)*var(49); // [ var(75) , var(49) ] D[50,75] = var(50); // [ var(75) , var(50) ] D[51,75] = (-1)*var(51); // [ var(75) , var(51) ] D[52,75] = var(52); // [ var(75) , var(52) ] D[55,75] = (-1)*var(55); // [ var(75) , var(55) ] D[56,75] = var(56); // [ var(75) , var(56) ] D[57,75] = (-1)*var(57); // [ var(75) , var(57) ] D[61,75] = (-1)*var(61); // [ var(75) , var(61) ] D[62,75] = var(62); // [ var(75) , var(62) ] D[65,75] = (-1)*var(65); // [ var(75) , var(65) ] D[66,75] = var(66); // [ var(75) , var(66) ] D[68,75] = (-1)*var(68); // [ var(75) , var(68) ] D[69,75] = var(69); // [ var(75) , var(69) ] D[70,75] = (-1)*var(70); // [ var(75) , var(70) ] D[38,76] = var(38); // [ var(76) , var(38) ] D[39,76] = var(39); // [ var(76) , var(39) ] D[40,76] = (-2)*var(40); // [ var(76) , var(40) ] D[41,76] = var(41); // [ var(76) , var(41) ] D[43,76] = var(43); // [ var(76) , var(43) ] D[44,76] = (-1)*var(44); // [ var(76) , var(44) ] D[45,76] = (-1)*var(45); // [ var(76) , var(45) ] D[46,76] = (-1)*var(46); // [ var(76) , var(46) ] D[47,76] = var(47); // [ var(76) , var(47) ] D[48,76] = (-1)*var(48); // [ var(76) , var(48) ] D[52,76] = (-1)*var(52); // [ var(76) , var(52) ] D[55,76] = var(55); // [ var(76) , var(55) ] D[58,76] = var(58); // [ var(76) , var(58) ] D[60,76] = (-1)*var(60); // [ var(76) , var(60) ] D[61,76] = var(61); // [ var(76) , var(61) ] D[62,76] = (-1)*var(62); // [ var(76) , var(62) ] D[63,76] = var(63); // [ var(76) , var(63) ] D[64,76] = (-1)*var(64); // [ var(76) , var(64) ] D[66,76] = (-1)*var(66); // [ var(76) , var(66) ] D[70,76] = var(70); // [ var(76) , var(70) ] D[71,76] = (-1)*var(71); // [ var(76) , var(71) ] D[40,77] = var(40); // [ var(77) , var(40) ] D[41,77] = (-2)*var(41); // [ var(77) , var(41) ] D[42,77] = var(42); // [ var(77) , var(42) ] D[44,77] = var(44); // [ var(77) , var(44) ] D[45,77] = var(45); // [ var(77) , var(45) ] D[46,77] = (-1)*var(46); // [ var(77) , var(46) ] D[47,77] = (-1)*var(47); // [ var(77) , var(47) ] D[48,77] = var(48); // [ var(77) , var(48) ] D[49,77] = var(49); // [ var(77) , var(49) ] D[50,77] = (-1)*var(50); // [ var(77) , var(50) ] D[51,77] = (-1)*var(51); // [ var(77) , var(51) ] D[53,77] = var(53); // [ var(77) , var(53) ] D[54,77] = (-1)*var(54); // [ var(77) , var(54) ] D[55,77] = (-1)*var(55); // [ var(77) , var(55) ] D[58,77] = (-1)*var(58); // [ var(77) , var(58) ] D[64,77] = var(64); // [ var(77) , var(64) ] D[66,77] = var(66); // [ var(77) , var(66) ] D[67,77] = (-1)*var(67); // [ var(77) , var(67) ] D[68,77] = var(68); // [ var(77) , var(68) ] D[69,77] = (-1)*var(69); // [ var(77) , var(69) ] D[70,77] = (-1)*var(70); // [ var(77) , var(70) ] D[41,78] = var(41); // [ var(78) , var(41) ] D[42,78] = (-2)*var(42); // [ var(78) , var(42) ] D[46,78] = var(46); // [ var(78) , var(46) ] D[47,78] = (-1)*var(47); // [ var(78) , var(47) ] D[50,78] = var(50); // [ var(78) , var(50) ] D[51,78] = var(51); // [ var(78) , var(51) ] D[52,78] = (-1)*var(52); // [ var(78) , var(52) ] D[54,78] = var(54); // [ var(78) , var(54) ] D[55,78] = var(55); // [ var(78) , var(55) ] D[56,78] = (-1)*var(56); // [ var(78) , var(56) ] D[57,78] = (-1)*var(57); // [ var(78) , var(57) ] D[58,78] = var(58); // [ var(78) , var(58) ] D[59,78] = (-1)*var(59); // [ var(78) , var(59) ] D[60,78] = var(60); // [ var(78) , var(60) ] D[61,78] = (-1)*var(61); // [ var(78) , var(61) ] D[62,78] = var(62); // [ var(78) , var(62) ] D[63,78] = (-1)*var(63); // [ var(78) , var(63) ] D[64,78] = (-1)*var(64); // [ var(78) , var(64) ] D[65,78] = var(65); // [ var(78) , var(65) ] D[66,78] = (-1)*var(66); // [ var(78) , var(66) ] D[68,78] = (-1)*var(68); // [ var(78) , var(68) ] // Y(i) * X(j): D[1,37] = (-1)*var(73); // [ var(37) , var(1) ] D[7,37] = (-1)*var(3); // [ var(37) , var(7) ] D[12,37] = (-1)*var(9); // [ var(37) , var(12) ] D[17,37] = (-1)*var(13); // [ var(37) , var(17) ] D[18,37] = (-1)*var(15); // [ var(37) , var(18) ] D[22,37] = (-1)*var(19); // [ var(37) , var(22) ] D[23,37] = (-1)*var(21); // [ var(37) , var(23) ] D[26,37] = (-1)*var(24); // [ var(37) , var(26) ] D[27,37] = (-1)*var(25); // [ var(37) , var(27) ] D[30,37] = (-1)*var(28); // [ var(37) , var(30) ] D[33,37] = (-1)*var(31); // [ var(37) , var(33) ] D[2,38] = (-1)*var(74); // [ var(38) , var(2) ] D[8,38] = (-1)*var(4); // [ var(38) , var(8) ] D[13,38] = (-1)*var(9); // [ var(38) , var(13) ] D[14,38] = (-1)*var(10); // [ var(38) , var(14) ] D[17,38] = (-1)*var(12); // [ var(38) , var(17) ] D[19,38] = (-1)*var(15); // [ var(38) , var(19) ] D[20,38] = (-1)*var(16); // [ var(38) , var(20) ] D[22,38] = (-1)*var(18); // [ var(38) , var(22) ] D[25,38] = (-1)*var(21); // [ var(38) , var(25) ] D[27,38] = (-1)*var(23); // [ var(38) , var(27) ] D[36,38] = var(35); // [ var(38) , var(36) ] D[3,39] = (-1)*var(75); // [ var(39) , var(3) ] D[7,39] = var(1); // [ var(39) , var(7) ] D[9,39] = (-1)*var(4); // [ var(39) , var(9) ] D[13,39] = (-1)*var(8); // [ var(39) , var(13) ] D[15,39] = (-1)*var(10); // [ var(39) , var(15) ] D[19,39] = (-1)*var(14); // [ var(39) , var(19) ] D[21,39] = (-1)*var(16); // [ var(39) , var(21) ] D[25,39] = (-1)*var(20); // [ var(39) , var(25) ] D[29,39] = (-1)*var(26); // [ var(39) , var(29) ] D[32,39] = (-1)*var(30); // [ var(39) , var(32) ] D[34,39] = (-1)*var(33); // [ var(39) , var(34) ] D[4,40] = (-1)*var(76); // [ var(40) , var(4) ] D[8,40] = var(2); // [ var(40) , var(8) ] D[9,40] = var(3); // [ var(40) , var(9) ] D[10,40] = (-1)*var(5); // [ var(40) , var(10) ] D[12,40] = var(7); // [ var(40) , var(12) ] D[16,40] = (-1)*var(11); // [ var(40) , var(16) ] D[24,40] = var(19); // [ var(40) , var(24) ] D[26,40] = var(22); // [ var(40) , var(26) ] D[28,40] = var(25); // [ var(40) , var(28) ] D[30,40] = var(27); // [ var(40) , var(30) ] D[35,40] = var(34); // [ var(40) , var(35) ] D[5,41] = (-1)*var(77); // [ var(41) , var(5) ] D[10,41] = var(4); // [ var(41) , var(10) ] D[11,41] = (-1)*var(6); // [ var(41) , var(11) ] D[14,41] = var(8); // [ var(41) , var(14) ] D[15,41] = var(9); // [ var(41) , var(15) ] D[18,41] = var(12); // [ var(41) , var(18) ] D[19,41] = var(13); // [ var(41) , var(19) ] D[22,41] = var(17); // [ var(41) , var(22) ] D[31,41] = var(28); // [ var(41) , var(31) ] D[33,41] = var(30); // [ var(41) , var(33) ] D[34,41] = var(32); // [ var(41) , var(34) ] D[6,42] = (-1)*var(78); // [ var(42) , var(6) ] D[11,42] = var(5); // [ var(42) , var(11) ] D[16,42] = var(10); // [ var(42) , var(16) ] D[20,42] = var(14); // [ var(42) , var(20) ] D[21,42] = var(15); // [ var(42) , var(21) ] D[23,42] = var(18); // [ var(42) , var(23) ] D[25,42] = var(19); // [ var(42) , var(25) ] D[27,42] = var(22); // [ var(42) , var(27) ] D[28,42] = var(24); // [ var(42) , var(28) ] D[30,42] = var(26); // [ var(42) , var(30) ] D[32,42] = var(29); // [ var(42) , var(32) ] D[1,43] = (-1)*var(39); // [ var(43) , var(1) ] D[3,43] = var(37); // [ var(43) , var(3) ] D[7,43] = (-1)*var(73)+(-1)*var(75); // [ var(43) , var(7) ] D[12,43] = (-1)*var(4); // [ var(43) , var(12) ] D[17,43] = (-1)*var(8); // [ var(43) , var(17) ] D[18,43] = (-1)*var(10); // [ var(43) , var(18) ] D[22,43] = (-1)*var(14); // [ var(43) , var(22) ] D[23,43] = (-1)*var(16); // [ var(43) , var(23) ] D[27,43] = (-1)*var(20); // [ var(43) , var(27) ] D[29,43] = var(24); // [ var(43) , var(29) ] D[32,43] = var(28); // [ var(43) , var(32) ] D[34,43] = var(31); // [ var(43) , var(34) ] D[2,44] = (-1)*var(40); // [ var(44) , var(2) ] D[4,44] = var(38); // [ var(44) , var(4) ] D[8,44] = (-1)*var(74)+(-1)*var(76); // [ var(44) , var(8) ] D[13,44] = var(3); // [ var(44) , var(13) ] D[14,44] = (-1)*var(5); // [ var(44) , var(14) ] D[17,44] = var(7); // [ var(44) , var(17) ] D[20,44] = (-1)*var(11); // [ var(44) , var(20) ] D[24,44] = (-1)*var(15); // [ var(44) , var(24) ] D[26,44] = (-1)*var(18); // [ var(44) , var(26) ] D[28,44] = (-1)*var(21); // [ var(44) , var(28) ] D[30,44] = (-1)*var(23); // [ var(44) , var(30) ] D[36,44] = (-1)*var(34); // [ var(44) , var(36) ] D[3,45] = (-1)*var(40); // [ var(45) , var(3) ] D[4,45] = var(39); // [ var(45) , var(4) ] D[9,45] = (-1)*var(75)+(-1)*var(76); // [ var(45) , var(9) ] D[12,45] = var(1); // [ var(45) , var(12) ] D[13,45] = var(2); // [ var(45) , var(13) ] D[15,45] = (-1)*var(5); // [ var(45) , var(15) ] D[21,45] = (-1)*var(11); // [ var(45) , var(21) ] D[24,45] = (-1)*var(14); // [ var(45) , var(24) ] D[28,45] = (-1)*var(20); // [ var(45) , var(28) ] D[29,45] = var(22); // [ var(45) , var(29) ] D[32,45] = var(27); // [ var(45) , var(32) ] D[35,45] = (-1)*var(33); // [ var(45) , var(35) ] D[4,46] = (-1)*var(41); // [ var(46) , var(4) ] D[5,46] = var(40); // [ var(46) , var(5) ] D[10,46] = (-1)*var(76)+(-1)*var(77); // [ var(46) , var(10) ] D[14,46] = var(2); // [ var(46) , var(14) ] D[15,46] = var(3); // [ var(46) , var(15) ] D[16,46] = (-1)*var(6); // [ var(46) , var(16) ] D[18,46] = var(7); // [ var(46) , var(18) ] D[24,46] = (-1)*var(13); // [ var(46) , var(24) ] D[26,46] = (-1)*var(17); // [ var(46) , var(26) ] D[31,46] = var(25); // [ var(46) , var(31) ] D[33,46] = var(27); // [ var(46) , var(33) ] D[35,46] = (-1)*var(32); // [ var(46) , var(35) ] D[5,47] = (-1)*var(42); // [ var(47) , var(5) ] D[6,47] = var(41); // [ var(47) , var(6) ] D[11,47] = (-1)*var(77)+(-1)*var(78); // [ var(47) , var(11) ] D[16,47] = var(4); // [ var(47) , var(16) ] D[20,47] = var(8); // [ var(47) , var(20) ] D[21,47] = var(9); // [ var(47) , var(21) ] D[23,47] = var(12); // [ var(47) , var(23) ] D[25,47] = var(13); // [ var(47) , var(25) ] D[27,47] = var(17); // [ var(47) , var(27) ] D[31,47] = (-1)*var(24); // [ var(47) , var(31) ] D[33,47] = (-1)*var(26); // [ var(47) , var(33) ] D[34,47] = (-1)*var(29); // [ var(47) , var(34) ] D[1,48] = (-1)*var(45); // [ var(48) , var(1) ] D[4,48] = var(43); // [ var(48) , var(4) ] D[7,48] = (-1)*var(40); // [ var(48) , var(7) ] D[9,48] = var(37); // [ var(48) , var(9) ] D[12,48] = (-1)*var(73)+(-1)*var(75)+(-1)*var(76); // [ var(48) , var(12) ] D[17,48] = var(2); // [ var(48) , var(17) ] D[18,48] = (-1)*var(5); // [ var(48) , var(18) ] D[23,48] = (-1)*var(11); // [ var(48) , var(23) ] D[26,48] = (-1)*var(14); // [ var(48) , var(26) ] D[29,48] = (-1)*var(19); // [ var(48) , var(29) ] D[30,48] = (-1)*var(20); // [ var(48) , var(30) ] D[32,48] = (-1)*var(25); // [ var(48) , var(32) ] D[35,48] = var(31); // [ var(48) , var(35) ] D[2,49] = (-1)*var(45); // [ var(49) , var(2) ] D[3,49] = (-1)*var(44); // [ var(49) , var(3) ] D[8,49] = var(39); // [ var(49) , var(8) ] D[9,49] = var(38); // [ var(49) , var(9) ] D[13,49] = (-1)*var(74)+(-1)*var(75)+(-1)*var(76); // [ var(49) , var(13) ] D[17,49] = var(1); // [ var(49) , var(17) ] D[19,49] = (-1)*var(5); // [ var(49) , var(19) ] D[24,49] = var(10); // [ var(49) , var(24) ] D[25,49] = (-1)*var(11); // [ var(49) , var(25) ] D[28,49] = var(16); // [ var(49) , var(28) ] D[29,49] = (-1)*var(18); // [ var(49) , var(29) ] D[32,49] = (-1)*var(23); // [ var(49) , var(32) ] D[36,49] = var(33); // [ var(49) , var(36) ] D[2,50] = (-1)*var(46); // [ var(50) , var(2) ] D[5,50] = var(44); // [ var(50) , var(5) ] D[8,50] = (-1)*var(41); // [ var(50) , var(8) ] D[10,50] = var(38); // [ var(50) , var(10) ] D[14,50] = (-1)*var(74)+(-1)*var(76)+(-1)*var(77); // [ var(50) , var(14) ] D[19,50] = var(3); // [ var(50) , var(19) ] D[20,50] = (-1)*var(6); // [ var(50) , var(20) ] D[22,50] = var(7); // [ var(50) , var(22) ] D[24,50] = var(9); // [ var(50) , var(24) ] D[26,50] = var(12); // [ var(50) , var(26) ] D[31,50] = (-1)*var(21); // [ var(50) , var(31) ] D[33,50] = (-1)*var(23); // [ var(50) , var(33) ] D[36,50] = var(32); // [ var(50) , var(36) ] D[3,51] = (-1)*var(46); // [ var(51) , var(3) ] D[5,51] = var(45); // [ var(51) , var(5) ] D[9,51] = (-1)*var(41); // [ var(51) , var(9) ] D[10,51] = var(39); // [ var(51) , var(10) ] D[15,51] = (-1)*var(75)+(-1)*var(76)+(-1)*var(77); // [ var(51) , var(15) ] D[18,51] = var(1); // [ var(51) , var(18) ] D[19,51] = var(2); // [ var(51) , var(19) ] D[21,51] = (-1)*var(6); // [ var(51) , var(21) ] D[24,51] = var(8); // [ var(51) , var(24) ] D[29,51] = (-1)*var(17); // [ var(51) , var(29) ] D[31,51] = (-1)*var(20); // [ var(51) , var(31) ] D[34,51] = var(27); // [ var(51) , var(34) ] D[35,51] = var(30); // [ var(51) , var(35) ] D[4,52] = (-1)*var(47); // [ var(52) , var(4) ] D[6,52] = var(46); // [ var(52) , var(6) ] D[10,52] = (-1)*var(42); // [ var(52) , var(10) ] D[11,52] = var(40); // [ var(52) , var(11) ] D[16,52] = (-1)*var(76)+(-1)*var(77)+(-1)*var(78); // [ var(52) , var(16) ] D[20,52] = var(2); // [ var(52) , var(20) ] D[21,52] = var(3); // [ var(52) , var(21) ] D[23,52] = var(7); // [ var(52) , var(23) ] D[28,52] = (-1)*var(13); // [ var(52) , var(28) ] D[30,52] = (-1)*var(17); // [ var(52) , var(30) ] D[31,52] = (-1)*var(19); // [ var(52) , var(31) ] D[33,52] = (-1)*var(22); // [ var(52) , var(33) ] D[35,52] = var(29); // [ var(52) , var(35) ] D[1,53] = (-1)*var(49); // [ var(53) , var(1) ] D[2,53] = (-1)*var(48); // [ var(53) , var(2) ] D[7,53] = (-1)*var(44); // [ var(53) , var(7) ] D[8,53] = var(43); // [ var(53) , var(8) ] D[12,53] = var(38); // [ var(53) , var(12) ] D[13,53] = var(37); // [ var(53) , var(13) ] D[17,53] = (-1)*var(73)+(-1)*var(74)+(-1)*var(75)+(-1)*var(76); // [ var(53) , var(17) ] D[22,53] = (-1)*var(5); // [ var(53) , var(22) ] D[26,53] = var(10); // [ var(53) , var(26) ] D[27,53] = (-1)*var(11); // [ var(53) , var(27) ] D[29,53] = var(15); // [ var(53) , var(29) ] D[30,53] = var(16); // [ var(53) , var(30) ] D[32,53] = var(21); // [ var(53) , var(32) ] D[36,53] = (-1)*var(31); // [ var(53) , var(36) ] D[1,54] = (-1)*var(51); // [ var(54) , var(1) ] D[5,54] = var(48); // [ var(54) , var(5) ] D[7,54] = (-1)*var(46); // [ var(54) , var(7) ] D[10,54] = var(43); // [ var(54) , var(10) ] D[12,54] = (-1)*var(41); // [ var(54) , var(12) ] D[15,54] = var(37); // [ var(54) , var(15) ] D[18,54] = (-1)*var(73)+(-1)*var(75)+(-1)*var(76)+(-1)*var(77); // [ var(54) , var(18) ] D[22,54] = var(2); // [ var(54) , var(22) ] D[23,54] = (-1)*var(6); // [ var(54) , var(23) ] D[26,54] = var(8); // [ var(54) , var(26) ] D[29,54] = var(13); // [ var(54) , var(29) ] D[33,54] = (-1)*var(20); // [ var(54) , var(33) ] D[34,54] = (-1)*var(25); // [ var(54) , var(34) ] D[35,54] = (-1)*var(28); // [ var(54) , var(35) ] D[2,55] = (-1)*var(51); // [ var(55) , var(2) ] D[3,55] = (-1)*var(50); // [ var(55) , var(3) ] D[5,55] = var(49); // [ var(55) , var(5) ] D[13,55] = (-1)*var(41); // [ var(55) , var(13) ] D[14,55] = var(39); // [ var(55) , var(14) ] D[15,55] = var(38); // [ var(55) , var(15) ] D[19,55] = (-1)*var(74)+(-1)*var(75)+(-1)*var(76)+(-1)*var(77); // [ var(55) , var(19) ] D[22,55] = var(1); // [ var(55) , var(22) ] D[24,55] = (-1)*var(4); // [ var(55) , var(24) ] D[25,55] = (-1)*var(6); // [ var(55) , var(25) ] D[29,55] = var(12); // [ var(55) , var(29) ] D[31,55] = var(16); // [ var(55) , var(31) ] D[34,55] = (-1)*var(23); // [ var(55) , var(34) ] D[36,55] = (-1)*var(30); // [ var(55) , var(36) ] D[2,56] = (-1)*var(52); // [ var(56) , var(2) ] D[6,56] = var(50); // [ var(56) , var(6) ] D[8,56] = (-1)*var(47); // [ var(56) , var(8) ] D[11,56] = var(44); // [ var(56) , var(11) ] D[14,56] = (-1)*var(42); // [ var(56) , var(14) ] D[16,56] = var(38); // [ var(56) , var(16) ] D[20,56] = (-1)*var(74)+(-1)*var(76)+(-1)*var(77)+(-1)*var(78); // [ var(56) , var(20) ] D[25,56] = var(3); // [ var(56) , var(25) ] D[27,56] = var(7); // [ var(56) , var(27) ] D[28,56] = var(9); // [ var(56) , var(28) ] D[30,56] = var(12); // [ var(56) , var(30) ] D[31,56] = var(15); // [ var(56) , var(31) ] D[33,56] = var(18); // [ var(56) , var(33) ] D[36,56] = (-1)*var(29); // [ var(56) , var(36) ] D[3,57] = (-1)*var(52); // [ var(57) , var(3) ] D[6,57] = var(51); // [ var(57) , var(6) ] D[9,57] = (-1)*var(47); // [ var(57) , var(9) ] D[11,57] = var(45); // [ var(57) , var(11) ] D[15,57] = (-1)*var(42); // [ var(57) , var(15) ] D[16,57] = var(39); // [ var(57) , var(16) ] D[21,57] = (-1)*var(75)+(-1)*var(76)+(-1)*var(77)+(-1)*var(78); // [ var(57) , var(21) ] D[23,57] = var(1); // [ var(57) , var(23) ] D[25,57] = var(2); // [ var(57) , var(25) ] D[28,57] = var(8); // [ var(57) , var(28) ] D[31,57] = var(14); // [ var(57) , var(31) ] D[32,57] = (-1)*var(17); // [ var(57) , var(32) ] D[34,57] = (-1)*var(22); // [ var(57) , var(34) ] D[35,57] = (-1)*var(26); // [ var(57) , var(35) ] D[1,58] = (-1)*var(55); // [ var(58) , var(1) ] D[2,58] = (-1)*var(54); // [ var(58) , var(2) ] D[5,58] = var(53); // [ var(58) , var(5) ] D[7,58] = (-1)*var(50); // [ var(58) , var(7) ] D[14,58] = var(43); // [ var(58) , var(14) ] D[17,58] = (-1)*var(41); // [ var(58) , var(17) ] D[18,58] = var(38); // [ var(58) , var(18) ] D[19,58] = var(37); // [ var(58) , var(19) ] D[22,58] = (-1)*var(73)+(-1)*var(74)+(-1)*var(75)+(-1)*var(76)+(-1)*var(77); // [ var(58) , var(22) ] D[26,58] = (-1)*var(4); // [ var(58) , var(26) ] D[27,58] = (-1)*var(6); // [ var(58) , var(27) ] D[29,58] = (-1)*var(9); // [ var(58) , var(29) ] D[33,58] = var(16); // [ var(58) , var(33) ] D[34,58] = var(21); // [ var(58) , var(34) ] D[36,58] = var(28); // [ var(58) , var(36) ] D[1,59] = (-1)*var(57); // [ var(59) , var(1) ] D[6,59] = var(54); // [ var(59) , var(6) ] D[7,59] = (-1)*var(52); // [ var(59) , var(7) ] D[11,59] = var(48); // [ var(59) , var(11) ] D[12,59] = (-1)*var(47); // [ var(59) , var(12) ] D[16,59] = var(43); // [ var(59) , var(16) ] D[18,59] = (-1)*var(42); // [ var(59) , var(18) ] D[21,59] = var(37); // [ var(59) , var(21) ] D[23,59] = (-1)*var(73)+(-1)*var(75)+(-1)*var(76)+(-1)*var(77)+(-1)*var(78); // [ var(59) , var(23) ] D[27,59] = var(2); // [ var(59) , var(27) ] D[30,59] = var(8); // [ var(59) , var(30) ] D[32,59] = var(13); // [ var(59) , var(32) ] D[33,59] = var(14); // [ var(59) , var(33) ] D[34,59] = var(19); // [ var(59) , var(34) ] D[35,59] = var(24); // [ var(59) , var(35) ] D[4,60] = var(55); // [ var(60) , var(4) ] D[8,60] = (-1)*var(51); // [ var(60) , var(8) ] D[9,60] = (-1)*var(50); // [ var(60) , var(9) ] D[10,60] = (-1)*var(49); // [ var(60) , var(10) ] D[13,60] = var(46); // [ var(60) , var(13) ] D[14,60] = var(45); // [ var(60) , var(14) ] D[15,60] = var(44); // [ var(60) , var(15) ] D[19,60] = (-1)*var(40); // [ var(60) , var(19) ] D[24,60] = (-1)*var(74)+(-1)*var(75)+(-2)*var(76)+(-1)*var(77); // [ var(60) , var(24) ] D[26,60] = var(1); // [ var(60) , var(26) ] D[28,60] = (-1)*var(6); // [ var(60) , var(28) ] D[29,60] = (-1)*var(7); // [ var(60) , var(29) ] D[31,60] = var(11); // [ var(60) , var(31) ] D[35,60] = (-1)*var(23); // [ var(60) , var(35) ] D[36,60] = var(27); // [ var(60) , var(36) ] D[2,61] = (-1)*var(57); // [ var(61) , var(2) ] D[3,61] = (-1)*var(56); // [ var(61) , var(3) ] D[6,61] = var(55); // [ var(61) , var(6) ] D[11,61] = var(49); // [ var(61) , var(11) ] D[13,61] = (-1)*var(47); // [ var(61) , var(13) ] D[19,61] = (-1)*var(42); // [ var(61) , var(19) ] D[20,61] = var(39); // [ var(61) , var(20) ] D[21,61] = var(38); // [ var(61) , var(21) ] D[25,61] = (-1)*var(74)+(-1)*var(75)+(-1)*var(76)+(-1)*var(77)+(-1)*var(78); // [ var(61) , var(25) ] D[27,61] = var(1); // [ var(61) , var(27) ] D[28,61] = (-1)*var(4); // [ var(61) , var(28) ] D[31,61] = (-1)*var(10); // [ var(61) , var(31) ] D[32,61] = var(12); // [ var(61) , var(32) ] D[34,61] = var(18); // [ var(61) , var(34) ] D[36,61] = var(26); // [ var(61) , var(36) ] D[1,62] = (-1)*var(60); // [ var(62) , var(1) ] D[4,62] = var(58); // [ var(62) , var(4) ] D[8,62] = (-1)*var(54); // [ var(62) , var(8) ] D[10,62] = (-1)*var(53); // [ var(62) , var(10) ] D[12,62] = (-1)*var(50); // [ var(62) , var(12) ] D[14,62] = var(48); // [ var(62) , var(14) ] D[17,62] = var(46); // [ var(62) , var(17) ] D[18,62] = var(44); // [ var(62) , var(18) ] D[22,62] = (-1)*var(40); // [ var(62) , var(22) ] D[24,62] = var(37); // [ var(62) , var(24) ] D[26,62] = (-1)*var(73)+(-1)*var(74)+(-1)*var(75)+(-2)*var(76)+(-1)*var(77); // [ var(62) , var(26) ] D[29,62] = var(3); // [ var(62) , var(29) ] D[30,62] = (-1)*var(6); // [ var(62) , var(30) ] D[33,62] = var(11); // [ var(62) , var(33) ] D[35,62] = var(21); // [ var(62) , var(35) ] D[36,62] = (-1)*var(25); // [ var(62) , var(36) ] D[1,63] = (-1)*var(61); // [ var(63) , var(1) ] D[2,63] = (-1)*var(59); // [ var(63) , var(2) ] D[6,63] = var(58); // [ var(63) , var(6) ] D[7,63] = (-1)*var(56); // [ var(63) , var(7) ] D[11,63] = var(53); // [ var(63) , var(11) ] D[17,63] = (-1)*var(47); // [ var(63) , var(17) ] D[20,63] = var(43); // [ var(63) , var(20) ] D[22,63] = (-1)*var(42); // [ var(63) , var(22) ] D[23,63] = var(38); // [ var(63) , var(23) ] D[25,63] = var(37); // [ var(63) , var(25) ] D[27,63] = (-1)*var(73)+(-1)*var(74)+(-1)*var(75)+(-1)*var(76)+(-1)*var(77)+(-1)*var(78); // [ var(63) , var(27) ] D[30,63] = (-1)*var(4); // [ var(63) , var(30) ] D[32,63] = (-1)*var(9); // [ var(63) , var(32) ] D[33,63] = (-1)*var(10); // [ var(63) , var(33) ] D[34,63] = (-1)*var(15); // [ var(63) , var(34) ] D[36,63] = (-1)*var(24); // [ var(63) , var(36) ] D[4,64] = var(61); // [ var(64) , var(4) ] D[6,64] = var(60); // [ var(64) , var(6) ] D[8,64] = (-1)*var(57); // [ var(64) , var(8) ] D[9,64] = (-1)*var(56); // [ var(64) , var(9) ] D[13,64] = var(52); // [ var(64) , var(13) ] D[16,64] = (-1)*var(49); // [ var(64) , var(16) ] D[20,64] = var(45); // [ var(64) , var(20) ] D[21,64] = var(44); // [ var(64) , var(21) ] D[24,64] = (-1)*var(42); // [ var(64) , var(24) ] D[25,64] = (-1)*var(40); // [ var(64) , var(25) ] D[28,64] = (-1)*var(74)+(-1)*var(75)+(-2)*var(76)+(-1)*var(77)+(-1)*var(78); // [ var(64) , var(28) ] D[30,64] = var(1); // [ var(64) , var(30) ] D[31,64] = (-1)*var(5); // [ var(64) , var(31) ] D[32,64] = (-1)*var(7); // [ var(64) , var(32) ] D[35,64] = var(18); // [ var(64) , var(35) ] D[36,64] = (-1)*var(22); // [ var(64) , var(36) ] D[3,65] = (-1)*var(62); // [ var(65) , var(3) ] D[7,65] = var(60); // [ var(65) , var(7) ] D[9,65] = var(58); // [ var(65) , var(9) ] D[12,65] = (-1)*var(55); // [ var(65) , var(12) ] D[13,65] = (-1)*var(54); // [ var(65) , var(13) ] D[15,65] = (-1)*var(53); // [ var(65) , var(15) ] D[17,65] = var(51); // [ var(65) , var(17) ] D[18,65] = var(49); // [ var(65) , var(18) ] D[19,65] = var(48); // [ var(65) , var(19) ] D[22,65] = (-1)*var(45); // [ var(65) , var(22) ] D[24,65] = (-1)*var(43); // [ var(65) , var(24) ] D[26,65] = var(39); // [ var(65) , var(26) ] D[29,65] = (-1)*var(73)+(-1)*var(74)+(-2)*var(75)+(-2)*var(76)+(-1)*var(77); // [ var(65) , var(29) ] D[32,65] = (-1)*var(6); // [ var(65) , var(32) ] D[34,65] = var(11); // [ var(65) , var(34) ] D[35,65] = (-1)*var(16); // [ var(65) , var(35) ] D[36,65] = var(20); // [ var(65) , var(36) ] D[1,66] = (-1)*var(64); // [ var(66) , var(1) ] D[4,66] = var(63); // [ var(66) , var(4) ] D[6,66] = var(62); // [ var(66) , var(6) ] D[8,66] = (-1)*var(59); // [ var(66) , var(8) ] D[12,66] = (-1)*var(56); // [ var(66) , var(12) ] D[16,66] = (-1)*var(53); // [ var(66) , var(16) ] D[17,66] = var(52); // [ var(66) , var(17) ] D[20,66] = var(48); // [ var(66) , var(20) ] D[23,66] = var(44); // [ var(66) , var(23) ] D[26,66] = (-1)*var(42); // [ var(66) , var(26) ] D[27,66] = (-1)*var(40); // [ var(66) , var(27) ] D[28,66] = var(37); // [ var(66) , var(28) ] D[30,66] = (-1)*var(73)+(-1)*var(74)+(-1)*var(75)+(-2)*var(76)+(-1)*var(77)+(-1)*var(78); // [ var(66) , var(30) ] D[32,66] = var(3); // [ var(66) , var(32) ] D[33,66] = (-1)*var(5); // [ var(66) , var(33) ] D[35,66] = (-1)*var(15); // [ var(66) , var(35) ] D[36,66] = var(19); // [ var(66) , var(36) ] D[5,67] = var(64); // [ var(67) , var(5) ] D[10,67] = var(61); // [ var(67) , var(10) ] D[11,67] = (-1)*var(60); // [ var(67) , var(11) ] D[14,67] = (-1)*var(57); // [ var(67) , var(14) ] D[15,67] = (-1)*var(56); // [ var(67) , var(15) ] D[16,67] = (-1)*var(55); // [ var(67) , var(16) ] D[19,67] = var(52); // [ var(67) , var(19) ] D[20,67] = var(51); // [ var(67) , var(20) ] D[21,67] = var(50); // [ var(67) , var(21) ] D[24,67] = var(47); // [ var(67) , var(24) ] D[25,67] = (-1)*var(46); // [ var(67) , var(25) ] D[28,67] = (-1)*var(41); // [ var(67) , var(28) ] D[31,67] = (-1)*var(74)+(-1)*var(75)+(-2)*var(76)+(-2)*var(77)+(-1)*var(78); // [ var(67) , var(31) ] D[33,67] = var(1); // [ var(67) , var(33) ] D[34,67] = (-1)*var(7); // [ var(67) , var(34) ] D[35,67] = (-1)*var(12); // [ var(67) , var(35) ] D[36,67] = var(17); // [ var(67) , var(36) ] D[3,68] = (-1)*var(66); // [ var(68) , var(3) ] D[6,68] = var(65); // [ var(68) , var(6) ] D[7,68] = var(64); // [ var(68) , var(7) ] D[9,68] = var(63); // [ var(68) , var(9) ] D[12,68] = (-1)*var(61); // [ var(68) , var(12) ] D[13,68] = (-1)*var(59); // [ var(68) , var(13) ] D[17,68] = var(57); // [ var(68) , var(17) ] D[21,68] = (-1)*var(53); // [ var(68) , var(21) ] D[23,68] = var(49); // [ var(68) , var(23) ] D[25,68] = var(48); // [ var(68) , var(25) ] D[27,68] = (-1)*var(45); // [ var(68) , var(27) ] D[28,68] = (-1)*var(43); // [ var(68) , var(28) ] D[29,68] = (-1)*var(42); // [ var(68) , var(29) ] D[30,68] = var(39); // [ var(68) , var(30) ] D[32,68] = (-1)*var(73)+(-1)*var(74)+(-2)*var(75)+(-2)*var(76)+(-1)*var(77)+(-1)*var(78); // [ var(68) , var(32) ] D[34,68] = (-1)*var(5); // [ var(68) , var(34) ] D[35,68] = var(10); // [ var(68) , var(35) ] D[36,68] = (-1)*var(14); // [ var(68) , var(36) ] D[1,69] = (-1)*var(67); // [ var(69) , var(1) ] D[5,69] = var(66); // [ var(69) , var(5) ] D[10,69] = var(63); // [ var(69) , var(10) ] D[11,69] = (-1)*var(62); // [ var(69) , var(11) ] D[14,69] = (-1)*var(59); // [ var(69) , var(14) ] D[16,69] = (-1)*var(58); // [ var(69) , var(16) ] D[18,69] = (-1)*var(56); // [ var(69) , var(18) ] D[20,69] = var(54); // [ var(69) , var(20) ] D[22,69] = var(52); // [ var(69) , var(22) ] D[23,69] = var(50); // [ var(69) , var(23) ] D[26,69] = var(47); // [ var(69) , var(26) ] D[27,69] = (-1)*var(46); // [ var(69) , var(27) ] D[30,69] = (-1)*var(41); // [ var(69) , var(30) ] D[31,69] = var(37); // [ var(69) , var(31) ] D[33,69] = (-1)*var(73)+(-1)*var(74)+(-1)*var(75)+(-2)*var(76)+(-2)*var(77)+(-1)*var(78); // [ var(69) , var(33) ] D[34,69] = var(3); // [ var(69) , var(34) ] D[35,69] = var(9); // [ var(69) , var(35) ] D[36,69] = (-1)*var(13); // [ var(69) , var(36) ] D[3,70] = (-1)*var(69); // [ var(70) , var(3) ] D[5,70] = var(68); // [ var(70) , var(5) ] D[7,70] = var(67); // [ var(70) , var(7) ] D[11,70] = (-1)*var(65); // [ var(70) , var(11) ] D[15,70] = var(63); // [ var(70) , var(15) ] D[18,70] = (-1)*var(61); // [ var(70) , var(18) ] D[19,70] = (-1)*var(59); // [ var(70) , var(19) ] D[21,70] = (-1)*var(58); // [ var(70) , var(21) ] D[22,70] = var(57); // [ var(70) , var(22) ] D[23,70] = var(55); // [ var(70) , var(23) ] D[25,70] = var(54); // [ var(70) , var(25) ] D[27,70] = (-1)*var(51); // [ var(70) , var(27) ] D[29,70] = var(47); // [ var(70) , var(29) ] D[31,70] = (-1)*var(43); // [ var(70) , var(31) ] D[32,70] = (-1)*var(41); // [ var(70) , var(32) ] D[33,70] = var(39); // [ var(70) , var(33) ] D[34,70] = (-1)*var(73)+(-1)*var(74)+(-2)*var(75)+(-2)*var(76)+(-2)*var(77)+(-1)*var(78); // [ var(70) , var(34) ] D[35,70] = (-1)*var(4); // [ var(70) , var(35) ] D[36,70] = var(8); // [ var(70) , var(36) ] D[4,71] = var(70); // [ var(71) , var(4) ] D[9,71] = (-1)*var(69); // [ var(71) , var(9) ] D[10,71] = (-1)*var(68); // [ var(71) , var(10) ] D[12,71] = var(67); // [ var(71) , var(12) ] D[15,71] = var(66); // [ var(71) , var(15) ] D[16,71] = var(65); // [ var(71) , var(16) ] D[18,71] = (-1)*var(64); // [ var(71) , var(18) ] D[21,71] = (-1)*var(62); // [ var(71) , var(21) ] D[23,71] = var(60); // [ var(71) , var(23) ] D[24,71] = (-1)*var(59); // [ var(71) , var(24) ] D[26,71] = var(57); // [ var(71) , var(26) ] D[28,71] = var(54); // [ var(71) , var(28) ] D[29,71] = (-1)*var(52); // [ var(71) , var(29) ] D[30,71] = (-1)*var(51); // [ var(71) , var(30) ] D[31,71] = (-1)*var(48); // [ var(71) , var(31) ] D[32,71] = var(46); // [ var(71) , var(32) ] D[33,71] = var(45); // [ var(71) , var(33) ] D[34,71] = (-1)*var(40); // [ var(71) , var(34) ] D[35,71] = (-1)*var(73)+(-1)*var(74)+(-2)*var(75)+(-3)*var(76)+(-2)*var(77)+(-1)*var(78); // [ var(71) , var(35) ] D[36,71] = (-1)*var(2); // [ var(71) , var(36) ] D[2,72] = var(71); // [ var(72) , var(2) ] D[8,72] = (-1)*var(70); // [ var(72) , var(8) ] D[13,72] = var(69); // [ var(72) , var(13) ] D[14,72] = var(68); // [ var(72) , var(14) ] D[17,72] = (-1)*var(67); // [ var(72) , var(17) ] D[19,72] = (-1)*var(66); // [ var(72) , var(19) ] D[20,72] = (-1)*var(65); // [ var(72) , var(20) ] D[22,72] = var(64); // [ var(72) , var(22) ] D[24,72] = var(63); // [ var(72) , var(24) ] D[25,72] = var(62); // [ var(72) , var(25) ] D[26,72] = (-1)*var(61); // [ var(72) , var(26) ] D[27,72] = (-1)*var(60); // [ var(72) , var(27) ] D[28,72] = (-1)*var(58); // [ var(72) , var(28) ] D[29,72] = var(56); // [ var(72) , var(29) ] D[30,72] = var(55); // [ var(72) , var(30) ] D[31,72] = var(53); // [ var(72) , var(31) ] D[32,72] = (-1)*var(50); // [ var(72) , var(32) ] D[33,72] = (-1)*var(49); // [ var(72) , var(33) ] D[34,72] = var(44); // [ var(72) , var(34) ] D[35,72] = (-1)*var(38); // [ var(72) , var(35) ] D[36,72] = (-1)*var(73)+(-2)*var(74)+(-2)*var(75)+(-3)*var(76)+(-2)*var(77)+(-1)*var(78); // [ var(72) , var(36) ] // X(i) * X(j): D[1,3] = var(7); // [ var(3) , var(1) ] D[1,9] = var(12); // [ var(9) , var(1) ] D[1,13] = var(17); // [ var(13) , var(1) ] D[1,15] = var(18); // [ var(15) , var(1) ] D[1,19] = var(22); // [ var(19) , var(1) ] D[1,21] = var(23); // [ var(21) , var(1) ] D[1,24] = var(26); // [ var(24) , var(1) ] D[1,25] = var(27); // [ var(25) , var(1) ] D[1,28] = var(30); // [ var(28) , var(1) ] D[1,31] = var(33); // [ var(31) , var(1) ] D[2,4] = var(8); // [ var(4) , var(2) ] D[2,9] = var(13); // [ var(9) , var(2) ] D[2,10] = var(14); // [ var(10) , var(2) ] D[2,12] = var(17); // [ var(12) , var(2) ] D[2,15] = var(19); // [ var(15) , var(2) ] D[2,16] = var(20); // [ var(16) , var(2) ] D[2,18] = var(22); // [ var(18) , var(2) ] D[2,21] = var(25); // [ var(21) , var(2) ] D[2,23] = var(27); // [ var(23) , var(2) ] D[2,35] = (-1)*var(36); // [ var(35) , var(2) ] D[3,4] = var(9); // [ var(4) , var(3) ] D[3,8] = var(13); // [ var(8) , var(3) ] D[3,10] = var(15); // [ var(10) , var(3) ] D[3,14] = var(19); // [ var(14) , var(3) ] D[3,16] = var(21); // [ var(16) , var(3) ] D[3,20] = var(25); // [ var(20) , var(3) ] D[3,26] = var(29); // [ var(26) , var(3) ] D[3,30] = var(32); // [ var(30) , var(3) ] D[3,33] = var(34); // [ var(33) , var(3) ] D[4,5] = var(10); // [ var(5) , var(4) ] D[4,7] = (-1)*var(12); // [ var(7) , var(4) ] D[4,11] = var(16); // [ var(11) , var(4) ] D[4,19] = (-1)*var(24); // [ var(19) , var(4) ] D[4,22] = (-1)*var(26); // [ var(22) , var(4) ] D[4,25] = (-1)*var(28); // [ var(25) , var(4) ] D[4,27] = (-1)*var(30); // [ var(27) , var(4) ] D[4,34] = (-1)*var(35); // [ var(34) , var(4) ] D[5,6] = var(11); // [ var(6) , var(5) ] D[5,8] = (-1)*var(14); // [ var(8) , var(5) ] D[5,9] = (-1)*var(15); // [ var(9) , var(5) ] D[5,12] = (-1)*var(18); // [ var(12) , var(5) ] D[5,13] = (-1)*var(19); // [ var(13) , var(5) ] D[5,17] = (-1)*var(22); // [ var(17) , var(5) ] D[5,28] = (-1)*var(31); // [ var(28) , var(5) ] D[5,30] = (-1)*var(33); // [ var(30) , var(5) ] D[5,32] = (-1)*var(34); // [ var(32) , var(5) ] D[6,10] = (-1)*var(16); // [ var(10) , var(6) ] D[6,14] = (-1)*var(20); // [ var(14) , var(6) ] D[6,15] = (-1)*var(21); // [ var(15) , var(6) ] D[6,18] = (-1)*var(23); // [ var(18) , var(6) ] D[6,19] = (-1)*var(25); // [ var(19) , var(6) ] D[6,22] = (-1)*var(27); // [ var(22) , var(6) ] D[6,24] = (-1)*var(28); // [ var(24) , var(6) ] D[6,26] = (-1)*var(30); // [ var(26) , var(6) ] D[6,29] = (-1)*var(32); // [ var(29) , var(6) ] D[7,8] = var(17); // [ var(8) , var(7) ] D[7,10] = var(18); // [ var(10) , var(7) ] D[7,14] = var(22); // [ var(14) , var(7) ] D[7,16] = var(23); // [ var(16) , var(7) ] D[7,20] = var(27); // [ var(20) , var(7) ] D[7,24] = (-1)*var(29); // [ var(24) , var(7) ] D[7,28] = (-1)*var(32); // [ var(28) , var(7) ] D[7,31] = (-1)*var(34); // [ var(31) , var(7) ] D[8,11] = var(20); // [ var(11) , var(8) ] D[8,15] = var(24); // [ var(15) , var(8) ] D[8,18] = var(26); // [ var(18) , var(8) ] D[8,21] = var(28); // [ var(21) , var(8) ] D[8,23] = var(30); // [ var(23) , var(8) ] D[8,34] = var(36); // [ var(34) , var(8) ] D[9,11] = var(21); // [ var(11) , var(9) ] D[9,14] = var(24); // [ var(14) , var(9) ] D[9,20] = var(28); // [ var(20) , var(9) ] D[9,22] = (-1)*var(29); // [ var(22) , var(9) ] D[9,27] = (-1)*var(32); // [ var(27) , var(9) ] D[9,33] = var(35); // [ var(33) , var(9) ] D[10,13] = var(24); // [ var(13) , var(10) ] D[10,17] = var(26); // [ var(17) , var(10) ] D[10,25] = (-1)*var(31); // [ var(25) , var(10) ] D[10,27] = (-1)*var(33); // [ var(27) , var(10) ] D[10,32] = var(35); // [ var(32) , var(10) ] D[11,12] = (-1)*var(23); // [ var(12) , var(11) ] D[11,13] = (-1)*var(25); // [ var(13) , var(11) ] D[11,17] = (-1)*var(27); // [ var(17) , var(11) ] D[11,24] = var(31); // [ var(24) , var(11) ] D[11,26] = var(33); // [ var(26) , var(11) ] D[11,29] = var(34); // [ var(29) , var(11) ] D[12,14] = var(26); // [ var(14) , var(12) ] D[12,19] = var(29); // [ var(19) , var(12) ] D[12,20] = var(30); // [ var(20) , var(12) ] D[12,25] = var(32); // [ var(25) , var(12) ] D[12,31] = (-1)*var(35); // [ var(31) , var(12) ] D[13,16] = (-1)*var(28); // [ var(16) , var(13) ] D[13,18] = var(29); // [ var(18) , var(13) ] D[13,23] = var(32); // [ var(23) , var(13) ] D[13,33] = (-1)*var(36); // [ var(33) , var(13) ] D[14,21] = var(31); // [ var(21) , var(14) ] D[14,23] = var(33); // [ var(23) , var(14) ] D[14,32] = (-1)*var(36); // [ var(32) , var(14) ] D[15,17] = var(29); // [ var(17) , var(15) ] D[15,20] = var(31); // [ var(20) , var(15) ] D[15,27] = (-1)*var(34); // [ var(27) , var(15) ] D[15,30] = (-1)*var(35); // [ var(30) , var(15) ] D[16,17] = var(30); // [ var(17) , var(16) ] D[16,19] = var(31); // [ var(19) , var(16) ] D[16,22] = var(33); // [ var(22) , var(16) ] D[16,29] = (-1)*var(35); // [ var(29) , var(16) ] D[17,21] = (-1)*var(32); // [ var(21) , var(17) ] D[17,31] = var(36); // [ var(31) , var(17) ] D[18,20] = var(33); // [ var(20) , var(18) ] D[18,25] = var(34); // [ var(25) , var(18) ] D[18,28] = var(35); // [ var(28) , var(18) ] D[19,23] = var(34); // [ var(23) , var(19) ] D[19,30] = var(36); // [ var(30) , var(19) ] D[20,29] = var(36); // [ var(29) , var(20) ] D[21,22] = var(34); // [ var(22) , var(21) ] D[21,26] = var(35); // [ var(26) , var(21) ] D[22,28] = (-1)*var(36); // [ var(28) , var(22) ] D[23,24] = (-1)*var(35); // [ var(24) , var(23) ] D[24,27] = (-1)*var(36); // [ var(27) , var(24) ] D[25,26] = (-1)*var(36); // [ var(26) , var(25) ] // Y(i) * Y(j): D[37,39] = (-1)*var(43); // [ var(39) , var(37) ] D[37,45] = (-1)*var(48); // [ var(45) , var(37) ] D[37,49] = (-1)*var(53); // [ var(49) , var(37) ] D[37,51] = (-1)*var(54); // [ var(51) , var(37) ] D[37,55] = (-1)*var(58); // [ var(55) , var(37) ] D[37,57] = (-1)*var(59); // [ var(57) , var(37) ] D[37,60] = (-1)*var(62); // [ var(60) , var(37) ] D[37,61] = (-1)*var(63); // [ var(61) , var(37) ] D[37,64] = (-1)*var(66); // [ var(64) , var(37) ] D[37,67] = (-1)*var(69); // [ var(67) , var(37) ] D[38,40] = (-1)*var(44); // [ var(40) , var(38) ] D[38,45] = (-1)*var(49); // [ var(45) , var(38) ] D[38,46] = (-1)*var(50); // [ var(46) , var(38) ] D[38,48] = (-1)*var(53); // [ var(48) , var(38) ] D[38,51] = (-1)*var(55); // [ var(51) , var(38) ] D[38,52] = (-1)*var(56); // [ var(52) , var(38) ] D[38,54] = (-1)*var(58); // [ var(54) , var(38) ] D[38,57] = (-1)*var(61); // [ var(57) , var(38) ] D[38,59] = (-1)*var(63); // [ var(59) , var(38) ] D[38,71] = var(72); // [ var(71) , var(38) ] D[39,40] = (-1)*var(45); // [ var(40) , var(39) ] D[39,44] = (-1)*var(49); // [ var(44) , var(39) ] D[39,46] = (-1)*var(51); // [ var(46) , var(39) ] D[39,50] = (-1)*var(55); // [ var(50) , var(39) ] D[39,52] = (-1)*var(57); // [ var(52) , var(39) ] D[39,56] = (-1)*var(61); // [ var(56) , var(39) ] D[39,62] = (-1)*var(65); // [ var(62) , var(39) ] D[39,66] = (-1)*var(68); // [ var(66) , var(39) ] D[39,69] = (-1)*var(70); // [ var(69) , var(39) ] D[40,41] = (-1)*var(46); // [ var(41) , var(40) ] D[40,43] = var(48); // [ var(43) , var(40) ] D[40,47] = (-1)*var(52); // [ var(47) , var(40) ] D[40,55] = var(60); // [ var(55) , var(40) ] D[40,58] = var(62); // [ var(58) , var(40) ] D[40,61] = var(64); // [ var(61) , var(40) ] D[40,63] = var(66); // [ var(63) , var(40) ] D[40,70] = var(71); // [ var(70) , var(40) ] D[41,42] = (-1)*var(47); // [ var(42) , var(41) ] D[41,44] = var(50); // [ var(44) , var(41) ] D[41,45] = var(51); // [ var(45) , var(41) ] D[41,48] = var(54); // [ var(48) , var(41) ] D[41,49] = var(55); // [ var(49) , var(41) ] D[41,53] = var(58); // [ var(53) , var(41) ] D[41,64] = var(67); // [ var(64) , var(41) ] D[41,66] = var(69); // [ var(66) , var(41) ] D[41,68] = var(70); // [ var(68) , var(41) ] D[42,46] = var(52); // [ var(46) , var(42) ] D[42,50] = var(56); // [ var(50) , var(42) ] D[42,51] = var(57); // [ var(51) , var(42) ] D[42,54] = var(59); // [ var(54) , var(42) ] D[42,55] = var(61); // [ var(55) , var(42) ] D[42,58] = var(63); // [ var(58) , var(42) ] D[42,60] = var(64); // [ var(60) , var(42) ] D[42,62] = var(66); // [ var(62) , var(42) ] D[42,65] = var(68); // [ var(65) , var(42) ] D[43,44] = (-1)*var(53); // [ var(44) , var(43) ] D[43,46] = (-1)*var(54); // [ var(46) , var(43) ] D[43,50] = (-1)*var(58); // [ var(50) , var(43) ] D[43,52] = (-1)*var(59); // [ var(52) , var(43) ] D[43,56] = (-1)*var(63); // [ var(56) , var(43) ] D[43,60] = var(65); // [ var(60) , var(43) ] D[43,64] = var(68); // [ var(64) , var(43) ] D[43,67] = var(70); // [ var(67) , var(43) ] D[44,47] = (-1)*var(56); // [ var(47) , var(44) ] D[44,51] = (-1)*var(60); // [ var(51) , var(44) ] D[44,54] = (-1)*var(62); // [ var(54) , var(44) ] D[44,57] = (-1)*var(64); // [ var(57) , var(44) ] D[44,59] = (-1)*var(66); // [ var(59) , var(44) ] D[44,70] = (-1)*var(72); // [ var(70) , var(44) ] D[45,47] = (-1)*var(57); // [ var(47) , var(45) ] D[45,50] = (-1)*var(60); // [ var(50) , var(45) ] D[45,56] = (-1)*var(64); // [ var(56) , var(45) ] D[45,58] = var(65); // [ var(58) , var(45) ] D[45,63] = var(68); // [ var(63) , var(45) ] D[45,69] = (-1)*var(71); // [ var(69) , var(45) ] D[46,49] = (-1)*var(60); // [ var(49) , var(46) ] D[46,53] = (-1)*var(62); // [ var(53) , var(46) ] D[46,61] = var(67); // [ var(61) , var(46) ] D[46,63] = var(69); // [ var(63) , var(46) ] D[46,68] = (-1)*var(71); // [ var(68) , var(46) ] D[47,48] = var(59); // [ var(48) , var(47) ] D[47,49] = var(61); // [ var(49) , var(47) ] D[47,53] = var(63); // [ var(53) , var(47) ] D[47,60] = (-1)*var(67); // [ var(60) , var(47) ] D[47,62] = (-1)*var(69); // [ var(62) , var(47) ] D[47,65] = (-1)*var(70); // [ var(65) , var(47) ] D[48,50] = (-1)*var(62); // [ var(50) , var(48) ] D[48,55] = (-1)*var(65); // [ var(55) , var(48) ] D[48,56] = (-1)*var(66); // [ var(56) , var(48) ] D[48,61] = (-1)*var(68); // [ var(61) , var(48) ] D[48,67] = var(71); // [ var(67) , var(48) ] D[49,52] = var(64); // [ var(52) , var(49) ] D[49,54] = (-1)*var(65); // [ var(54) , var(49) ] D[49,59] = (-1)*var(68); // [ var(59) , var(49) ] D[49,69] = var(72); // [ var(69) , var(49) ] D[50,57] = (-1)*var(67); // [ var(57) , var(50) ] D[50,59] = (-1)*var(69); // [ var(59) , var(50) ] D[50,68] = var(72); // [ var(68) , var(50) ] D[51,53] = (-1)*var(65); // [ var(53) , var(51) ] D[51,56] = (-1)*var(67); // [ var(56) , var(51) ] D[51,63] = var(70); // [ var(63) , var(51) ] D[51,66] = var(71); // [ var(66) , var(51) ] D[52,53] = (-1)*var(66); // [ var(53) , var(52) ] D[52,55] = (-1)*var(67); // [ var(55) , var(52) ] D[52,58] = (-1)*var(69); // [ var(58) , var(52) ] D[52,65] = var(71); // [ var(65) , var(52) ] D[53,57] = var(68); // [ var(57) , var(53) ] D[53,67] = (-1)*var(72); // [ var(67) , var(53) ] D[54,56] = (-1)*var(69); // [ var(56) , var(54) ] D[54,61] = (-1)*var(70); // [ var(61) , var(54) ] D[54,64] = (-1)*var(71); // [ var(64) , var(54) ] D[55,59] = (-1)*var(70); // [ var(59) , var(55) ] D[55,66] = (-1)*var(72); // [ var(66) , var(55) ] D[56,65] = (-1)*var(72); // [ var(65) , var(56) ] D[57,58] = (-1)*var(70); // [ var(58) , var(57) ] D[57,62] = (-1)*var(71); // [ var(62) , var(57) ] D[58,64] = var(72); // [ var(64) , var(58) ] D[59,60] = var(71); // [ var(60) , var(59) ] D[60,63] = var(72); // [ var(63) , var(60) ] D[61,62] = var(72); // [ var(62) , var(61) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUe6(); ncAlgebra; setring ncAlgebra; // ... 1008 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: e7(Q) has the type: E7, and defined by: proc makeUe7(list #) "USAGE: makeUe7([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(e_7) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(e_7) is derived from the Chevalley representation of e_7, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUe7; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..63),Y(1..63),H(1..7)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,127] = (2)*var(1); // [ var(127) , var(1) ] D[3,127] = (-1)*var(3); // [ var(127) , var(3) ] D[8,127] = var(8); // [ var(127) , var(8) ] D[10,127] = (-1)*var(10); // [ var(127) , var(10) ] D[14,127] = var(14); // [ var(127) , var(14) ] D[15,127] = (-1)*var(15); // [ var(127) , var(15) ] D[17,127] = (-1)*var(17); // [ var(127) , var(17) ] D[20,127] = var(20); // [ var(127) , var(20) ] D[21,127] = var(21); // [ var(127) , var(21) ] D[22,127] = (-1)*var(22); // [ var(127) , var(22) ] D[24,127] = (-1)*var(24); // [ var(127) , var(24) ] D[26,127] = var(26); // [ var(127) , var(26) ] D[27,127] = var(27); // [ var(127) , var(27) ] D[28,127] = (-1)*var(28); // [ var(127) , var(28) ] D[29,127] = (-1)*var(29); // [ var(127) , var(29) ] D[31,127] = (-1)*var(31); // [ var(127) , var(31) ] D[32,127] = var(32); // [ var(127) , var(32) ] D[33,127] = var(33); // [ var(127) , var(33) ] D[34,127] = var(34); // [ var(127) , var(34) ] D[35,127] = (-1)*var(35); // [ var(127) , var(35) ] D[36,127] = (-1)*var(36); // [ var(127) , var(36) ] D[38,127] = var(38); // [ var(127) , var(38) ] D[39,127] = var(39); // [ var(127) , var(39) ] D[40,127] = (-1)*var(40); // [ var(127) , var(40) ] D[41,127] = (-1)*var(41); // [ var(127) , var(41) ] D[43,127] = var(43); // [ var(127) , var(43) ] D[44,127] = var(44); // [ var(127) , var(44) ] D[45,127] = (-1)*var(45); // [ var(127) , var(45) ] D[48,127] = var(48); // [ var(127) , var(48) ] D[49,127] = (-1)*var(49); // [ var(127) , var(49) ] D[52,127] = var(52); // [ var(127) , var(52) ] D[62,127] = (-1)*var(62); // [ var(127) , var(62) ] D[63,127] = var(63); // [ var(127) , var(63) ] D[2,128] = (2)*var(2); // [ var(128) , var(2) ] D[4,128] = (-1)*var(4); // [ var(128) , var(4) ] D[9,128] = var(9); // [ var(128) , var(9) ] D[10,128] = (-1)*var(10); // [ var(128) , var(10) ] D[11,128] = (-1)*var(11); // [ var(128) , var(11) ] D[14,128] = (-1)*var(14); // [ var(128) , var(14) ] D[15,128] = var(15); // [ var(128) , var(15) ] D[16,128] = var(16); // [ var(128) , var(16) ] D[17,128] = (-1)*var(17); // [ var(128) , var(17) ] D[18,128] = (-1)*var(18); // [ var(128) , var(18) ] D[20,128] = var(20); // [ var(128) , var(20) ] D[21,128] = (-1)*var(21); // [ var(128) , var(21) ] D[22,128] = var(22); // [ var(128) , var(22) ] D[23,128] = var(23); // [ var(128) , var(23) ] D[24,128] = (-1)*var(24); // [ var(128) , var(24) ] D[25,128] = (-1)*var(25); // [ var(128) , var(25) ] D[26,128] = var(26); // [ var(128) , var(26) ] D[27,128] = (-1)*var(27); // [ var(128) , var(27) ] D[29,128] = var(29); // [ var(128) , var(29) ] D[30,128] = var(30); // [ var(128) , var(30) ] D[31,128] = (-1)*var(31); // [ var(128) , var(31) ] D[33,128] = var(33); // [ var(128) , var(33) ] D[34,128] = (-1)*var(34); // [ var(128) , var(34) ] D[36,128] = var(36); // [ var(128) , var(36) ] D[39,128] = var(39); // [ var(128) , var(39) ] D[50,128] = (-1)*var(50); // [ var(128) , var(50) ] D[53,128] = var(53); // [ var(128) , var(53) ] D[54,128] = (-1)*var(54); // [ var(128) , var(54) ] D[56,128] = var(56); // [ var(128) , var(56) ] D[57,128] = (-1)*var(57); // [ var(128) , var(57) ] D[58,128] = var(58); // [ var(128) , var(58) ] D[59,128] = (-1)*var(59); // [ var(128) , var(59) ] D[60,128] = var(60); // [ var(128) , var(60) ] D[1,129] = (-1)*var(1); // [ var(129) , var(1) ] D[3,129] = (2)*var(3); // [ var(129) , var(3) ] D[4,129] = (-1)*var(4); // [ var(129) , var(4) ] D[8,129] = var(8); // [ var(129) , var(8) ] D[9,129] = (-1)*var(9); // [ var(129) , var(9) ] D[10,129] = var(10); // [ var(129) , var(10) ] D[11,129] = (-1)*var(11); // [ var(129) , var(11) ] D[15,129] = var(15); // [ var(129) , var(15) ] D[16,129] = (-1)*var(16); // [ var(129) , var(16) ] D[17,129] = var(17); // [ var(129) , var(17) ] D[18,129] = (-1)*var(18); // [ var(129) , var(18) ] D[22,129] = var(22); // [ var(129) , var(22) ] D[23,129] = (-1)*var(23); // [ var(129) , var(23) ] D[24,129] = var(24); // [ var(129) , var(24) ] D[25,129] = (-1)*var(25); // [ var(129) , var(25) ] D[29,129] = var(29); // [ var(129) , var(29) ] D[30,129] = (-1)*var(30); // [ var(129) , var(30) ] D[31,129] = var(31); // [ var(129) , var(31) ] D[32,129] = (-1)*var(32); // [ var(129) , var(32) ] D[36,129] = var(36); // [ var(129) , var(36) ] D[37,129] = var(37); // [ var(129) , var(37) ] D[38,129] = (-1)*var(38); // [ var(129) , var(38) ] D[42,129] = var(42); // [ var(129) , var(42) ] D[43,129] = (-1)*var(43); // [ var(129) , var(43) ] D[44,129] = (-1)*var(44); // [ var(129) , var(44) ] D[46,129] = var(46); // [ var(129) , var(46) ] D[47,129] = var(47); // [ var(129) , var(47) ] D[48,129] = (-1)*var(48); // [ var(129) , var(48) ] D[51,129] = var(51); // [ var(129) , var(51) ] D[52,129] = (-1)*var(52); // [ var(129) , var(52) ] D[55,129] = var(55); // [ var(129) , var(55) ] D[61,129] = (-1)*var(61); // [ var(129) , var(61) ] D[62,129] = var(62); // [ var(129) , var(62) ] D[2,130] = (-1)*var(2); // [ var(130) , var(2) ] D[3,130] = (-1)*var(3); // [ var(130) , var(3) ] D[4,130] = (2)*var(4); // [ var(130) , var(4) ] D[5,130] = (-1)*var(5); // [ var(130) , var(5) ] D[8,130] = (-1)*var(8); // [ var(130) , var(8) ] D[9,130] = var(9); // [ var(130) , var(9) ] D[10,130] = var(10); // [ var(130) , var(10) ] D[11,130] = var(11); // [ var(130) , var(11) ] D[12,130] = (-1)*var(12); // [ var(130) , var(12) ] D[14,130] = var(14); // [ var(130) , var(14) ] D[18,130] = var(18); // [ var(130) , var(18) ] D[19,130] = (-1)*var(19); // [ var(130) , var(19) ] D[22,130] = (-1)*var(22); // [ var(130) , var(22) ] D[25,130] = var(25); // [ var(130) , var(25) ] D[26,130] = (-1)*var(26); // [ var(130) , var(26) ] D[28,130] = var(28); // [ var(130) , var(28) ] D[29,130] = (-1)*var(29); // [ var(130) , var(29) ] D[32,130] = var(32); // [ var(130) , var(32) ] D[33,130] = (-1)*var(33); // [ var(130) , var(33) ] D[35,130] = var(35); // [ var(130) , var(35) ] D[36,130] = (-1)*var(36); // [ var(130) , var(36) ] D[38,130] = var(38); // [ var(130) , var(38) ] D[39,130] = (-1)*var(39); // [ var(130) , var(39) ] D[41,130] = var(41); // [ var(130) , var(41) ] D[44,130] = var(44); // [ var(130) , var(44) ] D[46,130] = (-1)*var(46); // [ var(130) , var(46) ] D[50,130] = var(50); // [ var(130) , var(50) ] D[51,130] = (-1)*var(51); // [ var(130) , var(51) ] D[54,130] = var(54); // [ var(130) , var(54) ] D[55,130] = (-1)*var(55); // [ var(130) , var(55) ] D[57,130] = var(57); // [ var(130) , var(57) ] D[60,130] = (-1)*var(60); // [ var(130) , var(60) ] D[61,130] = var(61); // [ var(130) , var(61) ] D[4,131] = (-1)*var(4); // [ var(131) , var(4) ] D[5,131] = (2)*var(5); // [ var(131) , var(5) ] D[6,131] = (-1)*var(6); // [ var(131) , var(6) ] D[9,131] = (-1)*var(9); // [ var(131) , var(9) ] D[10,131] = (-1)*var(10); // [ var(131) , var(10) ] D[11,131] = var(11); // [ var(131) , var(11) ] D[12,131] = var(12); // [ var(131) , var(12) ] D[13,131] = (-1)*var(13); // [ var(131) , var(13) ] D[14,131] = (-1)*var(14); // [ var(131) , var(14) ] D[15,131] = (-1)*var(15); // [ var(131) , var(15) ] D[16,131] = var(16); // [ var(131) , var(16) ] D[17,131] = var(17); // [ var(131) , var(17) ] D[19,131] = var(19); // [ var(131) , var(19) ] D[20,131] = (-1)*var(20); // [ var(131) , var(20) ] D[21,131] = var(21); // [ var(131) , var(21) ] D[22,131] = var(22); // [ var(131) , var(22) ] D[26,131] = var(26); // [ var(131) , var(26) ] D[35,131] = (-1)*var(35); // [ var(131) , var(35) ] D[38,131] = (-1)*var(38); // [ var(131) , var(38) ] D[40,131] = var(40); // [ var(131) , var(40) ] D[41,131] = (-1)*var(41); // [ var(131) , var(41) ] D[42,131] = (-1)*var(42); // [ var(131) , var(42) ] D[43,131] = var(43); // [ var(131) , var(43) ] D[44,131] = (-1)*var(44); // [ var(131) , var(44) ] D[45,131] = var(45); // [ var(131) , var(45) ] D[46,131] = var(46); // [ var(131) , var(46) ] D[47,131] = (-1)*var(47); // [ var(131) , var(47) ] D[48,131] = var(48); // [ var(131) , var(48) ] D[51,131] = var(51); // [ var(131) , var(51) ] D[57,131] = (-1)*var(57); // [ var(131) , var(57) ] D[58,131] = (-1)*var(58); // [ var(131) , var(58) ] D[59,131] = var(59); // [ var(131) , var(59) ] D[60,131] = var(60); // [ var(131) , var(60) ] D[5,132] = (-1)*var(5); // [ var(132) , var(5) ] D[6,132] = (2)*var(6); // [ var(132) , var(6) ] D[7,132] = (-1)*var(7); // [ var(132) , var(7) ] D[11,132] = (-1)*var(11); // [ var(132) , var(11) ] D[12,132] = var(12); // [ var(132) , var(12) ] D[13,132] = var(13); // [ var(132) , var(13) ] D[16,132] = (-1)*var(16); // [ var(132) , var(16) ] D[17,132] = (-1)*var(17); // [ var(132) , var(17) ] D[18,132] = var(18); // [ var(132) , var(18) ] D[21,132] = (-1)*var(21); // [ var(132) , var(21) ] D[22,132] = (-1)*var(22); // [ var(132) , var(22) ] D[23,132] = var(23); // [ var(132) , var(23) ] D[24,132] = var(24); // [ var(132) , var(24) ] D[26,132] = (-1)*var(26); // [ var(132) , var(26) ] D[27,132] = var(27); // [ var(132) , var(27) ] D[28,132] = (-1)*var(28); // [ var(132) , var(28) ] D[29,132] = var(29); // [ var(132) , var(29) ] D[32,132] = (-1)*var(32); // [ var(132) , var(32) ] D[33,132] = var(33); // [ var(132) , var(33) ] D[35,132] = var(35); // [ var(132) , var(35) ] D[37,132] = (-1)*var(37); // [ var(132) , var(37) ] D[38,132] = var(38); // [ var(132) , var(38) ] D[42,132] = var(42); // [ var(132) , var(42) ] D[45,132] = (-1)*var(45); // [ var(132) , var(45) ] D[48,132] = (-1)*var(48); // [ var(132) , var(48) ] D[49,132] = var(49); // [ var(132) , var(49) ] D[51,132] = (-1)*var(51); // [ var(132) , var(51) ] D[52,132] = var(52); // [ var(132) , var(52) ] D[54,132] = (-1)*var(54); // [ var(132) , var(54) ] D[55,132] = var(55); // [ var(132) , var(55) ] D[56,132] = (-1)*var(56); // [ var(132) , var(56) ] D[57,132] = var(57); // [ var(132) , var(57) ] D[58,132] = var(58); // [ var(132) , var(58) ] D[6,133] = (-1)*var(6); // [ var(133) , var(6) ] D[7,133] = (2)*var(7); // [ var(133) , var(7) ] D[12,133] = (-1)*var(12); // [ var(133) , var(12) ] D[13,133] = var(13); // [ var(133) , var(13) ] D[18,133] = (-1)*var(18); // [ var(133) , var(18) ] D[19,133] = var(19); // [ var(133) , var(19) ] D[23,133] = (-1)*var(23); // [ var(133) , var(23) ] D[24,133] = (-1)*var(24); // [ var(133) , var(24) ] D[25,133] = var(25); // [ var(133) , var(25) ] D[27,133] = (-1)*var(27); // [ var(133) , var(27) ] D[29,133] = (-1)*var(29); // [ var(133) , var(29) ] D[30,133] = var(30); // [ var(133) , var(30) ] D[31,133] = var(31); // [ var(133) , var(31) ] D[33,133] = (-1)*var(33); // [ var(133) , var(33) ] D[34,133] = var(34); // [ var(133) , var(34) ] D[35,133] = (-1)*var(35); // [ var(133) , var(35) ] D[36,133] = var(36); // [ var(133) , var(36) ] D[38,133] = (-1)*var(38); // [ var(133) , var(38) ] D[39,133] = var(39); // [ var(133) , var(39) ] D[40,133] = (-1)*var(40); // [ var(133) , var(40) ] D[41,133] = var(41); // [ var(133) , var(41) ] D[42,133] = (-1)*var(42); // [ var(133) , var(42) ] D[43,133] = (-1)*var(43); // [ var(133) , var(43) ] D[44,133] = var(44); // [ var(133) , var(44) ] D[45,133] = var(45); // [ var(133) , var(45) ] D[46,133] = (-1)*var(46); // [ var(133) , var(46) ] D[47,133] = var(47); // [ var(133) , var(47) ] D[48,133] = var(48); // [ var(133) , var(48) ] D[50,133] = (-1)*var(50); // [ var(133) , var(50) ] D[51,133] = var(51); // [ var(133) , var(51) ] D[53,133] = (-1)*var(53); // [ var(133) , var(53) ] D[54,133] = var(54); // [ var(133) , var(54) ] D[56,133] = var(56); // [ var(133) , var(56) ] // H(i) * Y(j): D[64,127] = (-2)*var(64); // [ var(127) , var(64) ] D[66,127] = var(66); // [ var(127) , var(66) ] D[71,127] = (-1)*var(71); // [ var(127) , var(71) ] D[73,127] = var(73); // [ var(127) , var(73) ] D[77,127] = (-1)*var(77); // [ var(127) , var(77) ] D[78,127] = var(78); // [ var(127) , var(78) ] D[80,127] = var(80); // [ var(127) , var(80) ] D[83,127] = (-1)*var(83); // [ var(127) , var(83) ] D[84,127] = (-1)*var(84); // [ var(127) , var(84) ] D[85,127] = var(85); // [ var(127) , var(85) ] D[87,127] = var(87); // [ var(127) , var(87) ] D[89,127] = (-1)*var(89); // [ var(127) , var(89) ] D[90,127] = (-1)*var(90); // [ var(127) , var(90) ] D[91,127] = var(91); // [ var(127) , var(91) ] D[92,127] = var(92); // [ var(127) , var(92) ] D[94,127] = var(94); // [ var(127) , var(94) ] D[95,127] = (-1)*var(95); // [ var(127) , var(95) ] D[96,127] = (-1)*var(96); // [ var(127) , var(96) ] D[97,127] = (-1)*var(97); // [ var(127) , var(97) ] D[98,127] = var(98); // [ var(127) , var(98) ] D[99,127] = var(99); // [ var(127) , var(99) ] D[101,127] = (-1)*var(101); // [ var(127) , var(101) ] D[102,127] = (-1)*var(102); // [ var(127) , var(102) ] D[103,127] = var(103); // [ var(127) , var(103) ] D[104,127] = var(104); // [ var(127) , var(104) ] D[106,127] = (-1)*var(106); // [ var(127) , var(106) ] D[107,127] = (-1)*var(107); // [ var(127) , var(107) ] D[108,127] = var(108); // [ var(127) , var(108) ] D[111,127] = (-1)*var(111); // [ var(127) , var(111) ] D[112,127] = var(112); // [ var(127) , var(112) ] D[115,127] = (-1)*var(115); // [ var(127) , var(115) ] D[125,127] = var(125); // [ var(127) , var(125) ] D[126,127] = (-1)*var(126); // [ var(127) , var(126) ] D[65,128] = (-2)*var(65); // [ var(128) , var(65) ] D[67,128] = var(67); // [ var(128) , var(67) ] D[72,128] = (-1)*var(72); // [ var(128) , var(72) ] D[73,128] = var(73); // [ var(128) , var(73) ] D[74,128] = var(74); // [ var(128) , var(74) ] D[77,128] = var(77); // [ var(128) , var(77) ] D[78,128] = (-1)*var(78); // [ var(128) , var(78) ] D[79,128] = (-1)*var(79); // [ var(128) , var(79) ] D[80,128] = var(80); // [ var(128) , var(80) ] D[81,128] = var(81); // [ var(128) , var(81) ] D[83,128] = (-1)*var(83); // [ var(128) , var(83) ] D[84,128] = var(84); // [ var(128) , var(84) ] D[85,128] = (-1)*var(85); // [ var(128) , var(85) ] D[86,128] = (-1)*var(86); // [ var(128) , var(86) ] D[87,128] = var(87); // [ var(128) , var(87) ] D[88,128] = var(88); // [ var(128) , var(88) ] D[89,128] = (-1)*var(89); // [ var(128) , var(89) ] D[90,128] = var(90); // [ var(128) , var(90) ] D[92,128] = (-1)*var(92); // [ var(128) , var(92) ] D[93,128] = (-1)*var(93); // [ var(128) , var(93) ] D[94,128] = var(94); // [ var(128) , var(94) ] D[96,128] = (-1)*var(96); // [ var(128) , var(96) ] D[97,128] = var(97); // [ var(128) , var(97) ] D[99,128] = (-1)*var(99); // [ var(128) , var(99) ] D[102,128] = (-1)*var(102); // [ var(128) , var(102) ] D[113,128] = var(113); // [ var(128) , var(113) ] D[116,128] = (-1)*var(116); // [ var(128) , var(116) ] D[117,128] = var(117); // [ var(128) , var(117) ] D[119,128] = (-1)*var(119); // [ var(128) , var(119) ] D[120,128] = var(120); // [ var(128) , var(120) ] D[121,128] = (-1)*var(121); // [ var(128) , var(121) ] D[122,128] = var(122); // [ var(128) , var(122) ] D[123,128] = (-1)*var(123); // [ var(128) , var(123) ] D[64,129] = var(64); // [ var(129) , var(64) ] D[66,129] = (-2)*var(66); // [ var(129) , var(66) ] D[67,129] = var(67); // [ var(129) , var(67) ] D[71,129] = (-1)*var(71); // [ var(129) , var(71) ] D[72,129] = var(72); // [ var(129) , var(72) ] D[73,129] = (-1)*var(73); // [ var(129) , var(73) ] D[74,129] = var(74); // [ var(129) , var(74) ] D[78,129] = (-1)*var(78); // [ var(129) , var(78) ] D[79,129] = var(79); // [ var(129) , var(79) ] D[80,129] = (-1)*var(80); // [ var(129) , var(80) ] D[81,129] = var(81); // [ var(129) , var(81) ] D[85,129] = (-1)*var(85); // [ var(129) , var(85) ] D[86,129] = var(86); // [ var(129) , var(86) ] D[87,129] = (-1)*var(87); // [ var(129) , var(87) ] D[88,129] = var(88); // [ var(129) , var(88) ] D[92,129] = (-1)*var(92); // [ var(129) , var(92) ] D[93,129] = var(93); // [ var(129) , var(93) ] D[94,129] = (-1)*var(94); // [ var(129) , var(94) ] D[95,129] = var(95); // [ var(129) , var(95) ] D[99,129] = (-1)*var(99); // [ var(129) , var(99) ] D[100,129] = (-1)*var(100); // [ var(129) , var(100) ] D[101,129] = var(101); // [ var(129) , var(101) ] D[105,129] = (-1)*var(105); // [ var(129) , var(105) ] D[106,129] = var(106); // [ var(129) , var(106) ] D[107,129] = var(107); // [ var(129) , var(107) ] D[109,129] = (-1)*var(109); // [ var(129) , var(109) ] D[110,129] = (-1)*var(110); // [ var(129) , var(110) ] D[111,129] = var(111); // [ var(129) , var(111) ] D[114,129] = (-1)*var(114); // [ var(129) , var(114) ] D[115,129] = var(115); // [ var(129) , var(115) ] D[118,129] = (-1)*var(118); // [ var(129) , var(118) ] D[124,129] = var(124); // [ var(129) , var(124) ] D[125,129] = (-1)*var(125); // [ var(129) , var(125) ] D[65,130] = var(65); // [ var(130) , var(65) ] D[66,130] = var(66); // [ var(130) , var(66) ] D[67,130] = (-2)*var(67); // [ var(130) , var(67) ] D[68,130] = var(68); // [ var(130) , var(68) ] D[71,130] = var(71); // [ var(130) , var(71) ] D[72,130] = (-1)*var(72); // [ var(130) , var(72) ] D[73,130] = (-1)*var(73); // [ var(130) , var(73) ] D[74,130] = (-1)*var(74); // [ var(130) , var(74) ] D[75,130] = var(75); // [ var(130) , var(75) ] D[77,130] = (-1)*var(77); // [ var(130) , var(77) ] D[81,130] = (-1)*var(81); // [ var(130) , var(81) ] D[82,130] = var(82); // [ var(130) , var(82) ] D[85,130] = var(85); // [ var(130) , var(85) ] D[88,130] = (-1)*var(88); // [ var(130) , var(88) ] D[89,130] = var(89); // [ var(130) , var(89) ] D[91,130] = (-1)*var(91); // [ var(130) , var(91) ] D[92,130] = var(92); // [ var(130) , var(92) ] D[95,130] = (-1)*var(95); // [ var(130) , var(95) ] D[96,130] = var(96); // [ var(130) , var(96) ] D[98,130] = (-1)*var(98); // [ var(130) , var(98) ] D[99,130] = var(99); // [ var(130) , var(99) ] D[101,130] = (-1)*var(101); // [ var(130) , var(101) ] D[102,130] = var(102); // [ var(130) , var(102) ] D[104,130] = (-1)*var(104); // [ var(130) , var(104) ] D[107,130] = (-1)*var(107); // [ var(130) , var(107) ] D[109,130] = var(109); // [ var(130) , var(109) ] D[113,130] = (-1)*var(113); // [ var(130) , var(113) ] D[114,130] = var(114); // [ var(130) , var(114) ] D[117,130] = (-1)*var(117); // [ var(130) , var(117) ] D[118,130] = var(118); // [ var(130) , var(118) ] D[120,130] = (-1)*var(120); // [ var(130) , var(120) ] D[123,130] = var(123); // [ var(130) , var(123) ] D[124,130] = (-1)*var(124); // [ var(130) , var(124) ] D[67,131] = var(67); // [ var(131) , var(67) ] D[68,131] = (-2)*var(68); // [ var(131) , var(68) ] D[69,131] = var(69); // [ var(131) , var(69) ] D[72,131] = var(72); // [ var(131) , var(72) ] D[73,131] = var(73); // [ var(131) , var(73) ] D[74,131] = (-1)*var(74); // [ var(131) , var(74) ] D[75,131] = (-1)*var(75); // [ var(131) , var(75) ] D[76,131] = var(76); // [ var(131) , var(76) ] D[77,131] = var(77); // [ var(131) , var(77) ] D[78,131] = var(78); // [ var(131) , var(78) ] D[79,131] = (-1)*var(79); // [ var(131) , var(79) ] D[80,131] = (-1)*var(80); // [ var(131) , var(80) ] D[82,131] = (-1)*var(82); // [ var(131) , var(82) ] D[83,131] = var(83); // [ var(131) , var(83) ] D[84,131] = (-1)*var(84); // [ var(131) , var(84) ] D[85,131] = (-1)*var(85); // [ var(131) , var(85) ] D[89,131] = (-1)*var(89); // [ var(131) , var(89) ] D[98,131] = var(98); // [ var(131) , var(98) ] D[101,131] = var(101); // [ var(131) , var(101) ] D[103,131] = (-1)*var(103); // [ var(131) , var(103) ] D[104,131] = var(104); // [ var(131) , var(104) ] D[105,131] = var(105); // [ var(131) , var(105) ] D[106,131] = (-1)*var(106); // [ var(131) , var(106) ] D[107,131] = var(107); // [ var(131) , var(107) ] D[108,131] = (-1)*var(108); // [ var(131) , var(108) ] D[109,131] = (-1)*var(109); // [ var(131) , var(109) ] D[110,131] = var(110); // [ var(131) , var(110) ] D[111,131] = (-1)*var(111); // [ var(131) , var(111) ] D[114,131] = (-1)*var(114); // [ var(131) , var(114) ] D[120,131] = var(120); // [ var(131) , var(120) ] D[121,131] = var(121); // [ var(131) , var(121) ] D[122,131] = (-1)*var(122); // [ var(131) , var(122) ] D[123,131] = (-1)*var(123); // [ var(131) , var(123) ] D[68,132] = var(68); // [ var(132) , var(68) ] D[69,132] = (-2)*var(69); // [ var(132) , var(69) ] D[70,132] = var(70); // [ var(132) , var(70) ] D[74,132] = var(74); // [ var(132) , var(74) ] D[75,132] = (-1)*var(75); // [ var(132) , var(75) ] D[76,132] = (-1)*var(76); // [ var(132) , var(76) ] D[79,132] = var(79); // [ var(132) , var(79) ] D[80,132] = var(80); // [ var(132) , var(80) ] D[81,132] = (-1)*var(81); // [ var(132) , var(81) ] D[84,132] = var(84); // [ var(132) , var(84) ] D[85,132] = var(85); // [ var(132) , var(85) ] D[86,132] = (-1)*var(86); // [ var(132) , var(86) ] D[87,132] = (-1)*var(87); // [ var(132) , var(87) ] D[89,132] = var(89); // [ var(132) , var(89) ] D[90,132] = (-1)*var(90); // [ var(132) , var(90) ] D[91,132] = var(91); // [ var(132) , var(91) ] D[92,132] = (-1)*var(92); // [ var(132) , var(92) ] D[95,132] = var(95); // [ var(132) , var(95) ] D[96,132] = (-1)*var(96); // [ var(132) , var(96) ] D[98,132] = (-1)*var(98); // [ var(132) , var(98) ] D[100,132] = var(100); // [ var(132) , var(100) ] D[101,132] = (-1)*var(101); // [ var(132) , var(101) ] D[105,132] = (-1)*var(105); // [ var(132) , var(105) ] D[108,132] = var(108); // [ var(132) , var(108) ] D[111,132] = var(111); // [ var(132) , var(111) ] D[112,132] = (-1)*var(112); // [ var(132) , var(112) ] D[114,132] = var(114); // [ var(132) , var(114) ] D[115,132] = (-1)*var(115); // [ var(132) , var(115) ] D[117,132] = var(117); // [ var(132) , var(117) ] D[118,132] = (-1)*var(118); // [ var(132) , var(118) ] D[119,132] = var(119); // [ var(132) , var(119) ] D[120,132] = (-1)*var(120); // [ var(132) , var(120) ] D[121,132] = (-1)*var(121); // [ var(132) , var(121) ] D[69,133] = var(69); // [ var(133) , var(69) ] D[70,133] = (-2)*var(70); // [ var(133) , var(70) ] D[75,133] = var(75); // [ var(133) , var(75) ] D[76,133] = (-1)*var(76); // [ var(133) , var(76) ] D[81,133] = var(81); // [ var(133) , var(81) ] D[82,133] = (-1)*var(82); // [ var(133) , var(82) ] D[86,133] = var(86); // [ var(133) , var(86) ] D[87,133] = var(87); // [ var(133) , var(87) ] D[88,133] = (-1)*var(88); // [ var(133) , var(88) ] D[90,133] = var(90); // [ var(133) , var(90) ] D[92,133] = var(92); // [ var(133) , var(92) ] D[93,133] = (-1)*var(93); // [ var(133) , var(93) ] D[94,133] = (-1)*var(94); // [ var(133) , var(94) ] D[96,133] = var(96); // [ var(133) , var(96) ] D[97,133] = (-1)*var(97); // [ var(133) , var(97) ] D[98,133] = var(98); // [ var(133) , var(98) ] D[99,133] = (-1)*var(99); // [ var(133) , var(99) ] D[101,133] = var(101); // [ var(133) , var(101) ] D[102,133] = (-1)*var(102); // [ var(133) , var(102) ] D[103,133] = var(103); // [ var(133) , var(103) ] D[104,133] = (-1)*var(104); // [ var(133) , var(104) ] D[105,133] = var(105); // [ var(133) , var(105) ] D[106,133] = var(106); // [ var(133) , var(106) ] D[107,133] = (-1)*var(107); // [ var(133) , var(107) ] D[108,133] = (-1)*var(108); // [ var(133) , var(108) ] D[109,133] = var(109); // [ var(133) , var(109) ] D[110,133] = (-1)*var(110); // [ var(133) , var(110) ] D[111,133] = (-1)*var(111); // [ var(133) , var(111) ] D[113,133] = var(113); // [ var(133) , var(113) ] D[114,133] = (-1)*var(114); // [ var(133) , var(114) ] D[116,133] = var(116); // [ var(133) , var(116) ] D[117,133] = (-1)*var(117); // [ var(133) , var(117) ] D[119,133] = (-1)*var(119); // [ var(133) , var(119) ] // Y(i) * X(j): D[1,64] = (-1)*var(127); // [ var(64) , var(1) ] D[8,64] = (-1)*var(3); // [ var(64) , var(8) ] D[14,64] = (-1)*var(10); // [ var(64) , var(14) ] D[20,64] = (-1)*var(15); // [ var(64) , var(20) ] D[21,64] = (-1)*var(17); // [ var(64) , var(21) ] D[26,64] = (-1)*var(22); // [ var(64) , var(26) ] D[27,64] = (-1)*var(24); // [ var(64) , var(27) ] D[32,64] = (-1)*var(28); // [ var(64) , var(32) ] D[33,64] = (-1)*var(29); // [ var(64) , var(33) ] D[34,64] = (-1)*var(31); // [ var(64) , var(34) ] D[38,64] = (-1)*var(35); // [ var(64) , var(38) ] D[39,64] = (-1)*var(36); // [ var(64) , var(39) ] D[43,64] = (-1)*var(40); // [ var(64) , var(43) ] D[44,64] = (-1)*var(41); // [ var(64) , var(44) ] D[48,64] = (-1)*var(45); // [ var(64) , var(48) ] D[52,64] = (-1)*var(49); // [ var(64) , var(52) ] D[63,64] = var(62); // [ var(64) , var(63) ] D[2,65] = (-1)*var(128); // [ var(65) , var(2) ] D[9,65] = (-1)*var(4); // [ var(65) , var(9) ] D[15,65] = (-1)*var(10); // [ var(65) , var(15) ] D[16,65] = (-1)*var(11); // [ var(65) , var(16) ] D[20,65] = (-1)*var(14); // [ var(65) , var(20) ] D[22,65] = (-1)*var(17); // [ var(65) , var(22) ] D[23,65] = (-1)*var(18); // [ var(65) , var(23) ] D[26,65] = (-1)*var(21); // [ var(65) , var(26) ] D[29,65] = (-1)*var(24); // [ var(65) , var(29) ] D[30,65] = (-1)*var(25); // [ var(65) , var(30) ] D[33,65] = (-1)*var(27); // [ var(65) , var(33) ] D[36,65] = (-1)*var(31); // [ var(65) , var(36) ] D[39,65] = (-1)*var(34); // [ var(65) , var(39) ] D[53,65] = var(50); // [ var(65) , var(53) ] D[56,65] = var(54); // [ var(65) , var(56) ] D[58,65] = var(57); // [ var(65) , var(58) ] D[60,65] = var(59); // [ var(65) , var(60) ] D[3,66] = (-1)*var(129); // [ var(66) , var(3) ] D[8,66] = var(1); // [ var(66) , var(8) ] D[10,66] = (-1)*var(4); // [ var(66) , var(10) ] D[15,66] = (-1)*var(9); // [ var(66) , var(15) ] D[17,66] = (-1)*var(11); // [ var(66) , var(17) ] D[22,66] = (-1)*var(16); // [ var(66) , var(22) ] D[24,66] = (-1)*var(18); // [ var(66) , var(24) ] D[29,66] = (-1)*var(23); // [ var(66) , var(29) ] D[31,66] = (-1)*var(25); // [ var(66) , var(31) ] D[36,66] = (-1)*var(30); // [ var(66) , var(36) ] D[37,66] = (-1)*var(32); // [ var(66) , var(37) ] D[42,66] = (-1)*var(38); // [ var(66) , var(42) ] D[46,66] = (-1)*var(43); // [ var(66) , var(46) ] D[47,66] = (-1)*var(44); // [ var(66) , var(47) ] D[51,66] = (-1)*var(48); // [ var(66) , var(51) ] D[55,66] = (-1)*var(52); // [ var(66) , var(55) ] D[62,66] = var(61); // [ var(66) , var(62) ] D[4,67] = (-1)*var(130); // [ var(67) , var(4) ] D[9,67] = var(2); // [ var(67) , var(9) ] D[10,67] = var(3); // [ var(67) , var(10) ] D[11,67] = (-1)*var(5); // [ var(67) , var(11) ] D[14,67] = var(8); // [ var(67) , var(14) ] D[18,67] = (-1)*var(12); // [ var(67) , var(18) ] D[25,67] = (-1)*var(19); // [ var(67) , var(25) ] D[28,67] = var(22); // [ var(67) , var(28) ] D[32,67] = var(26); // [ var(67) , var(32) ] D[35,67] = var(29); // [ var(67) , var(35) ] D[38,67] = var(33); // [ var(67) , var(38) ] D[41,67] = var(36); // [ var(67) , var(41) ] D[44,67] = var(39); // [ var(67) , var(44) ] D[50,67] = var(46); // [ var(67) , var(50) ] D[54,67] = var(51); // [ var(67) , var(54) ] D[57,67] = var(55); // [ var(67) , var(57) ] D[61,67] = var(60); // [ var(67) , var(61) ] D[5,68] = (-1)*var(131); // [ var(68) , var(5) ] D[11,68] = var(4); // [ var(68) , var(11) ] D[12,68] = (-1)*var(6); // [ var(68) , var(12) ] D[16,68] = var(9); // [ var(68) , var(16) ] D[17,68] = var(10); // [ var(68) , var(17) ] D[19,68] = (-1)*var(13); // [ var(68) , var(19) ] D[21,68] = var(14); // [ var(68) , var(21) ] D[22,68] = var(15); // [ var(68) , var(22) ] D[26,68] = var(20); // [ var(68) , var(26) ] D[40,68] = var(35); // [ var(68) , var(40) ] D[43,68] = var(38); // [ var(68) , var(43) ] D[45,68] = var(41); // [ var(68) , var(45) ] D[46,68] = var(42); // [ var(68) , var(46) ] D[48,68] = var(44); // [ var(68) , var(48) ] D[51,68] = var(47); // [ var(68) , var(51) ] D[59,68] = var(57); // [ var(68) , var(59) ] D[60,68] = var(58); // [ var(68) , var(60) ] D[6,69] = (-1)*var(132); // [ var(69) , var(6) ] D[12,69] = var(5); // [ var(69) , var(12) ] D[13,69] = (-1)*var(7); // [ var(69) , var(13) ] D[18,69] = var(11); // [ var(69) , var(18) ] D[23,69] = var(16); // [ var(69) , var(23) ] D[24,69] = var(17); // [ var(69) , var(24) ] D[27,69] = var(21); // [ var(69) , var(27) ] D[29,69] = var(22); // [ var(69) , var(29) ] D[33,69] = var(26); // [ var(69) , var(33) ] D[35,69] = var(28); // [ var(69) , var(35) ] D[38,69] = var(32); // [ var(69) , var(38) ] D[42,69] = var(37); // [ var(69) , var(42) ] D[49,69] = var(45); // [ var(69) , var(49) ] D[52,69] = var(48); // [ var(69) , var(52) ] D[55,69] = var(51); // [ var(69) , var(55) ] D[57,69] = var(54); // [ var(69) , var(57) ] D[58,69] = var(56); // [ var(69) , var(58) ] D[7,70] = (-1)*var(133); // [ var(70) , var(7) ] D[13,70] = var(6); // [ var(70) , var(13) ] D[19,70] = var(12); // [ var(70) , var(19) ] D[25,70] = var(18); // [ var(70) , var(25) ] D[30,70] = var(23); // [ var(70) , var(30) ] D[31,70] = var(24); // [ var(70) , var(31) ] D[34,70] = var(27); // [ var(70) , var(34) ] D[36,70] = var(29); // [ var(70) , var(36) ] D[39,70] = var(33); // [ var(70) , var(39) ] D[41,70] = var(35); // [ var(70) , var(41) ] D[44,70] = var(38); // [ var(70) , var(44) ] D[45,70] = var(40); // [ var(70) , var(45) ] D[47,70] = var(42); // [ var(70) , var(47) ] D[48,70] = var(43); // [ var(70) , var(48) ] D[51,70] = var(46); // [ var(70) , var(51) ] D[54,70] = var(50); // [ var(70) , var(54) ] D[56,70] = var(53); // [ var(70) , var(56) ] D[1,71] = (-1)*var(66); // [ var(71) , var(1) ] D[3,71] = var(64); // [ var(71) , var(3) ] D[8,71] = (-1)*var(127)+(-1)*var(129); // [ var(71) , var(8) ] D[14,71] = (-1)*var(4); // [ var(71) , var(14) ] D[20,71] = (-1)*var(9); // [ var(71) , var(20) ] D[21,71] = (-1)*var(11); // [ var(71) , var(21) ] D[26,71] = (-1)*var(16); // [ var(71) , var(26) ] D[27,71] = (-1)*var(18); // [ var(71) , var(27) ] D[33,71] = (-1)*var(23); // [ var(71) , var(33) ] D[34,71] = (-1)*var(25); // [ var(71) , var(34) ] D[37,71] = var(28); // [ var(71) , var(37) ] D[39,71] = (-1)*var(30); // [ var(71) , var(39) ] D[42,71] = var(35); // [ var(71) , var(42) ] D[46,71] = var(40); // [ var(71) , var(46) ] D[47,71] = var(41); // [ var(71) , var(47) ] D[51,71] = var(45); // [ var(71) , var(51) ] D[55,71] = var(49); // [ var(71) , var(55) ] D[63,71] = (-1)*var(61); // [ var(71) , var(63) ] D[2,72] = (-1)*var(67); // [ var(72) , var(2) ] D[4,72] = var(65); // [ var(72) , var(4) ] D[9,72] = (-1)*var(128)+(-1)*var(130); // [ var(72) , var(9) ] D[15,72] = var(3); // [ var(72) , var(15) ] D[16,72] = (-1)*var(5); // [ var(72) , var(16) ] D[20,72] = var(8); // [ var(72) , var(20) ] D[23,72] = (-1)*var(12); // [ var(72) , var(23) ] D[28,72] = (-1)*var(17); // [ var(72) , var(28) ] D[30,72] = (-1)*var(19); // [ var(72) , var(30) ] D[32,72] = (-1)*var(21); // [ var(72) , var(32) ] D[35,72] = (-1)*var(24); // [ var(72) , var(35) ] D[38,72] = (-1)*var(27); // [ var(72) , var(38) ] D[41,72] = (-1)*var(31); // [ var(72) , var(41) ] D[44,72] = (-1)*var(34); // [ var(72) , var(44) ] D[53,72] = (-1)*var(46); // [ var(72) , var(53) ] D[56,72] = (-1)*var(51); // [ var(72) , var(56) ] D[58,72] = (-1)*var(55); // [ var(72) , var(58) ] D[61,72] = var(59); // [ var(72) , var(61) ] D[3,73] = (-1)*var(67); // [ var(73) , var(3) ] D[4,73] = var(66); // [ var(73) , var(4) ] D[10,73] = (-1)*var(129)+(-1)*var(130); // [ var(73) , var(10) ] D[14,73] = var(1); // [ var(73) , var(14) ] D[15,73] = var(2); // [ var(73) , var(15) ] D[17,73] = (-1)*var(5); // [ var(73) , var(17) ] D[24,73] = (-1)*var(12); // [ var(73) , var(24) ] D[28,73] = (-1)*var(16); // [ var(73) , var(28) ] D[31,73] = (-1)*var(19); // [ var(73) , var(31) ] D[35,73] = (-1)*var(23); // [ var(73) , var(35) ] D[37,73] = var(26); // [ var(73) , var(37) ] D[41,73] = (-1)*var(30); // [ var(73) , var(41) ] D[42,73] = var(33); // [ var(73) , var(42) ] D[47,73] = var(39); // [ var(73) , var(47) ] D[50,73] = (-1)*var(43); // [ var(73) , var(50) ] D[54,73] = (-1)*var(48); // [ var(73) , var(54) ] D[57,73] = (-1)*var(52); // [ var(73) , var(57) ] D[62,73] = (-1)*var(60); // [ var(73) , var(62) ] D[4,74] = (-1)*var(68); // [ var(74) , var(4) ] D[5,74] = var(67); // [ var(74) , var(5) ] D[11,74] = (-1)*var(130)+(-1)*var(131); // [ var(74) , var(11) ] D[16,74] = var(2); // [ var(74) , var(16) ] D[17,74] = var(3); // [ var(74) , var(17) ] D[18,74] = (-1)*var(6); // [ var(74) , var(18) ] D[21,74] = var(8); // [ var(74) , var(21) ] D[25,74] = (-1)*var(13); // [ var(74) , var(25) ] D[28,74] = (-1)*var(15); // [ var(74) , var(28) ] D[32,74] = (-1)*var(20); // [ var(74) , var(32) ] D[40,74] = var(29); // [ var(74) , var(40) ] D[43,74] = var(33); // [ var(74) , var(43) ] D[45,74] = var(36); // [ var(74) , var(45) ] D[48,74] = var(39); // [ var(74) , var(48) ] D[50,74] = (-1)*var(42); // [ var(74) , var(50) ] D[54,74] = (-1)*var(47); // [ var(74) , var(54) ] D[59,74] = var(55); // [ var(74) , var(59) ] D[61,74] = (-1)*var(58); // [ var(74) , var(61) ] D[5,75] = (-1)*var(69); // [ var(75) , var(5) ] D[6,75] = var(68); // [ var(75) , var(6) ] D[12,75] = (-1)*var(131)+(-1)*var(132); // [ var(75) , var(12) ] D[18,75] = var(4); // [ var(75) , var(18) ] D[19,75] = (-1)*var(7); // [ var(75) , var(19) ] D[23,75] = var(9); // [ var(75) , var(23) ] D[24,75] = var(10); // [ var(75) , var(24) ] D[27,75] = var(14); // [ var(75) , var(27) ] D[29,75] = var(15); // [ var(75) , var(29) ] D[33,75] = var(20); // [ var(75) , var(33) ] D[40,75] = (-1)*var(28); // [ var(75) , var(40) ] D[43,75] = (-1)*var(32); // [ var(75) , var(43) ] D[46,75] = (-1)*var(37); // [ var(75) , var(46) ] D[49,75] = var(41); // [ var(75) , var(49) ] D[52,75] = var(44); // [ var(75) , var(52) ] D[55,75] = var(47); // [ var(75) , var(55) ] D[59,75] = (-1)*var(54); // [ var(75) , var(59) ] D[60,75] = (-1)*var(56); // [ var(75) , var(60) ] D[6,76] = (-1)*var(70); // [ var(76) , var(6) ] D[7,76] = var(69); // [ var(76) , var(7) ] D[13,76] = (-1)*var(132)+(-1)*var(133); // [ var(76) , var(13) ] D[19,76] = var(5); // [ var(76) , var(19) ] D[25,76] = var(11); // [ var(76) , var(25) ] D[30,76] = var(16); // [ var(76) , var(30) ] D[31,76] = var(17); // [ var(76) , var(31) ] D[34,76] = var(21); // [ var(76) , var(34) ] D[36,76] = var(22); // [ var(76) , var(36) ] D[39,76] = var(26); // [ var(76) , var(39) ] D[41,76] = var(28); // [ var(76) , var(41) ] D[44,76] = var(32); // [ var(76) , var(44) ] D[47,76] = var(37); // [ var(76) , var(47) ] D[49,76] = (-1)*var(40); // [ var(76) , var(49) ] D[52,76] = (-1)*var(43); // [ var(76) , var(52) ] D[55,76] = (-1)*var(46); // [ var(76) , var(55) ] D[57,76] = (-1)*var(50); // [ var(76) , var(57) ] D[58,76] = (-1)*var(53); // [ var(76) , var(58) ] D[1,77] = (-1)*var(73); // [ var(77) , var(1) ] D[4,77] = var(71); // [ var(77) , var(4) ] D[8,77] = (-1)*var(67); // [ var(77) , var(8) ] D[10,77] = var(64); // [ var(77) , var(10) ] D[14,77] = (-1)*var(127)+(-1)*var(129)+(-1)*var(130); // [ var(77) , var(14) ] D[20,77] = var(2); // [ var(77) , var(20) ] D[21,77] = (-1)*var(5); // [ var(77) , var(21) ] D[27,77] = (-1)*var(12); // [ var(77) , var(27) ] D[32,77] = (-1)*var(16); // [ var(77) , var(32) ] D[34,77] = (-1)*var(19); // [ var(77) , var(34) ] D[37,77] = (-1)*var(22); // [ var(77) , var(37) ] D[38,77] = (-1)*var(23); // [ var(77) , var(38) ] D[42,77] = (-1)*var(29); // [ var(77) , var(42) ] D[44,77] = (-1)*var(30); // [ var(77) , var(44) ] D[47,77] = (-1)*var(36); // [ var(77) , var(47) ] D[50,77] = var(40); // [ var(77) , var(50) ] D[54,77] = var(45); // [ var(77) , var(54) ] D[57,77] = var(49); // [ var(77) , var(57) ] D[63,77] = var(60); // [ var(77) , var(63) ] D[2,78] = (-1)*var(73); // [ var(78) , var(2) ] D[3,78] = (-1)*var(72); // [ var(78) , var(3) ] D[9,78] = var(66); // [ var(78) , var(9) ] D[10,78] = var(65); // [ var(78) , var(10) ] D[15,78] = (-1)*var(128)+(-1)*var(129)+(-1)*var(130); // [ var(78) , var(15) ] D[20,78] = var(1); // [ var(78) , var(20) ] D[22,78] = (-1)*var(5); // [ var(78) , var(22) ] D[28,78] = var(11); // [ var(78) , var(28) ] D[29,78] = (-1)*var(12); // [ var(78) , var(29) ] D[35,78] = var(18); // [ var(78) , var(35) ] D[36,78] = (-1)*var(19); // [ var(78) , var(36) ] D[37,78] = (-1)*var(21); // [ var(78) , var(37) ] D[41,78] = var(25); // [ var(78) , var(41) ] D[42,78] = (-1)*var(27); // [ var(78) , var(42) ] D[47,78] = (-1)*var(34); // [ var(78) , var(47) ] D[53,78] = var(43); // [ var(78) , var(53) ] D[56,78] = var(48); // [ var(78) , var(56) ] D[58,78] = var(52); // [ var(78) , var(58) ] D[62,78] = (-1)*var(59); // [ var(78) , var(62) ] D[2,79] = (-1)*var(74); // [ var(79) , var(2) ] D[5,79] = var(72); // [ var(79) , var(5) ] D[9,79] = (-1)*var(68); // [ var(79) , var(9) ] D[11,79] = var(65); // [ var(79) , var(11) ] D[16,79] = (-1)*var(128)+(-1)*var(130)+(-1)*var(131); // [ var(79) , var(16) ] D[22,79] = var(3); // [ var(79) , var(22) ] D[23,79] = (-1)*var(6); // [ var(79) , var(23) ] D[26,79] = var(8); // [ var(79) , var(26) ] D[28,79] = var(10); // [ var(79) , var(28) ] D[30,79] = (-1)*var(13); // [ var(79) , var(30) ] D[32,79] = var(14); // [ var(79) , var(32) ] D[40,79] = (-1)*var(24); // [ var(79) , var(40) ] D[43,79] = (-1)*var(27); // [ var(79) , var(43) ] D[45,79] = (-1)*var(31); // [ var(79) , var(45) ] D[48,79] = (-1)*var(34); // [ var(79) , var(48) ] D[53,79] = var(42); // [ var(79) , var(53) ] D[56,79] = var(47); // [ var(79) , var(56) ] D[60,79] = (-1)*var(55); // [ var(79) , var(60) ] D[61,79] = (-1)*var(57); // [ var(79) , var(61) ] D[3,80] = (-1)*var(74); // [ var(80) , var(3) ] D[5,80] = var(73); // [ var(80) , var(5) ] D[10,80] = (-1)*var(68); // [ var(80) , var(10) ] D[11,80] = var(66); // [ var(80) , var(11) ] D[17,80] = (-1)*var(129)+(-1)*var(130)+(-1)*var(131); // [ var(80) , var(17) ] D[21,80] = var(1); // [ var(80) , var(21) ] D[22,80] = var(2); // [ var(80) , var(22) ] D[24,80] = (-1)*var(6); // [ var(80) , var(24) ] D[28,80] = var(9); // [ var(80) , var(28) ] D[31,80] = (-1)*var(13); // [ var(80) , var(31) ] D[37,80] = (-1)*var(20); // [ var(80) , var(37) ] D[40,80] = (-1)*var(23); // [ var(80) , var(40) ] D[45,80] = (-1)*var(30); // [ var(80) , var(45) ] D[46,80] = var(33); // [ var(80) , var(46) ] D[50,80] = var(38); // [ var(80) , var(50) ] D[51,80] = var(39); // [ var(80) , var(51) ] D[54,80] = var(44); // [ var(80) , var(54) ] D[59,80] = (-1)*var(52); // [ var(80) , var(59) ] D[62,80] = var(58); // [ var(80) , var(62) ] D[4,81] = (-1)*var(75); // [ var(81) , var(4) ] D[6,81] = var(74); // [ var(81) , var(6) ] D[11,81] = (-1)*var(69); // [ var(81) , var(11) ] D[12,81] = var(67); // [ var(81) , var(12) ] D[18,81] = (-1)*var(130)+(-1)*var(131)+(-1)*var(132); // [ var(81) , var(18) ] D[23,81] = var(2); // [ var(81) , var(23) ] D[24,81] = var(3); // [ var(81) , var(24) ] D[25,81] = (-1)*var(7); // [ var(81) , var(25) ] D[27,81] = var(8); // [ var(81) , var(27) ] D[35,81] = (-1)*var(15); // [ var(81) , var(35) ] D[38,81] = (-1)*var(20); // [ var(81) , var(38) ] D[40,81] = (-1)*var(22); // [ var(81) , var(40) ] D[43,81] = (-1)*var(26); // [ var(81) , var(43) ] D[49,81] = var(36); // [ var(81) , var(49) ] D[50,81] = var(37); // [ var(81) , var(50) ] D[52,81] = var(39); // [ var(81) , var(52) ] D[57,81] = (-1)*var(47); // [ var(81) , var(57) ] D[59,81] = (-1)*var(51); // [ var(81) , var(59) ] D[61,81] = var(56); // [ var(81) , var(61) ] D[5,82] = (-1)*var(76); // [ var(82) , var(5) ] D[7,82] = var(75); // [ var(82) , var(7) ] D[12,82] = (-1)*var(70); // [ var(82) , var(12) ] D[13,82] = var(68); // [ var(82) , var(13) ] D[19,82] = (-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(82) , var(19) ] D[25,82] = var(4); // [ var(82) , var(25) ] D[30,82] = var(9); // [ var(82) , var(30) ] D[31,82] = var(10); // [ var(82) , var(31) ] D[34,82] = var(14); // [ var(82) , var(34) ] D[36,82] = var(15); // [ var(82) , var(36) ] D[39,82] = var(20); // [ var(82) , var(39) ] D[45,82] = (-1)*var(28); // [ var(82) , var(45) ] D[48,82] = (-1)*var(32); // [ var(82) , var(48) ] D[49,82] = (-1)*var(35); // [ var(82) , var(49) ] D[51,82] = (-1)*var(37); // [ var(82) , var(51) ] D[52,82] = (-1)*var(38); // [ var(82) , var(52) ] D[55,82] = (-1)*var(42); // [ var(82) , var(55) ] D[59,82] = var(50); // [ var(82) , var(59) ] D[60,82] = var(53); // [ var(82) , var(60) ] D[1,83] = (-1)*var(78); // [ var(83) , var(1) ] D[2,83] = (-1)*var(77); // [ var(83) , var(2) ] D[8,83] = (-1)*var(72); // [ var(83) , var(8) ] D[9,83] = var(71); // [ var(83) , var(9) ] D[14,83] = var(65); // [ var(83) , var(14) ] D[15,83] = var(64); // [ var(83) , var(15) ] D[20,83] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-1)*var(130); // [ var(83) , var(20) ] D[26,83] = (-1)*var(5); // [ var(83) , var(26) ] D[32,83] = var(11); // [ var(83) , var(32) ] D[33,83] = (-1)*var(12); // [ var(83) , var(33) ] D[37,83] = var(17); // [ var(83) , var(37) ] D[38,83] = var(18); // [ var(83) , var(38) ] D[39,83] = (-1)*var(19); // [ var(83) , var(39) ] D[42,83] = var(24); // [ var(83) , var(42) ] D[44,83] = var(25); // [ var(83) , var(44) ] D[47,83] = var(31); // [ var(83) , var(47) ] D[53,83] = (-1)*var(40); // [ var(83) , var(53) ] D[56,83] = (-1)*var(45); // [ var(83) , var(56) ] D[58,83] = (-1)*var(49); // [ var(83) , var(58) ] D[63,83] = var(59); // [ var(83) , var(63) ] D[1,84] = (-1)*var(80); // [ var(84) , var(1) ] D[5,84] = var(77); // [ var(84) , var(5) ] D[8,84] = (-1)*var(74); // [ var(84) , var(8) ] D[11,84] = var(71); // [ var(84) , var(11) ] D[14,84] = (-1)*var(68); // [ var(84) , var(14) ] D[17,84] = var(64); // [ var(84) , var(17) ] D[21,84] = (-1)*var(127)+(-1)*var(129)+(-1)*var(130)+(-1)*var(131); // [ var(84) , var(21) ] D[26,84] = var(2); // [ var(84) , var(26) ] D[27,84] = (-1)*var(6); // [ var(84) , var(27) ] D[32,84] = var(9); // [ var(84) , var(32) ] D[34,84] = (-1)*var(13); // [ var(84) , var(34) ] D[37,84] = var(15); // [ var(84) , var(37) ] D[43,84] = (-1)*var(23); // [ var(84) , var(43) ] D[46,84] = (-1)*var(29); // [ var(84) , var(46) ] D[48,84] = (-1)*var(30); // [ var(84) , var(48) ] D[50,84] = (-1)*var(35); // [ var(84) , var(50) ] D[51,84] = (-1)*var(36); // [ var(84) , var(51) ] D[54,84] = (-1)*var(41); // [ var(84) , var(54) ] D[59,84] = var(49); // [ var(84) , var(59) ] D[63,84] = (-1)*var(58); // [ var(84) , var(63) ] D[2,85] = (-1)*var(80); // [ var(85) , var(2) ] D[3,85] = (-1)*var(79); // [ var(85) , var(3) ] D[5,85] = var(78); // [ var(85) , var(5) ] D[15,85] = (-1)*var(68); // [ var(85) , var(15) ] D[16,85] = var(66); // [ var(85) , var(16) ] D[17,85] = var(65); // [ var(85) , var(17) ] D[22,85] = (-1)*var(128)+(-1)*var(129)+(-1)*var(130)+(-1)*var(131); // [ var(85) , var(22) ] D[26,85] = var(1); // [ var(85) , var(26) ] D[28,85] = (-1)*var(4); // [ var(85) , var(28) ] D[29,85] = (-1)*var(6); // [ var(85) , var(29) ] D[36,85] = (-1)*var(13); // [ var(85) , var(36) ] D[37,85] = var(14); // [ var(85) , var(37) ] D[40,85] = var(18); // [ var(85) , var(40) ] D[45,85] = var(25); // [ var(85) , var(45) ] D[46,85] = (-1)*var(27); // [ var(85) , var(46) ] D[51,85] = (-1)*var(34); // [ var(85) , var(51) ] D[53,85] = (-1)*var(38); // [ var(85) , var(53) ] D[56,85] = (-1)*var(44); // [ var(85) , var(56) ] D[60,85] = var(52); // [ var(85) , var(60) ] D[62,85] = var(57); // [ var(85) , var(62) ] D[2,86] = (-1)*var(81); // [ var(86) , var(2) ] D[6,86] = var(79); // [ var(86) , var(6) ] D[9,86] = (-1)*var(75); // [ var(86) , var(9) ] D[12,86] = var(72); // [ var(86) , var(12) ] D[16,86] = (-1)*var(69); // [ var(86) , var(16) ] D[18,86] = var(65); // [ var(86) , var(18) ] D[23,86] = (-1)*var(128)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132); // [ var(86) , var(23) ] D[29,86] = var(3); // [ var(86) , var(29) ] D[30,86] = (-1)*var(7); // [ var(86) , var(30) ] D[33,86] = var(8); // [ var(86) , var(33) ] D[35,86] = var(10); // [ var(86) , var(35) ] D[38,86] = var(14); // [ var(86) , var(38) ] D[40,86] = var(17); // [ var(86) , var(40) ] D[43,86] = var(21); // [ var(86) , var(43) ] D[49,86] = (-1)*var(31); // [ var(86) , var(49) ] D[52,86] = (-1)*var(34); // [ var(86) , var(52) ] D[53,86] = (-1)*var(37); // [ var(86) , var(53) ] D[58,86] = var(47); // [ var(86) , var(58) ] D[60,86] = var(51); // [ var(86) , var(60) ] D[61,86] = var(54); // [ var(86) , var(61) ] D[3,87] = (-1)*var(81); // [ var(87) , var(3) ] D[6,87] = var(80); // [ var(87) , var(6) ] D[10,87] = (-1)*var(75); // [ var(87) , var(10) ] D[12,87] = var(73); // [ var(87) , var(12) ] D[17,87] = (-1)*var(69); // [ var(87) , var(17) ] D[18,87] = var(66); // [ var(87) , var(18) ] D[24,87] = (-1)*var(129)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132); // [ var(87) , var(24) ] D[27,87] = var(1); // [ var(87) , var(27) ] D[29,87] = var(2); // [ var(87) , var(29) ] D[31,87] = (-1)*var(7); // [ var(87) , var(31) ] D[35,87] = var(9); // [ var(87) , var(35) ] D[40,87] = var(16); // [ var(87) , var(40) ] D[42,87] = (-1)*var(20); // [ var(87) , var(42) ] D[46,87] = (-1)*var(26); // [ var(87) , var(46) ] D[49,87] = (-1)*var(30); // [ var(87) , var(49) ] D[50,87] = (-1)*var(32); // [ var(87) , var(50) ] D[55,87] = var(39); // [ var(87) , var(55) ] D[57,87] = var(44); // [ var(87) , var(57) ] D[59,87] = var(48); // [ var(87) , var(59) ] D[62,87] = (-1)*var(56); // [ var(87) , var(62) ] D[4,88] = (-1)*var(82); // [ var(88) , var(4) ] D[7,88] = var(81); // [ var(88) , var(7) ] D[11,88] = (-1)*var(76); // [ var(88) , var(11) ] D[13,88] = var(74); // [ var(88) , var(13) ] D[18,88] = (-1)*var(70); // [ var(88) , var(18) ] D[19,88] = var(67); // [ var(88) , var(19) ] D[25,88] = (-1)*var(130)+(-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(88) , var(25) ] D[30,88] = var(2); // [ var(88) , var(30) ] D[31,88] = var(3); // [ var(88) , var(31) ] D[34,88] = var(8); // [ var(88) , var(34) ] D[41,88] = (-1)*var(15); // [ var(88) , var(41) ] D[44,88] = (-1)*var(20); // [ var(88) , var(44) ] D[45,88] = (-1)*var(22); // [ var(88) , var(45) ] D[48,88] = (-1)*var(26); // [ var(88) , var(48) ] D[49,88] = (-1)*var(29); // [ var(88) , var(49) ] D[52,88] = (-1)*var(33); // [ var(88) , var(52) ] D[54,88] = var(37); // [ var(88) , var(54) ] D[57,88] = var(42); // [ var(88) , var(57) ] D[59,88] = var(46); // [ var(88) , var(59) ] D[61,88] = (-1)*var(53); // [ var(88) , var(61) ] D[1,89] = (-1)*var(85); // [ var(89) , var(1) ] D[2,89] = (-1)*var(84); // [ var(89) , var(2) ] D[5,89] = var(83); // [ var(89) , var(5) ] D[8,89] = (-1)*var(79); // [ var(89) , var(8) ] D[16,89] = var(71); // [ var(89) , var(16) ] D[20,89] = (-1)*var(68); // [ var(89) , var(20) ] D[21,89] = var(65); // [ var(89) , var(21) ] D[22,89] = var(64); // [ var(89) , var(22) ] D[26,89] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-1)*var(130)+(-1)*var(131); // [ var(89) , var(26) ] D[32,89] = (-1)*var(4); // [ var(89) , var(32) ] D[33,89] = (-1)*var(6); // [ var(89) , var(33) ] D[37,89] = (-1)*var(10); // [ var(89) , var(37) ] D[39,89] = (-1)*var(13); // [ var(89) , var(39) ] D[43,89] = var(18); // [ var(89) , var(43) ] D[46,89] = var(24); // [ var(89) , var(46) ] D[48,89] = var(25); // [ var(89) , var(48) ] D[51,89] = var(31); // [ var(89) , var(51) ] D[53,89] = var(35); // [ var(89) , var(53) ] D[56,89] = var(41); // [ var(89) , var(56) ] D[60,89] = (-1)*var(49); // [ var(89) , var(60) ] D[63,89] = (-1)*var(57); // [ var(89) , var(63) ] D[1,90] = (-1)*var(87); // [ var(90) , var(1) ] D[6,90] = var(84); // [ var(90) , var(6) ] D[8,90] = (-1)*var(81); // [ var(90) , var(8) ] D[12,90] = var(77); // [ var(90) , var(12) ] D[14,90] = (-1)*var(75); // [ var(90) , var(14) ] D[18,90] = var(71); // [ var(90) , var(18) ] D[21,90] = (-1)*var(69); // [ var(90) , var(21) ] D[24,90] = var(64); // [ var(90) , var(24) ] D[27,90] = (-1)*var(127)+(-1)*var(129)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132); // [ var(90) , var(27) ] D[33,90] = var(2); // [ var(90) , var(33) ] D[34,90] = (-1)*var(7); // [ var(90) , var(34) ] D[38,90] = var(9); // [ var(90) , var(38) ] D[42,90] = var(15); // [ var(90) , var(42) ] D[43,90] = var(16); // [ var(90) , var(43) ] D[46,90] = var(22); // [ var(90) , var(46) ] D[50,90] = var(28); // [ var(90) , var(50) ] D[52,90] = (-1)*var(30); // [ var(90) , var(52) ] D[55,90] = (-1)*var(36); // [ var(90) , var(55) ] D[57,90] = (-1)*var(41); // [ var(90) , var(57) ] D[59,90] = (-1)*var(45); // [ var(90) , var(59) ] D[63,90] = var(56); // [ var(90) , var(63) ] D[4,91] = var(85); // [ var(91) , var(4) ] D[9,91] = (-1)*var(80); // [ var(91) , var(9) ] D[10,91] = (-1)*var(79); // [ var(91) , var(10) ] D[11,91] = (-1)*var(78); // [ var(91) , var(11) ] D[15,91] = var(74); // [ var(91) , var(15) ] D[16,91] = var(73); // [ var(91) , var(16) ] D[17,91] = var(72); // [ var(91) , var(17) ] D[22,91] = (-1)*var(67); // [ var(91) , var(22) ] D[28,91] = (-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-1)*var(131); // [ var(91) , var(28) ] D[32,91] = var(1); // [ var(91) , var(32) ] D[35,91] = (-1)*var(6); // [ var(91) , var(35) ] D[37,91] = (-1)*var(8); // [ var(91) , var(37) ] D[40,91] = var(12); // [ var(91) , var(40) ] D[41,91] = (-1)*var(13); // [ var(91) , var(41) ] D[45,91] = var(19); // [ var(91) , var(45) ] D[50,91] = (-1)*var(27); // [ var(91) , var(50) ] D[53,91] = var(33); // [ var(91) , var(53) ] D[54,91] = (-1)*var(34); // [ var(91) , var(54) ] D[56,91] = var(39); // [ var(91) , var(56) ] D[61,91] = var(52); // [ var(91) , var(61) ] D[62,91] = (-1)*var(55); // [ var(91) , var(62) ] D[2,92] = (-1)*var(87); // [ var(92) , var(2) ] D[3,92] = (-1)*var(86); // [ var(92) , var(3) ] D[6,92] = var(85); // [ var(92) , var(6) ] D[12,92] = var(78); // [ var(92) , var(12) ] D[15,92] = (-1)*var(75); // [ var(92) , var(15) ] D[22,92] = (-1)*var(69); // [ var(92) , var(22) ] D[23,92] = var(66); // [ var(92) , var(23) ] D[24,92] = var(65); // [ var(92) , var(24) ] D[29,92] = (-1)*var(128)+(-1)*var(129)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132); // [ var(92) , var(29) ] D[33,92] = var(1); // [ var(92) , var(33) ] D[35,92] = (-1)*var(4); // [ var(92) , var(35) ] D[36,92] = (-1)*var(7); // [ var(92) , var(36) ] D[40,92] = (-1)*var(11); // [ var(92) , var(40) ] D[42,92] = var(14); // [ var(92) , var(42) ] D[46,92] = var(21); // [ var(92) , var(46) ] D[49,92] = var(25); // [ var(92) , var(49) ] D[53,92] = var(32); // [ var(92) , var(53) ] D[55,92] = (-1)*var(34); // [ var(92) , var(55) ] D[58,92] = (-1)*var(44); // [ var(92) , var(58) ] D[60,92] = (-1)*var(48); // [ var(92) , var(60) ] D[62,92] = (-1)*var(54); // [ var(92) , var(62) ] D[2,93] = (-1)*var(88); // [ var(93) , var(2) ] D[7,93] = var(86); // [ var(93) , var(7) ] D[9,93] = (-1)*var(82); // [ var(93) , var(9) ] D[13,93] = var(79); // [ var(93) , var(13) ] D[16,93] = (-1)*var(76); // [ var(93) , var(16) ] D[19,93] = var(72); // [ var(93) , var(19) ] D[23,93] = (-1)*var(70); // [ var(93) , var(23) ] D[25,93] = var(65); // [ var(93) , var(25) ] D[30,93] = (-1)*var(128)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(93) , var(30) ] D[36,93] = var(3); // [ var(93) , var(36) ] D[39,93] = var(8); // [ var(93) , var(39) ] D[41,93] = var(10); // [ var(93) , var(41) ] D[44,93] = var(14); // [ var(93) , var(44) ] D[45,93] = var(17); // [ var(93) , var(45) ] D[48,93] = var(21); // [ var(93) , var(48) ] D[49,93] = var(24); // [ var(93) , var(49) ] D[52,93] = var(27); // [ var(93) , var(52) ] D[56,93] = (-1)*var(37); // [ var(93) , var(56) ] D[58,93] = (-1)*var(42); // [ var(93) , var(58) ] D[60,93] = (-1)*var(46); // [ var(93) , var(60) ] D[61,93] = (-1)*var(50); // [ var(93) , var(61) ] D[3,94] = (-1)*var(88); // [ var(94) , var(3) ] D[7,94] = var(87); // [ var(94) , var(7) ] D[10,94] = (-1)*var(82); // [ var(94) , var(10) ] D[13,94] = var(80); // [ var(94) , var(13) ] D[17,94] = (-1)*var(76); // [ var(94) , var(17) ] D[19,94] = var(73); // [ var(94) , var(19) ] D[24,94] = (-1)*var(70); // [ var(94) , var(24) ] D[25,94] = var(66); // [ var(94) , var(25) ] D[31,94] = (-1)*var(129)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(94) , var(31) ] D[34,94] = var(1); // [ var(94) , var(34) ] D[36,94] = var(2); // [ var(94) , var(36) ] D[41,94] = var(9); // [ var(94) , var(41) ] D[45,94] = var(16); // [ var(94) , var(45) ] D[47,94] = (-1)*var(20); // [ var(94) , var(47) ] D[49,94] = var(23); // [ var(94) , var(49) ] D[51,94] = (-1)*var(26); // [ var(94) , var(51) ] D[54,94] = (-1)*var(32); // [ var(94) , var(54) ] D[55,94] = (-1)*var(33); // [ var(94) , var(55) ] D[57,94] = (-1)*var(38); // [ var(94) , var(57) ] D[59,94] = (-1)*var(43); // [ var(94) , var(59) ] D[62,94] = var(53); // [ var(94) , var(62) ] D[1,95] = (-1)*var(91); // [ var(95) , var(1) ] D[4,95] = var(89); // [ var(95) , var(4) ] D[9,95] = (-1)*var(84); // [ var(95) , var(9) ] D[11,95] = (-1)*var(83); // [ var(95) , var(11) ] D[14,95] = (-1)*var(79); // [ var(95) , var(14) ] D[16,95] = var(77); // [ var(95) , var(16) ] D[20,95] = var(74); // [ var(95) , var(20) ] D[21,95] = var(72); // [ var(95) , var(21) ] D[26,95] = (-1)*var(67); // [ var(95) , var(26) ] D[28,95] = var(64); // [ var(95) , var(28) ] D[32,95] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-1)*var(131); // [ var(95) , var(32) ] D[37,95] = var(3); // [ var(95) , var(37) ] D[38,95] = (-1)*var(6); // [ var(95) , var(38) ] D[43,95] = var(12); // [ var(95) , var(43) ] D[44,95] = (-1)*var(13); // [ var(95) , var(44) ] D[48,95] = var(19); // [ var(95) , var(48) ] D[50,95] = var(24); // [ var(95) , var(50) ] D[53,95] = (-1)*var(29); // [ var(95) , var(53) ] D[54,95] = var(31); // [ var(95) , var(54) ] D[56,95] = (-1)*var(36); // [ var(95) , var(56) ] D[61,95] = (-1)*var(49); // [ var(95) , var(61) ] D[63,95] = var(55); // [ var(95) , var(63) ] D[1,96] = (-1)*var(92); // [ var(96) , var(1) ] D[2,96] = (-1)*var(90); // [ var(96) , var(2) ] D[6,96] = var(89); // [ var(96) , var(6) ] D[8,96] = (-1)*var(86); // [ var(96) , var(8) ] D[12,96] = var(83); // [ var(96) , var(12) ] D[20,96] = (-1)*var(75); // [ var(96) , var(20) ] D[23,96] = var(71); // [ var(96) , var(23) ] D[26,96] = (-1)*var(69); // [ var(96) , var(26) ] D[27,96] = var(65); // [ var(96) , var(27) ] D[29,96] = var(64); // [ var(96) , var(29) ] D[33,96] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132); // [ var(96) , var(33) ] D[38,96] = (-1)*var(4); // [ var(96) , var(38) ] D[39,96] = (-1)*var(7); // [ var(96) , var(39) ] D[42,96] = (-1)*var(10); // [ var(96) , var(42) ] D[43,96] = (-1)*var(11); // [ var(96) , var(43) ] D[46,96] = (-1)*var(17); // [ var(96) , var(46) ] D[52,96] = var(25); // [ var(96) , var(52) ] D[53,96] = (-1)*var(28); // [ var(96) , var(53) ] D[55,96] = var(31); // [ var(96) , var(55) ] D[58,96] = var(41); // [ var(96) , var(58) ] D[60,96] = var(45); // [ var(96) , var(60) ] D[63,96] = var(54); // [ var(96) , var(63) ] D[1,97] = (-1)*var(94); // [ var(97) , var(1) ] D[7,97] = var(90); // [ var(97) , var(7) ] D[8,97] = (-1)*var(88); // [ var(97) , var(8) ] D[13,97] = var(84); // [ var(97) , var(13) ] D[14,97] = (-1)*var(82); // [ var(97) , var(14) ] D[19,97] = var(77); // [ var(97) , var(19) ] D[21,97] = (-1)*var(76); // [ var(97) , var(21) ] D[25,97] = var(71); // [ var(97) , var(25) ] D[27,97] = (-1)*var(70); // [ var(97) , var(27) ] D[31,97] = var(64); // [ var(97) , var(31) ] D[34,97] = (-1)*var(127)+(-1)*var(129)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(97) , var(34) ] D[39,97] = var(2); // [ var(97) , var(39) ] D[44,97] = var(9); // [ var(97) , var(44) ] D[47,97] = var(15); // [ var(97) , var(47) ] D[48,97] = var(16); // [ var(97) , var(48) ] D[51,97] = var(22); // [ var(97) , var(51) ] D[52,97] = var(23); // [ var(97) , var(52) ] D[54,97] = var(28); // [ var(97) , var(54) ] D[55,97] = var(29); // [ var(97) , var(55) ] D[57,97] = var(35); // [ var(97) , var(57) ] D[59,97] = var(40); // [ var(97) , var(59) ] D[63,97] = (-1)*var(53); // [ var(97) , var(63) ] D[4,98] = var(92); // [ var(98) , var(4) ] D[6,98] = var(91); // [ var(98) , var(6) ] D[9,98] = (-1)*var(87); // [ var(98) , var(9) ] D[10,98] = (-1)*var(86); // [ var(98) , var(10) ] D[15,98] = var(81); // [ var(98) , var(15) ] D[18,98] = (-1)*var(78); // [ var(98) , var(18) ] D[23,98] = var(73); // [ var(98) , var(23) ] D[24,98] = var(72); // [ var(98) , var(24) ] D[28,98] = (-1)*var(69); // [ var(98) , var(28) ] D[29,98] = (-1)*var(67); // [ var(98) , var(29) ] D[35,98] = (-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-1)*var(131)+(-1)*var(132); // [ var(98) , var(35) ] D[38,98] = var(1); // [ var(98) , var(38) ] D[40,98] = (-1)*var(5); // [ var(98) , var(40) ] D[41,98] = (-1)*var(7); // [ var(98) , var(41) ] D[42,98] = (-1)*var(8); // [ var(98) , var(42) ] D[49,98] = var(19); // [ var(98) , var(49) ] D[50,98] = var(21); // [ var(98) , var(50) ] D[53,98] = (-1)*var(26); // [ var(98) , var(53) ] D[57,98] = (-1)*var(34); // [ var(98) , var(57) ] D[58,98] = var(39); // [ var(98) , var(58) ] D[61,98] = (-1)*var(48); // [ var(98) , var(61) ] D[62,98] = var(51); // [ var(98) , var(62) ] D[2,99] = (-1)*var(94); // [ var(99) , var(2) ] D[3,99] = (-1)*var(93); // [ var(99) , var(3) ] D[7,99] = var(92); // [ var(99) , var(7) ] D[13,99] = var(85); // [ var(99) , var(13) ] D[15,99] = (-1)*var(82); // [ var(99) , var(15) ] D[19,99] = var(78); // [ var(99) , var(19) ] D[22,99] = (-1)*var(76); // [ var(99) , var(22) ] D[29,99] = (-1)*var(70); // [ var(99) , var(29) ] D[30,99] = var(66); // [ var(99) , var(30) ] D[31,99] = var(65); // [ var(99) , var(31) ] D[36,99] = (-1)*var(128)+(-1)*var(129)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(99) , var(36) ] D[39,99] = var(1); // [ var(99) , var(39) ] D[41,99] = (-1)*var(4); // [ var(99) , var(41) ] D[45,99] = (-1)*var(11); // [ var(99) , var(45) ] D[47,99] = var(14); // [ var(99) , var(47) ] D[49,99] = (-1)*var(18); // [ var(99) , var(49) ] D[51,99] = var(21); // [ var(99) , var(51) ] D[55,99] = var(27); // [ var(99) , var(55) ] D[56,99] = var(32); // [ var(99) , var(56) ] D[58,99] = var(38); // [ var(99) , var(58) ] D[60,99] = var(43); // [ var(99) , var(60) ] D[62,99] = var(50); // [ var(99) , var(62) ] D[3,100] = (-1)*var(95); // [ var(100) , var(3) ] D[8,100] = var(91); // [ var(100) , var(8) ] D[10,100] = var(89); // [ var(100) , var(10) ] D[14,100] = (-1)*var(85); // [ var(100) , var(14) ] D[15,100] = (-1)*var(84); // [ var(100) , var(15) ] D[17,100] = (-1)*var(83); // [ var(100) , var(17) ] D[20,100] = var(80); // [ var(100) , var(20) ] D[21,100] = var(78); // [ var(100) , var(21) ] D[22,100] = var(77); // [ var(100) , var(22) ] D[26,100] = (-1)*var(73); // [ var(100) , var(26) ] D[28,100] = (-1)*var(71); // [ var(100) , var(28) ] D[32,100] = var(66); // [ var(100) , var(32) ] D[37,100] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-2)*var(130)+(-1)*var(131); // [ var(100) , var(37) ] D[42,100] = (-1)*var(6); // [ var(100) , var(42) ] D[46,100] = var(12); // [ var(100) , var(46) ] D[47,100] = (-1)*var(13); // [ var(100) , var(47) ] D[50,100] = (-1)*var(18); // [ var(100) , var(50) ] D[51,100] = var(19); // [ var(100) , var(51) ] D[53,100] = var(23); // [ var(100) , var(53) ] D[54,100] = (-1)*var(25); // [ var(100) , var(54) ] D[56,100] = var(30); // [ var(100) , var(56) ] D[62,100] = var(49); // [ var(100) , var(62) ] D[63,100] = (-1)*var(52); // [ var(100) , var(63) ] D[1,101] = (-1)*var(98); // [ var(101) , var(1) ] D[4,101] = var(96); // [ var(101) , var(4) ] D[6,101] = var(95); // [ var(101) , var(6) ] D[9,101] = (-1)*var(90); // [ var(101) , var(9) ] D[14,101] = (-1)*var(86); // [ var(101) , var(14) ] D[18,101] = (-1)*var(83); // [ var(101) , var(18) ] D[20,101] = var(81); // [ var(101) , var(20) ] D[23,101] = var(77); // [ var(101) , var(23) ] D[27,101] = var(72); // [ var(101) , var(27) ] D[32,101] = (-1)*var(69); // [ var(101) , var(32) ] D[33,101] = (-1)*var(67); // [ var(101) , var(33) ] D[35,101] = var(64); // [ var(101) , var(35) ] D[38,101] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-1)*var(131)+(-1)*var(132); // [ var(101) , var(38) ] D[42,101] = var(3); // [ var(101) , var(42) ] D[43,101] = (-1)*var(5); // [ var(101) , var(43) ] D[44,101] = (-1)*var(7); // [ var(101) , var(44) ] D[50,101] = (-1)*var(17); // [ var(101) , var(50) ] D[52,101] = var(19); // [ var(101) , var(52) ] D[53,101] = var(22); // [ var(101) , var(53) ] D[57,101] = var(31); // [ var(101) , var(57) ] D[58,101] = (-1)*var(36); // [ var(101) , var(58) ] D[61,101] = var(45); // [ var(101) , var(61) ] D[63,101] = (-1)*var(51); // [ var(101) , var(63) ] D[1,102] = (-1)*var(99); // [ var(102) , var(1) ] D[2,102] = (-1)*var(97); // [ var(102) , var(2) ] D[7,102] = var(96); // [ var(102) , var(7) ] D[8,102] = (-1)*var(93); // [ var(102) , var(8) ] D[13,102] = var(89); // [ var(102) , var(13) ] D[19,102] = var(83); // [ var(102) , var(19) ] D[20,102] = (-1)*var(82); // [ var(102) , var(20) ] D[26,102] = (-1)*var(76); // [ var(102) , var(26) ] D[30,102] = var(71); // [ var(102) , var(30) ] D[33,102] = (-1)*var(70); // [ var(102) , var(33) ] D[34,102] = var(65); // [ var(102) , var(34) ] D[36,102] = var(64); // [ var(102) , var(36) ] D[39,102] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-1)*var(130)+(-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(102) , var(39) ] D[44,102] = (-1)*var(4); // [ var(102) , var(44) ] D[47,102] = (-1)*var(10); // [ var(102) , var(47) ] D[48,102] = (-1)*var(11); // [ var(102) , var(48) ] D[51,102] = (-1)*var(17); // [ var(102) , var(51) ] D[52,102] = (-1)*var(18); // [ var(102) , var(52) ] D[55,102] = (-1)*var(24); // [ var(102) , var(55) ] D[56,102] = (-1)*var(28); // [ var(102) , var(56) ] D[58,102] = (-1)*var(35); // [ var(102) , var(58) ] D[60,102] = (-1)*var(40); // [ var(102) , var(60) ] D[63,102] = (-1)*var(50); // [ var(102) , var(63) ] D[5,103] = var(98); // [ var(103) , var(5) ] D[11,103] = var(92); // [ var(103) , var(11) ] D[12,103] = (-1)*var(91); // [ var(103) , var(12) ] D[16,103] = (-1)*var(87); // [ var(103) , var(16) ] D[17,103] = (-1)*var(86); // [ var(103) , var(17) ] D[18,103] = (-1)*var(85); // [ var(103) , var(18) ] D[22,103] = var(81); // [ var(103) , var(22) ] D[23,103] = var(80); // [ var(103) , var(23) ] D[24,103] = var(79); // [ var(103) , var(24) ] D[28,103] = var(75); // [ var(103) , var(28) ] D[29,103] = (-1)*var(74); // [ var(103) , var(29) ] D[35,103] = (-1)*var(68); // [ var(103) , var(35) ] D[40,103] = (-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-2)*var(131)+(-1)*var(132); // [ var(103) , var(40) ] D[43,103] = var(1); // [ var(103) , var(43) ] D[45,103] = (-1)*var(7); // [ var(103) , var(45) ] D[46,103] = (-1)*var(8); // [ var(103) , var(46) ] D[49,103] = var(13); // [ var(103) , var(49) ] D[50,103] = (-1)*var(14); // [ var(103) , var(50) ] D[53,103] = var(20); // [ var(103) , var(53) ] D[59,103] = (-1)*var(34); // [ var(103) , var(59) ] D[60,103] = var(39); // [ var(103) , var(60) ] D[61,103] = var(44); // [ var(103) , var(61) ] D[62,103] = (-1)*var(47); // [ var(103) , var(62) ] D[4,104] = var(99); // [ var(104) , var(4) ] D[7,104] = var(98); // [ var(104) , var(7) ] D[9,104] = (-1)*var(94); // [ var(104) , var(9) ] D[10,104] = (-1)*var(93); // [ var(104) , var(10) ] D[13,104] = var(91); // [ var(104) , var(13) ] D[15,104] = var(88); // [ var(104) , var(15) ] D[25,104] = (-1)*var(78); // [ var(104) , var(25) ] D[28,104] = (-1)*var(76); // [ var(104) , var(28) ] D[30,104] = var(73); // [ var(104) , var(30) ] D[31,104] = var(72); // [ var(104) , var(31) ] D[35,104] = (-1)*var(70); // [ var(104) , var(35) ] D[36,104] = (-1)*var(67); // [ var(104) , var(36) ] D[41,104] = (-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(104) , var(41) ] D[44,104] = var(1); // [ var(104) , var(44) ] D[45,104] = (-1)*var(5); // [ var(104) , var(45) ] D[47,104] = (-1)*var(8); // [ var(104) , var(47) ] D[49,104] = (-1)*var(12); // [ var(104) , var(49) ] D[54,104] = var(21); // [ var(104) , var(54) ] D[56,104] = (-1)*var(26); // [ var(104) , var(56) ] D[57,104] = var(27); // [ var(104) , var(57) ] D[58,104] = (-1)*var(33); // [ var(104) , var(58) ] D[61,104] = var(43); // [ var(104) , var(61) ] D[62,104] = (-1)*var(46); // [ var(104) , var(62) ] D[3,105] = (-1)*var(101); // [ var(105) , var(3) ] D[6,105] = var(100); // [ var(105) , var(6) ] D[8,105] = var(98); // [ var(105) , var(8) ] D[10,105] = var(96); // [ var(105) , var(10) ] D[14,105] = (-1)*var(92); // [ var(105) , var(14) ] D[15,105] = (-1)*var(90); // [ var(105) , var(15) ] D[20,105] = var(87); // [ var(105) , var(20) ] D[24,105] = (-1)*var(83); // [ var(105) , var(24) ] D[27,105] = var(78); // [ var(105) , var(27) ] D[29,105] = var(77); // [ var(105) , var(29) ] D[33,105] = (-1)*var(73); // [ var(105) , var(33) ] D[35,105] = (-1)*var(71); // [ var(105) , var(35) ] D[37,105] = (-1)*var(69); // [ var(105) , var(37) ] D[38,105] = var(66); // [ var(105) , var(38) ] D[42,105] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-2)*var(130)+(-1)*var(131)+(-1)*var(132); // [ var(105) , var(42) ] D[46,105] = (-1)*var(5); // [ var(105) , var(46) ] D[47,105] = (-1)*var(7); // [ var(105) , var(47) ] D[50,105] = var(11); // [ var(105) , var(50) ] D[53,105] = (-1)*var(16); // [ var(105) , var(53) ] D[55,105] = var(19); // [ var(105) , var(55) ] D[57,105] = (-1)*var(25); // [ var(105) , var(57) ] D[58,105] = var(30); // [ var(105) , var(58) ] D[62,105] = (-1)*var(45); // [ var(105) , var(62) ] D[63,105] = var(48); // [ var(105) , var(63) ] D[1,106] = (-1)*var(103); // [ var(106) , var(1) ] D[5,106] = var(101); // [ var(106) , var(5) ] D[11,106] = var(96); // [ var(106) , var(11) ] D[12,106] = (-1)*var(95); // [ var(106) , var(12) ] D[16,106] = (-1)*var(90); // [ var(106) , var(16) ] D[18,106] = (-1)*var(89); // [ var(106) , var(18) ] D[21,106] = (-1)*var(86); // [ var(106) , var(21) ] D[23,106] = var(84); // [ var(106) , var(23) ] D[26,106] = var(81); // [ var(106) , var(26) ] D[27,106] = var(79); // [ var(106) , var(27) ] D[32,106] = var(75); // [ var(106) , var(32) ] D[33,106] = (-1)*var(74); // [ var(106) , var(33) ] D[38,106] = (-1)*var(68); // [ var(106) , var(38) ] D[40,106] = var(64); // [ var(106) , var(40) ] D[43,106] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-2)*var(131)+(-1)*var(132); // [ var(106) , var(43) ] D[46,106] = var(3); // [ var(106) , var(46) ] D[48,106] = (-1)*var(7); // [ var(106) , var(48) ] D[50,106] = var(10); // [ var(106) , var(50) ] D[52,106] = var(13); // [ var(106) , var(52) ] D[53,106] = (-1)*var(15); // [ var(106) , var(53) ] D[59,106] = var(31); // [ var(106) , var(59) ] D[60,106] = (-1)*var(36); // [ var(106) , var(60) ] D[61,106] = (-1)*var(41); // [ var(106) , var(61) ] D[63,106] = var(47); // [ var(106) , var(63) ] D[1,107] = (-1)*var(104); // [ var(107) , var(1) ] D[4,107] = var(102); // [ var(107) , var(4) ] D[7,107] = var(101); // [ var(107) , var(7) ] D[9,107] = (-1)*var(97); // [ var(107) , var(9) ] D[13,107] = var(95); // [ var(107) , var(13) ] D[14,107] = (-1)*var(93); // [ var(107) , var(14) ] D[20,107] = var(88); // [ var(107) , var(20) ] D[25,107] = (-1)*var(83); // [ var(107) , var(25) ] D[30,107] = var(77); // [ var(107) , var(30) ] D[32,107] = (-1)*var(76); // [ var(107) , var(32) ] D[34,107] = var(72); // [ var(107) , var(34) ] D[38,107] = (-1)*var(70); // [ var(107) , var(38) ] D[39,107] = (-1)*var(67); // [ var(107) , var(39) ] D[41,107] = var(64); // [ var(107) , var(41) ] D[44,107] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(107) , var(44) ] D[47,107] = var(3); // [ var(107) , var(47) ] D[48,107] = (-1)*var(5); // [ var(107) , var(48) ] D[52,107] = (-1)*var(12); // [ var(107) , var(52) ] D[54,107] = (-1)*var(17); // [ var(107) , var(54) ] D[56,107] = var(22); // [ var(107) , var(56) ] D[57,107] = (-1)*var(24); // [ var(107) , var(57) ] D[58,107] = var(29); // [ var(107) , var(58) ] D[61,107] = (-1)*var(40); // [ var(107) , var(61) ] D[63,107] = var(46); // [ var(107) , var(63) ] D[5,108] = var(104); // [ var(108) , var(5) ] D[7,108] = var(103); // [ var(108) , var(7) ] D[11,108] = var(99); // [ var(108) , var(11) ] D[16,108] = (-1)*var(94); // [ var(108) , var(16) ] D[17,108] = (-1)*var(93); // [ var(108) , var(17) ] D[19,108] = (-1)*var(91); // [ var(108) , var(19) ] D[22,108] = var(88); // [ var(108) , var(22) ] D[25,108] = (-1)*var(85); // [ var(108) , var(25) ] D[28,108] = var(82); // [ var(108) , var(28) ] D[30,108] = var(80); // [ var(108) , var(30) ] D[31,108] = var(79); // [ var(108) , var(31) ] D[36,108] = (-1)*var(74); // [ var(108) , var(36) ] D[40,108] = (-1)*var(70); // [ var(108) , var(40) ] D[41,108] = (-1)*var(68); // [ var(108) , var(41) ] D[45,108] = (-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-2)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(108) , var(45) ] D[48,108] = var(1); // [ var(108) , var(48) ] D[49,108] = (-1)*var(6); // [ var(108) , var(49) ] D[51,108] = (-1)*var(8); // [ var(108) , var(51) ] D[54,108] = (-1)*var(14); // [ var(108) , var(54) ] D[56,108] = var(20); // [ var(108) , var(56) ] D[59,108] = var(27); // [ var(108) , var(59) ] D[60,108] = (-1)*var(33); // [ var(108) , var(60) ] D[61,108] = (-1)*var(38); // [ var(108) , var(61) ] D[62,108] = var(42); // [ var(108) , var(62) ] D[3,109] = (-1)*var(106); // [ var(109) , var(3) ] D[5,109] = var(105); // [ var(109) , var(5) ] D[8,109] = var(103); // [ var(109) , var(8) ] D[12,109] = (-1)*var(100); // [ var(109) , var(12) ] D[17,109] = var(96); // [ var(109) , var(17) ] D[21,109] = (-1)*var(92); // [ var(109) , var(21) ] D[22,109] = (-1)*var(90); // [ var(109) , var(22) ] D[24,109] = (-1)*var(89); // [ var(109) , var(24) ] D[26,109] = var(87); // [ var(109) , var(26) ] D[27,109] = var(85); // [ var(109) , var(27) ] D[29,109] = var(84); // [ var(109) , var(29) ] D[33,109] = (-1)*var(80); // [ var(109) , var(33) ] D[37,109] = var(75); // [ var(109) , var(37) ] D[40,109] = (-1)*var(71); // [ var(109) , var(40) ] D[42,109] = (-1)*var(68); // [ var(109) , var(42) ] D[43,109] = var(66); // [ var(109) , var(43) ] D[46,109] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-2)*var(130)+(-2)*var(131)+(-1)*var(132); // [ var(109) , var(46) ] D[50,109] = (-1)*var(4); // [ var(109) , var(50) ] D[51,109] = (-1)*var(7); // [ var(109) , var(51) ] D[53,109] = var(9); // [ var(109) , var(53) ] D[55,109] = var(13); // [ var(109) , var(55) ] D[59,109] = (-1)*var(25); // [ var(109) , var(59) ] D[60,109] = var(30); // [ var(109) , var(60) ] D[62,109] = var(41); // [ var(109) , var(62) ] D[63,109] = (-1)*var(44); // [ var(109) , var(63) ] D[3,110] = (-1)*var(107); // [ var(110) , var(3) ] D[7,110] = var(105); // [ var(110) , var(7) ] D[8,110] = var(104); // [ var(110) , var(8) ] D[10,110] = var(102); // [ var(110) , var(10) ] D[13,110] = var(100); // [ var(110) , var(13) ] D[14,110] = (-1)*var(99); // [ var(110) , var(14) ] D[15,110] = (-1)*var(97); // [ var(110) , var(15) ] D[20,110] = var(94); // [ var(110) , var(20) ] D[31,110] = (-1)*var(83); // [ var(110) , var(31) ] D[34,110] = var(78); // [ var(110) , var(34) ] D[36,110] = var(77); // [ var(110) , var(36) ] D[37,110] = (-1)*var(76); // [ var(110) , var(37) ] D[39,110] = (-1)*var(73); // [ var(110) , var(39) ] D[41,110] = (-1)*var(71); // [ var(110) , var(41) ] D[42,110] = (-1)*var(70); // [ var(110) , var(42) ] D[44,110] = var(66); // [ var(110) , var(44) ] D[47,110] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-2)*var(130)+(-1)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(110) , var(47) ] D[51,110] = (-1)*var(5); // [ var(110) , var(51) ] D[54,110] = var(11); // [ var(110) , var(54) ] D[55,110] = (-1)*var(12); // [ var(110) , var(55) ] D[56,110] = (-1)*var(16); // [ var(110) , var(56) ] D[57,110] = var(18); // [ var(110) , var(57) ] D[58,110] = (-1)*var(23); // [ var(110) , var(58) ] D[62,110] = var(40); // [ var(110) , var(62) ] D[63,110] = (-1)*var(43); // [ var(110) , var(63) ] D[1,111] = (-1)*var(108); // [ var(111) , var(1) ] D[5,111] = var(107); // [ var(111) , var(5) ] D[7,111] = var(106); // [ var(111) , var(7) ] D[11,111] = var(102); // [ var(111) , var(11) ] D[16,111] = (-1)*var(97); // [ var(111) , var(16) ] D[19,111] = (-1)*var(95); // [ var(111) , var(19) ] D[21,111] = (-1)*var(93); // [ var(111) , var(21) ] D[25,111] = (-1)*var(89); // [ var(111) , var(25) ] D[26,111] = var(88); // [ var(111) , var(26) ] D[30,111] = var(84); // [ var(111) , var(30) ] D[32,111] = var(82); // [ var(111) , var(32) ] D[34,111] = var(79); // [ var(111) , var(34) ] D[39,111] = (-1)*var(74); // [ var(111) , var(39) ] D[43,111] = (-1)*var(70); // [ var(111) , var(43) ] D[44,111] = (-1)*var(68); // [ var(111) , var(44) ] D[45,111] = var(64); // [ var(111) , var(45) ] D[48,111] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-2)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(111) , var(48) ] D[51,111] = var(3); // [ var(111) , var(51) ] D[52,111] = (-1)*var(6); // [ var(111) , var(52) ] D[54,111] = var(10); // [ var(111) , var(54) ] D[56,111] = (-1)*var(15); // [ var(111) , var(56) ] D[59,111] = (-1)*var(24); // [ var(111) , var(59) ] D[60,111] = var(29); // [ var(111) , var(60) ] D[61,111] = var(35); // [ var(111) , var(61) ] D[63,111] = (-1)*var(42); // [ var(111) , var(63) ] D[6,112] = var(108); // [ var(112) , var(6) ] D[12,112] = var(104); // [ var(112) , var(12) ] D[13,112] = (-1)*var(103); // [ var(112) , var(13) ] D[18,112] = var(99); // [ var(112) , var(18) ] D[19,112] = (-1)*var(98); // [ var(112) , var(19) ] D[23,112] = (-1)*var(94); // [ var(112) , var(23) ] D[24,112] = (-1)*var(93); // [ var(112) , var(24) ] D[25,112] = (-1)*var(92); // [ var(112) , var(25) ] D[29,112] = var(88); // [ var(112) , var(29) ] D[30,112] = var(87); // [ var(112) , var(30) ] D[31,112] = var(86); // [ var(112) , var(31) ] D[35,112] = var(82); // [ var(112) , var(35) ] D[36,112] = (-1)*var(81); // [ var(112) , var(36) ] D[40,112] = var(76); // [ var(112) , var(40) ] D[41,112] = (-1)*var(75); // [ var(112) , var(41) ] D[45,112] = (-1)*var(69); // [ var(112) , var(45) ] D[49,112] = (-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-2)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(112) , var(49) ] D[52,112] = var(1); // [ var(112) , var(52) ] D[55,112] = (-1)*var(8); // [ var(112) , var(55) ] D[57,112] = (-1)*var(14); // [ var(112) , var(57) ] D[58,112] = var(20); // [ var(112) , var(58) ] D[59,112] = (-1)*var(21); // [ var(112) , var(59) ] D[60,112] = var(26); // [ var(112) , var(60) ] D[61,112] = var(32); // [ var(112) , var(61) ] D[62,112] = (-1)*var(37); // [ var(112) , var(62) ] D[4,113] = var(109); // [ var(113) , var(4) ] D[10,113] = (-1)*var(106); // [ var(113) , var(10) ] D[11,113] = (-1)*var(105); // [ var(113) , var(11) ] D[14,113] = var(103); // [ var(113) , var(14) ] D[17,113] = var(101); // [ var(113) , var(17) ] D[18,113] = var(100); // [ var(113) , var(18) ] D[21,113] = (-1)*var(98); // [ var(113) , var(21) ] D[24,113] = (-1)*var(95); // [ var(113) , var(24) ] D[27,113] = var(91); // [ var(113) , var(27) ] D[28,113] = (-1)*var(90); // [ var(113) , var(28) ] D[32,113] = var(87); // [ var(113) , var(32) ] D[35,113] = var(84); // [ var(113) , var(35) ] D[37,113] = (-1)*var(81); // [ var(113) , var(37) ] D[38,113] = (-1)*var(80); // [ var(113) , var(38) ] D[40,113] = (-1)*var(77); // [ var(113) , var(40) ] D[42,113] = var(74); // [ var(113) , var(42) ] D[43,113] = var(73); // [ var(113) , var(43) ] D[46,113] = (-1)*var(67); // [ var(113) , var(46) ] D[50,113] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-3)*var(130)+(-2)*var(131)+(-1)*var(132); // [ var(113) , var(50) ] D[53,113] = (-1)*var(2); // [ var(113) , var(53) ] D[54,113] = (-1)*var(7); // [ var(113) , var(54) ] D[57,113] = var(13); // [ var(113) , var(57) ] D[59,113] = (-1)*var(19); // [ var(113) , var(59) ] D[61,113] = var(30); // [ var(113) , var(61) ] D[62,113] = (-1)*var(36); // [ var(113) , var(62) ] D[63,113] = var(39); // [ var(113) , var(63) ] D[3,114] = (-1)*var(111); // [ var(114) , var(3) ] D[5,114] = var(110); // [ var(114) , var(5) ] D[7,114] = var(109); // [ var(114) , var(7) ] D[8,114] = var(108); // [ var(114) , var(8) ] D[17,114] = var(102); // [ var(114) , var(17) ] D[19,114] = (-1)*var(100); // [ var(114) , var(19) ] D[21,114] = (-1)*var(99); // [ var(114) , var(21) ] D[22,114] = (-1)*var(97); // [ var(114) , var(22) ] D[26,114] = var(94); // [ var(114) , var(26) ] D[31,114] = (-1)*var(89); // [ var(114) , var(31) ] D[34,114] = var(85); // [ var(114) , var(34) ] D[36,114] = var(84); // [ var(114) , var(36) ] D[37,114] = var(82); // [ var(114) , var(37) ] D[39,114] = (-1)*var(80); // [ var(114) , var(39) ] D[45,114] = (-1)*var(71); // [ var(114) , var(45) ] D[46,114] = (-1)*var(70); // [ var(114) , var(46) ] D[47,114] = (-1)*var(68); // [ var(114) , var(47) ] D[48,114] = var(66); // [ var(114) , var(48) ] D[51,114] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-2)*var(130)+(-2)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(114) , var(51) ] D[54,114] = (-1)*var(4); // [ var(114) , var(54) ] D[55,114] = (-1)*var(6); // [ var(114) , var(55) ] D[56,114] = var(9); // [ var(114) , var(56) ] D[59,114] = var(18); // [ var(114) , var(59) ] D[60,114] = (-1)*var(23); // [ var(114) , var(60) ] D[62,114] = (-1)*var(35); // [ var(114) , var(62) ] D[63,114] = var(38); // [ var(114) , var(63) ] D[1,115] = (-1)*var(112); // [ var(115) , var(1) ] D[6,115] = var(111); // [ var(115) , var(6) ] D[12,115] = var(107); // [ var(115) , var(12) ] D[13,115] = (-1)*var(106); // [ var(115) , var(13) ] D[18,115] = var(102); // [ var(115) , var(18) ] D[19,115] = (-1)*var(101); // [ var(115) , var(19) ] D[23,115] = (-1)*var(97); // [ var(115) , var(23) ] D[25,115] = (-1)*var(96); // [ var(115) , var(25) ] D[27,115] = (-1)*var(93); // [ var(115) , var(27) ] D[30,115] = var(90); // [ var(115) , var(30) ] D[33,115] = var(88); // [ var(115) , var(33) ] D[34,115] = var(86); // [ var(115) , var(34) ] D[38,115] = var(82); // [ var(115) , var(38) ] D[39,115] = (-1)*var(81); // [ var(115) , var(39) ] D[43,115] = var(76); // [ var(115) , var(43) ] D[44,115] = (-1)*var(75); // [ var(115) , var(44) ] D[48,115] = (-1)*var(69); // [ var(115) , var(48) ] D[49,115] = var(64); // [ var(115) , var(49) ] D[52,115] = (-1)*var(127)+(-1)*var(128)+(-1)*var(129)+(-2)*var(130)+(-2)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(115) , var(52) ] D[55,115] = var(3); // [ var(115) , var(55) ] D[57,115] = var(10); // [ var(115) , var(57) ] D[58,115] = (-1)*var(15); // [ var(115) , var(58) ] D[59,115] = var(17); // [ var(115) , var(59) ] D[60,115] = (-1)*var(22); // [ var(115) , var(60) ] D[61,115] = (-1)*var(28); // [ var(115) , var(61) ] D[63,115] = var(37); // [ var(115) , var(63) ] D[2,116] = var(113); // [ var(116) , var(2) ] D[9,116] = (-1)*var(109); // [ var(116) , var(9) ] D[15,116] = var(106); // [ var(116) , var(15) ] D[16,116] = var(105); // [ var(116) , var(16) ] D[20,116] = (-1)*var(103); // [ var(116) , var(20) ] D[22,116] = (-1)*var(101); // [ var(116) , var(22) ] D[23,116] = (-1)*var(100); // [ var(116) , var(23) ] D[26,116] = var(98); // [ var(116) , var(26) ] D[28,116] = var(96); // [ var(116) , var(28) ] D[29,116] = var(95); // [ var(116) , var(29) ] D[32,116] = (-1)*var(92); // [ var(116) , var(32) ] D[33,116] = (-1)*var(91); // [ var(116) , var(33) ] D[35,116] = (-1)*var(89); // [ var(116) , var(35) ] D[37,116] = var(86); // [ var(116) , var(37) ] D[38,116] = var(85); // [ var(116) , var(38) ] D[40,116] = var(83); // [ var(116) , var(40) ] D[42,116] = (-1)*var(79); // [ var(116) , var(42) ] D[43,116] = (-1)*var(78); // [ var(116) , var(43) ] D[46,116] = var(72); // [ var(116) , var(46) ] D[50,116] = (-1)*var(65); // [ var(116) , var(50) ] D[53,116] = (-1)*var(127)+(-2)*var(128)+(-2)*var(129)+(-3)*var(130)+(-2)*var(131)+(-1)*var(132); // [ var(116) , var(53) ] D[56,116] = (-1)*var(7); // [ var(116) , var(56) ] D[58,116] = var(13); // [ var(116) , var(58) ] D[60,116] = (-1)*var(19); // [ var(116) , var(60) ] D[61,116] = var(25); // [ var(116) , var(61) ] D[62,116] = (-1)*var(31); // [ var(116) , var(62) ] D[63,116] = var(34); // [ var(116) , var(63) ] D[4,117] = var(114); // [ var(117) , var(4) ] D[7,117] = var(113); // [ var(117) , var(7) ] D[10,117] = (-1)*var(111); // [ var(117) , var(10) ] D[11,117] = (-1)*var(110); // [ var(117) , var(11) ] D[14,117] = var(108); // [ var(117) , var(14) ] D[17,117] = var(107); // [ var(117) , var(17) ] D[21,117] = (-1)*var(104); // [ var(117) , var(21) ] D[25,117] = var(100); // [ var(117) , var(25) ] D[28,117] = (-1)*var(97); // [ var(117) , var(28) ] D[31,117] = (-1)*var(95); // [ var(117) , var(31) ] D[32,117] = var(94); // [ var(117) , var(32) ] D[34,117] = var(91); // [ var(117) , var(34) ] D[37,117] = (-1)*var(88); // [ var(117) , var(37) ] D[41,117] = var(84); // [ var(117) , var(41) ] D[44,117] = (-1)*var(80); // [ var(117) , var(44) ] D[45,117] = (-1)*var(77); // [ var(117) , var(45) ] D[47,117] = var(74); // [ var(117) , var(47) ] D[48,117] = var(73); // [ var(117) , var(48) ] D[50,117] = (-1)*var(70); // [ var(117) , var(50) ] D[51,117] = (-1)*var(67); // [ var(117) , var(51) ] D[54,117] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-3)*var(130)+(-2)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(117) , var(54) ] D[56,117] = (-1)*var(2); // [ var(117) , var(56) ] D[57,117] = (-1)*var(6); // [ var(117) , var(57) ] D[59,117] = var(12); // [ var(117) , var(59) ] D[61,117] = (-1)*var(23); // [ var(117) , var(61) ] D[62,117] = var(29); // [ var(117) , var(62) ] D[63,117] = (-1)*var(33); // [ var(117) , var(63) ] D[3,118] = (-1)*var(115); // [ var(118) , var(3) ] D[6,118] = var(114); // [ var(118) , var(6) ] D[8,118] = var(112); // [ var(118) , var(8) ] D[12,118] = var(110); // [ var(118) , var(12) ] D[13,118] = (-1)*var(109); // [ var(118) , var(13) ] D[19,118] = (-1)*var(105); // [ var(118) , var(19) ] D[24,118] = var(102); // [ var(118) , var(24) ] D[27,118] = (-1)*var(99); // [ var(118) , var(27) ] D[29,118] = (-1)*var(97); // [ var(118) , var(29) ] D[31,118] = (-1)*var(96); // [ var(118) , var(31) ] D[33,118] = var(94); // [ var(118) , var(33) ] D[34,118] = var(92); // [ var(118) , var(34) ] D[36,118] = var(90); // [ var(118) , var(36) ] D[39,118] = (-1)*var(87); // [ var(118) , var(39) ] D[42,118] = var(82); // [ var(118) , var(42) ] D[46,118] = var(76); // [ var(118) , var(46) ] D[47,118] = (-1)*var(75); // [ var(118) , var(47) ] D[49,118] = (-1)*var(71); // [ var(118) , var(49) ] D[51,118] = (-1)*var(69); // [ var(118) , var(51) ] D[52,118] = var(66); // [ var(118) , var(52) ] D[55,118] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-2)*var(130)+(-2)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(118) , var(55) ] D[57,118] = (-1)*var(4); // [ var(118) , var(57) ] D[58,118] = var(9); // [ var(118) , var(58) ] D[59,118] = (-1)*var(11); // [ var(118) , var(59) ] D[60,118] = var(16); // [ var(118) , var(60) ] D[62,118] = var(28); // [ var(118) , var(62) ] D[63,118] = (-1)*var(32); // [ var(118) , var(63) ] D[2,119] = var(117); // [ var(119) , var(2) ] D[7,119] = var(116); // [ var(119) , var(7) ] D[9,119] = (-1)*var(114); // [ var(119) , var(9) ] D[15,119] = var(111); // [ var(119) , var(15) ] D[16,119] = var(110); // [ var(119) , var(16) ] D[20,119] = (-1)*var(108); // [ var(119) , var(20) ] D[22,119] = (-1)*var(107); // [ var(119) , var(22) ] D[26,119] = var(104); // [ var(119) , var(26) ] D[28,119] = var(102); // [ var(119) , var(28) ] D[30,119] = (-1)*var(100); // [ var(119) , var(30) ] D[32,119] = (-1)*var(99); // [ var(119) , var(32) ] D[36,119] = var(95); // [ var(119) , var(36) ] D[37,119] = var(93); // [ var(119) , var(37) ] D[39,119] = (-1)*var(91); // [ var(119) , var(39) ] D[41,119] = (-1)*var(89); // [ var(119) , var(41) ] D[44,119] = var(85); // [ var(119) , var(44) ] D[45,119] = var(83); // [ var(119) , var(45) ] D[47,119] = (-1)*var(79); // [ var(119) , var(47) ] D[48,119] = (-1)*var(78); // [ var(119) , var(48) ] D[51,119] = var(72); // [ var(119) , var(51) ] D[53,119] = (-1)*var(70); // [ var(119) , var(53) ] D[54,119] = (-1)*var(65); // [ var(119) , var(54) ] D[56,119] = (-1)*var(127)+(-2)*var(128)+(-2)*var(129)+(-3)*var(130)+(-2)*var(131)+(-1)*var(132)+(-1)*var(133); // [ var(119) , var(56) ] D[58,119] = (-1)*var(6); // [ var(119) , var(58) ] D[60,119] = var(12); // [ var(119) , var(60) ] D[61,119] = (-1)*var(18); // [ var(119) , var(61) ] D[62,119] = var(24); // [ var(119) , var(62) ] D[63,119] = (-1)*var(27); // [ var(119) , var(63) ] D[4,120] = var(118); // [ var(120) , var(4) ] D[6,120] = var(117); // [ var(120) , var(6) ] D[10,120] = (-1)*var(115); // [ var(120) , var(10) ] D[13,120] = (-1)*var(113); // [ var(120) , var(13) ] D[14,120] = var(112); // [ var(120) , var(14) ] D[18,120] = (-1)*var(110); // [ var(120) , var(18) ] D[24,120] = var(107); // [ var(120) , var(24) ] D[25,120] = var(105); // [ var(120) , var(25) ] D[27,120] = (-1)*var(104); // [ var(120) , var(27) ] D[31,120] = (-1)*var(101); // [ var(120) , var(31) ] D[34,120] = var(98); // [ var(120) , var(34) ] D[35,120] = (-1)*var(97); // [ var(120) , var(35) ] D[38,120] = var(94); // [ var(120) , var(38) ] D[41,120] = var(90); // [ var(120) , var(41) ] D[42,120] = (-1)*var(88); // [ var(120) , var(42) ] D[44,120] = (-1)*var(87); // [ var(120) , var(44) ] D[47,120] = var(81); // [ var(120) , var(47) ] D[49,120] = (-1)*var(77); // [ var(120) , var(49) ] D[50,120] = var(76); // [ var(120) , var(50) ] D[52,120] = var(73); // [ var(120) , var(52) ] D[54,120] = (-1)*var(69); // [ var(120) , var(54) ] D[55,120] = (-1)*var(67); // [ var(120) , var(55) ] D[57,120] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-3)*var(130)+(-2)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(120) , var(57) ] D[58,120] = (-1)*var(2); // [ var(120) , var(58) ] D[59,120] = (-1)*var(5); // [ var(120) , var(59) ] D[61,120] = var(16); // [ var(120) , var(61) ] D[62,120] = (-1)*var(22); // [ var(120) , var(62) ] D[63,120] = var(26); // [ var(120) , var(63) ] D[2,121] = var(120); // [ var(121) , var(2) ] D[6,121] = var(119); // [ var(121) , var(6) ] D[9,121] = (-1)*var(118); // [ var(121) , var(9) ] D[13,121] = (-1)*var(116); // [ var(121) , var(13) ] D[15,121] = var(115); // [ var(121) , var(15) ] D[20,121] = (-1)*var(112); // [ var(121) , var(20) ] D[23,121] = var(110); // [ var(121) , var(23) ] D[29,121] = (-1)*var(107); // [ var(121) , var(29) ] D[30,121] = (-1)*var(105); // [ var(121) , var(30) ] D[33,121] = var(104); // [ var(121) , var(33) ] D[35,121] = var(102); // [ var(121) , var(35) ] D[36,121] = var(101); // [ var(121) , var(36) ] D[38,121] = (-1)*var(99); // [ var(121) , var(38) ] D[39,121] = (-1)*var(98); // [ var(121) , var(39) ] D[41,121] = (-1)*var(96); // [ var(121) , var(41) ] D[42,121] = var(93); // [ var(121) , var(42) ] D[44,121] = var(92); // [ var(121) , var(44) ] D[47,121] = (-1)*var(86); // [ var(121) , var(47) ] D[49,121] = var(83); // [ var(121) , var(49) ] D[52,121] = (-1)*var(78); // [ var(121) , var(52) ] D[53,121] = var(76); // [ var(121) , var(53) ] D[55,121] = var(72); // [ var(121) , var(55) ] D[56,121] = (-1)*var(69); // [ var(121) , var(56) ] D[57,121] = (-1)*var(65); // [ var(121) , var(57) ] D[58,121] = (-1)*var(127)+(-2)*var(128)+(-2)*var(129)+(-3)*var(130)+(-2)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(121) , var(58) ] D[60,121] = (-1)*var(5); // [ var(121) , var(60) ] D[61,121] = var(11); // [ var(121) , var(61) ] D[62,121] = (-1)*var(17); // [ var(121) , var(62) ] D[63,121] = var(21); // [ var(121) , var(63) ] D[5,122] = var(120); // [ var(122) , var(5) ] D[11,122] = var(118); // [ var(122) , var(11) ] D[12,122] = (-1)*var(117); // [ var(122) , var(12) ] D[17,122] = (-1)*var(115); // [ var(122) , var(17) ] D[18,122] = (-1)*var(114); // [ var(122) , var(18) ] D[19,122] = var(113); // [ var(122) , var(19) ] D[21,122] = var(112); // [ var(122) , var(21) ] D[24,122] = var(111); // [ var(122) , var(24) ] D[25,122] = var(109); // [ var(122) , var(25) ] D[27,122] = (-1)*var(108); // [ var(122) , var(27) ] D[31,122] = (-1)*var(106); // [ var(122) , var(31) ] D[34,122] = var(103); // [ var(122) , var(34) ] D[40,122] = (-1)*var(97); // [ var(122) , var(40) ] D[43,122] = var(94); // [ var(122) , var(43) ] D[45,122] = var(90); // [ var(122) , var(45) ] D[46,122] = (-1)*var(88); // [ var(122) , var(46) ] D[48,122] = (-1)*var(87); // [ var(122) , var(48) ] D[49,122] = (-1)*var(84); // [ var(122) , var(49) ] D[50,122] = (-1)*var(82); // [ var(122) , var(50) ] D[51,122] = var(81); // [ var(122) , var(51) ] D[52,122] = var(80); // [ var(122) , var(52) ] D[54,122] = var(75); // [ var(122) , var(54) ] D[55,122] = (-1)*var(74); // [ var(122) , var(55) ] D[57,122] = (-1)*var(68); // [ var(122) , var(57) ] D[59,122] = (-1)*var(127)+(-1)*var(128)+(-2)*var(129)+(-3)*var(130)+(-3)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(122) , var(59) ] D[60,122] = (-1)*var(2); // [ var(122) , var(60) ] D[61,122] = (-1)*var(9); // [ var(122) , var(61) ] D[62,122] = var(15); // [ var(122) , var(62) ] D[63,122] = (-1)*var(20); // [ var(122) , var(63) ] D[2,123] = var(122); // [ var(123) , var(2) ] D[5,123] = var(121); // [ var(123) , var(5) ] D[12,123] = (-1)*var(119); // [ var(123) , var(12) ] D[16,123] = (-1)*var(118); // [ var(123) , var(16) ] D[19,123] = var(116); // [ var(123) , var(19) ] D[22,123] = var(115); // [ var(123) , var(22) ] D[23,123] = var(114); // [ var(123) , var(23) ] D[26,123] = (-1)*var(112); // [ var(123) , var(26) ] D[29,123] = (-1)*var(111); // [ var(123) , var(29) ] D[30,123] = (-1)*var(109); // [ var(123) , var(30) ] D[33,123] = var(108); // [ var(123) , var(33) ] D[36,123] = var(106); // [ var(123) , var(36) ] D[39,123] = (-1)*var(103); // [ var(123) , var(39) ] D[40,123] = var(102); // [ var(123) , var(40) ] D[43,123] = (-1)*var(99); // [ var(123) , var(43) ] D[45,123] = (-1)*var(96); // [ var(123) , var(45) ] D[46,123] = var(93); // [ var(123) , var(46) ] D[48,123] = var(92); // [ var(123) , var(48) ] D[49,123] = var(89); // [ var(123) , var(49) ] D[51,123] = (-1)*var(86); // [ var(123) , var(51) ] D[52,123] = (-1)*var(85); // [ var(123) , var(52) ] D[53,123] = (-1)*var(82); // [ var(123) , var(53) ] D[55,123] = var(79); // [ var(123) , var(55) ] D[56,123] = var(75); // [ var(123) , var(56) ] D[58,123] = (-1)*var(68); // [ var(123) , var(58) ] D[59,123] = (-1)*var(65); // [ var(123) , var(59) ] D[60,123] = (-1)*var(127)+(-2)*var(128)+(-2)*var(129)+(-3)*var(130)+(-3)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(123) , var(60) ] D[61,123] = (-1)*var(4); // [ var(123) , var(61) ] D[62,123] = var(10); // [ var(123) , var(62) ] D[63,123] = (-1)*var(14); // [ var(123) , var(63) ] D[4,124] = var(123); // [ var(124) , var(4) ] D[9,124] = var(122); // [ var(124) , var(9) ] D[11,124] = (-1)*var(121); // [ var(124) , var(11) ] D[16,124] = (-1)*var(120); // [ var(124) , var(16) ] D[18,124] = var(119); // [ var(124) , var(18) ] D[23,124] = var(117); // [ var(124) , var(23) ] D[25,124] = (-1)*var(116); // [ var(124) , var(25) ] D[28,124] = var(115); // [ var(124) , var(28) ] D[30,124] = (-1)*var(113); // [ var(124) , var(30) ] D[32,124] = (-1)*var(112); // [ var(124) , var(32) ] D[35,124] = (-1)*var(111); // [ var(124) , var(35) ] D[38,124] = var(108); // [ var(124) , var(38) ] D[40,124] = var(107); // [ var(124) , var(40) ] D[41,124] = var(106); // [ var(124) , var(41) ] D[43,124] = (-1)*var(104); // [ var(124) , var(43) ] D[44,124] = (-1)*var(103); // [ var(124) , var(44) ] D[45,124] = (-1)*var(101); // [ var(124) , var(45) ] D[48,124] = var(98); // [ var(124) , var(48) ] D[49,124] = var(95); // [ var(124) , var(49) ] D[50,124] = var(93); // [ var(124) , var(50) ] D[52,124] = (-1)*var(91); // [ var(124) , var(52) ] D[53,124] = var(88); // [ var(124) , var(53) ] D[54,124] = (-1)*var(86); // [ var(124) , var(54) ] D[56,124] = (-1)*var(81); // [ var(124) , var(56) ] D[57,124] = var(79); // [ var(124) , var(57) ] D[58,124] = var(74); // [ var(124) , var(58) ] D[59,124] = (-1)*var(72); // [ var(124) , var(59) ] D[60,124] = (-1)*var(67); // [ var(124) , var(60) ] D[61,124] = (-1)*var(127)+(-2)*var(128)+(-2)*var(129)+(-4)*var(130)+(-3)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(124) , var(61) ] D[62,124] = (-1)*var(3); // [ var(124) , var(62) ] D[63,124] = var(8); // [ var(124) , var(63) ] D[3,125] = var(124); // [ var(125) , var(3) ] D[10,125] = (-1)*var(123); // [ var(125) , var(10) ] D[15,125] = (-1)*var(122); // [ var(125) , var(15) ] D[17,125] = var(121); // [ var(125) , var(17) ] D[22,125] = var(120); // [ var(125) , var(22) ] D[24,125] = (-1)*var(119); // [ var(125) , var(24) ] D[28,125] = (-1)*var(118); // [ var(125) , var(28) ] D[29,125] = (-1)*var(117); // [ var(125) , var(29) ] D[31,125] = var(116); // [ var(125) , var(31) ] D[35,125] = var(114); // [ var(125) , var(35) ] D[36,125] = var(113); // [ var(125) , var(36) ] D[37,125] = var(112); // [ var(125) , var(37) ] D[40,125] = (-1)*var(110); // [ var(125) , var(40) ] D[41,125] = (-1)*var(109); // [ var(125) , var(41) ] D[42,125] = (-1)*var(108); // [ var(125) , var(42) ] D[45,125] = var(105); // [ var(125) , var(45) ] D[46,125] = var(104); // [ var(125) , var(46) ] D[47,125] = var(103); // [ var(125) , var(47) ] D[49,125] = (-1)*var(100); // [ var(125) , var(49) ] D[50,125] = (-1)*var(99); // [ var(125) , var(50) ] D[51,125] = (-1)*var(98); // [ var(125) , var(51) ] D[53,125] = (-1)*var(94); // [ var(125) , var(53) ] D[54,125] = var(92); // [ var(125) , var(54) ] D[55,125] = var(91); // [ var(125) , var(55) ] D[56,125] = var(87); // [ var(125) , var(56) ] D[57,125] = (-1)*var(85); // [ var(125) , var(57) ] D[58,125] = (-1)*var(80); // [ var(125) , var(58) ] D[59,125] = var(78); // [ var(125) , var(59) ] D[60,125] = var(73); // [ var(125) , var(60) ] D[61,125] = (-1)*var(66); // [ var(125) , var(61) ] D[62,125] = (-1)*var(127)+(-2)*var(128)+(-3)*var(129)+(-4)*var(130)+(-3)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(125) , var(62) ] D[63,125] = (-1)*var(1); // [ var(125) , var(63) ] D[1,126] = var(125); // [ var(126) , var(1) ] D[8,126] = (-1)*var(124); // [ var(126) , var(8) ] D[14,126] = var(123); // [ var(126) , var(14) ] D[20,126] = var(122); // [ var(126) , var(20) ] D[21,126] = (-1)*var(121); // [ var(126) , var(21) ] D[26,126] = (-1)*var(120); // [ var(126) , var(26) ] D[27,126] = var(119); // [ var(126) , var(27) ] D[32,126] = var(118); // [ var(126) , var(32) ] D[33,126] = var(117); // [ var(126) , var(33) ] D[34,126] = (-1)*var(116); // [ var(126) , var(34) ] D[37,126] = (-1)*var(115); // [ var(126) , var(37) ] D[38,126] = (-1)*var(114); // [ var(126) , var(38) ] D[39,126] = (-1)*var(113); // [ var(126) , var(39) ] D[42,126] = var(111); // [ var(126) , var(42) ] D[43,126] = var(110); // [ var(126) , var(43) ] D[44,126] = var(109); // [ var(126) , var(44) ] D[46,126] = (-1)*var(107); // [ var(126) , var(46) ] D[47,126] = (-1)*var(106); // [ var(126) , var(47) ] D[48,126] = (-1)*var(105); // [ var(126) , var(48) ] D[50,126] = var(102); // [ var(126) , var(50) ] D[51,126] = var(101); // [ var(126) , var(51) ] D[52,126] = var(100); // [ var(126) , var(52) ] D[53,126] = var(97); // [ var(126) , var(53) ] D[54,126] = (-1)*var(96); // [ var(126) , var(54) ] D[55,126] = (-1)*var(95); // [ var(126) , var(55) ] D[56,126] = (-1)*var(90); // [ var(126) , var(56) ] D[57,126] = var(89); // [ var(126) , var(57) ] D[58,126] = var(84); // [ var(126) , var(58) ] D[59,126] = (-1)*var(83); // [ var(126) , var(59) ] D[60,126] = (-1)*var(77); // [ var(126) , var(60) ] D[61,126] = var(71); // [ var(126) , var(61) ] D[62,126] = (-1)*var(64); // [ var(126) , var(62) ] D[63,126] = (-2)*var(127)+(-2)*var(128)+(-3)*var(129)+(-4)*var(130)+(-3)*var(131)+(-2)*var(132)+(-1)*var(133); // [ var(126) , var(63) ] // X(i) * X(j): D[1,3] = var(8); // [ var(3) , var(1) ] D[1,10] = var(14); // [ var(10) , var(1) ] D[1,15] = var(20); // [ var(15) , var(1) ] D[1,17] = var(21); // [ var(17) , var(1) ] D[1,22] = var(26); // [ var(22) , var(1) ] D[1,24] = var(27); // [ var(24) , var(1) ] D[1,28] = var(32); // [ var(28) , var(1) ] D[1,29] = var(33); // [ var(29) , var(1) ] D[1,31] = var(34); // [ var(31) , var(1) ] D[1,35] = var(38); // [ var(35) , var(1) ] D[1,36] = var(39); // [ var(36) , var(1) ] D[1,40] = var(43); // [ var(40) , var(1) ] D[1,41] = var(44); // [ var(41) , var(1) ] D[1,45] = var(48); // [ var(45) , var(1) ] D[1,49] = var(52); // [ var(49) , var(1) ] D[1,62] = (-1)*var(63); // [ var(62) , var(1) ] D[2,4] = var(9); // [ var(4) , var(2) ] D[2,10] = var(15); // [ var(10) , var(2) ] D[2,11] = var(16); // [ var(11) , var(2) ] D[2,14] = var(20); // [ var(14) , var(2) ] D[2,17] = var(22); // [ var(17) , var(2) ] D[2,18] = var(23); // [ var(18) , var(2) ] D[2,21] = var(26); // [ var(21) , var(2) ] D[2,24] = var(29); // [ var(24) , var(2) ] D[2,25] = var(30); // [ var(25) , var(2) ] D[2,27] = var(33); // [ var(27) , var(2) ] D[2,31] = var(36); // [ var(31) , var(2) ] D[2,34] = var(39); // [ var(34) , var(2) ] D[2,50] = (-1)*var(53); // [ var(50) , var(2) ] D[2,54] = (-1)*var(56); // [ var(54) , var(2) ] D[2,57] = (-1)*var(58); // [ var(57) , var(2) ] D[2,59] = (-1)*var(60); // [ var(59) , var(2) ] D[3,4] = var(10); // [ var(4) , var(3) ] D[3,9] = var(15); // [ var(9) , var(3) ] D[3,11] = var(17); // [ var(11) , var(3) ] D[3,16] = var(22); // [ var(16) , var(3) ] D[3,18] = var(24); // [ var(18) , var(3) ] D[3,23] = var(29); // [ var(23) , var(3) ] D[3,25] = var(31); // [ var(25) , var(3) ] D[3,30] = var(36); // [ var(30) , var(3) ] D[3,32] = var(37); // [ var(32) , var(3) ] D[3,38] = var(42); // [ var(38) , var(3) ] D[3,43] = var(46); // [ var(43) , var(3) ] D[3,44] = var(47); // [ var(44) , var(3) ] D[3,48] = var(51); // [ var(48) , var(3) ] D[3,52] = var(55); // [ var(52) , var(3) ] D[3,61] = (-1)*var(62); // [ var(61) , var(3) ] D[4,5] = var(11); // [ var(5) , var(4) ] D[4,8] = (-1)*var(14); // [ var(8) , var(4) ] D[4,12] = var(18); // [ var(12) , var(4) ] D[4,19] = var(25); // [ var(19) , var(4) ] D[4,22] = (-1)*var(28); // [ var(22) , var(4) ] D[4,26] = (-1)*var(32); // [ var(26) , var(4) ] D[4,29] = (-1)*var(35); // [ var(29) , var(4) ] D[4,33] = (-1)*var(38); // [ var(33) , var(4) ] D[4,36] = (-1)*var(41); // [ var(36) , var(4) ] D[4,39] = (-1)*var(44); // [ var(39) , var(4) ] D[4,46] = (-1)*var(50); // [ var(46) , var(4) ] D[4,51] = (-1)*var(54); // [ var(51) , var(4) ] D[4,55] = (-1)*var(57); // [ var(55) , var(4) ] D[4,60] = (-1)*var(61); // [ var(60) , var(4) ] D[5,6] = var(12); // [ var(6) , var(5) ] D[5,9] = (-1)*var(16); // [ var(9) , var(5) ] D[5,10] = (-1)*var(17); // [ var(10) , var(5) ] D[5,13] = var(19); // [ var(13) , var(5) ] D[5,14] = (-1)*var(21); // [ var(14) , var(5) ] D[5,15] = (-1)*var(22); // [ var(15) , var(5) ] D[5,20] = (-1)*var(26); // [ var(20) , var(5) ] D[5,35] = (-1)*var(40); // [ var(35) , var(5) ] D[5,38] = (-1)*var(43); // [ var(38) , var(5) ] D[5,41] = (-1)*var(45); // [ var(41) , var(5) ] D[5,42] = (-1)*var(46); // [ var(42) , var(5) ] D[5,44] = (-1)*var(48); // [ var(44) , var(5) ] D[5,47] = (-1)*var(51); // [ var(47) , var(5) ] D[5,57] = (-1)*var(59); // [ var(57) , var(5) ] D[5,58] = (-1)*var(60); // [ var(58) , var(5) ] D[6,7] = var(13); // [ var(7) , var(6) ] D[6,11] = (-1)*var(18); // [ var(11) , var(6) ] D[6,16] = (-1)*var(23); // [ var(16) , var(6) ] D[6,17] = (-1)*var(24); // [ var(17) , var(6) ] D[6,21] = (-1)*var(27); // [ var(21) , var(6) ] D[6,22] = (-1)*var(29); // [ var(22) , var(6) ] D[6,26] = (-1)*var(33); // [ var(26) , var(6) ] D[6,28] = (-1)*var(35); // [ var(28) , var(6) ] D[6,32] = (-1)*var(38); // [ var(32) , var(6) ] D[6,37] = (-1)*var(42); // [ var(37) , var(6) ] D[6,45] = (-1)*var(49); // [ var(45) , var(6) ] D[6,48] = (-1)*var(52); // [ var(48) , var(6) ] D[6,51] = (-1)*var(55); // [ var(51) , var(6) ] D[6,54] = (-1)*var(57); // [ var(54) , var(6) ] D[6,56] = (-1)*var(58); // [ var(56) , var(6) ] D[7,12] = (-1)*var(19); // [ var(12) , var(7) ] D[7,18] = (-1)*var(25); // [ var(18) , var(7) ] D[7,23] = (-1)*var(30); // [ var(23) , var(7) ] D[7,24] = (-1)*var(31); // [ var(24) , var(7) ] D[7,27] = (-1)*var(34); // [ var(27) , var(7) ] D[7,29] = (-1)*var(36); // [ var(29) , var(7) ] D[7,33] = (-1)*var(39); // [ var(33) , var(7) ] D[7,35] = (-1)*var(41); // [ var(35) , var(7) ] D[7,38] = (-1)*var(44); // [ var(38) , var(7) ] D[7,40] = (-1)*var(45); // [ var(40) , var(7) ] D[7,42] = (-1)*var(47); // [ var(42) , var(7) ] D[7,43] = (-1)*var(48); // [ var(43) , var(7) ] D[7,46] = (-1)*var(51); // [ var(46) , var(7) ] D[7,50] = (-1)*var(54); // [ var(50) , var(7) ] D[7,53] = (-1)*var(56); // [ var(53) , var(7) ] D[8,9] = var(20); // [ var(9) , var(8) ] D[8,11] = var(21); // [ var(11) , var(8) ] D[8,16] = var(26); // [ var(16) , var(8) ] D[8,18] = var(27); // [ var(18) , var(8) ] D[8,23] = var(33); // [ var(23) , var(8) ] D[8,25] = var(34); // [ var(25) , var(8) ] D[8,28] = (-1)*var(37); // [ var(28) , var(8) ] D[8,30] = var(39); // [ var(30) , var(8) ] D[8,35] = (-1)*var(42); // [ var(35) , var(8) ] D[8,40] = (-1)*var(46); // [ var(40) , var(8) ] D[8,41] = (-1)*var(47); // [ var(41) , var(8) ] D[8,45] = (-1)*var(51); // [ var(45) , var(8) ] D[8,49] = (-1)*var(55); // [ var(49) , var(8) ] D[8,61] = var(63); // [ var(61) , var(8) ] D[9,12] = var(23); // [ var(12) , var(9) ] D[9,17] = var(28); // [ var(17) , var(9) ] D[9,19] = var(30); // [ var(19) , var(9) ] D[9,21] = var(32); // [ var(21) , var(9) ] D[9,24] = var(35); // [ var(24) , var(9) ] D[9,27] = var(38); // [ var(27) , var(9) ] D[9,31] = var(41); // [ var(31) , var(9) ] D[9,34] = var(44); // [ var(34) , var(9) ] D[9,46] = var(53); // [ var(46) , var(9) ] D[9,51] = var(56); // [ var(51) , var(9) ] D[9,55] = var(58); // [ var(55) , var(9) ] D[9,59] = (-1)*var(61); // [ var(59) , var(9) ] D[10,12] = var(24); // [ var(12) , var(10) ] D[10,16] = var(28); // [ var(16) , var(10) ] D[10,19] = var(31); // [ var(19) , var(10) ] D[10,23] = var(35); // [ var(23) , var(10) ] D[10,26] = (-1)*var(37); // [ var(26) , var(10) ] D[10,30] = var(41); // [ var(30) , var(10) ] D[10,33] = (-1)*var(42); // [ var(33) , var(10) ] D[10,39] = (-1)*var(47); // [ var(39) , var(10) ] D[10,43] = var(50); // [ var(43) , var(10) ] D[10,48] = var(54); // [ var(48) , var(10) ] D[10,52] = var(57); // [ var(52) , var(10) ] D[10,60] = var(62); // [ var(60) , var(10) ] D[11,13] = var(25); // [ var(13) , var(11) ] D[11,15] = var(28); // [ var(15) , var(11) ] D[11,20] = var(32); // [ var(20) , var(11) ] D[11,29] = (-1)*var(40); // [ var(29) , var(11) ] D[11,33] = (-1)*var(43); // [ var(33) , var(11) ] D[11,36] = (-1)*var(45); // [ var(36) , var(11) ] D[11,39] = (-1)*var(48); // [ var(39) , var(11) ] D[11,42] = var(50); // [ var(42) , var(11) ] D[11,47] = var(54); // [ var(47) , var(11) ] D[11,55] = (-1)*var(59); // [ var(55) , var(11) ] D[11,58] = var(61); // [ var(58) , var(11) ] D[12,14] = (-1)*var(27); // [ var(14) , var(12) ] D[12,15] = (-1)*var(29); // [ var(15) , var(12) ] D[12,20] = (-1)*var(33); // [ var(20) , var(12) ] D[12,28] = var(40); // [ var(28) , var(12) ] D[12,32] = var(43); // [ var(32) , var(12) ] D[12,37] = var(46); // [ var(37) , var(12) ] D[12,41] = (-1)*var(49); // [ var(41) , var(12) ] D[12,44] = (-1)*var(52); // [ var(44) , var(12) ] D[12,47] = (-1)*var(55); // [ var(47) , var(12) ] D[12,54] = var(59); // [ var(54) , var(12) ] D[12,56] = var(60); // [ var(56) , var(12) ] D[13,16] = (-1)*var(30); // [ var(16) , var(13) ] D[13,17] = (-1)*var(31); // [ var(17) , var(13) ] D[13,21] = (-1)*var(34); // [ var(21) , var(13) ] D[13,22] = (-1)*var(36); // [ var(22) , var(13) ] D[13,26] = (-1)*var(39); // [ var(26) , var(13) ] D[13,28] = (-1)*var(41); // [ var(28) , var(13) ] D[13,32] = (-1)*var(44); // [ var(32) , var(13) ] D[13,37] = (-1)*var(47); // [ var(37) , var(13) ] D[13,40] = var(49); // [ var(40) , var(13) ] D[13,43] = var(52); // [ var(43) , var(13) ] D[13,46] = var(55); // [ var(46) , var(13) ] D[13,50] = var(57); // [ var(50) , var(13) ] D[13,53] = var(58); // [ var(53) , var(13) ] D[14,16] = var(32); // [ var(16) , var(14) ] D[14,19] = var(34); // [ var(19) , var(14) ] D[14,22] = var(37); // [ var(22) , var(14) ] D[14,23] = var(38); // [ var(23) , var(14) ] D[14,29] = var(42); // [ var(29) , var(14) ] D[14,30] = var(44); // [ var(30) , var(14) ] D[14,36] = var(47); // [ var(36) , var(14) ] D[14,40] = (-1)*var(50); // [ var(40) , var(14) ] D[14,45] = (-1)*var(54); // [ var(45) , var(14) ] D[14,49] = (-1)*var(57); // [ var(49) , var(14) ] D[14,60] = (-1)*var(63); // [ var(60) , var(14) ] D[15,18] = (-1)*var(35); // [ var(18) , var(15) ] D[15,19] = var(36); // [ var(19) , var(15) ] D[15,21] = var(37); // [ var(21) , var(15) ] D[15,25] = (-1)*var(41); // [ var(25) , var(15) ] D[15,27] = var(42); // [ var(27) , var(15) ] D[15,34] = var(47); // [ var(34) , var(15) ] D[15,43] = (-1)*var(53); // [ var(43) , var(15) ] D[15,48] = (-1)*var(56); // [ var(48) , var(15) ] D[15,52] = (-1)*var(58); // [ var(52) , var(15) ] D[15,59] = var(62); // [ var(59) , var(15) ] D[16,24] = var(40); // [ var(24) , var(16) ] D[16,27] = var(43); // [ var(27) , var(16) ] D[16,31] = var(45); // [ var(31) , var(16) ] D[16,34] = var(48); // [ var(34) , var(16) ] D[16,42] = (-1)*var(53); // [ var(42) , var(16) ] D[16,47] = (-1)*var(56); // [ var(47) , var(16) ] D[16,55] = var(60); // [ var(55) , var(16) ] D[16,57] = var(61); // [ var(57) , var(16) ] D[17,20] = var(37); // [ var(20) , var(17) ] D[17,23] = var(40); // [ var(23) , var(17) ] D[17,30] = var(45); // [ var(30) , var(17) ] D[17,33] = (-1)*var(46); // [ var(33) , var(17) ] D[17,38] = (-1)*var(50); // [ var(38) , var(17) ] D[17,39] = (-1)*var(51); // [ var(39) , var(17) ] D[17,44] = (-1)*var(54); // [ var(44) , var(17) ] D[17,52] = var(59); // [ var(52) , var(17) ] D[17,58] = (-1)*var(62); // [ var(58) , var(17) ] D[18,20] = var(38); // [ var(20) , var(18) ] D[18,22] = var(40); // [ var(22) , var(18) ] D[18,26] = var(43); // [ var(26) , var(18) ] D[18,36] = (-1)*var(49); // [ var(36) , var(18) ] D[18,37] = (-1)*var(50); // [ var(37) , var(18) ] D[18,39] = (-1)*var(52); // [ var(39) , var(18) ] D[18,47] = var(57); // [ var(47) , var(18) ] D[18,51] = var(59); // [ var(51) , var(18) ] D[18,56] = (-1)*var(61); // [ var(56) , var(18) ] D[19,20] = (-1)*var(39); // [ var(20) , var(19) ] D[19,28] = var(45); // [ var(28) , var(19) ] D[19,32] = var(48); // [ var(32) , var(19) ] D[19,35] = var(49); // [ var(35) , var(19) ] D[19,37] = var(51); // [ var(37) , var(19) ] D[19,38] = var(52); // [ var(38) , var(19) ] D[19,42] = var(55); // [ var(42) , var(19) ] D[19,50] = (-1)*var(59); // [ var(50) , var(19) ] D[19,53] = (-1)*var(60); // [ var(53) , var(19) ] D[20,24] = (-1)*var(42); // [ var(24) , var(20) ] D[20,25] = (-1)*var(44); // [ var(25) , var(20) ] D[20,31] = (-1)*var(47); // [ var(31) , var(20) ] D[20,40] = var(53); // [ var(40) , var(20) ] D[20,45] = var(56); // [ var(45) , var(20) ] D[20,49] = var(58); // [ var(49) , var(20) ] D[20,59] = (-1)*var(63); // [ var(59) , var(20) ] D[21,23] = var(43); // [ var(23) , var(21) ] D[21,29] = var(46); // [ var(29) , var(21) ] D[21,30] = var(48); // [ var(30) , var(21) ] D[21,35] = var(50); // [ var(35) , var(21) ] D[21,36] = var(51); // [ var(36) , var(21) ] D[21,41] = var(54); // [ var(41) , var(21) ] D[21,49] = (-1)*var(59); // [ var(49) , var(21) ] D[21,58] = var(63); // [ var(58) , var(21) ] D[22,25] = (-1)*var(45); // [ var(25) , var(22) ] D[22,27] = var(46); // [ var(27) , var(22) ] D[22,34] = var(51); // [ var(34) , var(22) ] D[22,38] = var(53); // [ var(38) , var(22) ] D[22,44] = var(56); // [ var(44) , var(22) ] D[22,52] = (-1)*var(60); // [ var(52) , var(22) ] D[22,57] = (-1)*var(62); // [ var(57) , var(22) ] D[23,31] = var(49); // [ var(31) , var(23) ] D[23,34] = var(52); // [ var(34) , var(23) ] D[23,37] = var(53); // [ var(37) , var(23) ] D[23,47] = (-1)*var(58); // [ var(47) , var(23) ] D[23,51] = (-1)*var(60); // [ var(51) , var(23) ] D[23,54] = (-1)*var(61); // [ var(54) , var(23) ] D[24,26] = var(46); // [ var(26) , var(24) ] D[24,30] = var(49); // [ var(30) , var(24) ] D[24,32] = var(50); // [ var(32) , var(24) ] D[24,39] = (-1)*var(55); // [ var(39) , var(24) ] D[24,44] = (-1)*var(57); // [ var(44) , var(24) ] D[24,48] = (-1)*var(59); // [ var(48) , var(24) ] D[24,56] = var(62); // [ var(56) , var(24) ] D[25,26] = var(48); // [ var(26) , var(25) ] D[25,29] = var(49); // [ var(29) , var(25) ] D[25,33] = var(52); // [ var(33) , var(25) ] D[25,37] = (-1)*var(54); // [ var(37) , var(25) ] D[25,42] = (-1)*var(57); // [ var(42) , var(25) ] D[25,46] = (-1)*var(59); // [ var(46) , var(25) ] D[25,53] = var(61); // [ var(53) , var(25) ] D[26,31] = (-1)*var(51); // [ var(31) , var(26) ] D[26,35] = (-1)*var(53); // [ var(35) , var(26) ] D[26,41] = (-1)*var(56); // [ var(41) , var(26) ] D[26,49] = var(60); // [ var(49) , var(26) ] D[26,57] = var(63); // [ var(57) , var(26) ] D[27,28] = (-1)*var(50); // [ var(28) , var(27) ] D[27,30] = var(52); // [ var(30) , var(27) ] D[27,36] = var(55); // [ var(36) , var(27) ] D[27,41] = var(57); // [ var(41) , var(27) ] D[27,45] = var(59); // [ var(45) , var(27) ] D[27,56] = (-1)*var(63); // [ var(56) , var(27) ] D[28,33] = (-1)*var(53); // [ var(33) , var(28) ] D[28,34] = var(54); // [ var(34) , var(28) ] D[28,39] = (-1)*var(56); // [ var(39) , var(28) ] D[28,52] = (-1)*var(61); // [ var(52) , var(28) ] D[28,55] = var(62); // [ var(55) , var(28) ] D[29,32] = (-1)*var(53); // [ var(32) , var(29) ] D[29,34] = var(55); // [ var(34) , var(29) ] D[29,44] = var(58); // [ var(44) , var(29) ] D[29,48] = var(60); // [ var(48) , var(29) ] D[29,54] = var(62); // [ var(54) , var(29) ] D[30,37] = var(56); // [ var(37) , var(30) ] D[30,42] = var(58); // [ var(42) , var(30) ] D[30,46] = var(60); // [ var(46) , var(30) ] D[30,50] = var(61); // [ var(50) , var(30) ] D[31,32] = var(54); // [ var(32) , var(31) ] D[31,33] = var(55); // [ var(33) , var(31) ] D[31,38] = var(57); // [ var(38) , var(31) ] D[31,43] = var(59); // [ var(43) , var(31) ] D[31,53] = (-1)*var(62); // [ var(53) , var(31) ] D[32,36] = var(56); // [ var(36) , var(32) ] D[32,49] = var(61); // [ var(49) , var(32) ] D[32,55] = (-1)*var(63); // [ var(55) , var(32) ] D[33,41] = (-1)*var(58); // [ var(41) , var(33) ] D[33,45] = (-1)*var(60); // [ var(45) , var(33) ] D[33,54] = (-1)*var(63); // [ var(54) , var(33) ] D[34,35] = (-1)*var(57); // [ var(35) , var(34) ] D[34,40] = (-1)*var(59); // [ var(40) , var(34) ] D[34,53] = var(63); // [ var(53) , var(34) ] D[35,39] = (-1)*var(58); // [ var(39) , var(35) ] D[35,48] = var(61); // [ var(48) , var(35) ] D[35,51] = (-1)*var(62); // [ var(51) , var(35) ] D[36,38] = (-1)*var(58); // [ var(38) , var(36) ] D[36,43] = (-1)*var(60); // [ var(43) , var(36) ] D[36,50] = (-1)*var(62); // [ var(50) , var(36) ] D[37,49] = (-1)*var(62); // [ var(49) , var(37) ] D[37,52] = var(63); // [ var(52) , var(37) ] D[38,45] = (-1)*var(61); // [ var(45) , var(38) ] D[38,51] = var(63); // [ var(51) , var(38) ] D[39,40] = var(60); // [ var(40) , var(39) ] D[39,50] = var(63); // [ var(50) , var(39) ] D[40,44] = (-1)*var(61); // [ var(44) , var(40) ] D[40,47] = var(62); // [ var(47) , var(40) ] D[41,43] = (-1)*var(61); // [ var(43) , var(41) ] D[41,46] = var(62); // [ var(46) , var(41) ] D[42,45] = var(62); // [ var(45) , var(42) ] D[42,48] = (-1)*var(63); // [ var(48) , var(42) ] D[43,47] = (-1)*var(63); // [ var(47) , var(43) ] D[44,46] = (-1)*var(63); // [ var(46) , var(44) ] // Y(i) * Y(j): D[64,66] = (-1)*var(71); // [ var(66) , var(64) ] D[64,73] = (-1)*var(77); // [ var(73) , var(64) ] D[64,78] = (-1)*var(83); // [ var(78) , var(64) ] D[64,80] = (-1)*var(84); // [ var(80) , var(64) ] D[64,85] = (-1)*var(89); // [ var(85) , var(64) ] D[64,87] = (-1)*var(90); // [ var(87) , var(64) ] D[64,91] = (-1)*var(95); // [ var(91) , var(64) ] D[64,92] = (-1)*var(96); // [ var(92) , var(64) ] D[64,94] = (-1)*var(97); // [ var(94) , var(64) ] D[64,98] = (-1)*var(101); // [ var(98) , var(64) ] D[64,99] = (-1)*var(102); // [ var(99) , var(64) ] D[64,103] = (-1)*var(106); // [ var(103) , var(64) ] D[64,104] = (-1)*var(107); // [ var(104) , var(64) ] D[64,108] = (-1)*var(111); // [ var(108) , var(64) ] D[64,112] = (-1)*var(115); // [ var(112) , var(64) ] D[64,125] = var(126); // [ var(125) , var(64) ] D[65,67] = (-1)*var(72); // [ var(67) , var(65) ] D[65,73] = (-1)*var(78); // [ var(73) , var(65) ] D[65,74] = (-1)*var(79); // [ var(74) , var(65) ] D[65,77] = (-1)*var(83); // [ var(77) , var(65) ] D[65,80] = (-1)*var(85); // [ var(80) , var(65) ] D[65,81] = (-1)*var(86); // [ var(81) , var(65) ] D[65,84] = (-1)*var(89); // [ var(84) , var(65) ] D[65,87] = (-1)*var(92); // [ var(87) , var(65) ] D[65,88] = (-1)*var(93); // [ var(88) , var(65) ] D[65,90] = (-1)*var(96); // [ var(90) , var(65) ] D[65,94] = (-1)*var(99); // [ var(94) , var(65) ] D[65,97] = (-1)*var(102); // [ var(97) , var(65) ] D[65,113] = var(116); // [ var(113) , var(65) ] D[65,117] = var(119); // [ var(117) , var(65) ] D[65,120] = var(121); // [ var(120) , var(65) ] D[65,122] = var(123); // [ var(122) , var(65) ] D[66,67] = (-1)*var(73); // [ var(67) , var(66) ] D[66,72] = (-1)*var(78); // [ var(72) , var(66) ] D[66,74] = (-1)*var(80); // [ var(74) , var(66) ] D[66,79] = (-1)*var(85); // [ var(79) , var(66) ] D[66,81] = (-1)*var(87); // [ var(81) , var(66) ] D[66,86] = (-1)*var(92); // [ var(86) , var(66) ] D[66,88] = (-1)*var(94); // [ var(88) , var(66) ] D[66,93] = (-1)*var(99); // [ var(93) , var(66) ] D[66,95] = (-1)*var(100); // [ var(95) , var(66) ] D[66,101] = (-1)*var(105); // [ var(101) , var(66) ] D[66,106] = (-1)*var(109); // [ var(106) , var(66) ] D[66,107] = (-1)*var(110); // [ var(107) , var(66) ] D[66,111] = (-1)*var(114); // [ var(111) , var(66) ] D[66,115] = (-1)*var(118); // [ var(115) , var(66) ] D[66,124] = var(125); // [ var(124) , var(66) ] D[67,68] = (-1)*var(74); // [ var(68) , var(67) ] D[67,71] = var(77); // [ var(71) , var(67) ] D[67,75] = (-1)*var(81); // [ var(75) , var(67) ] D[67,82] = (-1)*var(88); // [ var(82) , var(67) ] D[67,85] = var(91); // [ var(85) , var(67) ] D[67,89] = var(95); // [ var(89) , var(67) ] D[67,92] = var(98); // [ var(92) , var(67) ] D[67,96] = var(101); // [ var(96) , var(67) ] D[67,99] = var(104); // [ var(99) , var(67) ] D[67,102] = var(107); // [ var(102) , var(67) ] D[67,109] = var(113); // [ var(109) , var(67) ] D[67,114] = var(117); // [ var(114) , var(67) ] D[67,118] = var(120); // [ var(118) , var(67) ] D[67,123] = var(124); // [ var(123) , var(67) ] D[68,69] = (-1)*var(75); // [ var(69) , var(68) ] D[68,72] = var(79); // [ var(72) , var(68) ] D[68,73] = var(80); // [ var(73) , var(68) ] D[68,76] = (-1)*var(82); // [ var(76) , var(68) ] D[68,77] = var(84); // [ var(77) , var(68) ] D[68,78] = var(85); // [ var(78) , var(68) ] D[68,83] = var(89); // [ var(83) , var(68) ] D[68,98] = var(103); // [ var(98) , var(68) ] D[68,101] = var(106); // [ var(101) , var(68) ] D[68,104] = var(108); // [ var(104) , var(68) ] D[68,105] = var(109); // [ var(105) , var(68) ] D[68,107] = var(111); // [ var(107) , var(68) ] D[68,110] = var(114); // [ var(110) , var(68) ] D[68,120] = var(122); // [ var(120) , var(68) ] D[68,121] = var(123); // [ var(121) , var(68) ] D[69,70] = (-1)*var(76); // [ var(70) , var(69) ] D[69,74] = var(81); // [ var(74) , var(69) ] D[69,79] = var(86); // [ var(79) , var(69) ] D[69,80] = var(87); // [ var(80) , var(69) ] D[69,84] = var(90); // [ var(84) , var(69) ] D[69,85] = var(92); // [ var(85) , var(69) ] D[69,89] = var(96); // [ var(89) , var(69) ] D[69,91] = var(98); // [ var(91) , var(69) ] D[69,95] = var(101); // [ var(95) , var(69) ] D[69,100] = var(105); // [ var(100) , var(69) ] D[69,108] = var(112); // [ var(108) , var(69) ] D[69,111] = var(115); // [ var(111) , var(69) ] D[69,114] = var(118); // [ var(114) , var(69) ] D[69,117] = var(120); // [ var(117) , var(69) ] D[69,119] = var(121); // [ var(119) , var(69) ] D[70,75] = var(82); // [ var(75) , var(70) ] D[70,81] = var(88); // [ var(81) , var(70) ] D[70,86] = var(93); // [ var(86) , var(70) ] D[70,87] = var(94); // [ var(87) , var(70) ] D[70,90] = var(97); // [ var(90) , var(70) ] D[70,92] = var(99); // [ var(92) , var(70) ] D[70,96] = var(102); // [ var(96) , var(70) ] D[70,98] = var(104); // [ var(98) , var(70) ] D[70,101] = var(107); // [ var(101) , var(70) ] D[70,103] = var(108); // [ var(103) , var(70) ] D[70,105] = var(110); // [ var(105) , var(70) ] D[70,106] = var(111); // [ var(106) , var(70) ] D[70,109] = var(114); // [ var(109) , var(70) ] D[70,113] = var(117); // [ var(113) , var(70) ] D[70,116] = var(119); // [ var(116) , var(70) ] D[71,72] = (-1)*var(83); // [ var(72) , var(71) ] D[71,74] = (-1)*var(84); // [ var(74) , var(71) ] D[71,79] = (-1)*var(89); // [ var(79) , var(71) ] D[71,81] = (-1)*var(90); // [ var(81) , var(71) ] D[71,86] = (-1)*var(96); // [ var(86) , var(71) ] D[71,88] = (-1)*var(97); // [ var(88) , var(71) ] D[71,91] = var(100); // [ var(91) , var(71) ] D[71,93] = (-1)*var(102); // [ var(93) , var(71) ] D[71,98] = var(105); // [ var(98) , var(71) ] D[71,103] = var(109); // [ var(103) , var(71) ] D[71,104] = var(110); // [ var(104) , var(71) ] D[71,108] = var(114); // [ var(108) , var(71) ] D[71,112] = var(118); // [ var(112) , var(71) ] D[71,124] = (-1)*var(126); // [ var(124) , var(71) ] D[72,75] = (-1)*var(86); // [ var(75) , var(72) ] D[72,80] = (-1)*var(91); // [ var(80) , var(72) ] D[72,82] = (-1)*var(93); // [ var(82) , var(72) ] D[72,84] = (-1)*var(95); // [ var(84) , var(72) ] D[72,87] = (-1)*var(98); // [ var(87) , var(72) ] D[72,90] = (-1)*var(101); // [ var(90) , var(72) ] D[72,94] = (-1)*var(104); // [ var(94) , var(72) ] D[72,97] = (-1)*var(107); // [ var(97) , var(72) ] D[72,109] = (-1)*var(116); // [ var(109) , var(72) ] D[72,114] = (-1)*var(119); // [ var(114) , var(72) ] D[72,118] = (-1)*var(121); // [ var(118) , var(72) ] D[72,122] = var(124); // [ var(122) , var(72) ] D[73,75] = (-1)*var(87); // [ var(75) , var(73) ] D[73,79] = (-1)*var(91); // [ var(79) , var(73) ] D[73,82] = (-1)*var(94); // [ var(82) , var(73) ] D[73,86] = (-1)*var(98); // [ var(86) , var(73) ] D[73,89] = var(100); // [ var(89) , var(73) ] D[73,93] = (-1)*var(104); // [ var(93) , var(73) ] D[73,96] = var(105); // [ var(96) , var(73) ] D[73,102] = var(110); // [ var(102) , var(73) ] D[73,106] = (-1)*var(113); // [ var(106) , var(73) ] D[73,111] = (-1)*var(117); // [ var(111) , var(73) ] D[73,115] = (-1)*var(120); // [ var(115) , var(73) ] D[73,123] = (-1)*var(125); // [ var(123) , var(73) ] D[74,76] = (-1)*var(88); // [ var(76) , var(74) ] D[74,78] = (-1)*var(91); // [ var(78) , var(74) ] D[74,83] = (-1)*var(95); // [ var(83) , var(74) ] D[74,92] = var(103); // [ var(92) , var(74) ] D[74,96] = var(106); // [ var(96) , var(74) ] D[74,99] = var(108); // [ var(99) , var(74) ] D[74,102] = var(111); // [ var(102) , var(74) ] D[74,105] = (-1)*var(113); // [ var(105) , var(74) ] D[74,110] = (-1)*var(117); // [ var(110) , var(74) ] D[74,118] = var(122); // [ var(118) , var(74) ] D[74,121] = (-1)*var(124); // [ var(121) , var(74) ] D[75,77] = var(90); // [ var(77) , var(75) ] D[75,78] = var(92); // [ var(78) , var(75) ] D[75,83] = var(96); // [ var(83) , var(75) ] D[75,91] = (-1)*var(103); // [ var(91) , var(75) ] D[75,95] = (-1)*var(106); // [ var(95) , var(75) ] D[75,100] = (-1)*var(109); // [ var(100) , var(75) ] D[75,104] = var(112); // [ var(104) , var(75) ] D[75,107] = var(115); // [ var(107) , var(75) ] D[75,110] = var(118); // [ var(110) , var(75) ] D[75,117] = (-1)*var(122); // [ var(117) , var(75) ] D[75,119] = (-1)*var(123); // [ var(119) , var(75) ] D[76,79] = var(93); // [ var(79) , var(76) ] D[76,80] = var(94); // [ var(80) , var(76) ] D[76,84] = var(97); // [ var(84) , var(76) ] D[76,85] = var(99); // [ var(85) , var(76) ] D[76,89] = var(102); // [ var(89) , var(76) ] D[76,91] = var(104); // [ var(91) , var(76) ] D[76,95] = var(107); // [ var(95) , var(76) ] D[76,100] = var(110); // [ var(100) , var(76) ] D[76,103] = (-1)*var(112); // [ var(103) , var(76) ] D[76,106] = (-1)*var(115); // [ var(106) , var(76) ] D[76,109] = (-1)*var(118); // [ var(109) , var(76) ] D[76,113] = (-1)*var(120); // [ var(113) , var(76) ] D[76,116] = (-1)*var(121); // [ var(116) , var(76) ] D[77,79] = (-1)*var(95); // [ var(79) , var(77) ] D[77,82] = (-1)*var(97); // [ var(82) , var(77) ] D[77,85] = (-1)*var(100); // [ var(85) , var(77) ] D[77,86] = (-1)*var(101); // [ var(86) , var(77) ] D[77,92] = (-1)*var(105); // [ var(92) , var(77) ] D[77,93] = (-1)*var(107); // [ var(93) , var(77) ] D[77,99] = (-1)*var(110); // [ var(99) , var(77) ] D[77,103] = var(113); // [ var(103) , var(77) ] D[77,108] = var(117); // [ var(108) , var(77) ] D[77,112] = var(120); // [ var(112) , var(77) ] D[77,123] = var(126); // [ var(123) , var(77) ] D[78,81] = var(98); // [ var(81) , var(78) ] D[78,82] = (-1)*var(99); // [ var(82) , var(78) ] D[78,84] = (-1)*var(100); // [ var(84) , var(78) ] D[78,88] = var(104); // [ var(88) , var(78) ] D[78,90] = (-1)*var(105); // [ var(90) , var(78) ] D[78,97] = (-1)*var(110); // [ var(97) , var(78) ] D[78,106] = var(116); // [ var(106) , var(78) ] D[78,111] = var(119); // [ var(111) , var(78) ] D[78,115] = var(121); // [ var(115) , var(78) ] D[78,122] = (-1)*var(125); // [ var(122) , var(78) ] D[79,87] = (-1)*var(103); // [ var(87) , var(79) ] D[79,90] = (-1)*var(106); // [ var(90) , var(79) ] D[79,94] = (-1)*var(108); // [ var(94) , var(79) ] D[79,97] = (-1)*var(111); // [ var(97) , var(79) ] D[79,105] = var(116); // [ var(105) , var(79) ] D[79,110] = var(119); // [ var(110) , var(79) ] D[79,118] = (-1)*var(123); // [ var(118) , var(79) ] D[79,120] = (-1)*var(124); // [ var(120) , var(79) ] D[80,83] = (-1)*var(100); // [ var(83) , var(80) ] D[80,86] = (-1)*var(103); // [ var(86) , var(80) ] D[80,93] = (-1)*var(108); // [ var(93) , var(80) ] D[80,96] = var(109); // [ var(96) , var(80) ] D[80,101] = var(113); // [ var(101) , var(80) ] D[80,102] = var(114); // [ var(102) , var(80) ] D[80,107] = var(117); // [ var(107) , var(80) ] D[80,115] = (-1)*var(122); // [ var(115) , var(80) ] D[80,121] = var(125); // [ var(121) , var(80) ] D[81,83] = (-1)*var(101); // [ var(83) , var(81) ] D[81,85] = (-1)*var(103); // [ var(85) , var(81) ] D[81,89] = (-1)*var(106); // [ var(89) , var(81) ] D[81,99] = var(112); // [ var(99) , var(81) ] D[81,100] = var(113); // [ var(100) , var(81) ] D[81,102] = var(115); // [ var(102) , var(81) ] D[81,110] = (-1)*var(120); // [ var(110) , var(81) ] D[81,114] = (-1)*var(122); // [ var(114) , var(81) ] D[81,119] = var(124); // [ var(119) , var(81) ] D[82,83] = var(102); // [ var(83) , var(82) ] D[82,91] = (-1)*var(108); // [ var(91) , var(82) ] D[82,95] = (-1)*var(111); // [ var(95) , var(82) ] D[82,98] = (-1)*var(112); // [ var(98) , var(82) ] D[82,100] = (-1)*var(114); // [ var(100) , var(82) ] D[82,101] = (-1)*var(115); // [ var(101) , var(82) ] D[82,105] = (-1)*var(118); // [ var(105) , var(82) ] D[82,113] = var(122); // [ var(113) , var(82) ] D[82,116] = var(123); // [ var(116) , var(82) ] D[83,87] = var(105); // [ var(87) , var(83) ] D[83,88] = var(107); // [ var(88) , var(83) ] D[83,94] = var(110); // [ var(94) , var(83) ] D[83,103] = (-1)*var(116); // [ var(103) , var(83) ] D[83,108] = (-1)*var(119); // [ var(108) , var(83) ] D[83,112] = (-1)*var(121); // [ var(112) , var(83) ] D[83,122] = var(126); // [ var(122) , var(83) ] D[84,86] = (-1)*var(106); // [ var(86) , var(84) ] D[84,92] = (-1)*var(109); // [ var(92) , var(84) ] D[84,93] = (-1)*var(111); // [ var(93) , var(84) ] D[84,98] = (-1)*var(113); // [ var(98) , var(84) ] D[84,99] = (-1)*var(114); // [ var(99) , var(84) ] D[84,104] = (-1)*var(117); // [ var(104) , var(84) ] D[84,112] = var(122); // [ var(112) , var(84) ] D[84,121] = (-1)*var(126); // [ var(121) , var(84) ] D[85,88] = var(108); // [ var(88) , var(85) ] D[85,90] = (-1)*var(109); // [ var(90) , var(85) ] D[85,97] = (-1)*var(114); // [ var(97) , var(85) ] D[85,101] = (-1)*var(116); // [ var(101) , var(85) ] D[85,107] = (-1)*var(119); // [ var(107) , var(85) ] D[85,115] = var(123); // [ var(115) , var(85) ] D[85,120] = var(125); // [ var(120) , var(85) ] D[86,94] = (-1)*var(112); // [ var(94) , var(86) ] D[86,97] = (-1)*var(115); // [ var(97) , var(86) ] D[86,100] = (-1)*var(116); // [ var(100) , var(86) ] D[86,110] = var(121); // [ var(110) , var(86) ] D[86,114] = var(123); // [ var(114) , var(86) ] D[86,117] = var(124); // [ var(117) , var(86) ] D[87,89] = (-1)*var(109); // [ var(89) , var(87) ] D[87,93] = (-1)*var(112); // [ var(93) , var(87) ] D[87,95] = (-1)*var(113); // [ var(95) , var(87) ] D[87,102] = var(118); // [ var(102) , var(87) ] D[87,107] = var(120); // [ var(107) , var(87) ] D[87,111] = var(122); // [ var(111) , var(87) ] D[87,119] = (-1)*var(125); // [ var(119) , var(87) ] D[88,89] = (-1)*var(111); // [ var(89) , var(88) ] D[88,92] = (-1)*var(112); // [ var(92) , var(88) ] D[88,96] = (-1)*var(115); // [ var(96) , var(88) ] D[88,100] = var(117); // [ var(100) , var(88) ] D[88,105] = var(120); // [ var(105) , var(88) ] D[88,109] = var(122); // [ var(109) , var(88) ] D[88,116] = (-1)*var(124); // [ var(116) , var(88) ] D[89,94] = var(114); // [ var(94) , var(89) ] D[89,98] = var(116); // [ var(98) , var(89) ] D[89,104] = var(119); // [ var(104) , var(89) ] D[89,112] = (-1)*var(123); // [ var(112) , var(89) ] D[89,120] = (-1)*var(126); // [ var(120) , var(89) ] D[90,91] = var(113); // [ var(91) , var(90) ] D[90,93] = (-1)*var(115); // [ var(93) , var(90) ] D[90,99] = (-1)*var(118); // [ var(99) , var(90) ] D[90,104] = (-1)*var(120); // [ var(104) , var(90) ] D[90,108] = (-1)*var(122); // [ var(108) , var(90) ] D[90,119] = var(126); // [ var(119) , var(90) ] D[91,96] = var(116); // [ var(96) , var(91) ] D[91,97] = (-1)*var(117); // [ var(97) , var(91) ] D[91,102] = var(119); // [ var(102) , var(91) ] D[91,115] = var(124); // [ var(115) , var(91) ] D[91,118] = (-1)*var(125); // [ var(118) , var(91) ] D[92,95] = var(116); // [ var(95) , var(92) ] D[92,97] = (-1)*var(118); // [ var(97) , var(92) ] D[92,107] = (-1)*var(121); // [ var(107) , var(92) ] D[92,111] = (-1)*var(123); // [ var(111) , var(92) ] D[92,117] = (-1)*var(125); // [ var(117) , var(92) ] D[93,100] = (-1)*var(119); // [ var(100) , var(93) ] D[93,105] = (-1)*var(121); // [ var(105) , var(93) ] D[93,109] = (-1)*var(123); // [ var(109) , var(93) ] D[93,113] = (-1)*var(124); // [ var(113) , var(93) ] D[94,95] = (-1)*var(117); // [ var(95) , var(94) ] D[94,96] = (-1)*var(118); // [ var(96) , var(94) ] D[94,101] = (-1)*var(120); // [ var(101) , var(94) ] D[94,106] = (-1)*var(122); // [ var(106) , var(94) ] D[94,116] = var(125); // [ var(116) , var(94) ] D[95,99] = (-1)*var(119); // [ var(99) , var(95) ] D[95,112] = (-1)*var(124); // [ var(112) , var(95) ] D[95,118] = var(126); // [ var(118) , var(95) ] D[96,104] = var(121); // [ var(104) , var(96) ] D[96,108] = var(123); // [ var(108) , var(96) ] D[96,117] = var(126); // [ var(117) , var(96) ] D[97,98] = var(120); // [ var(98) , var(97) ] D[97,103] = var(122); // [ var(103) , var(97) ] D[97,116] = (-1)*var(126); // [ var(116) , var(97) ] D[98,102] = var(121); // [ var(102) , var(98) ] D[98,111] = (-1)*var(124); // [ var(111) , var(98) ] D[98,114] = var(125); // [ var(114) , var(98) ] D[99,101] = var(121); // [ var(101) , var(99) ] D[99,106] = var(123); // [ var(106) , var(99) ] D[99,113] = var(125); // [ var(113) , var(99) ] D[100,112] = var(125); // [ var(112) , var(100) ] D[100,115] = (-1)*var(126); // [ var(115) , var(100) ] D[101,108] = var(124); // [ var(108) , var(101) ] D[101,114] = (-1)*var(126); // [ var(114) , var(101) ] D[102,103] = (-1)*var(123); // [ var(103) , var(102) ] D[102,113] = (-1)*var(126); // [ var(113) , var(102) ] D[103,107] = var(124); // [ var(107) , var(103) ] D[103,110] = (-1)*var(125); // [ var(110) , var(103) ] D[104,106] = var(124); // [ var(106) , var(104) ] D[104,109] = (-1)*var(125); // [ var(109) , var(104) ] D[105,108] = (-1)*var(125); // [ var(108) , var(105) ] D[105,111] = var(126); // [ var(111) , var(105) ] D[106,110] = var(126); // [ var(110) , var(106) ] D[107,109] = var(126); // [ var(109) , var(107) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUe7(); ncAlgebra; setring ncAlgebra; // ... 2541 noncommutative relations } //////////////////////////////////////////////////////////////////// // Algebra: e8(Q) has the type: E8, and defined by: proc makeUe8(list #) "USAGE: makeUe8([p]); p an optional integer (field characteristic) RETURN: a ring, describing U(e_8) NOTE: You have to activate this ring with the 'setring' command. The presentation of U(e_8) is derived from the Chevalley representation of e_8, positive resp. negative roots are denoted by x(i) resp. y(i); Cartan elements are denoted by h(i). SEE ALSO: makeUsl, makeUso5, makeUsp1, makeUe6, makeUe7, makeUe8, makeUg2, makeUf4 EXAMPLE: example makeUe8; shows examples " { int @p = defInt(#); ring @@@rrr = @p,(X(1..120),Y(1..120),H(1..8)),dp; int N = nvars(@@@rrr); matrix D[N][N]=0; // H(i) * X(j): D[1,241] = (2)*var(1); // [ var(241) , var(1) ] D[3,241] = (-1)*var(3); // [ var(241) , var(3) ] D[9,241] = var(9); // [ var(241) , var(9) ] D[11,241] = (-1)*var(11); // [ var(241) , var(11) ] D[16,241] = var(16); // [ var(241) , var(16) ] D[17,241] = (-1)*var(17); // [ var(241) , var(17) ] D[19,241] = (-1)*var(19); // [ var(241) , var(19) ] D[23,241] = var(23); // [ var(241) , var(23) ] D[24,241] = var(24); // [ var(241) , var(24) ] D[25,241] = (-1)*var(25); // [ var(241) , var(25) ] D[27,241] = (-1)*var(27); // [ var(241) , var(27) ] D[30,241] = var(30); // [ var(241) , var(30) ] D[31,241] = var(31); // [ var(241) , var(31) ] D[32,241] = (-1)*var(32); // [ var(241) , var(32) ] D[33,241] = (-1)*var(33); // [ var(241) , var(33) ] D[35,241] = (-1)*var(35); // [ var(241) , var(35) ] D[37,241] = var(37); // [ var(241) , var(37) ] D[38,241] = var(38); // [ var(241) , var(38) ] D[39,241] = var(39); // [ var(241) , var(39) ] D[40,241] = (-1)*var(40); // [ var(241) , var(40) ] D[41,241] = (-1)*var(41); // [ var(241) , var(41) ] D[43,241] = (-1)*var(43); // [ var(241) , var(43) ] D[45,241] = var(45); // [ var(241) , var(45) ] D[46,241] = var(46); // [ var(241) , var(46) ] D[47,241] = var(47); // [ var(241) , var(47) ] D[48,241] = (-1)*var(48); // [ var(241) , var(48) ] D[49,241] = (-1)*var(49); // [ var(241) , var(49) ] D[50,241] = (-1)*var(50); // [ var(241) , var(50) ] D[52,241] = var(52); // [ var(241) , var(52) ] D[53,241] = var(53); // [ var(241) , var(53) ] D[54,241] = var(54); // [ var(241) , var(54) ] D[55,241] = (-1)*var(55); // [ var(241) , var(55) ] D[56,241] = (-1)*var(56); // [ var(241) , var(56) ] D[59,241] = var(59); // [ var(241) , var(59) ] D[60,241] = var(60); // [ var(241) , var(60) ] D[61,241] = (-1)*var(61); // [ var(241) , var(61) ] D[62,241] = (-1)*var(62); // [ var(241) , var(62) ] D[66,241] = var(66); // [ var(241) , var(66) ] D[67,241] = var(67); // [ var(241) , var(67) ] D[68,241] = (-1)*var(68); // [ var(241) , var(68) ] D[73,241] = var(73); // [ var(241) , var(73) ] D[74,241] = (-1)*var(74); // [ var(241) , var(74) ] D[79,241] = var(79); // [ var(241) , var(79) ] D[93,241] = (-1)*var(93); // [ var(241) , var(93) ] D[97,241] = var(97); // [ var(241) , var(97) ] D[98,241] = (-1)*var(98); // [ var(241) , var(98) ] D[101,241] = var(101); // [ var(241) , var(101) ] D[102,241] = (-1)*var(102); // [ var(241) , var(102) ] D[104,241] = var(104); // [ var(241) , var(104) ] D[105,241] = (-1)*var(105); // [ var(241) , var(105) ] D[107,241] = var(107); // [ var(241) , var(107) ] D[108,241] = (-1)*var(108); // [ var(241) , var(108) ] D[109,241] = var(109); // [ var(241) , var(109) ] D[110,241] = (-1)*var(110); // [ var(241) , var(110) ] D[111,241] = var(111); // [ var(241) , var(111) ] D[112,241] = (-1)*var(112); // [ var(241) , var(112) ] D[113,241] = var(113); // [ var(241) , var(113) ] D[2,242] = (2)*var(2); // [ var(242) , var(2) ] D[4,242] = (-1)*var(4); // [ var(242) , var(4) ] D[10,242] = var(10); // [ var(242) , var(10) ] D[11,242] = (-1)*var(11); // [ var(242) , var(11) ] D[12,242] = (-1)*var(12); // [ var(242) , var(12) ] D[16,242] = (-1)*var(16); // [ var(242) , var(16) ] D[17,242] = var(17); // [ var(242) , var(17) ] D[18,242] = var(18); // [ var(242) , var(18) ] D[19,242] = (-1)*var(19); // [ var(242) , var(19) ] D[20,242] = (-1)*var(20); // [ var(242) , var(20) ] D[23,242] = var(23); // [ var(242) , var(23) ] D[24,242] = (-1)*var(24); // [ var(242) , var(24) ] D[25,242] = var(25); // [ var(242) , var(25) ] D[26,242] = var(26); // [ var(242) , var(26) ] D[27,242] = (-1)*var(27); // [ var(242) , var(27) ] D[28,242] = (-1)*var(28); // [ var(242) , var(28) ] D[30,242] = var(30); // [ var(242) , var(30) ] D[31,242] = (-1)*var(31); // [ var(242) , var(31) ] D[33,242] = var(33); // [ var(242) , var(33) ] D[34,242] = var(34); // [ var(242) , var(34) ] D[35,242] = (-1)*var(35); // [ var(242) , var(35) ] D[36,242] = (-1)*var(36); // [ var(242) , var(36) ] D[38,242] = var(38); // [ var(242) , var(38) ] D[39,242] = (-1)*var(39); // [ var(242) , var(39) ] D[41,242] = var(41); // [ var(242) , var(41) ] D[42,242] = var(42); // [ var(242) , var(42) ] D[43,242] = (-1)*var(43); // [ var(242) , var(43) ] D[46,242] = var(46); // [ var(242) , var(46) ] D[47,242] = (-1)*var(47); // [ var(242) , var(47) ] D[50,242] = var(50); // [ var(242) , var(50) ] D[54,242] = var(54); // [ var(242) , var(54) ] D[63,242] = (-1)*var(63); // [ var(242) , var(63) ] D[69,242] = var(69); // [ var(242) , var(69) ] D[70,242] = (-1)*var(70); // [ var(242) , var(70) ] D[75,242] = var(75); // [ var(242) , var(75) ] D[76,242] = (-1)*var(76); // [ var(242) , var(76) ] D[77,242] = (-1)*var(77); // [ var(242) , var(77) ] D[80,242] = var(80); // [ var(242) , var(80) ] D[81,242] = var(81); // [ var(242) , var(81) ] D[82,242] = (-1)*var(82); // [ var(242) , var(82) ] D[83,242] = (-1)*var(83); // [ var(242) , var(83) ] D[85,242] = var(85); // [ var(242) , var(85) ] D[86,242] = var(86); // [ var(242) , var(86) ] D[87,242] = (-1)*var(87); // [ var(242) , var(87) ] D[88,242] = (-1)*var(88); // [ var(242) , var(88) ] D[90,242] = var(90); // [ var(242) , var(90) ] D[91,242] = var(91); // [ var(242) , var(91) ] D[92,242] = (-1)*var(92); // [ var(242) , var(92) ] D[95,242] = var(95); // [ var(242) , var(95) ] D[96,242] = (-1)*var(96); // [ var(242) , var(96) ] D[100,242] = var(100); // [ var(242) , var(100) ] D[110,242] = (-1)*var(110); // [ var(242) , var(110) ] D[111,242] = (-1)*var(111); // [ var(242) , var(111) ] D[112,242] = var(112); // [ var(242) , var(112) ] D[113,242] = var(113); // [ var(242) , var(113) ] D[114,242] = (-1)*var(114); // [ var(242) , var(114) ] D[115,242] = var(115); // [ var(242) , var(115) ] D[1,243] = (-1)*var(1); // [ var(243) , var(1) ] D[3,243] = (2)*var(3); // [ var(243) , var(3) ] D[4,243] = (-1)*var(4); // [ var(243) , var(4) ] D[9,243] = var(9); // [ var(243) , var(9) ] D[10,243] = (-1)*var(10); // [ var(243) , var(10) ] D[11,243] = var(11); // [ var(243) , var(11) ] D[12,243] = (-1)*var(12); // [ var(243) , var(12) ] D[17,243] = var(17); // [ var(243) , var(17) ] D[18,243] = (-1)*var(18); // [ var(243) , var(18) ] D[19,243] = var(19); // [ var(243) , var(19) ] D[20,243] = (-1)*var(20); // [ var(243) , var(20) ] D[25,243] = var(25); // [ var(243) , var(25) ] D[26,243] = (-1)*var(26); // [ var(243) , var(26) ] D[27,243] = var(27); // [ var(243) , var(27) ] D[28,243] = (-1)*var(28); // [ var(243) , var(28) ] D[33,243] = var(33); // [ var(243) , var(33) ] D[34,243] = (-1)*var(34); // [ var(243) , var(34) ] D[35,243] = var(35); // [ var(243) , var(35) ] D[36,243] = (-1)*var(36); // [ var(243) , var(36) ] D[37,243] = (-1)*var(37); // [ var(243) , var(37) ] D[41,243] = var(41); // [ var(243) , var(41) ] D[42,243] = (-1)*var(42); // [ var(243) , var(42) ] D[43,243] = var(43); // [ var(243) , var(43) ] D[44,243] = var(44); // [ var(243) , var(44) ] D[45,243] = (-1)*var(45); // [ var(243) , var(45) ] D[50,243] = var(50); // [ var(243) , var(50) ] D[51,243] = var(51); // [ var(243) , var(51) ] D[52,243] = (-1)*var(52); // [ var(243) , var(52) ] D[53,243] = (-1)*var(53); // [ var(243) , var(53) ] D[57,243] = var(57); // [ var(243) , var(57) ] D[58,243] = var(58); // [ var(243) , var(58) ] D[59,243] = (-1)*var(59); // [ var(243) , var(59) ] D[60,243] = (-1)*var(60); // [ var(243) , var(60) ] D[64,243] = var(64); // [ var(243) , var(64) ] D[65,243] = var(65); // [ var(243) , var(65) ] D[66,243] = (-1)*var(66); // [ var(243) , var(66) ] D[67,243] = (-1)*var(67); // [ var(243) , var(67) ] D[71,243] = var(71); // [ var(243) , var(71) ] D[72,243] = var(72); // [ var(243) , var(72) ] D[73,243] = (-1)*var(73); // [ var(243) , var(73) ] D[78,243] = var(78); // [ var(243) , var(78) ] D[79,243] = (-1)*var(79); // [ var(243) , var(79) ] D[84,243] = var(84); // [ var(243) , var(84) ] D[89,243] = (-1)*var(89); // [ var(243) , var(89) ] D[93,243] = var(93); // [ var(243) , var(93) ] D[94,243] = (-1)*var(94); // [ var(243) , var(94) ] D[98,243] = var(98); // [ var(243) , var(98) ] D[99,243] = (-1)*var(99); // [ var(243) , var(99) ] D[102,243] = var(102); // [ var(243) , var(102) ] D[103,243] = (-1)*var(103); // [ var(243) , var(103) ] D[105,243] = var(105); // [ var(243) , var(105) ] D[106,243] = (-1)*var(106); // [ var(243) , var(106) ] D[108,243] = var(108); // [ var(243) , var(108) ] D[111,243] = (-1)*var(111); // [ var(243) , var(111) ] D[113,243] = (-1)*var(113); // [ var(243) , var(113) ] D[114,243] = var(114); // [ var(243) , var(114) ] D[115,243] = var(115); // [ var(243) , var(115) ] D[2,244] = (-1)*var(2); // [ var(244) , var(2) ] D[3,244] = (-1)*var(3); // [ var(244) , var(3) ] D[4,244] = (2)*var(4); // [ var(244) , var(4) ] D[5,244] = (-1)*var(5); // [ var(244) , var(5) ] D[9,244] = (-1)*var(9); // [ var(244) , var(9) ] D[10,244] = var(10); // [ var(244) , var(10) ] D[11,244] = var(11); // [ var(244) , var(11) ] D[12,244] = var(12); // [ var(244) , var(12) ] D[13,244] = (-1)*var(13); // [ var(244) , var(13) ] D[16,244] = var(16); // [ var(244) , var(16) ] D[20,244] = var(20); // [ var(244) , var(20) ] D[21,244] = (-1)*var(21); // [ var(244) , var(21) ] D[25,244] = (-1)*var(25); // [ var(244) , var(25) ] D[28,244] = var(28); // [ var(244) , var(28) ] D[29,244] = (-1)*var(29); // [ var(244) , var(29) ] D[30,244] = (-1)*var(30); // [ var(244) , var(30) ] D[32,244] = var(32); // [ var(244) , var(32) ] D[33,244] = (-1)*var(33); // [ var(244) , var(33) ] D[36,244] = var(36); // [ var(244) , var(36) ] D[37,244] = var(37); // [ var(244) , var(37) ] D[38,244] = (-1)*var(38); // [ var(244) , var(38) ] D[40,244] = var(40); // [ var(244) , var(40) ] D[41,244] = (-1)*var(41); // [ var(244) , var(41) ] D[45,244] = var(45); // [ var(244) , var(45) ] D[46,244] = (-1)*var(46); // [ var(244) , var(46) ] D[49,244] = var(49); // [ var(244) , var(49) ] D[50,244] = (-1)*var(50); // [ var(244) , var(50) ] D[53,244] = var(53); // [ var(244) , var(53) ] D[54,244] = (-1)*var(54); // [ var(244) , var(54) ] D[56,244] = var(56); // [ var(244) , var(56) ] D[57,244] = (-1)*var(57); // [ var(244) , var(57) ] D[60,244] = var(60); // [ var(244) , var(60) ] D[63,244] = var(63); // [ var(244) , var(63) ] D[64,244] = (-1)*var(64); // [ var(244) , var(64) ] D[70,244] = var(70); // [ var(244) , var(70) ] D[71,244] = (-1)*var(71); // [ var(244) , var(71) ] D[72,244] = (-1)*var(72); // [ var(244) , var(72) ] D[76,244] = var(76); // [ var(244) , var(76) ] D[77,244] = var(77); // [ var(244) , var(77) ] D[78,244] = (-1)*var(78); // [ var(244) , var(78) ] D[83,244] = var(83); // [ var(244) , var(83) ] D[84,244] = (-1)*var(84); // [ var(244) , var(84) ] D[85,244] = (-1)*var(85); // [ var(244) , var(85) ] D[88,244] = var(88); // [ var(244) , var(88) ] D[89,244] = var(89); // [ var(244) , var(89) ] D[90,244] = (-1)*var(90); // [ var(244) , var(90) ] D[94,244] = var(94); // [ var(244) , var(94) ] D[95,244] = (-1)*var(95); // [ var(244) , var(95) ] D[99,244] = var(99); // [ var(244) , var(99) ] D[100,244] = (-1)*var(100); // [ var(244) , var(100) ] D[103,244] = var(103); // [ var(244) , var(103) ] D[108,244] = (-1)*var(108); // [ var(244) , var(108) ] D[109,244] = (-1)*var(109); // [ var(244) , var(109) ] D[110,244] = var(110); // [ var(244) , var(110) ] D[111,244] = var(111); // [ var(244) , var(111) ] D[115,244] = (-1)*var(115); // [ var(244) , var(115) ] D[116,244] = var(116); // [ var(244) , var(116) ] D[4,245] = (-1)*var(4); // [ var(245) , var(4) ] D[5,245] = (2)*var(5); // [ var(245) , var(5) ] D[6,245] = (-1)*var(6); // [ var(245) , var(6) ] D[10,245] = (-1)*var(10); // [ var(245) , var(10) ] D[11,245] = (-1)*var(11); // [ var(245) , var(11) ] D[12,245] = var(12); // [ var(245) , var(12) ] D[13,245] = var(13); // [ var(245) , var(13) ] D[14,245] = (-1)*var(14); // [ var(245) , var(14) ] D[16,245] = (-1)*var(16); // [ var(245) , var(16) ] D[17,245] = (-1)*var(17); // [ var(245) , var(17) ] D[18,245] = var(18); // [ var(245) , var(18) ] D[19,245] = var(19); // [ var(245) , var(19) ] D[21,245] = var(21); // [ var(245) , var(21) ] D[22,245] = (-1)*var(22); // [ var(245) , var(22) ] D[23,245] = (-1)*var(23); // [ var(245) , var(23) ] D[24,245] = var(24); // [ var(245) , var(24) ] D[25,245] = var(25); // [ var(245) , var(25) ] D[29,245] = var(29); // [ var(245) , var(29) ] D[30,245] = var(30); // [ var(245) , var(30) ] D[40,245] = (-1)*var(40); // [ var(245) , var(40) ] D[45,245] = (-1)*var(45); // [ var(245) , var(45) ] D[48,245] = var(48); // [ var(245) , var(48) ] D[49,245] = (-1)*var(49); // [ var(245) , var(49) ] D[51,245] = (-1)*var(51); // [ var(245) , var(51) ] D[52,245] = var(52); // [ var(245) , var(52) ] D[53,245] = (-1)*var(53); // [ var(245) , var(53) ] D[55,245] = var(55); // [ var(245) , var(55) ] D[56,245] = (-1)*var(56); // [ var(245) , var(56) ] D[57,245] = var(57); // [ var(245) , var(57) ] D[58,245] = (-1)*var(58); // [ var(245) , var(58) ] D[59,245] = var(59); // [ var(245) , var(59) ] D[60,245] = (-1)*var(60); // [ var(245) , var(60) ] D[62,245] = var(62); // [ var(245) , var(62) ] D[64,245] = var(64); // [ var(245) , var(64) ] D[65,245] = (-1)*var(65); // [ var(245) , var(65) ] D[67,245] = var(67); // [ var(245) , var(67) ] D[72,245] = var(72); // [ var(245) , var(72) ] D[76,245] = (-1)*var(76); // [ var(245) , var(76) ] D[80,245] = (-1)*var(80); // [ var(245) , var(80) ] D[82,245] = var(82); // [ var(245) , var(82) ] D[83,245] = (-1)*var(83); // [ var(245) , var(83) ] D[85,245] = var(85); // [ var(245) , var(85) ] D[86,245] = (-1)*var(86); // [ var(245) , var(86) ] D[87,245] = var(87); // [ var(245) , var(87) ] D[88,245] = (-1)*var(88); // [ var(245) , var(88) ] D[90,245] = var(90); // [ var(245) , var(90) ] D[91,245] = (-1)*var(91); // [ var(245) , var(91) ] D[92,245] = var(92); // [ var(245) , var(92) ] D[95,245] = var(95); // [ var(245) , var(95) ] D[103,245] = (-1)*var(103); // [ var(245) , var(103) ] D[105,245] = (-1)*var(105); // [ var(245) , var(105) ] D[106,245] = var(106); // [ var(245) , var(106) ] D[107,245] = (-1)*var(107); // [ var(245) , var(107) ] D[108,245] = var(108); // [ var(245) , var(108) ] D[109,245] = var(109); // [ var(245) , var(109) ] D[116,245] = (-1)*var(116); // [ var(245) , var(116) ] D[117,245] = var(117); // [ var(245) , var(117) ] D[5,246] = (-1)*var(5); // [ var(246) , var(5) ] D[6,246] = (2)*var(6); // [ var(246) , var(6) ] D[7,246] = (-1)*var(7); // [ var(246) , var(7) ] D[12,246] = (-1)*var(12); // [ var(246) , var(12) ] D[13,246] = var(13); // [ var(246) , var(13) ] D[14,246] = var(14); // [ var(246) , var(14) ] D[15,246] = (-1)*var(15); // [ var(246) , var(15) ] D[18,246] = (-1)*var(18); // [ var(246) , var(18) ] D[19,246] = (-1)*var(19); // [ var(246) , var(19) ] D[20,246] = var(20); // [ var(246) , var(20) ] D[22,246] = var(22); // [ var(246) , var(22) ] D[24,246] = (-1)*var(24); // [ var(246) , var(24) ] D[25,246] = (-1)*var(25); // [ var(246) , var(25) ] D[26,246] = var(26); // [ var(246) , var(26) ] D[27,246] = var(27); // [ var(246) , var(27) ] D[30,246] = (-1)*var(30); // [ var(246) , var(30) ] D[31,246] = var(31); // [ var(246) , var(31) ] D[32,246] = (-1)*var(32); // [ var(246) , var(32) ] D[33,246] = var(33); // [ var(246) , var(33) ] D[37,246] = (-1)*var(37); // [ var(246) , var(37) ] D[38,246] = var(38); // [ var(246) , var(38) ] D[40,246] = var(40); // [ var(246) , var(40) ] D[44,246] = (-1)*var(44); // [ var(246) , var(44) ] D[45,246] = var(45); // [ var(246) , var(45) ] D[51,246] = var(51); // [ var(246) , var(51) ] D[55,246] = (-1)*var(55); // [ var(246) , var(55) ] D[59,246] = (-1)*var(59); // [ var(246) , var(59) ] D[61,246] = var(61); // [ var(246) , var(61) ] D[62,246] = (-1)*var(62); // [ var(246) , var(62) ] D[64,246] = (-1)*var(64); // [ var(246) , var(64) ] D[66,246] = var(66); // [ var(246) , var(66) ] D[67,246] = (-1)*var(67); // [ var(246) , var(67) ] D[68,246] = var(68); // [ var(246) , var(68) ] D[70,246] = (-1)*var(70); // [ var(246) , var(70) ] D[71,246] = var(71); // [ var(246) , var(71) ] D[72,246] = (-1)*var(72); // [ var(246) , var(72) ] D[73,246] = var(73); // [ var(246) , var(73) ] D[75,246] = (-1)*var(75); // [ var(246) , var(75) ] D[76,246] = var(76); // [ var(246) , var(76) ] D[77,246] = (-1)*var(77); // [ var(246) , var(77) ] D[78,246] = var(78); // [ var(246) , var(78) ] D[80,246] = var(80); // [ var(246) , var(80) ] D[81,246] = (-1)*var(81); // [ var(246) , var(81) ] D[83,246] = var(83); // [ var(246) , var(83) ] D[86,246] = var(86); // [ var(246) , var(86) ] D[92,246] = (-1)*var(92); // [ var(246) , var(92) ] D[95,246] = (-1)*var(95); // [ var(246) , var(95) ] D[96,246] = var(96); // [ var(246) , var(96) ] D[99,246] = (-1)*var(99); // [ var(246) , var(99) ] D[100,246] = var(100); // [ var(246) , var(100) ] D[102,246] = (-1)*var(102); // [ var(246) , var(102) ] D[103,246] = var(103); // [ var(246) , var(103) ] D[104,246] = (-1)*var(104); // [ var(246) , var(104) ] D[105,246] = var(105); // [ var(246) , var(105) ] D[107,246] = var(107); // [ var(246) , var(107) ] D[117,246] = (-1)*var(117); // [ var(246) , var(117) ] D[118,246] = var(118); // [ var(246) , var(118) ] D[6,247] = (-1)*var(6); // [ var(247) , var(6) ] D[7,247] = (2)*var(7); // [ var(247) , var(7) ] D[8,247] = (-1)*var(8); // [ var(247) , var(8) ] D[13,247] = (-1)*var(13); // [ var(247) , var(13) ] D[14,247] = var(14); // [ var(247) , var(14) ] D[15,247] = var(15); // [ var(247) , var(15) ] D[20,247] = (-1)*var(20); // [ var(247) , var(20) ] D[21,247] = var(21); // [ var(247) , var(21) ] D[26,247] = (-1)*var(26); // [ var(247) , var(26) ] D[27,247] = (-1)*var(27); // [ var(247) , var(27) ] D[28,247] = var(28); // [ var(247) , var(28) ] D[31,247] = (-1)*var(31); // [ var(247) , var(31) ] D[33,247] = (-1)*var(33); // [ var(247) , var(33) ] D[34,247] = var(34); // [ var(247) , var(34) ] D[35,247] = var(35); // [ var(247) , var(35) ] D[38,247] = (-1)*var(38); // [ var(247) , var(38) ] D[39,247] = var(39); // [ var(247) , var(39) ] D[40,247] = (-1)*var(40); // [ var(247) , var(40) ] D[41,247] = var(41); // [ var(247) , var(41) ] D[45,247] = (-1)*var(45); // [ var(247) , var(45) ] D[46,247] = var(46); // [ var(247) , var(46) ] D[48,247] = (-1)*var(48); // [ var(247) , var(48) ] D[49,247] = var(49); // [ var(247) , var(49) ] D[51,247] = (-1)*var(51); // [ var(247) , var(51) ] D[52,247] = (-1)*var(52); // [ var(247) , var(52) ] D[53,247] = var(53); // [ var(247) , var(53) ] D[55,247] = var(55); // [ var(247) , var(55) ] D[57,247] = (-1)*var(57); // [ var(247) , var(57) ] D[58,247] = var(58); // [ var(247) , var(58) ] D[59,247] = var(59); // [ var(247) , var(59) ] D[63,247] = (-1)*var(63); // [ var(247) , var(63) ] D[64,247] = var(64); // [ var(247) , var(64) ] D[68,247] = (-1)*var(68); // [ var(247) , var(68) ] D[69,247] = (-1)*var(69); // [ var(247) , var(69) ] D[70,247] = var(70); // [ var(247) , var(70) ] D[73,247] = (-1)*var(73); // [ var(247) , var(73) ] D[74,247] = var(74); // [ var(247) , var(74) ] D[75,247] = var(75); // [ var(247) , var(75) ] D[78,247] = (-1)*var(78); // [ var(247) , var(78) ] D[79,247] = var(79); // [ var(247) , var(79) ] D[83,247] = (-1)*var(83); // [ var(247) , var(83) ] D[84,247] = var(84); // [ var(247) , var(84) ] D[86,247] = (-1)*var(86); // [ var(247) , var(86) ] D[87,247] = (-1)*var(87); // [ var(247) , var(87) ] D[88,247] = var(88); // [ var(247) , var(88) ] D[90,247] = (-1)*var(90); // [ var(247) , var(90) ] D[91,247] = var(91); // [ var(247) , var(91) ] D[92,247] = var(92); // [ var(247) , var(92) ] D[94,247] = (-1)*var(94); // [ var(247) , var(94) ] D[95,247] = var(95); // [ var(247) , var(95) ] D[98,247] = (-1)*var(98); // [ var(247) , var(98) ] D[99,247] = var(99); // [ var(247) , var(99) ] D[101,247] = (-1)*var(101); // [ var(247) , var(101) ] D[102,247] = var(102); // [ var(247) , var(102) ] D[104,247] = var(104); // [ var(247) , var(104) ] D[118,247] = (-1)*var(118); // [ var(247) , var(118) ] D[119,247] = var(119); // [ var(247) , var(119) ] D[7,248] = (-1)*var(7); // [ var(248) , var(7) ] D[8,248] = (2)*var(8); // [ var(248) , var(8) ] D[14,248] = (-1)*var(14); // [ var(248) , var(14) ] D[15,248] = var(15); // [ var(248) , var(15) ] D[21,248] = (-1)*var(21); // [ var(248) , var(21) ] D[22,248] = var(22); // [ var(248) , var(22) ] D[28,248] = (-1)*var(28); // [ var(248) , var(28) ] D[29,248] = var(29); // [ var(248) , var(29) ] D[34,248] = (-1)*var(34); // [ var(248) , var(34) ] D[35,248] = (-1)*var(35); // [ var(248) , var(35) ] D[36,248] = var(36); // [ var(248) , var(36) ] D[39,248] = (-1)*var(39); // [ var(248) , var(39) ] D[41,248] = (-1)*var(41); // [ var(248) , var(41) ] D[42,248] = var(42); // [ var(248) , var(42) ] D[43,248] = var(43); // [ var(248) , var(43) ] D[46,248] = (-1)*var(46); // [ var(248) , var(46) ] D[47,248] = var(47); // [ var(248) , var(47) ] D[49,248] = (-1)*var(49); // [ var(248) , var(49) ] D[50,248] = var(50); // [ var(248) , var(50) ] D[53,248] = (-1)*var(53); // [ var(248) , var(53) ] D[54,248] = var(54); // [ var(248) , var(54) ] D[55,248] = (-1)*var(55); // [ var(248) , var(55) ] D[56,248] = var(56); // [ var(248) , var(56) ] D[58,248] = (-1)*var(58); // [ var(248) , var(58) ] D[59,248] = (-1)*var(59); // [ var(248) , var(59) ] D[60,248] = var(60); // [ var(248) , var(60) ] D[61,248] = (-1)*var(61); // [ var(248) , var(61) ] D[62,248] = var(62); // [ var(248) , var(62) ] D[64,248] = (-1)*var(64); // [ var(248) , var(64) ] D[65,248] = var(65); // [ var(248) , var(65) ] D[66,248] = (-1)*var(66); // [ var(248) , var(66) ] D[67,248] = var(67); // [ var(248) , var(67) ] D[68,248] = var(68); // [ var(248) , var(68) ] D[70,248] = (-1)*var(70); // [ var(248) , var(70) ] D[71,248] = (-1)*var(71); // [ var(248) , var(71) ] D[72,248] = var(72); // [ var(248) , var(72) ] D[73,248] = var(73); // [ var(248) , var(73) ] D[75,248] = (-1)*var(75); // [ var(248) , var(75) ] D[76,248] = (-1)*var(76); // [ var(248) , var(76) ] D[77,248] = var(77); // [ var(248) , var(77) ] D[78,248] = var(78); // [ var(248) , var(78) ] D[80,248] = (-1)*var(80); // [ var(248) , var(80) ] D[81,248] = var(81); // [ var(248) , var(81) ] D[82,248] = (-1)*var(82); // [ var(248) , var(82) ] D[83,248] = var(83); // [ var(248) , var(83) ] D[85,248] = (-1)*var(85); // [ var(248) , var(85) ] D[86,248] = var(86); // [ var(248) , var(86) ] D[87,248] = var(87); // [ var(248) , var(87) ] D[89,248] = (-1)*var(89); // [ var(248) , var(89) ] D[90,248] = var(90); // [ var(248) , var(90) ] D[93,248] = (-1)*var(93); // [ var(248) , var(93) ] D[94,248] = var(94); // [ var(248) , var(94) ] D[97,248] = (-1)*var(97); // [ var(248) , var(97) ] D[98,248] = var(98); // [ var(248) , var(98) ] D[101,248] = var(101); // [ var(248) , var(101) ] D[119,248] = (-1)*var(119); // [ var(248) , var(119) ] D[120,248] = var(120); // [ var(248) , var(120) ] // H(i) * Y(j): D[121,241] = (-2)*var(121); // [ var(241) , var(121) ] D[123,241] = var(123); // [ var(241) , var(123) ] D[129,241] = (-1)*var(129); // [ var(241) , var(129) ] D[131,241] = var(131); // [ var(241) , var(131) ] D[136,241] = (-1)*var(136); // [ var(241) , var(136) ] D[137,241] = var(137); // [ var(241) , var(137) ] D[139,241] = var(139); // [ var(241) , var(139) ] D[143,241] = (-1)*var(143); // [ var(241) , var(143) ] D[144,241] = (-1)*var(144); // [ var(241) , var(144) ] D[145,241] = var(145); // [ var(241) , var(145) ] D[147,241] = var(147); // [ var(241) , var(147) ] D[150,241] = (-1)*var(150); // [ var(241) , var(150) ] D[151,241] = (-1)*var(151); // [ var(241) , var(151) ] D[152,241] = var(152); // [ var(241) , var(152) ] D[153,241] = var(153); // [ var(241) , var(153) ] D[155,241] = var(155); // [ var(241) , var(155) ] D[157,241] = (-1)*var(157); // [ var(241) , var(157) ] D[158,241] = (-1)*var(158); // [ var(241) , var(158) ] D[159,241] = (-1)*var(159); // [ var(241) , var(159) ] D[160,241] = var(160); // [ var(241) , var(160) ] D[161,241] = var(161); // [ var(241) , var(161) ] D[163,241] = var(163); // [ var(241) , var(163) ] D[165,241] = (-1)*var(165); // [ var(241) , var(165) ] D[166,241] = (-1)*var(166); // [ var(241) , var(166) ] D[167,241] = (-1)*var(167); // [ var(241) , var(167) ] D[168,241] = var(168); // [ var(241) , var(168) ] D[169,241] = var(169); // [ var(241) , var(169) ] D[170,241] = var(170); // [ var(241) , var(170) ] D[172,241] = (-1)*var(172); // [ var(241) , var(172) ] D[173,241] = (-1)*var(173); // [ var(241) , var(173) ] D[174,241] = (-1)*var(174); // [ var(241) , var(174) ] D[175,241] = var(175); // [ var(241) , var(175) ] D[176,241] = var(176); // [ var(241) , var(176) ] D[179,241] = (-1)*var(179); // [ var(241) , var(179) ] D[180,241] = (-1)*var(180); // [ var(241) , var(180) ] D[181,241] = var(181); // [ var(241) , var(181) ] D[182,241] = var(182); // [ var(241) , var(182) ] D[186,241] = (-1)*var(186); // [ var(241) , var(186) ] D[187,241] = (-1)*var(187); // [ var(241) , var(187) ] D[188,241] = var(188); // [ var(241) , var(188) ] D[193,241] = (-1)*var(193); // [ var(241) , var(193) ] D[194,241] = var(194); // [ var(241) , var(194) ] D[199,241] = (-1)*var(199); // [ var(241) , var(199) ] D[213,241] = var(213); // [ var(241) , var(213) ] D[217,241] = (-1)*var(217); // [ var(241) , var(217) ] D[218,241] = var(218); // [ var(241) , var(218) ] D[221,241] = (-1)*var(221); // [ var(241) , var(221) ] D[222,241] = var(222); // [ var(241) , var(222) ] D[224,241] = (-1)*var(224); // [ var(241) , var(224) ] D[225,241] = var(225); // [ var(241) , var(225) ] D[227,241] = (-1)*var(227); // [ var(241) , var(227) ] D[228,241] = var(228); // [ var(241) , var(228) ] D[229,241] = (-1)*var(229); // [ var(241) , var(229) ] D[230,241] = var(230); // [ var(241) , var(230) ] D[231,241] = (-1)*var(231); // [ var(241) , var(231) ] D[232,241] = var(232); // [ var(241) , var(232) ] D[233,241] = (-1)*var(233); // [ var(241) , var(233) ] D[122,242] = (-2)*var(122); // [ var(242) , var(122) ] D[124,242] = var(124); // [ var(242) , var(124) ] D[130,242] = (-1)*var(130); // [ var(242) , var(130) ] D[131,242] = var(131); // [ var(242) , var(131) ] D[132,242] = var(132); // [ var(242) , var(132) ] D[136,242] = var(136); // [ var(242) , var(136) ] D[137,242] = (-1)*var(137); // [ var(242) , var(137) ] D[138,242] = (-1)*var(138); // [ var(242) , var(138) ] D[139,242] = var(139); // [ var(242) , var(139) ] D[140,242] = var(140); // [ var(242) , var(140) ] D[143,242] = (-1)*var(143); // [ var(242) , var(143) ] D[144,242] = var(144); // [ var(242) , var(144) ] D[145,242] = (-1)*var(145); // [ var(242) , var(145) ] D[146,242] = (-1)*var(146); // [ var(242) , var(146) ] D[147,242] = var(147); // [ var(242) , var(147) ] D[148,242] = var(148); // [ var(242) , var(148) ] D[150,242] = (-1)*var(150); // [ var(242) , var(150) ] D[151,242] = var(151); // [ var(242) , var(151) ] D[153,242] = (-1)*var(153); // [ var(242) , var(153) ] D[154,242] = (-1)*var(154); // [ var(242) , var(154) ] D[155,242] = var(155); // [ var(242) , var(155) ] D[156,242] = var(156); // [ var(242) , var(156) ] D[158,242] = (-1)*var(158); // [ var(242) , var(158) ] D[159,242] = var(159); // [ var(242) , var(159) ] D[161,242] = (-1)*var(161); // [ var(242) , var(161) ] D[162,242] = (-1)*var(162); // [ var(242) , var(162) ] D[163,242] = var(163); // [ var(242) , var(163) ] D[166,242] = (-1)*var(166); // [ var(242) , var(166) ] D[167,242] = var(167); // [ var(242) , var(167) ] D[170,242] = (-1)*var(170); // [ var(242) , var(170) ] D[174,242] = (-1)*var(174); // [ var(242) , var(174) ] D[183,242] = var(183); // [ var(242) , var(183) ] D[189,242] = (-1)*var(189); // [ var(242) , var(189) ] D[190,242] = var(190); // [ var(242) , var(190) ] D[195,242] = (-1)*var(195); // [ var(242) , var(195) ] D[196,242] = var(196); // [ var(242) , var(196) ] D[197,242] = var(197); // [ var(242) , var(197) ] D[200,242] = (-1)*var(200); // [ var(242) , var(200) ] D[201,242] = (-1)*var(201); // [ var(242) , var(201) ] D[202,242] = var(202); // [ var(242) , var(202) ] D[203,242] = var(203); // [ var(242) , var(203) ] D[205,242] = (-1)*var(205); // [ var(242) , var(205) ] D[206,242] = (-1)*var(206); // [ var(242) , var(206) ] D[207,242] = var(207); // [ var(242) , var(207) ] D[208,242] = var(208); // [ var(242) , var(208) ] D[210,242] = (-1)*var(210); // [ var(242) , var(210) ] D[211,242] = (-1)*var(211); // [ var(242) , var(211) ] D[212,242] = var(212); // [ var(242) , var(212) ] D[215,242] = (-1)*var(215); // [ var(242) , var(215) ] D[216,242] = var(216); // [ var(242) , var(216) ] D[220,242] = (-1)*var(220); // [ var(242) , var(220) ] D[230,242] = var(230); // [ var(242) , var(230) ] D[231,242] = var(231); // [ var(242) , var(231) ] D[232,242] = (-1)*var(232); // [ var(242) , var(232) ] D[233,242] = (-1)*var(233); // [ var(242) , var(233) ] D[234,242] = var(234); // [ var(242) , var(234) ] D[235,242] = (-1)*var(235); // [ var(242) , var(235) ] D[121,243] = var(121); // [ var(243) , var(121) ] D[123,243] = (-2)*var(123); // [ var(243) , var(123) ] D[124,243] = var(124); // [ var(243) , var(124) ] D[129,243] = (-1)*var(129); // [ var(243) , var(129) ] D[130,243] = var(130); // [ var(243) , var(130) ] D[131,243] = (-1)*var(131); // [ var(243) , var(131) ] D[132,243] = var(132); // [ var(243) , var(132) ] D[137,243] = (-1)*var(137); // [ var(243) , var(137) ] D[138,243] = var(138); // [ var(243) , var(138) ] D[139,243] = (-1)*var(139); // [ var(243) , var(139) ] D[140,243] = var(140); // [ var(243) , var(140) ] D[145,243] = (-1)*var(145); // [ var(243) , var(145) ] D[146,243] = var(146); // [ var(243) , var(146) ] D[147,243] = (-1)*var(147); // [ var(243) , var(147) ] D[148,243] = var(148); // [ var(243) , var(148) ] D[153,243] = (-1)*var(153); // [ var(243) , var(153) ] D[154,243] = var(154); // [ var(243) , var(154) ] D[155,243] = (-1)*var(155); // [ var(243) , var(155) ] D[156,243] = var(156); // [ var(243) , var(156) ] D[157,243] = var(157); // [ var(243) , var(157) ] D[161,243] = (-1)*var(161); // [ var(243) , var(161) ] D[162,243] = var(162); // [ var(243) , var(162) ] D[163,243] = (-1)*var(163); // [ var(243) , var(163) ] D[164,243] = (-1)*var(164); // [ var(243) , var(164) ] D[165,243] = var(165); // [ var(243) , var(165) ] D[170,243] = (-1)*var(170); // [ var(243) , var(170) ] D[171,243] = (-1)*var(171); // [ var(243) , var(171) ] D[172,243] = var(172); // [ var(243) , var(172) ] D[173,243] = var(173); // [ var(243) , var(173) ] D[177,243] = (-1)*var(177); // [ var(243) , var(177) ] D[178,243] = (-1)*var(178); // [ var(243) , var(178) ] D[179,243] = var(179); // [ var(243) , var(179) ] D[180,243] = var(180); // [ var(243) , var(180) ] D[184,243] = (-1)*var(184); // [ var(243) , var(184) ] D[185,243] = (-1)*var(185); // [ var(243) , var(185) ] D[186,243] = var(186); // [ var(243) , var(186) ] D[187,243] = var(187); // [ var(243) , var(187) ] D[191,243] = (-1)*var(191); // [ var(243) , var(191) ] D[192,243] = (-1)*var(192); // [ var(243) , var(192) ] D[193,243] = var(193); // [ var(243) , var(193) ] D[198,243] = (-1)*var(198); // [ var(243) , var(198) ] D[199,243] = var(199); // [ var(243) , var(199) ] D[204,243] = (-1)*var(204); // [ var(243) , var(204) ] D[209,243] = var(209); // [ var(243) , var(209) ] D[213,243] = (-1)*var(213); // [ var(243) , var(213) ] D[214,243] = var(214); // [ var(243) , var(214) ] D[218,243] = (-1)*var(218); // [ var(243) , var(218) ] D[219,243] = var(219); // [ var(243) , var(219) ] D[222,243] = (-1)*var(222); // [ var(243) , var(222) ] D[223,243] = var(223); // [ var(243) , var(223) ] D[225,243] = (-1)*var(225); // [ var(243) , var(225) ] D[226,243] = var(226); // [ var(243) , var(226) ] D[228,243] = (-1)*var(228); // [ var(243) , var(228) ] D[231,243] = var(231); // [ var(243) , var(231) ] D[233,243] = var(233); // [ var(243) , var(233) ] D[234,243] = (-1)*var(234); // [ var(243) , var(234) ] D[235,243] = (-1)*var(235); // [ var(243) , var(235) ] D[122,244] = var(122); // [ var(244) , var(122) ] D[123,244] = var(123); // [ var(244) , var(123) ] D[124,244] = (-2)*var(124); // [ var(244) , var(124) ] D[125,244] = var(125); // [ var(244) , var(125) ] D[129,244] = var(129); // [ var(244) , var(129) ] D[130,244] = (-1)*var(130); // [ var(244) , var(130) ] D[131,244] = (-1)*var(131); // [ var(244) , var(131) ] D[132,244] = (-1)*var(132); // [ var(244) , var(132) ] D[133,244] = var(133); // [ var(244) , var(133) ] D[136,244] = (-1)*var(136); // [ var(244) , var(136) ] D[140,244] = (-1)*var(140); // [ var(244) , var(140) ] D[141,244] = var(141); // [ var(244) , var(141) ] D[145,244] = var(145); // [ var(244) , var(145) ] D[148,244] = (-1)*var(148); // [ var(244) , var(148) ] D[149,244] = var(149); // [ var(244) , var(149) ] D[150,244] = var(150); // [ var(244) , var(150) ] D[152,244] = (-1)*var(152); // [ var(244) , var(152) ] D[153,244] = var(153); // [ var(244) , var(153) ] D[156,244] = (-1)*var(156); // [ var(244) , var(156) ] D[157,244] = (-1)*var(157); // [ var(244) , var(157) ] D[158,244] = var(158); // [ var(244) , var(158) ] D[160,244] = (-1)*var(160); // [ var(244) , var(160) ] D[161,244] = var(161); // [ var(244) , var(161) ] D[165,244] = (-1)*var(165); // [ var(244) , var(165) ] D[166,244] = var(166); // [ var(244) , var(166) ] D[169,244] = (-1)*var(169); // [ var(244) , var(169) ] D[170,244] = var(170); // [ var(244) , var(170) ] D[173,244] = (-1)*var(173); // [ var(244) , var(173) ] D[174,244] = var(174); // [ var(244) , var(174) ] D[176,244] = (-1)*var(176); // [ var(244) , var(176) ] D[177,244] = var(177); // [ var(244) , var(177) ] D[180,244] = (-1)*var(180); // [ var(244) , var(180) ] D[183,244] = (-1)*var(183); // [ var(244) , var(183) ] D[184,244] = var(184); // [ var(244) , var(184) ] D[190,244] = (-1)*var(190); // [ var(244) , var(190) ] D[191,244] = var(191); // [ var(244) , var(191) ] D[192,244] = var(192); // [ var(244) , var(192) ] D[196,244] = (-1)*var(196); // [ var(244) , var(196) ] D[197,244] = (-1)*var(197); // [ var(244) , var(197) ] D[198,244] = var(198); // [ var(244) , var(198) ] D[203,244] = (-1)*var(203); // [ var(244) , var(203) ] D[204,244] = var(204); // [ var(244) , var(204) ] D[205,244] = var(205); // [ var(244) , var(205) ] D[208,244] = (-1)*var(208); // [ var(244) , var(208) ] D[209,244] = (-1)*var(209); // [ var(244) , var(209) ] D[210,244] = var(210); // [ var(244) , var(210) ] D[214,244] = (-1)*var(214); // [ var(244) , var(214) ] D[215,244] = var(215); // [ var(244) , var(215) ] D[219,244] = (-1)*var(219); // [ var(244) , var(219) ] D[220,244] = var(220); // [ var(244) , var(220) ] D[223,244] = (-1)*var(223); // [ var(244) , var(223) ] D[228,244] = var(228); // [ var(244) , var(228) ] D[229,244] = var(229); // [ var(244) , var(229) ] D[230,244] = (-1)*var(230); // [ var(244) , var(230) ] D[231,244] = (-1)*var(231); // [ var(244) , var(231) ] D[235,244] = var(235); // [ var(244) , var(235) ] D[236,244] = (-1)*var(236); // [ var(244) , var(236) ] D[124,245] = var(124); // [ var(245) , var(124) ] D[125,245] = (-2)*var(125); // [ var(245) , var(125) ] D[126,245] = var(126); // [ var(245) , var(126) ] D[130,245] = var(130); // [ var(245) , var(130) ] D[131,245] = var(131); // [ var(245) , var(131) ] D[132,245] = (-1)*var(132); // [ var(245) , var(132) ] D[133,245] = (-1)*var(133); // [ var(245) , var(133) ] D[134,245] = var(134); // [ var(245) , var(134) ] D[136,245] = var(136); // [ var(245) , var(136) ] D[137,245] = var(137); // [ var(245) , var(137) ] D[138,245] = (-1)*var(138); // [ var(245) , var(138) ] D[139,245] = (-1)*var(139); // [ var(245) , var(139) ] D[141,245] = (-1)*var(141); // [ var(245) , var(141) ] D[142,245] = var(142); // [ var(245) , var(142) ] D[143,245] = var(143); // [ var(245) , var(143) ] D[144,245] = (-1)*var(144); // [ var(245) , var(144) ] D[145,245] = (-1)*var(145); // [ var(245) , var(145) ] D[149,245] = (-1)*var(149); // [ var(245) , var(149) ] D[150,245] = (-1)*var(150); // [ var(245) , var(150) ] D[160,245] = var(160); // [ var(245) , var(160) ] D[165,245] = var(165); // [ var(245) , var(165) ] D[168,245] = (-1)*var(168); // [ var(245) , var(168) ] D[169,245] = var(169); // [ var(245) , var(169) ] D[171,245] = var(171); // [ var(245) , var(171) ] D[172,245] = (-1)*var(172); // [ var(245) , var(172) ] D[173,245] = var(173); // [ var(245) , var(173) ] D[175,245] = (-1)*var(175); // [ var(245) , var(175) ] D[176,245] = var(176); // [ var(245) , var(176) ] D[177,245] = (-1)*var(177); // [ var(245) , var(177) ] D[178,245] = var(178); // [ var(245) , var(178) ] D[179,245] = (-1)*var(179); // [ var(245) , var(179) ] D[180,245] = var(180); // [ var(245) , var(180) ] D[182,245] = (-1)*var(182); // [ var(245) , var(182) ] D[184,245] = (-1)*var(184); // [ var(245) , var(184) ] D[185,245] = var(185); // [ var(245) , var(185) ] D[187,245] = (-1)*var(187); // [ var(245) , var(187) ] D[192,245] = (-1)*var(192); // [ var(245) , var(192) ] D[196,245] = var(196); // [ var(245) , var(196) ] D[200,245] = var(200); // [ var(245) , var(200) ] D[202,245] = (-1)*var(202); // [ var(245) , var(202) ] D[203,245] = var(203); // [ var(245) , var(203) ] D[205,245] = (-1)*var(205); // [ var(245) , var(205) ] D[206,245] = var(206); // [ var(245) , var(206) ] D[207,245] = (-1)*var(207); // [ var(245) , var(207) ] D[208,245] = var(208); // [ var(245) , var(208) ] D[210,245] = (-1)*var(210); // [ var(245) , var(210) ] D[211,245] = var(211); // [ var(245) , var(211) ] D[212,245] = (-1)*var(212); // [ var(245) , var(212) ] D[215,245] = (-1)*var(215); // [ var(245) , var(215) ] D[223,245] = var(223); // [ var(245) , var(223) ] D[225,245] = var(225); // [ var(245) , var(225) ] D[226,245] = (-1)*var(226); // [ var(245) , var(226) ] D[227,245] = var(227); // [ var(245) , var(227) ] D[228,245] = (-1)*var(228); // [ var(245) , var(228) ] D[229,245] = (-1)*var(229); // [ var(245) , var(229) ] D[236,245] = var(236); // [ var(245) , var(236) ] D[237,245] = (-1)*var(237); // [ var(245) , var(237) ] D[125,246] = var(125); // [ var(246) , var(125) ] D[126,246] = (-2)*var(126); // [ var(246) , var(126) ] D[127,246] = var(127); // [ var(246) , var(127) ] D[132,246] = var(132); // [ var(246) , var(132) ] D[133,246] = (-1)*var(133); // [ var(246) , var(133) ] D[134,246] = (-1)*var(134); // [ var(246) , var(134) ] D[135,246] = var(135); // [ var(246) , var(135) ] D[138,246] = var(138); // [ var(246) , var(138) ] D[139,246] = var(139); // [ var(246) , var(139) ] D[140,246] = (-1)*var(140); // [ var(246) , var(140) ] D[142,246] = (-1)*var(142); // [ var(246) , var(142) ] D[144,246] = var(144); // [ var(246) , var(144) ] D[145,246] = var(145); // [ var(246) , var(145) ] D[146,246] = (-1)*var(146); // [ var(246) , var(146) ] D[147,246] = (-1)*var(147); // [ var(246) , var(147) ] D[150,246] = var(150); // [ var(246) , var(150) ] D[151,246] = (-1)*var(151); // [ var(246) , var(151) ] D[152,246] = var(152); // [ var(246) , var(152) ] D[153,246] = (-1)*var(153); // [ var(246) , var(153) ] D[157,246] = var(157); // [ var(246) , var(157) ] D[158,246] = (-1)*var(158); // [ var(246) , var(158) ] D[160,246] = (-1)*var(160); // [ var(246) , var(160) ] D[164,246] = var(164); // [ var(246) , var(164) ] D[165,246] = (-1)*var(165); // [ var(246) , var(165) ] D[171,246] = (-1)*var(171); // [ var(246) , var(171) ] D[175,246] = var(175); // [ var(246) , var(175) ] D[179,246] = var(179); // [ var(246) , var(179) ] D[181,246] = (-1)*var(181); // [ var(246) , var(181) ] D[182,246] = var(182); // [ var(246) , var(182) ] D[184,246] = var(184); // [ var(246) , var(184) ] D[186,246] = (-1)*var(186); // [ var(246) , var(186) ] D[187,246] = var(187); // [ var(246) , var(187) ] D[188,246] = (-1)*var(188); // [ var(246) , var(188) ] D[190,246] = var(190); // [ var(246) , var(190) ] D[191,246] = (-1)*var(191); // [ var(246) , var(191) ] D[192,246] = var(192); // [ var(246) , var(192) ] D[193,246] = (-1)*var(193); // [ var(246) , var(193) ] D[195,246] = var(195); // [ var(246) , var(195) ] D[196,246] = (-1)*var(196); // [ var(246) , var(196) ] D[197,246] = var(197); // [ var(246) , var(197) ] D[198,246] = (-1)*var(198); // [ var(246) , var(198) ] D[200,246] = (-1)*var(200); // [ var(246) , var(200) ] D[201,246] = var(201); // [ var(246) , var(201) ] D[203,246] = (-1)*var(203); // [ var(246) , var(203) ] D[206,246] = (-1)*var(206); // [ var(246) , var(206) ] D[212,246] = var(212); // [ var(246) , var(212) ] D[215,246] = var(215); // [ var(246) , var(215) ] D[216,246] = (-1)*var(216); // [ var(246) , var(216) ] D[219,246] = var(219); // [ var(246) , var(219) ] D[220,246] = (-1)*var(220); // [ var(246) , var(220) ] D[222,246] = var(222); // [ var(246) , var(222) ] D[223,246] = (-1)*var(223); // [ var(246) , var(223) ] D[224,246] = var(224); // [ var(246) , var(224) ] D[225,246] = (-1)*var(225); // [ var(246) , var(225) ] D[227,246] = (-1)*var(227); // [ var(246) , var(227) ] D[237,246] = var(237); // [ var(246) , var(237) ] D[238,246] = (-1)*var(238); // [ var(246) , var(238) ] D[126,247] = var(126); // [ var(247) , var(126) ] D[127,247] = (-2)*var(127); // [ var(247) , var(127) ] D[128,247] = var(128); // [ var(247) , var(128) ] D[133,247] = var(133); // [ var(247) , var(133) ] D[134,247] = (-1)*var(134); // [ var(247) , var(134) ] D[135,247] = (-1)*var(135); // [ var(247) , var(135) ] D[140,247] = var(140); // [ var(247) , var(140) ] D[141,247] = (-1)*var(141); // [ var(247) , var(141) ] D[146,247] = var(146); // [ var(247) , var(146) ] D[147,247] = var(147); // [ var(247) , var(147) ] D[148,247] = (-1)*var(148); // [ var(247) , var(148) ] D[151,247] = var(151); // [ var(247) , var(151) ] D[153,247] = var(153); // [ var(247) , var(153) ] D[154,247] = (-1)*var(154); // [ var(247) , var(154) ] D[155,247] = (-1)*var(155); // [ var(247) , var(155) ] D[158,247] = var(158); // [ var(247) , var(158) ] D[159,247] = (-1)*var(159); // [ var(247) , var(159) ] D[160,247] = var(160); // [ var(247) , var(160) ] D[161,247] = (-1)*var(161); // [ var(247) , var(161) ] D[165,247] = var(165); // [ var(247) , var(165) ] D[166,247] = (-1)*var(166); // [ var(247) , var(166) ] D[168,247] = var(168); // [ var(247) , var(168) ] D[169,247] = (-1)*var(169); // [ var(247) , var(169) ] D[171,247] = var(171); // [ var(247) , var(171) ] D[172,247] = var(172); // [ var(247) , var(172) ] D[173,247] = (-1)*var(173); // [ var(247) , var(173) ] D[175,247] = (-1)*var(175); // [ var(247) , var(175) ] D[177,247] = var(177); // [ var(247) , var(177) ] D[178,247] = (-1)*var(178); // [ var(247) , var(178) ] D[179,247] = (-1)*var(179); // [ var(247) , var(179) ] D[183,247] = var(183); // [ var(247) , var(183) ] D[184,247] = (-1)*var(184); // [ var(247) , var(184) ] D[188,247] = var(188); // [ var(247) , var(188) ] D[189,247] = var(189); // [ var(247) , var(189) ] D[190,247] = (-1)*var(190); // [ var(247) , var(190) ] D[193,247] = var(193); // [ var(247) , var(193) ] D[194,247] = (-1)*var(194); // [ var(247) , var(194) ] D[195,247] = (-1)*var(195); // [ var(247) , var(195) ] D[198,247] = var(198); // [ var(247) , var(198) ] D[199,247] = (-1)*var(199); // [ var(247) , var(199) ] D[203,247] = var(203); // [ var(247) , var(203) ] D[204,247] = (-1)*var(204); // [ var(247) , var(204) ] D[206,247] = var(206); // [ var(247) , var(206) ] D[207,247] = var(207); // [ var(247) , var(207) ] D[208,247] = (-1)*var(208); // [ var(247) , var(208) ] D[210,247] = var(210); // [ var(247) , var(210) ] D[211,247] = (-1)*var(211); // [ var(247) , var(211) ] D[212,247] = (-1)*var(212); // [ var(247) , var(212) ] D[214,247] = var(214); // [ var(247) , var(214) ] D[215,247] = (-1)*var(215); // [ var(247) , var(215) ] D[218,247] = var(218); // [ var(247) , var(218) ] D[219,247] = (-1)*var(219); // [ var(247) , var(219) ] D[221,247] = var(221); // [ var(247) , var(221) ] D[222,247] = (-1)*var(222); // [ var(247) , var(222) ] D[224,247] = (-1)*var(224); // [ var(247) , var(224) ] D[238,247] = var(238); // [ var(247) , var(238) ] D[239,247] = (-1)*var(239); // [ var(247) , var(239) ] D[127,248] = var(127); // [ var(248) , var(127) ] D[128,248] = (-2)*var(128); // [ var(248) , var(128) ] D[134,248] = var(134); // [ var(248) , var(134) ] D[135,248] = (-1)*var(135); // [ var(248) , var(135) ] D[141,248] = var(141); // [ var(248) , var(141) ] D[142,248] = (-1)*var(142); // [ var(248) , var(142) ] D[148,248] = var(148); // [ var(248) , var(148) ] D[149,248] = (-1)*var(149); // [ var(248) , var(149) ] D[154,248] = var(154); // [ var(248) , var(154) ] D[155,248] = var(155); // [ var(248) , var(155) ] D[156,248] = (-1)*var(156); // [ var(248) , var(156) ] D[159,248] = var(159); // [ var(248) , var(159) ] D[161,248] = var(161); // [ var(248) , var(161) ] D[162,248] = (-1)*var(162); // [ var(248) , var(162) ] D[163,248] = (-1)*var(163); // [ var(248) , var(163) ] D[166,248] = var(166); // [ var(248) , var(166) ] D[167,248] = (-1)*var(167); // [ var(248) , var(167) ] D[169,248] = var(169); // [ var(248) , var(169) ] D[170,248] = (-1)*var(170); // [ var(248) , var(170) ] D[173,248] = var(173); // [ var(248) , var(173) ] D[174,248] = (-1)*var(174); // [ var(248) , var(174) ] D[175,248] = var(175); // [ var(248) , var(175) ] D[176,248] = (-1)*var(176); // [ var(248) , var(176) ] D[178,248] = var(178); // [ var(248) , var(178) ] D[179,248] = var(179); // [ var(248) , var(179) ] D[180,248] = (-1)*var(180); // [ var(248) , var(180) ] D[181,248] = var(181); // [ var(248) , var(181) ] D[182,248] = (-1)*var(182); // [ var(248) , var(182) ] D[184,248] = var(184); // [ var(248) , var(184) ] D[185,248] = (-1)*var(185); // [ var(248) , var(185) ] D[186,248] = var(186); // [ var(248) , var(186) ] D[187,248] = (-1)*var(187); // [ var(248) , var(187) ] D[188,248] = (-1)*var(188); // [ var(248) , var(188) ] D[190,248] = var(190); // [ var(248) , var(190) ] D[191,248] = var(191); // [ var(248) , var(191) ] D[192,248] = (-1)*var(192); // [ var(248) , var(192) ] D[193,248] = (-1)*var(193); // [ var(248) , var(193) ] D[195,248] = var(195); // [ var(248) , var(195) ] D[196,248] = var(196); // [ var(248) , var(196) ] D[197,248] = (-1)*var(197); // [ var(248) , var(197) ] D[198,248] = (-1)*var(198); // [ var(248) , var(198) ] D[200,248] = var(200); // [ var(248) , var(200) ] D[201,248] = (-1)*var(201); // [ var(248) , var(201) ] D[202,248] = var(202); // [ var(248) , var(202) ] D[203,248] = (-1)*var(203); // [ var(248) , var(203) ] D[205,248] = var(205); // [ var(248) , var(205) ] D[206,248] = (-1)*var(206); // [ var(248) , var(206) ] D[207,248] = (-1)*var(207); // [ var(248) , var(207) ] D[209,248] = var(209); // [ var(248) , var(209) ] D[210,248] = (-1)*var(210); // [ var(248) , var(210) ] D[213,248] = var(213); // [ var(248) , var(213) ] D[214,248] = (-1)*var(214); // [ var(248) , var(214) ] D[217,248] = var(217); // [ var(248) , var(217) ] D[218,248] = (-1)*var(218); // [ var(248) , var(218) ] D[221,248] = (-1)*var(221); // [ var(248) , var(221) ] D[239,248] = var(239); // [ var(248) , var(239) ] D[240,248] = (-1)*var(240); // [ var(248) , var(240) ] // Y(i) * X(j): D[1,121] = (-1)*var(241); // [ var(121) , var(1) ] D[9,121] = (-1)*var(3); // [ var(121) , var(9) ] D[16,121] = (-1)*var(11); // [ var(121) , var(16) ] D[23,121] = (-1)*var(17); // [ var(121) , var(23) ] D[24,121] = (-1)*var(19); // [ var(121) , var(24) ] D[30,121] = (-1)*var(25); // [ var(121) , var(30) ] D[31,121] = (-1)*var(27); // [ var(121) , var(31) ] D[37,121] = (-1)*var(32); // [ var(121) , var(37) ] D[38,121] = (-1)*var(33); // [ var(121) , var(38) ] D[39,121] = (-1)*var(35); // [ var(121) , var(39) ] D[45,121] = (-1)*var(40); // [ var(121) , var(45) ] D[46,121] = (-1)*var(41); // [ var(121) , var(46) ] D[47,121] = (-1)*var(43); // [ var(121) , var(47) ] D[52,121] = (-1)*var(48); // [ var(121) , var(52) ] D[53,121] = (-1)*var(49); // [ var(121) , var(53) ] D[54,121] = (-1)*var(50); // [ var(121) , var(54) ] D[59,121] = (-1)*var(55); // [ var(121) , var(59) ] D[60,121] = (-1)*var(56); // [ var(121) , var(60) ] D[66,121] = (-1)*var(61); // [ var(121) , var(66) ] D[67,121] = (-1)*var(62); // [ var(121) , var(67) ] D[73,121] = (-1)*var(68); // [ var(121) , var(73) ] D[79,121] = (-1)*var(74); // [ var(121) , var(79) ] D[97,121] = var(93); // [ var(121) , var(97) ] D[101,121] = var(98); // [ var(121) , var(101) ] D[104,121] = var(102); // [ var(121) , var(104) ] D[107,121] = var(105); // [ var(121) , var(107) ] D[109,121] = var(108); // [ var(121) , var(109) ] D[111,121] = var(110); // [ var(121) , var(111) ] D[113,121] = var(112); // [ var(121) , var(113) ] D[2,122] = (-1)*var(242); // [ var(122) , var(2) ] D[10,122] = (-1)*var(4); // [ var(122) , var(10) ] D[17,122] = (-1)*var(11); // [ var(122) , var(17) ] D[18,122] = (-1)*var(12); // [ var(122) , var(18) ] D[23,122] = (-1)*var(16); // [ var(122) , var(23) ] D[25,122] = (-1)*var(19); // [ var(122) , var(25) ] D[26,122] = (-1)*var(20); // [ var(122) , var(26) ] D[30,122] = (-1)*var(24); // [ var(122) , var(30) ] D[33,122] = (-1)*var(27); // [ var(122) , var(33) ] D[34,122] = (-1)*var(28); // [ var(122) , var(34) ] D[38,122] = (-1)*var(31); // [ var(122) , var(38) ] D[41,122] = (-1)*var(35); // [ var(122) , var(41) ] D[42,122] = (-1)*var(36); // [ var(122) , var(42) ] D[46,122] = (-1)*var(39); // [ var(122) , var(46) ] D[50,122] = (-1)*var(43); // [ var(122) , var(50) ] D[54,122] = (-1)*var(47); // [ var(122) , var(54) ] D[69,122] = var(63); // [ var(122) , var(69) ] D[75,122] = var(70); // [ var(122) , var(75) ] D[80,122] = var(76); // [ var(122) , var(80) ] D[81,122] = var(77); // [ var(122) , var(81) ] D[85,122] = var(82); // [ var(122) , var(85) ] D[86,122] = var(83); // [ var(122) , var(86) ] D[90,122] = var(87); // [ var(122) , var(90) ] D[91,122] = var(88); // [ var(122) , var(91) ] D[95,122] = var(92); // [ var(122) , var(95) ] D[100,122] = var(96); // [ var(122) , var(100) ] D[112,122] = (-1)*var(110); // [ var(122) , var(112) ] D[113,122] = (-1)*var(111); // [ var(122) , var(113) ] D[115,122] = (-1)*var(114); // [ var(122) , var(115) ] D[3,123] = (-1)*var(243); // [ var(123) , var(3) ] D[9,123] = var(1); // [ var(123) , var(9) ] D[11,123] = (-1)*var(4); // [ var(123) , var(11) ] D[17,123] = (-1)*var(10); // [ var(123) , var(17) ] D[19,123] = (-1)*var(12); // [ var(123) , var(19) ] D[25,123] = (-1)*var(18); // [ var(123) , var(25) ] D[27,123] = (-1)*var(20); // [ var(123) , var(27) ] D[33,123] = (-1)*var(26); // [ var(123) , var(33) ] D[35,123] = (-1)*var(28); // [ var(123) , var(35) ] D[41,123] = (-1)*var(34); // [ var(123) , var(41) ] D[43,123] = (-1)*var(36); // [ var(123) , var(43) ] D[44,123] = (-1)*var(37); // [ var(123) , var(44) ] D[50,123] = (-1)*var(42); // [ var(123) , var(50) ] D[51,123] = (-1)*var(45); // [ var(123) , var(51) ] D[57,123] = (-1)*var(52); // [ var(123) , var(57) ] D[58,123] = (-1)*var(53); // [ var(123) , var(58) ] D[64,123] = (-1)*var(59); // [ var(123) , var(64) ] D[65,123] = (-1)*var(60); // [ var(123) , var(65) ] D[71,123] = (-1)*var(66); // [ var(123) , var(71) ] D[72,123] = (-1)*var(67); // [ var(123) , var(72) ] D[78,123] = (-1)*var(73); // [ var(123) , var(78) ] D[84,123] = (-1)*var(79); // [ var(123) , var(84) ] D[93,123] = var(89); // [ var(123) , var(93) ] D[98,123] = var(94); // [ var(123) , var(98) ] D[102,123] = var(99); // [ var(123) , var(102) ] D[105,123] = var(103); // [ var(123) , var(105) ] D[108,123] = var(106); // [ var(123) , var(108) ] D[114,123] = var(111); // [ var(123) , var(114) ] D[115,123] = var(113); // [ var(123) , var(115) ] D[4,124] = (-1)*var(244); // [ var(124) , var(4) ] D[10,124] = var(2); // [ var(124) , var(10) ] D[11,124] = var(3); // [ var(124) , var(11) ] D[12,124] = (-1)*var(5); // [ var(124) , var(12) ] D[16,124] = var(9); // [ var(124) , var(16) ] D[20,124] = (-1)*var(13); // [ var(124) , var(20) ] D[28,124] = (-1)*var(21); // [ var(124) , var(28) ] D[32,124] = var(25); // [ var(124) , var(32) ] D[36,124] = (-1)*var(29); // [ var(124) , var(36) ] D[37,124] = var(30); // [ var(124) , var(37) ] D[40,124] = var(33); // [ var(124) , var(40) ] D[45,124] = var(38); // [ var(124) , var(45) ] D[49,124] = var(41); // [ var(124) , var(49) ] D[53,124] = var(46); // [ var(124) , var(53) ] D[56,124] = var(50); // [ var(124) , var(56) ] D[60,124] = var(54); // [ var(124) , var(60) ] D[63,124] = var(57); // [ var(124) , var(63) ] D[70,124] = var(64); // [ var(124) , var(70) ] D[76,124] = var(71); // [ var(124) , var(76) ] D[77,124] = var(72); // [ var(124) , var(77) ] D[83,124] = var(78); // [ var(124) , var(83) ] D[88,124] = var(84); // [ var(124) , var(88) ] D[89,124] = var(85); // [ var(124) , var(89) ] D[94,124] = var(90); // [ var(124) , var(94) ] D[99,124] = var(95); // [ var(124) , var(99) ] D[103,124] = var(100); // [ var(124) , var(103) ] D[110,124] = var(108); // [ var(124) , var(110) ] D[111,124] = var(109); // [ var(124) , var(111) ] D[116,124] = (-1)*var(115); // [ var(124) , var(116) ] D[5,125] = (-1)*var(245); // [ var(125) , var(5) ] D[12,125] = var(4); // [ var(125) , var(12) ] D[13,125] = (-1)*var(6); // [ var(125) , var(13) ] D[18,125] = var(10); // [ var(125) , var(18) ] D[19,125] = var(11); // [ var(125) , var(19) ] D[21,125] = (-1)*var(14); // [ var(125) , var(21) ] D[24,125] = var(16); // [ var(125) , var(24) ] D[25,125] = var(17); // [ var(125) , var(25) ] D[29,125] = (-1)*var(22); // [ var(125) , var(29) ] D[30,125] = var(23); // [ var(125) , var(30) ] D[48,125] = var(40); // [ var(125) , var(48) ] D[52,125] = var(45); // [ var(125) , var(52) ] D[55,125] = var(49); // [ var(125) , var(55) ] D[57,125] = var(51); // [ var(125) , var(57) ] D[59,125] = var(53); // [ var(125) , var(59) ] D[62,125] = var(56); // [ var(125) , var(62) ] D[64,125] = var(58); // [ var(125) , var(64) ] D[67,125] = var(60); // [ var(125) , var(67) ] D[72,125] = var(65); // [ var(125) , var(72) ] D[82,125] = var(76); // [ var(125) , var(82) ] D[85,125] = var(80); // [ var(125) , var(85) ] D[87,125] = var(83); // [ var(125) , var(87) ] D[90,125] = var(86); // [ var(125) , var(90) ] D[92,125] = var(88); // [ var(125) , var(92) ] D[95,125] = var(91); // [ var(125) , var(95) ] D[106,125] = var(103); // [ var(125) , var(106) ] D[108,125] = var(105); // [ var(125) , var(108) ] D[109,125] = var(107); // [ var(125) , var(109) ] D[117,125] = (-1)*var(116); // [ var(125) , var(117) ] D[6,126] = (-1)*var(246); // [ var(126) , var(6) ] D[13,126] = var(5); // [ var(126) , var(13) ] D[14,126] = (-1)*var(7); // [ var(126) , var(14) ] D[20,126] = var(12); // [ var(126) , var(20) ] D[22,126] = (-1)*var(15); // [ var(126) , var(22) ] D[26,126] = var(18); // [ var(126) , var(26) ] D[27,126] = var(19); // [ var(126) , var(27) ] D[31,126] = var(24); // [ var(126) , var(31) ] D[33,126] = var(25); // [ var(126) , var(33) ] D[38,126] = var(30); // [ var(126) , var(38) ] D[40,126] = var(32); // [ var(126) , var(40) ] D[45,126] = var(37); // [ var(126) , var(45) ] D[51,126] = var(44); // [ var(126) , var(51) ] D[61,126] = var(55); // [ var(126) , var(61) ] D[66,126] = var(59); // [ var(126) , var(66) ] D[68,126] = var(62); // [ var(126) , var(68) ] D[71,126] = var(64); // [ var(126) , var(71) ] D[73,126] = var(67); // [ var(126) , var(73) ] D[76,126] = var(70); // [ var(126) , var(76) ] D[78,126] = var(72); // [ var(126) , var(78) ] D[80,126] = var(75); // [ var(126) , var(80) ] D[83,126] = var(77); // [ var(126) , var(83) ] D[86,126] = var(81); // [ var(126) , var(86) ] D[96,126] = var(92); // [ var(126) , var(96) ] D[100,126] = var(95); // [ var(126) , var(100) ] D[103,126] = var(99); // [ var(126) , var(103) ] D[105,126] = var(102); // [ var(126) , var(105) ] D[107,126] = var(104); // [ var(126) , var(107) ] D[118,126] = (-1)*var(117); // [ var(126) , var(118) ] D[7,127] = (-1)*var(247); // [ var(127) , var(7) ] D[14,127] = var(6); // [ var(127) , var(14) ] D[15,127] = (-1)*var(8); // [ var(127) , var(15) ] D[21,127] = var(13); // [ var(127) , var(21) ] D[28,127] = var(20); // [ var(127) , var(28) ] D[34,127] = var(26); // [ var(127) , var(34) ] D[35,127] = var(27); // [ var(127) , var(35) ] D[39,127] = var(31); // [ var(127) , var(39) ] D[41,127] = var(33); // [ var(127) , var(41) ] D[46,127] = var(38); // [ var(127) , var(46) ] D[49,127] = var(40); // [ var(127) , var(49) ] D[53,127] = var(45); // [ var(127) , var(53) ] D[55,127] = var(48); // [ var(127) , var(55) ] D[58,127] = var(51); // [ var(127) , var(58) ] D[59,127] = var(52); // [ var(127) , var(59) ] D[64,127] = var(57); // [ var(127) , var(64) ] D[70,127] = var(63); // [ var(127) , var(70) ] D[74,127] = var(68); // [ var(127) , var(74) ] D[75,127] = var(69); // [ var(127) , var(75) ] D[79,127] = var(73); // [ var(127) , var(79) ] D[84,127] = var(78); // [ var(127) , var(84) ] D[88,127] = var(83); // [ var(127) , var(88) ] D[91,127] = var(86); // [ var(127) , var(91) ] D[92,127] = var(87); // [ var(127) , var(92) ] D[95,127] = var(90); // [ var(127) , var(95) ] D[99,127] = var(94); // [ var(127) , var(99) ] D[102,127] = var(98); // [ var(127) , var(102) ] D[104,127] = var(101); // [ var(127) , var(104) ] D[119,127] = (-1)*var(118); // [ var(127) , var(119) ] D[8,128] = (-1)*var(248); // [ var(128) , var(8) ] D[15,128] = var(7); // [ var(128) , var(15) ] D[22,128] = var(14); // [ var(128) , var(22) ] D[29,128] = var(21); // [ var(128) , var(29) ] D[36,128] = var(28); // [ var(128) , var(36) ] D[42,128] = var(34); // [ var(128) , var(42) ] D[43,128] = var(35); // [ var(128) , var(43) ] D[47,128] = var(39); // [ var(128) , var(47) ] D[50,128] = var(41); // [ var(128) , var(50) ] D[54,128] = var(46); // [ var(128) , var(54) ] D[56,128] = var(49); // [ var(128) , var(56) ] D[60,128] = var(53); // [ var(128) , var(60) ] D[62,128] = var(55); // [ var(128) , var(62) ] D[65,128] = var(58); // [ var(128) , var(65) ] D[67,128] = var(59); // [ var(128) , var(67) ] D[68,128] = var(61); // [ var(128) , var(68) ] D[72,128] = var(64); // [ var(128) , var(72) ] D[73,128] = var(66); // [ var(128) , var(73) ] D[77,128] = var(70); // [ var(128) , var(77) ] D[78,128] = var(71); // [ var(128) , var(78) ] D[81,128] = var(75); // [ var(128) , var(81) ] D[83,128] = var(76); // [ var(128) , var(83) ] D[86,128] = var(80); // [ var(128) , var(86) ] D[87,128] = var(82); // [ var(128) , var(87) ] D[90,128] = var(85); // [ var(128) , var(90) ] D[94,128] = var(89); // [ var(128) , var(94) ] D[98,128] = var(93); // [ var(128) , var(98) ] D[101,128] = var(97); // [ var(128) , var(101) ] D[120,128] = (-1)*var(119); // [ var(128) , var(120) ] D[1,129] = (-1)*var(123); // [ var(129) , var(1) ] D[3,129] = var(121); // [ var(129) , var(3) ] D[9,129] = (-1)*var(241)+(-1)*var(243); // [ var(129) , var(9) ] D[16,129] = (-1)*var(4); // [ var(129) , var(16) ] D[23,129] = (-1)*var(10); // [ var(129) , var(23) ] D[24,129] = (-1)*var(12); // [ var(129) , var(24) ] D[30,129] = (-1)*var(18); // [ var(129) , var(30) ] D[31,129] = (-1)*var(20); // [ var(129) , var(31) ] D[38,129] = (-1)*var(26); // [ var(129) , var(38) ] D[39,129] = (-1)*var(28); // [ var(129) , var(39) ] D[44,129] = var(32); // [ var(129) , var(44) ] D[46,129] = (-1)*var(34); // [ var(129) , var(46) ] D[47,129] = (-1)*var(36); // [ var(129) , var(47) ] D[51,129] = var(40); // [ var(129) , var(51) ] D[54,129] = (-1)*var(42); // [ var(129) , var(54) ] D[57,129] = var(48); // [ var(129) , var(57) ] D[58,129] = var(49); // [ var(129) , var(58) ] D[64,129] = var(55); // [ var(129) , var(64) ] D[65,129] = var(56); // [ var(129) , var(65) ] D[71,129] = var(61); // [ var(129) , var(71) ] D[72,129] = var(62); // [ var(129) , var(72) ] D[78,129] = var(68); // [ var(129) , var(78) ] D[84,129] = var(74); // [ var(129) , var(84) ] D[97,129] = (-1)*var(89); // [ var(129) , var(97) ] D[101,129] = (-1)*var(94); // [ var(129) , var(101) ] D[104,129] = (-1)*var(99); // [ var(129) , var(104) ] D[107,129] = (-1)*var(103); // [ var(129) , var(107) ] D[109,129] = (-1)*var(106); // [ var(129) , var(109) ] D[114,129] = var(110); // [ var(129) , var(114) ] D[115,129] = var(112); // [ var(129) , var(115) ] D[2,130] = (-1)*var(124); // [ var(130) , var(2) ] D[4,130] = var(122); // [ var(130) , var(4) ] D[10,130] = (-1)*var(242)+(-1)*var(244); // [ var(130) , var(10) ] D[17,130] = var(3); // [ var(130) , var(17) ] D[18,130] = (-1)*var(5); // [ var(130) , var(18) ] D[23,130] = var(9); // [ var(130) , var(23) ] D[26,130] = (-1)*var(13); // [ var(130) , var(26) ] D[32,130] = (-1)*var(19); // [ var(130) , var(32) ] D[34,130] = (-1)*var(21); // [ var(130) , var(34) ] D[37,130] = (-1)*var(24); // [ var(130) , var(37) ] D[40,130] = (-1)*var(27); // [ var(130) , var(40) ] D[42,130] = (-1)*var(29); // [ var(130) , var(42) ] D[45,130] = (-1)*var(31); // [ var(130) , var(45) ] D[49,130] = (-1)*var(35); // [ var(130) , var(49) ] D[53,130] = (-1)*var(39); // [ var(130) , var(53) ] D[56,130] = (-1)*var(43); // [ var(130) , var(56) ] D[60,130] = (-1)*var(47); // [ var(130) , var(60) ] D[69,130] = (-1)*var(57); // [ var(130) , var(69) ] D[75,130] = (-1)*var(64); // [ var(130) , var(75) ] D[80,130] = (-1)*var(71); // [ var(130) , var(80) ] D[81,130] = (-1)*var(72); // [ var(130) , var(81) ] D[86,130] = (-1)*var(78); // [ var(130) , var(86) ] D[89,130] = var(82); // [ var(130) , var(89) ] D[91,130] = (-1)*var(84); // [ var(130) , var(91) ] D[94,130] = var(87); // [ var(130) , var(94) ] D[99,130] = var(92); // [ var(130) , var(99) ] D[103,130] = var(96); // [ var(130) , var(103) ] D[112,130] = var(108); // [ var(130) , var(112) ] D[113,130] = var(109); // [ var(130) , var(113) ] D[116,130] = var(114); // [ var(130) , var(116) ] D[3,131] = (-1)*var(124); // [ var(131) , var(3) ] D[4,131] = var(123); // [ var(131) , var(4) ] D[11,131] = (-1)*var(243)+(-1)*var(244); // [ var(131) , var(11) ] D[16,131] = var(1); // [ var(131) , var(16) ] D[17,131] = var(2); // [ var(131) , var(17) ] D[19,131] = (-1)*var(5); // [ var(131) , var(19) ] D[27,131] = (-1)*var(13); // [ var(131) , var(27) ] D[32,131] = (-1)*var(18); // [ var(131) , var(32) ] D[35,131] = (-1)*var(21); // [ var(131) , var(35) ] D[40,131] = (-1)*var(26); // [ var(131) , var(40) ] D[43,131] = (-1)*var(29); // [ var(131) , var(43) ] D[44,131] = var(30); // [ var(131) , var(44) ] D[49,131] = (-1)*var(34); // [ var(131) , var(49) ] D[51,131] = var(38); // [ var(131) , var(51) ] D[56,131] = (-1)*var(42); // [ var(131) , var(56) ] D[58,131] = var(46); // [ var(131) , var(58) ] D[63,131] = (-1)*var(52); // [ var(131) , var(63) ] D[65,131] = var(54); // [ var(131) , var(65) ] D[70,131] = (-1)*var(59); // [ var(131) , var(70) ] D[76,131] = (-1)*var(66); // [ var(131) , var(76) ] D[77,131] = (-1)*var(67); // [ var(131) , var(77) ] D[83,131] = (-1)*var(73); // [ var(131) , var(83) ] D[88,131] = (-1)*var(79); // [ var(131) , var(88) ] D[93,131] = (-1)*var(85); // [ var(131) , var(93) ] D[98,131] = (-1)*var(90); // [ var(131) , var(98) ] D[102,131] = (-1)*var(95); // [ var(131) , var(102) ] D[105,131] = (-1)*var(100); // [ var(131) , var(105) ] D[110,131] = var(106); // [ var(131) , var(110) ] D[114,131] = (-1)*var(109); // [ var(131) , var(114) ] D[116,131] = (-1)*var(113); // [ var(131) , var(116) ] D[4,132] = (-1)*var(125); // [ var(132) , var(4) ] D[5,132] = var(124); // [ var(132) , var(5) ] D[12,132] = (-1)*var(244)+(-1)*var(245); // [ var(132) , var(12) ] D[18,132] = var(2); // [ var(132) , var(18) ] D[19,132] = var(3); // [ var(132) , var(19) ] D[20,132] = (-1)*var(6); // [ var(132) , var(20) ] D[24,132] = var(9); // [ var(132) , var(24) ] D[28,132] = (-1)*var(14); // [ var(132) , var(28) ] D[32,132] = (-1)*var(17); // [ var(132) , var(32) ] D[36,132] = (-1)*var(22); // [ var(132) , var(36) ] D[37,132] = (-1)*var(23); // [ var(132) , var(37) ] D[48,132] = var(33); // [ var(132) , var(48) ] D[52,132] = var(38); // [ var(132) , var(52) ] D[55,132] = var(41); // [ var(132) , var(55) ] D[59,132] = var(46); // [ var(132) , var(59) ] D[62,132] = var(50); // [ var(132) , var(62) ] D[63,132] = (-1)*var(51); // [ var(132) , var(63) ] D[67,132] = var(54); // [ var(132) , var(67) ] D[70,132] = (-1)*var(58); // [ var(132) , var(70) ] D[77,132] = (-1)*var(65); // [ var(132) , var(77) ] D[82,132] = var(71); // [ var(132) , var(82) ] D[87,132] = var(78); // [ var(132) , var(87) ] D[89,132] = (-1)*var(80); // [ var(132) , var(89) ] D[92,132] = var(84); // [ var(132) , var(92) ] D[94,132] = (-1)*var(86); // [ var(132) , var(94) ] D[99,132] = (-1)*var(91); // [ var(132) , var(99) ] D[106,132] = var(100); // [ var(132) , var(106) ] D[110,132] = (-1)*var(105); // [ var(132) , var(110) ] D[111,132] = (-1)*var(107); // [ var(132) , var(111) ] D[117,132] = var(115); // [ var(132) , var(117) ] D[5,133] = (-1)*var(126); // [ var(133) , var(5) ] D[6,133] = var(125); // [ var(133) , var(6) ] D[13,133] = (-1)*var(245)+(-1)*var(246); // [ var(133) , var(13) ] D[20,133] = var(4); // [ var(133) , var(20) ] D[21,133] = (-1)*var(7); // [ var(133) , var(21) ] D[26,133] = var(10); // [ var(133) , var(26) ] D[27,133] = var(11); // [ var(133) , var(27) ] D[29,133] = (-1)*var(15); // [ var(133) , var(29) ] D[31,133] = var(16); // [ var(133) , var(31) ] D[33,133] = var(17); // [ var(133) , var(33) ] D[38,133] = var(23); // [ var(133) , var(38) ] D[48,133] = (-1)*var(32); // [ var(133) , var(48) ] D[52,133] = (-1)*var(37); // [ var(133) , var(52) ] D[57,133] = (-1)*var(44); // [ var(133) , var(57) ] D[61,133] = var(49); // [ var(133) , var(61) ] D[66,133] = var(53); // [ var(133) , var(66) ] D[68,133] = var(56); // [ var(133) , var(68) ] D[71,133] = var(58); // [ var(133) , var(71) ] D[73,133] = var(60); // [ var(133) , var(73) ] D[78,133] = var(65); // [ var(133) , var(78) ] D[82,133] = (-1)*var(70); // [ var(133) , var(82) ] D[85,133] = (-1)*var(75); // [ var(133) , var(85) ] D[87,133] = (-1)*var(77); // [ var(133) , var(87) ] D[90,133] = (-1)*var(81); // [ var(133) , var(90) ] D[96,133] = var(88); // [ var(133) , var(96) ] D[100,133] = var(91); // [ var(133) , var(100) ] D[106,133] = (-1)*var(99); // [ var(133) , var(106) ] D[108,133] = (-1)*var(102); // [ var(133) , var(108) ] D[109,133] = (-1)*var(104); // [ var(133) , var(109) ] D[118,133] = var(116); // [ var(133) , var(118) ] D[6,134] = (-1)*var(127); // [ var(134) , var(6) ] D[7,134] = var(126); // [ var(134) , var(7) ] D[14,134] = (-1)*var(246)+(-1)*var(247); // [ var(134) , var(14) ] D[21,134] = var(5); // [ var(134) , var(21) ] D[22,134] = (-1)*var(8); // [ var(134) , var(22) ] D[28,134] = var(12); // [ var(134) , var(28) ] D[34,134] = var(18); // [ var(134) , var(34) ] D[35,134] = var(19); // [ var(134) , var(35) ] D[39,134] = var(24); // [ var(134) , var(39) ] D[41,134] = var(25); // [ var(134) , var(41) ] D[46,134] = var(30); // [ var(134) , var(46) ] D[49,134] = var(32); // [ var(134) , var(49) ] D[53,134] = var(37); // [ var(134) , var(53) ] D[58,134] = var(44); // [ var(134) , var(58) ] D[61,134] = (-1)*var(48); // [ var(134) , var(61) ] D[66,134] = (-1)*var(52); // [ var(134) , var(66) ] D[71,134] = (-1)*var(57); // [ var(134) , var(71) ] D[74,134] = var(62); // [ var(134) , var(74) ] D[76,134] = (-1)*var(63); // [ var(134) , var(76) ] D[79,134] = var(67); // [ var(134) , var(79) ] D[80,134] = (-1)*var(69); // [ var(134) , var(80) ] D[84,134] = var(72); // [ var(134) , var(84) ] D[88,134] = var(77); // [ var(134) , var(88) ] D[91,134] = var(81); // [ var(134) , var(91) ] D[96,134] = (-1)*var(87); // [ var(134) , var(96) ] D[100,134] = (-1)*var(90); // [ var(134) , var(100) ] D[103,134] = (-1)*var(94); // [ var(134) , var(103) ] D[105,134] = (-1)*var(98); // [ var(134) , var(105) ] D[107,134] = (-1)*var(101); // [ var(134) , var(107) ] D[119,134] = var(117); // [ var(134) , var(119) ] D[7,135] = (-1)*var(128); // [ var(135) , var(7) ] D[8,135] = var(127); // [ var(135) , var(8) ] D[15,135] = (-1)*var(247)+(-1)*var(248); // [ var(135) , var(15) ] D[22,135] = var(6); // [ var(135) , var(22) ] D[29,135] = var(13); // [ var(135) , var(29) ] D[36,135] = var(20); // [ var(135) , var(36) ] D[42,135] = var(26); // [ var(135) , var(42) ] D[43,135] = var(27); // [ var(135) , var(43) ] D[47,135] = var(31); // [ var(135) , var(47) ] D[50,135] = var(33); // [ var(135) , var(50) ] D[54,135] = var(38); // [ var(135) , var(54) ] D[56,135] = var(40); // [ var(135) , var(56) ] D[60,135] = var(45); // [ var(135) , var(60) ] D[62,135] = var(48); // [ var(135) , var(62) ] D[65,135] = var(51); // [ var(135) , var(65) ] D[67,135] = var(52); // [ var(135) , var(67) ] D[72,135] = var(57); // [ var(135) , var(72) ] D[74,135] = (-1)*var(61); // [ var(135) , var(74) ] D[77,135] = var(63); // [ var(135) , var(77) ] D[79,135] = (-1)*var(66); // [ var(135) , var(79) ] D[81,135] = var(69); // [ var(135) , var(81) ] D[84,135] = (-1)*var(71); // [ var(135) , var(84) ] D[88,135] = (-1)*var(76); // [ var(135) , var(88) ] D[91,135] = (-1)*var(80); // [ var(135) , var(91) ] D[92,135] = (-1)*var(82); // [ var(135) , var(92) ] D[95,135] = (-1)*var(85); // [ var(135) , var(95) ] D[99,135] = (-1)*var(89); // [ var(135) , var(99) ] D[102,135] = (-1)*var(93); // [ var(135) , var(102) ] D[104,135] = (-1)*var(97); // [ var(135) , var(104) ] D[120,135] = var(118); // [ var(135) , var(120) ] D[1,136] = (-1)*var(131); // [ var(136) , var(1) ] D[4,136] = var(129); // [ var(136) , var(4) ] D[9,136] = (-1)*var(124); // [ var(136) , var(9) ] D[11,136] = var(121); // [ var(136) , var(11) ] D[16,136] = (-1)*var(241)+(-1)*var(243)+(-1)*var(244); // [ var(136) , var(16) ] D[23,136] = var(2); // [ var(136) , var(23) ] D[24,136] = (-1)*var(5); // [ var(136) , var(24) ] D[31,136] = (-1)*var(13); // [ var(136) , var(31) ] D[37,136] = (-1)*var(18); // [ var(136) , var(37) ] D[39,136] = (-1)*var(21); // [ var(136) , var(39) ] D[44,136] = (-1)*var(25); // [ var(136) , var(44) ] D[45,136] = (-1)*var(26); // [ var(136) , var(45) ] D[47,136] = (-1)*var(29); // [ var(136) , var(47) ] D[51,136] = (-1)*var(33); // [ var(136) , var(51) ] D[53,136] = (-1)*var(34); // [ var(136) , var(53) ] D[58,136] = (-1)*var(41); // [ var(136) , var(58) ] D[60,136] = (-1)*var(42); // [ var(136) , var(60) ] D[63,136] = var(48); // [ var(136) , var(63) ] D[65,136] = (-1)*var(50); // [ var(136) , var(65) ] D[70,136] = var(55); // [ var(136) , var(70) ] D[76,136] = var(61); // [ var(136) , var(76) ] D[77,136] = var(62); // [ var(136) , var(77) ] D[83,136] = var(68); // [ var(136) , var(83) ] D[88,136] = var(74); // [ var(136) , var(88) ] D[97,136] = var(85); // [ var(136) , var(97) ] D[101,136] = var(90); // [ var(136) , var(101) ] D[104,136] = var(95); // [ var(136) , var(104) ] D[107,136] = var(100); // [ var(136) , var(107) ] D[111,136] = (-1)*var(106); // [ var(136) , var(111) ] D[114,136] = (-1)*var(108); // [ var(136) , var(114) ] D[116,136] = (-1)*var(112); // [ var(136) , var(116) ] D[2,137] = (-1)*var(131); // [ var(137) , var(2) ] D[3,137] = (-1)*var(130); // [ var(137) , var(3) ] D[10,137] = var(123); // [ var(137) , var(10) ] D[11,137] = var(122); // [ var(137) , var(11) ] D[17,137] = (-1)*var(242)+(-1)*var(243)+(-1)*var(244); // [ var(137) , var(17) ] D[23,137] = var(1); // [ var(137) , var(23) ] D[25,137] = (-1)*var(5); // [ var(137) , var(25) ] D[32,137] = var(12); // [ var(137) , var(32) ] D[33,137] = (-1)*var(13); // [ var(137) , var(33) ] D[40,137] = var(20); // [ var(137) , var(40) ] D[41,137] = (-1)*var(21); // [ var(137) , var(41) ] D[44,137] = (-1)*var(24); // [ var(137) , var(44) ] D[49,137] = var(28); // [ var(137) , var(49) ] D[50,137] = (-1)*var(29); // [ var(137) , var(50) ] D[51,137] = (-1)*var(31); // [ var(137) , var(51) ] D[56,137] = var(36); // [ var(137) , var(56) ] D[58,137] = (-1)*var(39); // [ var(137) , var(58) ] D[65,137] = (-1)*var(47); // [ var(137) , var(65) ] D[69,137] = var(52); // [ var(137) , var(69) ] D[75,137] = var(59); // [ var(137) , var(75) ] D[80,137] = var(66); // [ var(137) , var(80) ] D[81,137] = var(67); // [ var(137) , var(81) ] D[86,137] = var(73); // [ var(137) , var(86) ] D[91,137] = var(79); // [ var(137) , var(91) ] D[93,137] = (-1)*var(82); // [ var(137) , var(93) ] D[98,137] = (-1)*var(87); // [ var(137) , var(98) ] D[102,137] = (-1)*var(92); // [ var(137) , var(102) ] D[105,137] = (-1)*var(96); // [ var(137) , var(105) ] D[112,137] = var(106); // [ var(137) , var(112) ] D[115,137] = (-1)*var(109); // [ var(137) , var(115) ] D[116,137] = var(111); // [ var(137) , var(116) ] D[2,138] = (-1)*var(132); // [ var(138) , var(2) ] D[5,138] = var(130); // [ var(138) , var(5) ] D[10,138] = (-1)*var(125); // [ var(138) , var(10) ] D[12,138] = var(122); // [ var(138) , var(12) ] D[18,138] = (-1)*var(242)+(-1)*var(244)+(-1)*var(245); // [ var(138) , var(18) ] D[25,138] = var(3); // [ var(138) , var(25) ] D[26,138] = (-1)*var(6); // [ var(138) , var(26) ] D[30,138] = var(9); // [ var(138) , var(30) ] D[32,138] = var(11); // [ var(138) , var(32) ] D[34,138] = (-1)*var(14); // [ var(138) , var(34) ] D[37,138] = var(16); // [ var(138) , var(37) ] D[42,138] = (-1)*var(22); // [ var(138) , var(42) ] D[48,138] = (-1)*var(27); // [ var(138) , var(48) ] D[52,138] = (-1)*var(31); // [ var(138) , var(52) ] D[55,138] = (-1)*var(35); // [ var(138) , var(55) ] D[59,138] = (-1)*var(39); // [ var(138) , var(59) ] D[62,138] = (-1)*var(43); // [ var(138) , var(62) ] D[67,138] = (-1)*var(47); // [ var(138) , var(67) ] D[69,138] = var(51); // [ var(138) , var(69) ] D[75,138] = var(58); // [ var(138) , var(75) ] D[81,138] = var(65); // [ var(138) , var(81) ] D[85,138] = (-1)*var(71); // [ var(138) , var(85) ] D[89,138] = (-1)*var(76); // [ var(138) , var(89) ] D[90,138] = (-1)*var(78); // [ var(138) , var(90) ] D[94,138] = (-1)*var(83); // [ var(138) , var(94) ] D[95,138] = (-1)*var(84); // [ var(138) , var(95) ] D[99,138] = (-1)*var(88); // [ var(138) , var(99) ] D[106,138] = var(96); // [ var(138) , var(106) ] D[112,138] = (-1)*var(105); // [ var(138) , var(112) ] D[113,138] = (-1)*var(107); // [ var(138) , var(113) ] D[117,138] = (-1)*var(114); // [ var(138) , var(117) ] D[3,139] = (-1)*var(132); // [ var(139) , var(3) ] D[5,139] = var(131); // [ var(139) , var(5) ] D[11,139] = (-1)*var(125); // [ var(139) , var(11) ] D[12,139] = var(123); // [ var(139) , var(12) ] D[19,139] = (-1)*var(243)+(-1)*var(244)+(-1)*var(245); // [ var(139) , var(19) ] D[24,139] = var(1); // [ var(139) , var(24) ] D[25,139] = var(2); // [ var(139) , var(25) ] D[27,139] = (-1)*var(6); // [ var(139) , var(27) ] D[32,139] = var(10); // [ var(139) , var(32) ] D[35,139] = (-1)*var(14); // [ var(139) , var(35) ] D[43,139] = (-1)*var(22); // [ var(139) , var(43) ] D[44,139] = (-1)*var(23); // [ var(139) , var(44) ] D[48,139] = (-1)*var(26); // [ var(139) , var(48) ] D[55,139] = (-1)*var(34); // [ var(139) , var(55) ] D[57,139] = var(38); // [ var(139) , var(57) ] D[62,139] = (-1)*var(42); // [ var(139) , var(62) ] D[63,139] = var(45); // [ var(139) , var(63) ] D[64,139] = var(46); // [ var(139) , var(64) ] D[70,139] = var(53); // [ var(139) , var(70) ] D[72,139] = var(54); // [ var(139) , var(72) ] D[77,139] = var(60); // [ var(139) , var(77) ] D[82,139] = (-1)*var(66); // [ var(139) , var(82) ] D[87,139] = (-1)*var(73); // [ var(139) , var(87) ] D[92,139] = (-1)*var(79); // [ var(139) , var(92) ] D[93,139] = var(80); // [ var(139) , var(93) ] D[98,139] = var(86); // [ var(139) , var(98) ] D[102,139] = var(91); // [ var(139) , var(102) ] D[108,139] = (-1)*var(100); // [ var(139) , var(108) ] D[110,139] = (-1)*var(103); // [ var(139) , var(110) ] D[114,139] = var(107); // [ var(139) , var(114) ] D[117,139] = var(113); // [ var(139) , var(117) ] D[4,140] = (-1)*var(133); // [ var(140) , var(4) ] D[6,140] = var(132); // [ var(140) , var(6) ] D[12,140] = (-1)*var(126); // [ var(140) , var(12) ] D[13,140] = var(124); // [ var(140) , var(13) ] D[20,140] = (-1)*var(244)+(-1)*var(245)+(-1)*var(246); // [ var(140) , var(20) ] D[26,140] = var(2); // [ var(140) , var(26) ] D[27,140] = var(3); // [ var(140) , var(27) ] D[28,140] = (-1)*var(7); // [ var(140) , var(28) ] D[31,140] = var(9); // [ var(140) , var(31) ] D[36,140] = (-1)*var(15); // [ var(140) , var(36) ] D[40,140] = (-1)*var(17); // [ var(140) , var(40) ] D[45,140] = (-1)*var(23); // [ var(140) , var(45) ] D[48,140] = (-1)*var(25); // [ var(140) , var(48) ] D[52,140] = (-1)*var(30); // [ var(140) , var(52) ] D[61,140] = var(41); // [ var(140) , var(61) ] D[63,140] = var(44); // [ var(140) , var(63) ] D[66,140] = var(46); // [ var(140) , var(66) ] D[68,140] = var(50); // [ var(140) , var(68) ] D[73,140] = var(54); // [ var(140) , var(73) ] D[76,140] = (-1)*var(58); // [ var(140) , var(76) ] D[82,140] = (-1)*var(64); // [ var(140) , var(82) ] D[83,140] = (-1)*var(65); // [ var(140) , var(83) ] D[87,140] = (-1)*var(72); // [ var(140) , var(87) ] D[89,140] = var(75); // [ var(140) , var(89) ] D[94,140] = var(81); // [ var(140) , var(94) ] D[96,140] = var(84); // [ var(140) , var(96) ] D[103,140] = (-1)*var(91); // [ var(140) , var(103) ] D[106,140] = (-1)*var(95); // [ var(140) , var(106) ] D[110,140] = var(102); // [ var(140) , var(110) ] D[111,140] = var(104); // [ var(140) , var(111) ] D[118,140] = (-1)*var(115); // [ var(140) , var(118) ] D[5,141] = (-1)*var(134); // [ var(141) , var(5) ] D[7,141] = var(133); // [ var(141) , var(7) ] D[13,141] = (-1)*var(127); // [ var(141) , var(13) ] D[14,141] = var(125); // [ var(141) , var(14) ] D[21,141] = (-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(141) , var(21) ] D[28,141] = var(4); // [ var(141) , var(28) ] D[29,141] = (-1)*var(8); // [ var(141) , var(29) ] D[34,141] = var(10); // [ var(141) , var(34) ] D[35,141] = var(11); // [ var(141) , var(35) ] D[39,141] = var(16); // [ var(141) , var(39) ] D[41,141] = var(17); // [ var(141) , var(41) ] D[46,141] = var(23); // [ var(141) , var(46) ] D[55,141] = (-1)*var(32); // [ var(141) , var(55) ] D[59,141] = (-1)*var(37); // [ var(141) , var(59) ] D[61,141] = (-1)*var(40); // [ var(141) , var(61) ] D[64,141] = (-1)*var(44); // [ var(141) , var(64) ] D[66,141] = (-1)*var(45); // [ var(141) , var(66) ] D[71,141] = (-1)*var(51); // [ var(141) , var(71) ] D[74,141] = var(56); // [ var(141) , var(74) ] D[79,141] = var(60); // [ var(141) , var(79) ] D[82,141] = var(63); // [ var(141) , var(82) ] D[84,141] = var(65); // [ var(141) , var(84) ] D[85,141] = var(69); // [ var(141) , var(85) ] D[92,141] = (-1)*var(77); // [ var(141) , var(92) ] D[95,141] = (-1)*var(81); // [ var(141) , var(95) ] D[96,141] = (-1)*var(83); // [ var(141) , var(96) ] D[100,141] = (-1)*var(86); // [ var(141) , var(100) ] D[106,141] = var(94); // [ var(141) , var(106) ] D[108,141] = var(98); // [ var(141) , var(108) ] D[109,141] = var(101); // [ var(141) , var(109) ] D[119,141] = (-1)*var(116); // [ var(141) , var(119) ] D[6,142] = (-1)*var(135); // [ var(142) , var(6) ] D[8,142] = var(134); // [ var(142) , var(8) ] D[14,142] = (-1)*var(128); // [ var(142) , var(14) ] D[15,142] = var(126); // [ var(142) , var(15) ] D[22,142] = (-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(142) , var(22) ] D[29,142] = var(5); // [ var(142) , var(29) ] D[36,142] = var(12); // [ var(142) , var(36) ] D[42,142] = var(18); // [ var(142) , var(42) ] D[43,142] = var(19); // [ var(142) , var(43) ] D[47,142] = var(24); // [ var(142) , var(47) ] D[50,142] = var(25); // [ var(142) , var(50) ] D[54,142] = var(30); // [ var(142) , var(54) ] D[56,142] = var(32); // [ var(142) , var(56) ] D[60,142] = var(37); // [ var(142) , var(60) ] D[65,142] = var(44); // [ var(142) , var(65) ] D[68,142] = (-1)*var(48); // [ var(142) , var(68) ] D[73,142] = (-1)*var(52); // [ var(142) , var(73) ] D[74,142] = (-1)*var(55); // [ var(142) , var(74) ] D[78,142] = (-1)*var(57); // [ var(142) , var(78) ] D[79,142] = (-1)*var(59); // [ var(142) , var(79) ] D[83,142] = (-1)*var(63); // [ var(142) , var(83) ] D[84,142] = (-1)*var(64); // [ var(142) , var(84) ] D[86,142] = (-1)*var(69); // [ var(142) , var(86) ] D[88,142] = (-1)*var(70); // [ var(142) , var(88) ] D[91,142] = (-1)*var(75); // [ var(142) , var(91) ] D[96,142] = var(82); // [ var(142) , var(96) ] D[100,142] = var(85); // [ var(142) , var(100) ] D[103,142] = var(89); // [ var(142) , var(103) ] D[105,142] = var(93); // [ var(142) , var(105) ] D[107,142] = var(97); // [ var(142) , var(107) ] D[120,142] = (-1)*var(117); // [ var(142) , var(120) ] D[1,143] = (-1)*var(137); // [ var(143) , var(1) ] D[2,143] = (-1)*var(136); // [ var(143) , var(2) ] D[9,143] = (-1)*var(130); // [ var(143) , var(9) ] D[10,143] = var(129); // [ var(143) , var(10) ] D[16,143] = var(122); // [ var(143) , var(16) ] D[17,143] = var(121); // [ var(143) , var(17) ] D[23,143] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-1)*var(244); // [ var(143) , var(23) ] D[30,143] = (-1)*var(5); // [ var(143) , var(30) ] D[37,143] = var(12); // [ var(143) , var(37) ] D[38,143] = (-1)*var(13); // [ var(143) , var(38) ] D[44,143] = var(19); // [ var(143) , var(44) ] D[45,143] = var(20); // [ var(143) , var(45) ] D[46,143] = (-1)*var(21); // [ var(143) , var(46) ] D[51,143] = var(27); // [ var(143) , var(51) ] D[53,143] = var(28); // [ var(143) , var(53) ] D[54,143] = (-1)*var(29); // [ var(143) , var(54) ] D[58,143] = var(35); // [ var(143) , var(58) ] D[60,143] = var(36); // [ var(143) , var(60) ] D[65,143] = var(43); // [ var(143) , var(65) ] D[69,143] = (-1)*var(48); // [ var(143) , var(69) ] D[75,143] = (-1)*var(55); // [ var(143) , var(75) ] D[80,143] = (-1)*var(61); // [ var(143) , var(80) ] D[81,143] = (-1)*var(62); // [ var(143) , var(81) ] D[86,143] = (-1)*var(68); // [ var(143) , var(86) ] D[91,143] = (-1)*var(74); // [ var(143) , var(91) ] D[97,143] = var(82); // [ var(143) , var(97) ] D[101,143] = var(87); // [ var(143) , var(101) ] D[104,143] = var(92); // [ var(143) , var(104) ] D[107,143] = var(96); // [ var(143) , var(107) ] D[113,143] = (-1)*var(106); // [ var(143) , var(113) ] D[115,143] = (-1)*var(108); // [ var(143) , var(115) ] D[116,143] = var(110); // [ var(143) , var(116) ] D[1,144] = (-1)*var(139); // [ var(144) , var(1) ] D[5,144] = var(136); // [ var(144) , var(5) ] D[9,144] = (-1)*var(132); // [ var(144) , var(9) ] D[12,144] = var(129); // [ var(144) , var(12) ] D[16,144] = (-1)*var(125); // [ var(144) , var(16) ] D[19,144] = var(121); // [ var(144) , var(19) ] D[24,144] = (-1)*var(241)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245); // [ var(144) , var(24) ] D[30,144] = var(2); // [ var(144) , var(30) ] D[31,144] = (-1)*var(6); // [ var(144) , var(31) ] D[37,144] = var(10); // [ var(144) , var(37) ] D[39,144] = (-1)*var(14); // [ var(144) , var(39) ] D[44,144] = var(17); // [ var(144) , var(44) ] D[47,144] = (-1)*var(22); // [ var(144) , var(47) ] D[52,144] = (-1)*var(26); // [ var(144) , var(52) ] D[57,144] = (-1)*var(33); // [ var(144) , var(57) ] D[59,144] = (-1)*var(34); // [ var(144) , var(59) ] D[63,144] = (-1)*var(40); // [ var(144) , var(63) ] D[64,144] = (-1)*var(41); // [ var(144) , var(64) ] D[67,144] = (-1)*var(42); // [ var(144) , var(67) ] D[70,144] = (-1)*var(49); // [ var(144) , var(70) ] D[72,144] = (-1)*var(50); // [ var(144) , var(72) ] D[77,144] = (-1)*var(56); // [ var(144) , var(77) ] D[82,144] = var(61); // [ var(144) , var(82) ] D[87,144] = var(68); // [ var(144) , var(87) ] D[92,144] = var(74); // [ var(144) , var(92) ] D[97,144] = (-1)*var(80); // [ var(144) , var(97) ] D[101,144] = (-1)*var(86); // [ var(144) , var(101) ] D[104,144] = (-1)*var(91); // [ var(144) , var(104) ] D[109,144] = var(100); // [ var(144) , var(109) ] D[111,144] = var(103); // [ var(144) , var(111) ] D[114,144] = var(105); // [ var(144) , var(114) ] D[117,144] = var(112); // [ var(144) , var(117) ] D[2,145] = (-1)*var(139); // [ var(145) , var(2) ] D[3,145] = (-1)*var(138); // [ var(145) , var(3) ] D[5,145] = var(137); // [ var(145) , var(5) ] D[17,145] = (-1)*var(125); // [ var(145) , var(17) ] D[18,145] = var(123); // [ var(145) , var(18) ] D[19,145] = var(122); // [ var(145) , var(19) ] D[25,145] = (-1)*var(242)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245); // [ var(145) , var(25) ] D[30,145] = var(1); // [ var(145) , var(30) ] D[32,145] = (-1)*var(4); // [ var(145) , var(32) ] D[33,145] = (-1)*var(6); // [ var(145) , var(33) ] D[41,145] = (-1)*var(14); // [ var(145) , var(41) ] D[44,145] = var(16); // [ var(145) , var(44) ] D[48,145] = var(20); // [ var(145) , var(48) ] D[50,145] = (-1)*var(22); // [ var(145) , var(50) ] D[55,145] = var(28); // [ var(145) , var(55) ] D[57,145] = (-1)*var(31); // [ var(145) , var(57) ] D[62,145] = var(36); // [ var(145) , var(62) ] D[64,145] = (-1)*var(39); // [ var(145) , var(64) ] D[69,145] = (-1)*var(45); // [ var(145) , var(69) ] D[72,145] = (-1)*var(47); // [ var(145) , var(72) ] D[75,145] = (-1)*var(53); // [ var(145) , var(75) ] D[81,145] = (-1)*var(60); // [ var(145) , var(81) ] D[85,145] = var(66); // [ var(145) , var(85) ] D[90,145] = var(73); // [ var(145) , var(90) ] D[93,145] = var(76); // [ var(145) , var(93) ] D[95,145] = var(79); // [ var(145) , var(95) ] D[98,145] = var(83); // [ var(145) , var(98) ] D[102,145] = var(88); // [ var(145) , var(102) ] D[108,145] = (-1)*var(96); // [ var(145) , var(108) ] D[112,145] = (-1)*var(103); // [ var(145) , var(112) ] D[115,145] = var(107); // [ var(145) , var(115) ] D[117,145] = (-1)*var(111); // [ var(145) , var(117) ] D[2,146] = (-1)*var(140); // [ var(146) , var(2) ] D[6,146] = var(138); // [ var(146) , var(6) ] D[10,146] = (-1)*var(133); // [ var(146) , var(10) ] D[13,146] = var(130); // [ var(146) , var(13) ] D[18,146] = (-1)*var(126); // [ var(146) , var(18) ] D[20,146] = var(122); // [ var(146) , var(20) ] D[26,146] = (-1)*var(242)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246); // [ var(146) , var(26) ] D[33,146] = var(3); // [ var(146) , var(33) ] D[34,146] = (-1)*var(7); // [ var(146) , var(34) ] D[38,146] = var(9); // [ var(146) , var(38) ] D[40,146] = var(11); // [ var(146) , var(40) ] D[42,146] = (-1)*var(15); // [ var(146) , var(42) ] D[45,146] = var(16); // [ var(146) , var(45) ] D[48,146] = var(19); // [ var(146) , var(48) ] D[52,146] = var(24); // [ var(146) , var(52) ] D[61,146] = (-1)*var(35); // [ var(146) , var(61) ] D[66,146] = (-1)*var(39); // [ var(146) , var(66) ] D[68,146] = (-1)*var(43); // [ var(146) , var(68) ] D[69,146] = (-1)*var(44); // [ var(146) , var(69) ] D[73,146] = (-1)*var(47); // [ var(146) , var(73) ] D[80,146] = var(58); // [ var(146) , var(80) ] D[85,146] = var(64); // [ var(146) , var(85) ] D[86,146] = var(65); // [ var(146) , var(86) ] D[89,146] = var(70); // [ var(146) , var(89) ] D[90,146] = var(72); // [ var(146) , var(90) ] D[94,146] = var(77); // [ var(146) , var(94) ] D[100,146] = (-1)*var(84); // [ var(146) , var(100) ] D[103,146] = (-1)*var(88); // [ var(146) , var(103) ] D[106,146] = (-1)*var(92); // [ var(146) , var(106) ] D[112,146] = var(102); // [ var(146) , var(112) ] D[113,146] = var(104); // [ var(146) , var(113) ] D[118,146] = var(114); // [ var(146) , var(118) ] D[3,147] = (-1)*var(140); // [ var(147) , var(3) ] D[6,147] = var(139); // [ var(147) , var(6) ] D[11,147] = (-1)*var(133); // [ var(147) , var(11) ] D[13,147] = var(131); // [ var(147) , var(13) ] D[19,147] = (-1)*var(126); // [ var(147) , var(19) ] D[20,147] = var(123); // [ var(147) , var(20) ] D[27,147] = (-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246); // [ var(147) , var(27) ] D[31,147] = var(1); // [ var(147) , var(31) ] D[33,147] = var(2); // [ var(147) , var(33) ] D[35,147] = (-1)*var(7); // [ var(147) , var(35) ] D[40,147] = var(10); // [ var(147) , var(40) ] D[43,147] = (-1)*var(15); // [ var(147) , var(43) ] D[48,147] = var(18); // [ var(147) , var(48) ] D[51,147] = (-1)*var(23); // [ var(147) , var(51) ] D[57,147] = (-1)*var(30); // [ var(147) , var(57) ] D[61,147] = (-1)*var(34); // [ var(147) , var(61) ] D[63,147] = (-1)*var(37); // [ var(147) , var(63) ] D[68,147] = (-1)*var(42); // [ var(147) , var(68) ] D[71,147] = var(46); // [ var(147) , var(71) ] D[76,147] = var(53); // [ var(147) , var(76) ] D[78,147] = var(54); // [ var(147) , var(78) ] D[82,147] = var(59); // [ var(147) , var(82) ] D[83,147] = var(60); // [ var(147) , var(83) ] D[87,147] = var(67); // [ var(147) , var(87) ] D[93,147] = (-1)*var(75); // [ var(147) , var(93) ] D[96,147] = (-1)*var(79); // [ var(147) , var(96) ] D[98,147] = (-1)*var(81); // [ var(147) , var(98) ] D[105,147] = var(91); // [ var(147) , var(105) ] D[108,147] = var(95); // [ var(147) , var(108) ] D[110,147] = var(99); // [ var(147) , var(110) ] D[114,147] = (-1)*var(104); // [ var(147) , var(114) ] D[118,147] = (-1)*var(113); // [ var(147) , var(118) ] D[4,148] = (-1)*var(141); // [ var(148) , var(4) ] D[7,148] = var(140); // [ var(148) , var(7) ] D[12,148] = (-1)*var(134); // [ var(148) , var(12) ] D[14,148] = var(132); // [ var(148) , var(14) ] D[20,148] = (-1)*var(127); // [ var(148) , var(20) ] D[21,148] = var(124); // [ var(148) , var(21) ] D[28,148] = (-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(148) , var(28) ] D[34,148] = var(2); // [ var(148) , var(34) ] D[35,148] = var(3); // [ var(148) , var(35) ] D[36,148] = (-1)*var(8); // [ var(148) , var(36) ] D[39,148] = var(9); // [ var(148) , var(39) ] D[49,148] = (-1)*var(17); // [ var(148) , var(49) ] D[53,148] = (-1)*var(23); // [ var(148) , var(53) ] D[55,148] = (-1)*var(25); // [ var(148) , var(55) ] D[59,148] = (-1)*var(30); // [ var(148) , var(59) ] D[61,148] = (-1)*var(33); // [ var(148) , var(61) ] D[66,148] = (-1)*var(38); // [ var(148) , var(66) ] D[70,148] = var(44); // [ var(148) , var(70) ] D[74,148] = var(50); // [ var(148) , var(74) ] D[76,148] = var(51); // [ var(148) , var(76) ] D[79,148] = var(54); // [ var(148) , var(79) ] D[82,148] = var(57); // [ var(148) , var(82) ] D[88,148] = (-1)*var(65); // [ var(148) , var(88) ] D[89,148] = (-1)*var(69); // [ var(148) , var(89) ] D[92,148] = (-1)*var(72); // [ var(148) , var(92) ] D[96,148] = (-1)*var(78); // [ var(148) , var(96) ] D[99,148] = var(81); // [ var(148) , var(99) ] D[103,148] = var(86); // [ var(148) , var(103) ] D[106,148] = var(90); // [ var(148) , var(106) ] D[110,148] = (-1)*var(98); // [ var(148) , var(110) ] D[111,148] = (-1)*var(101); // [ var(148) , var(111) ] D[119,148] = var(115); // [ var(148) , var(119) ] D[5,149] = (-1)*var(142); // [ var(149) , var(5) ] D[8,149] = var(141); // [ var(149) , var(8) ] D[13,149] = (-1)*var(135); // [ var(149) , var(13) ] D[15,149] = var(133); // [ var(149) , var(15) ] D[21,149] = (-1)*var(128); // [ var(149) , var(21) ] D[22,149] = var(125); // [ var(149) , var(22) ] D[29,149] = (-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(149) , var(29) ] D[36,149] = var(4); // [ var(149) , var(36) ] D[42,149] = var(10); // [ var(149) , var(42) ] D[43,149] = var(11); // [ var(149) , var(43) ] D[47,149] = var(16); // [ var(149) , var(47) ] D[50,149] = var(17); // [ var(149) , var(50) ] D[54,149] = var(23); // [ var(149) , var(54) ] D[62,149] = (-1)*var(32); // [ var(149) , var(62) ] D[67,149] = (-1)*var(37); // [ var(149) , var(67) ] D[68,149] = (-1)*var(40); // [ var(149) , var(68) ] D[72,149] = (-1)*var(44); // [ var(149) , var(72) ] D[73,149] = (-1)*var(45); // [ var(149) , var(73) ] D[74,149] = (-1)*var(49); // [ var(149) , var(74) ] D[78,149] = (-1)*var(51); // [ var(149) , var(78) ] D[79,149] = (-1)*var(53); // [ var(149) , var(79) ] D[84,149] = (-1)*var(58); // [ var(149) , var(84) ] D[87,149] = var(63); // [ var(149) , var(87) ] D[90,149] = var(69); // [ var(149) , var(90) ] D[92,149] = var(70); // [ var(149) , var(92) ] D[95,149] = var(75); // [ var(149) , var(95) ] D[96,149] = var(76); // [ var(149) , var(96) ] D[100,149] = var(80); // [ var(149) , var(100) ] D[106,149] = (-1)*var(89); // [ var(149) , var(106) ] D[108,149] = (-1)*var(93); // [ var(149) , var(108) ] D[109,149] = (-1)*var(97); // [ var(149) , var(109) ] D[120,149] = var(116); // [ var(149) , var(120) ] D[1,150] = (-1)*var(145); // [ var(150) , var(1) ] D[2,150] = (-1)*var(144); // [ var(150) , var(2) ] D[5,150] = var(143); // [ var(150) , var(5) ] D[9,150] = (-1)*var(138); // [ var(150) , var(9) ] D[18,150] = var(129); // [ var(150) , var(18) ] D[23,150] = (-1)*var(125); // [ var(150) , var(23) ] D[24,150] = var(122); // [ var(150) , var(24) ] D[25,150] = var(121); // [ var(150) , var(25) ] D[30,150] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245); // [ var(150) , var(30) ] D[37,150] = (-1)*var(4); // [ var(150) , var(37) ] D[38,150] = (-1)*var(6); // [ var(150) , var(38) ] D[44,150] = (-1)*var(11); // [ var(150) , var(44) ] D[46,150] = (-1)*var(14); // [ var(150) , var(46) ] D[52,150] = var(20); // [ var(150) , var(52) ] D[54,150] = (-1)*var(22); // [ var(150) , var(54) ] D[57,150] = var(27); // [ var(150) , var(57) ] D[59,150] = var(28); // [ var(150) , var(59) ] D[64,150] = var(35); // [ var(150) , var(64) ] D[67,150] = var(36); // [ var(150) , var(67) ] D[69,150] = var(40); // [ var(150) , var(69) ] D[72,150] = var(43); // [ var(150) , var(72) ] D[75,150] = var(49); // [ var(150) , var(75) ] D[81,150] = var(56); // [ var(150) , var(81) ] D[85,150] = (-1)*var(61); // [ var(150) , var(85) ] D[90,150] = (-1)*var(68); // [ var(150) , var(90) ] D[95,150] = (-1)*var(74); // [ var(150) , var(95) ] D[97,150] = (-1)*var(76); // [ var(150) , var(97) ] D[101,150] = (-1)*var(83); // [ var(150) , var(101) ] D[104,150] = (-1)*var(88); // [ var(150) , var(104) ] D[109,150] = var(96); // [ var(150) , var(109) ] D[113,150] = var(103); // [ var(150) , var(113) ] D[115,150] = var(105); // [ var(150) , var(115) ] D[117,150] = (-1)*var(110); // [ var(150) , var(117) ] D[1,151] = (-1)*var(147); // [ var(151) , var(1) ] D[6,151] = var(144); // [ var(151) , var(6) ] D[9,151] = (-1)*var(140); // [ var(151) , var(9) ] D[13,151] = var(136); // [ var(151) , var(13) ] D[16,151] = (-1)*var(133); // [ var(151) , var(16) ] D[20,151] = var(129); // [ var(151) , var(20) ] D[24,151] = (-1)*var(126); // [ var(151) , var(24) ] D[27,151] = var(121); // [ var(151) , var(27) ] D[31,151] = (-1)*var(241)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246); // [ var(151) , var(31) ] D[38,151] = var(2); // [ var(151) , var(38) ] D[39,151] = (-1)*var(7); // [ var(151) , var(39) ] D[45,151] = var(10); // [ var(151) , var(45) ] D[47,151] = (-1)*var(15); // [ var(151) , var(47) ] D[51,151] = var(17); // [ var(151) , var(51) ] D[52,151] = var(18); // [ var(151) , var(52) ] D[57,151] = var(25); // [ var(151) , var(57) ] D[63,151] = var(32); // [ var(151) , var(63) ] D[66,151] = (-1)*var(34); // [ var(151) , var(66) ] D[71,151] = (-1)*var(41); // [ var(151) , var(71) ] D[73,151] = (-1)*var(42); // [ var(151) , var(73) ] D[76,151] = (-1)*var(49); // [ var(151) , var(76) ] D[78,151] = (-1)*var(50); // [ var(151) , var(78) ] D[82,151] = (-1)*var(55); // [ var(151) , var(82) ] D[83,151] = (-1)*var(56); // [ var(151) , var(83) ] D[87,151] = (-1)*var(62); // [ var(151) , var(87) ] D[96,151] = var(74); // [ var(151) , var(96) ] D[97,151] = var(75); // [ var(151) , var(97) ] D[101,151] = var(81); // [ var(151) , var(101) ] D[107,151] = (-1)*var(91); // [ var(151) , var(107) ] D[109,151] = (-1)*var(95); // [ var(151) , var(109) ] D[111,151] = (-1)*var(99); // [ var(151) , var(111) ] D[114,151] = (-1)*var(102); // [ var(151) , var(114) ] D[118,151] = (-1)*var(112); // [ var(151) , var(118) ] D[4,152] = var(145); // [ var(152) , var(4) ] D[10,152] = (-1)*var(139); // [ var(152) , var(10) ] D[11,152] = (-1)*var(138); // [ var(152) , var(11) ] D[12,152] = (-1)*var(137); // [ var(152) , var(12) ] D[17,152] = var(132); // [ var(152) , var(17) ] D[18,152] = var(131); // [ var(152) , var(18) ] D[19,152] = var(130); // [ var(152) , var(19) ] D[25,152] = (-1)*var(124); // [ var(152) , var(25) ] D[32,152] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-1)*var(245); // [ var(152) , var(32) ] D[37,152] = var(1); // [ var(152) , var(37) ] D[40,152] = (-1)*var(6); // [ var(152) , var(40) ] D[44,152] = (-1)*var(9); // [ var(152) , var(44) ] D[48,152] = var(13); // [ var(152) , var(48) ] D[49,152] = (-1)*var(14); // [ var(152) , var(49) ] D[55,152] = var(21); // [ var(152) , var(55) ] D[56,152] = (-1)*var(22); // [ var(152) , var(56) ] D[62,152] = var(29); // [ var(152) , var(62) ] D[63,152] = (-1)*var(31); // [ var(152) , var(63) ] D[69,152] = var(38); // [ var(152) , var(69) ] D[70,152] = (-1)*var(39); // [ var(152) , var(70) ] D[75,152] = var(46); // [ var(152) , var(75) ] D[77,152] = (-1)*var(47); // [ var(152) , var(77) ] D[81,152] = var(54); // [ var(152) , var(81) ] D[89,152] = var(66); // [ var(152) , var(89) ] D[93,152] = (-1)*var(71); // [ var(152) , var(93) ] D[94,152] = var(73); // [ var(152) , var(94) ] D[98,152] = (-1)*var(78); // [ var(152) , var(98) ] D[99,152] = var(79); // [ var(152) , var(99) ] D[102,152] = (-1)*var(84); // [ var(152) , var(102) ] D[110,152] = (-1)*var(96); // [ var(152) , var(110) ] D[112,152] = var(100); // [ var(152) , var(112) ] D[116,152] = (-1)*var(107); // [ var(152) , var(116) ] D[117,152] = var(109); // [ var(152) , var(117) ] D[2,153] = (-1)*var(147); // [ var(153) , var(2) ] D[3,153] = (-1)*var(146); // [ var(153) , var(3) ] D[6,153] = var(145); // [ var(153) , var(6) ] D[13,153] = var(137); // [ var(153) , var(13) ] D[17,153] = (-1)*var(133); // [ var(153) , var(17) ] D[25,153] = (-1)*var(126); // [ var(153) , var(25) ] D[26,153] = var(123); // [ var(153) , var(26) ] D[27,153] = var(122); // [ var(153) , var(27) ] D[33,153] = (-1)*var(242)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246); // [ var(153) , var(33) ] D[38,153] = var(1); // [ var(153) , var(38) ] D[40,153] = (-1)*var(4); // [ var(153) , var(40) ] D[41,153] = (-1)*var(7); // [ var(153) , var(41) ] D[48,153] = (-1)*var(12); // [ var(153) , var(48) ] D[50,153] = (-1)*var(15); // [ var(153) , var(50) ] D[51,153] = var(16); // [ var(153) , var(51) ] D[57,153] = var(24); // [ var(153) , var(57) ] D[61,153] = var(28); // [ var(153) , var(61) ] D[68,153] = var(36); // [ var(153) , var(68) ] D[69,153] = var(37); // [ var(153) , var(69) ] D[71,153] = (-1)*var(39); // [ var(153) , var(71) ] D[78,153] = (-1)*var(47); // [ var(153) , var(78) ] D[80,153] = (-1)*var(53); // [ var(153) , var(80) ] D[85,153] = (-1)*var(59); // [ var(153) , var(85) ] D[86,153] = (-1)*var(60); // [ var(153) , var(86) ] D[90,153] = (-1)*var(67); // [ var(153) , var(90) ] D[93,153] = (-1)*var(70); // [ var(153) , var(93) ] D[98,153] = (-1)*var(77); // [ var(153) , var(98) ] D[100,153] = var(79); // [ var(153) , var(100) ] D[105,153] = var(88); // [ var(153) , var(105) ] D[108,153] = var(92); // [ var(153) , var(108) ] D[112,153] = var(99); // [ var(153) , var(112) ] D[115,153] = (-1)*var(104); // [ var(153) , var(115) ] D[118,153] = var(111); // [ var(153) , var(118) ] D[2,154] = (-1)*var(148); // [ var(154) , var(2) ] D[7,154] = var(146); // [ var(154) , var(7) ] D[10,154] = (-1)*var(141); // [ var(154) , var(10) ] D[14,154] = var(138); // [ var(154) , var(14) ] D[18,154] = (-1)*var(134); // [ var(154) , var(18) ] D[21,154] = var(130); // [ var(154) , var(21) ] D[26,154] = (-1)*var(127); // [ var(154) , var(26) ] D[28,154] = var(122); // [ var(154) , var(28) ] D[34,154] = (-1)*var(242)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(154) , var(34) ] D[41,154] = var(3); // [ var(154) , var(41) ] D[42,154] = (-1)*var(8); // [ var(154) , var(42) ] D[46,154] = var(9); // [ var(154) , var(46) ] D[49,154] = var(11); // [ var(154) , var(49) ] D[53,154] = var(16); // [ var(154) , var(53) ] D[55,154] = var(19); // [ var(154) , var(55) ] D[59,154] = var(24); // [ var(154) , var(59) ] D[61,154] = var(27); // [ var(154) , var(61) ] D[66,154] = var(31); // [ var(154) , var(66) ] D[74,154] = (-1)*var(43); // [ var(154) , var(74) ] D[75,154] = (-1)*var(44); // [ var(154) , var(75) ] D[79,154] = (-1)*var(47); // [ var(154) , var(79) ] D[80,154] = (-1)*var(51); // [ var(154) , var(80) ] D[85,154] = (-1)*var(57); // [ var(154) , var(85) ] D[89,154] = (-1)*var(63); // [ var(154) , var(89) ] D[91,154] = var(65); // [ var(154) , var(91) ] D[95,154] = var(72); // [ var(154) , var(95) ] D[99,154] = var(77); // [ var(154) , var(99) ] D[100,154] = var(78); // [ var(154) , var(100) ] D[103,154] = var(83); // [ var(154) , var(103) ] D[106,154] = var(87); // [ var(154) , var(106) ] D[112,154] = (-1)*var(98); // [ var(154) , var(112) ] D[113,154] = (-1)*var(101); // [ var(154) , var(113) ] D[119,154] = (-1)*var(114); // [ var(154) , var(119) ] D[3,155] = (-1)*var(148); // [ var(155) , var(3) ] D[7,155] = var(147); // [ var(155) , var(7) ] D[11,155] = (-1)*var(141); // [ var(155) , var(11) ] D[14,155] = var(139); // [ var(155) , var(14) ] D[19,155] = (-1)*var(134); // [ var(155) , var(19) ] D[21,155] = var(131); // [ var(155) , var(21) ] D[27,155] = (-1)*var(127); // [ var(155) , var(27) ] D[28,155] = var(123); // [ var(155) , var(28) ] D[35,155] = (-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(155) , var(35) ] D[39,155] = var(1); // [ var(155) , var(39) ] D[41,155] = var(2); // [ var(155) , var(41) ] D[43,155] = (-1)*var(8); // [ var(155) , var(43) ] D[49,155] = var(10); // [ var(155) , var(49) ] D[55,155] = var(18); // [ var(155) , var(55) ] D[58,155] = (-1)*var(23); // [ var(155) , var(58) ] D[61,155] = var(26); // [ var(155) , var(61) ] D[64,155] = (-1)*var(30); // [ var(155) , var(64) ] D[70,155] = (-1)*var(37); // [ var(155) , var(70) ] D[71,155] = (-1)*var(38); // [ var(155) , var(71) ] D[74,155] = (-1)*var(42); // [ var(155) , var(74) ] D[76,155] = (-1)*var(45); // [ var(155) , var(76) ] D[82,155] = (-1)*var(52); // [ var(155) , var(82) ] D[84,155] = var(54); // [ var(155) , var(84) ] D[88,155] = var(60); // [ var(155) , var(88) ] D[92,155] = var(67); // [ var(155) , var(92) ] D[93,155] = var(69); // [ var(155) , var(93) ] D[96,155] = var(73); // [ var(155) , var(96) ] D[102,155] = (-1)*var(81); // [ var(155) , var(102) ] D[105,155] = (-1)*var(86); // [ var(155) , var(105) ] D[108,155] = (-1)*var(90); // [ var(155) , var(108) ] D[110,155] = (-1)*var(94); // [ var(155) , var(110) ] D[114,155] = var(101); // [ var(155) , var(114) ] D[119,155] = var(113); // [ var(155) , var(119) ] D[4,156] = (-1)*var(149); // [ var(156) , var(4) ] D[8,156] = var(148); // [ var(156) , var(8) ] D[12,156] = (-1)*var(142); // [ var(156) , var(12) ] D[15,156] = var(140); // [ var(156) , var(15) ] D[20,156] = (-1)*var(135); // [ var(156) , var(20) ] D[22,156] = var(132); // [ var(156) , var(22) ] D[28,156] = (-1)*var(128); // [ var(156) , var(28) ] D[29,156] = var(124); // [ var(156) , var(29) ] D[36,156] = (-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(156) , var(36) ] D[42,156] = var(2); // [ var(156) , var(42) ] D[43,156] = var(3); // [ var(156) , var(43) ] D[47,156] = var(9); // [ var(156) , var(47) ] D[56,156] = (-1)*var(17); // [ var(156) , var(56) ] D[60,156] = (-1)*var(23); // [ var(156) , var(60) ] D[62,156] = (-1)*var(25); // [ var(156) , var(62) ] D[67,156] = (-1)*var(30); // [ var(156) , var(67) ] D[68,156] = (-1)*var(33); // [ var(156) , var(68) ] D[73,156] = (-1)*var(38); // [ var(156) , var(73) ] D[74,156] = (-1)*var(41); // [ var(156) , var(74) ] D[77,156] = var(44); // [ var(156) , var(77) ] D[79,156] = (-1)*var(46); // [ var(156) , var(79) ] D[83,156] = var(51); // [ var(156) , var(83) ] D[87,156] = var(57); // [ var(156) , var(87) ] D[88,156] = var(58); // [ var(156) , var(88) ] D[92,156] = var(64); // [ var(156) , var(92) ] D[94,156] = (-1)*var(69); // [ var(156) , var(94) ] D[96,156] = var(71); // [ var(156) , var(96) ] D[99,156] = (-1)*var(75); // [ var(156) , var(99) ] D[103,156] = (-1)*var(80); // [ var(156) , var(103) ] D[106,156] = (-1)*var(85); // [ var(156) , var(106) ] D[110,156] = var(93); // [ var(156) , var(110) ] D[111,156] = var(97); // [ var(156) , var(111) ] D[120,156] = (-1)*var(115); // [ var(156) , var(120) ] D[1,157] = (-1)*var(152); // [ var(157) , var(1) ] D[4,157] = var(150); // [ var(157) , var(4) ] D[10,157] = (-1)*var(144); // [ var(157) , var(10) ] D[12,157] = (-1)*var(143); // [ var(157) , var(12) ] D[16,157] = (-1)*var(138); // [ var(157) , var(16) ] D[18,157] = var(136); // [ var(157) , var(18) ] D[23,157] = var(132); // [ var(157) , var(23) ] D[24,157] = var(130); // [ var(157) , var(24) ] D[30,157] = (-1)*var(124); // [ var(157) , var(30) ] D[32,157] = var(121); // [ var(157) , var(32) ] D[37,157] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-1)*var(245); // [ var(157) , var(37) ] D[44,157] = var(3); // [ var(157) , var(44) ] D[45,157] = (-1)*var(6); // [ var(157) , var(45) ] D[52,157] = var(13); // [ var(157) , var(52) ] D[53,157] = (-1)*var(14); // [ var(157) , var(53) ] D[59,157] = var(21); // [ var(157) , var(59) ] D[60,157] = (-1)*var(22); // [ var(157) , var(60) ] D[63,157] = var(27); // [ var(157) , var(63) ] D[67,157] = var(29); // [ var(157) , var(67) ] D[69,157] = (-1)*var(33); // [ var(157) , var(69) ] D[70,157] = var(35); // [ var(157) , var(70) ] D[75,157] = (-1)*var(41); // [ var(157) , var(75) ] D[77,157] = var(43); // [ var(157) , var(77) ] D[81,157] = (-1)*var(50); // [ var(157) , var(81) ] D[89,157] = (-1)*var(61); // [ var(157) , var(89) ] D[94,157] = (-1)*var(68); // [ var(157) , var(94) ] D[97,157] = var(71); // [ var(157) , var(97) ] D[99,157] = (-1)*var(74); // [ var(157) , var(99) ] D[101,157] = var(78); // [ var(157) , var(101) ] D[104,157] = var(84); // [ var(157) , var(104) ] D[111,157] = var(96); // [ var(157) , var(111) ] D[113,157] = (-1)*var(100); // [ var(157) , var(113) ] D[116,157] = (-1)*var(105); // [ var(157) , var(116) ] D[117,157] = var(108); // [ var(157) , var(117) ] D[1,158] = (-1)*var(153); // [ var(158) , var(1) ] D[2,158] = (-1)*var(151); // [ var(158) , var(2) ] D[6,158] = var(150); // [ var(158) , var(6) ] D[9,158] = (-1)*var(146); // [ var(158) , var(9) ] D[13,158] = var(143); // [ var(158) , var(13) ] D[23,158] = (-1)*var(133); // [ var(158) , var(23) ] D[26,158] = var(129); // [ var(158) , var(26) ] D[30,158] = (-1)*var(126); // [ var(158) , var(30) ] D[31,158] = var(122); // [ var(158) , var(31) ] D[33,158] = var(121); // [ var(158) , var(33) ] D[38,158] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246); // [ var(158) , var(38) ] D[45,158] = (-1)*var(4); // [ var(158) , var(45) ] D[46,158] = (-1)*var(7); // [ var(158) , var(46) ] D[51,158] = (-1)*var(11); // [ var(158) , var(51) ] D[52,158] = (-1)*var(12); // [ var(158) , var(52) ] D[54,158] = (-1)*var(15); // [ var(158) , var(54) ] D[57,158] = (-1)*var(19); // [ var(158) , var(57) ] D[66,158] = var(28); // [ var(158) , var(66) ] D[69,158] = (-1)*var(32); // [ var(158) , var(69) ] D[71,158] = var(35); // [ var(158) , var(71) ] D[73,158] = var(36); // [ var(158) , var(73) ] D[78,158] = var(43); // [ var(158) , var(78) ] D[80,158] = var(49); // [ var(158) , var(80) ] D[85,158] = var(55); // [ var(158) , var(85) ] D[86,158] = var(56); // [ var(158) , var(86) ] D[90,158] = var(62); // [ var(158) , var(90) ] D[97,158] = var(70); // [ var(158) , var(97) ] D[100,158] = (-1)*var(74); // [ var(158) , var(100) ] D[101,158] = var(77); // [ var(158) , var(101) ] D[107,158] = (-1)*var(88); // [ var(158) , var(107) ] D[109,158] = (-1)*var(92); // [ var(158) , var(109) ] D[113,158] = (-1)*var(99); // [ var(158) , var(113) ] D[115,158] = (-1)*var(102); // [ var(158) , var(115) ] D[118,158] = var(110); // [ var(158) , var(118) ] D[1,159] = (-1)*var(155); // [ var(159) , var(1) ] D[7,159] = var(151); // [ var(159) , var(7) ] D[9,159] = (-1)*var(148); // [ var(159) , var(9) ] D[14,159] = var(144); // [ var(159) , var(14) ] D[16,159] = (-1)*var(141); // [ var(159) , var(16) ] D[21,159] = var(136); // [ var(159) , var(21) ] D[24,159] = (-1)*var(134); // [ var(159) , var(24) ] D[28,159] = var(129); // [ var(159) , var(28) ] D[31,159] = (-1)*var(127); // [ var(159) , var(31) ] D[35,159] = var(121); // [ var(159) , var(35) ] D[39,159] = (-1)*var(241)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(159) , var(39) ] D[46,159] = var(2); // [ var(159) , var(46) ] D[47,159] = (-1)*var(8); // [ var(159) , var(47) ] D[53,159] = var(10); // [ var(159) , var(53) ] D[58,159] = var(17); // [ var(159) , var(58) ] D[59,159] = var(18); // [ var(159) , var(59) ] D[64,159] = var(25); // [ var(159) , var(64) ] D[66,159] = var(26); // [ var(159) , var(66) ] D[70,159] = var(32); // [ var(159) , var(70) ] D[71,159] = var(33); // [ var(159) , var(71) ] D[76,159] = var(40); // [ var(159) , var(76) ] D[79,159] = (-1)*var(42); // [ var(159) , var(79) ] D[82,159] = var(48); // [ var(159) , var(82) ] D[84,159] = (-1)*var(50); // [ var(159) , var(84) ] D[88,159] = (-1)*var(56); // [ var(159) , var(88) ] D[92,159] = (-1)*var(62); // [ var(159) , var(92) ] D[96,159] = (-1)*var(68); // [ var(159) , var(96) ] D[97,159] = (-1)*var(69); // [ var(159) , var(97) ] D[104,159] = var(81); // [ var(159) , var(104) ] D[107,159] = var(86); // [ var(159) , var(107) ] D[109,159] = var(90); // [ var(159) , var(109) ] D[111,159] = var(94); // [ var(159) , var(111) ] D[114,159] = var(98); // [ var(159) , var(114) ] D[119,159] = var(112); // [ var(159) , var(119) ] D[4,160] = var(153); // [ var(160) , var(4) ] D[6,160] = var(152); // [ var(160) , var(6) ] D[10,160] = (-1)*var(147); // [ var(160) , var(10) ] D[11,160] = (-1)*var(146); // [ var(160) , var(11) ] D[17,160] = var(140); // [ var(160) , var(17) ] D[20,160] = (-1)*var(137); // [ var(160) , var(20) ] D[26,160] = var(131); // [ var(160) , var(26) ] D[27,160] = var(130); // [ var(160) , var(27) ] D[32,160] = (-1)*var(126); // [ var(160) , var(32) ] D[33,160] = (-1)*var(124); // [ var(160) , var(33) ] D[40,160] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-1)*var(245)+(-1)*var(246); // [ var(160) , var(40) ] D[45,160] = var(1); // [ var(160) , var(45) ] D[48,160] = (-1)*var(5); // [ var(160) , var(48) ] D[49,160] = (-1)*var(7); // [ var(160) , var(49) ] D[51,160] = (-1)*var(9); // [ var(160) , var(51) ] D[56,160] = (-1)*var(15); // [ var(160) , var(56) ] D[61,160] = var(21); // [ var(160) , var(61) ] D[63,160] = var(24); // [ var(160) , var(63) ] D[68,160] = var(29); // [ var(160) , var(68) ] D[69,160] = (-1)*var(30); // [ var(160) , var(69) ] D[76,160] = (-1)*var(39); // [ var(160) , var(76) ] D[80,160] = var(46); // [ var(160) , var(80) ] D[83,160] = (-1)*var(47); // [ var(160) , var(83) ] D[86,160] = var(54); // [ var(160) , var(86) ] D[89,160] = (-1)*var(59); // [ var(160) , var(89) ] D[93,160] = var(64); // [ var(160) , var(93) ] D[94,160] = (-1)*var(67); // [ var(160) , var(94) ] D[98,160] = var(72); // [ var(160) , var(98) ] D[103,160] = var(79); // [ var(160) , var(103) ] D[105,160] = (-1)*var(84); // [ var(160) , var(105) ] D[110,160] = var(92); // [ var(160) , var(110) ] D[112,160] = (-1)*var(95); // [ var(160) , var(112) ] D[116,160] = var(104); // [ var(160) , var(116) ] D[118,160] = (-1)*var(109); // [ var(160) , var(118) ] D[2,161] = (-1)*var(155); // [ var(161) , var(2) ] D[3,161] = (-1)*var(154); // [ var(161) , var(3) ] D[7,161] = var(153); // [ var(161) , var(7) ] D[14,161] = var(145); // [ var(161) , var(14) ] D[17,161] = (-1)*var(141); // [ var(161) , var(17) ] D[21,161] = var(137); // [ var(161) , var(21) ] D[25,161] = (-1)*var(134); // [ var(161) , var(25) ] D[33,161] = (-1)*var(127); // [ var(161) , var(33) ] D[34,161] = var(123); // [ var(161) , var(34) ] D[35,161] = var(122); // [ var(161) , var(35) ] D[41,161] = (-1)*var(242)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(161) , var(41) ] D[46,161] = var(1); // [ var(161) , var(46) ] D[49,161] = (-1)*var(4); // [ var(161) , var(49) ] D[50,161] = (-1)*var(8); // [ var(161) , var(50) ] D[55,161] = (-1)*var(12); // [ var(161) , var(55) ] D[58,161] = var(16); // [ var(161) , var(58) ] D[61,161] = (-1)*var(20); // [ var(161) , var(61) ] D[64,161] = var(24); // [ var(161) , var(64) ] D[71,161] = var(31); // [ var(161) , var(71) ] D[74,161] = var(36); // [ var(161) , var(74) ] D[75,161] = var(37); // [ var(161) , var(75) ] D[80,161] = var(45); // [ var(161) , var(80) ] D[84,161] = (-1)*var(47); // [ var(161) , var(84) ] D[85,161] = var(52); // [ var(161) , var(85) ] D[91,161] = (-1)*var(60); // [ var(161) , var(91) ] D[93,161] = var(63); // [ var(161) , var(93) ] D[95,161] = (-1)*var(67); // [ var(161) , var(95) ] D[100,161] = (-1)*var(73); // [ var(161) , var(100) ] D[102,161] = (-1)*var(77); // [ var(161) , var(102) ] D[105,161] = (-1)*var(83); // [ var(161) , var(105) ] D[108,161] = (-1)*var(87); // [ var(161) , var(108) ] D[112,161] = (-1)*var(94); // [ var(161) , var(112) ] D[115,161] = var(101); // [ var(161) , var(115) ] D[119,161] = (-1)*var(111); // [ var(161) , var(119) ] D[2,162] = (-1)*var(156); // [ var(162) , var(2) ] D[8,162] = var(154); // [ var(162) , var(8) ] D[10,162] = (-1)*var(149); // [ var(162) , var(10) ] D[15,162] = var(146); // [ var(162) , var(15) ] D[18,162] = (-1)*var(142); // [ var(162) , var(18) ] D[22,162] = var(138); // [ var(162) , var(22) ] D[26,162] = (-1)*var(135); // [ var(162) , var(26) ] D[29,162] = var(130); // [ var(162) , var(29) ] D[34,162] = (-1)*var(128); // [ var(162) , var(34) ] D[36,162] = var(122); // [ var(162) , var(36) ] D[42,162] = (-1)*var(242)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(162) , var(42) ] D[50,162] = var(3); // [ var(162) , var(50) ] D[54,162] = var(9); // [ var(162) , var(54) ] D[56,162] = var(11); // [ var(162) , var(56) ] D[60,162] = var(16); // [ var(162) , var(60) ] D[62,162] = var(19); // [ var(162) , var(62) ] D[67,162] = var(24); // [ var(162) , var(67) ] D[68,162] = var(27); // [ var(162) , var(68) ] D[73,162] = var(31); // [ var(162) , var(73) ] D[74,162] = var(35); // [ var(162) , var(74) ] D[79,162] = var(39); // [ var(162) , var(79) ] D[81,162] = (-1)*var(44); // [ var(162) , var(81) ] D[86,162] = (-1)*var(51); // [ var(162) , var(86) ] D[90,162] = (-1)*var(57); // [ var(162) , var(90) ] D[91,162] = (-1)*var(58); // [ var(162) , var(91) ] D[94,162] = (-1)*var(63); // [ var(162) , var(94) ] D[95,162] = (-1)*var(64); // [ var(162) , var(95) ] D[99,162] = (-1)*var(70); // [ var(162) , var(99) ] D[100,162] = (-1)*var(71); // [ var(162) , var(100) ] D[103,162] = (-1)*var(76); // [ var(162) , var(103) ] D[106,162] = (-1)*var(82); // [ var(162) , var(106) ] D[112,162] = var(93); // [ var(162) , var(112) ] D[113,162] = var(97); // [ var(162) , var(113) ] D[120,162] = var(114); // [ var(162) , var(120) ] D[3,163] = (-1)*var(156); // [ var(163) , var(3) ] D[8,163] = var(155); // [ var(163) , var(8) ] D[11,163] = (-1)*var(149); // [ var(163) , var(11) ] D[15,163] = var(147); // [ var(163) , var(15) ] D[19,163] = (-1)*var(142); // [ var(163) , var(19) ] D[22,163] = var(139); // [ var(163) , var(22) ] D[27,163] = (-1)*var(135); // [ var(163) , var(27) ] D[29,163] = var(131); // [ var(163) , var(29) ] D[35,163] = (-1)*var(128); // [ var(163) , var(35) ] D[36,163] = var(123); // [ var(163) , var(36) ] D[43,163] = (-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(163) , var(43) ] D[47,163] = var(1); // [ var(163) , var(47) ] D[50,163] = var(2); // [ var(163) , var(50) ] D[56,163] = var(10); // [ var(163) , var(56) ] D[62,163] = var(18); // [ var(163) , var(62) ] D[65,163] = (-1)*var(23); // [ var(163) , var(65) ] D[68,163] = var(26); // [ var(163) , var(68) ] D[72,163] = (-1)*var(30); // [ var(163) , var(72) ] D[74,163] = var(34); // [ var(163) , var(74) ] D[77,163] = (-1)*var(37); // [ var(163) , var(77) ] D[78,163] = (-1)*var(38); // [ var(163) , var(78) ] D[83,163] = (-1)*var(45); // [ var(163) , var(83) ] D[84,163] = (-1)*var(46); // [ var(163) , var(84) ] D[87,163] = (-1)*var(52); // [ var(163) , var(87) ] D[88,163] = (-1)*var(53); // [ var(163) , var(88) ] D[92,163] = (-1)*var(59); // [ var(163) , var(92) ] D[96,163] = (-1)*var(66); // [ var(163) , var(96) ] D[98,163] = var(69); // [ var(163) , var(98) ] D[102,163] = var(75); // [ var(163) , var(102) ] D[105,163] = var(80); // [ var(163) , var(105) ] D[108,163] = var(85); // [ var(163) , var(108) ] D[110,163] = var(89); // [ var(163) , var(110) ] D[114,163] = (-1)*var(97); // [ var(163) , var(114) ] D[120,163] = (-1)*var(113); // [ var(163) , var(120) ] D[3,164] = (-1)*var(157); // [ var(164) , var(3) ] D[9,164] = var(152); // [ var(164) , var(9) ] D[11,164] = var(150); // [ var(164) , var(11) ] D[16,164] = (-1)*var(145); // [ var(164) , var(16) ] D[17,164] = (-1)*var(144); // [ var(164) , var(17) ] D[19,164] = (-1)*var(143); // [ var(164) , var(19) ] D[23,164] = var(139); // [ var(164) , var(23) ] D[24,164] = var(137); // [ var(164) , var(24) ] D[25,164] = var(136); // [ var(164) , var(25) ] D[30,164] = (-1)*var(131); // [ var(164) , var(30) ] D[32,164] = (-1)*var(129); // [ var(164) , var(32) ] D[37,164] = var(123); // [ var(164) , var(37) ] D[44,164] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-1)*var(245); // [ var(164) , var(44) ] D[51,164] = (-1)*var(6); // [ var(164) , var(51) ] D[57,164] = var(13); // [ var(164) , var(57) ] D[58,164] = (-1)*var(14); // [ var(164) , var(58) ] D[63,164] = (-1)*var(20); // [ var(164) , var(63) ] D[64,164] = var(21); // [ var(164) , var(64) ] D[65,164] = (-1)*var(22); // [ var(164) , var(65) ] D[69,164] = var(26); // [ var(164) , var(69) ] D[70,164] = (-1)*var(28); // [ var(164) , var(70) ] D[72,164] = var(29); // [ var(164) , var(72) ] D[75,164] = var(34); // [ var(164) , var(75) ] D[77,164] = (-1)*var(36); // [ var(164) , var(77) ] D[81,164] = var(42); // [ var(164) , var(81) ] D[93,164] = var(61); // [ var(164) , var(93) ] D[97,164] = (-1)*var(66); // [ var(164) , var(97) ] D[98,164] = var(68); // [ var(164) , var(98) ] D[101,164] = (-1)*var(73); // [ var(164) , var(101) ] D[102,164] = var(74); // [ var(164) , var(102) ] D[104,164] = (-1)*var(79); // [ var(164) , var(104) ] D[114,164] = (-1)*var(96); // [ var(164) , var(114) ] D[115,164] = var(100); // [ var(164) , var(115) ] D[116,164] = (-1)*var(103); // [ var(164) , var(116) ] D[117,164] = var(106); // [ var(164) , var(117) ] D[1,165] = (-1)*var(160); // [ var(165) , var(1) ] D[4,165] = var(158); // [ var(165) , var(4) ] D[6,165] = var(157); // [ var(165) , var(6) ] D[10,165] = (-1)*var(151); // [ var(165) , var(10) ] D[16,165] = (-1)*var(146); // [ var(165) , var(16) ] D[20,165] = (-1)*var(143); // [ var(165) , var(20) ] D[23,165] = var(140); // [ var(165) , var(23) ] D[26,165] = var(136); // [ var(165) , var(26) ] D[31,165] = var(130); // [ var(165) , var(31) ] D[37,165] = (-1)*var(126); // [ var(165) , var(37) ] D[38,165] = (-1)*var(124); // [ var(165) , var(38) ] D[40,165] = var(121); // [ var(165) , var(40) ] D[45,165] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-1)*var(245)+(-1)*var(246); // [ var(165) , var(45) ] D[51,165] = var(3); // [ var(165) , var(51) ] D[52,165] = (-1)*var(5); // [ var(165) , var(52) ] D[53,165] = (-1)*var(7); // [ var(165) , var(53) ] D[60,165] = (-1)*var(15); // [ var(165) , var(60) ] D[63,165] = (-1)*var(19); // [ var(165) , var(63) ] D[66,165] = var(21); // [ var(165) , var(66) ] D[69,165] = var(25); // [ var(165) , var(69) ] D[73,165] = var(29); // [ var(165) , var(73) ] D[76,165] = var(35); // [ var(165) , var(76) ] D[80,165] = (-1)*var(41); // [ var(165) , var(80) ] D[83,165] = var(43); // [ var(165) , var(83) ] D[86,165] = (-1)*var(50); // [ var(165) , var(86) ] D[89,165] = var(55); // [ var(165) , var(89) ] D[94,165] = var(62); // [ var(165) , var(94) ] D[97,165] = (-1)*var(64); // [ var(165) , var(97) ] D[101,165] = (-1)*var(72); // [ var(165) , var(101) ] D[103,165] = (-1)*var(74); // [ var(165) , var(103) ] D[107,165] = var(84); // [ var(165) , var(107) ] D[111,165] = (-1)*var(92); // [ var(165) , var(111) ] D[113,165] = var(95); // [ var(165) , var(113) ] D[116,165] = var(102); // [ var(165) , var(116) ] D[118,165] = (-1)*var(108); // [ var(165) , var(118) ] D[1,166] = (-1)*var(161); // [ var(166) , var(1) ] D[2,166] = (-1)*var(159); // [ var(166) , var(2) ] D[7,166] = var(158); // [ var(166) , var(7) ] D[9,166] = (-1)*var(154); // [ var(166) , var(9) ] D[14,166] = var(150); // [ var(166) , var(14) ] D[21,166] = var(143); // [ var(166) , var(21) ] D[23,166] = (-1)*var(141); // [ var(166) , var(23) ] D[30,166] = (-1)*var(134); // [ var(166) , var(30) ] D[34,166] = var(129); // [ var(166) , var(34) ] D[38,166] = (-1)*var(127); // [ var(166) , var(38) ] D[39,166] = var(122); // [ var(166) , var(39) ] D[41,166] = var(121); // [ var(166) , var(41) ] D[46,166] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(166) , var(46) ] D[53,166] = (-1)*var(4); // [ var(166) , var(53) ] D[54,166] = (-1)*var(8); // [ var(166) , var(54) ] D[58,166] = (-1)*var(11); // [ var(166) , var(58) ] D[59,166] = (-1)*var(12); // [ var(166) , var(59) ] D[64,166] = (-1)*var(19); // [ var(166) , var(64) ] D[66,166] = (-1)*var(20); // [ var(166) , var(66) ] D[71,166] = (-1)*var(27); // [ var(166) , var(71) ] D[75,166] = (-1)*var(32); // [ var(166) , var(75) ] D[79,166] = var(36); // [ var(166) , var(79) ] D[80,166] = (-1)*var(40); // [ var(166) , var(80) ] D[84,166] = var(43); // [ var(166) , var(84) ] D[85,166] = (-1)*var(48); // [ var(166) , var(85) ] D[91,166] = var(56); // [ var(166) , var(91) ] D[95,166] = var(62); // [ var(166) , var(95) ] D[97,166] = (-1)*var(63); // [ var(166) , var(97) ] D[100,166] = var(68); // [ var(166) , var(100) ] D[104,166] = var(77); // [ var(166) , var(104) ] D[107,166] = var(83); // [ var(166) , var(107) ] D[109,166] = var(87); // [ var(166) , var(109) ] D[113,166] = var(94); // [ var(166) , var(113) ] D[115,166] = var(98); // [ var(166) , var(115) ] D[119,166] = (-1)*var(110); // [ var(166) , var(119) ] D[1,167] = (-1)*var(163); // [ var(167) , var(1) ] D[8,167] = var(159); // [ var(167) , var(8) ] D[9,167] = (-1)*var(156); // [ var(167) , var(9) ] D[15,167] = var(151); // [ var(167) , var(15) ] D[16,167] = (-1)*var(149); // [ var(167) , var(16) ] D[22,167] = var(144); // [ var(167) , var(22) ] D[24,167] = (-1)*var(142); // [ var(167) , var(24) ] D[29,167] = var(136); // [ var(167) , var(29) ] D[31,167] = (-1)*var(135); // [ var(167) , var(31) ] D[36,167] = var(129); // [ var(167) , var(36) ] D[39,167] = (-1)*var(128); // [ var(167) , var(39) ] D[43,167] = var(121); // [ var(167) , var(43) ] D[47,167] = (-1)*var(241)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(167) , var(47) ] D[54,167] = var(2); // [ var(167) , var(54) ] D[60,167] = var(10); // [ var(167) , var(60) ] D[65,167] = var(17); // [ var(167) , var(65) ] D[67,167] = var(18); // [ var(167) , var(67) ] D[72,167] = var(25); // [ var(167) , var(72) ] D[73,167] = var(26); // [ var(167) , var(73) ] D[77,167] = var(32); // [ var(167) , var(77) ] D[78,167] = var(33); // [ var(167) , var(78) ] D[79,167] = var(34); // [ var(167) , var(79) ] D[83,167] = var(40); // [ var(167) , var(83) ] D[84,167] = var(41); // [ var(167) , var(84) ] D[87,167] = var(48); // [ var(167) , var(87) ] D[88,167] = var(49); // [ var(167) , var(88) ] D[92,167] = var(55); // [ var(167) , var(92) ] D[96,167] = var(61); // [ var(167) , var(96) ] D[101,167] = (-1)*var(69); // [ var(167) , var(101) ] D[104,167] = (-1)*var(75); // [ var(167) , var(104) ] D[107,167] = (-1)*var(80); // [ var(167) , var(107) ] D[109,167] = (-1)*var(85); // [ var(167) , var(109) ] D[111,167] = (-1)*var(89); // [ var(167) , var(111) ] D[114,167] = (-1)*var(93); // [ var(167) , var(114) ] D[120,167] = (-1)*var(112); // [ var(167) , var(120) ] D[5,168] = var(160); // [ var(168) , var(5) ] D[12,168] = var(153); // [ var(168) , var(12) ] D[13,168] = (-1)*var(152); // [ var(168) , var(13) ] D[18,168] = (-1)*var(147); // [ var(168) , var(18) ] D[19,168] = (-1)*var(146); // [ var(168) , var(19) ] D[20,168] = (-1)*var(145); // [ var(168) , var(20) ] D[25,168] = var(140); // [ var(168) , var(25) ] D[26,168] = var(139); // [ var(168) , var(26) ] D[27,168] = var(138); // [ var(168) , var(27) ] D[32,168] = var(133); // [ var(168) , var(32) ] D[33,168] = (-1)*var(132); // [ var(168) , var(33) ] D[40,168] = (-1)*var(125); // [ var(168) , var(40) ] D[48,168] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-1)*var(246); // [ var(168) , var(48) ] D[52,168] = var(1); // [ var(168) , var(52) ] D[55,168] = (-1)*var(7); // [ var(168) , var(55) ] D[57,168] = (-1)*var(9); // [ var(168) , var(57) ] D[61,168] = var(14); // [ var(168) , var(61) ] D[62,168] = (-1)*var(15); // [ var(168) , var(62) ] D[63,168] = (-1)*var(16); // [ var(168) , var(63) ] D[68,168] = var(22); // [ var(168) , var(68) ] D[69,168] = var(23); // [ var(168) , var(69) ] D[82,168] = (-1)*var(39); // [ var(168) , var(82) ] D[85,168] = var(46); // [ var(168) , var(85) ] D[87,168] = (-1)*var(47); // [ var(168) , var(87) ] D[89,168] = var(53); // [ var(168) , var(89) ] D[90,168] = var(54); // [ var(168) , var(90) ] D[93,168] = (-1)*var(58); // [ var(168) , var(93) ] D[94,168] = var(60); // [ var(168) , var(94) ] D[98,168] = (-1)*var(65); // [ var(168) , var(98) ] D[106,168] = var(79); // [ var(168) , var(106) ] D[108,168] = (-1)*var(84); // [ var(168) , var(108) ] D[110,168] = (-1)*var(88); // [ var(168) , var(110) ] D[112,168] = var(91); // [ var(168) , var(112) ] D[117,168] = (-1)*var(104); // [ var(168) , var(117) ] D[118,168] = var(107); // [ var(168) , var(118) ] D[4,169] = var(161); // [ var(169) , var(4) ] D[7,169] = var(160); // [ var(169) , var(7) ] D[10,169] = (-1)*var(155); // [ var(169) , var(10) ] D[11,169] = (-1)*var(154); // [ var(169) , var(11) ] D[14,169] = var(152); // [ var(169) , var(14) ] D[17,169] = var(148); // [ var(169) , var(17) ] D[28,169] = (-1)*var(137); // [ var(169) , var(28) ] D[32,169] = (-1)*var(134); // [ var(169) , var(32) ] D[34,169] = var(131); // [ var(169) , var(34) ] D[35,169] = var(130); // [ var(169) , var(35) ] D[40,169] = (-1)*var(127); // [ var(169) , var(40) ] D[41,169] = (-1)*var(124); // [ var(169) , var(41) ] D[49,169] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(169) , var(49) ] D[53,169] = var(1); // [ var(169) , var(53) ] D[55,169] = (-1)*var(5); // [ var(169) , var(55) ] D[56,169] = (-1)*var(8); // [ var(169) , var(56) ] D[58,169] = (-1)*var(9); // [ var(169) , var(58) ] D[61,169] = (-1)*var(13); // [ var(169) , var(61) ] D[70,169] = var(24); // [ var(169) , var(70) ] D[74,169] = var(29); // [ var(169) , var(74) ] D[75,169] = (-1)*var(30); // [ var(169) , var(75) ] D[76,169] = var(31); // [ var(169) , var(76) ] D[80,169] = (-1)*var(38); // [ var(169) , var(80) ] D[88,169] = (-1)*var(47); // [ var(169) , var(88) ] D[89,169] = var(52); // [ var(169) , var(89) ] D[91,169] = var(54); // [ var(169) , var(91) ] D[93,169] = (-1)*var(57); // [ var(169) , var(93) ] D[99,169] = (-1)*var(67); // [ var(169) , var(99) ] D[102,169] = var(72); // [ var(169) , var(102) ] D[103,169] = (-1)*var(73); // [ var(169) , var(103) ] D[105,169] = var(78); // [ var(169) , var(105) ] D[110,169] = (-1)*var(87); // [ var(169) , var(110) ] D[112,169] = var(90); // [ var(169) , var(112) ] D[116,169] = (-1)*var(101); // [ var(169) , var(116) ] D[119,169] = var(109); // [ var(169) , var(119) ] D[2,170] = (-1)*var(163); // [ var(170) , var(2) ] D[3,170] = (-1)*var(162); // [ var(170) , var(3) ] D[8,170] = var(161); // [ var(170) , var(8) ] D[15,170] = var(153); // [ var(170) , var(15) ] D[17,170] = (-1)*var(149); // [ var(170) , var(17) ] D[22,170] = var(145); // [ var(170) , var(22) ] D[25,170] = (-1)*var(142); // [ var(170) , var(25) ] D[29,170] = var(137); // [ var(170) , var(29) ] D[33,170] = (-1)*var(135); // [ var(170) , var(33) ] D[41,170] = (-1)*var(128); // [ var(170) , var(41) ] D[42,170] = var(123); // [ var(170) , var(42) ] D[43,170] = var(122); // [ var(170) , var(43) ] D[50,170] = (-1)*var(242)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(170) , var(50) ] D[54,170] = var(1); // [ var(170) , var(54) ] D[56,170] = (-1)*var(4); // [ var(170) , var(56) ] D[62,170] = (-1)*var(12); // [ var(170) , var(62) ] D[65,170] = var(16); // [ var(170) , var(65) ] D[68,170] = (-1)*var(20); // [ var(170) , var(68) ] D[72,170] = var(24); // [ var(170) , var(72) ] D[74,170] = (-1)*var(28); // [ var(170) , var(74) ] D[78,170] = var(31); // [ var(170) , var(78) ] D[81,170] = var(37); // [ var(170) , var(81) ] D[84,170] = var(39); // [ var(170) , var(84) ] D[86,170] = var(45); // [ var(170) , var(86) ] D[90,170] = var(52); // [ var(170) , var(90) ] D[91,170] = var(53); // [ var(170) , var(91) ] D[95,170] = var(59); // [ var(170) , var(95) ] D[98,170] = var(63); // [ var(170) , var(98) ] D[100,170] = var(66); // [ var(170) , var(100) ] D[102,170] = var(70); // [ var(170) , var(102) ] D[105,170] = var(76); // [ var(170) , var(105) ] D[108,170] = var(82); // [ var(170) , var(108) ] D[112,170] = var(89); // [ var(170) , var(112) ] D[115,170] = (-1)*var(97); // [ var(170) , var(115) ] D[120,170] = var(111); // [ var(170) , var(120) ] D[3,171] = (-1)*var(165); // [ var(171) , var(3) ] D[6,171] = var(164); // [ var(171) , var(6) ] D[9,171] = var(160); // [ var(171) , var(9) ] D[11,171] = var(158); // [ var(171) , var(11) ] D[16,171] = (-1)*var(153); // [ var(171) , var(16) ] D[17,171] = (-1)*var(151); // [ var(171) , var(17) ] D[23,171] = var(147); // [ var(171) , var(23) ] D[27,171] = (-1)*var(143); // [ var(171) , var(27) ] D[31,171] = var(137); // [ var(171) , var(31) ] D[33,171] = var(136); // [ var(171) , var(33) ] D[38,171] = (-1)*var(131); // [ var(171) , var(38) ] D[40,171] = (-1)*var(129); // [ var(171) , var(40) ] D[44,171] = (-1)*var(126); // [ var(171) , var(44) ] D[45,171] = var(123); // [ var(171) , var(45) ] D[51,171] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-1)*var(245)+(-1)*var(246); // [ var(171) , var(51) ] D[57,171] = (-1)*var(5); // [ var(171) , var(57) ] D[58,171] = (-1)*var(7); // [ var(171) , var(58) ] D[63,171] = var(12); // [ var(171) , var(63) ] D[65,171] = (-1)*var(15); // [ var(171) , var(65) ] D[69,171] = (-1)*var(18); // [ var(171) , var(69) ] D[71,171] = var(21); // [ var(171) , var(71) ] D[76,171] = (-1)*var(28); // [ var(171) , var(76) ] D[78,171] = var(29); // [ var(171) , var(78) ] D[80,171] = var(34); // [ var(171) , var(80) ] D[83,171] = (-1)*var(36); // [ var(171) , var(83) ] D[86,171] = var(42); // [ var(171) , var(86) ] D[93,171] = (-1)*var(55); // [ var(171) , var(93) ] D[97,171] = var(59); // [ var(171) , var(97) ] D[98,171] = (-1)*var(62); // [ var(171) , var(98) ] D[101,171] = var(67); // [ var(171) , var(101) ] D[105,171] = var(74); // [ var(171) , var(105) ] D[107,171] = (-1)*var(79); // [ var(171) , var(107) ] D[114,171] = var(92); // [ var(171) , var(114) ] D[115,171] = (-1)*var(95); // [ var(171) , var(115) ] D[116,171] = var(99); // [ var(171) , var(116) ] D[118,171] = (-1)*var(106); // [ var(171) , var(118) ] D[1,172] = (-1)*var(168); // [ var(172) , var(1) ] D[5,172] = var(165); // [ var(172) , var(5) ] D[12,172] = var(158); // [ var(172) , var(12) ] D[13,172] = (-1)*var(157); // [ var(172) , var(13) ] D[18,172] = (-1)*var(151); // [ var(172) , var(18) ] D[20,172] = (-1)*var(150); // [ var(172) , var(20) ] D[24,172] = (-1)*var(146); // [ var(172) , var(24) ] D[26,172] = var(144); // [ var(172) , var(26) ] D[30,172] = var(140); // [ var(172) , var(30) ] D[31,172] = var(138); // [ var(172) , var(31) ] D[37,172] = var(133); // [ var(172) , var(37) ] D[38,172] = (-1)*var(132); // [ var(172) , var(38) ] D[45,172] = (-1)*var(125); // [ var(172) , var(45) ] D[48,172] = var(121); // [ var(172) , var(48) ] D[52,172] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-1)*var(246); // [ var(172) , var(52) ] D[57,172] = var(3); // [ var(172) , var(57) ] D[59,172] = (-1)*var(7); // [ var(172) , var(59) ] D[63,172] = var(11); // [ var(172) , var(63) ] D[66,172] = var(14); // [ var(172) , var(66) ] D[67,172] = (-1)*var(15); // [ var(172) , var(67) ] D[69,172] = (-1)*var(17); // [ var(172) , var(69) ] D[73,172] = var(22); // [ var(172) , var(73) ] D[82,172] = var(35); // [ var(172) , var(82) ] D[85,172] = (-1)*var(41); // [ var(172) , var(85) ] D[87,172] = var(43); // [ var(172) , var(87) ] D[89,172] = (-1)*var(49); // [ var(172) , var(89) ] D[90,172] = (-1)*var(50); // [ var(172) , var(90) ] D[94,172] = (-1)*var(56); // [ var(172) , var(94) ] D[97,172] = var(58); // [ var(172) , var(97) ] D[101,172] = var(65); // [ var(172) , var(101) ] D[106,172] = (-1)*var(74); // [ var(172) , var(106) ] D[109,172] = var(84); // [ var(172) , var(109) ] D[111,172] = var(88); // [ var(172) , var(111) ] D[113,172] = (-1)*var(91); // [ var(172) , var(113) ] D[117,172] = (-1)*var(102); // [ var(172) , var(117) ] D[118,172] = var(105); // [ var(172) , var(118) ] D[1,173] = (-1)*var(169); // [ var(173) , var(1) ] D[4,173] = var(166); // [ var(173) , var(4) ] D[7,173] = var(165); // [ var(173) , var(7) ] D[10,173] = (-1)*var(159); // [ var(173) , var(10) ] D[14,173] = var(157); // [ var(173) , var(14) ] D[16,173] = (-1)*var(154); // [ var(173) , var(16) ] D[23,173] = var(148); // [ var(173) , var(23) ] D[28,173] = (-1)*var(143); // [ var(173) , var(28) ] D[34,173] = var(136); // [ var(173) , var(34) ] D[37,173] = (-1)*var(134); // [ var(173) , var(37) ] D[39,173] = var(130); // [ var(173) , var(39) ] D[45,173] = (-1)*var(127); // [ var(173) , var(45) ] D[46,173] = (-1)*var(124); // [ var(173) , var(46) ] D[49,173] = var(121); // [ var(173) , var(49) ] D[53,173] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(173) , var(53) ] D[58,173] = var(3); // [ var(173) , var(58) ] D[59,173] = (-1)*var(5); // [ var(173) , var(59) ] D[60,173] = (-1)*var(8); // [ var(173) , var(60) ] D[66,173] = (-1)*var(13); // [ var(173) , var(66) ] D[70,173] = (-1)*var(19); // [ var(173) , var(70) ] D[75,173] = var(25); // [ var(173) , var(75) ] D[76,173] = (-1)*var(27); // [ var(173) , var(76) ] D[79,173] = var(29); // [ var(173) , var(79) ] D[80,173] = var(33); // [ var(173) , var(80) ] D[88,173] = var(43); // [ var(173) , var(88) ] D[89,173] = (-1)*var(48); // [ var(173) , var(89) ] D[91,173] = (-1)*var(50); // [ var(173) , var(91) ] D[97,173] = var(57); // [ var(173) , var(97) ] D[99,173] = var(62); // [ var(173) , var(99) ] D[103,173] = var(68); // [ var(173) , var(103) ] D[104,173] = (-1)*var(72); // [ var(173) , var(104) ] D[107,173] = (-1)*var(78); // [ var(173) , var(107) ] D[111,173] = var(87); // [ var(173) , var(111) ] D[113,173] = (-1)*var(90); // [ var(173) , var(113) ] D[116,173] = (-1)*var(98); // [ var(173) , var(116) ] D[119,173] = var(108); // [ var(173) , var(119) ] D[1,174] = (-1)*var(170); // [ var(174) , var(1) ] D[2,174] = (-1)*var(167); // [ var(174) , var(2) ] D[8,174] = var(166); // [ var(174) , var(8) ] D[9,174] = (-1)*var(162); // [ var(174) , var(9) ] D[15,174] = var(158); // [ var(174) , var(15) ] D[22,174] = var(150); // [ var(174) , var(22) ] D[23,174] = (-1)*var(149); // [ var(174) , var(23) ] D[29,174] = var(143); // [ var(174) , var(29) ] D[30,174] = (-1)*var(142); // [ var(174) , var(30) ] D[38,174] = (-1)*var(135); // [ var(174) , var(38) ] D[42,174] = var(129); // [ var(174) , var(42) ] D[46,174] = (-1)*var(128); // [ var(174) , var(46) ] D[47,174] = var(122); // [ var(174) , var(47) ] D[50,174] = var(121); // [ var(174) , var(50) ] D[54,174] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-1)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(174) , var(54) ] D[60,174] = (-1)*var(4); // [ var(174) , var(60) ] D[65,174] = (-1)*var(11); // [ var(174) , var(65) ] D[67,174] = (-1)*var(12); // [ var(174) , var(67) ] D[72,174] = (-1)*var(19); // [ var(174) , var(72) ] D[73,174] = (-1)*var(20); // [ var(174) , var(73) ] D[78,174] = (-1)*var(27); // [ var(174) , var(78) ] D[79,174] = (-1)*var(28); // [ var(174) , var(79) ] D[81,174] = (-1)*var(32); // [ var(174) , var(81) ] D[84,174] = (-1)*var(35); // [ var(174) , var(84) ] D[86,174] = (-1)*var(40); // [ var(174) , var(86) ] D[90,174] = (-1)*var(48); // [ var(174) , var(90) ] D[91,174] = (-1)*var(49); // [ var(174) , var(91) ] D[95,174] = (-1)*var(55); // [ var(174) , var(95) ] D[100,174] = (-1)*var(61); // [ var(174) , var(100) ] D[101,174] = (-1)*var(63); // [ var(174) , var(101) ] D[104,174] = (-1)*var(70); // [ var(174) , var(104) ] D[107,174] = (-1)*var(76); // [ var(174) , var(107) ] D[109,174] = (-1)*var(82); // [ var(174) , var(109) ] D[113,174] = (-1)*var(89); // [ var(174) , var(113) ] D[115,174] = (-1)*var(93); // [ var(174) , var(115) ] D[120,174] = var(110); // [ var(174) , var(120) ] D[5,175] = var(169); // [ var(175) , var(5) ] D[7,175] = var(168); // [ var(175) , var(7) ] D[12,175] = var(161); // [ var(175) , var(12) ] D[18,175] = (-1)*var(155); // [ var(175) , var(18) ] D[19,175] = (-1)*var(154); // [ var(175) , var(19) ] D[21,175] = (-1)*var(152); // [ var(175) , var(21) ] D[25,175] = var(148); // [ var(175) , var(25) ] D[28,175] = (-1)*var(145); // [ var(175) , var(28) ] D[32,175] = var(141); // [ var(175) , var(32) ] D[34,175] = var(139); // [ var(175) , var(34) ] D[35,175] = var(138); // [ var(175) , var(35) ] D[41,175] = (-1)*var(132); // [ var(175) , var(41) ] D[48,175] = (-1)*var(127); // [ var(175) , var(48) ] D[49,175] = (-1)*var(125); // [ var(175) , var(49) ] D[55,175] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(175) , var(55) ] D[59,175] = var(1); // [ var(175) , var(59) ] D[61,175] = (-1)*var(6); // [ var(175) , var(61) ] D[62,175] = (-1)*var(8); // [ var(175) , var(62) ] D[64,175] = (-1)*var(9); // [ var(175) , var(64) ] D[70,175] = (-1)*var(16); // [ var(175) , var(70) ] D[74,175] = var(22); // [ var(175) , var(74) ] D[75,175] = var(23); // [ var(175) , var(75) ] D[82,175] = var(31); // [ var(175) , var(82) ] D[85,175] = (-1)*var(38); // [ var(175) , var(85) ] D[89,175] = (-1)*var(45); // [ var(175) , var(89) ] D[92,175] = (-1)*var(47); // [ var(175) , var(92) ] D[93,175] = var(51); // [ var(175) , var(93) ] D[95,175] = var(54); // [ var(175) , var(95) ] D[99,175] = var(60); // [ var(175) , var(99) ] D[102,175] = (-1)*var(65); // [ var(175) , var(102) ] D[106,175] = (-1)*var(73); // [ var(175) , var(106) ] D[108,175] = var(78); // [ var(175) , var(108) ] D[110,175] = var(83); // [ var(175) , var(110) ] D[112,175] = (-1)*var(86); // [ var(175) , var(112) ] D[117,175] = var(101); // [ var(175) , var(117) ] D[119,175] = (-1)*var(107); // [ var(175) , var(119) ] D[4,176] = var(170); // [ var(176) , var(4) ] D[8,176] = var(169); // [ var(176) , var(8) ] D[10,176] = (-1)*var(163); // [ var(176) , var(10) ] D[11,176] = (-1)*var(162); // [ var(176) , var(11) ] D[15,176] = var(160); // [ var(176) , var(15) ] D[17,176] = var(156); // [ var(176) , var(17) ] D[22,176] = var(152); // [ var(176) , var(22) ] D[32,176] = (-1)*var(142); // [ var(176) , var(32) ] D[36,176] = (-1)*var(137); // [ var(176) , var(36) ] D[40,176] = (-1)*var(135); // [ var(176) , var(40) ] D[42,176] = var(131); // [ var(176) , var(42) ] D[43,176] = var(130); // [ var(176) , var(43) ] D[49,176] = (-1)*var(128); // [ var(176) , var(49) ] D[50,176] = (-1)*var(124); // [ var(176) , var(50) ] D[56,176] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(176) , var(56) ] D[60,176] = var(1); // [ var(176) , var(60) ] D[62,176] = (-1)*var(5); // [ var(176) , var(62) ] D[65,176] = (-1)*var(9); // [ var(176) , var(65) ] D[68,176] = (-1)*var(13); // [ var(176) , var(68) ] D[74,176] = (-1)*var(21); // [ var(176) , var(74) ] D[77,176] = var(24); // [ var(176) , var(77) ] D[81,176] = (-1)*var(30); // [ var(176) , var(81) ] D[83,176] = var(31); // [ var(176) , var(83) ] D[86,176] = (-1)*var(38); // [ var(176) , var(86) ] D[88,176] = var(39); // [ var(176) , var(88) ] D[91,176] = (-1)*var(46); // [ var(176) , var(91) ] D[94,176] = var(52); // [ var(176) , var(94) ] D[98,176] = (-1)*var(57); // [ var(176) , var(98) ] D[99,176] = var(59); // [ var(176) , var(99) ] D[102,176] = (-1)*var(64); // [ var(176) , var(102) ] D[103,176] = var(66); // [ var(176) , var(103) ] D[105,176] = (-1)*var(71); // [ var(176) , var(105) ] D[110,176] = var(82); // [ var(176) , var(110) ] D[112,176] = (-1)*var(85); // [ var(176) , var(112) ] D[116,176] = var(97); // [ var(176) , var(116) ] D[120,176] = (-1)*var(109); // [ var(176) , var(120) ] D[3,177] = (-1)*var(172); // [ var(177) , var(3) ] D[5,177] = var(171); // [ var(177) , var(5) ] D[9,177] = var(168); // [ var(177) , var(9) ] D[13,177] = (-1)*var(164); // [ var(177) , var(13) ] D[19,177] = var(158); // [ var(177) , var(19) ] D[24,177] = (-1)*var(153); // [ var(177) , var(24) ] D[25,177] = (-1)*var(151); // [ var(177) , var(25) ] D[27,177] = (-1)*var(150); // [ var(177) , var(27) ] D[30,177] = var(147); // [ var(177) , var(30) ] D[31,177] = var(145); // [ var(177) , var(31) ] D[33,177] = var(144); // [ var(177) , var(33) ] D[38,177] = (-1)*var(139); // [ var(177) , var(38) ] D[44,177] = var(133); // [ var(177) , var(44) ] D[48,177] = (-1)*var(129); // [ var(177) , var(48) ] D[51,177] = (-1)*var(125); // [ var(177) , var(51) ] D[52,177] = var(123); // [ var(177) , var(52) ] D[57,177] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-2)*var(245)+(-1)*var(246); // [ var(177) , var(57) ] D[63,177] = (-1)*var(4); // [ var(177) , var(63) ] D[64,177] = (-1)*var(7); // [ var(177) , var(64) ] D[69,177] = var(10); // [ var(177) , var(69) ] D[71,177] = var(14); // [ var(177) , var(71) ] D[72,177] = (-1)*var(15); // [ var(177) , var(72) ] D[78,177] = var(22); // [ var(177) , var(78) ] D[82,177] = (-1)*var(28); // [ var(177) , var(82) ] D[85,177] = var(34); // [ var(177) , var(85) ] D[87,177] = (-1)*var(36); // [ var(177) , var(87) ] D[90,177] = var(42); // [ var(177) , var(90) ] D[93,177] = var(49); // [ var(177) , var(93) ] D[97,177] = (-1)*var(53); // [ var(177) , var(97) ] D[98,177] = var(56); // [ var(177) , var(98) ] D[101,177] = (-1)*var(60); // [ var(177) , var(101) ] D[108,177] = var(74); // [ var(177) , var(108) ] D[109,177] = (-1)*var(79); // [ var(177) , var(109) ] D[114,177] = (-1)*var(88); // [ var(177) , var(114) ] D[115,177] = var(91); // [ var(177) , var(115) ] D[117,177] = (-1)*var(99); // [ var(177) , var(117) ] D[118,177] = var(103); // [ var(177) , var(118) ] D[3,178] = (-1)*var(173); // [ var(178) , var(3) ] D[7,178] = var(171); // [ var(178) , var(7) ] D[9,178] = var(169); // [ var(178) , var(9) ] D[11,178] = var(166); // [ var(178) , var(11) ] D[14,178] = var(164); // [ var(178) , var(14) ] D[16,178] = (-1)*var(161); // [ var(178) , var(16) ] D[17,178] = (-1)*var(159); // [ var(178) , var(17) ] D[23,178] = var(155); // [ var(178) , var(23) ] D[35,178] = (-1)*var(143); // [ var(178) , var(35) ] D[39,178] = var(137); // [ var(178) , var(39) ] D[41,178] = var(136); // [ var(178) , var(41) ] D[44,178] = (-1)*var(134); // [ var(178) , var(44) ] D[46,178] = (-1)*var(131); // [ var(178) , var(46) ] D[49,178] = (-1)*var(129); // [ var(178) , var(49) ] D[51,178] = (-1)*var(127); // [ var(178) , var(51) ] D[53,178] = var(123); // [ var(178) , var(53) ] D[58,178] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(178) , var(58) ] D[64,178] = (-1)*var(5); // [ var(178) , var(64) ] D[65,178] = (-1)*var(8); // [ var(178) , var(65) ] D[70,178] = var(12); // [ var(178) , var(70) ] D[71,178] = (-1)*var(13); // [ var(178) , var(71) ] D[75,178] = (-1)*var(18); // [ var(178) , var(75) ] D[76,178] = var(20); // [ var(178) , var(76) ] D[80,178] = (-1)*var(26); // [ var(178) , var(80) ] D[84,178] = var(29); // [ var(178) , var(84) ] D[88,178] = (-1)*var(36); // [ var(178) , var(88) ] D[91,178] = var(42); // [ var(178) , var(91) ] D[93,178] = var(48); // [ var(178) , var(93) ] D[97,178] = (-1)*var(52); // [ var(178) , var(97) ] D[102,178] = (-1)*var(62); // [ var(178) , var(102) ] D[104,178] = var(67); // [ var(178) , var(104) ] D[105,178] = (-1)*var(68); // [ var(178) , var(105) ] D[107,178] = var(73); // [ var(178) , var(107) ] D[114,178] = (-1)*var(87); // [ var(178) , var(114) ] D[115,178] = var(90); // [ var(178) , var(115) ] D[116,178] = (-1)*var(94); // [ var(178) , var(116) ] D[119,178] = var(106); // [ var(178) , var(119) ] D[1,179] = (-1)*var(175); // [ var(179) , var(1) ] D[5,179] = var(173); // [ var(179) , var(5) ] D[7,179] = var(172); // [ var(179) , var(7) ] D[12,179] = var(166); // [ var(179) , var(12) ] D[18,179] = (-1)*var(159); // [ var(179) , var(18) ] D[21,179] = (-1)*var(157); // [ var(179) , var(21) ] D[24,179] = (-1)*var(154); // [ var(179) , var(24) ] D[28,179] = (-1)*var(150); // [ var(179) , var(28) ] D[30,179] = var(148); // [ var(179) , var(30) ] D[34,179] = var(144); // [ var(179) , var(34) ] D[37,179] = var(141); // [ var(179) , var(37) ] D[39,179] = var(138); // [ var(179) , var(39) ] D[46,179] = (-1)*var(132); // [ var(179) , var(46) ] D[52,179] = (-1)*var(127); // [ var(179) , var(52) ] D[53,179] = (-1)*var(125); // [ var(179) , var(53) ] D[55,179] = var(121); // [ var(179) , var(55) ] D[59,179] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(179) , var(59) ] D[64,179] = var(3); // [ var(179) , var(64) ] D[66,179] = (-1)*var(6); // [ var(179) , var(66) ] D[67,179] = (-1)*var(8); // [ var(179) , var(67) ] D[70,179] = var(11); // [ var(179) , var(70) ] D[75,179] = (-1)*var(17); // [ var(179) , var(75) ] D[79,179] = var(22); // [ var(179) , var(79) ] D[82,179] = (-1)*var(27); // [ var(179) , var(82) ] D[85,179] = var(33); // [ var(179) , var(85) ] D[89,179] = var(40); // [ var(179) , var(89) ] D[92,179] = var(43); // [ var(179) , var(92) ] D[95,179] = (-1)*var(50); // [ var(179) , var(95) ] D[97,179] = (-1)*var(51); // [ var(179) , var(97) ] D[99,179] = (-1)*var(56); // [ var(179) , var(99) ] D[104,179] = var(65); // [ var(179) , var(104) ] D[106,179] = var(68); // [ var(179) , var(106) ] D[109,179] = (-1)*var(78); // [ var(179) , var(109) ] D[111,179] = (-1)*var(83); // [ var(179) , var(111) ] D[113,179] = var(86); // [ var(179) , var(113) ] D[117,179] = var(98); // [ var(179) , var(117) ] D[119,179] = (-1)*var(105); // [ var(179) , var(119) ] D[1,180] = (-1)*var(176); // [ var(180) , var(1) ] D[4,180] = var(174); // [ var(180) , var(4) ] D[8,180] = var(173); // [ var(180) , var(8) ] D[10,180] = (-1)*var(167); // [ var(180) , var(10) ] D[15,180] = var(165); // [ var(180) , var(15) ] D[16,180] = (-1)*var(162); // [ var(180) , var(16) ] D[22,180] = var(157); // [ var(180) , var(22) ] D[23,180] = var(156); // [ var(180) , var(23) ] D[36,180] = (-1)*var(143); // [ var(180) , var(36) ] D[37,180] = (-1)*var(142); // [ var(180) , var(37) ] D[42,180] = var(136); // [ var(180) , var(42) ] D[45,180] = (-1)*var(135); // [ var(180) , var(45) ] D[47,180] = var(130); // [ var(180) , var(47) ] D[53,180] = (-1)*var(128); // [ var(180) , var(53) ] D[54,180] = (-1)*var(124); // [ var(180) , var(54) ] D[56,180] = var(121); // [ var(180) , var(56) ] D[60,180] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(180) , var(60) ] D[65,180] = var(3); // [ var(180) , var(65) ] D[67,180] = (-1)*var(5); // [ var(180) , var(67) ] D[73,180] = (-1)*var(13); // [ var(180) , var(73) ] D[77,180] = (-1)*var(19); // [ var(180) , var(77) ] D[79,180] = (-1)*var(21); // [ var(180) , var(79) ] D[81,180] = var(25); // [ var(180) , var(81) ] D[83,180] = (-1)*var(27); // [ var(180) , var(83) ] D[86,180] = var(33); // [ var(180) , var(86) ] D[88,180] = (-1)*var(35); // [ var(180) , var(88) ] D[91,180] = var(41); // [ var(180) , var(91) ] D[94,180] = (-1)*var(48); // [ var(180) , var(94) ] D[99,180] = (-1)*var(55); // [ var(180) , var(99) ] D[101,180] = var(57); // [ var(180) , var(101) ] D[103,180] = (-1)*var(61); // [ var(180) , var(103) ] D[104,180] = var(64); // [ var(180) , var(104) ] D[107,180] = var(71); // [ var(180) , var(107) ] D[111,180] = (-1)*var(82); // [ var(180) , var(111) ] D[113,180] = var(85); // [ var(180) , var(113) ] D[116,180] = var(93); // [ var(180) , var(116) ] D[120,180] = (-1)*var(108); // [ var(180) , var(120) ] D[6,181] = var(175); // [ var(181) , var(6) ] D[13,181] = var(169); // [ var(181) , var(13) ] D[14,181] = (-1)*var(168); // [ var(181) , var(14) ] D[20,181] = var(161); // [ var(181) , var(20) ] D[21,181] = (-1)*var(160); // [ var(181) , var(21) ] D[26,181] = (-1)*var(155); // [ var(181) , var(26) ] D[27,181] = (-1)*var(154); // [ var(181) , var(27) ] D[28,181] = (-1)*var(153); // [ var(181) , var(28) ] D[33,181] = var(148); // [ var(181) , var(33) ] D[34,181] = var(147); // [ var(181) , var(34) ] D[35,181] = var(146); // [ var(181) , var(35) ] D[40,181] = var(141); // [ var(181) , var(40) ] D[41,181] = (-1)*var(140); // [ var(181) , var(41) ] D[48,181] = var(134); // [ var(181) , var(48) ] D[49,181] = (-1)*var(133); // [ var(181) , var(49) ] D[55,181] = (-1)*var(126); // [ var(181) , var(55) ] D[61,181] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(181) , var(61) ] D[66,181] = var(1); // [ var(181) , var(66) ] D[68,181] = (-1)*var(8); // [ var(181) , var(68) ] D[71,181] = (-1)*var(9); // [ var(181) , var(71) ] D[74,181] = var(15); // [ var(181) , var(74) ] D[76,181] = (-1)*var(16); // [ var(181) , var(76) ] D[80,181] = var(23); // [ var(181) , var(80) ] D[82,181] = (-1)*var(24); // [ var(181) , var(82) ] D[85,181] = var(30); // [ var(181) , var(85) ] D[89,181] = var(37); // [ var(181) , var(89) ] D[93,181] = (-1)*var(44); // [ var(181) , var(93) ] D[96,181] = (-1)*var(47); // [ var(181) , var(96) ] D[100,181] = var(54); // [ var(181) , var(100) ] D[103,181] = var(60); // [ var(181) , var(103) ] D[105,181] = (-1)*var(65); // [ var(181) , var(105) ] D[106,181] = var(67); // [ var(181) , var(106) ] D[108,181] = (-1)*var(72); // [ var(181) , var(108) ] D[110,181] = (-1)*var(77); // [ var(181) , var(110) ] D[112,181] = var(81); // [ var(181) , var(112) ] D[118,181] = (-1)*var(101); // [ var(181) , var(118) ] D[119,181] = var(104); // [ var(181) , var(119) ] D[5,182] = var(176); // [ var(182) , var(5) ] D[8,182] = var(175); // [ var(182) , var(8) ] D[12,182] = var(170); // [ var(182) , var(12) ] D[15,182] = var(168); // [ var(182) , var(15) ] D[18,182] = (-1)*var(163); // [ var(182) , var(18) ] D[19,182] = (-1)*var(162); // [ var(182) , var(19) ] D[25,182] = var(156); // [ var(182) , var(25) ] D[29,182] = (-1)*var(152); // [ var(182) , var(29) ] D[32,182] = var(149); // [ var(182) , var(32) ] D[36,182] = (-1)*var(145); // [ var(182) , var(36) ] D[42,182] = var(139); // [ var(182) , var(42) ] D[43,182] = var(138); // [ var(182) , var(43) ] D[48,182] = (-1)*var(135); // [ var(182) , var(48) ] D[50,182] = (-1)*var(132); // [ var(182) , var(50) ] D[55,182] = (-1)*var(128); // [ var(182) , var(55) ] D[56,182] = (-1)*var(125); // [ var(182) , var(56) ] D[62,182] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(182) , var(62) ] D[67,182] = var(1); // [ var(182) , var(67) ] D[68,182] = (-1)*var(6); // [ var(182) , var(68) ] D[72,182] = (-1)*var(9); // [ var(182) , var(72) ] D[74,182] = (-1)*var(14); // [ var(182) , var(74) ] D[77,182] = (-1)*var(16); // [ var(182) , var(77) ] D[81,182] = var(23); // [ var(182) , var(81) ] D[87,182] = var(31); // [ var(182) , var(87) ] D[90,182] = (-1)*var(38); // [ var(182) , var(90) ] D[92,182] = var(39); // [ var(182) , var(92) ] D[94,182] = (-1)*var(45); // [ var(182) , var(94) ] D[95,182] = (-1)*var(46); // [ var(182) , var(95) ] D[98,182] = var(51); // [ var(182) , var(98) ] D[99,182] = (-1)*var(53); // [ var(182) , var(99) ] D[102,182] = var(58); // [ var(182) , var(102) ] D[106,182] = var(66); // [ var(182) , var(106) ] D[108,182] = (-1)*var(71); // [ var(182) , var(108) ] D[110,182] = (-1)*var(76); // [ var(182) , var(110) ] D[112,182] = var(80); // [ var(182) , var(112) ] D[117,182] = (-1)*var(97); // [ var(182) , var(117) ] D[120,182] = var(107); // [ var(182) , var(120) ] D[4,183] = var(177); // [ var(183) , var(4) ] D[11,183] = (-1)*var(172); // [ var(183) , var(11) ] D[12,183] = (-1)*var(171); // [ var(183) , var(12) ] D[16,183] = var(168); // [ var(183) , var(16) ] D[19,183] = var(165); // [ var(183) , var(19) ] D[20,183] = var(164); // [ var(183) , var(20) ] D[24,183] = (-1)*var(160); // [ var(183) , var(24) ] D[27,183] = (-1)*var(157); // [ var(183) , var(27) ] D[31,183] = var(152); // [ var(183) , var(31) ] D[32,183] = (-1)*var(151); // [ var(183) , var(32) ] D[37,183] = var(147); // [ var(183) , var(37) ] D[40,183] = var(144); // [ var(183) , var(40) ] D[44,183] = (-1)*var(140); // [ var(183) , var(44) ] D[45,183] = (-1)*var(139); // [ var(183) , var(45) ] D[48,183] = (-1)*var(136); // [ var(183) , var(48) ] D[51,183] = var(132); // [ var(183) , var(51) ] D[52,183] = var(131); // [ var(183) , var(52) ] D[57,183] = (-1)*var(124); // [ var(183) , var(57) ] D[63,183] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-1)*var(246); // [ var(183) , var(63) ] D[69,183] = (-1)*var(2); // [ var(183) , var(69) ] D[70,183] = (-1)*var(7); // [ var(183) , var(70) ] D[76,183] = var(14); // [ var(183) , var(76) ] D[77,183] = (-1)*var(15); // [ var(183) , var(77) ] D[82,183] = (-1)*var(21); // [ var(183) , var(82) ] D[83,183] = var(22); // [ var(183) , var(83) ] D[87,183] = (-1)*var(29); // [ var(183) , var(87) ] D[89,183] = var(34); // [ var(183) , var(89) ] D[93,183] = (-1)*var(41); // [ var(183) , var(93) ] D[94,183] = var(42); // [ var(183) , var(94) ] D[97,183] = var(46); // [ var(183) , var(97) ] D[98,183] = (-1)*var(50); // [ var(183) , var(98) ] D[101,183] = var(54); // [ var(183) , var(101) ] D[110,183] = var(74); // [ var(183) , var(110) ] D[111,183] = (-1)*var(79); // [ var(183) , var(111) ] D[114,183] = var(84); // [ var(183) , var(114) ] D[116,183] = (-1)*var(91); // [ var(183) , var(116) ] D[117,183] = var(95); // [ var(183) , var(117) ] D[118,183] = (-1)*var(100); // [ var(183) , var(118) ] D[3,184] = (-1)*var(179); // [ var(184) , var(3) ] D[5,184] = var(178); // [ var(184) , var(5) ] D[7,184] = var(177); // [ var(184) , var(7) ] D[9,184] = var(175); // [ var(184) , var(9) ] D[19,184] = var(166); // [ var(184) , var(19) ] D[21,184] = (-1)*var(164); // [ var(184) , var(21) ] D[24,184] = (-1)*var(161); // [ var(184) , var(24) ] D[25,184] = (-1)*var(159); // [ var(184) , var(25) ] D[30,184] = var(155); // [ var(184) , var(30) ] D[35,184] = (-1)*var(150); // [ var(184) , var(35) ] D[39,184] = var(145); // [ var(184) , var(39) ] D[41,184] = var(144); // [ var(184) , var(41) ] D[44,184] = var(141); // [ var(184) , var(44) ] D[46,184] = (-1)*var(139); // [ var(184) , var(46) ] D[55,184] = (-1)*var(129); // [ var(184) , var(55) ] D[57,184] = (-1)*var(127); // [ var(184) , var(57) ] D[58,184] = (-1)*var(125); // [ var(184) , var(58) ] D[59,184] = var(123); // [ var(184) , var(59) ] D[64,184] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(184) , var(64) ] D[70,184] = (-1)*var(4); // [ var(184) , var(70) ] D[71,184] = (-1)*var(6); // [ var(184) , var(71) ] D[72,184] = (-1)*var(8); // [ var(184) , var(72) ] D[75,184] = var(10); // [ var(184) , var(75) ] D[82,184] = var(20); // [ var(184) , var(82) ] D[84,184] = var(22); // [ var(184) , var(84) ] D[85,184] = (-1)*var(26); // [ var(184) , var(85) ] D[92,184] = (-1)*var(36); // [ var(184) , var(92) ] D[93,184] = (-1)*var(40); // [ var(184) , var(93) ] D[95,184] = var(42); // [ var(184) , var(95) ] D[97,184] = var(45); // [ var(184) , var(97) ] D[102,184] = var(56); // [ var(184) , var(102) ] D[104,184] = (-1)*var(60); // [ var(184) , var(104) ] D[108,184] = (-1)*var(68); // [ var(184) , var(108) ] D[109,184] = var(73); // [ var(184) , var(109) ] D[114,184] = var(83); // [ var(184) , var(114) ] D[115,184] = (-1)*var(86); // [ var(184) , var(115) ] D[117,184] = var(94); // [ var(184) , var(117) ] D[119,184] = (-1)*var(103); // [ var(184) , var(119) ] D[3,185] = (-1)*var(180); // [ var(185) , var(3) ] D[8,185] = var(178); // [ var(185) , var(8) ] D[9,185] = var(176); // [ var(185) , var(9) ] D[11,185] = var(174); // [ var(185) , var(11) ] D[15,185] = var(171); // [ var(185) , var(15) ] D[16,185] = (-1)*var(170); // [ var(185) , var(16) ] D[17,185] = (-1)*var(167); // [ var(185) , var(17) ] D[22,185] = var(164); // [ var(185) , var(22) ] D[23,185] = var(163); // [ var(185) , var(23) ] D[43,185] = (-1)*var(143); // [ var(185) , var(43) ] D[44,185] = (-1)*var(142); // [ var(185) , var(44) ] D[47,185] = var(137); // [ var(185) , var(47) ] D[50,185] = var(136); // [ var(185) , var(50) ] D[51,185] = (-1)*var(135); // [ var(185) , var(51) ] D[54,185] = (-1)*var(131); // [ var(185) , var(54) ] D[56,185] = (-1)*var(129); // [ var(185) , var(56) ] D[58,185] = (-1)*var(128); // [ var(185) , var(58) ] D[60,185] = var(123); // [ var(185) , var(60) ] D[65,185] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-1)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(185) , var(65) ] D[72,185] = (-1)*var(5); // [ var(185) , var(72) ] D[77,185] = var(12); // [ var(185) , var(77) ] D[78,185] = (-1)*var(13); // [ var(185) , var(78) ] D[81,185] = (-1)*var(18); // [ var(185) , var(81) ] D[83,185] = var(20); // [ var(185) , var(83) ] D[84,185] = (-1)*var(21); // [ var(185) , var(84) ] D[86,185] = (-1)*var(26); // [ var(185) , var(86) ] D[88,185] = var(28); // [ var(185) , var(88) ] D[91,185] = (-1)*var(34); // [ var(185) , var(91) ] D[98,185] = var(48); // [ var(185) , var(98) ] D[101,185] = (-1)*var(52); // [ var(185) , var(101) ] D[102,185] = var(55); // [ var(185) , var(102) ] D[104,185] = (-1)*var(59); // [ var(185) , var(104) ] D[105,185] = var(61); // [ var(185) , var(105) ] D[107,185] = (-1)*var(66); // [ var(185) , var(107) ] D[114,185] = var(82); // [ var(185) , var(114) ] D[115,185] = (-1)*var(85); // [ var(185) , var(115) ] D[116,185] = var(89); // [ var(185) , var(116) ] D[120,185] = (-1)*var(106); // [ var(185) , var(120) ] D[1,186] = (-1)*var(181); // [ var(186) , var(1) ] D[6,186] = var(179); // [ var(186) , var(6) ] D[13,186] = var(173); // [ var(186) , var(13) ] D[14,186] = (-1)*var(172); // [ var(186) , var(14) ] D[20,186] = var(166); // [ var(186) , var(20) ] D[21,186] = (-1)*var(165); // [ var(186) , var(21) ] D[26,186] = (-1)*var(159); // [ var(186) , var(26) ] D[28,186] = (-1)*var(158); // [ var(186) , var(28) ] D[31,186] = (-1)*var(154); // [ var(186) , var(31) ] D[34,186] = var(151); // [ var(186) , var(34) ] D[38,186] = var(148); // [ var(186) , var(38) ] D[39,186] = var(146); // [ var(186) , var(39) ] D[45,186] = var(141); // [ var(186) , var(45) ] D[46,186] = (-1)*var(140); // [ var(186) , var(46) ] D[52,186] = var(134); // [ var(186) , var(52) ] D[53,186] = (-1)*var(133); // [ var(186) , var(53) ] D[59,186] = (-1)*var(126); // [ var(186) , var(59) ] D[61,186] = var(121); // [ var(186) , var(61) ] D[66,186] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(186) , var(66) ] D[71,186] = var(3); // [ var(186) , var(71) ] D[73,186] = (-1)*var(8); // [ var(186) , var(73) ] D[76,186] = var(11); // [ var(186) , var(76) ] D[79,186] = var(15); // [ var(186) , var(79) ] D[80,186] = (-1)*var(17); // [ var(186) , var(80) ] D[82,186] = var(19); // [ var(186) , var(82) ] D[85,186] = (-1)*var(25); // [ var(186) , var(85) ] D[89,186] = (-1)*var(32); // [ var(186) , var(89) ] D[96,186] = var(43); // [ var(186) , var(96) ] D[97,186] = var(44); // [ var(186) , var(97) ] D[100,186] = (-1)*var(50); // [ var(186) , var(100) ] D[103,186] = (-1)*var(56); // [ var(186) , var(103) ] D[106,186] = (-1)*var(62); // [ var(186) , var(106) ] D[107,186] = var(65); // [ var(186) , var(107) ] D[109,186] = var(72); // [ var(186) , var(109) ] D[111,186] = var(77); // [ var(186) , var(111) ] D[113,186] = (-1)*var(81); // [ var(186) , var(113) ] D[118,186] = (-1)*var(98); // [ var(186) , var(118) ] D[119,186] = var(102); // [ var(186) , var(119) ] D[1,187] = (-1)*var(182); // [ var(187) , var(1) ] D[5,187] = var(180); // [ var(187) , var(5) ] D[8,187] = var(179); // [ var(187) , var(8) ] D[12,187] = var(174); // [ var(187) , var(12) ] D[15,187] = var(172); // [ var(187) , var(15) ] D[18,187] = (-1)*var(167); // [ var(187) , var(18) ] D[24,187] = (-1)*var(162); // [ var(187) , var(24) ] D[29,187] = (-1)*var(157); // [ var(187) , var(29) ] D[30,187] = var(156); // [ var(187) , var(30) ] D[36,187] = (-1)*var(150); // [ var(187) , var(36) ] D[37,187] = var(149); // [ var(187) , var(37) ] D[42,187] = var(144); // [ var(187) , var(42) ] D[47,187] = var(138); // [ var(187) , var(47) ] D[52,187] = (-1)*var(135); // [ var(187) , var(52) ] D[54,187] = (-1)*var(132); // [ var(187) , var(54) ] D[59,187] = (-1)*var(128); // [ var(187) , var(59) ] D[60,187] = (-1)*var(125); // [ var(187) , var(60) ] D[62,187] = var(121); // [ var(187) , var(62) ] D[67,187] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(187) , var(67) ] D[72,187] = var(3); // [ var(187) , var(72) ] D[73,187] = (-1)*var(6); // [ var(187) , var(73) ] D[77,187] = var(11); // [ var(187) , var(77) ] D[79,187] = (-1)*var(14); // [ var(187) , var(79) ] D[81,187] = (-1)*var(17); // [ var(187) , var(81) ] D[87,187] = (-1)*var(27); // [ var(187) , var(87) ] D[90,187] = var(33); // [ var(187) , var(90) ] D[92,187] = (-1)*var(35); // [ var(187) , var(92) ] D[94,187] = var(40); // [ var(187) , var(94) ] D[95,187] = var(41); // [ var(187) , var(95) ] D[99,187] = var(49); // [ var(187) , var(99) ] D[101,187] = (-1)*var(51); // [ var(187) , var(101) ] D[104,187] = (-1)*var(58); // [ var(187) , var(104) ] D[106,187] = (-1)*var(61); // [ var(187) , var(106) ] D[109,187] = var(71); // [ var(187) , var(109) ] D[111,187] = var(76); // [ var(187) , var(111) ] D[113,187] = (-1)*var(80); // [ var(187) , var(113) ] D[117,187] = (-1)*var(93); // [ var(187) , var(117) ] D[120,187] = var(105); // [ var(187) , var(120) ] D[6,188] = var(182); // [ var(188) , var(6) ] D[8,188] = var(181); // [ var(188) , var(8) ] D[13,188] = var(176); // [ var(188) , var(13) ] D[20,188] = var(170); // [ var(188) , var(20) ] D[22,188] = (-1)*var(168); // [ var(188) , var(22) ] D[26,188] = (-1)*var(163); // [ var(188) , var(26) ] D[27,188] = (-1)*var(162); // [ var(188) , var(27) ] D[29,188] = (-1)*var(160); // [ var(188) , var(29) ] D[33,188] = var(156); // [ var(188) , var(33) ] D[36,188] = (-1)*var(153); // [ var(188) , var(36) ] D[40,188] = var(149); // [ var(188) , var(40) ] D[42,188] = var(147); // [ var(188) , var(42) ] D[43,188] = var(146); // [ var(188) , var(43) ] D[48,188] = var(142); // [ var(188) , var(48) ] D[50,188] = (-1)*var(140); // [ var(188) , var(50) ] D[56,188] = (-1)*var(133); // [ var(188) , var(56) ] D[61,188] = (-1)*var(128); // [ var(188) , var(61) ] D[62,188] = (-1)*var(126); // [ var(188) , var(62) ] D[68,188] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(188) , var(68) ] D[73,188] = var(1); // [ var(188) , var(73) ] D[74,188] = (-1)*var(7); // [ var(188) , var(74) ] D[78,188] = (-1)*var(9); // [ var(188) , var(78) ] D[83,188] = (-1)*var(16); // [ var(188) , var(83) ] D[86,188] = var(23); // [ var(188) , var(86) ] D[87,188] = (-1)*var(24); // [ var(188) , var(87) ] D[90,188] = var(30); // [ var(188) , var(90) ] D[94,188] = var(37); // [ var(188) , var(94) ] D[96,188] = var(39); // [ var(188) , var(96) ] D[98,188] = (-1)*var(44); // [ var(188) , var(98) ] D[100,188] = (-1)*var(46); // [ var(188) , var(100) ] D[103,188] = (-1)*var(53); // [ var(188) , var(103) ] D[105,188] = var(58); // [ var(188) , var(105) ] D[106,188] = (-1)*var(59); // [ var(188) , var(106) ] D[108,188] = var(64); // [ var(188) , var(108) ] D[110,188] = var(70); // [ var(188) , var(110) ] D[112,188] = (-1)*var(75); // [ var(188) , var(112) ] D[118,188] = var(97); // [ var(188) , var(118) ] D[120,188] = (-1)*var(104); // [ var(188) , var(120) ] D[2,189] = var(183); // [ var(189) , var(2) ] D[10,189] = (-1)*var(177); // [ var(189) , var(10) ] D[17,189] = var(172); // [ var(189) , var(17) ] D[18,189] = var(171); // [ var(189) , var(18) ] D[23,189] = (-1)*var(168); // [ var(189) , var(23) ] D[25,189] = (-1)*var(165); // [ var(189) , var(25) ] D[26,189] = (-1)*var(164); // [ var(189) , var(26) ] D[30,189] = var(160); // [ var(189) , var(30) ] D[32,189] = var(158); // [ var(189) , var(32) ] D[33,189] = var(157); // [ var(189) , var(33) ] D[37,189] = (-1)*var(153); // [ var(189) , var(37) ] D[38,189] = (-1)*var(152); // [ var(189) , var(38) ] D[40,189] = (-1)*var(150); // [ var(189) , var(40) ] D[44,189] = var(146); // [ var(189) , var(44) ] D[45,189] = var(145); // [ var(189) , var(45) ] D[48,189] = var(143); // [ var(189) , var(48) ] D[51,189] = (-1)*var(138); // [ var(189) , var(51) ] D[52,189] = (-1)*var(137); // [ var(189) , var(52) ] D[57,189] = var(130); // [ var(189) , var(57) ] D[63,189] = (-1)*var(122); // [ var(189) , var(63) ] D[69,189] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-1)*var(246); // [ var(189) , var(69) ] D[75,189] = (-1)*var(7); // [ var(189) , var(75) ] D[80,189] = var(14); // [ var(189) , var(80) ] D[81,189] = (-1)*var(15); // [ var(189) , var(81) ] D[85,189] = (-1)*var(21); // [ var(189) , var(85) ] D[86,189] = var(22); // [ var(189) , var(86) ] D[89,189] = var(28); // [ var(189) , var(89) ] D[90,189] = (-1)*var(29); // [ var(189) , var(90) ] D[93,189] = (-1)*var(35); // [ var(189) , var(93) ] D[94,189] = var(36); // [ var(189) , var(94) ] D[97,189] = var(39); // [ var(189) , var(97) ] D[98,189] = (-1)*var(43); // [ var(189) , var(98) ] D[101,189] = var(47); // [ var(189) , var(101) ] D[112,189] = (-1)*var(74); // [ var(189) , var(112) ] D[113,189] = var(79); // [ var(189) , var(113) ] D[115,189] = (-1)*var(84); // [ var(189) , var(115) ] D[116,189] = var(88); // [ var(189) , var(116) ] D[117,189] = (-1)*var(92); // [ var(189) , var(117) ] D[118,189] = var(96); // [ var(189) , var(118) ] D[4,190] = var(184); // [ var(190) , var(4) ] D[7,190] = var(183); // [ var(190) , var(7) ] D[11,190] = (-1)*var(179); // [ var(190) , var(11) ] D[12,190] = (-1)*var(178); // [ var(190) , var(12) ] D[16,190] = var(175); // [ var(190) , var(16) ] D[19,190] = var(173); // [ var(190) , var(19) ] D[24,190] = (-1)*var(169); // [ var(190) , var(24) ] D[28,190] = var(164); // [ var(190) , var(28) ] D[32,190] = (-1)*var(159); // [ var(190) , var(32) ] D[35,190] = (-1)*var(157); // [ var(190) , var(35) ] D[37,190] = var(155); // [ var(190) , var(37) ] D[39,190] = var(152); // [ var(190) , var(39) ] D[44,190] = (-1)*var(148); // [ var(190) , var(44) ] D[49,190] = var(144); // [ var(190) , var(49) ] D[53,190] = (-1)*var(139); // [ var(190) , var(53) ] D[55,190] = (-1)*var(136); // [ var(190) , var(55) ] D[58,190] = var(132); // [ var(190) , var(58) ] D[59,190] = var(131); // [ var(190) , var(59) ] D[63,190] = (-1)*var(127); // [ var(190) , var(63) ] D[64,190] = (-1)*var(124); // [ var(190) , var(64) ] D[70,190] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(190) , var(70) ] D[75,190] = (-1)*var(2); // [ var(190) , var(75) ] D[76,190] = (-1)*var(6); // [ var(190) , var(76) ] D[77,190] = (-1)*var(8); // [ var(190) , var(77) ] D[82,190] = var(13); // [ var(190) , var(82) ] D[88,190] = var(22); // [ var(190) , var(88) ] D[89,190] = (-1)*var(26); // [ var(190) , var(89) ] D[92,190] = (-1)*var(29); // [ var(190) , var(92) ] D[93,190] = var(33); // [ var(190) , var(93) ] D[97,190] = (-1)*var(38); // [ var(190) , var(97) ] D[99,190] = var(42); // [ var(190) , var(99) ] D[102,190] = (-1)*var(50); // [ var(190) , var(102) ] D[104,190] = var(54); // [ var(190) , var(104) ] D[110,190] = (-1)*var(68); // [ var(190) , var(110) ] D[111,190] = var(73); // [ var(190) , var(111) ] D[114,190] = (-1)*var(78); // [ var(190) , var(114) ] D[116,190] = var(86); // [ var(190) , var(116) ] D[117,190] = (-1)*var(90); // [ var(190) , var(117) ] D[119,190] = var(100); // [ var(190) , var(119) ] D[3,191] = (-1)*var(186); // [ var(191) , var(3) ] D[6,191] = var(184); // [ var(191) , var(6) ] D[9,191] = var(181); // [ var(191) , var(9) ] D[13,191] = var(178); // [ var(191) , var(13) ] D[14,191] = (-1)*var(177); // [ var(191) , var(14) ] D[21,191] = (-1)*var(171); // [ var(191) , var(21) ] D[27,191] = var(166); // [ var(191) , var(27) ] D[31,191] = (-1)*var(161); // [ var(191) , var(31) ] D[33,191] = (-1)*var(159); // [ var(191) , var(33) ] D[35,191] = (-1)*var(158); // [ var(191) , var(35) ] D[38,191] = var(155); // [ var(191) , var(38) ] D[39,191] = var(153); // [ var(191) , var(39) ] D[41,191] = var(151); // [ var(191) , var(41) ] D[46,191] = (-1)*var(147); // [ var(191) , var(46) ] D[51,191] = var(141); // [ var(191) , var(51) ] D[57,191] = var(134); // [ var(191) , var(57) ] D[58,191] = (-1)*var(133); // [ var(191) , var(58) ] D[61,191] = (-1)*var(129); // [ var(191) , var(61) ] D[64,191] = (-1)*var(126); // [ var(191) , var(64) ] D[66,191] = var(123); // [ var(191) , var(66) ] D[71,191] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(191) , var(71) ] D[76,191] = (-1)*var(4); // [ var(191) , var(76) ] D[78,191] = (-1)*var(8); // [ var(191) , var(78) ] D[80,191] = var(10); // [ var(191) , var(80) ] D[82,191] = (-1)*var(12); // [ var(191) , var(82) ] D[84,191] = var(15); // [ var(191) , var(84) ] D[85,191] = var(18); // [ var(191) , var(85) ] D[93,191] = var(32); // [ var(191) , var(93) ] D[96,191] = (-1)*var(36); // [ var(191) , var(96) ] D[97,191] = (-1)*var(37); // [ var(191) , var(97) ] D[100,191] = var(42); // [ var(191) , var(100) ] D[105,191] = var(56); // [ var(191) , var(105) ] D[107,191] = (-1)*var(60); // [ var(191) , var(107) ] D[108,191] = var(62); // [ var(191) , var(108) ] D[109,191] = (-1)*var(67); // [ var(191) , var(109) ] D[114,191] = (-1)*var(77); // [ var(191) , var(114) ] D[115,191] = var(81); // [ var(191) , var(115) ] D[118,191] = (-1)*var(94); // [ var(191) , var(118) ] D[119,191] = var(99); // [ var(191) , var(119) ] D[3,192] = (-1)*var(187); // [ var(192) , var(3) ] D[5,192] = var(185); // [ var(192) , var(5) ] D[8,192] = var(184); // [ var(192) , var(8) ] D[9,192] = var(182); // [ var(192) , var(9) ] D[15,192] = var(177); // [ var(192) , var(15) ] D[19,192] = var(174); // [ var(192) , var(19) ] D[24,192] = (-1)*var(170); // [ var(192) , var(24) ] D[25,192] = (-1)*var(167); // [ var(192) , var(25) ] D[29,192] = (-1)*var(164); // [ var(192) , var(29) ] D[30,192] = var(163); // [ var(192) , var(30) ] D[43,192] = (-1)*var(150); // [ var(192) , var(43) ] D[44,192] = var(149); // [ var(192) , var(44) ] D[47,192] = var(145); // [ var(192) , var(47) ] D[50,192] = var(144); // [ var(192) , var(50) ] D[54,192] = (-1)*var(139); // [ var(192) , var(54) ] D[57,192] = (-1)*var(135); // [ var(192) , var(57) ] D[62,192] = (-1)*var(129); // [ var(192) , var(62) ] D[64,192] = (-1)*var(128); // [ var(192) , var(64) ] D[65,192] = (-1)*var(125); // [ var(192) , var(65) ] D[67,192] = var(123); // [ var(192) , var(67) ] D[72,192] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(192) , var(72) ] D[77,192] = (-1)*var(4); // [ var(192) , var(77) ] D[78,192] = (-1)*var(6); // [ var(192) , var(78) ] D[81,192] = var(10); // [ var(192) , var(81) ] D[84,192] = (-1)*var(14); // [ var(192) , var(84) ] D[87,192] = var(20); // [ var(192) , var(87) ] D[90,192] = (-1)*var(26); // [ var(192) , var(90) ] D[92,192] = var(28); // [ var(192) , var(92) ] D[95,192] = (-1)*var(34); // [ var(192) , var(95) ] D[98,192] = (-1)*var(40); // [ var(192) , var(98) ] D[101,192] = var(45); // [ var(192) , var(101) ] D[102,192] = (-1)*var(49); // [ var(192) , var(102) ] D[104,192] = var(53); // [ var(192) , var(104) ] D[108,192] = var(61); // [ var(192) , var(108) ] D[109,192] = (-1)*var(66); // [ var(192) , var(109) ] D[114,192] = (-1)*var(76); // [ var(192) , var(114) ] D[115,192] = var(80); // [ var(192) , var(115) ] D[117,192] = (-1)*var(89); // [ var(192) , var(117) ] D[120,192] = var(103); // [ var(192) , var(120) ] D[1,193] = (-1)*var(188); // [ var(193) , var(1) ] D[6,193] = var(187); // [ var(193) , var(6) ] D[8,193] = var(186); // [ var(193) , var(8) ] D[13,193] = var(180); // [ var(193) , var(13) ] D[20,193] = var(174); // [ var(193) , var(20) ] D[22,193] = (-1)*var(172); // [ var(193) , var(22) ] D[26,193] = (-1)*var(167); // [ var(193) , var(26) ] D[29,193] = (-1)*var(165); // [ var(193) , var(29) ] D[31,193] = (-1)*var(162); // [ var(193) , var(31) ] D[36,193] = (-1)*var(158); // [ var(193) , var(36) ] D[38,193] = var(156); // [ var(193) , var(38) ] D[42,193] = var(151); // [ var(193) , var(42) ] D[45,193] = var(149); // [ var(193) , var(45) ] D[47,193] = var(146); // [ var(193) , var(47) ] D[52,193] = var(142); // [ var(193) , var(52) ] D[54,193] = (-1)*var(140); // [ var(193) , var(54) ] D[60,193] = (-1)*var(133); // [ var(193) , var(60) ] D[66,193] = (-1)*var(128); // [ var(193) , var(66) ] D[67,193] = (-1)*var(126); // [ var(193) , var(67) ] D[68,193] = var(121); // [ var(193) , var(68) ] D[73,193] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(193) , var(73) ] D[78,193] = var(3); // [ var(193) , var(78) ] D[79,193] = (-1)*var(7); // [ var(193) , var(79) ] D[83,193] = var(11); // [ var(193) , var(83) ] D[86,193] = (-1)*var(17); // [ var(193) , var(86) ] D[87,193] = var(19); // [ var(193) , var(87) ] D[90,193] = (-1)*var(25); // [ var(193) , var(90) ] D[94,193] = (-1)*var(32); // [ var(193) , var(94) ] D[96,193] = (-1)*var(35); // [ var(193) , var(96) ] D[100,193] = var(41); // [ var(193) , var(100) ] D[101,193] = var(44); // [ var(193) , var(101) ] D[103,193] = var(49); // [ var(193) , var(103) ] D[106,193] = var(55); // [ var(193) , var(106) ] D[107,193] = (-1)*var(58); // [ var(193) , var(107) ] D[109,193] = (-1)*var(64); // [ var(193) , var(109) ] D[111,193] = (-1)*var(70); // [ var(193) , var(111) ] D[113,193] = var(75); // [ var(193) , var(113) ] D[118,193] = var(93); // [ var(193) , var(118) ] D[120,193] = (-1)*var(102); // [ var(193) , var(120) ] D[7,194] = var(188); // [ var(194) , var(7) ] D[14,194] = var(182); // [ var(194) , var(14) ] D[15,194] = (-1)*var(181); // [ var(194) , var(15) ] D[21,194] = var(176); // [ var(194) , var(21) ] D[22,194] = (-1)*var(175); // [ var(194) , var(22) ] D[28,194] = var(170); // [ var(194) , var(28) ] D[29,194] = (-1)*var(169); // [ var(194) , var(29) ] D[34,194] = (-1)*var(163); // [ var(194) , var(34) ] D[35,194] = (-1)*var(162); // [ var(194) , var(35) ] D[36,194] = (-1)*var(161); // [ var(194) , var(36) ] D[41,194] = var(156); // [ var(194) , var(41) ] D[42,194] = var(155); // [ var(194) , var(42) ] D[43,194] = var(154); // [ var(194) , var(43) ] D[49,194] = var(149); // [ var(194) , var(49) ] D[50,194] = (-1)*var(148); // [ var(194) , var(50) ] D[55,194] = var(142); // [ var(194) , var(55) ] D[56,194] = (-1)*var(141); // [ var(194) , var(56) ] D[61,194] = var(135); // [ var(194) , var(61) ] D[62,194] = (-1)*var(134); // [ var(194) , var(62) ] D[68,194] = (-1)*var(127); // [ var(194) , var(68) ] D[74,194] = (-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(194) , var(74) ] D[79,194] = var(1); // [ var(194) , var(79) ] D[84,194] = (-1)*var(9); // [ var(194) , var(84) ] D[88,194] = (-1)*var(16); // [ var(194) , var(88) ] D[91,194] = var(23); // [ var(194) , var(91) ] D[92,194] = (-1)*var(24); // [ var(194) , var(92) ] D[95,194] = var(30); // [ var(194) , var(95) ] D[96,194] = (-1)*var(31); // [ var(194) , var(96) ] D[99,194] = var(37); // [ var(194) , var(99) ] D[100,194] = var(38); // [ var(194) , var(100) ] D[102,194] = (-1)*var(44); // [ var(194) , var(102) ] D[103,194] = var(45); // [ var(194) , var(103) ] D[105,194] = (-1)*var(51); // [ var(194) , var(105) ] D[106,194] = var(52); // [ var(194) , var(106) ] D[108,194] = (-1)*var(57); // [ var(194) , var(108) ] D[110,194] = (-1)*var(63); // [ var(194) , var(110) ] D[112,194] = var(69); // [ var(194) , var(112) ] D[119,194] = (-1)*var(97); // [ var(194) , var(119) ] D[120,194] = var(101); // [ var(194) , var(120) ] D[2,195] = var(190); // [ var(195) , var(2) ] D[7,195] = var(189); // [ var(195) , var(7) ] D[10,195] = (-1)*var(184); // [ var(195) , var(10) ] D[17,195] = var(179); // [ var(195) , var(17) ] D[18,195] = var(178); // [ var(195) , var(18) ] D[23,195] = (-1)*var(175); // [ var(195) , var(23) ] D[25,195] = (-1)*var(173); // [ var(195) , var(25) ] D[30,195] = var(169); // [ var(195) , var(30) ] D[32,195] = var(166); // [ var(195) , var(32) ] D[34,195] = (-1)*var(164); // [ var(195) , var(34) ] D[37,195] = (-1)*var(161); // [ var(195) , var(37) ] D[41,195] = var(157); // [ var(195) , var(41) ] D[44,195] = var(154); // [ var(195) , var(44) ] D[46,195] = (-1)*var(152); // [ var(195) , var(46) ] D[49,195] = (-1)*var(150); // [ var(195) , var(49) ] D[53,195] = var(145); // [ var(195) , var(53) ] D[55,195] = var(143); // [ var(195) , var(55) ] D[58,195] = (-1)*var(138); // [ var(195) , var(58) ] D[59,195] = (-1)*var(137); // [ var(195) , var(59) ] D[64,195] = var(130); // [ var(195) , var(64) ] D[69,195] = (-1)*var(127); // [ var(195) , var(69) ] D[70,195] = (-1)*var(122); // [ var(195) , var(70) ] D[75,195] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247); // [ var(195) , var(75) ] D[80,195] = (-1)*var(6); // [ var(195) , var(80) ] D[81,195] = (-1)*var(8); // [ var(195) , var(81) ] D[85,195] = var(13); // [ var(195) , var(85) ] D[89,195] = (-1)*var(20); // [ var(195) , var(89) ] D[91,195] = var(22); // [ var(195) , var(91) ] D[93,195] = var(27); // [ var(195) , var(93) ] D[95,195] = (-1)*var(29); // [ var(195) , var(95) ] D[97,195] = (-1)*var(31); // [ var(195) , var(97) ] D[99,195] = var(36); // [ var(195) , var(99) ] D[102,195] = (-1)*var(43); // [ var(195) , var(102) ] D[104,195] = var(47); // [ var(195) , var(104) ] D[112,195] = var(68); // [ var(195) , var(112) ] D[113,195] = (-1)*var(73); // [ var(195) , var(113) ] D[115,195] = var(78); // [ var(195) , var(115) ] D[116,195] = (-1)*var(83); // [ var(195) , var(116) ] D[117,195] = var(87); // [ var(195) , var(117) ] D[119,195] = (-1)*var(96); // [ var(195) , var(119) ] D[4,196] = var(191); // [ var(196) , var(4) ] D[6,196] = var(190); // [ var(196) , var(6) ] D[11,196] = (-1)*var(186); // [ var(196) , var(11) ] D[14,196] = (-1)*var(183); // [ var(196) , var(14) ] D[16,196] = var(181); // [ var(196) , var(16) ] D[20,196] = (-1)*var(178); // [ var(196) , var(20) ] D[27,196] = var(173); // [ var(196) , var(27) ] D[28,196] = var(171); // [ var(196) , var(28) ] D[31,196] = (-1)*var(169); // [ var(196) , var(31) ] D[35,196] = (-1)*var(165); // [ var(196) , var(35) ] D[39,196] = var(160); // [ var(196) , var(39) ] D[40,196] = (-1)*var(159); // [ var(196) , var(40) ] D[45,196] = var(155); // [ var(196) , var(45) ] D[49,196] = var(151); // [ var(196) , var(49) ] D[51,196] = (-1)*var(148); // [ var(196) , var(51) ] D[53,196] = (-1)*var(147); // [ var(196) , var(53) ] D[58,196] = var(140); // [ var(196) , var(58) ] D[61,196] = (-1)*var(136); // [ var(196) , var(61) ] D[63,196] = var(134); // [ var(196) , var(63) ] D[66,196] = var(131); // [ var(196) , var(66) ] D[70,196] = (-1)*var(126); // [ var(196) , var(70) ] D[71,196] = (-1)*var(124); // [ var(196) , var(71) ] D[76,196] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(196) , var(76) ] D[80,196] = (-1)*var(2); // [ var(196) , var(80) ] D[82,196] = (-1)*var(5); // [ var(196) , var(82) ] D[83,196] = (-1)*var(8); // [ var(196) , var(83) ] D[88,196] = var(15); // [ var(196) , var(88) ] D[89,196] = var(18); // [ var(196) , var(89) ] D[93,196] = (-1)*var(25); // [ var(196) , var(93) ] D[96,196] = (-1)*var(29); // [ var(196) , var(96) ] D[97,196] = var(30); // [ var(196) , var(97) ] D[103,196] = var(42); // [ var(196) , var(103) ] D[105,196] = (-1)*var(50); // [ var(196) , var(105) ] D[107,196] = var(54); // [ var(196) , var(107) ] D[110,196] = var(62); // [ var(196) , var(110) ] D[111,196] = (-1)*var(67); // [ var(196) , var(111) ] D[114,196] = var(72); // [ var(196) , var(114) ] D[116,196] = (-1)*var(81); // [ var(196) , var(116) ] D[118,196] = var(90); // [ var(196) , var(118) ] D[119,196] = (-1)*var(95); // [ var(196) , var(119) ] D[4,197] = var(192); // [ var(197) , var(4) ] D[8,197] = var(190); // [ var(197) , var(8) ] D[11,197] = (-1)*var(187); // [ var(197) , var(11) ] D[12,197] = (-1)*var(185); // [ var(197) , var(12) ] D[15,197] = var(183); // [ var(197) , var(15) ] D[16,197] = var(182); // [ var(197) , var(16) ] D[19,197] = var(180); // [ var(197) , var(19) ] D[24,197] = (-1)*var(176); // [ var(197) , var(24) ] D[32,197] = (-1)*var(167); // [ var(197) , var(32) ] D[36,197] = var(164); // [ var(197) , var(36) ] D[37,197] = var(163); // [ var(197) , var(37) ] D[43,197] = (-1)*var(157); // [ var(197) , var(43) ] D[44,197] = (-1)*var(156); // [ var(197) , var(44) ] D[47,197] = var(152); // [ var(197) , var(47) ] D[56,197] = var(144); // [ var(197) , var(56) ] D[60,197] = (-1)*var(139); // [ var(197) , var(60) ] D[62,197] = (-1)*var(136); // [ var(197) , var(62) ] D[63,197] = (-1)*var(135); // [ var(197) , var(63) ] D[65,197] = var(132); // [ var(197) , var(65) ] D[67,197] = var(131); // [ var(197) , var(67) ] D[70,197] = (-1)*var(128); // [ var(197) , var(70) ] D[72,197] = (-1)*var(124); // [ var(197) , var(72) ] D[77,197] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(197) , var(77) ] D[81,197] = (-1)*var(2); // [ var(197) , var(81) ] D[83,197] = (-1)*var(6); // [ var(197) , var(83) ] D[87,197] = var(13); // [ var(197) , var(87) ] D[88,197] = (-1)*var(14); // [ var(197) , var(88) ] D[92,197] = var(21); // [ var(197) , var(92) ] D[94,197] = (-1)*var(26); // [ var(197) , var(94) ] D[98,197] = var(33); // [ var(197) , var(98) ] D[99,197] = (-1)*var(34); // [ var(197) , var(99) ] D[101,197] = (-1)*var(38); // [ var(197) , var(101) ] D[102,197] = var(41); // [ var(197) , var(102) ] D[104,197] = (-1)*var(46); // [ var(197) , var(104) ] D[110,197] = var(61); // [ var(197) , var(110) ] D[111,197] = (-1)*var(66); // [ var(197) , var(111) ] D[114,197] = var(71); // [ var(197) , var(114) ] D[116,197] = (-1)*var(80); // [ var(197) , var(116) ] D[117,197] = var(85); // [ var(197) , var(117) ] D[120,197] = (-1)*var(100); // [ var(197) , var(120) ] D[3,198] = (-1)*var(193); // [ var(198) , var(3) ] D[6,198] = var(192); // [ var(198) , var(6) ] D[8,198] = var(191); // [ var(198) , var(8) ] D[9,198] = var(188); // [ var(198) , var(9) ] D[13,198] = var(185); // [ var(198) , var(13) ] D[22,198] = (-1)*var(177); // [ var(198) , var(22) ] D[27,198] = var(174); // [ var(198) , var(27) ] D[29,198] = (-1)*var(171); // [ var(198) , var(29) ] D[31,198] = (-1)*var(170); // [ var(198) , var(31) ] D[33,198] = (-1)*var(167); // [ var(198) , var(33) ] D[38,198] = var(163); // [ var(198) , var(38) ] D[43,198] = (-1)*var(158); // [ var(198) , var(43) ] D[47,198] = var(153); // [ var(198) , var(47) ] D[50,198] = var(151); // [ var(198) , var(50) ] D[51,198] = var(149); // [ var(198) , var(51) ] D[54,198] = (-1)*var(147); // [ var(198) , var(54) ] D[57,198] = var(142); // [ var(198) , var(57) ] D[65,198] = (-1)*var(133); // [ var(198) , var(65) ] D[68,198] = (-1)*var(129); // [ var(198) , var(68) ] D[71,198] = (-1)*var(128); // [ var(198) , var(71) ] D[72,198] = (-1)*var(126); // [ var(198) , var(72) ] D[73,198] = var(123); // [ var(198) , var(73) ] D[78,198] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(198) , var(78) ] D[83,198] = (-1)*var(4); // [ var(198) , var(83) ] D[84,198] = (-1)*var(7); // [ var(198) , var(84) ] D[86,198] = var(10); // [ var(198) , var(86) ] D[87,198] = (-1)*var(12); // [ var(198) , var(87) ] D[90,198] = var(18); // [ var(198) , var(90) ] D[96,198] = var(28); // [ var(198) , var(96) ] D[98,198] = var(32); // [ var(198) , var(98) ] D[100,198] = (-1)*var(34); // [ var(198) , var(100) ] D[101,198] = (-1)*var(37); // [ var(198) , var(101) ] D[105,198] = (-1)*var(49); // [ var(198) , var(105) ] D[107,198] = var(53); // [ var(198) , var(107) ] D[108,198] = (-1)*var(55); // [ var(198) , var(108) ] D[109,198] = var(59); // [ var(198) , var(109) ] D[114,198] = var(70); // [ var(198) , var(114) ] D[115,198] = (-1)*var(75); // [ var(198) , var(115) ] D[118,198] = var(89); // [ var(198) , var(118) ] D[120,198] = (-1)*var(99); // [ var(198) , var(120) ] D[1,199] = (-1)*var(194); // [ var(199) , var(1) ] D[7,199] = var(193); // [ var(199) , var(7) ] D[14,199] = var(187); // [ var(199) , var(14) ] D[15,199] = (-1)*var(186); // [ var(199) , var(15) ] D[21,199] = var(180); // [ var(199) , var(21) ] D[22,199] = (-1)*var(179); // [ var(199) , var(22) ] D[28,199] = var(174); // [ var(199) , var(28) ] D[29,199] = (-1)*var(173); // [ var(199) , var(29) ] D[34,199] = (-1)*var(167); // [ var(199) , var(34) ] D[36,199] = (-1)*var(166); // [ var(199) , var(36) ] D[39,199] = (-1)*var(162); // [ var(199) , var(39) ] D[42,199] = var(159); // [ var(199) , var(42) ] D[46,199] = var(156); // [ var(199) , var(46) ] D[47,199] = var(154); // [ var(199) , var(47) ] D[53,199] = var(149); // [ var(199) , var(53) ] D[54,199] = (-1)*var(148); // [ var(199) , var(54) ] D[59,199] = var(142); // [ var(199) , var(59) ] D[60,199] = (-1)*var(141); // [ var(199) , var(60) ] D[66,199] = var(135); // [ var(199) , var(66) ] D[67,199] = (-1)*var(134); // [ var(199) , var(67) ] D[73,199] = (-1)*var(127); // [ var(199) , var(73) ] D[74,199] = var(121); // [ var(199) , var(74) ] D[79,199] = (-1)*var(241)+(-1)*var(242)+(-1)*var(243)+(-2)*var(244)+(-2)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(199) , var(79) ] D[84,199] = var(3); // [ var(199) , var(84) ] D[88,199] = var(11); // [ var(199) , var(88) ] D[91,199] = (-1)*var(17); // [ var(199) , var(91) ] D[92,199] = var(19); // [ var(199) , var(92) ] D[95,199] = (-1)*var(25); // [ var(199) , var(95) ] D[96,199] = var(27); // [ var(199) , var(96) ] D[99,199] = (-1)*var(32); // [ var(199) , var(99) ] D[100,199] = (-1)*var(33); // [ var(199) , var(100) ] D[103,199] = (-1)*var(40); // [ var(199) , var(103) ] D[104,199] = var(44); // [ var(199) , var(104) ] D[106,199] = (-1)*var(48); // [ var(199) , var(106) ] D[107,199] = var(51); // [ var(199) , var(107) ] D[109,199] = var(57); // [ var(199) , var(109) ] D[111,199] = var(63); // [ var(199) , var(111) ] D[113,199] = (-1)*var(69); // [ var(199) , var(113) ] D[119,199] = (-1)*var(93); // [ var(199) , var(119) ] D[120,199] = var(98); // [ var(199) , var(120) ] D[2,200] = var(196); // [ var(200) , var(2) ] D[6,200] = var(195); // [ var(200) , var(6) ] D[10,200] = (-1)*var(191); // [ var(200) , var(10) ] D[14,200] = (-1)*var(189); // [ var(200) , var(14) ] D[17,200] = var(186); // [ var(200) , var(17) ] D[23,200] = (-1)*var(181); // [ var(200) , var(23) ] D[26,200] = var(178); // [ var(200) , var(26) ] D[33,200] = (-1)*var(173); // [ var(200) , var(33) ] D[34,200] = (-1)*var(171); // [ var(200) , var(34) ] D[38,200] = var(169); // [ var(200) , var(38) ] D[40,200] = var(166); // [ var(200) , var(40) ] D[41,200] = var(165); // [ var(200) , var(41) ] D[45,200] = (-1)*var(161); // [ var(200) , var(45) ] D[46,200] = (-1)*var(160); // [ var(200) , var(46) ] D[49,200] = (-1)*var(158); // [ var(200) , var(49) ] D[51,200] = var(154); // [ var(200) , var(51) ] D[53,200] = var(153); // [ var(200) , var(53) ] D[58,200] = (-1)*var(146); // [ var(200) , var(58) ] D[61,200] = var(143); // [ var(200) , var(61) ] D[66,200] = (-1)*var(137); // [ var(200) , var(66) ] D[69,200] = var(134); // [ var(200) , var(69) ] D[71,200] = var(130); // [ var(200) , var(71) ] D[75,200] = (-1)*var(126); // [ var(200) , var(75) ] D[76,200] = (-1)*var(122); // [ var(200) , var(76) ] D[80,200] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(200) , var(80) ] D[85,200] = (-1)*var(5); // [ var(200) , var(85) ] D[86,200] = (-1)*var(8); // [ var(200) , var(86) ] D[89,200] = var(12); // [ var(200) , var(89) ] D[91,200] = var(15); // [ var(200) , var(91) ] D[93,200] = (-1)*var(19); // [ var(200) , var(93) ] D[97,200] = var(24); // [ var(200) , var(97) ] D[100,200] = (-1)*var(29); // [ var(200) , var(100) ] D[103,200] = var(36); // [ var(200) , var(103) ] D[105,200] = (-1)*var(43); // [ var(200) , var(105) ] D[107,200] = var(47); // [ var(200) , var(107) ] D[112,200] = (-1)*var(62); // [ var(200) , var(112) ] D[113,200] = var(67); // [ var(200) , var(113) ] D[115,200] = (-1)*var(72); // [ var(200) , var(115) ] D[116,200] = var(77); // [ var(200) , var(116) ] D[118,200] = (-1)*var(87); // [ var(200) , var(118) ] D[119,200] = var(92); // [ var(200) , var(119) ] D[2,201] = var(197); // [ var(201) , var(2) ] D[8,201] = var(195); // [ var(201) , var(8) ] D[10,201] = (-1)*var(192); // [ var(201) , var(10) ] D[15,201] = var(189); // [ var(201) , var(15) ] D[17,201] = var(187); // [ var(201) , var(17) ] D[18,201] = var(185); // [ var(201) , var(18) ] D[23,201] = (-1)*var(182); // [ var(201) , var(23) ] D[25,201] = (-1)*var(180); // [ var(201) , var(25) ] D[30,201] = var(176); // [ var(201) , var(30) ] D[32,201] = var(174); // [ var(201) , var(32) ] D[37,201] = (-1)*var(170); // [ var(201) , var(37) ] D[42,201] = (-1)*var(164); // [ var(201) , var(42) ] D[44,201] = var(162); // [ var(201) , var(44) ] D[50,201] = var(157); // [ var(201) , var(50) ] D[54,201] = (-1)*var(152); // [ var(201) , var(54) ] D[56,201] = (-1)*var(150); // [ var(201) , var(56) ] D[60,201] = var(145); // [ var(201) , var(60) ] D[62,201] = var(143); // [ var(201) , var(62) ] D[65,201] = (-1)*var(138); // [ var(201) , var(65) ] D[67,201] = (-1)*var(137); // [ var(201) , var(67) ] D[69,201] = (-1)*var(135); // [ var(201) , var(69) ] D[72,201] = var(130); // [ var(201) , var(72) ] D[75,201] = (-1)*var(128); // [ var(201) , var(75) ] D[77,201] = (-1)*var(122); // [ var(201) , var(77) ] D[81,201] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-1)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(201) , var(81) ] D[86,201] = (-1)*var(6); // [ var(201) , var(86) ] D[90,201] = var(13); // [ var(201) , var(90) ] D[91,201] = (-1)*var(14); // [ var(201) , var(91) ] D[94,201] = (-1)*var(20); // [ var(201) , var(94) ] D[95,201] = var(21); // [ var(201) , var(95) ] D[98,201] = var(27); // [ var(201) , var(98) ] D[99,201] = (-1)*var(28); // [ var(201) , var(99) ] D[101,201] = (-1)*var(31); // [ var(201) , var(101) ] D[102,201] = var(35); // [ var(201) , var(102) ] D[104,201] = (-1)*var(39); // [ var(201) , var(104) ] D[112,201] = (-1)*var(61); // [ var(201) , var(112) ] D[113,201] = var(66); // [ var(201) , var(113) ] D[115,201] = (-1)*var(71); // [ var(201) , var(115) ] D[116,201] = var(76); // [ var(201) , var(116) ] D[117,201] = (-1)*var(82); // [ var(201) , var(117) ] D[120,201] = var(96); // [ var(201) , var(120) ] D[5,202] = var(196); // [ var(202) , var(5) ] D[12,202] = var(191); // [ var(202) , var(12) ] D[13,202] = (-1)*var(190); // [ var(202) , var(13) ] D[19,202] = (-1)*var(186); // [ var(202) , var(19) ] D[20,202] = (-1)*var(184); // [ var(202) , var(20) ] D[21,202] = var(183); // [ var(202) , var(21) ] D[24,202] = var(181); // [ var(202) , var(24) ] D[27,202] = var(179); // [ var(202) , var(27) ] D[28,202] = var(177); // [ var(202) , var(28) ] D[31,202] = (-1)*var(175); // [ var(202) , var(31) ] D[35,202] = (-1)*var(172); // [ var(202) , var(35) ] D[39,202] = var(168); // [ var(202) , var(39) ] D[48,202] = (-1)*var(159); // [ var(202) , var(48) ] D[52,202] = var(155); // [ var(202) , var(52) ] D[55,202] = var(151); // [ var(202) , var(55) ] D[57,202] = (-1)*var(148); // [ var(202) , var(57) ] D[59,202] = (-1)*var(147); // [ var(202) , var(59) ] D[61,202] = (-1)*var(144); // [ var(202) , var(61) ] D[63,202] = (-1)*var(141); // [ var(202) , var(63) ] D[64,202] = var(140); // [ var(202) , var(64) ] D[66,202] = var(139); // [ var(202) , var(66) ] D[70,202] = var(133); // [ var(202) , var(70) ] D[71,202] = (-1)*var(132); // [ var(202) , var(71) ] D[76,202] = (-1)*var(125); // [ var(202) , var(76) ] D[82,202] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(202) , var(82) ] D[85,202] = (-1)*var(2); // [ var(202) , var(85) ] D[87,202] = (-1)*var(8); // [ var(202) , var(87) ] D[89,202] = (-1)*var(10); // [ var(202) , var(89) ] D[92,202] = var(15); // [ var(202) , var(92) ] D[93,202] = var(17); // [ var(202) , var(93) ] D[96,202] = (-1)*var(22); // [ var(202) , var(96) ] D[97,202] = (-1)*var(23); // [ var(202) , var(97) ] D[106,202] = var(42); // [ var(202) , var(106) ] D[108,202] = (-1)*var(50); // [ var(202) , var(108) ] D[109,202] = var(54); // [ var(202) , var(109) ] D[110,202] = (-1)*var(56); // [ var(202) , var(110) ] D[111,202] = var(60); // [ var(202) , var(111) ] D[114,202] = (-1)*var(65); // [ var(202) , var(114) ] D[117,202] = var(81); // [ var(202) , var(117) ] D[118,202] = (-1)*var(86); // [ var(202) , var(118) ] D[119,202] = var(91); // [ var(202) , var(119) ] D[4,203] = var(198); // [ var(203) , var(4) ] D[6,203] = var(197); // [ var(203) , var(6) ] D[8,203] = var(196); // [ var(203) , var(8) ] D[11,203] = (-1)*var(193); // [ var(203) , var(11) ] D[16,203] = var(188); // [ var(203) , var(16) ] D[20,203] = (-1)*var(185); // [ var(203) , var(20) ] D[22,203] = (-1)*var(183); // [ var(203) , var(22) ] D[27,203] = var(180); // [ var(203) , var(27) ] D[31,203] = (-1)*var(176); // [ var(203) , var(31) ] D[36,203] = var(171); // [ var(203) , var(36) ] D[40,203] = (-1)*var(167); // [ var(203) , var(40) ] D[43,203] = (-1)*var(165); // [ var(203) , var(43) ] D[45,203] = var(163); // [ var(203) , var(45) ] D[47,203] = var(160); // [ var(203) , var(47) ] D[51,203] = (-1)*var(156); // [ var(203) , var(51) ] D[56,203] = var(151); // [ var(203) , var(56) ] D[60,203] = (-1)*var(147); // [ var(203) , var(60) ] D[63,203] = var(142); // [ var(203) , var(63) ] D[65,203] = var(140); // [ var(203) , var(65) ] D[68,203] = (-1)*var(136); // [ var(203) , var(68) ] D[73,203] = var(131); // [ var(203) , var(73) ] D[76,203] = (-1)*var(128); // [ var(203) , var(76) ] D[77,203] = (-1)*var(126); // [ var(203) , var(77) ] D[78,203] = (-1)*var(124); // [ var(203) , var(78) ] D[83,203] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(203) , var(83) ] D[86,203] = (-1)*var(2); // [ var(203) , var(86) ] D[87,203] = (-1)*var(5); // [ var(203) , var(87) ] D[88,203] = (-1)*var(7); // [ var(203) , var(88) ] D[94,203] = var(18); // [ var(203) , var(94) ] D[96,203] = var(21); // [ var(203) , var(96) ] D[98,203] = (-1)*var(25); // [ var(203) , var(98) ] D[101,203] = var(30); // [ var(203) , var(101) ] D[103,203] = (-1)*var(34); // [ var(203) , var(103) ] D[105,203] = var(41); // [ var(203) , var(105) ] D[107,203] = (-1)*var(46); // [ var(203) , var(107) ] D[110,203] = (-1)*var(55); // [ var(203) , var(110) ] D[111,203] = var(59); // [ var(203) , var(111) ] D[114,203] = (-1)*var(64); // [ var(203) , var(114) ] D[116,203] = var(75); // [ var(203) , var(116) ] D[118,203] = (-1)*var(85); // [ var(203) , var(118) ] D[120,203] = var(95); // [ var(203) , var(120) ] D[3,204] = (-1)*var(199); // [ var(204) , var(3) ] D[7,204] = var(198); // [ var(204) , var(7) ] D[9,204] = var(194); // [ var(204) , var(9) ] D[14,204] = var(192); // [ var(204) , var(14) ] D[15,204] = (-1)*var(191); // [ var(204) , var(15) ] D[21,204] = var(185); // [ var(204) , var(21) ] D[22,204] = (-1)*var(184); // [ var(204) , var(22) ] D[29,204] = (-1)*var(178); // [ var(204) , var(29) ] D[35,204] = var(174); // [ var(204) , var(35) ] D[39,204] = (-1)*var(170); // [ var(204) , var(39) ] D[41,204] = (-1)*var(167); // [ var(204) , var(41) ] D[43,204] = (-1)*var(166); // [ var(204) , var(43) ] D[46,204] = var(163); // [ var(204) , var(46) ] D[47,204] = var(161); // [ var(204) , var(47) ] D[50,204] = var(159); // [ var(204) , var(50) ] D[54,204] = (-1)*var(155); // [ var(204) , var(54) ] D[58,204] = var(149); // [ var(204) , var(58) ] D[64,204] = var(142); // [ var(204) , var(64) ] D[65,204] = (-1)*var(141); // [ var(204) , var(65) ] D[71,204] = var(135); // [ var(204) , var(71) ] D[72,204] = (-1)*var(134); // [ var(204) , var(72) ] D[74,204] = (-1)*var(129); // [ var(204) , var(74) ] D[78,204] = (-1)*var(127); // [ var(204) , var(78) ] D[79,204] = var(123); // [ var(204) , var(79) ] D[84,204] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-2)*var(244)+(-2)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(204) , var(84) ] D[88,204] = (-1)*var(4); // [ var(204) , var(88) ] D[91,204] = var(10); // [ var(204) , var(91) ] D[92,204] = (-1)*var(12); // [ var(204) , var(92) ] D[95,204] = var(18); // [ var(204) , var(95) ] D[96,204] = (-1)*var(20); // [ var(204) , var(96) ] D[100,204] = var(26); // [ var(204) , var(100) ] D[102,204] = var(32); // [ var(204) , var(102) ] D[104,204] = (-1)*var(37); // [ var(204) , var(104) ] D[105,204] = var(40); // [ var(204) , var(105) ] D[107,204] = (-1)*var(45); // [ var(204) , var(107) ] D[108,204] = var(48); // [ var(204) , var(108) ] D[109,204] = (-1)*var(52); // [ var(204) , var(109) ] D[114,204] = (-1)*var(63); // [ var(204) , var(114) ] D[115,204] = var(69); // [ var(204) , var(115) ] D[119,204] = (-1)*var(89); // [ var(204) , var(119) ] D[120,204] = var(94); // [ var(204) , var(120) ] D[2,205] = var(202); // [ var(205) , var(2) ] D[5,205] = var(200); // [ var(205) , var(5) ] D[13,205] = (-1)*var(195); // [ var(205) , var(13) ] D[18,205] = (-1)*var(191); // [ var(205) , var(18) ] D[21,205] = var(189); // [ var(205) , var(21) ] D[25,205] = var(186); // [ var(205) , var(25) ] D[26,205] = var(184); // [ var(205) , var(26) ] D[30,205] = (-1)*var(181); // [ var(205) , var(30) ] D[33,205] = (-1)*var(179); // [ var(205) , var(33) ] D[34,205] = (-1)*var(177); // [ var(205) , var(34) ] D[38,205] = var(175); // [ var(205) , var(38) ] D[41,205] = var(172); // [ var(205) , var(41) ] D[46,205] = (-1)*var(168); // [ var(205) , var(46) ] D[48,205] = var(166); // [ var(205) , var(48) ] D[52,205] = (-1)*var(161); // [ var(205) , var(52) ] D[55,205] = (-1)*var(158); // [ var(205) , var(55) ] D[57,205] = var(154); // [ var(205) , var(57) ] D[59,205] = var(153); // [ var(205) , var(59) ] D[61,205] = var(150); // [ var(205) , var(61) ] D[64,205] = (-1)*var(146); // [ var(205) , var(64) ] D[66,205] = (-1)*var(145); // [ var(205) , var(66) ] D[69,205] = (-1)*var(141); // [ var(205) , var(69) ] D[71,205] = var(138); // [ var(205) , var(71) ] D[75,205] = var(133); // [ var(205) , var(75) ] D[80,205] = (-1)*var(125); // [ var(205) , var(80) ] D[82,205] = (-1)*var(122); // [ var(205) , var(82) ] D[85,205] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(205) , var(85) ] D[89,205] = (-1)*var(4); // [ var(205) , var(89) ] D[90,205] = (-1)*var(8); // [ var(205) , var(90) ] D[93,205] = var(11); // [ var(205) , var(93) ] D[95,205] = var(15); // [ var(205) , var(95) ] D[97,205] = (-1)*var(16); // [ var(205) , var(97) ] D[100,205] = (-1)*var(22); // [ var(205) , var(100) ] D[106,205] = var(36); // [ var(205) , var(106) ] D[108,205] = (-1)*var(43); // [ var(205) , var(108) ] D[109,205] = var(47); // [ var(205) , var(109) ] D[112,205] = var(56); // [ var(205) , var(112) ] D[113,205] = (-1)*var(60); // [ var(205) , var(113) ] D[115,205] = var(65); // [ var(205) , var(115) ] D[117,205] = (-1)*var(77); // [ var(205) , var(117) ] D[118,205] = var(83); // [ var(205) , var(118) ] D[119,205] = (-1)*var(88); // [ var(205) , var(119) ] D[2,206] = var(203); // [ var(206) , var(2) ] D[6,206] = var(201); // [ var(206) , var(6) ] D[8,206] = var(200); // [ var(206) , var(8) ] D[10,206] = (-1)*var(198); // [ var(206) , var(10) ] D[17,206] = var(193); // [ var(206) , var(17) ] D[22,206] = (-1)*var(189); // [ var(206) , var(22) ] D[23,206] = (-1)*var(188); // [ var(206) , var(23) ] D[26,206] = var(185); // [ var(206) , var(26) ] D[33,206] = (-1)*var(180); // [ var(206) , var(33) ] D[38,206] = var(176); // [ var(206) , var(38) ] D[40,206] = var(174); // [ var(206) , var(40) ] D[42,206] = (-1)*var(171); // [ var(206) , var(42) ] D[45,206] = (-1)*var(170); // [ var(206) , var(45) ] D[50,206] = var(165); // [ var(206) , var(50) ] D[51,206] = var(162); // [ var(206) , var(51) ] D[54,206] = (-1)*var(160); // [ var(206) , var(54) ] D[56,206] = (-1)*var(158); // [ var(206) , var(56) ] D[60,206] = var(153); // [ var(206) , var(60) ] D[65,206] = (-1)*var(146); // [ var(206) , var(65) ] D[68,206] = var(143); // [ var(206) , var(68) ] D[69,206] = var(142); // [ var(206) , var(69) ] D[73,206] = (-1)*var(137); // [ var(206) , var(73) ] D[78,206] = var(130); // [ var(206) , var(78) ] D[80,206] = (-1)*var(128); // [ var(206) , var(80) ] D[81,206] = (-1)*var(126); // [ var(206) , var(81) ] D[83,206] = (-1)*var(122); // [ var(206) , var(83) ] D[86,206] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(206) , var(86) ] D[90,206] = (-1)*var(5); // [ var(206) , var(90) ] D[91,206] = (-1)*var(7); // [ var(206) , var(91) ] D[94,206] = var(12); // [ var(206) , var(94) ] D[98,206] = (-1)*var(19); // [ var(206) , var(98) ] D[100,206] = var(21); // [ var(206) , var(100) ] D[101,206] = var(24); // [ var(206) , var(101) ] D[103,206] = (-1)*var(28); // [ var(206) , var(103) ] D[105,206] = var(35); // [ var(206) , var(105) ] D[107,206] = (-1)*var(39); // [ var(206) , var(107) ] D[112,206] = var(55); // [ var(206) , var(112) ] D[113,206] = (-1)*var(59); // [ var(206) , var(113) ] D[115,206] = var(64); // [ var(206) , var(115) ] D[116,206] = (-1)*var(70); // [ var(206) , var(116) ] D[118,206] = var(82); // [ var(206) , var(118) ] D[120,206] = (-1)*var(92); // [ var(206) , var(120) ] D[5,207] = var(203); // [ var(207) , var(5) ] D[8,207] = var(202); // [ var(207) , var(8) ] D[12,207] = var(198); // [ var(207) , var(12) ] D[13,207] = (-1)*var(197); // [ var(207) , var(13) ] D[19,207] = (-1)*var(193); // [ var(207) , var(19) ] D[20,207] = (-1)*var(192); // [ var(207) , var(20) ] D[24,207] = var(188); // [ var(207) , var(24) ] D[27,207] = var(187); // [ var(207) , var(27) ] D[29,207] = var(183); // [ var(207) , var(29) ] D[31,207] = (-1)*var(182); // [ var(207) , var(31) ] D[36,207] = var(177); // [ var(207) , var(36) ] D[43,207] = (-1)*var(172); // [ var(207) , var(43) ] D[47,207] = var(168); // [ var(207) , var(47) ] D[48,207] = (-1)*var(167); // [ var(207) , var(48) ] D[52,207] = var(163); // [ var(207) , var(52) ] D[57,207] = (-1)*var(156); // [ var(207) , var(57) ] D[62,207] = var(151); // [ var(207) , var(62) ] D[63,207] = (-1)*var(149); // [ var(207) , var(63) ] D[67,207] = (-1)*var(147); // [ var(207) , var(67) ] D[68,207] = (-1)*var(144); // [ var(207) , var(68) ] D[72,207] = var(140); // [ var(207) , var(72) ] D[73,207] = var(139); // [ var(207) , var(73) ] D[77,207] = var(133); // [ var(207) , var(77) ] D[78,207] = (-1)*var(132); // [ var(207) , var(78) ] D[82,207] = (-1)*var(128); // [ var(207) , var(82) ] D[83,207] = (-1)*var(125); // [ var(207) , var(83) ] D[87,207] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(207) , var(87) ] D[90,207] = (-1)*var(2); // [ var(207) , var(90) ] D[92,207] = (-1)*var(7); // [ var(207) , var(92) ] D[94,207] = (-1)*var(10); // [ var(207) , var(94) ] D[96,207] = var(14); // [ var(207) , var(96) ] D[98,207] = var(17); // [ var(207) , var(98) ] D[101,207] = (-1)*var(23); // [ var(207) , var(101) ] D[106,207] = (-1)*var(34); // [ var(207) , var(106) ] D[108,207] = var(41); // [ var(207) , var(108) ] D[109,207] = (-1)*var(46); // [ var(207) , var(109) ] D[110,207] = var(49); // [ var(207) , var(110) ] D[111,207] = (-1)*var(53); // [ var(207) , var(111) ] D[114,207] = var(58); // [ var(207) , var(114) ] D[117,207] = (-1)*var(75); // [ var(207) , var(117) ] D[118,207] = var(80); // [ var(207) , var(118) ] D[120,207] = (-1)*var(91); // [ var(207) , var(120) ] D[4,208] = var(204); // [ var(208) , var(4) ] D[7,208] = var(203); // [ var(208) , var(7) ] D[11,208] = (-1)*var(199); // [ var(208) , var(11) ] D[14,208] = var(197); // [ var(208) , var(14) ] D[15,208] = (-1)*var(196); // [ var(208) , var(15) ] D[16,208] = var(194); // [ var(208) , var(16) ] D[22,208] = (-1)*var(190); // [ var(208) , var(22) ] D[28,208] = (-1)*var(185); // [ var(208) , var(28) ] D[35,208] = var(180); // [ var(208) , var(35) ] D[36,208] = var(178); // [ var(208) , var(36) ] D[39,208] = (-1)*var(176); // [ var(208) , var(39) ] D[43,208] = (-1)*var(173); // [ var(208) , var(43) ] D[47,208] = var(169); // [ var(208) , var(47) ] D[49,208] = (-1)*var(167); // [ var(208) , var(49) ] D[53,208] = var(163); // [ var(208) , var(53) ] D[56,208] = var(159); // [ var(208) , var(56) ] D[58,208] = (-1)*var(156); // [ var(208) , var(58) ] D[60,208] = (-1)*var(155); // [ var(208) , var(60) ] D[65,208] = var(148); // [ var(208) , var(65) ] D[70,208] = var(142); // [ var(208) , var(70) ] D[74,208] = (-1)*var(136); // [ var(208) , var(74) ] D[76,208] = var(135); // [ var(208) , var(76) ] D[77,208] = (-1)*var(134); // [ var(208) , var(77) ] D[79,208] = var(131); // [ var(208) , var(79) ] D[83,208] = (-1)*var(127); // [ var(208) , var(83) ] D[84,208] = (-1)*var(124); // [ var(208) , var(84) ] D[88,208] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(208) , var(88) ] D[91,208] = (-1)*var(2); // [ var(208) , var(91) ] D[92,208] = (-1)*var(5); // [ var(208) , var(92) ] D[96,208] = (-1)*var(13); // [ var(208) , var(96) ] D[99,208] = var(18); // [ var(208) , var(99) ] D[102,208] = (-1)*var(25); // [ var(208) , var(102) ] D[103,208] = var(26); // [ var(208) , var(103) ] D[104,208] = var(30); // [ var(208) , var(104) ] D[105,208] = (-1)*var(33); // [ var(208) , var(105) ] D[107,208] = var(38); // [ var(208) , var(107) ] D[110,208] = var(48); // [ var(208) , var(110) ] D[111,208] = (-1)*var(52); // [ var(208) , var(111) ] D[114,208] = var(57); // [ var(208) , var(114) ] D[116,208] = (-1)*var(69); // [ var(208) , var(116) ] D[119,208] = var(85); // [ var(208) , var(119) ] D[120,208] = (-1)*var(90); // [ var(208) , var(120) ] D[4,209] = var(205); // [ var(209) , var(4) ] D[10,209] = var(202); // [ var(209) , var(10) ] D[12,209] = (-1)*var(200); // [ var(209) , var(12) ] D[18,209] = (-1)*var(196); // [ var(209) , var(18) ] D[20,209] = var(195); // [ var(209) , var(20) ] D[26,209] = var(190); // [ var(209) , var(26) ] D[28,209] = (-1)*var(189); // [ var(209) , var(28) ] D[32,209] = var(186); // [ var(209) , var(32) ] D[34,209] = (-1)*var(183); // [ var(209) , var(34) ] D[37,209] = (-1)*var(181); // [ var(209) , var(37) ] D[40,209] = (-1)*var(179); // [ var(209) , var(40) ] D[45,209] = var(175); // [ var(209) , var(45) ] D[48,209] = var(173); // [ var(209) , var(48) ] D[49,209] = var(172); // [ var(209) , var(49) ] D[52,209] = (-1)*var(169); // [ var(209) , var(52) ] D[53,209] = (-1)*var(168); // [ var(209) , var(53) ] D[55,209] = (-1)*var(165); // [ var(209) , var(55) ] D[59,209] = var(160); // [ var(209) , var(59) ] D[61,209] = var(157); // [ var(209) , var(61) ] D[63,209] = var(154); // [ var(209) , var(63) ] D[66,209] = (-1)*var(152); // [ var(209) , var(66) ] D[69,209] = var(148); // [ var(209) , var(69) ] D[70,209] = (-1)*var(146); // [ var(209) , var(70) ] D[75,209] = (-1)*var(140); // [ var(209) , var(75) ] D[76,209] = var(138); // [ var(209) , var(76) ] D[80,209] = var(132); // [ var(209) , var(80) ] D[82,209] = (-1)*var(130); // [ var(209) , var(82) ] D[85,209] = (-1)*var(124); // [ var(209) , var(85) ] D[89,209] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-4)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(209) , var(89) ] D[93,209] = (-1)*var(3); // [ var(209) , var(93) ] D[94,209] = (-1)*var(8); // [ var(209) , var(94) ] D[97,209] = var(9); // [ var(209) , var(97) ] D[99,209] = var(15); // [ var(209) , var(99) ] D[103,209] = (-1)*var(22); // [ var(209) , var(103) ] D[106,209] = var(29); // [ var(209) , var(106) ] D[110,209] = (-1)*var(43); // [ var(209) , var(110) ] D[111,209] = var(47); // [ var(209) , var(111) ] D[112,209] = (-1)*var(50); // [ var(209) , var(112) ] D[113,209] = var(54); // [ var(209) , var(113) ] D[116,209] = (-1)*var(65); // [ var(209) , var(116) ] D[117,209] = var(72); // [ var(209) , var(117) ] D[118,209] = (-1)*var(78); // [ var(209) , var(118) ] D[119,209] = var(84); // [ var(209) , var(119) ] D[2,210] = var(207); // [ var(210) , var(2) ] D[5,210] = var(206); // [ var(210) , var(5) ] D[8,210] = var(205); // [ var(210) , var(8) ] D[13,210] = (-1)*var(201); // [ var(210) , var(13) ] D[18,210] = (-1)*var(198); // [ var(210) , var(18) ] D[25,210] = var(193); // [ var(210) , var(25) ] D[26,210] = var(192); // [ var(210) , var(26) ] D[29,210] = var(189); // [ var(210) , var(29) ] D[30,210] = (-1)*var(188); // [ var(210) , var(30) ] D[33,210] = (-1)*var(187); // [ var(210) , var(33) ] D[38,210] = var(182); // [ var(210) , var(38) ] D[42,210] = (-1)*var(177); // [ var(210) , var(42) ] D[48,210] = var(174); // [ var(210) , var(48) ] D[50,210] = var(172); // [ var(210) , var(50) ] D[52,210] = (-1)*var(170); // [ var(210) , var(52) ] D[54,210] = (-1)*var(168); // [ var(210) , var(54) ] D[57,210] = var(162); // [ var(210) , var(57) ] D[62,210] = (-1)*var(158); // [ var(210) , var(62) ] D[67,210] = var(153); // [ var(210) , var(67) ] D[68,210] = var(150); // [ var(210) , var(68) ] D[69,210] = (-1)*var(149); // [ var(210) , var(69) ] D[72,210] = (-1)*var(146); // [ var(210) , var(72) ] D[73,210] = (-1)*var(145); // [ var(210) , var(73) ] D[78,210] = var(138); // [ var(210) , var(78) ] D[81,210] = var(133); // [ var(210) , var(81) ] D[85,210] = (-1)*var(128); // [ var(210) , var(85) ] D[86,210] = (-1)*var(125); // [ var(210) , var(86) ] D[87,210] = (-1)*var(122); // [ var(210) , var(87) ] D[90,210] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(210) , var(90) ] D[94,210] = (-1)*var(4); // [ var(210) , var(94) ] D[95,210] = (-1)*var(7); // [ var(210) , var(95) ] D[98,210] = var(11); // [ var(210) , var(98) ] D[100,210] = var(14); // [ var(210) , var(100) ] D[101,210] = (-1)*var(16); // [ var(210) , var(101) ] D[106,210] = (-1)*var(28); // [ var(210) , var(106) ] D[108,210] = var(35); // [ var(210) , var(108) ] D[109,210] = (-1)*var(39); // [ var(210) , var(109) ] D[112,210] = (-1)*var(49); // [ var(210) , var(112) ] D[113,210] = var(53); // [ var(210) , var(113) ] D[115,210] = (-1)*var(58); // [ var(210) , var(115) ] D[117,210] = var(70); // [ var(210) , var(117) ] D[118,210] = (-1)*var(76); // [ var(210) , var(118) ] D[120,210] = var(88); // [ var(210) , var(120) ] D[2,211] = var(208); // [ var(211) , var(2) ] D[7,211] = var(206); // [ var(211) , var(7) ] D[10,211] = (-1)*var(204); // [ var(211) , var(10) ] D[14,211] = var(201); // [ var(211) , var(14) ] D[15,211] = (-1)*var(200); // [ var(211) , var(15) ] D[17,211] = var(199); // [ var(211) , var(17) ] D[22,211] = (-1)*var(195); // [ var(211) , var(22) ] D[23,211] = (-1)*var(194); // [ var(211) , var(23) ] D[34,211] = var(185); // [ var(211) , var(34) ] D[41,211] = (-1)*var(180); // [ var(211) , var(41) ] D[42,211] = (-1)*var(178); // [ var(211) , var(42) ] D[46,211] = var(176); // [ var(211) , var(46) ] D[49,211] = var(174); // [ var(211) , var(49) ] D[50,211] = var(173); // [ var(211) , var(50) ] D[53,211] = (-1)*var(170); // [ var(211) , var(53) ] D[54,211] = (-1)*var(169); // [ var(211) , var(54) ] D[56,211] = (-1)*var(166); // [ var(211) , var(56) ] D[58,211] = var(162); // [ var(211) , var(58) ] D[60,211] = var(161); // [ var(211) , var(60) ] D[65,211] = (-1)*var(154); // [ var(211) , var(65) ] D[74,211] = var(143); // [ var(211) , var(74) ] D[75,211] = var(142); // [ var(211) , var(75) ] D[79,211] = (-1)*var(137); // [ var(211) , var(79) ] D[80,211] = var(135); // [ var(211) , var(80) ] D[81,211] = (-1)*var(134); // [ var(211) , var(81) ] D[84,211] = var(130); // [ var(211) , var(84) ] D[86,211] = (-1)*var(127); // [ var(211) , var(86) ] D[88,211] = (-1)*var(122); // [ var(211) , var(88) ] D[91,211] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-2)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(211) , var(91) ] D[95,211] = (-1)*var(5); // [ var(211) , var(95) ] D[99,211] = var(12); // [ var(211) , var(99) ] D[100,211] = (-1)*var(13); // [ var(211) , var(100) ] D[102,211] = (-1)*var(19); // [ var(211) , var(102) ] D[103,211] = var(20); // [ var(211) , var(103) ] D[104,211] = var(24); // [ var(211) , var(104) ] D[105,211] = (-1)*var(27); // [ var(211) , var(105) ] D[107,211] = var(31); // [ var(211) , var(107) ] D[112,211] = (-1)*var(48); // [ var(211) , var(112) ] D[113,211] = var(52); // [ var(211) , var(113) ] D[115,211] = (-1)*var(57); // [ var(211) , var(115) ] D[116,211] = var(63); // [ var(211) , var(116) ] D[119,211] = (-1)*var(82); // [ var(211) , var(119) ] D[120,211] = var(87); // [ var(211) , var(120) ] D[5,212] = var(208); // [ var(212) , var(5) ] D[7,212] = var(207); // [ var(212) , var(7) ] D[12,212] = var(204); // [ var(212) , var(12) ] D[15,212] = (-1)*var(202); // [ var(212) , var(15) ] D[19,212] = (-1)*var(199); // [ var(212) , var(19) ] D[21,212] = (-1)*var(197); // [ var(212) , var(21) ] D[24,212] = var(194); // [ var(212) , var(24) ] D[28,212] = (-1)*var(192); // [ var(212) , var(28) ] D[29,212] = var(190); // [ var(212) , var(29) ] D[35,212] = var(187); // [ var(212) , var(35) ] D[36,212] = var(184); // [ var(212) , var(36) ] D[39,212] = (-1)*var(182); // [ var(212) , var(39) ] D[43,212] = (-1)*var(179); // [ var(212) , var(43) ] D[47,212] = var(175); // [ var(212) , var(47) ] D[55,212] = (-1)*var(167); // [ var(212) , var(55) ] D[59,212] = var(163); // [ var(212) , var(59) ] D[62,212] = var(159); // [ var(212) , var(62) ] D[64,212] = (-1)*var(156); // [ var(212) , var(64) ] D[67,212] = (-1)*var(155); // [ var(212) , var(67) ] D[70,212] = (-1)*var(149); // [ var(212) , var(70) ] D[72,212] = var(148); // [ var(212) , var(72) ] D[74,212] = (-1)*var(144); // [ var(212) , var(74) ] D[77,212] = var(141); // [ var(212) , var(77) ] D[79,212] = var(139); // [ var(212) , var(79) ] D[82,212] = var(135); // [ var(212) , var(82) ] D[84,212] = (-1)*var(132); // [ var(212) , var(84) ] D[87,212] = (-1)*var(127); // [ var(212) , var(87) ] D[88,212] = (-1)*var(125); // [ var(212) , var(88) ] D[92,212] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-3)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(212) , var(92) ] D[95,212] = (-1)*var(2); // [ var(212) , var(95) ] D[96,212] = (-1)*var(6); // [ var(212) , var(96) ] D[99,212] = (-1)*var(10); // [ var(212) , var(99) ] D[102,212] = var(17); // [ var(212) , var(102) ] D[104,212] = (-1)*var(23); // [ var(212) , var(104) ] D[106,212] = var(26); // [ var(212) , var(106) ] D[108,212] = (-1)*var(33); // [ var(212) , var(108) ] D[109,212] = var(38); // [ var(212) , var(109) ] D[110,212] = (-1)*var(40); // [ var(212) , var(110) ] D[111,212] = var(45); // [ var(212) , var(111) ] D[114,212] = (-1)*var(51); // [ var(212) , var(114) ] D[117,212] = var(69); // [ var(212) , var(117) ] D[119,212] = (-1)*var(80); // [ var(212) , var(119) ] D[120,212] = var(86); // [ var(212) , var(120) ] D[3,213] = var(209); // [ var(213) , var(3) ] D[11,213] = (-1)*var(205); // [ var(213) , var(11) ] D[17,213] = (-1)*var(202); // [ var(213) , var(17) ] D[19,213] = var(200); // [ var(213) , var(19) ] D[25,213] = var(196); // [ var(213) , var(25) ] D[27,213] = (-1)*var(195); // [ var(213) , var(27) ] D[32,213] = (-1)*var(191); // [ var(213) , var(32) ] D[33,213] = (-1)*var(190); // [ var(213) , var(33) ] D[35,213] = var(189); // [ var(213) , var(35) ] D[40,213] = var(184); // [ var(213) , var(40) ] D[41,213] = var(183); // [ var(213) , var(41) ] D[44,213] = var(181); // [ var(213) , var(44) ] D[48,213] = (-1)*var(178); // [ var(213) , var(48) ] D[49,213] = (-1)*var(177); // [ var(213) , var(49) ] D[51,213] = (-1)*var(175); // [ var(213) , var(51) ] D[55,213] = var(171); // [ var(213) , var(55) ] D[57,213] = var(169); // [ var(213) , var(57) ] D[58,213] = var(168); // [ var(213) , var(58) ] D[61,213] = (-1)*var(164); // [ var(213) , var(61) ] D[63,213] = (-1)*var(161); // [ var(213) , var(63) ] D[64,213] = (-1)*var(160); // [ var(213) , var(64) ] D[69,213] = (-1)*var(155); // [ var(213) , var(69) ] D[70,213] = var(153); // [ var(213) , var(70) ] D[71,213] = var(152); // [ var(213) , var(71) ] D[75,213] = var(147); // [ var(213) , var(75) ] D[76,213] = (-1)*var(145); // [ var(213) , var(76) ] D[80,213] = (-1)*var(139); // [ var(213) , var(80) ] D[82,213] = var(137); // [ var(213) , var(82) ] D[85,213] = var(131); // [ var(213) , var(85) ] D[89,213] = (-1)*var(123); // [ var(213) , var(89) ] D[93,213] = (-1)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(213) , var(93) ] D[97,213] = (-1)*var(1); // [ var(213) , var(97) ] D[98,213] = (-1)*var(8); // [ var(213) , var(98) ] D[102,213] = var(15); // [ var(213) , var(102) ] D[105,213] = (-1)*var(22); // [ var(213) , var(105) ] D[108,213] = var(29); // [ var(213) , var(108) ] D[110,213] = (-1)*var(36); // [ var(213) , var(110) ] D[112,213] = (-1)*var(42); // [ var(213) , var(112) ] D[114,213] = var(47); // [ var(213) , var(114) ] D[115,213] = var(54); // [ var(213) , var(115) ] D[116,213] = (-1)*var(60); // [ var(213) , var(116) ] D[117,213] = var(67); // [ var(213) , var(117) ] D[118,213] = (-1)*var(73); // [ var(213) , var(118) ] D[119,213] = var(79); // [ var(213) , var(119) ] D[4,214] = var(210); // [ var(214) , var(4) ] D[8,214] = var(209); // [ var(214) , var(8) ] D[10,214] = var(207); // [ var(214) , var(10) ] D[12,214] = (-1)*var(206); // [ var(214) , var(12) ] D[18,214] = (-1)*var(203); // [ var(214) , var(18) ] D[20,214] = var(201); // [ var(214) , var(20) ] D[26,214] = var(197); // [ var(214) , var(26) ] D[32,214] = var(193); // [ var(214) , var(32) ] D[36,214] = (-1)*var(189); // [ var(214) , var(36) ] D[37,214] = (-1)*var(188); // [ var(214) , var(37) ] D[40,214] = (-1)*var(187); // [ var(214) , var(40) ] D[42,214] = (-1)*var(183); // [ var(214) , var(42) ] D[45,214] = var(182); // [ var(214) , var(45) ] D[48,214] = var(180); // [ var(214) , var(48) ] D[52,214] = (-1)*var(176); // [ var(214) , var(52) ] D[56,214] = var(172); // [ var(214) , var(56) ] D[60,214] = (-1)*var(168); // [ var(214) , var(60) ] D[62,214] = (-1)*var(165); // [ var(214) , var(62) ] D[63,214] = var(162); // [ var(214) , var(63) ] D[67,214] = var(160); // [ var(214) , var(67) ] D[68,214] = var(157); // [ var(214) , var(68) ] D[69,214] = var(156); // [ var(214) , var(69) ] D[73,214] = (-1)*var(152); // [ var(214) , var(73) ] D[77,214] = (-1)*var(146); // [ var(214) , var(77) ] D[81,214] = (-1)*var(140); // [ var(214) , var(81) ] D[83,214] = var(138); // [ var(214) , var(83) ] D[86,214] = var(132); // [ var(214) , var(86) ] D[87,214] = (-1)*var(130); // [ var(214) , var(87) ] D[89,214] = (-1)*var(128); // [ var(214) , var(89) ] D[90,214] = (-1)*var(124); // [ var(214) , var(90) ] D[94,214] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-4)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(214) , var(94) ] D[98,214] = (-1)*var(3); // [ var(214) , var(98) ] D[99,214] = (-1)*var(7); // [ var(214) , var(99) ] D[101,214] = var(9); // [ var(214) , var(101) ] D[103,214] = var(14); // [ var(214) , var(103) ] D[106,214] = (-1)*var(21); // [ var(214) , var(106) ] D[110,214] = var(35); // [ var(214) , var(110) ] D[111,214] = (-1)*var(39); // [ var(214) , var(111) ] D[112,214] = var(41); // [ var(214) , var(112) ] D[113,214] = (-1)*var(46); // [ var(214) , var(113) ] D[116,214] = var(58); // [ var(214) , var(116) ] D[117,214] = (-1)*var(64); // [ var(214) , var(117) ] D[118,214] = var(71); // [ var(214) , var(118) ] D[120,214] = (-1)*var(84); // [ var(214) , var(120) ] D[2,215] = var(212); // [ var(215) , var(2) ] D[5,215] = var(211); // [ var(215) , var(5) ] D[7,215] = var(210); // [ var(215) , var(7) ] D[15,215] = (-1)*var(205); // [ var(215) , var(15) ] D[18,215] = (-1)*var(204); // [ var(215) , var(18) ] D[21,215] = (-1)*var(201); // [ var(215) , var(21) ] D[25,215] = var(199); // [ var(215) , var(25) ] D[29,215] = var(195); // [ var(215) , var(29) ] D[30,215] = (-1)*var(194); // [ var(215) , var(30) ] D[34,215] = var(192); // [ var(215) , var(34) ] D[41,215] = (-1)*var(187); // [ var(215) , var(41) ] D[42,215] = (-1)*var(184); // [ var(215) , var(42) ] D[46,215] = var(182); // [ var(215) , var(46) ] D[50,215] = var(179); // [ var(215) , var(50) ] D[54,215] = (-1)*var(175); // [ var(215) , var(54) ] D[55,215] = var(174); // [ var(215) , var(55) ] D[59,215] = (-1)*var(170); // [ var(215) , var(59) ] D[62,215] = (-1)*var(166); // [ var(215) , var(62) ] D[64,215] = var(162); // [ var(215) , var(64) ] D[67,215] = var(161); // [ var(215) , var(67) ] D[72,215] = (-1)*var(154); // [ var(215) , var(72) ] D[74,215] = var(150); // [ var(215) , var(74) ] D[75,215] = (-1)*var(149); // [ var(215) , var(75) ] D[79,215] = (-1)*var(145); // [ var(215) , var(79) ] D[81,215] = var(141); // [ var(215) , var(81) ] D[84,215] = var(138); // [ var(215) , var(84) ] D[85,215] = var(135); // [ var(215) , var(85) ] D[90,215] = (-1)*var(127); // [ var(215) , var(90) ] D[91,215] = (-1)*var(125); // [ var(215) , var(91) ] D[92,215] = (-1)*var(122); // [ var(215) , var(92) ] D[95,215] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-3)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(215) , var(95) ] D[99,215] = (-1)*var(4); // [ var(215) , var(99) ] D[100,215] = (-1)*var(6); // [ var(215) , var(100) ] D[102,215] = var(11); // [ var(215) , var(102) ] D[104,215] = (-1)*var(16); // [ var(215) , var(104) ] D[106,215] = var(20); // [ var(215) , var(106) ] D[108,215] = (-1)*var(27); // [ var(215) , var(108) ] D[109,215] = var(31); // [ var(215) , var(109) ] D[112,215] = var(40); // [ var(215) , var(112) ] D[113,215] = (-1)*var(45); // [ var(215) , var(113) ] D[115,215] = var(51); // [ var(215) , var(115) ] D[117,215] = (-1)*var(63); // [ var(215) , var(117) ] D[119,215] = var(76); // [ var(215) , var(119) ] D[120,215] = (-1)*var(83); // [ var(215) , var(120) ] D[6,216] = var(212); // [ var(216) , var(6) ] D[13,216] = var(208); // [ var(216) , var(13) ] D[14,216] = (-1)*var(207); // [ var(216) , var(14) ] D[20,216] = var(204); // [ var(216) , var(20) ] D[21,216] = (-1)*var(203); // [ var(216) , var(21) ] D[22,216] = var(202); // [ var(216) , var(22) ] D[27,216] = (-1)*var(199); // [ var(216) , var(27) ] D[28,216] = (-1)*var(198); // [ var(216) , var(28) ] D[29,216] = var(196); // [ var(216) , var(29) ] D[31,216] = var(194); // [ var(216) , var(31) ] D[35,216] = var(193); // [ var(216) , var(35) ] D[36,216] = var(191); // [ var(216) , var(36) ] D[39,216] = (-1)*var(188); // [ var(216) , var(39) ] D[43,216] = (-1)*var(186); // [ var(216) , var(43) ] D[47,216] = var(181); // [ var(216) , var(47) ] D[61,216] = (-1)*var(167); // [ var(216) , var(61) ] D[66,216] = var(163); // [ var(216) , var(66) ] D[68,216] = var(159); // [ var(216) , var(68) ] D[71,216] = (-1)*var(156); // [ var(216) , var(71) ] D[73,216] = (-1)*var(155); // [ var(216) , var(73) ] D[74,216] = (-1)*var(151); // [ var(216) , var(74) ] D[76,216] = (-1)*var(149); // [ var(216) , var(76) ] D[78,216] = var(148); // [ var(216) , var(78) ] D[79,216] = var(147); // [ var(216) , var(79) ] D[82,216] = (-1)*var(142); // [ var(216) , var(82) ] D[83,216] = var(141); // [ var(216) , var(83) ] D[84,216] = (-1)*var(140); // [ var(216) , var(84) ] D[87,216] = var(134); // [ var(216) , var(87) ] D[88,216] = (-1)*var(133); // [ var(216) , var(88) ] D[92,216] = (-1)*var(126); // [ var(216) , var(92) ] D[96,216] = (-1)*var(241)+(-1)*var(242)+(-2)*var(243)+(-3)*var(244)+(-3)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(216) , var(96) ] D[100,216] = (-1)*var(2); // [ var(216) , var(100) ] D[103,216] = (-1)*var(10); // [ var(216) , var(103) ] D[105,216] = var(17); // [ var(216) , var(105) ] D[106,216] = (-1)*var(18); // [ var(216) , var(106) ] D[107,216] = (-1)*var(23); // [ var(216) , var(107) ] D[108,216] = var(25); // [ var(216) , var(108) ] D[109,216] = (-1)*var(30); // [ var(216) , var(109) ] D[110,216] = var(32); // [ var(216) , var(110) ] D[111,216] = (-1)*var(37); // [ var(216) , var(111) ] D[114,216] = var(44); // [ var(216) , var(114) ] D[118,216] = (-1)*var(69); // [ var(216) , var(118) ] D[119,216] = var(75); // [ var(216) , var(119) ] D[120,216] = (-1)*var(81); // [ var(216) , var(120) ] D[1,217] = var(213); // [ var(217) , var(1) ] D[9,217] = (-1)*var(209); // [ var(217) , var(9) ] D[16,217] = var(205); // [ var(217) , var(16) ] D[23,217] = var(202); // [ var(217) , var(23) ] D[24,217] = (-1)*var(200); // [ var(217) , var(24) ] D[30,217] = (-1)*var(196); // [ var(217) , var(30) ] D[31,217] = var(195); // [ var(217) , var(31) ] D[37,217] = var(191); // [ var(217) , var(37) ] D[38,217] = var(190); // [ var(217) , var(38) ] D[39,217] = (-1)*var(189); // [ var(217) , var(39) ] D[44,217] = (-1)*var(186); // [ var(217) , var(44) ] D[45,217] = (-1)*var(184); // [ var(217) , var(45) ] D[46,217] = (-1)*var(183); // [ var(217) , var(46) ] D[51,217] = var(179); // [ var(217) , var(51) ] D[52,217] = var(178); // [ var(217) , var(52) ] D[53,217] = var(177); // [ var(217) , var(53) ] D[57,217] = (-1)*var(173); // [ var(217) , var(57) ] D[58,217] = (-1)*var(172); // [ var(217) , var(58) ] D[59,217] = (-1)*var(171); // [ var(217) , var(59) ] D[63,217] = var(166); // [ var(217) , var(63) ] D[64,217] = var(165); // [ var(217) , var(64) ] D[66,217] = var(164); // [ var(217) , var(66) ] D[69,217] = var(159); // [ var(217) , var(69) ] D[70,217] = (-1)*var(158); // [ var(217) , var(70) ] D[71,217] = (-1)*var(157); // [ var(217) , var(71) ] D[75,217] = (-1)*var(151); // [ var(217) , var(75) ] D[76,217] = var(150); // [ var(217) , var(76) ] D[80,217] = var(144); // [ var(217) , var(80) ] D[82,217] = (-1)*var(143); // [ var(217) , var(82) ] D[85,217] = (-1)*var(136); // [ var(217) , var(85) ] D[89,217] = var(129); // [ var(217) , var(89) ] D[93,217] = (-1)*var(121); // [ var(217) , var(93) ] D[97,217] = (-2)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247); // [ var(217) , var(97) ] D[101,217] = (-1)*var(8); // [ var(217) , var(101) ] D[104,217] = var(15); // [ var(217) , var(104) ] D[107,217] = (-1)*var(22); // [ var(217) , var(107) ] D[109,217] = var(29); // [ var(217) , var(109) ] D[111,217] = (-1)*var(36); // [ var(217) , var(111) ] D[113,217] = (-1)*var(42); // [ var(217) , var(113) ] D[114,217] = var(43); // [ var(217) , var(114) ] D[115,217] = var(50); // [ var(217) , var(115) ] D[116,217] = (-1)*var(56); // [ var(217) , var(116) ] D[117,217] = var(62); // [ var(217) , var(117) ] D[118,217] = (-1)*var(68); // [ var(217) , var(118) ] D[119,217] = var(74); // [ var(217) , var(119) ] D[3,218] = var(214); // [ var(218) , var(3) ] D[8,218] = var(213); // [ var(218) , var(8) ] D[11,218] = (-1)*var(210); // [ var(218) , var(11) ] D[17,218] = (-1)*var(207); // [ var(218) , var(17) ] D[19,218] = var(206); // [ var(218) , var(19) ] D[25,218] = var(203); // [ var(218) , var(25) ] D[27,218] = (-1)*var(201); // [ var(218) , var(27) ] D[32,218] = (-1)*var(198); // [ var(218) , var(32) ] D[33,218] = (-1)*var(197); // [ var(218) , var(33) ] D[40,218] = var(192); // [ var(218) , var(40) ] D[43,218] = var(189); // [ var(218) , var(43) ] D[44,218] = var(188); // [ var(218) , var(44) ] D[48,218] = (-1)*var(185); // [ var(218) , var(48) ] D[50,218] = var(183); // [ var(218) , var(50) ] D[51,218] = (-1)*var(182); // [ var(218) , var(51) ] D[56,218] = (-1)*var(177); // [ var(218) , var(56) ] D[57,218] = var(176); // [ var(218) , var(57) ] D[62,218] = var(171); // [ var(218) , var(62) ] D[63,218] = (-1)*var(170); // [ var(218) , var(63) ] D[65,218] = var(168); // [ var(218) , var(65) ] D[68,218] = (-1)*var(164); // [ var(218) , var(68) ] D[69,218] = (-1)*var(163); // [ var(218) , var(69) ] D[72,218] = (-1)*var(160); // [ var(218) , var(72) ] D[77,218] = var(153); // [ var(218) , var(77) ] D[78,218] = var(152); // [ var(218) , var(78) ] D[81,218] = var(147); // [ var(218) , var(81) ] D[83,218] = (-1)*var(145); // [ var(218) , var(83) ] D[86,218] = (-1)*var(139); // [ var(218) , var(86) ] D[87,218] = var(137); // [ var(218) , var(87) ] D[90,218] = var(131); // [ var(218) , var(90) ] D[93,218] = (-1)*var(128); // [ var(218) , var(93) ] D[94,218] = (-1)*var(123); // [ var(218) , var(94) ] D[98,218] = (-1)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(218) , var(98) ] D[101,218] = (-1)*var(1); // [ var(218) , var(101) ] D[102,218] = (-1)*var(7); // [ var(218) , var(102) ] D[105,218] = var(14); // [ var(218) , var(105) ] D[108,218] = (-1)*var(21); // [ var(218) , var(108) ] D[110,218] = var(28); // [ var(218) , var(110) ] D[112,218] = var(34); // [ var(218) , var(112) ] D[114,218] = (-1)*var(39); // [ var(218) , var(114) ] D[115,218] = (-1)*var(46); // [ var(218) , var(115) ] D[116,218] = var(53); // [ var(218) , var(116) ] D[117,218] = (-1)*var(59); // [ var(218) , var(117) ] D[118,218] = var(66); // [ var(218) , var(118) ] D[120,218] = (-1)*var(79); // [ var(218) , var(120) ] D[4,219] = var(215); // [ var(219) , var(4) ] D[7,219] = var(214); // [ var(219) , var(7) ] D[10,219] = var(212); // [ var(219) , var(10) ] D[12,219] = (-1)*var(211); // [ var(219) , var(12) ] D[15,219] = (-1)*var(209); // [ var(219) , var(15) ] D[18,219] = (-1)*var(208); // [ var(219) , var(18) ] D[28,219] = var(201); // [ var(219) , var(28) ] D[32,219] = var(199); // [ var(219) , var(32) ] D[34,219] = var(197); // [ var(219) , var(34) ] D[36,219] = (-1)*var(195); // [ var(219) , var(36) ] D[37,219] = (-1)*var(194); // [ var(219) , var(37) ] D[42,219] = (-1)*var(190); // [ var(219) , var(42) ] D[49,219] = (-1)*var(187); // [ var(219) , var(49) ] D[53,219] = var(182); // [ var(219) , var(53) ] D[55,219] = var(180); // [ var(219) , var(55) ] D[56,219] = var(179); // [ var(219) , var(56) ] D[59,219] = (-1)*var(176); // [ var(219) , var(59) ] D[60,219] = (-1)*var(175); // [ var(219) , var(60) ] D[62,219] = (-1)*var(173); // [ var(219) , var(62) ] D[67,219] = var(169); // [ var(219) , var(67) ] D[70,219] = var(162); // [ var(219) , var(70) ] D[74,219] = var(157); // [ var(219) , var(74) ] D[75,219] = var(156); // [ var(219) , var(75) ] D[77,219] = (-1)*var(154); // [ var(219) , var(77) ] D[79,219] = (-1)*var(152); // [ var(219) , var(79) ] D[81,219] = (-1)*var(148); // [ var(219) , var(81) ] D[88,219] = var(138); // [ var(219) , var(88) ] D[89,219] = var(135); // [ var(219) , var(89) ] D[91,219] = var(132); // [ var(219) , var(91) ] D[92,219] = (-1)*var(130); // [ var(219) , var(92) ] D[94,219] = (-1)*var(127); // [ var(219) , var(94) ] D[95,219] = (-1)*var(124); // [ var(219) , var(95) ] D[99,219] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-4)*var(244)+(-3)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(219) , var(99) ] D[102,219] = (-1)*var(3); // [ var(219) , var(102) ] D[103,219] = (-1)*var(6); // [ var(219) , var(103) ] D[104,219] = var(9); // [ var(219) , var(104) ] D[106,219] = var(13); // [ var(219) , var(106) ] D[110,219] = (-1)*var(27); // [ var(219) , var(110) ] D[111,219] = var(31); // [ var(219) , var(111) ] D[112,219] = (-1)*var(33); // [ var(219) , var(112) ] D[113,219] = var(38); // [ var(219) , var(113) ] D[116,219] = (-1)*var(51); // [ var(219) , var(116) ] D[117,219] = var(57); // [ var(219) , var(117) ] D[119,219] = (-1)*var(71); // [ var(219) , var(119) ] D[120,219] = var(78); // [ var(219) , var(120) ] D[2,220] = var(216); // [ var(220) , var(2) ] D[6,220] = var(215); // [ var(220) , var(6) ] D[13,220] = var(211); // [ var(220) , var(13) ] D[14,220] = (-1)*var(210); // [ var(220) , var(14) ] D[21,220] = (-1)*var(206); // [ var(220) , var(21) ] D[22,220] = var(205); // [ var(220) , var(22) ] D[26,220] = (-1)*var(204); // [ var(220) , var(26) ] D[29,220] = var(200); // [ var(220) , var(29) ] D[33,220] = var(199); // [ var(220) , var(33) ] D[34,220] = var(198); // [ var(220) , var(34) ] D[38,220] = (-1)*var(194); // [ var(220) , var(38) ] D[41,220] = (-1)*var(193); // [ var(220) , var(41) ] D[42,220] = (-1)*var(191); // [ var(220) , var(42) ] D[46,220] = var(188); // [ var(220) , var(46) ] D[50,220] = var(186); // [ var(220) , var(50) ] D[54,220] = (-1)*var(181); // [ var(220) , var(54) ] D[61,220] = var(174); // [ var(220) , var(61) ] D[66,220] = (-1)*var(170); // [ var(220) , var(66) ] D[68,220] = (-1)*var(166); // [ var(220) , var(68) ] D[71,220] = var(162); // [ var(220) , var(71) ] D[73,220] = var(161); // [ var(220) , var(73) ] D[74,220] = var(158); // [ var(220) , var(74) ] D[78,220] = (-1)*var(154); // [ var(220) , var(78) ] D[79,220] = (-1)*var(153); // [ var(220) , var(79) ] D[80,220] = (-1)*var(149); // [ var(220) , var(80) ] D[84,220] = var(146); // [ var(220) , var(84) ] D[85,220] = (-1)*var(142); // [ var(220) , var(85) ] D[86,220] = var(141); // [ var(220) , var(86) ] D[90,220] = var(134); // [ var(220) , var(90) ] D[91,220] = (-1)*var(133); // [ var(220) , var(91) ] D[95,220] = (-1)*var(126); // [ var(220) , var(95) ] D[96,220] = (-1)*var(122); // [ var(220) , var(96) ] D[100,220] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-3)*var(244)+(-3)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(220) , var(100) ] D[103,220] = (-1)*var(4); // [ var(220) , var(103) ] D[105,220] = var(11); // [ var(220) , var(105) ] D[106,220] = (-1)*var(12); // [ var(220) , var(106) ] D[107,220] = (-1)*var(16); // [ var(220) , var(107) ] D[108,220] = var(19); // [ var(220) , var(108) ] D[109,220] = (-1)*var(24); // [ var(220) , var(109) ] D[112,220] = (-1)*var(32); // [ var(220) , var(112) ] D[113,220] = var(37); // [ var(220) , var(113) ] D[115,220] = (-1)*var(44); // [ var(220) , var(115) ] D[118,220] = var(63); // [ var(220) , var(118) ] D[119,220] = (-1)*var(70); // [ var(220) , var(119) ] D[120,220] = var(77); // [ var(220) , var(120) ] D[1,221] = var(218); // [ var(221) , var(1) ] D[8,221] = var(217); // [ var(221) , var(8) ] D[9,221] = (-1)*var(214); // [ var(221) , var(9) ] D[16,221] = var(210); // [ var(221) , var(16) ] D[23,221] = var(207); // [ var(221) , var(23) ] D[24,221] = (-1)*var(206); // [ var(221) , var(24) ] D[30,221] = (-1)*var(203); // [ var(221) , var(30) ] D[31,221] = var(201); // [ var(221) , var(31) ] D[37,221] = var(198); // [ var(221) , var(37) ] D[38,221] = var(197); // [ var(221) , var(38) ] D[44,221] = (-1)*var(193); // [ var(221) , var(44) ] D[45,221] = (-1)*var(192); // [ var(221) , var(45) ] D[47,221] = (-1)*var(189); // [ var(221) , var(47) ] D[51,221] = var(187); // [ var(221) , var(51) ] D[52,221] = var(185); // [ var(221) , var(52) ] D[54,221] = (-1)*var(183); // [ var(221) , var(54) ] D[57,221] = (-1)*var(180); // [ var(221) , var(57) ] D[60,221] = var(177); // [ var(221) , var(60) ] D[63,221] = var(174); // [ var(221) , var(63) ] D[65,221] = (-1)*var(172); // [ var(221) , var(65) ] D[67,221] = (-1)*var(171); // [ var(221) , var(67) ] D[69,221] = var(167); // [ var(221) , var(69) ] D[72,221] = var(165); // [ var(221) , var(72) ] D[73,221] = var(164); // [ var(221) , var(73) ] D[77,221] = (-1)*var(158); // [ var(221) , var(77) ] D[78,221] = (-1)*var(157); // [ var(221) , var(78) ] D[81,221] = (-1)*var(151); // [ var(221) , var(81) ] D[83,221] = var(150); // [ var(221) , var(83) ] D[86,221] = var(144); // [ var(221) , var(86) ] D[87,221] = (-1)*var(143); // [ var(221) , var(87) ] D[90,221] = (-1)*var(136); // [ var(221) , var(90) ] D[94,221] = var(129); // [ var(221) , var(94) ] D[97,221] = (-1)*var(128); // [ var(221) , var(97) ] D[98,221] = (-1)*var(121); // [ var(221) , var(98) ] D[101,221] = (-2)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-3)*var(245)+(-2)*var(246)+(-1)*var(247)+(-1)*var(248); // [ var(221) , var(101) ] D[104,221] = (-1)*var(7); // [ var(221) , var(104) ] D[107,221] = var(14); // [ var(221) , var(107) ] D[109,221] = (-1)*var(21); // [ var(221) , var(109) ] D[111,221] = var(28); // [ var(221) , var(111) ] D[113,221] = var(34); // [ var(221) , var(113) ] D[114,221] = (-1)*var(35); // [ var(221) , var(114) ] D[115,221] = (-1)*var(41); // [ var(221) , var(115) ] D[116,221] = var(49); // [ var(221) , var(116) ] D[117,221] = (-1)*var(55); // [ var(221) , var(117) ] D[118,221] = var(61); // [ var(221) , var(118) ] D[120,221] = (-1)*var(74); // [ var(221) , var(120) ] D[3,222] = var(219); // [ var(222) , var(3) ] D[7,222] = var(218); // [ var(222) , var(7) ] D[11,222] = (-1)*var(215); // [ var(222) , var(11) ] D[15,222] = (-1)*var(213); // [ var(222) , var(15) ] D[17,222] = (-1)*var(212); // [ var(222) , var(17) ] D[19,222] = var(211); // [ var(222) , var(19) ] D[25,222] = var(208); // [ var(222) , var(25) ] D[32,222] = (-1)*var(204); // [ var(222) , var(32) ] D[35,222] = (-1)*var(201); // [ var(222) , var(35) ] D[41,222] = (-1)*var(197); // [ var(222) , var(41) ] D[43,222] = var(195); // [ var(222) , var(43) ] D[44,222] = var(194); // [ var(222) , var(44) ] D[49,222] = var(192); // [ var(222) , var(49) ] D[50,222] = var(190); // [ var(222) , var(50) ] D[55,222] = (-1)*var(185); // [ var(222) , var(55) ] D[56,222] = (-1)*var(184); // [ var(222) , var(56) ] D[58,222] = (-1)*var(182); // [ var(222) , var(58) ] D[62,222] = var(178); // [ var(222) , var(62) ] D[64,222] = var(176); // [ var(222) , var(64) ] D[65,222] = var(175); // [ var(222) , var(65) ] D[70,222] = (-1)*var(170); // [ var(222) , var(70) ] D[72,222] = (-1)*var(169); // [ var(222) , var(72) ] D[74,222] = (-1)*var(164); // [ var(222) , var(74) ] D[75,222] = (-1)*var(163); // [ var(222) , var(75) ] D[77,222] = var(161); // [ var(222) , var(77) ] D[81,222] = var(155); // [ var(222) , var(81) ] D[84,222] = var(152); // [ var(222) , var(84) ] D[88,222] = (-1)*var(145); // [ var(222) , var(88) ] D[91,222] = (-1)*var(139); // [ var(222) , var(91) ] D[92,222] = var(137); // [ var(222) , var(92) ] D[93,222] = var(135); // [ var(222) , var(93) ] D[95,222] = var(131); // [ var(222) , var(95) ] D[98,222] = (-1)*var(127); // [ var(222) , var(98) ] D[99,222] = (-1)*var(123); // [ var(222) , var(99) ] D[102,222] = (-1)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-3)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(222) , var(102) ] D[104,222] = (-1)*var(1); // [ var(222) , var(104) ] D[105,222] = (-1)*var(6); // [ var(222) , var(105) ] D[108,222] = var(13); // [ var(222) , var(108) ] D[110,222] = (-1)*var(20); // [ var(222) , var(110) ] D[112,222] = (-1)*var(26); // [ var(222) , var(112) ] D[114,222] = var(31); // [ var(222) , var(114) ] D[115,222] = var(38); // [ var(222) , var(115) ] D[116,222] = (-1)*var(45); // [ var(222) , var(116) ] D[117,222] = var(52); // [ var(222) , var(117) ] D[119,222] = (-1)*var(66); // [ var(222) , var(119) ] D[120,222] = var(73); // [ var(222) , var(120) ] D[4,223] = var(220); // [ var(223) , var(4) ] D[6,223] = var(219); // [ var(223) , var(6) ] D[10,223] = var(216); // [ var(223) , var(10) ] D[14,223] = (-1)*var(214); // [ var(223) , var(14) ] D[20,223] = (-1)*var(211); // [ var(223) , var(20) ] D[22,223] = var(209); // [ var(223) , var(22) ] D[26,223] = (-1)*var(208); // [ var(223) , var(26) ] D[28,223] = var(206); // [ var(223) , var(28) ] D[34,223] = var(203); // [ var(223) , var(34) ] D[36,223] = (-1)*var(200); // [ var(223) , var(36) ] D[40,223] = var(199); // [ var(223) , var(40) ] D[42,223] = (-1)*var(196); // [ var(223) , var(42) ] D[45,223] = (-1)*var(194); // [ var(223) , var(45) ] D[49,223] = (-1)*var(193); // [ var(223) , var(49) ] D[53,223] = var(188); // [ var(223) , var(53) ] D[56,223] = var(186); // [ var(223) , var(56) ] D[60,223] = (-1)*var(181); // [ var(223) , var(60) ] D[61,223] = var(180); // [ var(223) , var(61) ] D[66,223] = (-1)*var(176); // [ var(223) , var(66) ] D[68,223] = (-1)*var(173); // [ var(223) , var(68) ] D[73,223] = var(169); // [ var(223) , var(73) ] D[74,223] = var(165); // [ var(223) , var(74) ] D[76,223] = var(162); // [ var(223) , var(76) ] D[79,223] = (-1)*var(160); // [ var(223) , var(79) ] D[80,223] = var(156); // [ var(223) , var(80) ] D[83,223] = (-1)*var(154); // [ var(223) , var(83) ] D[86,223] = (-1)*var(148); // [ var(223) , var(86) ] D[88,223] = var(146); // [ var(223) , var(88) ] D[89,223] = (-1)*var(142); // [ var(223) , var(89) ] D[91,223] = var(140); // [ var(223) , var(91) ] D[94,223] = var(134); // [ var(223) , var(94) ] D[96,223] = (-1)*var(130); // [ var(223) , var(96) ] D[99,223] = (-1)*var(126); // [ var(223) , var(99) ] D[100,223] = (-1)*var(124); // [ var(223) , var(100) ] D[103,223] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-4)*var(244)+(-3)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(223) , var(103) ] D[105,223] = (-1)*var(3); // [ var(223) , var(105) ] D[106,223] = (-1)*var(5); // [ var(223) , var(106) ] D[107,223] = var(9); // [ var(223) , var(107) ] D[110,223] = var(19); // [ var(223) , var(110) ] D[111,223] = (-1)*var(24); // [ var(223) , var(111) ] D[112,223] = var(25); // [ var(223) , var(112) ] D[113,223] = (-1)*var(30); // [ var(223) , var(113) ] D[116,223] = var(44); // [ var(223) , var(116) ] D[118,223] = (-1)*var(57); // [ var(223) , var(118) ] D[119,223] = var(64); // [ var(223) , var(119) ] D[120,223] = (-1)*var(72); // [ var(223) , var(120) ] D[1,224] = var(222); // [ var(224) , var(1) ] D[7,224] = var(221); // [ var(224) , var(7) ] D[9,224] = (-1)*var(219); // [ var(224) , var(9) ] D[15,224] = (-1)*var(217); // [ var(224) , var(15) ] D[16,224] = var(215); // [ var(224) , var(16) ] D[23,224] = var(212); // [ var(224) , var(23) ] D[24,224] = (-1)*var(211); // [ var(224) , var(24) ] D[30,224] = (-1)*var(208); // [ var(224) , var(30) ] D[37,224] = var(204); // [ var(224) , var(37) ] D[39,224] = var(201); // [ var(224) , var(39) ] D[44,224] = (-1)*var(199); // [ var(224) , var(44) ] D[46,224] = var(197); // [ var(224) , var(46) ] D[47,224] = (-1)*var(195); // [ var(224) , var(47) ] D[53,224] = (-1)*var(192); // [ var(224) , var(53) ] D[54,224] = (-1)*var(190); // [ var(224) , var(54) ] D[58,224] = var(187); // [ var(224) , var(58) ] D[59,224] = var(185); // [ var(224) , var(59) ] D[60,224] = var(184); // [ var(224) , var(60) ] D[64,224] = (-1)*var(180); // [ var(224) , var(64) ] D[65,224] = (-1)*var(179); // [ var(224) , var(65) ] D[67,224] = (-1)*var(178); // [ var(224) , var(67) ] D[70,224] = var(174); // [ var(224) , var(70) ] D[72,224] = var(173); // [ var(224) , var(72) ] D[75,224] = var(167); // [ var(224) , var(75) ] D[77,224] = (-1)*var(166); // [ var(224) , var(77) ] D[79,224] = var(164); // [ var(224) , var(79) ] D[81,224] = (-1)*var(159); // [ var(224) , var(81) ] D[84,224] = (-1)*var(157); // [ var(224) , var(84) ] D[88,224] = var(150); // [ var(224) , var(88) ] D[91,224] = var(144); // [ var(224) , var(91) ] D[92,224] = (-1)*var(143); // [ var(224) , var(92) ] D[95,224] = (-1)*var(136); // [ var(224) , var(95) ] D[97,224] = var(135); // [ var(224) , var(97) ] D[99,224] = var(129); // [ var(224) , var(99) ] D[101,224] = (-1)*var(127); // [ var(224) , var(101) ] D[102,224] = (-1)*var(121); // [ var(224) , var(102) ] D[104,224] = (-2)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-3)*var(245)+(-2)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(224) , var(104) ] D[107,224] = (-1)*var(6); // [ var(224) , var(107) ] D[109,224] = var(13); // [ var(224) , var(109) ] D[111,224] = (-1)*var(20); // [ var(224) , var(111) ] D[113,224] = (-1)*var(26); // [ var(224) , var(113) ] D[114,224] = var(27); // [ var(224) , var(114) ] D[115,224] = var(33); // [ var(224) , var(115) ] D[116,224] = (-1)*var(40); // [ var(224) , var(116) ] D[117,224] = var(48); // [ var(224) , var(117) ] D[119,224] = (-1)*var(61); // [ var(224) , var(119) ] D[120,224] = var(68); // [ var(224) , var(120) ] D[3,225] = var(223); // [ var(225) , var(3) ] D[6,225] = var(222); // [ var(225) , var(6) ] D[11,225] = (-1)*var(220); // [ var(225) , var(11) ] D[14,225] = (-1)*var(218); // [ var(225) , var(14) ] D[17,225] = (-1)*var(216); // [ var(225) , var(17) ] D[22,225] = var(213); // [ var(225) , var(22) ] D[27,225] = var(211); // [ var(225) , var(27) ] D[33,225] = var(208); // [ var(225) , var(33) ] D[35,225] = (-1)*var(206); // [ var(225) , var(35) ] D[40,225] = (-1)*var(204); // [ var(225) , var(40) ] D[41,225] = (-1)*var(203); // [ var(225) , var(41) ] D[43,225] = var(200); // [ var(225) , var(43) ] D[49,225] = var(198); // [ var(225) , var(49) ] D[50,225] = var(196); // [ var(225) , var(50) ] D[51,225] = var(194); // [ var(225) , var(51) ] D[56,225] = (-1)*var(191); // [ var(225) , var(56) ] D[58,225] = (-1)*var(188); // [ var(225) , var(58) ] D[61,225] = (-1)*var(185); // [ var(225) , var(61) ] D[65,225] = var(181); // [ var(225) , var(65) ] D[68,225] = var(178); // [ var(225) , var(68) ] D[71,225] = var(176); // [ var(225) , var(71) ] D[74,225] = (-1)*var(171); // [ var(225) , var(74) ] D[76,225] = (-1)*var(170); // [ var(225) , var(76) ] D[78,225] = (-1)*var(169); // [ var(225) , var(78) ] D[80,225] = (-1)*var(163); // [ var(225) , var(80) ] D[83,225] = var(161); // [ var(225) , var(83) ] D[84,225] = var(160); // [ var(225) , var(84) ] D[86,225] = var(155); // [ var(225) , var(86) ] D[88,225] = (-1)*var(153); // [ var(225) , var(88) ] D[91,225] = (-1)*var(147); // [ var(225) , var(91) ] D[93,225] = (-1)*var(142); // [ var(225) , var(93) ] D[96,225] = var(137); // [ var(225) , var(96) ] D[98,225] = var(134); // [ var(225) , var(98) ] D[100,225] = var(131); // [ var(225) , var(100) ] D[102,225] = (-1)*var(126); // [ var(225) , var(102) ] D[103,225] = (-1)*var(123); // [ var(225) , var(103) ] D[105,225] = (-1)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-3)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(225) , var(105) ] D[107,225] = (-1)*var(1); // [ var(225) , var(107) ] D[108,225] = (-1)*var(5); // [ var(225) , var(108) ] D[110,225] = var(12); // [ var(225) , var(110) ] D[112,225] = var(18); // [ var(225) , var(112) ] D[114,225] = (-1)*var(24); // [ var(225) , var(114) ] D[115,225] = (-1)*var(30); // [ var(225) , var(115) ] D[116,225] = var(37); // [ var(225) , var(116) ] D[118,225] = (-1)*var(52); // [ var(225) , var(118) ] D[119,225] = var(59); // [ var(225) , var(119) ] D[120,225] = (-1)*var(67); // [ var(225) , var(120) ] D[5,226] = var(223); // [ var(226) , var(5) ] D[12,226] = var(220); // [ var(226) , var(12) ] D[13,226] = (-1)*var(219); // [ var(226) , var(13) ] D[18,226] = var(216); // [ var(226) , var(18) ] D[20,226] = (-1)*var(215); // [ var(226) , var(20) ] D[21,226] = var(214); // [ var(226) , var(21) ] D[26,226] = (-1)*var(212); // [ var(226) , var(26) ] D[28,226] = var(210); // [ var(226) , var(28) ] D[29,226] = (-1)*var(209); // [ var(226) , var(29) ] D[34,226] = var(207); // [ var(226) , var(34) ] D[36,226] = (-1)*var(205); // [ var(226) , var(36) ] D[42,226] = (-1)*var(202); // [ var(226) , var(42) ] D[48,226] = var(199); // [ var(226) , var(48) ] D[52,226] = (-1)*var(194); // [ var(226) , var(52) ] D[55,226] = (-1)*var(193); // [ var(226) , var(55) ] D[59,226] = var(188); // [ var(226) , var(59) ] D[61,226] = var(187); // [ var(226) , var(61) ] D[62,226] = var(186); // [ var(226) , var(62) ] D[66,226] = (-1)*var(182); // [ var(226) , var(66) ] D[67,226] = (-1)*var(181); // [ var(226) , var(67) ] D[68,226] = (-1)*var(179); // [ var(226) , var(68) ] D[73,226] = var(175); // [ var(226) , var(73) ] D[74,226] = var(172); // [ var(226) , var(74) ] D[79,226] = (-1)*var(168); // [ var(226) , var(79) ] D[82,226] = var(162); // [ var(226) , var(82) ] D[85,226] = var(156); // [ var(226) , var(85) ] D[87,226] = (-1)*var(154); // [ var(226) , var(87) ] D[89,226] = var(149); // [ var(226) , var(89) ] D[90,226] = (-1)*var(148); // [ var(226) , var(90) ] D[92,226] = var(146); // [ var(226) , var(92) ] D[94,226] = (-1)*var(141); // [ var(226) , var(94) ] D[95,226] = var(140); // [ var(226) , var(95) ] D[96,226] = (-1)*var(138); // [ var(226) , var(96) ] D[99,226] = var(133); // [ var(226) , var(99) ] D[100,226] = (-1)*var(132); // [ var(226) , var(100) ] D[103,226] = (-1)*var(125); // [ var(226) , var(103) ] D[106,226] = (-1)*var(241)+(-2)*var(242)+(-2)*var(243)+(-4)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(226) , var(106) ] D[108,226] = (-1)*var(3); // [ var(226) , var(108) ] D[109,226] = var(9); // [ var(226) , var(109) ] D[110,226] = (-1)*var(11); // [ var(226) , var(110) ] D[111,226] = var(16); // [ var(226) , var(111) ] D[112,226] = (-1)*var(17); // [ var(226) , var(112) ] D[113,226] = var(23); // [ var(226) , var(113) ] D[117,226] = (-1)*var(44); // [ var(226) , var(117) ] D[118,226] = var(51); // [ var(226) , var(118) ] D[119,226] = (-1)*var(58); // [ var(226) , var(119) ] D[120,226] = var(65); // [ var(226) , var(120) ] D[1,227] = var(225); // [ var(227) , var(1) ] D[6,227] = var(224); // [ var(227) , var(6) ] D[9,227] = (-1)*var(223); // [ var(227) , var(9) ] D[14,227] = (-1)*var(221); // [ var(227) , var(14) ] D[16,227] = var(220); // [ var(227) , var(16) ] D[22,227] = var(217); // [ var(227) , var(22) ] D[23,227] = var(216); // [ var(227) , var(23) ] D[31,227] = (-1)*var(211); // [ var(227) , var(31) ] D[38,227] = (-1)*var(208); // [ var(227) , var(38) ] D[39,227] = var(206); // [ var(227) , var(39) ] D[45,227] = var(204); // [ var(227) , var(45) ] D[46,227] = var(203); // [ var(227) , var(46) ] D[47,227] = (-1)*var(200); // [ var(227) , var(47) ] D[51,227] = (-1)*var(199); // [ var(227) , var(51) ] D[53,227] = (-1)*var(198); // [ var(227) , var(53) ] D[54,227] = (-1)*var(196); // [ var(227) , var(54) ] D[58,227] = var(193); // [ var(227) , var(58) ] D[60,227] = var(191); // [ var(227) , var(60) ] D[65,227] = (-1)*var(186); // [ var(227) , var(65) ] D[66,227] = var(185); // [ var(227) , var(66) ] D[71,227] = (-1)*var(180); // [ var(227) , var(71) ] D[73,227] = (-1)*var(178); // [ var(227) , var(73) ] D[76,227] = var(174); // [ var(227) , var(76) ] D[78,227] = var(173); // [ var(227) , var(78) ] D[79,227] = var(171); // [ var(227) , var(79) ] D[80,227] = var(167); // [ var(227) , var(80) ] D[83,227] = (-1)*var(166); // [ var(227) , var(83) ] D[84,227] = (-1)*var(165); // [ var(227) , var(84) ] D[86,227] = (-1)*var(159); // [ var(227) , var(86) ] D[88,227] = var(158); // [ var(227) , var(88) ] D[91,227] = var(151); // [ var(227) , var(91) ] D[96,227] = (-1)*var(143); // [ var(227) , var(96) ] D[97,227] = (-1)*var(142); // [ var(227) , var(97) ] D[100,227] = (-1)*var(136); // [ var(227) , var(100) ] D[101,227] = var(134); // [ var(227) , var(101) ] D[103,227] = var(129); // [ var(227) , var(103) ] D[104,227] = (-1)*var(126); // [ var(227) , var(104) ] D[105,227] = (-1)*var(121); // [ var(227) , var(105) ] D[107,227] = (-2)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-3)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(227) , var(107) ] D[109,227] = (-1)*var(5); // [ var(227) , var(109) ] D[111,227] = var(12); // [ var(227) , var(111) ] D[113,227] = var(18); // [ var(227) , var(113) ] D[114,227] = (-1)*var(19); // [ var(227) , var(114) ] D[115,227] = (-1)*var(25); // [ var(227) , var(115) ] D[116,227] = var(32); // [ var(227) , var(116) ] D[118,227] = (-1)*var(48); // [ var(227) , var(118) ] D[119,227] = var(55); // [ var(227) , var(119) ] D[120,227] = (-1)*var(62); // [ var(227) , var(120) ] D[3,228] = var(226); // [ var(228) , var(3) ] D[5,228] = var(225); // [ var(228) , var(5) ] D[13,228] = (-1)*var(222); // [ var(228) , var(13) ] D[19,228] = (-1)*var(220); // [ var(228) , var(19) ] D[21,228] = var(218); // [ var(228) , var(21) ] D[25,228] = (-1)*var(216); // [ var(228) , var(25) ] D[27,228] = var(215); // [ var(228) , var(27) ] D[29,228] = (-1)*var(213); // [ var(228) , var(29) ] D[33,228] = var(212); // [ var(228) , var(33) ] D[35,228] = (-1)*var(210); // [ var(228) , var(35) ] D[41,228] = (-1)*var(207); // [ var(228) , var(41) ] D[43,228] = var(205); // [ var(228) , var(43) ] D[48,228] = (-1)*var(204); // [ var(228) , var(48) ] D[50,228] = var(202); // [ var(228) , var(50) ] D[55,228] = var(198); // [ var(228) , var(55) ] D[57,228] = var(194); // [ var(228) , var(57) ] D[61,228] = (-1)*var(192); // [ var(228) , var(61) ] D[62,228] = (-1)*var(191); // [ var(228) , var(62) ] D[64,228] = (-1)*var(188); // [ var(228) , var(64) ] D[68,228] = var(184); // [ var(228) , var(68) ] D[71,228] = var(182); // [ var(228) , var(71) ] D[72,228] = var(181); // [ var(228) , var(72) ] D[74,228] = (-1)*var(177); // [ var(228) , var(74) ] D[78,228] = (-1)*var(175); // [ var(228) , var(78) ] D[82,228] = (-1)*var(170); // [ var(228) , var(82) ] D[84,228] = var(168); // [ var(228) , var(84) ] D[85,228] = (-1)*var(163); // [ var(228) , var(85) ] D[87,228] = var(161); // [ var(228) , var(87) ] D[90,228] = var(155); // [ var(228) , var(90) ] D[92,228] = (-1)*var(153); // [ var(228) , var(92) ] D[93,228] = var(149); // [ var(228) , var(93) ] D[95,228] = (-1)*var(147); // [ var(228) , var(95) ] D[96,228] = var(145); // [ var(228) , var(96) ] D[98,228] = (-1)*var(141); // [ var(228) , var(98) ] D[100,228] = var(139); // [ var(228) , var(100) ] D[102,228] = var(133); // [ var(228) , var(102) ] D[105,228] = (-1)*var(125); // [ var(228) , var(105) ] D[106,228] = (-1)*var(123); // [ var(228) , var(106) ] D[108,228] = (-1)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(228) , var(108) ] D[109,228] = (-1)*var(1); // [ var(228) , var(109) ] D[110,228] = (-1)*var(4); // [ var(228) , var(110) ] D[112,228] = (-1)*var(10); // [ var(228) , var(112) ] D[114,228] = var(16); // [ var(228) , var(114) ] D[115,228] = var(23); // [ var(228) , var(115) ] D[117,228] = (-1)*var(37); // [ var(228) , var(117) ] D[118,228] = var(45); // [ var(228) , var(118) ] D[119,228] = (-1)*var(53); // [ var(228) , var(119) ] D[120,228] = var(60); // [ var(228) , var(120) ] D[1,229] = var(228); // [ var(229) , var(1) ] D[5,229] = var(227); // [ var(229) , var(5) ] D[9,229] = (-1)*var(226); // [ var(229) , var(9) ] D[13,229] = (-1)*var(224); // [ var(229) , var(13) ] D[21,229] = var(221); // [ var(229) , var(21) ] D[24,229] = var(220); // [ var(229) , var(24) ] D[29,229] = (-1)*var(217); // [ var(229) , var(29) ] D[30,229] = var(216); // [ var(229) , var(30) ] D[31,229] = (-1)*var(215); // [ var(229) , var(31) ] D[38,229] = (-1)*var(212); // [ var(229) , var(38) ] D[39,229] = var(210); // [ var(229) , var(39) ] D[46,229] = var(207); // [ var(229) , var(46) ] D[47,229] = (-1)*var(205); // [ var(229) , var(47) ] D[52,229] = var(204); // [ var(229) , var(52) ] D[54,229] = (-1)*var(202); // [ var(229) , var(54) ] D[57,229] = (-1)*var(199); // [ var(229) , var(57) ] D[59,229] = (-1)*var(198); // [ var(229) , var(59) ] D[64,229] = var(193); // [ var(229) , var(64) ] D[66,229] = var(192); // [ var(229) , var(66) ] D[67,229] = var(191); // [ var(229) , var(67) ] D[71,229] = (-1)*var(187); // [ var(229) , var(71) ] D[72,229] = (-1)*var(186); // [ var(229) , var(72) ] D[73,229] = (-1)*var(184); // [ var(229) , var(73) ] D[78,229] = var(179); // [ var(229) , var(78) ] D[79,229] = var(177); // [ var(229) , var(79) ] D[82,229] = var(174); // [ var(229) , var(82) ] D[84,229] = (-1)*var(172); // [ var(229) , var(84) ] D[85,229] = var(167); // [ var(229) , var(85) ] D[87,229] = (-1)*var(166); // [ var(229) , var(87) ] D[90,229] = (-1)*var(159); // [ var(229) , var(90) ] D[92,229] = var(158); // [ var(229) , var(92) ] D[95,229] = var(151); // [ var(229) , var(95) ] D[96,229] = (-1)*var(150); // [ var(229) , var(96) ] D[97,229] = var(149); // [ var(229) , var(97) ] D[100,229] = (-1)*var(144); // [ var(229) , var(100) ] D[101,229] = (-1)*var(141); // [ var(229) , var(101) ] D[104,229] = var(133); // [ var(229) , var(104) ] D[106,229] = var(129); // [ var(229) , var(106) ] D[107,229] = (-1)*var(125); // [ var(229) , var(107) ] D[108,229] = (-1)*var(121); // [ var(229) , var(108) ] D[109,229] = (-2)*var(241)+(-2)*var(242)+(-3)*var(243)+(-4)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(229) , var(109) ] D[111,229] = (-1)*var(4); // [ var(229) , var(111) ] D[113,229] = (-1)*var(10); // [ var(229) , var(113) ] D[114,229] = var(11); // [ var(229) , var(114) ] D[115,229] = var(17); // [ var(229) , var(115) ] D[117,229] = (-1)*var(32); // [ var(229) , var(117) ] D[118,229] = var(40); // [ var(229) , var(118) ] D[119,229] = (-1)*var(49); // [ var(229) , var(119) ] D[120,229] = var(56); // [ var(229) , var(120) ] D[4,230] = var(228); // [ var(230) , var(4) ] D[11,230] = var(226); // [ var(230) , var(11) ] D[12,230] = (-1)*var(225); // [ var(230) , var(12) ] D[19,230] = (-1)*var(223); // [ var(230) , var(19) ] D[20,230] = var(222); // [ var(230) , var(20) ] D[27,230] = var(219); // [ var(230) , var(27) ] D[28,230] = (-1)*var(218); // [ var(230) , var(28) ] D[32,230] = (-1)*var(216); // [ var(230) , var(32) ] D[35,230] = (-1)*var(214); // [ var(230) , var(35) ] D[36,230] = var(213); // [ var(230) , var(36) ] D[40,230] = var(212); // [ var(230) , var(40) ] D[43,230] = var(209); // [ var(230) , var(43) ] D[48,230] = (-1)*var(208); // [ var(230) , var(48) ] D[49,230] = (-1)*var(207); // [ var(230) , var(49) ] D[55,230] = var(203); // [ var(230) , var(55) ] D[56,230] = var(202); // [ var(230) , var(56) ] D[61,230] = (-1)*var(197); // [ var(230) , var(61) ] D[62,230] = (-1)*var(196); // [ var(230) , var(62) ] D[63,230] = var(194); // [ var(230) , var(63) ] D[68,230] = var(190); // [ var(230) , var(68) ] D[70,230] = (-1)*var(188); // [ var(230) , var(70) ] D[74,230] = (-1)*var(183); // [ var(230) , var(74) ] D[76,230] = var(182); // [ var(230) , var(76) ] D[77,230] = var(181); // [ var(230) , var(77) ] D[82,230] = (-1)*var(176); // [ var(230) , var(82) ] D[83,230] = (-1)*var(175); // [ var(230) , var(83) ] D[87,230] = var(169); // [ var(230) , var(87) ] D[88,230] = var(168); // [ var(230) , var(88) ] D[89,230] = (-1)*var(163); // [ var(230) , var(89) ] D[92,230] = (-1)*var(160); // [ var(230) , var(92) ] D[93,230] = (-1)*var(156); // [ var(230) , var(93) ] D[94,230] = var(155); // [ var(230) , var(94) ] D[96,230] = var(152); // [ var(230) , var(96) ] D[98,230] = var(148); // [ var(230) , var(98) ] D[99,230] = (-1)*var(147); // [ var(230) , var(99) ] D[102,230] = (-1)*var(140); // [ var(230) , var(102) ] D[103,230] = var(139); // [ var(230) , var(103) ] D[105,230] = var(132); // [ var(230) , var(105) ] D[106,230] = (-1)*var(131); // [ var(230) , var(106) ] D[108,230] = (-1)*var(124); // [ var(230) , var(108) ] D[110,230] = (-1)*var(241)+(-2)*var(242)+(-3)*var(243)+(-5)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(230) , var(110) ] D[111,230] = (-1)*var(1); // [ var(230) , var(111) ] D[112,230] = var(2); // [ var(230) , var(112) ] D[114,230] = (-1)*var(9); // [ var(230) , var(114) ] D[116,230] = (-1)*var(23); // [ var(230) , var(116) ] D[117,230] = var(30); // [ var(230) , var(117) ] D[118,230] = (-1)*var(38); // [ var(230) , var(118) ] D[119,230] = var(46); // [ var(230) , var(119) ] D[120,230] = (-1)*var(54); // [ var(230) , var(120) ] D[1,231] = var(230); // [ var(231) , var(1) ] D[4,231] = var(229); // [ var(231) , var(4) ] D[12,231] = (-1)*var(227); // [ var(231) , var(12) ] D[16,231] = (-1)*var(226); // [ var(231) , var(16) ] D[20,231] = var(224); // [ var(231) , var(20) ] D[24,231] = var(223); // [ var(231) , var(24) ] D[28,231] = (-1)*var(221); // [ var(231) , var(28) ] D[31,231] = (-1)*var(219); // [ var(231) , var(31) ] D[36,231] = var(217); // [ var(231) , var(36) ] D[37,231] = var(216); // [ var(231) , var(37) ] D[39,231] = var(214); // [ var(231) , var(39) ] D[45,231] = (-1)*var(212); // [ var(231) , var(45) ] D[47,231] = (-1)*var(209); // [ var(231) , var(47) ] D[52,231] = var(208); // [ var(231) , var(52) ] D[53,231] = var(207); // [ var(231) , var(53) ] D[59,231] = (-1)*var(203); // [ var(231) , var(59) ] D[60,231] = (-1)*var(202); // [ var(231) , var(60) ] D[63,231] = (-1)*var(199); // [ var(231) , var(63) ] D[66,231] = var(197); // [ var(231) , var(66) ] D[67,231] = var(196); // [ var(231) , var(67) ] D[70,231] = var(193); // [ var(231) , var(70) ] D[73,231] = (-1)*var(190); // [ var(231) , var(73) ] D[76,231] = (-1)*var(187); // [ var(231) , var(76) ] D[77,231] = (-1)*var(186); // [ var(231) , var(77) ] D[79,231] = var(183); // [ var(231) , var(79) ] D[82,231] = var(180); // [ var(231) , var(82) ] D[83,231] = var(179); // [ var(231) , var(83) ] D[87,231] = (-1)*var(173); // [ var(231) , var(87) ] D[88,231] = (-1)*var(172); // [ var(231) , var(88) ] D[89,231] = var(167); // [ var(231) , var(89) ] D[92,231] = var(165); // [ var(231) , var(92) ] D[94,231] = (-1)*var(159); // [ var(231) , var(94) ] D[96,231] = (-1)*var(157); // [ var(231) , var(96) ] D[97,231] = (-1)*var(156); // [ var(231) , var(97) ] D[99,231] = var(151); // [ var(231) , var(99) ] D[101,231] = var(148); // [ var(231) , var(101) ] D[103,231] = (-1)*var(144); // [ var(231) , var(103) ] D[104,231] = (-1)*var(140); // [ var(231) , var(104) ] D[106,231] = var(136); // [ var(231) , var(106) ] D[107,231] = var(132); // [ var(231) , var(107) ] D[109,231] = (-1)*var(124); // [ var(231) , var(109) ] D[110,231] = (-1)*var(121); // [ var(231) , var(110) ] D[111,231] = (-2)*var(241)+(-2)*var(242)+(-3)*var(243)+(-5)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(231) , var(111) ] D[113,231] = var(2); // [ var(231) , var(113) ] D[114,231] = (-1)*var(3); // [ var(231) , var(114) ] D[116,231] = (-1)*var(17); // [ var(231) , var(116) ] D[117,231] = var(25); // [ var(231) , var(117) ] D[118,231] = (-1)*var(33); // [ var(231) , var(118) ] D[119,231] = var(41); // [ var(231) , var(119) ] D[120,231] = (-1)*var(50); // [ var(231) , var(120) ] D[2,232] = (-1)*var(230); // [ var(232) , var(2) ] D[10,232] = var(228); // [ var(232) , var(10) ] D[17,232] = var(226); // [ var(232) , var(17) ] D[18,232] = (-1)*var(225); // [ var(232) , var(18) ] D[25,232] = (-1)*var(223); // [ var(232) , var(25) ] D[26,232] = var(222); // [ var(232) , var(26) ] D[32,232] = var(220); // [ var(232) , var(32) ] D[33,232] = var(219); // [ var(232) , var(33) ] D[34,232] = (-1)*var(218); // [ var(232) , var(34) ] D[40,232] = (-1)*var(215); // [ var(232) , var(40) ] D[41,232] = (-1)*var(214); // [ var(232) , var(41) ] D[42,232] = var(213); // [ var(232) , var(42) ] D[48,232] = var(211); // [ var(232) , var(48) ] D[49,232] = var(210); // [ var(232) , var(49) ] D[50,232] = var(209); // [ var(232) , var(50) ] D[55,232] = (-1)*var(206); // [ var(232) , var(55) ] D[56,232] = (-1)*var(205); // [ var(232) , var(56) ] D[61,232] = var(201); // [ var(232) , var(61) ] D[62,232] = var(200); // [ var(232) , var(62) ] D[68,232] = (-1)*var(195); // [ var(232) , var(68) ] D[69,232] = (-1)*var(194); // [ var(232) , var(69) ] D[74,232] = var(189); // [ var(232) , var(74) ] D[75,232] = var(188); // [ var(232) , var(75) ] D[80,232] = (-1)*var(182); // [ var(232) , var(80) ] D[81,232] = (-1)*var(181); // [ var(232) , var(81) ] D[85,232] = var(176); // [ var(232) , var(85) ] D[86,232] = var(175); // [ var(232) , var(86) ] D[89,232] = (-1)*var(170); // [ var(232) , var(89) ] D[90,232] = (-1)*var(169); // [ var(232) , var(90) ] D[91,232] = (-1)*var(168); // [ var(232) , var(91) ] D[93,232] = (-1)*var(162); // [ var(232) , var(93) ] D[94,232] = var(161); // [ var(232) , var(94) ] D[95,232] = var(160); // [ var(232) , var(95) ] D[98,232] = var(154); // [ var(232) , var(98) ] D[99,232] = (-1)*var(153); // [ var(232) , var(99) ] D[100,232] = (-1)*var(152); // [ var(232) , var(100) ] D[102,232] = (-1)*var(146); // [ var(232) , var(102) ] D[103,232] = var(145); // [ var(232) , var(103) ] D[105,232] = var(138); // [ var(232) , var(105) ] D[106,232] = (-1)*var(137); // [ var(232) , var(106) ] D[108,232] = (-1)*var(130); // [ var(232) , var(108) ] D[110,232] = var(122); // [ var(232) , var(110) ] D[112,232] = (-1)*var(241)+(-3)*var(242)+(-3)*var(243)+(-5)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(232) , var(112) ] D[113,232] = (-1)*var(1); // [ var(232) , var(113) ] D[115,232] = (-1)*var(9); // [ var(232) , var(115) ] D[116,232] = var(16); // [ var(232) , var(116) ] D[117,232] = (-1)*var(24); // [ var(232) , var(117) ] D[118,232] = var(31); // [ var(232) , var(118) ] D[119,232] = (-1)*var(39); // [ var(232) , var(119) ] D[120,232] = var(47); // [ var(232) , var(120) ] D[1,233] = var(232); // [ var(233) , var(1) ] D[2,233] = (-1)*var(231); // [ var(233) , var(2) ] D[10,233] = var(229); // [ var(233) , var(10) ] D[18,233] = (-1)*var(227); // [ var(233) , var(18) ] D[23,233] = (-1)*var(226); // [ var(233) , var(23) ] D[26,233] = var(224); // [ var(233) , var(26) ] D[30,233] = var(223); // [ var(233) , var(30) ] D[34,233] = (-1)*var(221); // [ var(233) , var(34) ] D[37,233] = (-1)*var(220); // [ var(233) , var(37) ] D[38,233] = (-1)*var(219); // [ var(233) , var(38) ] D[42,233] = var(217); // [ var(233) , var(42) ] D[45,233] = var(215); // [ var(233) , var(45) ] D[46,233] = var(214); // [ var(233) , var(46) ] D[52,233] = (-1)*var(211); // [ var(233) , var(52) ] D[53,233] = (-1)*var(210); // [ var(233) , var(53) ] D[54,233] = (-1)*var(209); // [ var(233) , var(54) ] D[59,233] = var(206); // [ var(233) , var(59) ] D[60,233] = var(205); // [ var(233) , var(60) ] D[66,233] = (-1)*var(201); // [ var(233) , var(66) ] D[67,233] = (-1)*var(200); // [ var(233) , var(67) ] D[69,233] = var(199); // [ var(233) , var(69) ] D[73,233] = var(195); // [ var(233) , var(73) ] D[75,233] = (-1)*var(193); // [ var(233) , var(75) ] D[79,233] = (-1)*var(189); // [ var(233) , var(79) ] D[80,233] = var(187); // [ var(233) , var(80) ] D[81,233] = var(186); // [ var(233) , var(81) ] D[85,233] = (-1)*var(180); // [ var(233) , var(85) ] D[86,233] = (-1)*var(179); // [ var(233) , var(86) ] D[89,233] = var(174); // [ var(233) , var(89) ] D[90,233] = var(173); // [ var(233) , var(90) ] D[91,233] = var(172); // [ var(233) , var(91) ] D[94,233] = (-1)*var(166); // [ var(233) , var(94) ] D[95,233] = (-1)*var(165); // [ var(233) , var(95) ] D[97,233] = (-1)*var(162); // [ var(233) , var(97) ] D[99,233] = var(158); // [ var(233) , var(99) ] D[100,233] = var(157); // [ var(233) , var(100) ] D[101,233] = var(154); // [ var(233) , var(101) ] D[103,233] = (-1)*var(150); // [ var(233) , var(103) ] D[104,233] = (-1)*var(146); // [ var(233) , var(104) ] D[106,233] = var(143); // [ var(233) , var(106) ] D[107,233] = var(138); // [ var(233) , var(107) ] D[109,233] = (-1)*var(130); // [ var(233) , var(109) ] D[111,233] = var(122); // [ var(233) , var(111) ] D[112,233] = (-1)*var(121); // [ var(233) , var(112) ] D[113,233] = (-2)*var(241)+(-3)*var(242)+(-3)*var(243)+(-5)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(233) , var(113) ] D[115,233] = (-1)*var(3); // [ var(233) , var(115) ] D[116,233] = var(11); // [ var(233) , var(116) ] D[117,233] = (-1)*var(19); // [ var(233) , var(117) ] D[118,233] = var(27); // [ var(233) , var(118) ] D[119,233] = (-1)*var(35); // [ var(233) , var(119) ] D[120,233] = var(43); // [ var(233) , var(120) ] D[3,234] = var(231); // [ var(234) , var(3) ] D[9,234] = var(230); // [ var(234) , var(9) ] D[11,234] = (-1)*var(229); // [ var(234) , var(11) ] D[16,234] = (-1)*var(228); // [ var(234) , var(16) ] D[19,234] = var(227); // [ var(234) , var(19) ] D[24,234] = var(225); // [ var(234) , var(24) ] D[27,234] = (-1)*var(224); // [ var(234) , var(27) ] D[31,234] = (-1)*var(222); // [ var(234) , var(31) ] D[35,234] = var(221); // [ var(234) , var(35) ] D[39,234] = var(218); // [ var(234) , var(39) ] D[43,234] = (-1)*var(217); // [ var(234) , var(43) ] D[44,234] = (-1)*var(216); // [ var(234) , var(44) ] D[47,234] = (-1)*var(213); // [ var(234) , var(47) ] D[51,234] = var(212); // [ var(234) , var(51) ] D[57,234] = (-1)*var(208); // [ var(234) , var(57) ] D[58,234] = (-1)*var(207); // [ var(234) , var(58) ] D[63,234] = var(204); // [ var(234) , var(63) ] D[64,234] = var(203); // [ var(234) , var(64) ] D[65,234] = var(202); // [ var(234) , var(65) ] D[70,234] = (-1)*var(198); // [ var(234) , var(70) ] D[71,234] = (-1)*var(197); // [ var(234) , var(71) ] D[72,234] = (-1)*var(196); // [ var(234) , var(72) ] D[76,234] = var(192); // [ var(234) , var(76) ] D[77,234] = var(191); // [ var(234) , var(77) ] D[78,234] = var(190); // [ var(234) , var(78) ] D[82,234] = (-1)*var(185); // [ var(234) , var(82) ] D[83,234] = (-1)*var(184); // [ var(234) , var(83) ] D[84,234] = (-1)*var(183); // [ var(234) , var(84) ] D[87,234] = var(178); // [ var(234) , var(87) ] D[88,234] = var(177); // [ var(234) , var(88) ] D[92,234] = (-1)*var(171); // [ var(234) , var(92) ] D[93,234] = var(167); // [ var(234) , var(93) ] D[96,234] = var(164); // [ var(234) , var(96) ] D[97,234] = var(163); // [ var(234) , var(97) ] D[98,234] = (-1)*var(159); // [ var(234) , var(98) ] D[101,234] = (-1)*var(155); // [ var(234) , var(101) ] D[102,234] = var(151); // [ var(234) , var(102) ] D[104,234] = var(147); // [ var(234) , var(104) ] D[105,234] = (-1)*var(144); // [ var(234) , var(105) ] D[107,234] = (-1)*var(139); // [ var(234) , var(107) ] D[108,234] = var(136); // [ var(234) , var(108) ] D[109,234] = var(131); // [ var(234) , var(109) ] D[110,234] = (-1)*var(129); // [ var(234) , var(110) ] D[111,234] = (-1)*var(123); // [ var(234) , var(111) ] D[114,234] = (-2)*var(241)+(-2)*var(242)+(-4)*var(243)+(-5)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(234) , var(114) ] D[115,234] = var(2); // [ var(234) , var(115) ] D[116,234] = (-1)*var(10); // [ var(234) , var(116) ] D[117,234] = var(18); // [ var(234) , var(117) ] D[118,234] = (-1)*var(26); // [ var(234) , var(118) ] D[119,234] = var(34); // [ var(234) , var(119) ] D[120,234] = (-1)*var(42); // [ var(234) , var(120) ] D[2,235] = (-1)*var(234); // [ var(235) , var(2) ] D[3,235] = var(233); // [ var(235) , var(3) ] D[9,235] = var(232); // [ var(235) , var(9) ] D[17,235] = (-1)*var(229); // [ var(235) , var(17) ] D[23,235] = (-1)*var(228); // [ var(235) , var(23) ] D[25,235] = var(227); // [ var(235) , var(25) ] D[30,235] = var(225); // [ var(235) , var(30) ] D[33,235] = (-1)*var(224); // [ var(235) , var(33) ] D[38,235] = (-1)*var(222); // [ var(235) , var(38) ] D[41,235] = var(221); // [ var(235) , var(41) ] D[44,235] = var(220); // [ var(235) , var(44) ] D[46,235] = var(218); // [ var(235) , var(46) ] D[50,235] = (-1)*var(217); // [ var(235) , var(50) ] D[51,235] = (-1)*var(215); // [ var(235) , var(51) ] D[54,235] = (-1)*var(213); // [ var(235) , var(54) ] D[57,235] = var(211); // [ var(235) , var(57) ] D[58,235] = var(210); // [ var(235) , var(58) ] D[64,235] = (-1)*var(206); // [ var(235) , var(64) ] D[65,235] = (-1)*var(205); // [ var(235) , var(65) ] D[69,235] = (-1)*var(204); // [ var(235) , var(69) ] D[71,235] = var(201); // [ var(235) , var(71) ] D[72,235] = var(200); // [ var(235) , var(72) ] D[75,235] = var(198); // [ var(235) , var(75) ] D[78,235] = (-1)*var(195); // [ var(235) , var(78) ] D[80,235] = (-1)*var(192); // [ var(235) , var(80) ] D[81,235] = (-1)*var(191); // [ var(235) , var(81) ] D[84,235] = var(189); // [ var(235) , var(84) ] D[85,235] = var(185); // [ var(235) , var(85) ] D[86,235] = var(184); // [ var(235) , var(86) ] D[90,235] = (-1)*var(178); // [ var(235) , var(90) ] D[91,235] = (-1)*var(177); // [ var(235) , var(91) ] D[93,235] = var(174); // [ var(235) , var(93) ] D[95,235] = var(171); // [ var(235) , var(95) ] D[97,235] = var(170); // [ var(235) , var(97) ] D[98,235] = (-1)*var(166); // [ var(235) , var(98) ] D[100,235] = (-1)*var(164); // [ var(235) , var(100) ] D[101,235] = (-1)*var(161); // [ var(235) , var(101) ] D[102,235] = var(158); // [ var(235) , var(102) ] D[104,235] = var(153); // [ var(235) , var(104) ] D[105,235] = (-1)*var(150); // [ var(235) , var(105) ] D[107,235] = (-1)*var(145); // [ var(235) , var(107) ] D[108,235] = var(143); // [ var(235) , var(108) ] D[109,235] = var(137); // [ var(235) , var(109) ] D[112,235] = (-1)*var(129); // [ var(235) , var(112) ] D[113,235] = (-1)*var(123); // [ var(235) , var(113) ] D[114,235] = var(122); // [ var(235) , var(114) ] D[115,235] = (-2)*var(241)+(-3)*var(242)+(-4)*var(243)+(-5)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(235) , var(115) ] D[116,235] = var(4); // [ var(235) , var(116) ] D[117,235] = (-1)*var(12); // [ var(235) , var(117) ] D[118,235] = var(20); // [ var(235) , var(118) ] D[119,235] = (-1)*var(28); // [ var(235) , var(119) ] D[120,235] = var(36); // [ var(235) , var(120) ] D[4,236] = (-1)*var(235); // [ var(236) , var(4) ] D[10,236] = var(234); // [ var(236) , var(10) ] D[11,236] = (-1)*var(233); // [ var(236) , var(11) ] D[16,236] = (-1)*var(232); // [ var(236) , var(16) ] D[17,236] = var(231); // [ var(236) , var(17) ] D[23,236] = var(230); // [ var(236) , var(23) ] D[32,236] = (-1)*var(227); // [ var(236) , var(32) ] D[37,236] = (-1)*var(225); // [ var(236) , var(37) ] D[40,236] = var(224); // [ var(236) , var(40) ] D[44,236] = (-1)*var(223); // [ var(236) , var(44) ] D[45,236] = var(222); // [ var(236) , var(45) ] D[49,236] = (-1)*var(221); // [ var(236) , var(49) ] D[51,236] = var(219); // [ var(236) , var(51) ] D[53,236] = (-1)*var(218); // [ var(236) , var(53) ] D[56,236] = var(217); // [ var(236) , var(56) ] D[58,236] = (-1)*var(214); // [ var(236) , var(58) ] D[60,236] = var(213); // [ var(236) , var(60) ] D[63,236] = (-1)*var(211); // [ var(236) , var(63) ] D[65,236] = var(209); // [ var(236) , var(65) ] D[69,236] = var(208); // [ var(236) , var(69) ] D[70,236] = var(206); // [ var(236) , var(70) ] D[75,236] = (-1)*var(203); // [ var(236) , var(75) ] D[76,236] = (-1)*var(201); // [ var(236) , var(76) ] D[77,236] = (-1)*var(200); // [ var(236) , var(77) ] D[80,236] = var(197); // [ var(236) , var(80) ] D[81,236] = var(196); // [ var(236) , var(81) ] D[83,236] = var(195); // [ var(236) , var(83) ] D[86,236] = (-1)*var(190); // [ var(236) , var(86) ] D[88,236] = (-1)*var(189); // [ var(236) , var(88) ] D[89,236] = (-1)*var(185); // [ var(236) , var(89) ] D[91,236] = var(183); // [ var(236) , var(91) ] D[93,236] = (-1)*var(180); // [ var(236) , var(93) ] D[94,236] = var(178); // [ var(236) , var(94) ] D[97,236] = (-1)*var(176); // [ var(236) , var(97) ] D[98,236] = var(173); // [ var(236) , var(98) ] D[99,236] = (-1)*var(171); // [ var(236) , var(99) ] D[101,236] = var(169); // [ var(236) , var(101) ] D[102,236] = (-1)*var(165); // [ var(236) , var(102) ] D[103,236] = var(164); // [ var(236) , var(103) ] D[104,236] = (-1)*var(160); // [ var(236) , var(104) ] D[105,236] = var(157); // [ var(236) , var(105) ] D[107,236] = var(152); // [ var(236) , var(107) ] D[110,236] = (-1)*var(143); // [ var(236) , var(110) ] D[111,236] = (-1)*var(137); // [ var(236) , var(111) ] D[112,236] = var(136); // [ var(236) , var(112) ] D[113,236] = var(131); // [ var(236) , var(113) ] D[114,236] = (-1)*var(130); // [ var(236) , var(114) ] D[115,236] = var(124); // [ var(236) , var(115) ] D[116,236] = (-2)*var(241)+(-3)*var(242)+(-4)*var(243)+(-6)*var(244)+(-4)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(236) , var(116) ] D[117,236] = var(5); // [ var(236) , var(117) ] D[118,236] = (-1)*var(13); // [ var(236) , var(118) ] D[119,236] = var(21); // [ var(236) , var(119) ] D[120,236] = (-1)*var(29); // [ var(236) , var(120) ] D[5,237] = (-1)*var(236); // [ var(237) , var(5) ] D[12,237] = var(235); // [ var(237) , var(12) ] D[18,237] = (-1)*var(234); // [ var(237) , var(18) ] D[19,237] = var(233); // [ var(237) , var(19) ] D[24,237] = var(232); // [ var(237) , var(24) ] D[25,237] = (-1)*var(231); // [ var(237) , var(25) ] D[30,237] = (-1)*var(230); // [ var(237) , var(30) ] D[32,237] = var(229); // [ var(237) , var(32) ] D[37,237] = var(228); // [ var(237) , var(37) ] D[44,237] = var(226); // [ var(237) , var(44) ] D[48,237] = (-1)*var(224); // [ var(237) , var(48) ] D[52,237] = (-1)*var(222); // [ var(237) , var(52) ] D[55,237] = var(221); // [ var(237) , var(55) ] D[57,237] = (-1)*var(219); // [ var(237) , var(57) ] D[59,237] = var(218); // [ var(237) , var(59) ] D[62,237] = (-1)*var(217); // [ var(237) , var(62) ] D[63,237] = var(215); // [ var(237) , var(63) ] D[64,237] = var(214); // [ var(237) , var(64) ] D[67,237] = (-1)*var(213); // [ var(237) , var(67) ] D[69,237] = (-1)*var(212); // [ var(237) , var(69) ] D[70,237] = (-1)*var(210); // [ var(237) , var(70) ] D[72,237] = (-1)*var(209); // [ var(237) , var(72) ] D[75,237] = var(207); // [ var(237) , var(75) ] D[77,237] = var(205); // [ var(237) , var(77) ] D[81,237] = (-1)*var(202); // [ var(237) , var(81) ] D[82,237] = var(201); // [ var(237) , var(82) ] D[85,237] = (-1)*var(197); // [ var(237) , var(85) ] D[87,237] = (-1)*var(195); // [ var(237) , var(87) ] D[89,237] = var(192); // [ var(237) , var(89) ] D[90,237] = var(190); // [ var(237) , var(90) ] D[92,237] = var(189); // [ var(237) , var(92) ] D[93,237] = var(187); // [ var(237) , var(93) ] D[94,237] = (-1)*var(184); // [ var(237) , var(94) ] D[95,237] = (-1)*var(183); // [ var(237) , var(95) ] D[97,237] = var(182); // [ var(237) , var(97) ] D[98,237] = (-1)*var(179); // [ var(237) , var(98) ] D[99,237] = var(177); // [ var(237) , var(99) ] D[101,237] = (-1)*var(175); // [ var(237) , var(101) ] D[102,237] = var(172); // [ var(237) , var(102) ] D[104,237] = var(168); // [ var(237) , var(104) ] D[106,237] = (-1)*var(164); // [ var(237) , var(106) ] D[108,237] = (-1)*var(157); // [ var(237) , var(108) ] D[109,237] = (-1)*var(152); // [ var(237) , var(109) ] D[110,237] = var(150); // [ var(237) , var(110) ] D[111,237] = var(145); // [ var(237) , var(111) ] D[112,237] = (-1)*var(144); // [ var(237) , var(112) ] D[113,237] = (-1)*var(139); // [ var(237) , var(113) ] D[114,237] = var(138); // [ var(237) , var(114) ] D[115,237] = (-1)*var(132); // [ var(237) , var(115) ] D[116,237] = var(125); // [ var(237) , var(116) ] D[117,237] = (-2)*var(241)+(-3)*var(242)+(-4)*var(243)+(-6)*var(244)+(-5)*var(245)+(-3)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(237) , var(117) ] D[118,237] = var(6); // [ var(237) , var(118) ] D[119,237] = (-1)*var(14); // [ var(237) , var(119) ] D[120,237] = var(22); // [ var(237) , var(120) ] D[6,238] = (-1)*var(237); // [ var(238) , var(6) ] D[13,238] = var(236); // [ var(238) , var(13) ] D[20,238] = (-1)*var(235); // [ var(238) , var(20) ] D[26,238] = var(234); // [ var(238) , var(26) ] D[27,238] = (-1)*var(233); // [ var(238) , var(27) ] D[31,238] = (-1)*var(232); // [ var(238) , var(31) ] D[33,238] = var(231); // [ var(238) , var(33) ] D[38,238] = var(230); // [ var(238) , var(38) ] D[40,238] = (-1)*var(229); // [ var(238) , var(40) ] D[45,238] = (-1)*var(228); // [ var(238) , var(45) ] D[48,238] = var(227); // [ var(238) , var(48) ] D[51,238] = (-1)*var(226); // [ var(238) , var(51) ] D[52,238] = var(225); // [ var(238) , var(52) ] D[57,238] = var(223); // [ var(238) , var(57) ] D[61,238] = (-1)*var(221); // [ var(238) , var(61) ] D[63,238] = (-1)*var(220); // [ var(238) , var(63) ] D[66,238] = (-1)*var(218); // [ var(238) , var(66) ] D[68,238] = var(217); // [ var(238) , var(68) ] D[69,238] = var(216); // [ var(238) , var(69) ] D[71,238] = (-1)*var(214); // [ var(238) , var(71) ] D[73,238] = var(213); // [ var(238) , var(73) ] D[76,238] = var(210); // [ var(238) , var(76) ] D[78,238] = var(209); // [ var(238) , var(78) ] D[80,238] = (-1)*var(207); // [ var(238) , var(80) ] D[82,238] = (-1)*var(206); // [ var(238) , var(82) ] D[83,238] = (-1)*var(205); // [ var(238) , var(83) ] D[85,238] = var(203); // [ var(238) , var(85) ] D[86,238] = var(202); // [ var(238) , var(86) ] D[87,238] = var(200); // [ var(238) , var(87) ] D[89,238] = (-1)*var(198); // [ var(238) , var(89) ] D[90,238] = (-1)*var(196); // [ var(238) , var(90) ] D[93,238] = (-1)*var(193); // [ var(238) , var(93) ] D[94,238] = var(191); // [ var(238) , var(94) ] D[96,238] = (-1)*var(189); // [ var(238) , var(96) ] D[97,238] = (-1)*var(188); // [ var(238) , var(97) ] D[98,238] = var(186); // [ var(238) , var(98) ] D[100,238] = var(183); // [ var(238) , var(100) ] D[101,238] = var(181); // [ var(238) , var(101) ] D[103,238] = (-1)*var(177); // [ var(238) , var(103) ] D[105,238] = (-1)*var(172); // [ var(238) , var(105) ] D[106,238] = var(171); // [ var(238) , var(106) ] D[107,238] = (-1)*var(168); // [ var(238) , var(107) ] D[108,238] = var(165); // [ var(238) , var(108) ] D[109,238] = var(160); // [ var(238) , var(109) ] D[110,238] = (-1)*var(158); // [ var(238) , var(110) ] D[111,238] = (-1)*var(153); // [ var(238) , var(111) ] D[112,238] = var(151); // [ var(238) , var(112) ] D[113,238] = var(147); // [ var(238) , var(113) ] D[114,238] = (-1)*var(146); // [ var(238) , var(114) ] D[115,238] = var(140); // [ var(238) , var(115) ] D[116,238] = (-1)*var(133); // [ var(238) , var(116) ] D[117,238] = var(126); // [ var(238) , var(117) ] D[118,238] = (-2)*var(241)+(-3)*var(242)+(-4)*var(243)+(-6)*var(244)+(-5)*var(245)+(-4)*var(246)+(-2)*var(247)+(-1)*var(248); // [ var(238) , var(118) ] D[119,238] = var(7); // [ var(238) , var(119) ] D[120,238] = (-1)*var(15); // [ var(238) , var(120) ] D[7,239] = (-1)*var(238); // [ var(239) , var(7) ] D[14,239] = var(237); // [ var(239) , var(14) ] D[21,239] = (-1)*var(236); // [ var(239) , var(21) ] D[28,239] = var(235); // [ var(239) , var(28) ] D[34,239] = (-1)*var(234); // [ var(239) , var(34) ] D[35,239] = var(233); // [ var(239) , var(35) ] D[39,239] = var(232); // [ var(239) , var(39) ] D[41,239] = (-1)*var(231); // [ var(239) , var(41) ] D[46,239] = (-1)*var(230); // [ var(239) , var(46) ] D[49,239] = var(229); // [ var(239) , var(49) ] D[53,239] = var(228); // [ var(239) , var(53) ] D[55,239] = (-1)*var(227); // [ var(239) , var(55) ] D[58,239] = var(226); // [ var(239) , var(58) ] D[59,239] = (-1)*var(225); // [ var(239) , var(59) ] D[61,239] = var(224); // [ var(239) , var(61) ] D[64,239] = (-1)*var(223); // [ var(239) , var(64) ] D[66,239] = var(222); // [ var(239) , var(66) ] D[70,239] = var(220); // [ var(239) , var(70) ] D[71,239] = var(219); // [ var(239) , var(71) ] D[74,239] = (-1)*var(217); // [ var(239) , var(74) ] D[75,239] = (-1)*var(216); // [ var(239) , var(75) ] D[76,239] = (-1)*var(215); // [ var(239) , var(76) ] D[79,239] = (-1)*var(213); // [ var(239) , var(79) ] D[80,239] = var(212); // [ var(239) , var(80) ] D[82,239] = var(211); // [ var(239) , var(82) ] D[84,239] = (-1)*var(209); // [ var(239) , var(84) ] D[85,239] = (-1)*var(208); // [ var(239) , var(85) ] D[88,239] = var(205); // [ var(239) , var(88) ] D[89,239] = var(204); // [ var(239) , var(89) ] D[91,239] = (-1)*var(202); // [ var(239) , var(91) ] D[92,239] = (-1)*var(200); // [ var(239) , var(92) ] D[93,239] = var(199); // [ var(239) , var(93) ] D[95,239] = var(196); // [ var(239) , var(95) ] D[96,239] = var(195); // [ var(239) , var(96) ] D[97,239] = var(194); // [ var(239) , var(97) ] D[99,239] = (-1)*var(191); // [ var(239) , var(99) ] D[100,239] = (-1)*var(190); // [ var(239) , var(100) ] D[102,239] = (-1)*var(186); // [ var(239) , var(102) ] D[103,239] = var(184); // [ var(239) , var(103) ] D[104,239] = (-1)*var(181); // [ var(239) , var(104) ] D[105,239] = var(179); // [ var(239) , var(105) ] D[106,239] = (-1)*var(178); // [ var(239) , var(106) ] D[107,239] = var(175); // [ var(239) , var(107) ] D[108,239] = (-1)*var(173); // [ var(239) , var(108) ] D[109,239] = (-1)*var(169); // [ var(239) , var(109) ] D[110,239] = var(166); // [ var(239) , var(110) ] D[111,239] = var(161); // [ var(239) , var(111) ] D[112,239] = (-1)*var(159); // [ var(239) , var(112) ] D[113,239] = (-1)*var(155); // [ var(239) , var(113) ] D[114,239] = var(154); // [ var(239) , var(114) ] D[115,239] = (-1)*var(148); // [ var(239) , var(115) ] D[116,239] = var(141); // [ var(239) , var(116) ] D[117,239] = (-1)*var(134); // [ var(239) , var(117) ] D[118,239] = var(127); // [ var(239) , var(118) ] D[119,239] = (-2)*var(241)+(-3)*var(242)+(-4)*var(243)+(-6)*var(244)+(-5)*var(245)+(-4)*var(246)+(-3)*var(247)+(-1)*var(248); // [ var(239) , var(119) ] D[120,239] = var(8); // [ var(239) , var(120) ] D[8,240] = (-1)*var(239); // [ var(240) , var(8) ] D[15,240] = var(238); // [ var(240) , var(15) ] D[22,240] = (-1)*var(237); // [ var(240) , var(22) ] D[29,240] = var(236); // [ var(240) , var(29) ] D[36,240] = (-1)*var(235); // [ var(240) , var(36) ] D[42,240] = var(234); // [ var(240) , var(42) ] D[43,240] = (-1)*var(233); // [ var(240) , var(43) ] D[47,240] = (-1)*var(232); // [ var(240) , var(47) ] D[50,240] = var(231); // [ var(240) , var(50) ] D[54,240] = var(230); // [ var(240) , var(54) ] D[56,240] = (-1)*var(229); // [ var(240) , var(56) ] D[60,240] = (-1)*var(228); // [ var(240) , var(60) ] D[62,240] = var(227); // [ var(240) , var(62) ] D[65,240] = (-1)*var(226); // [ var(240) , var(65) ] D[67,240] = var(225); // [ var(240) , var(67) ] D[68,240] = (-1)*var(224); // [ var(240) , var(68) ] D[72,240] = var(223); // [ var(240) , var(72) ] D[73,240] = (-1)*var(222); // [ var(240) , var(73) ] D[74,240] = var(221); // [ var(240) , var(74) ] D[77,240] = (-1)*var(220); // [ var(240) , var(77) ] D[78,240] = (-1)*var(219); // [ var(240) , var(78) ] D[79,240] = var(218); // [ var(240) , var(79) ] D[81,240] = var(216); // [ var(240) , var(81) ] D[83,240] = var(215); // [ var(240) , var(83) ] D[84,240] = var(214); // [ var(240) , var(84) ] D[86,240] = (-1)*var(212); // [ var(240) , var(86) ] D[87,240] = (-1)*var(211); // [ var(240) , var(87) ] D[88,240] = (-1)*var(210); // [ var(240) , var(88) ] D[90,240] = var(208); // [ var(240) , var(90) ] D[91,240] = var(207); // [ var(240) , var(91) ] D[92,240] = var(206); // [ var(240) , var(92) ] D[94,240] = (-1)*var(204); // [ var(240) , var(94) ] D[95,240] = (-1)*var(203); // [ var(240) , var(95) ] D[96,240] = (-1)*var(201); // [ var(240) , var(96) ] D[98,240] = (-1)*var(199); // [ var(240) , var(98) ] D[99,240] = var(198); // [ var(240) , var(99) ] D[100,240] = var(197); // [ var(240) , var(100) ] D[101,240] = (-1)*var(194); // [ var(240) , var(101) ] D[102,240] = var(193); // [ var(240) , var(102) ] D[103,240] = (-1)*var(192); // [ var(240) , var(103) ] D[104,240] = var(188); // [ var(240) , var(104) ] D[105,240] = (-1)*var(187); // [ var(240) , var(105) ] D[106,240] = var(185); // [ var(240) , var(106) ] D[107,240] = (-1)*var(182); // [ var(240) , var(107) ] D[108,240] = var(180); // [ var(240) , var(108) ] D[109,240] = var(176); // [ var(240) , var(109) ] D[110,240] = (-1)*var(174); // [ var(240) , var(110) ] D[111,240] = (-1)*var(170); // [ var(240) , var(111) ] D[112,240] = var(167); // [ var(240) , var(112) ] D[113,240] = var(163); // [ var(240) , var(113) ] D[114,240] = (-1)*var(162); // [ var(240) , var(114) ] D[115,240] = var(156); // [ var(240) , var(115) ] D[116,240] = (-1)*var(149); // [ var(240) , var(116) ] D[117,240] = var(142); // [ var(240) , var(117) ] D[118,240] = (-1)*var(135); // [ var(240) , var(118) ] D[119,240] = var(128); // [ var(240) , var(119) ] D[120,240] = (-2)*var(241)+(-3)*var(242)+(-4)*var(243)+(-6)*var(244)+(-5)*var(245)+(-4)*var(246)+(-3)*var(247)+(-2)*var(248); // [ var(240) , var(120) ] // X(i) * X(j): D[1,3] = var(9); // [ var(3) , var(1) ] D[1,11] = var(16); // [ var(11) , var(1) ] D[1,17] = var(23); // [ var(17) , var(1) ] D[1,19] = var(24); // [ var(19) , var(1) ] D[1,25] = var(30); // [ var(25) , var(1) ] D[1,27] = var(31); // [ var(27) , var(1) ] D[1,32] = var(37); // [ var(32) , var(1) ] D[1,33] = var(38); // [ var(33) , var(1) ] D[1,35] = var(39); // [ var(35) , var(1) ] D[1,40] = var(45); // [ var(40) , var(1) ] D[1,41] = var(46); // [ var(41) , var(1) ] D[1,43] = var(47); // [ var(43) , var(1) ] D[1,48] = var(52); // [ var(48) , var(1) ] D[1,49] = var(53); // [ var(49) , var(1) ] D[1,50] = var(54); // [ var(50) , var(1) ] D[1,55] = var(59); // [ var(55) , var(1) ] D[1,56] = var(60); // [ var(56) , var(1) ] D[1,61] = var(66); // [ var(61) , var(1) ] D[1,62] = var(67); // [ var(62) , var(1) ] D[1,68] = var(73); // [ var(68) , var(1) ] D[1,74] = var(79); // [ var(74) , var(1) ] D[1,93] = (-1)*var(97); // [ var(93) , var(1) ] D[1,98] = (-1)*var(101); // [ var(98) , var(1) ] D[1,102] = (-1)*var(104); // [ var(102) , var(1) ] D[1,105] = (-1)*var(107); // [ var(105) , var(1) ] D[1,108] = (-1)*var(109); // [ var(108) , var(1) ] D[1,110] = (-1)*var(111); // [ var(110) , var(1) ] D[1,112] = (-1)*var(113); // [ var(112) , var(1) ] D[2,4] = var(10); // [ var(4) , var(2) ] D[2,11] = var(17); // [ var(11) , var(2) ] D[2,12] = var(18); // [ var(12) , var(2) ] D[2,16] = var(23); // [ var(16) , var(2) ] D[2,19] = var(25); // [ var(19) , var(2) ] D[2,20] = var(26); // [ var(20) , var(2) ] D[2,24] = var(30); // [ var(24) , var(2) ] D[2,27] = var(33); // [ var(27) , var(2) ] D[2,28] = var(34); // [ var(28) , var(2) ] D[2,31] = var(38); // [ var(31) , var(2) ] D[2,35] = var(41); // [ var(35) , var(2) ] D[2,36] = var(42); // [ var(36) , var(2) ] D[2,39] = var(46); // [ var(39) , var(2) ] D[2,43] = var(50); // [ var(43) , var(2) ] D[2,47] = var(54); // [ var(47) , var(2) ] D[2,63] = (-1)*var(69); // [ var(63) , var(2) ] D[2,70] = (-1)*var(75); // [ var(70) , var(2) ] D[2,76] = (-1)*var(80); // [ var(76) , var(2) ] D[2,77] = (-1)*var(81); // [ var(77) , var(2) ] D[2,82] = (-1)*var(85); // [ var(82) , var(2) ] D[2,83] = (-1)*var(86); // [ var(83) , var(2) ] D[2,87] = (-1)*var(90); // [ var(87) , var(2) ] D[2,88] = (-1)*var(91); // [ var(88) , var(2) ] D[2,92] = (-1)*var(95); // [ var(92) , var(2) ] D[2,96] = (-1)*var(100); // [ var(96) , var(2) ] D[2,110] = var(112); // [ var(110) , var(2) ] D[2,111] = var(113); // [ var(111) , var(2) ] D[2,114] = var(115); // [ var(114) , var(2) ] D[3,4] = var(11); // [ var(4) , var(3) ] D[3,10] = var(17); // [ var(10) , var(3) ] D[3,12] = var(19); // [ var(12) , var(3) ] D[3,18] = var(25); // [ var(18) , var(3) ] D[3,20] = var(27); // [ var(20) , var(3) ] D[3,26] = var(33); // [ var(26) , var(3) ] D[3,28] = var(35); // [ var(28) , var(3) ] D[3,34] = var(41); // [ var(34) , var(3) ] D[3,36] = var(43); // [ var(36) , var(3) ] D[3,37] = var(44); // [ var(37) , var(3) ] D[3,42] = var(50); // [ var(42) , var(3) ] D[3,45] = var(51); // [ var(45) , var(3) ] D[3,52] = var(57); // [ var(52) , var(3) ] D[3,53] = var(58); // [ var(53) , var(3) ] D[3,59] = var(64); // [ var(59) , var(3) ] D[3,60] = var(65); // [ var(60) , var(3) ] D[3,66] = var(71); // [ var(66) , var(3) ] D[3,67] = var(72); // [ var(67) , var(3) ] D[3,73] = var(78); // [ var(73) , var(3) ] D[3,79] = var(84); // [ var(79) , var(3) ] D[3,89] = (-1)*var(93); // [ var(89) , var(3) ] D[3,94] = (-1)*var(98); // [ var(94) , var(3) ] D[3,99] = (-1)*var(102); // [ var(99) , var(3) ] D[3,103] = (-1)*var(105); // [ var(103) , var(3) ] D[3,106] = (-1)*var(108); // [ var(106) , var(3) ] D[3,111] = (-1)*var(114); // [ var(111) , var(3) ] D[3,113] = (-1)*var(115); // [ var(113) , var(3) ] D[4,5] = var(12); // [ var(5) , var(4) ] D[4,9] = (-1)*var(16); // [ var(9) , var(4) ] D[4,13] = var(20); // [ var(13) , var(4) ] D[4,21] = var(28); // [ var(21) , var(4) ] D[4,25] = (-1)*var(32); // [ var(25) , var(4) ] D[4,29] = var(36); // [ var(29) , var(4) ] D[4,30] = (-1)*var(37); // [ var(30) , var(4) ] D[4,33] = (-1)*var(40); // [ var(33) , var(4) ] D[4,38] = (-1)*var(45); // [ var(38) , var(4) ] D[4,41] = (-1)*var(49); // [ var(41) , var(4) ] D[4,46] = (-1)*var(53); // [ var(46) , var(4) ] D[4,50] = (-1)*var(56); // [ var(50) , var(4) ] D[4,54] = (-1)*var(60); // [ var(54) , var(4) ] D[4,57] = (-1)*var(63); // [ var(57) , var(4) ] D[4,64] = (-1)*var(70); // [ var(64) , var(4) ] D[4,71] = (-1)*var(76); // [ var(71) , var(4) ] D[4,72] = (-1)*var(77); // [ var(72) , var(4) ] D[4,78] = (-1)*var(83); // [ var(78) , var(4) ] D[4,84] = (-1)*var(88); // [ var(84) , var(4) ] D[4,85] = (-1)*var(89); // [ var(85) , var(4) ] D[4,90] = (-1)*var(94); // [ var(90) , var(4) ] D[4,95] = (-1)*var(99); // [ var(95) , var(4) ] D[4,100] = (-1)*var(103); // [ var(100) , var(4) ] D[4,108] = (-1)*var(110); // [ var(108) , var(4) ] D[4,109] = (-1)*var(111); // [ var(109) , var(4) ] D[4,115] = var(116); // [ var(115) , var(4) ] D[5,6] = var(13); // [ var(6) , var(5) ] D[5,10] = (-1)*var(18); // [ var(10) , var(5) ] D[5,11] = (-1)*var(19); // [ var(11) , var(5) ] D[5,14] = var(21); // [ var(14) , var(5) ] D[5,16] = (-1)*var(24); // [ var(16) , var(5) ] D[5,17] = (-1)*var(25); // [ var(17) , var(5) ] D[5,22] = var(29); // [ var(22) , var(5) ] D[5,23] = (-1)*var(30); // [ var(23) , var(5) ] D[5,40] = (-1)*var(48); // [ var(40) , var(5) ] D[5,45] = (-1)*var(52); // [ var(45) , var(5) ] D[5,49] = (-1)*var(55); // [ var(49) , var(5) ] D[5,51] = (-1)*var(57); // [ var(51) , var(5) ] D[5,53] = (-1)*var(59); // [ var(53) , var(5) ] D[5,56] = (-1)*var(62); // [ var(56) , var(5) ] D[5,58] = (-1)*var(64); // [ var(58) , var(5) ] D[5,60] = (-1)*var(67); // [ var(60) , var(5) ] D[5,65] = (-1)*var(72); // [ var(65) , var(5) ] D[5,76] = (-1)*var(82); // [ var(76) , var(5) ] D[5,80] = (-1)*var(85); // [ var(80) , var(5) ] D[5,83] = (-1)*var(87); // [ var(83) , var(5) ] D[5,86] = (-1)*var(90); // [ var(86) , var(5) ] D[5,88] = (-1)*var(92); // [ var(88) , var(5) ] D[5,91] = (-1)*var(95); // [ var(91) , var(5) ] D[5,103] = (-1)*var(106); // [ var(103) , var(5) ] D[5,105] = (-1)*var(108); // [ var(105) , var(5) ] D[5,107] = (-1)*var(109); // [ var(107) , var(5) ] D[5,116] = var(117); // [ var(116) , var(5) ] D[6,7] = var(14); // [ var(7) , var(6) ] D[6,12] = (-1)*var(20); // [ var(12) , var(6) ] D[6,15] = var(22); // [ var(15) , var(6) ] D[6,18] = (-1)*var(26); // [ var(18) , var(6) ] D[6,19] = (-1)*var(27); // [ var(19) , var(6) ] D[6,24] = (-1)*var(31); // [ var(24) , var(6) ] D[6,25] = (-1)*var(33); // [ var(25) , var(6) ] D[6,30] = (-1)*var(38); // [ var(30) , var(6) ] D[6,32] = (-1)*var(40); // [ var(32) , var(6) ] D[6,37] = (-1)*var(45); // [ var(37) , var(6) ] D[6,44] = (-1)*var(51); // [ var(44) , var(6) ] D[6,55] = (-1)*var(61); // [ var(55) , var(6) ] D[6,59] = (-1)*var(66); // [ var(59) , var(6) ] D[6,62] = (-1)*var(68); // [ var(62) , var(6) ] D[6,64] = (-1)*var(71); // [ var(64) , var(6) ] D[6,67] = (-1)*var(73); // [ var(67) , var(6) ] D[6,70] = (-1)*var(76); // [ var(70) , var(6) ] D[6,72] = (-1)*var(78); // [ var(72) , var(6) ] D[6,75] = (-1)*var(80); // [ var(75) , var(6) ] D[6,77] = (-1)*var(83); // [ var(77) , var(6) ] D[6,81] = (-1)*var(86); // [ var(81) , var(6) ] D[6,92] = (-1)*var(96); // [ var(92) , var(6) ] D[6,95] = (-1)*var(100); // [ var(95) , var(6) ] D[6,99] = (-1)*var(103); // [ var(99) , var(6) ] D[6,102] = (-1)*var(105); // [ var(102) , var(6) ] D[6,104] = (-1)*var(107); // [ var(104) , var(6) ] D[6,117] = var(118); // [ var(117) , var(6) ] D[7,8] = var(15); // [ var(8) , var(7) ] D[7,13] = (-1)*var(21); // [ var(13) , var(7) ] D[7,20] = (-1)*var(28); // [ var(20) , var(7) ] D[7,26] = (-1)*var(34); // [ var(26) , var(7) ] D[7,27] = (-1)*var(35); // [ var(27) , var(7) ] D[7,31] = (-1)*var(39); // [ var(31) , var(7) ] D[7,33] = (-1)*var(41); // [ var(33) , var(7) ] D[7,38] = (-1)*var(46); // [ var(38) , var(7) ] D[7,40] = (-1)*var(49); // [ var(40) , var(7) ] D[7,45] = (-1)*var(53); // [ var(45) , var(7) ] D[7,48] = (-1)*var(55); // [ var(48) , var(7) ] D[7,51] = (-1)*var(58); // [ var(51) , var(7) ] D[7,52] = (-1)*var(59); // [ var(52) , var(7) ] D[7,57] = (-1)*var(64); // [ var(57) , var(7) ] D[7,63] = (-1)*var(70); // [ var(63) , var(7) ] D[7,68] = (-1)*var(74); // [ var(68) , var(7) ] D[7,69] = (-1)*var(75); // [ var(69) , var(7) ] D[7,73] = (-1)*var(79); // [ var(73) , var(7) ] D[7,78] = (-1)*var(84); // [ var(78) , var(7) ] D[7,83] = (-1)*var(88); // [ var(83) , var(7) ] D[7,86] = (-1)*var(91); // [ var(86) , var(7) ] D[7,87] = (-1)*var(92); // [ var(87) , var(7) ] D[7,90] = (-1)*var(95); // [ var(90) , var(7) ] D[7,94] = (-1)*var(99); // [ var(94) , var(7) ] D[7,98] = (-1)*var(102); // [ var(98) , var(7) ] D[7,101] = (-1)*var(104); // [ var(101) , var(7) ] D[7,118] = var(119); // [ var(118) , var(7) ] D[8,14] = (-1)*var(22); // [ var(14) , var(8) ] D[8,21] = (-1)*var(29); // [ var(21) , var(8) ] D[8,28] = (-1)*var(36); // [ var(28) , var(8) ] D[8,34] = (-1)*var(42); // [ var(34) , var(8) ] D[8,35] = (-1)*var(43); // [ var(35) , var(8) ] D[8,39] = (-1)*var(47); // [ var(39) , var(8) ] D[8,41] = (-1)*var(50); // [ var(41) , var(8) ] D[8,46] = (-1)*var(54); // [ var(46) , var(8) ] D[8,49] = (-1)*var(56); // [ var(49) , var(8) ] D[8,53] = (-1)*var(60); // [ var(53) , var(8) ] D[8,55] = (-1)*var(62); // [ var(55) , var(8) ] D[8,58] = (-1)*var(65); // [ var(58) , var(8) ] D[8,59] = (-1)*var(67); // [ var(59) , var(8) ] D[8,61] = (-1)*var(68); // [ var(61) , var(8) ] D[8,64] = (-1)*var(72); // [ var(64) , var(8) ] D[8,66] = (-1)*var(73); // [ var(66) , var(8) ] D[8,70] = (-1)*var(77); // [ var(70) , var(8) ] D[8,71] = (-1)*var(78); // [ var(71) , var(8) ] D[8,75] = (-1)*var(81); // [ var(75) , var(8) ] D[8,76] = (-1)*var(83); // [ var(76) , var(8) ] D[8,80] = (-1)*var(86); // [ var(80) , var(8) ] D[8,82] = (-1)*var(87); // [ var(82) , var(8) ] D[8,85] = (-1)*var(90); // [ var(85) , var(8) ] D[8,89] = (-1)*var(94); // [ var(89) , var(8) ] D[8,93] = (-1)*var(98); // [ var(93) , var(8) ] D[8,97] = (-1)*var(101); // [ var(97) , var(8) ] D[8,119] = var(120); // [ var(119) , var(8) ] D[9,10] = var(23); // [ var(10) , var(9) ] D[9,12] = var(24); // [ var(12) , var(9) ] D[9,18] = var(30); // [ var(18) , var(9) ] D[9,20] = var(31); // [ var(20) , var(9) ] D[9,26] = var(38); // [ var(26) , var(9) ] D[9,28] = var(39); // [ var(28) , var(9) ] D[9,32] = (-1)*var(44); // [ var(32) , var(9) ] D[9,34] = var(46); // [ var(34) , var(9) ] D[9,36] = var(47); // [ var(36) , var(9) ] D[9,40] = (-1)*var(51); // [ var(40) , var(9) ] D[9,42] = var(54); // [ var(42) , var(9) ] D[9,48] = (-1)*var(57); // [ var(48) , var(9) ] D[9,49] = (-1)*var(58); // [ var(49) , var(9) ] D[9,55] = (-1)*var(64); // [ var(55) , var(9) ] D[9,56] = (-1)*var(65); // [ var(56) , var(9) ] D[9,61] = (-1)*var(71); // [ var(61) , var(9) ] D[9,62] = (-1)*var(72); // [ var(62) , var(9) ] D[9,68] = (-1)*var(78); // [ var(68) , var(9) ] D[9,74] = (-1)*var(84); // [ var(74) , var(9) ] D[9,89] = var(97); // [ var(89) , var(9) ] D[9,94] = var(101); // [ var(94) , var(9) ] D[9,99] = var(104); // [ var(99) , var(9) ] D[9,103] = var(107); // [ var(103) , var(9) ] D[9,106] = var(109); // [ var(106) , var(9) ] D[9,110] = (-1)*var(114); // [ var(110) , var(9) ] D[9,112] = (-1)*var(115); // [ var(112) , var(9) ] D[10,13] = var(26); // [ var(13) , var(10) ] D[10,19] = var(32); // [ var(19) , var(10) ] D[10,21] = var(34); // [ var(21) , var(10) ] D[10,24] = var(37); // [ var(24) , var(10) ] D[10,27] = var(40); // [ var(27) , var(10) ] D[10,29] = var(42); // [ var(29) , var(10) ] D[10,31] = var(45); // [ var(31) , var(10) ] D[10,35] = var(49); // [ var(35) , var(10) ] D[10,39] = var(53); // [ var(39) , var(10) ] D[10,43] = var(56); // [ var(43) , var(10) ] D[10,47] = var(60); // [ var(47) , var(10) ] D[10,57] = var(69); // [ var(57) , var(10) ] D[10,64] = var(75); // [ var(64) , var(10) ] D[10,71] = var(80); // [ var(71) , var(10) ] D[10,72] = var(81); // [ var(72) , var(10) ] D[10,78] = var(86); // [ var(78) , var(10) ] D[10,82] = (-1)*var(89); // [ var(82) , var(10) ] D[10,84] = var(91); // [ var(84) , var(10) ] D[10,87] = (-1)*var(94); // [ var(87) , var(10) ] D[10,92] = (-1)*var(99); // [ var(92) , var(10) ] D[10,96] = (-1)*var(103); // [ var(96) , var(10) ] D[10,108] = (-1)*var(112); // [ var(108) , var(10) ] D[10,109] = (-1)*var(113); // [ var(109) , var(10) ] D[10,114] = (-1)*var(116); // [ var(114) , var(10) ] D[11,13] = var(27); // [ var(13) , var(11) ] D[11,18] = var(32); // [ var(18) , var(11) ] D[11,21] = var(35); // [ var(21) , var(11) ] D[11,26] = var(40); // [ var(26) , var(11) ] D[11,29] = var(43); // [ var(29) , var(11) ] D[11,30] = (-1)*var(44); // [ var(30) , var(11) ] D[11,34] = var(49); // [ var(34) , var(11) ] D[11,38] = (-1)*var(51); // [ var(38) , var(11) ] D[11,42] = var(56); // [ var(42) , var(11) ] D[11,46] = (-1)*var(58); // [ var(46) , var(11) ] D[11,52] = var(63); // [ var(52) , var(11) ] D[11,54] = (-1)*var(65); // [ var(54) , var(11) ] D[11,59] = var(70); // [ var(59) , var(11) ] D[11,66] = var(76); // [ var(66) , var(11) ] D[11,67] = var(77); // [ var(67) , var(11) ] D[11,73] = var(83); // [ var(73) , var(11) ] D[11,79] = var(88); // [ var(79) , var(11) ] D[11,85] = var(93); // [ var(85) , var(11) ] D[11,90] = var(98); // [ var(90) , var(11) ] D[11,95] = var(102); // [ var(95) , var(11) ] D[11,100] = var(105); // [ var(100) , var(11) ] D[11,106] = (-1)*var(110); // [ var(106) , var(11) ] D[11,109] = var(114); // [ var(109) , var(11) ] D[11,113] = var(116); // [ var(113) , var(11) ] D[12,14] = var(28); // [ var(14) , var(12) ] D[12,17] = var(32); // [ var(17) , var(12) ] D[12,22] = var(36); // [ var(22) , var(12) ] D[12,23] = var(37); // [ var(23) , var(12) ] D[12,33] = (-1)*var(48); // [ var(33) , var(12) ] D[12,38] = (-1)*var(52); // [ var(38) , var(12) ] D[12,41] = (-1)*var(55); // [ var(41) , var(12) ] D[12,46] = (-1)*var(59); // [ var(46) , var(12) ] D[12,50] = (-1)*var(62); // [ var(50) , var(12) ] D[12,51] = var(63); // [ var(51) , var(12) ] D[12,54] = (-1)*var(67); // [ var(54) , var(12) ] D[12,58] = var(70); // [ var(58) , var(12) ] D[12,65] = var(77); // [ var(65) , var(12) ] D[12,71] = (-1)*var(82); // [ var(71) , var(12) ] D[12,78] = (-1)*var(87); // [ var(78) , var(12) ] D[12,80] = var(89); // [ var(80) , var(12) ] D[12,84] = (-1)*var(92); // [ var(84) , var(12) ] D[12,86] = var(94); // [ var(86) , var(12) ] D[12,91] = var(99); // [ var(91) , var(12) ] D[12,100] = (-1)*var(106); // [ var(100) , var(12) ] D[12,105] = var(110); // [ var(105) , var(12) ] D[12,107] = var(111); // [ var(107) , var(12) ] D[12,115] = (-1)*var(117); // [ var(115) , var(12) ] D[13,15] = var(29); // [ var(15) , var(13) ] D[13,16] = (-1)*var(31); // [ var(16) , var(13) ] D[13,17] = (-1)*var(33); // [ var(17) , var(13) ] D[13,23] = (-1)*var(38); // [ var(23) , var(13) ] D[13,32] = var(48); // [ var(32) , var(13) ] D[13,37] = var(52); // [ var(37) , var(13) ] D[13,44] = var(57); // [ var(44) , var(13) ] D[13,49] = (-1)*var(61); // [ var(49) , var(13) ] D[13,53] = (-1)*var(66); // [ var(53) , var(13) ] D[13,56] = (-1)*var(68); // [ var(56) , var(13) ] D[13,58] = (-1)*var(71); // [ var(58) , var(13) ] D[13,60] = (-1)*var(73); // [ var(60) , var(13) ] D[13,65] = (-1)*var(78); // [ var(65) , var(13) ] D[13,70] = var(82); // [ var(70) , var(13) ] D[13,75] = var(85); // [ var(75) , var(13) ] D[13,77] = var(87); // [ var(77) , var(13) ] D[13,81] = var(90); // [ var(81) , var(13) ] D[13,88] = (-1)*var(96); // [ var(88) , var(13) ] D[13,91] = (-1)*var(100); // [ var(91) , var(13) ] D[13,99] = var(106); // [ var(99) , var(13) ] D[13,102] = var(108); // [ var(102) , var(13) ] D[13,104] = var(109); // [ var(104) , var(13) ] D[13,116] = (-1)*var(118); // [ var(116) , var(13) ] D[14,18] = (-1)*var(34); // [ var(18) , var(14) ] D[14,19] = (-1)*var(35); // [ var(19) , var(14) ] D[14,24] = (-1)*var(39); // [ var(24) , var(14) ] D[14,25] = (-1)*var(41); // [ var(25) , var(14) ] D[14,30] = (-1)*var(46); // [ var(30) , var(14) ] D[14,32] = (-1)*var(49); // [ var(32) , var(14) ] D[14,37] = (-1)*var(53); // [ var(37) , var(14) ] D[14,44] = (-1)*var(58); // [ var(44) , var(14) ] D[14,48] = var(61); // [ var(48) , var(14) ] D[14,52] = var(66); // [ var(52) , var(14) ] D[14,57] = var(71); // [ var(57) , var(14) ] D[14,62] = (-1)*var(74); // [ var(62) , var(14) ] D[14,63] = var(76); // [ var(63) , var(14) ] D[14,67] = (-1)*var(79); // [ var(67) , var(14) ] D[14,69] = var(80); // [ var(69) , var(14) ] D[14,72] = (-1)*var(84); // [ var(72) , var(14) ] D[14,77] = (-1)*var(88); // [ var(77) , var(14) ] D[14,81] = (-1)*var(91); // [ var(81) , var(14) ] D[14,87] = var(96); // [ var(87) , var(14) ] D[14,90] = var(100); // [ var(90) , var(14) ] D[14,94] = var(103); // [ var(94) , var(14) ] D[14,98] = var(105); // [ var(98) , var(14) ] D[14,101] = var(107); // [ var(101) , var(14) ] D[14,117] = (-1)*var(119); // [ var(117) , var(14) ] D[15,20] = (-1)*var(36); // [ var(20) , var(15) ] D[15,26] = (-1)*var(42); // [ var(26) , var(15) ] D[15,27] = (-1)*var(43); // [ var(27) , var(15) ] D[15,31] = (-1)*var(47); // [ var(31) , var(15) ] D[15,33] = (-1)*var(50); // [ var(33) , var(15) ] D[15,38] = (-1)*var(54); // [ var(38) , var(15) ] D[15,40] = (-1)*var(56); // [ var(40) , var(15) ] D[15,45] = (-1)*var(60); // [ var(45) , var(15) ] D[15,48] = (-1)*var(62); // [ var(48) , var(15) ] D[15,51] = (-1)*var(65); // [ var(51) , var(15) ] D[15,52] = (-1)*var(67); // [ var(52) , var(15) ] D[15,57] = (-1)*var(72); // [ var(57) , var(15) ] D[15,61] = var(74); // [ var(61) , var(15) ] D[15,63] = (-1)*var(77); // [ var(63) , var(15) ] D[15,66] = var(79); // [ var(66) , var(15) ] D[15,69] = (-1)*var(81); // [ var(69) , var(15) ] D[15,71] = var(84); // [ var(71) , var(15) ] D[15,76] = var(88); // [ var(76) , var(15) ] D[15,80] = var(91); // [ var(80) , var(15) ] D[15,82] = var(92); // [ var(82) , var(15) ] D[15,85] = var(95); // [ var(85) , var(15) ] D[15,89] = var(99); // [ var(89) , var(15) ] D[15,93] = var(102); // [ var(93) , var(15) ] D[15,97] = var(104); // [ var(97) , var(15) ] D[15,118] = (-1)*var(120); // [ var(118) , var(15) ] D[16,18] = var(37); // [ var(18) , var(16) ] D[16,21] = var(39); // [ var(21) , var(16) ] D[16,25] = var(44); // [ var(25) , var(16) ] D[16,26] = var(45); // [ var(26) , var(16) ] D[16,29] = var(47); // [ var(29) , var(16) ] D[16,33] = var(51); // [ var(33) , var(16) ] D[16,34] = var(53); // [ var(34) , var(16) ] D[16,41] = var(58); // [ var(41) , var(16) ] D[16,42] = var(60); // [ var(42) , var(16) ] D[16,48] = (-1)*var(63); // [ var(48) , var(16) ] D[16,50] = var(65); // [ var(50) , var(16) ] D[16,55] = (-1)*var(70); // [ var(55) , var(16) ] D[16,61] = (-1)*var(76); // [ var(61) , var(16) ] D[16,62] = (-1)*var(77); // [ var(62) , var(16) ] D[16,68] = (-1)*var(83); // [ var(68) , var(16) ] D[16,74] = (-1)*var(88); // [ var(74) , var(16) ] D[16,85] = (-1)*var(97); // [ var(85) , var(16) ] D[16,90] = (-1)*var(101); // [ var(90) , var(16) ] D[16,95] = (-1)*var(104); // [ var(95) , var(16) ] D[16,100] = (-1)*var(107); // [ var(100) , var(16) ] D[16,106] = var(111); // [ var(106) , var(16) ] D[16,108] = var(114); // [ var(108) , var(16) ] D[16,112] = var(116); // [ var(112) , var(16) ] D[17,20] = (-1)*var(40); // [ var(20) , var(17) ] D[17,21] = var(41); // [ var(21) , var(17) ] D[17,24] = var(44); // [ var(24) , var(17) ] D[17,28] = (-1)*var(49); // [ var(28) , var(17) ] D[17,29] = var(50); // [ var(29) , var(17) ] D[17,31] = var(51); // [ var(31) , var(17) ] D[17,36] = (-1)*var(56); // [ var(36) , var(17) ] D[17,39] = var(58); // [ var(39) , var(17) ] D[17,47] = var(65); // [ var(47) , var(17) ] D[17,52] = (-1)*var(69); // [ var(52) , var(17) ] D[17,59] = (-1)*var(75); // [ var(59) , var(17) ] D[17,66] = (-1)*var(80); // [ var(66) , var(17) ] D[17,67] = (-1)*var(81); // [ var(67) , var(17) ] D[17,73] = (-1)*var(86); // [ var(73) , var(17) ] D[17,79] = (-1)*var(91); // [ var(79) , var(17) ] D[17,82] = var(93); // [ var(82) , var(17) ] D[17,87] = var(98); // [ var(87) , var(17) ] D[17,92] = var(102); // [ var(92) , var(17) ] D[17,96] = var(105); // [ var(96) , var(17) ] D[17,106] = (-1)*var(112); // [ var(106) , var(17) ] D[17,109] = var(115); // [ var(109) , var(17) ] D[17,111] = (-1)*var(116); // [ var(111) , var(17) ] D[18,22] = var(42); // [ var(22) , var(18) ] D[18,27] = var(48); // [ var(27) , var(18) ] D[18,31] = var(52); // [ var(31) , var(18) ] D[18,35] = var(55); // [ var(35) , var(18) ] D[18,39] = var(59); // [ var(39) , var(18) ] D[18,43] = var(62); // [ var(43) , var(18) ] D[18,47] = var(67); // [ var(47) , var(18) ] D[18,51] = (-1)*var(69); // [ var(51) , var(18) ] D[18,58] = (-1)*var(75); // [ var(58) , var(18) ] D[18,65] = (-1)*var(81); // [ var(65) , var(18) ] D[18,71] = var(85); // [ var(71) , var(18) ] D[18,76] = var(89); // [ var(76) , var(18) ] D[18,78] = var(90); // [ var(78) , var(18) ] D[18,83] = var(94); // [ var(83) , var(18) ] D[18,84] = var(95); // [ var(84) , var(18) ] D[18,88] = var(99); // [ var(88) , var(18) ] D[18,96] = (-1)*var(106); // [ var(96) , var(18) ] D[18,105] = var(112); // [ var(105) , var(18) ] D[18,107] = var(113); // [ var(107) , var(18) ] D[18,114] = var(117); // [ var(114) , var(18) ] D[19,22] = var(43); // [ var(22) , var(19) ] D[19,23] = var(44); // [ var(23) , var(19) ] D[19,26] = var(48); // [ var(26) , var(19) ] D[19,34] = var(55); // [ var(34) , var(19) ] D[19,38] = (-1)*var(57); // [ var(38) , var(19) ] D[19,42] = var(62); // [ var(42) , var(19) ] D[19,45] = (-1)*var(63); // [ var(45) , var(19) ] D[19,46] = (-1)*var(64); // [ var(46) , var(19) ] D[19,53] = (-1)*var(70); // [ var(53) , var(19) ] D[19,54] = (-1)*var(72); // [ var(54) , var(19) ] D[19,60] = (-1)*var(77); // [ var(60) , var(19) ] D[19,66] = var(82); // [ var(66) , var(19) ] D[19,73] = var(87); // [ var(73) , var(19) ] D[19,79] = var(92); // [ var(79) , var(19) ] D[19,80] = (-1)*var(93); // [ var(80) , var(19) ] D[19,86] = (-1)*var(98); // [ var(86) , var(19) ] D[19,91] = (-1)*var(102); // [ var(91) , var(19) ] D[19,100] = var(108); // [ var(100) , var(19) ] D[19,103] = var(110); // [ var(103) , var(19) ] D[19,107] = (-1)*var(114); // [ var(107) , var(19) ] D[19,113] = (-1)*var(117); // [ var(113) , var(19) ] D[20,23] = var(45); // [ var(23) , var(20) ] D[20,25] = var(48); // [ var(25) , var(20) ] D[20,30] = var(52); // [ var(30) , var(20) ] D[20,41] = (-1)*var(61); // [ var(41) , var(20) ] D[20,44] = (-1)*var(63); // [ var(44) , var(20) ] D[20,46] = (-1)*var(66); // [ var(46) , var(20) ] D[20,50] = (-1)*var(68); // [ var(50) , var(20) ] D[20,54] = (-1)*var(73); // [ var(54) , var(20) ] D[20,58] = var(76); // [ var(58) , var(20) ] D[20,64] = var(82); // [ var(64) , var(20) ] D[20,65] = var(83); // [ var(65) , var(20) ] D[20,72] = var(87); // [ var(72) , var(20) ] D[20,75] = (-1)*var(89); // [ var(75) , var(20) ] D[20,81] = (-1)*var(94); // [ var(81) , var(20) ] D[20,84] = (-1)*var(96); // [ var(84) , var(20) ] D[20,91] = var(103); // [ var(91) , var(20) ] D[20,95] = var(106); // [ var(95) , var(20) ] D[20,102] = (-1)*var(110); // [ var(102) , var(20) ] D[20,104] = (-1)*var(111); // [ var(104) , var(20) ] D[20,115] = var(118); // [ var(115) , var(20) ] D[21,23] = (-1)*var(46); // [ var(23) , var(21) ] D[21,32] = var(55); // [ var(32) , var(21) ] D[21,37] = var(59); // [ var(37) , var(21) ] D[21,40] = var(61); // [ var(40) , var(21) ] D[21,44] = var(64); // [ var(44) , var(21) ] D[21,45] = var(66); // [ var(45) , var(21) ] D[21,51] = var(71); // [ var(51) , var(21) ] D[21,56] = (-1)*var(74); // [ var(56) , var(21) ] D[21,60] = (-1)*var(79); // [ var(60) , var(21) ] D[21,63] = (-1)*var(82); // [ var(63) , var(21) ] D[21,65] = (-1)*var(84); // [ var(65) , var(21) ] D[21,69] = (-1)*var(85); // [ var(69) , var(21) ] D[21,77] = var(92); // [ var(77) , var(21) ] D[21,81] = var(95); // [ var(81) , var(21) ] D[21,83] = var(96); // [ var(83) , var(21) ] D[21,86] = var(100); // [ var(86) , var(21) ] D[21,94] = (-1)*var(106); // [ var(94) , var(21) ] D[21,98] = (-1)*var(108); // [ var(98) , var(21) ] D[21,101] = (-1)*var(109); // [ var(101) , var(21) ] D[21,116] = var(119); // [ var(116) , var(21) ] D[22,24] = (-1)*var(47); // [ var(24) , var(22) ] D[22,25] = (-1)*var(50); // [ var(25) , var(22) ] D[22,30] = (-1)*var(54); // [ var(30) , var(22) ] D[22,32] = (-1)*var(56); // [ var(32) , var(22) ] D[22,37] = (-1)*var(60); // [ var(37) , var(22) ] D[22,44] = (-1)*var(65); // [ var(44) , var(22) ] D[22,48] = var(68); // [ var(48) , var(22) ] D[22,52] = var(73); // [ var(52) , var(22) ] D[22,55] = var(74); // [ var(55) , var(22) ] D[22,57] = var(78); // [ var(57) , var(22) ] D[22,59] = var(79); // [ var(59) , var(22) ] D[22,63] = var(83); // [ var(63) , var(22) ] D[22,64] = var(84); // [ var(64) , var(22) ] D[22,69] = var(86); // [ var(69) , var(22) ] D[22,70] = var(88); // [ var(70) , var(22) ] D[22,75] = var(91); // [ var(75) , var(22) ] D[22,82] = (-1)*var(96); // [ var(82) , var(22) ] D[22,85] = (-1)*var(100); // [ var(85) , var(22) ] D[22,89] = (-1)*var(103); // [ var(89) , var(22) ] D[22,93] = (-1)*var(105); // [ var(93) , var(22) ] D[22,97] = (-1)*var(107); // [ var(97) , var(22) ] D[22,117] = var(120); // [ var(117) , var(22) ] D[23,27] = (-1)*var(51); // [ var(27) , var(23) ] D[23,28] = (-1)*var(53); // [ var(28) , var(23) ] D[23,29] = var(54); // [ var(29) , var(23) ] D[23,35] = (-1)*var(58); // [ var(35) , var(23) ] D[23,36] = (-1)*var(60); // [ var(36) , var(23) ] D[23,43] = (-1)*var(65); // [ var(43) , var(23) ] D[23,48] = var(69); // [ var(48) , var(23) ] D[23,55] = var(75); // [ var(55) , var(23) ] D[23,61] = var(80); // [ var(61) , var(23) ] D[23,62] = var(81); // [ var(62) , var(23) ] D[23,68] = var(86); // [ var(68) , var(23) ] D[23,74] = var(91); // [ var(74) , var(23) ] D[23,82] = (-1)*var(97); // [ var(82) , var(23) ] D[23,87] = (-1)*var(101); // [ var(87) , var(23) ] D[23,92] = (-1)*var(104); // [ var(92) , var(23) ] D[23,96] = (-1)*var(107); // [ var(96) , var(23) ] D[23,106] = var(113); // [ var(106) , var(23) ] D[23,108] = var(115); // [ var(108) , var(23) ] D[23,110] = (-1)*var(116); // [ var(110) , var(23) ] D[24,26] = var(52); // [ var(26) , var(24) ] D[24,33] = var(57); // [ var(33) , var(24) ] D[24,34] = var(59); // [ var(34) , var(24) ] D[24,40] = var(63); // [ var(40) , var(24) ] D[24,41] = var(64); // [ var(41) , var(24) ] D[24,42] = var(67); // [ var(42) , var(24) ] D[24,49] = var(70); // [ var(49) , var(24) ] D[24,50] = var(72); // [ var(50) , var(24) ] D[24,56] = var(77); // [ var(56) , var(24) ] D[24,61] = (-1)*var(82); // [ var(61) , var(24) ] D[24,68] = (-1)*var(87); // [ var(68) , var(24) ] D[24,74] = (-1)*var(92); // [ var(74) , var(24) ] D[24,80] = var(97); // [ var(80) , var(24) ] D[24,86] = var(101); // [ var(86) , var(24) ] D[24,91] = var(104); // [ var(91) , var(24) ] D[24,100] = (-1)*var(109); // [ var(100) , var(24) ] D[24,103] = (-1)*var(111); // [ var(103) , var(24) ] D[24,105] = (-1)*var(114); // [ var(105) , var(24) ] D[24,112] = (-1)*var(117); // [ var(112) , var(24) ] D[25,28] = (-1)*var(55); // [ var(28) , var(25) ] D[25,31] = var(57); // [ var(31) , var(25) ] D[25,36] = (-1)*var(62); // [ var(36) , var(25) ] D[25,39] = var(64); // [ var(39) , var(25) ] D[25,45] = var(69); // [ var(45) , var(25) ] D[25,47] = var(72); // [ var(47) , var(25) ] D[25,53] = var(75); // [ var(53) , var(25) ] D[25,60] = var(81); // [ var(60) , var(25) ] D[25,66] = (-1)*var(85); // [ var(66) , var(25) ] D[25,73] = (-1)*var(90); // [ var(73) , var(25) ] D[25,76] = (-1)*var(93); // [ var(76) , var(25) ] D[25,79] = (-1)*var(95); // [ var(79) , var(25) ] D[25,83] = (-1)*var(98); // [ var(83) , var(25) ] D[25,88] = (-1)*var(102); // [ var(88) , var(25) ] D[25,96] = var(108); // [ var(96) , var(25) ] D[25,103] = var(112); // [ var(103) , var(25) ] D[25,107] = (-1)*var(115); // [ var(107) , var(25) ] D[25,111] = var(117); // [ var(111) , var(25) ] D[26,35] = var(61); // [ var(35) , var(26) ] D[26,39] = var(66); // [ var(39) , var(26) ] D[26,43] = var(68); // [ var(43) , var(26) ] D[26,44] = var(69); // [ var(44) , var(26) ] D[26,47] = var(73); // [ var(47) , var(26) ] D[26,58] = (-1)*var(80); // [ var(58) , var(26) ] D[26,64] = (-1)*var(85); // [ var(64) , var(26) ] D[26,65] = (-1)*var(86); // [ var(65) , var(26) ] D[26,70] = (-1)*var(89); // [ var(70) , var(26) ] D[26,72] = (-1)*var(90); // [ var(72) , var(26) ] D[26,77] = (-1)*var(94); // [ var(77) , var(26) ] D[26,84] = var(100); // [ var(84) , var(26) ] D[26,88] = var(103); // [ var(88) , var(26) ] D[26,92] = var(106); // [ var(92) , var(26) ] D[26,102] = (-1)*var(112); // [ var(102) , var(26) ] D[26,104] = (-1)*var(113); // [ var(104) , var(26) ] D[26,114] = (-1)*var(118); // [ var(114) , var(26) ] D[27,30] = var(57); // [ var(30) , var(27) ] D[27,34] = var(61); // [ var(34) , var(27) ] D[27,37] = var(63); // [ var(37) , var(27) ] D[27,42] = var(68); // [ var(42) , var(27) ] D[27,46] = (-1)*var(71); // [ var(46) , var(27) ] D[27,53] = (-1)*var(76); // [ var(53) , var(27) ] D[27,54] = (-1)*var(78); // [ var(54) , var(27) ] D[27,59] = (-1)*var(82); // [ var(59) , var(27) ] D[27,60] = (-1)*var(83); // [ var(60) , var(27) ] D[27,67] = (-1)*var(87); // [ var(67) , var(27) ] D[27,75] = var(93); // [ var(75) , var(27) ] D[27,79] = var(96); // [ var(79) , var(27) ] D[27,81] = var(98); // [ var(81) , var(27) ] D[27,91] = (-1)*var(105); // [ var(91) , var(27) ] D[27,95] = (-1)*var(108); // [ var(95) , var(27) ] D[27,99] = (-1)*var(110); // [ var(99) , var(27) ] D[27,104] = var(114); // [ var(104) , var(27) ] D[27,113] = var(118); // [ var(113) , var(27) ] D[28,30] = var(59); // [ var(30) , var(28) ] D[28,33] = var(61); // [ var(33) , var(28) ] D[28,38] = var(66); // [ var(38) , var(28) ] D[28,44] = (-1)*var(70); // [ var(44) , var(28) ] D[28,50] = (-1)*var(74); // [ var(50) , var(28) ] D[28,51] = (-1)*var(76); // [ var(51) , var(28) ] D[28,54] = (-1)*var(79); // [ var(54) , var(28) ] D[28,57] = (-1)*var(82); // [ var(57) , var(28) ] D[28,65] = var(88); // [ var(65) , var(28) ] D[28,69] = var(89); // [ var(69) , var(28) ] D[28,72] = var(92); // [ var(72) , var(28) ] D[28,78] = var(96); // [ var(78) , var(28) ] D[28,81] = (-1)*var(99); // [ var(81) , var(28) ] D[28,86] = (-1)*var(103); // [ var(86) , var(28) ] D[28,90] = (-1)*var(106); // [ var(90) , var(28) ] D[28,98] = var(110); // [ var(98) , var(28) ] D[28,101] = var(111); // [ var(101) , var(28) ] D[28,115] = (-1)*var(119); // [ var(115) , var(28) ] D[29,32] = var(62); // [ var(32) , var(29) ] D[29,37] = var(67); // [ var(37) , var(29) ] D[29,40] = var(68); // [ var(40) , var(29) ] D[29,44] = var(72); // [ var(44) , var(29) ] D[29,45] = var(73); // [ var(45) , var(29) ] D[29,49] = var(74); // [ var(49) , var(29) ] D[29,51] = var(78); // [ var(51) , var(29) ] D[29,53] = var(79); // [ var(53) , var(29) ] D[29,58] = var(84); // [ var(58) , var(29) ] D[29,63] = (-1)*var(87); // [ var(63) , var(29) ] D[29,69] = (-1)*var(90); // [ var(69) , var(29) ] D[29,70] = (-1)*var(92); // [ var(70) , var(29) ] D[29,75] = (-1)*var(95); // [ var(75) , var(29) ] D[29,76] = (-1)*var(96); // [ var(76) , var(29) ] D[29,80] = (-1)*var(100); // [ var(80) , var(29) ] D[29,89] = var(106); // [ var(89) , var(29) ] D[29,93] = var(108); // [ var(93) , var(29) ] D[29,97] = var(109); // [ var(97) , var(29) ] D[29,116] = (-1)*var(120); // [ var(116) , var(29) ] D[30,35] = (-1)*var(64); // [ var(35) , var(30) ] D[30,36] = (-1)*var(67); // [ var(36) , var(30) ] D[30,40] = (-1)*var(69); // [ var(40) , var(30) ] D[30,43] = (-1)*var(72); // [ var(43) , var(30) ] D[30,49] = (-1)*var(75); // [ var(49) , var(30) ] D[30,56] = (-1)*var(81); // [ var(56) , var(30) ] D[30,61] = var(85); // [ var(61) , var(30) ] D[30,68] = var(90); // [ var(68) , var(30) ] D[30,74] = var(95); // [ var(74) , var(30) ] D[30,76] = var(97); // [ var(76) , var(30) ] D[30,83] = var(101); // [ var(83) , var(30) ] D[30,88] = var(104); // [ var(88) , var(30) ] D[30,96] = (-1)*var(109); // [ var(96) , var(30) ] D[30,103] = (-1)*var(113); // [ var(103) , var(30) ] D[30,105] = (-1)*var(115); // [ var(105) , var(30) ] D[30,110] = var(117); // [ var(110) , var(30) ] D[31,32] = (-1)*var(63); // [ var(32) , var(31) ] D[31,34] = var(66); // [ var(34) , var(31) ] D[31,41] = var(71); // [ var(41) , var(31) ] D[31,42] = var(73); // [ var(42) , var(31) ] D[31,49] = var(76); // [ var(49) , var(31) ] D[31,50] = var(78); // [ var(50) , var(31) ] D[31,55] = var(82); // [ var(55) , var(31) ] D[31,56] = var(83); // [ var(56) , var(31) ] D[31,62] = var(87); // [ var(62) , var(31) ] D[31,74] = (-1)*var(96); // [ var(74) , var(31) ] D[31,75] = (-1)*var(97); // [ var(75) , var(31) ] D[31,81] = (-1)*var(101); // [ var(81) , var(31) ] D[31,91] = var(107); // [ var(91) , var(31) ] D[31,95] = var(109); // [ var(95) , var(31) ] D[31,99] = var(111); // [ var(99) , var(31) ] D[31,102] = var(114); // [ var(102) , var(31) ] D[31,112] = var(118); // [ var(112) , var(31) ] D[32,38] = (-1)*var(69); // [ var(38) , var(32) ] D[32,39] = var(70); // [ var(39) , var(32) ] D[32,46] = (-1)*var(75); // [ var(46) , var(32) ] D[32,47] = var(77); // [ var(47) , var(32) ] D[32,54] = (-1)*var(81); // [ var(54) , var(32) ] D[32,66] = (-1)*var(89); // [ var(66) , var(32) ] D[32,71] = var(93); // [ var(71) , var(32) ] D[32,73] = (-1)*var(94); // [ var(73) , var(32) ] D[32,78] = var(98); // [ var(78) , var(32) ] D[32,79] = (-1)*var(99); // [ var(79) , var(32) ] D[32,84] = var(102); // [ var(84) , var(32) ] D[32,96] = var(110); // [ var(96) , var(32) ] D[32,100] = (-1)*var(112); // [ var(100) , var(32) ] D[32,107] = var(116); // [ var(107) , var(32) ] D[32,109] = (-1)*var(117); // [ var(109) , var(32) ] D[33,36] = (-1)*var(68); // [ var(36) , var(33) ] D[33,37] = (-1)*var(69); // [ var(37) , var(33) ] D[33,39] = var(71); // [ var(39) , var(33) ] D[33,47] = var(78); // [ var(47) , var(33) ] D[33,53] = var(80); // [ var(53) , var(33) ] D[33,59] = var(85); // [ var(59) , var(33) ] D[33,60] = var(86); // [ var(60) , var(33) ] D[33,67] = var(90); // [ var(67) , var(33) ] D[33,70] = var(93); // [ var(70) , var(33) ] D[33,77] = var(98); // [ var(77) , var(33) ] D[33,79] = (-1)*var(100); // [ var(79) , var(33) ] D[33,88] = (-1)*var(105); // [ var(88) , var(33) ] D[33,92] = (-1)*var(108); // [ var(92) , var(33) ] D[33,99] = (-1)*var(112); // [ var(99) , var(33) ] D[33,104] = var(115); // [ var(104) , var(33) ] D[33,111] = (-1)*var(118); // [ var(111) , var(33) ] D[34,43] = var(74); // [ var(43) , var(34) ] D[34,44] = var(75); // [ var(44) , var(34) ] D[34,47] = var(79); // [ var(47) , var(34) ] D[34,51] = var(80); // [ var(51) , var(34) ] D[34,57] = var(85); // [ var(57) , var(34) ] D[34,63] = var(89); // [ var(63) , var(34) ] D[34,65] = (-1)*var(91); // [ var(65) , var(34) ] D[34,72] = (-1)*var(95); // [ var(72) , var(34) ] D[34,77] = (-1)*var(99); // [ var(77) , var(34) ] D[34,78] = (-1)*var(100); // [ var(78) , var(34) ] D[34,83] = (-1)*var(103); // [ var(83) , var(34) ] D[34,87] = (-1)*var(106); // [ var(87) , var(34) ] D[34,98] = var(112); // [ var(98) , var(34) ] D[34,101] = var(113); // [ var(101) , var(34) ] D[34,114] = var(119); // [ var(114) , var(34) ] D[35,37] = var(70); // [ var(37) , var(35) ] D[35,38] = var(71); // [ var(38) , var(35) ] D[35,42] = var(74); // [ var(42) , var(35) ] D[35,45] = var(76); // [ var(45) , var(35) ] D[35,52] = var(82); // [ var(52) , var(35) ] D[35,54] = (-1)*var(84); // [ var(54) , var(35) ] D[35,60] = (-1)*var(88); // [ var(60) , var(35) ] D[35,67] = (-1)*var(92); // [ var(67) , var(35) ] D[35,69] = (-1)*var(93); // [ var(69) , var(35) ] D[35,73] = (-1)*var(96); // [ var(73) , var(35) ] D[35,81] = var(102); // [ var(81) , var(35) ] D[35,86] = var(105); // [ var(86) , var(35) ] D[35,90] = var(108); // [ var(90) , var(35) ] D[35,94] = var(110); // [ var(94) , var(35) ] D[35,101] = (-1)*var(114); // [ var(101) , var(35) ] D[35,113] = (-1)*var(119); // [ var(113) , var(35) ] D[36,38] = var(73); // [ var(38) , var(36) ] D[36,41] = var(74); // [ var(41) , var(36) ] D[36,44] = (-1)*var(77); // [ var(44) , var(36) ] D[36,46] = var(79); // [ var(46) , var(36) ] D[36,51] = (-1)*var(83); // [ var(51) , var(36) ] D[36,57] = (-1)*var(87); // [ var(57) , var(36) ] D[36,58] = (-1)*var(88); // [ var(58) , var(36) ] D[36,64] = (-1)*var(92); // [ var(64) , var(36) ] D[36,69] = var(94); // [ var(69) , var(36) ] D[36,71] = (-1)*var(96); // [ var(71) , var(36) ] D[36,75] = var(99); // [ var(75) , var(36) ] D[36,80] = var(103); // [ var(80) , var(36) ] D[36,85] = var(106); // [ var(85) , var(36) ] D[36,93] = (-1)*var(110); // [ var(93) , var(36) ] D[36,97] = (-1)*var(111); // [ var(97) , var(36) ] D[36,115] = var(120); // [ var(115) , var(36) ] D[37,41] = var(75); // [ var(41) , var(37) ] D[37,43] = (-1)*var(77); // [ var(43) , var(37) ] D[37,50] = var(81); // [ var(50) , var(37) ] D[37,61] = var(89); // [ var(61) , var(37) ] D[37,68] = var(94); // [ var(68) , var(37) ] D[37,71] = (-1)*var(97); // [ var(71) , var(37) ] D[37,74] = var(99); // [ var(74) , var(37) ] D[37,78] = (-1)*var(101); // [ var(78) , var(37) ] D[37,84] = (-1)*var(104); // [ var(84) , var(37) ] D[37,96] = (-1)*var(111); // [ var(96) , var(37) ] D[37,100] = var(113); // [ var(100) , var(37) ] D[37,105] = var(116); // [ var(105) , var(37) ] D[37,108] = (-1)*var(117); // [ var(108) , var(37) ] D[38,43] = (-1)*var(78); // [ var(43) , var(38) ] D[38,49] = (-1)*var(80); // [ var(49) , var(38) ] D[38,55] = (-1)*var(85); // [ var(55) , var(38) ] D[38,56] = (-1)*var(86); // [ var(56) , var(38) ] D[38,62] = (-1)*var(90); // [ var(62) , var(38) ] D[38,70] = (-1)*var(97); // [ var(70) , var(38) ] D[38,74] = var(100); // [ var(74) , var(38) ] D[38,77] = (-1)*var(101); // [ var(77) , var(38) ] D[38,88] = var(107); // [ var(88) , var(38) ] D[38,92] = var(109); // [ var(92) , var(38) ] D[38,99] = var(113); // [ var(99) , var(38) ] D[38,102] = var(115); // [ var(102) , var(38) ] D[38,110] = (-1)*var(118); // [ var(110) , var(38) ] D[39,40] = (-1)*var(76); // [ var(40) , var(39) ] D[39,42] = var(79); // [ var(42) , var(39) ] D[39,48] = (-1)*var(82); // [ var(48) , var(39) ] D[39,50] = var(84); // [ var(50) , var(39) ] D[39,56] = var(88); // [ var(56) , var(39) ] D[39,62] = var(92); // [ var(62) , var(39) ] D[39,68] = var(96); // [ var(68) , var(39) ] D[39,69] = var(97); // [ var(69) , var(39) ] D[39,81] = (-1)*var(104); // [ var(81) , var(39) ] D[39,86] = (-1)*var(107); // [ var(86) , var(39) ] D[39,90] = (-1)*var(109); // [ var(90) , var(39) ] D[39,94] = (-1)*var(111); // [ var(94) , var(39) ] D[39,98] = (-1)*var(114); // [ var(98) , var(39) ] D[39,112] = (-1)*var(119); // [ var(112) , var(39) ] D[40,46] = (-1)*var(80); // [ var(46) , var(40) ] D[40,47] = var(83); // [ var(47) , var(40) ] D[40,54] = (-1)*var(86); // [ var(54) , var(40) ] D[40,59] = var(89); // [ var(59) , var(40) ] D[40,64] = (-1)*var(93); // [ var(64) , var(40) ] D[40,67] = var(94); // [ var(67) , var(40) ] D[40,72] = (-1)*var(98); // [ var(72) , var(40) ] D[40,79] = (-1)*var(103); // [ var(79) , var(40) ] D[40,84] = var(105); // [ var(84) , var(40) ] D[40,92] = (-1)*var(110); // [ var(92) , var(40) ] D[40,95] = var(112); // [ var(95) , var(40) ] D[40,104] = (-1)*var(116); // [ var(104) , var(40) ] D[40,109] = var(118); // [ var(109) , var(40) ] D[41,45] = (-1)*var(80); // [ var(45) , var(41) ] D[41,47] = var(84); // [ var(47) , var(41) ] D[41,52] = (-1)*var(85); // [ var(52) , var(41) ] D[41,60] = var(91); // [ var(60) , var(41) ] D[41,63] = (-1)*var(93); // [ var(63) , var(41) ] D[41,67] = var(95); // [ var(67) , var(41) ] D[41,73] = var(100); // [ var(73) , var(41) ] D[41,77] = var(102); // [ var(77) , var(41) ] D[41,83] = var(105); // [ var(83) , var(41) ] D[41,87] = var(108); // [ var(87) , var(41) ] D[41,94] = var(112); // [ var(94) , var(41) ] D[41,101] = (-1)*var(115); // [ var(101) , var(41) ] D[41,111] = var(119); // [ var(111) , var(41) ] D[42,44] = var(81); // [ var(44) , var(42) ] D[42,51] = var(86); // [ var(51) , var(42) ] D[42,57] = var(90); // [ var(57) , var(42) ] D[42,58] = var(91); // [ var(58) , var(42) ] D[42,63] = var(94); // [ var(63) , var(42) ] D[42,64] = var(95); // [ var(64) , var(42) ] D[42,70] = var(99); // [ var(70) , var(42) ] D[42,71] = var(100); // [ var(71) , var(42) ] D[42,76] = var(103); // [ var(76) , var(42) ] D[42,82] = var(106); // [ var(82) , var(42) ] D[42,93] = (-1)*var(112); // [ var(93) , var(42) ] D[42,97] = (-1)*var(113); // [ var(97) , var(42) ] D[42,114] = (-1)*var(120); // [ var(114) , var(42) ] D[43,45] = var(83); // [ var(45) , var(43) ] D[43,46] = var(84); // [ var(46) , var(43) ] D[43,52] = var(87); // [ var(52) , var(43) ] D[43,53] = var(88); // [ var(53) , var(43) ] D[43,59] = var(92); // [ var(59) , var(43) ] D[43,66] = var(96); // [ var(66) , var(43) ] D[43,69] = (-1)*var(98); // [ var(69) , var(43) ] D[43,75] = (-1)*var(102); // [ var(75) , var(43) ] D[43,80] = (-1)*var(105); // [ var(80) , var(43) ] D[43,85] = (-1)*var(108); // [ var(85) , var(43) ] D[43,89] = (-1)*var(110); // [ var(89) , var(43) ] D[43,97] = var(114); // [ var(97) , var(43) ] D[43,113] = var(120); // [ var(113) , var(43) ] D[44,61] = (-1)*var(93); // [ var(61) , var(44) ] D[44,66] = var(97); // [ var(66) , var(44) ] D[44,68] = (-1)*var(98); // [ var(68) , var(44) ] D[44,73] = var(101); // [ var(73) , var(44) ] D[44,74] = (-1)*var(102); // [ var(74) , var(44) ] D[44,79] = var(104); // [ var(79) , var(44) ] D[44,96] = var(114); // [ var(96) , var(44) ] D[44,100] = (-1)*var(115); // [ var(100) , var(44) ] D[44,103] = var(116); // [ var(103) , var(44) ] D[44,106] = (-1)*var(117); // [ var(106) , var(44) ] D[45,50] = var(86); // [ var(50) , var(45) ] D[45,55] = (-1)*var(89); // [ var(55) , var(45) ] D[45,62] = (-1)*var(94); // [ var(62) , var(45) ] D[45,64] = var(97); // [ var(64) , var(45) ] D[45,72] = var(101); // [ var(72) , var(45) ] D[45,74] = var(103); // [ var(74) , var(45) ] D[45,84] = (-1)*var(107); // [ var(84) , var(45) ] D[45,92] = var(111); // [ var(92) , var(45) ] D[45,95] = (-1)*var(113); // [ var(95) , var(45) ] D[45,102] = (-1)*var(116); // [ var(102) , var(45) ] D[45,108] = var(118); // [ var(108) , var(45) ] D[46,48] = var(85); // [ var(48) , var(46) ] D[46,56] = (-1)*var(91); // [ var(56) , var(46) ] D[46,62] = (-1)*var(95); // [ var(62) , var(46) ] D[46,63] = var(97); // [ var(63) , var(46) ] D[46,68] = (-1)*var(100); // [ var(68) , var(46) ] D[46,77] = (-1)*var(104); // [ var(77) , var(46) ] D[46,83] = (-1)*var(107); // [ var(83) , var(46) ] D[46,87] = (-1)*var(109); // [ var(87) , var(46) ] D[46,94] = (-1)*var(113); // [ var(94) , var(46) ] D[46,98] = (-1)*var(115); // [ var(98) , var(46) ] D[46,110] = var(119); // [ var(110) , var(46) ] D[47,48] = (-1)*var(87); // [ var(48) , var(47) ] D[47,49] = (-1)*var(88); // [ var(49) , var(47) ] D[47,55] = (-1)*var(92); // [ var(55) , var(47) ] D[47,61] = (-1)*var(96); // [ var(61) , var(47) ] D[47,69] = var(101); // [ var(69) , var(47) ] D[47,75] = var(104); // [ var(75) , var(47) ] D[47,80] = var(107); // [ var(80) , var(47) ] D[47,85] = var(109); // [ var(85) , var(47) ] D[47,89] = var(111); // [ var(89) , var(47) ] D[47,93] = var(114); // [ var(93) , var(47) ] D[47,112] = var(120); // [ var(112) , var(47) ] D[48,53] = (-1)*var(89); // [ var(53) , var(48) ] D[48,54] = (-1)*var(90); // [ var(54) , var(48) ] D[48,58] = var(93); // [ var(58) , var(48) ] D[48,60] = (-1)*var(94); // [ var(60) , var(48) ] D[48,65] = var(98); // [ var(65) , var(48) ] D[48,79] = (-1)*var(106); // [ var(79) , var(48) ] D[48,84] = var(108); // [ var(84) , var(48) ] D[48,88] = var(110); // [ var(88) , var(48) ] D[48,91] = (-1)*var(112); // [ var(91) , var(48) ] D[48,104] = var(117); // [ var(104) , var(48) ] D[48,107] = (-1)*var(118); // [ var(107) , var(48) ] D[49,52] = (-1)*var(89); // [ var(52) , var(49) ] D[49,54] = (-1)*var(91); // [ var(54) , var(49) ] D[49,57] = var(93); // [ var(57) , var(49) ] D[49,67] = var(99); // [ var(67) , var(49) ] D[49,72] = (-1)*var(102); // [ var(72) , var(49) ] D[49,73] = var(103); // [ var(73) , var(49) ] D[49,78] = (-1)*var(105); // [ var(78) , var(49) ] D[49,87] = var(110); // [ var(87) , var(49) ] D[49,90] = (-1)*var(112); // [ var(90) , var(49) ] D[49,101] = var(116); // [ var(101) , var(49) ] D[49,109] = (-1)*var(119); // [ var(109) , var(49) ] D[50,52] = (-1)*var(90); // [ var(52) , var(50) ] D[50,53] = (-1)*var(91); // [ var(53) , var(50) ] D[50,59] = (-1)*var(95); // [ var(59) , var(50) ] D[50,63] = (-1)*var(98); // [ var(63) , var(50) ] D[50,66] = (-1)*var(100); // [ var(66) , var(50) ] D[50,70] = (-1)*var(102); // [ var(70) , var(50) ] D[50,76] = (-1)*var(105); // [ var(76) , var(50) ] D[50,82] = (-1)*var(108); // [ var(82) , var(50) ] D[50,89] = (-1)*var(112); // [ var(89) , var(50) ] D[50,97] = var(115); // [ var(97) , var(50) ] D[50,111] = (-1)*var(120); // [ var(111) , var(50) ] D[51,55] = var(93); // [ var(55) , var(51) ] D[51,59] = (-1)*var(97); // [ var(59) , var(51) ] D[51,62] = var(98); // [ var(62) , var(51) ] D[51,67] = (-1)*var(101); // [ var(67) , var(51) ] D[51,74] = (-1)*var(105); // [ var(74) , var(51) ] D[51,79] = var(107); // [ var(79) , var(51) ] D[51,92] = (-1)*var(114); // [ var(92) , var(51) ] D[51,95] = var(115); // [ var(95) , var(51) ] D[51,99] = (-1)*var(116); // [ var(99) , var(51) ] D[51,106] = var(118); // [ var(106) , var(51) ] D[52,56] = var(94); // [ var(56) , var(52) ] D[52,58] = (-1)*var(97); // [ var(58) , var(52) ] D[52,65] = (-1)*var(101); // [ var(65) , var(52) ] D[52,74] = var(106); // [ var(74) , var(52) ] D[52,84] = (-1)*var(109); // [ var(84) , var(52) ] D[52,88] = (-1)*var(111); // [ var(88) , var(52) ] D[52,91] = var(113); // [ var(91) , var(52) ] D[52,102] = var(117); // [ var(102) , var(52) ] D[52,105] = (-1)*var(118); // [ var(105) , var(52) ] D[53,57] = (-1)*var(97); // [ var(57) , var(53) ] D[53,62] = (-1)*var(99); // [ var(62) , var(53) ] D[53,68] = (-1)*var(103); // [ var(68) , var(53) ] D[53,72] = var(104); // [ var(72) , var(53) ] D[53,78] = var(107); // [ var(78) , var(53) ] D[53,87] = (-1)*var(111); // [ var(87) , var(53) ] D[53,90] = var(113); // [ var(90) , var(53) ] D[53,98] = var(116); // [ var(98) , var(53) ] D[53,108] = (-1)*var(119); // [ var(108) , var(53) ] D[54,55] = var(95); // [ var(55) , var(54) ] D[54,61] = var(100); // [ var(61) , var(54) ] D[54,63] = var(101); // [ var(63) , var(54) ] D[54,70] = var(104); // [ var(70) , var(54) ] D[54,76] = var(107); // [ var(76) , var(54) ] D[54,82] = var(109); // [ var(82) , var(54) ] D[54,89] = var(113); // [ var(89) , var(54) ] D[54,93] = var(115); // [ var(93) , var(54) ] D[54,110] = (-1)*var(120); // [ var(110) , var(54) ] D[55,60] = (-1)*var(99); // [ var(60) , var(55) ] D[55,65] = var(102); // [ var(65) , var(55) ] D[55,73] = var(106); // [ var(73) , var(55) ] D[55,78] = (-1)*var(108); // [ var(78) , var(55) ] D[55,83] = (-1)*var(110); // [ var(83) , var(55) ] D[55,86] = var(112); // [ var(86) , var(55) ] D[55,101] = (-1)*var(117); // [ var(101) , var(55) ] D[55,107] = var(119); // [ var(107) , var(55) ] D[56,57] = var(98); // [ var(57) , var(56) ] D[56,59] = (-1)*var(99); // [ var(59) , var(56) ] D[56,64] = var(102); // [ var(64) , var(56) ] D[56,66] = (-1)*var(103); // [ var(66) , var(56) ] D[56,71] = var(105); // [ var(71) , var(56) ] D[56,82] = (-1)*var(110); // [ var(82) , var(56) ] D[56,85] = var(112); // [ var(85) , var(56) ] D[56,97] = (-1)*var(116); // [ var(97) , var(56) ] D[56,109] = var(120); // [ var(109) , var(56) ] D[57,60] = var(101); // [ var(60) , var(57) ] D[57,74] = (-1)*var(108); // [ var(74) , var(57) ] D[57,79] = var(109); // [ var(79) , var(57) ] D[57,88] = var(114); // [ var(88) , var(57) ] D[57,91] = (-1)*var(115); // [ var(91) , var(57) ] D[57,99] = var(117); // [ var(99) , var(57) ] D[57,103] = (-1)*var(118); // [ var(103) , var(57) ] D[58,62] = var(102); // [ var(62) , var(58) ] D[58,67] = (-1)*var(104); // [ var(67) , var(58) ] D[58,68] = var(105); // [ var(68) , var(58) ] D[58,73] = (-1)*var(107); // [ var(73) , var(58) ] D[58,87] = var(114); // [ var(87) , var(58) ] D[58,90] = (-1)*var(115); // [ var(90) , var(58) ] D[58,94] = var(116); // [ var(94) , var(58) ] D[58,106] = (-1)*var(119); // [ var(106) , var(58) ] D[59,65] = (-1)*var(104); // [ var(65) , var(59) ] D[59,68] = (-1)*var(106); // [ var(68) , var(59) ] D[59,78] = var(109); // [ var(78) , var(59) ] D[59,83] = var(111); // [ var(83) , var(59) ] D[59,86] = (-1)*var(113); // [ var(86) , var(59) ] D[59,98] = (-1)*var(117); // [ var(98) , var(59) ] D[59,105] = var(119); // [ var(105) , var(59) ] D[60,61] = var(103); // [ var(61) , var(60) ] D[60,64] = (-1)*var(104); // [ var(64) , var(60) ] D[60,71] = (-1)*var(107); // [ var(71) , var(60) ] D[60,82] = var(111); // [ var(82) , var(60) ] D[60,85] = (-1)*var(113); // [ var(85) , var(60) ] D[60,93] = (-1)*var(116); // [ var(93) , var(60) ] D[60,108] = var(120); // [ var(108) , var(60) ] D[61,65] = var(105); // [ var(65) , var(61) ] D[61,67] = (-1)*var(106); // [ var(67) , var(61) ] D[61,72] = var(108); // [ var(72) , var(61) ] D[61,77] = var(110); // [ var(77) , var(61) ] D[61,81] = (-1)*var(112); // [ var(81) , var(61) ] D[61,101] = var(118); // [ var(101) , var(61) ] D[61,104] = (-1)*var(119); // [ var(104) , var(61) ] D[62,66] = (-1)*var(106); // [ var(66) , var(62) ] D[62,71] = var(108); // [ var(71) , var(62) ] D[62,76] = var(110); // [ var(76) , var(62) ] D[62,80] = (-1)*var(112); // [ var(80) , var(62) ] D[62,97] = var(117); // [ var(97) , var(62) ] D[62,107] = (-1)*var(120); // [ var(107) , var(62) ] D[63,74] = (-1)*var(110); // [ var(74) , var(63) ] D[63,79] = var(111); // [ var(79) , var(63) ] D[63,84] = (-1)*var(114); // [ var(84) , var(63) ] D[63,91] = var(116); // [ var(91) , var(63) ] D[63,95] = (-1)*var(117); // [ var(95) , var(63) ] D[63,100] = var(118); // [ var(100) , var(63) ] D[64,68] = var(108); // [ var(68) , var(64) ] D[64,73] = (-1)*var(109); // [ var(73) , var(64) ] D[64,83] = (-1)*var(114); // [ var(83) , var(64) ] D[64,86] = var(115); // [ var(86) , var(64) ] D[64,94] = (-1)*var(117); // [ var(94) , var(64) ] D[64,103] = var(119); // [ var(103) , var(64) ] D[65,66] = var(107); // [ var(66) , var(65) ] D[65,82] = (-1)*var(114); // [ var(82) , var(65) ] D[65,85] = var(115); // [ var(85) , var(65) ] D[65,89] = (-1)*var(116); // [ var(89) , var(65) ] D[65,106] = var(120); // [ var(106) , var(65) ] D[66,72] = (-1)*var(109); // [ var(72) , var(66) ] D[66,77] = (-1)*var(111); // [ var(77) , var(66) ] D[66,81] = var(113); // [ var(81) , var(66) ] D[66,98] = var(118); // [ var(98) , var(66) ] D[66,102] = (-1)*var(119); // [ var(102) , var(66) ] D[67,71] = (-1)*var(109); // [ var(71) , var(67) ] D[67,76] = (-1)*var(111); // [ var(76) , var(67) ] D[67,80] = var(113); // [ var(80) , var(67) ] D[67,93] = var(117); // [ var(93) , var(67) ] D[67,105] = (-1)*var(120); // [ var(105) , var(67) ] D[68,70] = (-1)*var(110); // [ var(70) , var(68) ] D[68,75] = var(112); // [ var(75) , var(68) ] D[68,97] = (-1)*var(118); // [ var(97) , var(68) ] D[68,104] = var(120); // [ var(104) , var(68) ] D[69,74] = var(112); // [ var(74) , var(69) ] D[69,79] = (-1)*var(113); // [ var(79) , var(69) ] D[69,84] = var(115); // [ var(84) , var(69) ] D[69,88] = (-1)*var(116); // [ var(88) , var(69) ] D[69,92] = var(117); // [ var(92) , var(69) ] D[69,96] = (-1)*var(118); // [ var(96) , var(69) ] D[70,73] = (-1)*var(111); // [ var(73) , var(70) ] D[70,78] = var(114); // [ var(78) , var(70) ] D[70,86] = (-1)*var(116); // [ var(86) , var(70) ] D[70,90] = var(117); // [ var(90) , var(70) ] D[70,100] = (-1)*var(119); // [ var(100) , var(70) ] D[71,77] = var(114); // [ var(77) , var(71) ] D[71,81] = (-1)*var(115); // [ var(81) , var(71) ] D[71,94] = var(118); // [ var(94) , var(71) ] D[71,99] = (-1)*var(119); // [ var(99) , var(71) ] D[72,76] = var(114); // [ var(76) , var(72) ] D[72,80] = (-1)*var(115); // [ var(80) , var(72) ] D[72,89] = var(117); // [ var(89) , var(72) ] D[72,103] = (-1)*var(120); // [ var(103) , var(72) ] D[73,75] = (-1)*var(113); // [ var(75) , var(73) ] D[73,93] = (-1)*var(118); // [ var(93) , var(73) ] D[73,102] = var(120); // [ var(102) , var(73) ] D[74,97] = var(119); // [ var(97) , var(74) ] D[74,101] = (-1)*var(120); // [ var(101) , var(74) ] D[75,78] = (-1)*var(115); // [ var(78) , var(75) ] D[75,83] = var(116); // [ var(83) , var(75) ] D[75,87] = (-1)*var(117); // [ var(87) , var(75) ] D[75,96] = var(119); // [ var(96) , var(75) ] D[76,81] = var(116); // [ var(81) , var(76) ] D[76,90] = (-1)*var(118); // [ var(90) , var(76) ] D[76,95] = var(119); // [ var(95) , var(76) ] D[77,80] = var(116); // [ var(80) , var(77) ] D[77,85] = (-1)*var(117); // [ var(85) , var(77) ] D[77,100] = var(120); // [ var(100) , var(77) ] D[78,89] = (-1)*var(118); // [ var(89) , var(78) ] D[78,99] = var(120); // [ var(99) , var(78) ] D[79,93] = var(119); // [ var(93) , var(79) ] D[79,98] = (-1)*var(120); // [ var(98) , var(79) ] D[80,87] = var(118); // [ var(87) , var(80) ] D[80,92] = (-1)*var(119); // [ var(92) , var(80) ] D[81,82] = var(117); // [ var(82) , var(81) ] D[81,96] = (-1)*var(120); // [ var(96) , var(81) ] D[82,86] = var(118); // [ var(86) , var(82) ] D[82,91] = (-1)*var(119); // [ var(91) , var(82) ] D[83,85] = var(118); // [ var(85) , var(83) ] D[83,95] = (-1)*var(120); // [ var(95) , var(83) ] D[84,89] = var(119); // [ var(89) , var(84) ] D[84,94] = (-1)*var(120); // [ var(94) , var(84) ] D[85,88] = var(119); // [ var(88) , var(85) ] D[86,92] = var(120); // [ var(92) , var(86) ] D[87,91] = var(120); // [ var(91) , var(87) ] D[88,90] = var(120); // [ var(90) , var(88) ] // Y(i) * Y(j): D[121,123] = (-1)*var(129); // [ var(123) , var(121) ] D[121,131] = (-1)*var(136); // [ var(131) , var(121) ] D[121,137] = (-1)*var(143); // [ var(137) , var(121) ] D[121,139] = (-1)*var(144); // [ var(139) , var(121) ] D[121,145] = (-1)*var(150); // [ var(145) , var(121) ] D[121,147] = (-1)*var(151); // [ var(147) , var(121) ] D[121,152] = (-1)*var(157); // [ var(152) , var(121) ] D[121,153] = (-1)*var(158); // [ var(153) , var(121) ] D[121,155] = (-1)*var(159); // [ var(155) , var(121) ] D[121,160] = (-1)*var(165); // [ var(160) , var(121) ] D[121,161] = (-1)*var(166); // [ var(161) , var(121) ] D[121,163] = (-1)*var(167); // [ var(163) , var(121) ] D[121,168] = (-1)*var(172); // [ var(168) , var(121) ] D[121,169] = (-1)*var(173); // [ var(169) , var(121) ] D[121,170] = (-1)*var(174); // [ var(170) , var(121) ] D[121,175] = (-1)*var(179); // [ var(175) , var(121) ] D[121,176] = (-1)*var(180); // [ var(176) , var(121) ] D[121,181] = (-1)*var(186); // [ var(181) , var(121) ] D[121,182] = (-1)*var(187); // [ var(182) , var(121) ] D[121,188] = (-1)*var(193); // [ var(188) , var(121) ] D[121,194] = (-1)*var(199); // [ var(194) , var(121) ] D[121,213] = var(217); // [ var(213) , var(121) ] D[121,218] = var(221); // [ var(218) , var(121) ] D[121,222] = var(224); // [ var(222) , var(121) ] D[121,225] = var(227); // [ var(225) , var(121) ] D[121,228] = var(229); // [ var(228) , var(121) ] D[121,230] = var(231); // [ var(230) , var(121) ] D[121,232] = var(233); // [ var(232) , var(121) ] D[122,124] = (-1)*var(130); // [ var(124) , var(122) ] D[122,131] = (-1)*var(137); // [ var(131) , var(122) ] D[122,132] = (-1)*var(138); // [ var(132) , var(122) ] D[122,136] = (-1)*var(143); // [ var(136) , var(122) ] D[122,139] = (-1)*var(145); // [ var(139) , var(122) ] D[122,140] = (-1)*var(146); // [ var(140) , var(122) ] D[122,144] = (-1)*var(150); // [ var(144) , var(122) ] D[122,147] = (-1)*var(153); // [ var(147) , var(122) ] D[122,148] = (-1)*var(154); // [ var(148) , var(122) ] D[122,151] = (-1)*var(158); // [ var(151) , var(122) ] D[122,155] = (-1)*var(161); // [ var(155) , var(122) ] D[122,156] = (-1)*var(162); // [ var(156) , var(122) ] D[122,159] = (-1)*var(166); // [ var(159) , var(122) ] D[122,163] = (-1)*var(170); // [ var(163) , var(122) ] D[122,167] = (-1)*var(174); // [ var(167) , var(122) ] D[122,183] = var(189); // [ var(183) , var(122) ] D[122,190] = var(195); // [ var(190) , var(122) ] D[122,196] = var(200); // [ var(196) , var(122) ] D[122,197] = var(201); // [ var(197) , var(122) ] D[122,202] = var(205); // [ var(202) , var(122) ] D[122,203] = var(206); // [ var(203) , var(122) ] D[122,207] = var(210); // [ var(207) , var(122) ] D[122,208] = var(211); // [ var(208) , var(122) ] D[122,212] = var(215); // [ var(212) , var(122) ] D[122,216] = var(220); // [ var(216) , var(122) ] D[122,230] = (-1)*var(232); // [ var(230) , var(122) ] D[122,231] = (-1)*var(233); // [ var(231) , var(122) ] D[122,234] = (-1)*var(235); // [ var(234) , var(122) ] D[123,124] = (-1)*var(131); // [ var(124) , var(123) ] D[123,130] = (-1)*var(137); // [ var(130) , var(123) ] D[123,132] = (-1)*var(139); // [ var(132) , var(123) ] D[123,138] = (-1)*var(145); // [ var(138) , var(123) ] D[123,140] = (-1)*var(147); // [ var(140) , var(123) ] D[123,146] = (-1)*var(153); // [ var(146) , var(123) ] D[123,148] = (-1)*var(155); // [ var(148) , var(123) ] D[123,154] = (-1)*var(161); // [ var(154) , var(123) ] D[123,156] = (-1)*var(163); // [ var(156) , var(123) ] D[123,157] = (-1)*var(164); // [ var(157) , var(123) ] D[123,162] = (-1)*var(170); // [ var(162) , var(123) ] D[123,165] = (-1)*var(171); // [ var(165) , var(123) ] D[123,172] = (-1)*var(177); // [ var(172) , var(123) ] D[123,173] = (-1)*var(178); // [ var(173) , var(123) ] D[123,179] = (-1)*var(184); // [ var(179) , var(123) ] D[123,180] = (-1)*var(185); // [ var(180) , var(123) ] D[123,186] = (-1)*var(191); // [ var(186) , var(123) ] D[123,187] = (-1)*var(192); // [ var(187) , var(123) ] D[123,193] = (-1)*var(198); // [ var(193) , var(123) ] D[123,199] = (-1)*var(204); // [ var(199) , var(123) ] D[123,209] = var(213); // [ var(209) , var(123) ] D[123,214] = var(218); // [ var(214) , var(123) ] D[123,219] = var(222); // [ var(219) , var(123) ] D[123,223] = var(225); // [ var(223) , var(123) ] D[123,226] = var(228); // [ var(226) , var(123) ] D[123,231] = var(234); // [ var(231) , var(123) ] D[123,233] = var(235); // [ var(233) , var(123) ] D[124,125] = (-1)*var(132); // [ var(125) , var(124) ] D[124,129] = var(136); // [ var(129) , var(124) ] D[124,133] = (-1)*var(140); // [ var(133) , var(124) ] D[124,141] = (-1)*var(148); // [ var(141) , var(124) ] D[124,145] = var(152); // [ var(145) , var(124) ] D[124,149] = (-1)*var(156); // [ var(149) , var(124) ] D[124,150] = var(157); // [ var(150) , var(124) ] D[124,153] = var(160); // [ var(153) , var(124) ] D[124,158] = var(165); // [ var(158) , var(124) ] D[124,161] = var(169); // [ var(161) , var(124) ] D[124,166] = var(173); // [ var(166) , var(124) ] D[124,170] = var(176); // [ var(170) , var(124) ] D[124,174] = var(180); // [ var(174) , var(124) ] D[124,177] = var(183); // [ var(177) , var(124) ] D[124,184] = var(190); // [ var(184) , var(124) ] D[124,191] = var(196); // [ var(191) , var(124) ] D[124,192] = var(197); // [ var(192) , var(124) ] D[124,198] = var(203); // [ var(198) , var(124) ] D[124,204] = var(208); // [ var(204) , var(124) ] D[124,205] = var(209); // [ var(205) , var(124) ] D[124,210] = var(214); // [ var(210) , var(124) ] D[124,215] = var(219); // [ var(215) , var(124) ] D[124,220] = var(223); // [ var(220) , var(124) ] D[124,228] = var(230); // [ var(228) , var(124) ] D[124,229] = var(231); // [ var(229) , var(124) ] D[124,235] = (-1)*var(236); // [ var(235) , var(124) ] D[125,126] = (-1)*var(133); // [ var(126) , var(125) ] D[125,130] = var(138); // [ var(130) , var(125) ] D[125,131] = var(139); // [ var(131) , var(125) ] D[125,134] = (-1)*var(141); // [ var(134) , var(125) ] D[125,136] = var(144); // [ var(136) , var(125) ] D[125,137] = var(145); // [ var(137) , var(125) ] D[125,142] = (-1)*var(149); // [ var(142) , var(125) ] D[125,143] = var(150); // [ var(143) , var(125) ] D[125,160] = var(168); // [ var(160) , var(125) ] D[125,165] = var(172); // [ var(165) , var(125) ] D[125,169] = var(175); // [ var(169) , var(125) ] D[125,171] = var(177); // [ var(171) , var(125) ] D[125,173] = var(179); // [ var(173) , var(125) ] D[125,176] = var(182); // [ var(176) , var(125) ] D[125,178] = var(184); // [ var(178) , var(125) ] D[125,180] = var(187); // [ var(180) , var(125) ] D[125,185] = var(192); // [ var(185) , var(125) ] D[125,196] = var(202); // [ var(196) , var(125) ] D[125,200] = var(205); // [ var(200) , var(125) ] D[125,203] = var(207); // [ var(203) , var(125) ] D[125,206] = var(210); // [ var(206) , var(125) ] D[125,208] = var(212); // [ var(208) , var(125) ] D[125,211] = var(215); // [ var(211) , var(125) ] D[125,223] = var(226); // [ var(223) , var(125) ] D[125,225] = var(228); // [ var(225) , var(125) ] D[125,227] = var(229); // [ var(227) , var(125) ] D[125,236] = (-1)*var(237); // [ var(236) , var(125) ] D[126,127] = (-1)*var(134); // [ var(127) , var(126) ] D[126,132] = var(140); // [ var(132) , var(126) ] D[126,135] = (-1)*var(142); // [ var(135) , var(126) ] D[126,138] = var(146); // [ var(138) , var(126) ] D[126,139] = var(147); // [ var(139) , var(126) ] D[126,144] = var(151); // [ var(144) , var(126) ] D[126,145] = var(153); // [ var(145) , var(126) ] D[126,150] = var(158); // [ var(150) , var(126) ] D[126,152] = var(160); // [ var(152) , var(126) ] D[126,157] = var(165); // [ var(157) , var(126) ] D[126,164] = var(171); // [ var(164) , var(126) ] D[126,175] = var(181); // [ var(175) , var(126) ] D[126,179] = var(186); // [ var(179) , var(126) ] D[126,182] = var(188); // [ var(182) , var(126) ] D[126,184] = var(191); // [ var(184) , var(126) ] D[126,187] = var(193); // [ var(187) , var(126) ] D[126,190] = var(196); // [ var(190) , var(126) ] D[126,192] = var(198); // [ var(192) , var(126) ] D[126,195] = var(200); // [ var(195) , var(126) ] D[126,197] = var(203); // [ var(197) , var(126) ] D[126,201] = var(206); // [ var(201) , var(126) ] D[126,212] = var(216); // [ var(212) , var(126) ] D[126,215] = var(220); // [ var(215) , var(126) ] D[126,219] = var(223); // [ var(219) , var(126) ] D[126,222] = var(225); // [ var(222) , var(126) ] D[126,224] = var(227); // [ var(224) , var(126) ] D[126,237] = (-1)*var(238); // [ var(237) , var(126) ] D[127,128] = (-1)*var(135); // [ var(128) , var(127) ] D[127,133] = var(141); // [ var(133) , var(127) ] D[127,140] = var(148); // [ var(140) , var(127) ] D[127,146] = var(154); // [ var(146) , var(127) ] D[127,147] = var(155); // [ var(147) , var(127) ] D[127,151] = var(159); // [ var(151) , var(127) ] D[127,153] = var(161); // [ var(153) , var(127) ] D[127,158] = var(166); // [ var(158) , var(127) ] D[127,160] = var(169); // [ var(160) , var(127) ] D[127,165] = var(173); // [ var(165) , var(127) ] D[127,168] = var(175); // [ var(168) , var(127) ] D[127,171] = var(178); // [ var(171) , var(127) ] D[127,172] = var(179); // [ var(172) , var(127) ] D[127,177] = var(184); // [ var(177) , var(127) ] D[127,183] = var(190); // [ var(183) , var(127) ] D[127,188] = var(194); // [ var(188) , var(127) ] D[127,189] = var(195); // [ var(189) , var(127) ] D[127,193] = var(199); // [ var(193) , var(127) ] D[127,198] = var(204); // [ var(198) , var(127) ] D[127,203] = var(208); // [ var(203) , var(127) ] D[127,206] = var(211); // [ var(206) , var(127) ] D[127,207] = var(212); // [ var(207) , var(127) ] D[127,210] = var(215); // [ var(210) , var(127) ] D[127,214] = var(219); // [ var(214) , var(127) ] D[127,218] = var(222); // [ var(218) , var(127) ] D[127,221] = var(224); // [ var(221) , var(127) ] D[127,238] = (-1)*var(239); // [ var(238) , var(127) ] D[128,134] = var(142); // [ var(134) , var(128) ] D[128,141] = var(149); // [ var(141) , var(128) ] D[128,148] = var(156); // [ var(148) , var(128) ] D[128,154] = var(162); // [ var(154) , var(128) ] D[128,155] = var(163); // [ var(155) , var(128) ] D[128,159] = var(167); // [ var(159) , var(128) ] D[128,161] = var(170); // [ var(161) , var(128) ] D[128,166] = var(174); // [ var(166) , var(128) ] D[128,169] = var(176); // [ var(169) , var(128) ] D[128,173] = var(180); // [ var(173) , var(128) ] D[128,175] = var(182); // [ var(175) , var(128) ] D[128,178] = var(185); // [ var(178) , var(128) ] D[128,179] = var(187); // [ var(179) , var(128) ] D[128,181] = var(188); // [ var(181) , var(128) ] D[128,184] = var(192); // [ var(184) , var(128) ] D[128,186] = var(193); // [ var(186) , var(128) ] D[128,190] = var(197); // [ var(190) , var(128) ] D[128,191] = var(198); // [ var(191) , var(128) ] D[128,195] = var(201); // [ var(195) , var(128) ] D[128,196] = var(203); // [ var(196) , var(128) ] D[128,200] = var(206); // [ var(200) , var(128) ] D[128,202] = var(207); // [ var(202) , var(128) ] D[128,205] = var(210); // [ var(205) , var(128) ] D[128,209] = var(214); // [ var(209) , var(128) ] D[128,213] = var(218); // [ var(213) , var(128) ] D[128,217] = var(221); // [ var(217) , var(128) ] D[128,239] = (-1)*var(240); // [ var(239) , var(128) ] D[129,130] = (-1)*var(143); // [ var(130) , var(129) ] D[129,132] = (-1)*var(144); // [ var(132) , var(129) ] D[129,138] = (-1)*var(150); // [ var(138) , var(129) ] D[129,140] = (-1)*var(151); // [ var(140) , var(129) ] D[129,146] = (-1)*var(158); // [ var(146) , var(129) ] D[129,148] = (-1)*var(159); // [ var(148) , var(129) ] D[129,152] = var(164); // [ var(152) , var(129) ] D[129,154] = (-1)*var(166); // [ var(154) , var(129) ] D[129,156] = (-1)*var(167); // [ var(156) , var(129) ] D[129,160] = var(171); // [ var(160) , var(129) ] D[129,162] = (-1)*var(174); // [ var(162) , var(129) ] D[129,168] = var(177); // [ var(168) , var(129) ] D[129,169] = var(178); // [ var(169) , var(129) ] D[129,175] = var(184); // [ var(175) , var(129) ] D[129,176] = var(185); // [ var(176) , var(129) ] D[129,181] = var(191); // [ var(181) , var(129) ] D[129,182] = var(192); // [ var(182) , var(129) ] D[129,188] = var(198); // [ var(188) , var(129) ] D[129,194] = var(204); // [ var(194) , var(129) ] D[129,209] = (-1)*var(217); // [ var(209) , var(129) ] D[129,214] = (-1)*var(221); // [ var(214) , var(129) ] D[129,219] = (-1)*var(224); // [ var(219) , var(129) ] D[129,223] = (-1)*var(227); // [ var(223) , var(129) ] D[129,226] = (-1)*var(229); // [ var(226) , var(129) ] D[129,230] = var(234); // [ var(230) , var(129) ] D[129,232] = var(235); // [ var(232) , var(129) ] D[130,133] = (-1)*var(146); // [ var(133) , var(130) ] D[130,139] = (-1)*var(152); // [ var(139) , var(130) ] D[130,141] = (-1)*var(154); // [ var(141) , var(130) ] D[130,144] = (-1)*var(157); // [ var(144) , var(130) ] D[130,147] = (-1)*var(160); // [ var(147) , var(130) ] D[130,149] = (-1)*var(162); // [ var(149) , var(130) ] D[130,151] = (-1)*var(165); // [ var(151) , var(130) ] D[130,155] = (-1)*var(169); // [ var(155) , var(130) ] D[130,159] = (-1)*var(173); // [ var(159) , var(130) ] D[130,163] = (-1)*var(176); // [ var(163) , var(130) ] D[130,167] = (-1)*var(180); // [ var(167) , var(130) ] D[130,177] = (-1)*var(189); // [ var(177) , var(130) ] D[130,184] = (-1)*var(195); // [ var(184) , var(130) ] D[130,191] = (-1)*var(200); // [ var(191) , var(130) ] D[130,192] = (-1)*var(201); // [ var(192) , var(130) ] D[130,198] = (-1)*var(206); // [ var(198) , var(130) ] D[130,202] = var(209); // [ var(202) , var(130) ] D[130,204] = (-1)*var(211); // [ var(204) , var(130) ] D[130,207] = var(214); // [ var(207) , var(130) ] D[130,212] = var(219); // [ var(212) , var(130) ] D[130,216] = var(223); // [ var(216) , var(130) ] D[130,228] = var(232); // [ var(228) , var(130) ] D[130,229] = var(233); // [ var(229) , var(130) ] D[130,234] = var(236); // [ var(234) , var(130) ] D[131,133] = (-1)*var(147); // [ var(133) , var(131) ] D[131,138] = (-1)*var(152); // [ var(138) , var(131) ] D[131,141] = (-1)*var(155); // [ var(141) , var(131) ] D[131,146] = (-1)*var(160); // [ var(146) , var(131) ] D[131,149] = (-1)*var(163); // [ var(149) , var(131) ] D[131,150] = var(164); // [ var(150) , var(131) ] D[131,154] = (-1)*var(169); // [ var(154) , var(131) ] D[131,158] = var(171); // [ var(158) , var(131) ] D[131,162] = (-1)*var(176); // [ var(162) , var(131) ] D[131,166] = var(178); // [ var(166) , var(131) ] D[131,172] = (-1)*var(183); // [ var(172) , var(131) ] D[131,174] = var(185); // [ var(174) , var(131) ] D[131,179] = (-1)*var(190); // [ var(179) , var(131) ] D[131,186] = (-1)*var(196); // [ var(186) , var(131) ] D[131,187] = (-1)*var(197); // [ var(187) , var(131) ] D[131,193] = (-1)*var(203); // [ var(193) , var(131) ] D[131,199] = (-1)*var(208); // [ var(199) , var(131) ] D[131,205] = (-1)*var(213); // [ var(205) , var(131) ] D[131,210] = (-1)*var(218); // [ var(210) , var(131) ] D[131,215] = (-1)*var(222); // [ var(215) , var(131) ] D[131,220] = (-1)*var(225); // [ var(220) , var(131) ] D[131,226] = var(230); // [ var(226) , var(131) ] D[131,229] = (-1)*var(234); // [ var(229) , var(131) ] D[131,233] = (-1)*var(236); // [ var(233) , var(131) ] D[132,134] = (-1)*var(148); // [ var(134) , var(132) ] D[132,137] = (-1)*var(152); // [ var(137) , var(132) ] D[132,142] = (-1)*var(156); // [ var(142) , var(132) ] D[132,143] = (-1)*var(157); // [ var(143) , var(132) ] D[132,153] = var(168); // [ var(153) , var(132) ] D[132,158] = var(172); // [ var(158) , var(132) ] D[132,161] = var(175); // [ var(161) , var(132) ] D[132,166] = var(179); // [ var(166) , var(132) ] D[132,170] = var(182); // [ var(170) , var(132) ] D[132,171] = (-1)*var(183); // [ var(171) , var(132) ] D[132,174] = var(187); // [ var(174) , var(132) ] D[132,178] = (-1)*var(190); // [ var(178) , var(132) ] D[132,185] = (-1)*var(197); // [ var(185) , var(132) ] D[132,191] = var(202); // [ var(191) , var(132) ] D[132,198] = var(207); // [ var(198) , var(132) ] D[132,200] = (-1)*var(209); // [ var(200) , var(132) ] D[132,204] = var(212); // [ var(204) , var(132) ] D[132,206] = (-1)*var(214); // [ var(206) , var(132) ] D[132,211] = (-1)*var(219); // [ var(211) , var(132) ] D[132,220] = var(226); // [ var(220) , var(132) ] D[132,225] = (-1)*var(230); // [ var(225) , var(132) ] D[132,227] = (-1)*var(231); // [ var(227) , var(132) ] D[132,235] = var(237); // [ var(235) , var(132) ] D[133,135] = (-1)*var(149); // [ var(135) , var(133) ] D[133,136] = var(151); // [ var(136) , var(133) ] D[133,137] = var(153); // [ var(137) , var(133) ] D[133,143] = var(158); // [ var(143) , var(133) ] D[133,152] = (-1)*var(168); // [ var(152) , var(133) ] D[133,157] = (-1)*var(172); // [ var(157) , var(133) ] D[133,164] = (-1)*var(177); // [ var(164) , var(133) ] D[133,169] = var(181); // [ var(169) , var(133) ] D[133,173] = var(186); // [ var(173) , var(133) ] D[133,176] = var(188); // [ var(176) , var(133) ] D[133,178] = var(191); // [ var(178) , var(133) ] D[133,180] = var(193); // [ var(180) , var(133) ] D[133,185] = var(198); // [ var(185) , var(133) ] D[133,190] = (-1)*var(202); // [ var(190) , var(133) ] D[133,195] = (-1)*var(205); // [ var(195) , var(133) ] D[133,197] = (-1)*var(207); // [ var(197) , var(133) ] D[133,201] = (-1)*var(210); // [ var(201) , var(133) ] D[133,208] = var(216); // [ var(208) , var(133) ] D[133,211] = var(220); // [ var(211) , var(133) ] D[133,219] = (-1)*var(226); // [ var(219) , var(133) ] D[133,222] = (-1)*var(228); // [ var(222) , var(133) ] D[133,224] = (-1)*var(229); // [ var(224) , var(133) ] D[133,236] = var(238); // [ var(236) , var(133) ] D[134,138] = var(154); // [ var(138) , var(134) ] D[134,139] = var(155); // [ var(139) , var(134) ] D[134,144] = var(159); // [ var(144) , var(134) ] D[134,145] = var(161); // [ var(145) , var(134) ] D[134,150] = var(166); // [ var(150) , var(134) ] D[134,152] = var(169); // [ var(152) , var(134) ] D[134,157] = var(173); // [ var(157) , var(134) ] D[134,164] = var(178); // [ var(164) , var(134) ] D[134,168] = (-1)*var(181); // [ var(168) , var(134) ] D[134,172] = (-1)*var(186); // [ var(172) , var(134) ] D[134,177] = (-1)*var(191); // [ var(177) , var(134) ] D[134,182] = var(194); // [ var(182) , var(134) ] D[134,183] = (-1)*var(196); // [ var(183) , var(134) ] D[134,187] = var(199); // [ var(187) , var(134) ] D[134,189] = (-1)*var(200); // [ var(189) , var(134) ] D[134,192] = var(204); // [ var(192) , var(134) ] D[134,197] = var(208); // [ var(197) , var(134) ] D[134,201] = var(211); // [ var(201) , var(134) ] D[134,207] = (-1)*var(216); // [ var(207) , var(134) ] D[134,210] = (-1)*var(220); // [ var(210) , var(134) ] D[134,214] = (-1)*var(223); // [ var(214) , var(134) ] D[134,218] = (-1)*var(225); // [ var(218) , var(134) ] D[134,221] = (-1)*var(227); // [ var(221) , var(134) ] D[134,237] = var(239); // [ var(237) , var(134) ] D[135,140] = var(156); // [ var(140) , var(135) ] D[135,146] = var(162); // [ var(146) , var(135) ] D[135,147] = var(163); // [ var(147) , var(135) ] D[135,151] = var(167); // [ var(151) , var(135) ] D[135,153] = var(170); // [ var(153) , var(135) ] D[135,158] = var(174); // [ var(158) , var(135) ] D[135,160] = var(176); // [ var(160) , var(135) ] D[135,165] = var(180); // [ var(165) , var(135) ] D[135,168] = var(182); // [ var(168) , var(135) ] D[135,171] = var(185); // [ var(171) , var(135) ] D[135,172] = var(187); // [ var(172) , var(135) ] D[135,177] = var(192); // [ var(177) , var(135) ] D[135,181] = (-1)*var(194); // [ var(181) , var(135) ] D[135,183] = var(197); // [ var(183) , var(135) ] D[135,186] = (-1)*var(199); // [ var(186) , var(135) ] D[135,189] = var(201); // [ var(189) , var(135) ] D[135,191] = (-1)*var(204); // [ var(191) , var(135) ] D[135,196] = (-1)*var(208); // [ var(196) , var(135) ] D[135,200] = (-1)*var(211); // [ var(200) , var(135) ] D[135,202] = (-1)*var(212); // [ var(202) , var(135) ] D[135,205] = (-1)*var(215); // [ var(205) , var(135) ] D[135,209] = (-1)*var(219); // [ var(209) , var(135) ] D[135,213] = (-1)*var(222); // [ var(213) , var(135) ] D[135,217] = (-1)*var(224); // [ var(217) , var(135) ] D[135,238] = var(240); // [ var(238) , var(135) ] D[136,138] = (-1)*var(157); // [ var(138) , var(136) ] D[136,141] = (-1)*var(159); // [ var(141) , var(136) ] D[136,145] = (-1)*var(164); // [ var(145) , var(136) ] D[136,146] = (-1)*var(165); // [ var(146) , var(136) ] D[136,149] = (-1)*var(167); // [ var(149) , var(136) ] D[136,153] = (-1)*var(171); // [ var(153) , var(136) ] D[136,154] = (-1)*var(173); // [ var(154) , var(136) ] D[136,161] = (-1)*var(178); // [ var(161) , var(136) ] D[136,162] = (-1)*var(180); // [ var(162) , var(136) ] D[136,168] = var(183); // [ var(168) , var(136) ] D[136,170] = (-1)*var(185); // [ var(170) , var(136) ] D[136,175] = var(190); // [ var(175) , var(136) ] D[136,181] = var(196); // [ var(181) , var(136) ] D[136,182] = var(197); // [ var(182) , var(136) ] D[136,188] = var(203); // [ var(188) , var(136) ] D[136,194] = var(208); // [ var(194) , var(136) ] D[136,205] = var(217); // [ var(205) , var(136) ] D[136,210] = var(221); // [ var(210) , var(136) ] D[136,215] = var(224); // [ var(215) , var(136) ] D[136,220] = var(227); // [ var(220) , var(136) ] D[136,226] = (-1)*var(231); // [ var(226) , var(136) ] D[136,228] = (-1)*var(234); // [ var(228) , var(136) ] D[136,232] = (-1)*var(236); // [ var(232) , var(136) ] D[137,140] = var(160); // [ var(140) , var(137) ] D[137,141] = (-1)*var(161); // [ var(141) , var(137) ] D[137,144] = (-1)*var(164); // [ var(144) , var(137) ] D[137,148] = var(169); // [ var(148) , var(137) ] D[137,149] = (-1)*var(170); // [ var(149) , var(137) ] D[137,151] = (-1)*var(171); // [ var(151) , var(137) ] D[137,156] = var(176); // [ var(156) , var(137) ] D[137,159] = (-1)*var(178); // [ var(159) , var(137) ] D[137,167] = (-1)*var(185); // [ var(167) , var(137) ] D[137,172] = var(189); // [ var(172) , var(137) ] D[137,179] = var(195); // [ var(179) , var(137) ] D[137,186] = var(200); // [ var(186) , var(137) ] D[137,187] = var(201); // [ var(187) , var(137) ] D[137,193] = var(206); // [ var(193) , var(137) ] D[137,199] = var(211); // [ var(199) , var(137) ] D[137,202] = (-1)*var(213); // [ var(202) , var(137) ] D[137,207] = (-1)*var(218); // [ var(207) , var(137) ] D[137,212] = (-1)*var(222); // [ var(212) , var(137) ] D[137,216] = (-1)*var(225); // [ var(216) , var(137) ] D[137,226] = var(232); // [ var(226) , var(137) ] D[137,229] = (-1)*var(235); // [ var(229) , var(137) ] D[137,231] = var(236); // [ var(231) , var(137) ] D[138,142] = (-1)*var(162); // [ var(142) , var(138) ] D[138,147] = (-1)*var(168); // [ var(147) , var(138) ] D[138,151] = (-1)*var(172); // [ var(151) , var(138) ] D[138,155] = (-1)*var(175); // [ var(155) , var(138) ] D[138,159] = (-1)*var(179); // [ var(159) , var(138) ] D[138,163] = (-1)*var(182); // [ var(163) , var(138) ] D[138,167] = (-1)*var(187); // [ var(167) , var(138) ] D[138,171] = var(189); // [ var(171) , var(138) ] D[138,178] = var(195); // [ var(178) , var(138) ] D[138,185] = var(201); // [ var(185) , var(138) ] D[138,191] = (-1)*var(205); // [ var(191) , var(138) ] D[138,196] = (-1)*var(209); // [ var(196) , var(138) ] D[138,198] = (-1)*var(210); // [ var(198) , var(138) ] D[138,203] = (-1)*var(214); // [ var(203) , var(138) ] D[138,204] = (-1)*var(215); // [ var(204) , var(138) ] D[138,208] = (-1)*var(219); // [ var(208) , var(138) ] D[138,216] = var(226); // [ var(216) , var(138) ] D[138,225] = (-1)*var(232); // [ var(225) , var(138) ] D[138,227] = (-1)*var(233); // [ var(227) , var(138) ] D[138,234] = (-1)*var(237); // [ var(234) , var(138) ] D[139,142] = (-1)*var(163); // [ var(142) , var(139) ] D[139,143] = (-1)*var(164); // [ var(143) , var(139) ] D[139,146] = (-1)*var(168); // [ var(146) , var(139) ] D[139,154] = (-1)*var(175); // [ var(154) , var(139) ] D[139,158] = var(177); // [ var(158) , var(139) ] D[139,162] = (-1)*var(182); // [ var(162) , var(139) ] D[139,165] = var(183); // [ var(165) , var(139) ] D[139,166] = var(184); // [ var(166) , var(139) ] D[139,173] = var(190); // [ var(173) , var(139) ] D[139,174] = var(192); // [ var(174) , var(139) ] D[139,180] = var(197); // [ var(180) , var(139) ] D[139,186] = (-1)*var(202); // [ var(186) , var(139) ] D[139,193] = (-1)*var(207); // [ var(193) , var(139) ] D[139,199] = (-1)*var(212); // [ var(199) , var(139) ] D[139,200] = var(213); // [ var(200) , var(139) ] D[139,206] = var(218); // [ var(206) , var(139) ] D[139,211] = var(222); // [ var(211) , var(139) ] D[139,220] = (-1)*var(228); // [ var(220) , var(139) ] D[139,223] = (-1)*var(230); // [ var(223) , var(139) ] D[139,227] = var(234); // [ var(227) , var(139) ] D[139,233] = var(237); // [ var(233) , var(139) ] D[140,143] = (-1)*var(165); // [ var(143) , var(140) ] D[140,145] = (-1)*var(168); // [ var(145) , var(140) ] D[140,150] = (-1)*var(172); // [ var(150) , var(140) ] D[140,161] = var(181); // [ var(161) , var(140) ] D[140,164] = var(183); // [ var(164) , var(140) ] D[140,166] = var(186); // [ var(166) , var(140) ] D[140,170] = var(188); // [ var(170) , var(140) ] D[140,174] = var(193); // [ var(174) , var(140) ] D[140,178] = (-1)*var(196); // [ var(178) , var(140) ] D[140,184] = (-1)*var(202); // [ var(184) , var(140) ] D[140,185] = (-1)*var(203); // [ var(185) , var(140) ] D[140,192] = (-1)*var(207); // [ var(192) , var(140) ] D[140,195] = var(209); // [ var(195) , var(140) ] D[140,201] = var(214); // [ var(201) , var(140) ] D[140,204] = var(216); // [ var(204) , var(140) ] D[140,211] = (-1)*var(223); // [ var(211) , var(140) ] D[140,215] = (-1)*var(226); // [ var(215) , var(140) ] D[140,222] = var(230); // [ var(222) , var(140) ] D[140,224] = var(231); // [ var(224) , var(140) ] D[140,235] = (-1)*var(238); // [ var(235) , var(140) ] D[141,143] = var(166); // [ var(143) , var(141) ] D[141,152] = (-1)*var(175); // [ var(152) , var(141) ] D[141,157] = (-1)*var(179); // [ var(157) , var(141) ] D[141,160] = (-1)*var(181); // [ var(160) , var(141) ] D[141,164] = (-1)*var(184); // [ var(164) , var(141) ] D[141,165] = (-1)*var(186); // [ var(165) , var(141) ] D[141,171] = (-1)*var(191); // [ var(171) , var(141) ] D[141,176] = var(194); // [ var(176) , var(141) ] D[141,180] = var(199); // [ var(180) , var(141) ] D[141,183] = var(202); // [ var(183) , var(141) ] D[141,185] = var(204); // [ var(185) , var(141) ] D[141,189] = var(205); // [ var(189) , var(141) ] D[141,197] = (-1)*var(212); // [ var(197) , var(141) ] D[141,201] = (-1)*var(215); // [ var(201) , var(141) ] D[141,203] = (-1)*var(216); // [ var(203) , var(141) ] D[141,206] = (-1)*var(220); // [ var(206) , var(141) ] D[141,214] = var(226); // [ var(214) , var(141) ] D[141,218] = var(228); // [ var(218) , var(141) ] D[141,221] = var(229); // [ var(221) , var(141) ] D[141,236] = (-1)*var(239); // [ var(236) , var(141) ] D[142,144] = var(167); // [ var(144) , var(142) ] D[142,145] = var(170); // [ var(145) , var(142) ] D[142,150] = var(174); // [ var(150) , var(142) ] D[142,152] = var(176); // [ var(152) , var(142) ] D[142,157] = var(180); // [ var(157) , var(142) ] D[142,164] = var(185); // [ var(164) , var(142) ] D[142,168] = (-1)*var(188); // [ var(168) , var(142) ] D[142,172] = (-1)*var(193); // [ var(172) , var(142) ] D[142,175] = (-1)*var(194); // [ var(175) , var(142) ] D[142,177] = (-1)*var(198); // [ var(177) , var(142) ] D[142,179] = (-1)*var(199); // [ var(179) , var(142) ] D[142,183] = (-1)*var(203); // [ var(183) , var(142) ] D[142,184] = (-1)*var(204); // [ var(184) , var(142) ] D[142,189] = (-1)*var(206); // [ var(189) , var(142) ] D[142,190] = (-1)*var(208); // [ var(190) , var(142) ] D[142,195] = (-1)*var(211); // [ var(195) , var(142) ] D[142,202] = var(216); // [ var(202) , var(142) ] D[142,205] = var(220); // [ var(205) , var(142) ] D[142,209] = var(223); // [ var(209) , var(142) ] D[142,213] = var(225); // [ var(213) , var(142) ] D[142,217] = var(227); // [ var(217) , var(142) ] D[142,237] = (-1)*var(240); // [ var(237) , var(142) ] D[143,147] = var(171); // [ var(147) , var(143) ] D[143,148] = var(173); // [ var(148) , var(143) ] D[143,149] = (-1)*var(174); // [ var(149) , var(143) ] D[143,155] = var(178); // [ var(155) , var(143) ] D[143,156] = var(180); // [ var(156) , var(143) ] D[143,163] = var(185); // [ var(163) , var(143) ] D[143,168] = (-1)*var(189); // [ var(168) , var(143) ] D[143,175] = (-1)*var(195); // [ var(175) , var(143) ] D[143,181] = (-1)*var(200); // [ var(181) , var(143) ] D[143,182] = (-1)*var(201); // [ var(182) , var(143) ] D[143,188] = (-1)*var(206); // [ var(188) , var(143) ] D[143,194] = (-1)*var(211); // [ var(194) , var(143) ] D[143,202] = var(217); // [ var(202) , var(143) ] D[143,207] = var(221); // [ var(207) , var(143) ] D[143,212] = var(224); // [ var(212) , var(143) ] D[143,216] = var(227); // [ var(216) , var(143) ] D[143,226] = (-1)*var(233); // [ var(226) , var(143) ] D[143,228] = (-1)*var(235); // [ var(228) , var(143) ] D[143,230] = var(236); // [ var(230) , var(143) ] D[144,146] = (-1)*var(172); // [ var(146) , var(144) ] D[144,153] = (-1)*var(177); // [ var(153) , var(144) ] D[144,154] = (-1)*var(179); // [ var(154) , var(144) ] D[144,160] = (-1)*var(183); // [ var(160) , var(144) ] D[144,161] = (-1)*var(184); // [ var(161) , var(144) ] D[144,162] = (-1)*var(187); // [ var(162) , var(144) ] D[144,169] = (-1)*var(190); // [ var(169) , var(144) ] D[144,170] = (-1)*var(192); // [ var(170) , var(144) ] D[144,176] = (-1)*var(197); // [ var(176) , var(144) ] D[144,181] = var(202); // [ var(181) , var(144) ] D[144,188] = var(207); // [ var(188) , var(144) ] D[144,194] = var(212); // [ var(194) , var(144) ] D[144,200] = (-1)*var(217); // [ var(200) , var(144) ] D[144,206] = (-1)*var(221); // [ var(206) , var(144) ] D[144,211] = (-1)*var(224); // [ var(211) , var(144) ] D[144,220] = var(229); // [ var(220) , var(144) ] D[144,223] = var(231); // [ var(223) , var(144) ] D[144,225] = var(234); // [ var(225) , var(144) ] D[144,232] = var(237); // [ var(232) , var(144) ] D[145,148] = var(175); // [ var(148) , var(145) ] D[145,151] = (-1)*var(177); // [ var(151) , var(145) ] D[145,156] = var(182); // [ var(156) , var(145) ] D[145,159] = (-1)*var(184); // [ var(159) , var(145) ] D[145,165] = (-1)*var(189); // [ var(165) , var(145) ] D[145,167] = (-1)*var(192); // [ var(167) , var(145) ] D[145,173] = (-1)*var(195); // [ var(173) , var(145) ] D[145,180] = (-1)*var(201); // [ var(180) , var(145) ] D[145,186] = var(205); // [ var(186) , var(145) ] D[145,193] = var(210); // [ var(193) , var(145) ] D[145,196] = var(213); // [ var(196) , var(145) ] D[145,199] = var(215); // [ var(199) , var(145) ] D[145,203] = var(218); // [ var(203) , var(145) ] D[145,208] = var(222); // [ var(208) , var(145) ] D[145,216] = (-1)*var(228); // [ var(216) , var(145) ] D[145,223] = (-1)*var(232); // [ var(223) , var(145) ] D[145,227] = var(235); // [ var(227) , var(145) ] D[145,231] = (-1)*var(237); // [ var(231) , var(145) ] D[146,155] = (-1)*var(181); // [ var(155) , var(146) ] D[146,159] = (-1)*var(186); // [ var(159) , var(146) ] D[146,163] = (-1)*var(188); // [ var(163) , var(146) ] D[146,164] = (-1)*var(189); // [ var(164) , var(146) ] D[146,167] = (-1)*var(193); // [ var(167) , var(146) ] D[146,178] = var(200); // [ var(178) , var(146) ] D[146,184] = var(205); // [ var(184) , var(146) ] D[146,185] = var(206); // [ var(185) , var(146) ] D[146,190] = var(209); // [ var(190) , var(146) ] D[146,192] = var(210); // [ var(192) , var(146) ] D[146,197] = var(214); // [ var(197) , var(146) ] D[146,204] = (-1)*var(220); // [ var(204) , var(146) ] D[146,208] = (-1)*var(223); // [ var(208) , var(146) ] D[146,212] = (-1)*var(226); // [ var(212) , var(146) ] D[146,222] = var(232); // [ var(222) , var(146) ] D[146,224] = var(233); // [ var(224) , var(146) ] D[146,234] = var(238); // [ var(234) , var(146) ] D[147,150] = (-1)*var(177); // [ var(150) , var(147) ] D[147,154] = (-1)*var(181); // [ var(154) , var(147) ] D[147,157] = (-1)*var(183); // [ var(157) , var(147) ] D[147,162] = (-1)*var(188); // [ var(162) , var(147) ] D[147,166] = var(191); // [ var(166) , var(147) ] D[147,173] = var(196); // [ var(173) , var(147) ] D[147,174] = var(198); // [ var(174) , var(147) ] D[147,179] = var(202); // [ var(179) , var(147) ] D[147,180] = var(203); // [ var(180) , var(147) ] D[147,187] = var(207); // [ var(187) , var(147) ] D[147,195] = (-1)*var(213); // [ var(195) , var(147) ] D[147,199] = (-1)*var(216); // [ var(199) , var(147) ] D[147,201] = (-1)*var(218); // [ var(201) , var(147) ] D[147,211] = var(225); // [ var(211) , var(147) ] D[147,215] = var(228); // [ var(215) , var(147) ] D[147,219] = var(230); // [ var(219) , var(147) ] D[147,224] = (-1)*var(234); // [ var(224) , var(147) ] D[147,233] = (-1)*var(238); // [ var(233) , var(147) ] D[148,150] = (-1)*var(179); // [ var(150) , var(148) ] D[148,153] = (-1)*var(181); // [ var(153) , var(148) ] D[148,158] = (-1)*var(186); // [ var(158) , var(148) ] D[148,164] = var(190); // [ var(164) , var(148) ] D[148,170] = var(194); // [ var(170) , var(148) ] D[148,171] = var(196); // [ var(171) , var(148) ] D[148,174] = var(199); // [ var(174) , var(148) ] D[148,177] = var(202); // [ var(177) , var(148) ] D[148,185] = (-1)*var(208); // [ var(185) , var(148) ] D[148,189] = (-1)*var(209); // [ var(189) , var(148) ] D[148,192] = (-1)*var(212); // [ var(192) , var(148) ] D[148,198] = (-1)*var(216); // [ var(198) , var(148) ] D[148,201] = var(219); // [ var(201) , var(148) ] D[148,206] = var(223); // [ var(206) , var(148) ] D[148,210] = var(226); // [ var(210) , var(148) ] D[148,218] = (-1)*var(230); // [ var(218) , var(148) ] D[148,221] = (-1)*var(231); // [ var(221) , var(148) ] D[148,235] = var(239); // [ var(235) , var(148) ] D[149,152] = (-1)*var(182); // [ var(152) , var(149) ] D[149,157] = (-1)*var(187); // [ var(157) , var(149) ] D[149,160] = (-1)*var(188); // [ var(160) , var(149) ] D[149,164] = (-1)*var(192); // [ var(164) , var(149) ] D[149,165] = (-1)*var(193); // [ var(165) , var(149) ] D[149,169] = (-1)*var(194); // [ var(169) , var(149) ] D[149,171] = (-1)*var(198); // [ var(171) , var(149) ] D[149,173] = (-1)*var(199); // [ var(173) , var(149) ] D[149,178] = (-1)*var(204); // [ var(178) , var(149) ] D[149,183] = var(207); // [ var(183) , var(149) ] D[149,189] = var(210); // [ var(189) , var(149) ] D[149,190] = var(212); // [ var(190) , var(149) ] D[149,195] = var(215); // [ var(195) , var(149) ] D[149,196] = var(216); // [ var(196) , var(149) ] D[149,200] = var(220); // [ var(200) , var(149) ] D[149,209] = (-1)*var(226); // [ var(209) , var(149) ] D[149,213] = (-1)*var(228); // [ var(213) , var(149) ] D[149,217] = (-1)*var(229); // [ var(217) , var(149) ] D[149,236] = var(240); // [ var(236) , var(149) ] D[150,155] = var(184); // [ var(155) , var(150) ] D[150,156] = var(187); // [ var(156) , var(150) ] D[150,160] = var(189); // [ var(160) , var(150) ] D[150,163] = var(192); // [ var(163) , var(150) ] D[150,169] = var(195); // [ var(169) , var(150) ] D[150,176] = var(201); // [ var(176) , var(150) ] D[150,181] = (-1)*var(205); // [ var(181) , var(150) ] D[150,188] = (-1)*var(210); // [ var(188) , var(150) ] D[150,194] = (-1)*var(215); // [ var(194) , var(150) ] D[150,196] = (-1)*var(217); // [ var(196) , var(150) ] D[150,203] = (-1)*var(221); // [ var(203) , var(150) ] D[150,208] = (-1)*var(224); // [ var(208) , var(150) ] D[150,216] = var(229); // [ var(216) , var(150) ] D[150,223] = var(233); // [ var(223) , var(150) ] D[150,225] = var(235); // [ var(225) , var(150) ] D[150,230] = (-1)*var(237); // [ var(230) , var(150) ] D[151,152] = var(183); // [ var(152) , var(151) ] D[151,154] = (-1)*var(186); // [ var(154) , var(151) ] D[151,161] = (-1)*var(191); // [ var(161) , var(151) ] D[151,162] = (-1)*var(193); // [ var(162) , var(151) ] D[151,169] = (-1)*var(196); // [ var(169) , var(151) ] D[151,170] = (-1)*var(198); // [ var(170) , var(151) ] D[151,175] = (-1)*var(202); // [ var(175) , var(151) ] D[151,176] = (-1)*var(203); // [ var(176) , var(151) ] D[151,182] = (-1)*var(207); // [ var(182) , var(151) ] D[151,194] = var(216); // [ var(194) , var(151) ] D[151,195] = var(217); // [ var(195) , var(151) ] D[151,201] = var(221); // [ var(201) , var(151) ] D[151,211] = (-1)*var(227); // [ var(211) , var(151) ] D[151,215] = (-1)*var(229); // [ var(215) , var(151) ] D[151,219] = (-1)*var(231); // [ var(219) , var(151) ] D[151,222] = (-1)*var(234); // [ var(222) , var(151) ] D[151,232] = (-1)*var(238); // [ var(232) , var(151) ] D[152,158] = var(189); // [ var(158) , var(152) ] D[152,159] = (-1)*var(190); // [ var(159) , var(152) ] D[152,166] = var(195); // [ var(166) , var(152) ] D[152,167] = (-1)*var(197); // [ var(167) , var(152) ] D[152,174] = var(201); // [ var(174) , var(152) ] D[152,186] = var(209); // [ var(186) , var(152) ] D[152,191] = (-1)*var(213); // [ var(191) , var(152) ] D[152,193] = var(214); // [ var(193) , var(152) ] D[152,198] = (-1)*var(218); // [ var(198) , var(152) ] D[152,199] = var(219); // [ var(199) , var(152) ] D[152,204] = (-1)*var(222); // [ var(204) , var(152) ] D[152,216] = (-1)*var(230); // [ var(216) , var(152) ] D[152,220] = var(232); // [ var(220) , var(152) ] D[152,227] = (-1)*var(236); // [ var(227) , var(152) ] D[152,229] = var(237); // [ var(229) , var(152) ] D[153,156] = var(188); // [ var(156) , var(153) ] D[153,157] = var(189); // [ var(157) , var(153) ] D[153,159] = (-1)*var(191); // [ var(159) , var(153) ] D[153,167] = (-1)*var(198); // [ var(167) , var(153) ] D[153,173] = (-1)*var(200); // [ var(173) , var(153) ] D[153,179] = (-1)*var(205); // [ var(179) , var(153) ] D[153,180] = (-1)*var(206); // [ var(180) , var(153) ] D[153,187] = (-1)*var(210); // [ var(187) , var(153) ] D[153,190] = (-1)*var(213); // [ var(190) , var(153) ] D[153,197] = (-1)*var(218); // [ var(197) , var(153) ] D[153,199] = var(220); // [ var(199) , var(153) ] D[153,208] = var(225); // [ var(208) , var(153) ] D[153,212] = var(228); // [ var(212) , var(153) ] D[153,219] = var(232); // [ var(219) , var(153) ] D[153,224] = (-1)*var(235); // [ var(224) , var(153) ] D[153,231] = var(238); // [ var(231) , var(153) ] D[154,163] = (-1)*var(194); // [ var(163) , var(154) ] D[154,164] = (-1)*var(195); // [ var(164) , var(154) ] D[154,167] = (-1)*var(199); // [ var(167) , var(154) ] D[154,171] = (-1)*var(200); // [ var(171) , var(154) ] D[154,177] = (-1)*var(205); // [ var(177) , var(154) ] D[154,183] = (-1)*var(209); // [ var(183) , var(154) ] D[154,185] = var(211); // [ var(185) , var(154) ] D[154,192] = var(215); // [ var(192) , var(154) ] D[154,197] = var(219); // [ var(197) , var(154) ] D[154,198] = var(220); // [ var(198) , var(154) ] D[154,203] = var(223); // [ var(203) , var(154) ] D[154,207] = var(226); // [ var(207) , var(154) ] D[154,218] = (-1)*var(232); // [ var(218) , var(154) ] D[154,221] = (-1)*var(233); // [ var(221) , var(154) ] D[154,234] = (-1)*var(239); // [ var(234) , var(154) ] D[155,157] = (-1)*var(190); // [ var(157) , var(155) ] D[155,158] = (-1)*var(191); // [ var(158) , var(155) ] D[155,162] = (-1)*var(194); // [ var(162) , var(155) ] D[155,165] = (-1)*var(196); // [ var(165) , var(155) ] D[155,172] = (-1)*var(202); // [ var(172) , var(155) ] D[155,174] = var(204); // [ var(174) , var(155) ] D[155,180] = var(208); // [ var(180) , var(155) ] D[155,187] = var(212); // [ var(187) , var(155) ] D[155,189] = var(213); // [ var(189) , var(155) ] D[155,193] = var(216); // [ var(193) , var(155) ] D[155,201] = (-1)*var(222); // [ var(201) , var(155) ] D[155,206] = (-1)*var(225); // [ var(206) , var(155) ] D[155,210] = (-1)*var(228); // [ var(210) , var(155) ] D[155,214] = (-1)*var(230); // [ var(214) , var(155) ] D[155,221] = var(234); // [ var(221) , var(155) ] D[155,233] = var(239); // [ var(233) , var(155) ] D[156,158] = (-1)*var(193); // [ var(158) , var(156) ] D[156,161] = (-1)*var(194); // [ var(161) , var(156) ] D[156,164] = var(197); // [ var(164) , var(156) ] D[156,166] = (-1)*var(199); // [ var(166) , var(156) ] D[156,171] = var(203); // [ var(171) , var(156) ] D[156,177] = var(207); // [ var(177) , var(156) ] D[156,178] = var(208); // [ var(178) , var(156) ] D[156,184] = var(212); // [ var(184) , var(156) ] D[156,189] = (-1)*var(214); // [ var(189) , var(156) ] D[156,191] = var(216); // [ var(191) , var(156) ] D[156,195] = (-1)*var(219); // [ var(195) , var(156) ] D[156,200] = (-1)*var(223); // [ var(200) , var(156) ] D[156,205] = (-1)*var(226); // [ var(205) , var(156) ] D[156,213] = var(230); // [ var(213) , var(156) ] D[156,217] = var(231); // [ var(217) , var(156) ] D[156,235] = (-1)*var(240); // [ var(235) , var(156) ] D[157,161] = (-1)*var(195); // [ var(161) , var(157) ] D[157,163] = var(197); // [ var(163) , var(157) ] D[157,170] = (-1)*var(201); // [ var(170) , var(157) ] D[157,181] = (-1)*var(209); // [ var(181) , var(157) ] D[157,188] = (-1)*var(214); // [ var(188) , var(157) ] D[157,191] = var(217); // [ var(191) , var(157) ] D[157,194] = (-1)*var(219); // [ var(194) , var(157) ] D[157,198] = var(221); // [ var(198) , var(157) ] D[157,204] = var(224); // [ var(204) , var(157) ] D[157,216] = var(231); // [ var(216) , var(157) ] D[157,220] = (-1)*var(233); // [ var(220) , var(157) ] D[157,225] = (-1)*var(236); // [ var(225) , var(157) ] D[157,228] = var(237); // [ var(228) , var(157) ] D[158,163] = var(198); // [ var(163) , var(158) ] D[158,169] = var(200); // [ var(169) , var(158) ] D[158,175] = var(205); // [ var(175) , var(158) ] D[158,176] = var(206); // [ var(176) , var(158) ] D[158,182] = var(210); // [ var(182) , var(158) ] D[158,190] = var(217); // [ var(190) , var(158) ] D[158,194] = (-1)*var(220); // [ var(194) , var(158) ] D[158,197] = var(221); // [ var(197) , var(158) ] D[158,208] = (-1)*var(227); // [ var(208) , var(158) ] D[158,212] = (-1)*var(229); // [ var(212) , var(158) ] D[158,219] = (-1)*var(233); // [ var(219) , var(158) ] D[158,222] = (-1)*var(235); // [ var(222) , var(158) ] D[158,230] = var(238); // [ var(230) , var(158) ] D[159,160] = var(196); // [ var(160) , var(159) ] D[159,162] = (-1)*var(199); // [ var(162) , var(159) ] D[159,168] = var(202); // [ var(168) , var(159) ] D[159,170] = (-1)*var(204); // [ var(170) , var(159) ] D[159,176] = (-1)*var(208); // [ var(176) , var(159) ] D[159,182] = (-1)*var(212); // [ var(182) , var(159) ] D[159,188] = (-1)*var(216); // [ var(188) , var(159) ] D[159,189] = (-1)*var(217); // [ var(189) , var(159) ] D[159,201] = var(224); // [ var(201) , var(159) ] D[159,206] = var(227); // [ var(206) , var(159) ] D[159,210] = var(229); // [ var(210) , var(159) ] D[159,214] = var(231); // [ var(214) , var(159) ] D[159,218] = var(234); // [ var(218) , var(159) ] D[159,232] = var(239); // [ var(232) , var(159) ] D[160,166] = var(200); // [ var(166) , var(160) ] D[160,167] = (-1)*var(203); // [ var(167) , var(160) ] D[160,174] = var(206); // [ var(174) , var(160) ] D[160,179] = (-1)*var(209); // [ var(179) , var(160) ] D[160,184] = var(213); // [ var(184) , var(160) ] D[160,187] = (-1)*var(214); // [ var(187) , var(160) ] D[160,192] = var(218); // [ var(192) , var(160) ] D[160,199] = var(223); // [ var(199) , var(160) ] D[160,204] = (-1)*var(225); // [ var(204) , var(160) ] D[160,212] = var(230); // [ var(212) , var(160) ] D[160,215] = (-1)*var(232); // [ var(215) , var(160) ] D[160,224] = var(236); // [ var(224) , var(160) ] D[160,229] = (-1)*var(238); // [ var(229) , var(160) ] D[161,165] = var(200); // [ var(165) , var(161) ] D[161,167] = (-1)*var(204); // [ var(167) , var(161) ] D[161,172] = var(205); // [ var(172) , var(161) ] D[161,180] = (-1)*var(211); // [ var(180) , var(161) ] D[161,183] = var(213); // [ var(183) , var(161) ] D[161,187] = (-1)*var(215); // [ var(187) , var(161) ] D[161,193] = (-1)*var(220); // [ var(193) , var(161) ] D[161,197] = (-1)*var(222); // [ var(197) , var(161) ] D[161,203] = (-1)*var(225); // [ var(203) , var(161) ] D[161,207] = (-1)*var(228); // [ var(207) , var(161) ] D[161,214] = (-1)*var(232); // [ var(214) , var(161) ] D[161,221] = var(235); // [ var(221) , var(161) ] D[161,231] = (-1)*var(239); // [ var(231) , var(161) ] D[162,164] = (-1)*var(201); // [ var(164) , var(162) ] D[162,171] = (-1)*var(206); // [ var(171) , var(162) ] D[162,177] = (-1)*var(210); // [ var(177) , var(162) ] D[162,178] = (-1)*var(211); // [ var(178) , var(162) ] D[162,183] = (-1)*var(214); // [ var(183) , var(162) ] D[162,184] = (-1)*var(215); // [ var(184) , var(162) ] D[162,190] = (-1)*var(219); // [ var(190) , var(162) ] D[162,191] = (-1)*var(220); // [ var(191) , var(162) ] D[162,196] = (-1)*var(223); // [ var(196) , var(162) ] D[162,202] = (-1)*var(226); // [ var(202) , var(162) ] D[162,213] = var(232); // [ var(213) , var(162) ] D[162,217] = var(233); // [ var(217) , var(162) ] D[162,234] = var(240); // [ var(234) , var(162) ] D[163,165] = (-1)*var(203); // [ var(165) , var(163) ] D[163,166] = (-1)*var(204); // [ var(166) , var(163) ] D[163,172] = (-1)*var(207); // [ var(172) , var(163) ] D[163,173] = (-1)*var(208); // [ var(173) , var(163) ] D[163,179] = (-1)*var(212); // [ var(179) , var(163) ] D[163,186] = (-1)*var(216); // [ var(186) , var(163) ] D[163,189] = var(218); // [ var(189) , var(163) ] D[163,195] = var(222); // [ var(195) , var(163) ] D[163,200] = var(225); // [ var(200) , var(163) ] D[163,205] = var(228); // [ var(205) , var(163) ] D[163,209] = var(230); // [ var(209) , var(163) ] D[163,217] = (-1)*var(234); // [ var(217) , var(163) ] D[163,233] = (-1)*var(240); // [ var(233) , var(163) ] D[164,181] = var(213); // [ var(181) , var(164) ] D[164,186] = (-1)*var(217); // [ var(186) , var(164) ] D[164,188] = var(218); // [ var(188) , var(164) ] D[164,193] = (-1)*var(221); // [ var(193) , var(164) ] D[164,194] = var(222); // [ var(194) , var(164) ] D[164,199] = (-1)*var(224); // [ var(199) , var(164) ] D[164,216] = (-1)*var(234); // [ var(216) , var(164) ] D[164,220] = var(235); // [ var(220) , var(164) ] D[164,223] = (-1)*var(236); // [ var(223) , var(164) ] D[164,226] = var(237); // [ var(226) , var(164) ] D[165,170] = (-1)*var(206); // [ var(170) , var(165) ] D[165,175] = var(209); // [ var(175) , var(165) ] D[165,182] = var(214); // [ var(182) , var(165) ] D[165,184] = (-1)*var(217); // [ var(184) , var(165) ] D[165,192] = (-1)*var(221); // [ var(192) , var(165) ] D[165,194] = (-1)*var(223); // [ var(194) , var(165) ] D[165,204] = var(227); // [ var(204) , var(165) ] D[165,212] = (-1)*var(231); // [ var(212) , var(165) ] D[165,215] = var(233); // [ var(215) , var(165) ] D[165,222] = var(236); // [ var(222) , var(165) ] D[165,228] = (-1)*var(238); // [ var(228) , var(165) ] D[166,168] = (-1)*var(205); // [ var(168) , var(166) ] D[166,176] = var(211); // [ var(176) , var(166) ] D[166,182] = var(215); // [ var(182) , var(166) ] D[166,183] = (-1)*var(217); // [ var(183) , var(166) ] D[166,188] = var(220); // [ var(188) , var(166) ] D[166,197] = var(224); // [ var(197) , var(166) ] D[166,203] = var(227); // [ var(203) , var(166) ] D[166,207] = var(229); // [ var(207) , var(166) ] D[166,214] = var(233); // [ var(214) , var(166) ] D[166,218] = var(235); // [ var(218) , var(166) ] D[166,230] = (-1)*var(239); // [ var(230) , var(166) ] D[167,168] = var(207); // [ var(168) , var(167) ] D[167,169] = var(208); // [ var(169) , var(167) ] D[167,175] = var(212); // [ var(175) , var(167) ] D[167,181] = var(216); // [ var(181) , var(167) ] D[167,189] = (-1)*var(221); // [ var(189) , var(167) ] D[167,195] = (-1)*var(224); // [ var(195) , var(167) ] D[167,200] = (-1)*var(227); // [ var(200) , var(167) ] D[167,205] = (-1)*var(229); // [ var(205) , var(167) ] D[167,209] = (-1)*var(231); // [ var(209) , var(167) ] D[167,213] = (-1)*var(234); // [ var(213) , var(167) ] D[167,232] = (-1)*var(240); // [ var(232) , var(167) ] D[168,173] = var(209); // [ var(173) , var(168) ] D[168,174] = var(210); // [ var(174) , var(168) ] D[168,178] = (-1)*var(213); // [ var(178) , var(168) ] D[168,180] = var(214); // [ var(180) , var(168) ] D[168,185] = (-1)*var(218); // [ var(185) , var(168) ] D[168,199] = var(226); // [ var(199) , var(168) ] D[168,204] = (-1)*var(228); // [ var(204) , var(168) ] D[168,208] = (-1)*var(230); // [ var(208) , var(168) ] D[168,211] = var(232); // [ var(211) , var(168) ] D[168,224] = (-1)*var(237); // [ var(224) , var(168) ] D[168,227] = var(238); // [ var(227) , var(168) ] D[169,172] = var(209); // [ var(172) , var(169) ] D[169,174] = var(211); // [ var(174) , var(169) ] D[169,177] = (-1)*var(213); // [ var(177) , var(169) ] D[169,187] = (-1)*var(219); // [ var(187) , var(169) ] D[169,192] = var(222); // [ var(192) , var(169) ] D[169,193] = (-1)*var(223); // [ var(193) , var(169) ] D[169,198] = var(225); // [ var(198) , var(169) ] D[169,207] = (-1)*var(230); // [ var(207) , var(169) ] D[169,210] = var(232); // [ var(210) , var(169) ] D[169,221] = (-1)*var(236); // [ var(221) , var(169) ] D[169,229] = var(239); // [ var(229) , var(169) ] D[170,172] = var(210); // [ var(172) , var(170) ] D[170,173] = var(211); // [ var(173) , var(170) ] D[170,179] = var(215); // [ var(179) , var(170) ] D[170,183] = var(218); // [ var(183) , var(170) ] D[170,186] = var(220); // [ var(186) , var(170) ] D[170,190] = var(222); // [ var(190) , var(170) ] D[170,196] = var(225); // [ var(196) , var(170) ] D[170,202] = var(228); // [ var(202) , var(170) ] D[170,209] = var(232); // [ var(209) , var(170) ] D[170,217] = (-1)*var(235); // [ var(217) , var(170) ] D[170,231] = var(240); // [ var(231) , var(170) ] D[171,175] = (-1)*var(213); // [ var(175) , var(171) ] D[171,179] = var(217); // [ var(179) , var(171) ] D[171,182] = (-1)*var(218); // [ var(182) , var(171) ] D[171,187] = var(221); // [ var(187) , var(171) ] D[171,194] = var(225); // [ var(194) , var(171) ] D[171,199] = (-1)*var(227); // [ var(199) , var(171) ] D[171,212] = var(234); // [ var(212) , var(171) ] D[171,215] = (-1)*var(235); // [ var(215) , var(171) ] D[171,219] = var(236); // [ var(219) , var(171) ] D[171,226] = (-1)*var(238); // [ var(226) , var(171) ] D[172,176] = (-1)*var(214); // [ var(176) , var(172) ] D[172,178] = var(217); // [ var(178) , var(172) ] D[172,185] = var(221); // [ var(185) , var(172) ] D[172,194] = (-1)*var(226); // [ var(194) , var(172) ] D[172,204] = var(229); // [ var(204) , var(172) ] D[172,208] = var(231); // [ var(208) , var(172) ] D[172,211] = (-1)*var(233); // [ var(211) , var(172) ] D[172,222] = (-1)*var(237); // [ var(222) , var(172) ] D[172,225] = var(238); // [ var(225) , var(172) ] D[173,177] = var(217); // [ var(177) , var(173) ] D[173,182] = var(219); // [ var(182) , var(173) ] D[173,188] = var(223); // [ var(188) , var(173) ] D[173,192] = (-1)*var(224); // [ var(192) , var(173) ] D[173,198] = (-1)*var(227); // [ var(198) , var(173) ] D[173,207] = var(231); // [ var(207) , var(173) ] D[173,210] = (-1)*var(233); // [ var(210) , var(173) ] D[173,218] = (-1)*var(236); // [ var(218) , var(173) ] D[173,228] = var(239); // [ var(228) , var(173) ] D[174,175] = (-1)*var(215); // [ var(175) , var(174) ] D[174,181] = (-1)*var(220); // [ var(181) , var(174) ] D[174,183] = (-1)*var(221); // [ var(183) , var(174) ] D[174,190] = (-1)*var(224); // [ var(190) , var(174) ] D[174,196] = (-1)*var(227); // [ var(196) , var(174) ] D[174,202] = (-1)*var(229); // [ var(202) , var(174) ] D[174,209] = (-1)*var(233); // [ var(209) , var(174) ] D[174,213] = (-1)*var(235); // [ var(213) , var(174) ] D[174,230] = var(240); // [ var(230) , var(174) ] D[175,180] = var(219); // [ var(180) , var(175) ] D[175,185] = (-1)*var(222); // [ var(185) , var(175) ] D[175,193] = (-1)*var(226); // [ var(193) , var(175) ] D[175,198] = var(228); // [ var(198) , var(175) ] D[175,203] = var(230); // [ var(203) , var(175) ] D[175,206] = (-1)*var(232); // [ var(206) , var(175) ] D[175,221] = var(237); // [ var(221) , var(175) ] D[175,227] = (-1)*var(239); // [ var(227) , var(175) ] D[176,177] = (-1)*var(218); // [ var(177) , var(176) ] D[176,179] = var(219); // [ var(179) , var(176) ] D[176,184] = (-1)*var(222); // [ var(184) , var(176) ] D[176,186] = var(223); // [ var(186) , var(176) ] D[176,191] = (-1)*var(225); // [ var(191) , var(176) ] D[176,202] = var(230); // [ var(202) , var(176) ] D[176,205] = (-1)*var(232); // [ var(205) , var(176) ] D[176,217] = var(236); // [ var(217) , var(176) ] D[176,229] = (-1)*var(240); // [ var(229) , var(176) ] D[177,180] = (-1)*var(221); // [ var(180) , var(177) ] D[177,194] = var(228); // [ var(194) , var(177) ] D[177,199] = (-1)*var(229); // [ var(199) , var(177) ] D[177,208] = (-1)*var(234); // [ var(208) , var(177) ] D[177,211] = var(235); // [ var(211) , var(177) ] D[177,219] = (-1)*var(237); // [ var(219) , var(177) ] D[177,223] = var(238); // [ var(223) , var(177) ] D[178,182] = (-1)*var(222); // [ var(182) , var(178) ] D[178,187] = var(224); // [ var(187) , var(178) ] D[178,188] = (-1)*var(225); // [ var(188) , var(178) ] D[178,193] = var(227); // [ var(193) , var(178) ] D[178,207] = (-1)*var(234); // [ var(207) , var(178) ] D[178,210] = var(235); // [ var(210) , var(178) ] D[178,214] = (-1)*var(236); // [ var(214) , var(178) ] D[178,226] = var(239); // [ var(226) , var(178) ] D[179,185] = var(224); // [ var(185) , var(179) ] D[179,188] = var(226); // [ var(188) , var(179) ] D[179,198] = (-1)*var(229); // [ var(198) , var(179) ] D[179,203] = (-1)*var(231); // [ var(203) , var(179) ] D[179,206] = var(233); // [ var(206) , var(179) ] D[179,218] = var(237); // [ var(218) , var(179) ] D[179,225] = (-1)*var(239); // [ var(225) , var(179) ] D[180,181] = (-1)*var(223); // [ var(181) , var(180) ] D[180,184] = var(224); // [ var(184) , var(180) ] D[180,191] = var(227); // [ var(191) , var(180) ] D[180,202] = (-1)*var(231); // [ var(202) , var(180) ] D[180,205] = var(233); // [ var(205) , var(180) ] D[180,213] = var(236); // [ var(213) , var(180) ] D[180,228] = (-1)*var(240); // [ var(228) , var(180) ] D[181,185] = (-1)*var(225); // [ var(185) , var(181) ] D[181,187] = var(226); // [ var(187) , var(181) ] D[181,192] = (-1)*var(228); // [ var(192) , var(181) ] D[181,197] = (-1)*var(230); // [ var(197) , var(181) ] D[181,201] = var(232); // [ var(201) , var(181) ] D[181,221] = (-1)*var(238); // [ var(221) , var(181) ] D[181,224] = var(239); // [ var(224) , var(181) ] D[182,186] = var(226); // [ var(186) , var(182) ] D[182,191] = (-1)*var(228); // [ var(191) , var(182) ] D[182,196] = (-1)*var(230); // [ var(196) , var(182) ] D[182,200] = var(232); // [ var(200) , var(182) ] D[182,217] = (-1)*var(237); // [ var(217) , var(182) ] D[182,227] = var(240); // [ var(227) , var(182) ] D[183,194] = var(230); // [ var(194) , var(183) ] D[183,199] = (-1)*var(231); // [ var(199) , var(183) ] D[183,204] = var(234); // [ var(204) , var(183) ] D[183,211] = (-1)*var(236); // [ var(211) , var(183) ] D[183,215] = var(237); // [ var(215) , var(183) ] D[183,220] = (-1)*var(238); // [ var(220) , var(183) ] D[184,188] = (-1)*var(228); // [ var(188) , var(184) ] D[184,193] = var(229); // [ var(193) , var(184) ] D[184,203] = var(234); // [ var(203) , var(184) ] D[184,206] = (-1)*var(235); // [ var(206) , var(184) ] D[184,214] = var(237); // [ var(214) , var(184) ] D[184,223] = (-1)*var(239); // [ var(223) , var(184) ] D[185,186] = (-1)*var(227); // [ var(186) , var(185) ] D[185,202] = var(234); // [ var(202) , var(185) ] D[185,205] = (-1)*var(235); // [ var(205) , var(185) ] D[185,209] = var(236); // [ var(209) , var(185) ] D[185,226] = (-1)*var(240); // [ var(226) , var(185) ] D[186,192] = var(229); // [ var(192) , var(186) ] D[186,197] = var(231); // [ var(197) , var(186) ] D[186,201] = (-1)*var(233); // [ var(201) , var(186) ] D[186,218] = (-1)*var(238); // [ var(218) , var(186) ] D[186,222] = var(239); // [ var(222) , var(186) ] D[187,191] = var(229); // [ var(191) , var(187) ] D[187,196] = var(231); // [ var(196) , var(187) ] D[187,200] = (-1)*var(233); // [ var(200) , var(187) ] D[187,213] = (-1)*var(237); // [ var(213) , var(187) ] D[187,225] = var(240); // [ var(225) , var(187) ] D[188,190] = var(230); // [ var(190) , var(188) ] D[188,195] = (-1)*var(232); // [ var(195) , var(188) ] D[188,217] = var(238); // [ var(217) , var(188) ] D[188,224] = (-1)*var(240); // [ var(224) , var(188) ] D[189,194] = (-1)*var(232); // [ var(194) , var(189) ] D[189,199] = var(233); // [ var(199) , var(189) ] D[189,204] = (-1)*var(235); // [ var(204) , var(189) ] D[189,208] = var(236); // [ var(208) , var(189) ] D[189,212] = (-1)*var(237); // [ var(212) , var(189) ] D[189,216] = var(238); // [ var(216) , var(189) ] D[190,193] = var(231); // [ var(193) , var(190) ] D[190,198] = (-1)*var(234); // [ var(198) , var(190) ] D[190,206] = var(236); // [ var(206) , var(190) ] D[190,210] = (-1)*var(237); // [ var(210) , var(190) ] D[190,220] = var(239); // [ var(220) , var(190) ] D[191,197] = (-1)*var(234); // [ var(197) , var(191) ] D[191,201] = var(235); // [ var(201) , var(191) ] D[191,214] = (-1)*var(238); // [ var(214) , var(191) ] D[191,219] = var(239); // [ var(219) , var(191) ] D[192,196] = (-1)*var(234); // [ var(196) , var(192) ] D[192,200] = var(235); // [ var(200) , var(192) ] D[192,209] = (-1)*var(237); // [ var(209) , var(192) ] D[192,223] = var(240); // [ var(223) , var(192) ] D[193,195] = var(233); // [ var(195) , var(193) ] D[193,213] = var(238); // [ var(213) , var(193) ] D[193,222] = (-1)*var(240); // [ var(222) , var(193) ] D[194,217] = (-1)*var(239); // [ var(217) , var(194) ] D[194,221] = var(240); // [ var(221) , var(194) ] D[195,198] = var(235); // [ var(198) , var(195) ] D[195,203] = (-1)*var(236); // [ var(203) , var(195) ] D[195,207] = var(237); // [ var(207) , var(195) ] D[195,216] = (-1)*var(239); // [ var(216) , var(195) ] D[196,201] = (-1)*var(236); // [ var(201) , var(196) ] D[196,210] = var(238); // [ var(210) , var(196) ] D[196,215] = (-1)*var(239); // [ var(215) , var(196) ] D[197,200] = (-1)*var(236); // [ var(200) , var(197) ] D[197,205] = var(237); // [ var(205) , var(197) ] D[197,220] = (-1)*var(240); // [ var(220) , var(197) ] D[198,209] = var(238); // [ var(209) , var(198) ] D[198,219] = (-1)*var(240); // [ var(219) , var(198) ] D[199,213] = (-1)*var(239); // [ var(213) , var(199) ] D[199,218] = var(240); // [ var(218) , var(199) ] D[200,207] = (-1)*var(238); // [ var(207) , var(200) ] D[200,212] = var(239); // [ var(212) , var(200) ] D[201,202] = (-1)*var(237); // [ var(202) , var(201) ] D[201,216] = var(240); // [ var(216) , var(201) ] D[202,206] = (-1)*var(238); // [ var(206) , var(202) ] D[202,211] = var(239); // [ var(211) , var(202) ] D[203,205] = (-1)*var(238); // [ var(205) , var(203) ] D[203,215] = var(240); // [ var(215) , var(203) ] D[204,209] = (-1)*var(239); // [ var(209) , var(204) ] D[204,214] = var(240); // [ var(214) , var(204) ] D[205,208] = (-1)*var(239); // [ var(208) , var(205) ] D[206,212] = (-1)*var(240); // [ var(212) , var(206) ] D[207,211] = (-1)*var(240); // [ var(211) , var(207) ] D[208,210] = (-1)*var(240); // [ var(210) , var(208) ] def @@RR=nc_algebra(1,D); return(@@RR); } example { "EXAMPLE:"; echo = 2; def ncAlgebra = makeUe8(); ncAlgebra; setring ncAlgebra; // ... 7752 noncommutative relations } //////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/ncall.lib000066400000000000000000000021651266270727000177340ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version ncall.lib 4.0.0.0 Jun_2013 "; // $Id: 378f3411e490f1857e026a7d4bf01854b9e16c29 $ category = "Noncommutative"; info=" LIBRARY: ncall.lib Load all noncommutative libraries @format central.lib: Computation of central elements of G- and GR-algebras ncalg.lib: Definitions of important GR-algebras ncdecomp.lib: Central character decomposition of a module nctools.lib: General tools for noncommutative algebras gkdim.lib: Procedures for calculating the Gelfand-Kirillov dimension qmatrix.lib: Quantum matrices, quantum minors and symmetric groups involut.lib: Computations and operations with involutions perron.lib: Computation of algebraic dependences @end format "; // nchomolog.lib: Noncommutative homological algebra /////////////////////////////////////////////////////////////////////////////// LIB "central.lib"; LIB "ncalg.lib"; LIB "ncdecomp.lib"; LIB "nctools.lib"; LIB "gkdim.lib"; LIB "qmatrix.lib"; LIB "involut.lib"; LIB "dmod.lib"; LIB "perron.lib"; //LIB "nchomolog.lib"; singular-4.0.3+ds/Singular/LIB/ncdecomp.lib000066400000000000000000000311511266270727000204300ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version ncdecomp.lib 4.0.0.0 Jun_2013 "; // $Id: cdb78216d4cb2c0f8aa563e5e67052fb5e228be2 $ category="Noncommutative"; info=" LIBRARY: ncdecomp.lib Decomposition of a module into its central characters AUTHORS: Viktor Levandovskyy, levandov@mathematik.uni-kl.de. OVERVIEW: @* This library presents algorithms for the central character decomposition of a module, @* i.e. a decomposition into generalized weight modules with respect to the center. @* Based on ideas of O. Khomenko and V. Levandovskyy (see the article [L2] in the @* References for details). PROCEDURES: CentralQuot(M,G); central quotient M:G, CentralSaturation(M,T); central saturation ((M:T):...):T) ( = M:T^infinity), CenCharDec(I,C); decomposition of I into central characters w.r.t. C IntersectWithSub(M,Z); intersection of M with the subalgebra, generated by pairwise commutative elements of Z. "; LIB "ncalg.lib"; LIB "primdec.lib"; LIB "central.lib"; /////////////////////////////////////////////////////////////////////////////// proc testncdecomplib() { example CentralQuot; example CentralSaturation; example CenCharDec; example IntersectWithSub; } static proc CharKernel(list L, int i) { // todo: think on more effective way of doing it... // compute \cup L[j], j!=i int sL = size(L); if ( (i<=0) || (i>sL)) { return(0); } int j; list Li; if (i ==1 ) { Li = L[2..sL]; } if (i ==sL ) { Li = L[1..sL-1]; } if ( (i>1) && (i < sL)) { Li = L[1..i-1]; for (j=i+1; j<=sL; j++) { Li[j-1] = L[j]; } } // print("intersecting kernels..."); module Cres = intersect(Li[1..size(Li)]); // uses std, try modulo! return(Cres); } /////////////////////////////////////////////////////////////////////////////// static proc CentralQuotPoly(module M, poly g) { // here an elimination of components should be used ! int N=nrows(M); // M = A^N /I_M module @M; int i,j; for(i=1; i<=N; i++) { @M=@M,g*gen(i); } @M = simplify(@M,2); @M = @M,M; module S = syz(@M); matrix s = S; module T; vector t; for(i=1; i<=ncols(s); i++) { t = 0*gen(N); for(j=1; j<=N; j++) { t = t + s[j,i]*gen(j); } T[i] = t; } T = simplify(T,2); return(T); } /////////////////////////////////////////////////////////////////////////////// static proc MyIsEqual(module A, module B) { // both A and B are submodules of free module option(redSB); option(redTail); if (attrib(A,"isSB")!=1) { A = slimgb(A); } if (attrib(B,"isSB")!=1) { B = slimgb(B); } int ANSWER = 1; if ( ( ncols(A) == ncols(B) ) && ( nrows(A) == nrows(B) ) ) { module @AB = module(matrix(A)-matrix(B)); @AB = simplify(@AB,2); if (@AB[1]!=0) { ANSWER = 0; } } else { ANSWER = 0; } return(ANSWER); } /////////////////////////////////////////////////////////////////////////////// proc CentralQuot(module I, ideal G) "USAGE: CentralQuot(M, G), M a module, G an ideal ASSUME: G is an ideal in the center of the base ring RETURN: module PURPOSE: compute the central quotient M:G THEORY: for an ideal G of the center of an algebra and a submodule M of A^n, @* the central quotient of M by G is defined to be @* M:G := { v in A^n | z*v in M, for all z in G }. NOTE: the output module is not necessarily given in a Groebner basis SEE ALSO: CentralSaturation, CenCharDec EXAMPLE: example CentralQuot; shows examples "{ /* check assupmtion. Elt's of G must be central */ if (! inCenter(G) ) { ERROR("ideal in the 2nd argument is not in the center of the base ring!"); } int i; list @L; for(i=1; i<=size(G); i++) { @L[i] = CentralQuotPoly(I,G[i]); } module @I = intersect(@L[1..size(G)]); if (nrows(@I)==1) { @I = ideal(@I); } return(@I); } example { "EXAMPLE:"; echo = 2; option(returnSB); def a = makeUsl2(); setring a; ideal I = e3,f3,h3-4*h; I = std(I); poly C=4*e*f+h^2-2*h; // C in Z(U(sl2)), the central element ideal G = (C-8)*(C-24); // G normal factor in Z(U(sl2)) as an ideal in the center ideal R = CentralQuot(I,G); // same as I:G R; } /////////////////////////////////////////////////////////////////////////////// proc CentralSaturation(module M, ideal T) "USAGE: CentralSaturation(M, T), for a module M and an ideal T ASSUME: T is an ideal in the center of the base ring RETURN: module PURPOSE: compute the central saturation of M by T, that is M:T^{\infty}, by repititive application of @code{CentralQuot} NOTE: the output module is not necessarily a Groebner basis SEE ALSO: CentralQuot, CenCharDec EXAMPLE: example CentralSaturation; shows examples "{ /* check assupmtion. Elt's of T must be central */ if (! inCenter(T) ) { ERROR("ideal in the 2nd argument is not in the center of the base ring!"); } option(redSB); option(redTail); option(returnSB); module Q=0; module S=M; while ( !MyIsEqual(Q,S) ) { Q = CentralQuot(S, T); S = CentralQuot(Q, T); } if (nrows(Q)==1) { Q = ideal(Q); } // Q = std(Q); return(Q); } example { "EXAMPLE:"; echo = 2; option(returnSB); def a = makeUsl2(); setring a; ideal I = e3,f3,h3-4*h; I = std(I); poly C=4*e*f+h^2-2*h; ideal G = C*(C-8); ideal R = CentralSaturation(I,G); R=std(R); vdim(R); R; } /////////////////////////////////////////////////////////////////////////////// proc CenCharDec(module I, def #) "USAGE: CenCharDec(I, C); I a module, C an ideal ASSUME: C consists of generators of the center of the base ring RETURN: a list L, where each entry consists of three records (if a finite decomposition exists) @* L[*][1] ('ideal' type), the central character as a maximal ideal in the center, @* L[*][2] ('module' type), the Groebner basis of the weight module, corresponding to the character in L[*][1], @* L[*][3] ('int' type) is the vector space dimension of the weight module (-1 in case of infinite dimension); PURPOSE: compute a finite decomposition of C into central characters or determine that there is no finite decomposition NOTE: actual decomposition is the sum of L[i][2] above; @* some modules have no finite decomposition (in such case one gets warning message) @* The function @code{central} in @code{central.lib} may be used to obtain C, when needed. SEE ALSO: CentralQuot, CentralSaturation EXAMPLE: example CenCharDec; shows examples " { list Center; if (typeof(#) == "ideal") { int cc; ideal tmp = ideal(#); for (cc=1; cc<=size(tmp); cc++) { Center[cc] = tmp[cc]; } kill tmp; } if (typeof(#) == "list") { Center = #; } /* check assupmtion. Elt's of G must be central */ if (! inCenter(Center) ) { ERROR("ideal in the 2nd argument is not in the center of the base ring!"); } int ppl = printlevel-voice+2; // M = A/I //1. Find the Zariski closure of Supp_Z M // J = Ann_M 1 == I // J \cap Z: option(redSB); option(redTail); option(returnSB); def @A = basering; setring @A; int sZ=size(Center); int i,j; poly t=1; for(i=1; i<=nvars(@A); i++) { t=t*var(i); } ring @Z=0,(@z(1..sZ)),dp; // @Z; def @ZplusA = @A+@Z; setring @ZplusA; // @ZplusA; ideal I = imap(@A,I); list Center = imap(@A,Center); poly t = imap(@A,t); ideal @Ker; for(i=1; i<=sZ; i++) { @Ker[i]=@z(i) - Center[i]; } @Ker = @Ker,I; // ideal @JcapZ = eliminate(@Ker,t); dbprint(ppl,"// -1-1- starting the computation of preimage in Z"); dbprint(ppl-1, @Ker); ideal @JcapZ = slimgb(@Ker); @JcapZ = nselect(@JcapZ,intvec(1..nvars(@A))); dbprint(ppl,"// -1-2- finished the computation of preimage in Z"); dbprint(ppl-1, @JcapZ); // do not forget parameters of a basering! // hmmm: todo ringlist string strZ="ring @@Z=("+charstr(@A)+"),(@z(1.."+string(sZ)+")),dp;"; // print(strZ); execute(strZ); setring @@Z; ideal @JcapZ = imap(@ZplusA,@JcapZ); dbprint(ppl,"// -1-3- starting the cosmetic Groebner basis in Z"); @JcapZ = slimgb(@JcapZ); // evtl. groebner? // @JcapZ; dbprint(ppl,"// -1-4- finished the cosmetic Groebner basis in Z"); dbprint(ppl-1, @JcapZ); int sJ = vdim(@JcapZ); dbprint(ppl,"// -1-5- the K-dimension of support is "+string(sJ)); if (sJ==-1) { "There is no finite decomposition"; return(0); } // print(@JcapZ); // 2. compute the min.ass.primes of the ideal in the center dbprint(ppl,"// -2-1- starting the computation of minimal primes in Z"); list @L = minAssGTZ(@JcapZ); int sL = size(@L); dbprint(ppl,"// -2-2- finished the computation of " + string(sL)+ " minimal primes in Z"); // print("etL:"); // @L; // exception: is sL==1, the whole ideal has unique cen.char if (sL ==1) { dbprint(ppl-1,"// -2-3- the whole module is gen. weight module itself"); setring @A; map @M = @@Z,Center[1..size(Center)]; list L = @M(@L); list @R; @R[1] = L[1]; if (nrows(@R[1])==1) { @R[1] = ideal(@R[1]); } @R[2] = I; if (nrows(@R[2])==1) { @R[2] = ideal(@R[2]); } dbprint(ppl-1,"// -2-4- final cosmetic Groebner basis"); @R[2] = slimgb(@R[2]); @R[3] = vdim(@R[2]); return(list(@R)); // for compliance with output a list } dbprint(ppl-1,"// -2-3- there are several characters"); dbprint(ppl,"// -*- computing Groebner bases of components (commutative)"); list @CharKer; for(i=1; i<=sL; i++) { @L[i] = slimgb(@L[i]); } dbprint(ppl,"// -*- finished computing Groebner bases of components"); // 3. compute the intersections of characters dbprint(ppl,"// -3- compute the intersections of characters"); for(i=1; i<=sL; i++) { @CharKer[i] = CharKernel(@L,i); } dbprint(ppl,"// -3- the intersections of characters is done"); // dbprint(ppl-1,@CharKer); // 4. Go back to the algebra and compute central saturations setring @A; map @M = @@Z,Center[1..size(Center)]; list L = @M(@CharKer); list R,@R; dbprint(ppl,"// -4- compute the central saturations"); dbprint(ppl-1,L); for(i=1; i<=sL; i++) { @R[1] = L[i]; if (nrows(@R[1])==1) { @R[1] = ideal(@R[1]); } @R[2] = CentralSaturation(I,L[i]); if (nrows(@R[2])==1) { @R[2] = ideal(@R[2]); } @R[2] = slimgb(@R[2]); @R[3] = vdim(@R[2]); R[i] = @R; } dbprint(ppl,"// -4- central saturations are done"); return(R); } example { "EXAMPLE:"; echo = 2; printlevel=0; option(returnSB); def a = makeUsl2(); // U(sl_2) in characteristic 0 setring a; ideal I = e3,f3,h3-4*h; I = twostd(I); // two-sided ideal generated by I vdim(I); // it is finite-dimensional ideal Cn = 4*e*f+h^2-2*h; // the only central element list T = CenCharDec(I,Cn); T; // consider another example ideal J = e*f*h; CenCharDec(J,Cn); } /////////////////////////////////////////////////////////////////////////////// proc IntersectWithSub (ideal M, def #) "USAGE: IntersectWithSub(M,Z), M an ideal, Z an ideal ASSUME: Z consists of pairwise commutative elements RETURN: ideal of two-sided generators, not a Groebner basis PURPOSE: computes the intersection of M with the subalgebra, generated by Z NOTE: usually Z consists of generators of the center @* The function @code{central} from @code{central.lib} may be used to obtain the center Z, if needed. EXAMPLE: example IntersectWithSub; shows an example " { ideal Z; if (typeof(#) == "list") { int cc; list tmp = #; for (cc=1; cc<=size(tmp); cc++) { Z[cc] = tmp[cc]; } kill tmp; } if (typeof(#) == "ideal") { Z = #; } // returns a submodule of M, equal to M \cap Z // assume/correctness: Z should consists of pairwise // commutative elements int nz = size(Z); int i,j; poly p; for (i=1; i not equal j++; continue; }//different sizes => not equal is_equal = 1; for (k = 1; k <= size(l[i]);k++) {//Compare every entry if (l[i][k]!=l[j][k]) { is_equal = 0; break; } }//Compare every entry if (is_equal == 1) {//Delete this entry, because there is another equal one int the list result = delete(result, i-deleted); deleted = deleted+1; break; }//Delete this entry, because there is another equal one int the list }//Compare the i'th factorization to the j'th }//Iterate over the different factorizations return(result); }//proc delete_dublicates_noteval //================================================== static proc ncfactor_isWeyl() " INPUT: None OUTPUT: Returns 1 if the basering is a Weyl algebra, 0 otherwise. " {//ncfactor_isWeyl if (nvars(basering) % 2 != 0) {//Ring cannot be a Weyl algebra, as we need an even number of vars return(0); }//Ring cannot be a Weyl algebra, as we need an even number of vars list tempRingList = ringlist(basering); if (size(tempRingList)<=4) {//Given ring is commutative return(0); }//Given ring is commutative matrix C = tempRingList[5]; matrix D = tempRingList[6]; int i; int j; //Checking if C is okay. for (i = 1; i 1) {return(0);} countOnes = 0; for (j = i-1; j>=1; j--) {//Checking whether there is at most one nontrivial entry in each col if (D[j,i] == 1 or D[j,i]==-1) {countOnes++;} }//Checking whether there is at most one nontrivial entry in each col if (countOnes > 1) {return(0);} }//Iterating the diagonal //Now check if all variables are paired up. list the_vars; for (i = 1; i<=nvars(basering); i++) { the_vars[i] = var(i); } int noPairForFirstOne; while(size(the_vars)>0) {//We did not pair up all variables yet noPairForFirstOne = 1; for (i = 2; i<=size(the_vars); i++) {//Compare the commutation relations of the jth variable to the first one if (the_vars[1]*the_vars[i] - the_vars[i]*the_vars[1] == 1 or the_vars[1]*the_vars[i] - the_vars[i]*the_vars[1] == -1) {//Found a counter matching one noPairForFirstOne = 0; the_vars = delete(the_vars,i); the_vars = delete(the_vars,1); break; }//Found a counter matching one }//Compare the commutation relations of the jth variable to the first one if(noPairForFirstOne) {return(0);} }//We did not pair up all variables yet return(1); }//ncfactor_isWeyl //================================================== static proc ncfactor_isQWeyl() " INPUT: None OUTPUT: Returns 1 if the basering is a Weyl algebra, 0 otherwise. " {//ncfactor_isqWeyl if (nvars(basering) % 2 != 0) {//Ring cannot be a Weyl algebra, as we need an even number of vars return(0); }//Ring cannot be a Weyl algebra, as we need an even number of vars /* if (npars(basering)!=nvars(basering) div 2) */ /* {//Ring must have enough parameters */ /* return(0); */ /* }//Ring must have enough parameters */ list tempRingList = ringlist(basering); if (size(tempRingList)<=4) {//Given ring is commutative return(0); }//Given ring is commutative matrix C = tempRingList[5]; matrix D = tempRingList[6]; int i; int j; int k; int validentry; //Checking if C is okay. for (i = 1; i 1) {return(0);} countOnes = 0; for (j = i-1; j>=1; j--) {//Checking whether there is at most one nontrivial entry in each col if (D[j,i] == 1 or D[j,i]==-1) {countOnes++;} }//Checking whether there is at most one nontrivial entry in each col if (countOnes > 1) {return(0);} }//Iterating the diagonal //Now check if all variables are paired up. list the_vars; for (i = 1; i<=nvars(basering); i++) { the_vars[i] = var(i); } int noPairForFirstOne; while(size(the_vars)>0) {//We did not pair up all variables yet noPairForFirstOne = 1; for (i = 2; i<=size(the_vars); i++) {//Compare the commutation relations of the jth variable to the first one for (j = 1; j<=npars(basering);j++) { for (k = 1; k<= npars(basering); k++) { if (the_vars[1]*the_vars[i] - par(k)*the_vars[i]*the_vars[1] == 1 or par(k)*the_vars[1]*the_vars[i] - the_vars[i]*the_vars[1] == -1) {//Found a counter matching one noPairForFirstOne = 0; break; }//Found a counter matching one } if (noPairForFirstOne == 0) { break; } } if(noPairForFirstOne==0) { the_vars = delete(the_vars,i); the_vars = delete(the_vars,1); break; } }//Compare the commutation relations of the jth variable to the first one if(noPairForFirstOne) {return(0);} }//We did not pair up all variables yet return(1); }//ncfactor_isqWeyl //////////////////////////////////////////////////// //================================================== //////////////////////////////////////////////////// static proc ncfactor_isShift() " INPUT: None OUTPUT: Returns 1 if the basering is a Shift algebra, 0 otherwise. " {//ncfactor_isShift if (nvars(basering) % 2 != 0) {//Ring cannot be a Shift algebra, as we need an even number of vars return(0); }//Ring cannot be a Shift algebra, as we need an even number of vars list tempRingList = ringlist(basering); if (size(tempRingList)<=4) {//Given ring is commutative return(0); }//Given ring is commutative matrix C = tempRingList[5]; matrix D = tempRingList[6]; int i; int j; int k; //Checking if C is okay. for (i = 1; i 1) {return(0);} countOperators = 0; for (j = i-1; j>=1; j--) {//Checking whether there is at most one nontrivial entry in each col if (D[j,i]!= 0) {//Nontrivial relation detected isValidNCRelation = 0; for (k =1; k<= nvars(basering); k++) {//checking validity for each ring element if (D[j,i] == var(k) or D[j,i]==-var(k)) {//valid relation isValidNCRelation = 1; break; }//valid relation }//checking validity for each ring element if (!isValidNCRelation) {//We have not a valid nc-relation at hand return(0); }//We have not a valid nc-relation at hand else {//Increase the numbers of operators occurring in that row countOperators++; }//Increase the numbers of operators occurring in that row }//Nontrivial relation detected }//Checking whether there is at most one nontrivial entry in each col if (countOperators > 1) {return(0);} }//Iterating the diagonal //Now check if all variables are paired up. list the_vars; for (i = 1; i<=nvars(basering); i++) { the_vars[i] = var(i); } int noPairForFirstOne; while(size(the_vars)>0) {//We did not pair up all variables yet noPairForFirstOne = 1; for (i = 2; i<=size(the_vars); i++) {//Compare the commutation relations of the jth variable to the first one if (the_vars[1]*the_vars[i] - the_vars[i]*the_vars[1] == the_vars[1] or the_vars[1]*the_vars[i] - the_vars[i]*the_vars[1] == -the_vars[1] or the_vars[1]*the_vars[i] - the_vars[i]*the_vars[1] == the_vars[i] or the_vars[1]*the_vars[i] - the_vars[i]*the_vars[1] == -the_vars[i]) {//Found a counter matching one noPairForFirstOne = 0; the_vars = delete(the_vars,i); the_vars = delete(the_vars,1); break; }//Found a counter matching one }//Compare the commutation relations of the jth variable to the first one if(noPairForFirstOne) {return(0);} }//We did not pair up all variables yet return(1); }//ncfactor_isShift //================================================== static proc isInCommutativeSubRing(poly h) " INPUT: A polynomial h in an arbitrary polynomial ring. OUTPUT: 1, if all variables that appear at least in 1 monomial in h are all commuting, 0 else. " {//isInCommutativeSubRing list tempRingList = ringlist(basering); if (size(tempRingList)<=4) {//In this case, the given ring was commutative return(1); }//In this case, the given ring was commutative list appearing_variables; int i; int j; intvec degreeIntVec; for (i = 1; i<=nvars(basering);i++) {//checking for variables that appear degreeIntVec = 0:nvars(basering); degreeIntVec[i] = 1; if (deg(h, degreeIntVec) >0) {//Variable does appear in h appearing_variables = appearing_variables + list(var(i)); }//Variable does appear in h }//checking for variables that appear for (i = 1; i=size(result[j])) {//result[i] has more entries result = delete(result,j); continue; }//result[i] has more entries else {//result[j] has more entries result = delete(result,i); i--; break; }//result[j] has more entries }//There are two equal results; throw away that one with the smaller size }//comparing with the other elements }//Iterating over all elements in result return(result); }//proc delete_dublicates_eval //==================================================* static proc combinekfinlf(list g, int nof) //nof stands for "number of factors" " given a list of factors g and a desired size nof, this procedure combines the factors, such that we recieve a list of the length nof. INPUT: A list of containing polynomials or any type where the *-operator is existent OUTPUT: All possibilities (without permutation of the given list) to combine the polynomials into nof polynomials given by the user. " {//Procedure combinekfinlf list result; int i; int j; int k; //iteration variables list fc; //fc stands for "factors combined" list temp; //a temporary store for factors def nofgl = size(g); //nofgl stands for "number of factors of the given list" if (nofgl == 0) {//g was the empty list return(result); }//g was the empty list if (nof <= 0) {//The user wants to recieve a negative number or no element as a result return(result); }//The user wants to recieve a negative number or no element as a result if (nofgl == nof) {//There are no factors to combine result = result + list(g); return(result); }//There are no factors to combine if (nof == 1) {//User wants to get just one factor result = result + list(list(product(g))); return(result); }//User wants to get just one factor for (i = nof; i > 1; i--) {//computing the possibilities that have at least one original factor from g for (j = i; j>=1; j--) {//shifting the window of combinable factors to the left //fc below stands for "factors combined" fc = combinekfinlf(list(g[(j)..(j+nofgl - i)]),nof - i + 1); for (k = 1; k<=size(fc); k++) {//iterating over the different solutions of the smaller problem if (j>1) {//There are g_i before the combination if (j+nofgl -i < nofgl) {//There are g_i after the combination temp = list(g[1..(j-1)]) + fc[k] + list(g[(j+nofgl-i+1)..nofgl]); }//There are g_i after the combination else {//There are no g_i after the combination temp = list(g[1..(j-1)]) + fc[k]; }//There are no g_i after the combination }//There are g_i before the combination if (j==1) {//There are no g_i before the combination if (j+ nofgl -i 0) {//set of equal pairs is not empty temp = M[1]; temppos = 1; for (i = 2; i<=size(M); i++) {//finding the minimal element of M if (M[i][1]<=temp[1]) {//a possible candidate that is smaller than temp could have been found if (M[i][1]==temp[1]) {//In this case we must look at the second number if (M[i][2]< temp[2]) {//the candidate is smaller temp = M[i]; temppos = i; }//the candidate is smaller }//In this case we must look at the second number else {//The candidate is definately smaller temp = M[i]; temppos = i; }//The candidate is definately smaller }//a possible candidate that is smaller than temp could have been found }//finding the minimal element of M M = delete(M, temppos); if(temp[1]>1) {//There are factors to combine before the equal factor if (temp[1]0) {//There are factors to combine for (i = 1; i <= size(pre); i++) {//all possible pre's... for (j = 1; j<= size(post); j++) {//...combined with all possible post's candidate= pre[i]+list(f[temp[1]])+post[j]; if (limitcheck(candidate,limits)) { result = result + list(candidate); } }//...combined with all possible post's }//all possible pre's... }//There are factors to combine }//The most common case else {//the last factor is the common one pre = merge_icf(list(f[1..(temp[1]-1)]),list(g[1..(temp[2]-1)]),limits); for (i = 1; i<= size(pre); i++) {//iterating over the possible pre-factors candidate = pre[i]+list(f[temp[1]]); if (limitcheck(candidate,limits)) { result = result + list(candidate); } }//iterating over the possible pre-factors }//the last factor is the common one }//There are factors to combine before the equal factor else {//There are no factors to combine before the equal factor if (temp[1]0) {//we could find other combinations for (i = 1; i<=size(post); i++) { candidate = list(f[temp[1]])+post[i]; if (limitcheck(candidate,limits)) { result = result + list(candidate); } } }//we could find other combinations }//Just a check for security }//There are no factors to combine before the equal factor }//set of equal pairs is not empty for (i = 1; i <= size(result); i++) {//delete those combinations, who have an entry with degree less or equal 0 for (j = 1; j<=size(result[i]);j++) {//Delete entry if there is a zero or an integer as a factor if (deg(result[i][j]) <= 0) {//found one result = delete(result,i); i--; break; }//found one }//Delete entry if there is a zero as factor }//delete those combinations, who have an entry with degree less or equal 0 return(result); }//proc merge_cf //==================================================* //merges two sets of factors static proc mergence(list l1, list l2, intvec limits) " DEPRECATED " {//Procedure mergence list g; list f; int k; int i; int j; list F = list(); list G = list(); list tempEntry; list comb; if (size(l2)<=size(l1)) {//l1 will be our g, l2 our f g = l1; f = l2; }//l1 will be our g, l2 our f else {//l1 will be our f, l2 our g g = l2; f = l1; }//l1 will be our f, l2 our g if (size(f)==1 or size(g)==1) {//One of them just has one entry if (size(f)== 1) {f = list(1) + f;} if (size(g) == 1) {g = list(1) + g;} }//One of them just has one entry //first, we need to add some latent -1's to the list f and to the list g in order //to get really all possibilities of combinations later for (i=1;i<=size(f)-1;i++) {//first iterator for (j=i+1;j<=size(f);j++) {//second iterator tempEntry = f; tempEntry[i] = (-1)*tempEntry[i]; tempEntry[j] = (-1)*tempEntry[j]; F = F + list(tempEntry); }//secont iterator }//first iterator F = F + list(f); //And now same game with g for (i=1;i<=size(g)-1;i++) {//first iterator for (j=i+1;j<=size(g);j++) {//second iterator tempEntry = g; tempEntry[i] = (-1)*tempEntry[i]; tempEntry[j] = (-1)*tempEntry[j]; G = G + list(tempEntry); }//secont iterator }//first iterator G = G + list(g); //Done with that list result; for (i = 1; i<=size(F); i++) {//Iterate over all entries in F for (j = 1;j<=size(G);j++) {//Same with G comb = combinekfinlf(F[i],2,limits); for (k = 1; k<= size(comb);k++) {//for all possibilities of combinations of the factors of f result = result + merge_cf(comb[k],G[j],limits); result = result + merge_icf(comb[k],G[j],limits); result = delete_dublicates_noteval(result); }//for all possibilities of combinations of the factors of f }//Same with G }//Iterate over all entries in F return(result); }//Procedure mergence //================================================== //Checks, whether a list of factors doesn't exceed the given limits static proc limitcheck(list g, intvec limits) " DEPRECATED " {//proc limitcheck int i; if (size(limits)!=3) {//check the input return(0); }//check the input if(size(g)==0) { return(0); } def prod = product(g); intvec iv11 = intvec(1,1); intvec iv10 = intvec(1,0); intvec iv01 = intvec(0,1); def limg = intvec(deg(prod,iv11) ,deg(prod,iv10),deg(prod,iv01)); for (i = 1; i<=size(limg);i++) {//the final check if(limg[i]>limits[i]) { return(0); } }//the final check return(1); }//proc limitcheck //==================================================* //one factorization of a homogeneous polynomial //in the first Weyl Algebra static proc homogfacFirstWeyl(poly h) "USAGE: homogfacFirstWeyl(h); h is a homogeneous polynomial in the first Weyl algebra with respect to the weight vector [-1,1] RETURN: list PURPOSE: Computes a factorization of a homogeneous polynomial h with respect to the weight vector [-1,1] in the first Weyl algebra THEORY: @code{homogfacFirstWeyl} returns a list with a factorization of the given, [-1,1]-homogeneous polynomial. If the degree of the polynomial is k with k positive, the last k entries in the output list are the second variable. If k is positive, the last k entries will be x. The other entries will be irreducible polynomials of degree zero or 1 resp. -1. SEE ALSO: homogfacFirstWeyl_all "{//proc homogfacFirstWeyl int p = printlevel-voice+2;//for dbprint def r = basering; poly hath; int i; int j; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} intvec ivm11 = intvec(-1,1); if (!homogwithorder(h,ivm11)) {//The given polynomial is not homogeneous ERROR("Given polynomial was not [-1,1]-homogeneous"); return(list()); }//The given polynomial is not homogeneous if (h==0) { return(list(0)); } list result; int m = deg(h,ivm11); dbprint(p,dbprintWhitespace +" Splitting the polynomial in A_0 and A_k-Part"); if (m!=0) {//The degree is not zero if (m <0) {//There are more x than y hath = lift(var(1)^(-m),h)[1,1]; for (i = 1; i<=-m; i++) { result = result + list(var(1)); } }//There are more x than y else {//There are more y than x hath = lift(var(2)^m,h)[1,1]; for (i = 1; i<=m;i++) { result = result + list(var(2)); } }//There are more y than x }//The degree is not zero else {//The degree is zero hath = h; }//The degree is zero dbprint(p,dbprintWhitespace+" Done"); //beginning to transform x^i*y^i in theta(theta-1)...(theta-i+1) list mons; dbprint(p,dbprintWhitespace+" Putting the monomials in the A_0-part in a list."); for(i = 1; i<=size(hath);i++) {//Putting the monomials in a list mons = mons+list(hath[i]); }//Putting the monomials in a list dbprint(p,dbprintWhitespace+" Done"); dbprint(p,dbprintWhitespace+" Mapping this monomials to K[theta]"); ring tempRing = 0,(x,y,theta),dp; setring tempRing; map thetamap = r,x,y; list mons = thetamap(mons); poly entry; for (i = 1; i<=size(mons);i++) {//transforming the monomials as monomials in theta entry = leadcoef(mons[i]); for (j = 0; j1;j--) {//drip x resp. y if (leftpart[j-1]==shiftvar) {//commutative j--; continue; }//commutative if (deg(leftpart[j-1],intvec(-1,1,0))!=0) {//stop here break; }//stop here //Here, we can only have a a0- part leftpart[j] = subst(leftpart[j-1],theta, theta + shift_sign); leftpart[j-1] = shiftvar; lparts = lparts + list(leftpart); }//drip x resp. y //and now deal with the right part if (rightpart[1] == x) { shift_sign = 1; shiftvar = x; } else { shift_sign = -1; shiftvar = y; } for (j = 1 ; j < size(rightpart); j++) { if (rightpart[j+1] == shiftvar) { j++; continue; } if (deg(rightpart[j+1],intvec(-1,1,0))!=0) { break; } rightpart[j] = subst(rightpart[j+1], theta, theta - shift_sign); rightpart[j+1] = shiftvar; rparts = rparts + list(rightpart); } //And now, we put all possibilities together tempadd = list(); for (j = 1; j<=size(lparts); j++) { for (k = 1; k<=size(rparts);k++) { tempadd = tempadd + list(lparts[j]+rparts[k]); } } tempadd = delete(tempadd,1); // The first entry is already in the list result = result + tempadd; continue; //We can may be not be done already with the ith entry }//One entry was theta resp. theta +1 }//checking every entry of result for theta or theta +1 dbprint(p,dbprintWhitespace +" Done"); //map back to the basering dbprint(p,dbprintWhitespace +" Mapping back everything to the basering"); setring(r); map finalmap = tempRing, var(1), var(2),var(1)*var(2); list result = finalmap(result); for (i=1; i<=size(result);i++) {//adding the K factor result[i] = k_factor + result[i]; }//adding the k-factor dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace +" Delete double entries in the list."); result = delete_dublicates_noteval(result); dbprint(p,dbprintWhitespace +" Done"); return(result); }//proc HomogfacFirstWeylAll /* example */ /* { */ /* "EXAMPLE:";echo=2; */ /* ring R = 0,(x,y),Ws(-1,1); */ /* def r = nc_algebra(1,1); */ /* setring(r); */ /* poly h = (x^2*y^2+1)*(x^4); */ /* homogfacFirstWeyl_all(h); */ /* } */ static proc homogfacNthWeyl_all(poly h) "USAGE: homogfacNthWeyl_all(h); h is a homogeneous polynomial in the nth Weyl algebra with respect to the ZZ-grading on the nth Weyl algebra. RETURN: list PURPOSE: Computes all factorizations of a homogeneous polynomial h with respect to the ZZ-grading on the nth Weyl algebra THEORY: @code{homogfacFirstWeyl} returns a list with all factorization of the given, homogeneous polynomial. It uses the output of homogfacNthWeyl and permutes its entries with respect to the commutation rule. Furthermore, if a factor of degree zero is irreducible in K[theta_1, ..., theta_n], but reducible in the nth Weyl algebra, the permutations of this element with the other entries will also be computed. SEE ALSO: homogfacFirstWeyl "{//proc HomogfacNthWeylAll int p=printlevel-voice+2;//for dbprint intvec iv11= 1:nvars(basering); if (deg(h,iv11) <= 0 ) {//h is a constant dbprint(p,"Given polynomial was not homogeneous"); return(list(list(h))); }//h is a constant def r = basering; list one_hom_fac; //stands for one homogeneous factorization int i; int j; int k; int l; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} dbprint(p,dbprintWhitespace +" Calculate one homogeneous factorization using homogfacNthWeyl"); //Compute again a homogeneous factorization one_hom_fac = homogfacNthWeyl(h); dbprint(p,dbprintWhitespace +"Successful"); if (size(one_hom_fac) == 0) {//there is no homogeneous factorization or the polynomial was not homogeneous return(list()); }//there is no homogeneous factorization or the polynomial was not homogeneous //divide list in A0-Part and a list of x_i's resp. y_i's list list_not_azero = list(); list list_azero; list k_factor; int is_list_not_azero_empty = 1; int is_list_azero_empty = 1; k_factor = list(number(one_hom_fac[1])); dbprint(p, dbprintWhitespace + "Determine whether there is an A0 part or not."); int absValueOfDegree = 0; intvec degVecH = degreeOfNthWeylPoly(h); intvec lExp; for (i = 1; i<=size(degVecH); i++) {//adding up the absolute values of the degrees of the respective variables absValueOfDegree = absValueOfDegree + absValue(degVecH[i]); }//adding up the absolute values of the degrees of the respective variables if (absValueOfDegree < size(one_hom_fac) - 1) {//There is a nontrivial A0 part list_azero = one_hom_fac[2..(size(one_hom_fac)-absValueOfDegree)]; is_list_azero_empty = 0; }//There is a nontrivial A0 part dbprint(p,dbprintWhitespace +" Combine x_i,d_i to x_id_i in the factorization again."); dbprint(p,dbprintWhitespace + " The corresponding list of A0 factors is: " + string(list_azero)); for (i = 1; i1;j--) {//drip x resp. y if (leftpart[j-1]==shiftvar) {//commutative j--; continue; }//commutative if (leadexp(leftpart[j-1])[thetaIndex + nvars(r) div 2] - leadexp(leftpart[j-1])[thetaIndex]!=0) {//stop here break; }//stop here //Here, we can only have a a0- part leftpart[j] = subst(leftpart[j-1],theta(thetaIndex), theta(thetaIndex) + shift_sign); leftpart[j-1] = shiftvar; lparts = lparts + list(leftpart); }//drip x resp. y //and now deal with the right part if (rightpart[1] == x(thetaIndex)) { shift_sign = 1; shiftvar = x(thetaIndex); } else { shift_sign = -1; shiftvar = y(thetaIndex); } for (j = 1 ; j < size(rightpart); j++) { if (rightpart[j+1] == shiftvar) { j++; continue; } if (leadexp(rightpart[j+1])[thetaIndex + nvars(r) div 2] - leadexp(rightpart[j+1])[thetaIndex]!=0) { break; } rightpart[j] = subst(rightpart[j+1], theta(thetaIndex), theta(thetaIndex) - shift_sign); rightpart[j+1] = shiftvar; rparts = rparts + list(rightpart); } //And now, we put all possibilities together tempadd = list(); for (j = 1; j<=size(lparts); j++) { for (k = 1; k<=size(rparts);k++) { tempadd = tempadd + list(lparts[j]+rparts[k]); } } tempadd = delete(tempadd,1); // The first entry is already in the list result = result + tempadd; continue; //We can may be not be done already with the ith entry }//One entry was theta resp. theta +1 }//checking every entry of result for theta or theta +1 dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace + "The new result list is:"); dbprint(result); setring(r); ideal finalMapList; for(i = 1; i<=nvars(r);i++) { finalMapList[i] = var(i); } for (i = 1; i<=nvars(r) div 2; i++) { finalMapList[i + nvars(r)] = var(i)*var(i + (nvars(r) div 2)); } map finalmap = tempRing,finalMapList; list result = finalmap(result); for (i=1; i<=size(result);i++) {//adding the K factor result[i] = k_factor + result[i]; }//adding the k-factor dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace +" Delete double entries in the list."); result = delete_dublicates_noteval(result); dbprint(p,dbprintWhitespace +" Done"); return(result); }//proc HomogfacNthWeylAll /* Interesting Test-Polys: ring R = 0,(x1,x2,x3,d1,d2,d3),dp; matrix C[6][6] = 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; matrix D[6][6] = 0,0,0,1,0,0, 0,0,0,0,1,0, 0,0,0,0,0,1, -1,0,0,0,0,0, 0,-1,0,0,0,0, 0,0,-1,0,0,0; def r = nc_algebra(C,D); setring(r); poly h =x1*x2^2*x3^3*d1*d2^2+x2*x3^3*d2; h = (x1*x2^2*x3 + d1^2*d2*d3^3*x1^3*x2^3*x3^4)*(x1*d1 + x2*d2 + x3*d3); h = x1^2*d1+x1*x2*d2; */ //==================================================* //Computes all permutations of a given list static proc perm(list l) " DEPRECATED " {//proc perm int i; int j; list tempresult; list result; if (size(l)==0) { return(list()); } if (size(l)==1) { return(list(l)); } for (i = 1; i<=size(l); i++ ) { tempresult = perm(delete(l,i)); for (j = 1; j<=size(tempresult);j++) { tempresult[j] = list(l[i])+tempresult[j]; } result = result+tempresult; } return(result); }//proc perm //================================================== //computes all permutations of a given list by //ignoring equal entries (faster than perm) static proc permpp(list l) " INPUT: A list with entries of a type, where the ==-operator is defined OUTPUT: A list with all permutations of this given list. " {//proc permpp int i; int j; list tempresult; list l_without_double; list l_without_double_pos; int double_entry; list result; if (size(l)==0) { return(list()); } if (size(l)==1) { return(list(l)); } for (i = 1; i<=size(l);i++) {//Filling the list with unique entries double_entry = 0; for (j = 1; j<=size(l_without_double);j++) { if (l_without_double[j] == l[i]) { double_entry = 1; break; } } if (!double_entry) { l_without_double = l_without_double + list(l[i]); l_without_double_pos = l_without_double_pos + list(i); } }//Filling the list with unique entries for (i = 1; i<=size(l_without_double); i++ ) { tempresult = permpp(delete(l,l_without_double_pos[i])); for (j = 1; j<=size(tempresult);j++) { tempresult[j] = list(l_without_double[i])+tempresult[j]; } result = result+tempresult; } return(result); }//proc permpp //================================================== static proc checkIfProperNthWeyl() " INPUT: None OUTPUT: Checks whether the given basering is a proper Weyl algebra. Proper means in the sense of our algorithms, i.e. fulfilling the assumption that o ur basering is the Nth Weyl algebra and that the xs are the first n variables, the differential operators are the last n. Returns 1 if proper, 0 otherwise. " {//checkIfProperNthWeyl if (!ncfactor_isWeyl()) {return(0);} int i; for (i = 1; i<=nvars(basering) div 2; i++) { if (var(i + nvars(basering) div 2)*var(i) - var(i)*var(i+nvars(basering) div 2)!=1) { return(0); } } return(1); }//checkIfProperNthWeyl //================================================== static proc checkIfProperNthQWeyl() " INPUT: None OUTPUT: Checks whether the given basering is a proper q-Weyl algebra. Proper means in the sense of our algorithms, i.e. fulfilling the assumption that o ur basering is the Nth Weyl algebra and that the xs are the first n variables, the differential operators are the last n. Returns 1 if proper, 0 otherwise. " {//checkIfProperNthQWeyl if (!ncfactor_isQWeyl()) {return(0);} int i; for (i = 1; i<=nvars(basering) div 2; i++) { if (var(i + nvars(basering) div 2)*var(i) - par(i)*var(i)*var(i+nvars(basering) div 2)!=1) { return(0); } } return(1); }//checkIfProperNthQWeyl //================================================== static proc checkIfProperNthShift() " INPUT: None OUTPUT: Checks whether the given basering is a proper shift algebra. Proper means in the sense of our algorithms, i.e. fulfilling the assumption that our basering is the Nth shift algebra and that the xs are the first n variables, the shift operators are the last n. Returns 1 if proper, 0 otherwise. " {//checkIfProperNthShift if (!ncfactor_isShift()) {return(0);} int i; for (i = 1; i<=nvars(basering) div 2; i++) { if (var(i + nvars(basering) div 2)*var(i) - var(i)*var(i+nvars(basering) div 2)!=var(i+nvars(basering) div 2)) { return(0); } } return(1); }//checkIfProperNthShift //================================================== proc facWeyl(poly h) "USAGE: facWeyl(h); h a polynomial in the nth Weyl algebra RETURN: list PURPOSE: compute all factorizations of a polynomial in the first Weyl algebra THEORY: Implements the new algorithm by A. Heinle and V. Levandovskyy, see the thesis of A. Heinle ASSUME: basering is the nth Weyl algebra, where n in NN. NOTE: Every entry of the output list is a list with factors for one possible factorization. The first factor is always a constant (1, if no nontrivial constant could be excluded). EXAMPLE: example facFirstWeyl; shows examples SEE ALSO: facSubWeyl, testNCfac, facFirstShift, facFirstWeyl "{//proc facWeyl //Definition of printlevel variable int p = printlevel-voice+2; int i; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} dbprint(p,dbprintWhitespace +" Checking if the given algebra is a Weyl algebra"); //Redefine the ring in my standard form if (!ncfactor_isWeyl()) {//Our basering is not the Weyl algebra ERROR("Ring was not a Weyl algebra"); return(list()); }//Our basering is not the Weyl algebra dbprint(p,dbprintWhitespace +" Successful"); //A last check before we start the real business: Is h maybe just //dependable on commutative variables? if (isInCommutativeSubRing(h)) {//h is in a commutative subring list hdepvars; intvec tempIntVec; for (i = 1; i<=nvars(basering) ; i++) { tempIntVec = 0:nvars(basering); tempIntVec[i] = 1; if (deg(h,tempIntVec)>0) { hdepvars = hdepvars + list(var(i)); } } if (size(hdepvars) ==0) {//We just have a constant return(list(list(h))); }//We just have a constant dbprint(p,dbprintWhitespace+"Polynomial was given commutative subring. Performing commutative factorization."); def r = basering; def rList = ringlist(basering); rList = delete(rList,5); rList = delete(rList,5); def tempRing = ring(rList); setring(tempRing); poly h = imap(r,h); list tempResult = factorize(h); list result = list(list()); int j; for (i = 1; i<=size(tempResult[1]); i++) { for (j = 1; j<=tempResult[2][i]; j++) { result[1] = result[1] + list(tempResult[1][i]); } } //mapping back setring(r); def result = imap(tempRing,result); dbprint(p,dbprintWhitespace+"result:"); dbprint(p,result); dbprint(p,dbprintWhitespace+"Computing all permutations of this factorization"); poly constantFactor = result[1][1]; result[1] = delete(result[1],1);//Deleting the constant factor result=permpp(result[1]); for (i = 1; i<=size(result);i++) {//Insert constant factor result[i] = insert(result[i],constantFactor); }//Insert constant factor dbprint(p,dbprintWhitespace+"Done."); return(result); }//h is in a commutative subring dbprint(p,dbprintWhitespace +" Successful"); list result = list(); int j; int k; int l; //counter if (!checkIfProperNthWeyl()) {//The given ring was not a proper nth Weyl algebra dbprint(p,dbprintWhitespace +" positions of the variables have to be switched"); dbprint(p,dbprintWhitespace + "Constructing the the proper ring."); def r = basering; list tempRingList = ringlist(r); tempRingList = delete(tempRingList,6); list the_vars; for (i = 1; i<=nvars(r); i++) {the_vars[i] = var(i);} int maybeDInWrongPos; poly tempVariable; for (i = 1; i<=size(the_vars) div 2; i++) {//Swapping the variables as needed maybeDInWrongPos = 1; if (the_vars[i + size(the_vars) div 2]*the_vars[i] -the_vars[i]*the_vars[i + size(the_vars) div 2] == 1) { i++; continue; } //If we enter this line, there is a break with our property //condition for (j = i+1; j<=size(the_vars); j++) { if (the_vars[j]*the_vars[i]-the_vars[i]*the_vars[j]==1) {//In this case, we matched a var x to a repective d tempVariable = the_vars[i + size(the_vars) div 2]; the_vars[i + size(the_vars) div 2] = the_vars[j]; the_vars[j] = tempVariable; maybeDInWrongPos = 0; break; }//In this case, we matched a var x to a repective d } if (maybeDInWrongPos) {//var(i) is actually a d, not an x print("i has to be pushed to the end."); tempVariable = the_vars[i]; the_vars = delete(the_vars, i); the_vars = the_vars + list(tempVariable); continue; }//var(i) is actually a d, not an x }//Swapping the variables as needed for (i = 1; i<=size(the_vars); i++) {tempRingList[2][i] = string(the_vars[i]);} matrix DTemp[nvars(r)][nvars(r)]; for (i = 1; i<=ncols(DTemp) div 2; i++) { DTemp[i,i + nvars(r) div 2] = 1; } tempRingList = tempRingList + list(DTemp); def tempRing = ring(tempRingList); dbprint(p,dbprintWhitespace + "Done. The altered ring is the following:"); dbprint(p,tempRing); setring(tempRing); poly h = imap(r,h); dbprint(p,dbprintWhitespace +" Successful"); list resulttemp = facWeyl(h); setring(r); result = imap(tempRing,resulttemp); return (result); }//The given ring was not a proper nth Weyl algebra dbprint(p, dbprintWhitespace +" factorization of the polynomial with the routine sfacwaNthWeyl"); result = sfacwaNthWeyl(h); dbprint(p,dbprintWhitespace +" Done"); if (homogwithorderNthWeyl(h)) { dbprint(p, dbprintWhitespace + " Polynomial was homogeneous, therefore we have already a complete factorization and do not have to go through the factors recursively."); return(result); } result = normalizeFactors(result); result = delete_dublicates_noteval(result); dbprint(p,dbprintWhitespace + "We have the following intermediate list of inhomogeneous factorizations:"); dbprint(p,result); dbprint(p,dbprintWhitespace +" recursively check factors for irreducibility"); list recursivetemp; int changedSomething; for(i = 1; i<=size(result);i++) {//recursively factorize factors if(size(result[i])>2) {//Nontrivial factorization for (j=2;j<=size(result[i]);j++) {//Factorize every factor recursivetemp = facWeyl(result[i][j]); //if(size(recursivetemp)>1) //{//we have a nontrivial factorization changedSomething = 0; for(k=1; k<=size(recursivetemp);k++) {//insert factorized factors if(size(recursivetemp[k])>2) {//nontrivial changedSomething = 1; result = insert(result,result[i],i); for(l = size(recursivetemp[k]);l>=2;l--) { result[i+1] = insert(result[i+1],recursivetemp[k][l],j); } result[i+1] = delete(result[i+1],j); }//nontrivial }//insert factorized factors if (changedSomething) { result = delete(result,i); } //}//we have a nontrivial factorization }//Factorize every factor }//Nontrivial factorization }//recursively factorize factors dbprint(p,dbprintWhitespace +" Done"); if (size(result)==0) {//only the trivial factorization could be found result = list(list(1,h)); }//only the trivial factorization could be found list resultWithInterchanges; dbprint(p,dbprintWhitespace+ "And the result without interchanges with homogeneous factors is:"); dbprint(p,result); for (i = 1; i <= size(result) ; i++) {//applying the interchanges to result resultWithInterchanges = resultWithInterchanges + checkForHomogInhomogInterchangabilityNthWeyl(result[i], 2, size(result[i])); }//applying the interchanges to result dbprint(p,dbprintWhitespace + "With interchanges, the result is:"); dbprint(p,resultWithInterchanges); //now, refine the possible redundant list return( delete_dublicates_noteval(resultWithInterchanges) ); }//proc facWeyl example { "EXAMPLE:";echo=2; ring R = 0,(x1,x2,d1,d2),dp; matrix C[4][4] = 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1; matrix D[4][4] = 0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0; def r = nc_algebra(C,D); setring(r); poly h = (d1+1)^2*(d1 + x1*d2); facWeyl(h); } //================================================== static proc normalizeFactors(list factList) "INPUT: A list of factorizations, as outputted e.g. by facWeyl OUTPUT: If any entry in a factorization is not primitive, this function divides the common divisor out and multiplies the first entry with it. " {//normalizeFactors int i; int j; list result = factList; for (i = 1; i<=size(result); i++) {//iterating through every different factorization for (j=2; j<=size(result[i]); j++) {//Iterating through all respective factors if (content(result[i][j])!=number(1)) {//Got one where the content is not equal to 1 result[i][1] = result[i][1] * content(result[i][j]); result[i][j] = result[i][j] / content(result[i][j]); }//Got one where the content is not equal to 1 }//Iterating through all respective factors }//iterating through every different factorization return(result); }//normalizeFactors //================================================== //factorization of the first Weyl Algebra //The following procedure just serves the purpose to //transform the input into an appropriate input for //the procedure sfacwa, where the ring must contain the //variables in a certain order. static proc facFirstWeyl_old(poly h) "USAGE: facFirstWeyl(h); h a polynomial in the first Weyl algebra RETURN: list PURPOSE: compute all factorizations of a polynomial in the first Weyl algebra THEORY: Implements the new algorithm by A. Heinle and V. Levandovskyy, see the thesis of A. Heinle ASSUME: basering is the first Weyl algebra NOTE: Every entry of the output list is a list with factors for one possible factorization. The first factor is always a constant (1, if no nontrivial constant could be excluded). EXAMPLE: example facFirstWeyl; shows examples SEE ALSO: facSubWeyl, testNCfac, facFirstShift "{//proc facFirstWeyl_old //Definition of printlevel variable int p = printlevel-voice+2; int i; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} dbprint(p,dbprintWhitespace +" Checking if the given algebra is a Weyl algebra"); //Redefine the ring in my standard form if (!isWeyl()) {//Our basering is not the Weyl algebra ERROR("Ring was not the first Weyl algebra"); return(list()); }//Our basering is not the Weyl algebra dbprint(p,dbprintWhitespace +" Successful"); dbprint(p,dbprintWhitespace +" Checking, if the given ring is the first Weyl algebra"); if(nvars(basering)!=2) {//Our basering is the Weyl algebra, but not the first ERROR("Ring is not the first Weyl algebra"); return(list()); }//Our basering is the Weyl algebra, but not the first //A last check before we start the real business: Is h already given as a polynomial just //in one variable? if (deg(h,intvec(1,0))== 0 or deg(h,intvec(0,1)) == 0) {//h is in K[x] or in K[d] if (deg(h,intvec(1,0))== 0 and deg(h,intvec(0,1)) == 0) {//We just have a constant return(list(list(h))); }//We just have a constant dbprint(p,dbprintWhitespace+"Polynomial was given in one variable. Performing commutative factorization."); int theCommVar; if (deg(h,intvec(1,0)) == 0) {//The second variable is the variable to factorize theCommVar = 2; }//The second variable is the variable to factorize else{theCommVar = 1;} def r = basering; ring tempRing = 0,(var(theCommVar)),dp; if (theCommVar == 1){map mapToCommutative = r,var(1),1;} else {map mapToCommutative = r,1,var(1);} poly h = mapToCommutative(h); list tempResult = factorize(h); list result = list(list()); int j; for (i = 1; i<=size(tempResult[1]); i++) { for (j = 1; j<=tempResult[2][i]; j++) { result[1] = result[1] + list(tempResult[1][i]); } } //mapping back setring(r); map mapBackFromCommutative = tempRing,var(theCommVar); def result = mapBackFromCommutative(result); dbprint(p,dbprintWhitespace+"result:"); dbprint(p,result); dbprint(p,dbprintWhitespace+"Computing all permutations of this factorization"); poly constantFactor = result[1][1]; result[1] = delete(result[1],1);//Deleting the constant factor result=permpp(result[1]); for (i = 1; i<=size(result);i++) {//Insert constant factor result[i] = insert(result[i],constantFactor); }//Insert constant factor dbprint(p,dbprintWhitespace+"Done."); return(result); }//h is in K[x] or in K[d] dbprint(p,dbprintWhitespace +" Successful"); list result = list(); int j; int k; int l; //counter if (ringlist(basering)[6][1,2] == -1) //manual of ringlist will tell you why { dbprint(p,dbprintWhitespace +" positions of the variables have to be switched"); def r = basering; ring tempRing = ringlist(r)[1][1],(x,y),Ws(-1,1); // very strange: // setting Wp(-1,1) leads to SegFault; to clarify why!!! def NTR = nc_algebra(1,1); setring NTR ; map transf = r, var(2), var(1); dbprint(p,dbprintWhitespace +" Successful"); list resulttemp = sfacwa(h); setring(r); map transfback = NTR, var(2),var(1); result = transfback(resulttemp); } else { dbprint(p, dbprintWhitespace +" factorization of the polynomial with the routine sfacwa"); result = sfacwa(h); dbprint(p,dbprintWhitespace +" Done"); } if (homogwithorder(h,intvec(-1,1))) { dbprint(p, dbprintWhitespace + " Polynomial was homogeneous, therefore we have already a complete factorization and do not have to go through the factors recursively."); return(result); } result = normalizeFactors(result); result = delete_dublicates_noteval(result); dbprint(p,dbprintWhitespace + "We have the following intermediate list of inhomogeneous factorizations:"); dbprint(p,result); dbprint(p,dbprintWhitespace +" recursively check factors for irreducibility"); list recursivetemp; int changedSomething; for(i = 1; i<=size(result);i++) {//recursively factorize factors if(size(result[i])>2) {//Nontrivial factorization for (j=2;j<=size(result[i]);j++) {//Factorize every factor recursivetemp = facFirstWeyl(result[i][j]); //if(size(recursivetemp)>1) //{//we have a nontrivial factorization changedSomething = 0; for(k=1; k<=size(recursivetemp);k++) {//insert factorized factors if(size(recursivetemp[k])>2) {//nontrivial changedSomething = 1; result = insert(result,result[i],i); for(l = size(recursivetemp[k]);l>=2;l--) { result[i+1] = insert(result[i+1],recursivetemp[k][l],j); } result[i+1] = delete(result[i+1],j); }//nontrivial }//insert factorized factors if (changedSomething) { result = delete(result,i); } //}//we have a nontrivial factorization }//Factorize every factor }//Nontrivial factorization }//recursively factorize factors dbprint(p,dbprintWhitespace +" Done"); if (size(result)==0) {//only the trivial factorization could be found result = list(list(1,h)); }//only the trivial factorization could be found list resultWithInterchanges; dbprint(p,dbprintWhitespace+ "And the result without interchanges with homogeneous factors is:"); dbprint(p,result); for (i = 1; i <= size(result) ; i++) {//applying the interchanges to result resultWithInterchanges = resultWithInterchanges + checkForHomogInhomogInterchangability(result[i],2,size(result[i])); }//applying the interchanges to result dbprint(p,dbprintWhitespace + "With interchanges, the result is:"); dbprint(p,resultWithInterchanges); //now, refine the possible redundant list return( delete_dublicates_noteval(resultWithInterchanges) ); }//proc facFirstWeyl_old proc facFirstWeyl(poly h) "USAGE: facFirstWeyl(h); h a polynomial in the first Weyl algebra RETURN: list PURPOSE: compute all factorizations of a polynomial in the first Weyl algebra THEORY: This function is a wrapper for facWeyl. It exists to make this library downward-compatible with older versions. ASSUME: basering is the first Weyl algebra NOTE: Every entry of the output list is a list with factors for one possible factorization. The first factor is always a constant (1, if no nontrivial constant could be excluded). EXAMPLE: example facFirstWeyl; shows examples SEE ALSO: facSubWeyl, testNCfac, facShift" {//facFirstWeyl return(facWeyl(h)); }//facFirstWeyl example { "EXAMPLE:";echo=2; ring R = 0,(x,y),dp; def r = nc_algebra(1,1); setring(r); poly h = (x^2*y^2+x)*(x+1); facFirstWeyl(h); } static proc checkForHomogInhomogInterchangabilityNthWeyl(list factors, int posLeft, int posRight) " INPUT: A list consisting of factors of a certain polynomial in the nth Weyl algebra, factors, and a position from the left and the right, where the last swap was done. OUTPUT: A list containing lists consisting of factors of a certain polynomial in the nth Weyl algebra. The purpose of this function is to check whether we can interchange certain inhomogeneous factors with homogeneous ones. If it is possible, this function returns a list of lists of possible interchanges. The idea came because of an example, where we need an extra swap in the end, otherwise we would not capture all factorizations. The example was h = x4d7+11x3d6+x2d7+x2d6+x3d4+29x2d5+xd6+8xd5+d6+5x2d3+14xd4+13d4+5xd2+d3+d; ASSUMPTIONS: - All factors are irreducible - Our basering is the Nth Weyl algebra; the xs are the first n variables, the differential operators are the last n. - No entry in the list factors is 0. " {//checkForHomogInhomogInterchangabilityNthWeyl int p = printlevel-voice+2; string dbprintWhitespace = ""; int i; int j; int k; int l; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} if (size(factors) <= 2 || posLeft >= posRight - 1) {//easiest case: There is nothing to swap return (list(factors)); }//easiest case: There is nothing to swap list result = list(factors); list tempResultEntries; list tempSwaps; list tempSwapsTempEntry; list attemptToSwap; int posHomogBegin; int posHomogEnd; poly leftHomogFactorProduct; poly rightHomogFactorProduct; dbprint(p, dbprintWhitespace+"We try to swap elements in the following list:"); dbprint(p, factors); dbprint(p, "The left border is at position: "+string(posLeft)); dbprint(p, "The right border is at position: " + string(posRight)); for (i = posLeft; i < posRight; i++) {//checking within the window posLeft <--> posRight, if there are interchanges possible leftHomogFactorProduct = 1; while (homogwithorderNthWeyl(factors[i])) {//We have a homogeneous polynomial somewhere on the left if (leftHomogFactorProduct == 1) {posHomogBegin = i;} leftHomogFactorProduct = leftHomogFactorProduct * factors[i]; i = i+1; if (i>=posRight) {break;} }//We have a homogeneous polynomial somewhere on the left if ((leftHomogFactorProduct !=1) && (!homogwithorderNthWeyl(factors[i]))) {//We have a group of homogeneous polynomials and an inhomogeneous one that we can try to swap. attemptToSwap = extractHomogeneousDivisorsRightNthWeyl(leftHomogFactorProduct*factors[i]); for (l = 1; l<=size(attemptToSwap); l++) { if (size(attemptToSwap[l])>1) {//Bingo, we were able to swap this one element dbprint(p,dbprintWhitespace+"We can swap entry "+string(i)+" with its predecessors"); dbprint(p,dbprintWhitespace+"The elements look like the following after the swap:"); dbprint(p,attemptToSwap); tempSwapsTempEntry = list(); for (j = size(factors); j >=1; j--) {//creating a new entry for the resulting list, replacing the swap in factors if (j==i) { for (k = size(attemptToSwap[l]); k >=1 ; k--) { tempSwapsTempEntry = insert(tempSwapsTempEntry, attemptToSwap[l][k]); } j=posHomogBegin;//Because of the change } else { tempSwapsTempEntry = insert(tempSwapsTempEntry,factors[j]); } }//creating a new entry for the resulting list, replacing the swap in factors if (posRight <= size(tempSwapsTempEntry)) { tempSwaps = insert(tempSwaps,list(list(posHomogBegin+1,posRight),tempSwapsTempEntry)); } else { tempSwaps = insert(tempSwaps,list(list(posHomogBegin+1,size(tempSwapsTempEntry)), tempSwapsTempEntry)); } }//Bingo, we were able to swap this one element } }//We have a group of homogeneous polynomials and an inhomogeneous one that we can try to swap. else { if (i trying to swap j = i+1; // print(j); // print(size(factors)); // print(posRight); // print("==="); while (homogwithorderNthWeyl(factors[j])) { rightHomogFactorProduct = rightHomogFactorProduct * factors[j]; posHomogEnd = j; j = j+1; if (j > posRight) {break;} } attemptToSwap = extractHomogeneousDivisorsLeftNthWeyl(factors[i]*rightHomogFactorProduct); for (l =1; l<=size(attemptToSwap);l++) { if (size(attemptToSwap[l])>1) {//Bingo, we were able to swap this one element dbprint(p,dbprintWhitespace+"We can swap entry "+string(i)+" and its successors"); dbprint(p,dbprintWhitespace+"The elements look like the following after the swap:"); dbprint(p,attemptToSwap); tempSwapsTempEntry = list(); for (j = size(factors); j >=1; j--) {//creating a new entry for the resulting list, replacing the swap in factors if (j==posHomogEnd) { for (k = size(attemptToSwap[l]); k >=1 ; k--) { tempSwapsTempEntry = insert(tempSwapsTempEntry, attemptToSwap[l][k]); } j = i; //Because we changed entry i+1 and i } else { tempSwapsTempEntry = insert(tempSwapsTempEntry,factors[j]); } }//creating a new entry for the resulting list, replacing the swap in factors tempSwaps=insert(tempSwaps, list(list(posLeft,i+size(attemptToSwap[l])-1),tempSwapsTempEntry)); }//Bingo, we were able to swap this one element } }//position i+1 is homogeneous, position i is not ==> trying to swap } } }//checking within the window posLeft <--> posRight, if there are - interchanges possible //Now we will recursively call the function for all swapped entries. dbprint(p,dbprintWhitespace+ "Our list of different factorizations is now:"); dbprint(p,tempSwaps); for (i = 1; i<=size(tempSwaps);i++) {//recursive call to all formerly attempted swaps. dbprint(p, "Calling checkForHomogInterchangabilityNthWeyl recursively with values:"); dbprint(p, tempSwaps); tempResultEntries=checkForHomogInhomogInterchangabilityNthWeyl(tempSwaps[i][2], tempSwaps[i][1][1],tempSwaps[i][1][2]); result = result + tempResultEntries; }//recursive call to all formerly attempted swaps. result = delete_dublicates_noteval(result); return(result); }//checkForHomogInhomogInterchangabilityNthWeyl static proc checkForHomogInhomogInterchangability(list factors, posLeft, posRight) " INPUT: A list consisting of factors of a certain polynomial in the first Weyl algebra, factors, and a position from the left and the right, where the last swap was done. OUTPUT: A list containing lists consisting of factors of a certain polynomial in the first Weyl algebra. The purpose of this function is to check whether we can interchange certain inhomogeneous factors with homogeneous ones. If it is possible, this function returns a list of lists of possible interchanges. The idea came because of an example, where we need an extra swap in the end, otherwise we would not capture all factorizations. The example was h = x4d7+11x3d6+x2d7+x2d6+x3d4+29x2d5+xd6+8xd5+d6+5x2d3+14xd4+13d4+5xd2+d3+d; ASSUMPTIONS: - All factors are irreducible " {//checkForHomogInhomogInterchangability int p = printlevel-voice+2; string dbprintWhitespace = ""; int i; int j; int k; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} if (size(factors) <= 2 || posLeft >= posRight - 1) {//easiest case: There is nothing to swap return (list(factors)); }//easiest case: There is nothing to swap list result = list(factors); list tempResultEntries; list tempSwaps; list tempSwapsTempEntry; list attemptToSwap; intvec ivm11 = intvec(-1,1); dbprint(p, dbprintWhitespace+"We try to swap elements in the following list:"); dbprint(p, factors); for (i = posLeft; i < posRight; i++) {//checking within the window posLeft <--> posRight, if there are interchanges possible if (homogwithorder(factors[i],ivm11) && !homogwithorder(factors[i+1],ivm11)) {//position i is homogeneous, position i+1 is not ==> trying to swap attemptToSwap = extractHomogeneousDivisorsRight(factors[i]*factors[i+1]); if (size(attemptToSwap[1])>1) {//Bingo, we were able to swap this one element dbprint(p,dbprintWhitespace+"We can swap entry "+string(i)+" and "+ string(i+1)); dbprint(p,dbprintWhitespace+"The elements look like the following after the swap:"); dbprint(p,attemptToSwap); tempSwapsTempEntry = list(); for (j = size(factors); j >=1; j--) {//creating a new entry for the resulting list, replacing the swap in factors if (j==i+1) { for (k = size(attemptToSwap[1]); k >=1 ; k--) { tempSwapsTempEntry = insert(tempSwapsTempEntry, attemptToSwap[1][k]); } j--; //Because we changed entry i+1 and i } else { tempSwapsTempEntry = insert(tempSwapsTempEntry,factors[j]); } }//creating a new entry for the resulting list, replacing the swap in factors tempSwaps = insert(tempSwaps,list(list(i+1,posRight),tempSwapsTempEntry)); }//Bingo, we were able to swap this one element }//position i is homogeneous, position i+1 is not ==> trying to swap else { if(!homogwithorder(factors[i],ivm11) && homogwithorder(factors[i+1],ivm11)) {//position i+1 is homogeneous, position i is not ==> trying to swap attemptToSwap = extractHomogeneousDivisorsLeft(factors[i]*factors[i+1]); if (size(attemptToSwap[1])>1) {//Bingo, we were able to swap this one element dbprint(p,dbprintWhitespace+"We can swap entry "+string(i)+" and "+ string(i+1)); dbprint(p,dbprintWhitespace+"The elements look like the following after the swap:"); dbprint(p,attemptToSwap); tempSwapsTempEntry = list(); for (j = size(factors); j >=1; j--) {//creating a new entry for the resulting list, replacing the swap in factors if (j==i+1) { for (k = size(attemptToSwap[1]); k >=1 ; k--) { tempSwapsTempEntry = insert(tempSwapsTempEntry, attemptToSwap[1][k]); } j--; //Because we changed entry i+1 and i } else { tempSwapsTempEntry = insert(tempSwapsTempEntry,factors[j]); } }//creating a new entry for the resulting list, replacing the swap in factors tempSwaps = insert(tempSwaps,list(list(posLeft,i),tempSwapsTempEntry)); }//Bingo, we were able to swap this one element }//position i+1 is homogeneous, position i is not ==> trying to swap } }//checking within the window posLeft <--> posRight, if there are interchanges possible //Now we will recursively call the function for all swapped entries. dbprint(p,dbprintWhitespace+ "Our list of different factorizations is now:"); dbprint(p,tempSwaps); for (i = 1; i<=size(tempSwaps);i++) {//recursive call to all formerly attempted swaps. tempResultEntries=checkForHomogInhomogInterchangability(tempSwaps[i][2], tempSwaps[i][1][1],tempSwaps[i][1][2]); result = result + tempResultEntries; }//recursive call to all formerly attempted swaps. result = delete_dublicates_noteval(result); return(result); }//checkForHomogInhomogInterchangability static proc sfacwa(poly h) "INPUT: A polynomial h in the first Weyl algebra OUTPUT: A list of factorizations, where the factors might still be reducible. ASSUMPTIONS: - Our basering is the first Weyl algebra; the x is the first variable, the differential operator the second. " {//proc sfacwa int i; int j; int k; int p = printlevel-voice+2; string dbprintWhitespace = ""; number commonCoefficient = content(h); for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} dbprint(p,dbprintWhitespace + " Extracting homogeneous left and right factors"); if(homogwithorder(h,intvec(-1,1))) {//we are already dealing with a -1,1 homogeneous poly dbprint(p,dbprintWhitespace+" Given polynomial is -1,1 homogeneous. Start homog. fac. and ret. its result"); return(homogfacFirstWeyl_all(h)); }//we are already dealing with a -1,1 homogeneous poly list resulttemp = extractHomogeneousDivisors(h/commonCoefficient); //resulttemp = resulttemp + list(list(h/commonCoefficient)); list inhomogeneousFactorsToFactorize; int isAlreadyInInhomogList; dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace +" Making Set of inhomogeneous polynomials we have to factorize."); for (i = 1; i<=size(resulttemp); i++) {//Going through all different kinds of factorizations where we extracted homogeneous factors for (j = 1;j<=size(resulttemp[i]);j++) {//searching for the inhomogeneous factor if (!homogwithorder(resulttemp[i][j],intvec(-1,1))) {//We have found our candidate isAlreadyInInhomogList = 0; for (k = 1; k<=size(inhomogeneousFactorsToFactorize);k++) {//Checking if our candidate is already in our tofactorize-list if (inhomogeneousFactorsToFactorize[k]==resulttemp[i][j]) {//The candidate was already in the list isAlreadyInInhomogList = 1; break; }//The candidate was already in the list }//Checking if our candidate is already in our tofactorize-list if (!isAlreadyInInhomogList) { inhomogeneousFactorsToFactorize=inhomogeneousFactorsToFactorize + list(resulttemp[i][j]); } }//We have found our candidate }//searching for the inhomogeneous factor }//Going through all different kinds of factorizations where we extracted homogeneous factors dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace + "The set is:"); dbprint(p,inhomogeneousFactorsToFactorize); dbprint(p,dbprintWhitespace+ "Factorizing the different occuring inhomogeneous factors"); for (i = 1; i<= size(inhomogeneousFactorsToFactorize); i++) {//Factorizing all kinds of inhomogeneous factors inhomogeneousFactorsToFactorize[i] = sfacwa2(inhomogeneousFactorsToFactorize[i]); for (j = 1; j<=size(inhomogeneousFactorsToFactorize[i]);j++) {//Deleting the leading coefficient since we don't need him if (deg(inhomogeneousFactorsToFactorize[i][j][1],intvec(1,1))==0) { inhomogeneousFactorsToFactorize[i][j] = delete(inhomogeneousFactorsToFactorize[i][j],1); } }//Deleting the leading coefficient since we don't need him }//Factorizing all kinds of inhomogeneous factors dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace +" Putting the factorizations in the lists"); list result; int posInhomogPoly; int posInhomogFac; for (i = 1; i<=size(resulttemp); i++) {//going through all by now calculated factorizations for (j = 1;j<=size(resulttemp[i]); j++) {//Finding the inhomogeneous factor if (!homogwithorder(resulttemp[i][j],intvec(-1,1))) {//Found it posInhomogPoly = j; break; }//Found it }//Finding the inhomogeneous factor for (k = 1; k<=size(inhomogeneousFactorsToFactorize);k++) {//Finding the matching inhomogeneous factorization we already determined if(product(inhomogeneousFactorsToFactorize[k][1]) == resulttemp[i][j]) {//found it posInhomogFac = k; break; }//Found it }//Finding the matching inhomogeneous factorization we already determined for (j = 1; j <= size(inhomogeneousFactorsToFactorize[posInhomogFac]); j++) { result = insert(result, resulttemp[i]); result[1] = delete(result[1],posInhomogPoly); for (k =size(inhomogeneousFactorsToFactorize[posInhomogFac][j]);k>=1; k--) {//Inserting factorizations result[1] = insert(result[1],inhomogeneousFactorsToFactorize[posInhomogFac][j][k], posInhomogPoly-1); }//Inserting factorizations dbprint(p,dbprintWhitespace + "Added a factorization to result, namely:"); dbprint(p, result[1]); } }//going through all by now calculated factorizations dbprint(p,dbprintWhitespace +" Done"); result = delete_dublicates_noteval(result); for (i = 1; i<=size(result);i++) {//Putting the content everywhere result[i] = insert(result[i],commonCoefficient); }//Putting the content everywhere return(result); }//proc sfacwa static proc sfacwaNthWeyl(poly h) "INPUT: A polynomial h in the Nth Weyl algebra OUTPUT: A list of factorizations, where the factors might still be reducible. ASSUMPTIONS: - Our basering is the Nth Weyl algebra; the xs are the first n variables, the differential operators are the last n. " {//proc sfacwaNthWeyl int i; int j; int k; int p = printlevel-voice+2; string dbprintWhitespace = ""; number commonCoefficient = content(h); for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} dbprint(p,dbprintWhitespace + " Extracting homogeneous left and right factors"); if(homogwithorderNthWeyl(h)) {//we are already dealing with a -1,1 homogeneous poly dbprint(p,dbprintWhitespace+" Given polynomial is -1,1 homogeneous. Start homog. fac. and ret. its result"); return(homogfacNthWeyl_all(h)); }//we are already dealing with a -1,1 homogeneous poly list resulttemp = extractHomogeneousDivisorsNthWeyl(h/commonCoefficient); //resulttemp = resulttemp + list(list(h/commonCoefficient)); list inhomogeneousFactorsToFactorize; int isAlreadyInInhomogList; dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace +" Making Set of inhomogeneous polynomials we have to factorize."); for (i = 1; i<=size(resulttemp); i++) {//Going through all different kinds of factorizations where we extracted homogeneous factors for (j = 1;j<=size(resulttemp[i]);j++) {//searching for the inhomogeneous factor if (!homogwithorderNthWeyl(resulttemp[i][j])) {//We have found our candidate isAlreadyInInhomogList = 0; for (k = 1; k<=size(inhomogeneousFactorsToFactorize);k++) {//Checking if our candidate is already in our tofactorize-list if (inhomogeneousFactorsToFactorize[k]==resulttemp[i][j]) {//The candidate was already in the list isAlreadyInInhomogList = 1; break; }//The candidate was already in the list }//Checking if our candidate is already in our tofactorize-list if (!isAlreadyInInhomogList) { inhomogeneousFactorsToFactorize=inhomogeneousFactorsToFactorize + list(resulttemp[i][j]); } }//We have found our candidate }//searching for the inhomogeneous factor }//Going through all different kinds of factorizations where we extracted homogeneous factors dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace + "The set is:"); dbprint(p,inhomogeneousFactorsToFactorize); dbprint(p,dbprintWhitespace+ "Factorizing the different occuring inhomogeneous factors"); for (i = 1; i<= size(inhomogeneousFactorsToFactorize); i++) {//Factorizing all kinds of inhomogeneous factors inhomogeneousFactorsToFactorize[i] = sfacwa2NthWeyl(inhomogeneousFactorsToFactorize[i]); for (j = 1; j<=size(inhomogeneousFactorsToFactorize[i]);j++) {//Deleting the leading coefficient since we don't need him if (deg(inhomogeneousFactorsToFactorize[i][j][1],intvec(1,1))==0) { inhomogeneousFactorsToFactorize[i][j] = delete(inhomogeneousFactorsToFactorize[i][j],1); } }//Deleting the leading coefficient since we don't need him }//Factorizing all kinds of inhomogeneous factors dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace +" Putting the factorizations in the lists"); list result; int posInhomogPoly; int posInhomogFac; for (i = 1; i<=size(resulttemp); i++) {//going through all by now calculated factorizations for (j = 1;j<=size(resulttemp[i]); j++) {//Finding the inhomogeneous factor if (!homogwithorderNthWeyl(resulttemp[i][j])) {//Found it posInhomogPoly = j; break; }//Found it }//Finding the inhomogeneous factor for (k = 1; k<=size(inhomogeneousFactorsToFactorize);k++) {//Finding the matching inhomogeneous factorization we already determined if(product(inhomogeneousFactorsToFactorize[k][1]) == resulttemp[i][j]) {//found it posInhomogFac = k; break; }//Found it }//Finding the matching inhomogeneous factorization we already determined for (j = 1; j <= size(inhomogeneousFactorsToFactorize[posInhomogFac]); j++) { result = insert(result, resulttemp[i]); result[1] = delete(result[1],posInhomogPoly); for (k =size(inhomogeneousFactorsToFactorize[posInhomogFac][j]);k>=1; k--) {//Inserting factorizations result[1] = insert(result[1],inhomogeneousFactorsToFactorize[posInhomogFac][j][k], posInhomogPoly-1); }//Inserting factorizations dbprint(p,dbprintWhitespace + "Added a factorization to result, namely:"); dbprint(p, result[1]); } }//going through all by now calculated factorizations dbprint(p,dbprintWhitespace +" Done"); result = delete_dublicates_noteval(result); for (i = 1; i<=size(result);i++) {//Putting the content everywhere result[i] = insert(result[i],commonCoefficient); }//Putting the content everywhere return(result); }//proc sfacwaNthWeyl static proc sfacwa2(poly h) " Subprocedure of sfacwa Assumptions: - h is not in K[x] or in K[d], or even in K. These cases are caught by the input - The coefficients are integer values and the gcd of the coefficients is 1 " {//proc sfacwa2 int p=printlevel-voice+2; // for dbprint int i; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} intvec ivm11 = intvec(-1,1); intvec iv11 = intvec(1,1); intvec iv10 = intvec(1,0); intvec iv01 = intvec(0,1); intvec iv1m1 = intvec(1,-1); poly p_max; poly p_min; poly q_max; poly q_min; map invo = basering,-var(1),var(2); list calculatedRightFactors; if(homogwithorder(h,ivm11)) {//Unnecessary how we are using it, but if one wants to use it on its own, we are stating it here dbprint(p,dbprintWhitespace+" Given polynomial is -1,1 homogeneous. Start homog. fac. and ret. its result"); return(homogfacFirstWeyl_all(h)); }//Unnecessary how we are using it, but if one wants to use it on its own, we are stating it here list result = list(); int j; int k; int l; dbprint(p,dbprintWhitespace+" Computing the degree-limits of the factorization"); //end finding the limits dbprint(p,dbprintWhitespace+" Computing the maximal and the minimal homogeneous part of the given polynomial"); list M = computeCombinationsMinMaxHomog(h); dbprint(p,dbprintWhitespace+" Done."); dbprint(p,dbprintWhitespace+" Filtering invalid combinations in M."); for (i = 1 ; i<= size(M); i++) {//filter valid combinations if (product(M[i]) == h) {//We have one factorization result = result + divides(M[i][1],h,invo,1); dbprint(p,dbprintWhitespace+"Result list updated:"); dbprint(p,dbprintWhitespace+string(result)); M = delete(M,i); continue; }//We have one factorization }//filter valid combinations dbprint(p,dbprintWhitespace+"Done."); dbprint(p,dbprintWhitespace+"The size of M is "+string(size(M))); for (i = 1; i<=size(M); i++) {//Iterate over all first combinations (p_max + p_min)(q_max + q_min) dbprint(p,dbprintWhitespace+" Combination No. "+string(i)+" in M:" ); p_max = jet(M[i][1],deg(M[i][1],ivm11),ivm11)-jet(M[i][1],deg(M[i][1],ivm11)-1,ivm11); p_min = jet(M[i][1],deg(M[i][1],iv1m1),iv1m1)-jet(M[i][1],deg(M[i][1],iv1m1)-1,iv1m1); q_max = jet(M[i][2],deg(M[i][2],ivm11),ivm11)-jet(M[i][2],deg(M[i][2],ivm11)-1,ivm11); q_min = jet(M[i][2],deg(M[i][2],iv1m1),iv1m1)-jet(M[i][2],deg(M[i][2],iv1m1)-1,iv1m1); dbprint(p,dbprintWhitespace+" pmax = "+string(p_max)); dbprint(p,dbprintWhitespace+" pmin = "+string(p_min)); dbprint(p,dbprintWhitespace+" qmax = "+string(q_max)); dbprint(p,dbprintWhitespace+" qmin = "+string(q_min)); //Check, whether p_max + p_min or q_max and q_min are already left or right divisors. if (divides(p_min + p_max,h,invo)) { dbprint(p,dbprintWhitespace+" Got one result."); result = result + divides(p_min + p_max,h,invo,1); } else { if (divides(q_min + q_max,h,invo)) { dbprint(p,dbprintWhitespace+" Got one result."); result = result + divides(q_min + q_max, h , invo, 1); } } //Now the check, if deg(p_max) = deg(p_min)+1 (and the same with q_max and q_min) if (deg(p_max, ivm11) == deg(p_min, ivm11) +1 or deg(q_max, ivm11) == deg(q_min, ivm11) +1 ) {//Therefore, p_max + p_min must be a left factor or we can dismiss the combination dbprint(p,dbprintWhitespace+" There are no homogeneous parts we can put between pmax and pmin resp. qmax and qmin."); //TODO: Prove, that then also a valid right factor is not possible M = delete(M,i); continue; }//Therefore, p_max + p_min must be a left factor or we can dismiss the combination //Done with the Check //If we come here, there are still homogeneous parts to be added to p_max + p_min //AND to q_max and q_min in //order to obtain a real factor //We use the procedure determineRestOfHomogParts to find our q. dbprint(p,dbprintWhitespace+" Solving for the other homogeneous parts in q"); calculatedRightFactors = determineRestOfHomogParts(p_max,p_min,q_max,q_min,h); dbprint(p,dbprintWhitespace+" Done with it. Found "+string(size(calculatedRightFactors)) +" solutions."); for (j = 1; j<=size(calculatedRightFactors);j++) {//Check out whether we really have right factors of h in calculatedRightFactors if (divides(calculatedRightFactors[j],h,invo)) { result = result + divides(calculatedRightFactors[j],h,invo,1); } else { dbprint(p,"Solution for max and min homog found, but not a divisor of h"); //TODO: Proof, why this can happen. } }//Check out whether we really have right factors of h in calculatedRightFactors }//Iterate over all first combinations (p_max + p_min)(q_max + q_min) result = delete_dublicates_noteval(result); //print(M); if (size(result) == 0) {//no factorization found result = list(list(h)); }//no factorization found return(result); }//proc sfacwa2 static proc sfacwa2NthWeyl(poly h) " Subprocedure of sfacwa Assumptions: - h is not part of a commutative subalgebra of the nth Weyl algebra - The coefficients are integer values and the gcd of the coefficients is 1 " {//proc sfacwa2NthWeyl int p=printlevel-voice+2; // for dbprint int i; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} poly p_max; poly p_min; poly q_max; poly q_min; ideal invoIdeal; intvec maxDegrees; intvec tempIntVec1; for (i = 1; i <= nvars(basering); i++) {//filling maxDegrees tempIntVec1 = 0:nvars(basering); tempIntVec1[i] = 1; maxDegrees[i] = deg(h,tempIntVec1); }//filling maxDegrees for (i = 1; i <= nvars(basering); i++) {//Filling the mapping rules for the involution map if (i <= nvars(basering) div 2) {invoIdeal[i] = -var(i);} else {invoIdeal[i] = var(i);} }//Filling the mapping rules for the involution map map invo = basering,invoIdeal; list calculatedRightFactors; if(homogwithorderNthWeyl(h)) {//Unnecessary how we are using it, but if one wants to use it on its own, we are stating it here dbprint(p,dbprintWhitespace+" Given polynomial is -1,1 homogeneous. Start homog. fac. and ret. its result"); return(homogfacNthWeyl_all(h)); }//Unnecessary how we are using it, but if one wants to use it on its own, we are stating it here list result = list(); int j; int k; int l; list tempBetweenDegreesP; list tempBetweenDegreesQ; dbprint(p,dbprintWhitespace+" Computing the degree-limits of the factorization"); //end finding the limits dbprint(p,dbprintWhitespace+" Computing the maximal and the minimal homogeneous part of the given polynomial"); list M = computeCombinationsMinMaxHomogNthWeyl(h); dbprint(p,dbprintWhitespace+" Done."); dbprint(p,dbprintWhitespace+" Filtering invalid combinations in M."); for (i = 1 ; i<= size(M); i++) {//filter valid combinations if (product(M[i]) == h) {//We have one factorization result = result + divides(M[i][1],h,invo,1); dbprint(p,dbprintWhitespace+"Result list updated:"); dbprint(p,dbprintWhitespace+string(result)); M = delete(M,i); continue; }//We have one factorization }//filter valid combinations dbprint(p,dbprintWhitespace+"Done."); dbprint(p,dbprintWhitespace+"The size of M is "+string(size(M))); for (i = 1; i<=size(M); i++) {//Iterate over all first combinations (p_max + p_min)(q_max + q_min) dbprint(p,dbprintWhitespace+" Combination No. "+string(i)+" in M:" ); p_max = homogDistributionNthWeyl(M[i][1])[2][2]; p_min = homogDistributionNthWeyl(M[i][1])[1][2]; q_max = homogDistributionNthWeyl(M[i][2])[2][2]; q_min = homogDistributionNthWeyl(M[i][2])[1][2]; dbprint(p,dbprintWhitespace+" pmax = "+string(p_max)); dbprint(p,dbprintWhitespace+" pmin = "+string(p_min)); dbprint(p,dbprintWhitespace+" qmax = "+string(q_max)); dbprint(p,dbprintWhitespace+" qmin = "+string(q_min)); //Check, whether p_max + p_min or q_max and q_min are already left or right divisors. if (divides(p_min + p_max,h,invo)) { dbprint(p,dbprintWhitespace+" Got one result."); result = result + divides(p_min + p_max,h,invo,1); } else { if (divides(q_min + q_max,h,invo)) { dbprint(p,dbprintWhitespace+" Got one result."); result = result + divides(q_min + q_max, h , invo, 1); } } //Now the check, if deg(p_max) = deg(p_min)+1 (and the same with q_max and q_min) tempBetweenDegreesP = possibleHomogPartsInBetween(degreeOfNthWeylPoly(p_max), degreeOfNthWeylPoly(p_min), maxDegrees); tempBetweenDegreesQ = possibleHomogPartsInBetween(degreeOfNthWeylPoly(q_max), degreeOfNthWeylPoly(q_min), maxDegrees); if (size(tempBetweenDegreesQ)==2 or size(tempBetweenDegreesP)==2 ) {//Therefore, p_max + p_min must be a left factor or we can dismiss the combination dbprint(p,dbprintWhitespace+" There are no homogeneous parts we can put between pmax and pmin resp. qmax and qmin."); //TODO: Prove, that then also a valid right factor is not possible M = delete(M,i); continue; }//Therefore, p_max + p_min must be a left factor or we can dismiss the combination //Done with the Check //If we come here, there are still homogeneous parts to be added to p_max + p_min //AND to q_max and q_min in //order to obtain a real factor //We use the procedure determineRestOfHomogParts to find our q. dbprint(p,dbprintWhitespace+" Solving for the other homogeneous parts in q"); calculatedRightFactors = determineRestOfHomogPartsNthWeyl(p_max,p_min,q_max,q_min,h); dbprint(p,dbprintWhitespace+" Done with it. Found "+string(size(calculatedRightFactors)) +" solutions."); for (j = 1; j<=size(calculatedRightFactors);j++) {//Check out whether we really have right factors of h in calculatedRightFactors if (divides(calculatedRightFactors[j],h,invo)) { result = result + divides(calculatedRightFactors[j],h,invo,1); } else { dbprint(p,"Solution for max and min homog found, but not a divisor of h"); //TODO: Proof, why this can happen. } }//Check out whether we really have right factors of h in calculatedRightFactors }//Iterate over all first combinations (p_max + p_min)(q_max + q_min) result = delete_dublicates_noteval(result); //print(M); if (size(result) == 0) {//no factorization found result = list(list(h)); }//no factorization found return(result); }//proc sfacwa2NthWeyl static proc determineRestOfHomogParts(poly pmax, poly pmin, poly qmax, poly qmin, poly h) "INPUT: Polynomials p_max, p_min, q_max, q_min and h. The maximum homogeneous part h_max of h is given by p_max*pmin, the minimum homogeneous part h_min of h is given by p_min*q_min. OUTPUT: A list of right factors q of h that have q_max and q_min as their maximum respectively minimum homogeneous part. Empty list, if those elements are not existent ASSUMPTIONS: - deg(p_max,intvec(-1,1))>deg(p_min,intvec(-1,1)) +1 - deg(q_max,intvec(-1,1))>deg(q_min,intvec(-1,1)) +1 - p_max*q_max = h_max - p_min*q_min = h_min - The basering is the first Weyl algebra " {//proc determineRestOfHomogParts int p=printlevel-voice+2; // for dbprint string dbprintWhitespace = ""; int i; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} int kappa = Min(intvec(deg(h,intvec(1,0)), deg(h,intvec(0,1)))); def R = basering; int n1 = deg(pmax,intvec(-1,1)); int nk = -deg(pmin,intvec(1,-1)); int m1 = deg(qmax,intvec(-1,1)); int ml = -deg(qmin,intvec(1,-1)); int j; int k; ideal mons; dbprint(p,dbprintWhitespace+" Extracting zero homog. parts of pmax, qmax, pmin, qmin and h."); //Extracting the zero homogeneous part of the given polynomials ideal pandqZero = pmax,pmin,qmax,qmin; if (n1 > 0){pandqZero[1] = lift(var(2)^n1,pmax)[1,1];} else{if (n1 < 0){pandqZero[1] = lift(var(1)^(-n1),pmax)[1,1];} else{pandqZero[1] = pmax;}} if (nk > 0){pandqZero[2] = lift(var(2)^nk,pmin)[1,1];} else{if (nk < 0){pandqZero[2] = lift(var(1)^(-nk),pmin)[1,1];} else{pandqZero[2] = pmin;}} if (m1 > 0){pandqZero[3] = lift(var(2)^m1,qmax)[1,1];} else{if (m1 < 0){pandqZero[3] = lift(var(1)^(-m1),qmax)[1,1];} else{pandqZero[3] = qmax;}} if (ml > 0){pandqZero[4] = lift(var(2)^ml,qmin)[1,1];} else{if (ml < 0){pandqZero[4] = lift(var(1)^(-ml),qmin)[1,1];} else{pandqZero[4] = qmin;}} list hZeroinR = homogDistribution(h); for (i = 1; i<=size(hZeroinR);i++) {//Extracting the zero homogeneous parts of the homogeneous summands of h if (hZeroinR[i][1] > 0){hZeroinR[i][2] = lift(var(2)^hZeroinR[i][1],hZeroinR[i][2])[1,1];} if (hZeroinR[i][1] < 0){hZeroinR[i][2] = lift(var(1)^(-hZeroinR[i][1]),hZeroinR[i][2])[1,1];} }//Extracting the zero homogeneous parts of the homogeneous summands of h dbprint(p,dbprintWhitespace+" Done!"); //Moving everything into the ring K[theta] dbprint(p,dbprintWhitespace+" Moving everything into the ring K[theta]"); ring KTheta = 0,(x,d,theta),dp; map thetamap = R, x, d; poly entry; ideal mons; ideal pandqZero; list hZeroinKTheta; setring(R); //Starting with p and q for (k=1; k<=4; k++) {//Transforming pmax(0),qmax(0),pmin(0),qmin(0) in theta-polys mons = ideal(); for(i = 1; i<=size(pandqZero[k]);i++) {//Putting the monomials in a list mons[size(mons)+1] = pandqZero[k][i]; }//Putting the monomials in a list setring(KTheta); mons = thetamap(mons); for (i = 1; i<=size(mons);i++) {//transforming the monomials as monomials in theta entry = leadcoef(mons[i]); for (j = 0; j= 1;k--) {//Transforming the different homogeneous parts of h into polys in K[theta] mons = ideal(); for(i = 1; i<=size(hZeroinR[k][2]);i++) {//Putting the monomials in a list mons[size(mons)+1] = hZeroinR[k][2][i]; }//Putting the monomials in a list setring(KTheta); mons = thetamap(mons); for (i = 1; i<=size(mons);i++) {//transforming the monomials as monomials in theta entry = leadcoef(mons[i]); for (j = 0; j."); setring(R); return(list()); }//No solution in this case. Return the empty list if(vdim(slimgb(solutionSystemforqs+theta))==-1) {//My conjecture is that this would never happen //ERROR("This is an counterexample to your conjecture. We have infinitely many solutions"); //TODO: See, what we would do here dbprint(p,dbprintWhitespace+"There are infinitely many solution to this system. We will return the empty list."); setring(R); return(list()); }//My conjecture is that this would never happen else {//We have finitely many solutions if(vdim(slimgb(solutionSystemforqs+theta))==1) {//exactly one solution for (i = 2; i<= size(qs)-1;i++) { qs[i][2] = NF(qs[i][2],solutionSystemforqs); } setring(R); map backFromSolutionRing = solutionRing,var(1)*var(2); list qs = backFromSolutionRing(qs); list result = list(0); for (i = 1; i<=size(qs); i++) { if (qs[i][1]>0){qs[i][2] = qs[i][2]*var(2)^qs[i][1];} if (qs[i][1]<0){qs[i][2] = qs[i][2]*var(1)^(-qs[i][1]);} result[1] = result[1] + qs[i][2]; } dbprint(p,dbprintWhitespace+"Found one unique solution. Returning the result."); return(result); }//exactly one solution else {//We have more than one solution, but finitely many def ringForSolveLib = solve(solutionSystemforqs+theta, "nodisplay"); setring ringForSolveLib; list valuesForQs = list(); list tempValues; int validSol; for (i = 1; i<=size(SOL); i++) {//filtering integer solutions validSol = 1; for (j =1; j<=size(SOL[i]); j++) {//Checking every entry if it is integer or not if (SOL[i][j] - int(SOL[i][j])!=0) {//No integer solution validSol = 0; break; }//No integer solution }//Checking every entry if it is integer or not if (validSol) { tempValues = list(); for (j = 1; j<=size(SOL[i]); j++) {//filling the valuesforQs tempValues[j]= int(SOL[i][j]); }//filling the valuesforQs valuesForQs = valuesForQs + list(tempValues); } }//filtering integer solutions print(valuesForQs); setring solutionRing; list differentQs = list(); ideal tempSolutionForQ; for (i = 1; i<=size(valuesForQs); i++) { differentQs[i] = qs; tempSolutionForQ = ideal(); for (j=2; j<=nvars(solutionRing);j++) {//filling solution ideal tempSolutionForQ[j-1] = var(j) - valuesForQs[i][j]; }//filling solution ideal for (j=2; j0){differentQs[k][i][2] = differentQs[k][i][2]*var(2)^differentQs[k][i][1];} if (differentQs[k][i][1]<0){differentQs[k][i][2] = differentQs[k][i][2]*var(1)^(-differentQs[k][i][1]);} result[k] = result[k] + differentQs[k][i][2]; } } dbprint(p,dbprintWhitespace+"Found multiple solutions. Returning the result."); return(result); }//We have more than one solution, but finitely many }//We have finitely many solutions }//proc determineRestOfHomogParts static proc determineRestOfHomogPartsNthWeyl(poly pmax, poly pmin, poly qmax, poly qmin, poly h) "INPUT: Polynomials p_max, p_min, q_max, q_min and h. The maximum homogeneous part h_max of h is given by p_max*pmin, the minimum homogeneous part h_min of h is given by p_min*q_min. OUTPUT: A list of right factors q of h that have q_max and q_min as their maximum respectively minimum homogeneous part. Empty list, if those elements are not existent ASSUMPTIONS: - deg(p_max) >_lex deg(p_min) +1 - deg(q_max) >_lex deg(q_min) +1 - p_max*q_max = h_max - p_min*q_min = h_min - The basering is the nth Weyl algebra and has the form, that the first n variables represent x1, ..., xn, and the second n variables do represent the d1, ..., dn. " {//proc determineRestOfHomogPartsNthWeyl int p=printlevel-voice+2; // for dbprint string dbprintWhitespace = ""; int i; int j; int k; int l; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} intvec kappa = 0:(nvars(basering) div 2); intvec maxDegrees; intvec tempIntVec1; intvec tempIntVec2; for (i = 1; i <= nvars(basering) div 2; i++) {//filling kappa tempIntVec1 = 0:nvars(basering); tempIntVec2 = 0:nvars(basering); tempIntVec1[i] = 1; tempIntVec2[i + nvars(basering) div 2] = 1; kappa[i] = Min(intvec(deg(h,tempIntVec1), deg(h,tempIntVec2))); }//filling kappa dbprint(p, dbprintWhitespace + "The Kappas for the respective variables are:"); dbprint(p,kappa); for (i = 1; i <= nvars(basering); i++) {//filling maxDegrees tempIntVec1 = 0:nvars(basering); tempIntVec1[i] = 1; maxDegrees[i] = deg(h,tempIntVec1); }//filling maxDegrees def R = basering; intvec n1 = degreeOfNthWeylPoly(pmax); intvec nk = degreeOfNthWeylPoly(pmin); list pBetweenDegrees = possibleHomogPartsInBetween(degreeOfNthWeylPoly(pmax), degreeOfNthWeylPoly(pmin), maxDegrees); int numberHomogPartsP = size(pBetweenDegrees); dbprint(p,dbprintWhitespace + "Possible degrees between pmax and pmin:"); dbprint(p,pBetweenDegrees); intvec m1 = degreeOfNthWeylPoly(qmax); intvec ml = degreeOfNthWeylPoly(qmin); list qBetweenDegrees = possibleHomogPartsInBetween(degreeOfNthWeylPoly(qmax), degreeOfNthWeylPoly(qmin), maxDegrees); int numberHomogPartsQ = size(qBetweenDegrees); dbprint(p,dbprintWhitespace + "Possible degrees between qmax and qmin:"); dbprint(p,qBetweenDegrees); ideal mons; list hBetweenDegrees = produceHomogListForProduct(pBetweenDegrees,qBetweenDegrees); int numberOfHomogPartsH = size(hBetweenDegrees); dbprint(p,dbprintWhitespace + "Possible degrees between hmax and hmin:"); dbprint(p,hBetweenDegrees); dbprint(p,dbprintWhitespace+" Extracting zero homog. parts of pmax, qmax, pmin, qmin and h."); //Extracting the zero homogeneous part of the given polynomials ideal pandqZero = pmax,pmin,qmax,qmin; for (i = 1; i<=nvars(basering) div 2; i++) {//Extracting zero homogeneous part variable for variable if (n1[i] > 0){pandqZero[1] = lift(var(i + nvars(basering) div 2)^n1[i],pandqZero[1])[1,1];} else{if (n1[i] < 0){pandqZero[1] = lift(var(i)^(-n1[i]),pandqZero[1])[1,1];} /* else{pandqZero[1] = pmax;} */} if (nk[i] > 0){pandqZero[2] = lift(var(i + nvars(basering) div 2)^nk[i],pandqZero[2])[1,1];} else{if (nk[i] < 0){pandqZero[2] = lift(var(i)^(-nk[i]),pandqZero[2])[1,1];} /* else{pandqZero[2] = pmin;} */} if (m1[i] > 0){pandqZero[3] = lift(var(i + nvars(basering) div 2)^m1[i],pandqZero[3])[1,1];} else{if (m1[i] < 0){pandqZero[3] = lift(var(i)^(-m1[i]),pandqZero[3])[1,1];} /* else{pandqZero[3] = qmax;} */} if (ml[i] > 0){pandqZero[4] = lift(var(i + nvars(basering) div 2)^ml[i],pandqZero[4])[1,1];} else{if (ml < 0){pandqZero[4] = lift(var(i)^(-ml[i]),pandqZero[4])[1,1];} /* else{pandqZero[4] = qmin;} */} }//Extracting zero homogeneous part variable for variable list hZeroinR = homogDistributionNthWeyl(h); for (i = 1; i<=size(hZeroinR);i++) {//Extracting the zero homogeneous parts of the homogeneous summands of h for (j = 1; j<=size(hZeroinR[i][1]); j++) {//Iterating through the different variables if (hZeroinR[i][1][j] > 0) { hZeroinR[i][2] = lift(var(j + nvars(basering) div 2)^hZeroinR[i][1][j],hZeroinR[i][2])[1,1]; } if (hZeroinR[i][1][j] < 0) { hZeroinR[i][2] = lift(var(j)^(-hZeroinR[i][1][j]),hZeroinR[i][2])[1,1]; } }//Iterating through the different variables }//Extracting the zero homogeneous parts of the homogeneous summands of h //Now we need to fill up the space between the h-parts: j = size(hZeroinR); hBetweenDegrees = reverse(hBetweenDegrees); list tempHList; /* for (i = size(hBetweenDegrees); i>0 ;i--) */ /* {//Filling up hzero with 0s in between */ /* ~; */ /* while (hBetweenDegrees[i] < hZeroinR[j][1]) */ /* { */ /* tempHList[i] = list(hBetweenDegrees[i],0); */ /* i--; */ /* } */ /* tempHList[i] = hZeroinR[j]; */ /* j--; */ /* }//Filling up hzero with 0s in between */ for (i = size(hBetweenDegrees); i>0 ;i--) { tempHList[i] = list(hBetweenDegrees[i],0); } for (i = 1; i <= size(hZeroinR); i++) { for (j = 1; j<=size(tempHList);j++) { if (hZeroinR[i][1] == tempHList[j][1]) { tempHList[j][2] = hZeroinR[i][2]; } } } hZeroinR = tempHList; //hBetweenDegrees = reverse(hBetweenDegrees); dbprint(p,dbprintWhitespace+" Done!"); dbprint(p,dbprintWhitespace+" Moving everything into the ring K[theta]"); ring KTheta = 0,(x(1..(nvars(basering) div 2)), d(1..(nvars(basering) div 2)), theta(1..(nvars(basering) div 2))),dp; setring(KTheta); ideal mapList; for (i = 1; i<=nvars(R) ; i++) {//filling the list of elements we want to map mapList[i] = var(i); }//filling the list of elements we want to map map thetamap = R, mapList; poly entry; ideal mons; ideal pandqZero; list hZeroinKTheta; intvec lExp; setring(R); //Starting with p and q for (k=1; k<=4; k++) {//Transforming pmax(0),qmax(0),pmin(0),qmin(0) in theta-polys mons = ideal(); for(i = 1; i<=size(pandqZero[k]);i++) {//Putting the monomials in a list mons[size(mons)+1] = pandqZero[k][i]; }//Putting the monomials in a list setring(KTheta); mons = thetamap(mons); for (i = 1; i<=size(mons);i++) {//transforming the monomials as monomials in the theta_i entry = leadcoef(mons[i]); lExp = leadexp(mons[i]); for (l = 1; l <=nvars(R) div 2; l++) { for (j = 0; j= 1;k--) {//Transforming the different homogeneous parts of h into polys in K[theta] mons = ideal(); for(i = 1; i<=size(hZeroinR[k][2]);i++) {//Putting the monomials in a list mons[size(mons)+1] = hZeroinR[k][2][i]; }//Putting the monomials in a list setring(KTheta); mons = thetamap(mons); for (i = 1; i<=size(mons);i++) {//transforming the monomials as monomials in theta entry = leadcoef(mons[i]); lExp = leadexp(mons[i]); for (l = 1; l <=nvars(R) div 2; l++) { for (j = 0; j=1; i--) { ps[i] = list(pBetweenDegrees[i],0); } ps[1][2] = pandqZero[2]; ps[numberHomogPartsP][2] = pandqZero[1]; list qs; for (i = numberHomogPartsQ; i>=1 ; i--) { qs[i] = list(qBetweenDegrees[i],0); } qs[1][2] = pandqZero[4]; qs[numberHomogPartsQ][2] = pandqZero[3]; qs = reverse(qs); ps = reverse(ps); pBetweenDegrees = reverse(pBetweenDegrees); qBetweenDegrees = reverse(qBetweenDegrees); tempIntVec2 = 0:nvars(R); for (i = 1; i<=size(kappa); i++) {tempIntVec2[i + size(kappa)] = kappa[i];} list coefficientIndices = possibleHomogPartsInBetween(kappa, 0:size(kappa), tempIntVec2); poly tempPoly; for (i = 2; i."); setring(R); return(list()); }//No solution in this case. Return the empty list if(vdim(slimgb(solutionSystemforqs + theThetas))==-1) {//My conjecture is that this would never happen //ERROR("This is an counterexample to your conjecture. We have infinitely many solutions"); //TODO: See, what we would do here dbprint(p,dbprintWhitespace+"There are infinitely many solution to this system. We will return the empty list."); setring(R); return(list()); }//My conjecture is that this would never happen else {//We have finitely many solutions if(vdim(slimgb(solutionSystemforqs+theThetas))==1) {//exactly one solution for (i = 2; i<= size(qs)-1;i++) { qs[i][2] = NF(qs[i][2],slimgb(solutionSystemforqs)); } setring(R); ideal finalMapList; for (i = 1; i<=nvars(R) div 2; i++) { finalMapList[i] = var(i)*var(i + (nvars(R) div 2)); } map backFromSolutionRing = solutionRing,finalMapList; list qs = backFromSolutionRing(qs); list result = list(0); for (i = 1; i<=size(qs); i++) { for (j= 1; j<=size(qs[i][1]); j++) { if (qs[i][1][j]>0){qs[i][2] = qs[i][2]*var(j + nvars(R) div 2)^qs[i][1][j];} if (qs[i][1][j]<0){qs[i][2] = qs[i][2]*var(j)^(-qs[i][1][j]);} } result[1] = result[1] + qs[i][2]; } dbprint(p,dbprintWhitespace+"Found one unique solution. Returning the result."); return(result); }//exactly one solution else {//We have more than one solution, but finitely many def ringForSolveLib = solve(solutionSystemforqs+theThetas, "nodisplay"); setring ringForSolveLib; list valuesForQs = list(); list tempValues; int validSol; for (i = 1; i<=size(SOL); i++) {//filtering integer solutions validSol = 1; for (j =1; j<=size(SOL[i]); j++) {//Checking every entry if it is integer or not if (SOL[i][j] - int(SOL[i][j])!=0) {//No integer solution validSol = 0; break; }//No integer solution }//Checking every entry if it is integer or not if (validSol) { tempValues = list(); for (j = 1; j<=size(SOL[i]); j++) {//filling the valuesforQs tempValues[j]= int(SOL[i][j]); }//filling the valuesforQs valuesForQs = valuesForQs + list(tempValues); } }//filtering integer solutions setring solutionRing; list differentQs = list(); ideal tempSolutionForQ; for (i = 1; i<=size(valuesForQs); i++) { differentQs[i] = qs; tempSolutionForQ = ideal(); for (j=(nvars(R) div 2)+1; j<=nvars(solutionRing);j++) {//filling solution ideal tempSolutionForQ[j-(nvars(R) div 2)] = var(j) - valuesForQs[i][j]; }//filling solution ideal for (j=2; j0) {differentQs[k][i][2] = differentQs[k][i][2]*var(j + nvars(R) div 2)^differentQs[k][i][1][j];} if (differentQs[k][i][1][j]<0) {differentQs[k][i][2] = differentQs[k][i][2]*var(j)^(-differentQs[k][i][1][j]);} } result[k] = result[k] + differentQs[k][i][2]; } } dbprint(p,dbprintWhitespace+"Found multiple solutions. Returning the result."); return(result); }//We have more than one solution, but finitely many }//We have finitely many solutions }//proc determineRestOfHomogPartsNthWeyl static proc produceHomogListForProduct(list homogParts1, list homogParts2) " INPUT: Two lists of integer vectors, homogParts1 and homogParts2, where the contained integer vectors all have the same size n. OUTPUT: One list of integer vectors, which have size n respectively. The entries are the set of possible integer vectors which result of a sum of an entry y in homogParts1 and an entry x in homogParts2. " {//produceHomogListForProduct int i; int j; int k; list p = reverse(sort(homogParts1)[1]); list q = reverse(sort(homogParts2)[1]); list result; intvec tempIntVec; for (i = 1; i<= size(homogParts1); i++) { for (j = 1; j<= size(homogParts2); j++) { tempIntVec = homogParts1[i] + homogParts2[j]; if (binarySearch(result,tempIntVec)==0) {//Element was not yet in result, add it result = result + list(tempIntVec); result = sort(result)[1]; }//Element was not yet in result, add it } } result = reverse(result); //Till here, we have a complete list with entries that are between hmax and hmin //Now, we need to filter this list. int isIn; for(i = 1; i<=size(p); i++) {//Checking, if homogparts[i] has a counterpart in homogparts2 isIn = 0; for (j = 1; j<=size(q); j++) {//iterating through the counterparts if(p[i] + q[j] == result[i]) { isIn = 1; break; } }//iterating through the counterparts if(!isIn) { result = delete(result,i); continue; } }//Checking, if homogparts[i] has a counterpart in homogparts2 for (i = 0; i inputElem) { last = middle -1; } else { return(middle); } } } return(0); }//binarySearch static proc possibleHomogPartsInBetween(intvec pmax, intvec pmin, intvec maxDegrees) " INPUT: Integer vectors pmax, pmin and maxDegrees. All but maxDegrees are of the same size, except from maxDegrees, which is double of the size of the rest. OUTPUT: A list of possible points in Z^n that can lie between pmax and pmin, sorted with respect to the lexicographic order from biggest to smallest (leftmost entry in the intvec is the biggest), represented as list of intvecs. " {//possibleHomogPartsInBetween if (size(pmax) != size(pmin) || 2*size(pmax)!=size(maxDegrees) || pmax<=pmin) { ERROR("pmax and pmin shall have the same size, and maxDegrees shall be double the size of both. Furhtermore, it must hold that pmax>pmin. The Input was: " + string(pmax) + ", " + string(pmin) + ", " + string(maxDegrees)); } list result; intvec tempIntVec = pmax; while(tempIntVec > pmin) { result = result + list(tempIntVec); tempIntVec = nextSmallerEntry(tempIntVec,pmin,maxDegrees); } result = result + list(pmin); return (sort(result)[1]); }//possibleHomogPartsInBetween static proc nextSmallerEntry(intvec pmax, intvec pmin, intvec maxDegrees) "INPUT: Integer vectors pmax, pmin and maxDegrees. maxDegrees has to have size 2*size(pmax), where pmin has to have the same size as pmax. OUTPUT: Counting down by lexicographical ordering, this function returns the next smaller entry after pmax, which is still bigger than pmin. " {//nextSmallerEntry if (pmax == pmin) {return (pmin);} if (size(pmax) == 1) { if (pmax <= pmin) {return(pmin);} else {return(pmax -1);} } int i; intvec recPmax = pmax[1..(size(pmax)-1)]; intvec recPmin = pmin[1..(size(pmin)-1)]; intvec recMaxDegrees = intvec(maxDegrees[1]); for (i = 2; i<=size(maxDegrees); i++) { if (i!=size(pmax) && i!= size(2*size(pmax))) { recMaxDegrees = recMaxDegrees,maxDegrees[i]; } } if (recPmax == recPmin) {//In this case, we can only possibly count down at our current position if (pmax[size(pmax)] > pmin[size(pmin)]) {return (recPmax,(pmax[size(pmax)]-1));} else {return(pmin);} }//In this case, we can only possibly count down at our current position else {//In this case, we can go down to the bounds given by maxDegrees if (pmax[size(pmax)] > -maxDegrees[size(pmax)]) { return (recPmax,(pmax[size(pmax)]-1)); } else { return(nextSmallerEntry(recPmax,recPmin,recMaxDegrees),maxDegrees[2*size(pmax)]); } }//In this case, we can go down to the bounds given by maxDegrees }//nextSmallerEntry static proc possibleHomogPartsInBetweenNonRecursive(intvec pmax, intvec pmin, intvec maxDegrees) " INPUT: Integer vectors pmax and maxDegrees. All but maxDegrees are of the same size, except from maxDegrees, which is double of the size of the rest. OUTPUT: A list of possible points in Z^n that can lie between pmax and pmin, sorted with respect to the lexicographic order from biggest to smallest (leftmost entry in the intvec is the biggest), represented as list of intvecs. " {//possibleHomogPartsInBetween if (size(pmax) != size(pmin) || 2*size(pmax)!=size(maxDegrees) || pmax<=pmin) { ERROR("pmax and pmin shall have the same size, and maxDegrees shall be double the size of both. Furhtermore, it must hold that pmax>pmin. The Input was: " + string(pmax) + ", " + string(pmin) + ", " + string(maxDegrees)); } list result = list(pmax); int pos; int i; int j; int k; list leftPart; int leftPartIsMaxAndMin; list possibleMiddles; list possibleRightParts = list(list()); list tempRightParts; intvec tempentry; for (pos = size(pmax); pos >=1 ; pos--) { leftPart = list(); leftPartIsMaxAndMin = 1; possibleMiddles = list(); for (i = 1; i < pos; i++) {//filling the left part leftPart[i] = pmax[i]; if(pmax[i]!=pmin[i]) {leftPartIsMaxAndMin = 0;} }//filling the left part if (leftPartIsMaxAndMin) { for (i = pmax[pos]-1; i>pmin[pos]; i--) {//possible entries for position pos possibleMiddles = possibleMiddles + list(i); }//possible entries for position pos } else { for (i = pmax[pos]-1; i>=-maxDegrees[pos]; i--) {//possible entries for position pos possibleMiddles = possibleMiddles + list(i); }//possible entries for position pos } for (i = 1; i<=size(possibleMiddles); i++) {//Adding possibilities to result for (j = 1; j<=size(possibleRightParts); j++) {//going through the right parts tempentry = intvec(0); for (k = 1; k<=size(leftPart);k++) { tempentry[k] = leftPart[k]; } if (size(leftPart)==0) {tempentry = possibleMiddles[i];} else {tempentry = tempentry,possibleMiddles[i];} for (k = 1; k<=size(possibleRightParts[j]) ; k++) { tempentry = tempentry, possibleRightParts[j][k]; } result = result + list(tempentry); }//going through the right parts }//Adding possibilities to result tempRightParts = list(); for (i = 1; i<=size(possibleRightParts);i++) { for (j = -maxDegrees[pos]; j <= maxDegrees[pos + size(pmax)]; j++) { tempRightParts = tempRightParts + list(list(j) + possibleRightParts[i]); } } possibleRightParts = tempRightParts; } //Now the last possible guys result = result + list(pmin); leftPart = list(); int positionWhereDifference = 1; for (i = 1; i<= size(pmin); i++) { if(pmax[i] != pmin[i]) { positionWhereDifference = i; break; } } possibleRightParts = list(list()); for (pos = size(pmin); pos > positionWhereDifference; pos--) {//Dealing with the minimal parts that we left out in the loop above leftPart = list(); possibleMiddles = list(); for (i = 1; i < pos; i++) {//filling up the left part leftPart[i] = pmin[i]; }//filling up the left part for (i = pmin[pos] +1 ; i<=maxDegrees[pos + size(pmin)] ; i++) { possibleMiddles = possibleMiddles + list(i); } for (i = 1; i<=size(possibleMiddles); i++) {//Adding possibilities to result for (j = 1; j<=size(possibleRightParts); j++) {//going through the right parts tempentry = intvec(0); for (k = 1; k<=size(leftPart);k++) { tempentry[k] = leftPart[k]; } if (size(leftPart)==0) {tempentry = possibleMiddles[i];} else {tempentry = tempentry,possibleMiddles[i];} for (k = 1; k<=size(possibleRightParts[j]) ; k++) { tempentry = tempentry, possibleRightParts[j][k]; } result = result + list(tempentry); }//going through the right parts }//Adding possibilities to result tempRightParts = list(); for (i = 1; i<=size(possibleRightParts);i++) { for (j = -maxDegrees[pos]; j <= maxDegrees[pos + size(pmax)]; j++) { tempRightParts = tempRightParts + list(list(j) + possibleRightParts[i]); } } possibleRightParts = tempRightParts; }//Dealing with the minimal parts that we left out in the loop above result = sort(result)[1]; if (result[1] != pmin) {result = insert(result,pmin);} return(result); }//possibleHomogPartsInBetween static proc gammaForTheta(int j1,int j2) " INPUT: Two integers j1 and j2 OUTPUT: A polynomial in the first variable of the given ring. It calculates the following function: / 1, if j1,j2>0 or j1,j2 <= 0 | prod_{kappa = 0}^{|j1|-1}(var(1)-kappa), if j1<0, j2>0, |j1|<=|j2| gamma_{j1,j2}:= < prod_{kappa = 0}^{j2-1}(var(1)-kappa-|j1|+|j2|), if j1<0, j2>0, |j1|>|j2| | prod_{kappa = 1}^{j1}(var(1)+kappa), if j1>0, j2<0, |j1|<=|j2| \ prod_{kappa = 1}^{|j2|}(\var(1)+kappa+|j1|-|j2|), if j1>0, j2<0, |j1|>|j2| ASSUMPTION: - Ring has at least one variable " {//gammaForTheta if (j1<=0 && j2 <=0) {return(1);} if (j1>=0 && j2 >=0){return(1);} poly result; int i; if (j1<0 && j2>0) {//case 2 or 3 from description above if (absValue(j1)<=absValue(j2)) {//Case 2 holds here result = 1; for (i = 0;i nvars(basering)) {ERROR("The size of the input vectors is bigger than the number of variables.");} int i; int j; ideal separateGammas; poly polyForPositionJ; for (j = 1; j <= size(j1); j++) {//Iterate through the \theta_j if (j1[j]<=0 && j2[j] <=0) { separateGammas[j] = 1; j++; continue; } if (j1[j]>=0 && j2[j] >=0) { separateGammas[j] = 1; j++; continue; } if (j1[j]<0 && j2[j]>0) {//case 2 or 3 from description above if (absValue(j1[j])<=absValue(j2[j])) {//Case 2 holds here polyForPositionJ = 1; for (i = 0;i=1;j--) { hath = result[i][j]*hath; tempList = extractHomogeneousDivisorsRight(hath); if(size(tempList[1])==1) {//We could not swap this element to the right break; }//We could not swap this element to the right dbprint(p,dbprintWhitespace+"A swapping (left) of an element was possible"); for(k = 1; k<=size(tempList);k++) { tempResult = insert(tempResult,result[i]); for (l = j;l<=posInhomog;l++) { tempResult[1] = delete(tempResult[1],j); } for (l = size(tempList[k]);l>=1;l--) { tempResult[1] = insert(tempResult[1],tempList[k][l],j-1); } } } hath = result[i][posInhomog]; for(j=posInhomog+1;j<=size(result[i]);j++) { hath = hath*result[i][j]; tempList = extractHomogeneousDivisorsLeft(hath); if(size(tempList[1])==1) {//We could not swap this element to the right break; }//We could not swap this element to the right dbprint(p,dbprintWhitespace+"A swapping (right) of an element was possible"); for(k = 1; k<=size(tempList);k++) { tempResult = insert(tempResult,result[i]); for (l=posInhomog; l<=j;l++) { tempResult[1] = delete(tempResult[1],posInhomog); } for (l = size(tempList[k]);l>=1;l--) { tempResult[1] = insert(tempResult[1],tempList[k][l],posInhomog-1); } } } }//Checking if we can swap left resp. right divisors result = result + tempResult; result = delete_dublicates_noteval(result); return(result); }//extractHomogeneousDivisors static proc extractHomogeneousDivisorsNthWeyl(poly h) "INPUT: A polynomial h in the nth Weyl algebra OUTPUT: If h is homogeneous with respect to the ZZ-grading on the nth Weyl algebra, then all factorizations of h are returned. If h is inhomogeneous, then a list l is returned whose entries are again lists k = [k_1,...,k_n], where k_1*...*k_n = h and there exists an i in {1,...,n}, such that k_i is inhomogeneous and there is no homogeneous polynomial that divides this k_i neither from the left nor from the right. All the other entries in k are homogeneous polynomials. GENERAL ASSUMPTIONS: - The basering is the nth Weyl algebra and has the form, that the first n variables represent x1, ..., xn, and the second n variables do represent the d1, ..., dn. " {//extractHomogeneousDivisorsNthWeyl int p=printlevel-voice+2; // for dbprint string dbprintWhitespace = ""; int i; int j; int k; int l; list result; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} if (homogwithorderNthWeyl(h)) {//given polynomial was homogeneous already dbprint(p,dbprintWhitespace+"Polynomial was homogeneous. Just returning all factorizations."); result = homogfacNthWeyl_all(h); for (i = 1; i<=size(result);i++) {//removing the first entry (coefficient) from the list result result[i] = delete(result[i],1); }//removing the first entry (coefficient) from the list result return(result); }//given polynomial was homogeneous already dbprint(p,dbprintWhitespace+"Calculating list with all homogeneous left divisors extracted"); list leftDivisionPossibilities = extractHomogeneousDivisorsLeftNthWeyl(h); dbprint(p,dbprintWhitespace+"Done. The result is:"); dbprint(p,leftDivisionPossibilities); dbprint(p,dbprintWhitespace+"Calculating list with all homogeneous Right divisors extracted"); list rightDivisionPossibilities = extractHomogeneousDivisorsRightNthWeyl(h); dbprint(p,dbprintWhitespace+"Done. The result is:"); dbprint(p,rightDivisionPossibilities); list tempList; dbprint(p,dbprintWhitespace+"Calculating remaining right and left homogeneous divisors"); for (i = 1; i<=size(leftDivisionPossibilities); i++) {//iterating through the list with extracted left divisors tempList = extractHomogeneousDivisorsRightNthWeyl (leftDivisionPossibilities[i][size(leftDivisionPossibilities[i])]); leftDivisionPossibilities[i] = delete(leftDivisionPossibilities[i], size(leftDivisionPossibilities[i])); for (j=1;j<=size(tempList);j++) {//Updating the list for Result tempList[j] = leftDivisionPossibilities[i] + tempList[j]; }//Updating the list for Result result = result + tempList; }//iterating through the list with extracted left divisors for (i = 1; i<=size(rightDivisionPossibilities); i++) {//iterating through the list with extracted right divisors tempList = extractHomogeneousDivisorsLeftNthWeyl(rightDivisionPossibilities[i][1]); rightDivisionPossibilities[i] = delete(rightDivisionPossibilities[i],1); for (j=1;j<=size(tempList);j++) {//Updating the list for Result tempList[j] = tempList[j]+rightDivisionPossibilities[i]; }//Updating the list for Result result = result + tempList; }//iterating through the list with extracted right divisors dbprint(p,dbprintWhitespace+"Done"); int posInhomog; poly hath = 1; list tempResult; dbprint(p,dbprintWhitespace+"Checking if we can swap left resp. right divisors and updating result."); for (i = 1; i<= size(result); i++) {//Checking if we can swap left resp. right divisors for (j = 1; j<=size(result[i]);j++) {//finding the position of the inhomogeneous element in the list if(!homogwithorderNthWeyl(result[i][j])) { posInhomog = j; break; } }//finding the position of the inhomogeneous element in the list hath = result[i][posInhomog]; for(j=posInhomog-1;j>=1;j--) { hath = result[i][j]*hath; tempList = extractHomogeneousDivisorsRightNthWeyl(hath); if(size(tempList[1])==1) {//We could not swap this element to the right break; }//We could not swap this element to the right dbprint(p,dbprintWhitespace+"A swapping (left) of an element was possible"); for(k = 1; k<=size(tempList);k++) { tempResult = insert(tempResult,result[i]); for (l = j;l<=posInhomog;l++) { tempResult[1] = delete(tempResult[1],j); } for (l = size(tempList[k]);l>=1;l--) { tempResult[1] = insert(tempResult[1],tempList[k][l],j-1); } } } hath = result[i][posInhomog]; for(j=posInhomog+1;j<=size(result[i]);j++) { hath = hath*result[i][j]; tempList = extractHomogeneousDivisorsLeftNthWeyl(hath); if(size(tempList[1])==1) {//We could not swap this element to the right break; }//We could not swap this element to the right dbprint(p,dbprintWhitespace+"A swapping (right) of an element was possible"); for(k = 1; k<=size(tempList);k++) { tempResult = insert(tempResult,result[i]); for (l=posInhomog; l<=j;l++) { tempResult[1] = delete(tempResult[1],posInhomog); } for (l = size(tempList[k]);l>=1;l--) { tempResult[1] = insert(tempResult[1],tempList[k][l],posInhomog-1); } } } }//Checking if we can swap left resp. right divisors result = result + tempResult; result = delete_dublicates_noteval(result); return(result); }//extractHomogeneousDivisorsNthWeyl static proc extractHomogeneousDivisorsLeft(poly h) "INPUT: A polynomial h in the first Weyl algebra OUTPUT: If h is homogeneous, then all factorizations of h are returned. If h is inhomogeneous, then a list l is returned whose entries are again lists k = [k_1,...,k_n], where k_1*...*k_n = h. The entry k_n is inhomogeneous and has no other homogeneous left divisors any more. All the other entries in k are homogeneous polynomials. " {//extractHomogeneousDivisorsLeft int p=printlevel-voice+2; // for dbprint string dbprintWhitespace = ""; int i;int j; int k; list result; poly hath; list recResult; map invo = basering,-var(1),var(2); for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} if (homogwithorder(h,intvec(-1,1))) {//given polynomial was homogeneous already dbprint(p,dbprintWhitespace+"Polynomial was homogeneous. Just returning all factorizations."); result = homogfacFirstWeyl_all(h); for (i = 1; i<=size(result);i++) {//removing the first entry (coefficient) from the list result result[i] = delete(result[i],1); }//removing the first entry (coefficient) from the list result return(result); }//given polynomial was homogeneous already list hlist = homogDistribution(h); dbprint(p,dbprintWhitespace+ " Computing factorizations of all homogeneous summands."); for (i = 1; i<= size(hlist); i++) { hlist[i] = homogfacFirstWeyl_all(hlist[i][2]); if (size(hlist[i][1])==1) {//One homogeneous part just has a trivial factorization if(hlist[i][1][1] == 0) { hlist = delete(hlist,i); continue; } else { return(list(list(h))); } }//One homogeneous part just has a trivial factorization } dbprint(p,dbprintWhitespace+ " Done."); dbprint(p,dbprintWhitespace+ " Trying to find Left divisors"); list alreadyConsideredCandidates; poly candidate; int isCandidate; for (i = 1; i<=size(hlist[1]);i++) {//Finding candidates for homogeneous left divisors of h candidate = hlist[1][i][2]; isCandidate = 0; for (j=1;j<=size(alreadyConsideredCandidates);j++) { if(alreadyConsideredCandidates[j] == candidate) { isCandidate =1; break; } } if(isCandidate) { i++; continue; } else { alreadyConsideredCandidates = alreadyConsideredCandidates + list(candidate); } dbprint(p,dbprintWhitespace+"Checking if "+string(candidate)+" is a homogeneous left divisor"); for (j = 2; j<=size(hlist);j++) {//Iterating through the other homogeneous parts isCandidate = 0; for(k=1; k<=size(hlist[j]);k++) { if(hlist[j][k][2]==candidate) { isCandidate = 1; break; } } if(!isCandidate) { break; } }//Iterating through the other homogeneous parts if(isCandidate) {//candidate was really a left divisor dbprint(p,dbprintWhitespace+string(candidate)+" is a homogeneous left divisor"); hath = involution(lift(involution(candidate,invo),involution(h,invo))[1,1],invo); recResult = extractHomogeneousDivisorsLeft(hath); for (j = 1; j<=size(recResult); j++) { recResult[j] = insert(recResult[j],candidate); } result = result + recResult; }//Candidate was really a left divisor }//Finding candidates for homogeneous left divisors of h if (size(result)==0) { return(list(list(h))); } return(result); }//extractHomogeneousDivisorsLeft static proc extractHomogeneousDivisorsLeftNthWeyl(poly h) "INPUT: A polynomial h in the nth Weyl algebra OUTPUT: If h is homogeneous with respect to the ZZ grading on the nth Weyl algebra, then all factorizations of h are returned. If h is inhomogeneous, then a list l is returned whose entries are again lists k = [k_1,...,k_n], where k_1*...*k_n = h. The entry k_n is inhomogeneous and has no other homogeneous left divisors any more. All the other entries in k are homogeneous polynomials. GENERAL ASSUMPTIONS: - The basering is the nth Weyl algebra and has the form, that the first n variables represent x1, ..., xn, and the second n variables do represent the d1, ..., dn. " {//extractHomogeneousDivisorsLeftNthWeyl int p=printlevel-voice+2; // for dbprint string dbprintWhitespace = ""; int i;int j; int k; list result; poly hath; list recResult; ideal invoIdeal; for (i = 1; i <= nvars(basering); i++) {//Filling the mapping rules for the involution map if (i <= nvars(basering) div 2) {invoIdeal[i] = -var(i);} else {invoIdeal[i] = var(i);} }//Filling the mapping rules for the involution map map invo = basering,invoIdeal; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} if (homogwithorderNthWeyl(h)) {//given polynomial was homogeneous already dbprint(p,dbprintWhitespace+"Polynomial was homogeneous. Just returning all factorizations."); result = homogfacNthWeyl_all(h); for (i = 1; i<=size(result);i++) {//removing the first entry (coefficient) from the list result result[i] = delete(result[i],1); }//removing the first entry (coefficient) from the list result return(result); }//given polynomial was homogeneous already list hlist = homogDistributionNthWeyl(h); dbprint(p,dbprintWhitespace+ " Computing factorizations of all homogeneous summands."); for (i = 1; i<= size(hlist); i++) { hlist[i] = homogfacNthWeyl_all(hlist[i][2]); if (size(hlist[i][1])==1) {//One homogeneous part just has a trivial factorization if(hlist[i][1][1] == 0) { hlist = delete(hlist,i); continue; } else { return(list(list(h))); } }//One homogeneous part just has a trivial factorization } dbprint(p,dbprintWhitespace+ " Done."); dbprint(p,dbprintWhitespace+ " Trying to find Left divisors"); list alreadyConsideredCandidates; poly candidate; int isCandidate; for (i = 1; i<=size(hlist[1]);i++) {//Finding candidates for homogeneous left divisors of h candidate = hlist[1][i][2]; isCandidate = 0; for (j=1;j<=size(alreadyConsideredCandidates);j++) { if(alreadyConsideredCandidates[j] == candidate) { isCandidate =1; break; } } if(isCandidate) { i++; continue; } else { alreadyConsideredCandidates = alreadyConsideredCandidates + list(candidate); } dbprint(p,dbprintWhitespace+"Checking if "+string(candidate)+" is a homogeneous left divisor"); for (j = 2; j<=size(hlist);j++) {//Iterating through the other homogeneous parts isCandidate = 0; for(k=1; k<=size(hlist[j]);k++) { if(hlist[j][k][2]==candidate) { isCandidate = 1; break; } } if(!isCandidate) { break; } }//Iterating through the other homogeneous parts if(isCandidate) {//candidate was really a left divisor dbprint(p,dbprintWhitespace+string(candidate)+" is a homogeneous left divisor"); hath = involution(lift(involution(candidate,invo),involution(h,invo))[1,1],invo); recResult = extractHomogeneousDivisorsLeftNthWeyl(hath); for (j = 1; j<=size(recResult); j++) { recResult[j] = insert(recResult[j],candidate); } result = result + recResult; }//Candidate was really a left divisor }//Finding candidates for homogeneous left divisors of h if (size(result)==0) { return(list(list(h))); } return(result); }//extractHomogeneousDivisorsLeftNthWeyl /* Interesting test cases: h=x1^2*x2*x3*d1*d2*d3+x1*x2^2*x3*d1*d2*d3+x1*x2*x3*d1^2*d2*d3+x1*x2*x3*d1*d3+x1*x2*x3*d2*d3 h = x1*(d1+x1); h = x1*d2 + x3*d3; h = x1*x2*d2^2+x2^2*d2*d3+x1*d2+2*x2*d3 */ static proc extractHomogeneousDivisorsRight(poly h) "INPUT: A polynomial h in the first Weyl algebra OUTPUT: If h is homogeneous, then all factorizations of h are returned. If h is inhomogeneous, then a list l is returned whose entries are again lists k = [k_1,...,k_n], where k_1*...*k_n = h. The entry k_1 is inhomogeneous and has no other homogeneous right divisors any more. All the other entries in k are homogeneous polynomials. " {//extractHomogeneousDivisorsRight int p=printlevel-voice+2; // for dbprint string dbprintWhitespace = ""; int i;int j; int k; list result; poly hath; list recResult; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} if (homogwithorder(h,intvec(-1,1))) {//given polynomial was homogeneous already dbprint(p,dbprintWhitespace+"Polynomial was homogeneous. Just returning all factorizations."); result = homogfacFirstWeyl_all(h); for (i = 1; i<=size(result);i++) {//removing the first entry (coefficient) from the list result result[i] = delete(result[i],1); }//removing the first entry (coefficient) from the list result return(result); }//given polynomial was homogeneous already list hlist = homogDistribution(h); dbprint(p,dbprintWhitespace+ " Computing factorizations of all homogeneous summands."); for (i = 1; i<= size(hlist); i++) { hlist[i] = homogfacFirstWeyl_all(hlist[i][2]); if (size(hlist[i][1])==1) {//One homogeneous part just has a trivial factorization if(hlist[i][1][1] == 0) { hlist = delete(hlist,i); continue; } else { return(list(list(h))); } }//One homogeneous part just has a trivial factorization } dbprint(p,dbprintWhitespace+ " Done."); dbprint(p,dbprintWhitespace+ " Trying to find right divisors"); list alreadyConsideredCandidates; poly candidate; int isCandidate; for (i = 1; i<=size(hlist[1]);i++) {//Finding candidates for homogeneous left divisors of h candidate = hlist[1][i][size(hlist[1][i])]; isCandidate = 0; for (j=1;j<=size(alreadyConsideredCandidates);j++) { if(alreadyConsideredCandidates[j] == candidate) { isCandidate =1; break; } } if(isCandidate) { i++; continue; } else { alreadyConsideredCandidates = alreadyConsideredCandidates + list(candidate); } dbprint(p,dbprintWhitespace+"Checking if "+string(candidate)+" is a homogeneous r-divisor"); for (j = 2; j<=size(hlist);j++) {//Iterating through the other homogeneous parts isCandidate = 0; for(k=1; k<=size(hlist[j]);k++) { if(hlist[j][k][size(hlist[j][k])]==candidate) { isCandidate = 1; break; } } if(!isCandidate) { break; } }//Iterating through the other homogeneous parts if(isCandidate) {//candidate was really a left divisor dbprint(p,dbprintWhitespace+string(candidate)+" is a homogeneous right divisor"); hath = lift(candidate,h)[1,1]; recResult = extractHomogeneousDivisorsRight(hath); for (j = 1; j<=size(recResult); j++) { recResult[j] = insert(recResult[j],candidate,size(recResult[j])); } result = result + recResult; }//Candidate was really a left divisor }//Finding candidates for homogeneous left divisors of h if (size(result)==0) { result = list(list(h)); } return(result); }//extractHomogeneousDivisorsRight static proc extractHomogeneousDivisorsRightNthWeyl(poly h) "INPUT: A polynomial h in the nth Weyl algebra OUTPUT: If h is homogeneous with respect to the ZZ grading on the nth Weyl algebra, then all factorizations of h are returned. If h is inhomogeneous, then a list l is returned whose entries are again lists k = [k_1,...,k_n], where k_1*...*k_n = h. The entry k_1 is inhomogeneous and has no other homogeneous right divisors any more. All the other entries in k are homogeneous polynomials. GENERAL ASSUMPTIONS: - The basering is the nth Weyl algebra and has the form, that the first n variables represent x1, ..., xn, and the second n variables do represent the d1, ..., dn. " {//extractHomogeneousDivisorsRightNthWeyl int p=printlevel-voice+2; // for dbprint string dbprintWhitespace = ""; int i;int j; int k; list result; poly hath; list recResult; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} if (homogwithorderNthWeyl(h)) {//given polynomial was homogeneous already dbprint(p,dbprintWhitespace+"Polynomial was homogeneous. Just returning all factorizations."); result = homogfacNthWeyl_all(h); for (i = 1; i<=size(result);i++) {//removing the first entry (coefficient) from the list result result[i] = delete(result[i],1); }//removing the first entry (coefficient) from the list result return(result); }//given polynomial was homogeneous already list hlist = homogDistributionNthWeyl(h); dbprint(p,dbprintWhitespace+ " Computing factorizations of all homogeneous summands."); for (i = 1; i<= size(hlist); i++) { hlist[i] = homogfacNthWeyl_all(hlist[i][2]); if (size(hlist[i][1])==1) {//One homogeneous part just has a trivial factorization if(hlist[i][1][1] == 0) { hlist = delete(hlist,i); continue; } else { return(list(list(h))); } }//One homogeneous part just has a trivial factorization } dbprint(p,dbprintWhitespace+ " Done."); dbprint(p,dbprintWhitespace+ " Trying to find right divisors"); list alreadyConsideredCandidates; poly candidate; int isCandidate; for (i = 1; i<=size(hlist[1]);i++) {//Finding candidates for homogeneous left divisors of h candidate = hlist[1][i][size(hlist[1][i])]; isCandidate = 0; for (j=1;j<=size(alreadyConsideredCandidates);j++) { if(alreadyConsideredCandidates[j] == candidate) { isCandidate =1; break; } } if(isCandidate) { i++; continue; } else { alreadyConsideredCandidates = alreadyConsideredCandidates + list(candidate); } dbprint(p,dbprintWhitespace+"Checking if "+string(candidate)+" is a homogeneous r-divisor"); for (j = 2; j<=size(hlist);j++) {//Iterating through the other homogeneous parts isCandidate = 0; for(k=1; k<=size(hlist[j]);k++) { if(hlist[j][k][size(hlist[j][k])]==candidate) { isCandidate = 1; break; } } if(!isCandidate) { break; } }//Iterating through the other homogeneous parts if(isCandidate) {//candidate was really a left divisor dbprint(p,dbprintWhitespace+string(candidate)+" is a homogeneous right divisor"); hath = lift(candidate,h)[1,1]; recResult = extractHomogeneousDivisorsRightNthWeyl(hath); for (j = 1; j<=size(recResult); j++) { recResult[j] = insert(recResult[j],candidate,size(recResult[j])); } result = result + recResult; }//Candidate was really a left divisor }//Finding candidates for homogeneous left divisors of h if (size(result)==0) { result = list(list(h)); } return(result); }//extractHomogeneousDivisorsRightNthWeyl static proc fromZeroHomogToThetaPoly(poly h) " //DEPRECATED INPUT: A polynomial h in the first Weyl algebra, homogeneous of degree 0 OUTPUT: The ring Ktheta with a polynomial result representing h as polynomial in theta ASSUMPTIONS: - h is homogeneous of degree 0 with respect to the [-1,1] weight vector - The basering is the first Weyl algebra " {//proc fromZeroHomogToThetaPoly int i; int j; list mons; if(!homogwithorder(h,intvec(-1,1))) {//Input not a homogeneous polynomial causes an error ERROR("The input was not a homogeneous polynomial"); }//Input not a homogeneous polynomial causes an error if(deg(h,intvec(-1,1))!=0) {//Input does not have degree 0 ERROR("The input did not have degree 0"); }//Input does not have degree 0 for(i = 1; i<=size(h);i++) {//Putting the monomials in a list mons = mons+list(h[i]); }//Putting the monomials in a list ring KTheta = 0,(x,y,theta),dp; setring KTheta; map thetamap = r,x,y; list mons = thetamap(mons); poly entry; for (i = 1; i<=size(mons);i++) {//transforming the monomials as monomials in theta entry = leadcoef(mons[i]); for (j = 0; j0) { tempList = getAllCombOfHomogFact(f1); for (i = 1; i<=size(tempList); i++) {//Every combination combined with the coefficient possibilities for (j = 1; j<=size(coeffTuplesMax); j++) {//iterating through the possible coefficient choices pqmax = pqmax + list(list(coeffTuplesMax[j][1]*tempList[i][1], coeffTuplesMax[j][2]*tempList[i][2])); }//iterating through the possible coefficient choices }//Every combination combined with the coefficient possibilities for (i = 1; i<=size(coeffTuplesMax); i++) { pqmax = pqmax + list(list(coeffTuplesMax[i][1],maxh/coeffTuplesMax[i][1])); pqmax = pqmax + list(list(maxh/coeffTuplesMax[i][2],coeffTuplesMax[i][2])); } } }//the maximal homogeneous factor is not a constant //Now we go to pqmin if (size(f2[1]) == 1) {//the minimal homogeneous factor is a constant pqmin = coeffTuplesMin; }//the minimal homogeneous factor is a constant else {//the minimal homogeneous factor is not a constant for (i = 1; i<=size(f2); i++) {//We can forget about the first coefficient now. Therefore we will delete him from the list. f2[i] = delete(f2[i],1); if(size(f2[i])==1) {//trivial thing for (j = 1; j<=size(coeffTuplesMin); j++) { pqmin = pqmin + list(list(coeffTuplesMin[j][1],coeffTuplesMin[j][2]*f2[i][1])); pqmin = pqmin + list(list(coeffTuplesMin[j][1]*f2[i][1],coeffTuplesMin[j][2])); } f2 = delete(f2,i); continue; } }//We can forget about the first coefficient now. Therefore we will delete him from the list. if(size(f2)>0) { tempList = getAllCombOfHomogFact(f2); for (i = 1; i<=size(tempList); i++) {//Every combination combined with the coefficient possibilities for (j = 1; j<=size(coeffTuplesMin); j++) {//iterating through the possible coefficient choices pqmin = pqmin + list(list(coeffTuplesMin[j][1]*tempList[i][1], coeffTuplesMin[j][2]*tempList[i][2])); }//iterating through the possible coefficient choices }//Every combination combined with the coefficient possibilities for (i = 1; i<=size(coeffTuplesMin); i++) { pqmin = pqmin + list(list(coeffTuplesMin[i][1],minh/coeffTuplesMin[i][1])); pqmin = pqmin + list(list(minh/coeffTuplesMin[i][2],coeffTuplesMin[i][2])); } } }//the minimal homogeneous factor is not a constant //and now we combine them together to obtain all possibilities. for (i = 1; i<=size(pqmax); i++) {//iterate over the maximal homogeneous combination possibilities for (j = 1; j<=size(pqmin); j++) {//iterate over the minimal homogeneous combiniation possibilities if (deg(pqmax[i][1], ivm11)>=deg(pqmin[j][1],ivm11) and deg(pqmax[i][2], ivm11)>=deg(pqmin[j][2],ivm11)) { if (pqmax[i][1]+pqmin[j][1]!=0 and pqmax[i][2]+pqmin[j][2]!=0) { if (deg(h,ivm11)<=deg(h-(pqmax[i][1]+pqmin[j][1])*(pqmax[i][2]+pqmin[j][2]),ivm11)) { j++; continue; } if (deg(h,iv1m1)<=deg(h-(pqmax[i][1]+pqmin[j][1])*(pqmax[i][2]+pqmin[j][2]),iv1m1)) { j++; continue; } result = result +list(list(pqmax[i][1]+pqmin[j][1],pqmax[i][2]+pqmin[j][2])); } } }//iterate over the minimal homogeneous combiniation possibilities }//iterate over the maximal homogeneous combination possibilities //Now deleting double entries result = delete_dublicates_noteval(result); return(result); }//proc computeCombinationsMinMaxHomog static proc computeCombinationsMinMaxHomogNthWeyl(poly h) "Input: A polynomial h in the nth Weyl Algebra Output: Combinations of the form (p_max + p_min)(q_max + q_min), such that p_max, p_min, q_max and q_min are homogeneous and p_max*q_max equals the maximal homogeneous part in h, and p_max * q_max equals the minimal homogeneous part in h. GENERAL ASSUMPTIONS: - h is not homogeneous. "{//proc computeCombinationsMinMaxHomogNthWeyl int p=printlevel-voice+2; // for dbprint string dbprintWhitespace = ""; int i; int j; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} list hList = homogDistributionNthWeyl(h); dbprint(p,dbprintWhitespace + "Computing maximal and minimal homogeneous part of h"); poly maxh = hList[size(hList)][2]; poly minh = hList[1][2]; dbprint(p,dbprintWhitespace + "Done. They are:"); dbprint(p,string(maxh) + ", " + string(minh)); dbprint(p, dbprintWhitespace + "Computing their respective homogeneous factorizations"); list f1 = homogfacNthWeyl_all(maxh); list f2 = homogfacNthWeyl_all(minh); dbprint(p,dbprintWhitespace + "Done."); list result = list(); list pqmax = list(); list pqmin = list(); list tempList = list(); //First, we are going to deal with our most hated guys: The Coefficients. // dbprint(p,dbprintWhitespace + "We get all combinations for the coefficient of the maximal homogeneous part"); list coeffTuplesMax = getAllCoeffTuplesComb(factorizeInt(number(f1[1][1]))); //We can assume without loss of generality, that p_max has a //nonnegative leading coefficient for (i = 1; i<=size(coeffTuplesMax);i++) {//Deleting all tuples with negative entries for p_max if (coeffTuplesMax[i][1]<0) { coeffTuplesMax = delete(coeffTuplesMax,i); continue; } }//Deleting all tuples with negative entries for p_max dbprint(p,dbprintWhitespace + "Done. The Combinations are:"); dbprint(p,coeffTuplesMax); dbprint(p,dbprintWhitespace + "We get all combinations for the coefficient of the minimal homogeneous part"); list coeffTuplesMin = getAllCoeffTuplesComb(factorizeInt(number(f2[1][1]))); dbprint(p,dbprintWhitespace + "Done. The Combinations are:"); dbprint(p,coeffTuplesMin); //Now, we will be actally dealing with the Combinations. //Let's start with the pqmax if (size(f1[1]) == 1) {//the maximal homogeneous factor is a constant dbprint(p,dbprintWhitespace + "the maximal homogeneous factor is a constant."); pqmax = coeffTuplesMax; }//the maximal homogeneous factor is a constant else {//the maximal homogeneous factor is not a constant dbprint(p,dbprintWhitespace + "Deleting the first list entry in each list (constant factor)."); for (i = 1; i<=size(f1); i++) {//We can forget about the first coefficient now. Therefore we will delete him from the list. f1[i] = delete(f1[i],1); if(size(f1[i])==1) {//trivial thing for (j = 1; j<=size(coeffTuplesMax); j++) { pqmax = pqmax + list(list(coeffTuplesMax[j][1],coeffTuplesMax[j][2]*f1[i][1])); pqmax = pqmax + list(list(coeffTuplesMax[j][1]*f1[i][1],coeffTuplesMax[j][2])); } f1 = delete(f1,i); continue; }//trivial thing }//We can forget about the first coefficient now. Therefore we will delete him from the list. dbprint(p,dbprintWhitespace + "Done."); dbprint(p,dbprintWhitespace + "Putting all possible pre-coefficients besides the entries in pqmax."); if (size(f1)>0) { tempList = getAllCombOfHomogFact(f1); for (i = 1; i<=size(tempList); i++) {//Every combination combined with the coefficient possibilities for (j = 1; j<=size(coeffTuplesMax); j++) {//iterating through the possible coefficient choices pqmax = pqmax + list(list(coeffTuplesMax[j][1]*tempList[i][1], coeffTuplesMax[j][2]*tempList[i][2])); }//iterating through the possible coefficient choices }//Every combination combined with the coefficient possibilities for (i = 1; i<=size(coeffTuplesMax); i++) { pqmax = pqmax + list(list(coeffTuplesMax[i][1],maxh/coeffTuplesMax[i][1])); pqmax = pqmax + list(list(maxh/coeffTuplesMax[i][2],coeffTuplesMax[i][2])); } } dbprint(p,dbprintWhitespace + "Done."); }//the maximal homogeneous factor is not a constant dbprint(p, dbprintWhitespace + "Doing the same for f2"); //Now we go to pqmin if (size(f2[1]) == 1) {//the minimal homogeneous factor is a constant pqmin = coeffTuplesMin; }//the minimal homogeneous factor is a constant else {//the minimal homogeneous factor is not a constant for (i = 1; i<=size(f2); i++) {//We can forget about the first coefficient now. Therefore we will delete him from the list. f2[i] = delete(f2[i],1); if(size(f2[i])==1) {//trivial thing for (j = 1; j<=size(coeffTuplesMin); j++) { pqmin = pqmin + list(list(coeffTuplesMin[j][1],coeffTuplesMin[j][2]*f2[i][1])); pqmin = pqmin + list(list(coeffTuplesMin[j][1]*f2[i][1],coeffTuplesMin[j][2])); } f2 = delete(f2,i); continue; } }//We can forget about the first coefficient now. Therefore we will delete him from the list. if(size(f2)>0) { tempList = getAllCombOfHomogFact(f2); for (i = 1; i<=size(tempList); i++) {//Every combination combined with the coefficient possibilities for (j = 1; j<=size(coeffTuplesMin); j++) {//iterating through the possible coefficient choices pqmin = pqmin + list(list(coeffTuplesMin[j][1]*tempList[i][1], coeffTuplesMin[j][2]*tempList[i][2])); }//iterating through the possible coefficient choices }//Every combination combined with the coefficient possibilities for (i = 1; i<=size(coeffTuplesMin); i++) { pqmin = pqmin + list(list(coeffTuplesMin[i][1],minh/coeffTuplesMin[i][1])); pqmin = pqmin + list(list(minh/coeffTuplesMin[i][2],coeffTuplesMin[i][2])); } } }//the minimal homogeneous factor is not a constant dbprint(p,dbprintWhitespace + "Done."); //and now we combine them together to obtain all possibilities. for (i = 1; i<=size(pqmax); i++) {//iterate over the maximal homogeneous combination possibilities for (j = 1; j<=size(pqmin); j++) {//iterate over the minimal homogeneous combiniation possibilities if (degreeOfNthWeylPoly(pqmax[i][1])>=degreeOfNthWeylPoly(pqmin[j][1]) and degreeOfNthWeylPoly(pqmax[i][2])>=degreeOfNthWeylPoly(pqmin[j][2])) { if (pqmax[i][1]+pqmin[j][1]!=0 and pqmax[i][2]+pqmin[j][2]!=0) { if (h-(pqmax[i][1]+pqmin[j][1])*(pqmax[i][2]+pqmin[j][2])==0) { /*REMARK: This part here is different from factoring the first Weyl algebra. As the output of degreeOfNthWeylPoly is in general an intvec instead of an int, we cannot say deg(0)=-1; Therefore, we need to catch the 0-case at this point, i.e. min and max homog are combined equal to h. */ result = result +list(list(pqmax[i][1]+pqmin[j][1],pqmax[i][2]+pqmin[j][2])); j++;continue; } if (degreeOfNthWeylPoly(h)<= degreeOfNthWeylPoly(h-(pqmax[i][1]+pqmin[j][1])*(pqmax[i][2]+pqmin[j][2]))) { j++; continue; } if (degreeOfNthWeylPolyInverted(h)<= degreeOfNthWeylPolyInverted(h-(pqmax[i][1]+pqmin[j][1])*(pqmax[i][2]+pqmin[j][2]))) { j++; continue; } result = result +list(list(pqmax[i][1]+pqmin[j][1],pqmax[i][2]+pqmin[j][2])); } } }//iterate over the minimal homogeneous combiniation possibilities }//iterate over the maximal homogeneous combination possibilities //Now deleting double entries result = delete_dublicates_noteval(result); return(result); }//proc computeCombinationsMinMaxHomogNthWeyl static proc getAllCombOfHomogFact(list l) "Gets called in computeCombinationsMinMaxHomog. It gets a list of different homogeneous factorizations of one homogeneous polynomial and returns the possibilities to combine them into two factors. Assumptions: - The list does not contain the first coefficient. - The list contains at least one list with two elements." {//proc getAllCombOfHomogFact list result; list leftAndRightHandSides; int i; int j; list tempset; if (size(l)==1 and size(l[1])==2) { result = result + list(list(l[1][1],l[1][2])); return(result); } leftAndRightHandSides = getPossibilitiesForRightSides(l); for (i = 1; i<=size(leftAndRightHandSides); i++) { result =result+list(list(leftAndRightHandSides[i][1],product(leftAndRightHandSides[i][2][1]))); //tidy up the right hand sides, because, if it is just one irreducible factor, we are done for (j = 1; j<=size(leftAndRightHandSides[i][2]);j++) {//Tidy up right hand sides if (size(leftAndRightHandSides[i][2][j])<2) {//Element can be dismissed leftAndRightHandSides[i][2] = delete(leftAndRightHandSides[i][2],j); continue; }//Element can be dismissed }//Tidy up right hand sides if (size(leftAndRightHandSides[i][2])>0) { tempset = getAllCombOfHomogFact(leftAndRightHandSides[i][2]); for (j = 1; j<=size(tempset);j++) {//multiplying the first factor with the left hand side result = result + list(list(leftAndRightHandSides[i][1]*tempset[j][1],tempset[j][2])); }//multiplying the first factor with the left hand side } } return(result); }//proc getAllCombOfHomogFact static proc getPossibilitiesForRightSides(list l) "Given a list of different factorizations l, this function returns a list of the form (a,{(a_2,...,a_n)| (a,a_2,...,a_n) in A})" {//getPossibilitiesForRightSide list templ = l; list result; poly firstElement; list rightSides; list tempRightSide; int i; int j; while (size(templ)>0) { firstElement = templ[1][1]; rightSides = list(); for (i = 1; i<= size(templ); i++) { if (templ[i][1] == firstElement) {//save the right sides tempRightSide = list(); for (j = 2; j<=size(templ[i]);j++) { tempRightSide = tempRightSide + list(templ[i][j]); } if (size(tempRightSide)!=0) { rightSides = rightSides + list(tempRightSide); } templ = delete(templ,i); continue; }//save the right sides } result = result + list(list(firstElement,rightSides)); } return(result); }//getPossibilitiesForRightSide static proc getAllCoeffTuplesComb(list l)" Given the output of factorizeInt ((a_1,...,a_n),(i_1,...,i_n)) , it returns all possible tuples of the set {(a,b) | There exists an real N!=emptyset subset of {1,...,n}, such that a = prod_{i \in N}a_i, b=prod_{i \not\in N} a_i} Assumption: The list is sorted from smallest integer to highest. - it is not the factorization of 0. " {//proc getAllCoeffTuplesComb list result; if (l[1][1] == 0) { ERROR("getAllCoeffTuplesComb: Zero Coefficients as leading and Tail Coeffs? That is not possible. Something went wrong."); } if (size(l[1]) == 1) {//Trivial Factorization, just 1 if (l[1][1] == 1) { return(list(list(1,1),list(-1,-1))); } else { return(list(list(-1,1),list(1,-1))); } }//Trivial Factorization, just 1 if (size(l[1]) == 2 and l[2][2]==1) {//Just a prime number if (l[1][1] == 1) { result = list(list(l[1][2],1),list(1,l[1][2])); result = result + list(list(-l[1][2],-1),list(-1,-l[1][2])); return(result); } else { result = list(list(l[1][2],-1),list(1,-l[1][2])); result = result + list(list(-l[1][2],1),list(-1,l[1][2])); return(result); } }//Just a prime number //Now comes the interesting case: a product of primes list tempPrimeFactors; list tempPowersOfThem; int i; for (i = 2; i<=size(l[1]);i++) {//Removing the starting 1 or -1 to get the N's tempPrimeFactors[i-1] = l[1][i]; tempPowersOfThem[i-1] = l[2][i]; }//Removing the starting 1 or -1 to get the N's list Ns = getAllSubsetsN(list(tempPrimeFactors,tempPowersOfThem)); list tempTuples; number productOfl = multiplyFactIntOutput(l); if (productOfl<0){productOfl = -productOfl;} tempTuples = tempTuples + list(list(1,productOfl),list(productOfl,1)); for (i = 1; i<=size(Ns); i++) { if (productOfl/Ns[i]>Ns[i]) {//TODO: BEWEISEN, dass das die einzigen Combos sind tempTuples = tempTuples + list(list(Ns[i],productOfl/Ns[i]),list(productOfl/Ns[i],Ns[i])); }//TODO: BEWEISEN, dass das die einzigen Combos sind if (productOfl/Ns[i]==Ns[i]) { tempTuples = tempTuples + list(list(Ns[i],Ns[i])); } } //And now, it just remains to get the -1s and 1-s correctly to the tuples list tempEntry; if (l[1][1] == 1) { for (i = 1; i<=size(tempTuples);i++) {//Adding everything to result tempEntry = tempTuples[i]; result = result + list(tempEntry); result = result + list(list(-tempEntry[1], -tempEntry[2])); }//Adding everyThing to Result } else { for (i = 1; i<=size(tempTuples);i++) {//Adding everything to result tempEntry = tempTuples[i]; result = result + list(list(tempEntry[1],-tempEntry[2])); result = result + list(list(-tempEntry[1], tempEntry[2])); }//Adding everyThing to Result } return(result); }//proc getAllCoeffTuplesComb static proc contains(list l, int elem) "Assumption: l is sorted" {//Binary Search in list if (size(l)<=1) { if(size(l) == 0){return(0);} if (l[1]!=elem){return(0);} else{return(1);} } int imax = size(l); int imin = 1; int imid; while(imax >= imin) { imid = (imin + imax)/2; if (l[imid] == elem){return(1);} if (l[imid] =1; i--) { result = insert(result, l[i]); } return(result); }//proc fromIntvecToList static proc factorizeInt(number n) "Given an integer n, factorizeInt computes its factorization. The output is a list containing two intvecs. The first contains the prime factors, the second its powers. ASSUMPTIONS: - n is given as integer number "{ if (n==0) {return(list(list(0),list(1)));} int i; list temp = primefactors(n); if (n<0) {list result = list(list(-1),list(1));} else {list result = list(list(1),list(1));} result[1] = result[1] + temp[1]; result[2] = result[2] + temp[2]; return(result); } static proc homogDistribution(poly h) "Input: A polynomial in the first Weyl Algebra. Output: A two-dimensional list of the following form. Every sublist contains exactly two entries. One for the Z-degree of the corresponding homogeneous part (integer), and the homogeneous polynomial itself, and those sublists are oredered by ascending degree. For example a call of homogDistribution(x+d+1) would have the output [1]: [1]: -1 [2]: x [2]: [1]: 0 [2]: 1 [3]: [1]: 1 [2]: d "{//homogDistribution if (h == 0) {//trivial case where input is 0 return(list(list(0,0))); }//trivial case where input is 0 if (!isWeyl()) {//Our basering is not the Weyl algebra ERROR("Ring was not the first Weyl algebra"); return(list()); }//Our basering is not the Weyl algebra if(nvars(basering)!=2) {//Our basering is the Weyl algebra, but not the first ERROR("Ring is not the first Weyl algebra"); return(list()); }//Our basering is the Weyl algebra, but not the first intvec ivm11 = intvec(-1,1); intvec iv1m1 = intvec(1,-1); poly tempH = h; poly minh; list result = list(); int nextExpectedDegree = -deg(tempH,iv1m1); while (tempH != 0) { minh = jet(tempH,deg(tempH,iv1m1),iv1m1)-jet(tempH,deg(tempH,iv1m1)-1,iv1m1); while (deg(minh,ivm11)>nextExpectedDegree) {//filling empty homogeneous spaces with 0 result = result + list(list(nextExpectedDegree,0)); nextExpectedDegree = nextExpectedDegree +1; }//filling empty homogeneous spaces with 0 result = result + list(list(deg(minh,ivm11),minh)); tempH = tempH - minh; nextExpectedDegree = nextExpectedDegree +1; } return(result); }//homogDistribution static proc homogDistributionNthWeyl(poly h) " INPUT: A polynomial in the n-th Weyl algebra OUTPUT: A two-dimensional list of the following form. Every sublist contains exactly two entries. One for the Z^n-degree of the corresponding homogeneous part (intvec), and the homogeneous polynomial itself, and those sublists are oredered by ascending degree using lexicographical ordering on Z^n. Different from homogDistribution, the 0-summands between the maximum and minimum homogeneous degree are not displayed. For example a call of homogDistribution(x1+d2+1) would have the output (ring is the second weyl algebra with variables x1,x2,d1,d2). [1]: [1]: [0,1] [2]: d2 [2]: [1]: [0,0] [2]: 1 [3]: [1]: [-1,0] [2]: x1 GENERAL ASSUMPTIONS: - The basering is the nth Weyl algebra and has the form, that the first n variables represent x1, ..., xn, and the second n variables do represent the d1, ..., dn. " {//proc homogDistributionNthWeyl if (h == 0) {//trivial case where input is 0 return(list(list(0,0))); }//trivial case where input is 0 //TODO: BUG in nctools? /* if (!isWeyl()) */ /* {//Our basering is not the Weyl algebra */ /* ERROR("Ring was not a Weyl algebra"); */ /* return(list()); */ /* }//Our basering is not the Weyl algebra */ list result; poly tempH = h; intvec degVec; poly leadPoly; while(tempH != 0) {//tempH is not equal to zero ==> We have still unconsidered homogeneous summands leadPoly = extractLeadingTermOfNthWeylPoly(tempH); degVec = degreeOfNthWeylPoly(tempH); result = insert(result,list(degVec,leadPoly)); tempH = tempH - leadPoly; }//tempH is not equal to zero ==> We have still unconsidered homogeneous summands return(result); }//proc homogDistributionNthWeyl static proc extractLeadingTermOfNthWeylPoly(poly h) " INPUT: A polynomial h in the nth Weyl algebra. OUTPUT: A polynomial p representing the homogeneous leading polynomial of h with respect to the -1,1 grading on the polynomial nth weyl algebra. GENERAL ASSUMPTIONS: - The ring given is the nth Weyl algebra and has the form, that the first n variables represent x1, ..., xn, and the second n variables do represent the d1, ..., dn. " {//extractLeadingTermOfNthWeylPoly poly result = 0; intvec leadDeg = degreeOfNthWeylPoly(h); int i; int j; int isPart = 0; intvec lExp; for (i = 1; i <=size(h); i++) {//iterating through the terms of h isPart = 1; lExp = leadexp(h[i]); for (j = 1; j<=nvars(basering) div 2; j++) {//checking if the term is part of the leading polynomial if(lExp[j + nvars(basering) div 2] - lExp[j] != leadDeg[j]) {//Summand was not part of leading polynomial isPart = 0; break; }//Summand was not part of leading polynomial }//checking if the term is part of the leading degree if (!isPart) {i++; continue;} else {//In this case, h[i] was part of the leading polynomial result = result + h[i]; }//In this case, h[i] was part of the leading polynomial }//iterating through the terms of h return(result); }//extractLeadingTermOfNthWeylPoly /* Test cases for this: ring R = 0,(x1,x2,x3,d1,d2,d3),dp; matrix C[6][6] = 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; matrix D[6][6] = 0,0,0,1,0,0, 0,0,0,0,1,0, 0,0,0,0,0,1, -1,0,0,0,0,0, 0,-1,0,0,0,0, 0,0,-1,0,0,0; def r = nc_algebra(C,D); setring(r); poly h = 0; extractLeadingTermOfNthWeylPoly(h); ==> 0 h = x3; extractLeadingTermOfNthWeylPoly(h); ==> x3 h = x1*x2*d1*d2 + x1^4*x2^2*x3^3*d1^4*d2^2*d3^3 + 1 + x1 + x2 + x3; extractLeadingTermOfNthWeylPoly(h); ==> x1^4*x2^2*x3^3*d1^4*d2^2*d3^3+x1*x2*d1*d2+1 h = (x1*d1)^5; extractLeadingTermOfNthWeylPoly(h); ==>x1^5*d1^5+10*x1^4*d1^4+25*x1^3*d1^3+15*x1^2*d1^2+x1*d1 */ static proc degreeOfNthWeylPoly(poly h) " INPUT: A polynomial h in the nth Weyl algebra OUTPUT: An intvector of size n, representing the degree of h with respect to the lexicographical ordering on ZZ^n by considering the -1,1 grading on the nth Weyl algebra. GENERAL ASSUMPTIONS: - The ring given is the nth Weyl algebra and has the form, that the first n variables represent x1, ..., xn, and the second n variables do represent the d1, ..., dn. " {//degreeOfNthWeylPoly intvec result = 0:(nvars(basering) div 2); int i; int j; int k; int alreadySmaller; intvec expVec; intvec posUpdated= 0:(nvars(basering) div 2); for(i = 1; i<=nvars(basering) div 2; i++) {//Going through every variable to determine the max. term for (j = 1; j <= size(h); j++) {//Iterating over every term in h alreadySmaller = 0; for (k = 1; k 0,0,0 h = x1 + d1 + x1*d2 + d1*d2; degreeOfNthWeylPoly(h); ==> 1,1,0 h = x1^5 + d1 + x1*d2 + d1*d2; degreeOfNthWeylPoly(h); ==> 1,1,0 h = 1; degreeOfNthWeylPoly(h); ==> 0,0,0 h = x1*d1; degreeOfNthWeylPoly(h); ==> 0,0,0 h = x2*d2; degreeOfNthWeylPoly(h); ==> 0,0,0 h = x3*d3; degreeOfNthWeylPoly(h); ==> 0,0,0 */ static proc degreeOfNthWeylPolyInverted(poly h) " INPUT: A polynomial h in the nth Weyl algebra OUTPUT: An intvector of size n, representing the degree of h with respect to the lexicographical ordering on ZZ^n by considering the 1,-1 grading on the nth Weyl algebra. GENERAL ASSUMPTIONS: - The ring given is the nth Weyl algebra and has the form, that the first n variables represent x1, ..., xn, and the second n variables do represent the d1, ..., dn. " {//degreeOfNthWeylPoly intvec result = 0:(nvars(basering) div 2); int i; int j; int k; int alreadySmaller; intvec expVec; intvec posUpdated= 0:(nvars(basering) div 2); for(i = 1; i<=nvars(basering) div 2; i++) {//Going through every variable to determine the max. term for (j = 1; j <= size(h); j++) {//Iterating over every term in h alreadySmaller = 0; for (k = 1; k2) {//We want max. two optional arguments dbprint(p,dbprintWhitespace + " More than two optional arguments"); return(list()); }//We want max. two optional arguments dbprint(p,dbprintWhitespace + " Done"); list result; int j; if (size(#)==0) {//No optional argument is given dbprint(p,dbprintWhitespace + " No optional arguments"); int valid = 1; for (i = size(l);i>=1;i--) {//iterate over the elements of the given list if (size(result)>0) { if (product(l[i])!=result[size(l)-i]) { valid = 0; break; } } result = insert(result, product(l[i])); }//iterate over the elements of the given list return(valid); }//No optional argument is given else { dbprint(p,dbprintWhitespace + " Optional arguments are given."); int valid = 1; for (i = size(l);i>=1;i--) {//iterate over the elements of the given list if (product(l[i])!=#[1]) { valid = 0; } result = insert(result, product(l[i])-#[1]); }//iterate over the elements of the given list if(size(#)==2) { dbprint(p,dbprintWhitespace + " A third argument is given. Output is a list now."); return(result); } return(valid); } }//proc testfac example { "EXAMPLE:";echo=2; ring r = 0,(x,y),dp; def R = nc_algebra(1,1); setring R; poly h = (x^2*y^2+1)*(x^2); def t1 = facFirstWeyl(h); //fist a correct list testNCfac(t1); //now a correct list with the factorized polynomial testNCfac(t1,h); //now we put in an incorrect list without a polynomial t1[3][3] = y; testNCfac(t1); // take h as additional input testNCfac(t1,h); // take h as additional input and output list of differences testNCfac(t1,h,1); } //================================================== //Procedure facSubWeyl: //This procedure serves the purpose to compute a //factorization of a given polynomial in a ring, whose subring //is the first Weyl algebra. The polynomial must only contain //the two arguments, which are also given by the user. proc facSubWeyl(poly h, poly X, poly D) "USAGE: facSubWeyl(h,x,y); h, X, D polynomials RETURN: list ASSUME: X and D are variables of a basering, which satisfy DX = XD +1. @* That is, they generate the copy of the first Weyl algebra in a basering. @* Moreover, h is a polynomial in X and D only. PURPOSE: compute factorizations of the polynomial, which depends on X and D. EXAMPLE: example facSubWeyl; shows examples SEE ALSO: facFirstWeyl, testNCfac, facFirstShift "{ int p = printlevel - voice + 2; dbprint(p," Start initial Checks of the input."); // basering can be anything having a Weyl algebra as subalgebra def @r = basering; //We begin to check the input for assumptions // which are: X,D are vars of the basering, if ( (isVar(X)!=1) || (isVar(D)!=1) || (size(X)>1) || (size(D)>1) || (leadcoef(X) != number(1)) || (leadcoef(D) != number(1)) ) { ERROR("expected pure variables as generators of a subalgebra"); } // Weyl algebra: poly w = D*X-X*D-1; // [D,X]=1 poly u = D*X-X*D+1; // [X,D]=1 if (u*w!=0) { // that is no combination gives Weyl ERROR("2nd and 3rd argument do not generate a Weyl algebra"); } // one of two is correct int isReverted = 0; // Reverted Weyl if dx=xd-1 holds if (u==0) { isReverted = 1; } // else: do nothing // DONE with assumptions, Input successfully checked dbprint(p," Successful"); intvec lexpofX = leadexp(X); intvec lexpofD = leadexp(D); int varnumX=1; int varnumD=1; while(lexpofX[varnumX] != 1) { varnumX++; } while(lexpofD[varnumD] != 1) { varnumD++; } /* VL : to add printlevel stuff */ dbprint(p," Change positions of the two variables in the list, if needed"); if (isReverted) { ring firstweyl = 0,(var(varnumD),var(varnumX)),dp; def Firstweyl = nc_algebra(1,1); setring Firstweyl; ideal M = ideal(0:nvars(@r)); M[varnumX]=var(2); M[varnumD]=var(1); map Q = @r,M; poly h= Q(h); } else { // that is unReverted ring firstweyl = 0,(var(varnumX),var(varnumD)),dp; def Firstweyl = nc_algebra(1,1); setring Firstweyl; poly h= imap(@r,h); } dbprint(p," Done!"); list result = facFirstWeyl(h); setring @r; list result; if (isReverted) { // map swap back ideal M; M[1] = var(varnumD); M[2] = var(varnumX); map S = Firstweyl, M; result = S(result); } else { // that is unReverted result = imap(Firstweyl,result); } return(result); }//proc facSubWeyl example { "EXAMPLE:";echo=2; ring r = 0,(x,y,z),dp; matrix D[3][3]; D[1,3]=-1; def R = nc_algebra(1,D); // x,z generate Weyl subalgebra setring R; poly h = (x^2*z^2+x)*x; list fact1 = facSubWeyl(h,x,z); // compare with facFirstWeyl: ring s = 0,(z,x),dp; def S = nc_algebra(1,1); setring S; poly h = (x^2*z^2+x)*x; list fact2 = facFirstWeyl(h); map F = R,x,0,z; list fact1 = F(fact1); // it is identical to list fact2 testNCfac(fact1); // check the correctness again } //================================================== //================================================== //************From here: Shift-Algebra************** //================================================== //==================================================* //one factorization of a homogeneous polynomial //in the first Shift Algebra static proc homogfacFirstShift(poly h) {//proc homogfacFirstShift int p=printlevel-voice+2; //for dbprint def r = basering; poly hath; intvec iv01 = intvec(0,1); int i; int j; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} if (!homogwithorder(h,iv01)) {//The given polynomial is not homogeneous ERROR("The given polynomial is not homogeneous."); return(list()); }//The given polynomial is not homogeneous if (h==0) { return(list(0)); } list result; int m = deg(h,iv01); dbprint(p,dbprintWhitespace+" exclude the homogeneous part of deg. 0"); if (m>0) {//The degree is not zero hath = lift(var(2)^m,h)[1,1]; for (i = 1; i<=m;i++) { result = result + list(var(2)); } }//The degree is not zero else {//The degree is zero hath = h; }//The degree is zero ring tempRing = 0,(x),dp; setring tempRing; map thetamap = r,x,1; poly hath = thetamap(hath); dbprint(p,dbprintWhitespace+" Factorize it using commutative factorization."); list azeroresult = factorize(hath); list azeroresult_return_form; for (i = 1; i<=size(azeroresult[1]);i++) {//rewrite the result of the commutative factorization for (j = 1; j <= azeroresult[2][i];j++) { azeroresult_return_form = azeroresult_return_form + list(azeroresult[1][i]); } }//rewrite the result of the commutative factorization setring(r); map finalmap = tempRing,var(1); list tempresult = finalmap(azeroresult_return_form); result = tempresult+result; return(result); }//proc homogfacFirstShift //================================================== //Computes all possible homogeneous factorizations static proc homogfacFirstShift_all(poly h) {//proc HomogfacFirstShiftAll int p=printlevel-voice+2; //for dbprint intvec iv11 = intvec(1,1); if (deg(h,iv11) <= 0 ) {//h is a constant return(list(list(h))); }//h is a constant def r = basering; list one_hom_fac; //stands for one homogeneous factorization int i; int j; int k; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} int shiftcounter; //Compute again a homogeneous factorization dbprint(p,dbprintWhitespace+" Computing one homog. factorization of the polynomial"); one_hom_fac = homogfacFirstShift(h); one_hom_fac = delete(one_hom_fac,1); if (size(one_hom_fac) == 0) {//there is no homogeneous factorization or the polynomial was not homogeneous return(list()); }//there is no homogeneous factorization or the polynomial was not homogeneous dbprint(p,dbprintWhitespace+" Permuting the 0-homogeneous part with the s"); list result = permpp(one_hom_fac); for (i = 1; i<=size(result);i++) { shiftcounter = 0; for (j = 1; j<=size(result[i]); j++) { if (result[i][j]==var(2)) { shiftcounter++; } else { result[i][j] = subst(result[i][j], var(1), var(1)-shiftcounter); } } result[i] = insert(result[i],1); } dbprint(p,dbprintWhitespace+" Deleting double entries in the resulting list"); result = delete_dublicates_noteval(result); return(result); }//proc HomogfacFirstShiftAll //================================================== //factorization of the first Shift Algebra static proc facFirstShift_old(poly h) "USAGE: facFirstShift(h); h a polynomial in the first shift algebra RETURN: list PURPOSE: compute all factorizations of a polynomial in the first shift algebra THEORY: Implements the new algorithm by A. Heinle and V. Levandovskyy, see the thesis of A. Heinle ASSUME: basering is the first shift algebra NOTE: Every entry of the output list is a list with factors for one possible factorization. EXAMPLE: example facFirstShift; shows examples SEE ALSO: testNCfac, facFirstWeyl, facSubWeyl "{//facFirstShift_old int p = printlevel - voice + 2; int i; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} dbprint(p,dbprintWhitespace +" Checking the input."); if(nvars(basering)!=2) {//Our basering is the Shift algebra, but not the first ERROR("Basering is not the first shift algebra"); return(list()); }//Our basering is the Shift algebra, but not the first def r = basering; setring r; list LR = ringlist(r); number @n = leadcoef(LR[5][1,2]); poly @p = LR[6][1,2]; if ( @n!=number(1) ) { ERROR("Basering is not the first shift algebra"); return(list()); } dbprint(p,dbprintWhitespace +" Done"); list result = list(); int j; int k; int l; //counter // create a ring with the ordering which makes shift algebra // graded // def r = basering; // done before ring tempRing = LR[1][1],(x,s),(a(0,1),Dp); def tempRingnc = nc_algebra(1,s); setring r; // information on relations if (@p == -var(1)) // reverted shift algebra { dbprint(p,dbprintWhitespace +" Reverted shift algebra. Swaping variables in Ringlist"); setring(tempRingnc); map transf = r, var(2), var(1); setring(r); map transfback = tempRingnc, var(2),var(1); // result = transfback(resulttemp); } else { if ( @p == var(2)) // usual shift algebra { setring(tempRingnc); map transf = r, var(1), var(2); // result = facshift(h); setring(r); map transfback = tempRingnc, var(1),var(2); } else { ERROR("Basering is not the first shift algebra"); return(list()); } } // main calls setring(tempRingnc); dbprint(p,dbprintWhitespace +" Factorize the given polynomial with the subroutine sFacShift"); list resulttemp = sFacShift(transf(h)); dbprint(p,dbprintWhitespace +" Successful"); setring(r); result = transfback(resulttemp); return( delete_dublicates_noteval(result) ); }//facFirstShift_old proc facFirstShift(poly h) "USAGE: facFirstShift(h); h a polynomial in the first shift algebra RETURN: list PURPOSE: compute all factorizations of a polynomial in the first shift algebra THEORY: This function is a wrapper for facShift. It exists to make this library downward-compatible with older versions. ASSUME: basering is the first shift algebra NOTE: Every entry of the output list is a list with factors for one possible factorization. EXAMPLE: example facFirstShift; shows examples SEE ALSO: testNCfac, facFirstWeyl, facSubWeyl "{//facFirstShift return(facShift(h)); }//facFirstShift example { "EXAMPLE:";echo=2; ring R = 0,(x,s),dp; def r = nc_algebra(1,s); setring(r); poly h = (s^2*x+x)*s; facFirstShift(h); } proc facShift(poly h) "USAGE: facShift(h); h a polynomial in the n'th shift algebra RETURN: list PURPOSE: compute all factorizations of a polynomial in the nth shift algebra THEORY: h is mapped to the $n$th Weyl algebra and then factorized there. The factorizations are mapped back (S_n in subalgebra of Weyl algebra). ASSUME: basering is the nth shift algebra NOTE: Every entry of the output list is a list with factors for one possible factorization. EXAMPLE: example facFirstShift; shows examples SEE ALSO: testNCfac, facFirstWeyl, facSubWeyl "{//facShift //Definition of printlevel variable int p = printlevel-voice+2; int i; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} dbprint(p,dbprintWhitespace +" Checking if the given algebra is a Shift algebra"); //Redefine the ring in my standard form if (!ncfactor_isShift()) {//Our basering is not the shift algebra ERROR("Ring was not a Shift algebra"); return(list()); }//Our basering is not the Shift algebra dbprint(p,dbprintWhitespace +" Successful"); //A last check before we start the real business: Is h maybe just //dependable on commutative variables? if (isInCommutativeSubRing(h)) {//h is in a commutative subring list hdepvars; intvec tempIntVec; for (i = 1; i<=nvars(basering) ; i++) { tempIntVec = 0:nvars(basering); tempIntVec[i] = 1; if (deg(h,tempIntVec)>0) { hdepvars = hdepvars + list(var(i)); } } if (size(hdepvars) ==0) {//We just have a constant return(list(list(h))); }//We just have a constant dbprint(p,dbprintWhitespace+"Polynomial was given commutative subring. Performing commutative factorization."); def r = basering; def rList = ringlist(basering); rList = delete(rList,5); rList = delete(rList,5); def tempRing = ring(rList); setring(tempRing); poly h = imap(r,h); list tempResult = factorize(h); list result = list(list()); int j; for (i = 1; i<=size(tempResult[1]); i++) { for (j = 1; j<=tempResult[2][i]; j++) { result[1] = result[1] + list(tempResult[1][i]); } } //mapping back setring(r); def result = imap(tempRing,result); dbprint(p,dbprintWhitespace+"result:"); dbprint(p,result); dbprint(p,dbprintWhitespace+"Computing all permutations of this factorization"); poly constantFactor = result[1][1]; result[1] = delete(result[1],1);//Deleting the constant factor result=permpp(result[1]); for (i = 1; i<=size(result);i++) {//Insert constant factor result[i] = insert(result[i],constantFactor); }//Insert constant factor dbprint(p,dbprintWhitespace+"Done."); return(result); }//h is in a commutative subring dbprint(p,dbprintWhitespace +" Successful"); list result = list(); int j; int k; int l; //counter if (!checkIfProperNthShift()) {//The given ring was not a proper nth shift algebra dbprint(p,dbprintWhitespace +" positions of the variables have to be switched"); dbprint(p,dbprintWhitespace + "Constructing the proper ring."); def r = basering; list tempRingList = ringlist(r); tempRingList = delete(tempRingList,6); list the_vars; for (i = 1; i<=nvars(r); i++) {the_vars[i] = var(i);} int maybeDInWrongPos; poly tempVariable; for (i = 1; i<=size(the_vars) div 2; i++) {//Swapping the variables as needed maybeDInWrongPos = 1; if (the_vars[i + size(the_vars) div 2]*the_vars[i] -the_vars[i]*the_vars[i + size(the_vars) div 2] == the_vars[i + size(the_vars) div 2]) { i++; continue; } //If we enter this line, there is a break with our property //condition for (j = i+1; j<=size(the_vars); j++) { if (the_vars[j]*the_vars[i]-the_vars[i]*the_vars[j]==the_vars[j]) {//In this case, we matched a var x to a repective s tempVariable = the_vars[i + size(the_vars) div 2]; the_vars[i + size(the_vars) div 2] = the_vars[j]; the_vars[j] = tempVariable; maybeDInWrongPos = 0; break; }//In this case, we matched a var x to a repective s } if (maybeDInWrongPos) {//var(i) is actually a s, not an x print("i has to be pushed to the end."); tempVariable = the_vars[i]; the_vars = delete(the_vars, i); the_vars = the_vars + list(tempVariable); continue; }//var(i) is actually a s, not an x }//Swapping the variables as needed for (i = 1; i<=size(the_vars); i++) {tempRingList[2][i] = string(the_vars[i]);} matrix DTemp[nvars(r)][nvars(r)]; for (i = 1; i<=ncols(DTemp) div 2; i++) { DTemp[i,i + nvars(r) div 2] = the_vars[i + nvars(r) div 2]; } tempRingList = tempRingList + list(DTemp); def tempRing = ring(tempRingList); dbprint(p,dbprintWhitespace + "Done. The altered ring is the following:"); dbprint(p,tempRing); setring(tempRing); //We have to go through an intermediate ring, as there is some strange //behaviour in Singular concerning the correctness of the matrix D. // See http://www.singular.uni-kl.de:8002/trac/ticket/542 for details. matrix DTemp = imap(r, DTemp); list tempRingList2 = ringlist(tempRing); tempRingList2[6]= DTemp; def tempRing2 = ring(tempRingList2); setring(tempRing2); poly h = imap(r,h); dbprint(p,dbprintWhitespace +" Successful"); list resulttemp = facShift(h); setring(r); result = imap(tempRing2,resulttemp); return (result); }//The given ring was not a proper nth Shift algebra dbprint(p, dbprintWhitespace +" factorization of the polynomial with the routine sfacNthShift"); result = sFacNthShift(h); dbprint(p,dbprintWhitespace +" Done"); return(result); }//facShift example { "EXAMPLE:";echo=2; ring R = 0,(x1,x2,s1,s2),dp; matrix C[4][4] = 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1; matrix D[4][4] = 0,0,s1,0, 0,0,0,s2, -s1,0,0,0, 0,-s2,0,0; def r = nc_algebra(C,D); setring(r); poly h = x1*(x1+1)*s1^2-2*x1*(x1+100)*s1+(x1+99)*(x1+100); facShift(h); } static proc sFacShift(poly h) " USAGE: A static procedure to factorize a polynomial in the first Shift algebra, where all the validity checks were made in advance. INPUT: A polynomial h in the first Shift Algebra. OUTPUT: A list of different factorizations of h, where the factors are irreducible ASSUMPTIONS: - The basering is the first Shift algebra and has n as first, and s as second variable, i.e. we have var(2)*var(1) = var(1)*var(2)+1 THEORY: If the given polynomial h is [0,1]-homogeneous, the routines for homogeneous factorizations are called. Otherwise we map the polynomial into the first Weyl algebra (the first shift algebra is a subring of the first Weyl algebra), and use facFirstWeyl to factorize it. Later we map the factors back, if possible. " {//proc sFacShift int p = printlevel - voice + 2; int i; int j ; string dbprintWhitespace = ""; number commonCoefficient = content(h); for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} //Checking if given polynomial is homogeneous if(homogwithorder(h,intvec(0,1))) {//The given polynomial is [0,1]-homogeneous dbprint(p,dbprintWhitespace+"The polynomial is [0,1]-homogeneous. Returning the homogeneous factorization"); return(homogfacFirstShift_all(h)); }//The given polynomial is [0,1]-homogeneous //---------- Start of interesting part ---------- dbprint(p,dbprintWhitespace+"Mapping the polynomial h into the first Weyl algebra."); poly temph = h/commonCoefficient; def ourBaseRing = basering; ring tempWeylAlgebraComm = 0,(x,d),dp; def tempWeylAlgebra = nc_algebra(1,1); setring(tempWeylAlgebra); map shiftMap = ourBaseRing, x*d, d; poly h = shiftMap(temph); dbprint(p,dbprintWhitespace+"Successful! The polynomial in the Weyl algebra is "+string(h)); dbprint(p,dbprintWhitespace+"Factorizing the polynomial in the first Weyl algebra"); list factorizationInWeyl = facFirstWeyl(h); dbprint(p,dbprintWhitespace+"Successful! The factorization is given by:"); dbprint(p,factorizationInWeyl); list validCombinations; dbprint(p,dbprintWhitespace+"Now we will map this back to the shift algebra and filter valid results"); //-Now we map the results back to the shift algebra. But first, we need to combine them properly. for (i = 1; i<=size(factorizationInWeyl); i++) {//Deleting the first Coefficient factor factorizationInWeyl[i] = delete(factorizationInWeyl[i],1); validCombinations = validCombinations + combineNonnegative(factorizationInWeyl[i]); }//Deleting the first Coefficient factor if (size(validCombinations) == 0) {//There are no valid combinations, therefore we can directly say, that h is irreducible setring(ourBaseRing); return(list(list(commonCoefficient, h/commonCoefficient))); }//There are no valid combinations, therefore we can directly say, that h is irreducible validCombinations = delete_dublicates_noteval(validCombinations); setring(ourBaseRing); map backFromWeyl = tempWeylAlgebra, var(1),var(2); list validCombinations = backFromWeyl(validCombinations); for (i = 1; i<=size(validCombinations); i++) { for (j = 1; j<=size(validCombinations[i]);j++) { setring(tempWeylAlgebra); fromWeylToShiftPoly(validCombinations[i][j],ourBaseRing); validCombinations[i][j] = result; kill result; kill tempResult; kill zeroPoly; kill fromWeyl; } } for (i = 1; i<=size(validCombinations); i++) {//Adding the common factor in the first position of the list validCombinations[i] = insert(validCombinations[i],commonCoefficient); }//Adding the common factor in the first position of the list dbprint(dbprintWhitespace+"Done."); //mapping return(validCombinations); }//proc sFacShift static proc sFacNthShift(poly h) " USAGE: A static procedure to factorize a polynomial in the nth Shift algebra, where all the validity checks were made in advance. INPUT: A polynomial h in the nth Shift Algebra. OUTPUT: A list of different factorizations of h, where the factors are irreducible ASSUMPTIONS: - The basering is the nth Shift algebra and the variables are given in the order (x_1, ... , x_n, s_1, ..., s_n), where s_i*x_i = (x_i+1)*s_i THEORY: We map the polynomial into the nth Weyl algebra (the nth shift algebra is a subring of the nth Weyl algebra), and use facWeyl to factorize it. Later we map the factors back, if possible. " {//proc sFacNthShift int p = printlevel - voice + 2; int i; int j ; string dbprintWhitespace = ""; number commonCoefficient = content(h); for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} //---------- Start of interesting part ---------- dbprint(p,dbprintWhitespace+"Mapping the polynomial h into the nth Weyl algebra."); poly temph = h/commonCoefficient; def ourBaseRing = basering; ring tempWeylAlgebraComm = 0,(x(1..(nvars(ourBaseRing) div 2)), d(1..(nvars(ourBaseRing) div 2))),dp; matrix C[nvars(ourBaseRing)][nvars(ourBaseRing)]; matrix D[nvars(ourBaseRing)][nvars(ourBaseRing)]; for (i = 1; i<= nvars(ourBaseRing); i++) {//Filling the matrices D and C for (j = 1; j<= nvars(ourBaseRing); j++) { C[i,j] = 1; if (j == (nvars(ourBaseRing) div 2) + i) { D[i,j] = 1; } else { D[i,j] = 0; } } }//Filling the matrices D and C def tempWeylAlgebra = nc_algebra(C,D); setring(tempWeylAlgebra); ideal shiftMapIdeal; for (i = 1; i<= nvars(tempWeylAlgebra) div 2; i++) { shiftMapIdeal[i] = x(i)*d(i); shiftMapIdeal[i + (nvars(tempWeylAlgebra) div 2)] = d(i); } map shiftMap = ourBaseRing, shiftMapIdeal; poly h = shiftMap(temph); dbprint(p,dbprintWhitespace+"Successful! The polynomial in the Weyl algebra is "+string(h)); dbprint(p,dbprintWhitespace+"Factorizing the polynomial in the nth Weyl algebra"); list factorizationInWeyl = facWeyl(h); dbprint(p,dbprintWhitespace+"Successful! The factorization is given by:"); dbprint(p,factorizationInWeyl); list validCombinations; dbprint(p,dbprintWhitespace+"Now we will map this back to the shift algebra and filter valid results"); //-Now we map the results back to the shift algebra. But first, we need to combine them properly. for (i = 1; i<=size(factorizationInWeyl); i++) {//Deleting the first Coefficient factor factorizationInWeyl[i] = delete(factorizationInWeyl[i],1); validCombinations = validCombinations + combineNonnegativeNthShift(factorizationInWeyl[i]); }//Deleting the first Coefficient factor if (size(validCombinations) == 0) {//There are no valid combinations, therefore we can directly say, that h is irreducible setring(ourBaseRing); return(list(list(commonCoefficient, h/commonCoefficient))); }//There are no valid combinations, therefore we can directly say, that h is irreducible validCombinations = delete_dublicates_noteval(validCombinations); setring(ourBaseRing); ideal backFromWeylIdeal; for (i = 1; i<=nvars(ourBaseRing); i++) { backFromWeylIdeal[i] = var(i); } map backFromWeyl = tempWeylAlgebra, backFromWeylIdeal; list validCombinations = backFromWeyl(validCombinations); for (i = 1; i<=size(validCombinations); i++) { for (j = 1; j<=size(validCombinations[i]);j++) { setring(tempWeylAlgebra); fromNthWeylToNthShiftPoly(validCombinations[i][j],ourBaseRing); validCombinations[i][j] = result; kill result; kill tempResult; kill zeroPoly; kill fromWeyl; } } for (i = 1; i<=size(validCombinations); i++) {//Adding the common factor in the first position of the list validCombinations[i] = insert(validCombinations[i],commonCoefficient); }//Adding the common factor in the first position of the list dbprint(dbprintWhitespace+"Done."); //mapping return(validCombinations); }//proc sFacNthShift //Tests: //(x1^2*s1 + s2)*(x2*s1+1); //(x1^2 + x2)*s1*s2; //(x2*x1 + s1)*(x2^2 + s2*s1) static proc combineNonnegative(list l) " USAGE: In sFacShift, when we want to map back the results of the factorization of the polynomial in the first Weyl algebra to the shift algebra. We need to recombine the factors such that we can map it back to the shift algebra without any problems. INPUT: A list l containing one factorization of a polynomial in the first Weyl algebra. For example for the polynomial (1+x)*(1+x+d) we would have the list [1,x+1,x+d+1]. OUTPUT:If we can map every factor without a problem back to the shift algebra (i.e. if the smallest homogeneous summand of every factor is of nonnegative degree), a list containing the same list as given in the input is returned. If otherwise some factors cause problems, we consider every possible combination (i.e. products of the factors) and extract those where all factors have a smallest homogeneous summand of nonnegative degree. ASSUMPTIONS: - Weyl algebra is given, and we have var(2)*var(1)=var(1)*var(2) +1 " {//combineNonnegative int p = printlevel - voice + 2; int i; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} //First the easy case: all of the factors fulfill the condition of mapping to shift: dbprint(p,dbprintWhitespace+"Checking, if the given factors can already be mapped without a problem."); int isValid = 1; for (i = 1; i<=size(l);i++) {//Checking for every entry if the condition is fulfilled. if (deg(l[i],intvec(1,-1))>0) {//Found one, where it is not fulfilled isValid = 0; break; }//Found one, where it is not fulfilled }//Checking for every entry if the condition is fulfilled. dbprint(p,dbprintWhitespace+"Done."); if (isValid) {//We can map every factor to the shift algebra and do not need to combine anything dbprint(p,dbprintWhitespace+"They can be mapped. Therefore we return them directly."); return(list(l)); }//We can map every factor to the shift algebra and do not need to combine anything dbprint(p,dbprintWhitespace+"They cannot be mapped. Looking for valid combinations."); //Starting with the case, where l only consists of 1 or two elements. if(size(l)<=2) {//The case where we won't call the function a second time if (deg(product(l),intvec(1,-1))>0) {//No way of a valid combination return(list()); }//No way of a valid combination else {//The product is the only possible and valid combination return(list(list(product(l)))); }//The product is the only possible and valid combination }//The case where we won't call the function a second time //---------- Easy pre-stuff done. now we combine the factors.---------- int pos; int j; int k; dbprint(p,dbprintWhitespace+"Making combinations of two."); list combinationsOfTwo = combinekfinlf(l,2); dbprint(p,dbprintWhitespace+"Done. Now checking, if there are valid ones in between."); list result; list validLHS; list validRHS; for (i = 1; i<=size(combinationsOfTwo); i++) {//go through all combinations and detect the valid ones if(deg(combinationsOfTwo[i][1],intvec(1,-1))>0 or deg(combinationsOfTwo[i][2],intvec(1,-1))>0) {//No chance, so no further treatment needed i++; continue; }//No chance, so no further treatment needed for (pos = 1; pos<=size(l);pos++) {//find the position where the combination splits if (product(l[1..pos]) == combinationsOfTwo[i][1]) {//Found the position break; }//Found the position }//find the position where the combination splits dbprint(p,dbprintWhitespace+"Calling combineNonnegative recursively with argument " + string(list(l[1..pos]))); validLHS = combineNonnegative(list(l[1..pos])); dbprint(p,dbprintWhitespace+"Calling combineNonnegative recursively with argument " + string(list(l[pos+1..size(l)]))); validRHS = combineNonnegative(list(l[pos+1..size(l)])); for (j = 1; j<=size(validLHS); j++) {//Combining the left hand side valid combnations... for (k = 1; k<=size(validRHS); k++) {//... with the right hand side valid combinations result = insert(result, validLHS[j]+validRHS[k]); }//... with the right hand side valid combinations }//Combining the left hand side valid combnations... }//go through all combinations and detect the valid ones result = delete_dublicates_noteval(result); dbprint(p,dbprintWhitespace+"Done."); return(result); }//combineNonnegative static proc combineNonnegativeNthShift(list l) " USAGE: In sFacNthShift, when we want to map back the results of the factorization of the polynomial in the nth Weyl algebra to the shift algebra. We need to recombine the factors such that we can map it back to the shift algebra without any problems. INPUT: A list l containing one factorization of a polynomial in the nth Weyl algebra. For example for the polynomial (1+x)*(1+x+d) we would have the list [1,x+1,x+d+1]. OUTPUT:If we can map every factor without a problem back to the shift algebra (i.e. if the smallest homogeneous summand of every factor is of nonnegative degree), a list containing the same list as given in the input is returned. If otherwise some factors cause problems, we consider every possible combination (i.e. products of the factors) and extract those where all factors have a smallest homogeneous summand of nonnegative degree. ASSUMPTIONS: - The nth Weyl algebra is given, and the variables are ordered in the form (x_1, ... , x_n, d_1, ..., d_n), with d_i*x_i = x_i * d_i + 1; " {//combineNonnegative int p = printlevel - voice + 2; int i; int j; intvec degreeOfInputPoly; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} //First the easy case: all of the factors fulfill the condition of mapping to shift: dbprint(p,dbprintWhitespace+"Checking, if the given factors can already be mapped without a problem."); int isValid = 1; for (i = 1; i<=size(l);i++) {//Checking for every entry if the condition is fulfilled. degreeOfInputPoly = degreeOfNthWeylPolyInverted(l[i]); for (j = 1; j<=size(degreeOfInputPoly); j++) {//checking if each entry has positive degree if (degreeOfInputPoly[j] > 0) { isValid = 0; break; } }//Found one, where it is not fulfilled }//Checking for every entry if the condition is fulfilled. dbprint(p,dbprintWhitespace+"Done."); if (isValid) {//We can map every factor to the shift algebra and do not need to combine anything dbprint(p,dbprintWhitespace+"They can be mapped. Therefore we return them directly."); return(list(l)); }//We can map every factor to the shift algebra and do not need to combine anything dbprint(p,dbprintWhitespace+"They cannot be mapped. Looking for valid combinations."); //Starting with the case, where l only consists of 1 or two elements. if(size(l)<=2) {//The case where we won't call the function a second time degreeOfInputPoly = degreeOfNthWeylPolyInverted(product(l)); for (j =1; j <= size(degreeOfInputPoly); j++) {//Checking if each entry has degree greater than zero or not if (degreeOfInputPoly[j] > 0) {//in this case, we can return false return(list()); }//in this case, we can return false }//Checking if each entry has degree greater than zero or not //If we encounter this line of code, we have two or less factors, //and they can be combined such that we can map it back to the nth //shift algebra return(list(list(product(l)))); }//The case where we won't call the function a second time //---------- Easy pre-stuff done. now we combine the factors.---------- int pos; int k; dbprint(p,dbprintWhitespace+"Making combinations of two."); list combinationsOfTwo = combinekfinlf(l,2); dbprint(p,dbprintWhitespace+"Done. Now checking, if there are valid ones in between."); list result; list validLHS; list validRHS; intvec degOfInpPoly1; intvec degOfInpPoly2; int noChance; for (i = 1; i<=size(combinationsOfTwo); i++) {//go through all combinations and detect the valid ones degOfInpPoly1 = degreeOfNthWeylPolyInverted(combinationsOfTwo[i][1]); degOfInpPoly2 = degreeOfNthWeylPolyInverted(combinationsOfTwo[i][2]); noChance = 0; for (j = 1; j<=size(degOfInpPoly1); j++) { if (degOfInpPoly1[j] > 0 or degOfInpPoly2[j] >0) {//No chance, so no further treatment needed noChance = 1; break; }//No chance, so no further treatment needed } if (noChance) { i++; continue; } for (pos = 1; pos<=size(l);pos++) {//find the position where the combination splits if (product(l[1..pos]) == combinationsOfTwo[i][1]) {//Found the position break; }//Found the position }//find the position where the combination splits dbprint(p,dbprintWhitespace+"Calling combineNonnegative recursively with argument " + string(list(l[1..pos]))); validLHS = combineNonnegativeNthShift(list(l[1..pos])); dbprint(p,dbprintWhitespace+"Calling combineNonnegative recursively with argument " + string(list(l[pos+1..size(l)]))); validRHS = combineNonnegativeNthShift(list(l[pos+1..size(l)])); for (j = 1; j<=size(validLHS); j++) {//Combining the left hand side valid combnations... for (k = 1; k<=size(validRHS); k++) {//... with the right hand side valid combinations result = insert(result, validLHS[j]+validRHS[k]); }//... with the right hand side valid combinations }//Combining the left hand side valid combnations... }//go through all combinations and detect the valid ones result = delete_dublicates_noteval(result); dbprint(p,dbprintWhitespace+"Done."); return(result); }//combineNonnegativeNthShift static proc fromWeylToShiftPoly(poly h, sAlgebra) " USAGE: Given a polynomial in the first Weyl algebra, this method returns it -- if possible -- as an element in the first shift algebra, which is given in the method header. INPUT: A polynomial h, and the first shift algebra as a ring OUTPUT: The correct mapping in the shift Algebra ASSUMPTIONS: - The lowest [-1,1]-homogeneous summand of h is of nonnegative degree - The shift algebra is given in the way that var(2)*var(1) = (var(1)+1)*var(2) " {//fromWeylToShiftPoly int p = printlevel - voice + 2; int i; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} if (deg(h,intvec(1,-1))>0) {//Wrong input polynomial ERROR("The lowest [-1,1] homogeneous summand of "+string(h)+" is of negative degree."); }//Wrong input polynomial def ourHomeBase = basering; list hDist = homogDistribution(h); setring(sAlgebra); poly result = 0; poly tempResult; poly zeroPoly; map fromWeyl = ourHomeBase, var(1), var(2); setring(ourHomeBase); poly zeroPoly; poly tempZeroPoly; int j; int k; int derDeg; for (i = 1; i<=size(hDist);i++) { derDeg = hDist[i][1]; setring(sAlgebra); tempResult = 1; setring(ourHomeBase); zeroPoly = lift(d^derDeg, hDist[i][2])[1,1]; for (j = 1; j<=size(zeroPoly); j++) { tempZeroPoly = zeroPoly[j]; setring(sAlgebra); zeroPoly = fromWeyl(tempZeroPoly); tempResult = tempResult * leadcoef(zeroPoly); setring(ourHomeBase); for (k = 1; k<=deg(zeroPoly[j],intvec(0,1));k++) { setring(sAlgebra); tempResult = tempResult*(var(1)-(k-1)); setring(ourHomeBase); } setring(sAlgebra); result = result + tempResult*var(2)^derDeg; tempResult = 1; setring(ourHomeBase); } } setring(sAlgebra); keepring(sAlgebra); }//fromWeylToShiftPoly static proc fromNthWeylToNthShiftPoly(poly h, def sAlgebra) " USAGE: Given a polynomial in the nth Weyl algebra, this method returns it -- if possible -- as an element in the nth shift algebra, which is given in the method header. INPUT: A polynomial h, and the nth shift algebra as a ring OUTPUT: The correct mapping in the nth shift Algebra ASSUMPTIONS: - The lowest [-1,1]-homogeneous summand of h is of nonnegative degree - The shift algebra is given in the way, that the variables are sorted by (x_1, ... , x_n, s_1, ..., s_n) with s_i x_i = (x_i + 1) s_i " {//fromNthWeylToNthShiftPoly int p = printlevel - voice + 2; int i; string dbprintWhitespace = ""; intvec degOfh; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} degOfh = degreeOfNthWeylPolyInverted(h); for (i = 1; i<=size(degOfh); i++) { if (degOfh[i]>0) {//Wrong input polynomial ERROR("The lowest [-1,1] homogeneous summand of "+string(h)+" is of negative degree."); }//Wrong input polynomial } def ourHomeBase = basering; list hDist = homogDistributionNthWeyl(h); setring(sAlgebra); poly result = 0; poly tempResult; poly zeroPoly; ideal fromWeylMapideal; for (i = 1; i<=nvars(sAlgebra); i++) { fromWeylMapideal[i] = var(i); } map fromWeyl = ourHomeBase, fromWeylMapideal; setring(ourHomeBase); poly zeroPoly; poly tempZeroPoly; int j; int k; int l; intvec derDeg; intvec tempIntVec; for (i = 1; i<=size(hDist);i++) { derDeg = hDist[i][1]; setring(sAlgebra); tempResult = 1; setring(ourHomeBase); zeroPoly = hDist[i][2]; for (j = 1; j<=nvars(ourHomeBase) div 2; j++) {//lifting all the powers of the different ds away zeroPoly = lift(var((nvars(ourHomeBase) div 2) + j)^derDeg[j],zeroPoly)[1,1]; }//lifting all the powers of the different ds away for (j = 1; j<=size(zeroPoly); j++) { tempZeroPoly = zeroPoly[j]; setring(sAlgebra); zeroPoly = fromWeyl(tempZeroPoly); tempResult = tempResult * leadcoef(zeroPoly); setring(ourHomeBase); for (l = 1; l <= nvars(ourHomeBase) div 2; l++) {//iterating through all the d's tempIntVec = 0:nvars(ourHomeBase); tempIntVec[(nvars(ourHomeBase) div 2) + l] = 1; for (k = 1; k<=deg(zeroPoly[j],tempIntVec);k++) { setring(sAlgebra); tempResult = tempResult*(var(l)-(k-1)); setring(ourHomeBase); } }//iterating through all the d's setring(sAlgebra); for (l = 1; l<=nvars(sAlgebra) div 2; l++) { tempResult = tempResult*var((nvars(sAlgebra) div 2) + l)^derDeg[l]; } result = result + tempResult; tempResult = 1; setring(ourHomeBase); } } setring(sAlgebra); kill fromWeylMapideal; keepring(sAlgebra); }//fromNthWeylToNthShiftPoly static proc refineFactList(list L) { // assume: list L is an output of factorization proc // doing: remove doubled entries int s = size(L); int sm; int i,j,k,cnt; list M, U, A, B; A = L; k = 0; cnt = 1; for (i=1; i<=s; i++) { if (size(A[i]) != 0) { M = A[i]; // "probing with"; M; i; B[cnt] = M; cnt++; for (j=i+1; j<=s; j++) { if ( isEqualList(M,A[j]) ) { k++; // U consists of intvecs with equal pairs U[k] = intvec(i,j); A[j] = 0; } } } } kill A,U,M; return(B); } example { "EXAMPLE:";echo=2; ring R = 0,(x,s),dp; def r = nc_algebra(1,1); setring(r); list l,m; l = list(1,s2+1,x,s,x+s); m = l,list(1,s,x,s,x),l; refineFactList(m); } static proc isEqualList(list L, list M) { // int boolean: 1=yes, 0 =no : test whether two lists are identical int s = size(L); if (size(M)!=s) { return(0); } int j=1; while ( (L[j]==M[j]) && (j 0) {//We have two distict formulas for x and y. In this case use formula for x if (shift == 1) { result[i][j] = subst(result[i][j],theta,par(1)*theta + 1); } else { result[i][j] = subst(result[i][j], theta,par(1)^shift*theta+(par(1)^shift-1)/(par(1)-1)); } }//We have two distict formulas for x and y. In this case use formula for x } } }//adjust the a_0-parts }//Compute all possibilities to permute the x's resp. the y's in the list else {//The result is just all the permutations of the a_0-part result = permpp(list_azero); }//The result is just all the permutations of the a_0 part if (size(result)==0) { return(result); } dbprint(p," Done"); dbprint(p," Searching for theta resp. theta + 1 in the list and factorize them"); //Now we are going deeper and search for theta resp. theta + 1, substitute //them by xy resp. yx and go on permuting int found_theta; int thetapos; list leftpart; list rightpart; list lparts; list rparts; list tempadd; for (i = 1; i<=size(result) ; i++) {//checking every entry of result for theta or theta +1 found_theta = 0; for(j=1;j<=size(result[i]);j++) { if (result[i][j]==theta) {//the jth entry is theta and can be written as x*y thetapos = j; result[i]= insert(result[i],var(1),j-1); j++; result[i][j] = var(2); found_theta = 1; break; }//the jth entry is theta and can be written as x*y if(result[i][j] == par(1)*theta +1) { thetapos = j; result[i] = insert(result[i],var(2),j-1); j++; result[i][j] = var(1); found_theta = 1; break; } } if (found_theta) {//One entry was theta resp. theta +1 leftpart = result[i]; leftpart = leftpart[1..thetapos]; rightpart = result[i]; rightpart = rightpart[(thetapos+1)..size(rightpart)]; lparts = list(leftpart); rparts = list(rightpart); //first deal with the left part if (leftpart[thetapos] == var(1)) { shift_sign = 1; shiftvar = var(1); } else { shift_sign = -1; shiftvar = var(2); } for (j = size(leftpart); j>1;j--) {//drip x resp. y if (leftpart[j-1]==shiftvar) {//commutative j--; continue; }//commutative if (deg(leftpart[j-1],intvec(-1,1,0))!=0) {//stop here break; }//stop here //Here, we can only have a a0- part if (shift_sign<0) { leftpart[j] = subst(leftpart[j-1],theta, 1/par(1)*(theta +shift_sign)); } if (shift_sign>0) { leftpart[j] = subst(leftpart[j-1],theta, par(1)*theta + shift_sign); } leftpart[j-1] = shiftvar; lparts = lparts + list(leftpart); }//drip x resp. y //and now deal with the right part if (rightpart[1] == var(1)) { shift_sign = 1; shiftvar = var(1); } else { shift_sign = -1; shiftvar = var(2); } for (j = 1 ; j < size(rightpart); j++) { if (rightpart[j+1] == shiftvar) { j++; continue; } if (deg(rightpart[j+1],intvec(-1,1,0))!=0) { break; } if (shift_sign<0) { rightpart[j] = subst(rightpart[j+1], theta, par(1)*theta - shift_sign); } if (shift_sign>0) { rightpart[j] = subst(rightpart[j+1], theta, 1/par(1)*(theta - shift_sign)); } rightpart[j+1] = shiftvar; rparts = rparts + list(rightpart); } //And now, we put all possibilities together tempadd = list(); for (j = 1; j<=size(lparts); j++) { for (k = 1; k<=size(rparts);k++) { tempadd = tempadd + list(lparts[j]+rparts[k]); } } tempadd = delete(tempadd,1); // The first entry is already in the list result = result + tempadd; continue; //We can may be not be done already with the ith entry }//One entry was theta resp. theta +1 }//checking every entry of result for theta or theta +1 dbprint(p," Done"); //map back to the basering dbprint(p," Mapping back everything to the basering"); setring(r); map finalmap = tempRing, var(1), var(2),var(1)*var(2); list result = finalmap(result); for (i=1; i<=size(result);i++) {//adding the K factor result[i] = k_factor + result[i]; }//adding the k-factor dbprint(p," Done"); dbprint(p," Delete double entries in the list."); result = delete_dublicates_noteval(result); dbprint(p," Done"); return(result); }//proc HomogfacFirstQWeylAll_old proc homogfacFirstQWeyl_all(poly h) "USAGE: homogfacFirstQWeyl_all(h); h is a homogeneous polynomial in the first q-Weyl algebra with respect to the weight vector [-1,1] RETURN: list PURPOSE: Computes all factorizations of a homogeneous polynomial h with respect to the weight vector [-1,1] in the first q-Weyl algebra THEORY: This function is a wrapper for homogFacNthQWeyl_all. It exists to make this library downward-compatible with older versions. SEE ALSO: homogfacFirstQWeyl "{//proc HomogfacFirstQWeylAll_old return(homogfacNthQWeyl_all(h)); }//proc HomogfacFirstQWeylAll_old example { "EXAMPLE:";echo=2; ring R = (0,q),(x,d),dp; def r = nc_algebra (q,1); setring(r); poly h = q^25*x^10*d^10+q^16*(q^4+q^3+q^2+q+1)^2*x^9*d^9+ q^9*(q^13+3*q^12+7*q^11+13*q^10+20*q^9+26*q^8+30*q^7+ 31*q^6+26*q^5+20*q^4+13*q^3+7*q^2+3*q+1)*x^8*d^8+ q^4*(q^9+2*q^8+4*q^7+6*q^6+7*q^5+8*q^4+6*q^3+ 4*q^2+2q+1)*(q^4+q^3+q^2+q+1)*(q^2+q+1)*x^7*d^7+ q*(q^2+q+1)*(q^5+2*q^4+2*q^3+3*q^2+2*q+1)*(q^4+q^3+q^2+q+1)*(q^2+1)*(q+1)*x^6*d^6+ (q^10+5*q^9+12*q^8+21*q^7+29*q^6+33*q^5+31*q^4+24*q^3+15*q^2+7*q+12)*x^5*d^5+ 6*x^3*d^3+24; homogfacFirstQWeyl_all(h); } //================================================== // Homogeneous factorization of the nth q-Weyl algebra //================================================== proc homogfacNthQWeyl(poly h) "USAGE: homogfacNthQWeyl(h); h is a homogeneous polynomial in the n'th q-Weyl algebra with respect to the weight vector [-1,...,-1,1,...,1]. \__ __/ \__ __/ \/ \/ n/2 n/2 RETURN: list PURPOSE: Computes a factorization of a homogeneous polynomial h in the n'th q-Weyl algebra THEORY:@code{homogfacNthQWeyl} returns a list with a factorization of the given, [-1,1]-homogeneous polynomial. For every i in 1..n: If the degree of the polynomial in [d_i,x_i] is k with k positive, the last entries in the output list are the second variable. If k is positive, the last k entries will be x_i. The other entries will be irreducible polynomials of degree zero or 1 resp. -1. resp. other variables GENERAL ASSUMPTIONS: - The basering is the nth Weyl algebra and has the form, that the first n variables represent x1, ..., xn, and the second n variables do represent the d1, ..., dn. - We have n parameters q_1,..., q_n given. SEE ALSO: homogfacFirstQWeyl, homogfacFirstQWeyl_all, homogfacNthQWeyl_all " {//proc homogfacNthQWeyl int p = printlevel-voice+2;//for dbprint poly hath = h; def r = basering; int i; int j; int k; string dbprintWhitespace = ""; for (i = 1; i<=voice;i++) {dbprintWhitespace = dbprintWhitespace + " ";} intvec ivm11 = intvec(-1,1); if(!checkIfProperNthQWeyl()) {//checking whether the given ring is proper q-Weyl ERROR("Assumptions on the ring structure not met."); return(list()); }//checking whether the given ring is proper q-Weyl if (!homogwithorderNthWeyl(h)) {//The given polynomial is not homogeneous ERROR("Given polynomial was not [-1,...,-1,1,...,1]-homogeneous"); return(list()); }//The given polynomial is not homogeneous if (h==0) { return(list(0)); } list result; intvec m = degreeOfNthWeylPoly(h); dbprint(p,dbprintWhitespace +" Splitting the polynomial in Q_0 and Q_k-Part"); dbprint(p,dbprintWhitespace + "Its [-1,...,-1,1,...,1] degree is "+string(m)); for (j = 1; j<=nvars(basering) div 2; j++) {//extracting the respective variable for every position dbprint(p,dbprintWhitespace + "Considering variables x_"+string(j)+" and d" + string(j)); if (m[j]!=0) {//The degree is not zero if (m[j] <0) {//There are more x than d hath = lift(var(j)^(-m[j]),hath)[1,1]; for (i = 1; i<=-m[j]; i++) { result = result + list(var(j)); } }//There are more x than d else {//There are more d than x hath = lift(var(nvars(basering) div 2 + j)^m[j],hath)[1,1]; for (i = 1; i<=m[j];i++) { result = result + list(var(nvars(basering) div 2 + j)); } }//There are more d than x }//The degree is not zero }//extracting the respective variable for every position dbprint(p,dbprintWhitespace+" Done"); //beginning to factor the zero-homogeneous part list mons; dbprint(p,dbprintWhitespace+" Putting the monomials in the Q_0-part in a list."); for(i = 1; i<=size(hath);i++) {//Putting the monomials in a list mons = mons+list(hath[i]); }//Putting the monomials in a list dbprint(p,dbprintWhitespace+" Done"); dbprint(p,dbprintWhitespace+" Mapping these monomials to K[theta_1,... , theta_n]"); list parameterNames; for (i = 1; i<=(nvars(basering) div 2); i++) {//saving the names of the parameters parameterNames[i] = ringlist(basering)[1][2][i]; }//saving the names of the parameters ring tempRingPre = (0,q(1..(nvars(basering) div 2))), (x(1..(nvars(basering) div 2)), d(1..(nvars(basering) div 2)), theta(1..(nvars(basering) div 2))),dp; list ringListTempRingPre = ringlist(tempRingPre); for (i = 1; i<=size(ringListTempRingPre[1][2]); i++) {//setting the same name for the parameters ringListTempRingPre[1][2][i] = parameterNames[i]; }//setting the same name for the parameters def tempRing = ring(ringListTempRingPre); setring(tempRing); ideal mapList; for (i = 1; i<=nvars(r) ; i++) {//filling the list of elements we want to map mapList[i] = var(i); }//filling the list of elements we want to map map thetamap = r,mapList; list mons = thetamap(mons); poly entry; intvec lExp; poly tempSummand; for (i = 1; i<=size(mons);i++) {//transforming the monomials as monomials in theta entry = leadcoef(mons[i]); lExp = leadexp(mons[i]); for (k = 1; k<=nvars(r) div 2; k++) {//iterating over the pairs x_kd_k for (j = 0; j0) { result[i][j] = subst(result[i][j],theta(k),par(k)^(shift[k])*theta(k) +(1-par(k)^(shift[k]))/(1-par(k))); } } } }//factor was a theta poly }//iterating through each factor }//adjust the a_0-parts }//Compute all possibilities to permute the x's resp. the y's in the list else {//The result is just all the permutations of the a_0-part result = permpp(list_azero); }//The result is just all the permutations of the a_0 part if (size(result)==0) { return(normalizeFactors(result)); } dbprint(p,dbprintWhitespace +" Done"); dbprint(p, dbprintWhitespace + "The factorization list is now:"); dbprint(p,result); dbprint(p, dbprintWhitespace + "Checking whether the intermediate result is correct or not"); dbprint(p,testNCfac(result)); dbprint(p,dbprintWhitespace +" Searching for theta resp. theta+1 in the list and fact. them"); //Now we are going deeper and search for theta resp. theta + 1, substitute //them by xy resp. yx and go on permuting int found_theta; int thetapos; int shift_sign; int thetaIndex; poly shiftvar; list leftpart; list rightpart; list lparts; list rparts; list tempadd; for (i = 1; i<=size(result) ; i++) {//checking every entry of result for theta or theta +1 found_theta = 0; for(j=1;j<=size(result[i]);j++) {//iterating through all factors for (k = 1; k<=nvars(r) div 2; k++) {//iterating through the variables if (result[i][j]==theta(k)) {//the jth entry is theta and can be written as x*y thetapos = j; thetaIndex = k; result[i]= insert(result[i],x(k),j-1); j++; result[i][j] = d(k); found_theta = 1; break; }//the jth entry is theta and can be written as x*y if(result[i][j] == theta(k) +1/par(k)) { thetapos = j; thetaIndex = k; result[i] = insert(result[i],d(k),j-1); j++; result[i][j] = x(k); found_theta = 1; break; } }//iterating through the variables if(found_theta) {break;} }//iterating through all factors if (found_theta) {//One entry was theta resp. theta +1 leftpart = result[i]; leftpart = leftpart[1..thetapos]; rightpart = result[i]; rightpart = rightpart[(thetapos+1)..size(rightpart)]; lparts = list(leftpart); rparts = list(rightpart); //first deal with the left part if (leftpart[thetapos] == x(thetaIndex)) { shift_sign = 1; shiftvar = x(thetaIndex); } else { shift_sign = -1; shiftvar = d(thetaIndex); } for (j = size(leftpart); j>1;j--) {//drip x resp. y if (leftpart[j-1]==shiftvar) {//commutative j--; continue; }//commutative if (leadexp(leftpart[j-1])[thetaIndex + nvars(r) div 2] - leadexp(leftpart[j-1])[thetaIndex]!=0) {//stop here break; }//stop here //Here, we can only have a a0- part if (shift_sign<0) { leftpart[j] = subst(leftpart[j-1],theta(thetaIndex), 1/par(thetaIndex)*(theta(thetaIndex)+shift_sign)); } else { if (shift_sign>0) { leftpart[j] = subst(leftpart[j-1],theta(thetaIndex), par(thetaIndex)*theta(thetaIndex)+shift_sign); } } leftpart[j-1] = shiftvar; lparts = lparts + list(leftpart); }//drip x resp. y //and now deal with the right part if (rightpart[1] == x(thetaIndex)) { shift_sign = 1; shiftvar = x(thetaIndex); } else { shift_sign = -1; shiftvar = d(thetaIndex); } for (j = 1 ; j < size(rightpart); j++) { if (rightpart[j+1] == shiftvar) { j++; continue; } if (leadexp(rightpart[j+1])[thetaIndex + nvars(r) div 2] - leadexp(rightpart[j+1])[thetaIndex]!=0) { break; } if (shift_sign<0) { rightpart[j] = subst(rightpart[j+1], theta(thetaIndex), par(thetaIndex)*theta(thetaIndex)+1); } else { if (shift_sign > 0) { rightpart[j] = subst(rightpart[j+1], theta(thetaIndex), 1/par(thetaIndex)*(theta(thetaIndex)-1)); } } rightpart[j+1] = shiftvar; rparts = rparts + list(rightpart); } //And now, we put all possibilities together tempadd = list(); for (j = 1; j<=size(lparts); j++) { for (k = 1; k<=size(rparts);k++) { tempadd = tempadd + list(lparts[j]+rparts[k]); } } tempadd = delete(tempadd,1); // The first entry is already in the list result = result + tempadd; continue; //We can may be not be done already with the ith entry }//One entry was theta resp. theta +1 }//checking every entry of result for theta or theta +1 dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace + "The new result list is:"); dbprint(result); setring(r); ideal finalMapList; for(i = 1; i<=nvars(r);i++) { finalMapList[i] = var(i); } for (i = 1; i<=nvars(r) div 2; i++) { finalMapList[i + nvars(r)] = var(i)*var(i + (nvars(r) div 2)); } map finalmap = tempRing,finalMapList; list result = finalmap(result); for (i=1; i<=size(result);i++) {//adding the K factor result[i] = k_factor + result[i]; }//adding the k-factor dbprint(p,dbprintWhitespace +" Done"); dbprint(p,dbprintWhitespace +" Delete double entries in the list."); result = delete_dublicates_noteval(result); dbprint(p,dbprintWhitespace +" Done"); return(normalizeFactors(result)); }//proc homogfacNthQWeyl_all example { "EXAMPLE:";echo=2; ring R = (0,q1,q2,q3),(x1,x2,x3,d1,d2,d3),dp; matrix C[6][6] = 1,1,1,q1,1,1, 1,1,1,1,q2,1, 1,1,1,1,1,q3, 1,1,1,1,1,1, 1,1,1,1,1,1, 1,1,1,1,1,1; matrix D[6][6] = 0,0,0,1,0,0, 0,0,0,0,1,0, 0,0,0,0,0,1, -1,0,0,0,0,0, 0,-1,0,0,0,0, 0,0,-1,0,0,0; def r = nc_algebra(C,D); setring(r); poly h =x1*x2^2*x3^3*d1*d2^2+x2*x3^3*d2; homogfacNthQWeyl_all(h); } //================================================== // EASY EXAMPLES FOR WEYL ALGEBRA //================================================== /* Easy and fast example polynomials where one can find factorizations: K (x^2+d)*(x^2+d); (x^2+x)*(x^2+d); (x^3+x+1)*(x^4+d*x+2); (x^2*d+d)*(d+x*d); d^3+x*d^3+2*d^2+2*(x+1)*d^2+d+(x+2)*d; //Example 5 Grigoriev-Schwarz. (d+1)*(d+1)*(d+x*d); //Landau Example projected to the first dimension. */ //================================================== //Some Bugs(fixed)/hard examples from Martin Lee: //================================================== // ex1, ex2 /* ring s = 0,(x,d),Ws(-1,1); def S = nc_algebra(1,1); setring S; poly a = 10x5d4+26x4d5+47x5d2-97x4d3; //Not so hard any more... Done in around 4 minutes def l= facFirstWeyl (a); l; kill l; poly b = -5328x8d5-5328x7d6+720x9d2+720x8d3-16976x7d4-38880x6d5 -5184x7d3-5184x6d4-3774x5d5+2080x8d+5760x7d2-6144x6d3-59616x5d4 +3108x3d6-4098x6d2-25704x5d3-21186x4d4+8640x6d-17916x4d3+22680x2d5 +2040x5d-4848x4d2-9792x3d3+3024x2d4-10704x3d2-3519x2d3+34776xd4 +12096xd3+2898d4-5040x2d+8064d3+6048d2; //Still very hard... But it seems to be only because of the //combinatorial explosion def l= facFirstWeyl (b); l; // ex3: there was difference in answers => fixed LIB "ncfactor.lib"; ring r = 0,(x,y,z),dp; matrix D[3][3]; D[1,3]=-1; def R = nc_algebra(1,D); setring R; poly g= 7*z4*x+62*z3+26*z; def l1= facSubWeyl (g, x, z); l1; //---- other ring ring s = 0,(x,z),dp; def S = nc_algebra(1,-1); setring S; poly g= 7*z4*x+62*z3+26*z; def l2= facFirstWeyl (g); l2; map F = R,x,0,z; list l1 = F(l1); l1; //---- so the answers look different, check them! testNCfac(l2); // ok testNCfac(l1); // was not ok, but now it's been fixed!!! // selbst D und X so vertauschen dass sie erfuellt ist : ist gemacht */ /* // bug from M Lee LIB "ncfactor.lib"; ring s = 0,(z,x),dp; def S = nc_algebra(1,1); setring S; poly f= -60z4x2-54z4-56zx3-59z2x-64; def l= facFirstWeyl (f); l; // before: empty list; after fix: 1 entry, f is irreducible poly g = 75z3x2+92z3+24; def l= facFirstWeyl (g); l; //before: empty list, now: correct */ /* more things from Martin Lee; fixed ring R = 0,(x,s),dp; def r = nc_algebra(1,s); setring(r); poly h = (s2*x+x)*s; h= h* (x+s); def l= facFirstShift(h); l; // contained doubled entries: not anymore, fixed! ring R = 0,(x,s),dp; def r = nc_algebra(1,-1); setring(r); poly h = (s2*x+x)*s; h= h* (x+s); def l= facFirstWeyl(h); l; // contained doubled entries: not anymore, fixed! */ //====================================================================== //Examples from TestSuite that are terminating in a reasonable time. //====================================================================== //Counter example for old Algorithm, but now working: /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "ncfactor.lib"; poly h = (1+x^2*d)^4; list lsng = facFirstWeyl(h); print(lsng); */ //Example 2.7. from Master thesis /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "ncfactor.lib"; poly h = (xdd + xd+1+ (xd+5)*x)*(((x*d)^2+1)*d + xd+3+ (xd+7)*x); list lsng = facFirstWeyl(h); print(lsng); */ //Example with high combinatorial income /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "ncfactor.lib"; poly h = (xdddd + (xd+1)*d*d+ (xd+5)*x*d*d)*(((x*d)^2+1)*d*x*x + (xd+3)*x*x+ (xd+7)*x*x*x); list lsng = facFirstWeyl(h); print(lsng); */ //Once a bug, now working /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "ncfactor.lib"; poly h = (x^2*d^2+x)*(x+1); list lsng = facFirstWeyl(h); print(lsng); */ //Another one of that kind /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "ncfactor.lib"; poly h = (x*d*d + (x*d)^5 +x)*((x*d+1)*d-(x*d-1)^5+x); list lsng = facFirstWeyl(h); print(lsng); */ //Example of Victor for Shift Algebra /* ring s = 0,(n,Sn),dp; def S = nc_algebra(1,Sn); setring S; LIB "ncfactor.lib"; list lsng = facFirstShift(n^2*Sn^2+3*n*Sn^2-n^2+2*Sn^2-3*n-2); print(lsng); */ //Interesting example, as there are actually also some complex solutions to it: /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "/Users/albertheinle/Studium/forschung/ncfactor/versionen/ncfactor.lib"; poly h =(x^3+x+1)*(x^4+d*x+2);//Example for finitely many, but more than one solution in between. list lsng = facFirstWeyl(h); print(lsng); */ //Another one of that kind: /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "ncfactor.lib"; poly h =(x^2+d)*(x^2+d);//Example for finitely many, but more than one solution in between. list lsng = facFirstWeyl(h); print(lsng); */ //Example by W. Koepf: /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "ncfactor.lib"; poly h = (x^4-1)*x*d^2+(1+7*x^4)*d+8*x^3; list lsng = facFirstWeyl(h); print(lsng); */ //Shift Example from W. Koepf /* ring R = 0,(n,s),dp; def r = nc_algebra(1,s); setring(r); LIB "ncfactor.lib"; poly h = n*(n+1)*s^2-2*n*(n+100)*s+(n+99)*(n+100); list lsng = facFirstShift(h); print(lsng); */ //Tsai Example... Once hard, now easy... /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "ncfactor.lib"; poly h = (x^6+2*x^4-3*x^2)*d^2-(4*x^5-4*x^4-12*x^2-12*x)*d + (6*x^4-12*x^3-6*x^2-24*x-12); list lsng =facFirstWeyl(h); print(lsng); */ //====================================================================== // Hard examples not yet calculatable in feasible amount of time //====================================================================== //Also a counterexample for REDUCE. Very long Groebner basis computation in between. /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); LIB "ncfactor.lib"; poly h = (d^4+x^2+dx+x)*(d^2+x^4+xd+d); list lsng = facFirstWeyl(h); print(lsng); */ //Example from the Mainz-Group /* ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); poly dop6 = 1/35*x^4*(27-70*x+35*x^2)+ 1/35*x*(32+152*x+100*x^2-59*x^3+210*x^4+105*x^5)*d+ (-10368/35-67056/35*x-35512/7*x^2-50328/7*x^3-40240/7*x^4-2400*x^5-400*x^6)*d^2+ (-144/35*(x+1)*(1225*x^5+11025*x^4+37485*x^3+61335*x^2+50138*x+16584)-6912/35*(x+2)* (x+1)*(105*x^4+1155*x^3+4456*x^2+7150*x+4212) -27648/35*(x+3)*(x+1)*(35*x^2+350*x+867)* (x+2)^2)*d^3; LIB "ncfactor.lib"; printlevel = 5; facFirstWeyl(dop6); $;*/ //Another Mainz Example: /* LIB "ncfactor.lib"; ring R = 0,(x,d),dp; def r = nc_algebra(1,1); setring(r); poly dopp = 82547*x^4*d^4+60237*x^3*d^3+26772*x^5*d^5+2231*x^6*d^6+x*(1140138* x^2*d^2-55872*x*d-3959658*x^3*d^3-8381805*x^4*d^4-3089576*x^5*d^5-274786* x^6*d^6)+x^2*(-16658622*x*d-83427714*x^2*d^2-19715033*x^3*d^3+78915395*x^4 *d^4+35337930*x^5*d^5+3354194*x^6*d^6)+x^3*(-99752472-1164881352*x*d+ 4408536996*x^2*d^2+11774185985*x^3*d^3+5262196786*x^4*d^4+1046030561/2*x^5* d^5-10564451/2*x^6*d^6)+x^4*(-1925782272+21995375398*x*d+123415803356*x^2* d^2+302465300831/2*x^3*d^3+34140803907/2*x^4*d^4-15535653409*x^5*d^5-\ 2277687768*x^6*d^6)+x^5*(71273525520+691398212366*x*d+901772633569*x^2*d^2+ 2281275427069*x^3*d^3+2944352819911/2*x^4*d^4+836872370039/4*x^5*d^5+ 9066399237/4*x^6*d^6)+x^6*(2365174430376+9596715855542*x*d+29459572469704*x^ 2*d^2+92502197003786*x^3*d^3+65712473180525*x^4*d^4+13829360193674*x^5*d^5 +3231449477251/4*x^6*d^6)+x^7*(26771079436836+117709870166226*x*d+ 821686455179082*x^2*d^2+1803972139232179*x^3*d^3+1083654460691481*x^4*d^4+ 858903621851785/4*x^5*d^5+50096565802957/4*x^6*d^6)+x^8*(179341727601960+ 2144653944040630*x*d+13123246960284302*x^2*d^2+41138357917778169/2*x^3*d^3+ 20605819587976401/2*x^4*d^4+3677396642905423/2*x^5*d^5+402688260229369/4*x^6 *d^6)+x^9*(2579190935961288+43587063726809764*x*d+157045086382352387*x^2*d^ 2+172175668477370223*x^3*d^3+138636285385875407/2*x^4*d^4+10707836398626232* x^5*d^5+529435530567584*x^6*d^6)+x^10*(41501953525903392+558336731465626084* x*d+1407267553543222268*x^2*d^2+1153046693323226808*x^3*d^3+ 372331468563656085*x^4*d^4+48654019090240214*x^5*d^5+2114661191282167*x^6*d ^6)+x^11*(364526077273381884+4158060401095928464*x*d+8646807662899324262*x^2* d^2+5914675753405705400*x^3*d^3+1631934058875116005*x^4*d^4+ 187371894330537204*x^5*d^5+7366806367019734*x^6*d^6)+x^12*( 1759850321214603648+18265471270535733520*x*d+34201910114871110912*x^2*d^2+ 21265221434709398152*x^3*d^3+5437363546219595036*x^4*d^4+594029113431041060* x^5*d^5+22881659624561644*x^6*d^6)+x^13*(4648382639403200688+ 45699084277107816096*x*d+81049061578449009384*x^2*d^2+48858488665016574368*x ^3*d^3+12515362110098721444*x^4*d^4+1412152747420021048*x^5*d^5+ 57196947123984972*x^6*d^6)+x^14*(5459369397960020544+55837825300341621824*x* d+105671876924055409696*x^2*d^2+71551727420848766624*x^3*d^3+ 21094786205096577808*x^4*d^4+2695663190297032192*x^5*d^5+118791751565613264* x^6*d^6)+x^15*(1023333653580043776+47171127937488813824*x*d+ 157258351906685700352*x^2*d^2+145765192195300531840*x^3*d^3+ 49876215785510342176*x^4*d^4+6647374188802036864*x^5*d^5+287310278455067312* x^6*d^6)+x^16*(11960091747366236160+250326608568269289472*x*d+ 677587171115580981248*x^2*d^2+538246374825683603456*x^3*d^3+ 161380433451548754048*x^4*d^4+19149099315354950144*x^5*d^5+ 746433247985092544*x^6*d^6)+x^17*(42246252365448668160+657220532737851248640* x*d+1531751689216283911680*x^2*d^2+1090829514212206064640*x^3*d^3+ 299280728709430851840*x^4*d^4+32932767387222323200*x^5*d^5+ 1202281367574179840*x^6*d^6)+x^18*(6239106101942784000+320638742839606579200* x*d+873857213570556364800*x^2*d^2+645649080101933721600*x^3*d^3+ 177008238160627276800*x^4*d^4+19165088507111475200*x^5*d^5+ 683600826675660800*x^6*d^6)+x^19*(-60440251454613504000-476055211197689856000 *x*d-733497382597635072000*x^2*d^2-386038662982742016000*x^3*d^3-\ 83361486778142976000*x^4*d^4-7524999543181824000*x^5*d^5-232189492987008000* x^6*d^6)+x^20*(1578562930483200000+12628503443865600000*x*d+ 19732036631040000000*x^2*d^2+10523752869888000000*x^3*d^3+ 2302070940288000000*x^4*d^4+210475057397760000*x^5*d^5+6577345543680000*x^6* d^6); printlevel = 3; facFirstWeyl(dopp); */ //Hard Example by Viktor: /* ring r = 0,(x,d), (dp); def R = nc_algebra(1,1); setring R; LIB "ncfactor.lib"; poly t = x; poly D =d; poly p = 2*t^2*D^8-6*t*D^8+2*t^2*D^7+8*t*D^7+12*D^7-2*t^4*D^6+6*t^3*D^6+12*t*D^6-20*D^6 -2*t^4*D^5-8*t^3*D^5-4*t^2*D^5+12*t*D^5-28*D^5-12*t^3*D^4-4*t^2*D^4-4*t*D^4-24*D^4+4*t^4*D^3 -12*t^3*D^3+2*t^2*D^3-18*t*D^3+16*D^3+6*t^4*D^2-2*t^3*D^2+2*t^2*D^2-2*t*D^2+44*D^2+2*t^4*D +12*t^3*D+2*t*D+4*t^3-8; list lsng = facFirstWeyl(p); print(lsng); */ /*later hard example From Beals-Kartashova paper ring R = 0, (x1,x2,d1,d2),dp;def r = Weyl();setring(r); poly h = d1^2 -d2^2 + x1*d2 + x2*d1 + 1/4*(x2^2 - x1^2) +1; */ singular-4.0.3+ds/Singular/LIB/nchomolog.lib000066400000000000000000000507121266270727000206310ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version nchomolog.lib 4.0.0.0 Jun_2013 "; // $Id: 4d7c72c150b707e8f0f10ce0382d235c8015a98e $ category="Noncommutative"; info=" LIBRARY: nchomolog.lib Procedures for Noncommutative Homological Algebra AUTHORS: Viktor Levandovskyy levandov@math.rwth-aachen.de, @* Christian Schilli, christian.schilli@rwth-aachen.de, @* Gerhard Pfister, pfister@mathematik.uni-kl.de OVERVIEW: In this library we present tools of homological algebra for finitely presented modules over GR-algebras. PROCEDURES: ncExt_R(k,M); computes presentation of Ext^k(M',R), M module, R basering, M'=coker(M) ncHom(M,N); computes presentation of Hom(M',N'), M,N modules, M'=coker(M), N'=coker(N) coHom(A,k); computes presentation of Hom(R^k,A), A matrix over basering R contraHom(A,k); computes presentation of Hom(A,R^k), A matrix over basering R dmodoublext(M, l); computes presentation of Ext_D^i(Ext_D^i(M,D),D), where D is a basering is_cenBimodule(M); checks whether a module presented by M is Artin-centralizing is_cenSubbimodule(M); checks whether a subbimodule M is Artin-centralizing "; LIB "dmod.lib"; LIB "gkdim.lib"; LIB "involut.lib"; LIB "nctools.lib"; LIB "ncalg.lib"; LIB "central.lib"; // ncExt(k,M,N); Ext^k(M',N'), M,N modules, M'=coker(M), N'=coker(N) // ncTensorMod(M,N); Tensor product of modules M'=coker(M), N'=coker(N) // ncTor(k,M,N); Tor_k(M',N'), M,N modules, M'=coker(M), N'=coker(N) // tensorMaps(M,N); tensor product of matrices /* LOG: 5.12.2012, VL: cleanup, is_cenSubbimodule and is_cenBimodule are added for assume checks; added doc for contraHom and coHom; assume check for ncHom etc. */ /* TODO: add noncomm examples to important precedures ncHom, */ proc contraHom(matrix M, int s) "USAGE: contraHom(A,k); A matrix, k int RETURN: matrix PURPOSE: compute the matrix of a homomorphism Hom(A,R^k), where R is the basering. Let A be a matrix defining a map F1-->F2 of free R-modules, then the matrix of Hom(F2,R^k)-->Hom(F1,R^k) is computed. NOTE: if A is matrix of a left (resp. right) R-module homomorphism, then Hom(A,R^k) is a right (resp. left) R-module R-module homomorphism EXAMPLE: example contraHom; shows an example. SEE ALSO: " { // also possible: compute with kontrahom from homolog_lib // and warn that the module changes its side int n,m=ncols(M),nrows(M); int a,b,c; matrix R[s*n][s*m]; for(b=1; b<=m; b++) { for(a=1; a<=s; a++) { for(c=1; c<=n; c++) { R[(a-1)*n+c,(a-1)*m+b] = M[b,c]; } } } return(R); } example { "EXAMPLE:"; echo = 2; ring A=0,(x,y,z),dp; matrix M[3][3]=1,2,3, 4,5,6, 7,8,9; module cM = contraHom(M,2); print(cM); } proc coHom(matrix M, int s) "USAGE: coHom(A,k); A matrix, k int PURPOSE: compute the matrix of a homomorphism Hom(R^k,A), where R is the basering. Let A be a matrix defining a map F1-->F2 of free R-modules, then the matrix of Hom(R^k,F1)-->Hom(R^k,F2) is computed. NOTE: Both A and Hom(A,R^k) are matrices for either left or right R-module homomorphisms EXAMPLE: example coHom; shows an example. " { int n,m=ncols(M),nrows(M); int a,b,c; matrix R[s*m][s*n]; for(b=1; b<=s; b++) { for(a=1; a<=m; a++) { for(c=1; c<=n; c++) { R[(a-1)*s+b,(c-1)*s+b] = M[a,c]; } } } return(R); } example { "EXAMPLE:"; echo = 2; ring A=0,(x,y,z),dp; matrix M[3][3]=1,2,3, 4,5,6, 7,8,9; module cM = coHom(M,2); print(cM); } proc ncHom(matrix M, matrix N) "USAGE: ncHom(M,N); M,N modules COMPUTE: A presentation of Hom(M',N'), M'=coker(M), N'=coker(N) ASSUME: M' is a left module, N' is a centralizing bimodule NOTE: ncHom(M,N) is a right module, hence a right presentation matrix is returned EXAMPLE: example ncHom; shows examples " { // assume: M is left module; nothing to check // assume: N is centralizing bimodule: to check if ( !is_cenBimodule(N) ) { ERROR("Second module in not centralizing."); } // returns a right presentation matrix (for a right module) matrix F = contraHom(M,nrows(N)); matrix B = coHom(N,ncols(M)); matrix C = coHom(N,nrows(M)); def Rbase = basering; def Rop = opposite(Rbase); setring Rop; matrix Bop = oppose(Rbase, B); matrix Cop = oppose(Rbase, C); matrix Fop = oppose(Rbase, F); matrix Dop = modulo(Fop, Bop); matrix Eop = modulo(Dop, Cop); setring Rbase; matrix E = oppose(Rop, Eop); kill Rop; return(E); } example { "EXAMPLE:"; echo = 2; ring A=0,(x,y,z),dp; matrix M[3][3]=1,2,3, 4,5,6, 7,8,9; matrix N[2][2]=x,y, z,0; module H = ncHom(M,N); print(H); } proc ncHom_alt(matrix M, matrix N) { // shorter but potentially slower matrix F = contraHom(M,nrows(N)); // \varphi^* matrix B = coHom(N,ncols(M)); // i matrix C = coHom(N,nrows(M)); // j matrix D = rightModulo(F,B); // D matrix E = rightModulo(D,C); // Hom(M,N) return(E); } example { "EXAMPLE:"; echo = 2; ring A=0,(x,y,z),dp; matrix M[3][3]=1,2,3, 4,5,6, 7,8,9; matrix N[2][2]=x,y, z,0; module H = ncHom_alt(M,N); print(H); } proc ncHom_R(matrix M) "USAGE: ncHom_R(M); M a module COMPUTE: A presentation of Hom_R(M',R), M'=coker(M) ASSUME: M' is a left module NOTE: ncHom_R(M) is a right module, hence a right presentation matrix is returned EXAMPLE: example ncHom_R; shows examples " { // assume: M is left module // returns a right presentation matrix // for a right module matrix F = transpose(M); def Rbase = basering; def Rop = opposite(Rbase); setring Rop; matrix Fop = oppose(Rbase, F); matrix Dop = modulo(Fop, std(0)); //ker Hom(A^n,A) -> Hom(A^m,A) matrix Eop = modulo(Dop, std(0)); // its presentation setring Rbase; matrix E = oppose(Rop, Eop); kill Rop; return(E); } example { "EXAMPLE:"; echo = 2; ring A=0,(x,t,dx,dt),dp; def W = Weyl(); setring W; matrix M[2][2] = dt, dx, t*dx,x*dt; module H = ncHom_R(M); print(H); matrix N[2][1] = x,dx; H = ncHom_R(N); print(H); } proc is_cenBimodule(module M) "USAGE: is_cenBimodule(M); M module COMPUTE: 1, if a module, presented by M can be centralizing in the sense of Artin and 0 otherwise NOTE: only one condition for centralizing factor module can be checked algorithmically EXAMPLE: example is_cenBimodule; shows examples " { // define in a ring R, for a module R: cen(M) ={ m in M: mr = rm for all r in R} // according to the definition, M is a centralizing bimodule <=> M is generated by cen(M) // if basering R is a G-algebra, then prop 6.4 of BGV indicates it's enough to provide // commutation of elements of M with the generators x_i of R // prop 6.4 verbatim generalizes to R = R'/I for a twosided I. // is M generates submodule, see the proc is_cenSubbimodule // let M be a presentation matrix for P=R*/R*M, then [e_i + M]x_j=x_j[e_i+M] // <=> Mx_j - x_jM in M must hold; thus forall j: Mx_j in M; thus M has to be // closed from the right, that is to be a two-sided submodule indeed // the rest of checks are complicated by now, so do the check only // *the algorithm *// if (isCommutative() ) { return(int(1));} int n = nvars(basering); int ans = 0; int i,j; vector P; module N; if ( attrib(M,"isSB") != 1) { N = std(M); } else { N = M; } // N is std(M) now for(i=1; i<=ncols(M); i++) { P = M[i]; if (P!=0) { for(j=1; j<=n; j++) { if ( NF(P*var(j) - var(j)*P, N) != 0) { return(ans); } } } } ans = 1; return(ans); } example { "EXAMPLE:"; echo = 2; def A = makeUsl2(); setring A; poly p = 4*e*f + h^2-2*h; // generator of the center matrix M[2][2] = p, p^2-7,0,p*(p+1); is_cenBimodule(M); // M is centralizing matrix N[2][2] = p, e*f,h,p*(p+1); is_cenBimodule(N); // N is not centralizing } proc is_cenSubbimodule(module M) "USAGE: is_cenSubbimodule(M); M module COMPUTE: 1, if a subbimodule, generated by the columns of M is centralizing in the sense of Artin and 0 otherwise EXAMPLE: example is_cenSubbimodule; shows examples " { // note: M in R^m is centralizing subbimodule iff it is generated by vectors, // each nonconstant component of which is central; 2 check: every entry of the // matrix M is central if (isCommutative()) { return(int(1));} return( inCenter(ideal(matrix(M))) ); } example { "EXAMPLE:"; echo = 2; def A = makeUsl2(); setring A; poly p = 4*e*f + h^2-2*h; // generator of the center matrix M[2][2] = p, p^2-7,0,p*(p+1); is_cenSubbimodule(M); // M is centralizing subbimodule matrix N[2][2] = p, e*f,h,p*(p+1); is_cenSubbimodule(N); // N is not centralizing subbimodule } proc ncExt(int i, matrix Ps, matrix Ph) "USAGE: Ext(i,M,N); i int, M,N matrices COMPUTE: A presentation of Ext^i(M',N'); for M'=coker(M) and N'=coker(N). ASSUME: M' is a left module, N' is a centralizing bimodule NOTE: ncExt(M,N) is a right module, hence a right presentation matrix is returned EXAMPLE: example ncExt; shows examples " { if ( !is_cenBimodule(Ph) ) { ERROR("Second module in not centralizing."); } if(i==0) { return(module(ncHom(Ps,Ph))); } list Phi = mres(Ps,i+1); module Im = coHom(Ph,ncols(Phi[i+1])); module f = contraHom(matrix(Phi[i+1]),nrows(Ph)); module Im1 = coHom(Ph,ncols(Phi[i])); module Im2 = contraHom(matrix(Phi[i]),nrows(Ph)); def Rbase = basering; def Rop = opposite(Rbase); setring Rop; module fop = oppose(Rbase,f); module Imop = oppose(Rbase,Im); module Im1op = oppose(Rbase,Im1); module Im2op = oppose(Rbase,Im2); module ker_op = modulo(fop,Imop); module ext_op = modulo(ker_op,Im1op+Im2op); // ext = prune(ext); // to be discussed and done prune_from_the_left setring Rbase; module ext = oppose(Rop,ext_op); kill Rop; return(ext); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),dp; ideal I = x2-y3; qring S = std(I); module M = [-x,y],[-y2,x]; module E1 = ncExt(1,M,M); E1; } proc ncExt_R(int i, matrix Ps) "USAGE: ncExt_R(i, M); i int, M module COMPUTE: a presentation of Ext^i(M',R); for M'=coker(M). RETURN: right module Ext, a presentation of Ext^i(M',R) EXAMPLE: example ncExt_R; shows an example "{ if (i==0) { return(ncHom_R(Ps)); // the rest is not needed } list Phi = nres(Ps,i+1); // left resolution module f = transpose(matrix(Phi[i+1])); // transp. because of Hom_R module Im2 = transpose(matrix(Phi[i])); def Rbase = basering; def Rop = opposite(Rbase); setring Rop; module fop = oppose(Rbase,f); module Im2op = oppose(Rbase,Im2); module ker_op = modulo(fop,std(0)); module ext_op = modulo(ker_op,Im2op); // ext = prune(ext); // to be discussed and done prune_from_the_left // necessary: compute SB! // "Computing SB of Ext"; // option(redSB); // option(redTail); // ext_op = std(ext_op); // int dimop = GKdim(ext_op); // printf("Ext has dimension %s",dimop); // if (dimop==0) // { // printf("of K-dimension %s",vdim(ext_op)); // } setring Rbase; module ext = oppose(Rop,ext_op); // a right module! kill Rop; return(ext); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),dp; poly F = x2-y2; def A = annfs(F); setring A; // A is the 2nd Weyl algebra matrix M[1][size(LD)] = LD; // ideal print(M); print(ncExt_R(1,M)); // hence the Ext^1 is zero module E = ncExt_R(2,M); // define the right module E print(E); // E is in the opposite algebra def Aop = opposite(A); setring Aop; module Eop = oppose(A,E); module T1 = ncExt_R(2,Eop); setring A; module T1 = oppose(Aop,T1); print(T1); // this is a left module Ext^2(Ext^2(M,A),A) print(M); // it is known that M holonomic implies Ext^2(Ext^2(M,A),A) iso to M } proc nctors(matrix M) { // ext^1_A(adj(M),A) def save = basering; matrix MM = M; // left def sop = opposite(save); setring sop; matrix MM = oppose(save,MM); // right MM = transpose(MM); // transposed list Phi = nres(MM,2); // i=1 module f = transpose(matrix(Phi[2])); // transp. because of Hom_R module Im2 = transpose(matrix(Phi[1])); setring save; module fop = oppose(sop,f); module Im2op = oppose(sop,Im2); module ker_op = modulo(fop,std(0)); module ext_op = modulo(ker_op,Im2op); // matrix E = ncExt_R(1,MM); // setring save; // matrix E = oppose(sop,E); return(ext_op); } proc altExt_R(int i, matrix Ps, map Invo) // TODO!!!!!!!! // matrix Ph // work thru Involutions; { if(i==0) { // return the formal adjoint matrix Ret = transpose(Ps); matrix Retop = involution(Ret, Invo); // "Computing prune of Hom"; // Retop = prune(Retop); // Retop = std(Retop); return(Retop); } list Phi = mres(Ps,i+1); // module Im = coHom(Ph,ncols(Phi[i+1])); module f = transpose(matrix(Phi[i+1])); f = involution(f, Invo); //= contraHom(matrix(Phi[i+1]),nrows(Ph)); // module Im1 = coHom(Ph,ncols(Phi[i])); module Im2 = transpose(matrix(Phi[i])); Im2 = involution(Im2, Invo); //contraHom(matrix(Phi[i]),nrows(Ph)); module ker_op = modulo(f,std(0)); module ext_op = modulo(ker_op,Im2); // ext = prune(ext); // to be discussed and done prune_from_the_left // optionally: compute SB! // "Computing prune of Ext"; ext_op = std(ext_op); int dimop = GKdim(ext_op); printf("Ext has dimension %s",dimop); if (dimop==0) { printf("of K-dimension %s",vdim(ext_op)); } module ext = involution(ext_op, Invo); // what about transpose? return(ext); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),dp; ideal I = x2-y3; qring S = std(I); module M = [-x,y],[-y2,x]; module E1 = ncExt(2,M,M); E1; } proc tensorMaps(matrix M, matrix N) { int r = ncols(M); int s = nrows(M); int p = ncols(N); int q = nrows(N); int a,b,c,d; matrix R[s*q][r*p]; for(b=1;b<=p;b++) { for(d=1;d<=q;d++) { for(a=1;a<=r;a++) { for(c=1;c<=s;c++) { R[(c-1)*q+d,(a-1)*p+b]=M[c,a]*N[d,b]; } } } } return(R); } proc ncTensorMod(matrix Phi, matrix Psi) { int s=nrows(Phi); int q=nrows(Psi); matrix A=tensorMaps(unitmat(s),Psi); //I_s tensor Psi matrix B=tensorMaps(Phi,unitmat(q)); //Phi tensor I_q matrix R=concat(A,B); //sum of A and B return(R); } proc ncTor(int i, matrix Ps, matrix Ph) { if(i==0) { return(module(ncTensorMod(Ps,Ph))); } // the tensor product list Phi = mres(Ph,i+1); // a resolution of Ph module Im = tensorMaps(unitmat(nrows(Phi[i])),Ps); module f = tensorMaps(matrix(Phi[i]),unitmat(nrows(Ps))); module Im1 = tensorMaps(unitmat(ncols(Phi[i])),Ps); module Im2 = tensorMaps(matrix(Phi[i+1]),unitmat(nrows(Ps))); module ker = modulo(f,Im); module tor = modulo(ker,Im1+Im2); // tor = prune(tor); return(tor); } static proc Hochschild() { ring A = 0,(x,y),dp; ideal I = x2-y3; qring B = std(I); module M = [-x,y],[-y2,x]; ring C = 0,(x,y,z,w),dp; // x->z, y->w ideal I = x2-y3,z3-w2; qring Be = std(I); //the enveloping algebra matrix AA[1][2] = x-z,y-w; //the presentation of the algebra B as Be-module module MM = imap(B,M); module E = ncExt(1,AA,MM); print(E); //the presentation of the H^1(A,M) ring A = 0,(x,y),dp; ideal I = x2-y3; qring B = std(I); ring C = 0,(x,y,z,w),dp; ideal I = x2-y3,z3-w2; qring Be = std(I); //the enveloping algebra matrix AA[1][2] = x-z,y-w; //the presentation of B as Be-module matrix AAA[1][2] = z,w; // equivalent? pres. of B print(ncExt(1,AA,AA)); //the presentation of the H^1(A,A) print(ncExt(1,AAA,AAA)); } static proc Lie() { // consider U(sl2)* U(sl2)^opp; LIB "ncalg.lib"; ring A = 0,(e,f,h,H,F,E),Dp; // any degree ordering int N = 6; // nvars(A); matrix @D[N][N]; @D[1,2] = -h; @D[1,3] = 2*e; @D[2,3] = -2*f; @D[4,5] = 2*F; @D[4,6] = -2*E; @D[5,6] = H; def AA = nc_algebra(1,@D); setring AA; ideal Q = E,F,H; poly Z = 4*e*f+h^2-2*h; // center poly Zo = 4*F*E+H^2+2*H; // center opposed ideal Qe = Z,Zo; //qring B = twostd(Qe); //ideal T = e-E,f-F,h-H; //ideal T2 = e-H,f-F,h-E; //Q = twostd(Q); // U is U(sl2) as left U(sl2)* U(sl2)^opp -- module matrix M[1][3] = E,F,H; module X0 = ncExt(0,M,M); print(X0); module X1 = ncExt(1,M,M); print(X1); module X2 = ncExt(2,M,M); // equal to Tor^Z_1(K,K) print(X2); // compute Tor^Z_1(K,K) ring r = 0,(z),dp; ideal i = z; matrix I[1][1]=z; Tor(1,I,I); } proc AllExts(module N, list #) // computes and shows everything // assumes we are in the opposite // and N is dual of some M // if # is given, map Invo and Ext_Invo are used { int UseInvo = 0; int sl = size(#); if (sl >0) { ideal I = ideal(#[1]); map Invo = basering, I; UseInvo = 1; "Using the involution"; } int nv = nvars(basering); int i,d; module E; list EE; print("--- module:"); print(matrix(N)); for (i=1; i<=nv; i++) { if (UseInvo) { E = altExt_R(i,N,Invo); } else { E = ncExt_R(i,N); } printf("--- Ext %s",i); print(matrix(E)); EE[i] = E; } return(E); } proc dmodualtest(module M, int n) { // computes the "dual" of the "dual" of a d-mod M // where n is the half-number of vars of Weyl algebra // assumed to be basering // returns the difference between M and Ext^n_D(Ext^n_D(M,D),D) def save = basering; setring save; module Md = ncExt_R(n,M); // right module // would be nice to use "prune"! // NO! prune performs left sided operations!!! // Md = prune(Md); // print(Md); def saveop = opposite(save); setring saveop; module Mdop = oppose(save,Md); // left module // here we're eligible to use prune Mdop = prune(Mdop); module Mopd = ncExt_R(n,Mdop); // right module setring save; module M2 = oppose(saveop,Mopd); // left module M2 = prune(M2); // eligible since M2 is a left mod M2 = groebner(M2); ideal tst = M2 - M; tst = groebner(tst); return(tst); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),dp; poly F = x3-y2; def A = annfs(F); setring A; dmodualtest(LD,2); } proc dmodoublext(module M, list #) "USAGE: dmodoublext(M [,i]); M module, i optional int COMPUTE: a presentation of Ext^i(Ext^i(M,D),D) for basering D RETURN: left module NOTE: by default, i is set to the integer part of the half of number of variables of D @* for holonomic modules over Weyl algebra, the double ext is known to be holonomic left module EXAMPLE: example dmodoublext; shows an example " { // assume: basering is a Weyl algebra? def save = basering; setring save; // if a list is nonempty and contains an integer N, n = N; otherwise n = nvars/2 int n; if (size(#) > 0) { // if (typeof(#) == "int") // { n = int(#[1]); // } // else // { // ERROR("the optional argument expected to have type int"); // } } else { n = nvars(save); n = n div 2; } // returns Ext^i_D(Ext^i_D(M,D),D), that is // computes the "dual" of the "dual" of a d-mod M (for n = nvars/2) module Md = ncExt_R(n,M); // right module // no prune yet! def saveop = opposite(save); setring saveop; module Mdop = oppose(save,Md); // left module // here we're eligible to use prune Mdop = prune(Mdop); module Mopd = ncExt_R(n,Mdop); // right module setring save; module M2 = oppose(saveop,Mopd); // left module kill saveop; M2 = prune(M2); // eligible since M2 is a left mod def M3; if (nrows(M2)==1) { M3 = ideal(M2); } else { M3 = M2; } M3 = groebner(M3); return(M3); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),dp; poly F = x3-y2; def A = annfs(F); setring A; dmodoublext(LD); LD; // fancier example: setring A; ideal I = Dx*(x2-y3),Dy*(x2-y3); I = groebner(I); print(dmodoublext(I,1)); print(dmodoublext(I,2)); } static proc part_Ext_R(matrix M) { // if i==0 matrix Ret = transpose(Ps); def Rbase = basering; def Rop = opposite(Rbase); setring Rop; module Retop = oppose(Rbase,Ret); module Hm = modulo(Retop,std(0)); // right kernel of transposed // "Computing prune of Hom"; // Retop = prune(Retop); // Retop = std(Retop); setring Rbase; Ret = oppose(Rop, Hm); kill Rop; return(Ret); // some checkz: // setring Rbase; // ker_op is the right Kernel of f^t: // module ker = oppose(Rop,ker_op); // print(f*ker); // module ext = oppose(Rop,ext_op); } singular-4.0.3+ds/Singular/LIB/ncpreim.lib000066400000000000000000000504241266270727000203010ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////// version="version ncpreim.lib 4.0.0.0 Jun_2013 "; // $Id: fcca2c37ec1caedea6c6ad3cd032dcf4bedf44e7 $ category="Noncommutative"; info=" LIBRARY: ncpreim.lib Non-commutative elimination and preimage computations AUTHOR: Daniel Andres, daniel.andres@math.rwth-aachen.de Support: DFG Graduiertenkolleg 1632 `Experimentelle und konstruktive Algebra' OVERVIEW: In G-algebras, elimination of variables is more involved than in the commutative case. One, not every subset of variables generates an algebra, which is again a G-algebra. Two, even if the subset of variables in question generates an admissible subalgebra, there might be no admissible elimination ordering, i.e. an elimination ordering which also satisfies the ordering condition for G-algebras. The difference between the procedure @code{eliminateNC} provided in this library and the procedure @code{eliminate (plural)} from the kernel is that eliminateNC will always find an admissible elimination if such one exists. Moreover, the use of @code{slimgb} for performing Groebner basis computations is possible. As an application of the theory of elimination, the procedure @code{preimageNC} is provided, which computes the preimage of an ideal under a homomorphism f: A -> B between G-algebras A and B. In contrast to the kernel procedure @code{preimage (plural)}, the assumption that A is commutative is not required. REFERENCES: (BGL) J.L. Bueso, J. Gomez-Torrecillas, F.J. Lobillo: `Re-filtering and exactness of the Gelfand-Kirillov dimension', Bull. Sci. math. 125, 8, 689-715, 2001. @* (GML) J.I. Garcia Garcia, J. Garcia Miranda, F.J. Lobillo: `Elimination orderings and localization in PBW algebras', Linear Algebra and its Applications 430(8-9), 2133-2148, 2009. @* (Lev) V. Levandovskyy: `Intersection of ideals with non-commutative subalgebras', ISSAC'06, 212-219, ACM, 2006. PROCEDURES: eliminateNC(I,v,eng); elimination in G-algebras preimageNC(A,f,J[,P,eng]); preimage of ideals under homomorphisms of G-algebras admissibleSub(v); checks whether subalgebra is admissible isUpperTriangular(M,k); checks whether matrix is (strictly) upper triangular appendWeight2Ord(w); appends weight to ordering elimWeight(v); computes elimination weight extendedTensor(A,I); tensor product of rings with additional relations KEYWORDS: preimage; elimination SEE ALSO: elim_lib, preimage (plural) "; LIB "elim.lib"; // for nselect LIB "nctools.lib"; // for makeWeyl etc. LIB "dmodapp.lib"; // for sortIntvec LIB "ncalg.lib"; // for makeUgl LIB "dmodloc.lib"; // for commRing /* CHANGELOG 11.12.12: docu, typos, fixed variable names in extendedTensor, moved commRing to dmodloc.lib 12.12.12: typos 17.12.12: docu 24.09.13: bugfix preimageNC naming conflict if f is map from ring called 'B' */ // -- Testing for consistency of the library --------------- static proc testncpreimlib() { example admissibleSub; example isUpperTriangular; example appendWeight2Ord; example elimWeight; example eliminateNC; example extendedTensor; example preimageNC; } // -- Tools ------------------------------------------------ proc admissibleSub (intvec v) " USAGE: admissibleSub(v); v intvec ASSUME: The entries of v are in the range 1..nvars(basering). RETURN: int, 1 if the variables indexed by the entries of v form an admissible subalgebra, 0 otherwise EXAMPLE: example admissibleSub; shows examples " { v = checkIntvec(v); int i,j; list RL = ringlist(basering); if (size(RL) == 4) { return(int(1)); } matrix D = RL[6]; ideal I; for (i=1; i<=size(v); i++) { for (j=i+1; j<=size(v); j++) { I[size(I)+1] = D[v[j],v[i]]; } } ideal M = maxideal(1); ideal J = M[v]; attrib(J,"isSB",1); M = NF(M,J); M = simplify(M,2); // get rid of double entries in v intvec opt = option(get); attrib(M,"isSB",1); option("redSB"); J = NF(I,M); option(set,opt); for (i=1; i<=ncols(I); i++) { if (J[i]<>I[i]) { return(int(0)); } } return(int(1)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(e,f,h),dp; matrix d[3][3]; d[1,2] = -h; d[1,3] = 2*e; d[2,3] = -2*f; def A = nc_algebra(1,d); setring A; A; // A is U(sl_2) // the subalgebra generated by e,f is not admissible since [e,f]=h admissibleSub(1..2); // but the subalgebra generated by f,h is admissible since [f,h]=2f admissibleSub(2..3); } proc isUpperTriangular(matrix M, list #) " USAGE: isUpperTriangular(M[,k]); M a matrix, k an optional int RETURN: int, 1 if the given matrix is upper triangular, 0 otherwise. NOTE: If k<>0 is given, it is checked whether M is strictly upper triangular. EXAMPLE: example isUpperTriangular; shows examples " { int strict; if (size(#)>0) { if ((typeof(#[1])=="int") || (typeof(#[1])=="number")) { strict = (0<>int(#[1])); } } int m = Min(intvec(nrows(M),ncols(M))); int j; ideal I; for (j=1; j<=m; j++) { I = M[j..nrows(M),j]; if (!strict) { I[1] = 0; } if (size(I)>0) { return(int(0)); } } return(int(1)); } example { "EXAMPLE:"; echo = 2; ring r = 0,x,dp; matrix M[2][3] = 0,1,2, 0,0,3; isUpperTriangular(M); isUpperTriangular(M,1); M[2,2] = 4; isUpperTriangular(M); isUpperTriangular(M,1); } proc appendWeight2Ord (intvec w) " USAGE: appendWeight2Ord(w); w an intvec RETURN: ring, the basering equipped with the ordering (a(w),<), where < is the ordering of the basering. EXAMPLE: example appendWeight2Ord; shows examples " { list RL = ringlist(basering); RL[3] = insert(RL[3],list("a",w),0); def A = ring(RL); return(A); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,x,d),Dp; intvec w = 1,2,3,4; def r2 = appendWeight2Ord(w); // for a commutative ring r2; matrix D[4][4]; D[1,2] = 3*a; D[1,4] = 3*x^2; D[2,3] = -x; D[2,4] = d; D[3,4] = 1; def A = nc_algebra(1,D); setring A; A; w = 2,1,1,1; def B = appendWeight2Ord(w); // for a non-commutative ring setring B; B; } static proc checkIntvec (intvec v) " USAGE: checkIntvec(v); v intvec RETURN: intvec consisting of entries of v in ascending order NOTE: Purpose of this proc: check if all entries of v are in the range 1..nvars(basering). " { if (size(v)>1) { v = sortIntvec(v)[1]; } int n = nvars(basering); if ( (v[1]<1) || v[size(v)]>n) { ERROR("Entries of intvec must be in the range 1.." + string(n)); } return(v); } // -- Elimination ------------------------------------------ /* // this is the same as Gweights@nctools.lib // // proc orderingCondition (matrix D) // " // USAGE: orderingCondition(D); D a matrix // ASSUME: The matrix D is a strictly upper triangular square matrix. // RETURN: intvec, say w, such that the ordering (a(w),<), where < is // any global ordering, satisfies the ordering condition for // all G-algebras induced by D. // NOTE: If no such ordering exists, the zero intvec is returned. // REMARK: Reference: (BGL) // EXAMPLE: example orderingCondition; shows examples // " // { // if (ncols(D) <> nrows(D)) // { // ERROR("Expected square matrix."); // } // if (isUpperTriangular(D,1)==0) // { // ERROR("Expected strictly upper triangular matrix."); // } // intvec v = 1..nvars(basering); // intvec w = orderingConditionEngine(D,v,0); // return(w); // } // example // { // "EXAMPLE:"; echo = 2; // // (Lev): Example 2 // ring r = 0,(a,b,x,d),dp; // matrix D[4][4]; // D[1,2] = 3*a; D[1,4] = 3*x^2; D[2,3] = -x; // D[2,4] = d; D[3,4] = 1; // // To create a G-algebra, the ordering condition implies // // that x^20) { V2[rowV2+1,i+1] = 1; // xj == 0 rowV2++; } else { V1[rowV1+1,1] = 1; // 1-xi <= 0 V1[rowV1+1,i+1] = -1; rowV1++; } } else { V1[i,1] = 1; // 1-xi <= 0 V1[i,i+1] = -1; rowV1++; } for (j=i+1; j<=n; j++) { if (deg(D[i,j])>0) { M2 = newtonDiag(D[i,j]); for (k=1; k<=nrows(M2); k++) { M2[k,i] = M2[k,i] - 1; // >= 0 M2[k,j] = M2[k,j] - 1; } oldM = M; M = intmat(M,nrows(M)+nrows(M2),n); M = oldM,M2; } } } intvec eq = 0,(-1:n); ring r = 0,x,dp; // to avoid problems with pars or char>0 module MM = module(transpose(matrix(M))); MM = simplify(MM,2+4); matrix A; if (MM[1]<>0) { if (elimweight) { MM = 0,transpose(MM); } else { MM = module(matrix(1:ncols(MM)))[1],transpose(MM); } A = transpose(concat(matrix(eq),transpose(-MM))); } else { A = transpose(eq); } A = transpose(concat(transpose(A),matrix(transpose(V1)))); if (elimweight) { A = transpose(concat(transpose(A),matrix(transpose(V2)))); } int m = nrows(A)-1; ring realr = (real,10),x,lp; matrix A = imap(r,A); dbprint(ppl,"// Calling simplex..."); dbprint(ppl-1,"// with the matrix " + print(A)); dbprint(ppl-1,"// and parameters " + string(intvec(m,n,m-rowV1-rowV2,rowV1,rowV2))); list L = simplex(A,m,n,m-rowV1-rowV2,rowV1,rowV2); int se = L[2]; if (se==-2) { ERROR("simplex yielded an error. Please inform the authors."); } intvec w = 0:n; if (se==0) { matrix S = L[1]; intvec s = L[3]; for (i=2; i<=nrows(S); i++) { if (s[i-1]<=n) { w[s[i-1]] = int(S[i,1]); } } } setring save; return(w); } proc eliminateNC (ideal I, intvec v, list #) " USAGE: eliminateNC(I,v,eng); I ideal, v intvec, eng optional int RETURN: ideal, I intersected with the subring defined by the variables not index by the entries of v ASSUME: The entries of v are in the range 1..nvars(basering) and the corresponding variables generate an admissible subalgebra. REMARKS: In order to determine the required elimination ordering, a linear programming problem is solved with the simplex algorithm. @* Reference: (GML) @* Unlike eliminate, this procedure will always find an elimination ordering, if such exists. NOTE: If eng<>0, @code{std} is used for Groebner basis computations, otherwise (and by default) @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. SEE ALSO: eliminate (plural) EXAMPLE: example eliminateNC; shows examples " { int ppl = printlevel - voice + 2; v = checkIntvec(v); if (!admissibleSub(v)) { ERROR("Subalgebra is not admissible: no elimination is possible."); } dbprint(ppl,"// Subalgebra is admissible."); int eng; if (size(#)>0) { if (typeof(#[1])=="int" || typeof(#[1])=="number") { eng = int(#[1]); } } def save = basering; int n = nvars(save); dbprint(ppl,"// Computing elimination weight..."); intvec w = elimWeight(v); if (w==(0:n)) { ERROR("No elimination ordering exists."); } dbprint(ppl,"// ...done."); dbprint(ppl-1,"// Using elimination weight " + string(w) + "."); def r = appendWeight2Ord(w); setring r; ideal I = imap(save,I); dbprint(ppl,"// Computing Groebner basis with engine " + string(eng)+"..."); I = engine(I,eng); dbprint(ppl,"// ...done."); dbprint(ppl-1,string(I)); I = nselect(I,v); setring save; I = imap(r,I); return(I); } example { "EXAMPLE:"; echo = 2; // (Lev): Example 2 ring r = 0,(a,b,x,d),Dp; matrix D[4][4]; D[1,2] = 3*a; D[1,4] = 3*x^2; D[2,3] = -x; D[2,4] = d; D[3,4] = 1; def A = nc_algebra(1,D); setring A; A; ideal I = a,x; // Since d*a-a*d = 3*x^2, any admissible ordering has to satisfy // x^2 < a*d, while any elimination ordering for {x,d} additionally // has to fulfil a << x and a << d. // Hence, the weight (0,0,1,1) is not an elimination weight for // (x,d) and the call eliminate(I,x*d); will produce an error. eliminateNC(I,3..4); // This call uses the elimination weight (0,0,1,2), which works. } // -- Preimages ------------------------------------------------ // TODO A or B commutative proc extendedTensor(def A, ideal I) " USAGE: extendedTensor(A,I); A ring, I ideal RETURN: ring, A+B (where B denotes the basering) extended with non- commutative relations between the vars of A and B, which arise from the homomorphism A -> B induced by I in the usual sense, i.e. if the vars of A are named x(i) and the vars of B y(j), then putting q(i)(j) = leadcoef(y(j)*I[i])/leadcoef(I[i]*y(j)) and r(i)(j) = y(j)*I[i] - q(i)(j)*I[i]*y(j) yields the relation y(j)*x(i) = q(i)(j)*x(i)*y(j)+r(i)(j). REMARK: Reference: (Lev) EXAMPLE: example extendedTensor; shows examples " { def B = basering; setring A; int nA = nvars(A); string varA = "," + charstr(A) + "," + varstr(A) + ","; setring B; int nB = nvars(B); list RL = ringlist(B); list L = RL[2]; string vB; int i,j; for (i=1; i<=nB; i++) { vB = "," + L[i] + ","; while (find(varA,vB)<>0) { vB[1] = "@"; vB = "," + vB; } vB = vB[2..size(vB)-1]; L[i] = vB; } RL[2] = L; def @B = ring(RL); kill L,RL; setring @B; ideal I = fetch(B,I); def E = A+@B; setring E; ideal I = imap(@B,I); matrix C = ringlist(E)[5]; matrix D = ringlist(E)[6]; poly p,q; for (i=1; i<=nA; i++) { for (j=nA+1; j<=nA+nB; j++) { // upper right block: new relations p = var(j)*I[i]; q = I[i]*var(j); C[i,j] = leadcoef(p)/leadcoef(q); D[i,j] = p - C[i,j]*q; } } def @EE = commRing(); setring @EE; matrix C = imap(E,C); matrix D = imap(E,D); def EE = nc_algebra(C,D); setring B; return(EE); } example { "EXAMPLE:"; echo = 2; def A = makeWeyl(2); setring A; A; def B = makeUgl(2); setring B; B; ideal I = var(1)*var(3), var(1)*var(4), var(2)*var(3), var(2)*var(4); I; def C = extendedTensor(A,I); setring C; C; } proc preimageNC (list #) " USAGE: preimageNC(A,f,J[,P,eng]); A ring, f map or ideal, J ideal, P optional string, eng optional int ASSUME: f defines a map from A to the basering. RETURN: nothing, instead exports an object `preim' of type ideal to ring A, being the preimage of J under f. NOTE: If P is given and not equal to the empty string, the preimage is exported to A under the name specified by P. Otherwise (and by default), P is set to `preim'. @* If eng<>0, @code{std} is used for Groebner basis computations, otherwise (and by default) @code{slimgb} is used. @* If printlevel=1, progress debug messages will be printed, if printlevel>=2, all the debug messages will be printed. REMARK: Reference: (Lev) SEE ALSO: preimage (plural) EXAMPLE: example preimageNC; shows examples " { int ppl = printlevel - voice + 2; if (size(#) <3) { ERROR("Expected 3 arguments.") } def B = basering; if (typeof(#[1])<>"ring") { ERROR("First argument must be a ring."); } def A = #[1]; setring A; ideal mm = maxideal(1); setring B; if (typeof(#[2])=="map" || typeof(#[2])=="ideal") { map phi = A,ideal(#[2]); } else { ERROR("Second argument must define a map from the specified ring to the basering."); } if (typeof(#[3])<>"ideal") { ERROR("Third argument must be an ideal in the specified ring"); } ideal J = #[3]; string str = "preim"; int eng; if (size(#)>3) { if (typeof(#[4])=="string") { if (#[4]<>"") { str = #[4]; } } if (size(#)>4) { if (typeof(#[5])=="int") { eng = #[5]; } } } setring B; ideal I = phi(mm); def E = extendedTensor(A,I); setring E; dbprint(ppl,"// Computing in ring"); dbprint(ppl,E); int nA = nvars(A); int nB = nvars(B); ideal @B2E = maxideal(1); @B2E = @B2E[(nA+1)..(nA+nB)]; map B2E = B,@B2E; ideal I = B2E(I); ideal Iphi; int i,j; for (i=1; i<=nA; i++) { Iphi[size(Iphi)+1] = var(i) - I[i]; } dbprint(ppl,"// I_{phi} is " + string(Iphi)); ideal J = imap(B,J); J = J + Iphi; intvec v = (nA+1)..(nA+nB); dbprint(ppl,"// Starting elimination..."); dbprint(ppl-1,string(J)); J = eliminateNC(J,v,eng); dbprint(ppl,"// ...done."); dbprint(ppl-1,string(J)); J = nselect(J,v); attrib(J,"isSB",1); setring A; dbprint(ppl,"// Writing output to specified ring under the name `" + str + "'."); str = "ideal " + str + " = imap(E,J); export(" + str + ");"; execute(str); setring B; return(); } example { "EXAMPLE:"; echo = 2; def A = makeUgl(3); setring A; A; // universal enveloping algebra of gl_3 ring r3 = 0,(x,y,z,Dx,Dy,Dz),dp; def B = Weyl(); setring B; B; // third Weyl algebra ideal ff = x*Dx,x*Dy,x*Dz,y*Dx,y*Dy,y*Dz,z*Dx,z*Dy,z*Dz; map f = A,ff; // f: A -> B, e(i,j) |-> x(i)D(j) ideal J = 0; preimageNC(A,f,J,"K"); // compute K := ker(f) setring A; K; } // -- Examples --------------------------------------------- static proc ex1 () { ring r1 = 0,(a,b),dp; int t = 7; def St = nc_algebra(1,t*a); ring r2 = 0,(x,D),dp; def W = nc_algebra(1,1); // W is the first Weyl algebra setring W; map psit = St, x^t,x*D+t; int p = 3; ideal Ip = x^p, x*D+p; preimageNC(St,psit,Ip); setring St; preim; } static proc ex2 () { ring r1 = 0,(e,f,h),dp; matrix D1[3][3]; D1[1,2] = -h; D1[1,3] = 2*e; D1[2,3] = -2*f; def U = nc_algebra(1,D1); // D is U(sl_2) ring r2 = 0,(x,D),dp; def W = nc_algebra(1,1); // W is the first Weyl algebra setring W; ideal tau = x,-x*D^2,2*x*D; def E = extendedTensor(U,tau); setring E; E; elimWeight(4..5); // zero, since there is no elimination ordering for x,D in E } static proc ex3 () { ring r1 = 0,(x,d,s),dp; matrix D1[3][3]; D1[1,2] = 1; def A = nc_algebra(1,D1); ring r2 = 0,(X,DX,T,DT),dp; matrix D2[4][4]; D2[1,2] = 1; D2[3,4] = 1; def B = nc_algebra(1,D2); setring B; map phi = A, X,DX,-DT*T; ideal J = T-X^2, DX+2*X*DT; preimageNC(A,phi,J); setring A; preim; } singular-4.0.3+ds/Singular/LIB/nctools.lib000066400000000000000000001354671266270727000203400ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version nctools.lib 4.0.0.0 Jun_2013 "; // $Id: ea93502d98e771d3d28eba0b836e261a2993ee2e $ category="Noncommutative"; info=" LIBRARY: nctools.lib General tools for noncommutative algebras AUTHORS: Levandovskyy V., levandov@mathematik.uni-kl.de, @* Lobillo, F.J., jlobillo@ugr.es, @* Rabelo, C., crabelo@ugr.es, @* Motsak, O., U@D, where U={motsak}, D={mathematik.uni-kl.de} OVERVIEW: Support: DFG (Deutsche Forschungsgesellschaft) and Metodos algebraicos y efectivos en grupos cuanticos, BFM2001-3141, MCYT, Jose Gomez-Torrecillas (Main researcher). PROCEDURES: Gweights(r); compute weights for a compatible ordering in a G-algebra, weightedRing(r); change the ordering of a ring to a weighted one, ndcond(); the ideal of non-degeneracy conditions in G-algebra, Weyl([p]); create Weyl algebra structure in a basering (two different realizations), makeWeyl(n, [p]); return n-th Weyl algebra in (x(i),D(i)) presentation, makeHeisenberg(N, [p,d]); return n-th Heisenberg algebra in (x(i),y(i),h) realization, Exterior(); return qring, the exterior algebra of a basering, findimAlgebra(M,[r]); create finite dimensional algebra structure from the basering and the multiplication matrix M, superCommutative([b,e,Q]); return qring, a super-commutative algebra over a basering, rightStd(I); compute right Groebner basis of an ideal, rightNF(f,I); compute right normal form wrt a submodule, rightModulo(M,N); compute kernel of a homomorphism of right modules, moduloSlim(A,B); compute modulo command via slimgb ncRelations(r); recover the non-commutative relations of a G-algebra, isCentral(p); check for the commutativity of a polynomial in the G-algebra, isNC(); check whether basering is noncommutative, isCommutative(); check whether basering is commutative isWeyl(); check whether basering is a Weyl algebra UpOneMatrix(); return NxN matrix with 1's in the whole upper triagle, AltVarStart(); return first alternating variable of a super-commutative algebra, AltVarEnd(); return last alternating variable of a super-commutative algebra, IsSCA(); check whether current ring is a super-commutative algebra, makeModElimRing(R); equip a ring with module elimination ordering, embedMat(M,m,n); embeds matrix M in a left upper corner of m times n matrix "; LIB "ring.lib"; // for rootofUnity LIB "poly.lib"; // for newtonDiag LIB "matrix.lib"; // for submat /////////////////////////////////////////////////////////////////////////////// // This procedure computes a weights vector for a G-algebra r proc Gweights(def r) "USAGE: Gweights(r); r a ring or a square matrix RETURN: intvec PURPOSE: compute an appropriate weight int vector for a G-algebra, i.e., such that \foral\;i1 ) { int n = ncols(tails); int m = nrows(IM)-1; int m1 = 0; int m2 = m; int m3 = 0; ring simplexring=(real,10),(x),lp;// The simplex procedure requires a basering of this type matrix M = IM; list sol = simplex (M,m,n,m1,m2,m3); return(weightvector(sol)); } else { "Invalid input"; //usually because the input is a one variable ring return(); } } else { "The input must be a ring or a square matrix"; return(); } } example { "EXAMPLE:";echo=2; ring r = (0,q),(a,b,c,d),lp; matrix C[4][4]; C[1,2]=q; C[1,3]=q; C[1,4]=1; C[2,3]=1; C[2,4]=q; C[3,4]=q; matrix D[4][4]; D[1,4]=(q-1/q)*b*c; def S = nc_algebra(C,D); setring S; S; Gweights(S); def D=fetch(r,D); Gweights(D); } /////////////////////////////////////////////////////////////////////////////// // This procedure take a ring r, call to Gweights(r) and use the output // of Gweights(r) to make a change of order in r // The output is a new ring, equal to r but the order // r must be a G-algebra proc weightedRing(def r) "USAGE: weightedRing(r); r a ring RETURN: ring PURPOSE: equip the variables of the given ring with weights such that the relations of new ring (with weighted variables) satisfies the ordering condition for G-algebras: e.g. \forall\;i1) { N=N[2..size(N)]; // Deleting the zero added in the definition of N M=intmat(N,size(N) div nc,nc); // Conversion from vector to matrix } else { intmat M[1][1]=0; } return (M); } /////////////////////////////////////////////////////////////////////////////// // This procedure run over the matrix of pij calculating Cij static proc Ct(matrix P) { int k = ncols(P); intvec T = 0; int i,j; // int notails=1; def S; for (j=2; j<=k; j++) { for (i=1; i1 ) { T = T,S; } } } } if ( size(T)==1 ) { intmat C[1][1] = 0; } else { T=T[2..size(T)]; // Deleting the zero added in the definition of T intmat C = intmat(T,size(T) div k,k); // Conversion from vector to matrix } return (C); } /////////////////////////////////////////////////////////////////////////////// // The purpose of this procedure is to produce the input matrix required by simplex procedure static proc SimplMat(matrix P) { intmat C=Ct(P); if (size(C)>1) { int r = nrows(C); int n = ncols(C); int f = 1+n+r; intmat M[f][n+1]=0; int i; for (i=2; i<=(n+1); i++) { M[1,i]=-1; // (0,-1,-1,-1,...) objective function in the first row } for (i=2; i<=f; i++) {M[i,1]=1;} // All the independent terms are 1 for (i=2; i<=(n+1); i++) {M[i,i]=-1;} // wi>=1 is an identity matrix M[(n+2)..f,2..(n+1)]=(-1)*intvec(C); // >= 1, a in C ... } else { int n = ncols(P); int f = 1+n; intmat M[f][n+1]=0; int i; for (i=2; i<=(n+1); i++) {M[1,i]=-1;} // (0,-1,-1,-1,...) objective function in the first row for (i=2; i<=f; i++) {M[i,1]=1;} // All the independent terms are 1 for (i=2; i<=(n+1); i++) {M[i,i]=-1;} // wi>=1 is an identity matrix } return (M); } /////////////////////////////////////////////////////////////////////////////// // This procedure generates a nice output of the simplex method consisting of a vector // with the solutions. The vector is ordered. static proc weightvector(list l) "ASSUME: l is the output of simplex. RETURN: if there is a solution, an intvec with it will be returned" { matrix m=l[1]; intvec nv=l[3]; int sol=l[2]; int rows=nrows(m); int N=l[6]; intmat wv[1][N]=0; int i; if (sol) { "no solution satisfies the given constraints"; } else { for ( i = 2; i <= rows; i++ ) { if ( nv[i-1] <= N ) { wv[1,nv[i-1]]=int(m[i,1]); } } } return (intvec(wv)); } /////////////////////////////////////////////////////////////////////////////// // This procedure recover the non-conmutative relations (matrices C and D) proc ncRelations(def r) "USAGE: ncRelations(r); r a ring RETURN: list L with two elements, both elements are of type matrix: @* L[1] = matrix of coefficients C, @* L[2] = matrix of polynomials D PURPOSE: recover the noncommutative relations via matrices C and D from a noncommutative ring SEE ALSO: ringlist, G-algebras EXAMPLE: example ncRelations; shows examples "{ list l; if (typeof(r)=="ring") { int n=nvars(r); matrix C[n][n]=0; matrix D[n][n]=0; poly f; poly g; if (n>1) { int i,j; for (i=2; i<=n; i++) { for (j=1; j0) { if ( typeof(#[1])!="ring" ) { return();} else { def @R1 = #[1]; setring @R1; } } int i,j; int n=nvars(basering); poly p; ideal I; number c; matrix C[n][n]; matrix D[n][n]; for (i=1; i<=n; i++) { for (j=i; j<=n; j++) { p=var(i)*var(j)-M[i,j]; if ( (ncols(I)==1) && (I[1]==0) ) { I=p; } else { I=I,p; } if (j>i) { if ((M[i,j]!=0) && (M[j,i]!=0)) { c = leadcoef(M[j,i])/leadcoef(M[i,j]); } else { c = 1; } C[i,j]=c; D[i,j]= M[j,i] -c*M[i,j]; } } } def save = basering; def S = nc_algebra(C,D); setring S; ideal fdQuot = fetch(save,I); export fdQuot; return(S); } example { "EXAMPLE:";echo=2; ring r=(0,a,b),(x(1..3)),dp; matrix S[3][3]; S[2,3]=a*x(1); S[3,2]=-b*x(1); def A=findimAlgebra(S); setring A; fdQuot = twostd(fdQuot); qring Qr = fdQuot; Qr; } /////////////////////////////////////////////////////////////////////////////// proc isCentral(poly p, list #) "USAGE: isCentral(p); p poly RETURN: int, 1 if p commutes with all variables and 0 otherwise PURPOSE: check whether p is central in a basering (that is, commutes with every generator of the ring) NOTE: if @code{printlevel} > 0, the procedure displays intermediate information (by default, @code{printlevel}=0 ) EXAMPLE: example isCentral; shows examples "{ //v an integer (with v!=0, procedure will be verbose) int N = nvars(basering); int in; int flag = 1; poly q = 0; for (in=1; in<=N; in++) { q = p*var(in)-var(in)*p; if (q!=0) { if ( (size(#) >0 ) || (printlevel>0) ) { "Non-central at:", var(in); } flag = 0; } } return(flag); } example { "EXAMPLE:";echo=2; ring r=0,(x,y,z),dp; matrix D[3][3]=0; D[1,2]=-z; D[1,3]=2*x; D[2,3]=-2*y; def S = nc_algebra(1,D); setring S; S; // this is U(sl_2) poly c = 4*x*y+z^2-2*z; printlevel = 0; isCentral(c); poly h = x*c; printlevel = 1; isCentral(h); } /////////////////////////////////////////////////////////////////////////////// proc UpOneMatrix(int N) "USAGE: UpOneMatrix(n); n an integer RETURN: intmat PURPOSE: compute an n x n matrix with 1's in the whole upper triangle NOTE: helpful for setting noncommutative algebras with complicated coefficient matrices EXAMPLE: example UpOneMatrix; shows examples "{ int ii,jj; intmat U[N][N]=0; for (ii=1;ii 0, the procedure displays intermediate information (by default, @code{printlevel}=0 ) EXAMPLE: example ndcond; shows examples " { // internal documentation, for tests etc // 1st arg: v an optional integer (if v!=0, will be verbose) // if the second argument is given, produces ndc w.r.t. powers x^N int N = 1; int Verbose = 0; if ( size(#)>=1 ) { Verbose = int(#[1]); } if ( size(#)>=2 ) { N = int(#[2]); } Verbose = ((Verbose) || (printlevel>0)); int cnt = 1; int numvars = nvars(basering); int a,b,c; poly p = 1; ideal res = 0; for (cnt=1; cnt<=N; cnt++) { if (Verbose) { "Processing degree :",cnt;} for (a=1; a<=numvars-2; a++) { for (b=a+1; b<=numvars-1; b++) { for(c=b+1; c<=numvars; c++) { p = (var(c)^cnt)*(var(b)^cnt); p = p*(var(a)^cnt); p = p-(var(c)^cnt)*((var(b)^cnt)*(var(a)^cnt)); if (Verbose) {a,".",b,".",c,".";} if (p!=0) { if ( res==0 ) { res[1] = p; } else { res = res,p; } if (Verbose) { "failed:",p; } } } } } if (Verbose) { "done"; } } return(res); } example { "EXAMPLE:";echo=2; ring r = (0,q1,q2),(x,y,z),dp; matrix C[3][3]; C[1,2]=q2; C[1,3]=q1; C[2,3]=1; matrix D[3][3]; D[1,2]=x; D[1,3]=z; def S = nc_algebra(C,D); setring S; S; ideal j=ndcond(); // the silent version j; printlevel=1; ideal i=ndcond(); // the verbose version i; } /////////////////////////////////////////////////////////////////////////////// proc Weyl(list #) "USAGE: Weyl() RETURN: ring PURPOSE: create a Weyl algebra structure on the basering NOTE: Activate this ring using the command @code{setring}. @*Assume the number of variables of a basering is 2k. (if the number of variables is odd, an error message will be returned) @* by default, the procedure treats first k variables as coordinates x_i and the last k as differentials d_i @* if a non-zero optional argument is given, the procedure treats 2k variables of a basering as k pairs (x_i,d_i), i.e. variables with odd numbers are treated as coordinates and with even numbers as differentials SEE ALSO: makeWeyl EXAMPLE: example Weyl; shows examples " { //there are two possibilities for choosing the PBW basis. //The variables have names x(i) for coordinates and d(i) for partial // differentiations. By default, the procedure //creates a ring, where the variables are ordered as x(1..n),d(1..n). the // tensor product-like realization x(1),d(1),x(2),d(2),... is used. string rname=nameof(basering); if ( rname == "basering") // i.e. no ring has been set yet { "You have to call the procedure from the ring"; return(); } int @chr = 0; if ( size(#) > 0 ) { if ( typeof( #[1] ) == "int" ) { @chr = #[1]; } } int nv = nvars(basering); int N = nv div 2; if ((nv % 2) != 0) { "Cannot create Weyl structure for an odd number of generators"; return(); } matrix @D[nv][nv]; int i; for ( i=1; i<=N; i++ ) { if ( @chr==0 ) // default { @D[i,N+i]=1; } else { @D[2*i-1,2*i]=1; } } def @R = nc_algebra(1,@D); return(@R); } example { "EXAMPLE:";echo=2; ring A1=0,(x(1..2),d(1..2)),dp; def S=Weyl(); setring S; S; kill A1,S; ring B1=0,(x1,d1,x2,d2),dp; def S=Weyl(1); setring S; S; } /////////////////////////////////////////////////////////////////////////////// proc makeHeisenberg(int N, list #) "USAGE: makeHeisenberg(n, [p,d]); int n (setting 2n+1 variables), optional int p (field characteristic), optional int d (power of h in the commutator) RETURN: ring PURPOSE: create the n-th Heisenberg algebra in the variables x(1),y(1),...,x(n),y(n),h over the rationals Q or F_p with the relations \forall\;i\in\{1,2,\ldots,n\}\;\;y(j)x(i) = x(i)y(j)+h^d. SEE ALSO: makeWeyl NOTE: activate this ring with the @code{setring} command @* If p is not prime, the next larger prime number will be used. EXAMPLE: example makeHeisenberg; shows examples " { int @chr = 0; int @deg = 1; if ( size(#) > 0 ) { if ( typeof( #[1] ) == "int" ) { @chr = #[1]; } } if ( size(#) > 1 ) { if ( typeof( #[2] ) == "int" ) { @deg = #[2]; if (@deg <1) { @deg = 1; } } } ring @@r=@chr,(x(1..N),y(1..N),h),lp; matrix D[2*N+1][2*N+1]; int i; for (i=1;i<=N;i++) { D[i,N+i]=h^@deg; } return(nc_algebra(1,D)); } example { "EXAMPLE:";echo=2; def a = makeHeisenberg(2); setring a; a; def H3 = makeHeisenberg(3, 7, 2); setring H3; H3; } /////////////////////////////////////////////////////////////////////////////// proc superCommutative(list #) "USAGE: superCommutative([b,[e, [Q]]]); RETURN: qring PURPOSE: create a super-commutative algebra (as a GR-algebra) over a basering, NOTE: activate this qring with the \"setring\" command. NOTE: if b==e then the resulting ring is commutative. @* By default, @code{b=1, e=nvars(basering), Q=0}. THEORY: given a basering, this procedure introduces the anti-commutative relations @* var(j)var(i)=-var(i)var(j) for all e>=j>i>=b and creates the quotient @* of the anti-commutative algebra modulo the two-sided ideal, generated by @* x(b)^2, ..., x(e)^2[ + Q] DISPLAY: If @code{printlevel} > 1, warning debug messages will be printed EXAMPLE: example superCommutative; shows examples " { int fprot = (printlevel > 1); // (find(option(),"prot") != 0); string rname=nameof(basering); if ( rname == "basering") // i.e. no ring has been set yet { ERROR("You have to call the procedure from the ring"); return(); } def saveRing = basering; int N = nvars(saveRing); int b = 1; int e = N; int flag = 0; ideal Q = 0; if(size(#)>0) { if(typeof(#[1]) != "int") { ERROR("The argument 'b' must be an integer!"); return(); } b = #[1]; if((b < 1)||(b > N)) { ERROR("The argument 'b' must within [1..nvars(basering)]!"); return(); } } if(size(#)>1) { if(typeof(#[2]) != "int") { ERROR("The argument 'e' must be an integer!"); return(); } e = #[2]; if((e < 1)||(e > N)) { ERROR("The argument 'e' must within [1..nvars(basering)]!"); return(); } if(e < b) { ERROR("The argument 'e' must be bigger or equal to 'b'!"); return(); } } if(size(#)>2) { if(typeof(#[3]) != "ideal") { ERROR("The argument 'Q' must be an ideal!"); return(); } Q = #[3]; } /* if(size(#)>3) { if(typeof(#[4]) != "int") { ERROR("The argument 'flag' must be an integer!"); return(); } flag = #[4]; } */ int iSavedDegBoung = degBound; if( (b == e) && (flag == 0) ) // commutative ring!!! { if( fprot == 1) { print("Warning: (b==e) means that the resulting ring will be commutative!"); } degBound=0; Q = std(Q + (var(b)^2)); degBound = iSavedDegBoung; qring @EA = Q; // and it will be internally commutative as well!!! return(@EA); } /* // Singular'(H.S.) politics: no ring copies! // in future nc_algebra() should return a new ring!!! list CurrRing = ringlist(basering); def @R = ring(CurrRing); setring @R; // @R; */ int i, j; if( (char(basering)==2) && (flag == 0) )// commutative ring!!! { if( fprot == 1) { print("Warning: (char == 2) means that the resulting ring will be commutative!"); } ideal I; for (i = e - b + 1; i > 0; i--) { I[i] = var(i + b - 1)^2; } degBound=0; Q = std(I + Q); degBound = iSavedDegBoung; qring @EA = Q; // and it will be internally commutative as well!!! return(@EA); } if( (b == 1) && (e == N) ) // just an exterior algebra? { def S = nc_algebra(-1, 0); // define ground G-algebra! setring S; } else { matrix @E = UpOneMatrix(N); for ( i = b; i < e; i++ ) { for ( j = i+1; j <= e; j++ ) { @E[i, j] = -1; } } def S = nc_algebra(@E, 0); // define ground G-algebra! setring S; } ideal @I; for (i = e - b + 1; i > 0; i--) { @I[i] = var(i + b - 1)^2; } degBound=0; @I = twostd(@I); // must be computed within the ground G-algebra => problems with local orderings! degBound = iSavedDegBoung; qring @EA = @I; ideal @Q = twostd(fetch(saveRing, Q)); if( size(@Q) > 0 ) { qring @EA2 = @Q; } attrib(basering, "isSCA", 1==1); attrib(basering, "iAltVarStart", b); attrib(basering, "iAltVarEnd", e); // "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; return(basering); } example { "EXAMPLE:";echo=2; ring R = 0,(x(1..4)),dp; // global! def ER = superCommutative(); // the same as Exterior (b = 1, e = N) setring ER; ER; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; kill R; kill ER; ring R = 0,(x(1..4)),(lp(1), dp(3)); // global! def ER = superCommutative(2); // b = 2, e = N setring ER; ER; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; kill R; kill ER; ring R = 0,(x, y, z),(ds(1), dp(2)); // mixed! def ER = superCommutative(2,3); // b = 2, e = 3 setring ER; ER; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; x + 1 + z + y; // ordering on variables: y > z > 1 > x std(x - x*x*x); std(ideal(x - x*x*x, x*x*z + y, z + y*x*x)); kill R; kill ER; ring R = 0,(x, y, z),(ds(1), dp(2)); // mixed! def ER = superCommutative(2, 3, ideal(x - x*x, x*x*z + y, z + y*x*x )); // b = 2, e = 3 setring ER; ER; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; } // Please, don't throw this away!!! Needed for backward compatibility. proc SuperCommutative(list #) "USAGE: please use @code{superCommutative} instead " { "// This procedure is deprecated. Please use superCommutative instead"; return( superCommutative(#) ); } example { "EXAMPLE:"; "Procedure is deprecated. Please use superCommutative instead"; } static proc ParseSCA() " RETURN: list {AltVarStart, AltVarEnd} is currRing is SCA, returns undef otherwise. NOTE: rings with only one non-commutative variable are commutative rings which are super-sommutative itself! " { if(typeof(attrib(basering, "isSCA"))=="int") // workaround, if(defined()) doesn't work!!!! { if(typeof(attrib(basering, "iAltVarStart"))=="int") { if(typeof(attrib(basering, "iAltVarEnd"))=="int") { if(attrib(basering, "isSCA")) { return(list( attrib(basering, "iAltVarStart"), attrib(basering, "iAltVarEnd") )); } } } } def saveRing = basering; int i, j; int N = nvars(saveRing); int b = N+1; int e = -1; int fprot = 0; // (find(option(),"prot") != 0); if( size(ideal(saveRing)) == 0 ) { return("SCA rings are factors by (at least) squares!"); // no squares in the factor ideal! } list L = ringlist(saveRing); if( size(L)!=6 ) { if(fprot) { print("// Warning: The current ring is internally commutative!"); } for( i = N; i > 0; i-- ) { if( NF(var(i)^2, std(0)) == 0 ) { if( (fprot == 1) and (i > 1) ) { print("// Warning: the SCA representation of the current commutative factor ring may be ambiguous!"); } return( list(i, i) ); // this is not unique in this case! there may be other squares in the factor ideal! } } return("The current commutative ring is not SCA! (Wrong quotient ideal)"); // no squares in the factor ideal! } module D = simplify(L[6], 2 + 4); if( size(D)>0 ) { return("The current ring is not SCA! (D!=0)"); } matrix C = L[5]; poly c; for( i = 1; i < N; i++ ) { for( j = i+1; j <= N; j++ ) { c = C[i, j]; if( c == -1 ) { if(i < b) { b = i; } if(j > e) { e = j; } } else { // should commute if( c!=1 ) { return("The current ring is not SCA! (C["+ string(i)+"," + string(j)+"]!=1)"); } } } } if( (b > N) || (e < 1)) { if(fprot) { print("Warning: The current ring is a commutative GR-algebra!"); } for( i = N; i > 0; i-- ) { if( NF(var(i)^2, std(0)) == 0 ) { if( (fprot == 1) and (i > 1) ) { print("Warning: the SCA representation of the current factor ring may be ambiguous!"); } return( list(i, i) ); // this is not unique in this case! there may be other squares in the factor ideal! } } return("The current commutative GR-algebra is not SCA! (Wrong quotient ideal)"); // no squares in the factor ideal! } for( i = 1; i < N; i++ ) { for( j = i+1; j <= N; j++ ) { c = C[i, j]; if( (b <= i) && (j <= e) ) // S <= i < j <= E { // anticommutative part if( c!= -1 ) { return("The current ring is not SCA! (C["+ string(i)+"," + string(j)+"]!=-1)"); } } else { // should commute if( c!=1 ) { return("The current ring is not SCA! (C["+ string(i)+"," + string(j)+"]!=1)"); } } } } for( i = b; i <= e; i++ ) { if( NF(var(i)^2, std(0)) != 0 ) { return("The current ring is not SCA! (Wrong quotient ideal)"); } } //////////////////////////////////////////////////////////////////////// // ok. this is a SCA!!! return(list(b, e)); } /////////////////////////////////////////////////////////////////////////////// proc AltVarStart() "USAGE: AltVarStart(); RETURN: int PURPOSE: returns the number of the first alternating variable of basering NOTE: basering should be a super-commutative algebra constructed by @* the procedure @code{superCommutative}, emits an error otherwise EXAMPLE: example AltVarStart; shows examples " { def l = ParseSCA(); if( typeof(l) != "string" ) { return(l[1]); } ERROR(l); return(); } example { "EXAMPLE:";echo=2; ring R = 0,(x(1..4)),dp; // global! def ER = superCommutative(2); // (b = 2, e = N) setring ER; ER; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; setring R; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; kill R, ER; ////////////////////////////////////////////////////////////////// ring R = 2,(x(1..4)),dp; // the same in char. = 2! def ER = superCommutative(2); // (b = 2, e = N) setring ER; ER; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; setring R; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; } /////////////////////////////////////////////////////////////////////////////// proc AltVarEnd() "USAGE: AltVarStart(); RETURN: int PURPOSE: returns the number of the last alternating variable of basering NOTE: basering should be a super-commutative algebra constructed by @* the procedure @code{superCommutative}, emits an error otherwise EXAMPLE: example AltVarEnd; shows examples " { def l = ParseSCA(); if( typeof(l) != "string" ) { return(l[2]); } ERROR(l); return(); } example { "EXAMPLE:";echo=2; ring R = 0,(x(1..4)),dp; // global! def ER = superCommutative(2); // (b = 2, e = N) setring ER; ER; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; setring R; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; kill R, ER; ////////////////////////////////////////////////////////////////// ring R = 2,(x(1..4)),dp; // the same in char. = 2! def ER = superCommutative(2); // (b = 2, e = N) setring ER; ER; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; setring R; "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; } /////////////////////////////////////////////////////////////////////////////// proc IsSCA() "USAGE: IsSCA(); RETURN: int PURPOSE: returns 1 if basering is a super-commutative algebra and 0 otherwise EXAMPLE: example IsSCA; shows examples " { def l = ParseSCA(); if( typeof(l) != "string" ) { return(1); } if( find(option(),"prot") != 0 ) { print(l); } return(0); } example { "EXAMPLE:";echo=2; ///////////////////////////////////////////////////////////////////// ring R = 0,(x(1..4)),dp; // commutative if(IsSCA()) { "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; } else { "Not a super-commutative algebra!!!"; } kill R; ///////////////////////////////////////////////////////////////////// ring R = 0,(x(1..4)),dp; def S = nc_algebra(1, 0); setring S; S; // still commutative! if(IsSCA()) { "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; } else { "Not a super-commutative algebra!!!"; } kill R, S; ///////////////////////////////////////////////////////////////////// ring R = 0,(x(1..4)),dp; list CurrRing = ringlist(R); def ER = ring(CurrRing); setring ER; // R; matrix E = UpOneMatrix(nvars(R)); int i, j; int b = 2; int e = 3; for ( i = b; i < e; i++ ) { for ( j = i+1; j <= e; j++ ) { E[i, j] = -1; } } def S = nc_algebra(E,0); setring S; S; if(IsSCA()) { "Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; } else { "Not a super-commutative algebra!!!"; } kill R, ER, S; ///////////////////////////////////////////////////////////////////// ring R = 0,(x(1..4)),dp; def ER = superCommutative(2); // (b = 2, e = N) setring ER; ER; if(IsSCA()) { "This is a SCA! Alternating variables: [", AltVarStart(), ",", AltVarEnd(), "]."; } else { "Not a super-commutative algebra!!!"; } kill R, ER; } /////////////////////////////////////////////////////////////////////////////// proc Exterior(list #) "USAGE: Exterior(); RETURN: qring PURPOSE: create the exterior algebra of a basering NOTE: activate this qring with the \"setring\" command THEORY: given a basering, this procedure introduces the anticommutative relations x(j)x(i)=-x(i)x(j) for all j>i, @* moreover, creates a factor algebra modulo the two-sided ideal, generated by x(i)^2 for all i EXAMPLE: example Exterior; shows examples " { string rname=nameof(basering); if ( rname == "basering") // i.e. no ring has been set yet { "You have to call the procedure from the ring"; return(); } int N = nvars(basering); string NewRing = "ring @R=("+charstr(basering)+"),("+varstr(basering)+"),("+ordstr(basering)+");"; execute(NewRing); matrix @E = UpOneMatrix(N); @E = -1*(@E); def @@RR = nc_algebra(@E,0); setring @@RR; int i; ideal Q; for ( i=1; i<=N; i++ ) { Q[i] = var(i)^2; } Q = twostd(Q); qring @EA = Q; return(@EA); } example { "EXAMPLE:";echo=2; ring R = 0,(x(1..3)),dp; def ER = Exterior(); setring ER; ER; } /////////////////////////////////////////////////////////////////////////////// proc makeWeyl(int n, list #) "USAGE: makeWeyl(n,[p]); n an integer, n>0; p an optional integer (field characteristic) RETURN: ring PURPOSE: create the n-th Weyl algebra over the rationals Q or F_p NOTE: activate this ring with the \"setring\" command. @* The presentation of an n-th Weyl algebra is classical: D(i)x(i)=x(i)D(i)+1, @* where x(i) correspond to coordinates and D(i) to partial differentiations, i=1,...,n. @* If p is not prime, the next larger prime number will be used. SEE ALSO: Weyl EXAMPLE: example makeWeyl; shows examples "{ if (n<1) { print("Incorrect input"); return(); } int @p = 0; if ( size(#) > 0 ) { if ( typeof( #[1] ) == "int" ) { @p = #[1]; } } if (n ==1) { ring @rr = @p,(x,D),dp; } else { ring @rr = @p,(x(1..n),D(1..n)),dp; } setring @rr; def @rrr = Weyl(); return(@rrr); } example { "EXAMPLE:"; echo = 2; def a = makeWeyl(3); setring a; a; } ////////////////////////////////////////////////////////////////////// proc isNC() "USAGE: isNC(); PURPOSE: check whether a basering is commutative or not RETURN: int, 1 if basering is noncommutative and 0 otherwise EXAMPLE: example isNC; shows examples "{ string rname=nameof(basering); if ( rname == "basering") // i.e. no ring has been set yet { "You have to call the procedure from the ring"; return(); } int n = nvars(basering); int i,j; poly p; for (i=1; i 4) // basering is nc_algebra { matrix C = L[5]; matrix D = L[6]; if (size(module(D)) <> 0) { iscom = 0; } else { matrix U = UpOneMatrix(nvars(basering)); if (size(module(C-U)) <> 0) { iscom = 0; } } } return(iscom); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; isCommutative(); def D = Weyl(); setring D; isCommutative(); setring r; def R = nc_algebra(1,0); setring R; isCommutative(); } ////////////////////////////////////////////////////////////////////// proc isWeyl () "USAGE: isWeyl(); RETURN: int, 1 if basering is a Weyl algebra, or 0 otherwise PURPOSE: check whether basering is a Weyl algebra EXAMPLE: example isWeyl; shows an example " { int i,j; int notW = 0; int N = nvars(basering); if (N mod 2 <> 0) { return(notW); } // odd number of generators int n = N div 2; list L = ringlist(basering); if (size(L) < 6) { return(notW); } // basering is commutative matrix C = L[5]; matrix D = L[6]; matrix U = UpOneMatrix(N); if (size(ideal(C-U)) <> 0) { return(notW); } // lt(xy)<>lt(yx) ideal I = ideal(D); if (size(I) <> n) { return(notW); } // not n entries<>0 I = simplify(I,4+2); int sI = size(I); if (sI > 2) { return(notW); } // more than 2 distinct entries for (i=1; i<=sI; i++) { if (I[i]<>1 && I[i]<>-1) { return (notW); } // other values apart from 1,-1 } ideal Ro,Co; for (i=1; i<=N; i++) { Ro = D[1..N,i]; Co = D[i,1..N]; if (size(Ro)>1 || size(Co)>1) { return(int(0)); // var(i) doesn't commute with more than 1 other vars } } return(int(1)); // all tests passed: basering is Weyl algebra } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,c,d),dp; isWeyl(); def D = Weyl(1); setring D; //make from r a Weyl algebra b*a; isWeyl(); ring t = 0,(Dx,x,y,Dy),dp; matrix M[4][4]; M[1,2]=-1; M[3,4]=1; def T = nc_algebra(1,M); setring T; isWeyl(); } ////////////////////////////////////////////////////////////////////// proc embedMat(matrix A, int m, int n) "USAGE: embedMat(A,m,n); A,B matrix/module RETURN: matrix PURPOSE: embed A in the left upper corner of mxn matrix EXAMPLE: example embedMat; shows an example " { // returns A embedded in the left upper corner of mxn matrix int rA = nrows(A); int cA = ncols(A); if ((rA >m) || (cA>n)) { ERROR("wrong dimensions of the new matrix"); } matrix @M[m][n]; int i,j; for(i=1;i<=rA; i++) { for(j=1;j<=cA; j++) { @M[i,j]=A[i,j]; } } return(@M); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,c,d),dp; matrix M[2][3]; M[1,1]=a; M[1,2]=b;M[2,2]=d;M[1,3]=c; print(M); print(embedMat(M,3,4)); matrix N = M; N[2,2]=0; print(embedMat(N,3,4)); } //proc moduloSlim (matrix A, matrix B) proc moduloSlim (module A, module B) "USAGE: moduloSlim(A,B); A,B module/matrix/ideal RETURN: module PURPOSE: compute @code{modulo} with slimgb as engine EXAMPLE: example moduloSlim; shows an example " { def save = basering; int rA = nrows(A); int rB = nrows(B); int cA = ncols(A); int cB = ncols(B); int j; int dab; // difference a,b dab = rA - rB; if (dab <0) { // rArB: add zero rows to B B = embedMat(B,rA,cB); } def mering = makeModElimRing(save); setring mering; module A = imap(save, A); module B = imap(save, B); // create matrix C // matrix C[2*rA][cA+cB]; module C; int i; for(i=1; i<= cA; i++) { C = C, A[i] + gen(rA + i); } C = C,B; // for(i=1; i<=cB; i++) // { // C = C, B[i]; // } C = C[2..ncols(C)]; // print(C); matrix D = slimgb(C); module E; int k; // TODO: why only first row? need smth like rA rows... for(i=1; i<= ncols(D); i++) { k=1; // determine first zero in the column while ( (D[k,i]==0) && (k<= cA+rA) ) { k++; } // what can that be: k = cA+rA+1=> zero column // k<=rA => column not in ker // rA+1 <= k <= rA+cA => column in ker if ( ( k>=rA+1) && (k<=rA+cA) ) { E = E,D[i]; } } // for(i=1; i<= ncols(D); i++) // { // if (D[1,i]==0) // { // E = E,D[i]; // } // } // // this E has 1st column and 1st row zero // use submat@matrix.lib // E = submat(E,intvec(2..nrows(E)),intvec(2..ncols(E))); E = submat(E,intvec(rA+1..nrows(E)),intvec(2..ncols(E))); setring save; module E = imap(mering,E); kill mering; // TODO: clean components! return(E); } example { "EXAMPLE:"; echo = 2; LIB "ncalg.lib"; ring r; // first classical example for modulo ideal h1=x,y,z; ideal h2=x; module m=moduloSlim(h1,h2); print(m); // now, a noncommutative example def A = makeUsl2(); setring A; // this algebra is U(sl_2) ideal H2 = e2,f2,h2-1; H2 = twostd(H2); print(matrix(H2)); // print H2 in a compact form ideal H1 = std(e); ideal T = moduloSlim(H1,H2); T = std( NF(std(H2+T),H2) ); T; // now, a matrix example: ring r2 = 0,(x,d), (dp); def R = nc_algebra(1,1); setring R; matrix M[2][2] = d, 0, 0, d*(x*d); matrix P[2][1] = (8x+7)*d+9x, (x2+1)*d + 5*x; module X = moduloSlim(P,M); print(X); } ////////////////////////////////////////////////////////////////////// proc makeModElimRing(list #) "USAGE: makeModElimRing(L); L a list RETURN: ring PURPOSE: create a copy of a given ring equipped with the @* elimination ordering for module components @code{(c,<)} NOTE: usually the list argument contains a ring to work with EXAMPLE: example makeModElimRing; shows an example " { // supports qring; // can be extended to handle C istead of c /* input/basering business */ def save; int Noinput = 0; if ( size(#)>0 ) { if (typeof(#[1]) == "ring" ) { save = #[1]; } else { print("unsupported input type, proceeding with basering"); Noinput = 1; } } if (Noinput) { if (nameof(basering)=="basering") { ERROR("no rings are given"); } else { save = basering; } } /* END input/basering business */ list L = ringlist(save); list Ord = L[3]; int s = size(Ord); int done; // detect where module ordering is located: either 1st or last entry int i,j; for(i=1; i<=s; i++) { if ( (Ord[i][1] == "C") || (Ord[i][1] == "c") ) { Ord[i][1] = "c"; j = i; i=s; } } if (j==0) { ERROR("no component entry found in the ringlist"); } list N; N[1] = Ord[j]; for(i=2; i<=j; i++) { N[i] = Ord[i-1]; } for(i=j+1; i<=s; i++) { N[i] = Ord[i]; } L[3] = N; def NR = ring(L); return(NR); } example { "EXAMPLE:"; echo = 2; ring r1 = 0,(x,y,z),(C,Dp); def r2 = makeModElimRing(r1); setring r2; r2; kill r2; ring r3 = 0,(z,t),(wp(2,3),c); def r2 = makeModElimRing(r3); setring r2; r2; kill r2; ring r4 = 0,(z,t,u,w),(a(1,2),C,wp(2,3,4,5)); def r2 = makeModElimRing(r4); setring r2; r2; } proc isLieType() "USAGE: isLieType(); RETURN: int, 1 if basering is a G-algebra of Lie type, 0 otherwise PURPOSE: G-algebra of Lie type has relations of the kind Y*X=X*Y+D EXAMPLE: example isLieType; shows an example " { def @B = basering; //save the name of basering int NVars = nvars(@B); //number of variables in basering int i, j; int answer = 1; // check basering is of Lie type: matrix @@CC[NVars][NVars]; for(i=1; i1 ) || ( (size(@C@)==1) && (@C@[1]!=1) ) ) { answer = 0; } return(answer); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; y*x; isLieType(); //yes def D = Weyl(); setring D; y*x; isLieType(); //yes setring r; def R = nc_algebra(-3,0); setring R; y*x; isLieType(); // no kill R; kill r; ring s = (0,q),(x,y),dp; def S = nc_algebra(q,0); setring S; y*x; isLieType(); //no kill S; setring s; def S = nc_algebra(q,y^2); setring S; y*x; isLieType(); //no } singular-4.0.3+ds/Singular/LIB/nfmodstd.lib000066400000000000000000000407461266270727000204700ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////////// version="version nfmodstd.lib 4.0.1.0 Sep_2014 "; // $Id: 839b0962067d1dafb230a592100f65f85495b25f $ category="Commutative Algebra"; info=" LIBRARY: nfmodstd.lib Groebner bases of ideals in polynomial rings over algebraic number fields AUTHORS: D.K. Boku boku@mathematik.uni-kl.de @* W. Decker decker@mathematik.uni-kl.de @* C. Fieker fieker@mathematik.uni-kl.de OVERVIEW: A library for computing the Groebner basis of an ideal in the polynomial ring over an algebraic number field Q(t) using the modular methods, where t is algebraic over the field of rational numbers Q. For the case Q(t) = Q, the procedure is inspired by Arnold [1]. This idea is then extended to the case t not in Q using factorization as follows: Let f be the minimal polynomial of t. For I, I' ideals in Q(t)[X], Q[X,t]/ respectively, we map I to I' via the map sending t to t + . We first choose a prime p such that f has at least two factors in characteristic p and add each factor f_i to I' to obtain the ideal J'_i = I' + . We then compute a standard basis G'_i of J'_i for each i and combine the G'_i to G_p (a standard basis of I'_p) using chinese remaindering for polynomials. The procedure is repeated for many primes p, where we compute the G_p in parallel until the number of primes is sufficiently large to recover the correct standard basis G' of I'. Finally, by mapping G' back to Q(t)[X], a standard basis G of I is obtained. REFERENCES: [1] E. A. Arnold: Modular algorithms for computing Groebner bases. J. Symb. Comp. 35, 403-419 (2003). PROCEDURES: chinrempoly(l,m); chinese remaindering for polynomials nfmodStd(I); standard basis of I over algebraic number field using modular methods "; LIB "modstd.lib"; //////////////////////////////////////////////////////////////////////////////// static proc testPrime(int p, ideal I) { /* * test whether a prime p divides the denominator(s) * and leading coefficients of generating set of ideal */ int i,j; poly f; number num; bigint d1,d2,d3; for(i = 1; i <= size(I); i++) { f = cleardenom(I[i]); if(f == 0) { return(0); } num = leadcoef(I[i])/leadcoef(f); d1 = bigint(numerator(num)); d2 = bigint(denominator(num)); if( (d1 mod p) == 0) { return(0); } if((d2 mod p) == 0) { return(0); } for(j = size(f); j > 0; j--) { d3 = bigint(leadcoef(f[j])); if( (d3 mod p) == 0) { return(0); } } } return(1); } //////////////////////////////////////////////////////////////////////////////// /* return 1 if the number of factors are in the required bound , 0 else */ static proc minpolyTask(poly f,int p) { /* * bound for irreducible factor(s) of (f mod p) * see testfact() */ int nr,k,ur; ur=deg(f); list L=factmodp(f,p); if(degtest(L[2])==1) { // now each factor is squarefree if(ur<=3) { return(1); } else { nr = testfact(ur); k=ncols(L[1]); if(nr < k && k < (ur-nr))// set bound for k { return(1); } } } return(0); } //////////////////////////////////////////////////////////////////////////////// /* return 1 if both testPrime(p,J) and minpolyTask(f,p) is true, 0 else */ static proc PrimeTestTask(int p, list L) { /* L=list(I), I=J,f; J ideal , f minpoly */ int sz,nr,dg; ideal J=L[1]; sz=ncols(J); poly f=J[sz]; dg=deg(f); if(!testPrime(p,J) or !minpolyTask(f,p)) { return(0); } return(1); } //////////////////////////////////////////////////////////////////////////////// /* compute factors of f mod p with multiplicity */ static proc factmodp(poly f, int p) { def R=basering; list l=ringlist(R); l[1]=p; def S=ring(l); setring S; list L=factorize(imap(R,f),2); ideal J=L[1]; intvec v=L[2]; list scx=J,v; setring R; return(imap(S,scx)); kill S; } //////////////////////////////////////////////////////////////////////////////// /* set a bound for number of factors w.r.t degree nr*/ static proc testfact(int nr) { // nr must be greater than 3 int i; if(nr>3 and nr<=5) { i=1; } if(nr>5 and nr<=10) { i=2; } if(nr>10 and nr<=15) { i=3; } if(nr>15 and nr<=20) { i=4; } if(nr>20 and nr<=25) { i=5; } if(nr>25 and nr<=30) { i=6; } if(nr>30) { i=10; } return(i); } /////////////////////////////////////////////////////////////////////////////// // return 1 if v[i]>1 , 0 else static proc degtest(intvec v) { for(int j=1;j<=nrows(v);j++) { if(v[j]>1) { return(0); } } return(1); } //////////////////////////////////////////////////////////////////////////////// static proc chinRm(list m, list ll, list lk,list l1,int uz) { poly ff,c; for(int i=1;i<=uz;i++) { c = division(l1[i]*ll[i],m[i])[2][1]; ff = ff + c*lk[i]; } return(ff); } //////////////////////////////////////////////////////////////////////////////// proc chinrempoly(list l,list m) "USAGE: chinrempoly(l, m); l list, m list RETURN: a polynomial (resp. ideal) which is congruent to l[i] modulo m[i] for all i NOTE: The procedure applies chinese remaindering to the first argument w.r.t. the moduli given in the second. The elements in the first list must be of same type which can be polynomial or ideal. The moduli must be of type polynomial. Elements in the second list must be distinct and co-prime. SEE ALSO: chinrem EXAMPLE: example chinrempoly; shows an example " { int i,j,sz,uz; uz = size(l); sz = ncols(ideal(l[1])); poly f=1; for(i=1;i<=uz;i++) { f=f*m[i]; } ideal I,J; list l1,ll,lk,l2; poly c,ff; for(j=1;j<=uz;j++) { lk[j]=f/m[j]; ll[j]=extgcd(lk[j],m[j])[2]; } for(i=1;i<=sz;i++) { for(j=1;j<=uz;j++) { I = l[j]; l1[j] = I[i]; } J[i] = chinRm(m,ll,lk,l1,uz); } return(J); } example { "EXAMPLE:"; echo = 2; ring rr=97,x,dp; poly f=x^7-7*x + 3; ideal J=factorize(f,1); J; list m=J[1..ncols(J)]; list l= x^2+2*x+3, x^2+5, x^2+7; ideal I=chinrempoly(l,m); I; ring s=0,x,dp; list m= x^2+2*x+3, x^3+5, x^4+x^3+7; list l=x^3 + 2, x^4 + 7, x^5 + 11; ideal I=chinrempoly(l,m); I; int p=prime(536546513); ring r = p, (x,y,a), (dp(2),dp(1)); poly minpolynomial = a^2+1; ideal kf=factorize(minpolynomial,1);//return factors without multiplicity kf; ideal k=(a+1)*x2+y, 3x-ay+ a+2; option(redSB); ideal k1=k,kf[1]; ideal k2 =k,kf[2]; k1=std(k1); k2=std(k2); list l=k1,k2; list m=kf[1..ncols(kf)]; ideal I=chinrempoly(l,m); I=simplify(I,2); I; } //////////////////////////////////////////////////////////////////////////////// static proc check_leadmonom_and_size(list L) { /* * compare the size of ideals in the list and * check the corresponding leading monomials * size(L)>=2 */ ideal J=L[1]; int i=size(L); int sc=ncols(J); int j,k; poly g=leadmonom(J[1]); for(j=1;j<=i;j++) { if(ncols(L[j])!=sc) { return(0); } } for(k=2;k<=i;k++) { for(j=1;j<=sc;j++) { if(leadmonom(J[j])!=leadmonom(L[k][j])) { return(0); } } } return(1); } //////////////////////////////////////////////////////////////////////////////// static proc LiftPolyCRT(ideal I) { /* * compute std for each factor and combine this result * to modulo minpoly via CRT for poly over char p>0 */ int u,in,j; list LL,Lk; ideal J,K,II; poly f; u=ncols(I); J=I[1..u-1]; f=I[u]; K=factorize(f,1); in=ncols(K); for(j=1;j<=in;j++) { LL[j]=K[j]; ideal I(j)=J,K[j]; I(j)=std(I(j)); if(size(I(j))==1) { Lk[j]=I(j); } else { I(j)[1]=0; I(j)=simplify(I(j), 2); Lk[j]=I(j); } } if(check_leadmonom_and_size(Lk)) { // apply CRT for polynomials II =chinrempoly(Lk,LL),f; } else { II=0; } return(II); } //////////////////////////////////////////////////////////////////////////////// static proc PtestStd(string command, list args, ideal result, int p) { /* * let G be std of I which is not yet known whether it is the correct * standard basis or not. So this procedure does the first test */ def br = basering; list lbr = ringlist(br); if (typeof(lbr[1]) == "int") { lbr[1] = p; } else { lbr[1][1] = p; } def rp = ring(lbr); setring(rp); ideal Ip = fetch(br, args)[1]; ideal Gp = fetch(br, result); attrib(Gp, "isSB", 1); int i; for (i = ncols(Ip); i > 0; i--) { if (reduce(Ip[i], Gp, 1) != 0) { setring(br); return(0); } } Ip = LiftPolyCRT(Ip); attrib(Ip,"isSB",1); for (i = ncols(Gp); i > 0; i--) { if (reduce(Gp[i], Ip, 1) != 0) { setring(br); return(0); } } setring(br); return(1); } //////////////////////////////////////////////////////////////////////////////// static proc cleardenomIdeal(ideal I) { int t=ncols(I); if(size(I)==0) { return(I); } else { for(int i=1;i<=t;i++) { I[i]=cleardenom(I[i]); } } return(I); } //////////////////////////////////////////////////////////////////////////////// static proc modStdparallelized(ideal I) { // apply modular.lib /* save options */ intvec opt = option(get); option(redSB); I = modular("Nfmodstd::LiftPolyCRT", list(I), PrimeTestTask, Modstd::deleteUnluckyPrimes_std, PtestStd, Modstd::finalTest_std,536870909); attrib(I, "isSB", 1); option(set,opt); return(I); } //////////////////////////////////////////////////////////////////////////////// /* main procedure */ proc nfmodStd(ideal I, list #) "USAGE: nfmodStd(I, #); I ideal, # optional parameters RETURN: standard basis of I over algebraic number field NOTE: The procedure passes to @ref{modStd} if the ground field has no parameter. In this case, the optional parameters # (if given) are directly passed to @ref{modStd}. SEE ALSO: modStd EXAMPLE: example nfmodStd; shows an example " { list L=#; def Rbs=basering; poly f; ideal J; int n=nvars(Rbs); if(size(I)==0) { return(ideal(0)); } if(npars(Rbs)==0) { J=modStd(I,L);//if algebraic number is in Q if(size(#)>0) { return(cleardenomIdeal(J)); } return(J); } list rl=ringlist(Rbs); f=rl[1][4][1]; rl[2][n+1]=rl[1][2][1]; rl[1]=rl[1][1]; rl[3][size(rl[3])+1]=rl[3][size(rl[3])]; rl[3][size(rl[3])-1]=list("dp",1); def S=ring(rl); setring S; poly f=imap(Rbs,f); ideal I=imap(Rbs,I); I = simplify(I,2);// eraze the zero generatos ideal J; if(f==0) { ERROR("minpoly must be non-zero"); } I=I,f; J=modStdparallelized(I); setring Rbs; J=imap(S,J); J=simplify(J,2); if(size(#)>0) { return(cleardenomIdeal(J)); } return(J); } example { "EXAMPLE:"; echo = 2; ring r1 =(0,a),(x,y),dp; minpoly =a^2+1; ideal k=(a/2+1)*x^2+2/3y, 3*x-a*y+ a/7+2; ideal I=nfmodStd(k); I; ring r2 =(0,a),(x,y,z),dp; minpoly =a^3 +2; ideal k=(a^2+a/2)*x^2+(a^2 -2/3*a)*yz, (3*a^2+1)*zx-(a+4/7)*y+ a+2/5; ideal IJ=nfmodStd(k); IJ; ring r3=0,(x,y),dp;// ring without parameter ideal I = x2 + y, xy - 7y + 2x; I=nfmodStd(I); I; } ////////////////////////////////////////////////////////////////////////////// /* Benchmark Problems from Boku, Decker, Fieker, Steenpass: Groebner Bases over Algebraic Number Fields. // 1 ring R = (0,a), (x,y,z), dp; minpoly = (a^2+1); poly f1 = (a+8)*x^2*y^2+5*x*y^3+(-a+3)*x^3*z +x^2*y*z; poly f2 = x^5+2*y^3*z^2+13*y^2*z^3+5*y*z^4; poly f3 = 8*x^3+(a+12)*y^3+x*z^2+3; poly f4 = (-a+7)*x^2*y^4+y^3*z^3+18*y^3*z^2; ideal I1 = f1,f2,f3,f4; // 2 ring R = (0,a), (x,y,z), dp; minpoly = (a^5+a^2+2); poly f1 = 2*x*y^4*z^2+(a-1)*x^2*y^3*z +(2*a)*x*y*z^2+7*y^3+(7*a+1); poly f2 = 2*x^2*y^4*z+(a)*x^2*y*z^2-x*y^2*z^2 +(2*a+3)*x^2*y*z-12*x+(12*a)*y; poly f3 = (2*a)*y^5*z+x^2*y^2*z-x*y^3*z +(-a)*x*y^3+y^4+2*y^2*z; poly f4 = (3*a)*x*y^4*z^3+(a+1)*x^2*y^2*z -x*y^3*z+4*y^3*z^2+(3*a)*x*y*z^3 +4*z^2-x+(a)*y; ideal I2 = f1,f2,f3,f4; // 3a ring R = (0,a), (v,w,x,y,z), dp; minpoly = (a^7-7*a+3); poly f1 = (a)*v+(a-1)*w+x+(a+2)*y+z; poly f2 = v*w+(a-1)*w*x+(a+2)*v*y+x*y+(a)*y*z; poly f3 = (a)*v*w*x+(a+5)*w*x*y+(a)*v*w*z +(a+2)*v*y*z+(a)*x*y*z; poly f4 = (a-11)*v*w*x*y+(a+5)*v*w*x*z +(a)*v*w*y*z+(a)*v*x*y*z +(a)*w*x*y*z; poly f5 = (a+3)*v*w*x*y*z+(a+23); ideal I3a = f1,f2,f3,f4,f5; // 3b ring R = (0,a), (u,v,w,x,y,z), dp; minpoly = (a^7-7*a+3); poly f1 = (a)*u+(a+2)*v+w+x+y+z; poly f2 = u*v+v*w+w*x+x*y+(a+3)*u*z+y*z; poly f3 = u*v*w+v*w*x+(a+1)*w*x*y+u*v*z+u*y*z +x*y*z; poly f4 = (a-1)*u*v*w*x+v*w*x*y+u*v*w*z +u*v*y*z+u*x*y*z+w*x*y*z; poly f5 = u*v*w*x*y+(a+1)*u*v*w*x*z+u*v*w*y*z +u*v*x*y*z+u*w*x*y*z+v*w*x*y*z; poly f6 = u*v*w*x*y*z+(-a+2); ideal I3b = f1,f2,f3,f4,f5,f6; // 4 ring R = (0,a), (w,x,y,z), dp; minpoly = (a^6+a^5+a^4+a^3+a^2+a+1); poly f1 = (a+5)*w^3*x^2*y+(a-3)*w^2*x^3*y +(a+7)*w*x^2*y^2; poly f2 = (a)*w^5+(a+3)*w*x^2*y^2 +(a^2+11)*x^2*y^2*z; poly f3 = (a+7)*w^3+12*x^3+4*w*x*y+(a)*z^3; poly f4 = 3*w^3+(a-4)*x^3+x*y^2; ideal I4 = f1,f2,f3,f4; // 5 ring R = (0,a), (w,x,y,z), dp; minpoly = (a^12-5*a^11+24*a^10-115*a^9+551*a^8 -2640*a^7+12649*a^6-2640*a^5+551*a^4 -115*a^3+24*a^2-5*a+1); poly f1 = (2*a+3)*w*x^4*y^2+(a+1)*w^2*x^3*y*z +2*w*x*y^2*z^3+(7*a-1)*x^3*z^4; poly f2 = 2*w^2*x^4*y+w^2*x*y^2*z^2 +(-a)*w*x^2*y^2*z^2 +(a+11)*w^2*x*y*z^3-12*w*z^6 +12*x*z^6; poly f3 = 2*x^5*y+w^2*x^2*y*z-w*x^3*y*z -w*x^3*z^2+(a)*x^4*z^2+2*x^2*y*z^3; poly f4 = 3*w*x^4*y^3+w^2*x^2*y*z^3 -w*x^3*y*z^3+(a+4)*x^3*y^2*z^3 +3*w*x*y^3*z^3+(4*a)*y^2*z^6-w*z^7 +x*z^7; ideal I5 = f1,f2,f3,f4; // 6 ring R = (0,a), (u,v,w,x,y,z), dp; minpoly = (a^2+5*a+1); poly f1 = u+v+w+x+y+z+(a); poly f2 = u*v+v*w+w*x+x*y+y*z+(a)*u+(a)*z; poly f3 = u*v*w+v*w*x+w*x*y+x*y*z+(a)*u*v +(a)*u*z+(a)*y*z; poly f4 = u*v*w*x+v*w*x*y+w*x*y*z+(a)*u*v*w +(a)*u*v*z+(a)*u*y*z+(a)*x*y*z; poly f5 = u*v*w*x*y+v*w*x*y*z+(a)*u*v*w*x +(a)*u*v*w*z+(a)*u*v*y*z+(a)*u*x*y*z +(a)*w*x*y*z; poly f6 = u*v*w*x*y*z+(a)*u*v*w*x*y +(a)*u*v*w*x*z+(a)*u*v*w*y*z +(a)*u*v*x*y*z+(a)*u*w*x*y*z +(a)*v*w*x*y*z; poly f7 = (a)*u*v*w*x*y*z-1; ideal I6 = f1,f2,f3,f4,f5,f6,f7; // 7 ring R = (0,a), (w,x,y,z), dp; minpoly = (a^8-16*a^7+19*a^6-a^5-5*a^4+13*a^3 -9*a^2+13*a+17); poly f1 = (-a^2-1)*x^2*y+2*w*x*z-2*w +(a^2+1)*y; poly f2 = (a^3-a-3)*w^3*y+4*w*x^2*y+4*w^2*x*z +2*x^3*z+(a)*w^2-10*x^2+4*w*y-10*x*z +(2*a^2+a); poly f3 = (a^2+a+11)*x*y*z+w*z^2-w-2*y; poly f4 = -w*y^3+4*x*y^2*z+4*w*y*z^2+2*x*z^3 +(2*a^3+a^2)*w*y+4*y^2-10*x*z-10*z^2 +(3*a^2+5); ideal I7 = f1,f2,f3,f4; // 8 ring R = (0,a), (t,u,v,w,x,y,z), dp; minpoly = (a^7+10*a^5+5*a^3+10*a+1); poly f1 = v*x+w*y-x*z-w-y; poly f2 = v*w-u*x+x*y-w*z+v+x+z; poly f3 = t*w-w^2+x^2-t; poly f4 = (-a)*v^2-u*y+y^2-v*z-z^2+u; poly f5 = t*v+v*w+(-a^2-a-5)*x*y-t*z+w*z+v+x+z +(a+1); poly f6 = t*u+u*w+(-a-11)*v*x-t*y+w*y-x*z-t-u +w+y; poly f7 = w^2*y^3-w*x*y^3+x^2*y^3+w^2*y^2*z -w*x*y^2*z+x^2*y^2*z+w^2*y*z^2 -w*x*y*z^2+x^2*y*z^2+w^2*z^3-w*x*z^3 +x^2*z^3; poly f8 = t^2*u^3+t^2*u^2*v+t^2*u*v^2+t^2*v^3 -t*u^3*x-t*u^2*v*x-t*u*v^2*x-t*v^3*x +u^3*x^2+u^2*v*x^2+u*v^2*x^2 +v^3*x^2; ideal I8 = f1,f2,f3,f4,f5,f6,f7,f8; */ singular-4.0.3+ds/Singular/LIB/noether.lib000066400000000000000000000706341266270727000203150ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version noether.lib 4.0.0.0 Jun_2013 "; // $Id: 3ac4f74f440223d4410077106d2595129e0647fb $ category="Commutative Algebra"; info=" LIBRARY: noether.lib Noether normalization of an ideal (not nessecary homogeneous) AUTHORS: A. Hashemi, Amir.Hashemi@lip6.fr OVERVIEW: A library for computing the Noether normalization of an ideal that DOES NOT require the computation of the dimension of the ideal. It checks whether an ideal is in Noether position. A modular version of these algorithms is also provided. The procedures are based on a paper of Amir Hashemi 'Efficient Algorithms for Computing Noether Normalization' (presented in ASCM 2007) This library computes also Castelnuovo-Mumford regularity and satiety of an ideal. A modular version of these algorithms is also provided. The procedures are based on a paper of Amir Hashemi 'Computation of Castelnuovo-Mumford regularity and satiety' (preprint 2008) PROCEDURES: NPos_test(id); checks whether monomial ideal id is in Noether position modNpos_test(id); the same as above using modular methods NPos(id); Noether normalization of ideal id modNPos(id); Noether normalization of ideal id by modular methods nsatiety(id); Satiety of ideal id modsatiety(id) Satiety of ideal id by modular methods regCM(id); Castelnuovo-Mumford regularity of ideal id modregCM(id); Castelnuovo-Mumford regularity of ideal id by modular methods "; LIB "elim.lib"; LIB "algebra.lib"; LIB "poly.lib"; LIB "ring.lib"; LIB "presolve.lib"; /////////////////////////////////////////////////////////////////////////////// proc NPos_test (ideal I) " USAGE: NPos_test (I); I monomial ideal RETURN: A list whose first element is 1, if i is in Noether position, 0 otherwise. The second element of this list is a list of variables ordered such that those variables are listed first, of which a power belongs to the initial ideal of i. If i is in Noether position, the method returns furthermore the dimension of i. ASSUME: i is a nonzero monomial ideal. " { //--------------------------- initialisation --------------------------------- int time,ii,j,k,l,d,t,jj; intvec v; def r0 = basering; int n = nvars(r0)-1; list L,Y,P1,P2,P3; if (I[1]==1) { print("The ideal is 1");return(1); } for ( ii = 1; ii <= n+1; ii++ ) { L[ii]=0; } for ( ii = 1; ii <= size(I); ii++ ) { Y=variables(I[ii]); l=rvar(Y[1][1]); if (size(Y[1])==1) { L[l]=1; P1=insert(P1,Y[1][1]); } if (L[l]==0) { L[l]=-1; } } t=size(P1); if (t==0) { for ( jj = 1; jj <= n+1; jj++ ) { P3=insert(P3,varstr(jj)); } } else { P2=findvars(ideal(P1[1..t]))[3]; for ( jj = 1; jj <= size(P2[1]); jj++ ) { P3=insert(P3,P2[1][jj]); } } if (L[n+1]==-1) { return(list(0,P1+P3)); } for ( ii = 1; ii <= n; ii++ ) { if (L[ii]==-1) { return(list(0,P1+P3)); } if (L[ii]==0 and L[ii+1]==1) { return(list(0,P1+P3)); } } d=n+1-sum(L); print("The dimension of the ideal is:");print(d); return(list(1,P1+P3)); } ////////////////////////////////////////// proc modNpos_test (ideal i) "USAGE: modNpos_test(i); i an ideal RETURN: 1 if i is in Noether position 0 otherwise. NOTE: This test is a probabilistic test, and it computes the initial of the ideal modulo the prime number 2147483647 (the biggest prime less than 2^31). " { "// WARNING: // The procedure is probabilistic and it computes the initial of the ideal modulo the prime number 2147483647"; int p; def br=basering; setring br; ideal I; list #; option(redSB); p=2147483647; #=ringlist(br); #[1]=p; def oro=ring(#); setring oro; ideal sbi,lsbi; sbi=fetch(br,i); lsbi=lead(std(sbi)); setring br; I=fetch(oro,lsbi); I=simplify(I,1); attrib(I,"isSB",1); return(NPos_test(I)); } /////////////////////////////////////////////////////////////////////////////// proc NPos (ideal i) "USAGE: NPos(i); i ideal RETURN: A linear map phi such that phi(i) is in Noether position " { //--------------------------- initialisation --------------------------------- int ii,jj,d,time,n,nl; intmat ran; def r0 = basering; ideal K,chcoord; n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,K,chcoord,m,L; list #; poly P; map phi; i = fetch(r0,i); time=rtimer; system("--ticks-per-sec",10); i=std(i); sbi=sort(lead(i))[1]; #=NPos_test(sbi); if ( #[1]== 1 ) { return ("The ideal is in Noether position and the time of this computation is:",rtimer-time,"/10 sec."); } else { L=maxideal(1); chcoord=maxideal(1); for ( ii = 1; ii<=n+1; ii++ ) { chcoord[rvar(#[2][ii])]=L[ii]; } phi=r1,chcoord; sbi=phi(sbi); if ( NPos_test(sbi)[1] == 1 ) { setring r0; chcoord=fetch(r1,chcoord); return (chcoord,"and the time of this computation is:",rtimer-time,"/10 sec."); } } while ( nl < 30 ) { nl=nl+1; I=i; L=maxideal(1); for ( ii = n; ii>=0; ii-- ) { chcoord=select1(maxideal(1),1..ii); ran=random(100,1,ii); ran=intmat(ran,1,ii+1); ran[1,ii+1]=1; m=select1(maxideal(1),1..(ii+1)); for ( jj = 1; jj<=ii+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[ii+1]=P; L[ii+1]=P; P=0; phi=r1,chcoord; I=phi(I); if ( NPos_test(sort(lead(std(I)))[1])[1] == 1 ) { K=x(ii..n); setring r0; K=fetch(r1,K); ideal L=fetch(r1,L); return (L,"and the time of this computation is:",rtimer-time,"/10 sec."); } } } "// WARNING: // The procedure has entered in more than 30 loops: in your example // the method may enter an infinite loop over a finite field!"; return (-1); } /////////////////////////////////////////////////////////////////////////////// proc modNPos (ideal i) "USAGE: modNPos(i); i ideal RETURN: A linear map phi such that phi(i) is in Noether position NOTE: It uses the procedure modNPos_test to test Noether position. " { //--------------------------- initialisation --------------------------------- int ii,jj,d,time,n,nl; intmat ran; def r0 = basering; ideal K,chcoord; n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,K,chcoord,m,L; poly P; list #; map phi; i = fetch(r0,i); time=rtimer; system("--ticks-per-sec",10); #=modNPos_test(i); if ( #[1]== 1 ) { return ("The ideal is in Noether position and the time of this computation is:",rtimer-time,"/10 sec."); } else { L=maxideal(1); chcoord=maxideal(1); for ( ii = 1; ii<=n+1; ii++ ) { chcoord[rvar(#[2][ii])]=L[ii]; } phi=r1,chcoord; I=phi(i); if ( modNPos_test(I)[1] == 1 ) { setring r0; chcoord=fetch(r1,chcoord); return (chcoord,"and the time of this computation is:",rtimer-time,"/10 sec."); } } while ( nl < 30 ) { nl=nl+1; I=i; L=maxideal(1); for ( ii = n; ii>=0; ii-- ) { chcoord=select1(maxideal(1),1..ii); ran=random(100,1,ii); ran=intmat(ran,1,ii+1); ran[1,ii+1]=1; m=select1(maxideal(1),1..(ii+1)); for ( jj = 1; jj<=ii+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[ii+1]=P; L[ii+1]=P; P=0; phi=r1,chcoord; I=phi(I); if ( modNPos_test(I)[1] == 1 ) { K=x(ii..n); setring r0; K=fetch(r1,K); ideal L=fetch(r1,L); return (L,"and the time of this computation is:",rtimer-time,"/10 sec."); } } } "// WARNING: // The procedure has entered in more than 30 loops: in your example // the method may enter an infinite loop over a finite field!"; return (-1); } //////////////////////////////////////////////////////////////////////////////////// static proc TestLastVarIsInGenericPos (ideal i) "USAGE: TestLastVarIsInGenericPos (i); i a monomial ideal, RETURN: 1 if the last variable is in generic position for i and 0 otherwise. THEORY: The last variable is in generic position if the quotient of the ideal with respect to this variable is equal to the quotient of the ideal with respect to the maximal ideal. " { //--------------------------- initialisation --------------------------------- int n,ret; def r0 = basering; n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal I,i; i = fetch(r0,i); attrib(i,"isSB",1); I=quotient(select(i,n+1),x(n)); I=I*maxideal(1); ret=1; if (size(reduce(I,i)) <> 0) { ret=0; } return(ret); } //////////////////////////////////////////////////////////////////////////////////// proc nsatiety (ideal i) "USAGE: nsatiety (i); i ideal, RETURN: an integer, the satiety of i. (returns -1 if i is not homogeneous) ASSUME: i is a homogeneous ideal of the basering R=K[x(0)..x(n)]. THEORY: The satiety, or saturation index, of a homogeneous ideal i is the least integer s such that, for all d>=s, the degree d part of the ideals i and isat=sat(i,maxideal(1))[1] coincide. " { //--------------------------- initialisation --------------------------------- int e,ii,jj,h,d,time,lastv,nl,ret; intmat ran; def r0 = basering; int n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,K,chcoord,m,L; poly P; map phi; i = fetch(r0,i); time=rtimer; system("--ticks-per-sec",100); sbi=std(i); //----- Check ideal homogeneous if ( homog(sbi) == 0 ) { dbprint(2,"The ideal is not homogeneous, and time for this test is: " + string(rtimer-time) + "/100sec."); return (); } I=simplify(lead(sbi),1); attrib(I,"isSB",1); K=select(I,n+1); if (size(K) == 0) { dbprint(2,"sat(i)=0 and the time of this computation: " + string(rtimer-time) + "/100sec."); return(); } if (TestLastVarIsInGenericPos(I) == 1 ) { dbprint(2,"sat(i)=" + string(maxdeg1(K)) + " and the time of this computation: " + string(rtimer-time) + "/100sec."); return(); } while ( nl < 5 ) { nl=nl+1; chcoord=select1(maxideal(1),1..n); ran=random(100,1,n); ran=intmat(ran,1,n+1); ran[1,n+1]=1; m=select1(maxideal(1),1..(n+1)); for ( jj = 1; jj<=n+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[n+1]=P; P=0; phi=r1,chcoord; L=std(phi(i)); I=simplify(lead(L),1); attrib(I,"isSB",1); K=select(I,n+1); if (size(K) == 0) { dbprint(2,"sat(i)=0 and the time of this computation: " + string(rtimer-time) + "/100sec."); return(); } if (TestLastVarIsInGenericPos(I) == 1 ) { dbprint(2,"sat(i)=" + string(maxdeg1(K)) + " and the time of this computation: " + string(rtimer-time) + "/100sec."); return(); } } } ////////////////////////////////////////////////////////////////////////////// proc modsatiety (ideal i) "USAGE: modsatiety(i); i ideal, RETURN: an integer, the satiety of i. (returns -1 if i is not homogeneous) ASSUME: i is a homogeneous ideal of the basering R=K[x(0)..x(n)]. THEORY: The satiety, or saturation index, of a homogeneous ideal i is the least integer s such that, for all d>=s, the degree d part of the ideals i and isat=sat(i,maxideal(1))[1] coincide. NOTE: This is a probabilistic procedure, and it computes the initial of the ideal modulo the prime number 2147483647 (the biggest prime less than 2^31). " { //--------------------------- initialisation --------------------------------- "// WARNING: The characteristic of base field must be zero. // The procedure is probabilistic and it computes the //initial ideals modulo the prime number 2147483647."; int e,ii,jj,h,d,time,lastv,nl,ret,s1,d1,siz,j,si,u,k,p; intvec v1; intmat ran; def r0 = basering; int n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,K,chcoord,m,L,sbi1,lsbi1,id1; vector V1; list #,LL,PL,Gb1,VGb1,Gb2,VGb2,Res1,Res2; poly P; map phi; time=rtimer; system("--ticks-per-sec",100); i = fetch(r0,i); //----- Check ideal homogeneous if ( homog(i) == 0 ) { "// WARNING: The ideal is not homogeneous."; dbprint(2,"Time for this test is: " + string(rtimer-time) + "/100sec."); return (); } option(redSB); p=2147483647; list r2=ringlist(r1); r2[1]=p; def oro=ring(r2); setring oro; ideal sbi=fetch(r1,i); sbi=std(sbi); setring r1; sbi=fetch(oro,sbi); kill oro; I=simplify(lead(sbi),1); attrib(I,"isSB",1); K=select(I,n+1); if (size(K) == 0) { dbprint(2,"msat(i)=0 and the time of this computation: " + string(rtimer-time) + "/100sec."); return(); } if (TestLastVarIsInGenericPos(I) == 1 ) { dbprint(2,"msat(i)=" + string(maxdeg1(K)) + " and the time of this computation: " + string(rtimer-time) + "/100sec."); return(); } while ( nl < 30 ) { nl=nl+1; chcoord=select1(maxideal(1),1..n); ran=random(100,1,n); ran=intmat(ran,1,n+1); ran[1,n+1]=1; m=select1(maxideal(1),1..(n+1)); for ( jj = 1; jj<=n+1; jj++ ) { P=P+ran[1,jj]*m[jj]; } chcoord[n+1]=P; P=0; phi=r1,chcoord; sbi=phi(i); list r2=ringlist(r1); r2[1]=p; def oro=ring(r2); setring oro; ideal sbi=fetch(r1,sbi); sbi=std(sbi); setring r1; sbi=fetch(oro,sbi); kill oro; lsbi1=lead(sbi); attrib(lsbi1,"isSB",1); K=select(lsbi1,n+1); if (size(K) == 0) { dbprint(2,"msat(i)=0 and the time of this computation: " + string(rtimer-time) + "/100sec."); return(); } if (TestLastVarIsInGenericPos(lsbi1) == 1 ) { dbprint(2,"msat(i)=" + string(maxdeg1(K)) + " and the time of this computation: " + string(rtimer-time) + "/100sec."); return(); } } } ////////////////////////////////////////////////////////////////////////////// // proc regCM (ideal i) "USAGE: regCM (i); i ideal RETURN: the Castelnuovo-Mumford regularity of i. (returns -1 if i is not homogeneous) ASSUME: i is a homogeneous ideal. " { //--------------------------- initialisation --------------------------------- int e,ii,jj,H,h,d,time,nl; def r0 = basering; int n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,J,K,L; list #; poly P; map phi; i = fetch(r0,i); time=rtimer; system("--ticks-per-sec",100); sbi=std(i); //----- Check ideal homogeneous if ( homog(sbi) == 0 ) { "// The ideal is not homogeneous!"; return (-1); } I=simplify(lead(sbi),1); attrib(I,"isSB",1); d=dim(I); if (char(r1) > 0 and d == 0) { def r2=changechar(0,r1); setring r2; ideal sbi,I,i,K,T; map phi; I = fetch(r1,I); i=I; attrib(I,"isSB",1); } else { def r2=changechar(ringlist(r1),r1); setring r2; ideal sbi,I,i,K,T,ic,Ic; map phi; I = imap(r1,I); Ic=I; attrib(I,"isSB",1); i = imap(r1,i); ic=i; } K=select(I,n+1); if (size(K) == 0) { h=0; } else { if (TestLastVarIsInGenericPos(I) == 1) { h=maxdeg1(K); } else { while ( nl < 30 ) { nl=nl+1; phi=r2,randomLast(100); T=phi(i); I=simplify(lead(std(T)),1); attrib(I,"isSB",1); K=select(I,n+1); if (size(K) == 0) { h=0;break; } if (TestLastVarIsInGenericPos(I) == 1 ) { h=maxdeg1(K);break; } } i=T; } } for ( ii = n; ii>=n-d+1; ii-- ) { i=subst(i,x(ii),0); s = "ring mr = ",charstr(r1),",x(0..ii-1),dp;"; execute(s); ideal i,sbi,I,J,K,L,T; poly P; map phi; i=imap(r2,i); I=simplify(lead(std(i)),1); attrib(I,"isSB",1); K=select(I,ii); if (size(K) == 0) { H=0; } else { if (TestLastVarIsInGenericPos(I) == 1) { H=maxdeg1(K); } else { while ( nl < 30 ) { nl=nl+1; phi=mr,randomLast(100); T=phi(i); I=simplify(lead(std(T)),1); attrib(I,"isSB",1); K=select(I,ii); if (size(K) == 0) { H=0;break; } if (TestLastVarIsInGenericPos(I) == 1 ) { H=maxdeg1(K);break; } } setring r2; i=imap(mr,T); kill mr; } } if (H > h) { h=H; } } if (nl < 30) { dbprint(2,"reg(i)=" + string(h) + " and the time of this computation: " + string(rtimer-time) + " sec./100"); return(); } else { I=Ic; attrib(I,"isSB",1); i=ic; K=subst(select(I,n+1),x(n),1); K=K*maxideal(maxdeg1(I)); if (size(reduce(K,I)) <> 0) { nl=0; while ( nl < 30 ) { nl=nl+1; phi=r1,randomLast(100); sbi=phi(i); I=simplify(lead(std(sbi)),1); attrib(I,"isSB",1); K=subst(select(I,n+1),x(n),1); K=K*maxideal(maxdeg1(I)); if (size(reduce(K,I)) == 0) { break; } } } h=maxdeg1(simplify(reduce(quotient(I,maxideal(1)),I),2))+1; for ( ii = n; ii> n-d+1; ii-- ) { sbi=subst(sbi,x(ii),0); s = "ring mr = ",charstr(r0),",x(0..ii-1),dp;"; execute(s); ideal sbi,I,L,K,T; map phi; sbi=imap(r1,sbi); I=simplify(lead(std(sbi)),1); attrib(I,"isSB",1); K=subst(select(I,ii),x(ii-1),1); K=K*maxideal(maxdeg1(I)); if (size(reduce(K,I)) <> 0) { nl=0; while ( nl < 30 ) { nl=nl+1; L=randomLast(100); phi=mr,L; T=phi(sbi); I=simplify(lead(std(T)),1); attrib(I,"isSB",1); K=subst(select(I,ii),x(ii-1),1); K=K*maxideal(maxdeg1(I)); if (size(reduce(K,I)) == 0) { sbi=T; break; } } } H=maxdeg1(simplify(reduce(quotient(I,maxideal(1)),I),2))+1; if (H > h) { h=H; } setring r1; sbi=fetch(mr,sbi); kill mr; } sbi=subst(sbi,x(n-d+1),0); s = "ring mr = ",charstr(r0),",x(0..n-d),dp;"; execute(s); ideal sbi,I,L,K,T; map phi; sbi=imap(r1,sbi); I=simplify(lead(std(sbi)),1); attrib(I,"isSB",1); H=maxdeg1(simplify(reduce(quotient(I,maxideal(1)),I),2))+1; if (H > h) { h=H; } dbprint(2,"reg(i)=" + string(h) + " and the time of this computation: " + string(rtimer-time) + " sec./100"); return(); } } ////////////////////////////////////////////////////////////////////////////// // proc modregCM(ideal i) "USAGE: modregCM(i); i ideal RETURN: an integer, the Castelnuovo-Mumford regularity of i. (returns -1 if i is not homogeneous) ASSUME: i is a homogeneous ideal and the characteristic of base field is zero.. NOTE: This is a probabilistic procedure, and it computes the initial of the ideal modulo the prime number 2147483647 (the biggest prime less than 2^31). " { //--------------------------- initialisation --------------------------------- "// WARNING: The characteristic of base field must be zero. // This procedure is probabilistic and it computes the initial //ideals modulo the prime number 2147483647"; int e,ii,jj,H,h,d,time,p,nl; def r0 = basering; int n = nvars(r0)-1; string s = "ring r1 = ",charstr(r0),",x(0..n),dp;"; execute(s); ideal i,sbi,I,J,K,L,lsbi1,lsbi2; list #; poly P; map phi; i = fetch(r0,i); time=rtimer; system("--ticks-per-sec",100); //----- Check ideal homogeneous if ( homog(i) == 0 ) { "// The ideal is not homogeneous!"; return (-1); } option(redSB); p=2147483647; #=ringlist(r1); #[1]=p; def oro=ring(#); setring oro; ideal sbi,lsbi; sbi=fetch(r1,i); lsbi=lead(std(sbi)); setring r1; lsbi1=fetch(oro,lsbi); lsbi1=simplify(lsbi1,1); attrib(lsbi1,"isSB",1); kill oro; I=lsbi1; d=dim(I); K=select(I,n+1); if (size(K) == 0) { h=0; } else { if (TestLastVarIsInGenericPos(I) == 1) { h=maxdeg1(K); } else { while ( nl < 30 ) { nl=nl+1; phi=r1,randomLast(100); sbi=phi(i); #=ringlist(r1); #[1]=p; def oro=ring(#); setring oro; ideal sbi,lsbi; sbi=fetch(r1,sbi); lsbi=lead(std(sbi)); setring r1; lsbi1=fetch(oro,lsbi); lsbi1=simplify(lsbi1,1); attrib(lsbi1,"isSB",1); kill oro; I=lsbi1; K=select(I,n+1); if (size(K) == 0) { h=0;break; } if (TestLastVarIsInGenericPos(I) == 1 ) { h=maxdeg1(K);break; } } i=sbi; } } for ( ii = n; ii>=n-d+1; ii-- ) { i=subst(i,x(ii),0); s = "ring mr = ","0",",x(0..ii-1),dp;"; execute(s); ideal i,sbi,I,J,K,L,lsbi1; poly P; list #; map phi; i=imap(r1,i); #=ringlist(mr); #[1]=p; def oro=ring(#); setring oro; ideal sbi,lsbi; sbi=fetch(mr,i); lsbi=lead(std(sbi)); setring mr; lsbi1=fetch(oro,lsbi); lsbi1=simplify(lsbi1,1); attrib(lsbi1,"isSB",1); kill oro; I=lsbi1; K=select(I,ii); if (size(K) == 0) { H=0; } else { if (TestLastVarIsInGenericPos(I) == 1) { H=maxdeg1(K); } else { nl=0; while ( nl < 30 ) { nl=nl+1; phi=mr,randomLast(100); sbi=phi(i); #=ringlist(mr); #[1]=p; def oro=ring(#); setring oro; ideal sbi,lsbi; sbi=fetch(mr,sbi); lsbi=lead(std(sbi)); setring mr; lsbi1=fetch(oro,lsbi); lsbi1=simplify(lsbi1,1); kill oro; I=lsbi1; attrib(I,"isSB",1); K=select(I,ii); if (size(K) == 0) { H=0;break; } if (TestLastVarIsInGenericPos(I) == 1 ) { H=maxdeg1(K);break; } } setring r1; i=imap(mr,sbi); kill mr; } } if (H > h) { h=H; } } dbprint(2,"mreg(i)=" + string(h) + " and the time of this computation: " + string(rtimer-time) + "sec./100"); return(); } /* ////////////////////////////////////////////////////////////// example { "EXAMPLE:"; echo = 2; ring r=0,(X,Y,a,b),dp; poly f=X^8+a*Y^4-Y; poly g=Y^8+b*X^4-X; poly h=diff(f,X)*diff(g,Y)-diff(f,Y)*diff(g,X); ideal i=f,g,h; } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,a,b),dp; ideal i=2*y^2*(y^2+x^2)+(b^2-3*a^2)*y^2-2*b*y^2*(x+y)+2*a^2*b*(y+x)-a^2*x^2+a^2*(a^2-b^2),4*y^3+4*y*(y^2+x^2)-2*b*y^2-4*b*y*(y+x)+2*(b^2-3*a^2)*y+2*a^2*b,4*x*y^2-2*b*y^2-2*a^2*x+2*a^2*b; } example { "EXAMPLE:"; echo = 2; ring r=0,(t,a,b,c,d),dp; ideal i=b4-a3d, ab3-a3c, bc4-ac3d-bcd3+ad4, c6-bc3d2-c3d3+bd5, ac5-b2c3d-ac2d3+b2d4, a2c4-a3d3+b3d3-a2cd3, b3c3-a3d3, ab2c3-a3cd2+b3cd2-ab2d3, a2bc3-a3c2d+b3c2d-a2bd3, a3c3-a3bd2, a4c2-a3b2d; } example { "EXAMPLE:"; echo = 2; ring r=0,(a,b,c,d,e),dp; ideal i=6*b4*c3+21*b4*c2*d+15b4cd2+9b4d3-8b2c2e-28b2cde+36b2d2e-144b2c-648b2d-120, 9b4c4+30b4c3d+39b4c2d2+18b4cd3-24b2c3e-16b2c2de+16b2cd2e+24b2d3e-432b2c2-720b2cd-432b2d2+16c2e2-32cde2+16d2e2+576ce-576de-240c+5184,-15b2c3e+15b2c2de-81b2c2+216b2cd-162b2d2+40c2e2-80cde2+40d2e2+1008ce-1008de+5184, -4b2c2+4b2cd-3b2d2+22ce-22de+261; } example { "EXAMPLE:"; echo = 2; ring r=0,(c,b,d,p,q),dp; ideal i=2*(b-1)^2+2*(q-p*q+p^2)+c^2*(q-1)^2-2*b*q+2*c*d*(1-q)*(q-p)+2*b*p*q*d*(d-c)+b^2*d^2*(1-2*p)+2*b*d^2*(p-q)+2*b*d*c*(p-1)+2*b*p*q*(c+1)+(b^2-2*b)*p^2*d^2+2*b^2*p^2+4*b*(1-b)*p+d^2*(p-q)^2,d*(2*p+1)*(q-p)+c*(p+2)*(1-q)+b*(b-2)*d+b*(1-2*b)*p*d+b*c*(q+p-p*q-1)+b*(b+1)*p^2*d, -b^2*(p-1)^2+2*p*(p-q)-2*(q-1),b^2+4*(p-q*q)+3*c^2*(q-1)*(q-1)-3*d^2*(p-q)^2+3*b^2*d^2*(p-1)^2+b^2*p*(p-2)+6*b*d*c*(p+q+q*p-1); } example { "EXAMPLE:"; echo = 2; ring r=0,(a,b,c,d,e,f),dp; ideal i=2adef+3be2f-cef2,4ad2f+5bdef+cdf2,2abdf+3b2ef-bcf2,4a2df+5abef+acf2,4ad2e+3bde2+7cdef, 2acde+3bce2-c2ef, 4abde+3b2e2-4acdf+2bcef-c2f2, 4a2de+3abe2+7acef, 4acd2+5bcde+c2df, 4abd2+3b2de+7bcdf, 16a2d2-9b2e2+32acdf-18bcef+7c2f2, 2abcd+3b2ce-bc2f, 4a2cd+5abce+ac2f, 4a2bd+3ab2e+7abcf, abc2f-cdef2, ab2cf-bdef2, 2a2bcf+3be2f2-cef3, ab3f-3bdf3, 2a2b2f-4adf3+3bef3-cf4, a3bf+4aef3, 3ac3e-cde3, 3b2c2e-bc3f+2cd2ef, abc2e-cde2f, 6a2c2e-4ade3-3be4+ce3f, 3b3ce-b2c2f+2bd2ef, 2a2bce+3be3f-ce2f2, 3a3ce+4ae3f, 4bc3d+cd3e, 4ac3d-3bc3e-2cd2e2+c4f, 8b2c2d-4ad4-3bd3e-cd3f, 4b3cd+3bd3f, 4ab3d+3b4e-b3cf-6bd2f2, 4a4d+3a3be+a3cf-8ae2f2; } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z,t,u,v,w),dp; ideal i=2tw+2wy-wz,2uw2-10vw2+20w3-7tu+35tv-70tw, 6tw2+2w2y-2w2z-21t2-7ty+7tz, 2v3-4uvw-5v2w+6uw2+7vw2-15w3-42vy, 6tw+9wy+2vz-3wz-21x, 9uw3-45vw3+135w4+14tv2-70tuw+196tvw-602tw2-14v2z+28uwz+14vwz-28w2z+147ux-735vx+2205wx-294ty+98tz+294yz-98z2, 36tw3+6w3y-9w3z-168t2w-14v2x+28uwx+14vwx-28w2x-28twy+42twz+588tx+392xy-245xz, 2uvw-6v2w-uw2+13vw2-5w3-28tw+14wy, u2w-3uvw+5uw2-28tw+14wy, tuw+tvw-11tw2-2vwy+8w2y+uwz-3vwz+5w2z-21wx, 5tuw-17tvw+33tw2-7uwy+22vwy-39w2y-2uwz+6vwz-10w2z+63wx, 20t2w-12uwx+30vwx-15w2x-10twy-8twz+4wyz, 4t2w-6uwx+12vwx-6w2x+2twy-2wy2-2twz+wyz, 8twx+8wxy-4wxz; } example { "EXAMPLE:"; echo = 2; ring r=0,(a,b,c,d,x,w,u,v),dp; ideal i=a+b+c+d,u+v+w+x, 3ab+3ac+3bc+3ad+3bd+3cd+2,bu+cu+du+av+cv+dv+aw+bw+dw+ax+bx+cx,bcu+bdu+cdu+acv+adv+cdv+abw+adw+bdw+abx+acx+bcx,abc+abd+acd+bcd,bcdu+acdv+abdw+abcx; } example { "EXAMPLE:"; echo = 2; ring r=0,(b,x,y,z,s,t,u,v,w),dp; ideal i=su+bv, tu+bw,tv+sw,sx+by,tx+bz,ty+sz,vx+uy,wx+uz,wy+vz; } example { "EXAMPLE:"; echo = 2; ring r=0,(t,a,b,c,d,e,f,g,h),dp; ideal i=a+c+d-e-h,2df+2cg+2eh-2h2-h-1,3df2+3cg2-3eh2+3h3+3h2-e+4h, 6bdg-6eh2+6h3-3eh+6h2-e+4h, 4df3+4cg3+4eh3-4h4-6h3+4eh-10h2-h-1, 8bdfg+8eh3-8h4+4eh2-12h3+4eh-14h2-3h-1, 12bdg2+12eh3-12h4+12eh2-18h3+8eh-14h2-h-1, -24eh3+24h4-24eh2+36h3-8eh+26h2+7h+1; } example { "EXAMPLE:"; echo = 2; ring r=0,(a,b,c,d,e,f,g,h,k,l),dp; ideal i=f2h-1,ek2-1,g2l-1, 2ef2g2hk2+f2g2h2k2+2ef2g2k2l+2f2g2hk2l+f2g2k2l2+ck2, 2e2fg2hk2+2efg2h2k2+2e2fg2k2l+4efg2hk2l+2fg2h2k2l+2efg2k2l2+2fg2hk2l2+2bfh, 2e2f2ghk2+2ef2gh2k2+2e2f2gk2l+4ef2ghk2l+2f2gh2k2l+2ef2gk2l2+2f2ghk2l2+2dgl, e2f2g2k2+2ef2g2hk2+2ef2g2k2l+2f2g2hk2l+f2g2k2l2+bf2, 2e2f2g2hk+2ef2g2h2k+2e2f2g2kl+4ef2g2hkl+2f2g2h2kl+2ef2g2kl2+2f2g2hkl2+2cek, e2f2g2k2+2ef2g2hk2+f2g2h2k2+2ef2g2k2l+2f2g2hk2l+dg2, -e2f2g2hk2-ef2g2h2k2-e2f2g2k2l-2ef2g2hk2l-f2g2h2k2l-ef2g2k2l2-f2g2hk2l2+a2; } example { "EXAMPLE:"; echo = 2; ring r=0,(b,c,d,e,f,g,h,j,k,l),dp; ideal i=-k9+9k8l-36k7l2+84k6l3-126k5l4+126k4l5-84k3l6+36k2l7-9kl8+l9, -bk8+8bk7l+k8l-28bk6l2-8k7l2+56bk5l3+28k6l3-70bk4l4-56k5l4+56bk3l5+70k4l5-28bk2l6-56k3l6+8bkl7+28k2l7-bl8-8kl8+l9, ck7-7ck6l-k7l+21ck5l2+7k6l2-35ck4l3-21k5l3+35ck3l4+35k4l4-21ck2l5-35k3l5+7ckl6+21k2l6-cl7-7kl7+l8, -dk6+6dk5l+k6l-15dk4l2-6k5l2+20dk3l3+15k4l3-15dk2l4-20k3l4+6dkl5+15k2l5-dl6-6kl6+l7, ek5-5ek4l-k5l+10ek3l2+5k4l2-10ek2l3-10k3l3+5ekl4+10k2l4-el5-5kl5+l6, -fk4+4fk3l+k4l-6fk2l2-4k3l2+4fkl3+6k2l3-fl4-4kl4+l5, gk3-3gk2l-k3l+3gkl2+3k2l2-gl3-3kl3+l4, -hk2+2hkl+k2l-hl2-2kl2+l3, jk-jl-kl+l2; } example { "EXAMPLE:"; echo = 2; ring r=0,x(0..10),dp; ideal i=x(1)*x(0),x(1)*x(2),x(2)*x(3),x(3)*x(4),x(4)*x(5),x(5)*x(6),x(6)*x(7),x(7)*x(8),x(8)*x(9),x(9)*x(10),x(10)*x(0); } example { "EXAMPLE:"; echo = 2; ring r=0,(a,b,c,d,e,f,g,h,j,k,l,m,n,o,p,q,s),dp; ideal i=ag,gj+am+np+q,bl,nq,bg+bk+al+lo+lp+b+c,ag+ak+jl+bm+bn+go+ko+gp+kp+lq+a+d+f+h+o+p,gj+jk+am+an+mo+no+mp+np+gq+kq+e+j+q+s-1,jm+jn+mq+nq,jn+mq+2nq,gj+am+2an+no+np+2gq+kq+q+s,2ag+ak+bn+go+gp+lq+a+d,bg+al, an+gq, 2jm+jn+mq, gj+jk+am+mo+2mp+np+e+2j+q, jl+bm+gp+kp+a+f+o+2p,lp+b,jn+mq,gp+a; } example { "EXAMPLE:"; echo = 2; ring r=0,(a,b,c,d,e,f,g,h,v,w,k,l,m,n,o,p,q,s,t,u),dp; ideal i=af+bg+ch+dv+ew-1/2, a2f+b2g+c2h+d2v+e2w-1/3,tdw+agk+ahl+bhm+avn+bvo+cvp+awq+bwu+cws-1/6, a3f+b3g+c3h+d3v+e3w-1/4, tdew+abgk+achl+bchm+advn+bdvo+cdvp+aewq+bewu+cews-1/8, td2w+a2gk+a2hl+b2hm+a2vn+b2vo+c2vp+a2wq+b2wu+c2ws-1/12, ahkm+tawn+tbwo+avko+tcwp+avlp+bvmp+awku+awls+bwms-1/24, a4f+b4g+c4h+d4v+e4w-1/5, tde2w+ab2gk+ac2hl+bc2hm+ad2vn+bd2vo+cd2vp+ae2wq+be2wu+ce2ws-1/10, td2ew+a2bgk+a2chl+b2chm+a2dvn+b2dvo+c2dvp+a2ewq+b2ewu+c2ews-1/15,achkm+taewn+tbewo+advko+tcewp+advlp+bdvmp+aewku+aewls+bewms-1/30,t2d2w+a2gk2+a2hl2+2abhlm+b2hm2+a2vn2+2abvno+b2vo2+2acvnp+2bcvop+c2vp2+2tadwq+a2wq2+2tbdwu+2abwqu+b2wu2+2tcdws+2acwqs+2bcwus+c2ws2-1/20,td3w+a3gk+a3hl+b3hm+a3vn+b3vo+c3vp+a3wq+b3wu+c3ws-1/20,abhkm+tadwn+tbdwo+abvko+tcdwp+acvlp+bcvmp+abwku+acwls+bcwms-1/40,a2hkm+ta2wn+tb2wo+a2vko+tc2wp+a2vlp+b2vmp+a2wku+a2wls+b2wms-1/60,tawko+tawlp+tbwmp+avkmp+awkms-1/20; } */ singular-4.0.3+ds/Singular/LIB/normal.lib000066400000000000000000006717021266270727000201440ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version normal.lib 4.0.1.1 Dec_2014 "; // $Id: 827ebffd6660fcaa018b95f88f16a2b3bc80f3fe $ category="Commutative Algebra"; info=" LIBRARY: normal.lib Normalization of Affine Rings AUTHORS: G.-M. Greuel, greuel@mathematik.uni-kl.de, @* S. Laplagne, slaplagn@dm.uba.ar, @* G. Pfister, pfister@mathematik.uni-kl.de PROCEDURES: normal(I,[...]); normalization of an affine ring normalP(I,[...]); normalization of an affine ring in positive characteristic normalC(I,[...]); normalization of an affine ring through a chain of rings HomJJ(L); presentation of End_R(J) as affine ring, J an ideal genus(I); computes the geometric genus of a projective curve primeClosure(L); integral closure of R/p, p a prime ideal closureFrac(L); writes a poly in integral closure as element of Quot(R/p) iMult(L); intersection multiplicity of the ideals of the list L deltaLoc(f,S); sum of delta invariants at conjugated singular points locAtZero(I); checks whether the zero set of I is located at 0 norTest(I,nor); checks the output of normal, normalP, normalC getSmallest(J); computes the polynomial of smallest degree of J getOneVar(J, vari); computes a polynomial of J in the variable vari changeDenominator(U1, c1, c2, I); computes ideal U2 such that 1/c1*U1=1/c2*U2 SEE ALSO: locnormal_lib;modnormal_lib "; LIB "general.lib"; LIB "poly.lib"; LIB "sing.lib"; LIB "primdec.lib"; LIB "elim.lib"; LIB "presolve.lib"; LIB "inout.lib"; LIB "ring.lib"; LIB "hnoether.lib"; LIB "reesclos.lib"; LIB "algebra.lib"; /////////////////////////////////////////////////////////////////////////////// proc normal(ideal id, list #) "USAGE: normal(id [,choose]); id = radical ideal, choose = list of options. @* Optional parameters in list choose (can be entered in any order):@* Decomposition:@* - \"equidim\" -> computes first an equidimensional decomposition of the input ideal, and then the normalization of each component (default).@* - \"prim\" -> computes first the minimal associated primes of the input ideal, and then the normalization of each prime. (When the input ideal is not prime and the minimal associated primes are easy to compute, this method is usually faster than \"equidim\".)@* - \"noDeco\" -> no preliminary decomposition is done. If the ideal is not equidimensional radical, output might be wrong.@* - \"isPrim\" -> assumes that the ideal is prime. If this assumption does not hold, the output might be wrong.@* - \"noFac\" -> factorization is avoided in the computation of the minimal associated primes; Other:@* - \"useRing\" -> uses the original ring ordering.@* If this option is set and if the ring ordering is not global, normal will change to a global ordering only for computing radicals and prime or equidimensional decompositions.@* If this option is not set, normal changes to dp ordering and performs all computations with respect to this ordering.@* - \"withDelta\" (or \"wd\") -> returns also the delta invariants.@* If the optional parameter choose is not given or empty, only \"equidim\" but no other option is used.@* - list(\"inputJ\", ideal inputJ) -> takes as initial test ideal the ideal inputJ. This option is only for use in other procedures. Using this option, the result might not be the normalization.@* (Option only valid for global algorithm.)@* - list(\"inputC\", ideal inputC) -> takes as initial conductor the ideal inputC. This option is only for use in other procedures. Using this option, the result might not be the normalization.@* (Option only valid for global algorithm.)@* Options used for computing integral basis (over rings of two variables):@* - \"var1\" -> uses a polynomial in the first variable as universal denominator.@* - \"var2\" -> uses a polynomial in the second variable as universal denominator.@* If the optional parameter choose is not given or empty, only \"equidim\" but no other option is used.@* ASSUME: The ideal must be radical, for non-radical ideals the output may be wrong (id=radical(id); makes id radical). However, when using the \"prim\" option the minimal associated primes of id are computed first and hence normal computes the normalization of the radical of id.@* NOTE: \"isPrim\" should only be used if id is known to be prime. RETURN: a list, say nor, of size 2 (resp. 3 with option \"withDelta\"). @format Let R denote the basering and id the input ideal. * nor[1] is a list of r rings, where r is the number of associated primes P_i with option \"prim\" (resp. >= no of equidimenensional components P_i with option \"equidim\").@* Each ring Ri := nor[1][i], i=1..r, contains two ideals with given names @code{norid} and @code{normap} such that: @* - Ri/norid is the normalization of the i-th component, i.e. the integral closure of R/P_i in its field of fractions (as affine ring); - @code{normap} gives the normalization map from R/id to Ri/norid for each i.@* - the direct sum of the rings Ri/norid, i=1,..r, is the normalization of R/id as affine algebra; @* * nor[2] is a list of size r with information on the normalization of the i-th component as module over the basering R:@* nor[2][i] is an ideal, say U, in R such that the integral closure of basering/P_i is generated as module over R by 1/c * U, with c the last element U[size(U)] of U.@* * nor[3] (if option \"withDelta\" is set) is a list of an intvec of size r, the delta invariants of the r components, and an integer, the total delta invariant of basering/id (-1 means infinite, and 0 that R/P_i resp. R/id is normal). @end format THEORY: We use here a general algorithm described in [G.-M.Greuel, S.Laplagne, F.Seelisch: Normalization of Rings (2009)].@* The procedure computes the R-module structure, the algebra structure and the delta invariant of the normalization of R/id:@* The normalization of R/id is the integral closure of R/id in its total ring of fractions. It is a finitely generated R-module and nor[2] computes R-module generators of it. More precisely: If U:=nor[2][i] and c:=U[size(U)], then c is a non-zero divisor and U/c is an R-module in the total ring of fractions, the integral closure of R/P_i. Since U[size(U)]/c is equal to 1, R/P_i resp. R/id is contained in the integral closure.@* The normalization is also an affine algebra over the ground field and nor[1] presents it as such. For geometric considerations nor[1] is relevant since the variety of the ideal norid in Ri is the normalization of the variety of the ideal P_i in R.@* The delta invariant of a reduced ring A is dim_K(normalization(A)/A). For A=K[x1,...,xn]/id we call this number also the delta invariant of id. nor[3] returns the delta invariants of the components P_i and of id. NOTE: To use the i-th ring type e.g.: @code{def R=nor[1][i]; setring R;}. @* Increasing/decreasing printlevel displays more/less comments (default: printlevel=0). @* Implementation works also for local rings. @* Not implemented for quotient rings. @* If the input ideal id is weighted homogeneous a weighted ordering may be used together with the useRing-option (qhweight(id); computes weights). KEYWORDS: normalization; integral closure; delta invariant. SEE ALSO: normalC, normalP. EXAMPLE: example normal; shows an example " { ASSUME(0, not isQuotientRing(basering) ); intvec opt = option(get); // Save current options int i,j; int decomp; // Preliminary decomposition: // 0 -> no decomposition (id is assumed to be prime) // 1 -> no decomposition // (id is assumed to be equidimensional radical) // 2 -> equidimensional decomposition // 3 -> minimal associated primes int noFac, useRing, withDelta; int dbg = printlevel - voice + 2; int nvar = nvars(basering); int chara = char(basering); int denomOption; // Method for choosing the conductor ideal inputJ = 0; // Test ideal given in the input (if any). ideal inputC = 0; // Conductor ideal given in the input (if any). list result, resultNew; list keepresult; list ringStruc; ideal U; poly c; int sp; // Number of components. // Default methods: noFac = 0; // Use facSTD when computing minimal associated primes decomp = 2; // Equidimensional decomposition useRing = 0; // Change first to dp ordering, and perform all // computations there. withDelta = 0; // Do not compute the delta invariant. denomOption = 0; // The default universal denominator is the smallest // degree polynomial. //--------------------------- define the method --------------------------- for ( i=1; i <= size(#); i++ ) { if ( typeof(#[i]) == "string" ) { //--------------------------- chosen methods ----------------------- if ( (#[i]=="isprim") or (#[i]=="isPrim") ) {decomp = 0;} if ( (#[i]=="nodeco") or (#[i]=="noDeco") ) {decomp = 1;} if (#[i]=="prim") {decomp = 3;} if (#[i]=="equidim") {decomp = 2;} if ( (#[i]=="nofac") or (#[i]=="noFac") ) {noFac=1;} if ( ((#[i]=="useRing") or (#[i]=="usering")) and (ordstr(basering) != "dp("+string(nvars(basering))+"),C")) {useRing = 1;} if ( (#[i]=="withDelta") or (#[i]=="wd") or (#[i]=="withdelta")) { if((decomp == 0) or (decomp == 3)) { withDelta = 1; } else { decomp = 3; withDelta = 1; //Note: the delta invariants cannot be computed with an equidimensional //decomposition, hence we compute first the minimal primes } } if (#[i]=="var1") {denomOption = 1;} if (#[i]=="var2") {denomOption = 2;} } if(typeof(#[i]) == "list"){ if(size(#[i]) == 2){ if (#[i][1]=="inputJ"){ if(typeof(#[i][2]) == "ideal"){ inputJ = #[i][2]; } } } if (#[i][1]=="inputC"){ if(size(#[i]) == 2){ if(typeof(#[i][2]) == "ideal"){ inputC = #[i][2]; } } } } } kill #; //------------------------ change ring if required ------------------------ // If the ordering is not global, we change to dp ordering for computing the // min ass primes. // If the ordering is global, but not dp, and useRing = 0, we also change to // dp ordering. int isGlobal = attrib(basering,"global");// Checks if the original ring has // global ordering. def origR = basering; // origR is the original ring // R is the ring where computations will be done if((useRing == 1) and (isGlobal == 1)) { def globR = basering; } else { // We change to dp ordering. list rl = ringlist(origR); list origOrd = rl[3]; list newOrd = list("dp", intvec(1:nvars(origR))), list("C", 0); rl[3] = newOrd; def globR = ring(rl); setring globR; ideal id = fetch(origR, id); } //------------------------ trivial checkings ------------------------ id = groebner(id); if((size(id) == 0) or (id[1] == 1)) { // The original ring R/I was normal. Nothing to do. // We define anyway a new ring, equal to R, to be able to return it. setring origR; list lR = ringlist(origR); def ROut = ring(lR); setring ROut; ideal norid = fetch(origR, id); ideal normap = maxideal(1); export norid; export normap; setring origR; if(withDelta) { result = list(list(ROut), list(ideal(1)), list(intvec(0), 0)); } else { result = list(list(ROut), list(ideal(1))); } sp = 1; // number of rings in the output option(set, opt); normalOutputText(dbg, withDelta, sp); return(result); } //------------------------ preliminary decomposition----------------------- list prim; if(decomp == 2) { dbprint(dbg, "// Computing the equidimensional decomposition..."); prim = equidim(id); } if((decomp == 0) or (decomp == 1)) { prim = id; } if(decomp == 3) { dbprint(dbg, "// Computing the minimal associated primes..."); if( noFac ) { prim = minAssGTZ(id,1); } else { prim = minAssGTZ(id); } } sp = size(prim); if(dbg>=1) { prim; ""; "// number of components is", sp; ""; } //----------------- back to the original ring if required ------------------ // if ring was not global and useRing is on, we go back to the original ring if((useRing == 1) and (isGlobal != 1)) { setring origR; def R = basering; list prim = fetch(globR, prim); } else { def R = basering; ideal inputJ = fetch(origR, inputJ); ideal inputC = fetch(origR, inputC); if(useRing == 0) { ideal U; poly c; } } // ---------------- normalization of the components------------------------- // calls normalM to compute the normalization of each component. list norComp; // The normalization of each component. int delt; int deltI = 0; int totalComps = 0; setring origR; def newROrigOrd; list newRListO; setring R; def newR; list newRList; for(i=1; i<=size(prim); i++) { if(dbg>=2){pause();} if(dbg>=1) { "// start computation of component",i; " --------------------------------"; } if(groebner(prim[i])[1] != 1) { if(dbg>=2) { "We compute the normalization in the ring"; basering; } printlevel = printlevel + 1; norComp = normalM(prim[i], decomp, withDelta, denomOption, inputJ, inputC); printlevel = printlevel - 1; for(j = 1; j <= size(norComp); j++) { newR = norComp[j][3]; if(!defined(savebasering)) { def savebasering;} savebasering=basering; setring newR; // must be in a compatible ring to newR // as ringlist may produce ring-dep. stuff if(!defined(newRList)) { list newRList;} newRList = ringlist(newR); setring savebasering; U = norComp[j][1]; c = norComp[j][2]; if(withDelta) { delt = norComp[j][4]; if((delt >= 0) and (deltI >= 0)) { deltI = deltI + delt; } else { deltI = -1; } } // -- incorporate result for this component to the list of results --- if(useRing == 0) { // We go back to the original ring. setring origR; U = fetch(R, U); c = fetch(R, c); newRListO = imap(newR, newRList); // We change the ordering in the new ring. if(nvars(newR) > nvars(origR)) { newRListO[3]=insert(origOrd, newRListO[3][1]); } else { newRListO[3] = origOrd; } newROrigOrd = ring(newRListO); setring newROrigOrd; ideal norid = imap(newR, norid); ideal normap = imap(newR, normap); export norid; export normap; setring origR; totalComps++; result[totalComps] = list(U, c, newROrigOrd); if(withDelta) { result[totalComps] = insert(result[totalComps], delt, 3); } setring R; } else { setring R; totalComps++; result[totalComps] = norComp[j]; } } } } // -------------------------- delta computation ---------------------------- if(withDelta == 1) { // Intersection multiplicities of list prim, sp=size(prim). if ( dbg >= 1 ) { "// Sum of delta for all components: ", deltI; } if(size(prim) > 1) { dbprint(dbg, "// Computing the sum of the intersection multiplicities of the components..."); int mul = iMult(prim); if ( mul < 0 ) { deltI = -1; } else { deltI = deltI + mul; } if ( dbg >= 1 ) { "// Intersection multiplicity is : ", mul; } } } // -------------------------- prepare output ------------------------------ setring origR; list RL; // List of rings list MG; // Module generators intvec DV; // Vector of delta's of each component for(i = 1; i <= size(result); i++) { RL[i] = result[i][3]; MG[i] = lineUpLast(result[i][1], result[i][2]); if(withDelta) { DV[i] = result[i][4]; } } if(withDelta) { resultNew = list(RL, MG, list(DV, deltI)); } else { resultNew = list(RL, MG); } sp = size(RL); //RL = list of rings option(set, opt); normalOutputText(dbg, withDelta, sp); return(resultNew); } example { "EXAMPLE:"; printlevel = printlevel+1; echo = 2; ring s = 0,(x,y),dp; ideal i = (x2-y3)*(x2+y2)*x; list nor = normal(i, "withDelta", "prim"); nor; // 2 branches have delta = 1, and 1 branch has delta = 0 // the total delta invariant is 13 def R2 = nor[1][2]; setring R2; norid; normap; echo = 0; printlevel = printlevel-1; pause(" hit return to continue"); echo=2; ring r = 2,(x,y,z),dp; ideal i = z3-xy4; list nor = normal(i, "withDelta", "prim"); nor; // the delta invariant is infinite // xy2z/z2 and xy3/z2 generate the integral closure of r/i as r/i-module // in its quotient field Quot(r/i) // the normalization as affine algebra over the ground field: def R = nor[1][1]; setring R; norid; normap; } /////////////////////////////////////////////////////////////////////////////// // Prints the output text in proc normal. // static proc normalOutputText(int dbg, int withDelta, int sp) // int dbg: printlevel // int withDelta: output contains information about the delta invariant // int sp: number of output rings. { if ( dbg >= 0 ) { ""; if(!withDelta) { "// 'normal' created a list, say nor, of two elements."; } else { "// 'normal' created a list, say nor, of three elements."; } "// To see the list type"; " nor;"; ""; "// * nor[1] is a list of", sp, "ring(s)."; "// To access the i-th ring nor[1][i], give it a name, say Ri, and type"; " def R1 = nor[1][1]; setring R1; norid; normap;"; "// For the other rings type first (if R is the name of your base ring)"; " setring R;"; "// and then continue as for R1."; "// Ri/norid is the affine algebra of the normalization of R/P_i where"; "// P_i is the i-th component of a decomposition of the input ideal id"; "// and normap the normalization map from R to Ri/norid."; ""; "// * nor[2] is a list of", sp, "ideal(s). Let ci be the last generator"; "// of the ideal nor[2][i]. Then the integral closure of R/P_i is"; "// generated as R-submodule of the total ring of fractions by"; "// 1/ci * nor[2][i]."; if(withDelta) { ""; "// * nor[3] is a list of an intvec of size", sp, "the delta invariants "; "// of the components, and an integer, the total delta invariant "; "// of R/id (-1 means infinite, and 0 that R/P_i resp. R/id is normal)."; } } } /////////////////////////////////////////////////////////////////////////////// proc HomJJ (list Li) "USAGE: HomJJ (Li); Li = list: ideal SBid, ideal id, ideal J, poly p ASSUME: R = P/id, P = basering, a polynomial ring, id an ideal of P, @* SBid = standard basis of id, @* J = ideal of P containing the polynomial p, @* p = nonzero divisor of R COMPUTE: Endomorphism ring End_R(J)=Hom_R(J,J) with its ring structure as affine ring, together with the map R --> Hom_R(J,J) of affine rings, where R is the quotient ring of P modulo the standard basis SBid. RETURN: a list l of three objects @format l[1] : a polynomial ring, containing two ideals, 'endid' and 'endphi' such that l[1]/endid = Hom_R(J,J) and endphi describes the canonical map R -> Hom_R(J,J) l[2] : an integer which is 1 if phi is an isomorphism, 0 if not l[3] : an integer, = dim_K(Hom_R(J,J)/R) (the contribution to delta) if the dimension is finite, -1 otherwise @end format NOTE: printlevel >=1: display comments (default: printlevel=0) EXAMPLE: example HomJJ; shows an example " { ASSUME(0, not isQuotientRing(basering) ); //---------- initialisation --------------------------------------------------- int isIso,isPr,isHy,isCo,isRe,isEq,oSAZ,ii,jj,q,y; intvec rw,rw1; list L; y = printlevel-voice+2; // y=printlevel (default: y=0) def P = basering; ideal SBid, id, J = Li[1], Li[2], Li[3]; poly p = Li[4]; int noRed = 0; if(size(Li) > 4) { if(Li[5] == 1) { noRed = 1; } } attrib(SBid,"isSB",1); int homo = homog(Li[2]); //is 1 if id is homogeneous, 0 if not //---- set attributes for special cases where algorithm can be simplified ----- if( homo==1 ) { rw = ringweights(P); } if( typeof(attrib(id,"isPrim"))=="int" ) { if(attrib(id,"isPrim")==1) { isPr=1; } } if( typeof(attrib(id,"onlySingularAtZero"))=="int" ) { if(attrib(id,"onlySingularAtZero")==1){oSAZ=1; } } if( typeof(attrib(id,"isIsolatedSingularity"))=="int" ) { if(attrib(id,"isIsolatedSingularity")==1) { isIso=1; } } if( typeof(attrib(id,"isCohenMacaulay"))=="int" ) { if(attrib(id,"isCohenMacaulay")==1) { isCo=1; } } if( typeof(attrib(id,"isRegInCodim2"))=="int" ) { if(attrib(id,"isRegInCodim2")==1) { isRe=1; } } if( typeof(attrib(id,"isEquidimensional"))=="int" ) { if(attrib(id,"isEquidimensional")==1) { isEq=1; } } //-------------------------- go to quotient ring ------------------------------ qring R = SBid; ideal id = fetch(P,id); ideal J = fetch(P,J); poly p = fetch(P,p); ideal f,rf,f2; module syzf; //---------- computation of p*Hom(J,J) as R-ideal ----------------------------- if ( y>=1 ) { "// compute p*Hom(J,J) = p*J:J"; "// the ideal J:";J; } f = quotient(p*J,J); //### (neu GMG 4.10.08) divide by the greatest common divisor: poly gg = gcd( f[1],p ); for(ii=2; ii <=ncols(f); ii++) { gg=gcd(gg,f[ii]); } for(ii=1; ii<=ncols(f); ii++) { f[ii]=f[ii]/gg; } p = p/gg; if ( y>=1 ) { "// the non-zerodivisor p:"; p; "// the module p*Hom(J,J) = p*J:J :"; f; ""; } f2 = std(p); //---------- Test: Hom(J,J) == R ?, if yes, go home --------------------------- //rf = interred(reduce(f,f2)); //### interred hier weggelassen, unten zugefuegt rf = reduce(f,f2); //represents p*Hom(J,J)/p*R = Hom(J,J)/R if ( size(rf) == 0 ) { if ( homog(f) && find(ordstr(basering),"s")==0 ) { ring newR1 = char(P),(X(1..nvars(P))),(a(rw),dp); } else { ring newR1 = char(P),(X(1..nvars(P))),dp; } ideal endphi = maxideal(1); ideal endid = fetch(P,id); endid = simplify(endid,2); L = substpart(endid,endphi,homo,rw); //## hier substpart def lastRing = L[1]; setring lastRing; attrib(endid,"onlySingularAtZero",oSAZ); attrib(endid,"isCohenMacaulay",isCo); attrib(endid,"isPrim",isPr); attrib(endid,"isIsolatedSingularity",isIso); attrib(endid,"isRegInCodim2",isRe); attrib(endid,"isEqudimensional",isEq); attrib(endid,"isHypersurface",0); attrib(endid,"isCompleteIntersection",0); attrib(endid,"isRadical",0); L=lastRing; L = insert(L,1,1); dbprint(y,"// case R = Hom(J,J)"); if(y>=1) { "// R=Hom(J,J)"; lastRing; "// the new ideal"; endid; " "; "// the old ring"; P; "// the old ideal"; setring P; id; " "; setring lastRing; "// the map to the new ring"; endphi; " "; pause(); ""; } setring P; L[3]=0; return(L); } if(y>=1) { "// R is not equal to Hom(J,J), we have to try again"; pause(); ""; } //---------- Hom(J,J) != R: create new ring and map from old ring ------------- // the ring newR1/SBid+syzf will be isomorphic to Hom(J,J) as R-module // f2=p (i.e. ideal generated by p) //f = mstd(f)[2]; //### geaendert GMG 04.10.08 //ideal ann = quotient(f2,f); //### f durch rf ersetzt rf = mstd(rf)[2]; //rf = NF(f,p), hence = ideal ann = quotient(f2,rf); //p:f = p:rf //------------- compute the contribution to delta ---------- //delt=dim_K(Hom(JJ)/R (or -1 if infinite) int delt=vdim(std(modulo(f,ideal(p)))); f = p,rf; // generates pJ:J mod(p), i.e. p*Hom(J,J)/p*R as R-module q = size(f); syzf = syz(f); if ( homo==1 ) { rw1 = rw,0; for ( ii=2; ii<=q; ii++ ) { rw = rw, deg(f[ii])-deg(f[1]); rw1 = rw1, deg(f[ii])-deg(f[1]); } ring newR1 = char(R),(X(1..nvars(R)),T(1..q)),(a(rw1),dp); } else { ring newR1 = char(R),(X(1..nvars(R)),T(1..q)),dp; } //map psi1 = P,maxideal(1); //### psi1 durch fetch ersetzt //ideal SBid = psi1(SBid); ideal SBid = fetch(P,SBid); attrib(SBid,"isSB",1); qring newR = std(SBid); //map psi = R,ideal(X(1..nvars(R))); //### psi durch fetch ersetzt //ideal id = psi(id); //ideal f = psi(f); //module syzf = psi(syzf); ideal id = fetch(R,id); ideal f = fetch(R,f); module syzf = fetch(R,syzf); ideal pf,Lin,Quad,Q; matrix T,A; list L1; //---------- computation of Hom(J,J) as affine ring --------------------------- // determine kernel of: R[T1,...,Tq] -> J:J >-> R[1/p]=R[t]/(t*p-1), // Ti -> fi/p -> t*fi (p=f1=f[1]), to get ring structure. This is of course // the same as the kernel of R[T1,...,Tq] -> pJ:J >-> R, Ti -> fi. // It is a fact, that the kernel is generated by the linear and the quadratic // relations // f=p,rf, rf=reduce(f,p), generates pJ:J mod(p), // i.e. p*Hom(J,J)/p*R as R-module pf = f[1]*f; T = matrix(ideal(T(1..q)),1,q); Lin = ideal(T*syzf); if(y>=1) { "// the ring structure of Hom(J,J) as R-algebra"; "// the linear relations:"; Lin; } poly ff; for (ii=2; ii<=q; ii++ ) { for ( jj=2; jj<=ii; jj++ ) { ff = NF(f[ii]*f[jj],std(0)); //this makes lift much faster A = lift(pf,ff); //ff lin. comb. of elts of pf mod I Quad = Quad, ideal(T(jj)*T(ii) - T*A); //quadratic relations } } if(y>=1) { "// the quadratic relations"; Quad; pause(); newline; } Q = Lin,Quad; Q = subst(Q,T(1),1); //Q = mstd(Q)[2]; //### sehr aufwendig, daher weggelassen (GMG) //### ev das neue interred //mstd dient nur zum verkleinern, die SB-Eigenschaft geht spaeter verloren //da in neuen Ring abgebildet und mit id vereinigt //---------- reduce number of variables by substitution, if possible ---------- if (homo==1) { ring newRing = char(R),(X(1..nvars(R)),T(2..q)),(a(rw),dp); } else { ring newRing = char(R),(X(1..nvars(R)),T(2..q)),dp; } ideal endid = imap(newR,id),imap(newR,Q); //hier wird Q weiterverwendet, die SB-Eigenschaft wird nicht verwendet. endid = simplify(endid,2); ideal endphi = ideal(X(1..nvars(R))); if(noRed == 0) { L = substpart(endid,endphi,homo,rw); def lastRing=L[1]; setring lastRing; //return(lastRing); } else { list RL = ringlist(newRing); def lastRing = ring(RL); setring lastRing; ideal endid = fetch(newRing, endid); ideal endphi = fetch(newRing, endphi); export(endid); export(endphi); //def lastRing = newRing; //setring R; //return(newR); } // L = substpart(endid,endphi,homo,rw); // def lastRing=L[1]; // setring lastRing; attrib(endid,"onlySingularAtZero",0); map sigma=R,endphi; ideal an=sigma(ann); export(an); //noetig? //ideal te=an,endid; //if(isIso && (size(reduce(te,std(maxideal(1))))==0)) //#### ok??? // { // attrib(endid,"onlySingularAtZero",oSAZ); // } //kill te; attrib(endid,"isCohenMacaulay",isCo); //#### ok??? attrib(endid,"isPrim",isPr); attrib(endid,"isIsolatedSingularity",isIso); attrib(endid,"isRegInCodim2",isRe); attrib(endid,"isEquidimensional",isEq); attrib(endid,"isHypersurface",0); attrib(endid,"isCompleteIntersection",0); attrib(endid,"isRadical",0); if(y>=1) { "// the new ring after reduction of the number of variables"; lastRing; "// the new ideal"; endid; ""; "// the old ring"; P; "// the old ideal"; setring P; id; " "; setring lastRing; "// the map to the new ring"; endphi; " "; pause(); ""; } L = lastRing; L = insert(L,0,1); L[3] = delt; setring(P); return(L); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x,y),wp(2,3); ideal id = y^2-x^3; ideal J = x,y; poly p = x; list Li = std(id),id,J,p; list L = HomJJ(Li); def end = L[1]; // defines ring L[1], containing ideals endid, endphi setring end; // makes end the basering end; endid; // end/endid is isomorphic to End(r/id) as ring map psi = r,endphi;// defines the canonical map r/id -> End(r/id) psi; L[3]; // contribution to delta } /////////////////////////////////////////////////////////////////////////////// //compute intersection multiplicities as needed for delta(I) in //normalizationPrimes and normalP: proc iMult (list prim) "USAGE: iMult(L); L a list of ideals RETURN: int, the intersection multiplicity of the ideals of L; if iMult(L) is infinite, -1 is returned. THEORY: If r=size(L)=2 then iMult(L) = vdim(std(L[1]+L[2])) and in general iMult(L) = sum{ iMult(L[j],Lj) | j=1..r-1 } with Lj the intersection of L[j+1],...,L[r]. If I is the intersection of all ideals in L then we have delta(I) = delta(L[1])+...+delta(L[r]) + iMult(L) where delta(I) = vdim (normalisation(R/I)/(R/I)), R the basering. EXAMPLE: example iMult; shows an example " { ASSUME(0, not isQuotientRing(basering) ); int i,mul,mu; int sp = size(prim); int y = printlevel-voice+2; if ( sp > 1 ) { ideal I(sp-1) = prim[sp]; mu = vdim(std(I(sp-1)+prim[sp-1])); mul = mu; if ( y>=1 ) { "// intersection multiplicity of component",sp,"with",sp-1,":"; mu; } if ( mu >= 0 ) { for (i=sp-2; i>=1 ; i--) { ideal I(i) = intersect(I(i+1),prim[i+1]); mu = vdim(std(I(i)+prim[i])); if ( mu < 0 ) { break; } mul = mul + mu; if ( y>=1 ) { "// intersection multiplicity of components",sp,"...",i+1,"with",i; mu; } } } } return(mul); } example { "EXAMPLE:"; echo = 2; ring s = 23,(x,y),dp; list L = (x-y),(x3+y2); iMult(L); L = (x-y),(x3+y2),(x3-y4); iMult(L); } /////////////////////////////////////////////////////////////////////////////// //check if I has a singularity only at zero, as needed in normalizationPrimes proc locAtZero (ideal I) "USAGE: locAtZero(I); I = ideal RETURN: int, 1 if I has only one point which is located at zero, 0 otherwise ASSUME: I is given as a standard bases in the basering NOTE: only useful in affine rings, in local rings vdim does the check EXAMPLE: example locAtZero; shows an example " { ASSUME(0, not isQuotientRing(basering) ); int ii,jj, caz; //caz: conzentrated at zero int dbp = printlevel-voice+2; int nva = nvars(basering); int vdi = vdim(I); if ( vdi < 0 ) { if (dbp >=1) { "// non-isolated singularitiy";""; } return(caz); } //Now the ideal is 0-dim //First an easy test //If I is homogenous and not constant it is concentrated at 0 if( homog(I)==1 && size(jet(I,0))==0) { caz=1; if (dbp >=1) { "// isolated singularity and homogeneous";""; } return(caz); } //Now the general case with I 0-dim. Choose an appropriate power pot, //and check each variable x whether x^pot is in I. int mi1 = mindeg1(lead(I)); int pot = vdi; if ( (mi1+(mi1==1))^2 < vdi ) { pot = (mi1+(mi1==1))^2; //### alternativ: pot = vdi lassen } while ( 1 ) { caz = 1; for ( ii=1; ii<= nva; ii++ ) { if ( NF(var(ii)^pot,I) != 0 ) { caz = 0; break; } } if ( caz == 1 || pot >= vdi ) { if (dbp >=1) { "// mindeg, exponent, vdim used in 'locAtZero':", mi1,pot,vdi; ""; } return(caz); } else { if ( pot^2 < vdi ) { pot = pot^2; } else { pot = vdi; } } } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; poly f = z5+y4+x3+xyz; ideal i = jacob(f),f; i=std(i); locAtZero(i); i= std(i*ideal(x-1,y,z)); locAtZero(i); } /////////////////////////////////////////////////////////////////////////////// //The next procedure normalizationPrimes computes the normalization of an //irreducible or an equidimensional ideal i. //- If i is irreducuble, then the returned list, say nor, has size 2 //with nor[1] the normalization ring and nor[2] the delta invariant. //- If i is equidimensional, than the "splitting tools" can create a //decomposition of i and nor can have more than 1 ring. static proc normalizationPrimes(ideal i,ideal ihp,int delt,intvec delti,list #) "USAGE: normalizationPrimes(i,ihp,delt[,si]); i = equidimensional ideal, ihp = map (partial normalization), delt = partial delta-invariant, si = ideal s.t. V(si) contains singular locus (optional) RETURN: a list of rings, say nor, and an integer, the delta-invariant at the end of the list. each ring nor[j], j = 1..size(nor)-1, contains two ideals with given names norid and normap such that - the direct sum of the rings nor[j]/norid is the normalization of basering/i; - normap gives the normalization map from basering/id to nor[j]/norid (for each j) nor[size(nor)] = dim_K(normalisation(P/i) / (P/i)) is the delta-invariant, where P is the basering. EXAMPLE: example normalizationPrimes; shows an example " { ASSUME(1, not isQuotientRing(basering) ); //Note: this procedure calls itself as long as the test for //normality, i.e if R==Hom(J,J), is negative. int printlev = printlevel; //store printlevel in order to reset it later int y = printlevel-voice+2; // y=printlevel (default: y=0) if(y>=1) { ""; "// START a normalization loop with the ideal"; i; ""; "// in the ring:"; basering; ""; pause(); ""; } def BAS=basering; list result,keepresult1,keepresult2,JM,gnirlist; ideal J,SB,MB; int depth,lauf,prdim,osaz; int ti=timer; gnirlist = ringlist(BAS); //----------- the trivial case of a zero ideal as input, RETURN ------------ if(size(i)==0) { if(y>=1) { "// the ideal was the zero-ideal"; } def newR7 = ring(gnirlist); setring newR7; ideal norid=ideal(0); ideal normap=fetch(BAS,ihp); export norid; export normap; result=newR7; result[size(result)+1]=list(delt,delti); setring BAS; return(result); } //--------------- General NOTATION, compute SB of input ----------------- // SM is a list, the result of mstd(i) // SM[1] = SB of input ideal i, // SM[2] = (minimal) generators for i. // We work with SM and will copy the attributes from i to SM[2] // JM will be a list, either JM[1]=maxideal(1),JM[2]=maxideal(1) // in case i has onlySingularAtZero, or JM = mstd(si) where si = #[1], // or JM = mstd(J) where J is the ideal of the singular locus // JM[2] must be (made) radical if(y>=1) { "// SB-computation of the ideal"; } list SM = mstd(i); //Now the work starts int dimSM = dim(SM[1]); //dimension of variety to normalize if(y>=1) { "// the dimension is:"; dimSM; } //----------------- the general case, set attributes ---------------- //Note: onlySingularAtZero is NOT preserved under the ring extension //basering --> Hom(J,J) (in contrast to isIsolatedSingularity), //therefore we reset it: attrib(i,"onlySingularAtZero",0); if(attrib(i,"isPrim")==1) { attrib(SM[2],"isPrim",1); } else { attrib(SM[2],"isPrim",0); } if(attrib(i,"isIsolatedSingularity")==1) { attrib(SM[2],"isIsolatedSingularity",1); } else { attrib(SM[2],"isIsolatedSingularity",0); } if(attrib(i,"isCohenMacaulay")==1) { attrib(SM[2],"isCohenMacaulay",1); } else { attrib(SM[2],"isCohenMacaulay",0); } if(attrib(i,"isRegInCodim2")==1) { attrib(SM[2],"isRegInCodim2",1); } else { attrib(SM[2],"isRegInCodim2",0); } if(attrib(i,"isEquidimensional")==1) { attrib(SM[2],"isEquidimensional",1); } else { attrib(SM[2],"isEquidimensional",0); } if(attrib(i,"isCompleteIntersection")==1) { attrib(SM[2],"isCompleteIntersection",1); } else { attrib(SM[2],"isCompleteIntersection",0); } if(attrib(i,"isHypersurface")==1) { attrib(SM[2],"isHypersurface",1); } else { attrib(SM[2],"isHypersurface",0); } if(attrib(i,"onlySingularAtZero")==1) { attrib(SM[2],"onlySingularAtZero",1); } else { attrib(SM[2],"onlySingularAtZero",0); } //------- an easy and cheap test for onlySingularAtZero --------- if( (attrib(SM[2],"isIsolatedSingularity")==1) && (homog(SM[2])==1) ) { attrib(SM[2],"onlySingularAtZero",1); } //-------------------- Trivial cases, in each case RETURN ------------------ // input ideal is the ideal of a partial normalization // ------------ Trivial case: input ideal contains a unit --------------- if( dimSM == -1) { ""; " // A unit ideal was found."; " // Stop with partial result computed so far";""; MB=SM[2]; intvec rw; list LL=substpart(MB,ihp,0,rw); def newR6=LL[1]; setring newR6; ideal norid=endid; ideal normap=endphi; kill endid,endphi; export norid; export normap; result=newR6; result[size(result)+1]=list(delt,delti); setring BAS; return(result); } // --- Trivial case: input ideal is zero-dimensional and homog --- if( (dim(SM[1])==0) && (homog(SM[2])==1) ) { if(y>=1) { "// the ideal was zero-dimensional and homogeneous"; } MB=maxideal(1); intvec rw; list LL=substpart(MB,ihp,0,rw); def newR5=LL[1]; setring newR5; ideal norid=endid; ideal normap=endphi; kill endid,endphi; export norid; export normap; result=newR5; result[size(result)+1]=list(delt,delti); setring BAS; return(result); } // --- Trivial case: input ideal defines a line --- //the one-dimensional, homogeneous case and degree 1 case if( (dim(SM[1])==1) && (maxdeg1(SM[2])==1) && (homog(SM[2])==1) ) { if(y>=1) { "// the ideal defines a line"; } MB=SM[2]; intvec rw; list LL=substpart(MB,ihp,0,rw); def newR4=LL[1]; setring newR4; ideal norid=endid; ideal normap=endphi; kill endid,endphi; export norid; export normap; result=newR4; result[size(result)+1]=list(delt,delti); setring BAS; return(result); } //---------------------- The non-trivial cases start ------------------- //the higher dimensional case //we test first hypersurface, CohenMacaulay and complete intersection if( ((size(SM[2])+dim(SM[1])) == nvars(basering)) ) { //the test for complete intersection attrib(SM[2],"isCohenMacaulay",1); attrib(SM[2],"isCompleteIntersection",1); attrib(SM[2],"isEquidimensional",1); if(y>=1) { "// the ideal is a complete intersection"; } } if( size(SM[2]) == 1 ) { attrib(SM[2],"isHypersurface",1); if(y>=1) { "// the ideal is a hypersurface"; } } //------------------- compute the singular locus ------------------- // Computation if singular locus is critical // Notation: J ideal of singular locus or (if given) containing it // JM = mstd(J) or maxideal(1),maxideal(1) // JM[1] SB of singular locus, JM[2] minbasis, dimJ = dim(JM[1]) // SM[1] SB of the input ideal i, SM[2] minbasis // Computation if singular locus is critical, because it determines the // size of the ring Hom_R(J,J). We only need a test ideal contained in J. //----------------------- onlySingularAtZero ------------------------- if( attrib(SM[2],"onlySingularAtZero") ) { JM = maxideal(1),maxideal(1); attrib(JM[1],"isSB",1); attrib(JM[2],"isRadical",1); if( dim(SM[1]) >=2 ) { attrib(SM[2],"isRegInCodim2",1); } } //-------------------- not onlySingularAtZero ------------------------- if( attrib(SM[2],"onlySingularAtZero") == 0 ) { //--- the case where an ideal #[1] is given: if( size(#)>0 ) { J = #[1],SM[2]; JM = mstd(J); if( typeof(attrib(#[1],"isRadical"))!="int" ) { attrib(JM[2],"isRadical",0); } } //--- the case where an ideal #[1] is not given: if( (size(#)==0) ) { if(y >=1 ) { "// singular locus will be computed"; } J = SM[1],minor(jacob(SM[2]),nvars(basering)-dim(SM[1]),SM[1]); if( y >=1 ) { "// SB of singular locus will be computed"; } JM = mstd(J); } int dimJ = dim(JM[1]); attrib(JM[1],"isSB",1); if( y>=1 ) { "// the dimension of the singular locus is"; dimJ ; ""; } if(dim(JM[1]) <= dim(SM[1])-2) { attrib(SM[2],"isRegInCodim2",1); } //------------------ the smooth case, RETURN ------------------- if( dimJ == -1 ) { if(y>=1) { "// the ideal is smooth"; } MB=SM[2]; intvec rw; list LL=substpart(MB,ihp,0,rw); def newR3=LL[1]; setring newR3; ideal norid=endid; ideal normap=endphi; kill endid,endphi; export norid; export normap; result=newR3; result[size(result)+1]=list(delt,delti); setring BAS; return(result); } //------- extra check for onlySingularAtZero, relatively cheap ---------- //it uses the procedure 'locAtZero' from for testing //if an ideal is concentrated at 0 if(y>=1) { "// extra test for onlySingularAtZero:"; } if ( locAtZero(JM[1]) ) { attrib(SM[2],"onlySingularAtZero",1); JM = maxideal(1),maxideal(1); attrib(JM[1],"isSB",1); attrib(JM[2],"isRadical",1); } else { attrib(SM[2],"onlySingularAtZero",0); } } //displaying the attributes: if(y>=2) { "// the attributes of the ideal are:"; "// isCohenMacaulay:", attrib(SM[2],"isCohenMacaulay"); "// isCompleteIntersection:", attrib(SM[2],"isCompleteIntersection"); "// isHypersurface:", attrib(SM[2],"isHypersurface"); "// isEquidimensional:", attrib(SM[2],"isEquidimensional"); "// isPrim:", attrib(SM[2],"isPrim"); "// isRegInCodim2:", attrib(SM[2],"isRegInCodim2"); "// isIsolatedSingularity:", attrib(SM[2],"isIsolatedSingularity"); "// onlySingularAtZero:", attrib(SM[2],"onlySingularAtZero"); "// isRad:", attrib(SM[2],"isRad");""; } //------------- case: CohenMacaulay in codim 2, RETURN --------------- if( (attrib(SM[2],"isRegInCodim2")==1) && (attrib(SM[2],"isCohenMacaulay")==1) ) { if(y>=1) { "// the ideal was CohenMacaulay and regular in codim 2, hence normal"; } MB=SM[2]; intvec rw; list LL=substpart(MB,ihp,0,rw); def newR6=LL[1]; setring newR6; ideal norid=endid; ideal normap=endphi; kill endid,endphi; export norid; export normap; result=newR6; result[size(result)+1]=list(delt,delti); setring BAS; return(result); } //---------- case: isolated singularity only at 0, RETURN ------------ // In this case things are easier, we can use the maximal ideal as radical // of the singular locus; // JM mstd of ideal of singular locus, SM mstd of input ideal if( attrib(SM[2],"onlySingularAtZero") ) { //------ check variables for being a non zero-divizor ------ // SL = ideal of vars not contained in ideal SM[1]: attrib(SM[2],"isIsolatedSingularity",1); ideal SL = simplify(reduce(maxideal(1),SM[1]),2); ideal Ann = quotient(SM[2],SL[1]); ideal qAnn = simplify(reduce(Ann,SM[1]),2); //NOTE: qAnn=0 if and only if first var (=SL[1]) not in SM is a nzd of R/SM //------------- We found a non-zerodivisor of R/SM ----------------------- // here the enlarging of the ring via Hom_R(J,J) starts if( size(qAnn)==0 ) { if(y>=1) { ""; "// the ideal rad(J):"; maxideal(1); ""; } // ------------- test for normality, compute Hom_R(J,J) ------------- // Note: // HomJJ (ideal SBid, ideal id, ideal J, poly p) with // SBid = SB of id, J = radical ideal of basering P with: // nonNormal(R) is in V(J), J contains the nonzero divisor p // of R = P/id (J = test ideal) // returns a list l of three objects // l[1] : a polynomial ring, containing two ideals, 'endid' and 'endphi' // s.t. l[1]/endid = Hom_R(J,J) and endphi= map R -> Hom_R(J,J) // l[2] : an integer which is 1 if phi is an isomorphism, 0 if not // l[3] : an integer, = dim_K(Hom_R(J,J)/R) if finite, -1 otherwise list RR; RR = SM[1],SM[2],maxideal(1),SL[1]; RR = HomJJ(RR,y); // --------------------- non-normal case ------------------ //RR[2]==0 means that the test for normality is negative if( RR[2]==0 ) { def newR=RR[1]; setring newR; map psi=BAS,endphi; list JM = psi(JM); //### ideal J = JM[2]; if ( delt>=0 && RR[3]>=0 ) { delt = delt+RR[3]; } else { delt = -1; } delti[size(delti)]=delt; // ---------- recursive call of normalizationPrimes ----------- //normalizationPrimes(ideal i,ideal ihp,int delt,intvec delti,list #) //ihp = (partial) normalisation map from basering //#[1] ideal s.t. V(#[1]) contains singular locus of i (test ideal) if ( y>=1 ) { "// case: onlySingularAtZero, non-zerodivisor found"; "// contribution of delta in ringextension R -> Hom_R(J,J):"; delt; } //intvec atr=getAttrib(endid); //"//### case: isolated singularity only at 0, recursive"; //"size endid:", size(endid), size(string(endid)); //"interred:"; //endid = interred(endid); //endid = setAttrib(endid,atr); //"size endid:", size(endid), size(string(endid)); printlevel=printlevel+1; list tluser = normalizationPrimes(endid,psi(ihp),delt,delti); //list tluser = // normalizationPrimes(endid,psi(ihp),delt,delti,J); //#### ??? improvement: give also the old ideal of sing locus??? printlevel = printlev; //reset printlevel setring BAS; return(tluser); } // ------------------ the normal case, RETURN ----------------- // Now RR[2] must be 1, hence the test for normality was positive MB=SM[2]; def newR7 = ring(gnirlist); setring newR7; ideal norid=fetch(BAS,MB); ideal normap=fetch(BAS,ihp); if ( delt>=0 && RR[3]>=0 ) { delt = delt+RR[3]; } else { delt = -1; } delti[size(delti)]=delt; intvec atr = getAttrib(norid); //"//### case: isolated singularity only at 0, final"; //"size norid:", size(norid), size(string(norid)); //"interred:"; //norid = interred(norid); //norid = setAttrib(norid,atr); //"size norid:", size(norid), size(string(norid)); export norid; export normap; result=newR7; result[size(result)+1]=list(delt,delti); setring BAS; return(result); } //------ zerodivisor of R/SM was found, gives a splitting ------------ //Now the case where qAnn!=0, i.e. SL[1] is a zero divisor of R/SM //and we have found a splitting: id and id1 //id = Ann defines components of R/SM in the complement of V(SL[1]) //id1 defines components of R/SM in the complement of V(id) else { ideal id = Ann; attrib(id,"isCohenMacaulay",0); attrib(id,"isPrim",0); attrib(id,"isIsolatedSingularity",1); attrib(id,"isRegInCodim2",0); attrib(id,"isHypersurface",0); attrib(id,"isCompleteIntersection",0); attrib(id,"isEquidimensional",0); attrib(id,"onlySingularAtZero",1); ideal id1 = quotient(SM[2],Ann); attrib(id1,"isCohenMacaulay",0); attrib(id1,"isPrim",0); attrib(id1,"isIsolatedSingularity",1); attrib(id1,"isRegInCodim2",0); attrib(id1,"isHypersurface",0); attrib(id1,"isCompleteIntersection",0); attrib(id1,"isEquidimensional",0); attrib(id1,"onlySingularAtZero",1); // ---------- recursive call of normalizationPrimes ----------- if ( y>=1 ) { "// case: onlySingularAtZero, zerodivisor found, splitting:"; "// total delta before splitting:", delt; "// splitting in two components:"; } printlevel = printlevel+1; //to see comments in normalizationPrimes keepresult1 = normalizationPrimes(id,ihp,0,0); //1st split factor keepresult2 = normalizationPrimes(id1,ihp,0,0); //2nd split factor printlevel = printlev; //reset printlevel int delt1 = keepresult1[size(keepresult1)][1]; int delt2 = keepresult2[size(keepresult2)][1]; intvec delti1 = keepresult1[size(keepresult1)][2]; intvec delti2 = keepresult2[size(keepresult2)][2]; if( delt>=0 && delt1>=0 && delt2>=0 ) { ideal idid1=id,id1; int mul = vdim(std(idid1)); if ( mul>=0 ) { delt = delt+mul+delt1+delt2; } else { delt = -1; } } if ( y>=1 ) { "// delta of first component:", delt1; "// delta of second componenet:", delt2; "// intersection multiplicity of both components:", mul; "// total delta after splitting:", delt; } else { delt = -1; } for(lauf=1;lauf<=size(keepresult2)-1;lauf++) { keepresult1=insert(keepresult1,keepresult2[lauf]); } keepresult1[size(keepresult1)]=list(delt,delti); return(keepresult1); } } // Case "onlySingularAtZero" has finished and returned result //-------------- General case, not onlySingularAtZero, RETURN --------------- //test for non-normality, i.e. if Hom(I,I)<>R //we can use Hom(I,I) to continue //------ check variables for being a non zero-divizor ------ // SL = ideal of vars not contained in ideal SM[1]: ideal SL = simplify(reduce(JM[2],SM[1]),2); ideal Ann = quotient(SM[2],SL[1]); ideal qAnn = simplify(reduce(Ann,SM[1]),2); //NOTE: qAnn=0 <==> first var (=SL[1]) not contained in SM is a nzd of R/SM //------------- We found a non-zerodivisor of R/SM ----------------------- //SM = mstd of ideal of variety, JM = mstd of ideal of singular locus if( size(qAnn)==0 ) { list RR; list RS; // ----------------- Computation of the radical ----------------- if(y>=1) { "// radical computation of singular locus"; } J = radical(JM[2]); //the radical of singular locus JM = mstd(J); if(y>=1) { "// radical is equal to:";""; JM[2]; ""; } // ------------ choose non-zerodivisor of smaller degree ---------- //### evtl. fuer SL[1] anderen Nichtnullteiler aus J waehlen ? if( deg(SL[1]) > deg(J[1]) ) { Ann=quotient(SM[2],J[1]); qAnn=simplify(reduce(Ann,SM[1]),2); if(size(qAnn)==0) { SL[1]=J[1]; } } // --------------- computation of Hom(rad(J),rad(J)) -------------- RR=SM[1],SM[2],JM[2],SL[1]; if(y>=1) { "// compute Hom(rad(J),rad(J))"; } RS=HomJJ(RR,y); //most important subprocedure // ------------------ the normal case, RETURN ----------------- // RS[2]==1 means that the test for normality was positive if(RS[2]==1) { def lastR=RS[1]; setring lastR; map psi1=BAS,endphi; ideal norid=endid; ideal normap=psi1(ihp); kill endid,endphi; intvec atr=getAttrib(norid); //"//### general case: not isolated singularity only at 0, final"; //"size norid:", size(norid), size(string(norid)); //"interred:"; //norid = interred(norid); //norid = setAttrib(norid,atr); //"size norid:", size(norid), size(string(norid)); export norid; export normap; result=lastR; if ( y>=1 ) { "// case: not onlySingularAtZero, last ring Hom_R(J,J) computed"; "// delta before last ring:", delt; } if ( delt>=0 && RS[3]>=0 ) { delt = delt+RS[3]; } else { delt = -1; } // delti = delti,delt; delti[size(delti)]=delt; if ( y>=1 ) { "// delta of last ring:", delt; } result[size(result)+1]=list(delt,delti); setring BAS; return(result); } // ----- the non-normal case, recursive call of normalizationPrimes ------- // RS=HomJJ(RR,y) was computed above, RS[1] contains endid and endphi // RS[1] = new ring Hom_R(J,J), RS[2]= 0 or 1, RS[2]=contribution to delta // now RS[2]must be 0, i.e. the test for normality was negative int n = nvars(basering); ideal MJ = JM[2]; def newR=RS[1]; setring newR; map psi=BAS,endphi; if ( y>=1 ) { "// case: not onlySingularAtZero, compute new ring = Hom_R(J,J)"; "// delta of old ring:", delt; } if ( delt>=0 && RS[3]>=0 ) { delt = delt+RS[3]; } else { delt = -1; } if ( y>=1 ) { "// delta of new ring:", delt; } delti[size(delti)]=delt; intvec atr=getAttrib(endid); //"//### general case: not isolated singularity only at 0, recursive"; //"size endid:", size(endid), size(string(endid)); //"interred:"; //endid = interred(endid); //endid = setAttrib(endid,atr); //"size endid:", size(endid), size(string(endid)); printlevel = printlevel+1; list tluser= normalizationPrimes(endid,psi(ihp),delt,delti,psi(MJ)); printlevel = printlev; //reset printlevel setring BAS; return(tluser); } //---- A whole singular component was found, RETURN ----- if( Ann == 1) { "// Input appeared not to be a radical ideal!"; "// A (everywhere singular) component with ideal"; "// equal to its Jacobian ideal was found"; "// Procedure will stop with partial result computed so far";""; MB=SM[2]; intvec rw; list LL=substpart(MB,ihp,0,rw); def newR6=LL[1]; setring newR6; ideal norid=endid; ideal normap=endphi; kill endid,endphi; export norid; export normap; result=newR6; result[size(result)+1]=lst(delt,delti); setring BAS; return(result); } //------ zerodivisor of R/SM was found, gives a splitting ------------ //Now the case where qAnn!=0, i.e. SL[1] is a zero divisor of R/SM //and we have found a splitting: new1 and new2 //id = Ann defines components of R/SM in the complement of V(SL[1]) //id1 defines components of R/SM in the complement of V(id) else { if(y>=1) { "// zero-divisor found"; } int equi = attrib(SM[2],"isEquidimensional"); int oSAZ = attrib(SM[2],"onlySingularAtZero"); int isIs = attrib(SM[2],"isIsolatedSingularity"); ideal new1 = Ann; ideal new2 = quotient(SM[2],Ann); //ideal new2=SL[1],SM[2]; def newR1 = ring(gnirlist); setring newR1; ideal vid = fetch(BAS,new1); ideal ihp = fetch(BAS,ihp); attrib(vid,"isCohenMacaulay",0); attrib(vid,"isPrim",0); attrib(vid,"isIsolatedSingularity",isIs); attrib(vid,"isRegInCodim2",0); attrib(vid,"onlySingularAtZero",oSAZ); attrib(vid,"isEquidimensional",equi); attrib(vid,"isHypersurface",0); attrib(vid,"isCompleteIntersection",0); // ---------- recursive call of normalizationPrimes ----------- if ( y>=1 ) { "// total delta before splitting:", delt; "// splitting in two components:"; } printlevel = printlevel+1; keepresult1 = normalizationPrimes(vid,ihp,0,0); //1st split factor list delta1 = keepresult1[size(keepresult1)]; setring BAS; def newR2 = ring(gnirlist); setring newR2; ideal vid = fetch(BAS,new2); ideal ihp = fetch(BAS,ihp); attrib(vid,"isCohenMacaulay",0); attrib(vid,"isPrim",0); attrib(vid,"isIsolatedSingularity",isIs); attrib(vid,"isRegInCodim2",0); attrib(vid,"isEquidimensional",equi); attrib(vid,"isHypersurface",0); attrib(vid,"isCompleteIntersection",0); attrib(vid,"onlySingularAtZero",oSAZ); keepresult2 = normalizationPrimes(vid,ihp,0,0); list delta2 = keepresult2[size(keepresult2)]; //2nd split factor printlevel = printlev; //reset printlevel setring BAS; //compute intersection multiplicity of both components: new1 = new1,new2; int mul=vdim(std(new1)); // ----- normalizationPrimes finished, add up results, RETURN -------- for(lauf=1;lauf<=size(keepresult2)-1;lauf++) { keepresult1 = insert(keepresult1,keepresult2[lauf]); } if ( delt >=0 && delta1[1] >=0 && delta2[1] >=0 && mul >=0 ) { delt = delt+mul+delta1[1]+delta2[1]; } else { delt = -1; } delti = -2; if ( y>=1 ) { "// zero divisor produced a splitting into two components"; "// delta of first component:", delta1; "// delta of second componenet:", delta2; "// intersection multiplicity of both components:", mul; "// total delta after splitting:", delt; } keepresult1[size(keepresult1)] = list(delt,delti); return(keepresult1); } } example { "EXAMPLE:";echo = 2; // Huneke ring qr=31991,(a,b,c,d,e),dp; ideal i= 5abcde-a5-b5-c5-d5-e5, ab3c+bc3d+a3be+cd3e+ade3, a2bc2+b2cd2+a2d2e+ab2e2+c2de2, abc5-b4c2d-2a2b2cde+ac3d2e-a4de2+bcd2e3+abe5, ab2c4-b5cd-a2b3de+2abc2d2e+ad4e2-a2bce3-cde5, a3b2cd-bc2d4+ab2c3e-b5de-d6e+3abcd2e2-a2be4-de6, a4b2c-abc2d3-ab5e-b3c2de-ad5e+2a2bcde2+cd2e4, b6c+bc6+a2b4e-3ab2c2de+c4d2e-a3cde2-abd3e2+bce5; list pr=normalizationPrimes(i); def r1 = pr[1]; setring r1; norid; normap; } /////////////////////////////////////////////////////////////////////////////// static proc substpart(ideal endid, ideal endphi, int homo, intvec rw) "//Repeated application of elimpart to endid, until no variables can be //directy substituded. homo=1 if input is homogeneous, rw contains //original weights, endphi (partial) normalization map"; //NOTE concerning iteration of maps: Let phi: x->f(y,z), y->g(x,z) then //phi: x+y+z->f(y,z)+g(x,z)+z, phi(phi):x+y+z->f(g(x,z),z)+g(f(y,z),z)+z //and so on: none of the x or y will be eliminated //Now subst: first x and then y: x+y+z->f(g(x,z),z)+g(x,z)+z eliminates y //further subst replaces x by y, makes no sense (objects more compicated). //Subst first y and then x eliminates x //In our situation we have triangular form: x->f(y,z), y->g(z). //phi: x+y+z->f(y,z)+g(z)+z, phi(phi):x+y+z->f(g(z),z)+g(z)+z eliminates x,y //subst x,y: x+y+z->f(g(z),z)+g(z)+z, eliminates x,y //subst y,x: x+y+z->f(y,z)+g(z)+z eliminates only x //HENCE: substitute vars depending on most other vars first //However, if the sytem xi-fi is reduced then xi does not appear in any of the //fj and hence the order does'nt matter when substitutinp xi by fi { ASSUME(1, not isQuotientRing(basering) ); def newRing = basering; int ii,jj; map phi = newRing,maxideal(1); //identity map list Le = elimpart(endid); //this proc and the next loop try to substitute as many variables as //possible indices of substituted variables int q = size(Le[2]); //q vars, stored in Le[2], have been substitutet intvec rw1 = 0; //will become indices of substituted variables rw1[nvars(basering)] = 0; rw1 = rw1+1; //rw1=1,..,1 (as many 1 as nvars(basering)) while( size(Le[2]) != 0 ) { endid = Le[1]; if ( defined(ps) ) { kill ps; } map ps = newRing,Le[5]; phi = ps(phi); for(ii=1;ii<=size(Le[2]);ii++) { phi=phi(phi); } //eingefuegt wegen x2-y2z2+z3 for( ii=1; ii<=size(rw1); ii++ ) { if( Le[4][ii]==0 ) //ii = index of var which was substituted { rw1[ii]=0; //substituted vars have entry 0 in rw1 } } Le=elimpart(endid); //repeated application of elimpart q = q + size(Le[2]); } endphi = phi(endphi); //---------- return ----------------------------------------------------------- // first the trivial case, where all variable have been eliminated if( nvars(newRing) == q ) { ring lastRing = char(basering),T(1),dp; ideal endid = T(1); ideal endphi = T(1); for(ii=2; ii<=q; ii++ ) { endphi[ii] = 0; } export(endid,endphi); list L = lastRing; setring newRing; return(L); } // in the homogeneous case put weights for the remaining vars correctly, i.e. // delete from rw those weights for which the corresponding entry of rw1 is 0 if (homo==1 && nvars(newRing)-q >1 && size(endid) >0 ) { jj=1; for( ii=2; ii1){ERROR("no hypersurface");} ideal J=std(slocus(I)); if(dim(J)<=0){return(0);} poly h; d=1; while((d)&&(i10){ERROR("delta not found, please inform the authors")}; h=randomLast(100)[n]; d=dim(std(J+ideal(h))); } I=I,h-1; if(char(R)<=19) { nor=normalP(I); } else { nor=normal(I); } return(nor[2][2]); } proc genus(ideal I,list #) "USAGE: genus(I) or genus(I,

, p prime I=std(I); ideal IC=simplify(flatten(lead(I)),2); list C; int i; for(i=1;i<=size(IC);i++) { C[i]=I[i]; } list rl=ringlist(R); rl[1]=0; def Shelp =ring(rl); } for(i=1;i<=size(C);i++) { if(deg(C[i])>0){h=h*C[i];} // das muss noch besser gemacht werden, // nicht ausmultiplizieren! } setring Shelp; poly h=imap(R,h); ideal fac=factorize(h,1); setring R; list II; h=1; ideal fac=imap(Shelp,fac); ASSUME(1, size(fac)==ncols(fac) || size(fac)==0); for(i=1;i<=size(fac);i++) { II=sat(I,fac[i]); I=II[1]; h=h*fac[i]^II[2]; } } I=std(I); return(list(I,h)); } proc primdecZM(module N) "USAGE: primdecZM(N); N module RETURN: a list pr of primary modules and their associated primes: @format pr[i][1] the i-th primary component, pr[i][2] the i-th prime component. @end format EXAMPLE: example primdecZM; shows an example " { list P,K,S; int i,j; list L=pseudo_primdecZM(N); list M,O; for(i=1;i<=size(L);i++) { if(size(L[i][2])!=0) { M=prepare_extractZM(L[i]); O=extractZM(L[i],M); P[size(P)+1]=list(O[1],L[i][2]); K[size(K)+1]=L[i][1]+O[2]*freemodule(nrows(L[i][1])); } else { P[size(P)+1]=L[i]; } } for(j=1;j<=size(K);j++) { S=primdecZM(K[j]); for(i=1;i<=size(S);i++) { P[size(P)+1]=S[i]; } } return(P); } example { "EXAMPLE:"; echo = 2; ring R=integer,(x,y),(c,lp); module N=[0,0,xy2-x2-xy],[0,y,x],[0,x,2xy-x],[x,0,-xy],[0,0,18x]; primdecZM(N); } //////////////////////////////////////////////////////////////////////////////// /* Examples: //=== IQ[a,b,c,d,e,f,g] intersect Z[a,b,c,d,e,f,g] = I (takes some time) ring R1=integer,(a,b,c,d,e,f,g),dp; ideal I=a2+2de+2cf+2bg+a, 2ab+e2+2df+2cg+b, b2+2ac+2ef+2dg+c, 2bc+2ad+f2+2eg+d, c2+2bd+2ae+2fg+e, 2cd+2be+2af+g2+f, d2+2ce+2bf+2ag+g; ring R2=integer,(a,b,c,d,e,f,g),dp; ideal I=181*32003, a2+2de+2cf+2bg+a, 2ab+e2+2df+2cg+b, b2+2ac+2ef+2dg+c, 2bc+2ad+f2+2eg+d, c2+2bd+2ae+2fg+e, 2cd+2be+2af+g2+f, d2+2ce+2bf+2ag+g; ring R3=integer,(w,z,y,x),dp; ideal I=xzw+(-y^2+y)*z^2, (-x^2+x)*w^2+yzw, ((y^4-2*y^3+y^2)*x-y^4+y^3)*z^3, y2z2w+(-y*4+2*y^3-y^2)*z3; ring R4=integer,(w,z,y,x),dp; ideal I=-2*yxzw+(-yx-y^2+y)*z^2, xw^2-yz^2, (yx^2-(2*y^2+2*y)*x+y^3-2*y^2+y)*z^3, (-2*y^2+2*y)*z^2*w+(yx-3*y^2-y)*z^3; ring R5=integer,(x,y,z),dp; ideal I=x2-y2-z2, xy-z2, y3+xz2-yz2+2z3+xy-z2, -y2z2+2z4+x2-y2+z2, y3z9+3y2z10+3yz11+z12-y2z2+2z4; ring R6=integer,(h, l, s, x, y, z),dp; //takes some time ideal I=hl-l2-4ls+hy, h2s-6ls3+h2z, xh2-l2s-h3; ring R7=integer,(x,y,z),dp; ideal I=x2-y2-(z+2)^2, xy-(z+2)^2, y3+x*(z+2)^2-y*(z+2)^2+2*(z+2)^3+xy-(z+2)^2, -y^2*(z+2)^2+2*(z+2)^4+x2-y2+(z+2)^2, y3z9+3y2z10+3yz11+z12-y2z2+2z4; ring R8=integer,(x,y,z),dp; ideal I=x2-y2-(z+2)^2, xy-(z+2)^2, y3+x*(z+2)^2-y*(z+2)^2+2*(z+2)^3+xy-(z+2)^2, -y^2*(z+2)^2+2*(z+2)^4+x2-y2+(z+2)^2, y3z9+3y2z10+3yz11+z12-y2z2+2z4; ring R9=integer,(w,z,y,x),dp; ideal I=630, ((y^2-y)*x-y^3+y^2)*z^2, (x-y)*zw, (x-y^2)*zw+(-y^2+y)*z^2, (-x^2+x)*w^2+(-yx+y)*zw; ring R10=integer,(w,z,y,x),dp; ideal I=1260, -yxzw+(-y^2+y)*z^2, (-x^2+x)*w^2-yxzw, ((-y^2+y)*x-y^3+2*y^2-y)*z^3, (y^2-y)*z^2*w+(-y^2+y)*z^2*w+(-y^2+y)*z^3; ring R11=integer,(w,z,y,x),dp; ideal I=(4*y^2*x^2+(4*y^3+4*y^2-y)*x-y^2-y)*z^2, (x+y+1)*zw+(-4*y^2*x-4*y^3-4*y^2)*z^2, (-x-2*y^2 - 2*y - 1)*zw + (8*y^3*x + 8*y^4 + 8*y^3 + 2*y^2+y)*z^2, ((y^3 + y^2)*x - y^2 - y)*z^2, (y +1)*zw + (-y^3 -y^2)*z^2, (x + 1)*zw +(- y^2 -y)*z^2, (x^2 +x)*w^2 + (-yx - y)*zw; ring R12=integer,(w,z,y,x),dp; ideal I=72, ((y^3 + y^2)*x - y^2 - y)*z^2, (y + 1)*zw + (-y^3 -y^2)*z^2, (x + 1)*zw + (-y^2 -y)*z^2, (x^2 + x)*w^2 + (-yx - y)*zw; ring R13=integer,(w,z,y,x),dp; ideal I=(((12*y+8)*x^2 +(2*y+2)*x)*zw +((-15*y^2 -4*y)*x-4*y^2 -y)*z^2, -x*w^2 +((-12*y -8)*x+2*y)*zw +(15*y^2+4*y)*z^2, (81*y^4*x^2 +(-54*y^3 -12*y^2)*x-12*y^3 -3*y^2)*z^3, (-24*yx+6*y^2-6*y)*z^2*w + (-81*y^4*x + 81*y^3 + 24*y^2)*z^3, (48*x^2 + (-30*y + 12)*x - 6*y)*z^2*w + ((81*y^3 -54*y^2 -24*y)*x -21*y^2 -6*y)*z^3, (-96*yx-18*y^3 +18*y^2-24*y)*z^2*w +(243*y^5*x-243*y^4 +72*y^3 +48*y^2)*z^3, 6*y*z^2*w^2 +((576*y+384)*x^2 + (-81*y^3 -306*y^2 -168*y+96)*x+81*y^2 -18*y)*z^3*w +((-720*y^2 - 192*y)*x + 450*y^3 - 60*y^2 - 48*y)*z^4); ring R14=integer,(x(1),x(2),x(3),x(4)),dp; ideal I=181*49^2, x(4)^4, x(1)*x(4)^3, x(1)*x(2)*x(4)^2, x(2)^2*x(4)^2, x(2)^2*x(3)*x(4), x(1)*x(2)*x(3)*x(4), x(1)*x(3)^2*x(4), x(3)^3*x(4); ring R15=integer,(x,y,z),dp; ideal I=32003*181*64, ((z^2-z)*y^2 + (z^2 -z)*y)*x; (z*y^3 + z*y^2)*x, (y^4 - y^2)*x, (z^2 - z)*y*x^2, (y^3 - y^2)*x^2, (z^3 - z^2)*x^4 + (2*z^3 -2*z^2)*x^3 + (z^3 -z^2)*x^2, z*y^2*x^2, z*y*x^4 +z*y*x^3, 2*y^2*x^4 +6*y^2*x^3 +6*y^2*x^2 + (y^3 +y^2)*x, z*x^5 + (z^2 +z)*x^4 + (2*z^2 -z)*x^3 + (z^2 -z)*x^2, y*x^6 + 3*y*x^5 + 3*y*x^4 + y*x^3; ring R16=integer,(x(1),x(2),x(3),x(4),x(5)),dp; ideal I=x(5)^5, x(1)*x(5)^4, x(1)*x(2)*x(5)^3, x(2)^2*x(5)^3, x(2)^2*x(3)*x(5)^2, x(1)*x(2)*x(3)*x(5)^2, x(1)*x(3)^2*x(5)^2, x(3)^3*x(5)^2, x(3)^3*x(4)*x(5), x(1)*x(3)^2*x(4)*x(5), x(1)*x(2)*x(3)*x(4)*x(5), x(2)^2*x(3)*x(4)*x(5), x(2)^2*x(4)^2*x(5), x(1)*x(2)*x(4)^2*x(5), x(1)*x(4)^3*x(5), x(4)^4*x(5); I=intersectZ(I,ideal(64*181,x(1)^2)); ring R17=integer,(x,y,z),dp; ideal I=374, (z+2)^8-140z6+2622*(z+2)^4-1820*(z+2)^2+169, 17y*(z+2)^4-374*y*(z+2)^2+221y+2z7-281z5+5240z3-3081z, 204y2+136yz3-3128yz+z6-149z4+2739z2+117, 17xz4-374xz2+221x+2z7-281z5+5240z3-3081z, 136xy-136xz-136yz+2z6-281z4+5376z2-3081, 204x2+136xz3-3128xz+z6-149z4+2739z2+117; ring R18=integer,(B,D,F,b,d,f),dp; ideal I=6, (b-d)*(B-D)-2*F+2, (b-d)*(B+D-2*F)+2*(B-D), (b-d)^2-2*(b+d)+f+1, B^2*b^3-1, D^2*d^3-1, F^2*f^3-1; ring R19=integer,(a,b,c,d,e,f),dp; ideal I=24, 2*(f+2)*b+2ec+d2+a2+a, 2*(f+2)*c+2ed+2ba+b, 2*(f+2)*d+e2+2ca+c+b2, 2*(f+2)*e+2da+d+2cb, (f+2)^2+2ea+e+2db+c2, 2*(f+2)*a+f+2eb+2dc; ring R20=integer,(x,y,z,w,u),dp; ideal I=24, 2x2-2y2+2z2-2w2+2u2-1, 2x3-2y3+2z3-2w3+2u3-1, 2x4-2y4+2z4-2w4+2u4-1, 2x5-2y5+2z5-2w5+2u5-1, 2x6-2y6+2z6-2w6+2u6-1; ring R21=integer,(x,y,z,t,u,v,h),dp; ideal I=66, 2x2+2y2+2z2+2t2+2u2+v2-vh, xy+yz+2zt+2tu+2uv-uh, 2xz+2yt+2zu+u2+2tv-th, 2xt+2yu+2tu+2zv-zh, t2+2xv+2yv+2zv-yh, 2x+2y+2z+2t+2u+v-h, x3+y3+z3+t3+u3+v3; ring R22=integer,(s,p,S,P,T,F,f),dp; ideal I=35, 2*T-S*s-2*F+2, 8*F*p-4*p*S-2*F*s^2+S*s^2+4*T-2*S*s, -2*s-4*p+s^2+f+1, s*T^2-p*s*P-p*S*T-2, p^3*P^2-1, F^2*f^3-1; ring R=integer,(x,y),(c,lp); module N=[0,0,xy2-x2-xy],[0,y,x],[0,x,2xy-x],[x,0,-xy],[0,0,18x]; ring R=integer,(x,y),(c,lp); module N=[0,0,xy2-x2-xy],[0,y,x],[0,x,2xy-x],[x,0,-xy],[0,0,18]; ring R=integer,(x,y),(c,lp); module N=[-y,7,0],[2y3-y2],[3x,y2],[2y-y2,x],[4,5x3]; ring r=integer,(x,y),(c,lp); module N=[0,0,xy2-x2-xy],[0,y,x],[0,x,xy-x],[x,0,-xy],[5x,0,0]; ring R2=integer,(a(1),a(2),a(3),b(1),b(2),b(3)),(c,lp); module N=[a(1)*b(1),a(2)*b(1),a(3)*b(1)],[a(1)*b(2),a(2)*b(2),a(3)*b(2)],[a(1)*b(3),a(2)*b(3),a(3)*b(3)]; ring R3=integer,(x,y,z),(c,lp); module N=[y2+z2,xy,xz],[xy,x2+z2,yz],[xz,yz,x2+y2]; ring R4=integer,(x,y,z,a,b,c),(c,lp); module N=[x3y2z2c,x2y3z2c,x2y2z3c],[x3y2z2b,x2y3z2b,x2y2z3b],[x3y2z2a,x2y3z2a,x2y2z3a]; */ singular-4.0.3+ds/Singular/LIB/primitiv.lib000066400000000000000000000340371266270727000205110ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version primitiv.lib 4.0.0.0 Jun_2013 "; // $Id: e55b398883c429e476b0c6a8e56119ffb792643a $ category="Commutative Algebra"; info=" LIBRARY: primitiv.lib Computing a Primitive Element AUTHOR: Martin Lamm, email: lamm@mathematik.uni-kl.de PROCEDURES: primitive(ideal i); find minimal polynomial for a primitive element primitive_extra(i); find primitive element for two generators splitring(f,R[,L]); define ring extension with name R and switch to it "; LIB "random.lib"; /////////////////////////////////////////////////////////////////////////////// proc primitive(ideal i) "USAGE: primitive(i); i ideal ASSUME: i is given by generators m[1],...,m[n] such that for j=1,...,n @* - m[j] is a polynomial in k[x(1),...,x(j)] @* - m[j](a[1],...,a[j-1],x(j)) is the minimal polynomial for a[j] over k(a[1],...,a[j-1]) @* (k the ground field of the current basering and x(1),...,x(n) the ring variables). RETURN: ideal j in k[x(n)] with - j[1] a minimal polynomial for a primitive element b of k(a[1],...,a[n]) over k, - j[2],...,j[n+1] polynomials in k[x(n)] such that j[i+1](b)=a[i] for i=1,...,n. NOTE: the number of variables in the basering has to be exactly n, the number of given generators (i.e., minimal polynomials).@* If the ground field k has only a few elements it may happen that no linear combination of a[1],...,a[n] is a primitive element. In this case @code{primitive(i)} returns the zero ideal, and one should use @code{primitive_extra(i)} instead. SEE ALSO: primitive_extra KEYWORDS: primitive element EXAMPLE: example primitive; shows an example " { def altring=basering; execute("ring deglexring=("+charstr(altring)+"),("+varstr(altring)+"),dp;"); ideal j; execute("ring lexring=("+charstr(altring)+"),("+varstr(altring)+"),lp;"); ideal i=fetch(altring,i); int k,schlecht,Fehlversuche,maxtry; int nva = nvars(basering); int p=char(basering); if (p==0) { p=100000; if (nva<3) { maxtry= 100000000; } else { maxtry=2147483647; } } else { if ((nva<4) || (p<60)) { maxtry=p^(nva-1); } else { maxtry=2147483647; // int overflow(^) vermeiden } } ideal jmap,j; map phi; option(redSB); //-------- Mache so lange Random-Koord.wechsel, bis letztes Polynom ------------- //--------------- das Minpoly eines primitiven Elements ist : ---------------- for (Fehlversuche=0; Fehlversuche2) { ERROR("i[2] must be poly in x,a"); } //if (variables(i[2])[2]!=a) { ERROR("i[2] must be poly in x,a"); } ring deglexring=char(altring),(x,y,z),dp; map transfer=altring,x,z; ideal i=transfer(i); if (size(i)!=2) { ERROR("either wrong number of given minimal polynomials"+newline+ "or wrong choice of ring variables (must use the first two)"); } matrix mat; ring lexring=char(altring),(x,y),lp; ideal j; ring deglex2ring=char(altring),(x,y),dp; ideal j; setring deglexring; ideal j; option(redSB); poly g=z; int found=0; //---------------- Schleife zum Finden des primitiven Elements --------------- //--- Schleife ist so angordnet, dass g in Charakteristik 0 linear bleibt ---- while (found==0) { j=eliminate(i+ideal(g-y),z); setring deglex2ring; j=std(imap(deglexring,j)); setring lexring; j=fglm(deglex2ring,j); if (size(j)==2) { if (deg(j[1])==grad1*grad2) { j[2]=j[2]/leadcoef(j[2]); // Normierung if (lead(j[2])==x) { // Alles ok found=1; } } } setring deglexring; if (found==0) { //------------------ waehle ein neues Polynom g ------------------------------ dbprint("Still searching for primitive element..."); countx=0; countz=0; while (found==0) { countx++; if (countx>=grad1) { countx=0; countz++; if (countz>=grad2) { ERROR("No primitive element found!! This should NEVER happen!"); } } g = g +x^countx *z^countz; mat=coeffs(g,z); if (size(mat)>countz) { mat=coeffs(mat[countz+1,1],x); if (size(mat)>countx) { if (mat[countx+1,1] != 0) { found=1; // d.h. hier: neues g gefunden }}} } found=0; } } //------------------- primitives Element gefunden; Rueckgabe ----------------- setring lexring; j[2]=x-j[2]; setring altring; map transfer=lexring,var(1),var(2); return(transfer(j)); } example { "EXAMPLE:"; echo = 2; ring exring=3,(x,y),dp; ideal i=x2+1,y3+y2-1; primitive_extra(i); ring extension=(3,y),x,dp; minpoly=y6-y5+y4-y3-y-1; number a=y5+y4+y2+y+1; a^2; factorize(x2+1); factorize(x3+x2-1); } /////////////////////////////////////////////////////////////////////////////// proc splitring(poly f,list #) "USAGE: splitring(f[,L]); f poly, L list of polys and/or ideals (optional) ASSUME: f is univariate and irreducible over the active ring. @* The active ring must allow an algebraic extension (e.g., it cannot be a transcendent ring extension of Q or Z/p). RETURN: ring; @* if called with a nonempty second parameter L, then in the output ring there is defined a list erg ( =L mapped to the new ring); if the minpoly of the active ring is non-zero, then the image of the primitive root of f in the output ring is appended as last entry of the list erg. NOTE: If the old ring has no parameter, the name @code{a} is chosen for the parameter of R (if @code{a} is no ring variable; if it is, @code{b} is chosen, etc.; if @code{a,b,c,o} are ring variables, @code{splitring(f[,L])} produces an error message), otherwise the name of the parameter is kept and only the minimal polynomial is changed. @* The names of the ring variables and the orderings are not affected. @* KEYWORDS: algebraic field extension; extension of rings EXAMPLE: example splitring; shows an example " { //----------------- split ist bereits eine proc in 'inout.lib' ! ------------- if (size(#)>=1) { list L=#; int L_groesse=size(L); } else { int L_groesse=-1; } //-------------- ermittle das Minimalpolynom des aktuellen Rings: ------------ string minp=string(minpoly); def altring=basering; string charakt=string(char(altring)); string varnames=varstr(altring); string algname; int i; int anzvar=size(maxideal(1)); //--------------- Fall 1: Bisheriger Ring hatte kein Minimalpolynom ---------- if (minp=="0") { // only possible without parameters (by assumption) if (find(varnames,"a")==0) { algname="a";} else { if (find(varnames,"b")==0) { algname="b";} else { if (find(varnames,"c")==0) { algname="c";} else { if (find(varnames,"o")==0) { algname="o";} else { "** Sorry -- could not find a free name for the primitive element."; "** Try e.g. a ring without 'a' or 'b' as variable."; return(); }} } } //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: - execute("ring splt1="+charakt+","+algname+",dp;"); ideal abbnach=var(1); for (i=1; i0) { list erg; map take=altring,maxideal(1); erg=take(L); } } else { //------------- Fall 2: Bisheriger Ring hatte ein Minimalpolynom: ----------- algname=parstr(altring); // Name des algebraischen Elements if (npars(altring)>1) {"only one Parameter is allowed!!"; return(altring);} //---------------- Minimalpolynom in ein Polynom umwandeln: ----------------- execute("ring splt2="+charakt+","+algname+",dp;"); execute("poly mipol="+minp+";"); // f ist Polynom in algname und einer weiteren Variablen -> mache f bivariat: execute("ring splt3="+charakt+",("+algname+","+varnames+"),dp;"); poly f=imap(altring,f); //-------------- Vorbereitung des Aufrufes von primitive: ------------------- execute("ring splt1="+charakt+",(x,y),dp;"); ideal abbnach=x; for (i=1; i<=anzvar; i++) { abbnach=abbnach,y; } map nach_splt1_3=splt3,abbnach; map nach_splt1_2=splt2,x; ideal maxid=nach_splt1_2(mipol),nach_splt1_3(f); ideal primit=primitive(maxid); if (size(primit)==0) { // Suche mit 1. Proc erfolglos primit=primitive_extra(maxid); } //-- erzeuge einen String, der das Minimalpolynom des neuen Rings enthaelt: - setring splt2; map nach_splt2=splt1,0,var(1); // x->0, y->a minp=string(nach_splt2(primit)[1]); if (printlevel > -1) { "// new minimal polynomial:",minp; } //--------------------- definiere den neuen Ring: --------------------------- execute("ring neuring = ("+charakt+","+algname+"),("+varnames+"),(" +ordstr(altring)+");"); execute("minpoly="+minp+";"); if (L_groesse>0) { //---------------------- Berechne die zurueckzugebende Liste: ------------- list erg; setring splt3; list zwi=imap(altring,L); map nach_splt3_1=splt1,0,var(1); // x->0, y->a //----- rechne das primitive Element von altring in das von neuring um: --- ideal convid=maxideal(1); convid[1]=nach_splt3_1(primit)[2]; poly new_b=nach_splt3_1(primit)[3]; map convert=splt3,convid; zwi=convert(zwi); setring neuring; erg=imap(splt3,zwi); erg[size(erg)+1]=imap(splt3,new_b); } } if (defined(erg)){export erg;} return(neuring); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),dp; def r1=splitring(x2-2); setring r1; basering; // change to Q(sqrt(2)) // change to Q(sqrt(2),sqrt(sqrt(2)))=Q(a) and return the transformed // old parameter: def r2=splitring(x2-a,a); setring r2; basering; erg; // the result is (a)^2 = (sqrt(sqrt(2)))^2 kill r1; kill r2; } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/purityfiltration.lib000066400000000000000000000603421266270727000222740ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////// //procedures examples comments version="version purityfiltration.lib 4.0.0.0 Jun_2013 "; // $Id: d6b6e3acf8119392f5ff8e096b32f5f1a647e0f4 $ category="Noncommutative"; info=" LIBRARY: purityfiltration.lib Algorithms for computing a purity filtration of a given module AUTHORS: Christian Schilli, christian.schilli@rwth-aachen.de @* Viktor Levandovskyy, levandov@math.rwth-aachen.de OVERVIEW: Purity is a notion with several meanings. In our context it is equidimensionality @* of a module (that is all M is pure iff any nonzero submodule of N has the same dimension as N). @* Notably, one should define purity with respect to a given dimension function. In the context @* of this library the corresponding function is the homological grade number j_A(M) of a module M over @* an K-algebra A. j_A(M) is the minimal integer k, such that Ext^k_A(M,A) != 0. REFERENCES: [AQ] Alban Quadrat: Grade filtration of linear functional systems, INRIA Report 7769 (2010), to appear in Acta Applicanda Mathematica. @* [B93] Jan-Erik Bjoerk: Analytic D-modules and applications, Kluwer Acad. Publ., 1993. @* [MB10] Mohamed Barakat: Purity Filtration and the Fine Structure of Autonomy. Proc. MTNS, 2010. PROCEDURES: projectiveDimension(matrix T,int i); compute a shortest resolution of coker(T) and its projective dimension purityFiltration(matrix R); compute the purity filtration of coker(R) purityTriang(matrix R) compute a triangular blockmatrix T, such that coker(R) isomorphic to coker(T) gradeNumber(matrix R); gives the grade number of the module coker(R) showgrades(list T); gives all grade numbers of the modules represented by the elements of T allExtOfLeft(matrix R); computes all right ext-modules ext^i(M,D) of a left module M=coker(R) over the ring D allExtOfRight(matrix R); computes all left ext-modules ext^i(M,D) of a right module M=coker(R) over the ring D doubleExt(matrix R, int i); computes the left module ext^i(ext^i(M,D),D) over the ring D, M=coker(R) allDoubleExt(matrix R); computes all double ext modules ext^i(ext^j(M,D),D) of the left module coker(R) over the ring D is_pure(matrix R); checks whether the module coker(R) is pure purelist(list T); checks whether all the modules represented by the elements of T are pure KEYWORDS: D-module; ext-module; filtration; projective dimension; resolution; purity "; LIB "nctools.lib"; LIB "matrix.lib"; LIB "poly.lib"; LIB "general.lib"; LIB "control.lib"; LIB "nchomolog.lib"; //------------------- auxiliary procedures -------------------------- proc testPurityfiltrationLib() { example projectiveDimension; example purityFiltration; example purityTriang; example gradeNumber; example showgrades; example allExtOfLeft; example allExtOfRight; example doubleExt; example allDoubleExt; example is_pure; example purelist; } static proc iszero (matrix R) "USAGE: iszero(R); R a matrix RETURN: int, 1, if R is zero, @* or 0, if it's not PURPOSE: checks, if the matrix R is zero or not " { ideal i=R; i=std(i); if (i==0) { return (1); } return (0); } proc lsyz (matrix R) "USAGE: lsyz(R), R a matrix RETURN: matrix, a left syzygy of R PURPOSE: computes the left syzygy module of the module, generated by the rows of R, i.e. @* a matrix X with X*R=0 " { matrix L=transpose(syz(transpose(R))); return(L); } proc rsyz (matrix R) "USAGE: rsyz(R), R a matrix RETURN: matrix, a rightsyzygy of R PURPOSE: computes the right syzygy module of the module, generated by the rows of R, i.e. @* a matrix X with R*X=0 EXAMPLE: example rsyz; shows example " { def save = basering; // with respect to non-commutative rings, def saveop = opposite(save); // we have to switch to the oppose ring for a rightsyzygy setring saveop; matrix Rop = oppose(save,R); matrix Bop = syz(Rop); setring save; matrix B =oppose(saveop,Bop); kill saveop; return(B); } example {"EXAMPLE:";echo = 2; ring D = 0,(x,y,z),dp; matrix R[3][2]=x,0,0,x,y,-z; matrix X=rsyz(R); print(X); // check print(R*X); } static proc rinv (matrix R) "USAGE: rinv(R), R a matrix RETURN: matrix, a right inverse of R PURPOSE: computes a right inverse matrix of R, if it exists @* if not, it returns the zero matrix " { return(rightInverse(R)); } static proc linv (matrix R) "USAGE: linv(R), R a matrix RETURN: matrix, a left inverse of R PURPOSE: computes a left inverse matrix of R, if it exists @* if not, it returns the zero matrix " { return (leftInverse(R)); } proc rlift(matrix M, matrix N) "USAGE: rlift(M,N), M and N matrices, so that the module, generated by the columns of N @* is a submodule of the one, generated by the columns of M RETURN: matrix, a right lift of N in M PURPOSE: computes a right lift matrix X of N in M, @* i.e. N=M*X " { def save = basering; // with respect to non-commutative rings, def saveop = opposite(save); // we have to change the ring for a rightlift setring saveop; matrix Mop = oppose(save,M); matrix Nop = oppose(save,N); matrix Bop = lift(Mop,Nop); setring save; matrix B =oppose(saveop,Bop); kill saveop; return(B); } proc llift(matrix M, matrix N) "USAGE: llift(M,N), M and N matrices, so that the module, generated by the rows of N @* is a submodule of the one, generated by the rows of M RETURN: matrix, a left lift of N in M PURPOSE: computes a left lift matrix X of N in M, @* i.e. N=X*M " { matrix X=transpose(lift(transpose(M),transpose(N))); return(X); } static proc concatz(matrix M, matrix N) "USAGE: concatz(M,N), M and N matrices RETURN: matrix PURPOSE: adds the rows of N under the rows of M, i.e. build the matrix (M^Tr,N^Tr)^Tr " { matrix X=transpose(concat(transpose(M),transpose(N))); return (X); } //------------------------- main procedures -------------------------- proc purityFiltration(matrix R) "USAGE: purityFiltration(S), S matrix with entries of an Auslander regular ring D RETURN: a list T of two lists, purity filtration of the module M=D^q/D^p(S^t) PURPOSE: the first list T[1] gives a filtration {M_i} of M, @* where the i-th entry of T[1] gives the representation matrix of M_(i-1). @* the second list T[2] gives representations of the factor Modules, @* i.e. T[2][i] gives the repr. matrix for M_(i-1)/M_i EXAMPLE: example purityFiltration; shows example " { int i,j; list re=projectiveDimension(R,0); list T=re[1]; int di=re[2]; list reres; // Rji=reres[i][j+1], i=1,..,n+1; j=0,..,i for( i=1; i<=di+1; i++ ) { list zw; zw[i+1]=T[i]; for( j=i; j >= 1; j--) { zw[j]=rsyz(zw[j+1]); } reres[i]=zw; kill zw; } list F; // Fij=F[j][i+1], j=2,..,n+1; i=0,..,j-1 for(i=2;i<=di;i++) { list ehm; matrix I[nrows(T[i-1])][nrows(T[i-1])]; I=I+1; ehm[i]=I; kill I; for (j=1; j<=i-1; j++) { ehm[i-j]=rlift(reres[i][i-j+1],ehm[i-j+1]*reres[i-1][i-j+1]); } F[i]=ehm; kill ehm; } // list M; // Mi=M[i+1], i=0,...,n+1 // M[1]=R1; // matrix Ti=lsyz(reres[1][1]); // matrix P[ncols(Ti)][ncols(Ti)]; // P=P+1; // for (i=1;i<=di; i++) // { // M[i+1]=transpose(modulo(transpose(Ti*P),transpose(reres[i][2]))); // P=F[i+1][1]*P; // Ti=lsyz(reres[i+1][1]); // } // M[di+2]=transpose(modulo(transpose(Ti*P),transpose(reres[di+1][2]))); // list I; // for (i=1;i<=di+1;i++) // { // I[i]=transpose(modulo(transpose(M[i]),transpose(M[i+1]))); // } list Rs,Rss; for(i=1; i<=di; i++) { list zw; zw[1]=lsyz(reres[i][1]); zw[2]=lsyz(zw[1]); Rss[i]=llift(zw[1],reres[i][2]); Rs[i]=zw; kill zw; } list Fs; for(i=2;i<=di;i++) { Fs[i]=llift(Rs[i-1][1],Rs[i][1]*F[i][1]); } list K,U; K[1]=transpose(R); U[1]=Rs[1][1]; for(i=2;i<=di;i++) { K[i]=transpose(std(transpose(concatz(Rss[i-1], Rs[i-1][2])))); U[i]=transpose(std(transpose(concatz(concatz(Fs[i],Rss[i-1]),Rs[i-1][2])))); } K[di+1]=transpose(std(transpose(concatz(Rss[di], Rs[di][2])))); U[di+1]=K[di+1]; list erg=(K,U); return (erg); } example {"EXAMPLE:";echo = 2; ring D = 0,(x1,x2,d1,d2),dp; def S=Weyl(); setring S; int i; matrix R[3][3]=0,d2-d1,d2-d1,d2,-d1,-d1-d2,d1,-d1,-2*d1; print(R); list T=purityFiltration(transpose(R)); // the purity filtration of coker(M) print(T[1][1]); print(T[1][2]); print(T[1][3]); // factor modules of the filtration print(T[2][1]); print(T[2][2]); print(T[2][3]); } proc purityTriang(matrix R) "USAGE: purityTriang(S), S matrix with entries of an Auslander regular ring D RETURN: a matrix T PURPOSE: compute a triangular block matrix T, such that M=D^p/D^q(S^t) is isomorphic to M'=D^p'/D^q(T^t) EXAMPLE: example purityTriang; shows example " { int i,j; list re=projectiveDimension(R,0); list T=re[1]; int di=re[2]; list reres; // Rji=reres[i][j+1], i=1,..,n+1; j=0,..,i for( i=1; i<=di+1; i++ ) { list zw; zw[i+1]=T[i]; for( j=i; j >= 1; j--) { zw[j]=rsyz(zw[j+1]); } reres[i]=zw; kill zw; } list F; // Fij=F[j][i+1], j=2,..,n+1; i=0,..,j-1 for(i=2;i<=di;i++) { list ehm; matrix I[nrows(T[i-1])][nrows(T[i-1])]; I=I+1; ehm[i]=I; kill I; for (j=1; j<=i-1; j++) { ehm[i-j]=rlift(reres[i][i-j+1],ehm[i-j+1]*reres[i-1][i-j+1]); } F[i]=ehm; kill ehm; } list Rs,Rss; for(i=1; i<=di; i++) { list zw; zw[1]=lsyz(reres[i][1]); zw[2]=lsyz(zw[1]); Rss[i]=llift(zw[1],reres[i][2]); Rs[i]=zw; kill zw; } list Fs; for(i=2;i<=di;i++) { Fs[i]=llift(Rs[i-1][1],Rs[i][1]*F[i][1]); } int sp; list spnr; spnr[1]=ncols(Rs[1][1]); for (i=2;i<=di;i++) { spnr[i]=ncols(Fs[i]); } spnr[di+1]=ncols(Rss[di]); sp=sum(spnr); matrix E[nrows(Rs[1][1])][nrows(Rs[1][1])]; E=E-1; list Z; int sumh; Z[1]=concat(Rs[1][1],E); sumh=ncols(Rs[1][1]); kill E; for(i=2;i<=di;i++) { matrix A; matrix B[1][sumh]; matrix E[nrows(Fs[i])][nrows(Fs[i])]; E=E-1; A=Fs[i]; if (i>2) { if (iszero(Rss[i-1])==0) { A=concatz(A,Rss[i-1]); } } if (iszero(Rs[i-1][2])==0) { A=concatz(A,Rs[i-1][2]); } A=concat(B,A,E); Z[i]=A; sumh=sumh+spnr[i]; kill A,B,E; } matrix hi,his; matrix N[1][sumh]; if (iszero(Rss[di])==0) { hi=concat(N,Rss[di]); } if (iszero(Rs[di][2])==0) { his=concat(N,Rs[di][2]); if (iszero(hi)==1) { hi=his; } if (iszero(hi)==0) { hi=concatz(hi,his); } } kill his; matrix ges=Z[1]; for (i=2;i<=di;i++) { ges = concatz(ges,Z[i]); } if (iszero(hi)==0) { ges=concatz(ges,hi); } return (ges); } example {"EXAMPLE:";echo = 2; ring D = 0,(x1,x2,d1,d2),dp; def S=Weyl(); setring S; int i; matrix R[3][3]=0,d2-d1,d2-d1,d2,-d1,-d1-d2,d1,-d1,-2*d1; print(R); matrix T=purityTriang(transpose(R)); // a triangular blockmatrix representing the module coker(R) print(T); } proc gradeNumber(matrix R) "USAGE: gradeNumber(R), R matrix, representing M=D^p/D^q(R^t) over a ring D RETURN: int, grade number of M PURPOSE: computes the grade number of M, i.e. the first i, with ext^i(M,D) !=0 @* returns -1 if M=0 EXAMPLE: example gradeNumber; shows examples " { matrix M=transpose(R); if (is_zero(transpose(M))==1) { return (-1); } list ext = allExtOfLeft(transpose(M)); int i=1; matrix L=ext[i]; while (is_zero(transpose(L))==1) { i=i+1; L=ext[i]; } return (i-1); } example {"EXAMPLE:";echo = 2; // trivial example ring D=0,(x,y,z),dp; matrix R[2][1]=1,x; gradeNumber(R); // R has left inverse, so M=D/D^2R=0 gradeNumber(transpose(R)); print(ncExt_R(0,R)); // so, ext^0(coker(R),D) =! 0) // // a little bit more complex matrix R1[3][1]=x,-y,z; gradeNumber(transpose(R1)); print(ncExt_R(0,transpose(R1))); print(ncExt_R(1,transpose(R1))); print(ncExt_R(2,transpose(R1))); // ext^i are zero for i=0,1,2 matrix ext3=ncExt_R(3,transpose(R1)); print(ext3); // not zero is_zero(ext3); } proc allExtOfLeft(matrix Ps) "USAGE: allExtOfLeft(M), RETURN: list, entries are ext-modules ASSUME: M presents a left module of finite left projective dimension n PURPOSE: For a left module presented by M over the basering D, @* compute a list T, whose entry T[i+1] is a matrix, presenting the right module Ext^i_D(M,D) for i=0..n EXAMPLE: example allExtOfLeft; shows example " { // old doc: ... T[i] gives the repr. matrix of ext^(i-1)(M,D), i=1,.., n+1 list ext, Phi; ext[1]=ncHom_R(Ps); Phi = mres(Ps,0); int di = size(Phi); Phi[di+1]= transpose(lsyz(transpose(Phi[di]))); int i; def Rbase = basering; for(i=1;i<=di;i++) { module f = transpose(matrix(Phi[i+1])); module Im2 = transpose(matrix(Phi[i])); def Rop = opposite(Rbase); setring Rop; module fop = oppose(Rbase,f); module Im2op = oppose(Rbase,Im2); module ker_op = modulo(fop,std(0)); module ext_op = modulo(ker_op,Im2op); setring Rbase; ext[i+1] = oppose(Rop,ext_op); // a right module! kill f, Im2, Rop; } return(ext); } example {"EXAMPLE:";echo = 2; ring D = 0,(x,y,z),dp; matrix R[6][4]= 0,-2*x,z-2*y-x,-1, 0,z-2*x,2*y-3*x,1, z,-6*x,-2*y-5*x,-1, 0,y-x,y-x,0, y,-x,-y-x,0, x,-x,-2*x,0; // coker(R) consider the left module M=D^6/D^4R list T=allExtOfLeft(transpose(R)); print(T[1]); print(T[2]); print(T[3]); print(T[4]); // right modules coker(T[i].)!! } proc allExtOfRight(matrix Ps) "USAGE: allExtOfRight(R), R matrix representing the right Module M=D^q/RD^p over a ring D @* M module with finite right projective dimension n RETURN: list, entries are ext-modules PURPOSE: computes a list T, which entries are representations of the left modules ext^i(M,D) @* T[i] gives the repr. matrix of ext^(i-1)(M,D), i=1,..,n+1 EXAMPLE: example allExtOfRight; shows example " { // matrix Ps=transpose(Y); list ext, Phi; def Rbase = basering; def Rop = opposite(Rbase); setring Rop; matrix Psop=oppose(Rbase,Ps); matrix ext1_op = ncHom_R(Psop); setring Rbase; ext[1]=oppose(Rop,ext1_op); kill Rop; list zw = rightreso(transpose(Ps)); // right resolution int di = size(zw); zw[di+1]=lsyz(zw[di]); Phi = zw; kill zw; int i; for(i=1;i<=di;i++) { module f = Phi[i+1]; module Im2 = Phi[i]; module ker = modulo(f,std(0)); ext[i+1] = modulo(ker,Im2); // a left module! kill f, Im2, ker; } return(ext); } example {"EXAMPLE:";echo = 2; ring D = 0,(x,y,z),dp; matrix R[6][4]= 0,-2*x,z-2*y-x,-1, 0,z-2*x,2*y-3*x,1, z,-6*x,-2*y-5*x,-1, 0,y-x,y-x,0, y,-x,-y-x,0, x,-x,-2*x,0; // coker(R) considered as right module projectiveDimension(R,1)[2]; list T=allExtOfRight(R); print(T[1]); print(T[2]); // left modules coker(.T[i])!! } static proc rightreso(matrix T) "USAGE: rightreso(T), T matrix representing the right module M=D*/TD* RETURN: list L, a right resolution of M PURPOSE: computes a right resolution of M, using mres @* the i-th entry of L gives the (i-1)th right syzygy module of M " { int j; matrix M=transpose(T); list res; def save = basering; // with respect to non-commutative rings, def saveop = opposite(save); // we have to change the ring for a rightresolution setring saveop; matrix Mop=oppose(save,M); list aufl=mres(Mop,0); list resop=aufl; kill aufl; for (j=1; j<=size(resop); j++) { matrix zw=resop[j]; setring save; res[j]=transpose(oppose(saveop,zw)); setring saveop; kill zw; } setring save; kill saveop; return(res); } proc showgrades(list T) "USAGE: showgrades(T), T list, which includes representation matrices of modules RETURN: list, gradenumbers of the entries in T PURPOSE: computes a list L with L[i]=gradenumber(M), M=D^p/D^qT[i] EXAMPLE: example showgrades; shows example " { list grades; int gr=size(T); int i; for (i=1;i<=gr;i++) { grades[i]=gradeNumber(transpose(T[i])); } return (grades); } example {"EXAMPLE:";echo = 2; ring D = 0,(x,y,z),dp; matrix R[6][4]= 0,-2*x,z-2*y-x,-1, 0,z-2*x,2*y-3*x,1, z,-6*x,-2*y-5*x,-1, 0,y-x,y-x,0, y,-x,-y-x,0, x,-x,-2*x,0; list T=purityFiltration(transpose(R))[2]; showgrades(T); // T[i] are i-1 pure (i=1,3,4) or zero (i=2) } proc doubleExt(matrix R, int i) "USAGE: doubleExt(R,i), R matrix representing the left Module M=D^p/D^q(R^t) over a ring D @* int i, less or equal the left projective dimension of M RETURN: matrix P, representing the double ext module PURPOSE: computes a matrix P, which represents the left module ext^i(ext^i(M,D)) EXAMPLE: example doubleExt; shows example " { return (allExtOfRight( allExtOfLeft(R)[i+1] )[i+1]); } example {"EXAMPLE:";echo = 2; ring D = 0,(x,y,z),dp; matrix R[7][3]= 0 ,0,1, 1 ,-4*x+z,-z, -1,8*x-2*z,z, 1 ,0 ,0, 0 ,x-y,0, 0 ,x-y,y, 0 ,0 ,x; // coker(R) is 2-pure, so all doubleExt are zero print(doubleExt(transpose(R),0)); print(doubleExt(transpose(R),1)); print(doubleExt(transpose(R),3)); // except of the second print(doubleExt(transpose(R),2)); } proc allDoubleExt(matrix R) "USAGE: allDoubleExt(R), R matrix representing the left Module M=D^p/D^q(R^t) over a ring D RETURN: list T, double indexed, which include all double-ext modules PURPOSE: computes all double ext-modules @* T[i][j] gives a representation matrix of ext^(j-1)(ext(i-1)(M,D)) EXAMPLE: example allDoubleExt; shows example " { list ext=allExtOfLeft(transpose(R)); list extext; int i; for(i=1;i<=size(ext);i++) { extext[i]=allExtOfRight(ext[i]); } kill ext; return (extext); } example {"EXAMPLE:";echo = 2; ring D = 0,(x1,x2,x3,d1,d2,d3),dp; def S=Weyl(); setring S; matrix R[6][4]= 0,-2*d1,d3-2*d2-d1,-1, 0,d3-2*d1,2*d2-3*d1,1, d3,-6*d1,-2*d2-5*d1,-1, 0,d2-d1,d2-d1,0, d2,-d1,-d2-d1,0, d1,-d1,-2*d1,0; list T=allDoubleExt(transpose(R)); // left projective dimension of M=coker(R) is 3 // ext^i(ext^0(M,D)), i=0,1,2,3 print(T[1][1]); print(T[1][2]); print(T[1][3]); print(T[1][4]); // ext^i(ext^1(M,D)), i=0,1,2,3 print(T[2][1]); print(T[2][2]); print(T[2][3]); print(T[2][4]); // ext^i(ext^2(M,D)), i=0,1,2,3 (all zero) print(T[3][1]); print(T[3][2]); print(T[3][3]); print(T[3][4]); // ext^i(ext^3(M,D)), i=0,1,2,3 (all zero) print(T[4][1]); print(T[4][2]); print(T[4][3]); print(T[4][4]); } proc is_pure(matrix R) "USAGE: is_pure(R), R representing the module M=D^p/D^q(R^t) RETURN: int, 0 or 1 PURPOSE: checks pureness of M. @* returns 1, if M is pure, or 0, if it's not @* remark: if M is zero, is_pure returns 1 EXAMPLE: example is_pure; shows example " { matrix M=transpose(R); int gr=gradeNumber(transpose(M)); int di=projectiveDimension(transpose(M),0)[2]; int i=0; while(i<=di) { if (i!=gr) { if ( is_zero( doubleExt(transpose(M),i) ) == 0 ) { return (0); } } i=i+1; } return (1); } example {"EXAMPLE:";echo = 2; ring D = 0,(x,y,z),dp; matrix R[3][2]=y,-z,x,0,0,x; list T=purityFiltration(transpose(R)); print(transpose(std(transpose(T[2][2])))); // so the purity filtration of coker(R) is trivial, // i.e. coker(R) is already pure is_pure(transpose(R)); // we can also have non-pure modules: matrix R2[6][4]= 0,-2*x,z-2*y-x,-1, 0,z-2*x,2*y-3*x,1, z,-6*x,-2*y-5*x,-1, 0,y-x,y-x,0, y,-x,-y-x,0, x,-x,-2*x,0; is_pure(transpose(R2)); } proc purelist(list T) "USAGE: purelist(T), T list, in which the i-th entry R=T[i] represents M=D^p/D^q(R^t) RETURN: list M, entries of M are 0 or 1 PURPOSE: if T[i] is pure, M[i] is 1, else M[i] is 0 EXAMPLE: example purelist; shows example " { int i; list erg; for(i=1;i<=size(T);i++) { erg[i]=is_pure(transpose(T[i])); } return (erg); } example {"EXAMPLE:";echo = 2; ring D = 0,(x,y,z),dp; matrix R[6][4]= 0,-2*x,z-2*y-x,-1, 0,z-2*x,2*y-3*x,1, z,-6*x,-2*y-5*x,-1, 0,y-x,y-x,0, y,-x,-y-x,0, x,-x,-2*x,0; is_pure(transpose(R)); // R is not pure, so we do the purity filtration list T=purityFiltration(transpose(R)); // all Elements of T[2] are either zero or pure purelist(T[2]); } proc projectiveDimension(matrix T, list #) "USAGE: projectiveDimension(R,i,j), R matrix representing the Modul M=coker(R) @* int i, with i=0 or i=1, j a natural number RETURN: list T, a projective resolution of M and its projective dimension PURPOSE: if i=0 (and by default), T[1] gives a shortest left resolution of M=D^p/D^q(R^t) and T[2] the left projective dimension of M @* if i=1, T[1] gives a shortest right resolution of M=D^p/RD^q and T[2] the right projective dimension of M @* in both cases T[1][j] is the (j-1)-th syzygy module of M NOTE: The algorithm is due to A. Quadrat, D. Robertz, Computation of bases of free modules over the Weyl algebras, J.Symb.Comp. 42, 2007. EXAMPLE: example projectiveDimension; shows examples " { int i = 0; // default if (size(#) >0) { i = int(#[1]); if ( (i!=0) and (i!=1) ) { printf("Unaccepted second argument. Use 0 to get a left resolution, 1 for a right one."); } } if (i==0) { return(prodim(T)); } int j; matrix M=T; list res; def save = basering; // with respect to non-commutative rings, def saveop = opposite(save); // we have to change the ring for a rightresolution setring saveop; matrix Mop=oppose(save,M); list aufl=prodim(Mop); int k=aufl[2]; list resop=aufl[1]; kill aufl; for (j=1; j<=size(resop); j++) { matrix zw=resop[j]; setring save; res[j]=transpose(oppose(saveop,zw)); setring saveop; kill zw; } setring save; list Y; Y[1]=res; Y[2]=k; kill saveop; kill res; return(Y); } example {"EXAMPLE:";echo = 2; // commutative example ring D = 0,(x,y,z),dp; matrix R[6][4]= 0,-2*x,z-2*y-x,-1, 0,z-2*x,2*y-3*x,1, z,-6*x,-2*y-5*x,-1, 0,y-x,y-x,0, y,-x,-y-x,0, x,-x,-2*x,0; // compute a left resolution of M=D^4/D^6*R list T=projectiveDimension(transpose(R),0); // so we have the left projective dimension T[2]; //we could also compute a right resolution of M=D^6/RD^4 list T1=projectiveDimension(R,1); // and we have right projective dimension T1[2]; // check, that a syzygy matrix of R has left inverse: print(leftInverse(syz(R))); // so lpd(M) must be 1. // Non-commutative example ring D1 = 0,(x1,x2,x3,d1,d2,d3),dp; def S=Weyl(); setring S; matrix R[3][3]= 1/2*x2*d1, x2*d2+1, x2*d3+1/2*d1, -1/2*x2*d2-3/2,0,1/2*d2, -d1-1/2*x2*d3,-d2,-1/2*d3; list T=projectiveDimension(R,0); // left projective dimension of coker(R) is T[2]; list T1=projectiveDimension(R,1); // both modules have the same projective dimension, but different resolutions, because D is non-commutative print(T[1][1]); // not the same as print(transpose(T1[1][1])); } static proc prodim(matrix M) "USAGE: prodim(R), R matrix representing the Modul M=coker(R) RETURN: list T, a left projective resolution of M and its left projective dimension PURPOSE: T[1] gives a shortest left resolution of M and T[2] the left projective dimension of M @* it is T[1][j] the (j-1)-th syzygy module of M " { matrix T=transpose(M); list R,zw; R[1]=T; if (rinv(R[1])==0) { R[2]=transpose(std(transpose(lsyz(R[1])))); } else { matrix S[1][ncols(T)]; R[1]=S; zw[1]=R; zw[2]=0; return (zw); } if (iszero(R[2])==1) { zw[1]=R; zw[2]=1; return (zw); } int i=1; matrix N; while (iszero(R[i+1])==0) { i=i+1; N=rinv(R[i]); if (iszero(N)==0) { if (i==2) { R[i-1]=concat(R[i-1],N); matrix K[1][nrows(R[1])]; R[2]=K; zw[1]=R; zw[2]=i-1; return (zw); } if (i>2) { R[i-1]=concat(R[i-1],N); matrix K[ncols(N)][1]; R[i-2]=concatz(R[i-2],K); R[i]=0; zw[1]=R; zw[2]=i-1; return(zw); } } R[i+1]=transpose(std(transpose(lsyz(R[i])))); } zw[1]=R; zw[2]=i; return (zw); } singular-4.0.3+ds/Singular/LIB/qhmoduli.lib000066400000000000000000001314311266270727000204640ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version qhmoduli.lib 4.0.0.0 Jun_2013 "; // $Id: bebbc37438a50e1faca24d907fdd18672a015f47 $ category="Singularities"; info=" LIBRARY: qhmoduli.lib Moduli Spaces of Semi-Quasihomogeneous Singularities AUTHOR: Thomas Bayer, email: bayert@in.tum.de PROCEDURES: ArnoldAction(f, [G, w]) Induced action of G_f on T_. ModEqn(f) Equations of the moduli space for principal part f QuotientEquations(G,A,I) Equations of Variety(I)/G w.r.t. action 'A' StabEqn(f) Equations of the stabilizer of f. StabEqnId(I, w) Equations of the stabilizer of the qhom. ideal I. StabOrder(f) Order of the stabilizer of f. UpperMonomials(f, [w]) Upper basis of the Milnor algebra of f. Max(data) maximal integer contained in 'data' Min(data) minimal integer contained in 'data' "; // NOTE: This library has been written in the frame of the diploma thesis // 'Computing moduli spaces of semiquasihomogeneous singularities and an // implementation in Singular', Arbeitsgruppe Algebraische Geometrie, // Fachbereich Mathematik, University Kaiserslautern, // Advisor: Prof. Gert-Martin Greuel LIB "rinvar.lib"; /////////////////////////////////////////////////////////////////////////////// proc ModEqn(poly f, list #) "USAGE: ModEqn(f [, opt]); poly f; int opt; PURPOSE: compute equations of the moduli space of semiquasihomogenos hypersurface singularity with principal part f w.r.t. right equivalence ASSUME: f quasihomogeneous polynomial with an isolated singularity at 0 RETURN: polynomial ring, possibly a simple extension of the ground field of the basering, containing the ideal 'modid' - 'modid' is the ideal of the moduli space if opt is even (> 0). otherwise it contains generators of the coordinate ring R of the moduli space (note : Spec(R) is the moduli space) OPTIONS: 1 compute equations of the mod. space, 2 use a primary decomposition, 4 compute E_f0, i.e., the image of G_f0, to combine options, add their value, default: opt =7 EXAMPLE: example ModEqn; shows an example " { int sizeOfAction, i, dimT, nonLinearQ, milnorNr, dbPrt; int imageQ, opt; intvec wt; ideal B; list Gf, tIndex, sList; string ringSTR; dbPrt = printlevel-voice+2; if(size(#) > 0) { opt = #[1]; } else { opt = 7; } if(opt div 4 > 0) { imageQ = 1; opt = opt - 4;} else { imageQ = 0; } wt = weight(f); milnorNr = vdim(std(jacob(f))); if(milnorNr == -1) { ERROR("the polynomial " + string(f) + " has a nonisolated singularity at 0"); } // singularity not isolated // 1st step : compute a basis of T_ B = UpperMonomials(f, wt); dimT = size(B); dbprint(dbPrt, "moduli equations of f = " + string(f) + ", f has Milnor number = " + string(milnorNr)); dbprint(dbPrt, " upper basis = " + string(B)); if(size(B) > 1) { // 2nd step : compute the stabilizer G_f of f dbprint(dbPrt, " compute equations of the stabilizer of f, called G_f"); Gf = StabEqn(f); dbprint(dbPrt, " order of the stabilizer = " + string(StabOrder(Gf))); // 3rd step : compute the induced action of G_f on T_ by means of a theorem of Arnold dbprint(dbPrt, " compute the induced action"); def RME1 = ArnoldAction(f, Gf, B); setring(RME1); export(RME1); dbprint(dbPrt, " G_f = " + string(stabid)); dbprint(dbPrt, " action of G_f : " + string(actionid)); // 4th step : linearize the action of G_f sizeOfAction = size(actionid); def RME2 = LinearizeAction(stabid, actionid, nvars(Gf[1])); setring RME2; export(RME2); kill RME1; if(size(actionid) == sizeOfAction) { nonLinearQ = 0;} else { nonLinearQ = 1; dbprint(dbPrt, " linearized action = " + string(actionid)); dbprint(dbPrt, " embedding of T_ = " + string(embedid)); } if(!imageQ) { // do not compute the image of Gf // 5th step : set E_f = G_f, dbprint(dbPrt, " compute equations of the quotient T_/G_f"); def RME3 = basering; } else { // 5th step : compute the ideal and the action of E_f dbprint(dbPrt, " compute E_f"); def RME3 = ImageGroup(groupid, actionid); setring(RME3); ideal embedid = imap(RME2, embedid); dbprint(dbPrt, " E_f = (" + string(groupid) + ")"); dbprint(dbPrt, " action of E'f = " + string(actionid)); dbprint(dbPrt, " compute equations of the quotient T_/E_f"); } export(RME3); kill RME2; // 6th step : compute the equations of the quotient T_/E_f ideal G = groupid; ideal variety = embedid; kill groupid,embedid; def RME4 = QuotientEquations(G, actionid, variety, opt); setring RME4; string @mPoly = string(minpoly); kill RME3; export(RME4); // simplify the ideal and create a new ring with propably less variables if(opt == 1 || opt == 3) { // equations computed ? sList = SimplifyIdeal(id, 0, "Y"); ideal newid = sList[1]; dbprint(dbPrt, " number of equations = " + string(size(sList[1]))); dbprint(dbPrt, " number of variables = " + string(size(sList[3]))); ringSTR = "ring RME5 = (" + charstr(basering) + "), (Y(1.." + string(size(sList[3])) + ")),dp;"; execute(ringSTR); execute("minpoly = number(" + @mPoly + ");"); ideal modid = imap(RME4, newid); } else { def RME5 = RME4; setring(RME5); ideal modid = imap(RME4, id); } export(modid); kill RME4; } else { def RME5 = basering; ideal modid = maxideal(1); if(size(B) == 1) { // 1-dimensional modid[size(modid)] = 0; modid = simplify(modid,2); } export(modid); } dbprint(dbPrt, " // 'ModEqn' created a new ring. // To see the ring, type (if the name of the ring is R): show(R); // To access the ideal of the moduli space of semiquasihomogeneous singularities // with principal part f, type def R = ModEqn(f); setring R; modid; // 'modid' is the ideal of the moduli space. // if 'opt' = 0 or even, then 'modid' contains algebra generators of S s.t. // spec(S) = moduli space of f. "); return(RME5); } example {"EXAMPLE:"; echo = 2; ring B = 0,(x,y), ls; poly f = -x4 + xy5; def R = ModEqn(f); setring R; modid; } /////////////////////////////////////////////////////////////////////////////// proc QuotientEquations(ideal G, ideal Gaction, ideal embedding, list#) "USAGE: QuotientEquations(G,action,emb [, opt]); ideal G,action,emb;int opt PURPOSE: compute the quotient of the variety given by the parameterization 'emb' by the linear action 'action' of the algebraic group G. ASSUME: 'action' is linear, G must be finite if the Reynolds operator is needed (i.e., NullCone(G,action) returns some non-invariant polys) RETURN: polynomial ring over a simple extension of the ground field of the basering, containing the ideals 'id' and 'embedid'. - 'id' contains the equations of the quotient, if opt = 1; if opt = 0, 2, 'id' contains generators of the coordinate ring R of the quotient (Spec(R) is the quotient) - 'embedid' = 0, if opt = 1; if opt = 0, 2, it is the ideal defining the equivariant embedding OPTIONS: 1 compute equations of the quotient, 2 use a primary decomposition when computing the Reynolds operator,@* to combine options, add their value, default: opt =3. EXAMPLE: example QuotientEquations; shows an example " { int i, opt, primaryDec, relationsQ, dbPrt; ideal Gf, variety; intvec wt; dbPrt = printlevel-voice+3; if(size(#) > 0) { opt = #[1]; } else { opt = 3; } if(opt div 2 > 0) { primaryDec = 1; opt = opt - 2; } else { primaryDec = 0; } if(opt > 0) { relationsQ = 1;} else { relationsQ = 0; } Gf = std(G); variety = EquationsOfEmbedding(embedding, nvars(basering) - size(Gaction)); if(size(variety) == 0) { // use Hilbert function ! //for(i = 1; i <= ncols(Gaction); i ++) { wt[i] = 1;} for(i = 1; i <= nvars(basering); i ++) { wt[i] = 1;} } def RQER = InvariantRing(Gf, Gaction, primaryDec); // compute the nullcone of the linear action def RQEB = basering; setring(RQER); export(RQER); if(relationsQ > 0) { dbprint(dbPrt, " compute equations of the variety (" + string(size(imap(RQER, invars))) + " invariants) "); if(!defined(variety)) { ideal variety = imap(RQEB, variety); } if(wt[1] > 0) { def RQES = ImageVariety(variety, imap(RQER, invars), wt); } else { def RQES = ImageVariety(variety, imap(RQER, invars)); // forget imap } setring(RQES); ideal id = imageid; ideal embedid = 0; } else { def RQES = basering; ideal id = imap(RQER, invars); ideal embedid = imap(RQEB, variety); } kill RQER; export(id); export(embedid); return(RQES); } /////////////////////////////////////////////////////////////////////////////// proc UpperMonomials(poly f, list #) "USAGE: UpperMonomials(poly f, [intvec w]) PURPOSE: compute the upper monomials of the milnor algebra of f. ASSUME: f is quasihomogeneous (w.r.t. w) RETURN: ideal EXAMPLE: example UpperMonomials; shows an example " { int i,d; intvec wt; ideal I, J; if(size(#) == 0) { wt = weight(f);} else { wt = #[1];} J = kbase(std(jacob(f))); d = deg(f, wt); for(i = 1; i <= size(J); i++) { if(deg(J[i], wt) > d) {I = I, J[i];} } return(simplify(I, 2)); } example {"EXAMPLE:"; echo = 2; ring B = 0,(x,y,z), ls; poly f = -z5+y5+x2z+x2y; UpperMonomials(f); } /////////////////////////////////////////////////////////////////////////////// proc ArnoldAction(poly f, list #) "USAGE: ArnoldAction(f, [Gf, B]); poly f; list Gf, B; 'Gf' is a list of two rings (coming from 'StabEqn') PURPOSE: compute the induced action of the stabilizer G of f on T_, where T_ is given by the upper monomials B of the Milnor algebra of f. ASSUME: f is quasihomogeneous RETURN: polynomial ring over the same ground field, containing the ideals 'actionid' and 'stabid'. - 'actionid' is the ideal defining the induced action of Gf on T_ @* - 'stabid' is the ideal of the stabilizer Gf in the new ring EXAMPLE: example ArnoldAction; shows an example " { int i, offset, ub, pos, nrStabVars, dbPrt; intvec wt = weight(f); ideal B; list Gf, parts, baseDeg; string ringSTR1, ringSTR2, parName, namesSTR, varSTR; dbPrt = printlevel-voice+2; if(size(#) == 0) { Gf = StabEqn(f); B = UpperMonomials(f, wt); } else { Gf = #[1]; if(size(#) > 1) { B = #[2];} else {B = UpperMonomials(f, wt);} } if(size(B) == 0) { ERROR("the principal part " + string(f) + " has no upper monomials");} for(i = 1; i <= size(B); i = i + 1) { baseDeg[i] = deg(B[i], wt); } ub = Max(baseDeg) + 1; // max degree of an upper mono. def RAAB = basering; def STR1 = Gf[1]; def STR2 = Gf[2]; nrStabVars = nvars(STR1); dbprint(dbPrt, "ArnoldAction of f = ", f, ", upper base = " + string(B)); setring STR1; string @mPoly = string(minpoly); setring RAAB; // setup new ring with s(..) and t(..) as parameters varSTR = string(maxideal(1)); ringSTR2 = "ring RAAS = "; if(npars(basering) == 1) { parName = parstr(basering); ringSTR2 = ringSTR2 + "(0, " + parstr(1) + "), "; } else { parName = "a"; ringSTR2 = ringSTR2 + "0, "; } offset = 1 + nrStabVars; namesSTR = "s(1.." + string(nrStabVars) + "), t(1.." + string(size(B)) + ")"; ringSTR2 = ringSTR2 + "(" + namesSTR + "), lp;"; ringSTR1 = "ring RAAR = (0, " + parName + "," + namesSTR + "), (" + varSTR + "), ls;"; // lp ? execute(ringSTR1); export(RAAR); ideal upperBasis, stabaction, action, reduceIdeal; poly f, F, monos, h; execute("reduceIdeal = " + @mPoly + ";"); reduceIdeal = reduceIdeal, imap(STR1, stabid); f = imap(RAAB, f); F = f; upperBasis = imap(RAAB, B); for(i = 1; i <= size(upperBasis); i = i + 1) { F = F + par(i + offset)*upperBasis[i]; } monos = F - f; stabaction = imap(STR2, actionid); // action of the stabilizer on the semiuniversal unfolding of f F = f + APSubstitution(monos, stabaction, reduceIdeal, wt, ub, nrStabVars, size(upperBasis)); // apply the theorem of Arnold h = ArnoldFormMain(f, upperBasis, F, reduceIdeal, nrStabVars, size(upperBasis)) - f; // extract the polynomials of the action of the stabilizer on T_ parts = MonosAndTerms(h, wt, ub); for(i = 1; i <= size(parts[1]); i = i + 1) { pos = FirstEntryQHM(upperBasis, parts[1][i]); if (pos!=0) { action[pos] = parts[2][i]/parts[1][i];} } execute(ringSTR2); execute("minpoly = number(" + @mPoly + ");"); ideal actionid = imap(RAAR, action); ideal stabid = imap(STR1, stabid); export(actionid); export(stabid); kill RAAR; dbprint(dbPrt, " // 'ArnoldAction' created a new ring. // To see the ring, type (if the name of the ring is R): show(R); // To access the ideal of the stabilizer G of f and its group action, // where f is the quasihomogeneous principal part, type def R = ArnoldAction(f); setring R; stabid; actionid; // 'stabid' is the ideal of the group G and 'actionid' is the ideal defining // the group action of the group G on T_. Note: this action might be nonlinear "); return(RAAS); } example {"EXAMPLE:"; echo = 2; ring B = 0,(x,y,z), ls; poly f = -z5+y5+x2z+x2y; def R = ArnoldAction(f); setring R; actionid; stabid; } /////////////////////////////////////////////////////////////////////////////// proc StabOrder(list #) "USAGE: StabOrder(f); poly f PURPOSE: compute the order of the stabilizer group of f. ASSUME: f quasihomogeneous polynomial with an isolated singularity at 0 RETURN: int GLOBAL: varSubsList " { list stab; if(size(#) == 1) { stab = StabEqn(#[1]); } else { stab = #;} def RSTO = stab[1]; setring(RSTO); return(vdim(std(stabid))); } /////////////////////////////////////////////////////////////////////////////// proc StabEqn(poly f) "USAGE: StabEqn(f); f polynomial PURPOSE: compute the equations of the isometry group of f. ASSUME: f semiquasihomogeneous polynomial with an isolated singularity at 0 RETURN: list of two rings 'S1', 'S2' - 'S1' contians the equations of the stabilizer (ideal 'stabid') @* - 'S2' contains the action of the stabilizer (ideal 'actionid') EXAMPLE: example StabEqn; shows an example GLOBAL: varSubsList, contains the index j s.t. x(i) -> x(i)t(j) ... " { dbprint(dbPrt, " // 'StabEqn' created a list of 2 rings. // To see the rings, type (if the name of your list is stab): show(stab); // To access the 1-st ring and map (and similair for the others), type: def S1 = stab[1]; setring S1; stabid; // S1/stabid is the coordinate ring of the variety of the // stabilizer, say G. If G x K^n --> K^n is the action of G on // K^n, then the ideal 'actionid' in the second ring describes // the dual map on the ring level. // To access the 2-nd ring and map (and similair for the others), type: def S2 = stab[2]; setring S2; actionid; "); return(StabEqnId(ideal(f), qhweight(f))); } example {"EXAMPLE:"; echo = 2; ring B = 0,(x,y,z), ls; poly f = -z5+y5+x2z+x2y; list stab = StabEqn(f); def S1 = stab[1]; setring S1; stabid; def S2 = stab[2]; setring S2; actionid; } /////////////////////////////////////////////////////////////////////////////// proc StabEqnId(ideal data, intvec wt) "USAGE: StabEqn(I, w); I ideal, w intvec PURPOSE: compute the equations of the isometry group of the ideal I, each generator of I is fixed by the stabilizer. ASSUME: I semiquasihomogeneous ideal w.r.t. 'w' with an isolated singularity at 0 RETURN: list of two rings 'S1', 'S2' - 'S1' contians the equations of the stabilizer (ideal 'stabid') @* - 'S2' contains the action of the stabilizer (ideal 'actionid') EXAMPLE: example StabEqnId; shows an example GLOBAL: varSubsList, contains the index j s.t. t(i) -> t(i)t(j) ... " { int i, j, c, k, r, nrVars, offset, n, sln, dbPrt; list Variables, rd, temp, sList, varSubsList; string ringSTR, ringSTR1, varString, parString; dbPrt = printlevel-voice+2; dbprint(dbPrt, "StabilizerEquations of " + string(data)); export(varSubsList); n = nvars(basering); Variables = StabVar(wt); // possible quasihomogeneous substitutions nrVars = 0; for(i = 1; i <= size(wt); i++) { nrVars = nrVars + size(Variables[i]); } // set the new basering needed for the substitutions varString = "s(1.." + string(nrVars) + ")"; if(npars(basering) == 1) { parString = "(0, " + parstr(basering) + ")"; } else { parString = "0"; } def RSTB = basering; string @mPoly = string(minpoly); ringSTR = "ring RSTR = " + parString + ", (" + varstr(basering) + ", " + varString + "), dp;"; // dp ringSTR1 = "ring RSTT = " + parString + ", (" + varString + ", " + varstr(basering) + "), dp;"; if(defined(RSTR)) { kill RSTR;} if(defined(RSTT)) { kill RSTT;} execute(ringSTR1); // this ring is only used for the result, where the variables export(RSTT); // are s(1..m),t(1..n), as needed for Derksens algorithm (NullCone) execute("minpoly = number(" + @mPoly + ");"); execute(ringSTR); export(RSTR); execute("minpoly = number(" + @mPoly + ");"); poly f, f1, g, h, vars, pp; // f1 is the polynomial after subs, ideal allEqns, qhsubs, actionid, stabid, J; list ringList; // all t(i)`s which do not appear in f1 ideal data = simplify(imap(RSTB, data), 2); // generate the quasihomogeneous substitution map F nrVars = 0; offset = 0; for(i = 1; i <= size(wt); i++) { // build the substitution t(i) -> ... if(i > 1) { offset = offset + size(Variables[i - 1]); } g = 0; for(j = 1; j <= size(Variables[i]); j++) { pp = 1; for(k = 2; k <= size(Variables[i][j]); k++) { pp = pp * var(Variables[i][j][k]); if(Variables[i][j][k] == i) { varSubsList[i] = offset + j;} } g = g + s(offset + j) * pp; } qhsubs[i] = g; } dbprint(dbPrt, " qhasihomogenous substituion =" + string(qhsubs)); map F = RSTR, qhsubs; kill varSubsList; // get the equations of the stabilizer by comparing coefficients // in the equation f = F(f). vars = RingVarProduct(Table("i", "i", 1, size(wt))); allEqns = 0; matrix newcoMx, coMx; int d; for(r = 1; r <= ncols(data); r++) { f = data[r]; f1 = F(f); d = deg(f); newcoMx = coef(f1, vars); // coefficients of F(f) coMx = coef(f, vars); // coefficients of f for(i = 1; i <= ncols(newcoMx); i++) { // build the system of eqns via coeff. comp. j = 1; h = 0; while(j <= ncols(coMx)) { // all monomials in f if(coMx[j][1] == newcoMx[i][1]) { h = coMx[j][2]; j = ncols(coMx) + 1;} else {j = j + 1;} } J = J, newcoMx[i][2] - h; // add equation } allEqns = allEqns, J; } allEqns = std(allEqns); // simplify the equations, i.e., if s(i) in J then remove s(i) from J // and from the basering sList = SimplifyIdeal(allEqns, n, "s"); stabid = sList[1]; map phi = basering, sList[2]; sln = size(sList[3]) - n; // change the substitution actionid = phi(qhsubs); // change to new ring, auxillary construction setring(RSTT); ideal actionid, stabid; actionid = imap(RSTR, actionid); stabid = imap(RSTR, stabid); export(stabid); export(actionid); ringList[2] = RSTT; dbprint(dbPrt, " substitution = " + string(actionid)); dbprint(dbPrt, " equations of stabilizer = " + string(stabid)); varString = "s(1.." + string(sln) + ")"; ringSTR = "ring RSTS = " + parString + ", (" + varString + "), dp;"; execute(ringSTR); execute("minpoly = number(" + @mPoly + ");"); ideal stabid = std(imap(RSTR, stabid)); export(stabid); ringList[1] = RSTS; dbprint(dbPrt, " // 'StabEqnId' created a list of 2 rings. // To see the rings, type (if the name of your list is stab): show(stab); // To access the 1-st ring and map (and similair for the others), type: def S1 = stab[1]; setring S1; stabid; // S1/stabid is the coordinate ring of the variety of the // stabilizer, say G. If G x K^n --> K^n is the action of G on // K^n, then the ideal 'actionid' in the second ring describes // the dual map on the ring level. // To access the 2-nd ring and map (and similair for the others), type: def S2 = stab[2]; setring S2; actionid; "); return(ringList); } example {"EXAMPLE:"; echo = 2; ring B = 0,(x,y,z), ls; ideal I = x2,y3,z6; intvec w = 3,2,1; list stab = StabEqnId(I, w); def S1 = stab[1]; setring S1; stabid; def S2 = stab[2]; setring S2; actionid; } /////////////////////////////////////////////////////////////////////////////// static proc ArnoldFormMain(poly f,def B, poly Fs, ideal reduceIdeal, int nrs, int nrt) "USAGE: ArnoldFormMain(f, B, Fs, rI, nrs, nrt); poly f,Fs; ideal B, rI; int nrs, nrt PURPOSE: compute the induced action of 'G_f' on T_, where f is the principal part and 'Fs' is the semiuniversal unfolding of 'f' with x_i substituted by actionid[i], 'B' is a list of upper basis monomials for the milnor algebra of 'f', 'nrs' = number of variables for 'G_f' and 'nrt' = dimension of T_ ASSUME: f is quasihomogeneous with an isolated singularity at 0, s(1..r), t(1..m) are parameters of the basering RETURN: poly EXAMPLE: example ArnoldAction; shows an example " { int i, j, d, ub, dbPrt; list upperBasis, basisDegList, gmonos, common, parts; ideal jacobianId, jacobIdstd, mapId; // needed for phi intvec wt = weight(f); matrix gCoeffMx; // for lift command poly newFs, g, gred, tt; // g = sum of all monomials of degree d, gred is needed for lift map phi; // the map from Arnold's Theorem dbPrt = printlevel-voice+2; jacobianId = jacob(f); jacobIdstd = std(jacobianId); newFs = Fs; for(i = 1; i <= size(B); i++) { basisDegList[i] = deg(B[i], wt); } ub = Max(basisDegList) + 1; // max degree of an upper monomial parts = MonosAndTerms(newFs - f, wt, ub); gmonos = parts[1]; d = deg(f, wt); for(i = d + 1; i < ub; i++) { // base[1] = monomials of degree i upperBasis[i] = SelectMonos(list(B, B), wt, i); // B must not contain 0's } // test if each monomial of Fs is contained in B, if not, // compute a substitution via Arnold's theorem and substitutite // it into newFs for(i = d + 1; i < ub; i = i + 1) { // ub instead of @UB dbprint(dbPrt, "-- degree = " + string(i) + " of " + string(ub - 1) + " ---------------------------"); if(size(newFs) < 80) { dbprint(dbPrt, " polynomial = " + string(newFs - f));} else { dbprint(dbPrt, " poly has deg (not weighted) " + string(deg(newFs)) + " and contains " + string(size(newFs)) + " monos");} // select monomials of degree i and intersect them with upperBasis[i] gmonos = SelectMonos(parts, wt, i); common = IntersectionQHM(upperBasis[i][1], gmonos[1]); if(size(common) == size(gmonos[1])) { dbprint(dbPrt, " no additional monomials "); } // other monomials than those in upperBasis occur, compute // the map constructed in the proof of Arnold's theorem // write g = c[i] * jacobianId[i] else { dbprint(dbPrt, " additional Monomials found, compute the map "); g = PSum(gmonos[2]); // sum of all monomials in g of degree i dbprint(dbPrt, " sum of degree " + string(i) + " is " + string(g)); gred = reduce(g, jacobIdstd); gCoeffMx = lift(jacobianId, g - gred); // compute c[i] mapId = var(1) - gCoeffMx[1][1]; // generate the map for(j = 2; j <= size(gCoeffMx); j++) { mapId[j] = var(j) - gCoeffMx[1][j]; } dbprint(dbPrt, " map = " + string(mapId)); // apply the map to newFs newFs = APSubstitution(newFs, mapId, reduceIdeal, wt, ub, nrs, nrt); parts = MonosAndTerms(newFs - f, wt, ub); // monos and terms of deg < ub newFs = PSum(parts[2]) + f; // result of APS... is already reduced dbprint(dbPrt, " monomials of degree " + string(i)); } } return(newFs); } /////////////////////////////////////////////////////////////////////////////// static proc MonosAndTerms(poly f,def wt, int ub) "USAGE: MonosAndTerms(f, w, ub); poly f, intvec w, int ub PURPOSE: returns a list of all monomials and terms occuring in f of weighted degree < ub RETURN: list _[1] list of monomials _[2] list of terms EXAMPLE: example MonosAndTerms shows an example " { int i, k; list monomials, terms; poly mono, lcInv, data; data = jet(f, ub - 1, wt); k = 0; for(i = 1; i <= size(data); i++) { mono = lead(data[i]); if(deg(mono, wt) < ub) { k = k + 1; lcInv = 1/leadcoef(mono); monomials[k] = mono * lcInv; terms[k] = mono; } } return(list(monomials, terms)); } example {"EXAMPLE:"; echo = 2; ring B = 0,(x,y,z), lp; poly f = 6*x2 + 2*x3 + 9*x*y2 + z*y + x*z6; MonosAndTerms(f, intvec(2,1,1), 5); } /////////////////////////////////////////////////////////////////////////////// static proc SelectMonos(def parts, intvec wt, int d) "USAGE: SelectMonos(parts, w, d); list/ideal parts, intvec w, int d PURPOSE: returns a list of all monomials and terms occuring in f of weighted degree = d RETURN: list _[1] list of monomials _[2] list of terms EXAMPLE: example SelectMonos; shows an example " { int i, k; list monomials, terms; poly mono; k = 0; for(i = 1; i <= size(parts[1]); i++) { mono = parts[1][i]; if(deg(mono, wt) == d) { k++; monomials[k] = mono; terms[k] = parts[2][i]; } } return(list(monomials, terms)); } example {"EXAMPLE:"; echo = 2; ring B = 0,(x,y,z), lp; poly f = 6*x2 + 2*x3 + 9*x*y2 + z*y + x*z6; list mt = MonosAndTerms(f, intvec(2,1,1), 5); SelectMonos(mt, intvec(2,1,1), 4); } /////////////////////////////////////////////////////////////////////////////// static proc Expand(def substitution,def degVec, ideal reduceI, intvec w1, int ub, list truncated) "USAGE: Expand(substitution, degVec, reduceI, w, ub, truncated); ideal/list substitution, list/intvec degVec, ideal reduceI, intvec w, int ub, list truncated PURPOSE: substitute 'substitution' in the monomial given by the list of exponents 'degVec', omit all terms of weighted degree > ub and reduce the result w.r.t. 'reduceI'. If truncated[i] = 0 then the result is stored for later use. RETURN: poly NOTE: used by APSubstitution GLOBAL: computedPowers " { int i, minDeg; list powerList; poly g, h; // compute substitution[1]^degVec[1],...,subs[n]^degVec[n] for(i = 1; i <= ncols(substitution); i++) { if(size(substitution[i]) < 3 || degVec[i] < 4) { powerList[i] = reduce(substitution[i]^degVec[i], reduceI); // new } // directly for small exponents else { powerList[i] = PolyPower1(i, substitution[i], degVec[i], reduceI, w1, truncated[i], ub); } } // multiply the terms obtained by using PolyProduct(); g = powerList[1]; minDeg = w1[1] * degVec[1]; for(i = 2; i <= ncols(substitution); i++) { g = jet(g, ub - w1[i] * degVec[i] - 1, w1); h = jet(powerList[i], ub - minDeg - 1, w1); g = PolyProduct(g, h, reduceI, w1, ub); if(g == 0) { Print(" g = 0 "); break;} minDeg = minDeg + w1[i] * degVec[i]; } return(g); } /////////////////////////////////////////////////////////////////////////////// static proc PolyProduct(poly g1, poly h1, ideal reduceI, intvec wt, int ub) "USAGE: PolyProduct(g, h, reduceI, wt, ub); poly g, h; ideal reduceI, intvec wt, int ub. PURPOSE: compute g*h and reduce it w.r.t 'reduceI' and omit terms of weighted degree > ub. RETURN: poly NOTE: used by 'Expand' " { int SUBSMAXSIZE = 3000; int i, nrParts, sizeOfPart, currentPos, partSize, maxSIZE; poly g, h, gxh, prodComp, @g2; // replace @g2 by subst. g = g1; h = h1; if(size(g)*size(h) > SUBSMAXSIZE) { // divide the polynomials with more terms in parts s.t. // the product of each part with the other polynomial // has at most SUBMAXSIZE terms if(size(g) < size(h)) { poly @h = h; h = g; g = @h;@h = 0; } maxSIZE = SUBSMAXSIZE / size(h); //print(" SUBSMAXSIZE = "+string(SUBSMAXSIZE)+" exceeded by "+string(size(g)*size(h)) + ", maxSIZE = ", string(maxSIZE)); nrParts = size(g) div maxSIZE + 1; partSize = size(g) div nrParts; gxh = 0; // 'g times h' for(i = 1; i <= nrParts; i++) { //print(" loop #" + string(i) + " of " + string(nrParts)); currentPos = (i - 1) * partSize; if(i < nrParts) {sizeOfPart = partSize;} else { sizeOfPart = size(g) - (nrParts - 1) * partSize; print(" last #" + string(sizeOfPart) + " terms ");} prodComp = g[currentPos + 1..sizeOfPart + currentPos] * h; // multiply a part @g2 = jet(prodComp, ub - 1, wt); // eventual reduce ... if(size(@g2) < size(prodComp)) { print(" killed " + string(size(prodComp) - size(@g2)) + " terms ");} gxh = reduce(gxh + @g2, reduceI); } } else { gxh = reduce(jet(g * h,ub - 1, wt), reduceI); } // compute directly return(gxh); } /////////////////////////////////////////////////////////////////////////////// static proc PolyPower1(int varIndex, poly f, int e, ideal reduceI, intvec wt, int truncated, int ub) "USAGE: PolyPower1(i, f, e, reduceI, wt, truncated, ub);int i, e, ub;poly f; ideal reduceI; intvec wt; list truncated; PURPOSE: compute f^e, use previous computations if possible, and reduce it w.r.t reudecI and omit terms of weighted degree > ub. RETURN: poly NOTE: used by 'Expand' GLOBAL: 'computedPowers' " { int i, ordOfg, lb, maxPrecomputedPower; poly g, fn; if(e == 0) { return(1);} if(e == 1) { return(f);} if(f == 0) { return(1); } else { // test if f has been computed to some power if(computedPowers[varIndex][1] > 0) { maxPrecomputedPower = computedPowers[varIndex][1]; if(maxPrecomputedPower >= e) { // no computation necessary, f^e has already benn computed g = computedPowers[varIndex][2][e - 1]; //Print("No computation, from list : g = elem [", varIndex, ", 2, ", e - 1, "]"); lb = e + 1; } else { // f^d computed, where d < e g = computedPowers[varIndex][2][maxPrecomputedPower - 1]; ordOfg = maxPrecomputedPower * wt[varIndex]; lb = maxPrecomputedPower + 1; } } else { // no precomputed data lb = 2; ordOfg = wt[varIndex]; g = f; } for(i = lb; i <= e; i++) { fn = jet(f, ub - ordOfg - 1, wt); // reduce w.r.t. reduceI g = PolyProduct(g, fn, reduceI, wt, ub); ordOfg = ordOfg + wt[varIndex]; if(g == 0) { break; } if((i > maxPrecomputedPower) && !truncated) { if(maxPrecomputedPower == 0) { // init computedPowers computedPowers[varIndex] = list(i, list(g)); } computedPowers[varIndex][1] = i; // new degree computedPowers[varIndex][2][i - 1] = g; maxPrecomputedPower = i; } } } return(g); } /////////////////////////////////////////////////////////////////////////////// static proc RingVarsToList(list @index) { int i; list temp; for(i = 1; i <= size(@index); i++) { temp[i] = string(var(@index[i])); } return(temp); } /////////////////////////////////////////////////////////////////////////////// static proc APSubstitution(poly f, ideal substitution, ideal reduceIdeal, intvec wt, int ub, int nrs, int nrt) "USAGE: APSubstitution(f, subs, reduceI, w, ub, int nrs, int nrt); poly f ideal subs, reduceI, intvec w, int ub, nrs, nrt; nrs = number of parameters s(1..nrs), nrt = number of parameters t(1..nrt) PURPOSE: substitute 'subs' in f, omit all terms with weighted degree > ub and reduce the result w.r.t. 'reduceI'. RETURN: poly GLOBAL: 'computedPowers' " { int i, j, k, d, offset; int n = nvars(basering); list coeffList, parts, degVecList, degOfMonos; list computedPowers, truncatedQ, degOfSubs, @temp; string ringSTR, @ringVars; export(computedPowers); // store arguments in strings def RASB = basering; parts = MonosAndTerms(f, wt, ub); for(i = 1; i <= size(parts[1]); i = i + 1) { coeffList[i] = parts[2][i]/parts[1][i]; degVecList[i] = leadexp(parts[1][i]); degOfMonos[i] = deg(parts[1][i], wt); } // built new basering with no parameters and order dp ! // the parameters of the basering are appended to // the variables of the basering ! // set ideal mpoly = minpoly for reduction ! @ringVars = "(" + varstr(basering) + ", " + parstr(1) + ","; // precondition if(nrs > 0) { @ringVars = @ringVars + "s(1.." + string(nrs) + "), "; } @ringVars = @ringVars + "t(1.." + string(nrt) + "))"; ringSTR = "ring RASR = 0, " + @ringVars + ", dp;"; // new basering // built the "reduction" ring with the reduction ideal execute(ringSTR); export(RASR); ideal reduceIdeal, substitution, newSubs; intvec w1, degVec; list minDeg, coeffList, degList; poly f, g, h, subsPoly; w1 = wt; // new weights offset = nrs + nrt + 1; for(i = n + 1; i <= offset + n; i = i + 1) { w1[i] = 0; } reduceIdeal = std(imap(RASB, reduceIdeal)); // omit later ! coeffList = imap(RASB, coeffList); substitution = imap(RASB, substitution); f = imap(RASB, f); for(i = 1; i <= n; i++) { // all "base" variables computedPowers[i] = list(0); for(j = 1; j <= size(substitution[i]); j++) { degList[j] = deg(substitution[i][j], w1);} degOfSubs[i] = degList; } // substitute in each monomial seperately g = 0; for(i = 1; i <= size(degVecList); i++) { truncatedQ = Table("0", "i", 1, n); newSubs = 0; degVec = degVecList[i]; d = degOfMonos[i]; // check if some terms in the substitution can be omitted // degVec = list of exponents of the monomial m // minDeg[j] denotes the weighted degree of the monomial m' // where m' is the monomial m without the j-th variable for(j = 1; j <= size(degVec); j++) { minDeg[j] = d - degVec[j] * wt[j]; } for(j = 1; j <= size(degVec); j++) { subsPoly = 0; // set substitution to 0 if(degVec[j] > 0) { // if variable occurs then check if // substitution[j][k] * (linear part)^(degVec[j]-1) + minDeg[j] < ub // i.e. look for the smallest possible combination in subs[j]^degVec[j] // which comes from the term substitution[j][k]. This term is multiplied // with the rest of the monomial, which has at least degree minDeg[j]. // If the degree of this product is < ub then substitution[j][k] contributes // to the result and cannot be omitted for(k = 1; k <= size(substitution[j]); k++) { if(degOfSubs[j][k] + (degVec[j] - 1) * wt[j] + minDeg[j] < ub) { subsPoly = subsPoly + substitution[j][k]; } } } newSubs[j] = subsPoly; // set substitution if(substitution[j] - subsPoly != 0) { truncatedQ[j] = 1;} // mark that substitution[j] is truncated } h = Expand(newSubs, degVec, reduceIdeal, w1, ub, truncatedQ) * coeffList[i]; // already reduced g = reduce(g + h, reduceIdeal); } kill computedPowers; setring RASB; poly fnew = imap(RASR, g); kill RASR; return(fnew); } /////////////////////////////////////////////////////////////////////////////// static proc StabVar(intvec wt) "USAGE: StabVar(w); intvec w PURPOSE: compute the indicies for quasihomogeneous substitutions of each variable. ASSUME: f semiquasihomogeneous polynomial with an isolated singularity at 0 RETURN: list _[i] list of combinations for var(i) (i must be appended to each comb) GLOBAL: 'varSubsList', contains the index j s.t. x(i) -> x(i)t(j) ... " { int i, j, k, uw, ic; list varList, Variables, subs; string str, varString; varList = StabVarComb(wt); for(i = 1; i <= size(wt); i = i + 1) { subs = 0; // built linear substituitons for(j = 1; j <= size(varList[1][i]); j++) { subs[j] = list(i) + list(varList[1][i][j]); } Variables[i] = subs; if(size(varList[2][i]) > 0) { // built nonlinear substituitons subs = 0; for(j = 1; j <= size(varList[2][i]); j++) { subs[j] = list(i) + varList[2][i][j]; } Variables[i] = Variables[i] + subs; } } return(Variables); } /////////////////////////////////////////////////////////////////////////////// static proc StabVarComb(intvec wt) "USAGE: StabVarComb(w); intvec w PURPOSE: list all possible indices of indeterminates for a quasihom. subs. RETURN: list _[1] linear substitutions _[2] nonlinear substiutions GLOBAL: 'varSubsList', contains the index j s.t. x(i) -> x(i)t(j) ... " { int mmi, mma, ii, j, k, uw, ic; list index, indices, usedWeights, combList, combinations; list linearSubs, nonlinearSubs; list partitions, subs, temp; // subs[i] = substitution for var(i) linearSubs = Table("0", "i", 1, size(wt)); nonlinearSubs = Table("0", "i", 1, size(wt)); uw = 0; ic = 0; mmi = Min(wt); mma = Max(wt); for(ii = mmi; ii <= mma; ii++) { if(containedQ(wt, ii)) { // find variables of weight ii k = 0; index = 0; // collect the indices of all variables of weight i for(j = 1; j <= size(wt); j++) { if(wt[j] == ii) { k++; index[k] = j; } } uw++; usedWeights[uw] = ii; ic++; indices[ii] = index; // linear part of the substitution for(j = 1; j <= size(index); j++) { linearSubs[index[j]] = index; } // nonlinear part of the substitution if(uw > 1) { // variables of least weight do not allow nonlinear subs. partitions = Partitions(ii, delete(usedWeights, uw)); for(j = 1; j <= size(partitions); j++) { combinations[j] = AllCombinations(partitions[j], indices); } for(j = 1; j <= size(index); j++) { nonlinearSubs[index[j]] = FlattenQHM(combinations); // flatten one level ! } } } } combList[1] = linearSubs; combList[2] = nonlinearSubs; return(combList); } /////////////////////////////////////////////////////////////////////////////// static proc AllCombinations(list partition, list indices) "USAGE: AllCombinations(partition,indices); list partition, indices) PURPOSE: all combinations for a given partititon RETURN: list GLOBAL: varSubsList, contains the index j s.t. x(i) -> x(i)t(j) ... " { int i, k, m, ok, p, offset; list nrList, indexList; k = 0; offset = 0; i = 1; ok = 1; m = partition[1]; while(ok) { if(i > size(partition)) { ok = 0; p = 0; } else { p = partition[i];} if(p == m) { i = i + 1;} else { k = k + 1; nrList[k] = i - 1 - offset; offset = offset + i - 1; indexList[k] = indices[m]; if(ok) { m = partition[i];} } } return(AllCombinationsAux(nrList, indexList)); } /////////////////////////////////////////////////////////////////////////////// static proc AllSingleCombinations(int n, list index) "USAGE: AllSingleCombinations(n index); int n, list index PURPOSE: all combinations for var(n) RETURN: list " { int i, j, k; list comb, newC, temp, newIndex; if(n == 1) { for(i = 1; i <= size(index); i++) { temp = index[i]; comb[i] = temp; } return(comb); } if(size(index) == 1) { temp = Table(string(index[1]), "i", 1, n); comb[1] = temp; return(comb); } newIndex = index; for(i = 1; i <= size(index); i = i + 1) { if(i > 1) { newIndex = delete(newIndex, 1); } newC = AllSingleCombinations(n - 1, newIndex); k = size(comb); temp = 0; for(j = 1; j <= size(newC); j++) { temp[1] = index[i]; temp = temp + newC[j]; comb[k + j] = temp; temp = 0; } } return(comb); } /////////////////////////////////////////////////////////////////////////////// static proc AllCombinationsAux(list parts, list index) "USAGE: AllCombinationsAux(parts ,index); list parts, index PURPOSE: all compbinations for nonlinear substituiton RETURN: list " { int i, j, k; list comb, firstC, restC; if(size(parts) == 0 || size(index) == 0) { return(comb);} firstC = AllSingleCombinations(parts[1], index[1]); restC = AllCombinationsAux(delete(parts, 1), delete(index, 1)); if(size(restC) == 0) { comb = firstC;} else { for(i = 1; i <= size(firstC); i++) { k = size(comb); for(j = 1; j <= size(restC); j++) { //elem = firstC[i] + restC[j]; // comb[k + j] = elem; comb[k + j] = firstC[i] + restC[j]; } } } return(comb); } /////////////////////////////////////////////////////////////////////////////// static proc Partitions(int n, list nr) "USAGE: Partitions(n, nr); int n, list nr PURPOSE: partitions of n consisting of elements from nr RETURN: list " { int i, j, k; list parts, temp, restP, newP, decP; if(size(nr) == 0) { return(list());} if(size(nr) == 1) { if(NumFactor(nr[1], n) > 0) { parts[1] = Table(string(nr[1]), "i", 1, NumFactor(nr[1], n)); } return(parts); } else { parts = Partitions(n, nr[1]); restP = Partitions(n, delete(nr, 1)); parts = parts + restP; for(i = 1; i <= n div nr[1]; i = i + 1) { temp = Table(string(nr[1]), "i", 1, i); decP = Partitions(n - i*nr[1], delete(nr, 1)); k = size(parts); for(j = 1; j <= size(decP); j++) { newP = temp + decP[j]; // new partition if(!containedQ(parts, newP, 1)) { k = k + 1; parts[k] = newP; } } } } return(parts); } /////////////////////////////////////////////////////////////////////////////// static proc NumFactor(int a, int b) " USAGE: NumFactor(a, b); int a, b PURPOSE: if b divides a then return b/a, else return 0 RETURN: int " { int c = b div a; if(c*a == b) { return(c); } else {return(0)} } /////////////////////////////////////////////////////////////////////////////// static proc Table(string cmd, string iterator, int lb, int ub) " USAGE: Table(cmd,i, lb, ub); string cmd, i; int lb, ub PURPOSE: generate a list of size ub - lb + 1 s.t. _[i] = cmd(i) RETURN: list " { list data; execute("int " + iterator + ";"); for(int @i = lb; @i <= ub; @i++) { execute(iterator + " = " + string(@i)); execute("data[" + string(@i) + "] = " + cmd + ";"); } return(data); } /////////////////////////////////////////////////////////////////////////////// static proc FlattenQHM(list data) " USAGE: FlattenQHM(n, nr); list data PURPOSE: flatten the list (one level) 'data', which is a list of lists RETURN: list " { int i, j, c; list fList, temp; c = 1; for(i = 1; i <= size(data); i++) { for(j = 1; j <= size(data[i]); j++) { fList[c] = data[i][j]; c = c + 1; } } return(fList); } /////////////////////////////////////////////////////////////////////////////// static proc IntersectionQHM(list l1, list l2) // Type : list // Purpose : Intersection of l1 and l2 { list l; int b, c; c = 1; for(int i = 1; i <= size(l1); i++) { b = containedQ(l2, l1[i]); if(b == 1) { l[c] = l1[i]; c++; } } return(l); } /////////////////////////////////////////////////////////////////////////////// static proc FirstEntryQHM(def data,def elem) // Type : int // Purpose : position of first entry equal to elem in data (from left to right) { int i, pos; i = 0; pos = 0; while(i < size(data)) { i++; if(data[i] == elem) { pos = i; break;} } return(pos); } /////////////////////////////////////////////////////////////////////////////// static proc PSum(def e) { poly f; for(int i = size(e);i>=1;i--) { f = f + e[i]; } return(f); } /////////////////////////////////////////////////////////////////////////////// proc Max(def data) "USAGE: Max(data); intvec/list of integers PURPOSE: find the maximal integer contained in 'data' RETURN: list ASSUME: 'data' contains only integers and is not empty " { int i; int max = data[1]; for(i = size(data); i>1;i--) { if(data[i] > max) { max = data[i]; } } return(max); } example {"EXAMPLE:"; echo = 2; Max(list(1,2,3)); } /////////////////////////////////////////////////////////////////////////////// proc Min(def data) "USAGE: Min(data); intvec/list of integers PURPOSE: find the minimal integer contained in 'data' RETURN: list ASSUME: 'data' contians only integers and is not empty " { int i; int min = data[1]; for(i = size(data);i>1; i--) { if(data[i] < min) { min = data[i]; } } return(min); } example {"EXAMPLE:"; echo = 2; Min(intvec(1,2,3)); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/qmatrix.lib000066400000000000000000000176611266270727000203370ustar00rootroot00000000000000///////////////////////////////////// version="version qmatrix.lib 4.0.0.0 Jun_2013 "; // $Id: 0ff9b9f42c3021528e3920ce6700195dc3d55673 $ category="Noncommutative"; info=" LIBRARY: qmatrix.lib Quantum matrices, quantum minors and symmetric groups AUTHORS: Lobillo, F.J., jlobillo@ugr.es @* Rabelo, C., crabelo@ugr.es SUPPORT: 'Metodos algebraicos y efectivos en grupos cuanticos', BFM2001-3141, MCYT, Jose Gomez-Torrecillas (Main researcher). PROCEDURES: quantMat(n, [p]); generates the quantum matrix ring of order n; qminor(u, v, nr); calculate a quantum minor of a quantum matrix SymGroup(n); generates an intmat containing S(n), each row is an element of S(n) LengthSymElement(v); calculates the length of the element v of S(n) LengthSym(M); calculates the length of each element of M, being M a subset of S(n) "; LIB "ncalg.lib"; LIB "nctools.lib"; // for rootofUnity /////////////////////////////////////////////////////////////////////////////// proc SymGroup(int n) "USAGE: SymGroup(n); n an integer (positive) RETURN: intmat PURPOSE: represent the symmetric group S(n) via integer vectors (permutations) NOTE: each row of the output integer matrix is an element of S(n) SEE ALSO: LengthSym, LengthSymElement EXAMPLE: example SymGroup; shows examples "{ if (n<=0) { "n must be positive"; intmat M[1][1]=0; } else { if (n==1) { intmat M[1][1]=1; } else { def N=SymGroup(n-1); // N is the symmetric group S(n-1) int m=nrows(N); // The order of S(n-1)=(n-1)! intmat M[m*n][n]; // Matrix to save S(n), m*n=n*(n-1)!=n!=#S(n) int i,j,k; for (i=1; i<=m; i++) { // fixed an element i of S(n-1) for (j=n; j>0; j--) { // and fixed a position j to introduce an "n" for (k=1; kv[i]. proc LengthSymElement(intvec v) "USAGE: LengthSymElement(v); v intvec RETURN: int PURPOSE: determine the length of the permutation given by v in some S(n) ASSUME: v represents an element of S(n); otherwise the output may have no sense SEE ALSO: SymGroup, LengthSym EXAMPLE: example LengthSymElement; shows examples "{ int n=size(v); int l=0; int i,j; for (i=1; i1), p an optional integer RETURN: ring (of quantum matrices). If p is specified, the quantum parameter q @* will be specialized at the p-th root of unity PURPOSE: compute the quantum matrix ring of order n NOTE: activate this ring with the \"setring\" command. @* The usual representation of the variables in this quantum @* algebra is not used because double indexes are not allowed @* in the variables. Instead the variables are listed by reading @* the rows of the usual matrix representation, that is, there @* will be n*n variables (one for each entry an n*N generic matrix), @* listed row-wise SEE ALSO: qminor EXAMPLE: example quantMat; shows examples "{ if (n>1) { int nv=n^2; intmat m[nv][nv]; int i,j; for (i=1; i<=nv; i++) { m[i,nv+1-i]=1; } int chr = 0; if ( size(#) > 0 ) { if ( typeof( #[1] ) == "int" ) { chr = #[1]; } } ring @rrr=(0,q),(y(1..nv)),Dp; minpoly = rootofUnity(chr); matrix C[nv][nv]=0; matrix D[nv][nv]=0; intvec idyi, idyj; for (i=1; i=2 ) { int p=#[1]; int b=#[2];} if( size(#)==1 ) { int p=#[1]; int b=30000;} if( size(#)==0 ) { int p=75; int b=30000;} //---------------- use sparsetriag for creation of genericid ------------------ def i = simplify(id,10); i = i*sparsetriag(ncols(i),ncols(i),p,b); return(i); } example { "EXAMPLE:"; echo = 2; ring r=0,(t,x,y,z),ds; ideal i= x3+y4,z4+yx,t+x+y+z; genericid(i,0,10); module m=[x,0,0,0],[0,y2,0,0],[0,0,z3,0],[0,0,0,t4]; print(genericid(m)); } /////////////////////////////////////////////////////////////////////////////// proc randomid (def id, list #) "USAGE: randomid(id[,k,b]); id ideal/module, b,k integers RETURN: ideal/module having k generators which are random linear combinations of generators of id with coefficients in the interval [-b,b] (default: b=30000, k=size(id)) NOTE: For performance reasons try small bound b in characteristic 0 EXAMPLE: example randomid; shows an example " { //----------------------------- set defaults ---------------------------------- if( size(#)>=2 ) { int k=#[1]; int b=#[2]; } if( size(#)==1 ) { int k=#[1]; int b=30000; } if( size(#)==0 ) { int k=size(id); int b=30000; } //--------------------------- create randomid --------------------------------- def i = id; i = matrix(id)*random(b,ncols(id),k); return(i); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; randomid(maxideal(2),2,9); module m=[x,0,1],[0,y2,0],[y,0,z3]; show(randomid(m)); } /////////////////////////////////////////////////////////////////////////////// proc randommat (int n, int m, list #) "USAGE: randommat(n,m[,id,b]); n,m,b integers, id ideal RETURN: nxm matrix, entries are random linear combinations of elements of id and coefficients in [-b,b] [default: (id,b) = (maxideal(1),30000)] NOTE: For performance reasons try small bound b in char 0 EXAMPLE: example randommat; shows an example " { //----------------------------- set defaults ---------------------------------- if( size(#)>=2 ) { ideal id=#[1]; int b=#[2]; } if( size(#)==1 ) { ideal id=#[1]; int b=30000; } if( size(#)==0 ) { ideal id=maxideal(1); int b=30000; } //--------------------------- create randommat -------------------------------- id=simplify(id,2); int g=ncols(id); matrix rand[n][m]; matrix ra[1][m]; for (int k=1; k<=n; k=k+1) { ra = id*random(b,g,m); rand[k,1..m]=ra[1,1..m]; } return(rand); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; matrix A=randommat(3,3,maxideal(2),9); print(A); A=randommat(2,3); print(A); } /////////////////////////////////////////////////////////////////////////////// proc sparseid (int k, int u, list #) "USAGE: sparseid(k,u[,o,p,b]); k,u,o,p,b integers RETURN: ideal having k generators, each of degree d, u<=d<=o, p percent of terms in degree d are 0, the remaining have random coefficients in the interval [1,b], (default: o=u, p=75, b=30000) EXAMPLE: example sparseid; shows an example " { //----------------------------- set defaults ---------------------------------- if( size(#)>=3 ) { int o=#[1]; int p=#[2]; int b=#[3]; } else {if( size(#)==2 ) { int o=#[1]; int p=#[2]; int b=30000; } else {if( size(#)==1 ) { int o=#[1]; int p=75; int b=30000; } else {if( size(#)==0 ) { int o=u; int p=75; int b=30000; }}}} //------------------ use sparsemat for creation of sparseid ------------------- int ii; matrix i[1][k]; intmat m; if( u <=0 ) { m = sparsemat(1,k,p,b); i = m; u=1; } for ( ii=u; ii<=o; ii++) { m = sparsemat(size(maxideal(ii)),k,p,b); i = i+matrix(maxideal(ii))*m; } return(ideal(i)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,c,d),ds; sparseid(2,3);""; sparseid(3,0,4,90,9); } /////////////////////////////////////////////////////////////////////////////// proc sparseHomogIdeal (int k, int u, list #) "USAGE: sparseid(k,u[,o,p,b]); k,u,o,p,b integers RETURN: ideal having k homogeneous generators, each of random degree in the interval [u,o], p percent of terms in degree d are 0, the remaining have random coefficients in the interval [1,b], (default: o=u, p=75, b=30000) EXAMPLE: example sparseid; shows an example " { //----------------------------- set defaults ---------------------------------- if( size(#)>=3 ) { int o=#[1]; int p=#[2]; int b=#[3]; } if( size(#)==2 ) { int o=#[1]; int p=#[2]; int b=30000; } if( size(#)==1 ) { int o=#[1]; int p=75; int b=30000; } if( size(#)==0 ) { int o=u; int p=75; int b=30000; } //------------------ use sparsemat for creation of sparseid ------------------- int ii; ideal i; intmat m; ideal id; for ( ii=k; ii>0; ii--) { id = maxideal(random(u, o)); // monomial basis of some degree m = sparsemat(size(id),1,p,b); // random coefficients i[ii] = (matrix(id)*m)[1,1]; } return(i); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,c,d),dp; sparseHomogIdeal(2,3);""; sparseHomogIdeal(3,0,4,90,9); } /////////////////////////////////////////////////////////////////////////////// proc sparsemat (int n, int m, list #) "USAGE: sparsemat(n,m[,p,b]); n,m,p,b integers RETURN: nxm integer matrix, p percent of the entries are 0, the remaining are random coefficients >=1 and <= b; [defaults: (p,b) = (75,1)] EXAMPLE: example sparsemat; shows an example " { int r,h,ii; int t = n*m; intmat v[1][t]; //----------------------------- set defaults ---------------------------------- if( size(#)>=2 ) { int p=#[1]; int b=#[2]; } if( size(#)==1 ) { int p=#[1]; int b=1; } if( size(#)==0 ) { int p=75; int b=1; } //------------------------- check trivial cases ------------------------------ if( p<0 ) { p = 0; } if(p>100) { p=100; } //--------------- this is faster for not very sparse matrices ---------------- if( p<40 ) { for( ii=1; ii<=t; ii++ ) { r=( random(1,100)>p ); v[1,ii]=r*random(1,b); h=h+r; } } int bb = t*(100-p); if( 100*h > bb ) { while( 100*h > bb ) { r=random(1,t); h=h-( v[1,r]>0 ); v[1,r]=0; } } else { //------------------- this is faster for sparse matrices --------------------- while ( 100*h < bb ) { r=random(1,t); h=h+(v[1,r]==0); v[1,r]=random(1,b); } } intmat M[n][m] = v[1,1..t]; return(M); } example { "EXAMPLE:"; echo = 2; sparsemat(5,5);""; sparsemat(5,5,95);""; sparsemat(5,5,5);""; sparsemat(5,5,50,100); } /////////////////////////////////////////////////////////////////////////////// proc sparsematrix (int n, int m, int o, list #) "USAGE: sparsematrix(n,m,o[,u,pe,pp,b]); n,m,o,u,pe,pp,b integers RETURN: nxm matrix, about pe percent of the entries are 0, the remaining are random polynomials of degree d, u<=d<=o, with pp percent of the terms being 0, the remaining have random coefficients in the interval [1,b] [default: (pe,u,pp,b) = (0,50,75,100)] EXAMPLE: example sparsematrix; shows an example " { int ii,jj; ideal id; matrix M[n][m]; //----------------------------- set defaults ---------------------------------- int pe=50;int u=0;int pp=75;int b=100; if( size(#)==4 ) { u=#[1]; pe=#[2]; pp=#[3]; b=#[4]; } else { if( size(#)==3 ) { u=#[1]; pe=#[2]; pp=#[3]; } else { if( size(#)==2 ) { u=#[1]; pe=#[2]; } else {if( size(#)==1 ) { u=#[1]; }}}} //------------------- use sparsemat and sparseid ----------------------------- intmat I = sparsemat(n,m,pe,1); for(ii=n; ii>0;ii--) { id = sparseid(m,u,o,pp,b); for(jj=m; jj>0; jj--) { if( I[ii,jj] !=0) { M[ii,jj]=id[jj]; } } } return(M); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,c,d),dp; // sparse matrix of sparse polys of degree <=2: print(sparsematrix(3,4,2));""; // dense matrix of sparse linear forms: print(sparsematrix(3,3,1,1,0,55,9)); } /////////////////////////////////////////////////////////////////////////////// proc sparsepoly (int u, list #) "USAGE: sparsepoly(u[,o,p,b]); u,o,p,b integers RETURN: poly having only terms in degree d, u<=d<=o, p percentage of the terms in degree d are 0, the remaining have random coefficients in [1,b), (defaults: o=u, p=75, b=30000) EXAMPLE: example sparsepoly; shows an example " { //----------------------------- set defaults ---------------------------------- if( size(#)>=3 ) { int o=#[1]; int p=#[2]; int b=#[3]; } else {if( size(#)==2 ) { int o=#[1]; int p=#[2]; int b=30000; } else {if( size(#)==1 ) { int o=#[1]; int p=75; int b=30000; } else {if( size(#)==0 ) { int o=u; int p=75; int b=30000; }}}} int ii; poly f; //----------------- use sparseid for creation of sparsepoly ------------------- for( ii=u; ii<=o; ii++ ) { f=f+sparseid(1,ii,ii,p,b)[1]; } return(f); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; sparsepoly(5);""; sparsepoly(3,5,90,9); } /////////////////////////////////////////////////////////////////////////////// proc sparsetriag (int n, int m, list #) "USAGE: sparsetriag(n,m[,p,b]); n,m,p,b integers RETURN: nxm lower triagonal integer matrix, diagonal entries equal to 1, about p percent of lower diagonal entries are 0, the remaining are random integers >=1 and <= b; [defaults: (p,b) = (75,1)] EXAMPLE: example sparsetriag; shows an example " { int ii,min,l,r; intmat M[n][m]; int t=(n*(n-1)) div 2; //----------------------------- set defaults ---------------------------------- if( size(#)>=2 ) { int p=#[1]; int b=#[2]; } if( size(#)==1 ) { int p=#[1]; int b=1; } if( size(#)==0 ) { int p=75; int b=1; } //---------------- use sparsemat for creation of sparsetriag ------------------ intmat v[1][t]=sparsemat(1,t,p,b); if( n<=m ) { min=n-1; M[n,n]=1; } else { min=m; } for( ii=1; ii<=min; ii++ ) { l=r+1; r=r+n-ii; M[ii..n,ii]=1,v[1,l..r]; } return(M); } example { "EXAMPLE:"; echo = 2; sparsetriag(5,7);""; sparsetriag(7,5,90);""; sparsetriag(5,5,0);""; sparsetriag(5,5,50,100); } /////////////////////////////////////////////////////////////////////////////// proc triagmatrix (int n, int m, int o, list #) "USAGE: triagmatrix(n,m,o[,u,pe,pp,b]); n,m,o,u,pe,pp,b integers RETURN: nxm lower triagonal matrix, diagonal entries equal to 1, about p percent of lower diagonal entries are 0, the remaining are random polynomials of degree d, u<=d<=o, with pp percent of the terms being 0, the remaining have random coefficients in the interval [1,b] [default: (pe,u,pp,b) = (0,50,75,100)] EXAMPLE: example triagmatrix; shows an example " { int ii,jj; ideal id; matrix M[n][m]; //----------------------------- set defaults ---------------------------------- int pe=50;int u=0;int pp=75;int b=100; if( size(#)==4 ) { u=#[1]; pe=#[2]; pp=#[3]; b=#[4]; } if( size(#)==3 ) { u=#[1]; pe=#[2]; pp=#[3]; } if( size(#)==2 ) { u=#[1]; pe=#[2]; } if( size(#)==1 ) { u=#[1]; } //------------------- use sparsemat and sparseid ----------------------------- intmat I = sparsetriag(n,m,pe,1); for(ii=1; ii<=n;ii++) { id = sparseid(m,u,o,pp,b); for(jj=1; jj=2 ) { int o=#[1]; int b=#[2]; } if( size(#)==1 ) { int o=#[1]; int b=10; } if( size(#)==0 ) { int o=u; int b=10; } //------------------ use sparsemat for creation of sparseid ------------------- ideal i,m; int ii,jj,s,r1,r2; if ( o=2 EXAMPLE: example ratstd; shows examples " { int ppl = printlevel-voice+1; int eng = 0; // optional arguments if (size(#)>0) { if (typeof(#[1]) == "int") { eng = int(#[1]); } } dbprint(ppl,"engine chosen to be"); dbprint(ppl,eng); // 0. do the subst's /reformulations // for the time being, ASSUME // the ord. is an elim. ord. for D // and the block of X's is on the left // its length is 'is' int i,j,k; dbprint(ppl,"// -1- creating K(x)[D]"); // 1. create K(x)[D], commutative def save = basering; list L = ringlist(save); list RL, tmp1,tmp2,tmp3,tmp4; intvec iv; // copy: field, enlarge it with Xs if ( size(L[1]) == 0) { // i.e. the field with char only tmp2[1] = L[1]; // tmp1 = L[2]; j = size(L[2]); iv = 1; for (i=1; i<=is; i++) { tmp1[i] = L[2][i]; iv = iv,1; } iv = iv[1..size(iv)-1]; //extra 1 tmp2[2] = tmp1; tmp3[1] = "lp"; tmp3[2] = iv; // tmp2[3] = 0; tmp4[1] = tmp3; tmp2[3] = tmp4; //[1] = "lp"; // tmp2[3][2] = iv; tmp2[4] = ideal(0); RL[1] = tmp2; } if ( size(L[1]) >0 ) { // TODO!!!!! tmp2[1] = L[1][1]; //char K // there are parameters // add to them X's, IGNORE alg.extension // the ordering on pars tmp1 = L[1][2]; // param names j = size(tmp1); iv = L[1][3][1][2]; for (i=1; i<=is; i++) { tmp1[j+i] = L[2][i]; iv = iv,1; } tmp2[2] = tmp1; tmp2[3] = L[1][3]; tmp2[3][1][2] = iv; tmp2[4] = ideal(0); RL[1] = tmp2; } // vars: leave only D's kill tmp1; list tmp1; // tmp1 = L[2]; for (i=is+1; i<= size(L[2]); i++) { tmp1[i-is] = L[2][i]; } RL[2] = tmp1; // old: assume the ordering is the block with (a(0:is),ORD) // old :set up ORD as the ordering // L; "RL:"; RL; if (size(L[3]) != 3) { //"note: strange ordering"; // NEW assume: ordering is the antiblock with (a(0:is),a(*1),a(*), ORD) // get the a() parts after is => they should form a complete D-ordering list L3 = L[3]; list NL3; kill tmp3; list tmp3; int @sl = size(L3); int w=1; int z; intvec va,vb; while(L3[w][1] == "a") { va = L3[w][2]; for(z=1;z<=nvars(save)-is;z++) { vb[z] = va[is+z]; } tmp3[1] = "a"; tmp3[2] = vb; NL3[w] = tmp3; tmp3=0; w++; } // check for completeness: must be >= nvars(save)-is rows if (w < nvars(save)-is) { "note: ordering is incomplete on D. Adding lower Dp block"; // adding: positive things like Dp tmp3[1]= "Dp"; for (z=1; z<=nvars(save)-is; z++) { va[is+z] = 1; } tmp3[2] = va; NL3[w] = tmp3; tmp3 = 0; w++; } NL3[w] = L3[@sl]; // module ord? RL[3] = NL3; } else { kill tmp2; list tmp2; tmp2[1] = L[3][2]; tmp2[2] = L[3][3]; RL[3] = tmp2; } // factor ideal is ignored RL[4] = ideal(0); // "ringlist:"; RL; def @RAT = ring(RL); dbprint(ppl,"// -2- preprocessing with content"); // 2. preprocess input with rm_content_id setring @RAT; dbprint(ppl-1, @RAT); // ideal CI = imap(save,I); def CI = imap(save,I); CI = rm_content_id(CI); dbprint(ppl-1, CI); dbprint(ppl,"// -3- running groebner"); // 3. compute G = GB(I) w.r.t. the elim. ord. for D setring save; // ideal CI = imap(@RAT,CI); def CI = imap(@RAT,CI); option(redSB); option(redTail); if (eng) { def G = slimgb(CI); } else { def G = groebner(CI); } // ideal G = groebner(CI); // although slimgb looks better // def G = slimgb(CI); G = simplify(G,2); // to be sure there are no 0's dbprint(ppl-1, G); dbprint(ppl,"// -4- postprocessing with content"); // 4. postprocess the output with 1) rm_content_id, 2) lm-minimization; setring @RAT; // ideal CG = imap(save,G); def CG = imap(save,G); CG = rm_content_id(CG); CG = simplify(CG,2); dbprint(ppl-1, CG); // warning: a bugfarm! in this ring, the ordering might change!!! (see appelF4) // so, simplify(32) should take place in the orig. ring! and NOT here // CG = simplify(CG,2+32); // 4b. create L(G) with X's as coeffs (for minimization) setring save; G = imap(@RAT,CG); int sG = ncols(G); // ideal LG; def LG = G; for (i=1; i<= sG; i++) { LG[i] = lead(G[i]); } // compute the D-dimension of the ideal in the ring @RAT setring @RAT; // ideal LG = imap(save,LG); def LG = imap(save,LG); // ideal LGG = groebner(LG); // cosmetics def LGG = groebner(LG); // cosmetics int d = dim(LGG); int Ddim = d; printf("the D-dimension is %s",d); if (d==0) { d = vdim(LGG); int Dvdim = d; printf("the K-dimension is %s",d); } // ideal SLG = simplify(LG,8+32); //contains zeros def SLG = simplify(LG,8+32); //contains zeros setring save; // ideal SLG = imap(@RAT,SLG); def SLG = imap(@RAT,SLG); // simplify(LG,8+32); //contains zeros intvec islg; if (SLG[1] == 0) { islg = 0; } else { islg = 1; } for (i=2; i<= ncols(SLG); i++) { if (SLG[i] == 0) { islg = islg, 0; } else { islg = islg, 1; } } for (i=1; i<= ncols(LG); i++) { if (islg[i] == 0) { G[i] = 0; } } G = simplify(G,2); // ready! // G = imap(@RAT,CG); // return the result // ideal pGBid = G; def pGBid = G; export pGBid; // export Ddim; // export Dvdim; setring @RAT; // ideal rGBid = imap(save,G); def rGBid = imap(save,G); // CG; export rGBid; setring save; return(@RAT); // kill @RAT; // return(G); } example { "EXAMPLE:"; echo = 2; ring r = (0,c),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp); // this ordering is an antiblock ordering, as it must be def S = Weyl(); setring S; // the ideal I below annihilates parametric Appel F4 function // where we set parameters to a=-2, b=-1 and d=0 ideal I = x*Dx*(x*Dx+c-1) - x*(x*Dx+y*Dy-2)*(x*Dx+y*Dy-1), y*Dy*(y*Dy-1) - y*(x*Dx+y*Dy-2)*(x*Dx+y*Dy-1); int is = 2; // hence 1st and 2nd variables, that is x and y // will become invertible in the localization def A = ratstd(I,2); // main call pGBid; // polynomial form of the basis in the localized ring setring A; // A is a commutative ring used for presentation rGBid; // "rational" or "localized" form of the basis //--- Now, let us compute a K(x,y) basis explicitly print(matrix(kbase(rGBid))); } /* oldExampleForDoc() { // VL: removed since it's too easy ring r = 0,(k,n,K,N),(a(0,0,1,1),a(0,0,1,0),dp); // note, that the ordering must be an antiblock ordering matrix D[4][4]; D[1,3] = K; D[2,4] = N; def S = nc_algebra(1,D); setring S; // S is the 2nd shift algebra ideal I = (k+1)*K - (n-k), (n-k+1)*N - (n+1); int is = 2; // hence 1..2 variables will be treated as invertible def A = ratstd(I,is); pGBid; // polynomial form setring A; rGBid; // rational form } */ /* exParamAppelF4() { // Appel F4 LIB "ratgb.lib"; ring r = (0,a,b,c,d),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp); matrix @D[4][4]; @D[1,3]=1; @D[2,4]=1; def S=nc_algebra(1,@D); setring S; ideal I = x*Dx*(x*Dx+c-1) - x*(x*Dx+y*Dy+a)*(x*Dx+y*Dy+b), y*Dy*(y*Dy+d-1) - y*(x*Dx+y*Dy+a)*(x*Dx+y*Dy+b); def A = ratstd(I,2); pGBid; // polynomial form setring A; rGBid; // rational form // hence, the K(x,y) basis is {1,Dx,Dy,Dy^2} } // more examples: // F1 is hard appel F1 { LIB "dmodapp.lib"; LIB "ratgb.lib"; def A = appelF1(); setring A; IAppel1; def F1 = ratstd(IAppel1,2); lead(pGBid); setring F1; rGBid; } // F2 is much easier appel F2 { LIB "dmodapp.lib"; LIB "ratgb.lib"; def A = appelF2(); setring A; IAppel2; def F1 = ratstd(IAppel2,2); lead(pGBid); setring F1; rGBid; } // F4 is feasible appel F4 { LIB "dmodapp.lib"; LIB "ratgb.lib"; def A = appelF4(); setring A; IAppel4; def F1 = ratstd(IAppel4,2); lead(pGBid); setring F1; rGBid; } */ // Important: example for treating modules // take two annihilators in 2 components /* LIB "nctools.lib"; ring r = (0,c),(x,y,Dx,Dy),(a(0,0,1,1),a(0,0,1,0),dp); // this ordering is an antiblock ordering, as it must be def S = Weyl(); setring S; // the ideal I below annihilates parametric Appel F4 function // where we set parameters to a=-2, b=-1 and d=0 ideal I = x*Dx*(x*Dx+c-1) - x*(x*Dx+y*Dy-2)*(x*Dx+y*Dy-1), y*Dy*(y*Dy-1) - y*(x*Dx+y*Dy-2)*(x*Dx+y*Dy-1); // the ideal J below annihilates parametric Appel F4 function // where we set parameters to a=0, b=-1, c=0, d=0 ideal J = x*Dx*(x*Dx-1) - x*(x*Dx+y*Dy)*(x*Dx+y*Dy-1), y*Dy*(y*Dy-1) - y*(x*Dx+y*Dy)*(x*Dx+y*Dy-1); module M = I*gen(1), J*gen(2); // harder modification: M = M, Dx*gen(1) + Dy*gen(2); // gives K(x,y)-dim 3 int is = 2; // hence 1st and 2nd variables, that is x and y // will become invertible in the localization def A = ratstd(M,2); // main call pGBid; // polynomial form of the basis in the localized ring setring A; // we see from computations, that the K(x,y) dimension is 8 rGBid; // "rational" or "localized" form of the basis print(matrix(kbase(rGBid)));// we see the K(x,y) basis of the corr. module */ singular-4.0.3+ds/Singular/LIB/realclassify.lib000066400000000000000000000462231266270727000213270ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version realclassify.lib 4.0.0.0 Jun_2013 "; // $Id: 304c900973a128db7524e71def15982bf895ee09 $ category="Singularities"; info=" LIBRARY: realclassify.lib Classification of real singularities AUTHOR: Magdaleen Marais, magdaleen@aims.ac.za Andreas Steenpass, steenpass@mathematik.uni-kl.de OVERVIEW: A library for classifying isolated hypersurface singularities over the reals w.r.t. right equivalence, based on the determinator of singularities by V.I. Arnold. This library is based on classify.lib by Kai Krueger, but handles the real case, while classify.lib does the complex classification. REFERENCES: Arnold, Varchenko, Gusein-Zade: Singularities of Differentiable Maps. Vol. 1: The classification of critical points caustics and wave fronts. Birkh\"auser, Boston 1985 Greuel, Lossen, Shustin: Introduction to singularities and deformations. Springer, Berlin 2007 PROCEDURES: realclassify(f); real classification of singularities of modality 0 and 1 realmorsesplit(f); splitting lemma in the real case milnornumber(f); Milnor number determinacy(f); an upper bound for the determinacy "; LIB "linalg.lib"; LIB "elim.lib"; LIB "primdec.lib"; LIB "classify.lib"; LIB "rootsur.lib"; LIB "rootsmr.lib"; LIB "atkins.lib"; LIB "solve.lib"; /////////////////////////////////////////////////////////////////////////////// proc realclassify(poly f, list #) " USAGE: realclassify(f[, format]); f poly, format string RETURN: A list containing (in this order) @* - the type of the singularity as a string, @* - the normal form, @* - the corank, the Milnor number, the inertia index and a bound for the determinacy as integers. @* The normal form involves parameters for singularities of modality greater than 0. The actual value of the parameters is not computed in most of the cases. If the value of the parameter is unknown, the normal form is given as a string with an \"a\" as the parameter. Otherwise, it is given as a polynomial. @* An optional string @code{format} can be provided. Its default value is \"short\" in which case the return value is the list described above. If set to \"nice\", a string is added at the end of this list, containing the result in a more readable form. NOTE: The classification is done over the real numbers, so in contrast to classify.lib, the signs of coefficients of monomials where even exponents occur matter. @* The ground field must be Q (the rational numbers). No field extensions of any kind nor floating point numbers are allowed. @* The monomial order must be local. @* The input polynomial must be contained in maxideal(2) and must be an isolated singularity of modality 0 or 1. The Milnor number is checked for being finite. SEE ALSO: classify KEYWORDS: Classification of singularities EXAMPLE: example realclassify; shows an example" { /* auxiliary variables */ int i, j; /* name for the basering */ def br = basering; /* read optional parameters */ int printcomments; if(size(#) > 0) { if(size(#) > 1 || typeof(#[1]) != "string") { ERROR("Wrong optional parameters."); } if(#[1] != "short" && #[1] != "nice") { ERROR("Wrong optional parameters."); } if(#[1] == "nice") { printcomments = 1; } } /* error check */ if(charstr(br) != "0") { ERROR("The ground field must be Q (the rational numbers)."); } int n = nvars(br); for(i = 1; i <= n; i++) { if(var(i) > 1) { ERROR("The monomial order must be local."); } } if(jet(f, 1) != 0) { ERROR("The input polynomial must be contained in maxideal(2)."); } /* compute Milnor number before continuing the error check */ int mu = milnornumber(f); /* continue error check */ if(mu < 1) { ERROR("The Milnor number of the input polynomial must be"+newline +"positive and finite."); } /* call classify before continuing the error check */ list dataFromClassify = prepRealclassify(f); int m = dataFromClassify[1]; // the modality of f string complextype = dataFromClassify[2]; // the complex type of f /* continue error check */ if(m > 1) { ERROR("The input polynomial must be a singularity of modality 0 or 1."); } /* apply splitting lemma */ list morse = realmorsesplit(f, mu); int cr = morse[1]; int lambda = morse[2]; int d = morse[3]; poly rf = morse[4]; /* determine the type */ string typeofsing; poly nf; poly monparam; // the monomial whose coefficient is the parameter // in the modality 1 cases, 0 otherwise string morecomments = newline; if(cr == 0) // case A[1] { typeofsing, nf = caseA1(rf, lambda, n); } if(cr == 1) // case A[k], k > 1 { typeofsing, nf = caseAk(rf, n); } if(cr == 2) { if(complextype[1,2] == "D[") // case D[k] { if(mu == 4) // case D[4] { typeofsing, nf = caseD4(rf); } else // case D[k], k > 4 { typeofsing, nf = caseDk(rf, mu); } } if(complextype == "E[6]") // case E[6] { typeofsing, nf = caseE6(rf); } if(complextype == "E[7]") // case E[7] { typeofsing, nf = caseE7(); } if(complextype == "E[8]") // case E[8] { typeofsing, nf = caseE8(); } if(typeofsing == "") { ERROR("This case is not yet implemented."); } } if(cr > 2) { ERROR("This case is not yet implemented."); } /* add the non-corank variables to the normal forms */ nf = addnondegeneratevariables(nf, lambda, cr); /* write normal form as a string in the cases with modality greater than 0 */ if(monparam != 0) { poly nf_tmp = nf; kill nf; def nf = modality1NF(nf_tmp, monparam); } /* write comments */ if(printcomments) { string comments = newline; comments = comments+"Type of singularity: " +typeofsing +newline +"Normal form: " +string(nf) +newline +"Corank: " +string(cr) +newline +"Milnor number: " +string(mu) +newline +"Inertia index: " +string(lambda)+newline +"Determinacy: <= "+string(d) +newline; if(morecomments != newline) { comments = comments+morecomments; } } /* return results */ if(printcomments) { return(list(typeofsing, nf, cr, mu, lambda, d, comments)); } else { return(list(typeofsing, nf, cr, mu, lambda, d)); } } example { "EXAMPLE:"; echo = 2; ring r = 0, (x,y,z), ds; poly f = (x2+3y-2z)^2+xyz-(x-y3+x2z3)^3; realclassify(f, "nice"); } /////////////////////////////////////////////////////////////////////////////// static proc caseA1(poly rf, int lambda, int n) { string typeofsing = "A[1]"; poly nf = 0; return(typeofsing, nf); } /////////////////////////////////////////////////////////////////////////////// static proc caseAk(poly rf, int n) { /* preliminaries */ string typeofsing; poly nf; int k = deg(lead(rf), 1:n)-1; if(k%2 == 0) { nf = var(1)^(k+1); typeofsing = "A["+string(k)+"]"; } else { if(leadcoef(rf) > 0) { nf = var(1)^(k+1); typeofsing = "A["+string(k)+"]+"; } else { nf = -var(1)^(k+1); typeofsing = "A["+string(k)+"]-"; } } return(typeofsing, nf); } /////////////////////////////////////////////////////////////////////////////// static proc caseD4(poly rf) { /* preliminaries */ string typeofsing; poly nf; def br = basering; map phi; rf = jet(rf, 3); number s1 = number(rf/(var(1)^3)); number s2 = number(rf/(var(2)^3)); if(s2 == 0 && s1 != 0) { phi = br, var(2), var(1); rf = phi(rf); } if(s1 == 0 && s2 == 0) { number t1 = number(rf/(var(1)^2*var(2))); number t2 = number(rf/(var(2)^2*var(1))); if(t1+t2 == 0) { phi = br, var(1)+2*var(2), var(2); rf = phi(rf); } else { phi = br, var(1)+var(2), var(2); rf = phi(rf); } } ring R = 0, y, dp; map phi = br, 1, y; poly rf = phi(rf); int k = nrroots(rf); setring(br); if(k == 3) { nf = var(1)^2*var(2)-var(2)^3; typeofsing = "D[4]-"; } else { nf = var(1)^2*var(2)+var(2)^3; typeofsing = "D[4]+"; } return(typeofsing, nf); } /////////////////////////////////////////////////////////////////////////////// static proc caseDk(poly rf, int mu) { /* preliminaries */ string typeofsing; poly nf; def br = basering; map phi; rf = jet(rf, mu-1); list factorization = factorize(jet(rf, 3)); list factors = factorization[1][2]; if(factorization[2][2] == 2) { factors = insert(factors, factorization[1][3], 1); } else { factors = insert(factors, factorization[1][3]); } factors[2] = factorization[1][1]*factors[2]; matrix T[2][2] = factors[1]/var(1), factors[1]/var(2), factors[2]/var(1), factors[2]/var(2); phi = br, luinverse(T)[2]*matrix(ideal(var(1), var(2)), 2, 1); rf = phi(rf); rf = jet(rf, mu-1); poly g; int i; for(i = 4; i < mu; i++) { g = jet(rf, i) - var(1)^2*var(2); if(g != 0) { phi = br, var(1)-(g/(var(1)*var(2)))/2, var(2)-(g/var(1)^i)*var(1)^(i-2); rf = phi(rf); rf = jet(rf, mu-1); } } number a = number(rf/var(2)^(mu-1)); if(a > 0) { typeofsing = "D["+string(mu)+"]+"; nf = var(1)^2*var(2)+var(2)^(mu-1); } else { typeofsing = "D["+string(mu)+"]-"; nf = var(1)^2*var(2)-var(2)^(mu-1); } return(typeofsing, nf); } /////////////////////////////////////////////////////////////////////////////// static proc caseE6(poly rf) { /* preliminaries */ string typeofsing; poly nf; def br = basering; map phi; poly g = jet(rf,3); number s = number(g/(var(1)^3)); if(s == 0) { phi = br, var(2), var(1); rf = phi(rf); g = jet(rf,3); } list Factors = factorize(g); poly g1 = Factors[1][2]; phi = br, (var(1)-(g1/var(2))*var(2))/(g1/var(1)), var(2); rf = phi(rf); rf = jet(rf,4); number w = number(rf/(var(2)^4)); if(w > 0) { typeofsing = "E[6]+"; nf = var(1)^3+var(2)^4; } else { typeofsing = "E[6]-"; nf = var(1)^3-var(2)^4; } return(typeofsing, nf); } /////////////////////////////////////////////////////////////////////////////// static proc caseE7() { string typeofsing = "E[7]"; poly nf = var(1)^3+var(1)*var(2)^3; return(typeofsing, nf); } /////////////////////////////////////////////////////////////////////////////// static proc caseE8() { string typeofsing = "E[8]"; poly nf = var(1)^3+var(2)^5; return(typeofsing, nf); } /////////////////////////////////////////////////////////////////////////////// /* print the normal form as a string for the modality 1 cases. The first argument is the normalform with parameter = 1, the second argument is the monomial whose coefficient is the parameter. */ static proc modality1NF(poly nf, poly monparam) { def br = basering; list lbr = ringlist(br); ring r = (0,a), x, dp; list lr = ringlist(r); setring(br); list lr = fetch(r, lr); lbr[1] = lr[1]; def s = ring(lbr); setring(s); poly nf = fetch(br, nf); poly monparam = fetch(br, monparam); nf = nf+(a-1)*monparam; string result = string(nf); setring(br); return(result); } /////////////////////////////////////////////////////////////////////////////// /* add squares of the non-degenerate variables (i.e. var(cr+1), ..., var(nvars(basering)) for corank cr) to the normalform nf, with signs according to the inertia index lambda */ static proc addnondegeneratevariables(poly nf, int lambda, int cr) { int n = nvars(basering); int i; for(i = cr+1; i <= n-lambda; i++) { nf = nf+var(i)^2; } for(i = n-lambda+1; i <= n ; i++) { nf = nf-var(i)^2; } return(nf); } /////////////////////////////////////////////////////////////////////////////// proc realmorsesplit(poly f, list #) " USAGE: realmorsesplit(f[, mu]); f poly, mu int RETURN: a list consisting of the corank of f, the inertia index, an upper bound for the determinacy, and the residual form of f NOTE: The characteristic of the basering must be zero, the monomial order must be local, f must be contained in maxideal(2) and the Milnor number of f must be finite. @* The Milnor number of f can be provided as an optional parameter in order to avoid that it is computed again. SEE ALSO: morsesplit KEYWORDS: Morse lemma; Splitting lemma EXAMPLE: example morsesplit; shows an example" { int i; /* error check */ if(char(basering) != 0) { ERROR("The characteristic must be zero."); } int n = nvars(basering); for(i = 1; i <= n; i++) { if(var(i) > 1) { ERROR("The monomial order must be local."); } } if(jet(f, 1) != 0) { ERROR("The input polynomial must be contained in maxideal(2)."); } /* get Milnor number before continuing error check */ int mu; if(size(#) > 0) // read optional parameter { if(size(#) > 1 || typeof(#[1]) != "int") { ERROR("Wrong optional parameters."); } else { mu = #[1]; } } else // compute Milnor number { mu = milnornumber(f); } /* continue error check */ if(mu < 0) { ERROR("The Milnor number of the input polynomial must be"+newline +"non-negative and finite."); } /* compute the determinacy */ int k = determinacy(f, mu); f = jet(f, k); /* get jet(f, 2) right */ matrix H = concat(jet(jacob(jacob(f)), 0)/2, unitmat(n)); H = sym_reduce(H); intvec perm_zero; intvec perm_neg; intvec perm_pos; int c; int lambda; for(i = 1; i <= n; i++) { if(H[i, i] == 0) { perm_zero = perm_zero, i; c++; } if(H[i, i] < 0) { perm_neg = perm_neg, i; lambda++; } if(H[i, i] > 0) { perm_pos = perm_pos, i; } } intvec perm; if(size(perm_zero) > 1) { perm = perm, perm_zero[2..size(perm_zero)]; } if(size(perm_neg) > 1) { perm = perm, perm_neg[2..size(perm_neg)]; } if(size(perm_pos) > 1) { perm = perm, perm_pos[2..size(perm_pos)]; } perm = perm[2..size(perm)]; matrix T[n][n]; matrix D[1][n]; for(i = 1; i <= n; i++) { T[1..n, i] = H[perm[i], (n+1)..(2*n)]; D[1, i] = H[perm[i], perm[i]]; } map phi = basering, matrix(maxideal(1))*transpose(T); f = phi(f); f = jet(f, k); /* separate the variables */ phi = basering, maxideal(1); map corank_part = basering, maxideal(1); for(i = c+1; i <= n; i++) { corank_part[i] = 0; } poly h = f-jet(f, 2)-corank_part(f); poly hi; while(h != 0) { for(i = c+1; i <= n; i++) { hi = h/var(i); phi[i] = var(i)-hi/(2*D[1, i]); h = h-hi*var(i); } f = phi(f); f = jet(f, k); h = f-jet(f, 2)-corank_part(f); } poly g = f-jet(f, 2); poly lead_g = leadcoef(g); if(lead_g > 0) { g = g/lead_g; } if(lead_g < 0) { g = -g/lead_g; } return(list(c, lambda, k, g)); } example { "EXAMPLE:"; echo = 2; ring r = 0, (x,y,z), ds; poly f = (x2+3y-2z)^2+xyz-(x-y3+x2z3)^3; realmorsesplit(f); } /////////////////////////////////////////////////////////////////////////////// /* symmetric Gauss algorithm If A is not a square matrix, then the largest upper or left submatrix is assumed to be symmetric. */ proc sym_reduce(matrix A) { int r = nrows(A); int c = ncols(A); int n = r; if(n > c) { n = c; } poly q; int i, j; for(i = 1; i <= n; i++) { for(j = i+1; j <= n; j++) { if(A[i, j] != 0) { while(A[i, i] == 0) { A[1..r, i] = A[1..r, i]+A[1..r, j]; A[i, 1..c] = A[i, 1..c]+A[j, 1..c]; } q = A[i, j]/A[i, i]; A[1..r, j] = A[1..r, j]-q*A[1..r, i]; A[j, 1..c] = A[j, 1..c]-q*A[i, 1..c]; } } } return(A); } /////////////////////////////////////////////////////////////////////////////// /* - apply jet(f, k) - rewrite f as f = a*var(i)^2+p*var(i)+r with var(i)-free p and r */ static proc rewriteformorsesplit(poly f, int k, int i) { f = jet(f, k); matrix C = coeffs(f, var(i)); poly r = C[1,1]; poly p = C[2,1]; poly a = (f-r-p*var(i))/var(i)^2; return(f, a, p, r); } /////////////////////////////////////////////////////////////////////////////// proc milnornumber(poly f) " USAGE: milnornumber(f); f poly RETURN: Milnor number of f, or -1 if the Milnor number is not finite KEYWORDS: Milnor number NOTE: The monomial order must be local. EXAMPLE: example milnornumber; shows an example" { /* error check */ int i; for(i = nvars(basering); i > 0; i--) { if(var(i) > 1) { ERROR("The monomial order must be local."); } } return(vdim(std(jacob(f)))); } example { "EXAMPLE:"; echo = 2; ring r = 0, (x,y), ds; poly f = x3+y4; milnornumber(f); } /////////////////////////////////////////////////////////////////////////////// proc determinacy(poly f, list #) " USAGE: determinacy(f[, mu]); f poly, mu int RETURN: an upper bound for the determinacy of f NOTE: The characteristic of the basering must be zero, the monomial order must be local, f must be contained in maxideal(1) and the Milnor number of f must be finite. @* The Milnor number of f can be provided as an optional parameter in order to avoid that it is computed again. SEE ALSO: milnornumber, highcorner KEYWORDS: Determinacy EXAMPLE: example determinacy; shows an example" { /* auxiliary variables */ int i; def br = basering; /* error check */ if(char(br) != 0) { ERROR("The characteristic must be zero."); } int n = nvars(br); for(i = 1; i <= n; i++) { if(var(i) > 1) { ERROR("The monomial order must be local."); } } if(jet(f, 0) != 0) { ERROR("The input polynomial must be contained in maxideal(1)."); } /* get Milnor number before continuing error check */ int mu; if(size(#) > 0) // read optional parameter { if(size(#) > 1 || typeof(#[1]) != "int") { ERROR("Wrong optional parameters."); } else { mu = #[1]; } } else // compute Milnor number { mu = milnornumber(f); } /* continue error check */ if(mu < 0) { ERROR("The Milnor number of the input polynomial must be"+newline +"non-negative and finite."); } int k; // an upper bound for the determinacy, // we use several methods: /* Milnor number */ k = mu+1; f = jet(f, k); /* highest corner */ int hc; if(ordstr(br) != "ds") { list lbr = ringlist(br); lbr[3] = list(list("ds", 1:nvars(br)), list("C", 0)); def br_ds = ring(lbr); setring(br_ds); poly f = fetch(br, f); } for(i = 0; i < 3; i++) { hc = deg(highcorner(std(maxideal(i)*jacob(f)))); hc = hc+2-i; if(hc < k) { k = hc; f = jet(f, k); } } if(ordstr(br) != "ds") { setring(br); } return(k); } example { "EXAMPLE:"; echo = 2; ring r = 0, (x,y), ds; poly f = x3+xy3; determinacy(f); } singular-4.0.3+ds/Singular/LIB/realizationMatroids.lib000066400000000000000000000503011266270727000226620ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////// version="version realizationMatroids.lib 4.0.0.0 Jun_2013 "; // $Id: 7c61e151b8c5acb9a757122ac09105728e170fb5 $ category="Tropical Geometry"; info=" LIBRARY: realizationMatroids.lib Deciding Relative Realizability for Tropical Fan Curves in 2-Dimensional Matroidal Fans AUTHORS: Anna Lena Winstel, winstel@mathematik.uni-kl.de OVERVIEW: In tropical geometry, one question to ask is the following: given a one-dimensional balanced polyhedral fan C which is set theoretically contained in the tropicalization trop(Y) of an algebraic variety Y, does there exist a curve X in Y such that trop(X) = C? This equality of C and trop(X) denotes an equality of both, the fans trop(X) and C and their weights on the maximal cones. The relative realization space of C with respect to Y is the space of all algebraic curves in Y which tropicalize to C. This library provides procedures deciding relative realizability for tropical fan curves, i.e. one-dimensional weighted balanced polyhedral fans, contained in two-dimensional matroidal fans trop(Y) where Y is a projective plane. NOTATION: If Y is a projective plane in (n-1)-dimensional projective space, we consider trop(Y) in R^n/<1>. Moreover, for the relative realization space of C with respect to Y we only consider algebraic curves of degree deg(C) in Y which tropicalize to C. PROCEDURES: realizationDim(I,C); For a given tropical fan curve C in trop(Y), where Y = V(I) is a projective plane, this routine returns the dimension of the relative realization space of C with respect to Y, that is the space of all algebraic curves of degree deg(C) in Y which tropicalize to C. If the realization space is empty, the output is set to -1. irrRealizationDim(I,C); This routine returns the dimension of the irreducible relative realization space of the tropical fan curve C with respect to Y = V(I), that is the space of all irreducible algebraic curves of degree deg(C) in Y which tropicalize to C. If the irreducible relative realization space is empty, the output is set to -1. realizationDimPoly(I,C); If C is a tropical fan curve contained in the tropicalization trop(Y) of the projective plane Y = V(I) such that the relative realization space M of C is non-empty, this routine returns the tuple (dim(M),f) where f is an example of a homogeneous polynomial of degree deg(C) cutting out a curve X in Y which tropicalizes to C. If M is empty, the output is set to -1. "; LIB "control.lib"; LIB "qhmoduli.lib"; static proc gcdvector(intvec v) { int i; int ggt = 0; for(i=1;i<=size(v);i++) { ggt = gcd(ggt,v[i]); if( ggt == 1 ) { return(ggt); } } return(ggt); } static proc balanced(list lInput) { list ba; int i; int j; if(size(lInput)>0) { for(i=1;i<=size(lInput[1]);i++) { ba[i] = 0; for(j=1;j<=size(lInput);j++) { ba[i] = ba[i] + lInput[j][i]; } } int boolean = 1; for(i=2;i<=size(ba);i++) { if(ba[i] != ba[1]) { boolean = 0; } } if(boolean == 1) { return(ba[1]); } else { return(0); } } else { return(0); } } static proc genPoly(int d, int i, int j, int k) { int ii; int ij; int ik = 1; poly f = 0; for(ii=0;ii<=d;ii++) { for(ij=0;ij<=d-ii;ij++) { f = f + a(ik)*x(i)^(d-ii-ij)*x(j)^ij*x(k)^ii; ik = ik + 1; } } return(f); } static proc prodvar(int n) { int i; poly f = 1; for(i=1;i<=n;i++) { f = f * x(i); } return(f); } static proc lessThan(int i, int j, intvec v, intvec w) { number a = v[i]; number b = v[j]; number c = w[i]; number d = w[j]; if((a/b)<(c/d)) { return(1); } else { return(0); } } static proc sortSlope(int i, int j, list lInput) { int k; int l; intvec v; for(k=1;k can be written as [w] = m*[v] where [v] is the primitive generator of K and m is the weight of K. RETURNS: the dimension of the relative realization space of the tropical curve C with respect to Y, and -1 if the relative realization space is empty. EXAMPLE: realizationDim; shows an example" { int ret = list(realizationDimIdeal(iInput,lInput))[1]; if(ret[1] == -2) { printf("WARNING: no computation possible, return value is not meaningful!"); return(-2); } else { return(ret); } } example { "EXAMPLE:"; echo=2; ring r = 0,(x(1..4)),dp; ideal I = x(1)+x(2)+x(3)+x(4); list C = list(intvec(2,2,0,0),intvec(0,0,2,1),intvec(0,0,0,1)); //C represents the tropical fan curve which consists of the cones //cone([(1,1,0,0)]) (with weight 2), cone([(0,0,2,1)]) (with weight 1) //and cone([(0,0,0,1)]) (with weight 1) realizationDim(I,C); } proc irrRealizationDim(ideal iInput, list lInput) "USAGE: irrRealizationDim(I,C); where I is a homogeneous linear ideal defining the projective plane Y = V(I) and C is a list of intvectors such that each intvector represents a one-dimensional cone in the tropical fan curve whose irreducible relative realizability should be checked. This representation is done in the following way: a one-dimensional cone K is represented by a vector w whose equivalence class [w] in R^n/<1> can be written as [w] = m*[v] where [v] is the primitive generator of K and m is the weight of K. RETURNS: the dimension of the irreducible relative realization space of C with respect to Y, and -1 if the irreducible realization space is empty. EXAMPLE: irrRealizationDim; shows an example" { int i; int i_dim = realizationDim(iInput,lInput); if(i_dim > -1) { //check if also realizable by an irreducible curve list lweight; int i_rdim = -1; //substitute the vectors by a primitve one and store the multiplicities for(i=1;i<=size(lInput);i++) { lweight[i] = gcdvector(lInput[i]); lInput[i] = lInput[i] div lweight[i]; } //find all decompositions into two tropical curves intvec tm; for(i=1;i<=size(lInput);i++) { tm[i] = 0; } int na; list C1; list C2; int dimC1; int dimC2; while(na==0) { na = 1; for(i=1;i<=size(lInput);i++) { if(tm[i] < lweight[i]) { tm[i] = tm[i]+1; na = 0; i = size(lInput); } else { tm[i] = 0; } } if(na == 0) { C1 = list(); C2 = list(); for(i=1;i<=size(lInput);i++) { if(tm[i] > 0) { C1 = C1 + list(tm[i]*lInput[i]); if(tm[i] < lweight[i]) { C2 = C2 + list((lweight[i]-tm[i])*lInput[i]); } } else { C2 = C2 + list(lweight[i]*lInput[i]); } } if((balanced(C2) != 0) and (balanced(C2) <= balanced(C1))) { dimC1 = realizationDim(iInput,C1); dimC2 = realizationDim(iInput,C2); if((dimC1 >= 0) and (dimC2 >= 0)) { i_rdim = Max(intvec(i_rdim,dimC1 + dimC2)); } } } } if(i_rdim < i_dim) { return(i_dim); } else { return(-1); } } else { return(-1); } } example { "EXAMPLE:"; echo=2; ring r = 0,(x(1..4)),dp; ideal I = x(1)+x(2)+x(3)+x(4); list C = list(intvec(2,2,0,0),intvec(0,0,2,2)); //C represents the tropical fan curve which consists of the cones //cone([(1,1,0,0)]) and cone([(1,1,0,0)]), both with weight 2 realizationDim(I,C); irrRealizationDim(I,C); } proc realizationDimPoly(ideal iInput, list lInput) "USAGE: realizationDimPoly(I,C); where I is a homogeneous linear ideal defining the projective plane Y = V(I) and C is a list of intvectors such that each intvector represents a one-dimensional cone in the tropical fan curve whose relative realizability should be checked. This representation is done in the following way: the one-dimensional cone K is represented by a vector w whose equivalence class [w] in R^n/<1> can be written as [w] = m*[v] where [v] is the primitive generator of K and m is the weight of K. RETURNS: If the relative realization space of the tropical fan curve C is non-empty, this routine returns the tuple (r,f), where r is the dimension of the relative realization space and f is an example of a homogeneous polynomial of degree deg(C) cutting out a curve X in Y which tropicalizes to C. In case the relative realization space is empty, the output is set to -1. EXAMPLE: realizationDimPoly; shows an example" { def save = basering; int d = balanced(lInput); int n = size(lInput[1]); int N = (d+2)*(d+1) div 2; int i; ring r = 0,(x(1..n),a(1..N)),dp; list ret = realizationDimIdeal(fetch(save,iInput),lInput); int realdim = ret[1]; if(realdim != -1) { ideal E = ret[2]; list NE = ret[3]; E = std(E); //find variables which are free to choose intvec v; for(i=1;i<=size(E);i++) { v = v + leadexp(E[i]); } int j; int k; int boolean; ideal E1; list NE1; poly f; poly g; //initialize the list of the free variables list lValues; if(size(v) > 1) { for(j=1;j<=N;j++) { if(v[j+n] == 0) { lValues = lValues + list(list(a(j),0)); } } } else { for(j=1;j<=N;j++) { lValues = lValues + list(list(a(j),0)); } } //try to find an easy solution boolean = 1; for(j=1;j<=size(lValues);j++) { if(boolean == 1) { lValues[j][2] = 0; } else { lValues[j][2] = lValues[j][2] + 1; } boolean = 1; E1 = E; for(i=1;i<=size(E1);i++) { for(k=1;k<=j;k++) { E1[i] = subst(E1[i],lValues[k][1],lValues[k][2]); } } NE1 = NE; for(i=1;i<=size(NE);i++) { for(k=1;k<=j;k++) { NE1[i] = subst(NE1[i],lValues[k][1],lValues[k][2]); } } E1 = std(E1); for(i=1;i<=size(NE1);i++) { if(reduce(NE1[i],E1) == 0) { boolean = 0; } } if(boolean == 0) { j = j-1; } } //compute the values of the dependent variables for(j=1;j<=size(E);j++) { f = E[j]; for(k=1;k<=size(lValues);k++) { f = subst(f,lValues[k][1],lValues[k][2]); } if(leadcoef(f) != 1) { for(k=1;k<=size(lValues);k++) { lValues[k][2] = lValues[k][2] * leadcoef(f); } } f = subst(f,leadmonom(f),0); lValues = lValues + list(list(leadmonom(E[j]),-f)); } g = genPoly(d,ret[4][1],ret[4][2],ret[4][3]); for(j=1;j<=N;j++) { g = subst(g,lValues[j][1],lValues[j][2]); } setring save; return(realdim,fetch(r,g)); } else { return(-1); } } example { "EXAMPLE:"; echo=2; ring r = 0,(x(1..4)),dp; ideal I = x(1)+x(2)+x(3)+x(4); list C = list(intvec(2,2,0,0),intvec(0,0,2,2)); //C represents the tropical fan curve which consists of the cones //cone([(1,1,0,0)]) and cone([(1,1,0,0)]), both with weight 2 realizationDimPoly(I,C); C = list(intvec(0,0,0,4),intvec(0,1,3,0),intvec(1,0,1,0),intvec(0,2,0,0),intvec(3,1,0,0)); //C represents the tropical fan curve which consists of the cones //cone([(0,0,0,1)]) with weight 4, //cone([(0,1,3,0)]), cone([(1,0,1,0)]) both with weight 1, //cone([(0,1,0,0)]) with weight 2, and //cone([(3,1,0,0)]) with weight 1 realizationDimPoly(I,C); } singular-4.0.3+ds/Singular/LIB/realrad.lib000066400000000000000000000640131266270727000202550ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version realrad.lib 4.0.0.0 Jun_2013 "; // $Id: b275d949fd627253e5d17a85b63c4ebd815a42ed $ category="real algebra"; info=" LIBRARY: realrad.lib Computation of real radicals AUTHOR : Silke Spang OVERVIEW: Algorithms about the computation of the real radical of an arbitary ideal over the rational numbers and transcendetal extensions thereof PROCEDURES: realpoly(f); Computes the real part of the univariate polynomial f realzero(j); Computes the real radical of the zerodimensional ideal j realrad(j); Computes the real radical of an arbitary ideal over transcendental extension of the rational numbers "; LIB "inout.lib"; LIB "poly.lib"; LIB "matrix.lib"; LIB "general.lib"; LIB "rootsur.lib"; LIB "algebra.lib"; LIB "standard.lib"; LIB "primdec.lib"; LIB "elim.lib"; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// //// the main procedure ////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// proc realrad(ideal id) "USAGE: realrad(id), id an ideal of arbitary dimension RETURN: the real radical of id EXAMPE: example realrad; shows an example" { def r=basering; int n=nvars(basering); // for faster Groebner basis and dimension compuations string neuring ="ring schnell=("+charstr(r)+"),("+varstr(r)+"),dp;"; execute(neuring); def ri=basering; list reddim;//reduct dimension to 0 list lpar,lvar,sub;//for the ringchange string pari,vari; int i,siz,l,j; string less="list lessvar="+varstr(r)+";"; execute(less); ideal id=imap(r,id); l=size(id); for (i=1;i<=l;i++) { id[i]=simplify_gen(id[i]); } id=groebner(id); if (dim(id)<=0) { id=realzero(id); setring r; id=imap(ri,id); return(id); } //sub are the subsets of {x_1,...,x_n} sub=subsets(n); siz=size(sub)-1;//we dont want to localize on all variables //for the empty set reddim[1]=zeroreduct(id); reddim[1]=realzero(reddim[1]); for (i=1;i<=siz;i++) { lvar=lessvar; lpar=list(); l=size(sub[i]); for (j=1;j<=l;j++) { lpar=lpar+list(lvar[sub[i][j]-j+1]); lvar=delete(lvar,sub[i][j]-j+1); } for(j=1;j<=l;j++)//there are l entries in lpar { pari=pari+","+string(lpar[j]); } l=n-l;//there are the remaining n-l entries in lvar for(j=1;j<=l;j++)//there are l entries in lpar { vari=vari+","+string(lvar[j]); } vari=vari[2..size(vari)]; neuring="ring neu=("+charstr(r)+pari+"),("+vari+"),dp;"; execute(neuring); ideal id=imap(r,id); ideal buffer=zeroreduct(id); buffer=realzero(buffer); setring ri; reddim[i+1]=imap(neu,buffer); kill neu; //compute the intersection of buffer with r reddim[i+1]=contnonloc(reddim[i+1],pari,vari); vari=""; pari=""; } id=intersect(reddim[1..(siz+1)]); //id=timeStd(id,301);//simplify the output id=interred(id); // timeStd does not work yet setring r; id=imap(ri,id); return(id); } example { "EXAMPLE:"; echo = 2; ring r1=0,(x,y,z),lp; //dimension 0 ideal i0=(x2+1)*(x3-2),(y3-2)*(y2+y+1),z3+2; //dimension 1 ideal i1=(y3+3y2+y+1)*(y2+4y+4)*(x2+1),(x2+y)*(x2-y2)*(x2+2xy+y2)*(y2+y+1); ideal i=intersect(i0,i1); realrad(i); } /*static*/ proc zeroreduct(ideal i) "USAGE:zeroreduct(i), i an arbitary ideal RETURN: an ideal j of dimension <=0 s.th. i is contained in j and j is contained in i_{Iso} which is the zariski closure of all real isolated points of i " { list equi; int d,n,di; n=nvars(basering); def r=basering; //chance ring to get faster groebner bases computation for dimensions string rneu="ring neu=("+charstr(r)+"),("+varstr(r)+"),dp;"; execute(rneu); ideal i=imap(r,i); i=groebner(i); while (dim(i)> 0) { equi=equidim(i); d=size(equi); equi[d]=radical(equi[d]); di=dim(std(equi[d])); equi[d]=equi[d],minor(jacob(equi[d]),n-di); equi[d]=radical(equi[d]); i=intersect(equi[1..d]); i=groebner(i); } setring r; i=imap(neu,i); //i=timeStd(i,301); i=interred(i); // timeStd does not work yet return(i); } ////////////////////////////////////////////////////////////////////////////// ///////the zero-dimensional case ///////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// proc realzero(ideal j) "USAGE: realzero(j); a zero-dimensional ideal j RETURN: j: a zero dimensional ideal, which is the real radical of i, if dim(i)=0 0: otherwise this acts via primary decomposition (i=1) listdecomp (i=2) or facstd (i=3) EXAMPLE: example realzero; shows an example" { list prim,prepared,nonshape,realu; int r;//counter int l;//number of first polynomial with degree >1 or even l=size(j); for (r=1;r<=l;r++) { j[r]=simplify_gen(j[r]); if (j[r]==1) { return(ideal(1)); } } option(redSB); //j=groebner(j); //special case //if (j==1) //{ // return(j); //} if (nvars(basering)==1) { j=groebner(j); j=realpoly(j[1]); return(j); } //if (dim(j)>0) {return(0);} def r_alt=basering; //store the ring //for a ring chance to the ordering lp; execute("ring r_neu =("+charstr(basering)+"),("+varstr(basering)+"),lp;"); setring r_neu; ideal boeser,max; prepared[1]=ideal(1); ideal j=imap(r_alt,j); //ideal j=fglm(r_alt,j); prim=primdecGTZ(j); for (r=1;r<=size(prim);r++) { max=prim[r][2]; max=groebner(max); realu=prepare_max(max); max=realu[1]; if (max!=1) { if (realu[2]==1) { prepared=insert(prepared,max); } else { nonshape=insert(nonshape,max); } } } j=intersect(prepared[1..size(prepared)]); //use a variable change into general position to obtain //the shape via radzero if (size(nonshape)>0) { boeser=GeneralPos(nonshape); j=intersect(j,boeser); } //j=timeStd(j,301); j=interred(j); // timeStd does not work yet setring r_alt; j=fetch(r_neu,j); return(j); } example { "EXAMPLE:"; echo = 2; //in non parametric fields ring r=0,(x,y),dp; ideal i=(y3+3y2+y+1)*(y2+4y+4)*(x2+1),(x2+y)*(x2-y2)*(x2+2xy+y2)*(y2+y+1); realzero(i); ideal j=(y3+3y2+y+1)*(y2-2y+1),(x2+y)*(x2-y2); realzero(j); //to get every path ring r1=(0,t),(x,y),lp; ideal m1=x2+1-t,y3+t2; ideal m2=x2+t2+1,y2+t; ideal m3=x2+1-t,y2-t; ideal m4=x^2+1+t,y2-t; ideal i=intersect(m1,m2,m3,m4); realzero(i); } static proc GeneralPos(list buffer) "USAGE: GeneralPos(buffer); buffer a list of maximal ideals which failed the prepare_max-test RETURN: j: the intersection of their realradicals EXAMPLE: example radzero; shows no example" { def r=basering; int n,ll; //for the mapping in general position map phi,psi; ideal j; ideal jmap=randomLast(20); string ri; intvec @hilb; ideal trans,transprep;// the transformation ideals int nva=nvars(r); int zz,k,l;//counter poly randp; for (zz=1;zz0) { randp=randp+(random(0,5)*par(1)+random(0,5)*par(1)^2+random(0,5))*var(zz); } else { randp=randp+random(0,5)*var(zz); } } randp=randp+var(nva); //now they are all irreducible in the non univariate case and //real in the univariate case int m=size(buffer); for (l=1;l<=m;l++) { //searching first non univariate polynomial with an even degree //for odd degree we could use the fundamental theorem of algebra and //get real zeros //this will act via a coordinate chance into general position //denote that this random chance doesn't work allways //the ideas for the transformation into general position are //used from the primdec.lib transprep=buffer[l]; if (voice>=10) { jmap[size(jmap)]=randp; } for (k=2;k<=n;k++) { if (ord(buffer[l][k])==1) { for (zz=1;zz<=nva;zz++) { if (lead(buffer[l][k])/var(zz)!=0) { transprep[k]=var(zz); } } jmap[nva]=subst(jmap[nva],lead(buffer[l][k]),0); } } phi =r,jmap; for (k=1;k<=nva;k++) { jmap[k]=-(jmap[k]-2*var(k)); } psi =r,jmap; //coordinate chance trans=phi(transprep); //acting with the chanced ideal trans=groebner(trans); trans[1]=realpoly(trans[1]); //special case if (trans==1) { buffer[l]=trans; } else { ri="ring rhelp=("+charstr(r)+ "),(" +varstr(r)+ ",@t),dp;"; execute(ri); ideal trans=homog(imap(r,trans),@t); ideal trans1=std(trans); @hilb=hilb(trans1,1); ri= "ring rhelp1=(" +charstr(r)+ "),(" +varstr(rhelp)+ "),lp;"; execute(ri); ideal trans=homog(imap(r,trans),@t); kill rhelp; trans=std(trans,@hilb); trans=subst(trans,@t,1);//dehomogenising setring r; trans=imap(rhelp1,trans); kill rhelp1; trans=std(trans); attrib(trans,"isSB",1); trans=realzero(trans); //going back buffer[l]=psi(trans); //buffer[l]=timeStd(buffer[l],301);//timelimit for std computation buffer[l]=interred(buffer[l]);//timeStd does not work yet } } //option(returnSB); j=intersect(buffer[1..m]); return(j); } /*proc minAssReal(ideal i, int erg) { int l,m,d,e,r,fac; ideal buffer,factor; list minreal; l=size(i); for (r=1;r<=l;r++) { i[r]=simplify_gen(i[r]); } list pr=primdecGTZ(i); m=size(pr); for (l=1;l<=m;l++) { d=dim(std(pr[l][2])); buffer=realrad(pr[l][2]); buffer=std(buffer); e=dim(buffer); if (d==e) { minreal=minreal+list(pr[l]); } } if (erg==0) { return(minreal); } else { pr=list(); m=size(minreal); for (l=1;l<=m;l++) { pr=insert(pr,minreal[l][2]); } i=intersect(pr[1..m]); //i=timeStd(i,301); i=interred(i);//timeStd does not work yet list realmin=minreal+list(i); return(realmin); } }*/ ////////////////////////////////////////////////////////////////////////////// ///////the univariate case /////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// proc realpoly(poly f) "USAGE: realpoly(f); a univariate polynomial f; RETURN: poly f, where f is the real part of the input f EXAMPLE: example realpoly; shows an example" { def r=basering; int tester; if (size(parstr(r))!=0) { string changering="ring rneu=0,("+parstr(r)+","+varstr(r)+"),lp"; execute(changering); poly f=imap(r,f); tester=1; } f=simplify(f,1);//wlog f is monic if (f==1) { setring r; return(f); } ideal j=factorize(f,1);//for getting the squarefree factorization poly erg=1; for (int i=1;i<=size(j);i=i+1) { if (is_real(j[i])==1) {erg=erg*j[i];} //we only need real primes } if (tester==1) { setring(r); poly erg=imap(rneu,erg); } return(erg); } example { "EXAMPLE:"; echo = 2; ring r1 = 0,x,dp; poly f=x5+16x2+x+1; realpoly(f); realpoly(f*(x4+2)); ring r2=0,(x,y),dp; poly f=x6-3x4y2 + y6 + x2y2 -6y+5; realpoly(f); ring r3=0,(x,y,z),dp; poly f=x4y4-2x5y3z2+x6y2z4+2x2y3z-4x3y2z3+2x4yz5+z2y2-2z4yx+z6x2; realpoly(f); realpoly(f*(x2+y2+1)); } /////////////////////////////////////////////////////////////////////////////// //// for semi-definiteness///////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc decision(poly f) " USAGE: decission(f); a multivariate polynomial f in Q[x_1,..,x_n] and lc f=0 RETURN: assume that the basering has a lexicographical ordering, 1 if f is positive semidefinite 0 if f is indefinite EXAMPLE: decision shows an example { string ri,lessvar,parvar,perm; ideal jac; list varlist,buffer,isol,@s,lhelp,lhelp1,lfac,worklist; poly p,g; def rbuffer; def r=basering; //diverse zaehler int @z,zz,count,tester; int n=nvars(r); //specialcases if (leadcoef(f)<0) { return(0); } lfac=factorize(f,2); ideal factor=lfac[1]; intvec @ex=lfac[2]; factor=factor[1]; zz=size(factor); f=1; for (@z=1;@z<=zz;@z++) { if ((@ex[@z] mod 2)==1) { f=f*factor[@z]; } } if (deg(f)<=0) { if (leadcoef(f)>=0) { return(1); } return(0); } //for recursion if (n==1) { if (sturm(f,-length(f),length(f))==0) { return(1); } return(0); } //search for a p in Q[x_n] such that f is pos. sem. definite //if and only if for every isolating setting S={a_1,...,a_r} holds that //every f(x_1,..,x_n-1, a_i) is positiv semidefinite //recursion of variables /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// ideal II = maxideal(1); varlist = II[1..n-1]; lessvar=string(varlist); parvar=string(var(n)); ri="ring r_neu="+charstr(r)+",(@t,"+parvar+","+lessvar+"),dp;"; execute(ri); poly f=imap(r,f); list varlist=imap(r,varlist); ideal jac=jacob(@t+f); jac=jac[3..(n+1)]; ideal eins=std(jac); ideal i=@t+f,jac; //use Wu method if (eins==1) { zz=0; } else { matrix m=char_series(i); zz=nrows(m);//number of rows } poly p=1; for (@z=1;@z<=zz;@z++) { p=p*m[@z,1]; } //trailing coefficient of p p=subst(p,@t,0); p=realpoly(p); @s=subsets(n-1); ideal jacs; for (@z=1;@z<=size(@s);@z++) { perm=""; lhelp=list(); worklist=varlist; buffer=jac[1..(n-1)]; //vorbereitungen fuer den Ringwechsel //setze worklist=x_1,..,x_(n-1) for (zz=1;zz<=size(@s[@z]);zz++) { buffer =delete(buffer ,@s[@z][zz]-zz+1); worklist=delete(worklist,@s[@z][zz]-zz+1); lhelp=lhelp+list(string(var(@s[@z][zz]+2))); lhelp1=insert(lhelp,string(var(@s[@z][zz]+2))); } //worklist=(x_1,...,x_n-1)\(x_i1,...,x_ik) //lhelp =(x_i1,...,x_ik) //buffer=diff(f,x_i) i not in (i1,..,ik); worklist=list("@t",string(var(2)))+lhelp+worklist; for (zz=1;zz<=n+1;zz++) { perm=perm+","+string(worklist[zz]); } perm=perm[2..size(perm)]; if (size(buffer)!=0) { jacs=buffer[1..size(buffer)]; jacs=@t+f,jacs; } else { jacs=@t+f; } rbuffer=basering; //perm=@t,x_n,x_1,..,x_ik,x\(x_i1,..,x_ik) ri="ring rh=0,("+perm+"),dp;"; execute(ri); ideal jacs=imap(rbuffer,jacs); poly p=imap(rbuffer,p); matrix m=char_series(jacs); poly e=1; for (count=1;count<=nrows(m);count++) { e=e*m[count,1]; } //search for the leading coefficient of e in //Q(@t,x_n)[x_@s[@z][1],..,x_@s[@z][size(@s[@z])] intmat l[n-1][n-1]; for (zz=1;zzn) { erg[1]=m; erg[2]=1; return(erg); } else { for (l=k;l<=n;l++) { if (realpoly(m[l])==1) { erg[1]=ideal(1); erg[2]=1; return(erg); } } } vari=""; kill r_neu; } if (size(parstr(r))==0) { erg[1]=m; j=1; for (i=1;i<=n;i++) { j=j*isuniv(m[i]); } erg[2]=j; return(erg); } erg[1]=m; erg[2]=0; return(erg); } static proc length(poly f) "USAGE: length(f); poly f; RETURN: sum of the absolute Value of all coeffients of an irreducible poly nomial f EXAMPLE: example length; shows an example" { number erg,buffer; f=simplify(f,1);//wlog f is monic int n=size(f); for (int i=1;i<=n;i=i+1) { buffer= leadcoef(f[i]); erg=erg + absValue(buffer); } return(erg); } example { "EXAMPLE:"; echo = 2; ring r1 = 0,x,dp; poly f=x4-6x3+x2+1; norm(f); ring r2=0,(x,y),dp; poly g=x2-y3; length(g); } ////////////////////////////////////////////////////////////////////////////// //////////////weniger wichtig fuers Verstaendnis////////////////////////////// ////////////////////////////////////////////////////////////////////////////// static proc isuniv(poly f) { int erg; if (f==0) { erg=1; } else { erg=(isuni(f)!=0); } return(erg); } static proc search_first(ideal j,int start, int i) "USAGE: searchfirst(j, start, i); id a reduced groebner basis w.r.t. lex RETURN: if i=1 then turns the number of the first non univariate entry with order >1 in its leading term after start else the first non univariate of even order EXAMPLE: example norm; shows no example" { int n=size(j); int k=start;//counter j=j,0; if (i==1) { while ((k<=n)&&(ord(j[k])==1)) { k=k+1; } } else { while ((k<=n)&&(ord(j[k]) mod 2==1)) { k=k+1; } } return(k); } static proc subsets(int n) "USAGE :subsets(n); n>=0 in Z RETURN :l a list of all non-empty subsets of {1,..,n} EXAMPLE:subsets(n) shows an example; " { list l,buffer; int i,j,binzahl; if (n<=0) { return(l); } int grenze=2**n-1; for (i=1;i<=grenze;i++) { binzahl=i; for (j=1;j<=n;j++) { if ((binzahl mod 2)==1) { buffer=buffer+list(j); } binzahl=binzahl div 2; } l[i]=buffer; buffer=list(); } return(l); } example { "EXAMPLE:"; echo = 2; subsets(3); subsets(4); } proc permutation(list L) " USAGE: permutation(L); L a list OUTPUT: a list of all permutation lists of L EXAMPLE: permutation(L) gives an example" { list erg,buffer,permi,einfueger; int i,j,l; int n=size(L); if (n==0) { return(erg); } if (n==1) { erg=list(L); return(erg); } for (i=1;i<=n;i++) { buffer=delete(L,i); einfueger=permutation(buffer); l=size(einfueger); for (j=1;j<=l;j++) { permi=list(L[i])+einfueger[j]; erg=insert(erg,permi); } } return(erg); } example { "EXAMPLE:"; echo = 2; list L1="Just","an","example"; permutation(L1); list L2=1,2,3,4; permutation(L2); } static proc simplify_gen(poly f) "USAGE : simplify_gen(f); f a polymimial in Q(y_1,..,y_m)[x_1,..,x_n] RETURN : a polynomial g such that g is the square-free part of f and every real univariate factor of f is cancelled out EXAMPLE:simplify_gen gives no example" { int i,l; ideal factor; poly g=1; factor=factorize(f,2)[1]; l=size(factor); for (i=1;i<=l;i++) { if (isuniv(factor[i])) { g=g*realpoly(factor[i]); } else { g=g*factor[i]; } } return(g); } static proc contnonloc(ideal id,string pari, string vari) "INPUT : a radical ideal id in in F[pari+vari] which is radical in F(pari)[vari), pari and vari strings of variables OUTPUT : the contraction ideal of id, i.e. idF(pari)[vari]\cap F[pari+vari] EXAMPLE: contnonloc shows an example " { list pr; list contractpr; int i,l,tester; ideal primcomp; def r=basering; string neu="ring r_neu=("+charstr(r)+pari+"),("+vari+"),dp;"; execute(neu); def r1=basering; ideal buffer; setring r; pr=primdecGTZ(id); l=size(pr); contractpr[1]=ideal(1); for (i=1;i<=l;i++) { primcomp=pr[i][2]; setring r1; buffer=imap(r,primcomp); buffer=groebner(buffer); if (buffer==1) { tester=0; } else { tester=1; } setring r; //id only consits of non units in F(pari) if (tester==1) { contractpr=insert(contractpr,primcomp); } } l=size(contractpr); id=intersect(contractpr[1..l]); return(id); } example { "EXAMPLE:"; echo = 2; ring r = 0,(a,b,c),lp; ideal i=b3+c5,ab2+c3; ideal j=contnonloc(i,",b","a,c"); j; } singular-4.0.3+ds/Singular/LIB/recover.lib000066400000000000000000002051461266270727000203140ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////////// version="version recover.lib 4.0.2.0 30.03.2015 "; // $Id: b927729927611a7d28bab0afd4a692f0cbc92260 $ category="Algebraic Geometry"; info=" LIBRARY: recover.lib Hybrid numerical/symbolical algorithms for algebraic geometry AUTHOR: Adrian Koch (kocha at rhrk.uni-kl.de) OVERVIEW: In this library you'll find implementations of some of the algorithms presented in the paper listed below: Bertini is used to compute a witness set of a given ideal I. Then a lattice basis reduction algorithm is used to recover exact results from the inexact numerical data. More precisely, we obtain elements of prime components of I, the radical of I, or an elimination ideal of I. NOTE that Bertini may create quite a lot of files in the current directory (or overwrite files which have the same names as the files it wants to create). It also prints information to the screen. The usefulness of the results of the exactness recovery algorithms heavily depends on the quality of the witness set and the quality of the lattice basis reduction algorithm. The procedures requiring a witness set as part of their input use a simple, unsofisticated version of the LLL algorithm. REFERENCES: Daniel Bates, Jonathan Hauenstein, Timothy McCoy, Chris Peterson, and Andrew Sommese; Recovering exact results from inexact numerical data in algebraic geometry; Published in Experimental Mathematics 22(1) on pages 38-50 in 2013 KEYWORDS: numerical algebraic geometry; hybrid algorithms; exactness recovery PROCEDURES: substAll(v,p); poly: ring variables in v substituted by elements of p veronese(d,p); ideal: image of p under the degree d Veronese embedding getRelations(p,..); list of ideals: homogeneous polynomial relations between components of p getRelationsRadical(p,..); modified version of getRelations gaussRowWithoutPerm(M); matrix: a row-reduced form of M gaussColWithoutPerm(M); matrix: a column-reduced form of M getWitnessSet(); extracts the witness set from the file \"main_data\" produced by Bertini writeBertiniInput(J); writes the input-file for bertini with the polynomials in J as functions num_prime_decom(I,..); is supposed to compute a prime decomposition of the radical of I num_prime_decom1(P,..); is supposed to compute a prime decomposition for the ideal represented by the witness point set P num_radical_via_decom(I,..); compute elements of the radical of I by using num_prime_decom num_radical_via_randlincom(I,..); computes elements of the radical of I by using a different method num_radical1(P,..); computes elements of the radical via num_prime_decom1 num_radical2(P,..); computes elements of the radical using a different method num_elim(I,f,..); computes elements of the elimination ideal of I w.r.t. the variables specified by f num_elim1(P,..,v); computes elements of the elimination ideal of the ideal represented by the witness point set P (w.r.t. the variables specified in v) realLLL(M); simple version of the LLL-algorithm;works only over real numbers "; LIB "matrix.lib"; LIB "linalg.lib"; LIB "inout.lib"; LIB "atkins.lib"; ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////// static procs for rounding /////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// static proc getposi(string s) {//returns the position of the . in a complex number, or 0 if there is no . in s int i; for(i=1; i<=size(s); i++) { if(s[i] == "."){return(i);} } return(0); } static proc string2digit(string ti) { intvec v=0,1,2,3,4,5,6,7,8,9; int i; for(i=1; i<=size(v); i++) { if( ti == string(v[i]) ) { return(poly(v[i])); } } } static proc string2poly(string t) { poly r=string2digit(t[1]); int i; for(i=2; i<=size(t); i++) { r=r*10+string2digit(t[i]); } return(r); } static proc roundstringpoly(string s, int posi) {//returns the string t; //first check, whether s is negative or not int e=0; if(s[1]=="-") { e=1; t=s[2..(posi-1)];//start at the second symbol (to drop the minus) } else { t=s[1..(posi-1)]; } poly r=string2poly(t);//this is always the rounded-down version of the absolute value //of r //we have to check now, whether we should have rounded up //for that, we check the digit after the . if(string2digit(s[posi+1]) >= 5) { r=r+1; } if(e == 1) {//readjust the sign, if needed r=-r; } return(r); } static proc roundpoly(poly r) { string s=string(r); int posi=getposi(s); if(posi == 0) {//there is no . in r, so r is an integer return(r); } return(roundstringpoly(s, posi)); } ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////// Veronese embedding //////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// proc substAll(poly v, list p) "USAGE: substAll(v,p); poly v, list p RETURN: poly: the polynomial obtained from v by substituting the elements of p for the ring variables NOTE: The list p should have as many elements as there are ring variables. EXAMPLE: example substAll; shows an example " {//substitutes the elements of p for the ring variables //used to obtain the value of the veronese map int i; poly f=v; for(i=1; i<=nvars(basering); i++) { f=subst(f,var(i),p[i]); } return(f); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; poly v=x+y+z; list p=7/11,5/11,-1/11; poly f=substAll(v,p); f; } proc veronese(int d, list p) "USAGE: veronese(d,p); int d, list p RETURN: ideal: the image of the point p under the degree d Veronese embedding NOTE: The list p should have as many elements as there are ring variables. The order of the points in the returned ideal corresponds to the order of the monomials in maxideal(d). SEE ALSO: maxideal EXAMPLE: example veronese; shows an example " {//image of p under the degree d Veronese embedding ideal V=maxideal(d); int i; poly v; int len=size(V); for(i=1; i <= len; i++) { v=V[i]; v=substAll(v,p); V[i]=v; } return(V); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y,z),dp; list p=2,3,5; ideal V=veronese(1,p); V; V=veronese(2,p); V; } static proc veronese_radical(int d, list P) {//returns a random linear combination of the images of the points in P under the //degree d Veronese embedding list p;//one of the points in P ideal Vp;//the Veronese embedding of p int i; for(i=1; i<=size(P); i++) { p=P[i]; Vp=veronese(d,p); P[i]=Vp; } //so we've replaced the points p with their images under the Veronese embedding //now we do a random linear combination of all these images //first, we rand some factors int di=10**7; int de=1; ideal F=poly(random(de,di))/di; poly f; for(i=2; i<=size(P); i++) { f=poly(random(de,di))/di; F=F,f; } //then we compute the linear combination poly v; int j; for(j=1; j<=size(P); j++) { Vp=P[j]; v=v+F[j]*Vp[1]; } ideal V=v; int len=size(maxideal(d)); for(i=2; i<=len; i++) { v=0; for(j=1; j<=size(P); j++) { Vp=P[j]; v=v+F[j]*Vp[i]; } V=V,v; } return(V); } ///////////////////////////////////////////////////////////////////////////////////////// ////////////////////////// some static procs ////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// static proc randlincom(ideal V, int len) {//produces a random linear combination of the real vectors defined by the real and the //imaginary part of V, respectively //(V is the image of a complex point p under a veronese embedding) poly randre,randim; int di=10**9; int de=1; //we get one of 2(di-de) numbers between (-)de/di and (-)1 randre=(-1)**random(1,2)*poly(random(de,di))/di; randim=(-1)**random(1,2)*poly(random(de,di))/di; ideal lincom=randre*repart(leadcoef(V[1]))+randim*impart(leadcoef(V[1])); int i; for(i=2; i<=len; i++) { lincom=lincom,randre*repart(leadcoef(V[i]))+randim*impart(leadcoef(V[i])); } return(lincom); } static proc getmatrix(ideal V, bigint C, int len) {//constructs the stacked matrix, but with randlincom(V,len) instead of V ideal rl=randlincom(V,len); matrix v=transpose(matrix(rl)); matrix E=diag(1,len); v=C*v; E=concat(E,v); E=transpose(E); return(E); } static proc getpolys(matrix B, int d) {//takes the integer parts* of the columns of B and uses them as coefficients in a //homogeneous poly of degree d //i.e. the first nrows-1 entries ideal V=maxideal(d); poly r=0;//will be one of the relation-polys ideal R;//will contain all the relations intvec rM=1..(nrows(B)-1); intvec cM=1..ncols(B); matrix M=submat(B,rM,cM);//B without the last row //poly nu=poly(10)**(2*d); int i,j; for(i=1; i<=ncols(M); i++) { if(absValue(B[nrows(B),i]) < 10)//if(is_almost_zero(B,i,d)) {//we should check first, if the value of the generated poly in p (i.e. the last //entry of the respective column in B) is "almost" 0 if(1) { for(j=1; j<=size(V); j++) { r=r+M[j,i]*V[j]; } R=R,r; r=0; } } } R=simplify(R,2);//gets rid of the zeroes return(R); } static proc getD(ideal J) { //computes the maximal degree among elements of J int maxdeg,c,i; poly g; for(i=1; i<=size(J); i++) { g=J[i]; c=deg(g); if(c > maxdeg) { maxdeg=c; } } return(maxdeg); } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// use_LLL procedures ////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// static proc mat2list(bigintmat B) { list c;//column of B list M;//the matrix: list of column-lists int i,j; for(i=1; i<=ncols(B); i++) { for(j=1; j<=nrows(B); j++) { c=c+list(B[j,i]); } M=M+list(c); c=list(); } return(M); } static proc list2bigintmat(list L); { int c=size(L); int r=size(L[1]); bigintmat B[r][c]; list Li; int i,j; for(i=1; i<=c; i++) { Li=L[i]; for(j=1; j<=r; j++) { B[j,i]=Li[j]; } } return(B); } static proc bigint2poly(bigint b) { poly p; string bs=string(b); int st=1; int c; if(bs[1] == "-") { st=2; c=1; } int i; for(i=st; i<=size(bs); i++) { p=p*10+string2intdigit(bs[i]); } if(c == 1) { return(-p); } return(p); } static proc bigintmat2matrix(bigintmat B) {//type conversion via matrix(B) does not work int r=nrows(B); int c=ncols(B); matrix M[r][c]; int i,j; for(i=1; i<=r; i++) { for(j=1; j<=c; j++) { M[i,j]=bigint2poly(B[i,j]); } } return(M); } static proc use_LLL(matrix A) { //first, we round the entries in the last row of A int r=nrows(A); int c=ncols(A); int i; for(i=1; i<=c; i++) { A[r,i]=roundpoly(A[r,i]); } //now, all entries of A are integers, but still have type poly //so we convert A to a bigintmat B bigintmat B=mat2bigintmat(A); //apply LLL list M=mat2list(B); list L=LLL(M); B=list2bigintmat(L); return(bigintmat2matrix(B)); } static proc use_LLL_bigintmat(matrix A) {//returns a bigintmat instead of a matrix //first, we round the entries in the last row of A int r=nrows(A); int c=ncols(A); int i; for(i=1; i<=c; i++) { A[r,i]=roundpoly(A[r,i]); } //now, all entries of A are integers, but still have type poly //so we convert A to a bigintmat B bigintmat B=mat2bigintmat(A); //apply LLL list M=mat2list(B); list L=LLL(M); B=list2bigintmat(L); return(B); } static proc use_FLINT_LLL(matrix A) { //first, we round the entries in the last row of A int r=nrows(A); int c=ncols(A); int i; for(i=1; i<=c; i++) { A[r,i]=roundpoly(A[r,i]); } //now, all entries of A are integers, but still have type poly //so we convert A to a bigintmat B bigintmat B=mat2bigintmat(A); //apply LLL bigintmat BB=system("LLL_Flint",B); return(BB); } static proc use_NTL_LLL(matrix A) { //first, we round the entries in the last row of A int r=nrows(A); int c=ncols(A); int i; for(i=1; i<=c; i++) { A[r,i]=roundpoly(A[r,i]); } //now, all entries of A are integers, but still have type poly //so we convert A to a bigintmat B bigintmat B=mat2bigintmat(A); def br=basering; ring newr=0,x,dp; matrix A=bigintmat2matrix(B); //NTL wants the lattice-vectors as row-vectors and returns a matrix of row-vectors A=transpose(A); matrix AA=system("LLL",A); AA=transpose(AA); bigintmat BB=mat2bigintmat(AA); setring br; return(BB); } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// the main procedure(s) ////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// proc getRelations(list p, int D, bigint C) "USAGE: getRelations(p,D,C); list p, int D, bigint C RETURN: list K: a list of ideals; the ideals contain homogeneous polynomial relations of degree <=D between the components of the point p NOTE: This procedure uses only the images of the one point p under the Veronese embeddings to find homogeneous polynomial relations. SEE ALSO: getRelationsRadical EXAMPLE: example getRelations; shows an example " {//uses degree d Veronese embeddings (for all d<=D) and LLL-algorithm to find //(homogeneous) polynomial relations between the entries of p //C is the Value with which the Veronese embedding is being multiplied (cf getmatrix) if(nvars(basering) != size(p) ) { ERROR("Number of variables not equal to the number of components of p."); } //get the precision list RL=ringlist(basering); RL=RL[1]; RL=RL[2]; int Prec=RL[2]; list P=list(p); int d,i,len; intvec rm; ideal vd,Kd; list K; matrix A,B; for(d=1; d<=D; d++) { vd=veronese(d,p); len=size(maxideal(d)); A=getmatrix(vd,C,len); B=realLLL(A); Kd=getpolys(B,d); if(size(Kd) == 0)//i.e. Kd has only zero-entries {//then dont add Kd to the list of relations d++; continue; } rm=check_is_zero_lincomradical(Prec,Kd,P); for(i=1; i<=size(rm); i++) { if( rm[i] == 1 ) { Kd[i] = 0; } } Kd=simplify(Kd,2); if(size(Kd) == 0)//i.e. Kd has only zero-entries {//then dont add Kd to the list of relations d++; continue; } K=K+list(Kd); } return(K); } example { "EXAMPLE:"; echo=2; ring r=(complex,50),(x,y,z),dp; list p=1,-1,0.5; getRelations(p,2,10000); } proc getRelationsRadical(list P, int D, bigint C) "USAGE: getRelationsRadical(P,D,C); list P, int D, bigint C RETURN: list K: a list of ideals; the ideals contain homogeneous polynomial relations of degree <=D between the components of the points in P NOTE: This procedure uses random linear combination of the Veronese embeddings of all points in P to find homogeneous polynomial relations. SEE ALSO: getRelations EXAMPLE: example getRelationsRadical; shows an example " {//here we compute random linear combinations of the degree d Veronese embeddings of the //points in P and then proceed as in getRelations to get homogeneous polynomials //which vanish on all points in P (with high probability) if(nvars(basering) != size(P[1]) ) { ERROR("Number of variables not equal to the number of components of P[1]."); } //get the precision list RL=ringlist(basering); RL=RL[1]; RL=RL[2]; int Prec=RL[2]; int d,i,len; intvec rm; ideal vd,Kd; list K; matrix A,B; for(d=1; d<=D; d++) { vd=veronese_radical(d,P); len=size(maxideal(d)); A=getmatrix(vd,C,len); B=realLLL(A); Kd=getpolys(B,d); if(size(Kd) == 0)//i.e. Kd has only zero-entries {//then dont add Kd to the list of relations d++; continue; } rm=check_is_zero_lincomradical(Prec,Kd,P); for(i=1; i<=size(rm); i++) { if( rm[i] == 1 ) { Kd[i] = 0; } } Kd=simplify(Kd,2); if(size(Kd) == 0)//i.e. Kd has only zero-entries {//then dont add Kd to the list of relations d++; continue; } K=K+list(Kd); } return(K); } example { "EXAMPLE:"; echo=2; ring r=(complex,50),(x,y,z),dp; list p1=1,-1,0.5; list p2=1,0,-1; list P=list(p1)+list(p2); getRelationsRadical(P,2,10**5); } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// Gauss reduction ////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// static proc find_unused_nonzero(matrix M, int j, intvec used) {//look in column j of M for a non-zero entry in an unused row //if there is one, return its row index //if there isn't, return 0 int i; int r=nrows(M); for(i=1; i<=r; i++) { if(used[i] == 0) { if(M[i,j] != 0) { return(i); } } } return(0); } proc gaussRowWithoutPerm(matrix M) "USAGE: gaussRowWithoutPerm(M); M a matrix of constant polynomials RETURN: matrix: basic Gaussian row reduction of M, just without permuting the rows EXAMPLE: example gaussRowWithoutPerm; shows an example " {//M a matrix of constant polys int n=ncols(M); int r=nrows(M); int i,j,k; intvec used;//the rows we already used to make entries in other rows 0 used[r]=0;//makes it a zero-intvec of length r //we dont want to change these used rows anymore and we dont want to use them again //entry i will be set to 1 if we used row i already for(j=1; j<=n; j++)//go through all columns of M { //find the first non-zero entry i=find_unused_nonzero(M,j,used); if(i != 0) {//and use it to make all non-pivot entries in the column equal to 0 used[i]=1; for(k=1; k<=r; k++) { if(used[k] == 0) { if(M[k,j] != 0) { M=addrow(M,i,-M[k,j]/M[i,j],k); } } } } } return(M); } example { "EXAMPLE:"; echo=2; ring r=0,x,dp; matrix M[5][4]=0,0,2,1,4,5,1,3,0,9,2,0,8,1,0,6,0,9,4,1; print(M); print(gaussRowWithoutPerm(M)); } proc gaussColWithoutPerm(matrix M) "USAGE: gaussColWithoutPerm(M); M a matrix of constant polynomials RETURN: matrix: basic Gaussian column reduction of M, just without permuting the columns EXAMPLE: example gaussColWithoutPerm; shows an example " { matrix T=transpose(M); matrix G=gaussRowWithoutPerm(T); return(transpose(G)); } example { "EXAMPLE:"; echo=2; ring r=0,x,dp; matrix M[3][4]=0,1,0,2,1,2,3,4,1,0,5,0; print(M); print(gaussColWithoutPerm(M)); } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /////////////////////// static procs needed for minrelations ////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// static proc multwithmaxideal(ideal I, int a) {//returns the ideal IM containing all products of elements of I and maxideal(a) ideal M=maxideal(a); int sM=size(M); ideal IM=I*M[1]; int i; for(i=2; i<=sM; i++) { IM=IM,I*M[i]; } return(IM); } static proc prodofallringvars(int dummy) {//returns the product of all ring variables poly f=1; int i; for(i=1; i<=nvars(basering); i++) { f=f*var(i); } return(f); } static proc getcoefmat(ideal IM, int m) {//computes the matrix of coefficients of the elements of IM //the order of the coefficients in each column corresponds to the order of the //monomials in maxideal(m); matrix Co; ideal M=maxideal(m); int sM=size(M); matrix C[sM][1];//the coeff vector of an element of IM with the coeffs placed at //the appropriate positions IM=simplify(IM,2);//be sure that size(IM) is the right thing -> get rid of zeroes int sIM=size(IM); matrix B; poly pr=prodofallringvars(1); poly g, Coj; int i,j,k; for(i=1; i<=sIM; i++) { g=IM[i]; Co=coef(g,pr); //we now have to put the coeffs in the appropriate places (corresponding to the //position of the respective monomial in maxideal) for(j=1; j<=ncols(Co); j++) { Coj=Co[1,j];//arranged as row vectors //compare the monomials of g with the elements of maxideal(m) //and when we find a match, place the coef at the appropriate place in C for(k=1; k<=sM; k++) { if(M[k] == Coj) { C[k,1]=Co[2,j]; break;//we dont need to check any other elements of M //since theyre all different } } } if(i==1) { B=C; C=0; i++; continue; } B=concat(B,C); C=0;//reset C to the zero vector } return(B); } static proc getconcatcoefmats(list L) {//L the first size(L) entries of K //returns the concatenated coef matrices //more precisely: let m be the degree of the elements of L[size(L)], then we want //to know, which homogenous polynomials of degree m can be written as a combination //of polynomials in the ideals contained in L. In particular, we want to know which //of the elements of L[size(L)] can be written as a combination of other polys //in L and are thereby superfluous (cf superfluousL) //what we do here is, we multiply each polynomial (of degree, say, d) in L with a //monomial of degree m-d and then store the coefficients of the resulting poly //in a matrix //(this is rather cumbersome and can probably be improved upon significantly) matrix B,C; ideal IM,I; int i,d,m; poly l; int sL=size(L); l=L[sL][1];//the polys are homogeneous; deg rising along L; deg same in L[j] //for all j m=deg(l);//the max degree if(sL == 1) {//then we only consider polys of one certain degree, so we don't have to //multiply any of the ideals with any maxideal C=getcoefmat(L[1],m); return(C);//we dont concatenate anything here, so the initialization of //C as the 1x1-zero-matrix is not an issue } for(i=1; i 0) { dfs=dfs+", f"+string(i); } else { dfs=dfs+"f"+string(i); } } dfs="function "+dfs+";"+newline; return(dfs); } static proc remove_brackets(string vg) {//removes any round brackets from a string int i; for(i=1; i b) { b=a; } } return(string(b)); } static proc get_prec_in_bits(int Prec) {//log_10(2) is approximately 3,3219281 //conversion from decimal digits to bits, rounded up int pb = (3322*Prec div 1000) + 1; int upb=3328;//upper bound on the precision if( pb > upb ) {//bertini allows a maximum of 3328 bits of precision return(upb); } int lowb=64;//lower bound if( pb < lowb) {//bertini requires a minimum of 64 bits of precision //however, using such a low precision is not recommended, since it will //probably not yield any useful results return(lowb); } //bertini wants the precision to be a multiple of 32 pb = pb + 32 - (pb mod 32); return(pb); } proc writeBertiniInput(ideal J, int Prec) "USAGE: writeBertiniInput(J); ideal J RETURN: none; writes the input-file for bertini using the polynomials given by J as functions NOTE: Either creates a file named input in the current directory or overwrites the existing one. If you want to pass different parameters to bertini, you can edit the produced input file or redefine this procedure. EXAMPLE: example writeBertiniInput; shows an example " {//writes the input-file for bertini //we change the ring so that the names of the ring variables are convenient for us def br=basering; int nv=nvars(br); ring r=0,x(1..nv),dp; ideal J=fetch(br,J); link l=":w ./input"; write(l,"CONFIG"); write(l,""); write(l,"TRACKTYPE: 1;"); write(l,"TRACKTOLBEFOREEG: 1e-8;"); write(l,"TRACKTOLDURINGEG: 1e-11;"); write(l,"FINALTOL: 1e-14;"); write(l,""); write(l,""); write(l,"PrintPathProgress: 1;"); write(l,"MPTYPE: 2;"); int pb=get_prec_in_bits(Prec); write(l,"AMPMaxPrec: "+string(pb)+";"); string cb=get_coef_bound_ideal(J); write(l,"COEFFBOUND: "+cb+";"); string db=string(getD(J)); write(l,"DEGREEBOUND: "+db+";"); write(l,""); write(l,"SHARPENDIGITS: "+string(Prec)+";"); write(l,"END;"); write(l,""); write(l,""); write(l,"INPUT"+newline); string vg=get_hom_var_group_str(1); write(l,vg); string dfs=get_declare_function_str(J); write(l,dfs); string fs=get_function_str(J); write(l,fs); write(l,"END;"); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; poly f1=x+y+z; poly f2=x2+xy+y2; ideal I=f1,f2; writeBertiniInput(I,300); } static proc find_string(string F, string S) {//search in string S for the string F //output all the positions in an intvec v string s; intvec v; int c=1;//counts the number of elements of v int i; int a=size(S); int len=size(F); for(i=1; i<=a; i++) { s=S[i,len]; if(F==s) { v[c]=i; c++; } } return(v); } static proc read_point(string r, int po, int endpo) {//reads out a single point from main_data //return as string representing a floating point number split into real and imaginary //part int i, b; for(i=po; i<=size(r); i++) { if(r[i] == newline) { b=i+1;//b is the first character in the line containing components of the point break; } } list p; string pj; int len, strt; strt=b; for(i=b; i<=endpo; i++) { if(r[i] == newline) { len=i-strt; pj=r[strt,len]; p=p+list(pj); strt=i+1; } } return(p); } static proc string2num(string numstr) { number n=0; int c=0; if(numstr[1] == "-") { numstr=numstr[2,size(numstr)-1]; c=1; } int i; for(i=size(numstr); i>=3; i--) { n=n/10+string2intdigit(numstr[i]); } n=n/10+string2intdigit(numstr[1]); if(c==1) { n=-n; } return(n); } static proc string2e(string estr) {//compute the exponent from the scientific notation int e=0; int c=0; if(estr[1] == "-") { c=1; } else { if(estr[1] != "+") { estr="+"+estr; return(string2e(estr)); } } estr=estr[2,size(estr)-1]; int i; for(i=1; i<=size(estr); i++) { e=e*10+string2intdigit(estr[i]); } if(c==1) { e=-e; } return(e); } static proc dismantle_string(string si) {//cuts the string into the real/imaginary parts and their exponents //example of a string si: //1.124564280901713e+00 -2.550064206873323e-01 int e1,e2; number im,re; string prt;//the currently considered part of the string int i, len; int strt=1; for(i=1; i<=size(si); i++) { if( si[i] == "e" ) { len=i-strt; prt=si[strt,len]; re=string2num(prt); break; } } strt=i+1;//start at the character coming after "e" for(i=strt; i<=size(si); i++) { if( si[i] == " " ) { len=i-strt; prt=si[strt,len]; e1=string2e(prt); break; } } strt=i+1;//start at the character coming after " " for(i=strt; i<=size(si); i++) { if( si[i] == "e" ) { len=i-strt; prt=si[strt,len]; im=string2num(prt); break; } } strt=i+1;//start at the character coming after "e" len=size(si)-strt+1; prt=si[strt,len]; e2=string2e(prt); number ten=10; if(0)//e1 < -1000 { re=0; } else { re=re*(ten^e1); } if(0)//e2 < -1000 { im=0; } else { im=im*(ten^e2); } number n=re + IUnit*im; return(n); } static proc convert_p(list p) {//p a list of strings representing the components of the point p //converts the list of strings to a list of numbers //interesting: apparently, since p is a list of strings to begin with, it is not //bound to the basering, so it will exist in the ring r, as well. But, as we change //the entries of p from type string to type number/poly, it gets bound to the ring r, //so it doesnt exist in br anymore. Hence, we have do define list p=fetch. //we change the ring, so that we know, what the imaginary unit is called, define the //points over that ring and then fetch them to the original ring def br=basering; list l=ringlist(br); l[1][3]="IUnit"; def r=ring(l); setring r; string si; number pi; int i; for(i=1; i<=size(p); i++) { pi=dismantle_string(p[i]); p[i]=pi; } setring br; list p=fetch(r,p); return(p); } static proc getP_plus_posis(int dummy) {//goes through the file main_data generated by bertini and returns the witness points //as a list of complex numbers //(the precision specified in the definition of the basering should* be at least as //high as the precision used by/to be expected from bertini) string r; list P,p; int i, j; r=read("main_data"); intvec posi=find_string("Estimated",r); intvec endpos=find_string("Multiplicity",r); for(i=1; i<=size(posi); i++) { p=read_point(r,posi[i],endpos[i]); if( size(p) == 0 ) { ERROR("Bertini nicht erfolgreich"); } P=P+list( convert_p(p) ); } return(posi, endpos, P); } static proc getPi_from_main_data(int i, intvec posi, intvec endpos) {//gets only the i-th point in main_data; is used by check_is_zero string r; list P,p; int j; r=read("main_data"); p=read_point(r,posi[i],endpos[i]); if( size(p) == 0 ) { ERROR("Bertini nicht erfolgreich"); } P=P+list( convert_p(p) ); return(P); } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// Applications ////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////// static procs to get the relations from the ////////////////////////// ////////////////// complex to the rational numbers ////////////////// ////////////////////////////////////////////////////////////////////////////////////////// static proc get_relations_as_bigintmats(list p, int D, bigint C) {//uses degree d Veronese embeddings (for all d<=D) and LLL-algorithm to find //(homogeneous) polynomial relations between the entries of p //C is the Value with which the Veronese embedding is being multiplied (cf getmatrix) //returns the list of the bigintmats computed by the LLL-algorithm //these are then processed further by get_relations_over_rationals after a switch //of rings in the level above if(nvars(basering) != size(p) ) { ERROR("Number of variables not equal to the number of components of p."); } int d,len; list mats; ideal vd; matrix A; bigintmat B; for(d=1; d<=D; d++) { vd=veronese(d,p); len=size(maxideal(d)); A=getmatrix(vd,C,len); //B=use_FLINT_LLL(A); B=use_NTL_LLL(A); //B=use_LLL_bigintmat(A); mats=mats+list(B); } return(mats); } static proc get_relations_radical_as_bigintmats(list P, int D, bigint C) {//is to get_relations_as_bigintmats what get_relationsRadical is to get_relations //ie uses a random linear combination of the Veronese embeddings of all points in P //in order to get polynomials which vanish over all points simultaneously int d,len; list mats; ideal vd; matrix A; bigintmat B; for(d=1; d<=D; d++) { vd=veronese_radical(d,P); len=size(maxideal(d)); A=getmatrix(vd,C,len); //B=use_FLINT_LLL(A); B=use_NTL_LLL(A); //B=use_LLL_bigintmat(A); mats=mats+list(B); } return(mats); } static proc check_is_zero(int Prec, ideal Kd, intvec posi, intvec endpos, int k) { def br=basering; int n=nvars(basering); ring R=(complex,Prec,IUnit),x(1..n),dp; ideal I=fetch(br,Kd); list P=getPi_from_main_data(k, posi, endpos); list p; poly v; number eps=number(10)**(5-Prec); number a; int i,j,c; int len = size(I); intvec rm; rm[len]=0; for(i=1; i<=len; i++) { for(j=1;j<=size(P); j++) { p=P[j]; v=substAll(I[i],p); a=number(v); a=absValue(repart(a))+absValue(impart(a)); //v=v*( poly(10)**(Prec-10) ); if( a > eps) { rm[i] = 1; break; } } } return(rm); } static proc get_relations_over_rationals(int D, int Prec, list mats, intvec posi, intvec endpos, int k) {//finds the relations by passing the bigintmats to getpolys //returns a list of ideals containing the corresponding polynomials bigintmat B; int d; list K; ideal Kd; intvec rm; int i; for(d=1; d<=D; d++) { B=mats[d]; Kd=getpolys(bigintmat2matrix(B),d); if(size(Kd) != 0) { rm=check_is_zero(Prec,Kd,posi,endpos,k); for(i=1; i<=size(rm); i++) { if( rm[i] == 1 ) { Kd[i] = 0; } } Kd=simplify(Kd,2); } if(size(Kd) == 0)//i.e. Kd has only zero-entries {//then dont add Kd to the list of relations d++; continue; } K=K+list(Kd); } return(K); } static proc getP_from_known_posis(intvec posi, intvec endpos) {//goes through the file main_data generated by bertini and returns the witness points //as a list of complex numbers //(the precision specified in the definition of the basering should* be at least as //high as the precision used by/to be expected from bertini) string r; list P,p; int i, j; r=read("main_data"); for(i=1; i<=size(posi); i++) { p=read_point(r,posi[i],endpos[i]); if( size(p) == 0 ) { ERROR("Bertini nicht erfolgreich"); } P=P+list( convert_p(p) ); } return(P); } static proc check_is_zero_lincomradical(int Prec, ideal I, list P) { //altered ckeck_is_zero for the linear-combination-of-Veronese-embeddings version //of the procedures list p; poly v; number eps=number(10)**(5-Prec); number a; int i,j,c; int len = size(I); intvec rm; rm[len]=0; for(i=1; i<=len; i++) { for(j=1;j<=size(P); j++) { p=P[j]; v=substAll(I[i],p); a=number(v); a=absValue(repart(a))+absValue(impart(a)); //v=v*( poly(10)**(Prec-10) ); if( a > eps) { rm[i] = 1; break; } } } return(rm); } static proc get_relations_lincomradical_over_rationals(int D, int Prec, list mats, intvec posi, intvec endpos) {//finds the relations by passing the bigintmats to getpolys //returns a list of ideals containing the corresponding polynomials bigintmat B; int d; list K; ideal Kd; intvec rm; int i; //set up the ring to check whether the supposed relations have value zero at //all the witness points def br=basering; int n=nvars(br); ring cr=(complex,Prec,IUnit),x(1..n),dp; list P=getP_from_known_posis(posi, endpos); ideal I; int le; setring br; for(d=1; d<=D; d++) { B=mats[d]; Kd=getpolys(bigintmat2matrix(B),d); //go to the complex ring to see which candidate relations should be removed setring cr; I=fetch(br,Kd); le=size(I); if(le != 0) { rm=check_is_zero_lincomradical(Prec,I,P); } //remove from the ideal over the rational numbers setring br; if(le != 0) { for(i=1; i<=size(rm); i++) { if( rm[i] == 1 ) { Kd[i] = 0; } } Kd=simplify(Kd,2); } if(size(Kd) == 0)//i.e. Kd has only zero-entries {//then dont add Kd to the list of relations d++; continue; } K=K+list(Kd); } return(K); } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// num_prime_decom ///////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// proc num_prime_decom(ideal I, int D, int Prec) "USAGE: num_prime_decom(I,D); ideal I, int D D a bound to the degree of the elements of the components of a prime decomposition of I. RETURN: list of ideals: each of the ideals a prime component of the radical of I REMARKS: Uses Bertini. NOTE: Should only be called from a ring over the rational numbers. EXAMPLE: example num_prime_decom; shows an example " {//App. 3.1: computes a prime decomposition of the radical of I //returns a list of ideals, each of them a prime component def br=basering; int n=nvars(br); list K;//will contain the relations over the basering list Q;//will contain the components ideal M; writeBertiniInput(I,Prec); //move to a ring over the complex numbers to get the points computed by bertini ring Ri=(complex,Prec,IUnit),x(1..n),dp; system("sh","bertini input"); list P; intvec posi, endpos; (posi, endpos, P)=getP_plus_posis(1); int sP=size(P); bigint C=bigint(10)**Prec;//digits of precision list p, mats; int i,j; for(i=1; i<=sP; i++) { setring Ri; //compute the relations (with LLL, NTL_LLL or FLINT_LLL) in the form of bigintmats p=P[i]; mats=get_relations_as_bigintmats(p,D,C); //move to br again to obtain the relation-polynomials over the rational numbers setring br; K=get_relations_over_rationals(D, Prec, mats, posi, endpos, i); if(size(K) == 0)//ie K the empty list { i++; continue; } K=minrelations(K); //K is now the list of ideals containing min gens in the respective degrees //now, we put these min gens in one ideal M=K[1]; for(j=2; j<=size(K); j++) { M=M+K[j]; } Q=Q+list(M); } return(Q); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y,z),dp; ideal I=(x+y)*(y+2z), (x+y)*(x-3z); int D=2; int Prec=300; num_prime_decom(I,D,Prec); //Let us compare that to the result of primdecSY: primdecSY(I); } proc num_prime_decom1(list P, int D, bigint C) "USAGE: num_prime_decom1(P,D,C); list P, int D, bigint C P a list of lists representing a witness point set representing an ideal I D should be a bound to the degree of the elements of the components of the prime decomposition of I C the number with which the images of the Veronese embeddings are multiplied RETURN: list of ideals: each of the ideals a prime component of the radical of I NOTE: Should only be called from a ring over the complex numbers. EXAMPLE: example num_prime_decom1; shows an example " {//P a list of lists containing the witness points //returns (or is supposed to return) a list containing the prime components //of the radical of the ideal which is represented by the witness points in P list p,K,Q; int i,j; ideal M; for(i=1; i<=size(P); i++) { p=P[i]; K=getRelations(p,D,C); if(size(K) == 0)//ie K the empty list { i++; continue; } K=minrelations(K); //K is now the list of ideals containing min gens in the respective degrees //now, we put these min gens in one ideal M=K[1]; for(j=2; j<=size(K); j++) { M=M+K[j]; } Q=Q+list(M); } return(Q); } example { "EXAMPLE:"; echo=2; //First, we compute a prime decomposition of the ideal I=x+y; ring R1=(complex,300,IUnit),(x,y),dp; list p1=1,-1; list P=list(p1); int D=2; bigint C=bigint(10)**300; num_prime_decom1(P,D,C); //Now, we try to obtain a prime decomposition of the ideal I=(x+y)*(y+2z), (x+y)*(x-3z); ring R2=(complex,20,IUnit),(x,y,z),dp; p1=1.7381623928,-1.7381623928,0.2819238763; list p2=-3.578512854,2.385675236,-1.192837618; P=p1,p2; num_prime_decom1(P,D,10000); //Now, we look at the result of a purely symbolic algorithm ring r2=0,(x,y,z),dp; ideal I=(x+y)*(y+2z), (x+y)*(x-3z); primdecSY(I); //If you compare the results, you may find that they don't match. //Most likely, the hybrid algorithm got the second component wrong. This is due to the //way the algorithm looks for homogeneous polynomial relations, and the specific version //of the LLL algorithm used here (an implementation into Singular of a rather simple //version which allows real input). It looks in degree 1, finds one relation and is //thereafter unable to see a second one. Then it moves on to degree 2 and finds //relations containing degree-1 relations as a factor. } ////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////// num_radical /////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// proc num_radical_via_decom(ideal I, int D, int Prec) "USAGE: num_radical_via_decom(I,D); ideal I, int D D a bound to the degree of the elements of the components. RETURN: ideal: the radical of I REMARKS: Uses Bertini. This procedure merely calls num_prime_decom with the same input and then intersects the returned components. NOTE: Should only be called from a ring over the rational numbers. SEE ALSO: num_prime_decom, num_radical_via_randlincom EXAMPLE: example num_radical_via_decom; shows an example " {//check p.14/15, App. 3.2 list Q=num_prime_decom(I,D,Prec); ideal interQ=1; int i; for(i=1; i<=size(Q); i++) { interQ=intersect(interQ,Q[i]); } return(interQ); } example { "EXAMPLE:"; echo=2; //First, we attempt to compute the radical via the hybrid algorithm. ring R=0,(x,y,z),dp; ideal I=(x+y)^2*(y+2z)^3, (x+y)^3*(x-3z)^2; int D=2; int Prec=300; ideal numRad=num_radical_via_decom(I,D,Prec); numRad; //Then we compute the radical symbolically and compare the results. ideal Rad=radical(I); Rad; reduce(Rad,std(numRad)); reduce(numRad,std(Rad)); } proc num_radical_via_randlincom(ideal I, int D, int Prec) "USAGE: num_radical_via_randlincom(I,D); ideal I, int D D a bound to the degree of the elements of the components. RETURN: ideal: the radical of I REMARKS: Uses Bertini. Instead of using the images of the Veronese embeddings of each individual witness point, this procedure first computes a random linear combination of those images and searches for homogeneous polynomial relations for this linear combination. NOTE: Should only be called from a ring over the rational numbers. SEE ALSO: num_radical_via_decom EXAMPLE: example num_radical_via_randlincom; shows an example " {//check p.14/15, App. 3.2 bigint C=bigint(10)**Prec;//digits of precision def br=basering; int n=nvars(br); writeBertiniInput(I,Prec); //move to a ring over the complex numbers to get the points computed by bertini ring Ri=(complex,Prec,IUnit),x(1..n),dp; system("sh","bertini input"); list P; intvec posi, endpos; (posi, endpos, P)=getP_plus_posis(1); list mats=get_relations_radical_as_bigintmats(P,D,C); setring br; list K=get_relations_lincomradical_over_rationals(D,Prec,mats,posi,endpos); ideal Q; if(size(K) > 0) { K=minrelations(K); Q=K[1]; int i; for(i=2; i<=size(K); i++) { Q=Q,K[i]; } } return(Q); } example { "EXAMPLE:"; echo=2; //First, we attempt to compute the radical via the hybrid algorithm. ring R=0,(x,y,z),dp; ideal I=(x+y)^2*(y+2z)^3, (x+y)^3*(x-3z)^2; int D=2; int Prec=300; ideal numRad=num_radical_via_randlincom(I,D,Prec); numRad; //Then we compute the radical symbolically and compare the results. ideal Rad=radical(I); Rad; reduce(Rad,std(numRad)); reduce(numRad,std(Rad)); } proc num_radical1(list P, int D, bigint C) "USAGE: num_radical1(P,D,C); list P, int D, bigint C P a list of lists representing a witness point set representing an ideal I D should be a bound to the degree of the elements of the components C the number with which the images of the Veronese embeddings are multiplied RETURN: list of ideals: each of the ideals a prime component of the radical of I REMARKS: This procedure merely calls num_prime_decom1 with the same input and then intersects the returned components. NOTE: Should only be called from a ring over the complex numbers. SEE ALSO: num_prime_decom1, num_radical2 EXAMPLE: example num_radical1; shows an example " {//computes the radical via num_prime_decom (intersecting the obtained prime decom) list Q=num_prime_decom1(P,D,C); ideal interQ=1; int i; for(i=1; i<=size(Q); i++) { interQ=intersect(interQ,Q[i]); } return(interQ); } example { "EXAMPLE:"; echo=2; //First, we write the input file for bertini and compute the radical symbolically. ring r=0,(x,y,z),dp; ideal I=4xy2-4z3,-2x2y+5xz2; ideal Rad=radical(I); writeBertiniInput(I,100); //Then we attempt to compute the radical via the hybrid algorithm. ring R=(complex,100,i),(x,y,z),dp; system("sh","bertini input"); list P=getWitnessSet(); int D=2; bigint C=bigint(10)**30; ideal Rad1=num_radical1(P,D,C); //Lastly, we compare the results. Rad1; ideal Rad=fetch(r,Rad); Rad; reduce(Rad,std(Rad1)); reduce(Rad1,std(Rad)); } proc num_radical2(list P, int D, bigint C) "USAGE: num_radical2(P,D,C); list P, int D, bigint C P a list of lists representing a witness point set representing an ideal I D should be a bound to the degree of the elements of the components C the number with which the images of the Veronese embeddings are multiplied RETURN: list of ideals: each of the ideals a prime component of the radical of I REMARKS: Instead of using the images of the Veronese embeddings of each individual witness point, this procedure first computes a random linear combination of those images and searches for homogeneous polynomial relations for this linear combination. NOTE: Should only be called from a ring over the complex numbers. SEE ALSO: num_radical1 EXAMPLE: example num_radical2; shows an example " {//computes the radical via getRelationsRadical list K=getRelationsRadical(P,D,C); K=minrelations(K); K; //unite the elements of K into one ideal ideal Q=K[1]; int i; for(i=2; i<=size(K); i++) { Q=Q,K[i]; } return(Q); } example { "EXAMPLE:"; echo=2; //First, we write the input file for bertini and compute the radical symbolically. ring r=0,(x,y,z),dp; ideal I=4xy2-4z3,-2x2y+5xz2; ideal Rad=radical(I); writeBertiniInput(I,100); //Then we attempt to compute the radical via the hybrid algorithm. ring R=(complex,100,i),(x,y,z),dp; system("sh","bertini input"); list P=getWitnessSet(); int D=2; bigint C=bigint(10)**30; ideal Rad2=num_radical2(P,D,C); //Lastly, we compare the results. Rad2; ideal Rad=fetch(r,Rad); Rad; reduce(Rad,std(Rad2)); reduce(Rad2,std(Rad)); } ////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// num_elim ///////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// static proc project_p(list p, intvec projvec) {//projects a single point p onto the components specified in projvec list pr;//the projection int i,k; for(i=1; i<=size(projvec); i++) { k=projvec[i]; pr=pr+list(p[k]); } return(pr); } static proc project_P(list P, intvec projvec) {//projects the points in P onto the components specified in projvec list p;//elements of P list Pr;//the list of projections list pr;//projection of a point p int i; for(i=1; i<=size(P); i++) { p=P[i]; pr=project_p(p,projvec); Pr=Pr+list(pr); } return(Pr); } static proc get_projection_intvec(intvec elvec) {//computes the intvec containing the indices of the variables which are not to be //eliminated int nv=nvars(basering); intvec projvec; int i,j,c,count;//count counts the elements of projvec for(i=1; i<=nv; i++) { c=1; for(j=1; j<=size(elvec); j++) { if(i == elvec[j]) { c=0; break; } } //if i is not among the elements of elvec, store it in projvec if(c == 1) { count++; projvec[count]=i; } } return(projvec); } static proc get_elvec(poly f) {//computes the elimination intvec from a product of ring variables if(size(f) != 1) { ERROR("f must be a product of ringvariables, i.e. a monomial."); } int n=nvars(basering); intvec elvec; int i, c; for(i=1; i<=n; i++) { if( f/var(i) != 0) { c++; elvec[c]=i; } } return(elvec); } proc num_elim(ideal I, poly f, int D, int Prec) "USAGE: num_elim(I,f,D); ideal I, poly f, int D f the product of the ring variables you want to eliminate D a bound to the degree of the elements of the components RETURN: ideal: the ideal obtained from I by eliminating the variables specified in f REMARKS: This procedure uses Bertini to compute a set of witness points for I, projects them onto the components corresponding to the variables specified in f and then proceeds as num_radical_via_randlincom. NOTE: Should only be called from a ring over the rational numbers. EXAMPLE: example num_elim; shows an example " {//App. 3.3 bigint C=bigint(10)**Prec;//digits of precision //first, get elvec and projvec intvec elvec=get_elvec(f); intvec projvec=get_projection_intvec(elvec); writeBertiniInput(I,Prec); //define the ring with eliminated variables //we have to compute the relations over this ring, since the number of variables //must be the same as the number of components of the projected point def br=basering; list l=ringlist(br); int i; for(i=size(elvec); i>=1; i--) { l[2]=delete(l[2],elvec[i]); } def brel=ring(l); int n=nvars(brel); //move to a ring over the complex numbers to get the points computed by bertini ring Ri=(complex,Prec,IUnit),x(1..n),dp; system("sh","bertini input"); list P; intvec posi, endpos; (posi, endpos, P)=getP_plus_posis(1); list Pr=project_P(P,projvec); list mats=get_relations_radical_as_bigintmats(Pr,D,C); setring brel; list K=get_relations_lincomradical_over_rationals(D,Prec,mats,posi,endpos); ideal R; if(size(K) > 0) { K=minrelations(K); R=K[1]; for(i=2; i<=size(K); i++) { R=R,K[i]; } } setring br; ideal R=imap(brel,R); return(R); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; poly f1=x-y; poly f2=z*(x+3y); poly f3=z*(x2+y2); ideal I=f1,f2,f3; //First, we attempt to compute the elimination ideal with the hybrid algorithm. ideal E1=num_elim(I,z,3,200); //Now, we compute the elimination ideal symbolically. ideal E2=elim(I,z); //Lastly, we compare the results. E1; E2; } proc num_elim1(list P, int D, bigint C, intvec elvec) "USAGE: num_elim1(P,D,C,v); list P, int D, bigint C, intvec v P a list of lists representing a witness point set representing an ideal J D should be a bound to the degree of the elements of the components C the number with which the images of the Veronese embeddings are multiplied v an intvec specifying the numbers/positions of the variables to be eliminated RETURN: ideal: the ideal obtained from J by eliminating the variables specified in v REMARKS: This procedure just canonically projects the witness points onto the components specified in the intvec v and then applies num_radical1 to the resulting points. NOTE: Should only be called from a ring over the complex numbers. EXAMPLE: example num_elim1; shows an example " {//let J be the ideal represented by the witness points in P //returns (or is supposed to return) the prime decomposition of the radical of the //elimination ideal of J //(where we eliminate the variables with the indices specified in elvec) //Note that, since we are in a homogeneous setting eliminating all variables //is quite simple, since we only have to decide, whether its the 0-ideal or the //whole ring. This procedure won't work in that case. intvec projvec=get_projection_intvec(elvec); list Pr=project_P(P,projvec); //We now have to change the ring we work over: we delete the variables which are //to be eliminated. -> The number of variables and the number of components in //the projected point are the same. Then we can apply our procedure and imap the //results to our original ring, since we didnt change the names of the variables. def br=basering; list l=ringlist(br); int i; for(i=size(elvec); i>=1; i--) { l[2]=delete(l[2],elvec[i]); } def r=ring(l); setring r; list Pr=fetch(br,Pr); ideal R=num_radical1(Pr,D,C); setring br; ideal R=imap(r,R); return(R); } example { "EXAMPLE:"; echo=2; //First, we write the input file for bertini and compute the elimination ideal //symbolically. ring r=0,(x,y,z),dp; poly f1=x-y; poly f2=z*(x+3y); poly f3=z*(x2+y2); ideal J=f1,f2,f3; ideal E2=elim(J,z); writeBertiniInput(J,100); //Then we attempt to compute the elimination ideal via the hybrid algorithm. ring R=(complex,100,i),(x,y,z),dp; system("sh","bertini input"); list P=getWitnessSet(); intvec v=3; bigint C=bigint(10)**25; ideal E1=num_elim1(P,2,C,v); //Lastly, we compare the results. E1; setring r; E2; } /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// //////////////////////////// lattice basis reduction ////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// //An implementation of a simple LLL algorithm //Works with real numbers //Is only used by those procedures which require the user to provide a witness set, // instead of calling Bertini to compute one. static proc eucl(int m, vector u) {//the square of the Euclidean norm of u poly e=inner_product(u,u); return(e); } static proc red(int i, module B, module U) { int j; poly r; for(j=i-1; j>=1; j--) { r=roundpoly(U[i][j]); B[i]=B[i]-r*B[j]; U[i]=U[i]-r*U[j]; } return(B,matrix(U)); } static proc initBBsU(matrix M) {//the columns of M a basis of a lattice over R int m=nrows(M); int c=ncols(M); module B=M; module Bs=M; poly f,k,u; matrix U=diag(1,c); int i,j; for(i=1; i<=c; i++) { for(j=1; j<=i-1; j++) { f=inner_product(B[i],Bs[j]); k=inner_product(Bs[j],Bs[j]); u=f/k; U[j,i]=u; Bs[i]=Bs[i]-u*Bs[j]; } (B,U)=red(i,B,U); } return(B,Bs,U); } static proc mymax(int i, int k) { if(i >= k) { return(i); } return(k); } proc realLLL(matrix M) "USAGE: realLLL(M); matrix M ASSUME: The columns of M represent a basis of a lattice. The groundfield is the field of real number or the field of complex numbers, the elements of M are real numbers. RETURN: matrix: the columns representing an LLL-reduced basis of the lattice given by M EXAMPLE: example realLLL; shows an example " { int n=ncols(M); int m=nrows(M); matrix U; module B,Bs; poly f,k,u; (B,Bs,U)=initBBsU(M); int i=1; int j; while(i 1/2) { (B,U)=red(i+1,B,U); } i=mymax(i-1,1); } } return(B); } example { "EXAMPLE:"; echo=2; ring r=(real,50),x,dp; matrix M[5][4]= 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 5*81726716.91827716, 817267.1691827716, poly(10)**30, 13*81726716.91827716; matrix L=realLLL(M); print(L); } singular-4.0.3+ds/Singular/LIB/redcgs.lib000066400000000000000000003340761266270727000201230ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////// version="version redcgs.lib 4.0.0.0 Jun_2013 "; // $Id: e00c2f27ae25b5a5f1606c262a29bb3d1a015b20 $ category="General purpose"; info=" LIBRARY: redcgs.lib Reduced Comprehensive Groebner Systems. OVERVIEW: Comprehensive Groebner Systems. Canonical Forms. The library contains Monte's algorithms to compute disjoint, reduced Comprehensive Groebner Systems (CGS). A CGS is a set of pairs of (segment,basis). The segments S_i are subsets of the parameter space, and the bases B_i are sets of polynomials specializing to Groebner bases of the specialized ideal for every point in S_i. The purpose of the routines in this library is to obtain CGS with better properties, namely disjoint segments forming a partition of the parameter space and reduced bases. Reduced bases are sets of polynomials that specialize to the reduced Groebner basis of the specialized ideal preserving the leading power products (lpp). The lpp characterize the type of solution in each segment. A further objective is to summarize as much as possible the segments with the same lpp into a single segment, and if possible to obtain a final result that is canonical, i.e. independent of the algorithm and only attached to the given ideal. There are three fundamental routines in the library: mrcgs, rcgs and crcgs. mrcgs (Minimal Reduced CGS) is an algorithm that packs so much as it is able to do (using algorithms adhoc) the segments with the same lpp, obtaining the minimal number of segments. The hypothesis is that the result is also canonical, but for the moment there is no proof of the uniqueness of this minimal packing. Moreover, the segments that are obtained are not locally closed, i.e. there are not difference of two varieties. On the other side, Michael Wibmer has proved that for homogeneous ideals, all the segments with reduced bases having the same lpp admit a unique basis specializing well. For this purpose it is necessary to extend the description of the elements of the bases to functions, forming sheaves of polynomials instead of simple polynomials, so that the polynomials in a sheaf either preserve the lpp of the corresponding polynomial of the specialized Groebner basis (and then it specializes well) or it specializes to 0. Moreover, in a sheaf, for every point in the corresponding segment, at least one of the polynomials specializes well. specializes well. And moreover Wibmer's Theorem ensures that the packed segments are locally closed, that is can be described as the difference of two varieties. Using Wibmer's Theorem we proved that an affine ideal can be homogenized, than discussed by mrcgs and finally de-homogenized. The bases so obtained can be reduced and specialize well in the segment. If the theoretic objective is reached, and all the segments of the homogenized ideal have been packed, locally closed segments will be obtained. If we only homogenize the given basis of the ideal, then we cannot ensure the canonicity of the partition obtained, because there are many different bases of the given ideal that can be homogenized, and the homogenized ideals are not identical. This corresponds to the algorithm rcgs and is recommended as the most practical routine. It provides locally closed segments and is usually faster than mrcgs and crcgs. But the given partition is not always canonical. Finally it is possible to homogenize the whole affine ideal, and then the packing algorithm will provide canonical segments by dehomogenizing. This corresponds to crcgs routine. It provides the best description of the segments and bases. In contrast crcgs algorithm is usually much more time consuming and it will not always finish in a reasonable time. Moreover it will contain more segments than mrcgs and possibly also more than rcgs. But the actual algorithms in the library to pack segments have some lacks. They are not theoretically always able to pack the segments that we know that can be packed. Nevertheless, thanks to Wibmer's Theorem, the algorithms rcgs and crcgs are able to detect if the objective has not been reached, and if so, to give a Warning. The warning does not invalidate the output, but it only recognizes that the theoretical objective is not completely reached by the actual computing methods and that some segments that can be packed have not been packed with a single basis. The routine buildtree is the first algorithm used in all the previous methods providing a first disjoint CGS, and can be used if none of the three fundamental algorithms of the library finishes in a reasonable time. There are also routines to visualize better the output of the previous algorithms: finalcases can be applied to the list provided by buildtree to obtain the CGS. The list provided by buildtree contains the whole discussion, and finalcases extracts the CGS. The output of buildtree can also be transformed into a file using buildtreetoMaple routine that can be read in Maple. Using Monte's dpgb library in Maple the output can be plotted (with the routine tplot). To plot the output of mrcgs, rcgs or crcgs in Maple, the library also provides the routine cantreetoMaple. The file written using it and read in Maple can then be plotted with the command plotcantree and printed with printcantree from the Monte's dpgb library in Maple. The output of mrcgs, rcgs and crcgs is given in form of tree using prime ideals in a canonical form that is described in the papers. Nevertheless this canonical form is somewhat uncomfortable to be interpreted. When the segments are all locally closed (and this is always the case for rcgs and crcgs) the routine cantodiffcgs transforms the output into a simpler form having only one list element for each segment and providing the two varieties whose difference represent the segment also in a canonical form. AUTHORS: Antonio Montes , Hans Schoenemann. OVERVIEW: see \"Minimal Reduced Comprehensive Groebner Systems\" by Antonio Montes. (http://www-ma2.upc.edu/~montes/). NOTATIONS: All given and determined polynomials and ideals are in the @* basering K[a][x]; (a=parameters, x=variables) @* After defining the ring and calling setglobalrings(); the rings @* @R (K[a][x]), @* @P (K[a]), @* @RP (K[x,a]) are defined globally @* They are used internally and can also be used by the user. @* The fundamental routines are: buildtree, mrcgs, rcgs and crcgs PROCEDURES: setglobalrings(); It is called by the fundamental routines of the library: (buildtree, mrcgs, rcgs, crcgs). After calling it, the rings @R, @P and @RP are defined globally. memberpos(f,J); Returns the list of two integers: the value 0 or 1 depending on if f belongs to J or not, and the position in J (0 if it does not belong). subset(F,G); If all elements of F belong to the ideal G it returns 1, and 0 otherwise. pdivi(f,F); Pseudodivision of a polynomial f by an ideal F in @R. Returns a list (r,q,m) such that m*f=r+sum(q.G). facvar(ideal J) Returns all the free-square factors of the elements of ideal J (non repeated). Integer factors are ignored, even 0 is ignored. It can be called from ideal @R, but the given ideal J must only contain polynomials in the parameters. redspec(N,W); Given null and non-null conditions depending only on the parameters it returns a red-specification. pnormalform(f,N,W); Reduces the polynomial f w.r.t. to the null condition ideal N and the non-null condition ideal W (both depending on the parameters). buildtree(F); Returns a list T describing a first reduced CGS of the ideal F in K[a][x]. buildtreetoMaple(T); Writes into a file the output of buildtree in Maple readable form. finalcases(T); From the output of buildtree it provides the list of its terminal vertices. That list represents the dichotomic, reduced CGS obtained by buildtree. mrcgs(F); Returns a list T describing the Minimal Reduced CGS of the ideal F of K[a][x] rcgs(F); Returns a list T describing the Reduced CGS of the ideal F of K[a][x] obtained by direct homogenizing and de-homogenizing the basis of the given ideal. crcgs(F); Returns a list T describing the Canonical Reduced CGS of the ideal F of K[a][x] obtained by homogenizing and de-homogenizing the initial ideal. cantreetoMaple)(M); Writes into a file the output of mrcgs, rcgs or crcgs in Maple readable form. cantodiffcgs(list L);From the output of rcgs or crcgs (or even of mrcgs when it is possible) it returns a simpler list where the segments are given as difference of varieties. SEE ALSO: compregb_lib "; // ************ Begin of the redCGS library ********************* // Library redCGS // (Reduced Comprehesive Groebner Systems): // Initial data: 21-1-2008 // Release 1: // Final data: 3_7-2008 // All given and determined polynomials and ideals are in the // basering K[a][x]; // After calling setglobalrings(); the rings // @R (K[a][x]), // @P (K[a]), // @RP (K[x,a]) are globally defined // They are used internally and can also be called by the user; // setglobalrings() is called by buildtree, so it is not required to // call setglobalrings before using // the fundamental routines of the library. // ************ Begin of buildtree ****************************** LIB "primdec.lib"; proc setglobalrings() "USAGE: setglobalrings(); No arguments RETURN: After its call the rings @R=K[a][x], @P=K[a], @RP=K[x,a] are defined as global variables. NOTE: It is called by the fundamental routines of the library. The user does not need to call it, except when none of the fundamental routines have been called and some other routines of the library are used. The basering R, must be of the form K[a][x], a=parameters, x=variables, and should be defined previously. KEYWORDS: ring, rings EXAMPLE: setglobalrings; shows an example" { def @R=basering; // must be of the form K[a][x], a=parameters, x=variables def Rx=ringlist(@R); def @P=ring(Rx[1]); list Lx; Lx[1]=0; Lx[2]=Rx[2]+Rx[1][2]; Lx[3]=Rx[1][3]; Lx[4]=Rx[1][4]; //def @K=ring(Lx); //exportto(Top,@K); //global ring K[x,a] with the order of x extended to x,a Rx[1]=0; def D=ring(Rx); def @RP=D+@P; exportto(Top,@R); // global ring K[a][x] exportto(Top,@P); // global ring K[a] exportto(Top,@RP); // global ring K[x,a] with product order setring(@R); } example { "EXAMPLE:"; echo = 2; ring R=(0,a,b),(x,y,z),dp; setglobalrings(); @R; @P; @RP; } //*************Auxilliary routines************** // cld : clears denominators of an ideal and normalizes to content 1 // can be used in @R or @P or @RP // input: // ideal J (J can be also poly), but the output is an ideal; // output: // ideal Jc (the new form of ideal J without denominators and // normalized to content 1) proc cld(ideal J) { if (size(J)==0){return(ideal(0));} def RR=basering; setring(@RP); def Ja=imap(RR,J); ideal Jb; if (size(Ja)==0){return(ideal(0));} int i; def j=0; for (i=1;i<=ncols(Ja);i++){if (size(Ja[i])!=0){j++; Jb[j]=cleardenom(Ja[i]);}} setring(RR); def Jc=imap(@RP,Jb); return(Jc); } proc memberpos(def f,def J) "USAGE: memberpos(f,J); (f,J) expected (polynomial,ideal) or (int,list(int)) or (int,intvec) or (intvec,list(intvec)) or (list(int),list(list(int))) or (ideal,list(ideal)) or (list(intvec), list(list(intvec))). The ring can be @R or @P or @RP or any other. RETURN: The list (t,pos) t int; pos int; t is 1 if f belongs to J and 0 if not. pos gives the position in J (or 0 if f does not belong). EXAMPLE: memberpos; shows an example" { int pos=0; int i=1; int j; int t=0; int nt; if (typeof(J)=="ideal"){nt=ncols(J);} else{nt=size(J);} if ((typeof(f)=="poly") or (typeof(f)=="int")) { // (poly,ideal) or // (poly,list(poly)) // (int,list(int)) or // (int,intvec) i=1; while(i<=nt) { if (f==J[i]){return(list(1,i));} i++; } return(list(0,0)); } else { if ((typeof(f)=="intvec") or ((typeof(f)=="list") and (typeof(f[1])=="int"))) { // (intvec,list(intvec)) or // (list(int),list(list(int))) i=1; t=0; pos=0; while((i<=nt) and (t==0)) { t=1; j=1; if (size(f)!=size(J[i])){t=0;} else { while ((j<=size(f)) and t) { if (f[j]!=J[i][j]){t=0;} j++; } } if (t){pos=i;} i++; } if (t){return(list(1,pos));} else{return(list(0,0));} } else { if (typeof(f)=="ideal") { // (ideal,list(ideal)) i=1; t=0; pos=0; while((i<=nt) and (t==0)) { t=1; j=1; if (ncols(f)!=ncols(J[i])){t=0;} else { while ((j<=ncols(f)) and t) { if (f[j]!=J[i][j]){t=0;} j++; } } if (t){pos=i;} i++; } if (t){return(list(1,pos));} else{return(list(0,0));} } else { if ((typeof(f)=="list") and (typeof(f[1])=="intvec")) { // (list(intvec),list(list(intvec))) i=1; t=0; pos=0; while((i<=nt) and (t==0)) { t=1; j=1; if (size(f)!=size(J[i])){t=0;} else { while ((j<=size(f)) and t) { if (f[j]!=J[i][j]){t=0;} j++; } } if (t){pos=i;} i++; } if (t){return(list(1,pos));} else{return(list(0,0));} } } } } } example { "EXAMPLE:"; echo = 2; list L=(7,4,5,1,1,4,9); memberpos(1,L); } proc subset(def J,def K) "USAGE: subset(J,K); (J,K) expected (ideal,ideal) or (list, list) RETURN: 1 if all the elements of J are in K, 0 if not. EXAMPLE: subset; shows an example;" { int i=1; int nt; if (typeof(J)=="ideal"){nt=ncols(J);} else{nt=size(J);} if (size(J)==0){return(1);} while(i<=nt) { if (memberpos(J[i],K)[1]){i++;} else {return(0);} } return(1); } example { "EXAMPLE:"; echo = 2; list J=list(7,3,2); list K=list(1,2,3,5,7,8); subset(J,K); } //*************Auxilliary routines************** // elimintfromideal: elimine the constant numbers from the ideal // (designed for W, nonnull conditions) // input: ideal J in the ring @P // output:ideal K with the elements of J that are non constants, in the ring @P proc elimintfromideal(ideal J) { int i; int j=0; ideal K; if (size(J)==0){return(ideal(0));} for (i=1;i<=ncols(J);i++){if (size(variables(J[i])) !=0){j++; K[j]=J[i];}} return(K); } // simpqcoeffs : simplifies a quotient of two polynomials of @R // for ring @R // input: two coeficients (or terms) of @R (that are considered as quotients) // output: the two coeficients reduced without common factors proc simpqcoeffs(poly n,poly m) { def nc=content(n); def mc=content(m); def gc=gcd(nc,mc); ideal s=n/gc,m/gc; return (s); } // pdivi : pseudodivision of a polynomial f by an ideal F in @R // in the ring @R // input: // poly f0 (given in the ring @R) // ideal F0 (given in the ring @R) // output: // list (poly r, ideal q, poly mu) proc pdivi(poly f,ideal F) "USAGE: pdivi(f,F); poly f: the polynomial to be divided ideal F: the divisor ideal RETURN: A list (poly r, ideal q, poly m). r is the remainder of the pseudodivision, q is the ideal of quotients, and m is the factor by which f is to be multiplied. NOTE: Pseudodivision of a polynomial f by an ideal F in @R. Returns a list (r,q,m) such that m*f=r+sum(q.G). KEYWORDS: division, reduce EXAMPLE: pdivi; shows an example" { int i; int j; poly r=0; poly mu=1; def p=f; ideal q; for (i=1; i<=size(F); i++){q[i]=0;} ideal lpf; ideal lcf; for (i=1;i<=size(F);i++){lpf[i]=leadmonom(F[i]);} for (i=1;i<=size(F);i++){lcf[i]=leadcoef(F[i]);} poly lpp; poly lcp; poly qlm; poly nu; poly rho; int divoc=0; ideal qlc; while (p!=0) { i=1; divoc=0; lpp=leadmonom(p); lcp=leadcoef(p); while (divoc==0 and i<=size(F)) { qlm=lpp/lpf[i]; if (qlm!=0) { qlc=simpqcoeffs(lcp,lcf[i]); nu=qlc[2]; mu=mu*nu; rho=qlc[1]*qlm; p=nu*p-rho*F[i]; r=nu*r; for (j=1;j<=size(F);j++){q[j]=nu*q[j];} q[i]=q[i]+rho; divoc=1; } else {i++;} } if (divoc==0) { r=r+lcp*lpp; p=p-lcp*lpp; } } list res=r,q,mu; return(res); } example { "EXAMPLE:"; echo = 2; ring R=(0,a,b,c),(x,y),dp; setglobalrings(); poly f=(ab-ac)*xy+(ab)*x+(5c); ideal F=ax+b,cy+a; def r=pdivi(f,F); r; r[3]*f-(r[2][1]*F[1]+r[2][2]*F[2])-r[1]; } // pspol : S-poly of two polynomials in @R // @R // input: // poly f (given in the ring @R) // poly g (given in the ring @R) // output: // list (S, red): S is the S-poly(f,g) and red is a Boolean variable // if red==1 then S reduces by Buchberger 1st criterion (not used) proc pspol(poly f,poly g) { def lcf=leadcoef(f); def lcg=leadcoef(g); def lpf=leadmonom(f); def lpg=leadmonom(g); def v=gcd(lpf,lpg); def s=simpqcoeffs(lcf,lcg); def vf=lpf/v; def vg=lpg/v; poly S=s[2]*vg*f-s[1]*vf*g; return(S); } // facvar: Returns all the free-square factors of the elements // of ideal J (non repeated). Integer factors are ignored, // even 0 is ignored. It can be called from ideal @R, but // the given ideal J must only contain poynomials in the // parameters. // Operates in the ring @P, but can be called from ring @R. // input: ideal J // output: ideal Jc: Returns all the free-square factors of the elements // of ideal J (non repeated). Integer factors are ignored, // even 0 is ignored. It can be called from ideal @R, but // the given ideal J must only contain poynomials in the // parameters. proc facvar(ideal J) "USAGE: facvar(J); J: an ideal in the parameters RETURN: all the free-square factors of the elements of ideal J (non repeated). Integer factors are ignored, even 0 is ignored. It can be called from ideal @R, but the given ideal J must only contain poynomials in the parameters. NOTE: Operates in the ring @P, and the ideal J must contain only polynomials in the parameters, but can be called from ring @R. KEYWORDS: factor EXAMPLE: facvar; shows an example" { int i; def RR=basering; setring(@P); def Ja=imap(RR,J); if(size(Ja)==0){return(ideal(0));} Ja=elimintfromideal(Ja); // also in ideal @P ideal Jb; if (size(Ja)==0){Jb=ideal(0);} else { for (i=1;i<=ncols(Ja);i++){if(size(Ja[i])!=0){Jb=Jb,factorize(Ja[i],1);}} Jb=simplify(Jb,2+4+8); Jb=cld(Jb); Jb=elimintfromideal(Jb); // also in ideal @P } setring(RR); def Jc=imap(@P,Jb); return(Jc); } example { "EXAMPLE:"; echo = 2; ring R=(0,a,b,c),(x,y,z),dp; setglobalrings(); ideal J=a2-b2,a2-2ab+b2,abc-bc; facvar(J); } // Wred: eliminate the factors in the polynom f that are in W // in ring @RP // input: // poly f: // ideal W of non-null conditions (already supposed that it is facvar) // output: // poly f2 where the non-null conditions in W have been dropped from f proc Wred(poly f, ideal W) { if (f==0){return(f);} def RR=basering; setring(@RP); def ff=imap(RR,f); def RPW=imap(RR,W); def l=factorize(ff,2); int i; poly f1=1; for(i=1;i<=size(l[1]);i++) { if ((memberpos(l[1][i],RPW)[1]) or (memberpos(-l[1][i],RPW)[1])){;} else{f1=f1*((l[1][i])^(l[2][i]));} } setring(RR); def f2=imap(@RP,f1); return(f2); } // pnormalform: reduces a polynomial w.r.t. a red-spec dividing by N and eliminating factors in W. // called in the ring @R // operates in the ring @RP // input: // poly f // ideal N (depends only on the parameters) // ideal W (depends only on the parameters) // (N,W) must be a red-spec (depends only on the parameters) // output: poly f2 reduced w.r.t. to the red-spec (N,W) // note: for security a lot of work is done. If (N,W) is already a red-spec it should be simplified proc pnormalform(poly f, ideal N, ideal W) "USAGE: pnormalform(f,N,W); f: the polynomial to be reduced modulo N,W (in parameters and variables) N: the null conditions ideal W: the non-null conditions (set of irreducible polynomials, ideal) RETURN: a reduced polynomial g of f, whose coefficients are reduced modulo N and having no factor in W. NOTE: Should be called from ring @R. Ideals N and W must be polynomials in the parameters forming a red-specification (see definition) the papers). KEYWORDS: division, pdivi, reduce EXAMPLE: pnormalform; shows an example" { def RR=basering; setring(@RP); def fa=imap(RR,f); def Na=imap(RR,N); def Wa=imap(RR,W); option(redSB); Na=groebner(Na); def r=cld(reduce(fa,Na)); def f1=Wred(r[1],Wa); setring(RR); def f2=imap(@RP,f1); return(f2) } example { "EXAMPLE:"; echo = 2; ring R=(0,a,b,c),(x,y),dp; setglobalrings(); poly f=(b^2-1)*x^3*y+(c^2-1)*x*y^2+(c^2*b-b)*x+(a-bc)*y; ideal N=(ab-c)*(a-b),(a-bc)*(a-b); ideal W=a^2-b^2,bc; def r=redspec(N,W); pnormalform(f,r[1],r[2]); } // idint: ideal intersection // in the ring @P. // it works in an extended ring // input: two ideals in the ring @P // output the intersection of both (is not a GB) proc idint(ideal I, ideal J) { def RR=basering; ring T=0,t,lp; def K=T+RR; setring(K); def Ia=imap(RR,I); def Ja=imap(RR,J); ideal IJ; int i; for(i=1;i<=size(Ia);i++){IJ[i]=t*Ia[i];} for(i=1;i<=size(Ja);i++){IJ[size(Ia)+i]=(1-t)*Ja[i];} ideal eIJ=eliminate(IJ,t); setring(RR); return(imap(K,eIJ)); } // redspec: generates a red-specification // called in any ring // it changes to the ring @P // input: // ideal N : the ideal of null-conditions // ideal W : set of non-null polynomials: if W corresponds to no non null conditions then W=ideal(0) // otherwise it should be given as an ideal. // returns: list (Na,Wa,DGN) // the completely reduced specification: // Na = ideal reduced and radical of the red-spec // facvar(Wa) = ideal the reduced non-null set of polynomials of the red-spec. // if it corresponds to no non null conditions then it is ideal(0) // otherwise the ideal is returned. // DGN = the list of prime ideals associated to Na (uses primASSGTZ in "primdec.lib") // none of the polynomials in facvar(Wa) are contained in none of the ideals in DGN // If the given conditions are not compatible, then N=ideal(1) and DGN=list(ideal(1)) proc redspec(ideal Ni, ideal Wi) "USAGE: redspec(N,W); N: null conditions ideal W: set of non-null polynomials (ideal) RETURN: a list (N1,W1,L1) containing a red-specification of the segment (N,W). N1 is the radical reduced ideal characterizing the segment. V(N1) is the Zarisky closure of the segment (N,W). The segment S=V(N1) \ V(h), where h=prod(w in W1) N1 is uniquely determined and no prime component of N1 contains none of the polynomials in W1. The polynomials in W1 are prime and reduced w.r.t. N1, and are considered non-null on the segment. L1 contains the list of prime components of N1. NOTE: can be called from ring @R but it works in ring @P. KEYWORDS: specification EXAMPLE: redspec; shows an example" { ideal Nc; ideal Wc; def RR=basering; setring(@P); def N=imap(RR,Ni); def W=imap(RR,Wi); ideal Wa; ideal Wb; if(size(W)==0){Wa=ideal(0);} //when there are no non-null conditions then W=ideal(0) else { Wa=facvar(W); } if (size(N)==0) { setring(RR); Wc=imap(@P,Wa); return(list(ideal(0), Wc, list(ideal(0)))); } int i; list LNb; list LNa; def LN=minAssGTZ(N); for (i=1;i<=size(LN);i++) { option(redSB); LNa[i]=groebner(LN[i]); } poly h=1; if (size(Wa)!=0) { for(i=1;i<=size(Wa);i++){h=h*Wa[i];} } ideal Na; intvec save_opt=option(get); if (size(N)!=0 and (size(LNa)>0)) { option(returnSB); Na=intersect(LNa[1..size(LNa)]); option(redSB); Na=groebner(Na); // T_ is needed? option(set,save_opt); } attrib(Na,"isSB",1); if (reduce(h,Na,1)==0) { setring(RR); Wc=imap(@P,Wa); return(list (ideal(1),Wc,list(ideal(1)))); } i=1; while(i<=size(LNa)) { if (reduce(h,LNa[i],1)==0){LNa=delete(LNa,i);} else{ i++;} } if (size(LNa)==0) { setring(RR); return(list(ideal(1),ideal(0),list(ideal(1)))); } option(returnSB); ideal Nb=intersect(LNa[1..size(LNa)]); option(redSB); Nb=groebner(Nb); // T_ is needed? option(set,save_opt); if (size(Wa)==0) { setring(RR); Nc=imap(@P,Nb); Wc=imap(@P,Wa); LNb=imap(@P,LNa); return(list(Nc,Wc,LNb)); } Wb=ideal(0); attrib(Nb,"isSB",1); for (i=1;i<=size(Wa);i++){Wb[i]=reduce(Wa[i],Nb);} Wb=facvar(Wb); if (size(LNa)!=0) { setring(RR); Nc=imap(@P,Nb); Wc=imap(@P,Wb); LNb=imap(@P,LNa); return(list(Nc,Wc,LNb)) } else { setring(RR); Nd=imap(@P,Nb); Wc=imap(@P,Wb); kill LNb; list LNb; return(list(Nd,Wc,LNb)) } } example { "EXAMPLE:"; echo = 2; ring r=(0,a,b,c),(x,y),dp; setglobalrings(); ideal N=(ab-c)*(a-b),(a-bc)*(a-b); ideal W=a^2-b^2,bc; redspec(N,W); } // lesspol: compare two polynomials by its leading power products // input: two polynomials f,g in the ring @R // output: 0 if f=g proc lesspol(poly f, poly g) { if (leadmonom(f)=P[size(P)][3]){Pr=insert(P,pair,size(P)); return(Pr);} kill Pr; list Pr; int j; int i=1; int loc=0; while((i<=size(P)) and (loc==0)) { if (pair[3]>=P[i][3]){j=i; i++;} else{loc=1; j=i-1;} } Pr=insert(P,pair,j); return(Pr); } // orderingpairs: // input: ideal F // output: list of ordered pairs (i,j,lcmij) of F in ascending order of lcmij // if a pair verifies Buchberger 1st criterion it is not stored // ring @R proc orderingpairs(ideal F) { int i; int j; poly lm; poly lpf; poly lpg; list P; list pair; if (size(F)<=1){return(P);} for (i=1;i<=size(F)-1;i++) { for (j=i+1;j<=size(F);j++) { lm=lcmlmonoms(F[i],F[j]); // Buchberger 1st criterion lpf=leadmonom(F[i]); lpg=leadmonom(F[j]); if (lpf*lpg!=lm) { pair=(i,j,lm); P=placepairinlist(pair,P); } } } return(P); } // Buchberger 2nd criterion // input: integers i,j // list P of pairs of the form (i,j) not yet verified // ring @R proc criterion(int i, int j, list P, ideal B) { def lcmij=lcmlmonoms(B[i],B[j]); int crit=0; int k=1; list ik; list jk; while ((k<=size(B)) and (crit==0)) { if ((k!=i) and (k!=j)) { if (i1) and (lab[1]==-1)) {lab=lab[2..size(lab)];} def term=vertex[2]; def B=vertex[3]; def N=vertex[4]; def W=vertex[5]; def LN=vertex[6]; def lpp=vertex[7]; def cond=vertex[8]; def lab0=lab; def lab1=lab; if ((size(lab)==1) and (lab[1]==-1)) { lab0=0; lab1=1; } else { lab0[size(lab)+1]=0; lab1[size(lab)+1]=1; } list vertex0; list vertex1; ideal B0; ideal lpp0; ideal lpp1; ideal N0=1; def W0=ideal(0); list LN0=ideal(1); def B1=B; def N1=N; def W1=W; list LN1=LN; list L; if (size(P)==0) { L=discusspolys(B,list(N,W,LN)); N0=L[1][1]; W0=L[1][2]; LN0=L[1][3]; N1=L[2][1]; W1=L[2][2]; LN1=L[2][3]; B1=L[3]; cond=L[4]; } if ((size(B1)!=0) and (N0[1]==1)) { L=discussSpolys(B1,list(N1,W1,LN1),P); N0=L[1][1]; W0=L[1][2]; LN0=L[1][3]; N1=L[2][1]; W1=L[2][2]; LN1=L[2][3]; B1=L[3]; P1=L[4]; cond=L[5]; lpp=ideal(0); for (i=1;i<=size(B1);i++){lpp[i]=leadmonom(B1[i]);} } vertex[3]=B1; vertex[4]=N1; // unnecessary vertex[5]=W1; // unnecessary vertex[6]=LN1;// unnecessary vertex[7]=lpp; vertex[8]=cond; if (size(@T)>0) { pos=size(@T)+1; @T[pos]=vertex; } if ((N0[1]!=1) and (N1[1]!=1)) { vertex1[1]=lab1; vertex1[2]=0; vertex1[3]=B1; vertex1[4]=N1; vertex1[5]=W1; vertex1[6]=LN1; vertex1[7]=lpp1; vertex1[8]=cond; if (size(B1)==0){B0=ideal(0); lpp0=ideal(0);} else { j=1; lpp0=ideal(0); for (i=1;i<=size(B1);i++) { f=pnormalform(B1[i],N0,W0); if (f!=0){B0[j]=f; lpp0[j]=leadmonom(f);j++;} } } vertex0[1]=lab0; vertex0[2]=0; vertex0[3]=B0; vertex0[4]=N0; vertex0[5]=W0; vertex0[6]=LN0; vertex0[7]=lpp0; vertex0[8]=cond; recbuildtree(vertex0,P0); recbuildtree(vertex1,P1); } else { vertex[2]=1; B1=mingb(B1); vertex[3]=redgb(B1,N1,W1); vertex[4]=N1; vertex[5]=W1; vertex[6]=LN1; lpp=ideal(0); for (i=1;i<=size(vertex[3]);i++){lpp[i]=leadmonom(vertex[3][i]);} vertex[7]=lpp; vertex[8]=cond; @T[pos]=vertex; } } //****************End of BuildTree************************************* //****************Begin BuildTree To Maple***************************** // buildtreetoMaple: writes the list provided by buildtree to a file // containing the table representing it in Maple // writes the list L=buildtree(F) to a file "writefile" that // is readable by Maple whith name T // input: // L: the list output by buildtree // T: the name (string) of the output table in Maple // writefile: the name of the datafile where the output is to be stored // output: // the result is written on the datafile "writefile" containig // the assignement to the table with name "T" proc buildtreetoMaple(list L, string T, string writefile) "USAGE: buildtreetoMaple(T, TM, writefile); T: is the list provided by buildtree, TM: is the name (string) of the table variable in Maple that will represent the output of buildtree, writefile: is the name (string) of the file where to write the content. RETURN: writes the list provided by buildtree to a file containing the table representing it in Maple. KEYWORDS: buildtree, Maple EXAMPLE: buildtreetoMaple; shows an example" { short=0; poly cond; int i; link LLw=":w "+writefile; string La=string("table(",T,");"); write(LLw, La); close(LLw); link LLa=":a "+writefile; def RL=ringlist(@R); list p=RL[1][2]; string param=string(p[1]); if (size(p)>1) { for(i=2;i<=size(p);i++){param=string(param,",",p[i]);} } list v=RL[2]; string vars=string(v[1]); if (size(v)>1) { for(i=2;i<=size(v);i++){vars=string(vars,",",v[i]);} } list xord; list pord; if (RL[1][3][1][1]=="dp"){pord=string("tdeg(",param);} if (RL[1][3][1][1]=="lp"){pord=string("plex(",param);} if (RL[3][1][1]=="dp"){xord=string("tdeg(",vars);} if (RL[3][1][1]=="lp"){xord=string("plex(",vars);} write(LLa,string(T,"[[9]]:=",xord,");")); write(LLa,string(T,"[[10]]:=",pord,");")); write(LLa,string(T,"[[11]]:=true; ")); list S; for (i=1;i<=size(L);i++) { if (L[i][2]==0) { cond=L[i][8]; S=btcond(T,L[i],cond); write(LLa,S[1]); write(LLa,S[2]); } S=btbasis(T,L[i]); write(LLa,S); S=btN(T,L[i]); write(LLa,S); S=btW(T,L[i]); write(LLa,S); if (L[i][2]==1) {S=btterminal(T,L[i]); write(LLa,S);} S=btlpp(T,L[i]); write(LLa,S); } close(LLa); } example { "EXAMPLE:"; echo = 2; ring R=(0,a1,a2,a3,a4),(x1,x2,x3,x4),dp; ideal F=x4-a4+a2, x1+x2+x3+x4-a1-a3-a4, x1*x3*x4-a1*a3*a4, x1*x3+x1*x4+x2*x3+x3*x4-a1*a4-a1*a3-a3*a4; def T=buildtree(F); finalcases(T); buildtreetoMaple(T,"Tb","Tb.txt"); } // auxiliary routine called by buildtreetoMaple // input: // list L: element i of the list of buildtree(F) // output: // the string of T[[lab,1]]:=label; in Maple proc btterminal(string T, list L) { int i; string Li; string term; string coma=","; if (L[2]==0){term="false";} else {term="true";} def lab=L[1]; string slab; if ((size(lab)==1) and lab[1]==-1) {slab="";coma="";} //if (size(lab)==0) else { slab=string(lab[1]); if (size(lab)>=1) { for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);} } } Li=string(T,"[[",slab,coma,"6]]:=",term,"; "); return(Li); } // auxiliary routine called by buildtreetoMaple // input: // list L: element i of the list of buildtree(F) // output: // the string of T[[lab,3]] (basis); in Maple proc btbasis(string T, list L) { int i; string Li; string coma=","; def lab=L[1]; string slab; if ((size(lab)==1) and lab[1]==-1) {slab="";coma="";} //if (size(lab)==0) else { slab=string(lab[1]); if (size(lab)>=1) { for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);} } } Li=string(T,"[[",slab,coma,"3]]:=[",L[3],"]; "); return(Li); } // auxiliary routine called by buildtreetoMaple // input: // list L: element i of the list of buildtree(F) // output: // the string of T[[lab,4]] (null conditions ideal); in Maple proc btN(string T, list L) { int i; string Li; string coma=","; def lab=L[1]; string slab; if ((size(lab)==1) and lab[1]==-1) {slab=""; coma="";} else { slab=string(lab[1]); if (size(lab)>=1) { for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);} } } if ((size(lab)==1) and lab[1]==-1) {Li=string(T,"[[",slab,coma,"4]]:=[ ]; ");} else {Li=string(T,"[[",slab,coma,"4]]:=[",L[4],"]; ");} return(Li); } // auxiliary routine called by buildtreetoMaple // input: // list L: element i of the list of buildtree(F) // output: // the string of T[[lab,5]] (null conditions ideal); in Maple proc btW(string T, list L) { int i; string Li; string coma=","; def lab=L[1]; string slab; if ((size(lab)==1) and lab[1]==-1) {slab=""; coma="";} else { slab=string(lab[1]); if (size(lab)>=1) { for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);} } } if (size(L[5])==0) {Li=string(T,"[[",slab,coma,"5]]:={ }; ");} else {Li=string(T,"[[",slab,coma,"5]]:={",L[5],"}; ");} return(Li); } // auxiliary routine called by buildtreetoMaple // input: // list L: element i of the list of buildtree(F) // output: // the string of T[[lab,12]] (lpp); in Maple proc btlpp(string T, list L) { int i; string Li; string coma=",";; def lab=L[1]; string slab; if ((size(lab)==1) and lab[1]==-1) {slab=""; coma="";} else { slab=string(lab[1]); if (size(lab)>=1) { for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);} } } if (size(L[7])==0) { Li=string(T,"[[",slab,coma,"12]]:=[ ]; "); } else { Li=string(T,"[[",slab,coma,"12]]:=[",L[7],"]; "); } return(Li); } // auxiliary routine called by buildtreetoMaple // input: // list L: element i of the list of buildtree(F) // output: // the list of strings of (T[[lab,0]]=0,T[[lab,1]]<>0); in Maple proc btcond(string T, list L, poly cond) { int i; string Li1; string Li2; def lab=L[1]; string slab; string coma=",";; if ((size(lab)==1) and lab[1]==-1) {slab=""; coma="";} else { slab=string(lab[1]); if (size(lab)>=1) { for (i=2;i<=size(lab);i++){slab=string(slab,",",lab[i]);} } } Li1=string(T,"[[",slab+coma,"0]]:=",L[8],"=0; "); Li2=string(T,"[[",slab+coma,"1]]:=",L[8],"<>0; "); return(list(Li1,Li2)); } //*****************End of BuildtreetoMaple********************* //*****************Begin of Selectcases************************ // given an intvec with sum=n // it returns the list of intvect with the sum=n+1 proc comp1(intvec l) { list L; int p=size(l); int i; if (p==0){return(l);} if (p==1){return(list(intvec(l[1]+1)));} L[1]=intvec((l[1]+1),l[2..p]); L[p]=intvec(l[1..p-1],(l[p]+1)); for (i=2;im[1,i])){j++;} if (m1[1,j]==m[1,i]){C[i]=m1[2,j];} } return(list(T,C)); } // given teh ideal of non-null conditions and an intvec lambda // with the exponents of each w in W // it returns the polynomial prod (w_i)^(lambda_i). proc WW(ideal W, intvec lambda) { if (size(W)==0){return(poly(1));} poly w=1; int i; for (i=1;i<=ncols(W);i++) { w=w*(W[i])^(lambda[i]); } return(w); } // given a polynomial f and the non-null conditions W // WPred eliminates the factors in f that are in W // ring @PAB // input: // poly f: // ideal W of non-null conditions (already supposed that it is facvar) // output: // poly f2 where the non-null conditions in W have been dropped from f proc WPred(poly f, ideal W) { if (f==0){return(f);} def l=factorize(f,2); int i; poly f1=1; for(i=1;i<=size(l[1]);i++) { if (memberpos(l[1][i],W)[1]){;} else{f1=f1*((l[1][i])^(l[2][i]));} } return(f1); } //genimage // ring @R //input: // poly f1, idel N1,ideal W1,poly f2, ideal N2, ideal W2 // corresponding to two polynomials having the same lpp // f1 in the redspec given by N1,W1, f2 in the redspec given by N2,W2 //output: // the list of (ideal GG, list(list r1, list r2)) // where g an ideal whose elements have the same lpp as f1 and f2 // that specialize well to f1 in N1,W1 and to f2 in N2,W2. // If it doesn't exist a genimage, then g=ideal(0). proc genimage(poly f1, ideal N1, ideal W1, poly f2, ideal N2, ideal W2) { int i; ideal W12; poly ff1; poly g1=0; ideal GG; int tt=1; // detect whether f1 reduces to 0 on segment 2 ff1=pnormalform(f1,N2,W2); if (ff1==0) { // detect whether N1 is included in N2 def RR=basering; setring @P; def NP1=imap(RR,N1); def NP2=imap(RR,N2); poly nr; i=1; while ((tt) and (i<=size(NP1))) { nr=reduce(NP1[i],NP2); if (nr!=0){tt=0;} i++; } setring(RR); } else{tt=0;} if (tt==1) { // detect whether W1 intersect W2 is non-empty for (i=1;i<=size(W1);i++) { if (memberpos(W1[i],W2)[1]) { W12[size(W12)+1]=W1[i]; } else { if (nonnull(W1[i],N2,W2)) { W12[size(W12)+1]=W1[i]; } } } for (i=1;i<=size(W2);i++) { if (not(memberpos(W2[i],W12)[1])) { W12[size(W12)+1]=W2[i]; } } } if (tt==1){g1=extendpoly(f1,N1,W12);} if (g1!=0) { //T_ "genimage has found a more generic basis (method 1)"; //T_ "f1:"; f1; "N1:"; N1; "W1:"; W1; //T_ "f2:"; f2; "N2:"; N2; "W2:"; W2; //T_ "g1:"; g1; if (pnormalform(g1,N1,W1)==0) { GG=f1,g1; //T_ "A sheaf has been found (method 2)"; } else { GG=g1; } return(GG); } // begins the second step; int bound=6; // in ring @R int j; int g=0; int alpha; int r1; int s1=1; int s2=1; poly G; matrix qT; matrix T; ideal N10; poly GT; ideal N12=N1,N2; def varx=maxideal(1); int nx=size(varx); poly pvarx=1; for (i=1;i<=nx;i++){pvarx=pvarx*varx[i];} def m=coef(43*f1+157*f2,pvarx); def m1=coef(f1,pvarx); def m2=coef(f2,pvarx); list L1=adaptcoef(m,m1); list L2=adaptcoef(m,m2); ideal Tm=L1[1]; ideal c1=L1[2]; ideal c2=L2[2]; poly ww1; poly ww2; poly cA1; poly cB1; matrix TT; poly H; list r; ideal q; poly mu; ideal N; // in ring @PAB list Px=ringlist(@P); list v="@A","@B"; Px[2]=Px[2]+v; def npx=size(Px[3][1][2]); Px[3][1][2]=1:(npx+size(v)); def @PAB=ring(Px); setring(@PAB); poly PH; ideal NP; list rP; def PN1=imap(@R,N1); def PW1=imap(@R,W1); def PN2=imap(@R,N2); def PW2=imap(@R,W2); def a1=imap(@R,c1); def a2=imap(@R,c2); matrix PT; ideal PN; ideal PN12=PN1,PN2; PN=liftstd(PN12,PT); list compos1; list compos2; list compos0; intvec comp0; poly w1=0; poly w2=0; poly h; poly cA=0; poly cB=0; int t=0; list l; poly h1; g=0; while ((g<=bound) and not(t)) { compos0=comp(g,2); r1=1; while ((r1<=size(compos0)) and not(t)) { comp0=compos0[r1]; if (comp0[1]<=bound/2) { compos1=comp(comp0[1],ncols(PW1)); s1=1; while ((s1<=size(compos1)) and not(t)) { if (comp0[2]<=bound/2) { compos2=comp(comp0[2],ncols(PW2)); s2=1; while ((s2<=size(compos2)) and not(t)) { w1=WW(PW1,compos1[s1]); w2=WW(PW2,compos2[s2]); h=@A*w1*a1[1]-@B*w2*a2[1]; h=reduce(h,PN); if (h==0){cA=1;cB=-1;} else { l=factorize(h,2); h1=1; for(i=1;i<=size(l[1]);i++) { if ((memberpos(@A,variables(l[1][i]))[1]) or (memberpos(@B,variables(l[1][i]))[1])) {h1=h1*l[1][i];} } cA=diff(h1,@B); cB=diff(h1,@A); } if ((cA!=0) and (cB!=0) and (jet(cA,0)==cA) and (jet(cB,0)==cB)) { t=1; alpha=1; while((t) and (alpha<=ncols(a1))) { h=cA*w1*a1[alpha]+cB*w2*a2[alpha]; if (not(reduce(h,PN,1)==0)){t=0;} alpha++; } } else{t=0;} s2++; } } s1++; } } r1++; } g++; } setring(@R); ww1=imap(@PAB,w1); ww2=imap(@PAB,w2); T=imap(@PAB,PT); N=imap(@PAB,PN); cA1=imap(@PAB,cA); cB1=imap(@PAB,cB); if (t) { G=0; for (alpha=1;alpha<=ncols(Tm);alpha++) { H=cA1*ww1*c1[alpha]+cB1*ww2*c2[alpha]; setring(@PAB); PH=imap(@R,H); PN=imap(@R,N); rP=division(PH,PN); setring(@R); r=imap(@PAB,rP); if (r[2][1]!=0){ERROR("the division is not null and it should be");} q=r[1]; qT=transpose(matrix(q)); N10=N12; for (i=size(N1)+1;i<=size(N1)+size(N2);i++){N10[i]=0;} G=G+(cA1*ww1*c1[alpha]-(matrix(N10)*T*qT)[1,1])*Tm[alpha]; } //T_ "genimage has found a more generic basis (method 2)"; //T_ "f1:"; f1; "N1:"; N1; "W1:"; W1; //T_ "f2:"; f2; "N2:"; N2; "W2:"; W2; //T_ "G:"; G; GG=ideal(G); } else{GG=ideal(0);} return(GG); } // purpose: given a polynomial f (in the reduced basis) // the null-conditions ideal N in the segment // end the set of non-null polynomials common to the segment and // a new segment, // to obtain an equivalent polynomial with a leading coefficient // that is non-null in the second segment. // input: // poly f: a polynomials of the reduced basis in the segment (N,W) // ideal N: the null-conditions ideal in the segment // ideal W12: the set of non-null polynomials common to the segment and // a second segment proc extendpoly(poly f, ideal N, ideal W12) { int bound=4; ideal cfs; ideal cfsn; ideal ppfs; poly p=f; poly fn; poly lm; poly lc; int tt=0; int i; while (p!=0) { lm=leadmonom(p); lc=leadcoef(p); cfs[size(cfs)+1]=lc; ppfs[size(ppfs)+1]=lm; p=p-lc*lm; } def lcf=cfs[1]; int r1=0; int s1; def RR=basering; setring @P; list compos1; poly w1; ideal q; def lcfp=imap(RR,lcf); def W=imap(RR,W12); def Np=imap(RR,N); def cfsp=imap(RR,cfs); ideal cfspn; matrix T; ideal H=lcfp,Np; def G=liftstd(H,T); list r; while ((r1<=bound) and not(tt)) { compos1=comp(r1,ncols(W)); s1=1; while ((s1<=size(compos1)) and not(tt)) { w1=WW(W,compos1[s1]); cfspn=ideal(0); cfspn[1]=w1; tt=1; i=2; while ((i<=size(cfsp)) and (tt)) { r=division(w1*cfsp[i],G); if (r[2][1]!=0){tt=0;} else { q=r[1]; cfspn[i]=(T*transpose(matrix(q)))[1,1]; } i++; } s1++; } r1++; } setring RR; if (tt) { cfsn=imap(@P,cfspn); fn=0; for (i=1;i<=size(ppfs);i++) { fn=fn+cfsn[i]*ppfs[i]; } } else{fn=0;} return(fn); } // nonnull // ring @P (or @R) // input: // poly f // ideal N // ideal W // output: // 1 if f is nonnull in the segment (N,W) // 0 if it can be zero proc nonnull(poly f, ideal N, ideal W) { int tt; ideal N0=N; N0[size(N0)+1]=f; poly h=1; int i; for (i=1;i<=size(W);i++){h=h*W[i];} def RR=basering; setring(@P); list Px=ringlist(@P); list v="@C"; Px[2]=Px[2]+v; def npx=size(Px[3][1][2]); Px[3][1][1]="dp"; Px[3][1][2]=1:(npx+size(v)); def @PC=ring(Px); setring(@PC); def N1=imap(RR,N0); def h1=imap(RR,h); ideal G=1-@C*h1; G=G+N1; option(redSB); ideal G1=groebner(G); if (G1[1]==1){tt=1;} else{tt=0;} setring(RR); return(tt); } // decide // input: // given two corresponding polynomials g1 and g2 with the same lpp // g1 belonging to the basis in the segment N1,W1 // g2 belonging to the basis in the segment N2,W2 // output: // an ideal (with a single polynomial of more if a sheaf is needed) // that specializes well on both segments to g1 and g2 respectivelly. // If ideal(0) is output, then no such polynomial nor sheaf exists. proc decide(poly g1, ideal N1, ideal W1, poly g2, ideal N2, ideal W2) { poly S; poly S1; poly S2; S=leadcoef(g2)*g1-leadcoef(g1)*g2; def RR=basering; setring(@RP); def SR=imap(RR,S); def N1R=imap(RR,N1); def N2R=imap(RR,N2); attrib(N1R,"isSB",1); attrib(N2R,"isSB",1); poly S1R=reduce(SR,N1R); poly S2R=reduce(SR,N2R); setring(RR); S1=imap(@RP,S1R); S2=imap(@RP,S2R); if ((S2==0) and (nonnull(leadcoef(g1),N2,W2))){return(ideal(g1));} if ((S1==0) and (nonnull(leadcoef(g2),N1,W1))){return(ideal(g2));} if ((S1==0) and (S2==0)) { //T_ "A sheaf has been found (method 1)"; return(ideal(g1,g2)); } return(ideal(genimage(g1,N1,W1,g2,N2,W2))); } // input: the tree (list) from buildtree output // output: the list of terminal vertices. proc finalcases(list T) "USAGE: finalcases(T); T is the list provided by buildtree RETURN: A list with the CGS determined by buildtree. Each element of the list represents one segment of the buildtree CGS. The list elements have the following structure: [1]: label (an intvec(1,0,..)) that indicates the position in the buildtree but that is irrelevant for the CGS [2]: 1 (integer) it is also irrelevant and indicates that this was a terminal vertex in buildtree. [3]: the reduced basis of the segment. [4], [5], [6]: the red-spec of the null and non-null conditions of the segment. [4] is the null-conditions radical ideal N, [5] is the non-null polynomials set (ideal) W, [6] is the set of prime components (ideals) of N. [7]: is the set of lpp [8]: poly 1 (irrelevant) is the condition to branch (but no more branch is necessary in the discussion, so 1 is the result. NOTE: It can be called having as argument the list output by buildtree KEYWORDS: buildtree, buildtreetoMaple, CGS EXAMPLE: finalcases; shows an example" { int i; list L; for (i=1;i<=size(T);i++) { if (T[i][2]) {L[size(L)+1]=T[i];} } return(L); } example { "EXAMPLE:"; echo = 2; ring R=(0,a1,a2,a3,a4),(x1,x2,x3,x4),dp; ideal F=x4-a4+a2, x1+x2+x3+x4-a1-a3-a4, x1*x3*x4-a1*a3*a4, x1*x3+x1*x4+x2*x3+x3*x4-a1*a4-a1*a3-a3*a4; def T=buildtree(F); finalcases(T); } // input: the list of terminal vertices of buildtree (output of finalcases) // output: the same terminal vertices grouped by lpp proc groupsegments(list T) { int i; list L; list lpp; list lp; list ls; int n=size(T); lpp[1]=T[n][7]; L[1]=list(lpp[1],list(list(T[n][1],T[n][3],T[n][4],T[n][5],T[n][6]))); if (n>1) { for (i=1;i<=size(T)-1;i++) { lp=memberpos(T[n-i][7],lpp); if(lp[1]==1) { ls=L[lp[2]][2]; ls[size(ls)+1]=list(T[n-i][1],T[n-i][3],T[n-i][4],T[n-i][5],T[n-i][6]); L[lp[2]][2]=ls; } else { lpp[size(lpp)+1]=T[n-i][7]; L[size(L)+1]=list(T[n-i][7],list(list(T[n-i][1],T[n-i][3],T[n-i][4],T[n-i][5],T[n-i][6]))); } } } return(L); } // eliminates repeated elements form an ideal proc elimrepeated(ideal F) { int i; int j; ideal FF; FF[1]=F[1]; for (i=2;i<=ncols(F);i++) { if (not(memberpos(F[i],FF)[1])) { FF[size(FF)+1]=F[i]; } } return(FF); } // decide F is the same as decide but allows as first element a sheaf F proc decideF(ideal F,ideal N,ideal W, poly f2, ideal N2, ideal W2) { int i; ideal G=F; ideal g; if (ncols(F)==1) {return(decide(F[1],N,W,f2,N2,W2));} for (i=1;i<=ncols(F);i++) { G=G+decide(F[i],N,W,f2,N2,W2); } return(elimrepeated(G)); } // newredspec // input: two redspec in the form of N,W and Nj,Wj // output: a redspec representing the minimal redspec segment that contains // both input segments. proc newredspec(ideal N,ideal W, ideal Nj, ideal Wj) { ideal nN; ideal nW; int u; def RR=basering; setring(@P); list r; def Np=imap(RR,N); def Wp=imap(RR,W); def Njp=imap(RR,Nj); def Wjp=imap(RR,Wj); Np=intersect(Np,Njp); ideal WR; for(u=1;u<=size(Wjp);u++) { if(nonnull(Wjp[u],Np,Wp)){WR[size(WR)+1]=Wjp[u];} } for(u=1;u<=size(Wp);u++) { if((not(memberpos(Wp[u],WR)[1])) and (nonnull(Wp[u],Njp,Wjp))) { WR[size(WR)+1]=Wp[u]; } } r=redspec(Np,WR); option(redSB); Np=groebner(r[1]); Wp=r[2]; setring(RR); nN=imap(@P,Np); nW=imap(@P,Wp); return(list(nN,nW)); } // selectcases // input: // list bT: the list output by buildtree. // output: // list L it contins the list of segments allowing a common // reduced basis. The elements of L are of the form // list (lpp,B,list(list(N,W,L),..list(N,W,L)) ) proc selectcases(list bT) { list T=groupsegments(finalcases(bT)); list T0=bT[1]; // first element of the list of buildtree list TT0; TT0[1]=list(T0[7],T0[3],list(list(T0[4],T0[5],T0[6]))); // first element of the output of selectcases list T1=T; // the initial list; it is only actualized (split) // when a segment is completly revised (all split are // already be considered); // ( (lpp, ((lab,B,N,W,L),.. ()) ), .. (..) ) list TT; // the output list ( (lpp,B,((N,W,L),..()) ),.. (..) ) // case i list S1; // the segments in case i T1[i][2]; ( (lab,B,N,W,L),..() ) list S2; // the segments in case i that are being summarized in // actual segment ( (N,W,L),..() ) list S3; // the segments in case i that cannot be summarized in // the actual case. When the case is finished a new case // is created with them ( (lab,B,N,W,L),..() ) list s3; // list of integers s whose segment cannot be summarized // in the actual case ideal lpp; // the summarized lpp (can contain repetitions) ideal lppi;// in proecess of sumarizing lpp (can contain repetitions) ideal B; // the summarized B (can contain polynomials with // the same lpp (sheaves)) ideal Bi; // in process of summarizing B (can contain polynomials with // the same lpp (sheaves)) ideal N; // the summarized N ideal W; // the summarized W ideal F; // the summarized polynomial j (can contain a sheaf instead of // a single poly) ideal FF; // the same as F but it can be ideal(0) poly lpj; poly fj; ideal Nj; ideal Wj; ideal G; int i; // the index of the case i in T1; int j; // the index of the polynomial j of the basis int s; // the index of the segment s in S1; int u; int tests; // true if al the polynomial in segment s have been generalized; list r; // initializing the new list i=1; while(i<=size(T1)) { S1=T1[i][2]; // ((lab,B,N,W,L)..) of the segments in case i if (size(S1)==1) { TT[i]=list(T1[i][1],S1[1][2],list(list(S1[1][3],S1[1][4],S1[1][5]))); } else { S2=list(); S3=list(); // ((lab,B,N,W,L)..) of the segments in case i to // create another segment i+1 s3=list(); B=S1[1][2]; Bi=ideal(0); lpp=T1[i][1]; j=1; tests=1; while (j<=size(S1[1][2])) { // j desings the new j-th polynomial N=S1[1][3]; W=S1[1][4]; F=ideal(S1[1][2][j]); s=2; while (s<=size(S1) and not(memberpos(s,s3)[1])) { // s desings the new segment s fj=S1[s][2][j]; Nj=S1[s][3]; Wj=S1[s][4]; FF=decideF(F,N,W,fj,Nj,Wj); if (FF[1]==0) { if (@ish) { "Warning: Dealing with an homogeneous ideal"; "mrcgs was not able to summarize all lpp cases into a single segment"; "Please send a mail with your Problem to antonio.montes@upc.edu"; "You found a counterexample of the complete success of the actual mrcgs algorithm"; //"T_"; "f1:"; F; "N1:"; N; "W1:"; W; "f2:"; fj; "N2:"; Nj; "W2:"; Wj; } S3[size(S3)+1]=S1[s]; s3[size(s3)+1]=s; tests=0; } else { F=FF; lpj=leadmonom(fj); r=newredspec(N,W,Nj,Wj); N=r[1]; W=r[2]; } s++; } if (Bi[1]==0){Bi=FF;} else { Bi=Bi+FF; } j++; } if (tests) { B=Bi; lpp=ideal(0); for (u=1;u<=size(B);u++){lpp[u]=leadmonom(B[u]);} } for (s=1;s<=size(T1[i][2]);s++) { if (not(memberpos(s,s3)[1])) { S2[size(S2)+1]=list(S1[s][3],S1[s][4],S1[s][5]); } } TT[i]=list(lpp,B,S2); // for (s=1;s<=size(s3);s++){S1=delete(S1,s);} T1[i][2]=S2; if (size(S3)>0){T1=insert(T1,list(T1[i][1],S3),i);} } i++; } for (i=1;i<=size(TT);i++){TT0[i+1]=TT[i];} return(TT0); } //*****************End of Selectcases************************** //*****************Begin of CanTree**************************** // equalideals // input: 2 ideals F and G; // output: 1 if they are identical (the same polynomials in the same order) // 0 else proc equalideals(ideal F, ideal G) { int i=1; int t=1; if (size(F)!=size(G)){return(0);} while ((i<=size(F)) and (t)) { if (F[i]!=G[i]){t=0;} i++; } return(t); } // delintvec // input: intvec V // int i // output: // intvec W (equal to V but the coordinate i is deleted proc delintvec(intvec V, int i) { int j; intvec W; for (j=1;j0) { LL[1]=list(lab,k); setring(RR); return(imap(@P,LL)); } else {setring(RR); return(LLL);} } // tree // purpose: given a label and the list L of vertices of the tree, // whose content // are of the form list(intvec lab, int children, ideal P) // to obtain the vertex and its position // input: // intvec lab: label of the vertex // list: L the list containing the vertices // output: // list V the vertex list(lab, children, P) proc tree(intvec lab,list L) { int i=0; int tt=1; list V; intvec labi; while ((in1)){tt=1;} return(tt); } // cantree // input: the list provided by selectcases // output: the list providing the canonicaltree proc cantree(list S) { string method=" "; list T0=S[1]; // first element of the list of selectcases int i; int j; list L; list T; L[1]=list(intvec(0),size(S)-1,T0[1],T0[2],T0[3][1],method); for (i=2;i<=size(S);i++) { T=GCS(intvec(i-1),S[i]); T=sortbylab(T); for (j=1;j<=size(T);j++) {L[size(L)+1]=T[j];} } return(L); } // addcase // recursive routine that adds to the list @L, (an alredy GCS) // a new redspec rs=(N,W,L); // and returns the test t whose value is // 0 if the new canspec is not to be hung to the fathers vertex, // 1 if yes. proc addcase(intvec labu, list rs) { int i; int j; int childu; ideal Pu; list T; int nchildu; def N=rs[1]; def W=rs[2]; def PN=rs[3]; ideal NN; ideal MM; int tt=1; poly h=1; for (i=1;i<=size(W);i++){h=h*W[i];} list u=tree(labu,@L); childu=u[1][2]; list v; intvec labv; int childv; list w; intvec labw; if (childu>0) { v=firstchild(u[1][1]); while(v[2][1]!=0) { labv=v[1][1]; w=firstchild(labv); while(w[2][1]!=0) { labw=w[1][1]; if(addcase(labw,rs)==0) {tt=0;} w=nextbrother(labw); } u=tree(labu,@L); childu=u[1][2]; v=nextbrother(v[1][1]); } deletebrotherscontaining(labu); relabelingindices(labu,labu); } if (tt==1) { u=tree(labu,@L); nchildu=lastchildrenindex(labu); if (size(labu)==1) { T=redtocanspec(labu,nchildu,rs); tt=0; } else { NN=N; if (containedP(u[1][3],N)){tt=0;} for (i=1;i<=size(u[1][3]);i++) { NN[size(NN)+1]=u[1][3][i]; } MM=NN; MM[size(MM)+1]=h; T=difftocanspec(labu,nchildu,NN,MM); } if (size(T)>0) { @L[u[2]][2]=@L[u[2]][2]+T[1][2]; for (i=2;i<=size(T);i++){@L[size(@L)+1]=T[i];} if (size(labu)>1) { simplifynewadded(labu); } } else{tt=1;} } return(tt); } // reduceR // reduces the polynomial f w.r.t. N, in the ring @P proc reduceR(poly f, ideal N) { def RR=basering; setring(@P); def fP=imap(RR,f); def NP=imap(RR,N); attrib(NP,"isSB",1); def rp=reduce(fP,NP); setring(RR); return(imap(@P,rp)); } // containedP // returns 1 if ideal Pu is contained in ideal Pv // returns 0 if not // in ring @P proc containedP(ideal Pu,ideal Pv) { int t=1; int n=size(Pu); int i=0; poly r=0; while ((t) and (i0) { v=firstchild(u[1][1]); labv=v[1][1]; childv=v[1][2]; Pv=v[1][3]; ii=0; t=0; while ((not(t)) and (ii1) { labfi=delintvec(labi,size(labi)); if (labfu==labfi) { lastlabi=labi[size(labi)]; if (lastlab1) { labfi=delintvec(labi,size(labi)); if (labfu==labfi) { lastlabi=labi[size(labi)]; if (lastlabu0) { v=firstchild(labu); labv=v[1][1]; for (ii=1;ii<=childu;ii++) { deleteverts(labv); if (ii0) { ideal N=#[1]; ideal W=#[2]; T=reduceconds(T,N,W); } kill @ish; return(T); } example { "EXAMPLE:"; echo = 2; ring R=(0,b,c,d,e,f),(x,y),dp; ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e; def T=mrcgs(F); T; cantreetoMaple(T,"Tm","Tm.txt"); //cantodiffcgs(T); // has non locally closed segments ring R=(0,a1,a2,a3,a4),(x1,x2,x3,x4),dp; ideal F2=x4-a4+a2, x1+x2+x3+x4-a1-a3-a4, x1*x3*x4-a1*a3*a4, x1*x3+x1*x4+x2*x3+x3*x4-a1*a4-a1*a3-a3*a4; def T2=mrcgs(F2); T2; cantreetoMaple(T2,"T2m","T2m.txt"); cantodiffcgs(T2); } // reduceconds: when null and nonnull conditions are specified it // takes the output of cantree and reduces the tree // assuming the null and nonnull conditions // input: list T (the output of cantree computed with null and nonull conditions // ideal N: null conditions // ideal W: non-null conditions // output: the list T assuming the null and non-null conditions proc reduceconds(list T,ideal N,ideal W) { int i; intvec lab; intvec labfu; list fu; int j; int t; list @L=T; exportto(Top,@L); int n=size(W); for (i=2;i<=size(@L);i++) { t=0; j=0; while ((not(t)) and (j1) { if (memberpos(W[j],@L[i][3])[1]) { t=1; @L[i][3]=ideal(1); } } } } for (i=2;i<=size(@L);i++) { if (size(@L[i][1])>1) { @L[i][3]=delidfromid(N,@L[i][3]); } } for (i=2;i<=size(@L);i++) { if ((size(@L[i][1])>1) and (size(@L[i][1]) mod 2==1) and (equalideals(@L[i][3],ideal(0)))) { lab=@L[i][1]; labfu=delintvec(lab,size(lab)); fu=tree(labfu,@L); @L[fu[2]][2]=@L[fu[2]][2]-1; deleteverts(lab); } } for (j=2; j<=size(@L); j++) { if (@L[j][2]>0) { deletebrotherscontaining(@L[j][1]); } } for (i=1;i<=@L[1][2];i++) { relabelingindices(intvec(i),intvec(i)); } list TT=@L; kill @L; return(TT); } //**************End of cantree****************************** //**************Begin of CanTreeTo Maple******************** // cantreetoMaple // input: list L: the output of cantree // string T: the name of the table of Maple that represents L // in Maple // string writefile: the name of the file where the table T // is written proc cantreetoMaple(list L, string T, string writefile) "USAGE: cantreetoMaple(T, TM, writefile); T: is the list provided by mrcgs or crcgs or crcgs, TM: is the name (string) of the table variable in Maple that will represent the output of the fundamental routines, writefile: is the name (string) of the file where to write the content. RETURN: writes the list provided by mrcgs or crcgs or crcgs to a file containing the table representing it in Maple. NOTE: It can be called from the output of mrcgs or rcgs of crcgs KEYWORDS: mrcgs, rcgs, crcgs, Maple EXAMPLE: cantreetoMaple; shows an example" { short=0; int i; list L0=L[1]; int numcases=L0[2]; link LLw=":w "+writefile; string La=string("table(",T,");"); write(LLw, La); close(LLw); link LLa=":a "+writefile; def RL=ringlist(@R); list p=RL[1][2]; string param=string(p[1]); if (size(p)>1) { for(i=2;i<=size(p);i++){param=string(param,",",p[i]);} } list v=RL[2]; string vars=string(v[1]); if (size(v)>1) { for(i=2;i<=size(v);i++){vars=string(vars,",",v[i]);} } list xord; list pord; if (RL[1][3][1][1]=="dp"){pord=string("tdeg(",param);} else { if (RL[1][3][1][1]=="lp"){pord=string("plex(",param);} } if (RL[3][1][1]=="dp"){xord=string("tdeg(",vars);} else { if (RL[3][1][1]=="lp"){xord=string("plex(",vars);} } write(LLa,string(T,"[[___xord]]:=",xord,");")); write(LLa,string(T,"[[___pord]]:=",pord,");")); //write(LLa,string(T,"[[11]]:=true; ")); list S; S=string(T,"[[0]]:=",numcases,";"); write(LLa,S); S=string(T,"[[___method]]:=",L[1][6],";"); // Method L[1][6]; write(LLa,S); S=string(T,"[[___basis]]:=[",L0[4],"];"); write(LLa,S); S=string(T,"[[___nullcond]]:=[",L0[5][1],"];"); write(LLa,S); S=string(T,"[[___notnullcond]]:={",L0[5][2],"};"); write(LLa,S); for (i=1;i<=numcases;i++) { S=ctlppbasis(T,L,intvec(i)); write(LLa,S[1]); write(LLa,S[2]); write(LLa,S[3]); //write(LLa,S[4]); ctrecwrite(LLa, L, T, intvec(i),S[4]); } close(LLa); } example { "EXAMPLE:"; echo = 2; ring R=(0,b,c,d,e,f),(x,y),dp; ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e; def T=mrcgs(F); T; cantreetoMaple(T,"Tm","Tm.txt"); } // ctlppbasis: auxiliary cantreetoMaple routine // input: // string T: the name of the table in Maple // intvec lab: the label of the case // ideal B: the basis of the case // output: // the string of T[[lab]] (basis); in Maple proc ctlppbasis(string T, list L, intvec lab) { list u; intvec lab0=lab,0; u=tree(lab,L); list Li; Li[1]=string(T,"[[",lab,",___lpp]]:=[",u[1][3],"]; "); Li[2]=string(T,"[[",lab,"]]:=[",u[1][4],"]; "); Li[3]=string(T,"[[",lab0,"]]:=",u[1][2],"; "); Li[4]=u[1][2]; return(Li); } // ctlppbasis: auxiliary cantreetoMaple routine // recursive routine to write all elements proc ctrecwrite(LLa, list L, string T, intvec lab, int n) { int i; intvec labi; intvec labi0; string S; list u; for (i=1;i<=n;i++) { labi=lab,i; u=tree(labi,L); S=string(T,"[[",labi,"]]:=[",u[1][3],"];"); write(LLa,S); labi0=labi,0; S=string(T,"[[",labi0,"]]:=",u[1][2],";"); write(LLa,S); ctrecwrite(LLa, L, T, labi, u[1][2]); } } //**************End of CanTreeTo Maple******************** //**************Begin homogenizing************************ // ishomog: // Purpose: test if a polynomial is homogeneous in the variables or not // input: poly f // output 1 if f is homogeneous, 0 if not proc ishomog(def f) { int i; poly r; int d; int dr; if (f==0){return(1);} d=deg(f); dr=d; r=f; while ((d==dr) and (r!=0)) { r=r-lead(r); dr=deg(r); } if (r==0){return(1);} else{return(0);} } proc rcgs(ideal F, list #) "USAGE: rcgs(F); F is the ideal from which to obtain the Reduced CGS. rcgs(F,L); where L is a list of the null conditions ideal N, and W the set of non-null polynomials (ideal). If this option is set, the ideals N and W must depend only on the parameters and the parameter space is reduced to V(N) \ V(h), where h=prod(w), for w in W. A reduced specification of (N,W) will be computed and used to restrict the parameter-space. The output will omit the known restrictions given as option. RETURN: The list representing the Reduced CGS. The description given here is analogous as for mrcgs and crcgs. The elements of the list T computed by rcgs are lists representing a rooted tree. Each element has as the two first entries with the following content:@* [1]: The label (intvec) representing the position in the rooted tree: 0 for the root (and this is a special element) i for the root of the segment i (i,...) for the children of the segment i [2]: the number of children (int) of the vertex. There thus three kind of vertices: 1) the root (first element labelled 0), 2) the vertices labelled with a single integer i, 3) the rest of vertices labelled with more indices. Description of the root. Vertex type 1) There is a special vertex (the first one) whose content is the following: [3] lpp of the given ideal [4] the given ideal [5] the red-spec of the (optional) given null and non-null conditions (see redspec for the description) [6] RCGS (to remember which algorithm has been used). If the algorithm used is mrcgs or crcgs then this will be stated at this vertex (mrcgs or CRCGS). Description of vertices type 2). These are the vertices that initiate a segment, and are labelled with a single integer. [3] lpp (ideal) of the reduced basis. If they are repeated lpp's this will correspond to a sheaf. [4] the reduced basis (ideal) of the segment. Description of vertices type 3). These vertices have as first label i and descend form vertex i in the position of the label (i,...). They contain moreover a unique prime ideal in the parameters and form ascending chains of ideals. How is to be read the rcgs tree? The vertices with an even number of integers in the label are to be considered as additive and those with an odd number of integers in the label are to be considered as substraction. As an example consider the following vertices: v1=((i),2,lpp,B), v2=((i,1),2,P_{(i,1)}), v3=((i,1,1),0,P_{(i,1,1)}, v4=((i,1,2),0,P_{(i,1,1)}), v5=((i,2),2,P_{(i,2)}, v6=((i,2,1),0,P_{(i,2,1)}, v7=((i,2,2),0,P_{(i,2,2)} They represent the segment: (V(i,1)\(V(i,1,1) u V(i,1,2))) u (V(i,2)\(V(i,2,1) u V(i,2,2))) where V(i,j,..) = V(P_{(i,j,..)} NOTE: There are three fundamental routines in the library: mrcgs, rcgs and crcgs. rcgs (Reduced CGS) is an algorithm that first homogenizes the basis of the given ideal then applies mrcgs and finally de-homogenizes and reduces the resulting bases. (See the note of mrcgs). As a result of Wibmer's Theorem, the resulting segments are locally closed (i.e. difference of varieties). Nevertheless, the output is not completely canonical as the homogeneous ideal considered is not the homogenized ideal of the given ideal but only the ideal obtained by homogenizing the given basis. The output can be visualized using cantreetoMaple, that will write a file with the content of mrcgs that can be read in Maple and plotted using the Maple plotcantree routine of the Monte's dpgb library You can also use the routine cantodiffcgs as the segments are all difference of two varieties to have a simpler view of the output. KEYWORDS: rcgs, crcgs, buildtree, cantreetoMaple, cantodiffcgs EXAMPLE: rcgs; shows an example" { ideal N; ideal W; int j; int i; poly f; if (size(#)==2) { N=#[1]; W=#[2]; } i=1; int postred=0; int ish=1; while ((ish) and (i<=size(F))) { ish=ishomog(F[i]); i++; } if (ish){return(mrcgs(F, #));} def RR=basering; list RRL=ringlist(RR); if (RRL[3][1][1]!="dp"){ERROR("the order must be dp");} poly @t; ring H=0,@t,dp; def RH=RR+H; setring(RH); setglobalrings(); def FH=imap(RR,F); list u; ideal B; ideal lpp; intvec lab; FH=homog(FH,@t); def Nh=imap(RR,N); def Wh=imap(RR,W); list L; if ((size(Nh)>0) or (size(Wh)>0)) { L=mrcgs(FH,list(Nh,Wh)); } else { L=mrcgs(FH); } L[1][3]=subst(L[1][3],@t,1); L[1][4]=subst(L[1][4],@t,1); for (i=1; i<=L[1][2]; i++) { lab=intvec(i); u=tree(lab,L); postred=difflpp(u[1][3]); B=sortideal(subst(L[u[2]][4],@t,1)); lpp=sortideal(subst(L[u[2]][3],@t,1)); if (memberpos(1,B)[1]){B=ideal(1); lpp=ideal(1);} if (postred) { lpp=ideal(0); B=postredgb(mingb(B)); for (j=1;j<=size(B);j++){lpp[j]=leadmonom(B[j]);} } else{"Sheaves present, not reduced bases in the case with:";lpp;} L[u[2]][4]=B; L[u[2]][3]=lpp; } setring(RR); setglobalrings(); list LL=imap(RH,L); LL[1][6]="RCGS"; return(LL); } example { "EXAMPLE:"; echo = 2; ring R=(0,b,c,d,e,f),(x,y),dp; ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e; def T=rcgs(F); T; cantreetoMaple(T,"Tr","Tr.txt"); cantodiffcgs(T); } proc difflpp(ideal lpp) { int t=1; int i; poly lp1=lpp[1]; poly lp; i=2; while ((i<=size(lpp)) and (t)) { lp=lpp[i]; if (lp==lp1){t=0;} lp1=lp; i++; } return(t); } // redgb: given a minimal bases (gb reducing) it // reduces each polynomial w.r.t. to the others proc postredgb(ideal F) { ideal G; ideal H; int i; if (size(F)==0){return(ideal(0));} for (i=1;i<=size(F);i++) { H=delfromideal(F,i); G[i]=pdivi(F[i],H)[1]; } return(G); } proc crcgs(ideal F, list #) "USAGE: crcgs(F); F is the ideal from which to obtain the Canonical Reduced CGS. crcgs(F,L); where L is a list of the null conditions ideal N, and W the set of non-null polynomials (ideal). If this option is set, the ideals N and W must depend only on the parameters and the parameter space is reduced to V(N) \ V(h), where h=prod(w), for w in W. A reduced specification of (N,W) will be computed and used to restrict the parameter-space. The output will omit the known restrictions given as option. RETURN: The list representing the Canonical Reduced CGS. The description given here is identical for mrcgs and rcgs. The elements of the list T computed by crcgs are lists representing a rooted tree. Each element has as the two first entries with the following content:@* [1]: The label (intvec) representing the position in the rooted tree: 0 for the root (and this is a special element) i for the root of the segment i (i,...) for the children of the segment i [2]: the number of children (int) of the vertex. There thus three kind of vertices: 1) the root (first element labelled 0), 2) the vertices labelled with a single integer i, 3) the rest of vertices labelled with more indices. Description of the root. Vertex type 1) There is a special vertex (the first one) whose content is the following: [3] lpp of the given ideal [4] the given ideal [5] the red-spec of the (optional) given null and non-null conditions (see redspec for the description) [6] mrcgs (to remember which algorithm has been used). If the algorithm used is rcgs of crcgs then this will be stated at this vertex (RCGS or CRCGS). Description of vertices type 2). These are the vertices that initiate a segment, and are labelled with a single integer. [3] lpp (ideal) of the reduced basis. If they are repeated lpp's this will correspond to a sheaf. [4] the reduced basis (ideal) of the segment. Description of vertices type 3). These vertices have as first label i and descend form vertex i in the position of the label (i,...). They contain moreover a unique prime ideal in the parameters and form ascending chains of ideals. How is to be read the mrcgs tree? The vertices with an even number of integers in the label are to be considered as additive and those with an odd number of integers in the label are to be considered as substraction. As an example consider the following vertices: v1=((i),2,lpp,B), v2=((i,1),2,P_{(i,1)}), v3=((i,1,1),0,P_{(i,1,1)}, v4=((i,1,2),0,P_{(i,1,1)}), v5=((i,2),2,P_{(i,2)}, v6=((i,2,1),0,P_{(i,2,1)}, v7=((i,2,2),0,P_{(i,2,2)} They represent the segment: (V(i,1)\(V(i,1,1) u V(i,1,2))) u (V(i,2)\(V(i,2,1) u V(i,2,2))) where V(i,j,..) = V(P_{(i,j,..)} NOTE: There are three fundamental routines in the library: mrcgs, rcgs and crcgs. crcgs (Canonical Reduced CGS) is an algorithm that first homogenizes the the given ideal then applies mrcgs and finally de-homogenizes and reduces the resulting bases. (See the note of mrcgs). As a result of Wibmer's Theorem, the resulting segments are locally closed (i.e. difference of varieties) and the partition is canonical as the homogenized ideal is uniquely associated to the given ideal not depending of the given basis. Nevertheless the computations to do are usually more time consuming and so it is preferable to compute first the rcgs and only if it success you can try crcgs. The output can be visualized using cantreetoMaple, that will write a file with the content of crcgs that can be read in Maple and plotted using the Maple plotcantree routine of the Monte's dpgb library You can also use the routine cantodiffcgs as the segments are all difference of two varieties to have a simpler view of the output. KEYWORDS: mrcgs, rcgs, buildtree, cantreetoMaple, cantodiffcgs EXAMPLE: mrcgs; shows an example" { int ish=1; int i=1; while ((ish) and (i<=size(F))) { ish=ishomog(F[i]); i++; } if (ish){return(mrcgs(F, #));} list L; def RR=basering; setglobalrings(); setring(@RP); ideal FP=imap(RR,F); option(redSB); def G=groebner(FP); setring(RR); def GR=imap(@RP,G); kill @RP; kill @P; L=rcgs(GR, #); L[1][6]="CRCGS"; return(L); } example { "EXAMPLE:"; echo = 2; ring R=(0,b,c,d,e,f),(x,y),dp; ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e; def T=crcgs(F); T; cantreetoMaple(T,"Tc","Tc.txt"); cantodiffcgs(T); } //purpose ideal intersection called in @R and computed in @P proc idintR(ideal N, ideal M) { def RR=basering; setring(@P); def Np=imap(RR,N); def Mp=imap(RR,M); def Jp=idint(Np,Mp); setring(RR); return(imap(@P,Jp)); } //purpose reduced groebner basis called in @R and computed in @P proc gbR(ideal N) { def RR=basering; setring(@P); def Np=imap(RR,N); option(redSB); Np=groebner(Np); setring(RR); return(imap(@P,Np)); } // purpose: given the output of a locally closed CGS (i.e. from rcgs or crcgs) // it returns the segments as difference of varieties. proc cantodiffcgs(list L) "USAGE: canttodiffcgs(T); T: is the list provided by mrcgs or crcgs or crcgs, RETURN: The list transforming the content of these routines to a simpler output where each segment corresponds to a single element of the list that is described as difference of two varieties. The first element of the list is identical to the first element of the list provided by the corresponding cgs algorithm, and contains general information on the call (see mrcgs). The remaining elements are lists of 4 elements, representing segments. These elements are [1]: the lpp of the segment [2]: the basis of the segment [3]; the ideal of the first variety (radical) [4]; the ideal of the second variety (radical) The segment is V([3]) \ V([4]). NOTE: It can be called from the output of mrcgs or rcgs of crcgs KEYWORDS: mrcgs, rcgs, crcgs, Maple EXAMPLE: cantodiffcgs; shows an example" { int i; int j; int k; int depth; list LL; list u; list v; list w; ideal N; ideal Nn; ideal M; ideal Mn; ideal N0; ideal W0; LL[1]=L[1]; N0=L[1][5][1]; W0=L[1][5][2]; def RR=basering; setring(@P); def N0P=imap(RR,N0); def W0P=imap(RR,N0); ideal NP; ideal MP; setring(RR); for (i=2;i<=size(L);i++) { depth=size(L[i][1]); if (depth>3){ERROR("the given CGS has non locally closed segments");} } for (i=1;i<=L[1][2];i++) { N=ideal(1); M=ideal(1); u=tree(intvec(i),L); for (j=1;j<=u[1][2];j++) { v=tree(intvec(i,j),L); Nn=v[1][3]; N=idintR(N,Nn); for (k=1;k<=v[1][2];k++) { w=tree(intvec(i,j,k),L); Mn=w[1][3]; M=idintR(M,Mn); } } setring(@P); def NP=imap(RR,N); def MP=imap(RR,M); MP=MP+N0P; for (j=1;j<=size(W0P);j++){MP=MP+ideal(W0P[j]);} NP=NP+N0P; NP=gbR(NP); MP=gbR(MP); setring(RR); N=imap(@P,NP); M=imap(@P,MP); LL[i+1]=list(u[1][3],u[1][4],N,M); } return(LL); } example { "EXAMPLE:"; echo = 2; ring R=(0,b,c,d,e,f),(x,y),dp; ideal F=x^2+b*y^2+2*c*x*y+2*d*x+2*e*y+f, 2*x+2*c*y+2*d, 2*b*y+2*c*x+2*e; def T=crcgs(F); T; cantreetoMaple(T,"Tc","Tc.txt"); cantodiffcgs(T); } //**************End homogenizing************************ singular-4.0.3+ds/Singular/LIB/reesclos.lib000066400000000000000000000311151266270727000204570ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version reesclos.lib 4.0.0.0 Jun_2013 "; // $Id: 53ae3f0d9c887447ca52755d6ebd614cced1b9bb $ category="Commutative Algebra"; info=" LIBRARY: reesclos.lib PROCEDURES TO COMPUTE THE INT. CLOSURE OF AN IDEAL AUTHOR: Tobias Hirsch, email: hirsch@math.tu-cottbus.de Janko Boehm, email: boehm@mathematik.uni-kl.de Magdaleen Marais, email: magdaleen@aims.ac.za OVERVIEW: A library to compute the integral closure of an ideal I in a polynomial ring R=k[x(1),...,x(n)] using the Rees Algebra R[It] of I. It computes the integral closure of R[It], which is a graded subalgebra of R[t]. The degree-k-component is the integral closure of the k-th power of I. In contrast to the previous version, the library uses 'normal.lib' to compute the integral closure of R[It]. This improves the performance considerably. PROCEDURES: ReesAlgebra(I); computes the Rees Algebra of an ideal I normalI(I[,p[,r]]); computes the integral closure of an ideal I using R[It] "; LIB "locnormal.lib"; // for HomJJ LIB "standard.lib"; // for groebner /////////////////////////////////////////////////////////////////////////////// proc ReesAlgebra (ideal I) "USAGE: ReesAlgebra (I); I = ideal RETURN: The Rees algebra R[It] as an affine ring, where I is an ideal in R. The procedure returns a list containing two rings: [1]: a ring, say RR; in the ring an ideal ker such that R[It]=RR/ker [2]: a ring, say Kxt; the basering with additional variable t containing an ideal mapI that defines the map RR-->Kxt EXAMPLE: example ReesAlgebra; shows an example " { // remember the data of the basering def oldring = basering; string oldchar = charstr(basering); string oldvar = varstr(basering); string oldord = ordstr(basering); int n = ncols(I); ideal m = maxideal(1); // Create a new ring with variables for each generator of I execute ("ring Rees = "+oldchar+",("+oldvar+",U(1.."+string(n)+")),dp"); // Kxt is the old ring with additional variable t // Here I -> t*I, so the generators of I generate the subalgebra R[It] in Kxt execute ("ring Kxt = "+oldchar+",("+oldvar+",t),dp"); ideal I = fetch(oldring,I); ideal m = fetch(oldring,m); int k; for (k=1;k<=n;k++) { I[k]=t*I[k]; } // Now we map from Rees to Kxt, identity on the original variables, and // U(k) -> I[k] ideal mapI = m,I; map phi = Rees,mapI; ideal zero = 0; export (mapI); // Now the Rees-Algebra is Rees/ker(phi) setring Rees; ideal ker = preimage(Kxt,phi,zero); export (ker); list result = Rees,Kxt; return(result); } example { "EXAMPLE:"; echo=2; ring R = 0,(x,y),dp; ideal I = x2,xy4,y5; list L = ReesAlgebra(I); def Rees = L[1]; // defines the ring Rees, containing the ideal ker setring Rees; // passes to the ring Rees Rees; ker; // R[It] is isomorphic to Rees/ker } //////////////////////////////////////////////////////////////////////////// static proc ClosureRees (list L, int useLocNormal) "USAGE: ClosureRees (L,useLocNormal); L a list, useLocNormal an integer ASSUME: L is a list containing - a ring L[1], inside L[1] an ideal ker such that L[1]/ker is isomorphic to the Rees Algebra R[It] of an ideal I in k[x] - a ring L[2]=k[x,t], inside L[1] an ideal mapI defining the map L[1] --> L[2] with image R[It] RETURN: quotients of elements of k[x,t] representing generators of the integral closure of R[It]. The result of ClosureRees is a list images, the first size(images)-1 entries are the numerators of the generators, the last one is the universal denominator " { int dblvl=printlevel-voice+2; // toggles how much data is printed // during the procedure def Kxt = basering; def R(1) = L[1]; setring R(1); // declaration of variables used later ideal ker(1)=ker; // in STEP 2 if (useLocNormal==1) { list preimages1 = locNormal(ker); ideal preimagesI=preimages1[1]; list preimagesL = list(preimagesI[2..size(preimagesI)])+list(preimagesI[1]); ideal preimages = ideal(preimagesL[1..size(preimagesL)]); } else { list nor = normal(ker); ideal preimages=nor[2][1]; } setring Kxt; map psi=R(1),mapI; // from ReesAlgebra: the map Rees->Kxt ideal images=psi(preimages); ideal psii = images[size(images)]*ideal(psi); list imagesl = images[1..size(images)]; list psil =psii[1..size(psii)]; imagesl=psil+imagesl; return(imagesl); } //////////////////////////////////////////////////////////////////////////// static proc ClosurePower(list images, list #) "USAGE: ClosurePower (L [,#]); L a list, # an optional list containing an integer ASSUME: - L is a list containing generators of the closure of R[It] in k[x,t] (the first size(L)-1 elements are the numerators, the last one is the denominator) - if # is given: #[1] is an integer, compute generators for the closure of I, I^2, ..., I^#[1] RETURN: the integral closure of I, ... I^#[1]. If # is not given, compute the closure of all powers up to the maximum degree in t occurring in the closure of R[It] (so this is the last power whose closure is not just the sum/product of the smaller powers). The returned result is a list of elements of k[x,t] containing generators of the closure of the desired powers of I. " { int dblvl=printlevel-voice+2; // toggles how much data is printed // during the procedure int j,k,d,computepow; // some counters int pow=0; int length = size(images)-1; // the number of generators poly image; poly @denominator = images[length+1]; // the universal denominator if (size(#)>0) { pow=#[1]; } computepow=pow; if (dblvl>0) { ""; "// The generators of the closure of R[It]:"; } intmat m[nvars(basering)-1][1]; // an intvec used for jet and maxdeg1 intvec tw=m,1; // such that t has weight 1 and all // other variables have weight 0 // Construct the generators of the closure of R[It] as elements of k[x,t] // If # is not given, determine the highest degree pow in t that occurs. for (j=1;j<=length;j++) { images[j] = (images[j]/@denominator); // construct the fraction image = images[j]; if (dblvl>0) { "generator",j,":",image; } if (computepow==0) // #[1] not given or ==0 => compute pow { if (maxdeg1(image,tw)>pow) // from poly.lib { pow=maxdeg1(image,tw); } } } if (dblvl>0) { ""; if (computepow==0) { "// Compute the closure up to the given powers of I"; } else { "// Compute the closure up to the maximal power of t that occured:",pow; } } // Construct a list consisting of #[1] resp. pow times the zero ideal ideal CurrentPower=0; list result; for (k=1;k<=pow;k++) { result=insert(result,CurrentPower); } // For each generator and each k, add its degree-k-coefficient to the # // closure of I^k for (j=1;j<=length;j++) { for (k=1;k<=pow;k++) { image=images[j]-jet(images[j],k-1,tw); if (image<>0) { image=subst(image/t^k,t,0); if (image<>0) { result[k]=result[k]+image; } } } } if (dblvl>0) { ""; "// The 'pure' parts of degrees 1..pow:"; result; ""; } // finally, add the suitable products of generators in lower degrees for (k=2;k<=pow;k++) { for (j=1;j<=(k div 2);j++) { result[k]=result[k]+result[j]*result[k-j]; } } return(result); } //////////////////////////////////////////////////////////////////////////// proc normalI(ideal I, list #) "USAGE: normalI (I [,p [,r [,l]]]); I an ideal, p, r, and l optional integers RETURN: the integral closure of I, ..., I^p, where I is an ideal in the polynomial ring R=k[x(1),...x(n)]. If p is not given, or p==0, compute the closure of all powers up to the maximum degree in t occurring in the closure of R[It] (so this is the last power whose closure is not just the sum/product of the smaller). If r is given and r==1, normalI starts with a check whether I is already a radical ideal. If l==1 then locNormal instead of normal is used to compute normalization. The result is a list containing the closure of the desired powers of I as ideals of the basering. DISPLAY: The procedure displays more comments for higher printlevel. EXAMPLE: example normalI; shows an example " { int dblvl=printlevel-voice+2; // toggles how much data is printed // during the procedure def BAS=basering; // remember the basering // two simple cases: principal ideals and radical ideals are always // integrally closed if (size(I)<=1) // includes the case I=(0) { if (dblvl>0) { "// Trivial case: I is a principal ideal"; } list result=I; if (size(#)>0) { for (int k=1;k<=#[1]-1;k++) { result=insert(result,I*result[k],k); } } return(result); } int testrad=0; // do the radical check? int uselocNormal=0; if (size(#)>1) { testrad=#[2]; if (size(#)==3) { uselocNormal=#[3]; } } if (testrad==1) { if (dblvl>0) { "//Check whether I is radical"; } if (size(reduce(radical(I),std(I)))==0) { if (dblvl>0) { "//Trivial case: I is a radical ideal"; } list result=I; if (size(#)>0) { for (int k=1;k<=#[1]-1;k++) { result=insert(result,I*result[k],k); } } return(result); } } // start with the computation of the Rees Algebra R[It] of I if (dblvl>0) { "// We start with the Rees Algebra of I:"; } list Rees = ReesAlgebra(I); def R(1)=Rees[1]; def Kxt=Rees[2]; setring R(1); if (dblvl>0) { R(1); ker; ""; "// Now ClosureRees computes generators for the integral closure"; "// of R[It] step by step"; } // ClosureRees computes fractions in R[x,t] representing the generators // of the closure of R[It] in k[x,t], which is the same as the closure // in Q(R[It]). // the first size(images)-1 entries are the numerators of the gene- // rators, the last entry is the 'universal' denominator setring Kxt; list images = ClosureRees(Rees,uselocNormal); // ClosureRees was done after the first HomJJ-call // ==> I is integrally closed, and images consists of the only entry "closed" if ((size(images)==1) && (typeof(images[1])=="string")) { if (dblvl>0) { "//I is integrally closed!"; } setring BAS; list result=I; if (size(#)>0) { for (int k=1;k<=#[1]-1;k++) { result=insert(result,I*result[k],k); } } return(result); } // construct the fractions corresponding to the generators of the // closure of I and its powers, depending on # (in fact, they will // not be real fractions, of course). This is done in ClosurePower. list result = ClosurePower(images,#); // finally fetch the result to the old basering setring BAS; list result=fetch(Kxt,result); return(result); } example { "EXAMPLE:"; echo=2; ring R=0,(x,y),dp; ideal I = x2,xy4,y5; list J = normalI(I); I; J; // J[1] is the integral closure of I } /* LIB"reesclos.lib"; // 1. x^i,y^i in k[x,y] // geht bis i = 19 (800sec), bis i=10 wenige Sekunden, // bei i = 20 ueber 1GB Hauptspeicher, in der 9. Iteration no memory // (braucht 20 Iterationen) ring r = 0,(x,y),dp; int i = 6; ideal I = x^i,y^i; list J = normalI(I); I; J; //================================================================ // 2. x^i,y^i,z^i in k[x,y,z] // aehnlich wie 1., funktioniert aber nur bis i=5 und dauert dort // >1 h //================================================================ // 3. scheitert in der ersten Iteration beim Radikal // Standardbasis des singulaeren Ortes: 7h (in char0), // in char(p) viel schneller, obwohl kleine Koeffizienten // schon bei Radikal -Test braucht er zu lang (>1h) ring r = 0,(x,y,z),dp; //ring r = 32003,(x,y,z),dp; ideal I = x2+xy3-5z,z3+y2-xzy,x2y3z5+y3-y5; list l= ReesAlgebra(I); list J = normalI(I); I; J; */ singular-4.0.3+ds/Singular/LIB/resbinomial.lib000066400000000000000000002631131266270727000211510ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////// version="version resbinomial.lib 4.0.0.0 Jun_2013 "; // $Id: 7f5e8f0a7c702784ef3334266f3d767725a1f457 $ category="Resolution of singularities"; info=" LIBRARY: resbinomial.lib Combinatorial algorithm of resolution of singularities of binomial ideals in arbitrary characteristic. Binomial resolution algorithm of Blanco AUTHORS: R. Blanco, mariarocio.blanco@uclm.es, @* G. Pfister, pfister@mathematik.uni-kl.de PROCEDURES: BINresol(J); computes a E-resolution of singularities of (J) (THE SECOND PART IS NOT IMPLEMENTED YET) Eresol(J); computes a E-resolution of singularities of (J) in char 0 determinecenter(L1,L2,c,n,Y,a,mb,flag,control3); computes the next blowing-up center Blowupcenter(L1,id,m,L2,c,n,h); makes the blowing-up Nonhyp(Coef,expJ,sJ,n,flag,sums); computes the ideal generated by the non hyperbolic generators of expJ identifyvar(); identifies status of variables Edatalist(Coef,Exp,k,n,flag); gives the E-order of each term in Exp EOrdlist(Coef,Exp,k,n,flag); computes the E-order of an ideal (giving in the language of lists) maxEord(Coef,Exp,k,n,flag); computes de maximum E-order of an ideal given by Coef and Exp ECoef(Coef,expP,sP,V,auxc,n,flag); Computes a simplified version of the E-Coeff ideal. The E-orders are correct, but tranformations of coefficients of the generators and powers of binomials cannot be computed easily in terms of lists. elimrep(L); removes repeated terms from a list Emaxcont(Coef,Exp,k,n,flag); computes a list of hypersurfaces of E-maximal contact cleanunit(mon,n,flag); clean the units in a monomial mon resfunction(t,auxinv,nchart,n); composes the E-resolution function calculateI(Coef,J,c,n,Y,a,b,D); computes the order of the non monomial part of an ideal J Maxord(L,n); computes the maximum exponent of an exceptional monomial ideal Gamma(L,c,n); computes the Gamma function for an exceptional monomial ideal given by L convertdata(C,L,n,flag); computes the ideal corresponding to C,L lcmofall(nchart,mobile); computes the lcm of the denominators of the E-orders for all the charts computemcm(Eolist); computes the lcm of the denominators of the E-orders for one chart constructH(Hhist,n,flag); construct the list of exceptional divisors accumulated at this chart constructblwup(blwhist,n,chy,flag); construct the ideal defining the map K[W] --> K[Wi], which gives the composition map of all the blowing up leading to this chart constructlastblwup(blwhist,n,chy,flag); construct the ideal defining the last blowup leading to this chart genoutput(chart,mobile,nchart,nsons,n,q,p); generates the output for visualization salida(idchart,chart,mobile,numson,previousa,n,q); generates the output for one chart iniD(n); creates a list of lists of zeros of size n sumlist(L1,L2); sums two lists component to component reslist(L1,L2); subtracts two lists component to component multiplylist(L,a); multiplies a list by a number, component to component dividelist(L1,L2); divides two lists component to component createlist(L1,L2); creates a list of lists of two elements "; // inidata(K,k); verifies input data, a binomial ideal K of k generators // data(K,k,n); transforms data on lists of length n // list0(n); creates a list of zeros of size n LIB "general.lib"; LIB "qhmoduli.lib"; LIB "inout.lib"; LIB "poly.lib"; LIB "resolve.lib"; LIB "reszeta.lib"; LIB "resgraph.lib"; //////////////////////////////////////////////////////////////////////////// static proc inidata(ideal K,int k) "USAGE: inidata(K,k); K any ideal, k integer (!=0) COMPUTE: Verifies the input data RETURN: flag indicating if the ideal is binomial or not EXAMPLE: example inidata; shows an example " { int i; for (i=1;i<=k; i++) { if (size(K[i])>2){return(0);} } return(1); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; ideal J1=x(1)^4*x(2)^2, x(1)^2+x(3)^3; inidata(J1,2); ideal J2=x(1)^4*x(2)^2, x(1)^2+x(2)^3+x(3)^5; inidata(J2,2); } ///////////////////////////////////////////////////////////////////////////////// proc changeoriginalvar() "USAGE: changeoriginalvar(); COMPUTE: Change the name of the variables to x(1...n), only necessary at the beginning RETURN: the new ring with the suitable names EXAMPLE: example changeoriginalvar; shows an example " { int i,n,cont; n=nvars(basering); cont=0; def r=basering; // check the name of the variables for (i=1;i<=n; i++){if (varstr(i)[1]=="x" or varstr(i)[1]=="y"){cont=cont+1;}} // change them if there exists some variable different from x(i) or y(i) if (cont!=n or n<=2){ // making the change def Rnew=changevar ("x()"); setring Rnew; // print("INVERTIBLE VARIABLES NOT CONSIDERED AT THE BEGINNING"); return(Rnew,1); } else{ // print("INVERTIBLE VARIABLES ALREADY CONSIDERED AT THE BEGINNING"); return(r,0); } } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(2),x(3),y(4),x(5..7),y(8)),dp; changeoriginalvar(); ring r = 0,(x,y,z,w),dp; changeoriginalvar(); } ///////////////////////////////////////////////////////////////////////////////// proc identifyvar() "USAGE: identifyvar(); COMPUTE: Asign 0 to variables x and 1 to variables y, only necessary at the beginning RETURN: list, say l, of size the dimension of the basering l[i] is: 0 if the i-th variable is x(i), 1 if the i-th variable is y(i) EXAMPLE: example identifyvar; shows an example " { int i,n; list flaglist; n=nvars(basering); flaglist=list0(n); for (i=1;i<=n; i++){if (varstr(i)[1]=="y"){flaglist[i]=1;}} return(flaglist); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(2),x(3),y(4),x(5..7),y(8)),dp; identifyvar(); } ///////////////////////////////////////////////////////////////////////////////// proc data(ideal K,int k,int n) "USAGE: data(K,k,n); K any ideal, k integer (!=0), n integer (!=0) COMPUTE: Construcs a list with the coefficients and exponents of one ideal RETURN: lists of coefficients and exponents of K EXAMPLE: example data; shows an example " {int i,j,lon; number aa; intvec cc; list bb,dd,aux,ddaux,Coef,Exp; for (i=1;i<=k; i++) { lon=size(K[i]); // binomial if (lon==2){aa=leadcoef(K[i][1]); bb=aa; Coef[i]=bb; // coefficients cc=leadexp(K[i][1]); // exponents // cc is an intvec, transform cc in dd, a list of lists dd=cc[1..n]; aux[1]=dd; // the same for the second term aa=leadcoef(K[i][2]); bb=aa; Coef[i]=Coef[i] + bb; // all the coefficients of i-th generator of K cc=leadexp(K[i][2]); dd=cc[1..n]; aux[2]=dd; Exp[i]=aux;} // monomial if (lon==1){aux=list(); aa=leadcoef(K[i][1]); bb=aa; Coef[i]=bb; cc=leadexp(K[i][1]); dd=cc[1..n]; aux[1]=dd; Exp[i]=aux;} } //end for return(Coef,Exp); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; ideal J=x(1)^4*x(2)^2, x(1)^2-x(3)^3; data(J,2,3); } ////////////////////////////////////////////////////// proc Edatalist(list Coef,list Exp,int k,int n,list flaglist) "USAGE: Edatalist(Coef,Exp,k,n,flaglist); Coef,Exp,flaglist lists, k,n, integers Exp is a list of lists of exponents, k=size(Exp) COMPUTE: computes a list with the E-order of each term RETURN: a list with the E-order of each term EXAMPLE: example Edatalist; shows an example " {int i,j,lon,mm; list dd,ss,sums; number aux,aux1,aux2; for (i=1;i<=k;i++){lon=size(Coef[i]); if (lon==1) { for (j=1;j<=n;j++){if (flaglist[j]==0){aux=aux+Exp[i][1][j];}} ss=aux; aux=0;} // monomial else { for (j=1;j<=n;j++){if (flaglist[j]==0){ aux1=aux1+Exp[i][1][j]; aux2=aux2+Exp[i][2][j];}} ss=aux1,aux2; aux1=0; aux2=0; } // binomial sums[i]=ss;} return(sums); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(2),x(3),y(4),x(5..7),y(8)),dp; list flag=identifyvar(); ideal J=x(1)^3*x(3)-y(2)*y(4)^2,x(5)*y(2)-x(7)*y(4)^2,x(6)^2*(1-y(4)*y(8)^5); list L=data(J,3,8); list EL=Edatalist(L[1],L[2],3,8,flag); EL; // E-order of each term ring r = 2,(x(1),y(2),x(3),y(4),x(5..7),y(8)),dp; list flag=identifyvar(); ideal J=x(1)^3*x(3)-y(2)*y(4)^2,x(5)*y(2)-x(7)*y(4)^2,x(6)^2*(1-y(4)*y(8)^5); list L=data(J,3,8); list EL=Edatalist(L[1],L[2],3,8,flag); EL; // E-order of each term IN CHAR 2, COMPUTATIONS NEED TO BE DONE IN CHAR 0 ring r = 0,(x(1..3)),dp; list flag=identifyvar(); ideal J=x(1)^4*x(2)^2, x(1)^2-x(3)^3; list L=data(J,2,3); list EL=Edatalist(L[1],L[2],2,3,flag); EL; // E-order of each term } /////////////////////////////////////////////////////////////////////////////////// proc EOrdlist(list Coef,list Exp,int k,int n,list flaglist) "USAGE: EOrdlist(Coef,Exp,k,n,flaglist); Coef,Exp,flaglist lists, k,n, integers Exp is a list of lists of exponents, k=size(Exp) COMPUTE: computes de E-order of an ideal given by a list (Coef,Exp) and extra information RETURN: maximal E-order, and its position=number of generator and term EXAMPLE: example EOrdlist; shows an example " {int i,can,canpost,lon; number canmin; list sums; sums=Edatalist(Coef,Exp,k,n,flaglist); canmin=sums[1][1]; // inicializating, works also with a monomial for (i=1;i<=k; i++){lon=size(sums[i]); // this is 2 for binomial and 1 for monomial generators if (sums[i][1]<=canmin and Coef[i][1]!=0){canmin=sums[i][1]; can=i; canpost=1;} // if the generator is a binomial we check the second term if (lon==2) {if (sums[i][2]0){ for (i=1;i<=k; i++){lon=size(sums[i]); if (lon==2){if (sums[i][1]==maxEo) // variables of the first term {for (j=1;j<=n; j++){if(Exp[i][1][j]!=0 and flag[j]==0){bx=j; maxvar=maxvar + bx;}}} if (sums[i][2]==maxEo) // variables of the second term {for (j=1;j<=n; j++){if(Exp[i][2][j]!=0 and flag[j]==0){bx=j; maxvar=maxvar + bx;}}}} else {if (sums[i][1]==maxEo) {for (j=1;j<=n; j++){if(Exp[i][1][j]!=0 and flag[j]==0){bx=j; maxvar=maxvar + bx;}}}} }} else {maxvar=list();} // eliminating repeated terms maxvar=elimrep(maxvar); // It is necessary to check if flag[j]==0 in order to avoid the selection of y variables return(maxEo,maxvar); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(2),x(3),y(4),x(5..7),y(8)),dp; list flag=identifyvar(); ideal J=x(1)^3*x(3)-y(2)*y(4)^2,x(5)*y(2)-x(7)*y(4)^2,x(6)^2*(1-y(4)*y(8)^5),x(7)^4*y(8)^2; list L=data(J,4,8); list hyp=Emaxcont(L[1],L[2],4,8,flag); hyp[1]; // max E-order=0 hyp[2]; // There are no hypersurfaces of E-maximal contact ring r = 0,(x(1),y(2),x(3),y(4),x(5..7),y(8)),dp; list flag=identifyvar(); ideal J=x(1)^3*x(3)-y(2)*y(4)^2*x(3),x(5)*y(2)-x(7)*y(4)^2,x(6)^2*(1-y(4)*y(8)^5),x(7)^4*y(8)^2; list L=data(J,4,8); list hyp=Emaxcont(L[1],L[2],4,8,flag); hyp[1]; // the E-order is 1 hyp[2]; // {x(3)=0},{x(5)=0},{x(7)=0} are hypersurfaces of E-maximal contact } /////////////////////////////////////////////////////// proc cleanunit(list mon,int n,list flaglist) "USAGE: cleanunit(mon,n,flaglist); mon, flaglist lists, n integer COMPUTE: We clean (or forget) the units in a monomial, given by "y" variables RETURN: The list defining the monomial ideal already cleaned EXAMPLE: example cleanunit; shows an example " { int i; for (i=1;i<=n;i++){if (flaglist[i]==1){mon[i]=0;}} // coef[1]=coef[1]*y(i)^mon[i]; IS NOT ALLOWED because mon[i] can be a number // therefore, the coefficients remain constant return(mon); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(2),x(3),y(4)),dp; list flag=identifyvar(); ideal J=x(1)^3*y(2)*x(3)^5*y(4)^8; list L=data(J,1,4); L[2][1][1]; // list of exponents of the monomial J list M=cleanunit(L[2][1][1],4,flag); M; // new list without units } ////////////////////////////////////////////////////// // Classification of the ideal E-Coeff_V(P): // ccase=1, E-Coeff_V(P)=0 // 2,3 Bold regular case // 4 P=1 monomial case (detected before) // 0 Otherwise proc ECoef(list Coef,list expP,int sP,int V,number auxc,int n,list flaglist) "USAGE: ECoef(Coef,expP,sP,V,auxc,n,flaglist); Coef, expP, flaglist lists, sP, V, n integers, auxc number COMPUTE: The ideal E-Coeff_V(P), where V is a permissible hypersurface which belongs to the center RETURN: list of exponents, list of coefficients and classification of the ideal E-Coeff_V(P) EXAMPLE: example ECoef; shows an example " { int i,j,k,l,numg,ccase,cont2,cont3,val; number aa; list Eco,newcoef,auxexp,newL,rs,rs2,aux,aux2,aux3,aux4,L; auxexp=expP; l=1; for (i=1;i<=sP;i++) {rs[i]=size(Coef[i]); if (rs[i]==2){ // binomials if (auxexp[i][1][V]!=auxexp[i][2][V]) // no common factors for the variable in V {for (j=1;j<=2;j++){if (auxexp[i][j][V]1){ccase=3;} // CASE P=x^{\alpha},x^{\beta}, IN FACT, BOLD REGULAR if (cont2==val and cont3==0){ccase=4;} // P=1, then I=1 monomial case // Case BOLD REGULAR P=x^{\alpha}*(1-\mu y^{\delta}) // IT IS NON NECESSARY TO CHECK IT, Eco=empty list, already done! L=maxEord(newcoef,Eco,numg,n,flaglist); // L[1] is the E-order of Eco if (L[1]==0){ccase=2; print("E-order zero!");} // BOLD REGULAR CASE // we leave it to check the computations } // close else return(Eco,newcoef,ccase); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(2),x(3),y(4),x(5..7)),dp; list flag=identifyvar(); ideal P=x(1)^2*x(3)^5-x(5)^7*y(4),x(6)^3*y(2)^5-x(7)^5,x(5)^3*x(6)-y(4)^3*x(1)^5; list L=data(P,3,7); list L2=ECoef(L[1],L[2],3,1,3,7,flag); L2[1]; // exponents of the E-Coefficient ideal respect to x(1) L2[2]; // its coefficients L2[3]; // classify the type of ideal obtained ring r = 0,(x(1),y(2),x(3),y(4)),dp; list flag=identifyvar(); ideal J=x(1)^3*(1-2*y(2)*y(4)^2); // Bold regular case list L=data(J,1,4); list L2=ECoef(L[1],L[2],1,1,3,4,flag); L2; ring r = 0,(x(1),y(2),x(3),y(4),x(5..7)),dp; list flag=identifyvar(); ideal J=x(1)^3-x(3)^2*y(4)^2,x(1)*x(7)*y(2)-x(6)^3*x(5)*y(4)^3,x(5)^3-x(5)^3*y(2)^2; list L=data(J,3,7); list L2=ECoef(L[1],L[2],3,1,2,7,flag); L2; ring r = 3,(x(1),y(2),x(3),y(4),x(5..7)),dp; list flag=identifyvar(); ideal J=x(1)^3-x(3)^2*y(4)^2,x(1)*x(7)*y(2)-x(6)^3*x(5)*y(4)^3,x(5)^3-x(5)^3*y(2)^2; list L=data(J,3,7); list L2=ECoef(L[1],L[2],3,1,2,7,flag); L2; // THE COMPUTATIONS ARE NOT CORRECT IN CHARACTERISTIC p>0 // because numbers are treated as 0 in assignments } //////////////////////////////////////////////////////////////////////////// // The intvec a indicates the previous center // Hhist = intvec of exceptional divisors of the parent chart proc determinecenter(list Coef,list expJ,number c,int n,int Y,intvec a,list listmb,list flag,int control3,intvec Hhist) "USAGE: determinecenter(Coef,expJ,c,n,Y,a,listmb,flag,control3,Hhist); Coef, expJ, listmb, flag lists, c number, n, Y, control3 integers, a, Hhist intvec COMPUTE: next center of blowing up and related information, see example RETURN: several lists defining the center and related information EXAMPLE: example determinecenter; shows an example " {int i,j,rstep,l,mm,cont,cont1,cont2,cont3,a4,sI,sP,V,V2,ccase,b,Mindx,tip,mval; number auxc,a1,a2,ex,maxEo,aux; list D,H,auxJ; // lists of D_n,D_n-1,...,D_1; H_n,H_n-1,...,H_1; J_n,J_n-1,...,J_1 list oldOlist,oldC,oldt,oldD,oldH,allH; // information of the previous step list Olist,C,t,Dstar,center,expI,expP,newJ,maxset; list maxvar,auxlist,aux3,auxD,auxolist,auxdiv,auxaux,L,rs,auxgamma,auxg2,aux1; // auxiliary lists list auxinvlist,newcoef,EL,Ecoaux,Hplus,transH,Hsum,auxset,sumnewH; // auxiliary lists list auxcoefI,auxcent,center2; intvec oldinfobo7,infobo7; int infaux,leh,leh2,leh3; tip=listmb[1]; // It is not used in this procedure, it is used to compute the lcm of the denominators oldOlist=listmb[2]; oldC=listmb[3]; oldt=listmb[4]; // t= resolution function oldD=listmb[5]; oldH=listmb[6]; allH=listmb[7]; oldinfobo7=listmb[8]; // auxiliary intvec, it is used to define BO[7] // inicializating lists Olist=list(); C=list(); auxinvlist=list(); auxJ[1]=expJ; rstep=n; // we are in dimension rstep auxc=c; cont=1; if (Y==0) {D=iniD(n); H=iniD(n); infobo7=-1;} // first center, inicializate previous information if (Y!=0 and rstep==n) // In dimension n, D'_n is always of this form { auxdiv=list0(n); Dstar[1]=oldD[1]; b=size(a); for (i=1;i<=n;i++) {for (j=1;j<=b;j++) {if (a[j]==i) {aux=aux+oldD[1][i];}}} Dstar[1][Y]=aux; aux=0; auxdiv[Y]=oldOlist[1]-oldC[1]; D[1]=sumlist(Dstar[1],auxdiv);} // list defining D_n // computing strict transforms of the exceptional divisors H if (Y!=0){transH=iniD(n); for (i=1;i<=size(oldH);i++){transH[i]=oldH[i]; transH[i][Y]=0;} // Note: size(oldH)<=n allH[Y]=1;} // transform of |H|=H_nU...UH_1 // We put here size(oldH) instead of n because maybe we have not // calculated all the dimensions in the previous step // STARTING THE LOOP while (rstep>=1) { if (Y!=0 and rstep!=n) // transformation law of D_i for ia4){cont=0; oldt[n-rstep+1]=0; } // VERIFICAR!!!! if (cont!=0 and oldt[n-rstep+1]==a1/a2 and c==oldC[1] and control3==0){H[n-rstep+1]=transH[n-rstep+1]; // we fill now the value for BO[7] if (oldinfobo7[n-rstep+1]==-1){leh=size(Hhist); infobo7[n-rstep+1]=Hhist[leh];} // suitable index !!! else{ infaux=oldinfobo7[n-rstep+1]; infobo7[n-rstep+1]=infaux;} // the same as the previous step } else { if (rstep=auxc) {expP=expI; Mindx=0;} // The coefficients also remain constant else {ex=maxEo/(auxc-maxEo); auxlist=list(); Mindx=1; auxlist[1]=multiplylist(D[n-rstep+1],ex); // weighted monomial part: D[n-rstep+1]^ex; expP=insert(expI,auxlist); // P=I+D[n-rstep+1]^ex; auxcoefI=Coef; Coef=insert(Coef,list(1));} // Adding the coefficient for M // NOTE: IT IS NECESSARY TO ADD COEFFICIENT 1 TO THE MONOMIAL PART M // E-ord(P_i)=E-ord(I_i) so to compute the E-order of P_i we can compute E-ord(I_i) // Calculate variables of E-maximal contact, ALWAYS WITH RESPECT TO THE IDEAL I !! sP=size(expP); // Can be different from size(expI) if (Mindx==1){ maxvar=Emaxcont(auxcoefI,expI,sI,n,flag);} else{ maxvar=Emaxcont(Coef,expP,sP,n,flag);} auxc=maxvar[1]; // E-order of P, critical value for the next step, ALSO VALID auxc=maxEo; if (auxc!=maxEo){print("ERROR, the E-order is not well computed");} maxset=maxvar[2]; // center=center + maxset; // HACER DESPUES Y A?ADIR SOLO V!!!!!! // Cleaning the center: eliminating repeated variables // center=elimrep(center); // if (rstep==1) {break;} // Induction finished, is not necessary to compute the rest // Calculate Hplus=set of non permissible hypersurfaces // RESET Hplus if c has dropped or we have eliminated hyperbolic generators // ES NECESARIO PONER CONDICION DE SI INVARIANTE BAJA O NO??? SI BAJA HPLUS NO SE USA... if (Y==0 or c gives (max E-order,sums) proc Nonhyp(list Coef,list expJ,int sJ,int n,list flaglist,list sums) "USAGE: Nonhyp(Coef,expJ,sJ,n,flaglist,sums); Coef, expJ, flaglist, sums lists, sJ, n integers COMPUTE: The "ideal" generated by the non hyperbolic generators of J RETURN: lists with the following information newcoef,newJ: coefficients and exponents of the non hyperbolic generators totalhyp,totalgen: coefficients and exponents of the hyperbolic generators flaglist: new list saying status of variables NOTE: the basering r is supposed to be a polynomial ring K[x,y], in fact, we work in a localization of K[x,y], of type K[x,y]_y with y invertible variables. EXAMPLE: example Nonhyp; shows an example " { int i,j,k,h,lon,lon2,cont; number eordcontrol; list genhyp,listgen,listid,posnumJ,newJ,newcoef,hypcoef,hyp,aux1,aux2,aux3,aux,midlist; list totalhyp,totalgen; eordcontrol=0; while (eordcontrol==0 and sJ!=0) { // Give a positional number/flag to each generator of expJ for (i=1;i<=sJ; i++){listgen=expJ[i]; listid=i; posnumJ[i]=listgen+listid; } // Select the non hyperbolic and hyperbolic generators for (j=1;j<=sJ; j++){lon=size(Coef[j]); if (lon==1){ // IS NOT NECESSARY TO CHECK IF THERE EXIST A MONOMIAL WITH ONLY UNITS, ALREADY DONE!! aux1=aux1+posnumJ[j]; aux3=list(); aux3[1]=expJ[j]; newJ=newJ+aux3; aux3[1]=Coef[j]; newcoef=newcoef+aux3; } else{ // CHECKING BINOMIALS, ONE TERM WITH E-ORDER ZERO GIVES HYPERBOLIC EQ if (sums[j][1]==0 or sums[j][2]==0){aux2=aux2+posnumJ[j]; aux3=list(); aux3[1]=expJ[j]; genhyp=genhyp+aux3; aux3[1]=Coef[j]; hypcoef=hypcoef+aux3; if (sums[j][1]==0){aux3[1]=expJ[j][2]; hyp=hyp+aux3;} if (sums[j][2]==0){aux3[1]=expJ[j][1]; hyp=hyp+aux3;} } else {aux1=aux1+posnumJ[j]; aux3=list(); aux3[1]=expJ[j]; newJ=newJ+aux3; aux3[1]=Coef[j]; newcoef=newcoef+aux3;} } } // NOTE: aux1 and aux2 are no needed right now! // Identify new y variables, that is, x variables in the monomials contained in hyp h=size(hyp); for (k=1;k<=h; k++){ for(i=1;i<=n; i++){ if (hyp[k][i]!=0 and flaglist[i]==0) {flaglist[i]=1;}}} // To replace x by y IT IS NECESSARY TO CHANGE THE BASERING!!! We change only the list flaglist // CHECK IF THE IDEAL IS ALREADY GENERATED BY MONOMIALS, in this case // WE HAVE FINISHED THE E-RESOLUTION PART, J GENERATED BY MONOMIALS AND HYPERBOLIC EQS cont=0; lon2=size(newJ); for (j=1;j<=lon2; j++){if (size(newJ[j])==1){cont=cont+1;}} if (cont==lon2){newcoef=list(); newJ=list(); totalgen=totalgen+genhyp; totalhyp=totalhyp+hypcoef; break;} // CHECK IF THERE ARE MORE HYPERBOLIC EQUATIONS AFTER UPDATE THE FLAG LIST // CHECK THE MAXIMAL E-ORDER AGAIN if (lon2==0){ // we are in the previous case, newJ=empty list, save values and exit totalgen=totalgen+genhyp; totalhyp=totalhyp+hypcoef; break; } midlist=maxEord(newcoef,newJ,lon2,n,flaglist); eordcontrol=midlist[1]; if (eordcontrol==0){ // new input for the loop Coef=newcoef; expJ=newJ; sJ=lon2; sums=midlist[2]; // flaglist is already updated totalgen=totalgen+genhyp; totalhyp=totalhyp+hypcoef; hypcoef=list(); genhyp=list(); newJ=list(); newcoef=list(); } else{ // If the process is already finished we save the values and exit totalgen=totalgen+genhyp; totalhyp=totalhyp+hypcoef; } } // closing while return(newcoef,newJ,totalhyp,totalgen,flaglist); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1),y(2),x(3),y(4),x(5..7)),dp; list flag=identifyvar(); // List giving flag=1 to invertible variables: y(2),y(4) ideal J=x(1)^3-x(3)^2*y(4)^2,x(1)*x(7)*y(2)-x(6)^3*x(5)*y(4)^3,1-x(5)^2*y(2)^2; list L=data(J,3,7); list L2=maxEord(L[1],L[2],3,7,flag); L2[1]; // Maximum E-order list New=Nonhyp(L[1],L[2],3,7,flag,L2[2]); New[1]; // Coefficients of the non hyperbolic part New[2]; // Exponents of the non hyperbolic part New[3]; // Coefficients of the hyperbolic part New[4]; // New hyperbolic equations New[5]; // New list giving flag=1 to invertible variables: y(2),y(4),y(5) ring r = 0,(x(1..4)),dp; list flag=identifyvar(); ideal J=1-x(1)^5*x(2)^2*x(3)^5, x(1)^2*x(3)^3+x(1)^4*x(4)^6; list L=data(J,2,4); list L2=maxEord(L[1],L[2],2,4,flag); L2[1]; // Maximum E-order list New=Nonhyp(L[1],L[2],2,4,flag,L2[2]); New; } ////////////////////////////////////////////////////////////// proc calculateI(list Coef,list expJ,number c,int n,int Y,intvec a,number oldordI,list oldD) "USAGE: calculateI(Coef,expJ,c,n,Y,a,b,D); Coef, expJ, D lists, c, b numbers, n,Y integers, a intvec RETURN: ideal I, non monomial part of J EXAMPLE: example calculateI; shows an example " { int i,cont1,b,j; number EordI,aux; list D,L,expI; list auxdiv,Dstar,aux1,rs; // WE NEED THE MONOMIAL PART, BUT ONLY IN DIMENSION n auxdiv=list0(n); auxdiv[Y]=oldordI-c; Dstar[1]=oldD[1]; b=size(a); for (i=1;i<=n;i++) {for (j=1;j<=b;j++) {if (a[j]==i) {aux=aux+oldD[1][i];}}} Dstar[1][Y]=aux; aux=0; D[1]=sumlist(Dstar[1],auxdiv); cont1=0; for (i=1;i<=n;i++) {if (D[1][i]==0) {cont1=cont1+1;}} // if it fails write listO(n)[i] if (cont1==n) {expI=expJ;} else { for (i=1;i<=size(expJ);i++) {rs[i]=size(Coef[i]); if (rs[i]==2){ aux1=list(); aux1[1]=reslist(expJ[i][1],D[1]); aux1[2]=reslist(expJ[i][2],D[1]); expI[i]=aux1;} // binomial else {aux1=list(); aux1[1]=reslist(expJ[i][1],D[1]); expI[i]=aux1;}} // monomial } return(expI); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; list flag=identifyvar(); ideal J=x(1)^4*x(2)^2, x(3)^3; list Lmb=1,list(0,0,0),list(0,0,0),list(3),iniD(3),iniD(3),list(0,0,0),-1; list L=data(J,2,3); list LL=determinecenter(L[1],L[2],3,3,0,0,Lmb,flag,0,-1); // Calculate the center module auxpath=[0,-1]; list infochart=0,0,0,L[2],L[1],flag,0,list(0,0,0),auxpath,list(),list(); list L3=Blowupcenter(LL[1],1,1,infochart,3,3,0); // blowing-up and looking to the x(3) chart calculateI(L3[2][1][5],L3[2][1][4],3,3,3,L3[2][1][3],3,iniD(3)); // (I_3) // looking to the x(1) chart calculateI(L3[2][2][5],L3[2][2][4],3,3,1,L3[2][2][3],3,iniD(3)); // (I_3) } ////////////////////////////////////////////////////////////////////////////////////// // // // E-RESOLUTION: Eresol(J) subroutine computing the E-resolution of J, char 0 // // // ////////////////////////////////////////////////////////////////////////////////////// proc Eresol(ideal J) "USAGE: Eresol(J); J ideal RETURN: The E-resolution of singularities of J in terms of the affine charts, see example EXAMPLE: example Eresol; shows an example " {int i,n,k,idchart,nchart,parent,Y,oldid,tnum,s,cont,control,control2,control3,cont2,val,rs2,l,cont3,tip; intvec a,Hhist; number c,EordJ,EordI,oldordI; list L,LL,oldD,t,auxL,finalchart,chart,auxchart,newL,auxp,auxfchart,L2; list Coef,expJ,expI,sons,oldOlist,oldC,oldt,oldH,allH,auxordJ,auxordI,auxmb,mobile,invariant; list step,nsons,auxinv,extraL,totalinv,auxsum; string empstring; module auxpath; // ADDED LATER list flag,newflag,blwhist,hipercoef,hiperexp,hipercoefson,hiperexpson; intvec infobo7; export finalchart; // export nsons; // export tnum; // export nchart; // export step; export invariant; export auxinv; export mobile; n=nvars(basering); flag=identifyvar(); k=size(J); // Checking input data if (inidata(J,k)==0){return("This library only works for binomial ideals.");} idchart=1; nchart=1; parent=0; step=0; control=0; control2=0; control3=0; // Translate the input ideal to a list auxL=data(J,k,n); // data gives (Coef,Exp) // THEREAFTER WE WORK ALL THE TIME WITH LISTS L=maxEord(auxL[1],auxL[2],k,n,flag); // gives (max E-ord, sums) EordJ=L[1]; // before the first blow up I=J EordI=EordJ; // main loop AT EACH CHART WE MUST INICIALIZATE ALL THE VALUES AND // CONSTRUCT THE FIRST CHART chart[1] BEFORE THE LOOP // at the first step, before the blow up, there are no exceptional divisors, Y=0 Y=0; expJ=auxL[2]; Coef=auxL[1]; Hhist=0; blwhist=list0(n); auxpath=[0,-1]; hipercoef=list(); // this is for the first chart hiperexp=list(); auxp=parent,Y,a,expJ,Coef,flag,Hhist,blwhist,auxpath,hipercoef,hiperexp; chart[1]=auxp; // information of the first chart tip=1; oldOlist=list0(n); oldC=list0(n); oldC[1]=EordJ; // non necessary here c=EordJ; // the value c is given by the previous step oldt=list0(n); oldD=iniD(n); oldH=iniD(n); allH=list0(n); for (i=1;i<=n;i++){infobo7[i]=-1;} auxmb=tip,oldOlist,oldC,oldt,oldD,oldH,allH,infobo7; mobile[1]=auxmb; // mobile corresponding to the first chart auxinv[1]=list(0); // NOTE: oldC[1] is the value c to classify the chart in one of the next cases // HERE BEGIN THE LOOP while (idchart<=nchart) // WE PROCEED WHILE THERE EXIST UNSOLVED CHARTS { if (idchart!=1) // WE ARE NOT IN THE FIRST CHART, INICIALIZATE ALL THE VALUES { parent=chart[idchart][1]; Y=chart[idchart][2]; a=chart[idchart][3]; expJ=chart[idchart][4]; Coef=chart[idchart][5]; flag=chart[idchart][6]; Hhist=chart[idchart][7]; // it is not necessary for the computations blwhist=chart[idchart][8]; auxpath=chart[idchart][9]; hipercoef=chart[idchart][10]; hiperexp=chart[idchart][11]; k=size(Coef); // IT IS NECESSARY TO COMPUTE IT BECAUSE IT DECREASES IF THERE ARE HYPERBOLIC EQS auxordJ=maxEord(Coef,expJ,k,n,flag); EordJ=auxordJ[1]; if (control==0){c=mobile[parent+1][3][1];} // we keep c from the last step else {c=EordJ; control=0; } // we reset the value of c if (control2==1){c=EordJ; control2=0; control3=1;} // we reset the value of c // NOTE: oldC[1] is the value c to classify the chart in one of the next cases } // The E-order must be computed here oldid=idchart; if (EordJ<0) {print("ERROR in J in chart"); print(idchart); ~; break;} //------------------------------------------------------------- // CASE J=1, if we reset c, can happen Eord=c=0 // or if there are hyperbolic equations at the beginning!!! A?ADIR!!!! // if (EordJ==0){auxfchart[1]=chart[idchart]; // WE HAVE FINISHED // finalchart=finalchart+auxfchart; // empstring="#"; print("reset c and Eord=c=0"); print(idchart); // invariant[idchart]=empstring; // auxinv[idchart]=list(0); // nsons[idchart]=0; // idchart=idchart+1;} //---------------------------------------------------------------------- if (EordJ>=c and EordJ!=0) // subroutine: E-RESOLUTION OF PAIRS { if (parent>0) { LL=determinecenter(Coef,expJ,c,n,Y,a,mobile[parent+1],flag,control3,chart[parent][7]); } else { LL=determinecenter(Coef,expJ,c,n,Y,a,mobile[parent+1],flag,control3,Hhist); } // determinecenter gives (center,auxJ,Olist,C,t,D,H,allH,auxinvlist,infobo7) // save current values, before the blow up oldOlist=LL[3]; tip=computemcm(oldOlist); oldC=LL[4]; oldt=LL[5]; oldD=LL[6]; oldH=LL[7]; allH=LL[8]; auxinv[idchart]=LL[9]; infobo7=LL[10]; auxmb=tip,oldOlist,oldC,oldt,oldD,oldH,allH,infobo7; mobile[idchart+1]=auxmb; invariant[idchart]=oldt; newL=Blowupcenter(LL[1],idchart,nchart,chart[idchart],c,n,step[idchart]); // Blowupcenter gives (info,auxchart,nchart,auxstep,num) // IMPORTANT: ADD THE NEW CHARTS AFTER EACH BLOW UP, IN ORDER TO KEEP THEM CORRECTLY step=step+newL[4]; nsons[idchart]=newL[5]; chart=chart+newL[2]; finalchart=finalchart+newL[1]; // new input for the loop idchart=idchart+1; nchart=newL[3]; control3=0; } // END OF CASE EordJ>=c //--------------------------------------------------------------------- else{ // compute EordI=max E-order(I) expI=calculateI(Coef,expJ,c,n,Y,a,mobile[parent+1][2][1],mobile[parent+1][5]); k=size(expJ); // probably non necessary auxordI=maxEord(Coef,expI,k,n,flag); EordI=auxordI[1]; auxsum=auxordI[2]; // CASE EordI>0 DROP c AND CONTINUE if (EordI>0){idchart=idchart; // keep the chart and back to the main loop while, dropping the value of c control=1;} else{ // EordI=0, so check if I=1 or not cont2=0; // If cont2=val then all the entries of expI are zero!! val=0; for (i=1;i<=k;i++) {rs2=size(Coef[i]); if (rs2==1){if (auxsum[i][1]==0){cont2=val; break;} // THERE EXIST A MONOMIAL WITH ONLY UNITS val=val+n; // monomials for (l=1;l<=n; l++) {if (expI[i][1][l]==0) {cont2=cont2+1;}} } else{val=val+(2*n); // binomials for (l=1;l<=n; l++) {if (expI[i][1][l]==0) {cont2=cont2+1;} if (expI[i][2][l]==0) {cont2=cont2+1;}} } } // CASE EordI==0 AND I=1 THIS CHART IS DONE, FINISH // NOTE: THIS CASE IS NOT MONOMIAL BECAUSE E-Sing(J,c) is empty if (cont2==val){auxfchart[1]=chart[idchart]; finalchart=finalchart+auxfchart; empstring="#"; invariant[idchart]=empstring; auxinv[idchart]=list(0); nsons[idchart]=0; // information for the mobile tip=1; oldOlist=list(0); oldC=list(0); oldt=list(0); oldD=list(0); oldH=list(0); allH=list(0); // the value of the parent + the new one infobo7=-1; auxmb=tip,oldOlist,oldC,oldt,oldD,oldH,allH,infobo7; mobile[idchart+1]=auxmb; idchart=idchart+1;} else{ // CASE EordI==0 AND I!=1 --> HYPERBOLIC EQUATIONS // COMPUTE THE IDEAL OF NON HYPERBOLIC ELEMENTS extraL=Nonhyp(Coef,expI,k,n,flag,auxordI[2]); // gives (newcoef,newI,hypcoef,genhyp,flaglist) // CHECK IF ALL THE VARIABLES ARE ALREADY INVERTIBLE newflag=extraL[5]; chart[idchart][6]=extraL[5]; // update the status of variables cont3=0; for (i=1;i<=n;i++){if (newflag[i]==1){cont3=cont3+1;}} if (cont3==n){ // ALL THE VARIABLES ARE INVERTIBLE auxfchart[1]=chart[idchart]; finalchart=finalchart+auxfchart; empstring="@"; invariant[idchart]=empstring; auxinv[idchart]=list(0); nsons[idchart]=0; // information for the mobile tip=1; oldOlist=list(0); oldC=list(0); oldt=list(0); oldD=list(0); oldH=list(0); allH=list(0); infobo7=-1; auxmb=tip,oldOlist,oldC,oldt,oldD,oldH,allH,infobo7; mobile[idchart+1]=auxmb; idchart=idchart+1;} else{ // OTHERWISE, CONTINUE CHEKING IF newI=0 or not Coef=extraL[1]; expI=extraL[2]; hipercoefson=extraL[3]; // Information about hyperbolic generators hiperexpson=extraL[4]; k=size(expI); if (k==0){auxfchart[1]=chart[idchart]; // WE HAVE FINISHED finalchart=finalchart+auxfchart; empstring="#"; // no more non-hyperbolic generators in this chart invariant[idchart]=empstring; auxinv[idchart]=list(0); nsons[idchart]=0; // information for the mobile tip=1; oldOlist=list(0); oldC=list(0); oldt=list(0); oldD=list(0); oldH=list(0); allH=list(0); infobo7=-1; auxmb=tip,oldOlist,oldC,oldt,oldD,oldH,allH,infobo7; mobile[idchart+1]=auxmb; idchart=idchart+1;} else{ // CONTINUE WITH THE IDEAL OF NON HYPERBOLIC EQS chart[idchart][4]=expI; // new input ideal and coefficients chart[idchart][5]=Coef; chart[idchart][10]=hipercoef+hipercoefson; chart[idchart][11]=hiperexp+hiperexpson; idchart=idchart; control2=1; // it is necessary to reset the value of c control3=1; // and the previous exceptional divisors } // PROBABLY IT IS NEC MORE INFORMATION !!! } // closing else otherwise } // closing else case I!=1 } // closing else for EordI=0 if (EordI<0) {print("ERROR in chart"); print(idchart); ~; break;} //----------------------- guardar de momento-------- // if (EordI==0) {auxfchart[1]=chart[idchart]; // finalchart=finalchart+auxfchart; // L2=Gamma(expJ,c,n); // HAY QUE APLICARLO AL M NO AL J // invariant[idchart]=L2[2]; // auxinv[idchart]=list(0); // nsons[idchart]=0; // idchart=idchart+1;} //------------------------------------------------ } // END ELSE //--------------------------------------------------- } // END LOOP WHILE tnum=step[nchart]; totalinv=resfunction(invariant,auxinv,nchart,n); return(chart,finalchart,invariant,nchart,step,nsons,auxinv,mobile,totalinv); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..2)),dp; ideal J=x(1)^2-x(2)^3; list L=Eresol(J); "Please press return after each break point to see the next element of the output list"; L[1][1]; // information of the first chart, L[1] list of charts ~; L[2]; // list of charts with information about sons ~; L[3]; // invariant, "#" means solved chart ~; L[4]; // number of charts, 7 in this example ~; L[5]; // height corresponding to each chart ~; L[6]; // number of sons ~; L[7]; // auxiliary invariant ~; L[8]; // H exceptional divisors and more information ~; L[9]; // complete resolution function "Second example, write L[i] to see the i-th component of the list"; ring r = 0,(x(1..3)),dp; ideal J=x(1)^2*x(2),x(3)^3; // SOLVED! list L=Eresol(J); L[4]; // 16 charts L[9]; // complete resolution function ~; "Third example, write L[i] to see the i-th component of the list"; ring r = 0,(x(1..2)),dp; ideal J=x(1)^3-x(1)*x(2)^3; list L=Eresol(J); L[4]; // 8 charts, rational exponents L[9]; // complete resolution function ~; } ////////////////////////////////////////////////////////////////////////////////////// proc resfunction(list invariant, list auxinv, int nchart,int n) "USAGE: resfunction(invariant,auxinv,nchart,n); invariant, auxinv lists, nchart, n integers COMPUTE: Patch the resolution function RETURN: The complete resolution function EXAMPLE: example resfunction; shows an example " { int i,j,l,k; list patchfun,aux; for (i=1;i<=nchart;i++){patchfun[i]=invariant[i];} for (i=1;i<=nchart;i++){if (auxinv[i][1]!=0 and size(auxinv[i])==3){l=size(invariant[i]); for (j=1;j<=l;j++){ if (invariant[i][j]==0){aux=auxinv[i]; patchfun[i][j]=aux; if (l0){list Lring=ringlist(basering); Lring[1]=0; // def r=basering; def Rnew=ring(Lring); setring Rnew; ideal chy=maxideal(1); map fRnew=r,chy; ideal J=fRnew(J); // E-RESOLUTION, Computations in char 0 list L=Eresol(J); // STEP 2: WRITE THE LOCALLY MONOMIAL IDEAL AS A MONOMIAL IDEAL // not implemented yet, CHAR p !!!! // STEP 3: DO THE E-RESOLUTION AGAIN (char 0 again) // generating output in char p int q=lcmofall(L[4],L[8]); // lcm of the denominators list B=genoutput(L[1],L[8],L[4],L[6],n,q,p); // generate output needed for visualization // setring r; // Back to the basering // ideal chy=maxideal(1); // map fr=Rnew,chy; // list L=fr(L); // list B=fr(B); } else{ // E-RESOLUTION list L=Eresol(J); // STEP 2: WRITE THE LOCALLY MONOMIAL IDEAL AS A MONOMIAL IDEAL // not implemented yet // STEP 3: DO THE E-RESOLUTION AGAIN // generating output int q=lcmofall(L[4],L[8]); list B=genoutput(L[1],L[8],L[4],L[6],n,q,p); } return(B); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..2)),dp; ideal J=x(1)^2-x(2)^3; list B=BINresol(J); B[1]; // list of final charts B[2]; // list of all charts ring r = 2,(x(1..3)),dp; ideal J=x(1)^2-x(2)^2*x(3)^2; list B=BINresol(J); B[2]; // list of all charts } /////////////////////////////////////////////////////// proc Maxord(list L,int n) "USAGE: Maxord(L,n); L list, n integer COMPUTE: Find the maximal entry of a list, input is a list defining a monomial RETURN: maximum entry of a list and its position EXAMPLE: example Maxord; shows an example " {int i,can; number canmax; list aux; canmax=1; can=1; for (i=1;i<=n;i++) { if (L[i]>=canmax and i>=can) {canmax=L[i]; can=i;}} return(canmax,can); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; ideal J=x(1)^2*x(2)*x(3)^5; list L=data(J,1,3); L[2]; // list of exponents Maxord(L[2][1][1],3); } /////////////////////////////////////////////////////// proc Gamma(list expM,number c,int n) "USAGE: Gamma(L,c,n); L list, c number, n integer COMPUTE: The Gamma function, resolution function corresponding to the monomial case RETURN: lists of maximum exponents in L, value of Gamma function, center of blow up EXAMPLE: example Gamma; shows an example " {int i,j,k,l,cont,can; intvec upla; number canmax; list expM2,gamma,L,aux,maxlist,center,aux2; i=1; cont=0; expM2=expM; while (cont==0 and i<=n) { L=Maxord(expM2,n); aux=L[1]; maxlist=maxlist + aux; can=L[2]; if (i==1) {upla=can; center=can;} else {upla=upla,can; aux2=can; center=center+aux2;} canmax=sum(maxlist); if (canmax>=c) {gamma[1]=-i; gamma[2]=canmax/c; gamma[3]=upla; cont=1;} else {expM2[can]=0;} i=i+1; } return(maxlist,gamma,center); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..5)),dp; ideal J=x(1)^2*x(2)*x(3)^5*x(4)^2*x(5)^3; list L=data(J,1,5); list G=Gamma(L[2][1][1],9,5); // critical value c=9 G[1]; // maximum exponents in the ideal G[2]; // maximal value of Gamma function G[3]; // center given by Gamma } /////////////////////////////////////////////////////// proc convertdata(list C,list L, int n, list flaglist) "USAGE: convertdata(C,L,n,flaglist); C, L, flaglist lists, n integer COMPUTE: Compute the ideal corresponding to the given lists C,L RETURN: an ideal whose coefficients are given by C, exponents given by L EXAMPLE: example convertdata; shows an example " {int i,j,k,a,b,lon; poly aux,aux1,aux2,aux3,f; ideal J; aux=poly(0); aux1=poly(1); aux2=poly(0); aux3=poly(1); k=size(L); for (i=1;i<=k;i++){lon=size(C[i]); if (lon==1){ // variables in the monomial for (j=1;j<=n;j++){a=int(poly(L[i][1][j])); if (a!=0){ if (flaglist[j]==0){aux=poly(x(j)^a); aux1=aux1*aux;} else {aux=poly(y(j)^a); aux1=aux1*aux;} } } if (C[i][1]!=0){aux1=C[i][1]*aux1;} // we add the coefficient else {aux1=0;} J[i]=aux1; aux1=poly(1); } else{ // variables in the binomial for (j=1;j<=n;j++){a=int(poly(L[i][1][j])); b=int(poly(L[i][2][j])); if (a!=0){ if (flaglist[j]==0){aux=poly(x(j)^a); aux1=aux1*aux;} else {aux=poly(y(j)^a); aux1=aux1*aux;} } if (b!=0){ if (flaglist[j]==0){aux2=poly(x(j)^b); aux3=aux3*aux2;} else {aux2=poly(y(j)^b); aux3=aux3*aux2;} } } // we add the coefficients if (C[i][1]!=0){aux1=C[i][1]*aux1;} else {aux1=0;} if (C[i][2]!=0){aux3=C[i][2]*aux3;} else {aux3=0;} f=aux1+aux3; J[i]=f; aux1=poly(1); aux3=poly(1); } } return(J); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..4),y(5)),dp; list M=identifyvar(); ideal J=x(1)^2*y(5)^2-x(2)^2*x(3)^2,6*x(4)^2; list L=data(J,2,5); L[1]; // Coefficients L[2]; // Exponents ideal J2=convertdata(L[1],L[2],5,M); J2; } ///////////////////////////////////////////////////////////////////////////// proc lcmofall(int nchart,list mobile) "USAGE: lcmofall(nchart,mobile); nchart integer, mobile list of lists COMPUTE: Compute the lcm of the denominators of the E-orders of all the charts RETURN: an integer given the lcm NOTE: CALL BEFORE salida EXAMPLE: example lcmofall; shows an example " { int i,m,tip,mcmall; intvec numall; for (i=2;i<=nchart+1;i++){ tip=mobile[i][1]; if (tip!=1){numall=numall,tip;} } m=size(numall); if (m==1){mcmall=1;} else{ if (numall[1]==0){numall=numall[2..m];} mcmall=lcm(numall);} return(mcmall); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..2)),dp; ideal J=x(1)^3-x(1)*x(2)^3; list L=Eresol(J); L[4]; // 8 charts, rational exponents L[8][2][2]; // E-orders at the first chart lcmofall(8,L[8]); } ///////////////////////////////////////////////////////////////////////////// proc salida(int idchart,list chart,list mobile,int numson,intvec previousa,int n,int q,int p) "USAGE: salida(idchart,chart,mobile,numson,previousa,n,q,p); idchart, numson, n, q, p integers, chart, mobile, lists, previousa intvec COMPUTE: CONVERT THE OUTPUT OF A CHART IN A RING, WHERE DEFINE A BASIC OBJECT (BO) RETURN: the ring corresponding to the chart EXAMPLE: example salida; shows an example " { int l,i,m,aux,parent,m4,j; intvec Hhist,EOhist,aux7,aux9; list expJ,Coef,BO,blwhist,Eolist,hipercoef,hiperexp; list flag; // chart gives: parent,Y,a,expJ,Coef,flag,Hhist,blwhist,path,hipercoef,hiperexp // mobile gives: tip,oldOlist,oldC,oldt,oldD,oldH,allH,infobo7; NOTE: Eolist=mobile[2]; // we need to define the suitable ring at this chart list Lring=ringlist(basering); def RR2=basering; flag=chart[6]; string newl; for (l=1;l<=n; l++){if (flag[l]==1){newl=string(l); Lring[2][l]="y("+newl+")";} } def RRnew=ring(Lring); setring RRnew; ideal chy=maxideal(1); map fRnew=RR2,chy; list chart=fRnew(chart); list mobile2=fRnew(mobile); flag=chart[6]; // we need to convert expJ and Coef to an ideal expJ=chart[4]; Coef=chart[5]; Hhist=chart[7]; blwhist=chart[8]; // now the ideal will be correctly defined in the ring Rnew ideal J2=convertdata(Coef,expJ,n,flag); // Computations in RRnew //------------------------------------------------------------------------------ // START TO CREATE THE BO corresponding to this chart BO=createBO(J2); // MODIFY BO WITH THE INFORMATION OF THE CHART // BO[1] an ideal, say W_i, defining the ambient space of the i-th chart of the blowing up // If there are hyperbolic equations, we put them here hipercoef=chart[10]; hiperexp=chart[11]; if (size(hipercoef)!=0){ ideal ambJ=convertdata(hipercoef,hiperexp,n,flag); BO[1]=ambJ; } // BO[2] an ideal defining the controlled transform BO[2]=J2; // BO[3] intvec, tupla containing the maximal E-order of BO[2] if (numson==0){BO[3]=1;} // we write 1 if the chart is a final chart else{ Eolist=mobile2[2]; // otherwise, convert the list of E-orders in an intvec m=size(Eolist); aux=int(Eolist[1]*q); EOhist=aux; if (m>1){for (i=2;i<=m;i++){aux=int(Eolist[i]*q); EOhist=EOhist,aux;}} BO[3]=EOhist; } // BO[4] the list of exceptional divisors given by Hhist BO[4]=constructH(Hhist,n,flag); // BO[5] an ideal defining the map K[W] ----> K[Wi] given by blwhist BO[5]=constructblwup(blwhist,n,chy,flag); // BO[6] an intvec, BO[6][j]=1 indicates that =1, i.e. the // strict transform does not meet the j-th exceptional divisor m4=size(BO[4]); ideal auxydeal; ideal Jint; for (j=1;j<=m4;j++){ auxydeal=BO[4][j]+J2; Jint=std(auxydeal); if (size(Jint)==1 and Jint[1]==1){BO[6][j]=1;} else{BO[6][j]=0;} } // BO[7] intvec, the index of the first blown-up object in the resolution process // leading to this object for which the value of b was BO[3] // the subsequent ones are the indices for the Coeff-Objects // of BO[2] used when determining the center // index of last element of H^- in H if (numson!=0){BO[7]=mobile2[8];} // it is always -1 at the final charts // BO[8] a matrix indicating that BO[4][i] meets BO[4][j] by BO[8][i,j]=1 for i < j if (m4>0){ matrix aux8[m4][m4]; BO[8]=aux8; ideal auxydeal2; ideal Jint2; for (i=1;i<=m4;i++){ for (j=i+1;j<=m4;j++){ auxydeal2=BO[4][i]+BO[4][j]; Jint2=std(auxydeal2); if (size(Jint2)==1 and Jint2[1]==1){BO[8][i,j]=0;} else{ for (l=1;l0 if (p>0){ list Lring; Lring=ringlist(RRnew); Lring[1]=p; def auxRnew=ring(Lring); kill Lring; setring auxRnew; ideal chy=maxideal(1); map frnew=RRnew,chy; def BO=frnew(BO); // def chart=frr(chart); def invSat=frnew(invSat); def lastMap=frnew(lastMap); def cent=frnew(cent); def path=frnew(path); } // export everything needed export BO; export(invSat); export lastMap; export path; export cent; if (p==0){return(RRnew);} else{ return(auxRnew);} } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..2)),dp; ideal J=x(1)^2-x(2)^3; list L=Eresol(J); list B=salida(5,L[1][5],L[8][6],2,L[1][3][3],2,1,0); // chart 5 def RR=B[1]; setring RR; BO; "press return to see next example"; ~; ring r = 0,(x(1..2)),dp; ideal J=x(1)^2-x(2)^3; list L=Eresol(J); list B=salida(7,L[1][7],L[8][8],0,L[1][5][3],2,1,0); // chart 7 def RR=B[1]; setring RR; BO; showBO(BO); "press return to see next example"; ~; ring r = 0,(x(1..2)),dp; ideal J=x(1)^3-x(1)*x(2)^3; list L=Eresol(J); // 8 charts, rational exponents list B=salida(1,L[1][1],L[8][2],2,0,2,2,0); // CHART 1 def RR=B[1]; setring RR; BO; } ///////////////////////////////////////////////////////////////////////////// // CONVERT THE OUTPUT OF Eresol IN A LIST OF RINGS, WHERE A BASIC OBJECT (BO) IS DEFINED // IN ORDER TO INTEGRATE THIS LIBRARY INSIDE THE LIBRARY resolve.lib proc genoutput(list chart,list mobile,int nchart,list nsons,int n,int q, int p) "USAGE: genoutput(chart,mobile,nchart,nsons,n,q,p); chart, mobile, nsons lists, nchart, n,q, p integers RETURN: two lists, the first one gives the rings corresponding to the final charts, the second one is the list of all rings corresponding to the affine charts of the resolution process EXAMPLE: example genoutput; shows an example " { int idchart,parent; list auxlist,solvedrings,totalringlist,previousa; list auxlistenp,solvedringsenp,totalringenp; // chart gives: parent,Y,a,expJ,Coef,flag,Hhist,blwhist,path,hipercoef,hiperexp // mobile gives: tip,oldOlist,oldC,oldt,oldD,oldH,allH,infobo7; NOTE: Eolist=mobile[2]; idchart=1; // first loop, construct list previousa while (idchart<=nchart) { if (idchart==1){previousa[1]=chart[2][3];} else { // if there are no sons, the next center is nothing if (nsons[idchart]==0){previousa[idchart]=0;} // always fill the parent parent=chart[idchart][1]; previousa[parent]=chart[idchart][3]; } idchart=idchart+1; } // HERE BEGIN THE LOOP idchart=1; while (idchart<=nchart) { def auxexit=salida(idchart,chart[idchart],mobile[idchart+1],nsons[idchart],previousa[idchart],n,q,p); if (p>0) { // we need the computations in char 0 too def auxexitenp=salida(idchart,chart[idchart],mobile[idchart+1],nsons[idchart],previousa[idchart],n,q,0); } else{def auxexitenp=auxexit;} // we add the ring to the list of all rings auxlist[1]=auxexit; totalringlist=totalringlist+auxlist; auxlistenp[1]=auxexitenp; totalringenp=totalringenp+auxlistenp; // if the chart has no sons, add it to the list of final charts if (nsons[idchart]==0) { solvedrings=solvedrings+auxlist; solvedringsenp=solvedringsenp+auxlistenp; } auxlist=list(); auxlistenp=list(); kill auxexit; kill auxexitenp; idchart=idchart+1; } // EXIT WHILE return(solvedrings,totalringlist,solvedringsenp,totalringenp); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..2)),dp; ideal J=x(1)^3-x(1)*x(2)^3; list L=Eresol(J); // 8 charts, rational exponents list B=genoutput(L[1],L[8],L[4],L[6],2,2,0); // generates the output presentTree(B); list iden0=collectDiv(B); ResTree(B,iden0[1]); // generates the resolution tree // Use presentTree(B); to see the final charts // To see the tree type in another shell // dot -Tjpg ResTree.dot -o ResTree.jpg // /usr/bin/X11/xv ResTree.jpg } ///////////////////////////////////////////////////////////////////// proc computemcm(list Eolist) "USAGE: computemcm(Eolist); Eolist list RETURN: an integer, the least common multiple of the denominators of the E-orders NOTE: Make the same as lcmofall but for one chart. NECESSARY BECAUSE THE E-ORDERS ARE OF TYPE NUMBER!! EXAMPLE: example computemcm; shows an example " { int m,i,aux,mcmchart; intvec num; m=size(Eolist); if (m==1){mcmchart=int(denominator(Eolist[1])); return(mcmchart);} if (m>1) { num=int(denominator(Eolist[1])); for (i=2;i<=m;i++) {aux=int(denominator(Eolist[i])); num=num,aux; } } mcmchart=lcm(num); return(mcmchart); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..2)),dp; ideal J=x(1)^3-x(1)*x(2)^3; list L=Eresol(J); // 8 charts, rational exponents L[8][2][2]; // maximal E-order at the first chart computemcm(L[8][2][2]); } ///////////////////////////////////////////////////////////////////// proc constructH(intvec Hhist,int n,list flag) "USAGE: constructH(Hhist,n,flag); Hhist intvec, n integer, flag list RETURN: the list of exceptional divisors accumulated at this chart EXAMPLE: example constructH; shows an example " { int i,j,m,l; list exceplist; ideal aux; m=size(Hhist); if (Hhist[1]==0 and m>1) { Hhist=Hhist[2..m]; m=m-1; for (i=1;i<=m;i++) { l=Hhist[i]; if (flag[l]==0){aux=ideal(poly(x(l))); } else {aux=ideal(poly(y(l))); } exceplist[i]=aux; } // eliminate repeated variables for (i=1;i<=m;i++) { for (j=1;j<=m;j++) { if (Hhist[i]==Hhist[j] and i!=j) { if (ij){exceplist[j]=ideal(1);} } } } } else {exceplist=list();} // else {exceplist=list(ideal(0));} // IF IT FAILS USE THIS return(exceplist); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; list flag=identifyvar(); ideal J=x(1)^4*x(2)^2, x(1)^2+x(3)^3; list L=Eresol(J); // 7 charts // history of the exceptional divisors at the 7-th chart L[1][7][7]; // blow ups at x(3)-th, x(1)-th and x(1)-th charts constructH(L[1][7][7],3,flag); } ///////////////////////////////////////////////////////////////////// proc constructblwup(list blwhist,int n,ideal chy,list flag) "USAGE: constructblwup(blwhist,n,chy,flag); blwhist, flag lists, n integer, chy ideal RETURN: the ideal defining the map K[W] --> K[Wi], which gives the composition map of all the blowing up leading to this chart NOTE: NECESSARY START WITH COLUMNS EXAMPLE: example constructblwup; shows an example " { int i,j,m,m2; poly aux2; m=size(blwhist[1]); for (j=1;j<=m;j++) { for (i=1;i<=n;i++) { m2=blwhist[i][j]; // If m2!=0 this variable changes. First decide if the variable to multiply is invertible or not if (m2!=0) { if (flag[m2]==0){aux2=poly(x(m2));} else {aux2=poly(y(m2));} // And then substitute this variable for the corresponding product in the whole ideal if (flag[i]==0){chy=subst(chy,x(i),x(i)*aux2);} else {chy=subst(chy,y(i),y(i)*aux2);} } } } return(chy); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; list flag=identifyvar(); ideal chy=maxideal(1); ideal J=x(1)^4*x(2)^2, x(1)^2+x(3)^3; list L=Eresol(J); // 7 charts // history of the blow ups at the 7-th chart, center {x(1)=x(3)=0} every time L[1][7][8]; // blow ups at x(3)-th, x(1)-th and x(1)-th charts constructblwup(L[1][7][8],3,chy,flag); } ///////////////////////////////////////////////////////////////////// proc constructlastblwup(list blwhist,int n,ideal chy,list flag) "USAGE: constructlastblwup(blwhist,n,chy,flag); blwhist, flag lists, n integer, chy ideal RETURN: the ideal defining the last blow up NOTE: NECESSARY START WITH COLUMNS EXAMPLE: example constructlastblwup; shows an example " { int i,j,m,m2; poly aux2; m=size(blwhist[1]); if (m>0) { for (i=1;i<=n;i++){ m2=blwhist[i][m]; // If m2!=0 this variable changes. First decide if the variable to multiply is invertible or not if (m2!=0) { if (flag[m2]==0){aux2=poly(x(m2));} else {aux2=poly(y(m2));} // And then substitute this variable for the corresponding product in the whole ideal if (flag[i]==0){chy=subst(chy,x(i),x(i)*aux2);} else {chy=subst(chy,y(i),y(i)*aux2);} } } } return(chy); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; list flag=identifyvar(); ideal chy=maxideal(1); ideal J=x(1)^4*x(2)^2, x(1)^2+x(3)^3; list L=Eresol(J); // 7 charts // history of the blow ups at the 7-th chart, center {x(1)=x(3)=0} every time L[1][7][8]; // blow ups at x(3)-th, x(1)-th and x(1)-th charts constructlastblwup(L[1][7][8],3,chy,flag); } ///////////////////////////////////////////////////////////////////// proc tradtoideal(intvec a,ideal J2,list flag) "USAGE: tradtoideal(a,J2,flag); a intvec, J2 ideal, flag list COMPUTE: traslate to an ideal the intvec defining the center RETURN: the ideal of the center, given by the intvec a, or J2 if a=0 EXAMPLE: example tradtoideal; shows an example " { int i,m; ideal acenter,aux2; if (a==0) {acenter=J2;} else { m=size(a); for (i=1;i<=m;i++) { if (flag[a[i]]==0){aux2=poly(x(a[i]));} else {aux2=poly(y(a[i]));} acenter=acenter+aux2; } } return(acenter); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; list flag=identifyvar(); ideal J=x(1)^4*x(2)^2, x(1)^2+x(3)^3; intvec a=1,3; // first center of blowing up tradtoideal(a,J,flag); } ////////////////////////////////////////////////////////////////////////////////////// // OPERATIONS WITH LISTS ////////////////////////////////////////////////////////////////////////////////////// proc iniD(int n) "USAGE: iniD(n); n integer RETURN: list of lists of zeros of size n EXAMPLE: example iniD; shows an example " {int i,j; list D,auxD; for (j=1;j<=n; j++) {auxD[j]=0;} for (i=1;i<=n; i++) {D[i]=auxD;} return(D); } example {"EXAMPLE:"; echo = 2; iniD(3); } ///////////////////////////////////////////////////////// proc sumlist(list L1,list L2) "USAGE: sumlist(L1,L2); L1,L2 lists, (size(L1)==size(L2)) RETURN: a list, sum of L1 and L2 EXAMPLE: example sumlist; shows an example " { int i,k; list sumL; k=size(L1); if (size(L2)!=k) {return("ERROR en sumlist, lists must have the same size");} for (i=1;i<=k;i++) {sumL[i]=L1[i]+L2[i];} return(sumL); } example {"EXAMPLE:"; echo = 2; list L1=1,2,3; list L2=5,9,7; sumlist(L1,L2); } /////////////////////////////////////////////////////// proc reslist(list L1,list L2) "USAGE: reslist(L1,L2); L1,L2 lists, (size(L1)==size(L2)) RETURN: a list, subtraction of L1 and L2 EXAMPLE: example reslist; shows an example " { int i,k; list resL; k=size(L1); if (size(L2)!=k) {return("ERROR en reslist, lists must have the same size");} for (i=1;i<=k;i++) {resL[i]=L1[i]-L2[i];} return(resL); } example {"EXAMPLE:"; echo = 2; list L1=1,2,3; list L2=5,9,7; reslist(L1,L2); } ////////////////////////////////////////////////////// proc multiplylist(list L,number a) "USAGE: multiplylist(L,a); L list, a number RETURN: list of elements of type number, multiplication of L times a EXAMPLE: example multiplylist; shows an example " {int i,k; list newL,bb; number b; k=size(L); for (i=1;i<=k;i++) {b=L[i]*a; bb=b; newL=newL+bb;} return(newL); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; list L=1,2,3; multiplylist(L,1/5); } /////////////////////////////////////////////////////// proc dividelist(list L1,list L2) "USAGE: dividelist(L1,L2); L1,L2 lists RETURN: list of elements of type number, division of L1 by L2 EXAMPLE: example dividelist; shows an example " {int i,k,k1,k2; list LL,bb; number a1,a2,b; k1=size(L1); k2=size(L2); if (k2!=k1) {print("ERROR en dividelist, lists must have the same size");} if (k1<=k2) {k=k1;} else {k=k2;} for (i=1;i<=k;i++) {a1=L1[i]; a2=L2[i]; b=a1/a2; bb=b; LL=LL+bb;} return(LL); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp; list L1=1,2,3; list L2=5,9,7; dividelist(L1,L2); } /////////////////////////////////////////////////////// proc createlist(list L1,list L2) "USAGE: createlist(L1,L2); L1,L2 lists, (size(L1)==size(L2)) RETURN: list of lists of two elements, the first one of L1 and the second of L2 EXAMPLE: example createlist; shows an example " {int i,k; list L,aux; k=size(L1); if (size(L2)!=k) {return("ERROR en createlist, lists must have the same size");} L=list0(k); for (i=1;i<=k;i++) {if (L1[i]!=0) {aux=L1[i],L2[i]; L[i]=aux;} else {L=delete(L,i);}} return(L); } example {"EXAMPLE:"; echo = 2; list L1=1,2,3; list L2=5,9,7; createlist(L1,L2); } /////////////////////////////////////////////////////// static proc list0(int n) "USAGE: list0(n); n integer RETURN: list of n zeros EXAMPLE: example list0; shows an example " {int i; list L0; for (i=1;i<=n;i++) {L0[i]=0;} return(L0); } example {"EXAMPLE:"; echo = 2; list0(4); } //////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/resgraph.lib000066400000000000000000000637041266270727000204640ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version resgraph.lib 4.0.0.0 Jun_2013 "; // $Id: c9ad90e46bae6ab8da94f0274c0d903107549129 $ category="Visualization"; info=" LIBRARY: resgraph.lib Visualization of Resolution Data AUTHOR: A. Fruehbis-Krueger, anne@mathematik.uni-kl.de, NOTE: This library uses the external programs surf, graphviz and imagemagick. @* Input data is assumed to originate from resolve.lib and reszeta.lib PROCEDURES: InterDiv(M[,name]) dual graph of resolution of a surface (uses graphviz,imagemagick) ResTree(L,M[,name]) tree of charts of resolution (uses graphviz,imagemagick) finalCharts(L,...) pictures of final charts of surface (uses surf) "; proc InterDiv(intmat M, list #) "USAGE: InterDiv(M[,name]); @* M = matrix @* name = string ASSUME: - M is first list entry of output of 'intersectionDiv' @* from library reszeta.lib @* - write permission in the current directory or in the @* directory in which the file with name 'name' resides CREATE: file 'name.jpg' containing dual graph of resolution @* if filename is given NOTE: only available on UNIX-type systems and programs @* 'display' (imagemagick package) and 'dot' (Graphviz package) need to @* be in the standard search PATH RETURN: nothing, only generating graphics output in separate window EXAMPLE: not available (for technical reasons) " { "Warning: alpha testing version of this procedure"; int i,j; string tempstr; //--------------------------------------------------------------------------- // build up temporary filename and open file for writing //--------------------------------------------------------------------------- if(size(#)>0) { if((typeof(#[1])=="string") && (goodFilename(#[1]))) { string @filename=#[1]; } else { ERROR("Second argument should specify a WRITABLE file"); } } if(!defined(@filename)) { string @filename=buildFilename("InterDiv.dot"); } link eing=":w "+@filename; //-------------------------------------------------------------------------- // write input for external program dot to file //-------------------------------------------------------------------------- write(eing,"graph G{"); for(i=1;i<=ncols(M);i++) { if(M[i,i]!=-2) { tempstr=string(i)+"[shape=circle,label=\""+string(M[i,i])+"\"];"; } else { tempstr=string(i)+"[shape=point,label=\" \"];"; } write(eing,tempstr); } for(i=1;i<=nrows(M);i++) { for(j=i+1;j<=ncols(M);j++) { if(M[i,j]!=0) { tempstr=string(i) + "--" + string(j) + ";"; write(eing,tempstr); } } } write(eing,"}"); close(eing); //--------------------------------------------------------------------------- // produce graphics output using the programs dot and display //--------------------------------------------------------------------------- string outfile=@filename + ".jpg"; if(!find(outfile,"/")) { //--- display needs fully qualified path to file outfile=system("getenv","PWD") + "/" + outfile; } j=system("sh","dot -Tjpg " + @filename + " -o "+ outfile); j=system("sh","display " + outfile + " &"); //--------------------------------------------------------------------------- // clean up if necessary //--------------------------------------------------------------------------- "Currently showing graphics in separate window"; "Press to continue"; pause(); if((size(#)==0)&&(find(@filename,"/tmp/"))) { //--- do not leave any garbage in the public directories j=system("sh","command rm " + outfile + " " + @filename); } return(); } /////////////////////////////////////////////////////////////////////////////// //static proc goodFilename(string datei) { //--- check whether the specified file datei is writable for us if(!system("sh","touch " + datei + " > /dev/null 2>&1")) { return(1); } else { return(0); } } ////////////////////////////////////////////////////////////////////////////// //static proc buildFilename(string datei) { if(goodFilename(datei)) { return(datei); } if(find(datei,"/")) { ERROR("Specified directory/file is not writable"); } datei="/tmp/" + datei; if(goodFilename(datei)) { return(datei); } //--- not reached ERROR("At least /tmp should be writable"); } /////////////////////////////////////////////////////////////////////////////// proc ResTree(list re, intmat DivMat, list #) "USAGE: ResTree(L,M[,name][,mark]); @* L = list @* M = matrix @* name = string @* mark = intvec ASSUME: - L is the output of 'resolve' from resolve.lib @* - M is first entry of output of 'collectDiv(L);' from reszeta.lib @* - write permission in the current directory or in the @* directory in which the file with name 'name' resides @* - mark intvec of size size(L[2]) @* mark[i]=0 (default) border of box black @* mark[i]=1 border of box red CREATE: file 'name.jpg' containing the tree of charts of L @* if filename is given NOTE: only available on UNIX-type systems and programs @* 'display' (imagemagick package) and 'dot' (Graphviz package) need to @* be in the standard search PATH RETURN: nothing, only generating graphics output in separate window EXAMPLE: not available (for technical reasons) " { //----------------------------------------------------------------------------- // Initialization and definition of the temporary filename //----------------------------------------------------------------------------- int i,j,dimC,jsave; string tempstr; def R=basering; if(size(#)>0) { if(typeof(#[1])=="string") { if(goodFilename(#[1])) { string @filename=#[1]; } else { ERROR("optional argument of type string "+ "should specify a writable file."); } } if(typeof(#[1])=="intvec") { intvec @rot=#[1]; } } if(size(#)>1) { if((typeof(#[2])=="string")&&(!defined(@filename))) { if(goodFilename(#[1])) { string @filename=#[1]; } else { ERROR("optional argument of type string "+ "should specify a writable file."); } } if((typeof(#[2])=="intvec")&&(!defined(@rot))) { intvec @rot=#[2]; } } if(!defined(@filename)) { string @filename=buildFilename("ResTree.dot"); } if(!defined(@rot)) { intvec @rot; @rot[size(re[2])]=0; } link eing=":w "+@filename; //---------------------------------------------------------------------------- // writing the input to the program dot into a file //---------------------------------------------------------------------------- write(eing,"graph G{"); tempstr="1[shape=box,label=\"chart 1\"];"; write(eing,tempstr); for(i=2;i<=size(re[2]);i++) { tempstr=string(i)+"[shape=box,label=\"chart " + string(i) + "\\nE:"+string(simplify(ideal(DivMat[i,1..ncols(DivMat)]),2)) + " \""; if(@rot[i]==1) { tempstr=tempstr + "color=\"red\"];"; } else { tempstr=tempstr + "];"; } write(eing,tempstr); } for(i=2;i<=size(re[2]);i++) { def S=re[2][i]; setring S; j=int(leadcoef(path[1,ncols(path)])); if(j!=jsave) { def T=re[2][j]; setring T; dimC=dim(std(BO[1]+cent)); setring S; kill T; } setring R; kill S; if(j!=jsave) { tempstr=string(j) + "--" + string(i) +"[label=\"d=" + string(dimC) + "\"];"; jsave=j; } else { tempstr=string(j) + "--" + string(i) +";"; } write(eing,tempstr); } write(eing,"}"); close(eing); //--------------------------------------------------------------------------- // Create the graphics output using the programs dot and display //--------------------------------------------------------------------------- string outfile=@filename + ".jpg"; if(!find(outfile,"/")) { //--- display needs fully qualified path to file outfile=system("getenv","PWD") + "/" + outfile; } j=system("sh", "dot -Tjpg " + @filename + " -o "+ outfile); j=system("sh","display " + outfile + "&"); //--------------------------------------------------------------------------- // Clean up public directories if necessary //--------------------------------------------------------------------------- "Currently showing graphics in separate window"; "Press to continue"; pause(); if(find(@filename,"/tmp/")) { //--- do not leave any garbage in the public directories j=system("sh","command rm " + @filename + ".jpg "+ @filename); } return(); } ///////////////////////////////////////////////////////////////////////////// proc finalCharts(list re, list inter, intvec endiv, list #) "USAGE: finalCharts(L1,L2,iv[,name]); @* L1 = list @* L2 = list @* iv = intvec @* name = string ASSUME: - L1 is the output of 'resolve' from resolve.lib @* - L2 is the output of 'intersectionDiv(L1)' from reszeta.lib @* - iv is the first entry of the output of 'abstractR(L1)' @* - write permission in the current directory or in the @* directory in which the file with name 'name' resides CREATE: - new windows in which surf-images of the final charts are presented @* - several '.ras' files in the directory in which 'name' resides NOTE: only available on UNIX-type systems @* external programs 'surf' and 'display' (imagemagick package) need to be @* in the standard search PATH RETURN: nothing, only generating graphics output in separate window EXAMPLE: not available (for technical reasons) " { //----------------------------------------------------------------------------- // Initialization and Sanity Checks //----------------------------------------------------------------------------- int i,j,k,a,b,cnt,whichE,offset,haveDcE8; def R=basering; list endCharts; string fname,tempstr; for(i=1;i<=size(endiv);i++) { if(endiv[i]==1) { endCharts[size(endCharts)+1]=i; //--- Sanity checks for the chart i if(nvars(re[2][i])!=3) { ERROR("This chart is not embedded in 3-dimensional space"); } if(defined(S)){kill S;} def S=re[2][i]; setring S; if(dim(std(BO[1]+BO[2]))!=2) { ERROR("Strict Transform is not a surface"); } if(size(equidim(BO[1]+BO[2]))!=1) { ERROR("Strict Transform has lower dimensional components."); } //--- put the missing information into dcE, if necessary for(k=1;k<=size(dcE);k++) { for(j=1;j<=size(dcE[k]);j++) { if(deg(std(dcE[k][j][1])[1])!=0) { if(size(dcE[k][j][1]) < 8) { setring R; k=prepareDcE(re,inter,endiv); setring S; } haveDcE8=1; break; } } if(haveDcE8!=0) break; } setring R; } } if(!defined(colorlist)) { list colorlist; for(i=1;i<=10;i++) { colorlist[i]="curve_red = "+string((i-1)*25)+"; curve_green = "+ string(255-(i-1)*25)+"; curve_blue = "+ string(((i-1) mod 5)*50)+";"; } } else { "Warning!"; "Using colors specified in variable colorlist. No syntax checks"; "performed on the content of this list."; "If built-in colors should be used, please rename the global"; "object colorlist"; } if(ncols(inter[1])>size(colorlist)) { ERROR("Too many exceptional curves on this surface....."); } if((size(endCharts)>20)&&(size(#)==0)) { ERROR("More than 20 final charts..."); } //----------------------------------------------------------------------------- // Determine the basename of the temporary files //----------------------------------------------------------------------------- if(size(#)>0) { if((typeof(#[1])=="string") && (goodFilename(#[1]))) { string fnamebase=#[1]; } else { ERROR("Second argument should specify a WRITABLE file"); } } if(!defined(@fnamebase)) { string fnamebase=buildFilename("Chart"); } //----------------------------------------------------------------------------- // Go through all final charts and write a separate surf input file for each //----------------------------------------------------------------------------- for(i=1;i<=size(endCharts);i++) { fname=fnamebase + string(endCharts[i]) + ".surf"; if(defined(eing)){kill eing;} link eing=":w "+fname; //--- define surf's root finding algorithm tempstr="root_finder = d_chain_bisection; epsilon = 0.000000001;"; write(eing,tempstr); //--- define image size tempstr="int wid = 480;width = wid; height = wid;"; write(eing,tempstr); //--- define ambient lighting tempstr="ambient=50;"; write(eing,tempstr); //--- define background colour: some shade of gray tempstr="background_red=200; background_green=200; background_blue=200;"; write(eing,tempstr); //--- define surface colour (one side): tempstr="surface_red=22; surface_green=150; surface_blue=255;"; write(eing,tempstr); //--- define surface colour (other side): tempstr="inside_red=255; inside_green=192; inside_blue=0;"; write(eing,tempstr); //--- define scaling factor tempstr="scale_x=0.5; scale_y=0.5; scale_z=0.5;"; write(eing,tempstr); //--- rotate a little bit tempstr="rot_y=0.9013941717697173; rot_x=-0.5556596516994916; rot_z=0.103062920202253447;"; write(eing,tempstr); //---------------------------------------------------------------------------- // change to the chart and extract the equation of the surface // then draw the surface //---------------------------------------------------------------------------- if(defined(S)){kill S;} def S=re[2][endCharts[i]]; setring S; //--- define equation of strict transform (hypersurface of dim 2) ideal drawJ=simplify(mstd(radical(BO[1]+BO[2]))[2],2); if(size(drawJ)>1) { //!!! unnoetig! Da kann man auch surface2,... machen ERROR("Did not find generator of principal ideal " + string(drawJ)); } tempstr="poly f = " + map2Surf(string(drawJ[1])) + ";"; write(eing,tempstr); tempstr="surface = f;draw_surface;"; write(eing,tempstr); //---------------------------------------------------------------------------- // now consider all exceptional curves in this chart separately // and draw them //--------------------------------------------------------------------------- if(!defined(dcE)) { //--- Oups, exceptional curves not yet decomposed in this chart //--- should not happen in practice ERROR("The procedure intersectionDiv has not been used on this tree of charts"); } for(j=1;j<=size(dcE);j++) { //--- Run through all exceptional divisors (in the embedded sense) for(k=1;k<=size(dcE[j]);k++) { //--- Run through all curves corresponding to the current divisor if(deg(std(dcE[j][k][1])[1])==0) { //--- This one is empty - skip it k++; if(k>size(dcE[j])) {break;} continue; } for(a=1;a<=size(inter[3]);a++) { //--- this curve belongs to which (Q-irred.) divisor in global numbering? if(inIVList(intvec(endCharts[i],j,k),inter[3][a])) break; } if(a>size(inter[3])) { //--- curve not found in list ERROR("Inconsistency between data of arguments 1 and 2"); } whichE=a; offset=0; for(a=1;a we ignore the other curves //--- 2) we can only form substrings of named strings: tempstr=dcE[j][k][6]; // give it a name tempstr=tempstr[b+1..tempint-1]; // find correct substring tempstr="poly f" + string(offset+dcE[j][k][8][a])+ "_" + string(b+1) + " = " + map2Surf(plugInNumZero(tempstr,dcE[j][k][7][a])) + ";"; write(eing,tempstr); tempstr="cutsurface" + string(cnt) + " = f" + string(offset+dcE[j][k][8][a]) + "_" +string(b+1) + ";"; write(eing,tempstr); cnt++; } b=tempint; // save end-mark tempint=find(dcE[j][k][6],",",b+1); // next one please } if(!find(dcE[j][k][7][a],"i")) { tempstr=dcE[j][k][6]; // as before, but for last tempstr=tempstr[b+1..size(tempstr)]; // fragment tempstr="poly f" + string(offset+dcE[j][k][8][a])+ "_" + string(b+1) + " = " + map2Surf(plugInNumZero(tempstr,dcE[j][k][7][a])) + ";"; write(eing,tempstr); tempstr="cutsurface" + string(cnt)+ " = f" + string(offset+dcE[j][k][8][a]) + "_" +string(b+1) + ";"; write(eing,tempstr); cnt++; } //--- draw the curve on the surface if(cnt>1) { tempstr=colorlist[offset+dcE[j][k][8][a]]; write(eing,tempstr); write(eing,"cut_with_surface;"); } kill tempint; } } } if(!find(fnamebase,"/")) { //--- display needs fully qualified path to file if(defined(outfile)) {kill outfile;} string outfile=system("getenv","PWD") + "/" + fnamebase; } if(!defined(outfile)) { tempstr="filename = \"" + fnamebase + string(endCharts[i]) + ".ras\";"; } else { tempstr="filename = \"" + outfile + string(endCharts[i]) + ".ras\";"; } write(eing,tempstr); tempstr="color_file_format = sun;"; write(eing,tempstr); tempstr="save_color_image;"; write(eing,tempstr); close(eing); j=system("sh", "surf -n " + fnamebase +string(endCharts[i]) + ".surf"); if(!defined(outfile)) { j=system("sh","display " + fnamebase + string(endCharts[i]) + ".ras &"); } else { j=system("sh","display " + outfile + string(endCharts[i]) + ".ras &"); kill outfile; } "Currently showing graphics for chart "+string(endCharts[i]) +" in separate window"; "Press to continue"; pause(); } return(0); } ////////////////////////////////////////////////////////////////////////////// // static proc plugInNumZero(string f,string num) { int i; string fStr=f; i=find(fStr,"t"); while(i!=0) { fStr = string(fStr[1..i-1]) + "(" + num + ")" + string(fStr[i+1..size(fStr)]); i=find(fStr,"t"); } return(fStr); } ////////////////////////////////////////////////////////////////////////////// // static proc replaceInStr(string alles, string alt, string neu) { int i=find(alles,alt); while(i!=0) { if((i-1)<1) { if(size(alt)==size(alles)) { alles=neu; } else { alles=neu + string(alles[i+size(alt)..size(alles)]); } } else { if(i+size(alt)>size(alles)) { alles=string(alles[1..i-1]) + neu; } else { alles=string(alles[1..i-1]) + neu + string(alles[i+size(alt)..size(alles)]); } } i=find(alles,alt); } return(alles); } ///////////////////////////////////////////////////////////////////////////// // static proc map2Surf(string str) { str=replaceInStr(str,string(var(1)),"x"); str=replaceInStr(str,string(var(2)),"y"); str=replaceInStr(str,string(var(3)),"z"); return(str); } ///////////////////////////////////////////////////////////////////////////// // static proc prepareDcE(list re, list inter, list endCharts) { def R=basering; //---Test whether we are in the irreducible surface case def S=re[2][1]; setring S; BO[2]=BO[2]+BO[1]; // make sure we are living in the smooth W if(dim(std(BO[2]))!=2) { ERROR("The given original object is not a surface"); } if(dim(std(slocus(BO[2])))>0) { ERROR("The given original object has non-isolated singularities."); } setring R; //---------------------------------------------------------------------------- // Compute a non-embedded resolution from the given embedded one by // dropping redundant trailing blow-ups //---------------------------------------------------------------------------- //--- compute non-embedded resolution int ii,j,k,a,b,comPa; list abst=abstractR(re); intvec endiv=abst[1]; intvec deleted=abst[2]; //--- identify the divisors in the various final charts list iden0=collectDiv(re,deleted)[2]; // list of final divisors //---------------------------------------------------------------------------- // For each Q-irred. divisor (specified in inter[3]), run through all // occurrences and identify the different C-components //---------------------------------------------------------------------------- for(ii=1;ii<=size(inter[3]);ii++) { //--- run through all Q-irred. curves, //--- set up the first occurrence for reference if(defined(S)) {kill S;} def S=re[2][inter[3][ii][1][1]]; // inter[3] = list of Q-irred div. // inter[3][ii] = ii-th thereof // inter[3][ii][1] = first occurrence // inter[3][ii][1][1] = corr. chart index setring S; dcE[inter[3][ii][1][2]][inter[3][ii][1][3]][8]= intvec(1..ncols(dcE[inter[3][ii][1][2]][inter[3][ii][1][3]][4])); //--- prepare the ideal of the divisor for mapping to different chart if(defined(idlist1)){kill idlist1;} list idlist1; idlist1[1]=dcE[inter[3][ii][1][2]][inter[3][ii][1][3]][6]; exportto(Top,idlist1); for(j=2;j<=size(inter[3][ii]);j++) { //--- now do the comparison with the other occurrences //--- 1. find a common parent for inter[3][ii][1][1] and inter[3][ii][j][1] if(defined(S)){kill S;} def S=re[2][inter[3][ii][j][1]]; setring S; if(defined(opath)){kill opath;} def opath=imap(re[2][inter[3][ii][1][1]],path); k=1; while(opath[1,k]==path[1,k]) { k++; if((k>ncols(opath))||(k>ncols(path))) break; } comPa=int(leadcoef(opath[1,k-1])); //--- 2. use fetchInTree to transfer the C-components if(defined(str)) {kill str;} if(defined(il)) {kill il;} if(defined(mpi)) {kill mpi;} if(defined(nulli)) {kill nulli;} string str="idlist1"; attrib(str,"algext",imap(re[2][inter[3][ii][1][1]],dcE)[inter[3][ii][1][2]][inter[3][ii][1][3]][5]); list il=fetchInTree(re,inter[3][ii][1][1],comPa,inter[3][ii][j][1],str,iden0,1); list nulli=imap(re[2][inter[3][ii][1][1]],dcE)[inter[3][ii][1][2]][inter[3][ii][1][3]][7]; string mpi=imap(re[2][inter[3][ii][1][1]],dcE)[inter[3][ii][1][2]][inter[3][ii][1][3]][5]; if(mpi!=dcE[inter[3][ii][j][2]][inter[3][ii][j][3]][5]) { ERROR("Problem identifying the appropriate field extension.!"); } if(defined(ringt)){kill ringt;} ring ringt=0,(t),dp; if(defined(St)){kill St;} def St=S+ringt; setring St; if(defined(strId)) {kill strId;} string strId="ideal id1=" + il[1] + ";"; execute(strId); id1=std(id1); strId="ideal idj=" + imap(S,dcE)[inter[3][ii][j][2]][inter[3][ii][j][3]][6] + ";"; execute(strId); idj=std(idj); if(defined(nullj)){kill nullj;} list nullj=imap(S,dcE)[inter[3][ii][1][2]][inter[3][ii][1][3]][7]; if(defined(rcomp)){kill rcomp;} strId="ring rcomp=complex,(" +varstr(basering) +"),(" + ordstr(basering) + ");"; execute(strId); def id1=imap(St,id1); def idj=imap(St,idj); ideal id10,idj0; if(defined(tintvec)){kill tintvec;} intvec tintvec; tintvec[size(nullj)]=0; for(a=1;a<=size(nullj);a++) { if(defined(numa)) {kill numa;} strId="number numa=" + string(nullj[a]) + ";"; execute(strId); idj0=subst(idj,t,numa); for(b=1;b<=size(nulli);b++) { if(defined(numb)) {kill numb;} strId="number numb=" + string(nulli[b]) + ";"; execute(strId); id10=subst(id1,t,numb); attrib(id10,"isSB",1); if(size(reduce(idj0,id10))==0) { tintvec[a]=b; break; } } if(!find(string(tintvec),string(b))) { ~; ERROR("Problem identifying C-components in different charts."); } } setring S; dcE[inter[3][ii][1][2]][inter[3][ii][1][3]][8]=tintvec; } } return(0); } singular-4.0.3+ds/Singular/LIB/resjung.lib000066400000000000000000000553721266270727000203300ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version resjung.lib 4.0.1.0 Nov_2014 "; // $Id: 8a7f52632c2869e127981bdafc45667b1efc800c $ category="Commutative Algebra"; info=" LIBRARY: jung.lib Resolution of surface singularities (Desingularization) Algorithm of Jung AUTHOR: Philipp Renner, philipp_renner@web.de PROCEDURES: jungresolve(J[,is_noeth]) computes a resolution (!not a strong one) of the surface given by the ideal J using Jungs Method, jungnormal(J[,is_noeth]) computes a representation of J such that all it's singularities are of Hirzebruch-Jung type, jungfib(J[,is_noeth]) computes a representation of J such that all it's singularities are quasi-ordinary "; LIB "resolve.lib"; LIB "mregular.lib"; LIB "sing.lib"; LIB "normal.lib"; LIB "primdec.lib"; //----------------------------------------------------------------------------------------- //Main procedure //----------------------------------------------------------------------------------------- proc jungfib(ideal id, list #) "USAGE: jungfib(J[,is_noeth]); @* J = ideal @* j = int ASSUME: J = two dimensional ideal RETURN: a list l of rings l[i] is a ring containing two Ideals: QIdeal and BMap. BMap defines a birational morphism from V(QIdeal)-->V(J), such that V(QIdeal) has only quasi-ordinary singularities. If is_noeth=1 the algorithm assumes J is in noether position with respect to the last two variables. As a default or if is_noeth = 0 the algorithm computes a coordinate change such that J is in noether position. NOTE: since the noether position algorithm is randomized the performance can vary significantly. EXAMPLE: example jungfib; shows an example. " { int noeth = 0; if(size(#) == 0) { #[1]=0; noeth=0; } if(#[1]==1){ noeth=1; } ideal I = id; I = radical(id); def A = basering; int n = nvars(A); if(deg(NF(1,groebner(slocus(id)))) == -1){ list result; ideal QIdeal = I; ideal BMap = maxideal(1); export(QIdeal); export(BMap); result[1] = A; return(result); } if(char(A) <> 0){ERROR("only works for characterisitc 0");} //dummy check if(dim(I)<> 2){ERROR("dimension is unequal 2");} //dummy check //Noether Normalization if(noeth == 0){ if(n==3){ int pos = NoetherP_test(I); if(pos ==0){ ideal noethpos = NoetherPosition(I); map phi = A,noethpos; kill noethpos,pos; } else{ ideal NoetherPos = var(pos); for(int i = 1;i<=3;i++){ if(i<>pos){ NoetherPos = NoetherPos + var(i); } } map phi = A,NoetherPos; kill i,pos,NoetherPos; } } else{ map phi = A,NoetherPosition(I); } ideal NoetherN = ideal(phi(I)); //image of id under the NoetherN coordinate change } else{ ideal NoetherN = I; map phi = A,maxideal(1); } kill I; //Critical Locus def C2 = branchlocus(NoetherN); setring C2; //dim of critical locus is 0 then the normalization is an resolution if(dim(clocus) == 0){ setring A; list nor = normal(NoetherN); list result; int sizeofnor = size(nor[1]); for(int i = 1;i<=sizeofnor;i++){ def R = nor[1][i]; setring R; ideal QIdeal = norid; ideal BMap = BMap; export(QIdeal); export(BMap); result[size(result)+1] = R; kill R; setring A; } kill sizeofnor; print("This is a resolution."); return(result); } //dim of critical locus is 1, so compute embedded resolution of the discriminant curve list embresolvee = embresolve(clocus); //build the fibreproduct setring A; list fibreP = buildFP(embresolvee,NoetherN,phi); //a list of lists, where fibreP[i] contains the information conserning //the i-th chart of the fibrepoduct //fibreP[i] is the ring; QIdeal the quotientideal; BMap is the map from A return(fibreP); } example{ "EXAMPLE:";echo = 2; //Computing a resolution of singularities of the variety z2-x3-y3 ring r = 0,(x,y,z),dp; ideal I = z2-x3-y3; //The ideal is in noether position list l = jungfib(I,1); def R1 = l[1]; def R2 = l[2]; setring R1; QIdeal; BMap; setring R2; QIdeal; BMap; } proc jungnormal(ideal id,list #) "USAGE: jungnormal(ideal J[,is_noeth]); @* J = ideal @* i = int ASSUME: J = two dimensional ideal RETURN: a list l of rings l[i] is a ring containing two Ideals: QIdeal and BMap. BMap defines a birational morphism from V(QIdeal)-->V(J), such that V(QIdeal) has only singularities of Hizebuch-Jung type. If is_noeth=1 the algorithm assumes J is in noether position with respect to the last two variables. As a default or if is_noeth = 0 the algorithm computes a coordinate change such that J is in noether position. NOTE: since the noether position algorithm is randomized the performance can vary significantly. EXAMPLE: example jungnormal; gives an example. " { int noeth = 0; if(size(#) == 0) { #[1]=0; noeth=0; } if(#[1]==1){ noeth=1; } def A = basering; list fibreP = jungfib(id,noeth); list result; for(int i =1;i<=size(fibreP);i++){ def R1 = fibreP[i]; setring R1; map f1 = A,BMap; list nor = normal(QIdeal); int sizeofnor = size(nor[1]); for(int j = 1;j<=sizeofnor;j++){ def Ri2 = nor[1][j]; setring Ri2; map f2 = R1,normap; ideal BMap = ideal(f2(f1)); ideal QIdeal = norid; export(BMap); export(QIdeal); result[size(result)+1] = Ri2; kill Ri2,f2; setring R1; } kill j,sizeofnor,R1; } return(result); } example{ "EXAMPLE:";echo = 2; //Computing a resolution of singularities of the variety z2-x3-y3 ring r = 0,(x,y,z),dp; ideal I = z2-x3-y3; //The ideal is in noether position list l = jungnormal(I,1); def R1 = l[1]; def R2 = l[2]; setring R1; QIdeal; BMap; setring R2; QIdeal; BMap; } proc jungresolve(ideal id,list #) "USAGE: jungresolve(ideal J[,is_noeth]); @* J = ideal @* i = int ASSUME: J = two dimensional ideal RETURN: a list l of rings l[i] is a ring containing two Ideals: QIdeal and BMap. BMap defines a birational morphism from V(QIdeal)-->V(J), such that V(QIdeal) is smooth. For this the algorithm computes first with jungnormal a representation of V(J) with Hirzebruch-Jung singularities and then it uses Villamayor's algorithm to resolve these singularities If is_noeth=1 the algorithm assumes J is in noether position with respect to the last two variables. As a default or if is_noeth = 0 the algorithm computes a coordinate change such that J is in noether position. NOTE: since the noether position algorithm is randomized the performance can vary significantly. EXAMPLE: example jungresolve; shows an example. " { int noeth = 0; if(size(#) == 0) { #[1]=0; noeth=0; } if(#[1]==1){ noeth=1; } def A = basering; list result; list nor = jungnormal(id,noeth); for(int i = 1;i<=size(nor);i++){ if(defined(R)==voice){kill R;} def R3 = nor[i]; setring R3; def R = changeord(list(list("dp",1:nvars(basering)))); setring R; ideal QIdeal = imap(R3,QIdeal); ideal BMap = imap(R3,BMap); map f = A,BMap; if(QIdeal <> 0){ list res = resolve(QIdeal); for(int j =1;j<=size(res[1]);j++){ def R2 = res[1][j]; setring R2; if(defined(QIdeal)==voice){kill QIdeal;} if(defined(BMap)==voice){kill BMap;} if(BO[1]<>0){ideal QIdeal = BO[1]+BO[2];} else{ideal QIdeal = BO[2];} map g = R,BO[5]; ideal BMap = ideal(g(f)); export(QIdeal); export(BMap); result[size(result)+1] = R2; kill R2; } kill j,res; } else{ result[size(result)+1] = nor[i]; } setring A; kill R,R3; } return(result); } example{ "EXAMPLE:";echo = 2; //Computing a resolution of singularities of the variety z2-x3-y3 ring r = 0,(x,y,z),dp; ideal I = z2-x3-y3; //The ideal is in noether position list l = jungresolve(I,1); def R1 = l[1]; def R2 = l[2]; setring R1; QIdeal; BMap; setring R2; QIdeal; BMap; } //--------------------------------------------------------------------------------------- //Critical locus for the Weierstrass map induced by the noether normalization //--------------------------------------------------------------------------------------- static proc branchlocus(ideal id) { //"USAGE: branchlocus(ideal J); // J = ideal //ASSUME: J = two dimensional ideal in noether position with respect of // the last two variables //RETURN: A ring containing the ideal clocus respresenting the criticallocus // of the projection V(J)-->C^2 on the last two coordinates //EXAMPLE: none" def A = basering; int n = nvars(A); list l = equidim(id); int k = size(l); ideal LastTwo = var(n-1),var(n); ideal lowdim = 1; //the components of id with dimension smaller 2 if(k>1){ for(int j=1;ji){ v[j]=1; } else{ v[j]=0; } } v[size(v)+1]=0; v[size(v)+1]=0; list ringl = ringlist(A); list l; l[1] = "a"; l[2] = v; list ll = insert(ringl[3],l); ringl[3]=ll; kill l,ll; def R = ring(ringl); //now x_j > x_i > x_n-1 > x_n forall j <> i,n-1,n setring R; ideal J = groebner(fetch(A,I));//this eliminates the variables setring A; ideal J = fetch(R,J); attrib(J,"isPrincipal",0); if(size(J)==1){ attrib(J,"isPrincipal",1); } int index = 1; if(attrib(J,"isPrincipal")==0){ setring R; for(int j = 1;j<=size(J);j++){//determines the monic polynomial in var(i) with coefficents in C2 intvec w = leadexp(J[j]); attrib(w,"isMonic",1); for(int k = 1;k<=size(w);k++){ if(w[k] <> 0 && k <> i){ attrib(w,"isMonic",0); break; } } //kill k; if(attrib(w,"isMonic")==1){ index = j; break; } kill w; } kill j; setring A; } product = product*resultant(J[index],diff(J[index],var(i)),var(i)); //Product of the discriminants, which lies in C2 kill index,J,v; } ring C2 = 0,(var(n-1),var(n)),dp; setring C2; ideal clocus= imap(A,product); //the critical locus is contained in this ideal I = preimage(A,LastTwo,lowdim); clocus= radical(intersect(clocus,I)); //radical is necessary since the resultant is in gerneral not reduced export(clocus); return(C2); } //----------------------------------------------------------------------------------------- //Build the fibre product of the embedded resolution and the coordinate ring of the variety //----------------------------------------------------------------------------------------- static proc buildFP(list embresolve,ideal NoetherN, map phi){ def A = basering; list fibreP; int n = nvars(A); for(int i=1;i<=size(embresolve);i++){ def R = embresolve[i]; setring R; list temp = ringlist(A); //data for the new ring which is, if A=K[x_1,..,x_n] and //R=K[y_1,..,y_m], K[x_1,..,x_n-2,y_1,..,y_m] for(int j = 1; j<= nvars(R);j++){ string st = string(var(j)); temp[2][n-2+j] = st; kill st; } temp[4] = BO[1]; ideal J = BO[5]; //ideal of the resolution map export(J); int m = size(J); def R2 = ring(temp); kill temp; setring R2; ideal Temp=0; //defines map from R to R2 which is the inclusion for(int k=n-1;k-1){ list primdecSL = primdecGTZ(Sl); for(int h =1;h<=size(primdecSL);h++){ attrib(primdecSL[h],"isRational",1); } kill h; if(!defined(index)){int index = 1;} if(defined(blowup)){kill blowup;} list blowup = blowUpBO(BO,primdecSL[index][2],3); //if it has a rational singularity blow it up else choose //some arbitary singular point if(attrib(primdecSL[1],"isRational")==0){ //if we blow up a non rational singularity the exeptional divisors //are reduzible so we need to separate them for(int k=1;k<=size(blowup);k++){ def R2=blowup[k]; setring R2; list L; for(int l = 1;l<=size(BO[4]);l++){ list primdecED=primdecGTZ(BO[4][l]); L = L + primdecED; kill primdecED; } kill l; BO[4] = L; blowup[k]=R2; kill L,R2; } kill k; } kill primdecSL; list hlp; for(int k = 1;k list L; intvec v = 1,1,1; L[1] = "lp"; L[2] = v; kill v; poly f = id[1]; int j = 0; for(int i = 1;i<=3;i++) { setring A; list l = ringA; //change ordering to lp and var(i)>var(j) j<>i list vari = ringA[2]; string h = vari[1]; vari[1] = vari[i]; vari[i] = h; l[2] = vari; kill h,vari; l[3][1] = L; def R = ring(l); kill l; setring R; ideal I = imap(A,id); if(defined(v)){kill v;} intvec v = leadexp(I[1]); attrib(v,"isMonic",1); //if(defined(k)==voice){kill k;} for(int k = 2;k<=3;k++) { //checks whether f is monic in var(i) if(v[k] <> 0 || v[1] == 0) { attrib(v,"isMonic",0); j++; break; } } kill k; if(attrib(v,"isMonic")==1) { index = i; return(index); } kill R; } if(j == 3){ return(0); } } else{ //not yet a test for more variables return(index); } } ////copied from resolve.lib///////////////// static proc normalCrossing(ideal J,list E,ideal V) "Internal procedure - no help and no example available " { int i,d,j; int n=nvars(basering); list E1,E2; ideal K,M,Estd; intvec v,w; for(i=1;i<=size(E);i++) { Estd=std(E[i]+J); if(deg(Estd[1])>0) { E1[size(E1)+1]=Estd; } } E=E1; for(i=1;i<=size(E);i++) { v=i; E1[i]=list(E[i],v); } list ll; int re=1; while((size(E1)>0)&&(re==1)) { K=E1[1][1]; v=E1[1][2]; attrib(K,"isSB",1); E1=delete(E1,1); d=n-dim(K); M=minor(jacob(K),d)+K; if(deg(std(M+V)[1])>0) { re=0; break; } for(i=1;i<=size(E);i++) { for(j=1;j<=size(v);j++){if(v[j]==i){break;}} if(j<=size(v)){if(v[j]==i){i++;continue;}} Estd=std(K+E[i]); w=v; if(deg(Estd[1])==0){i++;continue;} if(d==n-dim(Estd)) { if(deg(std(Estd+V)[1])>0) { re=0; break; } } w[size(w)+1]=i; E2[size(E2)+1]=list(Estd,w); } if(size(E2)>0) { if(size(E1)>0) { E1[size(E1)+1..size(E1)+size(E2)]=E2[1..size(E2)]; } else { E1=E2; } } kill E2; list E2; } return(re); } singular-4.0.3+ds/Singular/LIB/resolve.lib000066400000000000000000004153501266270727000203260ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version resolve.lib 4.0.0.0 Jun_2013 "; // $Id: 222bafc26ef1f3556e7fe8a3aa0467690ae8b3a3 $ category="Algebraic Geometry"; info=" LIBRARY: resolve.lib Resolution of singularities (Desingularization) Algorithm of Villamayor AUTHORS: A. Fruehbis-Krueger, anne@mathematik.uni-kl.de, @* G. Pfister, pfister@mathematik.uni-kl.de REFERENCES: [1] J.Kollar: Lectures on Resolution of Singularities, Princeton University Press (2007)@* (contains large overview over various known methods for curves and surfaces as well as@* a detailed description of the approach in the general case)@* [2] A.Bravo, S.Encinas, O.Villamayor: A Simplified Proof of Desingularisation and@* Applications, Rev. Math. Iberoamericana 21 (2005), 349-458@* (description of the algorithmic proof of desingularization in characteristic zero which underlies this implementation)@* [3] A.Fruehbis-Krueger: Computational Aspects of Singularities, in J.-P. Brasselet, J.Damon et al.: Singularities in Geometry and Topology, World Scientific Publishing, 253--327 (2007)@* (chapter 4 contains a detailed discussion on algorithmic desingularization and efficiency aspects thereof) PROCEDURES: blowUp(J,C[,W,E]) computes the blowing up of the variety V(J) (considered as embedded in V(W)) in the (smooth) center V(C), blowUp2(J,C) computes the blowing up of the variety V(J) in the (possibly singular) center V(C) Center(J[,W,E]) computes 'Villamayor'-center for blow up resolve(J) computes the desingularization of the variety V(J) showBO(BO) prints the content of a BO in more human readable form presentTree(L) prints the final charts in more human readable form showDataTypes() prints help text for output data types blowUpBO(BO,C) computes the blowing up of the variety V(BO[1]) in the center V(C). BO is a list (basic object), C is an ideal createBO(J,W,E) creates basic object from input data CenterBO(BO) computes the center for the next blow-up of the given basic object Delta(BO) apply the Delta-operator of [Bravo,Encinas,Villamayor] DeltaList(BO) list of results of Delta^0 to Delta^bmax "; LIB "elim.lib"; LIB "primdec.lib"; LIB "presolve.lib"; LIB "linalg.lib"; LIB "sing.lib"; /////////////////////////////////////////////////////////////////////////////// // Tasks: // 1) optimization of the local case // 2) optimization in Coeff // 3) change invariant to represent coeff=1 case /////////////////////////////////////////////////////////////////////////////// proc showDataTypes() "USAGE: showDataTypes(); RETURN: nothing, only pretty printing of extended version of help text EXAMPLE: none " { " "; "//////////////// Short description of data type BO ///////////////////"; "BO[1] an ideal, say Wi, defining the ambient space of the i-th chart"; " of the blowing up"; "BO[2] an ideal defining the strict transform"; "BO[3] intvec, the first integer b such that in the original object"; " (Delta^b(BO[2]))==1"; " the subsequent integers have the same property for Coeff-Objects"; " of BO[2] used when determining the center"; "BO[4] the list of exceptional divisors"; "BO[5] an ideal defining the map K[W] ----> K[Wi]"; "BO[6] an intvec BO[6][j]=1 indicates that =1, i.e. the"; " strict transform does not meet the j-th exceptional divisor"; "BO[7] intvec,"; " the index of the first blown-up object in the resolution process"; " leading to this object for which the value of b was BO[3]"; " the subsequent ones are the indices for the Coeff-Objects"; " of BO[2] used when determining the center"; "BO[i], i>7: internal data"; " "; pause(); " "; "///////////// Short description of data in a chart ///////////////////"; "All chart data is stored in an object of type ring, the following "; "variables are always present in such a ring:"; "BO: list of type basic object containing the variety, ambient space,"; " exceptional divisors and further data (see previous page)"; "cent: ideal, describing the upcoming center determined by the algorithm"; "path: module (autoconverted to matrix)"; " path[1][i]= (i-1)st chart in resolution history of this chart"; " path[2][i]= index of chart of the blow up leading to i-th chart"; " in resolution history"; "lastMap: ideal, describing the preceding blow up leading to this chart"; " "; pause(); " "; "///////////// Short description of type resolution data //////////////"; "list L containing two lists:"; "L[1]: list of rings, containing the final charts"; "L[2]: list of rings, containing all charts created in the resolution"; " process"; "The most convenient way to view these data is the procedure presentTree()"; "from this library. Alternatively, it can be digested using tools from"; "the libraries reszeta.lib and resgraph.lib"; "//////////////////////////////////////////////////////////////////////"; } /////////////////////////////////////////////////////////////////////////////// proc createBO(ideal J,list #) "USAGE: createBO(J[,W][,E]); @* J,W = ideals @* E = list ASSUME: J = ideal containing W ( W = 0 if not specified) @* E = list of smooth hypersurfaces (e.g. exceptional divisors) RETURN: list BO representing a basic object : BO[1] ideal W, if W has been specified; ideal(0) otherwise BO[2] ideal J BO[3] intvec BO[4] the list E of exceptional divisors if specified; empty list otherwise BO[5] an ideal defining the identity map BO[6] an intvec BO[7] intvec BO[8] a matrix entries 3,5,6,7,8 are initialized appropriately for use of CenterBO and blowUpBO EXAMPLE: example createBO; shows an example " { ideal W; list E; ideal abb=maxideal(1); intvec v; intvec bvec; intvec w=-1; matrix intE; if(size(#)>0) { if(typeof(#[1])=="ideal") { W=#[1]; } if(typeof(#[1])=="list") { E=#[1]; } if(size(#)>1) { if((typeof(#[2])=="list") && (size(E)==0)) { E=#[2]; } if((typeof(#[2])=="ideal") && (size(W)==0)) { W=#[2]; } } } list BO=W,J,bvec,E,abb,v,w,intE; return(BO); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal J=x2-y3; createBO(J,ideal(z)); } /////////////////////////////////////////////////////////////////////////////// proc blowUp(ideal J,ideal C,list #) "USAGE: blowUp(J,C[,W][,E]); W,J,C = ideals, E = list ASSUME: J = ideal containing W ( W = 0 if not specified) @* C = ideal containing J @* E = list of smooth hypersurfaces (e.g. exceptional divisors) NOTE: W the ideal of the ambient space, C the ideal of the center of the blowup and J the ideal of the variety Important difference to blowUp2: - the ambient space V(W) is blown up and V(J) transformed in it @* - V(C) is assumed to be non-singular COMPUTE: the blowing up of W in C, the exceptional locus, the strict transform of J and the blowup map RETURN: list, say l, of size at most size(C), l[i] is the affine ring corresponding to the i-th chart each l[i] contains the ideals - aS, ideal of the blownup ambient space - sT, ideal of the strict transform - eD, ideal of the exceptional divisor - bM, ideal corresponding to the blowup map l[i] also contains a list BO, which can best be viewed with showBO(BO) detailed information on the data type BO can be viewed via the command showDataTypes(); EXAMPLE: example blowUp; shows an example " { def S=basering; ideal W; list E; ideal abb=maxideal(1); intvec v; intvec bvec; intvec w=-1; matrix intE; if(size(#)>0) { if(typeof(#[1])=="ideal") { W=#[1]; } if(typeof(#[1])=="list") { E=#[1]; } if(size(#)>1) { if((typeof(#[2])=="list") && (size(E)==0)) { E=#[2]; } if((typeof(#[2])=="ideal") && (size(W)==0)) { W=#[2]; } } } list BO=W,J,bvec,E,abb,v,w,intE; int locaT; export locaT; list blow=blowUpBO(BO,C,0); kill locaT; int i; for(i=1;i<=size(blow);i++) { def Q=blow[i]; setring Q; ideal aS=BO[1]; ideal sT=BO[2]; ideal eD=BO[4][size(BO[4])]; ideal bM=BO[5]; kill lastMap; kill thisChart; export(aS); export(sT); export(eD); export(bM); blow[i]=Q; setring S; kill Q; } return(blow); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y),dp; ideal J=x2-y3; ideal C=x,y; list blow=blowUp(J,C); def Q=blow[1]; setring Q; aS; sT; eD; bM; } /////////////////////////////////////////////////////////////////////////////// proc blowUp2(ideal J,ideal C) "USAGE: blowUp2(J,C); J,C = ideals, ASSUME: C = ideal containing J NOTE: C the ideal of the center of the blowup and J the ideal of the variety Important differences to blowUp: - V(J) itself is blown up, not the ambient space - C is not assumed to be non-singular COMPUTE: the blowing up of J in C, the exceptional locus and the blow-up map RETURN: list, say l, of size at most size(C), l[i] is the affine ring corresponding to the i-th chart each l[i] contains the ideals - Jnew, ideal of the blownup J - eD, ideal of the new exceptional divisor - bM, ideal corresponding to the blowup map EXAMPLE: example blowUp2; shows an example " { //---------------------------------------------------------------------------- // Initialization and basic sanity checks of the input data //---------------------------------------------------------------------------- int i,j; def S=basering; def laM=maxideal(1); //--- number of generators of C should be as small as possible def mstdC=mstd(C); if(ncols(mstdC[1])0) { ERROR("V(J) does not contain V(C). Exiting."); } //--------------------------------------------------------------------------- // To compute the blowing up, we need to consider // (K[x_1,\dots,x_n]/J)[t*C[1],...,t*C[m]] // which we want to represent as a quotient of K[x_1,...,x_n,y_1,..,y_m] // by an ideal obtained by elimination of the extra variable t. // (in the comments n=nvars(S) and m=ncols(C)) //--------------------------------------------------------------------------- //--- set up rings for the elimination string r1="ring R=("+charstr(basering)+"),(x(1.."+string(nvars(S)); r1=r1+"),y(1.."+string(ncols(C))+")),dp;"; string r1t="ring Rt=("+charstr(basering)+"),(x(1.."+string(nvars(S)); r1t=r1t+"),y(1.."+string(ncols(C))+"),t),(dp,dp(1));"; execute(r1); // ring for describing the transforms execute(r1t); // like r1, but with additional variable t def J=fetch(S,J); def C=fetch(S,C); //--- we need to eliminate t from J,y(1)-t*C[1],...y(m)-t*C[m] ideal elId=J; for(i=1;i<=ncols(C);i++) { elId=elId,y(i)-t*C[i]; } elId=eliminate(elId,t); // ideal describing the transform of J setring R; // get rid of t def elId=fetch(Rt,elId); def E=fetch(S,C); // determine exceptional divisor E=E+elId; def laM0=fetch(S,laM); // the blowup map //----------------------------------------------------------------------------- // The result is now represented in an A^n \times P^{m-1}, hence // involving n+m variables. For further computations we would like // to pass to charts to keep the total number of variables as low as // possible //---------------------------------------------------------------------------- list resList; ideal Jsub; ideal Esub; ideal laM; ideal testId; map phi; list templist; for(i=1;i<=nvars(R)-nvars(S);i++) { //--- first pass elId and E on to the i-th chart Jsub=std(subst(elId,y(i),1)); if(deg(Jsub[1])==0) { //--- transform does not meet this chart ==> ignore it i++; continue; } Esub=std(subst(E,y(i),1)); //--- now get rid of unnecessary variables //--- first by appropriate coordinate changes templist=elimpart(Jsub); if(size(templist[2])>0) { phi=R,templist[5]; Jsub=phi(Jsub); Jsub=simplify(interred(Jsub),2); Esub=phi(Esub); Esub=simplify(interred(Esub),2); laM=phi(laM0); } else { laM=laM0; } //--- then by dropping non-occuring variables testId=Jsub,Esub,laM; templist=findvars(testId); if(size(templist[1])0) { if(typeof(#[1])=="ideal") { W=#[1]; } if(typeof(#[1])=="list") { E=#[1]; } if(size(#)>1) { if((typeof(#[2])=="list") && (size(E)==0)) { E=#[2]; } if((typeof(#[2])=="ideal") && (size(W)==0)) { W=#[2]; } if(size(#)==3){bvec=#[3];} } } list BO=W,J,bvec,E,abb,v,w,intE,intvec(0); if(defined(invSat)){kill invSat;} list invSat=ideal(0),intvec(0); export(invSat); list re=CenterBO(BO); ideal cent=re[1]; return(cent); } example { "EXAMPLE:"; echo = 2; ring R=0,(x,y),dp; ideal J=x2-y3; Center(J); } /////////////////////////////////////////////////////////////////////////////// proc blowUpBO(list BO, ideal C,int e) "USAGE: blowUpBO (BO,C,e); @* BO = basic object, a list: ideal W, @* ideal J, @* intvec b, @* list Ex, @* ideal ab, @* intvec v, @* intvec w, @* matrix M @* C = ideal @* e = integer (0 usual blowing up, 1 deleting extra charts, 2 deleting @* no charts ) ASSUME: R = basering, a polynomial ring, W an ideal of R, @* J = ideal containing W, @* C = ideal containing J COMPUTE: the blowing up of BO[1] in C, the exeptional locus, the strict transform of BO[2] NOTE: blowUpBO may be applied to basic objects in the sense of @* [Bravo, Encinas, Villamayor] in the following referred to as BO and @* to presentations in the sense of [Bierstone, Milman] in the following @* referred to as BM. RETURN: a list l of length at most size(C), l[i] is a ring containing an object BO resp. BM: @* BO[1]=BM[1] an ideal, say Wi, defining the ambient space of the i-th chart of the blowing up @* BO[2]=BM[2] an ideal defining the strict transform @* BO[3] intvec, the first integer b such that in the original object (Delta^b(BO[2]))==1 the subsequent integers have the same property for Coeff-Objects of BO[2] used when determining the center @* BM[3] intvec, BM[3][i] is the assigned multiplicity of BM[2][i] @* BO[4]=BM[4] the list of exceptional divisors @* BO[5]=BM[5] an ideal defining the map K[W] ----> K[Wi] @* BO[6]=BM[6] an intvec BO[6][j]=1 indicates that =1, i.e. the strict transform does not meet the j-th exceptional divisor @* BO[7] intvec, the index of the first blown-up object in the resolution process leading to this object for which the value of b was BO[3] the subsequent ones are the indices for the Coeff-Objects of BO[2] used when determining the center @* BM[7] intvec, BM[7][i] is the index at which the (2i-1)st entry of the invariant first reached its current maximal value @* BO[8]=BM[8] a matrix indicating that BO[4][i] meets BO[4][j] by BO[8][i,j]=1 for i < j @* BO[9] empty @* BM[9] the invariant EXAMPLE: example blowUpBO; shows an example " { //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- def R0=basering; if(!defined(locaT)){int locaT;} if(locaT){poly pp=@p;} intvec v; int shortC=defined(shortcut); int invS=defined(invSat); int eq,hy; int extra,noDel,keepDiv; if(e==1){extra=1;} //---keeps all charts if(e==2){noDel=1;} //---this is only for curves and surfaces //---keeps all charts with relevant informations on the exceptional divisors if(e==3){keepDiv=1;} if( typeof(attrib(BO[2],"isEqui"))=="int" ) { eq=attrib(BO[2],"isEqui"); } if( typeof(attrib(BO[2],"isHy"))=="int" ) { hy=attrib(BO[2],"isHy"); } string newvar; int n=nvars(R0); int i,j,l,m,x,jj,ll,haveCenters,co; //---the center should neither be the whole space nor empty if((size(C)==0)||(deg(C[1])==0)) { list result=R0; return(result); } if(!defined(debugBlowUp)) { int debugBlowUp=0; } //--------------------------------------------------------------------------- // Drop unnecessary variables //--------------------------------------------------------------------------- //---step 1: substitution if(!((keepDiv)||(noDel))) { //!!! in case keepDiv and noDel: //!!! maybe simplify the situation by an appropriate coordinate change //!!! of this kind -- without dropping variables? list L=elimpart(BO[1]); if(size(L[2])!=0) { map psi=R0,L[5]; C=psi(C); BO=psi(BO); } if(size(BO[1])==0) { ideal LL; for(j=1;j<=size(BO[4]);j++) { LL=LL,BO[4][j]; } LL=variables(LL); L=elimpart(BO[2]); if((size(L[2])!=0)&&(size(std(LL+L[2]))==size(L[2])+size(LL))) { map chi=R0,L[5]; C=chi(C); BO=chi(BO); } } //---step 2: dropping non-occurring variables int s=size(C); ideal K=BO[1],BO[2],C; for(j=1;j<=size(BO[4]);j++) { K=K,BO[4][j]; } list N=findvars(K); if(size(N[1]) In BlowUp: After dropping unnecessary variables"; "BO:"; BO; "C:"; C; } //--------------------------------------------------------------------------- // Do the actual blow-up //--------------------------------------------------------------------------- //--- control the names of the variables execute("ring R=("+charstr(R0)+"),(x(1..n)),dp;"); list BO=fetch(R1,BO); ideal C=fetch(R1,C); list Cmstd=mstd(C); C=Cmstd[2]; if(size(Cmstd[1])<=size(Cmstd[2])) { C=Cmstd[1]; } else { C=interred(C); } list result; //--- the blow-up process ideal W =BO[1]; ideal J =BO[2]; intvec bvec =BO[3]; list Ex =BO[4]; ideal abb=BO[5]; intvec wvec=BO[7]; ideal laM=maxideal(1); if((typeof(BO[9])=="intmat")||(typeof(BO[9])=="intvec")) { def @invmat=BO[9]; } if(size(BO)>9) { //--- check whether a previous center had been split into connected components if(size(BO[10])>0) { list knownCenters=BO[10]; haveCenters=1; } } matrix intE=BO[8]; Ex[size(Ex)+1]=var(1); //to have the list depending on R in case BO[4] is empty execute("ring S=("+charstr(R)+"),("+varstr(R)+",y(0..s-1)),dp;"); list resu; list B; execute("ring T=("+charstr(R)+"),("+varstr(R)+",y(0..s-1),t),dp;"); ideal C=imap(R,C); ideal W=imap(R,W); execute("map phi=S,"+varstr(R)+",t*C;") setring S; //--- the ideal describing the blow-up map ideal abb=imap(R,abb); ideal laM0=imap(R,laM); //--- the ideal of the blowing up of the ambient space ideal W=preimage(T,phi,W); //--- the ideal of the exceptional locus ideal E=imap(R,C); list E1=imap(R,Ex); E1[size(E1)]=E; ideal J=imap(R,J)+W; if(haveCenters){list kN=imap(R,knownCenters);} //--- the strict transform of the exceptional divisors for(j=1;j0){intE[j,l]=1;} else {intE[j,l]=0;} } } } } if(debugBlowUp) { "----> In BlowUp: After Blowing-up, before Clean-Up"; "W:"; W; "J:"; J; } //---------------------------------------------------------------------------- // generating and cleaning up the different charts //---------------------------------------------------------------------------- list M; map psi; list E2; ideal K,JJ,laM,LL,MM; n=nvars(S); list N; list Bstd; intvec delCharts,extraCharts; delCharts[s]=0; extraCharts[s]=0; ideal MA=y(0..s-1); list ZRes,ZlaM,ZsLstd; for(i=0;i<=s-1;i++) { if(haveCenters) { B[10]=kN; for(j=1;j<=size(kN);j++) { B[10][j][1]=subst(B[10][j][1],y(i),1); } } B[8]=intE; B[1]=std(subst(W,y(i),1)); if(deg(B[1][1])==0) { //--- subsets of the empty set are not really interesting! delCharts[i+1]=1; ZRes[i+1]=B; ZlaM[i+1]=laM; i++; continue; } Jsub=subst(J,y(i),1); attrib(Jsub,"isEqui",eq); attrib(Jsub,"isHy",hy); B[2]=Jsub; B[3]=bvec; for(j=1;j4) { //--- in this case the singular locus is too complicated sLstd=ideal(0); } JJ=Bstd[2]; attrib(JJ,"isEqui",eq); B[2]=JJ; sLstd=slocusE(B[2]); } m=0; if(deg(std(sLstd+MAtmp)[1])==0) { //--- the singular locus of B[2] is in the union of the remaining charts m=1; for(l=1;l<=size(B[4]);l++) { if(deg(std(B[2]+B[4][l]+MAtmp)[1])!=0) { //--- the exceptional divisor meets B[2] at the locus of MAtmp //--- we continue only if the option extra=1 and we have transversal //--- intersection m=0; break; } } } if(m) { //--- the i-th chart will be marked for deleting because all informations //--- are already contained in the union of the remaining charts delCharts[i+1]=1; } } } if(delCharts[i+1]==0) { MAtmp[i+1]=MA[i+1]; ZsLstd[i+1]=sLstd; } ZRes[i+1]=B; ZlaM[i+1]=laM; } //--------------------------------------------------------------------------- // extra = ignore uninteresting charts even if there is a normal // crosssing intersection in it //--------------------------------------------------------------------------- if(extra) { for(i=0;i<=s-1;i++) { if((delCharts[i+1]==0)&&(extraCharts[i+1])) { MAtmp[i+1]=0; B=ZRes[i+1]; sLstd=ZsLstd[i+1]; m=0; if(deg(std(sLstd+MAtmp)[1])==0) { //--- the singular locus of B[2] is in the union of the remaining charts m=1; for(l=1;l<=size(B[4]);l++) { if(deg(std(B[2]+B[4][l]+MAtmp)[1])!=0) { //--- the exceptional divisor meets B[2] at the locus of MAtmp //--- we continue only if the option extra=1 and we have transversal //--- intersection m=2; if(!transversalTB(B[2],list(B[4][l]),MAtmp)) { m=0;break; } } } } if(m) { if(m==1) { //--- the i-th chart will be marked for deleting because all informations //--- are already contained in the union of the remaining charts delCharts[i+1]=1; } else { //--- the option extra=1 and we have transversal intersection //--- we delete the chart in case of normal crossings if(normalCrossB(B[2],B[4],MAtmp)) { //--- in case of the option extra //--- the i-th chart will be marked for deleting because all informations //--- are already contained in the union of the remaining charts delCharts[i+1]=1; } } } if(delCharts[i+1]==0) { MAtmp[i+1]=MA[i+1]; } } } for(i=0;i<=s-1;i++) { if(!delCharts[i+1]){break;} } if(i==s){delCharts[s]=0;} } for(i=0;i<=s-1;i++) { B=ZRes[i+1]; laM=ZlaM[i+1]; if(noDel){delCharts[i+1]=0;} //---keeps chart if the exceptional divisor is not in any other chart if((delCharts[i+1])&&(keepDiv)) { for(j=1;j<=size(B[4]);j++) { if(deg(std(B[4][j])[1])>0) { x=0; for(l=0;l<=s-1;l++) { if((l!=i)&&(!delCharts[l+1])&&(deg(std(ZRes[l+1][4][j])[1])>0)) { x=1; break; } } if(!x) { delCharts[i+1]=0; //!!!evtl. diese Karten markieren und nicht weiter aufblasen??? break; } } } } //---keeps charts if the intersection of 2 divisors is not in any other chart if((delCharts[i+1])&&(keepDiv)) { for(j=1;j<=size(B[4])-1;j++) { for(l=j+1;l<=size(B[4]);l++) { if(deg(std(B[4][j]+B[4][l])[1])>0) { x=0; for(ll=0;ll<=s-1;ll++) { if((ll!=i)&&(!delCharts[ll+1])) { if(deg(std(ZRes[ll+1][4][j]+ZRes[ll+1][4][l])[1])>0) { x=1; break; } } } if(!x) { delCharts[i+1]=0; break; } } } if(!delCharts[i+1]){break;} } } //---keeps charts if the intersection of 3 divisors is not in any other chart if((delCharts[i+1])&&(keepDiv)) { for(j=1;j<=size(B[4])-2;j++) { for(l=j+1;l<=size(B[4])-1;l++) { for(ll=l+1;ll<=size(B[4]);ll++) { if(deg(std(B[4][j]+B[4][l]+B[4][ll])[1])>0) { x=0; for(jj=0;jj<=s-1;jj++) { if((jj!=i)&&(!delCharts[jj+1])) { if(deg(std(ZRes[jj+1][4][j] +ZRes[jj+1][4][l]+ZRes[jj+1][4][ll])[1])>0) { x=1; break; } } } if(!x) { delCharts[i+1]=0; break; } } } if(!delCharts[i+1]){break;} } if(!delCharts[i+1]){break;} } } if(delCharts[i+1]==0) { //--- try to decrease the number of variables by substitution if((!keepDiv)&&(!noDel)) { list WW=elimpart(B[1]); map phiW=basering,WW[5]; B=phiW(B); laM=phiW(laM); kill WW; kill phiW; if(size(B[1])==0) { LL=0; for(j=1;j<=size(B[4]);j++) { MM=std(B[4][j]); if(deg(MM[1])>0){LL=LL,MM;} } LL=variables(LL); M=elimpart(B[2]); if((size(M[2])!=0)&&(size(std(LL+M[2]))==size(M[2])+size(LL))) { psi=S,M[5]; B=psi(B); laM=psi(laM); } } } //---- interreduce B[1],B[2] and all B[4][j] B[1]=interred(B[1]); B[2]=interred(B[2]); E2=B[4]; for(j=1;j<=size(E2);j++){E2[j]=interred(E2[j]);} B[4]=E2; v=0;v[size(E2)]=0; //--- mark those j for which B[4] does not meet B[2] for(j=1;j<=size(E2);j++) { K=E2[j],B[2]; K=std(K); if(deg(K[1])==0) { v[j]=1; } } B[6]=v; B[7]=wvec; //--- throw away variables which do not occur K=B[1],B[2],B[5]; //Aenderung!!! for(j=1;j<=size(B[4]);j++){K=K,B[4][j];} N=findvars(K); if(size(N[1])0) { tt=sat(tt,BO[4][size(BO[4])])[1]; } if((deg(tt[1])>0)&&(deg(std(tt+BO[2]+BO[1])[1])>0)) { tList[size(tList)+1]= list(tt,BO[10][j][2],BO[10][j][3],BO[10][j][4]); } } BO[10]=tList; kill tList; } //--- marking variables which do not occur in BO[1] and BO[2] //--- and occur in exactly one BO[4][j], which is the hyperplane given by //--- this variable //!!!! not necessarily in exactly one BO[4][j] list N=findvars(BO[1]+BO[2]); if(size(N[1])dim(std(BO[2])))&&(deg(BO[2][1])>0)) { list BOtemp3=BO; BOtemp3[4]=EE; intvec ivtemp3; ivtemp3[size(BOtemp3[4])]=0; BOtemp3[6]=ivtemp3; BOtemp3[7][1]=-1; list iEtemp3=inters_E(BOtemp3); if(iEtemp3[2]>=dim(std(BOtemp3[2]))) { for(l=2;l<=size(vv);l++) { BO[6][vv[l]]=0; } } kill BOtemp3,ivtemp3,iEtemp3; } } list thisChart=ideal(0),i; export thisChart; //---------------------------------------------------------------------------- // export the basic object and append the ring to the list of rings //---------------------------------------------------------------------------- if(debugBlowUp) { "----> In BlowUp: Adding a single chart"; "BO:"; BO; } if(locaT) { map locaPhi=R0,laM; poly @p=locaPhi(pp); export(@p); } ideal lastMap=laM; export lastMap; if(invS){list invSat=imap(R0,invSat);export invSat;} if(defined(@invmat)){BO[9]=@invmat;} if(shortC){list shortcut=imap(R0,shortcut);export(shortcut);} export BO; result[size(result)+1]=R2; setring S; kill R2; } } setring R0; return(result); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y),dp; ideal W; ideal J=x2-y3; intvec b=1; list E; ideal abb=maxideal(1); intvec v; intvec w=-1; matrix M; intvec ma; list BO=W,J,b,E,abb,v,w,M,ma; ideal C=CenterBO(BO)[1]; list blow=blowUpBO(BO,C,0); def Q=blow[1]; setring Q; BO; } ////////////////////////////////////////////////////////////////////////////// static proc slocusE(ideal i) "Internal procedure - no help and no example available " { //--- do slocus in equidimensional case directly -- speed up if(size(i)==0){return(ideal(1));} if( typeof(attrib(i,"isEqui"))=="int" ) { if(attrib(i,"isEqui")==1) { ideal j=std(i); if(deg(j[1])==0){return(j);} int cod = nvars(basering)-dim(j); i = i+minor(jacob(i),cod); return(i); } } return(slocus(i)); } /////////////////////////////////////////////////////////////////////////////// static proc inters_E(list BO) "USAGE: inters_E(BO); @* BO = basic object, a list: ideal W, @* ideal J, @* intvec b, @* list Ex, @* ideal ab, @* intvec v, @* intvec w, @* matrix M ASSUME: R = basering, a polynomial ring, W an ideal of R, @* J = ideal containing W, @* BO in the setting of case 2 of [Bravo,Encinas,Villamayor] @* BO[4]=E, BO[4][1..count]=E^- @* BO[7][1]=count COMPUTE: (W,(P,1),E^+) in the notation of [Bravo,Encinas,Villamayor] RETURN: a list l , l[1]: P = product of ideals I(H_i1)+..+I(H_in) over all n-tuples of indices i1..in from 1..count l[2]: n = maximal number of H_i from E^- meeting J simultaneously l[3]: maximal number of H_i from E meeting J simultaneously EXAMPLE: internal procedure - no example available " { //--------------------------------------------------------------------- // Initialization //--------------------------------------------------------------------- int kk,jj,ii,updated,n,count2,kkdiff; def rb=basering; def W=BO[1]; ideal J=BO[1],BO[2]; int nonnormal; int maxkk=dim(std(J)); int dimJ=maxkk; ideal test2; list merklist1,merklist2; if(size(BO[4])==0) { list retlist=BO[2],n; return(retlist); } def E=BO[4]; intvec stoplist=BO[6]; //--- fill in all known information about exceptional divisors not meeting //--- current chart for(ii=1;ii<=size(E);ii++) { if(deg(std(E[ii])[1])==0) { stoplist[ii]=1; } } int count=BO[7][1]; if(!defined(debug_Inters_E)) { int debug_Inters_E=0; } //--------------------------------------------------------------------- // we only want to look at E^-, not at all of E //--------------------------------------------------------------------- if (count>-1) { if (count>0) { list E_new=E[1..count]; count2=size(E); } else { list E_new; count2=size(E); } } else { list E_new=E; count=size(E_new); count2=count; } //--------------------------------------------------------------------- // combinatorics is expensive in an interpreted language, // we leave it to the kernel by translating it into monomial // ideals in a new ring with variables t(i) //--------------------------------------------------------------------- string rstr="ring rcomb=0,(t(1.." + string(size(E)) + ")),dp;"; execute(rstr); ideal potid,potid2; list monlist,comblist,merkmon; for(kk=1;kk<=count;kk++) { if(stoplist[kk]==0) { //**************************************************************************/ // it does not make sense to intersect twice by the same E_i // ===> reduce by t(i)^2 //**************************************************************************/ potid=potid,t(kk)^2; } else { //**************************************************************************/ // it does not make sense to consider E_i with v[i]==1 ===> reduce by t(i) //**************************************************************************/ potid=potid,t(kk); //**************************************************************************/ // if stoplist[kk]==2 then J and all E_i automatically intersect E_kk // hence we need not test it, but we have to lower maxkk by one //**************************************************************************/ if(stoplist[kk]==2) { maxkk=maxkk-1; kkdiff++; // count these for dimension check later on } } } potid2=std(potid); if(count2>count) { potid=potid,t((count+1)..count2); for(kk=max(1,count);kk<=count2;kk++) { potid2=potid2,t(kk)^2; } } potid=std(potid); potid2=std(potid2); for(kk=1;(((kk<=count)||(kk<=maxkk+1))&&(kk<=count2));kk++) { //------------------------------------------------------------------------- // monlist[kk]=lists of kk entries of E_new, not containing an E_i twice, // not containing an E_i where v[i]==1 //------------------------------------------------------------------------- monlist[kk]=redMax(kk,potid); //*************************************************************************/ // in the case of n<=maxkk we also need to know whether n would still be // below this bound if we considered all of E instead of E_new // ===> merkmon contains previously ignored tuples E_i1,..,E_im //*************************************************************************/ if(kk<=maxkk+1) { merkmon[kk]=redMax(kk,potid2); merkmon[kk]=simplify(reduce(merkmon[kk],std(monlist[kk])),2); } } if(debug_Inters_E) { "----> In Inters_E: the tuples"; "tuples of E^-:"; monlist; "the remaining tuples:"; merkmon; } //------------------------------------------------------------------------- // check whether there is a kk-tuple of E_i intersecting J, // kk running from 1 to count //------------------------------------------------------------------------- for(kk=1;kk<=count;kk++) { if(size(monlist[kk])==0) break; kill comblist; list comblist; //--- transscribe the tuples from monomial notation to intvec notation for(jj=1;jj<=ncols(monlist[kk]);jj++) { comblist[jj]=leadexp(monlist[kk][jj]); } setring rb; updated=0; //------------------------------------------------------------------------ // Do the intersections //------------------------------------------------------------------------ for(jj=1;jj<=size(comblist);jj++) { //--- jj-th tuple from list of tuples of kk E_i test2=J; for(ii=1;ii<=count;ii++) { if(comblist[jj][ii]==1) { test2=test2,E_new[ii]; } } test2=std(test2); //--- check whether this intersection is non-empty and store it accordingly if(deg(test2[1])!=0) { //--- it is non-empty if(updated!=0) { merklist1[size(merklist1)+1]=comblist[jj]; } else { kill merklist1; list merklist1; merklist1[1]=comblist[jj]; updated=1; n=kk; } if(dim(test2)!=maxkk-kk+kkdiff) { nonnormal=1; } } else { //--- it is empty merklist2[size(merklist2)+1]=jj; } } setring rcomb; ideal redid; //--------------------------------------------------------------------- // update monlist and merkmon by the knowledge what intersections are // empty in the kk-th step //--------------------------------------------------------------------- for(jj=1;jj<=size(merklist2);jj++) { redid=redid,monlist[kk][merklist2[jj]]; } for(jj=kk+1;jj<=count;jj++) { monlist[jj]=simplify(reduce(monlist[jj],std(redid)),2); if(jj<=maxkk+1) { merkmon[jj]=simplify(reduce(merkmon[jj],std(redid)),2); } } kill redid; kill merklist2; list merklist2; } if(debug_Inters_E) { "----> In Inters_E: intersections found:"; merklist1; } //--------------------------------------------------------------------- // form the union of the intersections of the appropriate E_i //--------------------------------------------------------------------- setring rb; ideal center,dummy; list centlist; for(kk=1;kk<=size(merklist1);kk++) { for(jj=1;jj<=size(merklist1[kk]);jj++) { if(merklist1[kk][jj]==1) { dummy=dummy,E_new[jj]; } } if(size(center)==0) { center=dummy; centlist[1]=dummy; } else { center=intersect(center,dummy); centlist[size(centlist)+1]=dummy; } dummy=0; } if(debug_Inters_E) { "----> In Inters_E: intersection of E_i"; "maximal number of E_i encountered in:"; center; "the components of this locus:"; centlist; "maximal number of E_i from E^- intersecting simultaneously:",n; if(nonnormal) { "flag nonnormal is set"; } } list retlist=center,n; //------------------------------------------------------------------------- // If n<=maxkk, then test if this is the case for all of E not just E_new // using the pairs indicated by merkmon //------------------------------------------------------------------------- int ntotal=n; if((n<=maxkk)&&(nsize(merkmon)) { setring rb; break; } if(size(merkmon[kk])!=0) { kill comblist; list comblist; //--- transscribe tuples from monomial notation to intvec notation for(jj=1;jj<=size(merkmon[kk]);jj++) { comblist[jj]=leadexp(merkmon[kk][jj]); } setring rb; //--- check jj-th tuple from the list of kk-tuples for(jj=1;jj<=size(comblist);jj++) { test2=J; for(ii=1;ii<=nvars(rcomb);ii++) { if(comblist[jj][ii]==1) { test2=test2,E[ii]; } } test2=std(test2); //--- as soon as we found one we can proceed to the subsequent kk if(deg(test2[1])!=0) { ntotal=kk; if(dim(test2)-kkdiff!=maxkk-kk) { nonnormal=2; break; } } } //--- if we already know that too many E_i intersect simultaneously, //--- we need not proceed any further if(nonnormal) { break; } } else { setring rb; break; } } } //------------------------------------------------------------------------- // update the result accordingly and return it //------------------------------------------------------------------------- if(maxkk put it in the list of candidates if(det(A)!=0) { v=v[2..size(v)]; // first entry is zero for technical reasons w=w[2..size(w)]; // first entry is zero for technical reasons L=inverse_L(A); L[3]=IW; L[4]=v; L[5]=w; re[size(re)+1]=L; } } } //--------------------------------------------------------------------------- // return the result //--------------------------------------------------------------------------- return(re); } ///////////////////////////////////////////////////////////////////////////// static proc indexSet(int a, int b) "Internal procedure - no help and no example available " { //--------------------------------------------------------------------------- // Find all tuples of size b containing pairwise distict elements from a // list of a elements //--------------------------------------------------------------------------- //**************************************************************************/ // Combinatorics is expensive in an interpreted language // ==> shift it into the kernel //**************************************************************************/ def R=basering; list L; ring S=2,x(1..a),dp; ideal I=maxideal(b); int i; ideal J=x(1)^2; for(i=2;i<=a;i++){J=J,x(i)^2;} attrib(J,"isSB",1); I=reduce(I,J); I=simplify(I,2); for(i=1;i<=size(I);i++){L[i]=leadexp(I[i]);} setring R; return(L); } ///////////////////////////////////////////////////////////////////////////// proc DeltaList(list BO) "USAGE: DeltaList (BO); @* BO = basic object, a list: ideal W, @* ideal J, @* intvec b, @* list Ex, @* ideal ab, @* intvec v, @* intvec w, @* matrix M ASSUME: R = basering, a polynomial ring, W an ideal of R, @* J = ideal containing W COMPUTE: Delta-operator iteratively applied to J in the notation of [Bravo,Encinas,Villamayor] RETURN: list l of length ((max w-ord) * b), l[i+1]=Delta^i(J) EXAMPLE: example DeltaList; shows an example " { //---------------------------------------------------------------------------- // Iteratively apply proc Delta //---------------------------------------------------------------------------- int i; list L; ideal C=BO[2]; while(deg(C[1])!=0) { L[size(L)+1]=C; C=Delta(BO); BO[2]=C; } return(L); } example { "EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal W=z^2-x; ideal J=x*y^2+x^3; intvec b=1; list E; ideal abb=maxideal(1); intvec v; intvec w=-1; matrix M; list BO=W,J,b,E,abb,v,w,M; DeltaList(BO); } ///////////////////////////////////////////////////////////////////////////// proc CenterBM(list BM) "USAGE: CenterBM(BM); @* BM = object related to a presentation, a list: ideal W, @* ideal J, @* intvec b, @* list Ex, @* ideal ab, @* intvec v, @* intvec w, @* matrix M ASSUME: R = basering, a polynomial ring, W an ideal of R, @* J = ideal containing W COMPUTE: the center of the next blow-up of BM in the resolution algorithm of [Bierstone, Milman] RETURN: list l, l[1]: ideal describing the center l[2]: intvec w obtained in the process of determining l[1] l[3]: intvec b obtained in the process of determining l[1] l[4]: intmat invmat obtained in the process of determining l[1] EXAMPLE: example CenterBM; shows an example " { //!!! NOCH NICHT IN BETRIEB ERROR("Not implemented yet"); int i,j; intmat tmat[2][1]=0,-1; //--- re=center,E^- indices, b vector, n vector list re=ideal(1),BM[7],BM[3],tmat; ideal J=BM[2]; if(size(J)==0) { re[1]=ideal(0); return(re); } //--- find Delta^(b-1)(J) if(size(reduce(J,std(BM[1])))!=0) { list L=DeltaList(BM); } else { list L; L[1]=J; } if(!defined(debugCenter)) { int debugCenter; } if(debugCenter) { "----> In Center: after DeltaList"; "W"; BM[1]; "J"; BM[2]; "The Delta List:"; L; } int b=size(L); if(b==0) { //--- if J=W, we do not need to do anything //--- returning center=1 marks this chart as completed return(re); } //--------------------------------------------------------------------------- // check whether max ord is constant //--------------------------------------------------------------------------- if((BM[9][2,1]<0)||(BM[9][1,1]>b)) { //--- we are either at the beginning or the invariant has dropped intvec tempvec=size(BM[4]); BM[7]=tempvec; //!!!! nur fuer hyperflaechen!!!!!!!! tempvec=b; BM[3]=tempvec; //!!!! Ende !!!!!!!!!!!! kill tempvec; BM[9][1,1]=b; BM[9][2,1]=1; } //--------------------------------------------------------------------------- // prepare for intersection with E_i //--------------------------------------------------------------------------- ideal C=L[b]; re[2]=BM[7]; re[3]=BM[3]; BM[2]=C; if(debugCenter) { "----> In Center: before intersection with E_i:"; "bmax:",b; "Sing(J,bmax):"; C; "E:"; BO[4]; "list marking a priori known intersection properties:",BO[6]; "index of last element of E^- in E:",BO[7][1]; } list E=inters_E(BM); // !!!!!!!!! Drop Redundant fehlt noch!!!!!!!! //--------------------------------------------------------------------------- // Check whether it is a single point //--------------------------------------------------------------------------- ideal C1=std(ideal(L[b])+E[1]); if(dim(C1)==0) { if(size(E[4])==1) { tmat[1,1]=BM[9][1,1]; tmat[2,1]=BM[9][2,1]; re[4]=tmat; re[1]=radical(C1); return(re); } } if(size(BM[9])>2) { BM[9][1,2]=E[2]; BM[9][2,2]=1; } else { intmat tempInt[2][1]=E[2],1; BM[9]=concatInt(BM[9],tempInt); kill tempInt; } BM[2]=J; list BM1=dropDim(BM); list BMlist,hilfList; ideal hilf; intvec tempvec; if(!attrib(BM1[1],"isSB")){BM1[1]=std(BM1[1]);} for(i=1;i<=size(BM1[4]);i++) { hilf=simplify(reduce(BM1[4][i],BM1[1]),2); if(size(hilf)>1){"Problem with BM1[4]in CenterBM";~;} hilfList[i]=hilf[1]; } for(i=1;i<=size(E[4]);i++) { BMlist[i]=BM1; for(j=size(E[5][i]);j>=1;j--) { if(E[5][i][j]!=0) { BMlist[i][2][size(BMlist[i][2])+1]=hilfList[j]; BMlist[i][3][size(BMlist[i][3])+1]=1; } BMlist[i][4]=delete(BMlist[i][4],j); BMlist[i][6]=deleteInt(BMlist[i][6],j,0); } BMlist[i][7]=deleteInt(BMlist[i][7],1,-1); if(size(BMlist[i][9])>4) { intmat tempInt[2][ncols(BMlist[i][9])]=BMlist[i][9]; intmat tempInt2[2][ncols(BMlist[i][9])-2]= tempInt[1..2,3..ncols(BMlist[i][9])]; BMlist[i][9]=tempInt2; kill tempInt,tempInt2; } else { BMlist[i][9]=tmat; } } kill hilfList;list hilfList; hilfList[1]=CenterTail(BMlist[1],C); intmat maxmat=hilfList[1][9]; intvec maxiv=E[4][1]; int pos=1; for(i=2;i<=size(E[4]);i++) { hilfList[i]=CenterTail(BMlist[i],C); if(invGreater(hilfList[i][4]),maxmat,E[4][i],maxiv) { maxmat=hilfList[i][4]; maxiv=E[4][i]; pos=i; } } re[1]=hilfList[pos][1]; intmat tempint=BM[9]; intmat tempint1[2][2]=tempint[1..2,1..2]; re[4]=concatInt(tempint1,maxmat); re[2]=re[2][1],hilfList[pos][2]; re[3]=b; ~; return(re); } example { "EXAMPLE:"; echo = 2; ring R=0,(x,y),dp; ideal W; ideal J=x2-y3; intvec b=1; list E; ideal abb=maxideal(1); intvec v; intvec w=-1; matrix M; intmat invmat[2][1]=0,-1; list BM=W,J,b,E,abb,v,w,M,invmat; CenterBM(BM); } ///////////////////////////////////////////////////////////////////////////// static proc invGreater(intmat M1, intmat M2, intvec iv1, intvec iv2) { // Auxilliary procedure, BM-algorithm int i; for(i=1;i<=min(ncols(M1),ncols(M2));i++) { if(M1[2,i]==-1) { if(M1[1,i]==0){ERROR("Invariant not set");} if(M2[2,i]!=-1){return(1);} if(M2[1,i]==0){ERROR("Invariant not set");} break; } else { if(M2[2,i]==-1) { if(M2[1,i]==0){ERROR("Invariant not set");} return(0); } if(M1[1,i]*M2[2,i]!= M2[1,i]*M1[2,i]) { return(M1[1,i]*M2[2,i]> M2[1,i]*M1[2,i]); } } } return(iv1>iv2); } ///////////////////////////////////////////////////////////////////////////// proc CenterTail(list BM, ideal C) { //!!! Auxilliary procedure, BM-algorithm //!!!!!!!!Rueckgabe im Zentrumsformat int i,j,bmin; int alpha=lcm(BM[3]); vector w; list re; if(size(BM[2])==0) { re[1]=C+BM[1]; intvec tvec; re[3]=tvec; intmat tmat[2][1]=-1,-1; re[4]=tmat; tvec=size(BM[4]); re[2]=tvec; return(re); } for(i=1;i<=size(BM[3]);i++) { if(BM[2][i]!=0) { w[size(w)+1]=BM[2][i]^(alpha/BM[3][i]); } } module M=w; intvec satex; list satList; for(i=1;i<=size(BM[4]);i++) { satList=sat(M,BM[4][i]); satex[i]=satList[2]; M=satList[1]; } //!!!!Hilfsobjekt G bilden!!!!!!!!!!!!!!!! //!!!!Hilfsobjekt H,codim -1 bilden!!!!!!!!!!!!!!!! //!!!! ???? an welcher stelle????????? list deltaL; list BMtemp=BM; for(i=1;i<=nrows(M[1]);i++) { BMtemp[2]=ideal(M[1][i])+BMtemp[1]; deltaL[i]=DeltaList(BMtemp); if(i==1) { bmin=size(deltaL[i]); } else { bmin=min(size(deltaL[i]),bmin); } } if(bmin==0) { re[1]=C+BM[1]; intvec tvec; re[3]=tvec; if((BM[9][2,1]==-1)||(BM[9][1,1]!=0)) { tvec=size(BM[4]); re[2]=tvec; intmat tmat[2][1]=0,1; re[4]=tmat; } else { re[2]=BM[7]; re[4]=BM[9]; } return(re); } ideal Ctemp=ideal(1); while(deg(Ctemp[1])==0) { Ctemp=C; for(i=1;i<=nrows(M[1]);i++) { Ctemp=Ctemp,deltaL[i][bmin]; } Ctemp=std(Ctemp); bmin--; if(bmin==0){ERROR("empty set");} } //!!!!!!!!!!!!!Invariante ist bmin/alpha // naechster Eintrag s_i wie in CenterBM // dann dropDim .... } ///////////////////////////////////////////////////////////////////////////// static proc deleteInt(intvec v,int i,int ini) { //!!! Should be in kernel of Singular //--- delete i-th entry in intvec v, //--- if necessary reinitializing v with value ini int s=size(v); intvec w; if((i1)){w=v[1..i-1],v[i+1..s];} if(s==1){w=ini;return(w);} if(i==1){w=v[2..s];} if(i==s){w=v[1..s-1];} return(w); } ///////////////////////////////////////////////////////////////////////////// static proc concatInt(intmat A, intmat B) { //!!! Should be in kernel of Singular //--- concatenate two intmats if(nrows(A)!=nrows(B)){ERROR("could not concat, wrong number of rows");} intmat tempmat[nrows(A)][ncols(A)+ncols(B)]; tempmat[1..nrows(A),1..ncols(A)]=A[1..nrows(A),1..ncols(A)]; tempmat[1..nrows(A),ncols(A)+1..ncols(tempmat)]=B[1..nrows(A),1..ncols(B)]; return(tempmat); } ///////////////////////////////////////////////////////////////////////////// proc dropDim(list BM) { ERROR("Not implemented yet"); } ///////////////////////////////////////////////////////////////////////////// proc CenterBO(list BO,list #) "USAGE: CenterBO(BO); @* BO = basic object, a list: ideal W, @* ideal J, @* intvec b, @* list Ex, @* ideal ab, @* intvec v, @* intvec w, @* matrix M ASSUME: R = basering, a polynomial ring, W an ideal of R, @* J = ideal containing W COMPUTE: the center of the next blow-up of BO in the resolution algorithm of [Bravo,Encinas,Villamayor] RETURN: list l, l[1]: ideal describing the center@* l[2]: intvec w obtained in the process of determining l[1]@* l[3]: intvec b obtained in the process of determining l[1]@* l[4]: intvec inv obtained in the process of determining l[1] EXAMPLE: example CenterBO; shows an example " { //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- int i,bo7save; intvec tvec; //--- re=center,E^- indices, b vector, n vector list re=ideal(1),BO[7],BO[3],tvec; ideal J=BO[2]; if(size(J)==0) { re[1]=ideal(0); return(re); } //--- find Delta^(b-1)(J) if(size(reduce(J,std(BO[1])))!=0) { list L=DeltaList(BO); } else { list L; L[1]=J; } if(!defined(debugCenter)) { int debugCenter; } if(debugCenter) { "----> In Center: after DeltaList"; "W"; BO[1]; "J"; BO[2]; "The Delta List:"; L; } int b=size(L); if(b==0) { //--- if J=W, we do not need to do anything //--- returning center=1 marks this chart as completed return(re); } //--------------------------------------------------------------------------- // check whether max w-ord is constant //--------------------------------------------------------------------------- if(b==BO[3][1]) { //--- max w-ord is constant if(BO[7][1]==-1) { //--- first got its value in the previous step ==> initialize BO[7] tvec[1]=size(BO[4])-1; for(i=2;i<=size(BO[7]);i++) { tvec[i]=BO[7][i]; } re[2]=tvec; BO[7]=tvec; } } else { //--- max w-ord changed ==> reset BO[7], correct BO[3] tvec[1]=-1; re[2]=tvec; BO[7]=tvec; tvec[1]=b; BO[3]=tvec; if(defined(invSat)) { invSat[2]=intvec(0); } } re[3]=BO[3]; //--------------------------------------------------------------------------- // reduce from case 2 to case 1 of [Bravo, Encinas, Villamayor] //--------------------------------------------------------------------------- ideal C=L[b]; BO[2]=C; if(debugCenter) { "----> In Center: before intersection with E_i:"; "bmax:",b; "Sing(J,bmax):"; C; "E:"; BO[4]; "list marking a priori known intersection properties:",BO[6]; "index of last element of E^- in E:",BO[7][1]; } //--- is intermediate result in iteration already good? //--- return it to calling proc CenterBO if(size(#)>0) { if(#[1]==2) { re[1]=C; kill tvec; intvec tvec=re[2][1]; re[2]=tvec; kill tvec; intvec tvec=re[3][1]; re[3]=tvec; kill tvec; intvec tvec; re[4]=tvec; return(re); } } //--- do the reduction to case 1 list E=inters_E(BO); //--- if J is smooth and not too many E_i intersect simultaneously, let us //--- try to drop redundant components of the candidate for the center if((b==1)&&(size(E)>3)) { //--- if J is not smooth we do not want to drop any information if((size(E[4])>0) && (dim(std(slocusE(BO[2])))<0)) { //--- BO[2]==J because b==1 //--- DropRedundant is the counterpart to DropCoeff //--- do not leave out one of them separately!!! E=DropRedundant(BO,E); if(size(E)==1) { kill tvec; intvec tvec=re[2][1]; re[2]=tvec; tvec[1]=re[3][1]; re[3]=tvec; tvec[1]=re[4][1]; re[4]=tvec; re[1]=E[1]; return(re); } } } //--- set n correctly if(E[2] set BO[3][2] to zero to make sure that no previous data is used if(defined(tvec)) {kill tvec;} intvec tvec=BO[7][1],-1; BO[7]=tvec; tvec=BO[3][1],0; BO[3]=tvec; if(defined(invSat)) { invSat[2]=intvec(0); } } re[4][1]=E[2]; C=E[1]^b+J; C=mstd(C)[2]; ideal C1=std(ideal(L[b])+E[1]); if(debugCenter) { "----> In Center: reduction of case 2 to case 1"; "Output of inters_E, after dropping redundant components:"; E; "result of intersection with E^-, i.e.(E^-)^b+J:"; C; "candidate for center:"; C1; } //--------------------------------------------------------------------------- // Check whether we have a hypersurface component //--------------------------------------------------------------------------- if(dim(C1)==dim(std(BO[1]))-1) { if((size(reduce(J,C1))==0)&&(size(reduce(C1,std(J)))==0)) { //--- C1 equals J and is of codimension 1 in W re[1]=C1; } else { //--- C1 has a codimension 1 (in W) component re[1]=std(equiRadical(C1)); } kill tvec; intvec tvec=re[2][1]; re[2]=tvec; tvec[1]=re[3][1]; re[3]=tvec; tvec[1]=re[4][1]; re[4]=tvec; //--- is the codimension 1 component a good choice or do we need to reset //--- the information from the previous steps if(transversalT(re[1],BO[4])) { if(size(E)>2) { if(E[3]>E[2]) { if(defined(shortcut)){kill shortcut;} list shortcut=ideal(0),size(BO[4]),BO[7]; export(shortcut); } } return(re); } ERROR("reset in Center, please send the example to the authors."); } //--------------------------------------------------------------------------- // Check whether it is a single point //--------------------------------------------------------------------------- if(dim(C1)==0) { C1=std(radical(C1)); if(vdim(C1)==1) { //--- C1 is one point re[1]=C1; kill tvec; intvec tvec=re[2][1]; re[2]=tvec; kill tvec; intvec tvec=re[3][1]; re[3]=tvec; return(re); } } //--------------------------------------------------------------------------- // Prepare input for forming the Coeff-Ideal //--------------------------------------------------------------------------- BO[2]=C; if(size(BO[2])>5) { BO[2]=mstd(BO[2])[2]; } //--- drop leading entry of BO[3] tvec=BO[3]; if(size(tvec)>1) { tvec=tvec[2..size(tvec)]; BO[3]=tvec; } else { BO[3][1]=0; } tvec=BO[9]; if(size(tvec)>1) { tvec=tvec[2..size(tvec)]; BO[9]=tvec; } else { BO[9][1]=0; } bo7save=BO[7][1]; // original value needed for result if(defined(shortcut)) { if((bo7save!=shortcut[3][1])&&(size(shortcut[3])!=1)) { kill shortcut; } else { shortcut[2]=shortcut[2]-bo7save; tvec=shortcut[3]; if(size(tvec)>1) { tvec=tvec[2..size(tvec)]; shortcut[3]=tvec; } else { shortcut[3]=intvec(shortcut[2]); } } } if(BO[7][1]>-1) { //--- drop E^- and the corresponding information from BO[6] for(i=1;i<=BO[7][1];i++) { BO[4]=delete(BO[4],1); intvec bla1=BO[6]; BO[6]=intvec(bla1[2..size(bla1)]); kill bla1; } //--- drop leading entry of BO[7] tvec=BO[7]; if(size(tvec)>1) { tvec=tvec[2..size(tvec)]; BO[7]=tvec; } else { BO[7][1]=-1; } } else { if(BO[7][1]==-1) { list tplist; BO[4]=tplist; kill tplist; } } if(debugCenter) { "----> In Center: Input to Coeff"; "b:",b; "BO:"; BO; } //--- prepare the third entry of the invariant tuple int invSatSave=invSat[2][1]; tvec=invSat[2]; if(size(tvec)>1) { tvec=tvec[2..size(tvec)]; invSat[2]=tvec; } else { invSat[2][1]=0; } //--------------------------------------------------------------------------- // Form the Coeff-ideal, if possible and useful; otherwise use the previous // candidate for the center //--------------------------------------------------------------------------- list BO1=Coeff(BO,b); if(debugCenter) { "----> In Center: Output of Coeff"; BO1; } //--- Coeff returns int if something went wrong if(typeof(BO1[1])=="int") { if(BO1[1]==0) { //--- Coeff ideal was already resolved re[1]=C1; return(re); } else { //--- no global hypersurface found re=CoverCenter(BO,b,BO1[2]); kill tvec; intvec tvec=invSatSave; for(i=1;i<=size(invSat[2]);i++) { tvec[i+1]=invSat[2][i]; } invSat[2]=tvec; return(re); } } int coeff_invar; ideal Idropped=1; //--- if b=1 drop redundant components of the Coeff-ideal if(b==1) { //--- Counterpart to DropRedundant -- do not leave out one of them separately Idropped=DropCoeff(BO1); // blow-up in these components // is unnecessary } //--- to switch off DropCoeff, set Idropped=1; BO1[2]=sat(BO1[2],Idropped)[1]; if(deg(BO1[2][1])==0) { //--- Coeff ideal is trivial C1=radical(C1); ideal C2=sat(C1,Idropped)[1]; if(deg(std(C2)[1])!=0) { C1=C2; } //Aenderung: Strategie: nur im Notfall ganze except. Divisoren if(deg(std(BO1[2])[1])==0) { list BOtemp=BO; int bo17save=BO1[7][1]; BOtemp[7]=0; BO1=Coeff(BOtemp,b,int(0)); BO1[2]=sat(BO1[2],Idropped)[1]; if(deg(std(BO1[2])[1])==0) { //--- there is really nothing left to do for the Coeff ideal //--- the whole original BO1[2], i.e. Idropped, is the upcoming center re[1]=Idropped; re[2]=intvec(bo7save); re[3]=intvec(b); re[4]=intvec(E[2]); return(re); } if(deg(std(slocus(radical(BO1[2])))[1])==0) { re[1]=BO1[2]; // re[2]=intvec(bo7save,BO1[7][1]); re[2]=intvec(bo7save,bo17save); re[3]=intvec(b,1); re[4]=intvec(E[2],1); invSat[2]=intvec(1,0); return(re); } //!!! effizienter machen??? list pr=primdecGTZ(BO1[2]); ideal Itemp1=1; int aa,bb; for(aa=1;aa<=size(pr);aa++) { if(dim(std(pr[aa][2])) < (dim(std(BO1[1]))-1)) { //--- drop components which are themselves exceptional diviosrs Itemp1=intersect(Itemp1,pr[aa][1]); } } if(deg(std(Itemp1)[1])!=0) { //--- treat the remaining components of the weak Coeff ideal BO1[2]=Itemp1; } BO1[7]=BO[7]; for(aa=1;aa<=size(BO1[4]);aa++) { if(deg(std(BO1[4][aa])[1])==0){aa++;continue;} if(defined(satlist)){kill satlist;} list satlist=sat(BO1[2],BO1[4][aa]+BO1[1]); if(deg(std(satlist[1])[1])==0) { coeff_invar++; if(satlist[2]!=0) { for(bb=1;bb<=satlist[2]-1;bb++) { BO1[2]=quotient(BO1[2],BO1[4][aa]+BO1[1]); } } else { ERROR("J of temporary object had unexpected value; please send this example to the authors."); } } else { BO1[2]=satlist[1]; } } if(deg(std(Itemp1)[1])==0) { re[1]=BO1[2]; re[2]=intvec(bo7save,BO1[7][1]); re[3]=intvec(b,1); re[4]=intvec(E[2],1); invSat[2]=intvec(1,0); return(re); } kill aa,bb; } } if(invSatSave5) { BO1[2]=mstd(BO1[2])[2]; } list templist=CenterBO(BO1,2); //--- only a sophisticated guess of a good center computed by //--- leaving center before intersection with the E_i. //--- whether the guess was good, is stored in 'good'. //--- (this variant saves charts in cases like the Whitney umbrella) list E0,E1; ideal Cstd=std(radical(templist[1])); int good=((deg(std(slocusE(Cstd))[1])==0)&&(dim(std(BO1[2]))<=2)); //if(defined(satlist)){good=0;} if(good) { for(i=1;i<=size(BO[4]);i++) { if((deg(BO[4][i][1])>0)&&(size(reduce(BO[4][i],Cstd))!=0)) { E0[size(E0)+1]=BO[4][i]+Cstd; E1[size(E1)+1]=BO[4][i]; } } good=transversalT(Cstd,E1); if(good) { good=normalCross(E0); } } if(good) { list templist2=CenterBO(BO1,1); if(dim(std(templist2[1]))!=dim(Cstd)) { templist[1]=Cstd; if(defined(shortcut)){kill shortcut;} list shortcut=ideal(0),size(BO1[4]),templist[2]; export(shortcut); } else { templist=templist2; } kill templist2; } else { //--- sophisticated guess was wrong, follow Villamayor's approach kill templist; list templist=CenterBO(BO1,1); } } if((dim(std(templist[1]))==dim(std(BO1[1]))-1) &&(size(templist[4])==1)) { if(templist[4][1]==0) { for(i=1;i<=size(BO1[4]);i++) { if(size(reduce(templist[1],std(BO1[4][i])))==0) { templist[4][1]=1; break; } } } } //!!! subsequent line should be deleted //if(defined(satlist)){templist[3][1]=BO[3][1];} if(debugCenter) { "----> In Center: Iterated Center returned:"; templist; } //-------------------------------------------------------------------------- // set up the result and return it //-------------------------------------------------------------------------- re[1]=templist[1]; kill tvec; intvec tvec; tvec[1]=bo7save; for(i=1;i<=size(templist[2]);i++) { tvec[i+1]=templist[2][i]; } re[2]=tvec; if(defined(shortcut)) { shortcut[2]=shortcut[2]+bo7save; shortcut[3]=tvec; } kill tvec; intvec tvec; tvec[1]=invSatSave; for(i=1;i<=size(invSat[2]);i++) { tvec[i+1]=invSat[2][i]; } invSat[2]=tvec; kill tvec; intvec tvec; tvec[1]=b; for(i=1;i<=size(templist[3]);i++) { tvec[i+1]=templist[3][i]; } re[3]=tvec; kill tvec; intvec tvec; tvec[1]=E[2]; for(i=1;i<=size(templist[4]);i++) { tvec[i+1]=templist[4][i]; } re[4]=tvec; return(re); } example { "EXAMPLE:"; echo = 2; ring R=0,(x,y),dp; ideal W; ideal J=x2-y3; intvec b=1; list E; ideal abb=maxideal(1); intvec v; intvec w=-1; matrix M; list BO=W,J,b,E,abb,v,w,M,v; CenterBO(BO); } ////////////////////////////////////////////////////////////////////////////// static proc CoverCenter(list BO,int b, ideal Jb) { //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- def R=basering; int i,j,k; intvec merk,merk2,maxv,fvec; list L,ceList,re; ceList[1]=ideal(0); poly @p,@f; ideal K,dummy; if(!attrib(BO[2],"isSB")) { BO[2]=std(BO[2]); } for(i=1;i<=size(Jb);i++) { list tempmstd=mstd(slocus(Jb[i])); if(size(tempmstd[1])>size(tempmstd[2])) { dummy=tempmstd[2]; } else { dummy=tempmstd[1]; } kill tempmstd; L[i]=dummy; K=K,dummy; } K=simplify(K,2); //--------------------------------------------------------------------------- // The intersection of the singular loci of the L[i] is empty. // Find a suitable open covering of the affine chart, such that a global // hypersurface can be found in each open set. //--------------------------------------------------------------------------- matrix M=lift(K,ideal(1)); j=1; for(i=1;i<=nrows(M);i++) { if(M[i,1]!=0) { merk[size(merk)+1]=i; fvec[size(merk)]=j; } if((i-k)==size(L[j])) { k=i; j++; } } //-------------------------------------------------------------------------- // Find a candidate for the center in each open set //-------------------------------------------------------------------------- //--- first entry of merk is 0 by construction of merk for(i=2;i<=size(merk);i++) { //--- open set is D(@p) @p=K[merk[i]]; //--- hypersurface is V(@f) @f=Jb[fvec[i]]; execute("ring R1=("+charstr(R)+"),(@y,"+varstr(R)+"),dp;"); poly p=imap(R,@p); poly f=imap(R,@f); list @ce; list BO=imap(R,BO); BO[1]=BO[1]+ideal(@y*p-1); BO[2]=BO[2]+ideal(@y*p-1); for(j=1;j<=size(BO[4]);j++) { BO[4][j]=BO[4][j]+ideal(@y*p-1); } //--- like usual Coeff, but hypersurface is already known list BO1=SpecialCoeff(BO,b,f); //--- special situation in SpecialCoeff are marked by an error code of //--- type int if(typeof(BO1[1])=="int") { if(BO1[1]==0) { //--- Coeff ideal was already resolved @ce[1]=BO[2]; @ce[2]=BO[7]; @ce[3]=BO[3]; } else { if(BO[3]!=0) { //--- intersections with E do not meet conditions ==> reset ERROR("reset in Coeff, please send the example to the autors"); } } } else { //--- now do the recursion as usual @ce=CenterBO(BO1); } //--------------------------------------------------------------------------- // Go back to the whole affine chart and form a suitable union of the // candidates //--------------------------------------------------------------------------- //--- pass from open set to the whole affine chart by taking the closure @ce[1]=eliminate(@ce[1],@y); setring R; ceList[i]=imap(R1,@ce); //--- set up invariant vector and determine maximum value of it if(size(ceList[i][3])==size(ceList[i][4])) { kill merk2,maxv; intvec merk2,maxv; for(j=1;j<=size(ceList[i][3]);j++) { merk2[2*j-1]=ceList[i][3][j]; merk2[2*j]=ceList[i][4][j]; ceList[i][5]=merk2; if(maxv ignore i++; continue; } if(ceList[i][5]==maxv) { if(merk2!=ceList[i][2]) { //--- E^- not of the same size as before resp. initialization if(merk2[1]==-2) { //--- initialization: save size of E^- merk2=ceList[i][2]; re[1]=ceList[i][1]; re[2]=ceList[i][2]; re[3]=ceList[i][3]; re[4]=ceList[i][4]; } else { //--- otherwise ignore i++; continue; } } else { re[1]=intersect(re[1],ceList[i][1]); } } } //-------------------------------------------------------------------------- // Perform last checks and return the result //-------------------------------------------------------------------------- if(size(re)!=4) { //--- oops: already resolved in all open sets re[1]=BO[2]; re[2]=-1; re[3]=0; re[4]=intvec(0); } return(re); } ////////////////////////////////////////////////////////////////////////////// static proc SpecialCoeff(list BO,int b,poly f) { //---------------------------------------------------------------------------- // Coeff with given hypersurface -- no checks of the hypersurface performed //---------------------------------------------------------------------------- int i,ch; int e=int(factorial(b)); ideal C; list L=DeltaList(BO); int d=size(L); //--- set up ideal for(i=0;isize(pr)) { //--- the continue statement does not test the loop condition *sigh* break; } if(deg(std(slocus(pr[i]))[1])!=0) { //--- this component is singular ===> we still need it i++; continue; } Itemp=sat(I,pr[i])[1]; if(deg(std(Itemp+pr[i])[1])!=0) { //--- this component is not disjoint from the other ones ===> we still need it i++; continue; } if(!transversalT(pr[i],BO[4])) { //--- this component does not meet one of the remaining E_i transversally //--- ===> we still need it i++; continue; } if(!normalCross(BO[4],pr[i])) { //--- this component is not normal crossing with the remaining E_i //--- ===> we still need it i++; continue; } if(defined(EE)){kill EE;} list EE; for(j=1;j<=size(BO[4]);j++) { EE[j]=BO[4][j]+pr[i]; } if(!normalCross(EE)) { //--- we do not have a normal crossing situation for this component after all //--- ===> we still need it i++; continue; } Idropped=intersect(Idropped,pr[i]); I=Itemp; } return(Idropped); } ////////////////////////////////////////////////////////////////////////////// static proc DropRedundant(list BO,list E) "Internal procedure - no help and no example available " { //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- int ii,jj,kkdiff,nonnormal,ok; ideal testid,dummy; ideal center; intvec transverse,dontdrop,zerovec; transverse[size(BO[4])]=0; dontdrop[size(E[4])]=0; zerovec[size(E[4])]=0; ideal J=BO[2]; int dimJ=dim(std(BO[2])); list templist; if(size(E)<5) { //--- should not occur return(E); } for(ii=1;ii<=BO[7][1];ii++) { if(BO[6][ii]==2) { kkdiff++; } } int expDim=dimJ-E[2]+kkdiff; if(size(E)==6) { nonnormal=E[6]; } //--------------------------------------------------------------------------- // if dimJ were smaller than E[2], we would not have more than 3 entries in // in the list E // if dimJ is also at least E[3] and nonnormal is 0, we only need to test that // * the intersection is of the expected dimension // * the intersections of the BO[4][i] and J are normal crossing // * the elements of E^+ have no influence (is done below) //--------------------------------------------------------------------------- if((E[3]<=dimJ)&&(!nonnormal)) { ideal bla=E[1]+BO[2]+BO[1]; bla=radical(bla); bla=mstd(bla)[2]; if(dim(std(slocusE(bla)))<0) { if(transversalT(J,BO[4])) { ok=1; if(E[2]==E[3]) { //--- no further intersection with elements from E^+ for(ii=1;ii<=size(E[4]);ii++) { if(dim_slocus(BO[2]+E[4][ii])!=-1) { dontdrop[ii]=1; } } if(dontdrop==zerovec) { list relist; relist[1]=std(J); return(relist); } } } } } //--------------------------------------------------------------------------- // now check whether the E_i actually occurring in the intersections meet // J transversally (one by one) and mark those elements of E[4] where it is // not the case //--------------------------------------------------------------------------- if(!ok) { for(ii=1;ii<=size(E[5]);ii++) { //--- test the ii-th tuple of E[4] resp. its indices E[5] for(jj=1;jj<=size(E[5][ii]);jj++) { //--- if E[5][ii][jj]==1, E_jj is involved in E[4][ii] if(E[5][ii][jj]==1) { //--- transversality not yet determined if(transverse[jj]==0) { templist[1]=BO[4][jj]; if(transversalT(BO[2],templist)) { transverse[jj]=1; } else { transverse[jj]=-1; dontdrop[ii]=1; } } else { //--- already computed transversality if(transverse[jj]<0) { dontdrop[ii]=1; } } } } } } //--------------------------------------------------------------------------- // if one of the non-marked tuples from E^- in E[4] has an intersection // of the expected dimension and does not meet any E_i from E^+ // - except the ones which are met trivially - , it should be // dropped from the list. // it can also be dropped if an intersection occurs and normal crossing has // been checked. //--------------------------------------------------------------------------- for(ii=1;ii<=size(E[4]);ii++) { //--- if E[4][ii] does not have transversal intersections, we cannot drop it if(dontdrop[ii]==1) { ii++; continue; } //--- testing ii-th tuple from E[4] testid=BO[1]+BO[2]+E[4][ii]; if(dim(std(testid))!=expDim) { //--- not expected dimension dontdrop[ii]=1; ii++; continue; } testid=mstd(testid)[2]; if(dim(std(slocusE(testid)))>=0) { //--- not smooth, i.e. more than one component which intersect dontdrop[ii]=1; ii++; continue; } //--- if E^+ is empty, we are done; otherwise check intersections with E^+ if(BO[7][1]!=-1) { if(defined(pluslist)){kill pluslist;} list pluslist; for(jj=BO[7][1]+1;jj<=size(BO[4]);jj++) { dummy=BO[4][jj]+testid; dummy=std(dummy); if(expDim==dim(dummy)) { //--- intersection has wrong dimension dontdrop[ii]=1; break; } pluslist[jj-BO[7][1]]=BO[4][jj]+testid; } if(dontdrop[ii]==1) { ii++; continue; } if(!normalCross(pluslist)) { //--- unfortunately, it is not normal crossing dontdrop[ii]=1; } } } //--------------------------------------------------------------------------- // The returned list should look like the truncated output of inters_E //--------------------------------------------------------------------------- list retlist; for(ii=1;ii<=size(E[4]);ii++) { if(dontdrop[ii]==1) { if(size(center)>0) { center=intersect(center,E[4][ii]); } else { center=E[4][ii]; } } } retlist[1]=center; retlist[2]=E[2]; retlist[3]=E[3]; return(retlist); } ////////////////////////////////////////////////////////////////////////////// static proc transversalT(ideal J, list E,list #) "Internal procedure - no help and no example available " { //---------------------------------------------------------------------------- // check whether J and each element of the list E meet transversally //---------------------------------------------------------------------------- def R=basering; if(size(#)>0) { ideal pp=#[1]; } int i; ideal T,M; ideal Jstd=std(J); ideal Tstd; int d=nvars(basering)-dim(Jstd)+1; // d=n-dim(V(J) \cap hypersurface) for(i=1;i<=size(E);i++) { if(size(reduce(E[i],Jstd))==0) { //--- V(J) is contained in E[i] return(0); } T=J,E[i]; Tstd=std(T); d=nvars(basering)-dim(Tstd); if(deg(Tstd[1])!=0) { //--- intersection is non-empty //!!! abgeklemmt, da es doch in der Praxis vorkommt und korrekt sein kann!!! //!!! wenn ueberhaupt dann -1 zurueckgeben!!! // if((d>=4)&&(size(T)>=10)){return(0);} M=minor(jacob(T),d,Tstd)+T; M=std(M); if(deg(M[1])>0) { //--- intersection is not transversal if(size(#)==0) { return(0); } M=std(radical(M)); if(size(reduce(pp,M))>0){return(0);} } } } //--- passed all tests return(1); } /////////////////////////////////////////////////////////////////////////////// static proc transversalTB(ideal J, list E,ideal V) "Internal procedure - no help and no example available " { //---------------------------------------------------------------------------- // check whether J and each element of the list E meet transversally //---------------------------------------------------------------------------- def R=basering; int i; ideal T,M; ideal Jstd=std(J); ideal Tstd; int d=nvars(basering)-dim(Jstd)+1; // d=n-dim(V(J) \cap hypersurface) for(i=1;i<=size(E);i++) { if(size(reduce(E[i],Jstd))==0) { //--- V(J) is contained in E[i] return(0); } T=J,E[i]; Tstd=std(T); d=nvars(basering)-dim(Tstd); if(deg(Tstd[1])!=0) { //--- intersection is non-empty if((d>=4)&&(size(T)>=10)){return(0);} M=minor(jacob(T),d,Tstd)+T; M=std(M+V); if(deg(M[1])>0) { return(0); } } } //--- passed all tests return(1); } /////////////////////////////////////////////////////////////////////////////// static proc powerI(ideal I,int n,int m) { //--- compute (n!/m)-th power of I, more efficient variant int i; int mon=1; for(i=1;i<=size(I);i++) { if(size(I[i])>1){mon=0;break;} } if(mon) { if(size(reduce(I,std(radical(I[1]))))3)) { int e=int(factorial(n))/m; ideal J=1; poly p=I[1]; I=I[2..size(I)]; ideal K=p^e; for(i=1;i<=e;i++) { J=interred(J*I); K=K,(p^(e-i))*J; } return(K); } for(i=n;i>1;i--) { if(i!=m) { I=I^i; } } return(I); } /////////////////////////////////////////////////////////////////////////////// static proc Coeff(list BO, int b, list #) "USAGE: Coeff (BO); @* BO = basic object, a list: ideal W, @* ideal J, @* intvec b (already truncated for Coeff), @* list Ex (already truncated for Coeff), @* ideal ab, @* intvec v, @* intvec w (already truncated for Coeff), @* matrix M @* b = integer indication bmax(BO) ASSUME: R = basering, a polynomial ring, W an ideal of R, @* J = ideal containing W COMPUTE: Coeff-Ideal of BO as defined in [Bravo,Encinas,Villamayor] RETURN: basic object of the Coeff-Ideal EXAMPLE: example Coeff; shows an example " { //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //!!! TASK: lower dimension by more than one in a single step if possible !!! //!!! (improve bookkeeping of invariants in Coeff and Center) !!! //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- int i,k,dummy,errtype; int ma=size(BO[4]); intvec merk; if(!defined(debugCoeff)) { int debugCoeff; } ideal C; list L; if(size(#)!=0) { if(typeof(#[1])=="ideal") { L=#; } else { ma=#[1]; L=DeltaList(BO); } } else { L=DeltaList(BO); } if(debugCoeff) { "----> In Coeff: result of DeltaList:"; L; } int d=size(L); // bmax of BO if((debugCoeff)&&(d!=b)) { "!!!!!! Length of DeltaList does not equal second argument !!!!!!"; "!!!!!! BO might not have been ord ~ 1 or wrong b !!!!!!"; } if(b>=6){return(0);} // b is too big int e=int(factorial(b)); // b of Coeff-Ideal if(e==0) { ERROR( "// integer size too small for forming b! ."); } if(b==0) { ERROR( "// second argument to Coeff should never be zero." ); } //---------------------------------------------------------------------------- // Form the Coeff-Ideal // Step 1: choose hypersurface // Step 2: sum over correct powers of Delta^i(BO[2]) // Step 3: do the intersection //---------------------------------------------------------------------------- //--- Step 1 ideal Z; poly p; for(i=1;i<=ncols(L[d]);i++) { //--- Look for smooth hypersurface in generators of Delta^(bmax-1)(BO[2]) dummy=goodChoice(BO,L[d][i]); if(!dummy) { Z= L[d][i]; break; } else { if(dummy>1) { merk[size(merk)+1]=i; } if(dummy>errtype) { errtype=dummy; } } } if(size(Z)==0) { //--- no suitable element in generators of Delta^(bmax-1)(BO[2]) //--- try random linear combination for(k=1;k<=10;k++) { for(i=2;i<=size(merk);i++) { p=p+random(-100,100)*L[d][merk[i]]; } dummy=goodChoice(BO,p); if(!dummy) { Z=p; break; } else { p=0; } } if(dummy) { for(i=1;i<=size(L[d]);i++) { p=p+random(-100,100)*L[d][i]; } dummy=goodChoice(BO,p); if(!dummy) { //--- found a suitable one Z=p; } } if(dummy) { //--- did not find a suitable random linear combination either if(dummy>errtype) { errtype=dummy; } list retlist=errtype,L[d]; return(retlist); } } if(debugCoeff) { "----> In Coeff: Chosen hypersurface"; Z; } //--- Step 2 C=Z; for(i=0;i In Coeff: J before saturation"; C; } //--- Step 3 BO[1]=BO[1]+Z; BO[2]=C; for(i=1;i<=size(BO[4]);i++) { BO[6][i]=0; // reset intersection indicator BO[4][i]=BO[4][i]+Z; // intersect the E_i if(i<=ma) { BO[2]=sat(BO[2],BO[4][i]+BO[1])[1]; // "strict transform" of J w.r.t E, not "total" } } if(debugCoeff) { "----> In Coeff:"; " J after saturation:"; BO[2]; } return(BO); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal W; ideal J=z^2+x^2*y^2; intvec b=0; list E; ideal abb=maxideal(1); intvec v; intvec w=-1; matrix M; list BO=W,J,b,E,abb,v,w,M; Coeff(BO,2); } ////////////////////////////////////////////////////////////////////////////// static proc goodChoice(list BO, poly p) "Internal procedure - no help and no example available " { //--------------------------------------------------------------------------- // test whether new W is smooth //--------------------------------------------------------------------------- ideal W=BO[1]+ideal(p); if(size(reduce(p,std(BO[1])))==0) { //--- p is already in BO[1], i.e. does not define a hypersurface in W return(1); } if(dim(std(slocusE(W)))>=0) // if(dim(timeStd(slocusE(W),20))>=0) { //--- new W would not be smooth return(1); } if(size(BO[4])==0) { //--- E is empty, no further tests necessary return(0); } //-------------------------------------------------------------------------- // test whether the hypersurface meets the E_i transversally //-------------------------------------------------------------------------- list E=BO[4]; int i,d; ideal T=W; ideal Tstd=std(T); d=nvars(basering)-dim(Tstd)+1; ideal M; for(i=1;i<=size(E);i++) { T=W,E[i]; M=minor(jacob(T),d,Tstd)+T; M=std(M); if(deg(M[1])>0) { //--- intersection not transversal return(2); } } //-------------------------------------------------------------------------- // test whether the new E_i have normal crossings //-------------------------------------------------------------------------- for(i=1;i<=size(E);i++) { E[i]=E[i],p; } if(normalCross(E)) { return(0); } else { return(2); } } ////////////////////////////////////////////////////////////////////////////// proc presentTree(list L) "USAGE: presentTree(L); L=list, output of resolve RETURN: nothing, only pretty printing of the output data of resolve() EXAMPLE: none " { def r=basering; int i,j,k; if(size(L[2])==1) { "The object was already resolved or the list L does not"; "have required input format. There is just one chart in"; "the tree."; return(); } for(i=1;i<=size(L[1]);i++) { " "; "/////////////////////////// Final Chart",i,"/////////////////////////"; def s=L[1][i]; setring s; "======================== History of this chart ======================"; for(j=2;j<=ncols(path);j++) { " "; "Blow Up",j-1,":"; " Center determined in L[2]["+string(path[1,j])+"],"; " Passing to chart ",path[2,j]," in resulting blow up."; } " "; "======================== Data of this chart ========================"; showBO(BO); setring r; kill s; pause(); } "////////////////////////////////////////////////////////////////////"; "For identification of exceptional divisors please use the tools"; "provided by reszeta.lib, e.g. collectDiv."; "For viewing an illustration of the tree of charts please use the"; "procedure ResTree from resgraph.lib."; "////////////////////////////////////////////////////////////////////"; return(); } ////////////////////////////////////////////////////////////////////////////// proc showBO(list BO) "USAGE: showBO(BO); @* BO=basic object, a list: ideal W, @* ideal J, @* intvec b (already truncated for Coeff), @* list Ex (already truncated for Coeff), @* ideal ab, @* intvec v, @* intvec w (already truncated for Coeff), @* matrix M RETURN: nothing, only pretty printing EXAMPLE: none " { " "; "==== Ambient Space: ";BO[1];" "; "==== Ideal of Variety: ";BO[2];" "; int i; list M; for(i=1;i<=size(BO[4]);i++) { M[i]=ideal(BO[4][i]); } "==== Exceptional Divisors: ";print(M);" "; "==== Images of variables of original ring:";BO[5];" "; } ////////////////////////////////////////////////////////////////////////////// //////////////////////// main procedure //////////////////////////////// ////////////////////////////////////////////////////////////////////////////// proc resolve(ideal J, list #) "USAGE: resolve (J); or resolve (J,i[,k]); @* J ideal @* i,k int COMPUTE: a resolution of J, @* if i > 0 debugging is turned on according to the following switches: @* j1: value 0 or 1; turn off or on correctness checks in all steps @* j2: value 0 or 2; turn off or on debugCenter @* j3: value 0 or 4; turn off or on debugBlowUp @* j4: value 0 or 8; turn off or on debugCoeff @* j5: value 0 or 16:turn off or on debugging of Intersection with E^- @* j6: value 0 or 32:turn off or on stop after pass throught the loop @* i=j1+j2+j3+j4+j5+j6 RETURN: a list l of 2 lists of rings l[1][i] is a ring containing a basic object BO, the result of the resolution. l[2] contains all rings which occured during the resolution process NOTE: result may be viewed in a human readable form using presentTree() EXAMPLE: example resolve; shows an example " { //---------------------------------------------------------------------------- // Initialization and sanity checks //---------------------------------------------------------------------------- def R=basering; list allRings; allRings[1]=R; list endRings; module path=[0,-1]; ideal W; list E; ideal abb=maxideal(1); intvec v; intvec bvec; intvec w=-1; matrix intE; int extra,bm; if(defined(BO)){kill BO;} if(defined(cent)){kill cent;} ideal Jrad=equiRadical(J); if(size(reduce(Jrad,std(J)))!=0) { "WARNING! The input is not reduced or not equidimensional!"; "We will continue with the reduced top-dimensional part of input"; J=Jrad; } int i,j,debu,loca,locaT,ftemp,debugResolve,smooth; //--- switches for local and for debugging may occur in any order i=size(#); extra=3; for(j=1;j<=i;j++) { if(typeof(#[j])=="int") { debugResolve=#[j]; //--- debu: debug switch for resolve, smallest bit in debugResolve debu=debugResolve mod 2; } else { if(#[j]=="M") { bm=1; ERROR("Not implemented yet"); } if(#[j]=="E"){extra=0;} if(#[j]=="A"){extra=2;} if(#[j]=="K"){extra=3;} if(#[j]=="L"){loca=1;} } } if(loca) { list qs=minAssGTZ(J); ideal K=ideal(1); for(j=1;j<=size(qs);j++) { if(size(reduce(qs[j],std(maxideal(1))))==0) { K=intersect(K,qs[j]); } } J=K; list qr=minAssGTZ(slocus(J)); K=ideal(1); for(j=1;j<=size(qr);j++) { if(size(reduce(qr[j],std(maxideal(1))))!=0) { K=intersect(K,qr[j]); smooth++; } else { if(dim(std(qr[j]))>0){loca=0;} //---- test for isolated singularity at 0 } } K=std(K); //---- if deg(K[1])==0 the point 0 is on all components of the singular //---- locus and we can work globally if(smooth==size(qr)){smooth=-1;} //---- the point 0 is not on the singular locus if((deg(K[1])>0)&&(smooth>=0)&&(!loca)) { locaT=1; poly @p; for(j=1;j<=size(K);j++) { if(jet(K[j],0)!=0) { @p=K[j]; break; } } export(@p); } if((loca)&&(!smooth)){loca=0;} //---- the case that 0 is isolated singularity and the only singular point } export(locaT); //---In case of option "L" the following holds //---loca=0 and locaT=0 we perform the global case //---loca !=0: 0 is isolated singular point, but there are other singularities //---locaT!=0: O is singular point, but not isolated, and there is a componente//--- of the singular locus not containing 0 //--- if necessary, set the corresponding debugFlags if(defined(debugResolve)) { //--- 2nd bit from the right int debugCenter=(debugResolve div 2) mod 2; export debugCenter; //--- 3rd bit from the right int debugBlowUp=(debugResolve div 4) mod 2; export debugBlowUp; //--- 4th bit from the right int debugCoeff=(debugResolve div 8) mod 2; export debugCoeff; //--- 5th bit from the right int debug_Inters_E=(debugResolve div 16) mod 2; export debug_Inters_E; //--- 6th bit from the right int praes_stop=(debugResolve div 32) mod 2; } //--- set the correct attributes to J for speed ups if( typeof(attrib(J,"isEqui"))!="int" ) { if(size(J)==1) { attrib(J,"isEqui",1); } else { attrib(J,"isEqui",0); } } if(size(J)==1) { attrib(J,"isHy",1); } else { attrib(J,"isHy",0); } //--- create the BO list BO=W,J,bvec,E,abb,v,w,intE; if(defined(invSat)){kill invSat;} list invSat=ideal(0),intvec(0); export(invSat); if(bm) { intmat invmat[2][1]=0,-1; BO[9]=invmat; } else { BO[9]=intvec(0); } export BO; list tmpList; int blo; int k,Ecount,tmpPtr; i=0; if(smooth==-1) { endRings[1]=R; list result=endRings,allRings; if(debu) { "============= result will be tested =========="; " "; "the number of charts obtained:",size(endRings); "============= result is o.k. =========="; } kill debugCenter,debugBlowUp,debugCoeff,debug_Inters_E; return(result); } //----------------------------------------------------------------------------- // While there are rings to be considered, determine center and blow up //----------------------------------------------------------------------------- while(i9) { while(size(BO[10])>0) { list @ce=BO[10][1]; //--- check of the center // @ce=correctC(BO,@ce,bm); //--- use stored center BO[10]=delete(BO[10],1); if(size(@ce[1])==0) { //--- stored center was not ok continue; } tmpPtr=0; for(Ecount=1;Ecount <= size(@ce[2]); Ecount++) { if(@ce[2][Ecount]>-1) { tmpPtr=tmpPtr+@ce[2][Ecount]; } else { @ce[2][Ecount]=size(BO[4])-tmpPtr-1; for(int cnthlp=1;cnthlp<=size(BO[10]);cnthlp++) { BO[10][cnthlp][2][Ecount]=@ce[2][Ecount]; } kill cnthlp; break; } } if(Ecount set @ce to BO[2], because later checks work with BO instead of BO2 if((size(reduce(@ce[1],std(BO2[2])))==0)&& (size(reduce(BO2[2],std(@ce[1])))==0)) { @ce[1]=BO[2]; } if(size(specialReduce(@ce[1],te,p))==0) { BO=imap(S,BO); @ce[1]=BO[2]; } else { //@ce=correctC(BO,@ce,bm); @ce[1]=eliminate(@ce[1],@z); } setring S; list @ce=imap(R1,@ce); kill R1; if((size(reduce(BO[2],std(@ce[1])))==0) &&(size(reduce(@ce[1],Jstd))==0)) { //--- J and center coincide pr[1]=@ce[1]; ideal cent=@ce[1]; } else { //--- decompose center and use first component pr=minAssGTZ(@ce[1]); if(size(reduce(@p,std(pr[1])))==0){"Achtung";~;} if(deg(std(slocus(pr[1]))[1])>0){"singulaer";~;} ideal cent=pr[1]; } if(size(pr)>1) { //--- store the other components for(k=2;k<=size(pr);k++) { if(size(reduce(@p,std(pr[k])))==0){"Achtung";~;} if(deg(std(slocus(pr[k]))[1])>0){"singulaer";~;} if(size(reduce(@p,std(pr[k])))!=0) { tmpList[size(tmpList)+1]=list(pr[k],@ce[2],@ce[3],@ce[4]); } } BO[10]=tmpList; kill tmpList; list tmpList; } } if(!defined(@ce)) { //--- no previously determined center, we need to compute one if(loca) { //--- local case: center should be inside exceptional locus ideal Ex=ideal(1); k=0; for(j=1;j<=size(BO[4]);j++) { if(deg(BO[4][j][1])!=0) { Ex=Ex*BO[4][j]; //----!!!!hier evtl. Durchschnitt??? k++; } } //--- for computation of center: drop components not meeting the Ei list BOloc=BO; list qs=minAssGTZ(BOloc[2]); ideal K=ideal(1); for(j=1;j<=size(qs);j++) { if(CompMeetsE(qs[j],BOloc[4])) { K=intersect(K,qs[j]); } } BOloc[2]=K; //--- check whether we are done if(deg(std(BOloc[2])[1])==0) { list @ce=BO[2],intvec(-1),intvec(1),intvec(0); } if(!defined(@ce)) { if(BO[3][1]!=0) { BOloc[2]=BO[2]+Ex^((BO[3][1] div k)+1);//!!!!Vereinfachen??? } else { BOloc[2]=BO[2]+Ex^((size(DeltaList(BO)) div k)+1); } if(bm) { list @ce=CenterBM(BOloc); } else { list @ce=CenterBO(BOloc); } if(size(reduce(Ex,std(@ce[1])))!=0) { list tempPr=minAssGTZ(@ce[1]); for(k=size(tempPr);k>=1;k--) { if(size(reduce(Ex,std(tempPr[k])))!=0) { tempPr=delete(tempPr,k); } } @ce[1]=1; for(k=1;k<=size(tempPr);k++) { @ce[1]=intersect(@ce[1],tempPr[k]); } if(deg(std(@ce[1])[1])==0) { @ce[1]=BO[2]; } } } //--- test whether we are done if(size(reduce(slocusE(BO[2]),std(@ce[1])))!=0) { if(transversalT(BO[2],BO[4])) { if(defined(E)){kill E;} list E=BO[4]; for(j=1;j<=size(E);j++){if(deg(E[j][1])>0){E[j]=E[j]+BO[2];}} if(normalCross(E)) { @ce[1]=BO[2]; } kill E; } } } else { //--- non-local if(bm) { list @ce=CenterBM(BO); } else { list @ce=CenterBO(BO); } //--- check of the center //@ce=correctC(BO,@ce,bm); if((size(@ce[1])==0)&&(size(@ce[4])<(size(@ce[3])-1))) { intvec xxx=@ce[3]; xxx=xxx[1..size(@ce[4])]; @ce[3]=xxx; xxx=@ce[2]; xxx=xxx[1..size(@ce[4])]; @ce[2]=xxx; kill xxx; } } if((size(reduce(BO[2],std(@ce[1])))==0) &&(size(reduce(@ce[1],Jstd))==0)) { //--- J and center coincide pr[1]=@ce[1]; ideal cent=@ce[1]; } else { //--- decompose center and use first component pr=minAssGTZ(@ce[1]); ideal cent=pr[1]; } if(size(pr)>1) { //--- store the other components for(k=2;k<=size(pr);k++) { tmpList[k-1]=list(pr[k],@ce[2],@ce[3],@ce[4]); } BO[10]=tmpList; kill tmpList; list tmpList; } } //--- do not forget to update BO[7] and BO[3] export cent; BO[7]=@ce[2]; BO[3]=@ce[3]; if((loca||locaT)&&(size(@ce)<4)){@ce[4]=0;} //Provisorium !!! if((size(@ce[4])0) { if(deg(BO[1][1])==0) { "!!! W is empty !!!"; path; setring R; kill S; list result=endRings,allRings; return(result); } if(deg(std(slocusE(BO[1]))[1])>0) { "!!! W not smooth !!!"; path; setring R; kill S; list result=endRings,allRings; return(result); } } if((!loca)&&(!locaT)) { if(deg(std(slocusE(cent+BO[1]))[1])>0) { "!!! Center not smooth !!!"; path; std(cent+BO[1]); ~; setring R; kill S; list result=endRings,allRings; return(result); } } for(j=1;j<=size(BO[4]);j++) { if(deg(BO[4][j][1])>0) { if(deg(std(slocusE(BO[4][j]+BO[1]))[1])>0) { "!!! exceptional divisor is not smooth !!!"; path; setring R; kill S; list result=endRings,allRings; return(result); } } } if((!loca)&&(!locaT)) { if((norC(BO,cent))&&(size(reduce(cent,Jstd))!=0)) { "!!! this chart is already finished !!!"; cent=BO[2]; ~; } } } //---------------------------------------------------------------------------- // Do the blow up //---------------------------------------------------------------------------- //!!!! Change this as soon as there is time!!! //!!!! quick and dirty bug fix for old shortcut which has not yet been killed if((dim(std(cent))==0)&&defined(shortcut)) {kill shortcut;} //!!! end of bugfix if(size(reduce(cent,Jstd))!=0) { //--- center does not equal J tmpList=blowUpBO(BO,cent,extra); if((debu)&&(!loca)&&(!locaT)) { //--- test it, if debu is set if(!testBlowUp(BO,cent,tmpList,i,extra)) { "non-redundant chart has been killed!"; ~; } } //--- extend the list of all rings allRings[size(allRings)+1..size(allRings)+size(tmpList)]= tmpList[1..size(tmpList)]; for(j=1;j<=size(tmpList);j++) { def Q=allRings[size(allRings)-j+1]; setring Q; def path=imap(S,path); path=path,[i,size(tmpList)-j+1]; export path; setring S; kill Q; } kill tmpList; list tmpList; } else { //--- center equals J k=0; for(j=1;j<=size(BO[6]);j++) { if(BO[6][j]!=1) { //--- there is an E_i which meets J in this chart k=1; break; } } if((k)||(extra==2)) { //--- chart finished, non-redundant endRings[size(endRings)+1]=S; } } kill pr; setring R; kill S; } //--------------------------------------------------------------------------- // set up the result, test it (if debu is set) and return it //--------------------------------------------------------------------------- list result=endRings,allRings; if(debu) { "============= result will be tested =========="; " "; "the number of charts obtained:",size(endRings); if(locaT){loca=2;} int tes=testRes(J,endRings,loca); if(tes) { "============= result is o.k. =========="; } else { "============ result is wrong =========="; ~; } } kill debugCenter,debugBlowUp,debugCoeff,debug_Inters_E; if(locaT){kill @p;} kill locaT; return(result); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal J=x3+y5+yz2+xy4; list L=resolve(J,0); def Q=L[1][7]; setring Q; showBO(BO); } ////////////////////////////////////////////////////////////////////////// //static proc CompMeetsE(ideal J, list E) "Internal procedure - no help and no example available " { int i; for(i=1;i<=size(E);i++) { if(deg(std(E[i])[1])!=0) { if(deg(std(J+E[i])[1])!=0) { return(1); } } } return(0); } //======================================================================== //-------------- procedures for testing the result ---------------------- // (not yet commented) //======================================================================== ////////////////////////////////////////////////////////////////////////// static proc testRes(ideal J,list L,int loca) "Internal procedure - no help and no example available " { int loc; if(defined(locaT)){loc=locaT;} if(loc){loca=0;} def R=basering; ideal M=maxideal(1); int i,j,tr; for(i=1;i<=size(L);i++) { def Q=L[i]; setring Q; ideal J=BO[2]; list E=BO[4]; map phi=R,BO[5]; ideal K=phi(J)+BO[1]; ideal stTK=std(K); if(loca) { ideal M=phi(M)+BO[1]; ideal stTM=std(M); } for(j=1;j<=size(E);j++) { if(deg(E[j][1])>0) { stTK=sat(stTK,E[j])[1]; } if(loca) { stTM=sat(stTM,E[j])[1]; } } ideal sL=slocusE(J); if(loca){sL=sL+stTM;} ideal sLstd=std(sL); if(deg(sLstd[1])>0) { if(!loc) { "J is not smooth";i; setring R; return(0); } if(size(reduce(@p,std(radical(sLstd))))>0) { "J is not smooth";i; setring R; return(0); } } if(!((size(reduce(J,std(stTK)))==0) &&(size(reduce(stTK,std(J)))==0))) { "map is wrong";i; setring R; return(0); } if(loc){tr=transversalT(J,E,@p);} else{tr=transversalT(J,E);} if(!tr) { "E not transversal with J";i; setring R; return(0); } if(!normalCross(E)) { "E not normal crossings";i; setring R; return(0); } for(j=1;j<=size(E);j++) { if(deg(E[j][1])>0){E[j]=E[j]+J;} } if(!normalCross(E)) { "E not normal crossings with J";i; setring R; return(0); } kill J,E,phi,K,stTK; if(loca){kill M,stTM;} setring R; kill Q; } return(1); } ////////////////////////////////////////////////////////////////////////////// static proc testBlowUp(list BO,ideal cent,list tmpList, int j, int extra) { def R=basering; int n=nvars(basering); int i; if((extra!=3)&&(extra!=2)) { ideal K=BO[1],BO[2],cent; for(i=1;i<=size(BO[4]);i++) { K=K,BO[4][i]; } list N=findvars(K); //list N=findvars(BO[2]); if(size(N[1])0){setring R;return(0);} if(size(reduce(T,std(radical(sL))))>0){setring R;return(0);} setring R; return(1); } ////////////////////////////////////////////////////////////////////////////// static proc normalCross(list E,list #) "Internal procedure - no help and no example available " { int loc; if((defined(locaT))&&(defined(@p))) { loc=1; ideal pp=@p; } int i,d,j; int n=nvars(basering); list E1,E2; ideal K,M,Estd,cent; intvec v,w; if(size(#)>0){cent=#[1];} for(i=1;i<=size(E);i++) { Estd=std(E[i]); if(deg(Estd[1])>0) { E1[size(E1)+1]=Estd; } } E=E1; for(i=1;i<=size(E);i++) { v=i; E1[i]=list(E[i],v); } list ll; int re=1; int ok; while(size(E1)>0) { K=E1[1][1]; v=E1[1][2]; attrib(K,"isSB",1); E1=delete(E1,1); d=n-dim(K); M=minor(jacob(K),d)+K; if(deg(std(M)[1])>0) { if(size(#)>0) { if(size(reduce(M,std(cent)))>0) { ll[size(ll)+1]=std(M); } else { ok=1; } } if(!loc) { re=0; } else { if(size(reduce(pp,std(radical(M))))>0){re=0;} } } for(i=1;i<=size(E);i++) { for(j=1;j<=size(v);j++){if(v[j]==i){break;}} if(j<=size(v)){if(v[j]==i){i++;continue;}} Estd=std(K+E[i]); w=v; if(deg(Estd[1])==0){i++;continue;} if(d==n-dim(Estd)) { if(size(#)>0) { if(size(reduce(Estd,std(cent)))>0) { ll[size(ll)+1]=Estd; } else { ok=1; } } if(!loc) { re=0; } else { if(size(reduce(pp,std(radical(M))))>0){re=0;} } } w[size(w)+1]=i; E2[size(E2)+1]=list(Estd,w); } if(size(E2)>0) { if(size(E1)>0) { E1[size(E1)+1..size(E1)+size(E2)]=E2[1..size(E2)]; } else { E1=E2; } } kill E2; list E2; } /* if((!ok)&&(!re)&&(size(#)==1)) { "the center is wrong"; "it could be one of the following list"; ll; ~; } */ if((!ok)&&(!re)&&(size(#)==2)) { return(2); //for Center correction } return(re); } ////////////////////////////////////////////////////////////////////////////// static proc normalCrossB(ideal J,list E,ideal V) "Internal procedure - no help and no example available " { int i,d,j; int n=nvars(basering); list E1,E2; ideal K,M,Estd; intvec v,w; for(i=1;i<=size(E);i++) { Estd=std(E[i]+J); if(deg(Estd[1])>0) { E1[size(E1)+1]=Estd; } } E=E1; for(i=1;i<=size(E);i++) { v=i; E1[i]=list(E[i],v); } list ll; int re=1; while((size(E1)>0)&&(re==1)) { K=E1[1][1]; v=E1[1][2]; attrib(K,"isSB",1); E1=delete(E1,1); d=n-dim(K); M=minor(jacob(K),d)+K; if(deg(std(M+V)[1])>0) { re=0; break; } for(i=1;i<=size(E);i++) { for(j=1;j<=size(v);j++){if(v[j]==i){break;}} if(j<=size(v)){if(v[j]==i){i++;continue;}} Estd=std(K+E[i]); w=v; if(deg(Estd[1])==0){i++;continue;} if(d==n-dim(Estd)) { if(deg(std(Estd+V)[1])>0) { re=0; break; } } w[size(w)+1]=i; E2[size(E2)+1]=list(Estd,w); } if(size(E2)>0) { if(size(E1)>0) { E1[size(E1)+1..size(E1)+size(E2)]=E2[1..size(E2)]; } else { E1=E2; } } kill E2; list E2; } return(re); } ////////////////////////////////////////////////////////////////////////////// static proc norC(list BO,ideal cent) "Internal procedure - no help and no example available " { int j; list E=BO[4]; ideal N=BO[2]; if(BO[3][1]>1){return(0);} if(deg(std(slocusE(BO[2]))[1])>0){return(0);} if(!transversalT(N,E)){return(0);} for(j=1;j<=size(E);j++){if(deg(E[j][1])>0){E[j]=E[j]+N;}} if(!normalCross(E,cent)){return(0);} return(1); } ////////////////////////////////////////////////////////////////////////////// static proc specialReduce(ideal I,ideal J,poly p) { matrix M; int i,j; for(i=1;i<=ncols(I);i++) { M=coeffs(I[i],@z); I[i]=0; for(j=1;j<=nrows(M);j++) { I[i]=I[i]+M[j,1]*p^(nrows(M)-j); } I[i]=reduce(I[i],J); } return(I); } singular-4.0.3+ds/Singular/LIB/resources.lib000066400000000000000000000107651266270727000206620ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////// version="version resources.lib 4.0.0.0 Dec_2013 "; // $Id: 73b112cd1cdb048475ed47444e26850ac5c1154e $ category="General purpose"; info=" LIBRARY: resources.lib Tools to manage the computational resources AUTHOR: Andreas Steenpass, e-mail: steenpass@mathematik.uni-kl.de OVERVIEW: The purpose of this library is to manage the computational resources of a Singular session. The library tasks.lib and any library build upon tasks.lib respect these settings, i.e. they will not use more computational resources than provided via resources.lib. The provided procedures and their implementation are currently quite simple. The library can be extended later on to support, e.g., distributed computations on several servers. KEYWORDS: parallelization; distributed computing; semaphores SEE ALSO: tasks_lib, parallel_lib PROCEDURES: addcores(); add an integer to the number of available processor cores setcores(); set the number of available processor cores getcores(); get the number of available processor cores semaphore(); initialize a new semaphore "; /* initialize (lib-)global variables */ static proc mod_init() { int sem_cores = semaphore(system("--cpus")-1); exportto(Resources, sem_cores); int NCORES = system("semaphore", "get_value", sem_cores)+1; exportto(Resources, NCORES); } proc addcores(int n) "USAGE: addcores(n), n int RETURN: the adjusted number of available processor cores, after n has been added to it. If n is negative, this number is reduced. NOTE: The number of available processor cores must be at least 1. Reducing this number may take some time. @* This procedure should only be called in the main process of a Singular session and not within any task defined via tasks.lib. SEE ALSO: setcores, getcores, tasks_lib, parallel_lib EXAMPLE: example addcores; shows an example" { /* check for errors */ if (NCORES+n < 1) { ERROR("The number of cores to use must be at least 1."); } /* change the value of the semaphore */ int i; int tmp; if (n >= 0) { for (i = n; i > 0; i--) { tmp = system("semaphore", "release", sem_cores); } } else { for (i = n; i < 0; i++) { tmp = system("semaphore", "acquire", sem_cores); } } /* adjust and return NCORES */ NCORES = NCORES+n; return(NCORES); } example { "EXAMPLE:"; echo = 2; setcores(4); addcores(-2); } proc setcores(int n) "USAGE: setcores(n), n int RETURN: n. The number of available processor cores is set to n and n is returned. NOTE: The number of available processor cores must be at least 1. Reducing this number may take some time. @* This procedure should only be called in the main process of a Singular session and not within any task defined via tasks.lib. SEE ALSO: addcores, getcores, tasks_lib, parallel_lib EXAMPLE: example setcores; shows an example" { return(addcores(n-NCORES)); } example { "EXAMPLE:"; echo = 2; setcores(2); setcores(4); } proc getcores() "USAGE: getcores(n), n int RETURN: the number of available processor cores. NOTE: This procedure should only be called in the main process of a Singular session and not within any task defined via tasks.lib. SEE ALSO: addcores, setcores, tasks_lib, parallel_lib EXAMPLE: example getcores; shows an example" { return(NCORES); } example { "EXAMPLE:"; echo = 2; setcores(4); getcores(); } proc semaphore(int n) "USAGE: semaphore(n), n int RETURN: the index of a new semaphore initialized with n. EXAMPLE: example semaphore; shows an example" { int i = 0; while (system("semaphore", "exists", i) == 1) { i++; } if (system("semaphore", "init", i, n) != 1) { ERROR("no more semphores"); } return(i); } example { "EXAMPLE:"; echo = 2; int sem = semaphore(1); system("semaphore", "acquire", sem); system("semaphore", "try_acquire", sem); system("semaphore", "release", sem); system("semaphore", "try_acquire", sem); } /* wrapper for the now obsolete optional parameter in parallel.lib for the * number of processor cores */ static proc setcores_subtree(int n) { list oldvalues = list(sem_cores, NCORES); sem_cores = semaphore(n-1); NCORES = n; return(oldvalues); } static proc resetcores_subtree(list oldvalues) { sem_cores = oldvalues[1]; NCORES = oldvalues[2]; } singular-4.0.3+ds/Singular/LIB/reszeta.lib000066400000000000000000005056731266270727000203340ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////// version="version reszeta.lib 4.0.0.0 Jun_2013 "; // $Id: 77d644aec9fd87b1912ae9cb5552f7122ec45f22 $ category="Algebraic Geometry"; info=" LIBRARY: reszeta.lib topological Zeta-function and some other applications of desingularization AUTHORS: A. Fruehbis-Krueger, anne@mathematik.uni-kl.de, @* G. Pfister, pfister@mathematik.uni-kl.de REFERENCES: [1] Fruehbis-Krueger,A., Pfister,G.: Some Applications of Resolution of @* Singularities from a Practical Point of View, in Computational @* Commutative and Non-commutative Algebraic Geometry, @* NATO Science Series III, Computer and Systems Sciences 196, 104-117 (2005) [2] Fruehbis-Krueger: An Application of Resolution of Singularities: @* Computing the topological Zeta-function of isolated surface singularities @* in (C^3,0), in D.Cheniot, N.Dutertre et al.(Editors): Singularity Theory, @* World Scientific Publishing (2007) PROCEDURES: intersectionDiv(L) computes intersection form and genera of exceptional divisors (isolated singularities of surfaces) spectralNeg(L) computes negative spectral numbers (isolated hypersurface singularity) discrepancy(L) computes discrepancy of given resolution zetaDL(L,d) computes Denef-Loeser zeta function (hypersurface singularity of dimension 2) collectDiv(L[,iv]) identify exceptional divisors in different charts (embedded and non-embedded case) prepEmbDiv(L[,b]) prepare list of divisors (including components of strict transform, embedded case) abstractR(L) pass from embedded to non-embedded resolution computeV(re,DL) multiplicities of divisors in pullback of volume form computeN(re,DL) multiplicities of divisors in total transform of resolution "; LIB "resolve.lib"; LIB "solve.lib"; LIB "normal.lib"; /////////////////////////////////////////////////////////////////////////////// static proc spectral1(poly h,list re, list DL,intvec v, intvec n) "Internal procedure - no help and no example available " { //--- compute one spectral number //--- DL is output of prepEmbDiv int i; intvec w=computeH(h,re,DL); number gw=number(w[1]+v[1])/number(n[1]); for(i=2;i<=size(v);i++) { if(gw>number(w[i]+v[i])/number(n[i])) { gw=number(w[i]+v[i])/number(n[i]); } } return(gw-1); } /////////////////////////////////////////////////////////////////////////////// proc spectralNeg(list re,list #) "USAGE: spectralNeg(L); @* L = list of rings ASSUME: L is output of resolution of singularities RETURN: list of numbers, each a spectral number in (-1,0] EXAMPLE: example spectralNeg; shows an example " { //----------------------------------------------------------------------------- // Initialization and Sanity Checks //----------------------------------------------------------------------------- int i,j,l; number bound; list resu; if(size(#)>0) { //--- undocumented feature: //--- if # is not empty it computes numbers up to this bound, //--- not necessarily spectral numbers bound=number(#[1]); } //--- get list of embedded divisors list DL=prepEmbDiv(re,1); int k=1; ideal I,delI; number g; int m=nvars(basering); //--- prepare the multiplicities of exceptional divisors N and nu intvec v=computeV(re,DL); // nu intvec n=computeN(re,DL); // N //--------------------------------------------------------------------------- // start computation, first case separately, then loop //--------------------------------------------------------------------------- resu[1]=spectral1(1,re,DL,v,n); // first number, corresponding to // volume form itself if(resu[1]>=bound) { //--- exceeds bound ==> not a spectral number resu=delete(resu,1); return(resu); } delI=std(ideal(0)); while(k) { //--- now run through all monomial x volume form, degree by degree j++; k=0; I=maxideal(j); I=reduce(I,delI); for(i=1;i<=size(I);i++) { //--- all monomials in degree j g=spectral1(I[i],re,DL,v,n); if(g not a spectral number k=1; l=1; while(resu[l]K[y_1,...,y_n]/J defined by x_i ---> I_i. //--- Let basering=K[y_1,...,y_n], l=n-dim(basering/J), //--- I=, J= //--- For each subset v in {1,...,n} of l elements and //--- w in {1,...,r} of l elements //--- let K_v,w be the ideal generated by the n-l-minors of the matrix //--- (diff(I_i,y_j)+ //--- \sum_k diff(I_i,y_v[k])*diff(J_w[k],y_j))_{j not in v multiplied with //--- the determinant of (diff(J_w[i],y_v[j])) //--- the sum of all such ideals K_v,w plus J is returned. //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- int n=nvars(basering); int i,j,k; intvec u,v,w,x; matrix MI[ncols(I)][n]=jacob(I); matrix N=unitmat(n); matrix L; ideal K=J; if(size(J)==0) { K=minor(MI,n); } //--------------------------------------------------------------------------- // Do calculation as described above. // separately for case size(J)=1 //--------------------------------------------------------------------------- if(size(J)==1) { matrix MJ[ncols(J)][n]=jacob(J); N=concat(N,transpose(MJ)); v=1..n; for(i=1;i<=n;i++) { L=transpose(permcol(N,i,n+1)); if(i==1){w=2..n;} if(i==n){w=1..n-1;} if((i!=1)&&(i!=n)){w=1..i-1,i+1..n;} L=submat(L,v,w); L=MI*L; K=K+minor(L,n-1)*MJ[1,i]; } } if(size(J)>1) { matrix MJ[ncols(J)][n]=jacob(J); matrix SMJ; N=concat(N,transpose(MJ)); ideal Jstd=std(J); int l=n-dim(Jstd); int r=ncols(J); list L1=indexSet(n,l); list L2=indexSet(r,l); for(i=1;i<=size(L1);i++) { for(j=1;j<=size(L2);j++) { for(k=1;k<=size(L1[i]);k++) { if(L1[i][k]){v[size(v)+1]=k;} } v=v[2..size(v)]; for(k=1;k<=size(L2[j]);k++) { if(L2[j][k]){w[size(w)+1]=k;} } w=w[2..size(w)]; SMJ=submat(MJ,w,v); L=N; for(k=1;k<=l;k++) { L=permcol(L,v[k],n+w[k]); } u=1..n; x=1..n; v=sort(v)[1]; for(k=l;k>=1;k--) { if(v[k]) { u=deleteInt(u,v[k],1); } } L=transpose(submat(L,u,x)); L=MI*L; K=K+minor(L,n-l)*det(SMJ); } } } return(K); } /////////////////////////////////////////////////////////////////////////////// static proc computeH(ideal h,list re,list DL) "Internal procedure - no help and no example available " { //--- additional procedure to computeV, allows //--- computation for polynomial x volume form //--- by computing the contribution of the polynomial h //--- Note: DL is output of prepEmbDiv //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- def R=basering; ideal II=h; list iden=DL; def T=re[2][1]; setring T; int i,k; intvec v; v[size(iden)]=0; if(deg(II[1])==0){return(v);} //---------------------------------------------------------------------------- // Run through all exceptional divisors //---------------------------------------------------------------------------- for(k=1;k<=size(iden);k++) { for(i=1;i<=size(iden[k]);i++) { if(defined(S)){kill S;} def S=re[2][iden[k][i][1]]; setring S; if((!v[k])&&(defined(EList))) { if(defined(JJ)){kill JJ;} if(defined(phi)){kill phi;} map phi=T,BO[5]; ideal JJ=phi(II); if(size(JJ)!=0) { v[k]=ordE(JJ,EList[iden[k][i][2]],BO[1]); } } setring R; } } return(v); } ////////////////////////////////////////////////////////////////////////////// proc computeN(list re,list DL) "USAGE: computeN(L,DL); L = list of rings DL = divisor list ASSUME: L has structure of output of resolve DL has structure of output of prepEmbDiv RETURN: intvec, i-th entry is multiplicity of i-th divisor in total transform under resolution EXAMPLE: example computeN; " { //--- computes for every (Q-irred.) divisor E_i its multiplicity in f \circ pi //--- DL is output of prepEmbDiv //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- def R=basering; list iden=DL; def T=re[2][1]; setring T; ideal J=BO[2]; int i,k; intvec v; v[size(iden)]=0; //---------------------------------------------------------------------------- // Run through all exceptional divisors //---------------------------------------------------------------------------- for(k=1;k<=size(iden);k++) { for(i=1;i<=size(iden[k]);i++) { if(defined(S)){kill S;} def S=re[2][iden[k][i][1]]; setring S; if((!v[k])&&(defined(EList))) { if(defined(II)){kill II;} if(defined(phi)){kill phi;} map phi=T,BO[5]; ideal II=phi(J); if(size(II)!=0) { v[k]=ordE(II,EList[iden[k][i][2]],BO[1]); } } setring R; } } return(v); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal I=(x-y)*(x-z)*(y-z)-z4; list re=resolve(I,1); list iden=prepEmbDiv(re); intvec v=computeN(re,iden); v; } ////////////////////////////////////////////////////////////////////////////// static proc countEijk(list re,list iden,intvec iv,list #) "Internal procedure - no help and no example available " { //--- count the number of points in the intersection of 3 exceptional //--- hyperplanes (of dimension 2) - one of them is allowed to be a component //--- of the strict transform //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- int i,j,k,comPa,numPts,localCase; intvec ituple,jtuple,ktuple; list chList,tmpList; def R=basering; if(size(#)>0) { if(string(#[1])=="local") { localCase=1; } } //---------------------------------------------------------------------------- // Find common charts //---------------------------------------------------------------------------- for(i=1;i<=size(iden[iv[1]]);i++) { //--- find common charts - only for final charts if(defined(S)) {kill S;} def S=re[2][iden[iv[1]][i][1]]; setring S; if(!defined(EList)) { i++; setring R; continue; } setring R; kill ituple,jtuple,ktuple; intvec ituple=iden[iv[1]][i]; intvec jtuple=findInIVList(1,ituple[1],iden[iv[2]]); intvec ktuple=findInIVList(1,ituple[1],iden[iv[3]]); if((size(jtuple)!=1)&&(size(ktuple)!=1)) { //--- chList contains all information about the common charts, //--- each entry represents a chart and contains three intvecs from iden //--- one for each E_l kill tmpList; list tmpList=ituple,jtuple,ktuple; chList[size(chList)+1]=tmpList; i++; if(i<=size(iden[iv[1]])) { continue; } else { break; } } } if(size(chList)==0) { //--- no common chart !!! return(int(0)); } //---------------------------------------------------------------------------- // Count points in common charts //---------------------------------------------------------------------------- for(i=1;i<=size(chList);i++) { //--- run through all common charts if(defined(S)) { kill S;} def S=re[2][chList[i][1][1]]; setring S; //--- intersection in this chart if(defined(interId)){kill interId;} if(localCase==1) { //--- in this case we need to intersect with \pi^-1(0) ideal interId=EList[chList[i][1][2]]+EList[chList[i][2][2]] +EList[chList[i][3][2]]+BO[5]; } else { ideal interId=EList[chList[i][1][2]]+EList[chList[i][2][2]] +EList[chList[i][3][2]]; } interId=std(interId); if(defined(otherId)) {kill otherId;} ideal otherId=1; for(j=1;jncols(path))||(comPa>ncols(opath))) break; } comPa=int(leadcoef(path[1,comPa-1])); otherId=otherId+interId; otherId=intersect(otherId, fetchInTree(re,chList[j][1][1], comPa,chList[i][1][1],"interId",iden)); } otherId=std(otherId); //--- do not count each point more than once interId=sat(interId,otherId)[1]; export(interId); if(dim(interId)>0) { ERROR("CountEijk: intersection not zerodimensional"); } //--- add the remaining number of points to the total point count numPts numPts=numPts+vdim(interId); } return(numPts); } ////////////////////////////////////////////////////////////////////////////// static proc chiEij(list re, list iden, intvec iv) "Internal procedure - no help and no example available " { //!!! Copy of chiEij_local adjusted for non-local case //!!! changes must be made in both copies //--- compute the Euler characteristic of the intersection //--- curve of two exceptional hypersurfaces (of dimension 2) //--- one of which is allowed to be a component of the strict transform //--- using the formula chi(Eij)=2-2g(Eij) //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- int i,j,k,chi,g; intvec ituple,jtuple,inters; def R=basering; //---------------------------------------------------------------------------- // Find a common chart in which they intersect //---------------------------------------------------------------------------- for(i=1;i<=size(iden[iv[1]]);i++) { //--- find a common chart in which they intersect: only for final charts if(defined(S)) {kill S;} def S=re[2][iden[iv[1]][i][1]]; setring S; if(!defined(EList)) { i++; setring R; continue; } setring R; kill ituple,jtuple; intvec ituple=iden[iv[1]][i]; intvec jtuple=findInIVList(1,ituple[1],iden[iv[2]]); if(size(jtuple)==1) { if(i1) { ERROR("genus_Eij: higher dimensional intersection"); } if(dim(interId)>=0) { //--- save the index of the current chart for future use export(interId); inters[size(inters)+1]=iden[iv[1]][i][1]; } BO[1]=std(BO[1]); if(((dim(interId)<=0)&&(dim(BO[1])>2))|| ((dim(interId)<0)&&(dim(BO[1])==2))) { if(i1) { ERROR("genus_Eij: higher dimensional intersection"); } if(dim(interId)>=0) { //--- save the index of the current chart for future use export(interId); inters[size(inters)+1]=iden[iv[1]][i][1]; } BO[1]=std(BO[1]); if(dim(interId)<0) { if(i2)) { //--- for sets of points the Euler characteristic is just //--- the number of points //--- fat points are impossible, since everything is smooth and n.c. chi=chi+vdim(interId); points=1; } else { if(points==1) { ERROR("components of intersection do not have same dimension"); } g=genus(interId); //--- chi is the Euler characteristic of the (disjoint !!!) union of the //--- considered components //--- remark: components are disjoint, because the E_i are normal crossing!!! chi=chi+(2-2*g); } } return(chi); } ////////////////////////////////////////////////////////////////////////////// static proc computeChiE(list re, list iden) "Internal procedure - no help and no example available " { //--- compute the Euler characteristic of the exceptional hypersurfaces //--- (of dimension 2), not considering the components of the strict //--- transform //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- int i,j,k,m,thisE,otherE; def R=basering; intvec nulliv,chi_temp,kvec; nulliv[size(iden)]=0; list chi_E; for(i=1;i<=size(iden);i++) { chi_E[i]=list(); } //--------------------------------------------------------------------------- // Run through the list of charts and compute the Euler characteristic of // the new exceptional hypersurface and change the values for the old ones // according to the blow-up which has just been performed // For initialization reasons, treat the case of the first blow-up separately //--------------------------------------------------------------------------- for(i=2;i<=size(re[2]);i++) { //--- run through all charts if(defined(S)){kill S;} def S=re[2][i]; setring S; m=int(leadcoef(path[1,ncols(path)])); if(defined(Spa)){kill Spa;} def Spa=re[2][m]; if(size(BO[4])==1) { //--- just one exceptional divisor thisE=1; setring Spa; if(i==2) { //--- have not set the initial value of chi(E_1) yet if(dim(std(cent))==0) { //--- center was point ==> new except. div. is a P^2 list templist=3*vdim(std(BO[1]+cent)),nulliv; } else { //--- center was curve ==> new except. div. is curve x P^1 list templist=4-4*genus(BO[1]+cent),nulliv; } chi_E[1]=templist; kill templist; } setring S; i++; if(i new except. div. is a P^2 list templist=3*vdim(std(BO[1]+cent)),nulliv; } else { //--- center was curve ==> new except. div. is a C x P^1 list templist=4-4*genus(BO[1]+cent),nulliv; } chi_E[thisE]=templist; kill templist; } for(j=1;j<=size(BO[4]);j++) { //--- we are in the parent ring ==> thisE is not yet born //--- all the other E_i have already been initialized, but the chi //--- might change with the current blow-up at cent if(BO[6][j]==1) { //--- ignore empty sets j++; if(j<=size(BO[4])) { continue; } else { break; } } for(k=1;k<=size(iden);k++) { //--- find global index of BO[4][j] if(inIVList(intvec(m,j),iden[k])) { otherE=k; break; } } if(chi_E[otherE][2][thisE]==1) { //--- already considered this one j++; if(j<=size(BO[4])) { continue; } else { break; } } //--------------------------------------------------------------------------- // update chi according to the formula // chi(E_k^transf)=chi(E_k) - chi(C \cap E_k) + chi(E_k \cap E_new) // for convenience of implementation, we first compute // chi(E_k) - chi(C \cap E_k) // and afterwards add the last term chi(E_k \cap E_new) //--------------------------------------------------------------------------- ideal CinE=std(cent+BO[4][j]+BO[1]); // this is C \cap E_k if(dim(CinE)==1) { //--- center meets E_k in a curve chi_temp[otherE]=chi_E[otherE][1]-(2-2*genus(CinE)); } if(dim(CinE)==0) { //--- center meets E_k in points chi_temp[otherE]=chi_E[otherE][1]-vdim(std(CinE)); } kill CinE; setring S; //--- now we are back in the i-th ring in the list ideal CinE=std(BO[4][j]+BO[4][size(BO[4])]+BO[1]); // this is E_k \cap E_new if(dim(CinE)==1) { //--- if the two divisors meet, they meet in a curve chi_E[otherE][1]=chi_temp[otherE]+(2-2*genus(CinE)); chi_E[otherE][2][thisE]=1; // this blow-up of E_k is done } kill CinE; setring Spa; } } setring R; return(chi_E); } ////////////////////////////////////////////////////////////////////////////// static proc computeChiE_local(list re, list iden) "Internal procedure - no help and no example available " { //--- compute the Euler characteristic of the intersection of the //--- exceptional hypersurfaces with \pi^-1(0) which can be of //--- dimension 1 or 2 - not considering the components of the strict //--- transform //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- int i,j,k,aa,m,n,thisE,otherE; def R=basering; intvec nulliv,chi_temp,kvec,dimEi,endiv; nulliv[size(iden)]=0; dimEi[size(iden)]=0; endiv[size(re[2])]=0; list chi_E; for(i=1;i<=size(iden);i++) { chi_E[i]=list(); } //--------------------------------------------------------------------------- // Run through the list of charts and compute the Euler characteristic of // the new exceptional hypersurface and change the values for the old ones // according to the blow-up which has just been performed // For initialization reasons, treat the case of the first blow-up separately //--------------------------------------------------------------------------- for(i=2;i<=size(re[2]);i++) { //--- run through all charts if(defined(S)){kill S;} def S=re[2][i]; setring S; if(defined(EList)) { endiv[i]=1; } m=int(leadcoef(path[1,ncols(path)])); if(defined(Spa)){kill Spa;} def Spa=re[2][m]; if(size(BO[4])==1) { //--- just one exceptional divisor thisE=1; setring Spa; if(i==2) { //--- have not set the initial value of chi(E_1) yet //--- in the local case, we need to know whether the center contains 0 if(size(reduce(cent,std(maxideal(1))))!=0) { //--- first center does not meet 0 list templist=0,nulliv; dimEi[1]=-1; } else { if(dim(std(cent))==0) { //--- center was point ==> new except. div. is a P^2 list templist=3*vdim(std(BO[1]+cent)),nulliv; dimEi[1]=2; } else { //--- center was curve ==> intersection of new exceptional divisor //--- with \pi^-1(0) is a curve, namely P^1 setring S; list templist=2,nulliv; dimEi[1]=1; } } chi_E[1]=templist; kill templist; } setring S; i++; if(i new except. div. is a P^2 list templist=3*vdim(std(BO[1]+cent)),nulliv; dimEi[thisE]=2; } else { //--- center was curve ==> new except. div. is a C x P^1 if(dim(std(cent+BO[5]))==1) { //--- whole curve is in \pi^-1(0) list templist=4-4*genus(BO[1]+cent),nulliv; dimEi[thisE]=2; } else { //--- curve meets \pi^-1(0) in points //--- in S, the intersection will be a curve!!! setring S; list templist=2-2*genus(BO[1]+BO[4][size(BO[4])]+BO[5]),nulliv; dimEi[thisE]=1; setring Spa; } } } if(defined(templist)) { chi_E[thisE]=templist; kill templist; } } for(j=1;j<=size(BO[4]);j++) { //--- we are in the parent ring ==> thisE is not yet born //--- all the other E_i have already been initialized, but the chi //--- might change with the current blow-up at cent if(BO[6][j]==1) { //--- ignore empty sets j++; if(j<=size(BO[4])) { continue; } else { break; } } for(k=1;k<=size(iden);k++) { //--- find global index of BO[4][j] if(inIVList(intvec(m,j),iden[k])) { otherE=k; break; } } if(dimEi[otherE]<=1) { //--- dimEi[otherE]==-1: center leading to this E does not meet \pi^-1(0) //--- dimEi[otherE]== 0: center leading to this E does not meet \pi^-1(0) //--- in any previously visited charts //--- maybe in some other branch later, but has nothing //--- to do with this center //--- dimEi[otherE]== 1: E \cap \pi^-1(0) is curve //--- ==> chi is birational invariant j++; if(j<=size(BO[4])) { continue; } break; } if(chi_E[otherE][2][thisE]==1) { //--- already considered this one j++; if(j<=size(BO[4])) { continue; } else { break; } } //--------------------------------------------------------------------------- // update chi according to the formula // chi(E_k^transf)=chi(E_k) - chi(C \cap E_k) + chi(E_k \cap E_new) // for convenience of implementation, we first compute // chi(E_k) - chi(C \cap E_k) // and afterwards add the last term chi(E_k \cap E_new) //--------------------------------------------------------------------------- ideal CinE=std(cent+BO[4][j]+BO[1]); // this is C \cap E_k if(dim(CinE)==1) { //--- center meets E_k in a curve chi_temp[otherE]=chi_E[otherE][1]-(2-2*genus(CinE)); } if(dim(CinE)==0) { //--- center meets E_k in points chi_temp[otherE]=chi_E[otherE][1]-vdim(std(CinE)); } kill CinE; setring S; //--- now we are back in the i-th ring in the list ideal CinE=std(BO[4][j]+BO[4][size(BO[4])]+BO[1]); // this is E_k \cap E_new if(dim(CinE)==1) { //--- if the two divisors meet, they meet in a curve chi_E[otherE][1]=chi_temp[otherE][1]+(2-2*genus(CinE)); chi_E[otherE][2][thisE]=1; // this blow-up of E_k is done } kill CinE; setring Spa; } } //--- we still need to clean-up the 1-dimensional E_i \cap \pi^-1(0) for(i=1;i<=size(dimEi);i++) { if(dimEi[i]!=1) { //--- not 1-dimensional ==> skip i++; if(i>size(dimEi)) break; continue; } if(defined(myCharts)) {kill myCharts;} intvec myCharts; chi_E[i]=0; for(j=1;j<=size(re[2]);j++) { if(endiv[j]==0) { //--- not an endChart ==> skip j++; if(j>size(re[2])) break; continue; } if(defined(mtuple)) {kill mtuple;} intvec mtuple=findInIVList(1,j,iden[i]); if(size(mtuple)==1) { //-- nothing to do with this Ei ==> skip j++; if(j>size(re[2])) break; continue; } myCharts[size(myCharts)+1]=j; if(defined(S)){kill S;} def S=re[2][j]; setring S; if(defined(interId)){kill interId;} //--- all components ideal interId=std(BO[4][mtuple[2]]+BO[5]); if(defined(myPts)){kill myPts;} ideal myPts=1; export(myPts); export(interId); if(defined(doneId)){kill doneId;} if(defined(donePts)){kill donePts;} ideal donePts=1; ideal doneId=1; for(k=2;k0) { chi_E[i][1]=chi_E[i][1]+(2-2*genus(pr[k])); } } myPts=sat(myPts,donePts)[1]; chi_E[i][1]=chi_E[i][1]-vdim(myPts); } } setring R; return(chi_E); } ////////////////////////////////////////////////////////////////////////////// static proc chi_ast(list re,list iden,list #) "Internal procedure - no help and no example available " { //--- compute the Euler characteristic of the Ei,Eij,Eijk and the //--- corresponding Ei^*,Eij^*,Eijk^* by preparing the input to the //--- specialized auxilliary procedures and then recombining the results //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- int i,j,k,g; intvec tiv; list chi_ijk,chi_ij,chi_i,ast_ijk,ast_ij,ast_i,tmplist,g_ij,emptylist; list leererSchnitt; def R=basering; ring Rhelp=0,@t,dp; setring R; //---------------------------------------------------------------------------- // first compute the chi(Eij) and at the same time // check whether E_i \cap E_j is empty // the formula is // chi_ij=2-2*genus(E_i \cap E_j) //---------------------------------------------------------------------------- if(size(#)>0) { "Entering chi_ast"; } for(i=1;i<=size(iden)-1;i++) { for(j=i+1;j<=size(iden);j++) { if(defined(blub)){kill blub;} def blub=chiEij(re,iden,intvec(i,j)); if(typeof(blub)=="int") { tmplist=intvec(i,j),blub; } else { leererSchnitt[size(leererSchnitt)+1]=intvec(i,j); tmplist=intvec(i,j),0; } chi_ij[size(chi_ij)+1]=tmplist; } } if(size(#)>0) { "chi_ij computed"; } //----------------------------------------------------------------------------- // compute chi(Eijk)=chi^*(Eijk) by counting the points in the intersection // chi_ijk=#(E_i \cap E_j \cap E_k) // ast_ijk=chi_ijk //----------------------------------------------------------------------------- for(i=1;i<=size(iden)-2;i++) { for(j=i+1;j<=size(iden)-1;j++) { for(k=j+1;k<=size(iden);k++) { if(inIVList(intvec(i,j),leererSchnitt)) { tmplist=intvec(i,j,k),0; } else { tmplist=intvec(i,j,k),countEijk(re,iden,intvec(i,j,k)); } chi_ijk[size(chi_ijk)+1]=tmplist; } } } ast_ijk=chi_ijk; if(size(#)>0) { "chi_ijk computed"; } //---------------------------------------------------------------------------- // construct chi(Eij^*) by the formula // ast_ij=chi_ij - sum_ijk chi_ijk, // where k runs over all indices != i,j //---------------------------------------------------------------------------- for(i=1;i<=size(chi_ij);i++) { ast_ij[i]=chi_ij[i]; for(k=1;k<=size(chi_ijk);k++) { if(((chi_ijk[k][1][1]==chi_ij[i][1][1])|| (chi_ijk[k][1][2]==chi_ij[i][1][1]))&& ((chi_ijk[k][1][2]==chi_ij[i][1][2])|| (chi_ijk[k][1][3]==chi_ij[i][1][2]))) { ast_ij[i][2]=ast_ij[i][2]-chi_ijk[k][2]; } } } if(size(#)>0) { "ast_ij computed"; } //---------------------------------------------------------------------------- // construct ast_i according to the following formulae // ast_i=0 if E_i is (Q- resp. C-)component of the strict transform // chi_i=3*n if E_i originates from blowing up a Q-point, // which consists of n (different) C-points // chi_i=2-2g(C) if E_i originates from blowing up a (Q-)curve C // (chi_i=n*(2-2g(C_i))=2-2g(C), // where C=\cup C_i, C_i \cap C_j = \emptyset) // if E_i is not a component of the strict transform, then // ast_i=chi_i - sum_{j!=i} ast_ij //---------------------------------------------------------------------------- for(i=1;i<=size(iden);i++) { if(defined(S)) {kill S;} def S=re[2][iden[i][1][1]]; setring S; if(iden[i][1][2]>size(BO[4])) { i--; break; } } list idenE=iden; while(size(idenE)>i) { idenE=delete(idenE,size(idenE)); } list cl=computeChiE(re,idenE); for(i=1;i<=size(idenE);i++) { chi_i[i]=list(intvec(i),cl[i][1]); } if(size(#)>0) { "chi_i computed"; } for(i=1;i<=size(idenE);i++) { ast_i[i]=chi_i[i]; for(j=1;j<=size(ast_ij);j++) { if((ast_ij[j][1][1]==i)||(ast_ij[j][1][2]==i)) { ast_i[i][2]=ast_i[i][2]-chi_ij[j][2]; } } for(j=1;j<=size(ast_ijk);j++) { if((ast_ijk[j][1][1]==i)||(ast_ijk[j][1][2]==i) ||(ast_ijk[j][1][3]==i)) { ast_i[i][2]=ast_i[i][2]+chi_ijk[j][2]; } } } for(i=size(idenE)+1;i<=size(iden);i++) { ast_i[i]=list(intvec(i),0); } //--- results are in ast_i, ast_ij and ast_ijk //--- all are of the form intvec(indices),int(value) list result=ast_i,ast_ij,ast_ijk; return(result); } ////////////////////////////////////////////////////////////////////////////// static proc chi_ast_local(list re,list iden,list #) "Internal procedure - no help and no example available " { //--- compute the Euler characteristic of the Ei,Eij,Eijk and the //--- corresponding Ei^*,Eij^*,Eijk^* by preparing the input to the //--- specialized auxilliary procedures and then recombining the results //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- int i,j,k,g; intvec tiv; list chi_ijk,chi_ij,chi_i,ast_ijk,ast_ij,ast_i,tmplist,g_ij,emptylist; list leererSchnitt; def R=basering; ring Rhelp=0,@t,dp; setring R; //---------------------------------------------------------------------------- // first compute // if E_i \cap E_j \cap \pi^-1(0) is a curve: // chi(Eij) and at the same time // check whether E_i \cap E_j is empty // the formula is // chi_ij=2-2*genus(E_i \cap E_j) // otherwise (points): // chi(E_ij) by counting the points //---------------------------------------------------------------------------- if(size(#)>0) { "Entering chi_ast_local"; } for(i=1;i<=size(iden)-1;i++) { for(j=i+1;j<=size(iden);j++) { if(defined(blub)){kill blub;} def blub=chiEij_local(re,iden,intvec(i,j)); if(typeof(blub)=="int") { tmplist=intvec(i,j),blub; } else { leererSchnitt[size(leererSchnitt)+1]=intvec(i,j); tmplist=intvec(i,j),0; } chi_ij[size(chi_ij)+1]=tmplist; } } if(size(#)>0) { "chi_ij computed"; } //----------------------------------------------------------------------------- // compute chi(Eijk)=chi^*(Eijk) by counting the points in the intersection // chi_ijk=#(E_i \cap E_j \cap E_k \cap \pi^-1(0)) // ast_ijk=chi_ijk //----------------------------------------------------------------------------- for(i=1;i<=size(iden)-2;i++) { for(j=i+1;j<=size(iden)-1;j++) { for(k=j+1;k<=size(iden);k++) { if(inIVList(intvec(i,j),leererSchnitt)) { tmplist=intvec(i,j,k),0; } else { tmplist=intvec(i,j,k),countEijk(re,iden,intvec(i,j,k),"local"); } chi_ijk[size(chi_ijk)+1]=tmplist; } } } ast_ijk=chi_ijk; if(size(#)>0) { "chi_ijk computed"; } //---------------------------------------------------------------------------- // construct chi(Eij^*) by the formula // ast_ij=chi_ij - sum_ijk chi_ijk, // where k runs over all indices != i,j //---------------------------------------------------------------------------- for(i=1;i<=size(chi_ij);i++) { ast_ij[i]=chi_ij[i]; for(k=1;k<=size(chi_ijk);k++) { if(((chi_ijk[k][1][1]==chi_ij[i][1][1])|| (chi_ijk[k][1][2]==chi_ij[i][1][1]))&& ((chi_ijk[k][1][2]==chi_ij[i][1][2])|| (chi_ijk[k][1][3]==chi_ij[i][1][2]))) { ast_ij[i][2]=ast_ij[i][2]-chi_ijk[k][2]; } } } if(size(#)>0) { "ast_ij computed"; } //---------------------------------------------------------------------------- // construct ast_i according to the following formulae // ast_i=0 if E_i is (Q- resp. C-)component of the strict transform // if E_i \cap \pi^-1(0) is of dimension 2: // chi_i=3*n if E_i originates from blowing up a Q-point, // which consists of n (different) C-points // chi_i=2-2g(C) if E_i originates from blowing up a (Q-)curve C // (chi_i=n*(2-2g(C_i))=2-2g(C), // where C=\cup C_i, C_i \cap C_j = \emptyset) // if E_i \cap \pi^-1(0) is a curve: // use the formula chi_i=2-2*genus(E_i \cap \pi^-1(0)) // // for E_i not a component of the strict transform we have // ast_i=chi_i - sum_{j!=i} ast_ij //---------------------------------------------------------------------------- for(i=1;i<=size(iden);i++) { if(defined(S)) {kill S;} def S=re[2][iden[i][1][1]]; setring S; if(iden[i][1][2]>size(BO[4])) { i--; break; } } list idenE=iden; while(size(idenE)>i) { idenE=delete(idenE,size(idenE)); } list cl=computeChiE_local(re,idenE); for(i=1;i<=size(cl);i++) { if(size(cl[i])==0) { cl[i][1]=0; } } for(i=1;i<=size(idenE);i++) { chi_i[i]=list(intvec(i),cl[i][1]); } if(size(#)>0) { "chi_i computed"; } for(i=1;i<=size(idenE);i++) { ast_i[i]=chi_i[i]; for(j=1;j<=size(ast_ij);j++) { if((ast_ij[j][1][1]==i)||(ast_ij[j][1][2]==i)) { ast_i[i][2]=ast_i[i][2]-chi_ij[j][2]; } } for(j=1;j<=size(ast_ijk);j++) { if((ast_ijk[j][1][1]==i)||(ast_ijk[j][1][2]==i) ||(ast_ijk[j][1][3]==i)) { ast_i[i][2]=ast_i[i][2]+chi_ijk[j][2]; } } } for(i=size(idenE)+1;i<=size(iden);i++) { ast_i[i]=list(intvec(i),0); } //--- results are in ast_i, ast_ij and ast_ijk //--- all are of the form intvec(indices),int(value) //"End of chi_ast_local"; //~; list result=ast_i,ast_ij,ast_ijk; return(result); } ////////////////////////////////////////////////////////////////////////////// proc discrepancy(list re) "USAGE: discrepancy(L); @* L = list of rings ASSUME: L is the output of resolution of singularities RETRUN: discrepancies of the given resolution" { //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- def R=basering; int i,j; list iden=prepEmbDiv(re); //--- identify the E_i intvec Vvec=computeV(re,iden); //--- nu intvec Nvec=computeN(re,iden); //--- N intvec Avec; //--- only look at exceptional divisors, not at strict transform for(i=1;i<=size(iden);i++) { if(defined(S)) {kill S;} def S=re[2][iden[i][1][1]]; setring S; if(iden[i][1][2]>size(BO[4])) { i--; break; } } j=i; //--- discrepancies are a_i=nu_i-N_i for(i=1;i<=j;i++) { Avec[i]=Vvec[i]-Nvec[i]-1; } return(Avec); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal I=x2+y2+z3; list re=resolve(I); discrepancy(re); } ////////////////////////////////////////////////////////////////////////////// proc zetaDL(list re,int d,list #) "USAGE: zetaDL(L,d[,s1][,s2][,a]); L = list of rings; d = integer; s1,s2 = string; a = integer ASSUME: L is the output of resolution of singularities COMPUTE: local Denef-Loeser zeta function, if string s1 is present and has the value 'local'; global Denef-Loeser zeta function otherwise if string s1 or s2 has the value "A", additionally the characteristic polynomial of the monodromy is computed RETURN: list l if a is not present: l[1]: string specifying the top. zeta function l[2]: string specifying characteristic polynomial of monodromy, if "A" was specified if a is present: l[1]: string specifying the top. zeta function l[2]: list ast, ast[1]=chi(Ei^*) ast[2]=chi(Eij^*) ast[3]=chi(Eijk^*) l[3]: intvec nu of multiplicites as needed in computation of zeta function l[4]: intvec N of multiplicities as needed in compuation of zeta function l[5]: string specifying characteristic polynomial of monodromy, if "A" was specified EXAMPLE: example zetaDL; shows an example " { //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- def R=basering; int show_all,i; if(size(#)>0) { if((typeof(#[1])=="int")||(size(#)>2)) { show_all=1; } if(typeof(#[1])=="string") { if((#[1]=="local")||(#[1]=="lokal")) { // ERROR("Local case not implemented yet"); "Local Case: Assuming that no (!) charts were dropped"; "during calculation of the resolution (option \"A\")"; int localComp=1; if(size(#)>1) { if(#[2]=="A") { int aCampoFormula=1; } } } else { if(#[1]=="A") { int aCampoFormula=1; } "Computing global zeta function"; } } } //---------------------------------------------------------------------------- // Identify the embedded divisors and chi(Ei^*), chi(Eij^*) and chi(Eijk^*) // as well as the integer vector V(=nu) and N //---------------------------------------------------------------------------- list iden=prepEmbDiv(re); //--- identify the E_i //!!! TIMING: E8 takes 520 sec ==> needs speed up if(!defined(localComp)) { list ast_list=chi_ast(re,iden); //--- compute chi(E^*) } else { list ast_list=chi_ast_local(re,iden); } intvec Vvec=computeV(re,iden); //--- nu intvec Nvec=computeN(re,iden); //--- N //---------------------------------------------------------------------------- // Build a new ring with one parameter s // and compute Zeta_top^(d) in its ground field //---------------------------------------------------------------------------- ring Qs=(0,s),x,dp; number zetaTop=0; number enum,denom; denom=1; for(i=1;i<=size(Nvec);i++) { denom=denom*(Vvec[i]+s*Nvec[i]); } //--- factors for which index set J consists of one element //--- (do something only if d divides N_j) for(i=1;i<=size(ast_list[1]);i++) { if((((Nvec[ast_list[1][i][1][1]] div d)*d)-Nvec[ast_list[1][i][1][1]]==0)&& (ast_list[1][i][2]!=0)) { enum=enum+ast_list[1][i][2]*(denom/(Vvec[ast_list[1][i][1][1]]+s*Nvec[ast_list[1][i][1][1]])); } } //--- factors for which index set J consists of two elements //--- (do something only if d divides both N_i and N_j) //!!! TIMING: E8 takes 690 sec and has 703 elements //!!! ==> need to implement a smarter way to do this //!!! e.g. build up enumerator and denominator separately, thus not //!!! searching for common factors in each step for(i=1;i<=size(ast_list[2]);i++) { if((((Nvec[ast_list[2][i][1][1]] div d)*d)-Nvec[ast_list[2][i][1][1]]==0)&& (((Nvec[ast_list[2][i][1][2]] div d)*d)-Nvec[ast_list[2][i][1][2]]==0)&& (ast_list[2][i][2]!=0)) { enum=enum+ast_list[2][i][2]*(denom/((Vvec[ast_list[2][i][1][1]]+s*Nvec[ast_list[2][i][1][1]])*(Vvec[ast_list[2][i][1][2]]+s*Nvec[ast_list[2][i][1][2]]))); } } //--- factors for which index set J consists of three elements //--- (do something only if d divides N_i, N_j and N_k) //!!! TIMING: E8 takes 490 sec and has 8436 elements //!!! ==> same kind of improvements as in the previous case needed for(i=1;i<=size(ast_list[3]);i++) { if((((Nvec[ast_list[3][i][1][1]] div d)*d)-Nvec[ast_list[3][i][1][1]]==0)&& (((Nvec[ast_list[3][i][1][2]] div d)*d)-Nvec[ast_list[3][i][1][2]]==0)&& (((Nvec[ast_list[3][i][1][3]] div d)*d)-Nvec[ast_list[3][i][1][3]]==0)&& (ast_list[3][i][2]!=0)) { enum=enum+ast_list[3][i][2]*(denom/((Vvec[ast_list[3][i][1][1]]+s*Nvec[ast_list[3][i][1][1]])*(Vvec[ast_list[3][i][1][2]]+s*Nvec[ast_list[3][i][1][2]])*(Vvec[ast_list[3][i][1][3]]+s*Nvec[ast_list[3][i][1][3]]))); } } zetaTop=enum/denom; zetaTop=numerator(zetaTop)/denominator(zetaTop); string zetaStr=string(zetaTop); if(show_all) { list result=zetaStr,ast_list[1],ast_list[2],ast_list[3],Vvec,Nvec; } else { list result=zetaStr; } //--- compute characteristic polynomial of the monodromy //--- by the A'Campo formula if(defined(aCampoFormula)) { poly charP=1; for(i=1;i<=size(ast_list[1]);i++) { charP=charP*((s^Nvec[i]-1)^ast_list[1][i][2]); } string charPStr=string(charP/(s-1)); result[size(result)+1]=charPStr; } setring R; return(result); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal I=x2+y2+z3; list re=resolve(I,"K"); zetaDL(re,1); I=(xz+y2)*(xz+y2+x2)+z5; list L=resolve(I,"K"); zetaDL(L,1); //===== expected zeta function ========= // (20s^2+130s+87)/((1+s)*(3+4s)*(29+40s)) //====================================== } ////////////////////////////////////////////////////////////////////////////// proc abstractR(list re) "USAGE: abstractR(L); @* L = list of rings ASSUME: L is output of resolution of singularities NOTE: currently only implemented for isolated surface singularities RETURN: list l l[1]: intvec, where l[1][i]=1 if the corresponding ring is a final chart of non-embedded resolution l[1][i]=0 otherwise l[2]: intvec, where l[2][i]=1 if the corresponding ring does not occur in the non-embedded resolution l[2][i]=0 otherwise l[3]: list L EXAMPLE: example abstractR; shows an example " { //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- def R=basering; //---Test whether we are in the irreducible surface case def S=re[2][1]; setring S; BO[2]=BO[2]+BO[1]; if(dim(std(BO[2]))!=2) { ERROR("NOT A SURFACE"); } if(dim(std(slocus(BO[2])))>0) { ERROR("NOT AN ISOLATED SINGULARITY"); } setring R; int i,j,k,l,i0; intvec deleted; intvec endiv; endiv[size(re[2])]=0; deleted[size(re[2])]=0; //----------------------------------------------------------------------------- // run through all rings, only consider final charts // for each final chart follow the list of charts leading up to it until // we encounter a chart which is not finished in the non-embedded case //----------------------------------------------------------------------------- for(i=1;i<=size(re[2]);i++) { if(defined(S)){kill S;} def S=re[2][i]; setring S; if(size(reduce(cent,std(BO[2]+BO[1])))!=0) { //--- only consider endrings i++; continue; } i0=i; for(j=ncols(path);j>=2;j--) { //--- walk backwards through history if(j==2) { endiv[i0]=1; break; } k=int(leadcoef(path[1,j])); if((deleted[k]==1)||(endiv[k]==1)) { deleted[i0]=1; break; } if(defined(SPa)){kill SPa;} def SPa=re[2][k]; setring SPa; l=int(leadcoef(path[1,ncols(path)])); if(defined(SPa2)){kill SPa2;} def SPa2=re[2][l]; setring SPa2; if((deleted[l]==1)||(endiv[l]==1)) { //--- parent was already treated via different final chart //--- we may safely inherit the data deleted[i0]=1; setring S; i0=k; j--; continue; } setring SPa; //!!! Idea of Improvement: //!!! BESSER: rueckwaerts gehend nur testen ob glatt //!!! danach vorwaerts bis zum ersten Mal abstractNC //!!! ACHTUNG: rueckweg unterwegs notieren - wir haben nur vergangenheit! if((deg(std(slocus(BO[2]))[1])!=0)||(!abstractNC(BO))) { //--- not finished in the non-embedded case endiv[i0]=1; break; } //--- unnecessary chart in non-embedded case setring S; deleted[i0]=1; i0=k; } } //----------------------------------------------------------------------------- // Clean up the intvec deleted and return the result //----------------------------------------------------------------------------- setring R; for(i=1;i<=size(endiv);i++) { if(endiv[i]==1) { if(defined(S)) {kill S;} def S=re[2][i]; setring S; for(j=3;j0) { //--- we are not interested in the strict transform of X return(iden); } //---------------------------------------------------------------------------- // Run through all final charts and collect and identify all components of // the strict transform //---------------------------------------------------------------------------- //--- first final chart - to be used for initialization def S=re[2][iden0[size(iden0)][1][1]]; setring S; ncomps=size(EList)-size(BO[4]); if((ncomps==1)&&(deg(std(EList[size(EList)])[1])==0)) { ncomps=0; } offset=size(BO[4]); for(i=1;i<=ncomps;i++) { //--- add components of strict transform tmpList[1]=intvec(iden0[size(iden0)][1][1],size(BO[4])+i); iden[size(iden)+1]=tmpList; } //--- now run through the other final charts for(i=2;i<=size(iden0[size(iden0)]);i++) { if(defined(S2)){kill S2;} def S2=re[2][iden0[size(iden0)][i][1]]; setring S2; //--- determine common parent of this ring and re[2][iden0[size(iden0)][1][1]] if(defined(opath)){kill opath;} def opath=imap(S,path); j=1; while(opath[1,j]==path[1,j]) { j++; if((j>ncols(path))||(j>ncols(opath))) break; } if(defined(li1)){kill li1;} list li1; //--- fetch the components we have considered in //--- re[2][iden0[size(iden0)][1][1]] //--- via the resolution tree for(k=1;k<=ncomps;k++) { if(defined(id1)){kill id1;} string tempstr="EList["+string(eval(k+offset))+"]"; ideal id1=fetchInTree(re,iden0[size(iden0)][1][1], int(leadcoef(path[1,j-1])), iden0[size(iden0)][i][1],tempstr,iden0,1); kill tempstr; li1[k]=id1; kill id1; } //--- do the comparison for(k=size(BO[4])+1;k<=size(EList);k++) { //--- only components of the strict transform are interesting if((size(BO[4])+1==size(EList))&&(deg(std(EList[size(EList)])[1])==0)) { break; } found=0; for(j=1;j<=size(li1);j++) { if((size(reduce(li1[j],std(EList[k])))==0)&& (size(reduce(EList[k],std(li1[j])))==0)) { //--- found a match li1[j]=ideal(1); iden[size(iden0)-1+j][size(iden[size(iden0)-1+j])+1]= intvec(iden0[size(iden0)][i][1],k); found=1; break; } } if(!found) { //--- no match yet, maybe there are entries not corresponding to the //--- initialization of the list -- collected in list repair if(!defined(repair)) { //--- no entries in repair, we add the very first one list repair; repair[1]=list(intvec(iden0[size(iden0)][i][1],k)); } else { //--- compare against repair, and add the item appropriately //--- steps of comparison as before for(c=1;c<=size(repair);c++) { for(d=1;d<=size(repair[c]);d++) { if(defined(opath)) {kill opath;} def opath=imap(re[2][repair[c][d][1]],path); b=0; while(path[1,b+1]==opath[1,b+1]) { b++; if((b>ncols(path)-1)||(b>ncols(opath)-1)) break; } b=int(leadcoef(path[1,b])); string tempstr="EList["+string(eval(repair[c][d][2])) +"]"; if(defined(id1)){kill id1;} ideal id1=fetchInTree(re,repair[c][d][1],b, iden0[size(iden0)][i][1],tempstr,iden0,1); kill tempstr; if((size(reduce(EList[k],std(id1)))==0)&& (size(reduce(id1,std(EList[k])))==0)) { repair[c][size(repair[c])+1]=intvec(iden0[size(iden0)][i][1],k); break; } } if(d<=size(repair[c])) { break; } } if(c>size(repair)) { repair[size(repair)+1]=list(intvec(iden0[size(iden0)][i][1],k)); } } } } } if(defined(repair)) { //--- there were further components, add them for(c=1;c<=size(repair);c++) { iden[size(iden)+1]=repair[c]; } kill repair; } //--- up to now only Q-irred components - not C-irred components !!! return(iden); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal I=x2+y2+z11; list L=resolve(I); prepEmbDiv(L); } /////////////////////////////////////////////////////////////////////////////// static proc decompEinX(list BO) "Internal procedure - no help and no example available " { //--- decomposition of exceptional divisor, non-embedded resolution. //--- even a single exceptional divisor may be Q-reducible when considered //--- as divisor on the strict transform //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- int i,j,k,de,contact; intmat interMat; list dcE,tmpList,prList,sa,nullList; string mpol,compList; def R=basering; ideal I; //---------------------------------------------------------------------------- // pass to divisors on V(J) and throw away components already present as // previous exceptional divisors //---------------------------------------------------------------------------- for(i=1;i<=size(BO[4]);i++) { I=BO[4][i]+BO[2]; for(j=i+1;j<=size(BO[4]);j++) { sa=sat(I,BO[4][j]+BO[2]); if(sa[2]) { I=sa[1]; } } //!!! Practical improvement - not yet implemented: //!!!hier den Input besser aufbereiten (cf. J. Wahl's example) //!!!I[1]=x(2)^15*y(2)^9+3*x(2)^10*y(2)^6+3*x(2)^5*y(2)^3+x(2)+1; //!!!I[2]=x(2)^8*y(2)^6+y(0); //!!!heuristisch die Ordnung so waehlen, dass y(0) im Prinzip eliminiert //!!!wird. //----------------------------------------------------------------------------- // 1) decompose exceptional divisor (over Q) // 2) check whether there are C-reducible Q-components // 3) if necessary, find appropriate field extension of Q to decompose // 4) in each chart collect information in list dcE and export it //----------------------------------------------------------------------------- prList=primdecGTZ(I); for(j=1;j<=size(prList);j++) { tmpList=grad(prList[j][2]); de=tmpList[1]; interMat=tmpList[2]; mpol=tmpList[3]; compList=tmpList[4]; nullList=tmpList[5]; contact=Kontakt(prList[j][1],BO[2]); tmpList=prList[j][2],de,contact,interMat,mpol,compList,nullList; prList[j]=tmpList; } dcE[i]=prList; } return(dcE); } ////////////////////////////////////////////////////////////////////////////// static proc getMinpoly(poly p) "Internal procedure - no help and no example available " { //---assume that p is a polynomial in 2 variables and irreducible //---over Q. Computes an irreducible polynomial mp in one variable //---over Q such that p splits completely over the splitting field of mp //---returns mp as a string //---use a variant of the algorithm of S. Gao def R=basering; int i,j,k,a,b,m,n; intvec v; string mp="poly p=t-1;"; list Li=string(1); list re=mp,Li,1; //---check which variables occur in p for(i=1;i<=nvars(basering);i++) { if(p!=subst(p,var(i),0)){v[size(v)+1]=i;} } //---the polynomial is constant if(size(v)==1){return(re);} //---the polynomial depends only on one variable or is homogeneous //---in 2 variables if((size(v)==2)||((size(v)==3)&&(homog(p)))) { if((size(v)==3)&&(homog(p))) { p=subst(p,var(v[3]),1); } ring Rhelp=0,var(v[2]),dp; poly p=imap(R,p); ring Shelp=0,t,dp; poly p=fetch(Rhelp,p); int de=deg(p); p=simplifyMinpoly(p); Li=getNumZeros(p); short=0; mp="poly p="+string(p)+";"; re=mp,Li,de; setring R; return(re); } v=v[2..size(v)]; if(size(v)>2){ERROR("getMinpoly:input depends on more then 2 variables");} //---the general case, the polynomial is considered as polynomial in x an y now ring T=0,(x,y),lp; ideal M,N; M[nvars(R)]=0; N[nvars(R)]=0; M[v[1]]=x; N[v[1]]=y; M[v[2]]=y; N[v[2]]=x; map phi=R,M; map psi=R,N; poly p=phi(p); poly q=psi(p); ring Thelp=(0,x),y,dp; poly p=imap(T,p); poly q=imap(T,q); n=deg(p); //---the degree with respect to y m=deg(q); //---the degree with respect to x setring T; ring A=0,(u(1..m*(n+1)),v(1..(m+1)*n),x,y,t),dp; poly f=imap(T,p); poly g; poly h; for(i=0;i<=m-1;i++) { for(j=0;j<=n;j++) { g=g+u(i*(n+1)+j+1)*x^i*y^j; } } for(i=0;i<=m;i++) { for(j=0;j<=n-1;j++) { h=h+v(i*n+j+1)*x^i*y^j; } } poly L=f*(diff(g,y)-diff(h,x))+h*diff(f,x)-g*diff(f,y); //---according to the theory f is absolutely irreducible if and only if //---L(g,h)=0 has no non-trivial solution g,h //---(g=diff(f,x),h=diff(f,y) is always a solution) //---therefore we compute a vector space basis of G //---G={g in Q[x,y],deg_x(g)) //---according to the theory f=product over all c in C of the //---gcd(f,g-c*diff(f,x)) //---let g_1,...,g_a be a basis of G and write //---g*g_i=sum a_ij*g_j*diff(f,x) mod f //---let B=(a_ij) and ch=det(t*unitmat(a)-B) the characteristic //---polynomial then the number of distinct irreducible factors //---of gcd(f,g-c*diff(f,x)) in C[x,y] is equal to the multiplicity //---of c as a root of ch. //---in our special situation (f is irreducible over Q) ch should //---be irreducible and the different roots of ch lead to the //---factors of f, i.e. ch is the minpoly we are looking for poly fh=homog(f,t); //---homogenization is used to obtain a constant matrix using lift ideal Gh=homog(G,t); int dh,df; df=deg(fh); for(i=1;i<=a;i++) { if(deg(Gh[i])>dh){dh=deg(Gh[i]);} } for(i=1;i<=a;i++) { Gh[i]=t^(dh-deg(Gh[i]))*Gh[i]; } ideal GF=simplify(diff(fh,x),1)*Gh,fh; poly ch; matrix LI; matrix B[a][a]; matrix E=unitmat(a); poly gran; ideal fac; for(i=1;i<=a;i++) { LI=lift(GF,t^(df-1-dh)*Gh[i]*Gh); B=LI[1..a,1..a]; ch=det(t*E-B); //---irreducibility test fac=factorize(ch,1); if(deg(fac[1])==a) { ch=simplifyMinpoly(ch); Li=getNumZeros(ch); int de=deg(ch); short=0; mp="poly p="+string(ch)+";"; re=mp,Li,de; setring R; return(re); } } ERROR("getMinpoly:not found:please send the example to the authors"); } ////////////////////////////////////////////////////////////////////////////// static proc getNumZeros(poly p) "Internal procedure - no help and no example available " { //--- compute numerically (!!!) the zeros of the minimal polynomial def R=basering; ring S=0,t,dp; poly p=imap(R,p); def L=laguerre_solve(p,30); //!!! practical improvement: //!!! testen ob die Nullstellen signifikant verschieden sind //!!! und im Notfall Genauigkeit erhoehen list re; int i; for(i=1;i<=size(L);i++) { re[i]=string(L[i]); } setring R; return(re); } ////////////////////////////////////////////////////////////////////////////// static proc simplifyMinpoly(poly p) "Internal procedure - no help and no example available " { //--- describe field extension in a simple way p=cleardenom(p); int n=int(leadcoef(p)); int d=deg(p); int i,k; int re=1; number s=1; list L=primefactors(n); for(i=1;i<=size(L[1]);i++) { k=L[2][i] mod d; s=1/number((L[1][i])^(L[2][i] div d)); if(!k){p=subst(p,t,s*t);} } p=cleardenom(p); n=int(leadcoef(subst(p,t,0))); L=primefactors(n); for(i=1;i<=size(L[1]);i++) { k=L[2][i] mod d; s=(L[1][i])^(L[2][i] div d); if(!k){p=subst(p,t,s*t);} } p=cleardenom(p); return(p); } /////////////////////////////////////////////////////////////////////////////// static proc grad(ideal I) "Internal procedure - no help and no example available " { //--- computes the number of components over C //--- for a prime ideal of height 1 over Q def R=basering; int n=nvars(basering); string mp="poly p=t-1;"; string str=string(1); list zeroList=string(1); int i,j,k,l,d,e,c,mi; ideal Istd=std(I); intmat interMat; d=dim(Istd); if(d==-1){return(list(0,0,mp,str,zeroList));} if(d!=1){ERROR("ideal is not one-dimensional");} ideal Sloc=std(slocus(I)); if(deg(Sloc[1])>0) { //---This is only to test that in case of singularities we have only //---one singular point which is a normal crossing //---consider the different singular points ideal M; list pr=minAssGTZ(Sloc); if(size(pr)>1){ERROR("grad:more then one singular point");} for(l=1;l<=size(pr);l++) { M=std(pr[l]); d=vdim(M); if(d!=1) { //---now we have to extend the field if(defined(S)){kill S;} ring S=0,x(1..n),lp; ideal M=fetch(R,M); ideal I=fetch(R,I); ideal jmap; map phi=S,maxideal(1);; ideal Mstd=std(M); //---M has to be in general position with respect to lp, i.e. //---vdim(M)=deg(M[1]) poly p=Mstd[1]; e=vdim(Mstd); while(e!=deg(p)) { jmap=randomLast(100); phi=S,jmap; Mstd=std(phi(M)); p=Mstd[1]; } I=phi(I); kill phi; //---now it is in general position an M[1] defines the field extension //---Q[x]/M over Q ring Shelp=0,t,dp; ideal helpmap; helpmap[n]=t; map psi=S,helpmap; poly p=psi(p); ring T=(0,t),x(1..n),lp; poly p=imap(Shelp,p); //---we are now in the polynomial ring over the field Q[x]/M minpoly=leadcoef(p); ideal M=imap(S,Mstd); M=M,var(n)-t; ideal I=fetch(S,I); } //---we construct a map phi which maps M to maxideal(1) option(redSB); ideal Mstd=-simplify(std(M),1); option(noredSB); for(i=1;i<=n;i++) { Mstd=subst(Mstd,var(i),-var(i)); M[n-i+1]=Mstd[i]; } M=M[1..n]; //---go to the localization with respect to if(d!=1) { ring Tloc=(0,t),x(1..n),ds; poly p=imap(Shelp,p); minpoly=leadcoef(p); ideal M=fetch(T,M); map phi=T,M; } else { ring Tloc=0,x(1..n),ds; ideal M=fetch(R,M); map phi=R,M; } ideal I=phi(I); ideal Istd=std(I); mi=mi+milnor(Istd); if(mi>l) { ERROR("grad:divisor is really singular"); } setring R; } } intvec ind=indepSet(Istd,1)[1]; for(i=1;i<=n;i++){if(ind[i]) break;} //---the i-th variable is the independent one ring Shelp=0,x(1..n),dp; ideal I=fetch(R,I); if(defined(S)){kill S;} if(i==1){ring S=(0,x(1)),x(2..n),lp;} if(i==n){ring S=(0,x(n)),x(1..n-1),lp;} if((i!=1)&&(i!=n)){ring S=(0,x(i)),(x(1..i-1),x(i+1..n)),lp;} //---I is zero-dimensional now ideal I=imap(Shelp,I); ideal Istd=std(I); ideal jmap; map phi; poly p=Istd[1]; e=vdim(Istd); if(e==1) { setring R; str=string(I); list resi=1,interMat,mp,str,zeroList; return(resi); } //---move I to general position with respect to lp if(e!=deg(p)) { jmap=randomLast(5); phi=S,jmap; Istd=std(phi(I)); p=Istd[1]; } while(e!=deg(p)) { jmap=randomLast(100); phi=S,jmap; Istd=std(phi(I)); p=Istd[1]; } setring Shelp; poly p=imap(S,p); list Q=getMinpoly(p); int de=Q[3]; mp=Q[1]; //!!!diese Stelle effizienter machen //!!!minAssGTZ vermeiden durch direkte Betrachtung von //!!!p und mp und evtl. Quotientenbildung //!!!bisher nicht zeitkritisch string Tesr="ring Tes=(0,t),("+varstr(R)+"),dp;"; execute(Tesr); execute(mp); minpoly=leadcoef(p); ideal I=fetch(R,I); list pr=minAssGTZ(I); ideal allgEbene=randomLast(100)[nvars(basering)]; int minpts=vdim(std(I+allgEbene)); ideal tempi; j=1; for(i=1;i<=size(pr);i++) { tempi=std(pr[i]+allgEbene); if(vdim(tempi), ai in a field //---extension of Q, containing I+K and an integer a //---such that in the localization of the polynomial ring with //---respect to M the ideal I is not contained in K+M^a+1 but in M^a in def R=basering; int n=nvars(basering); int i,j,k,d,e; ideal J=std(I+K); if(dim(J)==-1){return(0);} ideal W; //---choice of the maximal ideal M for(i=1;i<=n;i++) { W=std(J,var(i)); d=dim(W); if(d==0) break; } i=1;k=2; while((d)&&(i if(d!=1) { ring Tloc=(0,t),x(1..n),ds; poly p=imap(Shelp,p); minpoly=leadcoef(p); ideal M=fetch(T,M); map phi=T,M; } else { ring Tloc=0,x(1..n),ds; ideal M=fetch(R,M); map phi=R,M; } ideal K=phi(K); ideal I=phi(I); //---compute the order of I in (Q[x]/M)[[x]]/K k=1;d=0; while(!d) { k++; d=size(reduce(I,std(maxideal(k)+K))); } setring R; return(k-1); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; ideal I=x4+z4+1; ideal K=x+y2+z2; Kontakt(I,K); } ////////////////////////////////////////////////////////////////////////////// static proc abstractNC(list BO) "Internal procedure - no help and no example available " { //--- check normal crossing property //--- used for passing from embedded to non-embedded resolution //---------------------------------------------------------------------------- // Initialization //---------------------------------------------------------------------------- int i,k,j,flag; list L; ideal J; if(dim(std(cent))>0){return(1);} //---------------------------------------------------------------------------- // check each exceptional divisor on V(J) //---------------------------------------------------------------------------- for(i=1;i<=size(BO[4]);i++) { if(dim(std(BO[2]+BO[4][i]))>0) { //--- really something to do J=radical(BO[4][i]+BO[2]); if(deg(std(slocus(J))[1])!=0) { if(!nodes(J)) { //--- really singular, not only nodes ==> not normal crossing return(0); } } for(k=1;k<=size(L);k++) { //--- run through previously considered divisors //--- we do not want to bother with the same one twice if((size(reduce(J,std(L[k])))==0)&&(size(reduce(L[k],std(J)))==0)) { //--- already considered this one flag=1;break; } //--- drop previously considered exceptional divisors from the current one J=sat(J,L[k])[1]; if(deg(std(J)[1])==0) { //--- nothing remaining flag=1;break; } } if(flag==0) { //--- add exceptional divisor to the list L[size(L)+1]=J; } flag=0; } } //--------------------------------------------------------------------------- // check intersection properties between different exceptional divisors //--------------------------------------------------------------------------- for(k=1;k not normal crossing return(0); } for(j=i+1;j<=size(L);j++) { if(deg(std(L[i]+L[j]+L[k])[1])>0) { //--- three divisors meet simultaneously ==> not normal crossing return(0); } } } } //--- we reached this point ==> normal crossing return(1); } ////////////////////////////////////////////////////////////////////////////// static proc nodes(ideal J) "Internal procedure - no help and no example available " { //--- check whether at most nodes occur as singularities ideal K=std(slocus(J)); if(deg(K[1])==0){return(1);} if(dim(K)>0){return(0);} if(vdim(K)!=vdim(std(radical(K)))){return(0);} return(1); } ////////////////////////////////////////////////////////////////////////////// proc intersectionDiv(list re) "USAGE: intersectionDiv(L); @* L = list of rings ASSUME: L is output of resolution of singularities (only case of isolated surface singularities) COMPUTE: intersection matrix and genera of the exceptional divisors (considered as curves on the strict transform) RETURN: list l, where l[1]: intersection matrix of exceptional divisors l[2]: intvec, genera of exceptional divisors l[3]: divisorList, encoding the identification of the divisors EXAMPLE: example intersectionDiv; shows an example " { //---------------------------------------------------------------------------- //--- Computes in case of surface singularities (non-embedded resolution): //--- the intersection of the divisors (on the surface) //--- assuming that re=resolve(J) //---------------------------------------------------------------------------- def R=basering; //---Test whether we are in the irreducible surface case def S=re[2][1]; setring S; BO[2]=BO[2]+BO[1]; // make sure we are living in the smooth W if(dim(std(BO[2]))!=2) { ERROR("The given original object is not a surface"); } if(dim(std(slocus(BO[2])))>0) { ERROR("The given original object has non-isolated singularities."); } setring R; //---------------------------------------------------------------------------- // Compute a non-embedded resolution from the given embedded one by // dropping redundant trailing blow-ups //---------------------------------------------------------------------------- list resu,tmpiden,templist; intvec divcomp; int i,j,k,offset1,offset2,a,b,c,d,q,found; //--- compute non-embedded resolution list abst=abstractR(re); intvec endiv=abst[1]; intvec deleted=abst[2]; //--- identify the divisors in the various final charts list iden=collectDiv(re,deleted)[2]; // list of final divisors list iden0=iden; // backup copy of iden for later use iden=delete(iden,size(iden)); // drop list of endRings from iden //--------------------------------------------------------------------------- // In iden, only the final charts should be listed, whereas iden0 contains // everything. //--------------------------------------------------------------------------- for(i=1;i<=size(iden);i++) { k=size(iden[i]); tmpiden=iden[i]; for(j=k;j>0;j--) { if(!endiv[iden[i][j][1]]) { //---not a final chart tmpiden=delete(tmpiden,j); } } if(size(tmpiden)==0) { //--- oops, this divisor does not appear in final charts iden=delete(iden,i); continue; } else { iden[i]=tmpiden; } } //--------------------------------------------------------------------------- // Even though the exceptional divisors were irreducible in the embedded // case, they may very well have become reducible after intersection with // the strict transform of the original object. // ===> compute a decomposition for each divisor in each of the final charts // and change the entries of iden accordingly // In particular, it is important to keep track of the identification of the // components of the divisors in each of the charts //--------------------------------------------------------------------------- int n=size(iden); for(i=1;i<=size(re[2]);i++) { if(endiv[i]) { def SN=re[2][i]; setring SN; if(defined(dcE)){kill dcE;} list dcE=decompEinX(BO); // decomposition of exceptional divisors export(dcE); setring R; kill SN; } } if(defined(tmpiden)){kill tmpiden;} list tmpiden=iden; for(i=1;i<=size(iden);i++) { for(j=size(iden[i]);j>0;j--) { def SN=re[2][iden[i][j][1]]; setring SN; if(size(dcE[iden[i][j][2]])==1) { if(dcE[iden[i][j][2]][1][2]==0) { tmpiden[i]=delete(tmpiden[i],j); } } setring R; kill SN; } } for(i=size(tmpiden);i>0;i--) { if(size(tmpiden[i])==0) { tmpiden=delete(tmpiden,i); } } iden=tmpiden; kill tmpiden; list tmpiden; //--- change entries of iden accordingly for(i=1;i<=size(iden);i++) { //--- first set up new entries in iden if necessary - using the first chart //--- in which we see the respective exceptional divisor if(defined(S)){kill S;} def S=re[2][iden[i][1][1]]; //--- considering first entry for i-th divisor setring S; a=size(dcE[iden[i][1][2]]); for(j=1;j<=a;j++) { //--- reducible - add to the list considering each component as an exceptional //--- divisor in its own right list tl; tl[1]=intvec(iden[i][1][1],iden[i][1][2],j); tmpiden[size(tmpiden)+1]=tl; kill tl; } //--- now identify the components in the other charts w.r.t. the ones in the //--- first chart which have already been added to the list for(j=2;j<=size(iden[i]);j++) { //--- considering remaining entries for the same original divisor if(defined(S2)){kill S2;} def S2=re[2][iden[i][j][1]]; setring S2; //--- determine common parent of this ring and re[2][iden[i][1][1]] if(defined(opath)){kill opath;} def opath=imap(S,path); b=1; while(opath[1,b]==path[1,b]) { b++; if((b>ncols(path))||(b>ncols(opath))) break; } if(defined(li1)){kill li1;} list li1; //--- fetch the components we have considered in re[2][iden[i][1][1]] //--- via the resolution tree for(k=1;k<=a;k++) { string tempstr="dcE["+string(eval(iden[i][1][2]))+"]["+string(k)+"][1]"; if(defined(id1)){kill id1;} ideal id1=fetchInTree(re,iden[i][1][1],int(leadcoef(path[1,b-1])), iden[i][j][1],tempstr,iden0,1); kill tempstr; li1[k]=radical(id1); // for comparison only the geometric // object matters kill id1; } //--- compare the components we have fetched with the components in the //--- current ring for(k=1;k<=size(dcE[iden[i][j][2]]);k++) { found=0; for(b=1;b<=size(li1);b++) { if((size(reduce(li1[b],std(dcE[iden[i][j][2]][k][1])))==0)&& (size(reduce(dcE[iden[i][j][2]][k][1],std(li1[b]+BO[2])))==0)) { li1[b]=ideal(1); tmpiden[size(tmpiden)-a+b][size(tmpiden[size(tmpiden)-a+b])+1]= intvec(iden[i][j][1],iden[i][j][2],k); found=1; break; } } if(!found) { if(!defined(repair)) { list repair; repair[1]=list(intvec(iden[i][j][1],iden[i][j][2],k)); } else { for(c=1;c<=size(repair);c++) { for(d=1;d<=size(repair[c]);d++) { if(defined(opath)) {kill opath;} def opath=imap(re[2][repair[c][d][1]],path); q=0; while(path[1,q+1]==opath[1,q+1]) { q++; if((q>ncols(path)-1)||(q>ncols(opath)-1)) break; } q=int(leadcoef(path[1,q])); string tempstr="dcE["+string(eval(repair[c][d][2]))+"]["+string(eval(repair[c][d][3]))+"][1]"; if(defined(id1)){kill id1;} ideal id1=fetchInTree(re,repair[c][d][1],q, iden[i][j][1],tempstr,iden0,1); kill tempstr; //!!! sind die nicht schon radical? id1=radical(id1); // for comparison // only the geometric // object matters if((size(reduce(dcE[iden[i][j][2]][k][1],std(id1+BO[2])))==0)&& (size(reduce(id1+BO[2],std(dcE[iden[i][j][2]][k][1])))==0)) { repair[c][size(repair[c])+1]=intvec(iden[i][j][1],iden[i][j][2],k); break; } } if(d<=size(repair[c])) { break; } } if(c>size(repair)) { repair[size(repair)+1]=list(intvec(iden[i][j][1],iden[i][j][2],k)); } } } } } if(defined(repair)) { for(c=1;c<=size(repair);c++) { tmpiden[size(tmpiden)+1]=repair[c]; } kill repair; } } setring R; for(i=size(tmpiden);i>0;i--) { if(size(tmpiden[i])==0) { tmpiden=delete(tmpiden,i); continue; } } iden=tmpiden; // store the modified divisor list kill tmpiden; // and clean up temporary objects //--------------------------------------------------------------------------- // Now we have decomposed everything into irreducible components over Q, // but over C there might still be some reducible ones left: // Determine the number of components over C. //--------------------------------------------------------------------------- n=0; for(i=1;i<=size(iden);i++) { if(defined(S)) {kill S;} def S=re[2][iden[i][1][1]]; setring S; divcomp[i]=ncols(dcE[iden[i][1][2]][iden[i][1][3]][4]); // number of components of the Q-irreducible curve dcE[iden[i][1][2]] n=n+divcomp[i]; setring R; } //--------------------------------------------------------------------------- // set up the entries Inters[i,j] , i!=j, in the intersection matrix: // we have to compute the intersection of the exceptional divisors (over C) // i.e. we have to work in over appropriate algebraic extension of Q. // (1) plug the intersection matrices of the components of the same Q-irred. // divisor into the correct position in the intersection matrix // (2) for comparison of Ei,k and Ej,l move to a chart where both divisors // are present, fetch the components from the very first chart containing // the respective divisor and then compare by using intersComp // (4) put the result into the correct position in the integer matrix Inters //--------------------------------------------------------------------------- //--- some initialization int comPai,comPaj; intvec v,w; intmat Inters[n][n]; //--- run through all Q-irreducible exceptional divisors for(i=1;i<=size(iden);i++) { if(divcomp[i]>1) { //--- (1) put the intersection matrix for Ei,k with Ei,l into the correct place for(k=1;k<=size(iden[i]);k++) { if(defined(tempmat)){kill tempmat;} intmat tempmat=imap(re[2][iden[i][k][1]],dcE)[iden[i][k][2]][iden[i][k][3]][4]; if(size(ideal(tempmat))!=0) { Inters[i+offset1..(i+offset1+divcomp[i]-1), i+offset1..(i+offset1+divcomp[i]-1)]= tempmat[1..nrows(tempmat),1..ncols(tempmat)]; break; } kill tempmat; } } offset2=offset1+divcomp[i]-1; //--- set up the components over C of the i-th exceptional divisor if(defined(S)){kill S;} def S=re[2][iden[i][1][1]]; setring S; if(defined(idlisti)) {kill idlisti;} list idlisti; idlisti[1]=dcE[iden[i][1][2]][iden[i][1][3]][6]; export(idlisti); setring R; //--- run through the remaining exceptional divisors and check whether they //--- have a chart in common with the i-th divisor for(j=i+1;j<=size(iden);j++) { kill templist; list templist; for(k=1;k<=size(iden[i]);k++) { intvec tiv2=findInIVList(1,iden[i][k][1],iden[j]); if(size(tiv2)!=1) { //--- tiv2[1] is a common chart for the divisors i and j tiv2[4..6]=iden[i][k]; templist[size(templist)+1]=tiv2; } kill tiv2; } if(size(templist)==0) { //--- the two (Q-irred) divisors do not appear in any chart simultaneously offset2=offset2+divcomp[j]-1; j++; continue; } for(k=1;k<=size(templist);k++) { if(defined(S)) {kill S;} //--- set up the components over C of the j-th exceptional divisor def S=re[2][iden[j][1][1]]; setring S; if(defined(idlistj)) {kill idlistj;} list idlistj; idlistj[1]=dcE[iden[j][1][2]][iden[j][1][3]][6]; export(idlistj); if(defined(opath)){kill opath;} def opath=imap(re[2][templist[k][1]],path); comPaj=1; while(opath[1,comPaj]==path[1,comPaj]) { comPaj++; if((comPaj>ncols(opath))||(comPaj>ncols(path))) break; } comPaj=int(leadcoef(path[1,comPaj-1])); setring R; kill S; def S=re[2][iden[i][1][1]]; setring S; if(defined(opath)){kill opath;} def opath=imap(re[2][templist[k][1]],path); comPai=1; while(opath[1,comPai]==path[1,comPai]) { comPai++; if((comPai>ncols(opath))||(comPai>ncols(path))) break; } comPai=int(leadcoef(opath[1,comPai-1])); setring R; kill S; def S=re[2][templist[k][1]]; setring S; if(defined(il)) {kill il;} if(defined(jl)) {kill jl;} if(defined(str1)) {kill str1;} if(defined(str2)) {kill str2;} string str1="idlisti"; string str2="idlistj"; attrib(str1,"algext",imap(re[2][iden[i][1][1]],dcE)[iden[i][1][2]][iden[i][1][3]][5]); attrib(str2,"algext",imap(re[2][iden[j][1][1]],dcE)[iden[j][1][2]][iden[j][1][3]][5]); list il=fetchInTree(re,iden[i][1][1],comPai, templist[k][1],str1,iden0,1); list jl=fetchInTree(re,iden[j][1][1],comPaj, templist[k][1],str2,iden0,1); list nulli=imap(re[2][iden[i][1][1]],dcE)[iden[i][1][2]][iden[i][1][3]][7]; list nullj=imap(re[2][iden[j][1][1]],dcE)[iden[j][1][2]][iden[j][1][3]][7]; string mpi=imap(re[2][iden[i][1][1]],dcE)[iden[i][1][2]][iden[i][1][3]][5]; string mpj=imap(re[2][iden[j][1][1]],dcE)[iden[j][1][2]][iden[j][1][3]][5]; if(defined(tintMat)){kill tintMat;} intmat tintMat=intersComp(il[1],mpi,nulli,jl[1],mpj,nullj); kill mpi; kill mpj; kill nulli; kill nullj; for(a=1;a<=divcomp[i];a++) { for(b=1;b<=divcomp[j];b++) { if(tintMat[a,b]!=0) { Inters[i+offset1+a-1,j+offset2+b-1]=tintMat[a,b]; Inters[j+offset2+b-1,i+offset1+a-1]=tintMat[a,b]; } } } } offset2=offset2+divcomp[j]-1; } offset1=offset1+divcomp[i]-1; } Inters=addSelfInter(re,Inters,iden,iden0,endiv); intvec GenusIden; list tl_genus; a=1; for(i=1;i<=size(iden);i++) { tl_genus=genus_E(re,iden0,iden[i][1]); for(j=1;j<=tl_genus[2];j++) { GenusIden[a]=tl_genus[1]; a++; } } list retlist=Inters,GenusIden,iden,divcomp; return(retlist); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp(3); ideal J=x(3)^5+x(2)^4+x(1)^3+x(1)*x(2)*x(3); list re=resolve(J); list di=intersectionDiv(re); di; } ////////////////////////////////////////////////////////////////////////////// static proc intersComp(string str1, string mp1, list null1, string str2, string mp2, list null2) "Internal procedure - no help and no example available " { //--- format of input //--- str1 : ideal (over field extension 1) //--- mp1 : minpoly of field extension 1 //--- null1: numerical zeros of minpoly //--- str2 : ideal (over field extension 2) //--- mp2 : minpoly of field extension 2 //--- null2: numerical zeros of minpoly //--- determine intersection matrix of the C-components defined by the input //--------------------------------------------------------------------------- // Initialization //--------------------------------------------------------------------------- int ii,jj,same; def R=basering; intmat InterMat[size(null1)][size(null2)]; ring ringst=0,(t,s),dp; //--------------------------------------------------------------------------- // Add new variables s and t and compare the minpolys and ideals // to find out whether they are identical //--------------------------------------------------------------------------- def S=R+ringst; setring S; if((mp1==mp2)&&(str1==str2)) { same=1; } //--- define first Q-component/C-components, substitute t by s string tempstr="ideal id1="+str1+";"; execute(tempstr); execute(mp1); id1=subst(id1,t,s); poly q=subst(p,t,s); kill p; //--- define second Q-component/C-components tempstr="ideal id2="+str2+";"; execute(tempstr); execute(mp2); //--- do the intersection ideal interId=id1+id2+ideal(p)+ideal(q); if(same) { interId=quotient(interId,t-s); } interId=std(interId); //--- refine the comparison by passing to each of the numerical zeros //--- of the two minpolys ideal stid=nselect(interId,1..nvars(R)); ring compl_st=complex,(s,t),dp; def stid=imap(S,stid); ideal tempid,tempid2; for(ii=1;ii<=size(null1);ii++) { tempstr="number numi="+null1[ii]+";"; execute(tempstr); tempid=subst(stid,s,numi); kill numi; for(jj=1;jj<=size(null2);jj++) { tempstr="number numj="+null2[jj]+";"; execute(tempstr); tempid2=subst(tempid,t,numj); kill numj; if(size(tempid2)==0) { InterMat[ii,jj]=1; } } } //--- sanity check; as both Q-components were Q-irreducible, //--- summation over all entries of a single row must lead to the same //--- result, no matter which row is chosen //--- dito for the columns int cou,cou1; for(ii=1;ii<=ncols(InterMat);ii++) { cou=0; for(jj=1;jj<=nrows(InterMat);jj++) { cou=cou+InterMat[jj,ii]; } if(ii==1){cou1=cou;} if(cou1!=cou){ERROR("intersComp:matrix has wrong entries");} } for(ii=1;ii<=nrows(InterMat);ii++) { cou=0; for(jj=1;jj<=ncols(InterMat);jj++) { cou=cou+InterMat[ii,jj]; } if(ii==1){cou1=cou;} if(cou1!=cou){ERROR("intersComp:matrix has wrong entries");} } return(InterMat); } ///////////////////////////////////////////////////////////////////////////// static proc addSelfInter(list re,intmat Inters,list iden,list iden0,intvec endiv) "Internal procedure - no help and no example available " { //--------------------------------------------------------------------------- // Initialization //--------------------------------------------------------------------------- def R=basering; int i,j,k,l,a,b; int n=size(iden); intvec v,w; list satlist; def T=re[2][1]; setring T; poly p; p=var(1); //any linear form will do, //but this one is most convenient ideal F=ideal(p); //---------------------------------------------------------------------------- // lift linear form to every end ring, determine the multiplicity of // the exceptional divisors and store it in Flist //---------------------------------------------------------------------------- list templist; intvec tiv; for(i=1;i<=size(endiv);i++) { if(endiv[i]==1) { kill v; intvec v; a=0; if(defined(S)) {kill S;} def S=re[2][i]; setring S; map resi=T,BO[5]; ideal F=resi(F)+BO[2]; ideal Ftemp=F; list Flist; if(defined(satlist)){kill satlist;} list satlist; for(a=1;a<=size(dcE);a++) { for(b=1;b<=size(dcE[a]);b++) { Ftemp=sat(Ftemp,dcE[a][b][1])[1]; } } F=sat(F,Ftemp)[1]; Flist[1]=Ftemp; Ftemp=1; list pr=primdecGTZ(F); v[size(pr)]=0; for(j=1;j<=size(pr);j++) { for(a=1;a<=size(dcE);a++) { if(j==1) { kill tiv; intvec tiv; tiv[size(dcE[a])]=0; templist[a]=tiv; if(v[j]==1) { a++; continue; } } if(dcE[a][1][2]==0) { a++; continue; } for(b=1;b<=size(dcE[a]);b++) { if((size(reduce(dcE[a][b][1],std(pr[j][2])))==0)&& (size(reduce(pr[j][2],std(dcE[a][b][1])))==0)) { templist[a][b]=Vielfachheit(pr[j][1],pr[j][2]); v[j]=1; break; } } if((v[j]==1)&&(j>1)) break; } } kill v; intvec v; Flist[2]=templist; } } //----------------------------------------------------------------------------- // Now set up all the data: // 1. run through all exceptional divisors in iden and determine the // coefficients c_i of the divisor of F. ===> civ // 2. determine the intersection locus of F^bar and the Ei and from this data // the F^bar.Ei . ===> intF //----------------------------------------------------------------------------- intvec civ; intvec intF; intF[ncols(Inters)]=0; int offset,comPa,ncomp,vd; for(i=1;i<=size(iden);i++) { ncomp=0; for(j=1;j<=size(iden[i]);j++) { if(defined(S)) {kill S;} def S=re[2][iden[i][j][1]]; setring S; if((size(civ)0) { civ[i+offset+k]=civ[i+k]; } } } if(defined(interId)) {kill interId;} ideal interId=dcE[iden[i][j][2]][iden[i][j][3]][1]+Flist[1]; if(defined(interList)) {kill interList;} list interList; interList[1]=string(interId); interList[2]=ideal(0); export(interList); if(defined(doneId)) {kill doneId;} if(defined(tempId)) {kill tempId;} ideal doneId=ideal(1); if(defined(dl)) {kill dl;} list dl; for(k=1;kncols(path))||(comPa>ncols(opath))) break; } comPa=int(leadcoef(path[1,comPa-1])); if(defined(str)) {kill str;} string str="interList"; attrib(str,"algext","poly p=t-1;"); dl=fetchInTree(re,iden[i][k][1],comPa,iden[i][j][1],str,iden0,1); if(defined(tempId)){kill tempId;} str="ideal tempId="+dl[1]+";"; execute(str); doneId=intersect(doneId,tempId); str="interId="+interList[1]+";"; execute(str); interId=sat(interId,doneId)[1]; interList[1]=string(interId); } interId=std(interId); if(dim(interId)>0) { "oops, intersection not a set of points"; ~; } vd=vdim(interId); if(vd>0) { for(k=i+offset;k<=i+offset+ncomp-1;k++) { intF[k]=intF[k]+(vd div ncomp); } } } offset=size(civ)-i-1; } if(defined(tiv)){kill tiv;} intvec tiv=civ[2..size(civ)]; civ=tiv; kill tiv; //----------------------------------------------------------------------------- // Using the F_total= sum c_i Ei + F^bar, the intersection matrix Inters and // the f^bar.Ei, determine the selfintersection numbers of the Ei from the // equation F_total.Ei=0 and store it in the diagonal of Inters. //----------------------------------------------------------------------------- intvec diag=Inters*civ+intF; for(i=1;i<=size(diag);i++) { Inters[i,i]=-diag[i] div civ[i]; } return(Inters); } ////////////////////////////////////////////////////////////////////////////// static proc invSort(list re, list #) "Internal procedure - no help and no example available " { int i,j,k,markier,EZeiger,offset; intvec v,e; intvec deleted; if(size(#)>0) { deleted=#[1]; } else { deleted[size(re[2])]=0; } list LE,HI; def R=basering; //---------------------------------------------------------------------------- // Go through all rings //---------------------------------------------------------------------------- for(i=1;i<=size(re[2]);i++) { if(deleted[i]){i++;continue} def S=re[2][i]; setring S; //---------------------------------------------------------------------------- // Determine Invariant //---------------------------------------------------------------------------- if((size(BO[3])==size(BO[9]))||(size(BO[3])==size(BO[9])+1)) { if(defined(merk2)){kill merk2;} intvec merk2; EZeiger=0; for(j=1;j<=size(BO[9]);j++) { offset=0; if(BO[7][j]==-1) { BO[7][j]=size(BO[4])-EZeiger; } for(k=EZeiger+1;(k<=EZeiger+BO[7][j])&&(k<=size(BO[4]));k++) { if(BO[6][k]==2) { offset++; } } EZeiger=EZeiger+BO[7][1]; merk2[3*j-2]=BO[3][j]; merk2[3*j-1]=BO[9][j]-offset; if(size(invSat[2])>j) { merk2[3*j]=-invSat[2][j]; } else { if(jsize(BO[9]))) { merk2[size(merk2)+1]=BO[3][size(BO[3])]; } if((size(merk2)%3)==0) { intvec tintvec=merk2[1..size(merk2)-1]; merk2=tintvec; kill tintvec; } } else { ERROR("This situation should not occur, please send the example to the authors."); } //---------------------------------------------------------------------------- // Save invariant describing current center as an object in this ring // We also store information on the intersection with the center and the // exceptional divisors //---------------------------------------------------------------------------- cent=std(cent); kill e; intvec e; for(j=1;j<=size(BO[4]);j++) { if(size(reduce(BO[4][j],std(cent+BO[1])))==0) { e[j]=1; } else { e[j]=0; } } if(size(ideal(merk2))==0) { markier=1; } if((size(merk2)%3==0)&&(merk2[size(merk2)]==0)) { intvec blabla=merk2[1..size(merk2)-1]; merk2=blabla; kill blabla; } if(defined(invCenter)){kill invCenter;} list invCenter=cent,merk2,e; export invCenter; //---------------------------------------------------------------------------- // Insert it into correct place in the list //---------------------------------------------------------------------------- if(i==1) { if(!markier) { HI=intvec(merk2[1]+1),intvec(1); } else { HI=intvec(778),intvec(1); // some really large integer // will be changed at the end!!! } LE[1]=HI; i++; setring R; kill S; continue; } if(markier==1) { if(i==2) { HI=intvec(777),intvec(2); // same really large integer-1 LE[2]=HI; i++; setring R; kill S; continue; } else { if(ncols(path)==2) { LE[2][2][size(LE[2][2])+1]=i; i++; setring R; kill S; continue; } else { markier=0; } } } j=1; def SOld=re[2][int(leadcoef(path[1,ncols(path)]))]; setring SOld; merk2=invCenter[2]; setring S; kill SOld; while(merk2size(LE)) break; } HI=merk2,intvec(i); if(j<=size(LE)) { if(merk2>LE[j][1]) { LE=insert(LE,HI,j-1); } else { while((merk2==LE[j][1])&&(size(merk2)size(LE)) break; } if(j<=size(LE)) { if((merk2!=LE[j][1])||(size(merk2)!=size(LE[j][1]))) { LE=insert(LE,HI,j-1); } else { LE[j][2][size(LE[j][2])+1]=i; } } else { LE[size(LE)+1]=HI; } } } else { LE[size(LE)+1]=HI; } setring R; kill S; } if((LE[1][1]==intvec(778)) && (size(LE)>2)) { LE[1][1]=intvec(LE[3][1][1]+2); // by now we know what 'sufficiently LE[2][1]=intvec(LE[3][1][1]+1); // large' is } return(LE); } example {"EXAMPLE:"; echo = 2; ring r = 0,(x(1..3)),dp(3); ideal J=x(1)^3-x(1)*x(2)^3+x(3)^2; list re=resolve(J,1); list di=invSort(re); di; } ///////////////////////////////////////////////////////////////////////////// static proc addToRE(intvec v,int x,list RE) "Internal procedure - no help and no example available " { //--- auxilliary procedure for collectDiv, //--- inserting an entry at the correct place int i=1; while(i<=size(RE)) { if(v==RE[i][1]) { RE[i][2][size(RE[i][2])+1]=x; return(RE); } if(v>RE[i][1]) { list templist=v,intvec(x); RE=insert(RE,templist,i-1); return(RE); } i++; } list templist=v,intvec(x); RE=insert(RE,templist,size(RE)); return(RE); } //////////////////////////////////////////////////////////////////////////// proc collectDiv(list re,list #) "USAGE: collectDiv(L); @* L = list of rings ASSUME: L is output of resolution of singularities COMPUTE: list representing the identification of the exceptional divisors in the various charts RETURN: list l, where l[1]: intmat, entry k in position i,j implies BO[4][j] of chart i is divisor k (if k!=0) if k==0, no divisor corresponding to i,j l[2]: list ll, where each entry of ll is a list of intvecs entry i,j in list ll[k] implies BO[4][j] of chart i is divisor k l[3]: list L EXAMPLE: example collectDiv; shows an example " { //------------------------------------------------------------------------ // Initialization //------------------------------------------------------------------------ int i,j,k,l,m,maxk,maxj,mPa,oPa,interC,pa,ignoreL,iTotal; int mLast,oLast=1,1; intvec deleted; //--- sort the rings by the invariant which controlled the last of the //--- exceptional divisors if(size(#)>0) { deleted=#[1]; } else { deleted[size(re[2])]=0; } list LE=invSort(re,deleted); list LEtotal=LE; intmat M[size(re[2])][size(re[2])]; intvec invar,tempiv; def R=basering; list divList; list RE,SE; intvec myEi,otherEi,tempe; int co=2; while(size(LE)>0) { //------------------------------------------------------------------------ // Run through the sorted list LE whose entries are lists containing // the invariant and the numbers of all rings corresponding to it //------------------------------------------------------------------------ for(i=co;i<=size(LE);i++) { //--- i==1 in first iteration: //--- the original ring which did not arise from a blow-up //--- hence there are no exceptional divisors to be identified there ; //------------------------------------------------------------------------ // For each fixed value of the invariant, run through all corresponding // rings //------------------------------------------------------------------------ for(l=1;l<=size(LE[i][2]);l++) { if(defined(S)){kill S;} def S=re[2][LE[i][2][l]]; setring S; if(size(BO[4])>maxj){maxj=size(BO[4]);} //--- all exceptional divisors, except the last one, were previously //--- identified - hence we can simply inherit the data from the parent ring for(j=1;j0) { k=int(leadcoef(path[1,ncols(path)])); k=M[k,j]; if(k==0) { RE=addToRE(LE[i][1],LE[i][2][l],RE); ignoreL=1; break; } M[LE[i][2][l],j]=k; tempiv=LE[i][2][l],j; divList[k][size(divList[k])+1]=tempiv; } } if(ignoreL){ignoreL=0;l++;continue;} //---------------------------------------------------------------------------- // In the remaining part of the procedure, the identification of the last // exceptional divisor takes place. // Step 1: check whether there is a previously considered ring with the // same parent; if this is the case, we can again inherit the data // Step 1':check whether the parent had a stored center which it then used // in this case, we are dealing with an additional component of this // divisor: store it in the integer otherComp // Step 2: if no appropriate ring was found in step 1, we check whether // there is a previously considered ring, in the parent of which // the center intersects the same exceptional divisors as the center // in our parent. // if such a ring does not exist: new exceptional divisor // if it exists: see below //---------------------------------------------------------------------------- if(path[1,ncols(path)-1]==0) { //--- current ring originated from very first blow-up //--- hence exceptional divisor is the first one M[LE[i][2][l],1]=1; if(size(divList)>0) { divList[1][size(divList[1])+1]=intvec(LE[i][2][l],j); } else { divList[1]=list(intvec(LE[i][2][l],j)); } l++; continue; } if(l==1) { list TE=addToRE(LE[i][1],1,SE); if(size(TE)!=size(SE)) { //--- new value of invariant hence new exceptional divisor SE=TE; divList[size(divList)+1]=list(intvec(LE[i][2][l],j)); M[LE[i][2][l],j]=size(divList); } kill TE; } for(k=1;k<=size(LEtotal);k++) { if(LE[i][1]==LEtotal[k][1]) { iTotal=k; break; } } //--- Step 1 k=1; while(LEtotal[iTotal][2][k]size(LEtotal[iTotal][2])) {break;} } if(ignoreL){ignoreL=0;l++;continue;} //--- Step 1', if necessary if(M[LE[i][2][l],j]==0) { int savedCent; def SPa1=re[2][int(leadcoef(path[1,ncols(path)]))]; // parent ring setring SPa1; if(size(BO)>9) { if(size(BO[10])>0) { savedCent=1; } } if(!savedCent) { def SPa2=re[2][int(leadcoef(path[1,ncols(path)]))]; map lMa=SPa2,lastMap; // map leading from grandparent to parent list transBO=lMa(BO); // actually we only need BO[10], but this is an // object not a name list tempsat; if(size(transBO)>9) { //--- there were saved centers while((k<=size(transBO[10])) & (savedCent==0)) { tempsat=sat(transBO[10][k][1],BO[4][size(BO[4])]); if(deg(tempsat[1][1])!=0) { //--- saved center can be seen in this affine chart if((size(reduce(tempsat[1],std(cent)))==0) && (size(reduce(cent,tempsat[1]))==0)) { //--- this was the saved center which was used savedCent=1; } } k++; } } kill lMa; // clean up temporary objects kill tempsat; kill transBO; } setring S; // back to the ring which we want to consider if(savedCent==1) { vector otherComp= gen(M[int(leadcoef(path[1,ncols(path)])),size(BO[4])-1]); } kill savedCent; if (defined(SPa2)){kill SPa2;} kill SPa1; } //--- Step 2, if necessary if(M[LE[i][2][l],j]==0) { //--- we are not done after step 1 and 2 pa=int(leadcoef(path[1,ncols(path)])); // parent ring tempe=imap(re[2][pa],invCenter)[3]; // intersection there kill myEi; intvec myEi; for(k=1;k<=size(tempe);k++) { if(tempe[k]==1) { //--- center meets this exceptional divisor myEi[size(myEi)+1]=M[pa,k]; mLast=k; } } //--- ring in which the last divisor we meet is new-born mPa=int(leadcoef(path[1,mLast+2])); k=1; while(LEtotal[iTotal][2][k]size(LEtotal[iTotal][2])) { break; } else { continue; } } //---------------------------------------------------------------------------- // Current situation: // 1. the last exceptional divisor could not be identified by simply // considering its parent // 2. it could not be proved to be a new one by considering its intersections // with previous exceptional divisors //---------------------------------------------------------------------------- if(defined(bool1)) { kill bool1;} int bool1= compareE(re,LE[i][2][l],LEtotal[iTotal][2][k],divList); if(bool1) { //--- found some non-empty intersection if(bool1==1) { //--- it is really the same exceptional divisor m=size(imap(re[2][LEtotal[iTotal][2][k]],BO)[4]); m=M[LEtotal[iTotal][2][k],m]; if(m==0) { RE=addToRE(LE[i][1],LE[i][2][l],RE); ignoreL=1; break; } M[LE[i][2][l],j]=m; tempiv=LE[i][2][l],j; divList[m][size(divList[m])+1]=tempiv; break; } else { m=size(imap(re[2][LEtotal[iTotal][2][k]],BO)[4]); m=M[LEtotal[iTotal][2][k],m]; if(m!=0) { otherComp[m]=1; } } } k++; if(k>size(LEtotal[iTotal][2])) { break; } } if(ignoreL){ignoreL=0;l++;continue;} if( M[LE[i][2][l],j]==0) { divList[size(divList)+1]=list(intvec(LE[i][2][l],j)); M[LE[i][2][l],j]=size(divList); } } setring R; kill S; } } LE=RE; co=1; kill RE; list RE; } //---------------------------------------------------------------------------- // Add the strict transform to the list of divisors at the last place // and clean up M //---------------------------------------------------------------------------- //--- add strict transform for(i=1;i<=size(re[2]);i++) { if(defined(S)){kill S;} def S=re[2][i]; setring S; if(size(reduce(cent,std(BO[2])))==0) { tempiv=i,0; RE[size(RE)+1]=tempiv; } setring R; } divList[size(divList)+1]=RE; //--- drop trailing zero-columns of M intvec iv0; iv0[nrows(M)]=0; for(i=ncols(M);i>0;i--) { if(intvec(M[1..nrows(M),i])!=iv0) break; } intmat N[nrows(M)][i]; for(i=1;i<=ncols(N);i++) { N[1..nrows(M),i]=M[1..nrows(M),i]; } kill M; intmat M=N; list retlist=cleanUpDiv(re,M,divList); return(retlist); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal I=xyz+x4+y4+z4; //we really need to blow up curves even if the generic point of //the curve the total transform is n.c. //this occurs here in r[2][5] list re=resolve(I); list di=collectDiv(re); di[1]; di[2]; } ////////////////////////////////////////////////////////////////////////////// static proc cleanUpDiv(list re,intmat M,list divList) "Internal procedure - no help and no example available " { //--- It may occur that two different entries of invSort coincide on the //--- first part up to the last entry of the shorter one. In this case //--- exceptional divisors may appear in both entries of the invSort-list. //--- To correct this, we now compare the final collection of Divisors //--- for coinciding ones. int i,j,k,a,oPa,mPa,comPa,mdim,odim; def R=basering; for(i=1;i<=size(divList)-2;i++) { if(defined(Sm)){kill Sm;} def Sm=re[2][divList[i][1][1]]; setring Sm; mPa=int(leadcoef(path[1,ncols(path)])); if(defined(SmPa)){kill SmPa;} def SmPa=re[2][mPa]; setring SmPa; mdim=dim(std(BO[1]+cent)); setring Sm; if(mPa==1) { //--- very first divisor originates exactly from the first blow-up //--- there cannot be any mistake here i++; continue; } for(j=i+1;j<=size(divList)-1;j++) { setring Sm; for(k=1;k<=size(divList[j]);k++) { if(size(findInIVList(1,divList[j][k][1],divList[i]))>1) { //--- same divisor cannot appear twice in the same chart k=-1; break; } } if(k==-1) { j++; if(j>size(divList)-1) break; continue; } if(defined(opath)){kill opath;} def opath=imap(re[2][divList[j][1][1]],path); oPa=int(leadcoef(opath[1,ncols(opath)])); if(defined(SoPa)){kill SoPa;} def SoPa=re[2][oPa]; setring SoPa; odim=dim(std(BO[1]+cent)); setring Sm; if(mdim!=odim) { //--- different dimension ==> cannot be same center j++; if(j>size(divList)-1) break; continue; } comPa=1; while(path[1,comPa]==opath[1,comPa]) { comPa++; if((comPa>ncols(path))||(comPa>ncols(opath))) break; } comPa=int(leadcoef(path[1,comPa-1])); if(defined(SPa)){kill SPa;} def SPa=re[2][mPa]; setring SPa; if(defined(tempIdE)){kill tempIdE;} ideal tempIdE=fetchInTree(re,oPa,comPa,mPa,"cent",divList); if((size(reduce(cent,std(tempIdE)))!=0)|| (size(reduce(tempIdE,std(cent)))!=0)) { //--- it is not the same divisor! j++; if(j>size(divList)) { break; } else { continue; } } for(k=1;k<=size(divList[j]);k++) { //--- append the entries of the j-th divisor (which is actually also the i-th) //--- to the i-th divisor divList[i][size(divList[i])+1]=divList[j][k]; } divList=delete(divList,j); //kill obsolete entry from the list for(k=1;k<=nrows(M);k++) { for(a=1;a<=ncols(M);a++) { if(M[k,a]==j) { //--- j-th divisor is actually the i-th one M[k,a]=i; } if(M[k,a]>j) { //--- index j was deleted from the list ==> all subsequent indices dropped by //--- one M[k,a]=M[k,a]-1; } } } j--; //do not forget to consider new j-th entry } } setring R; list retlist=M,divList; return(retlist); } ///////////////////////////////////////////////////////////////////////////// static proc findTrans(ideal Z, ideal E, list notE, list #) "Internal procedure - no help and no example available " { //---Auxilliary procedure for fetchInTree! //---Assume E prime ideal, Z+E eqidimensional, //---ht(E)+r=ht(Z+E). Compute P= in Z+E, and polynomial f, //---such that radical(Z+E)=radical((E+P):f) int i,j,d,e; ideal Estd=std(E); //!!! alternative to subsequent line: //!!! ideal Zstd=std(radical(Z+E)); ideal Zstd=std(Z+E); ideal J=1; if(size(#)>0) { J=#[1]; } if(deg(Zstd[1])==0){return(list(ideal(1),poly(1)));} for(i=1;i<=size(notE);i++) { notE[i]=std(notE[i]); } ideal Zred=simplify(reduce(Z,Estd),2); if(size(Zred)==0){Z,Estd;~;ERROR("Z is contained in E");} ideal P,Q,Qstd; Q=Estd; attrib(Q,"isSB",1); d=dim(Estd); e=dim(Zstd); for(i=1;i<=size(Zred);i++) { Qstd=std(Q,Zred[i]); if(dim(Qstd)20) { ~; ERROR("findTrans:Hier ist was faul"); } } list resu=P,f; return(resu); } ///////////////////////////////////////////////////////////////////////////// static proc compareE(list L, int m, int o, list DivL) "Internal procedure - no help and no example available " { //---------------------------------------------------------------------------- // We want to compare the divisors BO[4][size(BO[4])] of the rings // L[2][m] and L[2][o]. // In the initialization step, we collect all necessary data from those // those rings. In particular, we determine at what point (in the resolution // history) the branches for L[2][m] and L[2][o] were separated, denoting // the corresponding ring indices by mPa, oPa and comPa. //---------------------------------------------------------------------------- def R=basering; int i,j,k,len; //-- find direct parents and branching point in resolution history matrix tpm=imap(L[2][m],path); matrix tpo=imap(L[2][o],path); int m1,o1=int(leadcoef(tpm[1,ncols(tpm)])), int(leadcoef(tpo[1,ncols(tpo)])); while((i they cannot give rise //--- to the same divisor return(0); } def T=L[2][o1]; setring T; int dimCo1=dim(std(cent+BO[1])); def S=L[2][m1]; setring S; int dimCm1=dim(std(cent+BO[1])); if(dimCm1!=dimCo1) { //--- centers do not have same dimension ==> they cannot give rise //--- to the same divisor return(0); } //---------------------------------------------------------------------------- // fetch the center via the tree for comparison //---------------------------------------------------------------------------- if(defined(invLocus0)) {kill invLocus0;} ideal invLocus0=fetchInTree(L,o1,comPa,m1,"cent",DivL); // blow down from L[2][o1] to L[2][comPa] and then up to L[2][m1] if(deg(std(invLocus0+invCenter[1]+BO[1])[1])!=0) { setring R; return(int(1)); } if(size(BO)>9) { for(i=1;i<=size(BO[10]);i++) { if(deg(std(invLocus0+BO[10][i][1]+BO[1])[1])!=0) { if(dim(std(BO[10][i][1]+BO[1])) > dim(std(invLocus0+BO[10][i][1]+BO[1]))) { ERROR("Internal Error: Please send this example to the authors."); } setring R; return(int(2)); } } } setring R; return(int(0)); //---------------------------------------------------------------------------- // Return-Values: // TRUE (=1) if the exceptional divisors coincide, // TRUE (=2) if the exceptional divisors originate from different // components of the same center // FALSE (=0) otherwise //---------------------------------------------------------------------------- } ////////////////////////////////////////////////////////////////////////////// proc fetchInTree(list L, int o1, int comPa, int m1, string idname, list DivL, list #); "Internal procedure - no help and no example available " { //---------------------------------------------------------------------------- // Initialization and Sanity Checks //---------------------------------------------------------------------------- int i,j,k,m,branchPos,inJ,exception; string algext; //--- we need to be in L[2][m1] def R=basering; ideal test_for_the_same_ring=-77; def Sm1=L[2][m1]; setring Sm1; if(!defined(test_for_the_same_ring)) { //--- we are not in L[2][m1] ERROR("basering has to coincide with L[2][m1]"); } else { //--- we are in L[2][m1] kill test_for_the_same_ring; } //--- non-embedded case? if(size(#)>0) { inJ=1; } //--- do parameter values make sense? if(comPa<1) { ERROR("Common Parent should at least be the first ring!"); } //--- do we need to pass to an algebraic field extension of Q? if(typeof(attrib(idname,"algext"))=="string") { algext=attrib(idname,"algext"); } //--- check wheter comPa is in the history of m1 //--- same test for o1 can be done later on (on the fly) if(m1==comPa) { j=1; i=ncols(path)+1; } else { for(i=1;i<=ncols(path);i++) { if(int(leadcoef(path[1,i]))==comPa) { //--- comPa occurs in the history j=1; break; } } } branchPos=i; if(j==0) { ERROR("L[2][comPa] not in history of L[2][m1]!"); } //---------------------------------------------------------------------------- // Blow down ideal "idname" from L[2][o1] to L[2][comPa], where the latter // is assumed to be the common parent of L[2][o1] and L[2][m1] //---------------------------------------------------------------------------- if(size(algext)>0) { //--- size(algext)>0: case of algebraic extension of base field if(defined(tstr)){kill tstr;} string tstr="ring So1=(0,t),("+varstr(L[2][o1])+"),("+ordstr(L[2][o1])+");"; execute(tstr); setring So1; execute(algext); minpoly=leadcoef(p); if(defined(id1)) { kill id1; } if(defined(id2)) { kill id2; } if(defined(idlist)) { kill idlist; } execute("int bool2=defined("+idname+");"); if(bool2==0) { execute("list ttlist=imap(L[2][o1],"+idname+");"); } else { execute("list ttlist="+idname+";"); } kill bool2; def BO=imap(L[2][o1],BO); def path=imap(L[2][o1],path); def lastMap=imap(L[2][o1],lastMap); ideal id2=1; if(defined(notE)){kill notE;} list notE; intvec nE; list idlist; for(i=1;i<=size(ttlist);i++) { if((i==size(ttlist))&&(typeof(ttlist[i])!="string")) break; execute("ideal tid="+ttlist[i]+";"); idlist[i]=list(tid,ideal(1),nE); kill tid; } } else { //--- size(algext)==0: no algebraic extension of base needed def So1=L[2][o1]; setring So1; if(defined(id1)) { kill id1; } if(defined(id2)) { kill id2; } if(defined(idlist)) { kill idlist; } execute("ideal id1="+idname+";"); if(deg(std(id1)[1])==0) { //--- problems with findTrans if id1 is empty set //!!! todo: also correct in if branch!!! setring R; return(ideal(1)); } // id1=radical(id1); ideal id2=1; list idlist; if(defined(notE)){kill notE;} list notE; intvec nE; idlist[1]=list(id1,id2,nE); } if(defined(tli)){kill tli;} list tli; if(defined(id1)) { kill id1; } if(defined(id2)) { kill id2; } ideal id1; ideal id2; if(defined(Etemp)){kill Etemp;} ideal Etemp; for(m=1;m<=size(idlist);m++) { //!!! Duplicate Block!!! All changes also needed below!!! //!!! no subprocedure due to large data overhead!!! //--- run through all ideals to be fetched id1=idlist[m][1]; id2=idlist[m][2]; nE=idlist[m][3]; for(i=branchPos-1;i<=size(BO[4]);i++) { //--- run through all relevant exceptional divisors if(size(reduce(BO[4][i],std(id1+BO[1])))==0) { //--- V(id1) is contained in except. div. i in this chart if(size(reduce(id1,std(BO[4][i])))!=0) { //--- V(id1) does not equal except. div. i of this chart Etemp=BO[4][i]; if(npars(basering)>0) { //--- we are in an algebraic extension of the base field if(defined(prtemp)){kill prtemp;} list prtemp=minAssGTZ(BO[4][i]); // C-comp. of except. div. j=1; if(size(prtemp)>1) { //--- more than 1 component Etemp=ideal(1); for(j=1;j<=size(prtemp);j++) { //--- find correct component if(size(reduce(prtemp[j],std(id1)))==0) { Etemp=prtemp[j]; break; } } if(deg(std(Etemp)[1])==0) { ERROR("fetchInTree:something wrong in field extension"); } } prtemp=delete(prtemp,j); // remove this comp. from list while(size(prtemp)>1) { //--- collect all the others into prtemp[1] prtemp[1]=intersect(prtemp[1],prtemp[size(prtemp)]); prtemp=delete(prtemp,size(prtemp)); } } //--- determine tli[1] and tli[2] such that //--- V(id1) \cap D(id2) = V(tli[1]) \cap D(tli[2]) \cap BO[4][i] //--- inside V(BO[1]) (and if necessary inside V(BO[1]+BO[2])) if(inJ) { tli=findTrans(id1+BO[2]+BO[1],Etemp,notE,BO[2]); } else { tli=findTrans(id1+BO[1],Etemp,notE); } if(npars(basering)>0) { //--- in algebraic extension: make sure we stay outside the other components if(size(prtemp)>0) { for(j=1;j<=ncols(prtemp[1]);j++) { //--- find the (univariate) generator of prtemp[1] which is the remaining //--- factor from the factorization over the extension field if(size(reduce(prtemp[1][j],std(id1)))>0) { tli[2]=tli[2]*prtemp[1][j]; } } } } } else { //--- V(id1) equals except. div. i of this chart tli[1]=ideal(0); tli[2]=ideal(1); } id1=tli[1]; id2=id2*tli[2]; notE[size(notE)+1]=BO[4][i]; for(j=1;j<=size(DivL);j++) { if(inIVList(intvec(o1,i),DivL[j])) { nE[size(nE)+1]=j; break; } } if(size(nE)1) { while(int(leadcoef(path[1,ncols(path)]))>=comPa) { if((int(leadcoef(path[1,ncols(path)]))>comPa)&& (int(leadcoef(path[1,ncols(path)-1]))0) { if(defined(T0)){kill T0;} def T0=L[2][int(leadcoef(path[1,ncols(path)]))]; if(defined(tstr)){kill tstr;} string tstr="ring T=(0,t),(" +varstr(L[2][int(leadcoef(path[1,ncols(path)]))])+"),(" +ordstr(L[2][int(leadcoef(path[1,ncols(path)]))])+");"; execute(tstr); setring T; execute(algext); minpoly=leadcoef(p); kill tstr; def BO=imap(T0,BO); if(!defined(und_jetzt_raus)) { def path=imap(T0,path); def lastMap=imap(T0,lastMap); } if(defined(idlist)){kill idlist;} list idlist=list(list(ideal(1),ideal(1))); } else { def T=L[2][int(leadcoef(path[1,ncols(path)]))]; setring T; if(defined(id1)) { kill id1; } if(defined(id2)) { kill id2; } if(defined(idlist)){kill idlist;} list idlist=list(list(ideal(1),ideal(1))); } setring S; if(defined(phi)) { kill phi; } map phi=T,lastMap; //--- now do the actual blowing down ... for(m=1;m<=size(idlist);m++) { //--- ... for each entry of idlist separately if(defined(id1)){kill id1;} if(defined(id2)){kill id2;} ideal id1=idlist[m][1]+BO[1]; ideal id2=idlist[m][2]; nE=idlist[m][3]; if(defined(debug_fetchInTree)>0) { "Blowing down entry",m,"of idlist:"; setring S; "Abbildung:";phi; "before preimage"; id1; id2; } setring T; ideal id1=preimage(S,phi,id1); ideal id2=preimage(S,phi,id2); if(defined(debug_fetchInTree)>0) { "after preimage"; id1; id2; } if(size(id2)==0) { //--- preimage of (principal ideal) id2 was zero, i.e. //--- generator of previous id2 not in image setring S; //--- it might just be one offending factor ==> factorize ideal id2factors=factorize(id2[1])[1]; int zzz=size(id2factors); ideal curfactor; setring T; id2=ideal(1); ideal curfactor; for(int mm=1;mm<=zzz;mm++) { //--- blow down each factor separately setring S; curfactor=id2factors[mm]; setring T; curfactor=preimage(S,phi,curfactor); if(size(curfactor)>0) { id2[1]=id2[1]*curfactor[1]; } } kill curfactor; setring S; kill curfactor; kill id2factors; setring T; kill mm; kill zzz; if(defined(debug_fetchInTree)>0) { "corrected id2:"; id2; } } idlist[m]=list(id1,id2,nE); kill id1,id2; setring S; } setring T; //--- after blowing down we might again be sitting inside a relevant //--- exceptional divisor for(m=1;m<=size(idlist);m++) { //!!! Duplicate Block!!! All changes also needed above!!! //!!! no subprocedure due to large data overhead!!! //--- run through all ideals to be fetched if(defined(id1)) {kill id1;} if(defined(id2)) {kill id2;} if(defined(notE)) {kill notE;} if(defined(notE)) {kill notE;} list notE; ideal id1=idlist[m][1]; ideal id2=idlist[m][2]; nE=idlist[m][3]; for(i=branchPos-1;i<=size(BO[4]);i++) { //--- run through all relevant exceptional divisors if(size(reduce(BO[4][i],std(id1)))==0) { //--- V(id1) is contained in except. div. i in this chart if(size(reduce(id1,std(BO[4][i])))!=0) { //--- V(id1) does not equal except. div. i of this chart if(defined(Etemp)) {kill Etemp;} ideal Etemp=BO[4][i]; if(npars(basering)>0) { //--- we are in an algebraic extension of the base field if(defined(prtemp)){kill prtemp;} list prtemp=minAssGTZ(BO[4][i]); // C-comp.except.div. if(size(prtemp)>1) { //--- more than 1 component Etemp=ideal(1); for(j=1;j<=size(prtemp);j++) { //--- find correct component if(size(reduce(prtemp[j],std(id1)))==0) { Etemp=prtemp[j]; break; } } if(deg(std(Etemp)[1])==0) { ERROR("fetchInTree:something wrong in field extension"); } } prtemp=delete(prtemp,j); // remove this comp. from list while(size(prtemp)>1) { //--- collect all the others into prtemp[1] prtemp[1]=intersect(prtemp[1],prtemp[size(prtemp)]); prtemp=delete(prtemp,size(prtemp)); } } if(defined(tli)) {kill tli;} //--- determine tli[1] and tli[2] such that //--- V(id1) \cap D(id2) = V(tli[1]) \cap D(tli[2]) \cap BO[4][i] //--- inside V(BO[1]) (and if necessary inside V(BO[1]+BO[2])) if(inJ) { def tli=findTrans(id1+BO[2]+BO[1],Etemp,notE,BO[2]); } else { def tli=findTrans(id1+BO[1],Etemp,notE); } if(npars(basering)>0) { //--- in algebraic extension: make sure we stay outside the other components if(size(prtemp)>0) { for(j=1;j<=ncols(prtemp[1]);j++) { //--- find the (univariate) generator of prtemp[1] which is the remaining //--- factor from the factorization over the extension field if(size(reduce(prtemp[1][j],std(id1)))>0) { tli[2]=tli[2]*prtemp[1][j]; } } } } } else { tli[1]=ideal(0); tli[2]=ideal(1); } id1=tli[1]; id2=id2*tli[2]; notE[size(notE)+1]=BO[4][i]; for(j=1;j<=size(DivL);j++) { if(inIVList(intvec(o1,i),DivL[j])) { nE[size(nE)+1]=j; break; } } if(size(nE)0) { "idlist after current blow down step:"; idlist; } } if(defined(debug_fetchInTree)>0) { "Blowing down ended"; } //---------------------------------------------------------------------------- // Blow up ideal id1 from L[2][comPa] to L[2][m1]. To this end, first // determine the path to follow and save it in path_togo. //---------------------------------------------------------------------------- if(m1==comPa) { //--- no further blow ups needed if(size(algext)==0) { //--- no field extension ==> we are done return(idlist[1][1]); } else { //--- field extension ==> we need to encode the result list retlist; for(m=1;m<=size(idlist);m++) { retlist[m]=string(idlist[m][1]); } return(retlist); } } //--- we need to blow up if(defined(path_m1)) { kill path_m1; } matrix path_m1=imap(Sm1,path); intvec path_togo; for(i=1;i<=ncols(path_m1);i++) { if(path_m1[1,i]>=comPa) { path_togo=path_togo,int(leadcoef(path_m1[1,i])); } } path_togo=path_togo[2..size(path_togo)],m1; i=1; while(i0) { //--- in an algebraic extension of the base field if(defined(T0)){kill T0;} def T0=L[2][path_togo[i+1]]; if(defined(tstr)){kill tstr;} string tstr="ring T=(0,t),(" +varstr(T0)+"),(" +ordstr(T0)+");"; execute(tstr); setring T; execute(algext); minpoly=leadcoef(p); kill tstr; def path=imap(T0,path); def BO=imap(T0,BO); def lastMap=imap(T0,lastMap); if(defined(phi)){kill phi;} map phi=S,lastMap; list idlist=phi(idlist); if(defined(debug_fetchInTree)>0) { "in blowing up (algebraic extension case):"; phi; idlist; } } else { def T=L[2][path_togo[i+1]]; setring T; if(defined(phi)) { kill phi; } map phi=S,lastMap; if(defined(idlist)) {kill idlist;} list idlist=phi(idlist); idlist[1][1]=radical(idlist[1][1]); idlist[1][2]=radical(idlist[1][2]); if(defined(debug_fetchInTree)>0) { "in blowing up (case without field extension):"; phi; idlist; } } for(m=1;m<=size(idlist);m++) { //--- get rid of new exceptional divisor idlist[m][1]=sat(idlist[m][1]+BO[1],BO[4][size(BO[4])])[1]; idlist[m][2]=sat(idlist[m][2],BO[4][size(BO[4])])[1]; } if(defined(debug_fetchInTree)>0) { "after saturation:"; idlist; } if((size(algext)==0)&&(deg(std(idlist[1][1])[1])==0)) { //--- strict transform empty in this chart, it will stay empty till the end setring Sm1; return(ideal(1)); } kill S; i++; } if(defined(debug_fetchInTree)>0) { "End of blowing up steps"; } //--------------------------------------------------------------------------- // prepare results for returning them //--------------------------------------------------------------------------- ideal E,bla; intvec kv; list retlist; for(m=1;m<=size(idlist);m++) { for(j=2;j<=size(idlist[m][3]);j++) { kv=findInIVList(1,path_togo[size(path_togo)],DivL[idlist[m][3][j]]); if(kv!=intvec(0)) { E=E+BO[4][kv[2]]; } } bla=quotient(idlist[m][1]+E,idlist[m][2]); retlist[m]=string(bla); } if(size(algext)==0) { return(bla); } return(retlist); } ///////////////////////////////////////////////////////////////////////////// static proc findInIVList(int pos, int val, list ivl) "Internal procedure - no help and no example available " { //--- find entry with value val at position pos in list of intvecs //--- and return the corresponding entry int i; for(i=1;i<=size(ivl);i++) { if(ivl[i][pos]==val) { return(ivl[i]); } } return(intvec(0)); } ///////////////////////////////////////////////////////////////////////////// //static proc inIVList(intvec iv, list li) "Internal procedure - no help and no example available " { //--- if intvec iv is contained in list li return 1, 0 otherwise int i; int s=size(iv); for(i=1;i<=size(li);i++) { if(typeof(li[i])!="intvec"){ERROR("Not integer vector in the list");} if(s==size(li[i])) { if(iv==li[i]){return(1);} } } return(0); } ////////////////////////////////////////////////////////////////////////////// static proc Vielfachheit(ideal J,ideal I) "Internal procedure - no help and no example available " { //--- auxilliary procedure for addSelfInter //--- compute multiplicity, suitable for the special situation there int d=1; int vd; int c; poly p; ideal Ip,Jp; while((d>0)||(!vd)) { p=randomLast(100)[nvars(basering)]; Ip=std(I+ideal(p)); c++; if(c>20){ERROR("Vielfachheit: Dimension is wrong");} d=dim(Ip); vd=vdim(Ip); } Jp=std(J+ideal(p)); return(vdim(Jp) div vdim(Ip)); } ///////////////////////////////////////////////////////////////////////////// static proc genus_E(list re, list iden0, intvec Eindex) "Internal procedure - no help and no example available " { int i,ge,gel,num; def R=basering; ring Rhelp=0,@t,dp; def S=re[2][Eindex[1]]; setring S; def Sh=S+Rhelp; //---------------------------------------------------------------------------- //--- The Q-component X is reducible over C, decomposes into s=num components //--- X_i, we assume they have n.c. //--- s*g(X_i)=g(X)+s-1. //---------------------------------------------------------------------------- if(defined(I2)){kill I2;} ideal I2=dcE[Eindex[2]][Eindex[3]][1]; num=ncols(dcE[Eindex[2]][Eindex[3]][4]); setring Sh; if(defined(I2)){kill I2;} ideal I2=imap(S,I2); I2=homog(I2,@t); ge=genus(I2); gel=(ge+(num-1)) div num; if(gel*num-ge-num+1!=0){ERROR("genus_E: not divisible by num");} setring R; return(gel,num); } singular-4.0.3+ds/Singular/LIB/ring.lib000066400000000000000000001125771266270727000176130ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version ring.lib 4.0.2.2 Jan_2016 "; // $Id: 80fc872a4d42a846cb376f7bd59e9130cbc01801 $ category="General purpose"; info=" LIBRARY: ring.lib Manipulating Rings and Maps AUTHORS: Singular team PROCEDURES: changechar(c[,r]); make a copy of basering [ring r] with new char c changeord(o[,r]); make a copy of basering [ring r] with new ord o changevar(v[,r]); make a copy of basering [ring r] with new vars v defring(\"R\",c,n,v,o); define a ring R in specified char c, n vars v, ord o defrings(n[,p]); define ring Sn in n vars, char 32003 [p], ord ds defringp(n[,p]); define ring Pn in n vars, char 32003 [p], ord dp extendring(\"R\",n,v,o); extend given ring by n vars v, ord o and name it R fetchall(R[,str]); fetch all objects of ring R to basering imapall(R[,str]); imap all objects of ring R to basering mapall(R,i[,str]); map all objects of ring R via ideal i to basering ord_test(R); test wether ordering of R is global, local or mixed ringtensor(s,t,..); create ring, tensor product of rings s,t,... ringweights(r); intvec of weights of ring variables of ring r preimageLoc(R,phi,Q) computes preimage for non-global orderings rootofUnity(n); the minimal polynomial for the n-th primitive root of unity (parameters in square brackets [] are optional) optionIsSet(opt) check if as a string given option is set or not. hasFieldCoefficient check if the coefficient ring is considered a field hasGFCoefficient check if the coefficient ring is GF(p,k) hasNumericCoeffs(rng) check for use of floating point numbers hasCommutativeVars(rng) non-commutive or commnuative polynomial ring hasGlobalOrdering(rng) global versus mixed/local monomial ordering hasMixedOrdering() mixed versus global/local ordering hasFieldCoefficient(rng) coefficients are a field hasAlgExtensionCoefficient(r) coefficients are an algebraic extension isQuotientRing(rng) ring is a qotient ring isSubModule(I,J) check if I is in J as submodule changeordTo(r,o) change the ordering of a ring to a simple one addvarsTo(r,vars,i) add variables to a ring addNvarsTo(r,N,name,i) add N variables to a ring "; LIB "inout.lib"; LIB "general.lib"; LIB "primdec.lib"; /////////////////////////////////////////////////////////////////////////////// proc optionIsSet(string optionName) " USAGE: optionIsSet( optionName ) PARAMETERS: optionName: a name as string of an option of interest RETURN: true, if the by optionName given option is active, false otherwise. EXAMPLE: example optionIsSet; " { intvec op = option(get); //sanity check, if option is valid. will raise an error if not option(optionName); option("no" + optionName); option(set,op); // first entry is currently a comment "//options:", which is not an option. int pos = find(option(), optionName, 11 ); return(pos>0); } example { // check if the option "warn" is set. optionIsSet("warn"); option("warn"); // now the option is set optionIsSet("warn"); option("nowarn"); // now the option is unset optionIsSet("warn"); } static proc testOptionIsSet() { option("warn"); ASSUME(0, optionIsSet("warn") ); option("nowarn"); ASSUME(0, 0 == optionIsSet("warn") ); } /////////////////////////////////////////////////////////////////////////////// proc changechar (list @L, list #) "USAGE: changechar(c[,r]); c=list, r=ring RETURN: ring R, obtained from the ring r [default: r=basering], by changing ringlist(r)[1] to c. EXAMPLE: example changechar; shows an example " { def save_ring=basering; if( size(#)==0 ) { def @r=basering; } if(( size(#)==1 ) and (typeof(#[1])=="ring")) { def @r=#[1]; } setring @r; list rl=ringlist(@r); if(defined(@L)!=voice) { def @L=fetch(save_ring,@L); } if (size(@L)==1) { rl[1]=@L[1];} else { rl[1]=@L;} def Rnew=ring(rl); setring save_ring; return(Rnew); } example { "EXAMPLE:"; echo = 2; ring rr=2,A,dp; ring r=0,(x,y,u,v),(dp(2),ds); def R=changechar(ringlist(rr)); R;""; def R1=changechar(32003,R); setring R1; R1; kill R,R1; } /////////////////////////////////////////////////////////////////////////////// proc changeord (list @o, list #) "USAGE: changeord(neword[,r]); newordstr=list, r=ring/qring RETURN: ring R, obtained from the ring r [default: r=basering], by changing order(r) to neword. If, say, neword=list(list(\"wp\",intvec(2,3)),list(list(\"dp\",1:(n-2)))); and if the ring r exists and has n variables, the ring R will be equipped with the monomial ordering wp(2,3),dp. EXAMPLE: example changeord; shows an example " { def save_ring=basering; if( size(#)==0 ) { def @r=basering; } if( size(#)==1 ) { def @r=#[1]; } setring @r; list rl=ringlist(@r); rl[3]=@o; def Rnew=ring(rl); setring save_ring; return(Rnew); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,u,v),(dp(2),ds); def R=changeord(list(list("wp",intvec(2,3)),list("dp",1:2))); R; ""; ideal i = x^2,y^2-u^3,v; qring Q = std(i); def Q'=changeord(list(list("lp",nvars(Q))),Q); setring Q'; Q'; kill R,Q,Q'; } /////////////////////////////////////////////////////////////////////////////// proc changevar (string vars, list #) "USAGE: changevar(vars[,r]); vars=string, r=ring/qring RETURN: ring R, obtained from the ring r [default: r=basering], by changing varstr(r) according to the value of vars. If, say, vars = \"t()\" and the ring r exists and has n variables, the new basering will have name R and variables t(1),...,t(n). If vars = \"a,b,c,d\", the new ring will have the variables a,b,c,d. NOTE: This procedure is useful in connection with the procedure ringtensor, when a conflict between variable names must be avoided. This proc uses 'execute' or calls a procedure using 'execute'. EXAMPLE: example changevar; shows an example " { if( size(#)==0 ) { def @r=basering; } if( size(#)==1 ) { def @r=#[1]; } setring @r; ideal i = ideal(@r); int @q = size(i); if( @q!=0 ) { string @s = "Rnew1"; } else { string @s = "Rnew"; } string @newring = @s+"=("+charstr(@r)+"),("; if( vars[size(vars)-1]=="(" and vars[size(vars)]==")" ) { @newring = @newring+vars[1,size(vars)-2]+"(1.."+string(nvars(@r))+")"; } else { @newring = @newring+vars; } string ords=ordstr(@r); int l=size(ords); int l1,l2; while(l>0) { if (ords[l]=="(") { l1=l; break; } if (ords[l]==")") { l2=l; } l--; } string last_ord=string(ords[l1-3..l1-1]); if ((last_ord[1]!="w") && (last_ord[1]!="W") && (last_ord[2]!="M")) { if (l2==size(ords)) { ords=string(ords[1..l1-1]); } else { ords=string(ords[1..l1-1])+string(ords[l2+1..size(ords)]); } } @newring = @newring+"),("+ords+");"; execute("ring "+@newring); if( @q!=0 ) { map phi = @r,maxideal(1); ideal i = phi(i); attrib(i,"isSB",1); //*** attrib funktioniert ? qring Rnew=i; } return(Rnew); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,u,v),(dp(2),ds); ideal i = x^2,y^2-u^3,v; qring Q = std(i); setring(r); def R=changevar("A()"); R; ""; def Q'=changevar("a,b,c,d",Q); setring Q'; Q'; kill R,Q,Q'; } /////////////////////////////////////////////////////////////////////////////// proc defring (string s2, int n, string s3, string s4) "USAGE: defring(ch,n,va,or); ch,va,or=strings, n=integer RETURN: ring R with characteristic 'ch', ordering 'or' and n variables with names derived from va. If va is a single letter, say va=\"a\", and if n<=26 then a and the following n-1 letters from the alphabet (cyclic order) are taken as variables. If n>26 or if va is a single letter followed by a bracket, say va=\"T(\", the variables are T(1),...,T(n). NOTE: This proc is useful for defining a ring in a procedure. This proc uses 'execute' or calls a procedure using 'execute'. EXAMPLE: example defring; shows an example " { string @newring = "ring newring =("+s2+"),("; if( n>26 or s3[2]=="(" ) { string @v = s3[1]+"(1.."+string(n)+")"; } else { string @v = A_Z(s3,n); } @newring=@newring+@v+"),("+s4+");"; execute(@newring); return(newring); } example { "EXAMPLE:"; echo = 2; def r=defring("0",5,"u","ls"); r; setring r;""; def R=defring("2,A",10,"x(","dp(3),ws(1,2,3),ds"); R; setring R; kill R,r; } /////////////////////////////////////////////////////////////////////////////// proc defrings (int n, list #) "USAGE: defrings(n,[p]); n,p integers RETURN: ring R with characteristic p [default: p=32003], ordering ds and n variables x,y,z,a,b,...if n<=26 (resp. x(1..n) if n>26) NOTE: This proc uses 'execute' or calls a procedure using 'execute'. EXAMPLE: example defrings; shows an example " { int p; if (size(#)==0) { p=32003; } else { p=#[1]; } if (n >26) { string s="ring S ="+string(p)+",x(1.."+string(n)+"),ds;"; } else { string s="ring S ="+string(p)+",("+A_Z("x",n)+"),ds;"; } execute(s); dbprint(printlevel-voice+2," // 'defrings' created a ring. To see the ring, type (if the name R was // assigned to the return value): show R; // To make the ring the active basering, type setring R; "); return(S); } example { "EXAMPLE:"; echo = 2; def S5=defrings(5,0); S5; ""; def S30=defrings(30); S30; kill S5,S30; } /////////////////////////////////////////////////////////////////////////////// proc defringp (int n,list #) "USAGE: defringp(n,[p]); n,p=integers RETURN: ring R with characteristic p [default: p=32003], ordering dp and n variables x,y,z,a,b,...if n<=26 (resp. x(1..n) if n>26) NOTE: This proc uses 'execute' or calls a procedure using 'execute'. EXAMPLE: example defringp; shows an example " { int p; if (size(#)==0) { p=32003; } else { p=#[1]; } if (n >26) { string s="ring P="+string(p)+",x(1.."+string(n)+"),dp;"; } else { string s="ring P="+string(p)+",("+A_Z("x",n)+"),dp;"; } execute(s); dbprint(printlevel-voice+2," // 'defringp' created a ring. To see the ring, type (if the name R was // assigned to the return value): show R; // To make the ring the active basering, type setring R; "); return(P); } example { "EXAMPLE:"; echo = 2; def P5=defringp(5,0); P5; ""; def P30=defringp(30); P30; kill P5,P30; } /////////////////////////////////////////////////////////////////////////////// proc extendring (int n, string va, string o, list #) "USAGE: extendring(n,va,o[,iv,i,r]); va,o=strings, n,i=integers, r=ring, iv=intvec of positive integers or iv=0 RETURN: ring R, which extends the ring r by adding n new variables in front of (resp. after, if i!=0) the old variables. [default: (i,r)=(0,basering)]. @* -- The characteristic is the characteristic of r. @* -- The new vars are derived from va. If va is a single letter, say va=\"T\", and if n<=26 then T and the following n-1 letters from T..Z..T (resp. T(1..n) if n>26) are taken as additional variables. If va is a single letter followed by a bracket, say va=\"x(\", the new variables are x(1),...,x(n). @* -- The ordering is the product ordering of the ordering of r and of an ordering derived from `o` [and iv]. @* - If o contains a 'c' or a 'C' in front resp. at the end, this is taken for the whole ordering in front, resp. at the end. If o does not contain a 'c' or a 'C' the same rule applies to ordstr(r). @* - If no intvec iv is given, or if iv=0, o may be any allowed ordstr, like \"ds\" or \"dp(2),wp(1,2,3),Ds(2)\" or \"ds(a),dp(b),ls\" if a and b are globally (!) defined integers and if a+b+1<=n. If, however, a and b are local to a proc calling extendring, the intvec iv must be used to let extendring know the values of a and b @* - If a non-zero intvec iv is given, iv[1],iv[2],... are taken for the 1st, 2nd,... block of o, if o contains no substring \"w\" or \"W\" i.e. no weighted ordering (in the above case o=\"ds,dp,ls\" and iv=a,b). If o contains a weighted ordering (only one (!) weighted block is allowed) iv[1] is taken as size for the weight-vector, the next iv[1] values of iv are taken as weights and the remaining values of iv as block size for the remaining non-weighted blocks. e.g. o=\"dp,ws,Dp,ds\", iv=3,2,3,4,2,5 creates the ordering dp(2),ws(2,3,4),Dp(5),ds NOTE: This proc is useful for adding deformation parameters. This proc uses 'execute' or calls a procedure using 'execute'. If you use it in your own proc, it may be advisable to let the local names of your proc start with a @ EXAMPLE: example extendring; shows an example " { //--------------- initialization and place c/C of ordering properly ----------- string @o1,@o2,@ro,@wstr,@v,@newring; int @i,@w,@ii,@k; intvec @iv,@iw; if( find(o,"c")+find(o,"C") != 0) { @k=1; if( o[1]=="c" or o[1]=="C" ) { @o1=o[1,2]; o=o[3..size(o)]; } else { @o2=o[size(o)-1,2]; o=o[1..size(o)-2]; } } if( size(#)==0 ) { #[1]=0; } if( typeof(#[1])!="intvec" ) { if( size(#)==1 ) { @i=#[1]; def @r=basering; } if( size(#)==2 ) { @i=#[1]; def @r=#[2]; } if( o[size(o)]!=")" and find(o,",")==0 ) { o=o+"("+string(n)+")"; } } else { @iv=#[1]; if( size(#)==2 ) { @i=#[2]; def @r=basering; } if( size(#)==3 ) { @i=#[2]; def @r=#[3]; } if( @iv==0 && o[size(o)]!=")" && find(o,",")==0 ) {o=o+"("+string(n)+")";} } @ro=ordstr(@r); if( @ro[1]=="c" or @ro[1]=="C" ) { @v=@ro[1,2]; @ro=@ro[3..size(@ro)]; } else { @wstr=@ro[size(@ro)-1,2]; @ro=@ro[1..size(@ro)-2]; } if( @k==0) { @o1=@v; @o2=@wstr; } //----------------- prepare ordering if an intvec is given -------------------- if( typeof(#[1])=="intvec" and #[1]!=0 ) { @k=n; //@k counts no of vars not yet ordered @w=find(o,"w")+find(o,"W");o=o+" "; if( @w!=0 ) { @wstr=o[@w..@w+1]; o=o[1,@w-1]+"@"+o[@w+2,size(o)]; @iw=@iv[2..@iv[1]+1]; @wstr=@wstr+"("+string(@iw)+")"; @k=@k-@iv[1]; @iv=@iv[@iv[1]+2..size(@iv)]; @w=0; } for( @ii=1; @ii<=size(@iv); @ii=@ii+1 ) { if( find(o,",",@w+1)!=0 ) { @w=find(o,",",@w+1); if( o[@w-1]!="@" ) { o=o[1,@w-1]+"("+string(@iv[@ii])+")"+o[@w,size(o)]; @w=find(o,",",@w+1); @k=@k-@iv[@ii]; } else { @ii=@ii-1; } } } @w=find(o,"@"); if( @w!=0 ) { o=o[1,@w-1] + @wstr + o[@w+1,size(o)]; } if( @k>0 and o[size(o)]!=")" ) { o=o+"("+string(@k)+")"; } } //------------------------ prepare string of new ring ------------------------- @newring = "ring na =("+charstr(@r)+"),("; if( n>26 or va[2]=="(" ) { @v = va[1]+"(1.."+string(n)+")"; } else { @v = A_Z(va,n); } if( @i==0 ) { @v=@v+","+varstr(@r); o=@o1+o+","+@ro+@o2; } else { @v=varstr(@r)+","+@v; o=@o1+@ro+","+o+@o2; } @newring=@newring+@v+"),("+o+");"; //---------------------------- execute and export ----------------------------- execute(@newring); dbprint(printlevel-voice+2," // 'extendring' created a new ring. // To see the ring, type (if the name 'R' was assigned to the return value): show(R); "); return(na); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),ds; show(r);""; // blocksize is derived from no of vars: int t=5; def R1=extendring(t,"a","dp"); //t global: "dp" -> "dp(5)" show(R1); setring R1; ""; def R2=extendring(4,"T(","c,dp",1,r); //"dp" -> "c,..,dp(4)" show(R2); setring R2; ""; // no intvec given, blocksize given: given blocksize is used: def R3=extendring(4,"T(","dp(2)",0,r); // "dp(2)" -> "dp(2)" show(R3); setring R3; ""; // intvec given: weights and blocksize is derived from given intvec // (no specification of a blocksize in the given ordstr is allowed!) // if intvec does not cover all given blocks, the last block is used // for the remaining variables, if intvec has too many components, // the last ones are ignored intvec v=3,2,3,4,1,3; def R4=extendring(10,"A","ds,ws,Dp,dp",v,0,r); // v covers 3 blocks: v[1] (=3) : no of components of ws // next v[1] values (=v[2..4]) give weights // remaining components of v are used for the remaining blocks show(R4); kill r,R1,R2,R3,R4; } /////////////////////////////////////////////////////////////////////////////// proc fetchall (def R, list #) "USAGE: fetchall(R[,s]); R=ring/qring, s=string CREATE: fetch all objects of ring R (of type poly/ideal/vector/module/number/matrix) into the basering. If no 2nd argument is present, the names are the same as in R. If, say, f is a polynomial in R and the 2nd argument is the string \"R\", then f is mapped to f_R etc. RETURN: no return value NOTE: As fetch, this procedure maps the 1st, 2nd, ... variable of R to the 1st, 2nd, ... variable of the basering. The 2nd argument is useful in order to avoid conflicts of names, the empty string is allowed CAUTION: fetchall does not work for locally defined names. It does not work if R contains a map. SEE ALSO: imapall EXAMPLE: example fetchall; shows an example " { list @L@=names(R); int @ii@; string @s@; if( size(#) > 0 ) { @s@=@s@+"_"+#[1]; } for( @ii@=size(@L@); @ii@>0; @ii@-- ) { execute("def "+@L@[@ii@]+@s@+"=fetch(R,`@L@[@ii@]`);"); execute("export "+@L@[@ii@]+@s@+";"); } return(); } example { "EXAMPLE:"; echo=2; // The example is not shown since fetchall does not work in a procedure; // (and hence not in the example procedure). Try the following commands: // ring R=0,(x,y,z),dp; // ideal j=x,y2,z2; // matrix M[2][3]=1,2,3,x,y,z; // j; print(M); // ring S=0,(a,b,c),ds; // fetchall(R); //map from R to S: x->a, y->b, z->c; // names(S); // j; print(M); // fetchall(S,"1"); //identity map of S: copy objects, change names // names(S); // kill R,S; } /////////////////////////////////////////////////////////////////////////////// proc imapall (def R, list #) "USAGE: imapall(R[,s]); R=ring/qring, s=string CREATE: map all objects of ring R (of type poly/ideal/vector/module/number/matrix) into the basering by applying imap to all objects of R. If no 2nd argument is present, the names are the same as in R. If, say, f is a polynomial in R and the 3rd argument is the string \"R\", then f is mapped to f_R etc. RETURN: no return value NOTE: As imap, this procedure maps the variables of R to the variables with the same name in the basering, the other variables are mapped to 0. The 2nd argument is useful in order to avoid conflicts of names, the empty string is allowed CAUTION: imapall does not work for locally defined names. It does not work if R contains a map SEE ALSO: fetchall EXAMPLE: example imapall; shows an example " { list @L@=names(R); int @ii@; string @s@; if( size(#) > 0 ) { @s@=@s@+"_"+#[1]; } for( @ii@=size(@L@); @ii@>0; @ii@-- ) { execute("def "+@L@[@ii@]+@s@+"=imap(R,`@L@[@ii@]`);"); execute("export "+@L@[@ii@]+@s@+";"); } return(); } example { "EXAMPLE:"; echo = 2; // The example is not shown since imapall does not work in a procedure // (and hence not in the example procedure). Try the following commands: // ring R=0,(x,y,z,u),dp; // ideal j=x,y,z,u2+ux+z; // matrix M[2][3]=1,2,3,x,y,uz; // j; print(M); // ring S=0,(a,b,c,x,z,y),ds; // imapall(R); //map from R to S: x->x, y->y, z->z, u->0 // names(S); // j; print(M); // imapall(S,"1"); //identity map of S: copy objects, change names // names(S); // kill R,S; } /////////////////////////////////////////////////////////////////////////////// proc mapall (def R, ideal i, list #) "USAGE: mapall(R,i[,s]); R=ring/qring, i=ideal of basering, s=string CREATE: map all objects of ring R (of type poly/ideal/vector/module/number/ matrix, map) into the basering by mapping the j-th variable of R to the j-th generator of the ideal i. If no 3rd argument is present, the names are the same as in R. If, say, f is a polynomial in R and the 3rd argument is the string \"R\", then f is mapped to f_R etc. RETURN: no return value. NOTE: This procedure has the same effect as defining a map, say psi, by map psi=R,i; and then applying psi to all objects of R. In particular, maps from R to some ring S are composed with psi, creating thus a map from the basering to S. mapall may be combined with copyring to change vars for all objects. The 3rd argument is useful in order to avoid conflicts of names, the empty string is allowed. CAUTION: mapall does not work for locally defined names. EXAMPLE: example mapall; shows an example " { list @L@=names(R); map @psi@ = R,i; int @ii@; string @s@; if( size(#) > 0 ) { @s@=@s@+"_"+#[1]; } for( @ii@=size(@L@); @ii@>0; @ii@-- ) { execute("def "+@L@[@ii@]+@s@+"=@psi@(`@L@[@ii@]`);"); execute("export "+@L@[@ii@]+@s@+";"); } return(); } example { "EXAMPLE:"; echo = 2; // The example is not shown since mapall does not work in a procedure // (and hence not in the example procedure). Try the following commands: // ring R=0,(x,y,z),dp; // ideal j=x,y,z; // matrix M[2][3]=1,2,3,x,y,z; // map phi=R,x2,y2,z2; // ring S=0,(a,b,c),ds; // ideal i=c,a,b; // mapall(R,i); //map from R to S: x->c, y->a, z->b // names(S); // j; print(M); phi; //phi maps R to S: x->c2, y->a2, z->b2 // ideal i1=a2,a+b,1; // mapall(R,i1,\"\"); //map from R to S: x->a2, y->a+b, z->1 // names(S); // j_; print(M_); phi_; // changevar(\"T\",\"x()\",R); //change vars in R and call result T // mapall(R,maxideal(1)); //identity map from R to T // names(T); // j; print(M); phi; // kill R,S,T; } /////////////////////////////////////////////////////////////////////////////// proc ord_test (def r) "USAGE: ord_test(r); r ring/qring RETURN: int 1 (resp. -1, resp. 0) if ordering of r is global (resp. local, resp. mixed) SEE ALSO: attrib EXAMPLE: example ord_test; shows an example " { if (typeof(r) != "ring") { ERROR("ord_test requires a ring/qring as input"); } if (attrib(r,"global")==1) { return(1);} def BAS = basering; setring r; poly f; int n,o,u = nvars(r),1,1; int ii; for ( ii=1; ii<=n; ii++ ) { f = 1+var(ii); o = o*(lead(f) == var(ii)); u = u*(lead(f) == 1); } setring BAS; if ( o==1 ) { return(1); } if ( u==1 ) { return(-1); } else { return(0); } } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),dp; ring S = 0,(u,v),ls; ord_test(R); ord_test(S); ord_test(R+S); } /////////////////////////////////////////////////////////////////////////////// proc ringtensor (list #) "USAGE: ringtensor(r1,r2,...); r1,r2,...=rings RETURN: ring R whose variables are the variables from all rings r1,r2,... and whose monomial ordering is the block (product) ordering of the respective monomial orderings of r1,r2,... . Hence, R is the tensor product of the rings r1,r2,... with ordering matrix equal to the direct sum of the ordering matrices of r1,r2,... NOTE: The characteristic of the new ring will be p if one ring has characteristic p. The names of variables in the rings r1,r2,... must differ. The procedure works also for quotient rings ri, if the characteristic of ri is compatible with the characteristic of the result (i.e. if imap from ri to the result is implemented) SEE ALSO: ring operations EXAMPLE: example ringtensor; shows an example " { int @i; int @n = size(#); if (@n<=1) { ERROR("at least 2 rings required"); } def @s=#[1]+#[2]; for (@i=3; @i<=@n;@i++) { def @ss=@s+#[@i]; kill @s; def @s=@ss; kill @ss; } dbprint(printlevel-voice+2," // 'ringtensor' created a ring. To see the ring, type (if the name R was // assigned to the return value): show(R); // To make the ring the active basering, type setring R; "); return(@s); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,u,v),dp; ring s=0,(a,b,c),wp(1,2,3); ring t=0,x(1..5),(c,ls); def R=ringtensor(r,s,t); type R; setring s; ideal i = a2+b3+c5; def S=changevar("x,y,z"); //change vars of s setring S; qring qS =std(fetch(s,i)); //create qring of S mod i (mapped to S) def T=changevar("d,e,f,g,h",t); //change vars of t setring T; qring qT=std(d2+e2-f3); //create qring of T mod d2+e2-f3 def Q=ringtensor(s,qS,t,qT); setring Q; type Q; kill R,S,T,Q; } /////////////////////////////////////////////////////////////////////////////// proc ringweights (def P) "USAGE: ringweights(P); P=name of an existing ring (true name, not a string) RETURN: intvec consisting of the weights of the variables of P, as they appear when typing P;. NOTE: This is useful when enlarging P but keeping the weights of the old variables. EXAMPLE: example ringweights; shows an example " { int i; intvec rw; //------------------------- find weights ------------------------- for(i=nvars(P);i>0;i--) { rw[i]=ord(var(i)); } return(rw); } example {"EXAMPLE:"; echo = 2; ring r0 = 0,(x,y,z),dp; ringweights(r0); ring r1 = 0,x(1..5),(ds(3),wp(2,3)); ringweights(r1);""; // an example for enlarging the ring, keeping the first weights: intvec v = ringweights(r1),6,2,3,4,5; ring R = 0,x(1..10),(a(v),dp); ordstr(R); } /////////////////////////////////////////////////////////////////////////////// proc preimageLoc(string R_name,string phi_name,string Q_name ) "USAGE: preimageLoc ( ring_name, map_name, ideal_name ); all input parameters of type string RETURN: ideal PURPOSE: compute the preimage of an ideal under a given map for non-global orderings. The 2nd argument has to be the name of a map from the basering to the given ring (or the name of an ideal defining such a map), and the ideal has to be an ideal in the given ring. SEE ALSO: preimage KEYWORDS: preimage under a map between local rings, map between local rings, map between local and global rings EXAMPLE: example preimageLoc ; shows an example "{ def S=basering; int i; string newRing,minpoly_string; if(attrib(S,"global")!=1) { if(size(ideal(S))>0) /*qring*/ { ideal I=ideal(S); newRing="ring S0=("+charstr(S)+"),("+varstr(S)+"),dp;"; minpoly_string=string(minpoly); execute(newRing); execute("minpoly="+minpoly_string+";"); ideal I=imap(S,I); list pr=primdecGTZ(I); newRing="ring SL=("+charstr(S)+"),("+varstr(S)+"),("+ordstr(S)+");"; execute(newRing); execute("minpoly="+minpoly_string+";"); list pr=imap(S0,pr); ideal I0=std(pr[1][1]); for(i=2;i<=size(pr);i++) { I0=intersect(I0,std(pr[i][1])); } setring S0; ideal I0=imap(SL,I0); qring S1=std(I0); } else { def S1=S; } } else { def S1=S; } def @R=`R_name`; setring @R; def @phi=`phi_name`; ideal phiId=ideal(@phi); def Q=`Q_name`; if(attrib(@R,"global")!=1) { if(size(ideal(@R))>0) /*qring*/ { ideal J=ideal(@R); newRing="ring R0=("+charstr(@R)+"),("+varstr(@R)+"),dp;"; minpoly_string=string(minpoly); execute(newRing); execute("minpoly="+minpoly_string+";"); ideal J=imap(@R,J); list pr=primdecGTZ(J); newRing="ring RL=("+charstr(@R)+"),("+varstr(@R)+"),("+ordstr(@R)+");"; execute(newRing); execute("minpoly="+minpoly_string+";"); list pr=imap(R0,pr); ideal J0=std(pr[1][1]); for(i=2;i<=size(pr);i++) { J0=intersect(J0,std(pr[i][1])); } setring R0; ideal J0=imap(RL,J0); qring R1=std(J0); ideal Q=imap(@R,Q); map @phi=S1,imap(@R,phiId); } else { def R1=@R; } } else { def R1=@R; } setring S1; ideal preQ=preimage(R1,@phi,Q); setring S; ideal prQ=imap(S1,preQ); return(prQ); } example { "EXAMPLE:"; echo=2; ring S =0,(x,y,z),dp; ring R0=0,(x,y,z),ds; qring R=std(x+x2); map psi=S,x,y,z; ideal null; setring S; ideal nu=preimageLoc("R","psi","null"); nu; } ////////////////////////////////////////////////////////////////////////////// /* moved here from the nctools.lib */ /////////////////////////////////////////////////////////////////////////////// proc rootofUnity(int n) "USAGE: rootofUnity(n); n an integer RETURN: number PURPOSE: compute the minimal polynomial for the n-th primitive root of unity NOTE: works only in field extensions by one element EXAMPLE: example rootofUnity; shows examples " { if ( npars(basering) !=1 ) { ERROR(" the procedure works only with one ring parameter variable"); } if (n<0) { ERROR(" cannot compute ("+string(n)+")-th primitive root of unity"); } if (n==0) { return(number(0));} number mp = par(1); if (n==1) { return(mp-1); } if (n==2) { return(mp+1); } def OldRing = basering; string CH = charstr(basering); string MCH; int j=1; while ( (CH[j] !=",") && (j<=size(CH))) { MCH=MCH+CH[j]; j++; } string SR = "ring @@rR="+MCH+","+parstr(basering)+",dp;"; execute(SR); poly @t=var(1)^n-1; // (x^2i-1)=(x^i-1)(x^i+1) list l=factorize(@t); ideal @l=l[1]; list @d; int s=size(@l); int d=deg(@l[s]); int cnt=1; poly res; for (j=s-1; j>=1; j--) { if ( deg(@l[j]) > d) { d=deg(@l[j]); } } for (j=1; j<=s; j++) { if ( deg(@l[j]) == d) { @d[cnt]=@l[j]; cnt++; } } j=1; int i; number pw; int @sized = size(@d); if (@sized==1) { setring OldRing; list @rl = imap(@@rR,@d); mp = number(@rl[1]); kill @@rR; return(mp); } def @rng; setring OldRing; list rl = ringlist( OldRing); while ( j<=@sized ) { ASSUME(0, n%2 ==0); setring OldRing; @rng = ring(rl); setring @rng; list @rl = imap(@@rR,@d); number mp = leadcoef( @rl[j] ); minpoly = mp; number mp = minpoly; number pw = par(1)^(n div 2); if ( (pw != 1) || n==1 ) { break; } j = j+1; } setring OldRing; list @rl=imap(@@rR,@d); mp = leadcoef( @rl[j] ); kill @@rR; return(mp); } example { "EXAMPLE:";echo=2; ring r = (0,q),(x,y,z),dp; rootofUnity(6); rootofUnity(7); minpoly = rootofUnity(8); r; } proc isQuotientRing(def rng ) "USAGE: isQuotientRing ( rng ); RETURN: 1 if rng is a quotient ring, 0 otherwise. PURPOSE: check if typeof a rng "qring" KEYWORDS: qring ring ideal 'factor ring' EXAMPLE: example isQuotientRing ; shows an example " { if ( defined(basering) ) { def BAS=basering; } else { return (0); } //access to quotient ideal will fail, if basering and rng differs. setring rng; int result = ( size(ideal(rng)) != 0); setring BAS; return (result); } example { "EXAMPLE:";echo=2; ring rng = 0,x,dp; isQuotientRing(rng); //no // if a certain method does not support quotient rings, // then a parameter test could be performed: ASSUME( 0, 0==isQuotientRing(basering)); qring q= ideal(x); // constructs rng/ideal(x) isQuotientRing(q); // yes } static proc testIsQuotientRing() { ring rng7 = 7, x, dp; ring rng = real,x,dp; ASSUME(0, 0== isQuotientRing(rng) ) ; ASSUME(0, 0== isQuotientRing(rng7) ) ; ASSUME(0, char(basering)==0); // check that basering was not changed qring qrng = 1; ASSUME(0, isQuotientRing(qrng) ) ; ring rng2 = integer,x,dp; ASSUME(0, 0 == isQuotientRing(rng2) ) ; qring qrng2=0; ASSUME(0, not isQuotientRing(qrng2) ) ; ring rng3 = 0,x,dp; ASSUME(0, 0 == isQuotientRing(rng3) ) ; qring qrng3=1; ASSUME(0, isQuotientRing(qrng3) ) ; } proc hasFieldCoefficient(def rng ) "USAGE: hasFieldCoefficient ( rng ); RETURN: 1 if the coefficients form (and are considered to be) a field, 0 otherwise. KEYWORDS: ring coefficients EXAMPLE: example hasFieldCoefficient; shows an example SEE ALSO: attrib " { return (attrib(rng,"ring_cf")==0); } example { "EXAMPLE:";echo=2; ring rng = integer,x,dp; hasFieldCoefficient(rng); //no // if a certain method supports only rings with integer coefficients, // then a parameter test could be performed: ring rng2 = 0, x, dp; hasFieldCoefficient(rng2); // yes } proc hasAlgExtensionCoefficient(def rng ) "USAGE: hasAlgExtensionCoefficient ( rng ); RETURN: 1 if the coeffcients are an gelebrai extension, 0 otherwise. KEYWORDS: ring coefficients EXAMPLE: example hasAlgExtensionCoefficient; shows an example " { def savering=basering; setring rng; int r=(string(minpoly)!="0"); setring savering; return(r); } example { "EXAMPLE:";echo=2; ring rng = integer,x,dp; hasAlgExtensionCoefficient(rng); //no ring rng2 = (0,a), x, dp; minpoly=a2-1; hasAlgExtensionCoefficient(rng2); // yes } proc hasGFCoefficient(def rng ) "USAGE: hasGFCoefficient ( rng ); RETURN: 1 if the coeffcients form GF(p,k), 0 otherwise. KEYWORDS: ring coefficients EXAMPLE: example hasGFCoefficient; shows an example " { return((charstr(rng)!=string(char(rng))) && (npars(rng)==1) && (find(charstr(rng),string(char(rng)))!=1) && (charstr(basering)<>"real")&& (charstr(basering)<>"complex") ); } example { ring r1 = integer,x,dp; hasGF(r1); ring r2 = (4,a),x,dp; hasGF(r2); } proc hasGlobalOrdering (def rng) "USAGE: hasGlobalOrdering ( rng ); RETURN: 1 if rng has a global monomial ordering, 0 otherwise. KEYWORDS: monomial ordering EXAMPLE: example hasGlobalOrdering; shows an example " { return (attrib(rng,"global")==1); } example { ring rng = integer,x,dp; hasGlobalOrdering(rng); //yes ring rng2 = 0, x, ds; hasGlobalOrdering(rng2); // no } proc hasCommutativeVars (def rng) "USAGE: hasCommutativeVars ( rng ); RETURN: 1 if rng is a commutative polynomial ring, 0 otherwise. KEYWORDS: plural EXAMPLE: example hasCommutativeVars; shows an example " { list rl=ringlist(rng); return (size(rl)==4); } example { ring r=0,(x,y,z),dp; hasCommutativeVars(r); } proc hasNumericCoeffs(def rng) "USAGE: hasNumericCoeffs ( rng ); RETURN: 1 if rng has inexact coeffcients, 0 otherwise. KEYWORDS: floating point EXAMPLE: example hasNumericCoeffs; shows an example " { ERROR("not yet implemented"); } proc isSubModule(def I,def J) "USAGE: isSubModule(I,J): I, J: ideal or module RETURN: 1 if module(I) is in module(J), 0 otherwise EXAMPLE: isSubModule; shows an example { if (attrib(J,"isSB")) { return(size(reduce(I,J,1))==0); } else { return(size(reduce(I,groebner(J),1))==0); } } example { "EXAMPLE:"; echo = 2; ring r=0,x,dp; ideal I1=x2; ideal I2=x3; isSubModule(I1, I2); isSubModule(I2, I1); } proc hasMixedOrdering() "USAGE: hasMixedOrdering(); RETURN: 1 if ordering of basering is mixed, 0 else EXAMPLE: example hasMixedOrdering(); shows an example " { int i,p,m; for(i = 1; i <= nvars(basering); i++) { if(var(i) > 1) { p++; } else { m++; } } if((p > 0) && (m > 0)) { return(1); } return(0); } example { "EXAMPLE:"; echo = 2; ring R1 = 0,(x,y,z),dp; hasMixedOrdering(); ring R2 = 31,(x(1..4),y(1..3)),(ds(4),lp(3)); hasMixedOrdering(); ring R3 = 181,x(1..9),(dp(5),lp(4)); hasMixedOrdering(); } proc changeordTo(def r,string o) "USAGE: changeordTo(ring, string s); RETURN: a ring with the oderinging changed to the (simple) ordering s EXAMPLE: example changeordTo(); shows an example " { list rl=ringlist(r); rl[3]=list(list("C",0),list(o,1:nvars(r))); def rr=ring(rl); return(rr); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),lp; def rr=changeordTo(r,"dp"); rr; } proc addvarsTo(def r,list vars,int blockorder) "USAGE: addvarsTo(ring,list_of_strings, int); int may be: 0:ordering: dp 1:ordering dp,dp 2:oring.ordering,dp RETURN: a ring with the addtional variables EXAMPLE: example addvarsTo(); shows an example " { list rl=ringlist(r); int n=nvars(r); rl[2]=rl[2]+vars; if (blockorder==0) { rl[3]=list(list("C",0),list("dp",1:(nvars(r)+size(vars)))); } else { if (blockorder==2) { rl[3]=rl[3]+list(list("dp",1:size(vars))); } else { rl[3]=list(list("C",0),list("dp",1:nvars(r)),list("dp",1:size(vars))); } } def rr=ring(rl); return(rr); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),lp; def rr=addvarsTo(r,list("a","b"),0); rr; kill rr; def rr=addvarsTo(r,list("a","b"),1); rr; kill rr; def rr=addvarsTo(r,list("a","b"),2); rr; } proc addNvarsTo(def r,int N,string n,int blockorder) "USAGE: addNvarsTo(ring,int N, string name, int b); b may be: 0:ordering: dp 1:ordering dp,dp 2:oring.ordering,dp RETURN: a ring with N addtional variables EXAMPLE: example addNvarsTo(); shows an example " { list v; for(int i=N;i>0;i--) { v[i]=n+"("+string(i)+")"; } return(addvarsTo(r,v,blockorder)); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y),lp; def rr=addNvarsTo(r,2,"@",0); rr; kill rr; def rr=addNvarsTo(r,2,"@",1); rr; kill rr; def rr=addNvarsTo(r,2,"@",2); rr; } singular-4.0.3+ds/Singular/LIB/ringgb.lib000066400000000000000000000250241266270727000201120ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version ringgb.lib 4.0.0.0 Jun_2013 "; // $Id: 4ddabf56c4914ebf04eacb3a180c200e78759fee $ category="Miscellaneous"; info=" LIBRARY: ringgb.lib Functions for coefficient rings AUTHOR: Oliver Wienand, email: wienand@mathematik.uni-kl.de KEYWORDS: vanishing polynomial; zeroreduce; polynomial functions; library, ringgb.lib; ringgb.lib, functions for coefficient rings PROCEDURES: findZeroPoly(f); finds a vanishing polynomial for reducing f zeroReduce(f); normal form of f concerning the ideal of vanishing polynomials testZero(poly f); tests f defines the constant zero function noElements(def r); the number of elements of the coefficient ring, if of type (integer, ...) "; LIB "general.lib"; /////////////////////////////////////////////////////////////////////////////// proc findZeroPoly (poly f) "USAGE: findZeroPoly(f); f - a polynomial RETURN: zero polynomial with the same leading term as f if exists, otherwise 0 EXAMPLE: example findZeroPoly; shows an example " { list data = getZeroCoef(f); if (data[1] == 0) { return(0); } number q = leadcoef(f) / data[1]; if (q == 0) { return(0); } poly g = getZeroPolyRaw(data[2]); g = leadmonom(f) / leadmonom(g) * g; return(q * data[1] * g); //return(system("findZeroPoly", f)); } example { "EXAMPLE:"; echo = 2; ring r = (integer, 65536), (y,x), dp; poly f = 1024*x^8*y^2+11264*x^8*y+28672*x^8+45056*x^7*y^2+36864*x^7*y+16384*x^7+40960*x^6*y^2+57344*x^6*y+32768*x^6+30720*x^5*y^2+10240*x^5*y+8192*x^5+35840*x^4*y^2+1024*x^4*y+20480*x^4+30720*x^3*y^2+10240*x^3*y+8192*x^3+4096*x^2*y^2+45056*x^2*y+49152*x^2+40960*x*y^2+57344*x*y+32768*x; findZeroPoly(f); } proc zeroReduce(poly f, list #) "USAGE: zeroReduce(f, [i = 0]); f - a polynomial, i - noise level (if != 0 prints all steps) RETURN: reduced normal form of f modulo zero polynomials EXAMPLE: example zeroReduce; shows an example " { int i = 0; if (size(#) > 0) { i = #[1]; } poly h = f; poly n = 0; poly g = findZeroPoly(h); if (i <> 0) { printf("reducing polyfct : %s", h); } while ( h <> 0 ) { while ( g <> 0 ) { h = h - g; if (i <> 0) { printf(" reduce with: %s", g); printf(" to: %s", h); } g = findZeroPoly(h); } n = lead(h) + n; if (i <> 0) { printf("head irreducible : %s", lead(h)); printf("irreducible start : %s", n); printf("remains to check : %s", h - lead(h)); } h = h - lead(h); g = findZeroPoly(h); } return(n); } example { "EXAMPLE:"; echo = 2; ring r = (integer, 65536), (y,x), dp; poly f = 1024*x^8*y^2+11264*x^8*y+28672*x^8+45056*x^7*y^2+36864*x^7*y+16384*x^7+40960*x^6*y^2+57344*x^6*y+32768*x^6+30720*x^5*y^2+10240*x^5*y+8192*x^5+35840*x^4*y^2+1024*x^4*y+20480*x^4+30720*x^3*y^2+10240*x^3*y+8192*x^3+4096*x^2*y^2+45056*x^2*y+49152*x^2+40960*x*y^2+57344*x*y+32768*x; zeroReduce(f); kill r; ring r = (integer, 2, 32), (x,y,z), dp; // Polynomial 1: poly p1 = 3795162112*x^3+587202566*x^2*y+2936012853*x*y*z+2281701376*x+548767119*y^3+16777216*y^2+268435456*y*z+1107296256*y+4244635648*z^3+4244635648*z^2+16777216*z; // Polynomial 2: poly p2 = 1647678464*x^3+587202566*x^2*y+2936012853*x*y*z+134217728*x+548767119*y^3+16777216*y^2+268435456*y*z+1107296256*y+2097152000*z^3+2097152000*z^2+16777216*z; zeroReduce(p1-p2); } proc testZero(poly f) "USAGE: testZero(f); f - a polynomial RETURN: returns 1 if f is zero as a function and otherwise a counterexample as a list [f(x_1, ..., x_n), x_1, ..., x_n] EXAMPLE: example testZero; shows an example " { poly g; int j; bigint i = 0; bigint modul = noElements(basering); printf("Teste %s Belegungen ...", modul^nvars(basering)); for (; i < modul^nvars(basering); i = i + 1) { if ((i + 1) % modul^(nvars(basering)/2) == 0) { printf("bisher: %s", i); } g = f; for (j = 1; j <= nvars(basering); j++) { g = subst(g, var(j), number((i / modul^(j-1)) % modul)); } if (g != 0) { list counter = g; for (j = 1; j <= nvars(basering); j++) { counter = insert(counter, (i / modul^(j-1)) % modul); } return(counter); } } return(1); } example { "EXAMPLE:"; echo = 2; ring r = (integer, 12), (y,x), dp; poly f = 1024*x^8*y^2+11264*x^8*y+28672*x^8+45056*x^7*y^2+36864*x^7*y+16384*x^7+40960*x^6*y^2+57344*x^6*y+32768*x^6+30720*x^5*y^2+10240*x^5*y+8192*x^5+35840*x^4*y^2+1024*x^4*y+20480*x^4+30720*x^3*y^2+10240*x^3*y+8192*x^3+4096*x^2*y^2+45056*x^2*y+49152*x^2+40960*x*y^2+57344*x*y+32768*x; zeroReduce(f); testZero(f); poly g = findZeroPoly(x2y3); g; testZero(g); } proc noElements(def r) "USAGE: noElements(r); r - a ring with a finite coefficient ring of type integer RETURN: returns the number of elements of the coefficient ring of r EXAMPLE: example noElements; shows an example " { list l = ringlist(basering); return(l[1][2][1]^l[1][2][2]); } example { "EXAMPLE:"; echo = 2; ring r = (integer, 233,6), (y,x), dp; noElements(r); } static proc getZeroCoef(poly f) { if (f == 0) { return(0, leadexp(f)) } list data = sort(leadexp(f)); intvec exp = data[1]; intvec index = data[2]; intvec nec = 0:size(exp); int i = 1; int j = 2; bigint g; bigint G = 1; bigint modul = noElements(basering); bigint B = modul; for (; exp[i] < 2; i++) {if (i == size(exp)) break;} for (; i <= size(exp); i++) { g = gcd(B, G); G = G * g; B = B / g; if (g != 1) { nec[index[i]] = j - 1; } if (B == 1) { return(B, nec); } for (; j <= exp[i]; j++) { g = gcd(B, bigint(j)); G = G * g; B = B / g; if (g != 1) { nec[index[i]] = j; } if (B == 1) { return(B, nec); } } } if (B == modul) { nec = 0; return(0, nec); } return(B, nec); } static proc getZeroPolyRaw(intvec fexp) { list data = sort(fexp); intvec exp = data[1]; intvec index = data[2]; int j = 0; poly res = 1; poly tillnow = 1; int i = 1; for (; exp[i] < 2; i++) {if (i == size(exp)) break;} for (; i <= size(exp); i++) { for (; j < exp[i]; j++) { tillnow = tillnow * (var(1) - j); } res = res * subst(tillnow, var(1), var(index[i])); } return(res); } static proc getZeroPoly(poly f) { list data = getZeroCoef(f); poly g = getZeroPolyRaw(data[2]); g = leadmonom(f) / leadmonom(g) * g; return(data[1] * g); } static proc findZeroPolyWrap (poly f) "USAGE: findZeroPolyWrap(f); f - a polynomial RETURN: zero polynomial with the same leading term as f if exists, otherwise 0 NOTE: just a wrapper, work only in Z/2^n with n < int_machine_size - 1 EXAMPLE: example findZeroPoly; shows an example " { return(system("findZeroPoly", f)); } example { "EXAMPLE:"; echo = 2; ring r = (integer, 2, 16), (y,x), dp; poly f = 1024*x^8*y^2+11264*x^8*y+28672*x^8+45056*x^7*y^2+36864*x^7*y+16384*x^7+40960*x^6*y^2+57344*x^6*y+32768*x^6+30720*x^5*y^2+10240*x^5*y+8192*x^5+35840*x^4*y^2+1024*x^4*y+20480*x^4+30720*x^3*y^2+10240*x^3*y+8192*x^3+4096*x^2*y^2+45056*x^2*y+49152*x^2+40960*x*y^2+57344*x*y+32768*x; findZeroPoly(f); } /////////////////////////////////////////////////////////////////////////////// /* Examples: // POLYNOMIAL EXAMPLES (Singular ready) // =================== // // For each of the examples below, there are three equivalent polynomials. 'm' indicates the bit-widths of the // input/output variables. For some of the polynomials, I have attached the RTL as well. // // // 1) VOLTERRA MODELS: // // A) CUBIC FILTER: (m = 32, 3 Vars) LIB "ringgb.lib"; ring r = (integer, 2, 32), (x,y,z), dp; poly p1 = 3795162112*x^3+587202566*x^2*y+2936012853*x*y*z+2281701376*x+548767119*y^3+16777216*y^2+268435456*y*z \ +1107296256*y+4244635648*z^3+4244635648*z^2+16777216*z; poly p2 = 1647678464*x^3+587202566*x^2*y+2936012853*x*y*z+134217728*x+548767119*y^3+16777216*y^2+268435456*y*z \ +1107296256*y+2097152000*z^3+2097152000*z^2+16777216*z; poly p3 = 1647678464*x^3+587202566*x^2*y+2936012853*x*y*z+134217728*x+548767119*y^3+16777216*y^2+268435456*y*z \ +1107296256*y+2097152000*z^3+2097152000*z^2+16777216*z; zeroReduce(p1-p2); zeroReduce(p1-p3); zeroReduce(p2-p3); // B) DEGREE-4 FILTER: (m=16 , 3 Vars) LIB "ringgb.lib"; ring r = (integer, 2, 16), (x,y,z), dp; poly p1 = 16384*x^4+y^4+57344*z^4+64767*x*y^3+16127*y^2*z^2+8965*x^3*z+19275*x^2*y*z+51903*x*y*z+32768*x^2*y \ +40960*z^2+32768*x*y^2+49152*x^2+4869*y; poly p2 = 8965*x^3*z+19275*x^2*y*z+31999*x*y^3+51903*x*y*z+32768*x*y+y^4+32768*y^3+16127*y^2*z^2+32768*y^2 \ +4869*y+57344*z^4+40960*z^2; poly p3 = 8965*x^3*z+19275*x^2*y*z+31999*x*y^3+51903*x*y*z+32768*x*y+y^4+16127*y^2*z^2+4869*y+16384*z^3+16384*z; zeroReduce(p1-p2); zeroReduce(p1-p3); zeroReduce(p2-p3); // 2) Savitzsky Golay filter(m=16,5 Vars) LIB "ringgb.lib"; ring r = (integer, 2, 16), (v,w,x,y,z), dp; poly p1 = 25000*v^2*y+37322*v^2+22142*v*w*z+50356*w^3+58627*w^2+17797*w+17797*x^3+62500*x^2*z+41667*x \ +22142*y^3+23870*y^2+59464*y+41667*z+58627; poly p2 = 25000*v^2*y+4554*v^2+22142*v*w*z+32768*v+17588*w^3+25859*w^2+17797*w+17797*x^3+29732*x^2*z+32768*x^2 \ +32768*x*z+8899*x+22142*y^3+23870*y^2+59464*y+41667*z+58627; poly p3 = 25000*v^2*y+4554*v^2+22142*v*w*z+32768*v+17588*w^3+25859*w^2+17797*w+17797*x^3+29732*x^2*z+32768*x*z \ +41667*x+22142*y^3+23870*y^2+59464*y+41667*z+58627; zeroReduce(p1-p2); zeroReduce(p1-p3); zeroReduce(p2-p3); // 3) Anti-alias filter:(m=16, 1 Var) LIB "ringgb.lib"; ring r = (integer, 2, 16), c, dp; poly p1 = 156*c^6+62724*c^5+17968*c^4+18661*c^3+43593*c^2+40224*c+13281; poly p2 = 156*c^6+5380*c^5+1584*c^4+43237*c^3+27209*c^2+40224*c+13281; poly p3 = 156*c^6+5380*c^5+1584*c^4+10469*c^3+27209*c^2+7456*c+13281; zeroReduce(p1-p2); zeroReduce(p1-p3); zeroReduce(p2-p3); // 4) PSK:(m=16, 2 Var) LIB "ringgb.lib"; ring r = (integer, 2, 16), (x,y), dp; poly p1 = 4166*x^4+16666*x^3*y+25000*x^2*y^2+15536*x^2+16666*x*y^4+31072*x*y+4166*y^4+15536*y^2+34464; poly p2 = 4166*x^4+16666*x^3*y+8616*x^2*y^2+16384*x^2*y+15536*x^2+282*x*y^4+47456*x*y+53318*y^4+31920*y^2+34464; poly p3 = 4166*x^4+16666*x^3*y+8616*x^2*y^2+16384*x^2*y+15536*x^2+282*x*y^4+47456*x*y+4166*y^4+15536*y^2+34464; zeroReduce(p1-p2); zeroReduce(p1-p3); zeroReduce(p2-p3); // Ref: A. Peymandoust G. De Micheli, “Application of Symbolic Computer Algebra in High-Level Data-Flow // Synthesis,” IEEE Transactions on CAD/ICAS, Vol. 22, No. 9, September 2003, pp.1154-1165. */ singular-4.0.3+ds/Singular/LIB/rinvar.lib000066400000000000000000001070441266270727000201460ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version rinvar.lib 4.0.1.1 Jan_2015 "; // $Id: 2036ae3633503991df7ec7126fbaec4d34f07234 $ category="Invariant theory"; info=" LIBRARY: rinvar.lib Invariant Rings of Reductive Groups AUTHOR: Thomas Bayer, tbayer@in.tum.de http://wwwmayr.informatik.tu-muenchen.de/personen/bayert/ Current Address: Institut fuer Informatik, TU Muenchen OVERVIEW: Implementation based on Derksen's algorithm. Written in the scope of the diploma thesis (advisor: Prof. Gert-Martin Greuel) 'Computations of moduli spaces of semiquasihomogenous singularities and an implementation in Singular' PROCEDURES: HilbertSeries(I, w); Hilbert series of the ideal I w.r.t. weight w HilbertWeights(I, w); weighted degrees of the generators of I ImageVariety(I, F); ideal of the image variety F(variety(I)) ImageGroup(G, F); ideal of G w.r.t. the induced representation InvariantRing(G, Gaction); generators of the invariant ring of G InvariantQ(f, G, Gaction); decide if f is invariant w.r.t. G LinearizeAction(G, Gaction); linearization of the action 'Gaction' of G LinearActionQ(action,s,t); decide if action is linear in var(s..nvars) LinearCombinationQ(base, f); decide if f is in the linear hull of 'base' MinimalDecomposition(f,s,t); minimal decomposition of f (like coef) NullCone(G, act); ideal of the nullcone of the action 'act' of G ReynoldsImage(RO,f); image of f under the Reynolds operator 'RO' ReynoldsOperator(G, Gaction); Reynolds operator of the group G SimplifyIdeal(I[,m,s]); simplify the ideal I (try to reduce variables) SEE ALSO: qhmoduli_lib, zeroset_lib "; LIB "presolve.lib"; LIB "elim.lib"; LIB "zeroset.lib"; LIB "ring.lib"; /////////////////////////////////////////////////////////////////////////////// proc EquationsOfEmbedding(ideal embedding, int nrs) "USAGE: EquationsOfEmbedding(embedding, s); ideal embedding; int s; PURPOSE: compute the ideal of the variety parameterized by 'embedding' by implicitation and change the variables to the old ones. RETURN: ideal ASSUME: nvars(basering) = n, size(embedding) = r and s = n - r. The polynomials of embedding contain only var(s + 1 .. n). NOTE: the result is the Zariski closure of the parameterized variety EXAMPLE: example EquationsOfEmbedding; shows an example " { ideal tvars; for(int i = nrs + 1; i <= nvars(basering); i++) { tvars[i - nrs] = var(i); } def RE1 = ImageVariety(ideal(0), embedding); // implicitation of the parameterization // map F = RE1, tvars; map F = RE1, maxideal(1); return(F(imageid)); } example {"EXAMPLE:"; echo = 2; ring R = 0,(s(1..5), t(1..4)),dp; ideal emb = t(1), t(2), t(3), t(3)^2; ideal I = EquationsOfEmbedding(emb, 5); I; } /////////////////////////////////////////////////////////////////////////////// proc ImageGroup(ideal Grp, ideal Gaction) "USAGE: ImageGroup(G, action); ideal G, action; PURPOSE: compute the ideal of the image of G in GL(m,K) induced by the linear action 'action', where G is an algebraic group and 'action' defines an action of G on K^m (size(action) = m). RETURN: ring, a polynomial ring over the same ground field as the basering, containing the ideals 'groupid' and 'actionid'. - 'groupid' is the ideal of the image of G (order <= order of G) - 'actionid' defines the linear action of 'groupid' on K^m. NOTE: 'action' and 'actionid' have the same orbits all variables which give only rise to 0's in the m x m matrices of G have been omitted. ASSUME: basering K[s(1..r),t(1..m)] has r + m variables, G is the ideal of an algebraic group and F is an action of G on K^m. G contains only the variables s(1)...s(r). The action 'action' is given by polynomials f_1,...,f_m in basering, s.t. on the ring level we have K[t_1,...,t_m] --> K[s_1,...,s_r,t_1,...,t_m]/G t_i --> f_i(s_1,...,s_r,t_1,...,t_m) EXAMPLE: example ImageGroup; shows an example " { int i, j, k, newVars, nrt, imageSize, dbPrt; ideal matrixEntries; matrix coMx; poly tVars; string ringSTR1, ringSTR2, order; dbPrt = printlevel-voice+2; dbprint(dbPrt, "Image Group of " + string(Grp) + ", action = " + string(Gaction)); def RIGB = basering; string @mPoly = string(minpoly); tVars = 1; k = 0; // compute the representation of G induced by Gaction, i.e., a matrix // of size(Gaction) x size(Gaction) and polynomials in s(1),...,s(r) as // entries // the matrix is represented as the list 'matrixEntries' where // the entries which are always 0 are omittet. for(i = 1; i <= ncols(Gaction); i++) { tVars = tVars * var(i + nvars(basering) - ncols(Gaction)); } for(i = 1; i <= ncols(Gaction); i++){ coMx = coef(Gaction[i], tVars); for(j = 1; j <= ncols(coMx); j++){ k++; matrixEntries[k] = coMx[2, j]; } } newVars = size(matrixEntries); nrt = ncols(Gaction); // this matrix defines an embedding of G into GL(m, K). // in the next step the ideal of this image is computed // note that we have omitted all variables which give give rise // only to 0's. Note that z(1..newVars) are slack variables def RIGR=addNvarsTo(basering,newVars,"z",1); setring RIGR; ideal I1, I2, Gn, G, F, mEntries, newGaction; G = imap(RIGB, Grp); F = imap(RIGB, Gaction); mEntries = imap(RIGB, matrixEntries); // prepare the ideals needed to compute the image // and compute the new action of the image on K^m for(i=1;i<=size(mEntries);i++){ I1[i] = var(i + nvars(RIGB))-mEntries[i]; } I1 = std(I1); for(i = 1; i <= ncols(F); i++) { newGaction[i] = reduce(F[i], I1); } I2 = G, I1; I2 = std(I2); Gn = nselect(I2, 1.. nvars(RIGB)); imageSize = ncols(Gn); // create a new basering which might contain more variables // s(1..newVars) as the original basering and map the ideal // Gn (contians only z(1..newVars)) to this ring ringSTR2 = "ring RIGS = (" + charstr(basering) + "), (s(1.." + string(newVars) + "), t(1.." + string(nrt) + ")), lp;"; execute(ringSTR2); execute("minpoly = number(" + @mPoly + ");"); ideal mapIdeal, groupid, actionid; int offset; // construct the map F : RIGB -> RIGS for(i=1;i<=nvars(RIGB)-nrt;i++) { mapIdeal[i] = 0;} // s(i)-> 0 offset = nvars(RIGB) - nrt; for(i=1;i<=nrt;i++) { mapIdeal[i+offset] = var(newVars + i);} // t(i)->t(i) offset = offset + nrt; for(i=1;i<=newVars;i++) { mapIdeal[i + offset] = var(i);} // z(i)->s(i) // map Gn and newGaction to RIGS map F = RIGR, mapIdeal; groupid = F(Gn); actionid = F(newGaction); export groupid, actionid; dbprint(dbPrt+1, " // 'ImageGroup' created a new ring. // To see the ring, type (if the name 'R' was assigned to the return value): show(R); // To access the ideal of the image of the input group and to access the new // action of the group, type setring R; groupid; actionid; "); setring RIGB; return(RIGS); } example {"EXAMPLE:"; echo = 2; ring B = 0,(s(1..2), t(1..2)),dp; ideal G = s(1)^3-1, s(2)^10-1; ideal action = s(1)*s(2)^8*t(1), s(1)*s(2)^7*t(2); def R = ImageGroup(G, action); setring R; groupid; actionid; } /////////////////////////////////////////////////////////////////////////////// proc HilbertWeights(ideal I,intvec wt) "USAGE: HilbertWeights(I, w); ideal I, intvec wt PURPOSE: compute the weights of the "slack" variables needed for the computation of the algebraic relations of the generators of 'I' s.t. the Hilbert driven 'std' can be used. RETURN: intvec ASSUME: basering = K[t_1,...,t_m,...], 'I' is quasihomogenous w.r.t. 'w' and contains only polynomials in t_1,...,t_m " { int offset = size(wt); intvec wtn = wt; for(int i = 1; i <= size(I); i++) { wtn[offset + i] = deg(I[i], wt); } return(wtn); } /////////////////////////////////////////////////////////////////////////////// proc HilbertSeries(ideal I,intvec wt) "USAGE: HilbertSeries(I, w); ideal I, intvec wt PURPOSE: compute the polynomial p of the Hilbert Series, represented by p/q, of the ring K[t_1,...,t_m,y_1,...,y_r]/I1 where 'w' are the weights of the variables, computed, e.g., by 'HilbertWeights', 'I1' is of the form I[1] - y_1,...,I[r] - y_r and is quasihomogenous w.r.t. 'w' RETURN: intvec NOTE: the leading 0 of the result does not belong to p, but is needed in the Hilbert driven 'std'. " { int i; intvec hs1; matrix coMx; poly f = 1; for(i = 1; i <= ncols(I); i++) { f = f * (1 - var(1)^deg(I[i], wt));} coMx = coeffs(f, var(1)); for(i = 1; i <= deg(f) + 1; i++) { hs1[i] = int(coMx[i, 1]); } hs1[size(hs1) + 1] = 0; return(hs1); } /////////////////////////////////////////////////////////////////////////////// proc HilbertSeries1(wt) "USAGE: HilbertSeries1(wt); ideal I, intvec wt PURPOSE: compute the polynomial p of the Hilbert Series represented by p/q of the ring K[t_1,...,t_m,y_1,...,y_r]/I where I is a complete inter- section and the generator I[i] has degree wt[i] RETURN: poly " { int i, j; intvec hs1; matrix ma; poly f = 1; for(i = 1; i <= size(wt); i++) { f = f * (1 - var(1)^wt[i]);} ma = coef(f, var(1)); j = ncols(ma); for(i = 0; i <= deg(f); i++) { if(var(1)^i == ma[1, j]) { hs1[i + 1] = int(ma[2, j]); j--; } else { hs1[i + 1] = 0; } } hs1[size(hs1) + 1] = 0; return(hs1); } /////////////////////////////////////////////////////////////////////////////// proc ImageVariety(ideal I,ideal F, list #) "USAGE: ImageVariety(ideal I, F [, w]);ideal I; F is a list/ideal, intvec w. PURPOSE: compute the Zariski closure of the image of the variety of I under the morphism F. NOTE: if 'I' and 'F' are quasihomogenous w.r.t. 'w' then the Hilbert-driven 'std' is used. RETURN: polynomial ring over the same ground field, containing the ideal 'imageid'. The variables are Y(1),...,Y(k) where k = size(F) - 'imageid' is the ideal of the Zariski closure of F(X) where X is the variety of I. EXAMPLE: example ImageVariety; shows an example " { int i, dbPrt, nrNewVars; intvec wt, wth, hs1; def RARB = basering; nrNewVars = ncols(F); dbPrt = printlevel-voice+2; dbprint(dbPrt, "ImageVariety of " + string(I) + " under the map " + string(F)); if(size(#) > 0) { wt = #[1]; } // create new ring for elimination, Y(1),...,Y(m) are slack variables. //string @mPoly = string(minpoly); def RAR1=addNvarsTo(basering,nrNewVars,"Y",1); setring RAR1; list RAR2l=ringlist(RAR1); list RAR2ll=RAR2l[2]; RAR2ll=RAR2ll[size(RAR2ll)-nrNewVars+1..size(RAR2ll)]; RAR2l[2]=RAR2ll; RAR2l[3]=list(list("dp",1:nrNewVars),list("C",0)); def RAR2=ring(RAR2l); ideal I, J1, J2, Fm; I = imap(RARB, I); Fm = imap(RARB, F); if(size(wt) > 1) { wth = HilbertWeights(Fm, wt); hs1 = HilbertSeries(Fm, wt); } // get the ideal of the graph of F : X -> Y and compute a standard basis for(i = 1; i <= nrNewVars; i++) { J1[i] = var(i + nvars(RARB)) - Fm[i];} J1 = J1, I; if(size(wt) > 1) { J1 = std(J1, hs1, wth); // Hilbert-driven algorithm } else { J1 = std(J1); } // forget all elements which contain other than the slack variables J2 = nselect(J1, 1.. nvars(RARB)); setring RAR2; ideal imageid = imap(RAR1, J2); export(imageid); dbprint(dbPrt+1, " // 'ImageVariety' created a new ring. // To see the ring, type (if the name 'R' was assigned to the return value): show(R); // To access the ideal of the image variety, type setring R; imageid; "); setring RARB; return(RAR2); } example {"EXAMPLE:"; echo = 2; ring B = 0,(x,y),dp; ideal I = x4 - y4; ideal F = x2, y2, x*y; def R = ImageVariety(I, F); setring R; imageid; } /////////////////////////////////////////////////////////////////////////////// proc LinearizeAction(ideal Grp,def Gaction, int nrs) "USAGE: LinearizeAction(G,action,r); ideal G, action; int r PURPOSE: linearize the group action 'action' and find an equivariant embedding of K^m where m = size(action). ASSUME: G contains only variables var(1..r) (r = nrs) basering = K[s(1..r),t(1..m)], K = Q or K = Q(a) and minpoly != 0. RETURN: polynomial ring containing the ideals 'actionid', 'embedid', 'groupid' - 'actionid' is the ideal defining the linearized action of G - 'embedid' is a parameterization of an equivariant embedding (closed) - 'groupid' is the ideal of G in the new ring NOTE: set printlevel > 0 to see a trace EXAMPLE: example LinearizeAction; shows an example " { def altring = basering; int i, j, k, ok, loop, nrt, sizeOfDecomp, dbPrt; intvec wt; ideal action, basis, G, reduceIdeal; matrix decompMx; poly actCoeff; string str, order; dbPrt = printlevel-voice+2; dbprint(dbPrt, "LinearizeAction " + string(Gaction)); def RLAR = basering; string @mPoly = string(minpoly); order = ordstr(basering); nrt = ncols(Gaction); for(i = 1; i <= nrs; i++) { wt[i] = 0;} for(i = nrs + 1; i <= nrs + nrt; i++) { basis[i - nrs] = var(i); wt[i] = 1;} dbprint(dbPrt, " basis = " + string(basis)); if(attrib(Grp, "isSB")) { G = Grp; } else { G = std(Grp); } reduceIdeal = G; action = Gaction; loop = 1; i = 1; // check if each component of 'action' is linear in t(1),...,t(nrt). while(loop){ if(deg(action[i], wt) <= 1) { sizeOfDecomp = 0; dbprint(dbPrt, " " + string(action[i]) + " is linear"); } else { // action[i] is not linear // compute the minimal decomposition of action[i] // action[i]=decompMx[1,1]*decompMx[2,1]+ ... +decompMx[1,k]*decompMx[2,k] // decompMx[1,j] contains variables var(1)...var(nrs) // decompMx[2,j] contains variables var(nrs + 1)...var(nvars(basering)) dbprint(dbPrt, " " + string(action[i]) + " is not linear, a minimal decomposition is :"); decompMx = MinimalDecomposition(action[i], nrs, nrt); sizeOfDecomp = ncols(decompMx); dbprint(dbPrt, decompMx); for(j = 1; j <= sizeOfDecomp; j++) { // check if decompMx[2,j] is a linear combination of basis elements actCoeff = decompMx[2, j]; ok = LinearCombinationQ(basis, actCoeff, nrt + nrs); if(ok == 0) { // nonlinear element, compute new component of the action dbprint(dbPrt, " the polynomial " + string(actCoeff) + " is not a linear combination of the elements of basis"); nrt++; str = charstr(basering) + ", (" + varstr(basering) + ",t(" + string(nrt) + ")),"; if(defined(RLAB)) { kill RLAB;} def RLAB = basering; if(defined(RLAR)) { kill RLAR;} execute("ring RLAR = " + str + "(" + order + ");"); execute("minpoly = number(" + @mPoly + ");"); ideal basis, action, G, reduceIdeal; matrix decompMx; map F; poly actCoeff; wt[nrs + nrt] = 1; basis = imap(RLAB, basis), imap(RLAB, actCoeff); action = imap(RLAB, action); decompMx = imap(RLAB, decompMx); actCoeff = imap(RLAB, actCoeff); G = imap(RLAB, G); attrib(G, "isSB", 1); reduceIdeal = imap(RLAB, reduceIdeal), actCoeff - var(nrs + nrt); // compute action on the new basis element for(k = 1; k <= nrs; k++) { F[k] = 0;} for(k = nrs + 1; k < nrs + nrt; k++) { F[k] = action[k - nrs];} actCoeff = reduce(F(actCoeff), G); action[ncols(action) + 1] = actCoeff; dbprint(dbPrt, " extend basering by " + string(var(nrs + nrt))); dbprint(dbPrt, " new basis = " + string(basis)); dbprint(dbPrt, " action of G on new basis element = " + string(actCoeff)); dbprint(dbPrt, " decomp : " + string(decompMx[2, j]) + " -> " + string(var(nrs + nrt))); } // end if else { dbprint(dbPrt, " the polynomial " + string(actCoeff) + " is a linear combination of the elements of basis"); } } // end for reduceIdeal = std(reduceIdeal); action[i] = reduce(action[i], reduceIdeal); } // end else if(i < ncols(action)) { i++;} else {loop = 0;} } // end while if(defined(actionid)) { kill actionid; } ideal actionid, embedid, groupid; actionid = action; embedid = basis; groupid = G; export actionid, embedid, groupid; dbprint(dbPrt+1, " // 'LinearizeAction' created a new ring. // To see the ring, type (if the name 'R' was assigned to the return value): show(R); // To access the new action and the equivariant embedding, type setring R; actionid; embedid; groupid "); setring altring; return(RLAR); } example {"EXAMPLE:"; echo = 2; ring B = 0,(s(1..5), t(1..3)),dp; ideal G = s(3)-s(4), s(2)-s(5), s(4)*s(5), s(1)^2*s(4)+s(1)^2*s(5)-1, s(1)^2*s(5)^2-s(5), s(4)^4-s(5)^4+s(1)^2, s(1)^4+s(4)^3-s(5)^3, s(5)^5-s(1)^2*s(5); ideal action = -s(4)*t(1)+s(5)*t(1), -s(4)^2*t(2)+2*s(4)^2*t(3)^2+s(5)^2*t(2), s(4)*t(3)+s(5)*t(3); LinearActionQ(action, 5); def R = LinearizeAction(G, action, 5); setring R; R; actionid; embedid; groupid; LinearActionQ(actionid, 5); } /////////////////////////////////////////////////////////////////////////////// proc LinearActionQ(def Gaction, int nrs) "USAGE: LinearActionQ(action,nrs); ideal action, int nrs PURPOSE: check whether the action defined by 'action' is linear w.r.t. the variables var(nrs + 1...nvars(basering)). RETURN: 0 action not linear 1 action is linear EXAMPLE: example LinearActionQ; shows an example " { int i, nrt, loop; intvec wt; nrt = ncols(Gaction); for(i = 1; i <= nrs; i++) { wt[i] = 0;} for(i = nrs + 1; i <= nrs + nrt; i++) { wt[i] = 1;} loop = 1; i = 1; while(loop) { if(deg(Gaction[i], wt) > 1) { loop = 0; } else { i++; if(i > ncols(Gaction)) { loop = 0;} } } return(i > ncols(Gaction)); } example {"EXAMPLE:"; echo = 2; ring R = 0,(s(1..5), t(1..3)),dp; ideal G = s(3)-s(4), s(2)-s(5), s(4)*s(5), s(1)^2*s(4)+s(1)^2*s(5)-1, s(1)^2*s(5)^2-s(5), s(4)^4-s(5)^4+s(1)^2, s(1)^4+s(4)^3-s(5)^3, s(5)^5-s(1)^2*s(5); ideal Gaction = -s(4)*t(1)+s(5)*t(1), -s(4)^2*t(2)+2*s(4)^2*t(3)^2+s(5)^2*t(2), s(4)*t(3)+s(5)*t(3); LinearActionQ(Gaction, 5); LinearActionQ(Gaction, 8); } /////////////////////////////////////////////////////////////////////////////// proc LinearCombinationQ(ideal I, poly f) "USAGE: LinearCombination(I, f); ideal I, poly f PURPOSE: test whether f can be written as a linear combination of the generators of I. RETURN: 0 f is not a linear combination 1 f is a linear combination " { int i, loop, sizeJ; ideal J; J = I, f; sizeJ = size(J); def RLC = ImageVariety(ideal(0), J); // compute algebraic relations setring RLC; matrix coMx; poly relation = 0; loop = 1; i = 1; while(loop) { // look for a linear relation containing Y(nr) if(deg(imageid[i]) == 1) { coMx = coef(imageid[i], var(sizeJ)); if(coMx[1,1] == var(sizeJ)) { relation = imageid[i]; loop = 0; } } else { i++; if(i > ncols(imageid)) { loop = 0;} } } return(i <= ncols(imageid)); } /////////////////////////////////////////////////////////////////////////////// proc InvariantRing(ideal G, ideal action, list #) "USAGE: InvariantRing(G, Gact [, opt]); ideal G, Gact; int opt PURPOSE: compute generators of the invariant ring of G w.r.t. the action 'Gact' ASSUME: G is a finite group and 'Gact' is a linear action. RETURN: ring R; this ring comes with the ideals 'invars' and 'groupid' and with the poly 'newA': - 'invars' contains the algebra generators of the invariant ring - 'groupid' is the ideal of G in the new ring - 'newA' is the new representation of the primitive root of the minimal polynomial of the ring which was active when calling the procedure (if the minpoly did not change, 'newA' is set to 'a'). NOTE: the minimal polynomial of the output ring depends on some random choices EXAMPLE: example InvariantRing; shows an example " { int i, ok, dbPrt, noReynolds, primaryDec; ideal invarsGens, groupid; dbPrt = printlevel-voice+2; if(size(#) > 0) { primaryDec = #[1]; } else { primaryDec = 0; } dbprint(dbPrt, "InvariantRing of " + string(G)); dbprint(dbPrt, " action = " + string(action)); if(!attrib(G, "isSB")) { groupid = std(G);} else { groupid = G; } // compute the nullcone of G by means of Derksen's algorithm invarsGens = NullCone(groupid, action); // compute nullcone of linear action dbprint(dbPrt, " generators of zero-fibre ideal are " + string(invarsGens)); // make all generators of the nullcone invariant // if necessary, compute the Reynolds Operator, i.e., find all elements // of the variety defined by G. It might be necessary to extend the // ground field. def IRB = basering; if(defined(RIRR)) { kill RIRR;} def RIRR = basering; setring RIRR; // export(RIRR); // export(invarsGens); noReynolds = 1; dbprint(dbPrt, " nullcone is generated by " + string(size(invarsGens))); dbprint(dbPrt, " degrees = " + string(maxdeg(invarsGens))); for(i = 1; i <= ncols(invarsGens); i++){ ok = InvariantQ(invarsGens[i], groupid, action); if(ok) { dbprint(dbPrt, string(i) + ": poly " + string(invarsGens[i]) + " is invariant");} else { if(noReynolds) { // compute the Reynolds operator and change the ring ! noReynolds = 0; def RORN = ReynoldsOperator(groupid, action, primaryDec); setring RORN; ideal groupid = std(id); attrib(groupid, "isSB", 1); ideal action = actionid; setring RIRR; string parName, minPoly; if(npars(basering) == 0) { parName = "a"; minPoly = "0"; } else { parName = parstr(basering); minPoly = string(minpoly); } execute("ring RA1=0,(" + varstr(basering) + "," + parName + "), lp;"); if (minPoly!="0") { execute("ideal mpoly = std(" + minPoly + ");"); } ideal I = imap(RIRR,invarsGens); setring RORN; map Phi = RA1, maxideal(1); Phi[nvars(RORN) + 1] = newA; ideal invarsGens = Phi(I); kill Phi,RA1,RIRR; // end of ersetzt durch } dbprint(dbPrt, string(i) + ": poly " + string(invarsGens[i]) + " is NOT invariant"); invarsGens[i] = ReynoldsImage(ROelements, invarsGens[i]); dbprint(dbPrt, " --> " + string(invarsGens[i])); } } for(i = 1; i <= ncols(invarsGens); i++){ ok = InvariantQ(invarsGens[i], groupid, action); if(ok) { dbprint(dbPrt, string(i) + ": poly " + string(invarsGens[i]) + " is invariant"); } else { print(string(i) + ": Fatal Error with Reynolds ");} } if(noReynolds == 0) { def RIRS = RORN; setring RIRS; kill RORN; export groupid; } else { def RIRS = RIRR; kill RIRR; setring RIRS; export groupid; } ideal invars = invarsGens; kill invarsGens; if (defined(ROelements)) { kill ROelements,actionid,theZeroset,id; } export invars; dbprint(dbPrt+1, " // 'InvariantRing' created a new ring. // To see the ring, type (if the name 'R' was assigned to the return value): show(R); // To access the generators of the invariant ring type setring R; invars; // Note that the input group G is stored in R as the ideal 'groupid'; to // see it, type groupid; // Note that 'InvariantRing' might change the minimal polynomial // The representation of the algebraic number is given by 'newA' "); setring IRB; return(RIRS); } example {"EXAMPLE:"; echo = 2; ring B = 0, (s(1..2), t(1..2)), dp; ideal G = -s(1)+s(2)^3, s(1)^4-1; ideal action = s(1)*t(1), s(2)*t(2); def R = InvariantRing(std(G), action); setring R; invars; } /////////////////////////////////////////////////////////////////////////////// proc InvariantQ(poly f, ideal G,def action) "USAGE: InvariantQ(f, G, action); poly f; ideal G, action PURPOSE: check whether the polynomial f is invariant w.r.t. G, where G acts via 'action' on K^m. ASSUME: basering = K[s_1,...,s_m,t_1,...,t_m] where K = Q of K = Q(a) and minpoly != 0, f contains only t_1,...,t_m, G is the ideal of an algebraic group and a standardbasis. RETURN: int; 0 if f is not invariant, 1 if f is invariant NOTE: G need not be finite " { def altring=basering; map F; if(deg(f) == 0) { return(1); } for(int i = 1; i <= size(action); i++) { F[nvars(basering) - size(action) + i] = action[i]; } return(reduce(f - F(f), G) == 0); } /////////////////////////////////////////////////////////////////////////////// proc MinimalDecomposition(poly f, int nrs, int nrt) "USAGE: MinimalDecomposition(f,a,b); poly f; int a, b. PURPOSE: decompose f as a sum M[1,1]*M[2,1] + ... + M[1,r]*M[2,r] where M[1,i] contains only s(1..a), M[2,i] contains only t(1...b) s.t. r is minimal ASSUME: f polynomial in K[s(1..a),t(1..b)], K = Q or K = Q(a) and minpoly != 0 RETURN: 2 x r matrix M s.t. f = M[1,1]*M[2,1] + ... + M[1,r]*M[2,r] EXAMPLE: example MinimalDecomposition; " { int i, sizeOfMx, changed, loop; list initialTerms; matrix coM1, coM2, coM, decompMx, auxM; matrix m[2][2] = 0,1,1,0; poly vars1, vars2; if(f == 0) { return(decompMx); } // first decompose f w.r.t. t(1..nrt) // then decompose f w.r.t. s(1..nrs) vars1 = RingVarProduct(nrs+1..nrt+nrs); vars2 = RingVarProduct(1..nrs); coM1 = SimplifyCoefficientMatrix(m*coef(f, vars1)); // exchange rows of decomposition coM2 = SimplifyCoefficientMatrix(coef(f, vars2)); if(ncols(coM2) < ncols(coM1)) { auxM = coM1; coM1 = coM2; coM2 = auxM; } decompMx = coM1; // decompMx is the smaller decomposition if(ncols(decompMx) == 1) { return(decompMx);} // n = 1 is minimal changed = 0; loop = 1; i = 1; // first loop, try coM1 while(loop) { coM = MinimalDecomposition(f - coM1[1, i]*coM1[2, i], nrs, nrt); if(size(coM) == 1) { sizeOfMx = 0; } // coM = 0 else {sizeOfMx = ncols(coM); } // number of columns if(sizeOfMx + 1 < ncols(decompMx)) { // shorter decomposition changed = 1; decompMx = coM; initialTerms[1] = coM1[1, i]; initialTerms[2] = coM1[2, i]; } if(sizeOfMx == 1) { loop = 0;} // n = 2 is minimal if(i < ncols(coM1)) {i++;} else {loop = 0;} } if(sizeOfMx > 1) { // n > 2 loop = 1; // coM2 might yield i = 1; // a smaller decomposition } // first loop, try coM2 while(loop) { coM = MinimalDecomposition(f - coM2[1, i]*coM2[2, i], nrs, nrt); if(size(coM) == 1) { sizeOfMx = 0; } else {sizeOfMx = ncols(coM); } if(sizeOfMx + 1 < ncols(decompMx)) { changed = 1; decompMx = coM; initialTerms[1] = coM2[1, i]; initialTerms[2] = coM2[2, i]; } if(sizeOfMx == 1) { loop = 0;} if(i < ncols(coM2)) {i++;} else {loop = 0;} } if(!changed) { return(decompMx); } if(size(decompMx) == 1) { matrix decompositionM[2][1];} else { matrix decompositionM[2][ncols(decompMx) + 1];} decompositionM[1, 1] = initialTerms[1]; decompositionM[2, 1] = initialTerms[2]; if(size(decompMx) > 1) { for(i = 1; i <= ncols(decompMx); i++) { decompositionM[1, i + 1] = decompMx[1, i]; decompositionM[2, i + 1] = decompMx[2, i]; } } return(decompositionM); } example {"EXAMPLE:"; echo = 2; ring R = 0, (s(1..2), t(1..2)), dp; poly h = s(1)*(t(1) + t(1)^2) + (t(2) + t(2)^2)*(s(1)^2 + s(2)); matrix M = MinimalDecomposition(h, 2, 2); M; M[1,1]*M[2,1] + M[1,2]*M[2,2] - h; } /////////////////////////////////////////////////////////////////////////////// proc NullCone(ideal G,def action) "USAGE: NullCone(G, action); ideal G, action PURPOSE: compute the ideal of the nullcone of the linear action of G on K^n, given by 'action', by means of Deksen's algorithm ASSUME: basering = K[s(1..r),t(1..n)], K = Q or K = Q(a) and minpoly != 0, G is an ideal of a reductive algebraic group in K[s(1..r)], 'action' is a linear group action of G on K^n (n = ncols(action)) RETURN: ideal of the nullcone of G. NOTE: the generators of the nullcone are homogenous, but in general not invariant EXAMPLE: example NullCone; shows an example " { int i, nt, dbPrt, offset, groupVars; string ringSTR, vars, order; def RNCB = basering; // prepare the ring needed for the computation // s(1...) variables of the group // t(1...) variables of the affine space // y(1...) additional 'slack' variables nt = size(action); order = "(dp(" + string(nvars(basering) - nt) + "), dp);"; vars = "(s(1.." + string(nvars(basering) - nt); vars = vars +"),t(1.."+string(nt) + "), Y(1.." + string(nt) + "))," + order; ringSTR = "ring RNCR = (" + charstr(basering) + ")," + vars; // ring for the computation string @minPoly = string(minpoly); offset = size(G) + nt; execute(ringSTR); execute("poly aaa = number(" + @minPoly + ");"); if (aaa!=0) { minpoly = number(aaa); } ideal action, G, I, J, N, generators; map F; poly f; // built the ideal of the graph of GxV -> V, (s,v) -> s(v), i.e. // of the image of the map GxV -> GxVxV, (s,v) -> (s,v,s(v)) G = fetch(RNCB, G); action = fetch(RNCB, action); groupVars = nvars(basering) - 2*nt; offset = groupVars + nt; I = G; for(i = 1; i <= nt; i = i + 1) { I = I, var(offset + i) - action[i]; } J = std(I); // takes long, try to improve // eliminate N = nselect(J, 1.. groupVars); // substitute for(i = 1; i <= nvars(basering); i = i + 1) { F[i] = 0; } for(i = groupVars + 1; i <= offset; i = i + 1) { F[i] = var(i); } generators = mstd(F(N))[2]; setring RNCB; return(fetch(RNCR, generators)); } example {"EXAMPLE:"; echo = 2; ring R = 0, (s(1..2), x, y), dp; ideal G = -s(1)+s(2)^3, s(1)^4-1; ideal action = s(1)*x, s(2)*y; ideal inv = NullCone(G, action); inv; } /////////////////////////////////////////////////////////////////////////////// proc ReynoldsOperator(ideal Grp, ideal Gaction, list #) "USAGE: ReynoldsOperator(G, action [, opt]); ideal G, action; int opt PURPOSE: compute the Reynolds operator of the group G which acts via 'action' RETURN: polynomial ring R over a simple extension of the ground field of the basering (the extension might be trivial), containing a list 'ROelements', the ideals 'id', 'actionid' and the polynomial 'newA'. R = K(a)[s(1..r),t(1..n)]. - 'ROelements' is a list of ideals, each ideal represents a substitution map F : R -> R according to the zero-set of G - 'id' is the ideal of G in the new ring - 'newA' is the new representation of a' in terms of a. If the basering does not contain a parameter then 'newA' = 'a'. ASSUME: basering = K[s(1..r),t(1..n)], K = Q or K = Q(a') and minpoly != 0, G is the ideal of a finite group in K[s(1..r)], 'action' is a linear group action of G " { def ROBR = basering; int i, j, n, ns, primaryDec; ideal G1 = Grp; list solution, saction; string str; if(size(#) > 0) { primaryDec = #[1]; } else { primaryDec = 0; } kill #; n = nvars(basering); ns = n - size(Gaction); for(i = ns + 1; i <= n; i++) { G1 = G1, var(i);} def RORR = zeroSet(G1, primaryDec); setring ROBR; string parName, minPoly; if(npars(basering) == 0) { parName = "a"; minPoly = "0"; } else { parName = parstr(basering); minPoly = string(minpoly); } execute("ring RA1=0,(" + varstr(basering) + "," + parName + "), lp;"); if (minPoly!="0") { execute("ideal mpoly = std(" + minPoly + ");"); } ideal Grp = imap(ROBR,Grp); ideal Gaction = imap(ROBR,Gaction); setring RORR; map Phi = RA1, maxideal(1); Phi[nvars(RORR) + 1] = newA; id = Phi(Grp); // id already defined by zeroSet of level 0 ideal actionid = Phi(Gaction); kill parName,minPoly,Phi,RA1; // end of ersetzt durch list ROelements; ideal Rf; map groupElem; poly h1, h2; for(i = 1; i <= size(theZeroset); i++) { groupElem = theZeroset[i]; // element of G for(j = ns + 1; j<=n; j++) { groupElem[j] = var(j); } //do not change t's for(j = 1; j <= n - ns; j++) { h1 = actionid[j]; h2 = groupElem(h1); Rf[ns + j] = h2; } ROelements[i] = Rf; } export actionid, ROelements; setring ROBR; return(RORR); } /////////////////////////////////////////////////////////////////////////////// proc ReynoldsImage(list reynoldsOp, poly f) "USAGE: ReynoldsImage(RO, f); list RO, poly f PURPOSE: compute the Reynolds image of the polynomial f, where RO represents the Reynolds operator RETURN: poly " { def RIBR=basering; map F; poly h = 0; for(int i = 1; i <= size(reynoldsOp); i++) { F = RIBR, reynoldsOp[i]; h = h + F(f); } return(h/size(reynoldsOp)); } /////////////////////////////////////////////////////////////////////////////// static proc SimplifyCoefficientMatrix(matrix coefMatrix) "USAGE: SimplifyCoefficientMatrix(M); M matrix coming from coef(...) PURPOSE: simplify the matrix, i.e. find linear dependencies among the columns RETURN: matrix M, f = M[1,1]*M[2,1] + ... + M[1,n]*M[2,n] " { int i, j , loop; intvec columnList; matrix decompMx = coefMatrix; loop = 1; i = 1; while(loop) { columnList = 1..i; // current column for(j = i + 1; j <= ncols(decompMx); j++) { // test if decompMx[2, j] equals const * decompMx[2, i] if(LinearCombinationQ(ideal(decompMx[2, i]), decompMx[2, j])) { // column not needed decompMx[1, i] = decompMx[1, i] + decompMx[2, j] / decompMx[2, i] * decompMx[1, j]; } else { columnList[size(columnList) + 1] = j; } } if(defined(auxM)) { kill auxM;} matrix auxM[2][size(columnList)]; // built new matrix and omit for(j = 1; j <= size(columnList); j++) { // the linear dependent colums auxM[1, j] = decompMx[1, columnList[j]]; // found above auxM[2, j] = decompMx[2, columnList[j]]; } decompMx = auxM; if(i < ncols(decompMx) - 1) { i++;} else { loop = 0;} } return(decompMx); } /////////////////////////////////////////////////////////////////////////////// proc SimplifyIdeal(ideal I, list #) "USAGE: SimplifyIdeal(I [,m, name]); ideal I; int m, string name" PURPOSE: simplify ideal I to the ideal I', do not change the names of the first m variables, new ideal I' might contain less variables. I' contains variables var(1..m) RETURN: list _[1] ideal I' _[2] ideal representing a map phi to a ring with probably less vars. s.th. phi(I) = I' _[3] list of variables _[4] list from 'elimpart' " { int i, k, m; string nameCMD; ideal mId, In, mapId; // ideal for the map list sList, result; sList = elimpart(I); In = sList[1]; mapId = sList[5]; if(size(#) > 0) { m = #[1]; nameCMD = #[2]; } else { m = 0;} // nvars(basering); k = 0; for(i = 1; i <= nvars(basering); i++) { if(sList[4][i] != 0) { k++; if(k <= m) { mId[i] = sList[4][i]; } else { execute("mId["+string(i) +"] = "+nameCMD+"("+string(k-m)+");");} } else { mId[i] = 0;} } map phi = basering, mId; result[1] = phi(In); result[2] = phi(mapId); result[3] = simplify(sList[4], 2); result[4] = sList; return(result); } /////////////////////////////////////////////////////////////////////////////// proc RingVarProduct(def index) // list of indices { poly f = 1; for(int i = 1; i <= size(index); i++) { f = f * var(index[i]); } return(f); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/rootsmr.lib000066400000000000000000000474561266270727000203640ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version rootsmr.lib 4.0.0.0 Jun_2013 "; // $Id: 5e588048d574081b63e3c749e425de3c0352f458 $ category="Teaching"; info=" LIBRARY: rootsmr.lib Counting the number of real roots of polynomial systems AUTHOR: Enrique A. Tobis, etobis@dc.uba.ar OVERVIEW: Routines for counting the number of real roots of a multivariate polynomial system. Two methods are implemented: deterministic computation of the number of roots, via the signature of a certain bilinear form (nrRootsDeterm); and a rational univariate projection, using a pseudorandom polynomial (nrRootsProbab). It also includes a command to verify the correctness of the pseudorandom answer. REFERENCES: Basu, Pollack, Roy, \"Algorithms in Real Algebraic Geometry\", Springer, 2003. PROCEDURES: nrRootsProbab(I) Number of real roots of 0-dim ideal (probabilistic) nrRootsDeterm(I) Number of real roots of 0-dim ideal (deterministic) symsignature(m) Signature of the symmetric matrix m sturmquery(h,B,I) Sturm query of h on V(I) matbil(h,B,I) Matrix of the bilinear form on R/I associated to h matmult(f,B,I) Matrix of multiplication by f (m_f) on R/I in the basis B tracemult(f,B,I) Trace of m_f (B is an ordered basis of R/I) coords(f,B,I) Coordinates of f in the ordered basis B randcharpoly(B,I,n) Pseudorandom charpoly of univ. projection, n optional verify(p,B,i) Verifies the result of randcharpoly randlinpoly(n) Pseudorandom linear polynomial, n optional powersums(f,B,I) Powersums of the roots of a char polynomial symmfunc(S) Symmetric functions from the powersums S univarpoly(l) Polynomial with coefficients from l qbase(i) Like kbase, but the monomials are ordered KEYWORDS: real roots, univariate projection "; /////////////////////////////////////////////////////////////////// LIB "linalg.lib"; // We use charpoly LIB "rootsur.lib"; // We use varsigns proc nrRootsProbab(ideal I, list #) "USAGE: nrRootsProbab(I,[n]); ideal I, int n RETURN: int: the number of real roots of the ideal I by a probabilistic algorithm ASSUME: If I is not a Groebner basis, then a Groebner basis will be computed by using std. If I is already a Groebner basis (i.e. if attrib(I,"isSB"); returns 1) then this Groebner basis will be used, hence it must be one w.r.t. (any) global ordering. This may be useful if the ideal is known to be a Groebner basis or if it can be computed faster by a different method. NOTE: If n<10 is given, n is the number of digits being used for constructing a random characteristic polynomial, a bigger n is more safe but slower (default: n=5). If printlevel>0 the number of complex solutions is displayed (default: printlevel=0). SEE ALSO: nrroots, nrRootsDeterm, randcharpoly, solve EXAMPLE: example nrRootsProbab; shows an example" { //Note on complexity: Let n = no of complex roots of I (= vdim(std(I)). //Then the algorithm needs: //1 std(I) and ~n NF computations (of randcharpoly w.r.t. I) if (isparam(I)) { ERROR("This procedure cannot operate with parametric arguments"); } int pr = printlevel-voice+2; int v; int n=5; if (size(#) == 1) { n=#[1]; } if (attrib(I,"isSB")!=1) { I = std(I); } ideal b = qbase(I); v = size(b); if (v == 0) { ERROR("ideal is not 0-dimensional"); } dbprint(pr,"//ideal has " +string(v)+ " complex solutions, counted with multiplicity"); poly p = randcharpoly(b,I,n); return (nrroots(p)); } example { echo = 2; ring r = 0,(x,y,z),lp; ideal i = (x-1)*(x-2),(y-1)^3*(x-y),(z-1)*(z-2)*(z-3)^2; nrRootsProbab(i); //no of real roots (using internally std) i = groebner(i); //using the hilbert driven GB computation int pr = printlevel; printlevel = 2; nrRootsProbab(i); printlevel = pr; } /////////////////////////////////////////////////////////////////////////////// proc nrRootsDeterm(ideal I) "USAGE: nrRootsDeterm(I); ideal I RETURN: int: the number of real roots of the ideal I by a deterministic algorithm ASSUME: If I is not a Groebner basis, then a Groebner basis will be computed by using std. If I is already a Groebner basis (i.e. if attrib(I,"isSB"); returns 1) then this Groebner basis will be used, hence it must be one w.r.t. (any) global ordering. This may be useful if the ideal is known to be a Groebner basis or if it can be computed faster by a different method. NOTE: If printlevel>0 the number of complex solutions is displayed (default: printlevel=0). The procedure nrRootsProbab is usually faster. SEE ALSO: nrroots, nrRootsProbab, sturmquery, solve EXAMPLE: example nrRootsDeterm; shows an example" { //Note on complexity: Let n = no of complex roots of I (= vdim(std(I)). //Then the algotithm needs: //1 std(I) and (1/2)n*(n+1)^2 ~ 1/2n^3 NF computations (of monomials w.r.t. I) if (isparam(I)) { ERROR("This procedure cannot operate with parametric arguments"); } int pr = printlevel-voice+2; int v; if (attrib(I,"isSB")!=1) { I = std(I); } ideal b = qbase(I); v = size(b); if (v == 0) { ERROR("ideal is not 0-dimensional"); } dbprint(pr,"//ideal has " +string(v)+ " complex solutions, counted with multiplicity"); return (sturmquery(1,b,I)); } example { echo = 2; ring r = 0,(x,y,z),lp; ideal I = (x-1)*(x-2),(y-1),(z-1)*(z-2)*(z-3)^2; nrRootsDeterm(I); //no of real roots (using internally std) I = groebner(I); //using the hilbert driven GB computation int pr = printlevel; printlevel = 2; nrRootsDeterm(I); printlevel = pr; } /////////////////////////////////////////////////////////////////////////////// proc symsignature(matrix m) "USAGE: symsignature(m); m matrix. m must be symmetric. RETURN: int: the signature of m SEE ALSO: matbil,sturmquery EXAMPLE: example symsignature; shows an example" { int positive, negative, i, j; list l; poly variable; if (isparam(m)) { ERROR("This procedure cannot operate with parametric arguments"); } if (!isSquare(m)) { ERROR ("m must be a square matrix"); } // We check whether m is symmetric for (i = 1;i <= nrows(m);i++) { for (j = i;j <= nrows(m);j++) { if (m[i,j] != m[j,i]) { ERROR ("m must be a symmetric matrix"); } } } poly f = charpoly(m); // Uses the last variable of the ring for (i = size(f);i >= 1;i--) { l[i] = leadcoef(f[i]); } positive = varsigns(l); variable = var(nvars(basering)); // charpoly uses the last variable f = subst(f,variable,-variable); for (i = size(f);i >= 1;i--) { l[i] = leadcoef(f[i]); } negative = varsigns(l); return (positive - negative); } example { echo = 2; ring r = 0,(x,y),dp; ideal i = x4-y2x,y2-13; i = std(i); ideal b = qbase(i); matrix m = matbil(1,b,i); symsignature(m); } /////////////////////////////////////////////////////////////////////////////// proc sturmquery(poly h,ideal B,ideal I) "USAGE: sturmquery(h,b,i); h poly, b,i ideal RETURN: int: the Sturm query of h in V(i) ASSUME: i is a Groebner basis, b is an ordered monomial basis of r/i, r = basering. SEE ALSO: symsignature,matbil EXAMPLE: example sturmquery; shows an example" { if (isparam(h) || isparam(B) || isparam(I)) { ERROR("This procedure cannot operate with parametric arguments"); } return (mysymmsig(matbil(h,B,I))); } example { echo = 2; ring r = 0,(x,y),dp; ideal i = x4-y2x,y2-13; i = std(i); ideal b = qbase(i); sturmquery(1,b,i); } /////////////////////////////////////////////////////////////////////////////// static proc mysymmsig(matrix m) // returns the signature of a square symmetric matrix m { int positive, negative, i; list l; poly variable; poly f = charpoly(m); // Uses the last variable of the ring for (i = size(f);i >= 1;i--) { l[i] = leadcoef(f[i]); } positive = varsigns(l); variable = var(nvars(basering)); // charpoly uses the last variable f = subst(f,variable,-variable); for (i = size(f);i >= 1;i--) { l[i] = leadcoef(f[i]); } negative = varsigns(l); return (positive - negative); } /////////////////////////////////////////////////////////////////////////////// proc matbil(poly h,ideal B,ideal I) "USAGE: matbil(h,b,i); h poly, b,i ideal RETURN: matrix: the matrix of the bilinear form (f,g) |-> trace(m_fhg), m_fhg = multiplication with fhg on r/i ASSUME: i is a Groebner basis and b is an ordered monomial basis of r/i, r = basering SEE ALSO: matmult,tracemult EXAMPLE: example matbil; shows an example" { matrix m[size(B)][size(B)]; poly f; int k,l; //h = reduce(h,I); for (k = 1; k <= size(B); k++) { for (l = 1; l <= k; l++) { m[k,l] = tracemult(h*B[k]*B[l],B,I)[1]; m[l,k] = m[k,l]; // The matrix we are trying to compute is symmetric } } return(m); } example { echo = 2; ring r = 0,(x,y),dp; ideal i = x4-y2x,y2-13; i = std(i); ideal b = qbase(i); poly f = x3-xy+y-13+x4-y2x; matrix m = matbil(f,b,i); print(m); } /////////////////////////////////////////////////////////////////////////////// proc tracemult(poly f,ideal B,ideal I) "USAGE: tracemult(f,B,I);f poly, B,I ideal RETURN: number: the trace of the multiplication by f (m_f) on r/I, written in the monomial basis B of r/I, r = basering (faster than matmult + trace) ASSUME: I is given by a Groebner basis and B is an ordered monomial basis of r/I SEE ALSO: matmult,trace EXAMPLE: example tracemult; shows an example" { int k; // Iterates over the basis monomials int l; // Iterates over the rows of the matrix list coordinates; number m; poly g; //f = reduce(f,I); for (k = 1; k <= size(B); k++) { l=1; g = reduce(f*B[k],I); while (l <= k) { if (leadmonom(g[l]) == B[k]) { m = m + leadcoef(g[l]); break; } l++; } } return (m); } example { echo = 2; ring r = 0,(x,y),dp; ideal i = x4-y2x,y2-13; i = std(i); ideal b = qbase(i); poly f = x3-xy+y-13+x4-y2x; matrix m = matmult(f,b,i); print(m); tracemult(f,b,i); //the trace of m } /////////////////////////////////////////////////////////////////////////////// proc matmult(poly f, ideal B, ideal I) "USAGE: matmult(f,b,i); f poly, b,i ideal RETURN: matrix: the matrix of the multiplication map by f (m_f) on r/i w.r.t. to the monomial basis b of r/i (r = basering) ASSUME: i is a Groebner basis and b is an ordered monomial basis of r/i, as given by qbase(i) SEE ALSO: coords,matbil EXAMPLE: example matmult; shows an example" { int k; // Iterates over the basis monomials int l; // Iterates over the rows of the matrix list coordinates; matrix m[size(B)][size(B)]; //f = reduce(f,I); for (k = 1;k <= size(B);k++) { coordinates = coords(f*(B[k]),B,I); // f*x_k written on the basis B for (l = 1;l <= size(B);l++) { m[l,k] = coordinates[l]; } } return (m); } example { echo = 2; ring r = 0,(x,y),dp; ideal i = x4-y2x,y2-13; i = std(i); ideal b = qbase(i); poly f = x3-xy+y-13+x4-y2x; matrix m = matmult(f,b,i); print(m); } /////////////////////////////////////////////////////////////////////////////// proc coords(poly f,ideal B,ideal I) "USAGE: coords(f,b,i), f poly, b,i ideal RETURN: list of numbers: the coordinates of the class of f (mod i) in the monomial basis b ASSUME: i is a Groebner basis and b is an ordered monomial basis of r/i, r = basering SEE ALSO: matmult,matbil KEYWORDS: coordinates EXAMPLE: example coords; shows an example" { // We assume the basis is sorted according to the ring order poly g; int k,l=1,1; list coordinates; int N = size(B); // We first compute the normal form of f w.r.t. I g = reduce(f,I); int n = size(g); //allways n <= N while (k <= N) { if (leadmonom(g[l]) == B[k]) { coordinates[k] = leadcoef(g[l]); l++; } else { coordinates[k] = number(0); } k++; } return (coordinates); } example { echo = 2; ring r = 0,(x,y),dp; ideal i = x4-y2x,y2-13; poly f = x3-xy+y-13+x4-y2x; i = std(i); ideal b = qbase(i); b; coords(f,b,i); } /////////////////////////////////////////////////////////////////////////////// static proc isSquare(matrix m) // returns 1 if and only if m is a square matrix { return (nrows(m)==ncols(m)); } /////////////////////////////////////////////////////////////////////////////// proc randcharpoly(ideal B,ideal I,list #) "USAGE: randcharpoly(b,i); randcharpoly(b,i,n); b,i ideal; n int RETURN: poly: the characteristic polynomial of a pseudorandom rational univariate projection having one zero per zero of i. If n<10 is given, it is the number of digits being used for the pseudorandom coefficients (default: n=5) ASSUME: i is a Groebner basis and b is an ordered monomial basis of r/i, r = basering NOTE: shows a warning if printlevel>0 (default: printlevel=0) KEYWORDS: rational univariate projection EXAMPLE: example randcharpoly; shows an example" { int pr = printlevel - voice + 2; poly p; poly generic; list l; matrix m; poly q; if (size(#) == 1) { generic = randlinpoly(#[1]); } else { generic = randlinpoly(); } p = reduce(generic,I); m = matmult(p,B,I); q = charpoly(m); dbprint(pr,"*********************************************************************"); dbprint(pr,"* WARNING: This polynomial was obtained using pseudorandom numbers.*"); dbprint(pr,"* If you want to verify the result, please use the command *"); dbprint(pr,"* *"); dbprint(pr,"* verify(p,b,i) *"); dbprint(pr,"* *"); dbprint(pr,"* where p is the polynomial I returned, b is the monomial basis *"); dbprint(pr,"* used, and i the Groebner basis of the ideal *"); dbprint(pr,"*********************************************************************"); return(q); } example { echo = 2; ring r = 0,(x,y,z),dp; ideal i = (x-1)*(x-2),(y-1),(z-1)*(z-2)*(z-3)^2; i = std(i); ideal b = qbase(i); poly p = randcharpoly(b,i); p; nrroots(p); // See nrroots in urrcount.lib int pr = printlevel; printlevel = pr+2; p = randcharpoly(b,i,5); nrroots(p); printlevel = pr; } /////////////////////////////////////////////////////////////////////////////// proc verify(poly p,ideal B,ideal I) "USAGE: verify(p,B,I); p poly, B,I,ideal RETURN: integer: 1 if and only if the polynomial p splits the points of V(I). It's used to check the result of randcharpoly ASSUME: I is given by a Groebner basis and B is an ordered monomial basis of r/I, r = basering NOTE: comments the result if printlevel>0 (default: printlevel=0) SEE ALSO: randcharpoly EXAMPLE: example verify; shows an example" { int pr = printlevel - voice + 2; poly sqr_free; int correct; poly variable; if (isparam(p) || isparam(B) || isparam(I)) { ERROR("This procedure cannot operate with parametric arguments"); } variable = isuni(p); sqr_free = p/gcd(p,diff(p,variable)); correct = (mat_rk(matbil(1,B,I)) == deg(sqr_free)); if (correct) { dbprint(pr,"//Verification successful"); } else { dbprint(pr,"//The choice of random numbers was not useful"); dbprint(pr,"//You might want to try randcharpoly with a larger number of digits"); } return (correct); } example { echo = 2; ring r = 0,(x,y),dp; poly f = x3-xy+y-13+x4-y2x; ideal i = x4-y2x,y2-13; i = std(i); ideal b = qbase(i); poly p = randcharpoly(b,i); verify(p,b,i); } /////////////////////////////////////////////////////////////////////////////// proc randlinpoly(list #) "USAGE: randlinpoly(); randlinpoly(n); n int RETURN: poly: linear combination of the variables of the ring, with pseudorandom coefficients. If n<10 is given, it is the number of digits being used for the range of the coefficients (default: n=5) SEE ALSO: randcharpoly; EXAMPLE: example randlinpoly; shows an example" { int n,i; poly p = 0; int ndigits = 5; if (size(#) == 1) { ndigits = #[1]; } n = nvars(basering); for (i = 1;i <= n;i++) { p = p + var(i)*random(1,10^ndigits); } return (p); } example { echo = 2; ring r = 0,(x,y,z,w),dp; poly p = randlinpoly(); p; randlinpoly(5); } /////////////////////////////////////////////////////////////////////////////// proc powersums(poly f,ideal B,ideal I) "USAGE: powersums(f,b,i); f poly; b,i ideal RETURN: list: the powersums of the results of evaluating f at the zeros of I ASSUME: i is a Groebner basis and b is an ordered monomial basis of r/i, r = basering SEE ALSO: symmfunc EXAMPLE: example symmfunc; shows an example" { int N,k; list sums; N = size(B); for (k = 1;k <= N;k++) { sums = sums + list(leadcoef(trace(matmult(f^k,B,I)))); } return (sums); } example { echo = 2; ring r = 0,(x,y,z),dp; ideal i = (x-1)*(x-2),(y-1),(z+5); // V(I) = {(1,1,-5),(2,1,-5)} i = std(i); ideal b = qbase(i); poly f = x+y+z; list psums = list(-2-3,4+9); // f evaluated at V(I) gives {-3,-2} list l = powersums(f,b,i); psums; l; } /////////////////////////////////////////////////////////////////////////////// proc symmfunc(list S) "USAGE: symmfunc(s); s list RETURN: list: the symmetric functions of the roots of a polynomial, given the power sums of those roots. SEE ALSO: powersums EXAMPLE: example symmfunc; shows an example" { // Takes the list of power sums and returns the symmetric functions list a; int j,l,N; number sum; N = size(S); a[N+1] = 1; // We set the length of the list and initialize its last element. for (l = N - 1;l >= 0;l--) { sum = 0; for (j = l + 1;j <= N;j++) { sum = sum + ((a[j+1])*(S[j-l])); } sum = -sum; a[l+1] = sum/(N-l); } a = reverse(a); return (a); } example { echo = 2; ring r = 0,x,dp; poly p = (x-1)*(x-2)*(x-3); list psums = list(1+2+3,1+4+9,1+8+27); list l = symmfunc(psums); l; p; // Compare p with the elements of l } /////////////////////////////////////////////////////////////////////////////// proc univarpoly(list l) "USAGE: univarpoly(l); l list RETURN: poly: a polynomial p on the first variable of basering, say x, with p = l[1] + l[2]*x + l[3]*x^2 + ... EXAMPLE: example univarpoly; shows an example" { poly p; int i,n; n = size(l); for (i = 1;i <= n;i++) { p = p + l[i]*var(1)^(n-i); } return (p); } example { echo = 2; ring r = 0,x,dp; list l = list(1,2,3,4,5); poly p = univarpoly(l); p; } /////////////////////////////////////////////////////////////////////////////// proc qbase(ideal i) "USAGE: qbase(I); I zero-dimensional ideal RETURN: ideal: A monomial basis of the quotient between the basering and the ideal I, sorted according to the basering order. SEE ALSO: kbase KEYWORDS: zero-dimensional EXAMPLE: example qbase; shows an example" { ideal b; b = kbase(i); b = reverseideal(sort(b)[1]); // sort sorts in ascending order return (b); } example { echo = 2; ring r = 0,(x,y,z),dp; ideal i = 2x2,-y2,z3; i = std(i); ideal b = qbase(i); b; b = kbase(i); b; // Compare this with the result of qbase } /////////////////////////////////////////////////////////////////////////////// static proc reverseideal(ideal b) // Returns b reversed { int i; ideal result; result = b[1]; for (i = 2;i <= size(b);i++) { result = b[i], result; } return (result); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/rootsur.lib000066400000000000000000000551331266270727000203630ustar00rootroot00000000000000///////////////////////////////////////////////////////////////////////////// version="version rootsur.lib 4.0.0.0 Jun_2013 "; // $Id: 7a8d2af54e1e0979f68d97e96677fb413b84725c $ category="Teaching"; info=" LIBRARY: rootsur.lib Counting number of real roots of univariate polynomial AUTHOR: Enrique A. Tobis, etobis@dc.uba.ar OVERVIEW: Routines for bounding and counting the number of real roots of a univariate polynomial, by means of several different methods, namely Descartes' rule of signs, the Budan-Fourier theorem, Sturm sequences and Sturm-Habicht sequences. The first two give bounds on the number of roots. The other two compute the actual number of roots of the polynomial. There are several wrapper functions, to simplify the application of the aforesaid theorems and some functions to determine whether a given polynomial is univariate. REFERENCES: Basu, Pollack, Roy, \"Algorithms in Real Algebraic Geometry\", Springer, 2003. PROCEDURES: isuni(p) Checks whether a polynomial is univariate whichvariable(p) The only variable of a univariate monomial (or 0) varsigns(p) Number of sign changes in a list boundBuFou(p,a,b) Bound for number of real roots of polynomial p in interval (a,b) boundposDes(p) Bound for the number of positive real roots of polynomial p boundDes(p) Bound for the number of real roots of polynomial p allrealst(p) Checks whether all the roots of a polynomial are real (via Sturm) maxabs(p) A bound for the maximum absolute value of a root of a poly allreal(p) Checks whether all the roots of a polynomial are real (via St-Ha) sturm(p,a,b) Number of real roots of a polynomial on an interval (via Sturm) sturmseq(p) Sturm sequence of a polynomial sturmha(p,a,b) Number of real roots of a polynomial in (a,b) (via Sturm-Habicht) sturmhaseq(p) A Sturm-Habicht Sequence of a polynomial reverse(l) Reverses a list nrroots(p) The number of real roots of p isparam(p) Returns 0 if and only if the polynomial has non-parametric coefficients KEYWORDS: real roots, univariate polynomial "; /////////////////////////////////////////////////////////////////////////////// static proc isparametric(poly p) { int ispar; def ba = basering; // If the basering has parameters declared if (npars(basering) != 0) { // If we were given just a polynomial list lba = ringlist(ba); lba[1]=0; def rba = ring(lba); setring rba; poly p1 = imap(ba,p); setring ba; poly p1 = imap(rba,p1); ispar = (size(p-p1)!=0); } return (ispar); } /////////////////////////////////////////////////////////////////////////////// proc isparam(list #) "USAGE: isparam(ideal/module/poly/list); RETURN: int: 0 if the argument has non-parametric coefficients and 1 if it has parametric coefficients EXAMPLE: example isparam; shows an example" { int i; int ispar; def ar = #[1]; // It we were given only one argument (not a list) if (size(#) == 1) { if (typeof(ar) == "number") { ispar = (pardeg(ar) > 0); } else { if (typeof(ar) == "poly") { ispar = isparametric(ar); } else { if (typeof(ar) == "ideal" || typeof(ar) == "module") { // Ciclo que revisa cada polinomio i = size(ar); while (!ispar && (i >= 1)) { ispar = ispar || (isparametric(ar[i])); i--; } } else { if (typeof(ar) == "matrix" || typeof(ar) == "intmat") { int j; i = nrows(ar); while (!ispar && (i >= 1)) { j = nrows(ar); while (!ispar && (j >= 1)) { ispar = ispar || (isparametric(ar[i,j])); j--; } i--; } } }}}} else { if (size(#) > 1) { i = size(#); while (!ispar && (i >= 1)) { if ((typeof(#[i]) != "poly") && (typeof(#[i]) != "number") && typeof(#[i]) != "int") { ERROR("This procedure only works with lists of polynomials"); } ispar = ispar || (isparametric(#[i])); i--; } }} return (ispar); } example { echo = 2; ring r = 0,x,dp; isparam(2x3-56x+2); ring s = (0,a,b,c),x,dp; isparam(2x3-56x+2); isparam(2x3-56x+abc); } /////////////////////////////////////////////////////////////////////////////// proc isuni(poly p) "USAGE: isuni(p); poly p; RETURN: poly: if p is a univariate polynomial, it returns the variable. If not, zero. SEE ALSO: whichvariable EXAMPLE: example isuni; shows an example" { int v=univariate(p); if (v== -1) { v=1; } if (v>0) { return(var(v)); } else { return(0); } } example { echo = 2; ring r = 0,(x,y),dp; poly p = 6x7-3x2+2x-15/7; isuni(p); isuni(p*y); } /////////////////////////////////////////////////////////////////////////////// proc whichvariable(poly p) "USAGE: whichvariable(p); poly p RETURN: poly: if p is a univariate monomial, the variable. Otherwise 0. ASSUME: p is a monomial SEE ALSO: isuni EXAMPLE: example whichvariable; shows an example" { if (size(p) != 1) { ERROR("p must be a monomial"); } int v=univariate(p); if (v== -1) { v=1; } if (v>0) { return(var(v)); } else { return(0); } } example { echo = 2; ring r = 0,(x,y),dp; whichvariable(x5); whichvariable(x3y); } /////////////////////////////////////////////////////////////////////////////// proc varsigns(list l) "USAGE: varsigns(l); list l. RETURN: int: the number of sign changes in the list l SEE ALSO: boundposDes EXAMPLE: example varsigns; shows an example" { int lastsign; int numberofchanges = 0; if (isparam(l)) { ERROR("This procedure cannot operate with parametric arguments"); } lastsign = sign(l[1]); for (int i = 1; i <= size(l); i++) { if (sign(l[i]) != lastsign && sign(l[i]) != 0) { numberofchanges++; lastsign = sign(l[i]); } } return (numberofchanges); } example { echo = 2; ring r = 0,x,dp; list l = 1,2,3; varsigns(l); l = 1,-1,2,-2,3,-3; varsigns(l); } /////////////////////////////////////////////////////////////////////////////// proc boundBuFou(poly p,number a,number b) "USAGE: boundBuFou(p,a,b); p poly, a,b number RETURN: int: an upper bound for the number of real roots of p in (a,b], with the same parity as the actual number of roots (using the Budan-Fourier Theorem) ASSUME: - p is a univariate polynomial with rational coefficients@* - a, b are rational numbers with a < b SEE ALSO: boundposDes,varsigns EXAMPLE: example boundBuFou; shows an example" { int i; poly variable; list Der; list Dera,Derb; int d; number bound; variable = isuni(p); if (isparam(p) || isparam(a) || isparam(b)) { ERROR("This procedure cannot operate with parametric arguments"); } // p must be a univariate polynomial if (variable == 0) { ERROR("p must be a univariate polynomial"); } if (a >= b) { ERROR("a must be smaller than b"); } d = deg(p); // We calculate the list of derivatives Der[d+1] = p; for (i = 0;i < d;i++) { Der[d-i] = diff(Der[d-i+1],variable); } // Then evaluate that list for (i = d+1;i >= 1;i--) { Dera [i] = leadcoef(subst(Der[i],variable,a)); Derb [i] = leadcoef(subst(Der[i],variable,b)); } // Finally we calculate the sign variations bound = varsigns(Dera) - varsigns(Derb); return(bound); } example { echo = 2; ring r = 0,x,dp; poly p = (x+2)*(x-1)*(x-5); boundBuFou(p,-3,5); boundBuFou(p,-2,5); } /////////////////////////////////////////////////////////////////////////////// proc boundposDes(poly p) "USAGE: boundposDes(p); poly p RETURN: int: an upper bound for the number of positive roots of p, with the same parity as the actual number of positive roots of p. ASSUME: p is a univariate polynomial with rational coefficients SEE ALSO: boundBuFou EXAMPLE: example boundposDes; shows an example" { poly g; number nroots; poly variable; list coefficients; int i; variable = isuni(p); if (isparam(p)) { ERROR("This procedure cannot operate with parametric arguments"); } // p must be a univariate polynomial if (variable == 0) { ERROR("p must be a univariate polynomial"); } g = p; // We will work with g // We check whether 0 is a root of g, and if so, remove it if (subst(g,variable,0) == 0) { g = g/variable^(deg(g[size[g]])); } // We count the number of positive roots i = size(g); while (i >= 1) { coefficients[i] = leadcoef(g[i]); i--; } nroots = varsigns(coefficients); return(nroots); } example { echo = 2; ring r = 0,x,dp; poly p = (x+2)*(x-1)*(x-5); boundposDes(p); p = p*(x2+1); boundposDes(p); } /////////////////////////////////////////////////////////////////////////////// proc boundDes(poly p) "USAGE: boundDes(p); poly p RETURN: int: an upper bound for the number of real roots of p, with the same parity as the actual number of real roots of p. ASSUME: p is a univariate polynomial with rational coefficients SEE ALSO: boundBuFou EXAMPLE: example boundDes; shows an example" { poly g; number nroots; poly variable; list coefficients; int i; variable = isuni(p); if (isparam(p)) { ERROR("This procedure cannot operate with parametric arguments"); } // p must be a univariate polynomial if (variable == 0) { ERROR("p must be a univariate polynomial"); } g = p; // We will work with g nroots = 0; // We check whether 0 is a root of g, and if so, remove it if (subst(g,variable,0) == 0) { g = g/variable^(deg(g[size[g]])); nroots++; } // We count the number of positive roots i = size(g); while (i >= 1) { coefficients[i] = leadcoef(g[i]); i--; } nroots = nroots + varsigns(coefficients); // We count the number of negative roots g = subst(g,variable,-variable); i = size(g); while (i >= 1) { coefficients[i] = leadcoef(g[i]); i--; } nroots = nroots + varsigns(coefficients); return(nroots); } example { echo = 2; ring r = 0,x,dp; poly p = (x+2)*(x-1)*(x-5); boundDes(p); p = p*(x2+1); boundDes(p); } /////////////////////////////////////////////////////////////////////////////// proc allrealst(poly p) "USAGE: allrealst(p); poly p RETURN: int: 1 if and only if all the roots of p are real, 0 otherwise. Checks by using Sturm's Theorem whether all the roots of p are real ASSUME: p is a univariate polynomial with rational coefficients SEE ALSO: allreal,sturm,sturmha EXAMPLE: example allrealst; shows an example" { number upper,lower; poly sqfp; // The square-free part of p poly variable; variable = isuni(p); if (isparam(p)) { ERROR("This procedure cannot operate with parametric arguments"); } if (variable == 0) { ERROR ("p must be a univariate polynomial"); } sqfp = p/gcd(p,diff(p,variable)); upper = maxabs(sqfp); // By adding one we ensure that sqfp(upper) != 0 lower = -upper; return (sturm(sqfp,lower,upper) == deg(sqfp)); } example { echo = 2; ring r = 0,x,dp; poly p = (x+2)*(x-1)*(x-5); allrealst(p); p = p*(x2+1); allrealst(p); } /////////////////////////////////////////////////////////////////////////////// proc maxabs(poly p) "USAGE: maxabs(p); poly p RETURN: number: an upper bound for the largest absolute value of a root of p ASSUME: p is a univariate polynomial with rational coefficients SEE ALSO: sturm EXAMPLE: example maxabs; shows an example" { number maximum; poly monic; int i; if (isparam(p)) { ERROR("This procedure cannot operate with parametric arguments"); } monic = simplify(p,1); maximum = 0; for (i = 1; i <= size(monic); i++) { maximum = max(abs(leadcoef(p[i])),maximum); } return (maximum + 1); } example { echo = 2; echo = 2; ring r = 0,x,dp; poly p = (x+2)*(x-1)*(x-5); maxabs(p); } /////////////////////////////////////////////////////////////////////////////// proc sturm(poly p,number a,number b) "USAGE: sturm(p,a,b); poly p, number a,b RETURN: int: the number of real roots of p in (a,b] ASSUME: p is a univariate polynomial with rational coefficients,@* a, b are rational numbers with a < b SEE ALSO: sturmha,allrealst,allreal EXAMPLE: example sturm; shows an example" { list l; list pa; list pb; int signsA,signsB; int i; int nroots; poly variable; if (isparam(p)) { ERROR("This procedure cannot operate with parametric arguments"); } variable = isuni(p); if (variable == 0) { ERROR ("p must be a univariate polynomial"); } if (a >= b) { ERROR("a must be lower than b"); } if (subst(p,variable,a) == 0 || subst(p,variable,b) == 0) { ERROR ("Neither a nor b can be roots of P"); } l = sturmseq(p); i = size(l); while (i >= 1) { // We build the sequences pa[i] = leadcoef(subst(l[i],variable,a)); pb[i] = leadcoef(subst(l[i],variable,b)); i--; } signsA = varsigns(pa); signsB = varsigns(pb); nroots = signsA - signsB + nroots; return (nroots); } example { echo = 2; ring r = 0,x,dp; poly p = (x+2)*(x-1)*(x-5); sturm(p,-3,6); p = p*(x2+1); sturm(p,-3,6); p = p*(x+2); sturm(p,-3,6); } /////////////////////////////////////////////////////////////////////////////// proc sturmseq(poly p) "USAGE: sturmseq(p); p poly RETURN: list: a Sturm sequence of p ASSUME: p is a univariate polynomial with rational coefficients THEORY: The Sturm sequence of p (also called remainder sequence) is the sequence beginning with p, p' and goes on with the negative part of the remainder of the two previous polynomials, until the remainder is zero. See: Basu, Pollack, Roy, Algorithms in Real Algebraic Geometry, Springer, 2003. SEE ALSO: sturm,sturmhaseq EXAMPLE: example sturmseq; shows an example" { list stseq; poly variable; int i; variable = isuni(p); if (isparam(p)) { ERROR("This procedure cannot operate with parametric arguments"); } if (variable == 0) { ERROR ("p must be a univariate polynomial"); } // The two first polynomials in Sturm's sequence stseq = list(); stseq[1] = p; stseq[2] = diff(p,variable); poly q = -reduce(stseq[1],std(stseq[2])); i = 3; while (q <> 0) { stseq[i] = q; q = -reduce(stseq[i-1],std(stseq[i])); i++; } // Right now, we have gcd(P,P') in stseq[size(stseq)]; for (i = size(stseq)-1;i >= 1;i--) { stseq[i] = stseq[i]/(sign(leadcoef(stseq[size(stseq)]))*stseq[size(stseq)]); stseq[i] = stseq[i]/abs(leadcoef(stseq[i])); } // We divide the gcd by itself stseq[size(stseq)] = sign(leadcoef(stseq[size(stseq)])); return (stseq); } example { echo = 2; ring r = 0,(z,x),dp; poly p = x5-3x4+12x3+7x-153; sturmseq(p); } /////////////////////////////////////////////////////////////////////////////// proc allreal(poly p) "USAGE: allreal(p); RETURN: int: 1 if and only if all the roots of p are real, 0 otherwise SEE ALSO: allrealst EXAMPLE: example allreal; shows an example" { number upper,lower; poly sqfp; // The square-free part of p poly variable; if (isparam(p)) { ERROR("This procedure cannot operate with parametric arguments"); } variable = isuni(p); if (variable == 0) { ERROR ("p must be a univariate polynomial"); } sqfp = p/gcd(p,diff(p,variable)); return (sturmha(sqfp,-maxabs(p),maxabs(p)) == deg(sqfp)); } example { echo = 2; ring r = 0,x,dp; poly p = (x+2)*(x-1)*(x-5); allreal(p); p = p*(x2+1); allreal(p); } /////////////////////////////////////////////////////////////////////////////// proc sturmha(poly P,number a,number b) "USAGE: sturmha(p,a,b); poly p, number a,b RETURN: int: the number of real roots of p in (a,b) (using a Sturm-Habicht sequence) SEE ALSO: sturm,allreal EXAMPLE: example sturmha; shows an example" { list seq; int i; list seqa,seqb; poly variable; number bound; //number result; int result; if (isparam(P) || isparam(a) || isparam(b)) { ERROR("This procedure cannot operate with parametric arguments"); } if (!attrib(basering,"global")) { ERROR("This procedure requires a global ordering"); } variable = isuni(P); if (variable == 0) { ERROR ("P must be a univariate polynomial"); } if (a >= b) { ERROR("a must be lower than b"); } if (subst(P,variable,a) == 0 || subst(P,variable,b) == 0) { ERROR ("Neither a nor b can be roots of P"); } seq = sturmhaseq(P); bound = maxabs(P); if (a < -bound) { a = -bound; } if (b > bound) { b = bound; } // if (a == -bound && b == bound) { // for (i = size(seq);i >= 1;i--) { // seq[i] = leadcoef(seq[i]); // } // result = D(seq); // } else { for (i = size(seq);i >= 1;i--) { seqa[i] = leadcoef(subst(seq[i],variable,a)); seqb[i] = leadcoef(subst(seq[i],variable,b)); } result = (W(seqa) - W(seqb)); // } return (result); } example { echo = 2; ring r = 0,x,dp; poly p = (x+2)*(x-1)*(x-5); sturmha(p,-3,6); p = p*(x2+1); sturmha(p,-3,6); } /////////////////////////////////////////////////////////////////////////////// proc sturmhaseq(poly P) "USAGE: sturmhaseq(P); P poly. RETURN: list: the non-zero polynomials of the Sturm-Habicht sequence of P ASSUME: P is a univariate polynomial. THEORY: The Sturm-Habicht sequence (also subresultant sequence) is closely related to the Sturm sequence, but behaves better with respect to the size of the coefficients. It is defined via subresultants. See: Basu, Pollack, Roy, Algorithms in Real Algebraic Geometry, Springer, 2003. SEE ALSO: sturm,sturmseq,sturmha EXAMPLE: example sturmhaseq; shows an example" { poly Q; poly variable; int p,q,i,j,k,l; list SR; list sr; list srbar; list T; if (isparam(P)) { ERROR("This procedure cannot operate with parametric arguments"); } variable = isuni(P); if (variable == 0) { ERROR ("P must be a univariate polynomial"); } p = deg(P); Q = diff(P,variable); q = deg(Q); // Initialization SR[p+2] = sign(leadcoef(P)^(p-q-1))*P; // T[p+2] = SR[p+2]; srbar[p+2] = sign(leadcoef(P)^(p-q)); sr[p+2] = srbar[p+2]; SR[p-1+2] = sign(leadcoef(P)^(p-q+1))*Q; // T[p-1+2] = SR[p-1+2]; srbar[p-1+2] = sign(leadcoef(P)^(p-q+1))*leadcoef(Q); i = p+1; j = p; while (SR[j-1+2] != 0) { k = deg(SR[j-1+2]); if (k == j-1) { sr[j-1+2] = srbar[j-1+2]; SR[k-1+2] = -(reduce(sr[j-1+2]^2*SR[i-1+2], std(SR[j-1+2])))/(sr[j+2]*srbar[i-1+2]); // T[k-1+2] = SR[k-1+2]; srbar[k-1+2] = leadcoef(SR[k-1+2]); } if (k < j-1) { // Computation of sr[k+2] for (l = 1;l <= j-k-1;l++) { srbar[j-l-1+2] = ((-1)^l)*(srbar[j-1+2]*srbar[j-l+2])/sr[j+2]; } sr[k+2] = srbar[k+2]; // Computation of SR[k-1+2] SR[k-1+2] = -reduce(srbar[j-1+2]*sr[k+2]*SR[i-1+2], std(SR[j-1+2]))/(sr[j+2]*srbar[i-1+2]); srbar[k-1+2] = leadcoef(SR[k-1+2]); SR[k+2] = SR[j-1+2] * ( sr[k+2] / leadcoef(SR[j-1+2])); } i = j; j = k; } // We build a new list, discarding the undefined and zero elements // Plus, we reverse the elements list filtered; i = size(SR); while (i >= 1) { if (typeof(SR[i]) != "none") { if (SR[i] != 0) { filtered = insert(filtered,SR[i]); } } i--; } return (filtered); } example { echo = 2; ring r = 0,x,dp; poly p = x5-x4+x-3/2; list l = sturmhaseq(p); l; } /////////////////////////////////////////////////////////////////////////////// proc nrroots(poly p) "USAGE: nrroots(p); poly p RETURN: int: the number of real roots of p SEE ALSO: boundposDes, sturm, sturmha EXAMPLE: example nrroots; shows an example" { if (isparam(p)) { ERROR("This procedure cannot operate with parametric arguments"); } number a = maxabs(p); return (sturmha(p,-a,a)); } example { echo = 2; ring r = 0,x,dp; poly p = (x+2)*(x-1)*(x-5); nrroots(p); p = p*(x2+1); nrroots(p); } /////////////////////////////////////////////////////////////////////////////// static proc abs(number x) // Returns the absolute value of x { number av; if (x >= 0) { av = x; } else { av = -x; } return (av); } /////////////////////////////////////////////////////////////////////////////// proc sign(number x) { int sgn; if (isparam(x)) { print(x); ERROR("This procedure cannot operate with parameters"); } if (x > 0) { sgn = 1; } else { if (x < 0) { sgn = -1; } else { sgn = 0; }} return (sgn); } /////////////////////////////////////////////////////////////////////////////// proc reverse(list l) "USAGE: reverse(l); l list RETURN: list: l reversed. EXAMPLE: example reverse; shows an example" { int i; list result; for (i = 1;i <= size(l);i++) { result = list(l[i]) + result; } return (result); } example { echo = 2; ring r = 0,x,dp; list l = 1,2,3,4,5; list rev = reverse(l); l; rev; } /////////////////////////////////////////////////////////////////////////////// static proc D(list l) { int p; int q; int i; int sc; // The modified number of sign changes if (l[size(l)] == 0) { ERROR("l[size(l)] cannot be 0"); } sc = 0; // We know that l[size(l)]] != 0 p = size(l); q = p - 1; while (searchnot(l,q,-1,0)) { q = searchnot(l,q,-1,0); if ((p - q) % 2 == 1) { // if p-q is odd sc = sc + ((-1)^(((p-q)*(p-q-1)) / 2))*sign(l[p]*l[q]); } p = q; q = p - 1; } return (sc); } /////////////////////////////////////////////////////////////////////////////// static proc search(list l,int from,int dir,number element) { int i; int result; i = from; result = 0; while (i + dir >= 0 && i + dir <= size(l) + 1 && !result) { if (l[i] == element) { result = i; } i = i + dir; } return (result); } /////////////////////////////////////////////////////////////////////////////// static proc searchnot(list l,int from,int dir,number element) { int i; int result; i = from; result = 0; while (i + dir >= 0 && i + dir <= size(l) + 1 && !result) { if (l[i] != element) { result = i; } i = i + dir; } return (result); } /////////////////////////////////////////////////////////////////////////////// static proc W(list l) { int i,temp,sc,lastsign,nofzeros,n; n = size(l); sc = 0; nofzeros = 0; i = 1; lastsign = sign(l[i]); i++; while (i <= n) { if (l[i] == 0) { nofzeros++; } else { temp = lastsign * sign(l[i]); if (temp < 0) { sc++; } else { if (nofzeros == 2) { sc = sc + 2; } } nofzeros = 0; lastsign = temp div lastsign; } i++; } return (sc); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/rwalk.lib000066400000000000000000000235731266270727000177710ustar00rootroot00000000000000///////////////////////////////////////////////// version="version rwalk.lib 4.0.0.0 Jun_2014 "; // $Id: $ category="Commutative Algebra"; info=" LIBRARY: rwalk.lib Groebner Walk Conversion Algorithms AUTHOR: Stephan Oberfranz PROCEDURES: prwalk(ideal,int,int[,intvec,intvec]); standard basis of ideal via Random Perturbation Walk algorithm rwalk(ideal,int[,intvec,intvec]); standard basis of ideal via Random Walk algorithm frandwalk(ideal,int[,intvec,intvec]); standard basis of ideal via Random Fractal Walk algorithm "; /*********************************** * Argument string for Random Walk * ***********************************/ static proc OrderStringalp_NP(string Wpal,list #) { int n= nvars(basering); string order_str = "dp"; int nP = 1; //Default: if size(#)=0, the Groebnerwalk algorithm and its developments compute //a Groebner basis from "dp" to "lp" intvec curr_weight = system("Mivdp",n); //define (1,1,...,1) intvec target_weight = system("Mivlp",n); //define (1,0,...,0) if(size(#) != 0) { if(size(#) == 1) { if(typeof(#[1]) == "intvec") { curr_weight = #[1]; if(Wpal == "al"){ order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } else { order_str = "(Wp("+string(#[1])+"),C)"; } } else { if(typeof(#[1]) == "int"){ nP = #[1]; } else { if(typeof(#[1]) == "string") { if(#[1] == "Dp") { order_str = "Dp"; } else { order_str = "dp"; } } else { print("// ** the input must be \"(ideal, intvec)\" or "); print("// ** \"(ideal, string)\" or "); print("// ** \"(ideal, string,intvec)\" or "); print("// ** \"(ideal, intvec,intvec)\"."); print("// ** a lex. GB will be computed from \"dp\" to \"lp\"."); } } } } else { if(size(#) == 2) { if(typeof(#[1]) == "intvec" and typeof(#[2]) == "int") { curr_weight = #[1]; order_str = "(Wp("+string(#[1])+"),C)"; if(Wpal == "al") { order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } if(Wpal == "M") { order_str = "(M("+string(#[1])+"),C)"; } } else { if(typeof(#[1]) == "intvec" and typeof(#[2]) == "intvec") { curr_weight = #[1]; target_weight = #[2]; order_str = "(Wp("+string(#[1])+"),C)"; if(Wpal == "al") { order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } if(Wpal == "M"){ order_str = "(M("+string(#[1])+"),C)"; } } else { if(typeof(#[1]) == "string" and typeof(#[2]) == "intvec") { target_weight = #[2]; if(#[1] == "Dp") { order_str = "Dp"; } else { order_str = "dp"; } } else { print("// ** the input must be \"(ideal, intvec)\" or "); print("// ** \"(ideal, string)\" or "); print("// ** \"(ideal, string,intvec)\" or "); print("// ** \"(ideal, intvec,intvec)\"."); print("// ** a lex. GB will be computed from \"dp\" to \"lp\"."); } } } } else { if(size(#) == 3) { if(typeof(#[1]) == "intvec" and typeof(#[2]) == "intvec" and typeof(#[3]) == "int") { curr_weight = #[1]; target_weight = #[2]; nP = #[3]; order_str = "(Wp("+string(#[1])+"),C)"; if(Wpal == "al") { order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } if(Wpal == "M") { order_str = "(M("+string(#[1])+"),C)"; } } else { if(typeof(#[1]) == "string" and typeof(#[2]) == "intvec" and typeof(#[3]) == "int") { target_weight = #[2]; nP = #[3]; if(#[1] == "Dp") { order_str = "Dp"; } else { order_str = "dp"; } } else { print("// ** the input must be \"(ideal,intvec,intvec,int)\""); print("// ** and a lex. GB will be computed from \"dp\" to \"lp\""); } } } else { print("// ** The given input is wrong"); print("// ** and a lex. GB will be computed from \"dp\" to \"lp\""); } } } } list result; result[1] = nP; result[2] = order_str; result[3] = curr_weight; result[4] = target_weight; return(result); } /**************** * Random Walk * ****************/ proc rwalk(ideal Go, int radius, int pert_deg, list #) "SYNTAX: rwalk(ideal i, int radius); if size(#)>0 then rwalk(ideal i, int radius, intvec v, intvec w); intermediate Groebner bases are not reduced if reduction = 0 TYPE: ideal PURPOSE: compute the standard basis of the ideal, calculated via the Random walk algorithm from the ordering \"(a(v),lp)\", \"dp\", \"Dp\" or \"M\" to the ordering \"(a(w),lp)\", \"(a(1,0,...,0),lp)\" or \"M\". SEE ALSO: std, stdfglm, groebner, gwalk, pwalk, fwalk, twalk, awalk1, awalk2 KEYWORDS: Groebner walk EXAMPLE: example rwalk; shows an example" { //-------------------- Initialize parameters ------------------------ int n= nvars(basering); list OSCTW = OrderStringalp_NP("al",#); if(size(#)>1) { if(size(#[2]) == n*n) { OSCTW= OrderStringalp_NP("M", #); } } else { OSCTW= OrderStringalp_NP("al", #); } string ord_str = OSCTW[2]; intvec curr_weight = OSCTW[3]; // original weight vector intvec target_weight = OSCTW[4]; // target weight vector kill OSCTW; //-------------------- Initialize parameters ------------------------ int reduction=1; int printout=0; def xR = basering; execute("ring ostR = "+charstr(xR)+",("+varstr(xR)+"),"+ord_str+";"); def old_ring = basering; ideal G = fetch(xR, Go); G = system("Mrwalk", G, curr_weight, target_weight, radius, pert_deg, reduction, printout); setring xR; kill Go; keepring basering; ideal result = fetch(old_ring, G); attrib(result,"isSB",1); return (result); } example { "EXAMPLE:"; echo = 2; // compute a Groebner basis of I w.r.t. lp. ring r = 32003,(z,y,x), lp; ideal I = y3+xyz+y2z+xz3, 3+xy+x2y+y2z; int radius = 1; int perturb_deg = 2; rwalk(I,radius,perturb_deg); } /***************************************** * Perturbation Walk with random element * *****************************************/ proc prwalk(ideal Go, int radius, int o_pert_deg, int t_pert_deg, list #) "SYNTAX: rwalk(ideal i, int radius); if size(#)>0 then rwalk(ideal i, int radius, intvec v, intvec w); TYPE: ideal PURPOSE: compute the standard basis of the ideal, calculated via the Random Perturbation Walk algorithm from the ordering \"(a(v),lp)\", \"dp\", \"Dp\" or \"M\" to the ordering \"(a(w),lp)\", \"(a(1,0,...,0),lp)\" or \"M\". SEE ALSO: std, stdfglm, groebner, gwalk, pwalk, fwalk, twalk, awalk1, awalk2 KEYWORDS: Groebner walk EXAMPLE: example prwalk; shows an example" { //-------------------- Initialize parameters ------------------------ list OSCTW = OrderStringalp_NP("al", #); int nP = OSCTW[1]; string ord_str = OSCTW[2]; intvec curr_weight = OSCTW[3]; // original weight vector intvec target_weight = OSCTW[4]; // target weight vector kill OSCTW; //-------------------- Initialize parameters ------------------------ int reduction=1; int printout=0; def xR = basering; execute("ring ostR = ("+charstr(xR)+"),("+varstr(xR)+"),"+ord_str+";"); def old_ring = basering; ideal G = fetch(xR, Go); G = system("Mprwalk", G, curr_weight, target_weight, radius, o_pert_deg, t_pert_deg, nP, reduction, printout); setring xR; kill Go; keepring basering; ideal result = fetch(old_ring, G); attrib(result,"isSB",1); return (result); } example { "EXAMPLE:"; echo = 2; // compute a Groebner basis of I w.r.t. lp. ring r = 32003,(z,y,x), lp; ideal I = y3+xyz+y2z+xz3, 3+xy+x2y+y2z; int radius = 1; int o_perturb_deg = 2; int t_perturb_deg = 2; prwalk(I,radius,o_perturb_deg,t_perturb_deg); } /************************************ * Fractal Walk with random element * ************************************/ proc frandwalk(ideal Go, int radius, list #) "SYNTAX: frwalk(ideal i, int radius); frwalk(ideal i, int radius, intvec v, intvec w); TYPE: ideal PURPOSE: compute the standard basis of the ideal w.r.t. the lexicographical ordering or a weighted-lex ordering, calculated via the Random Fractal walk algorithm. SEE ALSO: std, stdfglm, groebner, gwalk, pwalk, twalk, awalk1, awalk2 KEYWORDS: The fractal walk algorithm EXAMPLE: example frandwalk; shows an example" { // we use ring with ordering (a(...),lp,C) list OSCTW = OrderStringalp_NP("al", #); string ord_str = OSCTW[2]; intvec curr_weight = OSCTW[3]; /* current weight vector */ intvec target_weight = OSCTW[4]; /* target weight vector */ kill OSCTW; def xR = basering; execute("ring ostR = ("+charstr(xR)+"),("+varstr(xR)+"),"+ord_str+";"); def old_ring = basering; //print("//** help ring = " + string(basering)); ideal G = fetch(xR, Go); int reduction=1; int printout=0; G = system("Mfrwalk", G, curr_weight, target_weight, radius, reduction, printout); setring xR; //kill Go; keepring basering; ideal result = fetch(old_ring, G); attrib(result,"isSB",1); return (result); } example { "EXAMPLE:"; echo = 2; ring r = 0,(z,y,x), lp; ideal I = y3+xyz+y2z+xz3, 3+xy+x2y+y2z; int reduction = 0; frandwalk(I,2); } singular-4.0.3+ds/Singular/LIB/sagbi.lib000066400000000000000000001174561266270727000177420ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////// version="version sagbi.lib 4.0.0.0 Jun_2013 "; // $Id: 1a57ac39190e7a55f6e7ea39972d0eb26c02b191 $ category="Commutative Algebra"; info=" LIBRARY: sagbi.lib Compute SAGBI basis (subalgebra bases analogous to Groebner bases for ideals) of a subalgebra AUTHORS: Jan Hackfeld, Jan.Hackfeld@rwth-aachen.de Gerhard Pfister, pfister@mathematik.uni-kl.de Viktor Levandovskyy, levandov@math.rwth-aachen.de OVERVIEW: SAGBI stands for 'subalgebra bases analogous to Groebner bases for ideals'. SAGBI bases provide important tools for working with finitely presented subalgebras of a polynomial ring. Note, that in contrast to Groebner bases, SAGBI bases may be infinite. REFERENCES: Ana Bravo: Some Facts About Canonical Subalgebra Bases, MSRI Publications 51, p. 247-254 PROCEDURES: sagbiSPoly(A [,r,m]); computes SAGBI S-polynomials of A sagbiReduce(I,A [,t,mt]); performs subalgebra reduction of I by A sagbi(A [,m,t]); computes SAGBI basis for A sagbiPart(A,k[,m]); computes partial SAGBI basis for A algebraicDependence(I,it); performs iterations of SAGBI for algebraic dependencies of I SEE ALSO: algebra_lib "; LIB "elim.lib"; LIB "toric.lib"; LIB "algebra.lib"; LIB "ring.lib"; ////////////////////////////////////////////////////////////////////////////// static proc assumeQring() { if (ideal(basering) != 0) { ERROR("This function has not yet been implemented over qrings."); } } static proc uniqueVariableName (string variableName) { //Adds character "@" at the beginning of variableName until this name ist unique //(not contained in the names of the ring variables or description of the coefficient field) string ringVars = charstr(basering) + "," + varstr(basering); while (find(ringVars,variableName) <> 0) { variableName="@"+variableName; } return(variableName); } static proc extendRing(def r, ideal leadTermsAlgebra, int method) { /* Extends ring r with additional variables. If k=ncols(leadTermsAlgebra) and * r contains already m additional variables @y, the procedure adds k-m variables * @y(m+1)...@y(k) to the ring. * The monomial ordering of the extended ring depends on method. * Important: When calling this function, the basering (where algebra is defined) has to be active */ def br=basering; int i; ideal varsBasering=maxideal(1); int numTotalAdditionalVars=ncols(leadTermsAlgebra); string variableName=uniqueVariableName("@y"); //get a variable name different from existing variables //-------- extend current baserring r with new variables @y, // one for each new element in ideal algebra ------------- setring r; list l = ringlist(r); for (i=nvars(r)-nvars(br)+1; i<=numTotalAdditionalVars;i++) { l[2][i+nvars(br)]=string(variableName,"(",i,")"); } if (method>=0 && method<=1) { if (nvars(r)==nvars(br)) { //first run of spolynomialGB in sagbi construction algorithms l[3][size(l[3])+1]=l[3][size(l[3])]; //save module ordering l[3][size(l[3])-1]=list("dp",intvec(1:numTotalAdditionalVars)); } else { //overwrite existing order for @y(i) to only get one block for the @y l[3][size(l[3])-1]=list("dp",intvec(1:numTotalAdditionalVars)); } } // VL : todo noncomm case: correctly use l[5] and l[6] // that is update matrices // at the moment this is troublesome, so use nc_algebra call // see how it done in algebraicDependence proc // VL def rNew=ring(l); setring br; return(rNew); } static proc stdKernPhi(ideal kernNew, ideal kernOld, ideal leadTermsAlgebra,int method) { /* Computes Groebner basis of kernNew+kernOld, where kernOld already is a GB * and kernNew contains elements of the form @y(i)-leadTermsAlgebra[i] added to it. * The techniques chosen is specified by the integer method */ ideal kern; attrib(kernOld,"isSB",1); if (method==0) { kernNew=reduce(kernNew,kernOld); kern=kernOld+kernNew; kern=std(kern); //kern=std(kernOld,kernNew); //Found bug using this method. // TODO Change if bug is removed //this call of std return Groebner Basis of ideal kernNew+kernOld // given that kernOld is a Groebner basis } if (method==1) { kernNew=reduce(kernNew,kernOld); kern=slimgb(kernNew+kernOld); } return(kern); } static proc spolynomialsGB(ideal algebra,def r,int method) { /* This procedure does the actual S-polynomial calculation using Groebner basis methods and is * called by the procedures sagbiSPoly,sagbi and sagbiPart. As this procedure is called * at each step of the SAGBI construction algorithm, we can reuse the information already calculated * which is contained in the ring r. This is done in the following order * 1. If r already contain m additional variables and m'=number of elements in algebra, extend r with variables @y(m+1),...,@y(m') * 2. Transfer all objects to this ring, kernOld=kern is the Groebnerbasis already computed * 3. Define ideal kernNew containing elements of the form leadTermsAlgebra(m+1)-@y(m+1),...,leadTermsAlgebra(m')-@y(m') * 4. Compute Groebnerbasis of kernOld+kernNew * 5. Compute the new algebraic relations */ int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information dbprint(ppl,"//Spoly-1- initialisation and precomputation"); def br=basering; ideal varsBasering=maxideal(1); ideal leadTermsAlgebra=lead(algebra); //save leading terms as ordering in ring extension //may not be compatible with ordering in basering int numGenerators=ncols(algebra); def rNew=extendRing(r,leadTermsAlgebra,method); // important: br has to be active here setring r; if (!defined(kern)) //only true for first run of spolynomialGB in sagbi construction algorithms { ideal kern=0; ideal algebraicRelations=0; } setring rNew; //-------------------------- transfer object to new ring rNew ---------------------- ideal varsBasering=fetch(br,varsBasering); ideal kernOld,algebraicRelationsOld; kernOld=fetch(r,kern); //kern is Groebner basis of the kernel of the map Phi:r->K[x_1,...,x_n], x(i)->x(i), @y(i)->leadTermsAlgebra(i) algebraicRelationsOld=fetch(r,algebraicRelations); ideal leadTermsAlgebra=fetch(br,leadTermsAlgebra); ideal listOfVariables=maxideal(1); //---------define kernNew containing elements to be added to the ideal kern -------- ideal kernNew; for (int i=nvars(r)-nvars(br)+1; i<=numGenerators; i++) { kernNew[i-nvars(r)+nvars(br)]=leadTermsAlgebra[i]-listOfVariables[i+nvars(br)]; } //--------------- calculate kernel of Phi depending on method chosen --------------- dbprint(ppl,"//Spoly-2- Groebner basis computation"); attrib(kernOld,"isSB",1); ideal kern=stdKernPhi(kernNew,kernOld,leadTermsAlgebra,method); dbprint(ppl-2,"//Spoly-2-1- ideal kern",kern); //-------------------------- calulate algebraic relations ----------------------- dbprint(ppl,"//Spoly-3- computing new algebraic relations"); ideal algebraicRelations=nselect(kern,1..nvars(br)); attrib(algebraicRelationsOld,"isSB",1); ideal algebraicRelationsNew=reduce(algebraicRelations,algebraicRelationsOld); /* canonicalizing: */ algebraicRelationsNew=canonicalform(algebraicRelationsNew); dbprint(ppl-2,"//Spoly-3-1- ideal of new algebraic relations",algebraicRelationsNew); /* algebraicRelationsOld is a groebner basis by construction (as variable * ordering is * block ordering we have an elemination ordering for the varsBasering) * Therefore, to only get the new algebraic relations, calculate * \ using groebner reduction */ kill kernOld,kernNew,algebraicRelationsOld,listOfVariables; export algebraicRelationsNew,algebraicRelations,kern; setring br; return(rNew); } static proc spolynomialsToric(ideal algebra) { /* This procedure does the actual S-polynomial calculation using toric.lib for * computation of a Groebner basis for the toric ideal kern(phi), where * phi:K[y_1,...,y_m]->K[x_1,...,x_n], y_i->leadmonom(algebra[i]) * By suitable substitutions we obtain the kernel of the map * K[y_1,...,y_m]->K[x_1,...,x_n], x(i)->x(i), @y(i)->leadterm(algebra[i]) */ int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information dbprint(ppl,"//Spoly-1- initialisation and precomputation"); def br=basering; int m=ncols(algebra); int n=nvars(basering); intvec tempVec; int i,j; ideal leadCoefficients; for (i=1;i<=m; i++) { leadCoefficients[i]=leadcoef(algebra[i]); } dbprint(ppl-2,"//Spoly-1-1- Vector of leading coefficients",leadCoefficients); int k=1; for (i=1;i<=n;i++) { for (j=1; j<=m; j++) { tempVec[k]=leadexp(algebra[j])[i]; k++; } } //The columns of the matrix A are now the exponent vectors //of the leadings monomials in algebra. intmat A[n][m]=intmat(tempVec,n,m); dbprint(ppl-2,"//Spoly-1-2- Matrix A",A); //Create the preimage ring K[@y(1),...,@y(m)], where m=ncols(algebra). string variableName=uniqueVariableName("@y"); list l = ringlist(basering); for (i=1; i<=m;i++) { l[2][i]=string(variableName,"(",i,")"); } l[3][2]=l[3][size(l[3])]; l[3][1]=list("dp",intvec(1:m)); def rNew=ring(l); setring rNew; //Use toric_ideal to compute the kernel dbprint(ppl,"//Spoly-2- call of toric_ideal"); ideal algebraicRelations=toric_ideal(A,"ect"); //Suitable substitution dbprint(ppl,"//Spoly-3- substitutions"); ideal leadCoefficients=fetch(br,leadCoefficients); for (i=1; i<=m; i++) { if (leadCoefficients[i]!=0) { algebraicRelations=subst(algebraicRelations,var(i),1/leadCoefficients[i]*var(i)); } } dbprint(ppl-2,"//Spoly-3-1- algebraic relations",algebraicRelations); export algebraicRelations; return(rNew); } static proc reductionGB(ideal F, ideal algebra,def r, int tailreduction,int method,int parRed) { /* This procedure does the actual SAGBI/subalgebra reduction using GB methods and is * called by the procedures sagbiReduce,sagbi and sagbiPart * If r already is an extension of the basering * and contains the ideal kern needed for the subalgebra reduction, * the reduction can be started directly, at each reduction step using the fact that * p=reduce(leadF,kern) in K[@y(1),...,@y(m)] <=> leadF in K[lead(algebra)] * Otherwise some precomputation has to be done, outlined below. * When using sagbiReduce,sagbi and sagbiPart the integer parRed will always be zero. Only the procedure * algebraicDependence causes this procedure to be called with parRed<>0. The only difference when parRed<>0 * is that the reduction algorithms returns the non-zero constants it attains (instead of just returning zero as the * correct remainder), as they will be expressions in parameters for an algebraic dependence. */ int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information dbprint(ppl,"//Red-1- initialisation and precomputation"); def br=basering; int numVarsBasering=nvars(br); ideal varsBasering=maxideal(1); int i; if (numVarsBasering==nvars(r)) { dbprint(ppl-1,"//Red-1-1- Groebner basis computation"); /* Case that ring r is the same ring as the basering. Using proc extendRing, * stdKernPhi * one construct the extension of the current baserring with new variables @y, one for each element * in ideal algebra and calculates the kernel of Phi, where * Phi: r---->br, x_i-->x_i, y_i-->f_i, * algebra={f_1,...f_m}, br=K[x1,...,x_n] und r=K[x1,...x_n,@y1,...@y_m] * This is similarly dones * (however step by step for each run of the SAGBI construction algorithm) * in the procedure spolynomialsGB */ ideal leadTermsAlgebra=lead(algebra); kill r; def r=extendRing(br,leadTermsAlgebra,method); setring r; ideal listOfVariables=maxideal(1); ideal leadTermsAlgebra=fetch(br,leadTermsAlgebra); ideal kern; for (i=1; i<=ncols(leadTermsAlgebra); i++) { kern[i]=leadTermsAlgebra[i]-listOfVariables[numVarsBasering+i]; } kern=stdKernPhi(kern,0,leadTermsAlgebra,method); dbprint(ppl-2,"//Red-1-1-1- Ideal kern",kern); } setring r; poly p,leadF; ideal varsBasering=fetch(br,varsBasering); setring br; map phi=r,varsBasering,algebra; poly p,normalform,leadF; intvec tempExp; //-------------algebraic reduction for each polynomial F[i] ------------------------ dbprint(ppl,"//Red-2- reduction, polynomial by polynomial"); for (i=1; i<=ncols(F);i++) { dbprint(ppl-1,"//Red-2-"+string(i)+"- starting with new polynomial"); dbprint(ppl-2,"//Red-2-"+string(i)+"-1- Polynomial before reduction",F[i]); normalform=0; while (F[i]!=0) { leadF=lead(F[i]); if(leadmonom(leadF)==1) { //K is always contained in the subalgebra, //thus the remainder is zero in this case if (parRed) { //If parRed<>0 save non-zero constants the reduction algorithms attains. break; } else { F[i]=0; break; } } //note: as the ordering in br and r might not be compatible //it can be that lead(F[i]) in r is //different from lead(F[i]) in br. //To take the "correct" leading term therefore take lead(F[i]) //in br and transfer it to the extension r setring r; leadF=fetch(br,leadF); p=reduce(leadF,kern); if (leadmonom(p)0) { algebra=sagbiReduce(algebra,monomials,1); for (i=1; i<=ncols(algebra);i++) { if(size(monomials[i])==1) { //Put back monomials into algebra. algebra[i]=monomials[i]; } } } return(algebra); } static proc sagbiConstruction(ideal algebra, int iterations, int tailreduction, int method,int parRed) /* This procedure is the SAGBI construction algorithm and does the actual computation * both for the procedure sagbi and sagbiPart. * - If the sagbi procedure calls this procedure, iterations==-1 * and this procedure only stops * if all S-Polynomials reduce to zero * (criterion for termination of SAGBI construction algorithm). * - If the sagbiPart procedure calls this procedure, iterations>=0 * and iterations specifies the * number of iterations. A degree boundary is not used here. * When this method is called via the procedures sagbi and sagbiPart the integer parRed * will always be zero. Only the procedure algebraicDependence calls this procedure with * parRed<>0. The only difference when parRed<>0 is that the reduction algorithms returns * the non-zero constants it attains (instead of just returning zero as the correct * remainder), as they will be expressions in parameters for an algebraic dependence. * These constants are saved in the ideal reducedParameters. */ { int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information dbprint(ppl,"// -0- initialisation and precomputation"); def br=basering; int i=1; ideal reducedParameters; int numReducedParameters=1; //number of elements plus one in reducedParameters int j; if (parRed==0) //if parRed<>0 the algebra does not contain monomials and normalisation should be avoided { algebra=reduceByMonomials(algebra); algebra=simplify(simplify(algebra,3),4); } // canonicalizing the gen's: algebra = canonicalform(algebra); ideal P=1; //note: P is initialized this way, so that the while loop is entered. //P gets overriden there, anyhow. ideal varsBasering=maxideal(1); map phi; ideal spolynomialsNew; def r=br; while (size(P)>0) { dbprint(ppl,"// -"+string(i)+"- interation of SAGBI construction algorithm"); dbprint(ppl-1,"// -"+string(i)+"-1- Computing algebraic relations"); def rNew=spolynomialsGB(algebra,r,method); /* canonicalizing inside! */ kill r; def r=rNew; kill rNew; phi=r,varsBasering,algebra; dbprint(ppl-1,"// -"+string(i)+"-2- Substituting into algebraic relations"); spolynomialsNew=simplify(phi(algebraicRelationsNew),6); //By construction spolynomialsNew only contains the spolynomials, //that have not already //been calculated in the steps before. dbprint(ppl-1,"// -"+string(i)+"-3- SAGBI reduction"); dbprint(ppl-2,"// -"+string(i)+"-3-1- new S-polynomials before reduction",spolynomialsNew); P=reductionGB(spolynomialsNew,algebra,r,tailreduction,method,parRed); if (parRed) { for(j=1; j<=ncols(P); j++) { if (leadmonom(P[j])==1) { reducedParameters[numReducedParameters]=P[j]; P[j]=0; numReducedParameters++; } } } if (parRed==0) { P=reduceByMonomials(P); //Reducing with monomials is cheap and can only result in less terms P=simplify(simplify(P,3),4); //Avoid that zeros are added to the bases or one element in P more than once } else { P=simplify(P,6); } /* canonicalize ! */ P = canonicalform(P); dbprint(ppl-2,"// -"+string(i)+"-3-1- new S-polynomials after reduction",P); algebra=algebra,P; //Note that elements and order of elements must in algebra must not be changed, //otherwise the already calculated //ideal in r will give wrong results. Thus it is important to use a komma here. i=i+1; if (iterations!=-1 && i>iterations) //When iterations==-1 the number of iterations is unlimited { break; } } if (iterations!=-1) { //case that sagbiPart called this procedure if (size(P)==0) { dbprint(4-voice, "//SAGBI construction algorithm terminated after "+string(i-1) +" iterations, as all SAGBI S-polynomials reduced to 0. //Returned generators therefore are a SAGBI basis."); } else { dbprint(4-voice, "//SAGBI construction algorithm stopped as it reached the limit of " +string(iterations)+" iterations. //In general the returned generators are no SAGBI basis for the given algebra."); } } kill r; if (parRed) { algebra=algebra,reducedParameters; } algebra = simplify(algebra,6); algebra = canonicalform(algebra); return(algebra); } proc sagbiSPoly(ideal algebra,list #) "USAGE: sagbiSPoly(A[, returnRing, meth]); A is an ideal, returnRing and meth are integers. RETURN: ideal or ring ASSUME: basering is not a qring PURPOSE: Returns SAGBI S-polynomials of the leading terms of a given ideal A if returnRing=0. @* Otherwise returns a new ring containing the ideals algebraicRelations @* and spolynomials, where these objects are explained by their name. @* See the example on how to access these objects. @format The other optional argument meth determines which method is used for computing the algebraic relations. - If meth=0 (default), the procedure std is used. - If meth=1, the procedure slimgb is used. - If meth=2, the prodecure uses toric_ideal. @end format EXAMPLE: example sagbiSPoly; shows an example" { assumeQring(); int returnRing; int method=0; def br=basering; ideal spolynomials; if (size(#)>=1) { if (typeof(#[1])=="int") { returnRing=#[1]; } else { ERROR("Type of first optional argument needs to be int."); } } if (size(#)==2) { if (typeof(#[2])=="int") { if (#[2]<0 || #[2]>2) { ERROR("Type of second optional argument needs to be 0,1 or 2."); } else { method=#[2]; } } else { ERROR("Type of second optional argument needs to be int."); } } if (method>=0 and method<=1) { ideal varsBasering=maxideal(1); def rNew=spolynomialsGB(algebra,br,method); map phi=rNew,varsBasering,algebra; spolynomials=simplify(phi(algebraicRelationsNew),7); } if(method==2) { def r2=spolynomialsToric(algebra); map phi=r2,algebra; spolynomials=simplify(phi(algebraicRelations),7); def rNew=extendRing(br,lead(algebra),0); setring rNew; ideal algebraicRelations=imap(r2,algebraicRelations); export algebraicRelations; setring br; } if (returnRing==0) { return(spolynomials); } else { setring rNew; ideal spolynomials=fetch(br,spolynomials); export spolynomials; setring br; return(rNew); } } example { "EXAMPLE:"; echo = 2; ring r= 0,(x,y),dp; ideal A=x*y+x,x*y^2,y^2+y,x^2+x; //------------------ Compute the SAGBI S-polynomials only sagbiSPoly(A); //------------------ Extended ring is to be returned, which contains // the ideal of algebraic relations and the ideal of the S-polynomials def rNew=sagbiSPoly(A,1); setring rNew; spolynomials; algebraicRelations; //----------------- Now we verify that the substitution of A[i] into @y(i) // results in the spolynomials listed above ideal A=fetch(r,A); map phi=rNew,x,y,A; ideal spolynomials2=simplify(phi(algebraicRelations),1); spolynomials2; } proc sagbiReduce(def idealORpoly, ideal algebra, list #) "USAGE: sagbiReduce(I, A[, tr, mt]); I, A ideals, tr, mt optional integers RETURN: ideal of remainders of I after SAGBI reduction by A ASSUME: basering is not a qring PURPOSE: @format The optional argument tr=tailred determines whether tail reduction will be performed. - If (tailred=0), no tail reduction is done. - If (tailred<>0), tail reduction is done. The other optional argument meth determines which method is used for Groebner basis computations. - If mt=0 (default), the procedure std is used. - If mt=1, the procedure slimgb is used. @end format EXAMPLE: example sagbiReduce; shows an example" { assumeQring(); int tailreduction=0; //Default int method=0; //Default ideal I; if(typeof(idealORpoly)=="ideal") { I=idealORpoly; } else { if(typeof(idealORpoly)=="poly") { I[1]=idealORpoly; } else { ERROR("Type of first argument needs to be an ideal or polynomial."); } } if (size(#)>=1) { if (typeof(#[1])=="int") { tailreduction=#[1]; } else { ERROR("Type of optional argument needs to be int."); } } if (size(#)>=2 ) { if (typeof(#[2])=="int") { if (#[2]<0 || #[2]>1) { ERROR("Type of second optional argument needs to be 0 or 1."); } else { method=#[2]; } } else { ERROR("Type of optional arguments needs to be int."); } } def r=basering; I=simplify(reductionGB(I,algebra,r,tailreduction,method,0),1); if(typeof(idealORpoly)=="ideal") { return(I); } else { if(typeof(idealORpoly)=="poly") { return(I[1]); } } } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; ideal A=x2,2*x2y+y,x3y2; poly p1=x^5+x2y+y; poly p2=x^16+x^12*y^5+6*x^8*y^4+x^6+y^4+3; ideal P=p1,p2; //--------------------------------------------- //SAGBI reduction of polynomial p1 by algebra A. //Default call, that is, no tail-reduction is done. sagbiReduce(p1,A); //--------------------------------------------- //SAGBI reduction of set of polynomials P by algebra A, //now tail-reduction is done. sagbiReduce(P,A,1); } proc sagbi(ideal algebra, list #) "USAGE: sagbi(A[, tr, mt]); A ideal, tr, mt optional integers RETURN: ideal, a SAGBI basis for A ASSUME: basering is not a qring PURPOSE: Computes a SAGBI basis for the subalgebra given by the generators in A. @format The optional argument tr=tailred determines whether tail reduction will be performed. - If (tailred=0), no tail reduction is performed, - If (tailred<>0), tail reduction is performed. The other optional argument meth determines which method is used for Groebner basis computations. - If mt=0 (default), the procedure std is used. - If mt=1, the procedure slimgb is used. @end format EXAMPLE: example sagbi; shows an example" { assumeQring(); int tailreduction=0; //default value int method=0; //default value if (size(#)>=1) { if (typeof(#[1])=="int") { tailreduction=#[1]; } else { ERROR("Type of optional argument needs to be int."); } } if (size(#)>=2 ) { if (typeof(#[2])=="int") { if (#[2]<0 || #[2]>1) { ERROR("Type of second optional argument needs to be 0 or 1."); } else { method=#[2]; } } else { ERROR("Type of optional arguments needs to be int."); } } ideal a; a=sagbiConstruction(algebra,-1,tailreduction,method,0); a=simplify(a,7); // a=interreduced(a); return(a); } example { "EXAMPLE:"; echo = 2; ring r= 0,(x,y,z),dp; ideal A=x2,y2,xy+y; //Default call, no tail-reduction is done. sagbi(A); //--------------------------------------------- //Call with tail-reduction and method specified. sagbi(A,1,0); } proc sagbiPart(ideal algebra, int iterations, list #) "USAGE: sagbiPart(A, k,[tr, mt]); A is an ideal, k, tr and mt are integers RETURN: ideal ASSUME: basering is not a qring PURPOSE: Performs k iterations of the SAGBI construction algorithm for the subalgebra given by the generators given by A. @format The optional argument tr=tailred determines if tail reduction will be performed. - If (tailred=0), no tail reduction is performed, - If (tailred<>0), tail reduction is performed. The other optional argument meth determines which method is used for Groebner basis computations. - If mt=0 (default), the procedure std is used. - If mt=1, the procedure slimgb is used. @end format EXAMPLE: example sagbiPart; shows an example" { assumeQring(); int tailreduction=0; //default value int method=0; //default value if (size(#)>=1) { if (typeof(#[1])=="int") { tailreduction=#[1]; } else { ERROR("Type of optional argument needs to be int."); } } if (size(#)>=2 ) { if (typeof(#[2])=="int") { if (#[2]<0 || #[2]>3) { ERROR("Type of second optional argument needs to be 0 or 1."); } else { method=#[2]; } } else { ERROR("Type of optional arguments needs to be int."); } } if (iterations<0) { ERROR("Number of iterations needs to be non-negative."); } ideal a; a=sagbiConstruction(algebra,iterations,tailreduction,method,0); a=simplify(a,6); // a=interreduced(a); return(a); } example { "EXAMPLE:"; echo = 2; ring r= 0,(x,y,z),dp; //The following algebra does not have a finite SAGBI basis. ideal A=x,xy-y2,xy2; //--------------------------------------------------- //Call with two iterations, no tail-reduction is done. sagbiPart(A,2); //--------------------------------------------------- //Call with three iterations, tail-reduction and method 0. sagbiPart(A,3,1,0); } proc algebraicDependence(ideal I,int iterations) "USAGE: algebraicDependence(I,it); I an an ideal, it is an integer RETURN: ring ASSUME: basering is not a qring PURPOSE: Returns a ring containing the ideal @code{algDep}, which contains possibly @* some algebraic dependencies of the elements of I obtained through @code{it} @* iterations of the SAGBI construction algorithms. See the example on how @* to access these objects. EXAMPLE: example algebraicDependence; shows an example" { assumeQring(); int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information dbprint(ppl,"//AlgDep-1- initialisation and precomputation"); def br=basering; int i; I=simplify(I,2); //avoid that I contains zeros //Create two polynomial rings, which both are extensions of the current basering. //The first ring will contain the additional paramteres @c(1),...,@c(m), the second one //will contain the additional variables @c(1),...,@c(m), where m=ncols(I). string parameterName=uniqueVariableName("@c"); list l = ringlist(basering); list parList; for (i=1; i<=ncols(I);i++) { parList[i]=string(parameterName,"(",i,")"); } l[1]=list(l[1],parList,list(list("dp",1:ncols(I)))); //add @c(i) to the ring as paramteres ideal temp=0; l[1][4]=temp; // addition VL: noncomm case int isNCcase = 0; // default for comm // if (size(l)>4) // { // // that is we're in the noncomm algebra // isNCcase = 1; // noncomm // matrix @C@ = l[5]; // matrix @D@ = l[6]; // l = l[1],l[2],l[3],l[4]; // } def parameterRing=ring(l); string extendVarName=uniqueVariableName("@c"); list l2 = ringlist(basering); for (i=1; i<=ncols(I);i++) { l2[2][i+nvars(br)]=string(extendVarName,"(",i,")"); //add @c(i) to the rings as variables } l2[3][size(l2[3])+1]=l2[3][size(l2[3])]; l2[3][size(l2[3])-1]=list("dp",intvec(1:ncols(I))); // if (isNCcase) // { // // that is we're in the noncomm algebra // matrix @C@2 = l2[5]; // matrix @D@2 = l2[6]; // l2 = l2[1],l2[2],l2[3],l2[4]; // } def extendVarRing=ring(l2); setring extendVarRing; // VL : this requires extended matrices // let's forget it for the moment // since this holds only for showing the answer // if (isNCcase) // { // matrix C2=imap(br,@C@2); // matrix D2=imap(br,@D@2); // def er2 = nc_algebra(C2,D2); // setring er2; // def extendVarRing=er2; // } setring parameterRing; // if (isNCcase) // { // matrix C=imap(br,@C@); // matrix D=imap(br,@D@); // def pr = nc_algebra(C,D); // setring pr; // def parameterRing=pr; // } //Compute a partial SAGBI basis of the algebra generated by I[1]-@c(1),...,I[m]-@c(m), //where the @c(n) are parameters ideal I=fetch(br,I); ideal algebra; for (i=1; i<=ncols(I);i++) { algebra[i]=I[i]-par(i); } dbprint(ppl,"//AlgDep-2- call of SAGBI construction algorithm"); algebra=sagbiConstruction(algebra, iterations,0,0,1); dbprint(ppl,"//AlgDep-3- postprocessing of results"); int j=1; //If K[x_1,...,x_n] was the basering, then algebra is in K(@c(1),...,@c(m))[x_1,...x_n]. We intersect //elements in algebra with K(@c(1),..,@c(n)) to get algDep. Note that @c(i) can only appear in the numerator, //as the SAGBI construction algorithms just multiplies and substracts polynomials. So actually we have //algDep=algebra intersect K[@c(1),...,@c(m)] ideal algDep; for (i=1; i<= ncols(algebra); i++) { if (leadmonom(algebra[i])==1) //leadmonom(algebra[i])==1 iff algebra[i] in K[@c(1),...,@c(m)] { algDep[j]=algebra[i]; j++; } } //Transfer algebraic dependencies to ring where @c(i) are not parameters, but now variables. setring extendVarRing; ideal algDep=imap(parameterRing,algDep); ideal algebra=imap(parameterRing,algebra); //Now get rid of constants in K that may have been added to algDep. for (i=1; i<=ncols(algDep); i++) { if(leadmonom(algDep[i])==1) { algDep[i]=0; } } algDep=simplify(algDep,2); export algDep,algebra; setring br; return(extendVarRing); } example { "EXAMPLE:"; echo = 2; ring r= 0,(x,y),dp; //The following algebra does not have a finite SAGBI basis. ideal I=x^2, xy-y2, xy2; //--------------------------------------------------- //Call with two iterations def DI = algebraicDependence(I,2); setring DI; algDep; // we see that no dependency has been seen so far //--------------------------------------------------- //Call with two iterations setring r; kill DI; def DI = algebraicDependence(I,3); setring DI; algDep; map F = DI,x,y,x^2, xy-y2, xy2; F(algDep); // we see that it is a dependence indeed } static proc interreduced(ideal I) { /* performs subalgebra interreduction of a set of subalgebra generators */ int ppl = printlevel-voice+3; //variable for additional printlevel-dependend information dbprint(ppl,"//Interred-1- starting interreduction"); ideal J,B; int i,j,k; poly f; for(k=1;k<=ncols(I);k++) { dbprint(ppl-1,"//Interred-1-"+string(k)+"- reducing next poly"); f=I[k]; I[k]=0; f=sagbiReduce(f,I,1); I[k]=f; } I=simplify(I,2); dbprint(ppl,"//Interred-2- interreduction completed"); return(I); } /////////////////////////////////////////////////////////////////////////////// proc sagbiReduction(poly p,ideal dom,list #) "USAGE: sagbiReduction(p,dom[,n]); p poly , dom ideal RETURN: polynomial, after one step of subalgebra reduction PURPOSE: @format Three algorithm variants are used to perform subalgebra reduction. The positive interger n determines which variant should be used. n may take the values 0 (default), 1 or 2. @end format NOTE: works over both polynomial rings and their quotients EXAMPLE: example sagbiReduction; shows an example" { def bsr=basering; ideal B=ideal(bsr);//When the basering is quotient ring this type casting // gives the quotient ideal. int b=size(B); int n=nvars(bsr); //In quotient rings, SINGULAR, usually does not reduce polynomials w.r.t the //quotient ideal,therefore we should first reduce, //when it is necessary for computations, // to have a uniquely determined representant for each equivalent //class,which is the case of this algorithm. if(b !=0) //means that the basering is a quotient ring { p=reduce(p,std(0)); dom=reduce(dom,std(0)); } int i,choose; int z=ncols(dom); if((size(#)>0) && (typeof(#[1])=="int")) { choose = #[1]; } if (size(#)>1) { choose =#[2]; } //=======================first algorithm(default)========================= if ( choose == 0 ) { list L = algebra_containment(lead(p),lead(dom),1); if( L[1]==1 ) { // the ring L[2] = char(bsr),(x(1..nvars(bsr)),y(1..z)),(dp(n),dp(m)), // contains poly check s.t. LT(p) is of the form check(LT(f1),...,LT(fr)) def s1 = L[2]; map psi = s1,maxideal(1),dom; poly re = p - psi(check); // divide by the maximal power of #[1] if ( (size(#)>0) && (typeof(#[1])=="poly") ) { while ((re!=0) && (re!=#[1]) &&(subst(re,#[1],0)==0)) { re=re/#[1]; } } return(re); } return(p); } //======================2end variant of algorithm========================= //It uses two different commands for elimaination. //if(choose==1):"elimainate"command. //if (choose==2):"nselect" command. else { poly v=product(maxideal(1)); //------------- change the basering bsr to bsr[@(0),...,@(z)] ---------- def s=addNvarsTo(basering,z+1,,"@",0); setring s; // Ev hier die Reihenfolge der Vars aendern. Dazu muss unten aber entsprechend // geaendert werden: // execute("ring s="+charstr(basering)+",(@(0..z),"+varstr(basering)+"),dp;"); //constructs the leading ideal of dom=(p-@(0),dom[1]-@(1),...,dom[z]-@(z)) ideal dom=imap(bsr,dom); for (i=1;i<=z;i++) { dom[i]=lead(dom[i])-var(nvars(bsr)+i+1); } dom=lead(imap(bsr,p))-@(0),dom; //---------- eliminate the variables of the basering bsr -------------- //i.e. computes dom intersected with K[@(0),...,@(z)]. if(choose==1) { ideal kern=eliminate(dom,imap(bsr,v));//eliminate does not need a //standard basis as input. } if(choose==2) { ideal kern= nselect(groebner(dom),1..n);//"nselect" is combinatorial command //which uses the internal command // "simplify" } //--------- test wether @(0)-h(@(1),...,@(z)) is in ker --------------- // for some poly h and divide by maximal power of q=#[1] poly h; z=size(kern); for (i=1;i<=z;i++) { h=kern[i]/@(0); if (deg(h)==0) { h=(1/h)*kern[i]; // define the map psi : s ---> bsr defined by @(i) ---> p,dom[i] setring bsr; map psi=s,maxideal(1),p,dom; poly re=psi(h); // divide by the maximal power of #[1] if ((size(#)>0) && (typeof(#[1])== "poly") ) { while ((re!=0) && (re!=#[1]) &&(subst(re,#[1],0)==0)) { re=re/#[1]; } } return(re); } } setring bsr; return(p); } } example {"EXAMPLE:"; echo = 2; ring r= 0,(x,y),dp; ideal dom =x2,y2,xy-y; poly p=x4+x3y+xy2-y2; sagbiReduction(p,dom); sagbiReduction(p,dom,2); // now let us see the action over quotient ring ideal I = xy; qring Q = std(I); ideal dom = imap(r,dom); poly p = imap(r,p); sagbiReduction(p,dom,1); } proc sagbiNF(id,ideal dom,int k,list#) "USAGE: sagbiNF(id,dom,k[,n]); id either poly or ideal,dom ideal, k and n positive intergers. RETURN: same as type of id; ideal or polynomial. PURPOSE: @format The integer k determines what kind of s-reduction is performed: - if (k=0) no tail s-reduction is performed. - if (k=1) tail s-reduction is performed. Three Algorithm variants are used to perform subalgebra reduction. The positive integer n determines which variant should be used. n may take the values (0 or default),1 or 2. @end format NOTE: sagbiNF works over both rings and quotient rings EXAMPLE: example sagbiNF; show example " { ideal rs; if (ideal(basering) == 0) { rs = sagbiReduce(id,dom,k) ; } else { rs = sagbiReduction(id,dom,k) ; } if (typeof(id)=="poly") { return (rs[1]); } return(rs); } example {"EXAMPLE:"; echo = 2; ring r=0,(x,y),dp; poly p=x4+x2y+y; ideal dom =x2,x2y+y,x3y2; sagbiNF(p,dom,1); ideal I= x2-xy; qring Q=std(I); // we go to the quotient ring poly p=imap(r,p); NF(p,std(0)); // the representative of p has changed ideal dom = imap(r,dom); print(matrix(NF(dom,std(0)))); // dom has changed as well sagbiNF(p,dom,0); // no tail reduction sagbiNF(p,dom,1);// tail subalgebra reduction is performed } static proc canonicalform(ideal I) { /* placeholder for the canonical form of a set of gen's */ /* for the time being we agree on content(p)=1; that is coeffs with no fractions */ int i; ideal J=I; for(i=ncols(I); i>=1; i--) { J[i] = canonicalform_poly(I[i]); } return(J); } static proc canonicalform_poly(poly p) { /* placeholder for the canonical form of a poly */ /* for the time being we agree on content(p)=1; that is coeffs with no fractions */ number n = content(p); return( p/content(p) ); } /* ring r= 0,(x,y),dp; //The following algebra does not have a finite SAGBI basis. ideal J=x^2, xy-y2, xy2, x^2*(x*y-y^2)^2 - (x*y^2)^2*x^4 + 11; //--------------------------------------------------- //Call with two iterations def DI = algebraicDependence(J,2); setring DI; algDep; */ singular-4.0.3+ds/Singular/LIB/schreyer.lib000066400000000000000000007141721266270727000204770ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// version="version schreyer.lib 4.0.0.0 Jun_2013 "; // $Id: 6fc099b9bfe722bb58361925280476feffaa6a22 $ category="General purpose"; info=" LIBRARY: schreyer.lib Schreyer resolution computations and helpers for derham.lib AUTHOR: Oleksandr Motsak , where U={motsak}, D={mathematik.uni-kl.de} KEYWORDS: Schreyer ordering; Schreyer resolution; syzygy OVERVIEW: The library contains several procedures for computing a/part of Schreyer resoltion (cf. [SFO]), and some helpers for derham.lib (which requires resolutions over the homogenized Weyl algebra) for that purpose. The input for any resolution computation is a set of vectors M in form of a module over some basering R. The helpers works both in the commutative and non-commutative setting (cf. [MO]), that is the ring R may be non-commutative, in which case the ring ordering over it must be global. They produce/work with partial Schreyer resolutions of (R^rank(M))/M in form of a specially constructed ring (endowed with a special ring ordering that will be extended in the course of a resolution computation) containing the following objects: @* RES: the list of modules contains the images of maps (also called syzygy modules) substituting the computed beginning of a Schreyer resolution, that is, each syzygy module is given by a Groebner basis with respect to the corresponding Schreyer ordering. RES starts with a zero map given by rank(M) zero generators indicating that the image of the first differential map is zero. The second map RES[2] is given by M, which indicates that the resolution of (R^rank(M))/M is being computed. @* MRES: the module is a direct sum of modules from RES and thus comprises all computed differentials. Syzygies are shifted so that gen(i) is mapped to MRES[i] under the differential map. @* Here, we call a free resolution a Schreyer resolution if each syzygy module is given by a Groebner basis with respect to the corresponding Schreyer ordering. A Schreyer resolution can be much bigger than a minimal resolution of the same module, but may be easier to construct. The Schreyer ordering succesively extends the starting module ordering on M (defined in Singular by the basering R) and is extended to higher syzygies using the following definition: @* a < b if and only if (d(a) 0 ) { if( typeof(#[1]) == "int" || typeof(#[1]) == "bigint" ) { k = #[1]; } } if( k < r ) { "// *** Wrong k: ", k, " < nrows: ", r, " => setting k = r = ", r; k = r; } // "k: ", k; "c: ", c; "I: ", I; for( i = c; i > 0; i-- ) { I[i] = I[i] + gen(k + i); } // Syzextra::DetailedPrint(I); return(I); } static proc separateSyzGB( module J, int c ) { module II, G; vector v; int i; J = simplify(J, 2); for( i = ncols(J); i > 0; i-- ) { v = J[i]; if( Syzextra::leadcomp(v) > c ) { II[i] = v; } else { G[i] = v; // leave only gen(i): i <= c } } II = simplify(II, 2); G = simplify(G, 2); return (list(G, II)); } static proc splitSyzGB( module J, int c ) { module JJ; vector v, vv; int i; for( i = ncols(J); i > 0; i-- ) { v = J[i]; vv = 0; while( Syzextra::leadcomp(v) <= c ) { vv = vv + lead(v); v = v - lead(v); } J[i] = vv; JJ[i] = v; } J = simplify(J, 2); JJ = simplify(JJ, 2); return (list(J, JJ)); } static proc Sinit(module M) { def @save = basering; int @DEBUG = 0; // !system("with", "ndebug"); if( @DEBUG ) { "Sinit::Input"; type(M); // Syzextra::DetailedPrint(M); attrib(M); } int @RANK = nrows(M); int @SIZE = ncols(M); int @IS_A_SB = attrib(M, "isSB"); // ??? only if all weights were zero?! if( !@IS_A_SB ) { M = std(M); // this should be faster than computing std in S (later on) } def S = Syzextra::MakeInducedSchreyerOrdering(1); // 1 puts history terms to the back // TODO: NOTE: +1 causes trouble to Singular interpreter!!!??? setring S; // a new ring with a Schreyer ordering if( @DEBUG ) { "Sinit::StartingISRing"; basering; // Syzextra::DetailedPrint(basering); } // Setup the leading syzygy^{-1} module to zero: module Z = 0; Z[@RANK] = 0; attrib(Z, "isHomog", intvec(0)); module MRES = Z; list RES; RES[1] = Z; module F = freemodule(@RANK); intvec @V = deg(F[1..@RANK]); module M = imap(@save, M); attrib(M, "isHomog", @V); attrib(M, "isSB", 1); if( @DEBUG ) { "Sinit::SB_Input: "; type(M); attrib(M); attrib(M, "isHomog"); // Syzextra::DetailedPrint(M); } if( @DEBUG ) { // 0^th syz. property if( size(module(transpose( transpose(M) * transpose(MRES) ))) > 0 ) { transpose( transpose(M) * transpose(MRES) ); "ERROR: transpose( transpose(M) * transpose(MRES) ) != 0!!!"; Syzextra::m2_end(666); } } RES[size(RES)+1] = M; // list of all syzygy modules MRES = MRES, M; attrib(MRES, "isHomog", @V); attrib(S, "InducionLeads", lead(M)); attrib(S, "InducionStart", @RANK); if( @DEBUG ) { "Sinit::MRES"; Syzextra::DetailedPrint(MRES); attrib(MRES, "isHomog"); attrib(S); } export RES; export MRES; return (S); } static proc Sstep() { int @DEBUG = 0; // !system("with", "ndebug"); if( @DEBUG ) { "Sstep::NextInducedRing"; Syzextra::DetailedPrint(basering); attrib(basering, "InducionLeads"); attrib(basering, "InducionStart"); Syzextra::GetInducedData(); } // syzygy step: /* // is initial weights are all zeroes! def L = lead(M); intvec @V = deg(M[1..ncols(M)]); @W; @V; @W = @V; attrib(L, "isHomog", @W); Syzextra::SetInducedReferrence(L, @RANK, 0); */ // def L = lead(MRES); // @W = @W, @V; // attrib(L, "isHomog", @W); // General setting: // Syzextra::SetInducedReferrence(MRES, 0, 0); // limit: 0! int @l = size(RES); module M = RES[@l]; module L = attrib(basering, "InducionLeads"); int limit = attrib(basering, "InducionStart"); // L; limit; int @RANK = ncols(MRES) - ncols(M); // nrows(M); // what if M is zero?! /* if( @RANK != nrows(M) ) { type(MRES); @RANK; type(M); pause(); } */ intvec @W = attrib(M, "isHomog"); intvec @V = deg(M[1..ncols(M)]); @V = @W, @V; if( @DEBUG ) { "Sstep::NextInput: "; M; deg(M[1..ncols(M)]); // no use of @W :(? @RANK; Syzextra::DetailedPrint(MRES); attrib(MRES, "isHomog"); @W; deg(MRES[1..ncols(MRES)]); } Syzextra::SetInducedReferrence(L, limit, 0); def K = prepareSyz(M, @RANK); // K; // attrib(K, "isHomog", @V); Syzextra::DetailedPrint(K, 1000); // pause(); K = Syzextra::idPrepare(K, @RANK); // std(K); // ? K = simplify(K, 2); // K; module N = separateSyzGB(K, @RANK)[2]; // 1^st syz. module: vectors which start in lower part (comp >= @RANK) // "N_0: "; N; Syzextra::DetailedPrint(N, 10); // basering; print(@V); type(N); // attrib(N, "isHomog", @V); // TODO: fix "wrong weights"!!!? deg is wrong :((( N = std(N); attrib(N, "isHomog", @V); // N; if( @DEBUG ) { if( size(N) > 0 ) { // next syz. property if( size(module(transpose( transpose(N) * transpose(MRES) ))) > 0 ) { MRES; "N: "; N; Syzextra::DetailedPrint(N, 10); "K:"; K; Syzextra::DetailedPrint(K, 10); "RANKS: ", @RANK; "ERROR: transpose( transpose(N) * transpose(MRES) ) != 0!!!"; transpose( transpose(N) * transpose(MRES) ); "transpose(N) * transpose(MRES): "; transpose(N) * transpose(MRES); Syzextra::DetailedPrint(module(_), 2); Syzextra::m2_end(666); } } } RES[@l + 1] = N; // list of all syzygy modules MRES = MRES, N; attrib(MRES, "isHomog", @V); L = L, lead(N); attrib(basering, "InducionLeads", L); if( @DEBUG ) { "Sstep::NextSyzOutput: "; Syzextra::DetailedPrint(N); attrib(N, "isHomog"); } } proc Scontinue(int l) "USAGE: Scontinue(int len) RETURN: nothing, instead it changes the currently active resolution PURPOSE: extends the currently active resolution by at most len syzygies ASSUME: must be used within a ring returned by Sres or Ssyz EXAMPLE: example Scontinue; shows an example " { def data = Syzextra::GetInducedData(); if( (!defined(RES)) || (!defined(MRES)) || (typeof(data) != "list") || (size(data) != 2) ) { ERROR("Sorry, but basering does not seem to be returned by Sres or Ssyz"); } for (; (l != 0) && (size(RES[size(RES)]) > 0); l-- ) { Sstep(); } } example { "EXAMPLE:"; echo = 2; ring r; module M = maxideal(1); M; def S = Ssyz(M); setring S; S; "Only the first syzygy: "; RES; MRES; "More syzygies: "; Scontinue(10); RES; MRES; } proc Ssyz(module M) "USAGE: Ssyz(module M) RETURN: ring, containing a Schreyer resolution PURPOSE: computes a Schreyer resolution of M of length 1 (see the library overview) SEE ALSO: Sres EXAMPLE: example Ssyz; shows an example " { def S = Sinit(M); setring S; Sstep(); // NOTE: what if M is zero? return (S); } example { "EXAMPLE:"; echo = 2; ring r; module M = maxideal(1); M; def S = Ssyz(M); setring S; S; "Only the first syzygy: "; RES; MRES; // Note gen(i) kill S; setring r; kill M; module M = 0; def S = Ssyz(M); setring S; S; "Only the first syzygy: "; RES; MRES; } proc Sres(module M, int l) "USAGE: Sres(module M, int len) RETURN: ring, containing a Schreyer resolution PURPOSE: computes a Schreyer resolution of M of length at most len (see the library overview) NOTE: If given len is zero then nvars(basering) + 1 is used instead. SEE ALSO: Ssyz EXAMPLE: example Sres; shows an example " { def S = Sinit(M); setring S; if (l == 0) { l = nvars(basering) + 1; // not really an estimate...?! } Sstep(); l = l - 1; Scontinue(l); return (S); } example { "EXAMPLE:"; echo = 2; ring r; module M = maxideal(1); M; def S = Sres(M, 0); setring S; S; RES; MRES; kill S; setring r; kill M; def A = nc_algebra(-1,0); setring A; ideal Q = var(1)^2, var(2)^2, var(3)^2; qring SCA = twostd(Q); basering; module M = maxideal(1); def S = Sres(M, 2); setring S; S; RES; MRES; } // ================================================================== // LIB "general.lib"; // for sort static proc MySort(def M) " Sorts the given ideal or module wrt >_{(c, ds)} (.<.<.<.<) " { if( typeof( attrib(basering, "DEBUG") ) == "int" ) { int @DEBUG = attrib(basering, "DEBUG"); } else { int @DEBUG = 0; // !system("with", "ndebug"); } if( typeof( attrib(basering, "KERCHECK") ) == "int" ) { int @KERCHECK = attrib(basering, "KERCHECK"); } else { int @KERCHECK = @DEBUG; } if( @DEBUG ) { "MySort:: Input: "; M; } def @N = M; if( size(M) > 0 ) { Syzextra::Sort_c_ds(@N); if( @KERCHECK ) { def iv = sort(lead(M), "c,ds", 1)[2]; // ,1 => reversed! // TODO: not needed? def @M = M; @M = M[iv]; // 0^th syz. property if( (size(@N) + size(@M)) > 0 ) { if( size(module( matrix(module(matrix(@N))) - matrix(module(matrix(@M))) )) > 0 ) { "ERROR: MySort: wrong sorting in 'MySort': @N != @M!!!"; "@M:"; @M; "@N:"; @N; "module( matrix(module(matrix(@N))) - matrix(module(matrix(@M))) ): "; module( matrix(module(matrix(@N))) - matrix(module(matrix(@M))) ); "ERROR: MySort: wrong sorting in 'MySort': @N != @M!!!"; Syzextra::m2_end(666); } } } } if( @DEBUG ) { "MySort:: Ouput: "; @N; } return (@N); } static proc SSinit(def M) { // rtimer, "***TIMESNAP0 for SSinit: on level: [",-1,"] :: t: ", timer, ", r: ", rtimer; if( (typeof(M) != "module") && (typeof(M) != "ideal") ) { ERROR("Sorry: need an ideal or a module for input"); } def @save = basering; int @DEBUG = 0; // !system("with", "ndebug"); if( typeof( attrib(SSinit, "DEBUG") ) == "int" ) { @DEBUG = attrib(SSinit, "DEBUG"); } int @SYZCHECK = 0; // @DEBUG; if( typeof( attrib(SSinit, "SYZCHECK") ) == "int" ) { @SYZCHECK = attrib(SSinit, "SYZCHECK"); } int @KERCHECK = 0; // @DEBUG; if( typeof( attrib(SSinit, "KERCHECK") ) == "int" ) { @KERCHECK = attrib(SSinit, "KERCHECK"); } int @IGNORETAILS = 0; if( typeof( attrib(SSinit, "IGNORETAILS") ) == "int" ) { @IGNORETAILS = attrib(SSinit, "IGNORETAILS"); } int @TREEOUTPUT = 0; if( typeof( attrib(SSinit, "TREEOUTPUT") ) == "int" ) { @TREEOUTPUT = attrib(SSinit, "TREEOUTPUT"); } int @RINGCHANGE = 0; if( typeof( attrib(SSinit, "RINGCHANGE") ) == "int" ) { @RINGCHANGE = attrib(SSinit, "RINGCHANGE"); } if( @DEBUG ) { "SSinit::Input"; type(M); attrib(M); } def opts = option(get); option(redSB); option(redTail); M = simplify(interred(groebner(M)), 1 + 2 + 4 + 32); // NOTE: we require interreduced GB for input option(set, opts); kill opts; // int @IS_A_SB = attrib(M, "isSB"); if( !@IS_A_SB ) { } else { } // attrib(M, "isSB", 1); if( @IGNORETAILS ) { M = lead(M); if( @DEBUG ) { "SSinit::Ignorring tails: M: "; type(M); } } def @N = MySort(M); // TODO: replace with inplace sorting!!! def LEAD = lead(@N); if( @KERCHECK ) { def @LEAD = lead(M); // sort wrt neg.deg.rev.lex! intvec iv_ds = sort(@LEAD, "c,ds", 1)[2]; // ,1 => reversed! M = M[iv_ds]; // sort M wrt ds on current leading terms @LEAD = @LEAD[iv_ds]; if( size(module( matrix(@N) - matrix(M) )) > 0 ) { "M:"; M; "@N:"; @N; "module( matrix(@N) - matrix(M) ): "; module( matrix(@N) - matrix(M) ); "ERROR: wrong sorting (in SSnit): @N != M!!!"; Syzextra::m2_end(666); } if( size(module( matrix(@LEAD) - matrix(LEAD) )) > 0 ) { "LEAD:"; LEAD; "@LEAD:"; @LEAD; "module( matrix(@LEAD) - matrix(LEAD) ): "; module( matrix(@LEAD) - matrix(LEAD) ); "ERROR: wrong sorting (in SSnit): @LEAD != LEAD!!!"; Syzextra::m2_end(666); } } M = @N; def TAIL = Syzextra::Tail(M); int @RANK = nrows(M); int @SIZE = ncols(M); intvec @DEGS = deg(M[1..@SIZE]); // store actuall degrees of input elements // TODO: what about real modules? weighted ones? if( @RINGCHANGE ) { list @l = ringlist(@save); int @z = 0; ideal @m = maxideal(1); intvec @wdeg = deg(@m[1..ncols(@m)]); // NOTE: @wdeg will be ignored anyway :( @l[3] = list(list("C", @z), list("lp", @wdeg)); kill @z, @m, @wdeg; // since these vars are ring independent! def S = ring(@l); // -- Syzextra::MakeInducedSchreyerOrdering(1); kill @l; setring S; // ring with an easy divisibility test ("C, lex") // or not!??? if( @DEBUG ) { "SSinit::NewRing(C,lex)?"; basering; Syzextra::DetailedPrint(basering); } } else { def S = basering; } // Setup the leading syzygy^{-1} module to zero: module Z = 0; Z[@RANK] = 0; attrib(Z, "isHomog", intvec(0)); if( !@RINGCHANGE ) { if( defined(RES) ) { if( @DEBUG ){ "WARN: killing existing object: RES!"; }; kill RES; } if( defined(MRES) ) { if( @DEBUG ){ "WARN: killing existing object: MRES!"; }; kill MRES; } if( defined(LRES) ) { if( @DEBUG ){ "WARN: killing existing object: LRES!"; }; kill LRES; } if( defined(TRES) ) { if( @DEBUG ){ "WARN: killing existing object: TRES!"; }; kill TRES; } } module MRES = Z; list RES; RES[1] = Z; list LRES; LRES[1] = Z; list TRES; TRES[1] = Z; if( !defined(M) ) { def M = imap(@save, M); } module F = freemodule(@RANK); intvec @V = deg(F[1..@RANK]); kill F; attrib(M, "isHomog", @V); attrib(M, "isSB", 1); attrib(M, "degrees", @DEGS); if( !defined(LEAD) ) { def LEAD = imap(@save, LEAD); } attrib(LEAD, "isHomog", @V); attrib(LEAD, "isSB", 1); if( !defined(TAIL) ) { def TAIL = imap(@save, TAIL); } if( @DEBUG ) { "SSinit::(sorted) SB_Input: "; type(M); attrib(M); attrib(M, "isHomog"); } if( @SYZCHECK ) { // 0^th syz. property if( size(module(transpose( transpose(M) * transpose(MRES) ))) > 0 ) { transpose( transpose(M) * transpose(MRES) ); "ERROR: transpose( transpose(M) * transpose(MRES) ) != 0!!!"; Syzextra::m2_end(666); } } RES [size(RES)+1] = M; // list of all syzygy modules LRES[size(LRES)+1] = LEAD; // list of all syzygy modules TRES[size(TRES)+1] = TAIL; // list of all syzygy modules MRES = MRES, M; //? attrib(MRES, "isHomog", @V); // attrib(S, "InducionStart", @RANK); if( typeof( attrib(SSinit, "LEAD2SYZ") ) == "int" ) { attrib(S, "LEAD2SYZ", attrib(SSinit, "LEAD2SYZ") ); } else { attrib(S, "LEAD2SYZ", 0); } if( typeof( attrib(SSinit, "TAILREDSYZ") ) == "int" ) { attrib(S, "TAILREDSYZ", attrib(SSinit, "TAILREDSYZ") ); } else { attrib(S, "TAILREDSYZ", 1); } if( typeof( attrib(SSinit, "HYBRIDNF") ) == "int" ) { attrib(S, "HYBRIDNF", attrib(SSinit, "HYBRIDNF") ); } else { attrib(S, "HYBRIDNF", 0); } if( typeof( attrib(SSinit, "NOCACHING") ) == "int" ) { attrib(S, "NOCACHING", attrib(SSinit, "NOCACHING") ); } else { attrib(S, "NOCACHING", 0); } // maybe resetting existing ring attributes! attrib(S, "DEBUG", @DEBUG); attrib(S, "SYZCHECK", @SYZCHECK); attrib(S, "KERCHECK", @KERCHECK); attrib(S, "IGNORETAILS", @IGNORETAILS); attrib(S, "TREEOUTPUT", @TREEOUTPUT); attrib(S, "SYZNUMBER", 0); if( @DEBUG ) { "SSinit::MRES"; MRES; // Syzextra::DetailedPrint(MRES); attrib(MRES, "isHomog"); attrib(S); } export RES; export MRES; export LRES; export TRES; // rtimer, "***TIMESNAP1 for SSinit: on level: [",attrib(basering,"SYZNUMBER"),"] :: t: ", timer, ", r: ", rtimer; return (S); } example { "EXAMPLE:"; echo = 2; ring R = 0, (w, x, y, z), dp; def M = maxideal(1); def S = SSinit(M); setring S; S; "Only the first initialization: "; RES; LRES; TRES; MRES; kill S; setring R; kill M; ideal M = w^2 - x*z, w*x - y*z, x^2 - w*y, x*y - z^2, y^2 - w*z; def S = SSinit(M); setring S; S; "Only the first initialization: "; RES; LRES; TRES; MRES; kill S; setring R; kill M; } LIB "poly.lib"; // for lcm /// Compute L(Syz(L)) static proc SSComputeLeadingSyzygyTerms(def L) { if( typeof( attrib(basering, "DEBUG") ) == "int" ) { int @DEBUG = attrib(basering, "DEBUG"); } else { int @DEBUG = 0; // !system("with", "ndebug"); } if( typeof( attrib(basering, "SYZCHECK") ) == "int" ) { int @SYZCHECK = attrib(basering, "SYZCHECK"); } else { int @SYZCHECK = @DEBUG; } if( typeof( attrib(basering, "KERCHECK") ) == "int" ) { int @KERCHECK = attrib(basering, "KERCHECK"); } else { int @KERCHECK = @DEBUG; } if( @DEBUG ) { "SSComputeLeadingSyzygyTerms::Input: "; L; } module SS = Syzextra::ComputeLeadingSyzygyTerms(L); if( @KERCHECK ) { int i, j, r; int N = ncols(L); def a, b; poly aa, bb; bigint c; ideal M; module S = 0; for(i = 1; i <= N; i++) { a = L[i]; c = Syzextra::leadcomp(a); r = int(c); aa = Syzextra::leadmonomial(a); M = 0; for(j = i-1; j > 0; j--) { b = L[j]; if( Syzextra::leadcomp(b) == c ) { bb = Syzextra::leadmonomial(b); M[j] = (lcm(aa, bb) / aa); } } // TODO: add quotient relations here... M = simplify(M, 1 + 2 + 32); M = MySort(M); S = S, M * gen(i); } S = MySort(simplify(S, 2)); if( (size(S) + size(SS)) > 0 ) { if( size(module(matrix(S) - matrix(SS))) > 0 ) { "ERROR: SSComputeLeadingSyzygyTerms: S != SS "; "basering: "; basering; // Syzextra::DetailedPrint(basering); "S: "; S; // Syzextra::DetailedPrint(_, 1); "SS: "; SS; // Syzextra::DetailedPrint(_, 1); "DIFF: "; module(matrix(S) - matrix(SS)); // Syzextra::DetailedPrint(_, 2); print(matrix(S) - matrix(SS)); Syzextra::m2_end(666); } } } if( @DEBUG ) { "SSComputeLeadingSyzygyTerms::Output: "; "SS: "; SS; } if( size(SS) > 0 ) { attrib(SS, "isSB", 1); } return (SS); } /// Compute Syz(L), where L is a monomial (leading) module static proc SSCompute2LeadingSyzygyTerms(def L) { if( typeof( attrib(basering, "DEBUG") ) == "int" ) { int @DEBUG = attrib(basering, "DEBUG"); } else { int @DEBUG = 0; // !system("with", "ndebug"); } if( typeof( attrib(basering, "SYZCHECK") ) == "int" ) { int @SYZCHECK = attrib(basering, "SYZCHECK"); } else { int @SYZCHECK = @DEBUG; } if( typeof( attrib(basering, "KERCHECK") ) == "int" ) { int @KERCHECK = attrib(basering, "KERCHECK"); } else { int @KERCHECK = @DEBUG; } if( @DEBUG ) { "SSCompute2LeadingSyzygyTerms::Input: "; L; } module SS = Syzextra::Compute2LeadingSyzygyTerms(L); if( @DEBUG ) { "SSCompute2LeadingSyzygyTerms::Syz(SS): "; SS; } if( @SYZCHECK ) { if( size(SS) > 0 and size(L) > 0 ) { if( size(module(transpose( transpose(SS) * transpose(L) ))) > 0 ) { transpose( transpose(SS) * transpose(L) ); "ERROR: transpose( transpose(SS) * transpose(L) ) != 0!!!"; Syzextra::m2_end(666); } } } if( @KERCHECK ) { int @TAILREDSYZ = 1; if( typeof( attrib(basering, "TAILREDSYZ") ) == "int" ) { @TAILREDSYZ = attrib(basering, "TAILREDSYZ"); } int i, j, r; int N = ncols(L); def a, b; poly aa, bb, @lcm; bigint c; module M; module S = 0; for(i = 1; i <= N; i++) { a = L[i]; // "a: ", a; c = Syzextra::leadcomp(a); r = int(c); aa = Syzextra::leadmonomial(a); M = 0; for(j = i-1; j > 0; j--) { b = L[j]; // "b: ", b; if( Syzextra::leadcomp(b) == c ) { bb = Syzextra::leadmonomial(b); @lcm = lcm(aa, bb); M[j] = (@lcm / aa)* gen(i) - (@lcm / bb)* gen(j); } } M = simplify(M, 2); // TODO: add quotient relations here... S = S, M; } if( @TAILREDSYZ ) { // Make sure that 2nd syzygy terms are not reducible by 1st def opts = option(get); option(redSB); option(redTail); S = std(S); // binomial module option(set, opts); // kill opts; } else { S = simplify(S, 2 + 32); } S = MySort(S); if( @DEBUG ) { "SSCompute2LeadingSyzygyTerms::Syz(S): "; S; } if( @SYZCHECK ) { if( size(S) > 0 and size(L) > 0 ) { if( size(module(transpose( transpose(S) * transpose(L) ))) > 0 ) { transpose( transpose(S) * transpose(L) ); "ERROR: transpose( transpose(S) * transpose(L) ) != 0!!!"; Syzextra::m2_end(666); } } } if(size(S) != size(SS)) { "ERROR: SSCompute2LeadingSyzygyTerms: size(S) != size(SS)"; "basering: "; basering; // Syzextra::DetailedPrint(basering); "S: "; S; // Syzextra::DetailedPrint(S, 2); "SS: "; SS; // Syzextra::DetailedPrint(SS, 2); Syzextra::m2_end(666); } if(size(S) > 0 && size(SS) > 0) { if( size(module(matrix(lead(S)) - matrix(lead(SS)))) > 0 ) { "ERROR: SSCompute2LeadingSyzygyTerms: lead(S) != lead(SS) "; "basering: "; basering; // Syzextra::DetailedPrint(basering); "lead(S ): "; lead(S ); // Syzextra::DetailedPrint(_, 2); "lead(SS): "; lead(SS); // Syzextra::DetailedPrint(_, 2); "DIFF: "; print( matrix(lead(S)) - matrix(lead(SS)) ); module(matrix(lead(S)) - matrix(lead(SS))); // Syzextra::DetailedPrint(_ , 4); Syzextra::m2_end(666); } if( @TAILREDSYZ ) { if( size(module(matrix( Syzextra::Tail(S)) - matrix( Syzextra::Tail(SS)))) > 0 ) { "ERROR: SSCompute2LeadingSyzygyTerms: Tail(S) != Tail(SS) "; "basering: "; basering; // Syzextra::DetailedPrint(basering); "Tail(S ): "; Syzextra::Tail(S ); // Syzextra::DetailedPrint(_, 2); "Tail(SS): "; Syzextra::Tail(SS); // Syzextra::DetailedPrint(_, 2); "DIFF: "; module( matrix( Syzextra::Tail(S)) - matrix( Syzextra::Tail(SS)) ); // Syzextra::DetailedPrint(_, 4); print( matrix( Syzextra::Tail(S)) - matrix( Syzextra::Tail(SS)) ); Syzextra::m2_end(666); } } } } module S2 = Syzextra::Tail(SS); SS = lead(SS); // (C,lp) on base ring! if( @SYZCHECK ) { if( ncols(SS) != ncols(S2) ) // || size(SS) != ncols(SS) || size(S2) != ncols(S2) { "ERROR: SSCompute2LeadingSyzygyTerms: inappropriate S2 / SS: "; type(SS); type(S2); L; Syzextra::m2_end(666); } } if( @DEBUG ) { "SSCompute2LeadingSyzygyTerms::Output: "; SS; S2; } attrib(SS, "isSB", 1); return (SS, S2); } // -------------------------------------------------------- // /// TODO: save shortcut (syz: |-.->) LM(LM(m) * "t") -> syz? static proc SSFindReducer(def product, def syzterm, def L, list #) { if( typeof( attrib(basering, "DEBUG") ) == "int" ) { int @DEBUG = attrib(basering, "DEBUG"); } else { int @DEBUG = 0; // !system("with", "ndebug"); } if( typeof( attrib(basering, "SYZCHECK") ) == "int" ) { int @SYZCHECK = attrib(basering, "SYZCHECK"); } else { int @SYZCHECK = @DEBUG; } if( typeof( attrib(basering, "KERCHECK") ) == "int" ) { int @KERCHECK = attrib(basering, "KERCHECK"); } else { int @KERCHECK = @DEBUG; } if( @DEBUG ) { "SSFindReducer::Input: "; "syzterm: ", syzterm; "product: ", product; // "L: ", L; // "T: ", T; if( size(#) > 0 ) { // "LSyz: ", #; } } if( @DEBUG && (syzterm != 0) ) { def @@c = Syzextra::leadcomp(syzterm); int @@r = int(@@c); def @@product = Syzextra::leadmonomial(syzterm) * L[@@r]; if( @@product != product) { "product: ", product, ", @@product: ", @@product; "ERROR: 'syzterm' results in wrong product !!!???"; Syzextra::m2_end(666); } } if( typeof(#[1]) == "module" ) { vector my = Syzextra::FindReducer(product, syzterm, L/*, T*/, #[1]); } else { vector my = Syzextra::FindReducer(product, syzterm, L/*, T*/); } if( @KERCHECK ) { bigint c = Syzextra::leadcomp(product); int r = int(c); def a, b, bb; vector nf = [0]; // looking for an appropriate diviser for( int k = ncols(L); k > 0; k-- ) { a = L[k]; // with the same mod. component if( Syzextra::leadcomp(a) == c ) { b = - ( Syzextra::leadmonomial(product) / Syzextra::leadmonomial(L[k])); // which divides the product: looking for the 1st appropriate one! if( b != 0 ) { bb = b * gen(k); if (size(bb + syzterm) == 0) // cannot allow something like: a*gen(i) - a*gen(i) { nf = [0]; } else { nf = bb; } // new syz. term should not be in if( size(#) > 0 ) { if( typeof(#[1]) == "module" ) { nf = NF(bb, #[1]); } } // while the complement (the fraction) is not reducible by leading syzygies if( nf != 0 ) // nf must be == bb!!! { /// TODO: save shortcut LM(m) * T[i] -> ? // choose ANY such reduction... (with the biggest index?) break; } } } } if( my != nf ) { "ERROR in Syzextra::FindReducer => ", my, " != nf: ", nf; Syzextra::m2_end(666); } } if( @DEBUG ) { "SSFindReducer::Output: ", my; } return (my); } /// TODO: save shortcut (syz: |-.->) LM(m) * "t" -> ? static proc SSReduceTerm(poly m, def t, def syzterm, def L, def T, list #) { if( typeof( attrib(basering, "DEBUG") ) == "int" ) { int @DEBUG = attrib(basering, "DEBUG"); } else { int @DEBUG = 0; // !system("with", "ndebug"); } if( @DEBUG ) { "SSReduce::Input: "; "syzterm: ", syzterm; "mult: ", m; "term: ", t; // "L: ", L; // "T: ", T; if( size(#) > 0 ) { // "LSyz: ", #; } // "attrib(LS, 'isSB')", attrib(LS, "isSB"); } if( typeof( attrib(basering, "KERCHECK") ) == "int" ) { int @KERCHECK = attrib(basering, "KERCHECK"); } else { int @KERCHECK = @DEBUG; } if( typeof( attrib(basering, "SYZCHECK") ) == "int" ) { int @SYZCHECK = attrib(basering, "SYZCHECK"); } else { int @SYZCHECK = @DEBUG; } if( @SYZCHECK && (syzterm != 0) ) { def @@c = Syzextra::leadcomp(syzterm); int @@r = int(@@c); poly @@m = Syzextra::leadmonomial(syzterm); def @@t = L[@@r]; if( (@@m != m) || (@@t != t)) { "m: ", m, ", t: ", t; "@@m: ", @@m, ", @@t: ", @@t; "ERROR: 'syzterm' results in wrong m * t !!!"; Syzextra::m2_end(666); } } if( typeof(#[1]) == "module" ) { vector ss = Syzextra::ReduceTerm(m, t, syzterm, L, T, #[1]); } else { vector ss = Syzextra::ReduceTerm(m, t, syzterm, L, T); } if( @KERCHECK ) { int @TREEOUTPUT = attrib(basering, "TREEOUTPUT"); vector s = 0; if( size(t) > 0 ) { def product = m * t; s = SSFindReducer(product, syzterm, L, #); if( size(s) != 0 ) { poly @b = Syzextra::leadmonomial(s); def @c = Syzextra::leadcomp(s); int k = int(@c); if( @TREEOUTPUT ){ "\CHILD{", (s), "}{", ( @b*L[k]), "}"; } s = s + SSTraverseTail(@b, T[k], L, T, #); // !!! } } if( s != ss ) { "ERROR in Syzextra::ReduceTerm => old: ", s, " != ker: ", ss; "m: ", m; "t: ", t; "syzterm: ", syzterm; L; T; #; Syzextra::m2_end(666); } } if( @DEBUG ) { "SSReduceTerm::Output: ", ss; } return (ss); } // TODO: store m * @tail -.-^-.-^-.--> ? static proc SSTraverseTail(poly m, def @tail, def L, def T, list #) { if( typeof( attrib(basering, "DEBUG") ) == "int" ) { int @DEBUG = attrib(basering, "DEBUG"); } else { int @DEBUG = 0; // !system("with", "ndebug"); } if( typeof( attrib(basering, "KERCHECK") ) == "int" ) { int @KERCHECK = attrib(basering, "KERCHECK"); } else { int @KERCHECK = @DEBUG; } if( @DEBUG ) { "SSTraverse::Input: "; "mult: ", m; "tail: ", @tail; // T[i]; if( size(#) > 0 ) { // "LSyz: "; #[1]; } } if( typeof(#[1]) == "module" ) { vector ss = Syzextra::TraverseTail(m, @tail, L, T, #[1]); } else { vector ss = Syzextra::TraverseTail(m, @tail, L, T); } if( @KERCHECK ) { vector s = 0; def @l, @p; @p = @tail; // iterate tail-terms in ANY order! while( size(@p) > 0 ) { @l = lead(@p); s = s + SSReduceTerm(m, @l, [0], L, T, #); // :( @p = @p - @l; } if( s != ss ) { "ERROR in Syzextra::TraverseTail => old: ", s, " != ker: ", ss; "m: ", m; "@tail: ", @tail; L; T; #; Syzextra::m2_end(666); } } if( @DEBUG ) { "SSTraverseTail::Output: ", ss; } return (ss); } // -------------------------------------------------------- // static proc SSSchreyerSyzygyNF(vector syz_lead, vector syz_2, def L, def T, list #) " Hybrid Syzygy computation: 'reduce' spoly by eliminating _any_ terms while discurding terms of lower order! Return the tail syzygy (without: syz_lead, starting with: syz_2)" { if( typeof( attrib(basering, "DEBUG") ) == "int" ) { int @DEBUG = attrib(basering, "DEBUG"); } else { int @DEBUG = 0; // !system("with", "ndebug"); } if( @DEBUG ) { "SSSchreyerSyzygyNF::Input: "; "syzygy_lead: ", syz_lead; "syzygy 2nd : ", syz_2; // L; T; if( size(#) > 0 ) { // "LSyz: "; #[1]; } } if( typeof( attrib(basering, "KERCHECK") ) == "int" ) { int @KERCHECK = attrib(basering, "KERCHECK"); } else { int @KERCHECK = @DEBUG; } if( typeof(#[1]) == "module" ) { def my = Syzextra::SchreyerSyzygyNF(syz_lead, syz_2, L, T, #[1]); } else { def my = Syzextra::SchreyerSyzygyNF(syz_lead, syz_2, L, T); } if( @KERCHECK ) { int @TREEOUTPUT = attrib(basering, "TREEOUTPUT"); def spoly = Syzextra::leadmonomial(syz_lead) * T[int( Syzextra::leadcomp(syz_lead))] + Syzextra::leadmonomial(syz_2) * T[int( Syzextra::leadcomp(syz_2))]; vector @tail = syz_2; poly @b; int k; while (size(spoly) > 0) { syz_2 = SSFindReducer(lead(spoly), 0, L, #); spoly = Syzextra::Tail(spoly); if( size(syz_2) != 0) { @b = Syzextra::leadmonomial(syz_2); k = int( Syzextra::leadcomp(syz_2)); if( @TREEOUTPUT ){ "\CHILD{", (syz_2), "}{", ( lead(spoly)), "}"; } spoly = spoly + @b * T[k]; @tail = @tail + syz_2; } } if( my != @tail ) { "ERROR in Syzextra::SchreyerSyzygyNF => old: ", @tail, " != ker: ", my; "syzygy_lead: ", syz_lead; "syzygy 2nd : ", syz_2; L; T; #; Syzextra::m2_end(666); } } if( @DEBUG ) { "SSSchreyerSyzygyNF::Output: ", my; } return (my); } // -------------------------------------------------------- // // module (N, LL, TT) = SSComputeSyzygy(L, T); // Compute Syz(L ++ T) = N = LL ++ TT static proc SSComputeSyzygy(def L, def T) { // rtimer, "***TIMESNAP0 for Syzextra::ComputeSyzygy(L,T): on level: [",attrib(basering,"SYZNUMBER"),"] :: t: ", timer, ", r: ", rtimer; int @DEBUG = attrib(basering, "DEBUG"); int @KERCHECK = attrib(basering, "KERCHECK"); int @SYZCHECK = attrib(basering, "SYZCHECK"); if( @DEBUG ) { "SSComputeSyzygy::Input"; "basering: ", basering; attrib(basering); // Syzextra::DetailedPrint(basering); // "iCompShift: ", iCompShift; "L: "; L; "T: "; T; } // option(prot); // rtimer, "***TIME for Syzextra::ComputeSyzygy(L,T): on level: [",attrib(basering,"SYZNUMBER"),"] :: t: ", timer, ", r: ", rtimer; list @res= Syzextra::ComputeSyzygy(L,T); // rtimer, "***TIME for Syzextra::ComputeSyzygy(L,T): on level: [",attrib(basering,"SYZNUMBER"),"] :: t: ", timer, ", r: ", rtimer; // option(noprot); // TODO: restore! module @LL = @res[1]; module @TT = @res[2]; if( @KERCHECK ) { int @SYZCHECK = attrib(basering, "SYZCHECK"); int @LEAD2SYZ = attrib(basering, "LEAD2SYZ"); int @TAILREDSYZ = attrib(basering, "TAILREDSYZ"); int @HYBRIDNF = attrib(basering, "HYBRIDNF"); int @IGNORETAILS = attrib(basering, "IGNORETAILS"); int @TREEOUTPUT = attrib(basering, "TREEOUTPUT"); int @SYZNUMBER = attrib(basering,"SYZNUMBER"); if( @HYBRIDNF == 2 ) { if( @SYZNUMBER < 3 ){ @HYBRIDNF = 1; } else { @HYBRIDNF = 0; } } module LL; /// Get the critical leading syzygy terms if( @LEAD2SYZ ) // & 2nd syz. term { module LL2; (LL, LL2) = SSCompute2LeadingSyzygyTerms(L); } else { LL = SSComputeLeadingSyzygyTerms(L); } if( ncols(LL) != ncols(@LL) ) { "ERROR in SSComputeSyzygy: wrong leading syzygies!?"; ""; L; T; ""; type(LL); type(@LL); Syzextra::m2_end(666); } if( size( module( matrix(LL) - matrix(@LL) ) ) != 0 ) { "ERROR in SSComputeSyzygy: wrong leading syzygies!?"; ""; L; T; ""; type(LL); type(@LL); Syzextra::m2_end(666); } module TT, SYZ; vector a, a2; bigint c; int r; poly aa; if( size(LL) > 0 ) { list LS; if( @TAILREDSYZ) { LS = list(LL); } vector @tail = 0; // for(int k = 1; k <= ncols(LL); k++ ) for(int k = ncols(LL); k > 0; k-- ) { // leading syz. term: a = LL[k]; if( !@IGNORETAILS ) { c = Syzextra::leadcomp(a); r = int(c); aa = Syzextra::leadmonomial(a); if( @TREEOUTPUT ){ "\ROOT{", (lead(a)), "}"; } // NF reduction: if( @HYBRIDNF == 0 ) // Traverse approach: { @tail = SSTraverseTail(aa, T[r], L, T, LS); // get the 2nd syzygy term... if( @LEAD2SYZ ) // with the 2nd syz. term: { a2 = LL2[k]; c = Syzextra::leadcomp(a2); r = int(c); aa = Syzextra::leadmonomial(a2); if( @TREEOUTPUT ){ "\CHILD{", (lead(a2)), "}{", ( aa*L[r]), "}"; } @tail = a2 + @tail + SSTraverseTail(aa, T[r], L, T, LS); } else { @tail = @tail + SSReduceTerm(aa, L[r], a, L, T, LS); } } else // Hybrid approach: { // get the 2nd syzygy term... if( @LEAD2SYZ ) { a2 = LL2[k]; } else { a2 = SSFindReducer( aa * L[r], a, L, LS); } if ( (@SYZCHECK || @DEBUG) ) { if( size(a2) == 0 ) // if syzterm == 0!!!! { "ERROR in SSComputeSyzygy: could not find the 2nd syzygy term during the hybrid NF!!!"; Syzextra::m2_end(666); } } if( @TREEOUTPUT ){ "\CHILD{", (a2), "}{", ( aa*L[r]), "}"; } @tail = SSSchreyerSyzygyNF(a, a2, L, T, LS); } } // else @tail remains zero! TT[k] = @tail; SYZ[k] = a + @tail; if ( TT[k] != @TT[k] ) { "ERROR in SSComputeSyzygy: wrong tail syzygy!?"; "INPUT"; L; T; "LEADING SYZYGY TERMS"; type(LL); "CURRENT TAILS"; type(TT); type(@TT); "WRONG TAIL [", k, "]:"; type(TT[k]); type(@TT[k]); // "IMAGES:"; // transpose( transpose(N) * transpose(MRES) ); Syzextra::m2_end(666); } } // FOR } if( ncols(TT) != ncols(@TT) ) { "ERROR in SSComputeSyzygy: wrong tail syzygies!?"; ""; L; T; ""; type(LL); type(@LL); ""; type(TT); type(@TT); Syzextra::m2_end(666); } if( size( module( matrix(TT) - matrix(@TT) ) ) != 0 ) { "ERROR in SSComputeSyzygy: wrong tail syzygies!?"; ""; TT; @TT; ""; L; T; ""; type(LL); type(@LL); Syzextra::m2_end(666); } } module @SYZ; for(int @k = ncols(@LL); @k > 0; @k-- ) { @SYZ[@k] = @LL[@k] + @TT[@k]; } if( @DEBUG ) { "SSComputeSyzygy::Output"; // "SYZ: "; @SYZ; "LL: "; @LL; "TT: "; @TT; } // rtimer, "***TIMESNAP1 for Syzextra::ComputeSyzygy(L,T): on level: [",attrib(basering,"SYZNUMBER"),"] :: t: ", timer, ", r: ", rtimer; return (@SYZ, @LL, @TT); } // resolution/syzygy step: static proc SSstep() { // rtimer, "***TIMESNAP0 for SSstep(): on level: [",attrib(basering,"SYZNUMBER"),"] :: t: ", timer, ", r: ", rtimer; int @DEBUG = attrib(basering, "DEBUG"); int @SYZCHECK = attrib(basering, "SYZCHECK"); if( @DEBUG ) { "SSstep::NextInducedRing"; "basering: ", basering; attrib(basering); } /* // is initial weights are all zeroes! def L = lead(M); intvec @V = deg(M[1..ncols(M)]); @W; @V; @W = @V; attrib(L, "isHomog", @W); Syzextra::SetInducedReferrence(L, @RANK, 0); */ // def L = lead(MRES); // @W = @W, @V; // attrib(L, "isHomog", @W); // General setting: // Syzextra::SetInducedReferrence(MRES, 0, 0); // limit: 0! int @l = size(RES); def M = RES[@l]; def L = LRES[@l]; def T = TRES[@l]; //// TODO: wrong !!!!! int @RANK = ncols(MRES) - ncols(M); // nrows(M); // what if M is zero?! /* if( @RANK != nrows(M) ) { type(MRES); @RANK; type(M); pause(); } */ intvec @W = attrib(M, "isHomog"); intvec @V = attrib(M, "degrees"); @V = @W, @V; if( @DEBUG ) { "Sstep::NextInput: "; M; L; @V; @RANK; // Syzextra::DetailedPrint(MRES); attrib(MRES, "isHomog"); } // TODO: N = SYZ( M )!!! module N, LL, TT; (N, LL, TT) = SSComputeSyzygy(/*M, */L, T/*, @RANK*/); // shift syz.comp by @RANK: module Z; Z = 0; Z[@RANK] = 0; Z = Z, transpose(LL); LL = transpose(Z); Z = 0; Z[@RANK] = 0; Z = Z, transpose(TT); TT = transpose(Z); Z = 0; Z[@RANK] = 0; Z = Z, transpose(N); N = transpose(Z); if( @SYZCHECK ) { if( size(N) > 0 ) { // next syz. property if( size(module(transpose( transpose(N) * transpose(MRES) ))) > 0 ) { "MRES", MRES; "N: "; N; // Syzextra::DetailedPrint(N, 2); "LL:"; LL; // Syzextra::DetailedPrint(LL, 1); "TT:"; TT; // Syzextra::DetailedPrint(TT, 10); "RANKS: ", @RANK; "transpose( transpose(N) * transpose(MRES) ) != 0!!!"; transpose( transpose(N) * transpose(MRES) ); "transpose(N) * transpose(MRES): "; transpose(N) * transpose(MRES); // Syzextra::DetailedPrint(module(_), 2); Syzextra::m2_end(666); } } } attrib(N, "isHomog", @V); // TODO: correct the following: intvec @DEGS = deg(N[1..ncols(N)]); // no mod. comp. weights :( attrib(N, "degrees", @DEGS); RES[@l + 1] = N; // list of all syzygy modules LRES[@l + 1] = LL; // list of all syzygy modules TRES[@l + 1] = TT; // list of all syzygy modules MRES = MRES, N; attrib(MRES, "isHomog", @V); // L = L, lead(N); attrib(basering, "InducionLeads", L); if( @DEBUG ) { "SSstep::NextSyzOutput: "; N; // Syzextra::DetailedPrint(N); attrib(N); } int ss = attrib(basering, "SYZNUMBER"); attrib(basering, "SYZNUMBER", ss + 1 ); // rtimer, "***TIMESNAP1 for SSstep(): on level: [",attrib(basering,"SYZNUMBER"),"] :: t: ", timer, ", r: ", rtimer; } static proc SScontinue(int l) "USAGE: SScontinue(l) RETURN: nothing, instead it changes RES and MRES variables in the current ring PURPOSE: computes further (at most l) syzygies NOTE: must be used within a ring returned by Sres or Ssyz. RES and MRES are explained in Sres EXAMPLE: example Scontinue; shows an example " { // rtimer, "***TIMESNAP0 for SScontinue: on level: [",attrib(basering,"SYZNUMBER"),"] :: t: ", timer, ", r: ", rtimer; /// TODO! // def data = Syzextra::GetInducedData(); if( (!defined(RES)) || (!defined(MRES)) ) /* || (typeof(data) != "list") || (size(data) != 2) */ { ERROR("Sorry, but basering does not seem to be returned by Sres or Ssyz"); } for (; (l != 0) && (size(RES[size(RES)]) > 0); l-- ) { SSstep(); } // rtimer, "***TIMESNAP1 for SScontinue: on level: [",attrib(basering,"SYZNUMBER"),"] :: t: ", timer, ", r: ", rtimer; } example { "EXAMPLE:"; echo = 2; ring r; module M = maxideal(1); M; def S = SSsyz(M); setring S; S; "Only the first syzygy: "; RES; MRES; "More syzygies: "; SScontinue(10); RES; MRES; } static proc SSsyz(def M) "USAGE: SSsyz(M) RETURN: ring, containing a list of modules RES and a module MRES PURPOSE: computes the first syzygy module of M (wrt some Schreyer ordering)? NOTE: The output is explained in Sres EXAMPLE: example Ssyz; shows an example " { if( (typeof(M) != "module") && (typeof(M) != "ideal") ) { ERROR("Sorry: need an ideal or a module for input"); } def SS = SSinit(M); setring SS; SSstep(); // NOTE: what if M is zero? return (SS); } example { "EXAMPLE:"; echo = 2; ring r; /* ideal M = 0; def S = SSsyz(M); setring S; S; "Only the first syzygy: "; RES; LRES; TRES; MRES; kill S; setring r; kill M; */ ideal M = maxideal(1); M; def S = SSres(M, 0); setring S; S; MRES; print(_); RES; kill S; setring r; kill M; kill r; ring R = 0, (w, x, y, z), dp; ideal M = w^2 - x*z, w*x - y*z, x^2 - w*y, x*y - z^2, y^2 - w*z; def S = SSres(M, 0); setring S; S; ""; LRES; ""; TRES; ""; MRES; print(_); RES; } static proc SSres(def M, int l) "USAGE: SSres(I, l) RETURN: ring, containing a list of modules RES and a module MRES PURPOSE: computes (at most l) syzygy modules of M wrt the classical Schreyer induced ordering with gen(i) > gen(j) if i > j, provided both gens are from the same syzygy level.??? NOTE: RES contains the images of maps subsituting the beginning of the Schreyer free resolution of baseRing^r/M, while MRES is a sum of these images in a big free sum, containing all the syzygy modules. The syzygy modules are shifted so that gen(i) correspons to MRES[i]. The leading zero module RES[0] indicates the fact that coker of the first map is zero. The number of zeroes inducates the rank of input. NOTE: If l == 0 then l is set to be nvars(basering) + 1 EXAMPLE: example SSres; shows an example " { if( (typeof(M) != "module") && (typeof(M) != "ideal") ) { ERROR("Sorry: need an ideal or a module for input"); } /* "KERCHECK: ", attrib(SSinit, "KERCHECK"); "SYZCHECK: ", attrib(SSinit, "SYZCHECK"); "DEBUG: ", attrib(SSinit, "DEBUG"); "HYBRIDNF: ", attrib(SSinit, "HYBRIDNF"); "TAILREDSYZ: ", attrib(SSinit, "TAILREDSYZ"); "LEAD2SYZ: ", attrib(SSinit, "LEAD2SYZ"); */ def SS = SSinit(M); setring SS; /* "KERCHECK: ", attrib(SS, "KERCHECK"); "SYZCHECK: ", attrib(SS, "SYZCHECK"); "DEBUG: ", attrib(SS, "DEBUG"); "HYBRIDNF: ", attrib(SS, "HYBRIDNF"); "TAILREDSYZ: ", attrib(SS, "TAILREDSYZ"); "LEAD2SYZ: ", attrib(SS, "LEAD2SYZ"); ""; "IGNORETAILS: ", attrib(SS, "IGNORETAILS"); "SYZNUMBER: ", attrib(SS, "SYZNUMBER"); */ if (l == 0) { l = nvars(basering) + 2; // not really an estimate...?! } SSstep(); l = l - 1; SScontinue(l); /* "KERCHECK: ", attrib(SS, "KERCHECK"); "SYZCHECK: ", attrib(SS, "SYZCHECK"); "DEBUG: ", attrib(SS, "DEBUG"); "HYBRIDNF: ", attrib(SS, "HYBRIDNF"); "TAILREDSYZ: ", attrib(SS, "TAILREDSYZ"); "LEAD2SYZ: ", attrib(SS, "LEAD2SYZ"); ""; "IGNORETAILS: ", attrib(SS, "IGNORETAILS"); "SYZNUMBER: ", attrib(SS, "SYZNUMBER"); */ return (SS); } example { "EXAMPLE:"; echo = 2; ring r; module M = maxideal(1); M; def S = SSres(M, 0); setring S; S; RES; MRES; } static proc SRES_betti2(SRES SR, def a) { def R = SR.r; setring R; return ( betti(SR.rsltn, a) ); } static proc SRES_betti1(SRES SR) { def R = SR.r; setring R; return ( betti(SR.rsltn) ); } static proc SRES_print(SRES SR) { def R = SR.r; setring R; "Schreyer resolution: "; SR.rsltn; // print (); "over the ring: "; R; } static proc SRES_minres(SRES SR) { def save = basering; SRES S; def R = SR.r; S.r = R; setring R; S.rsltn = minres(SR.rsltn); // in target ring :( return (S); } // cannot be automatically used via overloading :( static proc SRES_list(def SR) "USAGE: SRES_list(resolution) RETURN: list PURPOSE: convert given resolution to a list NOTE: result is over basering SEE ALSO: s_res, resolution EXAMPLE: example s_res; shows an example " { if( typeof(SR) != "SRES" ) { list @@@L = SR; return (@@@L); } def save = basering; def R = SR.r; // if( 0 ) // ( save == R ) // TODO: not implemented :((( // { list L = SR.rsltn; return (L); } setring R; list @@@L = SR.rsltn; setring save; return (imap( R, @@@L )); } static proc mod_init() { load("syzextra.so"); if( 1 ) // !defined(Syzextra) ) { // TODO: SSres - return SRESOLUTION? newstruct("SRES","ring r,resolution rsltn"); // http://www.singular.uni-kl.de/Manual/latest/sing_179.htm#SEC218 system("install","SRES","print",SRES_print, 1); system("install","SRES","betti",SRES_betti1, 1); // http://www.singular.uni-kl.de/Manual/latest/sing_260.htm#SEC299 system("install","SRES","betti",SRES_betti2, 2); // http://www.singular.uni-kl.de/Manual/latest/sing_260.htm#SEC299 system("install","SRES","minres",SRES_minres, 1); // http://www.singular.uni-kl.de/Manual/latest/sing_344.htm#SEC383 // system("install","SRES","list", SRES_list, 1); // will never work :((( // system("install","SRES","string",SRES_string, 1); } } static proc testallSexamples() { example Ssyz; example Scontinue; example Sres; } static proc testallSSexamples() { example SSsyz; example SScontinue; example SSres; } example { "EXAMPLE:"; echo = 2; testallSexamples(); testallSSexamples(); } static proc StartResTesting(list #) { int @treeout = attrib(SSinit, "TREEOUTPUT"); if( defined(@save_res_list) ) { ERROR("Sorry: existing global variable @save_res_list - run StopAddResTesting before another Start!!!"); } string @save_res_desc = string(#); if( !@treeout ) { ">>>>>>>>> {{{{{{{{{ STARTING TESTING ('" + @save_res_desc + "') :::::::::::: "; } else { "{ \"Example\": \"" + @save_res_desc + "\", \"computations\": ["; } list @save_res_list = list(); export @save_res_list; export @save_res_desc; } static proc StopResTesting() { int @treeout = attrib(SSinit, "TREEOUTPUT"); if( defined(@save_opts) || defined(@save_method) || defined(@save_desc) ) { ERROR("Sorry: existing global variables - run StopAddResTest before another Start!!!"); } if( !defined(@save_res_list) || !defined(@save_res_desc) ) { ERROR("Sorry: no global variable - run StartResTesting beforehand!!!"); } int i, j; int f = 0; def m, mm; if( !@treeout ) { for (i = size(@save_res_list); i > 0; i--) { "Total Time: ", @save_res_list[i][5], ", Res: ", @save_res_list[i][6], ", Minimal Betti: ", @save_res_list[i][5] - @save_res_list[i][6], ", ", @save_res_list[i][1], " :with: ", @save_res_list[i][2]; } } for (i = size(@save_res_list); i > 1; i--) { m = @save_res_list[i][4]; for (j = i-1; j > 0; j--) { mm = @save_res_list[j][4]; if( (nrows(m) != nrows(mm)) || (ncols(m) != ncols(mm)) ) { "ERROR: SIZE(Betti[j: ", j, "]) != SIZE(Betti[i: ", i, "]):"; "j: ", j; print( @save_res_list[j][4], "betti"); print(@save_res_list[j]); "i: ", i; print( @save_res_list[i][4], "betti"); print(@save_res_list[i]); f = 1; } else { if( m != mm ) { "ERROR: Betti[j: ", j, "] != Betti[i: ", i, "]:"; "j: ", j; print( @save_res_list[j][4], "betti"); print(@save_res_list[j]); "i: ", i; print( @save_res_list[i][4], "betti"); print(@save_res_list[i]); f = 1; }; }; }; }; if( f ) { print(@save_res_list); "<<<<<<<<< }}}}}}}}} STOP TESTING (", @save_res_desc, ") !!!!!!!!!!!! "; "ERROR: There were some wrong betti numbers... "; // Syzextra::m2_end(666); } else { if( !@treeout ) { "BETTI: "; print( @save_res_list[1][4], "betti"); } } kill @save_res_list; if( !@treeout ) { "<<<<<<<<< }}}}}}}}} STOP TESTING (", @save_res_desc, ") !!!!!!!!!!!! "; } else { // "{ \"Example\": \"" + @save_res_desc + "\", \"computations\": ["; "] },"; } kill @save_res_desc; } static proc StartAddResTest(string method, string desc) { int @treeout = attrib(SSinit, "TREEOUTPUT"); if( !defined(@save_res_list) ) { ERROR("Sorry: no global variable - run StartResTesting beforehand!!!"); } if( defined(@save_opts) || defined(@save_method) || defined(@save_desc) ) { ERROR("Sorry: existing global variables - run StopAddResTest before another Start!!!"); } def @save_opts = option(get); export @save_opts; def @save_method = method; export @save_method; def @save_desc = desc; export @save_desc; if( !@treeout ) { "< START RES TEST{{{ ", @save_method, ", with:", @save_desc, " ... "; } else { // Print("{ \"RESOLUTION: HYBRIDNF:%d, TAILREDSYZ: %d, LEAD2SYZ: %d, IGNORETAILS: %d\": [\n", // attributes.__HYBRIDNF__, attributes.__TAILREDSYZ__, attributes.__LEAD2SYZ__, attributes.__IGNORETAILS__); " { \"RESOLUTION: " + @save_method + ", with: " + @save_desc + "\": ["; } } static proc StopAddResTest(def RR, intmat S, int @t, int @m) { int @treeout = attrib(SSinit, "TREEOUTPUT"); if( !(defined(@save_opts) && defined(@save_method) && defined(@save_desc)) ) { ERROR("Sorry: no global variables - run StartAddResTest beforehand!!!"); } list @l = list(@save_method, @save_desc, option(get), S, @t, @m); // RR, // print(S, "betti"); if( !@treeout ) { "> -STOP RES TEST}}} ", @save_method, ", with:", @save_desc, ", Timer:", @t; option(); } else { " ] },"; } option(set, @save_opts); kill @save_opts; kill @save_method; kill @save_desc; @save_res_list[1 + size(@save_res_list)] = @l; } static proc SCheck(def S) { setring S; // for checking... module M = MRES; if( ncols(M) < nrows(M) ) { M[nrows(M)] = 0; } else { M = transpose(M); if( ncols(M) < nrows(M) ) { M[nrows(M)] = 0; } M = transpose(M); } if( nrows(M) != ncols(M) ) { "ERROR: non-square M!!!"; Syzextra::m2_end(666); } if( size(module( M*M )) > 0 ) { "ERROR: module( M*M ) != 0!!!"; module( M*M ); "MRES': "; M; print(M); Syzextra::m2_end(666); } // "MRES': "; M; print(M); if( size(RES[1]) != 0 ) { "ERROR: wrong starting zero module!!!"; Syzextra::m2_end(666); } // RES; /* MRES; RES; ""; LRES; ""; TRES; */ } //// TODO: SSres(0) fails..!!!?? static proc TestSSres(def I) { def save = basering; int @t,@m,r,rr,i; string name = "LEAD2SYZ:" +string(attrib(SSinit,"LEAD2SYZ")) + ",TAILREDSYZ:"+string(attrib(SSinit,"TAILREDSYZ")) + ",HYBRIDNF:" +string(attrib(SSinit,"HYBRIDNF")); int @PROFILE = attrib(SSinit, "PROFILE"); if(@PROFILE){ string @prof = "SSres_" + @save_res_desc + "_" + name + ".prof"; } StartAddResTest( "SSres", "minres + betti(,1) + mods: {" + name + "}" ); option(redSB); option(redTail); if(@PROFILE){ Syzextra::ProfilerStart(@prof);} timer=0;rtimer=0;def R=SSres(I,0);@m=rtimer; if(@PROFILE){ Syzextra::ProfilerStop();} setring R;module M;list @l=list();@l[size(RES)-1]=list();r=nrows(RES[1]);for(i=2;i<=size(RES);i++){M=RES[i];rr=nrows(M);if((r>0)&&(size(M)>0)&&(r0)&&(size(M)>0)&&(r 0) { DEBUG = #[1]; } def TREE = 0; if(size(#) > 1) { TREE = #[2]; } system("--min-time", "0.01"); system("--ticks-per-sec", 100); // option(prot); // TODO: only for now!! attrib(SSinit, "DEBUG", (DEBUG > 0) ); attrib(SSinit, "SYZCHECK", (DEBUG > 0) ); attrib(SSinit, "KERCHECK", (DEBUG > 0) ); attrib(SSinit, "TREEOUTPUT", TREE); attrib(SSinit, "PROFILE", 0); attrib(SSinit, "IGNORETAILS", 0); // not only frame attrib(SSinit, "NOCACHING", 0); int @treeout = attrib(SSinit, "TREEOUTPUT"); if( @treeout) { monitor("SimpleTests.json", "o"); "{ \"SimpleTests\": ["; } else { option(prot); } ring r; ideal M = maxideal(1); TestSSresAttribs(M, "\\\\GENERATED{" + string(M) + "} in " + string(basering)); kill r; ring r = 0, (a, b, c, d), lp; ideal M = maxideal(1); TestSSresAttribs(M, "\\\\GENERATED{" + string(M) + "} in " + string(basering)); kill r; ring R = 0, (w, x, y, z), dp; ideal M = w^2 - x*z, w*x - y*z, x^2 - w*y, x*y - z^2, y^2 - w*z; TestSSresAttribs(M, "\\\\GENERATED{" + string(M) + "} in " + string(basering)); kill R; ring r = 0, (a, b, c, d, e, f), dp; ideal M = maxideal(1); TestSSresAttribs(M, "\\\\GENERATED{" + string(M) + "} in " + string(basering)); kill r; ring r = 0, (x, y), lp; ideal M = x2, xy, y2; // Schreyer conterexample??? TestSSresAttribs(M, "\\\\GENERATED{" + string(M) + "} in " + string(basering)); kill r; ring r = 0, (x, y, z, t), dp; ideal M = homog(xy + y2 +x + 2y -1, t), homog(xz - x -y -z -2, t), homog(yz +1, t); // TODO: seg. fault? TestSSresAttribs(M, "\\\\GENERATED{" + string(M) + "} in " + string(basering)); kill r; ring AGR = (101), (a, b, c, d), dp; // simple: AGR@101n3d002s004%1: ideal M = c*d, b*d, a*d, c^2-d^2, b*c, a*c, b^2-d^2, a*b, a^2-d^2; TestSSresAttribs(M, "simple: AGR@101n3d002s004%1"); // medium: AGR@101n3d004s009%1; M = a*b+7*a*c-16*b*c-27*a*d+37*b*d-2*c*d, d^3, c*d^2, b*d^2, a*d^2, c^2*d, b*c*d, a*c*d, b^2*d, a^2*d, c^3, b*c^2, a*c^2, b^2*c, a^2*c, b^3, a^3; TestSSresAttribs(M, "medium: AGR@101n3d004s009%1"); kill AGR; string Name = "bordiga"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp; ideal I = -x2y+26/17xy2+70/17y3+96/121x2z+63/82xyz+115/11y2z-8114xz2-40/79yz2+16/125z3+3023x2u-123/70xyu+3395y2u-81/119xzu-23/66yzu+3626z2u+18/53xu2+111/58yu2-34/39zu2+53/40u3-94/17x2v-10/19xyv+81/88y2v-91/33xzv-9967yzv-103/4z2v-26/109xuv+69/97yuv+92/17zuv-19/96u2v+10/21xv2+6147yv2+32/113zv2-79/82uv2-77/51v3,4347x2y-9017xy2+11327y3+18/79x2z-93/43xyz-35/47y2z+14704xz2+10727yz2-1764z3-612x2u+20/107xyu-103/89y2u-39/2xzu+2345yzu+10251z2u-9984xu2-10299yu2+113/118zu2+37/91u3+2/31x2v+9552xyv-47/100y2v-3242xzv+113/27yzv-11271z2v-13/79xuv+15917yuv+5/114zuv+103/119u2v-21/55xv2-59/19yv2+101/68zv2-7817uv2-112/29v3,7228x2y-111/113xy2+5913y3+6/43x2z-11251xyz+27/121y2z+97/96xz2-7398yz2-97/114z3+38/15x2u+5005xyu-41/126y2u-61/116xzu+89/9yzu-4087z2u+26/15xu2-92/103yu2+21/68zu2-4027u3+97/91x2v+5150xyv-4/47y2v-2310xzv+7307yzv-77/86z2v+30/83xuv+413yuv-50zuv-103/106u2v+105/73xv2-109/98yv2+59/63zv2+715uv2+963v3,x3+3487x2y-9744xy2-13276y3-15213x2z-118/51xyz+101/104y2z+2754xz2+9111yz2-17/94z3+11136x2u-43/82xyu-9/41y2u-7306xzu-6839yzu+5692z2u-14682xu2+37/80yu2-85/97zu2-6186u3+34/15x2v+84/109xyv+5086y2v+27/112xzv-3/40yzv+19/120z2v+11222xuv+38/55yuv-24/83zuv+15814u2v-111/61xv2+49/44yv2+125/81zv2+1933uv2-19/71v3; TestSSresAttribs(I, Name); kill @p, Name, R; string Name = "rat.d8.g6"; int @p=31991; ring R = (@p),(x,y,z,u,v), dp; ideal I = -19/125x2y2-87/119xy3-97/21y4+36/53x2yz+2069xy2z-59/50y3z-65/33x2z2-14322xyz2+79/60y2z2-9035xz3-14890yz3+87/47z4-23/48x2yu+45/44xy2u+1972y3u+79/118x2zu-5173xyzu+115/121y2zu+1239xz2u-115/17yz2u-15900z3u-78/95x2u2+67/101xyu2-12757y2u2+12752xzu2+68/21yzu2+103/90z2u2-12917xu3+97/92yu3-24/49zu3-13/79u4-51/61x2yv-3103xy2v+77/117y3v+73/115x2zv-79/33xyzv+123/110y2zv+11969xz2v-31/95yz2v-123/95z3v-105/124x2uv+12624xyuv+2/63y2uv+6579xzuv+13/62yzuv+4388z2uv-12747xu2v-26/105yu2v-78/61zu2v-125/53u3v-5/71xyv2+62/77y2v2+21/44xzv2-9806yzv2+3/91z2v2+361xuv2+568yuv2+2926zuv2+53/38u2v2-14523yv3+2082zv3+113/115uv3,108/73x2y2+4028xy3+38/43y4-1944x2yz+39/80xy2z+8/109y3z+52/27x2z2+103/45xyz2+5834y2z2+63/101xz3+107/80yz3+1178z4-1/6x2yu+78/25xy2u-21/43y3u+50/71x2zu-14693xyzu+15074y2zu+9/103xz2u-7396yz2u-14493z3u+93/25x2u2+61/4xyu2-11306y2u2-79/81xzu2+59/82yzu2-5/106z2u2+89/71xu3-34/11yu3+15/103zu3-115/52u4-54/65x2yv+67/16xy2v-7/68y3v-10/13x2zv+32/85xyzv+1/91y2zv+107/118xz2v+7594yz2v-98/103z3v+9919x2uv-965xyuv+53/34y2uv+119/11xzuv-3400yzuv-8329z2uv+75/98xu2v-24yu2v+55/87zu2v-82/71u3v-73/115x2v2+85/19xyv2-213y2v2-7704xzv2-15347yzv2+14960z2v2+15065xuv2-125/17yuv2+32/83zuv2-14/73u2v2-21/44xv3+79/2yv3-61/32zv3+46/119uv3-2082v4,9/20x2y2+113/71xy3-88/65y4+9983x2yz-6722xy2z+87/68y3z+1893x2z2+65/32xyz2+51/55y2z2-102/53xz3+58/5yz3-7187z4-96/7x2yu-14/87xy2u-3532y3u+95/54x2zu+19/65xyzu-6728y2zu+31/121xz2u+73/106yz2u-91/5z3u-12928x2u2+707xyu2-55/48y2u2-96/25xzu2+15869yzu2-20/107z2u2-10030xu3-13786yu3-122/9zu3+19/59u4-7/52x2yv+101/74xy2v+83/6y3v-91/55x2zv-5266xyzv+85/61y2zv+126/95xz2v+56/51yz2v+13073z3v-50/21x2uv-13553xyuv-116/53y2uv+68/71xzuv-111/98yzuv-11037z2uv+68/121xu2v-124/53yu2v+54/55zu2v+5862u3v+12318x2v2-119/29xyv2+101/17y2v2-51/40xzv2-82/33yzv2-30/41z2v2-29/52xuv2+7817yuv2+8121zuv2-28/99u2v2+1125xv3-73/55yv3-14141zv3+8742uv3-1203v4,x2y2+11357xy3+295y4+144x2yz-31/54xy2z+89/119y3z+1/46x2z2+29/26xyz2+1384y2z2+1461xz3+113/91yz3+9494z4-7/32x2yu+12850xy2u-3626y3u-33/106x2zu-7/60xyzu-5935y2zu-8597xz2u+5527yz2u+1708z3u+6182x2u2-15780xyu2+4669y2u2-38/69xzu2+8412yzu2+9265z2u2-5679xu3-67/18yu3-34/67zu3-7178u4+113/56x2yv-3669xy2v+17/113y3v-87/35x2zv-4871xyzv-111/11y2zv-1131xz2v-72/13yz2v+838z3v-115/4x2uv+3395xyuv-43/68y2uv-82/13xzuv+7042yzuv-88/119z2uv+100/19xu2v+24/11yu2v+89/3zu2v+7395u3v-119/109x2v2+1/104xyv2+18/25y2v2+700xzv2-59/9yzv2-92/87z2v2+2486xuv2-67/103yuv2+1469zuv2-101/91u2v2-79/33xv3+10838yv3+81/4zv3-11843uv3+7204v4,19/125x3-15698x2y-22/117xy2-95/107y3+2027x2z-7750xyz+85/104y2z-15326xz2+31/101yz2+67/81z3-7879x2u-112/115xyu+124/81y2u+99/61xzu-7458yzu+40/33z2u-1502xu2+6591yu2-7/73zu2-42/95u3+93/83x2v-15/112xyv-84/95y2v+35/36xzv+5/24yzv-12768z2v+13232xuv-76/103yuv-79/52zuv-7217u2v+75/92xv2-49/64yv2+17/14zv2-6109uv2+1695v3; TestSSresAttribs(I, Name); kill R, Name, @p; if( @treeout) { "] }"; monitor(""); } } static proc testAGR(list #) { def DEBUG = 0; if(size(#) > 0) { DEBUG = #[1]; } system("--min-time", "0.01"); system("--ticks-per-sec", 100); attrib(SSinit, "DEBUG", 0); attrib(SSinit, "SYZCHECK", (DEBUG > 0)); attrib(SSinit, "KERCHECK", 0); attrib(SSinit, "TREEOUTPUT", 0); attrib(SSinit, "PROFILE", 0); attrib(SSinit, "IGNORETAILS", 0); // not only frame option(prot); ring AGR = (101), (a, b, c, d), dp; AGR; // lengthy: AGR@101n3d008s058%3, kernel only! ideal M = c^4*d^2+4*a^3*d^3+29*a^2*b*d^3-2*a*b^2*d^3+2*b^3*d^3-21*a^2*c*d^3+46*a*b*c*d^3+2*b^2*c*d^3-13*a*c^2*d^3+32*b*c^2*d^3+46*c^3*d^3-28*a^2*d^4+4*a*b*d^4+29*b^2*d^4-8*a*c*d^4+33*b*c*d^4-16*c^2*d^4+17*a*d^5-3*b*d^5-42*c*d^5+47*d^6,b*c^3*d^2+35*a^3*d^3+24*a^2*b*d^3+46*a*b^2*d^3-22*b^3*d^3-48*a^2*c*d^3+20*a*b*c*d^3-28*b^2*c*d^3-40*a*c^2*d^3-4*b*c^2*d^3+35*c^3*d^3-21*a^2*d^4+3*a*b*d^4+8*b^2*d^4-2*a*c*d^4-22*b*c*d^4+24*c^2*d^4+44*a*d^5+33*b*d^5+31*c*d^5+26*d^6,a*c^3*d^2-42*a^3*d^3+34*a^2*b*d^3-10*a*b^2*d^3+30*b^3*d^3-6*a^2*c*d^3-30*a*b*c*d^3-34*b^2*c*d^3+29*a*c^2*d^3+35*b*c^2*d^3+13*c^3*d^3+8*a^2*d^4+23*a*b*d^4-29*b^2*d^4+12*a*c*d^4-22*b*c*d^4-50*c^2*d^4-4*b*d^5+9*c*d^5+13*d^6,b^2*c^2*d^2+a^3*d^3-49*a^2*b*d^3+26*a*b^2*d^3+20*b^3*d^3+24*a^2*c*d^3-2*a*b*c*d^3+31*b^2*c*d^3-30*a*c^2*d^3+21*b*c^2*d^3-24*c^3*d^3-38*a^2*d^4-14*a*b*d^4-14*b^2*d^4+6*a*c*d^4+3*b*c*d^4+13*c^2*d^4-11*a*d^5-38*b*d^5+22*c*d^5+48*d^6,a*b*c^2*d^2+18*a^3*d^3-29*a^2*b*d^3-21*a*b^2*d^3-2*b^3*d^3-25*a^2*c*d^3+37*a*b*c*d^3-14*b^2*c*d^3-47*a*c^2*d^3-6*b*c^2*d^3-34*c^3*d^3+43*a^2*d^4+22*a*b*d^4-39*b^2*d^4-41*a*c*d^4-17*b*c*d^4-13*c^2*d^4-43*a*d^5+28*b*d^5-42*c*d^5-49*d^6,a^2*c^2*d^2-33*a^3*d^3+30*a^2*b*d^3-13*a*b^2*d^3+18*b^3*d^3-8*a^2*c*d^3-18*a*b*c*d^3-15*b^2*c*d^3-21*a*c^2*d^3+45*b*c^2*d^3-35*c^3*d^3-4*a^2*d^4-4*a*b*d^4+10*b^2*d^4-19*a*c*d^4-18*b*c*d^4-22*c^2*d^4-27*a*d^5+20*b*d^5-14*c*d^5+24*d^6,b^3*c*d^2-10*a^3*d^3+37*a*b^2*d^3-43*b^3*d^3-10*a^2*c*d^3-9*a*b*c*d^3+47*a*c^2*d^3-24*b*c^2*d^3+12*c^3*d^3+7*a^2*d^4+19*a*b*d^4-27*b^2*d^4-2*a*c*d^4-35*b*c*d^4+45*c^2*d^4-44*a*d^5-43*b*d^5+24*c*d^5+16*d^6,a*b^2*c*d^2+2*a^3*d^3-14*a^2*b*d^3+2*a*b^2*d^3+18*b^3*d^3-48*a^2*c*d^3+43*a*b*c*d^3-25*b^2*c*d^3+15*a*c^2*d^3-7*b*c^2*d^3+42*c^3*d^3-16*a^2*d^4+7*b^2*d^4-23*a*c*d^4+24*b*c*d^4+25*c^2*d^4-17*a*d^5-16*b*d^5-32*c*d^5-50*d^6,a^2*b*c*d^2-16*a^3*d^3+7*a^2*b*d^3-20*a*b^2*d^3+11*b^3*d^3+16*a^2*c*d^3+6*a*b*c*d^3-25*b^2*c*d^3+42*a*c^2*d^3-39*b*c^2*d^3-15*c^3*d^3-25*a^2*d^4+46*a*b*d^4-3*b^2*d^4+5*a*c*d^4+28*b*c*d^4+6*c^2*d^4-20*a*d^5-15*b*d^5-30*c*d^5+17*d^6,a^3*c*d^2+39*a^3*d^3+22*a^2*b*d^3-21*a*b^2*d^3+10*b^3*d^3+40*a^2*c*d^3-37*a*b*c*d^3+11*b^2*c*d^3+43*a*c^2*d^3+28*b*c^2*d^3-10*c^3*d^3+30*a^2*d^4+36*a*b*d^4-45*b^2*d^4-40*a*c*d^4-31*b*c*d^4+28*c^2*d^4+35*a*d^5+6*b*d^5+14*c*d^5+25*d^6,b^4*d^2+50*a^3*d^3+12*a^2*b*d^3+29*a*b^2*d^3-38*b^3*d^3-44*a^2*c*d^3+28*a*b*c*d^3+18*b^2*c*d^3-31*a*c^2*d^3+16*b*c^2*d^3-18*c^3*d^3+5*a^2*d^4-43*a*b*d^4+16*b^2*d^4+9*a*c*d^4-30*b*c*d^4+50*c^2*d^4+3*a*d^5+33*b*d^5+3*c*d^5-48*d^6,a*b^3*d^2+13*a^3*d^3-28*a^2*b*d^3-33*a*b^2*d^3-25*b^3*d^3-41*a^2*c*d^3+a*b*c*d^3+19*b^2*c*d^3+41*a*c^2*d^3-17*b*c^2*d^3+34*c^3*d^3-10*a^2*d^4+30*a*b*d^4+34*b^2*d^4+13*a*c*d^4+b*c*d^4-35*c^2*d^4-34*a*d^5+23*b*d^5-7*c*d^5+6*d^6,a^2*b^2*d^2+22*a^3*d^3-32*a^2*b*d^3+29*a*b^2*d^3+21*b^3*d^3-30*a^2*c*d^3-47*a*b*c*d^3-11*b^2*c*d^3-16*a*c^2*d^3-14*b*c^2*d^3+49*c^3*d^3+47*a^2*d^4-11*a*b*d^4+4*b^2*d^4+13*a*c*d^4+7*b*c*d^4-30*c^2*d^4+31*a*d^5+10*b*d^5-8*c*d^5-27*d^6,a^3*b*d^2-43*a^3*d^3-2*a^2*b*d^3+15*a*b^2*d^3+42*b^3*d^3+25*a^2*c*d^3+22*a*b*c*d^3-4*b^2*c*d^3-29*a*c^2*d^3-31*b*c^2*d^3-3*c^3*d^3+33*a^2*d^4+20*a*b*d^4-34*b^2*d^4+8*a*c*d^4+48*b*c*d^4-29*c^2*d^4-46*a*d^5+27*b*d^5+29*c*d^5+33*d^6,a^4*d^2+30*a^3*d^3-42*a*b^2*d^3-16*b^3*d^3-33*a^2*c*d^3+13*a*b*c*d^3+7*b^2*c*d^3-23*a*c^2*d^3+28*b*c^2*d^3-37*c^3*d^3+3*a^2*d^4-34*a*b*d^4+16*b^2*d^4-21*a*c*d^4-39*b*c*d^4+5*c^2*d^4+35*a*d^5+39*b*d^5-26*c*d^5-47*d^6,c^5*d+48*a^3*d^3-37*a^2*b*d^3+31*a*b^2*d^3-19*b^3*d^3+49*a^2*c*d^3-5*a*b*c*d^3+45*b^2*c*d^3+24*a*c^2*d^3-26*b*c^2*d^3-10*c^3*d^3-a^2*d^4+43*a*b*d^4-26*b^2*d^4+45*a*c*d^4-3*b*c*d^4+38*c^2*d^4+10*a*d^5-5*b*d^5-34*c*d^5+22*d^6,b*c^4*d+30*a^3*d^3-40*a^2*b*d^3-39*a*b^2*d^3+33*b^3*d^3+31*a^2*c*d^3-17*a*b*c*d^3-44*b^2*c*d^3+24*a*c^2*d^3+22*b*c^2*d^3-44*c^3*d^3-29*a^2*d^4+4*a*b*d^4-4*b^2*d^4+8*a*c*d^4-42*b*c*d^4+15*c^2*d^4-42*a*d^5+15*b*d^5-41*c*d^5-46*d^6,a*c^4*d-11*a^3*d^3-5*a^2*b*d^3+33*a*b^2*d^3+7*b^3*d^3-31*a^2*c*d^3-47*a*b*c*d^3-50*b^2*c*d^3-50*a*c^2*d^3-39*b*c^2*d^3+25*c^3*d^3+5*a^2*d^4+35*a*b*d^4-34*b^2*d^4+42*a*c*d^4-44*b*c*d^4-17*c^2*d^4+11*a*d^5+b*d^5+31*c*d^5+45*d^6,b^2*c^3*d+12*a^3*d^3-41*a^2*b*d^3+29*a*b^2*d^3-42*b^3*d^3-32*a^2*c*d^3+47*a*b*c*d^3-13*b^2*c*d^3-20*a*c^2*d^3+45*b*c^2*d^3-49*c^3*d^3-34*a^2*d^4+16*a*b*d^4+11*b^2*d^4-49*a*c*d^4-27*b*c*d^4-31*c^2*d^4+29*a*d^5-23*b*d^5+13*c*d^5+42*d^6,a*b*c^3*d-16*a^3*d^3-35*a^2*b*d^3+12*a*b^2*d^3-39*b^3*d^3-32*a*b*c*d^3-4*b^2*c*d^3+31*a*c^2*d^3+43*b*c^2*d^3-42*c^3*d^3+36*a^2*d^4-5*a*b*d^4-4*b^2*d^4+5*a*c*d^4+20*b*c*d^4+31*c^2*d^4+15*a*d^5+25*b*d^5-16*c*d^5-28*d^6,a^2*c^3*d-16*a^3*d^3+8*a^2*b*d^3+30*a*b^2*d^3-16*b^3*d^3+20*a^2*c*d^3-11*b^2*c*d^3-48*a*c^2*d^3+11*b*c^2*d^3-20*c^3*d^3-24*a^2*d^4-23*a*b*d^4+9*b^2*d^4+13*a*c*d^4-42*b*c*d^4+22*c^2*d^4-29*a*d^5-28*b*d^5-7*c*d^5-2*d^6,b^3*c^2*d+42*a^3*d^3-11*a^2*b*d^3+18*a*b^2*d^3-13*b^3*d^3+22*a^2*c*d^3-10*a*b*c*d^3-25*b^2*c*d^3-17*a*c^2*d^3-23*b*c^2*d^3-37*c^3*d^3-3*a^2*d^4-33*a*b*d^4+44*b^2*d^4-41*a*c*d^4+6*b*c*d^4-36*c^2*d^4-43*a*d^5+b*d^5+25*c*d^5+48*d^6,a*b^2*c^2*d+21*a^3*d^3+5*a^2*b*d^3+38*a*b^2*d^3+25*b^3*d^3-12*a^2*c*d^3+7*a*b*c*d^3+28*b^2*c*d^3+a*c^2*d^3+33*b*c^2*d^3+22*c^3*d^3+10*a^2*d^4-7*a*b*d^4-5*b^2*d^4+50*a*c*d^4-23*b*c*d^4+22*c^2*d^4-4*a*d^5+45*b*d^5-42*c*d^5+d^6,a^2*b*c^2*d-45*a^3*d^3+2*a^2*b*d^3+44*a*b^2*d^3-5*b^3*d^3-19*a^2*c*d^3-3*a*b*c*d^3+18*b^2*c*d^3-22*a*c^2*d^3+46*b*c^2*d^3+41*c^3*d^3-26*a^2*d^4-a*b*d^4-42*b^2*d^4-40*a*c*d^4+39*b*c*d^4+24*c^2*d^4-6*a*d^5-6*b*d^5+13*c*d^5-28*d^6,a^3*c^2*d+4*a^3*d^3+31*a^2*b*d^3+21*a*b^2*d^3+39*b^3*d^3-8*a^2*c*d^3+49*a*b*c*d^3-48*b^2*c*d^3-16*a*c^2*d^3-33*b*c^2*d^3+35*c^3*d^3+41*a^2*d^4+18*a*b*d^4+47*b^2*d^4-3*a*c*d^4+12*b*c*d^4+13*c^2*d^4+32*a*d^5-40*b*d^5+50*c*d^5-2*d^6,b^4*c*d+23*a^3*d^3+47*a^2*b*d^3-10*a*b^2*d^3-43*b^3*d^3+49*a^2*c*d^3+7*a*b*c*d^3+34*b^2*c*d^3-40*a*c^2*d^3-37*b*c^2*d^3-6*c^3*d^3+30*a^2*d^4-34*a*b*d^4-6*b^2*d^4+21*a*c*d^4+41*b*c*d^4-33*c^2*d^4-9*a*d^5+2*b*d^5+8*c*d^5+7*d^6,a*b^3*c*d-5*a^3*d^3-42*a^2*b*d^3+22*a*b^2*d^3-35*b^3*d^3+a^2*c*d^3+20*a*b*c*d^3-10*b^2*c*d^3+23*a*c^2*d^3-17*b*c^2*d^3+30*c^3*d^3+24*a^2*d^4+32*a*b*d^4-7*b^2*d^4-48*a*c*d^4-25*b*c*d^4-6*c^2*d^4-33*a*d^5+29*b*d^5+12*c*d^5+26*d^6,a^2*b^2*c*d+6*a^3*d^3-46*a^2*b*d^3-30*a*b^2*d^3+b^3*d^3-35*a^2*c*d^3+41*a*b*c*d^3-4*b^2*c*d^3-42*a*c^2*d^3+16*b*c^2*d^3+19*c^3*d^3-13*a^2*d^4-16*a*b*d^4+45*b^2*d^4-25*a*c*d^4-48*b*c*d^4+35*c^2*d^4+50*a*d^5+31*b*d^5-25*c*d^5+6*d^6,a^3*b*c*d+3*a^3*d^3-39*a^2*b*d^3+14*a*b^2*d^3-4*b^3*d^3-36*a^2*c*d^3+47*a*b*c*d^3+27*b^2*c*d^3+50*a*c^2*d^3-45*b*c^2*d^3+49*c^3*d^3-18*a^2*d^4+20*a*b*d^4+17*b^2*d^4+a*c*d^4+33*b*c*d^4+42*c^2*d^4+19*a*d^5+18*b*d^5+33*c*d^5+15*d^6,a^4*c*d-14*a^3*d^3-8*a^2*b*d^3-a*b^2*d^3-34*b^3*d^3-27*a^2*c*d^3-15*a*b*c*d^3-14*b^2*c*d^3+33*a*c^2*d^3-34*b*c^2*d^3-4*c^3*d^3+47*a^2*d^4+50*a*b*d^4-6*b^2*d^4+16*a*c*d^4+26*c^2*d^4-27*a*d^5+2*b*d^5-31*c*d^5+47*d^6,b^5*d+3*a^3*d^3-9*a^2*b*d^3+46*a*b^2*d^3+b^3*d^3-2*a^2*c*d^3-39*a*b*c*d^3-31*b^2*c*d^3-30*a*c^2*d^3+23*b*c^2*d^3+25*c^3*d^3+9*a^2*d^4-15*a*b*d^4-2*b^2*d^4-12*a*c*d^4+11*b*c*d^4+9*c^2*d^4+3*a*d^5+9*b*d^5+41*c*d^5-38*d^6,a*b^4*d-48*a^3*d^3+42*a^2*b*d^3+27*a*b^2*d^3+32*b^3*d^3+21*a^2*c*d^3-5*a*b*c*d^3-39*b^2*c*d^3+6*a*c^2*d^3-20*b*c^2*d^3+45*c^3*d^3-48*a^2*d^4+44*a*b*d^4+25*b^2*d^4-29*a*c*d^4+4*b*c*d^4+50*c^2*d^4-6*a*d^5-40*b*d^5-11*c*d^5-28*d^6,a^2*b^3*d-41*a^3*d^3+21*a^2*b*d^3+39*a*b^2*d^3-2*b^3*d^3+24*a*b*c*d^3-10*b^2*c*d^3+31*a*c^2*d^3-34*b*c^2*d^3-31*c^3*d^3+20*a^2*d^4+41*a*b*d^4-10*b^2*d^4-40*a*c*d^4+5*b*c*d^4+31*c^2*d^4+6*a*d^5+26*b*d^5+29*c*d^5-5*d^6,a^3*b^2*d-11*a^3*d^3-39*a^2*b*d^3+2*a*b^2*d^3-44*b^3*d^3-23*a^2*c*d^3+21*a*b*c*d^3-44*b^2*c*d^3-7*a*c^2*d^3+49*b*c^2*d^3+46*c^3*d^3+17*a^2*d^4+49*a*b*d^4-14*b^2*d^4+29*a*c*d^4-20*b*c*d^4-49*c^2*d^4-13*a*d^5-41*b*d^5-18*c*d^5+50*d^6,a^4*b*d+9*a^3*d^3+50*a^2*b*d^3+46*a*b^2*d^3-48*b^3*d^3+43*a^2*c*d^3-45*a*b*c*d^3+24*b^2*c*d^3-4*a*c^2*d^3-b*c^2*d^3-34*c^3*d^3+33*a^2*d^4+14*a*b*d^4-37*b^2*d^4-13*a*c*d^4+48*b*c*d^4-31*c^2*d^4-22*a*d^5+42*b*d^5+49*c*d^5-43*d^6,a^5*d+33*a^3*d^3-23*a^2*b*d^3+30*a*b^2*d^3+5*b^3*d^3-26*a^2*c*d^3-35*a*b*c*d^3-50*b^2*c*d^3-21*a*c^2*d^3+4*b*c^2*d^3+10*c^3*d^3+39*a^2*d^4-2*a*b*d^4+23*b^2*d^4+17*a*c*d^4-50*b*c*d^4-8*c^2*d^4-39*a*d^5+36*b*d^5-43*c*d^5-39*d^6,c^6+20*a^3*d^3-41*a*b^2*d^3+39*b^3*d^3+26*a^2*c*d^3-8*a*b*c*d^3-49*b^2*c*d^3+25*a*c^2*d^3+32*b*c^2*d^3-32*c^3*d^3-2*a^2*d^4-38*a*b*d^4-38*b^2*d^4+17*a*c*d^4+22*b*c*d^4-36*c^2*d^4-41*a*d^5+37*b*d^5-49*c*d^5-19*d^6,b*c^5-36*a^3*d^3+32*a^2*b*d^3-14*a*b^2*d^3-31*b^3*d^3-2*a^2*c*d^3-8*a*b*c*d^3-39*b^2*c*d^3-46*a*c^2*d^3+10*b*c^2*d^3+27*c^3*d^3+25*a^2*d^4-30*a*b*d^4+3*b^2*d^4-36*a*c*d^4+44*b*c*d^4+17*c^2*d^4-46*a*d^5-37*b*d^5-2*c*d^5-47*d^6,a*c^5-49*a^3*d^3+11*a^2*b*d^3-21*a*b^2*d^3-14*b^3*d^3+26*a^2*c*d^3-a*b*c*d^3+24*b^2*c*d^3-46*a*c^2*d^3+23*b*c^2*d^3+33*c^3*d^3-11*a^2*d^4-a*b*d^4+49*b^2*d^4-17*a*c*d^4+49*b*c*d^4+36*c^2*d^4+10*a*d^5-19*b*d^5+26*c*d^5-32*d^6,b^2*c^4-14*a^3*d^3+9*a^2*b*d^3-5*a*b^2*d^3+17*b^3*d^3+2*a^2*c*d^3+12*a*b*c*d^3-37*b^2*c*d^3-43*a*c^2*d^3+5*b*c^2*d^3-9*c^3*d^3-27*a^2*d^4+14*a*b*d^4-19*b^2*d^4+29*a*c*d^4+32*b*c*d^4-15*c^2*d^4-26*a*d^5-31*b*d^5+46*c*d^5-22*d^6,a*b*c^4+33*a^3*d^3-22*a^2*b*d^3-14*a*b^2*d^3-30*b^3*d^3-48*a^2*c*d^3+34*a*b*c*d^3-8*b^2*c*d^3-44*a*c^2*d^3-4*b*c^2*d^3+3*c^3*d^3+26*a^2*d^4+4*a*b*d^4+7*b^2*d^4-28*a*c*d^4-22*b*c*d^4-35*c^2*d^4-50*a*d^5-43*b*d^5+46*c*d^5-49*d^6,a^2*c^4-9*a^3*d^3+3*a^2*b*d^3+34*a*b^2*d^3+4*b^3*d^3+5*a^2*c*d^3-17*a*b*c*d^3-48*b^2*c*d^3+10*a*c^2*d^3+2*b*c^2*d^3-12*c^3*d^3-7*a^2*d^4-6*a*b*d^4+37*b^2*d^4-16*a*c*d^4+47*b*c*d^4+6*c^2*d^4-35*a*d^5-45*b*d^5-12*c*d^5-30*d^6,b^3*c^3-21*a^3*d^3-6*a^2*b*d^3-26*a*b^2*d^3-22*b^3*d^3-29*a*b*c*d^3-26*b^2*c*d^3+50*a*c^2*d^3-41*b*c^2*d^3+22*c^3*d^3-41*a^2*d^4+25*a*b*d^4+16*b^2*d^4+11*a*c*d^4+34*b*c*d^4+19*c^2*d^4-38*a*d^5-8*b*d^5-42*c*d^5-6*d^6,a*b^2*c^3+3*a^3*d^3-45*a^2*b*d^3+39*a*b^2*d^3+22*b^3*d^3+48*a^2*c*d^3-7*a*b*c*d^3-46*b^2*c*d^3-22*a*c^2*d^3-17*b*c^2*d^3-27*c^3*d^3-35*a^2*d^4+47*a*b*d^4+6*b^2*d^4-5*a*c*d^4-30*b*c*d^4+25*c^2*d^4-10*a*d^5+46*b*d^5+5*c*d^5-18*d^6,a^2*b*c^3-36*a^3*d^3+33*a^2*b*d^3+47*a*b^2*d^3-16*b^3*d^3-41*a^2*c*d^3+42*a*b*c*d^3-29*b^2*c*d^3+39*a*c^2*d^3-12*b*c^2*d^3-25*c^3*d^3-11*a^2*d^4-37*a*b*d^4+29*b^2*d^4-18*a*c*d^4+43*b*c*d^4+12*c^2*d^4-37*a*d^5+7*b*d^5+7*c*d^5-5*d^6,a^3*c^3+25*a^3*d^3+34*a^2*b*d^3+29*a*b^2*d^3-34*b^3*d^3-46*a^2*c*d^3-17*a*b*c*d^3+49*b^2*c*d^3-35*a*c^2*d^3-21*b*c^2*d^3-45*c^3*d^3+43*a^2*d^4+29*a*b*d^4+36*b^2*d^4+37*a*c*d^4+12*b*c*d^4-17*c^2*d^4+12*a*d^5+47*c*d^5-23*d^6,b^4*c^2-10*a^3*d^3+38*a^2*b*d^3+33*a*b^2*d^3+9*b^3*d^3-25*a^2*c*d^3+38*a*b*c*d^3-19*b^2*c*d^3-33*a*c^2*d^3-49*b*c^2*d^3-16*c^3*d^3-14*a^2*d^4-3*a*b*d^4-30*b^2*d^4-32*a*c*d^4+28*b*c*d^4-3*c^2*d^4-16*a*d^5+31*b*d^5-49*c*d^5-3*d^6,a*b^3*c^2+25*a^3*d^3-47*a^2*b*d^3+47*b^3*d^3+13*a^2*c*d^3-17*a*b*c*d^3+26*b^2*c*d^3-43*a*c^2*d^3+39*b*c^2*d^3-4*c^3*d^3+20*a^2*d^4+6*a*b*d^4+49*b^2*d^4+14*a*c*d^4-17*b*c*d^4+38*c^2*d^4+21*a*d^5-9*b*d^5-26*c*d^5+47*d^6,a^2*b^2*c^2+12*a^3*d^3+10*a^2*b*d^3-40*a*b^2*d^3+14*b^3*d^3+36*a^2*c*d^3-9*a*b*c*d^3+9*b^2*c*d^3+7*a*c^2*d^3+12*b*c^2*d^3-37*c^3*d^3-44*a^2*d^4-48*a*b*d^4+11*b^2*d^4-13*a*c*d^4+31*b*c*d^4+47*c^2*d^4+28*a*d^5+39*b*d^5+27*c*d^5-d^6,a^3*b*c^2-28*a^3*d^3-22*a^2*b*d^3-8*a*b^2*d^3+40*b^3*d^3-13*a^2*c*d^3+35*a*b*c*d^3-4*b^2*c*d^3+28*a*c^2*d^3+30*b*c^2*d^3-13*c^3*d^3+16*a^2*d^4+48*a*b*d^4-42*b^2*d^4+10*a*c*d^4-b*c*d^4+37*c^2*d^4-17*a*d^5-15*b*d^5+40*c*d^5+27*d^6,a^4*c^2+17*a^3*d^3+45*a^2*b*d^3+42*a*b^2*d^3-20*b^3*d^3-39*a^2*c*d^3-20*a*b*c*d^3-44*b^2*c*d^3+33*a*c^2*d^3+39*b*c^2*d^3-37*c^3*d^3+39*a^2*d^4+39*a*b*d^4-44*b^2*d^4+8*a*c*d^4-34*b*c*d^4+36*c^2*d^4-47*a*d^5+38*b*d^5-46*c*d^5+23*d^6,b^5*c+24*a^3*d^3+17*a^2*b*d^3-22*a*b^2*d^3-27*b^3*d^3+27*a^2*c*d^3+48*a*b*c*d^3+4*b^2*c*d^3+a*c^2*d^3-21*b*c^2*d^3-14*c^3*d^3+3*a^2*d^4+15*a*b*d^4+41*b^2*d^4-27*a*c*d^4+4*b*c*d^4+3*c^2*d^4-46*a*d^5+28*b*d^5+6*c*d^5+36*d^6,a*b^4*c-29*a^3*d^3+30*a^2*b*d^3+31*a*b^2*d^3+44*b^3*d^3-12*a^2*c*d^3-27*a*b*c*d^3+48*b^2*c*d^3+4*a*c^2*d^3+2*b*c^2*d^3-17*c^3*d^3-7*a^2*d^4+25*a*b*d^4-45*b^2*d^4-17*a*c*d^4-14*b*c*d^4-11*c^2*d^4-45*a*d^5-36*b*d^5-12*c*d^5-44*d^6,a^2*b^3*c-10*a^3*d^3-30*a^2*b*d^3-22*a*b^2*d^3-35*b^3*d^3+37*a^2*c*d^3-35*a*b*c*d^3-12*b^2*c*d^3-16*b*c^2*d^3+49*c^3*d^3+38*a^2*d^4-21*a*b*d^4-20*b^2*d^4-6*a*c*d^4+41*b*c*d^4+49*c^2*d^4+13*a*d^5-38*b*d^5-32*c*d^5-12*d^6,a^3*b^2*c+5*a^2*b*d^3-40*a*b^2*d^3+14*b^3*d^3-4*a^2*c*d^3-13*a*b*c*d^3+47*b^2*c*d^3+28*a*c^2*d^3+15*b*c^2*d^3+47*c^3*d^3-8*a^2*d^4-20*a*b*d^4+3*b^2*d^4+42*a*c*d^4+18*b*c*d^4-23*c^2*d^4-48*a*d^5+12*b*d^5-25*c*d^5-39*d^6,a^4*b*c+29*a^3*d^3+21*a^2*b*d^3-32*a*b^2*d^3+48*b^3*d^3-44*a^2*c*d^3-3*a*b*c*d^3-27*b^2*c*d^3+27*a*c^2*d^3+43*b*c^2*d^3-30*c^3*d^3+4*a^2*d^4+16*a*b*d^4+33*b^2*d^4+37*a*c*d^4-32*b*c*d^4+14*c^2*d^4+50*a*d^5-49*c*d^5-33*d^6,a^5*c-26*a^3*d^3-50*a^2*b*d^3+2*a*b^2*d^3+3*b^3*d^3-15*a^2*c*d^3-32*a*b*c*d^3-4*b^2*c*d^3-13*a*c^2*d^3-13*b*c^2*d^3+3*c^3*d^3+32*a^2*d^4-32*a*b*d^4-47*b^2*d^4-39*a*c*d^4-34*b*c*d^4-9*c^2*d^4-7*a*d^5-22*b*d^5+16*c*d^5+44*d^6,b^6+45*a^3*d^3-42*a^2*b*d^3-35*a*b^2*d^3+13*b^3*d^3+28*a^2*c*d^3-2*a*b*c*d^3-37*b^2*c*d^3-9*a*c^2*d^3+44*b*c^2*d^3-24*c^3*d^3+36*a^2*d^4+42*a*b*d^4-38*b^2*d^4-34*a*c*d^4-46*b*c*d^4+23*c^2*d^4-9*a*d^5-28*b*d^5+37*c*d^5+26*d^6,a*b^5-14*a^3*d^3+38*a^2*b*d^3-37*a*b^2*d^3-33*b^3*d^3-24*a^2*c*d^3+15*a*b*c*d^3+44*b^2*c*d^3-45*a*c^2*d^3+3*b*c^2*d^3-41*c^3*d^3-48*a^2*d^4-36*a*b*d^4+39*b^2*d^4+46*a*c*d^4-3*b*c*d^4+21*c^2*d^4-36*a*d^5-20*b*d^5+24*c*d^5-33*d^6,a^2*b^4-27*a^3*d^3-10*a^2*b*d^3-5*a*b^2*d^3+8*b^3*d^3+21*a^2*c*d^3+31*a*b*c*d^3-44*b^2*c*d^3+41*a*c^2*d^3+17*b*c^2*d^3-8*c^3*d^3+19*a^2*d^4+25*a*b*d^4+b^2*d^4+3*a*c*d^4+2*b*c*d^4-40*c^2*d^4+31*a*d^5-19*b*d^5+35*c*d^5-28*d^6,a^3*b^3-12*a^3*d^3-25*a^2*b*d^3+37*a*b^2*d^3-37*b^3*d^3+46*a^2*c*d^3+43*a*b*c*d^3+b^2*c*d^3-41*a*c^2*d^3-38*b*c^2*d^3-36*c^3*d^3-11*a*b*d^4+20*b^2*d^4-a*c*d^4-26*b*c*d^4+14*c^2*d^4-48*a*d^5+17*b*d^5+9*c*d^5+30*d^6,a^4*b^2+36*a^3*d^3+9*a^2*b*d^3-31*b^3*d^3+50*a^2*c*d^3+41*a*b*c*d^3+40*b^2*c*d^3+48*a*c^2*d^3-41*b*c^2*d^3-17*c^3*d^3+33*a^2*d^4+47*a*b*d^4+22*b^2*d^4+2*a*c*d^4+23*b*c*d^4-47*c^2*d^4+34*a*d^5-15*b*d^5-33*c*d^5-38*d^6,a^5*b-12*a^3*d^3-38*a^2*b*d^3+46*a*b^2*d^3-32*b^3*d^3-41*a^2*c*d^3+14*a*b*c*d^3-34*b^2*c*d^3+7*a*c^2*d^3-6*b*c^2*d^3+31*c^3*d^3+30*a^2*d^4+12*a*b*d^4-17*b^2*d^4-7*a*c*d^4-45*b*c*d^4+10*c^2*d^4+29*a*d^5-28*b*d^5+34*c*d^5-15*d^6,a^6-33*a^3*d^3-45*a^2*b*d^3+19*a*b^2*d^3+39*b^3*d^3-5*a^2*c*d^3-46*a*b*c*d^3+9*b^2*c*d^3+15*a*c^2*d^3-21*b*c^2*d^3+46*c^3*d^3-39*a^2*d^4-9*a*b*d^4+50*b^2*d^4-45*a*c*d^4-39*b*c*d^4-18*c^2*d^4-4*a*d^5-19*b*d^5+12*c*d^5+39*d^6,d^7,c*d^6,b*d^6,a*d^6,c^2*d^5,b*c*d^5,a*c*d^5,b^2*d^5,a*b*d^5,a^2*d^5,c^3*d^4,b*c^2*d^4,a*c^2*d^4,b^2*c*d^4,a*b*c*d^4,a^2*c*d^4,b^3*d^4,a*b^2*d^4,a^2*b*d^4,a^3*d^4; TestSSresAttribs2tr(M, "AGR@101n3d008s058%3"); // AGR@101n3d010s010%3, a bit slower... M = a^2*b^5-50*a*b^6-26*a^6*c+15*a^5*b*c-42*a^4*b^2*c-2*a^3*b^3*c+40*a^2*b^4*c-20*a*b^5*c+11*b^6*c-17*a^5*c^2-4*a^4*b*c^2+13*a^3*b^2*c^2-7*a^2*b^3*c^2+13*a*b^4*c^2-46*b^5*c^2+38*a^4*c^3+32*a^3*b*c^3-49*a^2*b^2*c^3-41*a*b^3*c^3+9*b^4*c^3+17*a^3*c^4-23*a^2*b*c^4+46*a*b^2*c^4+9*b^3*c^4-20*a^2*c^5-34*a*b*c^5-46*b^2*c^5-3*a*c^6+11*b*c^6-22*a^6*d-5*a^5*b*d-21*a^4*b^2*d-43*a^3*b^3*d-29*a^2*b^4*d+43*a*b^5*d-2*b^6*d+24*a^5*c*d-9*a^4*b*c*d+3*a^3*b^2*c*d+20*a^2*b^3*c*d+47*a*b^4*c*d-41*b^5*c*d+11*a^4*c^2*d-14*a^3*b*c^2*d+13*a^2*b^2*c^2*d-19*a*b^3*c^2*d-12*b^4*c^2*d+41*a^3*c^3*d-49*a^2*b*c^3*d-10*a*b^2*c^3*d+19*b^3*c^3*d-13*a^2*c^4*d+10*a*b*c^4*d-49*b^2*c^4*d-3*a*c^5*d-10*b*c^5*d+31*c^6*d-16*a^5*d^2+24*a^4*b*d^2-43*a^3*b^2*d^2+36*a^2*b^3*d^2-36*a^4*c*d^2-36*a^3*b*c*d^2-16*a^2*b^2*c*d^2+35*a*b^3*c*d^2+29*b^4*c*d^2+40*a^3*c^2*d^2-24*a^2*b*c^2*d^2-24*a*b^2*c^2*d^2+7*b^3*c^2*d^2+28*a^2*c^3*d^2+49*a*b*c^3*d^2+49*b^2*c^3*d^2+7*a*c^4*d^2-9*b*c^4*d^2+21*c^5*d^2-28*a^4*d^3+24*a^3*b*d^3-24*a^2*b^2*d^3+23*a*b^3*d^3+24*b^4*d^3+24*a^3*c*d^3-25*a^2*b*c*d^3-9*a*b^2*c*d^3-43*b^3*c*d^3+15*a^2*c^2*d^3+49*a*b*c^2*d^3+24*b^2*c^2*d^3-20*a*c^3*d^3-30*b*c^3*d^3-20*c^4*d^3+13*a^3*d^4+34*a^2*b*d^4-45*a*b^2*d^4+9*b^3*d^4+9*a^2*c*d^4-31*a*b*c*d^4-6*b^2*c*d^4-16*a*c^2*d^4+9*b*c^2*d^4+24*c^3*d^4+38*a^2*d^5-23*a*b*d^5-35*b^2*d^5+22*a*c*d^5-22*b*c*d^5+46*c^2*d^5+12*a*d^6+21*b*d^6-23*c*d^6-2*d^7,a^3*b^4+34*a^6*c+14*a^5*b*c+34*a^4*b^2*c+43*a^3*b^3*c-26*a^2*b^4*c+13*a*b^5*c+10*b^6*c-43*a^5*c^2+50*a^4*b*c^2-23*a^3*b^2*c^2-a^2*b^3*c^2+39*a*b^4*c^2+50*b^5*c^2+16*a^4*c^3+31*a^3*b*c^3-49*a^2*b^2*c^3+26*a*b^3*c^3-b^4*c^3-5*a^3*c^4+3*a^2*b*c^4-26*a*b^2*c^4-b^3*c^4-24*a^2*c^5-39*a*b*c^5+50*b^2*c^5-13*a*c^6+10*b*c^6-39*a^6*d+35*a^5*b*d+44*a^4*b^2*d-39*a^3*b^3*d-26*a^2*b^4*d-47*a*b^5*d-42*b^6*d+34*a^5*c*d-43*a^4*b*c*d-39*a^3*b^2*c*d+41*a^2*b^3*c*d+32*a*b^4*c*d-10*b^5*c*d+43*a^4*c^2*d+12*a^3*b*c^2*d-43*a^2*b^2*c^2*d+23*a*b^3*c^2*d-46*b^4*c^2*d+12*a^3*c^3*d-10*a^2*b*c^3*d+13*a*b^2*c^3*d-15*b^3*c^3*d-a^2*c^4*d+17*a*b*c^4*d-47*b^2*c^4*d+49*a*c^5*d-31*b*c^5*d-22*c^6*d-28*a^5*d^2-39*a^4*b*d^2+33*a^3*b^2*d^2-40*a^2*b^3*d^2+31*a*b^4*d^2+5*b^5*d^2+42*a^4*c*d^2-a^3*b*c*d^2+37*a^2*b^2*c*d^2-13*a*b^3*c*d^2+b^4*c*d^2+35*a^3*c^2*d^2-9*a^2*b*c^2*d^2+46*a*b^2*c^2*d^2-2*b^3*c^2*d^2+15*a^2*c^3*d^2-48*a*b*c^3*d^2+38*b^2*c^3*d^2-37*a*c^4*d^2-40*b*c^4*d^2+25*c^5*d^2+5*a^4*d^3-4*a^3*b*d^3+30*a^2*b^2*d^3-42*a*b^3*d^3+11*b^4*d^3+10*a^3*c*d^3+34*a^2*b*c*d^3-48*a*b^2*c*d^3+17*b^3*c*d^3-33*a^2*c^2*d^3-12*a*b*c^2*d^3-44*b^2*c^2*d^3-6*a*c^3*d^3+6*b*c^3*d^3-45*c^4*d^3+6*a^3*d^4+8*a^2*b*d^4-22*a*b^2*d^4+23*b^3*d^4-22*a^2*c*d^4-38*a*b*c*d^4+44*b^2*c*d^4-13*a*c^2*d^4-50*b*c^2*d^4+30*c^3*d^4-6*a^2*d^5-46*a*b*d^5+17*b^2*d^5-23*a*c*d^5-10*b*c*d^5+32*c^2*d^5-47*a*d^6+2*b*d^6+20*c*d^6-46*d^7,a^4*b^3+30*a*b^6-49*a^6*c+18*a^5*b*c+37*a^4*b^2*c+44*a^3*b^3*c-27*a^2*b^4*c-a*b^5*c-35*b^6*c-20*a^5*c^2+32*a^4*b*c^2+28*a^3*b^2*c^2-13*a^2*b^3*c^2-32*a*b^4*c^2+27*b^5*c^2-4*a^4*c^3+25*a^3*b*c^3+22*a^2*b^2*c^3-23*a*b^3*c^3-47*b^4*c^3+41*a^3*c^4-25*a^2*b*c^4-34*a*b^2*c^4-47*b^3*c^4-33*a^2*c^5-43*a*b*c^5+27*b^2*c^5-31*a*c^6-35*b*c^6-49*a^6*d+30*a^5*b*d-4*a^4*b^2*d+11*a^3*b^3*d-12*a^2*b^4*d-38*a*b^5*d+45*b^6*d+5*a^5*c*d-45*a^4*b*c*d-42*a^3*b^2*c*d-11*a^2*b^3*c*d+21*a*b^4*c*d+18*b^5*c*d-50*a^4*c^2*d-25*a^3*b*c^2*d+35*a^2*b^2*c^2*d-a*b^3*c^2*d+30*b^4*c^2*d+28*a^3*c^3*d-46*a^2*b*c^3*d-4*a*b^2*c^3*d+32*b^3*c^3*d+21*a^2*c^4*d-34*a*b*c^4*d+27*b^2*c^4*d+11*a*c^5*d-45*b*c^5*d+4*c^6*d+2*a^5*d^2-43*a^4*b*d^2-36*a^3*b^2*d^2+14*a^2*b^3*d^2+35*a*b^4*d^2+8*b^5*d^2+34*a^4*c*d^2-12*a^3*b*c*d^2-a^2*b^2*c*d^2-5*a*b^3*c*d^2+43*b^4*c*d^2+45*a^3*c^2*d^2-34*a^2*b*c^2*d^2+26*a*b^2*c^2*d^2+10*b^3*c^2*d^2-19*a^2*c^3*d^2+5*a*b*c^3*d^2-47*b^2*c^3*d^2+40*a*c^4*d^2+8*b*c^4*d^2+30*c^5*d^2+42*a^4*d^3+27*a^3*b*d^3+31*a^2*b^2*d^3-6*a*b^3*d^3+36*b^4*d^3+37*a^2*b*c*d^3+34*a*b^2*c*d^3-13*b^3*c*d^3+a^2*c^2*d^3+29*a*b*c^2*d^3-b^2*c^2*d^3-11*a*c^3*d^3-21*b*c^3*d^3+32*c^4*d^3+9*a^3*d^4-21*a^2*b*d^4+26*a*b^2*d^4+43*b^3*d^4-42*a^2*c*d^4-2*a*b*c*d^4-34*b^2*c*d^4+10*a*c^2*d^4-26*b*c^2*d^4-50*c^3*d^4+23*a^2*d^5+49*a*b*d^5+28*b^2*d^5-48*a*c*d^5-18*b*c*d^5-2*c^2*d^5-2*a*d^6-30*b*d^6+36*c*d^6-21*d^7,a^5*b^2+9*a*b^6+6*a^6*c+34*a^5*b*c-14*a^4*b^2*c-43*a^3*b^3*c-27*a^2*b^4*c+14*a*b^5*c+9*b^6*c-28*a^5*c^2-10*a^4*b*c^2+39*a^3*b^2*c^2-49*a^2*b^3*c^2-38*a*b^4*c^2+45*b^5*c^2+4*a^4*c^3+5*a^3*b*c^3+15*a^2*b^2*c^3-11*a*b^3*c^3-11*b^4*c^3+24*a^3*c^4-32*a^2*b*c^4-2*a*b^2*c^4-11*b^3*c^4+32*a^2*c^5-38*a*b*c^5+45*b^2*c^5-4*a*c^6+9*b*c^6+23*a^6*d-13*a^5*b*d+8*a^4*b^2*d-46*a^3*b^3*d-9*a^2*b^4*d-8*a*b^5*d+17*b^6*d+a^5*c*d+5*a^4*b*c*d-50*a^3*b^2*c*d+22*a^2*b^3*c*d-34*a*b^4*c*d-49*b^5*c*d+44*a^4*c^2*d+41*a^3*b*c^2*d-44*a^2*b^2*c^2*d-49*a*b^3*c^2*d+37*b^4*c^2*d+45*a^3*c^3*d+12*a^2*b*c^3*d-23*a*b^2*c^3*d-32*b^3*c^3*d-14*a^2*c^4*d+5*a*b*c^4*d+48*b^2*c^4*d+5*a*c^5*d-20*b*c^5*d-c^6*d+5*a^5*d^2-45*a^4*b*d^2+42*a^3*b^2*d^2+50*a^2*b^3*d^2-8*a*b^4*d^2-49*b^5*d^2-35*a^4*c*d^2-25*a^3*b*c*d^2-4*a^2*b^2*c*d^2-26*a*b^3*c*d^2-28*b^4*c*d^2+46*a^3*c^2*d^2+22*a^2*b*c^2*d^2+43*a*b^2*c^2*d^2-4*b^3*c^2*d^2-25*a^2*c^3*d^2+31*a*b*c^3*d^2-31*b^2*c^3*d^2-30*a*c^4*d^2-18*b*c^4*d^2-12*c^5*d^2-33*a^4*d^3-48*a^3*b*d^3-36*a^2*b^2*d^3-6*a*b^3*d^3+8*b^4*d^3+3*a^3*c*d^3-43*a^2*b*c*d^3+34*a*b^2*c*d^3+19*b^3*c*d^3+19*a^2*c^2*d^3-49*a*b*c^2*d^3-2*b^2*c^2*d^3+12*a*c^3*d^3-29*b*c^3*d^3-16*c^4*d^3+27*a^3*d^4+22*a^2*b*d^4+22*a*b^2*d^4-12*b^3*d^4+34*a^2*c*d^4+8*a*b*c*d^4+50*b^2*c*d^4+40*a*c^2*d^4+27*b*c^2*d^4-35*c^3*d^4-30*a^2*d^5+24*a*b*d^5+7*b^2*d^5+16*a*c*d^5+17*b*c*d^5-40*c^2*d^5-47*a*d^6-12*b*d^6+16*c*d^6+6*d^7,a^6*b-45*a*b^6-30*a^6*c-5*a^5*b*c-39*a^4*b^2*c-37*a^3*b^3*c+a^2*b^4*c-14*a*b^5*c-37*b^6*c+49*a^5*c^2+28*a^4*b*c^2+7*a^3*b^2*c^2-10*a^2*b^3*c^2+10*a*b^4*c^2+17*b^5*c^2-34*a^4*c^3+24*a^3*b*c^3-36*a^2*b^2*c^3-13*a*b^3*c^3+34*b^4*c^3-20*a^3*c^4-38*a^2*b*c^4+32*a*b^2*c^4+34*b^3*c^4-13*a^2*c^5+44*a*b*c^5+17*b^2*c^5+20*a*c^6-37*b*c^6+10*a^6*d+26*a^5*b*d+15*a^4*b^2*d+23*a^3*b^3*d+16*a^2*b^4*d+48*a*b^5*d-30*b^6*d-9*a^5*c*d-20*a^4*b*c*d+49*a^3*b^2*c*d-48*a^2*b^3*c*d-36*a*b^4*c*d-21*b^5*c*d+9*a^4*c^2*d-24*a^3*b*c^2*d+42*a^2*b^2*c^2*d+26*a*b^3*c^2*d-46*b^4*c^2*d-50*a^3*c^3*d-11*a^2*b*c^3*d-34*a*b^2*c^3*d+32*b^3*c^3*d-16*a^2*c^4*d-25*a*b*c^4*d+6*b^2*c^4*d+18*a*c^5*d-40*b*c^5*d+41*c^6*d-8*a^5*d^2-27*a^4*b*d^2-48*a^3*b^2*d^2-a^2*b^3*d^2+50*a*b^4*d^2+21*b^5*d^2-48*a^4*c*d^2+4*a^3*b*c*d^2-28*a^2*b^2*c*d^2-4*a*b^3*c*d^2+16*b^4*c*d^2+50*a^3*c^2*d^2+40*a^2*b*c^2*d^2+35*a*b^2*c^2*d^2+29*b^3*c^2*d^2-34*a^2*c^3*d^2-21*a*b*c^3*d^2-b^2*c^3*d^2-9*a*c^4*d^2-29*b*c^4*d^2+6*c^5*d^2+16*a^4*d^3-34*a^3*b*d^3+3*a^2*b^2*d^3+21*a*b^3*d^3+39*b^4*d^3+21*a^3*c*d^3-44*a^2*b*c*d^3-16*a*b^2*c*d^3+b^3*c*d^3-38*a^2*c^2*d^3+18*a*b*c^2*d^3+37*b^2*c^2*d^3-46*a*c^3*d^3+25*b*c^3*d^3-50*c^4*d^3-8*a^3*d^4-24*a^2*b*d^4-2*a*b^2*d^4+6*b^3*d^4+9*a^2*c*d^4+12*a*b*c*d^4+33*b^2*c*d^4-44*a*c^2*d^4+23*b*c^2*d^4-4*c^3*d^4-9*a^2*d^5-2*a*b*d^5-14*b^2*d^5+21*a*c*d^5-16*b*c*d^5-19*c^2*d^5+17*a*d^6-20*b*d^6+11*c*d^6-41*d^7,a^7-10*a*b^6-6*a^6*c-48*a^5*b*c-14*a^4*b^2*c-16*a^3*b^3*c-4*a^2*b^4*c+24*a*b^5*c-10*b^6*c-2*a^5*c^2+23*a^3*b^2*c^2+26*a^2*b^3*c^2+22*a*b^4*c^2-50*b^5*c^2+14*a^4*c^3-7*a^3*b*c^3+a^2*b^2*c^3-49*a*b^3*c^3+b^4*c^3-46*a^3*c^4+9*a^2*b*c^4+10*a*b^2*c^4+b^3*c^4+38*a^2*c^5-26*a*b*c^5-50*b^2*c^5+28*a*c^6-10*b*c^6-7*a^6*d+24*a^5*b*d-8*a^4*b^2*d+23*a^3*b^3*d+9*a^2*b^4*d+28*a*b^5*d-23*b^6*d-42*a^4*b*c*d+24*a^3*b^2*c*d-30*a^2*b^3*c*d-42*a*b^4*c*d-43*b^5*c*d-42*a^4*c^2*d+11*a^3*b*c^2*d+9*a^2*b^2*c^2*d-8*a*b^3*c^2*d+4*b^4*c^2*d+10*a^3*c^3*d+43*a^2*b*c^3*d+3*a*b^2*c^3*d-14*b^3*c^3*d-5*a^2*c^4*d+25*a*b*c^4*d-50*b^2*c^4*d-17*a*c^5*d+35*b*c^5*d+47*c^6*d-4*a^5*d^2-43*a^4*b*d^2+35*a^3*b^2*d^2+19*a^2*b^3*d^2+48*a*b^4*d^2+45*b^5*d^2+3*a^4*c*d^2-46*a^3*b*c*d^2+8*a^2*b^2*c*d^2-35*a*b^3*c*d^2-27*b^4*c*d^2-49*a^3*c^2*d^2+37*a^2*b*c^2*d^2-43*a*b^2*c^2*d^2+32*b^3*c^2*d^2+48*a^2*c^3*d^2+9*a*b*c^3*d^2+b^2*c^3*d^2-31*a*c^4*d^2-23*b*c^4*d^2-21*c^5*d^2+34*a^4*d^3+38*a^3*b*d^3+41*a^2*b^2*d^3-24*a*b^3*d^3+28*b^4*d^3+47*a^3*c*d^3-6*a^2*b*c*d^3+27*a*b^2*c*d^3-43*b^3*c*d^3-24*a^2*c^2*d^3-19*a*b*c^2*d^3-50*b^2*c^2*d^3+31*a*c^3*d^3+40*b*c^3*d^3+19*c^4*d^3+4*a^3*d^4-36*a^2*b*d^4+43*a*b^2*d^4+27*b^3*d^4+49*a^2*c*d^4-27*a*b*c*d^4-39*b^2*c*d^4+46*a*c^2*d^4+40*b*c^2*d^4+5*c^3*d^4-12*a^2*d^5-5*a*b*d^5+16*b^2*d^5-26*a*c*d^5-31*b*c*d^5-38*c^2*d^5+17*a*d^6-11*b*d^6-7*c*d^6-39*d^7,b*c*d^6-21*c^2*d^6+36*a*d^7-34*b*d^7-40*c*d^7-11*d^8,a*c*d^6-24*c^2*d^6+5*a*d^7-7*b*d^7+21*c*d^7-43*d^8,b^2*d^6+20*c^2*d^6+6*a*d^7-30*b*d^7+25*c*d^7+4*d^8,a*b*d^6+23*c^2*d^6-43*a*d^7+47*b*d^7+42*c*d^7+29*d^8,a^2*d^6+49*c^2*d^6+6*a*d^7-35*b*d^7+19*c*d^7-11*d^8,c^3*d^5-38*c^2*d^6+47*a*d^7+35*b*d^7+46*c*d^7+21*d^8,b*c^2*d^5+41*c^2*d^6-8*a*d^7+8*b*d^7+46*c*d^7+42*d^8,a*c^2*d^5+44*c^2*d^6+10*a*d^7-36*b*d^7-21*c*d^7+28*d^8,b^2*c*d^5+9*c^2*d^6+35*a*d^7+20*b*d^7+49*c*d^7-47*d^8,a*b*c*d^5+44*c^2*d^6+24*a*d^7-12*b*d^7+24*c*d^7-5*d^8,a^2*c*d^5-9*c^2*d^6-34*a*d^7+27*b*d^7-49*c*d^7+d^8,b^3*d^5+21*c^2*d^6-37*a*d^7-13*b*d^7-48*c*d^7+25*d^8,a*b^2*d^5+4*c^2*d^6-8*a*d^7-42*b*d^7-31*c*d^7+21*d^8,a^2*b*d^5+26*c^2*d^6-47*a*d^7-37*b*d^7+24*c*d^7+6*d^8,a^3*d^5-32*c^2*d^6-31*a*d^7+26*b*d^7-35*c*d^7-39*d^8,c^4*d^4+25*c^2*d^6+35*a*d^7+24*b*d^7+32*c*d^7-46*d^8,b*c^3*d^4+10*c^2*d^6-9*a*d^7-27*b*d^7-17*c*d^7+11*d^8,a*c^3*d^4-41*c^2*d^6+5*a*d^7-18*b*d^7-43*c*d^7-25*d^8,b^2*c^2*d^4-9*c^2*d^6+15*a*d^7-7*b*d^7-27*c*d^7-40*d^8,a*b*c^2*d^4-4*c^2*d^6+25*a*d^7-9*b*d^7-41*c*d^7-11*d^8,a^2*c^2*d^4+15*c^2*d^6-5*a*d^7-34*b*d^7-11*c*d^7-29*d^8,b^3*c*d^4+49*c^2*d^6-24*a*d^7-8*b*d^7+7*c*d^7-46*d^8,a*b^2*c*d^4-20*c^2*d^6-4*a*d^7+32*b*d^7-42*c*d^7-d^8,a^2*b*c*d^4+15*c^2*d^6+31*a*d^7+16*b*d^7-25*c*d^7+29*d^8,a^3*c*d^4-48*c^2*d^6-36*a*d^7-10*b*d^7+4*c*d^7+27*d^8,b^4*d^4+26*c^2*d^6-25*a*d^7-3*b*d^7-45*c*d^7-26*d^8,a*b^3*d^4+c^2*d^6-21*a*d^7-13*b*d^7-20*c*d^7+16*d^8,a^2*b^2*d^4+22*c^2*d^6-27*a*d^7-23*b*d^7-5*c*d^7-27*d^8,a^3*b*d^4+2*c^2*d^6-29*a*d^7-6*b*d^7+26*c*d^7-46*d^8,a^4*d^4-40*c^2*d^6-9*a*d^7-24*b*d^7+2*c*d^7-37*d^8,c^5*d^3+14*c^2*d^6+40*a*d^7+21*b*d^7+50*c*d^7+31*d^8,b*c^4*d^3-21*c^2*d^6-2*a*d^7-9*b*d^7-28*c*d^7+20*d^8,a*c^4*d^3-39*c^2*d^6+38*a*d^7-24*b*d^7-42*c*d^7-30*d^8,b^2*c^3*d^3+19*c^2*d^6-50*a*d^7-33*b*d^7+16*c*d^7-45*d^8,a*b*c^3*d^3-6*c^2*d^6-38*a*d^7+35*b*d^7+32*c*d^7-12*d^8,a^2*c^3*d^3+44*c^2*d^6+35*a*d^7+42*b*d^7-10*c*d^7-48*d^8,b^3*c^2*d^3+33*c^2*d^6-7*a*d^7-41*b*d^7-3*c*d^7-33*d^8,a*b^2*c^2*d^3-21*c^2*d^6-22*a*d^7-23*b*d^7+24*c*d^7+47*d^8,a^2*b*c^2*d^3+c^2*d^6-32*a*d^7-34*b*d^7-42*c*d^7+7*d^8,a^3*c^2*d^3+6*c^2*d^6-31*a*d^7-26*b*d^7+19*c*d^7-49*d^8,b^4*c*d^3+6*c^2*d^6-24*a*d^7+10*b*d^7-18*c*d^7-4*d^8,a*b^3*c*d^3+46*c^2*d^6+41*a*d^7+7*b*d^7+8*c*d^7-28*d^8,a^2*b^2*c*d^3+33*c^2*d^6-15*a*d^7-11*b*d^7+38*c*d^7+14*d^8,a^3*b*c*d^3-29*c^2*d^6-4*a*d^7-32*b*d^7+13*c*d^7-3*d^8,a^4*c*d^3-34*c^2*d^6+5*a*d^7+29*b*d^7-15*c*d^7-48*d^8,b^5*d^3-42*c^2*d^6+33*a*d^7-49*b*d^7+33*c*d^7-43*d^8,a*b^4*d^3+25*c^2*d^6-11*a*d^7-16*b*d^7+32*c*d^7-2*d^8,a^2*b^3*d^3-36*c^2*d^6-47*a*d^7-16*b*d^7+19*c*d^7+9*d^8,a^3*b^2*d^3-30*c^2*d^6-21*a*d^7-6*b*d^7+16*c*d^7-14*d^8,a^4*b*d^3+47*c^2*d^6-16*a*d^7-13*b*d^7+21*c*d^7+30*d^8,a^5*d^3-2*c^2*d^6+40*a*d^7+34*b*d^7+14*c*d^7-50*d^8,c^6*d^2-4*c^2*d^6-41*a*d^7+46*b*d^7+17*c*d^7+19*d^8,b*c^5*d^2-49*c^2*d^6+5*a*d^7-31*b*d^7+30*c*d^7+28*d^8,a*c^5*d^2-12*c^2*d^6-23*a*d^7-39*b*d^7+6*c*d^7-27*d^8,b^2*c^4*d^2-12*c^2*d^6-30*a*d^7+13*b*d^7-42*c*d^7+38*d^8,a*b*c^4*d^2-31*c^2*d^6+5*a*d^7-41*b*d^7-24*c*d^7,a^2*c^4*d^2-c^2*d^6+4*a*d^7+21*b*d^7+19*c*d^7-34*d^8,b^3*c^3*d^2-50*c^2*d^6-11*a*d^7+24*b*d^7+24*c*d^7-44*d^8,a*b^2*c^3*d^2+2*c^2*d^6-42*a*d^7-17*b*d^7-33*c*d^7-10*d^8,a^2*b*c^3*d^2+20*c^2*d^6+29*a*d^7+35*b*d^7-31*c*d^7-35*d^8,a^3*c^3*d^2+35*c^2*d^6-13*a*d^7+20*b*d^7-15*c*d^7-45*d^8,b^4*c^2*d^2+c^2*d^6+36*a*d^7-42*b*d^7+32*c*d^7+16*d^8,a*b^3*c^2*d^2-9*c^2*d^6-43*a*d^7-5*b*d^7-17*c*d^7+50*d^8,a^2*b^2*c^2*d^2-36*c^2*d^6+31*a*d^7+4*b*d^7-26*c*d^7-11*d^8,a^3*b*c^2*d^2+15*c^2*d^6+40*a*d^7-18*b*d^7-31*c*d^7+43*d^8,a^4*c^2*d^2+41*c^2*d^6-49*a*d^7+37*b*d^7+47*c*d^7-48*d^8,b^5*c*d^2-49*c^2*d^6+15*a*d^7+48*b*d^7+22*c*d^7+38*d^8,a*b^4*c*d^2+12*c^2*d^6+16*a*d^7-22*b*d^7-c*d^7+29*d^8,a^2*b^3*c*d^2+31*c^2*d^6+19*a*d^7+45*b*d^7-6*c*d^7+42*d^8,a^3*b^2*c*d^2+29*c^2*d^6-39*a*d^7+25*b*d^7-48*c*d^7-d^8,a^4*b*c*d^2-31*c^2*d^6+24*a*d^7-2*b*d^7+36*c*d^7+37*d^8,a^5*c*d^2+33*c^2*d^6-46*a*d^7-41*b*d^7-29*c*d^7-12*d^8,b^6*d^2-39*c^2*d^6+35*a*d^7-8*b*d^7+35*c*d^7+47*d^8,a*b^5*d^2-38*c^2*d^6-11*a*d^7-37*b*d^7-7*c*d^7-5*d^8,a^2*b^4*d^2+29*c^2*d^6+36*a*d^7-29*b*d^7+20*c*d^7+39*d^8,a^3*b^3*d^2-44*c^2*d^6+43*a*d^7-50*b*d^7-24*c*d^7-16*d^8,a^4*b^2*d^2+20*c^2*d^6+33*a*d^7+6*b*d^7+47*c*d^7+40*d^8,a^5*b*d^2-10*c^2*d^6+25*a*d^7-8*b*d^7-14*c*d^7+16*d^8,a^6*d^2+48*c^2*d^6+14*a*d^7+32*b*d^7+17*c*d^7+13*d^8,c^7*d+38*c^2*d^6-39*a*d^7+22*b*d^7+15*c*d^7-d^8,b*c^6*d+9*c^2*d^6+37*a*d^7+12*b*d^7+27*c*d^7+3*d^8,a*c^6*d-5*c^2*d^6+34*a*d^7+15*b*d^7+2*c*d^7-21*d^8,b^2*c^5*d+35*c^2*d^6+27*a*d^7+13*b*d^7-39*c*d^7+8*d^8,a*b*c^5*d-34*c^2*d^6-18*a*d^7-21*b*d^7-31*c*d^7+46*d^8,a^2*c^5*d-16*c^2*d^6-6*a*d^7-18*b*d^7+3*c*d^7+47*d^8,b^3*c^4*d-46*c^2*d^6+4*a*d^7-38*b*d^7-29*c*d^7-4*d^8,a*b^2*c^4*d-35*c^2*d^6-14*a*d^7-32*b*d^7-40*c*d^7-35*d^8,a^2*b*c^4*d+23*c^2*d^6-44*a*d^7-3*b*d^7+4*c*d^7-4*d^8,a^3*c^4*d+24*c^2*d^6-7*a*d^7-44*b*d^7-16*c*d^7+10*d^8,b^4*c^3*d+43*c^2*d^6+12*a*d^7+43*b*d^7-49*c*d^7-23*d^8,a*b^3*c^3*d+22*c^2*d^6+6*a*d^7+2*b*d^7-9*c*d^7,a^2*b^2*c^3*d+4*c^2*d^6+21*a*d^7-24*b*d^7-26*c*d^7+33*d^8,a^3*b*c^3*d+13*c^2*d^6-18*a*d^7+31*b*d^7-28*c*d^7+2*d^8,a^4*c^3*d+10*c^2*d^6-14*a*d^7+30*b*d^7-40*c*d^7+33*d^8,b^5*c^2*d-35*c^2*d^6-33*a*d^7+7*b*d^7+13*c*d^7+26*d^8,a*b^4*c^2*d-49*c^2*d^6+9*a*d^7+20*b*d^7+11*c*d^7-32*d^8,a^2*b^3*c^2*d+33*c^2*d^6-43*a*d^7-27*b*d^7-31*c*d^7-41*d^8,a^3*b^2*c^2*d-6*c^2*d^6+23*a*d^7+20*b*d^7-8*c*d^7-6*d^8,a^4*b*c^2*d+10*c^2*d^6-24*a*d^7+30*b*d^7+42*c*d^7-23*d^8,a^5*c^2*d+12*c^2*d^6+20*a*d^7+24*b*d^7-9*c*d^7-9*d^8,b^6*c*d-12*c^2*d^6+36*a*d^7+4*b*d^7-12*c*d^7+26*d^8,a*b^5*c*d-19*c^2*d^6-39*a*d^7-26*b*d^7-4*c*d^7+10*d^8,a^2*b^4*c*d+38*c^2*d^6-6*a*d^7+6*b*d^7+41*c*d^7+49*d^8,a^3*b^3*c*d-34*c^2*d^6-42*a*d^7+22*b*d^7-26*c*d^7-13*d^8,a^4*b^2*c*d+14*c^2*d^6+40*a*d^7+39*b*d^7-34*d^8,a^5*b*c*d-8*c^2*d^6+45*a*d^7-35*b*d^7+48*c*d^7+47*d^8,a^6*c*d-6*c^2*d^6-24*a*d^7-2*b*d^7-9*c*d^7+7*d^8,b^7*d+34*c^2*d^6-14*a*d^7+46*b*d^7-50*c*d^7+26*d^8,a*b^6*d+6*c^2*d^6+23*a*d^7-27*b*d^7-25*c*d^7-2*d^8,c^8+43*c^2*d^6+11*b*d^7-39*c*d^7-30*d^8,b*c^7-44*c^2*d^6-4*a*d^7-10*b*d^7+31*c*d^7+42*d^8,a*c^7-6*a*d^7+31*b*d^7+37*c*d^7-41*d^8,b^2*c^6-11*c^2*d^6-35*a*d^7+32*b*d^7-25*c*d^7-21*d^8,a*b*c^6+2*c^2*d^6+43*a*d^7-48*b*d^7-49*c*d^7-19*d^8,a^2*c^6-20*c^2*d^6-11*a*d^7-35*b*d^7-33*c*d^7+28*d^8,b^3*c^5+4*c^2*d^6-7*a*d^7-21*b*d^7-14*c*d^7+48*d^8,a*b^2*c^5+17*c^2*d^6+45*a*d^7-32*b*d^7+29*c*d^7+38*d^8,a^2*b*c^5-13*c^2*d^6+46*a*d^7+4*b*d^7-18*c*d^7+19*d^8,a^3*c^5-23*c^2*d^6-a*d^7-3*b*d^7-15*c*d^7+19*d^8,b^4*c^4-50*c^2*d^6+39*a*d^7+49*b*d^7+47*c*d^7+7*d^8,a*b^3*c^4-33*c^2*d^6+10*a*d^7+32*b*d^7+21*c*d^7-39*d^8,a^2*b^2*c^4+23*c^2*d^6+27*a*d^7-17*b*d^7+29*c*d^7+9*d^8,a^3*b*c^4-47*c^2*d^6-43*a*d^7-47*b*d^7-34*c*d^7-23*d^8,a^4*c^4-6*c^2*d^6+7*a*d^7+38*b*d^7-27*c*d^7-9*d^8,b^5*c^3-47*c^2*d^6+18*a*d^7-44*b*d^7-4*c*d^7-18*d^8,a*b^4*c^3+30*c^2*d^6+36*a*d^7+25*b*d^7+42*c*d^7+d^8,a^2*b^3*c^3+10*c^2*d^6+31*a*d^7+45*b*d^7-44*c*d^7+37*d^8,a^3*b^2*c^3-41*c^2*d^6-15*a*d^7-34*b*d^7-22*c*d^7+28*d^8,a^4*b*c^3+19*c^2*d^6-23*a*d^7+18*b*d^7-13*c*d^7-48*d^8,a^5*c^3+16*c^2*d^6+22*a*d^7-31*b*d^7+33*c*d^7+15*d^8,b^6*c^2-42*c^2*d^6-10*a*d^7-16*b*d^7-46*c*d^7+42*d^8,a*b^5*c^2-23*c^2*d^6+34*a*d^7-37*b*d^7+2*c*d^7+10*d^8,a^2*b^4*c^2-45*c^2*d^6-5*a*d^7+43*b*d^7-18*c*d^7+7*d^8,a^3*b^3*c^2+36*c^2*d^6+19*a*d^7+21*b*d^7+46*c*d^7-24*d^8,a^4*b^2*c^2-17*c^2*d^6+30*a*d^7-39*b*d^7-39*c*d^7-24*d^8,a^5*b*c^2+10*c^2*d^6-24*a*d^7-36*b*d^7-14*c*d^7+26*d^8,a^6*c^2+47*c^2*d^6-41*a*d^7+32*b*d^7+6*c*d^7+42*d^8,b^7*c+44*c^2*d^6-6*a*d^7+5*b*d^7+20*c*d^7+50*d^8,a*b^6*c+29*c^2*d^6-16*a*d^7+45*b*d^7-3*c*d^7+14*d^8,b^8+48*c^2*d^6-40*a*d^7-44*b*d^7-10*c*d^7-23*d^8,a*b^7-32*c^2*d^6-41*a*d^7-11*b*d^7+50*c*d^7+13*d^8,d^9,c*d^8,b*d^8,a*d^8,c^2*d^7; TestSSresAttribs2tr(M, "AGR@101n3d010s010%3"); kill AGR; ring AGR = (101), (a,b,c,d,e,f,g,h), dp; AGR; // AGR@101n7d005s010%2, medium: <= 2 ideal M = f*h-g*h,e*h-g*h,d*h-g*h,c*h-g*h,b*h-g*h,a*h-g*h,e*g+48*f*g-49*g*h,d*g+5*f*g-6*g*h,c*g+49*f*g-50*g*h,b*g-7*f*g+6*g*h,a*g-50*f*g+49*g*h,e*f-20*f*g+19*g*h,d*f+40*f*g-41*g*h,c*f-12*f*g+11*g*h,b*f+45*f*g-46*g*h,a*f+4*f*g-5*g*h,d*e-f*g,c*e-30*f*g+29*g*h,b*e-39*f*g+38*g*h,a*e+10*f*g-11*g*h,c*d-41*f*g+40*g*h,b*d-23*f*g+22*g*h,a*d-20*f*g+19*g*h,b*c+17*f*g-18*g*h,a*c+6*f*g-7*g*h,a*b+28*f*g-29*g*h,g^2*h-g*h^2,f^2*g-8*f*g^2+7*g*h^2,g*h^4+50*h^5,g^5+41*h^5,f*g^4-18*h^5,f^5+29*h^5,e^5+6*h^5,d^5-23*h^5,c^5-32*h^5, b^5+17*h^5,a^5+17*h^5,h^6; TestSSresAttribs2tr(M, "AGR@101n7d005s010%2"); kill AGR; // from Andreas...tooo long!? ring AGR = (101), (a,b,c,d,e), dp; AGR; // AGR101n4d007s021%4 ideal M = b^3*c*d-44*a*b*c^2*d-23*b^2*c^2*d-17*a*c^3*d+25*b*c^3*d-28*c^4*d+21*a^3*d^2+28*a^2*b*d^2+45*a*b^2*d^2-45*b^3*d^2+39*a^2*c*d^2+50*a*b*c*d^2-31*b^2*c*d^2+25*a*c^2*d^2-42*b*c^2*d^2-6*c^3*d^2+10*a^2*d^3-18*a*b*d^3-21*b^2*d^3-9*a*c*d^3+37*b*c*d^3-18*c^2*d^3+5*a*d^4+b*d^4-18*c*d^4+23*d^5-5*a^4*e+6*a^3*b*e-21*a^2*b^2*e-28*a*b^3*e+11*b^4*e+19*a^3*c*e+29*a^2*b*c*e-25*a*b^2*c*e-8*b^3*c*e+17*a^2*c^2*e+45*a*b*c^2*e-28*b^2*c^2*e+22*a*c^3*e+33*b*c^3*e+27*c^4*e-50*a^3*d*e+11*a^2*b*d*e-45*a*b^2*d*e-5*b^3*d*e-2*a^2*c*d*e-30*a*b*c*d*e-17*b^2*c*d*e-45*a*c^2*d*e+12*b*c^2*d*e-8*c^3*d*e+12*a^2*d^2*e+a*b*d^2*e-13*b^2*d^2*e-20*a*c*d^2*e+47*b*c*d^2*e-10*c^2*d^2*e+8*a*d^3*e+32*b*d^3*e-8*c*d^3*e+47*d^4*e+43*a^3*e^2+23*a^2*b*e^2+12*a*b^2*e^2+25*b^3*e^2-23*a^2*c*e^2-12*a*b*c*e^2+5*b^2*c*e^2-25*a*c^2*e^2-8*b*c^2*e^2-48*c^3*e^2+22*a^2*d*e^2+27*a*b*d*e^2-21*b^2*d*e^2+35*a*c*d*e^2-5*b*c*d*e^2+14*c^2*d*e^2+3*a*d^2*e^2-35*b*d^2*e^2+24*c*d^2*e^2-12*d^3*e^2-30*a^2*e^3+5*a*b*e^3-29*b^2*e^3-17*a*c*e^3-41*b*c*e^3-41*c^2*e^3-a*d*e^3-41*b*d*e^3+6*c*d*e^3+24*d^2*e^3+38*a*e^4+46*b*e^4+5*c*e^4-48*d*e^4-33*e^5, a*b^2*c*d-8*a^2*c^2*d+35*a*b*c^2*d-9*b^2*c^2*d+41*a*c^3*d+11*b*c^3*d+36*c^4*d-36*a^3*d^2-11*a^2*b*d^2-45*a*b^2*d^2+20*b^3*d^2-38*a^2*c*d^2-21*a*b*c*d^2-26*b^2*c*d^2+26*a*c^2*d^2+45*b*c^2*d^2+2*c^3*d^2+35*a^2*d^3-15*a*b*d^3-30*b^2*d^3-37*a*c*d^3+3*b*c*d^3+29*c^2*d^3-39*a*d^4-13*b*d^4+42*c*d^4+50*d^5-47*a^4*e+a^3*b*e-10*a^2*b^2*e+10*a*b^3*e-19*b^4*e+47*a^3*c*e+29*a^2*b*c*e+33*a*b^2*c*e-7*b^3*c*e+29*a^2*c^2*e-2*b^2*c^2*e-19*a*c^3*e+16*b*c^3*e+44*c^4*e+47*a^3*d*e-14*a^2*b*d*e+48*a*b^2*d*e-21*b^3*d*e+13*a^2*c*d*e+4*a*b*c*d*e+20*b^2*c*d*e-3*a*c^2*d*e-34*b*c^2*d*e-2*c^3*d*e+10*a^2*d^2*e+38*a*b*d^2*e+18*b^2*d^2*e-a*c*d^2*e+24*b*c*d^2*e-11*c^2*d^2*e+24*a*d^3*e-10*b*d^3*e+15*c*d^3*e-44*d^4*e+6*a^3*e^2-7*a^2*b*e^2+30*a*b^2*e^2+25*b^3*e^2+40*a^2*c*e^2+33*a*b*c*e^2+26*b^2*c*e^2-2*a*c^2*e^2-2*b*c^2*e^2+32*c^3*e^2+31*a^2*d*e^2+50*a*b*d*e^2-5*b^2*d*e^2-43*a*c*d*e^2+37*b*c*d*e^2-16*c^2*d*e^2+39*a*d^2*e^2+15*b*d^2*e^2+35*c*d^2*e^2-47*d^3*e^2+38*a^2*e^3+7*a*b*e^3+16*b^2*e^3+43*a*c*e^3+23*b*c*e^3+9*c^2*e^3+37*a*d*e^3-18*b*d*e^3+32*c*d*e^3-2*d^2*e^3-31*a*e^4+18*b*e^4-35*c*e^4+9*d*e^4-49*e^5, a^2*b*c*d+7*a^2*c^2*d-15*a*b*c^2*d+20*b^2*c^2*d+8*a*c^3*d-14*b*c^3*d+34*c^4*d+15*a^3*d^2+37*a^2*b*d^2-11*a*b^2*d^2-8*b^3*d^2-15*a^2*c*d^2-22*a*b*c*d^2-30*b^2*c*d^2+23*a*c^2*d^2+34*b*c^2*d^2+41*c^3*d^2-27*a^2*d^3+24*b^2*d^3-15*a*c*d^3+20*b*c*d^3-16*c^2*d^3-31*a*d^4+18*b*d^4-21*c*d^4+19*d^5+20*a^4*e+38*a^3*b*e-7*a^2*b^2*e+8*a*b^3*e-35*b^4*e+30*a^3*c*e-13*a^2*b*c*e+39*a*b^2*c*e-50*b^3*c*e+50*a^2*c^2*e-21*a*b*c^2*e+17*b^2*c^2*e-23*a*c^3*e+32*b*c^3*e-43*c^4*e-39*a^3*d*e+16*a^2*b*d*e+25*a*b^2*d*e-12*b^3*d*e+50*a^2*c*d*e+4*a*b*c*d*e-17*b^2*c*d*e-28*a*c^2*d*e-5*b*c^2*d*e+13*c^3*d*e+23*a^2*d^2*e+17*a*b*d^2*e+14*b^2*d^2*e-2*a*c*d^2*e+3*b*c*d^2*e+20*c^2*d^2*e-14*a*d^3*e+5*b*d^3*e-c*d^3*e+29*d^4*e-42*a^3*e^2-38*a^2*b*e^2-44*a*b^2*e^2-4*b^3*e^2+29*a^2*c*e^2-19*a*b*c*e^2+38*b^2*c*e^2+3*a*c^2*e^2-46*b*c^2*e^2-46*c^3*e^2-44*a^2*d*e^2+16*a*b*d*e^2-38*b^2*d*e^2+12*a*c*d*e^2+45*b*c*d*e^2-48*c^2*d*e^2+34*a*d^2*e^2+32*b*d^2*e^2+37*c*d^2*e^2+34*d^3*e^2+30*a^2*e^3+45*a*b*e^3+8*b^2*e^3+40*a*c*e^3-37*b*c*e^3-16*c^2*e^3-50*a*d*e^3-18*b*d*e^3-9*c*d*e^3-37*a*e^4-22*b*e^4+5*c*e^4+d*e^4+9*e^5, a^3*c*d-44*a^2*c^2*d-38*a*b*c^2*d-26*b^2*c^2*d-12*a*c^3*d-21*b*c^3*d+43*c^4*d-22*a^3*d^2-23*a^2*b*d^2+32*a*b^2*d^2+45*b^3*d^2-48*a^2*c*d^2-40*a*b*c*d^2+3*b^2*c*d^2+2*a*c^2*d^2-27*b*c^2*d^2-35*c^3*d^2+33*a^2*d^3-11*a*b*d^3-5*b^2*d^3+8*a*c*d^3-42*b*c*d^3+41*c^2*d^3-41*b*d^4+29*c*d^4+5*d^5+32*a^4*e-46*a^3*b*e-46*a^2*b^2*e+19*a*b^3*e-14*b^4*e-24*a^3*c*e+3*a^2*b*c*e-22*a*b^2*c*e+49*b^3*c*e-47*a^2*c^2*e+27*a*b*c^2*e+48*b^2*c^2*e+20*a*c^3*e-3*b*c^3*e-11*c^4*e-21*a^3*d*e+a^2*b*d*e-13*a*b^2*d*e-33*b^3*d*e+13*a^2*c*d*e-3*a*b*c*d*e+15*b^2*c*d*e+35*a*c^2*d*e-20*b*c^2*d*e+45*c^3*d*e-14*a^2*d^2*e+11*a*b*d^2*e-38*b^2*d^2*e+40*a*c*d^2*e-30*b*c*d^2*e+14*c^2*d^2*e-26*a*d^3*e-43*b*d^3*e+38*c*d^3*e-24*d^4*e-10*a^3*e^2-31*a^2*b*e^2+a*b^2*e^2-34*b^3*e^2+5*a^2*c*e^2-12*a*b*c*e^2-6*b^2*c*e^2-30*a*c^2*e^2-b*c^2*e^2+31*c^3*e^2+22*a^2*d*e^2-26*a*b*d*e^2+9*b^2*d*e^2+32*a*c*d*e^2+24*b*c*d*e^2-36*c^2*d*e^2-a*d^2*e^2-14*b*d^2*e^2-24*c*d^2*e^2+7*d^3*e^2+38*a^2*e^3+35*a*b*e^3+16*b^2*e^3+25*a*c*e^3-30*b*c*e^3+30*c^2*e^3-25*a*d*e^3+3*b*d*e^3+40*c*d*e^3+16*d^2*e^3+45*a*e^4+15*b*e^4-12*c*e^4+42*d*e^4+7*e^5, b^4*d+14*a^2*c^2*d+2*a*b*c^2*d+34*b^2*c^2*d-12*a*c^3*d+20*b*c^3*d-20*c^4*d+4*a^3*d^2-47*a^2*b*d^2-34*a*b^2*d^2-22*b^3*d^2+23*a^2*c*d^2-22*a*b*c*d^2-31*b^2*c*d^2-24*a*c^2*d^2+39*b*c^2*d^2-37*c^3*d^2-39*a^2*d^3-49*a*b*d^3-41*b^2*d^3-44*a*c*d^3+33*b*c*d^3-14*c^2*d^3-49*a*d^4+20*b*d^4+37*c*d^4+34*d^5+50*a^4*e-31*a^3*b*e-18*a^2*b^2*e-16*a*b^3*e+45*b^4*e+32*a^3*c*e+43*a^2*b*c*e-27*a*b^2*c*e+5*b^3*c*e+39*a^2*c^2*e+33*a*b*c^2*e-16*b^2*c^2*e-6*a*c^3*e-35*b*c^3*e-4*c^4*e-19*a^3*d*e+25*a^2*b*d*e-20*a*b^2*d*e+6*b^3*d*e-46*a^2*c*d*e-8*a*b*c*d*e+5*b^2*c*d*e+2*a*c^2*d*e-39*b*c^2*d*e-30*c^3*d*e+50*a^2*d^2*e-3*a*b*d^2*e-22*b^2*d^2*e+42*a*c*d^2*e-9*b*c*d^2*e+17*c^2*d^2*e+33*a*d^3*e+29*b*d^3*e-10*c*d^3*e+5*d^4*e+15*a^3*e^2+12*a^2*b*e^2-12*a*b^2*e^2+17*b^3*e^2+26*a^2*c*e^2+23*a*b*c*e^2+4*b^2*c*e^2-8*a*c^2*e^2+49*b*c^2*e^2-25*c^3*e^2-24*a^2*d*e^2-19*a*b*d*e^2+26*b^2*d*e^2+38*a*c*d*e^2+48*b*c*d*e^2-28*c^2*d*e^2-15*a*d^2*e^2+31*b*d^2*e^2-47*c*d^2*e^2-5*d^3*e^2-28*a^2*e^3+46*a*b*e^3-25*b^2*e^3-25*a*c*e^3-42*b*c*e^3-39*c^2*e^3-22*a*d*e^3+7*b*d*e^3+4*c*d*e^3-9*d^2*e^3+50*a*e^4-39*b*e^4+44*c*e^4+28*d*e^4+36*e^5, a*b^3*d-32*a^2*c^2*d-43*a*b*c^2*d-38*b^2*c^2*d-33*a*c^3*d-34*b*c^3*d+15*c^4*d-10*a^3*d^2+20*a^2*b*d^2+23*a*b^2*d^2-6*b^3*d^2-46*a^2*c*d^2-29*a*b*c*d^2-20*b^2*c*d^2+17*a*c^2*d^2-42*b*c^2*d^2+27*c^3*d^2-15*a^2*d^3-27*a*b*d^3+43*b^2*d^3-a*c*d^3+45*b*c*d^3+7*c^2*d^3+4*a*d^4-5*b*d^4-13*c*d^4-26*d^5-24*a^4*e-5*a^2*b^2*e-27*a*b^3*e-23*b^4*e+9*a^3*c*e+33*a^2*b*c*e+25*a*b^2*c*e+39*b^3*c*e-30*a^2*c^2*e-33*a*b*c^2*e-37*b^2*c^2*e-13*a*c^3*e+49*b*c^3*e-30*c^4*e+8*a^3*d*e+20*a^2*b*d*e+18*a*b^2*d*e-34*b^3*d*e-19*a^2*c*d*e+39*a*b*c*d*e+21*b^2*c*d*e+12*a*c^2*d*e-15*b*c^2*d*e+39*c^3*d*e+34*a^2*d^2*e+49*a*b*d^2*e-10*b^2*d^2*e-46*a*c*d^2*e+18*b*c*d^2*e-6*c^2*d^2*e+9*a*d^3*e+30*b*d^3*e+20*c*d^3*e+3*d^4*e-15*a^3*e^2-18*a^2*b*e^2+5*a*b^2*e^2+14*b^3*e^2+19*a^2*c*e^2+30*a*b*c*e^2-b^2*c*e^2+33*a*c^2*e^2+41*b*c^2*e^2-7*c^3*e^2+12*a^2*d*e^2-13*a*b*d*e^2-3*b^2*d*e^2-49*a*c*d*e^2-17*b*c*d*e^2+29*c^2*d*e^2-19*a*d^2*e^2-38*b*d^2*e^2-10*c*d^2*e^2+50*d^3*e^2-17*a^2*e^3+47*a*b*e^3-7*b^2*e^3-25*a*c*e^3+29*b*c*e^3-41*c^2*e^3-35*a*d*e^3+b*d*e^3+32*c*d*e^3-15*d^2*e^3+9*a*e^4+22*c*e^4+12*d*e^4+36*e^5, a^2*b^2*d-a^2*c^2*d-5*a*b*c^2*d+40*b^2*c^2*d+4*a*c^3*d+35*b*c^3*d+42*c^4*d-23*a^3*d^2-34*a^2*b*d^2+4*a*b^2*d^2+27*b^3*d^2+38*a^2*c*d^2-47*a*b*c*d^2+50*b^2*c*d^2+17*a*c^2*d^2+8*c^3*d^2+26*a^2*d^3-32*a*b*d^3+3*b^2*d^3+16*a*c*d^3-47*b*c*d^3-41*c^2*d^3-22*a*d^4-47*b*d^4-17*c*d^4-43*d^5-49*a^4*e+6*a^3*b*e-46*a^2*b^2*e+30*a*b^3*e-21*b^4*e+30*a^3*c*e+17*a^2*b*c*e+39*a*b^2*c*e+37*b^3*c*e+36*a^2*c^2*e+21*a*b*c^2*e-36*b^2*c^2*e-2*a*c^3*e+18*b*c^3*e-49*c^4*e-47*a^3*d*e+35*a^2*b*d*e+10*a*b^2*d*e+22*b^3*d*e-10*a^2*c*d*e-24*a*b*c*d*e-43*b^2*c*d*e-11*a*c^2*d*e+39*b*c^2*d*e+14*c^3*d*e-15*a^2*d^2*e+36*a*b*d^2*e+42*b^2*d^2*e+32*a*c*d^2*e+7*b*c*d^2*e-4*c^2*d^2*e-13*a*d^3*e+39*b*d^3*e+20*c*d^3*e+7*d^4*e+49*a^3*e^2+39*a^2*b*e^2-12*a*b^2*e^2+36*b^3*e^2+12*a^2*c*e^2-45*a*b*c*e^2+47*b^2*c*e^2+16*a*c^2*e^2+21*b*c^2*e^2+2*c^3*e^2+43*a^2*d*e^2+16*a*b*d*e^2+15*b^2*d*e^2+44*a*c*d*e^2+47*b*c*d*e^2+6*c^2*d*e^2+29*a*d^2*e^2-10*b*d^2*e^2-14*c*d^2*e^2+40*d^3*e^2+10*a^2*e^3-2*a*b*e^3-12*b^2*e^3-11*a*c*e^3+4*b*c*e^3+c^2*e^3-41*a*d*e^3-33*b*d*e^3+13*c*d*e^3+32*d^2*e^3-43*a*e^4+42*b*e^4-4*c*e^4-36*d*e^4, a^3*b*d-15*a^2*c^2*d-32*a*b*c^2*d+24*b^2*c^2*d+48*a*c^3*d+6*b*c^3*d-40*a^3*d^2+34*a^2*b*d^2+29*a*b^2*d^2+18*b^3*d^2-17*a^2*c*d^2+34*a*b*c*d^2+5*b^2*c*d^2-31*a*c^2*d^2-29*b*c^2*d^2-12*c^3*d^2+11*a^2*d^3+8*a*b*d^3+3*b^2*d^3-33*a*c*d^3-34*b*c*d^3-12*c^2*d^3-48*a*d^4+18*b*d^4+41*c*d^4-45*d^5-22*a^4*e+a^3*b*e-25*a^2*b^2*e+3*a*b^3*e+49*b^4*e-27*a^3*c*e-42*a^2*b*c*e+2*a*b^2*c*e+3*b^3*c*e-40*a^2*c^2*e-30*a*b*c^2*e+2*b^2*c^2*e-14*a*c^3*e-6*b*c^3*e+22*c^4*e-16*a^3*d*e+32*a^2*b*d*e-2*a*b^2*d*e-27*b^3*d*e+16*a^2*c*d*e+42*a*b*c*d*e-6*b^2*c*d*e-46*a*c^2*d*e-9*b*c^2*d*e+31*c^3*d*e-23*a^2*d^2*e-a*b*d^2*e+22*b^2*d^2*e+29*a*c*d^2*e+22*b*c*d^2*e-28*c^2*d^2*e-32*a*d^3*e-10*b*d^3*e-10*c*d^3*e+19*d^4*e-41*a^3*e^2+27*a^2*b*e^2+44*a*b^2*e^2-32*b^3*e^2-24*a^2*c*e^2-6*a*b*c*e^2-25*b^2*c*e^2+29*a*c^2*e^2+19*b*c^2*e^2-47*c^3*e^2+20*a^2*d*e^2-3*a*b*d*e^2+43*b^2*d*e^2-14*a*c*d*e^2+2*b*c*d*e^2-37*c^2*d*e^2-24*a*d^2*e^2-19*b*d^2*e^2+30*c*d^2*e^2+29*d^3*e^2-a^2*e^3-6*a*b*e^3-18*b^2*e^3-48*a*c*e^3+13*b*c*e^3+40*c^2*e^3-48*a*d*e^3-45*b*d*e^3-23*c*d*e^3-6*d^2*e^3+4*a*e^4+12*b*e^4+36*c*e^4+32*d*e^4-20*e^5, a^4*d+17*a^2*c^2*d-6*a*b*c^2*d-16*b^2*c^2*d-8*a*c^3*d+12*b*c^3*d+31*c^4*d-2*a^3*d^2+45*a^2*b*d^2+29*a*b^2*d^2-47*b^3*d^2+17*a^2*c*d^2-28*a*b*c*d^2-12*b^2*c*d^2-49*a*c^2*d^2-34*b*c^2*d^2-49*c^3*d^2-13*a^2*d^3+12*a*b*d^3-50*b^2*d^3-27*a*c*d^3+17*b*c*d^3+26*c^2*d^3-40*a*d^4+37*b*d^4+31*c*d^4+42*d^5-3*a^4*e+40*a^3*b*e+39*a^2*b^2*e-35*a*b^3*e+2*b^4*e-47*a^3*c*e-45*a^2*b*c*e-24*a*b^2*c*e-20*b^3*c*e+a^2*c^2*e-3*a*b*c^2*e+8*b^2*c^2*e-42*a*c^3*e-49*b*c^3*e-49*c^4*e+42*a^3*d*e+25*a^2*b*d*e+45*a*b^2*d*e+35*b^3*d*e+43*a^2*c*d*e-18*a*b*c*d*e+24*b^2*c*d*e-2*a*c^2*d*e-43*b*c^2*d*e+16*c^3*d*e-44*a^2*d^2*e+31*a*b*d^2*e+17*b^2*d^2*e-36*a*c*d^2*e+25*b*c*d^2*e-20*c^2*d^2*e+17*a*d^3*e-39*b*d^3*e-37*c*d^3*e+10*d^4*e-30*a^3*e^2+34*a^2*b*e^2-43*a*b^2*e^2-2*b^3*e^2-48*a^2*c*e^2+32*a*b*c*e^2+47*b^2*c*e^2+34*a*c^2*e^2-32*b*c^2*e^2+4*c^3*e^2-26*a^2*d*e^2+22*a*b*d*e^2+23*b^2*d*e^2-37*a*c*d*e^2+26*b*c*d*e^2-33*c^2*d*e^2-5*a*d^2*e^2+15*b*d^2*e^2+19*c*d^2*e^2-31*d^3*e^2+42*a^2*e^3+27*a*b*e^3+30*b^2*e^3+22*a*c*e^3-49*b*c*e^3-19*c^2*e^3+42*a*d*e^3+5*b*d*e^3+32*c*d*e^3+9*d^2*e^3-17*a*e^4-46*b*e^4+23*c*e^4-32*d*e^4-2*e^5, c^5+40*a^2*c^2*d+34*a*b*c^2*d-16*b^2*c^2*d+9*a*c^3*d-13*b*c^3*d+30*c^4*d+18*a^3*d^2+27*a^2*b*d^2+37*a*b^2*d^2-30*b^3*d^2-38*a^2*c*d^2-40*a*b*c*d^2-10*b^2*c*d^2-28*a*c^2*d^2-26*b*c^2*d^2+15*c^3*d^2-7*a^2*d^3+2*a*b*d^3+28*b^2*d^3+27*a*c*d^3+11*b*c*d^3-9*c^2*d^3-18*a*d^4+39*b*d^4+8*c*d^4+20*d^5+34*a^4*e+27*a^3*b*e+10*a^2*b^2*e-10*a*b^3*e+15*b^4*e+a^3*c*e+16*a^2*b*c*e+47*a*b^2*c*e-50*b^3*c*e-45*a^2*c^2*e-47*a*b*c^2*e-38*b^2*c^2*e+49*a*c^3*e+11*b*c^3*e-8*c^4*e-24*a^3*d*e+41*a^2*b*d*e+31*a*b^2*d*e-31*b^3*d*e-44*a^2*c*d*e-a*b*c*d*e-15*b^2*c*d*e-27*a*c^2*d*e-50*b*c^2*d*e+29*c^3*d*e+30*a^2*d^2*e+41*a*b*d^2*e-31*b^2*d^2*e-40*a*c*d^2*e+14*b*c*d^2*e-18*c^2*d^2*e+4*a*d^3*e-27*b*d^3*e-36*c*d^3*e-26*d^4*e-2*a^3*e^2+39*a^2*b*e^2-17*a*b^2*e^2-b^3*e^2+24*a^2*c*e^2-6*a*b*c*e^2-12*b^2*c*e^2+38*a*c^2*e^2+6*b*c^2*e^2+38*c^3*e^2+15*a^2*d*e^2-2*a*b*d*e^2-22*b^2*d*e^2+30*a*c*d*e^2+50*b*c*d*e^2-37*c^2*d*e^2+2*a*d^2*e^2+27*b*d^2*e^2+2*c*d^2*e^2+19*d^3*e^2+48*a^2*e^3+24*a*b*e^3+49*b^2*e^3-35*a*c*e^3+49*b*c*e^3+2*c^2*e^3+20*a*d*e^3+34*b*d*e^3-50*c*d*e^3-41*d^2*e^3+48*a*e^4-24*b*e^4-14*c*e^4+32*d*e^4-11*e^5, b*c^4+9*a^2*c^2*d-47*a*b*c^2*d-29*b^2*c^2*d+24*a*c^3*d-19*b*c^3*d-25*c^4*d+50*a^3*d^2-6*a^2*b*d^2-32*a*b^2*d^2-43*b^3*d^2+42*a^2*c*d^2-16*a*b*c*d^2-40*b^2*c*d^2+3*a*c^2*d^2+9*b*c^2*d^2+34*c^3*d^2-48*a^2*d^3-8*a*b*d^3-22*b^2*d^3+42*a*c*d^3+25*b*c*d^3-31*c^2*d^3-12*a*d^4+25*b*d^4+c*d^4+13*d^5-26*a^4*e+2*a^3*b*e-37*a^2*b^2*e+23*a*b^3*e+25*b^4*e+43*a^3*c*e-10*a^2*b*c*e+16*a*b^2*c*e-24*b^3*c*e+43*a^2*c^2*e-25*a*b*c^2*e+39*b^2*c^2*e+31*a*c^3*e-21*b*c^3*e+16*c^4*e+17*a^3*d*e-33*a^2*b*d*e+34*a*b^2*d*e-16*b^3*d*e+49*a^2*c*d*e+10*a*b*c*d*e-14*b^2*c*d*e+6*a*c^2*d*e+32*b*c^2*d*e-25*c^3*d*e-16*a^2*d^2*e-26*a*b*d^2*e+36*b^2*d^2*e+41*a*c*d^2*e-43*b*c*d^2*e-44*c^2*d^2*e+24*a*d^3*e+12*b*d^3*e-40*c*d^3*e+46*d^4*e-18*a^3*e^2+36*a^2*b*e^2-49*a*b^2*e^2+47*b^3*e^2-30*a^2*c*e^2+11*a*b*c*e^2-17*b^2*c*e^2-19*a*c^2*e^2-33*b*c^2*e^2+4*c^3*e^2-14*a^2*d*e^2-13*a*b*d*e^2-4*b^2*d*e^2-a*c*d*e^2+22*b*c*d*e^2-41*c^2*d*e^2+50*a*d^2*e^2+24*b*d^2*e^2-29*c*d^2*e^2-9*d^3*e^2+10*a^2*e^3+44*a*b*e^3+11*b^2*e^3+25*a*c*e^3+31*b*c*e^3+22*c^2*e^3+a*d*e^3-6*c*d*e^3+26*d^2*e^3-40*a*e^4+31*b*e^4-50*c*e^4+9*d*e^4+39*e^5, a*c^4-47*a^2*c^2*d+40*a*b*c^2*d-8*b^2*c^2*d+3*a*c^3*d-3*b*c^3*d+38*c^4*d-13*a^3*d^2+3*a^2*b*d^2+19*a*b^2*d^2+24*b^3*d^2-27*a^2*c*d^2-12*a*b*c*d^2-45*b^2*c*d^2+28*a*c^2*d^2+35*b*c^2*d^2-28*c^3*d^2+7*a^2*d^3+3*a*b*d^3-34*b^2*d^3+15*a*c*d^3+36*b*c*d^3-18*c^2*d^3-49*a*d^4+44*b*d^4+c*d^4-10*d^5+31*a^4*e-18*a^3*b*e+7*a^2*b^2*e+38*a*b^3*e+37*b^4*e+18*a^3*c*e-50*a^2*b*c*e+12*a*b^2*c*e+43*b^3*c*e+33*a^2*c^2*e+13*a*b*c^2*e+13*b^2*c^2*e-4*a*c^3*e+13*b*c^3*e+20*c^4*e-32*a^3*d*e-36*a^2*b*d*e+47*a*b^2*d*e+43*b^3*d*e-13*a^2*c*d*e-27*a*b*c*d*e+7*b^2*c*d*e-40*a*c^2*d*e-30*b*c^2*d*e+21*c^3*d*e-18*a^2*d^2*e-32*a*b*d^2*e-20*b^2*d^2*e-47*a*c*d^2*e+34*b*c*d^2*e-3*c^2*d^2*e-22*a*d^3*e-29*b*d^3*e-47*c*d^3*e-33*d^4*e-3*a^3*e^2+46*a^2*b*e^2-42*a*b^2*e^2+6*b^3*e^2+16*a^2*c*e^2-9*a*b*c*e^2-35*b^2*c*e^2-24*b*c^2*e^2-5*c^3*e^2+18*a^2*d*e^2+43*a*b*d*e^2-43*b^2*d*e^2+6*a*c*d*e^2+8*b*c*d*e^2-33*c^2*d*e^2-26*a*d^2*e^2+31*b*d^2*e^2-29*c*d^2*e^2+d^3*e^2+45*a^2*e^3+45*a*b*e^3-31*b^2*e^3-26*a*c*e^3+35*b*c*e^3+30*c^2*e^3-33*a*d*e^3-4*b*d*e^3+34*c*d*e^3+21*d^2*e^3+41*a*e^4-14*b*e^4-32*c*e^4-19*d*e^4+29*e^5, b^2*c^3+10*a^2*c^2*d+20*a*b*c^2*d+36*b^2*c^2*d-7*a*c^3*d+13*b*c^3*d+42*c^4*d-6*a^3*d^2+13*a^2*b*d^2+31*a*b^2*d^2-29*b^3*d^2+44*a^2*c*d^2-20*a*b*c*d^2+27*b^2*c*d^2+17*a*c^2*d^2-7*b*c^2*d^2-18*c^3*d^2-44*a^2*d^3-35*a*b*d^3-11*b^2*d^3-28*a*c*d^3+b*c*d^3+22*c^2*d^3-13*a*d^4-32*b*d^4-33*c*d^4-48*d^5-16*a^4*e+7*a^3*b*e-40*a^2*b^2*e-47*a*b^3*e+20*b^4*e-41*a^3*c*e+50*a^2*b*c*e-35*a*b^2*c*e+44*b^3*c*e-43*a^2*c^2*e+15*a*b*c^2*e-33*b^2*c^2*e-38*a*c^3*e-16*b*c^3*e+11*c^4*e+46*a^3*d*e+32*a^2*b*d*e+3*a*b^2*d*e+39*b^3*d*e-32*a^2*c*d*e-19*a*b*c*d*e+23*b^2*c*d*e-2*a*c^2*d*e-44*b*c^2*d*e-44*c^3*d*e+18*a^2*d^2*e+31*a*b*d^2*e+16*b^2*d^2*e+a*c*d^2*e+45*b*c*d^2*e-18*c^2*d^2*e+22*a*d^3*e+16*b*d^3*e+2*c*d^3*e+48*d^4*e-32*a^3*e^2+49*a^2*b*e^2-3*a*b^2*e^2+30*b^3*e^2+31*a^2*c*e^2+28*a*b*c*e^2-4*b^2*c*e^2+7*a*c^2*e^2+48*b*c^2*e^2+40*c^3*e^2-a^2*d*e^2+19*a*b*d*e^2+40*b^2*d*e^2-3*a*c*d*e^2+9*b*c*d*e^2+21*c^2*d*e^2+28*a*d^2*e^2+49*b*d^2*e^2+19*c*d^2*e^2+41*d^3*e^2-30*a^2*e^3-30*a*b*e^3+5*b^2*e^3-2*a*c*e^3+17*b*c*e^3-16*c^2*e^3+42*b*d*e^3-22*c*d*e^3+34*d^2*e^3+20*a*e^4+42*b*e^4+8*c*e^4+36*d*e^4-25*e^5, a*b*c^3-48*a^2*c^2*d-19*a*b*c^2*d+46*b^2*c^2*d-49*a*c^3*d-43*b*c^3*d+c^4*d-12*a^3*d^2+28*a^2*b*d^2+11*a*b^2*d^2+13*b^3*d^2+36*a^2*c*d^2+20*a*b*c*d^2+8*b^2*c*d^2-5*a*c^2*d^2+44*b*c^2*d^2-50*c^3*d^2+34*a^2*d^3+a*b*d^3-25*b^2*d^3+5*a*c*d^3-47*b*c*d^3-4*c^2*d^3-33*a*d^4-29*b*d^4+34*c*d^4+d^5-15*a^4*e+50*a^3*b*e+14*a^2*b^2*e+15*a*b^3*e+34*b^4*e+9*a^3*c*e+38*a^2*b*c*e+12*a*b^2*c*e+21*b^3*c*e+18*a^2*c^2*e+37*a*b*c^2*e-16*b^2*c^2*e+13*a*c^3*e+47*b*c^3*e-41*c^4*e-29*a^3*d*e-45*a^2*b*d*e+3*a*b^2*d*e+44*b^3*d*e-31*a^2*c*d*e-8*a*b*c*d*e-5*b^2*c*d*e-22*a*c^2*d*e-6*b*c^2*d*e+3*c^3*d*e-43*a^2*d^2*e-45*a*b*d^2*e-24*b^2*d^2*e+15*a*c*d^2*e+15*b*c*d^2*e+7*c^2*d^2*e-17*a*d^3*e-8*b*d^3*e-31*c*d^3*e+19*d^4*e-41*a^3*e^2-25*a^2*b*e^2-11*a*b^2*e^2-4*b^3*e^2-25*a^2*c*e^2-32*a*b*c*e^2-42*b^2*c*e^2-46*a*c^2*e^2-41*b*c^2*e^2-36*c^3*e^2+40*a^2*d*e^2-43*a*b*d*e^2+35*b^2*d*e^2+2*a*c*d*e^2-28*b*c*d*e^2-43*c^2*d*e^2+21*a*d^2*e^2+8*b*d^2*e^2-42*c*d^2*e^2+50*d^3*e^2+48*a^2*e^3-25*a*b*e^3+22*b^2*e^3-3*a*c*e^3-42*b*c*e^3+22*c^2*e^3-5*a*d*e^3-35*b*d*e^3+36*c*d*e^3-34*d^2*e^3+14*a*e^4+34*b*e^4+23*c*e^4-35*d*e^4+46*e^5, a^2*c^3-17*a^2*c^2*d-7*a*b*c^2*d+15*b^2*c^2*d+35*a*c^3*d-36*b*c^3*d-19*c^4*d+20*a^3*d^2-39*a^2*b*d^2-3*a*b^2*d^2-2*b^3*d^2+8*a^2*c*d^2+13*a*b*c*d^2-20*b^2*c*d^2+6*a*c^2*d^2-48*b*c^2*d^2-21*c^3*d^2+46*a^2*d^3+39*a*b*d^3+32*b^2*d^3-2*a*c*d^3+47*b*c*d^3+16*c^2*d^3+20*a*d^4-36*b*d^4-12*c*d^4+28*d^5+24*a^4*e+17*a^3*b*e-21*a^2*b^2*e+31*a*b^3*e+24*b^4*e-45*a^3*c*e+34*a^2*b*c*e+3*a*b^2*c*e+34*b^3*c*e+39*a^2*c^2*e+12*a*b*c^2*e+18*b^2*c^2*e+19*a*c^3*e-13*b*c^3*e+7*c^4*e+16*a^3*d*e-4*a^2*b*d*e+35*a*b^2*d*e+20*b^3*d*e+38*a^2*c*d*e-41*a*b*c*d*e+49*b^2*c*d*e+7*a*c^2*d*e+39*b*c^2*d*e+15*c^3*d*e+32*a^2*d^2*e+35*a*b*d^2*e-36*b^2*d^2*e+11*a*c*d^2*e+11*b*c*d^2*e-26*c^2*d^2*e+2*a*d^3*e-30*b*d^3*e-2*c*d^3*e+5*d^4*e-2*a^3*e^2-45*a^2*b*e^2-10*a*b^2*e^2-42*b^3*e^2+13*a^2*c*e^2+38*a*b*c*e^2+22*b^2*c*e^2+42*a*c^2*e^2+16*b*c^2*e^2+40*c^3*e^2-19*a^2*d*e^2-35*a*b*d*e^2-24*b^2*d*e^2+33*a*c*d*e^2-48*b*c*d*e^2-6*a*d^2*e^2+2*b*d^2*e^2-31*c*d^2*e^2-5*d^3*e^2+45*a^2*e^3+17*a*b*e^3+50*b^2*e^3-18*a*c*e^3+3*b*c*e^3+32*c^2*e^3+34*a*d*e^3-39*b*d*e^3-35*c*d*e^3+22*d^2*e^3-40*a*e^4+43*b*e^4+48*c*e^4-42*d*e^4+8*e^5, b^3*c^2+2*a^2*c^2*d-42*a*b*c^2*d-42*b^2*c^2*d+22*a*c^3*d-28*b*c^3*d-24*c^4*d-24*a^3*d^2+40*a^2*b*d^2-7*a*b^2*d^2+31*b^3*d^2+13*a^2*c*d^2+33*a*b*c*d^2+6*b^2*c*d^2+40*a*c^2*d^2+37*b*c^2*d^2+40*c^3*d^2-12*a^2*d^3+26*a*b*d^3+23*b^2*d^3+44*a*c*d^3+13*b*c*d^3-24*c^2*d^3+31*a*d^4+44*b*d^4+32*c*d^4+48*d^5+42*a^4*e+2*a^3*b*e-25*a^2*b^2*e-27*a*b^3*e-21*b^4*e+44*a^3*c*e+50*a^2*b*c*e+42*a*b^2*c*e+28*b^3*c*e+28*a^2*c^2*e+20*a*b*c^2*e+11*b^2*c^2*e-25*a*c^3*e+35*b*c^3*e+11*c^4*e+13*a^3*d*e+13*a^2*b*d*e-33*a*b^2*d*e+26*b^3*d*e+10*a^2*c*d*e-47*a*b*c*d*e+44*b^2*c*d*e-50*a*c^2*d*e+6*b*c^2*d*e+38*c^3*d*e-43*a^2*d^2*e-43*a*b*d^2*e+50*b^2*d^2*e-36*a*c*d^2*e+39*b*c*d^2*e+4*c^2*d^2*e+26*a*d^3*e+6*b*d^3*e-30*c*d^3*e-21*d^4*e+16*a^3*e^2-19*a^2*b*e^2+43*a*b^2*e^2-b^3*e^2-9*a^2*c*e^2-3*a*b*c*e^2-44*b^2*c*e^2-34*a*c^2*e^2-24*b*c^2*e^2+15*c^3*e^2+47*a^2*d*e^2-45*a*b*d*e^2-22*b^2*d*e^2-21*a*c*d*e^2+36*b*c*d*e^2+c^2*d*e^2-13*a*d^2*e^2+47*b*d^2*e^2-12*c*d^2*e^2+16*d^3*e^2-30*a^2*e^3-49*a*b*e^3+40*b^2*e^3+46*a*c*e^3-25*b*c*e^3-38*c^2*e^3-30*a*d*e^3-27*b*d*e^3+47*c*d*e^3+37*d^2*e^3+49*a*e^4+6*b*e^4-6*c*e^4+43*d*e^4+5*e^5, a*b^2*c^2-9*a^2*c^2*d+49*a*b*c^2*d+17*b^2*c^2*d-45*a*c^3*d+27*b*c^3*d-8*c^4*d-25*a^3*d^2-23*a^2*b*d^2+47*a*b^2*d^2+8*b^3*d^2+20*a^2*c*d^2+37*a*b*c*d^2+28*b^2*c*d^2+8*a*c^2*d^2+36*b*c^2*d^2+34*c^3*d^2+37*a^2*d^3+23*a*b*d^3+11*b^2*d^3-46*a*c*d^3+45*b*c*d^3-16*c^2*d^3-27*a*d^4-39*b*d^4+31*c*d^4-24*d^5+42*a^4*e-30*a^3*b*e+12*a^2*b^2*e-18*a*b^3*e+8*b^4*e-33*a^3*c*e+21*a^2*b*c*e-9*a*b^2*c*e+10*b^3*c*e+11*a^2*c^2*e-33*a*b*c^2*e-27*b^2*c^2*e+47*a*c^3*e-35*b*c^3*e+15*c^4*e-19*a^3*d*e+20*a^2*b*d*e+41*a*b^2*d*e+39*b^3*d*e+24*a^2*c*d*e-12*a*b*c*d*e-16*b^2*c*d*e+38*a*c^2*d*e-43*b*c^2*d*e+39*c^3*d*e-14*a^2*d^2*e+39*a*b*d^2*e+24*b^2*d^2*e-35*a*c*d^2*e-8*b*c*d^2*e-26*c^2*d^2*e-5*a*d^3*e+34*b*d^3*e+16*c*d^3*e+35*d^4*e-a^3*e^2+44*a^2*b*e^2+33*a*b^2*e^2+41*b^3*e^2+26*a^2*c*e^2-6*a*b*c*e^2-15*b^2*c*e^2-46*a*c^2*e^2-37*b*c^2*e^2-49*c^3*e^2-6*a^2*d*e^2+20*a*b*d*e^2-7*b^2*d*e^2+16*a*c*d*e^2+49*b*c*d*e^2-23*c^2*d*e^2+37*a*d^2*e^2+31*b*d^2*e^2+17*c*d^2*e^2-39*d^3*e^2-46*a^2*e^3-17*a*b*e^3+46*b^2*e^3-31*a*c*e^3+39*b*c*e^3-13*c^2*e^3+40*a*d*e^3+18*b*d*e^3+3*c*d*e^3-6*d^2*e^3-35*a*e^4+22*b*e^4-47*c*e^4-4*d*e^4+35*e^5, a^2*b*c^2+25*a^2*c^2*d-27*a*b*c^2*d+43*b^2*c^2*d+3*a*c^3*d+35*b*c^3*d+39*c^4*d+12*a^3*d^2-39*a^2*b*d^2-38*a*b^2*d^2+8*b^3*d^2+14*a^2*c*d^2+42*a*b*c*d^2-16*b^2*c*d^2+32*a*c^2*d^2-26*b*c^2*d^2+31*c^3*d^2-34*a^2*d^3-4*a*b*d^3+40*b^2*d^3+34*a*c*d^3-31*b*c*d^3+11*c^2*d^3+9*a*d^4+27*b*d^4+19*c*d^4-44*d^5-45*a^4*e+43*a^3*b*e-36*a^2*b^2*e+23*a*b^3*e-14*b^4*e-2*a^3*c*e+20*a^2*b*c*e-34*a*b^2*c*e+26*b^3*c*e+2*a^2*c^2*e-32*a*b*c^2*e+35*b^2*c^2*e-44*a*c^3*e-47*b*c^3*e-6*c^4*e+4*a^3*d*e+34*a^2*b*d*e-38*a*b^2*d*e-21*b^3*d*e+45*a^2*c*d*e-25*a*b*c*d*e+30*b^2*c*d*e+43*a*c^2*d*e-2*b*c^2*d*e+17*c^3*d*e+30*a^2*d^2*e+48*a*b*d^2*e+5*b^2*d^2*e+31*a*c*d^2*e+46*b*c*d^2*e+42*c^2*d^2*e-39*a*d^3*e-30*b*d^3*e+34*c*d^3*e+37*d^4*e+45*a^3*e^2-37*a^2*b*e^2+16*a*b^2*e^2-12*b^3*e^2+21*a^2*c*e^2-36*a*b*c*e^2+45*b^2*c*e^2-39*a*c^2*e^2+8*c^3*e^2-47*a^2*d*e^2+38*a*b*d*e^2+48*b^2*d*e^2-30*a*c*d*e^2-40*b*c*d*e^2+34*c^2*d*e^2+42*a*d^2*e^2-38*b*d^2*e^2+24*c*d^2*e^2+37*d^3*e^2-26*a^2*e^3-50*a*b*e^3+10*b^2*e^3-29*a*c*e^3-48*b*c*e^3+8*c^2*e^3+26*a*d*e^3-26*b*d*e^3-44*c*d*e^3+30*d^2*e^3-31*a*e^4-21*b*e^4-44*c*e^4-17*d*e^4+26*e^5, a^3*c^2+32*a^2*c^2*d+18*a*b*c^2*d+26*b^2*c^2*d-34*a*c^3*d+29*b*c^3*d+6*c^4*d-46*a^3*d^2-37*a^2*b*d^2-9*a*b^2*d^2+13*b^3*d^2-46*a^2*c*d^2-25*a*b*c*d^2-19*b^2*c*d^2-36*a*c^2*d^2-28*b*c^2*d^2+c^3*d^2-16*a^2*d^3-32*a*b*d^3-39*b^2*d^3-a*c*d^3-44*b*c*d^3-24*c^2*d^3+44*a*d^4-18*b*d^4-11*c*d^4+31*d^5-37*a^4*e+50*a^3*b*e-3*a^2*b^2*e+40*a*b^3*e-19*b^4*e+31*a^3*c*e+49*a^2*b*c*e+14*a*b^2*c*e+22*b^3*c*e-27*a^2*c^2*e-46*a*b*c^2*e+31*b^2*c^2*e+22*a*c^3*e+27*b*c^3*e+25*c^4*e+10*a^3*d*e-21*a^2*b*d*e-13*a*b^2*d*e-46*b^3*d*e-34*a^2*c*d*e+24*a*b*c*d*e-38*b^2*c*d*e-14*a*c^2*d*e+50*b*c^2*d*e+28*c^3*d*e+44*a^2*d^2*e+23*a*b*d^2*e-38*b^2*d^2*e-4*a*c*d^2*e-34*b*c*d^2*e-21*c^2*d^2*e+9*a*d^3*e-14*b*d^3*e-19*c*d^3*e+14*d^4*e+31*a^3*e^2-33*a^2*b*e^2-39*a*b^2*e^2+9*b^3*e^2+7*a^2*c*e^2+13*a*b*c*e^2-12*b^2*c*e^2+24*a*c^2*e^2+18*b*c^2*e^2+19*c^3*e^2+24*a^2*d*e^2-24*a*b*d*e^2-47*b^2*d*e^2-46*a*c*d*e^2+31*b*c*d*e^2+31*c^2*d*e^2-9*a*d^2*e^2+6*b*d^2*e^2+46*c*d^2*e^2+23*d^3*e^2-37*a^2*e^3+14*a*b*e^3-40*b^2*e^3+14*a*c*e^3-46*b*c*e^3-42*c^2*e^3+32*a*d*e^3+5*b*d*e^3-4*c*d*e^3-16*d^2*e^3-4*a*e^4+36*b*e^4+38*c*e^4+30*d*e^4-18*e^5, b^4*c+25*a^2*c^2*d+37*a*b*c^2*d+12*b^2*c^2*d-31*b*c^3*d+40*c^4*d-49*a^3*d^2+8*a^2*b*d^2+36*a*b^2*d^2+48*b^3*d^2-15*a^2*c*d^2+20*a*b*c*d^2-13*b^2*c*d^2-2*a*c^2*d^2+11*b*c^2*d^2+46*c^3*d^2+49*a^2*d^3-3*a*b*d^3-31*b^2*d^3-11*a*c*d^3+4*b*c*d^3+7*c^2*d^3-27*b*d^4+c*d^4+43*d^5+41*a^4*e-28*a^3*b*e+37*a^2*b^2*e-18*a*b^3*e+20*b^4*e-3*a^3*c*e+42*a^2*b*c*e-26*a*b^2*c*e-36*b^3*c*e-32*a^2*c^2*e+33*a*b*c^2*e-18*b^2*c^2*e-45*a*c^3*e+22*b*c^3*e+22*c^4*e+28*a^3*d*e-17*a^2*b*d*e-37*a*b^2*d*e-11*b^3*d*e+44*a^2*c*d*e-21*a*b*c*d*e+27*b^2*c*d*e-16*a*c^2*d*e+45*b*c^2*d*e+37*c^3*d*e+13*a^2*d^2*e-24*a*b*d^2*e+46*b^2*d^2*e-18*a*c*d^2*e-24*b*c*d^2*e+10*c^2*d^2*e-22*a*d^3*e-19*b*d^3*e+26*c*d^3*e+24*d^4*e+50*a^3*e^2-21*a^2*b*e^2-31*a*b^2*e^2+12*b^3*e^2+18*a^2*c*e^2-9*a*b*c*e^2-3*b^2*c*e^2+49*a*c^2*e^2-22*b*c^2*e^2-7*c^3*e^2+34*a^2*d*e^2+14*a*b*d*e^2-10*b^2*d*e^2-21*a*c*d*e^2-49*b*c*d*e^2-32*c^2*d*e^2-31*a*d^2*e^2-37*b*d^2*e^2+17*c*d^2*e^2-2*d^3*e^2+23*a^2*e^3+38*a*b*e^3+16*b^2*e^3+7*a*c*e^3-6*b*c*e^3+7*c^2*e^3-35*a*d*e^3+46*b*d*e^3-2*c*d*e^3-47*d^2*e^3+15*a*e^4-22*b*e^4+25*c*e^4+12*d*e^4+36*e^5, a*b^3*c+7*a^2*c^2*d-37*a*b*c^2*d-27*b^2*c^2*d-a*c^3*d-28*b*c^3*d+32*c^4*d-17*a^3*d^2+30*a^2*b*d^2+7*a*b^2*d^2-32*b^3*d^2-10*a^2*c*d^2+38*a*b*c*d^2-15*b^2*c*d^2+a*c^2*d^2-37*b*c^2*d^2-9*c^3*d^2-13*a^2*d^3+27*a*b*d^3-11*b^2*d^3+6*a*c*d^3+b*c*d^3-9*c^2*d^3+44*a*d^4+3*b*d^4-36*c*d^4+41*d^5-3*a^4*e+10*a^3*b*e-8*a*b^3*e-3*b^4*e-3*a^3*c*e+34*a^2*b*c*e+3*a*b^2*c*e+15*b^3*c*e-22*a^2*c^2*e-33*a*b*c^2*e-4*b^2*c^2*e+48*a*c^3*e+7*b*c^3*e-29*c^4*e+38*a^3*d*e+14*a^2*b*d*e-26*a*b^2*d*e+48*b^3*d*e-3*a^2*c*d*e-45*a*b*c*d*e+26*b^2*c*d*e+46*a*c^2*d*e+26*b*c^2*d*e+15*c^3*d*e+29*a^2*d^2*e+42*a*b*d^2*e+11*b^2*d^2*e+26*a*c*d^2*e+44*b*c*d^2*e-18*c^2*d^2*e-19*a*d^3*e+47*b*d^3*e+c*d^3*e+50*d^4*e+8*a^3*e^2-19*a^2*b*e^2+49*a*b^2*e^2+17*b^3*e^2-27*a^2*c*e^2+30*a*b*c*e^2+10*b^2*c*e^2+21*a*c^2*e^2+11*b*c^2*e^2+38*c^3*e^2+36*a^2*d*e^2-28*a*b*d*e^2+22*b^2*d*e^2-45*a*c*d*e^2-45*b*c*d*e^2+43*c^2*d*e^2-21*a*d^2*e^2+5*b*d^2*e^2-41*c*d^2*e^2+36*d^3*e^2-25*a^2*e^3-22*a*b*e^3-6*b^2*e^3+31*a*c*e^3+19*b*c*e^3-35*c^2*e^3+44*a*d*e^3+40*b*d*e^3-14*c*d*e^3+6*d^2*e^3+2*a*e^4-26*b*e^4+43*c*e^4+39*d*e^4+7*e^5, a^2*b^2*c-22*a^2*c^2*d+2*a*b*c^2*d-39*b^2*c^2*d-32*a*c^3*d-39*b*c^3*d+32*c^4*d+47*a^3*d^2-9*a^2*b*d^2+36*a*b^2*d^2-22*b^3*d^2+a^2*c*d^2+7*a*b*c*d^2+21*b^2*c*d^2+35*a*c^2*d^2+31*b*c^2*d^2+38*c^3*d^2+4*a^2*d^3+50*a*b*d^3-10*b^2*d^3-7*a*c*d^3-8*b*c*d^3-23*c^2*d^3+18*a*d^4+13*b*d^4+5*c*d^4-6*d^5-41*a^4*e+50*a^3*b*e+3*a^2*b^2*e+20*a*b^3*e-26*b^4*e-22*a^3*c*e+9*a^2*b*c*e+5*a*b^2*c*e+38*b^3*c*e-16*a^2*c^2*e-35*a*b*c^2*e-17*b^2*c^2*e-4*a*c^3*e-32*b*c^3*e-19*c^4*e-21*a^3*d*e+23*a^2*b*d*e+37*a*b^2*d*e+48*b^3*d*e-2*a^2*c*d*e-48*a*b*c*d*e-44*b^2*c*d*e+4*a*c^2*d*e+9*b*c^2*d*e-33*c^3*d*e+30*a^2*d^2*e+25*a*b*d^2*e+34*b^2*d^2*e-39*a*c*d^2*e+27*b*c*d^2*e+25*c^2*d^2*e+3*a*d^3*e-50*b*d^3*e-49*c*d^3*e-9*d^4*e-39*a^3*e^2+10*a^2*b*e^2-33*a*b^2*e^2+36*b^3*e^2+20*a^2*c*e^2+43*a*b*c*e^2+7*b^2*c*e^2+36*a*c^2*e^2-39*b*c^2*e^2-33*c^3*e^2+14*a^2*d*e^2-46*a*b*d*e^2+8*b^2*d*e^2+23*a*c*d*e^2+30*b*c*d*e^2-8*c^2*d*e^2+28*a*d^2*e^2-5*b*d^2*e^2+25*c*d^2*e^2+17*d^3*e^2+28*a^2*e^3-38*a*b*e^3-46*b^2*e^3-27*a*c*e^3-5*b*c*e^3-20*c^2*e^3+2*a*d*e^3-4*b*d*e^3+15*c*d*e^3-36*d^2*e^3+41*a*e^4+6*b*e^4+20*c*e^4+8*d*e^4-2*e^5, a^3*b*c+40*a^2*c^2*d-47*a*b*c^2*d-27*b^2*c^2*d+41*a*c^3*d-39*b*c^3*d-32*c^4*d+5*a^3*d^2-5*a^2*b*d^2-34*a*b^2*d^2-35*b^3*d^2+29*a^2*c*d^2+4*a*b*c*d^2-6*b^2*c*d^2+25*a*c^2*d^2+6*b*c^2*d^2-44*c^3*d^2-38*a^2*d^3-31*a*b*d^3+37*b^2*d^3-49*a*c*d^3-17*b*c*d^3+9*c^2*d^3+25*a*d^4+4*b*d^4-25*c*d^4-49*d^5-15*a^4*e-11*a^3*b*e+7*a^2*b^2*e+37*a*b^3*e-21*b^4*e+18*a^3*c*e+46*a^2*b*c*e+6*a*b^2*c*e+43*b^3*c*e-5*a^2*c^2*e+49*a*b*c^2*e+44*b^2*c^2*e-18*a*c^3*e+30*b*c^3*e+30*c^4*e+37*a^3*d*e-47*a^2*b*d*e+23*a*b^2*d*e-26*b^3*d*e-12*a^2*c*d*e+49*a*b*c*d*e+37*b^2*c*d*e+3*a*c^2*d*e-15*b*c^2*d*e+c^3*d*e-13*a^2*d^2*e+32*a*b*d^2*e-29*b^2*d^2*e-11*a*c*d^2*e-28*b*c*d^2*e+21*c^2*d^2*e-10*a*d^3*e-20*b*d^3*e-2*c*d^3*e-25*d^4*e-18*a^3*e^2-10*a^2*b*e^2-26*a*b^2*e^2+15*b^3*e^2-6*a^2*c*e^2+48*a*b*c*e^2-36*b^2*c*e^2-18*a*c^2*e^2+8*b*c^2*e^2+36*c^3*e^2+2*a^2*d*e^2+48*a*b*d*e^2-32*b^2*d*e^2+47*a*c*d*e^2+b*c*d*e^2-35*c^2*d*e^2+16*a*d^2*e^2-26*b*d^2*e^2+40*c*d^2*e^2+50*d^3*e^2+16*a^2*e^3+32*a*b*e^3-22*b^2*e^3-43*a*c*e^3+4*b*c*e^3-26*c^2*e^3-29*a*d*e^3+7*b*d*e^3+20*c*d*e^3+8*d^2*e^3-9*a*e^4-7*b*e^4+3*c*e^4+49*d*e^4-48*e^5, a^4*c-40*a^2*c^2*d+21*a*b*c^2*d+43*b^2*c^2*d+31*a*c^3*d-4*b*c^3*d+49*c^4*d+24*a^3*d^2-14*a^2*b*d^2+3*a*b^2*d^2-6*b^3*d^2+27*a^2*c*d^2+24*a*b*c*d^2-47*b^2*c*d^2-16*a*c^2*d^2+21*b*c^2*d^2-33*c^3*d^2+39*a^2*d^3-34*a*b*d^3-7*b^2*d^3+3*a*c*d^3+30*b*c*d^3-10*c^2*d^3+17*a*d^4+28*b*d^4+16*c*d^4-19*d^5+16*a^4*e-14*a^3*b*e+19*a^2*b^2*e-12*a*b^3*e-41*b^4*e-28*a^3*c*e+13*a^2*b*c*e+35*a*b^2*c*e-35*b^3*c*e+37*a^2*c^2*e-7*a*b*c^2*e+33*b^2*c^2*e-30*a*c^3*e+36*b*c^3*e-26*c^4*e-27*a^3*d*e+28*a^2*b*d*e+2*a*b^2*d*e+22*b^3*d*e-9*a^2*c*d*e+39*a*b*c*d*e-11*b^2*c*d*e+48*a*c^2*d*e+b*c^2*d*e-25*c^3*d*e-28*a^2*d^2*e-38*a*b*d^2*e-13*b^2*d^2*e-12*a*c*d^2*e-35*b*c*d^2*e-45*c^2*d^2*e-27*a*d^3*e-31*b*d^3*e+20*c*d^3*e+40*d^4*e+11*a^3*e^2-33*a^2*b*e^2-3*a*b^2*e^2+32*b^3*e^2+10*a^2*c*e^2+48*a*b*c*e^2-50*b^2*c*e^2+2*a*c^2*e^2-46*b*c^2*e^2+15*c^3*e^2-15*a^2*d*e^2+29*a*b*d*e^2+4*b^2*d*e^2-16*a*c*d*e^2+34*b*c*d*e^2-21*c^2*d*e^2+44*a*d^2*e^2-35*b*d^2*e^2+4*c*d^2*e^2-16*d^3*e^2-14*a^2*e^3+39*a*b*e^3+44*b^2*e^3-22*a*c*e^3-16*b*c*e^3+38*c^2*e^3-a*d*e^3+14*b*d*e^3-44*c*d*e^3-31*d^2*e^3+4*a*e^4+33*c*e^4-5*d*e^4+46*e^5, b^5-5*a^2*c^2*d-23*a*b*c^2*d+3*b^2*c^2*d-30*a*c^3*d-48*b*c^3*d-40*c^4*d-21*a^3*d^2-13*a^2*b*d^2+36*a*b^2*d^2-35*b^3*d^2-9*a^2*c*d^2+32*a*b*c*d^2-19*b^2*c*d^2+3*a*c^2*d^2-2*b*c^2*d^2+22*c^3*d^2-37*a^2*d^3+46*a*b*d^3-38*b^2*d^3-33*a*c*d^3-7*b*c*d^3+3*c^2*d^3-33*a*d^4+b*d^4+22*c*d^4+50*d^5-33*a^4*e+18*a^3*b*e+11*a^2*b^2*e-19*a*b^3*e+49*b^4*e+3*a^3*c*e-10*a^2*b*c*e-29*a*b^2*c*e-17*b^3*c*e-15*a^2*c^2*e+30*a*b*c^2*e+39*b^2*c^2*e+7*a*c^3*e-46*b*c^3*e+29*c^4*e-17*a^3*d*e+26*a^2*b*d*e+27*a*b^2*d*e-27*b^3*d*e-27*a^2*c*d*e-7*a*b*c*d*e-36*b^2*c*d*e+18*a*c^2*d*e-34*b*c^2*d*e+31*c^3*d*e+22*a^2*d^2*e-2*a*b*d^2*e+39*b^2*d^2*e+40*a*c*d^2*e+49*b*c*d^2*e-41*c^2*d^2*e-46*a*d^3*e-33*b*d^3*e-40*c*d^3*e+16*d^4*e-37*a^3*e^2-14*a^2*b*e^2-49*a*b^2*e^2+39*b^3*e^2-20*a^2*c*e^2-39*a*b*c*e^2+20*b^2*c*e^2+10*a*c^2*e^2+29*b*c^2*e^2+20*c^3*e^2-19*a^2*d*e^2+37*a*b*d*e^2+20*b^2*d*e^2+26*a*c*d*e^2-8*b*c*d*e^2+14*c^2*d*e^2+24*a*d^2*e^2-14*b*d^2*e^2-33*c*d^2*e^2-18*d^3*e^2-2*a^2*e^3-32*a*b*e^3-37*b^2*e^3+45*a*c*e^3-33*b*c*e^3+28*c^2*e^3-19*a*d*e^3-43*b*d*e^3-10*c*d*e^3+30*d^2*e^3+44*a*e^4+40*b*e^4-20*c*e^4-40*d*e^4-2*e^5, a*b^4-14*a^2*c^2*d+14*b^2*c^2*d+36*a*c^3*d+7*b*c^3*d-14*c^4*d-11*a^3*d^2+40*a^2*b*d^2-29*a*b^2*d^2-45*b^3*d^2+23*a^2*c*d^2+8*a*b*c*d^2+28*b^2*c*d^2+42*a*c^2*d^2+14*b*c^2*d^2+42*c^3*d^2-36*a^2*d^3-4*a*b*d^3+6*a*c*d^3-18*b*c*d^3+40*c^2*d^3-47*a*d^4-19*b*d^4-16*c*d^4+31*d^5-15*a^4*e+46*a^3*b*e+13*a^2*b^2*e-18*a*b^3*e+9*b^4*e+50*a^3*c*e-10*a^2*b*c*e-12*a*b^2*c*e+44*b^3*c*e+7*a^2*c^2*e+39*a*b*c^2*e-36*b^2*c^2*e+29*a*c^3*e-37*b*c^3*e-28*c^4*e-43*a^3*d*e+50*a^2*b*d*e-16*a*b^2*d*e+17*b^3*d*e+23*a^2*c*d*e-14*a*b*c*d*e+10*b^2*c*d*e+18*a*c^2*d*e+40*b*c^2*d*e-30*c^3*d*e+44*a^2*d^2*e+26*a*b*d^2*e+17*b^2*d^2*e+9*a*c*d^2*e+37*b*c*d^2*e-38*c^2*d^2*e+46*a*d^3*e+15*b*d^3*e+33*c*d^3*e+20*d^4*e+4*a^3*e^2-43*a^2*b*e^2-14*a*b^2*e^2-29*b^3*e^2+44*a^2*c*e^2-37*a*b*c*e^2-2*b^2*c*e^2+39*a*c^2*e^2-36*b*c^2*e^2+45*c^3*e^2-34*a^2*d*e^2-48*a*b*d*e^2-25*b^2*d*e^2+48*a*c*d*e^2+5*b*c*d*e^2-16*c^2*d*e^2+20*a*d^2*e^2+8*b*d^2*e^2-48*c*d^2*e^2+27*d^3*e^2-39*a^2*e^3-23*a*b*e^3-45*b^2*e^3-34*a*c*e^3-50*b*c*e^3-42*c^2*e^3+50*a*d*e^3+26*b*d*e^3+48*c*d*e^3-37*d^2*e^3-20*a*e^4-19*b*e^4+23*c*e^4+23*d*e^4+12*e^5, a^2*b^3-25*a^2*c^2*d+26*a*b*c^2*d+32*b^2*c^2*d-48*a*c^3*d-7*b*c^3*d-44*c^4*d+14*a^3*d^2+19*a^2*b*d^2-7*a*b^2*d^2-15*b^3*d^2+50*a^2*c*d^2-11*a*b*c*d^2-13*b^2*c*d^2-33*a*c^2*d^2-46*b*c^2*d^2+12*c^3*d^2-26*a^2*d^3-11*a*b*d^3+22*b^2*d^3+24*a*c*d^3-12*b*c*d^3-22*c^2*d^3+40*a*d^4-23*b*d^4-48*c*d^4-20*d^5+17*a^4*e-41*a^3*b*e-a^2*b^2*e-12*a*b^3*e-9*b^4*e-30*a^3*c*e+50*a^2*b*c*e+31*a*b^2*c*e+5*b^3*c*e+33*a^2*c^2*e+15*a*b*c^2*e-50*b^2*c^2*e+24*a*c^3*e-b*c^3*e-6*c^4*e-31*a^3*d*e-26*a^2*b*d*e+49*a*b^2*d*e-13*b^3*d*e+43*a^2*c*d*e-10*a*b*c*d*e+35*b^2*c*d*e+36*a*c^2*d*e-22*b*c^2*d*e+40*c^3*d*e-7*a^2*d^2*e+28*a*b*d^2*e-b^2*d^2*e+17*a*c*d^2*e+13*b*c*d^2*e+26*c^2*d^2*e+32*a*d^3*e+3*b*d^3*e+12*c*d^3*e+40*d^4*e-40*a^3*e^2+12*a^2*b*e^2+27*a*b^2*e^2-24*b^3*e^2+13*a^2*c*e^2-19*a*b*c*e^2-27*b^2*c*e^2-28*a*c^2*e^2+50*b*c^2*e^2-48*c^3*e^2-14*a^2*d*e^2+26*a*b*d*e^2+35*b^2*d*e^2-43*a*c*d*e^2+42*b*c*d*e^2+9*c^2*d*e^2-10*a*d^2*e^2+21*c*d^2*e^2-5*d^3*e^2-30*a^2*e^3+38*a*b*e^3-25*b^2*e^3-28*a*c*e^3+23*b*c*e^3+38*c^2*e^3-30*a*d*e^3-16*b*d*e^3-35*c*d*e^3+2*d^2*e^3+33*a*e^4+12*b*e^4-25*c*e^4+26*d*e^4-40*e^5, a^3*b^2-40*a^2*c^2*d+50*a*b*c^2*d+25*b^2*c^2*d+46*a*c^3*d-45*b*c^3*d-6*c^4*d-24*a^3*d^2-9*a^2*b*d^2-15*a*b^2*d^2+5*b^3*d^2+36*a^2*c*d^2-19*a*b*c*d^2+19*b^2*c*d^2+17*a*c^2*d^2+12*b*c^2*d^2-25*c^3*d^2-33*a^2*d^3-27*a*b*d^3+42*b^2*d^3-4*a*c*d^3+33*b*c*d^3+32*c^2*d^3+10*a*d^4+47*c*d^4-3*d^5-23*a^4*e-45*a^3*b*e+41*a^2*b^2*e+47*a*b^3*e+15*b^4*e-2*a^3*c*e+12*a^2*b*c*e+13*a*b^2*c*e-45*b^3*c*e-28*a^2*c^2*e-3*a*b*c^2*e-37*b^2*c^2*e+39*a*c^3*e+37*c^4*e-12*a^3*d*e-48*a^2*b*d*e-5*a*b^2*d*e+47*b^3*d*e-41*a^2*c*d*e-36*a*b*c*d*e-37*b^2*c*d*e-a*c^2*d*e-38*b*c^2*d*e+17*c^3*d*e-29*a^2*d^2*e-3*a*b*d^2*e-23*b^2*d^2*e-19*a*c*d^2*e+43*b*c*d^2*e-48*c^2*d^2*e-46*a*d^3*e+48*b*d^3*e+40*c*d^3*e-15*d^4*e-23*a^3*e^2-22*a^2*b*e^2-50*a*b^2*e^2-33*b^3*e^2+27*a^2*c*e^2-46*a*b*c*e^2+29*b^2*c*e^2-14*a*c^2*e^2+9*b*c^2*e^2-43*c^3*e^2-19*a^2*d*e^2-38*a*b*d*e^2+12*b^2*d*e^2+18*a*c*d*e^2+20*b*c*d*e^2+3*c^2*d*e^2-9*a*d^2*e^2-27*b*d^2*e^2-6*c*d^2*e^2+38*d^3*e^2+43*a^2*e^3+43*a*b*e^3+3*b^2*e^3+10*a*c*e^3+8*b*c*e^3+13*c^2*e^3+37*a*d*e^3+b*d*e^3-21*c*d*e^3+27*d^2*e^3+26*a*e^4-29*b*e^4-39*c*e^4+29*d*e^4+21*e^5, a^4*b-45*a^2*c^2*d-6*a*b*c^2*d-42*b^2*c^2*d-4*a*c^3*d-49*b*c^3*d+14*c^4*d+35*a^3*d^2-3*a^2*b*d^2+23*a*b^2*d^2+21*b^3*d^2-24*a^2*c*d^2-14*a*b*c*d^2+20*b^2*c*d^2-20*a*c^2*d^2+41*b*c^2*d^2-34*c^3*d^2-13*a^2*d^3-48*a*b*d^3-13*b^2*d^3+38*a*c*d^3+21*b*c*d^3+40*c^2*d^3-28*a*d^4-34*b*d^4+38*c*d^4-24*d^5-48*a^4*e-2*a^3*b*e-35*a^2*b^2*e+2*a*b^3*e-25*b^4*e+47*a^3*c*e-14*a^2*b*c*e+25*a*b^2*c*e-12*b^3*c*e-11*a^2*c^2*e+22*a*b*c^2*e+15*b^2*c^2*e+17*a*c^3*e+47*b*c^3*e-43*c^4*e+28*a^3*d*e+9*a^2*b*d*e+6*a*b^2*d*e+30*a^2*c*d*e+31*a*b*c*d*e-2*b^2*c*d*e-6*a*c^2*d*e-45*b*c^2*d*e-24*c^3*d*e-39*a^2*d^2*e-7*a*b*d^2*e-11*b^2*d^2*e+8*a*c*d^2*e-47*b*c*d^2*e+c^2*d^2*e+30*a*d^3*e-30*b*d^3*e-38*c*d^3*e-14*d^4*e-25*a^3*e^2-14*a^2*b*e^2+24*a*b^2*e^2-37*b^3*e^2-14*a^2*c*e^2+40*a*b*c*e^2+27*b^2*c*e^2+22*a*c^2*e^2-38*b*c^2*e^2+43*c^3*e^2-44*a^2*d*e^2+28*a*b*d*e^2-4*b^2*d*e^2-26*a*c*d*e^2+18*b*c*d*e^2+24*c^2*d*e^2-35*a*d^2*e^2+6*b*d^2*e^2+5*c*d^2*e^2-38*d^3*e^2-37*a^2*e^3+34*a*b*e^3-27*b^2*e^3-4*a*c*e^3-3*b*c*e^3-16*c^2*e^3+22*a*d*e^3-4*b*d*e^3-41*c*d*e^3+25*d^2*e^3-38*a*e^4+49*b*e^4+c*e^4+14*d*e^4+47*e^5, a^5-45*a^2*c^2*d-14*a*b*c^2*d-47*b^2*c^2*d-8*a*c^3*d+13*b*c^3*d+50*c^4*d-34*a^3*d^2-5*a^2*b*d^2+36*a*b^2*d^2+11*b^3*d^2+41*a^2*c*d^2-32*a*b*c*d^2+41*b^2*c*d^2-40*a*c^2*d^2+14*b*c^2*d^2+5*c^3*d^2+25*a^2*d^3+10*a*b*d^3-24*b^2*d^3-33*b*c*d^3-21*c^2*d^3+a*d^4+44*b*d^4-46*c*d^4-23*d^5-13*a^4*e+13*a^3*b*e-49*a*b^3*e+18*b^4*e+2*a^3*c*e+15*a^2*b*c*e-14*a*b^2*c*e-38*b^3*c*e+34*a^2*c^2*e+42*a*b*c^2*e-42*b^2*c^2*e-36*a*c^3*e+35*b*c^3*e-11*c^4*e+20*a^3*d*e+41*a*b^2*d*e+40*b^3*d*e-39*a^2*c*d*e-35*a*b*c*d*e-7*b^2*c*d*e-34*a*c^2*d*e-35*b*c^2*d*e+45*c^3*d*e+17*a^2*d^2*e+39*a*b*d^2*e+5*b^2*d^2*e-35*a*c*d^2*e-26*b*c*d^2*e-47*c^2*d^2*e+5*a*d^3*e-2*b*d^3*e+44*c*d^3*e+9*d^4*e-12*a^3*e^2+49*a^2*b*e^2-2*a*b^2*e^2-11*b^3*e^2-49*a^2*c*e^2-16*a*b*c*e^2-34*b^2*c*e^2+19*a*c^2*e^2-24*b*c^2*e^2-33*c^3*e^2-39*a^2*d*e^2+2*a*b*d*e^2+46*b^2*d*e^2-17*a*c*d*e^2+47*b*c*d*e^2+39*c^2*d*e^2+13*a*d^2*e^2+50*b*d^2*e^2-11*c*d^2*e^2+3*d^3*e^2+22*a^2*e^3-50*a*b*e^3+30*b^2*e^3-22*a*c*e^3-29*b*c*e^3-40*c^2*e^3+34*a*d*e^3+15*b*d*e^3-17*c*d*e^3+43*d^2*e^3+46*a*e^4-19*b*e^4-46*c*e^4-39*d*e^4-e^5, e^6, d*e^5, c*e^5, b*e^5, a*e^5, d^2*e^4, c*d*e^4, b*d*e^4, a*d*e^4, c^2*e^4, b*c*e^4, a*c*e^4, b^2*e^4, a*b*e^4, a^2*e^4, d^3*e^3, c*d^2*e^3, b*d^2*e^3, a*d^2*e^3, c^2*d*e^3, b*c*d*e^3, a*c*d*e^3, b^2*d*e^3, a*b*d*e^3, a^2*d*e^3, c^3*e^3, b*c^2*e^3, a*c^2*e^3, b^2*c*e^3, a*b*c*e^3, a^2*c*e^3, b^3*e^3, a*b^2*e^3, a^2*b*e^3, a^3*e^3, d^4*e^2, c*d^3*e^2, b*d^3*e^2, a*d^3*e^2, c^2*d^2*e^2, b*c*d^2*e^2, a*c*d^2*e^2, b^2*d^2*e^2, a*b*d^2*e^2, a^2*d^2*e^2, c^3*d*e^2, b*c^2*d*e^2, a*c^2*d*e^2, b^2*c*d*e^2, a*b*c*d*e^2, a^2*c*d*e^2, b^3*d*e^2, a*b^2*d*e^2, a^2*b*d*e^2, a^3*d*e^2, c^4*e^2, b*c^3*e^2, a*c^3*e^2, b^2*c^2*e^2, a*b*c^2*e^2; TestSSresAttribs2tr(M, "AGR101n4d007s021%4"); /* options: 1 1 0 : Time: 5/9/10 (35 without LCM) options: 1 1 1 : Time: 6/8/25 lres Time: 5 nres Time: 5 sres Time: 693 */ kill M; // AGR101n4d008s020%1, too big? ideal M = c^5*d-49*a^4*d^2-36*a^3*b*d^2-a^2*b^2*d^2-26*a*b^3*d^2+2*b^4*d^2+8*a^3*c*d^2-46*a^2*b*c*d^2-43*a*b^2*c*d^2-46*b^3*c*d^2-3*a^2*c^2*d^2-43*a*b*c^2*d^2+49*b^2*c^2*d^2-10*a*c^3*d^2+35*b*c^3*d^2+20*c^4*d^2-42*a^3*d^3+45*a^2*b*d^3+32*a*b^2*d^3-45*b^3*d^3-27*a^2*c*d^3+13*a*b*c*d^3+25*b^2*c*d^3+8*a*c^2*d^3+9*b*c^2*d^3+9*c^3*d^3+45*a^2*d^4+30*a*b*d^4+39*b^2*d^4-23*a*c*d^4+2*b*c*d^4-16*c^2*d^4+32*a*d^5-34*b*d^5+39*c*d^5+12*d^6-29*a^5*e-23*a^4*b*e-29*a^3*b^2*e-a^2*b^3*e-20*a*b^4*e+42*b^5*e+20*a^4*c*e-27*a^3*b*c*e-5*a^2*b^2*c*e-14*b^4*c*e-27*a^3*c^2*e-7*a^2*b*c^2*e-25*a*b^2*c^2*e+14*b^3*c^2*e+19*a^2*c^3*e+43*a*b*c^3*e-31*b^2*c^3*e+37*a*c^4*e-34*b*c^4*e+44*c^5*e+21*a^4*d*e+22*a^3*b*d*e+14*a^2*b^2*d*e-35*a*b^3*d*e-29*b^4*d*e-9*a^3*c*d*e-41*a^2*b*c*d*e+28*a*b^2*c*d*e+35*b^3*c*d*e+48*a^2*c^2*d*e+26*a*b*c^2*d*e-47*b^2*c^2*d*e+18*a*c^3*d*e+8*b*c^3*d*e-46*c^4*d*e+50*a^3*d^2*e-46*a^2*b*d^2*e-41*a*b^2*d^2*e-44*b^3*d^2*e+7*a^2*c*d^2*e-a*b*c*d^2*e+38*b^2*c*d^2*e+33*a*c^2*d^2*e-24*b*c^2*d^2*e-7*c^3*d^2*e+27*a^2*d^3*e+19*a*b*d^3*e-14*b^2*d^3*e+9*a*c*d^3*e+3*b*c*d^3*e+34*c^2*d^3*e-49*a*d^4*e-2*b*d^4*e+9*c*d^4*e+17*d^5*e+12*a^4*e^2-17*a^3*b*e^2+16*a^2*b^2*e^2+2*a*b^3*e^2+25*b^4*e^2+49*a^3*c*e^2+10*a^2*b*c*e^2-43*a*b^2*c*e^2+5*b^3*c*e^2+4*a^2*c^2*e^2-44*a*b*c^2*e^2-25*b^2*c^2*e^2+15*a*c^3*e^2-44*b*c^3*e^2-17*c^4*e^2+17*a^3*d*e^2+40*a^2*b*d*e^2+3*a*b^2*d*e^2-25*b^3*d*e^2-47*a^2*c*d*e^2-45*a*b*c*d*e^2+9*b^2*c*d*e^2-41*a*c^2*d*e^2-36*b*c^2*d*e^2-17*c^3*d*e^2-15*a^2*d^2*e^2+49*a*b*d^2*e^2+13*b^2*d^2*e^2-39*a*c*d^2*e^2+36*b*c*d^2*e^2-32*c^2*d^2*e^2+23*a*d^3*e^2+14*b*d^3*e^2+10*c*d^3*e^2-d^4*e^2+24*a^3*e^3+27*a^2*b*e^3+31*a*b^2*e^3-45*b^3*e^3-50*a^2*c*e^3-a*b*c*e^3+43*b^2*c*e^3+46*a*c^2*e^3-25*b*c^2*e^3+2*c^3*e^3+44*a^2*d*e^3+43*a*b*d*e^3-30*b^2*d*e^3-18*a*c*d*e^3+44*b*c*d*e^3-34*c^2*d*e^3-49*a*d^2*e^3-18*b*d^2*e^3-21*c*d^2*e^3-43*d^3*e^3-26*a^2*e^4-18*a*b*e^4+6*b^2*e^4-48*a*c*e^4+6*b*c*e^4-16*c^2*e^4-2*a*d*e^4-21*b*d*e^4+5*c*d*e^4-18*d^2*e^4+33*a*e^5-23*b*e^5-48*c*e^5+37*d*e^5-44*e^6, b*c^4*d-26*a^4*d^2-47*a^3*b*d^2+28*a^2*b^2*d^2+5*a*b^3*d^2+37*b^4*d^2-32*a^3*c*d^2+44*a^2*b*c*d^2+13*a*b^2*c*d^2-45*b^3*c*d^2+35*a^2*c^2*d^2-18*a*b*c^2*d^2-3*b^2*c^2*d^2-4*a*c^3*d^2-27*b*c^3*d^2-37*a^3*d^3-44*a^2*b*d^3-36*a*b^2*d^3+49*b^3*d^3-16*a^2*c*d^3+24*a*b*c*d^3+43*b^2*c*d^3-40*a*c^2*d^3-3*b*c^2*d^3-16*c^3*d^3+6*a^2*d^4+46*a*b*d^4+8*b^2*d^4-11*a*c*d^4-4*b*c*d^4-40*c^2*d^4-31*a*d^5-41*b*d^5-35*c*d^5-35*d^6+5*a^5*e-20*a^4*b*e+48*a^3*b^2*e-42*a^2*b^3*e+46*a*b^4*e-28*b^5*e+42*a^4*c*e+22*a^3*b*c*e+23*a^2*b^2*c*e-6*a*b^3*c*e-2*b^4*c*e+26*a^3*c^2*e+28*a^2*b*c^2*e+28*a*b^2*c^2*e-31*b^3*c^2*e-50*a^2*c^3*e+3*a*b*c^3*e+39*b^2*c^3*e-21*b*c^4*e+24*c^5*e-a^4*d*e+12*a^3*b*d*e+43*a^2*b^2*d*e+17*a*b^3*d*e-33*b^4*d*e-31*a^3*c*d*e+11*a^2*b*c*d*e-16*a*b^2*c*d*e-49*b^3*c*d*e+6*a^2*c^2*d*e+49*a*b*c^2*d*e-47*b^2*c^2*d*e-40*a*c^3*d*e-11*b*c^3*d*e-7*a^3*d^2*e+10*a^2*b*d^2*e-37*a*b^2*d^2*e+37*b^3*d^2*e+49*a^2*c*d^2*e+11*b^2*c*d^2*e-43*a*c^2*d^2*e+46*b*c^2*d^2*e-18*c^3*d^2*e+38*a^2*d^3*e+20*a*b*d^3*e-22*b^2*d^3*e-32*a*c*d^3*e+41*b*c*d^3*e+c^2*d^3*e+7*a*d^4*e+18*b*d^4*e-12*c*d^4*e-15*d^5*e+34*a^4*e^2-a^3*b*e^2+47*a^2*b^2*e^2+47*a*b^3*e^2-37*b^4*e^2-36*a^3*c*e^2-21*a^2*b*c*e^2-3*b^3*c*e^2-34*a^2*c^2*e^2-4*a*b*c^2*e^2+33*b^2*c^2*e^2+19*a*c^3*e^2+3*b*c^3*e^2-13*c^4*e^2-45*a^3*d*e^2+28*a^2*b*d*e^2-23*a*b^2*d*e^2+30*b^3*d*e^2+15*a^2*c*d*e^2+a*b*c*d*e^2-50*a*c^2*d*e^2-6*b*c^2*d*e^2+32*c^3*d*e^2+17*a^2*d^2*e^2-15*a*b*d^2*e^2+6*b^2*d^2*e^2+15*a*c*d^2*e^2-b*c*d^2*e^2+41*c^2*d^2*e^2-47*a*d^3*e^2+49*b*d^3*e^2-4*c*d^3*e^2-5*d^4*e^2+35*a^3*e^3+36*a^2*b*e^3+49*a*b^2*e^3+b^3*e^3-11*a^2*c*e^3+a*b*c*e^3+18*b^2*c*e^3+19*a*c^2*e^3+11*b*c^2*e^3-41*c^3*e^3-42*a^2*d*e^3+6*a*b*d*e^3-23*b^2*d*e^3+47*a*c*d*e^3+35*b*c*d*e^3+39*c^2*d*e^3-30*a*d^2*e^3-21*b*d^2*e^3-48*c*d^2*e^3-6*d^3*e^3+38*a^2*e^4-43*a*b*e^4-10*b^2*e^4-a*c*e^4+2*b*c*e^4-29*c^2*e^4+31*a*d*e^4+24*b*d*e^4+18*c*d*e^4+38*d^2*e^4+36*a*e^5-32*b*e^5-17*c*e^5+36*d*e^5+13*e^6, a*c^4*d+8*a^4*d^2+41*a^3*b*d^2-36*a^2*b^2*d^2+7*a*b^3*d^2+35*b^4*d^2+19*a^3*c*d^2-31*a^2*b*c*d^2+23*a*b^2*c*d^2-18*b^3*c*d^2+14*a*b*c^2*d^2-8*b^2*c^2*d^2+31*a*c^3*d^2-46*b*c^3*d^2-29*c^4*d^2-42*a^3*d^3+46*a^2*b*d^3-24*a*b^2*d^3+46*b^3*d^3-18*a^2*c*d^3-49*a*b*c*d^3-6*b^2*c*d^3+20*a*c^2*d^3+17*b*c^2*d^3+38*c^3*d^3-36*a^2*d^4+16*a*b*d^4+23*b^2*d^4-34*a*c*d^4-9*b*c*d^4-18*c^2*d^4-18*a*d^5+26*b*d^5-9*c*d^5-3*d^6-17*a^5*e+32*a^4*b*e-23*a^3*b^2*e-4*a^2*b^3*e+42*a*b^4*e-43*b^5*e+28*a^4*c*e+5*a^3*b*c*e-14*a^2*b^2*c*e-43*a*b^3*c*e+41*b^4*c*e+2*a^3*c^2*e-27*a^2*b*c^2*e-35*a*b^2*c^2*e+2*b^3*c^2*e-42*a^2*c^3*e+47*a*b*c^3*e+50*b^2*c^3*e-a*c^4*e+10*b*c^4*e+47*c^5*e-23*a^4*d*e+25*a^3*b*d*e-41*a^2*b^2*d*e+32*a*b^3*d*e-35*b^4*d*e+14*a^3*c*d*e-25*a^2*b*c*d*e+47*a*b^2*c*d*e-32*b^3*c*d*e+50*a^2*c^2*d*e-30*a*b*c^2*d*e+39*b^2*c^2*d*e+30*a*c^3*d*e-33*b*c^3*d*e+37*c^4*d*e-21*a^3*d^2*e+34*a^2*b*d^2*e+7*a*b^2*d^2*e-43*b^3*d^2*e+13*a^2*c*d^2*e+32*a*b*c*d^2*e-35*b^2*c*d^2*e+18*a*c^2*d^2*e-2*b*c^2*d^2*e+9*c^3*d^2*e+13*a^2*d^3*e-32*a*b*d^3*e-9*b^2*d^3*e-35*a*c*d^3*e-14*b*c*d^3*e+9*c^2*d^3*e+19*a*d^4*e-50*b*d^4*e+28*c*d^4*e-40*d^5*e+17*a^4*e^2-44*a^3*b*e^2+30*a^2*b^2*e^2+41*a*b^3*e^2+20*b^4*e^2+21*a^3*c*e^2+48*a^2*b*c*e^2+15*a*b^2*c*e^2-40*b^3*c*e^2-6*a^2*c^2*e^2-29*a*b*c^2*e^2-42*b^2*c^2*e^2-40*a*c^3*e^2-48*b*c^3*e^2+36*c^4*e^2+38*a^3*d*e^2+19*a^2*b*d*e^2+41*a*b^2*d*e^2+34*b^3*d*e^2+20*a^2*c*d*e^2-23*a*b*c*d*e^2-2*b^2*c*d*e^2+36*a*c^2*d*e^2-37*b*c^2*d*e^2+9*c^3*d*e^2-47*a^2*d^2*e^2-35*a*b*d^2*e^2+13*b^2*d^2*e^2-20*a*c*d^2*e^2-45*b*c*d^2*e^2+17*c^2*d^2*e^2-32*a*d^3*e^2+13*b*d^3*e^2-4*c*d^3*e^2-26*d^4*e^2+32*a^3*e^3-25*a^2*b*e^3+30*a*b^2*e^3-12*b^3*e^3+28*a^2*c*e^3+41*a*b*c*e^3-49*b^2*c*e^3+35*a*c^2*e^3+38*b*c^2*e^3+49*c^3*e^3-9*a^2*d*e^3-31*a*b*d*e^3-6*b^2*d*e^3+29*a*c*d*e^3+13*b*c*d*e^3-14*c^2*d*e^3+36*a*d^2*e^3+33*b*d^2*e^3-46*c*d^2*e^3+50*d^3*e^3-47*a^2*e^4+5*a*b*e^4+36*b^2*e^4-5*a*c*e^4+4*b*c*e^4-20*c^2*e^4+29*a*d*e^4+25*b*d*e^4-24*c*d*e^4-10*d^2*e^4-2*a*e^5-29*b*e^5-34*c*e^5-d*e^5+e^6, b^2*c^3*d-49*a^4*d^2+36*a^3*b*d^2-3*a^2*b^2*d^2+12*a*b^3*d^2+11*b^4*d^2+10*a^3*c*d^2+9*a^2*b*c*d^2-13*a*b^2*c*d^2+43*b^3*c*d^2-27*a^2*c^2*d^2-20*a*b*c^2*d^2+34*b^2*c^2*d^2-30*a*c^3*d^2-50*b*c^3*d^2+43*c^4*d^2+17*a^3*d^3+5*a^2*b*d^3+16*a*b^2*d^3+27*b^3*d^3-26*a^2*c*d^3+17*a*b*c*d^3-31*b^2*c*d^3-43*a*c^2*d^3-18*b*c^2*d^3-8*c^3*d^3-8*a^2*d^4+8*a*b*d^4+23*b^2*d^4+7*a*c*d^4-48*b*c*d^4+21*c^2*d^4+5*a*d^5+4*b*d^5+40*c*d^5-22*d^6+3*a^5*e-a^4*b*e+26*a^3*b^2*e+16*a^2*b^3*e-29*a*b^4*e-50*b^5*e-6*a^4*c*e+31*a^3*b*c*e+43*a^2*b^2*c*e+12*a*b^3*c*e+31*b^4*c*e-21*a^3*c^2*e+25*a^2*b*c^2*e+20*a*b^2*c^2*e+15*b^3*c^2*e-4*a^2*c^3*e-48*a*b*c^3*e-29*b^2*c^3*e+43*a*c^4*e-41*b*c^4*e-15*c^5*e-13*a^4*d*e-29*a^3*b*d*e+7*a^2*b^2*d*e+4*a*b^3*d*e-50*b^4*d*e+3*a^3*c*d*e+4*a^2*b*c*d*e+7*a*b^2*c*d*e+4*b^3*c*d*e+16*a^2*c^2*d*e-42*a*b*c^2*d*e+36*b^2*c^2*d*e-5*a*c^3*d*e+13*b*c^3*d*e+17*c^4*d*e+18*a^3*d^2*e-16*a^2*b*d^2*e-32*a*b^2*d^2*e-16*b^3*d^2*e-34*a^2*c*d^2*e-22*a*b*c*d^2*e-12*b^2*c*d^2*e+35*a*c^2*d^2*e+33*b*c^2*d^2*e-47*c^3*d^2*e+12*a^2*d^3*e-43*a*b*d^3*e+11*b^2*d^3*e+2*a*c*d^3*e+42*b*c*d^3*e-18*c^2*d^3*e+44*a*d^4*e+25*b*d^4*e+41*c*d^4*e+40*d^5*e+40*a^4*e^2-3*a^3*b*e^2-8*a^2*b^2*e^2+a*b^3*e^2-27*b^4*e^2+15*a^3*c*e^2+49*a^2*b*c*e^2-14*a*b^2*c*e^2+31*b^3*c*e^2+36*a^2*c^2*e^2-14*a*b*c^2*e^2-31*b^2*c^2*e^2+48*a*c^3*e^2-24*b*c^3*e^2-30*c^4*e^2-47*a^3*d*e^2+12*a^2*b*d*e^2+44*a*b^2*d*e^2+47*b^3*d*e^2-5*a^2*c*d*e^2+23*a*b*c*d*e^2+48*b^2*c*d*e^2-25*a*c^2*d*e^2-7*b*c^2*d*e^2+32*a^2*d^2*e^2+35*a*b*d^2*e^2-19*b^2*d^2*e^2+19*a*c*d^2*e^2+26*b*c*d^2*e^2+26*c^2*d^2*e^2+8*a*d^3*e^2-21*b*d^3*e^2-6*c*d^3*e^2-35*d^4*e^2-30*a^3*e^3+36*a^2*b*e^3-27*a*b^2*e^3-33*b^3*e^3-50*a^2*c*e^3+41*a*b*c*e^3+13*b^2*c*e^3+20*a*c^2*e^3+36*b*c^2*e^3+14*c^3*e^3+40*a^2*d*e^3-35*a*b*d*e^3+11*b^2*d*e^3+36*a*c*d*e^3+23*b*c*d*e^3-34*c^2*d*e^3+25*a*d^2*e^3-14*b*d^2*e^3-5*c*d^2*e^3+11*d^3*e^3+42*a^2*e^4-48*a*b*e^4-27*b^2*e^4-17*a*c*e^4+32*b*c*e^4-3*c^2*e^4-3*a*d*e^4-33*b*d*e^4-3*c*d*e^4-14*d^2*e^4+8*a*e^5+14*b*e^5+3*c*e^5-34*d*e^5-46*e^6, a*b*c^3*d-20*a^4*d^2+23*a^3*b*d^2-14*a^2*b^2*d^2+29*a*b^3*d^2-36*b^4*d^2-48*a^3*c*d^2+39*a^2*b*c*d^2-34*a*b^2*c*d^2+b^3*c*d^2-25*a^2*c^2*d^2+22*a*b*c^2*d^2-12*b^2*c^2*d^2+48*a*c^3*d^2-41*b*c^3*d^2+13*c^4*d^2-24*a^3*d^3-43*a^2*b*d^3-31*a*b^2*d^3-13*b^3*d^3+10*a^2*c*d^3-16*a*b*c*d^3+48*b^2*c*d^3-18*a*c^2*d^3+7*b*c^2*d^3+8*c^3*d^3-14*a^2*d^4-14*a*b*d^4+49*b^2*d^4+43*a*c*d^4+7*b*c*d^4-50*c^2*d^4-21*a*d^5-33*b*d^5-44*c*d^5-40*d^6-42*a^5*e+39*a^4*b*e-14*a^3*b^2*e+34*a^2*b^3*e+22*a*b^4*e+37*b^5*e+24*a^4*c*e+39*a^3*b*c*e-43*a^2*b^2*c*e-40*a*b^3*c*e-6*b^4*c*e-45*a^3*c^2*e+18*a^2*b*c^2*e-8*a*b^2*c^2*e+22*b^3*c^2*e-36*a^2*c^3*e+31*a*b*c^3*e+15*b^2*c^3*e+7*a*c^4*e-18*b*c^4*e-31*c^5*e-20*a^4*d*e+25*a^3*b*d*e-11*a^2*b^2*d*e-21*a*b^3*d*e-23*b^4*d*e+18*a^3*c*d*e-49*a^2*b*c*d*e+5*a*b^2*c*d*e+21*b^3*c*d*e-2*a^2*c^2*d*e+42*a*b*c^2*d*e-37*b^2*c^2*d*e+28*a*c^3*d*e-8*b*c^3*d*e+c^4*d*e+10*a^3*d^2*e-16*a^2*b*d^2*e-20*a*b^2*d^2*e+42*b^3*d^2*e+23*a^2*c*d^2*e-16*a*b*c*d^2*e+39*b^2*c*d^2*e+3*a*c^2*d^2*e+25*b*c^2*d^2*e-16*c^3*d^2*e-33*a^2*d^3*e-28*a*b*d^3*e+4*b^2*d^3*e-15*a*c*d^3*e-30*b*c*d^3*e-5*c^2*d^3*e-8*b*d^4*e-21*c*d^4*e+6*d^5*e-9*a^4*e^2-23*a^3*b*e^2-45*a^2*b^2*e^2+33*a*b^3*e^2+14*b^4*e^2+8*a^3*c*e^2+5*a^2*b*c*e^2-13*a*b^2*c*e^2-39*b^3*c*e^2-4*a^2*c^2*e^2+30*a*b*c^2*e^2-38*b^2*c^2*e^2+24*a*c^3*e^2-29*b*c^3*e^2-3*c^4*e^2+3*a^3*d*e^2+43*a^2*b*d*e^2-21*a*b^2*d*e^2-45*b^3*d*e^2-3*a^2*c*d*e^2-22*a*b*c*d*e^2+16*b^2*c*d*e^2-42*b*c^2*d*e^2-43*c^3*d*e^2-10*a*b*d^2*e^2+23*b^2*d^2*e^2-36*a*c*d^2*e^2+29*b*c*d^2*e^2-11*c^2*d^2*e^2+18*a*d^3*e^2-46*b*d^3*e^2-34*c*d^3*e^2+21*d^4*e^2+4*a^3*e^3+23*a^2*b*e^3-18*a*b^2*e^3-10*b^3*e^3+3*a^2*c*e^3+a*b*c*e^3-32*b^2*c*e^3-19*a*c^2*e^3-5*b*c^2*e^3+25*c^3*e^3-40*a^2*d*e^3-37*a*b*d*e^3-10*b^2*d*e^3-20*a*c*d*e^3+35*b*c*d*e^3+2*c^2*d*e^3+46*a*d^2*e^3+46*b*d^2*e^3+25*c*d^2*e^3+14*d^3*e^3-28*a^2*e^4+24*a*b*e^4-38*b^2*e^4+11*a*c*e^4+15*b*c*e^4-10*c^2*e^4-32*a*d*e^4+37*b*d*e^4+21*c*d*e^4-25*d^2*e^4-47*a*e^5-32*b*e^5+5*c*e^5+17*d*e^5+44*e^6, a^2*c^3*d+25*a^4*d^2-40*a^3*b*d^2-49*a^2*b^2*d^2+30*a*b^3*d^2-36*b^4*d^2+41*a^3*c*d^2+23*a^2*b*c*d^2-16*a*b^2*c*d^2-20*b^3*c*d^2-46*a^2*c^2*d^2-29*a*b*c^2*d^2-14*b^2*c^2*d^2-38*a*c^3*d^2+9*b*c^3*d^2+50*c^4*d^2-20*a^3*d^3-14*a^2*b*d^3+13*a*b^2*d^3+5*b^3*d^3+7*a^2*c*d^3+46*a*b*c*d^3+40*b^2*c*d^3-46*a*c^2*d^3+27*b*c^2*d^3-5*c^3*d^3+43*a^2*d^4+5*a*b*d^4+3*b^2*d^4+29*a*c*d^4-43*b*c*d^4-31*c^2*d^4-24*a*d^5-45*b*d^5-26*c*d^5-6*d^6+18*a^5*e+22*a^4*b*e-12*a^3*b^2*e+40*a^2*b^3*e-8*a*b^4*e+36*b^5*e+5*a^4*c*e+46*a^3*b*c*e+6*a^2*b^2*c*e-39*a*b^3*c*e-29*b^4*c*e+36*a^3*c^2*e+35*a^2*b*c^2*e+11*a*b^2*c^2*e-12*b^3*c^2*e+13*a^2*c^3*e+15*a*b*c^3*e+38*b^2*c^3*e-4*a*c^4*e-46*b*c^4*e+25*c^5*e-31*a^4*d*e+35*a^3*b*d*e+37*a^2*b^2*d*e+27*a*b^3*d*e-30*b^4*d*e-37*a^3*c*d*e-2*a^2*b*c*d*e+10*a*b^2*c*d*e+12*b^3*c*d*e+39*a^2*c^2*d*e+35*a*b*c^2*d*e-17*b^2*c^2*d*e-30*a*c^3*d*e+32*b*c^3*d*e+41*c^4*d*e+49*a^3*d^2*e-42*a^2*b*d^2*e-22*a*b^2*d^2*e-3*b^3*d^2*e+17*a^2*c*d^2*e+31*a*b*c*d^2*e+23*b^2*c*d^2*e+4*a*c^2*d^2*e+50*b*c^2*d^2*e+43*c^3*d^2*e+17*a^2*d^3*e-30*a*b*d^3*e+43*b^2*d^3*e+7*a*c*d^3*e+30*b*c*d^3*e+37*c^2*d^3*e-a*d^4*e+6*b*d^4*e+22*c*d^4*e-34*d^5*e-48*a^4*e^2+14*a^3*b*e^2+17*a^2*b^2*e^2-39*a*b^3*e^2+37*b^4*e^2-27*a^3*c*e^2+14*a^2*b*c*e^2-43*a*b^2*c*e^2+42*b^3*c*e^2-31*a^2*c^2*e^2+43*a*b*c^2*e^2-34*b^2*c^2*e^2-40*a*c^3*e^2-14*b*c^3*e^2+19*c^4*e^2+11*a^3*d*e^2+23*a^2*b*d*e^2+11*a*b^2*d*e^2+22*b^3*d*e^2+41*a^2*c*d*e^2-20*a*b*c*d*e^2+b^2*c*d*e^2-34*a*c^2*d*e^2-39*b*c^2*d*e^2-20*c^3*d*e^2+25*a^2*d^2*e^2+33*a*b*d^2*e^2-38*b^2*d^2*e^2-34*a*c*d^2*e^2-37*b*c*d^2*e^2-15*c^2*d^2*e^2-13*a*d^3*e^2-42*b*d^3*e^2+49*c*d^3*e^2+29*d^4*e^2-48*a^3*e^3+49*a^2*b*e^3-50*a*b^2*e^3-44*b^3*e^3-42*a^2*c*e^3+14*a*b*c*e^3-34*b^2*c*e^3+3*a*c^2*e^3-b*c^2*e^3+28*c^3*e^3+24*a^2*d*e^3+37*a*b*d*e^3+29*b^2*d*e^3-a*c*d*e^3+31*b*c*d*e^3-14*c^2*d*e^3-36*a*d^2*e^3-4*b*d^2*e^3+29*c*d^2*e^3-47*d^3*e^3-36*a^2*e^4-13*a*b*e^4-45*b^2*e^4-23*a*c*e^4-32*b*c*e^4+2*c^2*e^4+11*a*d*e^4-24*b*d*e^4-46*c*d*e^4-40*d^2*e^4-4*a*e^5-29*b*e^5+14*c*e^5-44*d*e^5+32*e^6, b^3*c^2*d+13*a^4*d^2+14*a^3*b*d^2-11*a^2*b^2*d^2-12*a*b^3*d^2-8*b^4*d^2-46*a^3*c*d^2-26*a^2*b*c*d^2+28*a*b^2*c*d^2+13*b^3*c*d^2-36*a^2*c^2*d^2+35*a*b*c^2*d^2+49*b^2*c^2*d^2+32*a*c^3*d^2+17*b*c^3*d^2+34*c^4*d^2-8*a^3*d^3-10*a^2*b*d^3+31*a*b^2*d^3-22*b^3*d^3+a^2*c*d^3+32*a*b*c*d^3+33*b^2*c*d^3+34*a*c^2*d^3-36*b*c^2*d^3-11*c^3*d^3-42*a^2*d^4-15*a*b*d^4-3*b^2*d^4-48*a*c*d^4+12*b*c*d^4+35*c^2*d^4-43*a*d^5+9*b*d^5+47*c*d^5+19*d^6-18*a^5*e+9*a^4*b*e+34*a^3*b^2*e+5*a^2*b^3*e+46*a*b^4*e-34*b^5*e-42*a^4*c*e-36*a^3*b*c*e+5*a^2*b^2*c*e+43*a*b^3*c*e-18*b^4*c*e+21*a^3*c^2*e-45*a^2*b*c^2*e-31*a*b^2*c^2*e+2*b^3*c^2*e+a*b*c^3*e-45*b^2*c^3*e+41*a*c^4*e+37*b*c^4*e-32*c^5*e+19*a^4*d*e-30*a^3*b*d*e+5*a^2*b^2*d*e+17*a*b^3*d*e+47*b^4*d*e-23*a^3*c*d*e+4*a^2*b*c*d*e+14*a*b^2*c*d*e-31*b^3*c*d*e+50*a^2*c^2*d*e-18*a*b*c^2*d*e-37*b^2*c^2*d*e-35*a*c^3*d*e+29*b*c^3*d*e-28*c^4*d*e+3*a^3*d^2*e+13*a^2*b*d^2*e-30*a*b^2*d^2*e-9*b^3*d^2*e+20*a^2*c*d^2*e+17*a*b*c*d^2*e-21*b^2*c*d^2*e-41*a*c^2*d^2*e-32*b*c^2*d^2*e+33*c^3*d^2*e-3*a^2*d^3*e-23*a*b*d^3*e-47*b^2*d^3*e-19*c^2*d^3*e+12*a*d^4*e-32*b*d^4*e-37*c*d^4*e+20*d^5*e+21*a^4*e^2+18*a^3*b*e^2-4*a^2*b^2*e^2+25*a*b^3*e^2-13*b^4*e^2+28*a^3*c*e^2-28*a^2*b*c*e^2-37*a*b^2*c*e^2-32*b^3*c*e^2+8*a^2*c^2*e^2+34*a*b*c^2*e^2-21*b^2*c^2*e^2+15*a*c^3*e^2-39*b*c^3*e^2-45*c^4*e^2-26*a^3*d*e^2+34*a^2*b*d*e^2-25*a*b^2*d*e^2+24*b^3*d*e^2+5*a^2*c*d*e^2+36*a*b*c*d*e^2-27*b^2*c*d*e^2+31*a*c^2*d*e^2+31*b*c^2*d*e^2+13*c^3*d*e^2-3*a^2*d^2*e^2-18*a*b*d^2*e^2+47*b^2*d^2*e^2+20*a*c*d^2*e^2+8*b*c*d^2*e^2-37*c^2*d^2*e^2+21*a*d^3*e^2+3*b*d^3*e^2-34*c*d^3*e^2+28*d^4*e^2-19*a^3*e^3+33*a^2*b*e^3-50*a*b^2*e^3-44*b^3*e^3+17*a^2*c*e^3-48*a*b*c*e^3-3*b^2*c*e^3+33*a*c^2*e^3+13*b*c^2*e^3-29*c^3*e^3+38*a^2*d*e^3-44*a*b*d*e^3-36*b^2*d*e^3-17*a*c*d*e^3+38*b*c*d*e^3+47*c^2*d*e^3+4*a*d^2*e^3-11*b*d^2*e^3-14*c*d^2*e^3-46*d^3*e^3-17*a^2*e^4-23*a*b*e^4+26*b^2*e^4+24*a*c*e^4-37*b*c*e^4+34*c^2*e^4+24*a*d*e^4-32*b*d*e^4-19*c*d*e^4+15*d^2*e^4-33*a*e^5+7*b*e^5-29*c*e^5+37*d*e^5-16*e^6, a*b^2*c^2*d-26*a^4*d^2-24*a^3*b*d^2-36*a^2*b^2*d^2+26*a*b^3*d^2+26*b^4*d^2+44*a^3*c*d^2-31*a^2*b*c*d^2-49*a*b^2*c*d^2-30*b^3*c*d^2-13*a^2*c^2*d^2+49*a*b*c^2*d^2-50*b^2*c^2*d^2+27*a*c^3*d^2+24*c^4*d^2-47*a^3*d^3+29*a^2*b*d^3+31*a*b^2*d^3-30*b^3*d^3+39*a^2*c*d^3+23*a*b*c*d^3+5*b^2*c*d^3-30*a*c^2*d^3-20*b*c^2*d^3-27*c^3*d^3-40*a^2*d^4+36*a*b*d^4+28*b^2*d^4+29*a*c*d^4+2*b*c*d^4+14*c^2*d^4-41*a*d^5+22*b*d^5+22*c*d^5+9*d^6-22*a^5*e-33*a^4*b*e-19*a^3*b^2*e+30*a^2*b^3*e+4*a*b^4*e+42*b^5*e-13*a^4*c*e+27*a^3*b*c*e-10*a^2*b^2*c*e+21*a*b^3*c*e-46*b^4*c*e-22*a^3*c^2*e-9*a^2*b*c^2*e+11*a*b^2*c^2*e+33*b^3*c^2*e-4*a^2*c^3*e-26*a*b*c^3*e+47*b^2*c^3*e+41*a*c^4*e-23*b*c^4*e-35*c^5*e-28*a^4*d*e+6*a^3*b*d*e+39*a^2*b^2*d*e+12*a*b^3*d*e-46*b^4*d*e+5*a^3*c*d*e-4*a^2*b*c*d*e+45*a*b^2*c*d*e-8*b^3*c*d*e-46*a^2*c^2*d*e-34*a*b*c^2*d*e-47*b^2*c^2*d*e+20*a*c^3*d*e+10*b*c^3*d*e+2*c^4*d*e+22*a^3*d^2*e-5*a^2*b*d^2*e+24*a*b^2*d^2*e+27*b^3*d^2*e+10*a^2*c*d^2*e-27*a*b*c*d^2*e+13*b^2*c*d^2*e+38*a*c^2*d^2*e+20*b*c^2*d^2*e-46*c^3*d^2*e-47*a^2*d^3*e+42*a*b*d^3*e-34*b^2*d^3*e-3*a*c*d^3*e+4*b*c*d^3*e+4*c^2*d^3*e+47*a*d^4*e+46*b*d^4*e+29*c*d^4*e+28*d^5*e+18*a^4*e^2+19*a^3*b*e^2+6*a^2*b^2*e^2-38*a*b^3*e^2-22*b^4*e^2-21*a^3*c*e^2+44*a^2*b*c*e^2-23*a*b^2*c*e^2-20*b^3*c*e^2-35*a^2*c^2*e^2-33*a*b*c^2*e^2+b^2*c^2*e^2+2*a*c^3*e^2+36*b*c^3*e^2+29*c^4*e^2-14*a^2*b*d*e^2-44*a*b^2*d*e^2+7*b^3*d*e^2+17*a^2*c*d*e^2-2*a*b*c*d*e^2+18*b^2*c*d*e^2-41*a*c^2*d*e^2+41*b*c^2*d*e^2+40*c^3*d*e^2+6*a^2*d^2*e^2-15*a*b*d^2*e^2-39*b^2*d^2*e^2-50*a*c*d^2*e^2-43*b*c*d^2*e^2-3*c^2*d^2*e^2+29*a*d^3*e^2-3*b*d^3*e^2+48*c*d^3*e^2+22*d^4*e^2+24*a^3*e^3+5*a^2*b*e^3-3*a*b^2*e^3-36*b^3*e^3-50*a^2*c*e^3+23*a*b*c*e^3+9*b^2*c*e^3+3*a*c^2*e^3+45*b*c^2*e^3-24*c^3*e^3-30*a^2*d*e^3+31*a*b*d*e^3+26*b^2*d*e^3-37*a*c*d*e^3-38*b*c*d*e^3-36*c^2*d*e^3-8*a*d^2*e^3-41*b*d^2*e^3-40*c*d^2*e^3+25*d^3*e^3-25*a^2*e^4+12*a*b*e^4-25*b^2*e^4-39*a*c*e^4-19*b*c*e^4-21*c^2*e^4+34*a*d*e^4-35*b*d*e^4+9*c*d*e^4-32*d^2*e^4+29*a*e^5+32*b*e^5-25*c*e^5-31*d*e^5-34*e^6, a^2*b*c^2*d+14*a^4*d^2+25*a^3*b*d^2-2*a^2*b^2*d^2-32*a*b^3*d^2-31*b^4*d^2-40*a^3*c*d^2-15*a^2*b*c*d^2+50*a*b^2*c*d^2+b^3*c*d^2-7*a^2*c^2*d^2-14*a*b*c^2*d^2+8*b^2*c^2*d^2+25*a*c^3*d^2+6*b*c^3*d^2+25*c^4*d^2-20*a^3*d^3+a^2*b*d^3-27*a*b^2*d^3+24*b^3*d^3+33*a^2*c*d^3-14*a*b*c*d^3-48*b^2*c*d^3+10*a*c^2*d^3+8*b*c^2*d^3+13*c^3*d^3-11*a^2*d^4+41*a*b*d^4+48*b^2*d^4+29*a*c*d^4-29*b*c*d^4+40*c^2*d^4+50*a*d^5+33*b*d^5-35*c*d^5-17*d^6-31*a^5*e+42*a^4*b*e+48*a^3*b^2*e-48*a^2*b^3*e-6*a*b^4*e+27*b^5*e+31*a^4*c*e+6*a^3*b*c*e-20*a^2*b^2*c*e-10*a*b^3*c*e-34*b^4*c*e-45*a^3*c^2*e+15*a^2*b*c^2*e+37*a*b^2*c^2*e+34*b^3*c^2*e-14*a^2*c^3*e-9*a*b*c^3*e-33*b^2*c^3*e-42*a*c^4*e+20*b*c^4*e+4*c^5*e+28*a^4*d*e+10*a^3*b*d*e-23*a^2*b^2*d*e-17*a*b^3*d*e-44*b^4*d*e-8*a^3*c*d*e-13*a^2*b*c*d*e+35*a*b^2*c*d*e-49*b^3*c*d*e-23*a^2*c^2*d*e-43*a*b*c^2*d*e+11*b^2*c^2*d*e+45*a*c^3*d*e-38*b*c^3*d*e-44*c^4*d*e+45*a^3*d^2*e+9*a^2*b*d^2*e+31*a*b^2*d^2*e-18*b^3*d^2*e-30*a^2*c*d^2*e+4*a*b*c*d^2*e+50*b^2*c*d^2*e+24*a*c^2*d^2*e+24*b*c^2*d^2*e-11*c^3*d^2*e-11*a^2*d^3*e-36*a*b*d^3*e+5*b^2*d^3*e+26*a*c*d^3*e-18*b*c*d^3*e-41*c^2*d^3*e-2*a*d^4*e+17*b*d^4*e+46*c*d^4*e+9*d^5*e-49*a^4*e^2-13*a^3*b*e^2+47*a^2*b^2*e^2+19*a*b^3*e^2+42*b^4*e^2+15*a^3*c*e^2-48*a^2*b*c*e^2+33*a*b^2*c*e^2-28*b^3*c*e^2-5*a^2*c^2*e^2-32*a*b*c^2*e^2+2*b^2*c^2*e^2-25*a*c^3*e^2-8*b*c^3*e^2+8*c^4*e^2-48*a^3*d*e^2-12*a^2*b*d*e^2-49*a*b^2*d*e^2+49*b^3*d*e^2-4*a^2*c*d*e^2-40*a*b*c*d*e^2+42*b^2*c*d*e^2-11*a*c^2*d*e^2+12*b*c^2*d*e^2+5*c^3*d*e^2+40*a^2*d^2*e^2+21*a*b*d^2*e^2-37*b^2*d^2*e^2+10*a*c*d^2*e^2-38*b*c*d^2*e^2-22*c^2*d^2*e^2-a*d^3*e^2+20*b*d^3*e^2-31*c*d^3*e^2-15*d^4*e^2+31*a^3*e^3-24*a^2*b*e^3-6*b^3*e^3-10*a^2*c*e^3-27*a*b*c*e^3+15*b^2*c*e^3-40*b*c^2*e^3+36*c^3*e^3+12*a^2*d*e^3+32*a*b*d*e^3-39*b^2*d*e^3-9*a*c*d*e^3+13*b*c*d*e^3+35*c^2*d*e^3+31*a*d^2*e^3-4*b*d^2*e^3+14*c*d^2*e^3+19*d^3*e^3-36*a^2*e^4-44*a*b*e^4-10*b^2*e^4+29*a*c*e^4-26*b*c*e^4+43*c^2*e^4+5*a*d*e^4+3*b*d*e^4-17*c*d*e^4+48*d^2*e^4-16*a*e^5+2*b*e^5-41*c*e^5-15*d*e^5-19*e^6, a^3*c^2*d+17*a^4*d^2+4*a^3*b*d^2+a^2*b^2*d^2+20*a*b^3*d^2-36*b^4*d^2-13*a^3*c*d^2+40*a^2*b*c*d^2-21*a*b^2*c*d^2-35*b^3*c*d^2-33*a^2*c^2*d^2-a*b*c^2*d^2+12*b^2*c^2*d^2+33*a*c^3*d^2-34*b*c^3*d^2-11*c^4*d^2+9*a^3*d^3-32*a^2*b*d^3+42*a*b^2*d^3-49*b^3*d^3-12*a^2*c*d^3-12*a*b*c*d^3+12*b^2*c*d^3+20*a*c^2*d^3+44*b*c^2*d^3+15*c^3*d^3+16*a^2*d^4+46*a*b*d^4+26*b^2*d^4+2*a*c*d^4-28*b*c*d^4-45*c^2*d^4+17*a*d^5-29*b*d^5+28*c*d^5-39*d^6+16*a^5*e+50*a^4*b*e+5*a^3*b^2*e+5*a^2*b^3*e-30*a*b^4*e-8*b^5*e+29*a^4*c*e-48*a^3*b*c*e-33*a^2*b^2*c*e-25*a*b^3*c*e+40*b^4*c*e-31*a^3*c^2*e-15*a^2*b*c^2*e+2*a*b^2*c^2*e+28*b^3*c^2*e-39*a^2*c^3*e+10*a*b*c^3*e-35*b^2*c^3*e+33*a*c^4*e-26*b*c^4*e-23*c^5*e+27*a^4*d*e-34*a^3*b*d*e+9*a^2*b^2*d*e+22*a*b^3*d*e-35*b^4*d*e+24*a^3*c*d*e+6*a^2*b*c*d*e+29*a*b^2*c*d*e-43*b^3*c*d*e+12*a^2*c^2*d*e+50*a*b*c^2*d*e-21*b^2*c^2*d*e-5*a*c^3*d*e-3*b*c^3*d*e-25*c^4*d*e+38*a^3*d^2*e-37*a^2*b*d^2*e+6*a*b^2*d^2*e+47*b^3*d^2*e+25*a^2*c*d^2*e+27*a*b*c*d^2*e+6*b^2*c*d^2*e-12*a*c^2*d^2*e-45*b*c^2*d^2*e-31*c^3*d^2*e-40*a^2*d^3*e+44*b^2*d^3*e-32*a*c*d^3*e-4*b*c*d^3*e-31*c^2*d^3*e+16*a*d^4*e-24*b*d^4*e+40*c*d^4*e-13*d^5*e-10*a^4*e^2+26*a^3*b*e^2+12*a^2*b^2*e^2+45*a*b^3*e^2+43*b^4*e^2+26*a^3*c*e^2+21*a^2*b*c*e^2-3*a*b^2*c*e^2-18*b^3*c*e^2+24*a^2*c^2*e^2+20*a*b*c^2*e^2-13*b^2*c^2*e^2+43*a*c^3*e^2+34*b*c^3*e^2-24*c^4*e^2+29*a^3*d*e^2+13*a^2*b*d*e^2-7*a*b^2*d*e^2-5*b^3*d*e^2+45*a^2*c*d*e^2+10*a*b*c*d*e^2+30*b^2*c*d*e^2-13*a*c^2*d*e^2+43*b*c^2*d*e^2+37*c^3*d*e^2+29*a^2*d^2*e^2+46*a*b*d^2*e^2+33*b^2*d^2*e^2+18*a*c*d^2*e^2-22*b*c*d^2*e^2+13*c^2*d^2*e^2+44*a*d^3*e^2+38*b*d^3*e^2+27*c*d^3*e^2+44*d^4*e^2-29*a^2*b*e^3-36*a*b^2*e^3+40*b^3*e^3+9*a^2*c*e^3-19*a*b*c*e^3+36*b^2*c*e^3+5*a*c^2*e^3+20*b*c^2*e^3+3*c^3*e^3+49*a^2*d*e^3-46*a*b*d*e^3+7*b^2*d*e^3-26*a*c*d*e^3+17*b*c*d*e^3-48*c^2*d*e^3-9*a*d^2*e^3-25*b*d^2*e^3-25*c*d^2*e^3-12*d^3*e^3+13*a^2*e^4+a*b*e^4+5*b^2*e^4+44*a*c*e^4+14*b*c*e^4+42*c^2*e^4+16*a*d*e^4+12*b*d*e^4+20*c*d*e^4+16*d^2*e^4-27*a*e^5+13*b*e^5+38*c*e^5-d*e^5-26*e^6, b^4*c*d-16*a^4*d^2-19*a^3*b*d^2+43*a^2*b^2*d^2+18*a*b^3*d^2-14*b^4*d^2-6*a^3*c*d^2-33*a^2*b*c*d^2-38*a*b^2*c*d^2-4*b^3*c*d^2+16*a^2*c^2*d^2-38*a*b*c^2*d^2+40*b^2*c^2*d^2+11*a*c^3*d^2+36*b*c^3*d^2+26*c^4*d^2+a^3*d^3-37*a^2*b*d^3-5*a*b^2*d^3-36*b^3*d^3+38*a^2*c*d^3+32*a*b*c*d^3+12*b^2*c*d^3+24*a*c^2*d^3-40*b*c^2*d^3-9*c^3*d^3+15*a^2*d^4+36*a*b*d^4-50*b^2*d^4-43*a*c*d^4+43*b*c*d^4+33*c^2*d^4-8*a*d^5-28*b*d^5-42*c*d^5-20*d^6+16*a^5*e+4*a^4*b*e+41*a^3*b^2*e+18*a^2*b^3*e+26*a*b^4*e+12*b^5*e+3*a^4*c*e-50*a^3*b*c*e+12*a^2*b^2*c*e-6*a*b^3*c*e-40*b^4*c*e+48*a^3*c^2*e+46*a^2*b*c^2*e-24*a*b^2*c^2*e+47*b^3*c^2*e-30*a^2*c^3*e+30*a*b*c^3*e+19*b^2*c^3*e-9*a*c^4*e-33*b*c^4*e-43*c^5*e-31*a^4*d*e-46*a^3*b*d*e-19*a^2*b^2*d*e-40*a*b^3*d*e+17*b^4*d*e-7*a^3*c*d*e+27*a^2*b*c*d*e-18*a*b^2*c*d*e+40*b^3*c*d*e+13*a^2*c^2*d*e-40*a*b*c^2*d*e-21*b^2*c^2*d*e+48*a*c^3*d*e-23*b*c^3*d*e-41*c^4*d*e-19*a^3*d^2*e+26*a^2*b*d^2*e-35*a*b^2*d^2*e-5*b^3*d^2*e+23*a^2*c*d^2*e+44*a*b*c*d^2*e-11*b^2*c*d^2*e+2*a*c^2*d^2*e-23*b*c^2*d^2*e-9*c^3*d^2*e+26*a^2*d^3*e+3*a*b*d^3*e+27*b^2*d^3*e+24*a*c*d^3*e+b*c*d^3*e-33*c^2*d^3*e+27*a*d^4*e-49*b*d^4*e-33*c*d^4*e+3*d^5*e-5*a^4*e^2-39*a^3*b*e^2-a^2*b^2*e^2+9*a*b^3*e^2+38*b^4*e^2+48*a^3*c*e^2-50*a^2*b*c*e^2+31*a*b^2*c*e^2-b^3*c*e^2+40*a^2*c^2*e^2+46*a*b*c^2*e^2-9*b^2*c^2*e^2-5*a*c^3*e^2+2*b*c^3*e^2-3*c^4*e^2-4*a^3*d*e^2+20*a^2*b*d*e^2-42*a*b^2*d*e^2+5*b^3*d*e^2-29*a^2*c*d*e^2+21*a*b*c*d*e^2-36*b^2*c*d*e^2+34*a*c^2*d*e^2+18*b*c^2*d*e^2-45*c^3*d*e^2+13*a^2*d^2*e^2-25*a*b*d^2*e^2+27*b^2*d^2*e^2+32*b*c*d^2*e^2+38*c^2*d^2*e^2+2*a*d^3*e^2+10*b*d^3*e^2+31*c*d^3*e^2-6*d^4*e^2+8*a^3*e^3-40*a^2*b*e^3+34*a*b^2*e^3+50*b^3*e^3-10*a^2*c*e^3-36*a*b*c*e^3-17*b^2*c*e^3-39*a*c^2*e^3+19*b*c^2*e^3-13*c^3*e^3+28*a^2*d*e^3+27*a*b*d*e^3+28*b^2*d*e^3+13*a*c*d*e^3+47*b*c*d*e^3-32*c^2*d*e^3+6*a*d^2*e^3+16*b*d^2*e^3-2*c*d^2*e^3+39*d^3*e^3+12*a^2*e^4-12*a*b*e^4+27*b^2*e^4-4*a*c*e^4+7*b*c*e^4-2*c^2*e^4+30*a*d*e^4-16*b*d*e^4-13*c*d*e^4+18*d^2*e^4-6*a*e^5+32*b*e^5-46*c*e^5+33*d*e^5+26*e^6, a*b^3*c*d-15*a^4*d^2-41*a^3*b*d^2-50*a^2*b^2*d^2-45*b^4*d^2+29*a^3*c*d^2+43*a^2*b*c*d^2-7*a*b^2*c*d^2-49*b^3*c*d^2+10*a^2*c^2*d^2+13*a*b*c^2*d^2-8*b^2*c^2*d^2+22*a*c^3*d^2+21*b*c^3*d^2-20*c^4*d^2-25*a^3*d^3+28*a^2*b*d^3+36*a*b^2*d^3+b^3*d^3-38*a^2*c*d^3+34*a*b*c*d^3-33*b^2*c*d^3+11*a*c^2*d^3+48*b*c^2*d^3+33*c^3*d^3+5*a^2*d^4+5*a*b*d^4+4*b^2*d^4+37*a*c*d^4+44*b*c*d^4-35*c^2*d^4+8*a*d^5+38*b*d^5+43*c*d^5-15*d^6+15*a^5*e+31*a^4*b*e-30*a^3*b^2*e+46*a^2*b^3*e-29*a*b^4*e+13*b^5*e-38*a^4*c*e+39*a^3*b*c*e+3*a^2*b^2*c*e-19*a*b^3*c*e-50*b^4*c*e-a^3*c^2*e+3*a^2*b*c^2*e-8*a*b^2*c^2*e-34*b^3*c^2*e-40*a^2*c^3*e+43*a*b*c^3*e+45*b^2*c^3*e-31*a*c^4*e+19*b*c^4*e+38*c^5*e+5*a^4*d*e-43*a^3*b*d*e+23*a^2*b^2*d*e+38*a*b^3*d*e-35*b^4*d*e-46*a^3*c*d*e+46*a^2*b*c*d*e-41*a*b^2*c*d*e+16*b^3*c*d*e-37*a^2*c^2*d*e+28*a*b*c^2*d*e-8*b^2*c^2*d*e+40*a*c^3*d*e-42*b*c^3*d*e-22*c^4*d*e+36*a^3*d^2*e+17*a^2*b*d^2*e+4*a*b^2*d^2*e+38*b^3*d^2*e-41*a^2*c*d^2*e-7*a*b*c*d^2*e-34*b^2*c*d^2*e+10*a*c^2*d^2*e-7*b*c^2*d^2*e-35*c^3*d^2*e-26*a^2*d^3*e-a*b*d^3*e-12*b^2*d^3*e+46*a*c*d^3*e-44*b*c*d^3*e+14*c^2*d^3*e-42*a*d^4*e-8*b*d^4*e+39*c*d^4*e+17*d^5*e+43*a^4*e^2+10*a^3*b*e^2-13*a^2*b^2*e^2-a*b^3*e^2+32*b^4*e^2+4*a^3*c*e^2+10*a^2*b*c*e^2-34*a*b^2*c*e^2+5*b^3*c*e^2-30*a^2*c^2*e^2-6*a*b*c^2*e^2+38*b^2*c^2*e^2-44*a*c^3*e^2+9*b*c^3*e^2+11*c^4*e^2+10*a^3*d*e^2+50*a^2*b*d*e^2-2*a*b^2*d*e^2-26*b^3*d*e^2+15*a^2*c*d*e^2-40*a*b*c*d*e^2+21*b^2*c*d*e^2-45*a*c^2*d*e^2-5*b*c^2*d*e^2-8*c^3*d*e^2+5*a^2*d^2*e^2+8*a*b*d^2*e^2-40*b^2*d^2*e^2+28*a*c*d^2*e^2-26*b*c*d^2*e^2+28*c^2*d^2*e^2+20*a*d^3*e^2-32*b*d^3*e^2-c*d^3*e^2-47*d^4*e^2-41*a^3*e^3-10*a^2*b*e^3-9*a*b^2*e^3+18*b^3*e^3-36*a^2*c*e^3+43*a*b*c*e^3+b^2*c*e^3+5*a*c^2*e^3+35*b*c^2*e^3-29*c^3*e^3+49*a^2*d*e^3+11*a*b*d*e^3-14*b^2*d*e^3-18*a*c*d*e^3+48*b*c*d*e^3-5*c^2*d*e^3-39*a*d^2*e^3+16*c*d^2*e^3+21*d^3*e^3+29*a^2*e^4+42*a*b*e^4+16*b^2*e^4+21*a*c*e^4-40*b*c*e^4-23*a*d*e^4-27*b*d*e^4+19*c*d*e^4-3*d^2*e^4+29*a*e^5+23*b*e^5-48*c*e^5-14*d*e^5-39*e^6, a^2*b^2*c*d+30*a^4*d^2-8*a^3*b*d^2-31*a^2*b^2*d^2-48*a*b^3*d^2-8*b^4*d^2-a^3*c*d^2-45*a^2*b*c*d^2+24*a*b^2*c*d^2-50*b^3*c*d^2+26*a^2*c^2*d^2-21*a*b*c^2*d^2+7*b^2*c^2*d^2-23*a*c^3*d^2-3*b*c^3*d^2-37*c^4*d^2+30*a^3*d^3-49*a^2*b*d^3-10*a*b^2*d^3+19*b^3*d^3-a^2*c*d^3-23*a*b*c*d^3+27*b^2*c*d^3+8*a*c^2*d^3+36*b*c^2*d^3+14*c^3*d^3-14*a^2*d^4+11*a*b*d^4+24*b^2*d^4-22*a*c*d^4+14*b*c*d^4-12*c^2*d^4+33*a*d^5-35*b*d^5-20*c*d^5-22*d^6-25*a^5*e-50*a^4*b*e-3*a^3*b^2*e-49*a^2*b^3*e-47*a*b^4*e-12*b^5*e+24*a^4*c*e+10*a^3*b*c*e-49*a^2*b^2*c*e-46*a*b^3*c*e-39*b^4*c*e+47*a^3*c^2*e-a^2*b*c^2*e+45*a*b^2*c^2*e-46*b^3*c^2*e+27*a^2*c^3*e-27*a*b*c^3*e+7*b^2*c^3*e+48*a*c^4*e-17*b*c^4*e+13*c^5*e+40*a^4*d*e+50*a^3*b*d*e-9*a^2*b^2*d*e-9*a*b^3*d*e+18*b^4*d*e+30*a^3*c*d*e-36*a^2*b*c*d*e-41*a*b^2*c*d*e+34*b^3*c*d*e+10*a^2*c^2*d*e-19*a*b*c^2*d*e+38*b^2*c^2*d*e-17*a*c^3*d*e-15*b*c^3*d*e-25*c^4*d*e+26*a^3*d^2*e-22*a^2*b*d^2*e+33*a*b^2*d^2*e+3*b^3*d^2*e+33*a^2*c*d^2*e+13*a*b*c*d^2*e-36*b^2*c*d^2*e+16*a*c^2*d^2*e+16*b*c^2*d^2*e+27*c^3*d^2*e-20*a^2*d^3*e+8*a*b*d^3*e+12*b^2*d^3*e-7*a*c*d^3*e-11*b*c*d^3*e-32*c^2*d^3*e+49*a*d^4*e-45*b*d^4*e+4*c*d^4*e+23*d^5*e-42*a^4*e^2-10*a^3*b*e^2+47*a^2*b^2*e^2+31*a*b^3*e^2-9*b^4*e^2-45*a^3*c*e^2-16*a^2*b*c*e^2-16*a*b^2*c*e^2+6*b^3*c*e^2+9*a^2*c^2*e^2-35*a*b*c^2*e^2-17*b^2*c^2*e^2-48*a*c^3*e^2-6*b*c^3*e^2+33*c^4*e^2+46*a^3*d*e^2-22*a^2*b*d*e^2+41*a*b^2*d*e^2+28*b^3*d*e^2+37*a^2*c*d*e^2-35*a*b*c*d*e^2+11*b^2*c*d*e^2-40*a*c^2*d*e^2-25*b*c^2*d*e^2-6*c^3*d*e^2+50*a^2*d^2*e^2-29*a*b*d^2*e^2-30*b^2*d^2*e^2+12*a*c*d^2*e^2+37*b*c*d^2*e^2-23*c^2*d^2*e^2-30*a*d^3*e^2-43*b*d^3*e^2+31*c*d^3*e^2-35*d^4*e^2+32*a^3*e^3-45*a^2*b*e^3-35*a*b^2*e^3+26*b^3*e^3-43*a^2*c*e^3-41*a*b*c*e^3-6*b^2*c*e^3-14*a*c^2*e^3-20*b*c^2*e^3-44*c^3*e^3+10*a^2*d*e^3-4*a*b*d*e^3-38*b^2*d*e^3-28*a*c*d*e^3+8*b*c*d*e^3+30*c^2*d*e^3-5*a*d^2*e^3+24*b*d^2*e^3+2*c*d^2*e^3-19*d^3*e^3-25*a^2*e^4+21*a*b*e^4-20*b^2*e^4-11*a*c*e^4+40*b*c*e^4+12*c^2*e^4-30*a*d*e^4+8*b*d*e^4-14*c*d*e^4-23*d^2*e^4+20*a*e^5-7*b*e^5-38*c*e^5-50*d*e^5-30*e^6, a^3*b*c*d+41*a^4*d^2+15*a^3*b*d^2-2*a^2*b^2*d^2-33*a*b^3*d^2+9*b^4*d^2+25*a^3*c*d^2-22*a^2*b*c*d^2-7*a*b^2*c*d^2-14*b^3*c*d^2-34*a^2*c^2*d^2-30*a*b*c^2*d^2+50*b^2*c^2*d^2+12*a*c^3*d^2-6*b*c^3*d^2+25*c^4*d^2-41*a^3*d^3-2*a^2*b*d^3+10*a*b^2*d^3+6*b^3*d^3-26*a^2*c*d^3+17*a*b*c*d^3+24*b^2*c*d^3+42*a*c^2*d^3-28*b*c^2*d^3+9*c^3*d^3+41*a^2*d^4-48*a*b*d^4+18*b^2*d^4-26*a*c*d^4+33*b*c*d^4-8*c^2*d^4+35*a*d^5+14*b*d^5-48*c*d^5-23*d^6+49*a^5*e+16*a^4*b*e+2*a^3*b^2*e+26*a^2*b^3*e+5*a*b^4*e+39*b^5*e-32*a^4*c*e+19*a^3*b*c*e-37*a^2*b^2*c*e+44*a*b^3*c*e+34*b^4*c*e+37*a^3*c^2*e-25*a^2*b*c^2*e-43*a*b^2*c^2*e+31*b^3*c^2*e-17*a^2*c^3*e-7*a*b*c^3*e-29*b^2*c^3*e+39*a*c^4*e-13*b*c^4*e+46*c^5*e-14*a^4*d*e-23*a^3*b*d*e-31*a^2*b^2*d*e+14*a*b^3*d*e+35*b^4*d*e-44*a^3*c*d*e+15*a^2*b*c*d*e-38*a*b^2*c*d*e-38*b^3*c*d*e-7*a^2*c^2*d*e-36*a*b*c^2*d*e-36*b^2*c^2*d*e+36*a*c^3*d*e+4*b*c^3*d*e+14*c^4*d*e+35*a^2*b*d^2*e+35*a*b^2*d^2*e-28*b^3*d^2*e+3*a^2*c*d^2*e+11*a*b*c*d^2*e-41*b^2*c*d^2*e-12*a*c^2*d^2*e-4*b*c^2*d^2*e+2*c^3*d^2*e+15*a^2*d^3*e-18*a*b*d^3*e+2*b^2*d^3*e+2*a*c*d^3*e-21*b*c*d^3*e+27*c^2*d^3*e+34*a*d^4*e+22*b*d^4*e-38*c*d^4*e+45*d^5*e+3*a^4*e^2+21*a^3*b*e^2-2*a^2*b^2*e^2+11*a*b^3*e^2-29*b^4*e^2-31*a^3*c*e^2+27*a^2*b*c*e^2-44*a*b^2*c*e^2-27*b^3*c*e^2-26*a^2*c^2*e^2+48*a*b*c^2*e^2-46*b^2*c^2*e^2-46*a*c^3*e^2-44*b*c^3*e^2-3*c^4*e^2+18*a^3*d*e^2-34*a^2*b*d*e^2+14*a*b^2*d*e^2+32*b^3*d*e^2+40*a^2*c*d*e^2+20*a*b*c*d*e^2+35*b^2*c*d*e^2-19*a*c^2*d*e^2+16*b*c^2*d*e^2-6*c^3*d*e^2-a^2*d^2*e^2+38*a*b*d^2*e^2+23*b^2*d^2*e^2-26*a*c*d^2*e^2-47*b*c*d^2*e^2+11*c^2*d^2*e^2+34*a*d^3*e^2-27*b*d^3*e^2-41*c*d^3*e^2-2*d^4*e^2+7*a^3*e^3-46*a^2*b*e^3-17*a*b^2*e^3+18*b^3*e^3+25*a^2*c*e^3+24*a*b*c*e^3+48*b^2*c*e^3-25*a*c^2*e^3-12*b*c^2*e^3+17*c^3*e^3+15*a^2*d*e^3+49*a*b*d*e^3-44*b^2*d*e^3+31*a*c*d*e^3-14*b*c*d*e^3-13*c^2*d*e^3-49*a*d^2*e^3-42*b*d^2*e^3-40*c*d^2*e^3+49*d^3*e^3-13*a^2*e^4-3*a*b*e^4-33*b^2*e^4+21*a*c*e^4-23*b*c*e^4+35*c^2*e^4+41*a*d*e^4-6*b*d*e^4+23*c*d*e^4-44*d^2*e^4-10*a*e^5-5*b*e^5+22*c*e^5-13*d*e^5-24*e^6, a^4*c*d-22*a^3*b*d^2+25*a^2*b^2*d^2+46*a*b^3*d^2+4*b^4*d^2-49*a^3*c*d^2+10*a^2*b*c*d^2-18*a*b^2*c*d^2-24*b^3*c*d^2+a^2*c^2*d^2-44*a*b*c^2*d^2+19*b^2*c^2*d^2+2*a*c^3*d^2-16*b*c^3*d^2+23*c^4*d^2-34*a^3*d^3+29*a^2*b*d^3+18*a*b^2*d^3-31*b^3*d^3-26*a^2*c*d^3+35*a*b*c*d^3-2*b^2*c*d^3-3*a*c^2*d^3-8*b*c^2*d^3+50*c^3*d^3-11*a^2*d^4+30*a*b*d^4-41*b^2*d^4+41*a*c*d^4+12*b*c*d^4+2*c^2*d^4+44*a*d^5+5*b*d^5-8*c*d^5-37*d^6+10*a^5*e+20*a^4*b*e-32*a^3*b^2*e-7*a^2*b^3*e-11*a*b^4*e-3*b^5*e+47*a^4*c*e-39*a^3*b*c*e+27*a^2*b^2*c*e+14*a*b^3*c*e+25*b^4*c*e+45*a^3*c^2*e-22*a^2*b*c^2*e-4*a*b^2*c^2*e+8*b^3*c^2*e+10*a^2*c^3*e-18*a*b*c^3*e-25*b^2*c^3*e-35*a*c^4*e+7*b*c^4*e+44*c^5*e+13*a^4*d*e-17*a^3*b*d*e+23*a^2*b^2*d*e-4*a*b^3*d*e+23*b^4*d*e-4*a^3*c*d*e+34*a^2*b*c*d*e+48*a*b^2*c*d*e-32*b^3*c*d*e-44*a^2*c^2*d*e+37*a*b*c^2*d*e-38*b^2*c^2*d*e-23*a*c^3*d*e-42*b*c^3*d*e-19*c^4*d*e-48*a^3*d^2*e+29*a^2*b*d^2*e-25*a*b^2*d^2*e+36*b^3*d^2*e-46*a^2*c*d^2*e+37*a*b*c*d^2*e+28*b^2*c*d^2*e+12*a*c^2*d^2*e+2*b*c^2*d^2*e-13*c^3*d^2*e-40*a^2*d^3*e+44*a*b*d^3*e+29*b^2*d^3*e+20*a*c*d^3*e+23*b*c*d^3*e-44*c^2*d^3*e+23*a*d^4*e+22*b*d^4*e+12*c*d^4*e-16*d^5*e+50*a^4*e^2+12*a^3*b*e^2-16*a^2*b^2*e^2+27*a*b^3*e^2+27*b^4*e^2-25*a^3*c*e^2+13*a^2*b*c*e^2-21*a*b^2*c*e^2+46*b^3*c*e^2-6*a^2*c^2*e^2+13*a*b*c^2*e^2-8*b^2*c^2*e^2+39*a*c^3*e^2+36*b*c^3*e^2+46*c^4*e^2-9*a^3*d*e^2-35*a^2*b*d*e^2-47*a*b^2*d*e^2-41*b^3*d*e^2+26*a^2*c*d*e^2-38*a*b*c*d*e^2+48*b^2*c*d*e^2-36*a*c^2*d*e^2+32*b*c^2*d*e^2-17*c^3*d*e^2+39*a^2*d^2*e^2-a*b*d^2*e^2+48*a*c*d^2*e^2-20*b*c*d^2*e^2-49*c^2*d^2*e^2-37*a*d^3*e^2-8*b*d^3*e^2-c*d^3*e^2-8*d^4*e^2-47*a^3*e^3+2*a^2*b*e^3-14*a*b^2*e^3-32*b^3*e^3+18*a^2*c*e^3+49*a*b*c*e^3-43*b^2*c*e^3-8*a*c^2*e^3-36*b*c^2*e^3+18*c^3*e^3+11*a^2*d*e^3+4*a*b*d*e^3+49*b^2*d*e^3+26*a*c*d*e^3+5*b*c*d*e^3-14*c^2*d*e^3+12*a*d^2*e^3+b*d^2*e^3-49*c*d^2*e^3+24*d^3*e^3+11*a^2*e^4-43*a*b*e^4-36*b^2*e^4+30*a*c*e^4-12*b*c*e^4+10*c^2*e^4-29*a*d*e^4-12*b*d*e^4+37*c*d*e^4+46*d^2*e^4+34*a*e^5+14*b*e^5-26*c*e^5+d*e^5+35*e^6, b^5*d-5*a^4*d^2-29*a^3*b*d^2-36*a^2*b^2*d^2-11*a*b^3*d^2+32*b^4*d^2-17*a^3*c*d^2+47*a^2*b*c*d^2+16*a*b^2*c*d^2-24*b^3*c*d^2+12*a^2*c^2*d^2+20*a*b*c^2*d^2-24*b^2*c^2*d^2-10*a*c^3*d^2-26*b*c^3*d^2+22*c^4*d^2-14*a^3*d^3-49*a^2*b*d^3-44*a*b^2*d^3-20*b^3*d^3+11*a^2*c*d^3-45*a*b*c*d^3-5*b^2*c*d^3-19*a*c^2*d^3-10*b*c^2*d^3-35*c^3*d^3-13*a^2*d^4+18*a*b*d^4+10*b^2*d^4+46*a*c*d^4+15*b*c*d^4-13*c^2*d^4-8*a*d^5+50*b*d^5+2*c*d^5-43*d^6-18*a^5*e-2*a^4*b*e-31*a^3*b^2*e-37*a^2*b^3*e+32*a*b^4*e-4*b^5*e+19*a^4*c*e-42*a^3*b*c*e+40*a^2*b^2*c*e+37*a*b^3*c*e+17*b^4*c*e+39*a^3*c^2*e+10*a^2*b*c^2*e-38*a*b^2*c^2*e+4*b^3*c^2*e+18*a^2*c^3*e+35*a*b*c^3*e-29*b^2*c^3*e-19*a*c^4*e-4*b*c^4*e+28*c^5*e+17*a^4*d*e-20*a^3*b*d*e+18*a^2*b^2*d*e+11*a*b^3*d*e+30*b^4*d*e-2*a^3*c*d*e+43*a^2*b*c*d*e+46*a*b^2*c*d*e+14*b^3*c*d*e+48*a^2*c^2*d*e-5*a*b*c^2*d*e-7*b^2*c^2*d*e+13*a*c^3*d*e+11*b*c^3*d*e+48*c^4*d*e+41*a^3*d^2*e+10*a^2*b*d^2*e-43*a*b^2*d^2*e-41*b^3*d^2*e+47*a^2*c*d^2*e-42*a*b*c*d^2*e+34*b^2*c*d^2*e+34*a*c^2*d^2*e-14*b*c^2*d^2*e-16*c^3*d^2*e-39*a^2*d^3*e+23*a*b*d^3*e-32*b^2*d^3*e-20*a*c*d^3*e+7*b*c*d^3*e-4*c^2*d^3*e+2*a*d^4*e+42*b*d^4*e-38*c*d^4*e-14*d^5*e-9*a^4*e^2+2*a^3*b*e^2-20*a^2*b^2*e^2-15*a*b^3*e^2+30*b^4*e^2-44*a^3*c*e^2-47*a^2*b*c*e^2+11*a*b^2*c*e^2+20*b^3*c*e^2-2*a^2*c^2*e^2+4*a*b*c^2*e^2+49*b^2*c^2*e^2-41*a*c^3*e^2-36*b*c^3*e^2+31*c^4*e^2+22*a^3*d*e^2+39*a^2*b*d*e^2-21*a*b^2*d*e^2+26*b^3*d*e^2+28*a^2*c*d*e^2+41*a*b*c*d*e^2-14*b^2*c*d*e^2+44*a*c^2*d*e^2+27*b*c^2*d*e^2-25*c^3*d*e^2-28*a^2*d^2*e^2-37*a*b*d^2*e^2+20*b^2*d^2*e^2+45*a*c*d^2*e^2+45*b*c*d^2*e^2-28*c^2*d^2*e^2-18*a*d^3*e^2+5*b*d^3*e^2-3*c*d^3*e^2+17*d^4*e^2+18*a^3*e^3+46*a^2*b*e^3+28*a*b^2*e^3-22*b^3*e^3-15*a^2*c*e^3+30*a*b*c*e^3-40*b^2*c*e^3-20*a*c^2*e^3+10*b*c^2*e^3-31*c^3*e^3+19*a^2*d*e^3+29*a*b*d*e^3+12*b^2*d*e^3-39*a*c*d*e^3-32*b*c*d*e^3+12*a*d^2*e^3-26*c*d^2*e^3+14*a^2*e^4+40*a*b*e^4-b^2*e^4+15*a*c*e^4+27*b*c*e^4+34*c^2*e^4-30*a*d*e^4+25*b*d*e^4-50*c*d*e^4+35*d^2*e^4+25*a*e^5+21*b*e^5-10*c*e^5-4*d*e^5-43*e^6, a*b^4*d+47*a^4*d^2+25*a^3*b*d^2-13*a^2*b^2*d^2+26*a*b^3*d^2-24*b^4*d^2-4*a^3*c*d^2-30*a^2*b*c*d^2+11*a*b^2*c*d^2+49*b^3*c*d^2-11*a^2*c^2*d^2-4*a*b*c^2*d^2+44*b^2*c^2*d^2+46*a*c^3*d^2-3*b*c^3*d^2-30*c^4*d^2+8*a^3*d^3+49*a^2*b*d^3+33*a*b^2*d^3+8*b^3*d^3-34*a^2*c*d^3-29*a*b*c*d^3-35*b^2*c*d^3-10*a*c^2*d^3+13*b*c^2*d^3-22*c^3*d^3+8*a^2*d^4+2*a*b*d^4+7*b^2*d^4-14*a*c*d^4+40*b*c*d^4+41*c^2*d^4-14*a*d^5+10*c*d^5-11*d^6-43*a^5*e-2*a^4*b*e-10*a^3*b^2*e-39*a^2*b^3*e+15*a*b^4*e-8*b^5*e+19*a^4*c*e+35*a^3*b*c*e+48*a^2*b^2*c*e-24*a*b^3*c*e-41*b^4*c*e-24*a^3*c^2*e+35*a^2*b*c^2*e-47*a*b^2*c^2*e+28*b^3*c^2*e-10*a^2*c^3*e+28*a*b*c^3*e-43*b^2*c^3*e+10*a*c^4*e-26*b*c^4*e-30*c^5*e+3*a^4*d*e-42*a^3*b*d*e-23*a^2*b^2*d*e+41*a*b^3*d*e+12*b^4*d*e-16*a^3*c*d*e+4*a^2*b*c*d*e+30*a*b^2*c*d*e+14*b^3*c*d*e+15*a^2*c^2*d*e-11*a*b*c^2*d*e+34*b^2*c^2*d*e-48*a*c^3*d*e+15*b*c^3*d*e+38*c^4*d*e+26*a^3*d^2*e-41*a^2*b*d^2*e-8*a*b^2*d^2*e+44*b^3*d^2*e-7*a^2*c*d^2*e+11*a*b*c*d^2*e-3*b^2*c*d^2*e+42*a*c^2*d^2*e+31*b*c^2*d^2*e-35*c^3*d^2*e-23*a^2*d^3*e+47*a*b*d^3*e+26*b^2*d^3*e+40*a*c*d^3*e-24*b*c*d^3*e-34*c^2*d^3*e+4*a*d^4*e-48*b*d^4*e-49*c*d^4*e-23*d^5*e-5*a^4*e^2-15*a^3*b*e^2+5*a^2*b^2*e^2+41*a*b^3*e^2-7*b^4*e^2-35*a^3*c*e^2+5*a^2*b*c*e^2+25*a*b^2*c*e^2-50*b^3*c*e^2+23*a^2*c^2*e^2+43*a*b*c^2*e^2+41*b^2*c^2*e^2+9*a*c^3*e^2-36*b*c^3*e^2-49*c^4*e^2-36*a^3*d*e^2-43*a^2*b*d*e^2-24*a*b^2*d*e^2+34*b^3*d*e^2-29*a^2*c*d*e^2-48*a*b*c*d*e^2+42*b^2*c*d*e^2+34*a*c^2*d*e^2+20*b*c^2*d*e^2-31*c^3*d*e^2+18*a^2*d^2*e^2-3*a*b*d^2*e^2+24*b^2*d^2*e^2-39*a*c*d^2*e^2+39*b*c*d^2*e^2-48*c^2*d^2*e^2-30*a*d^3*e^2-28*b*d^3*e^2+4*c*d^3*e^2+13*d^4*e^2-30*a^3*e^3+47*a^2*b*e^3+2*a*b^2*e^3+31*b^3*e^3+35*a^2*c*e^3+36*a*b*c*e^3-47*b^2*c*e^3+48*a*c^2*e^3-8*b*c^2*e^3-23*c^3*e^3+35*a^2*d*e^3+21*a*b*d*e^3+17*b^2*d*e^3-15*a*c*d*e^3-41*b*c*d*e^3+13*c^2*d*e^3+17*a*d^2*e^3-19*b*d^2*e^3+26*c*d^2*e^3-26*d^3*e^3-38*a^2*e^4+17*a*b*e^4+22*b^2*e^4-6*a*c*e^4-18*b*c*e^4+42*c^2*e^4+26*a*d*e^4-19*b*d*e^4-36*c*d*e^4-22*d^2*e^4+44*a*e^5+32*b*e^5-15*c*e^5-16*d*e^5+2*e^6, a^2*b^3*d-26*a^4*d^2+24*a^3*b*d^2-21*a^2*b^2*d^2-7*a*b^3*d^2-39*b^4*d^2-47*a^3*c*d^2+37*a^2*b*c*d^2+24*a*b^2*c*d^2-6*b^3*c*d^2+20*a^2*c^2*d^2-4*b^2*c^2*d^2+21*a*c^3*d^2-15*b*c^3*d^2-22*c^4*d^2-23*a^3*d^3+21*a^2*b*d^3-16*a*b^2*d^3-38*b^3*d^3-16*a^2*c*d^3+7*a*b*c*d^3-37*b^2*c*d^3-12*a*c^2*d^3+42*b*c^2*d^3+40*c^3*d^3-35*a^2*d^4+29*a*b*d^4-b^2*d^4+21*a*c*d^4+47*b*c*d^4-22*c^2*d^4-11*a*d^5-44*b*d^5+49*c*d^5+33*d^6-35*a^5*e-41*a^4*b*e+17*a^3*b^2*e-6*a^2*b^3*e-12*a*b^4*e+36*b^5*e-6*a^4*c*e-28*a^3*b*c*e+22*a^2*b^2*c*e+10*a*b^3*c*e-34*b^4*c*e+28*a^3*c^2*e-2*a^2*b*c^2*e-48*a*b^2*c^2*e-28*b^3*c^2*e+42*a^2*c^3*e+30*a*b*c^3*e-43*b^2*c^3*e-34*a*c^4*e+33*b*c^4*e-38*c^5*e+39*a^4*d*e-27*a^3*b*d*e+44*a^2*b^2*d*e+12*a*b^3*d*e+18*b^4*d*e-19*a^3*c*d*e-42*a^2*b*c*d*e+24*a*b^2*c*d*e-49*b^3*c*d*e+17*a^2*c^2*d*e+3*a*b*c^2*d*e+39*b^2*c^2*d*e-31*a*c^3*d*e-8*b*c^3*d*e+42*c^4*d*e-42*a^3*d^2*e+49*a^2*b*d^2*e-17*a*b^2*d^2*e-49*b^3*d^2*e-20*a^2*c*d^2*e-11*a*b*c*d^2*e-17*b^2*c*d^2*e+16*a*c^2*d^2*e+41*b*c^2*d^2*e+50*c^3*d^2*e-28*a^2*d^3*e+44*a*b*d^3*e-25*b^2*d^3*e-24*a*c*d^3*e-b*c*d^3*e-45*c^2*d^3*e-3*a*d^4*e-26*b*d^4*e-12*c*d^4*e+4*d^5*e+5*a^4*e^2+28*a^3*b*e^2-42*a^2*b^2*e^2+33*a*b^3*e^2-15*b^4*e^2-40*a^3*c*e^2+47*a^2*b*c*e^2-4*a*b^2*c*e^2-22*b^3*c*e^2-35*a^2*c^2*e^2-8*a*b*c^2*e^2-11*b^2*c^2*e^2-37*a*c^3*e^2-23*b*c^3*e^2+33*c^4*e^2-34*a^3*d*e^2+16*a^2*b*d*e^2-38*a*b^2*d*e^2+32*b^3*d*e^2+10*a^2*c*d*e^2-30*a*b*c*d*e^2+32*b^2*c*d*e^2-6*a*c^2*d*e^2-45*b*c^2*d*e^2-5*c^3*d*e^2-16*a^2*d^2*e^2-14*a*b*d^2*e^2+22*b^2*d^2*e^2+4*a*c*d^2*e^2-37*b*c*d^2*e^2-28*c^2*d^2*e^2-16*a*d^3*e^2+6*b*d^3*e^2+9*c*d^3*e^2-46*d^4*e^2-10*a^3*e^3-50*a^2*b*e^3+18*a*b^2*e^3+20*b^3*e^3-34*a^2*c*e^3+33*a*b*c*e^3-17*b^2*c*e^3-19*a*c^2*e^3-5*b*c^2*e^3+19*c^3*e^3-23*a^2*d*e^3+4*a*b*d*e^3+28*b^2*d*e^3+17*a*c*d*e^3+7*b*c*d*e^3+39*c^2*d*e^3+4*a*d^2*e^3-39*b*d^2*e^3-16*c*d^2*e^3-23*d^3*e^3-23*a^2*e^4-16*a*b*e^4-2*b^2*e^4-24*a*c*e^4-5*b*c*e^4+45*c^2*e^4-10*a*d*e^4-b*d*e^4+50*c*d*e^4+31*d^2*e^4+31*a*e^5-37*b*e^5-44*c*e^5+37*d*e^5-43*e^6, a^3*b^2*d-42*a^4*d^2-17*a^3*b*d^2-23*a^2*b^2*d^2-17*a*b^3*d^2-27*b^4*d^2-50*a^3*c*d^2+27*a^2*b*c*d^2-30*a*b^2*c*d^2-7*b^3*c*d^2+21*a^2*c^2*d^2+13*a*b*c^2*d^2+29*b^2*c^2*d^2-46*a*c^3*d^2+43*b*c^3*d^2-2*c^4*d^2-2*a^3*d^3+45*a^2*b*d^3-15*a*b^2*d^3-47*b^3*d^3-17*a^2*c*d^3-25*a*b*c*d^3+9*b^2*c*d^3-24*a*c^2*d^3+32*b*c^2*d^3+37*c^3*d^3+14*a^2*d^4+23*a*b*d^4+49*b^2*d^4+10*a*c*d^4+19*b*c*d^4-13*c^2*d^4-9*a*d^5+44*b*d^5+39*c*d^5-28*d^6-2*a^5*e+5*a^4*b*e-36*a^3*b^2*e-12*a^2*b^3*e+2*a*b^4*e+15*b^5*e-31*a^4*c*e-3*a^3*b*c*e+46*a^2*b^2*c*e+33*a*b^3*c*e+16*b^4*c*e+24*a^3*c^2*e-36*a^2*b*c^2*e+10*a*b^2*c^2*e+4*b^3*c^2*e+44*a^2*c^3*e+18*a*b*c^3*e-37*b^2*c^3*e-47*a*c^4*e+32*b*c^4*e-29*c^5*e+14*a^4*d*e+6*a^3*b*d*e+44*a^2*b^2*d*e+23*a*b^3*d*e+33*b^4*d*e-7*a^3*c*d*e+10*a^2*b*c*d*e+30*a*b^2*c*d*e+41*b^3*c*d*e-50*a^2*c^2*d*e+a*b*c^2*d*e+33*b^2*c^2*d*e-26*a*c^3*d*e-32*b*c^3*d*e+47*c^4*d*e+39*a^3*d^2*e+40*a^2*b*d^2*e+6*a*b^2*d^2*e+30*b^3*d^2*e-30*a^2*c*d^2*e-21*a*b*c*d^2*e-41*b^2*c*d^2*e-21*a*c^2*d^2*e-17*b*c^2*d^2*e-21*c^3*d^2*e+26*a^2*d^3*e+50*a*b*d^3*e+39*b^2*d^3*e-34*a*c*d^3*e-25*b*c*d^3*e-34*c^2*d^3*e+9*a*d^4*e-40*b*d^4*e-45*c*d^4*e-3*d^5*e-34*a^4*e^2-22*a^3*b*e^2-5*a^2*b^2*e^2+45*a*b^3*e^2-16*b^4*e^2-12*a^3*c*e^2+33*a^2*b*c*e^2+31*a*b^2*c*e^2+19*b^3*c*e^2+49*a^2*c^2*e^2-19*a*b*c^2*e^2+8*b^2*c^2*e^2+32*a*c^3*e^2+31*b*c^3*e^2+21*c^4*e^2+13*a^3*d*e^2-35*a^2*b*d*e^2-29*a*b^2*d*e^2-41*b^3*d*e^2+11*a^2*c*d*e^2+46*a*b*c*d*e^2+b^2*c*d*e^2+5*a*c^2*d*e^2+18*c^3*d*e^2-17*a^2*d^2*e^2+45*a*b*d^2*e^2-40*b^2*d^2*e^2-6*a*c*d^2*e^2-32*b*c*d^2*e^2-19*c^2*d^2*e^2+48*a*d^3*e^2+41*b*d^3*e^2-30*c*d^3*e^2-38*d^4*e^2+4*a^3*e^3+8*a^2*b*e^3-49*a*b^2*e^3+36*b^3*e^3-5*a^2*c*e^3-21*a*b*c*e^3-27*b^2*c*e^3+5*a*c^2*e^3+31*b*c^2*e^3+15*c^3*e^3+41*a^2*d*e^3+19*a*b*d*e^3+10*b^2*d*e^3+41*a*c*d*e^3+45*b*c*d*e^3+12*c^2*d*e^3-28*a*d^2*e^3+14*b*d^2*e^3+4*c*d^2*e^3-25*d^3*e^3+38*a^2*e^4+37*a*b*e^4-15*b^2*e^4-11*a*c*e^4-24*b*c*e^4+33*c^2*e^4-31*a*d*e^4+14*b*d*e^4+49*c*d*e^4+34*d^2*e^4-34*a*e^5-23*b*e^5+50*c*e^5+19*d*e^5+26*e^6, a^4*b*d+4*a^4*d^2-24*a^3*b*d^2+8*a^2*b^2*d^2-24*a*b^3*d^2-b^4*d^2+31*a^3*c*d^2-45*a^2*b*c*d^2-12*a*b^2*c*d^2+45*b^3*c*d^2+29*a^2*c^2*d^2+41*a*b*c^2*d^2-2*b^2*c^2*d^2-44*a*c^3*d^2-9*b*c^3*d^2+32*c^4*d^2+50*a^3*d^3-6*a^2*b*d^3+11*a*b^2*d^3-6*b^3*d^3-36*a^2*c*d^3-13*a*b*c*d^3-44*b^2*c*d^3+35*a*c^2*d^3+29*b*c^2*d^3-32*c^3*d^3+45*a^2*d^4-24*a*b*d^4-b^2*d^4+48*a*c*d^4+29*b*c*d^4+43*c^2*d^4+34*a*d^5-b*d^5+14*c*d^5+12*d^6-50*a^5*e-26*a^4*b*e-38*a^3*b^2*e-5*a^2*b^3*e+41*a*b^4*e+38*b^5*e-14*a^4*c*e+46*a^3*b*c*e-14*a^2*b^2*c*e-24*a*b^3*c*e+31*b^4*c*e-24*a^3*c^2*e-50*a^2*b*c^2*e+47*a*b^2*c^2*e+42*b^3*c^2*e-15*a^2*c^3*e-26*a*b*c^3*e+26*b^2*c^3*e-38*a*c^4*e-34*b*c^4*e+44*c^5*e-29*a^4*d*e+26*a^3*b*d*e-25*a^2*b^2*d*e+41*a*b^3*d*e+46*b^4*d*e+46*a^3*c*d*e-28*a^2*b*c*d*e-10*a*b^2*c*d*e+18*b^3*c*d*e+28*a^2*c^2*d*e+25*a*b*c^2*d*e-8*b^2*c^2*d*e-36*a*c^3*d*e+50*b*c^3*d*e-25*c^4*d*e+7*a^3*d^2*e+29*a^2*b*d^2*e-50*a*b^2*d^2*e-34*b^3*d^2*e-6*a^2*c*d^2*e-13*a*b*c*d^2*e+21*b^2*c*d^2*e+32*a*c^2*d^2*e-10*b*c^2*d^2*e-19*c^3*d^2*e-27*a^2*d^3*e+46*a*b*d^3*e-4*b^2*d^3*e+17*a*c*d^3*e+11*b*c*d^3*e+7*c^2*d^3*e+18*a*d^4*e-23*b*d^4*e-45*c*d^4*e+40*d^5*e+36*a^4*e^2-2*a^3*b*e^2-17*a^2*b^2*e^2+11*a*b^3*e^2+49*b^4*e^2-31*a^3*c*e^2+8*a^2*b*c*e^2-12*a*b^2*c*e^2-15*b^3*c*e^2+14*a^2*c^2*e^2-a*b*c^2*e^2+38*b^2*c^2*e^2-40*a*c^3*e^2-25*b*c^3*e^2+34*c^4*e^2-2*a^3*d*e^2-19*a^2*b*d*e^2+35*a*b^2*d*e^2-49*b^3*d*e^2-20*a^2*c*d*e^2+47*a*b*c*d*e^2-42*b^2*c*d*e^2+41*a*c^2*d*e^2+23*b*c^2*d*e^2+22*c^3*d*e^2-16*a^2*d^2*e^2+14*a*b*d^2*e^2-10*b^2*d^2*e^2+47*a*c*d^2*e^2+43*b*c*d^2*e^2+50*c^2*d^2*e^2-35*b*d^3*e^2+45*c*d^3*e^2+5*d^4*e^2+18*a^3*e^3+42*a^2*b*e^3+a*b^2*e^3+26*b^3*e^3+16*a^2*c*e^3+40*b^2*c*e^3-27*a*c^2*e^3-9*b*c^2*e^3-26*c^3*e^3-24*a^2*d*e^3-6*a*b*d*e^3-26*b^2*d*e^3+47*a*c*d*e^3-40*b*c*d*e^3+30*c^2*d*e^3-46*a*d^2*e^3-27*b*d^2*e^3-42*c*d^2*e^3-10*d^3*e^3+25*a^2*e^4+a*b*e^4-15*b^2*e^4-13*a*c*e^4-33*b*c*e^4+20*c^2*e^4+5*a*d*e^4-42*b*d*e^4-5*c*d*e^4-24*d^2*e^4-34*a*e^5+35*b*e^5-27*c*e^5-43*d*e^5-43*e^6, a^5*d+14*a^4*d^2-3*a^3*b*d^2+7*a^2*b^2*d^2-31*a*b^3*d^2-42*b^4*d^2-16*a^3*c*d^2+36*a^2*b*c*d^2-17*a*b^2*c*d^2-15*b^3*c*d^2+17*a^2*c^2*d^2+36*a*b*c^2*d^2+12*b^2*c^2*d^2-47*a*c^3*d^2-16*b*c^3*d^2-9*c^4*d^2-38*a^3*d^3-43*a^2*b*d^3+2*a*b^2*d^3-44*b^3*d^3-12*a^2*c*d^3+32*a*b*c*d^3+21*b^2*c*d^3-10*a*c^2*d^3-28*b*c^2*d^3-c^3*d^3+18*a^2*d^4-13*a*b*d^4+13*b^2*d^4+31*a*c*d^4+27*b*c*d^4+34*c^2*d^4-19*a*d^5-36*b*d^5-46*c*d^5+11*d^6-26*a^5*e-24*a^4*b*e-5*a^3*b^2*e+27*a^2*b^3*e-6*a*b^4*e-30*b^5*e+35*a^4*c*e-42*a^3*b*c*e+a^2*b^2*c*e-22*a*b^3*c*e+12*b^4*c*e+7*a^3*c^2*e-26*a^2*b*c^2*e-43*a*b^2*c^2*e-18*b^3*c^2*e+10*a^2*c^3*e-10*a*b*c^3*e+48*b^2*c^3*e-19*a*c^4*e-29*b*c^4*e-3*c^5*e+20*a^4*d*e+10*a^3*b*d*e+28*a^2*b^2*d*e+14*a*b^3*d*e-15*b^4*d*e-7*a^3*c*d*e-24*a^2*b*c*d*e-26*a*b^2*c*d*e+32*b^3*c*d*e+2*a^2*c^2*d*e+16*a*b*c^2*d*e+44*b^2*c^2*d*e-48*a*c^3*d*e+7*b*c^3*d*e+3*c^4*d*e-8*a^3*d^2*e+23*a^2*b*d^2*e-39*a*b^2*d^2*e+35*b^3*d^2*e-2*a^2*c*d^2*e-17*a*b*c*d^2*e+46*b^2*c*d^2*e-26*a*c^2*d^2*e+7*b*c^2*d^2*e+47*c^3*d^2*e-38*a^2*d^3*e+12*a*b*d^3*e-14*b^2*d^3*e-a*c*d^3*e+12*b*c*d^3*e+30*c^2*d^3*e-50*a*d^4*e-34*b*d^4*e-6*c*d^4*e-24*d^5*e-37*a^4*e^2-15*a^3*b*e^2+17*a^2*b^2*e^2+26*a*b^3*e^2-31*b^4*e^2+14*a^3*c*e^2+30*a^2*b*c*e^2-9*a*b^2*c*e^2-42*b^3*c*e^2-39*a^2*c^2*e^2-43*a*b*c^2*e^2+41*b^2*c^2*e^2-38*a*c^3*e^2-47*b*c^3*e^2+33*c^4*e^2+15*a^3*d*e^2-36*a^2*b*d*e^2+6*a*b^2*d*e^2-15*b^3*d*e^2+24*a^2*c*d*e^2-50*a*b*c*d*e^2-6*b^2*c*d*e^2-41*a*c^2*d*e^2+42*b*c^2*d*e^2+28*c^3*d*e^2-19*a^2*d^2*e^2-47*a*b*d^2*e^2+49*b^2*d^2*e^2-41*a*c*d^2*e^2-3*b*c*d^2*e^2-38*c^2*d^2*e^2+4*a*d^3*e^2-30*b*d^3*e^2+47*c*d^3*e^2+11*d^4*e^2-44*a^3*e^3-25*a^2*b*e^3+18*a*b^2*e^3-14*b^3*e^3+18*a^2*c*e^3-15*a*b*c*e^3+32*b^2*c*e^3+38*a*c^2*e^3-30*b*c^2*e^3-3*c^3*e^3-33*a^2*d*e^3-42*a*b*d*e^3-8*b^2*d*e^3-14*a*c*d*e^3+49*b*c*d*e^3-40*c^2*d*e^3-40*a*d^2*e^3+32*b*d^2*e^3-40*c*d^2*e^3+11*d^3*e^3-43*a^2*e^4-29*a*b*e^4+9*b^2*e^4-20*a*c*e^4+14*b*c*e^4+38*c^2*e^4-32*a*d*e^4+22*b*d*e^4-9*c*d*e^4-34*d^2*e^4+6*a*e^5-15*b*e^5+13*c*e^5-40*d*e^5-40*e^6, c^6+36*a^4*d^2-8*a^3*b*d^2-40*a^2*b^2*d^2-45*a*b^3*d^2+36*b^4*d^2-21*a^3*c*d^2-27*a^2*b*c*d^2+46*a*b^2*c*d^2+30*b^3*c*d^2+4*a*b*c^2*d^2-20*b^2*c^2*d^2+3*a*c^3*d^2-48*b*c^3*d^2-29*c^4*d^2+13*a^3*d^3-3*a^2*b*d^3-13*a*b^2*d^3-38*b^3*d^3+35*a^2*c*d^3-5*a*b*c*d^3-46*b^2*c*d^3-26*a*c^2*d^3-20*b*c^2*d^3-4*c^3*d^3+6*a^2*d^4-14*a*b*d^4+16*b^2*d^4+44*a*c*d^4-10*b*c*d^4+15*c^2*d^4+31*a*d^5-22*b*d^5-36*c*d^5-34*d^6-28*a^5*e+46*a^4*b*e+5*a^3*b^2*e+36*a^2*b^3*e-2*a*b^4*e+13*b^5*e-40*a^4*c*e+31*a^3*b*c*e+49*a^2*b^2*c*e+50*a*b^3*c*e+8*b^4*c*e-23*a^2*b*c^2*e+7*a*b^2*c^2*e+36*b^3*c^2*e-12*a^2*c^3*e-a*b*c^3*e-32*b^2*c^3*e+33*a*c^4*e-45*b*c^4*e+7*c^5*e-13*a^4*d*e-38*a^3*b*d*e+17*a^2*b^2*d*e-33*a*b^3*d*e-33*b^4*d*e-47*a^3*c*d*e+42*a^2*b*c*d*e-5*a*b^2*c*d*e-35*b^3*c*d*e-34*a^2*c^2*d*e-36*a*b*c^2*d*e+17*b^2*c^2*d*e+19*a*c^3*d*e+41*b*c^3*d*e-8*c^4*d*e-15*a^3*d^2*e-10*a^2*b*d^2*e-37*a*b^2*d^2*e-40*b^3*d^2*e-2*a^2*c*d^2*e-28*a*b*c*d^2*e+30*b^2*c*d^2*e+45*a*c^2*d^2*e+26*b*c^2*d^2*e-20*c^3*d^2*e-48*a^2*d^3*e+16*a*b*d^3*e+12*b^2*d^3*e+47*a*c*d^3*e-11*b*c*d^3*e+27*c^2*d^3*e-29*a*d^4*e+33*b*d^4*e+6*c*d^4*e-10*d^5*e-2*a^4*e^2-27*a^3*b*e^2-18*a^2*b^2*e^2-46*a*b^3*e^2-19*b^4*e^2+9*a^3*c*e^2+45*a^2*b*c*e^2+30*a*b^2*c*e^2+35*b^3*c*e^2-31*a^2*c^2*e^2+33*a*b*c^2*e^2+36*b^2*c^2*e^2-18*a*c^3*e^2+5*b*c^3*e^2-8*c^4*e^2-37*a^3*d*e^2+46*a^2*b*d*e^2-37*a*b^2*d*e^2+28*b^3*d*e^2+6*a^2*c*d*e^2-24*a*b*c*d*e^2+9*b^2*c*d*e^2+36*a*c^2*d*e^2-44*b*c^2*d*e^2+32*c^3*d*e^2+49*a^2*d^2*e^2-44*a*b*d^2*e^2-12*b^2*d^2*e^2-6*a*c*d^2*e^2+7*b*c*d^2*e^2-2*c^2*d^2*e^2+17*a*d^3*e^2-15*b*d^3*e^2+18*c*d^3*e^2-24*d^4*e^2-26*a^3*e^3+44*a^2*b*e^3-28*a*b^2*e^3+28*b^3*e^3-8*a^2*c*e^3+6*a*b*c*e^3-12*b^2*c*e^3-25*a*c^2*e^3-37*b*c^2*e^3+36*c^3*e^3-18*a^2*d*e^3-38*a*b*d*e^3+b^2*d*e^3+3*a*c*d*e^3+47*b*c*d*e^3+3*c^2*d*e^3-5*a*d^2*e^3-34*c*d^2*e^3-11*d^3*e^3-19*a^2*e^4+16*a*b*e^4+17*b^2*e^4+23*a*c*e^4-26*b*c*e^4+10*c^2*e^4+23*a*d*e^4-30*b*d*e^4-46*c*d*e^4-13*d^2*e^4-23*a*e^5+41*b*e^5+6*c*e^5-50*d*e^5+28*e^6, b*c^5+8*a^4*d^2-16*a^3*b*d^2+26*a^2*b^2*d^2+a*b^3*d^2+40*b^4*d^2-34*a^3*c*d^2+5*a^2*b*c*d^2+18*a*b^2*c*d^2-30*b^3*c*d^2+9*a^2*c^2*d^2+30*a*b*c^2*d^2-17*b^2*c^2*d^2+26*a*c^3*d^2+49*b*c^3*d^2+42*c^4*d^2+2*a^3*d^3+28*a^2*b*d^3-7*a*b^2*d^3-37*b^3*d^3+38*a^2*c*d^3-5*a*b*c*d^3-13*b^2*c*d^3-11*a*c^2*d^3-37*b*c^2*d^3+4*c^3*d^3-8*a^2*d^4-9*a*b*d^4+28*b^2*d^4+4*a*c*d^4+27*b*c*d^4+39*c^2*d^4+9*a*d^5-24*b*d^5+27*c*d^5+13*d^6-23*a^5*e-41*a^4*b*e-23*a^3*b^2*e+28*a^2*b^3*e+29*a*b^4*e-49*b^5*e-4*a^4*c*e-16*a^3*b*c*e-16*a^2*b^2*c*e+29*a*b^3*c*e-15*b^4*c*e-27*a^3*c^2*e+44*a^2*b*c^2*e-23*a*b^2*c^2*e-18*b^3*c^2*e-24*a^2*c^3*e-12*b^2*c^3*e-48*a*c^4*e+12*b*c^4*e+28*c^5*e-49*a^4*d*e+18*a^3*b*d*e+40*a^2*b^2*d*e-5*a*b^3*d*e-23*b^4*d*e-9*a^3*c*d*e-12*a^2*b*c*d*e-39*a*b^2*c*d*e-43*b^3*c*d*e+36*a^2*c^2*d*e+19*a*b*c^2*d*e+11*b^2*c^2*d*e+24*a*c^3*d*e+22*b*c^3*d*e+14*c^4*d*e-23*a^3*d^2*e-14*a^2*b*d^2*e+47*a*b^2*d^2*e+32*b^3*d^2*e+47*a^2*c*d^2*e+26*a*b*c*d^2*e-39*b^2*c*d^2*e+11*a*c^2*d^2*e-44*b*c^2*d^2*e-20*c^3*d^2*e-23*a^2*d^3*e-3*a*b*d^3*e-11*b^2*d^3*e-34*a*c*d^3*e+5*b*c*d^3*e-3*c^2*d^3*e-6*a*d^4*e-15*b*d^4*e+41*c*d^4*e+18*d^5*e+44*a^4*e^2-49*a^3*b*e^2+38*a^2*b^2*e^2+7*a*b^3*e^2-11*b^4*e^2+2*a^3*c*e^2-6*a^2*b*c*e^2-34*a*b^2*c*e^2-21*b^3*c*e^2+12*a^2*c^2*e^2+7*a*b*c^2*e^2-20*b^2*c^2*e^2-3*a*c^3*e^2-38*b*c^3*e^2-5*c^4*e^2-46*a^3*d*e^2-20*a^2*b*d*e^2+21*a*b^2*d*e^2-36*b^3*d*e^2-14*a^2*c*d*e^2+6*a*b*c*d*e^2+29*b^2*c*d*e^2+12*a*c^2*d*e^2-2*b*c^2*d*e^2+41*c^3*d*e^2+41*a^2*d^2*e^2+34*a*b*d^2*e^2-2*b^2*d^2*e^2+9*a*c*d^2*e^2+10*b*c*d^2*e^2-11*c^2*d^2*e^2+45*a*d^3*e^2+38*b*d^3*e^2-20*c*d^3*e^2-12*d^4*e^2-35*a^3*e^3+23*a*b^2*e^3+37*b^3*e^3+10*a^2*c*e^3+6*a*b*c*e^3+21*b^2*c*e^3-24*a*c^2*e^3+28*b*c^2*e^3+26*c^3*e^3+22*a^2*d*e^3+26*a*b*d*e^3+50*b^2*d*e^3+43*a*c*d*e^3+39*b*c*d*e^3-42*c^2*d*e^3-27*a*d^2*e^3+38*b*d^2*e^3+19*c*d^2*e^3-15*d^3*e^3+37*a^2*e^4+7*a*b*e^4-12*b^2*e^4-34*a*c*e^4+25*b*c*e^4+26*c^2*e^4+a*d*e^4-25*b*d*e^4-15*c*d*e^4-50*d^2*e^4-50*a*e^5-45*b*e^5+30*c*e^5+6*d*e^5+49*e^6, a*c^5+28*a^4*d^2-23*a^3*b*d^2+10*a^2*b^2*d^2-36*a*b^3*d^2+6*b^4*d^2+25*a^3*c*d^2-47*a^2*b*c*d^2+28*a*b^2*c*d^2-36*b^3*c*d^2-31*a^2*c^2*d^2-35*a*b*c^2*d^2-42*b^2*c^2*d^2+20*a*c^3*d^2-45*b*c^3*d^2+49*c^4*d^2-24*a^3*d^3+25*a^2*b*d^3+27*a*b^2*d^3+49*b^3*d^3-9*a^2*c*d^3-46*a*b*c*d^3-39*b^2*c*d^3-9*a*c^2*d^3-46*b*c^2*d^3+43*c^3*d^3-35*a^2*d^4+11*a*b*d^4+15*b^2*d^4-4*a*c*d^4+42*b*c*d^4+19*c^2*d^4-35*a*d^5-23*b*d^5-45*c*d^5+6*d^6-36*a^5*e-35*a^4*b*e+47*a^3*b^2*e-20*a^2*b^3*e+28*a*b^4*e+37*b^5*e-50*a^4*c*e-35*a^3*b*c*e+a^2*b^2*c*e+15*a*b^3*c*e-2*b^4*c*e-10*a^3*c^2*e-50*a^2*b*c^2*e-34*a*b^2*c^2*e+28*b^3*c^2*e+18*a^2*c^3*e-13*a*b*c^3*e-17*b^2*c^3*e-19*a*c^4*e+9*b*c^4*e-43*c^5*e-29*a^4*d*e-17*a^3*b*d*e+47*a^2*b^2*d*e+26*a*b^3*d*e-13*b^4*d*e+11*a^3*c*d*e+5*a^2*b*c*d*e-25*a*b^2*c*d*e+26*b^3*c*d*e-17*a^2*c^2*d*e-37*a*b*c^2*d*e-7*b^2*c^2*d*e+28*a*c^3*d*e+28*b*c^3*d*e-16*c^4*d*e+30*a^3*d^2*e-25*a^2*b*d^2*e+9*a*b^2*d^2*e+34*b^3*d^2*e+2*a^2*c*d^2*e+30*a*b*c*d^2*e-37*b^2*c*d^2*e+33*a*c^2*d^2*e-5*b*c^2*d^2*e-4*c^3*d^2*e+50*a^2*d^3*e-50*a*b*d^3*e+9*b^2*d^3*e+11*a*c*d^3*e-31*b*c*d^3*e+29*c^2*d^3*e-37*a*d^4*e-22*b*d^4*e-20*c*d^4*e-30*d^5*e+19*a^4*e^2+42*a^3*b*e^2+43*a^2*b^2*e^2-22*a*b^3*e^2+40*b^4*e^2-12*a^3*c*e^2-37*a^2*b*c*e^2-38*a*b^2*c*e^2+47*b^3*c*e^2+33*a^2*c^2*e^2-26*a*b*c^2*e^2+8*b^2*c^2*e^2+43*a*c^3*e^2+43*b*c^3*e^2-26*c^4*e^2+13*a^3*d*e^2+7*a^2*b*d*e^2-38*a*b^2*d*e^2+28*b^3*d*e^2-35*a^2*c*d*e^2+41*a*b*c*d*e^2+2*b^2*c*d*e^2-44*a*c^2*d*e^2-5*b*c^2*d*e^2+35*c^3*d*e^2+46*a^2*d^2*e^2-32*a*b*d^2*e^2-37*b^2*d^2*e^2+4*a*c*d^2*e^2+15*b*c*d^2*e^2+13*c^2*d^2*e^2+14*a*d^3*e^2+3*b*d^3*e^2-7*c*d^3*e^2+9*d^4*e^2-43*a^3*e^3+46*a^2*b*e^3-17*a*b^2*e^3+12*b^3*e^3-9*a^2*c*e^3+40*a*b*c*e^3+7*b^2*c*e^3-31*a*c^2*e^3+32*b*c^2*e^3-49*a^2*d*e^3+22*a*b*d*e^3+27*b^2*d*e^3+34*a*c*d*e^3-39*b*c*d*e^3-17*c^2*d*e^3-39*a*d^2*e^3+20*b*d^2*e^3-10*c*d^2*e^3+2*d^3*e^3+4*a^2*e^4+21*a*b*e^4+20*b^2*e^4+36*a*c*e^4+49*b*c*e^4+24*c^2*e^4-31*a*d*e^4+23*b*d*e^4+48*c*d*e^4-12*d^2*e^4+8*a*e^5-8*b*e^5-15*c*e^5-d*e^5+24*e^6, b^2*c^4-39*a^4*d^2+a^3*b*d^2+26*a^2*b^2*d^2+29*a*b^3*d^2-5*b^4*d^2+13*a^3*c*d^2-47*a^2*b*c*d^2+17*a*b^2*c*d^2+22*b^3*c*d^2+25*a^2*c^2*d^2-2*a*b*c^2*d^2+18*b^2*c^2*d^2+43*a*c^3*d^2+48*b*c^3*d^2-24*c^4*d^2-17*a^3*d^3-16*a^2*b*d^3-3*a*b^2*d^3+35*b^3*d^3+8*a^2*c*d^3+30*a*b*c*d^3-6*b^2*c*d^3+17*a*c^2*d^3-25*b*c^2*d^3+34*c^3*d^3+13*a^2*d^4-49*a*b*d^4-48*b^2*d^4-6*a*c*d^4+43*b*c*d^4+31*c^2*d^4+30*a*d^5-12*b*d^5+4*c*d^5+39*d^6+48*a^5*e+15*a^4*b*e-41*a^3*b^2*e+41*a^2*b^3*e-16*a*b^4*e+28*b^5*e-48*a^4*c*e+11*a^3*b*c*e+42*a^2*b^2*c*e+34*a*b^3*c*e+48*b^4*c*e-24*a^3*c^2*e+29*a^2*b*c^2*e+6*a*b^2*c^2*e+18*b^3*c^2*e-31*a^2*c^3*e+15*a*b*c^3*e+22*b^2*c^3*e-a*c^4*e+15*b*c^4*e-46*c^5*e-36*a^4*d*e+a^3*b*d*e+46*a^2*b^2*d*e-29*a*b^3*d*e+41*b^4*d*e-13*a^3*c*d*e-4*a^2*b*c*d*e-39*a*b^2*c*d*e-39*b^3*c*d*e+35*a^2*c^2*d*e-29*a*b*c^2*d*e-26*b^2*c^2*d*e-37*a*c^3*d*e-8*b*c^3*d*e-13*c^4*d*e+44*a^3*d^2*e-9*a^2*b*d^2*e-38*a*b^2*d^2*e-30*b^3*d^2*e+49*a^2*c*d^2*e+8*a*b*c*d^2*e-35*b^2*c*d^2*e+40*a*c^2*d^2*e-19*b*c^2*d^2*e-25*c^3*d^2*e+47*a^2*d^3*e+17*a*b*d^3*e-41*b^2*d^3*e-18*a*c*d^3*e+38*b*c*d^3*e+22*c^2*d^3*e-30*a*d^4*e+25*b*d^4*e-11*c*d^4*e-8*d^5*e+47*a^4*e^2+2*a^3*b*e^2+5*a^2*b^2*e^2-31*a*b^3*e^2+21*b^4*e^2-46*a^3*c*e^2-28*a^2*b*c*e^2+49*a*b^2*c*e^2+31*b^3*c*e^2-45*a^2*c^2*e^2+26*a*b*c^2*e^2+18*b^2*c^2*e^2+6*a*c^3*e^2-17*b*c^3*e^2-4*c^4*e^2-8*a^3*d*e^2-37*a^2*b*d*e^2-43*a*b^2*d*e^2+10*b^3*d*e^2+32*a^2*c*d*e^2+21*a*b*c*d*e^2+9*b^2*c*d*e^2-34*a*c^2*d*e^2-50*b*c^2*d*e^2-7*c^3*d*e^2+31*a^2*d^2*e^2+22*b^2*d^2*e^2-35*a*c*d^2*e^2-3*b*c*d^2*e^2+13*c^2*d^2*e^2-35*a*d^3*e^2-45*b*d^3*e^2-44*c*d^3*e^2+44*d^4*e^2+7*a^3*e^3+17*a^2*b*e^3+8*a*b^2*e^3+30*b^3*e^3-28*a^2*c*e^3-25*a*b*c*e^3+6*b^2*c*e^3-29*a*c^2*e^3-29*b*c^2*e^3-23*c^3*e^3-43*a^2*d*e^3+44*a*b*d*e^3+41*b^2*d*e^3-8*a*c*d*e^3-13*b*c*d*e^3+27*c^2*d*e^3+5*a*d^2*e^3+8*b*d^2*e^3+11*c*d^2*e^3-50*d^3*e^3+4*a^2*e^4-31*a*b*e^4-2*b^2*e^4-2*a*c*e^4-27*b*c*e^4-c^2*e^4-17*a*d*e^4-30*b*d*e^4-15*c*d*e^4+5*d^2*e^4-34*a*e^5-49*b*e^5+26*c*e^5-44*d*e^5+46*e^6, a*b*c^4+44*a^4*d^2-12*a^3*b*d^2-6*a^2*b^2*d^2-20*a*b^3*d^2+48*b^4*d^2+19*a^3*c*d^2+4*a^2*b*c*d^2+50*a*b^2*c*d^2+34*b^3*c*d^2-a^2*c^2*d^2-24*a*b*c^2*d^2+43*b^2*c^2*d^2-21*a*c^3*d^2-29*b*c^3*d^2+36*c^4*d^2+48*a^3*d^3-26*a^2*b*d^3-16*a*b^2*d^3+29*b^3*d^3-48*a^2*c*d^3-19*a*b*c*d^3-17*b^2*c*d^3-44*a*c^2*d^3+5*b*c^2*d^3-6*c^3*d^3-a^2*d^4-30*a*b*d^4-16*b^2*d^4+20*a*c*d^4+17*b*c*d^4-50*c^2*d^4+36*a*d^5-36*b*d^5-2*c*d^5+46*d^6-10*a^5*e-39*a^4*b*e+20*a^3*b^2*e+45*a^2*b^3*e-35*a*b^4*e+2*b^5*e+23*a^4*c*e-12*a^3*b*c*e-5*a^2*b^2*c*e+5*a*b^3*c*e-8*b^4*c*e+49*a^3*c^2*e+11*a^2*b*c^2*e-11*a*b^2*c^2*e+28*b^3*c^2*e+34*a^2*c^3*e+50*a*b*c^3*e+33*b^2*c^3*e-48*a*c^4*e-12*b*c^4*e+30*c^5*e+3*a^4*d*e-34*a^3*b*d*e+14*a^2*b^2*d*e-47*a*b^3*d*e+34*b^4*d*e-50*a^3*c*d*e-18*a^2*b*c*d*e-39*a*b^2*c*d*e-27*b^3*c*d*e-42*a^2*c^2*d*e-43*a*b*c^2*d*e+28*b^2*c^2*d*e+45*a*c^3*d*e+37*b*c^3*d*e-36*c^4*d*e+21*a^3*d^2*e+36*a^2*b*d^2*e+8*a*b^2*d^2*e-16*b^3*d^2*e+43*a^2*c*d^2*e+24*b^2*c*d^2*e-21*a*c^2*d^2*e+29*b*c^2*d^2*e-14*c^3*d^2*e+11*a^2*d^3*e+16*a*b*d^3*e-24*b^2*d^3*e+8*a*c*d^3*e-44*b*c*d^3*e+13*c^2*d^3*e-32*a*d^4*e+b*d^4*e-31*c*d^4*e-32*d^5*e+32*a^4*e^2-27*a^3*b*e^2+29*a^2*b^2*e^2-30*a*b^3*e^2+35*b^4*e^2-19*a^3*c*e^2+45*a^2*b*c*e^2-9*a*b^2*c*e^2+9*b^3*c*e^2-33*a^2*c^2*e^2+24*a*b*c^2*e^2-5*b^2*c^2*e^2-42*a*c^3*e^2+32*b*c^3*e^2+37*c^4*e^2+36*a^3*d*e^2-44*a^2*b*d*e^2+46*a*b^2*d*e^2+37*b^3*d*e^2+31*a^2*c*d*e^2+32*a*b*c*d*e^2-37*b^2*c*d*e^2-45*a*c^2*d*e^2-37*b*c^2*d*e^2+38*c^3*d*e^2+40*a^2*d^2*e^2-44*a*b*d^2*e^2+39*b^2*d^2*e^2-20*a*c*d^2*e^2+46*b*c*d^2*e^2+c^2*d^2*e^2-13*a*d^3*e^2+16*b*d^3*e^2-17*c*d^3*e^2+41*d^4*e^2-18*a^3*e^3+12*a^2*b*e^3-20*a*b^2*e^3+34*b^3*e^3+21*a^2*c*e^3+19*a*b*c*e^3+22*b^2*c*e^3+41*a*c^2*e^3+42*b*c^2*e^3-32*c^3*e^3-24*a^2*d*e^3-26*a*b*d*e^3-43*b^2*d*e^3-17*a*c*d*e^3-24*b*c*d*e^3+36*c^2*d*e^3+48*a*d^2*e^3+38*b*d^2*e^3-43*c*d^2*e^3-31*d^3*e^3-21*a^2*e^4+45*a*b*e^4-12*b^2*e^4-42*a*c*e^4-38*b*c*e^4-27*c^2*e^4-3*a*d*e^4-45*b*d*e^4-17*c*d*e^4+15*d^2*e^4+48*a*e^5+21*b*e^5-7*c*e^5-36*d*e^5+12*e^6, a^2*c^4+45*a^4*d^2-49*a^3*b*d^2-20*a^2*b^2*d^2-12*a*b^3*d^2-21*b^4*d^2-29*a^3*c*d^2+23*a^2*b*c*d^2+6*a*b^2*c*d^2-30*b^3*c*d^2-33*a^2*c^2*d^2+31*a*b*c^2*d^2+12*b^2*c^2*d^2+20*a*c^3*d^2-48*b*c^3*d^2-21*c^4*d^2-23*a^3*d^3-38*a^2*b*d^3-41*a*b^2*d^3-3*b^3*d^3+13*a^2*c*d^3-10*a*b*c*d^3-14*b^2*c*d^3+47*a*c^2*d^3+46*b*c^2*d^3-49*c^3*d^3-a^2*d^4-13*a*b*d^4+34*b^2*d^4+8*a*c*d^4-44*b*c*d^4+c^2*d^4-10*a*d^5-b*d^5-34*c*d^5-8*d^6-28*a^5*e+21*a^4*b*e-44*a^3*b^2*e-3*a^2*b^3*e-7*a*b^4*e+49*b^5*e-25*a^4*c*e+22*a^3*b*c*e+18*a^2*b^2*c*e-15*a*b^3*c*e+31*b^4*c*e-27*a^3*c^2*e+9*a^2*b*c^2*e-9*a*b^2*c^2*e+50*b^3*c^2*e-a^2*c^3*e-20*a*b*c^3*e+21*b^2*c^3*e+25*a*c^4*e-29*b*c^4*e-41*c^5*e+28*a^4*d*e-7*a^3*b*d*e-18*a^2*b^2*d*e-33*a*b^3*d*e-32*b^4*d*e-9*a^3*c*d*e-18*a^2*b*c*d*e-7*a*b^2*c*d*e-49*b^3*c*d*e+23*a^2*c^2*d*e+32*a*b*c^2*d*e+17*b^2*c^2*d*e-26*a*c^3*d*e+30*b*c^3*d*e-4*c^4*d*e+17*a^3*d^2*e-31*a^2*b*d^2*e+7*a*b^2*d^2*e-10*a^2*c*d^2*e+9*a*b*c*d^2*e+49*b^2*c*d^2*e-26*a*c^2*d^2*e-21*b*c^2*d^2*e+13*c^3*d^2*e+32*a^2*d^3*e+8*a*b*d^3*e+44*b^2*d^3*e+49*a*c*d^3*e-b*c*d^3*e+39*c^2*d^3*e-a*d^4*e-19*b*d^4*e-40*c*d^4*e-30*d^5*e-2*a^4*e^2-5*a^3*b*e^2-10*a^2*b^2*e^2-31*a*b^3*e^2+37*b^4*e^2+45*a^3*c*e^2+17*a^2*b*c*e^2-34*a*b^2*c*e^2-32*b^3*c*e^2-7*a^2*c^2*e^2-21*a*b*c^2*e^2+50*b^2*c^2*e^2+35*a*c^3*e^2-38*b*c^3*e^2+14*c^4*e^2-21*a^3*d*e^2-4*a^2*b*d*e^2-14*a*b^2*d*e^2+13*b^3*d*e^2-38*a^2*c*d*e^2+44*a*b*c*d*e^2+7*b^2*c*d*e^2-16*a*c^2*d*e^2+38*b*c^2*d*e^2+38*c^3*d*e^2+25*a^2*d^2*e^2-34*a*b*d^2*e^2-32*b^2*d^2*e^2+22*a*c*d^2*e^2+40*b*c*d^2*e^2+4*c^2*d^2*e^2-16*a*d^3*e^2+36*b*d^3*e^2-39*c*d^3*e^2-45*d^4*e^2+39*a^3*e^3+31*a^2*b*e^3-43*a*b^2*e^3-18*b^3*e^3+44*a^2*c*e^3-8*a*b*c*e^3+38*b^2*c*e^3-4*a*c^2*e^3+3*b*c^2*e^3-43*c^3*e^3-6*a^2*d*e^3+34*a*b*d*e^3+6*b^2*d*e^3-13*a*c*d*e^3+32*b*c*d*e^3+30*c^2*d*e^3+28*a*d^2*e^3+17*b*d^2*e^3-19*c*d^2*e^3-46*d^3*e^3+12*a^2*e^4+44*a*b*e^4-42*b^2*e^4-41*a*c*e^4-35*b*c*e^4-37*c^2*e^4+42*a*d*e^4+43*b*d*e^4+5*c*d*e^4+11*d^2*e^4+25*a*e^5-9*b*e^5-27*c*e^5+50*d*e^5+23*e^6, b^3*c^3-13*a^4*d^2-41*a^3*b*d^2+27*a^2*b^2*d^2+a*b^3*d^2+33*b^4*d^2+47*a^3*c*d^2-19*a^2*b*c*d^2-27*a*b^2*c*d^2-6*b^3*c*d^2+37*a^2*c^2*d^2+40*a*b*c^2*d^2+12*b^2*c^2*d^2+36*a*c^3*d^2-25*b*c^3*d^2-45*c^4*d^2-12*a^3*d^3-5*a^2*b*d^3+31*a*b^2*d^3-b^3*d^3-37*a^2*c*d^3+26*a*b*c*d^3-48*b^2*c*d^3+36*a*c^2*d^3+16*b*c^2*d^3+44*c^3*d^3+47*a^2*d^4-20*a*b*d^4-13*b^2*d^4+39*a*c*d^4+17*b*c*d^4-32*c^2*d^4-24*a*d^5-41*b*d^5-31*c*d^5+29*a^5*e+26*a^4*b*e+12*a^3*b^2*e-45*a^2*b^3*e+40*a*b^4*e+20*b^5*e-21*a^4*c*e-28*a^3*b*c*e+38*a^2*b^2*c*e+40*a*b^3*c*e-13*b^4*c*e-9*a^3*c^2*e-9*a^2*b*c^2*e-a*b^2*c^2*e-b^3*c^2*e+32*a^2*c^3*e+43*a*b*c^3*e-44*b^2*c^3*e+39*a*c^4*e+8*b*c^4*e-8*c^5*e+27*a^4*d*e+15*a^3*b*d*e-12*a^2*b^2*d*e-33*a*b^3*d*e+16*b^4*d*e+19*a^3*c*d*e-34*a^2*b*c*d*e+5*a*b^2*c*d*e-31*b^3*c*d*e+5*a^2*c^2*d*e-20*a*b*c^2*d*e-4*b^2*c^2*d*e-50*a*c^3*d*e+44*b*c^3*d*e-31*a^3*d^2*e+31*a^2*b*d^2*e+28*a*b^2*d^2*e-10*b^3*d^2*e+2*a^2*c*d^2*e-19*a*b*c*d^2*e-9*a*c^2*d^2*e+2*b*c^2*d^2*e+40*c^3*d^2*e+45*a^2*d^3*e+9*a*b*d^3*e+26*b^2*d^3*e-14*a*c*d^3*e+2*b*c*d^3*e+7*c^2*d^3*e+36*a*d^4*e-43*b*d^4*e-27*c*d^4*e-4*d^5*e+23*a^4*e^2+45*a^3*b*e^2+41*a^2*b^2*e^2+22*a*b^3*e^2+14*b^4*e^2-30*a^3*c*e^2+19*a^2*b*c*e^2-34*a*b^2*c*e^2+17*b^3*c*e^2-42*a^2*c^2*e^2-12*a*b*c^2*e^2-9*b^2*c^2*e^2-3*a*c^3*e^2+47*b*c^3*e^2+47*c^4*e^2+7*a^3*d*e^2+6*a^2*b*d*e^2+26*a*b^2*d*e^2+10*b^3*d*e^2-11*a^2*c*d*e^2-17*a*b*c*d*e^2+34*b^2*c*d*e^2+21*a*c^2*d*e^2+11*b*c^2*d*e^2+5*c^3*d*e^2-40*a^2*d^2*e^2+11*a*b*d^2*e^2+17*b^2*d^2*e^2+38*a*c*d^2*e^2-18*b*c*d^2*e^2+23*c^2*d^2*e^2+35*a*d^3*e^2+4*b*d^3*e^2-2*c*d^3*e^2+46*d^4*e^2+44*a^3*e^3-14*a^2*b*e^3+25*a*b^2*e^3-41*b^3*e^3-34*a^2*c*e^3-44*a*b*c*e^3+17*a*c^2*e^3+9*b*c^2*e^3+45*c^3*e^3+23*a^2*d*e^3-15*a*b*d*e^3+9*b^2*d*e^3-14*a*c*d*e^3-23*b*c*d*e^3+17*c^2*d*e^3+46*a*d^2*e^3+30*b*d^2*e^3+35*c*d^2*e^3-27*d^3*e^3-40*a^2*e^4-50*a*b*e^4-23*b^2*e^4-46*a*c*e^4+44*b*c*e^4+7*c^2*e^4+14*a*d*e^4-4*b*d*e^4-9*c*d*e^4+44*d^2*e^4-9*a*e^5+28*b*e^5+25*c*e^5+36*d*e^5+28*e^6, a*b^2*c^3+41*a^4*d^2-33*a^3*b*d^2+21*a^2*b^2*d^2-47*a*b^3*d^2-23*b^4*d^2+9*a^3*c*d^2+49*a^2*b*c*d^2+44*a*b^2*c*d^2-25*b^3*c*d^2-28*a^2*c^2*d^2+37*a*b*c^2*d^2+9*b^2*c^2*d^2-21*a*c^3*d^2+36*b*c^3*d^2+48*c^4*d^2+2*a^3*d^3+15*a^2*b*d^3-3*a*b^2*d^3-40*b^3*d^3-19*a^2*c*d^3+4*a*b*c*d^3-29*b^2*c*d^3-48*a*c^2*d^3+41*b*c^2*d^3+34*c^3*d^3+33*a^2*d^4-13*a*b*d^4-34*b^2*d^4-47*a*c*d^4+36*b*c*d^4+34*c^2*d^4+41*a*d^5+25*b*d^5-28*c*d^5-31*d^6+22*a^5*e+a^4*b*e+27*a^3*b^2*e+5*a^2*b^3*e-33*a*b^4*e+2*b^5*e+20*a^4*c*e-30*a^3*b*c*e+11*a^2*b^2*c*e+44*a*b^3*c*e-37*b^4*c*e+a^3*c^2*e+7*a^2*b*c^2*e-20*a*b^2*c^2*e+34*b^3*c^2*e-35*a^2*c^3*e+28*a*b*c^3*e-50*b^2*c^3*e-11*a*c^4*e-26*b*c^4*e+c^5*e-37*a^4*d*e+23*a^3*b*d*e+50*a^2*b^2*d*e+35*a*b^3*d*e-4*b^4*d*e-15*a^3*c*d*e-39*a^2*b*c*d*e-50*a*b^2*c*d*e+47*b^3*c*d*e-38*a^2*c^2*d*e-42*a*b*c^2*d*e+43*b^2*c^2*d*e+24*a*c^3*d*e+31*b*c^3*d*e+41*c^4*d*e-15*a^3*d^2*e+20*a^2*b*d^2*e-24*a*b^2*d^2*e-47*b^3*d^2*e+4*a^2*c*d^2*e+42*a*b*c*d^2*e+20*b^2*c*d^2*e-37*a*c^2*d^2*e+42*b*c^2*d^2*e+6*c^3*d^2*e-45*a^2*d^3*e-7*a*b*d^3*e-37*b^2*d^3*e-34*a*c*d^3*e-44*b*c*d^3*e-c^2*d^3*e-29*a*d^4*e+22*b*d^4*e-27*c*d^4*e-34*d^5*e-13*a^4*e^2+48*a^3*b*e^2+22*a^2*b^2*e^2+30*a*b^3*e^2-10*b^4*e^2-2*a^3*c*e^2+10*a^2*b*c*e^2+23*a*b^2*c*e^2+27*b^3*c*e^2+15*a^2*c^2*e^2-a*b*c^2*e^2+33*b^2*c^2*e^2-13*a*c^3*e^2-13*b*c^3*e^2+44*c^4*e^2-34*a^3*d*e^2+7*a^2*b*d*e^2+a*b^2*d*e^2-50*b^3*d*e^2+23*a^2*c*d*e^2+12*a*b*c*d*e^2+50*b^2*c*d*e^2+29*a*c^2*d*e^2+41*b*c^2*d*e^2+22*c^3*d*e^2-20*a^2*d^2*e^2+4*a*b*d^2*e^2-33*b^2*d^2*e^2-38*a*c*d^2*e^2+47*b*c*d^2*e^2+21*c^2*d^2*e^2+18*b*d^3*e^2+44*c*d^3*e^2+31*d^4*e^2-3*a^3*e^3-32*a^2*b*e^3-45*a*b^2*e^3-20*b^3*e^3+29*a^2*c*e^3-35*a*b*c*e^3-11*b^2*c*e^3-13*a*c^2*e^3-38*b*c^2*e^3+17*c^3*e^3-41*a^2*d*e^3-36*a*b*d*e^3-6*b^2*d*e^3-14*a*c*d*e^3-16*b*c*d*e^3-6*c^2*d*e^3+20*a*d^2*e^3-29*b*d^2*e^3+50*c*d^2*e^3-37*d^3*e^3-27*a^2*e^4+15*a*b*e^4+46*b^2*e^4+39*a*c*e^4-26*b*c*e^4-10*c^2*e^4-40*a*d*e^4-5*b*d*e^4-23*c*d*e^4+36*d^2*e^4-21*a*e^5+4*b*e^5-48*c*e^5+38*d*e^5-36*e^6, a^2*b*c^3+6*a^4*d^2-4*a^3*b*d^2+37*a^2*b^2*d^2+18*a*b^3*d^2-34*b^4*d^2+23*a^3*c*d^2-9*a^2*b*c*d^2-46*a*b^2*c*d^2+19*b^3*c*d^2+42*a^2*c^2*d^2-34*a*b*c^2*d^2-14*b^2*c^2*d^2-10*a*c^3*d^2+13*b*c^3*d^2+14*c^4*d^2-38*a^3*d^3-13*a^2*b*d^3+47*a*b^2*d^3-9*b^3*d^3-a^2*c*d^3+33*a*b*c*d^3+9*b^2*c*d^3+33*a*c^2*d^3+37*b*c^2*d^3+41*c^3*d^3+12*a^2*d^4-50*a*b*d^4+11*b^2*d^4-48*a*c*d^4+27*b*c*d^4-48*c^2*d^4-48*a*d^5-19*b*d^5+46*c*d^5+5*d^6+43*a^5*e-13*a^4*b*e-16*a^3*b^2*e+34*a^2*b^3*e+25*a*b^4*e+29*b^5*e-8*a^4*c*e-2*a^3*b*c*e+4*a^2*b^2*c*e+23*a*b^3*c*e+7*b^4*c*e-6*a^3*c^2*e-39*a^2*b*c^2*e-10*a*b^2*c^2*e+18*b^3*c^2*e-18*a^2*c^3*e+35*a*b*c^3*e+18*b^2*c^3*e-2*a*c^4*e+16*b*c^4*e-21*c^5*e-44*a^4*d*e-a^3*b*d*e+19*a^2*b^2*d*e+32*a*b^3*d*e+20*b^4*d*e+36*a^3*c*d*e+16*a^2*b*c*d*e+7*a*b^2*c*d*e+21*b^3*c*d*e+21*a^2*c^2*d*e-31*a*b*c^2*d*e+10*b^2*c^2*d*e-16*a*c^3*d*e+40*b*c^3*d*e-16*c^4*d*e-43*a^3*d^2*e+50*a^2*b*d^2*e-14*a*b^2*d^2*e-24*b^3*d^2*e-23*a^2*c*d^2*e-21*a*b*c*d^2*e-2*b^2*c*d^2*e+38*a*c^2*d^2*e+40*b*c^2*d^2*e+38*c^3*d^2*e-5*a^2*d^3*e+31*a*b*d^3*e-50*b^2*d^3*e+46*a*c*d^3*e-14*b*c*d^3*e+45*c^2*d^3*e-25*a*d^4*e-8*b*d^4*e+3*c*d^4*e+7*d^5*e-a^4*e^2-29*a^3*b*e^2-23*a^2*b^2*e^2+19*a*b^3*e^2-41*b^4*e^2+46*a^3*c*e^2-27*a^2*b*c*e^2-24*a*b^2*c*e^2+26*b^3*c*e^2+8*a^2*c^2*e^2-11*a*b*c^2*e^2-9*b^2*c^2*e^2+29*a*c^3*e^2+15*b*c^3*e^2-10*c^4*e^2-37*a^3*d*e^2+25*a^2*b*d*e^2-26*a*b^2*d*e^2+7*b^3*d*e^2-19*a^2*c*d*e^2-12*a*b*c*d*e^2+50*b^2*c*d*e^2-40*a*c^2*d*e^2-28*b*c^2*d*e^2+26*c^3*d*e^2+28*a^2*d^2*e^2+38*a*b*d^2*e^2+44*b^2*d^2*e^2-32*a*c*d^2*e^2-14*b*c*d^2*e^2+23*c^2*d^2*e^2+44*a*d^3*e^2+47*b*d^3*e^2+46*c*d^3*e^2+3*d^4*e^2-27*a^3*e^3+5*a^2*b*e^3-48*a*b^2*e^3+22*b^3*e^3+32*a^2*c*e^3+23*a*b*c*e^3+34*b^2*c*e^3+4*a*c^2*e^3-25*b*c^2*e^3+13*c^3*e^3+25*a^2*d*e^3-24*a*b*d*e^3+11*b^2*d*e^3+32*a*c*d*e^3-14*b*c*d*e^3+4*c^2*d*e^3+10*a*d^2*e^3-7*b*d^2*e^3+22*c*d^2*e^3-4*d^3*e^3+6*a^2*e^4+19*a*b*e^4+15*b^2*e^4+9*a*c*e^4-49*b*c*e^4+37*c^2*e^4-46*a*d*e^4+33*b*d*e^4+41*c*d*e^4-41*d^2*e^4+11*a*e^5-44*b*e^5+46*c*e^5+12*d*e^5-50*e^6, a^3*c^3-8*a^4*d^2+24*a^3*b*d^2-28*a^2*b^2*d^2+27*a*b^3*d^2-17*b^4*d^2-40*a^3*c*d^2+28*a^2*b*c*d^2+2*a*b^2*c*d^2-18*b^3*c*d^2+45*a^2*c^2*d^2-13*a*b*c^2*d^2-14*b^2*c^2*d^2+35*a*c^3*d^2-32*b*c^3*d^2+2*c^4*d^2-27*a^3*d^3-41*a^2*b*d^3-36*a*b^2*d^3-50*b^3*d^3+23*a^2*c*d^3+25*a*b*c*d^3+22*b^2*c*d^3+15*a*c^2*d^3-36*b*c^2*d^3-43*c^3*d^3-26*a^2*d^4-43*a*b*d^4-25*b^2*d^4-14*a*c*d^4+32*b*c*d^4+25*c^2*d^4+23*a*d^5-32*b*d^5+28*c*d^5-24*d^6+4*a^5*e-15*a^4*b*e-45*a^3*b^2*e-47*a^2*b^3*e+50*a*b^4*e+3*b^5*e+41*a^4*c*e+45*a^2*b^2*c*e+7*a*b^3*c*e-41*b^4*c*e+13*a^3*c^2*e+5*a^2*b*c^2*e+33*a*b^2*c^2*e+35*b^3*c^2*e+9*a^2*c^3*e-4*a*b*c^3*e-43*b^2*c^3*e-8*a*c^4*e+10*b*c^4*e-17*c^5*e+24*a^4*d*e-6*a^3*b*d*e+22*a^2*b^2*d*e+3*a*b^3*d*e+31*b^4*d*e-24*a^3*c*d*e+10*a^2*b*c*d*e+28*a*b^2*c*d*e-28*b^3*c*d*e+49*a^2*c^2*d*e+17*a*b*c^2*d*e+21*b^2*c^2*d*e-29*a*c^3*d*e-18*b*c^3*d*e+18*c^4*d*e+46*a^3*d^2*e+27*a^2*b*d^2*e+5*a*b^2*d^2*e+17*b^3*d^2*e+42*a^2*c*d^2*e+37*a*b*c*d^2*e+48*b^2*c*d^2*e+34*a*c^2*d^2*e+35*b*c^2*d^2*e+8*c^3*d^2*e+a^2*d^3*e-27*a*b*d^3*e+31*b^2*d^3*e+16*a*c*d^3*e+49*b*c*d^3*e-c^2*d^3*e+3*a*d^4*e-22*b*d^4*e+50*c*d^4*e-18*d^5*e+26*a^4*e^2+23*a^3*b*e^2+23*a^2*b^2*e^2-47*a*b^3*e^2+32*b^4*e^2-5*a^3*c*e^2-10*a^2*b*c*e^2-32*a*b^2*c*e^2+21*b^3*c*e^2+50*a^2*c^2*e^2+9*a*b*c^2*e^2+39*b^2*c^2*e^2+24*a*c^3*e^2-15*b*c^3*e^2-12*c^4*e^2+25*a^3*d*e^2+39*a^2*b*d*e^2+34*a*b^2*d*e^2+9*b^3*d*e^2+4*a^2*c*d*e^2+45*a*b*c*d*e^2+14*b^2*c*d*e^2+24*a*c^2*d*e^2+25*b*c^2*d*e^2-33*c^3*d*e^2+43*a^2*d^2*e^2-27*a*b*d^2*e^2+19*b^2*d^2*e^2-20*a*c*d^2*e^2-35*b*c*d^2*e^2+45*c^2*d^2*e^2-17*a*d^3*e^2-48*b*d^3*e^2-25*c*d^3*e^2-19*d^4*e^2+44*a^3*e^3+10*a^2*b*e^3+21*a*b^2*e^3-42*b^3*e^3+40*a^2*c*e^3-50*a*b*c*e^3-9*a*c^2*e^3+39*b*c^2*e^3+25*c^3*e^3+23*a^2*d*e^3-14*a*b*d*e^3+16*b^2*d*e^3+16*a*c*d*e^3+43*b*c*d*e^3-13*c^2*d*e^3-9*a*d^2*e^3-7*b*d^2*e^3+26*c*d^2*e^3-44*d^3*e^3-24*a^2*e^4+34*a*b*e^4+41*b^2*e^4-9*a*c*e^4+13*b*c*e^4-37*c^2*e^4-20*a*d*e^4-37*b*d*e^4+29*c*d*e^4+34*d^2*e^4+45*a*e^5+8*b*e^5+7*d*e^5+e^6, b^4*c^2-14*a^4*d^2-37*a^3*b*d^2+19*a^2*b^2*d^2+4*a*b^3*d^2+20*b^4*d^2+34*a^3*c*d^2+17*a^2*b*c*d^2-35*a*b^2*c*d^2-21*b^3*c*d^2+32*a^2*c^2*d^2-31*a*b*c^2*d^2+18*b^2*c^2*d^2+6*a*c^3*d^2+21*b*c^3*d^2+24*c^4*d^2-4*a^3*d^3+41*a^2*b*d^3-14*a*b^2*d^3+38*b^3*d^3-26*a^2*c*d^3-48*a*b*c*d^3-39*b^2*c*d^3+a*c^2*d^3+50*b*c^2*d^3-13*c^3*d^3+21*a^2*d^4-17*a*b*d^4+47*b^2*d^4+16*a*c*d^4+12*b*c*d^4+30*c^2*d^4+11*a*d^5-5*b*d^5-42*c*d^5-15*d^6+15*a^5*e-15*a^4*b*e+36*a^3*b^2*e-21*a^2*b^3*e-9*a*b^4*e-34*b^5*e-40*a^4*c*e+7*a^3*b*c*e-22*a^2*b^2*c*e+48*a*b^3*c*e-24*b^4*c*e-40*a^3*c^2*e+17*a^2*b*c^2*e-15*a*b^2*c^2*e+19*b^3*c^2*e-19*a^2*c^3*e-36*a*b*c^3*e+26*b^2*c^3*e-32*a*c^4*e-46*b*c^4*e+26*c^5*e-33*a^4*d*e+33*a^3*b*d*e+28*a^2*b^2*d*e+48*a*b^3*d*e-22*b^4*d*e+46*a^3*c*d*e+35*a^2*b*c*d*e-21*a*b^2*c*d*e+b^3*c*d*e+8*a^2*c^2*d*e+14*a*b*c^2*d*e+12*b^2*c^2*d*e-4*a*c^3*d*e+32*b*c^3*d*e-17*c^4*d*e-42*a^3*d^2*e-43*a^2*b*d^2*e+17*a*b^2*d^2*e+21*b^3*d^2*e-31*a^2*c*d^2*e-46*a*b*c*d^2*e-26*b^2*c*d^2*e+35*a*c^2*d^2*e+14*b*c^2*d^2*e-35*c^3*d^2*e-3*a^2*d^3*e+50*a*b*d^3*e+41*b^2*d^3*e+36*a*c*d^3*e+7*b*c*d^3*e+7*c^2*d^3*e+15*a*d^4*e-38*b*d^4*e-37*c*d^4*e-34*d^5*e+15*a^4*e^2+44*a^3*b*e^2+42*a^2*b^2*e^2+10*a*b^3*e^2-23*b^4*e^2+37*a^3*c*e^2+50*a^2*b*c*e^2+20*a*b^2*c*e^2-50*b^3*c*e^2-4*a^2*c^2*e^2-3*a*b*c^2*e^2-14*b^2*c^2*e^2-28*a*c^3*e^2-10*b*c^3*e^2-33*c^4*e^2-11*a^3*d*e^2-8*a^2*b*d*e^2-23*a*b^2*d*e^2-14*a^2*c*d*e^2+42*a*b*c*d*e^2-42*b^2*c*d*e^2-36*a*c^2*d*e^2+41*b*c^2*d*e^2-27*c^3*d*e^2+30*a^2*d^2*e^2+3*a*b*d^2*e^2+33*b^2*d^2*e^2-28*a*c*d^2*e^2-26*b*c*d^2*e^2+c^2*d^2*e^2+46*a*d^3*e^2+21*b*d^3*e^2-32*c*d^3*e^2-16*d^4*e^2-23*a^3*e^3+6*a^2*b*e^3+40*a*b^2*e^3-38*b^3*e^3+28*a^2*c*e^3-14*a*b*c*e^3+6*b^2*c*e^3+45*a*c^2*e^3+2*b*c^2*e^3-11*c^3*e^3+18*a^2*d*e^3+36*a*b*d*e^3-40*b^2*d*e^3-43*a*c*d*e^3+44*b*c*d*e^3-26*c^2*d*e^3+23*a*d^2*e^3+28*b*d^2*e^3+15*c*d^2*e^3-18*d^3*e^3-13*a^2*e^4-47*a*b*e^4-28*b^2*e^4-22*a*c*e^4+20*b*c*e^4+17*c^2*e^4+a*d*e^4+46*b*d*e^4-15*c*d*e^4+40*d^2*e^4+34*a*e^5-9*b*e^5-29*c*e^5+15*d*e^5+32*e^6, a*b^3*c^2-37*a^4*d^2-46*a^3*b*d^2+11*a^2*b^2*d^2+21*a*b^3*d^2+21*b^4*d^2-23*a^3*c*d^2-3*a^2*b*c*d^2+3*a*b^2*c*d^2-32*b^3*c*d^2-37*a^2*c^2*d^2-36*a*b*c^2*d^2+37*b^2*c^2*d^2-6*a*c^3*d^2-34*b*c^3*d^2+48*c^4*d^2+28*a^3*d^3+43*a^2*b*d^3+43*a*b^2*d^3+17*b^3*d^3+26*a^2*c*d^3+33*a*b*c*d^3-2*b^2*c*d^3-21*a*c^2*d^3-14*b*c^2*d^3-39*c^3*d^3-a^2*d^4-22*a*b*d^4-39*b^2*d^4-35*a*c*d^4+13*b*c*d^4-24*c^2*d^4-11*a*d^5+16*b*d^5+30*c*d^5-22*d^6-22*a^5*e+19*a^4*b*e-15*a^3*b^2*e-8*a^2*b^3*e+14*a*b^4*e-5*b^5*e+6*a^4*c*e+6*a^3*b*c*e+46*a^2*b^2*c*e+39*a*b^3*c*e+21*b^4*c*e-22*a^3*c^2*e+26*a^2*b*c^2*e+24*a*b^2*c^2*e+10*b^3*c^2*e-23*a^2*c^3*e+26*a*b*c^3*e+b^2*c^3*e+39*a*c^4*e+35*b*c^4*e-19*c^5*e+17*a^4*d*e+38*a^3*b*d*e+9*a^2*b^2*d*e-19*a*b^3*d*e+42*b^4*d*e-11*a^3*c*d*e-6*a^2*b*c*d*e+10*a*b^2*c*d*e-10*b^3*c*d*e+41*a^2*c^2*d*e+10*a*b*c^2*d*e+46*b^2*c^2*d*e-33*a*c^3*d*e-6*b*c^3*d*e+11*c^4*d*e-33*a^3*d^2*e-22*a^2*b*d^2*e-6*a*b^2*d^2*e-11*b^3*d^2*e+34*a^2*c*d^2*e-39*a*b*c*d^2*e-45*b^2*c*d^2*e-17*a*c^2*d^2*e-8*b*c^2*d^2*e-41*c^3*d^2*e+13*a^2*d^3*e-11*a*b*d^3*e-13*b^2*d^3*e+3*a*c*d^3*e-28*b*c*d^3*e+33*c^2*d^3*e-8*a*d^4*e+24*b*d^4*e-34*c*d^4*e-7*d^5*e+26*a^4*e^2+12*a^3*b*e^2-20*a^2*b^2*e^2+5*a*b^3*e^2+30*b^4*e^2+6*a^3*c*e^2-45*a^2*b*c*e^2-49*a*b^2*c*e^2+43*b^3*c*e^2-29*a^2*c^2*e^2+4*a*b*c^2*e^2+17*b^2*c^2*e^2+13*a*c^3*e^2+21*b*c^3*e^2+16*c^4*e^2-25*a^3*d*e^2-7*a^2*b*d*e^2+42*a*b^2*d*e^2-44*b^3*d*e^2+19*a^2*c*d*e^2+5*a*b*c*d*e^2-38*b^2*c*d*e^2-17*a*c^2*d*e^2-15*b*c^2*d*e^2-26*c^3*d*e^2+47*a^2*d^2*e^2-42*a*b*d^2*e^2-26*b^2*d^2*e^2-50*a*c*d^2*e^2+25*b*c*d^2*e^2-3*c^2*d^2*e^2-47*a*d^3*e^2-40*b*d^3*e^2+24*c*d^3*e^2+35*d^4*e^2-22*a^3*e^3-5*a^2*b*e^3-10*a*b^2*e^3-7*b^3*e^3+6*a^2*c*e^3-16*a*b*c*e^3-28*b^2*c*e^3-43*a*c^2*e^3+24*b*c^2*e^3-9*c^3*e^3+42*a^2*d*e^3-12*a*b*d*e^3-29*b^2*d*e^3+35*a*c*d*e^3+27*b*c*d*e^3+40*c^2*d*e^3-17*a*d^2*e^3+29*b*d^2*e^3+38*c*d^2*e^3+13*d^3*e^3-23*a^2*e^4+32*a*b*e^4+5*b^2*e^4+11*a*c*e^4-b*c*e^4-37*c^2*e^4+3*a*d*e^4-3*b*d*e^4+37*c*d*e^4-28*d^2*e^4-33*a*e^5+18*b*e^5+45*c*e^5-11*d*e^5+42*e^6, a^2*b^2*c^2+34*a^4*d^2+5*a^3*b*d^2-6*a^2*b^2*d^2-24*a*b^3*d^2+14*b^4*d^2+24*a^3*c*d^2-13*a^2*b*c*d^2+27*a*b^2*c*d^2+10*b^3*c*d^2-38*a^2*c^2*d^2+14*a*b*c^2*d^2+49*b^2*c^2*d^2+42*a*c^3*d^2-4*b*c^3*d^2+32*c^4*d^2+47*a^3*d^3+38*a^2*b*d^3+12*a*b^2*d^3-7*b^3*d^3+30*a^2*c*d^3+2*a*b*c*d^3+23*b^2*c*d^3-42*a*c^2*d^3+19*b*c^2*d^3-19*c^3*d^3-12*a^2*d^4+37*a*b*d^4+47*b^2*d^4+31*a*c*d^4+4*b*c*d^4-36*c^2*d^4-10*a*d^5-7*b*d^5+6*c*d^5-12*d^6-46*a^5*e-47*a^4*b*e+49*a^3*b^2*e+45*a^2*b^3*e+44*a*b^4*e+35*b^5*e+24*a^4*c*e+8*a^3*b*c*e-31*a^2*b^2*c*e+21*a*b^3*c*e+40*b^4*c*e-35*a^3*c^2*e+38*a^2*b*c^2*e+12*a*b^2*c^2*e-27*b^3*c^2*e+39*a^2*c^3*e-48*a*b*c^3*e+21*b^2*c^3*e+29*a*c^4*e-36*b*c^4*e-46*c^5*e-46*a^4*d*e+a^3*b*d*e+11*a^2*b^2*d*e+10*a*b^3*d*e-29*b^4*d*e-16*a^3*c*d*e-18*a^2*b*c*d*e+15*a*b^2*c*d*e-30*b^3*c*d*e-34*a^2*c^2*d*e+36*a*b*c^2*d*e+6*a*c^3*d*e-6*b*c^3*d*e+40*c^4*d*e+49*a^3*d^2*e-14*a^2*b*d^2*e-33*a*b^2*d^2*e+34*b^3*d^2*e-26*a^2*c*d^2*e-31*a*b*c*d^2*e-10*b^2*c*d^2*e+40*a*c^2*d^2*e+34*b*c^2*d^2*e+17*c^3*d^2*e-32*a^2*d^3*e-5*a*b*d^3*e-47*b^2*d^3*e-4*a*c*d^3*e+b*c*d^3*e+47*c^2*d^3*e+8*a*d^4*e+48*b*d^4*e-38*c*d^4*e+34*d^5*e-12*a^4*e^2+6*a^2*b^2*e^2-9*a*b^3*e^2-17*b^4*e^2-16*a^3*c*e^2-32*a^2*b*c*e^2+49*a*b^2*c*e^2+3*b^3*c*e^2+27*a^2*c^2*e^2-42*a*b*c^2*e^2-b^2*c^2*e^2+42*a*c^3*e^2+21*b*c^3*e^2-18*c^4*e^2-a^3*d*e^2+8*a^2*b*d*e^2+45*a*b^2*d*e^2+36*b^3*d*e^2+42*a^2*c*d*e^2-29*a*b*c*d*e^2+45*b^2*c*d*e^2-9*a*c^2*d*e^2-32*b*c^2*d*e^2-50*c^3*d*e^2-25*a^2*d^2*e^2+14*a*b*d^2*e^2-44*b^2*d^2*e^2-16*a*c*d^2*e^2+29*b*c*d^2*e^2+17*c^2*d^2*e^2-12*a*d^3*e^2+28*b*d^3*e^2+36*c*d^3*e^2+24*d^4*e^2+24*a^3*e^3-39*a^2*b*e^3-2*a*b^2*e^3-28*b^3*e^3+31*a^2*c*e^3-47*a*b*c*e^3-b^2*c*e^3-17*a*c^2*e^3+50*b*c^2*e^3-c^3*e^3-a^2*d*e^3+41*a*b*d*e^3-13*b^2*d*e^3-13*a*c*d*e^3+4*b*c*d*e^3+32*c^2*d*e^3-16*a*d^2*e^3-11*b*d^2*e^3+49*c*d^2*e^3+d^3*e^3+32*a^2*e^4-11*a*b*e^4+5*b^2*e^4+3*a*c*e^4-49*b*c*e^4+32*c^2*e^4-11*a*d*e^4-43*b*d*e^4+35*c*d*e^4-5*d^2*e^4+40*a*e^5+18*b*e^5+3*c*e^5+25*d*e^5+28*e^6, a^3*b*c^2-30*a^4*d^2+28*a^3*b*d^2+41*a^2*b^2*d^2-11*a*b^3*d^2+27*b^4*d^2-36*a^3*c*d^2+27*a^2*b*c*d^2+50*a*b^2*c*d^2-34*b^3*c*d^2-21*a^2*c^2*d^2-6*a*b*c^2*d^2-8*b^2*c^2*d^2-14*a*c^3*d^2-35*b*c^3*d^2+21*c^4*d^2+37*a^3*d^3-14*a^2*b*d^3-41*a*b^2*d^3+30*b^3*d^3+35*a^2*c*d^3-28*a*b*c*d^3+26*b^2*c*d^3+19*a*c^2*d^3+b*c^2*d^3-5*c^3*d^3-29*a^2*d^4+25*a*b*d^4-38*b^2*d^4+50*a*c*d^4+10*b*c*d^4+30*c^2*d^4+31*a*d^5-49*b*d^5+39*c*d^5-40*d^6+16*a^5*e-47*a^4*b*e+39*a^3*b^2*e-41*a^2*b^3*e-27*a*b^4*e+10*b^5*e-20*a^4*c*e+23*a^3*b*c*e-39*a^2*b^2*c*e+28*a*b^3*c*e-16*b^4*c*e+20*a^3*c^2*e+22*a^2*b*c^2*e+45*a*b^2*c^2*e-b^3*c^2*e+37*a^2*c^3*e-3*a*b*c^3*e-49*b^2*c^3*e+8*a*c^4*e-3*b*c^4*e+41*c^5*e+33*a^4*d*e+35*a^3*b*d*e+10*a^2*b^2*d*e-42*a*b^3*d*e+14*b^4*d*e+a^3*c*d*e-28*a^2*b*c*d*e-26*a*b^2*c*d*e+35*b^3*c*d*e-24*a^2*c^2*d*e-3*a*b*c^2*d*e+20*b^2*c^2*d*e+a*c^3*d*e+8*b*c^3*d*e-41*c^4*d*e-12*a^3*d^2*e-43*a^2*b*d^2*e+32*a*b^2*d^2*e-26*b^3*d^2*e-37*a^2*c*d^2*e+50*a*b*c*d^2*e-21*b^2*c*d^2*e+46*a*c^2*d^2*e-26*b*c^2*d^2*e+41*c^3*d^2*e+39*a^2*d^3*e+6*a*b*d^3*e-34*b^2*d^3*e+13*a*c*d^3*e-12*b*c*d^3*e-7*c^2*d^3*e-31*a*d^4*e+19*b*d^4*e-22*c*d^4*e+44*d^5*e+15*a^4*e^2-24*a^3*b*e^2-23*a^2*b^2*e^2-25*a*b^3*e^2+21*b^4*e^2+28*a^3*c*e^2+32*a^2*b*c*e^2+6*a*b^2*c*e^2-6*b^3*c*e^2-32*a^2*c^2*e^2+37*a*b*c^2*e^2-15*b^2*c^2*e^2-3*a*c^3*e^2+5*b*c^3*e^2+33*c^4*e^2+50*a^3*d*e^2+46*a^2*b*d*e^2+3*a*b^2*d*e^2+11*b^3*d*e^2-6*a^2*c*d*e^2-26*a*b*c*d*e^2-26*b^2*c*d*e^2+49*a*c^2*d*e^2+48*b*c^2*d*e^2+14*c^3*d*e^2-11*a^2*d^2*e^2-49*a*b*d^2*e^2+37*b^2*d^2*e^2-20*a*c*d^2*e^2+10*b*c*d^2*e^2+22*c^2*d^2*e^2+46*a*d^3*e^2+3*b*d^3*e^2+24*c*d^3*e^2-49*d^4*e^2-31*a^3*e^3+35*a^2*b*e^3-38*a*b^2*e^3+4*b^3*e^3-10*a^2*c*e^3+a*b*c*e^3-15*b^2*c*e^3-8*a*c^2*e^3-18*b*c^2*e^3-26*c^3*e^3+26*a^2*d*e^3+23*a*b*d*e^3+4*b^2*d*e^3-37*a*c*d*e^3+49*b*c*d*e^3-9*c^2*d*e^3-39*a*d^2*e^3+44*b*d^2*e^3+44*c*d^2*e^3+6*d^3*e^3+49*a^2*e^4+23*a*b*e^4+15*a*c*e^4-10*b*c*e^4+24*c^2*e^4+23*a*d*e^4-34*b*d*e^4-9*c*d*e^4-11*d^2*e^4+49*a*e^5+32*b*e^5-12*c*e^5+32*d*e^5+13*e^6, a^4*c^2-10*a^4*d^2+38*a^3*b*d^2-a^2*b^2*d^2+6*a*b^3*d^2+39*b^4*d^2-11*a^3*c*d^2+9*a^2*b*c*d^2+21*a*b^2*c*d^2-13*b^3*c*d^2+22*a^2*c^2*d^2+33*a*b*c^2*d^2-19*b^2*c^2*d^2-18*a*c^3*d^2-38*b*c^3*d^2-50*c^4*d^2-11*a^3*d^3-41*a^2*b*d^3-9*a*b^2*d^3-40*b^3*d^3-8*a^2*c*d^3+49*a*b*c*d^3+34*b^2*c*d^3+36*a*c^2*d^3-37*b*c^2*d^3+14*c^3*d^3-2*a^2*d^4+34*a*b*d^4+47*b^2*d^4+47*a*c*d^4-20*b*c*d^4-13*c^2*d^4+6*a*d^5-31*b*d^5+28*c*d^5-31*d^6-3*a^5*e+39*a^4*b*e+16*a^3*b^2*e+16*a^2*b^3*e+9*a*b^4*e+37*b^5*e-39*a^4*c*e+5*a^3*b*c*e+36*a^2*b^2*c*e-7*a*b^3*c*e+16*b^4*c*e-43*a^3*c^2*e-5*a^2*b*c^2*e+30*a*b^2*c^2*e+12*b^3*c^2*e-26*a^2*c^3*e+45*a*b*c^3*e+9*b^2*c^3*e+17*a*c^4*e-19*b*c^4*e-6*c^5*e-47*a^4*d*e-33*a^3*b*d*e+12*a^2*b^2*d*e+4*a*b^3*d*e+33*b^4*d*e+3*a^3*c*d*e-33*a^2*b*c*d*e-13*a*b^2*c*d*e+28*b^3*c*d*e-46*a^2*c^2*d*e-32*a*b*c^2*d*e+26*b^2*c^2*d*e-14*a*c^3*d*e+8*b*c^3*d*e-40*c^4*d*e+38*a^3*d^2*e-29*a^2*b*d^2*e+45*a*b^2*d^2*e+6*b^3*d^2*e-34*a^2*c*d^2*e-15*a*b*c*d^2*e-20*b^2*c*d^2*e-24*a*c^2*d^2*e-5*b*c^2*d^2*e-36*c^3*d^2*e+17*a^2*d^3*e-17*a*b*d^3*e-18*b^2*d^3*e+44*a*c*d^3*e+11*b*c*d^3*e-14*c^2*d^3*e-31*a*d^4*e-39*b*d^4*e-48*c*d^4*e+20*d^5*e+a^4*e^2-8*a^3*b*e^2+13*a^2*b^2*e^2-18*a*b^3*e^2-28*b^4*e^2-26*a^3*c*e^2+21*a^2*b*c*e^2-12*a*b^2*c*e^2-46*b^3*c*e^2-45*a^2*c^2*e^2+32*a*b*c^2*e^2-9*b^2*c^2*e^2+36*a*c^3*e^2+38*b*c^3*e^2-15*c^4*e^2-21*a^3*d*e^2+25*a^2*b*d*e^2-6*a*b^2*d*e^2+2*b^3*d*e^2-21*a*b*c*d*e^2+38*b^2*c*d*e^2-3*a*c^2*d*e^2-29*b*c^2*d*e^2-9*c^3*d*e^2-20*a^2*d^2*e^2+32*a*b*d^2*e^2-12*b^2*d^2*e^2-21*a*c*d^2*e^2-b*c*d^2*e^2-31*c^2*d^2*e^2-24*a*d^3*e^2-16*b*d^3*e^2+47*c*d^3*e^2+41*d^4*e^2-12*a^3*e^3-38*a^2*b*e^3-23*a*b^2*e^3+44*b^3*e^3-7*a^2*c*e^3+28*a*b*c*e^3+42*b^2*c*e^3+10*a*c^2*e^3-12*b*c^2*e^3-7*c^3*e^3+33*a^2*d*e^3+37*a*b*d*e^3+39*b^2*d*e^3-43*a*c*d*e^3-21*b*c*d*e^3+20*c^2*d*e^3+48*a*d^2*e^3+25*b*d^2*e^3-20*c*d^2*e^3+35*d^3*e^3+a^2*e^4+40*a*b*e^4+23*b^2*e^4+45*a*c*e^4-4*b*c*e^4-15*c^2*e^4+42*a*d*e^4-49*b*d*e^4-28*c*d*e^4-8*d^2*e^4-38*a*e^5-12*b*e^5+42*c*e^5+11*d*e^5+45*e^6, b^5*c+40*a^4*d^2-47*a^3*b*d^2+16*a^2*b^2*d^2+18*a*b^3*d^2+33*b^4*d^2+9*a^3*c*d^2-38*a^2*b*c*d^2-22*a*b^2*c*d^2+8*b^3*c*d^2-21*a^2*c^2*d^2-2*a*b*c^2*d^2+33*b^2*c^2*d^2+5*a*c^3*d^2-50*b*c^3*d^2-35*c^4*d^2+29*a^3*d^3+25*a^2*b*d^3-38*a*b^2*d^3+17*b^3*d^3-32*a^2*c*d^3-44*a*b*c*d^3-20*b^2*c*d^3-26*a*c^2*d^3-37*b*c^2*d^3+47*c^3*d^3+19*a^2*d^4-34*a*b*d^4-20*b^2*d^4+31*a*c*d^4-14*b*c*d^4-37*c^2*d^4-37*a*d^5+7*b*d^5-42*c*d^5+16*d^6-23*a^5*e-48*a^3*b^2*e-41*a^2*b^3*e+6*a*b^4*e+49*a^4*c*e+34*a^3*b*c*e-8*a^2*b^2*c*e+17*a*b^3*c*e+39*b^4*c*e+2*a^3*c^2*e+42*a^2*b*c^2*e+21*a*b^2*c^2*e-8*b^3*c^2*e-11*a^2*c^3*e+50*a*b*c^3*e+25*b^2*c^3*e-46*a*c^4*e-4*b*c^4*e-10*c^5*e+12*a^4*d*e+9*a^3*b*d*e-46*a^2*b^2*d*e-12*a*b^3*d*e-44*b^4*d*e-35*a^3*c*d*e-46*a^2*b*c*d*e+17*a*b^2*c*d*e+48*b^3*c*d*e-28*a^2*c^2*d*e-50*a*b*c^2*d*e-46*b^2*c^2*d*e+4*a*c^3*d*e-41*b*c^3*d*e-8*c^4*d*e+42*a^3*d^2*e+39*a^2*b*d^2*e+27*a*b^2*d^2*e-40*b^3*d^2*e-8*a^2*c*d^2*e+40*a*b*c*d^2*e-20*b^2*c*d^2*e+35*a*c^2*d^2*e-26*b*c^2*d^2*e-2*c^3*d^2*e-14*a^2*d^3*e-34*a*b*d^3*e-24*b^2*d^3*e+22*a*c*d^3*e+45*b*c*d^3*e-9*c^2*d^3*e-38*a*d^4*e-14*b*d^4*e+50*c*d^4*e-49*d^5*e-23*a^4*e^2-10*a^3*b*e^2-4*a^2*b^2*e^2+49*a*b^3*e^2+28*b^4*e^2-50*a^3*c*e^2+38*a^2*b*c*e^2+26*a*b^2*c*e^2-44*b^3*c*e^2+3*a^2*c^2*e^2+46*a*b*c^2*e^2+42*b^2*c^2*e^2+9*a*c^3*e^2+18*b*c^3*e^2-9*c^4*e^2+16*a^3*d*e^2-42*a^2*b*d*e^2+37*a*b^2*d*e^2-10*b^3*d*e^2-41*a^2*c*d*e^2-5*a*b*c*d*e^2+19*b^2*c*d*e^2+17*a*c^2*d*e^2-19*b*c^2*d*e^2+16*c^3*d*e^2+21*a^2*d^2*e^2-17*a*b*d^2*e^2-15*b^2*d^2*e^2-49*a*c*d^2*e^2+36*b*c*d^2*e^2-41*c^2*d^2*e^2+37*a*d^3*e^2-13*b*d^3*e^2-27*c*d^3*e^2-37*d^4*e^2+37*a^3*e^3-50*a^2*b*e^3+21*a*b^2*e^3+14*b^3*e^3-16*a^2*c*e^3+24*a*b*c*e^3-44*b^2*c*e^3+18*b*c^2*e^3+3*c^3*e^3-38*a^2*d*e^3+41*a*b*d*e^3+29*b^2*d*e^3-9*a*c*d*e^3+9*b*c*d*e^3-39*c^2*d*e^3+42*a*d^2*e^3+22*b*d^2*e^3+18*c*d^2*e^3+35*d^3*e^3+43*a^2*e^4+5*a*b*e^4+5*b^2*e^4+16*a*c*e^4-37*b*c*e^4+20*c^2*e^4-10*a*d*e^4+45*b*d*e^4-46*c*d*e^4+42*d^2*e^4+14*a*e^5+15*b*e^5+38*c*e^5+49*d*e^5+3*e^6, a*b^4*c+32*a^4*d^2+43*a^3*b*d^2+49*a^2*b^2*d^2+38*a*b^3*d^2+47*b^4*d^2+19*a^3*c*d^2+43*a^2*b*c*d^2-25*a*b^2*c*d^2+25*b^3*c*d^2+26*a^2*c^2*d^2-5*a*b*c^2*d^2-19*b^2*c^2*d^2+33*a*c^3*d^2-3*b*c^3*d^2-37*c^4*d^2+18*a^3*d^3-27*a^2*b*d^3-33*a*b^2*d^3-49*b^3*d^3+48*a^2*c*d^3-12*a*b*c*d^3+17*b^2*c*d^3+6*a*c^2*d^3-36*b*c^2*d^3+36*c^3*d^3+a^2*d^4-12*b^2*d^4-3*a*c*d^4-43*b*c*d^4-24*c^2*d^4-14*a*d^5-43*b*d^5-20*c*d^5+24*d^6-42*a^5*e-48*a^4*b*e+29*a^3*b^2*e-29*a^2*b^3*e-37*a*b^4*e+b^5*e-31*a^4*c*e+35*a^3*b*c*e+9*a^2*b^2*c*e-17*a*b^3*c*e-34*b^4*c*e+42*a^3*c^2*e-47*a^2*b*c^2*e+31*a*b^2*c^2*e+9*b^3*c^2*e+48*a^2*c^3*e-15*a*b*c^3*e+34*b^2*c^3*e+15*a*c^4*e-23*b*c^4*e+45*c^5*e-12*a^4*d*e+42*a^3*b*d*e-15*a^2*b^2*d*e-14*a*b^3*d*e+33*b^4*d*e-41*a^3*c*d*e+9*a^2*b*c*d*e+15*a*b^2*c*d*e-44*b^3*c*d*e-32*a^2*c^2*d*e+9*a*b*c^2*d*e+22*b^2*c^2*d*e-23*a*c^3*d*e+43*b*c^3*d*e-37*c^4*d*e+19*a^3*d^2*e-47*a^2*b*d^2*e+39*a*b^2*d^2*e-24*b^3*d^2*e-44*a^2*c*d^2*e-27*a*b*c*d^2*e-30*b^2*c*d^2*e-19*a*c^2*d^2*e-28*b*c^2*d^2*e-30*c^3*d^2*e-41*a^2*d^3*e+17*a*b*d^3*e-30*b^2*d^3*e+3*a*c*d^3*e+50*b*c*d^3*e+47*c^2*d^3*e+47*a*d^4*e-40*b*d^4*e+3*c*d^4*e+28*d^5*e-35*a^4*e^2+23*a^3*b*e^2+2*a^2*b^2*e^2-17*a*b^3*e^2-22*b^4*e^2+35*a^3*c*e^2-38*a^2*b*c*e^2-7*a*b^2*c*e^2-12*b^3*c*e^2+38*a^2*c^2*e^2-12*a*b*c^2*e^2+13*b^2*c^2*e^2+19*b*c^3*e^2-25*c^4*e^2-45*a^3*d*e^2-35*a^2*b*d*e^2+41*a*b^2*d*e^2+10*b^3*d*e^2+17*a^2*c*d*e^2-10*a*b*c*d*e^2-42*b^2*c*d*e^2+13*a*c^2*d*e^2-3*b*c^2*d*e^2-42*c^3*d*e^2-2*a^2*d^2*e^2-7*a*b*d^2*e^2+46*b^2*d^2*e^2+43*a*c*d^2*e^2+29*b*c*d^2*e^2+19*c^2*d^2*e^2-26*a*d^3*e^2+28*b*d^3*e^2+27*c*d^3*e^2+32*d^4*e^2+49*a^3*e^3+48*a^2*b*e^3+34*a*b^2*e^3-48*b^3*e^3+12*a^2*c*e^3+30*a*b*c*e^3+18*b^2*c*e^3-50*a*c^2*e^3+13*b*c^2*e^3+48*c^3*e^3+17*a^2*d*e^3+22*a*b*d*e^3-6*b^2*d*e^3-40*a*c*d*e^3-33*b*c*d*e^3-2*c^2*d*e^3-48*a*d^2*e^3-7*b*d^2*e^3+32*c*d^2*e^3-31*d^3*e^3+46*a^2*e^4+17*a*b*e^4+14*b^2*e^4+8*a*c*e^4-43*b*c*e^4+24*a*d*e^4-41*b*d*e^4-35*c*d*e^4-44*d^2*e^4-29*a*e^5+11*b*e^5+50*c*e^5-32*d*e^5+23*e^6, a^2*b^3*c-22*a^4*d^2+38*a^3*b*d^2+10*a^2*b^2*d^2-31*a*b^3*d^2+42*b^4*d^2-7*a^3*c*d^2-47*a^2*b*c*d^2+37*a*b^2*c*d^2-23*b^3*c*d^2-43*a^2*c^2*d^2+38*a*b*c^2*d^2+18*b^2*c^2*d^2+18*a*c^3*d^2+25*b*c^3*d^2+4*c^4*d^2+36*a^3*d^3-21*a^2*b*d^3+35*a*b^2*d^3+28*b^3*d^3+13*a^2*c*d^3+36*a*b*c*d^3-33*b^2*c*d^3+9*a*c^2*d^3+18*b*c^2*d^3-49*c^3*d^3-5*a^2*d^4-8*a*b*d^4-34*b^2*d^4-43*a*c*d^4-47*b*c*d^4-12*c^2*d^4+34*a*d^5+50*b*d^5-13*c*d^5-20*d^6+29*a^5*e-10*a^4*b*e+17*a^3*b^2*e+7*a^2*b^3*e+45*a*b^4*e-23*b^5*e+41*a^4*c*e+31*a^3*b*c*e+9*a^2*b^2*c*e+3*a*b^3*c*e-11*b^4*c*e+6*a^3*c^2*e+11*a^2*b*c^2*e-42*a*b^2*c^2*e+17*b^3*c^2*e+5*a^2*c^3*e-44*a*b*c^3*e-44*b^2*c^3*e+42*a*c^4*e-29*b*c^4*e+6*c^5*e+7*a^4*d*e-50*a^3*b*d*e+29*a^2*b^2*d*e-42*a*b^3*d*e-25*b^4*d*e-5*a^3*c*d*e-33*a^2*b*c*d*e+36*a*b^2*c*d*e+47*b^3*c*d*e-41*a^2*c^2*d*e+4*a*b*c^2*d*e+44*b^2*c^2*d*e-10*a*c^3*d*e-2*b*c^3*d*e+20*c^4*d*e+21*a^3*d^2*e+6*a^2*b*d^2*e-50*a*b^2*d^2*e+35*b^3*d^2*e-8*a^2*c*d^2*e-17*a*b*c*d^2*e+7*b^2*c*d^2*e+35*a*c^2*d^2*e+28*b*c^2*d^2*e+25*c^3*d^2*e-6*a^2*d^3*e-16*a*b*d^3*e+35*b^2*d^3*e-12*a*c*d^3*e+46*b*c*d^3*e+7*c^2*d^3*e+16*a*d^4*e-24*b*d^4*e+32*c*d^4*e-26*d^5*e+6*a^4*e^2+48*a^3*b*e^2-27*a^2*b^2*e^2+15*a*b^3*e^2-15*b^4*e^2-25*a^3*c*e^2+39*a^2*b*c*e^2-21*a*b^2*c*e^2-8*b^3*c*e^2+15*a^2*c^2*e^2+31*a*b*c^2*e^2+33*b^2*c^2*e^2-31*a*c^3*e^2-27*b*c^3*e^2-16*c^4*e^2+41*a^3*d*e^2-17*a^2*b*d*e^2-25*a*b^2*d*e^2-3*b^3*d*e^2+6*a^2*c*d*e^2-24*a*b*c*d*e^2+b^2*c*d*e^2-a*c^2*d*e^2-15*b*c^2*d*e^2+16*c^3*d*e^2+42*a^2*d^2*e^2+6*a*b*d^2*e^2-25*b^2*d^2*e^2+21*a*c*d^2*e^2+48*b*c*d^2*e^2-10*c^2*d^2*e^2+31*b*d^3*e^2-32*c*d^3*e^2+2*d^4*e^2+35*a^3*e^3+42*a^2*b*e^3+10*a*b^2*e^3-38*b^3*e^3+32*a^2*c*e^3+34*a*b*c*e^3+14*b^2*c*e^3-7*a*c^2*e^3+22*b*c^2*e^3+37*c^3*e^3+2*a^2*d*e^3-42*a*b*d*e^3-6*b^2*d*e^3-9*a*c*d*e^3+22*b*c*d*e^3+19*c^2*d*e^3-21*a*d^2*e^3-37*b*d^2*e^3+43*c*d^2*e^3-36*d^3*e^3+16*a^2*e^4-21*a*b*e^4+44*b^2*e^4-48*a*c*e^4+35*b*c*e^4-25*c^2*e^4+15*a*d*e^4+42*b*d*e^4-27*c*d*e^4+27*d^2*e^4-25*a*e^5-12*b*e^5+20*c*e^5+7*d*e^5+3*e^6, a^3*b^2*c-24*a^4*d^2+20*a^3*b*d^2+24*a^2*b^2*d^2-29*a*b^3*d^2-24*b^4*d^2+13*a^3*c*d^2+31*a*b^2*c*d^2-26*b^3*c*d^2-29*a^2*c^2*d^2-27*a*b*c^2*d^2+4*b^2*c^2*d^2+23*a*c^3*d^2+42*b*c^3*d^2-47*c^4*d^2+50*a^3*d^3+48*a^2*b*d^3-22*a*b^2*d^3+16*b^3*d^3-46*a^2*c*d^3-43*a*b*c*d^3+50*b^2*c*d^3-35*a*c^2*d^3-29*b*c^2*d^3-12*c^3*d^3+23*a^2*d^4+31*a*b*d^4+22*b^2*d^4-27*a*c*d^4-25*b*c*d^4-41*c^2*d^4+42*a*d^5-50*b*d^5+33*c*d^5+11*d^6+19*a^5*e-22*a^4*b*e+33*a^3*b^2*e+43*a^2*b^3*e+43*a*b^4*e-5*b^5*e-14*a^4*c*e-46*a^3*b*c*e-21*a^2*b^2*c*e+29*a*b^3*c*e+15*b^4*c*e+12*a^3*c^2*e-a^2*b*c^2*e-43*a*b^2*c^2*e+48*b^3*c^2*e+26*a^2*c^3*e-46*a*b*c^3*e-35*b^2*c^3*e+a*c^4*e+16*b*c^4*e+6*c^5*e-47*a^4*d*e-a^3*b*d*e+a^2*b^2*d*e-32*a*b^3*d*e-19*b^4*d*e-44*a^3*c*d*e+22*a^2*b*c*d*e+40*a*b^2*c*d*e-19*b^3*c*d*e+12*a^2*c^2*d*e-a*b*c^2*d*e-23*b^2*c^2*d*e-11*a*c^3*d*e-26*b*c^3*d*e-4*c^4*d*e-32*a^3*d^2*e-13*a^2*b*d^2*e-b^3*d^2*e+8*a^2*c*d^2*e-28*a*b*c*d^2*e+46*b^2*c*d^2*e-24*a*c^2*d^2*e+26*b*c^2*d^2*e+27*c^3*d^2*e+12*a^2*d^3*e+10*a*b*d^3*e-32*b^2*d^3*e-12*a*c*d^3*e-30*b*c*d^3*e+50*c^2*d^3*e+6*a*d^4*e+32*b*d^4*e+6*c*d^4*e-48*d^5*e+14*a^4*e^2+48*a^3*b*e^2+16*a^2*b^2*e^2+34*a*b^3*e^2+39*b^4*e^2+2*a^3*c*e^2+5*a^2*b*c*e^2-11*a*b^2*c*e^2-4*b^3*c*e^2-39*a^2*c^2*e^2+46*a*b*c^2*e^2-16*b^2*c^2*e^2-46*a*c^3*e^2-b*c^3*e^2+47*c^4*e^2-3*a^3*d*e^2-48*a^2*b*d*e^2-34*a*b^2*d*e^2+19*b^3*d*e^2+46*a^2*c*d*e^2-49*a*b*c*d*e^2-45*b^2*c*d*e^2-4*a*c^2*d*e^2+33*b*c^2*d*e^2-8*c^3*d*e^2-39*a^2*d^2*e^2-34*a*b*d^2*e^2+9*b^2*d^2*e^2-15*a*c*d^2*e^2+b*c*d^2*e^2+44*c^2*d^2*e^2-39*a*d^3*e^2+10*b*d^3*e^2+9*c*d^3*e^2-6*d^4*e^2-7*a^3*e^3+2*a^2*b*e^3+39*a*b^2*e^3+4*b^3*e^3-49*a^2*c*e^3+48*a*b*c*e^3+b^2*c*e^3+28*a*c^2*e^3-29*b*c^2*e^3-7*c^3*e^3+23*a^2*d*e^3+16*a*b*d*e^3+24*b^2*d*e^3-47*a*c*d*e^3+20*b*c*d*e^3+26*c^2*d*e^3+9*a*d^2*e^3+49*b*d^2*e^3+32*c*d^2*e^3+33*d^3*e^3-3*a^2*e^4+48*a*b*e^4-18*b^2*e^4-43*a*c*e^4-14*b*c*e^4-29*c^2*e^4+49*a*d*e^4-49*b*d*e^4-18*c*d*e^4-18*d^2*e^4+45*a*e^5-40*b*e^5-13*c*e^5+3*d*e^5+5*e^6, a^4*b*c-38*a^4*d^2+23*a^3*b*d^2-28*a^2*b^2*d^2-49*a*b^3*d^2-37*b^4*d^2+46*a^3*c*d^2-39*a^2*b*c*d^2+31*a*b^2*c*d^2+43*b^3*c*d^2+40*a^2*c^2*d^2-30*a*b*c^2*d^2-7*b^2*c^2*d^2+32*a*c^3*d^2+50*b*c^3*d^2+13*c^4*d^2-9*a^3*d^3+23*a^2*b*d^3-12*a*b^2*d^3-42*b^3*d^3+4*a^2*c*d^3-3*a*b*c*d^3+50*b^2*c*d^3+16*a*c^2*d^3+40*b*c^2*d^3-23*c^3*d^3+39*a^2*d^4+35*a*b*d^4-45*b^2*d^4+45*a*c*d^4-15*b*c*d^4-26*c^2*d^4+29*a*d^5+37*b*d^5+3*c*d^5-22*d^6-8*a^5*e+15*a^4*b*e+19*a^3*b^2*e-12*a^2*b^3*e+22*a*b^4*e-48*b^5*e+32*a^4*c*e+48*a^3*b*c*e-14*a^2*b^2*c*e+43*a*b^3*c*e-23*b^4*c*e-36*a^3*c^2*e+36*a^2*b*c^2*e+15*a*b^2*c^2*e-34*b^3*c^2*e-16*a^2*c^3*e+20*a*b*c^3*e-23*b^2*c^3*e+39*a*c^4*e-37*b*c^4*e+43*c^5*e+30*a^4*d*e-38*a^3*b*d*e-25*a^2*b^2*d*e-5*a*b^3*d*e-24*b^4*d*e+5*a^3*c*d*e-47*a^2*b*c*d*e-17*a*b^2*c*d*e+30*b^3*c*d*e-a^2*c^2*d*e-43*a*b*c^2*d*e-6*b^2*c^2*d*e-46*a*c^3*d*e-37*b*c^3*d*e-43*c^4*d*e+48*a^3*d^2*e+20*a^2*b*d^2*e+21*a*b^2*d^2*e+35*b^3*d^2*e-47*a^2*c*d^2*e+27*a*b*c*d^2*e+b^2*c*d^2*e+7*a*c^2*d^2*e-11*b*c^2*d^2*e+46*c^3*d^2*e+40*a^2*d^3*e+43*a*b*d^3*e-31*b^2*d^3*e+22*a*c*d^3*e+2*b*c*d^3*e-18*c^2*d^3*e+35*a*d^4*e+31*b*d^4*e-48*c*d^4*e+43*d^5*e+16*a^4*e^2+27*a^3*b*e^2-28*a^2*b^2*e^2-13*a*b^3*e^2+17*b^4*e^2-34*a^3*c*e^2+12*a^2*b*c*e^2-25*a*b^2*c*e^2+7*b^3*c*e^2-19*a^2*c^2*e^2-31*a*b*c^2*e^2+22*b^2*c^2*e^2-45*a*c^3*e^2-25*b*c^3*e^2+7*c^4*e^2-9*a^3*d*e^2-3*a^2*b*d*e^2+20*a*b^2*d*e^2+28*b^3*d*e^2+41*a^2*c*d*e^2-2*a*b*c*d*e^2+8*b^2*c*d*e^2-20*a*c^2*d*e^2+35*b*c^2*d*e^2-11*c^3*d*e^2-27*a^2*d^2*e^2-29*a*b*d^2*e^2+28*b^2*d^2*e^2+10*a*c*d^2*e^2-8*b*c*d^2*e^2+13*c^2*d^2*e^2-32*a*d^3*e^2+23*b*d^3*e^2-50*c*d^3*e^2+20*d^4*e^2+49*a^3*e^3+9*a^2*b*e^3+27*a*b^2*e^3-15*b^3*e^3-38*a^2*c*e^3+26*a*b*c*e^3-47*b^2*c*e^3+10*a*c^2*e^3-21*b*c^2*e^3+2*c^3*e^3+7*a^2*d*e^3-8*a*b*d*e^3-25*b^2*d*e^3+15*a*c*d*e^3+17*b*c*d*e^3-39*c^2*d*e^3+7*a*d^2*e^3-47*b*d^2*e^3+6*c*d^2*e^3+5*d^3*e^3+21*a^2*e^4-49*a*b*e^4-35*b^2*e^4+32*a*c*e^4-16*b*c*e^4+7*c^2*e^4-25*a*d*e^4+30*b*d*e^4-31*c*d*e^4-21*d^2*e^4+42*a*e^5-b*e^5+14*c*e^5+18*d*e^5+28*e^6, a^5*c-2*a^4*d^2-22*a^3*b*d^2-38*a^2*b^2*d^2+10*a*b^3*d^2+32*b^4*d^2-28*a^3*c*d^2+11*a^2*b*c*d^2-12*a*b^2*c*d^2-39*b^3*c*d^2+43*a^2*c^2*d^2+39*a*b*c^2*d^2-24*b^2*c^2*d^2+27*a*c^3*d^2+47*b*c^3*d^2+9*c^4*d^2+12*a^3*d^3+34*a^2*b*d^3-37*a*b^2*d^3+18*b^3*d^3+45*a^2*c*d^3+21*a*b*c*d^3+29*b^2*c*d^3+31*a*c^2*d^3+23*b*c^2*d^3+44*c^3*d^3-19*a^2*d^4+32*a*b*d^4+46*b^2*d^4+27*a*c*d^4+8*b*c*d^4-20*c^2*d^4-35*a*d^5-21*b*d^5+15*c*d^5-45*d^6-38*a^5*e-35*a^4*b*e-28*a^3*b^2*e-30*a^2*b^3*e-19*a*b^4*e-49*b^5*e+34*a^4*c*e-2*a^3*b*c*e-16*a^2*b^2*c*e-8*a*b^3*c*e-10*b^4*c*e-22*a^3*c^2*e+50*a^2*b*c^2*e-29*a*b^2*c^2*e-19*b^3*c^2*e+39*a^2*c^3*e-4*a*b*c^3*e-36*b^2*c^3*e-24*a*c^4*e-2*b*c^4*e-12*c^5*e-22*a^4*d*e-22*a^3*b*d*e-a^2*b^2*d*e-42*a*b^3*d*e-10*b^4*d*e-7*a^3*c*d*e-6*a^2*b*c*d*e+5*a*b^2*c*d*e+36*b^3*c*d*e-5*a^2*c^2*d*e-21*a*b*c^2*d*e-14*b^2*c^2*d*e-21*a*c^3*d*e+18*b*c^3*d*e+49*c^4*d*e-32*a^3*d^2*e-5*a^2*b*d^2*e-45*a*b^2*d^2*e+6*b^3*d^2*e-40*a*b*c*d^2*e-17*b^2*c*d^2*e-47*a*c^2*d^2*e+12*b*c^2*d^2*e-18*c^3*d^2*e-a^2*d^3*e+6*a*b*d^3*e+2*b^2*d^3*e-29*a*c*d^3*e+15*b*c*d^3*e+21*c^2*d^3*e-36*a*d^4*e-7*b*d^4*e+c*d^4*e-23*d^5*e-24*a^4*e^2+47*a^3*b*e^2+19*a^2*b^2*e^2-44*a*b^3*e^2-13*b^4*e^2+49*a^3*c*e^2+39*a^2*b*c*e^2+44*a*b^2*c*e^2+41*b^3*c*e^2-29*a^2*c^2*e^2+24*a*b*c^2*e^2+34*a*c^3*e^2+14*b*c^3*e^2+7*c^4*e^2+44*a^3*d*e^2+22*a^2*b*d*e^2+41*a*b^2*d*e^2+21*a^2*c*d*e^2+12*a*b*c*d*e^2-33*b^2*c*d*e^2-40*a*c^2*d*e^2+16*b*c^2*d*e^2-36*c^3*d*e^2+13*a^2*d^2*e^2-22*a*b*d^2*e^2+28*b^2*d^2*e^2+29*a*c*d^2*e^2+50*b*c*d^2*e^2+48*c^2*d^2*e^2+40*a*d^3*e^2+2*c*d^3*e^2-5*d^4*e^2-37*a^3*e^3+49*a^2*b*e^3-10*a*b^2*e^3-41*b^3*e^3+11*a^2*c*e^3-37*a*b*c*e^3+26*b^2*c*e^3-39*a*c^2*e^3-46*b*c^2*e^3-3*c^3*e^3+47*a^2*d*e^3+5*a*b*d*e^3-45*b^2*d*e^3+28*a*c*d*e^3+22*b*c*d*e^3+29*c^2*d*e^3+11*a*d^2*e^3+21*b*d^2*e^3+14*c*d^2*e^3+14*d^3*e^3+32*a^2*e^4-27*a*b*e^4-47*b^2*e^4-6*b*c*e^4-38*c^2*e^4-38*a*d*e^4-17*b*d*e^4+20*c*d*e^4-d^2*e^4-4*a*e^5-11*b*e^5-41*c*e^5+25*d*e^5-e^6, b^6-11*a^4*d^2+23*a^3*b*d^2+41*a^2*b^2*d^2+7*a*b^3*d^2+10*b^4*d^2-31*a^3*c*d^2+10*a^2*b*c*d^2+7*a*b^2*c*d^2+36*b^3*c*d^2-10*a^2*c^2*d^2+9*a*b*c^2*d^2-41*b^2*c^2*d^2-26*a*c^3*d^2+26*b*c^3*d^2+12*c^4*d^2+36*a^3*d^3-35*a^2*b*d^3+12*a*b^2*d^3-8*b^3*d^3+23*a^2*c*d^3+16*a*b*c*d^3-24*b^2*c*d^3+17*a*c^2*d^3-29*b*c^2*d^3-48*c^3*d^3+33*a^2*d^4+30*a*b*d^4-41*b^2*d^4-23*a*c*d^4+8*b*c*d^4-10*c^2*d^4+22*a*d^5+5*b*d^5-32*c*d^5+19*d^6+19*a^5*e+21*a^4*b*e-29*a^3*b^2*e+10*a^2*b^3*e-6*a*b^4*e-10*b^5*e-35*a^4*c*e-47*a^3*b*c*e-16*a^2*b^2*c*e-35*a*b^3*c*e+34*b^4*c*e-28*a^3*c^2*e-6*a^2*b*c^2*e-44*a*b^2*c^2*e-47*b^3*c^2*e-18*a^2*c^3*e+48*a*b*c^3*e-b^2*c^3*e-17*a*c^4*e-48*b*c^4*e-25*c^5*e-29*a^4*d*e-18*a^3*b*d*e-28*a^2*b^2*d*e-43*a*b^3*d*e-48*b^4*d*e+45*a^3*c*d*e+18*a^2*b*c*d*e+19*a*b^2*c*d*e-27*b^3*c*d*e-13*a^2*c^2*d*e+50*a*b*c^2*d*e+33*b^2*c^2*d*e+14*a*c^3*d*e+40*b*c^3*d*e+41*c^4*d*e-34*a^3*d^2*e-41*a^2*b*d^2*e+2*a*b^2*d^2*e+37*b^3*d^2*e-a^2*c*d^2*e+8*a*b*c*d^2*e-22*b^2*c*d^2*e-25*a*c^2*d^2*e+41*b*c^2*d^2*e+35*c^3*d^2*e-14*a^2*d^3*e+32*a*b*d^3*e+20*b^2*d^3*e+3*a*c*d^3*e+12*b*c*d^3*e-6*c^2*d^3*e+44*a*d^4*e+36*b*d^4*e+32*c*d^4*e-6*d^5*e+17*a^4*e^2-39*a^3*b*e^2+22*a^2*b^2*e^2+9*a*b^3*e^2+7*b^4*e^2-9*a^3*c*e^2-49*a^2*b*c*e^2+36*a*b^2*c*e^2+16*b^3*c*e^2-10*a^2*c^2*e^2+20*a*b*c^2*e^2+b^2*c^2*e^2-29*a*c^3*e^2-4*b*c^3*e^2-34*c^4*e^2-47*a^3*d*e^2+38*a^2*b*d*e^2+10*a*b^2*d*e^2+21*b^3*d*e^2-42*a^2*c*d*e^2-28*a*b*c*d*e^2-6*b^2*c*d*e^2+22*a*c^2*d*e^2+7*b*c^2*d*e^2-12*c^3*d*e^2-6*a^2*d^2*e^2+2*a*b*d^2*e^2-4*b^2*d^2*e^2+7*a*c*d^2*e^2-39*b*c*d^2*e^2-c^2*d^2*e^2+45*a*d^3*e^2+40*b*d^3*e^2+46*c*d^3*e^2+44*d^4*e^2-30*a^3*e^3+3*a^2*b*e^3+27*a*b^2*e^3+42*b^3*e^3-18*a^2*c*e^3+11*a*b*c*e^3+18*b^2*c*e^3-31*a*c^2*e^3-37*b*c^2*e^3+5*c^3*e^3-46*a^2*d*e^3+32*a*b*d*e^3+34*b^2*d*e^3-50*a*c*d*e^3+8*b*c*d*e^3+47*c^2*d*e^3-35*a*d^2*e^3+38*b*d^2*e^3-38*c*d^2*e^3-47*d^3*e^3+35*a^2*e^4+25*a*b*e^4+31*b^2*e^4+8*a*c*e^4+9*b*c*e^4+40*c^2*e^4-3*a*d*e^4-29*b*d*e^4+20*c*d*e^4+16*d^2*e^4+25*a*e^5+b*e^5+21*c*e^5+13*d*e^5-e^6, a*b^5+6*a^4*d^2-30*a^3*b*d^2+48*a^2*b^2*d^2+22*a*b^3*d^2+49*b^4*d^2-4*a^3*c*d^2+45*a^2*b*c*d^2-28*a*b^2*c*d^2-12*b^3*c*d^2+12*a^2*c^2*d^2+47*a*b*c^2*d^2-14*b^2*c^2*d^2+35*a*c^3*d^2-b*c^3*d^2-39*c^4*d^2-40*a^3*d^3+7*a^2*b*d^3+16*a*b^2*d^3+45*b^3*d^3-a^2*c*d^3+20*a*b*c*d^3-9*b^2*c*d^3-31*a*c^2*d^3-44*b*c^2*d^3-13*c^3*d^3+36*a^2*d^4+8*a*b*d^4+25*b^2*d^4-4*a*c*d^4-10*b*c*d^4-40*c^2*d^4+39*a*d^5-4*b*d^5-24*c*d^5-11*d^6+33*a^5*e+40*a^4*b*e+21*a^3*b^2*e-7*a^2*b^3*e-22*a*b^4*e-48*b^5*e-2*a^4*c*e-32*a^3*b*c*e+4*a^2*b^2*c*e-4*a*b^3*c*e+38*b^4*c*e+50*a^3*c^2*e-15*a^2*b*c^2*e-14*a*b^2*c^2*e+43*b^3*c^2*e+44*a^2*c^3*e-11*a*b*c^3*e-20*b^2*c^3*e-14*a*c^4*e+30*b*c^4*e-44*c^5*e-27*a^4*d*e+2*a^3*b*d*e-31*a^2*b^2*d*e-8*a*b^3*d*e-47*a^3*c*d*e-39*a^2*b*c*d*e-46*a*b^2*c*d*e+6*b^3*c*d*e+32*a^2*c^2*d*e+43*a*b*c^2*d*e-30*b^2*c^2*d*e-31*a*c^3*d*e-48*b*c^3*d*e+31*c^4*d*e+49*a^3*d^2*e-2*a^2*b*d^2*e-7*a*b^2*d^2*e-38*b^3*d^2*e+6*a^2*c*d^2*e+7*a*b*c*d^2*e+5*b^2*c*d^2*e+29*a*c^2*d^2*e-39*b*c^2*d^2*e-15*c^3*d^2*e+9*a^2*d^3*e-28*a*b*d^3*e+19*b^2*d^3*e-11*a*c*d^3*e-5*b*c*d^3*e-46*c^2*d^3*e-34*a*d^4*e-27*b*d^4*e-27*c*d^4*e+11*d^5*e-36*a^4*e^2-28*a^3*b*e^2+7*a^2*b^2*e^2+20*a*b^3*e^2-34*b^4*e^2+43*a^3*c*e^2-44*a^2*b*c*e^2+30*a*b^2*c*e^2-b^3*c*e^2-15*a^2*c^2*e^2+47*a*b*c^2*e^2-5*b^2*c^2*e^2-34*a*c^3*e^2-42*b*c^3*e^2-44*c^4*e^2-7*a^3*d*e^2+32*a^2*b*d*e^2-18*a*b^2*d*e^2-45*b^3*d*e^2+50*a^2*c*d*e^2+27*a*b*c*d*e^2-43*b^2*c*d*e^2-49*a*c^2*d*e^2-12*b*c^2*d*e^2+30*c^3*d*e^2-38*a^2*d^2*e^2+16*a*b*d^2*e^2-32*b^2*d^2*e^2-45*a*c*d^2*e^2+41*b*c*d^2*e^2+8*c^2*d^2*e^2+42*a*d^3*e^2+43*b*d^3*e^2+18*c*d^3*e^2-37*d^4*e^2-13*a^3*e^3+33*a^2*b*e^3-12*a*b^2*e^3-31*b^3*e^3-24*a^2*c*e^3+5*a*b*c*e^3-29*b^2*c*e^3+5*a*c^2*e^3+10*b*c^2*e^3+38*c^3*e^3+31*a^2*d*e^3+49*a*b*d*e^3-39*b^2*d*e^3+49*a*c*d*e^3+11*b*c*d*e^3+17*c^2*d*e^3-a*d^2*e^3+45*b*d^2*e^3-16*c*d^2*e^3+28*d^3*e^3+8*a^2*e^4+19*a*b*e^4+5*b^2*e^4+36*a*c*e^4-19*b*c*e^4-18*c^2*e^4-29*a*d*e^4+33*b*d*e^4-15*c*d*e^4+46*d^2*e^4+43*a*e^5+50*b*e^5+35*c*e^5+38*d*e^5+39*e^6, a^2*b^4-27*a^4*d^2-11*a^3*b*d^2+23*a^2*b^2*d^2+42*a*b^3*d^2+33*b^4*d^2-45*a^2*b*c*d^2+42*a*b^2*c*d^2+30*b^3*c*d^2-a^2*c^2*d^2+41*a*b*c^2*d^2+32*b^2*c^2*d^2-4*a*c^3*d^2-4*b*c^3*d^2+50*c^4*d^2+14*a^3*d^3-17*a^2*b*d^3+20*a*b^2*d^3-31*b^3*d^3+44*a^2*c*d^3+14*a*b*c*d^3+43*b^2*c*d^3+48*a*c^2*d^3-10*b*c^2*d^3-3*c^3*d^3-33*a^2*d^4+9*a*b*d^4+28*b^2*d^4-3*a*c*d^4+15*b*c*d^4+46*c^2*d^4-35*a*d^5-42*b*d^5+44*c*d^5-4*d^6+28*a^5*e+46*a^4*b*e+16*a^3*b^2*e+31*a^2*b^3*e-20*a*b^4*e-15*b^5*e-50*a^4*c*e-8*a^3*b*c*e+4*a^2*b^2*c*e+38*a*b^3*c*e+27*b^4*c*e-29*a^3*c^2*e+27*a^2*b*c^2*e-33*a*b^2*c^2*e-22*b^3*c^2*e-3*a^2*c^3*e-40*a*b*c^3*e+10*b^2*c^3*e-20*a*c^4*e-38*b*c^4*e+36*c^5*e-26*a^4*d*e+41*a^3*b*d*e-15*a^2*b^2*d*e+50*a*b^3*d*e+41*b^4*d*e-18*a^3*c*d*e+18*a^2*b*c*d*e-32*a*b^2*c*d*e+41*b^3*c*d*e-5*a^2*c^2*d*e-a*b*c^2*d*e-10*b^2*c^2*d*e-12*a*c^3*d*e-46*b*c^3*d*e+34*c^4*d*e-42*a^3*d^2*e+2*a^2*b*d^2*e+37*a*b^2*d^2*e-b^3*d^2*e-29*a^2*c*d^2*e+46*a*b*c*d^2*e-49*b^2*c*d^2*e+24*a*c^2*d^2*e-47*b*c^2*d^2*e-34*c^3*d^2*e+46*a^2*d^3*e-5*a*b*d^3*e-27*b^2*d^3*e-29*a*c*d^3*e+25*b*c*d^3*e-30*c^2*d^3*e-2*a*d^4*e-50*b*d^4*e-46*c*d^4*e+2*d^5*e+11*a^4*e^2+48*a^3*b*e^2+24*a^2*b^2*e^2+41*a*b^3*e^2-17*b^4*e^2-10*a^3*c*e^2+8*a^2*b*c*e^2+28*b^3*c*e^2-21*a^2*c^2*e^2+23*a*b*c^2*e^2+8*b^2*c^2*e^2+41*a*c^3*e^2+12*b*c^3*e^2+25*c^4*e^2+25*a^3*d*e^2-49*a^2*b*d*e^2+24*a*b^2*d*e^2-7*b^3*d*e^2-20*a^2*c*d*e^2-48*a*b*c*d*e^2+46*b^2*c*d*e^2-18*a*c^2*d*e^2+13*b*c^2*d*e^2-31*c^3*d*e^2-40*a^2*d^2*e^2+2*a*b*d^2*e^2-48*b^2*d^2*e^2-38*a*c*d^2*e^2+20*b*c*d^2*e^2+47*c^2*d^2*e^2-3*a*d^3*e^2+27*b*d^3*e^2+44*c*d^3*e^2+19*d^4*e^2+38*a^3*e^3+22*a^2*b*e^3+37*a*b^2*e^3+20*b^3*e^3-6*a^2*c*e^3-33*a*b*c*e^3+45*b^2*c*e^3+24*a*c^2*e^3+33*b*c^2*e^3+c^3*e^3+50*a^2*d*e^3-44*a*b*d*e^3-50*b^2*d*e^3-11*a*c*d*e^3-11*b*c*d*e^3-30*c^2*d*e^3-a*d^2*e^3-14*b*d^2*e^3-11*c*d^2*e^3-42*d^3*e^3+3*a^2*e^4-6*a*b*e^4+31*b^2*e^4-47*a*c*e^4+23*b*c*e^4-44*c^2*e^4-28*a*d*e^4-50*b*d*e^4+41*c*d*e^4-19*d^2*e^4+10*a*e^5+13*b*e^5+47*c*e^5+31*d*e^5-49*e^6, a^3*b^3-15*a^4*d^2-17*a^3*b*d^2-a^2*b^2*d^2+18*a*b^3*d^2-30*b^4*d^2-37*a^3*c*d^2+21*a^2*b*c*d^2-a*b^2*c*d^2+16*b^3*c*d^2-41*a^2*c^2*d^2+39*a*b*c^2*d^2-16*b^2*c^2*d^2-22*a*c^3*d^2+19*b*c^3*d^2+46*c^4*d^2-14*a^3*d^3+2*a^2*b*d^3+45*a*b^2*d^3+12*b^3*d^3-28*a^2*c*d^3-19*a*b*c*d^3-20*b^2*c*d^3-6*a*c^2*d^3+17*b*c^2*d^3-20*c^3*d^3+34*a^2*d^4+15*a*b*d^4-8*b^2*d^4+31*a*c*d^4-5*b*c*d^4+41*c^2*d^4-32*a*d^5-38*b*d^5+35*c*d^5-4*d^6-26*a^5*e-20*a^4*b*e-12*a^3*b^2*e+22*a^2*b^3*e-48*a*b^4*e+39*b^5*e-46*a^4*c*e-50*a^3*b*c*e+11*a^2*b^2*c*e-2*a*b^3*c*e+23*b^4*c*e+44*a^3*c^2*e+4*a^2*b*c^2*e+17*a*b^2*c^2*e-39*b^3*c^2*e-a^2*c^3*e-20*a*b*c^3*e-16*b^2*c^3*e+7*a*c^4*e+31*b*c^4*e+18*c^5*e-44*a^4*d*e+7*a^3*b*d*e+26*a^2*b^2*d*e-19*a*b^3*d*e-35*b^4*d*e+47*a^3*c*d*e+17*a^2*b*c*d*e-27*a*b^2*c*d*e-6*b^3*c*d*e-16*a^2*c^2*d*e-10*a*b*c^2*d*e+21*b^2*c^2*d*e-27*a*c^3*d*e+4*b*c^3*d*e-32*c^4*d*e-22*a^3*d^2*e+50*a^2*b*d^2*e-a*b^2*d^2*e+41*b^3*d^2*e-46*a^2*c*d^2*e-18*a*b*c*d^2*e+8*b^2*c*d^2*e-16*a*c^2*d^2*e-38*b*c^2*d^2*e-c^3*d^2*e+18*a^2*d^3*e-25*a*b*d^3*e-47*b^2*d^3*e-23*a*c*d^3*e+8*b*c*d^3*e+20*c^2*d^3*e-41*a*d^4*e-18*b*d^4*e-18*c*d^4*e+33*d^5*e+17*a^4*e^2-10*a^3*b*e^2+28*a^2*b^2*e^2-12*a*b^3*e^2-19*b^4*e^2-20*a^3*c*e^2+45*a^2*b*c*e^2+39*a*b^2*c*e^2+37*b^3*c*e^2-6*a^2*c^2*e^2+19*a*b*c^2*e^2+23*b^2*c^2*e^2+34*a*c^3*e^2+24*b*c^3*e^2+20*c^4*e^2+14*a^3*d*e^2-8*a^2*b*d*e^2+15*a*b^2*d*e^2+19*b^3*d*e^2+14*a^2*c*d*e^2-42*a*b*c*d*e^2-27*b^2*c*d*e^2+11*a*c^2*d*e^2+24*b*c^2*d*e^2-10*c^3*d*e^2+12*a^2*d^2*e^2+18*a*b*d^2*e^2+21*b^2*d^2*e^2+35*a*c*d^2*e^2-15*b*c*d^2*e^2-32*c^2*d^2*e^2+8*a*d^3*e^2+40*b*d^3*e^2+50*c*d^3*e^2-41*d^4*e^2+42*a^3*e^3-38*a^2*b*e^3-27*a*b^2*e^3+32*b^3*e^3+41*a^2*c*e^3+3*a*b*c*e^3+28*b^2*c*e^3+21*a*c^2*e^3-8*b*c^2*e^3+22*c^3*e^3+8*a^2*d*e^3+49*a*b*d*e^3-24*b^2*d*e^3-8*a*c*d*e^3+30*b*c*d*e^3+35*c^2*d*e^3+49*a*d^2*e^3+39*b*d^2*e^3+23*c*d^2*e^3-47*d^3*e^3+43*a^2*e^4-15*a*b*e^4+20*b^2*e^4-35*b*c*e^4+28*c^2*e^4+35*b*d*e^4+12*c*d*e^4+40*d^2*e^4+32*a*e^5-32*b*e^5+25*c*e^5+9*d*e^5-26*e^6, a^4*b^2-31*a^4*d^2+30*a^3*b*d^2-42*a^2*b^2*d^2-32*a*b^3*d^2-38*b^4*d^2-49*a^3*c*d^2-4*a^2*b*c*d^2-45*a*b^2*c*d^2+8*b^3*c*d^2+44*a^2*c^2*d^2+21*a*b*c^2*d^2-13*b^2*c^2*d^2-16*a*c^3*d^2+31*b*c^3*d^2-42*c^4*d^2+49*a^3*d^3+44*a^2*b*d^3+a*b^2*d^3+47*b^3*d^3-31*a^2*c*d^3+42*a*b*c*d^3-34*b^2*c*d^3-44*a*c^2*d^3-3*b*c^2*d^3-14*c^3*d^3+24*a^2*d^4+12*a*b*d^4+14*b^2*d^4-32*a*c*d^4+16*b*c*d^4+40*c^2*d^4+8*a*d^5+5*b*d^5+35*c*d^5+2*d^6+7*a^5*e+a^4*b*e-24*a^3*b^2*e-25*a^2*b^3*e-8*a*b^4*e-46*b^5*e+12*a^4*c*e-49*a^3*b*c*e+47*a^2*b^2*c*e-22*a*b^3*c*e-22*b^4*c*e+31*a^3*c^2*e-48*a^2*b*c^2*e-46*a*b^2*c^2*e+28*b^3*c^2*e-5*a^2*c^3*e+42*a*b*c^3*e-9*b^2*c^3*e+13*a*c^4*e+23*b*c^4*e-29*c^5*e+9*a^4*d*e+9*a^3*b*d*e+3*a^2*b^2*d*e+47*a*b^3*d*e+31*b^4*d*e-25*a^3*c*d*e-37*a*b^2*c*d*e-23*b^3*c*d*e+18*a^2*c^2*d*e+8*a*b*c^2*d*e-15*b^2*c^2*d*e-40*a*c^3*d*e+26*b*c^3*d*e-29*c^4*d*e+20*a^3*d^2*e-25*a^2*b*d^2*e+41*a*b^2*d^2*e+10*b^3*d^2*e-12*a^2*c*d^2*e+38*a*b*c*d^2*e-30*b^2*c*d^2*e-49*b*c^2*d^2*e-34*c^3*d^2*e+14*a^2*d^3*e+45*a*b*d^3*e-29*b^2*d^3*e-23*a*c*d^3*e+33*b*c*d^3*e-23*c^2*d^3*e-36*a*d^4*e+29*b*d^4*e+22*c*d^4*e+45*d^5*e-46*a^4*e^2-37*a^3*b*e^2-36*a^2*b^2*e^2-23*a*b^3*e^2-4*b^4*e^2+31*a^3*c*e^2+45*a^2*b*c*e^2-34*a*b^2*c*e^2+6*b^3*c*e^2-38*a^2*c^2*e^2-26*a*b*c^2*e^2-5*b^2*c^2*e^2-24*a*c^3*e^2-28*b*c^3*e^2+20*c^4*e^2+25*a^3*d*e^2+14*a^2*b*d*e^2+a*b^2*d*e^2+18*b^3*d*e^2+12*a^2*c*d*e^2+32*a*b*c*d*e^2+17*b^2*c*d*e^2+50*a*c^2*d*e^2-12*b*c^2*d*e^2-46*c^3*d*e^2+4*a^2*d^2*e^2-29*a*b*d^2*e^2-16*b^2*d^2*e^2+38*a*c*d^2*e^2+3*b*c*d^2*e^2-19*c^2*d^2*e^2+50*a*d^3*e^2+23*b*d^3*e^2+5*c*d^3*e^2+47*d^4*e^2-38*a^3*e^3-31*a^2*b*e^3+14*a*b^2*e^3-43*b^3*e^3+22*a^2*c*e^3+26*a*b*c*e^3-28*b^2*c*e^3-49*a*c^2*e^3+15*c^3*e^3-40*a^2*d*e^3+5*a*b*d*e^3-20*b^2*d*e^3-40*a*c*d*e^3+35*b*c*d*e^3+17*c^2*d*e^3-8*a*d^2*e^3-6*b*d^2*e^3+3*c*d^2*e^3-7*d^3*e^3+45*a^2*e^4-49*a*b*e^4+45*b^2*e^4-25*a*c*e^4+b*c*e^4-33*c^2*e^4-44*a*d*e^4+30*b*d*e^4-26*c*d*e^4+42*d^2*e^4+14*b*e^5-3*c*e^5-47*d*e^5+22*e^6, a^5*b-48*a^4*d^2-33*a^3*b*d^2-34*a^2*b^2*d^2-14*a*b^3*d^2-29*b^4*d^2-7*a^3*c*d^2-13*a^2*b*c*d^2+15*a*b^2*c*d^2+27*b^3*c*d^2+49*a^2*c^2*d^2-a*b*c^2*d^2+46*b^2*c^2*d^2+37*a*c^3*d^2+20*b*c^3*d^2-27*c^4*d^2+33*a^3*d^3+30*a^2*b*d^3+32*a*b^2*d^3+b^3*d^3-47*a^2*c*d^3-2*a*b*c*d^3-36*b^2*c*d^3-7*a*c^2*d^3-23*b*c^2*d^3-41*c^3*d^3-43*a^2*d^4-4*a*b*d^4+14*b^2*d^4+38*a*c*d^4+41*b*c*d^4+27*c^2*d^4-33*a*d^5-50*b*d^5+8*c*d^5+42*d^6-21*a^5*e+46*a^4*b*e+6*a^3*b^2*e+22*a^2*b^3*e+2*a*b^4*e-15*b^5*e+50*a^4*c*e-40*a^2*b^2*c*e+49*a*b^3*c*e+5*b^4*c*e+a^3*c^2*e+47*a^2*b*c^2*e-36*a*b^2*c^2*e+25*b^3*c^2*e-36*a^2*c^3*e+46*a*b*c^3*e+24*b^2*c^3*e-9*a*c^4*e+39*b*c^4*e-40*c^5*e+29*a^4*d*e-49*a^3*b*d*e+16*a^2*b^2*d*e+7*a*b^3*d*e-30*b^4*d*e+42*a^3*c*d*e+22*a^2*b*c*d*e-49*a*b^2*c*d*e+19*b^3*c*d*e-23*a^2*c^2*d*e+7*a*b*c^2*d*e+2*b^2*c^2*d*e-2*a*c^3*d*e-2*b*c^3*d*e+5*c^4*d*e+35*a^3*d^2*e-47*a^2*b*d^2*e-28*a*b^2*d^2*e+5*b^3*d^2*e+45*a^2*c*d^2*e+7*a*b*c*d^2*e+3*b^2*c*d^2*e+33*a*c^2*d^2*e-37*b*c^2*d^2*e+26*c^3*d^2*e-18*a*b*d^3*e-42*b^2*d^3*e-22*a*c*d^3*e-46*b*c*d^3*e-25*c^2*d^3*e+6*a*d^4*e-50*b*d^4*e+22*c*d^4*e-4*d^5*e-42*a^4*e^2+43*a^3*b*e^2+39*a^2*b^2*e^2+12*a*b^3*e^2-20*b^4*e^2+2*a^3*c*e^2+27*a^2*b*c*e^2-21*a*b^2*c*e^2+36*b^3*c*e^2+47*a^2*c^2*e^2-41*a*b*c^2*e^2-23*b^2*c^2*e^2+34*a*c^3*e^2-29*b*c^3*e^2-46*c^4*e^2+15*a^3*d*e^2+4*a^2*b*d*e^2-13*a*b^2*d*e^2+43*b^3*d*e^2-7*a^2*c*d*e^2+4*a*b*c*d*e^2-37*a*c^2*d*e^2-34*b*c^2*d*e^2+20*c^3*d*e^2-5*a^2*d^2*e^2-42*a*b*d^2*e^2+14*b^2*d^2*e^2+9*a*c*d^2*e^2-19*b*c*d^2*e^2+15*c^2*d^2*e^2-35*a*d^3*e^2+24*b*d^3*e^2-35*c*d^3*e^2-14*d^4*e^2-27*a^3*e^3-39*a^2*b*e^3-44*a*b^2*e^3-6*b^3*e^3-30*a^2*c*e^3+47*a*b*c*e^3-26*b^2*c*e^3+9*a*c^2*e^3+16*b*c^2*e^3+37*c^3*e^3-49*a^2*d*e^3+19*a*b*d*e^3+44*b^2*d*e^3-9*a*c*d*e^3-41*b*c*d*e^3+29*c^2*d*e^3-43*a*d^2*e^3+33*b*d^2*e^3-2*c*d^2*e^3-15*d^3*e^3-4*a^2*e^4-46*a*b*e^4+15*b^2*e^4+21*a*c*e^4+13*b*c*e^4+38*c^2*e^4-20*a*d*e^4+16*b*d*e^4-9*c*d*e^4-19*d^2*e^4+14*a*e^5-33*b*e^5+34*c*e^5+16*d*e^5-24*e^6, a^6-2*a^4*d^2+3*a^3*b*d^2+18*a^2*b^2*d^2-46*a*b^3*d^2-31*b^4*d^2+48*a^3*c*d^2+7*a^2*b*c*d^2+26*a*b^2*c*d^2+17*b^3*c*d^2-30*a^2*c^2*d^2-2*a*b*c^2*d^2+5*b^2*c^2*d^2-43*a*c^3*d^2-33*b*c^3*d^2-28*c^4*d^2-26*a^3*d^3-5*a^2*b*d^3+48*a*b^2*d^3+2*b^3*d^3-15*a^2*c*d^3-18*a*b*c*d^3-16*b^2*c*d^3-12*a*c^2*d^3+21*b*c^2*d^3-31*c^3*d^3+34*a^2*d^4-40*a*b*d^4+41*b^2*d^4+21*a*c*d^4+26*b*c*d^4+50*c^2*d^4-20*a*d^5+8*b*d^5+30*c*d^5+48*d^6-37*a^5*e+28*a^4*b*e+8*a^3*b^2*e+30*a^2*b^3*e-a*b^4*e-49*b^5*e-8*a^4*c*e+26*a^3*b*c*e+20*a^2*b^2*c*e+19*a*b^3*c*e-23*b^4*c*e+11*a^3*c^2*e+37*a^2*b*c^2*e+40*a*b^2*c^2*e-33*b^3*c^2*e-26*a^2*c^3*e+12*a*b*c^3*e+29*b^2*c^3*e-a*c^4*e-15*b*c^4*e-24*c^5*e-41*a^4*d*e-4*a^3*b*d*e+42*a^2*b^2*d*e+9*a*b^3*d*e-49*b^4*d*e-11*a^3*c*d*e+21*a^2*b*c*d*e+22*a*b^2*c*d*e+22*b^3*c*d*e-9*a^2*c^2*d*e+27*a*b*c^2*d*e-36*b^2*c^2*d*e-10*a*c^3*d*e-39*b*c^3*d*e-3*c^4*d*e+16*a^3*d^2*e+9*a^2*b*d^2*e+7*a*b^2*d^2*e+33*b^3*d^2*e+42*a^2*c*d^2*e-38*a*b*c*d^2*e+33*b^2*c*d^2*e+41*a*c^2*d^2*e-36*b*c^2*d^2*e-21*c^3*d^2*e+34*a^2*d^3*e-43*a*b*d^3*e+32*b^2*d^3*e-9*a*c*d^3*e-34*b*c*d^3*e-4*c^2*d^3*e-10*a*d^4*e-29*b*d^4*e+4*c*d^4*e+36*d^5*e+40*a^4*e^2-32*a^3*b*e^2+13*a^2*b^2*e^2+22*a*b^3*e^2-15*b^4*e^2+31*a^3*c*e^2+7*a^2*b*c*e^2-15*a*b^2*c*e^2+43*b^3*c*e^2-45*a^2*c^2*e^2-42*a*b*c^2*e^2+41*b^2*c^2*e^2-46*a*c^3*e^2-6*b*c^3*e^2+26*c^4*e^2+45*a^3*d*e^2+11*a^2*b*d*e^2+10*a*b^2*d*e^2+5*b^3*d*e^2+3*a^2*c*d*e^2-49*a*b*c*d*e^2-10*b^2*c*d*e^2-50*a*c^2*d*e^2+38*b*c^2*d*e^2+21*c^3*d*e^2+37*a^2*d^2*e^2+a*b*d^2*e^2+38*b^2*d^2*e^2+25*a*c*d^2*e^2-7*b*c*d^2*e^2-13*c^2*d^2*e^2+32*a*d^3*e^2+37*b*d^3*e^2-27*c*d^3*e^2-7*d^4*e^2+44*a^3*e^3+48*a^2*b*e^3+21*a*b^2*e^3+11*b^3*e^3+9*a^2*c*e^3+49*a*b*c*e^3-39*b^2*c*e^3+24*a*c^2*e^3+35*b*c^2*e^3-11*c^3*e^3+17*a^2*d*e^3+36*a*b*d*e^3-19*b^2*d*e^3-47*a*c*d*e^3-47*b*c*d*e^3-12*c^2*d*e^3+34*a*d^2*e^3+35*b*d^2*e^3+18*d^3*e^3-31*a^2*e^4+45*a*b*e^4+27*b^2*e^4+43*a*c*e^4-35*b*c*e^4-29*c^2*e^4-21*a*d*e^4+49*b*d*e^4-23*c*d*e^4+34*d^2*e^4-2*a*e^5+47*b*e^5+31*c*e^5-46*d*e^5-13*e^6, e^7, d*e^6, c*e^6, b*e^6, a*e^6, d^2*e^5, c*d*e^5, b*d*e^5, a*d*e^5, c^2*e^5, b*c*e^5, a*c*e^5, b^2*e^5, a*b*e^5, a^2*e^5, d^3*e^4, c*d^2*e^4, b*d^2*e^4, a*d^2*e^4, c^2*d*e^4, b*c*d*e^4, a*c*d*e^4, b^2*d*e^4, a*b*d*e^4, a^2*d*e^4, c^3*e^4, b*c^2*e^4, a*c^2*e^4, b^2*c*e^4, a*b*c*e^4, a^2*c*e^4, b^3*e^4, a*b^2*e^4, a^2*b*e^4, a^3*e^4, d^4*e^3, c*d^3*e^3, b*d^3*e^3, a*d^3*e^3, c^2*d^2*e^3, b*c*d^2*e^3, a*c*d^2*e^3, b^2*d^2*e^3, a*b*d^2*e^3, a^2*d^2*e^3, c^3*d*e^3, b*c^2*d*e^3, a*c^2*d*e^3, b^2*c*d*e^3, a*b*c*d*e^3, a^2*c*d*e^3, b^3*d*e^3, a*b^2*d*e^3, a^2*b*d*e^3, a^3*d*e^3, c^4*e^3, b*c^3*e^3, a*c^3*e^3, b^2*c^2*e^3, a*b*c^2*e^3, a^2*c^2*e^3, b^3*c*e^3, a*b^2*c*e^3, a^2*b*c*e^3, a^3*c*e^3, b^4*e^3, a*b^3*e^3, a^2*b^2*e^3, a^3*b*e^3, a^4*e^3, d^5*e^2, c*d^4*e^2, b*d^4*e^2, a*d^4*e^2, c^2*d^3*e^2, b*c*d^3*e^2, a*c*d^3*e^2, b^2*d^3*e^2, a*b*d^3*e^2, a^2*d^3*e^2, c^3*d^2*e^2, b*c^2*d^2*e^2, a*c^2*d^2*e^2, b^2*c*d^2*e^2, a*b*c*d^2*e^2; // M; TestSSresAttribs2tr(M, "AGR101n4d008s020%1_big"); /* options: 1 1 0 : Time: 29/32/73/92 (316 without LCM) options: 1 1 1 : Time: 32/34/43/202 lres Time: 24 nres Time: 19 sres Time: 71 */ kill M; kill AGR; ring AGR = (101), (a,b,c,d,e,f), dp; AGR; // AGR@101n5d005s016%1, new, medium difficulty? ideal M = b*d-13*c*d+7*a*e-32*b*e+31*c*e+3*d*e+46*a*f-13*b*f+22*c*f-19*d*f-33*e*f, a*d+2*c*d-42*a*e+46*b*e+7*c*e-38*d*e+31*a*f+9*b*f+27*c*f-19*d*f-24*e*f, b*c-35*c*d-34*a*e+4*b*e+33*c*e+23*d*e+4*a*f-43*b*f+43*c*f+17*d*f-13*e*f, a*c+49*c*d-28*a*e+18*b*e-23*c*e+3*d*e-5*a*f-23*b*f+2*c*f+46*d*f-40*e*f, a*b-38*c*d+a*e-49*b*e-20*c*e+32*d*e+13*a*f+25*b*f+37*c*f-27*d*f+25*e*f, f^4, e*f^3, d*f^3, c*f^3, b*f^3, a*f^3, e^2*f^2, d*e*f^2, c*e*f^2, b*e*f^2, a*e*f^2, d^2*f^2, c*d*f^2, c^2*f^2, b^2*f^2, a^2*f^2, e^3*f, d*e^2*f, c*e^2*f, b*e^2*f, a*e^2*f, d^2*e*f, d^3*f, c^3*f, b^3*f, a^3*f, e^4, d^4, c^4, b^4, a^4; TestSSresAttribs(M, "AGR@101n5d005s016%1"); kill M; } static proc testAGRhard(list #) { def DEBUG = 0; if(size(#) > 0) { DEBUG = #[1]; } system("--min-time", "0.01"); system("--ticks-per-sec", 100); attrib(SSinit, "DEBUG", 0); attrib(SSinit, "SYZCHECK", (DEBUG > 0)); attrib(SSinit, "KERCHECK", 0); attrib(SSinit, "TREEOUTPUT", 0); attrib(SSinit, "PROFILE", 0); option(prot); // AGR@101n5d006s016%1, new, hard ring AGR = (101), (a,b,c,d,e,f), dp; AGR; ideal M = b*d+47*c*d-27*a*e+37*b*e+21*c*e+31*d*e-31*a*f+23*b*f+47*c*f+42*d*f+11*e*f, a*d+7*c*d+19*a*e+28*b*e-33*c*e-28*d*e+15*a*f+28*b*f+47*c*f+3*d*f+14*e*f, b*c+29*c*d-25*a*e+12*b*e+23*c*e-50*d*e-17*a*f+30*b*f-37*c*f+35*d*f-e*f, a*c+46*c*d+12*a*e+27*b*e+39*c*e+23*d*e-45*a*f+39*b*f-35*c*f+4*d*f-10*e*f, a*b+38*c*d-18*a*e-34*b*e-30*c*e+38*d*e+22*a*f+34*b*f+39*c*f+30*d*f-19*e*f, f^5, e*f^4, d*f^4, c*f^4, b*f^4, a*f^4, e^2*f^3, d*e*f^3, c*e*f^3, b*e*f^3, a*e*f^3, d^2*f^3, c*d*f^3, c^2*f^3, b^2*f^3, a^2*f^3, e^3*f^2, d*e^2*f^2, c*e^2*f^2, b*e^2*f^2, a*e^2*f^2, d^2*e*f^2, d^3*f^2, c^3*f^2, b^3*f^2, a^3*f^2, e^4*f, e^5, d^5, c^5, b^5, a^5; TestSSresAttribs2tr(M, "AGR@101n5d006s016%1_hard"); kill M; } singular-4.0.3+ds/Singular/LIB/schubert.lib000066400000000000000000002205561266270727000204700ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////////// version="version schubert.lib 4.0.0.0 Nov_2013 "; // $Id: 3716882c59cbc1ea84c159503bd3b822962311a4 $ category="Algebraic Geometry"; info=" LIBRARY: schubert.lib Proceduces for Intersection Theory AUTHOR: Hiep Dang, email: hiep@mathematik.uni-kl.de OVERVIEW: We implement new classes (variety, sheaf, stack, graph) and methods for computing with them. An abstract variety is represented by a nonnegative integer which is its dimension and a graded ring which is its Chow ring. An abstract sheaf is represented by a variety and a polynomial which is its Chern character. In particular, we implement the concrete varieties such as projective spaces, Grassmannians, and projective bundles. An important task of this library is related to the computation of Gromov-Witten invariants. In particular, we implement new tools for the computation in equivariant intersection theory. These tools are based on the localization of moduli spaces of stable maps and Bott's formula. They are useful for the computation of Gromov-Witten invariants. In order to do this, we have to deal with moduli spaces of stable maps, which were introduced by Kontsevich, and the graphs corresponding to the fixed point components of a torus action on the moduli spaces of stable maps. As an insightful example, the numbers of rational curves on general complete intersection Calabi-Yau threefolds in projective spaces are computed up to degree 6. The results are all in agreement with predictions made from mirror symmetry computations. REFERENCES: Hiep Dang, Intersection theory with applications to the computation of Gromov-Witten invariants, Ph.D thesis, TU Kaiserslautern, 2013. Sheldon Katz and Stein A. Stromme, Schubert-A Maple package for intersection theory and enumerative geometry, 1992. Daniel R. Grayson, Michael E. Stillman, Stein A. Stromme, David Eisenbud and Charley Crissman, Schubert2-A Macaulay2 package for computation in intersection theory, 2010. Maxim Kontsevich, Enumeration of rational curves via torus actions, 1995. PROCEDURES: mod_init() create new objects in this library makeVariety(int,ideal) create a variety printVariety(variety) print procedure for a variety productVariety(variety,variety) make the product of two varieties ChowRing(variety) create the Chow ring of a variety Grassmannian(int,int) create a Grassmannian as a variety projectiveSpace(int) create a projective space as a variety projectiveBundle(sheaf) create a projective bundle as a variety integral(variety,poly) degree of a 0-cycle on a variety makeSheaf(variety,poly) create a sheaf printSheaf(sheaf) print procedure for sheaves rankSheaf(sheaf) return the rank of a sheaf totalChernClass(sheaf) compute the total Chern class of a sheaf ChernClass(sheaf,int) compute the k-th Chern class of a sheaf topChernClass(sheaf) compute the top Chern class of a sheaf totalSegreClass(sheaf) compute the total Segre class of a sheaf dualSheaf(sheaf) make the dual of a sheaf tensorSheaf(sheaf,sheaf) make the tensor of two sheaves symmetricPowerSheaf(sheaf,int) make the k-th symmetric power of a sheaf quotSheaf(sheaf,sheaf) make the quotient of two sheaves addSheaf(sheaf,sheaf) make the direct sum of two sheaves makeGraph(list,list) create a graph from a list of vertices and a list of edges printGraph(graph) print procedure for graphs moduliSpace(variety,int) create a moduli space of stable maps as an algebraic stack printStack(stack) print procedure for stacks dimStack(stack) compute the dimension of a stack fixedPoints(stack) compute the list of graphs corresponding the fixed point components of a torus action on the stack contributionBundle(stack,graph) compute the contribution bundle on a stack at a graph normalBundle(stack,graph) compute the normal bundle on a stack at a graph multipleCover(int) compute the contribution of multiple covers of a smooth rational curve as a Gromov-Witten invariant linesHypersurface(int) compute the number of lines on a general hypersurface rationalCurve(int,list) compute the Gromov-Witten invariant corresponding the number of rational curves on a general Calabi-Yau threefold sumofquotients(stack,list) prepare a command for parallel computation part(poly,int) compute a homogeneous component of a polynomial. parts(poly,int,int) compute the sum of homogeneous components of a polynomial logg(poly,int) compute Chern characters from total Chern classes. expp(poly,int) compute total Chern classes from Chern characters SchubertClass(list) compute the Schubert classes on a Grassmannian dualPartition(list) compute the dual of a partition KEYWORDS: Intersection theory; Enumerative geometry; Schubert calculus; Bott's formula; Gromov-Witten invariants. "; //////////////////////////////////////////////////////////////////////////////// LIB "general.lib"; LIB "homolog.lib"; LIB "parallel.lib"; //////////////////////////////////////////////////////////////////////////////// /////////// create new objects in this library //////////////////////////////// //////////////////////////////////////////////////////////////////////////////// proc mod_init() "USAGE: mod_init(); THEORY: This is to create new objects in this library such as variety, sheaf, stack, and graph. KEYWORDS: variety, sheaf, stack, graph EXAMPLE: example mod_init(); shows an example " { newstruct("variety","int dimension, ring baseRing, ideal relations"); newstruct("sheaf","variety currentVariety, poly ChernCharacter"); newstruct("graph","list vertices, list edges"); newstruct("stack","variety currentVariety, int degreeCurve"); system("install","variety","print",printVariety,1); system("install","variety","*",productVariety,2); system("install","sheaf","print",printSheaf,1); system("install","sheaf","*",tensorSheaf,2); system("install","sheaf","+",addSheaf,2); system("install","sheaf","-",quotSheaf,2); system("install","sheaf","^",symmetricPowerSheaf,2); system("install","graph","print",printGraph,1); system("install","stack","print",printStack,1); } example { "EXAMPLE:"; echo=2; mod_init(); } //////////////////////////////////////////////////////////////////////////////// //////// Procedures concerned with moduli spaces of stable maps //////////////// //////////////////////////////////////////////////////////////////////////////// proc printStack(stack M) "USAGE: printStack(M); M stack ASSUME: M is a moduli space of stable maps. THEORY: This is the print function used by Singular to print a stack. KEYWORDS: stack, moduli space of stable maps EXAMPLE: example printStack; shows an example " { "A moduli space of dimension", dimStack(M); } example { "EXAMPLE:"; echo=2; ring r = 0,(x),dp; variety P = projectiveSpace(4); stack M = moduliSpace(P,2); M; } proc moduliSpace(variety V, int d) "USAGE: moduliSpace(V,d); V variety, d int ASSUME: V is a projective space and d is a positive integer. THEORY: This is the function used by Singular to create a moduli space of stable maps from a genus zero curve to a projective space. KEYWORDS: stack, moduli space of stable maps, rational curves EXAMPLE: example moduliSpace; shows an example " { stack M; M.currentVariety = V; M.degreeCurve = d; return(M); } example { "EXAMPLE:"; echo=2; ring r = 0,(x),dp; variety P = projectiveSpace(4); stack M = moduliSpace(P,2); M; } proc dimStack(stack M) "USAGE: dimStack(M); M stack RETURN: int INPUT: M is a moduli space of stable maps. OUTPUT: the dimension of moduli space of stable maps. KEYWORDS: dimension, moduli space of stable maps, rational curves EXAMPLE: example dimStack; shows an example " { variety V = M.currentVariety; int n = V.dimension; int d = M.degreeCurve; return (n*d+n+d-3); } example { "EXAMPLE:"; echo=2; ring r = 0,(x),dp; variety P = projectiveSpace(4); stack M = moduliSpace(P,2); dimStack(M); } proc fixedPoints(stack M) "USAGE: fixedPoints(M); M stack RETURN: list INPUT: M is a moduli space of stable maps. OUTPUT: a list of graphs corresponding the fixed point components of a torus action on a moduli space of stable maps. KEYWORDS: fixed points, moduli space of stable maps, graph EXAMPLE: example fixedPoints; shows an example " { int i,j,k,h,m,n,p,q; list l; int d = M.degreeCurve; variety V = M.currentVariety; int r = V.dimension; for (i=0;i<=r;i++) { for (j=0;j<=r;j++) { if (i <> j) { l[size(l)+1] = list(graph1(d,i,j),2*d); } } } if (d == 2) { for (i=0;i<=r;i++) { for (j=0;j<=r;j++) { for (k=0;k<=r;k++) { if (i <> j and j <> k) { l[size(l)+1] = list(graph2(list(1,1),i,j,k),2); } } } } } if (d == 3) { for (i=0;i<=r;i++) { for (j=0;j<=r;j++) { for (k=0;k<=r;k++) { if (i <> j and j <> k) { l[size(l)+1] = list(graph2(list(2,1),i,j,k),2); for (h=0;h<=r;h++) { if (h <> k) { l[size(l)+1] = list(graph31(list(1,1,1),i,j,k,h),2); } if (h <> j) { l[size(l)+1] = list(graph32(list(1,1,1),i,j,k,h),6); } } } } } } } if (d == 4) { for (i=0;i<=r;i++) { for (j=0;j<=r;j++) { for (k=0;k<=r;k++) { if (i <> j and j <> k) { l[size(l)+1] = list(graph2(list(3,1),i,j,k),3); l[size(l)+1] = list(graph2(list(2,2),i,j,k),8); for (h=0;h<=r;h++) { if (h <> k) { l[size(l)+1] = list(graph31(list(2,1,1),i,j,k,h),2); l[size(l)+1] = list(graph31(list(1,2,1),i,j,k,h),4); } if (h <> j) { l[size(l)+1] = list(graph32(list(2,1,1),i,j,k,h),4); } for (m=0;m<=r;m++) { if (k <> h and m <> h) { l[size(l)+1] = list(graph41(list(1,1,1,1),i,j,k,h,m),2); } if (k <> h and m <> k) { l[size(l)+1] = list(graph42(list(1,1,1,1),i,j,k,h,m),2); } if (h <> j and m <> j) { l[size(l)+1] = list(graph43(list(1,1,1,1),i,j,k,h,m),24); } } } } } } } } if (d == 5) { for (i=0;i<=r;i++) { for (j=0;j<=r;j++) { for (k=0;k<=r;k++) { if (i <> j and j <> k) { l[size(l)+1] = list(graph2(list(4,1),i,j,k),4); l[size(l)+1] = list(graph2(list(3,2),i,j,k),6); for (h=0;h<=r;h++) { if (k <> h) { l[size(l)+1] = list(graph31(list(3,1,1),i,j,k,h),3); l[size(l)+1] = list(graph31(list(1,3,1),i,j,k,h),6); l[size(l)+1] = list(graph31(list(2,2,1),i,j,k,h),4); l[size(l)+1] = list(graph31(list(2,1,2),i,j,k,h),8); } if (j <> h) { l[size(l)+1] = list(graph32(list(3,1,1),i,j,k,h),6); l[size(l)+1] = list(graph32(list(2,2,1),i,j,k,h),8); } for (m=0;m<=r;m++) { if (k <> h and h <> m) { l[size(l)+1] = list(graph41(list(2,1,1,1),i,j,k,h,m),2); l[size(l)+1] = list(graph41(list(1,2,1,1),i,j,k,h,m),2); } if (k <> h and k <> m) { l[size(l)+1] = list(graph42(list(2,1,1,1),i,j,k,h,m),4); l[size(l)+1] = list(graph42(list(1,2,1,1),i,j,k,h,m),4); l[size(l)+1] = list(graph42(list(1,1,2,1),i,j,k,h,m),2); } if (j <> h and j <> m) { l[size(l)+1] = list(graph43(list(2,1,1,1),i,j,k,h,m),12); } for (n=0;n<=r;n++) { if (k <> h and h <> m and m <> n) { l[size(l)+1] = list(graph51(list(1,1,1,1,1),i,j,k,h,m,n),2); } if (k <> h and h <> m and h <> n) { l[size(l)+1] = list(graph52(list(1,1,1,1,1),i,j,k,h,m,n),2); } if (k <> h and k <> m and k <> n) { l[size(l)+1] = list(graph53(list(1,1,1,1,1),i,j,k,h,m,n),6); } if (j <> h and h <> m and h <> n) { l[size(l)+1] = list(graph54(list(1,1,1,1,1),i,j,k,h,m,n),8); } if (k <> h and k <> m and h <> n) { l[size(l)+1] = list(graph55(list(1,1,1,1,1),i,j,k,h,m,n),2); } if (j <> h and j <> m and j <> n) { l[size(l)+1] = list(graph56(list(1,1,1,1,1),i,j,k,h,m,n),120); } } } } } } } } } if (d == 6) { for (i=0;i<=r;i++) { for (j=0;j<=r;j++) { for (k=0;k<=r;k++) { if (i <> j and j <> k) { l[size(l)+1] = list(graph2(list(5,1),i,j,k),5); l[size(l)+1] = list(graph2(list(4,2),i,j,k),8); l[size(l)+1] = list(graph2(list(3,3),i,j,k),18); for (h=0;h<=r;h++) { if (k <> h) { l[size(l)+1] = list(graph31(list(4,1,1),i,j,k,h),4); l[size(l)+1] = list(graph31(list(1,4,1),i,j,k,h),8); l[size(l)+1] = list(graph31(list(3,2,1),i,j,k,h),6); l[size(l)+1] = list(graph31(list(3,1,2),i,j,k,h),6); l[size(l)+1] = list(graph31(list(1,3,2),i,j,k,h),6); l[size(l)+1] = list(graph31(list(2,2,2),i,j,k,h),16); } if (j <> h) { l[size(l)+1] = list(graph32(list(4,1,1),i,j,k,h),8); l[size(l)+1] = list(graph32(list(3,2,1),i,j,k,h),6); l[size(l)+1] = list(graph32(list(2,2,2),i,j,k,h),48); } for (m=0;m<=r;m++) { if (k <> h and h <> m) { l[size(l)+1] = list(graph41(list(3,1,1,1),i,j,k,h,m),3); l[size(l)+1] = list(graph41(list(1,3,1,1),i,j,k,h,m),3); l[size(l)+1] = list(graph41(list(2,2,1,1),i,j,k,h,m),4); l[size(l)+1] = list(graph41(list(2,1,2,1),i,j,k,h,m),4); l[size(l)+1] = list(graph41(list(2,1,1,2),i,j,k,h,m),8); l[size(l)+1] = list(graph41(list(1,2,2,1),i,j,k,h,m),8); } if (k <> h and k <> m) { l[size(l)+1] = list(graph42(list(3,1,1,1),i,j,k,h,m),6); l[size(l)+1] = list(graph42(list(1,3,1,1),i,j,k,h,m),6); l[size(l)+1] = list(graph42(list(1,1,3,1),i,j,k,h,m),3); l[size(l)+1] = list(graph42(list(2,2,1,1),i,j,k,h,m),8); l[size(l)+1] = list(graph42(list(1,1,2,2),i,j,k,h,m),8); l[size(l)+1] = list(graph42(list(2,1,2,1),i,j,k,h,m),4); l[size(l)+1] = list(graph42(list(1,2,2,1),i,j,k,h,m),4); } if (j <> h and j <> m) { l[size(l)+1] = list(graph43(list(3,1,1,1),i,j,k,h,m),18); l[size(l)+1] = list(graph43(list(2,2,1,1),i,j,k,h,m),16); } for (n=0;n<=r;n++) { if (k <> h and h <> m and m <> n) { l[size(l)+1] = list(graph51(list(2,1,1,1,1),i,j,k,h,m,n),2); l[size(l)+1] = list(graph51(list(1,2,1,1,1),i,j,k,h,m,n),2); l[size(l)+1] = list(graph51(list(1,1,2,1,1),i,j,k,h,m,n),4); } if (k <> h and h <> m and h <> n) { l[size(l)+1] = list(graph52(list(2,1,1,1,1),i,j,k,h,m,n),4); l[size(l)+1] = list(graph52(list(1,2,1,1,1),i,j,k,h,m,n),4); l[size(l)+1] = list(graph52(list(1,1,2,1,1),i,j,k,h,m,n),4); l[size(l)+1] = list(graph52(list(1,1,1,2,1),i,j,k,h,m,n),2); } if (k <> h and k <> m and k <> n) { l[size(l)+1] = list(graph53(list(2,1,1,1,1),i,j,k,h,m,n),12); l[size(l)+1] = list(graph53(list(1,2,1,1,1),i,j,k,h,m,n),12); l[size(l)+1] = list(graph53(list(1,1,2,1,1),i,j,k,h,m,n),4); } if (j <> h and h <> m and h <> n) { l[size(l)+1] = list(graph54(list(2,1,1,1,1),i,j,k,h,m,n),4); l[size(l)+1] = list(graph54(list(1,1,2,1,1),i,j,k,h,m,n),16); } if (k <> h and k <> m and h <> n) { l[size(l)+1] = list(graph55(list(2,1,1,1,1),i,j,k,h,m,n),2); l[size(l)+1] = list(graph55(list(1,2,1,1,1),i,j,k,h,m,n),2); l[size(l)+1] = list(graph55(list(1,1,1,2,1),i,j,k,h,m,n),4); } if (j <> h and j <> m and j <> n) { l[size(l)+1] = list(graph56(list(2,1,1,1,1),i,j,k,h,m,n),48); } for (p=0;p<=r;p++) { if (k <> h and h <> m and m <> n and n <> p) { l[size(l)+1] = list(graph61(list(1,1,1,1,1,1),i,j,k,h,m,n,p),2); } if (k <> h and h <> m and m <> n and m <> p) { l[size(l)+1] = list(graph62(list(1,1,1,1,1,1),i,j,k,h,m,n,p),2); } if (k <> h and h <> m and h <> n and n <> p) { l[size(l)+1] = list(graph63(list(1,1,1,1,1,1),i,j,k,h,m,n,p),1); } if (k <> h and h <> m and h <> n and h <> p) { l[size(l)+1] = list(graph64(list(1,1,1,1,1,1),i,j,k,h,m,n,p),6); } if (k <> h and k <> m and k <> n and n <> p) { l[size(l)+1] = list(graph65(list(1,1,1,1,1,1),i,j,k,h,m,n,p),4); } if (k <> h and k <> m and m <> p and h <> n) { l[size(l)+1] = list(graph66(list(1,1,1,1,1,1),i,j,k,h,m,n,p),6); } if (j <> h and h <> m and m <> n and m <> p) { l[size(l)+1] = list(graph67(list(1,1,1,1,1,1),i,j,k,h,m,n,p),8); } if (j <> h and h <> m and h <> n and h <> p) { l[size(l)+1] = list(graph68(list(1,1,1,1,1,1),i,j,k,h,m,n,p),12); } if (j <> h and h <> m and h <> n and n <> p) { l[size(l)+1] = list(graph69(list(1,1,1,1,1,1),i,j,k,h,m,n,p),2); } if (k <> h and k <> m and k <> n and k <> p) { l[size(l)+1] = list(graph610(list(1,1,1,1,1,1),i,j,k,h,m,n,p),24); } if (j <> h and j <> m and j <> n and j <> p) { l[size(l)+1] = list(graph611(list(1,1,1,1,1,1),i,j,k,h,m,n,p),720); } } } } } } } } } } return (l); } example { "EXAMPLE:"; echo=2; ring r = 0,x,dp; variety P = projectiveSpace(4); stack M = moduliSpace(P,2); def F = fixedPoints(M); size(F); typeof(F[1]) == "list"; typeof(F[1][1]) == "graph"; typeof(F[1][2]) == "int"; } static proc torusList(variety P) "USAGE: torusList(P); P variety RETURN: list INPUT: P is a projective space OUTPUT: a list of numbers THEORY: This is a procedure concerning the enumeration of rational curves. KEYWORDS: torus action EXAMPLE: example torusList; shows an example " { int i; int n = P.dimension; list l; for (i=0;i<=n;i++) { l = insert(l,number(10^i),size(l)); } return (l); } example { "EXAMPLE:"; echo=2; ring r = 0,x,dp; variety P = projectiveSpace(4); def L = torusList(P); L; } proc contributionBundle(stack M, graph G, list #) "USAGE: contributionBundle(M,G,#); M stack, G graph, # list RETURN: number INPUT: M is a moduli space of stable maps, G is a graph, # is a list. OUTPUT: a number corresponding to the contribution bundle on a moduli space of stable maps at a fixed point component (graph) KEYWORDS: contribution bundle, graph, multiple cover, rational curve, SEE ALSO: normalBundle EXAMPLE: example contributionBundle; shows an example " { def R = basering; setring R; int i,j,a; variety P = M.currentVariety; def L = torusList(P); int r = P.dimension; int d; if (size(#)==0) {d = 2*r - 3;} else { if (typeof(#[1]) == "int") {d = #[1];} else {Error("invalid optional argument");} } list e = G.edges; list v = G.vertices; number E = 1; number V = 1; if (r == 1) { for (i=1;i<=size(v);i++) { V = V*(-L[v[i][1]+1])^(v[i][2]-1); } for (j=1;j<=size(e);j++) { number f = 1; if (e[j][3]<>1) { for (a=1;a e[j][1] and k <> e[j][2]) { for (a=0;a<=d;a++) { y=y*((a*L[e[j][1]+1]+(d-a)*L[e[j][2]+1])/d - L[k+1]); } } } N = N*y; kill y,d,c; } for (i=1;i<=size(v);i++) { number F = 1; for (h=3;h<=size(v[i]);h++) { F = F*(L[v[i][h][1]+1]-L[v[i][h][2]+1])/v[i][h][3]; } if (v[i][2] == 1) { N = N/F; kill F; } else { number z = 1; for (m=0;m<=n;m++) { if (m<>v[i][1]) { z = z*(L[v[i][1]+1]-L[m+1]); } } if (v[i][2] == 3) { N = N*F/z^2; kill F,z; } else { number g = 0; for (b=3;b<=size(v[i]);b++) { g = g + v[i][b][3]/(L[v[i][b][1]+1]-L[v[i][b][2]+1]); } N = N*F*g^(3-v[i][2])/(z^(v[i][2]-1)); kill g,F,z; } } } return (N); } example { "EXAMPLE:"; echo=2; ring r = 0,x,dp; variety P = projectiveSpace(4); stack M = moduliSpace(P,2); def F = fixedPoints(M); graph G = F[1][1]; number f = normalBundle(M,G); f <> 0; } proc multipleCover(int d) "USAGE: multipleCover(d); d int RETURN: number THEORY: This is the contribution of degree d multiple covers of a smooth rational curve as a Gromov-Witten invariant. KEYWORDS: Gromov-Witten invariants, multiple covers SEE ALSO: rationalCurve, linesHypersurface EXAMPLE: example multipleCover; shows an example " { def R = basering; setring R; variety P = projectiveSpace(1); stack M = moduliSpace(P,d); def F = fixedPoints(M); int i; number r = 0; for (i=1;i<=size(F);i++) { graph G = F[i][1]; number s = contributionBundle(M,G); number t = F[i][2]*normalBundle(M,G); r = r + s/t; kill s,t,G; } return (r); } example { "EXAMPLE:"; echo=2; ring r = 0,x,dp; multipleCover(1); multipleCover(2); multipleCover(3); multipleCover(4); multipleCover(5); multipleCover(6); } proc linesHypersurface(int n) "USAGE: linesHypersurface(n); n int RETURN: number THEORY: This is the number of lines on a general hypersurface of degree d = 2n-3 in an n-dimensional projective space. KEYWORDS: Gromov-Witten invariants, lines on hypersurfaces SEE ALSO: linesHypersurface, multipleCover EXAMPLE: example linesHypersurface; shows an example " { def R = basering; setring R; variety P = projectiveSpace(n); stack M = moduliSpace(P,1); def F = fixedPoints(M); int i; number r = 0; for (i=1;i<=size(F);i++) { graph G = F[i][1]; number s = contributionBundle(M,G); number t = F[i][2]*normalBundle(M,G); r = r + s/t; kill s,t,G; } return (r); } example { "EXAMPLE:"; echo=2; ring r = 0,x,dp; linesHypersurface(2); linesHypersurface(3); linesHypersurface(4); linesHypersurface(5); linesHypersurface(6); linesHypersurface(7); linesHypersurface(8); linesHypersurface(9); linesHypersurface(10); } proc sumofquotients(stack M, list F, list #) "USAGE: sumofquotient(M,F,#); M stack, F list, # list RETURN: number THEORY: This is useful for the parallel computation of rationalCurve. KEYWORDS: Gromov-Witten invariants, rational curves on Calabi-Yau threefolds EXAMPLE: example sumofquotients; shows an example " { if (size(#) == 0) {list l = 5;} else {list l = #;} number sum = 0; number s, t; int i,j; for (i = size(F); i > 0; i--) { s = 1; for (j=1;j<=size(l);j++) { s = s*contributionBundle(M,F[i][1],list(l[j])); } t = F[i][2]*normalBundle(M,F[i][1]); sum = sum + s/t; } return(sum); } example { "EXAMPLE:"; echo=2; ring r = 0,x,dp; variety P = projectiveSpace(4); stack M = moduliSpace(P,2); list F = fixedPoints(M); sumofquotients(M,F); sumofquotients(M,F,list(5)); } proc rationalCurve(int d, list #) "USAGE: rationalCurve(d,#); d int, # list RETURN: number THEORY: This is the Gromov-Witten invariant corresponding the number of rational curves on a general Calabi-Yau threefold. KEYWORDS: Gromov-Witten invariants, rational curves on Calabi-Yau threefolds SEE ALSO: linesHypersurface, multipleCover EXAMPLE: example rationalCurve; shows an example " { def R = basering; setring R; int n,i; if (size(#) == 0) {n = 4; list l = 5;} else {n = size(#)+3; list l = #;} variety P = projectiveSpace(n); stack M = moduliSpace(P,d); def F = fixedPoints(M); int ncpus = system("--cpus"); int sizeF = size(F); list args; int from = 1; int to; for (i = 1; i <= ncpus; i++) { to = (sizeF*i) div ncpus; args[i] = list(M, list(F[from..to]), l); from = to+1; } list results = parallelWaitAll("sumofquotients", args); number r = 0; for (i = 1; i <= ncpus; i++) { r = r + results[i]; } return (r); } example { "EXAMPLE:"; echo=2; ring r = 0,x,dp; rationalCurve(1); /* rationalCurve(2); rationalCurve(3); rationalCurve(4); rationalCurve(1,list(4,2)); rationalCurve(1,list(3,3)); rationalCurve(1,list(3,2,2)); rationalCurve(1,list(2,2,2,2)); rationalCurve(2,list(4,2)); rationalCurve(2,list(3,3)); rationalCurve(2,list(3,2,2)); rationalCurve(2,list(2,2,2,2)); rationalCurve(3,list(4,2)); rationalCurve(3,list(3,3)); rationalCurve(3,list(3,2,2)); rationalCurve(3,list(2,2,2,2)); rationalCurve(4,list(4,2)); rationalCurve(4,list(3,3)); rationalCurve(4,list(3,2,2)); rationalCurve(4,list(2,2,2,2)); */ } //////////////////////////////////////////////////////////////////////////////// /////////// Procedures concerned with graphs /////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// proc printGraph(graph G) "USAGE: printGraph(G); G graph ASSUME: G is a graph. THEORY: This is the print function used by Singular to print a graph. KEYWORDS: graph EXAMPLE: example printGraph; shows an example " { "A graph with", size(G.vertices), "vertices and", size(G.edges), "edges"; } example { "EXAMPLE:"; echo=2; ring r = 0,x,dp; graph G = makeGraph(list(list(0,1,list(0,1,2)),list(1,1,list(1,0,2))), list(list(0,1,2))); G; } proc makeGraph(list v, list e) "USAGE: makeGraph(v,e); v list, e list ASSUME: v is a list of vertices, e is a list of edges. RETURN: graph with vertices v and edges e. THEORY: Creates a graph from a list of vertices and edges. KEYWORDS: graph EXAMPLE: example makeGraph; shows an example { graph G; G.vertices = v; G.edges = e; return(G); } example { "EXAMPLE:"; echo=2; ring r = 0,x,dp; graph G = makeGraph(list(list(0,1,list(0,1,2)),list(1,1,list(1,0,2))), list(list(0,1,2))); G; } static proc graph1(int d, int i, int j) { graph G; list f1 = i,j,d; list f2 = j,i,d; list v1 = i,1,f1; list v2 = j,1,f2; G.vertices = v1,v2; G.edges = list(f1); return (G); } static proc graph2(list d, int i, int j, int k) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,1,f4; G.vertices = v1,v2,v3; G.edges = f1,f3; return (G); } static proc graph31(list d, int i, int j, int k, int h) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,2,f4,f5; list v4 = h,1,f6; G.vertices = v1,v2,v3,v4; G.edges = f1,f3,f5; return (G); } static proc graph32(list d, int i, int j, int k, int h) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = j,h,d[3]; list f5 = k,j,d[2]; list f6 = h,j,d[3]; list v1 = i,1,f1; list v2 = j,3,f2,f3,f4; list v3 = k,1,f5; list v4 = h,1,f6; G.vertices = v1,v2,v3,v4; G.edges = f1,f3,f4; return (G); } static proc graph41(list d, int i, int j, int k, int h, int l) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = h,l,d[4]; list f8 = l,h,d[4]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,2,f4,f5; list v4 = h,2,f6,f7; list v5 = l,1,f8; G.vertices = v1,v2,v3,v4,v5; G.edges = f1,f3,f5,f7; return (G); } static proc graph42(list d, int i, int j, int k, int h, int l) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = k,l,d[4]; list f7 = h,k,d[3]; list f8 = l,k,d[4]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,3,f4,f5,f6; list v4 = h,1,f7; list v5 = l,1,f8; G.vertices = v1,v2,v3,v4,v5; G.edges = f1,f3,f5,f6; return (G); } static proc graph43(list d, int i, int j, int k, int h, int l) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = j,h,d[3]; list f5 = j,l,d[4]; list f6 = k,j,d[2]; list f7 = h,j,d[3]; list f8 = l,j,d[4]; list v1 = i,1,f1; list v2 = j,4,f2,f3,f4,f5; list v3 = k,1,f6; list v4 = h,1,f7; list v5 = l,1,f8; G.vertices = v1,v2,v3,v4,v5; G.edges = f1,f3,f4,f5; return (G); } static proc graph51(list d, int i, int j, int k, int h, int m, int n) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = m,n,d[5]; list f10 = n,m,d[5]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,2,f4,f5; list v4 = h,2,f6,f7; list v5 = m,2,f8,f9; list v6 = n,1,f10; G.vertices = v1,v2,v3,v4,v5,v6; G.edges = f1,f3,f5,f7,f9; return (G); } static proc graph52(list d, int i, int j, int k, int h, int m, int n) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = h,n,d[5]; list f10 = n,h,d[5]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,2,f4,f5; list v4 = h,3,f6,f7,f9; list v5 = m,1,f8; list v6 = n,1,f10; G.vertices = v1,v2,v3,v4,v5,v6; G.edges = f1,f3,f5,f7,f9; return (G); } static proc graph53(list d, int i, int j, int k, int h, int m, int n) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = k,m,d[4]; list f8 = m,k,d[4]; list f9 = k,n,d[5]; list f10 = n,k,d[5]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,4,f4,f5,f7,f9; list v4 = h,1,f6; list v5 = m,1,f8; list v6 = n,1,f10; G.vertices = v1,v2,v3,v4,v5,v6; G.edges = f1,f3,f5,f7,f9; return (G); } static proc graph54(list d, int i, int j, int k, int h, int m, int n) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = j,h,d[3]; list f6 = h,j,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = h,n,d[5]; list f10 = n,h,d[5]; list v1 = i,1,f1; list v2 = j,3,f2,f3,f5; list v3 = k,1,f4; list v4 = h,3,f6,f7,f9; list v5 = m,1,f8; list v6 = n,1,f10; G.vertices = v1,v2,v3,v4,v5,v6; G.edges = f1,f3,f5,f7,f9; return (G); } static proc graph55(list d, int i, int j, int k, int h, int m, int n) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = k,m,d[4]; list f8 = m,k,d[4]; list f9 = h,n,d[5]; list f10 = n,h,d[5]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,3,f4,f5,f7; list v4 = h,2,f6,f9; list v5 = m,1,f8; list v6 = n,1,f10; G.vertices = v1,v2,v3,v4,v5,v6; G.edges = f1,f3,f5,f7,f9; return (G); } static proc graph56(list d, int i, int j, int k, int h, int m, int n) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = j,h,d[3]; list f6 = h,j,d[3]; list f7 = j,m,d[4]; list f8 = m,j,d[4]; list f9 = j,n,d[5]; list f10 = n,j,d[5]; list v1 = i,1,f1; list v2 = j,5,f2,f3,f5,f7,f9; list v3 = k,1,f4; list v4 = h,1,f6; list v5 = m,1,f8; list v6 = n,1,f10; G.vertices = v1,v2,v3,v4,v5,v6; G.edges = f1,f3,f5,f7,f9; return (G); } static proc graph61(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = m,n,d[5]; list f10 = n,m,d[5]; list f11 = n,p,d[6]; list f12 = p,n,d[6]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,2,f4,f5; list v4 = h,2,f6,f7; list v5 = m,2,f8,f9; list v6 = n,2,f10,f11; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph62(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = m,n,d[5]; list f10 = n,m,d[5]; list f11 = m,p,d[6]; list f12 = p,m,d[6]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,2,f4,f5; list v4 = h,2,f6,f7; list v5 = m,3,f8,f9,f11; list v6 = n,1,f10; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph63(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = h,n,d[5]; list f10 = n,h,d[5]; list f11 = n,p,d[6]; list f12 = p,n,d[6]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,2,f4,f5; list v4 = h,3,f6,f7,f9; list v5 = m,1,f8; list v6 = n,2,f10,f11; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph64(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = h,n,d[5]; list f10 = n,h,d[5]; list f11 = h,p,d[6]; list f12 = p,h,d[6]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,2,f4,f5; list v4 = h,4,f6,f7,f9,f11; list v5 = m,1,f8; list v6 = n,1,f10; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph65(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = k,m,d[4]; list f8 = m,k,d[4]; list f9 = k,n,d[5]; list f10 = n,k,d[5]; list f11 = n,p,d[6]; list f12 = p,n,d[6]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,4,f4,f5,f7,f9; list v4 = h,1,f6; list v5 = m,1,f8; list v6 = n,2,f10,f11; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph66(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = k,m,d[4]; list f8 = m,k,d[4]; list f9 = h,n,d[5]; list f10 = n,h,d[5]; list f11 = m,p,d[6]; list f12 = p,m,d[6]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,3,f4,f5,f7; list v4 = h,2,f6,f9; list v5 = m,2,f8,f11; list v6 = n,1,f10; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph67(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = j,h,d[3]; list f6 = h,j,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = m,n,d[5]; list f10 = n,m,d[5]; list f11 = m,p,d[6]; list f12 = p,m,d[6]; list v1 = i,1,f1; list v2 = j,3,f2,f3,f5; list v3 = k,1,f4; list v4 = h,2,f6,f7; list v5 = m,3,f8,f9,f11; list v6 = n,1,f10; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph68(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = j,h,d[3]; list f6 = h,j,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = h,n,d[5]; list f10 = n,h,d[5]; list f11 = h,p,d[6]; list f12 = p,h,d[6]; list v1 = i,1,f1; list v2 = j,3,f2,f3,f5; list v3 = k,1,f4; list v4 = h,4,f6,f7,f9,f11; list v5 = m,1,f8; list v6 = n,1,f10; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph69(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = j,h,d[3]; list f6 = h,j,d[3]; list f7 = h,m,d[4]; list f8 = m,h,d[4]; list f9 = h,n,d[5]; list f10 = n,h,d[5]; list f11 = n,p,d[6]; list f12 = p,n,d[6]; list v1 = i,1,f1; list v2 = j,3,f2,f3,f5; list v3 = k,1,f4; list v4 = h,3,f6,f7,f9; list v5 = m,1,f8; list v6 = n,2,f10,f11; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph610(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = k,h,d[3]; list f6 = h,k,d[3]; list f7 = k,m,d[4]; list f8 = m,k,d[4]; list f9 = k,n,d[5]; list f10 = n,k,d[5]; list f11 = k,p,d[6]; list f12 = p,k,d[6]; list v1 = i,1,f1; list v2 = j,2,f2,f3; list v3 = k,5,f4,f5,f7,f9,f11; list v4 = h,1,f6; list v5 = m,1,f8; list v6 = n,1,f10; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } static proc graph611(list d, int i, int j, int k, int h, int m, int n, int p) { graph G; list f1 = i,j,d[1]; list f2 = j,i,d[1]; list f3 = j,k,d[2]; list f4 = k,j,d[2]; list f5 = j,h,d[3]; list f6 = h,j,d[3]; list f7 = j,m,d[4]; list f8 = m,j,d[4]; list f9 = j,n,d[5]; list f10 = n,j,d[5]; list f11 = j,p,d[6]; list f12 = p,j,d[6]; list v1 = i,1,f1; list v2 = j,6,f2,f3,f5,f7,f9,f11; list v3 = k,1,f4; list v4 = h,1,f6; list v5 = m,1,f8; list v6 = n,1,f10; list v7 = p,1,f12; G.vertices = v1,v2,v3,v4,v5,v6,v7; G.edges = f1,f3,f5,f7,f9,f11; return (G); } proc part(poly f, int n) "USAGE: part(f,n); f poly, n int RETURN: poly PURPOSE: computing the homogeneous component of a polynomial. EXAMPLE: example part; shows examples " { int i; poly p; for (i=1;i<=size(f);i++) { if (deg(f[i])==n) {p=p+f[i];} } return (p); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z),wp(1,2,3); poly f = 1+x+x2+x3+x4+y+y2+y3+z+z2+xy+xz+yz+xyz; part(f,0); part(f,1); part(f,2); part(f,3); part(f,4); part(f,5); part(f,6); } proc parts(poly f, int i, int j) "USAGE: parts(f,i,j); f poly, i int, j int RETURN: poly THEORY: computing a polynomial which is the sum of the homogeneous components of a polynomial. EXAMPLE: example parts; shows examples " { int k; poly p; for (k=i;k<=j;k++) { p=p+part(f,k); } return (p); } example { "EXAMPLE:"; echo=2; ring r = 0,(x,y,z),wp(1,2,3); poly f = 1+x+x2+x3+x4+y+y2+y3+z+z2+xy+xz+yz+xyz; parts(f,2,4); } proc logg(poly f, int n) "USAGE: logg(f,n); f poly, n int RETURN: poly THEORY: computing Chern characters from total Chern classes. EXAMPLE: example logg; shows examples " { poly p; int i,j,k,m; if (n==0) {p=0;} if (n==1) {p=part(f,1);} else { list l=-part(f,1); for (j=2;j<=n;j++) { poly q; for (k=1;k f_i = a^1_1 * var(1) * gen(1) + ... + a^1_m * var(1) * gen(m) + a^2_1 * var(2) * gen(1) + ... + a^2_m * var(2) * gen(m) + ... a^n_1 * var(n) * gen(1) + ... + a^n_m * var(n) * gen(m); NOTE: for every f_i we run only ONCE along w_i saving partial sums into a temporary array of polys of size m */ static proc TensorModuleMult(int m, module M) { return( system("tensorModuleMult", m, M) ); // trick! int n = nvars(basering); int k = ncols(M); int g, cc, vv; poly h; module Temp; // = {f_1, ..., f_k } intvec exp; vector pTempSum, w; for( int i = k; i > 0; i-- ) // for every w \in M { pTempSum[m] = 0; w = M[i]; while(w != 0) // for each term of w... { exp = leadexp(w); g = exp[n+1]; // module component! h = w[g]; w = w - h * gen(g); cc = g % m; if( cc == 0) { cc = m; } vv = 1 + (g - cc) / m; pTempSum = pTempSum + h * var(vv) * gen(cc); } Temp[i] = pTempSum; } Temp = transpose(Temp); return(Temp); } /////////////////////////////////////////////////////////////////////////////// proc truncate(module phi, int d) "USAGE: truncate(M,d); M module, d int ASSUME: @code{M} is graded, and it comes assigned with an admissible degree vector as an attribute RETURN: module NOTE: Output is a presentation matrix for the truncation of coker(M) at degree d. EXAMPLE: example truncate; shows an example KEYWORDS: truncated module " { if ( typeof(attrib(phi,"isHomog"))=="string" ) { if (size(phi)==0) { // assign weights 0 to generators of R^n (n=nrows(phi)) intvec v; v[nrows(phi)]=0; attrib(phi,"isHomog",v); } else { ERROR("No admissible degree vector assigned"); } } else { intvec v=attrib(phi,"isHomog"); } int i,m,dummy; int s = nrows(phi); module L; // TOO BIG!!! for (i=1; i<=s; i++) { if (d>v[i]) { L = L+maxideal(d-v[i])*gen(i); } else { L = L+gen(i); } } L = modulo(L,phi); L = minbase(prune(L)); if (size(L)==0) {return(L);} // it only remains to set the degrees for L: // ------------------------------------------ m = v[1]; for(i=2; i<=size(v); i++) { if(v[i]m) { vv = vv+d; } else { vv = vv+m; } attrib(L,"isHomog",vv); return(L); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; module M=maxideal(3); homog(M); // compute presentation matrix for truncated module (R/^3)_(>=2) module M2=truncate(M,2); print(M2); dimGradedPart(M2,1); dimGradedPart(M2,2); // this should coincide with: dimGradedPart(M,2); // shift grading by 1: intvec v=1; attrib(M,"isHomog",v); M2=truncate(M,2); print(M2); dimGradedPart(M2,3); } /////////////////////////////////////////////////////////////////////////////// proc truncateFast(module M, int d) "USAGE: truncateFast(M,d); M module, d int ASSUME: @code{M} is graded, and it comes assigned with an admissible degree vector as an attribute 'isHomog' RETURN: module NOTE: Output is a presentation matrix for the truncation of coker(M) at d. Fast + experimental version. M shoud be a SB! DISPLAY: If @code{printlevel}>=1, step-by step timings will be printed. If @code{printlevel}>=2 we add progress debug messages if @code{printlevel}>=3, even all intermediate results... EXAMPLE: example truncateFast; shows an example KEYWORDS: truncated module " { // int PL = printlevel + 1; int PL = printlevel - voice + 2; dbprint(PL-1, "// truncateFast(M: "+ string(nrows(M)) + " x " + string(ncols(M)) +", " + string(d) + "):"); dbprint(PL-2, M); intvec save = option(get); if( PL >= 2 ) { option(prot); option(mem); } int tTruncateBegin=timer; if (attrib(M,"isSB")!=1) { ERROR("M must be a standard basis!"); } dbprint(PL-1, "// M is a SB! "); if ( typeof(attrib(M,"isHomog"))=="string" ) { if (size(M)==0) { // assign weights 0 to generators of R^n (n=nrows(M)) intvec v; v[nrows(M)]=0; attrib(M,"isHomog",v); } else { ERROR("No admissible degree vector assigned"); } } else { intvec v=attrib(M,"isHomog"); } dbprint(PL-1, "// weighting(M): ["+ string(v) + "]"); int i,m,dummy; int s = nrows(M); int tKBaseBegin = timer; module L = kbase(M, d); // TODO: check whether this is always correct!?! dbprint(PL-1, "// L = kbase(M,d): "+string(nrows(L)) + " x " + string(ncols(L)) +""); dbprint(PL-2, L); dbprint(PL-1, "// weighting(L): ["+ string(attrib(L, "isHomog")) + "]"); int tModuloBegin = timer; L = modulo(L,M); dbprint(PL-1, "// L = modulo(L,M): "+string(nrows(L)) + " x " + string(ncols(L)) +""); dbprint(PL-2, L); dbprint(PL-1, "// weighting(L): ["+ string(attrib(L, "isHomog")) + "]"); int tPruneBegin = timer; L = prune(L); dbprint(PL-1, "// L = prune(L): "+string(nrows(L)) + " x " + string(ncols(L)) +""); dbprint(PL-2, L); dbprint(PL-1, "// weighting(L): ["+ string(attrib(L, "isHomog")) + "]"); int tPruneEnd = timer; L = minbase(L); int tMinBaseEnd = timer; dbprint(PL-1, "// L = minbase(L): "+string(nrows(L)) + " x " + string(ncols(L)) +""); dbprint(PL-2, L); dbprint(PL-1, "// weighting(L): ["+ string(attrib(L, "isHomog")) + "]"); if (size(L)!=0) { // it only remains to set the degrees for L: // ------------------------------------------ m = v[1]; for(i=2; i<=size(v); i++) { if(v[i]m) { vv = vv+d; } else { vv = vv+m; } attrib(L,"isHomog",vv); } int tTruncateEnd=timer; dbprint(PL-1, "// corrected weighting(L): ["+ string(attrib(L, "isHomog")) + "]"); if(PL > 0) { " -------------- TIMINGS -------------- Trunc Time: ", tTruncateEnd - tTruncateBegin, " :: Before .Time: ", tKBaseBegin - tTruncateBegin, " :: kBase Time: ", tModuloBegin - tKBaseBegin, " :: Modulo Time: ", tPruneBegin - tModuloBegin, " :: Prune Time: ", tPruneEnd - tPruneBegin, " :: Minbase Time: ", tMinBaseEnd - tPruneEnd, " :: After .Time: ", tTruncateEnd - tMinBaseEnd; } option(set, save); return(L); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z,u,v),dp; module M=maxideal(3); homog(M); // compute presentation matrix for truncated module (R/^3)_(>=2) int t=timer; module M2t=truncate(M,2); t = timer - t; "// Simple truncate: ", t; t=timer; module M2=truncateFast(std(M),2); t = timer - t; "// Fast truncate: ", t; print(M2); "// Check: M2t == M2?: ", size(NF(M2, std(M2t))) + size(NF(M2t, std(M2))); dimGradedPart(M2,1); dimGradedPart(M2,2); // this should coincide with: dimGradedPart(M,2); // shift grading by 1: intvec v=1; attrib(M,"isHomog",v); t=timer; M2t=truncate(M,2); t = timer - t; "// Simple truncate: ", t; t=timer; M2=truncateFast(std(M),2); t = timer - t; "// Fast truncate: ", t; print(M2); "// Check: M2t == M2?: ", size(NF(M2, std(M2t))) + size(NF(M2t, std(M2))); //? dimGradedPart(M2,3); } /////////////////////////////////////////////////////////////////////////////// proc dimGradedPart(module phi, int d) "USAGE: dimGradedPart(M,d); M module, d int ASSUME: @code{M} is graded, and it comes assigned with an admissible degree vector as an attribute RETURN: int NOTE: Output is the vector space dimension of the graded part of degree d of coker(M). EXAMPLE: example dimGradedPart; shows an example KEYWORDS: graded module, graded piece " { if ( typeof(attrib(phi,"isHomog"))=="string" ) { if (size(phi)==0) { // assign weights 0 to generators of R^n (n=nrows(phi)) intvec v; v[nrows(phi)]=0; } else { ERROR("No admissible degree vector assigned"); } } else { intvec v=attrib(phi,"isHomog"); } int s = nrows(phi); int i,m,dummy; module L,LL; for (i=1; i<=s; i++) { if (d>v[i]) { L = L+maxideal(d-v[i])*gen(i); LL = LL+maxideal(d+1-v[i])*gen(i); } else { L = L+gen(i); if (d==v[i]) { LL = LL+maxideal(1)*gen(i); } else { LL = LL+gen(i); } } } LL=LL,phi; L = modulo(L,LL); L = std(prune(L)); if (size(L)==0) {return(0);} return(vdim(L)); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; module M=maxideal(3); // assign compatible weight vector (here: 0) homog(M); // compute dimension of graded pieces of R/^3 : dimGradedPart(M,0); dimGradedPart(M,1); dimGradedPart(M,2); dimGradedPart(M,3); // shift grading: attrib(M,"isHomog",intvec(2)); dimGradedPart(M,2); } /////////////////////////////////////////////////////////////////////////////// proc CM_regularity (module M) "USAGE: CM_regularity(M); M module ASSUME: @code{M} is graded, and it comes assigned with an admissible degree vector as an attribute RETURN: integer, the Castelnuovo-Mumford regularity of coker(M) NOTE: procedure calls mres EXAMPLE: example CM_regularity; shows an example KEYWORDS: Castelnuovo-Mumford regularity " { if ( typeof(attrib(M,"isHomog"))=="string" ) { if (size(M)==0) { // assign weights 0 to generators of R^n (n=nrows(M)) intvec v; v[nrows(M)]=0; attrib(M,"isHomog",v); } else { ERROR("No admissible degree vector assigned"); } } if( attrib(CM_regularity,"Algorithm") == "minres_res" ) { def L = minres( res(M,0) ); // let's try it out! } else { def L = mres(M,0); } intmat BeL = betti(L); int r = nrows(module(matrix(BeL))); // last non-zero row if (typeof(attrib(BeL,"rowShift"))!="string") { int shift = attrib(BeL,"rowShift"); } return(r+shift-1); } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z,u),dp; resolution T1=mres(maxideal(1),0); module M=T1[3]; intvec v=2,2,2,2,2,2; attrib(M,"isHomog",v); CM_regularity(M); } /////////////////////////////////////////////////////////////////////////////// proc sheafCohBGG(module M,int l,int h) "USAGE: sheafCohBGG(M,l,h); M module, l,h int ASSUME: @code{M} is graded, and it comes assigned with an admissible degree vector as an attribute, @code{h>=l}, and the basering has @code{n+1} variables. RETURN: intmat, cohomology of twists of the coherent sheaf F on P^n associated to coker(M). The range of twists is determined by @code{l}, @code{h}. DISPLAY: The intmat is displayed in a diagram of the following form: @* @format l l+1 h ---------------------------------------------------------- n: h^n(F(l)) h^n(F(l+1)) ...... h^n(F(h)) ............................................... 1: h^1(F(l)) h^1(F(l+1)) ...... h^1(F(h)) 0: h^0(F(l)) h^0(F(l+1)) ...... h^0(F(h)) ---------------------------------------------------------- chi: chi(F(l)) chi(F(l+1)) ...... chi(F(h)) @end format A @code{'-'} in the diagram refers to a zero entry; a @code{'*'} refers to a negative entry (= dimension not yet determined). refers to a not computed dimension. @* NOTE: This procedure is based on the Bernstein-Gel'fand-Gel'fand correspondence and on Tate resolution ( see [Eisenbud, Floystad, Schreyer: Sheaf cohomology and free resolutions over exterior algebras, Trans AMS 355 (2003)] ).@* @code{sheafCohBGG(M,l,h)} does not compute all values in the above table. To determine all values of @code{h^i(F(d))}, @code{d=l..h}, use @code{sheafCohBGG(M,l-n,h+n)}. SEE ALSO: sheafCoh, dimH EXAMPLE: example sheafCohBGG; shows an example " { int i,j,k,row,col; if( typeof(attrib(M,"isHomog"))!="intvec" ) { if (size(M)==0) { attrib(M,"isHomog",0); } else { ERROR("No admissible degree vector assigned"); } } int n=nvars(basering)-1; int ell=l+n; def R=basering; int reg = CM_regularity(M); int bound=max(reg+1,h-1); module MT=truncate(M,bound); int m=nrows(MT); MT=transpose(jacobM(MT)); MT=syz(MT); matrix ML[n+1][1]=maxideal(1); matrix S=transpose(outer(ML,unitmat(m))); matrix SS=transpose(S*MT); //--- to the exterior algebra def AR = Exterior(); setring AR; intvec saveopt=option(get); option(redSB); option(redTail); module EM=imap(R,SS); intvec w; //--- here we are with our matrix int bound1=max(1,bound-ell+1); for (i=1; i<=nrows(EM); i++) { w[i]=-bound-1; } attrib(EM,"isHomog",w); resolution RE=mres(EM,bound1); intmat Betti=betti(RE); k=ncols(Betti); row=nrows(Betti); int shift=attrib(Betti,"rowShift")+(k+ell-1); intmat newBetti[n+1][h-l+1]; for (j=1; j<=row; j++) { for (i=l; i<=h; i++) { if ((k+1-j-i+ell-shift>0) and (j+i-ell+shift>=1)) { newBetti[n+2-shift-j,i-l+1]=Betti[j,k+1-j-i+ell-shift]; } else { newBetti[n+2-shift-j,i-l+1]=-1; } } } for (j=2; j<=n+1; j++) { for (i=1; i=k+j; i--) { newBetti[j,i]=-1; } } displayCohom(newBetti,l,h,n); option(set,saveopt); setring R; return(newBetti); } example {"EXAMPLE:"; echo = 2; // cohomology of structure sheaf on P^4: //------------------------------------------- ring r=0,x(1..5),dp; module M=0; def A=sheafCohBGG(M,-9,4); // cohomology of cotangential bundle on P^3: //------------------------------------------- ring R=0,(x,y,z,u),dp; resolution T1=mres(maxideal(1),0); module M=T1[3]; intvec v=2,2,2,2,2,2; attrib(M,"isHomog",v); def B=sheafCohBGG(M,-8,4); } /////////////////////////////////////////////////////////////////////////////// static proc showResult( def R, int l, int h ) { int PL = 1; // printlevel - voice + 2; // int PL = printlevel + 1; intmat Betti; if(typeof(R)=="resolution") { Betti = betti(R); } else { if(typeof(R)!="intmat") { ERROR("Wrong input!!!"); } Betti = R; } int n=nvars(basering)-1; int ell = l + n; int k = ncols(Betti); int row = nrows(Betti); int shift = attrib(Betti,"rowShift") + (k + ell - 1); int iWTH = h-l+1; int d = k - h + ell - 1; if( PL > 1 ) { "// l: ", l; "// h: ", h; "// n: ", n; "// ell: ", ell; "// k: ", k; "// row: ", row; "// shift: ", shift; "// iWTH: ", iWTH; "// d: ", d; } intmat newBetti[ n + 1 ][ iWTH ]; int i, j; for (j=1; j<=row; j++) { for (i=l; i<=h; i++) { if( (n+2-shift-j)>0 ) { if ( (k+1-j-i+ell-shift>0) and (j+i-ell+shift>=1)) { newBetti[n+2-shift-j,i-l+1]=Betti[j,k+1-j-i+ell-shift]; } else { newBetti[n+2-shift-j,i-l+1]=-1; } } } } for (j=2; j<=n+1; j++) { for (i=1; i=k+j; i--) { newBetti[j,i]=0; // -1; } } if( PL > 0 ) { "Cohomology table:"; displayCohom(newBetti, l, h, n); } return(newBetti); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// proc sheafCohBGG2(module M,int l,int h) "USAGE: sheafCohBGG2(M,l,h); M module, l,h int ASSUME: @code{M} is graded, and it comes assigned with an admissible degree vector as an attribute, @code{h>=l}, and the basering has @code{n+1} variables. RETURN: intmat, cohomology of twists of the coherent sheaf F on P^n associated to coker(M). The range of twists is determined by @code{l}, @code{h}. DISPLAY: The intmat is displayed in a diagram of the following form: @* @format l l+1 h ---------------------------------------------------------- n: h^n(F(l)) h^n(F(l+1)) ...... h^n(F(h)) ............................................... 1: h^1(F(l)) h^1(F(l+1)) ...... h^1(F(h)) 0: h^0(F(l)) h^0(F(l+1)) ...... h^0(F(h)) ---------------------------------------------------------- chi: chi(F(l)) chi(F(l+1)) ...... chi(F(h)) @end format A @code{'-'} in the diagram refers to a zero entry; a @code{'*'} refers to a negative entry (= dimension not yet determined). refers to a not computed dimension. @* If @code{printlevel}>=1, step-by step timings will be printed. If @code{printlevel}>=2 we add progress debug messages if @code{printlevel}>=3, even all intermediate results... NOTE: This procedure is based on the Bernstein-Gel'fand-Gel'fand correspondence and on Tate resolution ( see [Eisenbud, Floystad, Schreyer: Sheaf cohomology and free resolutions over exterior algebras, Trans AMS 355 (2003)] ).@* @code{sheafCohBGG(M,l,h)} does not compute all values in the above table. To determine all values of @code{h^i(F(d))}, @code{d=l..h}, use @code{sheafCohBGG(M,l-n,h+n)}. Experimental version. Should require less memory. SEE ALSO: sheafCohBGG EXAMPLE: example sheafCohBGG2; shows an example " { int PL = printlevel - voice + 2; // int PL = printlevel; dbprint(PL-1, "// sheafCohBGG2(M: "+ string(nrows(M)) + " x " + string(ncols(M)) +", " + string(l) + ", " + string(h) + "):"); dbprint(PL-2, M); intvec save = option(get); if( PL >= 2 ) { option(prot); option(mem); } def isCoker = attrib(M, "isCoker"); if( typeof(isCoker) == "int" ) { if( isCoker > 0 ) { dbprint(PL-1, "We are going to assume that M is given by coker matrix (that is, M is not a submodule presentation!)"); } } int i,j,k,row,col; if( typeof(attrib(M,"isHomog"))!="intvec" ) { if (size(M)==0) { attrib(M,"isHomog",0); } else { ERROR("No admissible degree vector assigned"); } } dbprint(PL-1, "// weighting(M): ["+ string(attrib(M, "isHomog")) + "]"); option(redSB); option(redTail); def R=basering; int n = nvars(R) - 1; int ell = l + n; ///////////////////////////////////////////////////////////////////////////// // computations int tBegin=timer; int reg = CM_regularity(M); int tCMEnd = timer; dbprint(PL-1, "// CM_reg(M): "+ string(reg)); int bound = max(reg + 1, h - 1); dbprint(PL-1, "// bound: "+ string(bound)); /////////////////////////////////////////////////////////////// int tSTDBegin=timer; M = std(M); // for kbase! // NOTE: this should be after CM_regularity, since otherwise CM_regularity computes JUST TOOOOOOO LONG sometimes (see Reg_Hard examples!) int tSTDEnd = timer; dbprint(PL-1, "// M = std(M: "+string(nrows(M)) + " x " + string(ncols(M)) + ")"); dbprint(PL-2, M); dbprint(PL-1, "// weighting(M): ["+ string(attrib(M, "isHomog")) + "]"); printlevel = printlevel + 1; int tTruncateBegin=timer; module MT = truncateFast(M, bound); int tTruncateEnd=timer; printlevel = printlevel - 1; dbprint(PL-1, "// MT = truncateFast(M: "+string(nrows(MT)) + " x " + string(ncols(MT)) +", " + string(bound) + ")"); dbprint(PL-2, MT); dbprint(PL-1, "// weighting(MT): ["+ string(attrib(MT, "isHomog")) + "]"); int m=nrows(MT); /////////////////////////////////////////////////////////////// int tTransposeJacobBegin=timer; MT = jacob(MT); // ! :( int tTransposeJacobEnd=timer; dbprint(PL-1, "// MT = jacob(MT: "+string(nrows(MT)) + " x " + string(ncols(MT)) + ")"); dbprint(PL-2, MT); dbprint(PL-1, "// weighting(MT): ["+ string(attrib(MT, "isHomog")) + "]"); int tSyzBegin=timer; MT = syz(MT); int tSyzEnd=timer; dbprint(PL-1, "// MT = syz(MT: "+string(nrows(MT)) + " x " + string(ncols(MT)) + ")"); dbprint(PL-2, MT); dbprint(PL-1, "// weighting(MT): ["+ string(attrib(MT, "isHomog")) + "]"); int tMatrixOppBegin=timer; module SS = TensorModuleMult(m, MT); int tMatrixOppEnd=timer; dbprint(PL-1, "// SS = TensorModuleMult("+ string(m)+ ", MT: "+string(nrows(MT)) + " x " + string(ncols(MT)) + ")"); dbprint(PL-2, SS); dbprint(PL-1, "// weighting(SS): ["+ string(attrib(SS, "isHomog")) + "]"); //--- to the exterior algebra def AR = Exterior(); setring AR; dbprint(PL-1, "// Test: var(1) * var(1): "+ string(var(1) * var(1))); int maxbound = max(1, bound - ell + 1); // int maxbound = max(1, bound - l + 1); // As In M2!!! dbprint(PL-1, "// maxbound: "+ string(maxbound)); //--- here we are with our matrix module EM=imap(R,SS); intvec w; for (i=1; i<=nrows(EM); i++) { w[i]=-bound-1; } attrib(EM,"isHomog",w); /////////////////////////////////////////////////////////////// dbprint(PL-1, "// EM: "+string(nrows(EM)) + " x " + string(ncols(EM)) + ")"); dbprint(PL-2, EM); dbprint(PL-1, "// weighting(EM): ["+ string(attrib(EM, "isHomog")) + "]"); int tResulutionBegin=timer; resolution RE = nres(EM, maxbound); // TODO: Plural computes one too many syzygies...?! int tMinResBegin=timer; RE = minres(RE); int tBettiBegin=timer; intmat Betti = betti(RE); // betti(RE, 1);? int tResulutionEnd=timer; int tEnd = tResulutionEnd; if( PL > 0 ) { // list L = RE; // TODO: size(L/RE) is wrong! " ---- RESULTS ---- Tate Resolution: "; RE; "Betti numbers for Tate resolution (diagonal cohomology table):"; print(Betti, "betti"); // Diagonal form! } // printlevel = printlevel + 1; Betti = showResult(Betti, l, h ); // Show usual form of cohomology table // printlevel = printlevel - 1; if(PL > 0) { " ---- TIMINGS ------- Trunc Time: ", tTruncateEnd - tTruncateBegin, " Reg Time: ", tCMEnd - tBegin, " kStd Time: ", tSTDEnd - tSTDBegin, " Jacob Time: ", tTransposeJacobEnd - tTransposeJacobBegin, " Syz Time: ", tSyzEnd - tSyzBegin, " Mat Time: ", tMatrixOppEnd - tMatrixOppBegin, " ------------------------------ Res Time: ", tResulutionEnd - tResulutionBegin, " :: NRes Time: ", tMinResBegin - tResulutionBegin, " :: MinRes .Time: ", tBettiBegin - tMinResBegin, " :: Betti .Time: ", tResulutionEnd - tBettiBegin, " --------------------------------------------------------- Total Time: ", tEnd - tBegin, " --------------------------------------------------------- "; } setring R; option(set, save); return(Betti); } example {"EXAMPLE:"; echo = 2; int pl = printlevel; int l,h, t; //------------------------------------------- // cohomology of structure sheaf on P^4: //------------------------------------------- ring r=32001,x(1..5),dp; module M= getStructureSheaf(); // OO_P^4 l = -12; h = 12; // range of twists: l..h printlevel = 0; ////////////////////////////////////////////// t = timer; def A = sheafCoh(M, l, h); // global Ext method: "Time: ", timer - t; ////////////////////////////////////////////// t = timer; A = sheafCohBGG(M, l, h); // BGG method (without optimization): "Time: ", timer - t; ////////////////////////////////////////////// t = timer; A = sheafCohBGG2(M, l, h); // BGG method (with optimization) "Time: ", timer - t; ////////////////////////////////////////////// printlevel = pl; kill A, r; //------------------------------------------- // cohomology of cotangential bundle on P^3: //------------------------------------------- ring R=32001,(x,y,z,u),dp; module M = getCotangentialBundle(); l = -12; h = 11; // range of twists: l..h ////////////////////////////////////////////// printlevel = 0; t = timer; def B = sheafCoh(M, l, h); // global Ext method: "Time: ", timer - t; ////////////////////////////////////////////// t = timer; B = sheafCohBGG(M, l, h); // BGG method (without optimization): "Time: ", timer - t; ////////////////////////////////////////////// t = timer; B = sheafCohBGG2(M, l, h); // BGG method (with optimization) "Time: ", timer - t; ////////////////////////////////////////////// printlevel = pl; } /////////////////////////////////////////////////////////////////////////////// proc dimH(int i,module M,int d) "USAGE: dimH(i,M,d); M module, i,d int ASSUME: @code{M} is graded, and it comes assigned with an admissible degree vector as an attribute, @code{h>=l}, and the basering @code{S} has @code{n+1} variables. RETURN: int, vector space dimension of @math{H^i(F(d))} for F the coherent sheaf on P^n associated to coker(M). NOTE: The procedure is based on local duality as described in [Eisenbud: Computing cohomology. In Vasconcelos: Computational methods in commutative algebra and algebraic geometry. Springer (1998)]. SEE ALSO: sheafCoh, sheafCohBGG EXAMPLE: example dimH; shows an example " { if( typeof(attrib(M,"isHomog"))=="string" ) { if (size(M)==0) { // assign weights 0 to generators of R^n (n=nrows(M)) intvec v; v[nrows(M)]=0; attrib(M,"isHomog",v); } else { ERROR("No admissible degree vector assigned"); } } int Result; int n=nvars(basering)-1; if ((i>0) and (i<=n)) { list L=Ext_R(n-i,M,1)[2]; def N=L[1]; return(dimGradedPart(N,-n-1-d)); } else { if (i==0) { list L=Ext_R(intvec(n+1,n+2),M,1)[2]; def N0=L[2]; def N1=L[1]; Result=dimGradedPart(M,d) - dimGradedPart(N0,-n-1-d) - dimGradedPart(N1,-n-1-d); return(Result); } else { return(0); } } } example {"EXAMPLE:"; echo = 2; ring R=0,(x,y,z,u),dp; resolution T1=mres(maxideal(1),0); module M=T1[3]; intvec v=2,2,2,2,2,2; attrib(M,"isHomog",v); dimH(0,M,2); dimH(1,M,0); dimH(2,M,1); dimH(3,M,-5); } /////////////////////////////////////////////////////////////////////////////// proc sheafCoh(module M,int l,int h,list #) "USAGE: sheafCoh(M,l,h); M module, l,h int ASSUME: @code{M} is graded, and it comes assigned with an admissible degree vector as an attribute, @code{h>=l}. The basering @code{S} has @code{n+1} variables. RETURN: intmat, cohomology of twists of the coherent sheaf F on P^n associated to coker(M). The range of twists is determined by @code{l}, @code{h}. DISPLAY: The intmat is displayed in a diagram of the following form: @* @format l l+1 h ---------------------------------------------------------- n: h^n(F(l)) h^n(F(l+1)) ...... h^n(F(h)) ............................................... 1: h^1(F(l)) h^1(F(l+1)) ...... h^1(F(h)) 0: h^0(F(l)) h^0(F(l+1)) ...... h^0(F(h)) ---------------------------------------------------------- chi: chi(F(l)) chi(F(l+1)) ...... chi(F(h)) @end format A @code{'-'} in the diagram refers to a zero entry. NOTE: The procedure is based on local duality as described in [Eisenbud: Computing cohomology. In Vasconcelos: Computational methods in commutative algebra and algebraic geometry. Springer (1998)].@* By default, the procedure uses @code{mres} to compute the Ext modules. If called with the additional parameter @code{\"sres\"}, the @code{sres} command is used instead. SEE ALSO: dimH, sheafCohBGG EXAMPLE: example sheafCoh; shows an example " { int use_sres; if( typeof(attrib(M,"isHomog"))!="intvec" ) { if (size(M)==0) { attrib(M,"isHomog",0); } else { ERROR("No admissible degree vector assigned"); } } if (size(#)>0) { if (#[1]=="sres") { use_sres=1; } } int i,j; module N,N0,N1; int n=nvars(basering)-1; intvec v=0..n+1; int col=h-l+1; intmat newBetti[n+1][col]; if (use_sres) { list L=Ext_R(v,M,1,"sres")[2]; } else { list L=Ext_R(v,M,1)[2]; } for (i=l; i<=h; i++) { N0=L[n+2]; N1=L[n+1]; newBetti[n+1,i-l+1]=dimGradedPart(M,i) - dimGradedPart(N0,-n-1-i) - dimGradedPart(N0,-n-1-i); } for (j=1; j<=n; j++) { N=L[j]; attrib(N,"isSB",1); if (dim(N)>=0) { for (i=l; i<=h; i++) { newBetti[j,i-l+1]=dimGradedPart(N,-n-1-i); } } } displayCohom(newBetti,l,h,n); return(newBetti); } example {"EXAMPLE:"; echo = 2; // // cohomology of structure sheaf on P^4: //------------------------------------------- ring r=0,x(1..5),dp; module M=0; def A=sheafCoh(0,-7,2); // // cohomology of cotangential bundle on P^3: //------------------------------------------- ring R=0,(x,y,z,u),dp; resolution T1=mres(maxideal(1),0); module M=T1[3]; intvec v=2,2,2,2,2,2; attrib(M,"isHomog",v); def B=sheafCoh(M,-6,2); } /////////////////////////////////////////////////////////////////////////////// proc displayCohom (intmat data, int l, int h, int n) "USAGE: displayCohom(data,l,h,n); data intmat, l,h,n int ASSUME: @code{h>=l}, @code{data} is the return value of @code{sheafCoh(M,l,h)} or of @code{sheafCohBGG(M,l,h)}, and the basering has @code{n+1} variables. RETURN: none NOTE: The intmat is displayed in a diagram of the following form: @* @format l l+1 h ---------------------------------------------------------- n: h^n(F(l)) h^n(F(l+1)) ...... h^n(F(h)) ............................................... 1: h^1(F(l)) h^1(F(l+1)) ...... h^1(F(h)) 0: h^0(F(l)) h^0(F(l+1)) ...... h^0(F(h)) ---------------------------------------------------------- chi: chi(F(l)) chi(F(l+1)) ...... chi(F(h)) @end format where @code{F} refers to the associated sheaf of @code{M} on P^n.@* A @code{'-'} in the diagram refers to a zero entry, a @code{'*'} refers to a negative entry (= dimension not yet determined). " { int i,j,k,dat,maxL; intvec notSumCol; notSumCol[h-l+1]=0; string s; maxL=4; for (i=1;i<=nrows(data);i++) { for (j=1;j<=ncols(data);j++) { if (size(string(data[i,j]))>=maxL-1) { maxL=size(string(data[i,j]))+2; } } } string Row=" "; string Row1="----"; for (i=l; i<=h; i++) { for (j=1; j<=maxL-size(string(i)); j++) { Row=Row+" "; } Row=Row+string(i); for (j=1; j<=maxL; j++) { Row1 = Row1+"-"; } } print(Row); print(Row1); for (j=1; j<=n+1; j++) { s = string(n+1-j); Row = ""; for(k=1; k<4-size(s); k++) { Row = Row+" "; } Row = Row + s+":"; for (i=0; i<=h-l; i++) { dat = data[j,i+1]; if (dat>0) { s = string(dat); } else { if (dat==0) { s="-"; } else { s="*"; notSumCol[i+1]=1; } } for(k=1; k<=maxL-size(s); k++) { Row = Row+" "; } Row = Row + s; } print(Row); } print(Row1); Row="chi:"; for (i=0; i<=h-l; i++) { dat = 0; if (notSumCol[i+1]==0) { for (j=0; j<=n; j++) { dat = dat + (-1)^j * data[n+1-j,i+1]; } s = string(dat); } else { s="*"; } for (k=1; k<=maxL-size(s); k++) { Row = Row+" "; } Row = Row + s; } print(Row); } /////////////////////////////////////////////////////////////////////////////// proc getStructureSheaf(list #) { if( size(#) == 0 ) { module M = 0; intvec v = 0; attrib(M,"isHomog",v); // homog(M); attrib(M, "isCoker", 1); // attrib(M); return(M); } if( typeof(#[1]) == "ideal") { ideal I = #[1]; if( size(#) == 2 ) { if( typeof(#[2]) == "int" ) { if( #[2] != 0 ) { qring @@@@QQ = std(I); module M = getStructureSheaf(); export M; // keepring @@@@QQ; // This is a bad idea... :(? return (@@@@QQ); } } } /* // This seems to be wrong!!! module M = I * gen(1); homog(M); M = modulo(gen(1), module(I * gen(1))); // basering^1 / I homog(M); attrib(M, "isCoker", 1); attrib(M); return(M); */ } ERROR("Wrong argument"); } example {"EXAMPLE:"; echo = 2; int pl = printlevel; printlevel = voice; //////////////////////////////////////////////////////////////////////////////// ring r; module M = getStructureSheaf(); "Basering: "; basering; "Module: ", string(M), ", grading is given by weights: ", attrib(M, "isHomog"); def A=sheafCohBGG2(M,-9,9); print(A); //////////////////////////////////////////////////////////////////////////////// setring r; module M = getStructureSheaf(ideal(var(1)), 0); "Basering: "; basering; "Module: ", string(M), ", grading is given by weights: ", attrib(M, "isHomog"); def A=sheafCohBGG2(M,-9,9); print(A); //////////////////////////////////////////////////////////////////////////////// setring r; def Q = getStructureSheaf(ideal(var(1)), 1); // returns a new ring! setring Q; // M was exported in the new ring! "Basering: "; basering; "Module: ", string(M), ", grading is given by weights: ", attrib(M, "isHomog"); def A=sheafCohBGG2(M,-9,9); print(A); printlevel = pl; } proc getCotangentialBundle() { resolution T1=mres(maxideal(1),3); module M=T1[3]; // attrib(M,"isHomog"); // homog(M); attrib(M, "isCoker", 1); // attrib(M); return (M); } proc getIdealSheafPullback(ideal I, ideal pi) { def save = basering; map P = save, pi; return( P(I) ); } // TODO: set attributes! proc getIdealSheaf(ideal I) { int i = homog(I); resolution FI = mres(I,2); // Syz + grading... module M = FI[2]; attrib(M, "isCoker", 1); // attrib(M); return(M); } /* Examples: --------- LIB "sheafcoh.lib"; ring S = 32003, x(0..4), dp; module MI=maxideal(1); attrib(MI,"isHomog",intvec(-1)); resolution kos = nres(MI,0); print(betti(kos),"betti"); LIB "random.lib"; matrix alpha0 = random(32002,10,3); module pres = module(alpha0)+kos[3]; attrib(pres,"isHomog",intvec(1,1,1,1,1,1,1,1,1,1)); resolution fcokernel = mres(pres,0); print(betti(fcokernel),"betti"); module dir = transpose(pres); attrib(dir,"isHomog",intvec(-1,-1,-1,-2,-2,-2, -2,-2,-2,-2,-2,-2,-2)); resolution fdir = mres(dir,2); print(betti(fdir),"betti"); ideal I = groebner(flatten(fdir[2])); resolution FI = mres(I,0); print(betti(FI),"betti"); module F=FI[2]; int t=timer; def A1=sheafCoh(F,-8,8); timer-t; t=timer; def A2=sheafCohBGG(F,-8,8); timer-t; LIB "sheafcoh.lib"; LIB "random.lib"; ring S = 32003, x(0..4), dp; resolution kos = nres(maxideal(1),0); betti(kos); matrix kos5 = kos[5]; matrix tphi = transpose(dsum(kos5,kos5)); matrix kos3 = kos[3]; matrix psi = dsum(kos3,kos3); matrix beta1 = random(32002,20,2); matrix tbeta1tilde = transpose(psi*beta1); matrix tbeta0 = lift(tphi,tbeta1tilde); matrix kos4 = kos[4]; matrix tkos4pluskos4 = transpose(dsum(kos4,kos4)); matrix tgammamin1 = random(32002,20,1); matrix tgamma0 = tkos4pluskos4*tgammamin1; matrix talpha0 = concat(tbeta0,tgamma0); matrix zero[20][1]; matrix tpsi = transpose(psi); matrix tpresg = concat(tpsi,zero); matrix pres = module(transpose(talpha0)) + module(transpose(tpresg)); module dir = transpose(pres); dir = prune(dir); homog(dir); intvec deg_dir = attrib(dir,"isHomog"); attrib(dir,"isHomog",deg_dir-2); // set degrees resolution fdir = mres(prune(dir),2); print(betti(fdir),"betti"); ideal I = groebner(flatten(fdir[2])); resolution FI = mres(I,0); module F=FI[2]; def A1=sheafCoh(F,-5,7); def A2=sheafCohBGG(F,-5,7); */ singular-4.0.3+ds/Singular/LIB/signcond.lib000066400000000000000000000240211266270727000204420ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////// version="version signcond.lib 4.0.0.0 Jun_2013 "; // $Id: 5d7118844e1de435273225d8cd9cb0962cb86d8e $ category="Symbolic-numerical solving"; info=" LIBRARY: signcond.lib Routines for computing realizable sign conditions AUTHOR: Enrique A. Tobis, etobis@dc.uba.ar OVERVIEW: Routines to determine the number of solutions of a multivariate polynomial system which satisfy a given sign configuration. REFERENCES: Basu, Pollack, Roy, \"Algorithms in Real Algebraic Geometry\", Springer, 2003. PROCEDURES: signcnd(P,I) The sign conditions realized by polynomials of P on a V(I) psigncnd(P,l) Pretty prints the output of signcnd (l) firstoct(I) The number of elements of V(I) with every coordinate > 0 KEYWORDS: real roots,sign conditions "; LIB "rootsmr.lib"; LIB "linalg.lib"; /////////////////////////////////////////////////////////////////////////////// proc firstoct(ideal I) "USAGE: firstoct(I); I ideal RETURN: number: the number of points of V(I) lying in the first octant ASSUME: I is given by a Groebner basis. SEE ALSO: signcnd EXAMPLE: example firstoct; shows an example" { ideal firstoctant; int j; list result; int n; if (isparam(I)) { ERROR("This procedure cannot operate with parametric arguments"); } for (j = nvars(basering);j > 0;j--) { firstoctant = firstoctant + var(j); } result = signcnd(firstoctant,I); list fst; for (j = nvars(basering);j > 0;j--) { fst[j] = 1; } n = isIn(fst,result[1]); if (n != -1) { return (result[2][n]); } else { return (0); } } example { echo = 2; ring r = 0,(x,y),dp; ideal i = (x-2)*(x+3)*x,y*(y-1); firstoct(i); } /////////////////////////////////////////////////////////////////////////////// proc signcnd(ideal P,ideal I) "USAGE: signcnd(P,I); ideal P,I RETURN: list: the sign conditions realized by the polynomials of P on V(I). The output of signcnd is a list of two lists. Both lists have the same length. This length is the number of sign conditions realized by the polynomials of P on the set V(i). Each element of the first list indicates a sign condition of the polynomials of P. Each element of the second list indicates how many elements of V(I) give rise to the sign condition expressed by the same position on the first list. See the example for further explanations of the output. ASSUME: I is a Groebner basis. NOTE: The procedure psigncnd performs some pretty printing of this output. SEE ALSO: firstoct, psigncnd EXAMPLE: example signcnd; shows an example" { ideal B; // Cumulative stuff matrix M; matrix SQs; matrix C; list Signs; list Exponents; // Used to store the precalculated SQs list SQvalues; list SQpositions; int i; // Variables for each step matrix Mi; matrix M3x3[3][3]; matrix M3x3inv[3][3]; // Constant matrices matrix c[3][1]; matrix sq[3][1]; int j; list exponentsi; list signi; int numberOfNonZero; if (isparam(P) || isparam(I)) { ERROR("This procedure cannot operate with parametric arguments"); } M3x3 = matrix(1,3,3); M3x3 = 1,1,1,0,1,-1,0,1,1; // The 3x3 matrix M3x3inv = inverse(M3x3); // First, we compute sturmquery(1,V(I)) I = groebner(I); B = qbase(I); sq[1,1] = sturmquery(1,B,I); // Number of real roots in V(I) SQvalues = SQvalues + list(sq[1,1]); SQpositions = SQpositions + list(1); // We initialize the cumulative variables M = matrix(1,1,1); Exponents = list(list()); Signs = list(list()); i = 1; while (i <= size(P)) { // for each poly in P sq[2,1] = sturmquery(P[i],B,I); sq[3,1] = sturmquery(P[i]^2,B,I); c = M3x3inv*sq; // We have to eliminate the 0 elements in c exponentsi = list(); signi = list(); // We determine the list of signs which correspond to a nonzero // number of roots numberOfNonZero = 3; if (c[1,1] != 0) { signi = list(0); } else { numberOfNonZero--; } if (c[2,1] != 0) { signi = signi + list(1); } else { numberOfNonZero--; } if (c[3,1] != 0) { signi = signi + list(-1); } else { numberOfNonZero--; } // We now determine the little matrix we'll work with, // and the list of exponents if (numberOfNonZero == 3) { Mi = M3x3; exponentsi = list(0,1,2); } else {if (numberOfNonZero == 2) { Mi = matrix(1,2,2); Mi[1,2] = 1; if (c[1,1] != 0 && c[2,1] != 0) { // 0,1 Mi[2,1] = 0; Mi[2,2] = 1; } else {if (c[1,1] != 0 && c[3,1] != 0) { // 0,-1 Mi[2,1] = 0; Mi[2,2] = -1; } else { // 1,-1 Mi[2,1] = 1; Mi[2,2] = -1; }} exponentsi = list(0,1); } else {if (numberOfNonZero == 1) { Mi = matrix(1,1,1); exponentsi = list(0); }}} // We store the Sturm Queries we'll need later if (numberOfNonZero == 2) { SQvalues = SQvalues + list(sq[2,1]); SQpositions = SQpositions + list(size(Exponents)+1); } else {if (numberOfNonZero == 3) { SQvalues = SQvalues + list(sq[2,1],sq[3,1]); SQpositions = SQpositions + list(size(Exponents)+1,size(Exponents)*2+1); }} // Now, we accumulate information M = tensor(Mi,M); Signs = expprod(Signs,signi); Exponents = expprod(Exponents,exponentsi); i++; } // At this point, we have the cumulative matrix, // the vector of exponents and the matching sign conditions. // We have to solve the big linear system to finish. M = inverse(M); // We have to compute the constants vector (the Sturm Queries) SQs = matrix(1,size(Exponents),1); j = 1; // We'll iterate over the presaved SQs for (i = 1;i <= size(Exponents);i++) { if (j <= size(SQvalues)) { if (SQpositions[j] == i) { SQs[i,1] = SQvalues[j]; j++; } else { SQs[i,1] = sturmquery(evalp(Exponents[i],P),B,I); } } else { SQs[i,1] = sturmquery(evalp(Exponents[i],P),B,I); } } C = M*SQs; list result; result[2] = list(); result[1] = list(); // We have to filter the 0 elements of C for (i = 1;i <= size(Signs);i++) { if (C[i,1] != 0) { result[1] = result[1] + list(Signs[i]); result[2] = result[2] + list(C[i,1]); } } return (result); } example { echo = 2; ring r = 0,(x,y),dp; ideal i = (x-2)*(x+3)*x,y*(y-1); ideal P = x,y; list l = signcnd(P,i); size(l[1]); // = the number of sign conditions of P on V(i) //Each element of l[1] indicates a sign condition of the polynomials of P. //The following means P[1] > 0, P[2] = 0: l[1][2]; //Each element of l[2] indicates how many elements of V(I) give rise to //the sign condition expressed by the same position on the first list. //The following means that exactly 1 element of V(I) gives rise to the //condition P[1] > 0, P[2] = 0: l[2][2]; } /////////////////////////////////////////////////////////////////////////////// proc psigncnd(ideal P,list l) "USAGE: psigncnd(P,l); ideal P, list l RETURN: list: a formatted version of l SEE ALSO: signcnd EXAMPLE: example psigncnd; shows an example" { string s; int n = size(l[1]); int i; for (i = 1;i <= n;i++) { s = s + string(l[2][i]) + " elements of V(I) satisfy " + psign(P,l[1][i]) + sprintf("%n",12); } return(s); } example { echo = 2; ring r = 0,(x,y),dp; ideal i = (x-2)*(x+3)*x,(y-1)*(y+2)*(y+4); ideal P = x,y; list l = signcnd(P,i); psigncnd(P,l); } /////////////////////////////////////////////////////////////////////////////// static proc psign(ideal P,list s) { int i; int n = size(P); string output; output = "{P[1]"; if (s[1] == -1) { output = output + " < 0"; } if (s[1] == 0) { output = output + " = 0"; } if (s[1] == 1) { output = output + " > 0"; } for (i = 2;i <= n;i++) { output = output + ","; output = output + "P[" + string(i) + "]"; if (s[i] == -1) { output = output + " < 0"; } if (s[i] == 0) { output = output + " = 0"; } if (s[i] == 1) { output = output + " > 0"; } } output = output + "}"; return (output); } /////////////////////////////////////////////////////////////////////////////// static proc isIn(list a,list b) //a is a list. b is a list of lists { int i,j; int found; found = 0; i = 1; while (i <= size(b) && !found) { j = 1; found = 1; if (size(a) != size(b[i])) { found = 0; } else { while(j <= size(a)) { found = found && a[j] == b[i][j]; j++; } } i++; } if (found) { return (i-1); } else { return (-1); } } /////////////////////////////////////////////////////////////////////////////// static proc expprod(list A,list B) // Computes the product of the list of lists A and the list B. { int i,j; list result; int la,lb; if (size(A) == 0) { A = list(list()); } la = size(A); lb = size(B); result[la*lb] = 0; for (i = 0;i < lb;i++) { for (j = 0;j < la;j++) { result[i*la+j+1] = A[j+1] + list(B[i+1]); } } return (result); } /////////////////////////////////////////////////////////////////////////////// static proc initlist(int n) // Returns an n-element list of 0s. { list l; int i; l[n] = 0; for (i = 1;i < n;i++) { l[i] = 0; } return(l); } /////////////////////////////////////////////////////////////////////////////// static proc evalp(list exp,ideal P) // Elevates each polynomial in P to the appropriate { int i; int n; poly result; n = size(exp); result = 1; for (i = 1;i <= n; i++) { result = result * (P[i]^exp[i]); } return (result); } /////////////////////////////////////////////////////////////////////////////// static proc incexp(list exp) { int k; k = 1; while (exp[k] == 2) { // We assume exp is not the last exponent (i.e. 2,...,2) exp[k] = 0; k++; } // exp[k] < 2 exp[k] = exp[k] + 1; return (exp); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/sing.lib000066400000000000000000001041231266270727000176000ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version sing.lib 4.0.0.0 Jun_2013 "; // $Id: 40709774f881e257950947e75efa72e9ffded150 $ category="Singularities"; info=" LIBRARY: sing.lib Invariants of Singularities AUTHORS: Gert-Martin Greuel, email: greuel@mathematik.uni-kl.de @* Bernd Martin, email: martin@math.tu-cottbus.de PROCEDURES: codim(id1, id2); vector space dimension of id2/id1 if finite deform(i); infinitesimal deformations of ideal i dim_slocus(i); dimension of singular locus of ideal i is_active(f,id); is polynomial f an active element mod id? (id ideal/module) is_ci(i); is ideal i a complete intersection? is_is(i); is ideal i an isolated singularity? is_reg(f,id); is polynomial f a regular element mod id? (id ideal/module) is_regs(i[,id]); are gen's of ideal i regular sequence modulo id? locstd(i); SB for local degree ordering without cancelling units milnor(i); milnor number of ideal i; (assume i is ICIS in nf) nf_icis(i); generic combinations of generators; get ICIS in nf slocus(i); ideal of singular locus of ideal i qhspectrum(f,w); spectrum numbers of w-homogeneous polynomial f Tjurina(i); SB of Tjurina module of ideal i (assume i is ICIS) tjurina(i); Tjurina number of ideal i (assume i is ICIS) T_1(i); T^1-module of ideal i T_2((i); T^2-module of ideal i T_12(i); T^1- and T^2-module of ideal i tangentcone(id); compute tangent cone of id "; LIB "inout.lib"; LIB "random.lib"; LIB "primdec.lib"; /////////////////////////////////////////////////////////////////////////////// proc deform (ideal id) "USAGE: deform(id); id=ideal or poly RETURN: matrix, columns are kbase of infinitesimal deformations EXAMPLE: example deform; shows an example " { list L=T_1(id,""); def K=L[1]; attrib(K,"isSB",1); return(L[2]*kbase(K)); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(x,y,z),ds; ideal i = xy,xz,yz; matrix T = deform(i); print(T); print(deform(x3+y5+z2)); } /////////////////////////////////////////////////////////////////////////////// proc dim_slocus (ideal i) "USAGE: dim_slocus(i); i ideal or poly RETURN: dimension of singular locus of i EXAMPLE: example dim_slocus; shows an example " { return(dim(std(slocus(i)))); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(x,y,z),ds; ideal i = x5+y6+z6,x2+2y2+3z2; dim_slocus(i); } /////////////////////////////////////////////////////////////////////////////// proc is_active (poly f,def id) "USAGE: is_active(f,id); f poly, id ideal or module RETURN: 1 if f is an active element modulo id (i.e. dim(id)=dim(id+f*R^n)+1, if id is a submodule of R^n) resp. 0 if f is not active. The basering may be a quotient ring NOTE: regular parameters are active but not vice versa (id may have embedded components). proc is_reg tests whether f is a regular parameter EXAMPLE: example is_active; shows an example " { if( size(id)==0 ) { return(1); } if( typeof(id)=="ideal" ) { ideal m=f; } if( typeof(id)=="module" ) { module m=f*freemodule(nrows(id)); } return(dim(std(id))-dim(std(id+m))); } example { "EXAMPLE:"; echo = 2; ring r =32003,(x,y,z),ds; ideal i = yx3+y,yz3+y3z; poly f = x; is_active(f,i); qring q = std(x4y5); poly f = x; module m = [yx3+x,yx3+y3x]; is_active(f,m); } /////////////////////////////////////////////////////////////////////////////// proc is_ci (ideal i) "USAGE: is_ci(i); i ideal RETURN: intvec = sequence of dimensions of ideals (j[1],...,j[k]), for k=1,...,size(j), where j is minimal base of i. i is a complete intersection if last number equals nvars-size(i) NOTE: dim(0-ideal) = -1. You may first apply simplify(i,10); in order to delete zeroes and multiples from set of generators printlevel >=0: display comments (default) EXAMPLE: example is_ci; shows an example " { int n; intvec dimvec; ideal id; i=minbase(i); int s = ncols(i); int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //--------------------------- compute dimensions ------------------------------ for( n=1; n<=s; n=n+1 ) { id = i[1..n]; dimvec[n] = dim(std(id)); } n = dimvec[s]; //--------------------------- output ------------------------------------------ if( n+s != nvars(basering) ) { dbprint(p,"// no complete intersection"); } if( n+s == nvars(basering) ) { dbprint(p,"// complete intersection of dim "+string(n)); } dbprint(p,"// dim-sequence:"); return(dimvec); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; // display comments ring r = 32003,(x,y,z),ds; ideal i = x4+y5+z6,xyz,yx2+xz2+zy7; is_ci(i); i = xy,yz; is_ci(i); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc is_is (ideal i) "USAGE: is_is(id); id ideal or poly RETURN: intvec = sequence of dimensions of singular loci of ideals generated by id[1]..id[i], k = 1..size(id); @* dim(0-ideal) = -1; id defines an isolated singularity if last number is 0 NOTE: printlevel >=0: display comments (default) EXAMPLE: example is_is; shows an example " { int l; intvec dims; ideal j; int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //--------------------------- compute dimensions ------------------------------ for( l=1; l<=ncols(i); l=l+1 ) { j = i[1..l]; dims[l] = dim(std(slocus(j))); } dbprint(p,"// dim of singular locus = "+string(dims[size(dims)]), "// isolated singularity if last number is 0 in dim-sequence:"); return(dims); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring r = 32003,(x,y,z),ds; ideal i = x2y,x4+y5+z6,yx2+xz2+zy7; is_is(i); poly f = xy+yz; is_is(f); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc is_reg (poly f,def id) "USAGE: is_reg(f,id); f poly, id ideal or module RETURN: 1 if multiplication with f is injective modulo id, 0 otherwise NOTE: Let R be the basering and id a submodule of R^n. The procedure checks injectivity of multiplication with f on R^n/id. The basering may be a quotient ring. EXAMPLE: example is_reg; shows an example " { if( f==0 ) { return(0); } int d,ii; def q = quotient(id,ideal(f)); id=std(id); d=size(q); for( ii=1; ii<=d; ii=ii+1 ) { if( reduce(q[ii],id)!=0 ) { return(0); } } return(1); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(x,y),ds; ideal i = x8,y8; ideal j = (x+y)^4; i = intersect(i,j); poly f = xy; is_reg(f,i); } /////////////////////////////////////////////////////////////////////////////// proc is_regs (ideal i, list #) "USAGE: is_regs(i[,id]); i poly, id ideal or module (default: id=0) RETURN: 1 if generators of i are a regular sequence modulo id, 0 otherwise NOTE: Let R be the basering and id a submodule of R^n. The procedure checks injectivity of multiplication with i[k] on R^n/id+i[1..k-1]. The basering may be a quotient ring. printlevel >=0: display comments (default) printlevel >=1: display comments during computation EXAMPLE: example is_regs; shows an example " { int d,ii,r; int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) if( size(#)==0 ) { ideal id; } else { def id=#[1]; } if( size(i)==0 ) { return(0); } d=size(i); if( typeof(id)=="ideal" ) { ideal m=1; } if( typeof(id)=="module" ) { module m=freemodule(nrows(id)); } for( ii=1; ii<=d; ii=ii+1 ) { if( p>=2 ) { "// checking whether element",ii,"is regular mod 1 ..",ii-1; } if( is_reg(i[ii],id)==0 ) { dbprint(p,"// elements 1.."+string(ii-1)+" are regular, " + string(ii)+" is not regular mod 1.."+string(ii-1)); return(0); } id=id+i[ii]*m; } if( p>=1 ) { "// elements are a regular sequence of length",d; } return(1); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring r1 = 32003,(x,y,z),ds; ideal i = x8,y8,(x+y)^4; is_regs(i); module m = [x,0,y]; i = x8,(x+z)^4;; is_regs(i,m); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc milnor (ideal i) "USAGE: milnor(i); i ideal or poly RETURN: Milnor number of i, if i is ICIS (isolated complete intersection singularity) in generic form, resp. -1 if not NOTE: use proc nf_icis to put generators in generic form printlevel >=1: display comments EXAMPLE: example milnor; shows an example " { i = simplify(i,10); //delete zeroes and multiples from set of generators int n = size(i); int l,q,m_nr; ideal t; intvec disc; int p = printlevel-voice+2; // p=printlevel+1 (default: p=0) //---------------------------- hypersurface case ------------------------------ if( n==1 or n==0 ) { i = std(jacob(i[1])); m_nr = vdim(i); if( m_nr<0 and p>=1 ) { "// Milnor number is infinite"; } return(m_nr); } //------------ isolated complete intersection singularity (ICIS) -------------- for( l=n; l>0; l=l-1) { t = minor(jacob(i),l); i[l] = 0; q = vdim(std(i+t)); disc[l]= q; if( q ==-1 ) { if( p>=1 ) { "// not in generic form or no ICIS; use proc nf_icis to put"; "// generators in generic form and then try milnor again!"; } return(q); } m_nr = q-m_nr; } //---------------------------- change sign ------------------------------------ if (m_nr < 0) { m_nr=-m_nr; } if( p>=1 ) { "//sequence of discriminant numbers:",disc; } return(m_nr); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 2; ring r = 32003,(x,y,z),ds; ideal j = x5+y6+z6,x2+2y2+3z2,xyz+yx; milnor(j); poly f = x7+y7+(x-y)^2*x2y2+z2; milnor(f); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc nf_icis (ideal i) "USAGE: nf_icis(i); i ideal RETURN: ideal = generic linear combination of generators of i if i is an ICIS (isolated complete intersection singularity), return i if not NOTE: this proc is useful in connection with proc milnor printlevel >=0: display comments (default) EXAMPLE: example nf_icis; shows an example " { i = simplify(i,10); //delete zeroes and multiples from set of generators int p,b = 100,0; int n = size(i); matrix mat=freemodule(n); int P = printlevel-voice+3; // P=printlevel+1 (default: P=1) //---------------------------- test: complete intersection? ------------------- intvec sl = is_ci(i); if( n+sl[n] != nvars(basering) ) { dbprint(P,"// no complete intersection"); return(i); } //--------------- test: isolated singularity in generic form? ----------------- sl = is_is(i); if ( sl[n] != 0 ) { dbprint(P,"// no isolated singularity"); return(i); } //------------ produce generic linear combinations of generators -------------- int prob; while ( sum(sl) != 0 ) { prob=prob+1; p=p-25; b=b+10; i = genericid(i,p,b); // proc genericid from random.lib sl = is_is(i); } dbprint(P,"// ICIS in generic form after "+string(prob)+" genericity loop(s)"); return(i); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring r = 32003,(x,y,z),ds; ideal i = x3+y4,z4+yx; nf_icis(i); ideal j = x3+y4,xy,yz; nf_icis(j); printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc slocus(ideal i) "USAGE: slocus(i); i ideal RETURN: ideal of singular locus of i. Quotient rings and rings with integer coefficients are currently not supported. EXAMPLE: example slocus; shows an example " { // quotient rings currently not supported ASSUME( 0, 0==isQuotientRing(basering) ); // integer coefficient rings currently not supported ASSUME( 0, hasFieldCoefficient(basering) ); def R=basering; int j,k; ideal res; if(ord_test(basering)!=1) { string va=varstr(basering); if( size( parstr(basering))>0){va=va+","+parstr(basering);} execute ("ring S = ("+charstr(basering)+"),("+va+"),dp;"); ideal i=imap(R,i); list l=equidim(i); setring R; list l=imap(S,l); } else { list l=equidim(i); } int n=size(l); if (n==1){return(slocusEqi(i));} res=slocusEqi(l[1]); for(j=2;j<=n;j++){res=intersect(res,slocusEqi(l[j]));} for(j=1;j]); id=ideal or poly ASSUME: id=ICIS (isolated complete intersection singularity) RETURN: standard basis of Tjurina-module of id, of type module if id=ideal, resp. of type ideal if id=poly. If a second argument is present (of any type) return a list: @* [1] = Tjurina number, [2] = k-basis of miniversal deformation, [3] = SB of Tjurina module, [4] = Tjurina module DISPLAY: Tjurina number if printlevel >= 0 (default) NOTE: Tjurina number = -1 implies that id is not an ICIS EXAMPLE: example Tjurina; shows examples " { //---------------------------- initialisation --------------------------------- def i = simplify(id,10); int tau,n = 0,size(i); if( size(ideal(i))==1 ) { def m=i; } // hypersurface case else { def m=i*freemodule(n); } // complete intersection case //--------------- compute Tjurina module, Tjurina number etc ------------------ def t1 = jacob(i)+m; // Tjurina module/ideal def st1 = std(t1); // SB of Tjurina module/ideal tau = vdim(st1); // Tjurina number dbprint(printlevel-voice+3,"// Tjurina number = "+string(tau)); if( size(#)>0 ) { def kB = kbase(st1); // basis of miniversal deformation return(tau,kB,st1,t1); } return(st1); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring r = 0,(x,y,z),ds; poly f = x5+y6+z7+xyz; // singularity T[5,6,7] list T = Tjurina(f,""); show(T[1]); // Tjurina number, should be 16 show(T[2]); // basis of miniversal deformation show(T[3]); // SB of Tjurina ideal show(T[4]); ""; // Tjurina ideal ideal j = x2+y2+z2,x2+2y2+3z2; show(kbase(Tjurina(j))); // basis of miniversal deformation hilb(Tjurina(j)); // Hilbert series of Tjurina module printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc tjurina (ideal i) "USAGE: tjurina(id); id=ideal or poly ASSUME: id=ICIS (isolated complete intersection singularity) RETURN: int = Tjurina number of id NOTE: Tjurina number = -1 implies that id is not an ICIS EXAMPLE: example tjurina; shows an example " { return(vdim(Tjurina(i))); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x,y,z),(c,ds); ideal j=x2+y2+z2,x2+2y2+3z2; tjurina(j); } /////////////////////////////////////////////////////////////////////////////// proc T_1 (ideal id, list #) "USAGE: T_1(id[,]); id = ideal or poly RETURN: T_1(id): of type module/ideal if id is of type ideal/poly. We call T_1(id) the T_1-module of id. It is a std basis of the presentation of 1st order deformations of P/id, if P is the basering. If a second argument is present (of any type) return a list of 3 modules: [1]= T_1(id) [2]= generators of normal bundle of id, lifted to P [3]= module of relations of [2], lifted to P (note: transpose[3]*[2]=0 mod id) The list contains all non-easy objects which must be computed to get T_1(id). DISPLAY: k-dimension of T_1(id) if printlevel >= 0 (default) NOTE: T_1(id) itself is usually of minor importance. Nevertheless, from it all relevant information can be obtained. The most important are probably vdim(T_1(id)); (which computes the Tjurina number), hilb(T_1(id)); and kbase(T_1(id)). If T_1 is called with two arguments, then matrix([2])*(kbase([1])) represents a basis of 1st order semiuniversal deformation of id (use proc 'deform', to get this in a direct way). For a complete intersection the proc Tjurina is faster. EXAMPLE: example T_1; shows an example " { def RR=basering; list RRL=ringlist(RR); if(RRL[4]!=0) { int aa=size(#); ideal QU=RRL[4]; RRL[4]=ideal(0); def RS=ring(RRL); setring RS; ideal id=imap(RR,id); ideal QU=imap(RR,QU); if(aa) { list RES=T_1(id+QU,1); } else { module RES=T_1(id+QU); } setring RR; def RES=imap(RS,RES); return(RES); } ideal J=simplify(id,10); //--------------------------- hypersurface case ------------------------------- if( size(J)<2 ) { ideal t1 = std(J+jacob(J[1])); module nb = [1]; module pnb; dbprint(printlevel-voice+3,"// dim T_1 = "+string(vdim(t1))); if( size(#)>0 ) { module st1 = t1*gen(1); attrib(st1,"isSB",1); return(st1,nb,pnb); } return(t1); } //--------------------------- presentation of J ------------------------------- int rk; def P = basering; module jac, t1; jac = jacob(J); // jacobian matrix of J converted to module list A=nres(J,2); // compute presentation of J def A(1..2)=A[1..2]; kill A; // A(2) = 1st syzygy module of J //---------- go to quotient ring mod J and compute normal bundle -------------- qring R = std(J); module jac = fetch(P,jac); module t1 = transpose(fetch(P,A(2))); list B=nres(t1,2); // resolve t1, B(2)=(J/J^2)*=normal_bdl def B(1..2)=B[1..2]; kill B; t1 = modulo(B(2),jac); // pres. of normal_bdl/trivial_deformations rk=nrows(t1); //-------------------------- pull back to basering ---------------------------- setring P; t1 = fetch(R,t1)+J*freemodule(rk); // T_1-module, presentation of T_1 t1 = std(t1); dbprint(printlevel-voice+3,"// dim T_1 = "+string(vdim(t1))); if( size(#)>0 ) { module B2 = fetch(R,B(2)); // presentation of normal bundle list L = t1,B2,A(2); attrib(L[1],"isSB",1); return(L); } return(t1); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring r = 32003,(x,y,z),(c,ds); ideal i = xy,xz,yz; module T = T_1(i); vdim(T); // Tjurina number = dim_K(T_1), should be 3 list L=T_1(i,""); module kB = kbase(L[1]); print(L[2]*kB); // basis of 1st order miniversal deformation show(L[2]); // presentation of normal bundle print(L[3]); // relations of i print(transpose(L[3])*L[2]); // should be 0 (mod i) printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc T_2 (ideal id, list #) "USAGE: T_2(id[,]); id = ideal RETURN: T_2(id): T_2-module of id . This is a std basis of a presentation of the module of obstructions of R=P/id, if P is the basering. If a second argument is present (of any type) return a list of 4 modules and 1 ideal: [1]= T_2(id) [2]= standard basis of id (ideal) [3]= module of relations of id (=1st syzygy module of id) @* [4]= presentation of syz/kos [5]= relations of Hom_P([3]/kos,R), lifted to P The list contains all non-easy objects which must be computed to get T_2(id). DISPLAY: k-dimension of T_2(id) if printlevel >= 0 (default) NOTE: The most important information is probably vdim(T_2(id)). Use proc miniversal to get equations of the miniversal deformation. EXAMPLE: example T_2; shows an example " { def RR=basering; list RRL=ringlist(RR); if(RRL[4]!=0) { int aa=size(#); ideal QU=RRL[4]; RRL[4]=ideal(0); def RS=ring(RRL); setring RS; ideal id=imap(RR,id); ideal QU=imap(RR,QU); if(aa) { list RES=T_2(id+QU,1); } else { module RES=T_2(id+QU); } setring RR; def RES=imap(RS,RES); return(RES); } //--------------------------- initialisation ---------------------------------- def P = basering; ideal J = id; module kos,SK,B2,t2; list L; int n,rk; //------------------- presentation of non-trivial syzygies -------------------- list A=nres(J,2); // resolve J, A(2)=syz def A(1..2)=A[1..2]; kill A; kos = koszul(2,J); // module of Koszul relations SK = modulo(A(2),kos); // presentation of syz/kos ideal J0 = std(J); // standard basis of J //?*** sollte bei der Berechnung von res mit anfallen, zu aendern!! //---------------------- fetch to quotient ring mod J ------------------------- qring R = J0; // make P/J the basering module A2' = transpose(fetch(P,A(2))); // dual of syz module t2 = transpose(fetch(P,SK)); // dual of syz/kos list B=nres(t2,2); // resolve (syz/kos)* def B(1..2)=B[1..2]; kill B; t2 = modulo(B(2),A2'); // presentation of T_2 rk = nrows(t2); //--------------------- fetch back to basering ------------------------------- setring P; t2 = fetch(R,t2)+J*freemodule(rk); t2 = std(t2); dbprint(printlevel-voice+3,"// dim T_2 = "+string(vdim(t2))); if( size(#)>0 ) { B2 = fetch(R,B(2)); // generators of Hom_P(syz/kos,R) L = t2,J0,A(2),SK,B2; return(L); } return(t2); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring r = 32003,(x,y),(c,dp); ideal j = x6-y4,x6y6,x2y4-x5y2; module T = T_2(j); vdim(T); hilb(T);""; ring r1 = 0,(x,y,z),dp; ideal id = xy,xz,yz; list L = T_2(id,""); vdim(L[1]); // vdim of T_2 print(L[3]); // syzygy module of id printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc T_12 (ideal i, list #) "USAGE: T_12(i[,any]); i = ideal RETURN: T_12(i): list of 2 modules: @* * standard basis of T_1-module =T_1(i), 1st order deformations @* * standard basis of T_2-module =T_2(i), obstructions of R=P/i @* If a second argument is present (of any type) return a list of 9 modules, matrices, integers: @* [1]= standard basis of T_1-module [2]= standard basis of T_2-module [3]= vdim of T_1 [4]= vdim of T_2 [5]= matrix, whose cols present infinitesimal deformations @* [6]= matrix, whose cols are generators of relations of i(=syz(i)) @* [7]= matrix, presenting Hom_P(syz/kos,R), lifted to P @* [8]= presentation of T_1-module, no std basis [9]= presentation of T_2-module, no std basis DISPLAY: k-dimension of T_1 and T_2 if printlevel >= 0 (default) NOTE: Use proc miniversal from deform.lib to get miniversal deformation of i, the list contains all objects used by proc miniversal. EXAMPLE: example T_12; shows an example " { def RR=basering; list RRL=ringlist(RR); if(RRL[4]!=0) { int aa=size(#); ideal QU=RRL[4]; RRL[4]=ideal(0); def RS=ring(RRL); setring RS; ideal id=imap(RR,id); ideal QU=imap(RR,QU); if(aa) { list RES=T_12(id+QU,1); } else { list RES=T_12(id+QU); } setring RR; list RES=imap(RS,RES); return(RES); } //--------------------------- initialisation ---------------------------------- int n,r1,r2,d1,d2; def P = basering; i = simplify(i,10); module jac,t1,t2,sbt1,sbt2; matrix Kos,Syz,SK,kbT_1,Sx; list L; ideal i0 = std(i); //-------------------- presentation of non-trivial syzygies ------------------- list I= nres(i,2); // resolve i Syz = matrix(I[2]); // syz(i) jac = jacob(i); // jacobi ideal Kos = koszul(2,i); // koszul-relations SK = modulo(Syz,Kos); // presentation of syz/kos //--------------------- fetch to quotient ring mod i ------------------------- qring Ox = i0; // make P/i the basering module Jac = fetch(P,jac); matrix No = transpose(fetch(P,Syz)); // ker(No) = Hom(syz,Ox) module So = transpose(fetch(P,SK)); // Hom(syz/kos,R) list resS = nres(So,2); matrix Sx = resS[2]; list resN = nres(No,2); matrix Nx = resN[2]; module T_2 = modulo(Sx,No); // presentation of T_2 r2 = nrows(T_2); module T_1 = modulo(Nx,Jac); // presentation of T_1 r1 = nrows(T_1); //------------------------ pull back to basering ------------------------------ setring P; t1 = fetch(Ox,T_1)+i*freemodule(r1); t2 = fetch(Ox,T_2)+i*freemodule(r2); sbt1 = std(t1); d1 = vdim(sbt1); sbt2 = std(t2); d2 = vdim(sbt2); dbprint(printlevel-voice+3,"// dim T_1 = "+string(d1),"// dim T_2 = "+string(d2)); if ( size(#)>0) { if (d1>0) { kbT_1 = fetch(Ox,Nx)*kbase(sbt1); } else { kbT_1 = 0; } Sx = fetch(Ox,Sx); L = sbt1,sbt2,d1,d2,kbT_1,Syz,Sx,t1,t2; return(L); } L = sbt1,sbt2; return(L); } example { "EXAMPLE:"; echo = 2; int p = printlevel; printlevel = 1; ring r = 199,(x,y,z,u,v),(c,ws(4,3,2,3,4)); ideal i = xz-y2,yz2-xu,xv-yzu,yu-z3,z2u-yv,zv-u2; //a cyclic quotient singularity list L = T_12(i,1); print(L[5]); //matrix of infin. deformations printlevel = p; } /////////////////////////////////////////////////////////////////////////////// proc codim (def id1,def id2) "USAGE: codim(id1,id2); id1,id2 ideal or module, both must be standard bases RETURN: int, which is: 1. the vectorspace dimension of id1/id2 if id2 is contained in id1 and if this number is finite@* 2. -1 if the dimension of id1/id2 is infinite@* 3. -2 if id2 is not contained in id1 COMPUTE: consider the Hilbert series iv1(t) of id1 and iv2(t) of id2. If codim(id1,id2) is finite, q(t)=(iv2(t)-iv1(t))/(1-t)^n is rational, and the codimension is the sum of the coefficients of q(t) (n = dimension of basering). EXAMPLE: example codim; shows an example " { if (attrib(id1,"isSB")!=1) { "first argument of codim is not a SB";} if (attrib(id2,"isSB")!=1) { "second argument of codim is not a SB";} intvec iv1, iv2, iv; int i, d1, d2, dd, i1, i2, ia, ie; //--------------------------- check id2 < id1 ------------------------------- ideal led = lead(id1); attrib(led, "isSB",1); i = size(NF(lead(id2),led)); if ( i > 0 ) { return(-2); } //--------------------------- 1. check finiteness --------------------------- i1 = dim(id1); i2 = dim(id2); if (i1 < 0) { if ( i2 < 0 ) { return(0); } if (i2 == 0) { return (vdim(id2)); } else { return(-1); } } if (i2 != i1) { return(-1); } if (i2 <= 0) { return(vdim(id2)-vdim(id1)); } // if (mult(id2) != mult(id1)) //{ // return(-1); // } //--------------------------- module --------------------------------------- d1 = nrows(id1); d2 = nrows(id2); dd = 0; if (d1 > d2) { id2=id2,maxideal(1)*gen(d1); dd = -1; } if (d2 > d1) { id1=id1,maxideal(1)*gen(d2); dd = 1; } //--------------------------- compute first hilbertseries ------------------ iv1 = hilb(id1,1); i1 = size(iv1); iv2 = hilb(id2,1); i2 = size(iv2); //--------------------------- difference of hilbertseries ------------------ if (i2 > i1) { for ( i=1; i<=i1; i=i+1) { iv2[i] = iv2[i]-iv1[i]; } ie = i2; iv = iv2; } else { for ( i=1; i<=i2; i=i+1) { iv1[i] = iv2[i]-iv1[i]; } iv = iv1; for (ie=i1;ie>=0;ie=ie-1) { if (ie == 0) { return(0); } if (iv[ie] != 0) { break; } } } ia = 1; while (iv[ia] == 0) { ia=ia+1; } //--------------------------- ia <= nonzeros <= ie ------------------------- iv1 = iv[ia]; for(i=ia+1;i<=ie;i=i+1) { iv1=iv1,iv[i]; } //--------------------------- compute second hilbertseries ----------------- iv2 = hilb(iv1); //--------------------------- check finitenes ------------------------------ i2 = size(iv2); i1 = ie - ia + 1 - i2; if (i1 != nvars(basering)) { return(-1); } //--------------------------- compute result ------------------------------- i1 = 0; for ( i=1; i<=i2; i=i+1) { i1 = i1 + iv2[i]; } return(i1+dd); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; ideal j = y6,x4; ideal m = x,y; attrib(m,"isSB",1); //let Singular know that ideals are a standard basis attrib(j,"isSB",1); codim(m,j); // should be 23 (Milnor number -1 of y7-x5) } /////////////////////////////////////////////////////////////////////////////// proc tangentcone (def id,list #) "USAGE: tangentcone(id [,n]); id = ideal, n = int RETURN: the tangent cone of id NOTE: The procedure works for any monomial ordering. If n=0 use std w.r.t. local ordering ds, if n=1 use locstd. EXAMPLE: example tangentcone; shows an example " { int ii,n; def bas = basering; ideal tang; if (size(#) !=0) { n= #[1]; } if( n==0 ) { def @newr@=changeord(list(list("ds",1:nvars(basering)))); setring @newr@; ideal @id = imap(bas,id); @id = std(@id); setring bas; id = imap(@newr@,@id); kill @newr@; } else { id = locstd(id); } for(ii=1; ii<=size(id); ii++) { tang[ii]=jet(id[ii],mindeg(id[ii])); } return(tang); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),ds; ideal i = 7xyz+z5,x2+y3+z7,5z5+y5; tangentcone(i); } /////////////////////////////////////////////////////////////////////////////// proc locstd (def id) "USAGE: locstd (id); id = ideal RETURN: a standard basis for a local degree ordering NOTE: the procedure homogenizes id w.r.t. a new 1st variable @t@, computes a SB w.r.t. (dp(1),dp) and substitutes @t@ by 1. Hence the result is a SB with respect to an ordering which sorts first w.r.t. the order and then refines it with dp. This is a local degree ordering. This is done in order to avoid cancellation of units and thus be able to use option(contentSB); EXAMPLE: example locstd; shows an example " { int ii; def bas = basering; execute("ring @r_locstd =("+charstr(bas)+"),(@t@,"+varstr(bas)+"),(dp(1),dp);"); ideal @id = imap(bas,id); ideal @hid = homog(@id,@t@); @hid = std(@hid); @hid = subst(@hid,@t@,1); setring bas; def @hid = imap(@r_locstd,@hid); attrib(@hid,"isSB",1); kill @r_locstd; return(@hid); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),ds; ideal i = xyz+z5,2x2+y3+z7,3z5+y5; locstd(i); } singular-4.0.3+ds/Singular/LIB/sing4ti2.lib000066400000000000000000000321411266270727000203030ustar00rootroot00000000000000/////////////////////////////////////////////////////////////// version="version sing4ti2.lib 4.0.0.0 Jun_2013 "; // $Id: 4c5fdd58e77e766b35c586fa6765e7a9fde9a64f $ category="Commutative Algebra"; info=" LIBRARY: sing4ti2.lib Communication Interface to 4ti2 AUTHORS: Thomas Kahle , kahle@mis.mpg.de @* Anne Fruehbis-Krueger, anne@math.uni-hannover.de NOTE: This library uses the external program 4ti2 for calculations @* and the standard unix tools sed and awk for conversion of @* the returned result PROCEDURES: markov4ti2(A[,i]) compute Markov basis of given lattice hilbert4ti2(A[,i]) compute Hilbert basis of given lattice graver4ti2(A[,i]) compute Graver basis of given lattice "; proc markov4ti2(matrix A, list #) "USAGE: markov4ti2(A[,i]); @* A=intmat @* i=int ASSUME: - A is a matrix with integer entries which describes the lattice @* as ker(A), if second argument is not present, @* as left image Im(A) = {zA, z \in ZZ^k}(!), if second argument is a positive integer @* - number of variables of basering equals number of columns of A @* (for ker(A)) resp. of rows of A (for Im(A)) CREATE: files sing4ti2.mat, sing4ti2.lat, sing4ti2.mar in the current @* directory (I/O files for communication with 4ti2) NOTE: input rules for 4ti2 also apply to input to this procedure @* hence ker(A)={x|Ax=0} and Im(A)={xA} RETURN: toric ideal specified by Markov basis thereof EXAMPLE: example markov4ti2; shows an example " { //-------------------------------------------------------------------------- // Initialization and Sanity Checks //-------------------------------------------------------------------------- int i,j; int nr=nrows(A); int nc=ncols(A); string fileending="mat"; if (size(#)!=0) { //--- default behaviour: use ker(A) as lattice //--- if #[1]!=0 use Im(A) as lattice if(typeof(#[1])!="int") { ERROR("optional parameter needs to be integer value");\ } if(#[1]!=0) { fileending="lat"; } } //--- we should also be checking whether all entries are indeed integers //--- or whether there are fractions, but in this case the error message //--- of 4ti2 is printed directly if(nvars(basering)!=ncols(A)) { ERROR("number of columns needs to match number of variables"); } //-------------------------------------------------------------------------- // preparing input file for 4ti2 //-------------------------------------------------------------------------- link eing=":w sing4ti2."+fileending; string eingstring=string(nr)+" "+string(nc); write(eing,eingstring); for(i=1;i<=nr;i++) { kill eingstring; string eingstring; for(j=1;j<=nc;j++) { if((deg(A[i,j])>0)||(char(basering)!=0)||(npars(basering)>0)) { ERROR("Input to markov4ti2 needs to be a matrix with integer entries"); } eingstring=eingstring+string(A[i,j])+" "; } write(eing, eingstring); } close(eing); //---------------------------------------------------------------------- // calling 4ti2 and converting output // Singular's string is too clumsy for this, hence we first prepare // using standard unix commands //---------------------------------------------------------------------- j=system("sh","markov sing4ti2 >/dev/null 2>&1"); j=system("sh","awk \'BEGIN{ORS=\",\";}{print $0;}\' sing4ti2.mar | sed s/[\\\ \\\t\\\v\\\f]/,/g | sed s/,+/,/g|sed s/,,/,/g|sed s/,,/,/g > sing4ti2.converted"); if(!defined(keepfiles)) { j=system("sh",("rm -f sing4ti2.mar sing4ti2."+fileending)); } //---------------------------------------------------------------------- // reading output of 4ti2 //---------------------------------------------------------------------- link ausg=":r sing4ti2.converted"; //--- last entry ideal(0) is used to tie the list to the basering //--- it will not be processed any further string ergstr="list erglist="+read(ausg)+ string(ideal(0))+";"; execute(ergstr); ideal toric; poly temppol1,temppol2; for(i=1;i<=erglist[1];i++) { temppol1=1; temppol2=1; for(j=1;j<=erglist[2];j++) { if(erglist[2+(i-1)*erglist[2]+j]>=0) { //--- positive exponents temppol1=temppol1*(var(j)^erglist[2+(i-1)*erglist[2]+j]); } else { //--- negative exponents temppol2=temppol2*(var(j)^(-erglist[2+(i-1)*erglist[2]+j])); } } toric=toric,temppol1-temppol2; } //--- get rid of leading entry 0; toric=toric[2..ncols(toric)]; return(toric); } example {"EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; matrix M[2][3]=0,1,2,2,1,0; markov4ti2(M); matrix N[1][3]=1,2,1; markov4ti2(N,1); } /////////////////////////////////////////////////////////////////////////////// proc graver4ti2(matrix A, list #) "USAGE: graver4ti2(A[,i]); @* A=intmat @* i=int ASSUME: - A is a matrix with integer entries which describes the lattice @* as ker(A), if second argument is not present, @* as the left image Im(A) = {zA : z \in ZZ^k}, if second argument is a positive integer @* - number of variables of basering equals number of columns of A @* (for ker(A)) resp. of rows of A (for Im(A)) CREATE: temporary files sing4ti2.mat, sing4ti2.lat, sing4ti2.gra @* in the current directory (I/O files for communication with 4ti2) NOTE: input rules for 4ti2 also apply to input to this procedure @* hence ker(A)={x|Ax=0} and Im(A)={xA} RETURN: toric ideal specified by Graver basis thereof EXAMPLE: example graver4ti2; shows an example " { //-------------------------------------------------------------------------- // Initialization and Sanity Checks //-------------------------------------------------------------------------- int i,j; int nr=nrows(A); int nc=ncols(A); string fileending="mat"; if (size(#)!=0) { //--- default behaviour: use ker(A) as lattice //--- if #[1]!=0 use Im(A) as lattice if(typeof(#[1])!="int") { ERROR("optional parameter needs to be integer value");\ } if(#[1]!=0) { fileending="lat"; } } //--- we should also be checking whether all entries are indeed integers //--- or whether there are fractions, but in this case the error message //--- of 4ti2 is printed directly if(nvars(basering)!=ncols(A)) { ERROR("number of columns needs to match number of variables"); } //-------------------------------------------------------------------------- // preparing input file for 4ti2 //-------------------------------------------------------------------------- link eing=":w sing4ti2."+fileending; string eingstring=string(nr)+" "+string(nc); write(eing,eingstring); for(i=1;i<=nr;i++) { kill eingstring; string eingstring; for(j=1;j<=nc;j++) { if((deg(A[i,j])>0)||(char(basering)!=0)||(npars(basering)>0)) { ERROR("Input to graver4ti2 needs to be a matrix with integer entries"); } eingstring=eingstring+string(A[i,j])+" "; } write(eing, eingstring); } close(eing); //---------------------------------------------------------------------- // calling 4ti2 and converting output // Singular's string is too clumsy for this, hence we first prepare // using standard unix commands //---------------------------------------------------------------------- j=system("sh","graver sing4ti2 >/dev/null 2>&1"); j=system("sh","awk \'BEGIN{ORS=\",\";}{print $0;}\' sing4ti2.gra | sed s/[\\\ \\\t\\\v\\\f]/,/g | sed s/,+/,/g |sed s/,,/,/g|sed s/,,/,/g > sing4ti2.converted"); if(!defined(keepfiles)) { j=system("sh",("rm -f sing4ti2.gra sing4ti2."+fileending)); } //---------------------------------------------------------------------- // reading output of 4ti2 //---------------------------------------------------------------------- link ausg=":r sing4ti2.converted"; //--- last entry ideal(0) is used to tie the list to the basering //--- it will not be processed any further string ergstr="list erglist="+read(ausg)+ string(ideal(0))+";"; execute(ergstr); ideal toric; poly temppol1,temppol2; for(i=1;i<=erglist[1];i++) { temppol1=1; temppol2=1; for(j=1;j<=erglist[2];j++) { if(erglist[2+(i-1)*erglist[2]+j]>=0) { //--- positive exponents temppol1=temppol1*(var(j)^erglist[2+(i-1)*erglist[2]+j]); } else { //--- negative exponents temppol2=temppol2*(var(j)^(-erglist[2+(i-1)*erglist[2]+j])); } } toric=toric,temppol1-temppol2; } //--- get rid of leading entry 0; toric=toric[2..ncols(toric)]; return(toric); } example {"EXAMPLE:"; echo=2; ring r=0,(x,y,z,w),dp; matrix M[2][4]=0,1,2,3,3,2,1,0; graver4ti2(M); } /////////////////////////////////////////////////////////////////////////////// proc hilbert4ti2(matrix A, list #) "USAGE: hilbert4ti2(A[,i]); @* A=intmat @* i=int ASSUME: - A is a matrix with integer entries which describes the lattice @* as ker(A), if second argument is not present, @* as the left image Im(A) = {zA : z \in ZZ^k}, if second argument is a positive integer @* - number of variables of basering equals number of columns of A @* (for ker(A)) resp. of rows of A (for Im(A)) CREATE: temporary files sing4ti2.mat, sing4ti2.lat, sing4ti2.mar @* in the current directory (I/O files for communication with 4ti2) NOTE: input rules for 4ti2 also apply to input to this procedure @* hence ker(A)={x|Ax=0} and Im(A)={xA} RETURN: toric ideal specified by Hilbert basis thereof EXAMPLE: example graver4ti2; shows an example " { //-------------------------------------------------------------------------- // Initialization and Sanity Checks //-------------------------------------------------------------------------- int i,j; int nr=nrows(A); int nc=ncols(A); string fileending="mat"; if (size(#)!=0) { //--- default behaviour: use ker(A) as lattice //--- if #[1]!=0 use Im(A) as lattice if(typeof(#[1])!="int") { ERROR("optional parameter needs to be integer value");\ } if(#[1]!=0) { fileending="lat"; } } //--- we should also be checking whether all entries are indeed integers //--- or whether there are fractions, but in this case the error message //--- of 4ti2 is printed directly if(nvars(basering)!=ncols(A)) { ERROR("number of columns needs to match number of variables"); } //-------------------------------------------------------------------------- // preparing input file for 4ti2 //-------------------------------------------------------------------------- link eing=":w sing4ti2."+fileending; string eingstring=string(nr)+" "+string(nc); write(eing,eingstring); for(i=1;i<=nr;i++) { kill eingstring; string eingstring; for(j=1;j<=nc;j++) { if((deg(A[i,j])>0)||(char(basering)!=0)||(npars(basering)>0)) { ERROR("Input to hilbert4ti2 needs to be a matrix with integer entries"); } eingstring=eingstring+string(A[i,j])+" "; } write(eing, eingstring); } close(eing); //---------------------------------------------------------------------- // calling 4ti2 and converting output // Singular's string is too clumsy for this, hence we first prepare // using standard unix commands //---------------------------------------------------------------------- j=system("sh","hilbert sing4ti2 >/dev/null 2>&1"); j=system("sh","awk \'BEGIN{ORS=\",\";}{print $0;}\' sing4ti2.hil | sed s/[\\\ \\\t\\\v\\\f]/,/g | sed s/,+/,/g |sed s/,,/,/g|sed s/,,/,/g > sing4ti2.converted"); if(!defined(keepfiles)) { j=system("sh",("rm -f sing4ti2.hil sing4ti2."+fileending)); } //---------------------------------------------------------------------- // reading output of 4ti2 //---------------------------------------------------------------------- link ausg=":r sing4ti2.converted"; //--- last entry ideal(0) is used to tie the list to the basering //--- it will not be processed any further string ergstr="list erglist="+read(ausg)+ string(ideal(0))+";"; execute(ergstr); ideal toric; poly temppol1,temppol2; for(i=1;i<=erglist[1];i++) { temppol1=1; temppol2=1; for(j=1;j<=erglist[2];j++) { if(erglist[2+(i-1)*erglist[2]+j]>=0) { //--- positive exponents temppol1=temppol1*(var(j)^erglist[2+(i-1)*erglist[2]+j]); } else { //--- negative exponents temppol2=temppol2*(var(j)^(-erglist[2+(i-1)*erglist[2]+j])); } } toric=toric,temppol1-temppol2; } //--- get rid of leading entry 0; toric=toric[2..ncols(toric)]; return(toric); } // A nice example here is the 3x3 Magic Squares example {"EXAMPLE:"; echo=2; ring r=0,(x1,x2,x3,x4,x5,x6,x7,x8,x9),dp; matrix M[7][9]=1,1,1,-1,-1,-1,0,0,0,1,1,1,0,0,0,-1,-1,-1,0,1,1,-1,0,0,-1,0,0,1,0,1,0,-1,0,0,-1,0,1,1,0,0,0,-1,0,0,-1,0,1,1,0,-1,0,0,0,-1,1,1,0,0,-1,0,-1,0,0; hilbert4ti2(M); } ///////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/solve.lib000066400000000000000000001635751266270727000200100ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version solve.lib 4.0.0.0 Jun_2013 "; // $Id: d2eba6aac4a78bf6f8383d72d4ce19110230c0fe $ category="Symbolic-numerical solving"; info=" LIBRARY: solve.lib Complex Solving of Polynomial Systems AUTHOR: Moritz Wenk, email: wenk@mathematik.uni-kl.de Wilfred Pohl, email: pohl@mathematik.uni-kl.de PROCEDURES: laguerre_solve(p,[..]); find all roots of univariate polynomial p solve(i,[..]); all roots of 0-dim. ideal i using triangular sets ures_solve(i,[..]); find all roots of 0-dimensional ideal i with resultants mp_res_mat(i,[..]); multipolynomial resultant matrix of ideal i interpolate(p,v,d); interpolate polynomial from evaluation points i and results j fglm_solve(i,[..]); find roots of 0-dim. ideal using FGLM and lex_solve lex_solve(i,p,[..]); find roots of reduced lexicographic standard basis simplexOut(l); prints solution of simplex in nice format triangLf_solve(l,[..]); find roots using triangular sys. (factorizing Lazard) triangM_solve(l,[..]); find roots of given triangular system (Moeller) triangL_solve(l,[..]); find roots using triangular system (Lazard) triang_solve(l,p,[..]); find roots of given triangular system "; LIB "triang.lib"; // needed for triang_solve LIB "ring.lib"; // needed for changeordTo /////////////////////////////////////////////////////////////////////////////// proc laguerre_solve( poly f, list # ) "USAGE: laguerre_solve(f [, m, l, n, s] ); f = polynomial,@* m, l, n, s = integers (control parameters of the method)@* m: precision of output in digits ( 4 <= m), if basering is not ring of complex numbers; l: precision of internal computation in decimal digits ( l >=8 ) only if the basering is not complex or complex with smaller precision;@* n: control of multiplicity of roots or of splitting of f into squarefree factors n < 0, no split of f (good, if all roots are simple) n >= 0, try to split n = 0, return only different roots n > 0, find all roots (with multiplicity) s: s != 0, returns ERROR if | f(root) | > 0.1^m (when computing in the current ring) ( default: m, l, n, s = 8, 30, 1, 0 ) ASSUME: f is a univariate polynomial;@* basering has characteristic 0 and is either complex or without parameters. RETURN: list of (complex) roots of the polynomial f, depending on n. The entries of the result are of type@* string: if the basering is not complex,@* number: otherwise. NOTE: If printlevel >0: displays comments ( default = 0 ). If s != 0 and if the procedure stops with ERROR, try a higher internal precision m. EXAMPLE: example laguerre_solve; shows an example " { if (char(basering)!=0){ERROR("characteristic of basering not 0");} if ((charstr(basering)[1]=="0") and (npars(basering)!=0)) {ERROR("basering has parameters");} int OLD_COMPLEX=0; int iv=checkv(f); // check for variable appearing in f if(iv==0){ERROR("Wrong polynomial!");} poly v=var(iv); // f univariate in v int solutionprec=8;// set the control int numberprec=30; int splitcontrol=1; int rootcheck=0; if(size(#)>0){solutionprec=#[1];if(solutionprec<4){solutionprec=4;}} if(size(#)>1){numberprec=#[2];if(numberprec<8){numberprec=8;}} if(solutionprec>numberprec){numberprec=solutionprec;} if(size(#)>2){splitcontrol=#[3];} if(size(#)>3){rootcheck=#[4];} int prot=printlevel-voice+2; int ringprec=0; poly p=divzero(f,iv); // divide out zeros as solution int iz=deg(f)-deg(p); // multiplicity of zero solution if(prot!=0) { string pout; string nl=newline; pout="//BEGIN laguerre_solve"; if(iz!=0){pout=pout+nl+"//zeros: divide out "+string(iz);} dbprint(prot,pout); } string ss,tt,oo; ss="";oo=ss; if(npars(basering)==1) { if(OLD_COMPLEX) { tt="1,"+string(par(1)); if(tt==charstr(basering)) {ss=tt;ringprec=system("getPrecDigits");} } else { tt=charstr(basering); if(size(tt)>7) { if(string(tt[1..7])=="complex") { ss=tt; ringprec=system("getPrecDigits"); } } } } list roots,simple; if(deg(p)==0) // only zero was root { roots=addzero(roots,ss,iz,splitcontrol); if(prot!=0){dbprint(prot,"//END laguerre_solve");} return(roots); } if(prot!=0)// more informations { pout="//control: complex ring with precision "+string(numberprec); if(size(ss)==0){pout=pout+nl+ "// basering not complex, hence solutiontype string"; if(solutionprec=0)// splitting { if(prot!=0){dbprint(prot,"//split in working ring:");} SPLIT=splitsqrfree(p,v); i1=size(SPLIT); if((i1==1)&&(charstr(rn)=="0")) { if(prot!=0){dbprint(prot,"//split exact in basering:");} setring rn; if(v>1) { ideal SQQQQ=splitsqrfree(p,v); setring lagc; SPLIT=imap(rn,SQQQQ); } else { oo="ring exa=0,"+string(var(1))+",lp;"; execute(oo); ideal SQQQQ=splitsqrfree(imap(rn,p),var(1)); setring lagc; SPLIT=imap(exa,SQQQQ); kill exa; } i1=size(SPLIT); } if(prot!=0) { if(i1>1) { int i3=deg(SPLIT[1]); pout="//results of split(the squarefree factors):"; if(i3>0){pout=pout+nl+ "// multiplicity "+string(i2)+", degree "+string(i3);} while(i20){pout=pout+nl+ "// multiplicity "+string(i2)+", degree "+string(i3);} } dbprint(prot,pout); i2=1; } else { if(charstr(rn)=="0"){dbprint(prot,"// polynomial is squarefree");} else{dbprint(prot,"//split without result");} } } } p=SPLIT[1];// the first part if(deg(p)>0) { roots=laguerre(p,numberprec,1);// the ring is already complex, hence numberprec is dummy if((size(roots)==0)||(string(roots[1])=="0")){ERROR("laguerre: no roots found");} if(rootcheck){checkroots(p,v,roots,ima,prc);} } while(i20) { simple=laguerre(p,numberprec,1); if((size(simple)==0)||(string(simple[1])=="0")){ERROR("laguerre: no roots found");} if(rootcheck){checkroots(p,v,simple,ima,prc);} if(splitcontrol==0)// no multiple roots { roots=roots+simple; } else// multiple roots { roots=roots+makemult(simple,i2); } } } if((solutionprec0){roots=addzero(roots,ss,iz,splitcontrol);} if(prot!=0){dbprint(prot,"//END laguerre_solve");} return(roots); } if(size(ss)==0){roots=transroots(roots);}// transform to string else // or map in basering { if(ringprec0){roots=addzero(roots,ss,iz,splitcontrol);} if(prot!=0){dbprint(prot,"//END laguerre_solve");} return(roots); } example { "EXAMPLE:";echo=2; // Find all roots of an univariate polynomial using Laguerre's method: ring rs1= 0,(x,y),lp; poly f = 15x5 + x3 + x2 - 10; // 10 digits precision laguerre_solve(f,10); // Now with complex coefficients, // internal precision is 30 digits (default) printlevel=2; ring rsc= (real,10,i),x,lp; poly f = (15.4+i*5)*x^5 + (25.0e-2+i*2)*x^3 + x2 - 10*i; list l = laguerre_solve(f); l; // check result, value of substituted polynomial should be near to zero // remember that l contains a list of strings // in the case of a different ring subst(f,x,l[1]); subst(f,x,l[2]); } ////////////////////////////////////////////////////////////////////////////// // subprocedures for laguerre_solve /* * if p depends only on var(i) * returns i * otherwise 0 */ static proc checkv(poly p) { int n=nvars(basering); int i=0; int v; while (n>0) { if ((p-subst(p,var(n),0))!=0) { i++; if (i>1){return(0);} v=n; } n--; } return(v); } /* * if p has only real coefficients * returns 0 * otherwise 1 */ static proc checkim(poly p) { poly q=p; while(q!=0) { if(impart(leadcoef(q))!=0){return(1);} q=q-lead(q); } return(0); } /* * make multiplicity m */ static proc makemult(list si,int m) { int k0=0; int k1=size(si); int k2,k3; number ro; list msi; for(k2=1;k2<=k1;k2++) { ro=si[k2]; for(k3=m;k3>0;k3--){k0++;msi[k0]=ro;} } return(msi); } /* * returns 1 for n<1 */ static proc cmp1(number n) { number r=repart(n); number i=impart(n); number c=r*r+i*i; if(c>1){return(1);} else{return(0);} } /* * exact division of polys f/g * (should be internal) */ static proc exdiv(poly f,poly g,poly v) { int d1=deg(f); int d2=deg(g); poly r0=f; poly rf=0; poly h; number n,m; m=leadcoef(g); while ((r0!=0)&&(d1>=d2)) { n=leadcoef(r0)/m; h=n*v^(d1-d2); rf=rf+h; r0=r0-h*g; d1=deg(r0); } return(cleardenom(rf)); } /* * p is univariant in x * perform a split of p into squarefree factors * such that the returned ideal 'split' consists of * the faktors, i.e. * p = n * product ( split[i]^i ) , n a number */ static proc splitsqrfree(poly p, poly x) { int dd=deg(p); if(dd==1){return(p);} int i=1; int j; ideal h,split; poly high; h=interred(ideal(p,diff(p,x))); if(deg(h[1])==0){return(p);} high=h[1]; split[1]=exdiv(p,high,x); while(1) { h=interred(ideal(split[i],high)); j=deg(h[1]); if(j==0){return(p);} if(deg(h[1])==deg(split[i])) { split=split,split[i]; split[i]=1; } else { split[i]=exdiv(split[i],h[1],x); split=split,h[1]; dd=dd-deg(split[i])*i; } j=j*(i+1); if(j==dd){break;} if(j>dd){return(p);} high=exdiv(high,h[1],x); if(deg(high)==0){return(p);} i++; } return(split); } /* * see checkroots */ static proc nerr(number n,number m) { int r; number z=0; number nr=repart(n); number ni=impart(n); if(nr=pr */ static proc checkroots(poly p,poly v,list r,int ima,number pr) { int i=0; int j; number n,m; ideal li; while(i0) { r[i]=string(r[i]); i--; } return(r); } /* * returns a polynomial without zeroroots */ static proc divzero(poly f,int iv) { poly p=f; poly q=p; poly r; while(p==q) { q=p/var(iv); r=q*var(iv); if(r==p){p=q;} } return(p); } /* * add zeros to solution */ static proc addzero(list zz,string ss,int iz,int a) { int i=1; int j=size(zz); if(size(ss)==0){zz[j+1]="0";} else{zz[j+1]=number(0);} if(a==0){return(zz);} while(i=8 ) only if the basering is not complex or complex with smaller precision, @* [default: (m,n,l) = (8,0,30), or if only (m,n) are set explicitly with n!=0, then (m,n,l) = (m,n,60) ] ASSUME: the ideal is 0-dimensional;@* basering has characteristic 0 and is either complex or without parameters; RETURN: (1) If called without the additional parameter @code{\"oldring\"}: @* ring @code{R} with the same number of variables but with complex coefficients (and precision m). @code{R} comes with a list @code{SOL} of numbers, in which complex roots of G are stored: @* * If n = 0, @code{SOL} is the list of all different solutions, each of them being represented by a list of numbers. @* * If n != 0, @code{SOL} is a list of two list: SOL[i][1] is the list of all different solutions with the multiplicity SOL[i][2].@* SOL is ordered w.r.t. multiplicity (the smallest first). @* (2) If called with the additional parameter @code{\"oldring\"}, the procedure looks for an appropriate ring (at top level) in which the solutions can be stored (interactive). @* The user may then select an appropriate ring and choose a name for the output list in this ring. The list is exported directly to the selected ring and the return value is a string \"result exported to\" + name of the selected ring. NOTE: If the problem is not 0-dim. the procedure stops with ERROR. If the ideal G is not a lexicographic Groebner basis, the lexicographic Groebner basis is computed internally (Hilbert driven). @* The computed solutions are displayed, unless @code{solve} is called with the additional parameter @code{\"nodisplay\"}. EXAMPLE: example solve; shows an example " { // test if basering admissible if (char(basering)!=0){ERROR("characteristic of basering not 0");} if ((charstr(basering)[1]=="0") and (npars(basering)!=0)) { ERROR("basering has parameters"); } // some global settings and control int oldr, nodisp, ii, jj; list LL; int outprec = 8; int mu = 0; int prec = 30; // check additional parameters... if (size(#)>0) { int sofar=1; if (typeof(#[1])=="int") { outprec = #[1]; if (outprec<4){outprec = 4;} if (size(#)>1) { if (typeof(#[2])=="int") { mu = #[2]; if (size(#)>2) { if (typeof(#[3])=="int") { prec = #[3]; if (prec<8){prec = 8;} } else { if(mu!=0){prec = 60;} if (#[3]=="oldring"){ oldr=1; } if (#[3]=="nodisplay"){ nodisp=1; } } sofar=3; } } else { if (#[2]=="oldring"){ oldr=1; } if (#[2]=="nodisplay"){ nodisp=1; } } sofar=2; } } else { if (#[1]=="oldring"){ oldr=1; } if (#[1]=="nodisplay"){ nodisp=1; } } for (ii=sofar+1;ii<=size(#);ii++) { // check for additional strings if (typeof(#[ii])=="string") { if (#[ii]=="oldring"){ oldr=1; } if (#[ii]=="nodisplay"){ nodisp=1; } } } } if (outprec>prec){prec = outprec;} // if interaktive version is chosen -- choice of basering (Top::`outR`) // and name for list of solutions (outL): if (oldr==1) { list Out; LL=names(Top); for (ii=1;ii<=size(LL);ii++) { if (typeof(`LL[ii]`)=="ring") { if (find(charstr(`LL[ii]`),"complex,"+string(outprec))) { jj++; Out[jj]=LL[ii]; } } } if (size(Out)>0) { print("// *** You may select between the following rings for storing "+ "the list of"); print("// *** complex solutions:"); Out; print("// *** Enter the number of the chosen ring"); print("// *** (0: none of them => new ring created and returned)"); string chosen; while (chosen=="") { chosen=read(""); } execute("def tchosen = "+chosen); if (typeof(tchosen)=="int") { if ((tchosen>0) and (tchosen<=size(Out))) { string outR = Out[tchosen]; print("// *** You have chosen the ring "+ outR +". In this ring" +" the following objects"); print("//*** are defined:"); listvar(Top::`outR`); print("// *** Enter a name for the list of solutions (different "+ "from existing names):"); string outL; while (outL==""){ outL=read(""); } } } } else { print("No appropriate ring for storing the list of solutions found " + "=> new ring created and returned"); } if (not(defined(outR))) { oldr=0; } } // string rinC = nameof(basering)+"C"; string sord = ordstr(basering); int nv = nvars(basering); def rin = basering; intvec ovec = option(get); option(redSB); option(returnSB); int sb = attrib(G,"isSB"); int lp = 0; if (size(sord)==size("C,lp()"+string(nv))) { lp = find(sord,"lp"); } // ERROR if (sb){if (dim(G)!=0){ERROR("ideal not zero-dimensional");}} // the trivial homogeneous case (unique solution: (0,...0)) if (homog(G)) { if (sb==0) { def dphom=changeordTo(rin,"dp"); setring dphom; ideal G = std(imap(rin,G)); if (dim(G)!=0){ERROR("ideal not zero-dimensional");} int vdG=vdim(G); } if (oldr!=1) { execute("ring rinC =(complex,"+string(outprec)+ "),("+varstr(basering)+"),lp;"); list SOL; if (mu==0){SOL[1] = zerolist(nv);} else{SOL[1] = list(zerolist(nv),list(vdG));} export SOL; if (nodisp==0) { print(SOL); } option(set,ovec); dbprint( printlevel-voice+3," // 'solve' created a ring, in which a list SOL of numbers (the complex solutions) // is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; SOL; "); return(rinC); } else { setring (Top::`outR`); list SOL; if (mu==0){SOL[1] = zerolist(nv);} else{SOL[1] = list(zerolist(nv),list(vdG));} execute("def "+outL + "=SOL;"); execute("export "+outL+";"); if (nodisp==0) { print(SOL); } option(set,ovec); kill SOL; return("result exported to "+outR+" as list "+outL); } } // look for reduced standard basis in lex if (sb*lp==0) { if (sb==0) { def dphilb=changeordTo(rin,"dp"); setring dphilb; ideal G = imap(rin,G); G = std(G); if (dim(G)!=0){ERROR("ideal not zero-dimensional");} } else { def dphilb = basering; G=interred(G); attrib(G,"isSB",1); } def lexhilb=changeordTo(rin,"lp"); setring lexhilb; option(redTail); ideal H = fglm(dphilb,G); kill dphilb; H = simplify(H,2); if (lp){setring rin;} else { def lplex=changeordTo(rin,"lp"); setring lplex; } ideal H = imap(lexhilb,H); kill lexhilb; } else{ideal H = interred(G);} // only 1 variable def hr = basering; if (nv==1) { if ((mu==0) and (charstr(basering)[1]=="0")) { // special case list L = laguerre_solve(H[1],prec,prec,mu,0); // list of strings if (oldr!=1) { execute("ring rinC =(complex,"+string(outprec)+"),("+varstr(basering)+"),lp;"); list SOL; for (ii=1; ii<=size(L); ii++ ) { execute("SOL[ii]=number("+L[ii]+");"); } export SOL; if (nodisp==0) { print(SOL); } option(set,ovec); dbprint( printlevel-voice+3," // 'solve' created a ring, in which a list SOL of numbers (the complex solutions) // is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; SOL; "); return(rinC); } else { setring (Top::`outR`); list SOL; for (ii=1; ii<=size(L); ii++ ) { execute("SOL[ii]="+L[ii]+";"); } execute("def "+outL + "=SOL;"); execute("export "+outL+";"); if (nodisp==0) { print(SOL); } option(set,ovec); kill SOL; return("result exported to "+outR+" as list "+outL); } } else { execute("ring internC=(complex,"+string(prec)+"),("+varstr(basering)+"),lp;"); ideal H = imap(hr,H); list sp = splittolist(splitsqrfree(H[1],var(1))); jj = size(sp); while(jj>0) { sp[jj][1] = laguerre(sp[jj][1],prec,1); jj--; } setring hr; if (oldr!=1) { execute("ring rinC =(complex,"+string(outprec)+"),("+varstr(basering)+"),lp;"); list SOL; list sp=imap(internC,sp); if(mu!=0){ SOL=sp; } else { jj = size(sp); SOL=sp[jj][1]; while(jj>1) { jj--; SOL = sp[jj][1]+SOL; } } export SOL; if (nodisp==0) { print(SOL); } option(set,ovec); dbprint( printlevel-voice+3," // 'solve' created a ring, in which a list SOL of numbers (the complex solutions) // is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; SOL; "); return(rinC); } else { setring (Top::`outR`); list SOL; list sp=imap(internC,sp); if(mu!=0){ SOL=sp; } else { jj = size(sp); SOL=sp[jj][1]; while(jj>1) { jj--; SOL = sp[jj][1]+SOL; } } kill sp; execute("def "+outL + "=SOL;"); execute("export "+outL+";"); if (nodisp==0) { print(SOL); } option(set,ovec); kill SOL; return("result exported to "+outR+" as list "+outL); } } } // the triangular sets (not univariate case) attrib(H,"isSB",1); if (mu==0) { list sp = triangMH(H); // faster, but destroy multiplicity } else { list sp = triangM(H); } // create the complex ring and map the result if (outprec1) { ret1 = trisolve(list(),triC[js],prec)+ret1; js--; } } else { ret1 = mutrisolve(list(),triC[1],prec); while (js>1) { ret1 = addlist(mutrisolve(list(),triC[js],prec),ret1,1); js--; } ret1 = finalclear(ret1); } // final computations option(set,ovec); if (outprec==prec) { // we are in ring rinC if (oldr!=1) { list SOL=ret1; export SOL; if (nodisp==0) { print(SOL); } dbprint( printlevel-voice+3," // 'solve' created a ring, in which a list SOL of numbers (the complex solutions) // is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; SOL; "); return(rinC); } else { setring (Top::`outR`); list SOL=imap(rinC,ret1); execute("def "+outL + "=SOL;"); execute("export "+outL+";"); if (nodisp==0) { print(SOL); } kill SOL; return("result exported to "+outR+" as list "+outL); } } else { if (oldr!=1) { execute("ring rinC =(complex,"+string(outprec)+"),("+varstr(basering)+"),lp;"); list SOL=imap(internC,ret1); export SOL; if (nodisp==0) { print(SOL); } dbprint( printlevel-voice+3," // 'solve' created a ring, in which a list SOL of numbers (the complex solutions) // is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; SOL; "); return(rinC); } else { setring (Top::`outR`); list SOL=imap(internC,ret1); execute("def "+outL + "=SOL;"); execute("export "+outL+";"); if (nodisp==0) { print(SOL); } kill SOL; return("result exported to "+outR+" as list "+outL); } } } example { "EXAMPLE:";echo=2; // Find all roots of a multivariate ideal using triangular sets: int d,t,s = 4,3,2 ; int i; ring A=0,x(1..d),dp; poly p=-1; for (i=d; i>0; i--) { p=p+x(i)^s; } ideal I = x(d)^t-x(d)^s+p; for (i=d-1; i>0; i--) { I=x(i)^t-x(i)^s+p,I; } I; // the multiplicity is vdim(std(I)); def AC=solve(I,6,0,"nodisplay"); // solutions should not be displayed // list of solutions is stored in AC as the list SOL (default name) setring AC; size(SOL); // number of different solutions SOL[5]; // the 5th solution // you must start with char. 0 setring A; def AC1=solve(I,6,1,"nodisplay"); setring AC1; size(SOL); // number of different multiplicities SOL[1][1][1]; // a solution with SOL[1][2]; // multiplicity 1 SOL[2][1][1]; // a solution with SOL[2][2]; // multiplicity 12 // the number of different solutions is equal to size(SOL[1][1])+size(SOL[2][1]); // the number of complex solutions (counted with multiplicities) is size(SOL[1][1])*SOL[1][2]+size(SOL[2][1])*SOL[2][2]; } ////////////////////////////////////////////////////////////////////////////// // subprocedures for solve /* * return one zero-solution */ static proc zerolist(int nv) { list ret; int i; number o=0; for (i=nv;i>0;i--){ret[i] = o;} return(ret); } /* ----------------------- check solution ----------------------- */ static proc multsol(list ff, int c) { int i,j; i = 0; j = size(ff); while (j>0) { if(c){i = i+ff[j][2]*size(ff[j][1]);} else{i = i+size(ff[j][1]);} j--; } return(i); } /* * the inputideal A => zero ? */ static proc checksol(ideal A, list lr) { int d = nvars(basering); list ro; ideal re,h; int i,j,k; for (i=size(lr);i>0;i--) { ro = lr[i]; for (j=d;j>0;j--) { re[j] = var(j)-ro[j]; } attrib(re,"isSB",1); k = size(reduce(A,re,1)); if (k){return(i);} } return(0); } /* * compare 2 solutions: returns 0 for equal */ static proc cmpn(list a,list b) { int ii; for(ii=size(a);ii>0;ii--){if(a[ii]!=b[ii]) break;} return(ii); } /* * delete equal solutions in the list */ static proc delequal(list r, int w) { list h; int i,j,k,c; if (w) { k = size(r); h = r[k][1]; k--; while (k>0) { h = r[k][1]+h; k--; } } else{h = r;} k=size(h); i=1; while(ii) { c=cmpn(h[i],h[j]); if(c==0) { h=delete(h,j); k--; } j--; } i++; } return(h); } /* ----------------------- substitution ----------------------- */ /* * instead of subst(T,var(v),n), much faster * need option(redSB) ! */ static proc linreduce(ideal T, int v, number n) { ideal re = var(v)-n; attrib (re,"isSB",1); return (reduce(T,re)); } /* ----------------------- triangular solution ----------------------- */ /* * solution of one tridiagonal system T * with precision prec * T[1] is univariant in var(1) * list o is empty for the first call */ static proc trisolve(list o, ideal T, int prec) { list lroots,ll; ideal S; int i,d; d = size(T); S = interred(ideal(T[1],diff(T[1],var(d)))); if (deg(S[1])) { T[1] = exdiv(T[1],S[1],var(d)); } ll = laguerre(T[1],prec,1); for (i=size(ll);i>0;i--){ll[i] = list(ll[i])+o;} if (d==1){return(ll);} for (i=size(ll);i>0;i--) { S = linreduce(ideal(T[2..d]),d,ll[i][1]); lroots = trisolve(ll[i],S,prec)+lroots; } return(lroots); } /* ------------------- triangular solution (mult) ------------------- */ /* * recompute equal solutions w.r.t. multiplicity */ static proc finalclear(list b) { list a = b; list r; int i,l,ju,j,k,ku,mu,c; // a[i] only i = 1; while (i<=size(a)) { ju = size(a[i][1]); j = 1; while (j<=ju) { mu = 1; k = j+1; while (k<=ju) { c = cmpn(a[i][1][j],a[i][1][k]); if (c==0) { a[i][1] = delete(a[i][1],k); ju--; mu++; } else{k++;} } if (mu>1) { r[1] = a[i]; r[1][1] = list(a[i][1][j]); a[i][1] = delete(a[i][1],j); a = addlist(r,a,mu); ju--; } else{j++;} } if (ju==0){a = delete(a,i);} else{i++;} } // a[i], a[l] i = 1; while (i0) { if (deg(sp[j])) { spl = list(list(sp[j],j))+spl; } j--; } return(spl); } /* * multiply the multiplicity */ static proc multlist(list a, int m) { int i; for (i=size(a);i>0;i--){a[i][2] = a[i][2]*m;} return(a); } /* * a+b w.r.t. to multiplicity as ordering * (programming like spolys) */ static proc addlist(list a, list b, int m) { int i,j,k,l,s; list r = list(); if (m>1){a = multlist(a,m);} k = size(a); l = size(b); i = 1; j = 1; while ((i<=k)&&(j<=l)) { s = a[i][2]-b[j][2]; if (s>=0) { r = r+list(b[j]); j++; if (s==0) { s = size(r); r[s][1] = r[s][1]+a[i][1]; i++; } } else { r = r+list(a[i]); i++; } } if (i>k) { if (j<=l){r = r+list(b[j..l]);} } else{r = r+list(a[i..k]);} return(r); } /* * solution of one tridiagonal system T with multiplicity * with precision prec * T[1] is univariant in var(1) * list o is empty for the first call */ static proc mutrisolve(list o, ideal T, int prec) { list lroots,ll,sp; ideal S,h; int i,d,m,z; d = size(T); sp = splittolist(splitsqrfree(T[1],var(d))); if (d==1){return(l_mutrisolve(sp,o,prec));} z = size(sp); while (z>0) { m = sp[z][2]; ll = laguerre(sp[z][1],prec,1); i = size(ll); while(i>0) { h = linreduce(ideal(T[2..d]),d,ll[i]); if (size(lroots)) { lroots = addlist(mutrisolve(list(ll[i])+o,h,prec),lroots,m); } else { lroots = mutrisolve(list(ll[i])+o,h,prec); if (m>1){lroots=multlist(lroots,m);} } i--; } z--; } return(lroots); } /* * the last call, we are ready */ static proc l_mutrisolve(list sp, list o, int prec) { list lroots,ll; int z,m,i; z = size(sp); while (z>0) { m = sp[z][2]; ll = laguerre(sp[z][1],prec,1); for (i=size(ll);i>0;i--){ll[i] = list(ll[i])+o;} if (size(lroots)) { lroots = addlist(list(list(ll,m)),lroots,1); } else { lroots = list(list(ll,m)); } z--; } return(lroots); } /////////////////////////////////////////////////////////////////////////////// proc ures_solve( ideal gls, list # ) "USAGE: ures_solve(i [, k, p] ); i = ideal, k, p = integers k=0: use sparse resultant matrix of Gelfand, Kapranov and Zelevinsky, @* k=1: use resultant matrix of Macaulay which works only for homogeneous ideals,@* p>0: defines precision of the long floats for internal computation if the basering is not complex (in decimal digits), (default: k=0, p=30) ASSUME: i is a zerodimensional ideal given by a quadratic system, that is,@* nvars(basering) = ncols(i) = number of vars actually occurring in i, RETURN: If the ground field is the field of complex numbers: list of numbers (the complex roots of the polynomial system i=0). @* Otherwise: ring @code{R} with the same number of variables but with complex coefficients (and precision p). @code{R} comes with a list @code{SOL} of numbers, in which complex roots of the polynomial system i are stored: @* EXAMPLE: example ures_solve; shows an example " { int typ=0;// defaults int prec=30; if ( size(#) > 0 ) { typ= #[1]; if ( typ < 0 || typ > 1 ) { ERROR("Valid values for second parameter k are: 0: use sparse Resultant (default) 1: use Macaulay Resultant"); } } if ( size(#) > 1 ) { prec= #[2]; if ( prec < 8 ) { prec = 8; } } list LL=uressolve(gls,typ,prec,1); int sizeLL=size(LL); if (sizeLL==0) { dbprint(printlevel-voice+3,"No solution found!"); return(list()); } if (typeof(LL[1][1])=="string") { int ii,jj; int nv=size(LL[1]); execute("ring rinC =(complex,"+string(prec)+",I),(" +varstr(basering)+"),lp;"); list SOL,SOLnew; for (ii=1; ii<=sizeLL; ii++) { SOLnew=list(); for (jj=1; jj<=nv; jj++) { execute("SOLnew["+string(jj)+"]="+LL[ii][jj]+";"); } SOL[ii]=SOLnew; } kill SOLnew; export SOL; dbprint( printlevel-voice+3," // 'ures_solve' created a ring, in which a list SOL of numbers (the complex // solutions) is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; SOL; "); return(rinC); } else { return(LL); } } example { "EXAMPLE:";echo=2; // compute the intersection points of two curves ring rsq = 0,(x,y),lp; ideal gls= x2 + y2 - 10, x2 + xy + 2y2 - 16; def R=ures_solve(gls,0,16); setring R; SOL; } /////////////////////////////////////////////////////////////////////////////// proc mp_res_mat( ideal i, list # ) "USAGE: mp_res_mat(i [, k] ); i ideal, k integer, k=0: sparse resultant matrix of Gelfand, Kapranov and Zelevinsky,@* k=1: resultant matrix of Macaulay (k=0 is default) ASSUME: The number of elements in the input system must be the number of variables in the basering plus one; if k=1 then i must be homogeneous. RETURN: module representing the multipolynomial resultant matrix EXAMPLE: example mp_res_mat; shows an example " { int typ=0; if ( size(#) > 0 ) { typ= #[1]; if ( typ < 0 || typ > 1 ) { ERROR("Valid values for third parameter are: 0: sparse resultant (default) 1: Macaulay resultant"); } } return(mpresmat(i,typ)); } example { "EXAMPLE:";echo=2; // compute resultant matrix in ring with parameters (sparse resultant matrix) ring rsq= (0,u0,u1,u2),(x1,x2),lp; ideal i= u0+u1*x1+u2*x2,x1^2 + x2^2 - 10,x1^2 + x1*x2 + 2*x2^2 - 16; module m = mp_res_mat(i); print(m); // computing sparse resultant det(m); // compute resultant matrix (Macaulay resultant matrix) ring rdq= (0,u0,u1,u2),(x0,x1,x2),lp; ideal h= homog(imap(rsq,i),x0); h; module m = mp_res_mat(h,1); print(m); // computing Macaulay resultant (should be the same as above!) det(m); // compute numerical sparse resultant matrix setring rsq; ideal ir= 15+2*x1+5*x2,x1^2 + x2^2 - 10,x1^2 + x1*x2 + 2*x2^2 - 16; module mn = mp_res_mat(ir); print(mn); // computing sparse resultant det(mn); } /////////////////////////////////////////////////////////////////////////////// proc interpolate( ideal p, ideal w, int d ) "USAGE: interpolate(p,v,d); p,v=ideals of numbers, d=integer ASSUME: Ground field K is the field of rational numbers, p and v are lists of elements of the ground field K with p[j] != -1,0,1, size(p) = n (= number of vars) and size(v)=N=(d+1)^n. RETURN: poly f, the unique polynomial f of degree n*d with prescribed values v[i] at the points p(i)=(p[1]^(i-1),..,p[n]^(i-1)), i=1,..,N. NOTE: mainly useful when n=1, i.e. f is satisfying f(p^(i-1)) = v[i], i=1..d+1. SEE ALSO: vandermonde. EXAMPLE: example interpolate; shows an example " { return(vandermonde(p,w,d)); } example { "EXAMPLE:"; echo=2; ring r1 = 0,(x),lp; // determine f with deg(f) = 4 and // v = values of f at points 3^0, 3^1, 3^2, 3^3, 3^4 ideal v=16,0,11376,1046880,85949136; interpolate( 3, v, 4 ); } /////////////////////////////////////////////////////////////////////////////// // changed for Singular 3 // Return value is now a list: (rlist, rn@) static proc psubst( int d, int dd, int n, list resl, ideal fi, int elem, int nv, int prec, int rn@, list rlist) { // nv: number of ring variables (fixed value) // elem: number of elements in ideal fi (fixed value) // fi: input ideal (fixed value) // rl: output list of roots // resl: actual list of roots // n: // dd: actual element of fi // d: actual variable list LL; int pdebug; int olddd=dd; dbprint(printlevel-voice+2, "// 0 step "+string(dd)+" of "+string(elem) ); if ( dd <= elem ) { int loop = 1; int k; list lsr,lh; poly ps; int thedd; dbprint( printlevel-voice+1,"// 1 dd = "+string(dd) ); thedd=0; while ( (dd+1 <= elem) && loop ) { ps= fi[dd+1]; if ( n-1 > 0 ) { dbprint( printlevel-voice, "// 2 ps=fi["+string(dd+1)+"]"+" size=" +string(size(coeffs(ps,var(n-1)))) +" leadexp(ps)="+string(leadexp(ps)) ); if ( size(coeffs(ps,var(n-1))) == 1 ) { dd++; // hier Leading-Exponent pruefen??? // oder ist das Polynom immer als letztes in der Liste?!? // leadexp(ps) } else { loop=0; } } else { dbprint( printlevel-voice, "// 2 ps=fi["+string(dd+1)+"]"+" leadexp(ps)=" +string(leadexp(ps)) ); dd++; } } thedd=dd; ps= fi[thedd]; dbprint( printlevel-voice+1, "// 3 fi["+string(thedd-1)+"]"+" leadexp(fi[thedd-1])=" +string(leadexp(fi[thedd-1])) ); dbprint( printlevel-voice+1, "// 3 ps=fi["+string(thedd)+"]"+" leadexp(ps)=" +string(leadexp(ps)) ); for ( k= nv; k > nv-d; k-- ) { dbprint( printlevel-voice, "// 4 subst(fi["+string(thedd)+"]," +string(var(k))+","+string(resl[k])+");" ); ps = subst(ps,var(k),resl[k]); } dbprint( printlevel-voice, "// 5 substituted ps="+string(ps) ); if ( ps != 0 ) { lsr= laguerre_solve( ps, prec, prec, 0 ); } else { dbprint( printlevel-voice+1,"// 30 ps == 0, thats not cool..."); lsr=list(number(0)); } dbprint( printlevel-voice+1, "// 6 laguerre_solve found roots: lsr["+string(size(lsr))+"]" ); if ( size(lsr) > 1 ) { dbprint( printlevel-voice+1, "// 10 checking roots found before, range " +string(dd-olddd)+" -- "+string(dd) ); dbprint( printlevel-voice+1, "// 10 thedd = "+string(thedd) ); int i,j,l; int ls=size(lsr); int lss; poly pss; list nares; int rroot; int nares_size; for ( i = 1; i <= ls; i++ ) // lsr[1..ls] { rroot=1; if ( pdebug>=2 ) {"// 13 root lsr["+string(i)+"] = "+string(lsr[i]);} for ( l = 0; l <= dd-olddd; l++ ) { if ( l+olddd != thedd ) { if ( pdebug>=2 ) {"// 11 checking ideal element "+string(l+olddd);} ps=fi[l+olddd]; if ( pdebug>=3 ) {"// 14 ps=fi["+string(l+olddd)+"]";} for ( k= nv; k > nv-d; k-- ) { if ( pdebug>=3 ) { "// 11 subst(fi["+string(olddd+l)+"]," +string(var(k))+","+string(resl[k])+");"; } ps = subst(ps,var(k),resl[k]); } pss=subst(ps,var(k),lsr[i]); // k=nv-d if ( pdebug>=3 ) { "// 15 0 == "+string(pss); } if ( pss != 0 ) { if ( system("complexNearZero", leadcoef(pss), prec) ) { if ( pdebug>=2 ) { "// 16 root "+string(i)+" is a real root"; } } else { if ( pdebug>=2 ) { "// 17 0 == "+string(pss); } rroot=0; } } } } if ( rroot == 1 ) // add root to list ? { if ( size(nares) > 0 ) { nares=nares[1..size(nares)],lsr[i]; } else { nares=lsr[i]; } if ( pdebug>=2 ) { "// 18 added root to list nares"; } } } nares_size=size(nares); if ( nares_size == 0 ) { "Numerical problem: No root found..."; "Output may be incorrect!"; nares=list(number(0)); } if ( pdebug>=1 ) { "// 20 found <"+string(size(nares))+"> roots"; } for ( i= 1; i <= nares_size; i++ ) { resl[nv-d]= nares[i]; if ( dd < elem ) { if ( i > 1 ) { rn@++; } LL = psubst( d+1, dd+1, n-1, resl, fi, elem, nv, prec, rn@, rlist ); rlist = LL[1]; rn@ = LL[2]; } else { if ( i > 1 ) { rn@++; } //bug found by O.Labs if ( pdebug>=1 ) {"// 30_1 <"+string(rn@)+"> "+string(size(resl))+" <-----";} if ( pdebug>=2 ){ resl; } rlist[rn@]=resl; } } } else { if ( pdebug>=2 ) { "// 21 found root to be: "+string(lsr[1]); } resl[nv-d]= lsr[1]; if ( dd < elem ) { LL= psubst( d+1, dd+1, n-1, resl, fi, elem, nv, prec, rn@, rlist ); rlist = LL[1]; rn@ = LL[2]; } else { if ( pdebug>=1 ) { "// 30_2 <"+string(rn@)+"> "+string(size(resl))+" <-----";} if ( pdebug>=2 ) { resl; } rlist[rn@]=resl; } } } return(list(rlist,rn@)); } /////////////////////////////////////////////////////////////////////////////// proc fglm_solve( ideal fi, list # ) "USAGE: fglm_solve(i [, p] ); i ideal, p integer ASSUME: the ground field has char 0. RETURN: ring @code{R} with the same number of variables but with complex coefficients (and precision p). @code{R} comes with a list @code{rlist} of numbers, in which the complex roots of i are stored.@* p>0: gives precision of complex numbers in decimal digits [default: p=30]. NOTE: The procedure uses a standard basis of i to determine all complex roots of i. EXAMPLE: example fglm_solve; shows an example " { int prec=30; if ( size(#)>=1 && typeof(#[1])=="int") { prec=#[1]; } def R = lex_solve(stdfglm(fi),prec); dbprint( printlevel-voice+3," // 'fglm_solve' created a ring, in which a list rlist of numbers (the // complex solutions) is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; rlist; "); return(R); } example { "EXAMPLE:";echo=2; ring r = 0,(x,y),lp; // compute the intersection points of two curves ideal s = x2 + y2 - 10, x2 + xy + 2y2 - 16; def R = fglm_solve(s,10); setring R; rlist; } /////////////////////////////////////////////////////////////////////////////// proc lex_solve( ideal fi, list # ) "USAGE: lex_solve( i[,p] ); i=ideal, p=integer, p>0: gives precision of complex numbers in decimal digits (default: p=30). ASSUME: i is a reduced lexicographical Groebner bases of a zero-dimensional ideal, sorted by increasing leading terms. RETURN: ring @code{R} with the same number of variables but with complex coefficients (and precision p). @code{R} comes with a list @code{rlist} of numbers, in which the complex roots of i are stored. EXAMPLE: example lex_solve; shows an example " { int prec=30; list LL; if ( size(#)>=1 && typeof(#[1])=="int") { prec=#[1]; } if ( !defined(pdebug) ) { int pdebug; } def oring= basering; // change the ground field to complex numbers string nrings= "ring RC =(complex,"+string(prec) +"),("+varstr(basering)+"),lp;"; execute(nrings); // map fi from old to new ring ideal fi= imap(oring,fi); int idelem= size(fi); int nv= nvars(basering); int i,j,k,lis; list resl,li; if ( !defined(rlist) ) { list rlist; export rlist; } li= laguerre_solve(fi[1],prec,prec,0); lis= size(li); dbprint(printlevel-voice+2,"// laguerre found roots: "+string(size(li))); int rn@; for ( j= 1; j <= lis; j++ ) { dbprint(printlevel-voice+1,"// root "+string(j) ); rn@++; resl[nv]= li[j]; LL = psubst( 1, 2, nv-1, resl, fi, idelem, nv, prec, rn@, rlist ); rlist=LL[1]; rn@=LL[2]; } dbprint( printlevel-voice+3," // 'lex_solve' created a ring, in which a list rlist of numbers (the // complex solutions) is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; rlist; "); return(RC); } example { "EXAMPLE:";echo=2; ring r = 0,(x,y),lp; // compute the intersection points of two curves ideal s = x2 + y2 - 10, x2 + xy + 2y2 - 16; def R = lex_solve(stdfglm(s),10); setring R; rlist; } /////////////////////////////////////////////////////////////////////////////// proc triangLf_solve( ideal fi, list # ) "USAGE: triangLf_solve(i [, p] ); i ideal, p integer, p>0: gives precision of complex numbers in digits (default: p=30). ASSUME: the ground field has char 0; i is a zero-dimensional ideal RETURN: ring @code{R} with the same number of variables but with complex coefficients (and precision p). @code{R} comes with a list @code{rlist} of numbers, in which the complex roots of i are stored. NOTE: The procedure uses a triangular system (Lazard's Algorithm with factorization) computed from a standard basis to determine recursively all complex roots of the input ideal i with Laguerre's algorithm. EXAMPLE: example triangLf_solve; shows an example " { int prec=30; if ( size(#)>=1 && typeof(#[1])=="int") { prec=#[1]; } def R=triang_solve(triangLfak(stdfglm(fi)),prec); dbprint( printlevel-voice+3," // 'triangLf_solve' created a ring, in which a list rlist of numbers (the // complex solutions) is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; rlist; "); return(R); } example { "EXAMPLE:";echo=2; ring r = 0,(x,y),lp; // compute the intersection points of two curves ideal s = x2 + y2 - 10, x2 + xy + 2y2 - 16; def R = triangLf_solve(s,10); setring R; rlist; } /////////////////////////////////////////////////////////////////////////////// proc triangM_solve( ideal fi, list # ) "USAGE: triangM_solve(i [, p ] ); i=ideal, p=integer, p>0: gives precision of complex numbers in digits (default: p=30). ASSUME: the ground field has char 0;@* i zero-dimensional ideal RETURN: ring @code{R} with the same number of variables but with complex coefficients (and precision p). @code{R} comes with a list @code{rlist} of numbers, in which the complex roots of i are stored. NOTE: The procedure uses a triangular system (Moellers Algorithm) computed from a standard basis of input ideal i to determine recursively all complex roots with Laguerre's algorithm. EXAMPLE: example triangM_solve; shows an example " { int prec=30; if ( size(#)>=1 && typeof(#[1])=="int") { prec=#[1]; } def R = triang_solve(triangM(stdfglm(fi)),prec); dbprint( printlevel-voice+3," // 'triangM_solve' created a ring, in which a list rlist of numbers (the // complex solutions) is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; rlist; "); return(R); } example { "EXAMPLE:";echo=2; ring r = 0,(x,y),lp; // compute the intersection points of two curves ideal s = x2 + y2 - 10, x2 + xy + 2y2 - 16; def R = triangM_solve(s,10); setring R; rlist; } /////////////////////////////////////////////////////////////////////////////// proc triangL_solve( ideal fi, list # ) "USAGE: triangL_solve(i [, p] ); i=ideal, p=integer,@* p>0: gives precision of complex numbers in digits (default: p=30). ASSUME: the ground field has char 0; i is a zero-dimensional ideal. RETURN: ring @code{R} with the same number of variables, but with complex coefficients (and precision p). @code{R} comes with a list @code{rlist} of numbers, in which the complex roots of i are stored. NOTE: The procedure uses a triangular system (Lazard's Algorithm) computed from a standard basis of input ideal i to determine recursively all complex roots with Laguerre's algorithm. EXAMPLE: example triangL_solve; shows an example " { int prec=30; if ( size(#)>=1 && typeof(#[1])=="int") { prec=#[1]; } def R=triang_solve(triangL(stdfglm(fi)),prec); dbprint( printlevel-voice+3," // 'triangL_solve' created a ring, in which a list rlist of numbers (the // complex solutions) is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; rlist; "); return(R); } example { "EXAMPLE:";echo=2; ring r = 0,(x,y),lp; // compute the intersection points of two curves ideal s = x2 + y2 - 10, x2 + xy + 2y2 - 16; def R = triangL_solve(s,10); setring R; rlist; } /////////////////////////////////////////////////////////////////////////////// proc triang_solve( list lfi, int prec, list # ) "USAGE: triang_solve(l,p [,d] ); l=list, p,d=integers@* l is a list of finitely many triangular systems, such that the union of their varieties equals the variety of the initial ideal.@* p>0: gives precision of complex numbers in digits,@* d>0: gives precision (1=1 && typeof(#[1])=="int" ) { myCompDigits=#[1]; } else { myCompDigits=(system("getPrecDigits")); } dbprint( printlevel-voice+2,"// myCompDigits="+string(myCompDigits) ); int idelem; int nv= nvars(basering); int i,j,lis; list resu,li; if ( !defined(rlist) ) { list rlist; export rlist; } int rn@=0; // map the list list lfi= imap(oring,lfi); int slfi= size(lfi); ideal fi; for ( i= 1; i <= slfi; i++ ) { // map fi from old to new ring fi= lfi[i]; //imap(oring,lfi[i]); idelem= size(fi); // solve fi[1] li= laguerre_solve(fi[1],myCompDigits,myCompDigits,0); lis= size(li); dbprint( printlevel-voice+2,"// laguerre found roots: "+string(lis) ); for ( j= 1; j <= lis; j++ ) { dbprint( printlevel-voice+2,"// root "+string(j) ); rn@++; resu[nv]= li[j]; LL = psubst( 1, 2, nv-1, resu, fi, idelem, nv, myCompDigits, rn@, rlist ); rlist = LL[1]; rn@ = LL[2]; } } dbprint( printlevel-voice+3," // 'triang_solve' created a ring, in which a list rlist of numbers (the // complex solutions) is stored. // To access the list of complex solutions, type (if the name R was assigned // to the return value): setring R; rlist; "); return(RC); } example { "EXAMPLE:";echo=2; ring r = 0,(x,y),lp; // compute the intersection points of two curves ideal s= x2 + y2 - 10, x2 + xy + 2y2 - 16; def R=triang_solve(triangLfak(stdfglm(s)),10); setring R; rlist; } /////////////////////////////////////////////////////////////////////////////// proc simplexOut(list l) "USAGE: simplexOut(l); l list ASSUME: l is the output of simplex. RETURN: Nothing. The procedure prints the computed solution of simplex (as strings) in a nice format. SEE ALSO: simplex EXAMPLE: example simplexOut; shows an example " { int i,j; matrix m= l[1]; intvec iposv= l[3]; int icase= l[2]; int cols= ncols(m); int rows= nrows(m); int N= l[6]; if ( 1 == icase ) // objective function is unbound { "objective function is unbound"; return(); } if ( -1 == icase ) // no solution satisfies the given constraints { "no solution satisfies the given constraints"; return(); } if ( -2 == icase ) // other error { "an error occurred during simplex computation!"; return(); } for ( i = 1; i <= rows; i++ ) { if (i == 1) { "z = "+string(m[1][1]); } else { if ( iposv[i-1] <= N ) { "x"+string(iposv[i-1])+" = "+string(m[i,1]); } // else // { // "Y"; iposv[i-1]-N+1; // } } } } example { "EXAMPLE:";echo=2; ring r = (real,10),(x),lp; // consider the max. problem: // // maximize x(1) + x(2) + 3*x(3) - 0.5*x(4) // // with constraints: x(1) + 2*x(3) <= 740 // 2*x(2) - 7*x(4) <= 0 // x(2) - x(3) + 2*x(4) >= 0.5 // x(1) + x(2) + x(3) + x(4) = 9 // matrix sm[5][5]= 0, 1, 1, 3,-0.5, 740,-1, 0,-2, 0, 0, 0,-2, 0, 7, 0.5, 0,-1, 1,-2, 9,-1,-1,-1,-1; int n = 4; // number of constraints int m = 4; // number of variables int m1= 2; // number of <= constraints int m2= 1; // number of >= constraints int m3= 1; // number of == constraints list sol=simplex(sm, n, m, m1, m2, m3); simplexOut(sol); } // local Variables: *** // c-set-style: bsd *** // End: *** singular-4.0.3+ds/Singular/LIB/spcurve.lib000066400000000000000000000756361266270727000203470ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////// version="version spcurve.lib 4.0.0.0 Jun_2013 "; // $Id: c59b3ead180716d2b229ac5332b70c0a55115262 $ category="Singularities"; info=" LIBRARY: spcurve.lib Deformations and Invariants of CM-codim 2 Singularities AUTHOR: Anne Fruehbis-Krueger, anne@mathematik.uni-kl.de PROCEDURES: isCMcod2(i); presentation matrix of the ideal i, if i is CM CMtype(i); Cohen-Macaulay type of the ideal i matrixT1(M,n); 1st order deformation T1 in matrix description semiCMcod2(M,T1); semiuniversal deformation of maximal minors of M discr(sem,n); discriminant of semiuniversal deformation qhmatrix(M); weights if M is quasihomogeneous relweight(N,W,a); relative matrix weight of N w.r.t. weights (W,a) posweight(M,T1,i); deformation of coker(M) of non-negative weight KSpencerKernel(M); kernel of the Kodaira-Spencer map "; LIB "elim.lib"; LIB "homolog.lib"; LIB "inout.lib"; LIB "poly.lib"; ///////////////////////////////////////////////////////////////////////////// proc isCMcod2(ideal kurve) "USAGE: isCMcod2(i); i an ideal RETURN: presentation matrix of i, if i is Cohen-Macaulay of codimension 2 @* a zero matrix otherwise EXAMPLE: example isCMcod2; shows an example" { int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //--------------------------------------------------------------------------- // Compute a minimal free resolution of the ideal and check if the // resolution has the expected structure //--------------------------------------------------------------------------- list kurveres=mres(kurve,0); matrix M=kurveres[2]; if ((size(kurveres)>3) && ((size(kurveres[3])>1) || ((size(kurveres[3])<=1) && (kurveres[3][1,1]!=0)))) { dbprint(p,"//not Cohen-Macaulay, codim 2"); matrix ret=0; return(ret); } return(M); } example { "EXAMPLE:"; echo=2; ring r=32003,(x,y,z),ds; ideal i=xz,yz,x^3-y^4; print(isCMcod2(i)); } ///////////////////////////////////////////////////////////////////////////// proc CMtype(ideal kurve) "USAGE: CMtype(i); i an ideal, CM of codimension 2 RETURN: Cohen-Macaulay type of i (integer) (-1, if i is not Cohen-Macaulay of codimension 2) EXAMPLE: example CMtype; shows an example" { int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) int gt = -1; //--------------------------------------------------------------------------- // Compute a minimal free resolution of the ideal and check if the // resolution has the expected structure //--------------------------------------------------------------------------- list kurveres; kurveres=mres(kurve,0); if ((size(kurveres)>3) && ((size(kurveres[3])>1) || ((size(kurveres[3])<=1) && (kurveres[3][1,1]!=0)))) { dbprint(p,"//not Cohen-Macaulay, codim 2"); return(gt); } //--------------------------------------------------------------------------- // Return the Cohen-Macaulay type of i //--------------------------------------------------------------------------- matrix M = matrix(kurveres[2]); gt = ncols(M); return(gt); } example { "EXAMPLE:"; echo=2; ring r=32003,(x,y,z),ds; ideal i=xy,xz,yz; CMtype(i); } ///////////////////////////////////////////////////////////////////////////// proc matrixT1(matrix M ,int n) "USAGE: matrixT1(M,n); M matrix, n integer ASSUME: M is a presentation matrix of an ideal i, CM of codimension 2; consider i as a family of ideals in a ring in the first n variables where the remaining variables are considered as parameters RETURN: list consisting of the k x (k+1) matrix M and a module K_M such that T1=Mat(k,k+1;R)/K_M is the space of first order deformations of i EXAMPLE: example matrixT1; shows an example" { int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //-------------------------------------------------------------------------- // Initialization and sanity checks //-------------------------------------------------------------------------- int nr=nrows(M); int nc=ncols(M); if ( nr < nc ) { M=transpose(M); int temp=nc; nc=nr; nr=temp; int tra=1; } if ( nr != (nc+1) ) { ERROR("not a k x (k+1) matrix"); } //--------------------------------------------------------------------------- // Construct the denominator - step by step // step 1: initialization //--------------------------------------------------------------------------- int gt=nc; int i,j; ideal m = M; ideal dx; ideal rv; ideal lv; matrix R[gt][gt]=0; matrix L[gt+1][gt+1]=0; matrix T1[n+gt*gt+(gt+1)*(gt+1)][gt*(gt+1)] = 0; //--------------------------------------------------------------------------- // step 2: the derivatives of the matrix are generators of the denominator //--------------------------------------------------------------------------- for( i=1; i<= n; i++ ) { dx=diff(m,var(i)); T1[i,1..gt*(gt+1)] = dx; } //--------------------------------------------------------------------------- // step 3: M*R is a generator as well //--------------------------------------------------------------------------- for( i=1; i <= gt; i++ ) { for ( j=1 ; j <= gt ; j++ ) { R[i,j]=1; rv = M * R; T1[n+(i-1)*gt+j,1..gt*(gt+1)] = rv; R[i,j]=0; } } //--------------------------------------------------------------------------- // step 4: so is L*M //--------------------------------------------------------------------------- for( i=1; i <= (gt+1); i++) { for( j=1 ; j <= (gt+1);j++ ) { L[i,j]=1; lv = L * M; T1[n+gt*gt+(i-1)*(gt+1)+j,1..gt*(gt+1)] = lv; L[i,j]=0; } } //--------------------------------------------------------------------------- // Compute the vectorspace basis of T1 //--------------------------------------------------------------------------- module t1 = module(transpose(T1)); list result=M,t1; return(result); } example { "EXAMPLE:"; echo = 2; ring r=32003,(x(1),x(2),x(3)),ds; ideal curve=x(1)*x(2),x(1)*x(3),x(2)*x(3); matrix M=isCMcod2(curve); matrixT1(M,3); } ///////////////////////////////////////////////////////////////////////////// proc semiCMcod2(matrix M, module t1,list #) "USAGE: semiCMcod2(M,t1[,s]); M matrix, t1 module, s any ASSUME: M is a presentation matrix of an ideal i, CM of codimension 2, and t1 is a presentation of the space of first order deformations of i ((M,t1) as returned by the procedure matrixT1) RETURN: new ring in which the ideal semi describing the semiuniversal deformation of i; if the optional third argument is given, the perturbation matrix of the semiuniversal deformation is returned instead of the ideal. NOTE: The current basering should not contain any variables named A(j) where j is some integer! EXAMPLE: example semiCMcod2; shows an example" { int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //--------------------------------------------------------------------------- // Initialization //--------------------------------------------------------------------------- module t1erz=kbase(std(t1)); int tau=vdim(t1); int gt=ncols(M); int i; def r=basering; if(size(M)!=gt*(gt+1)) { gt=gt-1; } for(i=1; i<=size(t1erz); i++) { if(rvar(A(i))) { int jj=-1; break; } } if (defined(jj)>1) { if (jj==-1) { ERROR("Your ring contains a variable T(i)!"); } } //--------------------------------------------------------------------------- // Definition of the new ring and the image of M and t1 in the new ring //--------------------------------------------------------------------------- ring rtemp=0,(A(1..tau)),dp; def rneu=r+rtemp; setring rneu; matrix M=imap(r,M); ideal m=M; module t1erz=imap(r,t1erz); //--------------------------------------------------------------------------- // Construction of the presentation matrix of the versal deformation //--------------------------------------------------------------------------- matrix N=matrix(m); matrix Mtemp[gt*(gt+1)][1]; for( i=1; i<=tau; i++) { Mtemp=t1erz[i]; N=N+A(i)*transpose(Mtemp); } ideal n=N; matrix O[gt+1][gt]=n; //--------------------------------------------------------------------------- // Construction of the return value //--------------------------------------------------------------------------- if(size(#)>0) { matrix semi=O; } else { ideal semi=minor(O,gt); } export semi; return(rneu); } example { "EXAMPLE:"; echo=2; ring r=32003,(x(1),x(2),x(3)),ds; ideal curve=x(1)*x(2),x(1)*x(3),x(2)*x(3); matrix M=isCMcod2(curve); list l=matrixT1(M,3); def rneu=semiCMcod2(l[1],std(l[2])); setring rneu; semi; } ///////////////////////////////////////////////////////////////////////////// proc discr(ideal kurve, int n) "USAGE: discr(sem,n); sem ideal, n integer ASSUME: sem is the versal deformation of an ideal of codimension 2. @* The first n variables of the ring are treated as variables all the others as parameters. RETURN: ideal describing the discriminant NOTE: This is not a powerful algorithm! EXAMPLE: example discr; shows an example" { int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //--------------------------------------------------------------------------- // some sanity checks and initialization //--------------------------------------------------------------------------- int i; ideal sem=std(kurve); ideal semdiff; ideal J2; int ncol=ncols(matrix(sem)); matrix Jacob[n][ncol]; //--------------------------------------------------------------------------- // compute the Jacobian matrix //--------------------------------------------------------------------------- for (i=1; i<=n; i++) { semdiff=diff(sem,var(i)); Jacob[i,1..ncol]=semdiff; } //--------------------------------------------------------------------------- // eliminate the first n variables in the ideal generated by // the versal deformation and the 2x2 minors of the Jacobian //--------------------------------------------------------------------------- semdiff=minor(Jacob,2); J2=sem,semdiff; J2=std(J2); poly eli=1; for(i=1; i<=n; i++) { eli=eli*var(i); } ideal dis=eliminate(J2,eli); return(dis); } example { "EXAMPLE:"; echo=2; ring r=32003,(x(1),x(2),x(3)),ds; ideal curve=x(1)*x(2),x(1)*x(3),x(2)*x(3); matrix M=isCMcod2(curve); list l=matrixT1(M,3); def rneu=semiCMcod2(l[1],std(l[2])); setring rneu; discr(semi,3); } ///////////////////////////////////////////////////////////////////////////// proc qhmatrix(matrix M) "USAGE: qhmatrix(M); M a k x (k+1) matrix RETURN: list, consisting of an integer vector containing the weights of the variables of the basering and an integer matrix giving the weights of the entries of M, if M is quasihomogeneous; zero integer vector and zero integer matrix, if M is not quasihomogeneous, i.e. does not allow row and column weights EXAMPLE: example qhmatrix; shows an example" { int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- def r=basering; int i,j,temp; int tra=0; int nr=nrows(M); int nc=ncols(M); if ( nr > nc ) { M=transpose(M); temp=nc; nc=nr; nr=temp; tra=1; } if ( nc != (nr+1) ) { ERROR("not a k x (k+1) matrix"); } ideal m=minor(M,nr); //--------------------------------------------------------------------------- // get the weight using the fact that the matrix is quasihomogeneous, if // its maximal minors are, and check, whether M is really quasihomogeneous //--------------------------------------------------------------------------- intvec a=weight(m); string tempstr="ring rneu=" + charstr(r) + ",(" + varstr(r) + "),Ws(" + string(a) + ");"; execute(tempstr); def M=imap(r,M); int difset=0; list l; int dif; int donttest=0; int comprow=0; intmat W[nr][nc]; //--------------------------------------------------------------------------- // find a row not containing a 0 //--------------------------------------------------------------------------- for(i=1; i<=nr; i++) { if(comprow==0) { comprow=i; for(j=1; j<=nc; j++) { if(M[i,j]==0) { comprow=0; break; } } } } //--------------------------------------------------------------------------- // get the weights of the comprow'th row or use emergency exit //--------------------------------------------------------------------------- if(comprow==0) { intvec v=0; intmat V=0 list ret=v,V; return(ret); } else { for(j=1; j<=nc; j++) { l[j]=deg(lead(M[comprow,j])); } } //--------------------------------------------------------------------------- // do the checks //--------------------------------------------------------------------------- for(i=1; i<=nr; i++) { if ( i==comprow ) { // this row should not be tested against itself donttest=1; } else { // initialize the difference of the rows, but ignore 0-entries if (M[i,1]!=0) { dif=deg(lead(M[i,1]))-l[1]; difset=1; } else { list memo; memo[1]=1; } } // check column by column for(j=1; j<=nc; j++) { if(M[i,j]==0) { if(defined(memo)!=0) { memo[size(memo)+1]=j; } else { list memo; memo[1]=j; } } temp=deg(lead(M[i,j])); if((difset!=1) && (donttest!=1) && (M[i,j]!=0)) { // initialize the difference of the rows, if necessary - still ignore 0s dif=deg(lead(M[i,j]))-l[j]; difset=1; } // is M[i,j] quasihomogeneous - else emergency exit if(M[i,j]!=jet(M[i,j],temp,a)-jet(M[i,j],temp-1,a)) { intvec v=0; intmat V=0; list ret=v,V; return(ret); } if(donttest!=1) { // check row and column weights - else emergency exit if(((temp-l[j])!=dif) && (M[i,j]!=0) && (difset==1)) { intvec v=0; intmat V=0; list ret=v,V; return(ret); } } // set the weight matrix entry W[i,j]=temp; } // clean up the 0's we left out if((difset==1) && (defined(memo)!=0)) { for(j=1; j<=size(memo); j++) { W[i,memo[j]]=dif+l[memo[j]]; } kill memo; } donttest=0; } //--------------------------------------------------------------------------- // transpose, if M was transposed during initialization, and return the list //--------------------------------------------------------------------------- if ( tra==1 ) { W=transpose(W); } setring r; list ret=a,W; return(ret); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),ds; matrix M[3][2]=z,0,y,x,x^3,y; qhmatrix(M); pmat(M); } ///////////////////////////////////////////////////////////////////////////// proc relweight(matrix N, intmat W, intvec a) "USAGE: relweight(N,W,a); N matrix, W intmat, a intvec ASSUME: N is a non-zero matrix W is an integer matrix of the same size as N a is an integer vector giving the weights of the variables RETURN: integer, max(a-weighted order(N_ij) - W_ij | all entries ij) @* string \"ERROR\" if sizes do not match EXAMPLE: example relweight; shows an example " { int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- if ((size(N)!=size(W)) || (ncols(N)!=ncols(W))) { ERROR("matrix size does not match"); } if (size(a)!=nvars(basering)) { ERROR("length of weight vector != number of variables"); } int i,j,temp; def r=basering; //--------------------------------------------------------------------------- // Comparision entry by entry //--------------------------------------------------------------------------- for(i=1; i<=nrows(N); i++) { for(j=1; j<=ncols(N); j++) { if (N[i,j]!=0) { temp=mindeg1(N[i,j],a)-W[i,j]; if (defined(ret)) { if(temp > ret) { ret=temp; } } else { int ret=temp; } } } } return(ret); } example { "EXAMPLE:"; echo=2; ring r=32003,(x,y,z),ds; matrix N[2][3]=z,0,y,x,x^3,y; intmat W[2][3]=1,1,1,1,1,1; intvec a=1,1,1; relweight(N,W,a); } ///////////////////////////////////////////////////////////////////////////// proc posweight(matrix M, module t1, int choose, list #) "USAGE: posweight(M,t1,n[,s]); M matrix, t1 module, n int, s string @* n=0 : all deformations of non-negative weight @* n=1 : only non-constant deformations of non-negative weight @* n=2 : all deformations of positive weight @* ASSUME: M is a presentation matrix of a Cohen-Macaulay codimension 2 ideal and t1 is its T1 space in matrix notation RETURN: new ring containing a list posw, consisting of a presentation matrix describing the deformation given by the generators of T1 of non-negative/positive weight and the weight vector for the new variables NOTE: The current basering should not contain any variables named T(i) where i is some integer! EXAMPLE: example posweight; shows an example" { //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- if (size(#)>0) { if (typeof(#[1])=="string") { string newname=#[1]; } } if (attrib(t1,"isSB")) { module t1erz=kbase(t1); int tau=vdim(t1); } else { module t1erz=kbase(std(t1)); int tau=vdim(std(t1)); } for(int i=1; i<=size(t1erz); i++) { if(rvar(T(i))) { int jj=-1; break; } } kill i; if (defined(jj)) { if (jj==-1) { ERROR("Your ring contains a variable T(i)!"); } } int pw=0; int i; def r=basering; list l=qhmatrix(M); int gt=ncols(M); if(size(M)!=gt*(gt+1)) { gt=gt-1; } matrix erzmat[gt+1][gt]; list erz; if ((size(l[1])==1) && (l[1][1]==0) && (size(l[2])==1) && (l[2][1,1]==0)) { ERROR("Internal Error: Problem determining the weights."); } //--------------------------------------------------------------------------- // Find the generators of T1 of non-negative weight //--------------------------------------------------------------------------- int relw; list rlw; for(i=1; i<=tau; i++) { erzmat=t1erz[i]; kill relw; def relw=relweight(erzmat,l[2],l[1]); if(typeof(relw)=="int") { if (((choose==0) && (relw>=0)) || ((choose==1) && (relw>=0) && (CMtype(minor(M+erzmat,gt))==gt)) || ((choose==2) && (relw > 0))) { pw++; rlw[pw]=relw; erz[pw]=erzmat; } } else { ERROR("Internal Error: Problem determining relative weight."); } } //--------------------------------------------------------------------------- // Definition of the new ring and the image of M and erz in the new ring //--------------------------------------------------------------------------- if(size(rlw)==0) { ERROR("Internal Error: Problem determining relative weight."); } intvec iv=rlw[1..size(rlw)]; ring rtemp=0,(T(1..pw)),dp; def rneu=r+rtemp; setring rneu; matrix M=imap(r,M); ideal m=M; // we cannot imap erz, if its size=0 if(pw==0) { list erz1; } else { list erz1=imap(r,erz); } //--------------------------------------------------------------------------- // Construction of the presentation matrix of the deformation //--------------------------------------------------------------------------- matrix N=matrix(m); ideal mtemp; matrix Mtemp[gt*(gt+1)][1]; for( i=1; i<=pw; i++) { mtemp=erz1[i]; Mtemp=mtemp; N=N+T(i)*transpose(Mtemp); } ideal n=N; matrix O[gt+1][gt]=n; //--------------------------------------------------------------------------- // Keep the matrix and return the ring in which it lives //--------------------------------------------------------------------------- list posw=O,iv; export posw; return(rneu); } example { "EXAMPLE:"; echo=2; ring r=32003,(x(1),x(2),x(3)),ds; ideal curve=(x(3)-x(1)^2)*x(3),(x(3)-x(1)^2)*x(2),x(2)^2-x(1)^7*x(3); matrix M=isCMcod2(curve); list l=matrixT1(M,3); def rneu=posweight(l[1],std(l[2]),0); setring rneu; pmat(posw[1]); posw[2]; } ///////////////////////////////////////////////////////////////////////////// proc KSpencerKernel(matrix M,list #) "USAGE: KSpencerKernel(M[,s][,v]); M matrix, s string, v intvec @* optional parameters (please specify in this order, if both are present): * s = first of the names of the new rings e.g. \"R\" leads to ring names R and R1 * v of size n(n+1) leads to the following module ordering @* gen(v[1]) > gen(v[2]) > ... > gen(v[n(n+1)]) where the matrix entry ij corresponds to gen((i-1)*n+j) ASSUME: M is a quasihomogeneous n x (n+1) matrix where the n minors define an isolated space curve singularity RETURN: new ring containing the coefficient matrix KS representing the kernel of the Kodaira-Spencer map of the family of non-negative deformations having the given singularity as special fibre NOTE: * the initial basering should not contain variables with name e(i) or T(i), since those variable names will internally be used by the script * setting an intvec with 5 entries and name watchProgress shows the progress of the computations: @* watchProgress[1]>0 => option(prot) in groebner commands @* watchProgress[2]>0 => trace output for highcorner @* watchProgress[3]>0 => output of deformed matrix @* watchProgress[4]>0 => result of elimination step @* watchProgress[4]>1 => trace output of multiplications with xyz and subsequent reductions @* watchProgress[5]>0 => matrix representing the kernel using print EXAMPLE: example KSpencerKernel; shows an example" { int p = printlevel-voice+3; // p=printlevel+1 (default: p=1) //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- intvec optvec=option(get); if (size(#)>0) { if (typeof(#[1])=="string") { string newname=#[1]; } if (typeof(#[1])=="intvec") { intvec desiredorder=#[1]; } if (size(#)>1) { if (typeof(#[2])=="intvec") { intvec desiredorder=#[2]; } } } if (defined(watchProgress)) { if ((typeof(watchProgress)!="intvec") || (size(watchProgress)<5)) { "watchProgress should be an intvec with at least 5 entries"; "ignoring watchProgress"; def kksave=watchProgress; kill watchProgress; } } option(redTail); if (nvars(basering) != 3 ) { ERROR("It should be a curve in 3 space"); } //--------------------------------------------------------------------------- // change to a basering with the correct weihted order //--------------------------------------------------------------------------- def rt=basering; list wl=qhmatrix(M); if ((size(wl)!=2) || ((wl[1]==0) && (wl[2]==0))) { ERROR("The matrix was not n x (n+1) or not quasihomogenous"); } string ringre=" ring r=" + charstr(rt) + ",(x,y,z), Ws(" + string(wl[1]) + ");"; execute(ringre); matrix M=imap(rt,M); int ne=size(M); if (defined(desiredorder)>1) { intvec iv; for(int i=1;i<=size(desiredorder);i++) { iv[desiredorder[i]]=i; } } else { intvec iv=1..ne; } list l=matrixT1(M,3); if (dim(std(l[2])) != 0) { ERROR("The matrix does not define an isolated space curve singularity"); } module t1qh=l[2]; //-------------------------------------------------------------------------- // Passing to a new ring with extra variables e(i) corresponding to // the module generators gen(i) for weighted standard basis computation // accepting weights for the gen(i) //-------------------------------------------------------------------------- int jj=0; for(int i=1; i<=ne; i++) { if(rvar(e(i))) { jj=-1; } } if (jj==-1) { ERROR("Your ring contains a variable e(i)!"); } if(defined(desiredorder)>1) { ringre="ring re=" + charstr(r) +",(e(1.." + string(ne) + "),"+ varstr(basering) + "),Ws("; intvec tempiv=intvec(wl[2]); for(i=1;i<=ne;i++) { ringre=ringre + string((-1)*tempiv[desiredorder[i]]) + ","; } ringre= ringre + string(wl[1]) + ");"; } else { ringre="ring re=" + charstr(r) +",(e(1.." + string(ne) + "),"+ varstr(basering) + "),Ws(" + string((-1)*intvec(wl[2])) + "," + string(wl[1]) + ");"; } execute(ringre); module temp=imap(r,t1qh); ideal t1qh=mod2id(temp,iv); if (defined(watchProgress)) { if (watchProgress[1]!=0) { option(prot); "Protocol output of the groebner computation (quasihomogenous case)"; } } ideal t1qhs=std(t1qh); if (defined(watchProgress)) { if (watchProgress[1]!=0) { "groebner computation finished"; option(noprot); } } ideal t1qhsl=lead(t1qhs); module mo=id2mod(t1qhsl,iv); //-------------------------------------------------------------------------- // Return to the initial ring to compute the kbase and noether there // (in the new ring t1qh is of course not of dimension 0 but of dimension 3 // so we have to go back) //-------------------------------------------------------------------------- setring r; module mo=imap(re,mo); attrib(mo,"isSB",1); // mo is monomial ==> SB attrib(mo,"isHomog",intvec(wl[2])); // highcorner has to respect the weights vector noe=highcorner(mo); if (defined(watchProgress)) { if (watchProgress[2]!=0) { "weights corresponding to the entries of the matrix:"; wl; "leading term of the groebner basis (quasihomogeneous case)"; mo; "noether"; noe; } } //-------------------------------------------------------------------------- // Define the family of curves with the same quasihomogeneous initial // matrix M, compute T1 and pass again to the ring with the variables e(i) //-------------------------------------------------------------------------- def rneu=posweight(M,mo,2); setring rneu; list li=posw; if (size(li)<=1) { ERROR("Internal Error: Problem determining perturbations of weight > 0.") } if (defined(watchProgress)) { if(watchProgress[3]!=0) { "perturbed matrix and weights of the perturbations:"; li; } } list li2=matrixT1(li[1],3); module Mpert=transpose(matrix(ideal(li2[1]))); module t1pert=li2[2]; int nv=nvars(rneu)-nvars(r); ring rtemp=0,(T(1..nv)),wp(li[2]); def reneu=re+rtemp; setring reneu; module noe=matrix(imap(r,noe)); ideal noet=mod2id(noe,iv); module temp=imap(rneu,t1pert); ideal t1pert=mod2id(temp,iv); //-------------------------------------------------------------------------- // Compute the standard basis and select those generators with leading term // divisible by some T(i) //-------------------------------------------------------------------------- noether=noet[size(noet)]; if (defined(watchProgress)) { if (watchProgress[1]!=0) { "protocol output of the groebner command (perturbed case)"; option(prot); } } ideal t1perts=std(t1pert); noether=noet[size(noet)]; t1perts=interred(t1perts); if (defined(Debug)) { if (watchProgress[1]!=0) { "groebner computation finished (perturbed case)"; option(noprot); } } ideal templ=lead(t1perts); for(int j=1;j<=nv;j++) { templ=subst(templ,T(j),0); } ideal mx; ideal mt; for(j=1;j<=size(t1perts);j++) { if(templ[j]!=0) { mx=mx,t1perts[j]; } else { mt=mt,t1perts[j]; } } //-------------------------------------------------------------------------- // multiply by the initial ring variables to shift the generators with // leading term divisible by some T(i) and reduce afterwards //-------------------------------------------------------------------------- // This is obviously no SB, but we have to reduce by attrib(mx,"isSB",1); // it and setting isSB suppresses error messages noether=noet[size(noet)]; ideal ker_gen=reduce(mt,mx); ideal ovar=var(ne+1),var(ne+2),var(ne+3); j=1; noether=noet[size(noet)]; if (defined(watchProgress)) { if (watchProgress[4]!=0) { "generators of the kernel as a C[T]{x} module:"; mt; "noether:"; noether; } } int zeros; templ=ker_gen; while(zeros==0) { zeros=1; templ=templ*ovar; templ=reduce(templ,mx); if(defined(watchProgress)) { if(watchProgress[4]>1) { templ; } } if (size(templ)!= 0) { zeros=0; ker_gen=ker_gen,templ; } } //------------------------------------------------------------------------- // kill zero entries, keep only one of identical entries //------------------------------------------------------------------------- ovar=var(1); for(i=2;i<=ne;i++) { ovar=ovar,var(i); } ker_gen=ker_gen,ovar^2; noether=noet[size(noet)]; ker_gen=simplify(ker_gen,10); //------------------------------------------------------------------------- // interreduce ker_gen as a k[T]-module //------------------------------------------------------------------------- intvec mgen=1..(ne+3); ideal Mpert=mod2id(imap(rneu,Mpert),iv); templ=0; for(i=1;i<=nv;i++) { templ[i]=diff(Mpert[size(Mpert)],T(i)); } templ=templ,ovar^2; list retl=subrInterred(templ,ker_gen,mgen); // Build up the matrix representing L module retlm=transpose(retl[2]); for(i=1;i<=size(retl[1]);i++) { if(reduce(retl[1][1,i],std(ovar^2))==0) { retlm[i]=0; } } retlm=simplify(transpose(simplify(transpose(retlm),10)),10); if(defined(watchProgress)) { if(watchProgress[5]>0) { print(retlm); } } ker_gen=retl[3]; // we define ret=i(L),(delta_j(t_k))_jk list ret=id2mod(ker_gen,iv),matrix(retlm); // cleanups - define what we previously killed if(defined(kksave)>1) { def watchProgress=kksave; export watch Progress; } option(set,optvec); def KS=ret[2]; export KS; return(reneu); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),ds; matrix M[3][2]=z-x^7,0,y^2,z,x^9,y; def rneu=KSpencerKernel(M,"ar"); setring rneu; basering; print(KS); } /////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/spectrum.lib000066400000000000000000000031641266270727000205050ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version spectrum.lib 4.0.0.0 Jun_2013 "; // $Id: f3e0a4f4c041175ac3b07f429fc854f78ecb0cde $ category="Singularities"; info=" LIBRARY: spectrum.lib Singularity Spectrum for Nondegenerate Singularities AUTHOR: S. Endrass PROCEDURES: spectrumnd(poly f[,1]); spectrum of nondegenerate isolated singularity f "; /////////////////////////////////////////////////////////////////////////////// proc spectrumnd (poly f,list #) "USAGE: spectrumnd(f[,1]); poly f ASSUME: basering has characteristic 0 and local ordering, f has isolated singularity at 0 and nondegenerate principal part RETURN: @format list S: ideal S[1]: spectral numbers in increasing order intvec S[2]: int S[2][i]: multiplicity of spectral number S[1][i] @end format NOTE: if a second argument 1 is given, no test for a degenerate principal part will be done SEE_ALSO: gmssing_lib KEYWORDS: singularities; Gauss-Manin connection; spectrum EXAMPLE: example spectrumnd; shows an example " { if(charstr(basering)!="0") { ERROR("characteristic 0 expected"); } if(size(#)==0) { list S=system("spectrum",f); } else { list S=system("spectrum",f,#[1]); } ideal a=number(S[4][1])/S[5][1]-1; int i; for(i=S[3];i>1;i--) { a[i]=number(S[4][i])/S[5][i]-1; } return(list(a,S[6])); } example { "EXAMPLE:"; echo = 2; ring R=0,(x,y),ds; poly f=x^31+x^6*y^7+x^2*y^12+x^13*y^2+y^29; list s=spectrumnd(f); size(s[1]); s[1][22]; s[2][22]; } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/standard.lib000066400000000000000000002144421266270727000204460ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////// version="version standard.lib 4.0.0.0 Jun_2013 "; // $Id: d657b982e59d14d7ef8c829e61865a62f9822bcd $ category="Miscellaneous"; info=" LIBRARY: standard.lib Procedures which are always loaded at Start-up PROCEDURES: stdfglm(ideal[,ord]) standard basis of ideal via fglm [and ordering ord] stdhilb(ideal[,h]) Hilbert driven Groebner basis of ideal groebner(ideal,...) standard basis using a heuristically chosen method res(ideal/module,[i]) free resolution of ideal or module sprintf(fmt,...) returns fomatted string fprintf(link,fmt,..) writes formatted string to link printf(fmt,...) displays formatted string weightKB(stc,dd,vl) degree dd part of a kbase w.r.t. some weigths qslimgb(i) computes a standard basis with slimgb in a qring par2varRing([i]) create a ring making pars to vars, together with i datetime() return date and time as a string max(i_1,...,i_k) maximum of i_1, ..., i_k min(i_1,...,i_k) minimum of i_1, ..., i_k "; //AUXILIARY PROCEDURES: // hilbRing([i]) ring for computing the (weighted) hilbert series // quotientList(L,...) ringlist for creating a correct quotient ring ////////////////////////////////////////////////////////////////////////////// proc stdfglm (ideal i, list #) "SYNTAX: @code{stdfglm (} ideal_expression @code{)} @* @code{stdfglm (} ideal_expression@code{,} string_expression @code{)} TYPE: ideal PURPOSE: computes the standard basis of the ideal in the basering via @code{fglm} from the ordering given as the second argument to the ordering of the basering. If no second argument is given, \"dp\" is used. The standard basis for the given ordering (resp. for \"dp\") is computed via the command groebner except if a further argument \"std\" or \"slimgb\" is given in which case std resp. slimgb is used. SEE ALSO: fglm, groebner, std, slimgb, stdhilb KEYWORDS: fglm EXAMPLE: example stdfglm; shows an example" { string os; int s = size(#); def P= basering; string algorithm; int ii; for( ii=1; ii<=s; ii++) { if ( typeof(#[ii])== "string" ) { if ( #[ii]=="std" || #[ii]=="slimgb" ) { algorithm = #[ii]; # = delete(#,ii); s--; ii--; } } } if((s > 0) && (typeof(#[1]) == "string")) { os = #[1]; ideal Qideal = ideal(P); int sQ = size(Qideal); int sM = size(minpoly); if ( sM!=0 ) { string mpoly = string(minpoly); } if (sQ!=0 ) { execute("ring Rfglm=("+charstr(P)+"),("+varstr(P)+"),"+os+";"); ideal Qideal = fetch(P,Qideal); qring Pfglm = groebner(Qideal,"std","slimgb"); } else { execute("ring Pfglm=("+charstr(P)+"),("+varstr(P)+"),"+os+";"); } if ( sM!=0 ) { execute("minpoly="+mpoly+";"); } } else { list BRlist = ringlist(P); int nvarP = nvars(P); intvec w; //for ringweights of basering P int k; for(k=1; k <= nvarP; k++) { w[k]=deg(var(k)); } BRlist[3] = list(); if( s==0 or (typeof(#[1]) != "string") ) { if( w==1 ) { BRlist[3][1]=list("dp",w); } else { BRlist[3][1]=list("wp",w); } BRlist[3][2]=list("C",intvec(0)); def Pfglm = ring(quotientList(BRlist)); setring Pfglm; } } ideal i = fetch(P,i); intvec opt = option(get); //save options option(redSB); if (size(algorithm) > 0) { i = groebner(i,algorithm); } else { i = groebner(i); } option(set,opt); setring P; return (fglm(Pfglm,i)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),lp; ideal i = y3+x2,x2y+x2,x3-x2,z4-x2-y; stdfglm(i); //uses fglm from "dp" (with groebner) to "lp" stdfglm(i,"std"); //uses fglm from "dp" (with std) to "lp" ring s = (0,x),(y,z,u,v),lp; minpoly = x2+1; ideal i = u5-v4,zv-u2,zu3-v3,z2u-v2,z3-uv,yv-zu,yu-z2,yz-v,y2-u,u-xy2; weight(i); stdfglm(i,"(a(2,3,4,5),dp)"); //uses fglm from "(a(2,3,4,5),dp)" to "lp" } ///////////////////////////////////////////////////////////////////////////// proc stdhilb(def i,list #) "SYNTAX: @code{stdhilb (} ideal_expression @code{)} @* @code{stdhilb (} module_expression @code{)} @* @code{stdhilb (} ideal_expression, intvec_expression @code{)}@* @code{stdhilb (} module_expression, intvec_expression @code{)}@* @code{stdhilb (} ideal_expression@code{,} list of string_expressions, and intvec_expression @code{)} @* TYPE: type of the first argument PURPOSE: Compute a Groebner basis of the ideal/module in the basering by using the Hilbert driven Groebner basis algorithm. If an argument of type string, stating @code{\"std\"} resp. @code{\"slimgb\"}, is given, the standard basis computation uses @code{std} or @code{slimgb}, otherwise a heuristically chosen method (default)@* If an optional second argument w of type intvec is given, w is used as variable weights. If w is not given, it is computed as w[i] = deg(var(i)). If the ideal is homogeneous w.r.t. w then the Hilbert series is computed w.r.t. to these weights. THEORY: If the ideal is not homogeneous compute first a Groebner basis of the homogenization [w.r.t. the weights w] of the ideal/module, then the Hilbert function and, finally, a Groebner basis in the original ring by using the computed Hilbert function. If the given w does not coincide with the variable weights of the basering, the result may not be a groebner basis in the original ring. NOTE: 'Homogeneous' means weighted homogeneous with respect to the weights w[i] of the variables var(i) of the basering. Parameters are not converted to variables. SEE ALSO: stdfglm, std, slimgb, groebner KEYWORDS: Hilbert function EXAMPLE: example stdhilb; shows an example" { //--------------------- save data from basering -------------------------- def P=basering; int nr; if (typeof(i)=="ideal") { nr=1;} else { nr= nrows(i); } //nr=1 if i is an ideal ideal Qideal = ideal(P); //defining the quotient ideal if P is a qring int was_qring; //remembers if basering was a qring int is_homog =homog(i); //check for homogeneity of i and Qideal if (size(Qideal) > 0) { was_qring = 1; } // save ordering of basering P for later use list ord_P = ringlist(P)[3]; //ordering of basering in ringlist string ordstr_P = ordstr(P); //ordering of basering as string int nvarP = nvars(P); //save options: intvec gopt = option(get); int p_opt; string s_opt = option(); if (find(s_opt, "prot")) { p_opt = 1; } //-------------------- check the given method and weights --------------------- //Note: stdhilb is used in elim where it is applied to an elimination ordering //a(1..1,0..0),wp(w). In such a ring deg(var(k)=0 for all vars corresponding to //0 in a(1..1,0..0), hence we cannot identify w via w[k] = deg(var(k)); //Therefore hilbstd has the option to give ringweights. int k; string method; for (k=1; k<=size(#); k++) { if (typeof(#[k]) == "intvec") { intvec w = #[k]; //given ringweights of basering P } if (typeof(#[k]) == "string") { method = method + "," + #[k]; } } if ( defined(w)!=voice ) { intvec w; for(k=nvarP; k>=1; k--) { w[k] = deg(var(k)); //compute ring weights } } if (npars(P) > 0) //clear denominators of parameters { for( k=ncols(i); k>0; k-- ) { i[k]=cleardenom(i[k]); } } //---------- exclude cases to which stdhilb should no be applied ---------- //Note that quotient ideal of qring must be homogeneous too int neg=1-attrib (P,"global"); if( //find(ordstr_P,"s") ||// covered by neg find(ordstr_P,"M") || neg ) { // if( defined(hi) && is_homog ) // { // if (p_opt){"std with given Hilbert function in basering";} // return( std(i,hi,w) ); //### here we would need Hibert-Samuel function // } if (p_opt) {"//-- stdhilb not implemented, we use std in ring:"; string(P);} return( std(i) ); } //------------------------ change to hilbRing ---------------------------- //The ground field of P and Philb coincide, Philb has an extra variable //@ or @(k). Philb is no qring and the predefined ideal/module Id(1) in //Philb is homogeneous (it is the homogenized i w.r.t. @ or @(k)) //Parameters of P are not converted in Philb //Philb has only 1 block dp or wp(w) list hiRi = hilbRing(i,w); intvec W = hiRi[2]; def Philb = hiRi[1]; setring Philb; //-------- compute Hilbert series of homogenized ideal in Philb --------- //There are three cases string algorithm; //possibilities: std, slimgb, stdorslimgb //define algorithm: if( find(method,"std") && !find(method,"slimgb") ) { algorithm = "std"; } if( find(method,"slimgb") && !find(method,"std") ) { algorithm = "slimgb"; } if( find(method,"std") && find(method,"slimgb") || (!find(method,"std") && !find(method,"slimgb")) ) { algorithm = "stdorslimgb"; } //### geaendert Dez08: es wird std(Id(1)) statt Id(1) aus Philb nach Phelp // weitergegeben fuer hilbertgetriebenen std if (( algorithm=="std" || ( algorithm=="stdorslimgb" && char(P)>0 ) ) && (defined(hi)!=voice)) { if (p_opt) {"compute hilbert series with std in ring " + string(Philb); "weights used for hilbert series:",W;} Id(1) = std(Id(1)); intvec hi = hilb( Id(1),1,W ); } if (( algorithm=="slimgb" || ( algorithm=="stdorslimgb" && char(P)==0 ) ) && (defined(hi)!=voice)) { if (p_opt) {"compute hilbert series with slimgb in ring " + string(Philb); "weights used for hilbert series:",W;} Id(1) = qslimgb(Id(1)); intvec hi = hilb( Id(1),1,W ); } //-------------- we need another intermediate ring Phelp ---------------- //In Phelp we change only the ordering from Philb (otherwise it coincides //with Philb). Phelp has in addition to P an extra homogenizing variable //with name @ (resp. @(i) if @ and @(1), ..., @(i-1) are defined) with //ordering an extra last block dp(1). //Phelp has the same ordering as P on common variables. In Phelp //a quotient ideal from P is added to the input list BRlist = ringlist(Philb); BRlist[3] = list(); int so = size(ord_P); if( ord_P[so][1] =="c" || ord_P[so][1] =="C" ) { list moduleord = ord_P[so]; so = so-1; } for (k=1; k<=so; k++) { BRlist[3][k] = ord_P[k]; } BRlist[3][so+1] = list("dp",1); w = w,1; if( defined(moduleord)==voice ) { BRlist[3][so+2] = moduleord; } //--- change to extended ring Phelp and compute std with hilbert series ---- def Phelp = ring(quotientList(BRlist)); setring Phelp; def i = imap(Philb, Id(1)); kill Philb; // compute std with Hilbert series option(redThrough); if (w == 1) { if (p_opt){ "std with hilb in " + string(Phelp);} i = std(i, hi); } else { if(p_opt){"std with weighted hilb in "+string(Phelp);} i = std(i, hi, w); } //-------------------- go back to original ring --------------------------- //The main computation is done. Do not forget to simplfy before maping. // subst 1 for homogenizing var if ( p_opt ) { "dehomogenization"; } i = subst(i, var(nvars(basering)), 1); if (p_opt) { "simplification"; } i= simplify(i,34); setring P; if (p_opt) { "imap to ring "+string(P); } i = imap(Phelp,i); kill Phelp; if( was_qring ) { i = NF(i,std(0)); } i = simplify(i,34); // compute reduced SB if (find(s_opt, "redSB") > 0) { if (p_opt) { "//interreduction"; } i=interred(i); } attrib(i, "isSB", 1); option(set,gopt); return (i); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),lp; ideal i = y3+x2,x2y+x2z2,x3-z9,z4-y2-xz; ideal j = stdhilb(i); j; ring r1 = 0,(x,y,z),wp(3,2,1); ideal i = y3+x2,x2y+x2z2,x3-z9,z4-y2-xz; //ideal is homogeneous ideal j = stdhilb(i,"std"); j; //this is equivalent to: intvec v = hilb(std(i),1); ideal j1 = std(i,v,intvec(3,2,1)); j1; size(NF(j,j1))+size(NF(j1,j)); //j and j1 define the same ideal } /////////////////////////////////////////////////////////////////////////////// proc quotientList (list RL, list #) "SYNTAX: @code{quotientList (} list_expression @code{)} @* @code{quotientList (} list_expression @code{,} string_expression@code{)} TYPE: list PURPOSE: define a ringlist, say QL, of the first argument, say RL, which is assumed to be the ringlist of a qring, but where the quotient ideal RL[4] is not a standard basis with respect to the given monomial order in RL[3]. Then QL will be obtained from RL just by replacing RL[4] by a standard of it with respect to this order. RL itself will be returnd if size(RL[4]) <= 1 (in which case it is known to be a standard basis w.r.t. any ordering) or if a second argument \"isSB\" of type string is given. NOTE: the command ring(quotientList(RL)) defines a quotient ring correctly and should be used instead of ring(RL) if the quotient ideal RL[4] is not (or not known to be) a standard basis with respect to the monomial ordering specified in RL[3]. SEE ALSO: ringlist, ring EXAMPLE: example quotientList; shows an example" { def P = basering; if( size(#) > 0 ) { if ( #[1] == "isSB") { return (RL); } } ideal Qideal = RL[4]; //##Achtung: falls basering Nullteiler hat, kann //die SB eines Elements mehrere Elemente enthalten if( size(Qideal) <= 0) { return (RL); } RL[4] = ideal(0); def Phelp = ring(RL); setring Phelp; ideal Qideal = groebner(fetch(P,Qideal)); setring P; RL[4]=fetch(Phelp,Qideal); return (RL); } example { "EXAMPLE:"; echo = 2; ring P = 0,(y,z,u,v),lp; ideal i = y+u2+uv3, z+uv3; //i is an lp-SB but not a dp_SB qring Q = std(i); list LQ = ringlist(Q); LQ[3][1][1]="dp"; def Q1 = ring(quotientList(LQ)); setring Q1; Q1; setring Q; ideal q1 = uv3+z, u2+y-z, yv3-zv3-zu; //q1 is a dp-standard basis LQ[4] = q1; def Q2 = ring(quotientList(LQ,"isSB")); setring Q2; Q2; } /////////////////////////////////////////////////////////////////////////////// proc par2varRing (list #) "USAGE: par2varRing([l]); l list of ideals/modules [default:l=empty list] RETURN: list, say L, with L[1] a ring where the parameters of the basering have been converted to an additional last block of variables, all of weight 1, and ordering dp. If a list l with l[i] an ideal/module is given, then l[i] + minpoly*freemodule(nrows(l[i])) is mapped to an ideal/module in L[1] with name Id(i). If the basering has no parameters then L[1] is the basering. EXAMPLE: example par2varRing; shows an example" { def P = basering; int npar = npars(P); //number of parameters int s = size(#); int ii; if ( npar == 0) { dbprint(printlevel-voice+3,"// ** no parameters, ring was not changed"); for( ii = 1; ii <= s; ii++) { def Id(ii) = #[ii]; export (Id(ii)); } return(list(P)); } list rlist = ringlist(P); list parlist = rlist[1]; rlist[1] = parlist[1]; string @Minpoly = string(minpoly); //check for minpoly: int sm = size(minpoly); //now create new ring for( ii = 1; ii <= s; ii++) { def Id(ii) = #[ii]; } int nvar = size(rlist[2]); int nblock = size(rlist[3]); int k; for (k=1; k<=npar; k++) { rlist[2][nvar+k] = parlist[2][k]; //change variable list } //converted parameters get one block dp. If module ordering was in front //it stays in front, otherwise it will be moved to the end intvec OW = 1:npar; if( rlist[3][nblock][1] =="c" || rlist[3][nblock][1] =="C" ) { rlist[3][nblock+1] = rlist[3][nblock]; rlist[3][nblock] = list("dp",OW); } else { rlist[3][nblock+1] = list("dp",OW); } def Ppar2var = ring(quotientList(rlist)); setring Ppar2var; if ( sm == 0 ) { for( ii = 1; ii <= s; ii++) { def Id(ii) = imap(P,Id(ii)); export (Id(ii)); } } else { if( find(option(),"prot") ){"//add minpoly to input";} execute("poly Minpoly = " + @Minpoly + " ;"); for( ii = 1; ii <= s; ii++) { def Id(ii) = imap(P,Id(ii)); if (typeof(Id(ii))=="module") { Id(ii) = Id(ii),Minpoly*freemodule(nrows(Id(ii))); } else { Id(ii) = Id(ii),Minpoly; } export (Id(ii)); } } list Lpar2var = Ppar2var; return(Lpar2var); } example { "EXAMPLE:"; echo = 2; ring R = (0,x),(y,z,u,v),lp; minpoly = x2+1; ideal i = x3,x2+y+z+u+v,xyzuv-1; i; def P = par2varRing(i)[1]; P; setring(P); Id(1); setring R; module m = x3*[1,1,1], (xyzuv-1)*[1,0,1]; def Q = par2varRing(m)[1]; Q; setring(Q); print(Id(1)); } ////////////////////////////////////////////////////////////////////////////// proc hilbRing ( list # ) "USAGE: hilbRing([w,l]); w = intvec, l = list of ideals/modules RETURN: list, say L: L[1] is a ring and L[2] an intvec L[1] is a ring whith an extra homogenizing variable with name @, resp. @(i) if @ and @(1), ..., @(i-1) are defined. The monomial ordering of L[1] is consists of 1 block: dp if the weights of the variables of the basering, say R, are all 1, resp. wp(w,1) wehre w is either given or the intvec of weights of the variables of R, i.e. w[k]=deg(var(k)). If R is a quotient ring P/Q, then L[1] is not a quotient ring but contains the ideal @Qidealhilb@, the homogenized ideal Q of P. (Parameters of R are not touched). If a list l is given with l[i] an ideal/module, then l[i] is mapped to Id(i), the homogenized l[i]+Q*freemodule(nrows(l[i]) in L[1] (Id(i) = l[i] if l[i] is already homogeneous). L[2] is the intvec (w,1). PURPOSE: Prepare a ring for computing the (weighted) hilbert series of an ideal/module with an easy monomial ordering. NOTE: For this purpose we need w[k]=deg(var(k)). However, if the ordering contains an extra weight vector a(v,0..0)) deg(var(k)) returns 0 for k being an index which is 0 in a. Therefore we must compute w beforehand and give it to hilbRing. EXAMPLE: example hilbRing; shows an example " { def P = basering; ideal Qideal = ideal(P); //defining the quotient ideal if P is a qring if( size(Qideal) != 0 ) { int is_qring =1; } list BRlist = ringlist(P); BRlist[4] = ideal(0); //kill quotient ideal in BRlist int nvarP = nvars(P); int s = size(#); int k; for(k = 1; k <= s; k++) { if ( typeof(#[k]) == "intvec" ) { intvec w = #[k]; //given weights for the variables # = delete (#,k); } } s = size(#); for(k = 1; k <= s; k++) { def Id(k) = #[k]; int nr(k) = nrows(Id(k)); } if ( defined(w)!=voice ) { intvec w; //for ringweights of basering P for(k=1; k<=nvarP; k++) { w[k]=deg(var(k)); //degree of kth variable } } //--------------------- a homogenizing variable is added ------------------ // call it @, resp. @(k) if @(1),...,@(k-1) are defined string homvar; if ( defined(@)==0 ) { homvar = "@"; } else { k=1; while( defined(@(k)) != 0 ) { k++; } homvar = "@("+string(k)+")"; } BRlist[2][nvarP+1] = homvar; w[nvarP +1]=1; //ordering is set to (dp,C) if weights of all variables are 1 //resp. to (wp(w,1),C) where w are the ringweights of basering P //homogenizing var gets weight 1: BRlist[3] = list(); BRlist[3][2]=list("C",intvec(0)); //put module ordering always last if(w==1) { BRlist[3][1]=list("dp",w); } else { BRlist[3][1]=list("wp",w); } //-------------- change ring and get ideal from previous ring --------------- def Philb = ring(quotientList(BRlist)); kill BRlist; setring Philb; if( defined(is_qring)==voice ) { ideal @Qidealhilb@ = imap(P,Qideal); if ( ! homog(@Qidealhilb@) ) { @Qidealhilb@ = homog( @Qidealhilb@, `homvar` ); } export(@Qidealhilb@); if( find(option(),"prot") ){"add quotient ideal to input";} for(k = 1; k <= s; k++) { //homogenize if necessary def Id(k) = imap(P,Id(k)); if ( ! homog(Id(k)) ) { Id(k) = homog( imap(P,Id(k)), `homvar` ); } if (typeof(Id(k))=="module") { Id(k) = Id(k),@Qidealhilb@*freemodule(nr(k)) ; } else { Id(k) = Id(k),@Qidealhilb@ ; } export(Id(k)); } } else { for(k = 1; k <= s; k++) { //homogenize if necessary def Id(k) = imap(P,Id(k)); if ( ! homog(Id(k)) ) { Id(k) = homog( imap(P,Id(k)), `homvar` ); } export(Id(k)); } } list Lhilb = Philb,w; setring(P); return(Lhilb); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z,u,v),lp; ideal i = x+y2+z3,xy+xv+yz+zu+uv,xyzuv-1; intvec w = 6,3,2,1,1; hilbRing(i,w); def P = hilbRing(w,i)[1]; setring P; Id(1); hilb(std(Id(1)),1); ring S = 0,(x,y,z,u,v),lp; qring T = std(x+y2+z3); ideal i = xy+xv+yz+zu+uv,xyzuv-v5; module m = i*[0,1,1] + (xyzuv-v5)*[1,1,0]; def Q = hilbRing(m)[1]; Q; setring Q; print(Id(1)); } ////////////////////////////////////////////////////////////////////////////// proc qslimgb (def i) "USAGE: qslimgb(i); i ideal or module RETURN: same type as input, a standard basis of i computed with slimgb NOTE: Only as long as slimgb does not know qrings qslimgb should be used in case the basering is (possibly) a quotient ring. The quotient ideal is added to the input and slimgb is applied. EXAMPLE: example qslimgb; shows an example" { def P = basering; ideal Qideal = ideal(P); //defining the quotient ideal if P is a qring int p_opt; if( find(option(),"prot") ) { p_opt=1; } if (size(Qideal) == 0) { if (p_opt) { "slimgb in ring " + string(P); } return(slimgb(i)); } //case of a qring; since slimgb does not know qrings we //delete the quotient ideal and add it to i list BRlist = ringlist(P); BRlist[4] = ideal(0); def Phelp = ring(BRlist); kill BRlist; setring Phelp; // module case: def iq = imap(P,i); iq = iq, imap(P,Qideal)*freemodule(nrows(iq)); if (p_opt) { "slimgb in ring " + string(Phelp); "(with quotient ideal added to input)"; } iq = slimgb(iq); setring P; if (p_opt) { "//imap to original ring"; } i = imap(Phelp,iq); kill Phelp; if (find(option(),"redSB") > 0) { if (p_opt) { "//interreduction"; } i=reduce(i,std(0)); i=interred(i); } attrib(i, "isSB", 1); return (i); } example { "EXAMPLE:"; echo = 2; ring R = (0,v),(x,y,z,u),dp; qring Q = std(x2-y3); ideal i = x+y2,xy+yz+zu+u*v,xyzu*v-1; ideal j = qslimgb(i); j; module m = [x+y2,1,0], [1,1,x2+y2+xyz]; print(qslimgb(m)); } ////////////////////////////////////////////////////////////////////////////// proc groebner(def i_par, list #) "SYNTAX: @code{groebner (} ideal_expression @code{)} @* @code{groebner (} module_expression @code{)} @* @code{groebner (} ideal_expression@code{,} list of string_expressions @code{)} @* @code{groebner (} ideal_expression@code{,} list of string_expressions and int_expression @code{)} TYPE: type of the first argument PURPOSE: computes a standard basis of the first argument @code{I} (ideal or module) by a heuristically chosen method (default) or by a method specified by further arguments of type string. Possible methods are: @* - the direct methods @code{\"std\"} or @code{\"slimgb\"} without conversion, @* - conversion methods @code{\"hilb\"} or @code{\"fglm\"} where a Groebner basis is first computed with an \"easy\" ordering and then converted to the ordering of the basering by the Hilbert driven Groebner basis computation or by linear algebra. The actual computation of the Groebner basis can be specified by @code{\"std\"} or by @code{\"slimgb\"} (not for all orderings implemented). @* A further string @code{\"par2var\"} converts parameters to an extra block of variables before a Groebner basis computation (and afterwards back). @code{option(prot)} informs about the chosen method. HINT: Since there exists no uniform best method for computing standard bases, and since the difference in performance of a method on different examples can be huge, it is recommended to test, for hard examples, first various methods on a simplified example (e.g. use characteristic 32003 instead of 0 or substitute a subset of parameters/variables by integers, etc.). @* SEE ALSO: stdhilb, stdfglm, std, slimgb KEYWORDS: groebner basis computations EXAMPLE: example groebner; shows an example" { //Vorgabe einer Teilmenge aus {hilb,fglm,par2var,std,slimgb} //V1: Erste Einstellungen (Jan 2007) //V2: Aktuelle Aenderungen (Juni 2008) //--------------------------------- //0. Immer Aufruf von std unabhaengig von der Vorgabe: // gemischte Ordnungen, extra Gewichtsvektor, Matrix Ordnungen // ### Todo: extra Gewichtsvektor sollte nicht immer mit std wirken, // sondern z.B. mit "hilb" arbeiten koennen // ### Todo: es sollte ein Gewichtsvektor mitgegeben werden koennen (oder // berechnet werden), z.B. groebner(I,"hilb",w) oder groebner(I,"withWeights") // wie bei elim in elim.lib //1. Keine Vorgabe: es wirkt die aktuelle Heuristk: // - Char = p: std //V1 - Char = 0: slimgb (im qring wird Quotientenideal zum Input addiert) //V2 - Char = 0: std // - 1-Block-Ordnungen/non-commutative: direkt Aufruf von std oder slimgb // - Komplizierte Ordnungen (lp oder > 1 Block): hilb //V1 - Parameter werden grundsaetzlich nicht in Variable umgewandelt //V2 - Mehr als ein Parmeter wird zu Variable konvertiert // - fglm is keine Heuristik, da sonst vorher dim==0 peprueft werden muss //2. Vorgabe aus {std,slimgb}: es wird wo immer moeglich das Angegebene // gewaehlt (da slimgb keine Hilbertfunktion kennt, wird std verwendet). // Bei slimgb im qring, wird das Quotientenideal zum Ideal addiert. // Bei Angabe von std zusammen mit slimgb (aequivalent zur Angabe von // keinem von beidem) wirkt obige Heuristik. //3. Nichtleere Vorgabe aus {hilb,fglm,std,slimgb}: // es wird nur das Angegebene und Moegliche sowie das Notwendige verwendet // und bei Wahlmoeglickeit je nach Heuristik. // Z.B. Vorgabe von {hilb} ist aequivalent zu {hilb,std,slimgb} und es wird // hilb und nach Heuristik std oder slimgb verwendet, // (V1: aber nicht par2var) // bei Vorgabe von {hilb,slimgb} wird hilb und wo moeglich slimgb verwendet. //4. Bei Vorgabe von {par2var} wird par2var immer mit hilb und nach Heuristik // std oder slimgb verwendet. Zu Variablen konvertierte Parameter haben // extra letzten Block und Gewichte 1. def P=basering; if ((typeof(i_par)=="vector")||(typeof(i_par)=="module")||(typeof(i_par)=="matrix")) {module i=i_par;} else {ideal i=i_par; } // int, poly, number, ideal kill i_par; // check for integer etc coefficients if (charstr(basering)[1]=="i") // either integer or integer,q { if (find(option(),"prot")) { "calling std for ideals in ring with ring coefficients"; } return (std(i)); } //----------------------- save the given method --------------------------- string method; //all given methods as a coma separated string list Method; //all given methods as a list int k; for (k=1; k<=size(#); k++) { if (typeof(#[k]) == "string") { method = method + "," + #[k]; Method = Method + list(#[k]); } } //--------------------- save data from basering --------------------------- string @Minpoly = string(minpoly); //minimal polynomial int was_minpoly; //remembers if there was a minpoly in P if (size(minpoly) > 0) { was_minpoly = 1; } ideal Qideal = ideal(P); //defining the quotient ideal if P is a qring int was_qring; //remembers if basering was a qring //int is_homog = 1; if (size(Qideal) > 0) { was_qring = 1; //is_homog = homog(Qideal); //remembers if Qideal was homog (homog(0)=1) } list BRlist = ringlist(P); //ringlist of basering // save ordering of basering P for later use list ord_P = BRlist[3]; //should be available in all rings string ordstr_P = ordstr(P); int nvars_P = nvars(P); int npars_P = npars(P); intvec w; //for ringweights of basering P for(k=1; k<=nvars_P; k++) { w[k]=deg(var(k)); } int neg=1-attrib (P,"global"); //save options: intvec opt=option(get); string s_opt = option(); int p_opt; if (find(s_opt, "prot")) { p_opt = 1; } //------------------ cases where std is always used ------------------------ //If other methods are not implemented or do not make sense, i.e. for //local or mixed orderings, matrix orderings, extra weight vector //### Todo: extra weight vector should be allowed for e.g. with "hilb" if( //( find(ordstr_P,"s") > 0 ) || // covered by neg ( find(ordstr_P,"M") > 0 ) || ( find(ordstr_P,"a") > 0 ) || neg ) { if (p_opt) { "std in basering"; } return(std(i)); } //now we have: //ideal or module, global ordering, no matrix ordering, no extra weight vector //The interesting cases start now. //------------------ classify the possible settings --------------------- string algorithm; //possibilities: std, slimgb, stdorslimgb, mathicgb string conversion; //possibilities: hilb, fglm, hilborfglm, no string partovar; //possibilities: yes, no string order; //possibilities: simple, !simple string direct; //possibilities: yes, no //define algorithm: if( (was_minpoly == 0) && (npars_P == 0) && (was_qring == 0) && (attrib (P,"global") == 1) && (char(P) > 0) && (size(BRlist)<=4) ) { if( defined(Singmathic) ) { algorithm = "mathicgb"; // make it default for any appropriate setting... if mathicgb is available... } else { if( p_opt && find(method,"mathicgb") ) { "Sorry Singmathic::mathicgb is not available!"; } } } if( find(method,"std") && !find(method,"slimgb") ) { algorithm = "std"; } if( find(method,"slimgb") && !find(method,"std") ) { algorithm = "slimgb"; } if( find(method,"std") && find(method,"slimgb") || (!find(method,"std") && !find(method,"slimgb")) ) { algorithm = "stdorslimgb"; } //define conversion: if( find(method,"hilb") && !find(method,"fglm") ) { conversion = "hilb"; } if( find(method,"fglm") && !find(method,"hilb") ) { conversion = "fglm"; } if( find(method,"fglm") && find(method,"hilb") ) { conversion = "hilborfglm"; } if( !find(method,"fglm") && !find(method,"hilb") ) { conversion = "no"; } //define partovar: //if( find(method,"par2var") && npars_P > 0 ) //V1 if( find(method,"par2var") || npars_P > 1 ) //V2 { partovar = "yes"; } else { partovar = "no"; } //define order: if (system("nblocks") <= 2) { if ( find(ordstr_P,"M")+find(ordstr_P,"lp")+find(ordstr_P,"rp") <= 0 ) { order = "simple"; } } //define direct: if ( (order=="simple" && (size(method)==0)) || (size(BRlist)>4) || (order=="simple" && (method==",par2var" && npars_P==0 )) || (conversion=="no" && partovar=="no" && (algorithm=="std" || algorithm=="slimgb" || algorithm=="mathicgb" || (find(method,"std") && find(method,"slimgb")) ) ) ) { direct = "yes"; } else { direct = "no"; } //order=="simple" means that the ordering of the variables consists of one //block which is not a matrix ordering and not a lexicographical ordering. //(Note:Singular counts always least 2 blocks, one is for module component): //Call a method "direct" if conversion=="no" && partovar="no" which means //that we apply std or slimgb dircet in the basering (exception //as long as slimgb does not know qrings: in a qring of a ring P //the ideal Qideal is added to the ideal and slimgb is applied in P). //We apply a direct method if we have a simple monomial ordering, if no //conversion (fglm or hilb) is specified and if the parameters shall //not be made to variables //BRlist (=ringlist of basering) > 4 if the basering is non-commutative //---------------------------- direct methods ----------------------------- if ( algorithm=="mathicgb" ) { if (p_opt) { algorithm + " in " + string(P); } return( mathicgb(i) ); } if ( direct == "yes" ) { //if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) ) //V1 if ( algorithm=="std" || (algorithm=="stdorslimgb") ) //V2 { if (p_opt) { "std in " + string(P); } return(std(i)); } //if( algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0)) //V1 if ( algorithm=="slimgb" ) //V2 { return(qslimgb(i)); } } //--------------------------- indirect methods ----------------------------- //indirect methods are methods where a conversion is used with a ring change //We are in the following situation: //direct=="no" (i.e. "hilb" or "fglm" or "par2var" is given) //or no method is given and we have a complicated monomial ordering //V1: "par2var" is not a default strategy, it must be explicitely //given in order to be performed. //V2: "par2var" is a default strategy if there are more than 1 parameters //------------ case where no parameters are made to variables ------------- if ( partovar == "no" && conversion == "hilb" || (partovar == "no" && conversion == "fglm" ) || (partovar == "no" && conversion == "hilborfglm" ) || (partovar == "no" && conversion == "no" && direct == "no") ) //last case: heuristic { if ( conversion=="fglm" ) { //if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) ) //V1 if ( algorithm=="std" || (algorithm=="stdorslimgb") ) //V2 { return (stdfglm(i,"std")); } //if(algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0))//V1 if( algorithm=="slimgb" ) //V2 { return (stdfglm(i,"slimgb")); } } else { //if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) )//V1 if ( algorithm=="std" || (algorithm=="stdorslimgb" ) ) //V2 { return (stdhilb(i,"std")); } //if(algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0))//V1 if ( algorithm=="slimgb" ) //V2 { return (stdhilb(i,"slimgb")); } } } //------------ case where parameters are made to variables ---------------- //define a ring Phelp via par2varRing in which the parameters are variables else { // reset options option(none); // turn on options prot, mem, redSB, intStrategy if previously set if ( find(s_opt, "prot") ) { option(prot); } if ( find(s_opt, "mem") ) { option(mem); } if ( find(s_opt, "redSB") ) { option(redSB); } if ( find(s_opt, "intStrategy") ) { option(intStrategy); } //first clear denominators of parameters if (npars_P > 0) { for( k=ncols(i); k>0; k-- ) { i[k]=cleardenom(i[k]); } } def Phelp = par2varRing(i)[1]; //minpoly is mapped with i setring Phelp; def i = Id(1); //is_homog = homog(i); //If parameters are converted to ring variables, they appear in an extra //block. Therefore we use always hilb for this block ordering: if ( conversion=="fglm" ) { i = (stdfglm(i)); //only uesful for 1 parameter with minpoly } else { //if ( algorithm=="std" || (algorithm=="stdorslimgb" && char(P)>0) )//V1 if ( algorithm=="std" || (algorithm=="stdorslimgb" )) //V2 { i = stdhilb(i,"std"); } //if(algorithm=="slimgb" || (algorithm=="stdorslimgb" && char(P)==0))//V1 if ( algorithm=="slimgb" ) //V2 { i = stdhilb(i,"slimgb"); } } } //-------------------- go back to original ring --------------------------- //The main computation is done. However, the SB coming from a ring with //extra variables is in general too big. We simplify it before mapping it //to the basering. if (p_opt) { "//simplification"; } if (was_minpoly) { execute("ideal Minpoly = " + @Minpoly + ";"); attrib(Minpoly,"isSB",1); i = simplify(NF(i,Minpoly),2); } def Li = lead(i); setring P; def Li = imap(Phelp,Li); Li = simplify(Li,32); intvec vi; for (k=1; k<=ncols(Li); k++) { vi[k] = Li[k]==0; } setring Phelp; for (k=1; k<=size(i) ;k++) { if(vi[k]==1) { i[k]=0; } } i = simplify(i,2); setring P; if (p_opt) { "//imap to original ring"; } i = imap(Phelp,i); kill Phelp; i = simplify(i,34); // clean-up time option(set, opt); if (find(s_opt, "redSB") > 0) { if (p_opt) { "//interreduction"; } i=interred(i); } attrib(i, "isSB", 1); return (i); } example { "EXAMPLE: "; echo=2; intvec opt = option(get); option(prot); ring r = 0,(a,b,c,d),dp; ideal i = a+b+c+d,ab+ad+bc+cd,abc+abd+acd+bcd,abcd-1; groebner(i); ring s = 0,(a,b,c,d),lp; ideal i = imap(r,i); groebner(i,"hilb"); ring R = (0,a),(b,c,d),lp; minpoly = a2+1; ideal i = a+b+c+d,ab+ad+bc+cd,abc+abd+acd+bcd,d2-c2b2; groebner(i,"par2var","slimgb"); groebner(i,"fglm"); //computes a reduced standard basis option(set,opt); } ////////////////////////////////////////////////////////////////////////// proc res(list #) "@c we do texinfo here: @cindex resolution, computation of @table @code @item @strong{Syntax:} @code{res (} ideal_expression@code{,} int_expression @code{[,} any_expression @code{])} @*@code{res (} module_expression@code{,} int_expression @code{[,} any_expression @code{])} @item @strong{Type:} resolution @item @strong{Purpose:} computes a (possibly minimal) free resolution of an ideal or module using a heuristically chosen method. @* The second (int) argument (say @code{k}) specifies the length of the resolution. If it is not positive then @code{k} is assumed to be the number of variables of the basering. @* If a third argument is given, the returned resolution is minimized. Depending on the input, the returned resolution is computed using the following methods: @table @asis @item @strong{quotient rings:} @code{nres} (classical method using syzygies) , see @ref{nres}. @item @strong{homogeneous ideals and k=0:} @code{lres} (La'Scala's method), see @ref{lres}. @item @strong{not minimized resolution and (homogeneous input with k not 0, or local rings):} @code{sres} (Schreyer's method), see @ref{sres}. @item @strong{all other inputs:} @code{mres} (classical method), see @ref{mres}. @end table @item @strong{Note:} Accessing single elements of a resolution may require some partial computations to be finished and may therefore take some time. @end table @c ref See also @ref{betti}; @ref{ideal}; @ref{minres}; @ref{module}; @ref{mres}; @ref{nres}; @ref{lres}; @ref{hres}; @ref{sres}; @ref{resolution}. @c ref " { def P=basering; if (size(#) < 2) { ERROR("res: need at least two arguments: ideal/module, int"); } def m=#[1]; //the ideal or module int i=#[2]; //the length of the resolution if (i< 0) { i=0;} string varstr_P = varstr(P); int p_opt; string s_opt = option(); // set p_opt, if option(prot) is set if (find(s_opt, "prot")) { p_opt = 1; } if( (size(ideal(basering)) > 0) || (size(ringlist(P)) > 4) ) { // the quick hack for qrings - seems to fit most needs // (lres is not implemented for qrings, sres is not so efficient) // || non-commutative, since only n/m-res are implemented for NC rings if (p_opt) { "using nres";} return(nres(m,i)); } /* if( attrib(basering, "global") == 1 ) // preparations for s_res usage. in testing! { if (p_opt) { "using s_res";} if( !defined(s_res) ) { def @@v=option(get); option(noloadLib); option(noloadProc); LIB( "schreyer.lib" ); // for s_res option(set, @@v); kill @@v; } resolution re = s_res(m,i); if(size(#)>2) { re=minres(re); } return(re); }*/ if(homog(m)==1) { resolution re; if (((i==0) or (i>=nvars(basering))) && (typeof(m) != "module") && (nvars(basering)>1)) { //LaScala for the homogeneous case and i == 0 if (p_opt) { "using lres";} re=lres(m,i); if(size(#)>2) { re=minres(re); } } else { if(size(#)>2) { if (p_opt) { "using mres";} re=mres(m,i); } else { if (p_opt) { "using sres";} re=sres(std(m),i); } } return(re); } //mres for the global non homogeneous case if(find(ordstr(P),"s")==0) { string ri= "ring Phelp =" +string(char(P))+",("+varstr_P+"),(dp,C);"; ri = ri + "minpoly = "+string(minpoly) + ";"; execute(ri); def m=imap(P,m); if (p_opt) { "using mres in another ring";} list re=mres(m,i); setring P; resolution result=imap(Phelp,re); if (size(#) > 2) {result = minres(result);} return(result); } //sres for the local case and not minimal resolution if(size(#)<=2) { string ri= "ring Phelp =" +string(char(P))+",("+varstr_P+"),(ls,c);"; ri = ri + "minpoly = "+string(minpoly) + ";"; execute(ri); def m=imap(P,m); m=std(m); if (p_opt) { "using sres in another ring";} list re=sres(m,i); setring P; resolution result=imap(Phelp,re); return(result); } //mres for the local case and minimal resolution string ri= "ring Phelp =" +string(char(P))+",("+varstr_P+"),(ls,C);"; ri = ri + "minpoly = "+string(minpoly) + ";"; execute(ri); def m=imap(P,m); if (p_opt) { "using mres in another ring";} list re=mres(m,i); setring P; resolution result=imap(Phelp,re); result = minres(result); return(result); } example {"EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; ideal i=xz,yz,x3-y3; def l=res(i,0); // homogeneous ideal: uses lres l; print(betti(l), "betti"); // input to betti may be of type resolution l[2]; // element access may take some time i=i,x+1; l=res(i,0); // inhomogeneous ideal: uses mres l; ring rs=0,(x,y,z),ds; ideal i=imap(r,i); def l=res(i,0); // local ring not minimized: uses sres l; res(i,0,0); // local ring and minimized: uses mres } ///////////////////////////////////////////////////////////////////////// proc quot (def m1,def m2,list #) "SYNTAX: @code{quot (} module_expression@code{,} module_expression @code{)} @*@code{quot (} module_expression@code{,} module_expression@code{,} int_expression @code{)} @*@code{quot (} ideal_expression@code{,} ideal_expression @code{)} @*@code{quot (} ideal_expression@code{,} ideal_expression@code{,} int_expression @code{)} TYPE: ideal SYNTAX: @code{quot (} module_expression@code{,} ideal_expression @code{)} TYPE: module PURPOSE: computes the quotient of the 1st and the 2nd argument. If a 3rd argument @code{n} is given the @code{n}-th method is used (@code{n}=1...5). SEE ALSO: quotient EXAMPLE: example quot; shows an example" { if (((typeof(m1)!="ideal") and (typeof(m1)!="module")) or ((typeof(m2)!="ideal") and (typeof(m2)!="module"))) { "USAGE: quot(m1, m2[, n]); m1, m2 two submodules of k^s,"; " n (optional) integer (1<= n <=5)"; "RETURN: the quotient of m1 and m2"; "EXAMPLE: example quot; shows an example"; return(); } if (typeof(m1)!=typeof(m2)) { return(quotient(m1,m2)); } if (size(#)>0) { if (typeof(#[1])=="int" ) { return(quot1(m1,m2,#[1])); } } else { return(quot1(m1,m2,2)); } } example { "EXAMPLE:"; echo = 2; ring r=181,(x,y,z),(c,ls); ideal id1=maxideal(4); ideal id2=x2+xyz,y2-z3y,z3+y5xz; option(prot); ideal id3=quotient(id1,id2); id3; ideal id4=quot(id1,id2,1); id4; ideal id5=quot(id1,id2,2); id5; } static proc quot1 (module m1, module m2,int n) "USAGE: quot1(m1, m2, n); m1, m2 two submodules of k^s, n integer (1<= n <=5) RETURN: the quotient of m1 and m2 EXAMPLE: example quot1; shows an example" { if (n==1) { return(quotient1(m1,m2)); } else { if (n==2) { return(quotient2(m1,m2)); } else { if (n==3) { return(quotient3(m1,m2)); } else { if (n==4) { return(quotient4(m1,m2)); } else { if (n==5) { return(quotient5(m1,m2)); } else { return(quotient(m1,m2)); } } } } } } example { "EXAMPLE:"; echo = 2; ring r=181,(x,y,z),(c,ls); ideal id1=maxideal(4); ideal id2=x2+xyz,y2-z3y,z3+y5xz; option(prot); ideal id6=quotient(id1,id2); id6; ideal id7=quot1(id1,id2,1); id7; ideal id8=quot1(id1,id2,2); id8; } static proc quotient0(module a,module b) { module mm=b+a; resolution rs=lres(mm,0); list I=list(rs); matrix M=I[2]; matrix A[1][nrows(M)]=M[1..nrows(M),1]; ideal i=A; return (i); } proc quotient1(module a,module b) //17sec "USAGE: quotient1(m1, m2); m1, m2 two submodules of k^s, RETURN: the quotient of m1 and m2" { int i; a=std(a); module dummy; module B=NF(b,a)+dummy; ideal re=quotient(a,module(B[1])); for(i=2;i<=ncols(B);i++) { re=intersect1(re,quotient(a,module(B[i]))); } return(re); } proc quotient2(module a,module b) //13sec "USAGE: quotient2(m1, m2); m1, m2 two submodules of k^s, RETURN: the quotient of m1 and m2" { a=std(a); module dummy; module bb=NF(b,a)+dummy; int i=ncols(bb); ideal re=quotient(a,module(bb[i])); bb[i]=0; module temp; module temp1; module bbb; int mx; i=i-1; while (1) { if (i==0) break; temp = a+bb*re; temp1 = lead(interred(temp)); mx=ncols(a); if (ncols(temp1)>ncols(a)) { mx=ncols(temp1); } temp1 = matrix(temp1,1,mx)-matrix(lead(a),1,mx); temp1 = dummy+temp1; if (deg(temp1[1])<0) break; re=intersect1(re,quotient(a,module(bb[i]))); bb[i]=0; i = i-1; } return(re); } proc quotient3(module a,module b) //89sec "USAGE: quotient3(m1, m2); m1, m2 two submodules of k^s, only for global rings RETURN: the quotient of m1 and m2" { string s="ring @newr=("+charstr(basering)+ "),("+varstr(basering)+",@t,@w),dp;"; def @newP=basering; execute(s); module b=imap(@newP,b); module a=imap(@newP,a); int i; int j=ncols(b); vector @b; for(i=1;i<=j;i++) { @b=@b+@t^(i-1)*@w^(j-i+1)*b[i]; } ideal re=quotient(a,module(@b)); setring @newP; ideal re=imap(@newr,re); return(re); } proc quotient5(module a,module b) //89sec "USAGE: quotient5(m1, m2); m1, m2 two submodules of k^s, only for global rings RETURN: the quotient of m1 and m2" { string s="ring @newr=("+charstr(basering)+ "),("+varstr(basering)+",@t),dp;"; def @newP=basering; execute(s); module b=imap(@newP,b); module a=imap(@newP,a); int i; int j=ncols(b); vector @b; for(i=1;i<=j;i++) { @b=@b+@t^(i-1)*b[i]; } @b=homog(@b,@w); ideal re=quotient(a,module(@b)); setring @newP; ideal re=imap(@newr,re); return(re); } proc quotient4(module a,module b) //95sec "USAGE: quotient4(m1, m2); m1, m2 two submodules of k^s, only for global rings RETURN: the quotient of m1 and m2" { string s="ring @newr=("+charstr(basering)+ "),("+varstr(basering)+",@t),dp;"; def @newP=basering; execute(s); module b=imap(@newP,b); module a=imap(@newP,a); int i; vector @b=b[1]; for(i=2;i<=ncols(b);i++) { @b=@b+@t^(i-1)*b[i]; } matrix sy=modulo(@b,a); ideal re=sy; setring @newP; ideal re=imap(@newr,re); return(re); } static proc intersect1(ideal i,ideal j) { def R=basering; execute("ring gnir = ("+charstr(basering)+"), ("+varstr(basering)+",@t),(C,dp);"); ideal i=var(nvars(basering))*imap(R,i)+(var(nvars(basering))-1)*imap(R,j); ideal j=eliminate(i,var(nvars(basering))); setring R; map phi=gnir,maxideal(1); return(phi(j)); } ////////////////////////////////////////////////////////////////// /// /// sprintf, fprintf printf /// proc sprintf(string fmt, list #) "SYNTAX: @code{sprintf (} string_expression @code{[,} any_expressions @code{] )} RETURN: string PURPOSE: @code{sprintf(fmt,...);} performs output formatting. The first argument is a format control string. Additional arguments may be required, depending on the content of the control string. A series of output characters is generated as directed by the control string; these characters are returned as a string. @* The control string @code{fmt} is simply text to be copied, except that the string may contain conversion specifications.@* Type @code{help print;} for a listing of valid conversion specifications. As an addition to the conversions of @code{print}, the @code{%n} and @code{%2} conversion specification does not consume an additional argument, but simply generates a newline character. NOTE: If one of the additional arguments is a list, then it should be wrapped in an additional @code{list()} command, since passing a list as an argument flattens the list by one level. SEE ALSO: fprintf, printf, print, string EXAMPLE : example sprintf; shows an example " { int sfmt = size(fmt); if (sfmt <= 1) { return (fmt); } int next, l, nnext; string ret; list formats = "%l", "%s", "%2l", "%2s", "%t", "%;", "%p", "%b", "%n", "%2"; while (1) { if (size(#) <= 0) { return (ret + fmt); } nnext = 0; while (nnext < sfmt) { nnext = find(fmt, "%", nnext + 1); if (nnext == 0) { next = 0; break; } l = 1; while (l <= size(formats)) { next = find(fmt, formats[l], nnext); if (next == nnext) break; l++; } if (next == nnext) break; } if (next == 0) { return (ret + fmt); } if (formats[l] != "%2" && formats[l] != "%n") { ret = ret + fmt[1, next - 1] + print(#[1], formats[l]); # = delete(#, 1); } else { ret = ret + fmt[1, next - 1] + print("", "%2s"); } if (size(fmt) <= (next + size(formats[l]) - 1)) { return (ret); } fmt = fmt[next + size(formats[l]), size(fmt)-next-size(formats[l]) + 1]; } } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; module m=[1,y],[0,x+z]; intmat M=betti(mres(m,0)); list l = r, m, M; string s = sprintf("s:%s,%n l:%l", 1, 2); s; s = sprintf("s:%n%s", l); s; s = sprintf("s:%2%s", list(l)); s; s = sprintf("2l:%n%2l", list(l)); s; s = sprintf("%p", list(l)); s; s = sprintf("%;", list(l)); s; s = sprintf("%b", M); s; } proc printf(string fmt, list #) "SYNTAX: @code{printf (} string_expression @code{[,} any_expressions@code{] )} RETURN: none PURPOSE: @code{printf(fmt,...);} performs output formatting. The first argument is a format control string. Additional arguments may be required, depending on the content of the control string. A series of output characters is generated as directed by the control string; these characters are displayed (i.e., printed to standard out). @* The control string @code{fmt} is simply text to be copied, except that the string may contain conversion specifications. @* Type @code{help print;} for a listing of valid conversion specifications. As an addition to the conversions of @code{print}, the @code{%n} and @code{%2} conversion specification does not consume an additional argument, but simply generates a newline character. NOTE: If one of the additional arguments is a list, then it should be enclosed once more into a @code{list()} command, since passing a list as an argument flattens the list by one level. SEE ALSO: sprintf, fprintf, print, string EXAMPLE : example printf; shows an example " { write("", sprintf(fmt, #)); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; module m=[1,y],[0,x+z]; intmat M=betti(mres(m,0)); list l=r,m,matrix(M); printf("s:%s,l:%l",1,2); printf("s:%s",l); printf("s:%s",list(l)); printf("2l:%2l",list(l)); printf("%p",matrix(M)); printf("%;",matrix(M)); printf("%b",M); } proc fprintf(link l, string fmt, list #) "SYNTAX: @code{fprintf (} link_expression@code{,} string_expression @code{[,} any_expressions@code{] )} RETURN: none PURPOSE: @code{fprintf(l,fmt,...);} performs output formatting. The second argument is a format control string. Additional arguments may be required, depending on the content of the control string. A series of output characters is generated as directed by the control string; these characters are written to the link l. The control string @code{fmt} is simply text to be copied, except that the string may contain conversion specifications.@* Type @code{help print;} for a listing of valid conversion specifications. As an addition to the conversions of @code{print}, the @code{%n} and @code{%2} conversion specification does not consume an additional argument, but simply generates a newline character. NOTE: If one of the additional arguments is a list, then it should be enclosed once more into a @code{list()} command, since passing a list as an argument flattens the list by one level. SEE ALSO: sprintf, printf, print, string EXAMPLE : example fprintf; shows an example " { write(l, sprintf(fmt, #)); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; module m=[1,y],[0,x+z]; intmat M=betti(mres(m,0)); list l=r,m,M; link li=""; // link to stdout fprintf(li,"s:%s,l:%l",1,2); fprintf(li,"s:%s",l); fprintf(li,"s:%s",list(l)); fprintf(li,"2l:%2l",list(l)); fprintf(li,"%p",list(l)); fprintf(li,"%;",list(l)); fprintf(li,"%b",M); } ////////////////////////////////////////////////////////////////////////// /* proc minres(list #) { if (size(#) == 2) { if (typeof(#[1]) == "ideal" || typeof(#[1]) == "module") { if (typeof(#[2] == "int")) { return (res(#[1],#[2],1)); } } } if (typeof(#[1]) == "resolution") { return minimizeres(#[1]); } else { return minimizeres(#); } } */ /////////////////////////////////////////////////////////////////////////////// proc weightKB(def stc, int dd, list wim) "SYNTAX: @code{weightKB (} module_expression@code{,} int_expression @code{,} list_expression @code{)}@* @code{weightKB (} ideal_expression@code{,} int_expression@code{,} list_expression @code{)} RETURN: the same as the input type of the first argument PURPOSE: If @code{I,d,wim} denotes the three arguments then weightKB computes the weighted degree- @code{d} part of a vector space basis (consisting of monomials) of the quotient ring, resp. of the quotient module, modulo @code{I} w.r.t. weights given by @code{wim} The information about the weights is given as a list of two intvec: @code{wim[1]} weights for all variables (positive), @code{wim[2]} weights for the module generators. NOTE: This is a generalization of the command @code{kbase} with the same first two arguments. SEE ALSO: kbase EXAMPLE: example weightKB; shows an example " { if(checkww(wim)){ERROR("wrong weights";);} kbclass(); wwtop=wim[1]; stc=interred(lead(stc)); if(typeof(stc)=="ideal") { stdtop=stc; ideal out=widkbase(dd); delkbclass(); out=simplify(out,2); // delete 0 return(out); } list mbase=kbprepare(stc); module mout; int im,ii; if(size(wim)>1){mmtop=wim[2];} else{mmtop=0;} for(im=size(mbase);im>0;im--) { stdtop=mbase[im]; if(im>size(mmtop)){ii=dd;} else{ii=dd-mmtop[im];} mout=mout+widkbase(ii)*gen(im); } delkbclass(); mout=simplify(mout,2); // delete 0 return(mout); } example { "EXAMPLE:"; echo=2; ring R=0, (x,y), wp(1,2); weightKB(ideal(0),3,intvec(1,2)); } /////////////////////////////////////////////////////////////////////////////// proc datetime() "SYNTAX: @code{datetime ()} RETURN: string PURPOSE: return the curent date and time as a string EXAMPLE: example datetime; shows an example " { return(read("|: date")); } example { "EXAMPLE:"; echo=2; datetime(); } /////////////////////////////////////////////////////////////////////////////// // construct global values static proc kbclass() { intvec wwtop,mmtop; export (wwtop,mmtop); ideal stdtop,kbtop; export (stdtop,kbtop); } // delete global values static proc delkbclass() { kill wwtop,mmtop; kill stdtop,kbtop; } // select parts of the modul static proc kbprepare(module mstc) { list rr; ideal kk; int i1,i2; mstc=transpose(mstc); for(i1=ncols(mstc);i1>0;i1--) { kk=0; for(i2=nrows(mstc[i1]);i2>0;i2--) { kk=kk+mstc[i1][i2]; } rr[i1]=kk; } return(rr); } // check for weights static proc checkww(list vv) { if(typeof(vv[1])!="intvec"){return(1);} intvec ww=vv[1]; int mv=nvars(basering); if(size(ww)0) { if(ww[mv]<=0){return(1);} mv--; } if(size(vv)>1) { if(typeof(vv[2])!="intvec"){return(1);} } return(0); } /////////////////////////////////////////////////////// // The "Caller" for ideals // dd - the degree of the result static proc widkbase(int dd) { if((size(stdtop)==1)&&(deg(stdtop[1])==0)){return(0);} if(dd<=0) { if(dd<0){return(0);} else{return(1);} } int m1,m2; m1=nvars(basering); while(wwtop[m1]>dd) { m1--; if(m1==0){return(0);} } attrib(stdtop,"isSB",1); poly mo=1; if(m1==1) { m2=dd div wwtop[1]; if((m2*wwtop[1])==dd) { mo=var(1)^m2; if(reduce(mo,stdtop)==mo){return(mo);} else{return(0);} } } kbtop=0; m2=dd; weightmon(m1-1,m2,mo); while(m2>=wwtop[m1]) { m2=m2-wwtop[m1]; mo=var(m1)*mo; if(m2==0) { if((mo!=0) and (reduce(mo,stdtop)==mo)) { kbtop[ncols(kbtop)+1]=mo; return(kbtop); } } weightmon(m1-1,m2,mo); } return(kbtop); } ///////////////////////////////////////////////////////// // the recursive procedure // va - number of the variable // drest - rest of the degree // mm - the candidate static proc weightmon(int va, int drest, poly mm) { if(va==0){return();} while(wwtop[va]>drest) { va--; if(va==0){return();} } int m2; if(va==1) { m2=drest div wwtop[1]; if((m2*wwtop[1])==drest) { mm=var(1)^m2*mm; if ((mm!=0) and (reduce(mm,stdtop)==mm)) { kbtop[ncols(kbtop)+1]=mm; } } return(); } m2=drest; if ((mm!=0) and (reduce(mm,stdtop)==mm)) { weightmon(va-1,m2,mm); } while(m2>=wwtop[va]) { m2=m2-wwtop[va]; mm=var(va)*mm; if(m2==0) { if ((mm!=0) and (reduce(mm,stdtop)==mm)) { kbtop[ncols(kbtop)+1]=mm; return(); } } if ((mm!=0) and (reduce(mm,stdtop)==mm)) { weightmon(va-1,m2,mm); } } return(); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y,z),dp; ideal i = x6,y4,xyz; intvec w = 2,3,6; weightKB(i, 12, list(w)); } /////////////////////////////////////////////////////////////////////////////// proc max(def i,list #) "SYNTAX: max (i_1, ..., i_k) TYPE: same as type of i_1, ..., i_k resp. PURPOSE: returns the maximum for any arguments of a type for which '>' is defined SEE ALSO: min EXAMPLE: example max; shows an example" { def maximum = i; for (int j=1; j<=size(#); j++) { if(#[j]>maximum) { maximum = #[j]; } } return(maximum); } example { "EXAMPLE:"; echo=2; // biggest int max(2,3); max(1,4,3); // lexicographically biggest intvec max(intvec(1,2),intvec(0,1),intvec(1,1)); // polynopmial with biggest leading monomial ring r = 0,x,dp; max(x+1,x2+x); } /////////////////////////////////////////////////////////////////////////////// proc min(def i,list #) "SYNTAX: min (i_1, ..., i_k) TYPE: same as type of i_1, ..., i_k resp. PURPOSE: returns the minimum for any arguments of a type for which '>' is defined SEE ALSO: max EXAMPLE: example min; shows an example" { def minimum = i; for (int j=1; j<=size(#); j++) { if(#[j]= l[k], with k!=j. PURPOSE: The procedure is applied in a situation where the standard basis computation in the basering R is done via a conversion through an overring Phelp with additional variables and where a direct imap from Phelp to R is too expensive. Assume Phelp is created by the procedure @code{par2varRing} or @code{hilbRing} and IPhelp is a SB in Phelp [ with l[j]= length(IPhelp(j)) or any other integer reflecting the complexity of a IPhelp[j] ]. Let I = lead(IPhelp) mapped to R and compute v = downsizeSB(imap(Phelp,I),l) in R. Then, if Ihelp[j] is deleted for all j with v[j]=1, we can apply imap to the remaining generators of Ihelp and still get SB in R (in general not minimal). EXAMPLE: example downsizeSB; shows an example" { int k,j; intvec v,l; poly M,N,W; int c=size(I); if( size(#) != 0 ) { if ( typeof(#[1]) == "intvec" ) { l = #[1]; } else { ERROR("// 2nd argument must be an intvec"); } } l[c+1]=0; v[c]=0; j=0; while(jl[k]) ) { I[j]=0; v[j]=1; break; } if( (M==N) && (l[j]<=l[k]) || N/M != 0 ) { I[k]=0; v[k]=1; } } } } } return(v); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z,t),(dp(3),dp); ideal i = x+y+z+t,xy+yz+xt+zt,xyz+xyt+xzt+yzt,xyzt-t4; ideal Id = std(i); ideal I = lead(Id); I; ring S = (0,t),(x,y,z),dp; downsizeSB(imap(r,I)); //Id[5] can be deleted, we still have a SB of i in the ring S ring R = (0,x),(y,z,u),lp; ideal i = x+y+z+u,xy+xu+yz+zu,xyz+xyu+xzu+yzu,xyzu-1; def Phelp = par2varRing()[1]; setring Phelp; ideal IPhelp = std(imap(R,i)); ideal I = lead(IPhelp); setring R; ideal I = imap(Phelp,I); I; intvec v = downsizeSB(I); v; } /////////////////////////////////////////////////////////////////////////// // PROBLEM: Die Prozedur funktioniert nur fuer Ringe die global bekannt // sind, also interaktiv, aber nicht aus einer Prozedur. // Z.B. funktioniert example imapDownsize; nicht proc imapDownsize (string R, string I) "SYNTAX: @code{imapDownsize (} string @code{,} string @code{)} *@ First string must be the string of the name of a ring, second string must be the string of the name of an object in the ring. TYPE: same type as the object with name the second string PURPOSE: maps the object given by the second string to the basering. If R resp. I are the first resp. second string, then imapDownsize(R,I) is equivalent to simplify(imap(`R`,`I`),34). NOTE: imapDownsize is usually faster than imap if `I` is large and if simplify has a great effect, since the procedure maps only those generators from `I` which are not killed by simplify( - ,34). This is useful if `I` is a standard bases for a block ordering of `R` and if some variables from the last block in `R` are mapped to parameters. Then the returned result is a standard basis in the basering. SEE ALSO: imap, fetch, map EXAMPLE: example imapDownsize; shows an example" { def BR = basering; int k; setring `R`; def @leadI@ = lead(`I`); int s = ncols(@leadI@); setring BR; ideal @leadI@ = simplify(imap(`R`,@leadI@),32); intvec vi; for (k=1; k<=s; k++) { vi[k] = @leadI@[k]==0; } kill @leadI@; setring `R`; kill @leadI@; for (k=1; k<=s; k++) { if( vi[k]==1 ) { `I`[k]=0; } } `I` = simplify(`I`,2); setring BR; return(imap(`R`,`I`)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z,t),(dp(3),dp); ideal i = x+y+z+t,xy+yz+xt+zt,xyz+xyt+xzt+yzt,xyzt-1; i = std(i); i; ring s = (0,t),(x,y,z),dp; imapDownsize("r","i"); //i[5] is omitted since lead(i[2]) | lead(i[5]) } /////////////////////////////////////////////////////////////////////////////// //die folgende proc war fuer groebner mit fglm vorgesehen, ist aber zu teuer. //Um die projektive Dimension korrekt zu berechnen, muss man aber teuer //voerher ein SB bzgl. einer Gradordnung berechnen und dann homogenisieren. //Sonst koennen hoeherdimensionale Komponenten in Unendlich entstehen proc projInvariants(ideal i,list #) "SYNTAX: @code{projInvariants (} ideal_expression @code{)} @* @code{projInvariants (} ideal_expression@code{,} list of string_expres sions@code{)} TYPE: list, say L, with L[1] and L[2] of type int and L[3] of type intvec PURPOSE: Computes the (projective) dimension (L[1]), degree (L[2]) and the first Hilbert series (L[3], as intvec) of the homogenized ideal in the ring given by the procedure @code{hilbRing} with global ordering dp (resp. wp if the variables have weights >1) If an argument of type string @code{\"std\"} resp. @code{\"slimgb\"} is given, the standard basis computatuion uses @code{std} or @code{slimgb}, otherwise a heuristically chosen method (default) NOTE: Homogenized means weighted homogenized with respect to the weights w[i] of the variables var(i) of the basering. The returned dimension, degree and Hilbertseries are the respective invariants of the projective variety defined by the homogenized ideal. The dimension is equal to the (affine) dimension of the ideal in the basering (degree and Hilbert series make only sense for homogeneous ideals). SEE ALSO: dim, dmult, hilb KEYWORDS: dimension, degree, Hilbert function EXAMPLE: example projInvariants; shows an example" { def P = basering; int p_opt; string s_opt = option(); if (find(option(), "prot")) { p_opt = 1; } //---------------- check method and clear denomintors -------------------- int k; string method; for (k=1; k<=size(#); k++) { if (typeof(#[k]) == "string") { method = method + "," + #[k]; } } if (npars(P) > 0) //clear denominators of parameters { for( k=ncols(i); k>0; k-- ) { i[k]=cleardenom(i[k]); } } //------------------------ change to hilbRing ---------------------------- list hiRi = hilbRing(i); intvec W = hiRi[2]; def Philb = hiRi[1]; //note: Philb is no qring and the predefined setring Philb; //ideal Id(1) in Philb is homogeneous int di, de; //for dimension, degree intvec hi; //for hilbert series //-------- compute Hilbert function of homogenized ideal in Philb --------- //Philb has only 1 block. There are three cases string algorithm; //possibilities: std, slimgb, stdorslimgb //define algorithm: if( find(method,"std") && !find(method,"slimgb") ) { algorithm = "std"; } if( find(method,"slimgb") && !find(method,"std") ) { algorithm = "slimgb"; } if( find(method,"std") && find(method,"slimgb") || (!find(method,"std") && !find(method,"slimgb")) ) { algorithm = "stdorslimgb"; } if ( algorithm=="std" || ( algorithm=="stdorslimgb" && char(P)>0 ) ) { if (p_opt) {"std in ring " + string(Philb);} Id(1) = std(Id(1)); di = dim(Id(1))-1; de = mult(Id(1)); hi = hilb( Id(1),1,W ); } if ( algorithm=="slimgb" || ( algorithm=="stdorslimgb" && char(P)==0 ) ) { if (p_opt) {"slimgb in ring " + string(Philb);} Id(1) = slimgb(Id(1)); di = dim( Id(1) ); if (di > -1) { di = di-1; } de = mult( Id(1) ); hi = hilb( Id(1),1,W ); } kill Philb; list L = di,de,hi; return(L); } example { "EXAMPLE:"; echo = 2; ring r = 32003,(x,y,z),lp; ideal i = y2-xz,x2-z; projInvariants(i); ring R = (0),(x,y,z,u,v),lp; //minpoly = x2+1; ideal i = x2+1,x2+y+z+u+v,xyzuv-1; projInvariants(i); qring S =std(x2+1); ideal i = imap(R,i); projInvariants(i); } */ /////////////////////////////////////////////////////////////////////////////// // EXAMPLES /////////////////////////////////////////////////////////////////////////////// /* example stdfglm; example stdhilb; example groebner; example res; example sprintf; example fprintf; example printf; example weightKB; example qslimgb; example par2varRing; */ static proc mod_init() { if(!defined(Singmathic)) { load("singmathic.so","try"); } //int pagelength=24; //exportto(Top,pagelength); } singular-4.0.3+ds/Singular/LIB/stratify.lib000066400000000000000000000663121266270727000205140ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////// version="version stratify.lib 4.0.0.0 Jun_2013 "; // $Id: 8644d49e73e108d6cf5156f28bedb19dee44523a $ category="Invariant theory"; info=" LIBRARY: stratify.lib Algorithmic Stratification for Unipotent Group-Actions AUTHOR: Anne Fruehbis-Krueger, anne@mathematik.uni-kl.de PROCEDURES: prepMat(M,wr,ws,step); list of submatrices corresp. to given filtration stratify(M,wr,ws,step); algorithmic stratifcation (main procedure) "; //////////////////////////////////////////////////////////////////////////// // REQUIRED LIBRARIES //////////////////////////////////////////////////////////////////////////// // first the ones written in Singular LIB "general.lib"; LIB "primdec.lib"; // then the ones written in C/C++ //////////////////////////////////////////////////////////////////////////// // PROCEDURES ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // For the kernel of the Kodaira-Spencer map in the case of hypersurface // singularities or CM codimension 2 singularities: // * step=min{ord(x_i)} // * wr corresponds to the weight vector of the d/dt_i (i.e. to -ord(t_i)) // (since the entries should be non-negative it may be necessary to // multiply the whole vector by -1) // * ws corresponds to the weight vector of the delta_i // * M is the matrix delta_i(t_j) ///////////////////////////////////////////////////////////////////////////// proc prepMat(matrix M, intvec wr, intvec ws, int step) "USAGE: prepMat(M,wr,ws,step); where M is a matrix, wr is an intvec of size ncols(M), ws an intvec of size nrows(M) and step is an integer RETURN: 2 lists of submatrices corresponding to the filtrations specified by wr and ws: the first list corresponds to the list for the filtration of AdA, i.e. the ranks of these matrices will be the r_i, the second one to the list for the filtration of L, i.e. the ranks of these matrices will be the s_i NOTE: * the entries of the matrix M are M_ij=delta_i(x_j), * wr is used to determine what subset of the set of all dx_i is generating AdF^l(A): if (k-1)*step <= wr[i] < k*step, then dx_i is in the set of generators of AdF^l(A) for all l>=k and the i-th column of M appears in each submatrix starting from the k-th * ws is used to determine what subset of the set of all delta_i is generating Z_l(L): if (k-1)*step <= ws[i] < k*step, then delta_i is in the set of generators of Z_l(A) for l < k and the i-th row of M appears in each submatrix up to the (k-1)th * the entries of wr and ws as well as step should be positive integers EXAMPLE: example prepMat; shows an example" { //---------------------------------------------------------------------- // Initialization and sanity checks //---------------------------------------------------------------------- int i,j; if ((size(wr)!=ncols(M)) || (size(ws)!=nrows(M))) { "size mismatch: wr should have " + string(ncols(M)) + "entries"; " ws should have " + string(nrows(M)) + "entries"; return("ERROR"); } //---------------------------------------------------------------------- // Sorting the matrix to obtain nice structure //---------------------------------------------------------------------- list sortwr=sort(wr); list sortws=sort(ws); if(sortwr[1]!=wr) { matrix N[nrows(M)][ncols(M)]; for(i=1;i<=size(wr);i++) { N[1..nrows(M),i]=M[1..nrows(M),sortwr[2][i]]; } wr=sortwr[1]; M=N; kill N; } if(sortws[1]!=ws) { matrix N[nrows(M)][ncols(M)]; for(i=1;i<=size(ws);i++) { N[i,1..ncols(M)]=M[sortws[2][i],1..ncols(M)]; } ws=sortws[1]; M=N; kill N; } //--------------------------------------------------------------------- // Forming the submatrices //--------------------------------------------------------------------- list R,S; i=1; j=0; while ((step*(i-1))<=wr[size(wr)]) { while ((step*i)>wr[j+1]) { j++; if(j==size(wr)) break; } if(j!=0) { matrix N[nrows(M)][j]=M[1..nrows(M),1..j]; } else { matrix N=matrix(0); } R[i]=N; kill N; i++; if(j==size(wr)) break; } i=1; j=0; while ((step*i)<=ws[size(ws)]) { while ((step*i)>ws[j+1]) { j++; if(j==size(ws)) break; } if(j==size(ws)) break; if(j!=0) { matrix N[nrows(M)-j][ncols(M)]=M[j+1..nrows(M),1..ncols(M)]; S[i]=N; kill N; } else { S[i]=M; } i++; } list ret=R,S; return(ret); } example { "EXAMPLE:"; echo=2; ring r=0,(t(1..3)),dp; matrix M[2][3]=0,t(1),3*t(2),0,0,t(1); print(M); intvec wr=1,3,5; intvec ws=2,4; int step=2; prepMat(M,wr,ws,step); } ///////////////////////////////////////////////////////////////////////////// static proc minorList (list matlist) "USAGE: minorList(l); where l is a list of matrices satisfying the condition that l[i] is a submatrix of l[i+1] RETURN: list of lists in which each entry of the returned list corresponds to one of the matrices of the list l and is itself the list of the minors (i.e. the 1st entry is the ideal generated by the 1-minors of the matrix etc.) EXAMPLE: example minorList(l); shows an example" { //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- int maxminor; int counter; if(size(matlist)==0) { return(matlist); } for(int i=1;i<=size(matlist);i++) { if(((typeof(matlist[i]))!="matrix") && ((typeof(matlist[i]))!="intmat")) { "The list should only contain matrices or intmats"; return("ERROR"); } } list ret,templist; int j; int k=0; ideal minid; //--------------------------------------------------------------------------- // find the maximal size of the minors and compute all possible minors, // and put a minimal system of generators into the list that will be returned //--------------------------------------------------------------------------- for(i=1;i<=size(matlist);i++) { if (nrows(matlist[i]) < ncols(matlist[i])) { maxminor=nrows(matlist[i]); } else { maxminor=ncols(matlist[i]); } if (maxminor < 1) { "The matrices should be of size at least 1 x 1"; return("ERROR"); } kill templist; list templist; for(j=1;j<=maxminor;j++) { minid=minor(matlist[i],j); if(size(minid)>0) { if (defined(watchdog_interrupt)) { kill watchdog_interrupt; } string watchstring="radical(ideal("; for(counter=1;counter =1;j--) { if(size(Ml[i][j])!=0) { templist[j]=Ml[i][j]; isZero=0; } else { if(isZero==0) { return("ERROR"); } } } if(size(templist)!=0) { Ml[i]=templist; } else { rv=rv,r; delvec=delvec,i; } kill templist; } if(size(delvec)>=2) { intvec dummydel=delvec[2..size(delvec)]; Ml=deleteSublist(dummydel,Ml); kill dummydel; } //--------------------------------------------------------------------------- // We do not need to go on if Ml disappeared //--------------------------------------------------------------------------- if(size(Ml)==0) { list ret; list templist; templist[1]=rv; templist[2]=mV; templist[3]=d; ret[1]=templist; return(ret); } //--------------------------------------------------------------------------- // Check for minors which cannot vanish at all //--------------------------------------------------------------------------- def rt=basering; ring ru=0,(U),dp; def rtu=rt+ru; setring rtu; def tempMl; def ML; def D; setring rt; int Mlrank=0; setring rtu; tempMl=imap(rt,Ml); ML=tempMl[1]; D=imap(rt,D); while(Mlrank1) { kill templist; } } if(size(delvec)>=2) { intvec dummydel=delvec[2..size(delvec)]; Ml=deleteSublist(dummydel,Ml); kill dummydel; } } //--------------------------------------------------------------------------- // We do not need to go on if Ml disappeared //--------------------------------------------------------------------------- if(size(Ml)==0) { list ret; list templist; templist[1]=intvec(rv); templist[2]=mV; templist[3]=d; ret[1]=templist; return(ret); } //--------------------------------------------------------------------------- // For each possible rank of Ml[1] and each element of Ml[1][rk] // call this procedure again //--------------------------------------------------------------------------- ideal Did; ideal newV; ideal tempid; poly f; list newd; int newr; list templist,retlist; setring rtu; ideal newV; ideal Did; def d; poly f; setring rt; for(i=0;i<=size(Ml[1]);i++) { // find the polynomials which are not allowed to vanish simulateously if((i f==0 ==> deg(f)<=0 // otherwise factorize f, if it does not take too long, // and add its factors, resp. f itself, to the list d if(deg(f)>0) { f=cleardenom(f); if (defined(watchdog_interrupt)) { kill watchdog_interrupt; } def watchtempid=watchdog(180,"factorize(eval(" + string(f) + "),1)"); if (defined(watchdog_interrupt)) { newd=d; newd[size(d)+1]=f; newd[1]=d[1]*f; } else { tempid=watchtempid; templist=tempid[1..size(tempid)]; newd=d+templist; f=newd[1]*f; tempid=simplify(ideal(newd[2..size(newd)]),14); templist=tempid[1..size(tempid)]; kill newd; list newd=f; newd=newd+templist; } kill watchtempid; } else { newd=d; } // take the corresponding sublist of the list of minors list Mltemp=delete(Ml,1); for(k=1;k<=size(Mltemp);k++) { templist=Mltemp[k]; if(i=2) { intvec dummydel=delvec[2..size(delvec)]; retlist=deleteSublist(dummydel,retlist); kill dummydel; } // set the intvec to the correct value for(i=1;i<=size(retlist);i++) { if(nl!=0) { intvec tempiv=rv,retlist[i][1]; retlist[i][1]=tempiv; kill tempiv; } else { if(size(rv)>1) { intvec tempiv=rv[2..size(rv)]; retlist[i][1]=tempiv; kill tempiv; } } } return(retlist); } example { "EXAMPLE:"; echo=2; ring r=0,(t(1..3)),dp; matrix M[2][3]=0,t(1),3*t(2),0,0,t(1); intvec wr=1,3,5; intvec ws=2,4; int step=2; list l=prepMat(M,wr,ws,step); l[1]; list l2=minorRadList(l[1]); list d=poly(1); strataList(l2,d,ideal(0),0,0); } ///////////////////////////////////////////////////////////////////////////// static proc cleanup(list stratlist) "USAGE: cleanup(l); where l is a list of lists in the format which is e.g. returned by strataList RETURN: list in which entries to the same integer vector have been joined to one entry the changed entries may be identified by checking whether its 3rd entry is an empty list, then all entries starting from the 4th one give the different possibilities for the open set NOTE: use the procedure killdups first to kill entries which are contained in other entries to the same integer vector otherwise the result will be meaningless EXAMPLE: example cleanup; shows an example" { int i,j; list leer; intvec delvec; if(size(stratlist)==0) { return(stratlist); } list ivlist; // sort the list using the intvec as criterion for(i=1;i<=size(stratlist);i++) { ivlist[i]=stratlist[i][1]; } list sortlist=sort(ivlist); list retlist; for(i=1;i<=size(stratlist);i++) { retlist[i]=stratlist[sortlist[2][i]]; } i=1; // find duplicate intvecs in the list while(isize(stratlist)) break; } if (j!=(i+1)) { retlist[i][3+j-i]=retlist[i][3]; retlist[i][3]=leer; i=j-1; // retlist[..][3] is empty if and only if there was more than one entry to this intvec } if(j>size(stratlist)) break; i++; } if(size(delvec)>=2) { intvec dummydel=delvec[2..size(delvec)]; retlist=deleteSublist(dummydel,retlist); kill dummydel; } return(retlist); } example { "EXAMPLE:"; echo=2; ring r=0,(t(1),t(2)),dp; intvec iv=1; list plist=t(1),t(1); list l1=iv,ideal(0),plist; plist=t(2),t(2); list l2=iv,ideal(0),plist; list l=l1,l2; cleanup(l); } ///////////////////////////////////////////////////////////////////////////// static proc joinRS(list Rlist,list Slist) "USAGE: joinRS(Rlist,Slist); where Rlist and Slist are lists in the format returned by strataList RETURN: one list in the format returned by stratalist in which the integer vector is the concatenation of the corresponding vectors from Rlist and Slist (of course only non-empty locally closed sets are returned) NOTE: since Slist is a list returned by strataList corresponding to the s-vector, it corresponds to the list of minors read from back to front EXAMPLE: no example available at the moment" { int j,k; list retlist; list templist,templi2; intvec tempiv; ideal tempid; ideal dlist; poly D; def rt=basering; ring ru=0,(U),dp; def rtu=rt+ru; setring rtu; def Rlist=imap(rt,Rlist); def Slist=imap(rt,Slist); setring rt; for(int i=1;i<=size(Rlist);i++) { for(j=1;j<=size(Slist);j++) { // skip empty sets if(Rlist[i][1][size(Rlist[i][1])]0) { templist[2]=mstd(Rlist[i][2]+Slist[j][2])[2]; } else { templist[2]=ideal(0); } // test again whether we are talking about the empty set setring rtu; def templist=imap(rt,templist); def tempid=templist[2]; if(reduce(1,std(tempid+poly(((Slist[j][3][1])*(Rlist[i][3][1])*U)-1)))==0) { kill templist; kill tempid; j++; setring rt; continue; } else { kill templist; kill tempid; setring rt; } // join the lists d if(size(Rlist[i][3])>1) { templi2=Rlist[i][3]; dlist=templi2[2..size(templi2)]; } else { kill dlist; ideal dlist; } if(size(Slist[j][3])>1) { templi2=Slist[j][3]; tempid=templi2[2..size(templi2)]; } else { kill tempid; ideal tempid; } dlist=dlist+tempid; dlist=simplify(dlist,14); D=1; for(k=1;k<=size(dlist);k++) { D=D*dlist[k]; } if(size(dlist)>0) { templi2=D,dlist[1..size(dlist)]; } else { templi2=list(1); } templist[3]=templi2; retlist[size(retlist)+1]=templist; } } return(retlist); } //////////////////////////////////////////////////////////////////////////// proc stratify(matrix M, intvec wr, intvec ws,int step) "USAGE: stratify(M,wr,ws,step); where M is a matrix, wr is an intvec of size ncols(M), ws an intvec of size nrows(M) and step is an integer RETURN: list of lists, each entry of the big list corresponds to one locally closed set and has the following entries: 1) intvec giving the corresponding rs-vector 2) ideal determining the closed set 3) list d of polynomials determining the open set D(d[1]) empty list if there is more than one open set 4-n) lists of polynomials determining open sets which all lead to the same rs-vector NOTE: * ring ordering should be global, i.e. the ring should be a polynomial ring * the entries of the matrix M are M_ij=delta_i(x_j), * wr is used to determine what subset of the set of all dx_i is generating AdF^l(A): if (k-1)*step < wr[i] <= k*step, then dx_i is in the set of generators of AdF^l(A) for all l>=k * ws is used to determine what subset of the set of all delta_i is generating Z_l(L): if (k-1)*step <= ws[i] < k*step, then delta_i is in the set of generators of Z_l(A) for l < k * the entries of wr and ws as well as step should be positive integers * the filtrations have to be known, no sanity checks concerning the filtrations are performed !!! EXAMPLE: example stratify; shows an example" { //--------------------------------------------------------------------------- // Initialization and sanity checks //--------------------------------------------------------------------------- int i,j; list submat=prepMat(M,wr,ws,step); if(defined(watchProgress)) { "List of submatrices to consider:"; submat; } if(ncols(submat[1][size(submat[1])])==nrows(submat[1][size(submat[1])])) { int symm=1; int nr=nrows(submat[1][size(submat[1])]); for(i=1;i<=nr;i++) { for(j=1;j<=nr-i;j++) { if(submat[1][size(submat[1])][i,j]!=submat[1][size(submat[1])][nr-j+1,nr-i+1]) { symm=0; break; } } if(symm==0) break; } } if(defined(symm)>1) { if(symm==0) { kill symm; } } list Rminors=minorList(submat[1]); if(defined(watchProgress)) { "minors corresponding to the r-vector:"; Rminors; } if(defined(symm)<2) { list Sminors=minorList(submat[2]); if(defined(watchProgress)) { "minors corresponding to the s-vector:"; Sminors; } } if(size(Rminors[1])==0) { Rminors=delete(Rminors,1); } //--------------------------------------------------------------------------- // Start the recursion and cleanup afterwards //--------------------------------------------------------------------------- list leer=poly(1); list Rlist=strataList(Rminors,leer,0,0,0); if(defined(watchProgress)) { "list of strata corresponding to r-vectors:"; Rlist; } Rlist=killdups(Rlist); if(defined(watchProgress)) { "previous list after killing duplicate entries:"; Rminors; } if(defined(symm)<2) { // Sminors have the smallest entry as the last one // In order to use the same routines as for the Rminors // we handle the s-vector in inverse order list Stemp; for(i=1;i<=size(Sminors);i++) { Stemp[size(Sminors)-i+1]=Sminors[i]; } list Slist=strataList(Stemp,leer,0,0,0); if(defined(watchProgress)) { "list of strata corresponding to s-vectors:"; Slist; } //--------------------------------------------------------------------------- // Join the Rlist and the Slist to obtain the stratification //--------------------------------------------------------------------------- Slist=killdups(Slist); if(defined(watchProgress)) { "previous list after killing duplicate entries:"; Slist; } list ret=joinRS(Rlist,Slist); if(defined(watchProgress)) { "list of strata corresponding to r- and s-vectors:"; ret; } ret=killdups(ret); if(defined(watchProgress)) { "previous list after killing duplicate entries:"; ret; } ret=cleanup(ret); } else { list ret=cleanup(Rlist); } return(ret); } example { "EXAMPLE:"; echo=2; ring r=0,(t(1..3)),dp; matrix M[2][3]=0,t(1),3*t(2),0,0,t(1); intvec wr=1,3,5; intvec ws=2,4; int step=2; stratify(M,wr,ws,step); } ///////////////////////////////////////////////////////////////////////////// static proc killdups(list l) "USAGE: killdups(l); where l is a list in the form returned by strataList RETURN: list which is obtained from the previous list by leaving out entries which have the same intvec as another entry in which the locally closed set is contained EXAMPLE: no example available at the moment" { int i=1; int j,k,skip; while(i=2) { delvec=sort(delvec)[1]; intvec dummydel=delvec[2..size(delvec)]; l=deleteSublist(dummydel,l); kill dummydel; } kill delvec; i++; } list ret=l; return(ret); } ///////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/surf.lib000066400000000000000000000266121266270727000176250ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version surf.lib 4.0.0.0 Jun_2013 "; // $Id: 4941ace9657fdbc969215d0661db113cf540815e $ category="Visualization"; info=" LIBRARY: surf.lib Procedures for Graphics with Surf AUTHOR: Hans Schoenemann, Frank Seelisch NOTE: @texinfo Using this library requires the program @code{surf} to be installed. You can download @code{surf} either from @uref{http://sourceforge.net/projects/surf} or from @uref{ftp://www.mathematik.uni-kl.de/pub/Math/Singular/utils/}. The procedure surfer requires the program @code{surfer} to be installed. You can download @code{surfer} from @uref{http://www.imaginary2008.de/surfer.imaginary2008.de} @*Under Windows, version 159 or newer of @code{surfer} is required. Under Mac OS X please move SURFER.app from http://www.mathematik.uni-kl.de/~motsak/files/SURFER.dmg under your /Applications. @end texinfo SEE ALSO: surfex_lib PROCEDURES: plot(I); plots plane curves and surfaces surfer(I); plots surfaces interactivly "; /////////////////////////////////////////////////////////////////////////////// proc num_of_vars(ideal I) "USAGE: num_of_vars(ideal I) RETURN: an intvec containing one entry for each ring variable. each contains the sums of all degrees in this variable of all monomials occuring in the ideal. An entry is zero if and only if the corresponding variable does not occur in the ideal. " { intvec v; int i; poly p; for(i=ncols(I);i>0;i--) { p=I[i]; while(p!=0) { v=v+leadexp(p); p=p-lead(p); } } return(v); } example { "EXAMPLE:"; echo = 2; ring r = 0, (x,y,z),dp; ideal j0 = x^2-x*y; num_of_vars(j0); ideal j1 = x^2-x*y-y; num_of_vars(j1); ideal j2 = x^2-x*y-y, x^3-2*y; num_of_vars(j2); } proc plot(ideal I,list #) "USAGE: plot(I); I ideal or poly ASSUME: I defines a plane curve or a surface given by one equation RETURN: nothing NOTE: requires the external program `surf` to be installed, to close the graphical interface just press `Q` EXAMPLE: example plot; shows an example " { string l = "/tmp/surf" + string(system("pid")); string err_mes; // string containing error messages def base=basering; intvec v=num_of_vars(I); int i,j,n; for(i=size(v);i>0;i--) { if (v[i]!=0) { n++; } } if (n==0 or n>3) { err_mes="Cannot plot equations with "+string(n)+" variables"; ERROR(err_mes); } ring r=0,(x,y,z),dp; short=0; map phi=base,0; j=1; for(i=1;i<=size(v);i++) { if (v[i]!=0) { phi[i]=var(j); j++; if(j==4) break; } } ideal I=simplify(phi(I),2); if (leadcoef(I[1]) <0) { I[1]=-I[1]; } if (ncols(I)==1 and n<=2 and nvars(base)!=3) // curve { write(":w "+l,"clip=none;"); write(l, "width=500; height=500; set_size; do_background=yes; background_red=255; background_green=255; background_blue=255;"); write(l, "root_finder=d_chain_bisection;epsilon=0.0000000001;iterations=20000;"); write(l, "curve_green=0; curve_blue=0; curve_width=1.5;"); if (size(#)>0) { write(l,#[1]); } write(l,"curve=",I[1],";"); write(l,"draw_curve;"); } else { if (ncols(I)==1 and (n==3 or nvars(base)==3)) // surface { write(":w " + l, "root_finder=d_chain_bisection;epsilon=0.0000000001;iterations=20000;"); write(l, "width=500; height=500; set_size; do_background=yes; background_red=255; background_green=255; background_blue=255;"); write(l, "rot_x=0.14; rot_y=-0.3;"); if (size(#) > 0) { write(l, #[1]); } write(l, "surface=",I[1],";"); write(l, "draw_surface;"); } else { err_mes = "cannot plot " + string(ncols(I)) + " equations in " + string(n) + " variables"; ERROR(err_mes); } } string surf_call; i = 0; if (isWindows()) { string surferPath = getShellOutput("which surfer"); if (find(surferPath, "no surfer in") != 0) { /* did not find surfer: either not installed or not yet included in $PATH variable */ err_mes = "calling `surfer` failed" + newline + " (Either the program Surfer is not installed," + newline + " or it has not yet been included in $PATH.)"; ERROR(err_mes); } else { surf_call = "((xwin -multiwindow -clipboard -silent-dup-error"; surf_call = surf_call + " >/dev/null 2>&1 &) && sleep 5 && (sinngularsurf "; surf_call = surf_call + l + ">/dev/null 2>&1))"; surf_call = surf_call + "&& command rm " + l; "Press q to exit from `surf`."; " (You may leave the XServer running for further" + newline + " invocations of `plot`.)"; i = system("sh", surf_call); if (i != 0) { err_mes = "calling `surf` failed" + newline + " (The shell returned the error code " + string(i) + "." + newline + " Perhaps the XServer was not properly set up, so" + newline + " try your plot command again. If `plot` fails" + newline + " again, then make sure that the program Surfer" + newline + " is installed and included in your $PATH variable.)"; ERROR(err_mes); } } } else { surf_call = "singularsurf "; surf_call = surf_call + l + " >/dev/null 2>&1"; "Close window to exit from `singularsurf`."; i = system("sh", surf_call); if (i != 0) { err_mes = "calling `surf` failed" + newline + " (The shell returned the error code " + string(i) + "."; ERROR(err_mes); } } system("sh", "command rm " + l); } example { "EXAMPLE:"; echo = 2; // --------- plane curves ------------ ring rr0 = 0,(x1,x2),dp; ideal I = x1^3 - x2^2; plot(I); ring rr1 = 0,(x,y,z),dp; ideal I(1) = 2x2-1/2x3 +1-y+1; plot(I(1)); // ---- Singular Logo -------------- poly logo = ((x+3)^3 + 2*(x+3)^2 - y^2)*(x^3 - y^2)*((x-3)^3-2*(x-3)^2-y^2); plot(logo); // Steiner surface ideal J(2) = x^2*y^2+x^2*z^2+y^2*z^2-17*x*y*z; plot(J(2)); // -------------------- plot(x*(x2-y2)+z2); // E7 plot(x^3-x*y^3+z^2); // Whitney umbrella plot(z^2-x^2*y); } proc surfer(ideal I) "USAGE: surfer(f); f poly ASSUME: f defines a surface given by one equation RETURN: nothing NOTE: requires the external program `surfer` to be installed, to close the graphical interface just close the window of surfer EXAMPLE: example surfer; shows an example " { string lForWindows = "surfer" + string(system("pid")); string l = "./" + lForWindows; string err_mes; // string containing error messages def base=basering; intvec v=num_of_vars(I); int i,j,n; for(i=size(v);i>0;i--) { if (v[i]!=0) { n++; } } if (n==0 or n>3) { err_mes="Cannot plot equations with "+string(n)+" variables"; ERROR(err_mes); } ring r=0,(x,y,z),dp; short=0; map phi=base,0; j=1; for(i=1;i<=size(v);i++) { if (v[i]!=0) { phi[i]=var(j); j++; if(j==4) break; } } ideal I=simplify(phi(I),2); if (leadcoef(I[1]) <0) { I[1]=-I[1]; } if (ncols(I)==1 and (n==3 or nvars(base)==3)) // surface { write(":w " + l, "surface=" + string(I[1]) + ";"); } else { err_mes = "cannot plot " + string(ncols(I)) + " equations in " + string(n) + " variables"; ERROR(err_mes); } string surf_call; i = 0; if (isWindows()) { string surferPath = getShellOutput("which surfer"); if (find(surferPath, "no surfer in") != 0) { /* did not find surfer: either not installed or not yet included in $PATH variable */ err_mes = "calling `surfer` failed" + newline + " (Either the program Surfer is not installed," + newline + " or it has not yet been included in $PATH.)"; ERROR(err_mes); } else { string singularPath = getShellOutput("pwd"); surferPath = windowsCorrection(surferPath); surferPath = surferPath[1..size(surferPath)-size("/surfer")]; singularPath = windowsCorrection(singularPath); link ll = "|: cygpath -w " + singularPath; singularPath = "'\""+read(ll)+"\"'"; close(ll); surf_call = "cygstart -w -d " + surferPath + " "; surf_call = surf_call + surferPath + "/surfer "; surf_call = surf_call + singularPath + "/" + lForWindows; "Close window to exit from `surfer`."; i = system("sh", surf_call); } } else { surf_call = "surfer"; surf_call = surf_call + " " + l + " >/dev/null 2>&1"; "Close window to exit from `surfer`."; i = system("sh", surf_call); if ( (i != 0) && isMacOSX() ) { "*!* Sorry: calling `surfer` failed ['"+surf_call+"']" + newline + " (The shell returned the error code " + string(i) + "." + newline + "But since we are on Mac OS X, let us try to open SURFER.app instead..." + newline + "Appropriate SURFER.app is available for instance at http://www.mathematik.uni-kl.de/~motsak/files/SURFER.dmg"; // fallback, will only work if SURFER.app is available (e.g. in /Applications) // get SURFER.app e.g. from http://www.mathematik.uni-kl.de/~motsak/files/SURFER.dmg // note that the newer (Java-based) variant of Surfer may not support command line usage yet :( surf_call = "open -a SURFER -W --args -t -s"; surf_call = surf_call + " " + l + " >/dev/null 2>&1"; "Close window to exit from `surfer`."; i = system("sh", surf_call); } } system("sh", "command rm " + l); if (i != 0) { err_mes = "calling `surfer` failed" + newline + " (The shell returned the error code " + string(i) + "."; ERROR(err_mes); } } example { "EXAMPLE:"; echo = 2; ring rr1 = 0,(x,y,z),dp; // Steiner surface ideal J(2) = x^2*y^2+x^2*z^2+y^2*z^2-17*x*y*z; surfer(J(2)); // -------------------- surfer(x*(x2-y2)+z2); // E7 surfer(x^3-x*y^3+z^2); // Whitney umbrella surfer(z^2-x^2*y); } static proc isWindows() "returns 1 if this SINGULAR instance runs under (some) Windows OS; 0 otherwise" { string s = system("uname"); for (int i = 1; i <= size(s)-2; i = i + 1) { if (s[i] == "W") { if (s[i+1] == "i") { if (s[i+2] == "n") { return (1); } } } } return (0); } static proc isMacOSX() "returns 1 if this SINGULAR instance runs under (some) Mac OS X; 0 otherwise" { string s = system("uname"); for (int i = 1; i <= size(s)-2; i = i + 1) { if (s[i] == "d" or s[i] == "D") { if (s[i+1] == "a" or s[i+1] == "A") { if (s[i+2] == "r" or s[i+2] == "R") { return (1); } } } } return (0); } static proc getShellOutput(string shellCommand) "returns the console output when executing the given shellCommand" { int s; string tempFilename = "tmp" + string(system("pid")); s = system("sh", shellCommand + " > " + tempFilename + " 2>&1"); string r1 = read(tempFilename); s = size(r1) - 1; string r2 = r1[1..s]; s = system("sh", "command rm " + tempFilename); return (r2); } static proc windowsCorrection(string windowsPath) "puts a backslash in front of each space and each special character and returns the resulting string" { string s = ""; int i; for (i = 1; i <= size(windowsPath); i++) { if (find(" ()", windowsPath[i]) != 0) { s = s + "\\"; } s = s + windowsPath[i]; } return (s); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/surfacesignature.lib000066400000000000000000000354521266270727000222220ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version surfacesignature.lib 4.0.0.0 Jun_2014 "; // $Id: 2627fa5318c92bdc77035f6e5bf28d53f61900e4 $ category="Singularities"; info=" LIBRARY: surfacesignature.lib signature of surface singularity AUTHORS: Gerhard Pfister pfister@mathematik.uni-kl.de @* Muhammad Ahsan Banyamin ahsanbanyamin@gmail.com @* Stefan Steidel steidel@mathematik.uni-kl.de OVERVIEW: A library for computing the signature of irreducible surface singularity. The signature of a surface singularity is defined in [3]. The algorithm we use has been proposed in [9]. Let g in C[x,y] define an isolated curve singularity at 0 in C^2 and f:=z^N+g(x,y). The zero-set V:=V(f) in C^3 of f has an isolated singularity at 0. For a small e>0 let V_e:=V(f-e) in C^3 be the Milnor fibre of (V,0) and s: H_2(V_e,R) x H_2(V_e,R) ---> R be the intersection form (cf. [1],[7]). H_2(V_e,R) is an m-dimensional R-vector space, m the Milnor number of (V,0) (cf. [1],[4],[5],[6]), and s is a symmetric bilinear form. Let sigma(f) be the signature of s, called the signature of the surface singularity (V,0). Formulaes to compute the signature are given by Nemethi (cf. [8],[9]) and van Doorn, Steenbrink (cf. [2]). We have implemented three approaches using Puiseux expansions, the resolution of singularities resp. the spectral pairs of the singularity. REFERENCES: [1] Arnold, V.I.; Gusein-Zade, S.M.; Varchenko, A.N.: Singularities of Differentiable Mappings. Vol. 1,2, Birkh\"auser (1988). [2] van Doorn, M.G.M.; Steenbrink, J.H.M.: A supplement to the monodromy theorem. Abh. Math. Sem. Univ. Hamburg 59, 225-233 (1989). [3] Durfee, A.H.: The Signature of Smoothings of Complex Surface Singularities. Mathematische Annalen 232, 85-98 (1978). [4] de Jong, T.; Pfister, G.: Local Analytic Geometry. Vieweg (2000). [5] Kerner, D.; Nemethi, A.: The Milnor fibre signature is not semi-continous. arXiv:0907.5252 (2009). [6] Kulikov, V.S.: Mixed Hodge Structures and Singularities. Cambridge Tracts in Mathematics 132, Cambridge University Press (1998). [7] Nemethi, A.: The real Seifert form and the spectral pairs of isolated hypersurface singularities. Compositio Mathematica 98, 23-41 (1995). [8] Nemethi, A.: Dedekind sums and the signature of f(x,y)+z^N. Selecta Mathematica, New series, Vol. 4, 361-376 (1998). [9] Nemethi, A.: The Signature of f(x,y)+z^$. Proceedings of Real and Complex Singularities (C.T.C. Wall's 60th birthday meeting, Liverpool (England), August 1996), London Math. Soc. Lecture Notes Series 263, 131--149 (1999). PROCEDURES: signatureBrieskorn(a1,a2,a3); signature of singularity x^a1+y^a2+z^a3 signaturePuiseux(N,f); signature of singularity z^N+f(x,y)=0, f irred. signatureNemethi(N,f); signature of singularity z^N+f(x,y)=0 "; LIB "hnoether.lib"; LIB "alexpoly.lib"; LIB "gmssing.lib"; /////////////////////////////////////////////////////////////////////////////// //------- sigma(z^N + f) in terms of Puiseux pairs of f for f irreducible ----- static proc exponentSequence(poly f) //=== computes the sequence a_1,...,a_s of exponents as described in [Nemethi] //=== using the Puiseux pairs (m_1, n_1),...,(m_s, n_s) of f: //=== - a_1 = m_1, //=== - a_i = m_i - n_i * (m_[i-1] - n_[i-1] * a_[i-1]). //=== //=== Return: list of two intvecs: //=== 1st entry: A = (a_1,...,a_s) //=== 2nd entry: N = (n_1,...,n_s) { def R = basering; ring S = 0,(x,y),dp; poly f = fetch(R,f); list puiseuxPairs = invariants(f); setring R; intvec M = puiseuxPairs[1][3]; intvec N = puiseuxPairs[1][4]; int i; int a = M[1]; intvec A = a; for(i = 2; i <= size(M); i++) { a = M[i] - N[i] * (M[i-1] - N[i-1] * a); A[size(A)+1] = a; } return(list(A,N)); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; exponentSequence(y4+2x3y2+x6+x5y); } /////////////////////////////////////////////////////////////////////////////// proc signatureBrieskorn(int a1, int a2, int a3) "USAGE: signatureBrieskorn(a1,a2,a3); a1,a2,a3 = integers RETURN: signature of Brieskorn singularity x^a1+y^a2+z^a3 EXAMPLE: example signatureBrieskorn; shows an example " { int a_temp, t, k1, k2, k3, s_t, sigma; number s; if(a1 > a2) { a_temp = a1; a1 = a2; a2 = a_temp; } if(a2 > a3) { a_temp = a2; a2 = a3; a3 = a_temp; } if(a1 > a2) { a_temp = a1; a1 = a2; a2 = a_temp; } for(t = 0; t <= 2; t++) { s_t = 0; for(k1 = 1; k1 <= a1-1; k1++) { for(k2 = 1; k2 <= a2-1; k2++) { for(k3 = 1; k3 <= a3-1; k3++) { s = number(k1)/a1 + number(k2)/a2 + number(k3)/a3; if(t < s) { if(s < t+1) { s_t = s_t + 1; } else { break; } } } if(k3 == 1) { break; } } if(k2 == 1) { break; } } sigma = sigma + (-1)^t * s_t; } return(sigma); } example { "EXAMPLE:"; echo = 2; ring R = 0,x,dp; signatureBrieskorn(11,3,5); } /////////////////////////////////////////////////////////////////////////////// proc signaturePuiseux(int N, poly f) "USAGE: signaturePuiseux(N,f); N = int, f = irreducible poly in 2 variables RETURN: signature of surface singularity defined by z^N + f(x,y) = 0 EXAMPLE: example signaturePuiseux; shows an example " { int i, d, prod, sigma; list L = exponentSequence(f); int s = size(L[2]); if(s == 1) { return(signatureBrieskorn(L[1][1], L[2][1], N)); } prod = 1; sigma = signatureBrieskorn(L[1][s], L[2][s], N); for(i = s - 1; i >= 1; i--) { prod = prod * L[2][i+1]; d = gcd(N, prod); sigma = sigma + d * signatureBrieskorn(L[1][i], L[2][i], N div d); } return(sigma); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; int N = 3; poly f = x15-21x14+8x13y-6x13-16x12y+20x11y2-x12+8x11y-36x10y2 +24x9y3+4x9y2-16x8y3+26x7y4-6x6y4+8x5y5+4x3y6-y8; signaturePuiseux(N,f); } /////////////////////////////////////////////////////////////////////////////// //------- sigma(z^N + f) in terms of the imbedded resolution graph of f ------- static proc dedekindSum(number b, number c, int a) { number s,d,e; int k; for(k=1;k<=a-1;k++) { d=bigint(k*b) mod a; e=bigint(k*c) mod a; if(d*e!=0) { s=s+(d/a-1/2)*(e/a-1/2); } } return(s); } /////////////////////////////////////////////////////////////////////////////// static proc isRupture(intvec v) //=== decides whether the exceptional divisor given by the row v in the //=== incidence matrix of the resolution graph intersects at least 3 other //=== divisors { int i,j; for(i=1;i<=size(v);i++) { if(v[i]<0){return(0);} if(v[i]!=0){j++;} } return(j>=4); } /////////////////////////////////////////////////////////////////////////////// static proc sumExcepDiv(intmat N, list M, int K, int n) //=== computes part of the formulae for eta(g,K), g defining an //=== isolated curve singularity //=== N the incidence matrix of the resolution graph of g //=== M list of total multiplicities //=== n = nrows(N) { int i,j,m,d; for(i=1;i<=n;i++) { if(N[i,i]>0) { m=gcd(K,M[i]); for(j=1;j<=n;j++) { if((i!=j)&&(N[i,j]!=0)) { if(m==1){break;} m=gcd(m,M[j]); } } d=d+m-1; } } return(d); } /////////////////////////////////////////////////////////////////////////////// static proc sumEdges(intmat N, list M, int K, int n) //=== computes part of the formulae for eta(g,K), g defining an //=== isolated curve singularity //=== N the incidence matrix of the resolution graph of g //=== M list of total multiplicities //=== n = nrows(N) { int i,j,d; for(i=1;i<=n-1;i++) { for(j=i+1;j<=n;j++) { if(N[i,j]==1) { d=d+gcd(K,gcd(M[i],M[j]))-1; } } } return(d); } /////////////////////////////////////////////////////////////////////////////// static proc etaRes(list L, int K) //=== L total multiplicities //=== eta-invariant in terms of the imbedded resolution graph of f { int i,j,d; intvec v; number e; intmat N = L[1]; // incidence matrix of the resolution graph int n = ncols(L[1]); // number of vertices in the resolution graph int a = ncols(L[2]); // number of branches list M; // total multiplicities for(i=1;i<=n;i++) { d=L[2][i,1]; for(j=2;j<=a;j++) { d=d+L[2][i,j]; } if(d==0){d=1;} M[i]=d; } for(i=1;i<=n;i++) { v=N[i,1..n]; if(isRupture(v)) // the divisor intersects more then two others { for(j=1;j<=n;j++) { if((i!=j)&&(v[j]!=0)) { e=e+dedekindSum(M[j],K,M[i]); } } } } if(a==1) { //the irreducible case return(4*e); } return(a-1+4*e+sumEdges(N,M,K,n)-sumExcepDiv(N,M,K,n)); } /////////////////////////////////////////////////////////////////////////////// static proc signatureRes(int N, poly f) //=== computes signature of surface singularity defined by z^N + f(x,y) = 0 //=== in terms of the imbedded resolution graph of f { list L = totalmultiplicities(f); return(etaRes(L,N) - N*etaRes(L,1)); } /////////////////////////////////////////////////////////////////////////////// //------------ sigma(z^N + f) in terms of the spectral pairs of f ------------- static proc fracPart(number n) //=== computes the fractional part n2 of n //=== i.e. n2 is not in Z but n-n2 is in Z { number a,b; int r; a = numerator(n); b = denominator(n); int z = int(number(a)); int y = int(number(b)); r = z mod y; int q = (z-r) div y; number n1 = q; number n2 = n-n1; return(n2); } /////////////////////////////////////////////////////////////////////////////// static proc etaSpec(list L, int N) //=== L spectral numbers //=== eta-invariant in terms of the spectral pairs of f { int i; number e, h; int n = ncols(L[1]); if((n mod 2) == 0) // 0 is not a spectral number, thus f is irreducible { for(i = n div 2+1; i <= n; i++) { e = e + (1 - 2 * fracPart(N * number(L[1][i]))) * L[3][i]; } return(2*e); } else // 0 is a spectral number, thus f is reducible { // sum of Hodge numbers in eta function for(i = 1; i <= n; i++) { if((L[2][i] == 2) && ((denominator(leadcoef(N*L[1][i]))==1) ||(denominator(leadcoef(N*L[1][i]))==-1))) { h = h + L[3][i]; } } // summand coming from spectral number 0 in eta function h = h + L[3][(n+1) div 2]; // sum coming from non-zero spectral numbers in eta function for(i = (n+3) div 2; i <= n; i++) { if(!((denominator(leadcoef(N*L[1][i]))==1) ||(denominator(leadcoef(N*L[1][i]))==-1))) { e = e + (1 - 2 * fracPart(N * number(L[1][i]))) * L[3][i]; } } return(h + 2*e); } } /////////////////////////////////////////////////////////////////////////////// static proc signatureSpec(int N, poly f) //=== computes signature of surface singularity defined by z^N + f(x,y) = 0 //=== in terms of the spectral pairs of f { def R = basering; def Rds = changeord(list(list("ds",1:nvars(basering)))); setring Rds; poly f = imap(R,f); list L = sppairs(f); setring R; list L = imap(Rds,L); return(etaSpec(L,N) - N*etaSpec(L,1)); } /////////////////////////////////////////////////////////////////////////////// //----------------- Consolidation of the two recent variants ------------------ proc signatureNemethi(int N, poly f, list #) "USAGE: signatureNemethi(N,f); N = integer, f = reduced poly in 2 variables, # empty or 1,2,3 @* - if #[1] = 1 then resolution of singularity is used @* - if #[1] = 2 then spectral pairs are used @* - if # is empty then both upper variants are used in parallel and the @* fastest returns the result RETURN: signature of surface singularity defined by z^N + f(x,y) = 0 REMARK: computes the signature of some special surface singularities EXAMPLE: example signatureNemethi; shows an example " { if(size(#) == 0) { link l(1) = "ssi:fork"; open(l(1)); link l(2) = "ssi:fork"; open(l(2)); list l = list(l(1),l(2)); write(l(1), quote(signatureRes(N,f))); write(l(2), quote(signatureSpec(N,f))); int winner = waitfirst(l); number sigma = read(l(winner)); close(l(1)); close(l(2)); if(printlevel >= 1) { if(winner == 1) { "Resolution of singularity has been used."; } if(winner == 2) { "Spectral pairs have been used."; } } return(sigma); } if(#[1] == 1) { return(signatureRes(N,f)); } if(#[1] == 2) { return(signatureSpec(N,f)); } } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y),dp; int N = 3; poly f = x15-21x14+8x13y-6x13-16x12y+20x11y2-x12+8x11y-36x10y2 +24x9y3+4x9y2-16x8y3+26x7y4-6x6y4+8x5y5+4x3y6-y8; signatureNemethi(N,f,1); printlevel = 1; signatureNemethi(N,f); } /////////////////////////////////////////////////////////////////////////////// /* Further examples ring r = 0,(x,y),dp; int N; poly f,g,g1,g2,g3; // irreducible polynomials N = 5; f = x15-21x14+8x13y-6x13-16x12y+20x11y2-x12+8x11y-36x10y2 +24x9y3+4x9y2-16x8y3+26x7y4-6x6y4+8x5y5+4x3y6-y8; g = f^3 + x17y17; N = 6; f = y4+2x3y2+x6+x5y; g1 = f^2 + x5y5; g2 = f^3 + x11y11; g3 = f^3 + x17y17; N = 7; f = x5+y11; g1 = f^3 + x11y11; g2 = f^3 + x17y17; N = 6; // k0 = 30, k1 = 35, k2 = 71 f = x71+6x65+15x59-630x52y6+20x53+6230x46y6+910x39y12+15x47 -7530x40y6+14955x33y12-285x26y18+6x41+1230x34y6+4680x27y12 +1830x20y18+30x13y24+x35-5x28y6+10x21y12-10x14y18+5x7y24-y30; // k0 = 16, k1 = 24, k2 = 28, k3 = 30, k4 = 31 f = x31-781x30+16x29y-3010x29-2464x28y+104x27y2-2805x28-7024x27y -5352x26y2+368x25y3+366x27-7136x26y-984x25y2-8000x24y3 +836x23y4+34x26-320x25y-6464x24y2+6560x23y3-8812x22y4+1392x21y5 -12x25+256x24y-1296x23y2-1536x22y3+4416x21y4-8864x20y5+1752x19y6 -x24+16x23y-88x22y2-16x21y3-404x20y4+3056x19y5-6872x18y6+1648x17y7 +8x21y2-96x20y3+524x19y4-1472x18y5+3464x17y6-3808x16y7+1290x15y8 -28x18y4+240x17y5-976x16y6+2208x15y7-2494x14y8+816x13y9+56x15y6 -320x14y7+844x13y8-1216x12y9+440x11y10-70x12y8+240x11y9-344x10y10 +240x9y11+56x9y10-96x8y11+52x7y12-28x6y12+16x5y13+8x3y14-y16; // reducible polynomials N = 12; f = ((y2-x3)^2 - 4x5y - x7)*(x2-y3); f = 2x3y3-2y5+x4-xy2; f = -x3y3+x6y+xy6-x4y4; */ singular-4.0.3+ds/Singular/LIB/surfex.lib000066400000000000000000001377711266270727000201730ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version surfex.lib 4.0.0.0 Jun_2013 "; // $Id: 2fb800ee344397b6175558e40cba9e886c6192ba $ category="Visualization"; info=" LIBRARY: surfex.lib Procedures for visualizing and rotating surfaces. @* It is still an alpha version (see http://www.AlgebraicSurface.net) AUTHOR: Oliver Labs This library uses the program surf (written by Stefan Endrass and others) and surfex (written by Oliver Labs and others, mainly Stephan Holzer). NOTE: This library requires the program surfex, surf and java to be installed. The software is used for producing raytraced images of surfaces. You can download @code{surfex} from http://www.surfex.AlgebraicSurface.net surfex is a front-end for surf which aims to be easier to use than the original tool. SEE ALSO: surf_lib PROCEDURES: plotRotated(poly,coord); Plot the surface given by the polynomial p with the coordinates coords(list) plotRot(poly); Similar to plotRotated, but guesses automatically which coordinates should be used plotRotatedList(varieties, coords); Plot the varieties given by the list varieties with the coordinates coords plotRotatedDirect(varieties); Plot the varieties given by the list varietiesList plotRotatedListFromSpecifyList(varietiesList); Plot the varieties given by the list varietiesList "; LIB "solve.lib"; LIB "primdec.lib"; LIB "sing.lib"; LIB "surf.lib"; /////////////////////////////////////////////////////////// // // the main procedures: // proc plotRot(poly p, list #) " USAGE: plotRot(poly p, list #) Similar to plotRotated, but guesses automatically which coordinates should be used. The optional int parameter can be used to set plotting quality. It opens the external program surfex for drawing the surface given by p, seen as a surface in the real affine space with coordinates coords. ASSUME: The basering is of characteristic zero and without parameters. " { list coords = list(); if(num_vars_id(p)==3) { execute("coords = "+string_of_vars(p)+";"); } else { if(num_vars_id(p)<3) { if(nvars(basering)==3) { execute("coords = "+varstr(basering)+";"); } else { if(nvars(basering)<3) { "Could not guess the coordinates because the number of variables in the basering is smaller than 3!"; "Please use plotRotated() instead of plotRot() and specify the coordinates explicitly."; return(0); } else { "Could not guess the coordinates because the number of variables in the polynomial is smaller than 3 and the number of variables in the basering is greater than three!"; "Please use plotRotated() instead of plotRot() and specify the coordinates explicitly."; return(0); } } } else { "Could not guess the coordinates because the number of variables in the polynomial is greater than 3!"; "Please use plotRotated() instead of plotRot() and specify the coordinates explicitly."; return(0); } } return(plotRotatedList(list(p), coords, #)); } example { "Example:"; echo=2; // More variables in the basering, but only 3 variables in the polynomial: ring r1 = 0, (w,x,y,z), dp; poly cayley_cubic = x^3+y^3+z^3+1^3-1/4*(x+y+z+1)^3; plotRot(cayley_cubic); // Three variables in the basering, but fewer variables in the polynomial: ring r2 = 0, (x,y,z), dp; plotRot(x^2+y^2-1); plotRot(y^2+z^2-1); // A cubic surface with a solitary point: // Use the additional parameter 3 to ask singular // to compute the singular locus before calling surfex. ring r3 = 0, (x,y,z), dp; poly kn_10 = x^3-3*x*y^2+z^3+3*x^2+3*y^2+z^2; plotRot(kn_10, 3); // The swallowtail: // a surface with a real solitary curve sticking out of the surface. // Use the additional parameter 3 to ask singular // to compute the singular locus before calling surfex. poly swallowtail = -4*y^2*z^3-16*x*z^4+27*y^4+144*x*y^2*z+128*x^2*z^2-256*x^3; } proc plotRotated(poly p, list coords, list #) " USAGE: plotRotated(poly p, list coords, list #) This opens the external program surfex for drawing the surface given by p, seen as a surface in the real affine space with coordinates coords. The optional int parameter can be used to set plotting quality. ASSUME: coords is a list of three variables. The basering is of characteristic zero and without parameters. " { return(plotRotatedList(list(p), coords, #)); } example { "Example:"; echo=2; // An easy example: a surface with four conical nodes. ring r = 0, (x,y,z), dp; poly cayley_cubic = x^3+y^3+z^3+1^3-1/4*(x+y+z+1)^3; // plotRotated(cayley_cubic, list(x,y,z)); // A difficult example: a surface with a one-dimensional real component! poly whitney_umbrella = x^2*z-y^2; // The Whitney Umbrella without its handle: plotRotated(whitney_umbrella, list(x,y,z)); // The Whitney Umbrella together with its handle: plotRotated(whitney_umbrella, list(x,y,z), 2); } proc plotRotatedList(list varieties, list coords, list #) " USAGE: plotRotatedList(list varieties, list coords, list #) This opens the external program surfex for drawing the surfaces given by varieties, seen as a surface in the real affine space with coordinates coords. The optional int parameter can be used to set plotting quality. ASSUME: coords is a list of three variables, varieties is a list of ideals describing the varieties to be shown. The basering is of characteristic zero and without parameters. " { def oring = basering; int plotquality = 0; if(size(#)>0) { plotquality = #[1]; } list varietiesList = list(list(), list(), list(), list()); list usedSurfaces = list(); list curveColors = list(); // go through the list of varieties // produce a list which can be used as input for plotRotatedListFromList() int i; int j; list indList; int ind; ideal itmp; int ncurves; list pd; int k; int surfind; list curSurfColors = list(); list listOfPoints = list(); string str_I = ""; for(i=1; i<=size(varieties); i++) { itmp = varieties[i]; if(plotquality>=3) { itmp = radical(itmp); } itmp = simplify(itmp,1); itmp = simplify(itmp,2); if(size(itmp)==1) { // i.e.: a surface given by one equation surfind = findInList(surfEqn(itmp[1],coords), usedSurfaces); if(surfind==0) { usedSurfaces = usedSurfaces + list(surfEqn(itmp[1],coords)); curSurfColors = list(list("insidecolor:",getInsideColorStr(size(varietiesList[1])+1)), list("outsidecolor:",getOutsideColorStr(size(varietiesList[1])+1))); varietiesList[1] = varietiesList[1] + list(list(list("eqno:",string(size(varietiesList[1])+1)), list("equation:",surfEqn(itmp[1], coords)), curSurfColors[1], curSurfColors[2], list("showcbox:","true"), list("transparency:","0"))); surfind = size(varietiesList[1]); } if(plotquality==1) { varieties = varieties + list(slocus(itmp[1])); } if(plotquality==2 || plotquality==3) { // remove doubled components and // add the 1-dimensional singular components // of the surface to the list of curves: int dsl = dim_slocus(itmp[1]); dsl; if(dsl>=0) { // i.e. there is a singular locus "compute singular locus..."; list eqd; // eqd = equidim(slocus(itmp[1])); ideal tmp_l; tmp_l = std(eqd[size(eqd)]); "dim:",dim(tmp_l); if(dim(tmp_l)==(nvars(basering)-3+2)) { "--- 2-dim."; // we have found a multiple component; // replace it by a simple copy of it itmp = quotient(itmp[1], tmp_l); varieties[i] = itmp[1]; eqd = delete(eqd,size(eqd)); if(size(eqd)>0) { tmp_l = std(eqd[size(eqd)]); } } if(dim(tmp_l)==(nvars(basering)-3+1)) { "--- 1-dim."; // we have found a 1-dimensional singular locus pd = std_primdecGTZ(tmp_l,2); for(k=1; k<=size(pd); k++) { if(pd[k][3]==(nvars(basering)-3+1)) { varieties = varieties + list(pd[k][2]); curveColors[size(varieties)] = curSurfColors; } else { "???"; } } eqd = delete(eqd,size(eqd)); if(size(eqd)>0) { tmp_l = std(eqd[size(eqd)]); } } if(dim(tmp_l)==(nvars(basering)-3+0)) { "--- 0-dim."; // we have found a 0-dimensional singular locus // we compute floating point approximations of the // coordinates of all singular points if(npars(oring)>0) { "str:",parstr(1),rootminpoly(); list all_real_sols = allroots_minpoly(); // "all sols:";all_real_sols; // sprintf("number %s = %s; ", parstr(1), rootminpoly()); int minp; if((npars(basering) == 1) && (minpoly != 0)) { minp = 1; } else { minp = 0; } str_I = ""; if(minp==1) { "minp=1"; string str_para = parstr(1); string str_tmp_l; def cur_ring = basering; if(1) { short=0; str_tmp_l = "ideal eqd_tmp = "+ // string(tmp_l)+","+string(minpoly)+";"; string(tmp_l); "str:",str_tmp_l; string str_num_mp = "number "+parstr(1)+"="+ decstr2ratstr(rootminpoly())+";"; execute("ring Iring = 0,(" // +string(coords)+","+str_para+"),dp;"); +string(coords)+"),dp;"); basering; execute(str_num_mp); execute(str_tmp_l); eqd_tmp; list real_sols = real_solve(eqd_tmp); real_sols; $; setring cur_ring; } } else { // minp==0: we do not know how to handle this "???"; } } else { "no pars"; ideal eqd_tmp = tmp_l; short=0; string str_tmp_l = "ideal eqd_tmp = "+string(tmp_l)+";"; def cur_ring = basering; execute("ring Iring = (real,30),("+string(coords)+"),("+ordstr(oring)+");"); // basering; execute(str_I); execute(str_tmp_l); list real_sols = real_solve(eqd_tmp); setring cur_ring; } "real_sols:";real_sols; for(k=1; k<=size(real_sols); k++) { "search point:"; string(list(real_sols[k][1],real_sols[k][2],real_sols[k][3],string(surfind))); // listOfPoints; if(findInList(string(list(list(real_sols[k][1],real_sols[k][2],real_sols[k][3],string(surfind)))), listOfPoints)==0) { "add pt"; varietiesList[4] = varietiesList[4] + list(list(real_sols[k][1],real_sols[k][2],real_sols[k][3],string(surfind))); listOfPoints = listOfPoints + list(string(list(real_sols[k][1],real_sols[k][2],real_sols[k][3],string(surfind)))); } } } } } } else { // i.e.: more than one equation varietiesList[2] = varietiesList[2] + list(list(list("surfaces:"), list("curveno:", string(size(varietiesList[2])+1)), list("showcbox:","true"))); if(size(curveColors) >= i) { varietiesList[2][size(varietiesList[2])][4] = curveColors[i][1]; varietiesList[2][size(varietiesList[2])][4][1] = "color:"; } ncurves = size(varietiesList[2]); for(j=1; j<=size(itmp); j++) { ind = findInList(surfEqn(itmp[j],coords), usedSurfaces); usedSurfaces = usedSurfaces + list(surfEqn(itmp[1],coords)); // "indList:";indList; if(ind == 0) { // "--------> not in list", surfEqn(itmp[j], coords); if(j==1) { varietiesList[1] = varietiesList[1] + list(list(list("eqno:",string(size(varietiesList[1])+1)), list("equation:",surfEqn(itmp[j], coords)), list("insidecolor:",getInsideColorStr(size(varietiesList[1])+1)), list("outsidecolor:",getOutsideColorStr(size(varietiesList[1])+1)), list("showcbox:","true"), list("transparency:","100"))); } else { varietiesList[1] = varietiesList[1] + list(list(list("eqno:",string(size(varietiesList[1])+1)), list("equation:",surfEqn(itmp[j], coords)), list("insidecolor:",getInsideColorStr(size(varietiesList[1])+1)), list("outsidecolor:",getOutsideColorStr(size(varietiesList[1])+1)), list("showcbox:","false"), list("transparency:","0"))); } ind = size(varietiesList[1]); } else { } varietiesList[2][ncurves][1] = varietiesList[2][ncurves][1] + list(string(ind)); } } } // "------------"; // varietiesList; // "------------"; return(plotRotatedListFromSpecifyList(varietiesList, coords, #)); } example { "Example:"; echo=2; // A cubic surface together with a tritangent plane // (i.e. a plane which cuts out three lines). ring r = 0, (x,y,z), dp; poly cayley_cubic = x^3+y^3+z^3+1^3-1/4*(x+y+z+1)^3; poly plane = 1-x-y-z; plotRotatedList(list(cayley_cubic, plane), list(x,y,z)); // The same cubic and plane. // The plane is not shown but only its intersection with the surface. plotRotatedList(list(cayley_cubic, ideal(cayley_cubic, plane)), list(x,y,z)); } proc plotRotatedListFromSpecifyList(list varietiesList, list #) " USAGE: plotRotatedListFromSpecifyList(list varietiesList, list #); varietiesList has a complicated format (not documented yet); see the example.@* The optional int parameter can be used to set plotting quality. ASSUME: The basering is of characteristic zero. EXAMPLE: example plotRotatedListFromSpecifyList; " { // make the surfex file string str = getSurfexCodeFromSpecifyList(varietiesList, #); return(plotRotatedFromCode(str, #)); } example { "Example:"; echo=2; // A cubic surface depending on a parameter: ring r = (0,p1), (x,y,z), dp; poly cayley_cubic = x^3+y^3+z^3+1^3-p1*(x+y+z+1)^3; poly plane = 1-x-y-z; plotRotatedListFromSpecifyList(list(list(list(list("eqno:","1"), list("equation:", string(cayley_cubic)) ) ), list(), list(list(1,"0.0","1.0","500","0.25+0.25*sin(PI*p1)")), list() )); } proc plotRotatedListFromStringList(list varieties, list #) " RETURN: the return code of the system command which executes surfex. USAGE: not documented yet. " { // make the surfex file getSurfexCodeFromStringList(varieties, #); string str = getSurfexCodeFromStringList(varieties, #); return(plotRotatedFromCode(str, #)); } proc plotRotatedDirect(list varieties, list #) " USAGE: plotRotatedDirect(list varieties, list #) This opens the external program surfex for drawing the surfaces given by varieties, seen as a surface in the real affine space with coordinates x,y,z. The format for the list varieties is not fully documented yet; please, see the examples below and try to adjust the examples to suit your needs.@* The optional int parameter can be used to set plotting quality. ASSUME: Passes the equations directly to surfex, i.e., the variable names should be x,y,z. The advantage is that one can use parameters p1, p2, ...; these will be passed to surfex. " { string str = getSurfexCodeFromListDirect(varieties, #); return(plotRotatedFromCode(str, #)); } example { "Example:"; echo=2; // A cubic surface depending on a parameter: ring r = (0,p1), (x,y,z), dp; poly cayley_cubic = x^3+y^3+z^3+1^3-p1*(x+y+z+1)^3; // The entries of the list of varieties can either be polynomials plotRotatedDirect(list(list(list(cayley_cubic)), list(), list(list(1,"0.0","1.0","500","0.25+0.25*sin(PI*p1)")) )); // or strings which represent surfex-readable polynomials plotRotatedDirect(list(list(list("x^3+y^3+z^3+1^3-p1*(x+y+z+1)^3")), list(), list(list("1","0.0","1.0","500","0.25+0.25*sin(PI*p1)")) )); // More complicated varieties plotRotatedDirect(list(list(list("x^2+y^2-z^2-3^2"), list("x*sin(p1)+y*cos(p1)-3")), list(list(list(1,2))), list(list("1","0.0","1.0","500","2*PI*p1")) )); } proc plotRotatedFromCode(string str, list #) " USAGE: plotRotatedFromCode(string str, list #); This procedure is only for internal usage; it takes the surfex-code as a string and calls surfex. " { // we need a temporary .sux file for surfex string tmpd = "/tmp"; string l="surf"+string(system("pid"))+".sux"; // a temporary file which stores the output of surfex string erg="/tmp/surferg"+string(system("pid")); write(":w "+tmpd+"/"+l, str); string surfex_path=system("Singular"); while(surfex_path[size(surfex_path)]!="/") { surfex_path=surfex_path[1..size(surfex_path)-1]; } surfex_path=surfex_path+"../LIB/surfex"; if (status(surfex_path,"exists")=="no") { // search in SINGULAR_PATH: string surfex_path1=system("SingularLib"); string surfex_path2=surfex_path1; while (find(surfex_path1,":")!=0) { surfex_path2=surfex_path1[1..find(surfex_path1,":")-1]; while(surfex_path2[size(surfex_path2)]==" ") { surfex_path2 = surfex_path2[1..(size(surfex_path2)-1)]; } if (status(surfex_path2+"/surfex","exists")=="yes") break; surfex_path1=surfex_path1[find(surfex_path1,":")+1,size(surfex_path1)]; surfex_path2=surfex_path1[1..(size(surfex_path1)-1)]; while(surfex_path2[size(surfex_path2)]==" ") { surfex_path2 = surfex_path2[1..(size(surfex_path2)-1)]; } } surfex_path=surfex_path2+"/surfex"; } int i=system("sh","surfex \""+surfex_path+"\" -d "+tmpd+" -i " + l +" >"+erg+" 2>/dev/null"); // delete the temporary file i = system("sh","rm " + l +" 2>/dev/null"); return(read(erg)); } /////////////////////////////////////////////////////////// // // procedures used to produce the surf-code: // proc getSurfexCodeFromListDirect(list varieties, list #) " USAGE: getSurfexCodeFromListDirect(list varieties, list #) ASSUME: varieties has four components, - the first is a list of polynomials, say f_1, ..., f_k - the second is a list of lists of numbers in {1, ..., k} describing the curves as intersections of the corresponding f_i - the third is a list of lists describing the parameters used in the polynomials f_i - the fourth is a list of lists of points given by their approximate coordinates (three decimal numbers) RETURN: the surfex code (.sux) " { int i; int j; string str = "this is surfex v0.89.07"+newline; str = str + "TYPE:" + newline; str = str + "specify"+newline; str = str + "EQUATIONS:"+newline; str = str + string(size(varieties[1])) + newline; for(i=1; i<=size(varieties[1]); i++) { str = str + "Equation:"+newline; str = str + "eqno:"+newline; str = str + string(i) + newline; str = str + "equation:"+newline; str = str + surfEqnDir(varieties[1][i][1]) + newline; if(size(varieties[1][i])>=2) { str = str + "showcbox:"+newline; str = str + varieties[1][i][2] + newline; // show it or not if(size(varieties[1][i])>=3) { str = str + "transparency:"+newline; str = str + string(varieties[1][i][3]) + newline; // transparency } } } str = str + "CURVES:"+newline; str = str + string(size(varieties[2])) + newline; for(i=1; i<=size(varieties[2]); i++) { str = str + "Curve:"+newline; str = str + "curveno:"+newline; str = str + string(i) + newline; str = str + "surfaces:"+newline; // "curves:";varieties[2][i]; for(j=1; j<=size(varieties[2][i][1]); j++) { str = str + string(varieties[2][i][1][j]) + newline; } if(size(varieties[2][i])>=2) { str = str + "showcbox:"+newline; str = str + varieties[2][i][2] + newline; // show it or not } } str = str + "PARAMETERS:"+newline; str = str + string(size(varieties[3])) + newline; for(i=1; i<=size(varieties[3]); i++) { str = str + "Parameter:"+newline; str = str + "parno:"+newline; str = str + string(varieties[3][i][1]) + newline; str = str + "fromtoval:"+newline; str = str + varieties[3][i][2] + newline; str = str + varieties[3][i][3] + newline; str = str + string(varieties[3][i][4]) + newline; if(size(varieties[3][i])>=5) { str = str + "function:"+newline; str = str + varieties[3][i][5]+newline; } } // str = str + "////////////////// Parameter: /////////////////////////"+newline; // str = str + "1" + newline; // str = str + "0.0" + newline; // str = str + "1.0" + newline; // str = str + "1000" + newline; // str = str + string(size(varieties[3])) + newline; return(str); } proc getSurfexCodeFromList(list varieties, list coords, list #) " ASSUME: varieties has four components, - the first is a list of polynomials, say f_1, ..., f_k - the second is a list of lists of numbers in {1, ..., k} describing the curves as intersections of the corresponding f_i - the third is a list of lists describing the parameters used in the polynomials f_i - the fourth is a list of lists of points given by their approximate coordinates (three decimal numbers) RETURN: the surfex code (.sux) " { int i; int j; string str = "this is surfex v0.89.07"+newline; str = str + "TYPE:" + newline; str = str + "specify"+newline; str = str + "EQUATIONS:"+newline; str = str + string(size(varieties[1])) + newline; for(i=1; i<=size(varieties[1]); i++) { str = str + "Equation:"+newline; str = str + "eqno:"+newline; str = str + string(i) + newline; str = str + "equation:"+newline; str = str + surfEqn(varieties[1][i][1], coords) + newline; str = str + "showcbox:"+newline; str = str + varieties[1][i][2] + newline; // show it or not str = str + "transparency:"+newline; str = str + string(varieties[1][i][3]) + newline; // transparency } str = str + "CURVES:"+newline; str = str + string(size(varieties[2])) + newline; for(i=1; i<=size(varieties[2]); i++) { str = str + "Curve:"+newline; str = str + "curveno:"+newline; str = str + string(i) + newline; str = str + "surfaces:"+newline; for(j=1; j<=size(varieties[2][i]); j++) { str = str + string(varieties[2][i][1][j]) + newline; } str = str + "showcbox:"+newline; str = str + varieties[2][i][2] + newline; // show it or not } str = str + "PARAMETERS:"+newline; str = str + string(size(varieties[3])) + newline; for(i=1; i<=size(varieties[3]); i++) { str = str + "Parameter:"+newline; str = str + "parno:"+newline; str = str + string(varieties[3][i][1]) + newline; str = str + "fromtoval:"+newline; str = str + surfEqn(varieties[3][i][2], coords) + newline; str = str + surfEqn(varieties[3][i][3], coords) + newline; str = str + string(varieties[3][i][4]) + newline; if(size(varieties[3][i])>=5) { str = str + "function:"+newline; str = str + varieties[3][i][5]+newline; } } // str = str + "////////////////// Parameter: /////////////////////////"+newline; // str = str + "1" + newline; // str = str + "0.0" + newline; // str = str + "1.0" + newline; // str = str + "1000" + newline; // str = str + string(size(varieties[3])) + newline; return(str); } proc getSurfexCodeFromStringList(list varieties, list #) " ASSUME: varieties has three components, - the first is a list of polynomials, say f_1, ..., f_k - the second is a list of lists of numbers in {1, ..., k} describing the curves as intersections of the corresponding f_i - the third is a list of lists describing the parameters used in the polynomials f_i RETURN: the surfex code (.sux) " { int i; int j; string str = "this is surfex v0.89.07"+newline; str = str + "TYPE:" + newline; str = str + "specify"+newline; str = str + "EQUATIONS:"+newline; str = str + string(size(varieties[1])) + newline; for(i=1; i<=size(varieties[1]); i++) { str = str + "Equation:"+newline; str = str + "eqno:"+newline; str = str + string(i) + newline; str = str + "equation:"+newline; str = str + varieties[1][i][1] + newline; str = str + "showcbox:"+newline; str = str + varieties[1][i][2] + newline; // show it or not str = str + "transparency:"+newline; str = str + varieties[1][i][3] + newline; // transparency } str = str + "CURVES:"+newline; str = str + string(size(varieties[2])) + newline; for(i=1; i<=size(varieties[2]); i++) { str = str + "Curve:"+newline; str = str + "curveno:"+newline; str = str + string(i) + newline; str = str + "surfaces:"+newline; for(j=1; j<=size(varieties[2][i][1]); j++) { str = str + string(varieties[2][i][1][j]) + newline; } str = str + "showcbox:"+newline; str = str + varieties[2][i][2] + newline; // show it or not } str = str + "PARAMETERS:"+newline; str = str + string(size(varieties[3])) + newline; for(i=1; i<=size(varieties[3]); i++) { str = str + "Parameter:"+newline; str = str + "parno:"+newline; str = str + string(varieties[3][i][1]) + newline; str = str + "fromtoval:"+newline; str = str + varieties[3][i][2] + newline; str = str + varieties[3][i][3] + newline; str = str + string(varieties[3][i][4]) + newline; if(size(varieties[3][i])>=5) { str = str + "function:"+newline; str = str + varieties[3][i][5]+newline; } } return(str); } proc getSurfexCodeFromSpecifyList(list varieties, list #) " ASSUME: varieties has three components, - the first is a list of polynomials, say f_1, ..., f_k - the second is a list of lists of numbers in {1, ..., k} describing the curves as intersections of the corresponding f_i - the third is a list of lists describing the parameters used in the polynomials f_i - the fourth is a list of lists describing the singular points to be shown as spheres RETURN: the surfex code (.sux) " { int i; int j; int k; string str = "this is surfex v0.89.07"+newline; str = str + "TYPE:" + newline; str = str + "specify"+newline; str = str + "EQUATIONS:"+newline; str = str + string(size(varieties[1])) + newline; for(i=1; i<=size(varieties[1]); i++) { str = str + "Equation:"+newline; for(j=1; j<=size(varieties[1][i]); j++) { str = str + varieties[1][i][j][1] +newline; str = str + varieties[1][i][j][2] +newline; } } str = str + "CURVES:"+newline; str = str + string(size(varieties[2])) + newline; for(i=1; i<=size(varieties[2]); i++) { str = str + "Curve:"+newline; for(j=1; j<=size(varieties[2][i]); j++) { str = str + varieties[2][i][j][1] +newline; if(varieties[2][i][j][1] == "surfaces:") { for(k=2; k<=size(varieties[2][i][j]); k++) { str = str + string(varieties[2][i][j][k]) + newline; } } else { str = str + varieties[2][i][j][2] +newline; } } // str = str + "curveno:"+newline; // str = str + string(i) + newline; // str = str + "surfaces:"+newline; // for(j=1; j<=size(varieties[2][i][1]); j++) { // str = str + string(varieties[2][i][1][j]) + newline; // } // str = str + "showcbox:"+newline; // str = str + varieties[2][i][2] + newline; // show it or not } str = str + "PARAMETERS:"+newline; str = str + string(size(varieties[3])) + newline; for(i=1; i<=size(varieties[3]); i++) { str = str + "Parameter:"+newline; str = str + "parno:"+newline; str = str + string(varieties[3][i][1]) + newline; str = str + "fromtoval:"+newline; str = str + varieties[3][i][2] + newline; str = str + varieties[3][i][3] + newline; str = str + string(varieties[3][i][4]) + newline; if(size(varieties[3][i])>=5) { str = str + "function:"+newline; str = str + varieties[3][i][5]+newline; } } string str_from = "0.0"; string str_to = "5.0"; string str_radius = "50"; str = str + "SOLITARY POINTS:"+newline; str = str + string(size(varieties[4])) + newline; for(i=1; i<=size(varieties[4]); i++) { str = str + "SolitaryPoint:"+newline; str = str + "solPtNo:"+newline; str = str + string(i) + newline; str = str + "surface:"+newline; str = str + varieties[4][i][4] + newline; str = str + "fromtoval:"+newline; str = str + str_from + newline; str = str + str_to + newline; str = str + str_radius + newline; str = str + "coords:" + newline; str = str + varieties[4][i][1] + newline; str = str + varieties[4][i][2] + newline; str = str + varieties[4][i][3] + newline; } return(str); } /////////////////////////////////////////////////////////// // // procedures for standard colors: // proc numBaseColors() " USAGE: numBaseColors() RETURN: the number of predefined surface colors. " { return(6); } proc baseSurfaceColors(int no) " USAGE: baseSurfaceColors(int no) REMARK: There are currently 6=numBaseColors() basic surface colors. You can modify them according to your wishes by just redefining this procedure in your Singular-script. If you want more colors, then you also have to redefine numBaseColors() accordingly. RETURN: a list of three integers describing the RGB values of a color. " { if(no%numBaseColors()==1) { return(list(240,160,0)); } if(no%numBaseColors()==2) { return(list(160,240,0)); } if(no%numBaseColors()==3) { return(list(0,160,240)); } if(no%numBaseColors()==4) { return(list(240,0,160)); } if(no%numBaseColors()==5) { return(list(0,240,160)); } if(no%numBaseColors()==0) { return(list(160,0,240)); } } proc getInsideColorStr(int no) " USAGE: getInsideColorStr(int no) RETURN: a string describing inside color number no where the three integer RGB values are in one line each. " { list bc = baseSurfaceColors(no); string str = string(bc[1])+newline+string(bc[2])+newline+string(bc[3]); return(str); } proc getOutsideColorStr(int no) " USAGE: getOutsideColorStr(int no) RETURN: a string describing outside color number no where the three integer RGB values are in one line each. " { list bc = baseSurfaceColors(no); string str = string(bc[1])+newline+string(bc[2])+newline+string(bc[3]); return(str); } /////////////////////////////////////////////////////////// // // procedures used by the plot procedures: // proc surfEqnDir(list #) " USAGE: surfEqnDir(list #) without any checks etc. RETURN: string(#[1]) where short=0. " { int stmp = short; short = 0; string str = string(#[1]); short = stmp; return(str); } proc surfEqn(poly p, list coords, list #) " USAGE: surfEqn(poly p, list coords) Tries to produce a string for the equation of p which is convenient for surfex. ASSUME: - p defines a plane curve or a surface, - coords is a list of the three coordinates to use, e.g. list(x,y,z), in this way, it is possible to distinguish between x^2+y^2-1 and y^2+z^2-1 RETURN: a string, that one can use with the external program surf EXAMPLE: example surfEqn; shows an example " { int params=0; if(size(#)>0) { params = #[1]; } string err_mes; // string containing error messages def base=basering; int mynvars = nvars(basering); intvec ind=num_of_vars(p); int i,j,n; int minp = 0; n=0; for(i=size(ind);i>0;i--) { if (ind[i]!=0) { n++; } else { if(var(i)==coords[1] || var(i)==coords[2] || var(i)==coords[3]) { ind[i]=1; n++; } } } params = params + npars(basering); n = n + npars(basering); if((npars(basering) == 1) && (minpoly != 0)) { minp = 1; } else { minp = 0; } string str_I = ""; for(i=1; i<=npars(basering); i=i+1) { if(!(parstr(i) == "i")) { if(minp==1) { str_I = str_I + sprintf("number %s = %s; ", parstr(i), rootminpoly()); } else { } } } int bshort = short; short = 0; if(!(minp==1 || npars(basering)==0)) { p=cleardenom(p); err_mes="Cannot plot equations with a parameter without a specified minpoly"; ERROR(err_mes); } str_I = str_I + "poly p = " + string(p) + ";"; short = bshort; if(params==0) { if (n<=2 or n>=4) { err_mes="Cannot plot equations with "+string(n)+" variables"; ERROR(err_mes); // return("0"); } if(n==4) { ring r=(real,30,30),(xx,yy,zz,ww),dp; } else { ring r=(real,30,30),(x,y,z),dp; } } else { if(n-params<=2 || n-params>=4) { err_mes="Cannot plot equations with "+string(n-params)+" variables"; ERROR(err_mes); // return("0"); } else { if(params == 1) { if(n-params==3) { if(minp==1) { // switch to a ring without minimal polynomial: execute("ring rr = (real,30,30),("+varstr(base)+"), dp;"); // rr; // "str_I",str_I; execute(str_I); def base = rr; ring r=(real,30,30),(x,y,z),dp; } else { p=cleardenom(p); ring r=(real,30,30),(x,y,z,p1),dp; } } } if(params == 2) { if(n-params==3) { p=cleardenom(p); ring r=(real,30,30),(x,y,z,p1,p2),dp; } } if(params == 3) { if(n-params==3) { p=cleardenom(p); execute("ring rr = (real,30,30),("+varstr(base)+","+parstr(base)+"), dp;"); rr; "str_I",str_I; execute(str_I); "pnew:",p; def base = rr; ring r=(real,30,30),(x,y,z,p1,p2,p3),dp; } } } } // basering; short=0; map phi=base,0; j=1; for(i=1;i<=mynvars;i++) { if (ind[i]!=0) { phi[i]=var(j); j++; } } poly p=(simplify(phi(p),1)); if (leadcoef(p) <0) { if(size(#)>1) { if(#[2]!=0) { p=-p; } } else { p=-p; } } if(leadcoef(p)!=0) { p = p/leadcoef(p); } string thesurfstr = string(p); if(minp == 1) { // replace k by rootRepl } return (thesurfstr); } // end of surfEqn() example { "EXAMPLE:"; echo =2; ring rr0 = 0,(x(1..3)),dp; poly p = x(1)^3 - x(2)^2; print(surfEqn(p,list(x(1),x(2),x(3)))); ring rr1 = 0,(x,y,z),dp; poly I(1) = 2x2-1/2x3 +1-y+1; print(surfEqn(I(1),list(x,y,z))); // Steiner surface poly J(2) = x^2*y^2+x^2*z^2+y^2*z^2-17*x*y*z; print(surfEqn(J(2),list(x,y,z))); } // end of example surfEqn() proc num_vars_id(ideal I) " USAGE: num_vars_id(ideal I) RETURN: The number of ring-variables occurring in the ideal I. " { intvec v = num_of_vars(I); int num = 0; for(int i=size(v);i>0;i--) { if (v[i]!=0) { num++; } } return(num); } example { "EXAMPLE:"; echo = 2; ring r = 0, (x,y,z),dp; ideal j = x^2-y, x^3-2; num_vars_id(j); } proc findInList(list obj, list l) " USAGE: findInList(list obj, list l) Tries to find the object obj in the list l. ASSUME: the object obj[1] can be compared to the objects in the list l RETURN: if obj[1]=l[i] for some i, then return the first such i, otherwise return 0 " { for(int i=1; i<=size(l); i++) { if(l[i]==obj[1]) { return(i); } } return(0); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z), dp; list a = list(x^2+y^2+z^2+1, x^2+y^2+z^2-1, x^2+y^2-z^2+1, x^2+y^2-z^2-1); findInList(x^2+y^2+z^2-1, a); findInList(x^2+y^2+z^2, a); } proc std_primdecGTZ(ideal I, list #) " USAGE: std_primdecGTZ(ideal I, list #) Computes a primdary decomposition pd of I using primdecGTZ and then calls std_for_pd(pd). For the output and options, consult the help of std_for_pd. RETURN: see std_for_pd. " { list pd = primdecGTZ(I); return(std_for_pd(pd, #)); } example { "EXAMPLE:"; echo = 2; ring r = 0, (x,y), dp; ideal j = y-x^2,z-x^3; primdecGTZ(j); std_primdecGTZ(j); std_primdecGTZ(j,1); } proc std_for_pd(list pd, list #) " USAGE: std_for_pd(list pd, list #) Call std for each of the prime ideals in the list pd replace the prime ideals by their standard-basis. Compute dim() and mult() of each prime component using these standard bases. If an additional argument is given then do the same for the primary components. ASSUME: pd is in the format produced by primdecGTZ() or primdecSY(). RETURN: A list, say l, of lists, similar to a list returned by primdecSY() or primdecGTZ(). However, each of the entries of l (which is a list l[i]) contains some additional entries: l[1]: the primary ideal l[2]: a standard basis of the associated prime ideal l[3]: dim() of this prime ideal l[4]: mult() of this prime ideal If an additional argument # is given then l[1] changes: l[1]: a standard basis of the primary ideal Morever, there are some more entries: l[5]: dim() of this primary ideal l[6]: mult() of this primary ideal l[7]: l[6] / l[5] " { if(typeof(pd[1])=="ideal") { // this is a Singular bug!? // "bug!";pd;"---"; pd = list(list(pd[1], pd[1])); // pd;$; } list pd_neu; int i; list coords; ideal stdtmp; ideal stdtmp2; for(i=1; i<=size(pd); i++) { stdtmp = std(pd[i][2]); stdtmp2 = pd[i][1]; if(size(#)>0) { stdtmp2 = std(stdtmp2); if(mult(stdtmp)==0) { pd_neu[i] = list(stdtmp2, stdtmp, dim(stdtmp), mult(stdtmp), dim(stdtmp2), mult(stdtmp2), 0); } else { pd_neu[i] = list(stdtmp2, stdtmp, dim(stdtmp), mult(stdtmp), dim(stdtmp2), mult(stdtmp2), mult(stdtmp2) div mult(stdtmp)); } } else { pd_neu[i] = list(stdtmp2, stdtmp, dim(stdtmp), mult(stdtmp)); } } return(pd_neu); } example { "EXAMPLE:"; echo = 2; ring r = 0, (x,y,z), dp; ideal j = y-x^2,z-x^3; list pd = primdecGTZ(j); pd; std_for_pd(pd, 1); } proc real_solve(ideal to_solve) " USAGE: real_solve(ideal to_solve) RETURN: a list of all real solutions (as strings) of the zero-dimensional ideal to_solve (without multiplicities). REMARK: Until now, it may happen that some points appear more than once. " { int k; int i; // def Isolring = solve(to_solve,30,0,60,"nodisplay"); def Isolring = solve(to_solve,9,0,13,"nodisplay"); setring Isolring; // list SOL = solve(to_solve, "oldring", "nodisplay"); list real_sols = list(); list tmpl; for(k=1; k<=size(SOL); k++) { if(find(string(SOL[k]),"I")==0 && find(string(SOL[k]),"i")==0) { tmpl = list(); for(i=1; i<=size(SOL[k]); i++) { tmpl = tmpl + list(string(SOL[k][i])); } real_sols = real_sols + list(tmpl); } } return(real_sols); } example { "EXAMPLE:"; echo = 2; ring r = 0, (x,y), dp; number a = 2; number b = 3; ideal j = (x^2-a),(y^3-b); real_solve(j); } proc rootminpoly(list #) " USAGE: rootminpoly(list #) RETURN: A root of the current minpoly as a string representation of a complex number with the given precision #[1] (default: 30). E.g. ring r=(0,s),x,dp; minpoly = s^2-2; => rootminpoly() 1.41421356237309504880168872421 ASSUME: The current minpoly is non-zero. " { int prec = 30; int k, done; if(size(#)>0) { prec = #[1]; } short = 0; string str_lag = sprintf("list lag = laguerre_solve(%s);", minpoly); string str_ring = sprintf("ring r_sqrt = (complex,prec,I),(%s),lp;", parstr(basering)); execute(str_ring); execute(str_lag); // lag; // choose a real solution, if it exists: done = 0; for(k=1; k<=size(lag) && done==0; k++) { if(find(string(lag[k]),"I")==0) { done = k; } } if(done==0) { // "no real solution."; } if(size(lag)>2) { // return the first real solution return(sprintf("%s",lag[done])); } if(sprintf("%s",lag[1])[1] == "-") { return(sprintf("%s",lag[2])); } else { if(sprintf("%s",lag[1])[1] == "(") { if(sprintf("%s",lag[1])[2] == "-") { return(sprintf("%s",lag[2])); } else { return(sprintf("%s",lag[1])); } } else { return(sprintf("%s",lag[1])); } } short = 1; } example { "EXAMPLE:"; echo =2; ring r=(0,s),x,dp; minpoly = s^2-2; rootminpoly(); ring R=(0,s),x,dp; minpoly = s^2+2; rootminpoly(); } proc allroots_minpoly(list #) " USAGE: allroots_minpoly(list #) RETURN: a list of strings containing all real roots of the minimal polynomial of the active ring. ASSUME: The current minpoly is non-zero. " { int prec = 30; int k, done; if(size(#)>0) { prec = #[1]; } short = 0; string str_lag = sprintf("list lag = laguerre_solve(%s);", minpoly); string str_ring = sprintf("ring r_sqrt = (complex,prec,I),(%s),lp;", parstr(basering)); execute(str_ring); execute(str_lag); // only take the real solutions: done = 0; list real_sols = list(); for(k=1; k<=size(lag) && done==0; k++) { if(find(string(lag[k]),"I")==0) { real_sols = real_sols + list(string(lag[k])); } } return(real_sols); } example { "EXAMPLE:"; echo = 2; ring r=(0,s),x,dp; minpoly = s^3-2; allroots_minpoly(); ring R=(0,s),x,dp; minpoly = s^2-2; allroots_minpoly(); } proc decstr2ratstr(string str) " USAGE: decstr2ratstr(string str) Convert a decimal number of not more than 30 digits to a rational number with 14 digits. REMARK: This procedure still has to be adapted to accept other precisions! " { ring decR = (complex,30,I),(x),lp; execute("number r="+str+";"); execute("r = "+truncdec(r,14)+";"); return(real2ratstr(r)); } proc real2ratstr(number r) " USAGE: real2ratstr(number r) RETURN: A string containing a rational number representing the decimal number r. ASSUME: The current ring has either real or complex base field. " { string ratstr = "number("+string(r*number(10000000000000000))+")/number(10000000000000000)"; return(ratstr); } proc truncdec(number r, int decs) " USAGE: truncdec(number r, int decs) Truncates a decimal number r to the given number (decs) of digits. RETURN: A string representing the truncated number. " { string str = string(r); return(str[1,(decs+2)]); } proc string_of_vars(ideal I) " USAGE: string_of_vars(ideal I) RETURN: A string of all variables contained in the ideal I, separated by commas. " { list listvars = list(); intvec v; int i; poly p; for(i=size(I);i>0;i--) { p=I[i]; while(p!=0) { v=v+leadexp(p); p=p-lead(p); } } for(i=1; i<=nvars(basering); i++) { if(v[i] > 0) { listvars = listvars + list(var(i)); } } string strvars = string(listvars); return(strvars); } singular-4.0.3+ds/Singular/LIB/swalk.lib000066400000000000000000000507061266270727000177700ustar00rootroot00000000000000//////////////////////////////////////////////////////// version="version swalk.lib 4.0.0.0 Jun_2013 "; // $Id: $ category="Commutative Algebra"; info=" LIBRARY: swalk.lib Sagbi Walk Conversion Algorithm AUTHOR: Junaid Alam Khan junaidalamkhan@gmail.com OVERVIEW: A library for computing the Sagbi basis of subalgebra through Sagbi walk algorithm. THEORY: The concept of SAGBI ( Subalgebra Analog to Groebner Basis for Ideals) is defined in [L. Robbiano, M. Sweedler: Subalgebra Bases, volume 42, volume 1430 of Lectures Note in Mathematics series, Springer-Verlag (1988),61-87]. The Sagbi Walk algorithm is the subalgebra analogue to the Groebner Walk algorithm which has been proposed in [S. Collart, M. Kalkbrener and D.Mall: Converting bases with the Grobner Walk. J. Symbolic Computation 24 (1997), 465-469]. PROCEDURES: swalk(ideal[,intvec]); Sagbi basis of subalgebra via Sagbi walk algorithm rswalk(ideal,int,int[,intvec]); Sagbi basis of subalgebra via Random Sagbi Walk Algorithm "; LIB "sagbi.lib"; LIB "atkins.lib"; ////////////////////////////////////////////////////////////////////////////// proc swalk(ideal Gox, list #) "USAGE: swalk(i[,v,w]); i ideal, v,w int vectors RETURN: The sagbi basis of the subalgebra defined by the generators of i, calculated via the Sagbi walk algorithm from the ordering dp to lp if v,w are not given (resp. from the ordering (a(v),lp) to the ordering (a(w),lp) if v and w are given). EXAMPLE: example swalk; shows an example " { /* we use ring with ordering (a(...),lp,C) */ list OSCTW = OrderStringalp_NP("al", #);//"dp" string ord_str = OSCTW[2]; intvec icurr_weight = OSCTW[3]; /* original weight vector */ intvec itarget_weight = OSCTW[4]; /* terget weight vector */ kill OSCTW; option(redSB); def xR = basering; list rl=ringlist(xR); rl[3][1][1]="dp"; def ostR=ring(rl); setring ostR; def new_ring = basering; ideal Gnew = fetch(xR, Gox); Gnew=sagbi(Gnew,1); Gnew=interreduceSd(Gnew); vector curr_weight=changeTypeInt(icurr_weight); vector target_weight=changeTypeInt(itarget_weight); ideal Gold; list l; intvec v; int n=0; while(n==0) { Gold=Gnew; def old_ring=new_ring; setring old_ring; number ulast; kill new_ring; if(curr_weight==target_weight){n=1;} else { l=collectDiffExpo(Gold); ulast=last(curr_weight, target_weight, l); vector new_weight=(1-ulast)*curr_weight+ulast*target_weight; vector w=cleardenom(new_weight); v=changeType(w); list p= ringlist(old_ring); p[3][1][2]= v; def new_ring=ring(p); setring new_ring; ideal Gold=fetch(old_ring,Gold); vector curr_weight=fetch(old_ring,new_weight); vector target_weight=fetch(old_ring,target_weight); kill old_ring; ideal Gnew=Convert(Gold); Gnew=interreduceSd(Gnew); } } setring xR; ideal result = fetch(old_ring, Gnew); attrib(result,"isSB",1); return (result); } example { "EXAMPLE:";echo = 2; ring r = 0,(x,y), lp; ideal I =x2,y2,xy+y,2xy2+y3; swalk(I); } ////////////////////////////////////////////////////////////////////////////// proc rswalk(ideal Gox, int weight_rad, int pdeg, list #) "USAGE: rswalk(i,weight_rad,p_deg[,v,w]); i ideal, v,w int vectors RETURN: The sagbi basis of the subalgebra defined by the generators of i, calculated via the Sagbi walk algorithm from the ordering dp to lp if v,w are not given (resp. from the ordering (a(v),lp) to the ordering (a(w),lp) if v and w are given). EXAMPLE: example swalk; shows an example " { /* we use ring with ordering (a(...),lp,C) */ list OSCTW = OrderStringalp_NP("al", #);//"dp" string ord_str = OSCTW[2]; intvec icurr_weight = OSCTW[3]; /* original weight vector */ intvec itarget_weight = OSCTW[4]; /* terget weight vector */ kill OSCTW; option(redSB); def xR = basering; list rl=ringlist(xR); rl[3][1][1]="dp"; def ostR=ring(rl); setring ostR; def new_ring = basering; ideal Gnew = fetch(xR, Gox); Gnew=sagbi(Gnew,1); Gnew=interreduceSd(Gnew); vector curr_weight=changeTypeInt(icurr_weight); vector target_weight=changeTypeInt(itarget_weight); ideal Gold; list l; intvec v; int n=0; while(n==0) { Gold=Gnew; def old_ring=new_ring; setring old_ring; kill new_ring; if(curr_weight==target_weight){n=1;} else { l=collectDiffExpo(Gold); vector new_weight=RandomNextWeight(Gold, l, curr_weight, target_weight, weight_rad, pdeg); vector w=cleardenom(new_weight); v=changeType(w); list p= ringlist(old_ring); p[3][1][2]= v; def new_ring=ring(p); setring new_ring; ideal Gold=fetch(old_ring,Gold); vector curr_weight=fetch(old_ring,new_weight); vector target_weight=fetch(old_ring,target_weight); kill old_ring; ideal Gnew=Convert(Gold); Gnew=interreduceSd(Gnew); } } setring xR; ideal result = fetch(old_ring, Gnew); attrib(result,"isSB",1); return (result); } example { "EXAMPLE:";echo = 2; ring r = 0,(x,y), lp; ideal I =x2,y2,xy+y,2xy2+y3; rswalk(I,2,2); } ////////////////////////////////////////////////////////////////////////////// static proc inprod(vector v,vector w) "USAGE: inprod(v,w); v,w vectors RETURN: inner product of vector v and w EXAMPLE: example inprod; shows an example " { poly a; int i; for(i=1;i<=nvars(basering);i++) { a=a+v[i]*w[i] ; } return(a); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),lp; vector v =[1,-1,2]; vector w = [1,0,3]; inprod(v,w); } ////////////////////////////////////////////////////////////////////////////// static proc diffExpo(poly f) "USAGE: diffExpo(f); f polynomial RETURN: a list of integers vectors which are the difference of exponent vector of leading monomial of f with the exponent vector of of other monmials in f. EXAMPLE: example diffExpo; shows an example " { list l; int i; intvec v; for(i=size(f);i>=2;i--) { v=leadexp(f[1])-leadexp(f[i]); l[i-1]=v; } return(l); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),lp; poly f = xy+z2 ; diffExpo(f); } ////////////////////////////////////////////////////////////////////////////// static proc collectDiffExpo( ideal i) "USAGE: collectDiffExpo(i); i ideal RETURN: a list which contains diffExpo(f), for all generators f of ideal i EXAMPLE: example collectDiffExpo; shows an example " { list l; int j; for(j=ncols(i); j>=1;j--) { l[j]=diffExpo(i[j]); } return(l); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),lp; ideal I = xy+z2,y3+x2y2; collectDiffExpo(I); } ////////////////////////////////////////////////////////////////////////////// static proc changeType(vector v) "USAGE: changeType(v); v vector RETURN: change the type of vector v into integer vector. EXAMPLE: example changeType; shows an example " { intvec w ; int j ; for(j=1;j<=nvars(basering);j++) { w[j]=int(leadcoef(v[j])); } return(w); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),lp; vector v = [2,1,3]; changeType(v); } ////////////////////////////////////////////////////////////////////////////// static proc changeTypeInt( intvec v) "USAGE: changeTypeInt(v); v integer vector RETURN: change the type of integer vector v into vector. EXAMPLE: example changeTypeInt; shows an example " { vector w; int j ; for(j=1;j<=size(v);j++) { w=w+v[j]*gen(j); } return(w); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),lp; intvec v = 4,2,3; changeTypeInt(v); } ////////////////////////////////////////////////////////////////////////////// static proc last( vector c, vector t,list l) "USAGE: last(c,t,l); c,t vectors, l list RETURN: a parametric value which corresponds to vector lies along the path between c and t using list l of integer vectors. This vector is the last vector on old Sagbi cone EXAMPLE: example last; shows an example " { number ul=1; int i,j,k; number u; vector v; for(i=1;i<=size(l);i++) { for(j=1;j<=size(l[i]);j++) { v=0; for(k=1;k<=size(l[i][j]);k++) { v=v+l[i][j][k]*gen(k); } poly n= inprod(c,v); poly q= inprod(t,v); number a=leadcoef(n); number b=leadcoef(q); number z=a-b; if(b<0) { u=a/z; if(usize(P)) {break;} } return(q); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; poly f = x2+yz+z; initialForm(f); } ////////////////////////////////////////////////////////////////////////////// static proc Initial(ideal I) "USAGE: Initial(I); I ideal RETURN: an ideal which is generate by the InitialForm of the generators of I. EXAMPLE: example Initial; shows an example " { ideal J; int i; for(i=1;i<=ncols(I);i++) { J[i]=initialForm(I[i]); } return(J); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; ideal I = x+1,x+y+1; Initial(I); } ////////////////////////////////////////////////////////////////////////////// static proc Lift(ideal In,ideal InG,ideal Gold) "USAGE: Lift(In, InG, Gold); In, InG, Gold ideals; Gold given by Sagbi basis {g_1,...,g_t}, In given by tne initial forms In(g_1),...,In(g_t), InG = {h_1,...,h_s} a Sagbi basis of In RETURN: P_j, a polynomial in K[y_1,..,y_t] such that h_j = P_j(In(g_1),...,In_(g_t)) and return f_j = P_j(g_1,...,g_t) EXAMPLE: example Lift; shows an example " { int i; ideal J; for(i=1;i<=ncols(InG);i++) { poly f=InG[i]; list l=algebra_containment(f,In,1); def s=l[2]; map F=s,maxideal(1),Gold ; poly g=F(check); ideal k=g; J=J+k; kill g,l,s,F,f,k; } return(J); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),(a(2,0,3),lp); ideal In = xy+z2,x2y2; ideal InG=xy+z2,x2y2,xyz2+1/2z4; ideal Gold=xy+z2,y3+x2y2; Lift(In,InG,Gold); } ////////////////////////////////////////////////////////////////////////////// static proc Convert( ideal Gold ) "USAGE: Convert(I); I ideal RETURN: Convert old Sagbi basis into new Sagbi basis EXAMPLE: example Convert; shows an example " { ideal In=Initial(Gold); ideal InG=sagbi(In,1)+In; ideal Gnew=Lift(In,InG,Gold); return(Gnew); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),lp; ideal I=xy+z2, y3+x2y2; Convert(I); } ////////////////////////////////////////////////////////////////////////////// static proc interreduceSd(ideal I) "USAGE: interreduceSd(I); I ideal RETURN: interreduceSd the set of generators if I with respect to a given term ordering EXAMPLE: example interreduceSd; shows an example " { list l,M; ideal J,B; int i,j,k; poly f; for(k=1;k<=ncols(I);k++) {l[k]=I[k];} for(j=1;j<=size(l);j++) { f=l[j]; M=delete(l,j); for(i=1;i<=size(M);i++) { B[i]=M[i];} f=sagbiNF(f,B,1); J=J+f; } return(J); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),lp; ideal I = xy+z2,x2y2+y3; interreduceSd(I); } ////////////////////////////////////////////////////////////////////////////// static proc OrderStringalp(string Wpal,list #) { int n= nvars(basering); string order_str; intvec curr_weight, target_weight; curr_weight = system("Mivdp",n); target_weight = system("Mivlp",n); if(size(#) != 0) { if(size(#) == 1) { if(typeof(#[1]) == "intvec") { if(Wpal == "al"){ order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } else { order_str = "(Wp("+string(#[1])+"),C)"; } curr_weight = #[1]; } else { if(typeof(#[1]) == "string") { if(#[1] == "Dp") { order_str = "Dp"; } else { order_str = "dp"; } } else { order_str = "dp"; } } } else { if(size(#) == 2) { if(typeof(#[2]) == "intvec") { target_weight = #[2]; } if(typeof(#[1]) == "intvec") { if(Wpal == "al"){ order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } else { order_str = "(Wp("+string(#[1])+"),C)"; } curr_weight = #[1]; } else { if(typeof(#[1]) == "string") { if(#[1] == "Dp") { order_str = "Dp"; } else { order_str = "dp"; } } else { order_str = "dp"; } } } } } else { order_str = "dp"; } list result; result[1] = order_str; result[2] = curr_weight; result[3] = target_weight; return(result); } ////////////////////////////////////////////////////////////////////////////// static proc OrderStringalp_NP(string Wpal,list #) { int n= nvars(basering); string order_str = "dp"; int nP = 1;// call LatsGB to compute the wanted GB by pwalk intvec curr_weight = system("Mivdp",n); //define (1,1,...,1) intvec target_weight = system("Mivlp",n); //define (1,0,...,0) if(size(#) != 0) { if(size(#) == 1) { if(typeof(#[1]) == "intvec") { curr_weight = #[1]; if(Wpal == "al") { order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } else { order_str = "(Wp("+string(#[1])+"),C)"; } } else { if(typeof(#[1]) == "int") { nP = #[1]; } else { print("// ** the input must be \"(ideal, int)\" or "); print("// ** \"(ideal, intvec)\""); print("// ** a lex. GB will be computed from \"dp\" to \"lp\""); } } } else { if(size(#) == 2) { if(typeof(#[1]) == "intvec" and typeof(#[2]) == "int") { curr_weight = #[1]; if(Wpal == "al") { order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } else { order_str = "(Wp("+string(#[1])+"),C)"; } } else { if(typeof(#[1]) == "intvec" and typeof(#[2]) == "intvec") { curr_weight = #[1]; target_weight = #[2]; if(Wpal == "al") { order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } else { order_str = "(Wp("+string(#[1])+"),C)"; } } else { print("// ** the input must be \"(ideal,intvec,int)\" or "); print("// ** \"(ideal,intvec,intvec)\""); print("// ** and a lex. GB will be computed from \"dp\" to \"lp\""); } } } else { if(size(#) == 3) { if(typeof(#[1]) == "intvec" and typeof(#[2]) == "intvec" and typeof(#[3]) == "int") { curr_weight = #[1]; target_weight = #[2]; nP = #[3]; if(Wpal == "al") { order_str = "(a("+string(#[1])+"),lp("+string(n) + "),C)"; } else { order_str = "(Wp("+string(#[1])+"),C)"; } } else { print("// ** the input must be \"(ideal,intvec,intvec,int)\""); print("// ** and a lex. GB will be computed from \"dp\" to \"lp\""); } } else { print("// ** The given input is wrong"); print("// ** and a lex. GB will be computed from \"dp\" to \"lp\""); } } } } list result; result[1] = nP; result[2] = order_str; result[3] = curr_weight; result[4] = target_weight; return(result); } ////////////////////////////////////////////////////////////////////////////// static proc test_in_cone(vector w, list l) { int i,j,k; vector v; poly n; number a; for(i=1;i<=size(l);i++) { for(j=1;j<=size(l[i]);j++) { v=0; for(k=1;k<=size(l[i][j]);k++) { v=v+l[i][j][k]*gen(k); } n = inprod(w,v); a = leadcoef(n); if(a<0) { return(0); } } } return(1); } ////////////////////////////////////////////////////////////////////////////// static proc PertVectors(ideal Gold, vector target_weight, int pdeg) { int nV = nvars(basering); int nG = size(Gold); int i; number ntemp, maxAi, maxA; if(pdeg > nV || pdeg <= 0) { intvec v_null=0; return v_null; } if(pdeg == 1) { return target_weight; } maxAi=0; for(i=1; i<=nV; i++) { ntemp = leadcoef(inprod(target_weight,gen(i))); if(ntemp < 0) { ntemp = -ntemp; } if(maxAi < ntemp) { maxAi = ntemp; } } maxA = maxAi+pdeg-1; number epsilon = maxA*deg(Gold)+1; vector pert_weight = epsilon^(pdeg-1)*target_weight; for(i=2; i<=pdeg; i++) { pert_weight = pert_weight + epsilon^(pdeg-i)*gen(i); } return(pert_weight); } ////////////////////////////////////////////////////////////////////////////// static proc RandomNextWeight(ideal Gold, list L, vector curr_weight, vector target_weight,int weight_rad, int pdeg) "USAGE: RandomNextWeight(Gold, L, curr_weight, target_weight); RETURN: Intermediate next weight vector EXAMPLE: example RandomNextWeight; shows an example " { int i,n1,n2,n3; number norm, weight_norm; def Rold = basering; int nV = nvars(basering); number ulast=last(curr_weight, target_weight, L); vector new_weight=(1-ulast)*curr_weight+ulast*target_weight; vector w1=cleardenom(new_weight); intvec v1=changeType(w1); list p= ringlist(Rold); p[3][1][2]= v1; def new_ring=ring(p); setring new_ring; ideal Gold = fetch(Rold, Gold); n1=size(Initial(Gold)); setring Rold; intvec next_weight; kill new_ring; while(1) { weight_norm = 0; while(weight_norm == 0) { for(i=1; i<=nV; i++) { next_weight[i] = random(1,10000)-5000; weight_norm = weight_norm + next_weight[i]^2; } norm = 0; while(norm^2 < weight_norm) { norm=norm+1; } weight_norm = 1+norm; } new_weight = 0; for(i=1; i<=nV;i++) { if(next_weight[i] < 0) { new_weight = new_weight + (1 + round(weight_rad*leadcoef(next_weight[i])/weight_norm))*gen(i); } else { new_weight = new_weight + ( round(weight_rad*leadcoef(next_weight[i])/weight_norm))*gen(i); } } new_weight = new_weight + curr_weight; if(test_in_cone(new_weight, L)==1) { break; } } kill next_weight; kill norm; vector w2=cleardenom(new_weight); intvec v2=changeType(w2); p[3][1][2]= v2; def new_ring=ring(p); setring new_ring; ideal Gold = fetch(Rold, Gold); n2=size(Initial(Gold)); setring Rold; kill new_ring; vector w3=cleardenom(PertVectors(Gold,target_weight,pdeg)); intvec v3=changeType(w3); p[3][1][2]= v1; def new_ring=ring(p); setring new_ring; ideal Gold = fetch(Rold, Gold); n3=size(Initial(Gold)); setring Rold; kill new_ring; kill p; if(n2 var(sigma[i]), 1 <= i <= n. EXAMPLE: example genSymId; shows an example " { if(nvars(basering) != size(sigma)) { ERROR("The input is no permutation of the ring-variables!!"); } int i; ideal perm; for(i = 1; i <= size(sigma); i++) { perm[size(perm)+1] = var(sigma[i]); } map f = basering, perm; ideal J = I; ideal helpJ = I; for(i = 1; i <= order(sigma) - 1; i++) { helpJ = f(helpJ); J = J, helpJ; } return(simplify(simplify(J,4),2)); } example { "EXAMPLE:"; echo = 2; ring R = 0,(u,v,w,x,y),dp; intvec pi = 2,3,4,5,1; ideal I = u2v + x3y - w2; genSymId(I,pi); } //////////////////////////////////////////////////////////////////////////////// proc isSymmetric(ideal I, intvec sigma) "USAGE: isSymmetric(I,sigma); I ideal, sigma intvec ASSUME: size(sigma) = nvars(basering) =: n RETURN: 1, if the set of generators of I is invariant under sigma; @* 0, if the set of generators of I is not invariant under sigma NOTE: sigma is a permutation of the variables of the basering, i.e. @* sigma: var(i) ----> var(sigma[i]), 1 <= i <= n. EXAMPLE: example isSymmetric; shows an example " { if(nvars(basering) != size(sigma)) { ERROR("The input is no permutation of the ring-variables!!"); } int i, j; list L; for(i = 1; i <= size(I); i++) { L[size(L)+1] = I[i]; } ideal perm; for(i = 1; i <= size(sigma); i++) { perm[size(perm)+1] = var(sigma[i]); } map f = basering, perm; ideal J = f(I); poly g; while(size(L) > 0) { j = size(L); g = L[1]; for(i = 1; i <= size(J); i++) { if(g - J[i] == 0) { L = delete(L, 1); break; } } if(j == size(L)) { return(0); } } return(1); } example { "EXAMPLE:"; echo = 2; ring R = 0,x(1..5),dp; ideal I = cyclic(5); intvec pi = 2,3,4,5,1; isSymmetric(I,pi); intvec tau = 2,5,1,4,3; isSymmetric(I,tau); } //////////////////////////////////////////////////////////////////////////////// static proc permute(intvec v, intvec P) { // permute the intvec v according to the permutation given by P int s = size(v); int n = size(P); int i; if(s < n) { for(i = s+1; i <= n; i = i+1) { v[i] = 0; } s = size(v); } intvec auxv = v; for(i = 1; i <= n; i = i+1) { auxv[i] = v[P[i]]; } return(auxv); } //////////////////////////////////////////////////////////////////////////////// static proc order(intvec sigma) { // compute the order of sigma in Sym({1,...,n}) with n := size(sigma) int ORD = 1; intvec id = 1..size(sigma); intvec tau = sigma; while(tau != id) { tau = permute(tau, sigma); ORD = ORD + 1; } return(ORD); } //////////////////////////////////////////////////////////////////////////////// static proc modExpo(bigint x, bigint a, bigint n) { // compute x^a mod n bigint z = 1; while(a != 0) { while((a mod 2) == 0) { a = a div 2; x = x^2 mod n; } a = a - 1; z = (z*x) mod n; } return(z); } //////////////////////////////////////////////////////////////////////////////// proc primRoot(int p, int k) "USAGE: primRoot(p,k); p,k integers ASSUME: p is a prime and k divides p-1. RETURN: int: a k-th primitive root of unity in Z/pZ EXAMPLE: example primRoot; shows an example " { if(k == 2) { return(-1); } if(p == 0) { return(0); } int i, j; if(((p-1) mod k) != 0) { ERROR("There is no "+string(k)+"-th primitive root of unity " +"in Z/"+string(p)+"Z."); return(0); } list PF = primefactors(p-1)[1]; bigint a; for(i = 2; i <= p-1; i++) { a = i; for(j = 1; j <= size(PF); j++) { if(modExpo(a, (p-1) div PF[j], p) == 1) { break; } } if(j == size(PF)+1) { a = modExpo(a, (p-1) div k, p); string str = "int xi = "+string(a); execute(str); return(xi); } } } example { "EXAMPLE:"; echo = 2; primRoot(181,10); ring R = 2147482801, x, lp; number a = primRoot(2147482801,5); a; a^2; a^3; a^4; a^5; } //////////////////////////////////////////////////////////////////////////////// static proc permMat(intvec sigma, list #) { // compute an intmat such that i-th row describes sigma^i int i; int n = size(sigma); if(size(#) == 0) { int ORD = order(sigma); } else { int ORD = #[1]; } intmat P[ORD][n]; intvec sigmai = sigma; for(i = 1; i <= ORD; i++) { P[i,1..n] = sigmai; sigmai = permute(sigmai, sigma); } return(P); } //////////////////////////////////////////////////////////////////////////////// static proc genTransId(intvec sigma, list #) { // list L of two ideals such that // - L[1] describes the transformation and // - L[2] describes the retransformation (inverse mapping). // ORD is the order of sigma in Sym({1,...,n}) with n := size(sigma) and // sigma: {1,...,n} ---> {1,...,n}: sigma(j) = sigma[j]. Since sigma is a // permutation of variables it induces an automorphism phi of the // basering, more precisely a linear variable transformation which is // generated by this procedure. In terms it holds: // // phi : basering ---------> basering // var(i) |----> L[1][i] // L[2][i] <----| var(i) int n = nvars(basering); if(n != size(sigma)) { ERROR("The input is no permutation of the ring-variables!!"); } int i, j, k; if(size(#) == 0) { int CHAR = char(basering); int ORD = order(sigma); if((((CHAR - 1) mod ORD) != 0) && (CHAR > 0)) { ERROR("Basering of characteristic "+string(CHAR)+" has no " +string(ORD)+"-th primitive root of unity!!"); } if((CHAR == 0) && (ORD > 2)) { "======================================== ========================================"; "If basering really has a "+string(ORD)+"-th " +"primitive root of unity then insert it as input!!"; "======================================== ========================================"; return(list()); } else { int xi = primRoot(CHAR, ORD); number a = xi; } } else { int ORD = #[1]; number a = #[2]; } intmat PERM = permMat(sigma,ORD); ideal TR, RETR; poly s_trans; matrix C; //-------------- retransformation ideal RETR is generated here ----------------- for(i = 1; i <= n; i++) { for(j = 0; j < ORD; j++) { for(k = 1; k <= ORD; k++) { // for each variable var(i): // s_trans^(j) = sum_{k=1}^{ORD} a^(k*j)*sigma^k(var(i)) // for j = 0,...,ORD-1 s_trans = s_trans + a^(k*j)*var(PERM[k,i]); } RETR = RETR + simplify(s_trans, 1); s_trans = 0; } } //---------------- transformation ideal TR is generated here ------------------- for(i = 1; i <= n; i++) { for(j = 1; j <= size(RETR); j++) { C = coeffs(RETR[j], var(i)); if(nrows(C) > 1) { // var(j) = RETR[j] = sum_{i in J} c_ij*var(i), J subset {1,...,n}, // and therefore var(i) = (sum_{j} s(j)/c_ij)/#(summands) s_trans = s_trans + var(j)/(C[nrows(C),1]); } } TR = TR + s_trans/number(size(s_trans)); s_trans = 0; } return(list(TR,RETR)); } //////////////////////////////////////////////////////////////////////////////// proc eigenvalues(ideal I, intvec sigma) "USAGE: eigenvalues(I,sigma); I ideal, sigma intvec ASSUME: size(sigma) = nvars(basering) =: n RETURN: list of eigenvalues of generators of I under permutation sigma NOTE: sigma is a permutation of the variables of the basering, i.e. sigma: var(i) ----> var(sigma[i]), 1 <= i <= n. EXAMPLE: example eigenvalues; shows an example " { int i, j; def A = basering; int n = nvars(A); poly ev; list EV; poly s, help_var; matrix C1, C2; ideal perm; for(i = 1; i <= n; i++) { perm[size(perm)+1] = var(sigma[i]); } map f = A, perm; for(i = 1; i <= size(I); i++) { //-------------- s is the image of I[i] under permutation sigma ---------------- s = I[i]; s = f(s); for(j = 1; j <= n; j++) { C1 = coeffs(I[i], var(j)); C2 = coeffs(s, var(j)); if(nrows(C1) > 1) { ev = C2[nrows(C2),1]/C1[nrows(C1),1]; //------ Furthermore check that I[i] is eigenvector of permutation sigma. ------ if(s == ev*I[i]) { break; } else { ERROR("I["+string(i)+"] is no eigenvector " +"of permutation sigma!!"); } } } EV[size(EV)+1] = ev; } return(EV); } example { "EXAMPLE:"; echo = 2; ring R = 11, x(1..5), dp; poly p1 = x(1)+x(2)+x(3)+x(4)+x(5); poly p2 = x(1)+4*x(2)+5*x(3)-2*x(4)+3*x(5); poly p3 = x(1)+5*x(2)+3*x(3)+4*x(4)-2*x(5); poly p4 = x(1)-2*x(2)+4*x(3)+3*x(4)+5*x(5); poly p5 = x(1)+3*x(2)-2*x(3)+5*x(4)+4*x(5); ideal I = p1,p2,p3,p4,p5; intvec tau = 2,3,4,5,1; eigenvalues(I,tau); } //////////////////////////////////////////////////////////////////////////////// proc symmStd(ideal I, intvec sigma, list #) "USAGE: symmStd(I,sigma,#); I ideal, sigma intvec ASSUME: size(sigma) = nvars(basering) =: n, basering has an order(sigma)-th primitive root of unity a (if char(basering) > 0) and sigma(I) = I RETURN: ideal, a standard basis of I NOTE: Assuming that the ideal I is invariant under the variable permutation sigma and the basering has an order(sigma)-th primitive root of unity the procedure uses linear transformation of variables in order to improve standard basis computation. If char(basering) = 0 all computations are done in the polynomial ring over the smallest field extension that has an order(sigma)-th primitive root of unity. EXAMPLE: example symmStd; shows an example " { if((nvars(basering) != size(sigma)) || (!isSymmetric(I,sigma))) { ERROR("The input is no permutation of the ring-variables!!"); } option(redSB); def R = basering; int CHAR = char(R); int n = nvars(R); int t; //-------- (1) Compute the order of variable permutation sigma. ---------------- int ORD = order(sigma); if((((CHAR - 1) mod ORD) != 0) && (CHAR > 0)) { ERROR("Basering of characteristic "+string(CHAR)+" has no " +string(ORD)+"-th primitive root of unity!!"); } //-------- (2) Compute the order(sigma)-th primitive root of unity ------------- //-------- in basering or move to ring extension. ------------- if((CHAR == 0) && (ORD > 2)) { def save_ring=basering; ring ext_ring=0,p,lp; def S = changechar(ringlist(ext_ring),save_ring); setring S; kill ext_ring; kill save_ring; minpoly = rootofUnity(ORD); ideal I = imap(R, I); number a = p; } else { int xi = primRoot(CHAR, ORD); number a = xi; } //--------- (3) Define the linear transformation of variables with ------------- //--------- respect to sigma. ------------- list L = genTransId(sigma,ORD,a); ideal TR = L[1]; ideal RETR = L[2]; //--------- (4) Compute the eigenvalues of the "new" variables of -------------- //--------- sigma after transformation. -------------- list EV = eigenvalues(RETR, sigma); //--------- (5) Transformation of the input-ideal is done here. ---------------- map f = basering, TR; t = timer; ideal I_trans = f(I); if(printlevel >= 11) { "Transformation: "+string(timer - t)+" seconds"; } //--------- (6) Compute a standard basis of the transformed ideal. ------------- t = timer; if(size(#) > 0) { ideal sI_trans = std(I_trans, #[1]); } else { ideal sI_trans = std(I_trans); } if(printlevel >= 11) { "1st Groebner basis: "+string(timer - t)+" seconds"; } //--------- (7) Retransformation is done here. --------------------------------- map g = basering, RETR; t = timer; ideal I_retrans = g(sI_trans); if(printlevel >= 11) { "Reverse Transformation: "+string(timer - t) +" seconds"; } //--------- (8) Compute a standard basis of the retransformaed ideal ----------- //--------- which is then a standard basis of the input-ideal. ----------- t = timer; ideal sI_retrans = std(I_retrans); if(printlevel >= 11) { "2nd Groebner basis: "+string(timer - t)+" seconds"; } if((CHAR == 0) && (ORD > 2)) { setring R; ideal sI_retrans = fetch(S, sI_retrans); return(sI_retrans); } else { return(sI_retrans); } } example { "EXAMPLE:"; echo = 2; ring R = 0, x(1..4), dp; ideal I = cyclic(4); I; intvec pi = 2,3,4,1; ideal sI = symmStd(I,pi); sI; ring S = 31, (x,y,z), dp; ideal J; J[1] = xy-y2+xz; J[2] = xy+yz-z2; J[3] = -x2+xz+yz; intvec tau = 3,1,2; ideal sJ = symmStd(J,tau); sJ; } //////////////////////////////////////////////////////////////////////////////// proc divPrimeTest(def II, bigint p, int k) { if((p - 1) mod k != 0) { return(0); } if(typeof(II) == "string") { execute("ideal I = "+II+";"); } else { ideal I = II; } int i,j; poly f; number cnt; for(i = 1; i <= size(I); i++) { f = cleardenom(I[i]); if(f == 0) { return(0); } cnt = leadcoef(I[i])/leadcoef(f); if((bigint(numerator(cnt)) mod p) == 0) { return(0); } if((bigint(denominator(cnt)) mod p) == 0) { return(0); } for(j = size(f); j > 0; j--) { if((bigint(leadcoef(f[j])) mod p) == 0) { return(0); } } } return(1); } //////////////////////////////////////////////////////////////////////////////// proc divPrimeList(int k, ideal I, int n, list #) { // the intvec of n greatest primes p <= 2147483647 (resp. n greatest primes // < L[size(L)] union with L) such that each (p-1) is divisible by k, and none // of these primes divides any coefficient occuring in I // --> similar to procedure primeList in modstd.lib intvec L; int i,p; int ncores = 1; //----------------- Initialize optional parameter ncores --------------------- if(size(#) > 0) { if(size(#) == 1) { if(typeof(#[1]) == "int") { ncores = #[1]; # = list(); } } else { ncores = #[2]; } } if(size(#) == 0) { p = 2147483647; while(!divPrimeTest(I,p,k)) { p = prime(p-1); if(p == 2) { ERROR("No more primes."); } } L[1] = p; } else { L = #[1]; p = prime(L[size(L)]-1); while(!divPrimeTest(I,p,k)) { p = prime(p-1); if(p == 2) { ERROR("No more primes."); } } L[size(L)+1] = p; } if(p == 2) { ERROR("No more primes."); } if(ncores == 1) { for(i = 2; i <= n; i++) { p = prime(p-1); while(!divPrimeTest(I,p,k)) { p = prime(p-1); if(p == 2) { ERROR("no more primes"); } } L[size(L)+1] = p; } } else { int neededSize = size(L)+n-1;; list parallelResults; list arguments; int neededPrimes = neededSize-size(L); while(neededPrimes > 0) { arguments = list(); for(i = ((neededPrimes div ncores)+1-(neededPrimes%ncores == 0)) *ncores; i > 0; i--) { p = prime(p-1); if(p == 2) { ERROR("no more primes"); } arguments[i] = list("I", p, k); } parallelResults = parallelWaitAll("divPrimeTest", arguments, 0, ncores); for(i = size(arguments); i > 0; i--) { if(parallelResults[i]) { L[size(L)+1] = arguments[i][2]; } } neededPrimes = neededSize-size(L); } if(size(L) > neededSize) { L = L[1..neededSize]; } } return(L); } example { "EXAMPLE:"; echo = 2; ring r = 0,(x,y,z),dp; ideal I = 2147483647x+y, z-181; intvec L = divPrimeList(4,I,10,10); size(L); L[1]; L[size(L)]; L = divPrimeList(4,I,5,L,5); size(L); L[size(L)]; } //////////////////////////////////////////////////////////////////////////////// proc spTestSB(ideal I, ideal J, list L, intvec sigma, int variant, list #) "USAGE: spTestSB(I,J,L,sigma,variant,#); I,J ideals, L intvec of primes, sigma intvec, variant integer RETURN: 1 (resp. 0) if for a randomly chosen prime p, that is not in L and divisible by the order of sigma, J mod p is (resp. is not) a standard basis of I mod p EXAMPLE: example spTestSB; shows an example " { int i,j,k,p; int ORD = order(sigma); def R = basering; list r = ringlist(R); while(!j) { j = 1; while(((p - 1) mod ORD) != 0) { p = prime(random(1000000000,2134567879)); if(p == 2){ ERROR("no more primes"); } } for(i = 1; i <= size(L); i++) { if(p == L[i]){ j = 0; break } } if(j) { for(i = 1; i <= ncols(I); i++) { for(k = 2; k <= size(I[i]); k++) { if((bigint(denominator(leadcoef(I[i][k]))) mod p) == 0){ j = 0; break; } } if(!j){ break; } } } if(j) { if(!primeTest(I,p)) { j = 0; } } } r[1] = p; def @R = ring(r); setring @R; ideal I = imap(R,I); ideal J = imap(R,J); attrib(J,"isSB",1); int t = timer; j = 1; if(isIncluded(I,J) == 0){ j = 0; } if(printlevel >= 11) { "isIncluded(I,J) takes "+string(timer - t)+" seconds"; "j = "+string(j); } t = timer; if(j) { if(size(#) > 0) { ideal K = smpStd(I,sigma,p,variant,#[1])[1]; } else { ideal K = smpStd(I,sigma,p,variant)[1]; } t = timer; if(isIncluded(J,K) == 0){ j = 0; } if(printlevel >= 11) { "isIncluded(J,K) takes "+string(timer - t)+" seconds"; "j = "+string(j); } } setring R; return(j); } example { "EXAMPLE:"; echo = 2; intvec L = 2,3,5; ring r = 0,(x,y,z),dp; ideal I = x+1,y+1; intvec sigma = 2,1,3; ideal J = x+1,y; spTestSB(I,J,L,sigma,2); spTestSB(J,I,L,sigma,2); } //////////////////////////////////////////////////////////////////////////////// proc smpStd(ideal I, intvec sigma, int p, int variant, list #) "USAGE: smpStd(I,sigma,p,#); I ideal, sigma intvec, p integer, variant integer ASSUME: If size(#) > 0, then #[1] is an intvec describing the Hilbert series. RETURN: ideal - a standard basis of I mod p, integer - p NOTE: The procedure computes a standard basis of the ideal I modulo p and fetches the result to the basering. If size(#) > 0 the Hilbert driven standard basis computation symmStd(.,.,#[1]) is used in symmStd. The standard basis computation modulo p does also vary depending on the integer variant, namely @* - variant = 1: symmStd(.,.,#[1]) resp. symmStd, @* - variant = 2: symmStd, @* - variant = 3: homog. - symmStd(.,.,#[1]) resp. symmStd - dehomog., @* - variant = 4: fglm. EXAMPLE: example smpStd; shows an example " { def R0 = basering; list rl = ringlist(R0); rl[1] = p; def @r = ring(rl); setring @r; ideal i = fetch(R0,I); option(redSB); if(variant == 1) { if(size(#) > 0) { i = symmStd(i, sigma, #[1]); } else { i = symmStd(i, sigma); } } if(variant == 2) { i = symmStd(i, sigma); } if(variant == 3) { list rl = ringlist(@r); int nvar@r = nvars(@r); int k; intvec w; for(k = 1; k <= nvar@r; k++) { w[k] = deg(var(k)); } w[nvar@r + 1] = 1; rl[2][nvar@r + 1] = "homvar"; rl[3][2][2] = w; def HomR = ring(rl); setring HomR; ideal i = imap(@r, i); i = homog(i, homvar); intvec tau = sigma, size(sigma)+1; if(size(#) > 0) { if(w == 1) { i = symmStd(i, tau, #[1]); } else { i = symmStd(i, tau, #[1], w); } } else { i = symmStd(i, tau); } i = subst(i, homvar, 1); i = simplify(i, 34); setring @r; i = imap(HomR, i); i = interred(i); kill HomR; } if(variant == 4) { def R1 = changeord(list(list("dp",1:nvars(basering)))); setring R1; ideal i = fetch(@r,i); i = symmStd(i, sigma); setring @r; i = fglm(R1,i); } setring R0; return(list(fetch(@r,i),p)); } example { "EXAMPLE:"; echo = 2; ring r1 = 0, x(1..4), dp; ideal I = cyclic(4); intvec sigma = 2,3,4,1; int p = 181; list P = smpStd(I,sigma,p,2); P; ring r2 = 0, x(1..5), lp; ideal I = cyclic(5); intvec tau = 2,3,4,5,1; int q = 31981; list Q = smpStd(I,tau,q,4); Q; } //////////////////////////////////////////////////////////////////////////////// proc syModStd(ideal I, intvec sigma, list #) "USAGE: syModStd(I,sigma); I ideal, sigma intvec ASSUME: size(sigma) = nvars(basering) and sigma(I) = I. If size(#) > 0, then # contains either 1, 2 or 4 integers such that @* - #[1] is the number of available processors for the computation, @* - #[2] is an optional parameter for the exactness of the computation, if #[2] = 1, the procedure computes a standard basis for sure, @* - #[3] is the number of primes until the first lifting, @* - #[4] is the constant number of primes between two liftings until the computation stops. RETURN: ideal, a standard basis of I if no warning appears; NOTE: The procedure computes a standard basis of the ideal I (over the rational numbers) by using modular methods and the fact that I is invariant under the variable permutation sigma. By default the procedure computes a standard basis of I for sure, but if the optional parameter #[2] = 0, it computes a standard basis of I with high probability. The procedure distinguishes between different variants for the standard basis computation in positive characteristic depending on the ordering of the basering, the parameter #[2] and if the ideal I is homogeneous. @* - variant = 1, if I is homogeneous, @* - variant = 2, if I is not homogeneous, 1-block-ordering, @* - variant = 3, if I is not homogeneous, complicated ordering (lp or > 1 block), @* - variant = 4, if I is not homogeneous, ordering lp, dim(I) = 0. EXAMPLE: example syModStd; shows an example " { if((nvars(basering) != size(sigma)) || (!isSymmetric(I,sigma))) { ERROR("The input is no permutation of the ring-variables!!"); } int TT = timer; int RT = rtimer; def R0 = basering; list rl = ringlist(R0); if((npars(R0) > 0) || (rl[1] > 0)) { ERROR("Characteristic of basering should be zero, basering should have no parameters."); } int index = 1; int i,k,c; int j = 1; int pTest, sizeTest; int en = 2134567879; int an = 1000000000; bigint N; int ORD = order(sigma); //-------------------- Initialize optional parameters ------------------------ if(size(#) > 0) { if(size(#) == 1) { int n1 = #[1]; int exactness = 1; if(n1 >= 10) { int n2 = n1 + 1; int n3 = n1; } else { int n2 = 10; int n3 = 10; } } if(size(#) == 2) { int n1 = #[1]; int exactness = #[2]; if(n1 >= 10) { int n2 = n1 + 1; int n3 = n1; } else { int n2 = 10; int n3 = 10; } } if(size(#) == 4) { int n1 = #[1]; int exactness = #[2]; if(n1 >= #[3]) { int n2 = n1 + 1; } else { int n2 = #[3]; } if(n1 >= #[4]) { int n3 = n1; } else { int n3 = #[4]; } } } else { int n1 = 1; int exactness = 1; int n2 = 10; int n3 = 10; } if(printlevel >= 10) { "n1 = "+string(n1)+", n2 = "+string(n2)+", n3 = "+string(n3) +", exactness = "+string(exactness); } //-------------------------- Save current options ------------------------------ intvec opt = option(get); option(redSB); //-------------------- Initialize the list of primes ------------------------- int tt = timer; int rt = rtimer; intvec L = divPrimeList(ORD,I,n2,n1); if(printlevel >= 10) { "CPU-time for divPrimeList: "+string(timer-tt)+" seconds."; "Real-time for divPrimeList: "+string(rtimer-rt)+" seconds."; } //--------------------- Decide which variant to take ------------------------- int variant; int h = homog(I); tt = timer; rt = rtimer; if(!hasMixedOrdering()) { if(h) { variant = 1; if(printlevel >= 10) { "variant = 1"; } rl[1] = L[5]; def @r = ring(rl); setring @r; def @s = changeord(list(list("dp",1:nvars(basering)))); setring @s; ideal I = std(fetch(R0,I)); intvec hi = hilb(I,1); setring R0; kill @r,@s; } else { string ordstr_R0 = ordstr(R0); int neg = 1 - attrib(R0,"global"); if((find(ordstr_R0, "M") > 0) || (find(ordstr_R0, "a") > 0) || neg) { variant = 2; if(printlevel >= 10) { "variant = 2"; } } else { string order; if(system("nblocks") <= 2) { if(find(ordstr_R0, "M") + find(ordstr_R0, "lp") + find(ordstr_R0, "rp") <= 0) { order = "simple"; } } if((order == "simple") || (size(rl) > 4)) { variant = 2; if(printlevel >= 10) { "variant = 2"; } } else { rl[1] = L[5]; def @r = ring(rl); setring @r; def @s = changeord(list(list("dp",1:nvars(basering)))); setring @s; ideal I = std(fetch(R0,I)); if(dim(I) == 0) { variant = 4; if(printlevel >= 10) { "variant = 4"; } } else { variant = 3; if(printlevel >= 10) { "variant = 3"; } int nvar@r = nvars(@r); intvec w; for(i = 1; i <= nvar@r; i++) { w[i] = deg(var(i)); } w[nvar@r + 1] = 1; list hiRi = hilbRing(fetch(R0,I),w); intvec W = hiRi[2]; @s = hiRi[1]; setring @s; intvec tau = sigma, size(sigma)+1; Id(1) = symmStd(Id(1),tau); intvec hi = hilb(Id(1), 1, W); } setring R0; kill @r,@s; } } } } else { if(exactness == 1) { return(groebner(I)); } if(h) { variant = 1; if(printlevel >= 10) { "variant = 1"; } rl[1] = L[5]; def @r = ring(rl); setring @r; def @s = changeord(list(list("dp",1:nvars(basering)))); setring @s; ideal I = std(fetch(R0,I)); intvec hi = hilb(I,1); setring R0; kill @r,@s; } else { string ordstr_R0 = ordstr(R0); int neg = 1 - attrib(R0,"global"); if((find(ordstr_R0, "M") > 0) || (find(ordstr_R0, "a") > 0) || neg) { variant = 2; if(printlevel >= 10) { "variant = 2"; } } else { string order; if(system("nblocks") <= 2) { if(find(ordstr_R0, "M") + find(ordstr_R0, "lp") + find(ordstr_R0, "rp") <= 0) { order = "simple"; } } if((order == "simple") || (size(rl) > 4)) { variant = 2; if(printlevel >= 10) { "variant = 2"; } } else { variant = 3; if(printlevel >= 10) { "variant = 3"; } rl[1] = L[5]; def @r = ring(rl); setring @r; int nvar@r = nvars(@r); intvec w; for(i = 1; i <= nvar@r; i++) { w[i] = deg(var(i)); } w[nvar@r + 1] = 1; list hiRi = hilbRing(fetch(R0,I),w); intvec W = hiRi[2]; def @s = hiRi[1]; setring @s; intvec tau = sigma, size(sigma)+1; Id(1) = symmStd(Id(1),tau); intvec hi = hilb(Id(1), 1, W); setring R0; kill @r,@s; } } } } list P,T1,T2,T3,LL; ideal J,K,H; //----- If there is more than one processor available, we parallelize the ---- //----- main standard basis computations in positive characteristic ---- if(n1 > 1) { ideal I_for_fork = I; export(I_for_fork); // I available for each link //----- Create n1 links l(1),...,l(n1), open all of them and compute --------- //----- standard basis for the primes L[2],...,L[n1 + 1]. --------- for(i = 1; i <= n1; i++) { //link l(i) = "MPtcp:fork"; link l(i) = "ssi:fork"; open(l(i)); if((variant == 1) || (variant == 3)) { write(l(i), quote(smpStd(I_for_fork, eval(sigma), eval(L[i + 1]), eval(variant), eval(hi)))); } if((variant == 2) || (variant == 4)) { write(l(i), quote(smpStd(I_for_fork, eval(sigma), eval(L[i + 1]), eval(variant)))); } } int t = timer; if((variant == 1) || (variant == 3)) { P = smpStd(I_for_fork, sigma, L[1], variant, hi); } if((variant == 2) || (variant == 4)) { P = smpStd(I_for_fork, sigma, L[1], variant); } t = timer - t; if(t > 60) { t = 60; } int i_sleep = system("sh", "sleep "+string(t)); T1[1] = P[1]; T2[1] = bigint(P[2]); index++; j = j + n1 + 1; } //-------------- Main standard basis computations in positive ---------------- //---------------------- characteristic start here --------------------------- list arguments_farey, results_farey; while(1) { tt = timer; rt = rtimer; if(printlevel >= 10) { "size(L) = "+string(size(L)); } if(n1 > 1) { while(j <= size(L) + 1) { for(i = 1; i <= n1; i++) { //--- ask if link l(i) is ready otherwise sleep for t seconds --- if(status(l(i), "read", "ready")) { //--- read the result from l(i) --- P = read(l(i)); T1[index] = P[1]; T2[index] = bigint(P[2]); index++; if(j <= size(L)) { if((variant == 1) || (variant == 3)) { write(l(i), quote(smpStd(I_for_fork, eval(sigma), eval(L[j]), eval(variant), eval(hi)))); j++; } if((variant == 2) || (variant == 4)) { write(l(i), quote(smpStd(I_for_fork, eval(sigma), eval(L[j]), eval(variant)))); j++; } } else { k++; close(l(i)); } } } //--- k describes the number of closed links --- if(k == n1) { j++; } i_sleep = system("sh", "sleep "+string(t)); } } else { while(j <= size(L)) { if((variant == 1) || (variant == 3)) { P = smpStd(I, sigma, L[j], variant, hi); } if((variant == 2) || (variant == 4)) { P = smpStd(I, sigma, L[j], variant); } T1[index] = P[1]; T2[index] = bigint(P[2]); index++; j++; } } if(printlevel >= 10) { "CPU-time for computing list is "+string(timer - tt)+" seconds."; "Real-time for computing list is "+string(rtimer - rt)+" seconds."; } //------------------------ Delete unlucky primes ----------------------------- //------------- unlucky if and only if the leading ideal is wrong ------------ LL = deleteUnluckyPrimes(T1,T2,h); T1 = LL[1]; T2 = LL[2]; //------------------- Now all leading ideals are the same -------------------- //------------------- Lift results to basering via farey --------------------- tt = timer; rt = rtimer; N = T2[1]; for(i = 2; i <= size(T2); i++) { N = N*T2[i]; } H = chinrem(T1,T2); if(n1 == 1) { J = farey(H,N); } else { for(i = ncols(H); i > 0; i--) { arguments_farey[i] = list(ideal(H[i]), N); } results_farey = parallelWaitAll("farey", arguments_farey, 0, n1); for(i = ncols(H); i > 0; i--) { J[i] = results_farey[i][1]; } } if(printlevel >= 10) { "CPU-time for lifting-process is "+string(timer - tt)+" seconds."; "Real-time for lifting-process is "+string(rtimer - rt)+" seconds."; } //---------------- Test if we already have a standard basis of I -------------- tt = timer; rt = rtimer; if((variant == 1) || (variant == 3)) { pTest = spTestSB(I,J,L,sigma,variant,hi); } if((variant == 2) || (variant == 4)) { pTest = spTestSB(I,J,L,sigma,variant); } if(printlevel >= 10) { "CPU-time for pTest is "+string(timer - tt)+" seconds."; "Real-time for pTest is "+string(rtimer - rt)+" seconds."; } if(pTest) { if(printlevel >= 10) { "CPU-time for computation without final tests is " +string(timer - TT)+" seconds."; "Real-time for computation without final tests is " +string(rtimer - RT)+" seconds."; } attrib(J,"isSB",1); if(exactness == 0) { option(set, opt); if(n1 > 1) { kill I_for_fork; } return(J); } if(exactness == 1) { tt = timer; rt = rtimer; sizeTest = 1 - isIncluded(I,J,n1); if(printlevel >= 10) { "CPU-time for checking if I subset is " +string(timer - tt)+" seconds."; "Real-time for checking if I subset is " +string(rtimer - rt)+" seconds."; } if(sizeTest == 0) { tt = timer; rt = rtimer; K = std(J); if(printlevel >= 10) { "CPU-time for last std-computation is " +string(timer - tt)+" seconds."; "Real-time for last std-computation is " +string(rtimer - rt)+" seconds."; } if(size(reduce(K,J)) == 0) { option(set, opt); if(n1 > 1) { kill I_for_fork; } return(J); } } } } //-------------- We do not already have a standard basis of I ---------------- //----------- Therefore do the main computation for more primes -------------- T1 = H; T2 = N; index = 2; j = size(L) + 1; tt = timer; rt = rtimer; L = divPrimeList(ORD,I,n3,L,n1); if(printlevel >= 10) { "CPU-time for divPrimeList: "+string(timer-tt)+" seconds."; "Real-time for divPrimeList: "+string(rtimer-rt)+" seconds."; } if(n1 > 1) { for(i = 1; i <= n1; i++) { open(l(i)); if((variant == 1) || (variant == 3)) { write(l(i), quote(smpStd(I_for_fork, eval(sigma), eval(L[j+i-1]), eval(variant), eval(hi)))); } if((variant == 2) || (variant == 4)) { write(l(i), quote(smpStd(I_for_fork, eval(sigma), eval(L[j+i-1]), eval(variant)))); } } j = j + n1; k = 0; } } } example { "EXAMPLE:"; echo = 2; ring R1 = 0, (x,y,z), dp; ideal I; I[1] = -2xyz4+xz5+xz; I[2] = -2xyz4+yz5+yz; intvec sigma = 2,1,3; ideal sI = syModStd(I,sigma); sI; ring R2 = 0, x(1..4), dp; ideal I = cyclic(4); I; intvec pi = 2,3,4,1; ideal sJ1 = syModStd(I,pi,1); ideal sJ2 = syModStd(I,pi,1,0); size(reduce(sJ1,sJ2)); size(reduce(sJ2,sJ1)); } singular-4.0.3+ds/Singular/LIB/tasks.lib000066400000000000000000001251041266270727000177670ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////// version="version tasks.lib 4.0.0.0 Dec_2013 "; // $Id: 9c9ecb6bd816d6b914cdf4a7a223d8aa98905ed0 $ category="General purpose"; info=" LIBRARY: tasks.lib A parallel framework based on tasks AUTHOR: Andreas Steenpass, e-mail: steenpass@mathematik.uni-kl.de OVERVIEW: This library provides a parallel framework based on tasks. It introduces a new Singular type @code{task}; an object of this type is a command (given by a string) applied to a list of arguments. Tasks can be computed in parallel via the procedures in this library and they can even be started recursively, i.e. from within other tasks. tasks.lib respects the limits for computational resources defined in @ref{resources_lib}, i.e., all tasks within the same Singular session will not use more computational resources than provided via resources.lib, even if tasks are started recursively. The Singular library @ref{parallel_lib} provides implementations of several parallel 'skeletons' based on tasks.lib. KEYWORDS: parallelization; distributed computing; task SEE ALSO: resources_lib, parallel_lib PROCEDURES: createTask(); create a task killTask(); kill a task copyTask(); copy a task compareTasks(); compare two tasks printTask(); print a task startTasks(); start tasks stopTask(); stop a task waitTasks(); wait for a certain number of tasks waitAllTasks(); wait for all tasks pollTask(); poll a task getCommand(); get the command of a task getArguments(); get the arguments of a task getResult(); get the result of a task getState(); get the state of a task "; /* RATIONALE FOR DEVELOPERS The Singular type 'task' ------------------------ tasks.lib introduces a Singular type 'task' which makes use of a pointer-like model in order to avoid unnecessary copying of data. 'task' is defined as a newstruct whose only member is 'int index'. This index points to an entry in the lib-internal list 'tasks'. The elements of this list are of the type 'internal_task' which is defined as a newstruct with the following members: int id - the internal ID string command - the command list arguments - the arguments def result - the result string state - the current state, see 'The life cycle of a task' list links - control handles, see 'Links' int linkID - the ID of the control handles The life cycle of a task ------------------------ 'uninitialized' --> 'created' --> 'started' --> 'completed' | ^ v | 'stopped' The state of a task t is 'uninitialized' iff (t.index == 0) or (typeof(tasks[t.index]) != "internal_task"). A task can be reset to 'uninitialized' by killTask() at any time. Assigned members for 'internal_task' ------------------------------------ For each state, the following members of an internal_task must be assigned: created: command arguments state started: id command arguments state links linkID stopped: command arguments state completed: command arguments result state All other members should be wiped out. Local supervisors ----------------- A call of 'startTasks(t(1..n));' for tasks t(1), ..., t(n) creates a child process which plays the role of a supervisor for these tasks. The computation of the tasks is done in child processes of the supervisor. The supervisor assigns an internal state to each task which is represented by an integer. The meaning of these integers and their relation to the global state of each task is as follows: internal state | meaning | corresponding global state ---------------|-------------------|--------------------------- 0 | waiting | started 1 | started | started 2 | (result) computed | started 3 | (result) sent | completed -1 | stopped | stopped Links ----- The ssi link between the main process and the supervisor is named 'l(pid)' where pid is the PID of the main process. The links between the supervisor and its child processes are named 'll(pid)(1)', 'll(pid)(2)', ... where pid is the PID of the supervisor. The link between the child processes of the supervisor and the main process is named 'L(pid)' where pid is the PID of the main process. This link is only for sending the results to the main process and must not be used in the other direction! For any task t whose state is 'started', tasks[t.index].links is list(L(pid), l(pid)) where pid is the PID of the main process. Communication model ------------------- stopTask() <--> supervisor 0, id --> waitTasks() <--> supervisor (demanded_task is an intvec containing the IDs of the tasks which are being waited for; ndemanded is the number of tasks that is being waited for.) 1, demanded_tasks, ndemanded --> [receiving results] 1, 0:2, -1 --> results_sent <-- [receiving remaining results] pollTask() <--> supervisor 2, id --> state <-- [receive result if state == 2 (computed)] startTasks_child() <--> startTasks_grandchild() [compute the result] 1, id <-- [wait until the result is requested] 1 --> [send the result] 2 <-- sending and receiving results: main process <--> supervisor <--> startTasks_grandchild() [request the result, see above] index, result (main process <-- startTasks_grandchild()) 3, id (main process --> supervisor) */ LIB "resources.lib"; static proc mod_init() { /* initialize the semaphores */ if (!defined(Resources)) { LIB "resources.lib"; } // the number of processor cores int sem_cores = Resources::sem_cores; exportto(Tasks, sem_cores); // the number of leaves in the parallel tree (not strict) int sem_leaves = semaphore(system("--cpus")+10); exportto(Tasks, sem_leaves); // the number of processes waiting for sem_cores with low priority int sem_queue = semaphore(2); exportto(Tasks, sem_queue); /* define the Singular type 'task' */ newstruct("task", "int index"); newstruct("internal_task", "int id, string command, list arguments," +"def result, string state, list links, int linkID"); system("install", "task", "=", createTask, 1); system("install", "task", "==", compareTasks, 2); system("install", "task", "print", printTask, 1); /* define (lib-)global variables */ list tasks; // the lib-internal list of tasks exportto(Tasks, tasks); int ntasks; // the current maximal index in 'tasks' exportto(Tasks, ntasks); int nlinkIDs; // the current maximal linkID exportto(Tasks, nlinkIDs); } proc createTask(alias string command, alias list arguments) "USAGE: createTask(command, arguments), command string, arguments list RETURN: a task with the given command and arguments whose state is 'created'. NOTE: 't = command, arguments;' is a shortcut for 't = createTask(command, arguments);'. SEE ALSO: startTasks, getCommand, getArguments, getState, killTask, copyTask, compareTasks, printTask EXAMPLE: example createTask; shows an example" { internal_task T; ntasks++; tasks[ntasks] = T; tasks[ntasks].command = command; tasks[ntasks].arguments = arguments; tasks[ntasks].state = "created"; task t; t.index = ntasks; return(t); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t = createTask("std", list(I)); // This is the same as: // task t = "std", list(I); t; killTask(t); } proc killTask(task t) "USAGE: killTask(t), t task RETURN: nothing. If the state of t is 'started', then t is stopped first. The internal data structures of t are erased and its state is set to 'uninitialized'. NOTE: 'killTask(t);' is not the same as 'kill t;'. The latter command does not erase the internal data structures of t. Hence killTask() should be called for any no longer needed task in order to free memory. SEE ALSO: stopTask, getState, createTask, printTask EXAMPLE: example killTask; shows an example" { if (t.index == 0) { return(); } if (typeof(tasks[t.index]) != "internal_task") { return(); } if (tasks[t.index].state == "started") { stopTask(t); } tasks[t.index] = def(0); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t = "std", list(I); startTasks(t); t; killTask(t); t; getState(t); } proc copyTask(task t) "USAGE: copyTask(t), t task RETURN: a copy of t. NOTE: 'task t1 = copyTask(t2);' is not the same as 'task t1 = t2;'. After the latter command, t1 points to the same object as t2; any changes to t2 will also effect t1. In contrast to this, copyTask() creates a new independend task. @* A task whose state is 'started' cannot be copied. SEE ALSO: getCommand, getArguments, getResult, getState, createTask, killTask, compareTasks, printTask EXAMPLE: example copyTask; shows an example" { task t_copy; if (t.index == 0) { return(t_copy); } if (typeof(tasks[t.index]) != "internal_task") { return(t_copy); } if (tasks[t.index].state == "started") { ERROR("cannot copy a task whose state is 'started'"); } ntasks++; tasks[ntasks] = tasks[t.index]; t_copy.index = ntasks; return(t_copy); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t1 = "std", list(I); startTasks(t1); waitAllTasks(t1); task t2 = copyTask(t1); killTask(t1); t2; // t2 survived getResult(t2); killTask(t2); } proc compareTasks(task t1, task t2) "USAGE: compareTasks(t1, t2), t1, t2 tasks RETURN: 1, if t1 and t2 coincide; 0, otherwise. NOTE: The arguments and the results of t1 and t2 are not compared. @* 't1 == t2' is a shortcut for 'compareTasks(t1, t2)'. SEE ALSO: getCommand, getArguments, getResult, getState, copyTask, printTask EXAMPLE: example compareTasks; shows an example" { if (tasks[t1.index].id != tasks[t2.index].id) { return(0); } if (tasks[t1.index].command != tasks[t2.index].command) { return(0); } if (tasks[t1.index].state != tasks[t2.index].state) { return(0); } if (tasks[t1.index].linkID != tasks[t2.index].linkID) { return(0); } return(1); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t1 = "std", list(I); task t2 = "std", list(I); compareTasks(t1, t2); startTasks(t1); waitAllTasks(t1); t1 == t2; // the same as compareTasks(t1, t2); killTask(t1); killTask(t2); // The arguments and the result are not compared! ideal J = x; task t3 = "std", list(I); task t4 = "std", list(J); t3 == t4; killTask(t3); killTask(t4); } proc printTask(task t) "USAGE: printTask(t), t task RETURN: nothing. Prints information about t. NOTE: 'print(t);' and 't;' are shortcuts for 'printTask(t)'. SEE ALSO: getCommand, getArguments, getResult, getState, createTask, killTask EXAMPLE: example printTask; shows an example" { if (t.index == 0) { "An uninitialized task"; return(); } if (typeof(tasks[t.index]) != "internal_task") { "An uninitialized task"; return(); } "A task with the following properties:"+newline +"command: "+tasks[t.index].command+newline +"no. of arguments: "+string(size(tasks[t.index].arguments))+newline +"state: "+tasks[t.index].state; } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t; printTask(t); t = "std", list(I); t; // the same as printTask(t); startTasks(t); waitAllTasks(t); t; killTask(t); } proc startTasks(list #) "USAGE: startTasks(t1, t2, ...), t1, t2, ... tasks RETURN: nothing. Starts the tasks t1, t2, ... and sets their states to 'started'. NOTE: A task whose state is neither 'created' nor 'stopped' cannot be started. @* If startTasks() is applied to a task whose state is 'stopped', then the computation of this task will be restarted from the beginning. @* Tasks can be started from within other tasks. A started task should not be accessed from within any task other than the one within which it was started. @* For each task, the start of its computation is subject to the internal scheduling. SEE ALSO: stopTask, waitTasks, pollTask, getState, createTask, printTask EXAMPLE: example startTasks; shows an example" { int nargs = size(#); if (nargs == 0) { ERROR("missing argument"); } int i; for (i = nargs; i > 0; i--) { if (typeof(#[i]) != "task") { ERROR("argument not of type 'task' (argument no. "+string(i)+")"); } if (#[i].index == 0) { ERROR("cannot start an uninitialized task (task no. " +string(i)+")"); } if (typeof(tasks[#[i].index]) != "internal_task") { ERROR("cannot start an uninitialized task (task no. " +string(i)+")"); } if (tasks[#[i].index].state != "created" && tasks[#[i].index].state != "stopped") { ERROR("cannot start a task whose state is not"+newline +"'created' or 'stopped'"); } } for (i = nargs; i > 0; i--) { tasks[#[i].index].id = i; // has to be set before forking tasks[#[i].index].state = "started"; } int pid = system("pid"); link l(pid) = "ssi:fork"; open(l(pid)); write(l(pid), quote(startTasks_child(#, eval(pid)))); int port = read(l(pid)); link L(pid) = "ssi:connect localhost:"+string(port); open(L(pid)); nlinkIDs++; for (i = nargs; i > 0; i--) { tasks[#[i].index].links = list(L(pid), l(pid)); tasks[#[i].index].linkID = nlinkIDs; } } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t1 = "std", list(I); task t2 = "slimgb", list(I); startTasks(t1, t2); waitAllTasks(t1, t2); getResult(t1); getResult(t2); killTask(t1); killTask(t2); } /* This procedure is started within the child after forking. */ static proc startTasks_child(list localtasks, int pid_parent) { int port = system("reserve", 1); write(l(pid_parent), port); link L(pid_parent) = system("reservedLink"); export(L(pid_parent)); int sem_write = semaphore(1); int pid = system("pid"); int nlocaltasks = size(localtasks); intvec state = 0:nlocaltasks; // the internal state of each localtask (see rationale) int nwaiting = nlocaltasks; // the number of local tasks with internal state 0 (waiting) int nfinished; // the number of local tasks with internal state 3 (result sent) or // -1 (stopped) intvec queue = 1..nlocaltasks; int next = 1; list links; links[nlocaltasks+1] = l(pid_parent); intvec assignment = 0:nlocaltasks; // the task with id = i is running in link no. assignment[i] int nlinks; // data sent by other processes int code; int id; if (!defined(demanded_tasks)) { intvec demanded_tasks; int demanded_tasks_index = 1; exportto(Tasks, demanded_tasks); exportto(Tasks, demanded_tasks_index); } else { demanded_tasks = 0; demanded_tasks_index = 1; } int ndemanded = -1; // internal counts int granted_leaves; int results_sent; // auxiliary variables intvec waiting_tasks; int wait; int deadlock; int tmp; int i; int j; while (nwaiting > 0) { wait = 0; if (nlinks == 0) { wait = -1; granted_leaves++; while (-wait < nwaiting) { if (system("semaphore", "try_acquire", sem_leaves) == 1) { wait--; } else { break; } } } while (wait == 0) { wait = waitfirst(links, 500); if (wait == 0) { while (-wait < nwaiting) { if (system("semaphore", "try_acquire", sem_leaves) == 1) { wait--; } else { break; } } } } if (wait < 0) { // open (-wait) new links while (wait < 0) { wait++; nlinks++; link ll(pid)(nlinks) = "ssi:fork"; open(ll(pid)(nlinks)); links[nlinks] = ll(pid)(nlinks); write(links[nlinks], quote(startTasks_grandchild( eval(localtasks[queue[next]].index), eval(pid_parent), eval(pid), eval(nlinks), eval(sem_write)))); assignment[queue[next]] = nlinks; state[queue[next]] = 1; nwaiting--; next++; } // wait == 0 } if (wait > 0 && wait <= nlocaltasks) { code = read(links[wait]); if (code == 1) { // result computed id = read(links[wait]); state[id] = 2; if (ndemanded > 0 && removeDemanded(id)) { write(links[wait], 1); ndemanded--; results_sent++; } } // code == 2: startTasks_grandchild() ended, do nothing } if (wait == nlocaltasks+1) { code = read(l(pid_parent)); if (code == 0) { // stopTask id = read(l(pid_parent)); if (state[id] == 0) { // waiting queue = give_priority(queue, intvec(id)); next++; } if (state[id] == 1 || state[id] == 2) { // started or computed close(links[assignment[id]]); open(links[assignment[id]]); write(links[assignment[id]], quote(startTasks_grandchild( eval(localtasks[queue[next]].index), eval(pid_parent), eval(pid), eval(assignment[id]), eval(sem_write)))); assignment[queue[next]] = assignment[id]; assignment[id] = 0; state[queue[next]] = 1; next++; } // state[id] == -1 (stopped) or state[id] == 3 (sent) // should not happen nwaiting--; nfinished++; state[id] = -1; } if (code == 1) { // waitTasks demanded_tasks = read(l(pid_parent)); demanded_tasks_index = size(demanded_tasks); ndemanded = read(l(pid_parent)); if (ndemanded > demanded_tasks_index) { ndemanded = demanded_tasks_index; } if (demanded_tasks == 0 && ndemanded == -1) { write(l(pid_parent), results_sent); continue; } else { results_sent = 0; } demanded_tasks = demanded_tasks[demanded_tasks_index..1]; deadlock = 0; waiting_tasks = 0:demanded_tasks_index; j = 0; for (i = demanded_tasks_index; i > 0; i--) { id = demanded_tasks[i]; if (state[id] == 0) { // waiting j++; waiting_tasks[j] = id; deadlock = 1; } } if (j > 0) { waiting_tasks = waiting_tasks[1..j]; queue = queue[next..size(queue)]; next = 1; queue = give_priority(queue, waiting_tasks); waiting_tasks = 0; } for (i = demanded_tasks_index; i > 0; i--) { id = demanded_tasks[i]; if (state[id] == 1) { // started deadlock = 0; } if (state[id] == 2) { // computed write(links[assignment[id]], 1); tmp = removeDemanded(id); ndemanded--; results_sent++; deadlock = 0; } } if (deadlock) { granted_leaves++; nlinks++; link ll(pid)(nlinks) = "ssi:fork"; open(ll(pid)(nlinks)); links[nlinks] = ll(pid)(nlinks); write(links[nlinks], quote(startTasks_grandchild( eval(localtasks[queue[next]].index), eval(pid_parent), eval(pid), eval(nlinks), eval(sem_write)))); assignment[queue[next]] = nlinks; state[queue[next]] = 1; nwaiting--; next++; } } if (code == 2) { // pollTask id = read(l(pid_parent)); if (state[id] == 0) { // waiting queue = queue[next..size(queue)]; next = 1; queue = give_priority(queue, intvec(id)); } if (state[id] == 2) { // computed write(links[assignment[id]], 1); } write(l(pid_parent), state[id]); } if (code == 3) { // got result id = read(l(pid_parent)); write(links[assignment[id]], quote(startTasks_grandchild( eval(localtasks[queue[next]].index), eval(pid_parent), eval(pid), eval(assignment[id]), eval(sem_write)))); assignment[queue[next]] = assignment[id]; assignment[id] = 0; state[queue[next]] = 1; state[id] = 3; nwaiting--; nfinished++; next++; } } } while (nfinished < nlocaltasks || ndemanded != -1) { wait = waitfirst(links); if (wait <= nlocaltasks) { code = read(links[wait]); if (code == 1) { // result computed id = read(links[wait]); state[id] = 2; if (ndemanded > 0 && removeDemanded(id)) { write(links[wait], 1); ndemanded--; results_sent++; } } // code == 2: startTasks_grandchild() ended, do nothing } if (wait == nlocaltasks+1) { code = read(l(pid_parent)); if (code == 0) { // stopTask id = read(l(pid_parent)); if (state[id] == 1 || state[id] == 2) { // started or computed close(links[assignment[id]]); if (nlinks > granted_leaves) { tmp = system("semaphore", "release", sem_leaves); } links[assignment[id]] = def(0); nlinks--; assignment[id] = 0; nfinished++; } // else: nothing to do state[id] = -1; } if (code == 1) { // waitTasks demanded_tasks = read(l(pid_parent)); demanded_tasks_index = size(demanded_tasks); ndemanded = read(l(pid_parent)); if (ndemanded > demanded_tasks_index) { ndemanded = demanded_tasks_index; } if (demanded_tasks == 0 && ndemanded == -1) { write(l(pid_parent), results_sent); continue; } else { results_sent = 0; } demanded_tasks = demanded_tasks[demanded_tasks_index..1]; for (i = demanded_tasks_index; i > 0; i--) { id = demanded_tasks[i]; if (state[id] == 2) { // computed write(links[assignment[id]], 1); tmp = removeDemanded(id); ndemanded--; results_sent++; } } } if (code == 2) { // pollTask id = read(l(pid_parent)); if (state[id] == 2) { // computed write(links[assignment[id]], 1); } write(l(pid_parent), state[id]); } if (code == 3) { // got result id = read(l(pid_parent)); close(links[assignment[id]]); if (nlinks > granted_leaves) { tmp = system("semaphore", "release", sem_leaves); } links[assignment[id]] = def(0); nlinks--; assignment[id] = 0; state[id] = 3; nfinished++; } } } } /* This procedure has to be started within the grandchildren after forking. */ static proc startTasks_grandchild(int index, int pid_grandparent, int pid_parent, int link_no, int sem_write) { def result; int tmp = system("semaphore", "acquire", sem_queue); tmp = system("semaphore", "acquire", sem_cores); tmp = system("semaphore", "release", sem_queue); execute("result = "+tasks[index].command+"(" +argsToString("tasks[index].arguments", size(tasks[index].arguments)) +");"); tmp = system("semaphore", "release", sem_cores); write(ll(pid_parent)(link_no), 1); write(ll(pid_parent)(link_no), tasks[index].id); tmp = read(ll(pid_parent)(link_no)); tmp = system("semaphore", "acquire", sem_write); write(L(pid_grandparent), index); write(L(pid_grandparent), result); tmp = system("semaphore", "release", sem_write); return(2); } /* Remove id from demanded_tasks and return 1, if id is an element of * demanded_tasks; return 0, otherwise. Note: * - demanded_tasks and demanded_tasks_index are (lib-)global objects * exported in startTasks_child(). * - demanded_tasks_index is used to avoid copying. It is defined to be * the greatest integer with demanded_tasks[demanded_tasks_index] != 0 * and demanded_tasks[demanded_tasks_index+1] == 0 (if defined). */ static proc removeDemanded(alias int id) { if (demanded_tasks[demanded_tasks_index] == id) { demanded_tasks[demanded_tasks_index] = 0; demanded_tasks_index--; return(1); } int i; for (i = demanded_tasks_index-1; i > 0; i--) { if (demanded_tasks[i] == id) { demanded_tasks[i..demanded_tasks_index] = demanded_tasks[(i+1)..demanded_tasks_index], 0; demanded_tasks_index--; return(1); } } return(0); } /* Move the elements in 'preferred' to the beginning of 'queue'. We may assume * that * - 'preferred' is a subset of 'queue'; * - the elements of 'preferred' are distinct and non-zero; * - the elements of 'queue' are distinct and non-zero. * For performance reasons, we may also assume that 'queue' and 'preferred' are * more or less ordered in most cases. Note that queue has the format * '0, indices, 0'. */ static proc give_priority(intvec queue, intvec preferred) { int size_queue = size(queue); int size_preferred = size(preferred); if (size_queue == size_preferred) { return(queue); } int index = size_queue; int i; int j; for (i = size_preferred; i > 0; i--) { for (j = size_queue; j > 0; j--) { if (queue[index] == preferred[i]) { queue[index] = 0; break; } index--; if (index == 0) { index = size_queue; } } } intvec not_preferred = 0:(size_queue-size_preferred); index = 1; for (i = 1; i <= size_queue; i++) { if (queue[i]) { not_preferred[index] = queue[i]; index++; } } queue = preferred, not_preferred; return(queue); } proc stopTask(task t) "USAGE: stopTask(t), t task RETURN: nothing. Stops the t and sets its state to 'stopped'. NOTE: A task whose state is not 'started' cannot be stopped. @* Intermediate results are discarded when a task is stopped. @* killTask() should be called for any no longer needed task. SEE ALSO: startTasks, waitTasks, pollTask, getState, killTask, printTask EXAMPLE: example stopTask; shows an example" { if (t.index == 0) { ERROR("cannot stop an uninitialized task"); } if (typeof(tasks[t.index]) != "internal_task") { ERROR("cannot stop an uninitialized task"); } if (tasks[t.index].state != "started") { ERROR("cannot stop a task whose state is not 'started'"); } write(tasks[t.index].links[2], 0); write(tasks[t.index].links[2], tasks[t.index].id); tasks[t.index].id = 0; tasks[t.index].links = list(); tasks[t.index].linkID = 0; tasks[t.index].state = "stopped"; } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t = "std", list(I); startTasks(t); stopTask(t); t; killTask(t); } proc waitTasks(list T, int N, list #) "USAGE: waitTasks(T, N[, timeout]), T list of tasks, N int, timeout int RETURN: an ordered list of the indices of those tasks which have been successfully completed. The state of these tasks is set to 'completed'. @* The procedure waits for N tasks to complete. @* An optional timeout in ms can be provided. Default is 0 which disables the timeout. NOTE: A task whose state is neither 'started' nor 'completed' cannot be waited for. @* The result of any completed task can be accessed via @ref{getResult}. @* The returned list may contain more than N entries if the computation of some tasks has already finished and/or if several tasks finish \"at the same time\". It may contain less than N entries in the case of timeout or errors occurring. @* Polling is guaranteed, i.e. the index of any task t for which 'pollTask(t);' would return 1 will appear in the returned list. SEE ALSO: startTasks, pollTask, getResult, getState, printTask EXAMPLE: example waitTasks; shows an example" { /* initialize the timer */ int oldtimerresolution = system("--ticks-per-sec"); system("--ticks-per-sec", 1000); int starting_time = rtimer; /* read optional parameters */ int timeout; if (size(#) > 0) { if (size(#) > 1 || typeof(#[1]) != "int") { ERROR("wrong optional parameter"); } timeout = #[1]; } /* check for errors */ if (timeout < 0) { ERROR("negative timeout"); } int nargs = size(T); if (nargs == 0) { ERROR("missing task"); } if (N < 1 || N > nargs) { ERROR("wrong number of tasks to wait for"); } int i; for (i = nargs; i > 0; i--) { if (typeof(T[i]) != "task") { ERROR("element not of type 'task' (element no. "+string(i)+")"); } if (T[i].index == 0) { ERROR("cannot wait for an uninitialized task (task no. "+string(i) +")"); } if (typeof(tasks[T[i].index]) != "internal_task") { ERROR("cannot wait for an uninitialized task (task no. "+string(i) +")"); } if (tasks[T[i].index].state != "started" && tasks[T[i].index].state != "completed") { ERROR("cannot wait for a task whose state is not"+newline +"'started' or 'completed' (task no. "+string(i)+")"); } } /* sort the tasks */ int ncompleted; list requests; list links; int sorted_in; int j; for (i = 1; i <= nargs; i++) { if (tasks[T[i].index].state == "completed") { ncompleted++; } else { // tasks[T[i].index].state == "started" sorted_in = 0; for (j = size(requests); j > 0; j--) { if (requests[j][1] == tasks[T[i].index].linkID) { requests[j][2][size(requests[j][2])+1] = tasks[T[i].index].id; sorted_in = 1; break; } } if (!sorted_in) { requests[size(requests)+1] = list(tasks[T[i].index].linkID, intvec(tasks[T[i].index].id), tasks[T[i].index].links[2]); links[size(links)+1] = tasks[T[i].index].links[1]; } } } /* send the reqests */ for (j = size(requests); j > 0; j--) { write(requests[j][3], 1); write(requests[j][3], requests[j][2]); write(requests[j][3], N-ncompleted); } /* wait for the results */ int wait; int index; int results_got; int remaining_time; int tmp; while (ncompleted < N) { wait = waitfirst(links, 0); if (wait == 0) { if (timeout == 0) { tmp = system("semaphore", "release", sem_cores); wait = waitfirst(links); tmp = system("semaphore", "acquire", sem_cores); } else { remaining_time = timeout-(rtimer-starting_time); if (remaining_time < 0) { break; } else { tmp = system("semaphore", "release", sem_cores); wait = waitfirst(links, remaining_time); tmp = system("semaphore", "acquire", sem_cores); } } } if (wait < 1) { break; } index = read(links[wait]); tasks[index].result = read(links[wait]); write(tasks[index].links[2], 3); write(tasks[index].links[2], tasks[index].id); tasks[index].id = 0; tasks[index].links = list(); tasks[index].linkID = 0; tasks[index].state = "completed"; ncompleted++; results_got++; } if (wait == -1) { ERROR("error in waitfirst()"); } /* end communication process */ for (j = size(requests); j > 0; j--) { write(requests[j][3], 1); write(requests[j][3], 0); write(requests[j][3], -1); } int results_sent; for (j = size(requests); j > 0; j--) { results_sent = results_sent + read(requests[j][3]); } while (results_sent > results_got) { wait = waitfirst(links); if (wait == -1) { ERROR("error in waitfirst()"); } index = read(links[wait]); tasks[index].result = read(links[wait]); write(tasks[index].links[2], 3); write(tasks[index].links[2], tasks[index].id); tasks[index].id = 0; tasks[index].links = list(); tasks[index].linkID = 0; tasks[index].state = "completed"; results_got++; } /* list completed tasks */ list completed; completed[nargs+1] = 0; j = 0; for (i = 1; i <= nargs; i++) { if (tasks[T[i].index].state == "completed") { j++; completed[j] = i; } } completed[nargs+1] = def(0); /* return the result */ system("--ticks-per-sec", oldtimerresolution); return(completed); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t1 = "std", list(I); task t2 = "slimgb", list(I); startTasks(t1, t2); waitTasks(list(t1, t2), 2); // wait for both tasks getResult(t1); getResult(t2); killTask(t1); killTask(t2); } proc waitAllTasks(list #) "USAGE: waitAllTasks(t1, t2, ...), t1, t2, ... tasks RETURN: nothing. Waits for all the tasks t1, t2, ... to complete. The state of the tasks is set to 'completed'. NOTE: A task whose state is neither 'started' nor 'completed' cannot be waited for. @* The result of any completed task can be accessed via @ref{getResult}. @* 'waitAllTasks(t1, t2, ...);' is a shortcut for 'waitTasks(list(t1, t2, ...), size(list(t1, t2, ...)));'. Since returning a list of the indices of the completed tasks does not make sense in this case, nothing is returned. SEE ALSO: waitTasks, startTasks, pollTask, getResult, getState, printTask EXAMPLE: example waitAllTasks; shows an example" { list tmp = waitTasks(#, size(#)); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t1 = "std", list(I); task t2 = "slimgb", list(I); startTasks(t1, t2); waitAllTasks(t1, t2); // the same as 'waitTasks(list(t1, t2), 2);', // but without return value getResult(t1); getResult(t2); killTask(t1); killTask(t2); } proc pollTask(task t) "USAGE: pollTask(t), t task RETURN: 1, if the computation of the task t has successfully finished; 0, otherwise. @* The state of any task whose computation has successfully finished is set to 'completed'. NOTE: A task whose state is neither 'started' nor 'completed' cannot be polled. @* The result of any completed task can be accessed via @ref{getResult}. @* pollTask() should return immediately. However, receiving the result of the task may take some time. SEE ALSO: startTasks, waitTasks, getResult, getState, printTask EXAMPLE: example pollTask; shows an example" { if (t.index == 0) { ERROR("cannot poll an uninitialized task"); } if (typeof(tasks[t.index]) != "internal_task") { ERROR("cannot poll an uninitialized task"); } if (tasks[t.index].state != "started" && tasks[t.index].state != "completed") { ERROR("cannot poll a task whose state is not"+newline +"'started' or 'completed'"); } if (tasks[t.index].state == "completed") { return(1); } // tasks[t.index].state == "started" write(tasks[t.index].links[2], 2); write(tasks[t.index].links[2], tasks[t.index].id); int state = read(tasks[t.index].links[2]); if (state == 0 || state == 1) { // waiting or started return(0); } if (state == 2) { // computed int index = read(tasks[t.index].links[1]); // index == t.index tasks[t.index].result = read(tasks[t.index].links[1]); write(tasks[t.index].links[2], 3); write(tasks[t.index].links[2], tasks[t.index].id); tasks[t.index].id = 0; tasks[t.index].links = list(); tasks[t.index].linkID = 0; tasks[t.index].state = "completed"; return(1); } // state == -1 (stopped) or state == 3 (sent) should not happen } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t = "std", list(I); startTasks(t); waitAllTasks(t); pollTask(t); // task already completed t; getResult(t); killTask(t); } proc getCommand(task t) "USAGE: getCommand(t), t task RETURN: a string, the command of t. NOTE: This command cannot be applied to tasks whose state is 'uninitialized'. SEE ALSO: getArguments, getResult, getState, createTask, printTask EXAMPLE: example getCommand; shows an example" { if (t.index == 0) { ERROR("cannot get command of an uninitialized task"); } if (typeof(tasks[t.index]) != "internal_task") { ERROR("cannot get command of an uninitialized task"); } return(tasks[t.index].command); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t = "std", list(I); getCommand(t); killTask(t); } proc getArguments(task t) "USAGE: getArguments(t), t task RETURN: a list, the arguments of t. NOTE: This command cannot be applied to tasks whose state is 'uninitialized'. SEE ALSO: getCommand, getResult, getState, createTask, printTask EXAMPLE: example getArguments; shows an example" { if (t.index == 0) { ERROR("cannot get arguments of an uninitialized task"); } if (typeof(tasks[t.index]) != "internal_task") { ERROR("cannot get arguments of an uninitialized task"); } return(tasks[t.index].arguments); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t = "std", list(I); getArguments(t); killTask(t); } proc getResult(task t) "USAGE: getResult(t), t task RETURN: the result of t. NOTE: This command cannot be applied to tasks whose state is not 'completed'. SEE ALSO: getCommand, getArguments, getState, waitTasks, pollTask, printTask EXAMPLE: example getResult; shows an example" { if (t.index == 0) { ERROR("cannot get result of an uninitialized task"); } if (typeof(tasks[t.index]) != "internal_task") { ERROR("cannot get result of an uninitialized task"); } if (tasks[t.index].state != "completed") { ERROR("cannot get result of a task which is not completed"); } return(tasks[t.index].result); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t = "std", list(I); startTasks(t); waitAllTasks(t); getResult(t); killTask(t); } proc getState(task t) "USAGE: getState(t), t task RETURN: a string, the state of t. SEE ALSO: getCommand, getArguments, getResult, printTask, createTask, startTasks, stopTask, waitTasks, pollTask, killTask EXAMPLE: example getState; shows an example" { if (t.index == 0) { return("uninitialized"); } if (typeof(tasks[t.index]) != "internal_task") { return("uninitialized"); } return(tasks[t.index].state); } example { "EXAMPLE:"; echo = 2; ring R = 0, (x,y), dp; ideal I = x9y2+x10, x2y7-y8; task t = "std", list(I); getState(t); startTasks(t); getState(t); waitAllTasks(t); getState(t); killTask(t); getState(t); } / * construct the string "name[1], name[2], name[3], ..., name[length]" */ static proc argsToString(string name, int length) { string output; if (length > 0) { output = name+"[1]"; } int i; for (i = 2; i <= length; i++) { output = output+", "+name+"["+string(i)+"]"; } return(output); } singular-4.0.3+ds/Singular/LIB/teachstd.lib000066400000000000000000000566771266270727000204630ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version teachstd.lib 4.0.0.0 Jun_2013 "; // $Id: 92ffc29de41ebc8e82235f0e4b83b6408de3d641 $ category="Teaching"; info=" LIBRARY: teachstd.lib Procedures for teaching standard bases AUTHOR: G.-M. Greuel, greuel@mathematik.uni-kl.de NOTE: The library is intended to be used for teaching purposes, but not for serious computations. Sufficiently high printlevel allows to control each step, thus illustrating the algorithms at work. The procedures are implemented exactly as described in the book 'A SINGULAR Introduction to Commutative Algebra' by G.-M. Greuel and G. Pfister (Springer 2002). PROCEDURES: ecart(f); ecart of f tail(f); tail of f sameComponent(f,g); test for same module component of lead(f) and lead(g) leadmonomial(f); leading monomial as polynomial (also for vectors) monomialLcm(m,n); lcm of monomials m and n as polynomial (also for vectors) spoly(f[,1]); s-polynomial of f [symmetric form] minEcart(T,h); element g from T of minimal ecart s.t. LM(g)|LM(h) NFMora(i); normal form of i w.r.t Mora algorithm prodcrit(f,g[,o]); test for product criterion chaincrit(f,g,h); test for chain criterion pairset(G); pairs form G neither satifying prodcrit nor chaincrit updatePairs(P,S,h); pairset P enlarded by not useless pairs (h,f), f in S standard(id); standard basis of ideal/module localstd(id); local standard basis of id using Lazard's method [parameters in square brackets are optional] "; LIB "poly.lib"; /////////////////////////////////////////////////////////////////////////////// proc ecart(def f) "USAGE: ecart(f); f poly or vector RETURN: the ecart e of f of type int EXAMPLE: example ecart; shows an example " { int e = maxdeg1(f)-maxdeg1(lead(f)); return(e); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),ls; ecart((y+z+x+xyz)**2); ring s=0,(x,y,z),dp; ecart((y+z+x+xyz)**2); } /////////////////////////////////////////////////////////////////////////////// proc leadmonomial(def f) "USAGE: leadmonomial(f); f poly or vector RETURN: the leading monomial of f of type poly NOTE: if f is of type poly, leadmonomial(f)=leadmonom(f), if f is of type vector and if leadmonom(f)=m*gen(i) then leadmonomial(f)=m EXAMPLE: example leadmonomial; shows an example " { int e; poly m; if(typeof(f) == "vector") { e=leadexp(f)[nvars(basering)+1]; m=leadmonom(f)[e,1]; } if(typeof(f) == "poly") { m=leadmonom(f); } return(m); } example { "EXAMPLE:"; echo = 2; ring s=0,(x,y,z),(c,dp); leadmonomial((y+z+x+xyz)^2); leadmonomial([(y+z+x+xyz)^2,xyz5]); } /////////////////////////////////////////////////////////////////////////////// proc tail(def f) "USAGE: tail(f); f poly or vector RETURN: f-lead(f), the tail of f of type poly EXAMPLE: example tail; shows an example " { def t = f-lead(f); return(t); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),ls; tail((y+z+x+xyz)**2); ring s=0,(x,y,z),dp; tail((y+z+x+xyz)**2); } /////////////////////////////////////////////////////////////////////////////// proc sameComponent(def f,def g) "USAGE: sameComponent(f,g); f,g poly or vector RETURN: 1 if f and g are of type poly or if f and g are of type vector and their leading monomials involve the same module component, 0 if not EXAMPLE: example sameComponent; shows an example " { if(typeof(f) != typeof(g)) { ERROR("** arguments must be of same type"); } if(typeof(f) == "vector") { if( leadexp(f)[nvars(basering)+1] != leadexp(g)[nvars(basering)+1] ) { return(0); } } return(1); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; sameComponent([y+z+x,xyz],[z2,xyz]); sameComponent([y+z+x,xyz],[z4,xyz]); sameComponent(y+z+x+xyz, xy+z5); } /////////////////////////////////////////////////////////////////////////////// proc monomialLcm(def m,def n) "USAGE: monomialLcm(m,n); m,n of type poly or vector RETURN: least common multiple of leading monomials of m and n, of type poly NOTE: if m = (x1...xr)^(a1,...,ar)*gen(i) (gen(i)=1 if m is of type poly) and n = (x1...xr)^(b1,...,br)*gen(j), then the proc returns (x1,...,xr)^(max(a1,b1),...,max(ar,br)) if i=j and 0 if i!=j. EXAMPLE: example monomialLcm; shows an example " { if(typeof(n) != typeof(m)) { ERROR("** arguments must be of same type"); } poly u ; if(sameComponent(m,n) == 0) //leading term of vectors involve { //different module components return(u); } intvec v = leadexp(m); //now start to compute lcm intvec w = leadexp(n); u=1; int i; for (i=1; i<=nvars(basering); i++) { if(v[i]>=w[i]) { u = u*var(i)**v[i]; } else { u = u*var(i)**w[i]; } } return(u); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),ds; monomialLcm(xy2,yz3); monomialLcm([xy2,xz],[yz3]); monomialLcm([xy2,xz3],[yz3]); } /////////////////////////////////////////////////////////////////////////////// proc spoly(def f,def g,list #) "USAGE: spoly(f,g[,s]); f,g poly or vector, s int RETURN: the s-polynomial of f and g, of type poly or vector if s!=0 the symmetric s-polynomial (without division) is returned EXAMPLE: example spoly; shows an example " { if(typeof(f) != typeof(g)) { ERROR("** arguments must be of same type"); } if(size(#) == 0) { #[1]=0; } int e; poly o = monomialLcm(f,g); if( o == 0) //can only happen, if vectors f and g involve { //different module components vector sp; return(sp); } poly m=(o/leadmonomial(f)); //compute the leading monomial as poly poly n=(o/leadmonomial(g)); f = m * f; g = n * g; // now they have the same LM! if (#[1]==0) //the asymmetric s-poly { def sp = f - (leadcoef(f)/leadcoef(g))*g; } else //the symmetric s-poly, avoiding division { def sp = leadcoef(g)*f - leadcoef(f)*g; } return(sp); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),ls; spoly(2x2+x2y,3y3+xyz); ring s=0,(x,y,z),(c,dp); spoly(2x2+x2y,3y3+xyz); spoly(2x2+x2y,3y3+xyz,1); //symmetric s-poly without division spoly([5x2+x2y,z5],[x2,y3,y4]); //s-poly for vectors } /////////////////////////////////////////////////////////////////////////////// proc minEcart(def T,def h) "USAGE: minEcart(T,h); T ideal or module, h poly or vector RETURN: element g from T such that leadmonom(g) divides leadmonom(h)@* ecart(g) is minimal with this property (if T != 0); return 0 if T is 0 or h = 0 EXAMPLE: example minEcart; shows an example " { int i,k,e; if (size(T)==0 or h==0 ) //trivial cases { h = 0; return(h); } //---- check whether some element in T has the same module component as h ---- int v; intvec w; T = simplify(T,2); if (typeof(h) == "vector") { e=1; v = leadexp(h)[nvars(basering)+1]; for( i=1; i<=size(T); i++) { w[i]=leadexp(T[i])[nvars(basering)+1]; if(v == w[i]) { e=0; //some element in T involves the same component as h } } } if ( e == 1 ) //no element in T involves the same component as h { h = 0; return(h); } if (typeof(h) == "poly") //for polys v=w[i] for all i { v = 1; w[size(T)]=0; w=w+1; } //------ check whether for some g in T leadmonom(g) divides leadmonom(h) ----- def g = T[1]; poly f = leadmonomial(h); for( i=1; i<=size(T); i++) { if( f/leadmonomial(T[i]) != 0 and v==w[i] ) { g=T[i]; k=i; break; } } if (k == 0) //no leadmonom(g) divides leadmonom(h) { g = 0; return(g); } //--look for T[i] with minimal ecart s.t.leadmonom(T[i]) divides leadmonom(h)-- for( i=k+1; i<=size(T); i++) { if( f/leadmonomial(T[i]) != 0 and v==w[i] ) { if (ecart(T[i]) < ecart(g)) { g=T[i]; } } } return(g); } example { "EXAMPLE:"; echo = 2; ring R=0,(x,y,z),dp; ideal T = x2y+x2,y3+xyz,xyz2+z4; poly h = x2y2z2+x5+yx3+z6; minEcart(T,h);""; ring S=0,(x,y,z),(c,ds); module T = [x2+x2y,y2],[y3+xyz,x3-z3],[x3y+z4,0,x2]; vector h = [x3y+x5+x2y2z2+z6,x3]; minEcart(T,h); } /////////////////////////////////////////////////////////////////////////////// proc NFMora(def f,def G,list #) "USAGE: NFMora(f,G[,s]); f poly or vector,G ideal or module, s int RETURN: the Mora normal form of f w.r.t. G, same type as f if s!=0 the symmetric s-polynomial (without division) is used NOTE: Show comments if printlevel > 0, pauses computation if printlevel > 1 EXAMPLE: example NFMora; shows an example " { if(size(#) == 0) { #[1]=0; } int y = printlevel - voice + 2; if( f==0 or size(G) ==0 ) { if (y>0) { "// 1st or 2nd argument 0"; } return(f); } int i,e; def h = f; def T = G; // -------------------- start with f to be reduced by G -------------------- if (y>0) {""; "// Input for NFMora is (f,T):"; "// f:"; f; "// T:"; T; "// Reduce f with T, eventually enlarging T for local ordering"; } // ----------------------- enter the reduction loop ------------------------ def g = minEcart(T,h); while (h!=0 and g!=0) { if (y>0) { ""; "// Reduction-step in NFMora:",i; "// h = (f after",i,"reductions) reduction with g from T:"; "// g = element of minimal ecart in T s.t. LM(g)|LM(h):"; "// h:";h; "// g:";g; } if (y>1) { pause("press to continue"); "// T, set used for reduction:"; T; pause("press to continue"); } e=0; if( ecart(g) > ecart(h) ) { T=T,h; e=1; } if (y>0 ) { "// T-set enlarged for next reduction? (yes/no = 1/0): ", e; if( e==1 ) { "// T-set for next reduction got enlarged by h:"; "// h:";h; if (y>1) { pause("press to continue"); } } } h = spoly(h,g,#[1]); g = minEcart(T,h); i=i+1; } if(y>0) { ""; "// normal form is:"; } return(h); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; poly f = x2y2z2+x5+yx3+z6-3y3; ideal G = x2y+x2,y3+xyz,xyz2+z6; NFMora(f,G);""; ring s=0,(x,y,z),ds; poly f = x3y+x5+x2y2z2+z6; ideal G = x2+x2y,y3+xyz,x3y2+z4; NFMora(f,G);""; vector v = [f,x2+x2y]; module M = [x2+x2y,f],[y3+xyz,y3],[x3y2+z4,z2]; NFMora(v,M); } /////////////////////////////////////////////////////////////////////////////// proc prodcrit(def f,def g,list #) "USAGE: prodcrit(f,g[,o]); f,g poly or vector, and optional int argument o RETURN: 1 if product criterion applies in the same module component, 2 if lead(f) and lead(g) involve different components, 0 else NOTE: if product criterion applies we can delete (f,g) from pairset. This procedure returns 0 if o is given and is a positive integer, or you may set the attribute \"default_arg\" for prodcrit to 1. EXAMPLE: example prodcrit; shows an example " { // ------------------ check for optional disabling argument ------------- if( size(#) > 0 ) {// "size(#): ", size(#); "typeof(#[1]): ", typeof(#[1]); if( typeof(#[1]) == "int" ) {// "#[1] = int ", #[1]; if( #[1] > 0 ) { return(0); } } } // ------------------- product criterion for polynomials --------------------- if(typeof(f)=="poly") { if( monomialLcm(f,g)==leadmonom(f)*leadmonom(g)) { return(1); } return(0); } // ------------------- product criterion for modules --------------------- if(sameComponent(f,g)==1) { if( monomialLcm(f,g)==leadmonomial(f)*leadmonomial(g) ) { int c = leadexp(f)[nvars(basering)+1]; //component involving lead(f) if((f-f[c]*gen(c))-(g-g[c]*gen(c))==0) //other components are 0 { return(1); } } return(0); } return(2); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; poly f = y3z3+x5+yx3+z6; poly g = x5+yx3; prodcrit(f,g); vector v = x3z2*gen(1)+x3y*gen(1)+x2y*gen(2); vector w = y4*gen(1)+y3*gen(2)+xyz*gen(1); prodcrit(v,w); } /////////////////////////////////////////////////////////////////////////////// proc chaincrit(def f,def g,def h) "USAGE: chaincrit(f,g,h); f,g,h poly or module RETURN: 1 if chain criterion applies, 0 else NOTE: if chain criterion applies to f,g,h we can delete (g,h) from pairset EXAMPLE: example chaincrit; shows an example " { if(sameComponent(f,g) and sameComponent(f,h)) { if( monomialLcm(g,h)/leadmonomial(f) !=0 ) { return(1); } } return(0); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; poly f = x2y2z2+x5+yx3+z6; poly g = x5+yx3; poly h = y2z5+x5+yx3; chaincrit(f,g,h); vector u = [x2y3-z2,x2y]; vector v = [x2y2+z2,x2-y2]; vector w = [x2y4+z3,x2+y2]; chaincrit(u,v,w); } /////////////////////////////////////////////////////////////////////////////// proc pairset(def G) "USAGE: pairset(G); G ideal or module RETURN: list L, L[1] = the pairset of G as list (not containing pairs for which the product or the chain criterion applies), L[2] = intvec v, v[1]= # product criterion, v[2]= # chain criterion EXAMPLE: example pairset; shows an example " { int i,j,k,s,c,ccrit,pcrit,pr; int y = printlevel - voice + 2; G = simplify(G,10); def g = G; ideal pair; list P,I; //P=pairlist of G, I=list of corresponding indices of pairs for (i=1; i<=size(G); i++) { for(j = i+1; j<=size(G); j++) { pr = prodcrit(G[i],G[j]); //check first product criterion if( pr != 0 ) { pcrit=pcrit+(pr==1); } else { s = size(P); //now check chain criterion for(k=1; k<=s; k++) { if( i==I[k][2] ) { if ( chaincrit(P[k][1],P[k][2],G[j]) ) { //need not include (G[i],G[j]) in P c=1; ccrit=ccrit+1; break; } } if( j==I[k][1] and c==0 ) { "########### enter pairset2 #############"; if ( chaincrit(G[i],P[k][1],P[k][2]) ) { //can delete P[k]=(P[k][1],P[k][2]) ccrit=ccrit+1; P = delete(P,k); s = s-1; } } } if ( c==0 ) { g = G[i],G[j]; P[s+1]=g; I[s+1]=intvec(i,j); } c=0; } } } if (y>0) { ""; "// product criterion:",pcrit," chain criterion:",ccrit; } intvec v = pcrit,ccrit; P=P,v; return(P); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; ideal G = x2y+x2,y3+xyz,xyz2+z4; pairset(G);""; module T = [x2y3-z2,x2y],[x2y2+z2,x2-y2],[x2y4+z3,x2+y2]; pairset(T); } /////////////////////////////////////////////////////////////////////////////// proc updatePairs(def P,def S,def h) "USAGE: updatePairs(P,S,h); P list, S ideal or module, h poly or vector@* P a list of pairs of polys or vectors (obtained from pairset) RETURN: list Q, Q[1] = the pairset P enlarged by all pairs (f,h), f from S, without pairs for which the product or the chain criterion applies@* Q[2] = intvec v, v[1]= # product criterion, v[2]= # chain criterion EXAMPLE: example updatePairs; shows an example " { int i,j,k,s,r,c,ccrit,pcrit,pr; int y = printlevel - voice + 2; ideal pair; list Q = P; //Q will become enlarged pairset s = size(P); r = size(Q); //r will grow with Q list R; def g = S; //give g the correct type ideal/module for (i=1; i<=size(S); i++) { pr = prodcrit(h,S[i]); if( pr != 0 ) //check product criterion { pcrit=pcrit+(pr==1); //count product criterion in same component } else { //prodcrit did not apply, check for chaincrit r=size(Q); for(k=1; k<=r; k++) { if( Q[k][2]==S[i] ) //S[i]=Q[k][2] { if( chaincrit(Q[k][1],S[i],h) ) { //can forget (S[i],h) c=1; ccrit=ccrit+1; break; } } } if ( c==0 ) { g = S[i],h; //add pair (S[i],h) Q[r+1] = g; } c=0; } } if (y>0) { "";; "// product criterion:",pcrit," chain criterion:",ccrit; } intvec v = pcrit,ccrit; Q = Q,v; return(Q); } example { "EXAMPLE:"; echo = 2; ring R1=0,(x,y,z),(c,dp); ideal S = x2y+x2,y3+xyz; poly h = x2y+xyz; list P = pairset(S)[1]; P;""; updatePairs(P,S,h);""; module T = [x2y3-z2,x2y],[x2y4+z3,x2+y2]; P = pairset(T)[1]; P;""; updatePairs(P,T,[x2+x2y,y3+xyz]); } /////////////////////////////////////////////////////////////////////////////// proc standard(def id, list #) "USAGE: standard(i[,s]); id ideal or module, s int RETURN: a standard basis of id, using generalized Mora's algorithm which is Buchberger's algorithm for global monomial orderings. If s!=0 the symmetric s-polynomial (without division) is used NOTE: Show comments if printlevel > 0, pauses computation if printlevel > 1 EXAMPLE: example standard; shows an example " { if(size(#) == 0) { #[1]=0; } def S = id; //S will become the standard basis of id def h = S[1]; int i,z; int y = printlevel - voice + 2; if(y>0) { ""; "// the set S, to become a standard basis:"; S; if(y>1) { "// create pairset, i.e. pairs from S,"; "// after application of product and chain criterion"; } } list P = pairset(S); //create pairset of S=id intvec v = P[2]; P = P[1]; //-------------------------- Main loop in SB lgorithm ---------------------- while (size(P) !=0) { z=z+1; if(y>0) { ""; "// Enter NFMora for next pair, count",z; "// size of partial standard basis S: (",size(S),")"; "// number of pairs of S after updating: (",size(P),")"; if(y>1) { "// 1st pair of new pairset:"; P[1]; "// set T=S used for reduction:";S; "// apply NFMora to (spoly,S), spoly = spoly(1st pair)"; } } //-------------------- apply NFMora = Mora's normal form ------------- h = spoly(P[1][1],P[1][2],#[1]); if(y>1) { "// spoly:";h; } h = NFMora(h,S,#[1]); if(h==0) //normal form is 0 { if(y==1) { "// pair has reduced to 0"; } if(y>1) { h;""; pause("press to continue"); } } P = delete(P,1); //spoly of pair reduced to 0, pair can be deleted //--- spoly of pair did not reduce to 0, update S and paiset of S ---- if( h != 0) { if(y==1) { "// ** new spoly in degree **:", deg(h); } if(y>1) { h;""; pause("press to continue"); "// update pairset"; } P=updatePairs(P,S,h); //update P (=paisert of S) v=v+P[2]; //with useful pairs (g,h), g from S P=P[1]; S=S,h; //update S, will become the standard basis } } //------------------------------ finished --------------------------------- if( find(option(),"prot") or y>0 ) { ""; //show how often prodcrit and chaincrit applied "// product criterion:",v[1]," chain criterion:",v[2]; ""; "// Final standard basis:"; } return(S); } example { "EXAMPLE:"; echo = 2; ring r=0,(x,y,z),dp; ideal G = x2y+x2,y3+xyz,xyz2+z4; standard(G);""; ring s=0,(x,y,z),(c,ds); ideal G = 2x2+x2y,y3+xyz,3x3y+z4; standard(G);""; standard(G,1);""; //use symmetric s-poly without division module M = [2x2,x3y+z4],[3y3+xyz,y3],[5z4,z2]; standard(M); } /////////////////////////////////////////////////////////////////////////////// proc localstd (def id) "USAGE: localstd(id); id = ideal RETURN: A standard basis for a local degree ordering, using Lazard's method. NOTE: The procedure homogenizes id w.r.t. a new 1st variable local@t, computes a SB w.r.t. (dp(1),dp) and substitutes local@t by 1. Hence the result is a SB with respect to an ordering which sorts first w.r.t. the subdegree of the original variables and then refines it with dp. This is the local degree ordering ds. localstd may be used in order to avoid cancellation of units and thus to be able to use option(contentSB) also for local orderings. EXAMPLE: example localstd; shows an example " { int ii; def bas = basering; execute("ring @r_locstd =("+charstr(bas)+"),(local@t,"+varstr(bas)+"),(dp(1),dp);"); ideal id = imap(bas,id); ideal hid = homog(id,local@t); hid = std(hid); hid = subst(hid,local@t,1); setring bas; def hid = imap(@r_locstd,hid); attrib(hid,"isSB",1); kill @r_locstd; return(hid); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y,z),ds; ideal i = xyz+z5,2x2+y3+z7,3z5+y5; localstd(i); } /////////////////////////////////////////////////////////////////////////////// /* // some examples: LIB"teachstd.lib"; option(prot); printlevel=3; ring r0 = 0,(t,x,y),lp; ideal i = x-t2,y-t3; standard(i); printlevel=1; standard(i); option(prot); printlevel =1; ring r1 = (0,a,b),(x,y,z),(c,ds); module M = [ax2,bx3y+z4],[a3y3+xyz,by3],[5az4,(a+b)*z2]; module N1= std(M); module N2 = standard(M,1); NF(lead(N2),lead(N1)); NF(lead(N1),lead(N2));rom T ring r2 = 0,(x,y,z),dp; ideal I = x2y+x2,y3+xyz,xyz2+z4; option(prot); int tt = timer; ideal J = standard(I); timer -tt; //4sec, product criterion: 9 chain criterion: 6 ideal J1 = std(I); NF(lead(J),lead(J1)); NF(lead(J1),lead(J)); ring r3 = 0,(x,y,z),ds; poly f = x3*y4+z5+xyz; ideal I = f,jacob(f); option(prot); int tt = timer; ideal J = standard(I); timer -tt; //3sec, product criterion: 1 chain criterion: 3 ideal J1 = std(I); NF(lead(J),lead(J1)); NF(lead(J1),lead(J)); //Becker: ring r4 = 32003,(x,y,z),lp; ideal I = x3-1, y3-1, -27x3-243x2y+27x2z-729xy2+162xyz-9xz2-729y3+243y2z-27yz2+z3-27; option(prot); int tt = timer; ideal J = standard(I); timer -tt; //201sec, product criterion: 42 chain criterion: 33 ideal J1 = std(I); NF(lead(J),lead(J1)); NF(lead(J1),lead(J)); //Alex ring r5 = 32003,(x,y,z,t),dp; ideal I = 2t3xy2z+x2ty+2x2y, 2tz+y3x2t+z2t3y2x; option(prot); printlevel =1; ideal J1 = std(I); int tt = timer; ideal J = standard(I); timer -tt; //15sec product criterion: 0 chain criterion: 12 NF(lead(J),lead(J1)); NF(lead(J1),lead(J)); ring r6 = 32003,(x,y,z,t),dp; //is already SB for ds, for dp too long ideal I= 9x8+y7t3z4+5x4y2t2+2xy2z3t2, 9y8+7xy6t+2x5y4t2+2x2yz3t2, 9z8+3x2y3z2t4; option(prot); int tt = timer; ideal J = standard(I); timer -tt; //0sec, product criterion: 3 chain criterion: 0 ideal J1 = std(I); NF(lead(J),lead(J1)); NF(lead(J1),lead(J)); */ singular-4.0.3+ds/Singular/LIB/template.lib000066400000000000000000000064551266270727000204640ustar00rootroot00000000000000//////////////////////////////////////////////////////////////// version="version template.lib 4.0.0.0 Jun_2013 "; // $Id: 8831501251e6607a4e30cef97bd72587addbf16f $ category="Miscellaneous"; // summary description of the library info=" LIBRARY: template.lib A Template for a Singular Library AUTHOR: Olaf Bachmann, email: obachman@mathematik.uni-kl.de SEE ALSO: standard_lib, Libraries, Typesetting of help and info strings KEYWORDS: library, template.lib; template.lib; library, info string PROCEDURES: mdouble(int) return double of int argument mtriple(int) return three times int argument msum([int,..,int]) sum of int arguments "; //////////////////////////////////////////////////////////////////// proc mdouble(int i) "USAGE: mdouble(i); i int RETURN: int: i+i NOTE: Help string is in pure ASCII. This line starts on a new line since previous line is short. No new line here. SEE ALSO: msum, mtriple, Typesetting of help and info strings KEYWORDS: procedure, ASCII help EXAMPLE: example mdouble; shows an example" { return (i + i); } example { "EXAMPLE:"; echo = 2; mdouble(0); mdouble(-1); } //////////////////////////////////////////////////////////////////// proc mtriple(int i) "@c we do texinfo here @table @asis @item @strong{Usage:} @code{mtriple(i)}; @code{i} int @item @strong{Return:} int: @math{i+i+i} @item @strong{Note:} Help is in pure Texinfo. @*This help string is written in texinfo, which enables you to use, among others, the @@math command for mathematical typesetting (for instance, to print @math{\alpha, \beta}). @*Texinfo also gives more control over the layout, but is, admittingly, more cumbersome to write. @end table @c use @c ref contstuct for references @cindex procedure, texinfo help @c ref @strong{See also:} @ref{mdouble}, @ref{msum}, @ref{Typesetting of help and info strings} @c ref " { return (i + i + i); } example { "EXAMPLE:"; echo = 2; mtriple(0); mtriple(-1); } //////////////////////////////////////////////////////////////////// proc msum(list #) "USAGE: msum([i_1,..,i_n]); @code{i_1,..,i_n} def RETURN: Sum of int arguments NOTE: This help string is written in a mixture of ASCII and texinfo. @* Use @ref for references (e.g., @pxref{mtriple}). @* Use @code for typewriter font (e.g., @code{i_1}). @* Use @math for simple math mode typesetting (e.g., @math{i_1}). @* Warning: Parenthesis like } are not allowed inside @math and @code. @* Use @example for indented, preformatted text typesetting in typewriter font: @example this --> that @end example Use @format for preformatted text typesetting in normal font: @format this --> that @end format Use @texinfo for text in pure texinfo: @texinfo @expansion{} @tex $i_{1,1}$ @end tex @end texinfo Note that automatic linebreaking is still in affect (like in this line). SEE ALSO: mdouble, mtriple, Typesetting of help and info strings KEYWORDS: procedure, ASCII/Texinfo help EXAMPLE: example msum; shows an example" { if (size(#) == 0) { return (0);} if (size(#) == 1) { return (#[1]);} int i; def s = #[1]; for (i=2; i<=size(#); i++) { s = s + #[i]; } return (s); } example { "EXAMPLE:"; echo = 2; msum(); msum(4); msum(1,2,3,4); } singular-4.0.3+ds/Singular/LIB/toric.lib000066400000000000000000000665611266270727000177750ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////// version="version toric.lib 4.0.0.0 Jun_2013 "; // $Id: 44e022afa582b7932c0f81c814395695cf47d67f $ category="Commutative Algebra"; info=" LIBRARY: toric.lib Standard Basis of Toric Ideals AUTHOR: Christine Theis, email: ctheis@math.uni-sb.de PROCEDURES: toric_ideal(A,..); computes the toric ideal of A toric_std(ideal I); standard basis of I by a specialized Buchberger algorithm "; /////////////////////////////////////////////////////////////////////////////// static proc toric_ideal_1(intmat A, string alg) { ideal I; // to be returned // check suitability of actual basering if(nvars(basering)0) { break; } } if(found==0) { close(MATRIX); dummy=system("sh","rm -f "+matrixfile); ERROR("The chosen algorithm needs a positive vector in the row space of the matrix."); } write(MATRIX,"positive row space vector:"); for(j=1;j<=ncols(A);j++) { write(MATRIX,A[found,j]); } } close(MATRIX); // call external program dummy=system("sh","toric_ideal -alg "+alg+" "+matrixfile); if (dummy!=0) { ERROR("toric_ideal failed with error code "+string(dummy)); } // read toric ideal from created file link TORIC_IDEAL=":r "+matrixfile+".GB."+alg; string toric_id=read(TORIC_IDEAL); int generators; pos=find(toric_id,"size"); pos=find(toric_id,":",pos); pos++; while(toric_id[pos]==" " || toric_id[pos]==newline) { pos++; } number_string=""; while(toric_id[pos]!=" " && toric_id[pos]!=newline) { number_string=number_string+toric_id[pos]; pos++; } execute("generators="+number_string+";"); intvec v; poly head; poly tail; pos=find(toric_id,"basis"); pos=find(toric_id,":",pos); pos++; for(i=1;i<=generators;i++) { head=1; tail=1; for(j=1;j<=ncols(A);j++) { while(toric_id[pos]==" " || toric_id[pos]==newline) { pos++; } number_string=""; while(toric_id[pos]!=" " && toric_id[pos]!=newline) { number_string=number_string+toric_id[pos]; pos++; } execute("v[j]="+number_string+";"); if(v[j]<0) { tail=tail*var(j)^(-v[j]); } if(v[j]>0) { head=head*var(j)^v[j]; } } I[i]=head-tail; } // delete all created files dummy=system("sh","rm -f "+matrixfile); dummy=system("sh","rm -f "+matrixfile+".GB."+alg); return(I); } /////////////////////////////////////////////////////////////////////////////// static proc toric_ideal_2(intmat A, string alg, intvec prsv) { ideal I; // to be returned // check arguments if(size(prsv)0) { head=head*var(j)^v[j]; } } I[i]=head-tail; } // delete all created files dummy=system("sh","rm -f "+matrixfile); dummy=system("sh","rm -f "+matrixfile+".GB."+alg); return(I); } /////////////////////////////////////////////////////////////////////////////// proc toric_ideal "USAGE: toric_ideal(A,alg); A intmat, alg string toric_ideal(A,alg,prsv); A intmat, alg string, prsv intvec RETURN: ideal: standard basis of the toric ideal of A NOTE: These procedures return the standard basis of the toric ideal of A with respect to the term ordering in the current basering. Not all term orderings are supported: The usual global term orderings may be used, but no block orderings combining them. One may call the procedure with several different algorithms: @* - the algorithm of Conti/Traverso using elimination (ect), @* - the algorithm of Pottier (pt), - an algorithm of Bigatti/La Scala/Robbiano (blr), - the algorithm of Hosten/Sturmfels (hs), - the algorithm of DiBiase/Urbanke (du). The argument `alg' should be the abbreviation for an algorithm as above: ect, pt, blr, hs or du. If `alg' is chosen to be `blr' or `hs', the algorithm needs a vector with positive coefficients in the row space of A. If no row of A contains only positive entries, one has to use the second version of toric_ideal which takes such a vector as its third argument. For the mathematical background, see @texinfo @ref{Toric ideals and integer programming}. @end texinfo EXAMPLE: example toric_ideal; shows an example SEE ALSO: toric_std, toric_lib, intprog_lib, Toric ideals " { if(size(#)==2) { return(toric_ideal_1(#[1],#[2])); } else { return(toric_ideal_2(#[1],#[2],#[3])); } } example { "EXAMPLE"; echo=2; ring r=0,(x,y,z),dp; // call with two arguments intmat A[2][3]=1,1,0,0,1,1; A; ideal I=toric_ideal(A,"du"); I; I=toric_ideal(A,"blr"); I; // call with three arguments intvec prsv=1,2,1; I=toric_ideal(A,"blr",prsv); I; } /////////////////////////////////////////////////////////////////////////////// proc toric_std(ideal I) "USAGE: toric_std(I); I ideal RETURN: ideal: standard basis of I NOTE: This procedure computes the standard basis of I using a specialized Buchberger algorithm. The generating system by which I is given has to consist of binomials of the form x^u-x^v. There is no real check if I is toric. If I is generated by binomials of the above form, but not toric, toric_std computes an ideal `between' I and its saturation with respect to all variables. For the mathematical background, see @texinfo @ref{Toric ideals and integer programming}. @end texinfo EXAMPLE: example toric_std; shows an example SEE ALSO: toric_ideal, toric_lib, intprog_lib, Toric ideals " { ideal J; // to be returned // check suitability of actual term ordering // the "module ordering" c or C is ignored string singular_ord=ordstr(basering); string test_ord; string external_ord=""; int i,j; intvec weightvec; if(find(singular_ord,"lp")==1) { external_ord="W_LEX"; for(i=1;i<=nvars(basering);i++) { weightvec[i]=0; } test_ord="lp("+string(nvars(basering))+"),"; if(singular_ord!=(test_ord+"C") && singular_ord!=(test_ord+"c")) { "Warning: Block orderings are not supported; lp used for computation."; } } if(external_ord=="" && find(singular_ord,"lp")==3) { external_ord="W_LEX"; for(i=1;i<=nvars(basering);i++) { weightvec[i]=0; } test_ord="lp("+string(nvars(basering))+"),"; if(singular_ord!=("C"+test_ord) && singular_ord!=("c"+test_ord)) { "Warning: Block orderings are not supported; lp used for computation."; } } if(external_ord=="" && find(singular_ord,"dp")==1) { external_ord="W_REV_LEX"; for(i=1;i<=nvars(basering);i++) { weightvec[i]=1; } test_ord="dp("+string(nvars(basering))+"),"; if(singular_ord!=(test_ord+"C") && singular_ord!=(test_ord+"c")) { "Warning: Block orderings are not supported; dp used for computation."; } } if(external_ord=="" && find(singular_ord,"dp")==3) { external_ord="W_REV_LEX"; for(i=1;i<=nvars(basering);i++) { weightvec[i]=1; } test_ord="dp("+string(nvars(basering))+"),"; if(singular_ord!=("C"+test_ord) && singular_ord!=("c"+test_ord)) { "Warning: Block orderings are not supported; dp used for computation."; } } if(external_ord=="" && find(singular_ord,"Dp")==1) { external_ord="W_LEX"; for(i=1;i<=nvars(basering);i++) { weightvec[i]=1; } test_ord="Dp("+string(nvars(basering))+"),"; if(singular_ord!=(test_ord+"C") && singular_ord!=(test_ord+"c")) { "Warning: Block orderings are not supported; Dp used for computation."; } } if(external_ord=="" && find(singular_ord,"Dp")==3) { external_ord="W_LEX"; for(i=1;i<=nvars(basering);i++) { weightvec[i]=1; } test_ord="Dp("+string(nvars(basering))+"),"; if(singular_ord!=("C"+test_ord) && singular_ord!=("c"+test_ord)) { "Warning: Block orderings are not supported; Dp used for computation."; } } int pos; string number_string; if(external_ord=="" && find(singular_ord,"wp")==1) { external_ord="W_REV_LEX"; pos=3; for(i=1;i<=nvars(basering);i++) { pos++; number_string=""; while(singular_ord[pos]!="," && singular_ord[pos]!=")") { number_string=number_string+singular_ord[pos]; pos++; } execute("weightvec["+string(i)+"]="+number_string+";"); } test_ord="wp("+string(weightvec)+"),"; if(singular_ord!=(test_ord+"C") && singular_ord!=(test_ord+"c")) { "Warning: Block orderings are not supported; wp("+string(weightvec)+") used for computation."; } } if(external_ord=="" && find(singular_ord,"wp")==3) { external_ord="W_REV_LEX"; pos=5; for(i=1;i<=nvars(basering);i++) { pos++; number_string=""; while(singular_ord[pos]!=",") { number_string=number_string+singular_ord[pos]; pos++; } execute("weightvec[i]="+number_string); } test_ord="wp("+string(weightvec)+"),"; if(singular_ord!=("C"+test_ord) && singular_ord!=("c"+test_ord)) { "Warning: Block orderings are not supported; wp("+string(weightvec)+") used for computation."; } } if(external_ord=="" && find(singular_ord,"Wp")==1) { external_ord="W_LEX"; pos=3; for(i=1;i<=nvars(basering);i++) { pos++; number_string=""; while(singular_ord[pos]!=",") { number_string=number_string+singular_ord[pos]; pos++; } execute("weightvec[i]="+number_string); } test_ord="Wp("+string(weightvec)+"),"; if(singular_ord!=(test_ord+"C") && singular_ord!=(test_ord+"c")) { "Warning: Block orderings are not supported; Wp("+string(weightvec)+") used for computation."; } } if(external_ord=="" && find(singular_ord,"Wp")==3) { external_ord="W_LEX"; pos=5; for(i=1;i<=nvars(basering);i++) { pos++; number_string=""; while(singular_ord[pos]!=",") { number_string=number_string+singular_ord[pos]; pos++; } execute("weightvec[i]="+number_string); } test_ord="Wp("+string(weightvec)+"),"; if(singular_ord!=("C"+test_ord) && singular_ord!=("c"+test_ord)) { "Warning: Block orderings are not supported; Wp("+string(weightvec)+") used for computation."; } } if(external_ord=="") { ERROR("The term ordering of the actual basering is not supported."); } // create first temporary file with which the external program is called int dummy; int process=system("pid"); string groebnerfile="temp_GROEBNER"+string(process); link GROEBNER=":w "+groebnerfile; open(GROEBNER); write(GROEBNER,"GROEBNER","computed with algorithm:","pt","term ordering:","elimination block",0,"weighted block",nvars(basering),external_ord); // algorithm is totally unimportant, only required by the external program for(i=1;i<=nvars(basering);i++) { write(GROEBNER,weightvec[i]); } write(GROEBNER,"size:",size(I),"Groebner basis:"); poly head; poly tail; poly rest; intvec v; for(j=1;j<=size(I);j++) { // test suitability of generator j rest=I[j]; head=lead(rest); rest=rest-head; tail=lead(rest); rest=rest-tail; if(head==0 && tail==0 && rest!=0) { close(GROEBNER); dummy=system("sh","rm -f "+groebnerfile); ERROR("Generator "+string(j)+" of the input ideal is no binomial."); } if(leadcoef(tail)!=-leadcoef(head)) // generator is no difference of monomials (or a constant multiple) { close(GROEBNER); dummy=system("sh","rm -f "+groebnerfile); ERROR("Generator "+string(j)+" of the input ideal is no difference of monomials."); } if(gcd(head,tail)!=1) { "Warning: The monomials of generator "+string(j)+" of the input ideal are not relatively prime."; } // write vector representation of generator j into the file v=leadexp(head)-leadexp(tail); for(i=1;i<=nvars(basering);i++) { write(GROEBNER,v[i]); } } close(GROEBNER); // create second temporary file string newcostfile="temp_NEW_COST"+string(process); link NEW_COST=":w "+newcostfile; open(NEW_COST); write(NEW_COST,"NEW_COST","variables:",nvars(basering),"cost vector:"); for(i=1;i<=nvars(basering);i++) { write(NEW_COST,weightvec[i]); } // call external program dummy=system("sh","change_cost "+groebnerfile+" "+newcostfile); if (dummy!=0) { ERROR("change_cost failed with error code "+string(dummy)); } // read toric standard basis from created file link TORIC_IDEAL=":r "+newcostfile+".GB.pt"; string toric_id=read(TORIC_IDEAL); int generators; pos=find(toric_id,"size"); pos=find(toric_id,":",pos); pos++; while(toric_id[pos]==" " || toric_id[pos]==newline) { pos++; } number_string=""; while(toric_id[pos]!=" " && toric_id[pos]!=newline) { number_string=number_string+toric_id[pos]; pos++; } execute("generators="+number_string+";"); pos=find(toric_id,"basis"); pos=find(toric_id,":",pos); pos++; for(j=1;j<=generators;j++) { head=1; tail=1; for(i=1;i<=nvars(basering);i++) { while(toric_id[pos]==" " || toric_id[pos]==newline) { pos++; } number_string=""; while(toric_id[pos]!=" " && toric_id[pos]!=newline) { number_string=number_string+toric_id[pos]; pos++; } execute("v[i]="+number_string+";"); if(v[i]<0) { tail=tail*var(i)^(-v[i]); } if(v[i]>0) { head=head*var(i)^v[i]; } } J[j]=head-tail; } // delete all created files dummy=system("sh","rm -f "+groebnerfile); dummy=system("sh","rm -f "+groebnerfile+".GB.pt"); dummy=system("sh","rm -f "+newcostfile); return(J); } example { "EXAMPLE"; echo=2; ring r=0,(x,y,z),wp(3,2,1); // call with toric ideal (of the matrix A=(1,1,1)) ideal I=x-y,x-z; ideal J=toric_std(I); J; // call with the same ideal, but badly chosen generators: // 1) not only binomials I=x-y,2x-y-z; J=toric_std(I); // 2) binomials whose monomials are not relatively prime I=x-y,xy-yz,y-z; J=toric_std(I); J; // call with a non-toric ideal that seems to be toric I=x-yz,xy-z; J=toric_std(I); J; // comparison with real standard basis and saturation ideal H=std(I); H; LIB "elim.lib"; sat(H,xyz); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/triang.lib000066400000000000000000001070571266270727000201350ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////// version="version triang.lib 4.0.0.0 Jun_2013 "; // $Id: d3a64a08e30d940468862f5d76cace02f83800ad $ category="Symbolic-numerical solving"; info=" LIBRARY: triang.lib Decompose Zero-dimensional Ideals into Triangular Sets AUTHOR: D. Hillebrand PROCEDURES: triangL(G); Decomposition of (G) into triangular systems (Lazard). triangLfak(G); Decomp. of (G) into tri. systems plus factorization. triangM(G[,.]); Decomposition of (G) into triangular systems (Moeller). triangMH(G[,.]); Decomp. of (G) into tri. syst. with disjoint varieties. "; LIB "general.lib"; // Muss geladen werden fuer den Befehl sort(). LIB "elim.lib"; // Muss geladen werden fuer sat(). /////////////////////////////////////////////////////////////////////////////// // // Der Lazard-Algorithmus // /////////////////////////////////////////////////////////////////////////////// proc triangL (ideal G) "USAGE: triangL(G); G=ideal ASSUME: G is the reduced lexicographical Groebner basis of the zero-dimensional ideal (G), sorted by increasing leading terms. RETURN: a list of finitely many triangular systems, such that the union of their varieties equals the variety of (G). NOTE: Algorithm of Lazard (see: Lazard, D.: Solving zero-dimensional algebraic systems, J. Symb. Comp. 13, 117 - 132, 1992). EXAMPLE: example triangL; shows an example " { // Test, ob G Groebnerbasis eines nulldimensionalen Ideals ist. if (attrib(G,"isSB") <> 1) { ERROR("The input is no groebner basis."); } else { if (dim(G) <> 0) { ERROR("ideal is not zero-dimensional."); } } if (size(G) <= 2) // schon Dreiecksbasis { return(list(G)); } // Noetige Optionen setzen. // obachman: save options so that tey can be reset on exit intvec ovec = option(get); option(redSB); option(returnSB); list B; // Bearbeitungsliste list F; // Ergebnisliste = Triangulierung ideal T, T_neu; poly p,p_neu,r,s,lt,lc,lcr; list inv; int u,v; int l,h; string st; T = ideal(G[1]); attrib(T,"isSB",1); B = list(list(T,2)); while (size(B) > 0) { T = B[1][1]; h = B[1][2]; B = Listenrest(B); p = G[h]; v = lvar(p); lc = lcoef(p,v); st=string(nvars(basering)-v+1); dbprint(string(timer)+" S"+st+": invertiere Leitkoeffizient von G["+string(h)+"]."); // Invertiere den Leitkoeffizienten von G[h] bzgl. var(v) modulo (T). inv = invertieren(lc,T); dbprint(string(timer)+" S"+st+": Anzahl Dreiecksbasen: "+string(size(inv))+"."); while (size(inv) > 0) { r = inv[1][1]; s = inv[1][2]; T = inv[1][3]; inv = Listenrest(inv); if (r == 0) // r == 0?, dann p nicht der ggt der Stufe, { dbprint(string(timer)+" S"+st+": Leitkoeffizient == 0."); B = list(list(T,h+1)) + B; } else // ansonsten ggt der Stufe gefunden. { dbprint(string(timer)+" S"+st+": ggt gefunden."); lt = var(v)**degv(p,v); p_neu = cleardenom(s*lt + reduce(r*(p-lc*lt),T)); T_neu = T,p_neu; attrib(T_neu,"isSB",1); // Restlichen Polynome der gleichen Stufe uebergehen. for (l = h+1; l <= size(G); l++) { u = lvar(G[l]); if (u <> v) {break;} } // Durchsuche restliche Stufen nach trivialen ggt's. while (l <= size(G)) { lc = lcoef(G[l],u); lcr = reduce(lc,T_neu); while (lcr == 0) // Gehe bis zum ersten Polynom <> 0 { // modulo (T_neu). l++; lc = lcoef(G[l],u); lcr = reduce(lc,T_neu); } if (deg(lcr) == 0) // Polynom <> 0 normiert?, dann { // an Dreiecksbasis anhaengen, dbprint(string(timer)+" S"+string(nvars(basering)-u+1)+": Schnellerkennung: ggt gefunden."); lt = var(u)**degv(G[l],u); p_neu = cleardenom(lcr*lt + reduce(G[l]-lc*lt,T_neu)); T_neu = T_neu,p_neu; attrib(T_neu,"isSB",1); u = lvar(G[l]); l++; while (l <= size(G)) // Rest der Stufe uebergehen. { if (lvar(G[l]) <> u) {u = lvar(G[l]); break;} l++; } } else // sonst nicht normierte Polynome auf der Stufe. { break; } } if (l > size(G)) // Ende von G erreicht, dann Dreiecks- { // basis der Triangulierung gefunden, dbprint(string(timer)+" S"+st+": Dreiecksbasis der Triangulierung gefunden."); F = F + list(T_neu); } else // sonst T_neu,l erneut bearbeiten. { B = list(list(T_neu,l)) + B; } } } } option(set, ovec); return(F); } //-------------------------------- example ---------------------------------- example { "EXAMPLE:"; echo = 2; ring rC5 = 0,(e,d,c,b,a),lp; triangL(stdfglm(cyclic(5))); } /////////////////////////////////////////////////////////////////////////////// proc triangLfak (ideal G) "USAGE: triangLfak(G); G=ideal ASSUME: G is the reduced lexicographical Groebner basis of the zero-dimensional ideal (G), sorted by increasing leading terms. RETURN: a list of finitely many triangular systems, such that the union of their varieties equals the variety of (G). NOTE: Algorithm of Lazard with factorization (see: Lazard, D.: Solving zero-dimensional algebraic systems, J. Symb. Comp. 13, 117 - 132, 1992). REMARK: each polynomial of the triangular systems is factorized. EXAMPLE: example triangLfak; shows an example " { return(triangLbas(G,2)); } //-------------------------------- example ---------------------------------- example { "EXAMPLE:"; echo = 2; ring rC5 = 0,(e,d,c,b,a),lp; triangLfak(stdfglm(cyclic(5))); } /////////////////////////////////////////////////////////////////////////////// static proc triangLbas (ideal G, list #) "USAGE: triangLbas(G[,i]); G reduzierte lexikographische Groebnerbasis des nulldimensionalen Ideals (G), nach Leittermen aufsteigend sortiert, i = 1 oder 2 (ohne Angabe i = 1). RETURN: Triangulierung von (G). Ist i == 2, dann wird jedes Polynom der Dreiecksbasen der Triangulierung zusaetzlich faktorisiert. NOTE: Algorithmus von Lazard (siehe: Lazard, D.: Solving zero-dimensional algebraic systems, J. Symb. Comp., Bd. 13, S. 117 - 132, 1992). " { // Test, ob G Groebnerbasis eines nulldimensionalen Ideals ist. if (attrib(G,"isSB") <> 1) { ERROR("The input is no groebner basis."); } else { if (dim(G) <> 0) { ERROR("ideal is not zero-dimensional."); } } // Noetige Optionen setzen. // obachman: save options so that tey can be reset on exit intvec ovec = option(get); option(redSB); option(returnSB); // Faktorisierungsschalter setzen. int fak; if (size(#) > 0 && typeof(#[1]) == "int") { if (#[1] == 2) {fak = 1;} } if (size(G) <= 2) // schon Dreiecksbasis { list E; if (fak) { E = faktorisiere_DB(G); } else { E = list(G); } option(set, ovec); return(E); } list B; // Bearbeitungsliste list F; // Ergebnisliste = Triangulierung list T_neu; ideal T; poly p,p_neu,r,s,lt,lc; list inv; int v; int l,h; string st; // B initialisieren if (fak) { B = H_anhaengen(faktorisiere_letzten(G[1]),2); } else { T = ideal(G[1]); attrib(T,"isSB",1); B = list(list(T,2)); } while (size(B) > 0) { T = B[1][1]; h = B[1][2]; B = Listenrest(B); p = G[h]; v = lvar(p); lc = lcoef(p,v); st=string(nvars(basering)-v+1); dbprint(string(timer)+" S"+st+": invertiere Leitkoeffizient von G["+string(h)+"]."); // invertiere den Leitkoeffizienten von G[h] bzgl. var(v) modulo (T). inv = invertieren(lc,T); dbprint(string(timer)+" S"+st+": Anzahl Dreiecksbasen: "+string(size(inv))+"."); while (size(inv) > 0) { r = inv[1][1]; s = inv[1][2]; T = inv[1][3]; inv = Listenrest(inv); if (r == 0) // r == 0?, dann p nicht der ggt der Stufe, { dbprint(string(timer)+" S"+st+": Leitkoeffizient == 0."); B = list(list(T,h+1)) + B; } else // ansonsten ggt der Stufe gefunden. { dbprint(string(timer)+" S"+st+": ggt gefunden."); lt = var(v)**degv(p,v); p_neu = cleardenom(s*lt + reduce(r*(p-lc*lt),T)); if (fak) { T_neu = faktorisiere_letzten(list(T + p_neu)); } else { T_neu = list(T + p_neu); } // Restlichen Polynome der gleichen Stufe uebergehen. for (l = h+1; l <= size(G); l++) { if (lvar(G[l]) <> v) {break;} } if (l > size(G)) // Ende von G erreicht, dann Dreiecks- { // basis der Triangulierung gefunden, dbprint(string(timer)+" S"+st+": Dreiecksbasis der Triangulierung gefunden."); F = F + T_neu; } else // sonst T_neu,l erneut bearbeiten. { B = H_anhaengen(T_neu,l) + B; } } } } option(set, ovec); return(F); } /////////////////////////////////////////////////////////////////////////////// static proc invertieren (poly p, ideal T) "USAGE: invertieren(p,T); p Polynom, T reduzierte Dreiecksbasis. RETURN: Liste von Tripeln (Listen) bestehend aus einem Polynom ri, einem Element aus dem Grundring si, und einer reduzierten Dreiecksbasis Ti, i = 1,...,m, so dass [T1,...,Tm] eine Triangulierung von T ist und p = 0 mod (Ti) falls ri = 0, ansonsten ri*p = si mod (Ti) fuer i = 1,...,m. " { // Triviale Faelle vorweg behandeln. p = reduce(p,T); if (p == 0) {return(list(list(0,0,T)));} if (deg(p) == 0) {return(list(list(1,p,T)));} list inv; int zerlegt; // zerlegt ist Schalter dafuer, ob T zerlegt wurde, export zerlegt; // einzige globale Variable. list toSee = list(list(p,T)); // zu bearbeitende Paare list toSave; // Ergebnisliste poly pr; while (size(toSee) > 0) { zerlegt = 0; // zerlegt = FALSE p = toSee[1][1]; T = toSee[1][2]; toSee = Listenrest(toSee); // invertieren_oT aufrufen, um p+(T) zu invertieren. inv = invertieren_oT(p,T); if (zerlegt) // T zerlegt?, dann pro neuer Dreiecksbasis { // weiteruntersuchen, pr = reduce(p,inv[1]); if (pr == 0) // es sei denn p ist reduziert gleich 0, { toSave = list(list(0,0,inv[1])) + toSave; attrib(toSave[1][3],"isSB",1); } else { toSee = list(list(pr,inv[1])) + toSee; attrib(toSee[1][2],"isSB",1); } pr = reduce(p,inv[2]); if (pr == 0) { toSave = list(list(0,0,inv[2])) + toSave; attrib(toSave[1][3],"isSB",1); } else { toSee = list(list(pr,inv[2])) + toSee; attrib(toSee[1][2],"isSB",1); } } else // ansonsten Quasi-Inverses gefunden. { toSave = list(list(inv[1],inv[2],T)) + toSave; attrib(toSave[1][3],"isSB",1); } } kill zerlegt; return(toSave); } /////////////////////////////////////////////////////////////////////////////// static proc invertieren_oT (poly p, ideal T) "USAGE: invertieren_oT(p,T); T reduzierte Dreiecksbasis, p <> 0 Polynom, irreduzibel modulo (T). RETURN: Entweder ein Quasi-Inverses (r,s) von p modulo (T), d.h. r*p = s mod (T) und s im Grundring, oder eine Triangulierung [T1,T2] von T mit (Ti) <> (T) fuer i = 1,2. " { // Quasi-Inverses von Konstante klar. if (deg(p) == 0) {return(list(1,p));} ideal T_bis_k,T1,T2; poly g,a,b; list rq; list gab; int i; int v = lvar(p); int k = nvars(basering)-v+1; // Zu p passende Dreiecksbasis auswaehlen. if (k == 1) { T_bis_k = 0; } else { T_bis_k = T[1..(k-1)]; } attrib(T_bis_k,"isSB",1); // Um p+(T) zu invertieren, erw. eukl. Algorithmus anwenden. gab = Erw_ggt_oT(T[k],p,v,T_bis_k); // Entweder Triangulierung von T_bis_k erhalten, if (zerlegt) { // T[k..size(T)] an gab[i] anhaengen und reduzieren. T1 = gab[1]; T2 = gab[2]; for (i = k; i <= size(T); i++) { T1 = T1 + cleardenom(reduce(T[i],T1)); T2 = T2 + cleardenom(reduce(T[i],T2)); attrib(T1,"isSB",1); attrib(T2,"isSB",1); } return(list(T1,T2)); } // ansonsten gilt: a*T[k] + b*p = g mod (T_bis_k) g = gab[1]; a = gab[2]; b = gab[3]; if (degv(g,v) > 0) // Entweder echten Teiler von T[k] gefunden, { // dann splitte T, rq = pdiv(T[k],g,v); T1 = T_bis_k; T1[k] = cleardenom(reduce(g,T1)); attrib(T1,"isSB",1); T2 = T_bis_k; T2[k] = cleardenom(reduce(rq[2],T2)); attrib(T2,"isSB",1); // T[k..size(T)] an T1, T2 anhaengen und reduzieren. for (i = k + 1; i <= size(T); i++) { T1 = T1 + cleardenom(reduce(T[i],T1)); T2 = T2 + cleardenom(reduce(T[i],T2)); attrib(T1,"isSB",1); attrib(T2,"isSB",1); } // zerlegt = TRUE, hier ist einzige Stelle, wo T zerlegt wird. zerlegt = 1; return(list(T1,T2)); } else // ansonsten Quasi-Inverses gefunden. { return(list(b,g)); } } /////////////////////////////////////////////////////////////////////////////// static proc Erw_ggt_oT (poly f, poly g, int v, ideal T) "USAGE: Erw_ggt_oT(f,g,v,T); f,g Polynome in var(v), f > g, T Dreiecksbasis mit groesster Variable var(v+1). RETURN: Liste aus drei Polynomen d,a,b, wobei a * f + b * g = d mod (T) und (d + (T)) = ((f + (T), g + (T)). NOTE: Dies ist der erweiterte euklidische Algorithmus im Polynom- ring ueber dem Restklassenring modulo (T) in der Unbestimmten var(v). Zusaetzlich wird jeweils der Dividend so normiert, dass der Leitkoeffizient bzgl. var(v) im Grundring ist und die Leikoeffizienten werden durch Anwendung der Subresultant-remainder-sequence Variante des euklidischen Algorithmus moeglichst klein gehalten. " { // Initialisierung fuer erw. eukl. Algorithmus. poly p1 = f; poly p2 = g; poly a1 = 1; poly a2 = 0; poly b1 = 0; poly b2 = 1; // Normierung des Dividenden. list pab = normieren_oT(p2,a2,b2,v,T); if (zerlegt) {return(pab);} p2 = pab[1]; a2 = pab[2]; b2 = pab[3]; poly p3,a3,b3,q; // Hilfspolynome list rq; // Rueckgabelisten der Fkten pdiv und normieren_oT vector clden; // Variablen fuer Subresultanten-Variante initialisieren. int delta = degv(p1,v)-degv(p2,v); number alpha; number beta = (-1)**(delta + 1); number psi = -1; number m; // Pseudodivision rq = pdiv(p1,p2,v); q = rq[2]; p3 = reduce(rq[1],T); while (p3 <> 0) // Hauptschleife des eukl. Algorithmus. { alpha = number(lcoef(p2,v)); // return von lcoef ist type poly m = alpha**(delta + 1); //m*p1 = q*p2 + p3 mod (T) p3 = p3 / beta; //m*p1 = q*p2 + beta * p3 mod (T) // a und b anpassen. q = reduce(q,T); a3 = reduce(m*a1 - q*a2,T); b3 = reduce(m*b1 - q*b2,T); a3 = a3 / beta; b3 = b3 / beta; // Variablen tauschen. p1 = p2; p2 = p3; a1 = a2; a2 = a3; b1 = b2; b2 = b3; // Normierung des Dividenden. pab = normieren_oT(p2,a2,b2,v,T); if (zerlegt) {return(pab);} p2 = pab[1]; a2 = pab[2]; b2 = pab[3]; if (degv(p2,v) > 0) // Dividend aus Grundring?, dann { // Subresultanten-Variabeln anpassen if (delta > 0) { psi = ((-alpha)**delta) / (psi**(delta-1)); } delta = degv(p1,v)-degv(p2,v); beta = (-alpha) * (psi**delta); rq = pdiv(p1,p2,v); // und Pseudodivision, q = rq[2]; p3 = reduce(rq[1], T); } else // ansonsten Ende. { p3 = 0; } } // Gemeinsame Teiler herausdividieren. clden = cleardenom([p2,a2,b2]); return(list(clden[1],clden[2],clden[3])); } /////////////////////////////////////////////////////////////////////////////// static proc normieren_oT (poly p, poly a, poly b, int v, ideal T) "USAGE: normieren_oT(p,a,b,v,T); p,a,b Polynome in var(v), T Dreiecksbasis. RETURN: Entweder Triangulierung [T1,T2] von (T) oder Liste,wobei [1] = reduce(r*p,T), [2] = reduce(r*a,T), [3] = reduce(r*b,T), und reduce(r*lcoef(p,v),T) ist im Grundring. " { poly lc = lcoef(p,v); if (deg(lc) == 0) {return(list(p,a,b));} // lc im Grundring lc = cleardenom(lc); // invertieren_oT aufrufen, um lc+(T) zu invertieren. list inv = invertieren_oT(lc,T); if (zerlegt) {return(inv);} // ansonsten Polynom zurueck gekommen. p = reduce(inv[1] * p,T); a = reduce(inv[1] * a,T); b = reduce(inv[1] * b,T); return(list(p,a,b)); } /////////////////////////////////////////////////////////////////////////////// // // Der Moeller-Algorithmus // /////////////////////////////////////////////////////////////////////////////// proc triangM (ideal G, list #) "USAGE: triangM(G[,i]); G=ideal, i=integer,@* ASSUME: G is the reduced lexicographical Groebner basis of the zero-dimensional ideal (G), sorted by increasing leading terms. RETURN: a list of finitely many triangular systems, such that the union of their varieties equals the variety of (G). If i = 2, then each polynomial of the triangular systems is factorized. NOTE: Algorithm of Moeller (see: Moeller, H.M.: On decomposing systems of polynomial equations with finitely many solutions, Appl. Algebra Eng. Commun. Comput. 4, 217 - 230, 1993). EXAMPLE: example triangM; shows an example " { // Test, ob G Groebnerbasis ist. if (attrib(G,"isSB") <> 1) { ERROR("The input is no groebner basis."); } // Faktorisierungsschalter setzen. int fak; if (size(#) > 0 && typeof(#[1]) == "int") { if (#[1] == 2) {fak = 1;} } // Noetige Optionen setzen. // obachman: save options so that they can be reset on exit intvec ovec = option(get); option(redSB); option(returnSB); list F,Fh; // Ergebnislisten int nG = size(G); if (nG <= 2) // G schon Dreiecksbasis? { if (fak) { F = faktorisiere_DB(G); } else { F = list(G); } option(set, ovec); return(F); } int u = lvar(G[nG-1]); int v = lvar(G[nG]); int m = nG; int l; ideal lc,G1,G2,H; poly lcr; int i,j,k; string s = string(nvars(basering)-v+1); // fuer Protokoll // Oberes Dreieckssytem abschneiden. while(u <> v) { m = m-1; if (m == 2) // G ist bereits Dreiecksbasis. { if (fak) { F = faktorisiere_DB(G); } else { F = list(G); } option(set, ovec); return (F); } v = u; u = lvar(G[m-1]); } // Leitkoeffizienten der Polynome bzgl. var(u) bestimmen. l = m-1; while(u == v) { lc = lc + lcoef(G[l],u); l = l - 1; u = lvar(G[l]); } // Erster Teil des Splitts. G1 = sort_red(ideal(G[1..l]) + lc); // Sortiere und reduziere GB. s = string(nvars(basering)-v+1); dbprint(string(timer)+" S"+s+": Erster Teil des Splitts."); // Rekursiver Aufruf, um G1 zu triangulieren. F = triangM(G1,#); dbprint(string(timer)+" S"+s+": Oberes Dreieckssystem anhaengen."); // Oberes Dreieckssystem an jede berechnete Dreiecksbasis anhaengen. for (j = m; j <= nG; j++) // meist nur j = m = nG { for (i = 1; i <= size(F); i++) { F[i] = F[i] + cleardenom(G[j][1] + reduce(G[j]-G[j][1],F[i])); attrib(F[i],"isSB",1); } if (fak) { F = faktorisiere_letzten(F); } } dbprint(string(timer)+" S"+s+": Zweiter Teil des Splitts, "+string(m-l-1)+" Leitkoeffizient(en)."); // Zweiten Teil des Splitts berechnen. H = ideal(G[1..m]); attrib(H,"isSB",1); for (k = m-l-1; k >= 1; k--) // Leitkoeffizientenliste durchgehen, { // angefangen mit lc des kleinsten Polynoms. lcr = reduce(lc[k],H); if (lcr <> 0) // d.h. (H):lcr <> (1) { dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Berechnung Idealquotient."); G2 = quotient(H,lcr); // Wg. Option returnSB schon Standardbasis. attrib(G2,"isSB",1); dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Rekursiver Aufruf."); // Rekursiver Aufruf, um G2 zu triangulieren. Fh = triangM(G2,#); dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Oberes Dreieckssystem, falls vorhanden, anhaengen."); // Oberes Dreieckssystem, falls vorhanden, // an jede berechnete Dreiecksbasis anhaengen. for (j = m + 1; j <= nG; j++) { for (i = 1; i <= size(Fh); i++) { Fh[i] = Fh[i] + cleardenom(G[j][1] + reduce(G[j]-G[j][1],Fh[i])); attrib(Fh[i],"isSB",1); } if (fak) { Fh = faktorisiere_letzten(Fh); } } F = F + Fh; if (k > 1) { dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Lex. GB von (H + lc) berechnen, naechsten lc reduzieren."); H = std(H + lcr); // Wg. reduce(...,H) oben notwendig. } } else { dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Leere Varietaet."); } } // Singular loescht die Attribute beim Listenverketten, deswegen neu setzen. for (i = 1; i <= size(F); i++) { attrib(F[i],"isSB",1); } option(set, ovec); return(F); } //-------------------------------- example---------------------------------- example { "EXAMPLE:"; echo = 2; ring rC5 = 0,(e,d,c,b,a),lp; triangM(stdfglm(cyclic(5))); //oder: triangM(stdfglm(cyclic(5)),2); } /////////////////////////////////////////////////////////////////////////////// proc triangMH (ideal G, list #) "USAGE: triangMH(G[,i]); G=ideal, i=integer ASSUME: G is the reduced lexicographical Groebner basis of the zero-dimensional ideal (G), sorted by increasing leading terms. RETURN: a list of finitely many triangular systems, such that the disjoint union of their varieties equals the variety of (G). If i = 2, then each polynomial of the triangular systems is factorized. NOTE: Algorithm of Moeller and Hillebrand (see: Moeller, H.M.: On decomposing systems of polynomial equations with finitely many solutions, Appl. Algebra Eng. Commun. Comput. 4, 217 - 230, 1993 and Hillebrand, D.: Triangulierung nulldimensionaler Ideale - Implementierung und Vergleich zweier Algorithmen, master thesis, Universitaet Dortmund, Fachbereich Mathematik, Prof. Dr. H.M. Moeller, 1999). EXAMPLE: example triangMH; shows an example " { // Test, ob G Groebnerbasis ist. if (attrib(G,"isSB") <> 1) { ERROR("The input is no groebner basis."); } if(npars(basering)<>0) { ERROR("basering has parameters"); } // Faktorisierungsschalter setzen. int fak; if (size(#) > 0 && typeof(#[1]) == "int") { if (#[1] == 2) {fak = 1;} } // Noetige Optionen setzen. // obachman: save options so that tey can be reset on exit intvec ovec = option(get); option(redSB); option(redTail); option(returnSB); list F,Fh; // Ergebnislisten int nG = size(G); if (nG <= 2) // G schon Dreiecksbasis? { if (fak) { F = faktorisiere_DB(G); } else { F = list(G); } option(set, ovec); return(F); } int u = lvar(G[nG-1]); int v = lvar(G[nG]); int m = nG; int l; poly lcr; ideal lc,G1,G2,H; int i,j,k; string s = string(nvars(basering)-v+1); // fuer Protokoll // Oberes Dreieckssytem abschneiden. while(u <> v) { m = m-1; if (m == 2) // G ist Dreiecksbasis. { if (fak) { F = faktorisiere_DB(G); } else { F = list(G); } option(set, ovec); return(F); } v = u; u = lvar(G[m-1]); } // Leitkoeffizienten der Polynome bzgl. var(u) bestimmen. l = m-1; while(u == v) { lc = lc + lcoef(G[l],u); l = l - 1; u = lvar(G[l]); } // Erster Teil des Splitts. G1 = sort_red(ideal(G[1..l]) + lc); // Sortiere und reduziere GB. s = string(nvars(basering)-v+1); dbprint(string(timer)+" S"+s+": Erster Teil des Splitts."); // Rekursiver Aufruf, um G1 zu triangulieren. F = triangMH(G1,#); dbprint(string(timer)+" S"+s+": Oberes Dreieckssystem anhaengen."); // Oberes Dreieckssystem an jede berechnete Dreiecksbasis anhaengen. for (j = m; j <= nG; j++) // meist nur j = m = nG { for (i = 1; i <= size(F); i++) { F[i] = F[i] + cleardenom(G[j][1] + reduce(G[j]-G[j][1],F[i])); attrib(F[i],"isSB",1); } if (fak) { F = faktorisiere_letzten(F); } } dbprint(string(timer)+" S"+s+": Zweiter Teil des Splitts, "+string(m-l-1)+" Leitkoeffizient(en)."); // Zweiten Teil des Splitts berechnen. H = ideal(G[1..l]); // Nur die Polynome in var(u). attrib(H,"isSB",1); for (k = m-l-1; k >= 1; k--) // Leitkoeffizientenliste durchgehen, { // angefangen mit lc des kleinsten Polynoms. lcr = reduce(lc[k],H); if (lcr <> 0) // d.h. (H):lcr <> (1) { dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Berechnung Saturation."); G2 = sat(H,lcr)[1]; // Saturation statt Idealquotient. attrib(G2,"isSB",1); if (G2[1] <> 1) { dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Rekursiver Aufruf."); // Rekursiver Aufruf, um G2 zu triangulieren. Fh = triangMH(G2,#); dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Ggt und oberes Dreieckssystem anhaengen."); // Ggt an jede Dreiecksbasis anhaengen. for (i = 1; i <= size(Fh); i++) { Fh[i] = std(Fh[i] + G[m-k]); } if (fak) { Fh = faktorisiere_letzten(Fh); } for (j = m+1; j <= nG; j++) // oberes Dreieckssystem an jede { // berechnete Dreiecksbasis anhaengen for (i = 1; i <= size(Fh); i++) { Fh[i] = Fh[i] + cleardenom(G[j][1] + reduce(G[j]-G[j][1],Fh[i])); attrib(Fh[i],"isSB",1); } if (fak) { Fh = faktorisiere_letzten(Fh); } } F = F + Fh; } else { dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Leere Varietaet (G2 == (1))."); } if (k > 1) { dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Lex. GB von (H + lc) berechnen, naechsten lc reduzieren."); H = std(H + lcr); // wegen reduce(...,H) oben } } else { dbprint(string(timer)+" S"+s+"L"+string(m-l-k)+": Leere Varietaet (lcr == 0)."); } } // Singular loescht die Attribute beim Listenverketten, deswegen neu setzen. for (i = 1; i <= size(F); i++) { attrib(F[i],"isSB",1); } option(set, ovec); return(F); } //-------------------------------- example ---------------------------------- example { "EXAMPLE:"; echo = 2; ring rC5 = 0,(e,d,c,b,a),lp; triangMH(stdfglm(cyclic(5))); } /////////////////////////////////////////////////////////////////////////////// // // Hilfsfunktionen // /////////////////////////////////////////////////////////////////////////////// static proc sort_red (ideal G) "USAGE: sort_red(G); G lexikographische Groebnerbasis. RETURN: reduzierte lex. GB G, deren Elemente nach aufsteigenden Leittermen sortiert sind. " { int i; // sortieren G = sort(G)[1]; // reduzieren ideal Gred = cleardenom(G[1]); attrib(Gred,"isSB",1); for (i = 2; i <= size(G); i++) { Gred = Gred + cleardenom(reduce(G[i],Gred)); attrib(Gred,"isSB",1); } attrib(Gred,"isSB",1); return(Gred); } /////////////////////////////////////////////////////////////////////////////// static proc Listenrest (list Liste) "USAGE: Listenrest(Liste); Liste muss eine mindestens einelementige Liste sein (leere Liste ergibt Fehler). RETURN: Liste ohne das erste Element. " { return(delete(Liste,1)); } /////////////////////////////////////////////////////////////////////////////// static proc Idealrest (ideal i) "USAGE: Idealrest(i); i Ideal, i <> (0). RETURN: Ideal i ohne das erste Element bzw das Nullideal, falls i nur ein Erzeugendes besass. " { int ni = size(i); if (ni == 1) { return(ideal(0)); // Nullideal } return(ideal(i[2..ni])); } /////////////////////////////////////////////////////////////////////////////// static proc H_anhaengen (list L, int h) "USAGE: H_anhaengen(L,h); L Liste aus Idealen, h natuerliche Zahl. RETURN: Macht aus dem Listenelement i ein Paar [i,h] und setzt Attribut "isSB" fuer i. " { int i; list E; // Ergebnisliste for (i = 1; i <= size(L); i++) { E = E + list(list(L[i],h)); attrib(E[size(E)][1],"isSB",1); } return(E); } /////////////////////////////////////////////////////////////////////////////// static proc faktorisiere_letzten (list L) "USAGE: faktorisiere_letzten(L); L Liste aus Idealen. RETURN: Faktorisiert letztes Polynom aus jedem Ideal der Liste und zerlegt das Ideal entsprechend. Attribut "isSB" wird gesetzt. " { int i,j; ideal h; int nh; list factors; list E; // Ergebnisliste for (i = 1; i <= size(L); i++) { h = L[i]; nh = size(h); factors = factorize(h[nh],1); for (j = 1; j <= size(factors[1]); j++) { h[nh] = factors[1][j]; E = insert(E,h,size(E)); attrib(E[size(E)],"isSB",1); } } return(E); } /////////////////////////////////////////////////////////////////////////////// static proc faktorisiere_DB (ideal db) "USAGE: faktorisiere_DB(db); db reduzierte Dreiecksbasis. RETURN: Liste aus reduzierten Dreiecksbasen, die ensteht, indem, mit dem ersten beginnend, jedes Polynom der Dreiecksbasis faktorisiert wird. " { int i,j; poly h; list E = faktorisiere_letzten(db[1]); for (j = 2; j <= size(db); j++) { for (i = 1; i <= size(E); i++) { h = db[j][1] + reduce(db[j]-db[j][1],E[i]); E[i] = E[i] + h; } E = faktorisiere_letzten(E); } return(E); } /////////////////////////////////////////////////////////////////////////////// static proc degv (poly f, int v) "USAGE: degv(f,v); f Polynom in var(v). RETURN: Liefert den Grad von f bzgl. var(v) bzw -1, falls f == 0. " { if (f == 0) {return(-1);} return(size(coeffs(f,var(v))) - 1); } ////////////////////////////////////////////////////////////////////////////// static proc pdiv (poly f, poly g, int v) "USAGE: pdiv(f,g); f,g Polynome in var(v), f > g. RETURN: Liste, wobei [1] = prem(f,g) (Pseudoremainder), [2] = pquo(f,g) (Pseudoquotient). NOTE: Pseudodivision von f durch g. " { // Initialisierung poly q = 0; poly rem = f; int deg_g = degv(g,v); int deg_rem = degv(rem,v); poly lcg = lcoef(g,v); // Im Lazard-Algor. aus dem Grundring. poly h; rem = rem*lcg**(deg_rem - deg_g + 1); // f durch g teilbar machen. // Gewoehnliche Polynomdivision while (rem <> 0 and deg_rem >= deg_g) { h = (lcoef(rem,v)/lcg)*var(v)**(deg_rem - deg_g); q = q + h; rem = rem - h*g; deg_rem = degv(rem,v); } return(list(rem,q)); } ////////////////////////////////////////////////////////////////////////////// static proc lvar (poly f) "USAGE: lvar(f); f nicht-konstantes Polynom. RETURN: groesste Variable von f bzgl. der aktuellen Termordnung. " { int i = 1; intvec exp = leadexp(f); while (1) { if (exp[i] <> 0) {return(i);} i++; } } ////////////////////////////////////////////////////////////////////////////// static proc lcoef (poly f, int v) "USAGE: lcoef(f,v); f Polynom, var(v) Ringvariable. RETURN: Leitkoeffizient von f bzgl. var(v). " { matrix m = coeffs(f,var(v)); return(m[size(m),1]); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/tropical.lib000066400000000000000000011255401266270727000204640ustar00rootroot00000000000000// version="version tropical.lib 4.0.0.0 Dec_2013 "; category="Tropical Geometry"; info=" LIBRARY: tropical.lib Computations in Tropical Geometry AUTHORS: Anders Jensen Needergard, email: jensen@math.tu-berlin.de @* Hannah Markwig, email: hannah@uni-math.gwdg.de @* Thomas Markwig, email: keilen@mathematik.uni-kl.de WARNING: - tropicalLifting will only work with LINUX and if in addition gfan is installed. @*- drawTropicalCurve and drawTropicalNewtonSubdivision will only display the @* tropical curve with LINUX and if in addition latex and kghostview @* are installed. @*- For tropicalLifting in the definition of the basering the parameter t @* from the Puiseux series field C{{t}} must be defined as a variable, @* while for all other procedures it must be defined as a parameter. THEORY: Fix some base field K and a bunch of lattice points v0,...,vm in the integer lattice Z^n, then this defines a toric variety as the closure of (K*)^n in the projective space P^m, where the torus is embedded via the map sending a point x in (K*)^n to the point (x^v0,...,x^vm). The generic hyperplane sections are just the images of the hypersurfaces in (K*)^n defined by the polynomials f=a0*x^v0+...+am*x^vm=0. Some properties of these hypersurfaces can be studied via tropicalisation. For this we suppose that K=C{{t}} is the field of Puiseux series over the field of complex numbers (or any other field with a valuation into the real numbers). One associates to the hypersurface given by f=a0*x^v0+...+am*x^vm the tropical hypersurface defined by the tropicalisation trop(f)=min{val(a0)+,...,val(am)+}. Here, denotes the standard scalar product of the integer vector v in Z^n with the vector x=(x1,...,xn) of variables, so that trop(f) is a piecewise linear function on R^n. The corner locus of this function (i.e. the points at which the minimum is attained a least twice) is the tropical hypersurface defined by trop(f). The theorem of Newton-Kapranov states that this tropical hypersurface is the same as if one computes pointwise the valuation of the hypersurface given by f. The analogue holds true if one replaces one equation f by an ideal I. A constructive proof of the theorem is given by an adapted version of the Newton-Puiseux algorithm. The hard part is to find a point in the variety over C{{t}} which corresponds to a given point in the tropical variety. It is the purpose of this library to provide basic means to deal with tropical varieties. Of course we cannot represent the field of Puiseux series over C in its full strength, however, in order to compute interesting examples it will be sufficient to replace the complex numbers C by the rational numbers Q and to replace Puiseux series in t by rational functions in t, i.e. we replace C{{t}} by Q(t), or sometimes even by Q[t]. Note, that this in particular forbids rational exponents for the t's. Moreover, in @sc{Singular} no negative exponents of monomials are allowed, so that the integer vectors vi will have to have non-negative entries. Shifting all exponents by a fixed integer vector does not change the tropicalisation nor does it change the toric variety. Thus this does not cause any restriction. If, however, for some reason you prefer to work with general vi, then you have to pass right away to the tropicalisation of the equations, whereever this is allowed -- these are linear polynomials where the constant coefficient corresponds to the valuation of the original coefficient and where the non-constant coefficient correspond to the exponents of the monomials, thus they may be rational numbers respectively negative numbers: e.g. if f=t^{1/2}*x^{-2}*y^3+2t*x*y+4 then trop(f)=min{1/2-2x+3y,1+x+y,0}. The main tools provided in this library are as follows: @* - tropicalLifting implements the constructive proof of the Theorem of Newton-Kapranov and constructs a point in the variety over C{{t}} corresponding to a given point in the corresponding tropical variety associated to an ideal I; the generators of I have to be in the polynomial ring Q[t,x1,...,xn] considered as a subring of C{{t}}[x1,...,xn]; a solution will be constructed up to given order; note that several field extensions of Q might be necessary throughout the intermediate computations; the procedures use the external program gfan @* - puiseuxExpansion computes a Newton-Puiseux expansion of a plane curve singularity @* - drawTropicalCurve visualises a tropical plane curve either given by a polynomial in Q(t)[x,y] or by a list of linear polynomials of the form ax+by+c with a,b in Z and c in Q; latex must be installed on your computer @* - tropicalJInvariant computes the tropical j-invaiant of a tropical elliptic curve @* - jInvariant computes the j-invariant of an elliptic curve @* - weierstrassForm computes the Weierstrass form of an elliptic curve PROCEDURES FOR TROPICAL LIFTING: tropicalLifting() computes a point in the tropical variety displayTropicalLifting() displays the output of tropicalLifting puiseuxExpansion() computes a Newton-Puiseux expansion in the plane displayPuiseuxExpansion() displays the output of puiseuxExpansion PROCEDURES FOR DRAWING TROPICAL CURVES: tropicalCurve() computes a tropical curve and its Newton subdivision drawTropicalCurve() produces a post script image of a tropical curve drawNewtonSubdivision() produces a post script image of a Newton subdivision PROCEDURES FOR J-INVARIANTS: tropicalJInvariant() computes the tropical j-invariant of a tropical curve weierstrassForm() computes the Weierstrass form of a cubic polynomial jInvariant() computes the j-invariant of a cubic polynomial GENERAL PROCEDURES: conicWithTangents() computes a conic through five points with tangents tropicalise() computes the tropicalisation of a polynomial tropicaliseSet() computes the tropicalisation several polynomials tInitialForm() computes the tInitial form of a polynomial in Q[t,x_1,...,x_n] tInitialIdeal() computes the tInitial ideal of an ideal in Q[t,x_1,...,x_n] initialForm() computes the initial form of poly in Q[x_1,...,x_n] initialIdeal() computes the initial ideal of an ideal in Q[x_1,...,x_n] PROCEDURES FOR LATEX CONVERSION: texNumber() outputs the texcommand for the leading coefficient of poly texPolynomial() outputs the texcommand for the polynomial poly texMatrix() outputs the texcommand for the matrix texDrawBasic() embeds output of texDrawTropical in a texdraw environment texDrawTropical() computes the texdraw commands for a tropical curve texDrawNewtonSubdivision() computes texdraw commands for a Newton subdivision texDrawTriangulation() computes texdraw commands for a triangulation AUXILARY PROCEDURES: radicalMemberShip() checks radical membership tInitialFormPar() computes the t-initial form of poly in Q(t)[x_1,...,x_n] tInitialFormParMax() same as tInitialFormPar, but uses maximum solveTInitialFormPar() displays approximated solution of a 0-dim ideal detropicalise() computes the detropicalisation of a linear form tDetropicalise() computes the detropicalisation of a linear form dualConic() computes the dual of an affine plane conic parameterSubstitute() substitutes in the polynomial the parameter t by t^N tropicalSubst() makes certain substitutions in a tropical polynomial randomPolyInT() computes a polynomial with random coefficients cleanTmp() clears /tmp from files created by other procedures KEYWORDS: tropical curves; tropical polynomials "; /////////////////////////////////////////////////////////////////////////////// /// Auxilary Static Procedures in this Library /////////////////////////////////////////////////////////////////////////////// /// - phiOmega /// - cutdown /// - tropicalparametriseNoabs /// - findzeros /// - basictransformideal /// - testw /// - simplifyToOrder /// - scalarproduct /// - intvecdelete /// - invertorder /// - ordermaximalidealsNoabs /// - displaypoly /// - displaycoef /// - choosegfanvector /// - tropicalliftingresubstitute /// - tropicalparametrise /// - eliminatecomponents /// - findzerosAndBasictransform /// - ordermaximalideals /// - verticesTropicalCurve /// - bunchOfLines /// - clearintmat /// - sortintvec /// - sortintmat /// - intmatcoldelete /// - intmatconcat /// - minInIntvec /// - positionInList /// - sortlist /// - minInList /// - vergleiche /// - koeffizienten /// - minOfPolys /// - shorten /// - minOfStringDecimal /// - decimal /// - stringcontainment /// - stringdelete /// - stringinsert /// - texmonomial /// - texcoefficient /// - abs /// - findNonLoopVertex /// - coordinatechange /// - weierstrassFormOfACubic /// - weierstrassFormOfA4x2Curve /// - weierstrassFormOfA2x2Curve /// - jInvariantOfACubic /// - jInvariantOfA4x2Curve /// - jInvariantOfA2x2Curve /// - jInvariantOfAPuiseuxCubic ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// LIB "random.lib"; LIB "solve.lib"; LIB "poly.lib"; LIB "elim.lib"; LIB "linalg.lib"; LIB "polymake.lib"; LIB "primdec.lib"; LIB "absfact.lib"; LIB "hnoether.lib"; LIB "ring.lib"; ////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /// Procedures concerned with tropical parametrisation /////////////////////////////////////////////////////////////////////////////// proc tropicalLifting (ideal i,intvec w,int ordnung,list #) "USAGE: tropicalLifting(i,w,ord[,opt]); i ideal, w intvec, ord int, opt string ASSUME: - i is an ideal in Q[t,x_1,...,x_n], w=(w_0,w_1,...,w_n) and (w_1/w_0,...,w_n/w_0) is in the tropical variety of i, and ord is the order up to which a point in V(i) over Q{{t}} lying over (w_1/w_0,...,w_n/w_0) shall be computed; w_0 may NOT be ZERO @* - the basering should not have any parameters on its own and it should have a global monomial ordering, e.g. ring r=0,(t,x(1..n)),dp; @* - the first variable of the basering will be treated as the parameter t in the Puiseux series field @* - the optional parameter opt should be one or more strings among the following: @* 'isZeroDimensional' : the dimension i is zero (not to be checked); @* 'isPrime' : the ideal is prime over Q(t)[x_1,...,x_n] (not to be checked); @* 'isInTrop' : (w_1/w_0,...,w_n/w_0) is in the tropical variety (not to be checked); @* 'oldGfan' : uses gfan version 0.2.1 or less @* 'findAll' : find all solutions of a zero-dimensional ideal over (w_1/w_0,...,w_n/w_0) @* 'noAbs' : do NOT use absolute primary decomposition @* 'puiseux' : n=1 and i is generated by one equation @* 'noResubst' : avoids the computation of the resubstitution RETURN: IF THE OPTION 'findAll' WAS NOT SET THEN: @* list, containing one lifting of the given point (w_1/w_0,...,w_n/w_0) in the tropical variety of i to a point in V(i) over Puiseux series field up to the first ord terms; more precisely: @* IF THE OPTION 'noAbs' WAS NOT SET, THEN: @* l[1] = ring Q[a]/m[[t]] @* l[2] = int @* l[3] = intvec @* l[4] = list @* IF THE OPTION 'noAbs' WAS SET, THEN: @* l[1] = ring Q[X(1),...,X(k)]/m[[t]] @* l[2] = int @* l[3] = intvec @* l[4] = list @* l[5] = string @* IF THE OPITON 'findAll' WAS SET, THEN: @* list, containing ALL liftings of the given point ((w_1/w_0,...,w_n/w_0) in the tropical variety of i to a point in V(i) over Puiseux series field up to the first ord terms, if the ideal is zero-dimensional over Q{{t}}; more precisely, each entry of the list is a list l as computed if 'findAll' was NOT set @* WE NOW DESCRIBE THE LIST ENTRIES IF 'findAll' WAS NOT SET: @* - the ring l[1] contains an ideal LIFT, which contains a point in V(i) lying over w up to the first ord terms; @* - and if the integer l[2] is N then t has to be replaced by t^1/N in the lift, or alternatively replace t by t^N in the defining ideal @* - if the k+1st entry of l[3] is non-zero, then the kth component of LIFT has to be multiplied t^(-l[3][k]/l[3][1]) AFTER substituting t by t^1/N @* - unless the option 'noResubst' was set, the kth entry of list l[4] is a string which represents the kth generator of the ideal i where the coordinates have been replaced by the result of the lift; the t-order of the kth entry should in principle be larger than the t-degree of LIFT @* - if the option 'noAbs' was set, then the string in l[5] defines a maximal ideal in the field Q[X(1),...,X(k)], where X(1),...,X(k) are the parameters of the ring in l[1]; the basefield of the ring in l[1] should be considered modulo this ideal REMARK: - it is best to use the procedure displayTropicalLifting to display the result @* - the option 'findAll' cannot be used if 'noAbs' is set @* - if the parameter 'findAll' is set AND the ideal i is zero-dimensional in Q{{t}}[x_1,...,x_n] then ALL points in V(i) lying over w are computed up to order ord; if the ideal is not-zero dimenisonal, then only the points in the ideal after cutting down to dimension zero will be computed @* - the procedure requires that the program GFAN is installed on your computer; if you have GFAN version less than 0.3.0 then you must use the optional parameter 'oldGfan' @* - the procedure requires the @sc{Singular} procedure absPrimdecGTZ to be present in the package primdec.lib, unless the option 'noAbs' is set; but even if absPrimdecGTZ is present it might be necessary to set the option 'noAbs' in order to avoid the costly absolute primary decomposition; the side effect is that the field extension which is computed throughout the recursion might need more than one parameter to be described @* - since Q is infinite, the procedure finishes with probability one @* - you can call the procedure with Z/pZ as base field instead of Q, but there are some problems you should be aware of: @* + the Puiseux series field over the algebraic closure of Z/pZ is NOT algebraicall closed, and thus there may not exist a point in V(i) over the Puiseux series field with the desired valuation; so there is no chance that the procedure produced a sensible output - e.g. if i=tx^p-tx-1 @* + if the dimension of i over Z/pZ(t) is not zero the process of reduction to zero might not work if the characteristic is small and you are unlucky @* + the option 'noAbs' has to be used since absolute primary decomposition in @sc{Singular} only works in characteristic zero @* - the basefield should either be Q or Z/pZ for some prime p; field extensions will be computed if necessary; if you need parameters or field extensions from the beginning they should rather be simulated as variables possibly adding their relations to the ideal; the weights for the additional variables should be zero EXAMPLE: example tropicalLifting; shows an example" { // if the basering has parameters, then exit with an error message if (parstr(basering)!="") { ERROR("The procedure is not implemented for rings with parameters. See: help tropicalLifting; for more information"); } // in order to avoid unpleasent surprises with the names of the variables // we change to a ring where the variables have names t and x(1),...,x(n) def ALTERRING=basering; if (nvars(basering)==2) { execute("ring BASERING=("+charstr(ALTERRING)+"),(t,x(1)),("+ordstr(ALTERRING)+");"); } else { execute("ring BASERING=("+charstr(ALTERRING)+"),(t,x(1.."+string(nvars(ALTERRING)-1)+")),("+ordstr(ALTERRING)+");"); } map altphi=ALTERRING,maxideal(1); ideal i=altphi(i); int j,k,l,jj,kk; // index variables // work through the optionional parameters int isprime,iszerodim,isintrop,gfanold,findall,noabs,nogfan,noresubst,puiseux; for (j=1;j<=size(#);j++) { if (#[j]=="isZeroDimensional") { iszerodim=1; } if (#[j]=="isPrime") { isprime=1; } if (#[j]=="isInTrop") { isintrop=1; } if (#[j]=="oldGfan") { gfanold=1; } if (#[j]=="findAll") { findall=1; } if (#[j]=="noAbs") { noabs=1; } if (#[j]=="puiseux") { int puiseuxgood=0; // test, if the option puiseux makes sense, i.e. we are considering a plane curve if ((size(i)==1) and (nvars(basering)==2)) { puiseuxgood=1; } // the case, where the base field has a parameter and a minimal polynomial is // treated by an additional variable (which should be the last variable) // and an ideal containing the minimal polynomial as first entry if ((size(i)==2) and (nvars(basering)==3)) { // check if the first entry is the minimal polynomial poly mpcheck=i[1]; if (substitute(mpcheck,var(1),0,var(2),0)==mpcheck) { puiseuxgood=1; } kill mpcheck; } if (puiseuxgood==0) { ERROR("The option puiseux is not allowed for this ring. See: help tropicalLifting; for more information"); } puiseux=1; nogfan=1; // if puiseux is set, then gfan should not be used } // this option is not documented -- it prevents the execution of gfan and // just asks for wneu to be inserted -- it can be used to check problems // with the precedure without calling gfan, if wneu is know from previous // computations if (#[j]=="noGfan") { nogfan=1; } if (#[j]=="noResubst") { noresubst=1; } } // if the basering has characteristic not equal to zero, // then absolute factorisation // is not available, and thus we need the option noAbs /* if ((char(basering)!=0) and (noabs!=1)) { ERROR("If the characteristic is not zero the procedure should be called with option 'noAbs'"); } */ int N=1; // we are working with the variable t^1/N - the N may be changed // w_0 must be non-zero! if (w[1]==0) { Error("The first coordinate of your input w must be NON-ZERO, since it is a DENOMINATOR!"); } // if w_0<0, then replace w by -w, so that the "denominator" w_0 is positive if (w[1]<0) { w=-w; } intvec prew=w; // stores w for later reference // for our computations, w[1] represents the weight of t and this // should be -w_0 !!! w[1]=-w[1]; // if w_0!=-1 then replace t by t^-w_0 and w_0 by -1 if (w[1]<-1) { i=subst(i,t,t^(-w[1])); N=-w[1]; w[1]=-1; } // if some entry of w is positive, we have to make a transformation, // which moves it to something non-positive for (j=2;j<=nvars(basering);j++) { if (w[j]>0) { // transform x_j to t^(-w[j])*x_j in the ideal i i=phiOmega(i,j,w[j]); w[j]=0; } } prew[1]=prew[1]+w[1]; prew=prew-w; // this now contains the positive part of the original w, // but the original first comp. of w // pass to a ring which represents Q[t]_[x1,...,xn] // for this, unfortunately, t has to be the last variable !!! ideal variablen; for (j=2;j<=nvars(basering);j++) { variablen=variablen+var(j); } execute("ring GRUNDRING=("+charstr(basering)+"),("+string(variablen)+",t),(dp("+string(nvars(basering)-1)+"),lp(1));"); ideal variablen; for (j=1;j<=nvars(basering)-1;j++) { variablen=variablen+var(j); } map GRUNDPHI=BASERING,t,variablen; ideal i=GRUNDPHI(i); // compute the initial ideal of i and test if w is in the tropical // variety of i // - the last entry 1 only means that t is the last variable in the ring ideal ini=tInitialIdeal(i,w,1); if (isintrop==0) // test if w is in trop(i) only if isInTrop has not been set { poly product=1; for (j=1;j<=nvars(basering)-1;j++) { product=product*var(j); } if (radicalMemberShip(product,ini)==1) // if w is not in Trop(i) - error { ERROR("The integer vector is not in the tropical variety of the ideal."); } } // compute next the dimension of i in K(t)[x] and cut the ideal down to dim 0 if (iszerodim==0) // do so only if is_dim_zero is not set { execute("ring QUOTRING=("+charstr(basering)+",t),("+string(variablen)+"),dp;"); ideal i=groebner(imap(GRUNDRING,i)); int dd=dim(i); setring GRUNDRING; // if the dimension is not zero, we cut the ideal down to dimension zero // and compute the // t-initial ideal of the new ideal at the same time if(dd!=0) { // the procedurce cutdown computes a new ring, in which there lives a // zero-dimensional // ideal which has been computed by cutting down the input with // generic linear forms // of the type x_i1-p_1,...,x_id-p_d for some polynomials // p_1,...,p_d not depending // on the variables x_i1,...,x_id; that way we have reduced // the number of variables by dd !!! // the new zero-dimensional ideal is called i, its t-initial // ideal (with respect to // the new w=CUTDOWN[2]) is ini, and finally there is a list // repl in the ring // which contains at the polynomial p_j at position i_j and //a zero otherwise; if (isprime==0) // the minimal associated primes of i are computed { list CUTDOWN=cutdown(i,w,dd); } else // i is assumed to be prime { list CUTDOWN=cutdown(i,w,dd,"isPrime"); } def CUTDOWNRING=CUTDOWN[1]; intvec precutdownw=w; // save the old w for later reference w=CUTDOWN[2]; // the new w - some components have been eliminated setring CUTDOWNRING; } } else { int dd=0; // the dimension of i } list liftrings; // will contain the final result // if the procedure is called without 'findAll' then it may happen, that no // proper solution is found when dd>0; in that case we have // to start all over again; // this is controlled by the while-loop intvec ordnungskontrollvektor=N,-w[2]; // used with the option puiseux while (size(liftrings)==0) { // compute lifting for the zero-dimensional ideal via tropicalparametrise if (noabs==1) // do not use absolute primary decomposition { list TP=list(tropicalparametriseNoabs(i,w,ordnung,gfanold,nogfan,puiseux,ini)); } else // use absolute primary decomposition { list TP=tropicalparametrise(i,w,ordnung,ordnungskontrollvektor,gfanold,findall,nogfan,puiseux,ini); } // compute the liftrings by resubstitution kk=1; // counts the liftrings int isgood; // test in the non-zerodimensional case // if the result has the correct valuation for (jj=1;jj<=size(TP);jj++) { // the list TP contains as a first entry the ring over which the // tropical parametrisation // of the (possibly cutdown ideal) i lives def LIFTRING=TP[jj][1]; // if the dimension of i originally was not zero, // then we have to fill in the missing // parts of the parametrisation if (dd!=0) { // we need a ring where the parameters X_1,...,X_k // from LIFTRING are present, // and where also the variables of CUTDOWNRING live execute("ring REPLACEMENTRING=("+charstr(LIFTRING)+"),("+varstr(CUTDOWNRING)+"),dp;"); list repl=imap(CUTDOWNRING,repl); // get the replacement rules // from CUTDOWNRING ideal PARA=imap(LIFTRING,PARA); // get the zero-dim. parametrisatio // from LIFTRING // compute the lift of the solution of the original ideal i ideal LIFT; k=1; // the lift has as many components as GRUNDRING has variables!=t for (j=1;j<=nvars(GRUNDRING)-1;j++) { // if repl[j]=0, then the corresponding variable was not eliminated if (repl[j]==0) { LIFT[j]=PARA[k]; // thus the lift has been // computed by tropicalparametrise k++; // k checks how many entries of PARA have already been used } else // if repl[j]!=0, repl[j] contains replacement rule for the lift { LIFT[j]=repl[j]; // we still have to replace the vars // in repl[j] by the corresp. entries of PARA // replace all variables!=t (from CUTDOWNRING) for (l=1;l<=nvars(CUTDOWNRING)-1;l++) { // substitute the kth variable by PARA[k] LIFT[j]=subst(LIFT[j],var(l),PARA[l]); } } } setring LIFTRING; ideal LIFT=imap(REPLACEMENTRING,LIFT); // test now if the LIFT has the correct valuation !!! // note: it may happen, that when resubstituting PARA into // the replacement rules // there occured some unexpected cancellation; // we only know that for SOME // solution of the zero-dimensional reduction NO // canellation will occur, // but for others this may very well happen; // this in particular means that // we possibly MUST compute all zero-dimensional // solutions when cutting down! intvec testw=precutdownw[1]; for (j=1;j<=size(LIFT);j++) { testw[j+1]=-ord(LIFT[j]); } if (testw==precutdownw) { isgood=1; } else { isgood=0; } } else { setring LIFTRING; ideal LIFT=PARA; isgood=1; } kill PARA; // only if LIFT has the right valuation we have to do something if (isgood==1) { // it remains to reverse the original substitutions, // where appropriate !!! // if some entry of the original w was positive, // we replace the corresponding // variable x_i by t^-w[i]*x_i, so we must now replace // the corresponding entry // LIFT[i] by t^-w[i]*LIFT[i] --- the original w is stored in prew // PROBLEM: THIS CANNOT BE DONE SINCE -w[i] IS NEGATIVE // INSTEAD: RETURN prew IN THE LIST /* for (j=2;j<=size(prew);j++) { if (prew[j]>0) { LIFT[j-1]=t^(-prew[j])*LIFT[j-1]; } } */ // if LIFTRING contains a parameter @a, change it to a if ((noabs==0) and (defined(@a)==-1)) { // pass first to a ring where a and @a // are variables in order to use maps poly mp=minpoly; ring INTERRING=char(LIFTRING),(t,@a,a),dp; poly mp=imap(LIFTRING,mp); ideal LIFT=imap(LIFTRING,LIFT); kill LIFTRING; // replace @a by a in minpoly and in LIFT map phi=INTERRING,t,a,a; mp=phi(mp); LIFT=phi(LIFT); // pass now to a ring whithout @a and with a as parameter ring LIFTRING=(char(INTERRING),a),t,ls; minpoly=number(imap(INTERRING,mp)); ideal LIFT=imap(INTERRING,LIFT); kill INTERRING; } // then export LIFT export(LIFT); // test the result by resubstitution setring GRUNDRING; list resubst; if (noresubst==0) { if (noabs==1) { resubst=tropicalliftingresubstitute(substitute(i,t,t^(TP[jj][2])),list(LIFTRING),N*TP[jj][2],TP[jj][3]); } else { resubst=tropicalliftingresubstitute(substitute(i,t,t^(TP[jj][2])),list(LIFTRING),N*TP[jj][2]); } } setring BASERING; // Finally, if t has been replaced by t^N, then we have to change the // third entry of TP by multiplying by N. if (noabs==1) { liftrings[kk]=list(LIFTRING,N*TP[jj][2],prew,resubst,TP[jj][3]); } else { liftrings[kk]=list(LIFTRING,N*TP[jj][2],prew,resubst); } kk++; kill resubst; } setring BASERING; kill LIFTRING; } // if dd!=0 and the procedure was called without the // option findAll, then it might very well // be the case that no solution is found, since // only one solution for the zero-dimensional // reduction was computed and this one might have // had cancellations when resubstituting; // if so we have to restart the process with the option findAll if (size(liftrings)==0) { "The procedure was called without findAll and no proper solution was found."; "The procedure will be restarted with the option 'findAll'."; "Go on by hitting RETURN!"; findall=1; noabs=0; setring CUTDOWNRING; int hadproblems; "i";i; "ini";tInitialIdeal(i,w,1); /* setring GRUNDRING; list repl=imap(CUTDOWNRING,repl); i=imap(CUTDOWNRING,i); for (j=1;j<=nvars(basering)-1;j++) { if (repl[j]!=0) { i=i+ideal(var(j)-repl[j]); } } ini=tInitialIdeal(i,precutdownw,1); w=precutdownw; */ } } // if internally the option findall was set, then return // only the first solution if (defined(hadproblems)!=0) { liftrings=liftrings[1]; } /////////////////////////////////////////////////////////// if (printlevel-voice+2>=0) { "The procedure has created a list of lists. The jth entry of this list contains a ring, an integer and an intvec. In this ring lives an ideal representing the wanted lifting, if the integer is N then in the parametrisation t has to be replaced by t^1/N, and if the ith component of the intvec is w[i] then the ith component in LIFT should be multiplied by t^-w[i]/N in order to get the parametrisation. Suppose your list has the name L, then you can access the 1st ring via: "; if (findall==1) { "def LIFTRing=L[1][1]; setring LIFTRing; LIFT; "; } else { "def LIFTRing=L[1]; setring LIFTRing; LIFT; "; } } if (findall==1) // if all solutions have been computed, return a list of lists { return(liftrings); } else //if only 1 solution was to be computed, return the 1st list in liftrings { liftrings=liftrings[1]; return(liftrings); } } example { "EXAMPLE:"; int oldprintlevel=printlevel; printlevel=1; echo=2; //////////////////////////////////////////////////////// // 1st EXAMPLE: //////////////////////////////////////////////////////// ring r=0,(t,x),dp; ideal i=(1+t2)*x2+t5x+t2; intvec w=1,-1; list LIST=tropicalLifting(i,w,4); def LIFTRing=LIST[1]; setring LIFTRing; // LIFT contains the first 4 terms of a point in the variety of i // over the Puiseux series field C{{t}} whose order is -w[1]/w[0]=1 LIFT; // Since the computations were done over Q a field extension was necessary, // and the parameter "a" satisfies the equation given by minpoly minpoly; //////////////////////////////////////////////////////// // 2nd EXAMPLE //////////////////////////////////////////////////////// setring r; LIST=tropicalLifting(x12-t11,intvec(12,-11),2,"isPrime","isInTrop"); def LIFTRing2=LIST[1]; setring LIFTRing2; // This time, LIFT contains the lifting of the point -w[1]/w[0]=11/12 // only after we replace in LIFT the variable t by t^1/N with N=LIST[3] LIFT; LIST[3]; /////////////////////////////////////////////////////// // 3rd EXAMPLE //////////////////////////////////////////////////////// ring R=0,(t,x,y,z),dp; ideal i=-y2t4+x2,yt3+xz+y; w=1,-2,0,2; LIST=tropicalLifting(i,w,3); // This time, LIFT contains the lifting of the point v=(-2,0,2) // only after we multiply LIFT[3] by t^k with k=-LIST[4][3]; // NOTE: since the last component of v is positive, the lifting // must start with a negative power of t, which in Singular // is not allowed for a variable. def LIFTRing3=LIST[1]; setring LIFTRing3; LIFT; LIST[4]; // An easier way to display this is via displayTropicalLifting. setring R; displayTropicalLifting(LIST,"subst"); printlevel=oldprintlevel; } /////////////////////////////////////////////////////////////////////////////// proc displayTropicalLifting (list troplift,list #) "USAGE: displaytropcallifting(troplift[,#]); troplift list, # list ASSUME: troplift is the output of tropicalLifting; the optional parameter # can be the string 'subst' RETURN: none NOTE: - the procedure displays the output of the procedure tropicalLifting @* - if the optional parameter 'subst' is given, then the lifting is substituted into the ideal and the result is displayed EXAMPLE: example displayTropicalLifting; shows an example" { int j; // if the procedure has to display more than one lifting if (typeof(troplift[1])=="list") { for (j=1;j<=size(troplift);j++) { "============================="; string(j)+". Lifting:"; ""; displayTropicalLifting(troplift[j],#); ""; } } // if the procedure has to display only one lifting else { list variablen; for (j=2;j<=nvars(basering);j++) { variablen[j-1]=string(var(j)); } def LIFTRing=troplift[1]; int N=troplift[2]; intvec wdiff=troplift[3]; string LIFTpar=parstr(LIFTRing); if (char(LIFTRing)==0) { string Kstring="Q"; } else { string Kstring="Z/"+string(char(LIFTRing))+"Z"; } // this means that tropicalLifting was called with // absolute primary decomposition if (size(troplift)==4) { setring LIFTRing; "The lifting of the point in the tropical variety lives in the ring"; if ((size(LIFTpar)==0) and (N==1)) { Kstring+"[[t]]"; } if ((size(LIFTpar)==0) and (N!=1)) { Kstring+"[[t^(1/"+string(N)+")]]"; } if ((size(LIFTpar)!=0) and (N!=1)) { Kstring+"["+LIFTpar+"]/"+string(minpoly)+"[[t^(1/"+string(N)+")]]"; } if ((size(LIFTpar)!=0) and (N==1)) { Kstring+"["+LIFTpar+"]/"+string(minpoly)+"[[t]]"; } } else // tropicalLifting was called with the option noAbs { string m=troplift[5]; setring LIFTRing; "The lifting of the point in the tropical variety lives in the ring"; if ((size(LIFTpar)==0) and (N==1)) { Kstring+"[[t]]"; } if ((size(LIFTpar)==0) and (N!=1)) { Kstring+"[[t^(1/"+string(N)+")]]"; } if ((size(LIFTpar)!=0) and (N!=1)) { Kstring+"["+LIFTpar+"]/M[[t^(1/"+string(N)+")]]"; "where M is the maximal ideal"; "M=<"+m+">"; } if ((size(LIFTpar)!=0) and (N==1)) { Kstring+"["+LIFTpar+"]/M[[t]]"; "where M is the maximal ideal"; "M=<"+m+">"; } } ""; "The lifting has the form:"; for (j=1;j<=size(LIFT);j++) { if (ncols(LIFT)==size(variablen)) { variablen[j]+"="+displaypoly(LIFT[j],N,wdiff[j+1],wdiff[1]); } else { "var("+string(j)+")="+displaypoly(LIFT[j],N,wdiff[j+1],wdiff[1]); } } if (size(#)>0) { if (#[1]=="subst") { ""; "Substituting the solution into the ideal gives:"; for(j=1;j<=size(troplift[4]);j++) { "i["+string(j)+"]="+troplift[4][j]; } } } } } example { "EXAMPLE:"; echo=2; ring r=0,(t,x,y,z),dp; ideal i=-y2t4+x2,yt3+xz+y; intvec w=2,-4,0,4; displayTropicalLifting(tropicalLifting(i,w,3),"subst"); } proc puiseuxExpansion (poly f,int n,list #) "USAGE: puiseuxExpansion(f,n,#); f poly, n int, # list ASSUME: f is a non-constant polynomial in two variables which is not divisible by the first variable and which is squarefree as a power series over the complex numbers; the base field is either the field of rational numbers or a finite extension thereof; monomial ordering is assumed to be local; the optional parameter # can be the string 'subst' RETURN: list, where each entry of the list l describes the Newton-Puiseux @* parametrisations of one branch of the plane curve singularity @* at the origin defined by f; only the terms up to order n of each @* parametetrisation are computed @* l[i][1] = is a ring @* l[i][2] = int @* l[i][3] = string @* @* WE NOW DESCRIBE THE LIST ENTRIES l[i] IN MORE DETAIL: @* - the ring l[i][1] contains an ideal LIFT and the Newton-Puiseux parametrisation of the branch is given by x=t^N and y=LIFT[1], where N=l[i][2] @* - if the base field had a parameter and a minimal polynomial, then the new base field will have a parameter and a new minimal polynomial, and LIFT[2] describes how the old parameter can be computed from the new one @* - if a field extension with minimal polynomial of degree k was necessary, then to the one extension produced acutally k extensions correspond by replacing the parameter a successively by all zeros of the minimal polynomial @* - if the option subst was set l[i][3] contains the polynomial where y has been substituted by y(t^{1/N}) as a string REMARK: - it is best to use the procedure displayPuiseuxExpansion to display the result @* - the procedure requires the @sc{Singular} procedure absPrimdecGTZ to be present in the package primdec.lib @* - if f is not squarefree it will be replaced by its squarefree part EXAMPLE: example puiseuxExpansion; shows an example" { if (deg(f)<=0) { ERROR("The input polynomial is not allowed to be constant!"); } if (char(basering)!=0) { ERROR("In positive characteristic a Puiseux expansion will not in general exist!"); } if ((npars(basering)>1) or ((npars(basering)==1) and (minpoly==0))) { ERROR("The procedure is not implemented for this base field!"); } if (nvars(basering)!=2) { ERROR("The base ring should depend on exactly two variables."); } if (f==(f / var(1))*var(1)) { ERROR("The input polynomial is not allowed to be divisible by the first variable."); } // if the ordering is not local, change to a local ordering if ((11) { if (#[1]=="subst") { noResubst=0; } } // replace f by its squarefree part f=squarefree(f); // check if var(1) or var(2) divide f int coordinatebranchtwo; if (f==(f / var(2))*var(2)) { coordinatebranchtwo=1; f=f/var(2); } int jj; // if f is now constant then we should skip the next part if (deg(f)!=0) { // compute the Newton polygon int zw; intvec w; int ggteiler; list NewtP=newtonpoly(f); list tls; list pexp; // if the base field has a minimal polynomial change the base ring and the ideal if (minpoly!=0) { poly mp=minpoly; def OLDRING=basering; execute("ring NEWRING=0,("+varstr(basering)+","+parstr(basering)+"),ds;"); ideal I=imap(OLDRING,mp),imap(OLDRING,f); } else { ideal I=f; } // for each facet of the Newton polygon compute the corresponding parametrisations // using tropicalLifting with the option "puiseux" which avoids gfan for (jj=1;jj<=size(NewtP)-1;jj++) { w=NewtP[jj]-NewtP[jj+1]; ggteiler=gcd(w[1],w[2]); zw=w[1] div ggteiler; w[1]=w[2] div ggteiler; w[2]=zw; // if we have introduced a third variable for the parameter, then w needs a third component if (nvars(basering)==3) { w[3]=0; } if (noResubst==0) { tls=tropicalLifting(I,w,n,"findAll","puiseux"); } else { tls=tropicalLifting(I,w,n,"findAll","puiseux","noResubst"); } pexp=pexp+tls; } // kill rings that are no longer needed if (defined(NEWRING)) { setring OLDRING; kill NEWRING; } if (defined(GLOBALRING)) { setring GLOBALRING; kill LOCALRING; } // remove the third entry in the list of parametrisations since we know // that none of the exponents in the parametrisation will be negative for (jj=1;jj<=size(pexp);jj++) { pexp[jj]=delete(pexp[jj],3); pexp[jj][3]=pexp[jj][3][size(pexp[jj][3])]; // replace the list in pexp[jj][3] by its first entry } } else // if f was reduced to a constant we still have to introduce the list pexp { list pexp; } // we have to add the parametrisations for the branches var(1) resp. var(2) if // we removed them def BASERING=basering; if (coordinatebranchtwo==1) { ring brring=0,t,ds; ideal LIFT=0; export(LIFT); setring BASERING; list pexpentry; pexpentry[1]=brring; pexpentry[2]=1; pexpentry[3]="0"; pexp[size(pexp)+1]=pexpentry; kill brring; } // check if all branches have been found int numberofbranchesfound; for (jj=1;jj<=size(pexp);jj++) { def countring=pexp[jj][1]; setring countring; if (minpoly==0) { numberofbranchesfound=numberofbranchesfound+1; } else { poly mp=minpoly; ring degreering=0,a,dp; poly mp=imap(countring,mp); numberofbranchesfound=numberofbranchesfound+deg(mp); setring countring; kill degreering; } setring BASERING; kill countring; } // give a warning if not all branches have been found if (numberofbranchesfound!=ord(subst(f,x,0))+coordinatebranchtwo) { "!!!! WARNING: The number of terms computed in the Puiseux expansion were"; "!!!! not enough to find all branches of the curve singularity!"; } return(pexp); } example { "EXAMPLE:"; echo=2; printlevel=1; ring r=0,(x,y),ds; poly f=x2-y4+x5y7; puiseuxExpansion(f,3,"subst"); displayPuiseuxExpansion(puiseuxExpansion(f,3)); } proc displayPuiseuxExpansion (list puiseux,list #) "USAGE: displayPuiseuxExpansion(puiseux[,#]); puiseux list, # list ASSUME: puiseux is the output of puiseuxExpansion; the optional parameter # can be the string 'subst' RETURN: none NOTE: - the procedure displays the output of the procedure puiseuxExpansion @* - if the optional parameter 'subst' is given, then the expansion is substituted into the polynomial and the result is displayed @* - if the base field had a parameter and a minimal polynomial, then the new base field will have a parameter and a minimal polynomial; var(2) is the old parameter and it is displayed how the old parameter can be computed from the new one EXAMPLE: example displayPuiseuxExpansion; shows an example" { int j; // if the procedure has to display more than one expansion if (typeof(puiseux[1])=="list") { for (j=1;j<=size(puiseux);j++) { "============================="; string(j)+". Expansion:"; ""; displayPuiseuxExpansion(puiseux[j],#); ""; } } // if the procedure has to display only one expansion else { list variablen; for (j=2;j<=nvars(basering);j++) { variablen[j-1]=string(var(j)); } def BASERING=basering; def LIFTRing=puiseux[1]; int N=puiseux[2]; string LIFTpar=parstr(LIFTRing); string Kstring="Q"; setring LIFTRing; "The Puiseux expansion lives in the ring"; if ((size(LIFTpar)==0) and (N==1)) { Kstring+"[[t]]"; } if ((size(LIFTpar)==0) and (N!=1)) { Kstring+"[[t^(1/"+string(N)+")]]"; } if ((size(LIFTpar)!=0) and (N!=1)) { Kstring+"["+LIFTpar+"]/"+string(minpoly)+"[[t^(1/"+string(N)+")]]"; } if ((size(LIFTpar)!=0) and (N==1)) { Kstring+"["+LIFTpar+"]/"+string(minpoly)+"[[t]]"; } ""; "The expansion has the form:"; // treat the case LIFT==0 separately if (size(LIFT)==0) { variablen[1]+"=0"; } else { for (j=1;j<=size(LIFT);j++) { if (ncols(LIFT)==size(variablen)) { variablen[j]+"="+displaypoly(LIFT[j],N,0,1); } else { "var("+string(j)+")="+displaypoly(LIFT[j],N,0,1); } } } if (size(#)>0) { if (#[1]=="subst") { setring BASERING; ""; "Substituting the expansion into the polynomial gives:"; "f="+puiseux[3]; } } } } example { "EXAMPLE:"; echo=2; ring r=0,(x,y),ds; poly f=x2-y4+x5y7; displayPuiseuxExpansion(puiseuxExpansion(f,3)); } /////////////////////////////////////////////////////////////////////////////// /// Procedures concerned with drawing a tropical curve or a Newton subdivision /////////////////////////////////////////////////////////////////////////////// proc tropicalCurve (def tp,list #) "USAGE: tropicalCurve(tp[,#]); tp list, # optional list ASSUME: tp is list of linear polynomials of the form ax+by+c with integers a, b and a rational number c representing a tropical Laurent polynomial defining a tropical plane curve; alternatively tp can be a polynomial in Q(t)[x,y] defining a tropical plane curve via the valuation map; the basering must have a global monomial ordering, two variables and up to one parameter! RETURN: list, each entry i=1,...,size(l)-1 corresponds to a vertex in the tropical plane curve defined by tp l[i][1] = x-coordinate of the ith vertex l[i][2] = y-coordinate of the ith vertex l[i][3] = intmat, if j is an entry in the first row of intmat then the ith vertex of the tropical curve is connected to the jth vertex with multiplicity given by the corresponding entry in the second row l[i][4] = list of lists, the first entry of a list is a primitive integer vector defining the direction of an unbounded edge emerging from the ith vertex of the graph, the corresponding second entry in the list is the multiplicity of the unbounded edge l[i][5] = a polynomial whose monomials mark the vertices in the Newton polygon corresponding to the entries in tp which take the common minimum at the ith vertex -- if some coefficient a or b of the linear polynomials in the input was negative, then each monomial has to be shifted by the values in l[size(l)][3] l[size(l)][1] = list, the entries describe the boundary points of the Newton subdivision l[size(l)][2] = list, the entries are pairs of integer vectors defining an interior edge of the Newton subdivision l[size(l)][3] = intvec, the monmials occuring in l[i][5] have to be shifted by this vector in order to represent marked vertices in the Newton polygon NOTE: here the tropical polynomial is supposed to be the MINIMUM of the linear forms in tp, unless the optional input #[1] is the string 'max' EXAMPLE: example tropicalCurve; shows an example" { // introduce necessary variables int i,j,k,l,d; intvec v,w,u; intmat D[2][2]; // the basering must have a global monomial ordering if (1>var(1)) { ERROR("The basering should have a global monomial ordering, e.g. ring r=(0,t),(x,y),dp;"); } // if you insert a single polynomial instead of an ideal // representing a tropicalised polynomial, // then we compute first the tropicalisation of this polynomial // -- this feature is not documented in the above help string if (typeof(tp)=="poly") { // exclude the case that the basering has not precisely // one parameter and two indeterminates if ((npars(basering)!=1) or (nvars(basering)!=2)) { ERROR("The basering should have precisely one parameter and two indeterminates!"); } poly f=tp; kill tp; list tp=tropicalise(f,#); // the tropicalisation of f } // Exclude the case that the basering has more than 2 indeterminates if (nvars(basering) != 2) { ERROR("The basering should have precisely two indeterminates!"); } // -1) Exclude the pathological case that the defining // tropical polynomial has only one term, // so that the tropical variety is not defined. if (size(tp)==1) { ERROR("A monomial does not define a tropical curve!"); intmat M[2][1]=0,0; return(list(list(0,0,M,list(),detropicalise(tp[1])),list(list(leadexp(detropicalise(tp[1]))),list()))); } // 0) If the input was a list of linear polynomials, // then some coefficient of x or y can be negative, // i.e. the input corresponds to the tropical curve // of a Laurent polynomial. In that case we should // add some ax+by, so that all coefficients are positive. // This does not change the tropical curve. // however, we have to save (a,b), since the Newton // polygone has to be shifted by (-a,-b). poly aa,bb; // koeffizienten for (i=1;i<=size(tp);i++) { if (koeffizienten(tp[i],1)=1;k--) { deleted=0; for (l=size(pairs[j]);l>=1 and deleted==0;l--) { if (((pairs[i][k][1]==pairs[j][l][1]) and (pairs[i][k][2]==pairs[j][l][2])) or ((pairs[i][k][1]==pairs[j][l][2]) and (pairs[i][k][2]==pairs[j][l][1]))) { inneredges[d]=pairs[i][k]; // new inner edge is saved in inneredges d++; ggt=abs(gcd(pairs[i][k][1][1]-pairs[i][k][2][1],pairs[i][k][1][2]-pairs[i][k][2][2])); zwsp=j,ggt; // and it is recorded that the ith and jth // vertex should be connected with mult ggt vtp[i][6]=intmatconcat(vtp[i][6],zwsp); zwsp=i,ggt; vtp[j][6]=intmatconcat(vtp[j][6],zwsp); pairs[i]=delete(pairs[i],k); // finally the pair is deleted // from both sets of pairs pairs[j]=delete(pairs[j],l); deleted=1; } } } } } // 5) The entries in vtp[i][6] are ordered, multiple entries are removed, // and the redundant zero is removed as well for (i=1;i<=size(vtp);i++) { vtp[i][6]=clearintmat(vtp[i][6]); } // 6) Declare the orientation of the boundary of the Newton polytope. // 6.1) Collect all potential vertices of the boundary of the Newton polytope. list vertices; // all vertices in the set of pairs k=1; for (i=1;i<=size(pairs);i++) { for (j=1;j<=size(pairs[i]);j++) { vertices[k]=pairs[i][j][1]; k++; vertices[k]=pairs[i][j][2]; k++; } } // 6.2) delete multiple vertices for (i=size(vertices)-1;i>=1;i--) { for (j=size(vertices);j>=i+1;j--) { if (vertices[i]==vertices[j]) { vertices=delete(vertices,j); } } } // 6.3) Order the vertices such that passing from one to the next we // travel along the boundary of the Newton polytope clock wise. boundaryNSD=findOrientedBoundary(vertices); list orderedvertices=boundaryNSD[1]; // 7) Find the unbounded edges emerging from a vertex in the tropical curve. // For this we check the remaining pairs for the ith NSD. // Each pair is ordered according // to the order in which the vertices occur in orderedvertices. // The direction of the // unbounded edge is then the outward pointing primitive normal // vector to the vector // pointing from the first vertex in a pair to the second one. intvec normalvector; // stores the outward pointing normal vector intvec zwspp; // used for intermediate storage int zw,pos1,pos2; // stores the gcd of entries of the // non-normalised normal vector, etc. int gestorben; // tests if unbounded edges are multiple for (i=1;i<=size(pairs);i++) { list ubedges; // stores the unbounded edges k=1; // counts the unbounded edges for (j=1;j<=size(pairs[i]);j++) { // computes the position of the vertices in the pos1=positionInList(orderedvertices,pairs[i][j][1]); // pair in the list orderedvertices pos2=positionInList(orderedvertices,pairs[i][j][2]); if (((pos1>pos2) and !((pos1==size(orderedvertices)) and (pos2==1))) or ((pos2==size(orderedvertices)) and (pos1==1))) // reorders them if necessary { zwspp=pairs[i][j][1]; pairs[i][j][1]=pairs[i][j][2]; pairs[i][j][2]=zwspp; } // the vector pointing from vertex 1 in the pair to vertex2 normalvector=pairs[i][j][2]-pairs[i][j][1]; ggt=gcd(normalvector[1],normalvector[2]); // the gcd of the entries zw=normalvector[2]; // create the outward pointing normal vector normalvector[2]=-normalvector[1] div ggt; normalvector[1]=zw div ggt; if (size(#)==0) // we are computing w.r.t. minimum { ubedges[k]=list(normalvector,ggt); // store outward pointing normal vec. } else // we are computing w.r.t. maximum { ubedges[k]=list(-normalvector,ggt); //store outward pointing normal vec. } k++; } // remove multiple unbounded edges for (j=size(ubedges);j>=1;j--) { gestorben=0; for(k=1;(k<=j-1) and (gestorben==0);k++) { if (ubedges[k][1]==ubedges[j][1]) { ubedges[k][2]=ubedges[k][2]+ubedges[j][2]; // add the multiplicities ubedges=delete(ubedges,j); gestorben=1; } } } vtp[i][7]=ubedges; // store the unbounded edges in vtp[i][7] kill ubedges; } // 8) Store the computed information for the ith part // of the NSD in the list graph[i]. list graph,gr; for (i=1;i<=size(vtp);i++) { // the first coordinate of the ith vertex of the tropical curve gr[1]=vtp[i][1]; // the second coordinate of the ith vertex of the tropical curve gr[2]=vtp[i][2]; // to which vertices is the ith vertex of the tropical curve connected gr[3]=vtp[i][6]; // the directions unbounded edges emerging from the ith // vertex of the trop. curve gr[4]=vtp[i][7]; // the vertices of the boundary of the ith part of the NSD gr[5]=vtp[i][3]; graph[i]=gr; } // 9) Shift the Newton subdivision by (aa,bb) if necessary intvec shiftvector=intvec(int(aa),int(bb)); if ((aa!=0) or (bb!=0)) { for (i=1;i<=size(boundaryNSD[2]);i++) { boundaryNSD[2][i]=boundaryNSD[2][i]+shiftvector; } for (i=1;i<=size(inneredges);i++) { for (j=1;j<=size(inneredges[i]);j++) { inneredges[i][j]=inneredges[i][j]+shiftvector; } } } // 10) Finally store the boundary vertices and // the inner edges as last entry in the list graph. // This represents the NSD. graph[size(vtp)+1]=list(boundaryNSD[2],inneredges,shiftvector); return(graph); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; poly f=t*(x7+y7+1)+1/t*(x4+y4+x2+y2+x3y+xy3)+1/t7*x2y2; list graph=tropicalCurve(f); // the tropical curve has size(graph)-1 vertices size(graph)-1; // the coordinates of the first vertex are graph[1][1],graph[1][2]; graph[1][1],graph[1][2]; // the first vertex is connected to the vertices // graph[1][3][1,1..ncols(graph[1][3])] intmat M=graph[1][3]; M[1,1..ncols(graph[1][3])]; // the weights of the edges to these vertices are // graph[1][3][2,1..ncols(graph[1][3])] M[2,1..ncols(graph[1][3])]; // from the first vertex emerge size(graph[1][4]) unbounded edges size(graph[1][4]); // the primitive integral direction vector of the first unbounded edge // of the first vertex graph[1][4][1][1]; // the weight of the first unbounded edge of the first vertex graph[1][4][1][2]; // the monomials which are part of the Newton subdivision of the first vertex graph[1][5]; // connecting the points in graph[size(graph)][1] we get // the boundary of the Newton polytope graph[size(graph)][1]; // an entry in graph[size(graph)][2] is a pair of points // in the Newton polytope bounding an inner edge graph[size(graph)][2][1]; } ///////////////////////////////////////////////////////////////////////// proc drawTropicalCurve (def f,list #) "USAGE: drawTropicalCurve(f[,#]); f poly or list, # optional list ASSUME: f is list of linear polynomials of the form ax+by+c with integers a, b and a rational number c representing a tropical Laurent polynomial defining a tropical plane curve; alternatively f can be a polynomial in Q(t)[x,y] defining a tropical plane curve via the valuation map; the basering must have a global monomial ordering, two variables and up to one parameter! RETURN: NONE NOTE: - the procedure creates the files /tmp/tropicalcurveNUMBER.tex and /tmp/tropicalcurveNUMBER.ps, where NUMBER is a random four digit integer; moreover it displays the tropical curve via kghostview; if you wish to remove all these files from /tmp, call the procedure cleanTmp @* - edges with multiplicity greater than one carry this multiplicity @* - if # is empty, then the tropical curve is computed w.r.t. minimum, if #[1] is the string 'max', then it is computed w.r.t. maximum @* - if the last optional argument is 'onlytexfile' then only the latex file is produced; this option should be used if kghostview is not installed on your system @* - note that lattice points in the Newton subdivision which are black correspond to markings of the marked subdivision, while lattice points in grey are not marked EXAMPLE: example drawTropicalCurve shows an example" { // check if the option "onlytexfile" is set, then only a tex file is produced if (size(#)!=0) { if (#[size(#)]=="onlytexfile") { int onlytexfile; #=delete(#,size(#)); } } // start the actual computations string texf; int j; if (typeof(f)=="poly") { // exclude the case that the basering has not precisely // one parameter and two indeterminates if ((npars(basering)!=1) or (nvars(basering)!=2)) { ERROR("The basering should have precisely one parameter and two indeterminates!"); } // if the characteristic of the base field is not 0 then replace the base field // by a field of characteristic zero if (char(basering)!=0) { string polynomstring=string(f); execute("ring drawring=(0,"+parstr(basering)+"),("+varstr(basering)+"),dp;"); execute("poly f="+polynomstring+";"); } texf=texPolynomial(f); // write the polynomial over Q(t) list graph=tropicalCurve(tropicalise(f,#),#); // graph of tropicalis. of f } if (typeof(f)=="list") { if (typeof(f[1])=="list") { texf="\\mbox{\\tt The defining equation was not handed over!}"; list graph=f; } else { // write the tropical polynomial defined by f if (size(#)==0) { texf="\\min\\{"; } else { texf="\\max\\{"; } for (j=1;j<=size(f);j++) { texf=texf+texPolynomial(f[j]); if (j=0) { "The embedded graph of the curve has not genus one."; } return(-1); } else { intmat nullmat[2][1]; // used to set // 4) find a vertex which has only one bounded edge, // if none exists zero is returned, // otherwise the number of the vertex in the list graph int nonloopvertex=findNonLoopVertex(graph); int dv; //checks if vert. has been found to which nonloopvertex is connected intmat delvert; // takes for a moment graph[i][3] of the vertex // to which nonloopvertex is connected // 5) delete successively vertices in the graph which // have only one bounded edge while (nonloopvertex>0) { // find the only vertex to which the nonloopvertex // is connected, when it is found // delete the connection in graph[i][3] and set dv=1 dv=0; for (i=1;i<=size(graph)-1 and dv==0;i++) { if (i!=nonloopvertex) { for (j=1;j<=ncols(graph[i][3]) and dv==0;j++) { if(graph[i][3][1,j]==nonloopvertex) // the vertex is found { delvert=graph[i][3]; delvert=intmatcoldelete(delvert,j); // delete the connection (note // there must have been two!) dv=1; graph[i][3]=delvert; } } } } graph[nonloopvertex][3]=nullmat; // the only connection of nonloopvertex // is killed nonloopvertex=findNonLoopVertex(graph); // find the next vertex // which has only one edge } // 6) find the loop and the weights of the edges intvec loop,weights; // encodes the loop and the edges i=1; // start by finding some vertex which belongs to the loop while (loop==0) { // if graph[i][3] of a vertex in the loop has 2 columns, all others have 1 if (ncols(graph[i][3])==1) { i++; } else { loop[1]=i; // a starting vertex is found loop[2]=graph[i][3][1,1]; // it is connected to vertex with this number weights[2]=graph[i][3][2,1]; // and the edge has this weight } } j=graph[i][3][1,1]; // the active vertex of the loop k=2; // counts the vertices in the loop while (j!=i) // the loop ends with the same vertex with which it starts { // the first row of graph[j][3] has two entries // corresponding to the two vertices // to which the active vertex j is connected; // one is loop[k-1], i.e. the one which // precedes j in the loop; we have to choose the other one if (graph[j][3][1,1]==loop[k-1]) { loop[k+1]=graph[j][3][1,2]; weights[k+1]=graph[j][3][2,2]; } else { loop[k+1]=graph[j][3][1,1]; weights[k+1]=graph[j][3][2,1]; } j=loop[k+1]; // set loop[k+1] the new active vertex k++; } // 7) compute for each edge in the loop the lattice length poly xcomp,ycomp; // the x- and y-components of the vectors // connecting two vertices of the loop number nenner; // the product of the denominators of // the x- and y-components number jinvariant; // the j-invariant int eins,zwei,ggt; for (i=1;i<=size(loop)-1;i++) // compute the lattice length for each edge { xcomp=graph[loop[i]][1]-graph[loop[i+1]][1]; ycomp=graph[loop[i]][2]-graph[loop[i+1]][2]; nenner=denominator(leadcoef(xcomp))*denominator(leadcoef(ycomp)); execute("eins="+string(numerator(leadcoef(nenner*xcomp)))+";"); execute("zwei="+string(numerator(leadcoef(nenner*ycomp)))+";"); ggt=gcd(eins,zwei); // the lattice length is the "gcd" // of the x-component and the y-component jinvariant=jinvariant+ggt/(nenner*weights[i+1]); // divided by the // weight of the edge } return(jinvariant); } } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; // tropcialJInvariant computes the tropical j-invariant of an elliptic curve tropicalJInvariant(t*(x3+y3+1)+1/t*(x2+y2+x+y+x2y+xy2)+1/t2*xy); // the Newton polygone need not be the standard simplex tropicalJInvariant(x+y+x2y+xy2+1/t*xy); // the curve can have arbitrary degree tropicalJInvariant(t*(x7+y7+1)+1/t*(x4+y4+x2+y2+x3y+xy3)+1/t7*x2y2); // the procedure does not realise, if the embedded graph of the tropical // curve has a loop that can be resolved tropicalJInvariant(1+x+y+xy+tx2y+txy2); // but it does realise, if the curve has no loop at all ... tropicalJInvariant(x+y+1); // or if the embedded graph has more than one loop - even if only one // cannot be resolved tropicalJInvariant(1+x+y+xy+tx2y+txy2+t3x5+t3y5+tx2y2+t2xy4+t2yx4); } ///////////////////////////////////////////////////////////////////////// proc weierstrassForm (poly f,list #) "USAGE: weierstrassForm(wf[,#]); wf poly, # list ASSUME: wf is a a polynomial whose Newton polygon has precisely one interior lattice point, so that it defines an elliptic curve on the toric surface corresponding to the Newton polygon RETURN: poly, the Weierstrass normal form of the polynomial NOTE: - the algorithm for the coefficients of the Weierstrass form is due to Fernando Rodriguez Villegas, villegas@math.utexas.edu @* - the characteristic of the base field should not be 2 or 3 @* - if an additional argument # is given, a simplified Weierstrass form is computed EXAMPLE: example weierstrassForm; shows an example" { // Check first if the Newton polygon has precisely one interior point // - compute the Newton polygon list polygon=newtonPolytopeLP(f); // - find the vertices of the Newton cycle and order it clockwise list pg=findOrientedBoundary(polygon)[2]; // - check if there is precisely one interior point in the Newton polygon if (picksFormula(pg)[3]!=1) { ERROR("The Newton polygon of the input has NOT precisely one interior point!"); } // Compute the Normal form of the polygon. list nf=ellipticNF(polygon); // Transform f by the unimodular affine coordinate transformation poly tf=coordinatechange(f,nf[2],nf[3]); // Check if the Newton polygon is of type 4x2, 2x2 or a cubic poly a,b=flatten(coeffs(tf,ideal(var(1)^4,var(1)^2*var(2)^2))); // if it is of type 4x2 if (a!=0) { return(weierstrassFormOfA4x2Curve(tf)); } // if it is of type 2x2 if (b!=0) { return(weierstrassFormOfA2x2Curve(tf)); } // else it is a cubic return(weierstrassFormOfACubic(tf,#)); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),lp; // f is already in Weierstrass form poly f=y2+yx+3y-x3-2x2-4x-6; weierstrassForm(f); // g is not, but wg is poly g=x+y+x2y+xy2+1/t*xy; poly wg=weierstrassForm(g); wg; // but it is not yet simple, since it still has an xy-term, unlike swg poly swg=weierstrassForm(g,1); swg; // the j-invariants of all three polynomials coincide jInvariant(g); jInvariant(wg); jInvariant(swg); // the following curve is elliptic as well poly h=x22y11+x19y10+x17y9+x16y9+x12y7+x9y6+x7y5+x2y3; // its Weierstrass form is weierstrassForm(h); } ///////////////////////////////////////////////////////////////////////// proc jInvariant (poly f,list #) "USAGE: jInvariant(f[,#]); f poly, # list ASSUME: - f is a a polynomial whose Newton polygon has precisely one interior lattice point, so that it defines an elliptic curve on the toric surface corresponding to the Newton polygon @* - it the optional argument # is present the base field should be Q(t) and the optional argument should be one of the following strings: @* 'ord' : then the return value is of type integer, namely the order of the j-invariant @* 'split' : then the return value is a list of two polynomials, such that the quotient of these two is the j-invariant RETURN: poly, the j-invariant of the elliptic curve defined by poly NOTE: the characteristic of the base field should not be 2 or 3, unless the input is a plane cubic EXAMPLE: example jInvariant; shows an example" { // compute first the Weierstrass form of the cubic and then the j-invariant if (size(#)==0) { return(jInvariantOfACubic(weierstrassForm(f),#)); } else { if (#[1]=="split") { return(jInvariantOfAPuiseuxCubic(weierstrassForm(f))); } else { return(jInvariantOfAPuiseuxCubic(weierstrassForm(f),"ord")); } } } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; // jInvariant computes the j-invariant of a cubic jInvariant(x+y+x2y+y3+1/t*xy); // if the ground field has one parameter t, then we can instead // compute the order of the j-invariant jInvariant(x+y+x2y+y3+1/t*xy,"ord"); // one can compare the order of the j-invariant to the tropical j-invariant tropicalJInvariant(x+y+x2y+y3+1/t*xy); // the following curve is elliptic as well poly h=x22y11+x19y10+x17y9+x16y9+x12y7+x9y6+x7y5+x2y3+x14y8; // its j-invariant is jInvariant(h); } /////////////////////////////////////////////////////////////////////////////// /// Procedures concerned with conics /////////////////////////////////////////////////////////////////////////////// proc conicWithTangents (list points,list #) "USAGE: conicWithTangents(points[,#]); points list, # optional list ASSUME: points is a list of five points in the plane over K(t) RETURN: list, l[1] = the list points of the five given points @* l[2] = the conic f passing through the five points @* l[3] = list of equations of tangents to f in the given points @* l[4] = ideal, tropicalisation of f (i.e. list of linear forms) @* l[5] = a list of the tropicalisation of the tangents @* l[6] = a list containing the vertices of the tropical conic f @* l[7] = a list containing lists with vertices of the tangents @* l[8] = a string which contains the latex-code to draw the tropical conic and its tropicalised tangents @* l[9] = if # is non-empty, this is the same data for the dual conic and the points dual to the computed tangents NOTE: the points must be generic, i.e. no three on a line EXAMPLE: example conicWithTangents; shows an example" { int i; // Compute the tropical coordinates of the given points - part 1 list pointdenom,pointnum; poly pp1,pp2; for (i=1;i<=size(points);i++) { pp1=denominator(leadcoef(points[i][1])); pp2=denominator(leadcoef(points[i][2])); pointdenom[i]=list(pp1,pp2); pp1=numerator(leadcoef(points[i][1])); pp2=numerator(leadcoef(points[i][2])); pointnum[i]=list(pp1,pp2); } // compute the equation of the conic def BASERING=basering; ring LINRING=(0,t),(x,y,a(1..6)),lp; list points=imap(BASERING,points); ideal I; // the ideal will contain the linear equations given by the conic // and the points for (i=1;i<=5;i++) { I=I,substitute(a(1)*x2+a(2)*xy+a(3)*y2+a(4)*x+a(5)*y+a(6),x,points[i][1],y,points[i][2]); } I=std(I); list COEFFICIENTS; ideal DENOMINATORS; for (i=1;i<=6;i++) { COEFFICIENTS[i]=leadcoef(reduce(a(i),I)); DENOMINATORS[i]=denominator(leadcoef(COEFFICIENTS[i])); } // compute the common denominator of the coefficients ring TRING=0,t,dp; ideal DENOMINATORS=imap(LINRING,DENOMINATORS); poly p=lcm(DENOMINATORS); // compute the tropical coordinates of the points - part 2 ring tRING=0,t,ls; list pointdenom=imap(BASERING,pointdenom); list pointnum=imap(BASERING,pointnum); intvec pointcoordinates; for (i=1;i<=size(pointdenom);i++) { pointcoordinates[2*i-1]=ord(pointnum[i][1])-ord(pointdenom[i][1]); pointcoordinates[2*i]=ord(pointnum[i][2])-ord(pointdenom[i][2]); } // multiply the coefficients of the conic by the common denominator setring LINRING; poly p=imap(TRING,p); for (i=1;i<=6;i++) { COEFFICIENTS[i]=COEFFICIENTS[i]*p; } // Compute the tangents to the conic in the given points // and tropicalise the conic and the tangents setring BASERING; list CO=imap(LINRING,COEFFICIENTS); poly f=CO[1]*x2+CO[2]*xy+CO[3]*y2+CO[4]*x+CO[5]*y+CO[6]; poly fx=diff(f,x); poly fy=diff(f,y); list tangents; list tropicaltangents; for (i=1;i<=5;i++) { tangents[i]=substitute(fx,x,points[i][1],y,points[i][2])*x+substitute(fy,x,points[i][1],y,points[i][2])*y; tangents[i]=tangents[i]-substitute(tangents[i],x,points[i][1],y,points[i][2]); tropicaltangents[i]=tropicalise(tangents[i]); } list tropicalf=tropicalise(f); // compute the vertices of the tropcial conic and of the tangents list graphf=tropicalCurve(tropicalf); list eckpunktef; for (i=1;i<=size(graphf)-1;i++) { eckpunktef[i]=list(graphf[i][1],graphf[i][2]); } list eckpunktetangents; for (i=1;i<=size(tropicaltangents);i++) { eckpunktetangents[i]=verticesTropicalCurve(tropicaltangents[i],0); } // find the minimal and maximal coordinates of vertices poly minx,miny,maxx,maxy=graphf[1][1],graphf[1][2],graphf[1][1],graphf[1][2]; for (i=2;i<=size(graphf)-1;i++) { minx=minOfPolys(list(minx,graphf[i][1])); miny=minOfPolys(list(miny,graphf[i][2])); maxx=-minOfPolys(list(-maxx,-graphf[i][1])); maxy=-minOfPolys(list(-maxy,-graphf[i][2])); } // find the scale factor for the texdraw image poly maxdiffx,maxdiffy; maxdiffx=maxx-minx; maxdiffy=maxy-miny; if (maxdiffx==0) { maxdiffx=1; } if (maxdiffy==0) { maxdiffy=1; } poly scalefactor=minOfPolys(list(12/leadcoef(maxdiffx),16/leadcoef(maxdiffy)))/4; // Produce a Latex-Image of the Conic with each of its Tangents string zusatzinfo; string TEXBILD="\\documentclass[12pt]{amsart} \\usepackage{texdraw} \\begin{document} \\parindent0cm \\begin{center} \\large\\bf A Tropical Conic through 5 Points and Tangents \\end{center} We consider the concic through the following five points: \\begin{displaymath} "; string texf=texDrawTropical(graphf,list("",scalefactor)); for (i=1;i<=size(points);i++) { TEXBILD=TEXBILD+"p_"+string(i)+"=("+texNumber(points[i][1])+","+texNumber(points[i][2])+"),\\;\\;\\;"; } TEXBILD=TEXBILD+" \\end{displaymath}"; for (i=1;i<=size(points);i++) { zusatzinfo=" \\move ("+decimal(pointcoordinates[2*i-1])+" "+decimal(pointcoordinates[2*i])+") \\fcir f:0.5 r:0.25 \\rmove (0.4 0.4) \\htext{$p_"+string(i)+"$=("+string(pointcoordinates[2*i-1])+","+string(pointcoordinates[2*i])+")} "; TEXBILD=TEXBILD+" Here we draw the conic and the tangent through point $p_"+string(i)+"$: \\vspace*{1cm} \\begin{center} "+texDrawBasic(list(texf,zusatzinfo,texDrawTropical(tropicalCurve(tropicaltangents[i]),list("",scalefactor," \\setgray 0.8 \\linewd 0.1 \\lpatt (0.1 0.4)"))))+ "\\end{center}"; if (i0) { list dualpoints; for (i=1;i<=size(points);i++) { dualpoints[i]=list(leadcoef(tangents[i])/substitute(tangents[i],x,0,y,0),leadcoef(tangents[i]-lead(tangents[i]))/substitute(tangents[i],x,0,y,0)); } list dualimage=conicWithTangents(dualpoints); return(list(points,f,tangents,tropicalf,tropicaltangents,eckpunktef,eckpunktetangents,TEXBILD,dualimage)); } else { return(list(points,f,tangents,tropicalf,tropicaltangents,eckpunktef,eckpunktetangents,TEXBILD)); } } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; // the input consists of a list of five points in the plane over Q(t) list points=list(1/t2,t),list(1/t,t2),list(1,1),list(t,1/t2),list(t2,1/t); list conic=conicWithTangents(points); // conic[1] is the list of the given five points conic[1]; // conic[2] is the equation of the conic f passing through the five points conic[2]; // conic[3] is a list containing the equations of the tangents // through the five points conic[3]; // conic[4] is an ideal representing the tropicalisation of the conic f conic[4]; // conic[5] is a list containing the tropicalisation // of the five tangents in conic[3] conic[5]; // conic[6] is a list containing the vertices of the tropical conic conic[6]; // conic[7] is a list containing the vertices of the five tangents conic[7]; // conic[8] contains the latex code to draw the tropical conic and // its tropicalised tangents; it can written in a file, processed and // displayed via kghostview write(":w /tmp/conic.tex",conic[8]); system("sh","cd /tmp; latex /tmp/conic.tex; dvips /tmp/conic.dvi -o; kghostview conic.ps &"); // with an optional argument the same information for the dual conic is computed // and saved in conic[9] conic=conicWithTangents(points,1); conic[9][2]; // the equation of the dual conic } /////////////////////////////////////////////////////////////////////////////// /// Procedures concerned with tropicalisation /////////////////////////////////////////////////////////////////////////////// proc tropicalise (poly f,list #) "USAGE: tropicalise(f[,#]); f polynomial, # optional list ASSUME: f is a polynomial in Q(t)[x_1,...,x_n] RETURN: list, the linear forms of the tropicalisation of f NOTE: if # is empty, then the valuation of t will be 1, @* if # is the string 'max' it will be -1; @* the latter supposes that we consider the maximum of the computed linear forms, the former that we consider their minimum EXAMPLE: example tropicalise; shows an example" { int order,j; list tropicalf; intvec exp; int i=0; while (f!=0) { i++; exp=leadexp(f); if (size(#)==0) { tropicalf[i]=simplifyToOrder(f)[1]; } else { tropicalf[i]=-simplifyToOrder(f)[1]; } for (j=1;j<=nvars(basering);j++) { tropicalf[i]=tropicalf[i]+exp[j]*var(j); } f=f-lead(f); } return(tropicalf); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; tropicalise(2t3x2-1/t*xy+2t3y2+(3t3-t)*x+ty+(t6+1)); } ///////////////////////////////////////////////////////////////////////// proc tropicaliseSet (ideal i) "USAGE: tropicaliseSet(i); i ideal ASSUME: i is an ideal in Q(t)[x_1,...,x_n] RETURN: list, the jth entry is the tropicalisation of the jth generator of i EXAMPLE: example tropicaliseSet; shows an example" { list tropicalid; for (int j=1;j<=size(i);j++) { tropicalid[j]=tropicalise(i[j]); } return(tropicalid); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; ideal i=txy-y2+1,2t3x2+1/t*y-t6; tropicaliseSet(i); } ///////////////////////////////////////////////////////////////////////// proc tInitialForm (poly f, intvec w) "USAGE: tInitialForm(f,w); f a polynomial, w an integer vector ASSUME: f is a polynomial in Q[t,x_1,...,x_n] and w=(w_0,w_1,...,w_n) RETURN: poly, the t-initialform of f(t,x) w.r.t. w evaluated at t=1 NOTE: the t-initialform is the sum of the terms with MAXIMAL weighted order w.r.t. w EXAMPLE: example tInitialForm; shows an example" { // take in lead(f) only the term of lowest t-order and set t=1 poly initialf=lead(f); // compute the order of lead(f) w.r.t. (1,w) int gewicht=scalarproduct(w,leadexp(f)); // do the same for the remaining part of f and compare the results // keep only the smallest ones int vglgewicht; f=f-lead(f); while (f!=0) { vglgewicht=scalarproduct(w,leadexp(f)); if (vglgewicht>gewicht) { initialf=lead(f); gewicht=vglgewicht; } else { if (vglgewicht==gewicht) { initialf=initialf+lead(f); } } f=f-lead(f); } initialf=substitute(initialf,var(1),1); return(initialf); } example { "EXAMPLE:"; echo=2; ring r=0,(t,x,y),dp; poly f=t4x2+y2-t2xy+t4x-t9; intvec w=-1,-2,-3; tInitialForm(f,w); } ///////////////////////////////////////////////////////////////////////// proc tInitialIdeal (ideal i,intvec w,list #) "USAGE: tInitialIdeal(i,w); i ideal, w intvec ASSUME: i is an ideal in Q[t,x_1,...,x_n] and w=(w_0,...,w_n) RETURN: ideal ini, the t-initial ideal of i with respect to w" { // THE PROCEDURE WILL BE CALLED FROM OTHER PROCEDURES INSIDE THIS LIBRARY; // IN THIS CASE THE VARIABLE t WILL INDEED BE THE LAST VARIABLE INSTEAD OF // THE FIRST, // AND WE THEREFORE HAVE TO MOVE IT BACK TO THE FRONT! // THIS IS NOT DOCUMENTED FOR THE GENERAL USER!!!! def BASERING=basering; int j; if (size(#)>0) { // we first have to move the variable t to the front again ideal variablen=var(nvars(basering)); for (j=1;j=1;j--) { if (w[j]<>0) // find the last non-zero component of w { int r=2; for (int k=1;k<=size(w);k++) { // fill the order matrix O with unit vectors if(k<>j) // except the unit vector of the non-zero component { intvec u; u[size(w)]=0; u[k]=1; O[r,1..size(w)]=u; r=r+1; kill u; } } return(O); } } } example { "EXAMPLE:"; echo=2; intvec v=2,3,0,0; weightVectorToOrderMatrix(v); } ///////////////////////////////////////////////////////////////////////// proc initialIdeal (ideal i, intvec w) "USAGE: initialIdeal(i,w); i ideal, w intvec ASSUME: i is an ideal in Q[x_1,...,x_n] and w=(w_1,...,w_n) RETURN: ideal, the initialIdeal of i w.r.t. w NOTE: the initialIdeal consists of the terms with MAXIMAL weighted order w.r.t. w EXAMPLE: example initialIdeal; shows an example" { def BASERING=basering; intmat O=weightVectorToOrderMatrix(w); execute("ring INITIALRING=("+charstr(BASERING)+"),("+varstr(basering)+"),M("+string(O)+");"); ideal i=imap(BASERING,i); i=std(i); ideal ini; for (int j=1;j<=size(i);j++) { ini[j]=initialForm(i[j],w); } setring BASERING; return(imap(INITIALRING,ini)); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y),dp; poly f=x3+y2-xy+x-1; intvec w=2,3; initialIdeal(f,w); } /////////////////////////////////////////////////////////////////////////////// /// PROCEDURES CONCERNED WITH THE LATEX CONVERSION /////////////////////////////////////////////////////////////////////////////// proc texNumber (poly p) "USAGE: texNumber(f); f poly RETURN: string, tex command representing leading coefficient of f using \frac EXAMPLE: example texNumber; shows an example" { number n=leadcoef(p); number den=denominator(n); number num=numerator(n); if (parstr(basering)=="") { if (den==-1) { den=-den; num=-num; } if (den==1) { return(string(num)); } else { return("\\tfrac{"+string(num)+"}{"+string(den)+"}"); } } def BASERING=basering; execute("ring PARAMETERRING=("+string(char(basering))+"),("+parstr(basering)+"),ds;"); poly den=imap(BASERING,den); poly num=imap(BASERING,num); if (den==1) { return(texPolynomial(num)); } else { return("\\tfrac{"+texPolynomial(num)+"}{"+texPolynomial(den)+"}"); } } example { "EXAMPLE:"; echo=2; ring r=(0,t),x,dp; texNumber((3t2-1)/t3); } ///////////////////////////////////////////////////////////////////////// proc texPolynomial (poly f) "USAGE: texPolynomial(f); f poly RETURN: string, the tex command representing f EXAMPLE: example texPolynomial; shows an example" { int altshort=short; short=0; if (f==0) { return("0"); } string texmf; string texco; string texf; string plus; int laenge=size(f); while (f!=0) { if (size(f)=1) { if (typeof(#[size(#)])=="string") { if (#[size(#)]!="max") { texdrawtp=texdrawtp+#[size(#)]; } } } // find the minimal and maximal coordinates of vertices // and find the scale factor for the texdraw image list SCFINPUT; SCFINPUT[1]=graph; list SCF=minScaleFactor(SCFINPUT); poly minx,miny,maxx,maxy=SCF[4],SCF[5],SCF[6],SCF[7]; poly centerx,centery=SCF[8],SCF[9]; int nachkomma=2; // number of decimals for the scalefactor number sf=1; // correction factor for scalefactor // if no scale factor was handed over to the procedure, use the // one computed by minScaleFactor; // check first if a scale factor has been handed over i=1; int scfpresent; while ((i<=size(#)) and (scfpresent==0)) { // if the scalefactor as polynomial was handed over, get it if (typeof(#[i])=="poly") { poly scalefactor=#[2]; scfpresent=1; } // if the procedure is called for drawing more than one tropical curve // then scalefactor,sf,nachkomma,minx,miny,maxx,maxy,centerx,centery // has been handed over to the procedure if (typeof(#[i])=="list") { poly scalefactor=#[i][1]; sf=#[i][2]; nachkomma=#[i][3]; minx=#[i][4]; miny=#[i][5]; maxx=#[i][6]; maxy=#[i][7]; centerx=#[i][8]; centery=#[i][9]; scfpresent=1; } i++; } // if no scalefactor was handed over we take the one computed in SCF if (scfpresent==0) { poly scalefactor=SCF[1]; sf=SCF[2]; nachkomma=SCF[3]; texdrawtp=texdrawtp+" \\relunitscale "+ decimal(scalefactor,nachkomma); } // compute the texdrawoutput for the tropical curve given by f list relxy; for (i=1;i<=size(graph)-1;i++) { // if the curve is a bunch of lines no vertex has to be drawn if (bunchoflines==0) { texdrawtp=texdrawtp+" \\move ("+decimal((graph[i][1]-centerx)/sf)+" "+decimal((graph[i][2]-centery)/sf)+") \\fcir f:0 r:"+decimal(2/(leadcoef(scalefactor)*10),size(string(int(scalefactor)))+1); } // draw the bounded edges emerging from the ith vertex for (j=1;j<=ncols(graph[i][3]);j++) { // don't draw it twice - and if there is only one vertex // and graph[i][3][1,1] is thus 0, nothing is done if (i1) and (noweights==0)) { texdrawtp=texdrawtp+" \\htext ("+decimal((graph[i][1]-centerx+graph[graph[i][3][1,j]][1])/(2*sf))+" "+decimal((graph[i][2]-centery+graph[graph[i][3][1,j]][2])/(2*sf))+"){$"+string(graph[i][3][2,j])+"$}"; } } } // draw the unbounded edges emerging from the ith vertex // they should not be too long for (j=1;j<=size(graph[i][4]);j++) { relxy=shorten(list(decimal((3*graph[i][4][j][1][1]/scalefactor)*sf),decimal((3*graph[i][4][j][1][2]/scalefactor)*sf),string(5*sf/2))); texdrawtp=texdrawtp+" \\move ("+decimal((graph[i][1]-centerx)/sf)+" "+decimal((graph[i][2]-centery)/sf)+") \\rlvec ("+relxy[1]+" "+relxy[2]+")"; // if the multiplicity is more than one, denote it in the picture if ((graph[i][4][j][2]>1) and (noweights==0)) { texdrawtp=texdrawtp+" \\htext ("+decimal(graph[i][1]/sf-centerx/sf+graph[i][4][j][1][1]/scalefactor)+" "+decimal(graph[i][2]/sf-centery/sf+graph[i][4][j][1][2]/scalefactor)+"){$"+string(graph[i][4][j][2])+"$}"; } } } // add lattice points if the scalefactor is >= 1/2 // and was not handed over if ((scalefactor>1/2) and (scfpresent==0)) { int uh=1; if (scalefactor>3) { uh=0; } texdrawtp=texdrawtp+" %% HERE STARTS THE CODE FOR THE LATTICE"; for (i=int(minx)-uh;i<=int(maxx)+uh;i++) { for (j=int(miny)-uh;j<=int(maxy)+uh;j++) { texdrawtp=texdrawtp+" \\move ("+decimal(i-centerx)+" "+decimal(j-centery)+") \\fcir f:0.8 r:"+decimal(1/(10*scalefactor),size(string(int(scalefactor)))+1); } } texdrawtp=texdrawtp+" %% HERE ENDS THE CODE FOR THE LATTICE "; } return(texdrawtp); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; poly f=x+y+x2y+xy2+1/t*xy; list graph=tropicalCurve(f); // compute the texdraw code of the tropical curve defined by f texDrawTropical(graph); // compute the texdraw code again, but set the scalefactor to 1 texDrawTropical(graph,"",1); } ///////////////////////////////////////////////////////////////////////// proc texDrawNewtonSubdivision (list graph,list #) "USAGE: texDrawNewtonSubdivision(graph[,#]); graph list, # optional list ASSUME: graph is the output of tropicalCurve RETURN: string, the texdraw code of the Newton subdivision of the tropical plane curve encoded by graph NOTE: - the list # may contain optional arguments, of which only one will be considered, namely the first entry of type 'poly'; this entry should be a rational number which specifies the scaling factor to be used; if it is missing, the factor will be computed; the list # may as well be empty @* - note that lattice points in the Newton subdivision which are black correspond to markings of the marked subdivision, while lattice points in grey are not marked EXAMPLE: example texDrawNewtonSubdivision; shows an example" { int i,j,k,l; list boundary=graph[size(graph)][1]; list inneredges=graph[size(graph)][2]; intvec shiftvector=graph[size(graph)][3]; string subdivision; // find maximal and minimal x- and y-coordinates and define the scalefactor poly maxx,maxy=1,1; for (i=1;i<=size(boundary);i++) { maxx=-minOfPolys(list(-maxx,-boundary[i][1])); maxy=-minOfPolys(list(-maxy,-boundary[i][2])); } // compute the scalefactor poly scalefactor=minOfPolys(list(12/leadcoef(maxx),12/leadcoef(maxy))); // Check if the scalefactor was handed over, then take that instead if (size(#)>0) { int scfpresent; i=1; while (i<=size(#) and scfpresent==0) { if (typeof(#[i])=="poly") { scalefactor=#[i]; scfpresent=1; } i++; } } // check if scaling is necessary if (scalefactor<1) { subdivision=subdivision+" \\relunitscale"+ decimal(scalefactor); } // define the texdraw code for the Newton subdivision for (i=1;i<=size(boundary)-1;i++) { subdivision=subdivision+" \\move ("+string(boundary[i][1])+" "+string(boundary[i][2])+") \\lvec ("+string(boundary[i+1][1])+" "+string(boundary[i+1][2])+")"; } subdivision=subdivision+" \\move ("+string(boundary[size(boundary)][1])+" "+string(boundary[size(boundary)][2])+") \\lvec ("+string(boundary[1][1])+" "+string(boundary[1][2])+") "; for (i=1;i<=size(inneredges);i++) { subdivision=subdivision+" \\move ("+string(inneredges[i][1][1])+" "+string(inneredges[i][1][2])+") \\lvec ("+string(inneredges[i][2][1])+" "+string(inneredges[i][2][2])+")"; } // add lattice points if the scalefactor is >= 1/2 if (scalefactor>1/2) { for (i=shiftvector[1];i<=int(maxx);i++) { for (j=shiftvector[2];j<=int(maxy);j++) { if (scalefactor > 2) { subdivision=subdivision+" \\move ("+string(i)+" "+string(j)+") \\fcir f:0.6 r:"+decimal(2/(10*scalefactor),size(string(int(scalefactor)))+1); } else { subdivision=subdivision+" \\move ("+string(i)+" "+string(j)+") \\fcir f:0.6 r:"+decimal(2/(20*scalefactor),size(string(int(scalefactor)))+1); } } } if ((shiftvector[1]!=0) or (shiftvector[2]!=0)) { subdivision=subdivision+" \\htext (-0.3 0.1){{\\tiny $(0,0)$}}"; } } // deal with the pathological cases if (size(boundary)==1) // then the Newton polytope is a point { subdivision=subdivision+" \\move ("+string(boundary[1][1])+" "+string(boundary[1][2])+") \\fcir f:0 r:0.15"; } else { matrix M[2][size(boundary)]; for (i=1;i<=size(boundary);i++) { M[1,i]=boundary[i][1]; M[2,i]=boundary[i][2]; } if ((size(boundary)-size(syz(M)))==1) { for (i=1;i<=size(boundary);i++) { subdivision=subdivision+" \\move ("+string(boundary[i][1])+" "+string(boundary[i][2])+") \\fcir f:0 r:"+decimal(2/(8*scalefactor),size(string(int(scalefactor)))+1); } } } // find the marked points in the subdivision poly pg; list markings; k=1; for (i=1;i=2;i--) { j=i-1; while (j>=1) { if (markings[i]==markings[j]) { markings=delete(markings,i); j=0; } j--; } } for (i=1;i<=size(markings);i++) { if (scalefactor > 2) { subdivision=subdivision+" \\move ("+string(markings[i][1])+" "+string(markings[i][2])+") \\fcir f:0 r:"+decimal(2/(8*scalefactor),size(string(int(scalefactor)))+1); } else { subdivision=subdivision+" \\move ("+string(markings[i][1])+" "+string(markings[i][2])+") \\fcir f:0 r:"+decimal(2/(16*scalefactor),size(string(int(scalefactor)))+1); } } // enclose subdivision in the texdraw environment string texsubdivision=" \\begin{texdraw} \\drawdim cm \\relunitscale 1 \\linewd 0.05" +subdivision+" \\end{texdraw} "; return(texsubdivision); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; poly f=x+y+x2y+xy2+1/t*xy; list graph=tropicalCurve(f); // compute the texdraw code of the Newton subdivision of the tropical curve texDrawNewtonSubdivision(graph); } ///////////////////////////////////////////////////////////////////////// proc texDrawTriangulation (list triang,list polygon) "USAGE: texDrawTriangulation(triang,polygon); triang,polygon list ASSUME: polygon is a list of integer vectors describing the lattice points of a marked polygon; triang is a list of integer vectors describing a triangulation of the marked polygon in the sense that an integer vector of the form (i,j,k) describes the triangle formed by polygon[i], polygon[j] and polygon[k] RETURN: string, a texdraw code for the triangulation described by triang without the texdraw environment EXAMPLE: example texDrawTriangulation; shows an example" { // the header of the texdraw output string latex=" \\drawdim cm \\relunitscale 1.2 \\arrowheadtype t:V "; int i,j; // indices list pairs,markings; // stores edges of the triangulation, respecively // the marked points for each triangle store the edges and marked // points of the triangle for (i=1;i<=size(triang);i++) { pairs[3*i-2]=intvec(triang[i][1],triang[i][2]); pairs[3*i-1]=intvec(triang[i][2],triang[i][3]); pairs[3*i]=intvec(triang[i][3],triang[i][1]); markings[3*i-2]=triang[i][1]; markings[3*i-1]=triang[i][2]; markings[3*i]=triang[i][3]; } // delete redundant pairs which occur more than once for (i=size(pairs);i>=1;i--) { for (j=1;j=1;i--) { for (j=1;jgewicht) { execute("koef="+leitkoef[2]+";"); initialf=koef*leadmonom(f); gewicht=vglgewicht; } else { if (vglgewicht==gewicht) { execute("koef="+leitkoef[2]+";"); initialf=initialf+koef*leadmonom(f); } } f=f-lead(f); } return(initialf); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; poly f=t4x2+y2-t2xy+t4x-1/t6; intvec w=2,3; tInitialFormParMax(f,w); } ///////////////////////////////////////////////////////////////////////// proc solveTInitialFormPar (ideal i) "USAGE: solveTInitialFormPar(i); i ideal ASSUME: i is a zero-dimensional ideal in Q(t)[x_1,...,x_n] generated by the (1,w)-homogeneous elements for some integer vector w - i.e. by the (1,w)-initialforms of polynomials RETURN: none NOTE: the procedure just displays complex approximations of the solution set of i EXAMPLE: example solveTInitialFormPar; shows an example" { i=subst(i,t,1); string CHARAKTERISTIK=charstr(basering); CHARAKTERISTIK=CHARAKTERISTIK[1..size(CHARAKTERISTIK)-2]; def BASERING=basering; execute("ring INITIALRING=("+CHARAKTERISTIK+"),("+varstr(basering)+"),("+ordstr(basering)+");"); list l=solve(imap(BASERING,i)); l; setring BASERING; // return(fetch(SUBSTRING,l)); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; ideal i=t2x2+y2,x-t2; solveTInitialFormPar(i); } ///////////////////////////////////////////////////////////////////////// proc detropicalise (def p) "USAGE: detropicalise(f); f poly or f list ASSUME: if f is of type poly then t is a linear polynomial with an arbitrary constant term and positive integer coefficients as further coefficients; @* if f is of type list then f is a list of polynomials of the type just described in before RETURN: poly, the detropicalisation of f ignoring the constant parts NOTE: the output will be a monomial and the constant coefficient has been ignored EXAMPLE: example detropicalise; shows an example" { poly dtp=1; while (p!=0) { if (leadmonom(p)!=1) { dtp=dtp*leadmonom(p)^int(leadcoef(p)); } p=p-lead(p); } return(dtp); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; detropicalise(3x+4y-1); } ///////////////////////////////////////////////////////////////////////// proc tDetropicalise (def p) "USAGE: tDetropicalise(f); f poly or f list ASSUME: if f is of type poly then f is a linear polynomial with an integer constant term and positive integer coefficients as further coefficients; @* if f is of type list then it is a list of polynomials of the type just described in before RETURN: poly, the detropicalisation of f over the field Q(t) NOTE: the output will be a term where the coeffiecient is a Laurent monomial in the variable t EXAMPLE: example tDetropicalise; shows an example" { poly dtp; if (typeof(p)=="list") { int i; for (i=1;i<=size(p);i++) { dtp=dtp+tDetropicalise(p[i]); } } else { dtp=1; while (p!=0) { if (leadmonom(p)!=1) { dtp=dtp*leadmonom(p)^int(leadcoef(p)); } else { dtp=t^int(leadcoef(p))*dtp; } p=p-lead(p); } } return(dtp); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; tDetropicalise(3x+4y-1); } /////////////////////////////////////////////////////////////////////////////// /// Auxilary Procedures concerned with conics /////////////////////////////////////////////////////////////////////////////// proc dualConic (poly f) "USAGE: dualConic(f); f poly ASSUME: f is an affine conic in two variables x and y RETURN: poly, the equation of the dual conic EXAMPLE: example dualConic; shows an example" { if (deg(f)!=2) { "The polynomial is not a conic"; return(0); } matrix A=coeffs(f,ideal(var(1)^2,var(1)*var(2),var(2)^2,var(1),var(2),1)); matrix C[3][3]=A[1,1],A[2,1]/2,A[4,1]/2,A[2,1]/2,A[3,1],A[5,1]/2,A[4,1]/2,A[5,1]/2,A[6,1]; matrix M[3][1]=var(1),var(2),1; matrix Cdual=-adjoint(C); matrix ffd=transpose(M)*Cdual*M; poly fdual=ffd[1,1]; return(fdual); } example { "EXAMPLE:"; echo=2; ring r=0,(x,y),dp; poly conic=2x2+1/2y2-1; dualConic(conic); } /////////////////////////////////////////////////////////////////////////////// /// Auxilary Procedures concerned with substitution /////////////////////////////////////////////////////////////////////////////// proc parameterSubstitute (poly f,int N) "USAGE: parameterSubstitute(f,N); f poly, N int ASSUME: f is a polynomial in Q(t)[x_1,...,x_n] describing a plane curve over Q(t) RETURN: poly f with t replaced by t^N EXAMPLE: example parameterSubstitute; shows an example" { def BASERING=basering; number nenner=1; for (int i=1;i<=size(f);i++) { nenner=nenner*denominator(leadcoef(f[i])); } f=f*nenner; f=subst(f,t,t^N)/number(subst(nenner,t,t^N)); return(f); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; poly f=t2xy+1/t*y+t3; parameterSubstitute(f,3); parameterSubstitute(f,-1); } ///////////////////////////////////////////////////////////////////////// proc tropicalSubst (poly f,int N,list #) "USAGE: parameterSubstitute(f,N,L); f poly, N int, L list ASSUME: f is a polynomial in Q(t)[x_1,...,x_k] and L is a list of the form var(i_1),poly_1,...,v(i_k),poly_k RETURN: list, the list is the tropical polynomial which we get from f by replacing the i-th variable be the i-th polynomial but in the i-th polynomial the parameter t is replaced by t^1/N EXAMPLE: example tropicalSubst; shows an example" { f=parameterSubstitute(f,N); f=substitute(f,#); list tp=tropicalise(f); poly const; for (int i=1;i<=size(tp);i++) { const=substitute(tp[i],x,0,y,0); tp[i]=tp[i]-const+const/N; } return(tp); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; poly f=t2x+1/t*y-1; tropicalSubst(f,2,x,x+t,y,tx+y+t2); // The procedure can be used to study the effect of a transformation of // the form x -> x+t^b, with b a rational number, on the tropicalisation and // the j-invariant of a cubic over the Puiseux series. f=t7*y3+t3*y2+t*(x3+xy2+y+1)+xy; // - the j-invariant, and hence its valuation, // does not change under the transformation jInvariant(f,"ord"); // - b=3/2, then the cycle length of the tropical cubic equals -val(j-inv) list g32=tropicalSubst(f,2,x,x+t3,y,y); tropicalJInvariant(g32); // - b=1, then it is still true, but only just ... list g1=tropicalSubst(f,1,x,x+t,y,y); tropicalJInvariant(g1); // - b=2/3, as soon as b<1, the cycle length is strictly less than -val(j-inv) list g23=tropicalSubst(f,3,x,x+t2,y,y); tropicalJInvariant(g23); } ///////////////////////////////////////////////////////////////////////// proc randomPolyInT (int d,int ug, int og, list #) "USAGE: randomPolyInT(d,ug,og[,#]); d, ug, og int, # list ASSUME: the basering has a parameter t RETURN: poly, a polynomial of degree d where the coefficients are of the form t^j with j a random integer between ug and og NOTE: if an optional argument # is given, then the coefficients are instead either of the form t^j as above or they are zero, and this is chosen randomly EXAMPLE: example randomPolyInT; shows an example" { if (defined(t)!=-1) { ERROR("basering has no paramter t");} int i,j,k; def BASERING=basering; ring RANDOMRING=(0,t),(x,y,z),dp; ideal m=maxideal(d); int nnn=size(m); for (i=1;i<=nnn;i++) { m[i]=subst(m[i],z,1); } poly randomPolynomial; for (i=1;i<=nnn;i++) { if (size(#)!=0) { k=random(0,1); } if (k==0) { j=random(ug,og); randomPolynomial=randomPolynomial+t^j*m[i]; } } setring BASERING; poly randomPolynomial=imap(RANDOMRING,randomPolynomial); if ((size(randomPolynomial)<3) and (nnn>=3)) { randomPolynomial=randomPolyInT(d,ug,og,#); } return(randomPolynomial); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; randomPolyInT(3,-2,5); randomPolyInT(3,-2,5,1); } ///////////////////////////////////////////////////////////////////////// proc cleanTmp () "USAGE: cleanTmp() PURPOSE: some procedures create latex and ps-files in the directory /tmp; in order to remove them simply call cleanTmp(); RETURN: none" { system("sh","cd /tmp; command rm -f tropicalcurve*; command rm -f tropicalnewtonsubdivision*"); } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// AUXILARY PROCEDURES, WHICH ARE DECLARED STATIC ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Procedures used in tropicalparametriseNoabs respectively in tropicalLifting: /// - phiOmega /// - cutdown /// - tropicalparametriseNoabs /// - findzeros /// - basictransformideal /// - testw /// - simplifyToOrder /// - scalarproduct /// - intvecdelete /// - invertorder /// - ordermaximalidealsNoabs /// - displaypoly /// - displaycoef /// - choosegfanvector /// - tropicalliftingresubstitute ////////////////////////////////////////////////////////////////////////////// static proc phiOmega (ideal i,int j,int wj) "USAGE: phiOmega(i,j,wj); i ideal, j int, wj int ASSUME: i an ideal in Q[t,x_1,...,x_n] and 00, in Q(t)[x]; the optional parameter # can contain the string 'isPrime' to indicate that the input ideal is prime and no minimal associated primes have to be computed RETURN: list, the first entry is a ring, namely the basering where some variables have been eliminated, and the ring contains the ideal i (with the same variables eliminated), the t-initial ideal ini of i (w.r.t. the weight vector where the entries corresponding to the deleted variables have been eliminated) and a list repl where for each eliminated variable there is one entry, namely a polynomial in the remaining variables and t that explains how resubstitution of a solution for the new i gives a solution for the old i; the second entry is the weight vector wvec with the components corresponding to the eliminated variables removed NOTE: needs the libraries random.lib and primdec.lib; is called from tropicalLifting" { // IDEA: i is an ideal of dimension d; we want to cut it with d random linear // forms in such a way that the resulting // ideal is 0-dim and still contains w in the tropical variety // NOTE: t is the last variable in the basering ideal pideal; //this is the ideal we want to return ideal cutideal; ideal pini; //this is the initial ideal ideal primini; //the initial of the prime we picl int j1,j2,dimp,winprim,j3; poly product=1; def BASERING=basering; ideal variablen; intvec setvec;intvec wvecp; setvec[nvars(basering)-1]=0; poly randomp=0; poly randomp1=0; poly randomp2=0; list erglini; list ergl; for (j1=1;j1<=nvars(basering)-1;j1++) { variablen=variablen+var(j1); // read the set of variables // (needed to make the quotring later) product=product*var(j1); // make product of all variables // (needed for the initial-monomial-check later } execute("ring QUOTRING=("+charstr(basering)+",t),("+string(variablen)+"),dp;"); setring BASERING; // change to quotring where we want to compute the primary decomposition of i if (size(#)==0) // we only have to do so if isPrime is not set { setring QUOTRING; ideal jideal=imap(BASERING,jideal); list primp=minAssGTZ(jideal); //compute the primary decomposition for (j1=1;j1<=size(primp);j1++) { for(j2=1;j2<=size(primp[j1]);j2++) { // clear all denominators primp[j1][j2]=primp[j1][j2]/content(primp[j1][j2]); } } setring BASERING; list primp=imap(QUOTRING,primp); // if i is not primary itself // go through the list of min. ass. primes and find the first // one which has w in its tropical variety if (size(primp)>1) { j1=1; while(winprim==0) { //compute the t-initial of the associated prime // - the last entry 1 only means that t is the last variable in the ring primini=tInitialIdeal(primp[j1],wvec,1); // check if it contains a monomial (resp if the product of var // is in the radical) if (radicalMemberShip(product,primini)==0) { // if w is in the tropical variety of the prime, we take that jideal=primp[j1]; setring QUOTRING; dimension=dim(groebner(imap(BASERING,jideal)));//compute its dimension setring BASERING; winprim=1; // and stop the checking } j1=j1+1; //else we look at the next associated prime } } else { jideal=primp[1]; //if i is primary itself we take its prime instead } } // now we start as a first try to intersect with a hyperplane parallel to // coordinate axes, because this would make our further computations // a lot easier. // We choose a subset of our n variables of size d=dim(ideal). // For each of these // variables, we want to fix a value: x_i= a_i*t^-w_i. // This will only work if the // projection of the d-dim variety to the other n-d variables // is the whole n-d plane. // Then a general choice for a_i will intersect the variety // in finitely many points. // If the projection is not the whole n-d plane, // then a general choice will not work. // We could determine if we picked a good // d-subset of variables using elimination // (NOTE, there EXIST d variables such that // a random choice of a_i's would work!). // But since this involves many computations, // we prefer to choose randomly and just // try in the end if our intersected ideal // satisfies our requirements. If this does not // work, we give up this try and use our second intersection idea, which // will work for a Zariksi-open subset (i.e. almost always). // // As random subset of d variables we choose // those for which the absolute value of the // wvec-coordinate is smallest, because this will // give us the smallest powers of t and hence // less effort in following computations. // Note that the smallest absolute value have those // which are biggest, because wvec is negative. //print("first try"); intvec wminust=intvecdelete(wvec,1); intmat A[2][size(wminust)]; // make a matrix with first row -wvec (without t) and second row 1..n A[1,1..size(wminust)]=-wminust; A[2,1..size(wminust)]=1..size(wminust); // sort this matrix in order to get // the d biggest entries and their position in wvec A=sortintmat(A); // we construct a vector which has 1 at entry j if j belongs to the list // of the d biggest entries of wvec and a 0 else for (j1=1;j1<=nvars(basering)-1;j1++) //go through the variables { for (j2=1;j2<=dimension;j2++) //go through the list of smallest entries { if (A[2,j2]==j1)//if the variable belongs to this list { setvec[j1]=1;//put a 1 } } } // using this 0/1-vector we produce // a random constant (i.e. coeff in Q times something in t) // for each of the biggest variables, // we add the forms x_i-random constant to the ideal // and we save the constant at the i-th place of // a list we want to return for later computations j3=0; while (j3<=1) { j3++; pideal=jideal; j2=1; for (j1=1;j1<=nvars(basering)-1;j1++) { if(setvec[j1]==1)//if x_i belongs to the biggest variables { if ((j3==1) and ((char(basering)==0) or (char(basering)>3))) { randomp1=random(1,3); randomp=t^(A[1,j2])*randomp1;// make a random constant // --- first we try small numbers } if ((j3==2) and ((char(basering)==0) or (char(basering)>100))) { randomp1=random(1,100); randomp=t^(A[1,j2])*randomp1;// make a random constant // --- next we try bigger numbers } else { randomp1=random(1,char(basering)-1); randomp=t^(A[1,j2])*randomp1;//make a random constant } ergl[A[2,j2]]=randomp;//and save the constant in a list erglini[A[2,j2]]=randomp1; j2=j2+1; } else { ergl[j1]=0; //if the variable is not among the d biggest ones, //save 0 in the list erglini[j1]=0; } } // print(ergl);print(pideal); // now we check if we made a good choice of pideal, i.e. if dim=0 and // wvec is still in the tropical variety // change to quotring where we compute dimension cutideal=pideal; for(j1=1;j1<=nvars(basering)-1;j1++) { if(setvec[j1]==1) { cutideal=cutideal,var(j1)-ergl[j1];//add all forms to the ideal } } setring QUOTRING; ideal cutideal=imap(BASERING,cutideal); dimp=dim(groebner(cutideal)); //compute the dim of p in the quotring //print("dimension"); //print(dimp); kill cutideal; setring BASERING; if (dimp==0) // if it is 0 as we want { // compute the t-initial of the associated prime // - the last 1 just means that the variable t is // the last variable in the ring pini=tInitialIdeal(cutideal,wvec ,1); //print("initial"); //print(pini); // and if the initial w.r.t. t contains no monomial // as we want (checked with // radical-membership of the product of all variables) if (radicalMemberShip(product,pini)==0) { // we made the right choice and now // we substitute the variables in the ideal // to get an ideal in less variables // also we make a projected vector // from wvec only the components of the remaining variables wvecp=wvec; variablen=0; j2=0; for(j1=1;j1<=nvars(basering)-1;j1++) { if(setvec[j1]==1)//if j belongs to the biggest variables { j2=j2+1; pideal=subst(pideal,var(j1),ergl[j1]);//substitute this variable pini=subst(pini,var(j1),erglini[j1]); wvecp=intvecdelete(wvecp,j1+2-j2); } else { variablen=variablen+var(j1); // read the set of remaining variables // (needed to make quotring later) } } // return pideal, the initial and the list ergl which tells us // which variables we replaced by which form execute("ring BASERINGLESS1=("+charstr(BASERING)+"),("+string(variablen)+",t),(dp("+string(ncols(variablen))+"),lp(1));"); ideal i=imap(BASERING,pideal); ideal ini=imap(BASERING,pini); //ideal ini2=tInitialIdeal(i,wvecp,1); list repl=imap(BASERING,ergl); export(i); export(ini); export(repl); return(list(BASERINGLESS1,wvecp)); } } } // this is our second try to cut down, which we only use if the first try // didn't work out. We intersect with d general hyperplanes // (i.e. we don't choose // them to be parallel to coordinate hyperplanes anymore. This works out with // probability 1. // // We choose general hyperplanes, i.e. linear forms which involve all x_i. // Each x_i has to be multiplied bz t^(w_i) in order // to get the same weight (namely 0) // for each term. As we cannot have negative exponents, we multiply // the whole form by t^minimumw. Notice that then in the first form, // there is one term without t- the term of the variable // x_i such that w_i is minimal. That is, we can solve for this variable. // In the second form, we can replace that variable, // and divide by t as much as possible. // Then there is again one term wihtout t - // the term of the variable with second least w. // So we can solve for this one again and also replace it in the first form. // Since all our coefficients are chosen randomly, // we can also from the beginning on // choose the set of variables which belong to the d smallest entries of wvec // (t not counting) and pick random forms g_i(t,x') // (where x' is the set of remaining variables) // and set x_i=g_i(t,x'). // // make a matrix with first row wvec (without t) and second row 1..n //print("second try"); setring BASERING; A[1,1..size(wminust)]=wminust; A[2,1..size(wminust)]=1..size(wminust); // sort this matrix in otder to get the d smallest entries // (without counting the t-entry) A=sortintmat(A); randomp=0; setvec=0; setvec[nvars(basering)-1]=0; // we construct a vector which has 1 at entry j if j belongs to the list of // the d smallest entries of wvec and a 0 else for (j1=1;j1<=nvars(basering)-1;j1++) //go through the variables { for (j2=1;j2<=dimension;j2++) //go through the list of smallest entries { if (A[2,j2]==j1)//if the variable belongs to this list { setvec[j1]=1;//put a 1 } } } variablen=0; wvecp=wvec; j2=0; for(j1=1;j1<=nvars(basering)-1;j1++) { if(setvec[j1]==1)//if j belongs to the biggest variables { j2=j2+1; wvecp=intvecdelete(wvecp,j1+2-j2);// delete the components // we substitute from wvec } else { variablen=variablen+var(j1); // read the set of remaining variables // (needed to make the quotring later) } } setring BASERING; execute("ring BASERINGLESS2=("+charstr(BASERING)+"),("+string(variablen)+",t),(dp("+string(ncols(variablen))+"),lp(1));"); // using the 0/1-vector which tells us which variables belong // to the set of smallest entries of wvec // we construct a set of d random linear // polynomials of the form x_i=g_i(t,x'), // where the set of all x_i is the set of // all variables which are in the list of smallest // entries in wvec, and x' are the other variables. // We add these d random linear polynomials to // the ideal pideal, i.e. we intersect // with these and hope to get something // 0-dim which still contains wvec in its // tropical variety. Also, we produce a list ergl // with g_i at the i-th position. // This is a list we want to return. // we try first with small numbers setring BASERING; pideal=jideal; for(j1=1;j1<=dimension;j1++)//go through the list of variables { // corres to the d smallest in wvec if ((char(basering)==0) or (char(basering)>3)) { randomp1=random(1,3); randomp=randomp1*t^(-A[1,j1]); } else { randomp1=random(1,char(basering)-1); randomp=randomp1*t^(-A[1,j1]); } for(j2=1;j2<=nvars(basering)-1;j2++)//go through all variables { if(setvec[j2]==0)//if x_j belongs to the set x' { // add a random term with the suitable power // of t to the random linear form if ((char(basering)==0) or (char(basering)>3)) { randomp2=random(1,3); randomp1=randomp1+randomp2*var(j2); randomp=randomp+randomp2*t^(wminust[j2]-A[1,j1])*var(j2); } else { randomp2=random(char(basering)-1); randomp1=randomp1+randomp2*var(j2); randomp=randomp+randomp2*t^(wminust[j2]-A[1,j1])*var(j2); } ergl[j2]=0;//if j belongs to x' we want a 0 in our list erglini[j2]=0; } } ergl[A[2,j1]]=randomp;// else we put there the random oly g_i(t,x') erglini[A[2,j1]]=randomp1; randomp=0; randomp1=0; } //print(ergl); // Again, we have to test if we made a good choice // to intersect,i.e. we have to check whether // pideal is 0-dim and contains wvec in the tropical variety. cutideal=pideal; for(j1=1;j1<=nvars(basering)-1;j1++) { if(setvec[j1]==1) { cutideal=cutideal,var(j1)-ergl[j1];//add all forms to the ideal } } setring QUOTRING; ideal cutideal=imap(BASERING,cutideal); dimp=dim(groebner(cutideal)); //compute the dim of p in the quotring //print("dimension"); //print(dimp); kill cutideal; setring BASERING; if (dimp==0) // if it is 0 as we want { // compute the t-initial of the associated prime // - the last 1 just means that the variable t // is the last variable in the ring pini=tInitialIdeal(cutideal,wvec ,1); //print("initial"); //print(pini); // and if the initial w.r.t. t contains no monomial as we want (checked with // radical-membership of the product of all variables) if (radicalMemberShip(product,pini)==0) { // we want to replace the variables x_i by the forms -g_i in // our ideal in order to return an ideal with less variables // first we substitute the chosen variables for(j1=1;j1<=nvars(basering)-1;j1++) { if(setvec[j1]==1)//if j belongs to the biggest variables { pideal=subst(pideal,var(j1),ergl[j1]);//substitute it pini=subst(pini,var(j1),erglini[j1]); } } setring BASERINGLESS2; ideal i=imap(BASERING,pideal); ideal ini=imap(BASERING,pini);//ideal ini2=tInitialIdeal(i,wvecp,1); list repl=imap(BASERING,ergl); export(i); export(ini); export(repl); return(list(BASERINGLESS2,wvecp)); } } // now we try bigger numbers while (1) //a never-ending loop which will stop with prob. 1 { // as we find a suitable ideal with that prob setring BASERING; pideal=jideal; for(j1=1;j1<=dimension;j1++)//go through the list of variables { // corres to the d smallest in wvec randomp1=random(1,100); randomp=randomp1*t^(-A[1,j1]); for(j2=1;j2<=nvars(basering)-1;j2++)//go through all variables { if(setvec[j2]==0)//if x_j belongs to the set x' { // add a random term with the suitable power // of t to the random linear form if ((char(basering)==0) or (char(basering)>100)) { randomp2=random(1,100); randomp1=randomp1+randomp2*var(j2); randomp=randomp+randomp2*t^(wminust[j2]-A[1,j1])*var(j2); } else { randomp2=random(1,char(basering)-1); randomp1=randomp1+randomp2; randomp=randomp+randomp2*t^(wminust[j2]-A[1,j1])*var(j2); } ergl[j2]=0;//if j belongs to x' we want a 0 in our list erglini[j2]=0; } } ergl[A[2,j1]]=randomp;// else we put there the random oly g_i(t,x') erglini[A[2,j1]]=randomp1; randomp=0; randomp1=0; } //print(ergl); // Again, we have to test if we made a good choice to // intersect,i.e. we have to check whether // pideal is 0-dim and contains wvec in the tropical variety. cutideal=pideal; for(j1=1;j1<=nvars(basering)-1;j1++) { if(setvec[j1]==1) { cutideal=cutideal,var(j1)-ergl[j1];//add all forms to the ideal } } setring QUOTRING; ideal cutideal=imap(BASERING,cutideal); dimp=dim(groebner(cutideal)); //compute the dim of p in the quotring //print("dimension"); //print(dimp); kill cutideal; setring BASERING; if (dimp==0) // if it is 0 as we want { // compute the t-initial of the associated prime // - the last 1 just means that the variable t // is the last variable in the ring pini=tInitialIdeal(cutideal,wvec ,1); //print("initial"); //print(pini); // and if the initial w.r.t. t contains no monomial // as we want (checked with // radical-membership of the product of all variables) if (radicalMemberShip(product,pini)==0) { // we want to replace the variables x_i by the forms -g_i in // our ideal in order to return an ideal with less variables //first we substitute the chosen variables for(j1=1;j1<=nvars(basering)-1;j1++) { if(setvec[j1]==1)//if j belongs to the biggest variables { pideal=subst(pideal,var(j1),ergl[j1]);//substitute it pini=subst(pini,var(j1),erglini[j1]); } } // return pideal and the list ergl which tells us // which variables we replaced by which form setring BASERINGLESS2; ideal i=imap(BASERING,pideal); ideal ini=imap(BASERING,pini);//ideal ini2=tInitialIdeal(i,wvecp,1); list repl=imap(BASERING,ergl); export(i); export(ini); export(repl); return(list(BASERINGLESS2,wvecp)); } } } } ///////////////////////////////////////////////////////////////////////// static proc tropicalparametriseNoabs (ideal i,intvec ww,int ordnung,int gfanold,int nogfan,int puiseux,list #) "USAGE: tropicalparametriseNoabs(i,tw,ord,gf,ng,pu[,#]); i ideal, tw intvec, ord int, gf,ng,pu int, # opt. list ASSUME: - i is an ideal in Q[t,x_1,...,x_n,X_1,...,X_k], tw=(w_0,w_1,...,w_n,0,...,0) and (w_0,...,w_n,0,...,0) is in the tropical variety of i, and ord is the order up to which a point in V(i) over C((t)) lying over w shall be computed; - moreover, k should be zero if the procedure is not called recursively; - the point in the tropical variety is supposed to lie in the NEGATIVE orthant; - the ideal is zero-dimensional when considered in (Q(t)[X_1,...,X_k]/m)[x_1,...,x_n], where m=#[2] is a maximal ideal in Q(t)[X_1,...,X_k]; - gf is 0 if version 2.2 or larger is used and it is 1 else - ng is 1 if gfan should not be executed - pu is 1 if n=1 and i is generated by one polynomial and newtonpoly is used to find a point in the tropical variety instead of gfan RETURN: list, l[1] = ring Q(0,X_1,...,X_r)[[t]] l[2] = int l[3] = string NOTE: - the procedure is also called recursively by itself, and if it is called in the first recursion, the list # is empty, otherwise #[1] is an integer, one more than the number of true variables x_1,...,x_n, and #[2] will contain the maximal ideal m in the variables X_1,...X_k by which the ring Q[t,x_1,...,x_n,X_1,...,X_k] should be divided to work correctly in K[t,x_1,...,x_n] where K=Q[X_1,...,X_k]/m is a field extension of Q; - the ring l[1] contains an ideal PARA, which contains the parametrisation of a point in V(i) lying over w up to the first ord terms; - the string m=l[3] contains the code of the maximal ideal m, by which we have to divide Q[X_1,...,X_r] in order to have the appropriate field extension over which the parametrisation lives; - and if the integer l[2] is N then t has to be replaced by t^1/N in the parametrisation, or alternatively replace t by t^N in the defining ideal - the procedure REQUIRES that the program GFAN is installed on your computer" { def ALTRING=basering; int recursively; // is set 1 if the procedure is called recursively by itself int jj,kk; if (size(#)==2) // this means the precedure has been called recursively { // how many variables are true variables, and how many come // from the field extension // only true variables have to be transformed int anzahlvariablen=#[1]; ideal gesamt_m=std(#[2]); // stores all maxideals used for field extensions // find the zeros of the w-initial ideal and transform the ideal i; // findzeros and basictransformideal need to know how // many of the variables are true variables list m_ring=findzeros(i,ww,anzahlvariablen); list btr=basictransformideal(i,ww,m_ring,anzahlvariablen); } else // the procedure has been called by tropicalLifting { // how many variables are true variables, and how many come from // the field extension only true variables have to be transformed int anzahlvariablen=nvars(basering); ideal gesamt_m; // stores all maxideals used for field extensions // the initial ideal of i has been handed over as #[1] ideal ini=#[1]; // find the zeros of the w-initial ideal and transform the ideal i; // we should hand the t-initial ideal ine to findzeros, // since we know it already list m_ring=findzeros(i,ww,ini); list btr=basictransformideal(i,ww,m_ring); } // check if for the transformation a field extension was necessary, i.e. if the // new variables had to be added to the old base ring; if so, change to the new // ring in which the transformed i and m and the zero a of V(m) live; otherwise // retreive i, a and m from btr if (size(btr)==1) { def PREVIOUSRING=basering; def TRRING=btr[1]; setring TRRING; ideal gesamt_m=imap(PREVIOUSRING,gesamt_m)+m; // add the newly found maximal // ideal to the previous ones } else { i=std(btr[1]); list a=btr[2]; ideal m=btr[3]; gesamt_m=gesamt_m+m; // add the newly found maximal // ideal to the previous ones } // check if there is a solution which has the n-th component zero, // if so, then eliminate the n-th variable from sat(i+x_n,t), // otherwise leave i as it is; // then check if the (remaining) ideal has as solution // where the n-1st component is zero, // and procede as before; do the same for the remaining variables; // this way we make sure that the remaining ideal has // a solution which has no component zero; intvec deletedvariables; // the jth entry is set 1, if we eliminate x_j int numberdeletedvariables; // the number of eliminated variables ideal variablen; // will contain the variables which are not eliminated intvec tw=ww; // in case some variables are deleted, // we have to store the old weight vector deletedvariables[anzahlvariablen]=0; ideal I,LI; i=i+m; // if a field extension was necessary, then i has to be extended by m for (jj=anzahlvariablen-1;jj>=1;jj--) // the variable t is the last one !!! { I=sat(ideal(var(jj)+i),t)[1]; LI=subst(I,var(nvars(basering)),0); //size(deletedvariables)=anzahlvariablen(before elim.) for (kk=1;kk<=size(deletedvariables)-1;kk++) { LI=subst(LI,var(kk),0); } if (size(LI)==0) // if no power of t is in lead(I) { // (where the X(i) are considered as field elements) // get rid of var(jj) i=eliminate(I,var(jj)); deletedvariables[jj]=1; anzahlvariablen--; // if a variable is eliminated, // then the number of true variables drops numberdeletedvariables++; } else { variablen=variablen+var(jj); // non-eliminated true variables are stored } } variablen=invertorder(variablen); // store also the additional variables and t, // since they for sure have not been eliminated for (jj=anzahlvariablen+numberdeletedvariables-1;jj<=nvars(basering);jj++) { variablen=variablen+var(jj); } // if some variables have been eliminated, // then pass to a new ring which has less variables, // but if no variables are left, then we are done def BASERING=basering; if ((numberdeletedvariables>0) and (anzahlvariablen>1)) // if only t remains, { // all true variables are gone execute("ring NEURING=("+charstr(basering)+"),("+string(variablen)+"),(dp("+string(size(variablen)-1)+"),lp(1));"); ideal i=imap(BASERING,i); ideal gesamt_m=imap(BASERING,gesamt_m); } // now we have to compute a point ww on the tropical variety // of the transformed ideal i; // of course, we only have to do so, if we have not yet // reached the order up to which we // were supposed to do our computations if ((ordnung>1) and (anzahlvariablen>1)) // if only t remains, { // all true variables are gone // else we have to use gfan def PREGFANRING=basering; if (nogfan!=1) { // pass to a ring which has variables which are suitable for gfan execute("ring GFANRING=("+charstr(basering)+"),(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,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),dp;"); ideal phiideal=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,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; phiideal[nvars(PREGFANRING)]=a; // map t to a map phi=PREGFANRING,phiideal; ideal i=phi(i); // homogenise the ideal i with the first not yet // used variable in our ring, since gfan // only handles homogenous ideals; in principle // for this one has first to compute a // standard basis of i and homogenise that, // but for the tropical variety (says Anders) // it suffices to homogenise an arbitrary system of generators // i=groebner(i); i=homog(i,maxideal(1)[nvars(PREGFANRING)+1]); // if gfan version >= 0.3.0 is used and the characteristic // is not zero, then write the basering to the output if ((gfanold!=1) and (char(GFANRING)!=0)) { string ringvariablen=varstr(GFANRING); ringvariablen=ringvariablen[1..2*nvars(PREGFANRING)+1]; write(":w /tmp/gfaninput","Z/"+string(char(GFANRING))+"Z["+ringvariablen+"]"); // write the ideal to a file which gfan takes as input and call gfan write(":a /tmp/gfaninput","{"+string(i)+"}"); } else { // write the ideal to a file which gfan takes as input and call gfan write(":w /tmp/gfaninput","{"+string(i)+"}"); } if (gfanold==1) { if (charstr(basering)!="0") { system("sh","gfan_tropicalbasis --mod "+charstr(basering)+" < /tmp/gfaninput > /tmp/gfanbasis"); system("sh","gfan_tropicalintersection < /tmp/gfanbasis > /tmp/gfanoutput"); } else { // system("sh","gfan_tropicalstartingcone < /tmp/gfaninput > /tmp/gfantropstcone"); // system("sh","gfan_tropicaltraverse < /tmp/gfantropstcone > /tmp/gfanoutput"); system("sh","gfan_tropicalbasis < /tmp/gfaninput > /tmp/gfanbasis"); system("sh","gfan_tropicalintersection < /tmp/gfanbasis > /tmp/gfanoutput"); } string trop=read("/tmp/gfanoutput"); setring PREGFANRING; intvec wneu=-1; // this integer vector will store // the point on the tropical variety wneu[nvars(basering)]=0; // for the time being simply stop Singular and set wneu by yourself int goon=1; trop; "CHOOSE A RAY IN THE OUTPUT OF GFAN WHICH HAS ONLY"; "NON-POSITIVE ENTRIES AND STARTS WITH A NEGATIVE ONE,"; "E.G. (-3,-4,-1,-5,0,0,0) - the last entry will always be 0 -"; "THEN TYPE THE FOLLOWING COMMAND IN SINGULAR: wneu=-3,-4,-1,-5,0,0;"; "AND HIT THE RETURN BUTTON TWICE (!!!) - NOTE, THE LAST 0 IS OMITTED"; "IF YOU WANT wneu TO BE TESTED, THEN SET goon=0;"; // THIS IS NOT NECESSARY !!!! IF WE COMPUTE NOT ONLY THE // TROPICAL PREVARIETY // test, if wneu really is in the tropical variety while (goon==0) { if (testw(reduce(i,std(gesamt_m)),wneu,anzahlvariablen)==1) { "CHOOSE A DIFFERENT RAY"; } else { goon=1; } } } else { system("sh","gfan_tropicallifting -n "+string(anzahlvariablen)+" --noMult -c < /tmp/gfaninput > /tmp/gfanoutput"); // read the result from gfan and store it to a string, // which in a later version // should be interpreded by Singular intvec wneu=choosegfanvector(read("/tmp/gfanoutput"),0)[1]; setring PREGFANRING; } } else // if gfan is NOT executed { // if puiseux is set, then we are in the case of a plane curve and can use the command newtonpoly if (puiseux==1) { list NewtP=newtonpoly(i[1]); wneu=NewtP[1]-NewtP[2]; int ggteiler=gcd(wneu[1],wneu[2]); wneu[1]=-wneu[1] div ggteiler; wneu[2]=wneu[2] div ggteiler; if (wneu[1]>0) { wneu=-wneu; } kill NewtP,ggteiler; } else // set wneu by hand { "Set intvec wneu!"; } } } // if we have not yet computed our parametrisation // up to the required order and // zero is not yet a solution, then we have // to go on by calling the procedure recursively; // if all variables were deleted, then i=0 and thus anzahlvariablen==0 if ((ordnung>1) and (anzahlvariablen>1)) { // we call the procedure with the transformed ideal i, // the new weight vector, with the // required order lowered by one, and with // additional parameters, namely the number of // true variables and the maximal ideal that // was computed so far to describe the field extension list PARALIST=tropicalparametriseNoabs(i,wneu,ordnung-1,gfanold,nogfan,puiseux,anzahlvariablen,gesamt_m); // the output will be a ring, in which the // parametrisation lives, and a string, which contains // the maximal ideal that describes the necessary field extension def PARARing=PARALIST[1]; int tweight=-tw[1]*PARALIST[2]; string PARAm=PARALIST[3]; setring PARARing; // if some variables have been eliminated in before, // then we have to insert zeros // into the parametrisation for those variables if (numberdeletedvariables>0) { ideal PARAneu=PARA; int k; for (jj=1;jj<=anzahlvariablen+numberdeletedvariables-1;jj++) // t admits { // no parametrisation if (deletedvariables[jj]!=1) { k++; PARA[jj]=PARAneu[k]; } else { PARA[jj]=poly(0); } } } } // otherwise we are done and we can start to compute // the last step of the parametrisation else { // we store the information on m in a string string PARAm=string(gesamt_m); // we define the weight of t, i.e. in the parametrisation t // has to be replaced by t^1/tweight int tweight=-tw[1]; // if additional variables were necessary, // we introduce them now as parameters; // in any case the parametrisation ring will // have only one variable, namely t, // and its order will be local, so that it // displays the lowest term in t first if (anzahlvariablen+numberdeletedvariables (a_j+x_j)*t^w_j l[2] = list, a_1,...,a_n a point in V(m) l[3] = ideal, the maximal ideal m or l[1] = ring which contains the ideals i and m, and the list a NOTE: the procedure is called from inside the recursive procedure tropicalparametriseNoabs; if it is called in the first recursion, the list # is empty, otherwise #[1] is an integer, the number of true variables x_1,...,x_n; during the procedure we check if a field extension is necessary to express a zero (a_1,...,a_n) of m; if so, we have to introduce new variables and a list containing a ring is returned, otherwise the list containing i, a and m is returned; the ideal m will be changed during the procedure since all variables which reduce to a polynomial in X_1,...,X_k modulo m will be eliminated, while the others are replaced by new variables X_k+1,...,X_k'" { def BASERING=basering; // the variable t is acutally the LAST variable !!! int j,k; // counters // store the weighted degrees of the elements of i in an integer vector intvec wdegs; for (j=1;j<=size(i);j++) { wdegs[j]=deg(i[j],intvec(w[2..size(w)],w[1])); } // how many variables are true variables, // and how many come from the field extension // only real variables have to be transformed if (size(#)>0) { int anzahlvariablen=#[1]; } else { int anzahlvariablen=nvars(basering); } // int zaehler; // testvariable // get the information if any new variables are needed from m_ring int neuvar=m_ring[2]; // number of variables which have to be added intvec neuevariablen=m_ring[3]; // [i]=1, if for the ith comp. // of a zero of m a new variable is needed def MRING=m_ring[1]; // MRING contains a and m list a=imap(MRING,a); // (a_1,...,a_n)=(a[2],...,a[n+1]) will be // a common zero of the ideal m ideal m=std(imap(MRING,m)); // m is zero, if neuvar==0, // otherwise we change the ring anyway // if a field extension is needed, then extend the polynomial // ring by new variables X_k+1,...,X_k'; if (neuvar>0) { // change to a ring where for each variable needed // in m a new variable has been introduced ideal variablen; // extract the variables x_1,...,x_n for (j=1;jt^w_0 { a[j]=X(zaehler); zaehler++; } for (k=1;k<=size(i);k++) { if (j!=1) // corresponds to x_(j-1) -- note t is the last variable { i[k]=substitute(i[k],var(j-1),(a[j]+var(j-1))*t^(-w[j])); } else // corresponds to t { i[k]=substitute(i[k],t,t^(-w[j])); } } } // we can divide the jth generator of i by t^-wdegs[j] for (j=1;j<=ncols(i);j++) { if (wdegs[j]<0) // if wdegs[j]==0 there is no need to divide, and { // we made sure that it is no positive i[j]=i[j]/t^(-wdegs[j]); } } // since we want to consider i now in the ring // (Q[X_1,...,X_k']/m)[t,x_1,...,x_n] // we can reduce i modulo m, so that "constant terms" // which are "zero" since they // are in m will disappear; simplify(...,2) then really removes them i=simplify(reduce(i,m),2); // if new variables have been introduced, we have // to return the ring containing i, a and m // otherwise we can simply return a list containing i, a and m if (neuvar>0) { export(m); export(i); export(a); list returnlist=TRANSFORMRING; return(returnlist); } else { return(list(i,a,m)); } } ///////////////////////////////////////////////////////////////////////// static proc testw (ideal i,intvec w,int anzahlvariablen,list #) "USAGE: testw(i,w,n); i ideal, w intvec, n number ASSUME: i is an ideal in Q[t,x_1,...,x_n,X_1,...,X_k] and w=(w_0,...,w_n,0,...,0) RETURN: int b, 0 if the t-initial ideal of i considered in Q(X_1,...,X_k)[t,x_1,...,x_n] is monomial free, 1 else NOTE: the procedure is called by tinitialform" { // compute the t-initial of i // - the last 1 just means that the variable t is the last variable in the ring if (size(#)==0) { ideal tin=tInitialIdeal(i,w); } else { ideal tin=tInitialIdeal(i,w,1); } int j; ideal variablen; poly monom=1; if (size(#)==0) { for (j=2;j<=anzahlvariablen;j++) { variablen=variablen+var(j); monom=monom*var(j); } ideal Parameter; for (j=anzahlvariablen+1;j<=nvars(basering);j++) { Parameter=Parameter+var(j); } } else { for (j=1;j<=anzahlvariablen-1;j++) { variablen=variablen+var(j); monom=monom*var(j); } ideal Parameter; for (j=anzahlvariablen;j<=nvars(basering)-1;j++) { Parameter=Parameter+var(j); } } def BASERING=basering; if (anzahlvariablensize(w)) or (size(w)==1)) { return(w); } if (i==1) { return(w[2..size(w)]); } if (i==size(w)) { return(w[1..size(w)-1]); } else { intvec erg=w[1..i-1],w[i+1..size(w)]; return(erg); } } ///////////////////////////////////////////////////////////////////////// static proc invertorder (ideal i) "USAGE: intvertorder(i); i ideal RETURN: ideal, the order of the entries of i has been inverted NOTE: the procedure is called by tropicalparametriseNoabs" { ideal ausgabe; for (int j=size(i);j>=1;j--) { ausgabe[size(i)-j+1]=i[j]; } return(ausgabe); } ///////////////////////////////////////////////////////////////////////// static proc ordermaximalidealsNoabs (list minassi,int anzahlvariablen) "USAGE: ordermaximalidealsNoabs(minassi); minassi list ASSUME: minassi is a list of maximal ideals RETURN: list, the procedure orders the maximal ideals in minassi according to how many new variables are needed to describe the zeros of the ideal l[j][1] = jth maximal ideal l[j][2] = the number of variables needed l[j][3] = intvec, if for the kth variable a new variable is needed to define the corresponding zero of l[j][1], then the k+1st entry is one l[j][4] = list, if for the kth variable no new variable is needed to define the corresponding zero of l[j][1], then its value is the k+1st entry NOTE: if a maximal ideal contains a variable, it is removed from the list; the procedure is called by findzeros" { int j,k,l; int neuvar; // number of new variables needed (for each maximal ideal) int pruefer; // is set one if a maximal ideal contains a variable list minassisort; // will contain the output for (j=1;j<=size(minassi);j++){minassisort[j]=0;} // initialise minassisort // to fix its initial length list zwischen; // needed for reordering list a;// (a_1,...,a_n)=(a[2],...,a[n+1]) will be a common zero of the ideal m poly nf; // normalform of a variable w.r.t. m intvec neuevariablen; // ith entry is 1, if for the ith component of a zero // of m a new variable is needed intvec testvariablen; // integer vector of length n=number of variables // compute for each maximal ideal the number of new variables, // which are needed to describe // its zeros -- note, a new variable is needed if modulo // the maximal ideal it does not reduce // to something which only depends on the following variables; // if no new variable is needed, then store the value // a variable reduces to in the list a; for (j=size(minassi);j>=1;j--) { a[1]=poly(0); // the first entry in a and in neuevariablen // corresponds to the variable t, neuevariablen[1]=0; // which is not present in the INITIALRING neuvar=0; minassi[j]=std(minassi[j]); for (k=1;(k<=anzahlvariablen-1) and (pruefer==0);k++) { nf=reduce(var(k),minassi[j]); // if a variable reduces to zero, then the maximal ideal // contains a variable and we can delete it if (nf==0) { pruefer=1; } // set the entries of testvariablen corresponding to the first // k variables to 1, and the others to 0 for (l=1;l<=nvars(basering);l++) { if (l<=k) { testvariablen[l]=1; } else { testvariablen[l]=0; } } // if the variable x_j reduces to a polynomial // in x_j+1,...,x_n,X_1,...,X_k modulo m // then we can eliminate x_j from the maximal ideal // (since we do not need any // further field extension to express a_j) and a_j // will just be this normalform, // otherwise we have to introduce a new variable in order to express a_j; if (scalarproduct(leadexp(nf),testvariablen)==0) { a[k+1]=nf; // a_k is the normal form of the kth variable modulo m neuevariablen[k+1]=0; // no new variable is needed } else { a[k+1]=poly(0); // a_k is set to zero until we have // introduced the new variable neuevariablen[k+1]=1; neuvar++; // the number of newly needed variables is raised by one } } // if the maximal ideal contains a variable, we simply delete it if (pruefer==0) { minassisort[j]=list(minassi[j],neuvar,neuevariablen,a); } // otherwise we store the information on a, // neuevariablen and neuvar together with the ideal else { minassi=delete(minassi,j); minassisort=delete(minassisort,j); pruefer=0; } } // sort the maximal ideals ascendingly according to // the number of new variables needed to // express the zero of the maximal ideal for (j=2;j<=size(minassi);j++) { l=j; for (k=j-1;k>=1;k--) { if (minassisort[l][2]1) and (N==1)) { dp=dp+displaycoef(koeffizienten[j-ord(p)+1])+"*t^"+string(j-(N*wj) div w1); } if (((j-(N*wj) div w1)>1) and (N!=1)) { dp=dp+displaycoef(koeffizienten[j-ord(p)+1])+"*t^("+string(j-(N*wj) div w1)+"/"+string(N)+")"; } if (((j-(N*wj) div w1)<-1) and (N==1)) { dp=dp+displaycoef(koeffizienten[j-ord(p)+1])+"*1/t^"+string(wj-j); } if (((j-(N*wj) div w1)<-1) and (N!=1)) { dp=dp+displaycoef(koeffizienten[j-ord(p)+1])+"*1/t^("+string((N*wj) div w1-j)+"/"+string(N)+")"; } if (j0) // noAbs was used { execute("ring NOQRing=("+string(char(LIFTRing))+"),("+varstr(basering)+","+parstr(LIFTRing)+"),dp;"); execute("qring TESTRing=std("+#[1]+");"); ideal i=imap(BASERING,i); } else // absolute primary decomposition was used { setring LIFTRing; poly mp=minpoly; execute("ring TESTRing=("+charstr(LIFTRing)+"),("+varstr(BASERING)+"),dp;"); minpoly=number(imap(LIFTRing,mp)); ideal i=imap(BASERING,i); } } else { def TESTRing=BASERING; setring TESTRing; } // map the ideal LIFT to the TESTRing and substitute the solutions in i ideal liftideal=imap(LIFTRing,LIFT); for (int j=1;j<=ncols(liftideal);j++) { i=substitute(i,var(j),liftideal[j]); } // map the resulting i back to LIFTRing; // if noAbs, then reduce i modulo the maximal ideal // before going back to LIFTRing if ((size(parstr(LIFTRing))!=0) and size(#)>0) { i=reduce(i,std(0)); setring LIFTRing; ideal i=imap(TESTRing,i); } else { setring LIFTRing; ideal i=imap(TESTRing,i); } list SUBSTTEST; // replace t by t^1/N for (j=1;j<=ncols(i);j++) { SUBSTTEST[j]=displaypoly(i[j],N,0,1); } return(SUBSTTEST); } /////////////////////////////////////////////////////////////////////////////// /// Procedures used in tropicalLifting when using absolute primary decomposition /// - tropicalparametrise /// - eliminatecomponents /// - findzerosAndBasictransform /// - ordermaximalideals /////////////////////////////////////////////////////////////////////////////// static proc tropicalparametrise (ideal i,intvec ww,int ordnung,intvec ordnungskontrollvektor,int gfanold,int findall,int nogfan,int puiseux,list #) "USAGE: tropicalparametrise(i,tw,ord,gf,fa,ng,pu[,#]); i ideal, tw intvec, ord int, gf,fa,ng,pu int, # opt. list ASSUME: - i is an ideal in Q[t,x_1,...,x_n,@a], tw=(w_0,w_1,...,w_n,0) and (w_0,...,w_n,0) is in the tropical variety of i, and ord is the order up to which a point in V(i) over K{{t}} lying over w shall be computed; - moreover, @a should be not be there if the procedure is not called recursively; - the point in the tropical variety is supposed to lie in the NEGATIVE orthant; - the ideal is zero-dimensional when considered in (K(t)[@a]/m)[x_1,...,x_n], where m=#[2] is a maximal ideal in K[@a]; - gf is 0 if version 2.2 or larger is used and it is 1 else - fa is 1 if all solutions should be found - ng is 1 if gfan should not be executed - pu is 1 if n=1 and i is generated by one polynomial and newtonpoly is used to find a point in the tropical variety instead of gfan RETURN: list, l[1] = ring K[@a]/m[[t]] l[2] = int NOTE: - the procedure is also called recursively by itself, and if it is called in the first recursion, the list # is empty, otherwise #[1] is an integer, one more than the number of true variables x_1,...,x_n, and #[2] will contain the maximal ideal m in the variable @a by which the ring K[t,x_1,...,x_n,@a] should be divided to work correctly in L[t,x_1,...,x_n] where L=Q[@a]/m is a field extension of K - the ring l[1] contains an ideal PARA, which contains the parametrisation of a point in V(i) lying over w up to the first ord terms; - the string m contains the code of the maximal ideal m, by which we have to divide K[@a] in order to have the appropriate field extension over which the parametrisation lives; - and if the integer l[3] is N then t has to be replaced by t^1/N in the parametrisation, or alternatively replace t by t^N in the defining ideal - the procedure REQUIRES that the program GFAN is installed on your computer" { def BASERING=basering; int recursively; // is set 1 if the procedure is called recursively by itself int ii,jj,kk,ll,jjj,kkk,lll; if (typeof(#[1])=="int") // this means the precedure has been { // called recursively // how many variables are true variables, and how many come // from the field extension // only true variables have to be transformed int anzahlvariablen=#[1]; // find the zeros of the w-initial ideal and transform the ideal i; // findzeros and basictransformideal need to know // how many of the variables are true variables // and do the basic transformation as well list zerolist=#[2]; list trring=findzerosAndBasictransform(i,ww,zerolist,findall,anzahlvariablen); } else // the procedure has been called by tropicalLifting { // how many variables are true variables, and // how many come from the field extension // only true variables have to be transformed int anzahlvariablen=nvars(basering); list zerolist; // will carry the zeros which are //computed in the recursion steps // the initial ideal of i has been handed over as #[1] ideal ini=#[1]; // find the zeros of the w-initial ideal and transform the ideal i; // we should hand the t-initial ideal ine to findzeros, // since we know it already; // and do the basic transformation as well list trring=findzerosAndBasictransform(i,ww,zerolist,findall,ini); } list wneulist; // carries all newly computed weight vector intvec wneu; // carries the newly computed weight vector intvec okvneu; // carries the newly computed ordnungskontrollvektor int tweight; // carries the weight of t list PARALIST; // carries the result when tropicalparametrise // is recursively called list eliminaterings; // carries the result of eliminatecomponents intvec deletedvariables; // contains inform. which variables have been deleted deletedvariables[anzahlvariablen-1]=0; // initialise this vector int numberdeletedvariables; // the number of deleted variables int oldanzahlvariablen=anzahlvariablen; // anzahlvariablen for later reference list liftings,partliftings; // the computed liftings (all resp. partly) // consider each ring which has been returned when computing the zeros of the // the t-initial ideal, equivalently, consider // each zero which has been returned for (jj=1;jj<=size(trring);jj++) { def TRRING=trring[jj]; setring TRRING; // check if a certain number of components lead to suitable // solutions with zero components; // compute them all if findall==1 eliminaterings=eliminatecomponents(i,m,oldanzahlvariablen,findall,oldanzahlvariablen-1,deletedvariables); // consider each of the rings returned by eliminaterings ... // there is at least one !!! for (ii=1;ii<=size(eliminaterings);ii++) { // #variables which have been eliminated numberdeletedvariables=oldanzahlvariablen-eliminaterings[ii][2]; // #true variables which remain (including t) anzahlvariablen=eliminaterings[ii][2]; // a 1 in this vector says that variable was eliminated deletedvariables=eliminaterings[ii][3]; setring TRRING; // set TRRING - this is important for the loop // pass the ring computed by eliminatecomponents def PREGFANRING=eliminaterings[ii][1]; setring PREGFANRING; poly m=imap(TRRING,m); // map the maximal ideal to this ring list zero=imap(TRRING,zero); // map the vector of zeros to this ring // now we have to compute a point ww on the tropical // variety of the transformed ideal i; // of course, we only have to do so, if we have // not yet reached the order up to which we // were supposed to do our computations if ((ordnung>1) and (anzahlvariablen>1)) // if only t remains, { // all true variables are gone if (nogfan!=1) { // pass to a ring which has variables which are suitable for gfan execute("ring GFANRING=("+string(char(basering))+"),(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,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),dp;"); ideal phiideal=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,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; phiideal[nvars(PREGFANRING)]=a; // map t to a map phi=PREGFANRING,phiideal; ideal II=phi(i); // homogenise the ideal II with the first not yet // used variable in our ring, since gfan // only handles homogenous ideals; in principle for this // one has first to compute a // standard basis of II and homogenise that, // but for the tropical variety (says Anders) // it suffices to homogenise an arbitrary system of generators // II=groebner(II); II=homog(II,maxideal(1)[nvars(PREGFANRING)+1]); // if gfan version >= 0.3.0 is used and the characteristic // is not zero, then write the basering to the output if ((gfanold!=1) and (char(GFANRING)!=0)) { string ringvariablen=varstr(GFANRING); ringvariablen=ringvariablen[1..2*nvars(PREGFANRING)+1]; write(":w /tmp/gfaninput","Z/"+string(char(GFANRING))+"Z["+ringvariablen+"]"); // write the ideal to a file which gfan takes as input and call gfan write(":a /tmp/gfaninput","{"+string(II)+"}"); } else { // write the ideal to a file which gfan takes as input and call gfan write(":w /tmp/gfaninput","{"+string(II)+"}"); } if (gfanold==1) { if (charstr(basering)!="0") { system("sh","gfan_tropicalbasis --mod "+charstr(basering)+" < /tmp/gfaninput > /tmp/gfanbasis"); system("sh","gfan_tropicalintersection < /tmp/gfanbasis > /tmp/gfanoutput"); } else { // system("sh","gfan_tropicalstartingcone < /tmp/gfaninput > /tmp/gfantropstcone"); // system("sh","gfan_tropicaltraverse < /tmp/gfantropstcone > /tmp/gfanoutput"); system("sh","gfan_tropicalbasis < /tmp/gfaninput > /tmp/gfanbasis"); system("sh","gfan_tropicalintersection < /tmp/gfanbasis > /tmp/gfanoutput"); } string trop=read("/tmp/gfanoutput"); setring PREGFANRING; wneu=-1; // this integer vector will store the point on the tropical variety wneu[nvars(basering)]=0; // for the time being simply stop Singular and set wneu by yourself int goon=1; trop; "CHOOSE A RAY IN THE OUTPUT OF GFAN WHICH HAS ONLY"; "NON-POSITIVE ENTRIES AND STARTS WITH A NEGATIVE ONE,"; "E.G. (-3,-4,-1,-5,0,0,0) - the last entry will always be 0 -"; "THEN TYPE THE FOLLOWING COMMAND IN SINGULAR: wneu=-3,-4,-1,-5,0,0;"; "AND HIT THE RETURN BUTTON - NOTE, THE LAST 0 IS OMITTED"; "IF YOU WANT wneu TO BE TESTED, THEN SET goon=0;"; // THIS IS NOT NECESSARY !!!! IF WE COMPUTE NOT ONLY // THE TROPICAL PREVARIETY // test, if wneu really is in the tropical variety while (goon==0) { if (testw(reduce(i,std(gesamt_m)),wneu,anzahlvariablen)==1) { "CHOOSE A DIFFERENT RAY"; } else { goon=1; } } wneulist[1]=wneu; } else { system("sh","gfan_tropicallifting -n "+string(anzahlvariablen)+" --noMult -c < /tmp/gfaninput > /tmp/gfanoutput"); // read the result from gfan and store it to a string, // which in a later version // should be interpreded by Singular wneulist=choosegfanvector(read("/tmp/gfanoutput"),findall); setring PREGFANRING; } kill GFANRING; } else // if gfan is NOT executed { // if puiseux is set, then we are in the case of a plane curve and can use the command newtonpoly if (puiseux==1) { if (nvars(basering)>2) // if the basering has a parameter { // we have to pass to a ring with two variables to compute the newtonpoly def PRENPRing=basering; poly NPpoly=i[1]; ring NPRING=(0,@a),(x(1),t),ds; poly NPpoly=imap(PRENPRing,NPpoly); list NewtP=newtonpoly(NPpoly); setring PRENPRing; kill NPRING; } else { list NewtP=newtonpoly(i[1]); } for (jjj=1;jjj<=size(NewtP)-1;jjj++) { wneu=NewtP[jjj]-NewtP[jjj+1]; int ggteiler=gcd(wneu[1],wneu[2]); wneu[1]=-wneu[1] div ggteiler; wneu[2]=wneu[2] div ggteiler; if (wneu[1]>0) { wneu=-wneu; } if (nvars(basering)>2) { wneu[3]=0; } wneulist[jjj]=wneu; } kill NewtP,ggteiler; } else // we have to set the points in the tropical variety by hand { if (findall==1) { "Set wneulist!"; } else { "Set intvec wneu!"; wneulist[1]=wneu; } } } } // if we have not yet computed our parametrisation up to // the required order and // zero is not yet a solution, then we have to go on // by calling the procedure recursively; // if all variables were deleted, then i=0 and thus anzahlvariablen==0 lll=0; if (((puiseux==0) and (ordnung>1)) or ((puiseux==1) and (ordnungskontrollvektor[2]1)) { partliftings=list(); // initialise partliftings // we call the procedure with the transformed // ideal i, the new weight vector, with the // required order lowered by one, and with // additional parameters, namely the number of // true variables and the maximal ideal that // was computed so far to describe the field extension for (kk=1;kk<=size(wneulist);kk++) { wneu=wneulist[kk]; okvneu=-ordnungskontrollvektor[1]*wneu[1],-ordnungskontrollvektor[2]*wneu[1]-wneu[2]; if (puiseux==0) { PARALIST=tropicalparametrise(i,wneu,ordnung-1,okvneu,gfanold,findall,nogfan,puiseux,anzahlvariablen,zero); } else { PARALIST=tropicalparametrise(i,wneu,ordnung,okvneu,gfanold,findall,nogfan,puiseux,anzahlvariablen,zero); } // the output will be a ring, in which the // parametrisation lives, and a string, which contains // the maximal ideal that describes the necessary field extension for (ll=1;ll<=size(PARALIST);ll++) { def PARARing=PARALIST[ll][1]; tweight=-ww[1]*PARALIST[ll][2]; setring PARARing; // if some variables have been eliminated // in before, then we have to insert zeros // into the parametrisation for those variables if (numberdeletedvariables>0) { ideal PARAneu=PARA; kkk=0; for (jjj=1;jjj<=anzahlvariablen+numberdeletedvariables-1;jjj++) { // t admits no parametrisation if (deletedvariables[jjj]!=1) { kkk++; PARA[jjj]=PARAneu[kkk]; } else { PARA[jjj]=poly(0); } } } lll++; partliftings[lll]=list(PARARing,tweight,wneu); setring PREGFANRING; kill PARARing; } } } // otherwise we are done and we can start // to compute the last step of the parametrisation else { // we define the weight of t, i.e. in the // parametrisation t has to be replaced by t^1/tweight tweight=-ww[1]; // if additional variables were necessary, // we introduce them now as parameters; // in any case the parametrisation ring will // have only one variable, namely t, // and its order will be local, so that it // displays the lowest term in t first if (anzahlvariablen so that // there is a solution which has strictly positive valuation // ADDENDUM: // if i (without m) has only one polynomial, then we can divide // i by t as long as possible to compute the saturation with respect to t /* // DER NACHFOLGENDE TEIL IST MUELL UND WIRD NICHT MEHR GAMACHT // for the test we simply compute the leading ideal // and set all true variables zero; // since the ordering was an elimination ordering // with respect to (@a if present and) t // there remains something not equal to zero // if and only if there is polynomial which only // depends on t (and @a if present), but that is // a unit in K{{t}}, which would show that there // is no solution with the component lastvar zero; // however, we also have to ensure that if there // exists a solution with the component lastvar // equal to zero then this component has a // valuation with all strictly positive values!!!!; // for this we can either saturate the ideal // after elimination with respect to // and see if the saturated ideal is contained in +m, // or ALTERNATIVELY we can pass to the // ring 0,(t,x_1,...,x_n,@a),(ds(n+1),dp(1)), // compute a standard basis of the elimination // ideal (plus m) there and check if the dimension 1 // (since we have not omitted the variable lastvar, // this means that we have the ideal // generated by t,x_1,...,[no x_lastvar],...,x_n // and this defines NO curve after omitting x_lastvar) I=std(ideal(var(lastvar)+i)); // first test, LI=lead(reduce(I,std(m))); //size(deletedvariables)=anzahlvariablen(before elimination) for (j=1;j<=anzahlvariablen-1;j++) { LI=subst(LI,var(j),0); } if (size(LI)==0) // if no power of t is in lead(I) (where @a is considered as a field element) */ if (size(i)-size(m)!=1) { I=reduce(sat(std(ideal(var(lastvar)+i)),t)[1],std(m)); // get rid of the minimal // polynomial for the test } else { I=subst(i,var(lastvar),0); while ((I[1]!=0) and (subst(I[1],t,0)==0)) { I[1]=I[1]/t; } I=reduce(I,std(m)); } LI=subst(I,var(nvars(basering)),0); //size(deletedvariables)=anzahlvariablen(before elimination) for (j=1;j<=anzahlvariablen-1;j++) { LI=subst(LI,var(j),0); } if (size(LI)==0) // the saturation lives in the maximal { // ideal generated by t and the x_i // get rid of var(lastvar) I=eliminate(I,var(lastvar))+m; // add the minimal polynomial again // store the information which variable has been eliminated intvec newdeletedvariables=deletedvariables; newdeletedvariables[lastvar]=1; // pass to a new ring whith one variable less if (anzahlvariablen>2) { string elring="ring ELIMINATERING=("+charstr(basering)+"),("+string(simplify(reduce(maxideal(1),std(var(lastvar))),2))+"),(dp("+string(anzahlvariablen-2)+"),"; } else { string elring="ring ELIMINATERING=("+charstr(basering)+"),("+string(simplify(reduce(maxideal(1),std(var(lastvar))),2))+"),("; } if (anzahlvariablen1) { eliminatelist=eliminatecomponents(i,imap(BASERING,m),anzahlvariablen-1,findall,lastvar-1,newdeletedvariables); } else { export(i); eliminatelist=list(list(ELIMINATERING,anzahlvariablen-1,newdeletedvariables)); } setring BASERING; } // next we have to test if there is also a solution // which has the variable lastvar non-zero; // to do so, we saturate with respect to this variable; // since when considered over K{{t}} // the ideal is zero dimensional, this really removes // all solutions with that component zero; // the checking is then done as above // ADDENDUM // if the ideal i (without m) is generated by a single polynomial // then we saturate by successively dividing by the variable if (size(i)-size(m)==1) { while (subst(i[1],var(lastvar),0)==0) { i[1]=i[1]/var(lastvar); } } else { i=std(sat(i,var(lastvar))[1]); } I=reduce(i,std(m)); // "remove" m from i // test first, if i still is in the ideal -- if not, then // we know that i has no longer a point in the tropical // variety with all components negative LI=subst(I,var(nvars(basering)),0); for (j=1;j<=anzahlvariablen-1;j++) // set all variables { // t,x_1,...,x_n equal to zero LI=subst(LI,var(j),0); } if (size(LI)==0) // the entries of i have no constant part { // check now, if the leading ideal of i contains an element // which only depends on t LI=lead(I); //size(deletedvariables)=anzahlvariablen(before elimination) for (j=1;j<=anzahlvariablen-1;j++) { LI=subst(LI,var(j),0); } if (size(LI)==0) // if no power of t is in lead(i) { // (where @a is considered as a field element) // if not yet all variables have been tested, go on with the // next smaller variable // else prepare the neccessary information for return if (lastvar>1) { saturatelist=eliminatecomponents(i,m,anzahlvariablen,findall,lastvar-1,deletedvariables); } else { execute("ring SATURATERING=("+charstr(basering)+"),("+varstr(basering)+"),("+ordstr(basering)+");"); ideal i=imap(BASERING,i); export(i); setring BASERING; saturatelist=list(list(SATURATERING,anzahlvariablen,deletedvariables)); } } } return(eliminatelist+saturatelist); } else // only one solution is searched for, we can do a simplified { // version of the above // check if there is a solution which has the n-th component // zero and with positive valuation, // if so, then eliminate the n-th variable from // sat(i+x_n,t), otherwise leave i as it is; // then check if the (remaining) ideal has as // solution where the n-1st component is zero ..., // and procede as before; do the same for the remaining variables; // this way we make sure that the remaining ideal has // a solution which has no component zero; ideal variablen; // will contain the variables which are not eliminated for (j=anzahlvariablen-1;j>=1;j--) // the variable t is the last one !!! { I=sat(ideal(std(var(j)+i)),t)[1]; LI=subst(I,var(nvars(basering)),0); //size(deletedvariables)=anzahlvariablen-1(before elimination) for (k=1;k<=size(deletedvariables);k++) { LI=subst(LI,var(k),0); } if (size(LI)==0) // if no power of t is in lead(I) { // (where the X(i) are considered as field elements) // get rid of var(j) i=eliminate(I,var(j)); deletedvariables[j]=1; anzahlvariablen--; // if a variable is eliminated, // then the number of true variables drops } else { variablen=variablen+var(j); // non-eliminated true variables are stored } } variablen=invertorder(variablen); // store also the additional variable and t, // since they for sure have not been eliminated for (j=size(deletedvariables)+1;j<=nvars(basering);j++) { variablen=variablen+var(j); } // if there are variables left, then pass to a ring which // only realises these variables else we are done if (anzahlvariablen>1) { string elring="ring ELIMINATERING=("+charstr(basering)+"),("+string(variablen)+"),(dp("+string(anzahlvariablen-1)+"),"; } else { string elring="ring ELIMINATERING=("+charstr(basering)+"),("+string(variablen)+"),("; } if (size(deletedvariables)+1 t^-w_l*(zero_l+x_l) for (l=1;l<=anzahlvariablen;l++) { for (k=1;k<=size(i);k++) { if (l!=1) // corresponds to x_(l-1) -- note t is the last variable { i[k]=subst(i[k],var(l-1),(zeroneu[l]+var(l-1))*t^(-w[l])); } else // corresponds to t { i[k]=subst(i[k],var(nvars(basering)),var(nvars(basering))^(-w[l])); } } } // we can divide the lth generator of i by t^-wdegs[l] for (l=1;l<=ncols(i);l++) { if (wdegs[l]<0) // if wdegs[l]==0 there is no need to divide, { // and we made sure that it is no positive i[l]=i[l]/t^(-wdegs[l]); } } // since we want to consider i now in the ring (Q[@a]/m)[t,x_1,...,x_n] // we can reduce i modulo m, so that "constant terms" // which are "zero" since they // are in m will disappear; simplify(...,2) then really removes them; // finally we add the minimal polynomial i=simplify(ideal(reduce(i,std(m))+m),2); export(i); export(m); export(zero); extensionringlist[j]=EXTENSIONRING; kill EXTENSIONRING; setring ABSRING; } return(extensionringlist); } ///////////////////////////////////////////////////////////////////////// static proc ordermaximalideals (list minassi,int anzahlvariablen) "USAGE: ordermaximalideals(minassi); minassi list ASSUME: minassi is a list of maximal ideals (together with the information how many conjugates it has), where the first polynomial is the minimal polynomial of the last variable in the ring which is considered as a parameter RETURN: list, the procedure orders the maximal ideals in minassi according to how many new variables are needed (namely none or one) to describe the zeros of the ideal, and accordingly to the degree of the corresponding minimal polynomial l[j][1] = the minimal polynomial for the jth maximal ideal l[j][2] = list, the k+1st entry is the kth coordinate of the zero described by the maximal ideal in terms of the last variable l[j][3] = poly, the replacement for the old variable @a NOTE: if a maximal ideal contains a variable, it is removed from the list; the procedure is called by findzerosAndBasictransform" { int j,k,l; int pruefer; // is set one if a maximal ideal contains a variable list minassisort; // will contain the output for (j=1;j<=size(minassi);j++){minassisort[j]=0;} // initialise minassisort // to fix its initial length list zwischen; // needed for reordering list zero; // (a_1,...,a_n)=(zero[2],...,zero[n+1]) will be // a common zero of the ideal m poly nf; // normalform of a variable w.r.t. m poly minimalpolynomial; // minimal polynomial for the field extension poly parrep; // the old variable @a possibly has to be replaced by a new one // compute for each maximal ideal the number of new variables, which are // needed to describe its zeros -- note, a new variable is needed // if the first entry of minassi[j][1] is not the last variable // store the value a variable reduces to in the list a; for (j=size(minassi);j>=1;j--) { minimalpolynomial=minassi[j][1][1]; if (minimalpolynomial==var(nvars(basering))) { minimalpolynomial=0; } zero[1]=poly(0); // the first entry in zero and in // neuevariablen corresponds to the variable t, minassi[j][1]=std(minassi[j][1]); for (k=1;(k<=anzahlvariablen-1) and (pruefer==0);k++) { // zero_k+1 is the normal form of the kth variable modulo m zero[k+1]=reduce(var(k),minassi[j][1]); // if a variable reduces to zero, then the maximal // ideal contains a variable and we can delete it if (zero[k+1]==0) { pruefer=1; } } // if anzahlvariablen=1;k--) { if (deg(minassisort[l][1])=2;i--) { for (j=i-1;j>=1;j--) { if ((eckpunkte[i][1]==eckpunkte[j][1]) and (eckpunkte[i][2]==eckpunkte[j][2])) { eckpunkte=delete(eckpunkte,i); j=0; } } } return(eckpunkte); } ///////////////////////////////////////////////////////////////////////// static proc bunchOfLines (def tp,list #) "USAGE: bunchOfLines(tp[,#]); tp list, # optional list ASSUME: tp is represents an ideal in Q[x,y] representing a tropical polynomial (in the form of the output of the procedure tropicalise) defining a bunch of ordinary lines in the plane, i.e. the Newton polygone is a line segment RETURN: list, see the procedure tropicalCurve for an explanation of the syntax of this list NOTE: - the tropical curve defined by tp will consist of a bunch of parallel lines and throughout the procedure a list with the name bunchoflines is computed, which represents these lines and has the following interpretation: list, each entry corresponds to a vertex in the tropical plane curve defined by tp l[i][1] = the equation of the ith line in the tropical curve l[i][2] = a polynomial whose monimials mark the vertices in the Newton polygon corresponding to the entries in tp which take the common minimum at the ith vertex - the information in l[i][2] represents the subdivision of the Newton polygon of tp (respectively a polynomial which defines tp); - if # is non-empty and #[1] is the string 'max', then in the computations minimum and maximum are exchanged; - if # is non-empty and the #[1] is not a string, only the vertices will be computed and the information on the Newton subdivision will be omitted; - here the tropical polynomial is supposed to be the MINIMUM of the linear forms in tp, unless the optional input #[1] is the string 'max' - the procedure is called from tropicalCurve" { // introduce necessary variables list oldtp=tp; // save the old entries of tp int i,j,k,l; ideal punkt; poly px; poly wert,vergleich; poly newton; list bunchoflines; int e=1; option(redSB); // find the direction of the line segment in the Newton polygon intvec direction=leadexp(detropicalise(tp[1]))-leadexp(detropicalise(tp[2])); direction=direction/gcd(direction[1],direction[2]); // change the coordinates in such a way, that the Newton polygon // lies on the x-axis if (direction[1]==0) // there is no x-term - exchange x and y { // and get rid of the new y part for (i=1;i<=size(tp);i++) { tp[i]=substitute(tp[i],var(1),0,var(2),var(1)); } } else { for (i=1;i<=size(tp);i++) { tp[i]=substitute(tp[i],var(2),0); } } // For all tuples (i,j) of entries in tp check if they attain // at their point of intersection // the minimal possible value for all linear forms in tp for (i=1;i<=size(tp)-1;i++) { for(j=i+1;j<=size(tp);j++) { punkt=std(ideal(tp[i]-tp[j])); px=-leadcoef(punkt[1]-lead(punkt[1]))/leadcoef(punkt[1]); l=1; wert=substitute(tp[i],var(1),px); newton=0; vergleich=wert; while((l<=size(tp)) and (vergleiche(wert,vergleich,#))) { vergleich=substitute(tp[l],var(1),px); if (vergleich==wert) { newton=newton+detropicalise(oldtp[l]); } l++; } if ((l==size(tp)+1) and (vergleiche(wert,vergleich,#))) { bunchoflines[e]=list((oldtp[i]-oldtp[j])/leadcoef(oldtp[i]-oldtp[j]),newton); e++; } } } // if a vertex appears several times, only its first occurence will be kept for (i=size(bunchoflines);i>=2;i--) { for (j=i-1;j>=1;j--) { if (bunchoflines[i][1]==bunchoflines[j][1]) { bunchoflines=delete(bunchoflines,i); j=0; } } } // sort the lines in an descending way according to the leading // exponent of the polynomial // defining the Newton polygone list nbol; list maximum; while (size(bunchoflines)!=0) { j=1; maximum=bunchoflines[1]; for (i=2;i<=size(bunchoflines);i++) { if (deg(bunchoflines[i][2])=1;i--) { if (vv[1,i]==vv[1,i+1]) { vv[2,i]=vv[2,i]+vv[2,i+1]; vv=intmatcoldelete(vv,i+1); } if (vv[1,i]==0) { vv=intmatcoldelete(vv,i); } } return(vv); } ///////////////////////////////////////////////////////////////////////// static proc sortintvec (intvec w) "USAGE: sortintvec(v); v intvec RETURN: intvec, the entries of v are ordered in an ascending way NOTE: not called at all" { int j,k,stop; intvec v=w[1]; for (j=2;j<=size(w);j++) { k=1; stop=0; while ((k<=size(v)) and (stop==0)) { if (v[k]ncols(w)) or (ncols(w)==1)) { return(w); } if (i==1) { intmat M[nrows(w)][ncols(w)-1]=w[1..nrows(w),2..ncols(w)]; return(M); } if (i==ncols(w)) { intmat M[nrows(w)][ncols(w)-1]=w[1..nrows(w),1..ncols(w)-1]; return(M); } else { intmat M[nrows(w)][i-1]=w[1..nrows(w),1..i-1]; intmat N[nrows(w)][ncols(w)-i]=w[1..nrows(w),i+1..ncols(w)]; return(intmatconcat(M,N)); } } ///////////////////////////////////////////////////////////////////////// static proc intmatconcat (intmat M,intmat N) "USAGE: intmatconcat(M,N); M,N intmat RETURN: intmat, M and N concatenated NOTE: the procedure is called by intmatcoldelete and sortintmat" { if (nrows(M)>=nrows(N)) { int m=nrows(M); } else { int m=nrows(N); } intmat P[m][ncols(M)+ncols(N)]; P[1..nrows(M),1..ncols(M)]=M[1..nrows(M),1..ncols(M)]; P[1..nrows(N),ncols(M)+1..ncols(M)+ncols(N)]=N[1..nrows(N),1..ncols(N)]; return(P); } ///////////////////////////////////////////////////////////////////////// static proc minInIntvec (intvec v) "USAGE: minInIntvec(v); v intvec RETURN: list, first entry is the minimal value in v, second entry is its position in v NOTE: called by sortintmat" { int min=v[1]; int minpos=1; for (int i=2;i<=size(v);i++) { if (v[i]vglwert); } if (size(#)>0) { if (typeof(#[1])=="string") { ergebnis=1-(wertvglwert); } } setring BASERING; return(ergebnis); } ///////////////////////////////////////////////////////////////////////// static proc koeffizienten (poly f,int k) "USAGE: koeffizienten(f,k) f poly, k int ASSUME: f=a*x+b*y+c is a linear polynomial in two variables, k is either 0, 1 or 2 RETURN: poly, one of the coefficients of f, depending on the value of k: k=0 : c is returned k=1 : a is returned k=2 : b is returned NOTE: the procedure is called from tropicalCurve" { poly c=substitute(f,var(1),0,var(2),0); if (k==0) { return(c); } f=f-c; if (k==1) { return(substitute(f,var(1),1,var(2),0)); } else { return(substitute(f,var(1),0,var(2),1)); } } //////////////////////////////////////////////////////////////////////////// /// Procedures used in tex-procedures and conicWithTangents: /// - minOfPolys /// - shorten /// - minOfStringDecimal /// - decimal /// - stringdelete /// - stringinsert /// - texmonomial /// - texcoefficient /// - abs ///////////////////////////////////////////////////////////////////////////// static proc minOfPolys (list v) "USAGE: minOfPolys(v); v list RETURN: poly, the minimum of the numbers in v NOTE: called by texDrawTropical" { poly min=v[1]; for (int i=2;i<=size(v);i++) { if (v[i]cc) or (aa<-cc)) { ascale=abs(cc/aa); } if ((bb>cc) or (bb<-cc)) { bscale=abs(cc/bb); } if (ascale0) { nachkomma=#[1]; } while ((check==0) and i<=size(s)) { if (s[i]==".") { if (i+nachkomma>size(s)) { nachkomma=size(s)-i; } for (j=i;j<=i+nachkomma;j++) { news=news+s[j]; } check=1; } else { news=news+s[i]; } i++; } setring BASERING; return(news); } ///////////////////////////////////////////////////////////////////////// static proc stringcontainment (string a, string b) "USAGE: stringcontainment(a,b); a,b string ASSUME: a is a string containing a single letter RETURN: int, one if a is one of the letters in b and zero else NOTE: the procedure is called from extremeraysC" { int i; for (i=1;i<=size(b);i++) { if (a==b[i]) { return(1); } } return(0); } ///////////////////////////////////////////////////////////////////////// static proc stringdelete (string w,int i) "USAGE: stringdelete(w,i); w string, i int RETURN: string, the string w with the ith component deleted NOTE: the procedure is called by texNumber and choosegfanvector" { if ((i>size(w)) or (i<=0)) { return(w); } if ((size(w)==1) and (i==1)) { return(""); } if (i==1) { return(w[2..size(w)]); } if (i==size(w)) { return(w[1..size(w)-1]); } else { string erg=w[1..i-1],w[i+1..size(w)]; return(erg); } } ///////////////////////////////////////////////////////////////////////// static proc stringinsert (string w,string v,int i) "USAGE: stringinsert(w,v,i); w string, v string, i int RETURN: string, the string w where at the ith component v has been inserted NOTE: the procedure is called by texmonomial" { if (i==1) { return(v[1]+w); } if (i==size(w)+1) { return(w+v[1]); } else { string anfang=w[1..i-1]; string ende=w[i..size(w)]; string erg=anfang+v+ende; return(erg); } } ///////////////////////////////////////////////////////////////////////// static proc texmonomial (poly f) "USAGE: texmonomial(f); f poly RETURN: string, the tex-command for the leading monomial of f NOTE: the procedure is called by texPolynomial and texNumber" { int altshort=short; short=0; string F=string(leadmonom(f)); int k; for (int j=1;j<=size(F);j++) { if (F[j]=="^") { F=stringinsert(F,"{",j+1); k=j+2; while (k<=size(F) and ((F[k]=="0") or (F[k]=="1") or (F[k]=="2") or (F[k]=="3") or (F[k]=="4") or (F[k]=="5") or (F[k]=="6") or (F[k]=="7") or (F[k]=="8") or (F[k]=="9"))) { k++; } F=stringinsert(F,"}",k); j=k+1; } if (F[j]=="(") { F=stringdelete(F,j); F=stringinsert(F,"_{",j); k=j+2; while (k<=size(F) and ((F[k]=="0") or (F[k]=="1") or (F[k]=="2") or (F[k]=="3") or (F[k]=="4") or (F[k]=="5") or (F[k]=="6") or (F[k]=="7") or (F[k]=="8") or (F[k]=="9"))) { k++; } F=stringdelete(F,k); F=stringinsert(F,"}",k); j=k; } if (F[j]=="*") { F=stringdelete(F,j); j--; } } short=altshort; return(F); } ///////////////////////////////////////////////////////////////////////// static proc texcoefficient (poly f,list #) "USAGE: texcoefficient(f[,#]); f poly, # optional list RETURN: string, the tex command representing the leading coefficient of f using \frac as coefficient NOTE: if # is non-empty, then the cdot at the end is omitted; this is needed for the constant term" { string cdot; if (size(#)==0) { cdot="\\cdot "; } string koeffizient=texNumber(f); if (koeffizient=="1") { if (size(#)==0) { return(""); } else { return(koeffizient); } } if (koeffizient=="-1") { if (size(#)==0) { return("-"); } else { return(koeffizient); } } if (size(koeffizient)>5) { string tfractest=koeffizient[2..6]; if (tfractest=="tfrac") { return(koeffizient+cdot); } } int anzahlplus,anzahlminus; for(int j=1;j<=size(koeffizient);j++) { if (koeffizient[j]=="+") { anzahlplus++; } if (koeffizient[j]=="-") { anzahlminus++; } } if ((anzahlplus==0) and (anzahlminus==1) and (koeffizient[1]=="-")) { return(koeffizient+cdot); } else { if (anzahlplus+anzahlminus>=1) { return("("+koeffizient+")"+cdot); } else { return(koeffizient+cdot); } } } ///////////////////////////////////////////////////////////////////////// static proc abs (def n) "USAGE: abs(n); n poly or int RETURN: poly or int, the absolute value of n" { if (n>=0) { return(n); } else { return(-n); } } /////////////////////////////////////////////////////////////////////////////// /// Procedures only used to compute j-invariants /// - findNonLoopVertex /// - coordinatechange /// - weierstrassFormOfACubic /// - weierstrassFormOfA4x2Curve /// - weierstrassFormOfA2x2Curve /// - jInvariantOfACubic /// - jInvariantOfA4x2Curve /// - jInvariantOfA2x2Curve /// - jInvariantOfAPuiseuxCubic /////////////////////////////////////////////////////////////////////////////// static proc findNonLoopVertex (list graph) "USAGE: findNonLoopVertex(graph); graph list ASSUME: graph is a list as in the output of tropicalCurve RETURN: int, the number of a vertex which has only one edge NOTE: the procedure is called by tropicalJInvariant" { int i,j; for (i=1;i<=size(graph)-1;i++) { if ((ncols(graph[i][3])==1) and (graph[i][3][1,1]!=0)) { return(i); } } return(-1); } ///////////////////////////////////////////////////////////////////////// static proc coordinatechange (poly f,intmat A,intvec v) "USAGE: coordinatechange(f,A,v); f poly, A intmat, v intvec ASSUME: f is a polynomial in two variables, A is a 2x2 integer matrix, and v is an integer vector with 2 entries RETURN: poly, the polynomial transformed by (x,y)->A*(x,y)+v NOTE: the procedure is called by weierstrassForm" { poly g; int i; intmat exp[2][1]; for (i=1;i<=size(f);i++) { exp=leadexp(f[i]); exp=A*exp; g=g+leadcoef(f[i])*var(1)^(exp[1,1]+v[1])*var(2)^(exp[2,1]+v[2]); } return(g); } ///////////////////////////////////////////////////////////////////////// static proc weierstrassFormOfACubic (poly f,list #) "USAGE: weierstrassFormOfACubic(wf[,#]); wf poly, # list ASSUME: poly is a cubic polynomial RETURN: poly, the Weierstrass normal form of the cubic, 0 if poly is not a cubic NOTE: - the algorithm for the coefficients of the Weierstrass form is due to Fernando Rodriguez Villegas, villegas@math.utexas.edu - if an additional argument # is given, the simplified Weierstrass form is computed - the procedure is called by weierstrassForm - the characteristic of the base field should not be 2 or 3 if # is non-empty" { if (deg(f)!=3) { ERROR("The curve is not a cubic!"); } // store the coefficients of f in a specific order poly t0,s1,s0,r2,r1,r0,q3,q2,q1,q0=flatten(coeffs(f,ideal(var(2)^3,var(2)^2,var(2)^2*var(1),var(2),var(2)*var(1),var(2)*var(1)^2,1,var(1),var(1)^2,var(1)^3))); // test, if f is already in Weierstrass form if ((t0==0) and (s1==1) and (s0==0) and (r0==0) and (q0==-1) and (size(#)==0)) { return (f); } // compute the coefficients a1,a2,a3,a4, and a6 of the Weierstrass // form y^2+a1xy+a3y=x^3+a2x^2+a4x+a6 poly a1=r1; poly a2=-(s0*q2+s1*q1+r0*r2); poly a3=(9*t0*q0-s0*r0)*q3+((-t0*q1-s1*r0)*q2+(-s0*r2*q1-s1*r2*q0)); poly a4=((-3*t0*r0+s0^2)*q1+(-3*s1*s0*q0+s1*r0^2))*q3 +(t0*r0*q2^2+(s1*s0*q1+((-3*t0*r2+s1^2)*q0+s0*r0*r2))*q2 +(t0*r2*q1^2+s1*r0*r2*q1+s0*r2^2*q0)); poly a6=(-27*t0^2*q0^2+(9*t0*s0*r0-s0^3)*q0-t0*r0^3)*q3^2+ (((9*t0^2*q0-t0*s0*r0)*q1+((-3*t0*s0*r1+(3*t0*s1*r0+ 2*s1*s0^2))*q0+(t0*r0^2*r1-s1*s0*r0^2)))*q2+(-t0^2*q1^3 +(t0*s0*r1+(2*t0*s1*r0-s1*s0^2))*q1^2+((3*t0*s0*r2+ (-3*t0*s1*r1+2*s1^2*s0))*q0+((2*t0*r0^2-s0^2*r0)*r2+ (-t0*r0*r1^2+s1*s0*r0*r1-s1^2*r0^2)))*q1+((9*t0*s1*r2- s1^3)*q0^2+(((-3*t0*r0+s0^2)*r1-s1*s0*r0)*r2+(t0*r1^3 -s1*s0*r1^2+s1^2*r0*r1))*q0)))*q3+(-t0^2*q0*q2^3+ (-t0*s1*r0*q1+((2*t0*s0*r2+(t0*s1*r1-s1^2*s0))*q0- t0*r0^2*r2))*q2^2+(-t0*s0*r2*q1^2+(-t0*s1*r2*q0+ (t0*r0*r1-s1*s0*r0)*r2)*q1+((2*t0*r0-s0^2)*r2^2+ (-t0*r1^2+s1*s0*r1-s1^2*r0)*r2)*q0)*q2+ (-t0*r0*r2^2*q1^2+(t0*r1-s1*s0)*r2^2*q0*q1- t0*r2^3*q0^2)); poly b2=a1^2+4*a2; poly b4=2*a4+a1*a3; poly b6=a3^2+4*a6; poly b8=a1^2*a6+4*a2*a6-a1*a3*a4+a2*a3^2-a4^2; poly c4=b2^2-24*b4; poly c6=-b2^3+36*b2*b4-216*b6; if (size(#)!=0) { return(substitute(var(2)^2+a1*var(1)*var(2)+a3*var(2)-var(1)^3-a2*var(1)^2-a4*var(1)-a6,var(2),var(2)-(a1*var(1)+a3)/2)); } else { return(var(2)^2+a1*var(1)*var(2)+a3*var(2)-var(1)^3-a2*var(1)^2-a4*var(1)-a6); } } ///////////////////////////////////////////////////////////////////////// static proc weierstrassFormOfA4x2Curve (poly f) "USAGE: weierstrassFormOfA4x2Curve(wf); wf poly ASSUME: poly is a polynomial of type 4x2 RETURN: poly, the Weierstrass normal form of the curve NOTE: - the procedure is called by weierstrassForm - the characteristic of the base field should not be 2 or 3" { poly u11,u40,u30,u20,u10,u00,u21,u01,u02=flatten(coeffs(f,ideal(var(1)*var(2),var(1)^4,var(1)^3,var(1)^2,var(1),1,var(1)^2*var(2),var(2),var(2)^2))); poly c4=(u11^4 - 8*u11^2*u20*u02 - 8*u11^2*u01*u21 + 24*u11*u10*u21*u02 + 24*u11*u30*u01*u02 + 192*u00*u40*u02^2 - 48*u00*u21^2*u02 - 48*u10*u30*u02^2 + 16*u20^2*u02^2 - 16*u20*u01*u21*u02 - 48*u40*u01^2*u02 + 16*u01^2*u21^2)/lead(u02^4); poly c6=(-u11^6 + 12*u11^4*u20*u02 + 12*u11^4*u01*u21 - 36*u11^3*u10*u21*u02 - 36*u11^3*u30*u01*u02 + 576*u11^2*u00*u40*u02^2 + 72*u11^2*u00*u21^2*u02 + 72*u11^2*u10*u30*u02^2 - 48*u11^2*u20^2*u02^2 - 24*u11^2*u20*u01*u21*u02 + 72*u11^2*u40*u01^2*u02 - 48*u11^2*u01^2*u21^2 - 864*u11*u00*u30*u21*u02^2 + 144*u11*u10*u20*u21*u02^2 - 864*u11*u10*u40*u01*u02^2 + 144*u11*u10*u01*u21^2*u02 + 144*u11*u20*u30*u01*u02^2 + 144*u11*u30*u01^2*u21*u02 - 2304*u00*u20*u40*u02^3 + 576*u00*u20*u21^2*u02^2 + 864*u00*u30^2*u02^3 + 1152*u00*u40*u01*u21*u02^2 - 288*u00*u01*u21^3*u02 + 864*u10^2*u40*u02^3 - 216*u10^2*u21^2*u02^2 - 288*u10*u20*u30*u02^3 + 144*u10*u30*u01*u21*u02^2 + 64*u20^3*u02^3 - 96*u20^2*u01*u21*u02^2 + 576*u20*u40*u01^2*u02^2 - 96*u20*u01^2*u21^2*u02 - 216*u30^2*u01^2*u02^2 - 288*u40*u01^3*u21*u02 + 64*u01^3*u21^3)/lead(u02^6); return(var(2)^2-var(1)^3+27*c4*var(1)+54*c6); } ///////////////////////////////////////////////////////////////////////// static proc weierstrassFormOfA2x2Curve (poly f) "USAGE: weierstrassFormOfA2x2Curve(f); f poly ASSUME: poly, is a polynomial defining an elliptic curve of type (2,2) on P^1xP^1 i.e. a polynomial of the form a+bx+cx2+dy+exy+fx2y+gy2+hxy2+ix2y2 RETURN: poly, a Weierstrass form of the elliptic curve defined by poly NOTE: - the algorithm is based on the paper Sang Yook An, Seog Young Kim, David C. Marshall, Susan H. Marshall, William G. McCallum and Alexander R. Perlis: Jacobians of Genus One Curves. Journal of Number Theory 90,2 (2001), 304-315. - the procedure is called by weierstrassForm - the characteristic of the base field should not be 2 or 3" { // get the coefficients of the polynomial poly A00,A10,A20,A01,A11,A21,A02,A12,A22=flatten(coeffs(f,ideal(1,var(1),var(1)^2,var(2),var(1)*var(2),var(1)^2*var(2),var(2)^2,var(1)*var(2)^2,var(1)^2*var(2)^2))); // define P1xP1 as quadric in P3 matrix A[4][4]=0,0,0,1/2,0,0,1/2,0,0,1/2,0,0,1/2,0,0,0; // define the image of the (2,2)-curve under the Segre embedding // as quadric which should be // intersected with the image of P1xP1 matrix B[4][4]=A00,A10/2,A01/2,0,A10/2,A20,A11/2,A21/2,A01/2,A11/2,A02,A12/2,0,A21/2,A12/2,A22; // compute the coefficients of the Weierstrass form of // the input polynomial and its j-invariant poly a=det(x*A+B); poly a0,a1,a2,a3,a4=flatten(coeffs(a,ideal(x4,x3,x2,x,1))); a1,a2,a3=-a1/4,a2/6,-a3/4; poly g2=a0*a4-4*a1*a3+3*a2^2; poly g3=a0*a2*a4+2*a1*a2*a3-a0*a3^2-a4*a1^2-a2^3; return(var(2)^2-var(1)^3+g2/4*var(1)+g3/4); } ///////////////////////////////////////////////////////////////////////// static proc jInvariantOfACubic (poly f,list #) "USAGE: jInvariantOfACubic(f[,#]); f poly, # list ASSUME: poly is a cubic polynomial defining an elliptic curve RETURN: poly, the j-invariant of the elliptic curve defined by poly NOTE: - if the base field is Q(t) an optional argument # may be given; then the algorithm only computes the negative of the order of the j-invariant" { if (deg(f)!=3) { ERROR("The input polynomial is not a cubic!"); } // compute first the Weierstrass form of the cubic // - this does not change the j-invariant f=weierstrassFormOfACubic(f); // compute the coefficients of the Weierstrass form poly a1,a2,a3,a4,a6=flatten(coeffs(f,ideal(var(1)*var(2),var(1)^2,var(2),var(1),1))); a2,a4,a6=-a2,-a4,-a6; // compute the j-invariant poly b2=a1^2+4*a2; poly b4=2*a4+a1*a3; poly b6=a3^2+4*a6; poly b8=a1^2*a6+4*a2*a6-a1*a3*a4+a2*a3^2-a4^2; poly c4=b2^2-24*b4; // poly c6=-b2^3+36*b2*b4-216*b6; poly delta=-b2^2*b8-8*b4^3-27*b6^2+9*b2*b4*b6; if (delta==0) { ERROR("The input is a rational curve and has no j-invariant!"); } if (size(#)>0) // if the optional argument is given, then only the { // negative of the order is computed int zaehler=3*simplifyToOrder(c4)[1]; int nenner=simplifyToOrder(delta)[1]; return(nenner-zaehler); } else { poly invariant=(c4^3/delta); return(invariant); } } ///////////////////////////////////////////////////////////////////////// static proc jInvariantOfA2x2Curve (poly f,list #) "USAGE: jInvariantOfA2x2Curve(f[,#]); f poly, # list ASSUME: poly, is a polynomial defining an elliptic curve of type (2,2) on P^1xP^1 i.e. a polynomial of the form a+bx+cx2+dy+exy+fx2y+gy2+hxy2+ix2y2 RETURN: poly, the j-invariant of the elliptic curve defined by poly NOTE: - if the base field is Q(t) an optional argument # may be given; then the algorithm only computes the negative of the order of the j-invariant - the characteristic should not be 2 or 3 - the procedure is not called at all, it is just stored for the purpose of comparison" { // get the coefficients of the polynomial poly A00,A10,A20,A01,A11,A21,A02,A12,A22=flatten(coeffs(f,ideal(1,var(1),var(1)^2,var(2),var(1)*var(2),var(1)^2*var(2),var(2)^2,var(1)*var(2)^2,var(1)^2*var(2)^2))); // define P1xP1 as quadric in P3 matrix A[4][4]=0,0,0,1/2,0,0,1/2,0,0,1/2,0,0,1/2,0,0,0; // define the image of the (2,2)-curve under the Segre embedding as quadric which should be // intersected with the image of P1xP1 matrix B[4][4]=A00,A10/2,A01/2,0,A10/2,A20,A11/2,A21/2,A01/2,A11/2,A02,A12/2,0,A21/2,A12/2,A22; // compute the coefficients of the Weierstrass form of // the input polynomial and its j-invariant poly a=det(var(1)*A+B); poly a0,a1,a2,a3,a4=flatten(coeffs(a,ideal(var(1)^4,var(1)^3,var(1)^2,var(1),1))); a1,a2,a3=-a1/4,a2/6,-a3/4; poly g2=a0*a4-4*a1*a3+3*a2^2; poly g3=a0*a2*a4+2*a1*a2*a3-a0*a3^2-a4*a1^2-a2^3; poly G2cube=g2^3; poly G3square=g3^2; poly jinvnum=1728*G2cube; poly jinvdenom=-27*G3square+G2cube; // check if the curve is rational if (jinvdenom==0) { ERROR("The input is a rational curve and has no j-invariant!"); } if (size(#)>0) // if the optional argument is given, { // then only the negative of the order is computed int zaehler=simplifyToOrder(jinvnum)[1]; int nenner=simplifyToOrder(jinvdenom)[1]; return(nenner-zaehler); } else { poly invariant=(jinvnum/jinvdenom); return(invariant); } } ///////////////////////////////////////////////////////////////////////// static proc jInvariantOfA4x2Curve (poly f,list #) "USAGE: jInvariantOfA4x2Curve(f[,#]); f poly, # list ASSUME: poly, is a polynomial defining an elliptic curve of type (4,2), i.e. a polynomial of the form a+bx+cx2+dx3+ex4+fy+gxy+hx2y+iy2 RETURN: poly, the j-invariant of the elliptic curve defined by poly NOTE: - if the base field is Q(t) an optional argument # may be given; then the algorithm only computes the negative of the order of the j-invariant - the characteristic should not be 2 or 3 - the procedure is not called at all, it is just stored for the purpose of comparison" { poly u11,u40,u30,u20,u10,u00,u21,u01,u02=flatten(coeffs(f,ideal(var(1)*var(2),var(1)^4,var(1)^3,var(1)^2,var(1),1,var(1)^2*var(2),var(2),var(2)^2))); poly c4=(u11^4 - 8*u11^2*u20*u02 - 8*u11^2*u01*u21 + 24*u11*u10*u21*u02 + 24*u11*u30*u01*u02 + 192*u00*u40*u02^2 - 48*u00*u21^2*u02 - 48*u10*u30*u02^2 + 16*u20^2*u02^2 - 16*u20*u01*u21*u02 - 48*u40*u01^2*u02 + 16*u01^2*u21^2); poly c6=(-u11^6 + 12*u11^4*u20*u02 + 12*u11^4*u01*u21 - 36*u11^3*u10*u21*u02 - 36*u11^3*u30*u01*u02 + 576*u11^2*u00*u40*u02^2 + 72*u11^2*u00*u21^2*u02 + 72*u11^2*u10*u30*u02^2 - 48*u11^2*u20^2*u02^2 - 24*u11^2*u20*u01*u21*u02 + 72*u11^2*u40*u01^2*u02 - 48*u11^2*u01^2*u21^2 - 864*u11*u00*u30*u21*u02^2 + 144*u11*u10*u20*u21*u02^2 - 864*u11*u10*u40*u01*u02^2 + 144*u11*u10*u01*u21^2*u02 + 144*u11*u20*u30*u01*u02^2 + 144*u11*u30*u01^2*u21*u02 - 2304*u00*u20*u40*u02^3 + 576*u00*u20*u21^2*u02^2 + 864*u00*u30^2*u02^3 + 1152*u00*u40*u01*u21*u02^2 - 288*u00*u01*u21^3*u02 + 864*u10^2*u40*u02^3 - 216*u10^2*u21^2*u02^2 - 288*u10*u20*u30*u02^3 + 144*u10*u30*u01*u21*u02^2 + 64*u20^3*u02^3 - 96*u20^2*u01*u21*u02^2 + 576*u20*u40*u01^2*u02^2 - 96*u20*u01^2*u21^2*u02 - 216*u30^2*u01^2*u02^2 - 288*u40*u01^3*u21*u02 + 64*u01^3*u21^3); poly c4cube=c4^3; poly jdenom=c4cube-c6^2; if (size(#)>0) // if the optional argument is given, { // then only the negative of the order is computed int zaehler=3*simplifyToOrder(c4)[1]; int nenner=simplifyToOrder(jinvdenom)[1]; return(nenner-zaehler); } else { return(1728*(c4cube/(jdenom))); } } ///////////////////////////////////////////////////////////////////////// static proc jInvariantOfAPuiseuxCubic (poly f,list #) "USAGE: jInvariantOfAPuiseuxCubic(f[,#]); f poly, # list ASSUME: poly is a cubic polynomial over Q(t) defining an elliptic curve and # is empty RETURN: list, containing two polynomials whose ratio is the j-invariant of the elliptic curve defined by poly ASSUME: poly is a cubic polynomial over Q(t) defining an elliptic curve and # is non-empty RETURN: int, the order of the j-invariant of the elliptic curve defined by poly NOTE: the procedure is called by jInvariant" { if (deg(f)!=3) { ERROR("The input polynomial is not a cubic!"); } // compute first the Weierstrass form of the cubic // - this does not change the j-invariant f=weierstrassFormOfACubic(f); // compute the coefficients of the Weierstrass form poly a1,a2,a3,a4,a6=flatten(coeffs(f,ideal(var(1)*var(2),var(1)^2,var(2),var(1),1))); a2,a4,a6=-a2,-a4,-a6; number dna1,dna2,dna3,dna4,dna6=denominator(leadcoef(a1)),denominator(leadcoef(a2)),denominator(leadcoef(a3)),denominator(leadcoef(a4)),denominator(leadcoef(a6)); number na1,na2,na3,na4,na6=numerator(leadcoef(a1)),numerator(leadcoef(a2)),numerator(leadcoef(a3)),numerator(leadcoef(a4)),numerator(leadcoef(a6)); number hn=dna1*dna2*dna3*dna4*dna6; a1=na1*dna2*dna3*dna4*dna6; a2=dna1*na2*dna3*dna4*dna6; a3=dna1*dna2*na3*dna4*dna6; a4=dna1*dna2*dna3*na4*dna6; a6=dna1*dna2*dna3*dna4*na6; // compute the j-invariant poly b2=a1^2+4*a2*hn; poly b4=2*a4*hn+a1*a3; poly b6=a3^2+4*a6*hn; poly b8=a1^2*a6+4*a2*a6*hn-a1*a3*a4+a2*a3^2-a4^2*hn; poly c4=b2^2-24*b4*hn^2; poly delta=-b2^2*b8-8*b4^3*hn-27*b6^2*hn^3+9*b2*b4*b6*hn; if (delta==0) { ERROR("The input is a rational curve and has no j-invariant!"); } if (size(#)>0) // if the optional argument is given, { // then only the negative of the order is computed int zaehler=3*simplifyToOrder(c4)[1]; int nenner=simplifyToOrder(delta)[1]; int ordhn=simplifyToOrder(hn)[1]; return(zaehler-nenner-5*ordhn); } else { def BASERING=basering; execute("ring TRING="+string(char(BASERING))+",t,ds;"); poly hn=imap(BASERING,hn); poly c4=imap(BASERING,c4); poly delta=imap(BASERING,delta); poly num=c4^3; poly denom=delta*hn^5; poly ggt=gcd(num,denom); num=num div ggt; denom=denom div ggt; setring BASERING; poly num=imap(TRING,num); poly denom=imap(TRING,denom); number teiler=1; if (char(BASERING)==0) { teiler=gcd(leadcoef(num),leadcoef(denom)); } num=num/teiler; denom=denom/teiler; list invariant=num,denom; return(invariant); } } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// /// Further examples for testing the procedures ///////////////////////////////////////////////////////////////////////////// /* /// Note, only the following procedures need further examples /// (the others are too simple): /// A) tropicalLifting (best tested via displayTropicalLifting) /// B) tropicalCurve (best tested via drawTropicalCurve) /// C) tropicalJInvariant /// D) weierstrassForm /// E) jInvariant //////////////////////////////////////////////////////////////////////////// /// A) Examples tropicalLifting //////////////////////////////////////////////////////////////////////////// // ------------------------------------------------------- // Example 1 // ------------------------------------------------------- ring r0=0,(t,x),dp; poly f=t7-6t4+3t3x+8t3-12t2x+6tx2-x3+t2; f; // The point -2/3 is in the tropical variety. list L=tropicalLifting(f,intvec(3,-2),4); L; displayTropicalLifting(L,"subst"); // -------------------------------------------------------- // Example 2 - a field extension is necessary // -------------------------------------------------------- poly g=(1+t2)*x2+t5x+t2; g; // The poin -1 is in the tropical variety. displayTropicalLifting(tropicalLifting(g,intvec(1,-1),4),"subst"); // -------------------------------------------------------- // Example 3 - the ideal is not zero dimensional // -------------------------------------------------------- ring r1=0,(t,x,y),dp; poly f=(9t27-12t26-5t25+21t24+35t23-51t22-40t21+87t20+56t19-94t18-62t17+92t16+56t15-70t14-42t13+38t12+28t11+18t10-50t9-48t8+40t7+36t6-16t5-12t4+4t2)*x2+(-9t24+12t23-4t22-42t20+28t19+30t18-20t17-54t16+16t15+48t14-16t12+8t11-18t10-26t9+30t8+20t7-24t6+4t5+28t4-8t3-16t2+4)*xy+(6t16-10t15-2t14+16t13+4t12-18t11-10t10+24t9+6t8-20t7+8t6+8t5-20t4-4t3+12t2+4t-4)*y2+(-9t28+3t27+8t26-4t25-45t24-6t23+42t22+30t21-94t20-40t19+68t18+82t17-38t16-60t15+26t14+36t13-22t12-20t11+4t10+4t9+12t8+8t7-8t6-8t5+4t4)*x+(9t27-21t26+16t25+14t24+12t23-61t22+27t21+80t20-19t19-100t18+26t17+96t16-24t15-84t14+44t12-2t11-18t10+2t9+40t8+4t7-32t6-12t5+4t3+12t2-4)*y+(9t27-12t26+4t25+36t23-18t22-28t21-2t20+54t19+14t18-52t17-44t16+24t15+40t14-4t13-12t12+4t11-4t10-4t9+4t8); f; displayTropicalLifting(tropicalLifting(f,intvec(1,-1,-4),3),"subst"); // -------------------------------------------------------- // Example 4 - the ideal has even more equations // -------------------------------------------------------- ring r2=0,(t,x,y,z),dp; ideal i=t-x3+3yz,t2xy-2x2z; i; displayTropicalLifting(tropicalLifting(i,intvec(1,1,3,0),2),"subst"); // -------------------------------------------------------- // Example 5-7 - testing some options // -------------------------------------------------------- setring r0; poly f1=(x2-t3)*(x3-t5)*(x5-t7)*(x7-t11)*(x11-t13); f1; displayTropicalLifting(tropicalLifting(f1,intvec(7,-11),4,"noAbs"),"subst"); poly f2=(1+t2)*x2+t5x+t2; f2; displayTropicalLifting(tropicalLifting(f2,intvec(1,-1),4,"isZeroDimensional","findAll"),"subst"); poly f3=t7-6t4+3t3x+8t3-12t2x+6tx2-x3+t2; f3; displayTropicalLifting(tropicalLifting(f3,intvec(3,-2),4,"isInTrop","findAll"),"subst"); // --------------------------------------------------------- // Even more examples // --------------------------------------------------------- ring r1=0,(t,x),dp; poly f1=(x2-t3)*(x3-t5)*(x5-t7)*(x7-t11)*(x11-t13); displayTropicalLifting(tropicalLifting(f1,intvec(7,-11),4,"noAbs"),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (7,-11) /////////////////////////////////////////////////////////////////// // one field extension needed // x=(X(1))*t+(-1/2*X(1))*t^3+(3/8*X(1)-1/2)*t^5+(-5/16*X(1)+1/2)*t^7+(19/128*X(1)-1/2)*t^9+(-15/256*X(1)+1/2)*t^11+(-9/1024*X(1)-1/2)*t^13 where t->t and X(1)^2+1=0 poly f2=(1+t2)*x2+t5x+t2; displayTropicalLifting(tropicalLifting(f2,intvec(1,-1),4,"isZeroDimensional","findAll"),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-1) /////////////////////////////////////////////////////////////////// // x=t2+2t3+t7 the result is exact poly f3=t7-6t4+3t3x+8t3-12t2x+6tx2-x3+t2; displayTropicalLifting(tropicalLifting(f3,intvec(3,-2),4,"isInTrop","findAll"),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (3,-2) /////////////////////////////////////////////////////////////////// // full parametrisation is given by t->t2+t3 and x=3t7+t9+4t11-t12, this however cannot be computed // so: t->t2 and x=-3t7-21/2t8-239/8t9-78t10-25589/128t11-506t12-1298967/1024t13-3159t14-256667105/32768t15-19371t16-12540259065/262144t17-118066t18-1222177873545/4194304t19-719423t20-59637294735495/33554432t21 poly f4=t12-83t11-88t10-69t9+3t8x+153t8+298t7x-81t7+165t6x-402t5x+3t4x2+189t4x-131t3x2+213t2x2-86tx2+x3+9x2; displayTropicalLifting(tropicalLifting(f4,intvec(2,-7),4,"findAll"),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (2,-7) /////////////////////////////////////////////////////////////////// // t->t6 and x=3t3+t7+4t11-t12 poly f5=t12-4120t11+6t10x-1008t10-96t9x+15t8x2+4453t9-2016t8x-144t7x2+20t6x3-18t8-108t7x-1008t6x2-96t5x3+15t4x4-4681t7-36t6x-162t5x2-24t3x4+6t2x5+243t6-18t4x2-108t3x3+x6+1890t5+486t4x-27tx4+243t2x2-729t3; displayTropicalLifting(tropicalLifting(f5,intvec(2,-1),3,"isInTrop","isZeroDimensional","findAll"),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (2,-1) /////////////////////////////////////////////////////////////////// ring r2=0,(t,x,y),dp; poly f7=(9t27-12t26-5t25+21t24+35t23-51t22-40t21+87t20+56t19-94t18-62t17+92t16+56t15-70t14-42t13+38t12+28t11+18t10-50t9-48t8+40t7+36t6-16t5-12t4+4t2)*x2+(-9t24+12t23-4t22-42t20+28t19+30t18-20t17-54t16+16t15+48t14-16t12+8t11-18t10-26t9+30t8+20t7-24t6+4t5+28t4-8t3-16t2+4)*xy+(6t16-10t15-2t14+16t13+4t12-18t11-10t10+24t9+6t8-20t7+8t6+8t5-20t4-4t3+12t2+4t-4)*y2+(-9t28+3t27+8t26-4t25-45t24-6t23+42t22+30t21-94t20-40t19+68t18+82t17-38t16-60t15+26t14+36t13-22t12-20t11+4t10+4t9+12t8+8t7-8t6-8t5+4t4)*x+(9t27-21t26+16t25+14t24+12t23-61t22+27t21+80t20-19t19-100t18+26t17+96t16-24t15-84t14+44t12-2t11-18t10+2t9+40t8+4t7-32t6-12t5+4t3+12t2-4)*y+(9t27-12t26+4t25+36t23-18t22-28t21-2t20+54t19+14t18-52t17-44t16+24t15+40t14-4t13-12t12+4t11-4t10-4t9+4t8); displayTropicalLifting(tropicalLifting(f7,intvec(1,-1,-4),4,"isPrime"),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-1,-4) /////////////////////////////////////////////////////////////////// ring r3=0,(t,x,y,z),dp; ideal i1=-y2t4+x2,yt3+xz+y; displayTropicalLifting(tropicalLifting(i1,intvec(1,-2,0,2),4,"findAll"),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-2,0,2) /////////////////////////////////////////////////////////////////// ideal i2=-y2t4+x2,yt3+yt2+xz; displayTropicalLifting(tropicalLifting(i2,intvec(1,-3,-1,0),4),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-3,-1,0) //////////////////////////////////////////////////////////////// ring r4=0,(t,x,y,z,u),dp; ideal i3=t3x+ty+u,tx+t2u+y; displayTropicalLifting(tropicalLifting(i3,intvec(1,-1,-2,-1,-3),6),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-1,-2,-1,-3) ///////////////////////////////////////////////////////////////////// setring r2; ideal i5=t3-t2y+t2-tx-ty+xy,t3-t2y+t2-2ty+y2,-t4+2t3x-t2x2-t3+3t2x-3tx2+x3+t2+t-x,-t4+2t3x-t2x2-t3+2t2x-tx2+t2y-2txy+x2y+t2+t-y; displayTropicalLifting(tropicalLifting(i5,intvec(1,-1,-1),3),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-1,-1) //////////////////////////////////////////////////////////////////// ring r5=0,(t,V,W,X,Y,Z),dp; ideal i5=VXt5+3VZt4-2VXt3+WXt3+V2t2+3WZt2-2WXt+VW,-4W2X4+V2t2; displayTropicalLifting(tropicalLifting(i5,intvec(2,-3,-3,-1,-1,-1),3),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (2,-3,-3,-1,-1,-1) /////////////////////////////////////////////////////////////////// ring r6=0,(t,x,y,z),dp; ideal i6=t4xy-y3z3+3t2xy3-txy2+t4y; displayTropicalLifting(tropicalLifting(i6,intvec(3,0,-9,2),4),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (3,0,-9,2) //////////////////////////////////////////////////////////// // very easy example stops after one loop with an exact result ideal i7=t2xy-2x2z; displayTropicalLifting(tropicalLifting(i7,intvec(1,1,3,0),4),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,1,3,0) ///////////////////////////////////////////////////////////// displayTropicalLifting(tropicalLifting(i7,intvec(1,-3,-1,0),4),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-3,-1,0) ///////////////////////////////////////////////////////////////// // requires one field extension ideal i8=t-x3+3yz; displayTropicalLifting(tropicalLifting(i8,intvec(1,1,3,0),4),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,1,3,0) ///////////////////////////////////////////////////////////////// displayTropicalLifting(tropicalLifting(i8,intvec(1,-3,-1,0),4),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-3,-1,0) ///////////////////////////////////////////////////////////////// // requires one field extension ideal i9=t-x3+3yz,t2xy-2x2z; displayTropicalLifting(tropicalLifting(i9,intvec(1,1,3,0),4),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,1,3,0) // takes too much time //displayTropicalLifting(tropicalLifting(i9,intvec(1,-3,-1,0),4),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-3,-1,0) ///////////////////////////////////////////////////////////////////// // too much for Gfan did not work on my computer //ideal i10=t2xy+t4-z2,t-2xy+z2+tz,z2-y; //displayTropicalLifting(tropicalLifting(i10,intvec(2,4,-6,-3),2),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (2,4,-6,-3) //////////////////////////////////////////////////////////////////// ring r7=0,(t,x,y),dp; ideal i11=t4xy-y3+3t2xy3-txy2+t4y; displayTropicalLifting(tropicalLifting(i11,intvec(1,3,1),5),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,3,1) //////////////////////////////////////////////////////////////// ring r8=0,(t,x),dp; ideal i12=x32+(16t6)*x30+(8t10)*x29+(120t12)*x28+(112t16)*x27+(32t20+560t18)*x26+(728t22)*x25+(388t26+1820t24)*x24+(80t30+2912t28)*x23+(2160t32+4368t30)*x22+(824t36+8008t34)*x21+(138t40+7304t38+8008t36)*x20+(3840t42+16016t40)*x19+(1180t46+16720t44+11440t42)*x18+(170t50+10680t48+24024t46)*x17+(4480t52+27324t50+12870t48)*x16+(1168t56+19680t54+27456t52)*x15+(152t60+9920t58+32736t56+11440t54)*x14+(3472t62+25200t60+24024t58)*x13+(804t66+14140t64+29040t62+8008t60)*x12+(96t70+5824t68+22848t66+16016t64)*x11+(1776t72+13496t70+19008t68+4368t66)*x10+(364t76+6020t74+14640t72+8008t70)*x9+(42t80+2112t78+8680t76+9020t74+1820t72)*x8+(544t82+3920t80+6480t78+2912t76)*x7+(104t86+1448t84+3680t82+2992t80+560t78)*x6+(12t90+400t88+1568t86+1880t84+728t82)*x5+(94t92+564t90+970t88+648t86+120t84)*x4+(16t96+144t94+352t92+320t90+112t88)*x3+(3t100+36t98+112t96+140t94+80t92+16t90)*x2+(6t102+20t100+34t98+24t96+8t94)*x+(t106+5t104+8t102+8t100+4t98+t96); displayTropicalLifting(tropicalLifting(i12,intvec(1,-3),2),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-3) //////////////////////////////////////////////////////////////// ring r9=3,(t,x),dp; ideal i13=imap(r8,i12); displayTropicalLifting(tropicalLifting(i13,intvec(1,-3),3,"noAbs"),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-3) ///////////////////////////////////////////////////// // without the option findAll we first get only a non-valid solution !!! ring r10=0,(t,x,y,z,u),dp; ideal i14=-y2t5-xyt4-2yzt3+yut2+xut+2zu; displayTropicalLifting(tropicalLifting(i14,intvec(1,-2,-1,-3,-3),3),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (1,-2,-1,-3,-3) /////////////////////////////////////////////////////// // test for positive characteristic /////////////////////////////////////////////////////////////////// ring r11=13,(t,x),dp; poly f1=(x2-t3)*(x3-t5)*(x5-t7)*(x7-t11)*(x11-t13); displayTropicalLifting(tropicalLifting(f1,intvec(7,-11),4,"findAll"),"subst"); /////////////////////////////////////////////////////////////////// // weight was: (7,-11) /////////////////////////////////////////////////////////////////// // one field extension needed // x=(X(1))*t+(-1/2*X(1))*t^3+(3/8*X(1)-1/2)*t^5+(-5/16*X(1)+1/2)*t^7+(19/128*X(1)-1/2)*t^9+(-15/256*X(1)+1/2)*t^11+(-9/1024*X(1)-1/2)*t^13 where t->t and X(1)^2+1=0 poly f2=(1+t2)*x2+t5x+t2; displayTropicalLifting(tropicalLifting(f2,intvec(1,-1),4,"isZeroDimensional","findAll"),"subst"); /////////////////////////////////////////////////////////////////// ring r12=5,(t,x,y),dp; ideal i11=t4xy-y3+3t2xy3-txy2+t4y; displayTropicalLifting(tropicalLifting(i11,intvec(1,3,1),5),"subst"); /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// /// B) Examples for tropicalCurve /////////////////////////////////////////////////////////////////// ring r=(0,t),(x,y),dp; poly f=t*(x7+y7+1)+1/t*(x4+y4+x2+y2+x3y+xy3)+1/t7*x2y2; list graph=tropicalCurve(f); graph; size(graph)-1; drawTropicalCurve(graph); poly g=t3*(x7+y7+1)+1/t3*(x4+y4+x2+y2+x3y+xy3)+1/t21*x2y2; list tropical_g=tropicalise(g); tropical_g; drawTropicalCurve(tropical_g); /// further examples poly f1=x+y; poly f2=xy+xy3+xy6+txy9; poly f3=xy+x2y3+x3y6+tx4y9; poly f4=t*(x3+y3+1)+1/t*(x2+y2+x+y+x2y+xy2)+1/t2*xy; poly f5=t8x3+t8y3+t8+t4x2y+t4xy2+t4x2+t4y2+t4x+t4y+t2xy; poly f6=x3+y3+1; poly f7=t*x70+t*y70+1/t*x40+1/t7*x20y20+1/t*y40+1/t*x30y+1/t*xy30+1/t*x20+1/t*y20+t; poly f8=t10*x7+t10*y7+1/t10*x4+1/t70*x2y2+1/t10*y4+1/t10*x3y+1/t10*xy3+1/t10*x2+1/t10*y2+t10; poly f9=x+y+x2y+xy2+1/t*xy; poly f10=1+x+y+xy+tx2y+txy2+t3x5+t3y5+tx2y2+t2xy4+t2yx4; poly f11=1/(t8)*x6y+1/(t16)*x5y2+1/(t9)*x4y3+(t4)*x2y5+1/(t11)*xy6+(t5)*y7+1/(t5)*x6+(t16)*x4y2+(t10)*x3y3+(t19)*xy5+(t14)*x5+1/(t17)*x3y2+(t10)*x2y3+1/(t20)*xy4+(t13)*y5+1/(t17)*x4+(t9)*x3y+(t11)*xy3+1/(t3)*xy2+(t7)*y3+1/(t18)*x2+(t16)*x; poly f12=-x3+(6t13+3t12+t5+3t4+3t3+1)/(t19)*x2+(2t5+1)/(t12)*xy+y2+(9t28-12t23-12t22+3t21+9t19+3t16-8t15-16t14-24t13-9t12-6t11-8t10-3t9-3t8-4t6-8t5-8t4-3t3-3t-2)/(t35)*x+(9t27+6t20-8t14-4t13-6t12-3t11-4t9-t8-4t5-4t4-2t3-1)/(t27)*y+(27t50+27t43-36t37-9t36-27t35-27t34-t32+12t31-18t30-11t29-54t28-36t27-12t25+13t24+28t23+61t22+27t21+18t20+16t19+3t18+14t17+3t16+16t15+26t14+44t13+34t12+21t11+27t10+12t9+7t8+t6+10t5+11t4+7t3+t2+2t+2)/(t50); poly f13=x3+(3t9+1)/(t8)*x2y+(3t10+2t+1)/(t8)*xy2+(t10+t7+t+1)/(t7)*y3+1/(t8)*x2+(2t5+1)/(t12)*xy+(t5+t3+1)/(t11)*y2+1/(t8)*x+(t+1)/(t8)*y+1; poly f14=x3+(3t9+3t6c+1)/(t8)*x2y+(3t12+6t9c+3t6c2+2t3+t2+2c)/(t10)*xy2+(t15+3t12c+t12+3t9c2+t6c3+t6+t5+2t3c+t2c+c2)/(t12)*y3+1/(t8)*x2+(2t5+2t2c+1)/(t12)*xy+(t8+t6+2t5c+t3+t2c2+c)/(t14)*y2+1/(t8)*x+(t3+t2+c)/(t10)*y+1; poly f15=x3+x2y+xy2+(t5)*y3+x2+1/(t4)*xy+y2+x+y+1; poly f16=t*(x7+y7+1)+1/t*(x4+y4+x2+y2+x3y+xy3)+1/t7*x2y2; /////////////////////////////////////////////////////////////////// /// B) Examples for tropicalJInvariant /////////////////////////////////////////////////////////////////// // tropcial_j_invariant computes the tropical j-invariant of the elliptic curve f tropicalJInvariant(t*(x3+y3+1)+1/t*(x2+y2+x+y+x2y+xy2)+1/t2*xy); // the Newton polygone need not be the standard simplex tropicalJInvariant(x+y+x2y+xy2+1/t*xy); // the curve can have arbitrary degree tropicalJInvariant(t*(x7+y7+1)+1/t*(x4+y4+x2+y2+x3y+xy3)+1/t7*x2y2); // the procedure does not realise, if the embedded graph of the tropical curve has // a loop that can be resolved tropicalJInvariant(1+x+y+xy+tx2y+txy2); // but it does realise, if the curve has no loop at all ... tropicalJInvariant(x+y+1); // or if the embedded graph has more than one loop - even if only one cannot be resolved tropicalJInvariant(1+x+y+xy+tx2y+txy2+t3x5+t3y5+tx2y2+t2xy4+t2yx4); // f is already in Weierstrass form weierstrassForm(y2+yx+3y-x3-2x2-4x-6); // g is not, but wg is g=x+y+x2y+xy2+1/t*xy; poly wg=weierstrassForm(g); wg; // ... but it is not yet a simple, since it still has an xy-term, unlike swg poly swg=weierstrassForm(g,1); swg; // the j-invariants of all three polynomials coincide ... jInvariant(g); jInvariant(wg); jInvariant(swg); // the following curve is elliptic as well poly h=x22y11+x19y10+x17y9+x16y9+x12y7+x9y6+x7y5+x2y3; // its Weierstrass form is weierstrassForm(h); jInvariant(x+y+x2y+y3+1/t*xy,"ord"); // see also example f5-f16 in part B) */ ///////////////////////////////////////////////////////////////////////// proc drawTwoTropicalCurves (list ff,list #) "USAGE: drawTropicalCurve(f[,#]); f poly or list, # optional list ASSUME: f is list of linear polynomials of the form ax+by+c with integers a, b and a rational number c representing a tropical Laurent polynomial defining a tropical plane curve; alternatively f can be a polynomial in Q(t)[x,y] defining a tropical plane curve via the valuation map; the basering must have a global monomial ordering, two variables and up to one parameter! RETURN: NONE NOTE: - the procedure creates the files /tmp/tropicalcurveNUMBER.tex and /tmp/tropicalcurveNUMBER.ps, where NUMBER is a random four digit integer; moreover it displays the tropical curve via kghostview; if you wish to remove all these files from /tmp, call the procedure cleanTmp @* - edges with multiplicity greater than one carry this multiplicity @* - if # is empty, then the tropical curve is computed w.r.t. minimum, if #[1] is the string 'max', then it is computed w.r.t. maximum @* - if the last optional argument is 'onlytexfile' then only the latex file is produced; this option should be used if kghostview is not installed on your system @* - note that lattice points in the Newton subdivision which are black correspond to markings of the marked subdivision, while lattice points in grey are not marked EXAMPLE: example drawTropicalCurve shows an example" { // check if the option "onlytexfile" is set, then only a tex file is produced if (size(#)!=0) { if (#[size(#)]=="onlytexfile") { int onlytexfile; #=delete(#,size(#)); } } // store this list # for use in the Newton subdivision list oldsharp=#; // start the actual computations string texf; list graph,graphs,texfs; int i,j; for (i=1;i<=size(ff);i++) { def f=ff[i]; if (typeof(f)=="poly") { // exclude the case that the basering has not precisely // one parameter and two indeterminates if ((npars(basering)!=1) or (nvars(basering)!=2)) { ERROR("The basering should have precisely one parameter and two indeterminates!"); } texf=texPolynomial(f); // write the polynomial over Q(t) graph=tropicalCurve(tropicalise(f,#),#); // graph of tropicalis. of f } if (typeof(f)=="list") { if (size(#)==0) { texf="\\min\\{"; } else { texf="\\max\\{"; } for (j=1;j<=size(f);j++) { texf=texf+texPolynomial(f[j]); if (j1) { TDT=TDT+" "+texDrawTropical(graphs[i],#); } else { #=insert(#,"noweights"); TDT=TDT+" "+texDrawTropical(graphs[i],#); #=delete(#,1); } } // add lattice points if the scalefactor is >= 1/2 // and was not handed over def scalefactor=SCF[1]; if (scalefactor>1/2) { def minx=SCF[4]; def miny=SCF[5]; def maxx=SCF[6]; def maxy=SCF[7]; def centerx=SCF[8]; def centery=SCF[9]; int uh=1; if (scalefactor>3) { uh=0; } TDT=TDT+" %% HERE STARTS THE CODE FOR THE LATTICE"; for (i=int(minx)-uh;i<=int(maxx)+uh;i++) { for (j=int(miny)-uh;j<=int(maxy)+uh;j++) { TDT=TDT+" \\move ("+decimal(i-centerx)+" "+decimal(j-centery)+") \\fcir f:0.8 r:"+decimal(1/(10*scalefactor),size(string(int(scalefactor)))+1); } } TDT=TDT+" %% HERE ENDS THE CODE FOR THE LATTICE "; } TEXBILD=TEXBILD+" \\begin{center} "+texDrawBasic(TDT)+ // write the tropical curve "\\end{center} \\vspace*{0.5cm} "; // compute the scaling factor for the Newton subdivisions oldsharp[size(oldsharp)+1]=nsdScaleFactor(graphs); for (i=1;i<=size(ff);i++) { if (i==1) { fname="f_1\\cdots f_{"+string(size(ff)-1)+"}"; } else { fname="f_{"+string(i-1)+"}"; } TEXBILD=TEXBILD+" The Newton subdivision of the tropical curve $"+fname+"$ is: \\vspace*{0.5cm} \\begin{center} "+texDrawNewtonSubdivision(graphs[i],oldsharp)+" \\end{center} \\vspace*{0.5cm} "; } TEXBILD=TEXBILD+" \\end{document}"; if(defined(onlytexfile)==0) { int rdnum=random(1000,9999); write(":w /tmp/tropicalcurve"+string(rdnum)+".tex",TEXBILD); system("sh","cd /tmp; latex /tmp/tropicalcurve"+string(rdnum)+".tex; dvips /tmp/tropicalcurve"+string(rdnum)+".dvi -o; command rm tropicalcurve"+string(rdnum)+".log; command rm tropicalcurve"+string(rdnum)+".aux; command rm tropicalcurve"+string(rdnum)+".ps?; command rm tropicalcurve"+string(rdnum)+".dvi; kghostview tropicalcurve"+string(rdnum)+".ps &"); } else { return(TEXBILD); } } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; // poly f=t*(x3+y3+1)+1/t*(x2+y2+x+y+x2y+xy2)+1/t2*xy; poly f=x+y+1; // the command drawTropicalCurve(f) computes the graph of the tropical curve // given by f and displays a post script image, provided you have kghostview // we can instead apply the procedure to a tropical polynomial and use "maximum" poly g=t3*(x7+y7+1)+1/t3*(x4+y4+x2+y2+x3y+xy3)+1/t21*x2y2; // list tropical_g=tropicalise(g); drawTwoTropicalCurves(list(f,g),"max"); } proc minScaleFactor (list graphs) { list graph; int j,i,k; poly minx,miny,maxx,maxy; poly minX,minY,maxX,maxY; poly maxdiffx,maxdiffy; poly centerx,centery; int nachkomma; number sf,scf; poly scalefactor; list SFCS; for (k=1;k<=size(graphs);k++) { graph=graphs[k]; // find the minimal and maximal coordinates of vertices minx,miny,maxx,maxy=graph[1][1],graph[1][2],graph[1][1],graph[1][2]; for (i=2;i<=size(graph)-1;i++) { minx=minOfPolys(list(minx,graph[i][1])); miny=minOfPolys(list(miny,graph[i][2])); maxx=-minOfPolys(list(-maxx,-graph[i][1])); maxy=-minOfPolys(list(-maxy,-graph[i][2])); } if (k==1) { minX=minx; minY=miny; maxX=maxx; maxY=maxy; } else { if (minxmaxX) { maxX=maxx; } if (maxy>maxY) { maxY=maxy; } } } minx,miny,maxx,maxy=minX,minY,maxX,maxY; // find the scale factor for the texdraw image maxdiffx=maxx-minx; maxdiffy=maxy-miny; centerx,centery=int(minx+maxdiffx/2),int(miny+maxdiffy/2); if (maxdiffx==0) { maxdiffx=1; } if (maxdiffy==0) { maxdiffy=1; } nachkomma=2; // number of decimals for the scalefactor sf=1; // correction factor for scalefactor scalefactor=minOfPolys(list(12/leadcoef(maxdiffx),16/leadcoef(maxdiffy))); // if the scalefactor is less than 1/100, then we need more than 2 decimals if (leadcoef(scalefactor) < 1/100) { scf=leadcoef(scalefactor); while (scf < 1/100) { scf=scf * 10; nachkomma++; } } // if the scalefactor is < 1/100, then we should rather scale the // coordinates directly, since otherwise texdraw gets into trouble if (nachkomma > 2) { for (i=3;i<=nachkomma;i++) { scalefactor=scalefactor * 10; sf=sf*10; } } return(list(scalefactor,sf,nachkomma,minx,miny,maxx,maxy,centerx,centery)); } example { "EXAMPLE:"; echo=2; ring r=(0,t),(x,y),dp; poly f=t*(x3+y3+1)+1/t*(x2+y2+x+y+x2y+xy2)+1/t2*xy; poly g=1/t3*(x7+y7+1)+t3*(x4+y4+x2+y2+x3y+xy3)+t21*x2y2; list graphs; graphs[1]=tropicalCurve(f); graphs[2]=tropicalCurve(g); minScaleFactor(graphs); } proc nsdScaleFactor (list graphs) { int i,j; list graph,boundary,scalefactors; poly maxx,maxy; for (j=1;j<=size(graphs);j++) { graph=graphs[j]; boundary=graph[size(graph)][1]; // find maximal and minimal x- and y-coordinates and define the scalefactor maxx,maxy=1,1; for (i=1;i<=size(boundary);i++) { maxx=-minOfPolys(list(-maxx,-boundary[i][1])); maxy=-minOfPolys(list(-maxy,-boundary[i][2])); } scalefactors[j]=minOfPolys(list(12/leadcoef(maxx),12/leadcoef(maxy))); } return(minOfPolys(scalefactors)); } singular-4.0.3+ds/Singular/LIB/tst.lib000066400000000000000000000616531266270727000174640ustar00rootroot00000000000000////////////////////////////////////////////////////////////////////////// version="version tst.lib 4.0.0.0 Jun_2013 "; // $Id: f7662d74f2d5d7c7e908fbe2830304edb0d07779 $ category="Utilities"; info=" LIBRARY: tst.lib Procedures for running automatic tst Tests AUTHORS: Singular team PROCEDURES: tst_system(s) returns string which is stdout of system(\"sh\", s) tst_ignore(any,[keyword], [link]) writes string(any) to link (or stdout), prepending prefix \"// tst_ignore:\" tst_init() writes some identification data to GetTstStatusFile() tst_status([any]) writes status info to GetTstStatusFile() tst_InitTimer() initialize tst-Timer tst_StopTimer() stop Tst-Timer tst_GetTimer get value of Tst-Timer tst_ReportTimer report value of Tst-Timer tst_groebnerTest(ideal i) tests groebner command tst_stdEqual(ideal i1, ideal i2) test whether two std's are \"equal\" tst_test_res(ideal i) test different res commands for homog ideal i "; ///////////////////////////////////////////////////////////////////////////// proc tst_system(string s, list #) "USAGE: tst_system(s); s string RETURN: string which is stdout and stderr of system(\"sh\", s) EXAMPLE: example tst_system; shows examples" { string tmpfile = "/tmp/tst_" + string(system("pid")); int errno; s = s + " 1>" + tmpfile + " 2>&1"; errno = system("sh", s); s = read(tmpfile); errno = system("sh", "rm -f " + tmpfile); if (size(#) > 0 && size(s) > 1) { s = s[1, size(s) -1]; } return (s); } example { "EXAMPLE"; echo = 2; string s = tst_system("echo This is an example of tst_system"); "The following is what the system call wrote to stdout: " + s; } proc tst_ignore(list #) "USAGE: tst_ignore(any,[keyword], [link]) any -- valid argument to string() keyword -- an arbitrary string link -- a link which can be written to RETURN: none; writes string(any) to link (or stdout, if no link given), prepending prefix \"// tst_ignore:\", or \"// tst_ignore:keyword hostname:\", if keyword was given. Should be used in tst files to output system dependent data (like date, pathnames). EXAMPLE: example tst_ignore; shows examples " { if (! defined(tst_no_status)) { string s; string keyword = ""; link outlink = ""; // Check # of args if (size(#) < 1 || size(#) > 3) { ERROR("Error tst_ignore: Wrong number of arguments Usage: tst_ignore (any,[keyword], [link]);"); } // Get Args s = string(#[1]); if (size(#) == 3) { keyword = #[2]; outlink = #[3]; } if (size(#) == 2) { if (typeof(#[2]) == "string") { keyword = #[2]; } else { outlink = #[2]; } } // check args if (typeof(keyword) != "string") { "Error tst_ignore: Keyword must be a string"; "Usage: tst_ignore (any,[keyword], [link]);"; return(); } if (status(outlink, "open", "no")) { open(outlink); } if (status(outlink, "write", "not ready")) { "Error tst_ignore: Cannot write to link"; outlink; "Usage: tst_ignore (any,[keyword], [link]);"; return(); } // ready -- do the actual work if (keyword != "") { write(outlink,"// tst_ignore:" + keyword + " :: " + tst_system("hostname", 1) + ":" + s); } else { write(outlink, "// tst_ignore: " + s); } } } example { "EXAMPLE"; "System independent data can safely be output in tst files;"; "However, system dependent data like dates, or pathnames, should be output"; "using the command tst_ignore(...), like"; echo = 2; tst_ignore(tst_system("date")); int t1 = timer; tst_ignore(t1, "time"); tst_ignore(memory(1), "memory"); } static proc Get_tst_timer() { if (! defined (tst_timer)) { string tst_timer = "// tst_ignore:0"; export tst_timer; return (0); } else { execute("int tst_int_timer = " + tst_timer[15,size(tst_timer)] + ";"); return (tst_int_timer); } } static proc Set_tst_timer (int this_time) { tst_timer = tst_timer[1,14] + string(this_time); } static proc GetTstStatusFile() { if (!defined(tst_status_file)) { return ("tst_status.out"); } else { return (tst_status_file); } } static proc tst_status_out (def prefix, def what, list #) { string outstring; outstring = string(prefix) + " >> " + string(what); if (size(#) > 0) { outstring = outstring + " :: " + tst_system("hostname", 1) + ":" + string(#[1]); } write(":a " + GetTstStatusFile(), outstring); } proc tst_status (list #) "USAGE: tst_status([prefix [, start_up]]) prefix -- string start_up -- int RETURN: none PURPOSE: writes to tst-output the current memory usage and used CPU time. If no integer argument is given, the elapsed CPU time since the last call to tst_status() is reported. If an integer argument is given, the elapsed CPU time since the start-up of @sc{Singular} is reported. If prefix is given, output reported start with prefix. NOTE: Should be used regularly within tst files to enable automatic tracking of memory and time performance. EXAMPLE: example tst_status; shows example SEE ALSO: tst_init " { int start_up; if (size(#) > 0) { if (typeof(#[1]) == "string") { string prefix = #[1]; if (size(#) > 1) { start_up = 1; } } else { start_up = 1; } } if (! defined(tst_no_status)) { if (! defined(tst_status_counter)) { int tst_status_counter = 1; export tst_status_counter; } else { tst_status_counter++; } if (!defined(prefix)) { int prefix = tst_status_counter; } tst_status_out(prefix, "tst_memory_0", memory(0)); tst_status_out(prefix, "tst_memory_1", memory(1)); tst_status_out(prefix, "tst_memory_2", memory(2)); if (start_up > 0) { tst_status_out(prefix, "tst_timer_1", timer); } else { tst_status_out(prefix, "tst_timer", timer - Get_tst_timer()); Set_tst_timer(timer); } } } example { "EXAMPLE"; echo = 2; tst_status(); ring r; poly p = (x+y+z)^40; tst_status(); tst_status(1); } proc tst_init(list #) "USAGE: tst_init([file]) file -- string RETURN: none PURPOSE: initializes further calls to tst routines: If no arguments are given, and if tst_status_file is not defined, then tst-output is written to stdout, else tst-output is written to file. EXAMPLE: example tst_init; shows example " { if (! defined(tst_no_status)) { string outfile = ""; if (size(#) > 0) { if (typeof(#[1]) == string) { outfile = #[1]; } } if (!defined(tst_status_file)) { string tst_status_file = outfile; export tst_status_file; } if (GetTstStatusFile() != "") { write(":w " + GetTstStatusFile(), "Status Output of " + GetTstStatusFile()); } tst_status_out("init", "USER :" + system("getenv", "USER")); tst_status_out("init", "HOSTNAME:" + tst_system("hostname", 1)); tst_status_out("init", "uname -a:" + tst_system("uname -a", 1)); tst_status_out("init", "date :" + tst_system("date", 1)); tst_status_out("init", "version :" + string(system("version"))); tst_status_out("init", "ticks :" + string(system("--ticks-per-sec"))); "init >> " + GetTstStatusFile(); } } example { "EXAMPLE"; echo = 2; tst_init(); } proc tst_InitTimer(list #) "USAGE: tst_InitTime([ticks_per_second]) ticks_per_second -- int RETURN: none PURPOSE: initializes tst timer for subsequent calls to tst_StopTimer or tst_ReportTimer. If the ticks_per_second argument is given, then the timer resolution is set to this value. Otherwise, the default timer resolution is used. SEE ALSO: tst_StopTimer, tst_GetTimer, tst_ReportTimer " { if (!defined(tst_Timer)) { int tst_Timer; export tst_Timer; } if (size(#) > 0) { if (typeof(#[1]) == "int") { if (#[1] > 0) { system("--ticks-per-sec", #[1]); } else { ERROR("need integer argument > 0"); } } else { ERROR("need integer argument"); } } tst_Timer = timer; } proc tst_StopTimer() "USAGE: tst_StopTimer() RETURN: int, timer ticks of elapsed CPU time since last call to tst_InitTimer PUPOSE: stops the timer initialized by previous call to tst_InitTimer SEE ALSO: tst_InitTimer, tst_GetTimer, tst_ReportTimer " { tst_Timer = timer - tst_Timer; return (tst_Timer); } proc tst_GetTimer() "USAGE: tst_GetTimer() RETURN: int, timer ticks of elapsed CPU time since last call to tst_Init NOTE: does NOT stop the time initialized by previous call to tst_InitTimer SEE ALSO: tst_InitTimer, tst_GetTimer, tst_ReportTimer " { int tt = timer - tst_Timer; return (tt); } proc tst_ReportTimer(list #) "USAGE: tst_ReportTimer([prefix]) RETURN: none PUPOSE: stops the timer initialized by previous call to tst_InitTimer; reports time to tst-output; if prefix is given, timer output is prefixed by it. SEE ALSO: tst_InitTimer, tst_GetTimer, tst_StopTimer, tst_OutTimer, tst_init " { tst_Timer = timer - tst_Timer; tst_OutTimer(tst_Timer, #); } proc tst_OutTimer(int tt, list #) "USAGE: tst_OutTimer(ticks [, prefix]) RETURN: none PURPOSE: reports value of tt to tst-output; if prefix is given, timer output is prefixed by it. SEE ALSO: tst_InitTimer, tst_GetTimer, tst_StopTimer, tst_ReportTimer, tst_init " { string prefix = "OutTimer"; if (size(#) > 0) { prefix = string(#[1]); } tst_status_out(prefix, "tst-Timer", tt); } /////////////////////////////////////////////////////////////////////// proc tst_groebnerTest(ideal i, list #) "USAGE: tst_groebnerTesti,[v]) : ideal i, [int v] RETURN: 1, if groebner command produced \"equal\" std as std command 0, otherwise Two std's are \"equal\" here, if their redSB's are element-wise equal, and if they reduce each other to zero, and if their leading ideals are equal On success, times of std - groebner is written with tst_ignore, and times are added to global variables tst_std_time and tst_groebner_time. If v given, and <= 0, short ideal characteristic is printed, if v > 0, ideals are printed. On failure, Error message and ideals are printed. EXAMPLE: example tst_groebner; shows an example " { int st = timer; ideal si = std(i); st = timer - st; int gt = timer; ideal gi = groebner(i); gt = timer - gt; if (tst_stdEqual(si, gi)) { tst_ignore(string(st) + " - " + string(gt) + " == " + string(st - gt)); if (! defined(tst_groebner_time)) { int tst_groebner_time; int tst_std_time; export tst_groebner_time, tst_std_time; } tst_std_time = tst_std_time + st; tst_groebner_time = tst_groebner_time + gt; if (size(#)) { if (typeof(#[1] == "int")) { if (#[1] <= 0) { idPrintShort(si, "si"); idPrintShort(gi, "gi"); } else { si; gi; } } } return (1); } return (0); } example { "EXAMPLE: "; echo = 2; ring r = 0, (a,b,c,d), lp; ideal i = a+b+c+d, ab+ad+bc+cd, abc+abd+acd+bcd, abcd-1; // cyclic 4 tst_groebnerTest(i); tst_groebnerTest(i, 0); tst_groebnerTest(i, 1); } // // A routine which test for equality of "std-bases" // proc tst_stdEqual(ideal i1, ideal i2) "USAGE: tst_stdEqual(i1, i2) ideal i1, i2 RETURN 1, if i1 \"equald\" i2 as a std bases 0, otherwise Two std's are \"equal\" here, if their redSB's are element-wise equal, and if they reduce each other to zero, and if their leading ideals are equal On failure, error message is printed. EXAMPLE: example tst_stdEqual; shows an example " { int i; int back; intvec opts = option(get); option(redSB); ideal ri1 = simplify(interred(i1), 1); ideal ri2 = simplify(interred(i2), 1); option(set, opts); if (size(ri1) != size(ri2)) { "Error in tst_stdEqual: Reduced sizes differ"; size(ri1); size(ri2); return(0); } for (i=1; i<=size(ri1); i++) { if (ri1[i] != ri2[i]) { "Error in tst_stdEqual: " + string(i) + " th polynomials differ"; ri1[i]; ri2[i]; return(0); } } // reduced SB are now equal if (size(reduce(i1, i2, 1)) == 0) { if (size(reduce(i2, i1, 1)) == 0) { poly p1, p2; ideal si1 = simplify(i1, 7); ideal si2 = simplify(i2, 7); if (size(si1) == size(si2)) { for (i=1; i<=size(si1); i++) { p1 = p1 + lead(si1[i]); p2 = p2 + lead(si2[i]); } if (p1 != p2) { "Error in tst_stdEqual: Lead monoms differ:"; p1; p2; return(0); } } else { "Error in tst_stdEqual: size differs:"; size(si1); size(si2); return(0); } } else { "Error in tst_stdEqual: reduce(i2, i1) != 0"; return(0); } } else { back = 1; "Error in tst_stdEqual: reduce(i1, i2) != 0"; return(0); } return (1); } example { "EXAMPLE: "; echo = 2; ring r = 0, (a,b,c,d), lp; ideal i = a+b+c+d, ab+ad+bc+cd, abc+abd+acd+bcd, abcd-1; // cyclic 4 tst_stdEqual(groebner(i), std(i)); tst_stdEqual(std(i), i); } static proc idPrintShort(ideal id, string name) { "Summary of " + name + " (leading monoms and size of polys):"; int i; for (i = 1; i<=size(id); i++) { "[" + string(i) + "]: #" + string(size(id[i])) + ":" + string(lead(id[i])); } } proc tst_test_res(ideal i, list #) "USAGE: tst_test_res(ideal i, only_lres_and_hres) RETURN: 1, if ok; 0 on error PURPOSE: Tests sres, lres, hres, mres with betti commands and conversions If optinal third argument is given, test only lres and hres EXAMPLE: example tst_test_res shows an example" { int ret = 1; if (! homog(i)) { ERROR("ERROR: input ideal needs to be homogenous "); } if (size(#) == 0) { resolution rs = sres(std(i), 0); resolution rm = mres(i,0); } resolution rh = hres(i,0); resolution rl = lres(i, 0); if (size(#) == 0) { intmat is = betti(rs); intmat im = betti(rm); } intmat ih = betti(rh); intmat il = betti(rl); if (size(ih) != size(il)){"ERROR: size(ih) != size(il)";return(0);} if (size(#) == 0) { if (size(ih) != size(is)){"ERROR: size(ih) != size(is)";return(0);} if (size(ih) != size(im)){"ERROR: size(ih) != size(im)";return(0);} } if (ih != il){"ERROR: ih != il";return(0);} if (size(#) == 0) { if (ih != is){"ERROR: ih != is";return(0);} if (ih != im){"ERROR: ih != im";return(0);} } if (size(#) == 0) { list ls = list(rs); list lm = list(rm); } list lh = list(rh); list ll = list(rl); if (size(#) == 0) { intmat is_1 = betti(ls); intmat im_1 = betti(lm); } intmat ih_1 = betti(lh); intmat il_1 = betti(ll); if (size(ih_1) != size(il_1)){"ERROR: size(ih_1) != size(il_1)";return(0);} if (size(#) == 0) { if (size(ih_1) != size(is_1)){"ERROR: size(ih_1) != size(is_1)";return(0);} if (size(ih_1) != size(im_1)){"ERROR: size(ih_1) != size(im_1)";return(0);} } if (ih_1 != il_1){"ERROR: ih_1 != il_1";return(0);} if (size(#) == 0) { if (ih_1 != is_1){"ERROR: ih_1 != is_1";return(0);} if (ih_1 != im_1){"ERROR: ih_1 != im_1";return(0);} } if (size(ih) != size(ih_1)) {"ERROR: size(ih) != size(ih_1)";return(0);} if (ih != ih_1) {"ERROR: ih != ih_1";return(0);} return (ret); } example { "EXAMPLE: "; echo = 2; ring an=0,(w,x,y,z),(dp,C); ideal i= 1w2xy+1w2xz+1w2yz+1wxyz+1x2yz+1xy2z+1xyz2, 1w4x+1w4z+1w3yz+1w2xyz+1wx2yz+1x2y2z+1xy2z2, 1w6+1w5z+1w4xz+1w3xyz+1w2xy2z+1wx2y2z+1x2y2z2; tst_test_res(i); kill an; } ///////////////////////////////////////////////////////////////////////////// proc tst_rgen_init_weights(int n) { intvec v = 1..n; return (v); } proc tst_rgen_init_matrix(int n) { intmat m[n][n]; int i; // let us emulate lp for (i=1; i<= n; i++) { m[i,i] = 1; } return (m); } proc tst_rgen_generate_block(int n_vars, string simple_ordering, int extra_weights) { string order = simple_ordering; if (extra_weights > n_vars) { extra_weights = n_vars; } if ((simple_ordering[1] == "W") || (simple_ordering[1] == "w")) { order = order + "(" + string(tst_rgen_init_weights(n_vars)) + ")"; } else { if (simple_ordering[1] == "M") { order = order + "(" + string(tst_rgen_init_matrix(n_vars)) + ")"; } else { order = order + "(" + string(n_vars) + ")"; } } if (extra_weights >= 1) { order = "a(" + string(tst_rgen_init_weights(extra_weights)) + ")," + order; } return (order); } proc tst_rgen_generate_blocks(int n_vars, list simple_orderings, intvec extra_weights) { int i; int j; list blocks; for (i=1; i<=size(simple_orderings); i++) { for (j=1; j<=size(extra_weights); j++) { blocks = blocks + list(tst_rgen_generate_block(n_vars, simple_orderings[i], extra_weights[j])); } } return (blocks); } proc tst_rgen_generate_product_orderings(int n_vars, list simple_orderings, intvec extra_weights, intvec products) { list p_orderings; int i; int nn_vars, j, k,l; list nb_orderings; string n_ordering; for (i=1;i<=size(products);i++) { if (products[i] > 1 && products[i] <= n_vars) { nn_vars = n_vars div products[i]; nb_orderings = tst_rgen_generate_blocks(nn_vars, simple_orderings, extra_weights); for (j=1; j<=size(nb_orderings); j++) { n_ordering = nb_orderings[j]; for (k=2; k<=products[i]; k++) { l = (j + k - 1) % size(nb_orderings); if (l == 0) { l = size(nb_orderings); } n_ordering = n_ordering + "," + nb_orderings[l]; } if (products[i]*nn_vars < n_vars) { n_ordering = n_ordering + ", lp"; } p_orderings = p_orderings + list(n_ordering); } } else { if (products[i] == 1) { p_orderings = p_orderings + tst_rgen_generate_blocks(n_vars, simple_orderings, extra_weights); } } } if (size(p_orderings) < 1) { p_orderings = tst_rgen_generate_blocks(n_vars, simple_orderings, extra_weights); } return (p_orderings); } proc tst_rgen_init() { if (! defined(tst_rgen_charstrs)) { list tst_rgen_charstrs; export(tst_rgen_charstrs); tst_rgen_charstrs = list("32003", "0"); } if (! defined(tst_rgen_nvars)) { intvec tst_rgen_nvars; export(tst_rgen_nvars); tst_rgen_nvars = 1..10; } if (! defined(tst_rgen_simple_orderings)) { list tst_rgen_simple_orderings; export(tst_rgen_simple_orderings); tst_rgen_simple_orderings = list("lp", "dp", "Dp", "ls", "ds", "Ds", "wp","Wp","ws","Ws","M"); } if (! defined(tst_rgen_comp_orderings)) { list tst_rgen_comp_orderings; export(tst_rgen_comp_orderings); tst_rgen_comp_orderings = list("", "C", "c", "CC", "cc"); } if (! defined(tst_rgen_products)) { intvec tst_rgen_products; export(tst_rgen_products); tst_rgen_products = 1..3; } if (! defined(tst_rgen_extra_weights)) { intvec tst_rgen_extra_weights; export(tst_rgen_extra_weights); tst_rgen_extra_weights = 0..2; } if (! defined(tst_rgen_exp_bounds)) { list tst_rgen_exp_bounds; export(tst_rgen_exp_bounds); } if (! defined(tst_rgen_char_index)) { int tst_rgen_char_index, tst_rgen_var_index, tst_rgen_comp_index, tst_rgen_ordering_index, tst_rgen_exp_bounds_index; list tst_rgen_orderings; export(tst_rgen_char_index); export(tst_rgen_var_index); export(tst_rgen_comp_index); export(tst_rgen_ordering_index); export(tst_rgen_orderings); export(tst_rgen_exp_bounds_index); } tst_rgen_char_index = 1; tst_rgen_var_index = 1; tst_rgen_comp_index = 1; tst_rgen_ordering_index = 0; tst_rgen_exp_bounds_index = 1; tst_rgen_orderings = tst_rgen_generate_product_orderings(tst_rgen_nvars[1], tst_rgen_simple_orderings, tst_rgen_extra_weights, tst_rgen_products); } proc tst_next_ring() { tst_rgen_ordering_index++; if (tst_rgen_ordering_index > size(tst_rgen_orderings)) { tst_rgen_comp_index++; if (tst_rgen_comp_index > size(tst_rgen_comp_orderings)) { tst_rgen_exp_bounds_index++; if (tst_rgen_exp_bounds_index > size(tst_rgen_exp_bounds)) { tst_rgen_var_index++; if (tst_rgen_var_index > size(tst_rgen_nvars)) { tst_rgen_char_index++; if (tst_rgen_char_index > size(tst_rgen_charstrs)) { return (""); } tst_rgen_var_index = 1; } tst_rgen_exp_bounds_index = 1; } tst_rgen_comp_index = 1; tst_rgen_orderings = tst_rgen_generate_product_orderings(tst_rgen_nvars[tst_rgen_var_index], tst_rgen_simple_orderings, tst_rgen_extra_weights, tst_rgen_products); } tst_rgen_ordering_index = 1; } if (tst_rgen_nvars[tst_rgen_var_index] <= 26) { string rs = "(" + tst_rgen_charstrs[tst_rgen_char_index] + "),(" + A_Z("a", tst_rgen_nvars[tst_rgen_var_index]) + "),("; } else { string rs = "(" + tst_rgen_charstrs[tst_rgen_char_index] + "),(x(1.." + string(tst_rgen_nvars[tst_rgen_var_index]) + ")),("; } if (tst_rgen_comp_orderings[tst_rgen_comp_index] == "CC") { rs = rs + "C," + tst_rgen_orderings[tst_rgen_ordering_index]; } else { if (tst_rgen_comp_orderings[tst_rgen_comp_index] == "cc") { rs = rs + "c," + tst_rgen_orderings[tst_rgen_ordering_index]; } else { if (tst_rgen_comp_orderings[tst_rgen_comp_index] == "C") { rs = rs + tst_rgen_orderings[tst_rgen_ordering_index] + ", C"; } else { if (tst_rgen_comp_orderings[tst_rgen_comp_index] == "c") { rs = rs + tst_rgen_orderings[tst_rgen_ordering_index] + ",c"; } else { rs = rs + tst_rgen_orderings[tst_rgen_ordering_index]; } } } } if (size(tst_rgen_exp_bounds) > 0) { if (! defined(tst_rgen_Lring)) { string tst_rgen_Lring; export(tst_rgen_Lring); } tst_rgen_Lring = rs + ",L(" + string(tst_rgen_exp_bounds[tst_rgen_exp_bounds_index]) + "))"; if (system("version") >= 1309) { rs = tst_rgen_Lring; } else { rs = rs + ")"; } } else { rs = rs + ")"; } return (rs); } proc tst_FullIdeal() { ideal id, mid; int n_vars = nvars(basering); int i,j; for (i=1; i<=n_vars; i++) { mid = maxideal(i); id[i] = mid[1]; for (j=2;j<=size(mid); j++) { id[i] = id[i] + mid[j]; } } return (id); } proc tst_cyclic(int n) { int i, j, k, l; ideal id; poly p, q; for (i=1; i n) { k=1; } for (l=2; l <= i; l++) { q = q*var(k); k++; if (k > n) { k=1; } } p = p + q; } id[i] = p; } p = var(1); for (i=2;i<=n;i++) { p = p*var(i); } id[n] = p -1; return (id); } proc tst_hom_cyclic(int n) { ideal i = tst_cyclic(n); i[n] = i[n] + 1 + var(n+1)^n; return (i); } proc tst_TestMult(ideal id, int how_often, int Module) { int i, j, l, is, s; module m; def ret; poly p; if (Module > 0) { for (i=1; i<= size(id); i++) { m[i] = id[i] + gen(2)*id[i]; } ret = m; } else { ret = id; } l = 0; for (i=1; i<= how_often; i++) { l++; if (l > size(id)) { l = 1; } for (j=1;j<=size(id);j++) { ret[j] = ret[j]*id[l]; } } for (i=1; i<=size(ret); i++) { is = size(ret[i]); s = s + is; string(i) + " : " + string(is) + " : " + string(lead(ret[i])); } "s : " + string(s); } proc tst_TestAdd(ideal id, int how_often, int Module) { int i, j, k, l; module m; ideal idl = 1, maxideal(1); if (Module > 0) { for (i=1; i<= size(id); i++) { m[i] = id[i] + gen(2)*id[i]; } } def r,p; if (Module > 0) { r = m; } else { r = id; } l = 0; for (j=1; j<= how_often; j++) { l++; if (l > size(idl)) { l = 1; } for (k=1; k<=size(r); k++) { p = idl[l]*r[k]; for (i=1; i<=k;i++) { p = p + r[i]; } r[k] = p; } } int is, s; for (i=1; i<=size(r); i++) { is = size(r[i]); s = s + is; string(i) + " : " + string(is) + " : " + string(lead(r[i])); } "s : " + string(s); } proc tst_PrintStats(def id) { int i, is, s; for (i=1; i<=size(id); i++) { is = size(id[i]); s = s + is; string(i) + " : " + string(is) + " : " + string(lead(id[i])); } "s : " + string(s); } singular-4.0.3+ds/Singular/LIB/weierstr.lib000066400000000000000000000155111266270727000205060ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version weierstr.lib 4.0.0.0 Jun_2013 "; // $Id: b457489cc9c710a0b3f9d3dee99355b33c6ae63e $ category="Teaching"; info=" LIBRARY: weierstr.lib Procedures for the Weierstrass Theorems AUTHOR: G.-M. Greuel, greuel@mathematik.uni-kl.de PROCEDURES: weierstrDiv(g,f,d); perform Weierstrass division of g by f up to degree d weierstrPrep(f,d); perform Weierstrass preparation of f up to degree d lastvarGeneral(f); make f general of finite order w.r.t. last variable generalOrder(f); compute integer b s.t. f is x_n-general of order b (parameters in square brackets [] are optional) "; LIB "mondromy.lib"; LIB "poly.lib"; /////////////////////////////////////////////////////////////////////////////// proc generalOrder (poly f) "USAGE: generalOrder(f); f=poly RETURN: integer b if f is general of order b w.r.t. the last variable, say T, resp. -1 if not (i.e. f(0,...,0,T) is of order b, resp. f(0,...,0,T)==0) NOTE: the procedure works for any monomial ordering EXAMPLE: example generalOrder; shows an example " { int ii; int n = nvars(basering); for (ii=1; ii0) { "//",f;"// is "+string(var(n))+"-general of order", b; pause("press to continue"); } if ( b==-1 ) { "// second polynomial is not general w.r.t. last variable"; "// use the procedure lastvarGeneral first"; result=h,g; return(result); } //------------------------- start computation -------------------------------- D = d+b; poly fhat = jet(f,b-1,v); poly ftilde = (f-fhat)/var(n)^b; poly u = invunit(ftilde,D); if (y>0) { "// fhat (up to order", d,"):"; "//", fhat; "// ftilde:"; "//", ftilde; "// ftilde-inverse:"; "//", u; pause("press to continue"); } poly khat, ktilde; poly k=g; khat = jet(k,b-1,v); ktilde = (k-r)/var(n)^b; r = khat; h = ktilde; ii=0; while (size(k) > 0) { if (y>0) { "// loop",ii+1; "// khat:"; "//", khat; "// ktilde:"; "//", ktilde; "// remainder:"; "//", r; "// multiplier:"; "//", h; pause("press to continue"); } k = jet(-fhat*u*ktilde,D); khat = jet(k,b-1,v); ktilde = (k-khat)/var(n)^b; r = r + khat; h = h + ktilde; ii=ii+1; } result = jet(u*h,d),jet(r,d),ii; return(result); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),ds; poly f = y - xy2 + x2; poly g = y; list l = weierstrDiv(g,f,10); l;""; l[1]*f + l[2]; //g = l[1]*f+l[2] up to degree 10 } /////////////////////////////////////////////////////////////////////////////// proc weierstrPrep (poly f, int d) "USAGE: weierstrPrep(f,d); f=poly, d=integer ASSUME: f must be general of finite order, say b, in the last ring variable, say T; if not apply the procedure lastvarGeneral first PURPOSE: perform the Weierstrass preparation of f up to order d RETURN: - a list, say l, of two polynomials and one integer, l[1] a unit, l[2] a Weierstrass polynomial, l[3] an integer such that l[1]*f = l[2], where l[2] is a Weierstrass polynomial, (i.e. l[2] = T^b + lower terms in T) up to (including) total degree d l[3] is the number of iterations used@* - if f is not T-general, return (0,0) NOTE: the procedure works for any monomial ordering THEORY: the proof of Grauert-Remmert (Analytische Stellenalgebren) is used for the algorithm EXAMPLE: example weierstrPrep; shows an example " { int n = nvars(basering); int b = generalOrder(f); if ( b==-1 ) { "// second polynomial is not general w.r.t. last variable"; "// use the procedure lastvarGeneral first"; poly h,g; list result=h,g; return(result); } list L = weierstrDiv(var(n)^b,f,d); list result = L[1], var(n)^b - L[2],L[3]; return(result); } example { "EXAMPLE:"; echo = 2; ring R = 0,(x,y),ds; poly f = xy+y2+y4; list l = weierstrPrep(f,5); l; ""; f*l[1]-l[2]; // = 0 up to degree 5 } /////////////////////////////////////////////////////////////////////////////// proc lastvarGeneral (poly f) "USAGE: lastvarGeneral(f,d); f=poly RETURN: poly, say g, obtained from f by a generic change of variables, s.t. g is general of finite order b w.r.t. the last ring variable, say T (i.e. g(0,...,0,T)= c*T^b + higher terms, c!=0) NOTE: the procedure works for any monomial ordering EXAMPLE: example lastvarGeneral; shows an example " { int n = nvars(basering); int b = generalOrder(f); if ( b >=0 ) { return(f); } else { def B = basering; int ii; map phi; ideal m=maxideal(1); int d = mindeg1(f); poly g = jet(f,d); for (ii=1; ii<=n-1; ii++) { if (size(g)>size(subst(g,var(ii),0)) ) { m[ii]= var(ii)+ random(1-(voice-2)*10,1+(voice-2)*10)*var(n); phi = B,m; g = phi(f); break; } } if ( voice <=5 ) { return(lastvarGeneral(g)); } if ( voice ==6 ) { for (ii=1; ii<=n-1; ii++) { m[ii]= var(ii)+ var(n)*random(1,1000); } phi = basering,m; g = phi(f); return(lastvarGeneral(g)); } else { for (ii=1; ii<=n-1; ii++) { m[ii]= var(ii)+ var(n)^random(2,voice*d); } phi = basering,m; g = phi(f); return(lastvarGeneral(g)); } } } example { "EXAMPLE:"; echo = 2; ring R = 2,(x,y,z),ls; poly f = xyz; lastvarGeneral(f); } /////////////////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/LIB/zeroset.lib000066400000000000000000001325501266270727000203400ustar00rootroot00000000000000//////////////////////////////////////////////////////////////////////////// version="version zeroset.lib 4.0.0.0 Jun_2013 "; // $Id: 5540e60ae4427cbb3496537ada892d633ad0b801 $ category="Symbolic-numerical solving"; info=" LIBRARY: zeroset.lib Procedures for roots and factorization AUTHOR: Thomas Bayer, email: tbayer@mathematik.uni-kl.de,@* http://wwwmayr.informatik.tu-muenchen.de/personen/bayert/@* Current address: Hochschule Ravensburg-Weingarten OVERVIEW: Algorithms for finding the zero-set of a zero-dim. ideal in Q(a)[x_1,..,x_n], roots and factorization of univariate polynomials over Q(a)[t] where a is an algebraic number. Written in the scope of the diploma thesis (advisor: Prof. Gert-Martin Greuel) 'Computations of moduli spaces of semiquasihomogeneous singularities and an implementation in Singular'. This library is meant as a preliminary extension of the functionality of @sc{Singular} for univariate factorization of polynomials over simple algebraic extensions in characteristic 0. NOTE: Subprocedures with postfix 'Main' require that the ring contains a variable 'a' and no parameters, and the ideal 'mpoly', where 'minpoly' from the basering is stored. PROCEDURES: Quotient(f, g) quotient q of f w.r.t. g (in f = q*g + remainder) remainder(f,g) remainder of the division of f by g roots(f) computes all roots of f in an extension field of Q sqfrNorm(f) norm of f (f must be squarefree) zeroSet(I) zero-set of the 0-dim. ideal I egcdMain(f, g) gcd over an algebraic extension field of Q factorMain(f) factorization of f over an algebraic extension field invertNumberMain(c) inverts an element of an algebraic extension field quotientMain(f, g) quotient of f w.r.t. g remainderMain(f,g) remainder of the division of f by g rootsMain(f) computes all roots of f, might extend the ground field sqfrNormMain(f) norm of f (f must be squarefree) containedQ(data, f) f in data ? sameQ(a, b) a == b (list a,b) "; LIB "primitiv.lib"; LIB "primdec.lib"; // note : return a ring : ring need not be exported !!! // Artihmetic in Q(a)[x] without built-in procedures // assume basering = Q[x,a] and minpoly is represented by mpoly(a). // the algorithms are taken from "Polynomial Algorithms in Computer Algebra", // F. Winkler, Springer Verlag Wien, 1996. // To do : // squarefree factorization // multiplicities // Improvement : // a main problem is the growth of the coefficients. Try roots(x7 - 1) // return ideal mpoly ! // mpoly is not monic, comes from primitive_extra // IMPLEMENTATION // // In procedures with name 'proc-name'Main a polynomial ring over a simple // extension field is represented as Q[x...,a] together with the ideal // 'mpoly' (attribute "isSB"). The arithmetic in the extension field is // implemented in the procedures in the procedures 'MultPolys' (multiplication) // and 'InvertNumber' (inversion). After addition and substraction one should // apply 'SimplifyPoly' to the result to reduce the result w.r.t. 'mpoly'. // This is done by reducing each coefficient seperately, which is more // efficient for polynomials with many terms. /////////////////////////////////////////////////////////////////////////////// proc roots(poly f) "USAGE: roots(f); where f is a polynomial PURPOSE: compute all roots of f in a finite extension of the ground field without multiplicities. RETURN: ring, a polynomial ring over an extension field of the ground field, containing a list 'theRoots' and polynomials 'newA' and 'f': @format - 'theRoots' is the list of roots of the polynomial f (no multiplicities) - if the ground field is Q(a') and the extension field is Q(a), then 'newA' is the representation of a' in Q(a). If the basering contains a parameter 'a' and the minpoly remains unchanged then 'newA' = 'a'. If the basering does not contain a parameter then 'newA' = 'a' (default). - 'f' is the polynomial f in Q(a) (a' being substituted by 'newA') @end format ASSUME: ground field to be Q or a simple extension of Q given by a minpoly EXAMPLE: example roots; shows an example " { int dbPrt = printlevel-voice+3; // create a new ring where par(1) is replaced by the variable // with the same name or, if basering does not contain a parameter, // with a new variable 'a'. def ROB = basering; def ROR = TransferRing(basering); setring ROR; export(ROR); // get the polynomial f and find the roots poly f = imap(ROB, f); list result = rootsMain(f); // find roots of f // store the roots and the new representation of 'a' and transform // the coefficients of f. list theRoots = result[1]; poly newA = result[2]; map F = basering, maxideal(1); F[nvars(basering)] = newA; poly fn = SimplifyPoly(F(f)); // create a new ring with minploy = mpoly[1] (from ROR) def RON = NewBaseRing(); setring(RON); list theRoots = imap(ROR, theRoots); poly newA = imap(ROR, newA); poly f = imap(ROR, fn); kill ROR; export(theRoots); export(newA); export(f); dbprint(dbPrt," // 'roots' created a new ring which contains the list 'theRoots' and // the polynomials 'f' and 'newA' // To access the roots, newA and the new representation of f, type def R = roots(f); setring R; theRoots; newA; f; "); return(RON); } example {"EXAMPLE:"; echo = 2; ring R = (0,a), x, lp; minpoly = a2+1; poly f = x3 - a; def R1 = roots(f); setring R1; minpoly; newA; f; theRoots; map F; F[1] = theRoots[1]; F(f); } /////////////////////////////////////////////////////////////////////////////// proc rootsMain(poly f) "USAGE: rootsMain(f); where f is a polynomial PURPOSE: compute all roots of f in a finite extension of the ground field without multiplicities. RETURN: list, all entries are polynomials @format _[1] = roots of f, each entry is a polynomial _[2] = 'newA' - if the ground field is Q(b) and the extension field is Q(a), then 'newA' is the representation of b in Q(a) _[3] = minpoly of the algebraic extension of the ground field @end format ASSUME: basering = Q[x,a] ideal mpoly must be defined, it might be 0! NOTE: might change the ideal mpoly!! EXAMPLE: example rootsMain; shows an example " { int i, linFactors, nlinFactors, dbPrt; intvec wt = 1,0; // deg(a) = 0 list factorList, nlFactors, nlMult, roots, result; poly fa, lc; dbPrt = printlevel-voice+3; // factor f in Q(a)[t] to obtain the roots lying in Q(a) // firstly, find roots of the linear factors, // nonlinear factors are processed later dbprint(dbPrt, "roots of " + string(f) + ", minimal polynomial = " + string(mpoly[1])); factorList = factorMain(f); // Factorize f dbprint(dbPrt, (" prime factors of f are : " + string(factorList[1]))); linFactors = 0; nlinFactors = 0; for(i = 2; i <= size(factorList[1]); i = i + 1) { // find linear and nonlinear factors fa = factorList[1][i]; if(deg(fa, wt) == 1) { linFactors++; // get the root from the linear factor lc = LeadTerm(fa, 1)[3]; fa = MultPolys(invertNumberMain(lc), fa); // make factor monic roots[linFactors] = var(1) - fa; // fa is monic !! } else { // ignore nonlinear factors nlinFactors++; nlFactors[nlinFactors] = factorList[1][i]; nlMult[nlinFactors] = factorList[2][i]; } } if(linFactors == size(factorList[1]) - 1) { // all roots of f are contained in the ground field result[1] = roots; result[2] = var(2); result[3] = mpoly[1]; return(result); } // process the nonlinear factors, i.e., extend the ground field // where a nonlinear factor (irreducible) is a minimal polynomial // compute the primitive element of this extension ideal primElem, minPolys, Fid; list partSol; map F, Xchange; poly f1, newA, mp, oldMinPoly; Fid = mpoly; F[1] = var(1); Xchange[1] = var(2); // the variables have to be exchanged Xchange[2] = var(1); // for the use of 'primitive' if(nlinFactors == 1) // one nl factor { // compute the roots of the nonlinear (irreducible, monic) factor f1 of f // by extending the basefield by a' with minimal polynomial f1 // Then call roots(f1) to find the roots of f1 over the new base field f1 = nlFactors[1]; if(mpoly[1] != 0) { mp = mpoly[1]; minPolys = Xchange(mp), Xchange(f1); if (deg(jet(minPolys[2],0,intvec(1,0)))==0) { primElem = primitive(minPolys); } // random coord. change else { primElem = primitive_extra(minPolys); } // no random coord. change mpoly = std(primElem[1]); F = basering, maxideal(1); F[2] = primElem[2]; // transfer all to the new representation newA = primElem[2]; // new representation of a f1 = SimplifyPoly(F(f1)); //reduce(F(f1), mpoly); if(size(roots) > 0) {roots = SimplifyData(F(roots));} } else { mpoly = std(Xchange(f1)); newA = var(2); } result[3] = mpoly[1]; oldMinPoly = mpoly[1]; partSol = rootsMain(f1); // find roots of f1 over extended field if(oldMinPoly != partSol[3]) { // minpoly has changed ? // all previously computed roots must be transformed // because the minpoly has changed result[3] = partSol[3]; // new minpoly F[2] = partSol[2]; // new representation of algebraic number if(size(roots) > 0) {roots = SimplifyData(F(roots)); } newA = SimplifyPoly(F(newA)); // F(newA); } roots = roots + partSol[1]; // add roots result[2] = newA; result[1] = roots; } else { // more than one nonlinear (irreducible) factor (f_1,...,f_r) // solve each of them by rootsMain(f_i), append their roots // change the minpoly and transform all previously computed // roots if necessary. // Note that the for-loop is more or less book-keeping newA = var(2); result[2] = newA; for(i = 1; i <= size(nlFactors); i = i + 1) { oldMinPoly = mpoly[1]; partSol = rootsMain(nlFactors[i]); // main work nlFactors[i] = 0; // delete factor result[3] = partSol[3]; // store minpoly // book-keeping starts here as in the case 1 nonlinear factor if(oldMinPoly != partSol[3]) { // minpoly has changed F = basering, maxideal(1); F[2] = partSol[2]; // transfer all to the new representation newA = SimplifyPoly(F(newA)); // F(newA); new representation of a result[2] = newA; if(i < size(nlFactors)) { nlFactors = SimplifyData(F(nlFactors)); } // transform remaining factors if(size(roots) > 0) {roots = SimplifyData(F(roots));} } roots = roots + partSol[1]; // transform roots result[1] = roots; } // end more than one nl factor } return(result); } /////////////////////////////////////////////////////////////////////////////// proc zeroSet(ideal I, list #) "USAGE: zeroSet(I [,opt] ); I=ideal, opt=integer PURPOSE: compute the zero-set of the zero-dim. ideal I, in a finite extension of the ground field. RETURN: ring, a polynomial ring over an extension field of the ground field, containing a list 'theZeroset', a polynomial 'newA', and an ideal 'id': @format - 'theZeroset' is the list of the zeros of the ideal I, each zero is an ideal. - if the ground field is Q(b) and the extension field is Q(a), then 'newA' is the representation of b in Q(a). If the basering contains a parameter 'a' and the minpoly remains unchanged then 'newA' = 'a'. If the basering does not contain a parameter then 'newA' = 'a' (default). - 'id' is the ideal I in Q(a)[x_1,...] (a' substituted by 'newA') @end format ASSUME: dim(I) = 0, and ground field to be Q or a simple extension of Q given by a minpoly. OPTIONS: opt = 0: no primary decomposition (default) opt > 0: primary decomposition NOTE: If I contains an algebraic number (parameter) then I must be transformed w.r.t. 'newA' in the new ring. EXAMPLE: example zeroSet; shows an example " { int primaryDecQ, dbPrt; list rp; dbPrt = printlevel-voice+2; if(size(#) > 0) { primaryDecQ = #[1]; } else { primaryDecQ = 0; } // create a new ring 'ZSR' with one additional variable instead of the // parameter // if the basering does not contain a parameter then 'a' is used as the // additional variable. def RZSB = basering; def ZSR = TransferRing(RZSB); setring ZSR; // get ideal I and find the zero-set ideal id = std(imap(RZSB, I)); // print(dim(id)); if(dim(id) > 1) { // new variable adjoined to ZSR ERROR(" ideal not zerodimensional "); } list result = zeroSetMain(id, primaryDecQ); // store the zero-set, minimal polynomial and the new representative of 'a' list theZeroset = result[1]; poly newA = result[2]; poly minPoly = result[3][1]; // transform the generators of the ideal I w.r.t. the new representation // of 'a' map F = basering, maxideal(1); F[nvars(basering)] = newA; id = SimplifyData(F(id)); // create a new ring with minpoly = minPoly def RZBN = NewBaseRing(); setring RZBN; list theZeroset = imap(ZSR, theZeroset); poly newA = imap(ZSR, newA); ideal id = imap(ZSR, id); kill ZSR; export(id); export(theZeroset); export(newA); dbprint(dbPrt," // 'zeroSet' created a new ring which contains the list 'theZeroset', the ideal // 'id' and the polynomial 'newA'. 'id' is the ideal of the input transformed // w.r.t. 'newA'. // To access the zero-set, 'newA' and the new representation of the ideal, type def R = zeroSet(I); setring R; theZeroset; newA; id; "); setring RZSB; return(RZBN); } example {"EXAMPLE:"; echo = 2; ring R = (0,a), (x,y,z), lp; minpoly = a2 + 1; ideal I = x2 - 1/2, a*z - 1, y - 2; def T = zeroSet(I); setring T; minpoly; newA; id; theZeroset; map F1 = basering, theZeroset[1]; map F2 = basering, theZeroset[2]; F1(id); F2(id); } /////////////////////////////////////////////////////////////////////////////// proc invertNumberMain(poly f) "USAGE: invertNumberMain(f); where f is a polynomial PURPOSE: compute 1/f if f is a number in Q(a), i.e., f is represented by a polynomial in Q[a]. RETURN: poly 1/f ASSUME: basering = Q[x_1,...,x_n,a], ideal mpoly must be defined and != 0 ! NOTE: outdated, use / instead " { if(diff(f, var(1)) != 0) { ERROR("number must not contain variable !");} int n = nvars(basering); def RINB = basering; string ringSTR = "ring RINR = 0, " + string(var(n)) + ", dp;"; execute(ringSTR); // new ring = Q[a] list gcdList; poly f, g, inv; f = imap(RINB, f); g = imap(RINB, mpoly)[1]; if(diff(f, var(1)) != 0) { inv = extgcd(f, g)[2]; } // f contains var(1) else { inv = 1/f;} // f element in Q setring(RINB); return(imap(RINR, inv)); } /////////////////////////////////////////////////////////////////////////////// proc MultPolys(poly f, poly g) "USAGE: MultPolys(f, g); poly f,g PURPOSE: multiply the polynomials f and g and reduce them w.r.t. mpoly RETURN: poly f*g ASSUME: basering = Q[x,a], ideal mpoly must be defined, it might be 0 ! " { return(SimplifyPoly(f * g)); } /////////////////////////////////////////////////////////////////////////////// proc LeadTerm(poly f, int i) "USAGE: LeadTerm(f); poly f, int i PURPOSE: compute the leading coef and term of f w.r.t var(i), where the last ring variable is treated as a parameter. RETURN: list of polynomials _[1] = leading term _[2] = leading monomial _[3] = leading coefficient ASSUME: basering = Q[x_1,...,x_n,a] " { list result; matrix co = coef(f, var(i)); result[1] = co[1, 1]*co[2, 1]; result[2] = co[1, 1]; result[3] = co[2, 1]; return(result); } /////////////////////////////////////////////////////////////////////////////// proc Quotient(poly f, poly g) "USAGE: Quotient(f, g); where f,g are polynomials; PURPOSE: compute the quotient q and remainder r s.t. f = g*q + r, deg(r) < deg(g) RETURN: list of polynomials @format _[1] = quotient q _[2] = remainder r @end format ASSUME: basering = Q[x] or Q(a)[x] NOTE: This procedure is outdated, and should no longer be used. Use div and mod instead. EXAMPLE: example Quotient; shows an example " { def QUOB = basering; def QUOR = TransferRing(basering); // new ring with parameter 'a' replaced by a variable setring QUOR; export(QUOR); poly f = imap(QUOB, f); poly g = imap(QUOB, g); list result = quotientMain(f, g); setring(QUOB); list result = imap(QUOR, result); kill QUOR; return(result); } example {"EXAMPLE:"; echo = 2; ring R = (0,a), x, lp; minpoly = a2+1; poly f = x4 - 2; poly g = x - a; list qr = Quotient(f, g); qr; qr[1]*g + qr[2] - f; } proc quotientMain(poly f, poly g) "USAGE: quotientMain(f, g); where f,g are polynomials PURPOSE: compute the quotient q and remainder r s.th. f = g*q + r, deg(r) < deg(g) RETURN: list of polynomials @format _[1] = quotient q _[2] = remainder r @end format ASSUME: basering = Q[x,a] and ideal mpoly is defined (it might be 0), this represents the ring Q(a)[x] together with its minimal polynomial. NOTE: outdated, use div/mod instead " { if(g == 0) { ERROR("Division by zero !");} def QMB = basering; def QMR = NewBaseRing(); setring QMR; poly f, g, h; h = imap(QMB, f) / imap(QMB, g); setring QMB; return(list(imap(QMR, h), 0)); } /////////////////////////////////////////////////////////////////////////////// proc remainder(poly f, poly g) "USAGE: remainder(f, g); where f,g are polynomials PURPOSE: compute the remainder of the division of f by g, i.e. a polynomial r s.t. f = g*q + r, deg(r) < deg(g). RETURN: poly ASSUME: basering = Q[x] or Q(a)[x] NOTE: outdated, use mod/reduce instead " { def REMB = basering; def REMR = TransferRing(basering); // new ring with parameter 'a' replaced by a variable setring(REMR); export(REMR); poly f = imap(REMB, f); poly g = imap(REMB, g); poly h = remainderMain(f, g); setring(REMB); poly r = imap(REMR, h); kill REMR; return(r); } example {"EXAMPLE:"; echo = 2; ring R = (0,a), x, lp; minpoly = a2+1; poly f = x4 - 1; poly g = x3 - 1; remainder(f, g); } proc remainderMain(poly f, poly g) "USAGE: remainderMain(f, g); where f,g are polynomials PURPOSE: compute the remainder r s.t. f = g*q + r, deg(r) < deg(g) RETURN: poly ASSUME: basering = Q[x,a] and ideal mpoly is defined (it might be 0), this represents the ring Q(a)[x] together with its minimal polynomial. NOTE: outdated, use mod/reduce instead " { int dg; intvec wt = 1,0;; poly lc, g1, r; if(deg(g, wt) == 0) { return(0); } lc = LeadTerm(g, 1)[3]; g1 = MultPolys(invertNumberMain(lc), g); // make g monic return(SimplifyPoly(reduce(f, std(g1)))); } /////////////////////////////////////////////////////////////////////////////// proc egcdMain(poly f, poly g) "USAGE: egcdMain(f, g); where f,g are polynomials PURPOSE: compute the polynomial gcd of f and g over Q(a)[x] RETURN: poly ASSUME: basering = Q[x,a] and ideal mpoly is defined (it might be 0), this represents the ring Q(a)[x] together with its minimal polynomial. NOTE: outdated, use gcd instead EXAMPLE: example EGCD; shows an example " { // might be extended to return s1, s2 s.t. f*s1 + g*s2 = gcd int i = 1; poly r1, r2, r; r1 = f; r2 = g; while(r2 != 0) { r = remainderMain(r1, r2); r1 = r2; r2 = r; } return(r1); } /////////////////////////////////////////////////////////////////////////////// proc MEGCD(poly f, poly g, int varIndex) "USAGE: MEGCD(f, g, i); poly f, g; int i PURPOSE: compute the polynomial gcd of f and g in the i'th variable RETURN: poly ASSUME: f, g are polynomials in var(i), last variable is the algebraic number EXAMPLE: example MEGCD; shows an example " // might be extended to return s1, s2 s.t. f*s1 + g*s2 = gc // not used ! { string @str, @sf, @sg, @mp, @parName; def @RGCDB = basering; @sf = string(f); @sg = string(g); @mp = string(minpoly); if(npars(basering) == 0) { @parName = "0";} else { @parName = "(0, " + parstr(basering) + ")"; } @str = "ring @RGCD = " + @parName + ", " + string(var(varIndex)) + ", dp;"; execute(@str); if(@mp != "0") { execute ("minpoly = " + @mp + ";"); } execute("poly @f = " + @sf + ";"); execute("poly @g = " + @sg + ";"); export(@RGCD); poly @h = gcd(@f, @g); setring(@RGCDB); poly h = imap(@RGCD, @h); kill @RGCD; return(h); } /////////////////////////////////////////////////////////////////////////////// proc sqfrNorm(poly f) "USAGE: sqfrNorm(f); where f is a polynomial PURPOSE: compute the norm of the squarefree polynomial f in Q(a)[x]. RETURN: list with 3 entries @format _[1] = squarefree norm of g (poly) _[2] = g (= f(x - s*a)) (poly) _[3] = s (int) @end format ASSUME: f must be squarefree, basering = Q(a)[x] and minpoly != 0. NOTE: the norm is an element of Q[x] EXAMPLE: example sqfrNorm; shows an example " { def SNB = basering; def SNR = TransferRing(SNB); // new ring with parameter 'a' // replaced by a variable setring SNR; poly f = imap(SNB, f); list result = sqfrNormMain(f); // squarefree norm of f setring SNB; list result = imap(SNR, result); kill SNR; return(result); } example {"EXAMPLE:"; echo = 2; ring R = (0,a), x, lp; minpoly = a2+1; poly f = x4 - 2*x + 1; sqfrNorm(f); } proc sqfrNormMain(poly f) "USAGE: sqfrNorm(f); where f is a polynomial PURPOSE: compute the norm of the squarefree polynomial f in Q(a)[x]. RETURN: list with 3 entries @format _[1] = squarefree norm of g (poly) _[2] = g (= f(x - s*a)) (poly) _[3] = s (int) @end format ASSUME: f must be squarefree, basering = Q[x,a] and ideal mpoly is equal to 'minpoly', this represents the ring Q(a)[x] together with 'minpoly'. NOTE: the norm is an element of Q[x] EXAMPLE: example SqfrNorm; shows an example " { def SNRMB = basering; int s = 0; intvec wt = 1,0; ideal mapId; // list result; poly g, N, N1, h; string ringSTR; mapId[1] = var(1) - var(2); // linear transformation mapId[2] = var(2); map Fs = SNRMB, mapId; N = resultant(f, mpoly[1], var(2)); // norm of f N1 = diff(N, var(1)); g = f; ringSTR = "ring SNRM1 = 0, " + string(var(1)) + ", dp;"; // univariate ring execute(ringSTR); poly N, N1, h; // N, N1 do not contain 'a', use built-in gcd h = gcd(imap(SNRMB, N), imap(SNRMB, N1)); setring(SNRMB); h = imap(SNRM1, h); while(deg(h, wt) != 0) { // while norm is not squarefree s = s + 1; g = reduce(Fs(g), mpoly); N = reduce(resultant(g, mpoly[1], var(2)), mpoly); // norm of g N1 = reduce(diff(N, var(1)), mpoly); setring(SNRM1); h = gcd(imap(SNRMB, N), imap(SNRMB, N1)); setring(SNRMB); h = imap(SNRM1, h); } return(list(N, g, s)); } /////////////////////////////////////////////////////////////////////////////// proc factorMain(poly f) "USAGE: factorMain(f); where f is a polynomial PURPOSE: compute the factorization of the squarefree polynomial f over Q(a)[t], minpoly = p(a). RETURN: list with 2 entries @format _[1] = factors, first is a constant _[2] = multiplicities (not yet implemented) @end format ASSUME: basering = Q[x,a], representing Q(a)[x]. An ideal mpoly must be defined, representing the minimal polynomial (it might be 0!). NOTE: outdated, use factorize instead EXAMPLE: example Factor; shows an example " { // extend this by a squarefree factorization !! // multiplicities are not valid !! int i, s; list normList, factorList, quo_rem; poly f1, h, h1, H, g, leadCoef, invCoeff; ideal fac1, fac2; map F; // if no minimal polynomial is defined then use 'factorize' // FactorOverQ is wrapped around 'factorize' if(mpoly[1] == 0) { // print(" factorize : deg = " + string(deg(f, intvec(1,0)))); factorList = factorize(f); // FactorOverQ(f); return(factorList); } // if mpoly != 0 and f does not contain the algebraic number, a root of // f might be contained in Q(a). Hence one must not use 'factorize'. fac1[1] = 1; fac2[1] = 1; normList = sqfrNormMain(f); // print(" factorize : deg = " + string(deg(normList[1], intvec(1,0)))); factorList = factorize(normList[1]); // factor squarefree norm of f over Q[x] g = normList[2]; s = normList[3]; F[1] = var(1) + s*var(2); // inverse transformation F[2] = var(2); fac1[1] = factorList[1][1]; fac2[1] = factorList[2][1]; for(i = 2; i <= size(factorList[1]); i = i + 1) { H = factorList[1][i]; h = egcdMain(H, g); quo_rem = quotientMain(g, h); g = quo_rem[1]; fac1[i] = SimplifyPoly(F(h)); fac2[i] = 1; // to be changed later } return(list(fac1, fac2)); } /////////////////////////////////////////////////////////////////////////////// proc zeroSetMain(ideal I, int primDecQ) "USAGE: zeroSetMain(ideal I, int opt); ideal I, int opt PURPOSE: compute the zero-set of the zero-dim. ideal I, in a simple extension of the ground field. RETURN: list - 'f' is the polynomial f in Q(a) (a' being substituted by newA) _[1] = zero-set (list), is the list of the zero-set of the ideal I, each entry is an ideal. _[2] = 'newA'; if the ground field is Q(a') and the extension field is Q(a), then 'newA' is the representation of a' in Q(a). If the basering contains a parameter 'a' and the minpoly remains unchanged then 'newA' = 'a'. If the basering does not contain a parameter then 'newA' = 'a' (default). _[3] = 'mpoly' (ideal), the minimal polynomial of the simple extension of the ground field. ASSUME: basering = K[x_1,x_2,...,x_n] where K = Q or a simple extension of Q given by a minpoly; dim(I) = 0. NOTE: opt = 0 no primary decomposition opt > 0 use a primary decomposition EXAMPLE: example zeroSetMain; shows an example " { // main work is done in zeroSetMainWork, here the zero-set of each ideal from the // primary decompostion is coputed by menas of zeroSetMainWork, and then the // minpoly and the parameter representing the algebraic extension are // transformed according to 'newA', i.e., only bookeeping is done. def altring=basering; int i, j, n, noMP, dbPrt; intvec w; list currentSol, result, idealList, primDecList, zeroSet; ideal J; map Fa; poly newA, oldMinPoly; dbPrt = printlevel-voice+2; dbprint(dbPrt, "zeroSet of " + string(I) + ", minpoly = " + string(minpoly)); n = nvars(basering) - 1; for(i = 1; i <= n; i++) { w[i] = 1;} w[n + 1] = 0; if(primDecQ == 0) { return(zeroSetMainWork(I, w, 0)); } newA = var(n + 1); if(mpoly[1] == 0) { noMP = 1;} else {noMP = 0;} primDecList = primdecGTZ(I); // primary decomposition dbprint(dbPrt, "primary decomposition consists of " + string(size(primDecList)) + " primary ideals "); // idealList = PDSort(idealList); // high degrees first for(i = 1; i <= size(primDecList); i = i + 1) { idealList[i] = primDecList[i][2]; // use prime component dbprint(dbPrt, string(i) + " " + string(idealList[i])); } // compute the zero-set of each primary ideal and join them. // If necessary, change the ground field and transform the zero-set dbprint(dbPrt, " find the zero-set of each primary ideal, form the union and keep track of the minimal polynomials "); for(i = 1; i <= size(idealList); i = i + 1) { J = idealList[i]; idealList[i] = 0; oldMinPoly = mpoly[1]; dbprint(dbPrt, " ideal#" + string(i) + " of " + string(size(idealList)) + " = " + string(J)); currentSol = zeroSetMainWork(J, w, 0); if(oldMinPoly != currentSol[3]) { // change minpoly and transform solutions dbprint(dbPrt, " change minpoly to " + string(currentSol[3][1])); dbprint(dbPrt, " new representation of algebraic number = " + string(currentSol[2])); if(!noMP) { // transform the algebraic number a Fa = basering, maxideal(1); Fa[n + 1] = currentSol[2]; newA = SimplifyPoly(Fa(newA)); // new representation of a if(size(zeroSet) > 0) {zeroSet = SimplifyZeroset(Fa(zeroSet)); } if(i < size(idealList)) { idealList = SimplifyZeroset(Fa(idealList)); } } else { noMP = 0;} } zeroSet = zeroSet + currentSol[1]; // add new elements } return(list(zeroSet, newA, mpoly)); } /////////////////////////////////////////////////////////////////////////////// proc zeroSetMainWork(ideal id, intvec wt, int sVars) "USAGE: zeroSetMainWork(I, wt, sVars); PURPOSE: compute the zero-set of the zero-dim. ideal I, in a finite extension of the ground field (without multiplicities). RETURN: list, all entries are polynomials _[1] = zeros, each entry is an ideal _[2] = newA; if the ground field is Q(a') this is the rep. of a' w.r.t. a _[3] = minpoly of the algebraic extension of the ground field (ideal) _[4] = name of algebraic number (default = 'a') ASSUME: basering = Q[x_1,x_2,...,x_n,a] ideal mpoly must be defined, it might be 0! NOTE: might change 'mpoly' !! EXAMPLE: example IdealSolve; shows an example " { def altring=basering; int i, j, k, nrSols, n, noMP; ideal I, generators, gens, solid, partsolid; list linSol, linearSolution, nLinSol, nonlinSolutions, partSol, sol, solutions, result; list linIndex, nlinIndex, index; map Fa, Fsubs; poly oldMinPoly, newA; if(mpoly[1] == 0) { noMP = 1;} else { noMP = 0;} n = nvars(basering) - 1; newA = var(n + 1); I = std(id); // find linear solutions of univariate generators linSol = LinearZeroSetMain(I, wt); generators = linSol[3]; // they are a standardbasis linIndex = linSol[2]; linearSolution = linSol[1]; if(size(linIndex) + sVars == n) { // all variables solved solid = SubsMapIdeal(linearSolution, linIndex, 0); result[1] = list(solid); result[2] = var(n + 1); result[3] = mpoly; return(result); } // find roots of the nonlinear univariate polynomials of generators // if necessary, transform linear solutions w.r.t. newA oldMinPoly = mpoly[1]; nLinSol = NonLinearZeroSetMain(generators, wt); // find solutions of univariate generators nonlinSolutions = nLinSol[1]; // store solutions nlinIndex = nLinSol[4]; // and index of solved variables generators = nLinSol[5]; // new generators // change minpoly if necessary and transform the ideal and the partial solutions if(oldMinPoly != nLinSol[3]) { newA = nLinSol[2]; if(!noMP && size(linearSolution) > 0) { // transform the algebraic number a Fa = basering, maxideal(1); Fa[n + 1] = newA; linearSolution = SimplifyData(Fa(linearSolution)); // ... } } // check if all variables are solved. if(size(linIndex) + size(nlinIndex) == n - sVars) { solutions = MergeSolutions(linearSolution, linIndex, nonlinSolutions, nlinIndex, list(), n); } else { // some variables are not solved. // substitute each partial solution in generators and find the // zero set of the resulting ideal by recursive application // of zeroSetMainWork ! index = linIndex + nlinIndex; nrSols = 0; for(i = 1; i <= size(nonlinSolutions); i = i + 1) { sol = linearSolution + nonlinSolutions[i]; solid = SubsMapIdeal(sol, index, 1); Fsubs = basering, solid; gens = std(SimplifyData(Fsubs(generators))); // substitute partial solution oldMinPoly = mpoly[1]; partSol = zeroSetMainWork(gens, wt, size(index) + sVars); if(oldMinPoly != partSol[3]) { // minpoly has changed Fa = basering, maxideal(1); Fa[n + 1] = partSol[2]; // a -> p(a), representation of a w.r.t. new minpoly newA = reduce(Fa(newA), mpoly); generators = std(SimplifyData(Fa(generators))); if(size(linearSolution) > 0) { linearSolution = SimplifyData(Fa(linearSolution));} if(size(nonlinSolutions) > 0) { nonlinSolutions = SimplifyZeroset(Fa(nonlinSolutions)); } sol = linearSolution + nonlinSolutions[i]; } for(j = 1; j <= size(partSol[1]); j++) { // for all partial solutions partsolid = partSol[1][j]; for(k = 1; k <= size(index); k++) { partsolid[index[k]] = sol[k]; } nrSols++; solutions[nrSols] = partsolid; } } } // end else return(list(solutions, newA, mpoly)); } /////////////////////////////////////////////////////////////////////////////// proc LinearZeroSetMain(ideal I, intvec wt) "USAGE: LinearZeroSetMain(I, wt) PURPOSE: solve the univariate linear polys in I ASSUME: basering = Q[x_1,...,x_n,a] RETURN: list _[1] = partial solution of I _[2] = index of solved vars _[3] = new generators (standardbasis) " { def altring=basering; int i, ok, n, found, nrSols; ideal generators, newGens; list result, index, totalIndex, vars, sol, temp; map F; poly f; result[1] = index; // sol[1] should be the empty list n = nvars(basering) - 1; generators = I; // might be wrong, use index ! ok = 1; nrSols = 0; while(ok) { found = 0; for(i = 1; i <= size(generators); i = i + 1) { f = generators[i]; vars = Variables(f, n); if(size(vars) == 1 && deg(f, wt) == 1) { // univariate,linear nrSols++; found++; index[nrSols] = vars[1]; sol[nrSols] = var(vars[1]) - MultPolys(invertNumberMain(LeadTerm(f, vars[1])[3]), f); } } if(found > 0) { F = basering, SubsMapIdeal(sol, index, 1); newGens = std(SimplifyData(F(generators))); // substitute, simplify alg. number if(size(newGens) == 0) {ok = 0;} generators = newGens; } else { ok = 0; } } if(nrSols > 0) { result[1] = sol;} result[2] = index; result[3] = generators; return(result); } /////////////////////////////////////////////////////////////////////////////// proc NonLinearZeroSetMain(ideal I, intvec wt) "USAGE: NonLinearZeroSetMain(I, wt); PURPOSE: solves the (nonlinear) univariate polynomials in I of the ground field (without multiplicities). RETURN: list, all entries are polynomials _[1] = list of solutions _[2] = newA _[3] = minpoly _[4] - index of solved variables _[5] = new representation of I ASSUME: basering = Q[x_1,x_2,...,x_n,a], ideal 'mpoly' must be defined, it might be 0 ! NOTE: might change 'mpoly' !! " { int i, nrSols, ok, n; ideal generators; list result, sols, index, vars, partSol; map F; poly f, newA; string ringSTR; def NLZR = basering; export(NLZR); n = nvars(basering) - 1; generators = I; newA = var(n + 1); result[2] = newA; // default nrSols = 0; ok = 1; i = 1; while(ok) { // test if the i-th generator of I is univariate f = generators[i]; vars = Variables(f, n); if(size(vars) == 1) { generators[i] = 0; generators = simplify(generators, 2); // remove 0 nrSols++; index[nrSols] = vars[1]; // store index of solved variable // create univariate ring ringSTR = "ring RIS1 = 0, (" + string(var(vars[1])) + ", " + string(var(n+1)) + "), lp;"; execute(ringSTR); ideal mpoly = std(imap(NLZR, mpoly)); list roots; poly f = imap(NLZR, f); export(RIS1); export(mpoly); roots = rootsMain(f); // get "old" basering with new minpoly setring(NLZR); partSol = imap(RIS1, roots); kill RIS1; if(mpoly[1] != partSol[3]) { // change minpoly mpoly = std(partSol[3]); F = NLZR, maxideal(1); F[n + 1] = partSol[2]; if(size(sols) > 0) {sols = SimplifyZeroset(F(sols)); } newA = reduce(F(newA), mpoly); // normal form result[2] = newA; generators = SimplifyData(F(generators)); // does not remove 0's } sols = ExtendSolutions(sols, partSol[1]); } // end univariate else { i = i + 1; } if(i > size(generators)) { ok = 0;} } result[1] = sols; result[3] = mpoly; result[4] = index; result[5] = std(generators); kill NLZR; return(result); } /////////////////////////////////////////////////////////////////////////////// static proc ExtendSolutions(list solutions, list newSolutions) "USAGE: ExtendSolutions(sols, newSols); list sols, newSols; PURPOSE: extend the entries of 'sols' by the entries of 'newSols', each entry of 'newSols' is a number. RETURN: list ASSUME: basering = Q[x_1,...,x_n,a], ideal 'mpoly' must be defined, it might be 0 ! NOTE: used by 'NonLinearZeroSetMain' " { int i, j, k, n, nrSols; list newSols, temp; nrSols = size(solutions); if(nrSols > 0) {n = size(solutions[1]);} else { n = 0; nrSols = 1; } k = 0; for(i = 1; i <= nrSols; i++) { for(j = 1; j <= size(newSolutions); j++) { k++; if(n == 0) { temp[1] = newSolutions[j];} else { temp = solutions[i]; temp[n + 1] = newSolutions[j]; } newSols[k] = temp; } } return(newSols); } /////////////////////////////////////////////////////////////////////////////// static proc MergeSolutions(list sol1, list index1, list sol2, list index2) "USAGE: MergeSolutions(sol1, index1, sol2, index2); all parameters are lists RETURN: list PURPOSE: create a list of solutions of size n, each entry of 'sol2' must have size n. 'sol1' is one partial solution (from 'LinearZeroSetMain') 'sol2' is a list of partial solutions (from 'NonLinearZeroSetMain') ASSUME: 'sol2' is not empty NOTE: used by 'zeroSetMainWork' { int i, j, k, m; ideal sol; list newSols; m = 0; for(i = 1; i <= size(sol2); i++) { m++; newSols[m] = SubsMapIdeal(sol1 + sol2[i], index1 + index2, 0); } return(newSols); } /////////////////////////////////////////////////////////////////////////////// static proc SubsMapIdeal(list sol, list index, int opt) "USAGE: SubsMapIdeal(sol,index,opt); list sol, index; int opt; PURPOSE: built an ideal I as follows. if i is contained in 'index' then set I[i] = sol[i] if i is not contained in 'index' then - opt = 0: set I[i] = 0 - opt = 1: set I[i] = var(i) if opt = 1 and n = nvars(basering) then set I[n] = var(n). RETURN: ideal ASSUME: size(sol) = size(index) <= nvars(basering) " { int k = 0; ideal I; for(int i = 1; i <= nvars(basering) - 1; i = i + 1) { // built subs. map if(containedQ(index, i)) { k++; I[index[k]] = sol[k]; } else { if(opt) { I[i] = var(i); } else { I[i] = 0; } } } if(opt) {I[nvars(basering)] = var(nvars(basering));} return(I); } /////////////////////////////////////////////////////////////////////////////// proc SimplifyZeroset(def data) "USAGE: SimplifyZeroset(data); list data PURPOSE: reduce the entries of the elements of 'data' w.r.t. the ideal 'mpoly' 'data' is a list of ideals/lists. RETURN: list ASSUME: basering = Q[x_1,...,x_n,a], order = lp 'data' is a list of ideals ideal 'mpoly' must be defined, it might be 0 ! " { int i; list result; for(i = 1; i <= size(data); i++) { result[i] = SimplifyData(data[i]); } return(result); } /////////////////////////////////////////////////////////////////////////////// proc Variables(poly f, int n) "USAGE: Variables(f,n); poly f; int n; PURPOSE: list of variables among var(1),...,var(n) which occur in f. RETURN: list ASSUME: n <= nvars(basering) " { int i, nrV; list index; nrV = 0; for(i = 1; i <= n; i = i + 1) { if(diff(f, var(i)) != 0) { nrV++; index[nrV] = i; } } return(index); } /////////////////////////////////////////////////////////////////////////////// proc containedQ(def data,def f, list #) "USAGE: containedQ(data, f [, opt]); data=list; f=any type; opt=integer PURPOSE: test if f is an element of data. RETURN: int 0 if f not contained in data 1 if f contained in data OPTIONS: opt = 0 : use '==' for comparing f with elements from data@* opt = 1 : use @code{sameQ} for comparing f with elements from data " { int opt, i, found; if(size(#) > 0) { opt = #[1];} else { opt = 0; } i = 1; found = 0; while((!found) && (i <= size(data))) { if(opt == 0) { if(f == data[i]) { found = 1;} else {i = i + 1;} } else { if(sameQ(f, data[i])) { found = 1;} else {i = i + 1;} } } return(found); } ////////////////////////////////////////////////////////////////////////////// proc sameQ(def a,def b) "USAGE: sameQ(a, b); a,b=list/intvec PURPOSE: test a == b elementwise, i.e., a[i] = b[i]. RETURN: int 0 if a != b 1 if a == b " { if(typeof(a) == typeof(b)) { if(typeof(a) == "list" || typeof(a) == "intvec") { if(size(a) == size(b)) { int i = 1; int ok = 1; while(ok && (i <= size(a))) { if(a[i] == b[i]) { i = i + 1;} else {ok = 0;} } return(ok); } else { return(0); } } else { return(a == b);} } else { return(0);} } /////////////////////////////////////////////////////////////////////////////// static proc SimplifyPoly(poly f) "USAGE: SimplifyPoly(f); poly f PURPOSE: reduces the coefficients of f w.r.t. the ideal 'moly' if they contain the algebraic number 'a'. RETURN: poly ASSUME: basering = Q[x_1,...,x_n,a] ideal mpoly must be defined, it might be 0 ! NOTE: outdated, use reduce instead " { matrix coMx; poly f1, vp; vp = 1; for(int i = 1; i < nvars(basering); i++) { vp = vp * var(i);} coMx = coef(f, vp); f1 = 0; for(i = 1; i <= ncols(coMx); i++) { f1 = f1 + coMx[1, i] * reduce(coMx[2, i], mpoly); } return(f1); } /////////////////////////////////////////////////////////////////////////////// static proc SimplifyData(def data) "USAGE: SimplifyData(data); ideal/list data; PURPOSE: reduces the entries of 'data' w.r.t. the ideal 'mpoly' if they contain the algebraic number 'a' RETURN: ideal/list ASSUME: basering = Q[x_1,...,x_n,a] ideal 'mpoly' must be defined, it might be 0 ! " { def altring=basering; int n; poly f; if(typeof(data) == "ideal") { n = ncols(data); } else { n = size(data);} for(int i = 1; i <= n; i++) { f = data[i]; data[i] = SimplifyPoly(f); } return(data); } /////////////////////////////////////////////////////////////////////////////// static proc TransferRing(def R) "USAGE: TransferRing(R); PURPOSE: creates a new ring containing the same variables as R, but without parameters. If R contains a parameter then this parameter is added as the last variable and 'minpoly' is represented by the ideal 'mpoly' If the basering does not contain a parameter then 'a' is added and 'mpoly' = 0. RETURN: ring ASSUME: R = K[x_1,...,x_n] where K = Q or K = Q(a). NOTE: Creates the ring needed for all prodecures with name 'proc-name'Main " { def altring=basering; string ringSTR, parName, minPoly; setring(R); if(npars(basering) == 0) { parName = "a"; minPoly = "0"; } else { parName = parstr(basering); minPoly = string(minpoly); } ringSTR = "ring TR = 0, (" + varstr(basering) + "," + parName + "), lp;"; execute(ringSTR); execute("ideal mpoly = std(" + minPoly + ");"); export(mpoly); setring altring; return(TR); } /////////////////////////////////////////////////////////////////////////////// static proc NewBaseRing() "USAGE: NewBaseRing(); PURPOSE: creates a new ring, the last variable is added as a parameter. minpoly is set to mpoly[1]. RETURN: ring ASSUME: basering = Q[x_1,...,x_n, a], 'mpoly' must be defined " { int n = nvars(basering); int MP; string ringSTR, parName, varString; def BR = basering; if(mpoly[1] != 0) { parName = "(0, " + string(var(n)) + ")"; MP = 1; } else { parName = "0"; MP = 0; } for(int i = 1; i < n - 1; i++) { varString = varString + string(var(i)) + ","; } varString = varString + string(var(n-1)); ringSTR = "ring TR = " + parName + ", (" + varString + "), lp;"; execute(ringSTR); if(MP) { minpoly = number(imap(BR, mpoly)[1]); } setring BR; return(TR); } /////////////////////////////////////////////////////////////////////////////// /* Examples: // order = 20; ring S1 = 0, (s(1..3)), lp; ideal I = s(2)*s(3), s(1)^2*s(2)+s(1)^2*s(3)-1, s(1)^2*s(3)^2-s(3), s(2)^4-s(3)^4+s(1)^2, s(1)^4+s(2)^3-s(3)^3, s(3)^5-s(1)^2*s(3); ideal mpoly = std(0); // order = 10 ring S2 = 0, (s(1..5)), lp; ideal I = s(2)+s(3)-s(5), s(4)^2-s(5), s(1)*s(5)+s(3)*s(4)-s(4)*s(5), s(1)*s(4)+s(3)-s(5), s(3)^2-2*s(3)*s(5), s(1)*s(3)-s(1)*s(5)+s(4)*s(5), s(1)^2+s(4)^2-2*s(5), -s(1)+s(5)^3, s(3)*s(5)^2+s(4)-s(5)^3, s(1)*s(5)^2-1; ideal mpoly = std(0); //order = 126 ring S3 = 0, (s(1..5)), lp; ideal I = s(3)*s(4), s(2)*s(4), s(1)*s(3), s(1)*s(2), s(3)^3+s(4)^3-1, s(2)^3+s(4)^3-1, s(1)^3-s(4)^3, s(4)^4-s(4), s(1)*s(4)^3-s(1), s(5)^7-1; ideal mpoly = std(0); // order = 192 ring S4 = 0, (s(1..4)), lp; ideal I = s(2)*s(3)^2*s(4)+s(1)*s(3)*s(4)^2, s(2)^2*s(3)*s(4)+s(1)*s(2)*s(4)^2, s(1)*s(3)^3+s(2)*s(4)^3, s(1)*s(2)*s(3)^2+s(1)^2*s(3)*s(4), s(1)^2*s(3)^2-s(2)^2*s(4)^2, s(1)*s(2)^2*s(3)+s(1)^2*s(2)*s(4), s(1)^3*s(3)+s(2)^3*s(4), s(2)^4-s(3)^4, s(1)*s(2)^3+s(3)*s(4)^3, s(1)^2*s(2)^2-s(3)^2*s(4)^2, s(1)^3*s(2)+s(3)^3*s(4), s(1)^4-s(4)^4, s(3)^5*s(4)-s(3)*s(4)^5, s(3)^8+14*s(3)^4*s(4)^4+s(4)^8-1, 15*s(2)*s(3)*s(4)^7-s(1)*s(4)^8+s(1), 15*s(3)^4*s(4)^5+s(4)^9-s(4), 16*s(3)*s(4)^9-s(3)*s(4), 16*s(2)*s(4)^9-s(2)*s(4), 16*s(1)*s(3)*s(4)^8-s(1)*s(3), 16*s(1)*s(2)*s(4)^8-s(1)*s(2), 16*s(1)*s(4)^10-15*s(2)*s(3)*s(4)-16*s(1)*s(4)^2, 16*s(1)^2*s(4)^9-15*s(1)*s(2)*s(3)-16*s(1)^2*s(4), 16*s(4)^13+15*s(3)^4*s(4)-16*s(4)^5; ideal mpoly = std(0); ring R = (0,a), (x,y,z), lp; minpoly = a2 + 1; ideal I1 = x2 - 1/2, a*z - 1, y - 2; ideal I2 = x3 - 1/2, a*z2 - 3, y - 2*a; */ singular-4.0.3+ds/Singular/Makefile.am000066400000000000000000000166401266270727000176040ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I../m4 GIT_VERSION := $(shell $(top_srcdir)/git-version-gen $(top_srcdir)/.tarball-git-version) AM_CPPFLAGS = -I${top_srcdir} -I${top_builddir} -I${top_srcdir}/kernel -I${top_builddir}/kernel -I${top_srcdir}/libpolys -I${top_builddir}/libpolys $(FACTORY_INCLUDES) $(GMP_CFLAGS) $(NTL_CFLAGS) $(FLINT_CFLAGS) -DGIT_VERSION='"$(GIT_VERSION)"' all-local: feOpt.inc feOptTS.inc feOptES.inc iparith.inc all.lib gftables MOD ${abs_builddir}/LIB Singular$(EXEEXT) ESingular$(EXEEXT) TSingular$(EXEEXT) SUBDIRS = dyn_modules ########################### Possible builtin modules... ######################### BUILTIN_FLAGS = ${BUILTIN_LIBS} ########################### libSingular* ######################### libSingular_LTLIBRARIES = libSingular.la libSingulardir = $(libdir) libSingular_la_CPPFLAGS = ${AM_CPPFLAGS} -DLIBSINGULAR ${PTHREAD_CFLAGS} SOURCES = \ links/asciiLink.cc\ attrib.cc\ blackbox.cc\ calcSVD.cc\ cntrlc.cc\ countedref.cc\ denom_list.cc\ eigenval_ip.cc\ extra.cc\ feOpt.cc\ fehelp.cc\ fevoices.cc\ fglm.cc\ gms.cc\ grammar.cc\ iparith.cc\ ipassign.cc\ ipconv.cc\ ipid.cc\ iplib.cc\ ipprint.cc\ ipshell.cc\ libparse.cc\ linearAlgebra_ip.cc\ lists.cc\ maps_ip.cc\ misc_ip.cc\ mod_lib.cc\ links/ndbm.cc\ newstruct.cc\ number2.cc\ pcv.cc\ links/pipeLink.cc\ scanner.cc\ sdb.cc\ links/silink.cc\ links/sing_dbm.cc\ links/slInit_Static.cc\ links/ssiLink.cc\ links/semaphore.c\ subexpr.cc\ pyobject_setup.cc\ walk.cc\ walk_ip.cc\ wrapper.cc\ mmstd.c claptmpl.cc\ febase.cc # links/slInit_Dynamic.cc libSingular_la_SOURCES = $(SOURCES) SingularHEADERS = \ attrib.h \ blackbox.h \ cntrlc.h \ countedref.h \ links/dbm_sl.h \ distrib.h \ eigenval_ip.h \ feOpt.h feOptTab.h fehelp.h \ fglm.h \ gms.h \ grammar.h \ idrec.h \ ipconv.h \ ipid.h \ ipprint.h \ ipshell.h \ libparse.h \ libsingular.h \ linearAlgebra_ip.h\ lists.h \ locals.h \ maps_ip.h \ misc_ip.h \ mmalloc.h \ mod_lib.h \ links/ndbm.h \ newstruct.h \ number2.h \ pcv.h \ links/pipeLink.h \ pyobject_setup.h \ run.h \ sdb.h \ links/silink.h \ links/sing_dbm.h \ links/slInit.h \ links/ssiLink.h \ links/simpleipc.h \ stype.h \ subexpr.h \ table.h \ tok.h \ walk.h \ fevoices.h # -DMAKE_DISTRIBUTION # plural_cmd.inc nodist_libSingular_la_SOURCES = feOpt.inc iparith.inc libSingular_la_LDFLAGS =${USEPPROCSDYNAMICLDFLAGS} ${USEPPROCSDYNAMICLD} -release ${PACKAGE_VERSION} ${PTHREAD_LDFLAGS} libSingular_la_LIBADD =${USEPPROCSDYNAMICLDFLAGS} ${USEPPROCSDYNAMICLD} ${BUILTIN_FLAGS} ${top_builddir}/kernel/libkernel.la ${PTHREAD_LIBS} libSingular_includedir = ${includedir}/singular/Singular nobase_libSingular_include_HEADERS = $(SingularHEADERS) ######################################################### # handle all the generated *.inc noinst_PROGRAMS = gentable1 feOptGen feOptES feOptTS gentable1_SOURCES = gentable.cc grammar.h tok.h table.h gentable1_CPPFLAGS = ${AM_CPPFLAGS} feOptGen_SOURCES = feOptGen.cc feOptGen.h feOptGen_CPPFLAGS = ${AM_CPPFLAGS} feOptES_SOURCES = feOptGen.cc feOptGen.h feOptES_CPPFLAGS = ${AM_CPPFLAGS} -DESINGULAR feOptTS_SOURCES = feOptGen.cc feOptGen.h feOptTS_CPPFLAGS = ${AM_CPPFLAGS} -DTSINGULAR ########################### Singular* ######################### EXTRA_PROGRAMS = libparse Singulard # the "optional_programs" variable should be defined in the configure # script, and listed in an AC_SUBST macro optional_Singular_programs = bin_PROGRAMS = Singular ESingular TSingular $(optional_Singular_programs) Singular_SOURCES = tesths.cc fegetopt.c fegetopt.h utils.cc utils.h Singular_LDADD = libSingular.la ${BUILTIN_FLAGS} Singular_LDFLAGS = -static ${AM_LDFLAGS} ${BUILTIN_FLAGS} Singulard_SOURCES = tesths.cc fegetopt.c fegetopt.h utils.cc utils.h Singulard_LDADD = libSingular.la ${BUILTIN_FLAGS} Singulard_LDFLAGS = -shared ${AM_LDFLAGS} ${BUILTIN_FLAGS} scriptdir = $(libexecdir)/singular/MOD dist_script_SCRIPTS = singularsurf #### ESingular ESingular_CPPFLAGS = ${AM_CPPFLAGS} -DESINGULAR -DPROTO # ESingular_LDFLAGS = -static ${AM_LDFLAGS} ESingular_LDADD = ${top_builddir}/libpolys/reporter/libreporter.la \ ${top_builddir}/libpolys/misc/libmisc.la ${top_builddir}/omalloc/libomalloc.la \ ${top_builddir}/resources/libresources.la ESingular_SOURCES = emacs.cc fegetopt.c fegetopt.h feOptES.inc feOpt.cc #### same for TSingular TSingular_CPPFLAGS = ${AM_CPPFLAGS} -DTSINGULAR -DPROTO # TSingular_LDFLAGS = -static ${AM_LDFLAGS} TSingular_LDADD = ${top_builddir}/libpolys/reporter/libreporter.la \ ${top_builddir}/libpolys/misc/libmisc.la ${top_builddir}/omalloc/libomalloc.la \ ${top_builddir}/resources/libresources.la TSingular_SOURCES = emacs.cc fegetopt.c fegetopt.h feOptTS.inc feOpt.cc # utils.cc utils.h #### libparse libparse_CPPFLAGS = ${AM_CPPFLAGS} -DSTANDALONE_PARSER libparse_SOURCES = libparse.cc fegetopt.c fegetopt.h utils.cc utils.h libparse_LDADD = ${top_builddir}/omalloc/libomalloc.la libparse_LDFLAGS = -static ${AM_LDFLAGS} ######################################################### # the Singular library (*.lib files) include ${srcdir}/singular-libs singularlibrarydir = ${datadir}/singular singularlibrary = $(SLIB0:%=LIB/%) $(SLIB1:%=LIB/%) $(PLIBS:%=LIB/%) $(SLIB2:%=LIB/%) nobase_dist_singularlibrary_DATA = LIB/tst.lib LIB/help.cnf ${singularlibrary} EXTRA_DIST = grammar.y libparse.ll make_alllib.sh LIB/all.lib.tmpl \ singular-libs LIB/help.cnf LIB/.singularrc LIB/COPYING \ links/slInit_Dynamic.cc ../doc/singular.idx dist_singularlibrary_DATA = ../doc/singular.idx singularalllibrarydir = ${datadir}/singular/LIB singularalllibrary = all.lib nobase_dist_singularalllibrary_DATA = all.lib all.lib: ${srcdir}/make_alllib.sh ${srcdir}/LIB/all.lib.tmpl ${singularlibrary} ${srcdir}/make_alllib.sh ${srcdir}/LIB/all.lib.tmpl ${SLIB0} ${PLIBS} ########################### TEST ######################### TESTS_ENVIRONMENT = SINGULARPATH='${top_builddir}/Singular/LIB:${top_srcdir}/Singular/LIB:${top_builddir}/libpolys/polys/.libs:${top_builddir}/factory/gftables' TESTS_ENVIRONMENT += SINGULAR_ROOT_DIR='${top_builddir}' TESTS=test check_PROGRAMS=$(TESTS) test_SOURCES = test.cc test_LDADD = libSingular.la ######################################################### # These files are built first BUILT_SOURCES = feOpt.inc feOptTS.inc feOptES.inc iparith.inc all.lib gftables MOD CLEANFILES = $(BUILT_SOURCES) $(EXTRA_PROGRAMS) clean-local: if [ "${abs_builddir}" != "${abs_srcdir}" ]; then \ if [ -L ${abs_builddir}/LIB ]; then unlink ${abs_builddir}/LIB; fi \ fi feOpt.inc: feOptGen$(EXEEXT) ${builddir}/feOptGen$(EXEEXT) feOptES.inc: feOptES$(EXEEXT) ${builddir}/feOptES$(EXEEXT) feOptTS.inc: feOptTS$(EXEEXT) ${builddir}/feOptTS$(EXEEXT) iparith.inc: gentable1$(EXEEXT) table.h ${builddir}/gentable1$(EXEEXT) # # fake rule to fix parallel make http://www.gnu.org/s/hello/manual/automake/Multiple-Outputs.html gftables: ${top_srcdir}/factory/gftables ln -snf ${top_srcdir}/factory/gftables ${builddir}/gftables ${abs_builddir}/LIB: ${srcdir}/LIB if [ "${abs_builddir}" != "${abs_srcdir}" ]; then \ ln -snf ${abs_srcdir}/LIB ${abs_builddir}/; \ fi MOD: if [ -d "${top_builddir}/libpolys/polys/.libs" ]; then \ ln -snf ${top_builddir}/libpolys/polys/.libs/ ${abs_builddir}/MOD; \ fi echoLIBS: @echo ${SLIB0} ${SLIB1} ${SLIB2} ${PLIBS} singular-4.0.3+ds/Singular/README000066400000000000000000000013441266270727000164230ustar00rootroot00000000000000 Singular version 4.0 University of Kaiserslautern Department of Mathematics Centre for Computer Algebra Authors: W.Decker, G.-M. Greuel, G. Pfister, H. Schoenemann (C) 1986-2014 All Rights Reserved README FILE FOR SINGULAR INTERPRETER ==================================== This directory contains the source files for the Singular interpreter and the following subdirectories: 'LIB' -- contains Singular libraries written in Singular's programming language If you receive this file as part of a complete Singular distribution, see also the files contained in the top directory of the full Singular distribution. GOOD LUCK and ENJOY! Your Singular team. singular-4.0.3+ds/Singular/attrib.cc000066400000000000000000000224571266270727000173470ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: attributes to leftv and idhdl */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static omBin sattr_bin = omGetSpecBin(sizeof(sattr)); void sattr::Print() { omCheckAddrSize(this,sizeof(sattr)); ::Print("attr:%s, type %s \n",name,Tok2Cmdname(atyp)); if (next!=NULL) next->Print(); } attr sattr::Copy() { assume (this!=NULL); omCheckAddrSize(this,sizeof(sattr)); attr n=(attr)omAlloc0Bin(sattr_bin); n->atyp=atyp; if (name!=NULL) n->name=omStrDup(name); n->data=CopyA(); if (next!=NULL) { n->next=next->Copy(); } return n; } // in subexr.cc: //void * sattr::CopyA() //{ // omCheckAddrSize(this,sizeof(sattr)); // return s_internalCopy(atyp,data); //} static void attr_free(attr h, const ring r=currRing) { if (h->data!=NULL) /*avoid assume failure */ { s_internalDelete(h->atyp,h->data,r); h->data=NULL; } } attr sattr::set(const char * s, void * d, int t) { attr h = get(s); attr result=this; if (h!=NULL) { attr_free(h); } else { h = (attr)omAlloc0Bin(sattr_bin); h->next = this; result=h; } h->name = s; h->data = d; h->atyp = t; #ifdef TEST //::Print("set attr >>%s<< of type %s\n",h->name, Tok2Cmdname(t)); #endif return result; } attr sattr::get(const char * s) { attr h = this; while (h!=NULL) { if (0 == strcmp(s,h->name)) { #ifdef TEST //::Print("get attr >>%s<< of type %s\n",h->name, Tok2Cmdname(h->atyp)); #endif return h; } h = h->next; } return NULL; } #if 0 void * atGet(idhdl root,const char * name) { attr temp = root->attribute->get(name); if (temp!=NULL) return temp->data; else return NULL; } void * atGet(leftv root,const char * name) { attr temp; attr a=*(root->Attribute()); temp = a->get(name); if (temp!=NULL) return temp->data; else return NULL; } #endif void * atGet(idhdl root,const char * name, int t, void *defaultReturnValue) { attr temp = root->attribute->get(name); if ((temp!=NULL) && (temp->atyp==t)) return temp->data; else return defaultReturnValue; } void * atGet(leftv root,const char * name, int t) { attr *a=(root->Attribute()); if (a!=NULL) { attr temp = (*a)->get(name); if ((temp!=NULL) && (temp->atyp==t)) return temp->data; } return NULL; } void atSet(idhdl root,const char * name,void * data,int typ) { if (root!=NULL) { if ((IDTYP(root)!=RING_CMD) && (IDTYP(root)!=QRING_CMD) && (!RingDependend(IDTYP(root)))&&(RingDependend(typ))) WerrorS("cannot set ring-dependend objects at this type"); else root->attribute=root->attribute->set(name,data,typ); } } void atSet(leftv root,const char * name,void * data,int typ) { if (root!=NULL) { attr *a=root->Attribute(); int rt=root->Typ(); if (a==NULL) WerrorS("cannot set attributes of this object"); else if ((rt!=RING_CMD) && (rt!=QRING_CMD) && (!RingDependend(rt))&&(RingDependend(typ))) WerrorS("cannot set ring-dependend objects at this type"); else { *a=(*a)->set(name,data,typ); } } } void sattr::kill(const ring r) { attr_free(this,r); omFree((ADDRESS)name); name=NULL; omFreeBin((ADDRESS)this, sattr_bin); } void sattr::killAll(const ring r) { attr temp = this,temp1; while (temp!=NULL) { temp1 = temp->next; omCheckAddr(temp); temp->kill(r); temp = temp1; } } void at_Kill(idhdl root,const char * name, const ring r) { attr temp = root->attribute->get(name); if (temp!=NULL) { attr N = temp->next; attr temp1 = root->attribute; if (temp1==temp) { root->attribute = N; } else { while (temp1->next!=temp) temp1 = temp1->next; temp1->next = N; } temp->kill(r); } } void at_KillAll(idhdl root, const ring r) { root->attribute->killAll(r); root->attribute = NULL; } void at_KillAll(leftv root, const ring r) { root->attribute->killAll(r); root->attribute = NULL; } BOOLEAN atATTRIB1(leftv res,leftv v) { int t; attr *aa=(v->Attribute()); if (aa==NULL) { WerrorS("this object cannot have attributes"); return TRUE; } attr a=*aa; BOOLEAN haveNoAttribute=TRUE; if (v->e==NULL) { if (hasFlag(v,FLAG_STD)) { PrintS("attr:isSB, type int\n"); haveNoAttribute=FALSE; } if (hasFlag(v,FLAG_QRING)) { PrintS("attr:qringNF, type int\n"); haveNoAttribute=FALSE; } if (((t=v->Typ())==RING_CMD)||(t==QRING_CMD)) { PrintS("attr:global, type int\n"); haveNoAttribute=FALSE; } } else { leftv at=v->LData(); return atATTRIB1(res,at); } if (a!=NULL) a->Print(); else if(haveNoAttribute) PrintS("no attributes\n"); return FALSE; } BOOLEAN atATTRIB2(leftv res,leftv v,leftv b) { char *name=(char *)b->Data(); int t; leftv at=NULL; if (v->e!=NULL) at=v->LData(); if (strcmp(name,"isSB")==0) { res->rtyp=INT_CMD; res->data=(void *)(long)hasFlag(v,FLAG_STD); if (at!=NULL) res->data=(void *)(long)(hasFlag(v,FLAG_STD)||(hasFlag(at,FLAG_STD))); } else if ((strcmp(name,"rank")==0)&&(v->Typ()==MODUL_CMD)) { res->rtyp=INT_CMD; res->data=(void *)(((ideal)v->Data())->rank); } else if ((strcmp(name,"global")==0) &&(((t=v->Typ())==RING_CMD)||(t==QRING_CMD))) { res->rtyp=INT_CMD; res->data=(void *)(((ring)v->Data())->OrdSgn==1); } else if ((strcmp(name,"ring_cf")==0) &&(((t=v->Typ())==RING_CMD)||(t==QRING_CMD))) { res->rtyp=INT_CMD; res->data=(void *)(long)(rField_is_Ring((ring)v->Data())); } else if (strcmp(name,"qringNF")==0) { res->rtyp=INT_CMD; res->data=(void *)(long)hasFlag(v,FLAG_QRING); if (at!=NULL) res->data=(void *)(long)(hasFlag(v,FLAG_QRING)||(hasFlag(at,FLAG_QRING))); } #ifdef HAVE_SHIFTBBA else if ((strcmp(name,"isLPring")==0) &&(((t=v->Typ())==RING_CMD)||(t==QRING_CMD))) { res->rtyp=INT_CMD; res->data=(void *)(long)(((ring)v->Data())->isLPring); } #endif else { attr *aa=v->Attribute(); if (aa==NULL) { WerrorS("this object cannot have attributes"); return TRUE; } attr a=*aa; a=a->get(name); if (a!=NULL) { res->rtyp=a->atyp; res->data=a->CopyA(); } else { res->rtyp=STRING_CMD; res->data=omStrDup(""); } } return FALSE; } BOOLEAN atATTRIB3(leftv /*res*/,leftv v,leftv b,leftv c) { idhdl h=(idhdl)v->data; int t; if (v->e!=NULL) { v=v->LData(); if (v==NULL) return TRUE; h=NULL; } else if (v->rtyp!=IDHDL) h=NULL; char *name=(char *)b->Data(); if (strcmp(name,"isSB")==0) { if (c->Typ()!=INT_CMD) { WerrorS("attribute isSB must be int"); return TRUE; } if (((long)c->Data())!=0L) { if (h!=NULL) setFlag(h,FLAG_STD); setFlag(v,FLAG_STD); } else { if (h!=NULL) resetFlag(h,FLAG_STD); resetFlag(v,FLAG_STD); } } else if (strcmp(name,"qringNF")==0) { if (c->Typ()!=INT_CMD) { WerrorS("attribute qringNF must be int"); return TRUE; } if (((long)c->Data())!=0L) { if (h!=NULL) setFlag(h,FLAG_QRING); setFlag(v,FLAG_QRING); } else { if (h!=NULL) resetFlag(h,FLAG_QRING); resetFlag(v,FLAG_QRING); } } else if ((strcmp(name,"rank")==0)&&(v->Typ()==MODUL_CMD)) { if (c->Typ()!=INT_CMD) { WerrorS("attribute `rank` must be int"); return TRUE; } ideal I=(ideal)v->Data(); I->rank=si_max((int)I->rank,(int)((long)c->Data())); } else if ((strcmp(name,"global")==0) &&(((t=v->Typ())==RING_CMD)||(t==QRING_CMD))) { WerrorS("can not set attribute `global`"); return TRUE; } #ifdef HAVE_SHIFTBBA else if ((strcmp(name,"isLPring")==0) &&(((t=v->Typ())==RING_CMD)||(t==QRING_CMD))) { if (c->Typ()==INT_CMD) ((ring)v->Data())->isLPring=(int)(long)c->Data(); else { WerrorS("attribute `isLPring` must be int"); return TRUE; } } #endif else { int typ=c->Typ(); if (h!=NULL) atSet(h,omStrDup(name),c->CopyD(typ),typ/*c->T(yp()*/); else atSet(v,omStrDup(name),c->CopyD(typ),typ/*c->T(yp()*/); } return FALSE; } BOOLEAN atKILLATTR1(leftv /*res*/,leftv a) { idhdl h=NULL; if ((a->rtyp==IDHDL)&&(a->e==NULL)) { h=(idhdl)a->data; resetFlag((idhdl)a->data,FLAG_STD); } resetFlag(a,FLAG_STD); if (h->attribute!=NULL) { atKillAll(h); a->attribute=NULL; } else atKillAll(a); return FALSE; } BOOLEAN atKILLATTR2(leftv /*res*/,leftv a,leftv b) { if ((a->rtyp!=IDHDL)||(a->e!=NULL)) { WerrorS("object must have a name"); return TRUE; } char *name=(char *)b->Data(); if (strcmp(name,"isSB")==0) { resetFlag(a,FLAG_STD); resetFlag((idhdl)a->data,FLAG_STD); } else if (strcmp(name,"global")==0) { WerrorS("can not set attribut `global`"); return TRUE; } else { atKill((idhdl)a->data,name); } return FALSE; } singular-4.0.3+ds/Singular/attrib.h000066400000000000000000000031711266270727000172010ustar00rootroot00000000000000#ifndef ATTRIB_H #define ATTRIB_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: attributes to leftv and idhdl */ #include #include #include class sattr; typedef sattr * attr; class sattr: public omallocClass { public: inline void Init() { memset(this,0,sizeof(*this)); } const char * name; void * data; attr next; int atyp; /* the type of the attribut, describes the data field */ void Print(); attr Copy(); /* copy all arguments */ void * CopyA(); /* copy the data of this attribute */ attr set(const char * s, void * data, int t); attr get(const char * s); void kill(const ring r); void killAll(const ring r); }; //void * atGet(idhdl root,const char * name); //void * atGet(leftv root,const char * name); void * atGet(idhdl root,const char * name, int t, void *defaultReturnValue = NULL); void * atGet(leftv root,const char * name, int t); void atSet(idhdl root,const char * name,void * data,int typ); void atSet(leftv root,const char * name,void * data,int typ); void at_KillAll(idhdl root,const ring r); void at_KillAll(leftv root,const ring r); #define atKillAll(H) at_KillAll(H,currRing) void at_Kill(idhdl root,const char * name,const ring r); #define atKill(H,A) at_Kill(H,A,currRing) BOOLEAN atATTRIB1(leftv res,leftv a); BOOLEAN atATTRIB2(leftv res,leftv a,leftv b); BOOLEAN atATTRIB3(leftv res,leftv a,leftv b,leftv c); BOOLEAN atKILLATTR1(leftv res,leftv a); BOOLEAN atKILLATTR2(leftv res,leftv a,leftv b); #endif singular-4.0.3+ds/Singular/blackbox.cc000066400000000000000000000124711266270727000176420ustar00rootroot00000000000000 #include #include #include "tok.h" #include "subexpr.h" #include "ipshell.h" #include "blackbox.h" #define MAX_BB_TYPES 256 // #define BLACKBOX_DEVEL 1 static blackbox* blackboxTable[MAX_BB_TYPES]; static char * blackboxName[MAX_BB_TYPES]; static int blackboxTableCnt=0; #define BLACKBOX_OFFSET (MAX_TOK+1) blackbox* getBlackboxStuff(const int t) { if (t>MAX_TOK) /*MAX_TOK+1 is BLACKBOX_OFFSET*/ return (blackboxTable[t-BLACKBOX_OFFSET]); else return NULL; } void blackbox_default_destroy(blackbox */*b*/, void */*d*/) { WerrorS("missing blackbox_destroy"); } char *blackbox_default_String(blackbox */*b*/,void */*d*/) { WerrorS("missing blackbox_String"); return omStrDup(""); } void *blackbox_default_Copy(blackbox */*b*/,void */*d*/) { WerrorS("missing blackbox_Copy"); return NULL; } void blackbox_default_Print(blackbox *b,void *d) { char *s=b->blackbox_String(b,d); PrintS(s); omFree(s); } void *blackbox_default_Init(blackbox */*b*/) { return NULL; } BOOLEAN blackbox_default_serialize(blackbox */*b*/, void */*d*/, si_link /*f*/) { WerrorS("blackbox_serialize is not implemented"); return TRUE; } BOOLEAN blackbox_default_deserialize(blackbox **/*b*/, void **/*d*/, si_link /*f*/) { WerrorS("blackbox_deserialize is not implemented"); return TRUE; } BOOLEAN blackboxDefaultOp1(int op,leftv l, leftv r) { if (op==TYPEOF_CMD) { l->data=omStrDup(getBlackboxName(r->Typ())); l->rtyp=STRING_CMD; return FALSE; } else if (op==NAMEOF_CMD) { if (r->name==NULL) l->data=omStrDup(""); else l->data=omStrDup(r->name); l->rtyp=STRING_CMD; return FALSE; } return TRUE; } BOOLEAN blackboxDefaultOp2(int op,leftv /*l*/, leftv r1, leftv /*r2*/) { return TRUE; } BOOLEAN blackboxDefaultOp3(int op,leftv /*l*/, leftv r1,leftv /*r2*/, leftv /*r3*/) { return TRUE; } BOOLEAN blackboxDefaultOpM(int op,leftv res, leftv args) { if (op==LIST_CMD) { res->rtyp=LIST_CMD; return jjLIST_PL(res,args); } else if(op==STRING_CMD) { blackbox *b=getBlackboxStuff(args->Typ()); res->data=b->blackbox_String(b,args->Data()); res->rtyp=STRING_CMD; args=args->next; if(args!=NULL) { sleftv res2; int ret=iiExprArithM(&res2,args,op); if (ret) return TRUE; char *s2=(char*)omAlloc(strlen((char*)res->data)+strlen((char*)res2.data)+1); sprintf(s2,"%s%s",(char*)res->data,(char*)res2.data); omFree(res2.data); omFree(res->data); res->data=s2; } return FALSE; } return TRUE; } BOOLEAN blackbox_default_Check(blackbox *,leftv,leftv) { return FALSE; } int setBlackboxStuff(blackbox *bb, const char *n) { int where=-1; if (MAX_BB_TYPES<=blackboxTableCnt) { // second try, find empty slot from removed bb: for (int i=0;i %d)",n,i+BLACKBOX_OFFSET,where+BLACKBOX_OFFSET); } } blackboxTable[where]=bb; blackboxName[where]=omStrDup(n); #ifdef BLACKBOX_DEVEL Print("setBlackboxStuff: define bb:name=%s:rt=%d (table:cnt=%d)\n",blackboxName[where],where+BLACKBOX_OFFSET,where); #endif if (bb->blackbox_destroy==NULL) bb->blackbox_destroy=blackbox_default_destroy; if (bb->blackbox_String==NULL) bb->blackbox_String=blackbox_default_String; if (bb->blackbox_Print==NULL) bb->blackbox_Print=blackbox_default_Print; if (bb->blackbox_Init==NULL) bb->blackbox_Init=blackbox_default_Init; if (bb->blackbox_Copy==NULL) bb->blackbox_Copy=blackbox_default_Copy; if (bb->blackbox_Op1==NULL) bb->blackbox_Op1=blackboxDefaultOp1; if (bb->blackbox_Op2==NULL) bb->blackbox_Op2=blackboxDefaultOp2; if (bb->blackbox_Op3==NULL) bb->blackbox_Op3=blackboxDefaultOp3; if (bb->blackbox_OpM==NULL) bb->blackbox_OpM=blackboxDefaultOpM; if (bb->blackbox_CheckAssign==NULL) bb->blackbox_CheckAssign=blackbox_default_Check; if (bb->blackbox_serialize==NULL) bb->blackbox_serialize=blackbox_default_serialize; if (bb->blackbox_deserialize==NULL) bb->blackbox_deserialize=blackbox_default_deserialize; return where+BLACKBOX_OFFSET; } } void removeBlackboxStuff(const int rt) { omfree(blackboxTable[rt-BLACKBOX_OFFSET]); omfree(blackboxName[rt-BLACKBOX_OFFSET]); blackboxTable[rt-BLACKBOX_OFFSET]=NULL; blackboxName[rt-BLACKBOX_OFFSET]=NULL; } const char *getBlackboxName(const int t) { char *b=blackboxName[t-BLACKBOX_OFFSET]; if (b!=NULL) return b; else return ""; } int blackboxIsCmd(const char *n, int & tok) { for(int i=blackboxTableCnt-1;i>=0;i--) { if(strcmp(n,blackboxName[i])==0) { #ifdef BLACKBOX_DEVEL Print("blackboxIsCmd: found bb:%s:%d (table:%d)\n",n,i+BLACKBOX_OFFSET,i); #endif tok=i+BLACKBOX_OFFSET; return ROOT_DECL; } } tok=0; return 0; } void printBlackboxTypes() { for(int i=blackboxTableCnt-1;i>=0;i--) { if (blackboxName[i]!=NULL) Print("type %d: %s\n",i,blackboxName[i]); } } singular-4.0.3+ds/Singular/blackbox.h000066400000000000000000000062571266270727000175110ustar00rootroot00000000000000#ifndef BLACKBOX_H #define BLACKBOX_H #include #include #include #include #include void removeBlackboxStuff(const int rt); struct blackbox_struct; typedef struct blackbox_struct blackbox; struct blackbox_struct { /// destroy the object: b points to blackbox_struct, d to data void (*blackbox_destroy)(blackbox *b, void *d); /// convert the object to a string (which should be freed by omFree) char *(*blackbox_String)(blackbox *b,void *d); /// print the object: default: use string representation void (*blackbox_Print)(blackbox *b,void *d); /// construct the default object void *(*blackbox_Init)(blackbox *b); /// copy the object: b points to blackbox_struct, d to data void *(*blackbox_Copy)(blackbox *b,void *d); /// interpreter assign: l:=r BOOLEAN (*blackbox_Assign)(leftv l, leftv r); /// interpreter: unary operations op(r), r(), ... // convention for blackbox_Op1..blackbox_OpM: // return FALSE, if op was successfully performed // return TRUE (and an error message) for failure // return TRUE (and no error message) if not defined BOOLEAN (*blackbox_Op1)(int op,leftv l, leftv r); /// interpreter: binary operations: op(r1,r2), r1 op r2,... BOOLEAN (*blackbox_Op2)(int op,leftv l, leftv r1,leftv r2); /// interpreter: tertiary op: op(r1,r2,r3) BOOLEAN (*blackbox_Op3)(int op,leftv l, leftv r1,leftv r2, leftv r3); /// interpreter: operations with undefined number of operands BOOLEAN (*blackbox_OpM)(int op,leftv l, leftv r); /// is an assign of r to l (part of b) impossible? BOOLEAN (*blackbox_CheckAssign)(blackbox *b,leftv l, leftv r); /// serialize BOOLEAN (*blackbox_serialize)(blackbox *b,void *d, si_link f); /// deserialize BOOLEAN (*blackbox_deserialize)(blackbox **b,void **d, si_link f); /// additional type info void *data; /// addtinional gneral properties int properties; // bit 0:blackbox is only a wrapper for lists #define BB_LIKE_LIST(B) ((B)->properties &1) } ; /// default procedure blackboxDefaultOp1, to be called as "default:" branch BOOLEAN blackboxDefaultOp1(int op,leftv l, leftv r); /// default procedure blackboxDefaultOp2, to be called as "default:" branch BOOLEAN blackboxDefaultOp2(int op,leftv l, leftv r1, leftv r2); /// default procedure blackboxDefaultOp3, to be called as "default:" branch BOOLEAN blackboxDefaultOp3(int op,leftv l, leftv r1,leftv r2, leftv r3); /// default procedure blackboxDefaultOpM, to be called as "default:" branch BOOLEAN blackboxDefaultOpM(int op,leftv l, leftv r); /// default procedure blackbox_default_Print: print the string void blackbox_default_Print(blackbox *b,void *d); /// return the structure to the type given by t blackbox* getBlackboxStuff(const int t); /// return the name to the type given by t (r/o) const char * getBlackboxName(const int t); /// used by scanner: returns ROOT_DECL for known types /// (and the type number in @c tok) int blackboxIsCmd(const char *n, int & tok); /// define a new type int setBlackboxStuff(blackbox *bb,const char *name); /// list all defined type (for debugging) void printBlackboxTypes(); #endif singular-4.0.3+ds/Singular/calcSVD.cc000066400000000000000000000055431266270727000173360ustar00rootroot00000000000000#include #include #ifdef HAVE_SVD #include #include #include #include #include template class std::vector< amp::mpfr_record* >; poly p_svdInit(char *s) { poly p=pInit(); n_Read(s, &pGetCoeff(p), currRing->cf); return p; } /************************************************************************* Testing SVD decomposition subroutine *************************************************************************/ lists testsvd(matrix M) { const unsigned int Precision=300; int max_i=M->nrows; int max_j=M->ncols; ap::template_2d_array< amp::ampf > a; int m; int n; int maxmn; int i; int j; int gpass; int pass; bool waserrors; bool wsorted; bool wfailed; amp::ampf materr; amp::ampf orterr; amp::ampf othererr; amp::ampf threshold; amp::ampf failthreshold; amp::ampf failr; materr = 0; orterr = 0; othererr = 0; wsorted = true; wfailed = false; waserrors = false; maxmn = 50; threshold = 5*100*amp::ampf::getAlgoPascalEpsilon(); failthreshold = amp::ampf("5.0E-3"); a.setbounds(1, max_i, 1, max_j); // // fill matrix a entries from M // for(i=1; i<=max_i; i++) { for(j=1; j<=max_j; j++) { char *str=pString(MATELEM(M,i,j)); Print(" to svd:%d,%d=%s\n",i,j,str); a(i,j) = amp::ampf(str); } } //testsvdproblem(a, max_i, max_j, materr, orterr, othererr, wsorted, wfailed); ap::template_2d_array< amp::ampf > u; ap::template_2d_array< amp::ampf > vt; ap::template_1d_array< amp::ampf > w; svd::svddecomposition(a, max_i, max_j, 2, 2, 2, w, u, vt); matrix Mu,Mw,Mvt; Mu=mpNew(max_i,max_i); Mw=mpNew(max_i,max_j); Mvt=mpNew(max_j,max_j); for(i=1;i<=max_i;i++) { for(j=1;j<=max_i;j++) { MATELEM(Mu,i,j)=p_svdInit(u(i,j).toString()); // Print(" after svd:%d,%d=%s\n",i,j,u(i,j).toString()); } } for(i=1;i<=si_min(max_i,max_j);i++) { MATELEM(Mw,i,i)=p_svdInit(w(i).toString()); //Print(" after svd:%d,%d=%s\n",i,w(i).toString()); } for(i=1;i<=max_j;i++) { for(j=1;j<=max_j;j++) { MATELEM(Mvt,i,j)=p_svdInit(vt(i,j).toString()); //Print(" after svd:%d,%d=%s\n",i,j,vt(i,j).toString()); } } lists L=(lists)omAlloc(sizeof(slists)); L->Init(3); L->m[0].rtyp=MATRIX_CMD; L->m[1].rtyp=MATRIX_CMD; L->m[2].rtyp=MATRIX_CMD; L->m[0].data=(char*)Mu; L->m[1].data=(char*)Mw; L->m[2].data=(char*)Mvt; return L; } #endif singular-4.0.3+ds/Singular/claptmpl.cc000066400000000000000000000112701266270727000176650ustar00rootroot00000000000000// emacs edit mode for this file is -*- C++ -*- /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT - instantiation of all templates */ #include //#include //using namespace std; #define SINGULAR 1 #include #include #include // templates for fglm: template class List; template class ListItem; template class ListIterator; template class List; template class ListItem; template class ListIterator; // ---------------------------------------------------------------------------- // kmatrix.cc // begin of file // Stephan Endrass, endrass@mathematik.uni-mainz.de // 23.7.99 // ---------------------------------------------------------------------------- #ifdef HAVE_SPECTRUM #ifdef KMATRIX_PRINT #include #ifndef KMATRIX_IOSTREAM #include #endif #endif #include #include template class KMatrix; #ifdef KMATRIX_PRINT template OSTREAM & operator << ( OSTREAM&,const KMatrix& ); template static void print_rational( OSTREAM&,int,const Rational& ); #endif #endif /* HAVE_SPECTRUM */ // ---------------------------------------------------------------------------- // kmatrix.cc // end of file // ---------------------------------------------------------------------------- #ifdef HAVE_PLURAL #include // for CMultiplier etc classes template class CMultiplier; template class CMultiplier; template class CMultiplier; // #include // for CCacheHash etc classes // template class CCacheHash; // template class CCacheHash; #endif #include #ifdef HAVE_BOOST #include #include using std::vector; using boost::dynamic_bitset; template class dynamic_bitset<>; template class vector >; #elif defined(USE_STDVECBOOL) #include using std::vector; template class vector; template class vector >; #endif template int pos_helper(kStrategy strat, poly p, int len, intset setL, polyset set); template int pos_helper(kStrategy strat, poly p, wlen_type len, wlen_set setL, polyset set); #ifdef NORO_CACHE //template class std::map >; //#include template class std::vector; //template class std::priority_queue; //template class std::vector; //template class std::vector >; //template class std::vector* >; //template class std::vector* >; template class std::vector* >; //template SparseRow * noro_red_to_non_poly_t(poly p, int &len, NoroCache* cache,slimgb_alg* c); template SparseRow* noro_red_to_non_poly_t(poly p, int &len, NoroCache* cache,slimgb_alg* c); //template SparseRow* noro_red_to_non_poly_t(poly p, int &len, NoroCache* cache,slimgb_alg* c); //template void simplest_gauss_modp (tgb_uint16* a, int nrows,int ncols); template void simplest_gauss_modp (tgb_uint32* a, int nrows,int ncols); //template void simplest_gauss_modp (tgb_uint8* a, int nrows,int ncols); //template poly row_to_poly(tgb_uint8* row, poly* terms, int tn, ring r); template poly row_to_poly(tgb_uint32* row, poly* terms, int tn, ring r); //template poly row_to_poly(tgb_uint16* row, poly* terms, int tn, ring r); template void noro_step(poly*p,int &pn,slimgb_alg* c); template void noro_step(poly*p,int &pn,slimgb_alg* c); template void noro_step(poly*p,int &pn,slimgb_alg* c); //std::priority_queue // #endif /* next lines are templates used in new minor code */ #include #include #include template class std::list; template class std::list; template class std::list; template class std::list; /* template class std::_List_base >; template class std::_List_base >; template class std::_List_base >; template class std::_List_base >; */ template class Cache; template class Cache; singular-4.0.3+ds/Singular/cntrlc.cc000066400000000000000000000340041266270727000173360ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT - interupt handling */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* undef, if you don't want GDB to come up on error */ #define CALL_GDB #if defined(__OPTIMIZE__) && defined(CALL_GDB) #undef CALL_GDB #endif #if defined(unix) #include #include #ifdef TIME_WITH_SYS_TIME #include #ifdef HAVE_SYS_TIME_H #include #endif #else #ifdef HAVE_SYS_TIME_H #include #else #include #endif #endif #ifdef HAVE_SYS_TIMES_H #include #endif #define INTERACTIVE 0 #define STACK_TRACE 1 #ifdef CALL_GDB static void debug (int); static void debug_stop (char *const*args); #endif #ifndef __OPTIMIZE__ static void stack_trace_sigchld (int); static void stack_trace (char *const*args); #endif #endif si_link pipeLastLink=NULL; BOOLEAN singular_in_batchmode=FALSE; void sig_pipe_hdl(int /*sig*/) { if (pipeLastLink!=NULL) { slClose(pipeLastLink); pipeLastLink=NULL; WerrorS("pipe failed"); } } volatile BOOLEAN do_shutdown = FALSE; volatile int defer_shutdown = 0; void sig_term_hdl(int /*sig*/) { do_shutdown = TRUE; if (!defer_shutdown) { m2_end(1); } } /*---------------------------------------------------------------------* * File scope Variables (Variables share by several functions in * the same file ) * *---------------------------------------------------------------------*/ /* data */ jmp_buf si_start_jmpbuf; int siRandomStart; short si_restart=0; BOOLEAN siCntrlc = FALSE; typedef void (*si_hdl_typ)(int); /*0 implementation*/ /*---------------------------------------------------------------------* * Functions declarations * *---------------------------------------------------------------------*/ void sigint_handler(int /*sig*/); si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler); /*---------------------------------------------------------------------*/ /** * @brief meta function for binding a signal to an handler @param[in] sig Signal number @param[in] signal_handler Pointer to signal handler @return value of signal() **/ /*---------------------------------------------------------------------*/ si_hdl_typ si_set_signal ( int sig, si_hdl_typ signal_handler) { #if 0 si_hdl_typ retval=signal (sig, (si_hdl_typ)signal_handler); if (retval == SIG_ERR) { fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig); } si_siginterrupt(sig, 0); /*system calls will be restarted if interrupted by the specified * signal sig. This is the default behavior in Linux. */ #else struct sigaction new_action,old_action; memset(&new_action, 0, sizeof(struct sigaction)); /* Set up the structure to specify the new action. */ new_action.sa_handler = signal_handler; if (sig==SIGINT) sigemptyset (&new_action.sa_mask); else new_action.sa_flags = SA_RESTART; int r=si_sigaction (sig, &new_action, &old_action); si_hdl_typ retval=(si_hdl_typ)old_action.sa_handler; if (r == -1) { fprintf(stderr, "Unable to init signal %d ... exiting...\n", sig); retval=SIG_ERR; } #endif return retval; } /* si_set_signal */ /*---------------------------------------------------------------------*/ #if defined(__linux__) && defined(__i386) #if !defined(HAVE_SIGCONTEXT) && !defined(HAVE_ASM_SIGCONTEXT_H) // we need the following structure sigcontext_struct. // if configure finds asm/singcontext.h we assume // that this file contains the structure and is included // via signal.h struct sigcontext_struct { unsigned short gs, __gsh; unsigned short fs, __fsh; unsigned short es, __esh; unsigned short ds, __dsh; unsigned long edi; unsigned long esi; unsigned long ebp; unsigned long esp; unsigned long ebx; unsigned long edx; unsigned long ecx; unsigned long eax; unsigned long trapno; unsigned long err; unsigned long eip; unsigned short cs, __csh; unsigned long eflags; unsigned long esp_at_signal; unsigned short ss, __ssh; unsigned long i387; unsigned long oldmask; unsigned long cr2; }; #endif #define HAVE_SIGSTRUCT typedef struct sigcontext_struct sigcontext; #endif #if defined(__linux__) && defined(__amd64) #define HAVE_SIGSTRUCT #endif #if defined(HAVE_SIGSTRUCT) /*2---------------------------------------------------------------------*/ /** * @brief signal handler for run time errors, linux/i386, x86_64 version @param[in] sig @param[in] s **/ /*---------------------------------------------------------------------*/ void sigsegv_handler(int sig, sigcontext s) { fprintf(stderr,"Singular : signal %d (v: %d):\n",sig,SINGULAR_VERSION); if (sig!=SIGINT) { fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf); fprintf(stderr,"Segment fault/Bus error occurred at %lx because of %lx (r:%d)\n" "please inform the authors\n", #ifdef __i386__ (long)s.eip, #else /* x86_64*/ (long)s.rip, #endif (long)s.cr2,siRandomStart); } #ifdef __OPTIMIZE__ if(si_restart<3) { si_restart++; fprintf(stderr,"trying to restart...\n"); init_signals(); longjmp(si_start_jmpbuf,1); } #endif /* __OPTIMIZE__ */ #ifdef CALL_GDB if (sig!=SIGINT) { if (singular_in_batchmode) debug(STACK_TRACE); else debug(INTERACTIVE); } #endif /* CALL_GDB */ exit(0); } /*---------------------------------------------------------------------*/ #elif defined(SunOS) /*SPARC_SUNOS*/ /*2 * signal handler for run time errors, sparc sunos 4 version */ void sigsegv_handler(int sig, int code, struct sigcontext *scp, char *addr) { fprintf(stderr,"Singular : signal %d, code %d (v: %d):\n", sig,code,SINGULAR_VERSION); if ((sig!=SIGINT)&&(sig!=SIGABRT)) { fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf); fprintf(stderr,"Segment fault/Bus error occurred at %x (r:%d)\n" "please inform the authors\n", (int)addr,siRandomStart); } #ifdef __OPTIMIZE__ if(si_restart<3) { si_restart++; fprintf(stderr,"trying to restart...\n"); init_signals(); longjmp(si_start_jmpbuf,1); } #endif /* __OPTIMIZE__ */ #ifdef CALL_GDB if (sig!=SIGINT) debug(STACK_TRACE); #endif /* CALL_GDB */ exit(0); } #else /*---------------------------------------------------------------------*/ /*2 * signal handler for run time errors, general version */ void sigsegv_handler(int sig) { fprintf(stderr,"Singular : signal %d (v: %d):\n", sig,SINGULAR_VERSION); if (sig!=SIGINT) { fprintf(stderr,"current line:>>%s<<\n",my_yylinebuf); fprintf(stderr,"Segment fault/Bus error occurred (r:%d)\n" "please inform the authors\n", siRandomStart); } #ifdef __OPTIMIZE__ if(si_restart<3) { si_restart++; fprintf(stderr,"trying to restart...\n"); init_signals(); longjmp(si_start_jmpbuf,1); } #endif /* __OPTIMIZE__ */ #if defined(unix) #ifdef CALL_GDB if (sig!=SIGINT) debug(STACK_TRACE); #endif /* CALL_GDB */ #endif /* unix */ exit(0); } #endif /*2 * signal handler for SIGINT */ int sigint_handler_cnt=0; void sigint_handler(int /*sig*/) { mflush(); #ifdef HAVE_FEREAD if (fe_is_raw_tty) fe_temp_reset(); #endif /* HAVE_FEREAD */ char default_opt=' '; if ((feOptSpec[FE_OPT_CNTRLC].value!=NULL) && ((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0]) { default_opt=((char*)(feOptSpec[FE_OPT_CNTRLC].value))[0]; } loop { int cnt=0; int c; if (singular_in_batchmode) { c = 'q'; } else if (default_opt!=' ') { c = default_opt; } else { fprintf(stderr,"// ** Interrupt at cmd:`%s` in line:'%s'\n", Tok2Cmdname(iiOp),my_yylinebuf); if (feOptValue(FE_OPT_EMACS) == NULL) { fputs("abort after this command(a), abort immediately(r), print backtrace(b), continue(c) or quit Singular(q) ?",stderr); fflush(stderr);fflush(stdin); c = fgetc(stdin); } else { c = 'a'; } } switch(c) { case 'q': case EOF: m2_end(2); case 'r': if (sigint_handler_cnt<3) { sigint_handler_cnt++; fputs("** Warning: Singular should be restarted as soon as possible **\n",stderr); fflush(stderr); extern void my_yy_flush(); my_yy_flush(); currentVoice=feInitStdin(NULL); longjmp(si_start_jmpbuf,1); } else { fputs("** tried too often, try another possibility **\n",stderr); fflush(stderr); } break; case 'b': VoiceBackTrack(); break; case 'a': siCntrlc++; case 'c': if ((feOptValue(FE_OPT_EMACS) == NULL) && (default_opt!=' ')) { /* Read until a newline or EOF */ while (c != EOF && c != '\n') c = fgetc(stdin); } si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler); return; //siCntrlc ++; //if (siCntrlc>2) si_set_signal(SIGINT,(si_hdl_typ) sigsegv_handler); //else si_set_signal(SIGINT,(si_hdl_typ) sigint_handler); } cnt++; if(cnt>5) m2_end(2); } } //void test_int() //{ // if (siCntrlc!=0) // { // int saveecho = si_echo; // siCntrlc = FALSE; // si_set_signal(SIGINT ,sigint_handler); // iiDebug(); // si_echo = saveecho; // } //} #ifdef unix # ifndef __OPTIMIZE__ volatile int si_stop_stack_trace_x; # ifdef CALL_GDB static void debug (int method) { if (feOptValue(FE_OPT_NO_TTY)) { dReportError("Caught Signal 11"); return; } int pid; char buf[16]; char * args[4] = { (char*)"gdb", (char*)"Singular", NULL, NULL }; #ifdef HAVE_FEREAD if (fe_is_raw_tty) fe_temp_reset(); #endif /* HAVE_FEREAD */ sprintf (buf, "%d", getpid ()); args[2] = buf; pid = fork (); if (pid == 0) { switch (method) { case INTERACTIVE: fprintf (stderr, "\n\nquit with \"p si_stop_stack_trace_x=0\"\n\n\n"); debug_stop (args); break; case STACK_TRACE: fprintf (stderr, "stack_trace\n"); stack_trace (args); break; default: // should not be reached: exit(1); } } else if (pid == -1) { perror ("could not fork"); return; } si_stop_stack_trace_x = 1; while (si_stop_stack_trace_x) ; } static void debug_stop (char *const*args) { execvp (args[0], args); perror ("exec failed"); _exit (0); } # endif /* CALL_GDB */ static void stack_trace (char *const*args) { int pid; int in_fd[2]; int out_fd[2]; fd_set fdset; fd_set readset; struct timeval tv; int sel, index, state; char buffer[256]; char c; if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1)) { perror ("could open pipe"); m2_end(999); } pid = fork (); if (pid == 0) { si_close (0); si_dup2 (in_fd[0],0); /* set the stdin to the in pipe */ si_close (1); si_dup2 (out_fd[1],1); /* set the stdout to the out pipe */ si_close (2); si_dup2 (out_fd[1],2); /* set the stderr to the out pipe */ execvp (args[0], args); /* exec gdb */ perror ("exec failed"); m2_end(999); } else if (pid == -1) { perror ("could not fork"); m2_end(999); } FD_ZERO (&fdset); FD_SET (out_fd[0], &fdset); si_write (in_fd[1], "backtrace\n", 10); si_write (in_fd[1], "p si_stop_stack_trace_x = 0\n", 28); si_write (in_fd[1], "quit\n", 5); index = 0; state = 0; loop { readset = fdset; tv.tv_sec = 1; tv.tv_usec = 0; sel = si_select (FD_SETSIZE, &readset, NULL, NULL, &tv); if (sel == -1) break; if ((sel > 0) && (FD_ISSET (out_fd[0], &readset))) { if (si_read (out_fd[0], &c, 1)) { switch (state) { case 0: if (c == '#') { state = 1; index = 0; buffer[index++] = c; } break; case 1: buffer[index++] = c; if ((c == '\n') || (c == '\r')) { buffer[index] = 0; fprintf (stderr, "%s", buffer); state = 0; index = 0; } break; default: break; } } } else if (si_stop_stack_trace_x==0) break; } si_close (in_fd[0]); si_close (in_fd[1]); si_close (out_fd[0]); si_close (out_fd[1]); m2_end(0); } # endif /* !__OPTIMIZE__ */ #endif /* unix */ /*2 * init signal handlers */ void init_signals() { #ifdef SIGSEGV si_set_signal(SIGSEGV,(si_hdl_typ)sigsegv_handler); #endif #ifdef SIGBUS si_set_signal(SIGBUS, (si_hdl_typ)sigsegv_handler); #endif #ifdef SIGFPE si_set_signal(SIGFPE, (si_hdl_typ)sigsegv_handler); #endif #ifdef SIGILL si_set_signal(SIGILL, (si_hdl_typ)sigsegv_handler); #endif #ifdef SIGIOT si_set_signal(SIGIOT, (si_hdl_typ)sigsegv_handler); #endif si_set_signal(SIGINT ,(si_hdl_typ)sigint_handler); si_set_signal(SIGCHLD, (si_hdl_typ)sig_chld_hdl); si_set_signal(SIGPIPE, (si_hdl_typ)sig_pipe_hdl); si_set_signal(SIGTERM, (si_hdl_typ)sig_term_hdl); } singular-4.0.3+ds/Singular/cntrlc.h000066400000000000000000000012261266270727000172000ustar00rootroot00000000000000#ifndef CNTRLC_H #define CNTRLC_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT - interupt and signal handling */ #include #include #include extern jmp_buf si_start_jmpbuf; extern short si_restart; extern int siRandomStart; extern BOOLEAN siCntrlc; void init_signals(); extern BOOLEAN singular_in_batchmode; /* TRUE for child of a fork or started with --batch*/ /* for deferring the call of m2_end() in SIGTERM handler if necessary */ extern volatile BOOLEAN do_shutdown; extern volatile int defer_shutdown; #endif singular-4.0.3+ds/Singular/countedref.cc000066400000000000000000000521211266270727000202070ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file countedref.cc * * @author Alexander Dreyer * @date 2012-08-15 * * This file defines reference countes interpreter objects and adds the * @c blackbox operations for high-level types 'reference' and 'shared'. * * @note This works was supported by the "Industrial Algebra" project. * * @par Copyright: * (c) 2012 by The Singular Team, see LICENSE file **/ //***************************************************************************** #include #include "ipid.h" #include "countedref.h" #include "blackbox.h" #include "newstruct.h" #include "ipshell.h" /// Overloading ring destruction inline void CountedRefPtr_kill(ring r) { rKill(r); } /** @class CountedRefData * This class stores a reference counter as well as a Singular interpreter object. * It also take care of the context, e.g. the current ring, wrap object, etc. **/ class CountedRefData: public RefCounter { typedef CountedRefData self; public: typedef CountedRefWeakPtr back_ptr; private: typedef RefCounter base; /// Generate object linked to other reference (e.g. for subscripts) CountedRefData(leftv wrapid, back_ptr back): base(), m_data(wrapid), m_ring(back->m_ring), m_back(back) { } /// @name Disallow copying to avoid inconsistence //@{ self& operator=(const self&); CountedRefData(const self&); //@} public: typedef LeftvDeep::copy_tag copy_tag; /// Fix smart pointer type to referenced data typedef back_ptr::ptr_type ptr_type; /// Fix smart pointer type to ring typedef CountedRefPtr ring_ptr; /// Construct shared memory empty Singular object explicit CountedRefData(): base(), m_data(), m_ring(), m_back() { } /// Reference Singular object explicit CountedRefData(leftv data): base(), m_data(data), m_ring(parent(data)), m_back() { } /// Construct reference for Singular object CountedRefData(leftv data, copy_tag do_copy): base(), m_data(data, do_copy), m_ring(parent(data)), m_back() { } /// Destruct ~CountedRefData() { if (!m_back.unassigned()) { if (m_back == this) m_back.invalidate(); else m_data.clearid(root()); } } /// Generate object for indexing ptr_type wrapid() { return new self(m_data.idify(root()), weakref()); } /// Gerenate weak (but managed) reference to @c *this back_ptr weakref() { if (m_back.unassigned()) m_back = this; return m_back; } /// Replace with other Singular data self& operator=(leftv rhs) { m_data = rhs; m_ring = parent(rhs); return *this; } /// Write (shallow) copy to given handle BOOLEAN put(leftv res) { return broken() || m_data.put(res); } /// Extract (shallow) copy of stored data LeftvShallow operator*() const { return (broken()? LeftvShallow(): (const LeftvShallow&)m_data); } /// Determine active ring when ring dependency changes BOOLEAN rering() { if (m_ring ^ m_data.ringed()) m_ring = (m_ring? NULL: currRing); return (m_back && (m_back != this) && m_back->rering()); } /// Get the current context idhdl* root() { return (m_ring? &m_ring->idroot: &IDROOT); } /// Check whether identifier became invalid BOOLEAN broken() const { if (!m_back.unassigned() && !m_back) return complain("Back-reference broken"); if (m_ring) { if (m_ring != currRing) return complain("Referenced identifier not from current ring"); return m_data.isid() && m_data.brokenid(currRing->idroot) && complain("Referenced identifier not available in ring anymore"); } if (!m_data.isid()) return FALSE; return m_data.brokenid(IDROOT) && ((currPack == basePack) || m_data.brokenid(basePack->idroot)) && complain("Referenced identifier not available in current context"); } /// Reassign actual object BOOLEAN assign(leftv result, leftv arg) { if (!m_data.isid()) { (*this) = arg; return FALSE; } return put(result) || iiAssign(result, arg) || rering(); } /// Recover additional information (e.g. subexpression) from likewise object BOOLEAN retrieve(leftv res) { return m_data.retrieve(res); } /// Check whether data is all-zero BOOLEAN unassigned() const { return m_data.unassigned(); } private: /// Raise error message and return @c TRUE BOOLEAN complain(const char* text) const { WerrorS(text); return TRUE; } /// Store ring for ring-dependent objects static ring parent(leftv rhs) { return (rhs->RingDependend()? currRing: NULL); } protected: /// Singular object LeftvDeep m_data; /// Store namespace for ring-dependent objects ring_ptr m_ring; /// Reference to actual object for wrap structures back_ptr m_back; }; /// Supporting smart pointer @c CountedRefPtr inline void CountedRefPtr_kill(CountedRefData* data) { delete data; } /// blackbox support - initialization void* countedref_Init(blackbox*) { return NULL; } /// We use the function pointer as a marker of reference types /// for CountedRef::is_ref(leftv), see the latter for details BOOLEAN countedref_CheckAssign(blackbox */*b*/, leftv /*L*/, leftv /*R*/) { return FALSE; } class CountedRef { typedef CountedRef self; public: /// name type for identifiers typedef int id_type; /// Name type for handling referenced data typedef CountedRefData data_type; /// Fix smart pointer type to referenced data typedef CountedRefPtr data_ptr; /// Check whether argument is already a reference type /// @note We check for the function pointer @c countedref_CheckAssign here, /// that we (ab-)use as a unique marker. This avoids to check a bunch of /// of runtime-varying @c typ IDs for identifying reference-like types. static BOOLEAN is_ref(leftv arg) { int typ = arg->Typ(); return ((typ > MAX_TOK) && (getBlackboxStuff(typ)->blackbox_CheckAssign == countedref_CheckAssign)); } /// Reference given Singular data explicit CountedRef(leftv arg): m_data(new data_type(arg)) { } protected: /// Recover previously constructed reference CountedRef(data_ptr arg): m_data(arg) { assume(arg); } public: /// Construct copy CountedRef(const self& rhs): m_data(rhs.m_data) { } /// Replace reference self& operator=(const self& rhs) { m_data = rhs.m_data; return *this; } BOOLEAN assign(leftv result, leftv arg) { return m_data->assign(result,arg); } /// Extract (shallow) copy of stored data LeftvShallow operator*() { return m_data->operator*(); } /// Construct reference data object marked by given identifier number BOOLEAN outcast(leftv res, int typ) { res->rtyp = typ; return outcast(res); } /// Construct reference data object from *this BOOLEAN outcast(leftv res) { if (res->rtyp == IDHDL) IDDATA((idhdl)res->data) = (char *)outcast(); else res->data = (void *)outcast(); return FALSE; } /// Construct raw reference data data_type* outcast() { m_data.reclaim(); return m_data; } /// Kills a link to the referenced object void destruct() { m_data.release(); } /// Kills the link to the referenced object ~CountedRef() { } /// Replaces argument by a shallow copy of the references data BOOLEAN dereference(leftv arg) { m_data.reclaim(); BOOLEAN b= m_data->put(arg) || ((arg->next != NULL) && resolve(arg->next)); m_data.release(); return b; } /// Check whether object in valid in current context BOOLEAN broken() {return m_data->broken(); } /// Check whether (shared) data was initialized but not assigned yet. BOOLEAN unassigned() const { return m_data->unassigned(); } /// Get number of references pointing here, too BOOLEAN count(leftv res) { return construct(res, m_data.count() - 1); } // Get internal indentifier BOOLEAN enumerate(leftv res) { return construct(res, (long)(data_type*)m_data); } /// Check for likewise identifiers BOOLEAN likewise(leftv res, leftv arg) { return resolve(arg) || construct(res, operator*()->data == arg->data); } /// Check for identical reference objects BOOLEAN same(leftv res, leftv arg) { return construct(res, m_data == arg->Data()); } /// Get type of references data BOOLEAN type(leftv res) { return construct(res, Tok2Cmdname(operator*()->Typ())); }; /// Get (possibly) internal identifier name BOOLEAN name(leftv res) { return construct(res, operator*()->Name()); } /// Recover the actual object from raw Singular data static self cast(void* data) { assume(data != NULL); return self(static_cast(data)); } /// Recover the actual object from Singular interpreter object static self cast(leftv arg) { assume(arg != NULL); assume(is_ref(arg)); return self::cast(arg->Data()); } /// If necessary dereference. static BOOLEAN resolve(leftv arg) { assume(arg != NULL); while (is_ref(arg)) { if(CountedRef::cast(arg).dereference(arg)) return TRUE; }; return (arg->next != NULL) && resolve(arg->next); } /// Construct integer value static BOOLEAN construct(leftv res, long data) { res->data = (void*) data; res->rtyp = INT_CMD; return FALSE; } /// Construct string static BOOLEAN construct(leftv res, const char* data) { res->data = (void*)omStrDup(data); res->rtyp = STRING_CMD; return FALSE; } /// Construct void-style object static BOOLEAN construct(leftv res) { res->data = NULL; res->rtyp = NONE; return FALSE; } protected: /// Store pointer to actual data data_ptr m_data; }; /// blackbox support - convert to string representation void countedref_Print(blackbox */*b*/, void* ptr) { if (ptr) (*CountedRef::cast(ptr))->Print(); else PrintS(""); } /// blackbox support - convert to string representation char* countedref_String(blackbox */*b*/, void* ptr) { if (ptr == NULL) return omStrDup(sNoName); return (*CountedRef::cast(ptr))->String(); } /// blackbox support - copy element void* countedref_Copy(blackbox*/*b*/, void* ptr) { if (ptr) return CountedRef::cast(ptr).outcast(); return NULL; } /// blackbox support - assign element BOOLEAN countedref_Assign(leftv result, leftv arg) { // Case: replace assignment behind reference if (result->Data() != NULL) { CountedRef ref = CountedRef::cast(result); return CountedRef::resolve(arg) || ref.assign(result, arg); } // Case: copy reference if (result->Typ() == arg->Typ()) return CountedRef::cast(arg).outcast(result); // Case: new reference if ((arg->rtyp == IDHDL) || CountedRef::is_ref(arg)) return CountedRef(arg).outcast(result); WerrorS("Can only take reference from identifier"); return TRUE; } BOOLEAN countedref_CheckInit(leftv res, leftv arg) { if (arg->Data() != NULL) return FALSE; res->rtyp = NONE; WerrorS("Noninitialized access"); return TRUE; } /// blackbox support - unary operations BOOLEAN countedref_Op1(int op, leftv res, leftv head) { if(op == TYPEOF_CMD) return blackboxDefaultOp1(op, res, head); if (countedref_CheckInit(res, head)) return TRUE; if ((op == DEF_CMD) || (op == head->Typ())) { res->rtyp = head->Typ(); return iiAssign(res, head); } CountedRef ref = CountedRef::cast(head); return ref.dereference(head) || iiExprArith1(res, head, op == LINK_CMD? head->Typ(): op); } /// blackbox support - binary operations (resolve seocnd argument) static BOOLEAN countedref_Op2_(int op, leftv res, leftv head, leftv arg) { if (CountedRef::is_ref(arg)) { CountedRef ref = CountedRef::cast(arg); return ref.dereference(arg) || iiExprArith2(res, head, op, arg); } return iiExprArith2(res, head, op, arg); } BOOLEAN countedref_Op2(int op, leftv res, leftv head, leftv arg) { if (countedref_CheckInit(res, head)) return TRUE; if (CountedRef::is_ref(head)) { CountedRef ref = CountedRef::cast(head); return ref.dereference(head) || countedref_Op2_(op, res, head, arg); } return countedref_Op2_(op, res, head, arg); } static BOOLEAN countedref_Op3__(int op, leftv res, leftv head, leftv arg1, leftv arg2) { if (CountedRef::is_ref(arg2)) { CountedRef ref = CountedRef::cast(arg2); return ref.dereference(arg2) || iiExprArith3(res, op, head, arg1, arg2); } return iiExprArith3(res, op, head, arg1, arg2); } static BOOLEAN countedref_Op3_(int op, leftv res, leftv head, leftv arg1, leftv arg2) { if (CountedRef::is_ref(arg1)) { CountedRef ref = CountedRef::cast(arg1); return ref.dereference(arg1) || countedref_Op3__(op, res, head, arg1, arg2); } return countedref_Op3__(op, res, head, arg1, arg2); } /// blackbox support - ternary operations BOOLEAN countedref_Op3(int op, leftv res, leftv head, leftv arg1, leftv arg2) { if (countedref_CheckInit(res, head)) return TRUE; if (CountedRef::is_ref(head)) { CountedRef ref = CountedRef::cast(head); return ref.dereference(head) || countedref_Op3_(op, res, head, arg1, arg2); } return countedref_Op3_(op, res, head, arg1, arg2); } /// blackbox support - destruction void countedref_destroy(blackbox */*b*/, void* ptr) { if (ptr) CountedRef::cast(ptr).destruct(); } class CountedRefShared: public CountedRef { typedef CountedRefShared self; typedef CountedRef base; /// Reinterprete @c CountedRef as @c CountedRefShared CountedRefShared(const base& rhs): base(rhs) { } /// Generate from data pointer CountedRefShared(data_ptr rhs): base(rhs) { } public: /// Default constructor for initialized, but all-zero, shared data object CountedRefShared(): base(new data_type) { } /// Construct internal copy of Singular interpreter object explicit CountedRefShared(leftv arg): base(new data_type(arg, data_type::copy_tag())) { } /// Construct new reference to internal data CountedRefShared(const self& rhs): base(rhs) { } /// Desctruct ~CountedRefShared() { } /// Change reference to shared data self& operator=(const self& rhs) { return static_cast(base::operator=(rhs)); } /// Recovering outcasted @c CountedRefShared object from interpreter object static self cast(leftv arg) { return base::cast(arg); } /// Recovering outcasted @c CountedRefShared object from raw data static self cast(void* arg) { return base::cast(arg); } /// Temporarily wrap with identifier for '[' and '.' operation self wrapid() { return self(m_data->wrapid()); } /// Generate weak reference (may get invalid) data_type::back_ptr weakref() { return m_data->weakref(); } /// Recover more information (e.g. subexpression data) from computed result BOOLEAN retrieve(leftv res, int typ) { return (m_data->retrieve(res) && outcast(res, typ)); } }; /// Blackbox support - generate initialized, but all-zero - shared data void* countedref_InitShared(blackbox*) { return CountedRefShared().outcast(); } /// Blackbox support - unary operation for shared data BOOLEAN countedref_Op1Shared(int op, leftv res, leftv head) { if(op == TYPEOF_CMD) return blackboxDefaultOp1(op, res, head); if (countedref_CheckInit(res, head)) return TRUE; if ((op == DEF_CMD) || (op == head->Typ())) { res->rtyp = head->Typ(); return iiAssign(res, head); } CountedRefShared ref = CountedRefShared::cast(head); if (op == LINK_CMD) { if (ref.dereference(head)) return TRUE; res->Copy(head); return (res->Typ() == NONE); } CountedRefShared wrap = ref.wrapid(); int typ = head->Typ(); return wrap.dereference(head) || iiExprArith1(res, head, op) || wrap.retrieve(res, typ); } /// blackbox support - binary operations BOOLEAN countedref_Op2Shared(int op, leftv res, leftv head, leftv arg) { if (countedref_CheckInit(res, head)) return TRUE; if (CountedRefShared::is_ref(head)) { CountedRefShared wrap = CountedRefShared::cast(head).wrapid(); int typ = head->Typ(); return wrap.dereference(head) || countedref_Op2_(op, res, head, arg) || wrap.retrieve(res, typ); } return countedref_Op2_(op, res, head, arg); } /// blackbox support - n-ary operations BOOLEAN countedref_OpM(int op, leftv res, leftv args) { if (args->Data() == NULL) return FALSE; if(op == SYSTEM_CMD) { if (args->next) { leftv next = args->next; args->next = NULL; char* name = (next->Typ() == STRING_CMD? (char*) next->Data(): (char*)next->Name()); next = next->next; if (strcmp(name, "help") == 0) { PrintS("system(, ...): extended functionality for reference/shared data \n"); PrintS(" system(, count) - number of references pointing to \n"); PrintS(" system(, enumerate) - unique number for identifying \n"); PrintS(" system(, undefined) - checks whether had been assigned\n"); PrintS(" system(, \"help\") - prints this information message\n"); PrintS(" system(, \"typeof\") - actual type referenced by \n"); PrintS(" system(, same, ) - tests for identic reference objects\n"); return CountedRef::construct(res); } if (strncmp(name, "undef", 5) == 0) { return CountedRef::construct(res, args->Data()? (CountedRef::cast(args).unassigned()? 1: 2): 0); } CountedRef obj = CountedRef::cast(args); if (next) { if (strcmp(name, "same") == 0) return obj.same(res, next); // likewise may be hard to interprete, so we not not document it above if (strncmp(name, "like", 4) == 0) return obj.likewise(res, next); } if (strncmp(name, "count", 5) == 0) return obj.count(res); if (strncmp(name, "enum", 4) == 0) return obj.enumerate(res); if (strcmp(name, "name") == 0) return obj.name(res); // undecumented if (strncmp(name, "typ", 3) == 0) return obj.type(res); } return TRUE; } if (op == LIST_CMD) { res->rtyp = op; return jjLIST_PL(res, args); } CountedRef ref = CountedRef::cast(args); return ref.dereference(args) || iiExprArithM(res, args, op); } /// blackbox support - assign element BOOLEAN countedref_AssignShared(leftv result, leftv arg) { /// Case: replace assignment behind reference if ((result->Data() != NULL) && !CountedRefShared::cast(result).unassigned()) { CountedRef ref = CountedRef::cast(result); return CountedRef::resolve(arg) || ref.assign(result, arg); } /// Case: new reference to already shared data if (result->Typ() == arg->Typ()) { if (result->Data() != NULL) CountedRefShared::cast(result).destruct(); return CountedRefShared::cast(arg).outcast(result); } if(CountedRefShared::cast(result).unassigned()) { return CountedRefShared::cast(result).assign(result, arg); } /// Case: new shared data return CountedRefShared(arg).outcast(result); } /// blackbox support - destruction void countedref_destroyShared(blackbox */*b*/, void* ptr) { if (ptr) CountedRefShared::cast(ptr).destruct(); } BOOLEAN countedref_serialize(blackbox */*b*/, void *d, si_link f) { sleftv l; memset(&l,0,sizeof(l)); l.rtyp = STRING_CMD; l.data = (void*)omStrDup("shared"); // references are converted f->m->Write(f, &l); CountedRefShared::cast(d).dereference(&l); f->m->Write(f, &l); return FALSE; } BOOLEAN countedref_deserialize(blackbox **/*b*/, void **d, si_link f) { // rtyp must be set correctly (to the blackbox id) by routine calling leftv data=f->m->Read(f); CountedRefShared sh(data); *d = sh.outcast(); return FALSE; } void countedref_reference_load() { int tok; if (blackboxIsCmd("reference", tok) == ROOT_DECL) return; blackbox *bbx = (blackbox*)omAlloc0(sizeof(blackbox)); bbx->blackbox_CheckAssign = countedref_CheckAssign; bbx->blackbox_destroy = countedref_destroy; bbx->blackbox_String = countedref_String; bbx->blackbox_Print = countedref_Print; bbx->blackbox_Init = countedref_Init; bbx->blackbox_Copy = countedref_Copy; bbx->blackbox_Assign = countedref_Assign; bbx->blackbox_Op1 = countedref_Op1; bbx->blackbox_Op2 = countedref_Op2; bbx->blackbox_Op3 = countedref_Op3; bbx->blackbox_OpM = countedref_OpM; bbx->blackbox_serialize = countedref_serialize; bbx->blackbox_deserialize = countedref_deserialize; bbx->data = omAlloc0(newstruct_desc_size()); setBlackboxStuff(bbx, "reference"); } void countedref_shared_load() { int tok; if (blackboxIsCmd("shared", tok) == ROOT_DECL) return; blackbox *bbxshared = (blackbox*)omAlloc0(sizeof(blackbox)); bbxshared->blackbox_String = countedref_String; bbxshared->blackbox_Print = countedref_Print; bbxshared->blackbox_Copy = countedref_Copy; bbxshared->blackbox_Op3 = countedref_Op3; bbxshared->blackbox_OpM = countedref_OpM; bbxshared->blackbox_serialize = countedref_serialize; bbxshared->blackbox_deserialize = countedref_deserialize; bbxshared->blackbox_CheckAssign = countedref_CheckAssign; bbxshared->blackbox_Assign = countedref_AssignShared; bbxshared->blackbox_destroy = countedref_destroyShared; bbxshared->blackbox_Op1 = countedref_Op1Shared; bbxshared->blackbox_Op2 = countedref_Op2Shared; bbxshared->blackbox_Init = countedref_InitShared; bbxshared->data = omAlloc0(newstruct_desc_size()); setBlackboxStuff(bbxshared, "shared"); } singular-4.0.3+ds/Singular/countedref.h000066400000000000000000000321251266270727000200530ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file countedref.h * * This file defines reusable classes supporting reference counted interpreter * objects and initiates the @c blackbox operations for high-level types * 'reference' and 'shared'. * * @note This works was supported by the "Industrial Algebra" project. * * @author Alexander Dreyer * @date 2012-08-15 * * @par Copyright: * (c) 2012 by The Singular Team, see LICENSE file **/ //***************************************************************************** #ifndef SINGULAR_COUNTEDREF_H_ #define SINGULAR_COUNTEDREF_H_ #include #include #include #include #include /** @class CountedRefPtr * This class implements a smart pointer which handles pointer-style access * to a reference-counted structure and destructing the latter after use. * * The template arguments, include the pointer type @c PtrType, and two * integral (bool) properties: use @c Nondestructive to disallow destruction * and @c NeverNull to assume, that @c PtrType cannot be @c NULL. * Finally, @c CountType allows you to select a typ to represent the internal reference count. * * @note The class of @c PtrType must have an accessible integral attribute @c ref. * For convenience use @c RefCounter as public base. * In addition you must overload @c void CountedRefPtr_kill(PtrType) accordingly. **/ template class CountedRefPtr { typedef CountedRefPtr self; public: //{ @name Name template arguments typedef PtrType ptr_type; typedef CountType count_type; enum { nondestructive = Nondestructive, never_null = NeverNull }; //} /// Default constructor @note: exisis only if @c NeverNull is false CountedRefPtr(): m_ptr(NULL) {} /// Convert from pointer CountedRefPtr(ptr_type ptr): m_ptr(ptr) { reclaim(); } /// Convert from compatible smart pointer template CountedRefPtr(const CountedRefPtr& rhs): m_ptr(rhs.m_ptr) { reclaim(); } /// Construct refernce copy CountedRefPtr(const self& rhs): m_ptr(rhs.m_ptr) { reclaim(); } /// Unlink one reference ~CountedRefPtr() { release(); } //{ @name Replace data behind reference self& operator=(const self& rhs) { return operator=(rhs.m_ptr); } self& operator=(ptr_type ptr) { release(); m_ptr = ptr; reclaim(); return *this; } //} /// Checking equality bool operator==(const self& rhs) const { return m_ptr == rhs.m_ptr; } //{ @name Pointer-style interface bool operator==(ptr_type ptr) const { return m_ptr == ptr; } operator bool() const { return NeverNull || m_ptr; } operator const ptr_type() const { return m_ptr; } operator ptr_type() { return m_ptr; } const ptr_type operator->() const { return *this; } ptr_type operator->() { return *this; } //} /// @name Reference count interface //@{ count_type count() const { return (*this? m_ptr->ref: 0); } void reclaim() { if (*this) ++m_ptr->ref; } void release() { if (*this && (--m_ptr->ref <= 0) && !nondestructive) CountedRefPtr_kill(m_ptr); } //@} private: /// Store actual pointer ptr_type m_ptr; }; /** @class RefCounter * This class implements implements a refernce counter which we can use * as a public base of objects managed by @CountedRefPtr. **/ class RefCounter { public: /// Name numerical type for enumbering typedef short count_type; /// Allow our smart pointer to access internals template friend class CountedRefPtr; /// Any Constructor resets the counter RefCounter(...): ref(0) {} /// Destructor ~RefCounter() { assume(ref == 0); } private: /// Number of references count_type ref; // naming consistent with other classes }; template class CountedRefWeakPtr; template class CountedRefIndirectPtr: public RefCounter { public: friend class CountedRefWeakPtr; ~CountedRefIndirectPtr() { } private: CountedRefIndirectPtr(PtrType ptr): m_ptr(ptr) { } CountedRefIndirectPtr& operator=(PtrType ptr) { m_ptr = ptr; return *this; } PtrType m_ptr; }; template inline void CountedRefPtr_kill(CountedRefIndirectPtr* pval) { delete pval; } template class CountedRefWeakPtr { typedef CountedRefWeakPtr self; public: /// @name Name template arguments //@{ Name template arguments typedef PtrType ptr_type; typedef CountedRefPtr*> ptrptr_type; //@} /// Construct unassigned weak reference CountedRefWeakPtr(): m_indirect(NULL) { } /// Convert from pointer CountedRefWeakPtr(ptr_type ptr): m_indirect(new CountedRefIndirectPtr(ptr)) { } /// Construct copy CountedRefWeakPtr(const self& rhs): m_indirect(rhs.m_indirect) { } /// Unlink one reference (handled by CountedRefPtr) ~CountedRefWeakPtr() { } /// Mark weak reference as invalid void invalidate() { *this = NULL; } /// Test whether reference was never used bool unassigned() const { return !m_indirect; } /// Pointer-style interface //@{ operator bool() const { return operator->(); } self& operator=(const self& rhs) { m_indirect = rhs.m_indirect; return *this; } self& operator=(ptr_type ptr) { if (!m_indirect) m_indirect = new CountedRefIndirectPtr(ptr); else m_indirect->m_ptr = ptr; return *this; } bool operator==(ptr_type ptr) const { return m_indirect &&(m_indirect->m_ptr == ptr); } bool operator!=(ptr_type rhs) const { return !operator==(rhs); } const ptr_type operator->() const { return (m_indirect? m_indirect->m_ptr: NULL); } ptr_type operator->() { return (m_indirect? m_indirect->m_ptr:NULL); } //@} private: ptrptr_type m_indirect; }; /** @class LeftvHelper * This class implements some recurrent code sniplets to be used with * @c leftv and @c idhdl.implements a refernce counter which we can use **/ class LeftvHelper { public: static leftv idify(leftv head, idhdl* root) { idhdl handle = newid(head, root); leftv res = (leftv)omAlloc0(sizeof(*res)); res->data =(void*) handle; res->rtyp = IDHDL; return res; } static idhdl newid(leftv head, idhdl* root) { static unsigned int counter = 0; char* name = (char*) omAlloc0(512); sprintf(name, " :%u:%p:_shared_: ", ++counter, head->data); if ((*root) == NULL ) enterid(name, 0, head->rtyp, root, TRUE, FALSE); else *root = (*root)->set(name, 0, head->rtyp, TRUE); IDDATA(*root) = (char*) head->data; return *root; } static void clearid(idhdl handle, idhdl* root) { IDDATA(handle)=NULL; IDTYP(handle)=NONE; killhdl2(handle, root, NULL); } template static Type* cpy(Type* result, Type* data) { return (Type*)memcpy(result, data, sizeof(Type)); } template static Type* cpy(Type* data) { return cpy((Type*)omAlloc0(sizeof(Type)), data); } template static Type* recursivecpy(Type* data) { if (data == NULL) return data; Type* result = cpy(data); result->next = recursivecpy(data->next); return result; } template static Type* shallowcpy(Type* result, Type* data) { cpy(result, data)->e = recursivecpy(data->e); return result; } template static Type* shallowcpy(Type* data) { return shallowcpy((Type*) omAlloc0(sizeof(Type)), data); } template static void recursivekill(Type* current) { if(current == NULL) return; recursivekill(current->next); omFree(current); } static leftv allocate() { return (leftv)omAlloc0(sizeof(sleftv)); } }; /** @class LeftvShallow * Ths class wraps @c leftv by taking into acount memory allocation, destruction * as well as shallowly copying of a given @c leftv, i.e. we just copy auxiliary * information (like subexpressions), but not the actual data. * * @note This is useful to avoid invalidating @c leftv while operating on th **/ class LeftvShallow: public LeftvHelper { typedef LeftvShallow self; public: /// Just allocate (all-zero) @c leftv LeftvShallow(): m_data(allocate()) { } /// Shallow copy the input data LeftvShallow(leftv data): m_data(shallowcpy(data)) { } /// Construct (shallow) copy of @c *this LeftvShallow(const self& rhs): m_data(shallowcpy(rhs.m_data)) { } /// Destruct ~LeftvShallow() { recursivekill(m_data->e); omFree(m_data); } /// Assign shallow copy of the input self& operator=(leftv rhs) { recursivekill(m_data->e); shallowcpy(m_data, rhs); return *this; } /// Assign (shallow) copy of @c *this self& operator=(const self& rhs) { return (*this) = rhs.m_data; } /// @name Pointer-style access //@{ /*const*/ leftv operator->() const { return m_data; } /*^ warning: 'const' type qualifier on return type has no effect!!! */ leftv operator->() { return m_data; } //@] protected: /// The actual data pointer leftv m_data; }; /** @class LeftvDeep * This class wraps @c leftv by taking into acount memory allocation, destruction * as well as deeply copying of a given @c leftv, i.e. we also take over * ownership of the @c leftv data. * * We have two variants: + LeftvDeep(leftv): treats referenced identifiers as "the data" + LeftvDeep(leftv, copy_tag): takes care of a full copy of identifier's data * * @note It invalidats @c leftv on input. **/ class LeftvDeep: public LeftvHelper { typedef LeftvDeep self; /// @name Do not permit copying (avoid inconsistence) //@{ self& operator=(const self&); LeftvDeep(const self&); //@} public: /// Allocate all-zero object by default LeftvDeep(): m_data(allocate()) {} /// Store a deep copy of the data /// @ note Occupies the provided @c leftv and invalidates the latter LeftvDeep(leftv data): m_data(cpy(data)) { data->e = NULL; // occupy subexpression if(!isid()) m_data->data=data->CopyD(); } /// Construct even deeper copy: /// Skip identifier (if any) and take care of the data on our own struct copy_tag {}; LeftvDeep(leftv data, copy_tag): m_data(allocate()) { m_data->Copy(data); } /// Really clear data ~LeftvDeep() { m_data->CleanUp(); } /// @name Access via shallow copy to avoid invalidating the stored handle //@{ operator LeftvShallow() { return m_data; } LeftvShallow operator*() {return *this; } //@} /// Determine whether we point to the same data bool like(const self& rhs) const { return m_data->data == rhs.m_data->data; } /// Reassign a new deep copy by occupieing another @c leftv /// @note clears @c *this in the first self& operator=(leftv rhs) { if(isid()) { m_data->e = rhs->e; rhs->e = NULL; IDTYP((idhdl)m_data->data) = rhs->Typ(); IDDATA((idhdl)m_data->data) = (char*) rhs->CopyD(); } else { m_data->CleanUp(); m_data->Copy(rhs); } return *this; } /// Check a given context for our identifier BOOLEAN brokenid(idhdl context) const { assume(isid()); return (context == NULL) || ((context != (idhdl) m_data->data) && brokenid(IDNEXT(context))); } /// Put a shallow copy to given @c leftv BOOLEAN put(leftv result) { leftv next = result->next; result->next = NULL; result->CleanUp(); shallowcpy(result, m_data); result->next = next; /// @note @c attrib should read the attributes of the identifier if (isid()) { result->attribute = ((idhdl)m_data->data)->attribute; result->flag = ((idhdl)m_data->data)->flag; } return FALSE; } /// Get additional data (e.g. subexpression data) from likewise instances BOOLEAN retrieve(leftv res) { if (res->data == m_data->data) { if(m_data->e != res->e) recursivekill(m_data->e); cpy(m_data, res); res->Init(); return TRUE; } return FALSE; } /// Check for being an identifier BOOLEAN isid() const { return m_data->rtyp==IDHDL;} /// Test whether we reference to ring-dependent data BOOLEAN ringed() { return m_data->RingDependend(); } /// Check whether (all-zero) initialized data was never assigned. BOOLEAN unassigned() const { return m_data->Typ()==0; } /// Wrap data by identifier, if not done yet leftv idify(idhdl* root) { leftv res = (isid()? m_data: LeftvHelper::idify(m_data, root)); ++(((idhdl)res->data)->ref); return res; } /// Erase identifier handles by @c *this /// @note Assumes that we reference an identifier and that we own the latter. /// This is useful to clear the result of a subsequent call of @c idify. void clearid(idhdl* root) { assume(isid()); if (--((idhdl)m_data->data)->ref <= 0) // clear only if we own LeftvHelper::clearid((idhdl)m_data->data, root); } private: /// Store the actual data leftv m_data; }; /// Initialize @c blackbox types 'reference' and 'shared', or both void countedref_reference_load(); void countedref_shared_load(); inline void countedref_init() { countedref_reference_load(); countedref_shared_load(); } #endif /*SINGULAR_COUNTEDREF_H_ */ singular-4.0.3+ds/Singular/denom_list.cc000066400000000000000000000007621266270727000202120ustar00rootroot00000000000000 #include #include #include lists get_denom_list() { int size; denominator_list d = DENOMINATOR_LIST; size=0; while(d!=0) { size++; d=d->next; } lists l=(lists)omAlloc(sizeof(*l)); l->Init(size); d=DENOMINATOR_LIST; for (int i=0;im[i].rtyp=NUMBER_CMD; l->m[i].data=d->n; d=d->next; omFree(DENOMINATOR_LIST); DENOMINATOR_LIST=d; } return l; } singular-4.0.3+ds/Singular/distrib.h000066400000000000000000000000341266270727000173470ustar00rootroot00000000000000#define MAKE_DISTRIBUTION 1 singular-4.0.3+ds/Singular/dyn_modules/000077500000000000000000000000001266270727000200635ustar00rootroot00000000000000singular-4.0.3+ds/Singular/dyn_modules/Makefile.am000066400000000000000000000001551266270727000221200ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../m4 SUBDIRS=staticdemo bigintm syzextra pyobject gfanlib polymake singmathic Order singular-4.0.3+ds/Singular/dyn_modules/Order/000077500000000000000000000000001266270727000211365ustar00rootroot00000000000000singular-4.0.3+ds/Singular/dyn_modules/Order/Makefile.am000066400000000000000000000030011266270727000231640ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../../m4 SOURCES = nforder.cpp nforder.h \ singular.cc \ nforder_elt.cc nforder_elt.h \ nforder_ideal.cc nforder_ideal.h MYINCLUDES = -I${top_srcdir} -I${top_builddir} -I${srcdir} \ -I${top_srcdir}/libpolys -I${top_builddir}/libpolys \ -I${top_srcdir}/factory/include -I${top_builddir}/factory/include \ $(FACTORY_CFLAGS) $(NTL_CFLAGS) $(GMP_CFLAGS) $(GOOGLE_PERFTOOLS_CFLAGS) if SI_BUILTIN_ORDER noinst_LTLIBRARIES=Order.la P_PROCS_CPPFLAGS_COMMON = -DSTATIC_VERSION P_PROCS_MODULE_LDFLAGS = -module else module_LTLIBRARIES=Order.la moduledir = $(libexecdir)/singular/MOD P_PROCS_CPPFLAGS_COMMON = -DDYNAMIC_VERSION # Add under Mac OS X: -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup P_PROCS_MODULE_LDFLAGS = -module -export-dynamic -avoid-version -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup endif Order_la_SOURCES = $(SOURCES) Order_la_CPPFLAGS = ${MYINCLUDES} ${P_PROCS_CPPFLAGS_COMMON} Order_la_LDFLAGS = ${AM_LDFLAGS} ${P_PROCS_MODULE_LDFLAGS} ${GOOGLE_PERFTOOL_LDFLAGS} # AM_COLOR_TESTS=always # # TESTS_ENVIRONMENT = SINGULARPATH='${abs_top_builddir}/Singular/LIB:${abs_top_srcdir}/Singular/LIB:${abs_top_builddir}/libpolys/polys/.libs:${abs_top_builddir}/factory/gftables:${abs_builddir}/.libs:${abs_srcdir}' # TESTS_ENVIRONMENT += SINGULAR_ROOT_DIR='${abs_top_builddir}' # TESTS_ENVIRONMENT += SINGULAR_BIN_DIR='${abs_top_builddir}/Singular' # # TESTS=test_release.sh # # EXTRA_DIST = nforder.tst test.sh $(TESTS) singular-4.0.3+ds/Singular/dyn_modules/Order/nforder.cpp000066400000000000000000000460131266270727000233050ustar00rootroot00000000000000#include #include "nforder.h" #include #include #include #include "Singular/ipid.h" //////////////////////////////////// //// Konstruktoren/Destruktoren //// //////////////////////////////////// /*________________0_______________*/ void nforder::init() { rc = 1; // Gibt es eine Multtable, so gibt es keine Baseorder baseorder = NULL; basis = NULL; // Discriminante wird erst berechnet, wenn sie benötigt wird discriminant = NULL; divisor = NULL; flags = 0; multtable = NULL; m_coeffs = NULL; setOneIsOne(); } nforder::nforder(int dim, bigintmat **m,const coeffs q) { init(); m_coeffs = q; dimension = dim; multtable = (bigintmat**)(omAlloc(dim*sizeof(bigintmat*))); for (int i=0; iref_count_incref(); //Gibt es eine Baseorder, brauchen wir keine Multtable. Könnte aber evtl. generiert werden multtable = NULL; divisor = n_Copy(div,basecoeffs()); basis->simplifyContentDen(&divisor); dimension = o->getDim(); discriminant = NULL; inv_basis = new bigintmat(base->rows(), base->rows(), q); inv_divisor = basis->pseudoinv(inv_basis); inv_basis->skalmult(divisor, q); inv_basis->simplifyContentDen(&inv_divisor); } nforder::nforder(nforder *o, int) { init(); m_coeffs = o->basecoeffs(); ::Print("copy called: %lx\n", (long unsigned int) m_coeffs); // Kopiert die Daten der übergebenen Ordnung auf die erzeugte if (o->discriminant) discriminant = n_Copy(o->discriminant, basecoeffs()); // get-Funktionen liefern immer nur Kopien der Attribute zurück dimension = o->getDim(); multtable = (bigintmat **)omAlloc(dimension*sizeof(bigintmat*)); if (!o->getMult(multtable)) { omFree(multtable); multtable = NULL; } baseorder = o->getBase(); if (baseorder) baseorder->ref_count_incref(); basis = o->getBasis(); if (o->divisor) divisor = n_Copy(o->divisor, basecoeffs()); if (o->inv_basis) { inv_basis = new bigintmat(o->inv_basis); inv_divisor = n_Copy(o->inv_divisor, basecoeffs()); } } void nforder::Write() { StringAppend("Order:\nof dimension %d and rc: %d\n", dimension, ref_count()); if (discriminant && !n_IsZero(discriminant, m_coeffs)) { StringAppend("and discriminant: "); n_Write(discriminant, m_coeffs); StringAppend("\n"); } // coeffs if (multtable) { StringAppend("Multiplication table:\n"); for(int i=0; iWrite(); StringAppendS("\n"); } } if (baseorder) { StringAppendS("as extension of:"); baseorder->Write(); StringAppendS("with basis:\n"); basis->Write(); StringAppendS("and denominator: "); n_Write(divisor, m_coeffs); StringAppendS("\nwith inv_basis:\n"); inv_basis->Write(); StringAppendS("and inv_denominator: "); n_Write(inv_divisor, m_coeffs); StringAppendS("\n"); } StringAppend("Flags: %lx\n", flags); } char * nforder::String() { StringSetS(""); Write(); return StringEndS(); } void nforder::Print() { char * s = String(); PrintS(s); PrintS("\n"); omFree(s); } void nforder_delete(nforder* o) { if (o->ref_count_decref()>0) { return; } delete o; } nforder::~nforder() { if (multtable != NULL) { for (int i=0; idet(); assume(discriminant); delete m; } else { number prod = n_Init(1, basecoeffs()); number tmp, tmp2; //assumes that the basis is triangular! for (int i=1; i<=dimension; i++) { tmp2 = basis->view(i, i); tmp = n_Mult(prod, tmp2, basecoeffs()); n_Delete(&prod, basecoeffs()); prod = tmp; } baseorder->calcdisc(); number disc = baseorder->viewDisc(); assume(disc); number detquad = n_Mult(prod, prod, basis->basecoeffs()); discriminant = n_Mult(disc, detquad, basecoeffs()); for (int i=1; i<=2*dimension; i++) { tmp = n_Div(discriminant, divisor, basecoeffs()); n_Delete(&discriminant, basecoeffs()); discriminant = tmp; } n_Delete(&detquad, basis->basecoeffs()); } } bigintmat *nforder::traceMatrix() { bigintmat *m = new bigintmat(dimension, dimension, basecoeffs()); bigintmat *base1 = new bigintmat(dimension, 1, basecoeffs()); bigintmat *base2 = new bigintmat(dimension, 1, basecoeffs()); bigintmat *mm = new bigintmat(dimension, dimension, basecoeffs()); number sum; for (int i=1; i<=dimension; i++) { for (int j=i; j<=dimension; j++) { // Berechnet Produkt von Basiselementen i und j und speichert es in base1 basis_elt(base1, i); basis_elt(base2, j); elMult(base1, base2); // Schreibt Abbildungsmatrix der Multiplikation mit base1 in mm sum = elTrace(base1); m->set(i, j, sum, basecoeffs()); if (i!=j) m->set(j, i, sum, basecoeffs()); n_Delete(&sum, basecoeffs()); } } delete base1; delete base2; delete mm; return m; } //////////////////////////////////// ////// Öffentliche Funktionen ////// //////////////////////////////////// /*_____________+1_______________ */ number nforder::getDisc() { // Falls Discriminante bisher noch nicht berechnet wurde, berechne diese if (!discriminant || n_IsZero(discriminant, basecoeffs())) { calcdisc(); } return n_Copy(discriminant, basecoeffs()); } int nforder::getDim() { return dimension; } bigintmat *nforder::getBasis() { // Falls basis ein NULL-Pointer ist, liefere NULL zurück, andernfalls liefere eine Kopie von basis if (basis == NULL) return NULL; bigintmat *m = new bigintmat(basis); //wenn Fehler dann hier return m; } bigintmat *nforder::viewBasis() { if (basis == NULL) return NULL; return basis; } bool nforder::getMult(bigintmat **m) { // Falls multtable ein NULL-Pointer ist, liefere NULL zurück, andernfalls erzeuge neues Array of Matrix, kopiere die Matrizen aus multtable dort hinein, und gib es zurück if (multtable == NULL) { return false; } for (int i=0; ibaseorder) { ref_count_incref(); return this; } nforder * O = baseorder; number den = n_Copy(divisor, c); bigintmat *bas = getBasis(); while (O->baseorder) { bigintmat * b = bimMult(bas, O->viewBasis()); n_InpMult(den, O->divisor, c); O = O->baseorder; delete bas; bas = b; } nforder * res = new nforder(O, bas, den, c); if (discriminant) res->discriminant = n_Copy(discriminant, c); //TODO: copy multtable if we have it delete bas; n_Delete(&den, c); return res; } void nforder::elAdd(bigintmat *a, bigintmat *b) { if ((a->cols() != 1) || (a->rows() != dimension) || (b->cols() != 1) || (b->rows() != dimension)) { Werror("Error in elSub"); } else { a->add(b); } } void nforder::elSub(bigintmat *a, bigintmat *b) { if ((a->cols() != 1) || (a->rows() != dimension) || (b->cols() != 1) || (b->rows() != dimension)) { // Kein Zeilenvektor der korrekten Größe Werror("Error in elSub"); } else { a->sub(b); } } void nforder::elMult(bigintmat *a, bigintmat *b) { if ((a->cols() != 1) || (a->rows() != dimension) || (b->cols() != 1) || (b->rows() != dimension)) { // Kein Zeilenvektor der korrekten Größe Werror("Error in elMult"); } coeffs C = a->basecoeffs(); assume(C == b->basecoeffs()); assume(C == this->basecoeffs()); if (multtable != NULL) { // Multiplikation mit Hilfe von Multiplikationstabelle // Zu Grunde liegende Formel: Basis w_i; Für alpha = sum a_i*w_i und beta = sum b_i*w_i gilt: // alpha*beta = sum sum a_i*b_j*w_i*w_j bigintmat *sum = new bigintmat(dimension, 1, C); bigintmat *tmp = new bigintmat(dimension, 1, C); number ntmp; for (int i=1; i<=dimension; i++) { // Laufe mit i durch Basiselemente for (int j=1; j<=dimension; j++) { // Laufe mit j durch Basiselemente // Speichere Produkt von Basiselem. i mit Basiselem. j als Koeff.vektor in tmp multtable[i-1]->getcol(j, tmp); // Multipliziere ihn mit a[i] und b[j] ntmp = n_Mult(a->view(i, 1), b->view(j, 1), C); tmp->skalmult(ntmp, C); n_Delete(&ntmp, C); // und addiere alles auf sum->add(tmp); } } delete tmp; // Am Ende überschreibe a mit dem Ergebnis for (int i=0; iset(i+1, 1, sum->get(i+1, 1)); delete sum; } else { // Multiplikation mit hilfe von baseorder: bigintmat *sumb = new bigintmat(dimension, 1, C); // Produkt von a (b) mit basis liefert Koeff-Vektor von a*divisor (b*divisor) in baseorder bimMult(basis, a, a); bimMult(basis, b, sumb); // Multipliziere Elemente in baseorder (und speichere in suma) baseorder->elMult(a, sumb); delete sumb; a->skaldiv(divisor); bimMult(inv_basis, a, a); a->skaldiv(inv_divisor); a->skaldiv(divisor); } } //TODO: compute the trace from the mult-table without // the explicit rep_mat number nforder::elTrace(bigintmat *a) { bigintmat * rep_mat = elRepMat(a); number t = rep_mat->trace(); delete rep_mat; return t; } number nforder::elNorm(bigintmat *a) { bigintmat * rep_mat = elRepMat(a); number n = rep_mat->det(); delete rep_mat; return n; } bigintmat * nforder::elRepMat(bigintmat *a) { bigintmat *b=new bigintmat(dimension, dimension, basecoeffs()); multmap(a, b); return b; } //CF: TODO if multtable, then use lin. comb. of multtable //rather than poducts. reduces complexity by a magnitude. void nforder::multmap(bigintmat *a, bigintmat *m) { if ((m->cols() != dimension) || (m->rows() != dimension)) { Werror("Error in multmap"); return; } bigintmat *bas = new bigintmat(dimension, 1, basecoeffs()); for (int i=1; i<=dimension; i++) { // Durchläuft alle Basiselemente // Multipliziert i-tes Basiselement mit a basis_elt(bas, i); elMult(bas, a); // Schreibt Ergebnis in i-te Zeile der Matrix m. Am Ende ist m dann die Abbildungsmatrix der Multiplikation mit a m->setcol(i, bas); } delete bas; } /*________________1_______________ */ void basis_elt(bigintmat *m, int i) { if (((m->rows() == 1) && (i <= m->cols())) || ((m->cols() == 1) && (i <= m->rows()))) { // Falls m Zeilen- oder Spaltenvektor ist, setze alle Einträge auf 0 und Eintrag i auf 1 (Koeff-Vektor des i-ten Basiselements) number t1 = n_Init(0,m->basecoeffs()); for (int j=0; ((jrows()) || (jcols())); j++) { m->set(j, t1); } n_Delete(&t1,m->basecoeffs()); number t2 = n_Init(1,m->basecoeffs()); m->set(i-1, t2); n_Delete(&t2,m->basecoeffs()); } else Werror("Error in basis_elt. Not a vector."); } //////////////////////////////////// //////////// 2 Round 2 ///////////// //////////////////////////////////// //TODO: make the radical a proper ideal rather than a matrix // or at least, provide an ideal based interface // similar, expand the multring to deal with ideals bigintmat *radicalmodpbase(nforder *o, number p, coeffs c) { number dimen = n_Init(o->getDim(), o->basecoeffs()); int n = o->getDim(); bigintmat *m, *bas; // Berechnet F_p-Basis von I_p/pI_p (Radical mod p) // Dazu: if (n_Greater(p, dimen, c)) { // Falls Primzahl größer gleich Dimension der Ordnung, so berechne Kern der Spurmatrix modulo p. // also works it p is no prime. m = o->traceMatrix(); bas = new bigintmat(n, 1, o->basecoeffs()); } else { // Sonst: Berechne Kern der Abbildung x -> x^(p^j) mod p, wobei j>0 mit p^j >= dimension int j = 1; // ex als number, oder reicht long long int? // Finde j von oben und berechne p^j number ex = n_Init(1, o->basecoeffs()); number temp; while (n_Greater(dimen, ex, o->basecoeffs())) { temp = n_Mult(ex, p, o->basecoeffs()); n_Delete(&ex, o->basecoeffs()); ex = temp; j++; } // Berechne Abbildungsmatrix der oben genannten Abbildung und speichere diese in m (genauere Erklärung dazu: Siehe multmap()) m = new bigintmat(n, n, o->basecoeffs()); bas = new bigintmat(n, 1, o->basecoeffs()); bigintmat *prod = new bigintmat(n, 1, o->basecoeffs()); number klauf; number eins = n_Init(1, o->basecoeffs()); for (int i=1; i<=n; i++) { basis_elt(bas, i); prod->copy(bas); klauf = n_Init(1, o->basecoeffs()); for (; n_Greater(ex, klauf, o->basecoeffs());) { o->elMult(prod, bas); prod->mod(p); temp = n_Add(klauf, eins, o->basecoeffs()); n_Delete(&klauf, o->basecoeffs()); klauf = temp; } n_Delete(&klauf, o->basecoeffs()); m->setcol(i, prod); } delete prod; n_Delete(&ex, o->basecoeffs()); n_Delete(&eins, o->basecoeffs()); } bigintmat *kbase = new bigintmat(n, n, o->basecoeffs()); // Speichere Basiselemente von Kern der Matrix m (Spurmatrix oder Abbildungsmatrix, je nach if-else-Fall) (von Z/pZ -> Z/pZ) in kbase (ersten kdim Spalten bilden Basis) int kdim = kernbase(m, kbase, p, c); // Schreibe für jedes i=1,, .., dimension p*(i-tes Basiselement) als Spalten in Matrix gen, dahinter die oben errechnete Basis vom Kern // Wir erhalten (als Spalten) ein Erzeugendensystem vom Kern von Z->Z/pZ: x->x^(p^j) bigintmat *gen = new bigintmat(n, n+kdim, o->basecoeffs()); for (int i=1; i<=n; i++) { basis_elt(bas, i); bas->skalmult(p, c); gen->setcol(i, bas); } for (int i=1; i<=kdim; i++) { kbase->getcol(i, bas); gen->setcol(i+n, bas); } // HNF auf EZS anwenden liefert (als letzten dimension Spalten) eine Basis des Kerns gen->hnf(); bigintmat *tmp = new bigintmat(n, 1, o->basecoeffs()); bigintmat *nbase = new bigintmat(n, n, o->basecoeffs()); // Schreibe diese als Spalten in nbase und gib nbase zurück for (int i=1; i<=n; i++) { gen->getcol(gen->cols()-n+i, tmp); nbase->setcol(i, tmp); } n_Delete(&dimen, o->basecoeffs()); delete m; delete bas; delete kbase; delete gen; delete tmp; return nbase; } void rowhnf(bigintmat * b) { bigintmat * n = b->transpose(), *m; // for(int i=1; i<= n->rows() /2; i++) // n->swaprow(i, n->rows()-i+1); // TODO: needs probable more row&column swapping. n->hnf(); m = n->transpose(); b->copy(m); delete n; delete m; } #ifdef HAVE_RINGS number multring(bigintmat *nbase, nforder *o, number p) { coeffs R = o->basecoeffs(); number divi; int n = o->getDim(); bigintmat *inv = new bigintmat(n, n, R); divi = nbase->pseudoinv(inv); // Zusammenbau der "langen" Matrix bigintmat *lon = new bigintmat(n, 0, R); bigintmat *oldlon; bigintmat *mm = new bigintmat(n, n, R); bigintmat *temp = new bigintmat(n, 1, R); bigintmat *nochnetemp = new bigintmat(n, n, R); for (int i=1; i<=n; i++) { nbase->getcol(i, temp); o->multmap(temp, mm); bimMult(inv, mm, nochnetemp); mm->copy(nochnetemp); mm->inpTranspose(); oldlon = lon; lon = new bigintmat(n, (i)*n, o->basecoeffs()); lon->concatcol(oldlon, mm); delete oldlon; } lon->skaldiv(divi); bigintmat * red; if (1) { bigintmat * cmp = lon->modhnf(p, o->basecoeffs()); red = cmp; } else { lon->hnf(); red = new bigintmat(n, n, o->basecoeffs()); lon->getColRange((n-1)*n+1, n, red); } delete lon; red->inpTranspose(); number divisor = red->pseudoinv(nbase); nbase->hnf(); delete inv; delete mm; delete temp; delete red; delete nochnetemp; n_Delete(&divi, o->basecoeffs()); return divisor; } #endif #ifdef HAVE_RINGS nforder *onestep(nforder *o, number p, coeffs c) { // Berechne F_p-Basis von I_p/pI_p bigintmat *basis; basis = radicalmodpbase(o, p, c); // Bestimme Basis vom Ring der Multiplikatoren (speicher diese in basis), und Nenner davon (in divisor) number divisor = multring(basis, o, p); // Erzeuge neue Ordnung, der o zu Grunde liegt, mit Basis basis und Nenner divisor if (basis->isOne() && n_IsOne(divisor, c)) { delete basis; n_Delete(&divisor, c); return o; } nforder *no = new nforder(o, basis, divisor, c); delete basis; n_Delete(&divisor, c); return no; } #endif #ifdef HAVE_RINGS nforder *pmaximal(nforder *o, number p) { coeffs c = o->basecoeffs(); nforder *no = o; nforder *otemp; // TODO: check if p^2 still divides disc (maybe in onestep) // simplify the tower do { otemp = no; no = onestep(otemp, p, c); if (no==otemp) break; nforder_delete (otemp); otemp = no->simplify(); nforder_delete (no); no = otemp; } while (1); return no; } #endif /* // Zum Round2 fehlt noch die Faktorisierung der Diskriminante. Daher auch noch nicht getestet nforder *round2(nforder *o) { nforder *otemp = new nforder(o,basecoeffs()); number p = otemp->getsmallestsqprime(); // Benötigt kleinste Primzahl, die die Disc. quadratisch teilt nforder *no; number eins = n_Init(1, basecoeffs()); number tmp; while (n_GreaterZero(p,basecoeffs())) { // Laufe durch Primzahlen p, die die Ordnung quadratisch teilen, und erzeuge p-maximale Ordnung no = pmaximal(otemp, p); delete otemp; otemp = no; // Nimm nächstgrößere Primzahl, welche die Ordnung quadratisch teilt tmp = n_Add(p,eins, basecoeffs()); p = otemp->getsmallestsqprime(tmp); // Benötigt kleinste Primzahl größer tmp, die die Disc. quad. teilt n_Delete(&tmp, basecoeffs()); } n_Delete(&p, basecoeffs()); n_Delete(&eins, basecoeffs()); return otemp; } */ void nforder::createmulttable(bigintmat **a) { // Falls es eine Multtable gibt, liefere eine Kopie davon zurück if (multtable != NULL) { for (int i=0; i= p, die die Diskriminante quadratisch teilt */ void multmap(bigintmat *a, bigintmat *m); bigintmat *traceMatrix(); void createmulttable(bigintmat **a); }; //////////////////////////////////// ////// 1 Komfortfunktionen ///////// //////////////////////////////////// /* Setzt Vektor m auf (0,...,0,1,0,...,0) (i-ten Basisvektor) */ void basis_elt(bigintmat *m, int i); //////////////////////////////////// //////////// 2 Round 2 ///////////// //////////////////////////////////// /* Liefert bzgl. Primzahl p um eines größere Ordnung von o zurück */ nforder *onestep(nforder *o, number p, coeffs c); /* Macht liefert p-maximale Ordnung von o zurück */ nforder *pmaximal(nforder *o, number p); /* Liefert Maximalordnung, ausgehend von o, zurück */ nforder *round2(nforder *o); // Benötigt Faktorisierung der Diskriminanten /* Liefert Basis von I_p(O)/pI_p(O) */ bigintmat *radicalmodpbase(nforder *o, number p, coeffs c); /* Berechnet die Basis mit Hilfe der langen Matrix */ number multring(bigintmat* nbase, nforder *o, number p); void nforder_delete(nforder *o); #endif singular-4.0.3+ds/Singular/dyn_modules/Order/nforder_elt.cc000066400000000000000000000143521266270727000237550ustar00rootroot00000000000000#include "kernel/mod2.h" // general settings/macros //#include"kernel/febase.h" // for Print, WerrorS #include"Singular/ipid.h" // for SModulFunctions, leftv #include"Singular/number2.h" // for SModulFunctions, leftv #include // nRegister, coeffs.h #include #include"Singular/blackbox.h" // blackbox type #include "nforder.h" #include extern n_coeffType nforder_type; static void WriteRing(const coeffs r, BOOLEAN details) { ((nforder *)r->data)->Print(); } static char* CoeffString(const coeffs r) { return ((nforder *)r->data)->String(); } static void EltWrite(number a, const coeffs r) { bigintmat * b = (bigintmat*)a; if (a) { bigintmat * c = b->transpose(); c->Write(); StringAppendS("^t "); } else { StringAppendS("(Null)\n"); } } number EltCreateMat(nforder *a, bigintmat *b) { number xx; if (b->rows()==1) { assume(b->cols()==a->getDim()); xx = (number) b->transpose(); } else { assume(b->rows() == a->getDim()); assume(b->cols() == 1); xx = (number) new bigintmat((bigintmat*)b); } // Print("Created new element %lx from %lx\n", xx, b); return (number) xx; } static BOOLEAN order_cmp(coeffs n, n_coeffType t, void*parameter) { return (t==nforder_type) && (n->data == parameter); } static void KillChar(coeffs r) { Print("KillChar %lx\n", r); } #ifdef LDEBUG BOOLEAN EltDBTest(number, const char *, const int, const coeffs) { return TRUE; } #endif static void SetChar(const coeffs r) { Print("%s called\n", __func__); } // or NULL // general stuff static number EltMult(number a, number b, const coeffs r) { nforder *O = (nforder*) (r->data); bigintmat *c = new bigintmat((bigintmat*)a); O->elMult(c, (bigintmat*) b); return (number) c; } static number EltSub(number a, number b, const coeffs r) { nforder *O = (nforder*) (r->data); bigintmat *c = new bigintmat((bigintmat*)a); O->elSub(c, (bigintmat*) b); return (number) c; } static number EltAdd(number a, number b, const coeffs r) { nforder *O = (nforder*) (r->data); bigintmat *c = new bigintmat((bigintmat*)a); O->elAdd(c, (bigintmat*) b); return (number) c; } static number EltDiv(number a, number b, const coeffs r) { Werror("%s called\n", __func__, a, b, r); return NULL; } static number EltIntDiv(number a, number b, const coeffs r) { Werror("IntDiv called on order elts", a, b, r); return NULL; } static number EltIntMod(number a, number b, const coeffs r) { Werror("IntMod called on order elts", a, b, r); return NULL; } static number EltExactDiv(number a, number b, const coeffs r) { Werror("%s called\n", __func__, a, b, r); return NULL; } /// init with an integer static number EltInit(long i,const coeffs r) { nforder * O = (nforder*) r->data; if (!O) return NULL; //during init, this seems to be called with O==NULL coeffs C = O->basecoeffs(); bigintmat * b = new bigintmat(O->getDim(), 1, C); if (O->oneIsOne()) { basis_elt(b, 1); number I = n_Init(i, C); b->skalmult(I, C); n_Delete(&I, C); return (number) b; } else return NULL; } /// init with a GMP integer static number EltInitMPZ(mpz_t i, const coeffs r) { Werror("%s called\n", __func__); return NULL; } /// how complicated, (0) => 0, or positive static int EltSize(number n, const coeffs r) { Werror("%s called\n", __func__); return NULL; } /// convertion to int, 0 if impossible static long EltInt(number &n, const coeffs r) { Werror("%s called\n", __func__); return NULL; } /// Converts a non-negative number n into a GMP number, 0 if impossible static void EltMPZ(mpz_t result, number &n, const coeffs r) { Werror("%s called\n", __func__); } /// changes argument inline: a:= -a /// return -a! (no copy is returned) /// the result should be assigned to the original argument: e.g. a = n_Neg(a,r) static number EltNeg(number a, const coeffs r) /// return -a { Werror("%s called\n", __func__); return NULL; } static number EltInvers(number a, const coeffs r) /// return 1/a { Werror("%s called\n", __func__); return NULL; } static number EltCopy(number a, const coeffs r) { return EltCreateMat((nforder*)r->data, (bigintmat*)a); } static const char * EltRead(const char * s, number * a, const coeffs r) { // Print("%s called with ->%s-<\n", __func__, s); return s; } static BOOLEAN EltEqual(number a,number b, const coeffs r) { Print("%s called\n", __func__, a, b, r); return 0; } static BOOLEAN EltGreater(number a,number b, const coeffs r) { Print("%s called\n", __func__, a, b, r); return 0; } static BOOLEAN EltIsOne(number a, const coeffs r) { // Print("%s called\n", __func__, a, r); return 0; } static BOOLEAN EltIsMOne(number a, const coeffs r) { // Print("%s called\n", __func__, a, r); return 0; } static BOOLEAN EltGreaterZero(number a, const coeffs r) { // Print("%s called\n", __func__, a, r); return 1; } static BOOLEAN EltIsZero(number a, const coeffs r) { return (a==NULL) || ((bigintmat*)a)->isZero(); } static nMapFunc EltSetMap(const coeffs src, const coeffs dst) { Print("%s called\n", __func__, src, dst); return NULL; } static void EltDelete(number * a, const coeffs r) { // Print("Deleting %lx\n%s\n", *a, (((bigintmat*)(*a))->String())); delete (bigintmat*)(*a); *a = NULL; } BOOLEAN n_nfOrderInit(coeffs r, void * parameter) { assume( getCoeffType(r) == nforder_type ); r->nCoeffIsEqual=order_cmp; r->cfKillChar = KillChar; r->cfSetChar = SetChar; r->cfCoeffString=CoeffString; r->cfCoeffWrite=WriteRing; r->cfWriteShort=EltWrite; r->cfInit = EltInit; r->cfMult = EltMult; r->cfSub = EltSub; r->cfAdd = EltAdd; r->cfDiv = EltDiv; r->cfExactDiv = EltExactDiv; r->cfInitMPZ = EltInitMPZ; r->cfSize = EltSize; r->cfInt = EltInt; r->cfMPZ = EltMPZ; r->cfInpNeg = EltNeg; r->cfInvers = EltInvers; r->cfCopy = EltCopy; r->data = parameter; r->cfWriteLong = EltWrite; r->cfRead =EltRead; r->cfGreater = EltGreater; r->cfEqual = EltEqual; r->cfIsZero = EltIsZero; r->cfIsOne = EltIsOne; r->cfIsMOne = EltIsMOne; r->cfGreaterZero = EltGreaterZero; r->cfDelete = EltDelete; r->cfSetMap = EltSetMap; if (parameter) r->nNULL = EltInit(0, r); #ifdef LDEBUG r->cfDBTest = EltDBTest; #endif return FALSE; } singular-4.0.3+ds/Singular/dyn_modules/Order/nforder_elt.h000066400000000000000000000002771266270727000236200ustar00rootroot00000000000000#ifndef NFORDER_ELT_HPP #define NFORDER_ELT_HPP extern n_coeffType nforder_type; number EltCreateMat(nforder *a, bigintmat *b); BOOLEAN n_nfOrderInit(coeffs r, void * parameter); #endif singular-4.0.3+ds/Singular/dyn_modules/Order/nforder_ideal.cc000066400000000000000000000166141266270727000242520ustar00rootroot00000000000000#include #include "nforder.h" #include #include #include #include "Singular/ipid.h" #include "nforder_ideal.h" //////////////////////////////////// //// Konstruktoren/Destruktoren //// //////////////////////////////////// /*________________0_______________*/ void nforder_ideal::init() { memset(this, 0, sizeof(nforder_ideal)); } nforder_ideal::nforder_ideal(bigintmat * _basis, const coeffs O) { init(); ord = O; basis = new bigintmat(_basis); } nforder_ideal::nforder_ideal(nforder_ideal *I, int) { init(); ord = I->ord; coeffs C = ((nforder *)ord->data)->basecoeffs(); basis = new bigintmat(I->basis); if (I->den) { den = n_Copy(I->den, C); } if (I->norm) { norm = n_Copy(I->norm, C); norm_den = n_Copy(I->norm_den, C); } if (I->min) { min = n_Copy(I->min, C); min_den = n_Copy(I->min_den, C); } } void nforder_ideal::Write() { coeffs C = ((nforder *)ord->data)->basecoeffs(); if (isFractional()) { StringAppendS("Fractional "); } StringAppend("Ideal with basis:\n"); basis->Write(); if (isFractional()) { number d; StringAppend(" / "); n_Write((d = viewBasisDen()), C); } StringAppendS("\n"); if (norm) { StringAppendS("and norm "); n_Write(norm, C); StringAppendS(" / "); n_Write(norm_den, C); StringAppendS(" "); } if (min) { StringAppendS("and min "); n_Write(min, C); StringAppendS(" / "); n_Write(min_den, C); StringAppendS(" "); } } char * nforder_ideal::String() { StringSetS(""); Write(); return StringEndS(); } void nforder_ideal::Print() { char * s = String(); PrintS(s); PrintS("\n"); omFree(s); } nforder_ideal::~nforder_ideal() { if (basis) delete basis; coeffs C = ((nforder *)ord->data)->basecoeffs(); if (den) n_Delete(&den, C); if (norm) { n_Delete(&norm, C); n_Delete(&norm_den, C); } if (min) { n_Delete(&min, C); n_Delete(&min_den, C); } } #ifdef HAVE_RINGS nforder_ideal * nf_idAdd(nforder_ideal *A, nforder_ideal *B) { assume(A->order() == B->order()); nforder * O = (nforder*) A->order()->data; coeffs C = O->basecoeffs(); bigintmat * r = new bigintmat(O->getDim(), 2*O->getDim(), C), *s1, *s2; number den = NULL; if (B->isFractional()) { s1 = A->getBasis(); s1->skalmult(B->viewBasisDen(), C); den = n_Copy(B->viewBasisDen(), C); } else { s1 = A->viewBasis(); } if (A->isFractional()) { s2 = B->getBasis(); s2->skalmult(A->viewBasisDen(), C); if (den) { number d = n_Mult(den, A->viewBasisDen(), C); n_Delete(&den, C); den = d; } else { den = n_Copy(A->viewBasisDen(), C); } } else { s2 = B->viewBasis(); } r->concatcol(s1, s2); if (A->isFractional()) delete s2; if (B->isFractional()) delete s1; number modA = NULL, modB = NULL; if (!(modA = A->viewMin())) { modA = A->viewNorm(); } if (!(modB = B->viewMin())) { modB = B->viewNorm(); } bigintmat *t2; if (modA && modB) { number mod = n_Gcd(modA, modB, C); t2 = r->modhnf(mod, C); n_Delete(&mod, C); } else { r->hnf(); t2 = new bigintmat(O->getDim(), O->getDim(), C); t2->copySubmatInto(r, 1, O->getDim()+1, O->getDim(), O->getDim(), 1,1); } delete r; if (den) { t2->simplifyContentDen(&den); } nforder_ideal *D = new nforder_ideal(t2, A->order()); if (den) D->setBasisDenTransfer(den); if (O->oneIsOne()) D->setMinTransfer(t2->get(1,1), den ? n_Copy(den, C) : n_Init(1, C)); D->setNormTransfer(t2->det(), den ? n_Copy(den, C) : n_Init(1, C)); delete t2; return D; } #endif #ifdef HAVE_RINGS nforder_ideal * nf_idMult(nforder_ideal *A, nforder_ideal *B) { assume(A->order() == B->order()); nforder * O = (nforder*) A->order()->data; coeffs C = O->basecoeffs(); number den = NULL; bigintmat * r= NULL; bigintmat * c = new bigintmat(O->getDim(), 1, C), *rep = new bigintmat(O->getDim(), O->getDim(), C); for(int i=0; igetDim(); i++) { A->viewBasis()->getcol(i+1, c); O->multmap(c, rep); bigintmat * cc = bimMult(rep, B->viewBasis()); if (r) { bigintmat * s = new bigintmat(O->getDim(), r->cols()+O->getDim(), C); s->concatcol(r, cc); delete r; delete cc; r = s; } else { r = cc; } } delete c; number modA = NULL, modB = NULL; if (!(modA = A->viewMin())) { modA = A->viewNorm(); } if (!(modB = B->viewMin())) { modB = B->viewNorm(); } bigintmat * t1; if (modA && modB) { number mod = n_Mult(modA, modB, C); t1 = r->modhnf(mod, C); n_Delete(&mod, C); } else { r->hnf(); t1 = new bigintmat(O->getDim(), O->getDim(), C); r->getColRange(r->cols()-O->getDim()+1, O->getDim(), t1); } delete r; if (A->isFractional()) { den = A->viewBasisDen(); } if (B->isFractional()) { if (den) den = n_Mult(den, B->viewBasisDen(), C); else den = n_Copy(B->viewBasisDen(), C); } if (den) { t1->simplifyContentDen(&den); } nforder_ideal *D = new nforder_ideal(t1, A->order()); if (den) D->setBasisDenTransfer(den); if (O->oneIsOne()) D->setMinTransfer(t1->get(1,1), den ? n_Copy(den, C) : n_Init(1, C)); D->setNormTransfer(t1->det(), den ? n_Copy(den, C) : n_Init(1, C)); delete t1; return D; } #endif nforder_ideal* nf_idMult(nforder_ideal * A, number b) { nforder * O = (nforder*) A->order()->data; coeffs C = O->basecoeffs(); bigintmat * r = O->elRepMat((bigintmat*) b); bigintmat * s = bimMult(r, A->viewBasis()); delete r; if (A->isFractional()) { number d = n_Copy(A->viewBasisDen(), C); s->simplifyContentDen(&d); nforder_ideal * res = new nforder_ideal(s, A->order()); res->setBasisDenTransfer(d); return res; } else { return new nforder_ideal(s, A->order()); } } nforder_ideal * nf_idInit(int i, coeffs O) { nforder *ord = (nforder*) O->data; coeffs C = ord->basecoeffs(); bigintmat * r = new bigintmat(ord->getDim(), ord->getDim(), C); r->one(); number I = n_Init(i, C); r->skalmult(I, C); nforder_ideal * A = new nforder_ideal(r, O); delete r; number n; n_Power(I, ord->getDim(), &n, C); A->setNormTransfer(n, n_Init(1, C)); A->setMinTransfer(I, n_Init(1, C)); return A; } nforder_ideal * nf_idInit(number I, coeffs O) { nforder *ord = (nforder*) O->data; bigintmat * r = ord->elRepMat((bigintmat*)I); nforder_ideal * A = new nforder_ideal(r, O); delete r; return A; } nforder_ideal* nf_idMult(nforder_ideal * A, int b) { nforder * O = (nforder*) A->order()->data; coeffs C = O->basecoeffs(); bigintmat * s = new bigintmat(A->viewBasis()); number bb = n_Init(b, C); s->skalmult(bb, C); n_Delete(&bb, C); if (A->isFractional()) { number d = n_Copy(A->viewBasisDen(), C); s->simplifyContentDen(&d); nforder_ideal * res = new nforder_ideal(s, A->order()); res->setBasisDenTransfer(d); return res; } else { return new nforder_ideal(s, A->order()); } } nforder_ideal* nf_idPower(nforder_ideal* A, int i) { if (i==0) { return nf_idInit(1, A->order()); } else if (i==1) { return new nforder_ideal(A, 1); } else if (i<0) { Werror("not done yet"); } else { nforder_ideal *B = nf_idPower(A, i/2); nforder_ideal *res = nf_idMult(B, B); delete B; if (i&1) { nforder_ideal * C = nf_idMult(res, B); delete res; return C; } else { return res; } } } singular-4.0.3+ds/Singular/dyn_modules/Order/nforder_ideal.h000066400000000000000000000047011266270727000241060ustar00rootroot00000000000000////////////////////////////////////////// ////////////////////////////////////////// //// ideals in oforder //////////// ////////////////////////////////////////// ////////////////////////////////////////// #ifndef NFORDER_IDEAL_HPP #define NFORDER_IDEAL_HPP #include class nforder_ideal { private: //////////////////////////////////// ////////// Membervariablen ///////// //////////////////////////////////// number norm, norm_den, min, min_den; coeffs ord; // but of dynamic type order! (as cring) bigintmat *basis; number den; // fractional ideals.... public: //////////////////////////////////// /// 0 Konstruktoren/Destruktoren /// //////////////////////////////////// nforder_ideal(); void init(); nforder_ideal(bigintmat *basis, number * min, number * min_den, number * norm, number * norm_den, const coeffs ord); nforder_ideal(bigintmat *basis, const coeffs q); nforder_ideal(nforder_ideal *i, int); ~nforder_ideal(); void Write(); char * String(); void Print(); //////////////////////////////////// // +1 Zugriff auf Membervariablen // //////////////////////////////////// number getNorm(), getNormDen(), getMin(), getMinDen(); inline coeffs order() const { return ord; } inline bigintmat * viewBasis() {return basis;}; inline bigintmat * getBasis() {return new bigintmat(basis);}; inline number viewBasisDen() {return den;}; inline int isFractional() {return den!=NULL;}; inline void setMinTransfer(number a, number b){min = a; min_den = b;} inline void setNormTransfer(number a, number b){norm = a; norm_den = b;} inline number viewNorm() { return norm;}; inline number viewMin() { return norm;}; inline void setBasisDenTransfer(number a){den = a;} //////////////////////////////////// ////// +2 Elementoperationen /////// //////////////////////////////////// // Addiert/Subtrahiert/Multipliziert zu a das Element b hinzu }; nforder_ideal* nf_idAdd(nforder_ideal *a, nforder_ideal *b); nforder_ideal* nf_idMult(nforder_ideal *a, nforder_ideal *b); nforder_ideal* nf_idMult(nforder_ideal *a, number b); nforder_ideal* nf_idMult(nforder_ideal *a, int b); nforder_ideal* nf_idPower(nforder_ideal *a, int b); nforder_ideal* nf_idInit(int, coeffs); nforder_ideal* nf_idInit(number, coeffs); nforder_ideal* nf_idDiv(nforder_ideal *a, nforder_ideal *b); nforder_ideal* nf_idMeet(nforder_ideal *a, nforder_ideal *b); #endif singular-4.0.3+ds/Singular/dyn_modules/Order/singular.cc000066400000000000000000000330751266270727000233010ustar00rootroot00000000000000#include "kernel/mod2.h" // general settings/macros #include "Singular/mod_lib.h" //#include"kernel/febase.h" // for Print, WerrorS #include"Singular/ipid.h" // for SModulFunctions, leftv #include"Singular/number2.h" // for SModulFunctions, leftv #include // nRegister, coeffs.h #include #include"Singular/blackbox.h" // blackbox type #include "nforder.h" #include "nforder_elt.h" #include "nforder_ideal.h" #include #ifdef SINGULAR_4_1 static int nforder_type_id=0; n_coeffType nforder_type =n_unknown; // coeffs stuff: ----------------------------------------------------------- static coeffs nforder_AE=NULL; static void nforder_Register() { puts("nforder_Register called"); nforder_type=nRegister(n_unknown,n_nfOrderInit); nforder_AE=nInitChar(nforder_type,NULL); } // black box stuff: --------------------------------------------------------- static void * nforder_ideal_Init(blackbox */*b*/) { nforder_AE->ref++; return nforder_AE; } static char * nforder_ideal_String(blackbox *b, void *d) { StringSetS(""); if (d) ((nforder_ideal *)d)->Write(); else StringAppendS("o not defined o"); return StringEndS(); } static void * nforder_ideal_Copy(blackbox* /*b*/, void *d) { return new nforder_ideal((nforder_ideal*)d, 1);} static BOOLEAN nforder_ideal_Assign(leftv l, leftv r) { if (l->Typ()==r->Typ()) { if (l->rtyp==IDHDL) { IDDATA((idhdl)l->data)=(char *)nforder_ideal_Copy((blackbox*)NULL, r->data); } else { l->data=(char *)nforder_ideal_Copy((blackbox*)NULL, r->data); } return FALSE; } return TRUE; } static void nforder_ideal_destroy(blackbox * /*b*/, void *d) { if (d!=NULL) { delete (nforder_ideal*)d; } } BOOLEAN checkArgumentIsOrder(leftv arg, nforder * cmp, nforder ** result) { if (arg->Typ() != CRING_CMD) return FALSE; coeffs R = (coeffs) arg->Data(); if (getCoeffType(R) != nforder_type) return FALSE; nforder * O = (nforder*) R->data; if (cmp && cmp != O) return FALSE; *result = O; return TRUE; } BOOLEAN checkArgumentIsBigintmat(leftv arg, coeffs r, bigintmat ** result) { if (arg->Typ() != BIGINTMAT_CMD) return FALSE; bigintmat * b = (bigintmat*) arg->Data(); if (r && b->basecoeffs() != r) return FALSE; *result = b; return TRUE; } BOOLEAN checkArgumentIsNumber2(leftv arg, coeffs r, number2 * result) { if (arg->Typ() != CNUMBER_CMD) return FALSE; number2 b = (number2) arg->Data(); if (r && b->cf != r) return FALSE; *result = b; return TRUE; } BOOLEAN checkArgumentIsNFOrderIdeal(leftv arg, coeffs r, nforder_ideal ** result) { if (arg->Typ() != nforder_type_id) return FALSE; *result = (nforder_ideal *) arg->Data(); if (r && (*result)->order() != r) return FALSE; return TRUE; } BOOLEAN checkArgumentIsInt(leftv arg, int* result) { if (arg->Typ() != INT_CMD) return FALSE; *result = (long) arg->Data(); return TRUE; } BOOLEAN checkArgumentIsBigint(leftv arg, number* result) { switch (arg->Typ()) { case BIGINT_CMD: *result = (number)arg->Data(); return TRUE; break; case NUMBER_CMD: if (currRing->cf == coeffs_BIGINT && getCoeffType(coeffs_BIGINT) == n_Z) { *result = (number)arg->Data(); return TRUE; } else return FALSE; break; case CNUMBER_CMD: { number2 n = (number2)arg->Data(); if (getCoeffType(n->cf) == n_Z) { *result = n->n; return TRUE; } return FALSE; break; } default: return FALSE; } } static BOOLEAN nforder_ideal_Op2(int op,leftv l, leftv r1, leftv r2) { Print("Types are %d %d\n", r1->Typ(), r2->Typ()); number2 e; int f; nforder_ideal *I, *J, *H; switch (op) { case '+': { if (!checkArgumentIsNFOrderIdeal(r1, NULL, &I)) return TRUE; if (!checkArgumentIsNFOrderIdeal(r2, I->order(), &J)) return TRUE; H = nf_idAdd(I, J); break; } case '*': { if (!checkArgumentIsNFOrderIdeal(r1, NULL, &I)) { leftv r = r1; r1 = r2; r2 = r; //at least ONE argument has to be an ideal } if (!checkArgumentIsNFOrderIdeal(r1, NULL, &I)) return TRUE; if (checkArgumentIsNFOrderIdeal(r2, I->order(), &J)) { H = nf_idMult(I, J); } else if (checkArgumentIsNumber2(r2, I->order(), &e)) { H = nf_idMult(I, e->n); } else if (checkArgumentIsInt(r2, &f)) { H = nf_idMult(I, f); } else return TRUE; break; } case '^': { if (!checkArgumentIsNFOrderIdeal(r1, NULL, &I)) return TRUE; if (!checkArgumentIsInt(r2, &f)) return TRUE; H = nf_idPower(I, f); break; } default: return TRUE; } l->rtyp = nforder_type_id; l->data = (void*)H; return FALSE; } static BOOLEAN nforder_ideal_bb_setup() { blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox)); // all undefined entries will be set to default in setBlackboxStuff // the default Print is quite useful, // all other are simply error messages b->blackbox_destroy=nforder_ideal_destroy; b->blackbox_String=nforder_ideal_String; //b->blackbox_Print=blackbox_default_Print; b->blackbox_Init=nforder_ideal_Init; b->blackbox_Copy=nforder_ideal_Copy; b->blackbox_Assign=nforder_ideal_Assign; //b->blackbox_Op1=blackbox_default_Op1; b->blackbox_Op2=nforder_ideal_Op2; //b->blackbox_Op3=blackbox_default_Op3; //b->blackbox_OpM=blackbox_default_OpM; nforder_type_id = setBlackboxStuff(b,"NFOrderIdeal"); Print("setup: created a blackbox type [%d] '%s'",nforder_type_id, getBlackboxName(nforder_type_id)); PrintLn(); return FALSE; // ok, TRUE = error! } // module stuff: ------------------------------------------------------------ BOOLEAN checkBigintmatDim(bigintmat * b, int r, int c) { if (b->rows() != r) return FALSE; if (b->cols() != c) return FALSE; return TRUE; } #define returnNumber(_res, _n, _R) \ do { \ number2 _r = (number2)omAlloc(sizeof(struct snumber2)); \ _r->n = _n; \ _r->cf = _R; \ _res->rtyp = CNUMBER_CMD; \ _res->data = _r; \ } while (0) static BOOLEAN build_ring(leftv result, leftv arg) { nforder *o; if (arg->Typ() == LIST_CMD) { lists L = (lists)arg->Data(); int n = lSize(L)+1; bigintmat **multtable = (bigintmat**)omAlloc(n*sizeof(bigintmat*)); for(int i=0; im[i].Data()); } o = new nforder(n, multtable, nInitChar(n_Z, 0)); omFree(multtable); } else { assume(arg->Typ() == INT_CMD); int dimension = (int)(long)arg->Data(); bigintmat **multtable = (bigintmat**)omAlloc(dimension*sizeof(bigintmat*)); arg = arg->next; for (int i=0; iData()); arg = arg->next; } o = new nforder(dimension, multtable, nInitChar(n_Z, 0)); for (int i=0; irtyp=CRING_CMD; // set the result type result->data=(char*)nInitChar(nforder_type, o);// set the result data return FALSE; } static BOOLEAN ideal_from_mat(leftv result, leftv arg) { nforder * O; if (!checkArgumentIsOrder(arg, NULL, &O)) { WerrorS("usage: IdealFromMat(order, basis matrix)"); return TRUE; } arg = arg->next; bigintmat *b; if (!checkArgumentIsBigintmat(arg, O->basecoeffs(), &b)) { WerrorS("3:usage: IdealFromMat(order, basis matrix)"); return TRUE; } result->rtyp = nforder_type_id; result->data = new nforder_ideal(b, nInitChar(nforder_type, O)); return FALSE; } static BOOLEAN elt_from_mat(leftv result, leftv arg) { nforder * O; if (!checkArgumentIsOrder(arg, NULL, &O)) { WerrorS("usage: EltFromMat(order, matrix)"); return TRUE; } arg = arg->next; bigintmat *b; if (!checkArgumentIsBigintmat(arg, O->basecoeffs(), &b)) { WerrorS("2:usage: EltFromMat(order, matrix)"); return TRUE; } returnNumber(result, (number)EltCreateMat(O, b), nInitChar(nforder_type, O)); return FALSE; } static BOOLEAN discriminant(leftv result, leftv arg) { nforder * O; if (!checkArgumentIsOrder(arg, NULL, &O)) { WerrorS("usage: Discriminant(order)"); return TRUE; } O->calcdisc(); returnNumber(result, O->getDisc(), O->basecoeffs()); return FALSE; } static BOOLEAN pMaximalOrder(leftv result, leftv arg) { nforder * o; if (!checkArgumentIsOrder(arg, NULL, &o)) { WerrorS("usage: pMaximalOrder(order, int)"); return TRUE; } arg = arg->next; long p = (int)(long)arg->Data(); number P = n_Init(p, o->basecoeffs()); nforder *op = pmaximal(o, P); result->rtyp=CRING_CMD; // set the result type result->data=(char*)nInitChar(nforder_type, op);// set the result data assume(result->data); return FALSE; } static BOOLEAN oneStep(leftv result, leftv arg) { assume (arg->Typ()==CRING_CMD); coeffs c = (coeffs)arg->Data(); assume (c->type == nforder_type); nforder * o = (nforder*)c->data; arg = arg->next; long p = (int)(long)arg->Data(); number P = n_Init(p, o->basecoeffs()); nforder *op = onestep(o, P, o->basecoeffs()); result->rtyp=CRING_CMD; // set the result type result->data=(char*)nInitChar(nforder_type, op);// set the result data return FALSE; } static BOOLEAN nforder_simplify(leftv result, leftv arg) { nforder * o; if (!checkArgumentIsOrder(arg, NULL, &o)) { WerrorS("usage: NFOrderSimplify(order)"); return TRUE; } nforder *op = o->simplify(); result->rtyp=CRING_CMD; // set the result type result->data=(char*)nInitChar(nforder_type, op);// set the result data return FALSE; } static BOOLEAN eltTrace(leftv result, leftv arg) { number2 a; if (!checkArgumentIsNumber2(arg, NULL, &a)) { WerrorS("EltTrace(elt)"); return TRUE; } coeffs c = a->cf; if (getCoeffType(c) != nforder_type) { WerrorS("EltTrace(elt in order)"); return TRUE; } bigintmat * aa = (bigintmat*)a->n; nforder * o = (nforder*)c->data; number t = o->elTrace(aa); returnNumber(result, t, o->basecoeffs()); return FALSE; } static BOOLEAN eltNorm(leftv result, leftv arg) { number2 a; if (!checkArgumentIsNumber2(arg, NULL, &a)) { WerrorS("EltNorm(elt)"); return TRUE; } coeffs c = a->cf; if (getCoeffType(c) != nforder_type) { WerrorS("EltNorm(elt in order)"); return TRUE; } bigintmat * aa = (bigintmat*)a->n; nforder * o = (nforder*)c->data; number t = o->elNorm(aa); returnNumber(result, t, o->basecoeffs()); return FALSE; } static BOOLEAN eltRepMat(leftv result, leftv arg) { assume (arg->Typ()==CNUMBER_CMD); number2 a = (number2) arg->Data(); coeffs c = a->cf; bigintmat * aa = (bigintmat*)a->n; assume (c->type == nforder_type); nforder * o = (nforder*)c->data; bigintmat* t = o->elRepMat(aa); result->rtyp = BIGINTMAT_CMD; result->data = t; return FALSE; } static BOOLEAN smithtest(leftv result, leftv arg) { assume (arg->Typ()==BIGINTMAT_CMD); bigintmat *a = (bigintmat *) arg->Data(); arg = arg->next; long p = (int)(long)arg->Data(); number P = n_Init(p, a->basecoeffs()); bigintmat * A, *B; diagonalForm(a, &A, &B); result->rtyp = NONE; return FALSE; } extern "C" int SI_MOD_INIT(Order)(SModulFunctions* psModulFunctions) { nforder_Register(); nforder_ideal_bb_setup(); psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""),// the library name, "nfOrder",// the name for the singular interpreter FALSE, // should not be static build_ring); // the C/C++ routine psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""),// the library name, "pMaximalOrder",// the name for the singular interpreter FALSE, // should not be static pMaximalOrder); // the C/C++ routine psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""),// the library name, "oneStep",// the name for the singular interpreter FALSE, // should not be static oneStep); // the C/C++ routine psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""), "Discriminant", FALSE, discriminant); psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""), "EltFromMat", FALSE, elt_from_mat); psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""), "NFOrderSimplify", FALSE, nforder_simplify); psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""), "EltNorm", FALSE, eltNorm); psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""), "EltTrace", FALSE, eltTrace); psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""), "EltRepMat", FALSE, eltRepMat); psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""), "SmithTest", FALSE, smithtest); psModulFunctions->iiAddCproc( (currPack->libname? currPack->libname: ""), "IdealFromMat", FALSE, ideal_from_mat); module_help_main( (currPack->libname? currPack->libname: "NFOrder"),// the library name, "nforder: orders in number fields"); // the help string for the module return MAX_TOK; } #endif singular-4.0.3+ds/Singular/dyn_modules/bigintm/000077500000000000000000000000001266270727000215145ustar00rootroot00000000000000singular-4.0.3+ds/Singular/dyn_modules/bigintm/Makefile.am000066400000000000000000000025501266270727000235520ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../../m4 if SI_BUILTIN_BIGINTM noinst_LTLIBRARIES=bigintm.la # check_LTLIBRARIES=bigintm.la P_PROCS_CPPFLAGS_COMMON = -DSTATIC_VERSION P_PROCS_MODULE_LDFLAGS = -module else module_LTLIBRARIES=bigintm.la moduledir = $(libexecdir)/singular/MOD P_PROCS_CPPFLAGS_COMMON = -DDYNAMIC_VERSION P_PROCS_MODULE_LDFLAGS = -module -export-dynamic -avoid-version -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup # Add under Mac OS X: -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup endif MYINCLUDES = -I${top_srcdir} -I${top_builddir} \ -I${top_srcdir}/libpolys -I${top_builddir}/libpolys \ $(FACTORY_INCLUDES) $(RESOURCES_INCLUDES) $(OMALLOC_INCLUDES) \ $(FLINT_CFLAGS) $(NTL_CFLAGS) $(GMP_CFLAGS) bigintm_la_SOURCES = mod_main.cc bigintm.cc bigintm.h bigintm_la_CPPFLAGS = ${MYINCLUDES} ${P_PROCS_CPPFLAGS_COMMON} bigintm_la_LDFLAGS = ${P_PROCS_MODULE_LDFLAGS} # AM_COLOR_TESTS=always # # TESTS_ENVIRONMENT = SINGULARPATH='${abs_top_builddir}/Singular/LIB:${abs_top_srcdir}/Singular/LIB:${abs_top_builddir}/libpolys/polys/.libs:${abs_top_builddir}/factory/gftables:${abs_builddir}/.libs:${abs_srcdir}' # TESTS_ENVIRONMENT += SINGULAR_ROOT_DIR='${abs_top_builddir}' # TESTS_ENVIRONMENT += SINGULAR_BIN_DIR='${abs_top_builddir}/Singular' # # TESTS=test_release.sh # # EXTRA_DIST = test.sh $(TESTS) singular-4.0.3+ds/Singular/dyn_modules/bigintm/bigintm.cc000066400000000000000000000164241266270727000234630ustar00rootroot00000000000000 #include #include #include #include #include #include #include #include #include // extern coeffs coeffs_BIGINT #include "bigintm.h" #define HAVE_BIGINTM 1 namespace { #ifdef HAVE_BIGINTM static int bigintm_type_id = -1; #endif #ifdef HAVE_BIGINTM static char * bigintm_String(blackbox */*b*/, void *d) { if (d==NULL) return omStrDup("oo"); else { StringSetS(""); number n=(number)d; n_Write(n, coeffs_BIGINT); d=(void*)n; return StringEndS(); } } static void * bigintm_Copy(blackbox*/*b*/, void *d) { number n=(number)d; return n_Copy(n, coeffs_BIGINT); } static BOOLEAN bigintm_Assign(leftv l, leftv r) { assume( l->Typ() == bigintm_type_id ); // blackbox *ll=getBlackboxStuff(l->Typ()); if (r->Typ()>MAX_TOK) { if (bigintm_type_id == r->Typ()) { // blackbox *rr=getBlackboxStuff(r->Typ()); if (l->Data()!=NULL) { number n1=(number)l->Data(); n_Delete(&n1,coeffs_BIGINT); } number n2=(number)r->CopyD(); if (l->rtyp==IDHDL) { IDDATA((idhdl)l->data)=(char *)n2; } else { l->data=(void *)n2; } return FALSE; } else { Werror("bigintm_Assign: assign %s (%d) = %s (%d)", getBlackboxName(l->Typ()), l->Typ(), getBlackboxName(r->Typ()), r->Typ()); return TRUE; } } else if (r->Typ()==INT_CMD) { if (l->Data()!=NULL) { number n1=(number)l->Data(); n_Delete(&n1,coeffs_BIGINT); } number n2=n_Init((int)(long)r->Data(),coeffs_BIGINT); if (l->rtyp==IDHDL) { IDDATA((idhdl)l->data)=(char *)n2; } else { l->data=(void *)n2; } return FALSE; } else Werror("assign %d = %d",l->Typ(),r->Typ()); return TRUE; } BOOLEAN bigintm_Op1(int op,leftv l, leftv r) { // interpreter: a1 is ist bigintm assume( r->Typ() == bigintm_type_id ); /* // "typeof( )" is handled by 'blackboxDefaultOp1' if (op==TYPEOF_CMD) { l->data=omStrDup(getBlackboxName(r->Typ())); l->rtyp=STRING_CMD; return FALSE; } */ return blackboxDefaultOp1(op, l, r); } static BOOLEAN bigintm_OpM(int op, leftv res, leftv args); static BOOLEAN bigintm_Op2(int op, leftv res, leftv a1, leftv a2) { // interpreter: a1 is ist bigintm assume( a1->Typ() == bigintm_type_id ); // blackbox *a=getBlackboxStuff(a1->Typ()); number n1=(number)a1->Data(); switch(op) { case '+': { if (a2->Typ()==INT_CMD) { number n2=n_Init((int)(long)a2->Data(), coeffs_BIGINT); number n=n_Add(n1,n2, coeffs_BIGINT); res->data=(void *)n; res->rtyp=a1->Typ(); return FALSE; } else if (a2->Typ()==a1->Typ()) { number n2=(number)a2->Data(); number n=n_Add(n1,n2, coeffs_BIGINT); res->data=(void *)n; res->rtyp=a1->Typ(); return FALSE; } Werror("bigintm_Op2: Op: '+': Sorry unsupported 2nd argument-type: %s in", Tok2Cmdname(a2->Typ())); return TRUE; } case '-': { if (a2->Typ()==INT_CMD) { number n2=n_Init((int)(long)a2->Data(),coeffs_BIGINT); number n=n_Sub(n1,n2, coeffs_BIGINT); res->data=(void *)n; res->rtyp=a1->Typ(); return FALSE; } else if (a2->Typ()==a1->Typ()) { number n2=(number)a2->Data(); number n=n_Sub(n1,n2, coeffs_BIGINT); res->data=(void *)n; res->rtyp=a1->Typ(); return FALSE; } Werror("bigintm_Op2: Op: '-': Sorry unsupported 2nd argument-type: %s in", Tok2Cmdname(a2->Typ())); return TRUE; } case '*': { if (a2->Typ()==INT_CMD) { number n2=n_Init((int)(long)a2->Data(), coeffs_BIGINT); number n=n_Mult(n1,n2, coeffs_BIGINT); res->data=(void *)n; res->rtyp=a1->Typ(); return FALSE; } else if (a2->Typ()==a1->Typ()) { number n2=(number)a2->Data(); number n=n_Mult(n1,n2, coeffs_BIGINT); res->data=(void *)n; res->rtyp=a1->Typ(); return FALSE; } Werror("bigintm_Op2: Op: '*': Sorry unsupported 2nd argument-type: '%s' in", Tok2Cmdname(a2->Typ())); return TRUE; } case EQUAL_EQUAL: { if( a1 == a2) { res->data= (void *) (TRUE); res->rtyp= INT_CMD; return FALSE; } else if (a2->Typ()==INT_CMD) { number n2=n_Init((int)(long)a2->Data(), coeffs_BIGINT); res->data=(void *) (long) n_Equal(n1,n2, coeffs_BIGINT); res->rtyp= INT_CMD; n_Delete(&n2,coeffs_BIGINT); return FALSE; } else if (a2->Typ()==a1->Typ()) { number n2=(number)a2->Data(); res->data=(void *) (long) n_Equal(n1,n2, coeffs_BIGINT); res->rtyp= INT_CMD; return FALSE; } Werror("bigintm_Op2: Op: '==': Sorry unsupported 2nd argument-type: '%s' in", Tok2Cmdname(a2->Typ())); return TRUE; } case '.': { if (a2->name==NULL) { Werror("bigintm_Op2: Op: '.': 2nd argument-type: '%s'(%d) should be a NAME", Tok2Cmdname(a2->Typ()), a2->Typ()); return TRUE; } Werror("bigintm_Op2: Op: '.': 2nd argument-type: '%s'(%d) is called '%s' in ", Tok2Cmdname(a2->Typ()), a2->Typ(), a2->name); return TRUE; } default: return blackboxDefaultOp2(op,res,a1,a2); } } // BOOLEAN opM(int op, leftv res, leftv args) static BOOLEAN bigintm_OpM(int op, leftv res, leftv args) { // interpreter: args->1. arg is ist bigintm assume( args->Typ() == bigintm_type_id ); blackbox *a=getBlackboxStuff(args->Typ()); switch(op) { case STRING_CMD: { res->data=(void *)a->blackbox_String(a,args->Data()); res->rtyp=STRING_CMD; return FALSE; } default: return blackboxDefaultOpM(op, res, args); } return blackboxDefaultOpM(op, res, args); } static void bigintm_destroy(blackbox */*b*/, void *d) { if (d!=NULL) { number n=(number)d; n_Delete(&n, coeffs_BIGINT); } } #endif } // this is only a demo BOOLEAN bigintm_setup() { #ifndef HAVE_BIGINTM Werror("bigintm_setup: Sorry BIGINTM was not compiled in!"); return TRUE; // ok, TRUE = error! #else if( bigintm_type_id == -1 ) { blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox)); // all undefined entries will be set to default in setBlackboxStuff // the default Print is quite usefule, // all other are simply error messages b->blackbox_destroy=bigintm_destroy; b->blackbox_String=bigintm_String; //b->blackbox_Print=blackbox_default_Print; //b->blackbox_Init=blackbox_default_Init; b->blackbox_Copy=bigintm_Copy; b->blackbox_Assign=bigintm_Assign; // TO ASK: no default?! b->blackbox_Op1=bigintm_Op1; b->blackbox_Op2=bigintm_Op2; //b->blackbox_Op3=blackboxDefaultOp3; b->blackbox_OpM=bigintm_OpM; bigintm_type_id = setBlackboxStuff(b,"bigintm"); Print("bigintm_setup: created a blackbox type [%d] '%s'",bigintm_type_id, getBlackboxName(bigintm_type_id)); PrintLn(); return FALSE; // ok, TRUE = error! } else { Werror("bigintm_setup: Sorry should NOT be run twice!"); return TRUE; // ok, TRUE = error! } #endif } singular-4.0.3+ds/Singular/dyn_modules/bigintm/bigintm.h000066400000000000000000000001061266270727000233130ustar00rootroot00000000000000#ifndef BIGINTM_H #define BIGINTM_H BOOLEAN bigintm_setup(); #endif singular-4.0.3+ds/Singular/dyn_modules/bigintm/mod_main.cc000066400000000000000000000017401266270727000236100ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "bigintm.h" namespace { static inline void NoReturn(leftv& res) { res->rtyp = NONE; res->data = NULL; } /// listing all blackbox types (debug stuff) static BOOLEAN printBlackboxTypes0(leftv __res, leftv /*__v*/) { NoReturn(__res); printBlackboxTypes(); return FALSE; } /// init the bigintm (a sample blackbox) type static BOOLEAN bigintm_setup0(leftv __res, leftv /*__v*/) { NoReturn(__res); return bigintm_setup(); } } extern "C" int SI_MOD_INIT(bigintm)(SModulFunctions* psModulFunctions) { psModulFunctions->iiAddCproc(currPack->libname,(char*)"printBlackboxTypes",FALSE, printBlackboxTypes0); psModulFunctions->iiAddCproc(currPack->libname,(char*)"bigintm_setup",FALSE, bigintm_setup0); // Q: should we call 'bigintm_setup' here??!?!? return MAX_TOK; } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/000077500000000000000000000000001266270727000214655ustar00rootroot00000000000000singular-4.0.3+ds/Singular/dyn_modules/gfanlib/Makefile.am000066400000000000000000000047651266270727000235350ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../../m4 SOURCES = singularWishlist.h gfanlib_exceptions.h callgfanlib_conversion.cc callgfanlib_conversion.h bbcone.cc bbcone.h bbfan.cc bbfan.h bbpolytope.cc bbpolytope.h gfan.h gitfan.cc gitfan.h std_wrapper.cc std_wrapper.h tropicalVarietyOfPolynomials.h tropicalVarietyOfPolynomials.cc ppinitialReduction.cc ppinitialReduction.h containsMonomial.cc containsMonomial.h adjustWeights.cc adjustWeights.h tropicalStrategy.cc tropicalStrategy.h initial.cc initial.h witness.cc witness.h lift.cc lift.h flip.cc flip.h tropicalCurves.cc tropicalCurves.h groebnerCone.cc groebnerCone.h startingCone.cc startingCone.h tropicalTraversal.cc tropicalTraversal.h tropicalVarietyOfIdeals.cc tropicalVarietyOfIdeals.h tropicalVariety.cc tropicalVariety.h groebnerFan.cc groebnerFan.h groebnerComplex.cc groebnerComplex.h tropical.cc tropical.h gfanlib.cc MY_CPPFLAGS = -I${srcdir} -I${top_srcdir} -I${top_builddir} \ -I${top_srcdir}/libpolys -I${top_builddir}/libpolys \ ${FACTORY_INCLUDES} ${RESOURCES_INCLUDES} ${OMALLOC_INCLUDES} \ ${FLINT_CFLAGS} ${NTL_CFLAGS} ${GMP_CFLAGS} if SI_BUILTIN_GFANLIB if HAVE_GFANLIB noinst_LTLIBRARIES=gfanlib.la endif ## moduledir = $(libdir)/singular P_PROCS_CPPFLAGS_COMMON = -DSTATIC_VERSION P_PROCS_MODULE_LDFLAGS = -module else if HAVE_GFANLIB module_LTLIBRARIES=gfanlib.la endif moduledir = $(libexecdir)/singular/MOD P_PROCS_CPPFLAGS_COMMON = -DDYNAMIC_VERSION # Add under Mac OS X: -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup P_PROCS_MODULE_LDFLAGS = -module -export-dynamic -avoid-version -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup endif gfanlib_la_SOURCES = $(SOURCES) gfanlib_la_CPPFLAGS = ${MY_CPPFLAGS} ${P_PROCS_CPPFLAGS_COMMON} ${CDDGMPCPPFLAGS} gfanlib_la_LDFLAGS = ${P_PROCS_MODULE_LDFLAGS} # forcefully enable exceptions for polymake CXXFLAGS+= $(FEXCEPTIONSFRTTI_CXXFLAGS) if HAVE_GFANLIB gfanlib_la_LIBADD = ${abs_top_builddir}/gfanlib/libgfan.la ${CDDGMPLDFLAGS} endif #AM_COLOR_TESTS=always # #TESTS_ENVIRONMENT = SINGULARPATH='${abs_top_builddir}/Singular/LIB:${abs_top_srcdir}/Singular/LIB:${abs_top_builddir}/libpolys/polys/.libs:${abs_top_builddir}/factory/gftables:${abs_builddir}/.libs:${abs_srcdir}' #TESTS_ENVIRONMENT += SINGULAR_ROOT_DIR='${abs_top_builddir}' #TESTS_ENVIRONMENT += SINGULAR_BIN_DIR='${abs_top_builddir}/Singular' $(SHELL) -x # #if WANT_DEBUG # TESTS=test_release.sh test_debug.sh #else # TESTS=test_release.sh #endif # # EXTRA_DIST = gfanlib.tst test.sh $(TESTS) singular-4.0.3+ds/Singular/dyn_modules/gfanlib/adjustWeights.cc000066400000000000000000000064041266270727000246250ustar00rootroot00000000000000#include #include #ifndef NDEBUG static bool checkForNonPositiveEntries(const gfan::ZVector &w) { for (unsigned i=0; i0) return w; /* compute w+(1-min)*(1,...,1) and return it */ gfan::ZVector v=gfan::ZVector(w.size()); for (unsigned i=0; i0) return e; /* compute w+(1-min)*(1,...,1) and return it */ gfan::ZVector v=gfan::ZVector(e.size()); for (unsigned i=0; i0) k = gfan::Integer((long)1)-(e[0]/w[0]); for (unsigned i=1; i gfan::ZVector nonvalued_adjustWeightForHomogeneity(const gfan::ZVector &w); gfan::ZVector valued_adjustWeightForHomogeneity(const gfan::ZVector &w); gfan::ZVector nonvalued_adjustWeightUnderHomogeneity(const gfan::ZVector &e, const gfan::ZVector &w); gfan::ZVector valued_adjustWeightUnderHomogeneity(const gfan::ZVector &e, const gfan::ZVector &w); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/bbcone.cc000066400000000000000000001440251266270727000232320ustar00rootroot00000000000000#include #if HAVE_GFANLIB #include #include #include #include #include #include #include #include #include #include #include #include #include int coneID; std::string toString(const gfan::ZCone* const c) { std::stringstream s; s<<"AMBIENT_DIM"<ambientDimension()<getInequalities(); char* ineqs = toString(i); if (c->areFacetsKnown()) s<<"FACETS"<getEquations(); char* eqs = toString(e); if (c->areImpliedEquationsKnown()) s<<"LINEAR_SPAN"<areExtremeRaysKnown()) { gfan::ZMatrix r=c->extremeRays(); char* rs = toString(r); s<<"RAYS"<generatorsOfLinealitySpace(); char* ls = toString(l); s<<"LINEALITY_SPACE"<Data()!=NULL) { gfan::ZCone* zd = (gfan::ZCone*)l->Data(); delete zd; } newZc = new gfan::ZCone(); } else if (r->Typ()==l->Typ()) { if (l->Data()!=NULL) { gfan::ZCone* zd = (gfan::ZCone*)l->Data(); delete zd; } newZc = (gfan::ZCone*)r->CopyD(); } else if (r->Typ()==INT_CMD) { int ambientDim = (int)(long)r->Data(); if (ambientDim < 0) { Werror("expected an int >= 0, but got %d", ambientDim); return TRUE; } if (l->Data()!=NULL) { gfan::ZCone* zd = (gfan::ZCone*)l->Data(); delete zd; } newZc = new gfan::ZCone(ambientDim); } else { Werror("assign Type(%d) = Type(%d) not implemented",l->Typ(),r->Typ()); return TRUE; } if (l->rtyp==IDHDL) { IDDATA((idhdl)l->data)=(char*) newZc; } else { l->data=(void *)newZc; } return FALSE; } char* bbcone_String(blackbox* /*b*/, void *d) { if (d==NULL) return omStrDup("invalid object"); else { std::string s=toString((gfan::ZCone*) d); return omStrDup(s.c_str()); } } void bbcone_destroy(blackbox* /*b*/, void *d) { if (d!=NULL) { gfan::ZCone* zc = (gfan::ZCone*) d; delete zc; } } void* bbcone_Copy(blackbox* /*b*/, void *d) { gfan::ZCone* zc = (gfan::ZCone*)d; gfan::ZCone* newZc = new gfan::ZCone(*zc); return newZc; } static BOOLEAN bbcone_Op2(int op, leftv res, leftv i1, leftv i2) { gfan::ZCone* zp = (gfan::ZCone*) i1->Data(); switch(op) { case '&': { if (i2->Typ()==coneID) { gfan::ZCone* zq = (gfan::ZCone*) i2->Data(); int d1 = zp->ambientDimension(); int d2 = zq->ambientDimension(); if (d1 != d2) { WerrorS("mismatching ambient dimensions"); return TRUE; } gfan::ZCone* zs = new gfan::ZCone(); *zs = gfan::intersection(*zp, *zq); zs->canonicalize(); res->rtyp = coneID; res->data = (void*) zs; return FALSE; } return blackboxDefaultOp2(op,res,i1,i2); } case '|': { if(i2->Typ()==coneID) { gfan::ZCone* zq = (gfan::ZCone*) i2->Data(); int d1 = zp->ambientDimension(); int d2 = zq->ambientDimension(); if (d1 != d2) { WerrorS("mismatching ambient dimensions"); return TRUE; } gfan::ZMatrix rays = zp->extremeRays(); rays.append(zq->extremeRays()); gfan::ZMatrix lineality = zp->generatorsOfLinealitySpace(); lineality.append(zq->generatorsOfLinealitySpace()); gfan::ZCone* zs = new gfan::ZCone(); *zs = gfan::ZCone::givenByRays(rays,lineality); zs->canonicalize(); res->rtyp = coneID; res->data = (void*) zs; return FALSE; } return blackboxDefaultOp2(op,res,i1,i2); } case EQUAL_EQUAL: { if(i2->Typ()==coneID) { gfan::ZCone* zq = (gfan::ZCone*) i2->Data(); zp->canonicalize(); zq->canonicalize(); bool b = !((*zp)!=(*zq)); res->rtyp = INT_CMD; res->data = (void*) b; return FALSE; } return blackboxDefaultOp2(op,res,i1,i2); } default: return blackboxDefaultOp2(op,res,i1,i2); } return blackboxDefaultOp2(op,res,i1,i2); } /* singular wrapper for gfanlib functions */ static BOOLEAN jjCONENORMALS1(leftv res, leftv v) { /* method for generating a cone object from inequalities; valid parametrizations: (intmat) */ bigintmat* ineq = NULL; if (v->Typ() == INTMAT_CMD) { intvec* ineq0 = (intvec*) v->Data(); ineq = iv2bim(ineq0,coeffs_BIGINT); } else ineq = (bigintmat*) v->Data(); gfan::ZMatrix* zm = bigintmatToZMatrix(ineq); gfan::ZCone* zc = new gfan::ZCone(*zm, gfan::ZMatrix(0, zm->getWidth())); delete zm; if (v->Typ() == INTMAT_CMD) delete ineq; res->rtyp = coneID; res->data = (void*) zc; return FALSE; } static BOOLEAN jjCONENORMALS2(leftv res, leftv u, leftv v) { /* method for generating a cone object from iequalities, and equations (...) valid parametrizations: (intmat, intmat) Errors will be invoked in the following cases: - u and v have different numbers of columns */ bigintmat* ineq = NULL; bigintmat* eq = NULL; if (u->Typ() == INTMAT_CMD) { intvec* ineq0 = (intvec*) u->Data(); ineq = iv2bim(ineq0,coeffs_BIGINT); } else ineq = (bigintmat*) u->Data(); if (v->Typ() == INTMAT_CMD) { intvec* eq0 = (intvec*) v->Data(); eq = iv2bim(eq0,coeffs_BIGINT); } else eq = (bigintmat*) v->Data(); if (ineq->cols() != eq->cols()) { Werror("expected same number of columns but got %d vs. %d", ineq->cols(), eq->cols()); return TRUE; } gfan::ZMatrix* zm1 = bigintmatToZMatrix(ineq); gfan::ZMatrix* zm2 = bigintmatToZMatrix(eq); gfan::ZCone* zc = new gfan::ZCone(*zm1, *zm2); delete zm1; delete zm2; if (u->Typ() == INTMAT_CMD) delete ineq; if (v->Typ() == INTMAT_CMD) delete eq; res->rtyp = coneID; res->data = (void*) zc; return FALSE; } static BOOLEAN jjCONENORMALS3(leftv res, leftv u, leftv v, leftv w) { /* method for generating a cone object from inequalities, equations, and an integer k; valid parametrizations: (intmat, intmat, int); Errors will be invoked in the following cases: - u and v have different numbers of columns, - k not in [0..3]; if the 2^0-bit of k is set, then ... */ bigintmat* ineq = NULL; bigintmat* eq = NULL; if (u->Typ() == INTMAT_CMD) { intvec* ineq0 = (intvec*) u->Data(); ineq = iv2bim(ineq0,coeffs_BIGINT); } else ineq = (bigintmat*) u->Data(); if (v->Typ() == INTMAT_CMD) { intvec* eq0 = (intvec*) v->Data(); eq = iv2bim(eq0,coeffs_BIGINT); } else eq = (bigintmat*) v->Data(); if (ineq->cols() != eq->cols()) { Werror("expected same number of columns but got %d vs. %d", ineq->cols(), eq->cols()); return TRUE; } int k = (int)(long)w->Data(); if ((k < 0) || (k > 3)) { WerrorS("expected int argument in [0..3]"); return TRUE; } gfan::ZMatrix* zm1 = bigintmatToZMatrix(ineq); gfan::ZMatrix* zm2 = bigintmatToZMatrix(eq); gfan::ZCone* zc = new gfan::ZCone(*zm1, *zm2, k); delete zm1; delete zm2; if (u->Typ() == INTMAT_CMD) delete ineq; if (v->Typ() == INTMAT_CMD) delete eq; res->rtyp = coneID; res->data = (void*) zc; return FALSE; } BOOLEAN coneViaNormals(leftv res, leftv args) { leftv u = args; if ((u != NULL) && ((u->Typ() == BIGINTMAT_CMD) || (u->Typ() == INTMAT_CMD))) { if (u->next == NULL) return jjCONENORMALS1(res, u); } leftv v = u->next; if ((v != NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTMAT_CMD))) { if (v->next == NULL) return jjCONENORMALS2(res, u, v); } leftv w = v->next; if ((w != NULL) && (w->Typ() == INT_CMD)) { if (w->next == NULL) return jjCONENORMALS3(res, u, v, w); } WerrorS("coneViaInequalities: unexpected parameters"); return TRUE; } static BOOLEAN jjCONERAYS1(leftv res, leftv v) { /* method for generating a cone object from half-lines (cone = convex hull of the half-lines; note: there may be entire lines in the cone); valid parametrizations: (intmat) */ bigintmat* rays = NULL; if (v->Typ() == INTMAT_CMD) { intvec* rays0 = (intvec*) v->Data(); rays = iv2bim(rays0,coeffs_BIGINT); } else rays = (bigintmat*) v->Data(); gfan::ZMatrix* zm = bigintmatToZMatrix(rays); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(*zm, gfan::ZMatrix(0, zm->getWidth())); res->rtyp = coneID; res->data = (void*) zc; delete zm; if (v->Typ() == INTMAT_CMD) delete rays; return FALSE; } static BOOLEAN jjCONERAYS2(leftv res, leftv u, leftv v) { /* method for generating a cone object from half-lines, and lines (any point in the cone being the sum of a point in the convex hull of the half-lines and a point in the span of the lines; the second argument may contain or entirely consist of zero rows); valid parametrizations: (intmat, intmat) Errors will be invoked in the following cases: - u and v have different numbers of columns */ bigintmat* rays = NULL; bigintmat* linSpace = NULL; if (u->Typ() == INTMAT_CMD) { intvec* rays0 = (intvec*) u->Data(); rays = iv2bim(rays0,coeffs_BIGINT); } else rays = (bigintmat*) u->Data(); if (v->Typ() == INTMAT_CMD) { intvec* linSpace0 = (intvec*) v->Data(); linSpace = iv2bim(linSpace0,coeffs_BIGINT); } else linSpace = (bigintmat*) v->Data(); if (rays->cols() != linSpace->cols()) { Werror("expected same number of columns but got %d vs. %d", rays->cols(), linSpace->cols()); return TRUE; } gfan::ZMatrix* zm1 = bigintmatToZMatrix(rays); gfan::ZMatrix* zm2 = bigintmatToZMatrix(linSpace); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(*zm1, *zm2); res->rtyp = coneID; res->data = (void*) zc; delete zm1; delete zm2; if (u->Typ() == INTMAT_CMD) delete rays; if (v->Typ() == INTMAT_CMD) delete linSpace; return FALSE; } static BOOLEAN jjCONERAYS3(leftv res, leftv u, leftv v, leftv w) { /* method for generating a cone object from half-lines, and lines (any point in the cone being the sum of a point in the convex hull of the half-lines and a point in the span of the lines), and an integer k; valid parametrizations: (intmat, intmat, int); Errors will be invoked in the following cases: - u and v have different numbers of columns, - k not in [0..3]; if the 2^0-bit of k is set, then the lineality space is known to be the span of the provided lines; if the 2^1-bit of k is set, then the extreme rays are known: each half-line spans a (different) extreme ray */ bigintmat* rays = NULL; bigintmat* linSpace = NULL; if (u->Typ() == INTMAT_CMD) { intvec* rays0 = (intvec*) u->Data(); rays = iv2bim(rays0,coeffs_BIGINT); } else rays = (bigintmat*) u->Data(); if (v->Typ() == INTMAT_CMD) { intvec* linSpace0 = (intvec*) v->Data(); linSpace = iv2bim(linSpace0,coeffs_BIGINT); } else linSpace = (bigintmat*) v->Data(); if (rays->cols() != linSpace->cols()) { Werror("expected same number of columns but got %d vs. %d", rays->cols(), linSpace->cols()); return TRUE; } int k = (int)(long)w->Data(); if ((k < 0) || (k > 3)) { WerrorS("expected int argument in [0..3]"); return TRUE; } gfan::ZMatrix* zm1 = bigintmatToZMatrix(rays); gfan::ZMatrix* zm2 = bigintmatToZMatrix(linSpace); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(*zm1, *zm2); //k should be passed on to zc; not available yet res->rtyp = coneID; res->data = (void*) zc; delete zm1; delete zm2; if (u->Typ() == INTMAT_CMD) delete rays; if (v->Typ() == INTMAT_CMD) delete linSpace; return FALSE; } BOOLEAN coneViaRays(leftv res, leftv args) { leftv u = args; if ((u != NULL) && ((u->Typ() == BIGINTMAT_CMD) || (u->Typ() == INTMAT_CMD))) { if (u->next == NULL) return jjCONERAYS1(res, u); leftv v = u->next; if ((v != NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTMAT_CMD))) { if (v->next == NULL) return jjCONERAYS2(res, u, v); leftv w = v->next; if ((w != NULL) && (w->Typ() == INT_CMD)) { if (w->next == NULL) return jjCONERAYS3(res, u, v, w); } } } WerrorS("coneViaPoints: unexpected parameters"); return TRUE; } BOOLEAN inequalities(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID || u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zmat = zc->getInequalities(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zMatrixToBigintmat(zmat); return FALSE; } WerrorS("inequalities: unexpected parameters"); return TRUE; } BOOLEAN equations(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID || u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zmat = zc->getEquations(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zMatrixToBigintmat(zmat); return FALSE; } WerrorS("equations: unexpected parameters"); return TRUE; } BOOLEAN facets(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID || u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zm = zc->getFacets(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zMatrixToBigintmat(zm); return FALSE; } WerrorS("facets: unexpected parameters"); return TRUE; } BOOLEAN impliedEquations(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID || u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zmat = zc->getImpliedEquations(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zMatrixToBigintmat(zmat); return FALSE; } WerrorS("span: unexpected parameters"); return TRUE; } BOOLEAN generatorsOfSpan(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID || u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zmat = zc->generatorsOfSpan(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zMatrixToBigintmat(zmat); return FALSE; } WerrorS("generatorsOfSpan: unexpected parameters"); return TRUE; } BOOLEAN generatorsOfLinealitySpace(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID || u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zmat = zc->generatorsOfLinealitySpace(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zMatrixToBigintmat(zmat); return FALSE; } WerrorS("generatorsOfLinealitySpace: unexpected parameters"); return TRUE; } BOOLEAN rays(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zm = zc->extremeRays(); res->rtyp = BIGINTMAT_CMD; res->data = (void*)zMatrixToBigintmat(zm); return FALSE; } if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); gfan::ZMatrix zmat = rays(zf); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zMatrixToBigintmat(zmat); return FALSE; } WerrorS("rays: unexpected parameters"); return TRUE; } BOOLEAN quotientLatticeBasis(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zmat = zc->quotientLatticeBasis(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zMatrixToBigintmat(zmat); return FALSE; } WerrorS("quotientLatticeBasis: unexpected parameters"); return TRUE; } BOOLEAN getLinearForms(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zmat = zc->getLinearForms(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zMatrixToBigintmat(zmat); return FALSE; } WerrorS("getLinearForms: unexpected parameters"); return TRUE; } BOOLEAN ambientDimension(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) zc->ambientDimension(); return FALSE; } if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) getAmbientDimension(zf); return FALSE; } if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) getAmbientDimension(zc); return FALSE; } WerrorS("ambientDimension: unexpected parameters"); return TRUE; } BOOLEAN dimension(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) zc->dimension(); return FALSE; } if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) getDimension(zf); return FALSE; } if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) getDimension(zc); return FALSE; } WerrorS("dimension: unexpected parameters"); return TRUE; } BOOLEAN codimension(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) zc->codimension(); return FALSE; } if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) getCodimension(zf); return FALSE; } if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) getCodimension(zc); return FALSE; } WerrorS("getCodimension: unexpected parameters"); return TRUE; } BOOLEAN linealityDimension(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) zc->dimensionOfLinealitySpace(); return FALSE; } if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); res->rtyp = INT_CMD; res->data = (void*) (long) getLinealityDimension(zf); return FALSE; } WerrorS("linealityDimension: unexpected parameters"); return TRUE; } BOOLEAN getMultiplicity(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); number i = integerToNumber(zc->getMultiplicity()); res->rtyp = BIGINT_CMD; res->data = (void*) i; return FALSE; } WerrorS("getMultiplicity: unexpected parameters"); return TRUE; } BOOLEAN isOrigin(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); int i = zc->isOrigin(); res->rtyp = INT_CMD; res->data = (void*) (long) i; return FALSE; } WerrorS("isOrigin: unexpected parameters"); return TRUE; } BOOLEAN isFullSpace(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); int i = zc->isFullSpace(); res->rtyp = INT_CMD; res->data = (void*) (long) i; return FALSE; } WerrorS("isFullSpace: unexpected parameters"); return TRUE; } BOOLEAN isSimplicial(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*) u->Data(); int b = zc->isSimplicial(); res->rtyp = INT_CMD; res->data = (void*) (long) b; return FALSE; } if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*) u->Data(); bool b = isSimplicial(zf); res->rtyp = INT_CMD; res->data = (void*) (long) b; return FALSE; } WerrorS("isSimplicial: unexpected parameters"); return TRUE; } BOOLEAN containsPositiveVector(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); int i = zc->containsPositiveVector(); res->rtyp = INT_CMD; res->data = (void*) (long) i; return FALSE; } WerrorS("containsPositiveVector: unexpected parameters"); return TRUE; } BOOLEAN linealitySpace(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZCone* zd = new gfan::ZCone(zc->linealitySpace()); res->rtyp = coneID; res->data = (void*) zd; return FALSE; } WerrorS("linealitySpace: unexpected parameters"); return TRUE; } BOOLEAN dualCone(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZCone* zd = new gfan::ZCone(zc->dualCone()); res->rtyp = coneID; res->data = (void*) zd; return FALSE; } WerrorS("dual: unexpected parameters"); return TRUE; } BOOLEAN negatedCone(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZCone* zd = new gfan::ZCone(zc->negated()); res->rtyp = coneID; res->data = (void*) zd; return FALSE; } WerrorS("negatedCone: unexpected parameters"); return TRUE; } BOOLEAN semigroupGenerator(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); int d = zc->dimension(); int dLS = zc->dimensionOfLinealitySpace(); if (d == dLS + 1) { gfan::ZVector zv = zc->semiGroupGeneratorOfRay(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(zv); return FALSE; } Werror("expected dim of cone one larger than dim of lin space\n" "but got dimensions %d and %d", d, dLS); } WerrorS("semigroupGenerator: unexpected parameters"); return TRUE; } BOOLEAN relativeInteriorPoint(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZVector zv = zc->getRelativeInteriorPoint(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(zv); return FALSE; } WerrorS("relativeInteriorPoint: unexpected parameters"); return TRUE; } BOOLEAN uniquePoint(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZVector zv = zc->getUniquePoint(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(zv); return FALSE; } WerrorS("uniquePoint: unexpected parameters"); return TRUE; } gfan::ZVector randomPoint(const gfan::ZCone* zc) { gfan::ZVector rp = gfan::ZVector(zc->ambientDimension()); gfan::ZMatrix rays = zc->extremeRays(); for (int i=0; igeneratorsOfLinealitySpace(); for (int i=0; iTyp() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZVector zv = randomPoint(zc); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(zv); return FALSE; } WerrorS("randomPoint: unexpected parameters"); return TRUE; } BOOLEAN setMultiplicity(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); leftv v = u->next; if ((v != NULL) && (v->Typ() == INT_CMD)) { int val = (int)(long)v->Data(); zc->setMultiplicity(gfan::Integer(val)); res->rtyp = NONE; res->data = NULL; return FALSE; } } WerrorS("setMultiplicity: unexpected parameters"); return TRUE; } BOOLEAN setLinearForms(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); leftv v = u->next; if ((v != NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) { bigintmat* mat=NULL; if (v->Typ() == INTVEC_CMD) { intvec* mat0 = (intvec*) v->Data(); mat = iv2bim(mat0,coeffs_BIGINT)->transpose(); } else mat = (bigintmat*) v->Data(); gfan::ZMatrix* zm = bigintmatToZMatrix(mat); zc->setLinearForms(*zm); res->rtyp = NONE; res->data = NULL; delete zm; if (v->Typ() == INTVEC_CMD) delete mat; return FALSE; } } WerrorS("setLinearForms: unexpected parameters"); return TRUE; } gfan::ZMatrix liftUp(const gfan::ZMatrix &zm) { int r=zm.getHeight(); int c=zm.getWidth(); gfan::ZMatrix zn(r+1,c+1); zn[1][1]=1; for (int i=0; iTyp() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*) u->Data(); gfan::ZMatrix ineq=zc->getInequalities(); gfan::ZMatrix eq=zc->getEquations(); gfan::ZCone* zd = new gfan::ZCone(liftUp(ineq),liftUp(eq)); res->rtyp = polytopeID; res->data = (void*) zd; return FALSE; } WerrorS("makePolytope: unexpected parameters"); return TRUE; } BOOLEAN intersectCones(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZCone* zc1 = (gfan::ZCone*)u->Data(); gfan::ZCone* zc2 = (gfan::ZCone*)v->Data(); int d1 = zc1->ambientDimension(); int d2 = zc2->ambientDimension(); if (d1 != d2) { Werror("expected ambient dims of both cones to coincide\n" "but got %d and %d", d1, d2); return TRUE; } gfan::ZCone zc3 = gfan::intersection(*zc1, *zc2); zc3.canonicalize(); res->rtyp = coneID; res->data = (void *)new gfan::ZCone(zc3); return FALSE; } if ((v != NULL) && (v->Typ() == polytopeID)) { gfan::ZCone* zc11 = (gfan::ZCone*)u->Data(); gfan::ZCone zc1 = liftUp(*zc11); gfan::ZCone* zc2 = (gfan::ZCone*)v->Data(); int d1 = zc1.ambientDimension(); int d2 = zc2->ambientDimension(); if (d1 != d2) { Werror("expected ambient dims of both cones to coincide\n" "but got %d and %d", d1, d2); return TRUE; } gfan::ZCone zc3 = gfan::intersection(zc1, *zc2); zc3.canonicalize(); res->rtyp = polytopeID; res->data = (void *)new gfan::ZCone(zc3); return FALSE; } } if ((u != NULL) && (u->Typ() == polytopeID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZCone* zc1 = (gfan::ZCone*)u->Data(); gfan::ZCone* zc22 = (gfan::ZCone*)v->Data(); gfan::ZCone zc2 = liftUp(*zc22); int d1 = zc1->ambientDimension(); int d2 = zc2.ambientDimension(); if (d1 != d2) { Werror("expected ambient dims of both cones to coincide\n" "but got %d and %d", d1, d2); return TRUE; } gfan::ZCone zc3 = gfan::intersection(*zc1, zc2); zc3.canonicalize(); res->rtyp = polytopeID; res->data = (void *)new gfan::ZCone(zc3); return FALSE; } if ((v != NULL) && (v->Typ() == polytopeID)) { gfan::ZCone* zc1 = (gfan::ZCone*)u->Data(); gfan::ZCone* zc2 = (gfan::ZCone*)v->Data(); int d1 = zc1->ambientDimension(); int d2 = zc2->ambientDimension(); if (d1 != d2) { Werror("expected ambient dims of both cones to coincide\n" "but got %d and %d", d1, d2); return TRUE; } gfan::ZCone zc3 = gfan::intersection(*zc1, *zc2); zc3.canonicalize(); res->rtyp = polytopeID; res->data = (void *)new gfan::ZCone(zc3); return FALSE; } } WerrorS("convexIntersection: unexpected parameters"); return TRUE; } BOOLEAN convexHull(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZCone* zc1 = (gfan::ZCone*)u->Data(); gfan::ZCone* zc2 = (gfan::ZCone*)v->Data(); int d1 = zc1->ambientDimension(); int d2 = zc2->ambientDimension(); if (d1 != d2) { Werror("expected ambient dims of both cones to coincide\n" "but got %d and %d", d1, d2); return TRUE; } gfan::ZMatrix zm1 = zc1->extremeRays(); gfan::ZMatrix zm2 = zc2->extremeRays(); gfan::ZMatrix zn1 = zc1->generatorsOfLinealitySpace(); gfan::ZMatrix zn2 = zc2->generatorsOfLinealitySpace(); gfan::ZMatrix zm = combineOnTop(zm1,zm2); gfan::ZMatrix zn = combineOnTop(zn1,zn2); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(zm, zn); res->rtyp = coneID; res->data = (void*) zc; return FALSE; } if ((v != NULL) && (v->Typ() == polytopeID)) { gfan::ZCone* zc11 = (gfan::ZCone*)u->Data(); gfan::ZCone zc1 = liftUp(*zc11); gfan::ZCone* zc2 = (gfan::ZCone*)v->Data(); int d1 = zc1.ambientDimension()-1; int d2 = zc2->ambientDimension()-1; if (d1 != d2) { Werror("expected ambient dims of both cones to coincide\n" "but got %d and %d", d1, d2); return TRUE; } gfan::ZMatrix zm1 = zc1.extremeRays(); gfan::ZMatrix zm2 = zc2->extremeRays(); gfan::ZMatrix zn = zc1.generatorsOfLinealitySpace(); gfan::ZMatrix zm = combineOnTop(zm1,zm2); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(zm, zn); res->rtyp = polytopeID; res->data = (void*) zc; return FALSE; } } if ((u != NULL) && (u->Typ() == polytopeID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZCone* zc1 = (gfan::ZCone*)u->Data(); gfan::ZCone* zc22 = (gfan::ZCone*)v->Data(); gfan::ZCone zc2 = liftUp(*zc22); int d1 = zc1->ambientDimension()-1; int d2 = zc2.ambientDimension()-1; if (d1 != d2) { Werror("expected ambient dims of both cones to coincide\n" "but got %d and %d", d1, d2); return TRUE; } gfan::ZMatrix zm1 = zc1->extremeRays(); gfan::ZMatrix zm2 = zc2.extremeRays(); gfan::ZMatrix zn = zc2.generatorsOfLinealitySpace(); gfan::ZMatrix zm = combineOnTop(zm1,zm2); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(zm,gfan::ZMatrix(0, zm.getWidth())); res->rtyp = polytopeID; res->data = (void*) zc; return FALSE; } if ((v != NULL) && (v->Typ() == polytopeID)) { gfan::ZCone* zc1 = (gfan::ZCone*)u->Data(); gfan::ZCone* zc2 = (gfan::ZCone*)v->Data(); int d1 = zc1->ambientDimension()-1; int d2 = zc2->ambientDimension()-1; if (d1 != d2) { Werror("expected ambient dims of both cones to coincide\n" "but got %d and %d", d1, d2); return TRUE; } gfan::ZMatrix zm1 = zc1->extremeRays(); gfan::ZMatrix zm2 = zc2->extremeRays(); gfan::ZMatrix zm = combineOnTop(zm1,zm2); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(zm,gfan::ZMatrix(0, zm.getWidth())); res->rtyp = polytopeID; res->data = (void*) zc; return FALSE; } } WerrorS("convexHull: unexpected parameters"); return TRUE; } BOOLEAN coneLink(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { leftv v = u->next; if ((v != NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); bigintmat* iv = NULL; if (v->Typ() == INTVEC_CMD) { intvec* iv0 = (intvec*) v->Data(); iv = iv2bim(iv0,coeffs_BIGINT)->transpose(); } else iv = (bigintmat*)v->Data(); gfan::ZVector* zv = bigintmatToZVector(iv); int d1 = zc->ambientDimension(); int d2 = zv->size(); if (d1 != d2) { Werror("expected ambient dim of cone and size of vector\n" " to be equal but got %d and %d", d1, d2); return TRUE; } if(!zc->contains(*zv)) { WerrorS("the provided intvec does not lie in the cone"); return TRUE; } gfan::ZCone* zd = new gfan::ZCone(zc->link(*zv)); res->rtyp = coneID; res->data = (void *) zd; delete zv; if (v->Typ() == INTMAT_CMD) delete iv; return FALSE; } } WerrorS("coneLink: unexpected parameters"); return TRUE; } BOOLEAN containsInSupport(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == coneID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZCone* zd = (gfan::ZCone*)v->Data(); int d1 = zc->ambientDimension(); int d2 = zd->ambientDimension(); if (d1 != d2) { Werror("expected cones with same ambient dimensions\n but got" " dimensions %d and %d", d1, d2); return TRUE; } bool b = (zc->contains(*zd) ? 1 : 0); res->rtyp = INT_CMD; res->data = (void*) (long) b; return FALSE; } if ((v != NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); bigintmat* iv = NULL; if (v->Typ() == INTVEC_CMD) { intvec* iv0 = (intvec*) v->Data(); iv = iv2bim(iv0,coeffs_BIGINT)->transpose(); } else iv = (bigintmat*)v->Data(); gfan::ZVector* zv = bigintmatToZVector(iv); int d1 = zc->ambientDimension(); int d2 = zv->size(); if (d1 != d2) { Werror("expected cones with same ambient dimensions\n but got" " dimensions %d and %d", d1, d2); return TRUE; } int b = zc->contains(*zv); res->rtyp = INT_CMD; res->data = (void*) (long) b; delete zv; if (v->Typ() == INTMAT_CMD) delete iv; return FALSE; } } WerrorS("containsInSupport: unexpected parameters"); return TRUE; } BOOLEAN containsRelatively(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { leftv v = u->next; if ((v != NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); bigintmat* iv = NULL; if (v->Typ() == INTVEC_CMD) { intvec* iv0 = (intvec*) v->Data(); iv = iv2bim(iv0,coeffs_BIGINT)->transpose(); } else iv = (bigintmat*)v->Data(); gfan::ZVector* zv = bigintmatToZVector(iv); int d1 = zc->ambientDimension(); int d2 = zv->size(); if (d1 == d2) { bool b = (zc->containsRelatively(*zv) ? 1 : 0); res->rtyp = INT_CMD; res->data = (void *) b; delete zv; if (v->Typ() == INTMAT_CMD) delete iv; return FALSE; } delete zv; if (v->Typ() == INTMAT_CMD) delete iv; Werror("expected ambient dim of cone and size of vector\n" "to be equal but got %d and %d", d1, d2); } } WerrorS("containsRelatively: unexpected parameters"); return TRUE; } BOOLEAN hasFace(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == coneID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZCone* zd = (gfan::ZCone*)v->Data(); bool b = zc->hasFace(*zd); res->rtyp = INT_CMD; res->data = (void*) (long) b; return FALSE; } } if ((u != NULL) && (u->Typ() == polytopeID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZCone* zd = (gfan::ZCone*)v->Data(); bool b = zc->hasFace(*zd); res->rtyp = INT_CMD; res->data = (void*) (long) b; return FALSE; } } WerrorS("containsAsFace: unexpected parameters"); return TRUE; } BOOLEAN canonicalizeCone(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZCone* zd = new gfan::ZCone(*zc); zd->canonicalize(); res->rtyp = coneID; res->data = (void*) zd; return FALSE; } WerrorS("canonicalizeCone: unexpected parameters"); return TRUE; } BOOLEAN containsCone(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == LIST_CMD)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == coneID)) { lists l = (lists) u->Data(); gfan::ZCone* zc = (gfan::ZCone*) v->Data(); zc->canonicalize(); int b = 0; for (int i=0; i<=lSize(l); i++) { if (l->m[i].Typ() != coneID) { WerrorS("containsCone: entries of wrong type in list"); return TRUE; } gfan::ZCone* ll = (gfan::ZCone*) l->m[i].Data(); ll->canonicalize(); if (!((*ll) != (*zc))) { b = 1; break; } } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } } WerrorS("containsCone: unexpected parameters"); return TRUE; } lists listOfFacets(const gfan::ZCone &zc) { gfan::ZMatrix inequalities = zc.getFacets(); gfan::ZMatrix equations = zc.getImpliedEquations(); lists L = (lists)omAllocBin(slists_bin); int r = inequalities.getHeight(); int c = inequalities.getWidth(); L->Init(r); /* next we iterate over each of the r facets, build the respective cone and add it to the list */ /* this is the i=0 case */ gfan::ZMatrix newInequalities = inequalities.submatrix(1,0,r,c); gfan::ZMatrix newEquations = equations; newEquations.appendRow(inequalities[0]); L->m[0].rtyp = coneID; L->m[0].data=(void*) new gfan::ZCone(newInequalities,newEquations); /* these are the cases i=1,...,r-2 */ for (int i=1; im[i].rtyp = coneID; L->m[i].data=(void*) new gfan::ZCone(newInequalities,newEquations); } /* this is the i=r-1 case */ newInequalities = inequalities.submatrix(0,0,r-1,c); newEquations = equations; newEquations.appendRow(inequalities[r]); L->m[r-1].rtyp = coneID; L->m[r-1].data=(void*) new gfan::ZCone(newInequalities,newEquations); return L; } BOOLEAN listOfFacets(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*) u->Data(); lists L = listOfFacets(*zc); res->rtyp = LIST_CMD; res->data = (void*) L; return FALSE; } WerrorS("listOfFacets: unexpected parameters"); return TRUE; } /*** * Given a cone and a point in its boundary, * returns the inner normal vector of a facet * containing the point. * Unless the point is in the relative interior of the facet * the facet is not unique. * In case no facet contains the point, * then 0 is returned. **/ gfan::ZVector* facetContaining(gfan::ZCone* zc, gfan::ZVector* zv) { gfan::ZMatrix facets = zc->getFacets(); for (int i=0; iambientDimension()); } BOOLEAN facetContaining(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { leftv v = u->next; if ((v != NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) { gfan::ZCone* zc = (gfan::ZCone*) u->Data(); bigintmat* point1; if (v->Typ() == INTVEC_CMD) { intvec* point0 = (intvec*) v->Data(); point1 = iv2bim(point0,coeffs_BIGINT)->transpose(); } else point1 = (bigintmat*) v->Data(); gfan::ZVector* point = bigintmatToZVector(*point1); gfan::ZVector* facet = facetContaining(zc, point); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(*facet); delete facet; delete point; if (v->Typ() == INTVEC_CMD) delete point1; return FALSE; } } WerrorS("facetContaining: unexpected parameters"); return TRUE; } /*** * Computes a relative interior point for each facet of zc **/ gfan::ZMatrix interiorPointsOfFacets(const gfan::ZCone &zc, const std::set &exceptThese) { gfan::ZMatrix inequalities = zc.getFacets(); gfan::ZMatrix equations = zc.getImpliedEquations(); int r = inequalities.getHeight(); int c = inequalities.getWidth(); /* our cone has r facets, if r==0 return empty matrices */ gfan::ZMatrix relativeInteriorPoints = gfan::ZMatrix(0,c); if (r==0) return relativeInteriorPoints; /* next we iterate over each of the r facets, * build the respective cone and add it to the list * this is the i=0 case */ gfan::ZMatrix newInequalities = inequalities.submatrix(1,0,r,c); gfan::ZMatrix newEquations = equations; newEquations.appendRow(inequalities[0]); gfan::ZCone facet = gfan::ZCone(newInequalities,newEquations); facet.canonicalize(); gfan::ZVector interiorPoint = facet.getRelativeInteriorPoint(); if (exceptThese.count(interiorPoint)==0) relativeInteriorPoints.appendRow(interiorPoint); /* these are the cases i=1,...,r-2 */ for (int i=1; i interiorPointsAndNormalsOfFacets(const gfan::ZCone zc, const std::set &exceptThesePoints, const bool onlyLowerHalfSpace) { gfan::ZMatrix inequalities = zc.getFacets(); gfan::ZMatrix equations = zc.getImpliedEquations(); int r = inequalities.getHeight(); int c = inequalities.getWidth(); /* our cone has r facets, if r==0 return empty matrices */ gfan::ZMatrix relativeInteriorPoints = gfan::ZMatrix(0,c); gfan::ZMatrix outerFacetNormals = gfan::ZMatrix(0,c); if (r==0) return std::make_pair(relativeInteriorPoints,outerFacetNormals); /* next we iterate over each of the r facets, * build the respective cone and add it to the list * this is the i=0 case */ gfan::ZMatrix newInequalities = inequalities.submatrix(1,0,r,c); gfan::ZMatrix newEquations = equations; newEquations.appendRow(inequalities[0]); gfan::ZCone facet = gfan::ZCone(newInequalities,newEquations); gfan::ZVector interiorPoint = facet.getRelativeInteriorPoint(); if (onlyLowerHalfSpace==false || interiorPoint[0].sign()<0) { if (exceptThesePoints.count(interiorPoint)==0) { relativeInteriorPoints.appendRow(interiorPoint); outerFacetNormals.appendRow(-inequalities[0]); } } /* these are the cases i=1,...,r-2 */ for (int i=1; idata; sleftv l; memset(&l,0,sizeof(l)); l.rtyp=STRING_CMD; l.data=(void*)"cone"; f->m->Write(f, &l); gfan::ZCone *Z=((gfan::ZCone*) d; /* AMBIENT_DIM */ fprintf(dd->f_write("%d ",Z->ambientDimension()); /* FACETS or INEQUALITIES */ fprintf(dd->f_write("%d ",Z->areFacetsKnown()); gfan::ZMatrix i=Z->getInequalities(); .... /* LINEAR_SPAN or EQUATIONS */ fprintf(dd->f_write("%d ",Z->areImpliedEquationsKnown()); gfan::ZMatrix e=Z->getEquations(); .... /* RAYS */ gfan::ZMatrix r=Z->extremeRays(); .... /* LINEALITY_SPACE */ gfan::ZMatrix l=Z->generatorsOfLinealitySpace(); .... return FALSE; } BOOLEAN bbcone_deserialize(blackbox **b, void **d, si_link f) { ssiInfo *dd = (ssiInfo *)f->data; gfan::ZCone *Z; /* AMBIENT_DIM */ = s_readint(dd->f_read); /* areFacetsKnown: */ = s_readint(dd->f_read); if (areFacetsKnown) ....FACETS else ....INEQUALITIES /* areImpliedEquationsKnown*/ = s_readint(dd->f_read); if(areImpliedEquationsKnown) ....EQUATIONS else ...LINEAR_SPAN ...RAYS ...LINEALITY_SPACE *d=Z; return FALSE; } #endif void bbcone_setup(SModulFunctions* p) { blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox)); // all undefined entries will be set to default in setBlackboxStuff // the default Print is quite usefull, // all other are simply error messages b->blackbox_destroy=bbcone_destroy; b->blackbox_String=bbcone_String; // b->blackbox_Print=blackbox_default_Print; b->blackbox_Init=bbcone_Init; b->blackbox_Copy=bbcone_Copy; b->blackbox_Assign=bbcone_Assign; b->blackbox_Op2=bbcone_Op2; //b->blackbox_serialize=bbcone_serialize; //b->blackbox_deserialize=bbcone_deserialize; p->iiAddCproc("","coneViaInequalities",FALSE,coneViaNormals); p->iiAddCproc("","coneViaPoints",FALSE,coneViaRays); // iiAddCproc("","makePolytope",FALSE,coneToPolytope); p->iiAddCproc("","ambientDimension",FALSE,ambientDimension); p->iiAddCproc("","canonicalizeCone",FALSE,canonicalizeCone); p->iiAddCproc("","codimension",FALSE,codimension); p->iiAddCproc("","coneLink",FALSE,coneLink); p->iiAddCproc("","containsAsFace",FALSE,hasFace); p->iiAddCproc("","containsInSupport",FALSE,containsInSupport); p->iiAddCproc("","containsPositiveVector",FALSE,containsPositiveVector); p->iiAddCproc("","containsRelatively",FALSE,containsRelatively); p->iiAddCproc("","convexHull",FALSE,convexHull); p->iiAddCproc("","convexIntersection",FALSE,intersectCones); p->iiAddCproc("","dimension",FALSE,dimension); p->iiAddCproc("","dualCone",FALSE,dualCone); p->iiAddCproc("","equations",FALSE,equations); p->iiAddCproc("","facets",FALSE,facets); p->iiAddCproc("","generatorsOfLinealitySpace",FALSE,generatorsOfLinealitySpace); p->iiAddCproc("","generatorsOfSpan",FALSE,generatorsOfSpan); p->iiAddCproc("","getLinearForms",FALSE,getLinearForms); p->iiAddCproc("","getMultiplicity",FALSE,getMultiplicity); p->iiAddCproc("","inequalities",FALSE,inequalities); p->iiAddCproc("","isFullSpace",FALSE,isFullSpace); p->iiAddCproc("","isOrigin",FALSE,isOrigin); p->iiAddCproc("","isSimplicial",FALSE,isSimplicial); p->iiAddCproc("","linealityDimension",FALSE,linealityDimension); p->iiAddCproc("","linealitySpace",FALSE,linealitySpace); p->iiAddCproc("","negatedCone",FALSE,negatedCone); p->iiAddCproc("","quotientLatticeBasis",FALSE,quotientLatticeBasis); p->iiAddCproc("","randomPoint",FALSE,randomPoint); p->iiAddCproc("","rays",FALSE,rays); p->iiAddCproc("","relativeInteriorPoint",FALSE,relativeInteriorPoint); p->iiAddCproc("","semigroupGenerator",FALSE,semigroupGenerator); p->iiAddCproc("","setLinearForms",FALSE,setLinearForms); p->iiAddCproc("","setMultiplicity",FALSE,setMultiplicity); p->iiAddCproc("","span",FALSE,impliedEquations); p->iiAddCproc("","uniquePoint",FALSE,uniquePoint); p->iiAddCproc("","listContainsCone",FALSE,containsCone); p->iiAddCproc("","listOfFacets",FALSE,listOfFacets); p->iiAddCproc("","facetContaining",FALSE,facetContaining); coneID=setBlackboxStuff(b,"cone"); } #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/bbcone.h000066400000000000000000000013561266270727000230730ustar00rootroot00000000000000#ifndef BBCONE_H #define BBCONE_H #include #if HAVE_GFANLIB #include #include #include #include extern int coneID; void bbcone_setup(SModulFunctions* p); std::string toString(const gfan::ZCone* const c); gfan::ZVector randomPoint(const gfan::ZCone* zc); gfan::ZCone liftUp(const gfan::ZCone &zc); gfan::ZMatrix interiorPointsOfFacets(const gfan::ZCone &zc, const std::set &exceptThese=std::set()); std::pair interiorPointsAndNormalsOfFacets(const gfan::ZCone zc, const std::set &exceptThesePoints=std::set(), const bool onlyLowerHalfSpace=false); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/bbfan.cc000066400000000000000000000704371266270727000230570ustar00rootroot00000000000000#include #if HAVE_GFANLIB #include #include #include #include #include #include #include #include #include #include int fanID; void* bbfan_Init(blackbox* /*b*/) { return (void*) new gfan::ZFan(0); } void bbfan_destroy(blackbox* /*b*/, void *d) { if (d!=NULL) { gfan::ZFan* zf = (gfan::ZFan*) d; delete zf; } } char* bbfan_String(blackbox* /*b*/, void *d) { if (d==NULL) return omStrDup("invalid object"); else { gfan::ZFan* zf = (gfan::ZFan*)d; std::string s = zf->toString(2+4+8+128); return omStrDup(s.c_str()); // ======= // std::stringstream s; // std::string raysAndCones = zf->toStringJustRaysAndMaximalCones(); // s << raysAndCones; // if (zf->getDimension() >= 0) // <=> zf is not empty // { // assert(zf->numberOfConesOfDimension(zf->getDimension()-zf->getLinealityDimension(),0,0)); // gfan::ZCone zc = zf->getCone(zf->getDimension()-zf->getLinealityDimension(),0,0,0); // gfan::ZMatrix genLinSpace = zc.generatorsOfLinealitySpace(); // char* gens = toString(genLinSpace); // s << std::endl << "GENERATORS_LINEALITY_SPACE:" << std::endl; // s << gens; // } // std::string sstring = s.str(); // return omStrDup(sstring.c_str()); // >>>>>>> status updated 11.03. } } void* bbfan_Copy(blackbox* /*b*/, void *d) { gfan::ZFan* zf = (gfan::ZFan*)d; gfan::ZFan* newZf = new gfan::ZFan(*zf); return newZf; } BOOLEAN bbfan_Assign(leftv l, leftv r) { gfan::ZFan* newZf; if (r==NULL) { if (l->Data()!=NULL) { gfan::ZFan* zd = (gfan::ZFan*) l->Data(); delete zd; } newZf = new gfan::ZFan(0); } else if (r->Typ()==l->Typ()) { if (l->Data()!=NULL) { gfan::ZFan* zd = (gfan::ZFan*) l->Data(); delete zd; } newZf = (gfan::ZFan*) r->CopyD(); } else if (r->Typ()==INT_CMD) { int ambientDim = (int) (long) r->Data(); if (ambientDim < 0) { Werror("expected an int >= 0, but got %d", ambientDim); return TRUE; } if (l->Data()!=NULL) { gfan::ZFan* zd = (gfan::ZFan*) l->Data(); delete zd; } newZf = new gfan::ZFan(ambientDim); } else { Werror("assign Type(%d) = Type(%d) not implemented",l->Typ(),r->Typ()); return TRUE; } if (l->rtyp==IDHDL) { IDDATA((idhdl)l->data) = (char*) newZf; } else { l->data = (void*) newZf; } return FALSE; } /* returns 1 iff all rows consist of entries 1..n, where n is the number of columns of the provided bigintmat; 0 otherwise */ static gfan::IntMatrix permutationIntMatrix(const bigintmat* iv) { int cc = iv->cols(); int rr = iv->rows(); bigintmat* ivCopy = new bigintmat(rr, cc, coeffs_BIGINT); number temp1 = n_Init(1,coeffs_BIGINT); for (int r = 1; r <= rr; r++) for (int c = 1; c <= cc; c++) { number temp2 = n_Sub(IMATELEM(*iv, r, c),temp1,coeffs_BIGINT); ivCopy->set(r,c,temp2); n_Delete(&temp2,coeffs_BIGINT); } n_Delete(&temp1,coeffs_BIGINT); gfan::ZMatrix* zm = bigintmatToZMatrix(ivCopy); gfan::IntMatrix im = gfan::IntMatrix(gfan::ZToIntMatrix(*zm)); delete zm; return im; } static BOOLEAN jjFANEMPTY_I(leftv res, leftv v) { int ambientDim = (int)(long)v->Data(); if (ambientDim < 0) { Werror("expected non-negative ambient dim but got %d", ambientDim); return TRUE; } res->rtyp = fanID; res->data = (void*)(new gfan::ZFan(ambientDim)); return FALSE; } static BOOLEAN jjFANEMPTY_IM(leftv res, leftv v) { bigintmat* permutations = (bigintmat*)v->Data(); int ambientDim = permutations->cols(); gfan::IntMatrix im = permutationIntMatrix(permutations); if (!gfan::Permutation::arePermutations(im)) { Werror("provided bigintmat contains invalid permutations of {1, ..., %d}", ambientDim); return TRUE; } gfan::SymmetryGroup sg = gfan::SymmetryGroup(ambientDim); sg.computeClosure(im); res->rtyp = fanID; res->data = (void*)(new gfan::ZFan(sg)); return FALSE; } BOOLEAN emptyFan(leftv res, leftv args) { leftv u = args; if (u == NULL) { res->rtyp = fanID; res->data = (void*) new gfan::ZFan(0); return FALSE; } if ((u != NULL) && (u->Typ() == INT_CMD)) { if (u->next == NULL) return jjFANEMPTY_I(res, u); } if ((u != NULL) && (u->Typ() == BIGINTMAT_CMD)) { if (u->next == NULL) return jjFANEMPTY_IM(res, u); } WerrorS("emptyFan: unexpected parameters"); return TRUE; } static BOOLEAN jjFANFULL_I(leftv res, leftv v) { int ambientDim = (int)(long)v->Data(); if (ambientDim < 0) { Werror("expected non-negative ambient dim but got %d", ambientDim); return TRUE; } gfan::ZFan* zf = new gfan::ZFan(gfan::ZFan::fullFan(ambientDim)); res->rtyp = fanID; res->data = (void*) zf; return FALSE; } static BOOLEAN jjFANFULL_IM(leftv res, leftv v) { bigintmat* permutations = (bigintmat*)v->Data(); int ambientDim = permutations->cols(); gfan::IntMatrix im = permutationIntMatrix(permutations); if (!gfan::Permutation::arePermutations(im)) { Werror("provided bigintmat contains invalid permutations of {1, ..., %d}", ambientDim); return TRUE; } gfan::SymmetryGroup sg = gfan::SymmetryGroup(ambientDim); sg.computeClosure(im); gfan::ZFan* zf = new gfan::ZFan(gfan::ZFan::fullFan(sg)); res->rtyp = fanID; res->data = (void*) zf; return FALSE; } BOOLEAN fullFan(leftv res, leftv args) { leftv u = args; if (u == NULL) { res->rtyp = fanID; res->data = (void*) new gfan::ZFan(0); return FALSE; } if ((u != NULL) && (u->Typ() == INT_CMD)) if (u->next == NULL) return jjFANFULL_I(res, u); if ((u != NULL) && (u->Typ() == BIGINTMAT_CMD)) if (u->next == NULL) return jjFANFULL_IM(res, u); WerrorS("fullFan: unexpected parameters"); return TRUE; } int getAmbientDimension(gfan::ZFan* zf) { return zf->getAmbientDimension(); } int getCodimension(gfan::ZFan* zf) { return zf->getCodimension(); } int getDimension(gfan::ZFan* zf) { return zf->getDimension(); } int getLinealityDimension(gfan::ZFan* zf) { return zf->getLinealityDimension(); } BOOLEAN numberOfConesOfDimension(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == INT_CMD)) { leftv w=v->next; if ((w != NULL) && (w->Typ() == INT_CMD)) { leftv x=w->next; if ((x != NULL) && (x->Typ() == INT_CMD)) { gfan::ZFan* zf = (gfan::ZFan*) u->Data(); int d = (int)(long)v->Data(); int o = (int)(long)w->Data(); int m = (int)(long)x->Data(); if ( (0<=d) && (d <= zf->getAmbientDimension()) && ((o == 0) || (o == 1)) && ((m == 0) || (m == 1))) { bool oo = (bool) o; bool mm = (bool) m; int ld = zf->getLinealityDimension(); if (d-ld>=0) { int n = zf->numberOfConesOfDimension(d-ld,oo,mm); res->rtyp = INT_CMD; res->data = (void*) (long) n; return FALSE; } res->rtyp = INT_CMD; res->data = (void*) (long) 0; return FALSE; } } } } } WerrorS("numberOfConesOfDimension: unexpected parameters"); return TRUE; } BOOLEAN ncones(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); int d = zf->getAmbientDimension(); int n = 0; for (int i=0; i<=d; i++) n = n + zf->numberOfConesOfDimension(i,0,0); res->rtyp = INT_CMD; res->data = (void*) (long) n; return FALSE; } WerrorS("ncones: unexpected parameters"); return TRUE; } BOOLEAN nmaxcones(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); int n = 0; for (int d=0; d<=zf->getAmbientDimension(); d++) n = n + zf->numberOfConesOfDimension(d,0,1); res->rtyp = INT_CMD; res->data = (void*) (long) n; return FALSE; } WerrorS("nmaxcones: unexpected parameters"); return TRUE; } bool isCompatible(const gfan::ZFan* zf, const gfan::ZCone* zc) { bool b = (zf->getAmbientDimension() == zc->ambientDimension()); if(b) { for (int d=0; d<=zf->getAmbientDimension(); d++) { for (int i=0; inumberOfConesOfDimension(d,0,1); i++) { gfan::ZCone zd = zf->getCone(d,i,0,1); gfan::ZCone zt = gfan::intersection(*zc,zd); zt.canonicalize(); b = b && zd.hasFace(zt); } } } return b; } BOOLEAN isCompatible(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); gfan::ZCone* zc = (gfan::ZCone*)v->Data(); int b = isCompatible(zf,zc); res->rtyp = INT_CMD; res->data = (void*) (long) b; return FALSE; } } WerrorS("isCompatible: unexpected parameters"); return TRUE; } BOOLEAN insertCone(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->rtyp==IDHDL) && (u->e==NULL) && (u->Typ() == fanID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); gfan::ZCone* zc = (gfan::ZCone*)v->Data(); zc->canonicalize(); leftv w=v->next; int n; if ((w != NULL) && (w->Typ() == INT_CMD)) n = (int)(long) w; if (n != 0) { if (!isCompatible(zf,zc)) { WerrorS("insertCone: cone and fan not compatible"); return TRUE; } } zf->insert(*zc); res->rtyp = NONE; res->data = NULL; IDDATA((idhdl)u->data) = (char*) zf; return FALSE; } } WerrorS("insertCone: unexpected parameters"); return TRUE; } bool containsInCollection(gfan::ZFan* zf, gfan::ZCone* zc) { gfan::ZVector zv=zc->getRelativeInteriorPoint(); for (int d=0; d<=zf->getAmbientDimension(); d++) { for (int i=0; inumberOfConesOfDimension(d,0,1); i++) { gfan::ZCone zd = zf->getCone(d,i,0,1); zd.canonicalize(); if (zd.containsRelatively(zv)) { gfan::ZCone temp = *zc; temp.canonicalize(); return (!(zd != temp)); } } } return 0; } BOOLEAN containsInCollection(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); gfan::ZCone* zc = (gfan::ZCone*)v->Data(); if((zf->getAmbientDimension() == zc->ambientDimension())) { res->rtyp = INT_CMD; res->data = (void*) (long) (int) containsInCollection(zf,zc); return FALSE; } WerrorS("containsInCollection: mismatching ambient dimensions"); return TRUE; } } WerrorS("containsInCollection: unexpected parameters"); return TRUE; } // BOOLEAN coneContaining(leftv res, leftv args) // { // leftv u=args; // if ((u != NULL) && (u->Typ() == fanID)) // { // leftv v=u->next; // if ((v != NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) // { // gfan::ZFan* zf = (gfan::ZFan*)u->Data(); // gfan::ZVector* point; // if (v->Typ() == INTVEC_CMD) // { // intvec* w0 = (intvec*) v->Data(); // bigintmat* w1 = iv2bim(w0,coeffs_BIGINT); // w1->inpTranspose(); // point = bigintmatToZVector(*w1); // delete w1; // } // else // { // bigintmat* w1 = (bigintmat*) v->Data(); // point = bigintmatToZVector(*w1); // } // lists L = (lists)omAllocBin(slists_bin); // res->rtyp = LIST_CMD; // res->data = (void*) L; // delete point; // return FALSE; // } // } // WerrorS("coneContaining: unexpected parameters"); // return TRUE; // } BOOLEAN removeCone(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); gfan::ZCone* zc = (gfan::ZCone*)v->Data(); zc->canonicalize(); leftv w=v->next; int n = 1; if ((w != NULL) && (w->Typ() == INT_CMD)) n = (int)(long) w; if (n != 0) { if (!containsInCollection(zf,zc)) { WerrorS("removeCone: cone not contained in fan"); return TRUE; } } zf->remove(*zc); res->rtyp = NONE; res->data = NULL; IDDATA((idhdl)u->data) = (char*) zf; return FALSE; } } WerrorS("removeCone: unexpected parameters"); return TRUE; } BOOLEAN getCone(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == INT_CMD)) { leftv w=v->next; if ((w != NULL) && (w->Typ() == INT_CMD)) { gfan::ZFan* zf = (gfan::ZFan*) u->Data(); int d = (int)(long)v->Data(); int i = (int)(long)w->Data(); int o = -1; int m = -1; leftv x=w->next; if ((x != NULL) && (x->Typ() == INT_CMD)) { o = (int)(long)x->Data(); leftv y=x->next; if ((y != NULL) && (y->Typ() == INT_CMD)) { m = (int)(long)y->Data(); } } if (o == -1) o = 0; if (m == -1) m = 0; if (((o == 0) || (o == 1)) && ((m == 0) || (m == 1))) { bool oo = (bool) o; bool mm = (bool) m; if (0<=d && d<=zf->getAmbientDimension()) { int ld = zf->getLinealityDimension(); if (0numberOfConesOfDimension(d-ld,oo,mm)) { i=i-1; if (d-ld>=0) { gfan::ZCone zc = zf->getCone(d-ld,i,oo,mm); res->rtyp = coneID; res->data = (void*)new gfan::ZCone(zc); return FALSE; } else { WerrorS("getCone: invalid dimension; no cones in this dimension"); return TRUE; } } else { WerrorS("getCone: invalid index"); return TRUE; } } else { WerrorS("getCone: invalid dimension"); return TRUE; } } else { WerrorS("getCone: invalid specifier for orbit or maximal"); return TRUE; } } } } WerrorS("getCone: unexpected parameters"); return TRUE; } BOOLEAN getCones(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == INT_CMD)) { gfan::ZFan* zf = (gfan::ZFan*) u->Data(); int d = (int)(long)v->Data(); int o = -1; int m = -1; leftv w=v->next; if ((w != NULL) && (w->Typ() == INT_CMD)) { o = (int)(long)w->Data(); leftv x=w->next; if ((x != NULL) && (x->Typ() == INT_CMD)) { m = (int)(long)x->Data(); } } if (o == -1) o = 0; if (m == -1) m = 0; if (((o == 0) || (o == 1)) && ((m == 0) || (m == 1))) { bool oo = (bool) o; bool mm = (bool) m; if (0<=d && d<=zf->getAmbientDimension()) { int ld = zf->getLinealityDimension(); if (d-ld>=0) { lists L = (lists)omAllocBin(slists_bin); int n = zf->numberOfConesOfDimension(d-ld,oo,mm); L->Init(n); for (int i=0; igetCone(d-ld,i,oo,mm); L->m[i].rtyp = coneID; L->m[i].data=(void*) new gfan::ZCone(zc); } res->rtyp = LIST_CMD; res->data = (void*) L; return FALSE; } else { WerrorS("getCones: invalid dimension; no cones in this dimension"); return TRUE; } } else { WerrorS("getCones: invalid dimension"); return TRUE; } } else { WerrorS("getCones: invalid specifier for orbit or maximal"); return TRUE; } } } WerrorS("getCones: unexpected parameters"); return TRUE; } int isSimplicial(gfan::ZFan* zf) { int i = zf->isSimplicial() ? 1 : 0; return i; } BOOLEAN isPure(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*) u->Data(); int b = zf->isPure(); res->rtyp = INT_CMD; res->data = (void*) (long) b; return FALSE; } WerrorS("isPure: unexpected parameters"); return TRUE; } // BOOLEAN isComplete(leftv res, leftv args) // { // leftv u=args; // if ((u != NULL) && (u->Typ() == fanID)) // { // gfan::ZFan* zf = (gfan::ZFan*) u->Data(); // int b = zf->isComplete(); // res->rtyp = INT_CMD; // res->data = (void*) (long) b; // return FALSE; // } // WerrorS("isComplete: unexpected parameters"); // return TRUE; // } BOOLEAN fVector(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*) u->Data(); gfan::ZVector zv=zf->getFVector(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(zv); return FALSE; } WerrorS("fVector: unexpected parameters"); return TRUE; } gfan::ZMatrix rays(const gfan::ZFan* const zf) { gfan::ZMatrix rays(0,zf->getAmbientDimension()); for (int i=0; inumberOfConesOfDimension(1,0,0); i++) { gfan::ZCone zc = zf->getCone(1, i, 0, 0); rays.append(zc.extremeRays()); } return rays; } int numberOfConesWithVector(gfan::ZFan* zf, gfan::ZVector* v) { int count = 0; int ambientDim = zf->getAmbientDimension(); for (int i=0; inumberOfConesOfDimension(ambientDim, 0, 0); i++) { gfan::ZCone zc = zf->getCone(ambientDim, i, 0, 0); if (zc.contains(*v)) { count = count +1; if (count > 1) return count; } } return count; } BOOLEAN numberOfConesWithVector(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == BIGINTMAT_CMD)) { gfan::ZFan* zf = (gfan::ZFan*) u->Data(); bigintmat* v0 = (bigintmat*) v->Data(); int ambientDim = zf->getAmbientDimension(); if (ambientDim != v0->cols()) { WerrorS("numberOfConesWithVector: mismatching dimensions"); return TRUE; } gfan::ZVector* v1 = bigintmatToZVector(*v0); int count = numberOfConesWithVector(zf, v1); delete v1; res->rtyp = INT_CMD; res->data = (void*) (long) count; return FALSE; } } WerrorS("numberOfConesWithVector: unexpected parameters"); return TRUE; } BOOLEAN fanFromString(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == STRING_CMD)) { std::string fanInString = (char*) u->Data(); std::istringstream s(fanInString); gfan::ZFan* zf = new gfan::ZFan(s); res->rtyp = fanID; res->data = (void*) zf; return FALSE; } WerrorS("fanFromString: unexpected parameters"); return TRUE; } BOOLEAN fanViaCones(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == LIST_CMD)) { lists L = (lists) u->Data(); if (lSize(L)>-1) { if (L->m[0].Typ() != coneID) { WerrorS("fanViaCones: list contains entries of wrong type"); return TRUE; } gfan::ZCone* zc = (gfan::ZCone*) L->m[0].Data(); gfan::ZFan* zf = new gfan::ZFan(zc->ambientDimension()); zf->insert(*zc); for (int i=1; i<=lSize(L); i++) { if (L->m[i].Typ() != coneID) { WerrorS("fanViaCones: entries of wrong type in list"); return TRUE; } gfan::ZCone* zc = (gfan::ZCone*) L->m[i].Data(); if (zc->ambientDimension() != zf->getAmbientDimension()) { WerrorS("fanViaCones: inconsistent ambient dimensions amongst cones in list"); return TRUE; } zf->insert(*zc); } res->rtyp = fanID; res->data = (void*) zf; return FALSE; } res->rtyp = fanID; res->data = (void*) new gfan::ZFan(0); return FALSE; } if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*) u->Data(); gfan::ZFan* zf = new gfan::ZFan(zc->ambientDimension()); zf->insert(*zc); while (u->next != NULL) { u = u->next; if (u->Typ() != coneID) { WerrorS("fanViaCones: arguments of wrong type"); return TRUE; } gfan::ZCone* zc = (gfan::ZCone*) u->Data(); if (zc->ambientDimension() != zf->getAmbientDimension()) { WerrorS("fanViaCones: inconsistent ambient dimensions amongst input cones"); return TRUE; } zf->insert(*zc); } res->rtyp = fanID; res->data = (void*) zf; return FALSE; } if (u == NULL) { res->rtyp = fanID; res->data = (void*) new gfan::ZFan(0); return FALSE; } WerrorS("fanViaCones: unexpected parameters"); return TRUE; } // BOOLEAN tropicalVariety(leftv res, leftv args) // { // leftv u=args; // if ((u != NULL) && (u->Typ() == POLY_CMD)) // { // int n = rVar(currRing); // gfan::ZFan* zf = new gfan::ZFan(n); // int* expv1 = (int*)omAlloc((n+1)*sizeof(int)); // int* expv2 = (int*)omAlloc((n+1)*sizeof(int)); // int* expvr = (int*)omAlloc((n+1)*sizeof(int)); // gfan::ZVector expw1 = gfan::ZVector(n); // gfan::ZVector expw2 = gfan::ZVector(n); // gfan::ZVector expwr = gfan::ZVector(n); // gfan::ZMatrix eq, ineq; // for (poly s1=(poly)u->Data(); s1!=NULL; pIter(s1)) // { // pGetExpV(s1,expv1); // expw1 = intStar2ZVector(n,expv1); // for (poly s2=pNext(s1); s2!=NULL; pIter(s2)) // { // pGetExpV(s2,expv2); // expw2 = intStar2ZVector(n,expv2); // eq = gfan::ZMatrix(0,n); // eq.appendRow(expw1-expw2); // ineq = gfan::ZMatrix(0,n); // for (poly r=(poly)u->Data(); r!=NULL; pIter(r)) // { // pGetExpV(r,expvr); // expwr = intStar2ZVector(n,expvr); // if ((r!=s1) && (r!=s2)) // { // ineq.appendRow(expw1-expwr); // } // } // gfan::ZCone zc = gfan::ZCone(ineq,eq); // zf->insert(zc); // } // } // omFreeSize(expv1,(n+1)*sizeof(int)); // omFreeSize(expv2,(n+1)*sizeof(int)); // omFreeSize(expvr,(n+1)*sizeof(int)); // res->rtyp = fanID; // res->data = (void*) zf; // return FALSE; // } // WerrorS("tropicalVariety: unexpected parameters"); // return TRUE; // } gfan::ZFan commonRefinement(gfan::ZFan zf, gfan::ZFan zg) { assume(zf.getAmbientDimension() == zg.getAmbientDimension()); // gather all maximal cones of f and g std::list maximalConesOfF; for (int d=0; d<=zf.getAmbientDimension(); d++) for (int i=0; i maximalConesOfG; for (int d=0; d<=zg.getAmbientDimension(); d++) for (int i=0; i::iterator itf=maximalConesOfF.begin(); itf != maximalConesOfF.end(); itf++) for (std::list::iterator itg=maximalConesOfG.begin(); itg != maximalConesOfG.end(); itg++) zr.insert(intersection(*itf,*itg)); return zr; } BOOLEAN commonRefinement(leftv res, leftv args) { leftv u=args; if ((u != NULL) && (u->Typ() == fanID)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*) u->Data(); gfan::ZFan* zg = (gfan::ZFan*) v->Data(); gfan::ZFan* zr = new gfan::ZFan(commonRefinement(*zf,*zg)); res->rtyp = fanID; res->data = (void*) zr; return FALSE; } } WerrorS("commonRefinement: unexpected parameters"); return TRUE; } // BOOLEAN grFan(leftv res, leftv h) // { // /*======== GFAN ==============*/ // /* // WILL HAVE TO CHANGE RETURN TYPE TO LIST_CMD // */ // /* // heuristic: // 0 = keep all Groebner bases in memory // 1 = write all Groebner bases to disk and read whenever necessary // 2 = use a mixed heuristic, based on length of Groebner bases // */ // if( h!=NULL && h->Typ()==IDEAL_CMD && h->next!=NULL && h->next->Typ()==INT_CMD) // { // int heuristic; // heuristic=(int)(long)h->next->Data(); // ideal I=((ideal)h->Data()); // #ifndef USE_ZFAN // #define USE_ZFAN // #endif // #ifndef USE_ZFAN // res->rtyp=LIST_CMD; //res->rtyp=coneID; res->data(void*)zcone; // res->data=(lists) grfan(I,heuristic,FALSE); // #else // res->rtyp=fanID; // res->data=(void*)(grfan(I,heuristic,FALSE)); // #endif // return FALSE; // } // else // { // WerrorS("Usage: grfan(,)"); // return TRUE; // } // } //Possibility to have only one Groebner cone computed by specifying a weight vector FROM THE RELATIVE INTERIOR! //Needs wp as ordering! // if(strcmp(sys_cmd,"grcone")==0) // { // if(h!=NULL && h->Typ()==IDEAL_CMD && h->next!=NULL && h->next->Typ()==INT_CMD) // { // ideal I=((ideal)h->Data()); // res->rtyp=LIST_CMD; // res->data=(lists)grcone_by_intvec(I); // } // } void bbfan_setup(SModulFunctions* p) { blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox)); // all undefined entries will be set to default in setBlackboxStuff // the default Print is quite usefule, // all other are simply error messages b->blackbox_destroy=bbfan_destroy; b->blackbox_String=bbfan_String; //b->blackbox_Print=blackbox_default_Print; b->blackbox_Init=bbfan_Init; b->blackbox_Copy=bbfan_Copy; b->blackbox_Assign=bbfan_Assign; p->iiAddCproc("","emptyFan",FALSE,emptyFan); p->iiAddCproc("","fullFan",FALSE,fullFan); /* the following functions are implemented in bbcone.cc */ // iiAddCproc("","containsInSupport",FALSE,containsInSupport); // iiAddCproc("","getAmbientDimension",FALSE,getAmbientDimension); // iiAddCproc("","getCodimension",FALSE,getDimension); // iiAddCproc("","getDimension",FALSE,getDimension); // iiAddCproc("","getLinealityDimension",FALSE,getLinealityDimension); // iiAddCproc("","isSimplicial",FALSE,isSimplicial); /********************************************************/ p->iiAddCproc("","isCompatible",FALSE,isCompatible); p->iiAddCproc("","numberOfConesOfDimension",FALSE,numberOfConesOfDimension); p->iiAddCproc("","ncones",FALSE,ncones); p->iiAddCproc("","nmaxcones",FALSE,nmaxcones); p->iiAddCproc("","insertCone",FALSE,insertCone); p->iiAddCproc("","removeCone",FALSE,removeCone); p->iiAddCproc("","getCone",FALSE,getCone); p->iiAddCproc("","getCones",FALSE,getCones); p->iiAddCproc("","isPure",FALSE,isPure); p->iiAddCproc("","fanFromString",FALSE,fanFromString); p->iiAddCproc("","fanViaCones",FALSE,fanViaCones); p->iiAddCproc("","numberOfConesWithVector",FALSE,numberOfConesWithVector); // iiAddCproc("","isComplete",FALSE,isComplete); not working as expected, should leave this to polymake p->iiAddCproc("","fVector",FALSE,fVector); p->iiAddCproc("","containsInCollection",FALSE,containsInCollection); // p->iiAddCproc("","tropicalVariety",FALSE,tropicalVariety); p->iiAddCproc("","commonRefinement",FALSE,commonRefinement); // iiAddCproc("","grFan",FALSE,grFan); fanID=setBlackboxStuff(b,"fan"); //Print("created type %d (fan)\n",fanID); } #endif // gfan::ZFan commonRefinementCompleteFans(const gfan::ZFan &zf, const gfan::ZFan &zg) // { // assume(zf->getAmbientDimension() == zg->getAmbientDimension()); // gfan::ZFan zfg = gfan::ZFan(zf->getAmbientDimension()); // int d = zf->getAmbientDimension(); // for (int i=0; inumberOfConesOfDimension(d,0,1); i++) // for (int j=0; jnumberOfConesOfDimension(d,0,1); j++) // { // gfan::ZCone zc = intersection(zf->getCone(d,i,0,1),zg->getCone(d,j,0,1)); // if (zc.dimension()==d) zgf.insert(zc); // } // return zfg; // } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/bbfan.h000066400000000000000000000011061266270727000227040ustar00rootroot00000000000000#ifndef BBFAN_H #define BBFAN_H #include #if HAVE_GFANLIB #include #include extern int fanID; void bbfan_setup(SModulFunctions* p); bool isCompatible(const gfan::ZFan* zf, const gfan::ZCone* zc); int getAmbientDimension(gfan::ZFan* zf); int getCodimension(gfan::ZFan* zf); int getDimension(gfan::ZFan* zf); int getLinealityDimension(gfan::ZFan* zf); int isSimplicial(gfan::ZFan* zf); gfan::Matrix rays(const gfan::ZFan* const zf); gfan::ZFan commonRefinement(gfan::ZFan zf, gfan::ZFan zg); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/bbpolytope.cc000066400000000000000000000313741266270727000241630ustar00rootroot00000000000000#include #if HAVE_GFANLIB #include #include #include #include #include #include #include #include #include int polytopeID; std::string bbpolytopeToString(gfan::ZCone const &c) { std::stringstream s; gfan::ZMatrix i=c.getInequalities(); gfan::ZMatrix e=c.getEquations(); s<<"AMBIENT_DIM"<Data()!=NULL) { gfan::ZCone* zd = (gfan::ZCone*)l->Data(); delete zd; } newZc = new gfan::ZCone(); } else if (r->Typ()==l->Typ()) { if (l->Data()!=NULL) { gfan::ZCone* zd = (gfan::ZCone*)l->Data(); delete zd; } gfan::ZCone* zc = (gfan::ZCone*)r->Data(); newZc = new gfan::ZCone(*zc); } // else if (r->Typ()==INT_CMD) TODO:r->Typ()==BIGINTMAT_CMD // { // int ambientDim = (int)(long)r->Data(); // if (ambientDim < 0) // { // Werror("expected an int >= 0, but got %d", ambientDim); // return TRUE; // } // if (l->Data()!=NULL) // { // gfan::ZCone* zd = (gfan::ZCone*)l->Data(); // delete zd; // } // newZc = new gfan::ZCone(ambientDim); // } else { Werror("assign Type(%d) = Type(%d) not implemented",l->Typ(),r->Typ()); return TRUE; } if (l->rtyp==IDHDL) { IDDATA((idhdl)l->data) = (char*) newZc; } else { l->data=(void *)newZc; } return FALSE; } char* bbpolytope_String(blackbox* /*b*/, void *d) { if (d==NULL) return omStrDup("invalid object"); else { gfan::ZCone* zc = (gfan::ZCone*)d; std::string s=bbpolytopeToString(*zc); return omStrDup(s.c_str()); } } void bbpolytope_destroy(blackbox* /*b*/, void *d) { if (d!=NULL) { gfan::ZCone* zc = (gfan::ZCone*) d; delete zc; } } void* bbpolytope_Copy(blackbox* /*b*/, void *d) { gfan::ZCone* zc = (gfan::ZCone*)d; gfan::ZCone* newZc = new gfan::ZCone(*zc); return newZc; } static BOOLEAN ppCONERAYS1(leftv res, leftv v) { /* method for generating a cone object from half-lines (cone = convex hull of the half-lines; note: there may be entire lines in the cone); valid parametrizations: (bigintmat) */ bigintmat* rays = NULL; if (v->Typ() == INTMAT_CMD) { intvec* rays0 = (intvec*) v->Data(); rays = iv2bim(rays0,coeffs_BIGINT); } else rays = (bigintmat*) v->Data(); gfan::ZMatrix* zm = bigintmatToZMatrix(rays); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(*zm, gfan::ZMatrix(0, zm->getWidth())); res->rtyp = polytopeID; res->data = (void*) zc; delete zm; if (v->Typ() == INTMAT_CMD) delete rays; return FALSE; } static BOOLEAN ppCONERAYS3(leftv res, leftv u, leftv v) { /* method for generating a cone object from half-lines (any point in the cone being the sum of a point in the convex hull of the half-lines and a point in the span of the lines), and an integer k; valid parametrizations: (bigintmat, int); Errors will be invoked in the following cases: - k not 0 or 1; if the k=1, then the extreme rays are known: each half-line spans a (different) extreme ray */ bigintmat* rays = NULL; if (u->Typ() == INTMAT_CMD) { intvec* rays0 = (intvec*) u->Data(); rays = iv2bim(rays0,coeffs_BIGINT); } else rays = (bigintmat*) u->Data(); int k = (int)(long)v->Data(); if ((k < 0) || (k > 1)) { WerrorS("expected int argument in [0..1]"); return TRUE; } k=k*2; gfan::ZMatrix* zm = bigintmatToZMatrix(rays); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(*zm,gfan::ZMatrix(0, zm->getWidth())); //k should be passed on to zc; not available yet res->rtyp = polytopeID; res->data = (void*) zc; delete zm; if (v->Typ() == INTMAT_CMD) delete rays; return FALSE; } BOOLEAN polytopeViaVertices(leftv res, leftv args) { leftv u = args; if ((u != NULL) && ((u->Typ() == BIGINTMAT_CMD) || (u->Typ() == INTMAT_CMD))) { if (u->next == NULL) return ppCONERAYS1(res, u); leftv v = u->next; if ((v != NULL) && (v->Typ() == INT_CMD)) { if (v->next == NULL) return ppCONERAYS3(res, u, v); } } WerrorS("polytopeViaPoints: unexpected parameters"); return TRUE; } static BOOLEAN ppCONENORMALS1(leftv res, leftv v) { /* method for generating a cone object from inequalities; valid parametrizations: (bigintmat) */ bigintmat* ineq = NULL; if (v->Typ() == INTMAT_CMD) { intvec* ineq0 = (intvec*) v->Data(); ineq = iv2bim(ineq0,coeffs_BIGINT); } else ineq = (bigintmat*) v->Data(); gfan::ZMatrix* zm = bigintmatToZMatrix(ineq); gfan::ZCone* zc = new gfan::ZCone(*zm, gfan::ZMatrix(0, zm->getWidth())); delete zm; if (v->Typ() == INTMAT_CMD) delete ineq; res->rtyp = polytopeID; res->data = (void*) zc; return FALSE; } static BOOLEAN ppCONENORMALS2(leftv res, leftv u, leftv v) { /* method for generating a cone object from iequalities, and equations (...) valid parametrizations: (bigintmat, bigintmat) Errors will be invoked in the following cases: - u and v have different numbers of columns */ bigintmat* ineq = NULL; bigintmat* eq = NULL; if (u->Typ() == INTMAT_CMD) { intvec* ineq0 = (intvec*) u->Data(); ineq = iv2bim(ineq0,coeffs_BIGINT); } else ineq = (bigintmat*) u->Data(); if (v->Typ() == INTMAT_CMD) { intvec* eq0 = (intvec*) v->Data(); eq = iv2bim(eq0,coeffs_BIGINT); } else eq = (bigintmat*) v->Data(); if (ineq->cols() != eq->cols()) { Werror("expected same number of columns but got %d vs. %d", ineq->cols(), eq->cols()); return TRUE; } gfan::ZMatrix* zm1 = bigintmatToZMatrix(ineq); gfan::ZMatrix* zm2 = bigintmatToZMatrix(eq); gfan::ZCone* zc = new gfan::ZCone(*zm1, *zm2); delete zm1; delete zm2; if (u->Typ() == INTMAT_CMD) delete ineq; if (v->Typ() == INTMAT_CMD) delete eq; res->rtyp = polytopeID; res->data = (void*) zc; return FALSE; } static BOOLEAN ppCONENORMALS3(leftv res, leftv u, leftv v, leftv w) { /* method for generating a cone object from inequalities, equations, and an integer k; valid parametrizations: (bigintmat, bigintmat, int); Errors will be invoked in the following cases: - u and v have different numbers of columns, - k not in [0..3]; if the 2^0-bit of k is set, then ... */ bigintmat* ineq = NULL; bigintmat* eq = NULL; if (u->Typ() == INTMAT_CMD) { intvec* ineq0 = (intvec*) u->Data(); ineq = iv2bim(ineq0,coeffs_BIGINT); } else ineq = (bigintmat*) u->Data(); if (v->Typ() == INTMAT_CMD) { intvec* eq0 = (intvec*) v->Data(); eq = iv2bim(eq0,coeffs_BIGINT); } else eq = (bigintmat*) v->Data(); if (ineq->cols() != eq->cols()) { Werror("expected same number of columns but got %d vs. %d", ineq->cols(), eq->cols()); return TRUE; } int k = (int)(long)w->Data(); if ((k < 0) || (k > 3)) { WerrorS("expected int argument in [0..3]"); return TRUE; } gfan::ZMatrix* zm1 = bigintmatToZMatrix(ineq); gfan::ZMatrix* zm2 = bigintmatToZMatrix(eq); gfan::ZCone* zc = new gfan::ZCone(*zm1, *zm2, k); delete zm1; delete zm2; if (u->Typ() == INTMAT_CMD) delete ineq; if (v->Typ() == INTMAT_CMD) delete eq; res->rtyp = polytopeID; res->data = (void*) zc; return FALSE; } BOOLEAN polytopeViaNormals(leftv res, leftv args) { leftv u = args; if ((u != NULL) && ((u->Typ() == BIGINTMAT_CMD) || (u->Typ() == INTMAT_CMD))) { if (u->next == NULL) return ppCONENORMALS1(res, u); } leftv v = u->next; if ((v != NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTMAT_CMD))) { if (v->next == NULL) return ppCONENORMALS2(res, u, v); } leftv w = v->next; if ((w != NULL) && (w->Typ() == INT_CMD)) { if (w->next == NULL) return ppCONENORMALS3(res, u, v, w); } WerrorS("polytopeViaInequalities: unexpected parameters"); return TRUE; } BOOLEAN vertices(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZMatrix zmat = zc->extremeRays(); res->rtyp = BIGINTMAT_CMD; res->data = (void*)zMatrixToBigintmat(zmat); return FALSE; } WerrorS("vertices: unexpected parameters"); return TRUE; } int getAmbientDimension(gfan::ZCone* zc) // zc is meant to represent a polytope here { // hence ambientDimension-1 return zc->ambientDimension()-1; } int getCodimension(gfan::ZCone *zc) { return zc->codimension(); } int getDimension(gfan::ZCone* zc) { return zc->dimension()-1; } gfan::ZVector intStar2ZVectorWithLeadingOne(const int d, const int* i) { gfan::ZVector zv(d+1); zv[0]=1; for(int j=1; j<=d; j++) { zv[j]=i[j]; } return zv; } BOOLEAN newtonPolytope(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == POLY_CMD)) { poly p = (poly)u->Data(); int N = rVar(currRing); gfan::ZMatrix zm(1,N+1); int *leadexpv = (int*)omAlloc((N+1)*sizeof(int)); while (p!=NULL) { pGetExpV(p,leadexpv); gfan::ZVector zv = intStar2ZVectorWithLeadingOne(N, leadexpv); zm.appendRow(zv); pIter(p); } omFreeSize(leadexpv,(N+1)*sizeof(int)); gfan::ZCone* zc = new gfan::ZCone(); *zc = gfan::ZCone::givenByRays(zm, gfan::ZMatrix(0, zm.getWidth())); res->rtyp = polytopeID; res->data = (void*) zc; return FALSE; } WerrorS("newtonPolytope: unexpected parameters"); return TRUE; } BOOLEAN scalePolytope(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == INT_CMD)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == polytopeID)) { int s = (int)(long) u->Data(); gfan::ZCone* zp = (gfan::ZCone*) v->Data(); gfan::ZMatrix zm = zp->extremeRays(); for (int i=0; irtyp = polytopeID; res->data = (void*) zq; return FALSE; } } WerrorS("scalePolytope: unexpected parameters"); return TRUE; } BOOLEAN dualPolytope(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*) u->Data(); gfan::ZCone* zq = new gfan::ZCone(zp->dualCone()); res->rtyp = polytopeID; res->data = (void*) zq; return FALSE; } WerrorS("dualPolytope: unexpected parameters"); return TRUE; } void bbpolytope_setup(SModulFunctions* p) { blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox)); // all undefined entries will be set to default in setBlackboxStuff // the default Print is quite usefule, // all other are simply error messages b->blackbox_destroy=bbpolytope_destroy; b->blackbox_String=bbpolytope_String; //b->blackbox_Print=blackbox_default_Print; b->blackbox_Init=bbpolytope_Init; b->blackbox_Copy=bbpolytope_Copy; b->blackbox_Assign=bbpolytope_Assign; p->iiAddCproc("","polytopeViaPoints",FALSE,polytopeViaVertices); p->iiAddCproc("","polytopeViaInequalities",FALSE,polytopeViaNormals); p->iiAddCproc("","vertices",FALSE,vertices); p->iiAddCproc("","newtonPolytope",FALSE,newtonPolytope); p->iiAddCproc("","scalePolytope",FALSE,scalePolytope); p->iiAddCproc("","dualPolytope",FALSE,dualPolytope); /********************************************************/ /* the following functions are implemented in bbcone.cc */ // iiAddCproc("","getAmbientDimension",FALSE,getAmbientDimension); // iiAddCproc("","getCodimension",FALSE,getAmbientDimension); // iiAddCproc("","getDimension",FALSE,getDimension); /********************************************************/ /* the following functions are identical to those in bbcone.cc */ // iiAddCproc("","facets",FALSE,facets); // iiAddCproc("","setLinearForms",FALSE,setLinearForms); // iiAddCproc("","getLinearForms",FALSE,getLinearForms); // iiAddCproc("","setMultiplicity",FALSE,setMultiplicity); // iiAddCproc("","getMultiplicity",FALSE,getMultiplicity); // iiAddCproc("","hasFace",FALSE,hasFace); /***************************************************************/ // iiAddCproc("","getEquations",FALSE,getEquations); // iiAddCproc("","getInequalities",FALSE,getInequalities); polytopeID=setBlackboxStuff(b,"polytope"); //Print("created type %d (polytope)\n",polytopeID); } #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/bbpolytope.h000066400000000000000000000007671266270727000240270ustar00rootroot00000000000000#ifndef BBPOLYTOPE_H #define BBPOLYTOPE_H #include #if HAVE_GFANLIB #include #include extern int polytopeID; void bbpolytope_setup(SModulFunctions* p); // zc is meant to represent a polytope here bigintmat* getFacetNormals(gfan::ZCone *zc); int getAmbientDimension(gfan::ZCone* zc); int getCodimension(gfan::ZCone *zc); int getDimension(gfan::ZCone* zc); gfan::ZVector intStar2ZVectorWithLeadingOne(const int d, const int* i); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/callgfanlib_conversion.cc000066400000000000000000000072241266270727000265040ustar00rootroot00000000000000#include #include #include #include #include // for coeffs_BIGINT number integerToNumber(const gfan::Integer &I) { mpz_t i; mpz_init(i); I.setGmp(i); long m = 268435456; if(mpz_cmp_si(i,m)) { int temp = (int) mpz_get_si(i); return n_Init(temp,coeffs_BIGINT); } else return n_InitMPZ(i,coeffs_BIGINT); } bigintmat* zVectorToBigintmat(const gfan::ZVector &zv) { int d=zv.size(); bigintmat* bim = new bigintmat(1,d,coeffs_BIGINT); for(int i=1;i<=d;i++) { number temp = integerToNumber(zv[i-1]); bim->set(1,i,temp); n_Delete(&temp,coeffs_BIGINT); } return bim; } bigintmat* zMatrixToBigintmat(const gfan::ZMatrix &zm) { int d=zm.getHeight(); int n=zm.getWidth(); bigintmat* bim = new bigintmat(d,n,coeffs_BIGINT); for(int i=1;i<=d;i++) for(int j=1; j<=n; j++) { number temp = integerToNumber(zm[i-1][j-1]); bim->set(i,j,temp); n_Delete(&temp,coeffs_BIGINT); } return bim; } gfan::Integer* numberToInteger(const number &n) { if (SR_HDL(n) & SR_INT) return new gfan::Integer(SR_TO_INT(n)); else return new gfan::Integer(n->z); } gfan::ZMatrix* bigintmatToZMatrix(const bigintmat &bim) { int d=bim.rows(); int n=bim.cols(); gfan::ZMatrix* zm = new gfan::ZMatrix(d,n); for(int i=0;iStringAsPrinted(); if (s==NULL) s = (char*) omAlloc0(sizeof(char)); delete bim; return s; } gfan::ZFan* toFanStar(std::set setOfCones) { if (setOfCones.size() > 0) { std::set::iterator cone = setOfCones.begin(); gfan::ZFan* zf = new gfan::ZFan(cone->ambientDimension()); for (std::set::iterator cone = setOfCones.begin(); cone!=setOfCones.end(); cone++) zf->insert(*cone); return zf; } else return new gfan::ZFan(gfan::ZFan::fullFan(currRing->N)); } std::set rays(std::set setOfCones) { std::set setOfRays; for (std::set::iterator cone = setOfCones.begin(); cone!=setOfCones.end(); cone++) { gfan::ZMatrix raysOfCone = cone->extremeRays(); for (int i=0; i #include #include #include gfan::Integer* numberToInteger(const number &n); number integerToNumber(const gfan::Integer &I); bigintmat* zVectorToBigintmat(const gfan::ZVector &zv); bigintmat* zMatrixToBigintmat(const gfan::ZMatrix &zm); gfan::ZMatrix* bigintmatToZMatrix(const bigintmat &bim); gfan::ZVector* bigintmatToZVector(const bigintmat &bim); gfan::ZVector intStar2ZVector(const int d, const int* i); gfan::ZVector wvhdlEntryToZVector(const int n, const int* wvhdl0); int* ZVectorToIntStar(const gfan::ZVector &v, bool &overflow); char* toString(gfan::ZMatrix const &m); gfan::ZVector expvToZVector(const int n, const int* expv); gfan::ZFan* toFanStar(std::set setOfCones); std::set rays(std::set setOfCones); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/containsMonomial.cc000066400000000000000000000135451266270727000253160ustar00rootroot00000000000000#include #include #include #include poly checkForMonomialViaSuddenSaturation(const ideal I, const ring r) { ring origin = currRing; if (currRing != r) rChangeCurrRing(r); ideal M = idInit(1); M->m[0] = p_Init(r); for (int i=1; i<=rVar(r); i++) p_SetExp(M->m[0],i,1,r); p_SetCoeff(M->m[0],n_Init(1,r->cf),r); p_Setm(M->m[0],r); p_Test(M->m[0],r); ideal J = id_Copy(I,r); bool b; int k = 0; if (currRing != r) rChangeCurrRing(r); intvec* nullVector = NULL; do { ideal Jstd = kStd(J,currRing->qideal,testHomog,&nullVector); ideal JquotM = idQuot(Jstd,M,true,true); ideal JquotMredJ = kNF(Jstd,currRing->qideal,JquotM); b = idIs0(JquotMredJ); id_Delete(&Jstd,r); id_Delete(&J,r); J = JquotM; id_Delete(&JquotMredJ,r); k++; } while (!b); poly monom = NULL; if (id_IsConstant(J,r)) { monom = p_Init(r); for (int i=1; i<=rVar(r); i++) p_SetExp(monom,i,k,r); p_SetCoeff(monom,n_Init(1,r->cf),r); p_Setm(monom,r); } id_Delete(&M,r); id_Delete(&J,r); if (currRing != origin) rChangeCurrRing(origin); return monom; } BOOLEAN checkForMonomial(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { ideal I; poly monom; omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); I = (ideal) u->CopyD(); monom = checkForMonomialViaSuddenSaturation(I,currRing); id_Delete(&I,currRing); p_Delete(&monom,currRing); omUpdateInfo(); Print("usedBytesAfter=%ld\n",om_Info.UsedBytes); I = (ideal) u->Data(); res->rtyp = POLY_CMD; res->data = (char*) checkForMonomialViaSuddenSaturation(I,currRing); return FALSE; } return TRUE; } #if 0 // /*** // * Creates an int* representing the transposition of the last two variables // **/ // static inline int* createPermutationVectorForSaturation(static const ring &r) // { // int* w = (int*) omAlloc0((rVar(r)+1)*sizeof(int)); // for (int i=1; i<=rVar(r)-2; i++) // w[i] = i; // w[rVar(r)-1] = rVar(r); // w[rVar(r)] = rVar(r)-1; // } /*** * Creates an int* representing the permutation * 1 -> 1, ..., i-1 -> i-1, i -> n, i+1 -> n-1, ... , n -> i **/ static inline int* createPermutationVectorForSaturation(const ring &r, const int i) { int* sigma = (int*) omAlloc0((rVar(r)+1)*sizeof(int)); int j; for (j=1; j 1, ..., i -> i, i+1 -> n, i+2 -> n-1, ... , n -> i+1 * to an int* representing the permutation * 1 -> 1, ..., i-1 -> i-1, i -> n, i+1 -> n-1, ... , n -> i **/ static void changePermutationVectorForSaturation(int* sigma, const ring &r, const int i) { for (int j=i; jwvhdl[0][j] = r->wvhdl[0][sigma[j+1]]; s->wvhdl[1][j] = r->wvhdl[1][sigma[j+1]]; } rComplete(s,1); rTest(s); return s; } /*** * creates a ring s that is a copy of r except with ordering wp(w) **/ static inline ring createInitialRingForSaturation(const ring &r, const gfan::ZVector &w, bool &ok) { assume(rVar(r) == (int) w.size()); ring s = rCopy0(r); int i; for (i=0; s->order[i]; i++) omFreeSize(s->wvhdl[i],rVar(r)*sizeof(int)); i++; omFreeSize(s->order,i*sizeof(int)); s->order = (int*) omAlloc0(3*sizeof(int)); omFreeSize(s->block0,i*sizeof(int)); s->block0 = (int*) omAlloc0(3*sizeof(int)); omFreeSize(s->block1,i*sizeof(int)); s->block1 = (int*) omAlloc0(3*sizeof(int)); omFreeSize(s->wvhdl,i*sizeof(int*)); s->wvhdl = (int**) omAlloc0(3*sizeof(int*)); s->order[0] = ringorder_wp; s->block0[0] = 1; s->block1[0] = rVar(r); s->wvhdl[0] = ZVectorToIntStar(w,ok); s->order[1]=ringorder_C; rComplete(s,1); rTest(s); return s; } /*** * Given an weighted homogeneous ideal I with respect to weight w * that in standard basis form with respect to the ordering ws(-w), * derives the standard basis of I:^\infty * and returns a long k such that I:^\infty=I:^k **/ static long deriveStandardBasisOfSaturation(ideal &I, ring &r) { long k=0, l; poly current; for (int i=0; im[i]; l = p_GetExp(current,rVar(r),r); if (kcf / I->m[0] ring r = rCopy0(currRing); nKillChar(r->cf); r->cf = nInitChar(n_Zp,(void*)(long)n_Int(p_GetCoeff(I->m[0],currRing),currRing->cf)); rComplete(r); rTest(r); ideal J = id_Copy(I, currRing); poly cache; number temp; for (int i=0; im[i]; while (cache) { // TODO: temp = npMapGMP(p_GetCoeff(cache,currRing),currRing->cf,r->cf); p_SetCoeff(cache,temp,r); pIter(cache); } } J = kStd(J,NULL,isHomog,NULL); bool b = false; ring s = createInitialRingForSaturation(currRing, w, b); if (b) { WerrorS("containsMonomial: overflow in weight vector"); return NULL; } return NULL; } #endif //0 singular-4.0.3+ds/Singular/dyn_modules/gfanlib/containsMonomial.h000066400000000000000000000004341266270727000251510ustar00rootroot00000000000000#ifndef CONTAINS_MONOMIAL_H #define CONTAINS_MONOMIAL_H #include #include #include poly checkForMonomialViaSuddenSaturation(const ideal I, const ring r); BOOLEAN checkForMonomial(leftv res, leftv args); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/flip.cc000066400000000000000000000100551266270727000227270ustar00rootroot00000000000000#include #include #include #include #include #include #include static void deleteOrdering(ring r) { if (r->order != NULL) { int i=rBlocks(r); assume(r->block0 != NULL && r->block1 != NULL && r->wvhdl != NULL); /* delete order */ omFreeSize((ADDRESS)r->order,i*sizeof(int)); omFreeSize((ADDRESS)r->block0,i*sizeof(int)); omFreeSize((ADDRESS)r->block1,i*sizeof(int)); /* delete weights */ for (int j=0; jwvhdl[j]!=NULL) omFree(r->wvhdl[j]); omFreeSize((ADDRESS)r->wvhdl,i*sizeof(int *)); } else assume(r->block0 == NULL && r->block1 == NULL && r->wvhdl == NULL); return; } /*** * Given a Groebner basis I of an ideal in r, an interior Point * on a face of the maximal Groebner cone associated to the ordering on r, * and a vector pointing outwards from it, * returns a pair (Is,s) such that: * (1) s is the same mathematical ring as r, but with a new ordering such that * the interior point lies on the intersection of both maximal Groebner cones * (2) Is is a Groebner basis of the same ideal with respect to the ordering on s **/ std::pair flip(const ideal I, const ring r, const gfan::ZVector interiorPoint, const gfan::ZVector facetNormal, const gfan::ZVector adjustedInteriorPoint, const gfan::ZVector adjustedFacetNormal) { /* create a ring with weighted ordering */ bool ok; ring sAdjusted = rCopy0(r); int n = rVar(sAdjusted); deleteOrdering(sAdjusted); sAdjusted->order = (int*) omAlloc0(4*sizeof(int)); sAdjusted->block0 = (int*) omAlloc0(4*sizeof(int)); sAdjusted->block1 = (int*) omAlloc0(4*sizeof(int)); sAdjusted->wvhdl = (int**) omAlloc0(4*sizeof(int**)); sAdjusted->order[0] = ringorder_a; sAdjusted->block0[0] = 1; sAdjusted->block1[0] = n; sAdjusted->wvhdl[0] = ZVectorToIntStar(adjustedInteriorPoint,ok); sAdjusted->order[1] = ringorder_wp; sAdjusted->block0[1] = 1; sAdjusted->block1[1] = n; sAdjusted->wvhdl[1] = ZVectorToIntStar(adjustedFacetNormal,ok); sAdjusted->order[2] = ringorder_C; rComplete(sAdjusted); rTest(sAdjusted); nMapFunc identity = n_SetMap(r->cf,sAdjusted->cf); /* compute initial ideal and map it to the new ordering */ ideal inIr = initial(I,r,interiorPoint); int k = idSize(I); ideal inIsAdjusted = idInit(k); for (int i=0; im[i] = p_PermPoly(inIr->m[i],NULL,r,sAdjusted,identity,NULL,0); id_Delete(&inIr,r); /* compute Groebner basis of the initial ideal */ intvec* nullVector = NULL; ring origin = currRing; rChangeCurrRing(sAdjusted); ideal inIsAdjustedGB = kStd(inIsAdjusted,currRing->qideal,testHomog,&nullVector); ideal IsAdjustedGB = lift(I,r,inIsAdjustedGB,sAdjusted); id_Delete(&inIsAdjusted,sAdjusted); id_Delete(&inIsAdjustedGB,sAdjusted); ring s = rCopy0(r); n = rVar(s); deleteOrdering(s); s->order = (int*) omAlloc0(5*sizeof(int)); s->block0 = (int*) omAlloc0(5*sizeof(int)); s->block1 = (int*) omAlloc0(5*sizeof(int)); s->wvhdl = (int**) omAlloc0(5*sizeof(int**)); s->order[0] = ringorder_a; s->block0[0] = 1; s->block1[0] = n; s->wvhdl[0] = ZVectorToIntStar(interiorPoint,ok); s->order[1] = ringorder_a; s->block0[1] = 1; s->block1[1] = n; s->wvhdl[1] = ZVectorToIntStar(facetNormal,ok); s->order[2] = ringorder_dp; s->block0[2] = 1; s->block1[2] = n; s->order[3] = ringorder_C; rComplete(s); rTest(s); identity = n_SetMap(sAdjusted->cf,s->cf); k = idSize(IsAdjustedGB); ideal IsGB = idInit(k); for (int i=0; im[i] = p_PermPoly(IsAdjustedGB->m[i],NULL,sAdjusted,s,identity,NULL,0); id_Delete(&IsAdjustedGB,sAdjusted); rDelete(sAdjusted); rChangeCurrRing(origin); /* lift the Groebner basis of the initial ideal * to a Groebner basis of the original ideal, * the currRingChange is solely for sake of performance */ return std::make_pair(IsGB,s); } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/flip.h000066400000000000000000000007141266270727000225720ustar00rootroot00000000000000#ifndef GFANLIB_FLIP_H #define GFANLIB_FLIP_H #include #include #include std::pair flip(const ideal I, const ring r, const gfan::ZVector interiorPoint, const gfan::ZVector facetNormal, const gfan::ZVector adjustedInteriorPoint, const gfan::ZVector adjustedFacetNormal); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/gfan.h000066400000000000000000000312301266270727000225500ustar00rootroot00000000000000/* gfan.h Interface to gfan.cc Author: monerjan */ #ifndef GFAN_H #define GFAN_H #include #if HAVE_GFANLIB #include #include #ifdef HAVE_CDD_SETOPER_H #include #include #include #elif HAVE_CDDLIB_SETOPER_H #include #include #include #else #include #include #include #endif #include #include extern int gfanHeuristic; #ifndef USE_ZFAN #define USE_ZFAN #endif #ifndef USE_ZFAN lists grfan(ideal inputIdeal, int heuristic, bool singleCone); #else #include gfan::ZFan *grfan(ideal inputIdeal, int h, bool singleCone); #endif // lists grcone_by_intvec(ideal inputIdeal); class facet { private: /** \brief Inner normal of the facet, describing it uniquely up to isomorphism */ int64vec *fNormal; /** \brief An interior point of the facet*/ int64vec *interiorPoint; /** \brief Universal Cone Number * The number of the cone the facet belongs to, Set in getConeNormals() */ int UCN; /** \brief The codim of the facet */ short codim; /** \brief The Groebner basis on the other side of a shared facet * * In order not to have to compute the flipped GB twice we store the basis we already get * when identifying search facets. Thus in the next step of the reverse search we can * just copy the old cone and update the facet and the gcBasis. * facet::flibGB is set via facet::setFlipGB() and printed via facet::printFlipGB */ ideal flipGB; //The Groebner Basis on the other side, computed via gcone::flip public: /** \brief Boolean value to indicate whether a facet is flippable or not * This is also used to mark facets that nominally are flippable but which do * not intersect with the positive orthant. This check is done in gcone::getCodim2Normals */ bool isFlippable; //**flippable facet? */ //bool isIncoming; //Is the facet incoming or outgoing in the reverse search? No longer in use facet *next; //Pointer to next facet facet *prev; //Pointer to predecessor. Needed for the SearchList in noRevS facet *codim2Ptr; //Pointer to (codim-2)-facet. Bit of recursion here ;-) int numCodim2Facets; //#of (codim-2)-facets of this facet. Set in getCodim2Normals() unsigned numRays; //Number of spanning rays of the facet ring flipRing; //the ring on the other side of the facet // int64vec **fRays; /** The default constructor. */ facet(); /** Constructor for lower dimensional faces*/ facet(const int &n); /** The copy constructor */ facet(const facet& f); /** A shallow copy of facets*/ facet* shallowCopy(const facet& f); void shallowDelete(); /** The default destructor */ ~facet(); /** Comparison operator*/ // inline bool operator==(const facet *f,const facet *g); /** \brief Comparison of facets*/ // inline bool areEqual(facet *f, facet *g);//Now static /** Stores the facet normal \param int64vec*/ inline void setFacetNormal(int64vec *iv); /** Returns the facet normal */ inline int64vec *getFacetNormal() const; /** Return a reference to the facet normal*/ inline const int64vec *getRef2FacetNormal() const; /** Method to print the facet normal*/ inline void printNormal() const; /** Store the flipped GB*/ inline void setFlipGB(ideal I); /** Return the flipped GB*/ inline ideal getFlipGB(); /** Print the flipped GB*/ inline void printFlipGB(); /** Set the UCN */ inline void setUCN(int n); /** \brief Get the UCN * Returns the UCN iff this != NULL, else -1 */ inline int getUCN(); /** Store an interior point of the facet */ inline void setInteriorPoint(int64vec *iv); inline int64vec *getInteriorPoint(); inline const int64vec *getRef2InteriorPoint(); /** \brief Debugging function * prints the facet normal an all (codim-2)-facets that belong to it */ volatile void fDebugPrint(); friend class gcone; }; /** *\brief Implements the cone structure * * A cone is represented by a linked list of facet normals * @see facet */ class gcone { private: ideal inputIdeal; //the original ring baseRing; //the basering of the cone int64vec *ivIntPt; //an interior point of the cone int UCN; //unique number of the cone int pred; //UCN of the cone this one is derived from static int counter; public: /** \brief Pointer to the first facet */ facet *facetPtr; //Will hold the adress of the first facet; set by gcone::getConeNormals #ifdef gfanp static float time_getConeNormals; static float time_getCodim2Normals; static float t_getExtremalRays; static float t_ddPolyh; static float time_flip; static float time_flip2; static float t_areEqual; static float t_ffG; static float t_markings; static float t_dd; static float t_kStd; static float time_enqueue; static float time_computeInv; static float t_ddMC; static float t_mI; static float t_iP; static float t_isParallel; static unsigned parallelButNotEqual; static unsigned numberOfFacetChecks; #endif /** Matrix to contain the homogeneity/lineality space */ static dd_MatrixPtr dd_LinealitySpace; static int lengthOfSearchList; /** Maximum size of the searchlist*/ static int maxSize; /** is the ideal homogeneous? */ static bool hasHomInput; /** # of variables in the ring */ static int numVars; //#of variables in the ring /** The hilbert function - for the homogeneous case*/ static int64vec *hilbertFunction; /** The zero vector. Needed in case of fNormal mismatch*/ static int64vec *ivZeroVector; /** # of facets of the cone * This value is set by gcone::getConeNormals */ int numFacets; //#of facets of the cone /** * At least as a workaround we store the irredundant facets of a matrix here. * This is needed to compute an interior points of a cone. Note that there * will be non-flippable facets in it! */ dd_MatrixPtr ddFacets; //Matrix to store irredundant facets of the cone /** Array of intvecs representing the rays of the cone*/ int64vec **gcRays; unsigned numRays; //#rays of the cone /** Contains the Groebner basis of the cone. Is set by gcone::getGB(ideal I)*/ ideal gcBasis; //GB of the cone, set by gcone::getGB(); gcone *next; //Pointer to next cone gcone *prev; gcone(); gcone(ring r, ideal I); gcone(const gcone& gc, const facet &f); ~gcone(); inline int getCounter(); inline ring getBaseRing(); inline ring getRef2BaseRing(); inline void setBaseRing(ring r); inline void setIntPoint(int64vec *iv); inline int64vec *getIntPoint(bool shallow=FALSE); inline void showIntPoint(); inline void setNumFacets(); inline int getNumFacets(); inline int getUCN(); inline int getPredUCN(); volatile void showFacets(short codim=1); // volatile void showSLA(facet &f); // void idDebugPrint(const ideal &I); // void invPrint(const ideal &I); // bool isMonomial(const ideal &I); // int64vec *ivNeg(const int64vec *iv); // inline int dotProduct(int64vec &iva, int64vec &ivb); // inline int dotProduct(const int64vec &iva, const int64vec &ivb); // inline bool isParallel(const int64vec &a, const int64vec &b); void noRevS(gcone &gcRoot, bool usingIntPoint=FALSE); // inline int intgcd(const int &a, const int &b); void writeConeToFile(const gcone &gc, bool usingIntPoints=FALSE); void readConeFromFile(int gcNum, gcone *gc); int64vec f2M(gcone *gc, facet *f, int n=1); // inline void sortRays(gcone *gc); //The real stuff void getConeNormals(const ideal &I, bool compIntPoint=FALSE); void getCodim2Normals(const gcone &gc); void getExtremalRays(const gcone &gc); void orderRays(); void flip(ideal gb, facet *f); void flip2(const ideal &gb, facet *f); void computeInv(const ideal &gb, ideal &inv, const int64vec &f); //poly restOfDiv(poly const &f, ideal const &I); removed with r12286 inline ideal ffG(const ideal &H, const ideal &G); inline void getGB(ideal const &inputIdeal); void interiorPoint( dd_MatrixPtr &M, int64vec &iv);//used from flip and optionally from getConeNormals // void interiorPoint2(); //removed Feb 8th, 2010, new method Feb 19th, 2010, again removed Mar 16th, 2010 void preprocessInequalities(dd_MatrixPtr &M); ring rCopyAndAddWeight(const ring &r, int64vec *ivw); ring rCopyAndAddWeight2(const ring &, const int64vec *, const int64vec *); // ring rCopyAndChangeWeight(const ring &r, int64vec *ivw); //NOTE remove // void reverseSearch(gcone *gcAct); //NOTE both removed from r12286 // bool isSearchFacet(gcone &gcTmp, facet *testfacet); //NOTE remove void makeInt(const dd_MatrixPtr &M, const int line, int64vec &n); // void normalize();//NOTE REMOVE facet * enqueueNewFacets(facet *f); facet * enqueue2(facet *f); // dd_MatrixPtr facets2Matrix(const gcone &gc);//NOTE remove /** Compute the lineality space Ax=0 and return it as dd_MatrixPtr dd_LinealitySpace*/ dd_MatrixPtr computeLinealitySpace(); inline bool iv64isStrictlyPositive(const int64vec *); /** Exchange 2 ordertype_a by just 1 */ void replaceDouble_ringorder_a_ByASingleOne(); // static void gcone::idPrint(ideal &I); // friend class facet; }; lists lprepareResult(gcone *gc, const int n); /* static int64 int64gcd(const int64 &a, const int64 &b); */ /* static int intgcd(const int &a, const int &b); */ /* static int dotProduct(const int64vec &iva, const int64vec &ivb); */ /* static bool isParallel(const int64vec &a, const int64vec &b); */ /* static int64vec *ivNeg(/\*const*\/ int64vec *iv); */ /* static void idDebugPrint(const ideal &I); */ /* static volatile void showSLA(facet &f); */ /* static bool isMonomial(const ideal &I); */ /* static bool ivAreEqual(const int64vec &a, const int64vec &b); */ /* static bool areEqual2(facet *f, facet *g); */ /* static bool areEqual( facet *f, facet *g); */ // bool iv64isStrictlyPositive(int64vec *); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/gfanlib.cc000066400000000000000000000010761266270727000234020ustar00rootroot00000000000000#include #if HAVE_GFANLIB #include #include #include #include #include #include #include template class gfan::Vector; template class gfan::Vector; template class gfan::Matrix; template class gfan::Matrix; extern "C" int SI_MOD_INIT(gfanlib)(SModulFunctions* p) { bbcone_setup(p); bbfan_setup(p); bbpolytope_setup(p); gitfan_setup(p); tropical_setup(p); return MAX_TOK; } #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/gfanlib_exceptions.h000066400000000000000000000010061266270727000254760ustar00rootroot00000000000000#ifndef GFANLIB_EXCEPTIONS_H #define GFANLIB_EXCEPTIONS_H #include #include class weightOverflowException: public std::exception { virtual const char* what() const throw() { return "int overflow in a weight vector"; } }; extern weightOverflowException weightOverflow; class exponentOverflowException: public std::exception { virtual const char* what() const throw() { return "int overflow in an exponent"; } }; extern exponentOverflowException exponentOverflow; #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/gitfan.cc000066400000000000000000000245021266270727000232470ustar00rootroot00000000000000/*************************************************************** * * File: gitfan.cc * Purpose: Computationally intensive procedures for gitfan.lib, * outsourced to improve the performance. * Authors: Janko Boehm boehm@mathematik.uni-kl.de * Simon Keicher keicher@mail.mathematik.uni-tuebingen.de * Yue Ren ren@mathematik.uni-kl.de * ***************************************************************/ #include #if HAVE_GFANLIB #include #include #include #include #include #include #include #include namespace gitfan { facet::facet(): eta(gfan::ZCone()), interiorPoint(gfan::ZVector()), facetNormal(gfan::ZVector()) { } facet::facet(const gitfan::facet &f): eta(f.eta), interiorPoint(f.interiorPoint), facetNormal(f.facetNormal) { #ifndef SING_NDEBUG gfan::ZCone c = f.eta; gfan::ZVector v = f.interiorPoint; gfan::ZVector w = f.facetNormal; assume(c.ambientDimension() == (int)v.size()); assume(c.ambientDimension() == (int)w.size()); assume(c.contains(v)); assume(!c.contains(w)); #endif } facet::facet(const gfan::ZCone &c, const gfan::ZVector &v, const gfan::ZVector &w): eta(c), interiorPoint(v), facetNormal(w) { #ifndef SING_NDEBUG assume(c.ambientDimension() == (int)v.size()); assume(c.ambientDimension() == (int)w.size()); assume(c.contains(v)); assume(!c.contains(w)); #endif } facet::~facet() { #ifndef SING_NDEBUG gfan::ZCone c = this->eta; gfan::ZVector v = this->interiorPoint; gfan::ZVector w = this->facetNormal; assume(c.ambientDimension() == (int)v.size()); assume(c.ambientDimension() == (int)w.size()); assume(c.contains(v)); assume(!c.contains(w)); #endif } void mergeFacets(facets &F, const facets &newFacets) { std::pair check(newFacets.begin(),false); for(facets::iterator p=newFacets.begin(); p!=newFacets.end(); p++) { check = F.insert(*p); if(!check.second) F.erase(check.first); } } } static gfan::ZCone subcone(const lists &cones, const gfan::ZVector &point) { gfan::ZCone sigma = gfan::ZCone(gfan::ZMatrix(1,point.size()), gfan::ZMatrix(1,point.size())); gfan::ZCone* zc; for (int i=0; i<=cones->nr; i++) { zc = (gfan::ZCone*) cones->m[i].Data(); if (zc->contains(point)) sigma = gfan::intersection(sigma,*zc); } return(sigma); } static gitfan::facets interiorFacets(const gfan::ZCone &zc, const gfan::ZCone &bound) { gfan::ZMatrix inequalities = zc.getFacets(); gfan::ZMatrix equations = zc.getImpliedEquations(); int r = inequalities.getHeight(); int c = inequalities.getWidth(); gitfan::facets F; if (r*c == 0) /*** * this is the trivial case where either we are in a zerodimensional ambient space, * or the cone has no facets. **/ return F; // int index = 0; /* next we iterate over each of the r facets, build the respective cone and add it to the list */ /* this is the i=0 case */ gfan::ZMatrix newInequalities = inequalities.submatrix(1,0,r,c); gfan::ZMatrix newEquations = equations; newEquations.appendRow(inequalities[0]); gfan::ZCone eta = gfan::ZCone(newInequalities,newEquations); eta.canonicalize(); gfan::ZVector v = eta.getRelativeInteriorPoint(); gfan::ZVector w = inequalities[0]; if (bound.containsRelatively(v)) F.insert(gitfan::facet(eta,v,w)); /* these are the cases i=1,...,r-2 */ for (int i=1; iTyp() == LIST_CMD)) { leftv v=u->next; if ((v != NULL) && (v->Typ() == BIGINTMAT_CMD)) { lists cones = (lists) u->Data(); bigintmat* bim = (bigintmat*) v->Data(); gfan::ZMatrix* zm = bigintmatToZMatrix(bim->transpose()); gfan::ZCone support = gfan::ZCone::givenByRays(*zm, gfan::ZMatrix(0, zm->getWidth())); delete zm; /*** * Randomly compute a first full-dimensional cone and insert it into the fan. * Compute a list of facets and relative interior points. * The relative interior points are unique, assuming the cone is stored in canonical form, * which is the case in our algorithm, as we supply no redundant inequalities. * Hence we can decide whether a facet need to be traversed by crosschecking * its relative interior point with this list. **/ gfan::ZCone lambda; gfan::ZVector point; do { point = randomPoint(&support); lambda = subcone(cones, point); } while (lambda.dimension() < lambda.ambientDimension()); int iterationNumber = 1; std::cout << "cones found: " << iterationNumber++ << std::endl; lambda.canonicalize(); gfan::ZFan* Sigma = new gfan::ZFan(lambda.ambientDimension()); Sigma->insert(lambda); gitfan::facets F = interiorFacets(lambda, support); if (F.empty()) { res->rtyp = fanID; res->data = (void*) Sigma; return FALSE; } int mu = 1024; gitfan::facet f; gfan::ZCone eta; gfan::ZVector interiorPoint; gfan::ZVector facetNormal; gitfan::facets newFacets; while (!F.empty()) { /*** * Extract a facet to traverse and its relative interior point. **/ f = *(F.begin()); eta = f.getEta(); interiorPoint = f.getInteriorPoint(); facetNormal = f.getFacetNormal(); /*** * construct a point, which lies on the other side of the facet. * make sure it lies in the known support of our fan * and that the cone around the point is maximal, containing eta. **/ point = mu * interiorPoint - facetNormal; while (!support.containsRelatively(point)) { mu = mu * 16; point = mu * interiorPoint - facetNormal; } lambda = subcone(cones,point); while ((lambda.dimension() < lambda.ambientDimension()) && !(lambda.contains(interiorPoint))) { mu = mu * 16; point = mu * interiorPoint - facetNormal; lambda = subcone(cones,point); } std::cout << "cones found: " << iterationNumber++ << std::endl; /*** * insert lambda into Sigma, and create a list of facets of lambda. * merge the two lists of facets **/ lambda.canonicalize(); Sigma->insert(lambda); newFacets = interiorFacets(lambda, support); mergeFacets(F,newFacets); newFacets.clear(); } res->rtyp = fanID; res->data = (void*) Sigma; return FALSE; } } WerrorS("refineCones: unexpected parameters"); return TRUE; } static int binomial(int n, int k) { if (nTyp() == INT_CMD)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == INT_CMD)) { int n = (int)(long) u->Data(); int k = (int)(long) v->Data(); unsigned int v = 0; for (int i=0; iInit(count); unsigned int t; while (!(v & (1<m[--count].rtyp = INTVEC_CMD; L->m[count].data = (void*) intToAface(v,n,k); // t gets v's least significant 0 bits set to 1 t = v | (v - 1); // Next set to 1 the most significant bit to change, // set to 0 the least significant ones, and add the necessary 1 bits. v = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1)); } res->rtyp = LIST_CMD; res->data = (void*) L; return FALSE; } } WerrorS("listOfAfacesToCheck: unexpected parameter"); return TRUE; } BOOLEAN nextAfaceToCheck(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == INTVEC_CMD)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == INT_CMD)) { leftv w = v->next; if ((w != NULL) && (w->Typ() == INT_CMD)) { intvec* aface = (intvec*) u->Data(); int ambientDimension = (int)(long) v->Data(); int dimension = (int)(long) w->Data(); unsigned int af = 0; for (int i=0; ilength(); i++) af |= 1<<((*aface)[i]-1); unsigned int t = af | (af - 1); af = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(af) + 1)); if (af & (1<rtyp = INTVEC_CMD; res->data = (void*) new intvec(1); return FALSE; } res->rtyp = INTVEC_CMD; res->data = (void*) intToAface(af,ambientDimension,dimension); return FALSE; } } } WerrorS("nextAfaceToCheck: unexpected parameter"); return TRUE; } void gitfan_setup(SModulFunctions* p) { p->iiAddCproc("","refineCones",FALSE,refineCones); p->iiAddCproc("","listOfAfacesToCheck",FALSE,listOfAfacesToCheck); p->iiAddCproc("","nextAfaceToCheck",FALSE,nextAfaceToCheck); } #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/gitfan.h000066400000000000000000000021041266270727000231030ustar00rootroot00000000000000#ifndef GITFAN_H #define GITFAN_H #include #if HAVE_GFANLIB #include #include #include namespace gitfan { class facet { gfan::ZCone eta; gfan::ZVector interiorPoint; gfan::ZVector facetNormal; public: facet(); facet(const facet &f); facet(const gfan::ZCone &c, const gfan::ZVector &v, const gfan::ZVector &w); ~facet(); gfan::ZCone getEta() { return this->eta; }; gfan::ZVector getInteriorPoint() { return this->interiorPoint; }; gfan::ZVector getFacetNormal() { return this->facetNormal; }; friend struct facet_compare; }; struct facet_compare { bool operator()(const facet &f, const facet &g) const { const gfan::ZVector v1 = f.interiorPoint; const gfan::ZVector v2 = g.interiorPoint; #ifndef SING_NDEBUG assume(v1.size() == v2.size()); #endif return v1 < v2; } }; typedef std::set facets; void mergeFacets(facets &F, const facets &newFacets); } void gitfan_setup(SModulFunctions* p); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/groebnerComplex.cc000066400000000000000000000057641266270727000251430ustar00rootroot00000000000000#include #include #include #include #include #include #include gfan::ZFan* groebnerComplex(const tropicalStrategy currentStrategy) { groebnerCone startingCone = groebnerStartingCone(currentStrategy); groebnerCones tropicalVariety = groebnerTraversal(startingCone); return toFanStar(tropicalVariety); } BOOLEAN groebnerComplex(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { ideal I = (ideal) u->Data(); leftv v = u->next; if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { leftv w = v->next; if (w==NULL) { number p = (number) v->Data(); tropicalStrategy currentStrategy(I,p,currRing); if (idSize(I)==1) { try { ideal startingIdeal = currentStrategy.getStartingIdeal(); ring startingRing = currentStrategy.getStartingRing(); currentStrategy.pReduce(startingIdeal,startingRing); poly g = startingIdeal->m[0]; pReduceInhomogeneous(g, currentStrategy.getUniformizingParameter(), startingRing); gfan::ZFan* zf = groebnerFanOfPolynomial(g,startingRing,true); res->rtyp = fanID; res->data = (char*) zf; return FALSE; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } } else { try { gfan::ZFan* zf = groebnerComplex(currentStrategy); res->rtyp = fanID; res->data = (char*) zf; return FALSE; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } } } } } if ((u!=NULL) && (u->Typ()==POLY_CMD)) { poly g = (poly) u->Data(); leftv v = u->next; if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { leftv w = v->next; if (w==NULL) { try { number p = (number) v->Data(); ideal I = idInit(1); I->m[0] = p_Copy(g,currRing); tropicalStrategy currentStrategy(I,p,currRing); ideal startingIdeal = currentStrategy.getStartingIdeal(); ring startingRing = currentStrategy.getStartingRing(); poly gg = startingIdeal->m[0]; pReduceInhomogeneous(gg, currentStrategy.getUniformizingParameter(), startingRing); gfan::ZFan* zf = groebnerFanOfPolynomial(gg,startingRing,true); id_Delete(&I,currRing); res->rtyp = fanID; res->data = (char*) zf; return FALSE; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } } } } WerrorS("groebnerComplex: unexpected parameters"); return TRUE; } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/groebnerComplex.h000066400000000000000000000001751266270727000247740ustar00rootroot00000000000000#ifndef GFANLIB_GROEBNERCOMPLEX_H #define GFANLIB_GROEBNERCOMPLEX_H BOOLEAN groebnerComplex(leftv res, leftv args); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/groebnerCone.cc000066400000000000000000000466251266270727000244210ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include #include #include #ifndef NDEBUG static bool checkPolynomialInput(const ideal I, const ring r) { if (r) rTest(r); if (I && r) id_Test(I,r); return ((!I) || (I && r)); } static bool checkOrderingAndCone(const ring r, const gfan::ZCone zc) { return true; if (r) { int n = rVar(r); int* w = r->wvhdl[0]; gfan::ZVector v = wvhdlEntryToZVector(n,w); if (r->order[0]==ringorder_ws) v = gfan::Integer((long)-1)*v; if (!zc.contains(v)) { std::cout << "ERROR: weight of ordering not inside Groebner cone!" << std::endl << "cone: " << std::endl << toString(&zc) << "weight: " << std::endl << v << std::endl; return false; } return true; } return (zc.dimension()==0); } static bool checkPolyhedralInput(const gfan::ZCone zc, const gfan::ZVector p) { return zc.containsRelatively(p); } #if 0 /*unused*/ static bool checkOrderingAndWeight(const ideal I, const ring r, const gfan::ZVector w, const tropicalStrategy& currentCase) { groebnerCone sigma(I,r,currentCase); gfan::ZCone zc = sigma.getPolyhedralCone(); return zc.contains(w); } #endif bool groebnerCone::checkFlipConeInput(const gfan::ZVector interiorPoint, const gfan::ZVector facetNormal) const { /* check first whether interiorPoint lies on the boundary of the cone */ if (!polyhedralCone.contains(interiorPoint)) { std::cout << "ERROR: interiorPoint is not contained in the Groebner cone!" << std::endl << "cone: " << std::endl << toString(&polyhedralCone) << "interiorPoint:" << std::endl << interiorPoint << std::endl; return false; } if (polyhedralCone.containsRelatively(interiorPoint)) { std::cout << "ERROR: interiorPoint is contained in the interior of the maximal Groebner cone!" << std::endl << "cone: " << std::endl << toString(&polyhedralCone) << "interiorPoint:" << std::endl << interiorPoint << std::endl; return false; } gfan::ZCone hopefullyAFacet = polyhedralCone.faceContaining(interiorPoint); if (hopefullyAFacet.dimension()!=(polyhedralCone.dimension()-1)) { std::cout << "ERROR: interiorPoint is not contained in the interior of a facet!" << std::endl << "cone: " << std::endl << toString(&polyhedralCone) << "interiorPoint:" << std::endl << interiorPoint << std::endl; return false; } /* check whether facet normal points outwards */ gfan::ZCone dual = polyhedralCone.dualCone(); if(dual.containsRelatively(facetNormal)) { std::cout << "ERROR: facetNormal is not pointing outwards!" << std::endl << "cone: " << std::endl << toString(&polyhedralCone) << "facetNormal:" << std::endl << facetNormal << std::endl; return false; } return true; } #endif //NDEBUG groebnerCone::groebnerCone(): polynomialIdeal(NULL), polynomialRing(NULL), polyhedralCone(gfan::ZCone(0)), interiorPoint(gfan::ZVector(0)), currentStrategy(NULL) { } groebnerCone::groebnerCone(const ideal I, const ring r, const tropicalStrategy& currentCase): polynomialIdeal(NULL), polynomialRing(NULL), currentStrategy(¤tCase) { assume(checkPolynomialInput(I,r)); if (r) polynomialRing = rCopy(r); if (I) { polynomialIdeal = id_Copy(I,r); currentCase.pReduce(polynomialIdeal,polynomialRing); currentCase.reduce(polynomialIdeal,polynomialRing); } int n = rVar(polynomialRing); poly g = NULL; int* leadexpv = (int*) omAlloc((n+1)*sizeof(int)); int* tailexpv = (int*) omAlloc((n+1)*sizeof(int)); gfan::ZVector leadexpw = gfan::ZVector(n); gfan::ZVector tailexpw = gfan::ZVector(n); gfan::ZMatrix inequalities = gfan::ZMatrix(0,n); for (int i=0; im[i]; if (g) { p_GetExpV(g,leadexpv,r); leadexpw = expvToZVector(n, leadexpv); pIter(g); while (g) { p_GetExpV(g,tailexpv,r); tailexpw = expvToZVector(n, tailexpv); inequalities.appendRow(leadexpw-tailexpw); pIter(g); } } } omFreeSize(leadexpv,(n+1)*sizeof(int)); omFreeSize(tailexpv,(n+1)*sizeof(int)); // if (currentStrategy->restrictToLowerHalfSpace()) // { // gfan::ZVector lowerHalfSpaceCondition = gfan::ZVector(n); // lowerHalfSpaceCondition[0] = -1; // inequalities.appendRow(lowerHalfSpaceCondition); // } polyhedralCone = gfan::ZCone(inequalities,gfan::ZMatrix(0, inequalities.getWidth())); polyhedralCone.canonicalize(); interiorPoint = polyhedralCone.getRelativeInteriorPoint(); assume(checkOrderingAndCone(polynomialRing,polyhedralCone)); } groebnerCone::groebnerCone(const ideal I, const ring r, const gfan::ZVector& w, const tropicalStrategy& currentCase): polynomialIdeal(NULL), polynomialRing(NULL), currentStrategy(¤tCase) { assume(checkPolynomialInput(I,r)); if (r) polynomialRing = rCopy(r); if (I) { polynomialIdeal = id_Copy(I,r); currentCase.pReduce(polynomialIdeal,polynomialRing); currentCase.reduce(polynomialIdeal,polynomialRing); } int n = rVar(polynomialRing); gfan::ZMatrix inequalities = gfan::ZMatrix(0,n); gfan::ZMatrix equations = gfan::ZMatrix(0,n); int* expv = (int*) omAlloc((n+1)*sizeof(int)); for (int i=0; im[i]; if (g) { p_GetExpV(g,expv,polynomialRing); gfan::ZVector leadexpv = intStar2ZVector(n,expv); long d = wDeg(g,polynomialRing,w); for (pIter(g); g; pIter(g)) { p_GetExpV(g,expv,polynomialRing); gfan::ZVector tailexpv = intStar2ZVector(n,expv); if (wDeg(g,polynomialRing,w)==d) equations.appendRow(leadexpv-tailexpv); else { assume(wDeg(g,polynomialRing,w)restrictToLowerHalfSpace()) // { // gfan::ZVector lowerHalfSpaceCondition = gfan::ZVector(n); // lowerHalfSpaceCondition[0] = -1; // inequalities.appendRow(lowerHalfSpaceCondition); // } polyhedralCone = gfan::ZCone(inequalities,equations); polyhedralCone.canonicalize(); interiorPoint = polyhedralCone.getRelativeInteriorPoint(); assume(checkOrderingAndCone(polynomialRing,polyhedralCone)); } /*** * Computes the groebner cone of I around u+e*w for e>0 sufficiently small. * Assumes that this cone is a face of the maximal Groenbner cone given by the ordering of r. **/ groebnerCone::groebnerCone(const ideal I, const ring r, const gfan::ZVector& u, const gfan::ZVector& w, const tropicalStrategy& currentCase): polynomialIdeal(NULL), polynomialRing(NULL), currentStrategy(¤tCase) { assume(checkPolynomialInput(I,r)); if (r) polynomialRing = rCopy(r); if (I) { polynomialIdeal = id_Copy(I,r); currentCase.pReduce(polynomialIdeal,polynomialRing); currentCase.reduce(polynomialIdeal,polynomialRing); } int n = rVar(polynomialRing); gfan::ZMatrix inequalities = gfan::ZMatrix(0,n); gfan::ZMatrix equations = gfan::ZMatrix(0,n); int* expv = (int*) omAlloc((n+1)*sizeof(int)); for (int i=0; im[i]; if (g) { p_GetExpV(g,expv,polynomialRing); gfan::ZVector leadexpv = intStar2ZVector(n,expv); long d1 = wDeg(g,polynomialRing,u); long d2 = wDeg(g,polynomialRing,w); for (pIter(g); g; pIter(g)) { p_GetExpV(g,expv,polynomialRing); gfan::ZVector tailexpv = intStar2ZVector(n,expv); if (wDeg(g,polynomialRing,u)==d1 && wDeg(g,polynomialRing,w)==d2) equations.appendRow(leadexpv-tailexpv); else { assume(wDeg(g,polynomialRing,u)restrictToLowerHalfSpace()) // { // gfan::ZVector lowerHalfSpaceCondition = gfan::ZVector(n); // lowerHalfSpaceCondition[0] = -1; // inequalities.appendRow(lowerHalfSpaceCondition); // } polyhedralCone = gfan::ZCone(inequalities,equations); polyhedralCone.canonicalize(); interiorPoint = polyhedralCone.getRelativeInteriorPoint(); assume(checkOrderingAndCone(polynomialRing,polyhedralCone)); } groebnerCone::groebnerCone(const ideal I, const ideal inI, const ring r, const tropicalStrategy& currentCase): polynomialIdeal(id_Copy(I,r)), polynomialRing(rCopy(r)), currentStrategy(¤tCase) { assume(checkPolynomialInput(I,r)); assume(checkPolynomialInput(inI,r)); currentCase.pReduce(polynomialIdeal,polynomialRing); currentCase.reduce(polynomialIdeal,polynomialRing); int n = rVar(r); gfan::ZMatrix equations = gfan::ZMatrix(0,n); int* expv = (int*) omAlloc((n+1)*sizeof(int)); for (int i=0; im[i]; if (g) { p_GetExpV(g,expv,r); gfan::ZVector leadexpv = intStar2ZVector(n,expv); for (pIter(g); g; pIter(g)) { p_GetExpV(g,expv,r); gfan::ZVector tailexpv = intStar2ZVector(n,expv); equations.appendRow(leadexpv-tailexpv); } } } gfan::ZMatrix inequalities = gfan::ZMatrix(0,n); for (int i=0; im[i]; if (g) { p_GetExpV(g,expv,r); gfan::ZVector leadexpv = intStar2ZVector(n,expv); for (pIter(g); g; pIter(g)) { p_GetExpV(g,expv,r); gfan::ZVector tailexpv = intStar2ZVector(n,expv); inequalities.appendRow(leadexpv-tailexpv); } } } omFreeSize(expv,(n+1)*sizeof(int)); if (currentStrategy->restrictToLowerHalfSpace()) { gfan::ZVector lowerHalfSpaceCondition = gfan::ZVector(n); lowerHalfSpaceCondition[0] = -1; inequalities.appendRow(lowerHalfSpaceCondition); } polyhedralCone = gfan::ZCone(inequalities,equations); polyhedralCone.canonicalize(); interiorPoint = polyhedralCone.getRelativeInteriorPoint(); assume(checkOrderingAndCone(polynomialRing,polyhedralCone)); } groebnerCone::groebnerCone(const groebnerCone &sigma): polynomialIdeal(NULL), polynomialRing(NULL), polyhedralCone(gfan::ZCone(sigma.getPolyhedralCone())), interiorPoint(gfan::ZVector(sigma.getInteriorPoint())), currentStrategy(sigma.getTropicalStrategy()) { assume(checkPolynomialInput(sigma.getPolynomialIdeal(),sigma.getPolynomialRing())); assume(checkOrderingAndCone(sigma.getPolynomialRing(),sigma.getPolyhedralCone())); assume(checkPolyhedralInput(sigma.getPolyhedralCone(),sigma.getInteriorPoint())); if (sigma.getPolynomialIdeal()) polynomialIdeal = id_Copy(sigma.getPolynomialIdeal(),sigma.getPolynomialRing()); if (sigma.getPolynomialRing()) polynomialRing = rCopy(sigma.getPolynomialRing()); } groebnerCone::~groebnerCone() { assume(checkPolynomialInput(polynomialIdeal,polynomialRing)); assume(checkOrderingAndCone(polynomialRing,polyhedralCone)); assume(checkPolyhedralInput(polyhedralCone,interiorPoint)); if (polynomialIdeal) id_Delete(&polynomialIdeal,polynomialRing); if (polynomialRing) rDelete(polynomialRing); } groebnerCone& groebnerCone::operator=(const groebnerCone& sigma) { assume(checkPolynomialInput(sigma.getPolynomialIdeal(),sigma.getPolynomialRing())); assume(checkOrderingAndCone(sigma.getPolynomialRing(),sigma.getPolyhedralCone())); assume(checkPolyhedralInput(sigma.getPolyhedralCone(),sigma.getInteriorPoint())); if (sigma.getPolynomialIdeal()) polynomialIdeal = id_Copy(sigma.getPolynomialIdeal(),sigma.getPolynomialRing()); if (sigma.getPolynomialRing()) polynomialRing = rCopy(sigma.getPolynomialRing()); polyhedralCone = sigma.getPolyhedralCone(); interiorPoint = sigma.getInteriorPoint(); currentStrategy = sigma.getTropicalStrategy(); return *this; } /** * Returns true if Groebner cone contains w, false otherwise */ bool groebnerCone::contains(const gfan::ZVector &w) const { return polyhedralCone.contains(w); } /*** * Returns a point in the tropical variety, if the groebnerCone contains one. * Returns an empty vector otherwise. **/ gfan::ZVector groebnerCone::tropicalPoint() const { assume(checkOrderingAndCone(polynomialRing,polyhedralCone)); ideal I = polynomialIdeal; ring r = polynomialRing; gfan::ZCone coneToCheck = polyhedralCone; gfan::ZMatrix R = coneToCheck.extremeRays(); for (int i=0; irestrictToLowerHalfSpace() || R[i][0].sign()<=0); if (currentStrategy->restrictToLowerHalfSpace() && R[i][0].sign()==0) continue; std::pair s = currentStrategy->checkInitialIdealForMonomial(I,r,R[i]); if (s.first==NULL) { if (s.second<0) // if monomial was initialized, delete it p_Delete(&s.first,r); return R[i]; } } return gfan::ZVector(); } /** * Given an interior point on the facet and the outer normal factor on the facet, * returns the adjacent groebnerCone sharing that facet */ groebnerCone groebnerCone::flipCone(const gfan::ZVector &interiorPoint, const gfan::ZVector &facetNormal) const { assume(this->checkFlipConeInput(interiorPoint,facetNormal)); /* Note: the polynomial ring created will have a weighted ordering with respect to interiorPoint * and with a weighted ordering with respect to facetNormal as tiebreaker. * Hence it is sufficient to compute the initial form with respect to facetNormal, * to obtain an initial form with respect to interiorPoint+e*facetNormal, * for e>0 sufficiently small */ std::pair flipped = currentStrategy->computeFlip(polynomialIdeal,polynomialRing,interiorPoint,facetNormal); assume(checkPolynomialInput(flipped.first,flipped.second)); groebnerCone flippedCone(flipped.first, flipped.second, interiorPoint, facetNormal, *currentStrategy); id_Delete(&flipped.first,flipped.second); rDelete(flipped.second); return flippedCone; } /*** * Returns a complete list of neighboring Groebner cones. **/ groebnerCones groebnerCone::groebnerNeighbours() const { std::pair facetsData = interiorPointsAndNormalsOfFacets(polyhedralCone); gfan::ZMatrix interiorPoints = facetsData.first; gfan::ZMatrix facetNormals = facetsData.second; groebnerCones neighbours; for (int i=0; irestrictToLowerHalfSpace()) { assume(w[0].sign()<=0); if (w[0].sign()==0 && v[0].sign()>0) continue; } neighbours.insert(flipCone(interiorPoints[i],facetNormals[i])); } return neighbours; } bool groebnerCone::pointsOutwards(const gfan::ZVector w) const { gfan::ZCone dual = polyhedralCone.dualCone(); return (!dual.contains(w)); } /*** * Returns a complete list of neighboring Groebner cones in the tropical variety. **/ groebnerCones groebnerCone::tropicalNeighbours() const { gfan::ZMatrix interiorPoints = interiorPointsOfFacets(polyhedralCone); groebnerCones neighbours; for (int i=0; irestrictToLowerHalfSpace() && interiorPoints[i][0].sign()==0)) { ideal initialIdeal = initial(polynomialIdeal,polynomialRing,interiorPoints[i]); gfan::ZMatrix ray = raysOfTropicalStar(initialIdeal,polynomialRing,interiorPoints[i],currentStrategy); for (int j=0; j 0) { groebnerCones::iterator sigma = setOfCones.begin(); gfan::ZFan* zf = new gfan::ZFan(sigma->getPolyhedralCone().ambientDimension()); for (; sigma!=setOfCones.end(); sigma++) { gfan::ZCone zc = sigma->getPolyhedralCone(); // assume(isCompatible(zf,&zc)); zf->insert(zc); } return zf; } else return new gfan::ZFan(gfan::ZFan(currRing->N)); } #ifndef NDEBUG BOOLEAN flipConeDebug(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { leftv v = u->next; if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { leftv w = v->next; if ((w!=NULL) && (w->Typ()==BIGINTMAT_CMD)) { leftv x = w->next; if ((x!=NULL) && (x->Typ()==BIGINTMAT_CMD)) { omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); ideal I = (ideal) u->CopyD(); number p = (number) v->CopyD(); bigintmat* interiorPoint0 = (bigintmat*) w->CopyD(); bigintmat* facetNormal0 = (bigintmat*) x->CopyD(); tropicalStrategy debug = tropicalStrategy::debugStrategy(I,p,currRing); gfan::ZVector* interiorPoint = bigintmatToZVector(interiorPoint0); gfan::ZVector* facetNormal = bigintmatToZVector(facetNormal0); groebnerCone sigma(I,currRing,debug); groebnerCone theta = sigma.flipCone(*interiorPoint,*facetNormal); id_Delete(&I,currRing); n_Delete(&p,currRing->cf); delete interiorPoint0; delete facetNormal0; delete interiorPoint; delete facetNormal; res->rtyp = NONE; res->data = NULL; return FALSE; } } } } WerrorS("computeFlipDebug: unexpected parameters"); return TRUE; } BOOLEAN groebnerNeighboursDebug(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { leftv v = u->next; if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); ideal I = (ideal) u->CopyD(); number p = (number) v->CopyD(); tropicalStrategy debug = tropicalStrategy::debugStrategy(I,p,currRing); groebnerCone sigma(I,currRing,debug); groebnerCones neighbours = sigma.groebnerNeighbours(); id_Delete(&I,currRing); n_Delete(&p,currRing->cf); res->rtyp = NONE; res->data = NULL; return FALSE; } } WerrorS("computeFlipDebug: unexpected parameters"); return TRUE; } BOOLEAN tropicalNeighboursDebug(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { leftv v = u->next; if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); ideal I = (ideal) u->CopyD(); number p = (number) v->CopyD(); tropicalStrategy debug = tropicalStrategy::debugStrategy(I,p,currRing); groebnerCone sigma(I,currRing,debug); groebnerCones neighbours = sigma.groebnerNeighbours(); id_Delete(&I,currRing); n_Delete(&p,currRing->cf); res->rtyp = NONE; res->data = NULL; return FALSE; } } WerrorS("computeFlipDebug: unexpected parameters"); return TRUE; } #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/groebnerCone.h000066400000000000000000000075261266270727000242600ustar00rootroot00000000000000#ifndef CALLGFANLIB_GROEBNERCONE_H #define CALLGFANLIB_GROEBNERCONE_H #include #include #include #include #include #include #include #include /** \file * implementation of the class groebnerCone * * groebnerCone is a class that encapsulates relevant (possibly redundant) information about a groebnerCone. * Moreover, it contains implrementation of several highly non-trivial algorithms, such as computing its neighbours * in the Groebner fan or computing its neighbours in the tropical variety. */ class groebnerCone; struct groebnerCone_compare; typedef std::set groebnerCones; class groebnerCone { private: /** * ideal to which this Groebner cone belongs to */ ideal polynomialIdeal; /** * ring in which the ideal exists */ ring polynomialRing; gfan::ZCone polyhedralCone; gfan::ZVector interiorPoint; const tropicalStrategy* currentStrategy; public: groebnerCone(); groebnerCone(const ideal I, const ring r, const tropicalStrategy& currentCase); groebnerCone(const ideal I, const ring r, const gfan::ZVector& w, const tropicalStrategy& currentCase); groebnerCone(const ideal I, const ring r, const gfan::ZVector& u, const gfan::ZVector& w, const tropicalStrategy& currentCase); groebnerCone(const ideal I, const ideal inI, const ring r, const tropicalStrategy& currentCase); groebnerCone(const groebnerCone& sigma); ~groebnerCone(); groebnerCone& operator=(const groebnerCone& sigma); void deletePolynomialData() { assume ((!polynomialIdeal) || (polynomialIdeal && polynomialRing)); if (polynomialIdeal) id_Delete(&polynomialIdeal,polynomialRing); if (polynomialRing) rDelete(polynomialRing); polynomialIdeal = NULL; polynomialRing = NULL; } ideal getPolynomialIdeal() const { return polynomialIdeal; }; ring getPolynomialRing() const { return polynomialRing; }; gfan::ZCone getPolyhedralCone() const { return polyhedralCone; }; gfan::ZVector getInteriorPoint() const { return interiorPoint; }; const tropicalStrategy* getTropicalStrategy() const { return currentStrategy; }; friend struct groebnerCone_compare; bool isTrivial() const { bool b = (polynomialRing==NULL); return b; } /** * Returns true if Groebner cone contains w, false otherwise */ bool contains(const gfan::ZVector &w) const; /** * Returns a point in the tropical variety, if the groebnerCone contains one. * Returns an empty vector otherwise. */ gfan::ZVector tropicalPoint() const; /** * Given an interior point on the facet and the outer normal factor on the facet, * returns the adjacent groebnerCone sharing that facet */ groebnerCone flipCone(const gfan::ZVector &interiorPoint, const gfan::ZVector &facetNormal) const; /** * Returns a complete list of neighboring Groebner cones. */ groebnerCones groebnerNeighbours() const; /** * Returns a complete list of neighboring Groebner cones in the tropical variety. */ groebnerCones tropicalNeighbours() const; /** * Debug tools. */ #ifndef NDEBUG bool checkFlipConeInput(const gfan::ZVector interiorPoint, const gfan::ZVector facetNormal) const; bool pointsOutwards(const gfan::ZVector) const; #endif }; struct groebnerCone_compare { bool operator()(const groebnerCone &sigma, const groebnerCone &theta) const { const gfan::ZVector p1 = sigma.getInteriorPoint(); const gfan::ZVector p2 = theta.getInteriorPoint(); assume (p1.size() == p2.size()); return p1 < p2; } }; gfan::ZFan* toFanStar(groebnerCones setOfCones); #ifndef NDEBUG BOOLEAN flipConeDebug(leftv res, leftv args); BOOLEAN groebnerNeighboursDebug(leftv res, leftv args); BOOLEAN tropicalNeighboursDebug(leftv res, leftv args); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/groebnerFan.cc000066400000000000000000000072101266270727000242240ustar00rootroot00000000000000#include #include #include #include #include BITSET groebnerBitsetSave1, groebnerBitsetSave2; /*** * sets option(redSB) **/ static void setOptionRedSB() { SI_SAVE_OPT(groebnerBitsetSave1,groebnerBitsetSave2); si_opt_1|=Sy_bit(OPT_REDSB); } /*** * sets option(noredSB); **/ static void undoSetOptionRedSB() { SI_RESTORE_OPT(groebnerBitsetSave1,groebnerBitsetSave2); } gfan::ZFan* groebnerFan(const tropicalStrategy currentStrategy) { groebnerCone startingCone = groebnerStartingCone(currentStrategy); groebnerCones groebnerFan = groebnerTraversal(startingCone); return toFanStar(groebnerFan); } gfan::ZFan* groebnerFanOfPolynomial(poly g, ring r, bool onlyLowerHalfSpace=false) { int n = rVar(r); if (g==NULL || g->next==NULL) { // if g is a term or zero, return the fan consisting of the whole weight space gfan::ZFan* zf = new gfan::ZFan(gfan::ZFan::fullFan(n)); return zf; } else { gfan::ZVector lowerHalfSpaceCondition = gfan::ZVector(n); lowerHalfSpaceCondition[0] = -1; // otherwise, obtain a list of all the exponent vectors int* expv = (int*) omAlloc((n+1)*sizeof(int)); gfan::ZMatrix exponents = gfan::ZMatrix(0,n); for (poly s=g; s; pIter(s)) { p_GetExpV(s,expv,r); gfan::ZVector zv = intStar2ZVector(n,expv); exponents.appendRow(intStar2ZVector(n,expv)); } omFreeSize(expv,(n+1)*sizeof(int)); // and construct the Groebner fan gfan::ZFan* zf = new gfan::ZFan(n); int l = exponents.getHeight(); for (int i=0; iinsert(zc); } return zf; } } BOOLEAN groebnerFan(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { ideal I = (ideal) u->CopyD(); leftv v = u->next; if (v==NULL) { if (idSize(I)==1) { try { poly g = I->m[0]; gfan::ZFan* zf = groebnerFanOfPolynomial(g,currRing); res->rtyp = fanID; res->data = (char*) zf; return FALSE; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } } else { try { tropicalStrategy currentStrategy(I,currRing); setOptionRedSB(); gfan::ZFan* zf = groebnerFan(currentStrategy); undoSetOptionRedSB(); res->rtyp = fanID; res->data = (char*) zf; return FALSE; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } } } } if ((u!=NULL) && (u->Typ()==POLY_CMD)) { poly g = (poly) u->Data(); leftv v = u->next; if (v==NULL) { try { gfan::ZFan* zf = groebnerFanOfPolynomial(g,currRing); res->rtyp = fanID; res->data = (char*) zf; return FALSE; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } } } WerrorS("groebnerFan: unexpected parameters"); return TRUE; } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/groebnerFan.h000066400000000000000000000003501266270727000240640ustar00rootroot00000000000000#ifndef GFANLIB_GROEBNERFAN_H #define GFANLIB_GROEBNERFAN_H #include gfan::ZFan* groebnerFanOfPolynomial(poly g, ring r, bool onlyLowerHalfSpace=false); BOOLEAN groebnerFan(leftv res, leftv args); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/initial.cc000066400000000000000000000071551266270727000234350ustar00rootroot00000000000000#include #include #include #include long wDeg(const poly p, const ring r, const gfan::ZVector w) { long d=0; for (unsigned i=0; inext; currentTerm; pIter(currentTerm)) { long e = wDeg(currentTerm,r,w); if (dm[i] = initial(I->m[i],r,w); return inI; } poly initial(const poly p, const ring r, const gfan::ZVector w, const gfan::ZMatrix W) { if (p==NULL) return NULL; poly q0 = p_Head(p,r); poly q1 = q0; gfan::ZVector d = WDeg(p,r,w,W); for (poly currentTerm = p->next; currentTerm; pIter(currentTerm)) { gfan::ZVector e = WDeg(currentTerm,r,w,W); if (dm[i] = initial(I->m[i],r,w,W); return inI; } void initial(poly* pStar, const ring r, const gfan::ZVector w) { poly p = *pStar; if (p==NULL) return; long d = wDeg(p,r,w); poly q0 = p; poly q1 = q0; pNext(q1) = NULL; pIter(p); while(p) { long e = wDeg(p,r,w); if (dm[i],r,w); return; } void initial(poly* pStar, const ring r, const gfan::ZVector w, const gfan::ZMatrix W) { poly p = *pStar; if (p==NULL) return; gfan::ZVector d = WDeg(p,r,w,W); poly q0 = p; poly q1 = q0; pNext(q1) = NULL; pIter(p); while(p) { gfan::ZVector e = WDeg(p,r,w,W); if (dm[i],r,w,W); return; } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/initial.h000066400000000000000000000036721266270727000232770ustar00rootroot00000000000000#ifndef INITIAL_H #define INITIAL_H /** * various functions to compute the initial form of polynomials and ideals */ #include #include #include /** * Returns the weighted degree of the leading term of p with respect to w */ long wDeg(const poly p, const ring r, const gfan::ZVector w); /** * Returns the weighted multidegree of the leading term of p with respect to (w,W). * The weighted multidegree is a vector of length one higher than the column vectors of W. * The first entry is the weighted degree with respect to w * and the i+1st entry is the weighted degree with respect to the i-th row vector of W. */ gfan::ZVector WDeg(const poly p, const ring r, const gfan::ZVector w, const gfan::ZMatrix W); /** * Returns the initial form of p with respect to w */ poly initial(const poly p, const ring r, const gfan::ZVector w); /** * Returns the initial form of I with respect to w */ ideal initial(const ideal I, const ring r, const gfan::ZVector w); /** * Returns the initial form of p with respect to w and W */ poly initial(const poly p, const ring r, const gfan::ZVector w, const gfan::ZMatrix W); /** * Returns the initial form of I with respect to w and W */ ideal initial(const ideal I, const ring r, const gfan::ZVector w, const gfan::ZMatrix W); /** * Stores the initial form of *pStar with respect to w in pStar */ void initial(poly* pStar, const ring r, const gfan::ZVector w); /** * Stores the initial form of *IStar with respect to w in IStar */ void initial(ideal* IStar, const ring r, const gfan::ZVector w); /** * Stores the initial form of *pStar with respect to w and W in pStar */ void initial(poly* pStar, const ring r, const gfan::ZVector w, const gfan::ZMatrix W); /** * Stores the initial form of *IStar with respect to w and W in IStar */ void initial(ideal* IStar, const ring r, const gfan::ZVector w, const gfan::ZMatrix W); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/lift.cc000066400000000000000000000024351266270727000227360ustar00rootroot00000000000000#include /*** * Suppose r and s are the same ring but with two adjacent orderings, * w is a weight vector in the relative interior of their common facet. * Given a standard basis of an ideal I with respect to the ordering of r, * a standard basis of its w-initial ideal inI with respect to * the ordering of s, computes a standard basis of I with respect to * the ordering of s. **/ // ideal lift(const ideal I, const ring r, const ideal inI, const ring s) // { // nMapFunc identity = n_SetMap(r->cf,s->cf); // int k = idSize(I); ideal Is = idInit(k); // for (int i=0; im[i] = p_PermPoly(I->m[i],NULL,r,s,identity,NULL,0); // ideal J = idInit(k); // for (int i=0; im[i] = witness(inI->m[i],Is,inI,s); // id_Delete(&Is,s); // return J; // } ideal lift(const ideal J, const ring r, const ideal inI, const ring s) { nMapFunc identity = n_SetMap(s->cf,r->cf); int k = idSize(inI); ideal inIr = idInit(k); for (int i=0; im[i] = p_PermPoly(inI->m[i],NULL,s,r,identity,NULL,0); ideal Ir = witness(inIr,J,r); identity = n_SetMap(r->cf,s->cf); ideal Is = idInit(k); for (int i=0; im[i] = p_PermPoly(Ir->m[i],NULL,r,s,identity,NULL,0); id_Delete(&inIr,r); id_Delete(&Ir,r); return Is; } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/lift.h000066400000000000000000000002201266270727000225660ustar00rootroot00000000000000#ifndef LIFT_H #define LIFT_H #include ideal lift(const ideal I, const ring r, const ideal inI, const ring s); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/ppinitialReduction.cc000066400000000000000000000526661266270727000256610ustar00rootroot00000000000000#include #include #include "singularWishlist.h" #include "ppinitialReduction.h" #include #include #include #ifndef NDEBUG bool isOrderingLocalInT(const ring r) { poly one = p_One(r); poly t = p_One(r); p_SetExp(t,1,1,r); p_Setm(t,r); int s = p_LmCmp(one,t,r); p_Delete(&one,r); p_Delete(&t,r); return (s==1); } #endif void divideByCommonGcd(poly &g, const ring r) { number commonGcd = n_Copy(p_GetCoeff(g,r),r->cf); for (poly gCache=pNext(g); gCache; pIter(gCache)) { number commonGcdCache = n_Gcd(commonGcd,p_GetCoeff(gCache,r),r->cf); n_Delete(&commonGcd,r->cf); commonGcd = commonGcdCache; if (n_IsOne(commonGcd,r->cf)) { n_Delete(&commonGcd,r->cf); return; } } for (poly gCache=g; gCache; pIter(gCache)) { number oldCoeff = p_GetCoeff(gCache,r); number newCoeff = n_Div(oldCoeff,commonGcd,r->cf); p_SetCoeff(gCache,newCoeff,r); } p_Test(g,r); n_Delete(&commonGcd,r->cf); return; } /*** * changes a polynomial g with the help p-t such that * 1) each term of g has a distinct monomial in x * 2) no term of g has a coefficient divisible by p * in particular, this means that all g_\alpha can be obtained * by reading the coefficients and that g is initially reduced * with respect to p-t **/ void pReduce(poly &g, const number p, const ring r) { if (g==NULL) return; p_Test(g,r); poly toBeChecked = pNext(g); pNext(g) = NULL; poly gEnd = g; poly gCache; number coeff, pPower; int power; poly subst; while(toBeChecked) { for (gCache = g; gCache; pIter(gCache)) if (p_LeadmonomDivisibleBy(gCache,toBeChecked,r)) break; if (gCache) { n_Power(p,p_GetExp(toBeChecked,1,r)-p_GetExp(gCache,1,r),&pPower,r->cf); coeff = n_Mult(p_GetCoeff(toBeChecked,r),pPower,r->cf); p_SetCoeff(gCache,n_Add(p_GetCoeff(gCache,r),coeff,r->cf),r); n_Delete(&pPower,r->cf); n_Delete(&coeff,r->cf); toBeChecked=p_LmDeleteAndNext(toBeChecked,r); } else { if (n_DivBy(p_GetCoeff(toBeChecked,r),p,r->cf)) { power=1; coeff=n_Div(p_GetCoeff(toBeChecked,r),p,r->cf); while (n_DivBy(coeff,p,r->cf)) { power++; number coeff0 = n_Div(coeff,p,r->cf); n_Delete(&coeff,r->cf); coeff = coeff0; coeff0 = NULL; if (power<1) { WerrorS("pReduce: overflow in exponent"); throw 0; } } subst=p_LmInit(toBeChecked,r); p_AddExp(subst,1,power,r); p_SetCoeff(subst,coeff,r); p_Setm(subst,r); p_Test(subst,r); toBeChecked=p_LmDeleteAndNext(toBeChecked,r); toBeChecked=p_Add_q(toBeChecked,subst,r); p_Test(toBeChecked,r); } else { pNext(gEnd)=toBeChecked; pIter(gEnd); pIter(toBeChecked); pNext(gEnd)=NULL; p_Test(g,r); } } } p_Test(g,r); divideByCommonGcd(g,r); return; } bool p_xLeadmonomDivisibleBy(const poly g, const poly f, const ring r) { poly gx = p_Head(g,r); poly fx = p_Head(f,r); p_SetExp(gx,1,0,r); p_SetExp(fx,1,0,r); p_Setm(gx,r); p_Setm(fx,r); bool b = p_LeadmonomDivisibleBy(gx,fx,r); p_Delete(&gx,r); p_Delete(&fx,r); return b; } void pReduceInhomogeneous(poly &g, const number p, const ring r) { if (g==NULL) return; p_Test(g,r); poly toBeChecked = pNext(g); pNext(g) = NULL; poly gEnd = g; poly gCache; number coeff, pPower; int power; poly subst; while(toBeChecked) { for (gCache = g; gCache; pIter(gCache)) if (p_xLeadmonomDivisibleBy(gCache,toBeChecked,r)) break; if (gCache) { n_Power(p,p_GetExp(toBeChecked,1,r)-p_GetExp(gCache,1,r),&pPower,r->cf); coeff = n_Mult(p_GetCoeff(toBeChecked,r),pPower,r->cf); p_SetCoeff(gCache,n_Add(p_GetCoeff(gCache,r),coeff,r->cf),r); n_Delete(&pPower,r->cf); n_Delete(&coeff,r->cf); toBeChecked=p_LmDeleteAndNext(toBeChecked,r); } else { if (n_DivBy(p_GetCoeff(toBeChecked,r),p,r->cf)) { power=1; coeff=n_Div(p_GetCoeff(toBeChecked,r),p,r->cf); while (n_DivBy(coeff,p,r->cf)) { power++; number coeff0 = n_Div(coeff,p,r->cf); n_Delete(&coeff,r->cf); coeff = coeff0; coeff0 = NULL; if (power<1) { WerrorS("pReduce: overflow in exponent"); throw 0; } } subst=p_LmInit(toBeChecked,r); p_AddExp(subst,1,power,r); p_SetCoeff(subst,coeff,r); p_Setm(subst,r); p_Test(subst,r); toBeChecked=p_LmDeleteAndNext(toBeChecked,r); toBeChecked=p_Add_q(toBeChecked,subst,r); p_Test(toBeChecked,r); } else { pNext(gEnd)=toBeChecked; pIter(gEnd); pIter(toBeChecked); pNext(gEnd)=NULL; p_Test(g,r); } } } p_Test(g,r); divideByCommonGcd(g,r); return; } void ptNormalize(poly* gStar, const number p, const ring r) { poly g = *gStar; if (g==NULL || n_DivBy(p_GetCoeff(g,r),p,r->cf)) return; p_Test(g,r); // create p-t poly pt = p_Init(r); p_SetCoeff(pt,n_Copy(p,r->cf),r); pNext(pt) = p_Init(r); p_SetExp(pNext(pt),1,1,r); p_Setm(pNext(pt),r); p_SetCoeff(pNext(pt),n_Init(-1,r->cf),r); // make g monic with the help of p-t number a,b; number gcd = n_ExtGcd(p_GetCoeff(g,r),p,&a,&b,r->cf); assume(n_IsUnit(gcd,r->cf)); // now a*leadcoef(g)+b*p = gcd with gcd being a unit // so a*g+b*(p-t)*leadmonom(g) should have a unit as leading coefficient // but first check whether b is 0, // since p_Mult_nn doesn't allow 0 as number input if (n_IsZero(b,r->cf)) { n_Delete(&a,r->cf); n_Delete(&b,r->cf); n_Delete(&gcd,r->cf); p_Delete(&pt,r); return; } poly m = p_Head(g,r); p_SetCoeff(m,n_Init(1,r->cf),r); g = p_Add_q(p_Mult_nn(g,a,r),p_Mult_nn(p_Mult_mm(pt,m,r),b,r),r); n_Delete(&a,r->cf); n_Delete(&b,r->cf); n_Delete(&gcd,r->cf); p_Delete(&m,r); p_Test(g,r); return; } void ptNormalize(ideal I, const number p, const ring r) { for (int i=0; im[i]),p,r); return; } #ifndef NDEBUG BOOLEAN ptNormalize(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); ideal I = (ideal) u->CopyD(); number p = (number) v->CopyD(); ptNormalize(I,p,currRing); n_Delete(&p,currRing->cf); res->rtyp = IDEAL_CMD; res->data = (char*) I; return FALSE; } } return TRUE; } #endif //NDEBUG #ifndef NDEBUG BOOLEAN pReduceDebug(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == POLY_CMD)) { poly g; number p = n_Init(3,currRing->cf); omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); g = (poly) u->CopyD(); (void) pReduce(g,p,currRing); p_Delete(&g,currRing); omUpdateInfo(); Print("usedBytesAfter=%ld\n",om_Info.UsedBytes); g = (poly) u->CopyD(); (void) pReduce(g,p,currRing); n_Delete(&p,currRing->cf); res->rtyp = POLY_CMD; res->data = (char*) g; return FALSE; } return TRUE; } #endif //NDEBUG void pReduce(ideal &I, const number p, const ring r) { int k = idSize(I); for (int i=0; im[i]!=NULL) { number c = p_GetCoeff(I->m[i],r); if (!n_Equal(p,c,r->cf)) pReduce(I->m[i],p,r); } } return; } /** * reduces h initially with respect to g, * returns false if h was initially reduced in the first place, * returns true if reductions have taken place. * assumes that h and g are in pReduced form and homogeneous in x of the same degree */ bool ppreduceInitially(poly* hStar, const poly g, const ring r) { poly h = *hStar; if (h==NULL || g==NULL) return false; p_Test(h,r); p_Test(g,r); poly hCache; for (hCache=h; hCache; pIter(hCache)) if (p_LeadmonomDivisibleBy(g,hCache,r)) break; if (hCache) { number gAlpha = p_GetCoeff(g,r); poly hAlphaT = p_Init(r); p_SetCoeff(hAlphaT,n_Copy(p_GetCoeff(hCache,r),r->cf),r); p_SetExp(hAlphaT,1,p_GetExp(hCache,1,r)-p_GetExp(g,1,r),r); for (int i=2; i<=r->N; i++) p_SetExp(hAlphaT,i,0,r); p_Setm(hAlphaT,r); p_Test(hAlphaT,r); poly q1 = p_Mult_nn(h,gAlpha,r); p_Test(q1,r); poly q2 = p_Mult_q(p_Copy(g,r),hAlphaT,r); p_Test(q2,r); q2 = p_Neg(q2,r); p_Test(q2,r); h = p_Add_q(q1,q2,r); p_Test(h,r); p_Test(g,r); *hStar = h; return true; } p_Test(h,r); p_Test(g,r); return false; } #ifndef NDEBUG BOOLEAN ppreduceInitially0(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == POLY_CMD)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == POLY_CMD)) { poly g,h; omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); h = (poly) u->CopyD(); g = (poly) v->CopyD(); (void)ppreduceInitially(&h,g,currRing); p_Delete(&h,currRing); p_Delete(&g,currRing); omUpdateInfo(); Print("usedBytesAfter=%ld\n",om_Info.UsedBytes); h = (poly) u->CopyD(); g = (poly) v->CopyD(); (void)ppreduceInitially(&h,g,currRing); p_Delete(&g,currRing); res->rtyp = POLY_CMD; res->data = (char*) h; return FALSE; } } return TRUE; } #endif //NDEBUG /*** * reduces I initially with respect to itself and with respect to p-t. * also sorts the generators of I with respect to the leading monomials in descending order. * assumes that I is generated by elements which are homogeneous in x of the same degree. **/ bool ppreduceInitially(ideal I, const number p, const ring r) { int m=idSize(I),n=m; poly cache; do { int j=0; for (int i=1; im[i-1],I->m[i],r)<0) { cache=I->m[i-1]; I->m[i-1]=I->m[i]; I->m[i]=cache; j = i; } } n=j; } while(n); for (int i=0; im[i],p,r); /*** * the first pass. removing terms with the same monomials in x as lt(g_i) out of g_j for im[j], I->m[i], r)) pReduce(I->m[j],p,r); /*** * the second pass. removing terms divisible by lt(g_j) out of g_i for im[i], I->m[j],r)) pReduce(I->m[i],p,r); /*** * removes the elements of I which have been reduced to 0 in the previous two passes **/ idSkipZeroes(I); return false; } #ifndef NDEBUG BOOLEAN ppreduceInitially1(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == NUMBER_CMD)) { ideal I; number p; omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); I = (ideal) u->CopyD(); p = (number) v->CopyD(); (void) ppreduceInitially(I,p,currRing); id_Delete(&I,currRing); n_Delete(&p,currRing->cf); omUpdateInfo(); Print("usedBytesAfter=%ld\n",om_Info.UsedBytes); I = (ideal) u->CopyD(); p = (number) v->CopyD(); (void) ppreduceInitially(I,p,currRing); n_Delete(&p,currRing->cf); res->rtyp = IDEAL_CMD; res->data = (char*) I; return FALSE; } } return TRUE; } #endif //NDEBUG /*** * inserts g into I and reduces I with respect to itself and p-t * returns the position in I in which g was inserted * assumes that I was already sorted and initially reduced in the first place **/ int ppreduceInitially(ideal I, const number p, const poly g, const ring r) { id_Test(I,r); p_Test(g,r); idInsertPoly(I,g); int n=idSize(I); int j; for (j=n-1; j>0; j--) { if (p_LmCmp(I->m[j], I->m[j-1],r)>0) { poly cache = I->m[j]; I->m[j] = I->m[j-1]; I->m[j-1] = cache; } else break; } /*** * the first pass. removing terms with the same monomials in x as lt(g_i) out of g_j for im[j], I->m[i], r)) pReduce(I->m[j],p,r); for (int k=j+1; km[k], I->m[j], r)) { pReduce(I->m[k],p,r); for (int l=j+1; lm[k], I->m[l], r)) pReduce(I->m[k],p,r); } /*** * the second pass. removing terms divisible by lt(g_j) and lt(g_k) out of g_i for im[i], I->m[k], r)) pReduce(I->m[i],p,r); for (int k=j; km[k], I->m[l], r)) pReduce(I->m[k],p,r); /*** * removes the elements of I which have been reduced to 0 in the previous two passes **/ idSkipZeroes(I); id_Test(I,r); return j; } #ifndef NDEBUG BOOLEAN ppreduceInitially2(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == NUMBER_CMD)) { leftv w = v->next; if ((w != NULL) && (w->Typ() == POLY_CMD)) { ideal I; number p; poly g; omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); I = (ideal) u->CopyD(); p = (number) v->CopyD(); g = (poly) w->CopyD(); (void) ppreduceInitially(I,p,g,currRing); id_Delete(&I,currRing); n_Delete(&p,currRing->cf); omUpdateInfo(); Print("usedBytesAfter=%ld\n",om_Info.UsedBytes); I = (ideal) u->CopyD(); p = (number) v->CopyD(); g = (poly) w->CopyD(); (void) ppreduceInitially(I,p,g,currRing); n_Delete(&p,currRing->cf); res->rtyp = IDEAL_CMD; res->data = (char*) I; return FALSE; } } } return TRUE; } #endif //NDEBUG static poly ppNext(poly p, int l) { poly q = p; for (int i=0; i &T) { std::pair pointerToTerm; int k=T.size(); do { int j=0; for (int i=1; im[generatorA],termA),ppNext(H->m[generatorB],termB),r)<0) { mark cache=T[i-1]; T[i-1]=T[i]; T[i]=cache; j = i; } } k=j; } while(k); return; } static poly getTerm(const ideal H, const mark ab) { int a = ab.first; int b = ab.second; return ppNext(H->m[a],b); } static void adjustMarks(std::vector &T, const int newEntry) { for (unsigned i=0; i=newEntry) T[i].first = T[i].first+1; } return; } static void cleanupMarks(const ideal H, std::vector &T) { for (unsigned i=0; i T; for (int i=0; im[i]=H->m[i]; if (pNext(I->m[i])!=NULL) T.push_back(std::make_pair(i,1)); } /*** * Step 3: as long as the working list is not empty, successively reduce terms in it * by adding suitable elements to I and reducing it initially with respect to itself **/ int k=idSize(G); while (T.size()>0) { sortMarks(I,r,T); int i=0; for (; im[i],getTerm(I,T[0]),r)) break; if (iN; j++) p_SetExp(g,j,p_GetExp(h0,j,r)-p_GetExp(G->m[i],j,r),r); p_Setm(g,r); g = p_Mult_q(g,p_Copy(G->m[i],r),r); int newEntry = ppreduceInitially(I,p,g,r); adjustMarks(T,newEntry); } else T[0].second = T[0].second+1; cleanupMarks(I,T); } /*** * Step 4: cleanup, delete all polynomials in I which have been added in Step 3 **/ k=idSize(I); for (int i=0; im[j],I->m[i],r)) { I->m[i]=NULL; break; } } } id_Delete(&I,r); return false; } #ifndef NDEBUG BOOLEAN ppreduceInitially3(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == NUMBER_CMD)) { leftv w = v->next; if ((w != NULL) && (w->Typ() == IDEAL_CMD)) { ideal H,G; number p; omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); H = (ideal) u->CopyD(); p = (number) v->CopyD(); G = (ideal) w->CopyD(); (void) ppreduceInitially(H,p,G,currRing); n_Delete(&p,currRing->cf); id_Delete(&G,currRing); res->rtyp = IDEAL_CMD; res->data = (char*) H; return FALSE; } } } return TRUE; } #endif //NDEBUG /** * reduces I initially with respect to itself. * assumes that the generators of I are homogeneous in x and that p-t is in I. */ bool ppreduceInitially(ideal I, const ring r, const number p) { assume(!n_IsUnit(p,r->cf)); /*** * Step 1: split up I into components of same degree in x * the lowest component should only contain p-t **/ std::map H; int n = idSize(I); for (int i=0; im[i] = p_Cleardenom(I->m[i],r); long d = 0; for (int j=2; j<=r->N; j++) d += p_GetExp(I->m[i],j,r); std::map::iterator it = H.find(d); if (it != H.end()) idInsertPoly(it->second,I->m[i]); else { std::pair Hd(d,idInit(1)); Hd.second->m[0] = I->m[i]; H.insert(Hd); } } std::map::iterator it=H.begin(); ideal Hi = it->second; idShallowDelete(&Hi); it++; Hi = it->second; /*** * Step 2: reduce each component initially with respect to itself * and all lower components **/ if (ppreduceInitially(Hi,p,r)) return true; id_Test(Hi,r); id_Test(I,r); ideal G = idInit(n); int m=0; ideal GG = (ideal) omAllocBin(sip_sideal_bin); GG->nrows = 1; GG->rank = 1; GG->m=NULL; for (it++; it!=H.end(); it++) { int l=idSize(Hi); int k=l; poly cache; /** * sorts Hi according to degree in t in descending order * (lowest first, highest last) */ do { int j=0; for (int i=1; im[i-1],1,r)m[i],1,r)) { cache=Hi->m[i-1]; Hi->m[i-1]=Hi->m[i]; Hi->m[i]=cache; j = i; } } k=j; } while(k); int kG=n-m, kH=0; for (int i=n-m-l; im[i]),&(Hi->m[kH]),(n-i)*sizeof(poly)); break; } if (kH==l) break; if (p_GetExp(G->m[kG],1,r)>p_GetExp(Hi->m[kH],1,r)) G->m[i] = G->m[kG++]; else G->m[i] = Hi->m[kH++]; } m += l; IDELEMS(GG) = m; GG->m = &G->m[n-m]; id_Test(it->second,r); id_Test(GG,r); if (ppreduceInitially(it->second,p,GG,r)) return true; id_Test(it->second,r); id_Test(GG,r); idShallowDelete(&Hi); Hi = it->second; } idShallowDelete(&Hi); ptNormalize(I,p,r); omFreeBin((ADDRESS)GG, sip_sideal_bin); idShallowDelete(&G); return false; } #ifndef NDEBUG BOOLEAN reduceInitiallyDebug(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == NUMBER_CMD)) { omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); ideal I = (ideal) u->CopyD(); number p = (number) v->Data(); (void) ppreduceInitially(I,currRing,p); res->rtyp = IDEAL_CMD; res->data = (char*) I; return FALSE; } } return TRUE; } #endif // BOOLEAN ppreduceInitially(leftv res, leftv args) // { // leftv u = args; // if ((u != NULL) && (u->Typ() == IDEAL_CMD)) // { // ideal I = (ideal) u->CopyD(); // (void) ppreduceInitially(I,currRing); // res->rtyp = IDEAL_CMD; // res->data = (char*) I; // return FALSE; // } // return TRUE; // } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/ppinitialReduction.h000066400000000000000000000012761266270727000255120ustar00rootroot00000000000000#ifndef PPINITIALREDUCTION_H #define PPINITIALREDUCTION_H #include #include typedef std::pair mark; typedef std::vector > marks; bool isOrderingLocalInT(const ring r); void pReduce(ideal &I, const number p, const ring r); void pReduceInhomogeneous(poly &g, const number p, const ring r); bool ppreduceInitially(ideal I, const ring r, const number p); /* BOOLEAN ppreduceInitially(leftv res, leftv args); */ #ifndef NDEBUG BOOLEAN pReduceDebug(leftv res, leftv args); BOOLEAN reduceInitiallyDebug(leftv res, leftv args); BOOLEAN ptNormalize(leftv res, leftv args); BOOLEAN ppreduceInitially3(leftv res, leftv args); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/singularWishlist.h000066400000000000000000000036171266270727000252200ustar00rootroot00000000000000#ifndef SINGULARWISHLIST_H #define SINGULARWISHLIST_H #include /* #ifndef NDEBUG */ /* void z_Write(number p, ring r) */ /* { */ /* poly g = p_One(r); */ /* p_SetCoeff(g,p,r); */ /* p_Write(g,r); */ /* return; */ /* } */ /* #endif */ static inline BOOLEAN _p_LeadmonomDivisibleByNoComp(poly a, poly b, const ring r) { int i=r->VarL_Size - 1; unsigned long divmask = r->divmask; unsigned long la, lb; if (r->VarL_LowIndex >= 0) { i += r->VarL_LowIndex; do { la = a->exp[i]; lb = b->exp[i]; if ((la > lb) || (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask))) { pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE); return FALSE; } i--; } while (i>=r->VarL_LowIndex); } else { do { la = a->exp[r->VarL_Offset[i]]; lb = b->exp[r->VarL_Offset[i]]; if ((la > lb) || (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask))) { pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE); return FALSE; } i--; } while (i>=0); } pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == TRUE); return TRUE; } /** * p_LmDivisibleBy checks also the divisibility of coefficients **/ static inline BOOLEAN p_LeadmonomDivisibleBy(poly a, poly b, const ring r) { p_LmCheckPolyRing1(b, r); pIfThen1(a != NULL, p_LmCheckPolyRing1(b, r)); if (p_GetComp(a, r) == 0 || p_GetComp(a,r) == p_GetComp(b,r)) return _p_LeadmonomDivisibleByNoComp(a, b, r); return FALSE; } /** * id_ShallowDelete deletes the monomials of the polynomials stored inside of it **/ inline void idShallowDelete (ideal *h) { if (*h != NULL) { int k; k=(*h)->nrows*(*h)->ncols; if (k>0) omFreeSize((ADDRESS)((*h)->m),sizeof(poly)*k); omFreeBin((ADDRESS)*h, sip_sideal_bin); *h=NULL; } return; } #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/startingCone.cc000066400000000000000000000462621266270727000244460ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include groebnerCone groebnerStartingCone(const tropicalStrategy& currentStrategy) { groebnerCone sigma(currentStrategy.getStartingIdeal(), currentStrategy.getStartingRing(), currentStrategy); return sigma; } /** * Computes a starting point outside the lineatliy space by traversing the Groebner fan, * checking each cone whether it contains a ray in the tropical variety. * Returns a point in the tropical variety and a maximal Groebner cone containing the point. **/ std::pair tropicalStartingPoint(const ideal I, const ring r, const tropicalStrategy& currentStrategy) { // start by computing a maximal Groebner cone and // check whether one of its rays lies in the tropical variety const groebnerCone sigma(I,r,currentStrategy); gfan::ZVector startingPoint = sigma.tropicalPoint(); if (startingPoint.size() > 0) return std::make_pair(startingPoint,sigma); // if not, traverse the groebnerFan and until such a cone is found // and return the maximal cone together with a point in its ray groebnerCones groebnerFan; groebnerCones workingList; workingList.insert(sigma); while (!workingList.empty()) { const groebnerCone sigma = *(workingList.begin()); groebnerCones neighbours = sigma.groebnerNeighbours(); for (groebnerCones::iterator tau = neighbours.begin(); tau!=neighbours.end(); tau++) { if (groebnerFan.count(*tau) == 0) { if (workingList.count(*tau) == 0) { startingPoint = tau->tropicalPoint(); if (startingPoint.size() > 0) return std::make_pair(startingPoint,*tau); } workingList.insert(*tau); } } groebnerFan.insert(sigma); workingList.erase(sigma); } // return some trivial output, if such a cone cannot be found gfan::ZVector emptyVector = gfan::ZVector(0); groebnerCone emptyCone = groebnerCone(); return std::pair(emptyVector,emptyCone); } /** * Computes a starting point outside the lineatliy space by traversing the Groebner fan, * checking each cone whether it contains a ray in the tropical variety. * Returns a point in the tropical variety and a maximal Groebner cone containing the point. **/ std::pair tropicalStartingDataViaGroebnerFan(const ideal I, const ring r, const tropicalStrategy& currentStrategy) { // start by computing a maximal Groebner cone and // check whether one of its rays lies in the tropical variety const groebnerCone sigma(I,r,currentStrategy); gfan::ZVector startingPoint = sigma.tropicalPoint(); if (startingPoint.size() > 0) return std::make_pair(startingPoint,sigma); // if not, traverse the groebnerFan and until such a cone is found // and return the maximal cone together with a point in its ray groebnerCones groebnerFan; groebnerCones workingList; workingList.insert(sigma); while (!workingList.empty()) { const groebnerCone sigma = *(workingList.begin()); groebnerCones neighbours = sigma.groebnerNeighbours(); for (groebnerCones::iterator tau = neighbours.begin(); tau!=neighbours.end(); tau++) { if (groebnerFan.count(*tau) == 0) { if (workingList.count(*tau) == 0) { startingPoint = tau->tropicalPoint(); if (startingPoint.size() > 0) return std::make_pair(startingPoint,*tau); } workingList.insert(*tau); } } groebnerFan.insert(sigma); workingList.erase(sigma); } // return some trivial output, if such a cone cannot be found gfan::ZVector emptyVector = gfan::ZVector(0); groebnerCone emptyCone = groebnerCone(); return std::pair(emptyVector,emptyCone); } BOOLEAN positiveTropicalStartingPoint(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { ideal I = (ideal) u->Data(); if (idSize(I)==1) { tropicalStrategy currentStrategy(I,currRing); poly g = I->m[0]; std::set Tg = tropicalVariety(g,currRing,¤tStrategy); for (std::set::iterator zc=Tg.begin(); zc!=Tg.end(); zc++) { gfan::ZMatrix ray = zc->extremeRays(); for (int i=0; irtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(ray[i]); return FALSE; } } } res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(gfan::ZVector(0)); return FALSE; } WerrorS("positiveTropicalStartingPoint: ideal not principal"); return TRUE; } WerrorS("positiveTropicalStartingPoint: unexpected parameters"); return TRUE; } BOOLEAN nonNegativeTropicalStartingPoint(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { ideal I = (ideal) u->Data(); if (idSize(I)==1) { tropicalStrategy currentStrategy(I,currRing); poly g = I->m[0]; std::set Tg = tropicalVariety(g,currRing,¤tStrategy); for (std::set::iterator zc=Tg.begin(); zc!=Tg.end(); zc++) { gfan::ZMatrix ray = zc->extremeRays(); for (int i=0; irtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(ray[i]); return FALSE; } } } res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(gfan::ZVector(0)); return FALSE; } WerrorS("nonNegativeTropicalStartingPoint: ideal not principal"); return TRUE; } WerrorS("nonNegativeTropicalStartingPoint: unexpected parameters"); return TRUE; } BOOLEAN negativeTropicalStartingPoint(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { ideal I = (ideal) u->Data(); if (idSize(I)==1) { tropicalStrategy currentStrategy(I,currRing); poly g = I->m[0]; std::set Tg = tropicalVariety(g,currRing,¤tStrategy); for (std::set::iterator zc=Tg.begin(); zc!=Tg.end(); zc++) { gfan::ZMatrix ray = zc->extremeRays(); for (int i=0; irtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(ray[i]); return FALSE; } } } res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(gfan::ZVector(0)); return FALSE; } WerrorS("negativeTropicalStartingPoint: ideal not principal"); return TRUE; } WerrorS("negativeTropicalStartingPoint: unexpected parameters"); return TRUE; } BOOLEAN nonPositiveTropicalStartingPoint(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { ideal I = (ideal) u->Data(); if (idSize(I)==1) { tropicalStrategy currentStrategy(I,currRing); poly g = I->m[0]; std::set Tg = tropicalVariety(g,currRing,¤tStrategy); for (std::set::iterator zc=Tg.begin(); zc!=Tg.end(); zc++) { gfan::ZMatrix ray = zc->extremeRays(); for (int i=0; irtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(ray[i]); return FALSE; } } } res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(gfan::ZVector(0)); return FALSE; } WerrorS("nonPositiveTropicalStartingPoint: ideal not principal"); return TRUE; } WerrorS("nonPositiveTropicalStartingPoint: unexpected parameters"); return TRUE; } BOOLEAN tropicalStartingPoint(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { ideal I = (ideal) u->Data(); tropicalStrategy currentStrategy(I,currRing); if (idSize(I)==1) { poly g = I->m[0]; std::set Tg = tropicalVariety(g,currRing,¤tStrategy); if (Tg.empty()) { res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(gfan::ZVector(0)); return FALSE; } gfan::ZCone C = *(Tg.begin()); gfan::ZMatrix rays = C.extremeRays(); if (rays.getHeight()==0) { gfan::ZMatrix lin = C.generatorsOfLinealitySpace(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(lin[0]); return FALSE; } res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(rays[0]); return FALSE; } gfan::ZCone C0 = currentStrategy.getHomogeneitySpace(); if (C0.dimension()==currentStrategy.getExpectedDimension()) { gfan::ZMatrix lin = C0.generatorsOfLinealitySpace(); res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(lin[0]); return FALSE; } std::pair startingData = tropicalStartingDataViaGroebnerFan(I,currRing,currentStrategy); gfan::ZVector startingPoint = startingData.first; res->rtyp = BIGINTMAT_CMD; res->data = (void*) zVectorToBigintmat(startingPoint); return FALSE; } WerrorS("tropicalStartingPoint: unexpected parameters"); return TRUE; } /*** * returs the lineality space of the Groebner fan **/ static gfan::ZCone linealitySpaceOfGroebnerFan(const ideal I, const ring r) { int n = rVar(r); gfan::ZMatrix equations = gfan::ZMatrix(0,n); int* expv = (int*) omAlloc((n+1)*sizeof(int)); int k = idSize(I); for (int i=0; im[i]; if (g) { p_GetExpV(g,expv,r); gfan::ZVector leadexp = intStar2ZVector(n,expv); for (pIter(g); g; pIter(g)) { p_GetExpV(g,expv,r); equations.appendRow(leadexp-intStar2ZVector(n,expv)); } } } omFreeSize(expv,(n+1)*sizeof(int)); return gfan::ZCone(gfan::ZMatrix(0,n),equations); } /*** * Computes a starting cone in the tropical variety. **/ groebnerCone tropicalStartingCone(const tropicalStrategy& currentStrategy) { ring r = currentStrategy.getStartingRing(); ideal I = currentStrategy.getStartingIdeal(); currentStrategy.reduce(I,r); if (currentStrategy.isValuationTrivial()) { // copy the data, so that it be deleted when passed to the loop // s <- r // inI <- I ring s = rCopy(r); int k = idSize(I); ideal inI = idInit(k); nMapFunc identityMap = n_SetMap(r->cf,s->cf); for (int i=0; im[i] = p_PermPoly(I->m[i],NULL,r,s,identityMap,NULL,0); // repeatedly computes a point in the tropical variety outside the lineality space, // take the initial ideal with respect to it // and check whether the dimension of its homogeneity space // equals the dimension of the tropical variety gfan::ZCone zc = linealitySpaceOfGroebnerFan(inI,s); gfan::ZVector startingPoint; groebnerCone ambientMaximalCone; if (zc.dimension()>=currentStrategy.getExpectedDimension()) { // check whether the lineality space is contained in the tropical variety // i.e. whether the ideal does not contain a monomial poly mon = checkForMonomialViaSuddenSaturation(I,r); if (mon) { groebnerCone emptyCone = groebnerCone(); p_Delete(&mon,r); id_Delete(&inI,s); return emptyCone; } groebnerCone startingCone(inI,inI,s,currentStrategy); id_Delete(&inI,s); return startingCone; } while (zc.dimension() startingData = tropicalStartingDataViaGroebnerFan(inI,s,currentStrategy); startingPoint = startingData.first; ambientMaximalCone = groebnerCone(startingData.second); id_Delete(&inI,s); rDelete(s); inI = ambientMaximalCone.getPolynomialIdeal(); s = ambientMaximalCone.getPolynomialRing(); // compute the initial ideal with respect to the weight inI = initial(inI,s,startingPoint); zc = linealitySpaceOfGroebnerFan(inI,s); } // once the dimension of the homogeneity space equals that of the tropical variety // we know that we have an initial ideal with respect to a weight // in the relative interior of a maximal cone in the tropical variety // from this we can read of the inequalities and equations // but before doing so, we must lift the generating set of inI // to a generating set of I ideal J = lift(I,r,inI,s); // todo: use computeLift from tropicalStrategy groebnerCone startingCone(J,inI,s,currentStrategy); id_Delete(&inI,s); id_Delete(&J,s); // assume(checkContainmentInTropicalVariety(startingCone)); return startingCone; } else { // copy the data, so that it be deleted when passed to the loop // s <- r // inJ <- I ring s = rCopy(r); int k = idSize(I); ideal inJ = idInit(k); nMapFunc identityMap = n_SetMap(r->cf,s->cf); for (int i=0; im[i] = p_PermPoly(I->m[i],NULL,r,s,identityMap,NULL,0); // and check whether the dimension of its homogeneity space // equals the dimension of the tropical variety gfan::ZCone zc = linealitySpaceOfGroebnerFan(inJ,s); if (zc.dimension()>=currentStrategy.getExpectedDimension()) { // this shouldn't happen as trivial cases should be caught beforehand // this is the case that the tropical variety consists soely out of the lineality space poly mon = checkForMonomialViaSuddenSaturation(I,r); if (mon) { groebnerCone emptyCone = groebnerCone(); p_Delete(&mon,r); return emptyCone; } groebnerCone startingCone(I,inJ,s,currentStrategy); id_Delete(&inJ,s); rDelete(s); return startingCone; } // compute a point in the tropical variety outside the lineality space // compute the initial ideal with respect to the weight std::pair startingData = tropicalStartingDataViaGroebnerFan(inJ,s,currentStrategy); gfan::ZVector startingPoint = startingData.first; groebnerCone ambientMaximalCone = groebnerCone(startingData.second); id_Delete(&inJ,s); rDelete(s); inJ = ambientMaximalCone.getPolynomialIdeal(); s = ambientMaximalCone.getPolynomialRing(); inJ = initial(inJ,s,startingPoint); ideal inI = initial(I,r,startingPoint); zc = linealitySpaceOfGroebnerFan(inJ,s); // and check whether the dimension of its homogeneity space // equals the dimension of the tropical variety if (zc.dimension()==currentStrategy.getExpectedDimension()) { // this case shouldn't happen as trivial cases should be caught beforehand // this is the case that the tropical variety has a one-codimensional lineality space ideal J = lift(I,r,inJ,s); // todo: use computeLift from tropicalStrategy groebnerCone startingCone(J,inJ,s,currentStrategy); id_Delete(&inJ,s); id_Delete(&J,s); return startingCone; } // from this point on, inJ contains the uniformizing parameter, // hence it contains a monomial if and only if its residue over the residue field does. // so we will switch to the residue field ring rShortcut = rCopy0(r); nKillChar(rShortcut->cf); rShortcut->cf = nCopyCoeff((currentStrategy.getShortcutRing())->cf); rComplete(rShortcut); rTest(rShortcut); k = idSize(inJ); ideal inJShortcut = idInit(k); nMapFunc takingResidues = n_SetMap(s->cf,rShortcut->cf); for (int i=0; im[i] = p_PermPoly(inJ->m[i],NULL,s,rShortcut,takingResidues,NULL,0); idSkipZeroes(inJShortcut); id_Delete(&inJ,s); // we are interested in a maximal cone of the tropical variety of inJShortcut // this basically equivalent to the case without valuation (or constant coefficient case) // except that our ideal is still only homogeneous in the later variables, // hence we set the optional parameter completelyHomogeneous as 'false' tropicalStrategy shortcutStrategy(inJShortcut,rShortcut,false); groebnerCone startingConeShortcut = tropicalStartingCone(shortcutStrategy); id_Delete(&inJShortcut,rShortcut); rDelete(rShortcut); // now we need to obtain the initial of the residue of inJ // with respect to a weight in the tropical cone, // and obtain the initial of inJ with respect to the same weight ring sShortcut = startingConeShortcut.getPolynomialRing(); inJShortcut = startingConeShortcut.getPolynomialIdeal(); gfan::ZCone zd = startingConeShortcut.getPolyhedralCone(); gfan::ZVector interiorPoint = startingConeShortcut.getInteriorPoint(); inJShortcut = initial(inJShortcut,sShortcut,interiorPoint); inI = initial(inI,r,interiorPoint); s = rCopy0(sShortcut); // s will be a ring over the valuation ring nKillChar(s->cf); // with the same ordering as sShortcut s->cf = nCopyCoeff(r->cf); rComplete(s); rTest(s); k = idSize(inJShortcut); // inJ will be overwritten with initial of inJ inJ = idInit(k+1); inJ->m[0] = p_One(s); // with respect to that weight identityMap = n_SetMap(r->cf,s->cf); // first element will obviously be p p_SetCoeff(inJ->m[0],identityMap(currentStrategy.getUniformizingParameter(),r->cf,s->cf),s); nMapFunc findingRepresentatives = n_SetMap(sShortcut->cf,s->cf); for (int i=0; im[i+1] = p_PermPoly(inJShortcut->m[i],NULL,sShortcut,s,findingRepresentatives,NULL,0); ideal J = currentStrategy.computeLift(inJ,s,inI,I,r); // currentStrategy.reduce(J,s); groebnerCone startingCone(J,inJ,s,currentStrategy); id_Delete(&inJ,s); id_Delete(&J,s); rDelete(s); id_Delete(&inI,r); // assume(checkContainmentInTropicalVariety(startingCone)); return startingCone; } } BOOLEAN tropicalStartingCone(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { ideal I = (ideal) u->CopyD(); leftv v = u->next; if ((v != NULL) && (v->Typ() == NUMBER_CMD)) { number p = (number) v->Data(); leftv w = v->next; if (w==NULL) { tropicalStrategy currentStrategy(I,p,currRing); groebnerCone sigma = tropicalStartingCone(currentStrategy); gfan::ZCone* startingCone = new gfan::ZCone(sigma.getPolyhedralCone()); res->rtyp = coneID; res->data = (char*) startingCone; return FALSE; } } else { if (v==NULL) { tropicalStrategy currentStrategy(I,currRing); groebnerCone sigma = tropicalStartingCone(currentStrategy); res->rtyp = coneID; res->data = (char*) new gfan::ZCone(sigma.getPolyhedralCone()); return FALSE; } } } WerrorS("tropicalStartingCone: unexpected parameters"); return TRUE; } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/startingCone.h000066400000000000000000000011601266270727000242740ustar00rootroot00000000000000#ifndef STARTING_CONE_H #define STARTING_CONE_H #include #include groebnerCone groebnerStartingCone(const tropicalStrategy& currentStrategy); groebnerCone tropicalStartingCone(const tropicalStrategy& currentCase); BOOLEAN tropicalStartingPoint(leftv res, leftv args); BOOLEAN positiveTropicalStartingPoint(leftv res, leftv args); BOOLEAN nonNegativeTropicalStartingPoint(leftv res, leftv args); BOOLEAN negativeTropicalStartingPoint(leftv res, leftv args); BOOLEAN nonPositiveTropicalStartingPoint(leftv res, leftv args); BOOLEAN tropicalStartingCone(leftv res, leftv args); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/std_wrapper.cc000066400000000000000000000007221266270727000243270ustar00rootroot00000000000000#include #include #include ideal gfanlib_kStd_wrapper(ideal I, ring r, tHomog h=testHomog) { ring origin = currRing; if (origin != r) rChangeCurrRing(r); intvec* nullVector = NULL; ideal stdI = kStd(I,currRing->qideal,h,&nullVector); // there is still a memory leak here!!! id_DelDiv(stdI,currRing); idSkipZeroes(stdI); if (origin != r) rChangeCurrRing(origin); return stdI; } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/std_wrapper.h000066400000000000000000000003131266270727000241650ustar00rootroot00000000000000#ifndef CALLGFANLIB_STD_WRAPPER_H #define CALLGFANLIB_STD_WRAPPER_H #include #include ideal gfanlib_kStd_wrapper(ideal I, ring r, tHomog h=testHomog); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropical.cc000066400000000000000000000334021266270727000236130ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include #include int tropicalVerboseLevel = 0; gfan::ZCone homogeneitySpace(ideal I, ring r) { int n = rVar(r); poly g; int* leadexpv = (int*) omAlloc((n+1)*sizeof(int)); int* tailexpv = (int*) omAlloc((n+1)*sizeof(int)); gfan::ZVector leadexpw = gfan::ZVector(n); gfan::ZVector tailexpw = gfan::ZVector(n); gfan::ZMatrix equations = gfan::ZMatrix(0,n); for (int i=0; im[i]; if (g) { p_GetExpV(g,leadexpv,r); leadexpw = intStar2ZVector(n,leadexpv); pIter(g); while (g) { p_GetExpV(g,tailexpv,r); tailexpw = intStar2ZVector(n,tailexpv); equations.appendRow(leadexpw-tailexpw); pIter(g); } } } omFreeSize(leadexpv,(n+1)*sizeof(int)); omFreeSize(tailexpv,(n+1)*sizeof(int)); return gfan::ZCone(gfan::ZMatrix(0, equations.getWidth()),equations); } BOOLEAN homogeneitySpace(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == POLY_CMD)) { leftv v = u->next; if (v == NULL) { poly g = (poly) u->Data(); ideal I = idInit(1); I->m[0] = g; res->rtyp = coneID; res->data = (void*) new gfan::ZCone(homogeneitySpace(I,currRing)); I->m[0] = NULL; id_Delete(&I,currRing); return FALSE; } } if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if (v == NULL) { ideal I = (ideal) u->Data(); res->rtyp = coneID; res->data = (void*) new gfan::ZCone(homogeneitySpace(I,currRing)); return FALSE; } } WerrorS("homogeneitySpace: unexpected parameters"); return TRUE; } gfan::ZCone lowerHomogeneitySpace(ideal I, ring r) { int n = rVar(r); poly g; int* leadexpv = (int*) omAlloc((n+1)*sizeof(int)); int* tailexpv = (int*) omAlloc((n+1)*sizeof(int)); gfan::ZVector leadexpw = gfan::ZVector(n); gfan::ZVector tailexpw = gfan::ZVector(n); gfan::ZMatrix equations = gfan::ZMatrix(0,n); for (int i=0; im[i]; if (g) { p_GetExpV(g,leadexpv,r); leadexpw = intStar2ZVector(n,leadexpv); pIter(g); while (g) { p_GetExpV(g,tailexpv,r); tailexpw = intStar2ZVector(n,tailexpv); equations.appendRow(leadexpw-tailexpw); pIter(g); } } } gfan::ZMatrix inequalities = gfan::ZMatrix(0,n); gfan::ZVector lowerHalfSpaceCondition = gfan::ZVector(n); lowerHalfSpaceCondition[0] = -1; inequalities.appendRow(lowerHalfSpaceCondition); omFreeSize(leadexpv,(n+1)*sizeof(int)); omFreeSize(tailexpv,(n+1)*sizeof(int)); return gfan::ZCone(inequalities,equations); } BOOLEAN lowerHomogeneitySpace(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == POLY_CMD)) { leftv v = u->next; if (v == NULL) { poly g = (poly) u->Data(); ideal I = idInit(1); I->m[0] = g; res->rtyp = coneID; res->data = (void*) new gfan::ZCone(lowerHomogeneitySpace(I,currRing)); I->m[0] = NULL; id_Delete(&I,currRing); return FALSE; } } if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if (v == NULL) { ideal I = (ideal) u->Data(); res->rtyp = coneID; res->data = (void*) new gfan::ZCone(lowerHomogeneitySpace(I,currRing)); return FALSE; } } WerrorS("lowerHomogeneitySpace: unexpected parameters"); return TRUE; } gfan::ZCone groebnerCone(const ideal I, const ring r, const gfan::ZVector &w) { int n = rVar(r); poly g = NULL; int* leadexpv = (int*) omAlloc((n+1)*sizeof(int)); int* tailexpv = (int*) omAlloc((n+1)*sizeof(int)); gfan::ZVector leadexpw = gfan::ZVector(n); gfan::ZVector tailexpw = gfan::ZVector(n); gfan::ZMatrix inequalities = gfan::ZMatrix(0,n); for (int i=0; im[i]; if (g!=NULL) { p_GetExpV(g,leadexpv,currRing); leadexpw = intStar2ZVector(n, leadexpv); pIter(g); while (g!=NULL) { pGetExpV(g,tailexpv); tailexpw = intStar2ZVector(n, tailexpv); inequalities.appendRow(leadexpw-tailexpw); pIter(g); } } } ideal inI = initial(I,currRing,w); gfan::ZMatrix equations = gfan::ZMatrix(0,n); for (int i=0; im[i]; if (g!=NULL) { p_GetExpV(g,leadexpv,currRing); leadexpw = intStar2ZVector(n, leadexpv); pIter(g); while (g!=NULL) { pGetExpV(g,tailexpv); tailexpw = intStar2ZVector(n, tailexpv); equations.appendRow(leadexpw-tailexpw); pIter(g); } } } omFreeSize(leadexpv,(n+1)*sizeof(int)); omFreeSize(tailexpv,(n+1)*sizeof(int)); id_Delete(&inI,currRing); return gfan::ZCone(inequalities,equations); } BOOLEAN groebnerCone(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == POLY_CMD)) { leftv v = u->next; if ((v !=NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) { try { poly g = (poly) u->Data(); ideal I = idInit(1); I->m[0] = g; gfan::ZVector* weightVector; if (v->Typ() == INTVEC_CMD) { intvec* w0 = (intvec*) v->Data(); bigintmat* w1 = iv2bim(w0,coeffs_BIGINT); w1->inpTranspose(); weightVector = bigintmatToZVector(*w1); delete w1; } else { bigintmat* w1 = (bigintmat*) v->Data(); weightVector = bigintmatToZVector(*w1); } res->rtyp = coneID; res->data = (void*) new gfan::ZCone(groebnerCone(I,currRing,*weightVector)); delete weightVector; I->m[0] = NULL; id_Delete(&I,currRing); return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } } if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if ((v !=NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) { try { ideal I = (ideal) u->Data(); gfan::ZVector* weightVector; if (v->Typ() == INTVEC_CMD) { intvec* w0 = (intvec*) v->Data(); bigintmat* w1 = iv2bim(w0,coeffs_BIGINT); w1->inpTranspose(); weightVector = bigintmatToZVector(*w1); delete w1; } else { bigintmat* w1 = (bigintmat*) v->Data(); weightVector = bigintmatToZVector(*w1); } res->rtyp = coneID; res->data = (void*) new gfan::ZCone(groebnerCone(I,currRing,*weightVector)); delete weightVector; return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } } WerrorS("groebnerCone: unexpected parameters"); return TRUE; } gfan::ZCone maximalGroebnerCone(const ideal &I, const ring &r) { int n = rVar(r); poly g = NULL; int* leadexpv = (int*) omAlloc((n+1)*sizeof(int)); int* tailexpv = (int*) omAlloc((n+1)*sizeof(int)); gfan::ZVector leadexpw = gfan::ZVector(n); gfan::ZVector tailexpw = gfan::ZVector(n); gfan::ZMatrix inequalities = gfan::ZMatrix(0,n); for (int i=0; im[i]; pGetExpV(g,leadexpv); leadexpw = intStar2ZVector(n, leadexpv); pIter(g); while (g != NULL) { pGetExpV(g,tailexpv); tailexpw = intStar2ZVector(n, tailexpv); inequalities.appendRow(leadexpw-tailexpw); pIter(g); } } omFreeSize(leadexpv,(n+1)*sizeof(int)); omFreeSize(tailexpv,(n+1)*sizeof(int)); return gfan::ZCone(inequalities,gfan::ZMatrix(0, inequalities.getWidth())); } BOOLEAN maximalGroebnerCone(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == POLY_CMD)) { leftv v = u->next; if (v == NULL) { try { poly g = (poly) u->Data(); ideal I = idInit(1); I->m[0] = g; res->rtyp = coneID; res->data = (void*) new gfan::ZCone(maximalGroebnerCone(I,currRing)); I->m[0] = NULL; id_Delete(&I,currRing); return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } } if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if (v == NULL) { try { ideal I = (ideal) u->Data(); res->rtyp = coneID; res->data = (void*) new gfan::ZCone(maximalGroebnerCone(I,currRing)); return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } } WerrorS("maximalGroebnerCone: unexpected parameters"); return TRUE; } BOOLEAN initial(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == POLY_CMD)) { leftv v = u->next; if ((v !=NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) { poly p = (poly) u->Data(); gfan::ZVector* weightVector; if (v->Typ() == INTVEC_CMD) { intvec* w0 = (intvec*) v->Data(); bigintmat* w1 = iv2bim(w0,coeffs_BIGINT); w1->inpTranspose(); weightVector = bigintmatToZVector(*w1); delete w1; } else { bigintmat* w1 = (bigintmat*) v->Data(); weightVector = bigintmatToZVector(*w1); } res->rtyp = POLY_CMD; res->data = (void*) initial(p, currRing, *weightVector); delete weightVector; return FALSE; } } if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if ((v !=NULL) && ((v->Typ() == BIGINTMAT_CMD) || (v->Typ() == INTVEC_CMD))) { try { ideal I = (ideal) u->Data(); gfan::ZVector* weightVector; if (v->Typ() == INTVEC_CMD) { intvec* w0 = (intvec*) v->Data(); bigintmat* w1 = iv2bim(w0,coeffs_BIGINT); w1->inpTranspose(); weightVector = bigintmatToZVector(*w1); delete w1; } else { bigintmat* w1 = (bigintmat*) v->Data(); weightVector = bigintmatToZVector(*w1); } res->rtyp = IDEAL_CMD; res->data = (void*) initial(I, currRing, *weightVector); delete weightVector; return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } } WerrorS("initial: unexpected parameters"); return TRUE; } void tropical_setup(SModulFunctions* p) { p->iiAddCproc("","groebnerCone",FALSE,groebnerCone); p->iiAddCproc("","maximalGroebnerCone",FALSE,maximalGroebnerCone); p->iiAddCproc("","homogeneitySpace",FALSE,homogeneitySpace); p->iiAddCproc("","lowerHomogeneitySpace",FALSE,lowerHomogeneitySpace); p->iiAddCproc("","initial",FALSE,initial); p->iiAddCproc("","tropicalVariety",FALSE,tropicalVariety); p->iiAddCproc("","groebnerFan",FALSE,groebnerFan); p->iiAddCproc("","groebnerComplex",FALSE,groebnerComplex); #ifndef NDEBUG // p->iiAddCproc("","tropicalNeighbours",FALSE,tropicalNeighbours); // p->iiAddCproc("","initial0",FALSE,initial0); p->iiAddCproc("","pReduceDebug",FALSE,pReduceDebug); // p->iiAddCproc("","ppreduceInitially0",FALSE,ppreduceInitially0); // p->iiAddCproc("","ppreduceInitially1",FALSE,ppreduceInitially1); // p->iiAddCproc("","ppreduceInitially2",FALSE,ppreduceInitially2); p->iiAddCproc("","ptNormalize",FALSE,ptNormalize); p->iiAddCproc("","ppreduceInitially3",FALSE,ppreduceInitially3); // p->iiAddCproc("","ppreduceInitially4",FALSE,ppreduceInitially4); // p->iiAddCproc("","ttpReduce",FALSE,ttpReduce); // p->iiAddCproc("","ttreduceInitially0",FALSE,ttreduceInitially0); // p->iiAddCproc("","ttreduceInitially1",FALSE,ttreduceInitially1); // p->iiAddCproc("","ttreduceInitially2",FALSE,ttreduceInitially2); // p->iiAddCproc("","ttreduceInitially3",FALSE,ttreduceInitially3); // p->iiAddCproc("","ttreduceInitially4",FALSE,ttreduceInitially4); // p->iiAddCproc("","checkForMonomial",FALSE,checkForMonomial); // p->iiAddCproc("","dwr0",FALSE,dwr0); // p->iiAddCproc("","witness0",FALSE,witness0); // p->iiAddCproc("","tropicalVariety00",FALSE,tropicalVariety00); // p->iiAddCproc("","tropicalVariety01",FALSE,tropicalVariety01); // p->iiAddCproc("","tropicalCurve0",FALSE,tropicalCurve0); // p->iiAddCproc("","tropicalCurve1",FALSE,tropicalCurve1); p->iiAddCproc("","reduceInitiallyDebug",FALSE,reduceInitiallyDebug); p->iiAddCproc("","computeWitnessDebug",FALSE,computeWitnessDebug); p->iiAddCproc("","computeFlipDebug",FALSE,computeFlipDebug); p->iiAddCproc("","flipConeDebug",FALSE,flipConeDebug); // p->iiAddCproc("","groebnerNeighboursDebug",FALSE,groebnerNeighboursDebug); // p->iiAddCproc("","tropicalNeighboursDebug",FALSE,tropicalNeighboursDebug); p->iiAddCproc("","tropicalStarDebug",FALSE,tropicalStarDebug); p->iiAddCproc("","tropicalStartingPoint",FALSE,tropicalStartingPoint); p->iiAddCproc("","positiveTropicalStartingPoint",FALSE,positiveTropicalStartingPoint); p->iiAddCproc("","nonNegativeTropicalStartingPoint",FALSE,nonNegativeTropicalStartingPoint); p->iiAddCproc("","negativeTropicalStartingPoint",FALSE,negativeTropicalStartingPoint); p->iiAddCproc("","nonPositiveTropicalStartingPoint",FALSE,nonPositiveTropicalStartingPoint); p->iiAddCproc("","tropicalStartingCone",FALSE,tropicalStartingCone); #endif //NDEBUG // p->iiAddCproc("","ppreduceInitially",FALSE,ppreduceInitially); // p->iiAddCproc("","ttreduceInitially",FALSE,ttreduceInitially); } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropical.h000066400000000000000000000003071266270727000234530ustar00rootroot00000000000000#ifndef TROPICAL_H #define TROPICAL_H #include "Singular/ipid.h" extern int tropicalVerboseLevel; gfan::ZCone homogeneitySpace(ideal I, ring r); void tropical_setup(SModulFunctions* p); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalCurves.cc000066400000000000000000000265641266270727000250160ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #ifndef NDEBUG #include #endif /*** * Given two sets of cones A,B and a dimensional bound d, * computes the intersections of all cones of A with all cones of B, * and throws away those of lower dimension than d. **/ static ZConesSortedByDimension intersect(const ZConesSortedByDimension &setA, const ZConesSortedByDimension &setB, int d=0) { if (setA.empty()) return setB; if (setB.empty()) return setA; ZConesSortedByDimension setAB; for (ZConesSortedByDimension::iterator coneOfA=setA.begin(); coneOfA!=setA.end(); coneOfA++) { for (ZConesSortedByDimension::iterator coneOfB=setB.begin(); coneOfB!=setB.end(); coneOfB++) { gfan::ZCone coneOfIntersection = gfan::intersection(*coneOfA,*coneOfB); if (coneOfIntersection.dimension()>=d) { coneOfIntersection.canonicalize(); setAB.insert(coneOfIntersection); } } } return setAB; } /*** * Given a ring r, weights u, w, and a matrix E, returns a copy of r whose ordering is, * for any ideal homogeneous with respect to u, weighted with respect to u and * whose tiebreaker is genericly weighted with respect to v and E in the following sense: * the ordering "lies" on the affine space A running through v and spanned by the row vectors of E, * and it lies in a Groebner cone of dimension at least rank(E)=dim(A). **/ static ring genericlyWeightedOrdering(const ring r, const gfan::ZVector &u, const gfan::ZVector &w, const gfan::ZMatrix &W, const tropicalStrategy* currentStrategy) { int n = rVar(r); int h = W.getHeight(); /* create a copy s of r and delete its ordering */ ring s = rCopy0(r); omFree(s->order); s->order = (int*) omAlloc0((h+4)*sizeof(int)); omFree(s->block0); s->block0 = (int*) omAlloc0((h+4)*sizeof(int)); omFree(s->block1); s->block1 = (int*) omAlloc0((h+4)*sizeof(int)); for (int j=0; s->wvhdl[j]; j++) omFree(s->wvhdl[j]); omFree(s->wvhdl); s->wvhdl = (int**) omAlloc0((h+4)*sizeof(int*)); /* construct a new ordering as describe above */ bool overflow = false; s->order[0] = ringorder_a; s->block0[0] = 1; s->block1[0] = n; gfan::ZVector uAdjusted = currentStrategy->adjustWeightForHomogeneity(u); s->wvhdl[0] = ZVectorToIntStar(uAdjusted,overflow); s->order[1] = ringorder_a; s->block0[1] = 1; s->block1[1] = n; gfan::ZVector wAdjusted = currentStrategy->adjustWeightUnderHomogeneity(w,uAdjusted); s->wvhdl[1] = ZVectorToIntStar(wAdjusted,overflow); for (int j=0; jorder[j+2] = ringorder_a; s->block0[j+2] = 1; s->block1[j+2] = n; wAdjusted = currentStrategy->adjustWeightUnderHomogeneity(W[j],uAdjusted); s->wvhdl[j+2] = ZVectorToIntStar(wAdjusted,overflow); } s->order[h+1] = ringorder_wp; s->block0[h+1] = 1; s->block1[h+1] = n; wAdjusted = currentStrategy->adjustWeightUnderHomogeneity(W[h-1],uAdjusted); s->wvhdl[h+1] = ZVectorToIntStar(wAdjusted,overflow); s->order[h+2] = ringorder_C; if (overflow) { WerrorS("genericlyWeightedOrdering: overflow in weight vector"); throw 0; // weightOverflow; } /* complete the ring and return it */ rComplete(s); rTest(s); return s; } /*** * Let I be an ideal. Given a weight vector u in the relative interior * of a one-codimensional cone of the tropical variety of I and * the initial ideal inI with respect to it, computes the star of the tropical variety in u. **/ ZConesSortedByDimension tropicalStar(ideal inI, const ring r, const gfan::ZVector &u, const tropicalStrategy* currentStrategy) { int k = idSize(inI); int d = currentStrategy->getExpectedDimension(); /* Compute the common refinement over all tropical varieties * of the polynomials in the generating set */ ZConesSortedByDimension C = tropicalVarietySortedByDimension(inI->m[0],r,currentStrategy); for (int i=1; im[i],r,currentStrategy),d); /* Cycle through all maximal cones of the refinement. * Pick a monomial ordering corresponding to a generic weight vector in it * and check if the initial ideal is monomial free, generic meaning * that it lies in a maximal Groebner cone in the maximal cone of the refinement. * If the initial ideal is not monomial free, compute a witness for the monomial * and compute the common refinement with its tropical variety. * If all initial ideals are monomial free, then we have our tropical curve */ // gfan::ZFan* zf = toFanStar(C); // std::cout << zf->toString(2+4+8+128) << std::endl; // delete zf; for (std::set::iterator zc=C.begin(); zc!=C.end();) { gfan::ZVector w = zc->getRelativeInteriorPoint(); gfan::ZMatrix W = zc->generatorsOfSpan(); // std::cout << zc->extremeRays() << std::endl; ring s = genericlyWeightedOrdering(r,u,w,W,currentStrategy); nMapFunc identity = n_SetMap(r->cf,s->cf); ideal inIs = idInit(k); for (int j=0; jm[j] = p_PermPoly(inI->m[j],NULL,r,s,identity,NULL,0); ideal inIsSTD = gfanlib_kStd_wrapper(inIs,s,isHomog); id_Delete(&inIs,s); ideal ininIs = initial(inIsSTD,s,w,W); std::pair mons = currentStrategy->checkInitialIdealForMonomial(ininIs,s); if (mons.first!=NULL) { poly gs; if (mons.second>=0) // cheap way out, ininIsSTD already contains a monomial in its generators gs = inIsSTD->m[mons.second]; else // compute witness gs = witness(mons.first,inIsSTD,ininIs,s); C = intersect(C,tropicalVarietySortedByDimension(gs,s,currentStrategy),d); nMapFunc mMap = n_SetMap(s->cf,r->cf); poly gr = p_PermPoly(gs,NULL,s,r,mMap,NULL,0); idInsertPoly(inI,gr); k++; if (mons.second<0) { // if necessary, cleanup mons and gs p_Delete(&mons.first,s); p_Delete(&gs,s); } // cleanup rest, reset zc id_Delete(&inIsSTD,s); id_Delete(&ininIs,s); rDelete(s); zc = C.begin(); } else { // cleanup remaining data of first stage id_Delete(&inIsSTD,s); id_Delete(&ininIs,s); rDelete(s); gfan::ZVector wNeg = currentStrategy->negateWeight(w); if (zc->contains(wNeg)) { s = genericlyWeightedOrdering(r,u,wNeg,W,currentStrategy); identity = n_SetMap(r->cf,s->cf); inIs = idInit(k); for (int j=0; jm[j] = p_PermPoly(inI->m[j],NULL,r,s,identity,NULL,0); inIsSTD = gfanlib_kStd_wrapper(inIs,s,isHomog); id_Delete(&inIs,s); ininIs = initial(inIsSTD,s,wNeg,W); mons = currentStrategy->checkInitialIdealForMonomial(ininIs,s); if (mons.first!=NULL) { poly gs; if (mons.second>=0) // cheap way out, ininIsSTD already contains a monomial in its generators gs = inIsSTD->m[mons.second]; else // compute witness gs = witness(mons.first,inIsSTD,ininIs,s); C = intersect(C,tropicalVarietySortedByDimension(gs,s,currentStrategy),d); nMapFunc mMap = n_SetMap(s->cf,r->cf); poly gr = p_PermPoly(gs,NULL,s,r,mMap,NULL,0); idInsertPoly(inI,gr); k++; if (mons.second<0) { // if necessary, cleanup mons and gs p_Delete(&mons.first,s); p_Delete(&gs,s); } // reset zc zc = C.begin(); } else zc++; // cleanup remaining data of second stage id_Delete(&inIsSTD,s); id_Delete(&ininIs,s); rDelete(s); } else zc++; } } return C; } gfan::ZMatrix raysOfTropicalStar(ideal I, const ring r, const gfan::ZVector &u, const tropicalStrategy* currentStrategy) { ZConesSortedByDimension C = tropicalStar(I,r,u,currentStrategy); // gfan::ZFan* zf = toFanStar(C); // std::cout << zf->toString(); // delete zf; gfan::ZMatrix raysOfC(0,u.size()); if (!currentStrategy->restrictToLowerHalfSpace()) { for (ZConesSortedByDimension::iterator zc=C.begin(); zc!=C.end(); zc++) { assume(zc->dimensionOfLinealitySpace()+1 >= zc->dimension()); if (zc->dimensionOfLinealitySpace()+1 >= zc->dimension()) raysOfC.appendRow(zc->getRelativeInteriorPoint()); else { gfan::ZVector interiorPoint = zc->getRelativeInteriorPoint(); if (!currentStrategy->homogeneitySpaceContains(interiorPoint)) { raysOfC.appendRow(interiorPoint); raysOfC.appendRow(currentStrategy->negateWeight(interiorPoint)); } else { gfan::ZMatrix zm = zc->generatorsOfLinealitySpace(); for (int i=0; ihomogeneitySpaceContains(point)) { raysOfC.appendRow(point); raysOfC.appendRow(currentStrategy->negateWeight(point)); break; } } } } } } else { for (ZConesSortedByDimension::iterator zc=C.begin(); zc!=C.end(); zc++) { assume(zc->dimensionOfLinealitySpace()+2 >= zc->dimension()); if (zc->dimensionOfLinealitySpace()+2 == zc->dimension()) raysOfC.appendRow(zc->getRelativeInteriorPoint()); else { gfan::ZVector interiorPoint = zc->getRelativeInteriorPoint(); if (!currentStrategy->homogeneitySpaceContains(interiorPoint)) { raysOfC.appendRow(interiorPoint); raysOfC.appendRow(currentStrategy->negateWeight(interiorPoint)); } else { gfan::ZMatrix zm = zc->generatorsOfLinealitySpace(); for (int i=0; ihomogeneitySpaceContains(point)) { raysOfC.appendRow(point); raysOfC.appendRow(currentStrategy->negateWeight(point)); break; } } } } } } return raysOfC; } /*** * Computes the tropical curve of an x-homogeneous ideal I * which is weighted homogeneous with respect to weight w in ring r **/ #ifndef NDEBUG BOOLEAN tropicalStarDebug(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { leftv v = u->next; if ((v!=NULL) && (v->Typ()==BIGINTMAT_CMD)) { omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); ideal inI = (ideal) u->CopyD(); bigintmat* u = (bigintmat*) v->CopyD(); tropicalStrategy currentCase(inI,currRing); gfan::ZVector* v = bigintmatToZVector(u); ZConesSortedByDimension C = tropicalStar(inI,currRing,*v,¤tCase); id_Delete(&inI,currRing); delete u; delete v; res->rtyp = NONE; res->data = NULL; // res->rtyp = fanID; // res->data = (char*) toFanStar(C); return FALSE; } } WerrorS("tropicalStarDebug: unexpected parameters"); return TRUE; } #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalCurves.h000066400000000000000000000011731266270727000246450ustar00rootroot00000000000000#ifndef TROPICAL_CURVE_H #define TROPICAL_CURVE_H #include #include #include #include #include ZConesSortedByDimension tropicalStar(const ideal I, const ring r, const gfan::ZVector &u, const tropicalStrategy* currentStrategy); gfan::ZMatrix raysOfTropicalStar(ideal I, const ring r, const gfan::ZVector &u, const tropicalStrategy* currentStrategy); #ifndef NDEBUG BOOLEAN tropicalStarDebug(leftv res, leftv args); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalStrategy.cc000066400000000000000000000747371266270727000253560ustar00rootroot00000000000000#include #include #include // #include #include #include #include // for various commands in dim(ideal I, ring r): #include #include #include #include // for isPrime(int i) /*** * Computes the dimension of an ideal I in ring r * Copied from jjDim in iparith.cc **/ int dim(ideal I, ring r) { ring origin = currRing; if (origin != r) rChangeCurrRing(r); int d; if (rField_is_Ring(currRing)) { int i = idPosConstant(I); if ((i != -1) #ifdef HAVE_RINGS && (n_IsUnit(p_GetCoeff(I->m[i],currRing->cf),currRing->cf)) #endif ) return -1; ideal vv = id_Head(I,currRing); if (i != -1) pDelete(&vv->m[i]); d = scDimInt(vv, currRing->qideal); if (rField_is_Ring_Z(currRing) && (i==-1)) d++; idDelete(&vv); return d; } else d = scDimInt(I,currRing->qideal); if (origin != r) rChangeCurrRing(origin); return d; } static void swapElements(ideal I, ideal J) { assume(idSize(I)==idSize(J)); for (int i=idSize(I)-1; i>=0; i--) { poly cache = I->m[i]; I->m[i] = J->m[i]; J->m[i] = cache; } } static bool noExtraReduction(ideal I, ring r, number /*p*/) { int n = rVar(r); gfan::ZVector allOnes(n); for (int i=0; iorder; int* block0 = rShortcut->block0; int* block1 = rShortcut->block1; int** wvhdl = rShortcut->wvhdl; int h = rBlocks(r); rShortcut->order = (int*) omAlloc0((h+1)*sizeof(int)); rShortcut->block0 = (int*) omAlloc0((h+1)*sizeof(int)); rShortcut->block1 = (int*) omAlloc0((h+1)*sizeof(int)); rShortcut->wvhdl = (int**) omAlloc0((h+1)*sizeof(int*)); rShortcut->order[0] = ringorder_a; rShortcut->block0[0] = 1; rShortcut->block1[0] = n; bool overflow; rShortcut->wvhdl[0] = ZVectorToIntStar(allOnes,overflow); for (int i=1; i<=h; i++) { rShortcut->order[i] = order[i-1]; rShortcut->block0[i] = block0[i-1]; rShortcut->block1[i] = block1[i-1]; rShortcut->wvhdl[i] = wvhdl[i-1]; } rComplete(rShortcut); rTest(rShortcut); omFree(order); omFree(block0); omFree(block1); omFree(wvhdl); int k = idSize(I); ideal IShortcut = idInit(k); nMapFunc intoShortcut = n_SetMap(r->cf,rShortcut->cf); for (int i=0; im[i] = p_PermPoly(I->m[i],NULL,r,rShortcut,intoShortcut,NULL,0); ideal JShortcut = gfanlib_kStd_wrapper(IShortcut,rShortcut); ideal J = idInit(k); nMapFunc outofShortcut = n_SetMap(rShortcut->cf,r->cf); for (int i=0; im[i] = p_PermPoly(JShortcut->m[i],NULL,rShortcut,r,outofShortcut,NULL,0); swapElements(I,J); id_Delete(&IShortcut,rShortcut); id_Delete(&JShortcut,rShortcut); rDelete(rShortcut); id_Delete(&J,r); return false; } /** * Initializes all relevant structures and information for the trivial valuation case, * i.e. computing a tropical variety without any valuation. */ tropicalStrategy::tropicalStrategy(const ideal I, const ring r, const bool completelyHomogeneous, const bool completeSpace): originalRing(rCopy(r)), originalIdeal(id_Copy(I,r)), expectedDimension(dim(originalIdeal,originalRing)), linealitySpace(homogeneitySpace(originalIdeal,originalRing)), startingRing(rCopy(originalRing)), startingIdeal(id_Copy(originalIdeal,originalRing)), uniformizingParameter(NULL), shortcutRing(NULL), onlyLowerHalfSpace(false), weightAdjustingAlgorithm1(nonvalued_adjustWeightForHomogeneity), weightAdjustingAlgorithm2(nonvalued_adjustWeightUnderHomogeneity), extraReductionAlgorithm(noExtraReduction) { assume(rField_is_Q(r) || rField_is_Zp(r) || rField_is_Ring_Z(r)); if (!completelyHomogeneous) { weightAdjustingAlgorithm1 = valued_adjustWeightForHomogeneity; weightAdjustingAlgorithm2 = valued_adjustWeightUnderHomogeneity; } if (!completeSpace) onlyLowerHalfSpace = true; } /** * Given a polynomial ring r over the rational numbers and a weighted ordering, * returns a polynomial ring s over the integers with one extra variable, which is weighted -1. */ static ring constructStartingRing(ring r) { assume(rField_is_Q(r)); ring s = rCopy0(r,FALSE,FALSE); nKillChar(s->cf); s->cf = nInitChar(n_Z,NULL); int n = rVar(s)+1; s->N = n; char** oldNames = s->names; s->names = (char**) omAlloc((n+1)*sizeof(char**)); s->names[0] = omStrDup("t"); for (int i=1; inames[i] = oldNames[i-1]; omFree(oldNames); s->order = (int*) omAlloc0(3*sizeof(int)); s->block0 = (int*) omAlloc0(3*sizeof(int)); s->block1 = (int*) omAlloc0(3*sizeof(int)); s->wvhdl = (int**) omAlloc0(3*sizeof(int**)); s->order[0] = ringorder_ws; s->block0[0] = 1; s->block1[0] = n; s->wvhdl[0] = (int*) omAlloc(n*sizeof(int)); s->wvhdl[0][0] = 1; if (r->order[0] == ringorder_lp) { s->wvhdl[0][1] = 1; } else if (r->order[0] == ringorder_ls) { s->wvhdl[0][1] = -1; } else if (r->order[0] == ringorder_dp) { for (int i=1; iwvhdl[0][i] = -1; } else if (r->order[0] == ringorder_ds) { for (int i=1; iwvhdl[0][i] = 1; } else if (r->order[0] == ringorder_ws) { for (int i=1; iwvhdl[0][i] = r->wvhdl[0][i-1]; } else { for (int i=1; iwvhdl[0][i] = -r->wvhdl[0][i-1]; } s->order[1] = ringorder_C; rComplete(s); rTest(s); return s; } static ideal constructStartingIdeal(ideal originalIdeal, ring originalRing, number uniformizingParameter, ring startingRing) { // construct p-t poly g = p_One(startingRing); p_SetCoeff(g,uniformizingParameter,startingRing); pNext(g) = p_One(startingRing); p_SetExp(pNext(g),1,1,startingRing); p_SetCoeff(pNext(g),n_Init(-1,startingRing->cf),startingRing); p_Setm(pNext(g),startingRing); ideal pt = idInit(1); pt->m[0] = g; // map originalIdeal from originalRing into startingRing int k = idSize(originalIdeal); ideal J = idInit(k+1); nMapFunc nMap = n_SetMap(originalRing->cf,startingRing->cf); int n = rVar(originalRing); int* shiftByOne = (int*) omAlloc((n+1)*sizeof(int)); for (int i=1; i<=n; i++) shiftByOne[i]=i+1; for (int i=0; im[i] = p_PermPoly(originalIdeal->m[i],shiftByOne,originalRing,startingRing,nMap,NULL,0); omFreeSize(shiftByOne,(n+1)*sizeof(int)); ring origin = currRing; rChangeCurrRing(startingRing); ideal startingIdeal = kNF(pt,startingRing->qideal,J); // mathematically redundant, rChangeCurrRing(origin); // but helps with upcoming std computation // ideal startingIdeal = J; J = NULL; assume(startingIdeal->m[k]==NULL); startingIdeal->m[k] = pt->m[0]; startingIdeal = gfanlib_kStd_wrapper(startingIdeal,startingRing); id_Delete(&J,startingRing); pt->m[0] = NULL; id_Delete(&pt,startingRing); return startingIdeal; } /*** * Initializes all relevant structures and information for the valued case, * i.e. computing a tropical variety over the rational numbers with p-adic valuation **/ tropicalStrategy::tropicalStrategy(ideal J, number q, ring s): originalRing(rCopy(s)), originalIdeal(id_Copy(J,s)), expectedDimension(dim(originalIdeal,originalRing)+1), linealitySpace(gfan::ZCone()), // to come, see below startingRing(NULL), // to come, see below startingIdeal(NULL), // to come, see below uniformizingParameter(NULL), // to come, see below shortcutRing(NULL), // to come, see below onlyLowerHalfSpace(true), weightAdjustingAlgorithm1(valued_adjustWeightForHomogeneity), weightAdjustingAlgorithm2(valued_adjustWeightUnderHomogeneity), extraReductionAlgorithm(ppreduceInitially) { /* assume that the ground field of the originalRing is Q */ assume(rField_is_Q(s)); /* replace Q with Z for the startingRing * and add an extra variable for tracking the uniformizing parameter */ startingRing = constructStartingRing(originalRing); /* map the uniformizing parameter into the new coefficient domain */ nMapFunc nMap = n_SetMap(originalRing->cf,startingRing->cf); uniformizingParameter = nMap(q,originalRing->cf,startingRing->cf); /* map the input ideal into the new polynomial ring */ startingIdeal = constructStartingIdeal(J,s,uniformizingParameter,startingRing); reduce(startingIdeal,startingRing); linealitySpace = homogeneitySpace(startingIdeal,startingRing); /* construct the shorcut ring */ shortcutRing = rCopy0(startingRing); nKillChar(shortcutRing->cf); shortcutRing->cf = nInitChar(n_Zp,(void*)(long)IsPrime(n_Int(uniformizingParameter,startingRing->cf))); rComplete(shortcutRing); rTest(shortcutRing); } tropicalStrategy::tropicalStrategy(const tropicalStrategy& currentStrategy): originalRing(rCopy(currentStrategy.getOriginalRing())), originalIdeal(id_Copy(currentStrategy.getOriginalIdeal(),currentStrategy.getOriginalRing())), expectedDimension(currentStrategy.getExpectedDimension()), linealitySpace(currentStrategy.getHomogeneitySpace()), startingRing(rCopy(currentStrategy.getStartingRing())), startingIdeal(id_Copy(currentStrategy.getStartingIdeal(),currentStrategy.getStartingRing())), uniformizingParameter(NULL), shortcutRing(NULL), onlyLowerHalfSpace(currentStrategy.restrictToLowerHalfSpace()), weightAdjustingAlgorithm1(currentStrategy.weightAdjustingAlgorithm1), weightAdjustingAlgorithm2(currentStrategy.weightAdjustingAlgorithm2), extraReductionAlgorithm(currentStrategy.extraReductionAlgorithm) { if (originalRing) rTest(originalRing); if (originalIdeal) id_Test(originalIdeal,originalRing); if (startingRing) rTest(startingRing); if (startingIdeal) id_Test(startingIdeal,startingRing); if (currentStrategy.getUniformizingParameter()) { uniformizingParameter = n_Copy(currentStrategy.getUniformizingParameter(),startingRing->cf); n_Test(uniformizingParameter,startingRing->cf); } if (currentStrategy.getShortcutRing()) { shortcutRing = rCopy(currentStrategy.getShortcutRing()); rTest(shortcutRing); } } tropicalStrategy::~tropicalStrategy() { if (originalRing) rTest(originalRing); if (originalIdeal) id_Test(originalIdeal,originalRing); if (startingRing) rTest(startingRing); if (startingIdeal) id_Test(startingIdeal,startingRing); if (uniformizingParameter) n_Test(uniformizingParameter,startingRing->cf); if (shortcutRing) rTest(shortcutRing); id_Delete(&originalIdeal,originalRing); rDelete(originalRing); if (startingIdeal) id_Delete(&startingIdeal,startingRing); if (uniformizingParameter) n_Delete(&uniformizingParameter,startingRing->cf); if (startingRing) rDelete(startingRing); if (shortcutRing) rDelete(shortcutRing); } tropicalStrategy& tropicalStrategy::operator=(const tropicalStrategy& currentStrategy) { originalRing = rCopy(currentStrategy.getOriginalRing()); originalIdeal = id_Copy(currentStrategy.getOriginalIdeal(),currentStrategy.getOriginalRing()); expectedDimension = currentStrategy.getExpectedDimension(); startingRing = rCopy(currentStrategy.getStartingRing()); startingIdeal = id_Copy(currentStrategy.getStartingIdeal(),currentStrategy.getStartingRing()); uniformizingParameter = n_Copy(currentStrategy.getUniformizingParameter(),startingRing->cf); shortcutRing = rCopy(currentStrategy.getShortcutRing()); onlyLowerHalfSpace = currentStrategy.restrictToLowerHalfSpace(); weightAdjustingAlgorithm1 = currentStrategy.weightAdjustingAlgorithm1; weightAdjustingAlgorithm2 = currentStrategy.weightAdjustingAlgorithm2; extraReductionAlgorithm = currentStrategy.extraReductionAlgorithm; if (originalRing) rTest(originalRing); if (originalIdeal) id_Test(originalIdeal,originalRing); if (startingRing) rTest(startingRing); if (startingIdeal) id_Test(startingIdeal,startingRing); if (uniformizingParameter) n_Test(uniformizingParameter,startingRing->cf); if (shortcutRing) rTest(shortcutRing); return *this; } void tropicalStrategy::putUniformizingBinomialInFront(ideal I, const ring r, const number q) const { poly p = p_One(r); p_SetCoeff(p,q,r); poly t = p_One(r); p_SetExp(t,1,1,r); p_Setm(t,r); poly pt = p_Add_q(p,p_Neg(t,r),r); int k = idSize(I); int l; for (l=0; lm[l],pt,r)) break; } p_Delete(&pt,r); if (l>1) { pt = I->m[l]; for (int i=l; i>0; i--) I->m[l] = I->m[l-1]; I->m[0] = pt; pt = NULL; } return; } bool tropicalStrategy::reduce(ideal I, const ring r) const { rTest(r); id_Test(I,r); nMapFunc identity = n_SetMap(startingRing->cf,r->cf); number p = identity(uniformizingParameter,startingRing->cf,r->cf); bool b = extraReductionAlgorithm(I,r,p); // putUniformizingBinomialInFront(I,r,p); n_Delete(&p,r->cf); return b; } void tropicalStrategy::pReduce(ideal I, const ring r) const { rTest(r); id_Test(I,r); if (isValuationTrivial()) return; nMapFunc identity = n_SetMap(startingRing->cf,r->cf); number p = identity(uniformizingParameter,startingRing->cf,r->cf); ::pReduce(I,p,r); n_Delete(&p,r->cf); return; } ring tropicalStrategy::getShortcutRingPrependingWeight(const ring r, const gfan::ZVector &v) const { ring rShortcut = rCopy0(r); // save old ordering int* order = rShortcut->order; int* block0 = rShortcut->block0; int* block1 = rShortcut->block1; int** wvhdl = rShortcut->wvhdl; // adjust weight and create new ordering gfan::ZVector w = adjustWeightForHomogeneity(v); int h = rBlocks(r); int n = rVar(r); rShortcut->order = (int*) omAlloc0((h+1)*sizeof(int)); rShortcut->block0 = (int*) omAlloc0((h+1)*sizeof(int)); rShortcut->block1 = (int*) omAlloc0((h+1)*sizeof(int)); rShortcut->wvhdl = (int**) omAlloc0((h+1)*sizeof(int*)); rShortcut->order[0] = ringorder_a; rShortcut->block0[0] = 1; rShortcut->block1[0] = n; bool overflow; rShortcut->wvhdl[0] = ZVectorToIntStar(w,overflow); for (int i=1; i<=h; i++) { rShortcut->order[i] = order[i-1]; rShortcut->block0[i] = block0[i-1]; rShortcut->block1[i] = block1[i-1]; rShortcut->wvhdl[i] = wvhdl[i-1]; } // if valuation non-trivial, change coefficient ring to residue field if (isValuationNonTrivial()) { nKillChar(rShortcut->cf); rShortcut->cf = nCopyCoeff(shortcutRing->cf); } rComplete(rShortcut); rTest(rShortcut); // delete old ordering omFree(order); omFree(block0); omFree(block1); omFree(wvhdl); return rShortcut; } std::pair tropicalStrategy::checkInitialIdealForMonomial(const ideal I, const ring r, const gfan::ZVector &w) const { // quick check whether I already contains an ideal int k = idSize(I); for (int i=0; im[i]; if (pNext(g)==NULL && (isValuationTrivial() || n_IsOne(p_GetCoeff(g,r),r->cf))) return std::pair(g,i); } ring rShortcut; ideal inIShortcut; if (w.size()>0) { // if needed, prepend extra weight for homogeneity // switch to residue field if valuation is non trivial rShortcut = getShortcutRingPrependingWeight(r,w); // compute the initial ideal and map it into the constructed ring // if switched to residue field, remove possibly 0 elements ideal inI = initial(I,r,w); inIShortcut = idInit(k); nMapFunc intoShortcut = n_SetMap(r->cf,rShortcut->cf); for (int i=0; im[i] = p_PermPoly(inI->m[i],NULL,r,rShortcut,intoShortcut,NULL,0); if (isValuationNonTrivial()) idSkipZeroes(inIShortcut); id_Delete(&inI,r); } else { rShortcut = r; inIShortcut = I; } // check initial ideal for monomial and // if it exsists, return a copy of the monomial in the input ring poly p = checkForMonomialViaSuddenSaturation(inIShortcut,rShortcut); poly monomial = NULL; if (p!=NULL) { monomial=p_One(r); for (int i=1; i<=rVar(r); i++) p_SetExp(monomial,i,p_GetExp(p,i,rShortcut),r); p_Setm(monomial,r); p_Delete(&p,rShortcut); } if (w.size()>0) { // if needed, cleanup id_Delete(&inIShortcut,rShortcut); rDelete(rShortcut); } return std::pair(monomial,-1); } ring tropicalStrategy::copyAndChangeCoefficientRing(const ring r) const { ring rShortcut = rCopy0(r); nKillChar(rShortcut->cf); rShortcut->cf = nCopyCoeff(shortcutRing->cf); rComplete(rShortcut); rTest(rShortcut); return rShortcut; } ideal tropicalStrategy::computeWitness(const ideal inJ, const ideal inI, const ideal I, const ring r) const { // if the valuation is trivial and the ring and ideal have not been extended, // then it is sufficient to return the difference between the elements of inJ // and their normal forms with respect to I and r if (isValuationTrivial()) return witness(inJ,I,r); // if the valuation is non-trivial and the ring and ideal have been extended, // then we can make a shortcut through the residue field else { assume(idSize(inI)==idSize(I)); int uni = findPositionOfUniformizingBinomial(I,r); assume(uni>=0); /** * change ground ring into finite field * and map the data into it */ ring rShortcut = copyAndChangeCoefficientRing(r); int k = idSize(inJ); int l = idSize(I); ideal inJShortcut = idInit(k); ideal inIShortcut = idInit(l); nMapFunc takingResidues = n_SetMap(r->cf,rShortcut->cf); for (int i=0; im[i] = p_PermPoly(inJ->m[i],NULL,r,rShortcut,takingResidues,NULL,0); for (int j=0; jm[j] = p_PermPoly(inI->m[j],NULL,r,rShortcut,takingResidues,NULL,0); id_Test(inJShortcut,rShortcut); id_Test(inIShortcut,rShortcut); /** * Compute a division with remainder over the finite field * and map the result back to r */ matrix QShortcut = divisionDiscardingRemainder(inJShortcut,inIShortcut,rShortcut); matrix Q = mpNew(l,k); nMapFunc takingRepresentatives = n_SetMap(rShortcut->cf,r->cf); for (int ij=k*l-1; ij>=0; ij--) Q->m[ij] = p_PermPoly(QShortcut->m[ij],NULL,rShortcut,r,takingRepresentatives,NULL,0); nMapFunc identity = n_SetMap(startingRing->cf,r->cf); number p = identity(uniformizingParameter,startingRing->cf,r->cf); /** * Compute the normal forms */ ideal J = idInit(k); for (int j=0; jm[j],r); for (int i=0; im[i],r); q0 = p_Add_q(q0,p_Neg(p_Mult_q(qij,inIi,r),r),r); } q0 = p_Div_nn(q0,p,r); poly q0g0 = p_Mult_q(q0,p_Copy(I->m[uni],r),r); // q0 = NULL; poly qigi = NULL; for (int i=0; im[i],r); poly Ii = p_Copy(I->m[i],r); qigi = p_Add_q(qigi,p_Mult_q(qij,Ii,r),r); } J->m[j] = p_Add_q(q0g0,qigi,r); } id_Delete(&inIShortcut,rShortcut); id_Delete(&inJShortcut,rShortcut); mp_Delete(&QShortcut,rShortcut); rDelete(rShortcut); mp_Delete(&Q,r); n_Delete(&p,r->cf); return J; } } ideal tropicalStrategy::computeStdOfInitialIdeal(const ideal inI, const ring r) const { // if valuation trivial, then compute std as usual if (isValuationTrivial()) return gfanlib_kStd_wrapper(inI,r); // if valuation non-trivial, then uniformizing parameter is in ideal // so switch to residue field first and compute standard basis over the residue field ring rShortcut = copyAndChangeCoefficientRing(r); nMapFunc takingResidues = n_SetMap(r->cf,rShortcut->cf); int k = idSize(inI); ideal inIShortcut = idInit(k); for (int i=0; im[i] = p_PermPoly(inI->m[i],NULL,r,rShortcut,takingResidues,NULL,0); ideal inJShortcut = gfanlib_kStd_wrapper(inIShortcut,rShortcut); // and lift the result back to the ring with valuation nMapFunc takingRepresentatives = n_SetMap(rShortcut->cf,r->cf); k = idSize(inJShortcut); ideal inJ = idInit(k+1); inJ->m[0] = p_One(r); nMapFunc identity = n_SetMap(startingRing->cf,r->cf); p_SetCoeff(inJ->m[0],identity(uniformizingParameter,startingRing->cf,r->cf),r); for (int i=0; im[i+1] = p_PermPoly(inJShortcut->m[i],NULL,rShortcut,r,takingRepresentatives,NULL,0); id_Delete(&inJShortcut,rShortcut); id_Delete(&inIShortcut,rShortcut); rDelete(rShortcut); return inJ; } ideal tropicalStrategy::computeLift(const ideal inJs, const ring s, const ideal inIr, const ideal Ir, const ring r) const { int k = idSize(inJs); ideal inJr = idInit(k); nMapFunc identitysr = n_SetMap(s->cf,r->cf); for (int i=0; im[i] = p_PermPoly(inJs->m[i],NULL,s,r,identitysr,NULL,0); ideal Jr = computeWitness(inJr,inIr,Ir,r); nMapFunc identityrs = n_SetMap(r->cf,s->cf); ideal Js = idInit(k); for (int i=0; im[i] = p_PermPoly(Jr->m[i],NULL,r,s,identityrs,NULL,0); return Js; } static void deleteOrdering(ring r) { if (r->order != NULL) { int i=rBlocks(r); assume(r->block0 != NULL && r->block1 != NULL && r->wvhdl != NULL); /* delete order */ omFreeSize((ADDRESS)r->order,i*sizeof(int)); omFreeSize((ADDRESS)r->block0,i*sizeof(int)); omFreeSize((ADDRESS)r->block1,i*sizeof(int)); /* delete weights */ for (int j=0; jwvhdl[j]!=NULL) omFree(r->wvhdl[j]); omFreeSize((ADDRESS)r->wvhdl,i*sizeof(int *)); } else assume(r->block0 == NULL && r->block1 == NULL && r->wvhdl == NULL); return; } ring tropicalStrategy::copyAndChangeOrderingWP(const ring r, const gfan::ZVector &w, const gfan::ZVector &v) const { // copy shortcutRing and change to desired ordering bool ok; ring s = rCopy0(r); int n = rVar(s); deleteOrdering(s); gfan::ZVector wAdjusted = adjustWeightForHomogeneity(w); gfan::ZVector vAdjusted = adjustWeightUnderHomogeneity(v,wAdjusted); s->order = (int*) omAlloc0(5*sizeof(int)); s->block0 = (int*) omAlloc0(5*sizeof(int)); s->block1 = (int*) omAlloc0(5*sizeof(int)); s->wvhdl = (int**) omAlloc0(5*sizeof(int**)); s->order[0] = ringorder_a; s->block0[0] = 1; s->block1[0] = n; s->wvhdl[0] = ZVectorToIntStar(wAdjusted,ok); s->order[1] = ringorder_a; s->block0[1] = 1; s->block1[1] = n; s->wvhdl[1] = ZVectorToIntStar(vAdjusted,ok); s->order[2] = ringorder_lp; s->block0[2] = 1; s->block1[2] = n; s->order[3] = ringorder_C; rComplete(s); rTest(s); return s; } ring tropicalStrategy::copyAndChangeOrderingLS(const ring r, const gfan::ZVector &w, const gfan::ZVector &v) const { // copy shortcutRing and change to desired ordering bool ok; ring s = rCopy0(r); int n = rVar(s); deleteOrdering(s); s->order = (int*) omAlloc0(5*sizeof(int)); s->block0 = (int*) omAlloc0(5*sizeof(int)); s->block1 = (int*) omAlloc0(5*sizeof(int)); s->wvhdl = (int**) omAlloc0(5*sizeof(int**)); s->order[0] = ringorder_a; s->block0[0] = 1; s->block1[0] = n; s->wvhdl[0] = ZVectorToIntStar(w,ok); s->order[1] = ringorder_a; s->block0[1] = 1; s->block1[1] = n; s->wvhdl[1] = ZVectorToIntStar(v,ok); s->order[2] = ringorder_lp; s->block0[2] = 1; s->block1[2] = n; s->order[3] = ringorder_C; rComplete(s); rTest(s); return s; } std::pair tropicalStrategy::computeFlip(const ideal Ir, const ring r, const gfan::ZVector &interiorPoint, const gfan::ZVector &facetNormal) const { assume(isValuationTrivial() || interiorPoint[0].sign()<0); assume(checkForUniformizingBinomial(Ir,r)); // get a generating system of the initial ideal // and compute a standard basis with respect to adjacent ordering ideal inIr = initial(Ir,r,interiorPoint); ring sAdjusted = copyAndChangeOrderingWP(r,interiorPoint,facetNormal); nMapFunc identity = n_SetMap(r->cf,sAdjusted->cf); int k = idSize(Ir); ideal inIsAdjusted = idInit(k); for (int i=0; im[i] = p_PermPoly(inIr->m[i],NULL,r,sAdjusted,identity,NULL,0); ideal inJsAdjusted = computeStdOfInitialIdeal(inIsAdjusted,sAdjusted); // find witnesses of the new standard basis elements of the initial ideal // with the help of the old standard basis of the ideal k = idSize(inJsAdjusted); ideal inJr = idInit(k); identity = n_SetMap(sAdjusted->cf,r->cf); for (int i=0; im[i] = p_PermPoly(inJsAdjusted->m[i],NULL,sAdjusted,r,identity,NULL,0); ideal Jr = computeWitness(inJr,inIr,Ir,r); ring s = copyAndChangeOrderingLS(r,interiorPoint,facetNormal); identity = n_SetMap(r->cf,s->cf); ideal Js = idInit(k); for (int i=0; im[i] = p_PermPoly(Jr->m[i],NULL,r,s,identity,NULL,0); // this->reduce(Jr,r); // cleanup id_Delete(&inIsAdjusted,sAdjusted); id_Delete(&inJsAdjusted,sAdjusted); rDelete(sAdjusted); id_Delete(&inIr,r); id_Delete(&Jr,r); id_Delete(&inJr,r); assume(isValuationTrivial() || isOrderingLocalInT(s)); return std::make_pair(Js,s); } bool tropicalStrategy::checkForUniformizingBinomial(const ideal I, const ring r) const { // if the valuation is trivial, // then there is no special condition the first generator has to fullfill if (isValuationTrivial()) return true; // if the valuation is non-trivial then checks if the first generator is p-t nMapFunc identity = n_SetMap(startingRing->cf,r->cf); poly p = p_One(r); p_SetCoeff(p,identity(uniformizingParameter,startingRing->cf,r->cf),r); poly t = p_One(r); p_SetExp(t,1,1,r); p_Setm(t,r); poly pt = p_Add_q(p,p_Neg(t,r),r); for (int i=0; im[i],pt,r)) { p_Delete(&pt,r); return true; } } p_Delete(&pt,r); return false; } int tropicalStrategy::findPositionOfUniformizingBinomial(const ideal I, const ring r) const { assume(isValuationNonTrivial()); // if the valuation is non-trivial then checks if the first generator is p-t nMapFunc identity = n_SetMap(startingRing->cf,r->cf); poly p = p_One(r); p_SetCoeff(p,identity(uniformizingParameter,startingRing->cf,r->cf),r); poly t = p_One(r); p_SetExp(t,1,1,r); p_Setm(t,r); poly pt = p_Add_q(p,p_Neg(t,r),r); for (int i=0; im[i],pt,r)) { p_Delete(&pt,r); return i; } } p_Delete(&pt,r); return -1; } bool tropicalStrategy::checkForUniformizingParameter(const ideal inI, const ring r) const { // if the valuation is trivial, // then there is no special condition the first generator has to fullfill if (isValuationTrivial()) return true; // if the valuation is non-trivial then checks if the first generator is p if (inI->m[0]==NULL) return false; nMapFunc identity = n_SetMap(startingRing->cf,r->cf); poly p = p_One(r); p_SetCoeff(p,identity(uniformizingParameter,startingRing->cf,r->cf),r); for (int i=0; im[i],p,r)) { p_Delete(&p,r); return true; } } p_Delete(&p,r); return false; } #ifndef NDEBUG tropicalStrategy::tropicalStrategy(): originalRing(NULL), originalIdeal(NULL), expectedDimension(NULL), linealitySpace(gfan::ZCone()), startingRing(NULL), startingIdeal(NULL), uniformizingParameter(NULL), shortcutRing(NULL), onlyLowerHalfSpace(false) { weightAdjustingAlgorithm1=NULL; weightAdjustingAlgorithm2=NULL; extraReductionAlgorithm=NULL; } tropicalStrategy tropicalStrategy::debugStrategy(const ideal startIdeal, number unifParameter, ring startRing) { tropicalStrategy debug; debug.originalRing = rCopy(startRing); debug.originalIdeal = id_Copy(startIdeal,startRing); debug.startingRing = rCopy(startRing); debug.startingIdeal = id_Copy(startIdeal,startRing); debug.uniformizingParameter = n_Copy(unifParameter,startRing->cf); debug.shortcutRing = rCopy0(startRing); nKillChar(debug.shortcutRing->cf); debug.shortcutRing->cf = nInitChar(n_Zp,(void*)(long)IsPrime(n_Int(unifParameter,startRing->cf))); rComplete(debug.shortcutRing); rTest(debug.shortcutRing); debug.onlyLowerHalfSpace = true; debug.weightAdjustingAlgorithm1 = valued_adjustWeightForHomogeneity; debug.weightAdjustingAlgorithm2 = valued_adjustWeightUnderHomogeneity; debug.extraReductionAlgorithm = ppreduceInitially; return debug; } BOOLEAN computeWitnessDebug(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { leftv v = u->next; if ((v!=NULL) && (v->Typ()==IDEAL_CMD)) { leftv w = v->next; if ((w!=NULL) && (w->Typ()==IDEAL_CMD)) { leftv x = w->next; if ((x!=NULL) && (x->Typ()==NUMBER_CMD)) { omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); ideal inJ = (ideal) u->CopyD(); ideal inI = (ideal) v->CopyD(); ideal I = (ideal) w->CopyD(); number p = (number) x->CopyD(); tropicalStrategy debug = tropicalStrategy::debugStrategy(I,p,currRing); ideal J = debug.computeWitness(inJ,inI,I,currRing); id_Delete(&inJ,currRing); id_Delete(&inI,currRing); id_Delete(&I,currRing); n_Delete(&p,currRing->cf); res->rtyp = IDEAL_CMD; res->data = (char*) J; return FALSE; } } } } return TRUE; } BOOLEAN computeFlipDebug(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { leftv v = u->next; if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { leftv w = v->next; if ((w!=NULL) && (w->Typ()==BIGINTMAT_CMD)) { leftv x = w->next; if ((x!=NULL) && (x->Typ()==BIGINTMAT_CMD)) { omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); ideal I = (ideal) u->CopyD(); number p = (number) v->CopyD(); bigintmat* interiorPoint0 = (bigintmat*) w->CopyD(); bigintmat* facetNormal0 = (bigintmat*) x->CopyD(); tropicalStrategy debug = tropicalStrategy::debugStrategy(I,p,currRing); gfan::ZVector* interiorPoint = bigintmatToZVector(interiorPoint0); gfan::ZVector* facetNormal = bigintmatToZVector(facetNormal0); std::pair Js = debug.computeFlip(I,currRing,*interiorPoint,*facetNormal); ideal J = Js.first; ring s = Js.second; id_Delete(&J,s); rDelete(s); id_Delete(&I,currRing); n_Delete(&p,currRing->cf); delete interiorPoint0; delete facetNormal0; delete interiorPoint; delete facetNormal; res->rtyp = NONE; res->data = NULL; return FALSE; } } } } WerrorS("computeFlipDebug: unexpected parameters"); return TRUE; } #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalStrategy.h000066400000000000000000000235521266270727000252050ustar00rootroot00000000000000#ifndef GFANLIB_TROPICALSTRATEGY_H #define GFANLIB_TROPICALSTRATEGY_H #include #include #include #include // for idSize #include #include #include #include #include #include #ifndef NDEBUG #include // for isPrime(int i) #include #include #endif /** \file * implementation of the class tropicalStrategy * * tropicalStrategy is a class that contains information relevant for * computing tropical varieties that is dependent on the valuation of the coefficient field. * It represents the mutable part of an overall framework that is capable of * computing tropical varieties both over coefficient fields without valuation and * with valuation (currently: only p-adic valuation over rational numbers) */ typedef gfan::ZVector (*wAdjAlg1)(gfan::ZVector); typedef gfan::ZVector (*wAdjAlg2)(gfan::ZVector,gfan::ZVector); typedef bool (*redAlg)(ideal,ring,number); class tropicalStrategy { private: /** * polynomial ring over a field with valuation */ ring originalRing; /** * input ideal, assumed to be a homogeneous prime ideal */ ideal originalIdeal; /** * the expected Dimension of the polyhedral output, * i.e. the dimension of the ideal if valuation trivial * or the dimension of the ideal plus one if valuation non-trivial * (as the output is supposed to be intersected with a hyperplane) */ int expectedDimension; /** * the homogeneity space of the Grobner fan */ gfan::ZCone linealitySpace; /** * polynomial ring over the valuation ring extended by one extra variable t */ ring startingRing; /** * preimage of the input ideal under the map that sends t to the uniformizing parameter */ ideal startingIdeal; /** * uniformizing parameter in the valuation ring */ number uniformizingParameter; /** * polynomial ring over the residue field */ ring shortcutRing; /** * true if valuation non-trivial, false otherwise */ bool onlyLowerHalfSpace; /** * A function such that: * Given weight w, returns a strictly positive weight u such that an ideal satisfying * the valuation-sepcific homogeneity conditions is weighted homogeneous with respect to w * if and only if it is homogeneous with respect to u */ gfan::ZVector (*weightAdjustingAlgorithm1) (const gfan::ZVector &w); /** * A function such that: * Given strictly positive weight w and weight v, * returns a strictly positive weight u such that on an ideal that is weighted homogeneous * with respect to w the weights u and v coincide */ gfan::ZVector (*weightAdjustingAlgorithm2) (const gfan::ZVector &v, const gfan::ZVector &w); /** * A function that reduces the generators of an ideal I so that * the inequalities and equations of the Groebner cone can be read off. */ bool (*extraReductionAlgorithm) (ideal I, ring r, number p); ring copyAndChangeCoefficientRing(const ring r) const; ring copyAndChangeOrderingWP(const ring r, const gfan::ZVector &w, const gfan::ZVector &v) const; ring copyAndChangeOrderingLS(const ring r, const gfan::ZVector &w, const gfan::ZVector &v) const; /** * if valuation non-trivial, checks whether the generating system contains p-t * otherwise returns true */ bool checkForUniformizingBinomial(const ideal I, const ring r) const; /** * if valuation non-trivial, checks whether the genearting system contains p * otherwise returns true */ bool checkForUniformizingParameter(const ideal inI, const ring r) const; int findPositionOfUniformizingBinomial(const ideal I, const ring r) const; void putUniformizingBinomialInFront(ideal I, const ring r, const number q) const; public: /** * Constructor for the trivial valuation case */ tropicalStrategy(const ideal I, const ring r, const bool completelyHomogeneous=true, const bool completeSpace=true); /** * Constructor for the non-trivial valuation case * p is the uniformizing parameter of the valuation */ tropicalStrategy(const ideal J, const number p, const ring s); /** * copy constructor */ tropicalStrategy(const tropicalStrategy& currentStrategy); #ifndef NDEBUG tropicalStrategy(); static tropicalStrategy debugStrategy(const ideal startIdeal, number unifParameter, ring startRing); #endif /** * destructor */ ~tropicalStrategy(); /** * assignment operator **/ tropicalStrategy& operator=(const tropicalStrategy& currentStrategy); bool isValuationTrivial() const { bool b = (uniformizingParameter==NULL); return b; } bool isValuationNonTrivial() const { bool b = (uniformizingParameter!=NULL); return b; } /** * returns the polynomial ring over the field with valuation */ ring getOriginalRing() const { rTest(originalRing); return originalRing; } /** * returns the input ideal over the field with valuation */ ideal getOriginalIdeal() const { if (originalIdeal) id_Test(originalIdeal,originalRing); return originalIdeal; } /** * returns the polynomial ring over the valuation ring */ ring getStartingRing() const { if (startingRing) rTest(startingRing); return startingRing; } /** * returns the input ideal */ ideal getStartingIdeal() const { if (startingIdeal) id_Test(startingIdeal,startingRing); return startingIdeal; } int getExpectedAmbientDimension() const { return rVar(startingRing); } /** * returns the expected Dimension of the polyhedral output */ int getExpectedDimension() const { return expectedDimension; } /** * returns the uniformizing parameter in the valuation ring */ number getUniformizingParameter() const { if (uniformizingParameter) n_Test(uniformizingParameter,startingRing->cf); return uniformizingParameter; } ring getShortcutRing() const { if (shortcutRing) rTest(shortcutRing); return shortcutRing; } /** * returns the homogeneity space of the preimage ideal */ gfan::ZCone getHomogeneitySpace() const { return linealitySpace; } /** * returns true, if v is contained in the homogeneity space; false otherwise */ bool homogeneitySpaceContains(const gfan::ZVector &v) const { return linealitySpace.contains(v); } /** * returns true, if valuation non-trivial, false otherwise */ bool restrictToLowerHalfSpace() const { return onlyLowerHalfSpace; } /** * Given weight w, returns a strictly positive weight u such that an ideal satisfying * the valuation-sepcific homogeneity conditions is weighted homogeneous with respect to w * if and only if it is homogeneous with respect to u */ gfan::ZVector adjustWeightForHomogeneity(gfan::ZVector w) const { return this->weightAdjustingAlgorithm1(w); } /** * Given strictly positive weight w and weight v, * returns a strictly positive weight u such that on an ideal that is weighted homogeneous * with respect to w the weights u and v coincide */ gfan::ZVector adjustWeightUnderHomogeneity(gfan::ZVector v, gfan::ZVector w) const { return this->weightAdjustingAlgorithm2(v,w); } gfan::ZVector negateWeight(const gfan::ZVector &w) const { gfan::ZVector wNeg(w.size()); if (this->isValuationNonTrivial()) { wNeg[0]=w[0]; for (unsigned i=1; i checkInitialIdealForMonomial(const ideal I, const ring r, const gfan::ZVector &w=0) const; /** * given generators of the initial ideal, computes its standard basis */ ideal computeStdOfInitialIdeal(const ideal inI, const ring r) const; /** * suppose w a weight in maximal groebner cone of > * suppose I (initially) reduced standard basis w.r.t. > and inI initial forms of its elements w.r.t. w * suppose inJ elements of initial ideal that are homogeneous w.r.t w * returns J elements of ideal whose initial form w.r.t. w are inI * in particular, if w lies also inthe maximal groebner cone of another ordering >' * and inJ is a standard basis of the initial ideal w.r.t. >' * then the returned J will be a standard baiss of the ideal w.r.t. >' */ ideal computeWitness(const ideal inJ, const ideal inI, const ideal I, const ring r) const; ideal computeLift(const ideal inJs, const ring s, const ideal inIr, const ideal Ir, const ring r) const; /** * given an interior point of a groebner cone * computes the groebner cone adjacent to it */ std::pair computeFlip(const ideal Ir, const ring r, const gfan::ZVector &interiorPoint, const gfan::ZVector &facetNormal) const; }; #ifndef NDEBUG BOOLEAN computeWitnessDebug(leftv res, leftv args); BOOLEAN computeFlipDebug(leftv res, leftv args); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalTraversal.cc000066400000000000000000000134041266270727000254770ustar00rootroot00000000000000#include #include #include std::vector checkNecessaryTropicalFlips(const groebnerCones &tropicalVariety, const groebnerCones &workingList, const gfan::ZVector &interiorPoint, const gfan::ZMatrix &normalVectors) { int k = normalVectors.getHeight(); std::vector needToFlip(k,true); int n = normalVectors.getWidth(); gfan::ZMatrix testVectors(k,n); gfan::ZVector bigInteriorPoint = 1000*interiorPoint; for (int i=0; icontains(interiorPoint)) { for (int i=0; icontains(testVectors[i])) needToFlip[i] = false; } } } for (groebnerCones::iterator sigma = workingList.begin(); sigma!=workingList.end(); sigma++) { if (sigma->contains(interiorPoint)) { for (int i=0; icontains(testVectors[i])) needToFlip[i] = false; } } } return needToFlip; } groebnerCones tropicalTraversalMinimizingFlips(const groebnerCone startingCone) { groebnerCones tropicalVariety; if (startingCone.isTrivial()) { return tropicalVariety; } groebnerCones workingList; workingList.insert(startingCone); const tropicalStrategy* currentStrategy=startingCone.getTropicalStrategy(); std::set finishedInteriorPoints; while(!workingList.empty()) { /** * Pick an element the working list and compute interior points on its facets */ groebnerCone sigma=*(workingList.begin()); gfan::ZMatrix interiorPoints = interiorPointsOfFacets(sigma.getPolyhedralCone(),finishedInteriorPoints); for (int i=0; irestrictToLowerHalfSpace() && interiorPoint[0].sign()==0)) { ideal inI = initial(sigma.getPolynomialIdeal(),sigma.getPolynomialRing(),interiorPoint); gfan::ZMatrix normalVectors = raysOfTropicalStar(inI, sigma.getPolynomialRing(), interiorPoint, sigma.getTropicalStrategy()); id_Delete(&inI,sigma.getPolynomialRing()); std::vector needToFlip = checkNecessaryTropicalFlips(tropicalVariety,workingList,interiorPoint,normalVectors); for (int j=0; j 0) Print("cones finished: %lu cones in working list: %lu\n", (unsigned long)tropicalVariety.size(), (unsigned long)workingList.size()); } return tropicalVariety; } std::vector checkNecessaryGroebnerFlips(const groebnerCones &groebnerFan, const groebnerCones &workingList, const gfan::ZMatrix &interiorPoints) { int k = interiorPoints.getHeight(); std::vector needToFlip(k,true); for (groebnerCones::iterator sigma = groebnerFan.begin(); sigma!=groebnerFan.end(); sigma++) { for (int i=0; icontains(interiorPoints[i])) needToFlip[i] = false; } } for (groebnerCones::iterator sigma = workingList.begin(); sigma!=workingList.end(); sigma++) { for (int i=0; icontains(interiorPoints[i])) needToFlip[i] = false; } } return needToFlip; } groebnerCones groebnerTraversal(const groebnerCone startingCone) { const tropicalStrategy* currentStrategy = startingCone.getTropicalStrategy(); groebnerCones groebnerFan; groebnerCones workingList; workingList.insert(startingCone); std::set finishedInteriorPoints; bool onlyLowerHalfSpace = !currentStrategy->isValuationTrivial(); while(!workingList.empty()) { /** * Pick a maximal Groebner cone from the working list * and compute interior points on its facets as well as outer facet normals */ groebnerCone sigma=*(workingList.begin()); workingList.erase(workingList.begin()); std::pair interiorPointsAndOuterFacetNormals = interiorPointsAndNormalsOfFacets(sigma.getPolyhedralCone(), finishedInteriorPoints, onlyLowerHalfSpace); gfan::ZMatrix interiorPoints = interiorPointsAndOuterFacetNormals.first; gfan::ZMatrix outerFacetNormals = interiorPointsAndOuterFacetNormals.second; std::vector needToFlip = checkNecessaryGroebnerFlips(groebnerFan,workingList, interiorPoints); for (int i=0; i 0) Print("cones finished: %lu cones in working list: %lu\n", (unsigned long)groebnerFan.size(), (unsigned long)workingList.size()); } return groebnerFan; } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalTraversal.h000066400000000000000000000004631266270727000253420ustar00rootroot00000000000000#ifndef TROPICAL_TRAVERSAL_H #define TROPICAL_TRAVERSAL_H #include groebnerCones tropicalTraversalMinimizingFlips(const groebnerCone startingCone); groebnerCones tropicalTraversal(const groebnerCone startingCone); groebnerCones groebnerTraversal(const groebnerCone startingCone); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalVariety.cc000066400000000000000000000120051266270727000251530ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include BITSET bitsetSave1, bitsetSave2; /*** * sets option(redSB) **/ static void setOptionRedSB() { SI_SAVE_OPT(bitsetSave1,bitsetSave2); si_opt_1|=Sy_bit(OPT_REDSB); } /*** * sets option(noredSB); **/ static void undoSetOptionRedSB() { SI_RESTORE_OPT(bitsetSave1,bitsetSave2); } static gfan::ZFan* toZFan(std::set maxCones, int d) { gfan::ZFan* zf = new gfan::ZFan(d); for (std::set::iterator sigma = maxCones.begin(); sigma!=maxCones.end(); sigma++) zf->insert(*sigma); return zf; } BOOLEAN tropicalVariety(leftv res, leftv args) { leftv u = args; if ((u!=NULL) && (u->Typ()==POLY_CMD)) { poly g = (poly) u->Data(); leftv v = u->next; if (v==NULL) { try { ideal I = idInit(1); I->m[0] = g; tropicalStrategy currentStrategy(I,currRing); std::set maxCones = tropicalVariety(g,currRing,¤tStrategy); res->rtyp = fanID; res->data = (char*) toZFan(maxCones,currentStrategy.getExpectedAmbientDimension()); I->m[0] = NULL; id_Delete(&I,currRing); return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { try { ideal I = idInit(1); I->m[0] = g; number p = (number) v->Data(); tropicalStrategy currentStrategy(I,p,currRing); ideal startingIdeal = currentStrategy.getStartingIdeal(); ring startingRing = currentStrategy.getStartingRing(); poly gStart = startingIdeal->m[0]; std::set maxCones = tropicalVariety(gStart,startingRing,¤tStrategy); res->rtyp = fanID; res->data = (char*) toZFan(maxCones,currentStrategy.getExpectedAmbientDimension()); I->m[0] = NULL; id_Delete(&I,currRing); return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } } if ((u!=NULL) && (u->Typ()==IDEAL_CMD)) { ideal I = (ideal) u->Data(); leftv v = u->next; if (idSize(I)==1) { poly g = I->m[0]; if (v==NULL) { try { tropicalStrategy currentStrategy(I,currRing); std::set maxCones = tropicalVariety(g,currRing,¤tStrategy); res->rtyp = fanID; res->data = (char*) toZFan(maxCones,currentStrategy.getExpectedAmbientDimension()); return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { try { number p = (number) v->Data(); tropicalStrategy currentStrategy(I,p,currRing); ideal startingIdeal = currentStrategy.getStartingIdeal(); ring startingRing = currentStrategy.getStartingRing(); poly gStart = startingIdeal->m[0]; std::set maxCones = tropicalVariety(gStart,startingRing,¤tStrategy); res->rtyp = fanID; res->data = (char*) toZFan(maxCones,currentStrategy.getExpectedAmbientDimension()); return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } } if (v==NULL) { try { setOptionRedSB(); ideal stdI; if (!hasFlag(u,FLAG_STD)) stdI = gfanlib_kStd_wrapper(I,currRing); else stdI = id_Copy(I,currRing); tropicalStrategy currentStrategy(stdI,currRing); gfan::ZFan* tropI = tropicalVariety(currentStrategy); res->rtyp = fanID; res->data = (char*) tropI; undoSetOptionRedSB(); id_Delete(&stdI,currRing); return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } if ((v!=NULL) && (v->Typ()==NUMBER_CMD)) { try { number p = (number) v->Data(); ideal stdI; if (!hasFlag(u,FLAG_STD)) stdI = gfanlib_kStd_wrapper(I,currRing); else stdI = id_Copy(I,currRing); tropicalStrategy currentStrategy(stdI,p,currRing); gfan::ZFan* tropI = tropicalVariety(currentStrategy); res->rtyp = fanID; res->data = (char*) tropI; id_Delete(&stdI,currRing); return FALSE; } catch (const std::exception& ex) { Werror("ERROR: %s",ex.what()); return TRUE; } } return FALSE; } WerrorS("tropicalVariety: unexpected parameters"); return TRUE; } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalVariety.h000066400000000000000000000002051266270727000250140ustar00rootroot00000000000000#ifndef CALLGFANLIB_TROPICALVARIETY_H #define CALLGFANLIB_TROPICALVARIETY_H BOOLEAN tropicalVariety(leftv res, leftv args); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalVarietyOfIdeals.cc000066400000000000000000000005301266270727000265620ustar00rootroot00000000000000#include #include #include gfan::ZFan* tropicalVariety(const tropicalStrategy currentStrategy) { groebnerCone startingCone = tropicalStartingCone(currentStrategy); groebnerCones tropicalVariety = tropicalTraversalMinimizingFlips(startingCone); return toFanStar(tropicalVariety); } singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalVarietyOfIdeals.h000066400000000000000000000003451266270727000264300ustar00rootroot00000000000000#ifndef CALLGfANLIB_TROPICALVARIETYOFIDEALS #define CALLGfANLIB_TROPICALVARIETYOFIDEALS #include #include gfan::ZFan* tropicalVariety(const tropicalStrategy currentStrategy); #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalVarietyOfPolynomials.cc000066400000000000000000000077031266270727000277000ustar00rootroot00000000000000#include #include #include #include #include #include #ifndef NDEBUG #include // for leftv #include // for fanID #endif /*** * Returns the tropical variety of a polynomial g in ring r. * Depending on the current case, it will compute either the whole tropical variety * or just the part in the first lower half-space. * An empty set means that the tropical Variety is the whole space, * i.e. g is either 0 or a non-zero monomial. **/ std::set tropicalVariety(const poly g, const ring r, const tropicalStrategy* currentCase) { int n = rVar(r); std::set tropVar; if (g && g->next) { int* expv = (int*) omAlloc((n+1)*sizeof(int)); gfan::ZMatrix exponents = gfan::ZMatrix(0,n); for (poly s=g; s; pIter(s)) { p_GetExpV(s,expv,r); gfan::ZVector zv = intStar2ZVector(n,expv); exponents.appendRow(intStar2ZVector(n,expv)); } omFreeSize(expv,(n+1)*sizeof(int)); int l = exponents.getHeight(); gfan::ZVector lowerHalfSpaceCondition = gfan::ZVector(n); lowerHalfSpaceCondition[0] = -1; for (int i=0; irestrictToLowerHalfSpace()) inequalities.appendRow(lowerHalfSpaceCondition); for (int k=0; k=n-1) { zc.canonicalize(); tropVar.insert(zc); } } } } return tropVar; } ZConesSortedByDimension tropicalVarietySortedByDimension(const poly g, const ring r, const tropicalStrategy* currentCase) { int n = rVar(r); ZConesSortedByDimension tropVar; if (g && g->next) { int* expv = (int*) omAlloc((n+1)*sizeof(int)); gfan::ZMatrix exponents = gfan::ZMatrix(0,n); for (poly s=g; s; pIter(s)) { p_GetExpV(s,expv,r); gfan::ZVector zv = intStar2ZVector(n,expv); exponents.appendRow(intStar2ZVector(n,expv)); } omFreeSize(expv,(n+1)*sizeof(int)); int l = exponents.getHeight(); gfan::ZVector lowerHalfSpaceCondition = gfan::ZVector(n); lowerHalfSpaceCondition[0] = -1; for (int i=0; irestrictToLowerHalfSpace()) inequalities.appendRow(lowerHalfSpaceCondition); for (int k=0; k=n-1) { zc.canonicalize(); tropVar.insert(zc); } } } } return tropVar; } // #ifndef NDEBUG // BOOLEAN tropicalVariety00(leftv res, leftv args) // { // leftv u = args; // poly g = (poly) u->CopyD(); // omUpdateInfo(); // Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); // std::set C = fullTropicalVarietyOfPolynomial(g,currRing); // p_Delete(&g,currRing); // res->rtyp = fanID; // res->data = (char*) toFanStar(C); // return FALSE; // } // BOOLEAN tropicalVariety01(leftv res, leftv args) // { // leftv u = args; // poly g = (poly) u->CopyD(); // omUpdateInfo(); // Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); // std::set C = lowerTropicalVarietyOfPolynomial(g,currRing); // p_Delete(&g,currRing); // res->rtyp = fanID; // res->data = (char*) toFanStar(C); // return FALSE; // } // #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/tropicalVarietyOfPolynomials.h000066400000000000000000000017621266270727000275410ustar00rootroot00000000000000#ifndef GFANLIB_TROPICALVARIETYOFPOLYNOMIALS_H #define GFANLIB_TROPICALVARIETYOFPOLYNOMIALS_H #include #include #include #include #ifndef NDEBUG #include // for leftv #include // for fanID #endif struct ZConeCompareDimensionFirst { bool operator() (const gfan::ZCone &zc, const gfan::ZCone &zd) const { int n = zc.dimension(); int m = zd.dimension(); if (n==m) return zcm; } }; typedef std::set ZConesSortedByDimension; std::set tropicalVariety(const poly g, const ring r, const tropicalStrategy* currentCase); ZConesSortedByDimension tropicalVarietySortedByDimension(const poly g, const ring r, const tropicalStrategy* currentCase); #ifndef NDEBUG BOOLEAN tropicalVariety00(leftv res, leftv args); BOOLEAN tropicalVariety01(leftv res, leftv args); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/witness.cc000066400000000000000000000052421266270727000234730ustar00rootroot00000000000000#include #include #include #include #include #include #include matrix divisionDiscardingRemainder(const poly f, const ideal G, const ring r) { ring origin = currRing; if (origin != r) rChangeCurrRing(r); ideal F = idInit(1); F->m[0]=f; ideal m = idLift(G,F); F->m[0]=NULL; id_Delete(&F, currRing); matrix Q = id_Module2formatedMatrix(m,IDELEMS(G),1,currRing); if (origin != r) rChangeCurrRing(origin); return Q; } matrix divisionDiscardingRemainder(const ideal F, const ideal G, const ring r) { ring origin = currRing; if (origin != r) rChangeCurrRing(r); ideal R; matrix U; ideal m = idLift(G,F,&R,FALSE,FALSE,TRUE,&U); matrix Q = id_Module2formatedMatrix(m,IDELEMS(G),IDELEMS(F),currRing); id_Delete(&R,r); mp_Delete(&U,r); if (origin != r) rChangeCurrRing(origin); return Q; } poly witness(const poly m, const ideal I, const ideal inI, const ring r) { assume(idSize(I)==idSize(inI)); matrix Q = divisionDiscardingRemainder(m,inI,r); int k = idSize(I); poly f = p_Mult_q(p_Copy(I->m[0],r),Q->m[0],r); Q->m[0] = NULL; for (int i=1; im[i],r),Q->m[i],r),r); Q->m[i] = NULL; } mp_Delete(&Q,r); return f; } ideal witness(const ideal inI, const ideal J, const ring r) { ring origin = currRing; if (origin!=r) rChangeCurrRing(r); ideal NFinI = kNF(J,r->qideal,inI); if (origin!=r) rChangeCurrRing(origin); int k = idSize(inI); ideal I = idInit(k); for (int i=0; im[i] = p_Add_q(p_Copy(inI->m[i],r),p_Neg(NFinI->m[i],r),r); NFinI->m[i] = NULL; } return I; } #ifndef NDEBUG BOOLEAN dwrDebug(leftv res, leftv args) { leftv u = args; leftv v = u->next; ideal F = (ideal) u->CopyD(); ideal G = (ideal) v->CopyD(); omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); matrix Q = divisionDiscardingRemainder(F,G,currRing); id_Delete(&F,currRing); id_Delete(&G,currRing); res->rtyp = MATRIX_CMD; res->data = (char*) Q; return FALSE; } BOOLEAN witnessDebug(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == IDEAL_CMD)) { leftv v = u->next; if ((v!=NULL) && (v->Typ()==IDEAL_CMD)) { omUpdateInfo(); Print("usedBytesBefore=%ld\n",om_Info.UsedBytes); ideal inI = (ideal) u->CopyD(); ideal J = (ideal) v->CopyD(); ideal I = witness(inI,J,currRing); id_Delete(&inI,currRing); id_Delete(&J,currRing); res->rtyp = IDEAL_CMD; res->data = (char*) I; return FALSE; } } return TRUE; } #endif singular-4.0.3+ds/Singular/dyn_modules/gfanlib/witness.h000066400000000000000000000033541266270727000233370ustar00rootroot00000000000000#ifndef WITNESS_H #define WITNESS_H #include #include /** * Computes a division discarding remainder of f with respect to G. * Given f a polynomial and G={g1,...,gk} a set of polynomials in r, * returns a matrix Q=(q1,...,qk) over r such that * f = q1*g1+...+qk*gk+s * is a determinate division with remainder s. */ matrix divisionDiscardingRemainder(const poly f, const ideal G, const ring r); /** * Computes a division discarding remainder of F with respect to G. * Given F={f1,...,fl} and G={g1,...,gk} two sets of polynomials in r, * returns a matrix Q=(qij) i=1,..,k j=1,...,l over r such that * fj = q1j*g1+...+qkj*gk+sj * is a determinate division with remainder sj for all j=1,...,l. */ matrix divisionDiscardingRemainder(const ideal F, const ideal G, const ring r); /** * Let w be the uppermost weight vector in the matrix defining the ordering on r. * Let I be a Groebner basis of an ideal in r, inI its initial form with respect w. * Given an w-homogeneous element m of inI, computes a witness g of m in I, * i.e. g in I such that in_w(g)=m. */ poly witness(const poly m, const ideal I, const ideal inI, const ring r); /** * Computes witnesses in J for inI * Given inI={h1,...,hl} and J={g1,...,gk} two sets of polynomials in r, * returns a set I={f1,...,fl} of such that * in_w(fj)=hj for all j=1,...,l, * where w denotes the uppoermost weight vector in the matrix defining the ordering on r. * Assumes that hj is an element of */ ideal witness(const ideal inI, const ideal J, const ring r); #ifndef NDEBUG #include BOOLEAN dwrDebug(leftv res, leftv args); BOOLEAN witnessDebug(leftv res, leftv args); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/polymake/000077500000000000000000000000001266270727000217045ustar00rootroot00000000000000singular-4.0.3+ds/Singular/dyn_modules/polymake/Makefile.am000066400000000000000000000026611266270727000237450ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../../m4 AM_CPPFLAGS = -I${top_srcdir} -I${top_builddir} \ -I${top_srcdir}/libpolys -I${top_builddir}/libpolys \ $(PM_INC) $(PM_CFLAGS) \ ${FACTORY_INCLUDES} ${RESOURCES_INCLUDES} ${OMALLOC_INCLUDES} \ ${FLINT_CFLAGS} ${NTL_CFLAGS} ${GMP_CFLAGS} # $(FEXCEPTIONSFRTTI_CXXFLAGS) ?? if SI_BUILTIN_POLYMAKE noinst_LTLIBRARIES=polymake.la ## moduledir = $(libdir)/singular P_PROCS_CPPFLAGS_COMMON = -DSTATIC_VERSION P_PROCS_MODULE_LDFLAGS = -module else module_LTLIBRARIES=polymake.la moduledir = $(libexecdir)/singular/MOD P_PROCS_CPPFLAGS_COMMON = -DDYNAMIC_VERSION P_PROCS_MODULE_LDFLAGS = -module -export-dynamic -avoid-version -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup # Add under Mac OS X: -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup endif if SING_HAVE_POLYMAKE # forcefully enable exceptions for polymake CXXFLAGS+= $(FEXCEPTIONSFRTTI_CXXFLAGS) PM_CXXFLAGS= ${FEXCEPTIONSFRTTI_CXXFLAGS} P_PROCS_MODULE_LDFLAGS+= ${PM_LDFLAGS} polymake_la_LIBADD= ${PM_LIBS} endif SOURCES = polymake_conversion.h polymake_conversion.cc \ polymake_documentation.h polymake_documentation.cc \ polymake_wrapper.cc polymake_la_SOURCES = $(SOURCES) polymake_la_CPPFLAGS = ${AM_CPPFLAGS} ${P_PROCS_CPPFLAGS_COMMON} ${PM_CXXFLAGS} polymake_la_CXXFLAGS = ${PM_CXXFLAGS} polymake_la_CFLAGS = ${PM_CXXFLAGS} polymake_la_LDFLAGS = ${P_PROCS_MODULE_LDFLAGS} singular-4.0.3+ds/Singular/dyn_modules/polymake/polymake_conversion.cc000066400000000000000000000336251266270727000263120ustar00rootroot00000000000000#include #ifdef HAVE_POLYMAKE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // for bigints, // is there really nothing better than this? /* Functions for converting Integers, Rationals and their Matrices in between C++, gfan, polymake and singular */ /* gfan -> polymake */ polymake::Integer GfInteger2PmInteger (const gfan::Integer& gi) { mpz_t cache; mpz_init(cache); gi.setGmp(cache); polymake::Integer pi(cache); return pi; } polymake::Rational GfRational2PmRational (const gfan::Rational& gr) { mpq_t cache; mpq_init(cache); gr.setGmp(cache); polymake::Rational pr(cache); return pr; } polymake::Vector Intvec2PmVectorInteger (const intvec* iv) { polymake::Vector vi(iv->length()); for(int i=1; i<=iv->length(); i++) { vi[i-1]=(*iv)[i-1]; } return vi; } polymake::Matrix GfZMatrix2PmMatrixInteger (const gfan::ZMatrix* zm) { int rows=zm->getHeight(); int cols=zm->getWidth(); polymake::Matrix mi(rows,cols); for(int r=1; r<=rows; r++) for(int c=1; c<=cols; c++) mi(r-1,c-1) = GfInteger2PmInteger((*zm)[r-1][c-1]); return mi; } polymake::Matrix GfQMatrix2PmMatrixRational (const gfan::QMatrix* qm) { int rows=qm->getHeight(); int cols=qm->getWidth(); polymake::Matrix mr(rows,cols); for(int r=1; r<=rows; r++) for(int c=1; c<=cols; c++) mr(r-1,c-1) = GfRational2PmRational((*qm)[r-1][c-1]); return mr; } /* gfan <- polymake */ gfan::Integer PmInteger2GfInteger (const polymake::Integer& pi) { mpz_class cache(pi.get_rep()); gfan::Integer gi(cache.get_mpz_t()); return gi; } gfan::Rational PmRational2GfRational (const polymake::Rational& pr) { mpq_class cache(pr.get_rep()); gfan::Rational gr(cache.get_mpq_t()); return gr; } gfan::ZMatrix PmMatrixInteger2GfZMatrix (const polymake::Matrix* mi) { int rows=mi->rows(); int cols=mi->cols(); gfan::ZMatrix zm(rows,cols); for(int r=1; r<=rows; r++) for(int c=1; c<=cols; c++) zm[r-1][c-1] = PmInteger2GfInteger((*mi)(r-1,c-1)); return zm; } gfan::QMatrix PmMatrixRational2GfQMatrix (const polymake::Matrix* mr) { int rows=mr->rows(); int cols=mr->cols(); gfan::QMatrix qm(rows,cols); for(int r=1; r<=rows; r++) for(int c=1; c<=cols; c++) qm[r-1][c-1] = PmRational2GfRational((*mr)(r-1,c-1)); return qm; } /* polymake -> singular */ int PmInteger2Int(const polymake::Integer& pi, bool &ok) { int i=0; try { i = pi.to_int(); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); ok = false; } return i; } number PmInteger2Number (const polymake::Integer& pi) { mpz_class cache(pi.get_rep()); long m = 268435456; if(mpz_cmp_si(cache.get_mpz_t(),m)) { int temp = (int) mpz_get_si(cache.get_mpz_t()); return n_Init(temp,coeffs_BIGINT); } else return n_InitMPZ(cache.get_mpz_t(),coeffs_BIGINT); } intvec* PmVectorInteger2Intvec (const polymake::Vector* vi, bool &ok) { intvec* iv = new intvec(vi->size()); for(int i=1; i<=vi->size(); i++) { (*iv)[i-1] = PmInteger2Int((*vi)[i-1],ok); } return iv; } intvec* PmMatrixInteger2Intvec (polymake::Matrix* mi, bool &ok) { int rows = mi->rows(); int cols = mi->cols(); intvec* iv = new intvec(rows,cols,0); const polymake::Integer* pi = concat_rows(*mi).begin(); for (int r = 1; r <= rows; r++) for (int c = 1; c <= cols; c++) { IMATELEM(*iv,r,c) = PmInteger2Int(*pi, ok); pi++; } return iv; } bigintmat* PmMatrixInteger2Bigintmat (polymake::Matrix* mi) { int rows = mi->rows(); int cols = mi->cols(); bigintmat* bim= new bigintmat(rows,cols,coeffs_BIGINT); const polymake::Integer* pi = concat_rows(*mi).begin(); for (int r = 1; r <= rows; r++) for (int c = 1; c <= cols; c++) { number temp = PmInteger2Number(*pi); bim->set(r,c,temp); n_Delete(&temp,coeffs_BIGINT); pi++; } return bim; } lists PmIncidenceMatrix2ListOfIntvecs (polymake::IncidenceMatrix* icmat) { int rows = icmat->rows(); int cols = icmat->cols(); lists L = (lists)omAllocBin(slists_bin); L->Init(rows); for (int r = 0; r < rows; r++) { intvec* iv = new intvec(cols); int i=0; for (int c = 0; c < cols; c++) { if ((*icmat).row(r).exists(c)) { (*iv)[i]=c; i++; } } iv->resize(i); L->m[r].rtyp = INTVEC_CMD; L->m[r].data = (void*) iv; } return L; } lists PmAdjacencyMatrix2ListOfEdges (polymake::IncidenceMatrix* icmat) { int rows = icmat->rows(); int cols = icmat->cols(); // counting number of edges int i=0; int r, c; for (r=0; rInit(i); i=0; for (r=0; rm[i].rtyp = INTVEC_CMD; L->m[i].data = (void*) iv; i++; } } } return L; } intvec* PmSetInteger2Intvec (polymake::Set* si, bool &b) { polymake::Vector vi(*si); return PmVectorInteger2Intvec(&vi,b); } /* polymake <- singular */ polymake::Matrix Intvec2PmMatrixInteger (const intvec* im) { int rows=im->rows(); int cols=im->cols(); polymake::Matrix mi(rows,cols); for(int r=0; risa("Cone")) { polymake::Integer ambientdim1 = pc->give("CONE_AMBIENT_DIM"); bool ok=true; int ambientdim2 = PmInteger2Int(ambientdim1, ok); if (!ok) { WerrorS("PmCone2ZCone: overflow while converting polymake::Integer to int"); } polymake::Matrix ineqrational = pc->give("FACETS"); polymake::Matrix eqrational = pc->give("LINEAR_SPAN"); // polymake::Matrix exraysrational = pc->give("RAYS"); // polymake::Matrix linrational = pc->give("LINEALITY_SPACE"); gfan::ZMatrix zv, zw, zx, zy, zz; // the following branching statements are to cover cases in which polymake returns empty matrices // by convention, gfanlib ignores empty matrices, hence zero matrices of right dimensions have to be supplied if (ineqrational.cols()!=0) { polymake::Matrix ineqinteger = polymake::common::primitive(ineqrational); zv = PmMatrixInteger2GfZMatrix(&ineqinteger); } else zv = gfan::ZMatrix(0, ambientdim2); if (eqrational.cols()!=0) { polymake::Matrix eqinteger = polymake::common::primitive(eqrational); zw = PmMatrixInteger2GfZMatrix(&eqinteger); } else zw = gfan::ZMatrix(0, ambientdim2); // if (exraysrational.cols()!=0) // { // polymake::Matrix exraysinteger = polymake::common::primitive(exraysrational); // zx = PmMatrixInteger2GfZMatrix(&exraysinteger); // } // else // zx = gfan::ZMatrix(0, ambientdim2); // if (linrational.cols()!=0) // { // polymake::Matrix lininteger = polymake::common::primitive(linrational); // zy = PmMatrixInteger2GfZMatrix(&lininteger); // } // else // zy = gfan::ZMatrix(0, ambientdim2); // gfan::ZCone* zc = new gfan::ZCone(zv,zw,zx,zy,zz,3); gfan::ZCone* zc = new gfan::ZCone(zv,zw,3); return zc; } WerrorS("PmCone2ZCone: unexpected parameters"); return NULL; } gfan::ZCone* PmPolytope2ZPolytope (polymake::perl::Object* pp) { if (pp->isa("Polytope")) { polymake::Integer ambientdim1 = pp->give("CONE_AMBIENT_DIM"); bool ok=true; int ambientdim2 = PmInteger2Int(ambientdim1, ok); if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); } polymake::Matrix ineqrational = pp->give("FACETS"); polymake::Matrix eqrational = pp->give("AFFINE_HULL"); // polymake::Matrix vertrational = pp->give("VERTICES"); // polymake::Matrix linrational = pp->give("LINEALITY_SPACE"); gfan::ZMatrix zv, zw; // the following branching statements are to cover the cases when polymake returns empty matrices // by convention, gfanlib ignores empty matrices, hence zero matrices of right dimensions have to be supplied if (ineqrational.cols()!=0) { polymake::Matrix ineqinteger = polymake::common::primitive(ineqrational); zv = PmMatrixInteger2GfZMatrix(&ineqinteger); } else zv = gfan::ZMatrix(0, ambientdim2); if (eqrational.cols()!=0) { polymake::Matrix eqinteger = polymake::common::primitive(eqrational); zw = PmMatrixInteger2GfZMatrix(&eqinteger); } else zw = gfan::ZMatrix(0, ambientdim2); // if (vertrational.cols()!=0) // { // polymake::Matrix vertinteger = polymake::common::primitive(vertrational); // zx = PmMatrixInteger2GfZMatrix(&vertinteger); // } // else // zx = gfan::ZMatrix(0, ambientdim2); // if (linrational.cols()!=0) // { // polymake::Matrix lininteger = polymake::common::primitive(linrational); // zy = PmMatrixInteger2GfZMatrix(&lininteger); // } // else // zy = gfan::ZMatrix(0, ambientdim2); // gfan::ZCone* zp = new gfan::ZCone(zv,zw,zx,zy,zz,3); gfan::ZCone* zp = new gfan::ZCone(zv,zw,3); return zp; } WerrorS("PmPolytope2ZPolytope: unexpected parameters"); return NULL; } gfan::ZFan* PmFan2ZFan (polymake::perl::Object* pf) { if (pf->isa("PolyhedralFan")) { int d = (int) pf->give("FAN_AMBIENT_DIM"); gfan::ZFan* zf = new gfan::ZFan(d); int n = pf->give("N_MAXIMAL_CONES"); for (int i=0; iCallPolymakeMethod("cone",i); gfan::ZCone* zc=PmCone2ZCone(&pmcone); zf->insert(*zc); } return zf; } WerrorS("PmFan2ZFan: unexpected parameters"); return NULL; } polymake::perl::Object* ZCone2PmCone (gfan::ZCone* zc) { polymake::perl::Object* gc = new polymake::perl::Object("Cone"); gfan::ZMatrix inequalities = zc->getInequalities(); gc->take("FACETS") << GfZMatrix2PmMatrixInteger(&inequalities); gfan::ZMatrix equations = zc->getEquations(); gc->take("LINEAR_SPAN") << GfZMatrix2PmMatrixInteger(&equations); // if(zc->areExtremeRaysKnown()) // { // gfan::ZMatrix extremeRays = zc->extremeRays(); // gc->take("RAYS") << GfZMatrix2PmMatrixInteger(&extremeRays); // } // if(zc->areGeneratorsOfLinealitySpaceKnown()) // { // gfan::ZMatrix lineality = zc->generatorsOfLinealitySpace(); // gc->take("LINEALITY_SPACE") << GfZMatrix2PmMatrixInteger(&lineality); // } return gc; } polymake::perl::Object* ZPolytope2PmPolytope (gfan::ZCone* zc) { polymake::perl::Object* pp = new polymake::perl::Object("Polytope"); gfan::ZMatrix inequalities = zc->getInequalities(); pp->take("FACETS") << GfZMatrix2PmMatrixInteger(&inequalities); gfan::ZMatrix equations = zc->getEquations(); pp->take("LINEAR_SPAN") << GfZMatrix2PmMatrixInteger(&equations); // if(zc->areExtremeRaysKnown()) // { // gfan::ZMatrix vertices = zc->extremeRays(); // pp->take("VERTICES") << GfZMatrix2PmMatrixInteger(&vertices); // } return pp; } polymake::Matrix raysOf(gfan::ZFan* zf) { int d = zf->getAmbientDimension(); int n = zf->numberOfConesOfDimension(1,0,0); gfan::ZMatrix zm(n,d); for (int i=0; igetCone(1,i,0,0); gfan::ZMatrix ray = zc.extremeRays(); for (int j=0; jnumberOfConesOfDimension(1,0,0); return n; } int numberOfMaximalConesOf(gfan::ZFan* zf) { int d = zf->getAmbientDimension(); int n = 0; for (int i=0; i<=d; i++) { n = n + zf->numberOfConesOfDimension(i,0,1); } return n; } polymake::Array > conesOf(gfan::ZFan* zf) { int r = numberOfMaximalConesOf(zf); polymake::Matrix pm=raysOf(zf); polymake::Array > L(r); int ii = 0; for (int d=1; d<=zf->getAmbientDimension(); d++) { for (int i=0; inumberOfConesOfDimension(d,0,1); i++) { gfan::IntVector v = zf->getConeIndices(d,i,0,1); polymake::Set s; for (int j=0; j<(int)v.size(); j++) { s = s+v[j]; } L[ii] = s; ii = ii + 1; } } return L; } polymake::perl::Object* ZFan2PmFan (gfan::ZFan* zf) { polymake::perl::Object* pf = new polymake::perl::Object("PolyhedralFan"); polymake::Matrix zm = raysOf(zf); pf->take("RAYS") << zm; // using rays here instead of INPUT_RAYS prevents redundant computations polymake::Array > ar = conesOf(zf); pf->take("MAXIMAL_CONES") << ar; return pf; } #endif singular-4.0.3+ds/Singular/dyn_modules/polymake/polymake_conversion.h000066400000000000000000000051551266270727000261510ustar00rootroot00000000000000#ifndef POLYMAKE_CONVERSION_H #define POLYMAKE_CONVERSION_H #include #ifdef HAVE_POLYMAKE #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Functions for converting Integers, Rationals and their Matrices in between C++, gfan, polymake and singular */ /* gfan -> polymake */ polymake::Integer GfInteger2PmInteger (const gfan::Integer& gi); polymake::Rational GfRational2PmRational (const gfan::Rational& gr); polymake::Vector Intvec2PmVectorInteger (const intvec* iv); polymake::Matrix GfZMatrix2PmMatrixInteger (const gfan::ZMatrix* zm); polymake::Matrix GfQMatrix2PmMatrixRational (const gfan::QMatrix* qm); /* gfan <- polymake */ gfan::Integer PmInteger2GfInteger (const polymake::Integer& pi); gfan::Rational PmRational2GfRational (const polymake::Rational& pr); gfan::ZMatrix PmMatrixInteger2GfZMatrix (const polymake::Matrix* mi); gfan::QMatrix PmMatrixRational2GfQMatrix (const polymake::Matrix* mr); /* polymake -> singular */ int PmInteger2Int(const polymake::Integer& pi, bool &ok); intvec* PmVectorInteger2Intvec (const polymake::Vector* vi, bool &ok); intvec* PmMatrixInteger2Intvec (polymake::Matrix* mi, bool &ok); lists PmIncidenceMatrix2ListOfIntvecs (polymake::IncidenceMatrix* icmat); lists PmAdjacencyMatrix2ListOfEdges (polymake::IncidenceMatrix* icmat); intvec* PmSetInteger2Intvec (polymake::Set* si, bool &b); number PmInteger2Number (const polymake::Integer& pi); bigintmat* PmMatrixInteger2Bigintmat (polymake::Matrix* mi); /* polymake <- singular */ polymake::Matrix Intvec2PmMatrixInteger (const intvec* im); /* Functions for converting cones and fans in between gfan and polymake, Singular shares the same cones and fans with gfan */ gfan::ZCone* PmCone2ZCone (polymake::perl::Object* pc); gfan::ZCone* PmPolytope2ZPolytope (polymake::perl::Object* pp); gfan::ZFan* PmFan2ZFan (polymake::perl::Object* pf); polymake::perl::Object* ZCone2PmCone (gfan::ZCone* zc); polymake::perl::Object* ZPolytope2PmPolytope (gfan::ZCone* zc); polymake::perl::Object* ZFan2PmFan (gfan::ZFan* zf); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/polymake/polymake_documentation.cc000066400000000000000000000356351266270727000270010ustar00rootroot00000000000000#include #ifdef HAVE_POLYMAKE /* #include #include #include #include #include #include #include #include */ #include void init_polymake_help() { const char *polymake_banner = "Welcome to polymake\nCopyright (c) 1997-2012\nEwgenij Gawrilow, Michael Joswig (TU Darmstadt)\nhttp://www.polymake.org\n"; PrintS(polymake_banner); const char* polymake_help = "SHARED LIBRARY: polymake.so Interface to polymake (http://www.polymake.org)\nAUTHORS: Janko Boehm, boehm@mathematik.uni-kl.de\n Yue Ren, ren@mathematik.uni-kl.de\n\nOVERVIEW:\nPolymake is a tool to study the combinatorics \nand the geometry of convex polytopes and polyhedra. \nIt is also capable of dealing with simplicial complexes, \nmatroids, polyhedral fans, graphs, tropical objects.\nThe interface relies on the callable library functionality,\nby Ewgenij Gawrilow.\n\nREFERENCES:\nEwgenij Gawrilow and Michael Joswig. polymake: a framework for analyzing convex polytopes. \nPolytopes—combinatorics and computation (Oberwolfach, 1997), 43–73, DMV Sem., 29, Birkhäuser, Basel, 2000. MR1785292 (2001f:52033)\n\nPROCEDURES:\n boundaryLatticePoints(polytope p);\n ehrhartPolynomialCoeff(polytope p);\n facetVertexLatticeDistances(polytope p);\n facetWidth(polytope p);\n facetWidths(polytope p);\n fVector(polytope p);\n gorensteinIndex(polytope p);\n gorensteinVector(polytope p);\n hilbertBasis(cone c);\n hStarVector(polytope p);\n hVector(polytope p);\n interiorLatticePoints(polytope p);\n isBounded(polytope p);\n isCanonical(polytope p);\n isCompressed(polytope p);\n isGorenstein(polytope p);\n isLatticeEmpty(polytope p);\n isNormal(polytope p);\n isReflexive(polytope p);\n isSmooth(polytope p);\n isVeryAmple(polytope p);\n latticeCodegree(polytope p);\n latticeDegree(polytope p);\n latticePoints(polytope p);\n latticeVolume(polytope p);\n maximalFace(polytope p, intvec v);\n maximalValue(polytope p, intvec v);\n minimalFace(polytope p, intvec v);\n minimalValue(polytope p, intvec v);\n minkowskiSum(polytope p, polytope q);\n nBoundaryLatticePoints(polytope p);\n nHilbertBasis(cone c);\n"; module_help_main("polymake.so",polymake_help); const char*isReflexive_help = "USAGE: isReflexive(polytope p)\nRETURN: int, 1 if p is reflexive and 0 otherwise\nKEYWORDS: polytopes; polymake; reflexive\nEXAMPLE: example isReflexive shows an example\nexample\n{ \"EXAMPLE: \";\nintmat M[4][4]=1,1,0,0, 1,0,1,0, 1,0,0,1, 1,-1,-1,-1;\npolytope p = polytopeViaVertices(M);\nPolymake::isReflexive(p);\nintmat N[4][4]=1,2,0,0, 1,0,2,0, 1,0,0,2, 1,-2,-2,-2;\nq = polytopeViaVertices(N);\nPolymake::isReflexive(q);\n}\n"; module_help_proc("polymake.so","isReflexive", isReflexive_help); const char* isBounded_help = "USAGE: isBounded(polytope p)\nRETURN: int, 1 if p is bounded, 0 otherwise.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example isBounded shows an example\n"; module_help_proc("polymake.so","isBounded", isBounded_help); const char* isGorenstein_help = "USAGE: isGorenstein(polytope p)\nRETURN: int, 1 if p is gorenstein (i.e. reflexive after dilatation and translation), 0 otherwise.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example isGorenstein shows an example\n"; module_help_proc("polymake.so","isGorenstein", isGorenstein_help); const char* gorensteinIndex_help = "USAGE: gorensteinIndex(polytope p)\nRETURN: int, n if p is reflexive after dilatation by n and translation, 0 otherwise.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example gorensteinIndex shows an example\n"; module_help_proc("polymake.so","gorensteinIndex", gorensteinIndex_help); const char* gorensteinVector_help = "USAGE: gorensteinVector(polytope p)\nRETURN: intvec, v if p is reflexive after dilatation and translation by v, 0 otherwise.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example gorensteinVector shows an example\n"; module_help_proc("polymake.so","gorensteinVector", gorensteinVector_help); const char* isCanonical_help = "USAGE: isCanonical(polytope p)\nRETURN: intvec, 1 if p has exactly one interior lattice point, 0 otherwise.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example isCanonical shows an example\n"; module_help_proc("polymake.so","isCanonical", isCanonical_help); const char* isTerminal_help = "USAGE: isLatticeEmpty(polytope p)\nRETURN: int, 1 if p contains no lattice points other than the vertices, 0 otherwise.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example isLatticeEmpty shows an example\n"; module_help_proc("polymake.so","isTerminal", isTerminal_help); const char* latticeVolume_help = "USAGE: latticeVolume(polytope p)\nRETURN: int, the normalized lattice volume of p, that is, (dim(P))! times the volume of P.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example latticeVolume shows an example\n"; module_help_proc("polymake.so","latticeVolume", latticeVolume_help); const char* latticeDegree_help = "USAGE: latticeDegree(polytope p)\nRETURN: int, the lattice degree of p, i.e. degree of the Ehrhart polynomial of P.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example latticeDegree shows an example\n"; module_help_proc("polymake.so","latticeDegree", latticeDegree_help); const char* latticeCodegree_help = "USAGE: latticeCodegree(polytope p)\nRETURN: int, getDimension(p)+1-latticeDegree(p), which is the smallest number k such that k*p has an interior latt\\nice point.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example latticeCodegree shows an example\n"; module_help_proc("polymake.so","latticeCodegree", latticeCodegree_help); const char* ehrhartPolynomialCoeff_help = "USAGE: ehrhartPolynomialCoeff(polytope p)\nRETURN: intvec, coefficients of the Ehrhart polynomial of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example ehrhartPolynomialCoeff shows an example\n"; module_help_proc("polymake.so","ehrhartPolynomialCoeff", ehrhartPolynomialCoeff_help); const char* hStarVector_help = "USAGE: hStarVector(polytope p)\nRETURN: intvec, h*-vector of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example hStarVector shows an example\n"; module_help_proc("polymake.so","hStarVector", hStarVector_help); const char* hVector_help = "USAGE: hVector(polytope p)\nRETURN: intvec, h-vector of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example hVector shows an example\n"; module_help_proc("polymake.so","hVector", hVector_help); const char* fVector_help = "USAGE: fVector(polytope p)\nRETURN: intvec, the f-vector of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example fVector shows an example\n"; module_help_proc("polymake.so","fVector", fVector_help); const char* isNormal_help = "USAGE: isNormal(polytope p)\nRETURN: int, 1 if p is normal, i.e. the projective toric variety defined by p is projectively normal, 0 otherwise.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example isNormal shows an example\n"; module_help_proc("polymake.so","isNormal", isNormal_help); const char* facetWidths_help = "USAGE: facetWidths(polytope p)\nRETURN: intvec, vector with the integral widths of p with respect to all facet normals.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example facetWidths shows an example\n"; module_help_proc("polymake.so","facetWidths", facetWidths_help); const char* facetWidth_help = "USAGE: facetWidth(polytope p)\nRETURN: int, maximum of the integral widths of p over all facet normals.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example facetWidth shows an example\n"; module_help_proc("polymake.so","facetWidth", facetWidth_help); const char* facetVertexLatticeDistances_help = "USAGE: facetVertexLatticeDistances(polytope p)\nRETURN: intmat, matrix of lattice distances between vertices (columns) and facets (rows).\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example facetVertexLatticeDistances shows an example\n"; module_help_proc("polymake.so","facetVertexLatticeDistances", facetVertexLatticeDistances_help); const char* isCompressed_help = "USAGE: isCompressed(polytope p)\nRETURN: int, 1 if facetWidth(p)=1, 0 otherwise.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example isCompressed shows an example\n"; module_help_proc("polymake.so","isCompressed", isCompressed_help); const char* isSmooth_help = "USAGE: isSmooth(polytope p)\n isSmooth(cone c)\n isSmooth(fan F)\nRETURN: int, 1 if p, c, or F is smooth, 0 otherwise.\nKEYWORDS: polytopes; cones; fans; polymake;\nEXAMPLE: example isSmooth shows an example\n"; module_help_proc("polymake.so","isSmooth", isSmooth_help); const char* isVeryAmple_help = "USAGE: isVeryAmple(polytope p)\nRETURN: int, 1 if p is very ample, 0 otherwise.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example isVeryAmple shows an example\n"; module_help_proc("polymake.so","isVeryAmple", isVeryAmple_help); const char* latticePoints_help = "USAGE: latticePoints(polytope p)\nRETURN: intmat, matrix whose rows are the lattice points of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example latticePoints shows an example\n"; module_help_proc("polymake.so","latticePoints", latticePoints_help); const char* nLatticePoints_help = "USAGE: nLatticePoints(polytope p)\nRETURN: int, number of lattice points of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example nLatticePoints shows an example\n"; module_help_proc("polymake.so","nLatticePoints", nLatticePoints_help); const char* interiorLatticePoints_help = "USAGE: interiorLatticePoints(polytope p)\nRETURN: intmat, an matrix whose rows are the lattice points in the relative interior of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example interiorLatticePoints shows an example\n"; module_help_proc("polymake.so","interiorLatticePoints", interiorLatticePoints_help); const char* nInteriorLatticePoints_help = "USAGE: nInteriorLatticePoints(polytope p)\nRETURN: int, number of lattice points in the relative interior of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example nInteriorLatticePoints shows an example\n"; module_help_proc("polymake.so","nInteriorLatticePoints", nInteriorLatticePoints_help); const char* boundaryLatticePoints_help = "USAGE: boundaryLatticePoints(polytope p)\nRETURN: intmat, matrix whose rows are the lattice points in the relative boundary of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example boundaryLatticePoints shows an example\n"; module_help_proc("polymake.so","boundaryLatticePoints", boundaryLatticePoints_help); const char* nBoundaryLatticePoints_help = "USAGE: nBoundaryLatticePoints(polytope p)\nRETURN: int, number of lattice points in the relative boundary of p.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example nBoundaryLatticePoints shows an example\n"; module_help_proc("polymake.so","nBoundaryLatticePoints", nBoundaryLatticePoints_help); const char* hilbertBasis_help = "USAGE: hilbertBasis(cone c)\nRETURN: intmat, Hilbert basis of the semigroup of c.\nKEYWORDS: cones; polymake;\nEXAMPLE: example hilbertBasis shows an example\n"; module_help_proc("polymake.so","hilbertBasis", hilbertBasis_help); const char* nHilbertBasis_help = "USAGE: nHilbertBasis(cone c)\nRETURN: int, size of the Hilbert basis of the semigroup of c.\nKEYWORDS: cones; polymake;\nEXAMPLE: example nHilbertBasis shows an example\n"; module_help_proc("polymake.so","nHilbertBasis", nHilbertBasis_help); const char* minkowskiSum_help = "USAGE: minkowskiSum(polytope p, polytope q)\nRETURN: polytope, Minkowski sum of p and q.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example minkowskiSum shows an example\n"; module_help_proc("polymake.so","minkowskiSum", minkowskiSum_help); const char* minimalValue_help = "USAGE: minimalValue(polytope p, intvec v)\nRETURN: int, the minimal value of the linear form v on p.\n The first coordinate of v corresponds to a shift of the\n minimal value since p is considered as a polytope\n in the plane (first coordinate) = 1.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example minimalValue shows an example\n"; module_help_proc("polymake.so","minimalValue", minimalValue_help); const char* maximalValue_help = "USAGE: maximalValue(polytope p, intvec v)\nRETURN: int, maximal value of the linear form v on p.\n The first coordinate of v corresponds to a shift of the\n maximal value since p is considered as a polytope\n in the plane (first coordinate) = 1.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example maximalValue shows an example\n"; module_help_proc("polymake.so","maximalValue", maximalValue_help); const char* minimalFace_help = "USAGE: minimalFace(polytope p, intvec v)\nRETURN: intmat, vertices of the face of p on which the linear form v\n is minimal.\n The first coordinate of v corresponds to a shift of the\n minimal value since p is considered as a polytope\n in the plane (first coordinate) = 1. Hence\n the minimal face is independent of the first coordinate of v.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example minimalFace shows an example\n"; module_help_proc("polymake.so","minimalFace", minimalFace_help); const char* maximalFace_help = "USAGE: maximalFace(polytope p, intvec v)\nRETURN: intmat, vertices of the face of p on which the linear form v\n is maximal.\n The first coordinate of v corresponds to a shift of the\n maximal value since p is considered as a polytope\n in the plane (first coordinate) = 1. Hence\n the maximal face is independent of the first coordinate of v.\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example maximalFace shows an example\n"; module_help_proc("polymake.so","maximalFace", maximalFace_help); const char* visual_help = "USAGE: visual(polytope p)\n visual(fan F)\nRETURN: none, draws the polytope p or fan F using jreality.\nKEYWORDS: polytopes; polymake; visualization;\nEXAMPLE: example visual shows an example\n"; module_help_proc("polymake.so","visual", visual_help); const char* normalFan_help = "USAGE: normalFan(polytope p)\nRETURN: fan,\nKEYWORDS: polytopes; polymake; visualization;\nEXAMPLE: example visual shows an example\n"; module_help_proc("polymake.so","normalFan", normalFan_help); const char* vertexAdjacencyGraph_help = "USAGE: vertexAdjacencyGraph(polytope p)\nRETURN: list,\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example visual shows an example\n"; module_help_proc("polymake.so","vertexAdjacencyGraph", normalFan_help); const char* vertexEdgeGraph_help = "USAGE: vertexEdgeGraph(polytope p)\nRETURN: list,\nKEYWORDS: polytopes; polymake;\nEXAMPLE: example visual shows an example\n"; module_help_proc("polymake.so","vertexEdgeGraph", normalFan_help); } #endif singular-4.0.3+ds/Singular/dyn_modules/polymake/polymake_documentation.h000066400000000000000000000002351266270727000266270ustar00rootroot00000000000000#ifndef POLYMAKE_DOCUMENTATION_H #define POLYMAKE_DOCUMENTATION_H #include #ifdef HAVE_POLYMAKE void init_polymake_help(); #endif #endif singular-4.0.3+ds/Singular/dyn_modules/polymake/polymake_wrapper.cc000066400000000000000000001355061266270727000256060ustar00rootroot00000000000000#include #ifdef HAVE_POLYMAKE #include #include #include #include #include #include #include #include #include #include polymake::Main* init_polymake=NULL; static BOOLEAN bbpolytope_Op2(int op, leftv res, leftv i1, leftv i2) { gfan::ZCone* zp = (gfan::ZCone*) i1->Data(); switch(op) { case '+': { if (i2->Typ()==polytopeID || i2->Typ()==coneID) { gfan::ZCone* zq = (gfan::ZCone*) i2->Data(); gfan::ZCone* ms; try { polymake::perl::Object* pp = ZPolytope2PmPolytope(zp); polymake::perl::Object* pq = ZPolytope2PmPolytope(zq); polymake::perl::Object pms; CallPolymakeFunction("minkowski_sum", *pp, *pq) >> pms; ms = PmPolytope2ZPolytope(&pms); delete pp; delete pq; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = polytopeID; res->data = (void*) ms; return FALSE; } return blackboxDefaultOp2(op,res,i1,i2); } case '*': { if (i2->Typ()==INT_CMD) { int s = (int)(long) i2->Data(); gfan::ZMatrix zm = zp->extremeRays(); for (int i=0; irtyp = polytopeID; res->data = (void*) zs; return FALSE; } return blackboxDefaultOp2(op,res,i1,i2); } case '&': { if (i2->Typ()==polytopeID) { gfan::ZCone* zq = (gfan::ZCone*) i2->Data(); int d1 = zp->ambientDimension(); int d2 = zq->ambientDimension(); if (d1 != d2) { Werror("mismatching ambient dimensions"); return TRUE; } gfan::ZCone* zs = new gfan::ZCone(); *zs = gfan::intersection(*zp, *zq); zs->canonicalize(); res->rtyp = polytopeID; res->data = (void*) zs; return FALSE; } return blackboxDefaultOp2(op,res,i1,i2); } case '|': { if(i2->Typ()==polytopeID) { gfan::ZCone* zq = (gfan::ZCone*) i2->Data(); int d1 = zp->ambientDimension(); int d2 = zq->ambientDimension(); if (d1 != d2) { Werror("mismatching ambient dimensions"); return TRUE; } gfan::ZMatrix rays = zp->extremeRays(); rays.append(zq->extremeRays()); gfan::ZMatrix lineality = zp->generatorsOfLinealitySpace(); lineality.append(zq->generatorsOfLinealitySpace()); gfan::ZCone* zs = new gfan::ZCone(); *zs = gfan::ZCone::givenByRays(rays,lineality); zs->canonicalize(); res->rtyp = polytopeID; res->data = (void*) zs; return FALSE; } return blackboxDefaultOp2(op,res,i1,i2); } case EQUAL_EQUAL: { if(i2->Typ()==polytopeID) { gfan::ZCone* zq = (gfan::ZCone*) i2->Data(); zp->canonicalize(); zq->canonicalize(); bool b = !((*zp)!=(*zq)); res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } return blackboxDefaultOp2(op,res,i1,i2); } default: return blackboxDefaultOp2(op,res,i1,i2); } return blackboxDefaultOp2(op,res,i1,i2); } /* Functions for using Polymake in Singular */ // BOOLEAN cube(leftv res, leftv args) // { // leftv u = args; // if ((u !=NULL) && (u->Typ() == INT_CMD)) // { // int ambientDim = (int)(long)u->Data(); // if (ambientDim < 0) // { // Werror("expected non-negative ambient dim but got %d", ambientDim); // return TRUE; // } // gfan::ZMatrix zm(ambientDim*2,ambientDim+1); // int j=1; // for (int i=0; irtyp = coneID; // res->data = (char *)zc; // return FALSE; // } // WerrorS("cube: unexpected parameters"); // return TRUE; // } // BOOLEAN cross(leftv res, leftv args) // { // leftv u = args; // if ((u !=NULL) && (u->Typ() == INT_CMD)) // { // int ambientDim = (int)(long)u->Data(); // if (ambientDim < 0) // { // Werror("expected non-negative ambient dim but got %d", ambientDim); // return TRUE; // } // gfan::ZMatrix zm(ambientDim*2,ambientDim+1); // int j=1; // for (int i=0; irtyp = coneID; // res->data = (char *)zc; // return FALSE; // } // WerrorS("cross: unexpected parameters"); // return TRUE; // } BOOLEAN PMisLatticePolytope(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("Lattice"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isLatticePolytope: unexpected parameters"); return TRUE; } BOOLEAN PMisBounded(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("BOUNDED"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isBounded: unexpected parameters"); return TRUE; } BOOLEAN PMisReflexive(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("REFLEXIVE"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isReflexive: unexpected parameters"); return TRUE; } BOOLEAN PMisGorenstein(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("GORENSTEIN"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isGorenstein: unexpected parameters"); return TRUE; } BOOLEAN PMgorensteinIndex(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); int gi; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); bool b = p->give("GORENSTEIN"); if (b) { polymake::Integer pgi = p->give("GORENSTEIN_INDEX"); gi = PmInteger2Int(pgi,ok); delete p; } else { delete p; WerrorS("gorensteinIndex: input polytope not gorenstein"); return TRUE; } } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) gi; return FALSE; } WerrorS("gorensteinIndex: unexpected parameters"); return TRUE; } BOOLEAN PMgorensteinVector(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* gv; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); bool b = p->give("GORENSTEIN"); if (b) { polymake::Vector pgv = p->give("GORENSTEIN_VECTOR"); gv = PmVectorInteger2Intvec(&pgv,ok); delete p; } else { delete p; WerrorS("gorensteinVector: input polytope not gorenstein"); return TRUE; } } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("gorensteinVector: overflow in PmVectorInteger2Intvec"); return TRUE; } res->rtyp = INTVEC_CMD; res->data = (char*) gv; return FALSE; } WerrorS("gorensteinVector: unexpected parameters"); return TRUE; } BOOLEAN PMisCanonical(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("CANONICAL"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isCanonical: unexpected parameters"); return TRUE; } BOOLEAN PMisTerminal(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("TERMINAL"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isTerminal: unexpected parameters"); return TRUE; } BOOLEAN PMisLatticeEmpty(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("LATTICE_EMPTY"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isLatticeEmpty: unexpected parameters"); return TRUE; } BOOLEAN PMlatticeVolume(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); int lv; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Integer plv = p->give("LATTICE_VOLUME"); delete p; lv = PmInteger2Int(plv,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) lv; return FALSE; } WerrorS("latticeVolume: unexpected parameters"); return TRUE; } BOOLEAN PMlatticeDegree(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); int ld; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Integer pld = p->give("LATTICE_DEGREE"); delete p; ld = PmInteger2Int(pld,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) ld; return FALSE; } WerrorS("latticeDegree: unexpected parameters"); return TRUE; } BOOLEAN PMlatticeCodegree(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); int lc; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Integer plc = p->give("LATTICE_CODEGREE"); delete p; lc = PmInteger2Int(plc,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) lc; return FALSE; } WerrorS("latticeCodegree: unexpected parameters"); return TRUE; } BOOLEAN PMehrhartPolynomialCoeff(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* ec; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Vector pec = p->give("EHRHART_POLYNOMIAL_COEFF"); delete p; ec = PmVectorInteger2Intvec(&pec,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("ehrhartPolynomialCoeff: overflow in PmVectorInteger2Intvec"); return TRUE; } res->rtyp = INTVEC_CMD; res->data = (char*) ec; return FALSE; } WerrorS("ehrhartPolynomialCoeff: unexpected parameters"); return TRUE; } BOOLEAN PMfVector(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* hv; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Vector phv = p->give("F_VECTOR"); delete p; hv = PmVectorInteger2Intvec(&phv,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("fVectorP: overflow in PmVectorInteger2Intvec"); return TRUE; } res->rtyp = INTVEC_CMD; res->data = (char*) hv; return FALSE; } WerrorS("fVectorP: unexpected parameters"); return TRUE; } BOOLEAN PMhVector(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* hv; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Vector phv = p->give("H_VECTOR"); delete p; hv = PmVectorInteger2Intvec(&phv,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("hVector: overflow in PmVectorInteger2Intvec"); return TRUE; } res->rtyp = INTVEC_CMD; res->data = (char*) hv; return FALSE; } WerrorS("hVector: unexpected parameters"); return TRUE; } BOOLEAN PMhStarVector(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* hv; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Vector phv = p->give("H_STAR_VECTOR"); delete p; hv = PmVectorInteger2Intvec(&phv,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("hStarVector: overflow in PmVectorInteger2Intvec"); return TRUE; } res->rtyp = INTVEC_CMD; res->data = (char*) hv; return FALSE; } WerrorS("hStarVector: unexpected parameters"); return TRUE; } BOOLEAN PMisNormal(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("NORMAL"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isNormal: unexpected parameters"); return TRUE; } BOOLEAN PMfacetWidths(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* fw; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Vector pfw = p->give("FACET_WIDTHS"); delete p; fw = PmVectorInteger2Intvec(&pfw,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("facetWidths: overflow in PmVectorInteger2Intvec"); return TRUE; } res->rtyp = INTVEC_CMD; res->data = (char*) fw; return FALSE; } WerrorS("facetWidths: unexpected parameters"); return TRUE; } BOOLEAN PMfacetWidth(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); int fw; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Integer pfw = p->give("FACET_WIDTH"); delete p; fw = PmInteger2Int(pfw,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) fw; return FALSE; } WerrorS("facetWidth: unexpected parameters"); return TRUE; } BOOLEAN PMfacetVertexLatticeDistances(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* ld; bool ok=true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Matrix pld = p->give("FACET_VERTEX_LATTICE_DISTANCES"); delete p; ld = PmMatrixInteger2Intvec(&pld,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INTMAT_CMD; res->data = (char*) ld; return FALSE; } WerrorS("facetVertexLatticeDistances: unexpected parameters"); return TRUE; } BOOLEAN PMisCompressed(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("COMPRESSED"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isCompressed: unexpected parameters"); return TRUE; } BOOLEAN PMisSmooth(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZCone2PmCone(zc); b = p->give("SMOOTH_CONE"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("SMOOTH"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); bool b; try { polymake::perl::Object* p = ZFan2PmFan(zf); b = p->give("SMOOTH_FAN"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isSmooth: unexpected parameters"); return TRUE; } BOOLEAN PMisVeryAmple(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); bool b; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); b = p->give("VERY_AMPLE"); delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) b; return FALSE; } WerrorS("isVeryAmple: unexpected parameters"); return TRUE; } BOOLEAN PMlatticePoints(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* iv; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Matrix lp = p->give("LATTICE_POINTS"); delete p; iv = PmMatrixInteger2Intvec(&lp,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INTMAT_CMD; res->data = (char*) iv; return FALSE; } WerrorS("LatticePoints: unexpected parameters"); return TRUE; } BOOLEAN PMnLatticePoints(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); int n; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Integer nlp = p->give("N_LATTICE_POINTS"); delete p; n = PmInteger2Int(nlp,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) n; return FALSE; } WerrorS("nLatticePoints: unexpected parameters"); return TRUE; } BOOLEAN PMinteriorLatticePoints(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* iv; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Matrix lp = p->give("INTERIOR_LATTICE_POINTS"); delete p; iv = PmMatrixInteger2Intvec(&lp,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INTMAT_CMD; res->data = (char*) iv; return FALSE; } WerrorS("interiorLatticePoints: unexpected parameters"); return TRUE; } BOOLEAN PMnInteriorLatticePoints(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); int n; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Integer nlp = p->give("N_INTERIOR_LATTICE_POINTS"); delete p; n = PmInteger2Int(nlp,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) n; return FALSE; } WerrorS("nInteriorLatticePoints: unexpected parameters"); return TRUE; } BOOLEAN PMboundaryLatticePoints(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* iv; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Matrix lp = p->give("BOUNDARY_LATTICE_POINTS"); delete p; iv = PmMatrixInteger2Intvec(&lp,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INTMAT_CMD; res->data = (char*) iv; return FALSE; } WerrorS("boundaryLatticePoints: unexpected parameters"); return TRUE; } BOOLEAN PMnBoundaryLatticePoints(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); int n; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Integer nlp = p->give("N_BOUNDARY_LATTICE_POINTS"); delete p; n = PmInteger2Int(nlp,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) n; return FALSE; } WerrorS("nBoundaryLatticePoints: unexpected parameters"); return TRUE; } BOOLEAN PMhilbertBasis(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* iv; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Matrix lp = p->give("HILBERT_BASIS"); delete p; iv = PmMatrixInteger2Intvec(&lp,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INTMAT_CMD; res->data = (char*) iv; return FALSE; } WerrorS("hilbertBasis: unexpected parameters"); return TRUE; } BOOLEAN PMnHilbertBasis(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == coneID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); int n; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Integer nlp = p->give("N_HILBERT_BASIS"); delete p; n = PmInteger2Int(nlp,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) n; return FALSE; } WerrorS("nHilbertBasis: unexpected parameters"); return TRUE; } BOOLEAN PMminkowskiSum(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); gfan::ZCone* zq = (gfan::ZCone*)v->Data(); gfan::ZCone* ms; try { polymake::perl::Object* pp = ZPolytope2PmPolytope(zp); polymake::perl::Object* pq = ZPolytope2PmPolytope(zq); polymake::perl::Object pms; CallPolymakeFunction("minkowski_sum", *pp, *pq) >> pms; delete pp; delete pq; ms = PmPolytope2ZPolytope(&pms); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = polytopeID; res->data = (char*) ms; return FALSE; } if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); gfan::ZCone* zc = (gfan::ZCone*)v->Data(); gfan::ZCone* zq = new gfan::ZCone(liftUp(*zc)); gfan::ZCone* ms; try { polymake::perl::Object* pp = ZPolytope2PmPolytope(zp); polymake::perl::Object* pq = ZPolytope2PmPolytope(zq); polymake::perl::Object pms; CallPolymakeFunction("minkowski_sum", *pp, *pq) >> pms; delete pp; delete pq; ms = PmPolytope2ZPolytope(&pms); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); delete zq; return TRUE; } res->rtyp = polytopeID; res->data = (char*) ms; delete zq; return FALSE; } } if ((u != NULL) && (u->Typ() == coneID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == polytopeID)) { gfan::ZCone* zc = (gfan::ZCone*)u->Data(); gfan::ZCone* zp = new gfan::ZCone(liftUp(*zc)); gfan::ZCone* zq = (gfan::ZCone*)v->Data(); gfan::ZCone* ms; try { polymake::perl::Object* pp = ZPolytope2PmPolytope(zp); polymake::perl::Object* pq = ZPolytope2PmPolytope(zq); polymake::perl::Object pms; CallPolymakeFunction("minkowski_sum", *pp, *pq) >> pms; delete pp; delete pq; ms = PmPolytope2ZPolytope(&pms); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); delete zp; return TRUE; } res->rtyp = polytopeID; res->data = (char*) ms; delete zp; return FALSE; } if ((v != NULL) && (v->Typ() == coneID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); gfan::ZCone* zq = (gfan::ZCone*)v->Data(); gfan::ZCone* ms; try { polymake::perl::Object* pp = ZPolytope2PmPolytope(zp); polymake::perl::Object* pq = ZPolytope2PmPolytope(zq); polymake::perl::Object pms; CallPolymakeFunction("minkowski_sum", *pp, *pq) >> pms; delete pp; delete pq; ms = PmPolytope2ZPolytope(&pms); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = coneID; res->data = (char*) ms; return FALSE; } } WerrorS("minkowskiSum: unexpected parameters"); return TRUE; } polymake::Matrix verticesOf(const polymake::perl::Object* p, const polymake::Set* s) { polymake::Matrix allrays = p->give("VERTICES"); polymake::Matrix wantedrays; bool ok = true; for(polymake::Entire >::const_iterator i=polymake::entire(*s); !i.at_end(); i++) { wantedrays = wantedrays / allrays.row(PmInteger2Int(*i,ok)); } if (!ok) { WerrorS("overflow while converting polymake::Integer to int in raysOf"); } return wantedrays; } BOOLEAN PMmaximalFace(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == INTVEC_CMD)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* iv = (intvec*) v->Data(); intvec* maxface; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::perl::Object o("LinearProgram"); o.take("LINEAR_OBJECTIVE") << Intvec2PmVectorInteger(iv); p->take("LP") << o; polymake::Set mf = p->give("LP.MAXIMAL_FACE"); polymake::Matrix vertices = verticesOf(p,&mf); delete p; maxface = new intvec(PmMatrixInteger2Intvec(&vertices,ok)); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INTVEC_CMD; res->data = (char*) maxface; return FALSE; } } WerrorS("maximalFace: unexpected parameters"); return TRUE; } BOOLEAN PMminimalFace(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == INTVEC_CMD)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* iv = (intvec*) v->Data(); intvec* minface; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::perl::Object o("LinearProgram"); o.take("LINEAR_OBJECTIVE") << Intvec2PmVectorInteger(iv); p->take("LP") << o; polymake::Set mf = p->give("LP.MINIMAL_FACE"); polymake::Matrix vertices = verticesOf(p,&mf); delete p; minface = new intvec(PmMatrixInteger2Intvec(&vertices,ok)); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INTVEC_CMD; res->data = (char*) minface; return FALSE; } } WerrorS("minimalFace: unexpected parameters"); return TRUE; } BOOLEAN PMmaximalValue(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == INTVEC_CMD)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* iv = (intvec*) v->Data(); if (iv->rows()==zp->ambientDimension()) { int m; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Vector lo = Intvec2PmVectorInteger(iv); polymake::perl::Object o("LinearProgram"); o.take("LINEAR_OBJECTIVE") << lo; p->take("LP") << o; polymake::Integer mv = p->give("LP.MAXIMAL_VALUE"); delete p; m = PmInteger2Int(mv,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) m; return FALSE; } } WerrorS("maximalValue: vector is of wrong size"); return TRUE; } WerrorS("maximalValue: unexpected parameters"); return TRUE; } BOOLEAN PMminimalValue(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { leftv v = u->next; if ((v != NULL) && (v->Typ() == INTVEC_CMD)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); intvec* iv = (intvec*) v->Data(); if (iv->rows()==zp->ambientDimension()) { int m; bool ok = true; try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Vector lo = Intvec2PmVectorInteger(iv); polymake::perl::Object o("LinearProgram"); o.take("LINEAR_OBJECTIVE") << lo; p->take("LP") << o; polymake::Integer mv = p->give("LP.MINIMAL_VALUE"); delete p; m = PmInteger2Int(mv,ok); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } if (!ok) { WerrorS("overflow while converting polymake::Integer to int"); return TRUE; } res->rtyp = INT_CMD; res->data = (char*) (long) m; return FALSE; } } WerrorS("minimalValue: vector is of wrong size"); return TRUE; } WerrorS("minimalValue: unexpected parameters"); return TRUE; } BOOLEAN visual(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); try { polymake::perl::Object* pp = ZPolytope2PmPolytope(zp); VoidCallPolymakeFunction("jreality",pp->CallPolymakeMethod("VISUAL")); delete pp; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = NONE; res->data = NULL; return FALSE; } if ((u != NULL) && (u->Typ() == fanID)) { gfan::ZFan* zf = (gfan::ZFan*)u->Data(); try { polymake::perl::Object* pf=ZFan2PmFan(zf); VoidCallPolymakeFunction("jreality",pf->CallPolymakeMethod("VISUAL")); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = NONE; res->data = NULL; return FALSE; } WerrorS("visual: unexpected parameters"); return TRUE; } BOOLEAN normalFan(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*)u->Data(); gfan::ZFan* zf = new gfan::ZFan(0); try { polymake::perl::Object* p=ZPolytope2PmPolytope(zp); polymake::perl::Object pf; CallPolymakeFunction("normal_fan", *p) >> pf; delete p; zf = PmFan2ZFan(&pf); } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = fanID; res->data = (char*) zf; return FALSE; } WerrorS("normalFan: unexpected parameters"); return TRUE; } BOOLEAN PMconeViaRays(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == INTMAT_CMD)) { polymake::perl::Object pc("Cone"); intvec* hlines = (intvec*) u->Data(); // these will are half lines in the cone polymake::Matrix pmhlines = Intvec2PmMatrixInteger(hlines); pc.take("INPUT_RAYS") << pmhlines; leftv v = u->next; if ((v != NULL) && (v->Typ() == INTMAT_CMD)) { intvec* lines = (intvec*) v->Data(); // these will be lines in the cone polymake::Matrix pmlines = Intvec2PmMatrixInteger(lines); pc.take("INPUT_LINEALITY") << pmlines; // leftv w = v->next; // if ((w != NULL) && (w->Typ() == INT_CMD)) // { // int flag = (int) (long) w->Data(); // TODO: this will indicate whether the // // information provided are exact // } } gfan::ZCone* zc = PmCone2ZCone(&pc); res->rtyp = coneID; res->data = (char*) zc; return FALSE; } WerrorS("coneViaRays: unexpected parameters"); return TRUE; } BOOLEAN PMpolytopeViaVertices(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == INTMAT_CMD)) { polymake::perl::Object pp("Polytope"); intvec* points = (intvec*) u->Data(); // these will be vertices of or points in the polytope polymake::Matrix pmpoints = Intvec2PmMatrixInteger(points); leftv v = u->next; if ((v != NULL) && (v->Typ() == INT_CMD)) { int flag = (int) (long) v->Data(); switch(flag) { case 0: pp.take("POINTS") << pmpoints; // case means the matrix may contain points inside the polytope case 1: pp.take("VERTICES") << pmpoints; // case means the matrix only contains vertices of the polytope default: WerrorS("polytopeViaVertices: invalid flag"); } } else pp.take("POINTS") << pmpoints; // by default, we assume that matrix may contain non-vertices gfan::ZCone* zp = PmPolytope2ZPolytope(&pp); res->rtyp = polytopeID; res->data = (char*) zp; return FALSE; } WerrorS("polytopeViaVertices: unexpected parameters"); return TRUE; } BOOLEAN PMvertexAdjacencyGraph(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*) u->Data(); lists output=(lists)omAllocBin(slists_bin); output->Init(2); try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Matrix vert0 = p->give("VERTICES"); bigintmat* vert1 = PmMatrixInteger2Bigintmat(&vert0); output->m[0].rtyp = BIGINTMAT_CMD; output->m[0].data = (void*) vert1; polymake::Graph<> gr=p->give("GRAPH.ADJACENCY"); polymake::IncidenceMatrix adj = adjacency_matrix(gr); lists listOfEdges = PmIncidenceMatrix2ListOfIntvecs(&adj); output->m[1].rtyp = LIST_CMD; output->m[1].data = (void*) listOfEdges; delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = LIST_CMD; res->data = (void*) output; return FALSE; } WerrorS("vertexEdgeGraph: unexpected parameters"); return TRUE; } BOOLEAN PMvertexEdgeGraph(leftv res, leftv args) { leftv u = args; if ((u != NULL) && (u->Typ() == polytopeID)) { gfan::ZCone* zp = (gfan::ZCone*) u->Data(); lists output=(lists)omAllocBin(slists_bin); output->Init(2); try { polymake::perl::Object* p = ZPolytope2PmPolytope(zp); polymake::Matrix vert0 = p->give("VERTICES"); bigintmat* vert1 = PmMatrixInteger2Bigintmat(&vert0); output->m[0].rtyp = BIGINTMAT_CMD; output->m[0].data = (void*) vert1; polymake::Graph<> gr=p->give("GRAPH.ADJACENCY"); polymake::IncidenceMatrix adj = adjacency_matrix(gr); lists listOfEdges = PmAdjacencyMatrix2ListOfEdges(&adj); output->m[1].rtyp = LIST_CMD; output->m[1].data = (void*) listOfEdges; delete p; } catch (const std::exception& ex) { WerrorS("ERROR: "); WerrorS(ex.what()); WerrorS("\n"); return TRUE; } res->rtyp = LIST_CMD; res->data = (void*) output; return FALSE; } WerrorS("vertexEdgeGraph: unexpected parameters"); return TRUE; } #include // extern "C" void omp_set_num_threads(int num_threads); extern "C" int SI_MOD_INIT(polymake)(SModulFunctions* p) { omp_set_num_threads(1); // avoid multiple threads within polymake/libnormaliz if (init_polymake==NULL) {init_polymake = new polymake::Main();} init_polymake->set_application("fan"); // p->iiAddCproc("polymake.so","coneViaPoints",FALSE,PMconeViaRays); // p->iiAddCproc("polymake.so","polytopeViaPoints",FALSE,PMpolytopeViaVertices); p->iiAddCproc("polymake.so","isLatticePolytope",FALSE,PMisLatticePolytope); p->iiAddCproc("polymake.so","isBounded",FALSE,PMisBounded); p->iiAddCproc("polymake.so","isReflexive",FALSE,PMisReflexive); p->iiAddCproc("polymake.so","isGorenstein",FALSE,PMisGorenstein); p->iiAddCproc("polymake.so","gorensteinIndex",FALSE,PMgorensteinIndex); p->iiAddCproc("polymake.so","gorensteinVector",FALSE,PMgorensteinVector); p->iiAddCproc("polymake.so","isCanonical",FALSE,PMisCanonical); p->iiAddCproc("polymake.so","isTerminal",FALSE,PMisTerminal); p->iiAddCproc("polymake.so","isLatticeEmpty",FALSE,PMisLatticeEmpty); p->iiAddCproc("polymake.so","latticeVolume",FALSE,PMlatticeVolume); p->iiAddCproc("polymake.so","latticeDegree",FALSE,PMlatticeDegree); p->iiAddCproc("polymake.so","latticeCodegree",FALSE,PMlatticeCodegree); p->iiAddCproc("polymake.so","ehrhartPolynomialCoeff",FALSE,PMehrhartPolynomialCoeff); p->iiAddCproc("polymake.so","fVectorP",FALSE,PMfVector); p->iiAddCproc("polymake.so","hVector",FALSE,PMhVector); p->iiAddCproc("polymake.so","hStarVector",FALSE,PMhStarVector); p->iiAddCproc("polymake.so","isNormal",FALSE,PMisNormal); p->iiAddCproc("polymake.so","facetWidths",FALSE,PMfacetWidths); p->iiAddCproc("polymake.so","facetWidth",FALSE,PMfacetWidth); p->iiAddCproc("polymake.so","facetVertexLatticeDistances",FALSE,PMfacetVertexLatticeDistances); p->iiAddCproc("polymake.so","isCompressed",FALSE,PMisCompressed); p->iiAddCproc("polymake.so","isSmooth",FALSE,PMisSmooth); p->iiAddCproc("polymake.so","isVeryAmple",FALSE,PMisVeryAmple); p->iiAddCproc("polymake.so","latticePoints",FALSE,PMlatticePoints); p->iiAddCproc("polymake.so","nLatticePoints",FALSE,PMnLatticePoints); p->iiAddCproc("polymake.so","interiorLatticePoints",FALSE,PMinteriorLatticePoints); p->iiAddCproc("polymake.so","nInteriorLatticePoints",FALSE,PMnInteriorLatticePoints); p->iiAddCproc("polymake.so","boundaryLatticePoints",FALSE,PMboundaryLatticePoints); p->iiAddCproc("polymake.so","nBoundaryLatticePoints",FALSE,PMnBoundaryLatticePoints); p->iiAddCproc("polymake.so","hilbertBasis",FALSE,PMhilbertBasis); p->iiAddCproc("polymake.so","nHilbertBasis",FALSE,PMnHilbertBasis); p->iiAddCproc("polymake.so","minkowskiSum",FALSE,PMminkowskiSum); p->iiAddCproc("polymake.so","maximalFace",FALSE,PMmaximalFace); p->iiAddCproc("polymake.so","minimalFace",FALSE,PMminimalFace); p->iiAddCproc("polymake.so","maximalValue",FALSE,PMmaximalValue); p->iiAddCproc("polymake.so","minimalValue",FALSE,PMminimalValue); p->iiAddCproc("polymake.so","visual",FALSE,visual); p->iiAddCproc("polymake.so","normalFan",FALSE,normalFan); p->iiAddCproc("polymake.so","vertexAdjacencyGraph",FALSE,PMvertexAdjacencyGraph); p->iiAddCproc("polymake.so","vertexEdgeGraph",FALSE,PMvertexEdgeGraph); blackbox* b=getBlackboxStuff(polytopeID); b->blackbox_Op2=bbpolytope_Op2; init_polymake_help(); return MAX_TOK; } #endif /* HAVE_POLYMAKE */ singular-4.0.3+ds/Singular/dyn_modules/pyobject/000077500000000000000000000000001266270727000217025ustar00rootroot00000000000000singular-4.0.3+ds/Singular/dyn_modules/pyobject/Makefile.am000066400000000000000000000025701266270727000237420ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../../m4 if SI_BUILTIN_PYOBJECT noinst_LTLIBRARIES = pyobject.la ## moduledir = $(libdir)/singular P_PROCS_CPPFLAGS_COMMON = -DSTATIC_VERSION P_PROCS_MODULE_LDFLAGS = -module else !SI_BUILTIN_PYOBJECT module_LTLIBRARIES = pyobject.la moduledir = $(libexecdir)/singular/MOD P_PROCS_CPPFLAGS_COMMON = -DDYNAMIC_VERSION # Add under Mac OS X: -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup P_PROCS_MODULE_LDFLAGS = -module -export-dynamic -avoid-version -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup ### -export-dynamic -shared -module -avoid-version (add to all DMs?) endif !SI_BUILTIN_PYOBJECT ########################################################################## AM_CPPFLAGS = -I${top_srcdir} -I${top_builddir} -I${top_srcdir}/kernel -I${top_builddir}/kernel -I${top_srcdir}/libpolys -I${top_builddir}/libpolys $(FACTORY_INCLUDES) $(GMP_CFLAGS) $(NTL_CFLAGS) $(FLINT_CFLAGS) pyobject_la_SOURCES = pyobject.cc ### if HAVE_PYTHON??? pyobject_la_CXXFLAGS = $(PYTHON_CSPEC) pyobject_la_CPPFLAGS = $(PYTHON_CPPFLAGS) ${AM_CPPFLAGS} ${P_PROCS_CPPFLAGS_COMMON} pyobject_la_LDFLAGS = $(PYTHON_EXTRA_LIBS) $(PYTHON_LSPEC) ${AM_LDFLAGS} $(PYTHON_EXTRA_LDFLAGS) $(PYTHON_LDFLAGS) ${P_PROCS_MODULE_LDFLAGS} pyobject_la_LIBADD = $(PYTHON_EXTRA_LIBS) $(PYTHON_LSPEC) $(PYTHON_EXTRA_LDFLAGS) $(PYTHON_LDFLAGS) singular-4.0.3+ds/Singular/dyn_modules/pyobject/pyobject.cc000066400000000000000000000453751266270727000240460ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file pyobject.cc * * @author Alexander Dreyer * @date 2010-12-15 * * This file defines the @c blackbox operations for the pyobject type. * * @par Copyright: * (c) 2010 by The Singular Team, see LICENSE file **/ //***************************************************************************** #include #ifdef HAVE_PYTHON #include #include #include #include #include #include #include #include #include #include #include #include // #include // std::distance // #include void sync_contexts(); /** @class PythonInterpreter * This class initializes and finalized the python interpreter. * * It also stores the Singular token number, which is assigned to this type on * runtime. **/ class PythonInterpreter { public: typedef int id_type; ~PythonInterpreter() { if(m_owns_python) Py_Finalize(); } /// Initialize unique (singleton) python interpreter instance, /// and set Singular type identifier static void init(id_type num) { instance().m_id = num; } /// Get Singular type identitfier static id_type id() { return instance().m_id; } private: /// Singleton: Only init() is allowed to construct an instance PythonInterpreter(): m_id(0), m_owns_python(false) { start_python(); } /// Static initialization - /// safely takes care of destruction on program termination static PythonInterpreter& instance() { static PythonInterpreter init_interpreter; return init_interpreter; } void start_python() { if (!Py_IsInitialized()) init_python(); set_python_defaults(); } void init_python() { Py_Initialize(); m_owns_python = true; } void set_python_defaults() { // Sone python modules needs argc, argv set for some reason char* argv = (char*)""; PySys_SetArgv(1, &argv); PyRun_SimpleString("from sys import path, modules"); PyRun_SimpleString("_SINGULAR_IMPORTED = dict()"); char cmd[MAXPATHLEN + 20]; sprintf(cmd, "path.insert(0, '%s')", feGetResource('b')); PyRun_SimpleString(cmd); PyRun_SimpleString("del path"); // cleanup } id_type m_id; bool m_owns_python; }; /** @class PythonObject * This class defines an interface for calling PyObject from Singular. * * @note This class does not take care of the memory mangement, this is done in * the blackbox routines. **/ class PythonObject { typedef PythonObject self; public: typedef PyObject* ptr_type; struct sequence_tag{}; PythonObject(): m_ptr(Py_None) { } PythonObject(ptr_type ptr): m_ptr(ptr) { if (!ptr && handle_exception()) m_ptr = Py_None; } ptr_type check_context(ptr_type ptr) const { if(ptr) sync_contexts(); return ptr; } /// Unary operations self operator()(int op) const { switch(op) { case '(': return check_context(PyObject_CallObject(*this, NULL)); case ATTRIB_CMD: return PyObject_Dir(*this); case PROC_CMD: return *this; } if (op == PythonInterpreter::id()) return *this; return self(NULL); } /// Binary and n-ary operations self operator()(int op, const self& arg) const { switch(op) { case '+': return PyNumber_Add(*this, arg); case '-': return PyNumber_Subtract(*this, arg); case '*': return PyNumber_Multiply(*this, arg); case '/': return PyNumber_Divide(*this, arg); case '^': return PyNumber_Power(*this, arg, Py_None); case '(': return check_context(PyObject_CallObject(*this, arg)); case '[': return operator[](arg); case KILLATTR_CMD: return del_attr(arg); case LIST_CMD: return args2list(arg); case '.': case COLONCOLON: case ATTRIB_CMD: return attr(arg); } return self(NULL); } /// Ternary operations self operator()(int op, const self& arg1, const self& arg2) const { switch(op) { case ATTRIB_CMD: if(PyObject_SetAttr(*this, arg1, arg2) == -1) handle_exception(); return self(); } return self(NULL); } /// Get item self operator[](const self& idx) const { return PyObject_GetItem(*this, idx); } self operator[](long idx) const { return operator[](PyInt_FromLong(idx)); } /// Get actual PyObject* operator const ptr_type() const { return m_ptr; } /// Get representative as C-style string char* repr() const { return omStrDup(PyString_AsString(PyObject_Repr(*this))); } /// Extract C-style string char* str() const { return omStrDup(PyString_AsString(*this)); } Py_ssize_t size() const { return PyObject_Size(m_ptr); } BOOLEAN assign_to(leftv result) { return (m_ptr? (m_ptr == Py_None? none_to(result): python_to(result)): TRUE); } void import_as(const char* name) const { idhdl handle = enterid(omStrDup(name), 0, DEF_CMD, &IDROOT, FALSE); if (handle) { IDDATA(handle) = (char*)m_ptr; Py_XINCREF(m_ptr); IDTYP(handle) = PythonInterpreter::id(); } else { Werror("Importing pyobject to Singular failed"); } } int compare(int op, const self& arg) const { return PyObject_RichCompareBool(*this, arg, py_opid(op)); } self attr(const self& arg) const { return PyObject_GetAttr(*this, arg); } self del_attr(const self& arg) const { if (!PyObject_HasAttr(*this, arg)) Werror("Cannot delete attribute %s.", arg.repr()); else PyObject_DelAttr(*this, arg); return self(); } protected: self args2list(const self& args) const { self pylist(PyList_New(0)); PyList_Append(pylist, *this); if(PyTuple_Check(args)) pylist.append_iter(PyObject_GetIter(args)); else PyList_Append(pylist, args); return pylist; } BOOLEAN handle_exception() const { if(!PyErr_Occurred()) return FALSE; PyObject *pType, *pMessage, *pTraceback; PyErr_Fetch(&pType, &pMessage, &pTraceback); WerrorS("pyobject error occured"); WerrorS(PyString_AsString(pMessage)); Py_XDECREF(pType); Py_XDECREF(pMessage); Py_XDECREF(pTraceback); PyErr_Clear(); return TRUE; } void append_iter(self iterator) { ptr_type item; while ((item = PyIter_Next(iterator))) { PyList_Append(*this, item); Py_DECREF(item); } } int py_opid(int op) const{ switch(op) { case '<': return Py_LT; case '>': return Py_GT; case EQUAL_EQUAL: return Py_EQ; case NOTEQUAL: return Py_NE; case GE: return Py_GE; case LE: return Py_LE; } return -1; } private: BOOLEAN none_to(leftv result) const { Py_XDECREF(m_ptr); result->data = NULL; result->rtyp = NONE; return FALSE; } BOOLEAN python_to(leftv result) const { result->data = m_ptr; Py_XINCREF(m_ptr); result->rtyp = PythonInterpreter::id(); return !m_ptr; } /// The actual pointer ptr_type m_ptr; }; /** @class PythonCastStatic * This template class does conversion of Singular objects to python objects on * compile-time. * * @note The Singular objects are assumed to be equivalent to the template argument. **/ template class PythonCastStatic: public PythonObject { typedef PythonCastStatic self; public: PythonCastStatic(void* value): PythonObject(get(reinterpret_cast(value))) {} PythonCastStatic(leftv value): PythonObject(get(reinterpret_cast(value->Data()))) {} private: ptr_type get(ptr_type value) { return value; } ptr_type get(long value) { return PyInt_FromLong(value); } ptr_type get(int value) { return PyInt_FromLong((long)value); } ptr_type get(const char* value) { return PyString_FromString(value); } ptr_type get(char* value) { return get(const_cast(value)); } ptr_type get(intvec* value); // inlined below ptr_type get(lists value); // inlined after PythonObjectDynamic }; template inline PythonObject::ptr_type PythonCastStatic::get(intvec* value) { ptr_type pylist(PyList_New(0)); for (int idx = 0; idx < value->length(); ++idx) PyList_Append(pylist, self::get((*value)[idx])); return pylist; } /** @class PythonCastDynamic * This class does conversion of Singular objects to python objects on runtime. * **/ class PythonCastDynamic: public PythonObject { typedef PythonCastDynamic self; public: PythonCastDynamic(leftv value): PythonObject(get(value, value->Typ())) {} private: PythonObject get(leftv value, int typeId) { if (typeId == PythonInterpreter::id()) return PythonCastStatic<>(value); switch (typeId) { case INT_CMD: return PythonCastStatic(value); case STRING_CMD: return PythonCastStatic(value); case LIST_CMD: return PythonCastStatic(value); case INTVEC_CMD: return PythonCastStatic(value); } sleftv tmp; BOOLEAN newstruct_Assign_user(int, leftv, leftv); // declaring overloaded '=' if (!newstruct_Assign_user(PythonInterpreter::id(), &tmp, value)) return PythonCastStatic<>(&tmp); if (typeId > MAX_TOK) // custom types { blackbox *bbx = getBlackboxStuff(typeId); assume(bbx != NULL); if (! bbx->blackbox_Op1(PythonInterpreter::id(), &tmp, value)) return PythonCastStatic<>(&tmp); } Werror("type '%s` incompatible with 'pyobject`", iiTwoOps(typeId)); return PythonObject(); } }; template inline PythonObject::ptr_type PythonCastStatic::get(lists value) { ptr_type pylist(PyList_New(0)); for (int i = 0; i <= value->nr; ++i) PyList_Append(pylist, PythonCastDynamic((value->m) + i)); return pylist; } /// Template specialization for getting handling sequence template <> class PythonCastStatic: public PythonObject { public: PythonCastStatic(leftv value): PythonObject(PyTuple_New(size(value))) { append_to(value); } private: size_t size(leftv iter, size_t distance = 0) const { if (iter) { do { ++distance; } while((iter = iter->next)); }; return distance; } void append_to(leftv iter) const { for(size_t idx = 0; iter != NULL; iter = iter->next) PyTuple_SetItem(*this, idx++, PythonCastDynamic(iter)); } }; PythonObject get_attrib_name(leftv arg) { typedef PythonCastStatic result_type; if (arg->Typ() == STRING_CMD) return result_type(arg); return result_type((void*)arg->Name()); } /// Evaluate string in python PythonObject python_eval(const char* arg) { PyObject* globals = PyModule_GetDict(PyImport_Import(PyString_FromString("__main__"))); return PyRun_String(arg, Py_eval_input, globals, globals); } /// Evaluate string in python from Singular BOOLEAN python_eval(leftv result, leftv arg) { if ( !arg || (arg->Typ() != STRING_CMD) ) { Werror("expected python_eval('string')"); return TRUE; } return python_eval(reinterpret_cast(arg->Data())).assign_to(result); } /// Execute string in python from Singular BOOLEAN python_run(leftv result, leftv arg) { if ( !arg || (arg->Typ() != STRING_CMD) ) { Werror("expected python_run('string')"); return TRUE; } PyRun_SimpleString(reinterpret_cast(arg->Data())); sync_contexts(); Py_INCREF(Py_None); return PythonCastStatic<>(Py_None).assign_to(result); } PythonObject names_from_module(const char* module_name) { char buffer[strlen(module_name) + 30]; sprintf (buffer, "SINGULAR_MODULE_NAME = '%s'", module_name); PyRun_SimpleString(buffer); PyRun_SimpleString("from sys import modules"); PyRun_SimpleString("exec('from ' + SINGULAR_MODULE_NAME + ' import *')"); return python_eval("[str for str in dir(modules[SINGULAR_MODULE_NAME]) if str[0] != '_']"); } void from_module_import_all(const char* module_name) { char buffer[strlen(module_name) + 20]; sprintf (buffer, "from %s import *", module_name); PyRun_SimpleString(buffer); } /// import python module and export identifiers in Singular namespace BOOLEAN python_import(leftv result, leftv value) { if ((value == NULL) || (value->Typ()!= STRING_CMD)) { Werror("expected python_import('string')"); return TRUE; } from_module_import_all(reinterpret_cast(value->Data())); sync_contexts(); Py_INCREF(Py_None); return PythonCastStatic<>(Py_None).assign_to(result); } /// blackbox support - initialization void* pyobject_Init(blackbox*) { Py_INCREF(Py_None); return Py_None; } /// blackbox support - convert to string representation char* pyobject_String(blackbox *b, void* ptr) { return PythonCastStatic<>(ptr).repr(); } /// blackbox support - copy element void* pyobject_Copy(blackbox*b, void* ptr) { Py_XINCREF(ptr); return ptr; } /// blackbox support - assign element BOOLEAN pyobject_Assign(leftv l, leftv r) { Py_XDECREF(l->Data()); PyObject* result = PythonCastDynamic(r); Py_XINCREF(result); if (l->rtyp == IDHDL) IDDATA((idhdl)l->data) = (char *)result; else l->data = (void *)result; return !result; } /// blackbox support - unary operations BOOLEAN pyobject_Op1(int op, leftv res, leftv head) { switch(op) { case INT_CMD: // built-in return types first { long value = PyInt_AsLong(PythonCastStatic<>(head)); if( (value == -1) && PyErr_Occurred() ) { Werror("'pyobject` cannot be converted to integer"); PyErr_Clear(); return TRUE; } res->data = (void*) value; res->rtyp = INT_CMD; return FALSE; } case TYPEOF_CMD: res->data = (void*) omStrDup("pyobject"); res->rtyp = STRING_CMD; return FALSE; } if (!PythonCastStatic<>(head)(op).assign_to(res)) return FALSE; BOOLEAN newstruct_Op1(int, leftv, leftv); // forward declaration return newstruct_Op1(op, res, head); } /// blackbox support - binary operations BOOLEAN pyobject_Op2(int op, leftv res, leftv arg1, leftv arg2) { PythonCastStatic<> lhs(arg1); switch(op) // built-in return types and special cases first { case '<': case '>': case EQUAL_EQUAL: case NOTEQUAL: case GE: case LE: { res->data = (void *)(long)(lhs.compare(op, PythonCastDynamic(arg2))); res->rtyp = INT_CMD; return FALSE; } case '.': case COLONCOLON: case ATTRIB_CMD: return lhs.attr(get_attrib_name(arg2)).assign_to(res); } PythonCastDynamic rhs(arg2); if (!lhs(op, rhs).assign_to(res)) return FALSE; BOOLEAN newstruct_Op2(int, leftv, leftv, leftv); // forward declaration return newstruct_Op2(op, res, arg1, arg2); } /// blackbox support - ternary operations BOOLEAN pyobject_Op3(int op, leftv res, leftv arg1, leftv arg2, leftv arg3) { PythonCastStatic<> lhs(arg1); PythonCastDynamic rhs1(arg2); PythonCastDynamic rhs2(arg3); if (!lhs(op, rhs1, rhs2).assign_to(res)) return FALSE; return blackboxDefaultOp3(op, res, arg1, arg2, arg3); } /// blackbox support - n-ary operations BOOLEAN pyobject_OpM(int op, leftv res, leftv args) { switch(op) // built-in return types first { case STRING_CMD: { blackbox* a = getBlackboxStuff(args->Typ()); res->data = (void *)a->blackbox_String(a, args->Data()); res->rtyp = STRING_CMD; return FALSE; } case INTVEC_CMD: PythonObject obj = PythonCastStatic<>(args->Data()); unsigned long len = obj.size(); intvec* vec = new intvec(len); for(unsigned long idx = 0; idx != len; ++idx) { long value = PyInt_AsLong(obj[idx]); (*vec)[idx] = static_cast(value); if ((value == -1) && PyErr_Occurred()) { value = 0; PyErr_Clear(); } if (value != long((*vec)[idx])) { delete vec; Werror("'pyobject` cannot be converted to intvec"); return TRUE; } } res->data = (void *)vec; res->rtyp = op; return FALSE; } typedef PythonCastStatic seq_type; if (! PythonCastStatic<>(args)(op, seq_type(args->next)).assign_to(res)) return FALSE; BOOLEAN newstruct_OpM(int, leftv, leftv); // forward declaration return newstruct_OpM(op, res, args); } /// blackbox support - destruction void pyobject_destroy(blackbox *b, void* ptr) { Py_XDECREF(ptr); } PyObject* get_current_definition(const char* name) { idhdl handle = ggetid(name); if (!handle || (IDTYP(handle) != PythonInterpreter::id())) return NULL; PythonCastStatic value(IDDATA(handle)); return value; } /// getting stuff from python to Singular namespace void sync_contexts() { PyRun_SimpleString("_SINGULAR_NEW = modules['__main__'].__dict__.copy()"); PythonObject newElts = python_eval("[(_k, _e) \ for (_k, _e) in _SINGULAR_NEW.iteritems() \ if _k not in _SINGULAR_IMPORTED or not _SINGULAR_IMPORTED[_k] is _e]"); long len = newElts.size(); for (long idx = 0; idx < len; ++idx) { long i = 0; char* name = newElts[idx][i].str(); if (name && (*name != '\0') && (*name != '_')) { Py_XDECREF(get_current_definition(name)); i = 1; newElts[idx][i].import_as(name); } } PythonObject deletedElts = python_eval("list(set(_SINGULAR_IMPORTED.iterkeys()) - \ set(_SINGULAR_NEW.iterkeys()))"); len = deletedElts.size(); for (long idx = 0; idx < len; ++idx) { char* name = deletedElts[idx].str(); if (name && (*name != '\0') && (*name != '_')) killid(name, &IDROOT); } PyRun_SimpleString("_SINGULAR_IMPORTED =_SINGULAR_NEW"); PyRun_SimpleString("del _SINGULAR_NEW"); } blackbox* pyobject_blackbox(int& tok) { if(blackboxIsCmd("pyobject", tok) != ROOT_DECL) { tok = setBlackboxStuff((blackbox*)omAlloc0(sizeof(blackbox)), "pyobject"); } return getBlackboxStuff(tok); } #define PYOBJECT_ADD_C_PROC(name) \ psModulFunctions->iiAddCproc((currPack->libname? currPack->libname: ""),\ (char*)#name, FALSE, name); extern "C" int SI_MOD_INIT(pyobject)(SModulFunctions* psModulFunctions) { int tok = -1; blackbox* bbx = pyobject_blackbox(tok); if (bbx->blackbox_Init != pyobject_Init) { bbx->blackbox_destroy = pyobject_destroy; bbx->blackbox_String = pyobject_String; bbx->blackbox_Init = pyobject_Init; bbx->blackbox_Copy = pyobject_Copy; bbx->blackbox_Assign = pyobject_Assign; bbx->blackbox_Op1 = pyobject_Op1; bbx->blackbox_Op2 = pyobject_Op2; bbx->blackbox_Op3 = pyobject_Op3; bbx->blackbox_OpM = pyobject_OpM; bbx->data = (void*)omAlloc0(newstruct_desc_size()); PythonInterpreter::init(tok); PYOBJECT_ADD_C_PROC(python_import); PYOBJECT_ADD_C_PROC(python_eval); PYOBJECT_ADD_C_PROC(python_run); } return MAX_TOK; } #undef PYOBJECT_ADD_C_PROC #endif /* HAVE_PYTHON */ singular-4.0.3+ds/Singular/dyn_modules/singmathic/000077500000000000000000000000001266270727000222115ustar00rootroot00000000000000singular-4.0.3+ds/Singular/dyn_modules/singmathic/Makefile.am000066400000000000000000000025421266270727000242500ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../../m4 if SI_BUILTIN_SINGMATHIC noinst_LTLIBRARIES=singmathic.la P_PROCS_CPPFLAGS_COMMON = -DSTATIC_VERSION P_PROCS_MODULE_LDFLAGS = -module else module_LTLIBRARIES=singmathic.la moduledir = $(libexecdir)/singular/MOD P_PROCS_CPPFLAGS_COMMON = -DDYNAMIC_VERSION P_PROCS_MODULE_LDFLAGS = -module -export-dynamic -avoid-version -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup # Add under Mac OS X: -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup endif MYINCLUDES = -I${top_srcdir} -I${top_builddir} \ -I${top_srcdir}/libpolys -I${top_builddir}/libpolys \ $(FACTORY_INCLUDES) $(RESOURCES_INCLUDES) $(OMALLOC_INCLUDES) \ $(FLINT_CFLAGS) $(NTL_CFLAGS) $(GMP_CFLAGS) $(CPPFLAGS) singmathic_la_SOURCES = singmathic.cc singmathic_la_CPPFLAGS = ${MYINCLUDES} ${P_PROCS_CPPFLAGS_COMMON} singmathic_la_LDFLAGS = ${P_PROCS_MODULE_LDFLAGS} ${MATHIC_LIBS} # AM_COLOR_TESTS=always # # TESTS_ENVIRONMENT = SINGULARPATH='${abs_top_builddir}/Singular/LIB:${abs_top_srcdir}/Singular/LIB:${abs_top_builddir}/libpolys/polys/.libs:${abs_top_builddir}/factory/gftables:${abs_builddir}/.libs:${abs_srcdir}' # TESTS_ENVIRONMENT += SINGULAR_ROOT_DIR='${abs_top_builddir}' # TESTS_ENVIRONMENT += SINGULAR_BIN_DIR='${abs_top_builddir}/Singular' # # TESTS=test_release.sh # # EXTRA_DIST = test.sh $(TESTS) singular-4.0.3+ds/Singular/dyn_modules/singmathic/singmathic.cc000066400000000000000000000377471266270727000246700ustar00rootroot00000000000000#include #ifdef HAVE_MATHICGB #include #include #include #include #include #include #include typedef mgb::GroebnerConfiguration::Coefficient Coefficient; typedef mgb::GroebnerConfiguration::VarIndex VarIndex; typedef mgb::GroebnerConfiguration::Exponent Exponent; typedef mgb::GroebnerConfiguration::BaseOrder BaseOrder; // Constructs a Singular ideal. class MathicToSingStream { public: MathicToSingStream(Coefficient modulus, VarIndex varCount): mModulus(modulus), mVarCount(varCount), mPolyCount(0), mTerm(0), mIdeal(0) {} ~MathicToSingStream() {deleteIdeal();} // Mathic stream interface Coefficient modulus() const {return mModulus;} VarIndex varCount() const {return mModulus;} void idealBegin(size_t polyCount) { deleteIdeal(); mIdeal = idInit(polyCount); mPolyCount = 0; } void appendPolynomialBegin(size_t termCount) {} void appendTermBegin(const mgb::GroebnerConfiguration::Component c) { if (mTerm == 0) mTerm = mIdeal->m[mPolyCount] = pInit(); else mTerm = mTerm->next = pInit(); pSetComp(mTerm,c); } void appendExponent(VarIndex index, Exponent exponent) { pSetExp(mTerm, index + 1, exponent); } void appendTermDone(Coefficient coefficient) { mTerm->coef = reinterpret_cast(coefficient); pSetm(mTerm); } void appendPolynomialDone() { ++mPolyCount; mTerm = 0; } void idealDone() {} // Singular interface ::ideal takeIdeal() { ::ideal id = mIdeal; mIdeal = 0; return id; } private: void deleteIdeal() { if (mIdeal != 0) { idDelete(&mIdeal); mIdeal = 0; } } const Coefficient mModulus; const VarIndex mVarCount; size_t mPolyCount; poly mTerm; ::ideal mIdeal; }; #include bool setOrder(ring r, mgb::GroebnerConfiguration& conf) { const VarIndex varCount = conf.varCount(); bool didSetComponentBefore = false; mgb::GroebnerConfiguration::BaseOrder baseOrder = mgb::GroebnerConfiguration::RevLexDescendingBaseOrder; std::vector gradings; for (int block = 0; r->order[block] != ringorder_no; ++block) { // *** ringorder_no const rRingOrder_t type = static_cast(r->order[block]); if (r->block0[block] < 0 || r->block1[block] < 0) { WerrorS("Unexpected negative block0/block1 in ring."); return false; } const VarIndex block0 = static_cast(r->block0[block]); const VarIndex block1 = static_cast(r->block1[block]); const int* const weights = r->wvhdl[block]; if (block0 > block1) { WerrorS("Unexpected block0 > block1 in ring."); return false; } // *** ringorder_c and ringorder_C if (type == ringorder_c || type == ringorder_C) { if (block0 != 0 || block1 != 0 || weights != 0) { WerrorS("Unexpected non-zero fields on c/C block in ring."); return false; } if (didSetComponentBefore) { WerrorS("Unexpected two c/C blocks in ring."); return false; } didSetComponentBefore = true; if (r->order[block + 1] == ringorder_no) { conf.setComponentBefore (mgb::GroebnerConfiguration::ComponentAfterBaseOrder); } else conf.setComponentBefore(gradings.size() / varCount); conf.setComponentsAscending(type == ringorder_C); continue; } if (block0 == 0 || block1 == 0) { WerrorS("Expected block0 != 0 and block1 != 0 in ring."); return false; } if (block1 > varCount) { // todo: first handle any block types where this is not true WerrorS("Expected block1 <= #vars in ring."); return false; } // dim is how many variables this block concerns. const size_t dim = static_cast(block1 - block0 + 1); // *** single-graded/ungraded lex/revlex orders // a(w): w-graded and that's it // a64(w): w-graded with 64-bit weights (not supported here) // lp: lex from left (descending) // Dp: 1-graded, lex from left (descending) // Ds: -1-graded, lex from left (descending) // Wp(w): w-graded, lex from left (descending) // Ws(w): -w-graded, lex from left (descending) // rp: lex from right (ascending) // rs: revlex from right (descending) // dp: 1-graded, revlex from right (descending) // ds: -1-graded, revlex from right (descending) // wp(w): w-graded, revlex from right (descending) // ws(w): -w-graded, revlex from right (descending) // ls: revlex from left (ascending) if (type == ringorder_a64) { WerrorS("Block type a64 not supported for MathicGB interface."); return false; } // * handle the single-grading part const bool oneGrading = (type == ringorder_Dp || type == ringorder_dp); const bool minusOneGrading = (type == ringorder_Ds || type == ringorder_ds); const bool wGrading = (type == ringorder_a || type == ringorder_Wp || type == ringorder_wp); const bool minusWGrading = (type == ringorder_ws || type == ringorder_Ws); if (oneGrading || minusOneGrading || wGrading || minusWGrading) { const VarIndex begin = gradings.size(); gradings.resize(begin + varCount); if (oneGrading || minusOneGrading) { if (weights != 0) { WerrorS("Expect wvhdl == 0 in Dp/dp/Ds/ds-block in ring."); return false; } const Exponent value = oneGrading ? 1 : -1; for (int var = block0 - 1; var < block1; ++var) gradings[begin + var] = value; } else { if (weights == 0) { WerrorS("Expect wvhdl != 0 in a/Wp/wp/ws/Ws-block in ring."); return false; } if (wGrading) { for (int var = 0; var < dim; ++var) gradings[begin + (block0 - 1) + var] = weights[var]; } else { for (int var = 0; var < dim; ++var) gradings[begin + (block0 - 1) + var] = -weights[var]; } } } if (type == ringorder_a) continue; // a has only the grading, so we are done already // * handle the lex/revlex part const bool lexFromLeft = type == ringorder_lp || type == ringorder_Dp || type == ringorder_Ds || type == ringorder_Wp || type == ringorder_Ws; const bool lexFromRight = type == ringorder_rp; const bool revlexFromLeft = type == ringorder_ls; const bool revlexFromRight = type == ringorder_rs || type == ringorder_dp || type == ringorder_ds || type == ringorder_wp || type == ringorder_ws; if (lexFromLeft || lexFromRight || revlexFromLeft || revlexFromRight) { const int next = r->order[block + 1]; bool final = next == ringorder_no; if (!final && r->order[block + 2] == ringorder_no) final = next == ringorder_c || next == ringorder_C; if (final) { if (lexFromRight) baseOrder = mgb::GroebnerConfiguration::LexAscendingBaseOrder; else if (revlexFromRight) baseOrder = mgb::GroebnerConfiguration::RevLexDescendingBaseOrder; else if (lexFromLeft) baseOrder = mgb::GroebnerConfiguration::LexDescendingBaseOrder; else baseOrder = mgb::GroebnerConfiguration::RevLexAscendingBaseOrder; continue; } const size_t begin = gradings.size(); gradings.resize(begin + dim * varCount); const Exponent value = (lexFromLeft || lexFromRight) ? 1 : -1; if (lexFromLeft || revlexFromLeft) { for (size_t row = 0; row < dim; ++row) gradings[begin + row * varCount + (block0 - 1) + row] = value; } else { for (size_t row = 0; row < dim; ++row) gradings[begin + row * varCount + (block1 - 1) - row] = value; } continue; } // *** ringorder_M: a square invertible matrix if (type == ringorder_M) { if (weights == 0) { WerrorS("Expected wvhdl != 0 in M-block in ring."); return false; } const size_t begin = gradings.size(); gradings.resize(begin + dim * varCount); for (size_t row = 0; row < dim; ++row) for (size_t col = block0 - 1; col < block1; ++col) gradings[begin + row * varCount + col] = weights[row * dim + col]; continue; } // *** Miscellaneous unsupported or invalid block types if ( type == ringorder_s || type == ringorder_S || type == ringorder_IS ) { // todo: Consider supporting this later. WerrorS("Schreyer order s/S/IS not supported in MathicGB interface."); return false; } if (type == ringorder_am) { // This block is a Schreyer-like ordering only used in Spielwiese. // todo: Consider supporting it later. WerrorS("Block type am not supported in MathicGB interface"); return false; } if (type == ringorder_L) { WerrorS("Invalid L-block found in order of ring."); return false; } if (type == ringorder_aa) { // I don't know what an aa block is supposed to do. WerrorS("aa ordering not supported by the MathicGB interface."); return false; } if (type == ringorder_unspec) { WerrorS("Invalid unspec-block found in order of ring."); return false; } WerrorS("Unknown block type found in order of ring."); return false; } if (!didSetComponentBefore) { WerrorS("Expected to find a c/C block in ring."); return false; } if (!conf.setMonomialOrder(baseOrder, gradings)) { WerrorS("MathicGB does not support non-global orders."); return false; } return true; } bool prOrderMatrix(ring r) { const int varCount = r->N; mgb::GroebnerConfiguration conf(101, varCount,0); if (!setOrder(r, conf)) return false; const std::vector& gradings = conf.monomialOrder().second; if (gradings.size() % varCount != 0) { WerrorS("Expected matrix to be a multiple of varCount."); return false; } const size_t rowCount = gradings.size() / varCount; std::cout << "Order matrix:\n"; for (size_t row = 0; row < rowCount; ++row) { for (size_t col = 0; col < varCount; ++col) std::cerr << ' ' << gradings[row * varCount + col]; std::cerr << '\n'; } std::cerr << "Base order: " << mgb::GroebnerConfiguration::baseOrderName(conf.monomialOrder().first) << '\n'; std::cerr << "Component before: " << conf.componentBefore() << '\n'; std::cerr << "Components ascending: " << conf.componentsAscending() << '\n'; std::cerr << "Schreyering: " << conf.schreyering() << '\n'; } void prOrder(ring r) { std::cout << "Printing order of ring.\n"; for (int block = 0; ; ++block) { switch (r->order[block]) { case ringorder_no: // end of blocks return; case ringorder_a: std::cout << "a"; break; case ringorder_a64: ///< for int64 weights std::cout << "a64"; break; case ringorder_c: std::cout << "c"; break; case ringorder_C: std::cout << "C"; break; case ringorder_M: std::cout << "M"; break; case ringorder_S: ///< S? std::cout << "S"; break; case ringorder_s: ///< s? std::cout << "s"; break; case ringorder_lp: std::cout << "lp"; break; case ringorder_dp: std::cout << "dp"; break; case ringorder_rp: std::cout << "rp"; break; case ringorder_Dp: std::cout << "Dp"; break; case ringorder_wp: std::cout << "wp"; break; case ringorder_Wp: std::cout << "Wp"; break; case ringorder_ls: std::cout << "ls"; // not global break; case ringorder_ds: std::cout << "ds"; // not global break; case ringorder_Ds: std::cout << "Ds"; // not global break; case ringorder_ws: std::cout << "ws"; // not global break; case ringorder_Ws: std::cout << "Ws"; // not global break; case ringorder_am: std::cout << "am"; break; case ringorder_L: std::cout << "L"; break; // the following are only used internally case ringorder_aa: ///< for idElimination, like a, except pFDeg, pWeigths ignore it std::cout << "aa"; break; case ringorder_rs: ///< opposite of ls std::cout << "rs"; break; case ringorder_IS: ///< Induced (Schreyer) ordering std::cout << "IS"; break; case ringorder_unspec: std::cout << "unspec"; break; } const int b0 = r->block0[block]; const int b1 = r->block1[block]; std::cout << ' ' << b0 << ':' << b1 << " (" << r->wvhdl[block] << ")" << std::flush; if (r->wvhdl[block] != 0 && b0 != 0) { for (int v = 0; v <= b1 - b0; ++v) std::cout << ' ' << r->wvhdl[block][v]; } else std::cout << " null"; std::cout << '\n'; } } BOOLEAN prOrderX(leftv result, leftv arg) { if (currRing == 0) { WerrorS("There is no current ring."); return TRUE; } prOrder(currRing); prOrderMatrix(currRing); result->rtyp=NONE; return FALSE; } BOOLEAN mathicgb(leftv result, leftv arg) { result->rtyp=NONE; if (arg == NULL || arg->next != NULL || ((arg->Typ() != IDEAL_CMD) &&(arg->Typ() != MODUL_CMD))){ WerrorS("Syntax: mathicgb(/)"); return TRUE; } if (!rField_is_Zp(currRing)) { WerrorS("Polynomial ring must be over Zp."); return TRUE; } const int characteristic = n_GetChar(currRing); const int varCount = currRing->N; const ideal I=(ideal) arg->Data(); mgb::GroebnerConfiguration conf(characteristic, varCount,I->rank); conf.setMaxThreadCount(0); // default number of cores if (!setOrder(currRing, conf)) return TRUE; if (TEST_OPT_PROT) conf.setLogging("all"); mgb::GroebnerInputIdealStream toMathic(conf); const ideal id = static_cast(arg->Data()); const int size = IDELEMS(id); toMathic.idealBegin(size); for (int i = 0; i < size; ++i) { const poly origP = id->m[i]; int termCount = 0; for (poly p = origP; p != 0; p = pNext(p)) ++termCount; toMathic.appendPolynomialBegin(termCount); for (poly p = origP; p != 0; p = pNext(p)) { toMathic.appendTermBegin(pGetComp(p)); for (int i = 1; i <= currRing->N; ++i) toMathic.appendExponent(i - 1, pGetExp(p, i)); const long coefLong = reinterpret_cast(pGetCoeff(p)); toMathic.appendTermDone(static_cast(coefLong)); } toMathic.appendPolynomialDone(); } toMathic.idealDone(); MathicToSingStream fromMathic(characteristic, varCount); mgb::computeGroebnerBasis(toMathic, fromMathic); result->rtyp = arg->Typ(); result->data = fromMathic.takeIdeal(); return FALSE; } template class std::vector; template void mgb::computeGroebnerBasis (mgb::GroebnerInputIdealStream&, MathicToSingStream&); extern "C" int SI_MOD_INIT(singmathic)(SModulFunctions* psModulFunctions) { psModulFunctions->iiAddCproc( (currPack->libname ? currPack->libname : ""), "mathicgb", FALSE, mathicgb ); psModulFunctions->iiAddCproc( (currPack->libname ? currPack->libname : ""), "mathicgb_prOrder", FALSE, prOrderX ); return MAX_TOK; } /* #else int SI_MOD_INIT(singmathic)(SModulFunctions* psModulFunctions) { WerrorS( "Cannot initialize the Singular interface to MathicGB " "as this Singular executable was built without support " "for MathicGB." ); return 1; } */ /* ressources: ------------------------------------------------------------ http://stackoverflow.com/questions/3786408/number-of-threads-used-by-intel-tbb When you create the scheduler, you can specify the number of threads as tbb::task_scheduler_init init(nthread); How do I know how many threads are available? Do not ask! Not even the scheduler knows how many threads really are available There may be other processes running on the machine Routine may be nested inside other parallel routines conf.setMaxThreadCount(0); // default number of cores */ #endif /* HAVE_MATHICGB */ singular-4.0.3+ds/Singular/dyn_modules/staticdemo/000077500000000000000000000000001266270727000222175ustar00rootroot00000000000000singular-4.0.3+ds/Singular/dyn_modules/staticdemo/Makefile.am000066400000000000000000000012121266270727000242470ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../../m4 if SI_BUILTIN_STATICDEMO noinst_LTLIBRARIES=staticdemo.la P_PROCS_MODULE_LDFLAGS = -module P_PROCS_CPPFLAGS_COMMON = -DSTATIC_VERSION MYINCLUDES = -I${top_srcdir} -I${top_builddir} \ -I${top_srcdir}/libpolys -I${top_builddir}/libpolys \ $(FACTORY_INCLUDES) $(RESOURCES_INCLUDES) $(OMALLOC_INCLUDES) \ $(FLINT_CFLAGS) $(NTL_CFLAGS) $(GMP_CFLAGS) $(GOOGLE_PERFTOOLS_CFLAGS) staticdemo_la_SOURCES = staticdemo.cc staticdemo_la_CPPFLAGS = ${MYINCLUDES} ${P_PROCS_CPPFLAGS_COMMON} staticdemo_la_LDFLAGS = ${AM_LDFLAGS} ${P_PROCS_MODULE_LDFLAGS} else EXTRA_DIST=staticdemo.cc endif singular-4.0.3+ds/Singular/dyn_modules/staticdemo/staticdemo.cc000066400000000000000000000005551266270727000246670ustar00rootroot00000000000000#include #include #include class SModulFunctions; #ifndef STATIC_VERSION # error This is a demo static module. It is not supposed to be built dynamically... #endif #include extern "C" int SI_MOD_INIT(staticdemo)(SModulFunctions*){ PrintS("init of staticdemo\n"); return (MAX_TOK); } singular-4.0.3+ds/Singular/dyn_modules/syzextra/000077500000000000000000000000001266270727000217545ustar00rootroot00000000000000singular-4.0.3+ds/Singular/dyn_modules/syzextra/DebugPrint.cc000066400000000000000000000050741266270727000243340ustar00rootroot00000000000000// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file DebugPrint.cc * * Here we implement dPrint-s. * * ABSTRACT: debug-detailed-printing * * @author Oleksandr Motsak * * **/ /*****************************************************************************/ // include header file #include #include "DebugPrint.h" #include #include #include BEGIN_NAMESPACE() /// debug-print monomial poly/vector p, assuming that it lives in the ring R static inline void m_DebugPrint(const poly p, const ring R) { Print("\nexp[0..%d]\n", R->ExpL_Size - 1); for(int i = 0; i < R->ExpL_Size; i++) Print("%09lx ", p->exp[i]); PrintLn(); Print("v0:%9ld ", p_GetComp(p, R)); for(int i = 1; i <= R->N; i++) Print(" v%d:%5ld",i, p_GetExp(p, i, R)); PrintLn(); } END_NAMESPACE BEGIN_NAMESPACE_SINGULARXX BEGIN_NAMESPACE(DEBUG) // debug-print at most nTerms (2 by default) terms from poly/vector p, // assuming that lt(p) lives in lmRing and tail(p) lives in tailRing. void dPrint(const poly p, const ring lmRing, const ring tailRing, const int nTerms) { assume( nTerms >= 0 ); if( p != NULL ) { assume( p != NULL ); p_Write(p, lmRing, tailRing); if( (p != NULL) && (nTerms > 0) ) { assume( p != NULL ); assume( nTerms > 0 ); // debug pring leading term m_DebugPrint(p, lmRing); poly q = pNext(p); // q = tail(p) // debug pring tail (at most nTerms-1 terms from it) for(int j = nTerms - 1; (q !=NULL) && (j > 0); pIter(q), --j) m_DebugPrint(q, tailRing); if (q != NULL) PrintS("...\n"); } } else PrintS("0\n"); } // output an ideal void dPrint(const ideal id, const ring lmRing, const ring tailRing, const int nTerms) { assume( nTerms >= 0 ); if( id == NULL ) PrintS("(NULL)"); else { Print("Module of rank %ld,real rank %ld and %d generators.\n", id->rank,id_RankFreeModule(id, lmRing, tailRing),IDELEMS(id)); int j = (id->ncols*id->nrows) - 1; while ((j > 0) && (id->m[j]==NULL)) j--; for (int i = 0; i <= j; i++) { Print("generator %d: ",i); dPrint(id->m[i], lmRing, tailRing, nTerms); } } } END_NAMESPACE END_NAMESPACE_SINGULARXX // Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab singular-4.0.3+ds/Singular/dyn_modules/syzextra/DebugPrint.h000066400000000000000000000024021266270727000241660ustar00rootroot00000000000000// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file DebugPrint.h * * Detailed print for debugging * * ABSTRACT: dPrint outputs as much info as possible * * @author Oleksandr Motsak * * **/ /*****************************************************************************/ #ifndef DEBUGPRINT_H #define DEBUGPRINT_H // include basic definitions #include "singularxx_defs.h" #include BEGIN_NAMESPACE_SINGULARXX BEGIN_NAMESPACE(DEBUG) /// debug-print at most nTerms (2 by default) terms from poly/vector p, /// assuming that lt(p) lives in lmRing and tail(p) lives in tailRing. void dPrint(const poly p, const ring lmRing = currRing, const ring tailRing = currRing, const int nTerms = 2); /// prints an ideal, optionally with details void dPrint(const ideal id, const ring lmRing = currRing, const ring tailRing = currRing, const int nTerms = 0); END_NAMESPACE END_NAMESPACE_SINGULARXX #endif /* #ifndef DEBUGPRINT_H */ // Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab singular-4.0.3+ds/Singular/dyn_modules/syzextra/Makefile.am000066400000000000000000000030411266270727000240060ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../../m4 MYINCLUDES = -I${top_srcdir} -I${top_builddir} \ -I${top_srcdir}/libpolys -I${top_builddir}/libpolys \ $(FACTORY_INCLUDES) $(RESOURCES_INCLUDES) $(OMALLOC_INCLUDES) \ $(FLINT_CFLAGS) $(NTL_CFLAGS) $(GMP_CFLAGS) $(GOOGLE_PERFTOOLS_CFLAGS) if SI_BUILTIN_SYZEXTRA noinst_LTLIBRARIES=syzextra.la P_PROCS_CPPFLAGS_COMMON = -DSTATIC_VERSION P_PROCS_MODULE_LDFLAGS = -module else module_LTLIBRARIES=syzextra.la moduledir = $(libexecdir)/singular/MOD P_PROCS_CPPFLAGS_COMMON = -DDYNAMIC_VERSION # Add under Mac OS X: -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup P_PROCS_MODULE_LDFLAGS = -module -export-dynamic -avoid-version -flat_namespace -weak_reference_mismatches weak -undefined dynamic_lookup endif SOURCES = mod_main.cc DebugPrint.cc DebugPrint.h myNF.cc myNF.h singularxx_defs.h syzextra.cc syzextra.h syzextra_la_SOURCES = $(SOURCES) syzextra_la_CPPFLAGS = ${MYINCLUDES} ${P_PROCS_CPPFLAGS_COMMON} syzextra_la_LDFLAGS = ${AM_LDFLAGS} ${P_PROCS_MODULE_LDFLAGS} ${GOOGLE_PERFTOOL_LDFLAGS} AM_COLOR_TESTS=always TESTS_ENVIRONMENT = SINGULARPATH='${abs_top_builddir}/Singular/LIB:${abs_top_srcdir}/Singular/LIB:${abs_top_builddir}/libpolys/polys/.libs:${abs_top_builddir}/factory/gftables:${abs_builddir}/.libs:${abs_srcdir}' TESTS_ENVIRONMENT += SINGULAR_ROOT_DIR='${abs_top_builddir}' TESTS_ENVIRONMENT += SINGULAR_BIN_DIR='${abs_top_builddir}/Singular' TESTS=test_release.sh EXTRA_DIST = test.sh $(TESTS) # syzextra.tst ederc.tst test_clear_enum.tst CLEANFILES = SimpleTests.json singular-4.0.3+ds/Singular/dyn_modules/syzextra/mod_main.cc000066400000000000000000001350601266270727000240530ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include // #include #include #include #include #include #include #include #include #include #include // For iiAddCproc // extern coeffs coeffs_BIGINT #include "singularxx_defs.h" #include "DebugPrint.h" #include "myNF.h" #include "syzextra.h" #include #if GOOGLE_PROFILE_ENABLED #include #endif // #if GOOGLE_PROFILE_ENABLED #include #include #include extern void pISUpdateComponents(ideal F, const intvec *const V, const int MIN, const ring r); // extern ring rCurrRingAssure_SyzComp(); extern ring rAssure_InducedSchreyerOrdering(const ring r, BOOLEAN complete, int sign); extern int rGetISPos(const int p, const ring r); // USING_NAMESPACE_SINGULARXX; USING_NAMESPACE( SINGULARXXNAME :: DEBUG ) USING_NAMESPACE( SINGULARXXNAME :: NF ) USING_NAMESPACE( SINGULARXXNAME :: SYZEXTRA ) BEGIN_NAMESPACE_NONAME // returns TRUE, if idRankFreeModule(m) > 0 ??? /// test whether this input has vectors among entries or no enties /// result must be FALSE for only 0-entries static BOOLEAN id_IsModule(ideal id, ring r) { id_Test(id, r); if( id->rank != 1 ) return TRUE; if (rRing_has_Comp(r)) { const int l = IDELEMS(id); for (int j=0; jm[j] != NULL && p_GetComp(id->m[j], r) > 0) return TRUE; return FALSE; // rank: 1, only zero or no entries? can be an ideal OR module... BUT in the use-case should better be an ideal! } return FALSE; } static inline void NoReturn(leftv& res) { res->rtyp = NONE; res->data = NULL; } /// wrapper around n_ClearContent static BOOLEAN _ClearContent(leftv res, leftv h) { NoReturn(res); const char *usage = "'ClearContent' needs a (non-zero!) poly or vector argument..."; if( h == NULL ) { WarnS(usage); return TRUE; } assume( h != NULL ); if( !( h->Typ() == POLY_CMD || h->Typ() == VECTOR_CMD) ) { WarnS(usage); return TRUE; } assume (h->Next() == NULL); poly ph = reinterpret_cast(h->Data()); if( ph == NULL ) { WarnS(usage); return TRUE; } const ring r = currRing; assume( r != NULL ); assume( r->cf != NULL ); const coeffs C = r->cf; number n; // experimentall (recursive enumerator treatment) of alg. ext CPolyCoeffsEnumerator itr(ph); n_ClearContent(itr, n, C); res->data = n; res->rtyp = NUMBER_CMD; return FALSE; } /// wrapper around n_ClearDenominators static BOOLEAN _ClearDenominators(leftv res, leftv h) { NoReturn(res); const char *usage = "'ClearDenominators' needs a (non-zero!) poly or vector argument..."; if( h == NULL ) { WarnS(usage); return TRUE; } assume( h != NULL ); if( !( h->Typ() == POLY_CMD || h->Typ() == VECTOR_CMD) ) { WarnS(usage); return TRUE; } assume (h->Next() == NULL); poly ph = reinterpret_cast(h->Data()); if( ph == NULL ) { WarnS(usage); return TRUE; } const ring r = currRing; assume( r != NULL ); assume( r->cf != NULL ); const coeffs C = r->cf; number n; // experimentall (recursive enumerator treatment) of alg. ext. CPolyCoeffsEnumerator itr(ph); n_ClearDenominators(itr, n, C); res->data = n; res->rtyp = NUMBER_CMD; return FALSE; } /// try to get an optional (simple) integer argument out of h /// or return the default value static int getOptionalInteger(const leftv& h, const int _n) { if( h!= NULL && h->Typ() == INT_CMD ) { int n = (int)(long)(h->Data()); if( n < 0 ) Warn("Negative (%d) optional integer argument", n); return (n); } return (_n); } static BOOLEAN noop(leftv __res, leftv /*__v*/) { NoReturn(__res); return FALSE; } static BOOLEAN _ProfilerStart(leftv __res, leftv h) { NoReturn(__res); #if GOOGLE_PROFILE_ENABLED if( h!= NULL && h->Typ() == STRING_CMD ) { const char* name = (char*)(h->Data()); assume( name != NULL ); ProfilerStart(name); } else WerrorS("ProfilerStart requires a string [name] argument"); #else WarnS("Sorry no google profiler support (GOOGLE_PROFILE_ENABLE!=1)..."); // return TRUE; // ? #endif // #if GOOGLE_PROFILE_ENABLED return FALSE; (void)h; } static BOOLEAN _ProfilerStop(leftv __res, leftv /*__v*/) { NoReturn(__res); #if GOOGLE_PROFILE_ENABLED ProfilerStop(); #else WarnS("Sorry no google profiler support (GOOGLE_PROFILE_ENABLED!=1)..."); // return TRUE; // ? #endif // #if GOOGLE_PROFILE_ENABLED return FALSE; } static inline number jjLONG2N(long d) { return n_Init(d, coeffs_BIGINT); } static inline void view(const intvec* v) { #ifndef SING_NDEBUG v->view(); #else // This code duplication is only due to Hannes's #ifndef SING_NDEBUG! Print ("intvec: {rows: %d, cols: %d, length: %d, Values: \n", v->rows(), v->cols(), v->length()); for (int i = 0; i < v->rows(); i++) { Print ("Row[%3d]:", i); for (int j = 0; j < v->cols(); j++) Print (" %5d", (*v)[j + i * (v->cols())] ); PrintLn (); } PrintS ("}\n"); #endif } static BOOLEAN DetailedPrint(leftv __res, leftv h) { NoReturn(__res); if( h == NULL ) { WarnS("DetailedPrint needs an argument..."); return TRUE; } if( h->Typ() == NUMBER_CMD) { number n = (number)h->Data(); const ring r = currRing; n_Test(n, r->cf); StringSetS(""); n_Write(n, r->cf); PrintS(StringEndS()); PrintLn(); return FALSE; } if( h->Typ() == RING_CMD) { const ring r = (const ring)h->Data(); rWrite(r, TRUE); PrintLn(); #ifdef RDEBUG //rDebugPrint(r); #endif return FALSE; } if( h->Typ() == POLY_CMD || h->Typ() == VECTOR_CMD) { const poly p = (const poly)h->Data(); h = h->Next(); dPrint(p, currRing, currRing, getOptionalInteger(h, 3)); return FALSE; } if( h->Typ() == IDEAL_CMD || h->Typ() == MODUL_CMD) { const ideal id = (const ideal)h->Data(); h = h->Next(); dPrint(id, currRing, currRing, getOptionalInteger(h, 3)); return FALSE; } if( h->Typ() == RESOLUTION_CMD ) { const syStrategy syzstr = reinterpret_cast(h->Data()); h = h->Next(); int nTerms = getOptionalInteger(h, 1); Print("RESOLUTION_CMD(%p): ", reinterpret_cast(syzstr)); PrintLn(); const ring save = currRing; const ring r = syzstr->syRing; // const ring rr = (r != NULL) ? r: save; const int iLength = syzstr->length; Print("int 'length': %d", iLength); PrintLn(); Print("int 'regularity': %d", syzstr->regularity); PrintLn(); Print("short 'list_length': %hd", syzstr->list_length); PrintLn(); Print("short 'references': %hd", syzstr->references); PrintLn(); #define PRINT_pINTVECTOR(s, v) Print("intvec '%10s'(%p)", #v, reinterpret_cast((s)->v)); \ if( (s)->v != NULL ){ PrintS(": "); view((s)->v); }; \ PrintLn(); PRINT_pINTVECTOR(syzstr, resolution); PRINT_pINTVECTOR(syzstr, betti); PRINT_pINTVECTOR(syzstr, Tl); PRINT_pINTVECTOR(syzstr, cw); #undef PRINT_pINTVECTOR if (r == NULL) Print("ring '%10s': NULL", "syRing"); else if (r == currRing) Print("ring '%10s': currRing", "syRing"); else if (r != NULL && r != save) { Print("ring '%10s': ", "syRing"); rWrite(r); #ifdef RDEBUG // rDebugPrint(r); #endif // rChangeCurrRing(r); } PrintLn(); const SRes rP = syzstr->resPairs; Print("SRes 'resPairs': %p", reinterpret_cast(rP)); PrintLn(); if (rP != NULL) for (int iLevel = 0; (iLevel < iLength) && (rP[iLevel] != NULL) && ((*syzstr->Tl)[iLevel] >= 0); iLevel++) { int n = 0; const int iTl = (*syzstr->Tl)[iLevel]; for (int j = 0; (j < iTl) && ((rP[iLevel][j].lcm!=NULL) || (rP[iLevel][j].syz!=NULL)); j++) { if (rP[iLevel][j].isNotMinimal==NULL) n++; } Print("minimal-resPairs-Size[1+%d]: %d", iLevel, n); PrintLn(); } // const ring rrr = (iLevel > 0) ? rr : save; ? #define PRINT_RESOLUTION(s, v) Print("resolution '%12s': %p", #v, reinterpret_cast((s)->v)); PrintLn(); \ if ((s)->v != NULL) \ for (int iLevel = 0; (iLevel < iLength) && ( ((s)->v)[iLevel] != NULL ); iLevel++) \ { \ /* const ring rrr = (iLevel > 0) ? save : save; */ \ Print("id '%10s'[%d]: (%p) ncols = %d / size: %d; nrows = %d, rank = %ld / rk: %ld", #v, iLevel, reinterpret_cast(((s)->v)[iLevel]), ((s)->v)[iLevel]->ncols, idSize(((s)->v)[iLevel]), ((s)->v)[iLevel]->nrows, ((s)->v)[iLevel]->rank, -1L/*id_RankFreeModule(((s)->v)[iLevel], rrr)*/ ); \ PrintLn(); \ } \ PrintLn(); // resolvente: PRINT_RESOLUTION(syzstr, minres); PRINT_RESOLUTION(syzstr, fullres); // assume (id_RankFreeModule (syzstr->res[1], rr) == syzstr->res[1]->rank); PRINT_RESOLUTION(syzstr, res); PRINT_RESOLUTION(syzstr, orderedRes); #undef PRINT_RESOLUTION #define PRINT_POINTER(s, v) Print("pointer '%17s': %p", #v, reinterpret_cast((s)->v)); PrintLn(); // 2d arrays: PRINT_POINTER(syzstr, truecomponents); PRINT_POINTER(syzstr, ShiftedComponents); PRINT_POINTER(syzstr, backcomponents); PRINT_POINTER(syzstr, Howmuch); PRINT_POINTER(syzstr, Firstelem); PRINT_POINTER(syzstr, elemLength); PRINT_POINTER(syzstr, sev); // arrays of intvects: PRINT_POINTER(syzstr, weights); PRINT_POINTER(syzstr, hilb_coeffs); #undef PRINT_POINTER if (syzstr->fullres==NULL) { PrintS("resolution 'fullres': (NULL) => resolution not computed yet"); PrintLn(); } else { Print("resolution 'fullres': (%p) => resolution seems to be computed already", reinterpret_cast(syzstr->fullres)); PrintLn(); dPrint(*syzstr->fullres, save, save, nTerms); } if (syzstr->minres==NULL) { PrintS("resolution 'minres': (NULL) => resolution not minimized yet"); PrintLn(); } else { Print("resolution 'minres': (%p) => resolution seems to be minimized already", reinterpret_cast(syzstr->minres)); PrintLn(); dPrint(*syzstr->minres, save, save, nTerms); } /* int ** truecomponents; long** ShiftedComponents; int ** backcomponents; int ** Howmuch; int ** Firstelem; int ** elemLength; unsigned long ** sev; intvec ** weights; intvec ** hilb_coeffs; SRes resPairs; //polynomial data for internal use only resolvente fullres; resolvente minres; resolvente res; //polynomial data for internal use only resolvente orderedRes; //polynomial data for internal use only */ // if( currRing != save ) rChangeCurrRing(save); } return FALSE; } /// wrapper around p_Tail and id_Tail static BOOLEAN Tail(leftv res, leftv h) { NoReturn(res); if( h == NULL ) { WarnS("Tail needs a poly/vector/ideal/module argument..."); return TRUE; } assume( h != NULL ); const ring r = currRing; if( h->Typ() == POLY_CMD || h->Typ() == VECTOR_CMD) { res->data = p_Tail( (const poly)h->Data(), r ); res->rtyp = h->Typ(); h = h->Next(); assume (h == NULL); return FALSE; } if( h->Typ() == IDEAL_CMD || h->Typ() == MODUL_CMD) { res->data = id_Tail( (const ideal)h->Data(), r ); res->rtyp = h->Typ(); h = h->Next(); assume (h == NULL); return FALSE; } WarnS("Tail needs a single poly/vector/ideal/module argument..."); return TRUE; } static BOOLEAN _ComputeLeadingSyzygyTerms(leftv res, leftv h) { const SchreyerSyzygyComputationFlags attributes(currRingHdl); const BOOLEAN OPT__DEBUG = attributes.OPT__DEBUG; // const BOOLEAN OPT__SYZCHECK = attributes.OPT__SYZCHECK; const BOOLEAN OPT__LEAD2SYZ = attributes.OPT__LEAD2SYZ; // const BOOLEAN OPT__HYBRIDNF = attributes.OPT__HYBRIDNF; // const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ; const ring r = attributes.m_rBaseRing; NoReturn(res); if( h == NULL ) { WarnS("ComputeLeadingSyzygyTerms needs an argument..."); return TRUE; } assume( h != NULL ); if( h->Typ() == IDEAL_CMD || h->Typ() == MODUL_CMD) { const ideal id = (const ideal)h->Data(); assume(id != NULL); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("ComputeLeadingSyzygyTerms::Input: \n"); dPrint(id, r, r, 0); } assume( !OPT__LEAD2SYZ ); h = h->Next(); assume (h == NULL); const ideal newid = ComputeLeadingSyzygyTerms(id, attributes); res->data = newid; res->rtyp = MODUL_CMD; return FALSE; } WarnS("ComputeLeadingSyzygyTerms needs a single ideal/module argument..."); return TRUE; } /// sorting wrt & reversing... /// change the input inplace!!! // TODO: use a ring with >_{c, ds}!??? static BOOLEAN _Sort_c_ds(leftv res, leftv h) { const SchreyerSyzygyComputationFlags attributes(currRingHdl); const BOOLEAN OPT__DEBUG = FALSE; // attributes.OPT__DEBUG; // const BOOLEAN OPT__SYZCHECK = attributes.OPT__SYZCHECK; // const BOOLEAN OPT__LEAD2SYZ = attributes.OPT__LEAD2SYZ; // const BOOLEAN OPT__HYBRIDNF = attributes.OPT__HYBRIDNF; // const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ; NoReturn(res); const ring r = attributes.m_rBaseRing; NoReturn(res); if( h == NULL ) { WarnS("Sort_c_ds needs an argument..."); return TRUE; } assume( h != NULL ); if( (h->Typ() == IDEAL_CMD || h->Typ() == MODUL_CMD) && (h->rtyp == IDHDL) // must be a variable! && (h->e == NULL) // not a list element ) { const ideal id = (const ideal)h->Data(); assume(id != NULL); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("Sort_c_ds::Input: \n"); dPrint(id, r, r, 0); } assume (h->Next() == NULL); id_Test(id, r); Sort_c_ds(id, r); // NOT A COPY! inplace sorting!!! // res->data = id; // res->rtyp = h->Typ(); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("Sort_c_ds::Output: \n"); dPrint(id, r, r, 0); } // NOTE: nothing is to be returned!!! return FALSE; } WarnS("ComputeLeadingSyzygyTerms needs a single ideal/module argument (must be a variable!)..."); return TRUE; } static BOOLEAN _Compute2LeadingSyzygyTerms(leftv res, leftv h) { const SchreyerSyzygyComputationFlags attributes(currRingHdl); const BOOLEAN OPT__DEBUG = attributes.OPT__DEBUG; // const BOOLEAN OPT__SYZCHECK = attributes.OPT__SYZCHECK; const BOOLEAN OPT__LEAD2SYZ = attributes.OPT__LEAD2SYZ; // const BOOLEAN OPT__HYBRIDNF = attributes.OPT__HYBRIDNF; // const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ; const ring r = attributes.m_rBaseRing; NoReturn(res); if( h == NULL ) { WarnS("Compute2LeadingSyzygyTerms needs an argument..."); return TRUE; } assume( h != NULL ); assume( OPT__LEAD2SYZ ); // ??? if( h->Typ() == IDEAL_CMD || h->Typ() == MODUL_CMD) { const ideal id = (const ideal)h->Data(); assume(id != NULL); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("Compute2LeadingSyzygyTerms::Input: \n"); dPrint(id, r, r, 0); } h = h->Next(); assume (h == NULL); res->data = Compute2LeadingSyzygyTerms(id, attributes); res->rtyp = MODUL_CMD; return FALSE; } WarnS("Compute2LeadingSyzygyTerms needs a single ideal/module argument..."); return TRUE; } /// proc SSFindReducer(def product, def syzterm, def L, def T, list #) static BOOLEAN _FindReducer(leftv res, leftv h) { const SchreyerSyzygyComputationFlags attributes(currRingHdl); const BOOLEAN OPT__DEBUG = attributes.OPT__DEBUG; // const BOOLEAN OPT__SYZCHECK = attributes.OPT__SYZCHECK; // const BOOLEAN OPT__LEAD2SYZ = attributes.OPT__LEAD2SYZ; // const BOOLEAN OPT__HYBRIDNF = attributes.OPT__HYBRIDNF; const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ; const char* usage = "`FindReducer(, , [,])` expected"; const ring r = attributes.m_rBaseRing; NoReturn(res); if ((h==NULL) || (h->Typ()!=VECTOR_CMD && h->Typ() !=POLY_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const poly product = (poly) h->Data(); assume (product != NULL); h = h->Next(); if ((h==NULL) || !((h->Typ()==VECTOR_CMD) || (h->Data() == NULL)) ) { WerrorS(usage); return TRUE; } poly syzterm = NULL; if(h->Typ()==VECTOR_CMD) syzterm = (poly) h->Data(); h = h->Next(); if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const ideal L = (ideal) h->Data(); h = h->Next(); assume( IDELEMS(L) > 0 ); ideal LS = NULL; if ((h != NULL) && (h->Typ() ==MODUL_CMD) && (h->Data() != NULL)) { LS = (ideal)h->Data(); h = h->Next(); } #ifndef SING_NDEBUG if( LIKELY( OPT__TAILREDSYZ) ) assume (LS != NULL); #endif assume( h == NULL ); if( UNLIKELY(OPT__DEBUG) ) { PrintS("FindReducer(product, syzterm, L, T, #)::Input: \n"); PrintS("product: "); dPrint(product, r, r, 0); PrintS("syzterm: "); dPrint(syzterm, r, r, 0); // PrintS("L: "); dPrint(L, r, r, 0); // PrintS("T: "); dPrint(T, r, r, 0); if( LS == NULL ) // PrintS("LS: NULL\n"); ; else { // PrintS("LS: "); dPrint(LS, r, r, 0); } } res->rtyp = VECTOR_CMD; res->data = FindReducer(product, syzterm, L, LS, attributes); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("FindReducer::Output: \n"); dPrint((poly)res->data, r, r, 0); } return FALSE; } // proc SchreyerSyzygyNF(vector syz_lead, vector syz_2, def L, def T, list #) static BOOLEAN _SchreyerSyzygyNF(leftv res, leftv h) { const SchreyerSyzygyComputationFlags attributes(currRingHdl); const BOOLEAN OPT__DEBUG = attributes.OPT__DEBUG; // const BOOLEAN OPT__SYZCHECK = attributes.OPT__SYZCHECK; // const BOOLEAN OPT__LEAD2SYZ = attributes.OPT__LEAD2SYZ; const BOOLEAN OPT__HYBRIDNF = attributes.OPT__HYBRIDNF; const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ; const char* usage = "`SchreyerSyzygyNF(, , , [,])` expected"; const ring r = attributes.m_rBaseRing; NoReturn(res); assume( OPT__HYBRIDNF ); // ??? if ((h==NULL) || (h->Typ() != VECTOR_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const poly syz_lead = (poly) h->Data(); assume (syz_lead != NULL); h = h->Next(); if ((h==NULL) || (h->Typ() != VECTOR_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const poly syz_2 = (poly) h->Data(); assume (syz_2 != NULL); h = h->Next(); if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const ideal L = (ideal) h->Data(); assume( IDELEMS(L) > 0 ); h = h->Next(); if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const ideal T = (ideal) h->Data(); assume( IDELEMS(L) == IDELEMS(T) ); ideal LS = NULL; h = h->Next(); if ((h != NULL) && (h->Typ() ==MODUL_CMD) && (h->Data() != NULL)) { LS = (ideal)h->Data(); h = h->Next(); } #ifndef SING_NDEBUG if( LIKELY( OPT__TAILREDSYZ) ) assume (LS != NULL); #endif assume( h == NULL ); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("SchreyerSyzygyNF(syz_lead, syz_2, L, T, #)::Input: \n"); PrintS("syz_lead: "); dPrint(syz_lead, r, r, 0); PrintS("syz_2: "); dPrint(syz_2, r, r, 0); // PrintS("L: "); dPrint(L, r, r, 0); // PrintS("T: "); dPrint(T, r, r, 0); if( LS == NULL ) // PrintS("LS: NULL\n") ; else { // PrintS("LS: "); dPrint(LS, r, r, 0); } } res->rtyp = VECTOR_CMD; res->data = SchreyerSyzygyNF(syz_lead, (syz_2!=NULL)? p_Copy(syz_2, r): syz_2, L, T, LS, attributes); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("SchreyerSyzygyNF::Output: "); dPrint((poly)res->data, r, r, 0); } return FALSE; } /// proc SSReduceTerm(poly m, def t, def syzterm, def L, def T, list #) static BOOLEAN _ReduceTerm(leftv res, leftv h) { const SchreyerSyzygyComputationFlags attributes(currRingHdl); const BOOLEAN OPT__DEBUG = attributes.OPT__DEBUG; // const BOOLEAN OPT__SYZCHECK = attributes.OPT__SYZCHECK; // const BOOLEAN OPT__LEAD2SYZ = attributes.OPT__LEAD2SYZ; // const BOOLEAN OPT__HYBRIDNF = attributes.OPT__HYBRIDNF; const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ; const char* usage = "`ReduceTerm(, , , , [,])` expected"; const ring r = attributes.m_rBaseRing; NoReturn(res); if ((h==NULL) || (h->Typ() !=POLY_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const poly multiplier = (poly) h->Data(); assume (multiplier != NULL); h = h->Next(); if ((h==NULL) || (h->Typ()!=VECTOR_CMD && h->Typ() !=POLY_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const poly term4reduction = (poly) h->Data(); assume( term4reduction != NULL ); poly syztermCheck = NULL; h = h->Next(); if ((h==NULL) || !((h->Typ()==VECTOR_CMD) || (h->Data() == NULL)) ) { WerrorS(usage); return TRUE; } if(h->Typ()==VECTOR_CMD) syztermCheck = (poly) h->Data(); h = h->Next(); if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const ideal L = (ideal) h->Data(); assume( IDELEMS(L) > 0 ); h = h->Next(); if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const ideal T = (ideal) h->Data(); assume( IDELEMS(L) == IDELEMS(T) ); ideal LS = NULL; h = h->Next(); if ((h != NULL) && (h->Typ() ==MODUL_CMD) && (h->Data() != NULL)) { LS = (ideal)h->Data(); h = h->Next(); } #ifndef SING_NDEBUG if( LIKELY( OPT__TAILREDSYZ) ) assume (LS != NULL); #endif assume( h == NULL ); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("ReduceTerm(m, t, syzterm, L, T, #)::Input: \n"); PrintS("m: "); dPrint(multiplier, r, r, 0); PrintS("t: "); dPrint(term4reduction, r, r, 0); PrintS("syzterm: "); dPrint(syztermCheck, r, r, 0); // PrintS("L: "); dPrint(L, r, r, 0); // PrintS("T: "); dPrint(T, r, r, 0); if( LS == NULL ) // PrintS("LS: NULL\n") ; else { // PrintS("LS: "); dPrint(LS, r, r, 0); } } if ( UNLIKELY( OPT__DEBUG && syztermCheck != NULL) ) { const int c = p_GetComp(syztermCheck, r) - 1; assume( c >= 0 && c < IDELEMS(L) ); const poly p = L->m[c]; assume( p != NULL ); assume( pNext(p) == NULL ); assume( p_EqualPolys(term4reduction, p, r) ); // assume? TODO poly m = leadmonom(syztermCheck, r); assume( m != NULL ); assume( pNext(m) == NULL ); assume( p_EqualPolys(multiplier, m, r) ); // assume? TODO p_Delete(&m, r); // NOTE: leadmonomial(syzterm) == m && L[leadcomp(syzterm)] == t } res->rtyp = VECTOR_CMD; res->data = ReduceTerm(multiplier, term4reduction, syztermCheck, L, T, LS, attributes); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("ReduceTerm::Output: "); dPrint((poly)res->data, r, r, 0); } return FALSE; } // proc SSTraverseTail(poly m, def @tail, def L, def T, list #) static BOOLEAN _TraverseTail(leftv res, leftv h) { const SchreyerSyzygyComputationFlags attributes(currRingHdl); const BOOLEAN OPT__DEBUG = attributes.OPT__DEBUG; // const BOOLEAN OPT__SYZCHECK = attributes.OPT__SYZCHECK; // const BOOLEAN OPT__LEAD2SYZ = attributes.OPT__LEAD2SYZ; // const BOOLEAN OPT__HYBRIDNF = attributes.OPT__HYBRIDNF; const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ; const char* usage = "`TraverseTail(, , , [,])` expected"; const ring r = attributes.m_rBaseRing; NoReturn(res); if ((h==NULL) || (h->Typ() !=POLY_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const poly multiplier = (poly) h->Data(); assume (multiplier != NULL); h = h->Next(); if ((h==NULL) || (h->Typ()!=VECTOR_CMD && h->Typ() !=POLY_CMD)) { WerrorS(usage); return TRUE; } const poly tail = (poly) h->Data(); h = h->Next(); if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const ideal L = (ideal) h->Data(); assume( IDELEMS(L) > 0 ); h = h->Next(); if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const ideal T = (ideal) h->Data(); assume( IDELEMS(L) == IDELEMS(T) ); h = h->Next(); ideal LS = NULL; if ((h != NULL) && (h->Typ() ==MODUL_CMD) && (h->Data() != NULL)) { LS = (ideal)h->Data(); h = h->Next(); } #ifndef SING_NDEBUG if( LIKELY( OPT__TAILREDSYZ) ) assume (LS != NULL); #endif assume( h == NULL ); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("TraverseTail(m, t, L, T, #)::Input: \n"); PrintS("m: "); dPrint(multiplier, r, r, 0); PrintS("t: "); dPrint(tail, r, r, 0); // PrintS("L: "); dPrint(L, r, r, 0); // PrintS("T: "); dPrint(T, r, r, 0); if( LS == NULL ) // PrintS("LS: NULL\n") ; else { // PrintS("LS: "); dPrint(LS, r, r, 0); } } res->rtyp = VECTOR_CMD; res->data = TraverseTail(multiplier, tail, L, T, LS, attributes); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("TraverseTail::Output: "); dPrint((poly)res->data, r, r, 0); } return FALSE; } static BOOLEAN _ComputeResolution(leftv res, leftv h) { const SchreyerSyzygyComputationFlags attributes(currRingHdl); const BOOLEAN OPT__DEBUG = attributes.OPT__DEBUG; const char* usage = "`ComputeResolution(, , [,int])` expected"; const ring r = attributes.m_rBaseRing; NoReturn(res); // input if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const int type = h->Typ(); ideal M = (ideal)(h->CopyD()); // copy for resolution...!??? int size = IDELEMS(M); assume( size >= 0 ); h = h->Next(); // lead if ((h==NULL) || (h->Typ()!=type) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } ideal L = (ideal)(h->CopyD()); // no copy! assume( IDELEMS(L) == size ); h = h->Next(); if ((h==NULL) || (h->Typ()!=type) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } ideal T = (ideal)(h->CopyD()); // no copy! assume( IDELEMS(T) == size ); h = h->Next(); // length..? long length = 0; if ((h!=NULL) && (h->Typ()==INT_CMD)) { length = (long)(h->Data()); h = h->Next(); } assume( h == NULL ); if( length <= 0 ) length = 1 + rVar(r); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("ComputeResolution(M, length)::Input: \n"); Print( "starting length: %ld\n", length); PrintS("M: \n"); dPrint(M, r, r, 0); PrintS("L=LEAD(M): \n"); dPrint(L, r, r, 0); PrintS("T=TAIL(M): \n"); dPrint(T, r, r, 0); } syStrategy _res=(syStrategy)omAlloc0(sizeof(ssyStrategy)); // class ssyStrategy; typedef ssyStrategy * syStrategy; // typedef ideal * resolvente; _res->length = length + 1; // index + 1; _res->fullres = (resolvente)omAlloc0((_res->length+1)*sizeof(ideal)); int index = 0; _res->fullres[index++] = M; // if (UNLIKELY(attributes.OPT__TREEOUTPUT)) // Print("{ \"RESOLUTION: HYBRIDNF:%d, TAILREDSYZ: %d, LEAD2SYZ: %d, IGNORETAILS: %d\": [\n", attributes.OPT__HYBRIDNF, attributes.OPT__TAILREDSYZ, attributes.OPT__LEAD2SYZ, attributes.OPT__IGNORETAILS); while( (!idIs0(L)) && (index < length)) { attributes.nextSyzygyLayer(); ideal LL, TT; ComputeSyzygy(L, T, LL, TT, attributes); if( UNLIKELY( OPT__DEBUG ) ) { Print("ComputeResolution()::Separated Syzygy[%d]: \n", index); // PrintS("LL: \n"); dPrint(LL, r, r, 0); // PrintS("TT: \n"); dPrint(TT, r, r, 0); } size = IDELEMS(LL); assume( size == IDELEMS(TT) ); id_Delete(&L, r); id_Delete(&T, r); L = LL; T = TT; // id_Add(T, L, r); M = idInit(size, 0); for( int i = size-1; i >= 0; i-- ) { M->m[i] = p_Add_q(p_Copy(T->m[i], r), p_Copy(L->m[i], r), r); // TODO: :((( } M->rank = id_RankFreeModule(M, r); if( UNLIKELY( OPT__DEBUG ) ) { Print("ComputeResolution()::Restored Syzygy[%d]: \n", index); PrintS("M = LL + TT: \n"); dPrint(M, r, r, 0); } _res->fullres[index++] = M; // ??? } // if ( UNLIKELY(attributes.OPT__TREEOUTPUT) ) // PrintS("] }\n"); id_Delete(&L, r); id_Delete(&T, r); res->data = _res; res->rtyp = RESOLUTION_CMD; if( UNLIKELY(OPT__DEBUG) ) { Print("ComputeResolution::Output (index: %d): ", index); // class sleftv; typedef sleftv * leftv; sleftv _h; DetailedPrint(&_h, res); } // omFreeSize(_res, sizeof(ssyStrategy)); return FALSE; } /// module (LL, TT) = SSComputeSyzygy(L, T); /// Compute Syz(L ++ T) = N = LL ++ TT // proc SSComputeSyzygy(def L, def T) static BOOLEAN _ComputeSyzygy(leftv res, leftv h) { const SchreyerSyzygyComputationFlags attributes(currRingHdl); const BOOLEAN OPT__DEBUG = attributes.OPT__DEBUG; // const BOOLEAN OPT__SYZCHECK = attributes.OPT__SYZCHECK; // const BOOLEAN OPT__LEAD2SYZ = attributes.OPT__LEAD2SYZ; // const BOOLEAN OPT__HYBRIDNF = attributes.OPT__HYBRIDNF; // const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ; const char* usage = "`ComputeSyzygy(, )` expected"; const ring r = attributes.m_rBaseRing; NoReturn(res); if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const ideal L = (ideal) h->Data(); assume( IDELEMS(L) > 0 ); h = h->Next(); if ((h==NULL) || (h->Typ()!=IDEAL_CMD && h->Typ() !=MODUL_CMD) || (h->Data() == NULL)) { WerrorS(usage); return TRUE; } const ideal T = (ideal) h->Data(); assume( IDELEMS(L) == IDELEMS(T) ); h = h->Next(); assume( h == NULL ); if( UNLIKELY( OPT__DEBUG ) ) { PrintS("ComputeSyzygy(L, T)::Input: \n"); // PrintS("L: "); dPrint(L, r, r, 0); // PrintS("T: "); dPrint(T, r, r, 0); } ideal LL, TT; ComputeSyzygy(L, T, LL, TT, attributes); lists l = (lists)omAllocBin(slists_bin); l->Init(2); l->m[0].rtyp = MODUL_CMD; l->m[0].data = reinterpret_cast(LL); l->m[1].rtyp = MODUL_CMD; l->m[1].data = reinterpret_cast(TT); res->data = l; res->rtyp = LIST_CMD; if( UNLIKELY( OPT__DEBUG ) ) { PrintS("ComputeSyzygy::Output: \nLL: \n"); dPrint(LL, r, r, 0); PrintS("\nTT: \n"); dPrint(TT, r, r, 0); } return FALSE; } /// Get leading term without a module component static BOOLEAN _leadmonom(leftv res, leftv h) { NoReturn(res); if ((h!=NULL) && (h->Typ()==VECTOR_CMD || h->Typ()==POLY_CMD) && (h->Data() != NULL)) { const ring r = currRing; const poly p = (poly)(h->Data()); res->data = reinterpret_cast( leadmonom(p, r) ); res->rtyp = POLY_CMD; return FALSE; } WerrorS("`leadmonom()` expected"); return TRUE; } /// Get leading component static BOOLEAN leadcomp(leftv res, leftv h) { NoReturn(res); if ((h!=NULL) && (h->Typ()==VECTOR_CMD || h->Typ()==POLY_CMD)) { const ring r = currRing; const poly p = (poly)(h->Data()); if (p != NULL ) { assume( p != NULL ); p_LmTest(p, r); const unsigned long iComp = p_GetComp(p, r); // assume( iComp > 0 ); // p is a vector res->data = reinterpret_cast(jjLONG2N(iComp)); } else res->data = reinterpret_cast(jjLONG2N(0)); res->rtyp = BIGINT_CMD; return FALSE; } WerrorS("`leadcomp()` expected"); return TRUE; } /// Get raw leading exponent vector static BOOLEAN leadrawexp(leftv res, leftv h) { NoReturn(res); if ((h!=NULL) && (h->Typ()==VECTOR_CMD || h->Typ()==POLY_CMD) && (h->Data() != NULL)) { const ring r = currRing; const poly p = (poly)(h->Data()); assume( p != NULL ); p_LmTest(p, r); const int iExpSize = r->ExpL_Size; // intvec *iv = new intvec(iExpSize); lists l=(lists)omAllocBin(slists_bin); l->Init(iExpSize); for(int i = iExpSize-1; i >= 0; i--) { l->m[i].rtyp = BIGINT_CMD; l->m[i].data = reinterpret_cast(jjLONG2N(p->exp[i])); // longs... } res->rtyp = LIST_CMD; // list of bigints res->data = reinterpret_cast(l); return FALSE; } WerrorS("`leadrawexp()` expected"); return TRUE; } /// Endowe the current ring with additional (leading) Syz-component ordering static BOOLEAN MakeSyzCompOrdering(leftv res, leftv /*h*/) { NoReturn(res); // res->data = rCurrRingAssure_SyzComp(); // changes current ring! :( res->data = reinterpret_cast(rAssure_SyzComp(currRing, TRUE)); res->rtyp = RING_CMD; // return new ring! // QRING_CMD? return FALSE; } /// Same for Induced Schreyer ordering (ordering on components is defined by sign!) static BOOLEAN MakeInducedSchreyerOrdering(leftv res, leftv h) { NoReturn(res); int sign = 1; if ((h!=NULL) && (h->Typ()==INT_CMD)) { const int s = (int)((long)(h->Data())); if( s != -1 && s != 1 ) { WerrorS("`MakeInducedSchreyerOrdering()` called with wrong integer argument (must be +-1)!"); return TRUE; } sign = s; } assume( sign == 1 || sign == -1 ); res->data = reinterpret_cast(rAssure_InducedSchreyerOrdering(currRing, TRUE, sign)); res->rtyp = RING_CMD; // return new ring! // QRING_CMD? return FALSE; } /// Returns old SyzCompLimit, can set new limit static BOOLEAN SetSyzComp(leftv res, leftv h) { NoReturn(res); const ring r = currRing; if( !rIsSyzIndexRing(r) ) { WerrorS("`SetSyzComp()` called on incompatible ring (not created by 'MakeSyzCompOrdering'!)"); return TRUE; } res->rtyp = INT_CMD; res->data = reinterpret_cast(rGetCurrSyzLimit(r)); // return old syz limit if ((h!=NULL) && (h->Typ()==INT_CMD)) { const int iSyzComp = (int)reinterpret_cast(h->Data()); assume( iSyzComp > 0 ); rSetSyzComp(iSyzComp, currRing); } return FALSE; } /// ? static BOOLEAN GetInducedData(leftv res, leftv h) { NoReturn(res); const ring r = currRing; int p = 0; // which IS-block? p^th! if ((h!=NULL) && (h->Typ()==INT_CMD)) { p = (int)((long)(h->Data())); h=h->next; assume(p >= 0); } const int pos = rGetISPos(p, r); if( /*(*/ -1 == pos /*)*/ ) { WerrorS("`GetInducedData([int])` called on incompatible ring (not created by 'MakeInducedSchreyerOrdering'!)"); return TRUE; } const int iLimit = r->typ[pos].data.is.limit; const ideal F = r->typ[pos].data.is.F; ideal FF = id_Copy(F, r); lists l=(lists)omAllocBin(slists_bin); l->Init(2); l->m[0].rtyp = INT_CMD; l->m[0].data = reinterpret_cast(iLimit); // l->m[1].rtyp = MODUL_CMD; if( id_IsModule(FF, r) ) // ??? { l->m[1].rtyp = MODUL_CMD; // Print("before: %d\n", FF->nrows); // FF->nrows = id_RankFreeModule(FF, r); // ??? // Print("after: %d\n", FF->nrows); } else l->m[1].rtyp = IDEAL_CMD; l->m[1].data = reinterpret_cast(FF); res->rtyp = LIST_CMD; // list of int/module res->data = reinterpret_cast(l); return FALSE; } /* // the following turned out to be unnecessary... /// Finds p^th AM ordering, and returns its position in r->typ[] AND /// corresponding &r->wvhdl[] /// returns FALSE if something went wrong! /// p - starts with 0! BOOLEAN rGetAMPos(const ring r, const int p, int &typ_pos, int &wvhdl_pos, const BOOLEAN bSearchWvhdl = FALSE) { #if MYTEST Print("rGetAMPos(p: %d...)\nF:", p); PrintLn(); #endif typ_pos = -1; wvhdl_pos = -1; if (r->typ==NULL) return FALSE; int j = p; // Which IS record to use... for( int pos = 0; pos < r->OrdSize; pos++ ) if( r->typ[pos].ord_typ == ro_am) if( j-- == 0 ) { typ_pos = pos; if( bSearchWvhdl ) { const int nblocks = rBlocks(r) - 1; const int* w = r->typ[pos].data.am.weights; // ? for( pos = 0; pos <= nblocks; pos ++ ) if (r->order[pos] == ringorder_am) if( r->wvhdl[pos] == w ) { wvhdl_pos = pos; break; } if (wvhdl_pos < 0) return FALSE; assume(wvhdl_pos >= 0); } assume(typ_pos >= 0); return TRUE; } return FALSE; } // // ? // static BOOLEAN GetAMData(leftv res, leftv h) // { // NoReturn(res); // // const ring r = currRing; // // int p = 0; // which IS-block? p^th! // // if ((h!=NULL) && (h->Typ()==INT_CMD)) // p = (int)((long)(h->Data())); h=h->next; // // assume(p >= 0); // // int d, w; // // if( !rGetAMPos(r, p, d, w, TRUE) ) // { // Werror("`GetAMData([int])`: no %d^th _am block-ordering!", p); // return TRUE; // } // // assume( r->typ[d].ord_typ == ro_am ); // assume( r->order[w] == ringorder_am ); // // // const short start = r->typ[d].data.am.start; // bounds of ordering (in E) // const short end = r->typ[d].data.am.end; // const short len_gen = r->typ[d].data.am.len_gen; // i>len_gen: weight(gen(i)):=0 // const int *weights = r->typ[d].data.am.weights; // pointers into wvhdl field of length (end-start+1) + len_gen // // contents w_1,... w_n, len, mod_w_1, .. mod_w_len, 0 // // assume( weights == r->wvhdl[w] ); // // // lists l=(lists)omAllocBin(slists_bin); // l->Init(2); // // const short V = end-start+1; // intvec* ww_vars = new intvec(V); // intvec* ww_gens = new intvec(len_gen); // // for (int i = 0; i < V; i++ ) // (*ww_vars)[i] = weights[i]; // // assume( weights[V] == len_gen ); // // for (int i = 0; i < len_gen; i++ ) // (*ww_gens)[i] = weights[i - V - 1]; // // // l->m[0].rtyp = INTVEC_CMD; // l->m[0].data = reinterpret_cast(ww_vars); // // l->m[1].rtyp = INTVEC_CMD; // l->m[1].data = reinterpret_cast(ww_gens); // // // return FALSE; // // } */ /// Returns old SyzCompLimit, can set new limit static BOOLEAN SetInducedReferrence(leftv res, leftv h) { NoReturn(res); const ring r = currRing; if( !( (h!=NULL) && ( (h->Typ()==IDEAL_CMD) || (h->Typ()==MODUL_CMD))) ) { WerrorS("`SetInducedReferrence(, [int[, int]])` expected"); return TRUE; } const ideal F = (ideal)h->Data(); ; // No copy! h=h->next; int rank = 0; if ((h!=NULL) && (h->Typ()==INT_CMD)) { rank = (int)((long)(h->Data())); h=h->next; assume(rank >= 0); } else rank = id_RankFreeModule(F, r); // Starting syz-comp (1st: i+1) int p = 0; // which IS-block? p^th! if ((h!=NULL) && (h->Typ()==INT_CMD)) { p = (int)((long)(h->Data())); h=h->next; assume(p >= 0); } const int posIS = rGetISPos(p, r); if( /*(*/ -1 == posIS /*)*/ ) { WerrorS("`SetInducedReferrence(, [int[, int]])` called on incompatible ring (not created by 'MakeInducedSchreyerOrdering'!)"); return TRUE; } // F & componentWeights belong to that ordering block of currRing now: rSetISReference(r, F, rank, p); // F will be copied! return FALSE; } // F = ISUpdateComponents( F, V, MIN ); // // replace gen(i) -> gen(MIN + V[i-MIN]) for all i > MIN in all terms from F! static BOOLEAN ISUpdateComponents(leftv res, leftv h) { NoReturn(res); PrintS("ISUpdateComponents:.... \n"); if ((h!=NULL) && (h->Typ()==MODUL_CMD)) { ideal F = (ideal)h->Data(); ; // No copy! h=h->next; if ((h!=NULL) && (h->Typ()==INTVEC_CMD)) { const intvec* const V = (const intvec* const) h->Data(); h=h->next; if ((h!=NULL) && (h->Typ()==INT_CMD)) { const int MIN = (int)((long)(h->Data())); pISUpdateComponents(F, V, MIN, currRing); return FALSE; } } } WerrorS("`ISUpdateComponents(, intvec, int)` expected"); return TRUE; } /// NF using length static BOOLEAN reduce_syz(leftv res, leftv h) { // const ring r = currRing; if ( !( (h!=NULL) && (h->Typ()==VECTOR_CMD || h->Typ()==POLY_CMD) ) ) { WerrorS("`reduce_syz(!, , , [int])` expected"); return TRUE; } res->rtyp = h->Typ(); const poly v = reinterpret_cast(h->Data()); h=h->next; if ( !( (h!=NULL) && (h->Typ()==MODUL_CMD || h->Typ()==IDEAL_CMD ) ) ) { WerrorS("`reduce_syz(, !, , [int])` expected"); return TRUE; } assumeStdFlag(h); const ideal M = reinterpret_cast(h->Data()); h=h->next; if ( !( (h!=NULL) && (h->Typ()== INT_CMD) ) ) { WerrorS("`reduce_syz(, , !, [int])` expected"); return TRUE; } const int iSyzComp = (int)((long)(h->Data())); h=h->next; int iLazyReduce = 0; if ( ( (h!=NULL) && (h->Typ()== INT_CMD) ) ) iLazyReduce = (int)((long)(h->Data())); res->data = (void *)kNFLength(M, currRing->qideal, v, iSyzComp, iLazyReduce); // NOTE: currRing :( return FALSE; } /// Get raw syzygies (idPrepare) static BOOLEAN idPrepare(leftv res, leftv h) { // extern int rGetISPos(const int p, const ring r); const ring r = currRing; const bool isSyz = rIsSyzIndexRing(r); const int posIS = rGetISPos(0, r); if ( !( (h!=NULL) && (h->Typ()==MODUL_CMD) && (h->Data() != NULL) ) ) { WerrorS("`idPrepare()` expected"); return TRUE; } const ideal I = reinterpret_cast(h->Data()); assume( I != NULL ); idTest(I); int iComp = -1; h=h->next; if ( (h!=NULL) && (h->Typ()==INT_CMD) ) { iComp = (int)((long)(h->Data())); } else { if( (!isSyz) && (-1 == posIS) ) { WerrorS("`idPrepare(<...>)` called on incompatible ring (not created by 'MakeSyzCompOrdering' or 'MakeInducedSchreyerOrdering'!)"); return TRUE; } if( isSyz ) iComp = rGetCurrSyzLimit(r); else iComp = id_RankFreeModule(r->typ[posIS].data.is.F, r); // ; } assume(iComp >= 0); intvec* w = reinterpret_cast(atGet(h, "isHomog", INTVEC_CMD)); tHomog hom = testHomog; // int add_row_shift = 0; // if (w!=NULL) { w = ivCopy(w); // add_row_shift = ww->min_in(); // // (*ww) -= add_row_shift; // // if (idTestHomModule(I, currRing->qideal, ww)) // { hom = isHomog; // w = ww; // } // else // { // //WarnS("wrong weights"); // delete ww; // w = NULL; // hom=testHomog; // } } // computes syzygies of h1, // works always in a ring with ringorder_s // NOTE: rSetSyzComp(syzcomp) should better be called beforehand // ideal idPrepare (ideal h1, tHomog hom, int syzcomp, intvec **w); ideal J = // idPrepare( I, hom, iComp, &w); kStd(I, currRing->qideal, hom, &w, NULL, iComp); idTest(J); if (w!=NULL) atSet(res, omStrDup("isHomog"), w, INTVEC_CMD); // if (w!=NULL) delete w; res->rtyp = MODUL_CMD; res->data = reinterpret_cast(J); return FALSE; } /// Get raw syzygies (idPrepare) static BOOLEAN _p_Content(leftv res, leftv h) { if ( !( (h!=NULL) && (h->Typ()==POLY_CMD) && (h->Data() != NULL) ) ) { WerrorS("`p_Content()` expected"); return TRUE; } const poly p = reinterpret_cast(h->Data()); pTest(p); pWrite(p); PrintLn(); p_Content( p, currRing); pTest(p); pWrite(p); PrintLn(); NoReturn(res); return FALSE; } static BOOLEAN _m2_end(leftv res, leftv h) { int ret = 0; if ( (h!=NULL) && (h->Typ()!=INT_CMD) ) { WerrorS("`m2_end([])` expected"); return TRUE; } ret = (int)(long)(h->Data()); m2_end( ret ); NoReturn(res); return FALSE; } // no args. // init num stats static BOOLEAN _NumberStatsInit(leftv res, leftv h) { if ( (h!=NULL) && (h->Typ()!=INT_CMD) ) { WerrorS("`NumberStatsInit([])` expected"); return TRUE; } unsigned long v = 0; if( h != NULL ) v = (unsigned long)(h->Data()); number_stats_Init(v); NoReturn(res); return FALSE; } // maybe one arg. // print num stats static BOOLEAN _NumberStatsPrint(leftv res, leftv h) { if ( (h!=NULL) && (h->Typ()!=STRING_CMD) ) { WerrorS("`NumberStatsPrint([])` expected"); return TRUE; } const char* msg = NULL; if( h != NULL ) msg = (const char*)(h->Data()); number_stats_Print(msg); NoReturn(res); return FALSE; } END_NAMESPACE extern "C" int SI_MOD_INIT(syzextra)(SModulFunctions* psModulFunctions) { #define ADD(C,D,E) \ psModulFunctions->iiAddCproc((currPack->libname? currPack->libname: ""), (char*)C, D, E); // #define ADD(A,B,C,D,E) ADD0(iiAddCproc, "", C, D, E) //#define ADD0(A,B,C,D,E) A(B, (char*)C, D, E) // #define ADD(A,B,C,D,E) ADD0(A->iiAddCproc, B, C, D, E) ADD("ClearContent", FALSE, _ClearContent); ADD("ClearDenominators", FALSE, _ClearDenominators); ADD("m2_end", FALSE, _m2_end); ADD("DetailedPrint", FALSE, DetailedPrint); ADD("leadmonomial", FALSE, _leadmonom); ADD("leadcomp", FALSE, leadcomp); ADD("leadrawexp", FALSE, leadrawexp); ADD("ISUpdateComponents", FALSE, ISUpdateComponents); ADD("SetInducedReferrence", FALSE, SetInducedReferrence); ADD("GetInducedData", FALSE, GetInducedData); ADD("SetSyzComp", FALSE, SetSyzComp); ADD("MakeInducedSchreyerOrdering", FALSE, MakeInducedSchreyerOrdering); ADD("MakeSyzCompOrdering", FALSE, MakeSyzCompOrdering); ADD("ProfilerStart", FALSE, _ProfilerStart); ADD("ProfilerStop", FALSE, _ProfilerStop ); ADD("noop", FALSE, noop); ADD("idPrepare", FALSE, idPrepare); ADD("reduce_syz", FALSE, reduce_syz); ADD("p_Content", FALSE, _p_Content); ADD("Tail", FALSE, Tail); ADD("ComputeLeadingSyzygyTerms", FALSE, _ComputeLeadingSyzygyTerms); ADD("Compute2LeadingSyzygyTerms", FALSE, _Compute2LeadingSyzygyTerms); ADD("Sort_c_ds", FALSE, _Sort_c_ds); ADD("FindReducer", FALSE, _FindReducer); ADD("ReduceTerm", FALSE, _ReduceTerm); ADD("TraverseTail", FALSE, _TraverseTail); ADD("SchreyerSyzygyNF", FALSE, _SchreyerSyzygyNF); ADD("ComputeSyzygy", FALSE, _ComputeSyzygy); ADD("ComputeResolution", FALSE, _ComputeResolution); // ADD("GetAMData", FALSE, GetAMData); ADD("NumberStatsInit", FALSE, _NumberStatsInit); ADD("NumberStatsPrint", FALSE, _NumberStatsPrint); // ADD("", FALSE, ); #undef ADD return MAX_TOK; } singular-4.0.3+ds/Singular/dyn_modules/syzextra/myNF.cc000066400000000000000000000164141266270727000231420ustar00rootroot00000000000000// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file DebugPrint.cc * * Here we implement dPrint-s. * * ABSTRACT: debug-detailed-printing * * @author Oleksandr Motsak * * **/ /*****************************************************************************/ // include header file #include #include #include #include #include #include #include #include #include // #include #include #include #include // #include #include "myNF.h" #ifdef HAVE_PLURAL #define PLURAL_INTERNAL_DECLARATIONS 1 #endif #include #include #include BEGIN_NAMESPACE() /// reduction procedure for the normal form, which uses pLength instead of pSize! static poly redNFLength (poly h,int &max_ind,int nonorm,kStrategy strat) { if (h==NULL) return NULL; int j; max_ind=strat->sl; if (0 > strat->sl) { return h; } LObject P(h); P.SetShortExpVector(); P.bucket = kBucketCreate(currRing); kBucketInit(P.bucket,P.p,pLength(P.p)); kbTest(P.bucket); #ifdef HAVE_RINGS BOOLEAN is_ring = rField_is_Ring(currRing); #endif #ifdef KDEBUG if (TEST_OPT_DEBUG) { PrintS("redNF: starting S: "); for( j = 0; j <= max_ind; j++ ) { Print("S[%d] (of size: %d): ", j, pLength(strat->S[j])); wrp(strat->S[j]); } }; #endif loop { j=kFindDivisibleByInS(strat,&max_ind,&P); if (j>=0) { #ifdef HAVE_RINGS if (!is_ring) { #endif int sl=pLength(strat->S[j]); int jj=j; loop { int sll; jj=kFindNextDivisibleByInS(strat,jj+1,max_ind,&P); if (jj<0) break; sll=pLength(strat->S[jj]); if (sll S%d:%d)\n",j,sl,jj,sll); #endif //else if (TEST_OPT_PROT) { PrintS("b"); mflush(); } j=jj; sl=sll; } } if ((nonorm==0) && (!nIsOne(pGetCoeff(strat->S[j])))) { pNorm(strat->S[j]); //if (TEST_OPT_PROT) { PrintS("n"); mflush(); } } #ifdef HAVE_RINGS } #endif nNormalize(pGetCoeff(P.p)); #ifdef KDEBUG if (TEST_OPT_DEBUG) { PrintS("red:"); wrp(h); PrintS(" with "); wrp(strat->S[j]); } #endif #ifdef HAVE_PLURAL if (rIsPluralRing(currRing)) { number coef; nc_kBucketPolyRed(P.bucket,strat->S[j],&coef); nDelete(&coef); } else #endif { number coef; coef=kBucketPolyRed(P.bucket,strat->S[j],pLength(strat->S[j]),strat->kNoether); nDelete(&coef); } h = kBucketGetLm(P.bucket); // FRAGE OLIVER if (h==NULL) { kBucketDestroy(&P.bucket); #ifdef KDEBUG if (TEST_OPT_DEBUG) { PrintS("redNF: starting S: "); for( j = 0; j <= max_ind; j++ ) { Print("S[%d] (of size: %d): ", j, pLength(strat->S[j])); wrp(strat->S[j]); } }; #endif return NULL; } kbTest(P.bucket); P.p=h; P.t_p=NULL; P.SetShortExpVector(); #ifdef KDEBUG if (TEST_OPT_DEBUG) { PrintS("\nto:"); wrp(h); PrintLn(); } #endif } else { P.p=kBucketClear(P.bucket); kBucketDestroy(&P.bucket); pNormalize(P.p); #ifdef KDEBUG if (TEST_OPT_DEBUG) { PrintS("redNF: starting S: "); for( j = 0; j <= max_ind; j++ ) { Print("S[%d] (of size: %d): ", j, pLength(strat->S[j])); wrp(strat->S[j]); } }; #endif return P.p; } } } poly kNF2Length (ideal F,ideal Q,poly q,kStrategy strat, int lazyReduce) { assume(q!=NULL); assume(!(idIs0(F)&&(Q==NULL))); // NF(q, std(0) in polynomial ring? // lazy_reduce flags: can be combined by | //#define KSTD_NF_LAZY 1 // do only a reduction of the leading term //#define KSTD_NF_NONORM 4 // only global: avoid normalization, return a multiply of NF poly p; // int i; //if ((idIs0(F))&&(Q==NULL)) // return pCopy(q); /*F=0*/ //strat->ak = id_RankFreeModule(F, RING!); /*- creating temp data structures------------------- -*/ BITSET save1; SI_SAVE_OPT1(save1); si_opt_1|=Sy_bit(OPT_REDTAIL); initBuchMoraCrit(strat); strat->initEcart = initEcartBBA; strat->enterS = enterSBba; #ifndef NO_BUCKETS strat->use_buckets = (!TEST_OPT_NOT_BUCKETS) && (!rIsPluralRing(currRing)); #endif /*- set S -*/ strat->sl = -1; /*- init local data struct.---------------------------------------- -*/ /*Shdl=*/initS(F,Q,strat); /*- compute------------------------------------------------------- -*/ //if ((TEST_OPT_INTSTRATEGY)&&(lazyReduce==0)) //{ // for (i=strat->sl;i>=0;i--) // pNorm(strat->S[i]); //} kTest(strat); if (TEST_OPT_PROT) { PrintS("r"); mflush(); } if (BVERBOSE(23)) kDebugPrint(strat); int max_ind; p = redNFLength(pCopy(q),max_ind,lazyReduce & KSTD_NF_NONORM,strat); if ((p!=NULL)&&((lazyReduce & KSTD_NF_LAZY)==0)) { if (TEST_OPT_PROT) { PrintS("t"); mflush(); } #ifdef HAVE_RINGS if (rField_is_Ring(currRing)) { p = redtailBba_Z(p,max_ind,strat); } else #endif { si_opt_1 &= ~Sy_bit(OPT_INTSTRATEGY); p = redtailBba(p,max_ind,strat,(lazyReduce & KSTD_NF_NONORM)==0); } } /*- release temp data------------------------------- -*/ omfree(strat->sevS); omfree(strat->ecartS); omfree(strat->T); omfree(strat->sevT); omfree(strat->R); omfree(strat->S_2_R); omfree(strat->L); omfree(strat->B); omfree(strat->fromQ); idDelete(&strat->Shdl); SI_RESTORE_OPT1(save1); if (TEST_OPT_PROT) PrintLn(); return p; } END_NAMESPACE BEGIN_NAMESPACE_SINGULARXX BEGIN_NAMESPACE(NF) poly kNFLength(ideal F, ideal Q, poly p,int syzComp, int lazyReduce) { if (p==NULL) return NULL; poly pp = p; #ifdef HAVE_PLURAL if(rIsSCA(currRing)) { const unsigned int m_iFirstAltVar = scaFirstAltVar(currRing); const unsigned int m_iLastAltVar = scaLastAltVar(currRing); pp = p_KillSquares(pp, m_iFirstAltVar, m_iLastAltVar, currRing); if(Q == currRing->qideal) Q = SCAQuotient(currRing); } #endif if ((idIs0(F))&&(Q==NULL)) { #ifdef HAVE_PLURAL if(p != pp) return pp; #endif return pCopy(p); /*F+Q=0*/ } kStrategy strat=new skStrategy; strat->syzComp = syzComp; strat->ak = si_max(id_RankFreeModule(F, currRing),pMaxComp(p)); poly res; if (rHasLocalOrMixedOrdering(currRing)==-1) res=kNF1(F,Q,pp,strat,lazyReduce); else res=kNF2Length(F,Q,pp,strat,lazyReduce); delete(strat); #ifdef HAVE_PLURAL if(pp != p) p_Delete(&pp, currRing); #endif return res; } END_NAMESPACE END_NAMESPACE_SINGULARXX // Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab singular-4.0.3+ds/Singular/dyn_modules/syzextra/myNF.h000066400000000000000000000021661266270727000230030ustar00rootroot00000000000000// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file myNF.h * * NF which uses pLength instead of pSize! * * ABSTRACT: NF using length * * @author Oleksandr Motsak * * **/ /*****************************************************************************/ #ifndef MYNF_H #define MYNF_H // include basic definitions #include "singularxx_defs.h" struct spolyrec; typedef struct spolyrec polyrec; typedef polyrec * poly; struct ip_sring; typedef struct ip_sring * ring; struct sip_sideal; typedef struct sip_sideal * ideal; BEGIN_NAMESPACE_SINGULARXX BEGIN_NAMESPACE(NF) /// high-level functio, which calls kNF2Length(redNFLength) poly kNFLength(ideal F, ideal Q, poly p, int syzComp, int lazyReduce); END_NAMESPACE END_NAMESPACE_SINGULARXX #endif /* #ifndef MYNF_H */ // Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab singular-4.0.3+ds/Singular/dyn_modules/syzextra/singularxx_defs.h000066400000000000000000000032621266270727000253350ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file singularxx_defs.h * * @author Alexander Dreyer * @date 2009-06-15 * * This file includes some basic definitions for the SINGULAR++ interface. * * @par Copyright: * (c) 2009 by The SINGULAR Team, see LICENSE file * **/ //***************************************************************************** // Note: inclusion of CSINGULARTypes.h at the end // Get configuration // #include "singular_config.h" #ifndef SINGULAR_singular_defs_h_ #define SINGULAR_singular_defs_h_ #ifdef HAVE_NAMESPACES #define BEGIN_NAMESPACE(a) namespace a { #define END_NAMESPACE } #define USING_NAMESPACE(a) using namespace a; #define FROM_NAMESPACE(a, s) a :: s #else #define BEGIN_NAMESPACE(a) #define END_NAMESPACE #define USING_NAMESPACE(a) #define FROM_NAMESPACE(a, s) s #endif #define SINGULARXXNAME Singular #define BEGIN_NAMESPACE_SINGULARXX BEGIN_NAMESPACE(SINGULARXXNAME) #define END_NAMESPACE_SINGULARXX END_NAMESPACE #define USING_NAMESPACE_SINGULARXX USING_NAMESPACE(SINGULARXXNAME) #define FROM_NAMESPACE_SINGULARXXNAME(s) FROM_NAMESPACE(SINGULARXXNAME, s) #define BEGIN_NAMESPACE_NONAME BEGIN_NAMESPACE() #ifndef HAVE_THROW # define SINGULARXX_THROW(type) throw type(); #else # define SINGULARXX_THROW(type) Werror(type().what()); #endif /// For optimizing if-branches #ifdef __GNUC__ #define LIKELY(expression) (__builtin_expect(!!(expression), 1)) #define UNLIKELY(expression) (__builtin_expect(!!(expression), 0)) #else #define LIKELY(expression) (expression) #define UNLIKELY(expression) (expression) #endif // #include "CSingularTypes.h" #endif /* SINGULAR_singular_defs_h_ */ singular-4.0.3+ds/Singular/dyn_modules/syzextra/syzextra.cc000066400000000000000000002236351266270727000241670ustar00rootroot00000000000000// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file syzextra.cc * * New implementations for the computation of syzygies and resolutions * * ABSTRACT: Computation of Syzygies due to Schreyer * * @author Oleksandr Motsak * **/ /*****************************************************************************/ // include header file #include #ifndef _GNU_SOURCE #define _GNU_SOURCE /*for qsort_r on cygwin, must be before system includes*/ #endif #include #include "syzextra.h" #include "DebugPrint.h" #include #include #include #include #include #include #include #include // for kBucket* #include // for sBucket* //#include // for CPolynomialSummator #include // for MIN_LENGTH_BUCKET #include #include #include #include #include #include #include #include #include #include #include // For iiAddCproc #include #include #ifndef RTIMER_BENCHMARKING # define RTIMER_BENCHMARKING 0 #endif // USING_NAMESPACE_SINGULARXX; USING_NAMESPACE( SINGULARXXNAME :: DEBUG ) BEGIN_NAMESPACE_SINGULARXX BEGIN_NAMESPACE(SYZEXTRA) BEGIN_NAMESPACE_NONAME #ifndef SING_NDEBUG ring SBucketFactory::_GetBucketRing(const SBucketFactory::Bucket& bt) { assume( bt != NULL ); return sBucketGetRing(bt); } bool SBucketFactory::_IsBucketEmpty(const SBucketFactory::Bucket& bt) { assume( bt != NULL ); return sIsEmpty(bt); } #endif SBucketFactory::Bucket SBucketFactory::_CreateBucket(const ring r) { const Bucket bt = sBucketCreate(r); assume( bt != NULL ); assume( _IsBucketEmpty(bt) ); assume( r == _GetBucketRing(bt) ); return bt; } void SBucketFactory::_DestroyBucket(SBucketFactory::Bucket & bt) { if( bt != NULL ) { assume( _IsBucketEmpty(bt) ); sBucketDestroy( &bt ); bt = NULL; } } class SBucketWrapper { typedef SBucketFactory::Bucket Bucket; private: Bucket m_bucket; SBucketFactory& m_factory; public: SBucketWrapper(const ring r, SBucketFactory& factory): m_bucket( factory.getBucket(r) ), m_factory( factory ) {} ~SBucketWrapper() { m_factory.putBucket( m_bucket ); } public: /// adds p to the internal bucket /// destroys p, l == length(p) inline void Add( poly p, const int l ) { assume( pLength(p) == l ); sBucket_Add_p( m_bucket, p, l ); } /// adds p to the internal bucket /// destroys p inline void Add( poly p ){ Add(p, pLength(p)); } poly ClearAdd() { poly p; int l; sBucketClearAdd(m_bucket, &p, &l); assume( pLength(p) == l ); return p; } }; static FORCE_INLINE poly pp_Add_qq( const poly a, const poly b, const ring R) { return p_Add_q( p_Copy(a, R), p_Copy(b, R), R ); } static FORCE_INLINE poly p_VectorProductLT( poly s, const ideal& L, const ideal& T, const ring& R) { assume( IDELEMS(L) == IDELEMS(T) ); poly vp = NULL; // resulting vector product while( s != NULL ) { const poly nxt = pNext(s); pNext(s) = NULL; if( !n_IsZero( p_GetCoeff(s, R), R) ) { const int i = p_GetComp(s, R) - 1; assume( i >= 0 ); assume( i < IDELEMS(L) ); p_SetComp(s, 0, R); p_SetmComp(s, R); vp = p_Add_q( vp, pp_Mult_qq( s, L->m[i], R ), R); vp = p_Add_q( vp, pp_Mult_qq( s, T->m[i], R ), R); } p_Delete(&s, R); s = nxt; }; assume( s == NULL ); return vp; } static FORCE_INLINE int atGetInt(idhdl rootRingHdl, const char* attribute, long def) { return ((int)(long)(atGet(rootRingHdl, attribute, INT_CMD, (void*)def))); } END_NAMESPACE BEGIN_NAMESPACE(SORT_c_ds) #if (defined(HAVE_QSORT_R) && (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || defined __FreeBSD__ || defined __BSD__ || defined OpenBSD3_1 || defined OpenBSD3_9)) static int cmp_c_ds(void *R, const void *p1, const void *p2){ #elif (defined(HAVE_QSORT_R) && (defined _GNU_SOURCE || defined __GNU__ || defined __linux__)) static int cmp_c_ds(const void *p1, const void *p2, void *R){ #else static int cmp_c_ds(const void *p1, const void *p2){ void *R = currRing; #endif assume(R != NULL); const int YES = 1; const int NO = -1; const ring r = (const ring) R; // TODO/NOTE: the structure is known: C, lp!!! assume( r == currRing ); // for now... const poly a = *(const poly*)p1; const poly b = *(const poly*)p2; assume( a != NULL ); assume( b != NULL ); p_LmTest(a, r); p_LmTest(b, r); const signed long iCompDiff = p_GetComp(a, r) - p_GetComp(b, r); // TODO: test this!!!!!!!!!!!!!!!! //return -( compare (c, qsorts) ) #ifndef SING_NDEBUG const int OPT__DEBUG = 0; if( OPT__DEBUG ) { PrintS("cmp_c_ds: a, b: \np1: "); dPrint(a, r, r, 0); PrintS("b: "); dPrint(b, r, r, 0); PrintLn(); } #endif if( iCompDiff > 0 ) return YES; if( iCompDiff < 0 ) return NO; assume( iCompDiff == 0 ); const signed long iDegDiff = p_Totaldegree(a, r) - p_Totaldegree(b, r); if( iDegDiff > 0 ) return YES; if( iDegDiff < 0 ) return NO; assume( iDegDiff == 0 ); #ifndef SING_NDEBUG if( OPT__DEBUG ) { PrintS("cmp_c_ds: a & b have the same comp & deg! "); PrintLn(); } #endif for (int v = rVar(r); v > 0; v--) { assume( v > 0 ); assume( v <= rVar(r) ); const signed int d = p_GetExp(a, v, r) - p_GetExp(b, v, r); if( d > 0 ) return YES; if( d < 0 ) return NO; assume( d == 0 ); } return 0; } /* static int cmp_poly(const poly &a, const poly &b) { const int YES = 1; const int NO = -1; const ring r = (const ring) currRing; // TODO/NOTE: the structure is known: C, lp!!! assume( r == currRing ); assume( a != NULL ); assume( b != NULL ); p_LmTest(a, r); p_LmTest(b, r); assume( p_GetComp(a, r) == 0 ); assume( p_GetComp(b, r) == 0 ); #ifndef SING_NDEBUG const int OPT__DEBUG = 0; if( OPT__DEBUG ) { PrintS("cmp_lex: a, b: \np1: "); dPrint(a, r, r, 0); PrintS("b: "); dPrint(b, r, r, 0); PrintLn(); } #endif for (int v = rVar(r); v > 0; v--) { assume( v > 0 ); assume( v <= rVar(r) ); const signed int d = p_GetExp(a, v, r) - p_GetExp(b, v, r); if( d > 0 ) return YES; if( d < 0 ) return NO; assume( d == 0 ); } return 0; } */ END_NAMESPACE /* namespace SORT_c_ds */ /// writes a monomial (p), /// uses form x*gen(.) if ko != coloumn number of p static void writeLatexTerm(const poly t, const ring r, const bool bCurrSyz = true, const bool bLTonly = true) { if( t == NULL ) { PrintS(" 0 "); return; } assume( r != NULL ); const coeffs C = r->cf; assume(C != NULL); poly p = t; BOOLEAN writePlus = FALSE; do { assume( p != NULL ); // write coef... number& n = p_GetCoeff(p, r); n_Normalize(n, C); BOOLEAN writeMult = FALSE; ///< needs * before pp or module generator BOOLEAN writeOne = FALSE; ///< need to write something after '-'! if( n_IsZero(n, C) ) { PrintS( writePlus? " + 0" : " 0 " ); writePlus = TRUE; writeMult = TRUE; // return; // yes? } if (n_IsMOne(n, C)) { PrintS(" - "); writeOne = TRUE; writePlus = FALSE; } else if (!n_IsOne(n, C)) { if( writePlus && n_GreaterZero(n, C) ) PrintS(" + "); StringSetS(""); n_WriteLong(n, C); if (true) { char *s = StringEndS(); PrintS(s); omFree(s); } writeMult = TRUE; writePlus = TRUE; } else writeOne = TRUE; // missing '1' if no PP and gen...!? // write monom... const short N = rVar(r); BOOLEAN wrotePP = FALSE; ///< needs * before module generator? for (short i = 0; i < N; i++) { const long ee = p_GetExp(p, i+1, r); if (ee!=0L) { if (writeMult) { PrintS(" "); writeMult = FALSE; } else if( writePlus ) PrintS(" + "); writePlus = FALSE; if (ee != 1L) Print(" %s^{%ld} ", rRingVar(i, r), ee); else Print(" %s ", rRingVar(i, r)); writeOne = FALSE; wrotePP = TRUE; } } writePlus = writePlus || wrotePP; writeMult = writeMult || wrotePP; // write module gen... const long comp = p_GetComp(p, r); if (comp > 0 ) { if (writeMult) PrintS(" "); else if( writePlus ) PrintS(" + "); if (bCurrSyz) Print(" \\\\GEN{%ld} ", comp); else Print(" \\\\GENP{%ld} ", comp); writeOne = FALSE; } if ( writeOne ) PrintS( writePlus? " + 1 " : " 1 " ); pIter(p); writePlus = TRUE; } while( (!bLTonly) && (p != NULL) ); } static FORCE_INLINE poly myp_Head(const poly p, const bool bIgnoreCoeff, const ring r) { assume( p != NULL ); p_LmCheckPolyRing1(p, r); poly np; omTypeAllocBin(poly, np, r->PolyBin); p_SetRingOfLm(np, r); memcpy(np->exp, p->exp, r->ExpL_Size*sizeof(long)); pNext(np) = NULL; pSetCoeff0(np, (bIgnoreCoeff)? NULL : n_Copy(pGetCoeff(p), r->cf)); p_LmCheckPolyRing1(np, r); return np; } /// return a new term: leading coeff * leading monomial of p /// with 0 leading component! poly leadmonom(const poly p, const ring r, const bool bSetZeroComp) { if( UNLIKELY(p == NULL ) ) return NULL; assume( p != NULL ); p_LmTest(p, r); poly m = p_LmInit(p, r); p_SetCoeff0(m, n_Copy(p_GetCoeff(p, r), r), r); if( bSetZeroComp ) p_SetComp(m, 0, r); p_Setm(m, r); assume( m != NULL ); assume( pNext(m) == NULL ); p_LmTest(m, r); if( bSetZeroComp ) assume( p_GetComp(m, r) == 0 ); return m; } poly p_Tail(const poly p, const ring r) { if( UNLIKELY(p == NULL) ) return NULL; else return p_Copy( pNext(p), r ); } ideal id_Tail(const ideal id, const ring r) { if( UNLIKELY(id == NULL) ) return NULL; const ideal newid = idInit(IDELEMS(id),id->rank); for (int i=IDELEMS(id) - 1; i >= 0; i--) newid->m[i] = p_Tail( id->m[i], r ); newid->rank = id_RankFreeModule(newid, currRing); return newid; } void Sort_c_ds(const ideal id, const ring r) { const int sizeNew = IDELEMS(id); #if ( (defined(HAVE_QSORT_R)) && (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || defined __FreeBSD__ || defined __BSD__ || defined OpenBSD3_1 || defined OpenBSD3_9) ) #define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, r, cmp) #elif ( (defined(HAVE_QSORT_R)) && (defined _GNU_SOURCE || defined __GNU__ || defined __linux__)) #define qsort_my(m, s, ss, r, cmp) qsort_r(m, s, ss, cmp, r) #else #define qsort_my(m, s, ss, r, cmp) qsort(m, s, ss, cmp) #endif if( sizeNew >= 2 ) qsort_my(id->m, sizeNew, sizeof(poly), r, FROM_NAMESPACE(SORT_c_ds, cmp_c_ds)); #undef qsort_my id->rank = id_RankFreeModule(id, r); } /// Clean up all the accumulated data void SchreyerSyzygyComputation::CleanUp() { extern void id_Delete (ideal*, const ring); id_Delete(const_cast(&m_idTails), m_rBaseRing); // TODO!!! /*if( m_sum_bucket != NULL ) { assume ( sIsEmpty(m_sum_bucket) ); sBucketDestroy(&m_sum_bucket); m_sum_bucket = NULL; }*/ if( m_spoly_bucket != NULL ) { kBucketDestroy(&m_spoly_bucket); m_spoly_bucket = NULL; } for( TCache::iterator it = m_cache.begin(); it != m_cache.end(); it++ ) { TP2PCache& T = it->second; for(TP2PCache::iterator vit = T.begin(); vit != T.end(); vit++ ) { p_Delete( (&(vit->second)), m_rBaseRing); p_Delete( const_cast(&(vit->first)), m_rBaseRing); } } } /* for( TTailTerms::const_iterator it = m_idTailTerms.begin(); it != m_idTailTerms.end(); it++ ) { const TTail& v = *it; for(TTail::const_iterator vit = v.begin(); vit != v.end(); vit++ ) delete const_cast(*vit); } */ int CReducerFinder::PreProcessTerm(const poly t, CReducerFinder& syzChecker) const { assume( t != NULL ); if( UNLIKELY(OPT__DEBUG & OPT__TAILREDSYZ) ) assume( !IsDivisible(t) ); // each input term should NOT be in const ring r = m_rBaseRing; if( LIKELY(OPT__TAILREDSYZ) ) if( p_LmIsConstant(t, r) ) // most basic case of baing coprime with L, whatever that is... return 1; // TODO: prove this...? // return false; // appears to be fine const long comp = p_GetComp(t, r); CReducersHash::const_iterator itr = m_hash.find(comp); if ( itr == m_hash.end() ) return 2; // no such leading component!!! assume( itr->first == comp ); const bool bIdealCase = (comp == 0); const bool bSyzCheck = syzChecker.IsNonempty(); // need to check even in ideal case????? proof? "&& !bIdealCase" if( LIKELY(OPT__TAILREDSYZ && (bIdealCase || bSyzCheck)) ) { const TReducers& v = itr->second; const int N = rVar(r); // TODO: extract exps of t beforehand?! bool coprime = true; for(TReducers::const_iterator vit = v.begin(); (vit != v.end()) && coprime; ++vit ) { assume( (*vit)->CheckLT( m_L ) ); const poly p = (*vit)->lt(); assume( p_GetComp(p, r) == comp ); // TODO: check if coprime with Leads... if OPT__TAILREDSYZ ! for( int var = N; var > 0; --var ) if( (p_GetExp(p, var, r) != 0) && (p_GetExp(t, var, r) != 0) ) { #ifndef SING_NDEBUG if( OPT__DEBUG | 0) { PrintS("CReducerFinder::PreProcessTerm, 't' is NOT co-prime with the following leading term: \n"); dPrint(p, r, r, 0); } #endif coprime = false; // t not coprime with p! break; } if( bSyzCheck && coprime ) { poly ss = p_LmInit(t, r); p_SetCoeff0(ss, n_Init(1, r), r); // for delete & printout only!... p_SetComp(ss, (*vit)->label() + 1, r); // coeff? p_Setm(ss, r); coprime = ( syzChecker.IsDivisible(ss) ); #ifndef SING_NDEBUG if( OPT__DEBUG && !coprime) { PrintS("CReducerFinder::PreProcessTerm, 't' is co-prime with p but may lead to NOT divisible syz.term: \n"); dPrint(ss, r, r, 0); } #endif p_LmDelete(&ss, r); // deletes coeff as well??? } assume( p == (*vit)->lt() ); assume( (*vit)->CheckLT( m_L ) ); } #ifndef SING_NDEBUG if( OPT__DEBUG && coprime ) PrintS("CReducerFinder::PreProcessTerm, the following 't' is 'co-prime' with all of leading terms! \n"); #endif return coprime? 3: 0; // t was coprime with all of leading terms!!! } // return true; // delete the term return 0; } void SchreyerSyzygyComputation::SetUpTailTerms() { const ideal idTails = m_idTails; assume( idTails != NULL ); assume( idTails->m != NULL ); const ring r = m_rBaseRing; unsigned long pp[4] = {0,0,0,0}; // count preprocessed terms... #ifndef SING_NDEBUG if( OPT__DEBUG | 0) { PrintS("SchreyerSyzygyComputation::SetUpTailTerms(): Tails: \n"); dPrint(idTails, r, r, 0); } #endif for( int p = IDELEMS(idTails) - 1; p >= 0; --p ) for( poly* tt = &(idTails->m[p]); (*tt) != NULL; ) { const poly t = *tt; const int k = m_div.PreProcessTerm(t, m_checker); // 0..3 assume( 0 <= k && k <= 3 ); pp[k]++; // collect stats if( k ) { #ifndef SING_NDEBUG if( OPT__DEBUG) { Print("SchreyerSyzygyComputation::SetUpTailTerms(): PP (%d) the following TT: \n", k); dPrint(t, r, r, 0); } #endif (*tt) = p_LmDeleteAndNext(t, r); // delete the lead and next... } else tt = &pNext(t); // go next? } #ifndef SING_NDEBUG if( OPT__DEBUG | 0) { PrintS("SchreyerSyzygyComputation::SetUpTailTerms(): Preprocessed Tails: \n"); dPrint(idTails, r, r, 0); } #endif if( UNLIKELY(OPT__PROT) ) { Print("(PP/ST: {c: %lu, C: %lu, P: %lu} + %lu)", pp[1], pp[2], pp[3], pp[0]); m_stat[0] += pp [0]; m_stat[1] += pp [1]; m_stat[2] += pp [2]; m_stat[3] += pp [3]; } } /* m_idTailTerms.resize( IDELEMS(idTails) ); for( unsigned int p = IDELEMS(idTails) - 1; p >= 0; p -- ) { TTail& v = m_idTailTerms[p]; poly t = idTails->m[p]; v.resize( pLength(t) ); unsigned int pp = 0; while( t != NULL ) { assume( t != NULL ); // TODO: compute L:t! // ideal reducers; // CReducerFinder m_reducers CTailTerm* d = v[pp] = new CTailTerm(); ++pp; pIter(t); } } */ void SchreyerSyzygyComputation::PrintStats() const { Print("SchreyerSyzygyComputation Stats: (PP/ST: {c: %lu, C: %lu, P: %lu} + %lu, LOT: %lu, LCM: %lu, ST:%lu, LK: %lu {*: %lu})\n", m_stat[1], m_stat[2], m_stat[3], m_stat[0], m_stat[4], m_stat[5], m_stat[8], m_stat[6] + m_stat[7], m_stat[7] ); } ideal SchreyerSyzygyComputation::Compute1LeadingSyzygyTerms() { const ideal& id = m_idLeads; const ring& r = m_rBaseRing; // const SchreyerSyzygyComputationFlags& attributes = m_atttributes; assume(!OPT__LEAD2SYZ); // 1. set of components S? // 2. for each component c from S: set of indices of leading terms // with this component? // 3. short exp. vectors for each leading term? const int size = IDELEMS(id); if( size < 2 ) { const ideal newid = idInit(1, 0); newid->m[0] = NULL; // zero ideal... return newid; } // TODO/NOTE: input is supposed to be (reverse-) sorted wrt "(c,ds)"!?? // components should come in groups: count elements in each group // && estimate the real size!!! // use just a vector instead??? const ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case! int k = 0; for (int j = 0; j < size; j++) { const poly p = id->m[j]; assume( p != NULL ); const int c = p_GetComp(p, r); for (int i = j - 1; i >= 0; i--) { const poly pp = id->m[i]; assume( pp != NULL ); const int cc = p_GetComp(pp, r); if( c != cc ) continue; const poly m = p_Init(r); // p_New??? // m = LCM(p, pp) / p! // TODO: optimize: knowing the ring structure: (C/lp)! for (int v = rVar(r); v > 0; v--) { assume( v > 0 ); assume( v <= rVar(r) ); const short e1 = p_GetExp(p , v, r); const short e2 = p_GetExp(pp, v, r); if( e1 >= e2 ) p_SetExp(m, v, 0, r); else p_SetExp(m, v, e2 - e1, r); } assume( (j > i) && (i >= 0) ); p_SetComp(m, j + 1, r); pNext(m) = NULL; p_SetCoeff0(m, n_Init(1, r->cf), r); // for later... p_Setm(m, r); // should not do anything!!! newid->m[k++] = m; } } // if( OPT__DEBUG & FALSE ) // { // PrintS("ComputeLeadingSyzygyTerms::Temp0: \n"); // dPrint(newid, r, r, 0); // } // the rest of newid is assumed to be zeroes... // simplify(newid, 2 + 32)?? // sort(newid, "C,ds")[1]??? id_DelDiv(newid, r); // #define SIMPL_LMDIV 32 // if( OPT__DEBUG & FALSE ) // { // PrintS("ComputeLeadingSyzygyTerms::Temp1: \n"); // dPrint(newid, r, r, 0); // } idSkipZeroes(newid); // #define SIMPL_NULL 2 // if( OPT__DEBUG ) // { // PrintS("ComputeLeadingSyzygyTerms::Output: \n"); // dPrint(newid, r, r, 0); // } Sort_c_ds(newid, r); return newid; } ideal SchreyerSyzygyComputation::Compute2LeadingSyzygyTerms() { const ideal& id = m_idLeads; const ring& r = m_rBaseRing; // const SchreyerSyzygyComputationFlags& attributes = m_atttributes; // 1. set of components S? // 2. for each component c from S: set of indices of leading terms // with this component? // 3. short exp. vectors for each leading term? const int size = IDELEMS(id); if( size < 2 ) { const ideal newid = idInit(1, 1); newid->m[0] = NULL; // zero module... return newid; } // TODO/NOTE: input is supposed to be sorted wrt "C,ds"!?? // components should come in groups: count elements in each group // && estimate the real size!!! // use just a vector instead??? ideal newid = idInit( (size * (size-1))/2, size); // maximal size: ideal case! int k = 0; for (int j = 0; j < size; j++) { const poly p = id->m[j]; assume( p != NULL ); const int c = p_GetComp(p, r); for (int i = j - 1; i >= 0; i--) { const poly pp = id->m[i]; assume( pp != NULL ); const int cc = p_GetComp(pp, r); if( c != cc ) continue; // allocate memory & zero it out! const poly m = p_Init(r); const poly mm = p_Init(r); // m = LCM(p, pp) / p! mm = LCM(p, pp) / pp! // TODO: optimize: knowing the ring structure: (C/lp)! for (int v = rVar(r); v > 0; v--) { assume( v > 0 ); assume( v <= rVar(r) ); const short e1 = p_GetExp(p , v, r); const short e2 = p_GetExp(pp, v, r); if( e1 >= e2 ) p_SetExp(mm, v, e1 - e2, r); // p_SetExp(m, v, 0, r); else p_SetExp(m, v, e2 - e1, r); // p_SetExp(mm, v, 0, r); } assume( (j > i) && (i >= 0) ); p_SetComp(m, j + 1, r); p_SetComp(mm, i + 1, r); const number& lc1 = p_GetCoeff(p , r); const number& lc2 = p_GetCoeff(pp, r); #if NODIVISION assume( n_IsOne(lc1, r->cf) ); assume( n_IsOne(lc2, r->cf) ); p_SetCoeff0( m, n_Init( 1, r->cf), r ); p_SetCoeff0(mm, n_Init(-1, r->cf), r ); #else number g = n_Lcm( lc1, lc2, r->cf ); p_SetCoeff0(m , n_Div(g, lc1, r), r); p_SetCoeff0(mm, n_InpNeg(n_Div(g, lc2, r), r), r); n_Delete(&g, r); #endif p_Setm(m, r); // should not do anything!!! p_Setm(mm, r); // should not do anything!!! pNext(m) = mm; // pNext(mm) = NULL; newid->m[k++] = m; } } // if( OPT__DEBUG & FALSE ) // { // PrintS("Compute2LeadingSyzygyTerms::Temp0: \n"); // dPrint(newid, r, r, 0); // } if( UNLIKELY(!OPT__TAILREDSYZ) ) { // simplify(newid, 2 + 32)?? // sort(newid, "C,ds")[1]??? id_DelDiv(newid, r); // #define SIMPL_LMDIV 32 // if( OPT__DEBUG & FALSE ) // { // PrintS("Compute2LeadingSyzygyTerms::Temp1 (deldiv): \n"); // dPrint(newid, r, r, 0); // } } else { // option(redSB); option(redTail); // TEST_OPT_REDSB // TEST_OPT_REDTAIL assume( r == currRing ); BITSET _save_test; SI_SAVE_OPT1(_save_test); SI_RESTORE_OPT1(Sy_bit(OPT_REDTAIL) | Sy_bit(OPT_REDSB) | _save_test); intvec* w=new intvec(IDELEMS(newid)); ideal tmp = kStd(newid, currRing->qideal, isHomog, &w); delete w; SI_RESTORE_OPT1(_save_test) id_Delete(&newid, r); newid = tmp; // if( OPT__DEBUG & FALSE ) // { // PrintS("Compute2LeadingSyzygyTerms::Temp1 (std): \n"); // dPrint(newid, r, r, 0); // } } idSkipZeroes(newid); Sort_c_ds(newid, r); return newid; } poly SchreyerSyzygyComputation::TraverseNF(const poly a, const poly a2) const { #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif const ideal& L = m_idLeads; const ideal& T = m_idTails; const ring& R = m_rBaseRing; const int r = p_GetComp(a, R) - 1; assume( r >= 0 && r < IDELEMS(T) ); assume( r >= 0 && r < IDELEMS(L) ); assume( a != NULL ); #ifndef SING_NDEBUG if( OPT__DEBUG ) { PrintS("SchreyerSyzygyComputation::TraverseNF(syz_lead, poly syz_2), \n"); PrintS("syz_lead: \n"); dPrint(a, R, R, 0); PrintS("syz_2: \n"); dPrint(a2, R, R, 0); PrintLn(); } #endif if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("{ \"proc\": \"TraverseNF\", \"nodelabel\": \""); writeLatexTerm(a, R); PrintS("\", \"children\": ["); } poly aa = leadmonom(a, R); assume( aa != NULL); // :( #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif poly t = TraverseTail(aa, r); if( a2 != NULL ) { assume( OPT__LEAD2SYZ ); if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("{ \"proc\": \"TraverseNF2\", \"nodelabel\": \""); writeLatexTerm(a2, R); PrintS("\", \"children\": ["); } // replace the following... ? const int r2 = p_GetComp(a2, R) - 1; poly aa2 = leadmonom(a2, R); // :( assume( r2 >= 0 && r2 < IDELEMS(T) ); poly s = TraverseTail(aa2, r2); p_Delete(&aa2, R); if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("], \"noderesult\": \""); writeLatexTerm(s, R, true, false); PrintS("\" },"); } t = p_Add_q(a2, p_Add_q(t, s, R), R); #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif } else t = p_Add_q(t, ReduceTerm(aa, L->m[r], a), R); // should be identical to bove with a2 p_Delete(&aa, R); if( UNLIKELY(OPT__TREEOUTPUT) ) { // poly tt = pp_Add_qq( a, t, R); PrintS("], \"noderesult\": \""); writeLatexTerm(t, R, true, false); PrintS("\" },"); // p_Delete(&tt, R); } #ifndef SING_NDEBUG if( OPT__DEBUG ) { PrintS("SchreyerSyzygyComputation::TraverseNF(syz_lead, poly syz_2), ==>>> \n"); dPrint(t, R, R, 0); PrintLn(); } #endif #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif return t; } void SchreyerSyzygyComputation::ComputeSyzygy() { #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif assume( m_idLeads != NULL ); assume( m_idTails != NULL ); const ideal& L = m_idLeads; const ideal& T = m_idTails; ideal& TT = m_syzTails; const ring& R = m_rBaseRing; // if( m_sum_bucket == NULL ) // m_sum_bucket = sBucketCreate(R); // assume ( sIsEmpty(m_sum_bucket) ); if( m_spoly_bucket == NULL ) m_spoly_bucket = kBucketCreate(R); assume( IDELEMS(L) == IDELEMS(T) ); #ifdef SING_NDEBUG int t, r; // for rtimer benchmarking in prot realease mode #endif if( UNLIKELY(OPT__TREEOUTPUT) ) Print("\n{ \"syzygylayer\": \"%d\", \"hybridnf\": \"%d\", \"diagrams\": \n[", OPT__SYZNUMBER, OPT__HYBRIDNF ); if( UNLIKELY(OPT__PROT) ) Print("\n[%d]", OPT__SYZNUMBER ); if( m_syzLeads == NULL ) { #ifdef SING_NDEBUG if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) ) { t = getTimer(); r = getRTimer(); Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::ComputeLeadingSyzygyTerms: t: %d, r: %d\n", r, t, r); } #endif ComputeLeadingSyzygyTerms( OPT__LEAD2SYZ && !OPT__IGNORETAILS ); // 2 terms OR 1 term! #ifdef SING_NDEBUG if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) ) { t = getTimer() - t; r = getRTimer() - r; Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::ComputeLeadingSyzygyTerms: dt: %d, dr: %d\n", getRTimer(), t, r); } #endif } assume( m_syzLeads != NULL ); ideal& LL = m_syzLeads; const int size = IDELEMS(LL); TT = idInit(size, 0); if( size == 1 && LL->m[0] == NULL ) { if( UNLIKELY(OPT__TREEOUTPUT) ) PrintS("]},"); return; } // use hybrid (Schreyer NF) method? const bool method = (OPT__HYBRIDNF == 1); // || (OPT__HYBRIDNF == 2 && OPT__SYZNUMBER < 3); if( UNLIKELY(OPT__PROT) ) Print("[%s NF|%s]",(method) ? "PR" : "TT", (NOPRODUCT == 1)? "_,_": "^*^" ); if( LIKELY(!OPT__IGNORETAILS) ) { if( T != NULL ) { #ifdef SING_NDEBUG if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) ) { t = getTimer(); r = getRTimer(); Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SetUpTailTerms(): t: %d, r: %d\n", r, t, r); } #endif SetUpTailTerms(); #ifdef SING_NDEBUG if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) ) { t = getTimer() - t; r = getRTimer() - r; Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SetUpTailTerms(): dt: %d, dr: %d\n", getRTimer(), t, r); } #endif } } #ifdef SING_NDEBUG if( UNLIKELY(OPT__PROT & RTIMER_BENCHMARKING) ) { t = getTimer(); r = getRTimer(); Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SyzygyLift: t: %d, r: %d\n", r, t, r); } #endif #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif // for( int k = 0; k < size; ++k ) // TODO: should be fine now! for( int k = size - 1; k >= 0; --k ) { const poly a = LL->m[k]; assume( a != NULL ); poly a2 = pNext(a); // Splitting 2-terms Leading syzygy module if( a2 != NULL ) pNext(a) = NULL; if( UNLIKELY(OPT__IGNORETAILS) ) { TT->m[k] = NULL; assume( a2 != NULL ); if( a2 != NULL ) p_Delete(&a2, R); continue; } // TT->m[k] = a2; #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif poly nf; if( method ) nf = SchreyerSyzygyNF(a, a2); else nf = TraverseNF(a, a2); #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif TT->m[k] = nf; if( UNLIKELY(OPT__SYZCHECK) ) { // TODO: check the correctness (syzygy property): a + TT->m[k] should be a syzygy!!! poly s = pp_Add_qq( a, TT->m[k], R); // current syzygy poly vp = p_VectorProductLT(s, L, T, R); if( UNLIKELY( OPT__DEBUG && (vp != NULL) && ! OPT__TREEOUTPUT ) ) { Warn("SchreyerSyzygyComputation::ComputeSyzygy: failed syzygy property for syzygy [%d], non-zero image is as follows: ", k); dPrint(vp, R, R, 0); p_Delete(&vp, R); PrintS("SchreyerSyzygyComputation::ComputeSyzygy: Wrong syzygy is as follows: "); s = pp_Add_qq( a, TT->m[k], R); dPrint(s, R, R, 0); p_Delete(&s, R); PrintS("SchreyerSyzygyComputation::ComputeSyzygy: Testing with the other method"); if( !method ) s = SchreyerSyzygyNF(a, a2); else s = TraverseNF(a, a2); s = p_Add_q( p_Copy(a, R), s, R); // another syzygy // :(((( PrintS("SchreyerSyzygyComputation::ComputeSyzygy: The other method gives the following syzygy: "); dPrint(s, R, R, 0); vp = p_VectorProductLT(s, L, T, R); if( vp == NULL ) { PrintS("SchreyerSyzygyComputation::ComputeSyzygy: .... which is correct!!! "); } else { Warn("SchreyerSyzygyComputation::ComputeSyzygy: failed to compute syzygy tail[%d] with both methods!!! Non-zero image (2nd) is as follows: ", k); dPrint(vp, R, R, 0); } #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif } else assume( vp == NULL ); if( UNLIKELY( OPT__PROT && (vp != NULL) ) ) Warn("ERROR: SyzCheck failed, wrong tail: [%d]\n\n", k); // check k'th syzygy failed p_Delete(&vp, R); } #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif } #ifdef SING_NDEBUG if( UNLIKELY( OPT__PROT & RTIMER_BENCHMARKING ) ) { t = getTimer() - t; r = getRTimer() - r; Print("\n%% %5d **!TIME4!** SchreyerSyzygyComputation::ComputeSyzygy::SyzygyLift: dt: %d, dr: %d\n", getRTimer(), t, r); } #endif TT->rank = id_RankFreeModule(TT, R); if( UNLIKELY(OPT__TREEOUTPUT) ) PrintS("\n]},"); if( UNLIKELY(OPT__PROT) ) PrintLn(); } void SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms(bool bComputeSecondTerms) { // const SchreyerSyzygyComputationFlags& attributes = m_atttributes; // const BOOLEAN OPT__LEAD2SYZ = attributes.OPT__LEAD2SYZ; // const BOOLEAN OPT__TAILREDSYZ = attributes.OPT__TAILREDSYZ; assume( m_syzLeads == NULL ); if( UNLIKELY(bComputeSecondTerms) ) { assume( OPT__LEAD2SYZ ); // m_syzLeads = FROM_NAMESPACE(INTERNAL, _Compute2LeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes)); m_syzLeads = Compute2LeadingSyzygyTerms(); } else { assume( !OPT__LEAD2SYZ ); m_syzLeads = Compute1LeadingSyzygyTerms(); } // m_syzLeads = FROM_NAMESPACE(INTERNAL, _ComputeLeadingSyzygyTerms(m_idLeads, m_rBaseRing, m_atttributes)); // NOTE: set m_LS if tails are to be reduced! assume( m_syzLeads!= NULL ); if ( LIKELY( OPT__TAILREDSYZ && !OPT__IGNORETAILS && (IDELEMS(m_syzLeads) > 0) && !((IDELEMS(m_syzLeads) == 1) && (m_syzLeads->m[0] == NULL)) ) ) { m_LS = m_syzLeads; m_checker.Initialize(m_syzLeads); #ifndef SING_NDEBUG if( OPT__DEBUG ) { const ring& r = m_rBaseRing; PrintS("SchreyerSyzygyComputation::ComputeLeadingSyzygyTerms: \n"); PrintS("m_syzLeads: \n"); dPrint(m_syzLeads, r, r, 0); PrintS("m_checker.Initialize(m_syzLeads) => \n"); m_checker.DebugPrint(); } #endif assume( m_checker.IsNonempty() ); // TODO: this always fails... BUG???? } if( UNLIKELY( OPT__PROT ) ) Print("(L%dS:%d)", bComputeSecondTerms ? 2 : 1, IDELEMS(m_syzLeads)); } poly SchreyerSyzygyComputation::SchreyerSyzygyNF(const poly syz_lead, poly syz_2) const { assume( !OPT__IGNORETAILS ); const ideal& L = m_idLeads; const ideal& T = m_idTails; const ring& r = m_rBaseRing; assume( syz_lead != NULL ); #ifndef SING_NDEBUG if( OPT__DEBUG ) { PrintS("SchreyerSyzygyComputation::SchreyerSyzygyNF(syz_lead, poly syz_2), \n"); PrintS("syz_lead: \n"); dPrint(syz_lead, r, r, 0); PrintS("syz_2: \n"); dPrint(syz_2, r, r, 0); PrintLn(); } #endif if( UNLIKELY( OPT__TREEOUTPUT ) ) { PrintS("{ \"nodelabel\": \""); writeLatexTerm(syz_lead, r); PrintS("\", \"children\": ["); } if( syz_2 == NULL ) { const int rr = p_GetComp(syz_lead, r) - 1; assume( rr >= 0 && rr < IDELEMS(T) ); assume( rr >= 0 && rr < IDELEMS(L) ); #if NOPRODUCT syz_2 = m_div.FindReducer(syz_lead, L->m[rr], syz_lead, m_checker); p_Test(syz_2, r); if( UNLIKELY( OPT__TREEOUTPUT ) ) { PrintS("{ \"nodelabel\": \""); writeLatexTerm(syz_2, r); PrintS("\" },"); } #else poly aa = leadmonom(syz_lead, r); assume( aa != NULL); // :( aa = p_Mult_mm(aa, L->m[rr], r); if( UNLIKELY( OPT__TREEOUTPUT ) ) { PrintS("{ \"nodelabel\": \""); writeLatexTerm(syz_2, r); PrintS("\", \"edgelabel\": \""); writeLatexTerm(aa, r, false); PrintS("\" },"); } syz_2 = m_div.FindReducer(aa, syz_lead, m_checker); p_Test(syz_2, r); p_Delete(&aa, r); #endif } assume( syz_2 != NULL ); // by construction of S-Polynomial assume( L != NULL ); assume( T != NULL ); assume( IDELEMS(L) == IDELEMS(T) ); int c = p_GetComp(syz_lead, r) - 1; assume( c >= 0 && c < IDELEMS(T) ); if( m_spoly_bucket == NULL ) m_spoly_bucket = kBucketCreate(r); SBucketWrapper tail(r, m_sum_bucket_factory); kBucket_pt bucket = m_spoly_bucket; assume( bucket != NULL ); kbTest(bucket); m_spoly_bucket = NULL; // kBucketInit(bucket, NULL, 0); // not needed!? poly p = leadmonom(syz_lead, r); // :( // poly spoly = pp_Mult_qq(p, T->m[c], r); kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], 0); // TODO: store pLength(T->m[c]) separately!? p_Delete(&p, r); kbTest(bucket); c = p_GetComp(syz_2, r) - 1; assume( c >= 0 && c < IDELEMS(T) ); p = leadmonom(syz_2, r); // :( // spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r); kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], 0); // pLength(T->m[c])?! kbTest(bucket); p_Delete(&p, r); // const bool bUsePolynomial = TEST_OPT_NOT_BUCKETS; // || (pLength(spoly) < MIN_LENGTH_BUCKET); // CPolynomialSummator tail(r, bUsePolynomial); tail.Add(syz_2, 1); kbTest(bucket); for( poly spoly = kBucketExtractLm(bucket); spoly != NULL; p_LmDelete(&spoly, r), spoly = kBucketExtractLm(bucket)) { kbTest(bucket); poly t = m_div.FindReducer(spoly, NULL, m_checker); p_Test(t, r); if( t != NULL ) { p = leadmonom(t, r); // :( c = p_GetComp(t, r) - 1; assume( c >= 0 && c < IDELEMS(T) ); if(UNLIKELY( OPT__TREEOUTPUT )) { PrintS("{ \"nodelabel\": \""); writeLatexTerm(t, r); PrintS("\", \"edgelabel\": \""); writeLatexTerm(spoly, r, false); PrintS("\" },"); } kBucket_Plus_mm_Mult_pp(bucket, p, T->m[c], 0); // pLength(T->m[c])? // spoly = p_Add_q(spoly, pp_Mult_qq(p, T->m[c], r), r); p_Delete(&p, r); tail.Add(t, 1); } // otherwise discard that leading term altogether! else if( UNLIKELY(OPT__PROT) ) ++ m_stat[4]; // PrintS("$"); // LOT kbTest(bucket); } kbTest(bucket); // now bucket must be empty! assume( kBucketClear(bucket) == NULL ); const poly result = tail.ClearAdd(); // TODO: use Merge with sBucket??? if( m_spoly_bucket == NULL ) m_spoly_bucket = bucket; else kBucketDestroy(&bucket); if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("]},"); } #ifndef SING_NDEBUG if( OPT__DEBUG ) { PrintS("SchreyerSyzygyComputation::SchreyerSyzygyNF(syz_lead, poly syz_2) =>>> \n"); dPrint(result, r, r, 0); PrintLn(); // TODO: Add SyzCheck!!!??? } #endif return result; } // namespace { // }; bool my_p_LmCmp (poly a, poly b, const ring r) { return p_LmCmp(a, b, r) == -1; } // TODO: change to simple lex. memory compare! // NOTE: need p_Copy?????? for image + multiplier!!??? // NOTE: better store complete syz. terms!!? poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, const int tail) const { #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif const ring& r = m_rBaseRing; assume(m_idTails != NULL && m_idTails->m != NULL); assume( tail >= 0 && tail < IDELEMS(m_idTails) ); p_Test(multiplier, r); if( UNLIKELY(OPT__NOCACHING) ) return ComputeImage(multiplier, tail); // TODO: store (multiplier, tail) -.-^-.-^-.--> ! TCache::iterator top_itr = m_cache.find(tail); if ( top_itr != m_cache.end() ) { assume( top_itr->first == tail ); TP2PCache& T = top_itr->second; TP2PCache::iterator itr = T.find(multiplier); if( itr != T.end() ) // Yey - Reuse!!! { assume( p_LmEqual(itr->first, multiplier, r) ); if( itr->second == NULL ) // leadcoeff plays no role if value is NULL! return (NULL); if( UNLIKELY( OPT__TREEOUTPUT ) ) { // PrintS("{ \"nodelabel\": \""); writeLatexTerm(multiplier, r, false); // Print(" \\\\GEN{%d}\", \"children\": [ ", tail + 1); PrintS("{ \"proc\": \"TTLookup\", \"nodelabel\": \""); writeLatexTerm(itr->first, r, false); Print(" \\\\GEN{%d}\", \"Lookup\": \"", tail + 1); writeLatexTerm(itr->second, r, true, false); PrintS("\", "); } poly p = p_Copy(itr->second, r); // COPY!!! p_Test(multiplier, r); if( !n_Equal( pGetCoeff(multiplier), pGetCoeff(itr->first), r) ) // normalize coeffs!? { number n = n_Div( pGetCoeff(multiplier), pGetCoeff(itr->first), r); // new number if( UNLIKELY( OPT__TREEOUTPUT ) ) { StringSetS(""); n_Write(n, r); char* s = StringEndS(); Print("\"recale\": \"%s\", ", s); omFree(s); } if( UNLIKELY( OPT__PROT ) ) ++ m_stat[7]; // PrintS("l*"); // lookup & rescale p = p_Mult_nn(p, n, r); // ! n_Delete(&n, r); } else if( UNLIKELY( OPT__PROT ) ) ++ m_stat[6]; // PrintS("l"); // lookup no rescale if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("\"noderesult\": \""); writeLatexTerm(p, r, true, false); PrintS("\" },"); } #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif p_Test(multiplier, r); return p; } if( UNLIKELY(OPT__TREEOUTPUT) ) { Print("{ \"proc\": \"TTStore%d\", \"nodelabel\": \"", tail + 1); writeLatexTerm(multiplier, r, false); Print(" \\\\GEN{%d}\", \"children\": [", tail + 1); } p_Test(multiplier, r); const poly p = ComputeImage(multiplier, tail); if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("], \"noderesult\": \""); writeLatexTerm(p, r, true, false); PrintS("\" },"); } if( UNLIKELY(OPT__PROT) ) ++ m_stat[8]; // PrintS("S"); // store p_Test(multiplier, r); T.insert( TP2PCache::value_type(myp_Head(multiplier, (p==NULL), r), p) ); // T[ multiplier ] = p; p_Test(multiplier, r); // if( p == NULL ) // return (NULL); #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif return p_Copy(p, r); } CCacheCompare o(r); TP2PCache T(o); if( UNLIKELY(OPT__TREEOUTPUT) ) { Print("{ \"proc\": \"TTStore%d\", \"nodelabel\": \"", 0); writeLatexTerm(multiplier, r, false); Print(" \\\\GEN{%d}\", \"children\": [", tail + 1); } const poly p = ComputeImage(multiplier, tail); if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("], \"noderesult\": \""); writeLatexTerm(p, r, true, false); PrintS("\" },"); } if( UNLIKELY( OPT__PROT ) ) ++ m_stat[8]; // PrintS("S"); // store // %d", tail + 1); T.insert( TP2PCache::value_type(myp_Head(multiplier, (p==NULL), r), p) ); m_cache.insert( TCache::value_type(tail, T) ); // if( p == NULL ) // return (NULL); #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif return p_Copy(p, r); } poly SchreyerSyzygyComputation::ComputeImage(poly multiplier, const int tail) const { const ring& r = m_rBaseRing; assume(m_idTails != NULL && m_idTails->m != NULL); assume( tail >= 0 && tail < IDELEMS(m_idTails) ); p_Test(multiplier, r); const poly t = m_idTails->m[tail]; // !!! if(t != NULL) { if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("{ \"proc\": \"ComputeImage\", \"nodelabel\": \""); writeLatexTerm(multiplier, r, false); Print(" \\\\GEN{%d}\", \"edgelabel\": \"", tail + 1); writeLatexTerm(t, r, false); PrintS("\", \"children\": ["); } const poly p = TraverseTail(multiplier, t); p_Test(multiplier, r); if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("], \"noderesult\": \""); writeLatexTerm(p, r, true, false); PrintS("\" },"); } return p; } return NULL; } poly SchreyerSyzygyComputation::TraverseTail(poly multiplier, poly tail) const { assume( !OPT__IGNORETAILS ); const ideal& L = m_idLeads; const ideal& T = m_idTails; const ring& r = m_rBaseRing; assume( multiplier != NULL ); assume( L != NULL ); assume( T != NULL ); p_Test(multiplier, r); #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif if( UNLIKELY( !( (!OPT__TAILREDSYZ) || m_lcm.Check(multiplier) )) ) { if( UNLIKELY(OPT__TAILREDSYZ && OPT__PROT) ) { ++ m_stat[5]; // PrintS("%"); // check LCM ! #ifndef SING_NDEBUG if( OPT__DEBUG ) { PrintS("\nTT,%:"); dPrint(multiplier, r, r, 0); PrintS(", * :"); dPrint(tail, r, r, 0); PrintLn(); } #endif } return NULL; } // const bool bUsePolynomial = TEST_OPT_NOT_BUCKETS; // || (pLength(tail) < MIN_LENGTH_BUCKET); SBucketWrapper sum(r, m_sum_bucket_factory); /* sBucket_pt sum; if( m_sum_bucket == NULL ) sum = sBucketCreate(r); else { if( !sIsEmpty(m_sum_bucket) ) sum = sBucketCreate(r); else { sum = m_sum_bucket; m_sum_bucket = NULL; } } assume( sum != NULL ); assume ( sIsEmpty(sum) ); assume( r == sBucketGetRing(sum) ); */ // poly s; int len; // CPolynomialSummator sum(r, bUsePolynomial); // poly s = NULL; if( UNLIKELY( OPT__TREEOUTPUT & 0 ) ) { Print("{ \"proc\": \"TTPoly\", \"nodelabel\": \""); writeLatexTerm(multiplier, r, false); Print(" * \\\\ldots \", \"children\": ["); } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! for(poly p = tail; p != NULL; p = pNext(p)) // iterate over the tail { // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! const poly rt = ReduceTerm(multiplier, p, NULL); // TODO: also return/store length? sum.Add(rt); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // const int lp = pLength(rt); // if( rt != NULL && lp != 0 ) // sBucket_Add_p(sum, rt, lp); } // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // sBucketClearAdd(sum, &s, &len); // Will Not Clear?!? const poly s = sum.ClearAdd(); // assume( sum != NULL ); assume ( sIsEmpty(sum) ); /* if( m_sum_bucket == NULL ) m_sum_bucket = sum; else sBucketDestroy(&sum); assume( pLength(s) == len ); */ #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif if( UNLIKELY( OPT__TREEOUTPUT & 0 ) ) { PrintS("], \"noderesult\": \""); writeLatexTerm(s, r, true, false); PrintS("\" },"); } p_Test(multiplier, r); return s; } poly SchreyerSyzygyComputation::ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck) const { #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif assume( !OPT__IGNORETAILS ); const ideal& L = m_idLeads; const ideal& T = m_idTails; const ring& r = m_rBaseRing; assume( multiplier != NULL ); assume( term4reduction != NULL ); assume( L != NULL ); assume( T != NULL ); p_Test(multiplier, r); // simple implementation with FindReducer: poly s = NULL; if( (!OPT__TAILREDSYZ) || m_lcm.Check(multiplier) ) // TODO: UNLIKELY / LIKELY ???? { #if NOPRODUCT s = m_div.FindReducer(multiplier, term4reduction, syztermCheck, m_checker); // s ???? p_Test(s, r); p_Test(multiplier, r); if( s == NULL ) // No Reducer? { if( UNLIKELY(OPT__PROT) ) ++ m_stat[4]; // PrintS("$"); // LOT return NULL; } if( UNLIKELY( OPT__TREEOUTPUT ) ) { poly product = pp_Mult_mm(multiplier, term4reduction, r); PrintS("{ \"proc\": \"RdTrmNoP\", \"nodelabel\": \""); writeLatexTerm(s, r); PrintS("\", \"edgelabel\": \""); writeLatexTerm(product, r, false); p_Delete(&product, r); } #else // NOTE: only LT(term4reduction) should be used in the following: poly product = pp_Mult_mm(multiplier, term4reduction, r); p_Test(product, r); s = m_div.FindReducer(product, syztermCheck, m_checker); // ?? p_Test(s, r); p_Test(multiplier, r); if( s == NULL ) // No Reducer? { if( UNLIKELY(OPT__PROT) ) ++ m_stat[4]; // PrintS("$"); // LOT return NULL; } if( UNLIKELY(OPT__TREEOUTPUT) ) { PrintS("{ \"proc\": \"RdTrmP\", \"nodelabel\": \""); writeLatexTerm(s, r); PrintS("\", \"edgelabel\": \""); writeLatexTerm(product, r, false); } p_Delete(&product, r); #endif } #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif if( s == NULL ) // No Reducer? { if( UNLIKELY( OPT__TAILREDSYZ && OPT__PROT) ) { ++ m_stat[5]; // PrintS("%"); // check LCM ! #ifndef SING_NDEBUG if( OPT__DEBUG ) { PrintS("\n%: RedTail("); dPrint(multiplier, r, r, 0); PrintS(" * : "); dPrint(term4reduction, r,r,0 ); PrintS(", { "); dPrint(syztermCheck,r,r,0 ); PrintS(" }) "); PrintLn(); } #endif } return NULL; } p_Test(multiplier, r); p_Test(s, r); poly b = leadmonom(s, r); p_Test(b, r); const int c = p_GetComp(s, r) - 1; assume( c >= 0 && c < IDELEMS(T) ); if( UNLIKELY( OPT__TREEOUTPUT ) ) PrintS("\", \"children\": ["); const poly t = TraverseTail(b, c); // T->m[c]; if( UNLIKELY( OPT__TREEOUTPUT ) ) { PrintS("], \"noderesult\": \""); writeLatexTerm(t, r, true, false); PrintS("\""); if( syztermCheck != NULL ) { PrintS(", \"syztermCheck\":\"" ); writeLatexTerm(syztermCheck, r, true, false); PrintS("\" },"); } else PrintS(" },"); } p_Test(multiplier, r); if( t != NULL ) s = p_Add_q(s, t, r); #ifndef SING_NDEBUG if( OPT__DEBUG ) { m_div.Verify(); m_checker.Verify(); } #endif p_Test(multiplier, r); return s; } SchreyerSyzygyComputationFlags::SchreyerSyzygyComputationFlags(idhdl rootRingHdl): OPT__DEBUG( atGetInt(rootRingHdl,"DEBUG", 0) ), OPT__LEAD2SYZ( atGetInt(rootRingHdl, "LEAD2SYZ", 0) ), OPT__TAILREDSYZ( atGetInt(rootRingHdl, "TAILREDSYZ", 1) ), OPT__HYBRIDNF( atGetInt(rootRingHdl, "HYBRIDNF", 0) ), OPT__IGNORETAILS( atGetInt(rootRingHdl, "IGNORETAILS", 0) ), OPT__SYZNUMBER( atGetInt(rootRingHdl, "SYZNUMBER", 0) ), OPT__TREEOUTPUT( atGetInt(rootRingHdl, "TREEOUTPUT", 0) ), OPT__SYZCHECK( atGetInt(rootRingHdl, "SYZCHECK", 0) ), OPT__PROT(TEST_OPT_PROT), OPT__NOCACHING( atGetInt(rootRingHdl, "NOCACHING", 0) ), m_rBaseRing( rootRingHdl->data.uring ) { #ifndef SING_NDEBUG if( OPT__DEBUG & 0 ) { PrintS("SchreyerSyzygyComputationFlags: \n"); Print(" DEBUG: \t%d\n", OPT__DEBUG); // Print(" SYZCHECK : \t%d\n", OPT__SYZCHECK); Print(" LEAD2SYZ: \t%d\n", OPT__LEAD2SYZ); Print(" TAILREDSYZ: \t%d\n", OPT__TAILREDSYZ); Print(" IGNORETAILS: \t%d\n", OPT__IGNORETAILS); Print(" TREEOUTPUT: \t%d\n", OPT__TREEOUTPUT); Print(" SYZCHECK: \t%d\n", OPT__SYZCHECK); } #endif // TODO: just current setting! assume( rootRingHdl == currRingHdl ); assume( rootRingHdl->typ == RING_CMD ); assume( m_rBaseRing == currRing ); // move the global ring here inside??? } CLeadingTerm::CLeadingTerm(unsigned int _label, const poly _lt, const ring R): m_sev( p_GetShortExpVector(_lt, R) ), m_label( _label ), m_lt( _lt ) #ifndef SING_NDEBUG , _R(R), m_lt_copy( myp_Head(_lt, true, R) ) // note that p_LmEqual only tests exponents! #endif { #ifndef SING_NDEBUG assume( pNext(m_lt_copy) == NULL ); #endif assume( sev() == p_GetShortExpVector(lt(), R) ); } #ifndef SING_NDEBUG CLeadingTerm::~CLeadingTerm() { assume( p_LmEqual(m_lt, m_lt_copy, _R) ); assume( m_sev == p_GetShortExpVector(m_lt, _R) ); poly p = const_cast(m_lt_copy); p_Delete(&p, _R); } poly CLeadingTerm::lt() const { assume( p_LmEqual(m_lt, m_lt_copy, _R) ); assume( m_sev == p_GetShortExpVector(m_lt, _R) ); return m_lt; } unsigned long CLeadingTerm::sev() const { assume( p_LmEqual(m_lt, m_lt_copy, _R) ); assume( m_sev == p_GetShortExpVector(m_lt, _R) ); return m_sev; } unsigned int CLeadingTerm::label() const { assume( p_LmEqual(m_lt, m_lt_copy, _R) ); assume( m_sev == p_GetShortExpVector(m_lt, _R) ); return m_label; } #endif CReducerFinder::~CReducerFinder() { for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++ ) { const TReducers& v = it->second; for(TReducers::const_iterator vit = v.begin(); vit != v.end(); vit++ ) delete const_cast(*vit); } } void CReducerFinder::Initialize(const ideal L) { assume( m_L == NULL || m_L == L ); if( m_L == NULL ) m_L = L; assume( m_L == L ); if( L != NULL ) { const ring& R = m_rBaseRing; assume( R != NULL ); for( int k = IDELEMS(L) - 1; k >= 0; k-- ) { const poly a = L->m[k]; // assume( a != NULL ); // NOTE: label is k \in 0 ... |L|-1!!! if( a != NULL ) m_hash[p_GetComp(a, R)].push_back( new CLeadingTerm(k, a, R) ); } } } CReducerFinder::CReducerFinder(const ideal L, const SchreyerSyzygyComputationFlags& flags): SchreyerSyzygyComputationFlags(flags), m_L(const_cast(L)), // for debug anyway m_hash() { assume( flags.m_rBaseRing == m_rBaseRing ); if( L != NULL ) Initialize(L); } /// _p_LmDivisibleByNoComp for a | b*c static inline BOOLEAN _p_LmDivisibleByNoComp(const poly a, const poly b, const poly c, const ring r) { int i=r->VarL_Size - 1; unsigned long divmask = r->divmask; unsigned long la, lb; if (r->VarL_LowIndex >= 0) { i += r->VarL_LowIndex; do { la = a->exp[i]; lb = b->exp[i] + c->exp[i]; if ((la > lb) || (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask))) { pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE); return FALSE; } i--; } while (i>=r->VarL_LowIndex); } else { do { la = a->exp[r->VarL_Offset[i]]; lb = b->exp[r->VarL_Offset[i]] + c->exp[r->VarL_Offset[i]]; if ((la > lb) || (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask))) { pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE); return FALSE; } i--; } while (i>=0); } #ifdef HAVE_RINGS assume( !rField_is_Ring(r) ); // not implemented for rings...! #endif return TRUE; } bool CLeadingTerm::CheckLT( const ideal & L ) const { // for( int i = IDELEMS(L); i >= 0; --i) assume( pNext(L->m[i]) == NULL ); // ??? return ( L->m[label()] == lt() ); } bool CLeadingTerm::DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const { // may have no coeff yet // assume ( !n_IsZero( p_GetCoeff(product, r), r ) ); assume ( !n_IsZero( p_GetCoeff(lt(), r), r ) ); assume( sev() == p_GetShortExpVector(lt(), r) ); assume( product != NULL ); assume( (p_GetComp(lt(), r) == p_GetComp(product, r)) || (p_GetComp(lt(), r) == 0) ); #ifndef SING_NDEBUG assume( r == _R ); #endif // const int k = label(); // assume( m_L->m[k] == p ); return p_LmShortDivisibleByNoComp(lt(), sev(), product, not_sev, r); } #if NOPRODUCT /// as DivisibilityCheck(multiplier * t, ...) for monomial 'm' /// and a module term 't' bool CLeadingTerm::DivisibilityCheck(const poly m, const poly t, const unsigned long not_sev, const ring r) const { assume ( !n_IsZero( p_GetCoeff(lt(), r), r ) ); assume( sev() == p_GetShortExpVector(lt(), r) ); assume( m != NULL ); assume( t != NULL ); assume ( !n_IsZero( p_GetCoeff(m, r), r ) ); assume ( !n_IsZero( p_GetCoeff(t, r), r ) ); // assume( p_GetComp(m, r) == 0 ); assume( (p_GetComp(lt(), r) == p_GetComp(t, r)) || (p_GetComp(lt(), r) == 0) ); p_Test(m, r); p_Test(t, r); // const int k = label(); // assume( m_L->m[k] == p ); #ifndef SING_NDEBUG assume( r == _R ); #endif if (sev() & not_sev) return false; return _p_LmDivisibleByNoComp(lt(), m, t, r); // return p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r); } #endif /// TODO: class CDivisorEnumerator: public SchreyerSyzygyComputationFlags { private: const CReducerFinder& m_reds; const poly m_product; const unsigned long m_not_sev; const long m_comp; CReducerFinder::CReducersHash::const_iterator m_itr; CReducerFinder::TReducers::const_iterator m_current, m_finish; bool m_active; public: CDivisorEnumerator(const CReducerFinder& self, const poly product): SchreyerSyzygyComputationFlags(self), m_reds(self), m_product(product), m_not_sev(~p_GetShortExpVector(product, m_rBaseRing)), m_comp(p_GetComp(product, m_rBaseRing)), m_itr(), m_current(), m_finish(), m_active(false) { assume( m_comp >= 0 ); assume( m_reds.m_L != NULL ); /// TODO: m_L should stay the same!!! assume( product != NULL ); // may have no coeff yet :( // assume ( !n_IsZero( p_GetCoeff(product, m_rBaseRing), m_rBaseRing ) ); #ifndef SING_NDEBUG if( OPT__DEBUG ) m_reds.Verify(); #endif } inline bool Reset() { m_active = false; m_itr = m_reds.m_hash.find(m_comp); if( m_itr == m_reds.m_hash.end() ) return false; assume( m_itr->first == m_comp ); m_current = (m_itr->second).begin(); m_finish = (m_itr->second).end(); if (m_current == m_finish) return false; // m_active = true; return true; } const CLeadingTerm& Current() const { assume( m_active ); assume( m_current != m_finish ); return *(*m_current); } inline bool MoveNext() { assume( m_current != m_finish ); if( m_active ) ++m_current; else m_active = true; // for Current() // looking for the next good entry for( ; m_current != m_finish; ++m_current ) { assume( Current().CheckLT( m_reds.m_L ) ); if( Current().DivisibilityCheck(m_product, m_not_sev, m_rBaseRing) ) { #ifndef SING_NDEBUG if( OPT__DEBUG ) { Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().label()); dPrint(Current().lt(), m_rBaseRing, m_rBaseRing, 0); } #endif // m_active = true; assume( Current().CheckLT( m_reds.m_L ) ); return true; } assume( Current().CheckLT( m_reds.m_L ) ); } // the end... :( assume( m_current == m_finish ); m_active = false; return false; } }; bool CReducerFinder::IsDivisible(const poly product) const { #ifndef SING_NDEBUG if( OPT__DEBUG ) Verify(); #endif assume( product != NULL ); // NOTE: q may have no coeff!!! CDivisorEnumerator itr(*this, product); if( !itr.Reset() ) return false; return itr.MoveNext(); /* const ring& r = m_rBaseRing; const long comp = p_GetComp(product, r); const unsigned long not_sev = ~p_GetShortExpVector(product, r); assume( comp >= 0 ); CReducersHash::const_iterator it = m_hash.find(comp); // same module component assume( m_L != NULL ); if( it == m_hash.end() ) return false; // assume comp! const TReducers& reducers = it->second; for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ ) { assume( (*vit)->CheckLT( m_L ) ); if( (*vit)->DivisibilityCheck(product, not_sev, r) ) { if( OPT__DEBUG ) { Print("_FindReducer::Test LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + (*vit)->label()); dPrint((*vit)->lt(), r, r, 0); } return true; } } return false; */ } #ifndef SING_NDEBUG void CReducerFinder::Verify() const { const ring& r = m_rBaseRing; for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++) { const TReducers& reducers = it->second; for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ ) { assume( (*vit)->CheckLT( m_L ) ); const poly p = (*vit)->lt(); const unsigned long p_sev = (*vit)->sev(); assume( p_sev == p_GetShortExpVector(p, r) ); assume( p_GetComp(p, r) == it->first ); const int k = (*vit)->label(); assume( m_L->m[k] == p ); pp_Test(p, r, r); } } } void CReducerFinder::DebugPrint() const { const ring& r = m_rBaseRing; for( CReducersHash::const_iterator it = m_hash.begin(); it != m_hash.end(); it++) { Print("Hash Key: %ld, Values: \n", it->first); const TReducers& reducers = it->second; for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ ) { assume( (*vit)->CheckLT( m_L ) ); const int k = (*vit)->label(); const poly p = (*vit)->lt(); pp_Test(p, r, r); assume( m_L->m[k] == p ); const unsigned long p_sev = (*vit)->sev(); assume( p_sev == p_GetShortExpVector(p, r) ); assume( p_GetComp(p, r) == it->first ); Print("L[%d]: ", k); dPrint(p, r, r, 0); Print("SEV: %ld\n", p_sev); assume( m_L->m[k] == p ); } } } #endif #if NOPRODUCT /// TODO: class CDivisorEnumerator2: public SchreyerSyzygyComputationFlags { private: const CReducerFinder& m_reds; const poly m_multiplier, m_term; const unsigned long m_not_sev; const long m_comp; CReducerFinder::CReducersHash::const_iterator m_itr; CReducerFinder::TReducers::const_iterator m_current, m_finish; bool m_active; public: CDivisorEnumerator2(const CReducerFinder& self, const poly m, const poly t): SchreyerSyzygyComputationFlags(self), m_reds(self), m_multiplier(m), m_term(t), m_not_sev(~p_GetShortExpVector(m, t, m_rBaseRing)), m_comp(p_GetComp(t, m_rBaseRing)), m_itr(), m_current(), m_finish(), m_active(false) { assume( m_comp >= 0 ); assume( m_reds.m_L != NULL ); assume( m_multiplier != NULL ); assume( m_term != NULL ); assume( m != NULL ); assume( t != NULL ); assume ( !n_IsZero( p_GetCoeff(m, m_rBaseRing), m_rBaseRing ) ); assume ( !n_IsZero( p_GetCoeff(t, m_rBaseRing), m_rBaseRing ) ); p_Test(m, m_rBaseRing); // assume( p_GetComp(m_multiplier, m_rBaseRing) == 0 ); #ifndef SING_NDEBUG if( OPT__DEBUG ) m_reds.Verify(); #endif } inline bool Reset() { m_active = false; m_itr = m_reds.m_hash.find(m_comp); if( m_itr == m_reds.m_hash.end() ) return false; assume( m_itr->first == m_comp ); m_current = (m_itr->second).begin(); m_finish = (m_itr->second).end(); if (m_current == m_finish) return false; return true; } const CLeadingTerm& Current() const { assume( m_active ); assume( m_current != m_finish ); return *(*m_current); } inline bool MoveNext() { assume( m_current != m_finish ); if( m_active ) ++m_current; else m_active = true; // looking for the next good entry for( ; m_current != m_finish; ++m_current ) { assume( Current().CheckLT( m_reds.m_L ) ); if( Current().DivisibilityCheck(m_multiplier, m_term, m_not_sev, m_rBaseRing) ) { #ifndef SING_NDEBUG if( OPT__DEBUG ) { Print("CDivisorEnumerator::MoveNext::est LS: q is divisible by LS[%d] !:((, diviser is: ", 1 + Current().label()); dPrint(Current().lt(), m_rBaseRing, m_rBaseRing, 0); } #endif // m_active = true; assume( Current().CheckLT( m_reds.m_L ) ); return true; } assume( Current().CheckLT( m_reds.m_L ) ); } // the end... :( assume( m_current == m_finish ); m_active = false; return false; } }; poly CReducerFinder::FindReducer(const poly multiplier, const poly t, const poly syzterm, const CReducerFinder& syz_checker) const { const ring& r = m_rBaseRing; #ifndef SING_NDEBUG if( OPT__DEBUG ) { Verify(); syz_checker.Verify(); } #endif p_Test(multiplier, r); CDivisorEnumerator2 itr(*this, multiplier, t); if( !itr.Reset() ) return NULL; // don't care about the module component of multiplier (as it may be the syzygy term) // product = multiplier * t? assume( multiplier != NULL ); assume( t != NULL ); const ideal& L = m_L; assume( L != NULL ); // for debug/testing only! long c = 0; if (syzterm != NULL) c = p_GetComp(syzterm, r) - 1; assume( c >= 0 && c < IDELEMS(L) ); p_Test(multiplier, r); if (UNLIKELY( OPT__DEBUG && (syzterm != NULL) )) { const poly m = L->m[c]; assume( m != NULL ); assume( pNext(m) == NULL ); // def @@c = leadcomp(syzterm); int @@r = int(@@c); // def @@product = leadmonomial(syzterm) * L[@@r]; poly lm = p_Mult_mm( leadmonom(syzterm, r, true), m, r); // !NC :( poly pr = p_Mult_q( leadmonom(multiplier, r, true), leadmonom(t, r, false), r); // !NC :( assume( p_EqualPolys(lm, pr, r) ); p_Delete(&lm, r); p_Delete(&pr, r); } #ifndef SING_NDEBUG if( OPT__DEBUG ) { Verify(); syz_checker.Verify(); } #endif const BOOLEAN to_check = (syz_checker.IsNonempty()); // OPT__TAILREDSYZ && // const poly q = p_One(r); const poly q = p_New(r); pNext(q) = NULL; if( UNLIKELY(OPT__DEBUG) ) p_SetCoeff0(q, 0, r); // for printing q assume( pNext(q) == NULL ); p_Test(multiplier, r); while( itr.MoveNext() ) { assume( itr.Current().CheckLT( L ) ); // ??? const poly p = itr.Current().lt(); // ??? const int k = itr.Current().label(); p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t // TODO: do it once? p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k])) p_SetComp(q, k + 1, r); p_Setm(q, r); p_Test(multiplier, r); // cannot allow something like: a*gen(i) - a*gen(i) if (syzterm != NULL && (k == c)) if (p_ExpVectorEqual(syzterm, q, r)) { #ifndef SING_NDEBUG if( OPT__DEBUG ) { Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: "); dPrint(syzterm, r, r, 0); } #endif assume( itr.Current().CheckLT( L ) ); // ??? continue; } // while the complement (the fraction) is not reducible by leading syzygies if( to_check && syz_checker.IsDivisible(q) ) { #ifndef SING_NDEBUG if( OPT__DEBUG ) { PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: "); } #endif assume( itr.Current().CheckLT( L ) ); // ??? continue; } number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r); #if NODIVISION // we assume all leading coeffs to be 1! assume( n_IsOne(p_GetCoeff(p, r), r->cf) ); #else if( !n_IsOne( p_GetCoeff(p, r), r ) ) n = n_Div(n, p_GetCoeff(p, r), r); #endif p_SetCoeff0(q, n_InpNeg(n, r), r); // n_Delete(&n, r); #ifndef SING_NDEBUG if( OPT__DEBUG ) { Verify(); syz_checker.Verify(); } #endif p_Test(multiplier, r); p_Test(q, r); assume( itr.Current().CheckLT( L ) ); // ??? return q; } /* const long comp = p_GetComp(t, r); assume( comp >= 0 ); const unsigned long not_sev = ~p_GetShortExpVector(multiplier, t, r); // ! // for( int k = IDELEMS(L)-1; k>= 0; k-- ) // { // const poly p = L->m[k]; // // if ( p_GetComp(p, r) != comp ) // continue; // // const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!! // looking for an appropriate diviser p = L[k]... CReducersHash::const_iterator it = m_hash.find(comp); // same module component if( it == m_hash.end() ) return NULL; // assume comp! assume( m_L != NULL ); const TReducers& reducers = it->second; for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ ) { const poly p = (*vit)->lt(); // ?? const int k = (*vit)->label(); assume( L->m[k] == p ); // CheckLT // const unsigned long p_sev = (*vit)->sev(); // assume( p_sev == p_GetShortExpVector(p, r) ); // if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) ) // continue; if( !(*vit)->DivisibilityCheck(multiplier, t, not_sev, r) ) continue; // if (p_sev & not_sev) continue; // if( !_p_LmDivisibleByNoComp(p, multiplier, t, r) ) continue; p_ExpVectorSum(q, multiplier, t, r); // q == product == multiplier * t p_ExpVectorDiff(q, q, p, r); // (LM(product) / LM(L[k])) p_SetComp(q, k + 1, r); p_Setm(q, r); // cannot allow something like: a*gen(i) - a*gen(i) if (syzterm != NULL && (k == c)) if (p_ExpVectorEqual(syzterm, q, r)) { if( OPT__DEBUG ) { Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: "); dPrint(syzterm, r, r, 0); } continue; } // while the complement (the fraction) is not reducible by leading syzygies if( to_check && syz_checker.IsDivisible(q) ) { if( OPT__DEBUG ) { PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: "); } continue; } number n = n_Mult( p_GetCoeff(multiplier, r), p_GetCoeff(t, r), r); p_SetCoeff0(q, n_InpNeg( n_Div(n, p_GetCoeff(p, r), r), r), r); n_Delete(&n, r); return q; } */ p_LmFree(q, r); #ifndef SING_NDEBUG if( OPT__DEBUG ) { Verify(); syz_checker.Verify(); } #endif p_Test(multiplier, r); return NULL; } #endif poly CReducerFinder::FindReducer(const poly product, const poly syzterm, const CReducerFinder& syz_checker) const { #ifndef SING_NDEBUG if( OPT__DEBUG ) { Verify(); syz_checker.Verify(); } #endif CDivisorEnumerator itr(*this, product); if( !itr.Reset() ) return NULL; const ring& r = m_rBaseRing; assume( product != NULL ); const ideal& L = m_L; assume( L != NULL ); // for debug/testing only! long c = 0; if (syzterm != NULL) c = p_GetComp(syzterm, r) - 1; assume( c >= 0 && c < IDELEMS(L) ); if (UNLIKELY( OPT__DEBUG && (syzterm != NULL) )) { const poly m = L->m[c]; assume( m != NULL ); assume( pNext(m) == NULL ); poly lm = p_Mult_mm(leadmonom(syzterm, r), m, r); assume( p_EqualPolys(lm, product, r) ); // def @@c = leadcomp(syzterm); int @@r = int(@@c); // def @@product = leadmonomial(syzterm) * L[@@r]; p_Delete(&lm, r); } #ifndef SING_NDEBUG if( OPT__DEBUG ) { Verify(); syz_checker.Verify(); } #endif const BOOLEAN to_check = (syz_checker.IsNonempty()); // OPT__TAILREDSYZ && const poly q = p_New(r); pNext(q) = NULL; if( UNLIKELY(OPT__DEBUG) ) p_SetCoeff0(q, 0, r); // ONLY for printing q while( itr.MoveNext() ) { assume( itr.Current().CheckLT( L ) ); // ??? const poly p = itr.Current().lt(); // ?? const int k = itr.Current().label(); p_ExpVectorDiff(q, product, p, r); // (LM(product) / LM(L[k])) p_SetComp(q, k + 1, r); p_Setm(q, r); // cannot allow something like: a*gen(i) - a*gen(i) if (syzterm != NULL && (k == c)) if (p_ExpVectorEqual(syzterm, q, r)) { #ifndef SING_NDEBUG if( OPT__DEBUG ) { Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: "); dPrint(syzterm, r, r, 0); } #endif assume( itr.Current().CheckLT( L ) ); // ??? continue; } // while the complement (the fraction) is not reducible by leading syzygies if( to_check && syz_checker.IsDivisible(q) ) // ????? { #ifndef SING_NDEBUG if( OPT__DEBUG ) { PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: "); } #endif assume( itr.Current().CheckLT( L ) ); // ??? continue; } #if NODIVISION assume( n_IsOne(p_GetCoeff(p, r), r->cf) ); p_SetCoeff0(q, n_InpNeg( n_Copy(p_GetCoeff(product, r), r), r), r); #else p_SetCoeff0(q, n_InpNeg( n_Div( p_GetCoeff(product, r), p_GetCoeff(p, r), r), r), r); #endif assume( itr.Current().CheckLT( L ) ); // ??? #ifndef SING_NDEBUG if( OPT__DEBUG ) { Verify(); syz_checker.Verify(); } #endif return q; } /* const long comp = p_GetComp(product, r); const unsigned long not_sev = ~p_GetShortExpVector(product, r); assume( comp >= 0 ); // for( int k = IDELEMS(L)-1; k>= 0; k-- ) // { // const poly p = L->m[k]; // // if ( p_GetComp(p, r) != comp ) // continue; // // const unsigned long p_sev = p_GetShortExpVector(p, r); // to be stored in m_hash!!! // looking for an appropriate diviser p = L[k]... CReducersHash::const_iterator it = m_hash.find(comp); // same module component if( it == m_hash.end() ) return NULL; assume( m_L != NULL ); const TReducers& reducers = it->second; const BOOLEAN to_check = (syz_checker.IsNonempty()); // OPT__TAILREDSYZ && const poly q = p_New(r); pNext(q) = NULL; if( OPT__DEBUG ) p_SetCoeff0(q, 0, r); // for printing q for(TReducers::const_iterator vit = reducers.begin(); vit != reducers.end(); vit++ ) { const poly p = (*vit)->lt(); // ??? assume( p_GetComp(p, r) == comp ); const int k = (*vit)->label(); assume( L->m[k] == p ); // CheckLT const unsigned long p_sev = (*vit)->sev(); assume( p_sev == p_GetShortExpVector(p, r) ); if( !p_LmShortDivisibleByNoComp(p, p_sev, product, not_sev, r) ) continue; // // ... which divides the product, looking for the _1st_ appropriate one! // if( !p_LmDivisibleByNoComp(p, product, r) ) // included inside p_LmShortDivisibleBy! // continue; p_ExpVectorDiff(q, product, p, r); // (LM(product) / LM(L[k])) p_SetComp(q, k + 1, r); p_Setm(q, r); // cannot allow something like: a*gen(i) - a*gen(i) if (syzterm != NULL && (k == c)) if (p_ExpVectorEqual(syzterm, q, r)) { if( OPT__DEBUG ) { Print("_FindReducer::Test SYZTERM: q == syzterm !:((, syzterm is: "); dPrint(syzterm, r, r, 0); } continue; } // while the complement (the fraction) is not reducible by leading syzygies if( to_check && syz_checker.IsDivisible(q) ) { if( OPT__DEBUG ) { PrintS("_FindReducer::Test LS: q is divisible by LS[?] !:((: "); } continue; } p_SetCoeff0(q, n_InpNeg( n_Div( p_GetCoeff(product, r), p_GetCoeff(p, r), r), r), r); return q; } */ p_LmFree(q, r); #ifndef SING_NDEBUG if( OPT__DEBUG ) { Verify(); syz_checker.Verify(); } #endif return NULL; } CLCM::CLCM(const ideal& L, const SchreyerSyzygyComputationFlags& flags): SchreyerSyzygyComputationFlags(flags), std::vector(), m_compute(false), m_N(rVar(flags.m_rBaseRing)) { const ring& R = m_rBaseRing; assume( flags.m_rBaseRing == R ); assume( R != NULL ); assume( L != NULL ); if( LIKELY( OPT__TAILREDSYZ && !OPT__HYBRIDNF && (L != NULL) )) // TODO: not hybrid!? { const int l = IDELEMS(L); assume( l > 0 ); resize(l, false); for( int k = l - 1; k >= 0; k-- ) { const poly a = L->m[k]; assume( a != NULL ); for (unsigned int j = m_N; j > 0; j--) if ( !(*this)[j] ) (*this)[j] = (p_GetExp(a, j, R) > 0); } m_compute = true; } } bool CLCM::Check(const poly m) const { assume( m != NULL ); if( m_compute && (m != NULL)) { const ring& R = m_rBaseRing; assume( OPT__TAILREDSYZ && !OPT__HYBRIDNF ); for (unsigned int j = m_N; j > 0; j--) if ( (*this)[j] ) if(p_GetExp(m, j, R) > 0) return true; return false; } else return true; } CCacheCompare::CCacheCompare(): m_ring(currRing) {} template class std::vector; template class std::vector; template class std::map< CReducerFinder::TComponentKey, CReducerFinder::TReducers >; template class std::map; template class std::map; template class std::stack ; END_NAMESPACE END_NAMESPACE_SINGULARXX // Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab singular-4.0.3+ds/Singular/dyn_modules/syzextra/syzextra.h000066400000000000000000000430511266270727000240210ustar00rootroot00000000000000// -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file syzextra.h * * Computation of Syzygies * * ABSTRACT: Computation of Syzygies due to Schreyer * * @author Oleksandr Motsak * **/ /*****************************************************************************/ #ifndef SYZEXTRA_H #define SYZEXTRA_H #include #include #include #include // include basic definitions #include "singularxx_defs.h" struct spolyrec; typedef struct spolyrec polyrec; typedef polyrec* poly; struct ip_sring; typedef struct ip_sring* ring; typedef struct ip_sring const* const_ring; struct sip_sideal; typedef struct sip_sideal * ideal; class idrec; typedef idrec * idhdl; class kBucket; typedef kBucket* kBucket_pt; #ifndef NOPRODUCT # define NOPRODUCT 1 #endif // set to 1 if all leading coeffs are assumed to be all =1... // note the use of simplify on input in SSinit! #ifndef NODIVISION # define NODIVISION 1 #endif BEGIN_NAMESPACE_SINGULARXX BEGIN_NAMESPACE(SYZEXTRA) poly leadmonom(const poly p, const ring r, const bool bSetZeroComp = true); /// return the tail of a given polynomial or vector /// returns NULL if input is NULL, otherwise /// the result is a new polynomial/vector in the ring r poly p_Tail(const poly p, const ring r); /// return the tail of a given ideal or module /// returns NULL if input is NULL, otherwise /// the result is a new ideal/module in the ring r /// NOTE: the resulting rank is autocorrected ideal id_Tail(const ideal id, const ring r); /// inplace sorting of the module (ideal) id wrt <_(c,ds) void Sort_c_ds(const ideal id, const ring r); class sBucket; typedef sBucket* sBucket_pt; /** @class SBucketFactory syzextra.h * * sBucket Factory * * Cleate/store/reuse buckets * */ class SBucketFactory: private std::stack { private: typedef std::stack Base; // typedef std::vector Memory; // typedef std::deque Memory; // typedef std::stack Base; public: typedef Base::value_type Bucket; SBucketFactory(const ring r) #ifndef SING_NDEBUG : m_ring(r) #endif { push ( _CreateBucket(r) ); // start with at least one sBucket...? assume( top() != NULL ); }; ~SBucketFactory() { while( !empty() ) { _DestroyBucket( top() ); pop(); } } Bucket getBucket(const ring r, const bool remove = true) { assume( r == m_ring ); Bucket bt = NULL; if( !empty() ) { bt = top(); if( remove ) pop(); } else { bt = _CreateBucket(r); if( !remove ) { push(bt); assume( bt == top() ); } } assume( bt != NULL ); assume( _IsBucketEmpty(bt) ); assume( r == _GetBucketRing(bt) ); return bt; } // TODO: this may be spared if we give-out a smart Bucket (which returns here upon its destructor!) void putBucket(const Bucket & bt, const bool replace = false) { assume( bt != NULL ); assume( _IsBucketEmpty(bt) ); assume( m_ring == _GetBucketRing(bt) ); if( empty() ) push( bt ); else { if( replace ) top() = bt; else { if( bt != top() ) push( bt ); } } assume( bt == top() ); } private: #ifndef SING_NDEBUG const ring m_ring; ///< For debugging: all buckets are over the same ring... right?! /// get bucket ring static ring _GetBucketRing(const Bucket& bt); static bool _IsBucketEmpty(const Bucket& bt); #endif /// inital allocation for new buckets static Bucket _CreateBucket(const ring r); /// we only expect empty buckets to be left at the end for destructor /// bt will be set to NULL static void _DestroyBucket(Bucket & bt); private: SBucketFactory(); SBucketFactory(const SBucketFactory&); void operator=(const SBucketFactory&); }; /// Computation attribute storage struct SchreyerSyzygyComputationFlags { SchreyerSyzygyComputationFlags(idhdl rootRingHdl); SchreyerSyzygyComputationFlags(const SchreyerSyzygyComputationFlags& attr): OPT__DEBUG(attr.OPT__DEBUG), OPT__LEAD2SYZ(attr.OPT__LEAD2SYZ), OPT__TAILREDSYZ(attr.OPT__TAILREDSYZ), OPT__HYBRIDNF(attr.OPT__HYBRIDNF), OPT__IGNORETAILS(attr.OPT__IGNORETAILS), OPT__SYZNUMBER(attr.OPT__SYZNUMBER), OPT__TREEOUTPUT(attr.OPT__TREEOUTPUT), OPT__SYZCHECK(attr.OPT__SYZCHECK), OPT__PROT(attr.OPT__PROT), OPT__NOCACHING(attr.OPT__NOCACHING), m_rBaseRing(attr.m_rBaseRing) {} /// output all the intermediate states const int OPT__DEBUG; // DebugOutput; /// ? const int OPT__LEAD2SYZ; // TwoLeadingSyzygyTerms; /// Reduce syzygy tails wrt the leading syzygy terms const int OPT__TAILREDSYZ; // TailReducedSyzygies; /// Use the usual NF's S-poly reduction while dropping lower order terms /// 2 means - smart selection! const int OPT__HYBRIDNF; // UseHybridNF /// ignore tails and compute the pure Schreyer frame const int OPT__IGNORETAILS; // @IGNORETAILS /// Syzygy level (within a resolution) mutable int OPT__SYZNUMBER; inline void nextSyzygyLayer() const { OPT__SYZNUMBER++; } /// output lifting tree const int OPT__TREEOUTPUT; /// CheckSyzygyProperty: TODO const int OPT__SYZCHECK; /// TEST_OPT_PROT const bool OPT__PROT; /// no caching/stores/lookups const int OPT__NOCACHING; /// global base ring const ring m_rBaseRing; }; class SchreyerSyzygyComputation; class CLCM: public SchreyerSyzygyComputationFlags, public std::vector { public: CLCM(const ideal& L, const SchreyerSyzygyComputationFlags& flags); bool Check(const poly m) const; private: bool m_compute; const unsigned int m_N; ///< number of ring variables }; class CLeadingTerm { public: CLeadingTerm(unsigned int label, const poly lt, const ring); #ifndef SING_NDEBUG ~CLeadingTerm(); #endif #if NOPRODUCT bool DivisibilityCheck(const poly multiplier, const poly t, const unsigned long not_sev, const ring r) const; #endif bool DivisibilityCheck(const poly product, const unsigned long not_sev, const ring r) const; bool CheckLT( const ideal & L ) const; #ifndef SING_NDEBUG poly lt() const; unsigned long sev() const; unsigned int label() const; #else inline poly lt() const { return m_lt; }; inline unsigned long sev() const { return m_sev; }; inline unsigned int label() const { return m_label; }; #endif private: const unsigned long m_sev; ///< not short exp. vector // NOTE/TODO: either of the following should be enough: const unsigned int m_label; ///< index in the main L[] + 1 const poly m_lt; ///< the leading term itself L[label-1] #ifndef SING_NDEBUG const ring _R; const poly m_lt_copy; ///< original copy of LEAD(lt) (only for debug!!!) #endif // disable the following: CLeadingTerm(); CLeadingTerm(const CLeadingTerm&); void operator=(const CLeadingTerm&); }; // TODO: needs a specialized variant without a component (hash!) class CReducerFinder: public SchreyerSyzygyComputationFlags { #if NOPRODUCT friend class CDivisorEnumerator2; #endif friend class CDivisorEnumerator; public: typedef long TComponentKey; typedef std::vector TReducers; private: typedef std::map< TComponentKey, TReducers> CReducersHash; public: /// goes over all leading terms CReducerFinder(const ideal L, const SchreyerSyzygyComputationFlags& flags); void Initialize(const ideal L); ~CReducerFinder(); #if NOPRODUCT poly FindReducer(const poly multiplier, const poly monom, const poly syzterm, const CReducerFinder& checker) const; #endif // TODO: save shortcut (syz: |-.->) LM(LM(m) * "t") -> syz? poly // const_iterator // TODO: return const_iterator it, s.th: it->m_lt is the needed FindReducer(const poly product, const poly syzterm, const CReducerFinder& checker) const; bool IsDivisible(const poly q) const; inline bool IsNonempty() const { return !m_hash.empty(); } /// is the term to be "preprocessed" as lower order term or lead to only reducible syzygies... int PreProcessTerm(const poly t, CReducerFinder& syzChecker) const; #ifndef SING_NDEBUG void DebugPrint() const; void Verify() const; #endif private: ideal m_L; ///< only for debug CReducersHash m_hash; // can also be replaced with a vector indexed by components private: CReducerFinder(const CReducerFinder&); void operator=(const CReducerFinder&); }; extern ideal id_Copy (const ideal, const ring); bool my_p_LmCmp (poly, poly, const ring); typedef poly TCacheKey; typedef poly TCacheValue; struct CCacheCompare { const ring & m_ring; CCacheCompare(); CCacheCompare(const ring& r): m_ring(r) { assume(r != NULL); } CCacheCompare(const CCacheCompare& lhs): m_ring(lhs.m_ring) { assume(m_ring != NULL); } CCacheCompare& operator=(const CCacheCompare& lhs) { assume(lhs.m_ring != NULL); return (const_cast(lhs)); } inline bool operator() (const TCacheKey& l, const TCacheKey& r) const { assume(m_ring != NULL); return my_p_LmCmp(l, r, m_ring); } }; typedef std::map TP2PCache; // deallocation??? !!! typedef std::map TCache; /** @class SchreyerSyzygyComputation syzextra.h * * Computing syzygies after Schreyer * * Storing/accumulating data during the computation requires some global * object, like this class. Ideally the above global functions should not * be used in favour of this class. * * @sa Schreyer Syzygy Computation Paper & Talk & Python prototype */ class SchreyerSyzygyComputation: public SchreyerSyzygyComputationFlags { friend class CLCM; friend class CReducerFinder; public: /// Construct a global object for given input data (separated into leads & tails) SchreyerSyzygyComputation(const ideal idLeads, const ideal idTails, const SchreyerSyzygyComputationFlags setting): SchreyerSyzygyComputationFlags(setting), m_idLeads(idLeads), m_idTails(id_Copy(idTails, setting.m_rBaseRing)), m_syzLeads(NULL), m_syzTails(NULL), m_LS(NULL), m_lcm(m_idLeads, setting), m_div(m_idLeads, setting), m_checker(NULL, setting), m_cache(), m_sum_bucket_factory(setting.m_rBaseRing), m_spoly_bucket(NULL) { if( UNLIKELY(OPT__PROT) ) memset( &m_stat, 0, sizeof(m_stat) ); } /// Construct a global object for given input data (separated into leads & tails) SchreyerSyzygyComputation(const ideal idLeads, const ideal idTails, const ideal syzLeads, const SchreyerSyzygyComputationFlags setting): SchreyerSyzygyComputationFlags(setting), m_idLeads(idLeads), m_idTails(id_Copy(idTails, setting.m_rBaseRing)), m_syzLeads(syzLeads), m_syzTails(NULL), m_LS(syzLeads), m_lcm(m_idLeads, setting), m_div(m_idLeads, setting), m_checker(NULL, setting), m_cache(), m_sum_bucket_factory(setting.m_rBaseRing), m_spoly_bucket(NULL) { if( UNLIKELY(OPT__PROT) ) memset( &m_stat, 0, sizeof(m_stat) ); if( LIKELY(OPT__TAILREDSYZ && !OPT__IGNORETAILS) ) { if (syzLeads != NULL) m_checker.Initialize(syzLeads); // if( idTails != NULL ) // SetUpTailTerms(); } } /// Destructor should not destruct the resulting m_syzLeads, m_syzTails. ~SchreyerSyzygyComputation(){ CleanUp(); } /// Convert the given ideal of tails into the internal representation (with reducers!) /// Preprocess m_idTails as well...? void SetUpTailTerms(); /// print statistics about the used heuristics void PrintStats() const; /// Read off the results while detaching them from this object /// NOTE: no copy! inline void ReadOffResult(ideal& syzL, ideal& syzT) { syzL = m_syzLeads; syzT = m_syzTails; m_syzLeads = m_syzTails = NULL; // m_LS ? if ( UNLIKELY(OPT__PROT) ) PrintStats(); } /// The main driver function: computes void ComputeSyzygy(); /// Computes Syz(leads) or only LEAD of it. /// The result is stored into m_syzLeads void ComputeLeadingSyzygyTerms(bool bComputeSecondTerms = true); /// Main HybridNF == 1: poly reduce + LOT + LCM? poly SchreyerSyzygyNF(const poly syz_lead, poly syz_2 = NULL) const; // Main (HybridNF == 0) Tree Travers + LOT + LCM? poly TraverseNF(const poly syz_lead, const poly syz_2 = NULL) const; /// High level caching function!!! poly TraverseTail(poly multiplier, const int tail) const; // REMOVE? /// called only from above and from outside (for testing) poly TraverseTail(poly multiplier, poly tail) const; /// TODO: save shortcut (syz: |-.->) LM(m) * "t" -> ? ??? poly ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck) const; /// low level computation... poly ComputeImage(poly multiplier, const int tail) const; public: /// just for testing via the wrapper below inline poly _FindReducer(const poly product, const poly syzterm) const { return m_div.FindReducer(product, syzterm, m_checker); } private: void CleanUp(); protected: /// just leading terms ideal Compute1LeadingSyzygyTerms(); /// leading + second terms ideal Compute2LeadingSyzygyTerms(); private: /// input leading terms const ideal m_idLeads; /// input tails const ideal m_idTails; /// output (syzygy) leading terms (+2nd terms?) ideal m_syzLeads; /// output (syzygy) tails ideal m_syzTails; /*mutable?*/ ideal m_LS; ///< leading syzygy terms used for reducing syzygy tails /// Bitmask for variables occuring in leading terms const CLCM m_lcm; /// Divisor finder const CReducerFinder m_div; /// for checking tail-terms and makeing them irreducible (wrt m_LS!) CReducerFinder m_checker; /* // need more data here: // (m_idLeads : m_tailterm) = (m, pos, compl), s.th: compl * m_tailterm divides m_idLeads[pos] // but resulting sysygy compl * gen(pos) should not be in // Idea: extend CReducerFinder??!! struct CTailTerm { const poly m_tailterm; const CReducerFinder m_reducers; // positions are labels (in m_idLeads)... // compl - to be computed if needed? CTailTerm(const poly tt, const CReducerFinder reds): m_tailterm(tt), m_reducers(reds) {} }; typedef std::vector TTail; typedef std::vector TTailTerms; TTailTerms m_idTailTerms; */ mutable TCache m_cache; // cacher comp + poly -> poly! // mutable??? /// TODO: look into m_idTailTerms!!!!!!!!!!!!!!!!!!!!!!!! map? heaps??? // NOTE/TODO: the following globally shared buckets violate reentrance - they should rather belong to TLS! /// used for simple summing up mutable SBucketFactory m_sum_bucket_factory; // sBucket_pt /// for S-Polynomial reductions mutable kBucket_pt m_spoly_bucket; // only used inside of SchreyerSyzygyNF! destruction by CleanUp()! /// Statistics: /// 0..3: as in SetUpTailTerms()::PreProcessTerm() // TODO!!?? /// 4: number of terms discarded due to LOT heuristics /// 5: number of terms discarded due to LCM heuristics /// 6, 7: lookups without & with rescale, 8: stores mutable unsigned long m_stat[9]; }; // The following wrappers are just for testing separate functions on highest level (within schreyer.lib) static inline void ComputeSyzygy(const ideal L, const ideal T, ideal& LL, ideal& TT, const SchreyerSyzygyComputationFlags A) { SchreyerSyzygyComputation syz(L, T, A); syz.ComputeSyzygy(); syz.ReadOffResult(LL, TT); } static inline ideal ComputeLeadingSyzygyTerms(const ideal& L, const SchreyerSyzygyComputationFlags A) { SchreyerSyzygyComputation syz(L, NULL, A); syz.ComputeLeadingSyzygyTerms(false); ideal LL, TT; syz.ReadOffResult(LL, TT); return LL; // assume TT is NULL! } static inline ideal Compute2LeadingSyzygyTerms(const ideal& L, const SchreyerSyzygyComputationFlags A) { SchreyerSyzygyComputation syz(L, NULL, A); syz.ComputeLeadingSyzygyTerms(true); ideal LL, TT; syz.ReadOffResult(LL, TT); return LL; // assume TT is NULL! } static inline poly FindReducer(poly product, poly syzterm, ideal L, ideal LS, const SchreyerSyzygyComputationFlags A) { SchreyerSyzygyComputation syz(L, NULL, LS, A); return syz._FindReducer(product, syzterm); } static inline poly TraverseTail(poly multiplier, poly tail, ideal L, ideal T, ideal LS, const SchreyerSyzygyComputationFlags A) { SchreyerSyzygyComputation syz(L, T, LS, A); return syz.TraverseTail(multiplier, tail); } static inline poly ReduceTerm(poly multiplier, poly term4reduction, poly syztermCheck, ideal L, ideal T, ideal LS, const SchreyerSyzygyComputationFlags A) { SchreyerSyzygyComputation syz(L, T, LS, A); return syz.ReduceTerm(multiplier, term4reduction, syztermCheck); } static inline poly SchreyerSyzygyNF(poly syz_lead, poly syz_2, ideal L, ideal T, ideal LS, const SchreyerSyzygyComputationFlags A) { SchreyerSyzygyComputation syz(L, T, LS, A); return syz.SchreyerSyzygyNF(syz_lead, syz_2); } END_NAMESPACE END_NAMESPACE_SINGULARXX #endif /* #ifndef SYZEXTRA_H */ // Vi-modeline: vim: filetype=c:syntax:shiftwidth=2:tabstop=8:textwidth=0:expandtab singular-4.0.3+ds/Singular/dyn_modules/syzextra/test.sh000077500000000000000000000005701266270727000232740ustar00rootroot00000000000000#!/bin/sh #"$SINGULAR_EXECUTABLE" -teq "$srcdir/test_clear_enum.tst" || exit 1 #"$SINGULAR_EXECUTABLE" -teq "$srcdir/ederc.tst" || exit 1 #"$SINGULAR_EXECUTABLE" -teq "$srcdir/syzextra.tst" || exit 1 "$SINGULAR_EXECUTABLE" -tec 'LIB "schreyer.lib"; listvar(Top); proc T(){ Schreyer::testSimple(1, 0); /* Schreyer::testAGR(0); Schreyer::testAGRhard(0); */ } T(); $' || exit 1 singular-4.0.3+ds/Singular/dyn_modules/syzextra/test_release.sh000077500000000000000000000001271266270727000247720ustar00rootroot00000000000000#!/bin/sh export SINGULAR_EXECUTABLE="$SINGULAR_BIN_DIR/Singular" . "$srcdir/test.sh" singular-4.0.3+ds/Singular/eigenval_ip.cc000066400000000000000000000132241266270727000203340ustar00rootroot00000000000000/***************************************** * Computer Algebra System SINGULAR * *****************************************/ /* * ABSTRACT: eigenvalues of constant square matrices */ #include #ifdef HAVE_EIGENVAL #include #include #include #include #include #include #include #include #include #include #include #include BOOLEAN evSwap(leftv res,leftv h) { if(currRing) { short t[]={3,MATRIX_CMD,INT_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { matrix M=(matrix)h->Data(); h=h->next; int i=(int)(long)h->Data(); h=h->next; int j=(int)(long)h->Data(); res->rtyp=MATRIX_CMD; res->data=(void *)evSwap(mp_Copy(M, currRing),i,j); return FALSE; } return TRUE; } WerrorS("no ring active"); return TRUE; } BOOLEAN evRowElim(leftv res,leftv h) { if(currRing) { short t[]={4,MATRIX_CMD,INT_CMD,INT_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { matrix M=(matrix)h->CopyD(); h=h->next; int i=(int)(long)h->Data(); h=h->next; int j=(int)(long)h->Data(); h=h->next; int k=(int)(long)h->Data(); res->rtyp=MATRIX_CMD; res->data=(void *)evRowElim(M,i,j,k); return FALSE; } return TRUE; } WerrorS("no ring active"); return TRUE; } BOOLEAN evColElim(leftv res,leftv h) { if(currRing) { short t[]={4,MATRIX_CMD,INT_CMD,INT_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { matrix M=(matrix)h->Data(); h=h->next; int i=(int)(long)h->Data(); h=h->next; int j=(int)(long)h->Data(); h=h->next; int k=(int)(long)h->Data(); res->rtyp=MATRIX_CMD; res->data=(void *)evColElim(mp_Copy(M, currRing),i,j,k); return FALSE; } return TRUE; } WerrorS("no ring active"); return TRUE; } BOOLEAN evHessenberg(leftv res,leftv h) { if(currRing) { if(h&&h->Typ()==MATRIX_CMD) { matrix M=(matrix)h->Data(); res->rtyp=MATRIX_CMD; res->data=(void *)evHessenberg(mp_Copy(M, currRing)); return FALSE; } WerrorS(" expected"); return TRUE; } WerrorS("no ring active"); return TRUE; } lists evEigenvals(matrix M) { lists l=(lists)omAllocBin(slists_bin); if(MATROWS(M)!=MATCOLS(M)) { l->Init(0); return(l); } M=evHessenberg(M); int n=MATCOLS(M); ideal e=idInit(n,1); intvec *m=new intvec(n); poly t=pOne(); pSetExp(t,1,1); pSetm(t); for(int j0=1,j=2,k=0;j<=n+1;j0=j,j++) { while(j<=n&&MATELEM(M,j,j-1)!=NULL) j++; if(j==j0+1) { e->m[k]=pHead(MATELEM(M,j0,j0)); (*m)[k]=1; k++; } else { int n0=j-j0; matrix M0=mpNew(n0,n0); j0--; for(int i=1;i<=n0;i++) for(int j=1;j<=n0;j++) MATELEM(M0,i,j)=pCopy(MATELEM(M,j0+i,j0+j)); for(int i=1;i<=n0;i++) MATELEM(M0,i,i)=pSub(MATELEM(M0,i,i),pCopy(t)); intvec *m0; ideal e0=singclap_factorize(mp_DetBareiss(M0,currRing),&m0,2, currRing); if (e0==NULL) { l->Init(0); return(l); } for(int i=0;im[i])==NULL) { (*m)[k]=(*m0)[i]; k++; } else if(pGetExp(e0->m[i],1)<2&&pGetExp(pNext(e0->m[i]),1)<2&& pNext(pNext(e0->m[i]))==NULL) { number e1=nCopy(pGetCoeff(e0->m[i])); e1=nInpNeg(e1); if(pGetExp(pNext(e0->m[i]),1)==0) e->m[k]=pNSet(nDiv(pGetCoeff(pNext(e0->m[i])),e1)); else e->m[k]=pNSet(nDiv(e1,pGetCoeff(pNext(e0->m[i])))); nDelete(&e1); pNormalize(e->m[k]); (*m)[k]=(*m0)[i]; k++; } else { e->m[k]=e0->m[i]; pNormalize(e->m[k]); e0->m[i]=NULL; (*m)[k]=(*m0)[i]; k++; } } delete(m0); idDelete(&e0); } } pDelete(&t); idDelete((ideal *)&M); for(int i0=0;i0m[i0],e->m[i1])) { (*m)[i0]+=(*m)[i1]; (*m)[i1]=0; } else { if(e->m[i0]==NULL&&!nGreaterZero(pGetCoeff(e->m[i1]))|| e->m[i1]==NULL&& (nGreaterZero(pGetCoeff(e->m[i0]))||pNext(e->m[i0])!=NULL)|| e->m[i0]!=NULL&&e->m[i1]!=NULL&& (pNext(e->m[i0])!=NULL&&pNext(e->m[i1])==NULL|| pNext(e->m[i0])==NULL&&pNext(e->m[i1])==NULL&& nGreater(pGetCoeff(e->m[i0]),pGetCoeff(e->m[i1])))) { poly e1=e->m[i0]; e->m[i0]=e->m[i1]; e->m[i1]=e1; int m1=(*m)[i0]; (*m)[i0]=(*m)[i1]; (*m)[i1]=m1; } } } } int n0=0; for(int i=0;i0) n0++; ideal e0=idInit(n0,1); intvec *m0=new intvec(n0); for(int i=0,i0=0;i0) { e0->m[i0]=e->m[i]; e->m[i]=NULL; (*m0)[i0]=(*m)[i]; i0++; } idDelete(&e); delete(m); l->Init(2); l->m[0].rtyp=IDEAL_CMD; l->m[0].data=e0; l->m[1].rtyp=INTVEC_CMD; l->m[1].data=m0; return(l); } BOOLEAN evEigenvals(leftv res,leftv h) { if(currRing) { if(h&&h->Typ()==MATRIX_CMD) { matrix M=(matrix)h->CopyD(); res->rtyp=LIST_CMD; res->data=(void *)evEigenvals(M); return FALSE; } WerrorS(" expected"); return TRUE; } WerrorS("no ring active"); return TRUE; } #endif /* HAVE_EIGENVAL */ singular-4.0.3+ds/Singular/eigenval_ip.h000066400000000000000000000011011266270727000201650ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: eigenvalues of constant square matrices */ #ifndef EIGENVAL_IP_H #define EIGENVAL_IP_H #ifdef HAVE_EIGENVAL #include BOOLEAN evSwap(leftv res,leftv h); BOOLEAN evRowElim(leftv res,leftv h); BOOLEAN evColElim(leftv res,leftv h); BOOLEAN evHessenberg(leftv res,leftv h); lists evEigenvals(matrix M); BOOLEAN evEigenvals(leftv res,leftv h); #endif /* ifdef HAVE_EIGENVAL */ #endif /* EIGENVAL_IP_H */ singular-4.0.3+ds/Singular/emacs.cc000066400000000000000000000206001266270727000171360ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: Esingular main file */ #include #include #include #include #ifdef __CYGWIN__ #define BOOLEAN boolean #endif #include #include #ifdef DecAlpha_OSF1 #define _BSD #endif #include #include #include #ifdef __CYGWIN__ #include #endif #if !defined(TSINGULAR) && !defined(ESINGULAR) #define ESINGULAR #endif #ifdef system #undef system #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif #ifndef MAXPATHLEN #define MAXPATHLEN 1024 #endif # define DIR_SEP '/' # define DIR_SEPP "/" # define UP_DIR ".." #ifndef __CYGWIN__ void error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); } #else void error(const char* fmt, ...) { char buf[4096]; int j =0; va_list args; va_start(args, fmt); j = sprintf(buf, ""); j += vsprintf(buf + j,fmt,args); j += sprintf(buf + j,"\n"); va_end(args); MessageBox(NULL, buf, "ESingular.exe", MB_ICONSTOP); exit(1); } #endif #define Warn error #define WarnS error #define StringAppend printf #define Print error #define feReportBug(s) fePrintReportBug(s, __FILE__, __LINE__) void fePrintReportBug(char* msg, char* file, int line) { error("YOU HAVE FOUND A BUG IN SINGULAR.\n" "Please, email the following output to singular@mathematik.uni-kl.de\n" "Bug occured at %s:%d\n" "Message: %s\n" "Version: " S_UNAME VERSION __DATE__ __TIME__, file, line, msg); } void mainUsage() { error( "Use `%s --help' for a complete list of options\n", feArgv0); } extern char* feResourceDefault(const char id); extern char* feResourceDefault(const char* key); int main(int argc, char** argv) { char* singular = NULL; char* emacs = NULL; #ifndef TSINGULAR char* emacs_dir = NULL; char* emacs_load = NULL; char cwd[MAXPATHLEN]; #endif int no_emacs_call = 0; // parse-cmdline options feInitResources(argv[0]); feResource('S'); feResource('b'); feResource('r'); int optc, option_index; while ((optc = fe_getopt_long(argc, argv, SHORT_OPTS_STRING, feOptSpec, &option_index)) != EOF) { switch(optc) { case 'h': extern void feOptHelp(const char* name); feOptHelp(feArgv0); exit(0); break; case '?': case ':': case '\0': mainUsage(); exit(1); case LONG_OPTION_RETURN: { switch(option_index) { #ifdef TSINGULAR case FE_OPT_XTERM: emacs = fe_optarg; break; #else case FE_OPT_EMACS: emacs = fe_optarg; break; case FE_OPT_EMACS_DIR: emacs_dir = fe_optarg; break; case FE_OPT_EMACS_LOAD: emacs_load = fe_optarg; break; #endif case FE_OPT_SINGULAR: singular = fe_optarg; break; case FE_OPT_NO_CALL: no_emacs_call = 1; break; case FE_OPT_DUMP_VERSIONTUPLE: feOptDumpVersionTuple(); exit(0); break; default: goto NEXT; } // delete options from option-list if (fe_optind > 2 && *argv[fe_optind-1] != '-' && fe_optarg != NULL && feOptSpec[option_index].has_arg) { argv[fe_optind-2] = NULL; } argv[fe_optind-1] = NULL; } } NEXT:{} } int i, length = 0; char* syscall; for (i=1; i #include #include #include #include #include #include #include #include #ifdef TIME_WITH_SYS_TIME # include # ifdef HAVE_SYS_TIME_H # include # endif #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYS_TIMES_H #include #endif #include #include // #include #include #include #include "coeffs/AE.h" // #include "coeffs/OPAE.h" #include "coeffs/AEp.h" // #include "coeffs/OPAEp.h" #include "coeffs/AEQ.h" // #include "coeffs/OPAEQ.h" #include #include #include #include #include // #include #include #include #include #include #include #include #include #include #include #include #include #include #include // for tests of t-rep-GB #include #include #include #include "tok.h" #include "ipid.h" #include "lists.h" #include "cntrlc.h" #include "ipshell.h" #include "sdb.h" #include "feOpt.h" #include "fehelp.h" #include "distrib.h" #include "misc_ip.h" #include "attrib.h" #include "links/silink.h" #include "walk.h" #include #include #include #ifdef HAVE_RINGS #include #endif #ifdef HAVE_F5 #include #endif #ifdef HAVE_WALK #include "walk.h" #endif #ifdef HAVE_SPECTRUM #include #endif #ifdef HAVE_PLURAL #include #include // for CMultiplier etc classes #include #include #include "ipconv.h" #ifdef HAVE_RATGRING #include #endif #endif #ifdef __CYGWIN__ /* only for the DLLTest */ /* #include "WinDllTest.h" */ #ifdef HAVE_DL #include #endif #endif // Define to enable many more system commands //#undef MAKE_DISTRIBUTION #ifndef MAKE_DISTRIBUTION #define HAVE_EXTENDED_SYSTEM 1 #endif #include #include #include #include #ifdef HAVE_EIGENVAL #include "eigenval_ip.h" #endif #ifdef HAVE_GMS #include "gms.h" #endif #ifdef HAVE_SIMPLEIPC #include "Singular/links/simpleipc.h" #endif #ifdef HAVE_PCV #include "pcv.h" #endif #ifdef __CYGWIN__ //#include //#include #endif #ifndef MAKE_DISTRIBUTION static BOOLEAN jjEXTENDED_SYSTEM(leftv res, leftv h); #endif #ifdef __CYGWIN__ /* PySingular initialized? */ static int PyInitialized = 0; #endif /* expects a SINGULAR square matrix with number entries where currRing is expected to be over some field F_p; returns a long** matrix with the "same", i.e., appropriately mapped entries; leaves singularMatrix unmodified */ unsigned long** singularMatrixToLongMatrix(matrix singularMatrix) { int n = singularMatrix->rows(); assume(n == singularMatrix->cols()); unsigned long **longMatrix = 0; longMatrix = new unsigned long *[n] ; for (int i = 0 ; i < n; i++) longMatrix[i] = new unsigned long [n]; number entry; for (int r = 0; r < n; r++) for (int c = 0; c < n; c++) { poly p=MATELEM(singularMatrix, r + 1, c + 1); int entryAsInt; if (p!=NULL) { entry = p_GetCoeff(p, currRing); entryAsInt = n_Int(entry, currRing->cf); if (entryAsInt < 0) entryAsInt += n_GetChar(currRing->cf); } else entryAsInt=0; longMatrix[r][c] = (unsigned long)entryAsInt; } return longMatrix; } /* expects an array of unsigned longs with valid indices 0..degree; returns the following poly, where x denotes the first ring variable of currRing, and d = degree: polyCoeffs[d] * x^d + polyCoeffs[d-1] * x^(d-1) + ... + polyCoeffs[0] leaves polyCoeffs unmodified */ poly longCoeffsToSingularPoly(unsigned long *polyCoeffs, const int degree) { poly result = NULL; for (int i = 0; i <= degree; i++) { if ((int)polyCoeffs[i] != 0) { poly term = p_ISet((int)polyCoeffs[i], currRing); if (i > 0) { p_SetExp(term, 1, i, currRing); p_Setm(term, currRing); } result = p_Add_q(result, term, currRing); } } return result; } //void emStart(); /*2 * the "system" command */ BOOLEAN jjSYSTEM(leftv res, leftv args) { if(args->Typ() == STRING_CMD) { const char *sys_cmd=(char *)(args->Data()); leftv h=args->next; // ONLY documented system calls go here // Undocumented system calls go down into jjEXTENDED_SYSTEM (#ifdef HAVE_EXTENDED_SYSTEM) /*==================== nblocks ==================================*/ if (strcmp(sys_cmd, "nblocks") == 0) { ring r; if (h == NULL) { if (currRingHdl != NULL) { r = IDRING(currRingHdl); } else { WerrorS("no ring active"); return TRUE; } } else { if (h->Typ() != RING_CMD) { WerrorS("ring expected"); return TRUE; } r = (ring) h->Data(); } res->rtyp = INT_CMD; res->data = (void*) (long)(rBlocks(r) - 1); return FALSE; } /*==================== version ==================================*/ if(strcmp(sys_cmd,"version")==0) { res->rtyp=INT_CMD; res->data=(void *)SINGULAR_VERSION; return FALSE; } else /*==================== cpu ==================================*/ if(strcmp(sys_cmd,"cpu")==0) { long cpu=1; //feOptValue(FE_OPT_CPUS); #ifdef _SC_NPROCESSORS_ONLN cpu=sysconf(_SC_NPROCESSORS_ONLN); #elif defined(_SC_NPROCESSORS_CONF) cpu=sysconf(_SC_NPROCESSORS_CONF); #endif res->data=(void *)cpu; res->rtyp=INT_CMD; return FALSE; } else /*==================== sh ==================================*/ if(strcmp(sys_cmd,"sh")==0) { if (feOptValue(FE_OPT_NO_SHELL)) { WerrorS("shell execution is disallowed in restricted mode"); return TRUE; } res->rtyp=INT_CMD; if (h==NULL) res->data = (void *)(long) system("sh"); else if (h->Typ()==STRING_CMD) res->data = (void*)(long) system((char*)(h->Data())); else WerrorS("string expected"); return FALSE; } else #if 0 if(strcmp(sys_cmd,"power1")==0) { res->rtyp=POLY_CMD; poly f=(poly)h->CopyD(); poly g=pPower(f,2000); res->data=(void *)g; return FALSE; } else if(strcmp(sys_cmd,"power2")==0) { res->rtyp=POLY_CMD; poly f=(poly)h->Data(); poly g=pOne(); for(int i=0;i<2000;i++) g=pMult(g,pCopy(f)); res->data=(void *)g; return FALSE; } if(strcmp(sys_cmd,"power3")==0) { res->rtyp=POLY_CMD; poly f=(poly)h->Data(); poly p2=pMult(pCopy(f),pCopy(f)); poly p4=pMult(pCopy(p2),pCopy(p2)); poly p8=pMult(pCopy(p4),pCopy(p4)); poly p16=pMult(pCopy(p8),pCopy(p8)); poly p32=pMult(pCopy(p16),pCopy(p16)); poly p64=pMult(pCopy(p32),pCopy(p32)); poly p128=pMult(pCopy(p64),pCopy(p64)); poly p256=pMult(pCopy(p128),pCopy(p128)); poly p512=pMult(pCopy(p256),pCopy(p256)); poly p1024=pMult(pCopy(p512),pCopy(p512)); poly p1536=pMult(p1024,p512); poly p1792=pMult(p1536,p256); poly p1920=pMult(p1792,p128); poly p1984=pMult(p1920,p64); poly p2000=pMult(p1984,p16); res->data=(void *)p2000; pDelete(&p2); pDelete(&p4); pDelete(&p8); //pDelete(&p16); pDelete(&p32); //pDelete(&p64); //pDelete(&p128); //pDelete(&p256); //pDelete(&p512); //pDelete(&p1024); //pDelete(&p1536); //pDelete(&p1792); //pDelete(&p1920); //pDelete(&p1984); return FALSE; } else #endif /*==================== uname ==================================*/ if(strcmp(sys_cmd,"uname")==0) { res->rtyp=STRING_CMD; res->data = omStrDup(S_UNAME); return FALSE; } else /*==================== with ==================================*/ if(strcmp(sys_cmd,"with")==0) { if (h==NULL) { res->rtyp=STRING_CMD; res->data=(void *)versionString(); return FALSE; } else if (h->Typ()==STRING_CMD) { #define TEST_FOR(A) if(strcmp(s,A)==0) res->data=(void *)1; else char *s=(char *)h->Data(); res->rtyp=INT_CMD; #ifdef HAVE_DBM TEST_FOR("DBM") #endif #ifdef HAVE_DLD TEST_FOR("DLD") #endif //TEST_FOR("factory") //TEST_FOR("libfac") #ifdef HAVE_READLINE TEST_FOR("readline") #endif #ifdef TEST_MAC_ORDER TEST_FOR("MAC_ORDER") #endif // unconditional since 3-1-0-6 TEST_FOR("Namespaces") #ifdef HAVE_DYNAMIC_LOADING TEST_FOR("DynamicLoading") #endif #ifdef HAVE_EIGENVAL TEST_FOR("eigenval") #endif #ifdef HAVE_GMS TEST_FOR("gms") #endif #ifdef OM_NDEBUG TEST_FOR("om_ndebug") #endif #ifdef SING_NDEBUG TEST_FOR("ndebug") #endif {}; return FALSE; #undef TEST_FOR } return TRUE; } else /*==================== browsers ==================================*/ if (strcmp(sys_cmd,"browsers")==0) { res->rtyp = STRING_CMD; StringSetS(""); feStringAppendBrowsers(0); res->data = StringEndS(); return FALSE; } else /*==================== pid ==================================*/ if (strcmp(sys_cmd,"pid")==0) { res->rtyp=INT_CMD; res->data=(void *)(long) getpid(); return FALSE; } else /*==================== getenv ==================================*/ if (strcmp(sys_cmd,"getenv")==0) { if ((h!=NULL) && (h->Typ()==STRING_CMD)) { res->rtyp=STRING_CMD; const char *r=getenv((char *)h->Data()); if (r==NULL) r=""; res->data=(void *)omStrDup(r); return FALSE; } else { WerrorS("string expected"); return TRUE; } } else /*==================== setenv ==================================*/ if (strcmp(sys_cmd,"setenv")==0) { #ifdef HAVE_SETENV const short t[]={2,STRING_CMD,STRING_CMD}; if (iiCheckTypes(h,t,1)) { res->rtyp=STRING_CMD; setenv((char *)h->Data(), (char *)h->next->Data(), 1); res->data=(void *)omStrDup((char *)h->next->Data()); feReInitResources(); return FALSE; } else { return TRUE; } #else WerrorS("setenv not supported on this platform"); return TRUE; #endif } else /*==================== Singular ==================================*/ if (strcmp(sys_cmd, "Singular") == 0) { res->rtyp=STRING_CMD; const char *r=feResource("Singular"); if (r == NULL) r=""; res->data = (void*) omStrDup( r ); return FALSE; } else if (strcmp(sys_cmd, "SingularLib") == 0) { res->rtyp=STRING_CMD; const char *r=feResource("SearchPath"); if (r == NULL) r=""; res->data = (void*) omStrDup( r ); return FALSE; } else /*==================== options ==================================*/ if (strstr(sys_cmd, "--") == sys_cmd) { if (strcmp(sys_cmd, "--") == 0) { fePrintOptValues(); return FALSE; } feOptIndex opt = feGetOptIndex(&sys_cmd[2]); if (opt == FE_OPT_UNDEF) { Werror("Unknown option %s", sys_cmd); WerrorS("Use 'system(\"--\");' for listing of available options"); return TRUE; } // for Untyped Options (help version), // setting it just triggers action if (feOptSpec[opt].type == feOptUntyped) { feSetOptValue(opt,0); return FALSE; } if (h == NULL) { if (feOptSpec[opt].type == feOptString) { res->rtyp = STRING_CMD; const char *r=(const char*)feOptSpec[opt].value; if (r == NULL) r=""; res->data = omStrDup(r); } else { res->rtyp = INT_CMD; res->data = feOptSpec[opt].value; } return FALSE; } if (h->Typ() != STRING_CMD && h->Typ() != INT_CMD) { WerrorS("Need string or int argument to set option value"); return TRUE; } const char* errormsg; if (h->Typ() == INT_CMD) { if (feOptSpec[opt].type == feOptString) { Werror("Need string argument to set value of option %s", sys_cmd); return TRUE; } errormsg = feSetOptValue(opt, (int)((long) h->Data())); if (errormsg != NULL) Werror("Option '--%s=%d' %s", sys_cmd, (int) ((long)h->Data()), errormsg); } else { errormsg = feSetOptValue(opt, (char*) h->Data()); if (errormsg != NULL) Werror("Option '--%s=%s' %s", sys_cmd, (char*) h->Data(), errormsg); } if (errormsg != NULL) return TRUE; return FALSE; } else /*==================== HC ==================================*/ if (strcmp(sys_cmd,"HC")==0) { res->rtyp=INT_CMD; res->data=(void *)(long) HCord; return FALSE; } else /*==================== random ==================================*/ if(strcmp(sys_cmd,"random")==0) { const short t[]={1,INT_CMD}; if (h!=NULL) { if (iiCheckTypes(h,t,1)) { siRandomStart=(int)((long)h->Data()); siSeed=siRandomStart; factoryseed(siRandomStart); return FALSE; } else { return TRUE; } } res->rtyp=INT_CMD; res->data=(void*)(long) siSeed; return FALSE; } else /*==================== std_syz =================*/ if (strcmp(sys_cmd, "std_syz") == 0) { ideal i1; int i2; if ((h!=NULL) && (h->Typ()==MODUL_CMD)) { i1=(ideal)h->CopyD(); h=h->next; } else return TRUE; if ((h!=NULL) && (h->Typ()==INT_CMD)) { i2=(int)((long)h->Data()); } else return TRUE; res->rtyp=MODUL_CMD; res->data=idXXX(i1,i2); return FALSE; } else /*======================= demon_list =====================*/ if (strcmp(sys_cmd,"denom_list")==0) { res->rtyp=LIST_CMD; extern lists get_denom_list(); res->data=(lists)get_denom_list(); return FALSE; } else /*==================== complexNearZero ======================*/ if(strcmp(sys_cmd,"complexNearZero")==0) { const short t[]={2,NUMBER_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { if ( !rField_is_long_C(currRing) ) { WerrorS( "unsupported ground field!"); return TRUE; } else { res->rtyp=INT_CMD; res->data=(void*)complexNearZero((gmp_complex*)h->Data(), (int)((long)(h->next->Data()))); return FALSE; } } else { return TRUE; } } else /*==================== getPrecDigits ======================*/ if(strcmp(sys_cmd,"getPrecDigits")==0) { if ( (currRing==NULL) || (!rField_is_long_C(currRing) && !rField_is_long_R(currRing))) { WerrorS( "unsupported ground field!"); return TRUE; } res->rtyp=INT_CMD; res->data=(void*)(long)gmp_output_digits; //if (gmp_output_digits!=getGMPFloatDigits()) //{ Print("%d, %d\n",getGMPFloatDigits(),gmp_output_digits);} return FALSE; } else /*==================== lduDecomp ======================*/ if(strcmp(sys_cmd, "lduDecomp")==0) { const short t[]={1,MATRIX_CMD}; if (iiCheckTypes(h,t,1)) { matrix aMat = (matrix)h->Data(); matrix pMat; matrix lMat; matrix dMat; matrix uMat; poly l; poly u; poly prodLU; lduDecomp(aMat, pMat, lMat, dMat, uMat, l, u, prodLU); lists L = (lists)omAllocBin(slists_bin); L->Init(7); L->m[0].rtyp = MATRIX_CMD; L->m[0].data=(void*)pMat; L->m[1].rtyp = MATRIX_CMD; L->m[1].data=(void*)lMat; L->m[2].rtyp = MATRIX_CMD; L->m[2].data=(void*)dMat; L->m[3].rtyp = MATRIX_CMD; L->m[3].data=(void*)uMat; L->m[4].rtyp = POLY_CMD; L->m[4].data=(void*)l; L->m[5].rtyp = POLY_CMD; L->m[5].data=(void*)u; L->m[6].rtyp = POLY_CMD; L->m[6].data=(void*)prodLU; res->rtyp = LIST_CMD; res->data = (char *)L; return FALSE; } else { return TRUE; } } else /*==================== lduSolve ======================*/ if(strcmp(sys_cmd, "lduSolve")==0) { /* for solving a linear equation system A * x = b, via the given LDU-decomposition of the matrix A; There is one valid parametrisation: 1) exactly eight arguments P, L, D, U, l, u, lTimesU, b; P, L, D, and U realise the LDU-decomposition of A, that is, P * A = L * D^(-1) * U, and P, L, D, and U satisfy the properties decribed in method 'luSolveViaLDUDecomp' in linearAlgebra.h; see there; l, u, and lTimesU are as described in the same location; b is the right-hand side vector of the linear equation system; The method will return a list of either 1 entry or three entries: 1) [0] if there is no solution to the system; 2) [1, x, H] if there is at least one solution; x is any solution of the given linear system, H is the matrix with column vectors spanning the homogeneous solution space. The method produces an error if matrix and vector sizes do not fit. */ const short t[]={7,MATRIX_CMD,MATRIX_CMD,MATRIX_CMD,MATRIX_CMD,POLY_CMD,POLY_CMD,MATRIX_CMD}; if (!iiCheckTypes(h,t,1)) { return TRUE; } if (rField_is_Ring(currRing)) { WerrorS("field required"); return TRUE; } matrix pMat = (matrix)h->Data(); matrix lMat = (matrix)h->next->Data(); matrix dMat = (matrix)h->next->next->Data(); matrix uMat = (matrix)h->next->next->next->Data(); poly l = (poly) h->next->next->next->next->Data(); poly u = (poly) h->next->next->next->next->next->Data(); poly lTimesU = (poly) h->next->next->next->next->next->next->Data(); matrix bVec = (matrix)h->next->next->next->next->next->next->next->Data(); matrix xVec; int solvable; matrix homogSolSpace; if (pMat->rows() != pMat->cols()) { Werror("first matrix (%d x %d) is not quadratic", pMat->rows(), pMat->cols()); return TRUE; } if (lMat->rows() != lMat->cols()) { Werror("second matrix (%d x %d) is not quadratic", lMat->rows(), lMat->cols()); return TRUE; } if (dMat->rows() != dMat->cols()) { Werror("third matrix (%d x %d) is not quadratic", dMat->rows(), dMat->cols()); return TRUE; } if (dMat->cols() != uMat->rows()) { Werror("third matrix (%d x %d) and fourth matrix (%d x %d) %s", dMat->rows(), dMat->cols(), uMat->rows(), uMat->cols(), "do not t"); return TRUE; } if (uMat->rows() != bVec->rows()) { Werror("fourth matrix (%d x %d) and vector (%d x 1) do not fit", uMat->rows(), uMat->cols(), bVec->rows()); return TRUE; } solvable = luSolveViaLDUDecomp(pMat, lMat, dMat, uMat, l, u, lTimesU, bVec, xVec, homogSolSpace); /* build the return structure; a list with either one or three entries */ lists ll = (lists)omAllocBin(slists_bin); if (solvable) { ll->Init(3); ll->m[0].rtyp=INT_CMD; ll->m[0].data=(void *)(long)solvable; ll->m[1].rtyp=MATRIX_CMD; ll->m[1].data=(void *)xVec; ll->m[2].rtyp=MATRIX_CMD; ll->m[2].data=(void *)homogSolSpace; } else { ll->Init(1); ll->m[0].rtyp=INT_CMD; ll->m[0].data=(void *)(long)solvable; } res->rtyp = LIST_CMD; res->data=(char*)ll; return FALSE; } else /*==== countedref: reference and shared ====*/ if (strcmp(sys_cmd, "shared") == 0) { #ifndef SI_COUNTEDREF_AUTOLOAD void countedref_shared_load(); countedref_shared_load(); #endif res->rtyp = NONE; return FALSE; } else if (strcmp(sys_cmd, "reference") == 0) { #ifndef SI_COUNTEDREF_AUTOLOAD void countedref_reference_load(); countedref_reference_load(); #endif res->rtyp = NONE; return FALSE; } else /*==================== semaphore =================*/ #ifdef HAVE_SIMPLEIPC if (strcmp(sys_cmd,"semaphore")==0) { if((h!=NULL) && (h->Typ()==STRING_CMD) && (h->next!=NULL) && (h->next->Typ()==INT_CMD)) { int v=1; if ((h->next->next!=NULL)&& (h->next->next->Typ()==INT_CMD)) v=(int)(long)h->next->next->Data(); res->data=(char *)(long)simpleipc_cmd((char *)h->Data(),(int)(long)h->next->Data(),v); res->rtyp=INT_CMD; return FALSE; } else { WerrorS("Usage: system(\"semaphore\",,int)"); return TRUE; } } else #endif /*==================== reserved port =================*/ if (strcmp(sys_cmd,"reserve")==0) { int ssiReservePort(int clients); const short t[]={1,INT_CMD}; if (iiCheckTypes(h,t,1)) { res->rtyp=INT_CMD; int p=ssiReservePort((int)(long)h->Data()); res->data=(void*)(long)p; return (p==0); } return TRUE; } else /*==================== reserved link =================*/ if (strcmp(sys_cmd,"reservedLink")==0) { extern si_link ssiCommandLink(); res->rtyp=LINK_CMD; si_link p=ssiCommandLink(); res->data=(void*)p; return (p==NULL); } else /*==================== install newstruct =================*/ if (strcmp(sys_cmd,"install")==0) { const short t[]={4,STRING_CMD,STRING_CMD,PROC_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { return newstruct_set_proc((char*)h->Data(),(char*)h->next->Data(), (int)(long)h->next->next->next->Data(), (procinfov)h->next->next->Data()); } return TRUE; } else /*==================== newstruct =================*/ if (strcmp(sys_cmd,"newstruct")==0) { const short t[]={1,STRING_CMD}; if (iiCheckTypes(h,t,1)) { int id=0; char *n=(char*)h->Data(); blackboxIsCmd(n,id); if (id>0) { blackbox *bb=getBlackboxStuff(id); if (BB_LIKE_LIST(bb)) { newstruct_desc desc=(newstruct_desc)bb->data; newstructShow(desc); return FALSE; } else Werror("'%s' is not a newstruct",n); } else Werror("'%s' is not a blackbox object",n); } return TRUE; } else /*==================== blackbox =================*/ if (strcmp(sys_cmd,"blackbox")==0) { printBlackboxTypes(); return FALSE; } else /*================= absBiFact ======================*/ #ifdef HAVE_NTL if (strcmp(sys_cmd, "absFact") == 0) { const short t[]={1,POLY_CMD}; if (iiCheckTypes(h,t,1) && (currRing!=NULL) && (getCoeffType(currRing->cf)==n_transExt)) { res->rtyp=LIST_CMD; intvec *v=NULL; ideal mipos= NULL; int n= 0; ideal f=singclap_absFactorize((poly)(h->Data()), mipos, &v, n, currRing); if (f==NULL) return TRUE; ivTest(v); lists l=(lists)omAllocBin(slists_bin); l->Init(4); l->m[0].rtyp=IDEAL_CMD; l->m[0].data=(void *)f; l->m[1].rtyp=INTVEC_CMD; l->m[1].data=(void *)v; l->m[2].rtyp=IDEAL_CMD; l->m[2].data=(void*) mipos; l->m[3].rtyp=INT_CMD; l->m[3].data=(void*) (long) n; res->data=(void *)l; return FALSE; } else return TRUE; } else #endif /* =================== LLL via NTL ==============================*/ #ifdef HAVE_NTL if (strcmp(sys_cmd, "LLL") == 0) { if (h!=NULL) { res->rtyp=h->Typ(); if (h->Typ()==MATRIX_CMD) { res->data=(char *)singntl_LLL((matrix)h->Data(), currRing); return FALSE; } else if (h->Typ()==INTMAT_CMD) { res->data=(char *)singntl_LLL((intvec*)h->Data()); return FALSE; } else return TRUE; } else return TRUE; } else #endif /* =================== LLL via Flint ==============================*/ #ifdef HAVE_FLINT #ifdef FLINT_VER_2_4_5 if (strcmp(sys_cmd, "LLL_Flint") == 0) { if (h!=NULL) { if(h->next == NULL) { res->rtyp=h->Typ(); if (h->Typ()==BIGINTMAT_CMD) { res->data=(char *)singflint_LLL((bigintmat*)h->Data(), NULL); return FALSE; } else if (h->Typ()==INTMAT_CMD) { res->data=(char *)singflint_LLL((intvec*)h->Data(), NULL); return FALSE; } else return TRUE; } if(h->next->Typ()!= INT_CMD) { WerrorS("matrix,int or bigint,int expected"); return TRUE; } if(h->next->Typ()== INT_CMD) { if(((int)((long)(h->next->Data())) != 0) && (int)((long)(h->next->Data()) != 1)) { WerrorS("int is different from 0, 1"); return TRUE; } res->rtyp=h->Typ(); if((long)(h->next->Data()) == 0) { if (h->Typ()==BIGINTMAT_CMD) { res->data=(char *)singflint_LLL((bigintmat*)h->Data(), NULL); return FALSE; } else if (h->Typ()==INTMAT_CMD) { res->data=(char *)singflint_LLL((intvec*)h->Data(), NULL); return FALSE; } else return TRUE; } // This will give also the transformation matrix U s.t. res = U * m if((long)(h->next->Data()) == 1) { if (h->Typ()==BIGINTMAT_CMD) { bigintmat* m = (bigintmat*)h->Data(); bigintmat* T = new bigintmat(m->rows(),m->rows(),m->basecoeffs()); for(int i = 1; i<=m->rows(); i++) { n_Delete(&(BIMATELEM(*T,i,i)),T->basecoeffs()); BIMATELEM(*T,i,i)=n_Init(1, T->basecoeffs()); } m = singflint_LLL(m,T); lists L = (lists)omAllocBin(slists_bin); L->Init(2); L->m[0].rtyp = BIGINTMAT_CMD; L->m[0].data = (void*)m; L->m[1].rtyp = BIGINTMAT_CMD; L->m[1].data = (void*)T; res->data=L; res->rtyp=LIST_CMD; return FALSE; } else if (h->Typ()==INTMAT_CMD) { intvec* m = (intvec*)h->Data(); intvec* T = new intvec(m->rows(),m->rows(),(int)0); for(int i = 1; i<=m->rows(); i++) IMATELEM(*T,i,i)=1; m = singflint_LLL(m,T); lists L = (lists)omAllocBin(slists_bin); L->Init(2); L->m[0].rtyp = INTMAT_CMD; L->m[0].data = (void*)m; L->m[1].rtyp = INTMAT_CMD; L->m[1].data = (void*)T; res->data=L; res->rtyp=LIST_CMD; return FALSE; } else return TRUE; } } } else return TRUE; } else #endif #endif /*==================== shift-test for freeGB =================*/ #ifdef HAVE_SHIFTBBA if (strcmp(sys_cmd, "stest") == 0) { const short t[]={4,POLY_CMD,INT_CMD,INT_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { poly p=(poly)h->CopyD(); h=h->next; int sh=(int)((long)(h->Data())); h=h->next; int uptodeg=(int)((long)(h->Data())); h=h->next; int lVblock=(int)((long)(h->Data())); res->data = pLPshift(p,sh,uptodeg,lVblock); res->rtyp = POLY_CMD; return FALSE; } else return TRUE; } else #endif /*==================== block-test for freeGB =================*/ #ifdef HAVE_SHIFTBBA if (strcmp(sys_cmd, "btest") == 0) { const short t[]={2,POLY_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { poly p=(poly)h->CopyD(); h=h->next; int lV=(int)((long)(h->Data())); res->rtyp = INT_CMD; res->data = (void*)(long)pLastVblock(p, lV); return FALSE; } else return TRUE; } else #endif /*==================== shrink-test for freeGB =================*/ #ifdef HAVE_SHIFTBBA if (strcmp(sys_cmd, "shrinktest") == 0) { const short t[]={2,POLY_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { poly p=(poly)h->Data(); h=h->next; int lV=(int)((long)(h->Data())); res->rtyp = POLY_CMD; // res->data = p_mShrink(p, lV, currRing); // kStrategy strat=new skStrategy; // strat->tailRing = currRing; res->data = p_Shrink(p, lV, currRing); return FALSE; } else return TRUE; } else #endif /*==================== pcv ==================================*/ #ifdef HAVE_PCV if(strcmp(sys_cmd,"pcvLAddL")==0) { return pcvLAddL(res,h); } else if(strcmp(sys_cmd,"pcvPMulL")==0) { return pcvPMulL(res,h); } else if(strcmp(sys_cmd,"pcvMinDeg")==0) { return pcvMinDeg(res,h); } else if(strcmp(sys_cmd,"pcvP2CV")==0) { return pcvP2CV(res,h); } else if(strcmp(sys_cmd,"pcvCV2P")==0) { return pcvCV2P(res,h); } else if(strcmp(sys_cmd,"pcvDim")==0) { return pcvDim(res,h); } else if(strcmp(sys_cmd,"pcvBasis")==0) { return pcvBasis(res,h); } else #endif /*==================== hessenberg/eigenvalues ==================================*/ #ifdef HAVE_EIGENVAL if(strcmp(sys_cmd,"hessenberg")==0) { return evHessenberg(res,h); } else #endif /*==================== eigenvalues ==================================*/ #ifdef HAVE_EIGENVAL if(strcmp(sys_cmd,"eigenvals")==0) { return evEigenvals(res,h); } else #endif /*==================== rowelim ==================================*/ #ifdef HAVE_EIGENVAL if(strcmp(sys_cmd,"rowelim")==0) { return evRowElim(res,h); } else #endif /*==================== rowcolswap ==================================*/ #ifdef HAVE_EIGENVAL if(strcmp(sys_cmd,"rowcolswap")==0) { return evSwap(res,h); } else #endif /*==================== Gauss-Manin system ==================================*/ #ifdef HAVE_GMS if(strcmp(sys_cmd,"gmsnf")==0) { return gmsNF(res,h); } else #endif /*==================== contributors =============================*/ if(strcmp(sys_cmd,"contributors") == 0) { res->rtyp=STRING_CMD; res->data=(void *)omStrDup( "Olaf Bachmann, Michael Brickenstein, Hubert Grassmann, Kai Krueger, Victor Levandovskyy, Wolfgang Neumann, Thomas Nuessler, Wilfred Pohl, Jens Schmidt, Mathias Schulze, Thomas Siebert, Ruediger Stobbe, Moritz Wenk, Tim Wichmann"); return FALSE; } else /*==================== spectrum =============================*/ #ifdef HAVE_SPECTRUM if(strcmp(sys_cmd,"spectrum") == 0) { if ((h==NULL) || (h->Typ()!=POLY_CMD)) { WerrorS("poly expected"); return TRUE; } if (h->next==NULL) return spectrumProc(res,h); if (h->next->Typ()!=INT_CMD) { WerrorS("poly,int expected"); return TRUE; } if(((long)h->next->Data())==1L) return spectrumfProc(res,h); return spectrumProc(res,h); } else /*==================== semic =============================*/ if(strcmp(sys_cmd,"semic") == 0) { if ((h->next!=NULL) && (h->Typ()==LIST_CMD) && (h->next->Typ()==LIST_CMD)) { if (h->next->next==NULL) return semicProc(res,h,h->next); else if (h->next->next->Typ()==INT_CMD) return semicProc3(res,h,h->next,h->next->next); } return TRUE; } else /*==================== spadd =============================*/ if(strcmp(sys_cmd,"spadd") == 0) { const short t[]={2,LIST_CMD,LIST_CMD}; if (iiCheckTypes(h,t,1)) { return spaddProc(res,h,h->next); } return TRUE; } else /*==================== spmul =============================*/ if(strcmp(sys_cmd,"spmul") == 0) { const short t[]={2,LIST_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { return spmulProc(res,h,h->next); } return TRUE; } else #endif /*==================== tensorModuleMult ========================= */ #define HAVE_SHEAFCOH_TRICKS 1 #ifdef HAVE_SHEAFCOH_TRICKS if(strcmp(sys_cmd,"tensorModuleMult")==0) { const short t[]={2,INT_CMD,MODUL_CMD}; // WarnS("tensorModuleMult!"); if (iiCheckTypes(h,t,1)) { int m = (int)( (long)h->Data() ); ideal M = (ideal)h->next->Data(); res->rtyp=MODUL_CMD; res->data=(void *)id_TensorModuleMult(m, M, currRing); return FALSE; } return TRUE; } else #endif /*==================== twostd =================*/ #ifdef HAVE_PLURAL if (strcmp(sys_cmd, "twostd") == 0) { ideal I; if ((h!=NULL) && (h->Typ()==IDEAL_CMD)) { I=(ideal)h->CopyD(); res->rtyp=IDEAL_CMD; if (rIsPluralRing(currRing)) res->data=twostd(I); else res->data=I; setFlag(res,FLAG_TWOSTD); setFlag(res,FLAG_STD); } else return TRUE; return FALSE; } else #endif /*==================== lie bracket =================*/ #ifdef HAVE_PLURAL if (strcmp(sys_cmd, "bracket") == 0) { const short t[]={2,POLY_CMD,POLY_CMD}; if (iiCheckTypes(h,t,1)) { poly p=(poly)h->CopyD(); h=h->next; poly q=(poly)h->Data(); res->rtyp=POLY_CMD; if (rIsPluralRing(currRing)) res->data=nc_p_Bracket_qq(p,q, currRing); return FALSE; } return TRUE; } else #endif /*==================== env ==================================*/ #ifdef HAVE_PLURAL if (strcmp(sys_cmd, "env")==0) { if ((h!=NULL) && (h->Typ()==RING_CMD)) { ring r = (ring)h->Data(); res->data = rEnvelope(r); res->rtyp = RING_CMD; return FALSE; } else { WerrorS("`system(\"env\",)` expected"); return TRUE; } } else #endif /* ============ opp ======================== */ #ifdef HAVE_PLURAL if (strcmp(sys_cmd, "opp")==0) { if ((h!=NULL) && (h->Typ()==RING_CMD)) { ring r=(ring)h->Data(); res->data=rOpposite(r); res->rtyp=RING_CMD; return FALSE; } else { WerrorS("`system(\"opp\",)` expected"); return TRUE; } } else #endif /*==================== oppose ==================================*/ #ifdef HAVE_PLURAL if (strcmp(sys_cmd, "oppose")==0) { if ((h!=NULL) && (h->Typ()==RING_CMD) && (h->next!= NULL)) { ring Rop = (ring)h->Data(); h = h->next; idhdl w; if ((w=Rop->idroot->get(h->Name(),myynest))!=NULL) { poly p = (poly)IDDATA(w); res->data = pOppose(Rop, p, currRing); // into CurrRing? res->rtyp = POLY_CMD; return FALSE; } } else { WerrorS("`system(\"oppose\",,)` expected"); return TRUE; } } else #endif /*==================== freeGB, twosided GB in free algebra =================*/ #ifdef HAVE_PLURAL #ifdef HAVE_SHIFTBBA if (strcmp(sys_cmd, "freegb") == 0) { const short t[]={3,IDEAL_CMD,INT_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { ideal I=(ideal)h->CopyD(); h=h->next; int uptodeg=(int)((long)(h->Data())); h=h->next; int lVblock=(int)((long)(h->Data())); res->data = freegb(I,uptodeg,lVblock); if (res->data == NULL) { /* that is there were input errors */ res->data = I; } res->rtyp = IDEAL_CMD; return FALSE; } else return TRUE; } else #endif /*SHIFTBBA*/ #endif /*PLURAL*/ /*==================== walk stuff =================*/ /*==================== walkNextWeight =================*/ #ifdef HAVE_WALK #ifdef OWNW if (strcmp(sys_cmd, "walkNextWeight") == 0) { const short t[]={3,INTVEC_CMD,INTVEC_CMD,IDEAL_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->Data())->length() != currRing->N || ((intvec*) h->next->Data())->length() != currRing->N) { Werror("system(\"walkNextWeight\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } res->data = (void*) walkNextWeight(((intvec*) h->Data()), ((intvec*) h->next->Data()), (ideal) h->next->next->Data()); if (res->data == NULL || res->data == (void*) 1L) { res->rtyp = INT_CMD; } else { res->rtyp = INTVEC_CMD; } return FALSE; } else #endif #endif /*==================== walkNextWeight =================*/ #ifdef HAVE_WALK #ifdef OWNW if (strcmp(sys_cmd, "walkInitials") == 0) { if (h == NULL || h->Typ() != IDEAL_CMD) { WerrorS("system(\"walkInitials\", ideal) expected"); return TRUE; } res->data = (void*) walkInitials((ideal) h->Data()); res->rtyp = IDEAL_CMD; return FALSE; } else #endif #endif /*==================== walkAddIntVec =================*/ #ifdef HAVE_WALK #ifdef WAIV if (strcmp(sys_cmd, "walkAddIntVec") == 0) { const short t[]={2,INTVEC_CMD,INTVEC_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; intvec* arg1 = (intvec*) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); res->data = (intvec*) walkAddIntVec(arg1, arg2); res->rtyp = INTVEC_CMD; return FALSE; } else #endif #endif /*==================== MwalkNextWeight =================*/ #ifdef HAVE_WALK #ifdef MwaklNextWeight if (strcmp(sys_cmd, "MwalkNextWeight") == 0) { const short t[]={3,INTVEC_CMD,INTVEC_CMD,IDEAL_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->Data())->length() != currRing->N || ((intvec*) h->next->Data())->length() != currRing->N) { Werror("system(\"MwalkNextWeight\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } intvec* arg1 = (intvec*) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); ideal arg3 = (ideal) h->next->next->Data(); intvec* result = (intvec*) MwalkNextWeight(arg1, arg2, arg3); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif //MWalkNextWeight #endif /*==================== Mivdp =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "Mivdp") == 0) { if (h == NULL || h->Typ() != INT_CMD) { WerrorS("system(\"Mivdp\", int) expected"); return TRUE; } if ((int) ((long)(h->Data())) != currRing->N) { Werror("system(\"Mivdp\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } int arg1 = (int) ((long)(h->Data())); intvec* result = (intvec*) Mivdp(arg1); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== Mivlp =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "Mivlp") == 0) { if (h == NULL || h->Typ() != INT_CMD) { WerrorS("system(\"Mivlp\", int) expected"); return TRUE; } if ((int) ((long)(h->Data())) != currRing->N) { Werror("system(\"Mivlp\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } int arg1 = (int) ((long)(h->Data())); intvec* result = (intvec*) Mivlp(arg1); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MpDiv =================*/ #ifdef HAVE_WALK #ifdef MpDiv if(strcmp(sys_cmd, "MpDiv") == 0) { const short t[]={2,POLY_CMD,POLY_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; poly arg1 = (poly) h->Data(); poly arg2 = (poly) h->next->Data(); poly result = MpDiv(arg1, arg2); res->rtyp = POLY_CMD; res->data = result; return FALSE; } else #endif #endif /*==================== MpMult =================*/ #ifdef HAVE_WALK #ifdef MpMult if(strcmp(sys_cmd, "MpMult") == 0) { const short t[]={2,POLY_CMD,POLY_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; poly arg1 = (poly) h->Data(); poly arg2 = (poly) h->next->Data(); poly result = MpMult(arg1, arg2); res->rtyp = POLY_CMD; res->data = result; return FALSE; } else #endif #endif /*==================== MivSame =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "MivSame") == 0) { const short t[]={2,INTVEC_CMD,INTVEC_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; /* if (((intvec*) h->Data())->length() != currRing->N || ((intvec*) h->next->Data())->length() != currRing->N) { Werror("system(\"MivSame\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } */ intvec* arg1 = (intvec*) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); /* poly result = (poly) MivSame(arg1, arg2); res->rtyp = POLY_CMD; res->data = (poly) result; */ res->rtyp = INT_CMD; res->data = (void*)(long) MivSame(arg1, arg2); return FALSE; } else #endif /*==================== M3ivSame =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "M3ivSame") == 0) { const short t[]={3,INTVEC_CMD,INTVEC_CMD,INTVEC_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; /* if (((intvec*) h->Data())->length() != currRing->N || ((intvec*) h->next->Data())->length() != currRing->N || ((intvec*) h->next->next->Data())->length() != currRing->N ) { Werror("system(\"M3ivSame\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } */ intvec* arg1 = (intvec*) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); /* poly result = (poly) M3ivSame(arg1, arg2, arg3); res->rtyp = POLY_CMD; res->data = (poly) result; */ res->rtyp = INT_CMD; res->data = (void*)(long) M3ivSame(arg1, arg2, arg3); return FALSE; } else #endif /*==================== MwalkInitialForm =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "MwalkInitialForm") == 0) { const short t[]={2,IDEAL_CMD,INTVEC_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if(((intvec*) h->next->Data())->length() != currRing->N) { Werror("system \"MwalkInitialForm\"...) intvec not of length %d\n", currRing->N); return TRUE; } ideal id = (ideal) h->Data(); intvec* int_w = (intvec*) h->next->Data(); ideal result = (ideal) MwalkInitialForm(id, int_w); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif /*==================== MivMatrixOrder =================*/ #ifdef HAVE_WALK /************** Perturbation walk **********/ if(strcmp(sys_cmd, "MivMatrixOrder") == 0) { if(h==NULL || h->Typ() != INTVEC_CMD) { WerrorS("system(\"MivMatrixOrder\",intvec) expected"); return TRUE; } intvec* arg1 = (intvec*) h->Data(); intvec* result = MivMatrixOrder(arg1); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MivMatrixOrderdp =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "MivMatrixOrderdp") == 0) { if(h==NULL || h->Typ() != INT_CMD) { WerrorS("system(\"MivMatrixOrderdp\",intvec) expected"); return TRUE; } int arg1 = (int) ((long)(h->Data())); intvec* result = (intvec*) MivMatrixOrderdp(arg1); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MPertVectors =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "MPertVectors") == 0) { const short t[]={3,IDEAL_CMD,INTVEC_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); int arg3 = (int) ((long)(h->next->next->Data())); intvec* result = (intvec*) MPertVectors(arg1, arg2, arg3); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MPertVectorslp =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "MPertVectorslp") == 0) { const short t[]={3,IDEAL_CMD,INTVEC_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); int arg3 = (int) ((long)(h->next->next->Data())); intvec* result = (intvec*) MPertVectorslp(arg1, arg2, arg3); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /************** fractal walk **********/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "Mfpertvector") == 0) { const short t[]={2,IDEAL_CMD,INTVEC_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* result = Mfpertvector(arg1, arg2); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MivUnit =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "MivUnit") == 0) { const short t[]={1,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; int arg1 = (int) ((long)(h->Data())); intvec* result = (intvec*) MivUnit(arg1); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MivWeightOrderlp =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "MivWeightOrderlp") == 0) { const short t[]={1,INTVEC_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; intvec* arg1 = (intvec*) h->Data(); intvec* result = MivWeightOrderlp(arg1); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MivWeightOrderdp =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "MivWeightOrderdp") == 0) { if(h==NULL || h->Typ() != INTVEC_CMD) { WerrorS("system(\"MivWeightOrderdp\",intvec) expected"); return TRUE; } intvec* arg1 = (intvec*) h->Data(); //int arg2 = (int) h->next->Data(); intvec* result = MivWeightOrderdp(arg1); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MivMatrixOrderlp =================*/ #ifdef HAVE_WALK if(strcmp(sys_cmd, "MivMatrixOrderlp") == 0) { if(h==NULL || h->Typ() != INT_CMD) { WerrorS("system(\"MivMatrixOrderlp\",int) expected"); return TRUE; } int arg1 = (int) ((long)(h->Data())); intvec* result = (intvec*) MivMatrixOrderlp(arg1); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MkInterRedNextWeight =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "MkInterRedNextWeight") == 0) { const short t[]={3,INTVEC_CMD,INTVEC_CMD,IDEAL_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->Data())->length() != currRing->N || ((intvec*) h->next->Data())->length() != currRing->N) { Werror("system(\"MkInterRedNextWeight\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } intvec* arg1 = (intvec*) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); ideal arg3 = (ideal) h->next->next->Data(); intvec* result = (intvec*) MkInterRedNextWeight(arg1, arg2, arg3); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif /*==================== MPertNextWeight =================*/ #ifdef HAVE_WALK #ifdef MPertNextWeight if (strcmp(sys_cmd, "MPertNextWeight") == 0) { const short t[]={3,INTVEC_CMD,IDEAL_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->Data())->length() != currRing->N) { Werror("system(\"MPertNextWeight\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } intvec* arg1 = (intvec*) h->Data(); ideal arg2 = (ideal) h->next->Data(); int arg3 = (int) h->next->next->Data(); intvec* result = (intvec*) MPertNextWeight(arg1, arg2, arg3); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif //MPertNextWeight #endif /*==================== Mivperttarget =================*/ #ifdef HAVE_WALK #ifdef Mivperttarget if (strcmp(sys_cmd, "Mivperttarget") == 0) { const short t[]={2,IDEAL_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; ideal arg1 = (ideal) h->Data(); int arg2 = (int) h->next->Data(); intvec* result = (intvec*) Mivperttarget(arg1, arg2); res->rtyp = INTVEC_CMD; res->data = result; return FALSE; } else #endif //Mivperttarget #endif /*==================== Mwalk =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "Mwalk") == 0) { const short t[]={6,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD,RING_CMD,INT_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) { Werror("system(\"Mwalk\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } ideal arg1 = (ideal) h->CopyD(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); ring arg4 = (ring) h->next->next->next->Data(); int arg5 = (int) (long) h->next->next->next->next->Data(); int arg6 = (int) (long) h->next->next->next->next->next->Data(); ideal result = (ideal) Mwalk(arg1, arg2, arg3, arg4, arg5, arg6); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif /*==================== Mpwalk =================*/ #ifdef HAVE_WALK #ifdef MPWALK_ORIG if (strcmp(sys_cmd, "Mwalk") == 0) { const short t[]={4,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD,RING_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if ((((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) && (((intvec*) h->next->Data())->length() != (currRing->N)*(currRing->N) && ((intvec*) h->next->next->Data())->length() != (currRing->N)*(currRing->N))) { Werror("system(\"Mwalk\" ...) intvecs not of length %d or %d\n", currRing->N,(currRing->N)*(currRing->N)); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); ring arg4 = (ring) h->next->next->next->Data(); ideal result = (ideal) Mwalk(arg1, arg2, arg3,arg4); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #else if (strcmp(sys_cmd, "Mpwalk") == 0) { const short t[]={8,IDEAL_CMD,INT_CMD,INT_CMD,INTVEC_CMD,INTVEC_CMD,INT_CMD,INT_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if(((intvec*) h->next->next->next->Data())->length() != currRing->N && ((intvec*) h->next->next->next->next->Data())->length()!=currRing->N) { Werror("system(\"Mpwalk\" ...) intvecs not of length %d\n",currRing->N); return TRUE; } ideal arg1 = (ideal) h->Data(); int arg2 = (int) (long) h->next->Data(); int arg3 = (int) (long) h->next->next->Data(); intvec* arg4 = (intvec*) h->next->next->next->Data(); intvec* arg5 = (intvec*) h->next->next->next->next->Data(); int arg6 = (int) (long) h->next->next->next->next->next->Data(); int arg7 = (int) (long) h->next->next->next->next->next->next->Data(); int arg8 = (int) (long) h->next->next->next->next->next->next->next->Data(); ideal result = (ideal) Mpwalk(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif #endif /*==================== Mrwalk =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "Mrwalk") == 0) { const short t[]={7,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD,INT_CMD,INT_CMD,INT_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if(((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->Data())->length() != (currRing->N)*(currRing->N) && ((intvec*) h->next->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != (currRing->N)*(currRing->N) ) { Werror("system(\"Mrwalk\" ...) intvecs not of length %d or %d\n", currRing->N,(currRing->N)*(currRing->N)); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); int arg4 = (int)(long) h->next->next->next->Data(); int arg5 = (int)(long) h->next->next->next->next->Data(); int arg6 = (int)(long) h->next->next->next->next->next->Data(); int arg7 = (int)(long) h->next->next->next->next->next->next->Data(); ideal result = (ideal) Mrwalk(arg1, arg2, arg3, arg4, arg5, arg6, arg7); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif /*==================== MAltwalk1 =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "MAltwalk1") == 0) { const short t[]={5,IDEAL_CMD,INT_CMD,INT_CMD,INTVEC_CMD,INTVEC_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->next->next->next->Data())->length() != currRing->N && ((intvec*) h->next->next->next->next->Data())->length()!=currRing->N) { Werror("system(\"MAltwalk1\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } ideal arg1 = (ideal) h->Data(); int arg2 = (int) ((long)(h->next->Data())); int arg3 = (int) ((long)(h->next->next->Data())); intvec* arg4 = (intvec*) h->next->next->next->Data(); intvec* arg5 = (intvec*) h->next->next->next->next->Data(); ideal result = (ideal) MAltwalk1(arg1, arg2, arg3, arg4, arg5); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif /*==================== MAltwalk1 =================*/ #ifdef HAVE_WALK #ifdef MFWALK_ALT if (strcmp(sys_cmd, "Mfwalk_alt") == 0) { const short t[]={4,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) { Werror("system(\"Mfwalk\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); int arg4 = (int) h->next->next->next->Data(); ideal result = (ideal) Mfwalk_alt(arg1, arg2, arg3, arg4); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif #endif /*==================== Mfwalk =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "Mfwalk") == 0) { const short t[]={5,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD,INT_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) { Werror("system(\"Mfwalk\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); int arg4 = (int)(long) h->next->next->next->Data(); int arg5 = (int)(long) h->next->next->next->next->Data(); ideal result = (ideal) Mfwalk(arg1, arg2, arg3, arg4, arg5); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif /*==================== Mfrwalk =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "Mfrwalk") == 0) { const short t[]={6,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD,INT_CMD,INT_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; /* if (((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N) { Werror("system(\"Mfrwalk\" ...) intvecs not of length %d\n",currRing->N); return TRUE; } */ if((((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) && (((intvec*) h->next->Data())->length() != (currRing->N)*(currRing->N) && ((intvec*) h->next->next->Data())->length() != (currRing->N)*(currRing->N) )) { Werror("system(\"Mfrwalk\" ...) intvecs not of length %d or %d\n", currRing->N,(currRing->N)*(currRing->N)); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); int arg4 = (int)(long) h->next->next->next->Data(); int arg5 = (int)(long) h->next->next->next->next->Data(); int arg6 = (int)(long) h->next->next->next->next->next->Data(); ideal result = (ideal) Mfrwalk(arg1, arg2, arg3, arg4, arg5, arg6); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else /*==================== Mprwalk =================*/ if (strcmp(sys_cmd, "Mprwalk") == 0) { const short t[]={9,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD,INT_CMD,INT_CMD,INT_CMD,INT_CMD,INT_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if((((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) && (((intvec*) h->next->Data())->length() != (currRing->N)*(currRing->N) && ((intvec*) h->next->next->Data())->length() != (currRing->N)*(currRing->N) )) { Werror("system(\"Mrwalk\" ...) intvecs not of length %d or %d\n", currRing->N,(currRing->N)*(currRing->N)); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); int arg4 = (int)(long) h->next->next->next->Data(); int arg5 = (int)(long) h->next->next->next->next->Data(); int arg6 = (int)(long) h->next->next->next->next->next->Data(); int arg7 = (int)(long) h->next->next->next->next->next->next->Data(); int arg8 = (int)(long) h->next->next->next->next->next->next->next->Data(); int arg9 = (int)(long) h->next->next->next->next->next->next->next->next->Data(); ideal result = (ideal) Mprwalk(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif /*==================== TranMImprovwalk =================*/ #ifdef HAVE_WALK #ifdef TRAN_Orig if (strcmp(sys_cmd, "TranMImprovwalk") == 0) { const short t[]={3,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) { Werror("system(\"TranMImprovwalk\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); ideal result = (ideal) TranMImprovwalk(arg1, arg2, arg3); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif #endif /*==================== MAltwalk2 =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "MAltwalk2") == 0) { const short t[]={3,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) { Werror("system(\"MAltwalk2\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); ideal result = (ideal) MAltwalk2(arg1, arg2, arg3); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif /*==================== MAltwalk2 =================*/ #ifdef HAVE_WALK if (strcmp(sys_cmd, "TranMImprovwalk") == 0) { const short t[]={4,IDEAL_CMD,INTVEC_CMD,INTVEC_CMD,INT_CMD}; if (!iiCheckTypes(h,t,1)) return TRUE; if (((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) { Werror("system(\"TranMImprovwalk\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); int arg4 = (int) ((long)(h->next->next->next->Data())); ideal result = (ideal) TranMImprovwalk(arg1, arg2, arg3, arg4); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif /*==================== TranMrImprovwalk =================*/ #if 0 #ifdef HAVE_WALK if (strcmp(sys_cmd, "TranMrImprovwalk") == 0) { if (h == NULL || h->Typ() != IDEAL_CMD || h->next == NULL || h->next->Typ() != INTVEC_CMD || h->next->next == NULL || h->next->next->Typ() != INTVEC_CMD || h->next->next->next == NULL || h->next->next->next->Typ() != INT_CMD || h->next->next->next == NULL || h->next->next->next->next->Typ() != INT_CMD || h->next->next->next == NULL || h->next->next->next->next->next->Typ() != INT_CMD) { WerrorS("system(\"TranMrImprovwalk\", ideal, intvec, intvec) expected"); return TRUE; } if (((intvec*) h->next->Data())->length() != currRing->N && ((intvec*) h->next->next->Data())->length() != currRing->N ) { Werror("system(\"TranMrImprovwalk\" ...) intvecs not of length %d\n", currRing->N); return TRUE; } ideal arg1 = (ideal) h->Data(); intvec* arg2 = (intvec*) h->next->Data(); intvec* arg3 = (intvec*) h->next->next->Data(); int arg4 = (int)(long) h->next->next->next->Data(); int arg5 = (int)(long) h->next->next->next->next->Data(); int arg6 = (int)(long) h->next->next->next->next->next->Data(); ideal result = (ideal) TranMrImprovwalk(arg1, arg2, arg3, arg4, arg5, arg6); res->rtyp = IDEAL_CMD; res->data = result; return FALSE; } else #endif #endif /*================= Extended system call ========================*/ { #ifndef MAKE_DISTRIBUTION return(jjEXTENDED_SYSTEM(res, args)); #else Werror( "system(\"%s\",...) %s", sys_cmd, feNotImplemented ); #endif } } /* typ==string */ return TRUE; } #ifdef HAVE_EXTENDED_SYSTEM // You can put your own system calls here # include # include # ifdef HAVE_NEWTON # include # endif # include # include # include static BOOLEAN jjEXTENDED_SYSTEM(leftv res, leftv h) { if(h->Typ() == STRING_CMD) { char *sys_cmd=(char *)(h->Data()); h=h->next; /*==================== test syz strat =================*/ if (strcmp(sys_cmd, "syz") == 0) { int posInT_EcartFDegpLength(const TSet set,const int length,LObject &p); int posInT_FDegpLength(const TSet set,const int length,LObject &p); int posInT_pLength(const TSet set,const int length,LObject &p); int posInT0(const TSet set,const int length,LObject &p); int posInT1(const TSet set,const int length,LObject &p); int posInT2(const TSet set,const int length,LObject &p); int posInT11(const TSet set,const int length,LObject &p); int posInT110(const TSet set,const int length,LObject &p); int posInT13(const TSet set,const int length,LObject &p); int posInT15(const TSet set,const int length,LObject &p); int posInT17(const TSet set,const int length,LObject &p); int posInT17_c(const TSet set,const int length,LObject &p); int posInT19(const TSet set,const int length,LObject &p); if ((h!=NULL) && (h->Typ()==STRING_CMD)) { const char *s=(const char *)h->Data(); if (strcmp(s,"posInT_EcartFDegpLength")==0) test_PosInT=posInT_EcartFDegpLength; else if (strcmp(s,"posInT_FDegpLength")==0) test_PosInT=posInT_FDegpLength; else if (strcmp(s,"posInT_pLength")==0) test_PosInT=posInT_pLength; else if (strcmp(s,"posInT0")==0) test_PosInT=posInT0; else if (strcmp(s,"posInT1")==0) test_PosInT=posInT1; else if (strcmp(s,"posInT2")==0) test_PosInT=posInT2; else if (strcmp(s,"posInT11")==0) test_PosInT=posInT11; else if (strcmp(s,"posInT110")==0) test_PosInT=posInT110; else if (strcmp(s,"posInT13")==0) test_PosInT=posInT13; else if (strcmp(s,"posInT15")==0) test_PosInT=posInT15; else if (strcmp(s,"posInT17")==0) test_PosInT=posInT17; else if (strcmp(s,"posInT17_c")==0) test_PosInT=posInT17_c; else if (strcmp(s,"posInT19")==0) test_PosInT=posInT19; else Print("valid posInT:0,1,2,11,110,13,15,17,17_c,19,_EcartFDegpLength,_FDegpLength,_pLength,_EcartpLength\n"); } else { test_PosInT=NULL; test_PosInL=NULL; } si_opt_2|=Sy_bit(23); return FALSE; } else /*==================== locNF ======================================*/ if(strcmp(sys_cmd,"locNF")==0) { const short t[]={4,VECTOR_CMD,MODUL_CMD,INT_CMD,INTVEC_CMD}; if (iiCheckTypes(h,t,1)) { poly f=(poly)h->Data(); h=h->next; ideal m=(ideal)h->Data(); assumeStdFlag(h); h=h->next; int n=(int)((long)h->Data()); h=h->next; intvec *v=(intvec *)h->Data(); /* == now the work starts == */ short * iv=iv2array(v, currRing); poly r=0; poly hp=ppJetW(f,n,iv); int s=MATCOLS(m); int j=0; matrix T=mp_InitI(s,1,0, currRing); while (hp != NULL) { if (pDivisibleBy(m->m[j],hp)) { if (MATELEM(T,j+1,1)==0) { MATELEM(T,j+1,1)=pDivideM(pHead(hp),pHead(m->m[j])); } else { pAdd(MATELEM(T,j+1,1),pDivideM(pHead(hp),pHead(m->m[j]))); } hp=ppJetW(ksOldSpolyRed(m->m[j],hp,0),n,iv); j=0; } else { if (j==s-1) { r=pAdd(r,pHead(hp)); hp=pLmDeleteAndNext(hp); /* hp=pSub(hp,pHead(hp));*/ j=0; } else { j++; } } } matrix Temp=mp_Transp((matrix) id_Vec2Ideal(r, currRing), currRing); matrix R=mpNew(MATCOLS((matrix) id_Vec2Ideal(f, currRing)),1); for (int k=1;k<=MATROWS(Temp);k++) { MATELEM(R,k,1)=MATELEM(Temp,k,1); } lists L=(lists)omAllocBin(slists_bin); L->Init(2); L->m[0].rtyp=MATRIX_CMD; L->m[0].data=(void *)R; L->m[1].rtyp=MATRIX_CMD; L->m[1].data=(void *)T; res->data=L; res->rtyp=LIST_CMD; // iv aufraeumen omFree(iv); return FALSE; } else return TRUE; } else /*==================== poly debug ==================================*/ if(strcmp(sys_cmd,"p")==0) { # ifdef RDEBUG p_DebugPrint((poly)h->Data(), currRing); # else Warn("Sorry: not available for release build!"); # endif return FALSE; } else /*==================== setsyzcomp ==================================*/ if(strcmp(sys_cmd,"setsyzcomp")==0) { if ((h!=NULL) && (h->Typ()==INT_CMD)) { int k = (int)(long)h->Data(); if ( currRing->order[0] == ringorder_s ) { rSetSyzComp(k, currRing); } } } /*==================== ring debug ==================================*/ if(strcmp(sys_cmd,"r")==0) { # ifdef RDEBUG rDebugPrint((ring)h->Data()); # else Warn("Sorry: not available for release build!"); # endif return FALSE; } else /*==================== changeRing ========================*/ /* The following code changes the names of the variables in the current ring to "x1", "x2", ..., "xN", where N is the number of variables in the current ring. The purpose of this rewriting is to eliminate indexed variables, as they may cause problems when generating scripts for Magma, Maple, or Macaulay2. */ if(strcmp(sys_cmd,"changeRing")==0) { int varN = currRing->N; char h[10]; for (int i = 1; i <= varN; i++) { omFree(currRing->names[i - 1]); sprintf(h, "x%d", i); currRing->names[i - 1] = omStrDup(h); } rComplete(currRing); res->rtyp = INT_CMD; res->data = (void*)0L; return FALSE; } else /*==================== mtrack ==================================*/ if(strcmp(sys_cmd,"mtrack")==0) { #ifdef OM_TRACK om_Opts.MarkAsStatic = 1; FILE *fd = NULL; int max = 5; while (h != NULL) { omMarkAsStaticAddr(h); if (fd == NULL && h->Typ()==STRING_CMD) { fd = fopen((char*) h->Data(), "w"); if (fd == NULL) Warn("Can not open %s for writing og mtrack. Using stdout"); // %s ??? } if (h->Typ() == INT_CMD) { max = (int)(long)h->Data(); } h = h->Next(); } omPrintUsedTrackAddrs((fd == NULL ? stdout : fd), max); if (fd != NULL) fclose(fd); om_Opts.MarkAsStatic = 0; return FALSE; #endif } /*==================== mtrack_all ==================================*/ if(strcmp(sys_cmd,"mtrack_all")==0) { #ifdef OM_TRACK om_Opts.MarkAsStatic = 1; FILE *fd = NULL; if ((h!=NULL) &&(h->Typ()==STRING_CMD)) { fd = fopen((char*) h->Data(), "w"); if (fd == NULL) Warn("Can not open %s for writing og mtrack. Using stdout"); omMarkAsStaticAddr(h); } // OB: TBC print to fd omPrintUsedAddrs((fd == NULL ? stdout : fd), 5); if (fd != NULL) fclose(fd); om_Opts.MarkAsStatic = 0; return FALSE; #endif } else /*==================== backtrace ==================================*/ #ifndef OM_NDEBUG if(strcmp(sys_cmd,"backtrace")==0) { omPrintCurrentBackTrace(stdout); return FALSE; } else #endif #if !defined(OM_NDEBUG) /*==================== omMemoryTest ==================================*/ if (strcmp(sys_cmd,"omMemoryTest")==0) { #ifdef OM_STATS_H PrintS("\n[om_Info]: \n"); omUpdateInfo(); #define OM_PRINT(name) Print(" %-22s : %10ld \n", #name, om_Info . name) OM_PRINT(MaxBytesSystem); OM_PRINT(CurrentBytesSystem); OM_PRINT(MaxBytesSbrk); OM_PRINT(CurrentBytesSbrk); OM_PRINT(MaxBytesMmap); OM_PRINT(CurrentBytesMmap); OM_PRINT(UsedBytes); OM_PRINT(AvailBytes); OM_PRINT(UsedBytesMalloc); OM_PRINT(AvailBytesMalloc); OM_PRINT(MaxBytesFromMalloc); OM_PRINT(CurrentBytesFromMalloc); OM_PRINT(MaxBytesFromValloc); OM_PRINT(CurrentBytesFromValloc); OM_PRINT(UsedBytesFromValloc); OM_PRINT(AvailBytesFromValloc); OM_PRINT(MaxPages); OM_PRINT(UsedPages); OM_PRINT(AvailPages); OM_PRINT(MaxRegionsAlloc); OM_PRINT(CurrentRegionsAlloc); #undef OM_PRINT #endif #ifdef OM_OPTS_H PrintS("\n[om_Opts]: \n"); #define OM_PRINT(format, name) Print(" %-22s : %10" format"\n", #name, om_Opts . name) OM_PRINT("d", MinTrack); OM_PRINT("d", MinCheck); OM_PRINT("d", MaxTrack); OM_PRINT("d", MaxCheck); OM_PRINT("d", Keep); OM_PRINT("d", HowToReportErrors); OM_PRINT("d", MarkAsStatic); OM_PRINT("u", PagesPerRegion); OM_PRINT("p", OutOfMemoryFunc); OM_PRINT("p", MemoryLowFunc); OM_PRINT("p", ErrorHook); #undef OM_PRINT #endif #ifdef OM_ERROR_H Print("\n\n[om_ErrorStatus] : '%s' (%s)\n", omError2String(om_ErrorStatus), omError2Serror(om_ErrorStatus)); Print("[om_InternalErrorStatus]: '%s' (%s)\n", omError2String(om_InternalErrorStatus), omError2Serror(om_InternalErrorStatus)); #endif // omTestMemory(1); // omtTestErrors(); return FALSE; } else #endif /*==================== pDivStat =============================*/ #if defined(PDEBUG) || defined(PDIV_DEBUG) if(strcmp(sys_cmd,"pDivStat")==0) { extern void pPrintDivisbleByStat(); pPrintDivisbleByStat(); return FALSE; } else #endif /*==================== alarm ==================================*/ #ifdef unix if(strcmp(sys_cmd,"alarm")==0) { if ((h!=NULL) &&(h->Typ()==INT_CMD)) { // standard variant -> SIGALARM (standard: abort) //alarm((unsigned)h->next->Data()); // process time (user +system): SIGVTALARM struct itimerval t,o; memset(&t,0,sizeof(t)); t.it_value.tv_sec =(unsigned)((unsigned long)h->Data()); setitimer(ITIMER_VIRTUAL,&t,&o); return FALSE; } else WerrorS("int expected"); } else #endif /*==================== red =============================*/ #if 0 if(strcmp(sys_cmd,"red")==0) { if ((h!=NULL) &&(h->Typ()==IDEAL_CMD)) { res->rtyp=IDEAL_CMD; res->data=(void *)kStdred((ideal)h->Data(),NULL,testHomog,NULL); setFlag(res,FLAG_STD); return FALSE; } else WerrorS("ideal expected"); } else #endif /*==================== fastcomb =============================*/ if(strcmp(sys_cmd,"fastcomb")==0) { if ((h!=NULL) &&(h->Typ()==IDEAL_CMD)) { if (h->next!=NULL) { if (h->next->Typ()!=POLY_CMD) { Warn("Wrong types for poly= comb(ideal,poly)"); } } res->rtyp=POLY_CMD; res->data=(void *) fglmLinearCombination( (ideal)h->Data(),(poly)h->next->Data()); return FALSE; } else WerrorS("ideal expected"); } else /*==================== comb =============================*/ if(strcmp(sys_cmd,"comb")==0) { if ((h!=NULL) &&(h->Typ()==IDEAL_CMD)) { if (h->next!=NULL) { if (h->next->Typ()!=POLY_CMD) { Warn("Wrong types for poly= comb(ideal,poly)"); } } res->rtyp=POLY_CMD; res->data=(void *)fglmNewLinearCombination( (ideal)h->Data(),(poly)h->next->Data()); return FALSE; } else WerrorS("ideal expected"); } else #if 0 /* debug only */ /*==================== listall ===================================*/ if(strcmp(sys_cmd,"listall")==0) { void listall(int showproc); int showproc=0; if ((h!=NULL) && (h->Typ()==INT_CMD)) showproc=(int)((long)h->Data()); listall(showproc); return FALSE; } else #endif #if 0 /* debug only */ /*==================== proclist =================================*/ if(strcmp(sys_cmd,"proclist")==0) { void piShowProcList(); piShowProcList(); return FALSE; } else #endif /* ==================== newton ================================*/ #ifdef HAVE_NEWTON if(strcmp(sys_cmd,"newton")==0) { if ((h->Typ()!=POLY_CMD) || (h->next->Typ()!=INT_CMD) || (h->next->next->Typ()!=INT_CMD)) { WerrorS("system(\"newton\",,,) expected"); return TRUE; } poly p=(poly)(h->Data()); int l=pLength(p); short *points=(short *)omAlloc(currRing->N*l*sizeof(short)); int i,j,k; k=0; poly pp=p; for (i=0;pp!=NULL;i++) { for(j=1;j<=currRing->N;j++) { points[k]=pGetExp(pp,j); k++; } pIter(pp); } hc_ERG r=hc_KOENIG(currRing->N, // dimension l, // number of points (short*) points, // points: x_1, y_1,z_1, x_2,y_2,z2,... currRing->OrdSgn==-1, (int) (h->next->Data()), // 1: Milnor, 0: Newton (int) (h->next->next->Data()) // debug ); //----<>---Output----------------------- // PrintS("Bin jetzt in extra.cc bei der Auswertung.\n"); // ********** lists L=(lists)omAllocBin(slists_bin); L->Init(6); L->m[0].rtyp=STRING_CMD; // newtonnumber; L->m[0].data=(void *)omStrDup(r.nZahl); L->m[1].rtyp=INT_CMD; L->m[1].data=(void *)(long)r.achse; // flag for unoccupied axes L->m[2].rtyp=INT_CMD; L->m[2].data=(void *)(long)r.deg; // #degenerations if ( r.deg != 0) // only if degenerations exist { L->m[3].rtyp=INT_CMD; L->m[3].data=(void *)(long)r.anz_punkte; // #points //---<>--number of points------ int anz = r.anz_punkte; // number of points int dim = (currRing->N); // dimension intvec* v = new intvec( anz*dim ); for (i=0; im[4].rtyp=INTVEC_CMD; L->m[4].data=(void *)v; //---<>--degenerations--------- int deg = r.deg; // number of points intvec* w = new intvec( r.speicher ); // necessary memory i=0; // start copying do { (*w)[i] = r.deg_tab[i]; i++; } while (r.deg_tab[i-1] != -2); // mark for end of list L->m[5].rtyp=INTVEC_CMD; L->m[5].data=(void *)w; } else { L->m[3].rtyp=INT_CMD; L->m[3].data=(char *)0; L->m[4].rtyp=DEF_CMD; L->m[5].rtyp=DEF_CMD; } res->data=(void *)L; res->rtyp=LIST_CMD; // free all pointer in r: delete[] r.nZahl; delete[] r.pu; delete[] r.deg_tab; // Ist das ein Problem?? omFreeSize((ADDRESS)points,currRing->N*l*sizeof(short)); return FALSE; } else #endif /*==== connection to Sebastian Jambor's code ======*/ /* This code connects Sebastian Jambor's code for computing the minimal polynomial of an (n x n) matrix with entries in F_p to SINGULAR. Two conversion methods are needed; see further up in this file: (1) conversion of a matrix with long entries to a SINGULAR matrix with number entries, where the numbers are coefficients in currRing; (2) conversion of an array of longs (encoding the coefficients of the minimal polynomial) to a SINGULAR poly living in currRing. */ if (strcmp(sys_cmd, "minpoly") == 0) { if ((h == NULL) || (h->Typ() != MATRIX_CMD) || h->next != NULL) { Werror("expected exactly one argument: %s", "a square matrix with number entries"); return TRUE; } else { matrix m = (matrix)h->Data(); int n = m->rows(); unsigned long p = (unsigned long)n_GetChar(currRing->cf); if (n != m->cols()) { WerrorS("expected exactly one argument: " "a square matrix with number entries"); return TRUE; } unsigned long** ml = singularMatrixToLongMatrix(m); unsigned long* polyCoeffs = computeMinimalPolynomial(ml, n, p); poly theMinPoly = longCoeffsToSingularPoly(polyCoeffs, n); res->rtyp = POLY_CMD; res->data = (void *)theMinPoly; for (int i = 0; i < n; i++) delete[] ml[i]; delete[] ml; delete[] polyCoeffs; return FALSE; } } else /*==================== sdb_flags =================*/ #ifdef HAVE_SDB if (strcmp(sys_cmd, "sdb_flags") == 0) { if ((h!=NULL) && (h->Typ()==INT_CMD)) { sdb_flags=(int)((long)h->Data()); } else { WerrorS("system(\"sdb_flags\",`int`) expected"); return TRUE; } return FALSE; } else #endif /*==================== sdb_edit =================*/ #ifdef HAVE_SDB if (strcmp(sys_cmd, "sdb_edit") == 0) { if ((h!=NULL) && (h->Typ()==PROC_CMD)) { procinfov p=(procinfov)h->Data(); sdb_edit(p); } else { WerrorS("system(\"sdb_edit\",`proc`) expected"); return TRUE; } return FALSE; } else #endif /*==================== GF =================*/ #if 0 // for testing only if (strcmp(sys_cmd, "GF") == 0) { if ((h!=NULL) && (h->Typ()==POLY_CMD)) { int c=rChar(currRing); setCharacteristic( c,nfMinPoly[0], currRing->parameter[0][0] ); CanonicalForm F( convSingGFFactoryGF( (poly)h->Data(), currRing ) ); res->rtyp=POLY_CMD; res->data=convFactoryGFSingGF( F, currRing ); return FALSE; } else { WerrorS("wrong typ"); return TRUE;} } else #endif /*==================== SVD =================*/ #ifdef HAVE_SVD if (strcmp(sys_cmd, "svd") == 0) { extern lists testsvd(matrix M); res->rtyp=LIST_CMD; res->data=(char*)(testsvd((matrix)h->Data())); eturn FALSE; } else #endif /*==================== DLL =================*/ #ifdef __CYGWIN__ #ifdef HAVE_DL /* testing the DLL functionality under Win32 */ if (strcmp(sys_cmd, "DLL") == 0) { typedef void (*Void_Func)(); typedef int (*Int_Func)(int); void *hh=dynl_open("WinDllTest.dll"); if ((h!=NULL) && (h->Typ()==INT_CMD)) { int (*f)(int); if (hh!=NULL) { int (*f)(int); f=(Int_Func)dynl_sym(hh,"PlusDll"); int i=10; if (f!=NULL) printf("%d\n",f(i)); else PrintS("cannot find PlusDll\n"); } } else { void (*f)(); f= (Void_Func)dynl_sym(hh,"TestDll"); if (f!=NULL) f(); else PrintS("cannot find TestDll\n"); } return FALSE; } else #endif #endif #ifdef HAVE_RING2TOM /*==================== ring-GB ==================================*/ if (strcmp(sys_cmd, "findZeroPoly")==0) { ring r = currRing; poly f = (poly) h->Data(); res->rtyp=POLY_CMD; res->data=(poly) kFindZeroPoly(f, r, r); return(FALSE); } else /*==================== Creating zero polynomials =================*/ #ifdef HAVE_VANIDEAL if (strcmp(sys_cmd, "createG0")==0) { /* long exp[50]; int N = 0; while (h != NULL) { N += 1; exp[N] = (long) h->Data(); // if (exp[i] % 2 != 0) exp[i] -= 1; h = h->next; } for (int k = 1; N + k <= currRing->N; k++) exp[k] = 0; poly t_p; res->rtyp=POLY_CMD; res->data= (poly) kCreateZeroPoly(exp, -1, &t_p, currRing, currRing); return(FALSE); */ res->rtyp = IDEAL_CMD; res->data = (ideal) createG0(); return(FALSE); } else #endif /*==================== redNF_ring =================*/ if (strcmp(sys_cmd, "redNF_ring")==0) { ring r = currRing; poly f = (poly) h->Data(); h = h->next; ideal G = (ideal) h->Data(); res->rtyp=POLY_CMD; res->data=(poly) ringRedNF(f, G, r); return(FALSE); } else #endif /*==================== Roune Hilb =================*/ if (strcmp(sys_cmd, "hilbroune") == 0) { ideal I; if ((h!=NULL) && (h->Typ()==IDEAL_CMD)) { I=(ideal)h->CopyD(); slicehilb(I); } else return TRUE; return FALSE; } else /*==================== F5 Implementation =================*/ #ifdef HAVE_F5 if (strcmp(sys_cmd, "f5")==0) { if (h->Typ()!=IDEAL_CMD) { WerrorS("ideal expected"); return TRUE; } ring r = currRing; ideal G = (ideal) h->Data(); h = h->next; int opt; if(h != NULL) { opt = (int) (long) h->Data(); } else { opt = 2; } h = h->next; int plus; if(h != NULL) { plus = (int) (long) h->Data(); } else { plus = 0; } h = h->next; int termination; if(h != NULL) { termination = (int) (long) h->Data(); } else { termination = 0; } res->rtyp=IDEAL_CMD; res->data=(ideal) F5main(G,r,opt,plus,termination); return FALSE; } else #endif /*==================== Testing groebner basis =================*/ #ifdef HAVE_RINGS if (strcmp(sys_cmd, "NF_ring")==0) { ring r = currRing; poly f = (poly) h->Data(); h = h->next; ideal G = (ideal) h->Data(); res->rtyp=POLY_CMD; res->data=(poly) ringNF(f, G, r); return(FALSE); } else if (strcmp(sys_cmd, "spoly")==0) { poly f = pCopy((poly) h->Data()); h = h->next; poly g = pCopy((poly) h->Data()); res->rtyp=POLY_CMD; res->data=(poly) plain_spoly(f,g); return(FALSE); } else if (strcmp(sys_cmd, "testGB")==0) { ideal I = (ideal) h->Data(); h = h->next; ideal GI = (ideal) h->Data(); res->rtyp = INT_CMD; res->data = (void *)(long) testGB(I, GI); return(FALSE); } else #endif /*==================== sca?AltVar ==================================*/ #ifdef HAVE_PLURAL if ( (strcmp(sys_cmd, "AltVarStart") == 0) || (strcmp(sys_cmd, "AltVarEnd") == 0) ) { ring r = currRing; if((h!=NULL) && (h->Typ()==RING_CMD)) r = (ring)h->Data(); else { WerrorS("`system(\"AltVarStart/End\"[,])` expected"); return TRUE; } res->rtyp=INT_CMD; if (rIsSCA(r)) { if(strcmp(sys_cmd, "AltVarStart") == 0) res->data = (void*)(long)scaFirstAltVar(r); else res->data = (void*)(long)scaLastAltVar(r); return FALSE; } WerrorS("`system(\"AltVarStart/End\",) requires a SCA ring"); return TRUE; } else #endif /*==================== RatNF, noncomm rational coeffs =================*/ #ifdef HAVE_RATGRING if (strcmp(sys_cmd, "intratNF") == 0) { poly p; poly *q; ideal I; int is, k, id; if ((h!=NULL) && (h->Typ()==POLY_CMD)) { p=(poly)h->CopyD(); h=h->next; // Print("poly is done\n"); } else return TRUE; if ((h!=NULL) && (h->Typ()==IDEAL_CMD)) { I=(ideal)h->CopyD(); q = I->m; h=h->next; // Print("ideal is done\n"); } else return TRUE; if ((h!=NULL) && (h->Typ()==INT_CMD)) { is=(int)((long)(h->Data())); // res->rtyp=INT_CMD; // Print("int is done\n"); // res->rtyp=IDEAL_CMD; if (rIsPluralRing(currRing)) { id = IDELEMS(I); int *pl=(int*)omAlloc0(IDELEMS(I)*sizeof(int)); for(k=0; k < id; k++) { pl[k] = pLength(I->m[k]); } Print("starting redRat\n"); //res->data = (char *) redRat(&p, q, pl, (int)IDELEMS(I),is,currRing); res->data=p; res->rtyp=POLY_CMD; // res->data = ncGCD(p,q,currRing); } else { res->rtyp=POLY_CMD; res->data=p; } } else return TRUE; return FALSE; } else /*==================== RatNF, noncomm rational coeffs =================*/ if (strcmp(sys_cmd, "ratNF") == 0) { poly p,q; int is, htype; if ((h!=NULL) && ( (h->Typ()==POLY_CMD) || (h->Typ()==VECTOR_CMD) ) ) { p=(poly)h->CopyD(); h=h->next; htype = h->Typ(); } else return TRUE; if ((h!=NULL) && ( (h->Typ()==POLY_CMD) || (h->Typ()==VECTOR_CMD) ) ) { q=(poly)h->CopyD(); h=h->next; } else return TRUE; if ((h!=NULL) && (h->Typ()==INT_CMD)) { is=(int)((long)(h->Data())); res->rtyp=htype; // res->rtyp=IDEAL_CMD; if (rIsPluralRing(currRing)) { res->data = nc_rat_ReduceSpolyNew(q,p,is, currRing); // res->data = ncGCD(p,q,currRing); } else res->data=p; } else return TRUE; return FALSE; } else /*==================== RatSpoly, noncomm rational coeffs =================*/ if (strcmp(sys_cmd, "ratSpoly") == 0) { poly p,q; int is; if ((h!=NULL) && (h->Typ()==POLY_CMD)) { p=(poly)h->CopyD(); h=h->next; } else return TRUE; if ((h!=NULL) && (h->Typ()==POLY_CMD)) { q=(poly)h->CopyD(); h=h->next; } else return TRUE; if ((h!=NULL) && (h->Typ()==INT_CMD)) { is=(int)((long)(h->Data())); res->rtyp=POLY_CMD; // res->rtyp=IDEAL_CMD; if (rIsPluralRing(currRing)) { res->data = nc_rat_CreateSpoly(p,q,is,currRing); // res->data = ncGCD(p,q,currRing); } else res->data=p; } else return TRUE; return FALSE; } else #endif // HAVE_RATGRING /*==================== Rat def =================*/ if (strcmp(sys_cmd, "ratVar") == 0) { int start,end; if ((h!=NULL) && (h->Typ()==POLY_CMD)) { start=pIsPurePower((poly)h->Data()); h=h->next; } else return TRUE; if ((h!=NULL) && (h->Typ()==POLY_CMD)) { end=pIsPurePower((poly)h->Data()); h=h->next; } else return TRUE; currRing->real_var_start=start; currRing->real_var_end=end; return (start==0)||(end==0)||(start>end); } else /*==================== t-rep-GB ==================================*/ if (strcmp(sys_cmd, "unifastmult")==0) { poly f = (poly)h->Data(); h=h->next; poly g=(poly)h->Data(); res->rtyp=POLY_CMD; res->data=unifastmult(f,g,currRing); return(FALSE); } else if (strcmp(sys_cmd, "multifastmult")==0) { poly f = (poly)h->Data(); h=h->next; poly g=(poly)h->Data(); res->rtyp=POLY_CMD; res->data=multifastmult(f,g,currRing); return(FALSE); } else if (strcmp(sys_cmd, "mults")==0) { res->rtyp=INT_CMD ; res->data=(void*)(long) Mults(); return(FALSE); } else if (strcmp(sys_cmd, "fastpower")==0) { ring r = currRing; poly f = (poly)h->Data(); h=h->next; int n=(int)((long)h->Data()); res->rtyp=POLY_CMD ; res->data=(void*) pFastPower(f,n,r); return(FALSE); } else if (strcmp(sys_cmd, "normalpower")==0) { poly f = (poly)h->Data(); h=h->next; int n=(int)((long)h->Data()); res->rtyp=POLY_CMD ; res->data=(void*) pPower(pCopy(f),n); return(FALSE); } else if (strcmp(sys_cmd, "MCpower")==0) { ring r = currRing; poly f = (poly)h->Data(); h=h->next; int n=(int)((long)h->Data()); res->rtyp=POLY_CMD ; res->data=(void*) pFastPowerMC(f,n,r); return(FALSE); } else if (strcmp(sys_cmd, "bit_subst")==0) { ring r = currRing; poly outer = (poly)h->Data(); h=h->next; poly inner=(poly)h->Data(); res->rtyp=POLY_CMD ; res->data=(void*) uni_subst_bits(outer, inner,r); return(FALSE); } else /*==================== gcd-varianten =================*/ if (strcmp(sys_cmd, "gcd") == 0) { if (h==NULL) { #ifdef HAVE_PLURAL Print("EZGCD:%d (use EZGCD for gcd of polynomials in char 0)\n",isOn(SW_USE_EZGCD)); Print("EZGCD_P:%d (use EZGCD_P for gcd of polynomials in char p)\n",isOn(SW_USE_EZGCD_P)); Print("CRGCD:%d (use chinese Remainder for gcd of polynomials in char 0)\n",isOn(SW_USE_CHINREM_GCD)); Print("QGCD:%d (use QGCD for gcd of polynomials in alg. ext.)\n",isOn(SW_USE_QGCD)); #endif Print("homog:%d (use homog. test for factorization of polynomials)\n",singular_homog_flag); return FALSE; } else if ((h!=NULL) && (h->Typ()==STRING_CMD) && (h->next!=NULL) && (h->next->Typ()==INT_CMD)) { int d=(int)(long)h->next->Data(); char *s=(char *)h->Data(); #ifdef HAVE_PLURAL if (strcmp(s,"EZGCD")==0) { if (d) On(SW_USE_EZGCD); else Off(SW_USE_EZGCD); } else if (strcmp(s,"EZGCD_P")==0) { if (d) On(SW_USE_EZGCD_P); else Off(SW_USE_EZGCD_P); } else if (strcmp(s,"CRGCD")==0) { if (d) On(SW_USE_CHINREM_GCD); else Off(SW_USE_CHINREM_GCD); } else if (strcmp(s,"QGCD")==0) { if (d) On(SW_USE_QGCD); else Off(SW_USE_QGCD); } else #endif if (strcmp(s,"homog")==0) { if (d) singular_homog_flag=1; else singular_homog_flag=0; } else return TRUE; return FALSE; } else return TRUE; } else /*==================== subring =================*/ if (strcmp(sys_cmd, "subring") == 0) { if (h!=NULL) { extern ring rSubring(ring r,leftv v); /* ipshell.cc*/ res->data=(char *)rSubring(currRing,h); res->rtyp=RING_CMD; return res->data==NULL; } else return TRUE; } else /*==================== HNF =================*/ #ifdef HAVE_NTL if (strcmp(sys_cmd, "HNF") == 0) { if (h!=NULL) { res->rtyp=h->Typ(); if (h->Typ()==MATRIX_CMD) { res->data=(char *)singntl_HNF((matrix)h->Data(), currRing); return FALSE; } else if (h->Typ()==INTMAT_CMD) { res->data=(char *)singntl_HNF((intvec*)h->Data()); return FALSE; } else return TRUE; } else return TRUE; } else /*================= probIrredTest ======================*/ if (strcmp (sys_cmd, "probIrredTest") == 0) { if (h!=NULL && (h->Typ()== POLY_CMD) && ((h->next != NULL) && h->next->Typ() == STRING_CMD)) { CanonicalForm F= convSingPFactoryP((poly)(h->Data()), currRing); char *s=(char *)h->next->Data(); double error= atof (s); int irred= probIrredTest (F, error); res->rtyp= INT_CMD; res->data= (void*)(long)irred; return FALSE; } else return TRUE; } else #endif #ifdef __CYGWIN__ /*==================== Python Singular =================*/ if (strcmp(sys_cmd, "python") == 0) { const char* c; if ((h!=NULL) && (h->Typ()==STRING_CMD)) { c=(const char*)h->Data(); if (!PyInitialized) { PyInitialized = 1; // Py_Initialize(); // initPySingular(); } // PyRun_SimpleString(c); return FALSE; } else return TRUE; } else /*==================== Python Singular ================= if (strcmp(sys_cmd, "ipython") == 0) { const char* c; { if (!PyInitialized) { PyInitialized = 1; Py_Initialize(); initPySingular(); } PyRun_SimpleString( "try: \n\ __IPYTHON__ \n\ except NameError: \n\ argv = [''] \n\ banner = exit_msg = '' \n\ else: \n\ # Command-line options for IPython (a list like sys.argv) \n\ argv = ['-pi1','In <\\#>:','-pi2',' .\\D.:','-po','Out<\\#>:'] \n\ banner = '*** Nested interpreter ***' \n\ exit_msg = '*** Back in main IPython ***' \n\ \n\ # First import the embeddable shell class \n\ from IPython.Shell import IPShellEmbed \n\ # Now create the IPython shell instance. Put ipshell() anywhere in your code \n\ # where you want it to open. \n\ ipshell = IPShellEmbed(argv,banner=banner,exit_msg=exit_msg) \n\ ipshell()"); return FALSE; } } else */ #endif /*==================== mpz_t loader ======================*/ if(strcmp(sys_cmd, "GNUmpLoad")==0) { if ((h != NULL) && (h->Typ() == STRING_CMD)) { char* filename = (char*)h->Data(); FILE* f = fopen(filename, "r"); if (f == NULL) { WerrorS( "invalid file name (in paths use '/')"); return FALSE; } mpz_t m; mpz_init(m); mpz_inp_str(m, f, 10); fclose(f); number n = n_InitMPZ(m, coeffs_BIGINT); res->rtyp = BIGINT_CMD; res->data = (void*)n; return FALSE; } else { WerrorS( "expected valid file name as a string"); return TRUE; } } else /*==================== intvec matching ======================*/ /* Given two non-empty intvecs, the call 'system("intvecMatchingSegments", ivec, jvec);' computes all occurences of jvec in ivec, i.e., it returns a list of int indices k such that ivec[k..size(jvec)+k-1] = jvec. If no such k exists (e.g. when ivec is shorter than jvec), an intvec with the single entry 0 is being returned. */ if(strcmp(sys_cmd, "intvecMatchingSegments")==0) { if ((h != NULL) && (h->Typ() == INTVEC_CMD) && (h->next != NULL) && (h->next->Typ() == INTVEC_CMD) && (h->next->next == NULL)) { intvec* ivec = (intvec*)h->Data(); intvec* jvec = (intvec*)h->next->Data(); intvec* r = new intvec(1); (*r)[0] = 0; int validEntries = 0; for (int k = 0; k <= ivec->rows() - jvec->rows(); k++) { if (memcmp(&(*ivec)[k], &(*jvec)[0], sizeof(int) * jvec->rows()) == 0) { if (validEntries == 0) (*r)[0] = k + 1; else { r->resize(validEntries + 1); (*r)[validEntries] = k + 1; } validEntries++; } } res->rtyp = INTVEC_CMD; res->data = (void*)r; return FALSE; } else { WerrorS("expected two non-empty intvecs as arguments"); return TRUE; } } else /* ================== intvecOverlap ======================= */ /* Given two non-empty intvecs, the call 'system("intvecOverlap", ivec, jvec);' computes the longest intvec kvec such that ivec ends with kvec and jvec starts with kvec. The length of this overlap is being returned. If there is no overlap at all, then 0 is being returned. */ if(strcmp(sys_cmd, "intvecOverlap")==0) { if ((h != NULL) && (h->Typ() == INTVEC_CMD) && (h->next != NULL) && (h->next->Typ() == INTVEC_CMD) && (h->next->next == NULL)) { intvec* ivec = (intvec*)h->Data(); intvec* jvec = (intvec*)h->next->Data(); int ir = ivec->rows(); int jr = jvec->rows(); int r = jr; if (ir < jr) r = ir; /* r = min{ir, jr} */ while ((r >= 1) && (memcmp(&(*ivec)[ir - r], &(*jvec)[0], sizeof(int) * r) != 0)) r--; res->rtyp = INT_CMD; res->data = (void*)(long)r; return FALSE; } else { WerrorS("expected two non-empty intvecs as arguments"); return TRUE; } } else /*==================== Hensel's lemma ======================*/ if(strcmp(sys_cmd, "henselfactors")==0) { if ((h != NULL) && (h->Typ() == INT_CMD) && (h->next != NULL) && (h->next->Typ() == INT_CMD) && (h->next->next != NULL) && (h->next->next->Typ() == POLY_CMD) && (h->next->next->next != NULL) && (h->next->next->next->Typ() == POLY_CMD) && (h->next->next->next->next != NULL) && (h->next->next->next->next->Typ() == POLY_CMD) && (h->next->next->next->next->next != NULL) && (h->next->next->next->next->next->Typ() == INT_CMD) && (h->next->next->next->next->next->next == NULL)) { int xIndex = (int)(long)h->Data(); int yIndex = (int)(long)h->next->Data(); poly hh = (poly)h->next->next->Data(); poly f0 = (poly)h->next->next->next->Data(); poly g0 = (poly)h->next->next->next->next->Data(); int d = (int)(long)h->next->next->next->next->next->Data(); poly f; poly g; henselFactors(xIndex, yIndex, hh, f0, g0, d, f, g); lists L = (lists)omAllocBin(slists_bin); L->Init(2); L->m[0].rtyp = POLY_CMD; L->m[0].data=(void*)f; L->m[1].rtyp = POLY_CMD; L->m[1].data=(void*)g; res->rtyp = LIST_CMD; res->data = (char *)L; return FALSE; } else { WerrorS( "expected argument list (int, int, poly, poly, poly, int)"); return TRUE; } } else /*==================== neworder =============================*/ if(strcmp(sys_cmd,"neworder")==0) { if ((h!=NULL) &&(h->Typ()==IDEAL_CMD)) { res->rtyp=STRING_CMD; res->data=(void *)singclap_neworder((ideal)h->Data(), currRing); return FALSE; } else WerrorS("ideal expected"); } else /*==================== Approx_Step =================*/ #ifdef HAVE_PLURAL if (strcmp(sys_cmd, "astep") == 0) { ideal I; if ((h!=NULL) && (h->Typ()==IDEAL_CMD)) { I=(ideal)h->CopyD(); res->rtyp=IDEAL_CMD; if (rIsPluralRing(currRing)) res->data=Approx_Step(I); else res->data=I; setFlag(res,FLAG_STD); } else return TRUE; return FALSE; } else #endif /*==================== PrintMat =================*/ #ifdef HAVE_PLURAL if (strcmp(sys_cmd, "PrintMat") == 0) { int a; int b; ring r; int metric; if (h!=NULL) { if (h->Typ()==INT_CMD) { a=(int)((long)(h->Data())); h=h->next; } else if (h->Typ()==INT_CMD) { b=(int)((long)(h->Data())); h=h->next; } else if (h->Typ()==RING_CMD) { r=(ring)h->Data(); h=h->next; } else return TRUE; } else return TRUE; if ((h!=NULL) && (h->Typ()==INT_CMD)) { metric=(int)((long)(h->Data())); } res->rtyp=MATRIX_CMD; if (rIsPluralRing(r)) res->data=nc_PrintMat(a,b,r,metric); else res->data=NULL; return FALSE; } else #endif /* ============ NCUseExtensions ======================== */ #ifdef HAVE_PLURAL if(strcmp(sys_cmd,"NCUseExtensions")==0) { if ((h!=NULL) && (h->Typ()==INT_CMD)) res->data=(void *)(long)setNCExtensions( (int)((long)(h->Data())) ); else res->data=(void *)(long)getNCExtensions(); res->rtyp=INT_CMD; return FALSE; } else #endif /* ============ NCGetType ======================== */ #ifdef HAVE_PLURAL if(strcmp(sys_cmd,"NCGetType")==0) { res->rtyp=INT_CMD; if( rIsPluralRing(currRing) ) res->data=(void *)(long)ncRingType(currRing); else res->data=(void *)(-1L); return FALSE; } else #endif /* ============ ForceSCA ======================== */ #ifdef HAVE_PLURAL if(strcmp(sys_cmd,"ForceSCA")==0) { if( !rIsPluralRing(currRing) ) return TRUE; int b, e; if ((h!=NULL) && (h->Typ()==INT_CMD)) { b = (int)((long)(h->Data())); h=h->next; } else return TRUE; if ((h!=NULL) && (h->Typ()==INT_CMD)) { e = (int)((long)(h->Data())); } else return TRUE; if( !sca_Force(currRing, b, e) ) return TRUE; return FALSE; } else #endif /* ============ ForceNewNCMultiplication ======================== */ #ifdef HAVE_PLURAL if(strcmp(sys_cmd,"ForceNewNCMultiplication")==0) { if( !rIsPluralRing(currRing) ) return TRUE; if( !ncInitSpecialPairMultiplication(currRing) ) // No Plural! return TRUE; return FALSE; } else #endif /* ============ ForceNewOldNCMultiplication ======================== */ #ifdef HAVE_PLURAL if(strcmp(sys_cmd,"ForceNewOldNCMultiplication")==0) { if( !rIsPluralRing(currRing) ) return TRUE; if( !ncInitSpecialPowersMultiplication(currRing) ) // Enable Formula for Plural (depends on swiches)! return TRUE; return FALSE; } else #endif /*==================== test64 =================*/ #if 0 if(strcmp(sys_cmd,"test64")==0) { long l=8;int i; for(i=1;i<62;i++) { l=l<<1; number n=n_Init(l,coeffs_BIGINT); Print("%ld= ",l);n_Print(n,coeffs_BIGINT); CanonicalForm nn=n_convSingNFactoryN(n,TRUE,coeffs_BIGINT); n_Delete(&n,coeffs_BIGINT); n=n_convFactoryNSingN(nn,coeffs_BIGINT); PrintS(" F:"); n_Print(n,coeffs_BIGINT); PrintLn(); n_Delete(&n,coeffs_BIGINT); } Print("SIZEOF_LONG=%d\n",SIZEOF_LONG); return FALSE; } else #endif /*==================== n_SwitchChinRem =================*/ if(strcmp(sys_cmd,"cache_chinrem")==0) { extern int n_SwitchChinRem; Print("caching inverse in chines remainder:%d\n",n_SwitchChinRem); if ((h!=NULL)&&(h->Typ()==INT_CMD)) n_SwitchChinRem=(int)(long)h->Data(); return FALSE; } else /*==================== LU for bigintmat =================*/ #ifdef SINGULAR_4_1 if(strcmp(sys_cmd,"LU")==0) { if ((h!=NULL) && (h->Typ()==CMATRIX_CMD)) { // get the argument: bigintmat *b=(bigintmat *)h->Data(); // just for tests: simply transpose bigintmat *bb=b->transpose(); // return the result: res->rtyp=CMATRIX_CMD; res->data=(char*)bb; return FALSE; } else { WerrorS("system(\"LU\",) expected"); return TRUE; } } else #endif /*==================== Error =================*/ Werror( "(extended) system(\"%s\",...) %s", sys_cmd, feNotImplemented ); } return TRUE; } #endif // HAVE_EXTENDED_SYSTEM singular-4.0.3+ds/Singular/feOpt.cc000066400000000000000000000223731266270727000171340ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: Implementation of option buisness */ #include #include #include #include #define FE_OPT_STRUCTURE #include "feOpt.h" #if !defined(GENERATE_OPTION_INDEX) && !defined(ESINGULAR) && !defined(TSINGULAR) #include #include #endif #include "fehelp.h" const char SHORT_OPTS_STRING[] = "bdhpqstvxec:r:u:"; ////////////////////////////////////////////////////////////// // // Generation of feOptIndex // #ifdef GENERATE_OPTION_INDEX #include #include #include int main() { FILE* fd; #ifdef ESINGULAR fd = fopen("feOptES.xx", "w"); #elif defined(TSINGULAR) fd = fopen("feOptTS.xx", "w"); #else fd = fopen("feOpt.xx", "w"); #endif if (fd == NULL) exit(1); int i = 0; fputs("typedef enum\n{\n", fd); while (feOptSpec[i].name != NULL) { const char* name = feOptSpec[i].name; fputs("FE_OPT_", fd); while (*name != 0) { if (*name == '-') { putc('_', fd); } else if (*name >= 97 && *name <= 122) { putc(*name - 32, fd); } else { putc(*name, fd); } name++; } if (i == 0) { fputs("=0", fd); } i++; fputs(",\n ", fd); } fprintf(fd, "FE_OPT_UNDEF\n} feOptIndex;\n"); fclose(fd); #ifdef ESINGULAR rename("feOptES.xx", "feOptES.inc"); #elif defined(TSINGULAR) rename("feOptTS.xx", "feOptTS.inc"); #else rename("feOpt.xx", "feOpt.inc"); #endif return(0); } #else // ! GENERATE_OPTION_INDEX /////////////////////////////////////////////////////////////// // // Getting Values // feOptIndex feGetOptIndex(const char* name) { int opt = 0; while (opt != (int) FE_OPT_UNDEF) { if (strcmp(feOptSpec[opt].name, name) == 0) return (feOptIndex) opt; opt = opt + 1; } return FE_OPT_UNDEF; } feOptIndex feGetOptIndex(int optc) { int opt = 0; if (optc == LONG_OPTION_RETURN) return FE_OPT_UNDEF; while (opt != (int) FE_OPT_UNDEF) { if (feOptSpec[opt].val == optc) return (feOptIndex) opt; opt = opt + 1; } return FE_OPT_UNDEF; } /////////////////////////////////////////////////////////////// // // Setting Values // // // Return: NULL -- everything ok // "error-string" on error #if !defined(ESINGULAR) && !defined(TSINGULAR) #include #include #include #include #include "ipshell.h" #include "tok.h" #include "sdb.h" #include "cntrlc.h" #include static const char* feOptAction(feOptIndex opt); const char* feSetOptValue(feOptIndex opt, char* optarg) { if (opt == FE_OPT_UNDEF) return "option undefined"; if (feOptSpec[opt].type != feOptUntyped) { if (feOptSpec[opt].type != feOptString) { if (optarg != NULL) { errno = 0; feOptSpec[opt].value = (void*) strtol(optarg, NULL, 10); if (errno) return "invalid integer argument"; } else { feOptSpec[opt].value = (void*) 0; } } else { assume(feOptSpec[opt].type == feOptString); if (feOptSpec[opt].set && feOptSpec[opt].value != NULL) omFree(feOptSpec[opt].value); if (optarg != NULL) feOptSpec[opt].value = omStrDup(optarg); else feOptSpec[opt].value = NULL; feOptSpec[opt].set = 1; } } return feOptAction(opt); } const char* feSetOptValue(feOptIndex opt, int optarg) { if (opt == FE_OPT_UNDEF) return "option undefined"; if (feOptSpec[opt].type != feOptUntyped) { if (feOptSpec[opt].type == feOptString) return "option value needs to be an integer"; feOptSpec[opt].value = (void*)(long) optarg; } return feOptAction(opt); } static const char* feOptAction(feOptIndex opt) { // do some special actions switch(opt) { case FE_OPT_BATCH: if (feOptSpec[FE_OPT_BATCH].value) fe_fgets_stdin=fe_fgets_dummy; return NULL; case FE_OPT_HELP: feOptHelp(feArgv0); return NULL; case FE_OPT_PROFILE: traceit=1024; return NULL; case FE_OPT_QUIET: if (feOptSpec[FE_OPT_QUIET].value) si_opt_2 &= ~(Sy_bit(0)|Sy_bit(V_LOAD_LIB)); else si_opt_2 |= Sy_bit(V_LOAD_LIB)|Sy_bit(0); return NULL; case FE_OPT_NO_TTY: #if defined(HAVE_FEREAD) || defined(HAVE_READLINE) if (feOptSpec[FE_OPT_NO_TTY].value) fe_fgets_stdin=fe_fgets; #endif return NULL; case FE_OPT_SDB: #ifdef HAVE_SDB if (feOptSpec[FE_OPT_SDB].value) sdb_flags = 1; else sdb_flags = 0; #endif return NULL; case FE_OPT_VERSION: { char *s=versionString(); printf("%s",s); omFree(s); return NULL; } case FE_OPT_ECHO: si_echo = (int) ((long)(feOptSpec[FE_OPT_ECHO].value)); if (si_echo < 0 || si_echo > 9) return "argument of option is not in valid range 0..9"; return NULL; case FE_OPT_RANDOM: siRandomStart = (unsigned int) ((unsigned long) (feOptSpec[FE_OPT_RANDOM].value)); siSeed=siRandomStart; factoryseed(siRandomStart); return NULL; case FE_OPT_EMACS: if (feOptSpec[FE_OPT_EMACS].value) { // print EmacsDir and InfoFile so that Emacs // mode can pcik it up Warn("EmacsDir: %s", (feResource('e' /*"EmacsDir"*/) != NULL ? feResource('e' /*"EmacsDir"*/) : "")); Warn("InfoFile: %s", (feResource('i' /*"InfoFile"*/) != NULL ? feResource('i' /*"InfoFile"*/) : "")); } return NULL; case FE_OPT_NO_WARN: if (feOptSpec[FE_OPT_NO_WARN].value) feWarn = FALSE; else feWarn = TRUE; return NULL; case FE_OPT_NO_OUT: if (feOptSpec[FE_OPT_NO_OUT].value) feOut = FALSE; else feOut = TRUE; return NULL; case FE_OPT_MIN_TIME: { double mintime = atof((char*) feOptSpec[FE_OPT_MIN_TIME].value); if (mintime <= 0) return "invalid float argument"; SetMinDisplayTime(mintime); return NULL; } case FE_OPT_BROWSER: feHelpBrowser((char*) feOptSpec[FE_OPT_BROWSER].value, 1); case FE_OPT_TICKS_PER_SEC: { int ticks = (int) ((long)(feOptSpec[FE_OPT_TICKS_PER_SEC].value)); if (ticks <= 0) return "integer argument must be larger than 0"; SetTimerResolution(ticks); return NULL; } case FE_OPT_DUMP_VERSIONTUPLE: { feOptDumpVersionTuple(); return NULL; } default: return NULL; } } // Prints usage message void fePrintOptValues() { int i = 0; while (feOptSpec[i].name != 0) { if (feOptSpec[i].help != NULL && feOptSpec[i].type != feOptUntyped #ifndef SING_NDEBUG && *(feOptSpec[i].help) != '/' #endif ) { if (feOptSpec[i].type == feOptString) { if (feOptSpec[i].value == NULL) { Print("// --%-15s\n", feOptSpec[i].name); } else { Print("// --%-15s \"%s\"\n", feOptSpec[i].name, (char*) feOptSpec[i].value); } } else { Print("// --%-15s %d\n", feOptSpec[i].name, (int)(long)feOptSpec[i].value); } } i++; } } #endif // ! ESingular // Prints help message void feOptHelp(const char* name) { int i = 0; char tmp[20]; #if defined(ESINGULAR) printf("ESingular starts up Singular within emacs;\n"); #elif defined(TSINGULAR) printf("TSingular starts up Singular within a terminal window;\n"); #endif printf("Singular is a Computer Algebra System (CAS) for Polynomial Computations.\n"); printf("Usage: %s [options] [file1 [file2 ...]]\n", name); printf("Options:\n"); while (feOptSpec[i].name != 0) { if (feOptSpec[i].help != NULL #ifdef SING_NDEBUG && *(feOptSpec[i].help) != '/' #endif ) { if (feOptSpec[i].has_arg > 0) { if (feOptSpec[i].has_arg > 1) sprintf(tmp, "%s[=%s]", feOptSpec[i].name, feOptSpec[i].arg_name); else sprintf(tmp, "%s=%s", feOptSpec[i].name, feOptSpec[i].arg_name); printf(" %c%c --%-20s %s\n", (feOptSpec[i].val != LONG_OPTION_RETURN ? '-' : ' '), (feOptSpec[i].val != LONG_OPTION_RETURN ? feOptSpec[i].val : ' '), tmp, feOptSpec[i].help); } else { printf(" %c%c --%-20s %s\n", (feOptSpec[i].val != LONG_OPTION_RETURN ? '-' : ' '), (feOptSpec[i].val != LONG_OPTION_RETURN ? feOptSpec[i].val : ' '), feOptSpec[i].name, feOptSpec[i].help); } } i++; } printf("\nFor more information, type `help;' from within Singular or visit\n"); printf("http://www.singular.uni-kl.de or consult the\n"); printf("Singular manual (available as on-line info or html manual).\n"); } void feOptDumpVersionTuple(void) { printf("%s\n",VERSION); } #endif // GENERATE_OPTION_INDEX singular-4.0.3+ds/Singular/feOpt.h000066400000000000000000000034541266270727000167750ustar00rootroot00000000000000#ifndef FEOPTS_H #define FEOPTS_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: Declarations for working with Options */ #include #include extern const char SHORT_OPTS_STRING[]; /* specifies format of options */ extern struct fe_option feOptSpec[]; /* provides feOptIndex enum type for fast accesses to feOptSpec */ #if ! defined(GENERATE_DEPEND) # ifdef ESINGULAR # include # elif defined(TSINGULAR) # include # else # include # endif #else typedef enum {FE_OPT_UNDEF} feOptIndex; #endif void feOptHelp(const char* name); void feOptDumpVersionTuple(void); #ifdef __cplusplus static inline void* feOptValue(feOptIndex opt) { return feOptSpec[(int)opt].value; } inline int feOptValue(feOptIndex opt, char** val) { if (opt != FE_OPT_UNDEF && feOptSpec[(int)opt].type == feOptString) { *val = (char*) feOptSpec[(int)opt].value; return TRUE; } *val = NULL; return FALSE; } inline int feOptValue(feOptIndex opt, int* val) { if (opt != FE_OPT_UNDEF && feOptSpec[(int)opt].type != feOptString) { *val = (int) ((long)(feOptSpec[(int)opt].value)); return TRUE; } *val = 0; return FALSE; } // maps name to otions feOptIndex feGetOptIndex(const char* name); feOptIndex feGetOptIndex(int optc); // Setting option values: // Return: NULL -- everything ok // "error-string" on error // opt->type must be feOptInt or feOptBool const char* feSetOptValue(feOptIndex opt, int optarg); // for opt->type != feOptString, optarg is converted // to an int const char* feSetOptValue(feOptIndex opt, char* optarg); void fePrintOptValues(); #endif /* __cplusplus */ #endif /* FEOPTS_H */ singular-4.0.3+ds/Singular/feOptGen.cc000066400000000000000000000027071266270727000175650ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: Implementation of option business */ #include #include #include #define FE_OPT_STRUCTURE #include "feOptGen.h" #include "fehelp.h" const char SHORT_OPTS_STRING[] = "bdhqstvxec:r:u:"; ////////////////////////////////////////////////////////////// // // Generation of feOptIndex // #include #include #include int main() { FILE* fd; #ifdef ESINGULAR fd = fopen("feOptES.xx", "w"); #elif defined(TSINGULAR) fd = fopen("feOptTS.xx", "w"); #else fd = fopen("feOpt.xx", "w"); #endif if (fd == NULL) exit(1); int i = 0; fputs("typedef enum\n{\n", fd); while (feOptSpec[i].name != NULL) { const char* name = feOptSpec[i].name; fputs("FE_OPT_", fd); while (*name != 0) { if (*name == '-') { putc('_', fd); } else if (*name >= 97 && *name <= 122) { putc(*name - 32, fd); } else { putc(*name, fd); } name++; } if (i == 0) { fputs("=0", fd); } i++; fputs(",\n ", fd); } fprintf(fd, "FE_OPT_UNDEF\n} feOptIndex;\n"); fclose(fd); #ifdef ESINGULAR rename("feOptES.xx", "feOptES.inc"); #elif defined(TSINGULAR) rename("feOptTS.xx", "feOptTS.inc"); #else rename("feOpt.xx", "feOpt.inc"); #endif return(0); } singular-4.0.3+ds/Singular/feOptGen.h000066400000000000000000000006121266270727000174200ustar00rootroot00000000000000#ifndef FEOPTSGEN_H #define FEOPTSGEN_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: Declarations for working with Options */ #include extern const char SHORT_OPTS_STRING[]; #include typedef enum {FE_OPT_UNDEF} feOptIndex; #endif /* FEOPTSGEN_H */ singular-4.0.3+ds/Singular/feOptTab.h000066400000000000000000000156761266270727000174350ustar00rootroot00000000000000#ifndef FE_OPT_TAB_H #define FE_OPT_TAB_H #define LONG_OPTION_RETURN 13 // Define here which cmd-line options are recognized #ifndef FE_OPT_STRUCTURE extern struct fe_option feOptSpec[]; #else struct fe_option feOptSpec[] = { // // Has to be of the form // {name, has_arg, val, // arg_name, help, type, value, set} // where: // // name is the name of the long option. // // has_arg // is: no_argument (or 0) if the option does not take // an argument, required_argument (or 1) if the option // requires an argument, or optional_argument (or 2) // if the option takes an optional argument. // // val is the value to return, or to load into the // variable pointed to by flag. // NEEDS TO BE LONG_OPTION_RETURN, for long option // short option char, for short option // // arg_name if set, uses this value as name for argument in // display of help // // help one-line description of option // // type one of feOptUntyped (value is never set), // feOptBool, feOptInt, feOptString // // value (default) value of option // // set only relevant for feOptString: // 1: if value different from default value // 0: otherwise // // The order in which options are specified is the order in which // their help is printed on -h // // Options whose hel starts with an "//" are considered undocumented, // i.e., their help is not printed on -h // #if defined(ESINGULAR) || defined(TSINGULAR) #ifdef ESINGULAR // options only relevant for ESINGULAR {"emacs", required_argument, LONG_OPTION_RETURN, "EMACS", "Use EMACS as emacs program to run Singular", feOptString, 0, 0}, {"emacs-dir", required_argument, LONG_OPTION_RETURN, "DIR", "Use DIR as directory to look for emacs lisp files", feOptString, 0, 0}, {"emacs-load", required_argument, LONG_OPTION_RETURN, "FILE", "Load FILE on emacs start-up, instead of default", feOptString, 0, 0}, #else {"xterm", required_argument, LONG_OPTION_RETURN, "XTERM", "Use XTERM as terminal program to run Singular", feOptString, 0, 0}, #endif {"singular", required_argument, LONG_OPTION_RETURN, "PROG", "Start PROG as Singular program within emacs", feOptString, 0, 0}, {"no-call", no_argument, LONG_OPTION_RETURN, 0, "Do not start program. Print call to stdout", feOptBool, 0, 0}, #endif {"batch", no_argument, 'b', 0, "Run in batch mode", feOptBool, 0, 0}, {"execute", required_argument, 'c', "STRING", "Execute STRING on start-up", feOptString, 0, 0}, {"sdb", no_argument, 'd', 0, "Enable source code debugger (experimental)", feOptBool, 0, 0}, {"echo", optional_argument, 'e', "VAL", "Set value of variable `echo' to (integer) VAL", feOptInt, 0, 0}, {"help", no_argument, 'h', 0, "Print help message and exit", feOptUntyped, 0, 0}, {"profile", no_argument, 'p', 0, "Collect profiling data in smon.out", feOptBool, 0, 0}, {"quiet", no_argument, 'q', 0, "Do not print start-up banner and lib load messages", feOptBool, 0, 0}, {"sort", no_argument, 's', 0, "// Sort NTL results", feOptBool, 0, 0}, {"random", required_argument, 'r', "SEED", "Seed random generator with (integer) SEED", feOptInt, 0, 0}, {"no-tty", no_argument, 't', 0, "Do not redefine the terminal characteristics", feOptBool, 0, 0}, {"user-option", required_argument, 'u', "STRING", "Return STRING on `system(\"--user-option\")'", feOptString, 0, 0}, {"version", no_argument, 'v', 0, "Print extended version and configuration info", feOptUntyped, 0, 0}, {"allow-net", no_argument, LONG_OPTION_RETURN, 0, "Allow one to fetch (html) help pages from the net", feOptBool, 0, 0}, {"browser", required_argument, LONG_OPTION_RETURN, "BROWSER", "Display help in BROWSER (see help.cnf)", feOptString, 0, 0}, {"cntrlc", optional_argument, LONG_OPTION_RETURN, "CHAR", "Automatic answer for CTRL-C prompt", feOptString, 0, 0}, #ifndef ESINGULAR {"emacs", no_argument, LONG_OPTION_RETURN, 0, "Set defaults for running within emacs", feOptBool, 0, 0}, #endif {"no-stdlib", no_argument, LONG_OPTION_RETURN, 0, "Do not load `standard.lib' on start-up", feOptBool, 0, 0}, {"no-rc", no_argument, LONG_OPTION_RETURN, 0, "Do not execute `.singularrc' file(s) on start-up", feOptBool, 0, 0}, {"no-warn", no_argument, LONG_OPTION_RETURN, 0, "Do not display warning messages", feOptBool, 0, 0}, {"no-out", no_argument, LONG_OPTION_RETURN, 0, "Suppress all output", feOptBool, 0, 0}, {"no-shell", no_argument, LONG_OPTION_RETURN, 0, "Restricted mode: prohibit shell escape commands and links", feOptBool, 0, 0}, {"min-time", required_argument, LONG_OPTION_RETURN, "SECS", "Do not display times smaller than SECS (in seconds)", feOptString, (void*) "0.5", 0}, {"cpus", required_argument, LONG_OPTION_RETURN, "#CPUs", "maximal number of CPUs to use", feOptInt, (void*)2, 0}, {"MPport", required_argument, LONG_OPTION_RETURN, "PORT", "Use PORT number for conections", feOptString, 0, 0}, {"MPhost", required_argument, LONG_OPTION_RETURN, "HOST", "Use HOST for connections", feOptString, 0, 0}, {"link", required_argument, LONG_OPTION_RETURN, "LINK", "Use LINK for connections", feOptString, 0, 0}, {"ticks-per-sec", required_argument, LONG_OPTION_RETURN, "TICKS", "Sets unit of timer to TICKS per second", feOptInt, (void*)1, 0}, {"dump-versiontuple", no_argument, LONG_OPTION_RETURN, 0, "//Display the version-tuple and exit", feOptUntyped, 0, 0}, // terminator -- do NOT remove { 0, 0, 0, 0, 0, feOptInt, 0, 0} }; #endif #endif singular-4.0.3+ds/Singular/febase.cc000066400000000000000000000031651266270727000173020ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: i/o system */ #include /* I need myfread in standalone_parser */ #ifndef STANDALONE_PARSER #include #include #include //#include #include #include #include #include #include #include #include #ifdef HAVE_PWD_H #include #endif #define fePutChar(c) fputc((unsigned char)(c),stdout) /*0 implementation */ // char fe_promptstr[] =" "; // output/print buffer: // line buffer for reading: // minimal value for MAX_FILE_BUFFER: 4*4096 - see Tst/Long/gcd0_l.tst // this is an upper limit for the size of monomials/numbers read via the interpreter #define MAX_FILE_BUFFER 4*4096 int si_echo = 0; int printlevel = 0; int colmax = 80; char prompt_char = '>'; /*1 either '>' or '.'*/ int yylineno = 0; int myynest = -1; int traceit = 0; char my_yylinebuf[80]; #if 0 void monitor(char* s, int mode) { if (feProt) { fclose(feProtFile); feProt = 0; } if ((s!=NULL) && (*s!='\0')) { feProtFile = myfopen(s,"w"); if (feProtFile==NULL) { Werror("cannot open %s",s); feProt=0; } else feProt = mode; } } #else void monitor(void *F, int mode) { if (feProt) { fclose(feProtFile); feProt = 0; } if (F!=NULL) { feProtFile = (FILE *)F; feProt = mode; } } #endif #else /* ! STANDALONE_PARSER */ #include #endif singular-4.0.3+ds/Singular/fegetopt.c000066400000000000000000000575711266270727000175410ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* obachman 9/99: adapted to Singular by * adding prefix fe_ to global variables * extended fe_option structure */ #include #ifndef __STDC__ # ifndef const # define const # endif #endif /* This tells Alpha OSF/1 not to define a getopt prototype in . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #include /* #include "tailor.h" */ /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #endif /* GNU C library. */ /* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a long-named option. Because this is not POSIX.2 compliant, it is being phased out. */ /* #define GETOPT_COMPAT */ /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *fe_optarg = 0; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `fe_optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* XXX 1003.2 says this must be 1 before any call. */ int fe_optind = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int fe_opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ #define BAD_OPTION '\0' int fe_optopt = BAD_OPTION; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return EOF with `fe_optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #define my_strlen strlen #else /* Avoid depending on library functions or files whose names are inconsistent. */ #if __STDC__ || defined(PROTO) extern char *getenv(const char *name); extern int strcmp (const char *s1, const char *s2); extern int strncmp(const char *s1, const char *s2, size_t n); static int my_strlen(const char *s); static const char *my_index (const char *str, int chr); #else extern char *getenv (); #endif static int my_strlen (const char *str) { int n = 0; while (*str++) n++; return n; } static const char * my_index (const char *str, int chr) { while (*str) { if (*str == chr) return (const char *) str; str++; } return 0; } #endif /* GNU C library. */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,fe_optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. To perform the swap, we first reverse the order of all elements. So all options now come before all non options, but they are in the wrong order. So we put back the options and non options in original order by reversing them again. For example: original input: a b c -x -y reverse all: -y -x c b a reverse options: -x -y c b a reverse non options: -x -y a b c */ #if __STDC__ || defined(PROTO) static void exchange (char **argv); #endif static void exchange (char **argv) { char *temp, **first, **last; /* Reverse all the elements [first_nonopt, fe_optind) */ first = &argv[first_nonopt]; last = &argv[fe_optind-1]; while (first < last) { temp = *first; *first = *last; *last = temp; first++; last--; } /* Put back the options in order */ first = &argv[first_nonopt]; first_nonopt += (fe_optind - last_nonopt); last = &argv[first_nonopt - 1]; while (first < last) { temp = *first; *first = *last; *last = temp; first++; last--; } /* Put back the non options in order */ first = &argv[first_nonopt]; last_nonopt = fe_optind; last = &argv[last_nonopt-1]; while (first < last) { temp = *first; *first = *last; *last = temp; first++; last--; } } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `fe_optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns `EOF'. Then `fe_optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return BAD_OPTION after printing an error message. If you set `fe_opterr' to zero, the error message is suppressed but we still return BAD_OPTION. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `fe_optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `fe_optarg', otherwise `fe_optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns the value of the option's `val' field. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct fe_option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _fe_getopt_internal ( int argc, char *const *argv, const char *optstring, const struct fe_option *longopts, int *longind, int long_only) { int option_index; fe_optarg = 0; /* Initialize the internal data when the first call is made. Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ if (fe_optind == 0) { first_nonopt = last_nonopt = fe_optind = 1; nextchar = NULL; /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (getenv ("POSIXLY_CORRECT") != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; } if (nextchar == NULL || *nextchar == '\0') { if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != fe_optind) exchange ((char **) argv); else if (last_nonopt != fe_optind) first_nonopt = fe_optind; /* Now skip any additional non-options and extend the range of non-options previously skipped. */ while (fe_optind < argc && (argv[fe_optind][0] != '-' || argv[fe_optind][1] == '\0') #ifdef GETOPT_COMPAT && (longopts == NULL || argv[fe_optind][0] != '+' || argv[fe_optind][1] == '\0') #endif /* GETOPT_COMPAT */ ) fe_optind++; last_nonopt = fe_optind; } /* Special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (fe_optind != argc && !strcmp (argv[fe_optind], "--")) { fe_optind++; if (first_nonopt != last_nonopt && last_nonopt != fe_optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = fe_optind; last_nonopt = argc; fe_optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (fe_optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) fe_optind = first_nonopt; return EOF; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if ((argv[fe_optind][0] != '-' || argv[fe_optind][1] == '\0') #ifdef GETOPT_COMPAT && (longopts == NULL || argv[fe_optind][0] != '+' || argv[fe_optind][1] == '\0') #endif /* GETOPT_COMPAT */ ) { if (ordering == REQUIRE_ORDER) return EOF; fe_optarg = argv[fe_optind++]; return 1; } /* We have found another option-ARGV-element. Start decoding its characters. */ nextchar = (argv[fe_optind] + 1 + (longopts != NULL && argv[fe_optind][1] == '-')); } if (longopts != NULL && ((argv[fe_optind][0] == '-' && (argv[fe_optind][1] == '-' || long_only)) #ifdef GETOPT_COMPAT || argv[fe_optind][0] == '+' #endif /* GETOPT_COMPAT */ )) { const struct fe_option *p; char *s = nextchar; int exact = 0; int ambig = 0; const struct fe_option *pfound = NULL; int indfound = 0; while (*s && *s != '=') s++; /* Test all options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, s - nextchar)) { if (s - nextchar == my_strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (fe_opterr) fprintf (stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[fe_optind]); nextchar += my_strlen (nextchar); fe_optind++; return BAD_OPTION; } if (pfound != NULL) { option_index = indfound; fe_optind++; if (*s) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) fe_optarg = s + 1; else { if (fe_opterr) { if (argv[fe_optind - 1][1] == '-') /* --option */ fprintf (stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[fe_optind - 1][0], pfound->name); } nextchar += my_strlen (nextchar); return BAD_OPTION; } } else if (pfound->has_arg == 1) { if (fe_optind < argc) fe_optarg = argv[fe_optind++]; else { if (fe_opterr) fprintf (stderr, "%s: option `%s' requires an argument\n", argv[0], argv[fe_optind - 1]); nextchar += my_strlen (nextchar); return optstring[0] == ':' ? ':' : BAD_OPTION; } } nextchar += my_strlen (nextchar); if (longind != NULL) *longind = option_index; return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[fe_optind][1] == '-' #ifdef GETOPT_COMPAT || argv[fe_optind][0] == '+' #endif /* GETOPT_COMPAT */ || my_index (optstring, *nextchar) == NULL) { if (fe_opterr) { if (argv[fe_optind][1] == '-') /* --option */ fprintf (stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar); else /* +option or -option */ fprintf (stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[fe_optind][0], nextchar); } nextchar = (char *) ""; fe_optind++; return BAD_OPTION; } } /* Look at and handle the next option-character. */ { char c = *nextchar++; const char *temp = my_index (optstring, c); /* Increment `fe_optind' when we start to process its last character. */ if (*nextchar == '\0') ++fe_optind; if (temp == NULL || c == ':') { if (fe_opterr) { #if 0 if (c < 040 || c >= 0177) fprintf (stderr, "%s: unrecognized option, character code 0%o\n", argv[0], c); else fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); #else /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); #endif } fe_optopt = c; return BAD_OPTION; } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { fe_optarg = nextchar; fe_optind++; } else fe_optarg = 0; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { fe_optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ fe_optind++; } else if (fe_optind == argc) { if (fe_opterr) { #if 0 fprintf (stderr, "%s: option `-%c' requires an argument\n", argv[0], c); #else /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], c); #endif } fe_optopt = c; if (optstring[0] == ':') c = ':'; else c = BAD_OPTION; } else /* We already incremented `fe_optind' once; increment it again when taking next ARGV-elt as argument. */ fe_optarg = argv[fe_optind++]; nextchar = NULL; } } return c; } } int fe_getopt ( int argc, char *const *argv, const char *optstring) { return _fe_getopt_internal (argc, argv, optstring, (const struct fe_option *) 0, (int *) 0, 0); } int fe_getopt_long ( int argc, char *const *argv, const char *options, const struct fe_option *long_options, int *opt_index) { return _fe_getopt_internal (argc, argv, options, long_options, opt_index, 0); } int fe_getopt_long_only ( int argc, char *const *argv, const char *options, const struct fe_option *long_options, int *opt_index) { return _fe_getopt_internal (argc, argv, options, long_options, opt_index, 1); } #ifdef TEST_GETOPT /* Compile with -DTEST_GETOPT to make an executable for use in testing the above definition of `getopt'. */ int main (int argc, char **argv) { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = fe_getopt (argc, argv, "abc:d:0123456789"); if (c == EOF) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", fe_optarg); break; case BAD_OPTION: break; default: printf ("?? fe_getopt returned character code 0%o ??\n", c); } } if (fe_optind < argc) { printf ("non-option ARGV-elements: "); while (fe_optind < argc) printf ("%s ", argv[fe_optind++]); printf ("\n"); } exit (0); } #endif /* TEST_GETOPT */ singular-4.0.3+ds/Singular/fegetopt.h000066400000000000000000000110661266270727000175330ustar00rootroot00000000000000/* Declarations for getopt. Copyright (C) 1989, 1990, 1991, 1992, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* obachman 9/99: adapted to Singular by * adding prefix fe_ to global variables * extended fe_option structure */ #ifndef FEGETOPT_H #define FEGETOPT_H 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *fe_optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int fe_optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int fe_opterr; /* Set to an option character which was unrecognized. */ extern int fe_optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options `getopt' returns the contents of the `val' field. */ typedef enum {feOptUntyped, feOptBool, feOptInt, feOptString} feOptType; struct fe_option { #if __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int val; /* Stuff added for Singular */ const char* arg_name;/* name of argument, for display in help */ const char* help; /* (short) help string */ feOptType type; /* type of argument, if has_arg > 0 */ void* value; /* (default) value of option */ int set; /* only relevant for strings: 0 if not set, 1 if set */ }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if defined(__STDC__) || defined(PROTO) || defined(__cplusplus) extern int fe_getopt (int argc, char *const *argv, const char *shortopts); extern int fe_getopt_long (int argc, char *const *argv, const char *shortopts, const struct fe_option *longopts, int *longind); extern int fe_getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct fe_option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _fe_getopt_internal (int argc, char *const *argv, const char *shortopts, const struct fe_option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int fe_getopt (); extern int fe_getopt_long (); extern int fe_getopt_long_only (); extern int _fe_getopt_internal (); #endif /* not __STDC__ */ #ifdef __cplusplus } #endif #endif /* _GETOPT_H */ singular-4.0.3+ds/Singular/fehelp.cc000066400000000000000000000736621266270727000173310ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: help system */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipid.h" #include "ipshell.h" #include "libparse.h" #include "feOpt.h" #include "tok.h" #include "fehelp.h" /***************************************************************** * * Declarations: Data structures * *****************************************************************/ #define MAX_HE_ENTRY_LENGTH 160 typedef struct { char key[MAX_HE_ENTRY_LENGTH]; char node[MAX_HE_ENTRY_LENGTH]; char url[MAX_HE_ENTRY_LENGTH]; long chksum; } heEntry_s; typedef heEntry_s * heEntry; typedef void (*heBrowserHelpProc)(heEntry hentry, int br); typedef BOOLEAN (*heBrowserInitProc)(int warn, int br); typedef struct { const char* browser; heBrowserInitProc init_proc; heBrowserHelpProc help_proc; const char* required; const char* action; } heBrowser_s; typedef heBrowser_s * heBrowser; /***************************************************************** * * Declarations: Local functions * *****************************************************************/ static char* strclean(char* str); static BOOLEAN heKey2Entry(char* filename, char* key, heEntry hentry); static int heReKey2Entry (char* filename, char* key, heEntry hentry); static BOOLEAN strmatch(char* s, char* re); static BOOLEAN heOnlineHelp(char* s); static void heBrowserHelp(heEntry hentry); static long heKeyChksum(char* key); // browser functions static BOOLEAN heGenInit(int,int); static void heGenHelp(heEntry hentry,int); static void heBuiltinHelp(heEntry hentry,int); static BOOLEAN heDummyInit(int,int); static void heDummyHelp(heEntry hentry,int); static BOOLEAN heEmacsInit(int,int); static void heEmacsHelp(heEntry hentry,int); static heBrowser heCurrentHelpBrowser = NULL; static int heCurrentHelpBrowserIndex= -1; /***************************************************************** * * Definition: available help browsers * *****************************************************************/ // order is important -- first possible help is chosen // moved to LIB/help.cnf static heBrowser_s *heHelpBrowsers=NULL; /***************************************************************** * * Implementation: public function * *****************************************************************/ void feHelp(char *str) { str = strclean(str); if (str == NULL) {heBrowserHelp(NULL); return;} if (strlen(str) > MAX_HE_ENTRY_LENGTH - 2) // need room for extra ** str[MAX_HE_ENTRY_LENGTH - 3] = '\0'; BOOLEAN key_is_regexp = (strchr(str, '*') != NULL); // try proc help and library help if (! key_is_regexp && heOnlineHelp(str)) return; heEntry_s hentry; memset(&hentry,0,sizeof(hentry)); char* idxfile = feResource('x' /*"IdxFile"*/); // Try exact match of help string with key in index if (!key_is_regexp && (idxfile != NULL) && heKey2Entry(idxfile, str, &hentry)) { heBrowserHelp(&hentry); return; } // Try to match approximately with key in index file if (idxfile != NULL) { if (heCurrentHelpBrowser == NULL) feHelpBrowser(NULL, 0); assume(heCurrentHelpBrowser != NULL); StringSetS(""); int found = heReKey2Entry(idxfile, str, &hentry); // Try to match with str* if (found == 0) { char mkey[MAX_HE_ENTRY_LENGTH]; strcpy(mkey, str); strcat(mkey, "*"); found = heReKey2Entry(idxfile, mkey, &hentry); // Try to match with *str* if (found == 0) { mkey[0] = '*'; strcpy(mkey + 1, str); strcat(mkey, "*"); found = heReKey2Entry(idxfile, mkey, &hentry); } // Print warning and return if nothing found if (found == 0) { Warn("No help for topic '%s' (not even for '*%s*')", str, str); WarnS("Try '?;' for general help"); WarnS("or '?Index;' for all available help topics."); return; } } // do help if unique match was found if (found == 1) { heBrowserHelp(&hentry); return; } // Print warning about multiple matches and return if (key_is_regexp) Warn("No unique help for '%s'", str); else Warn("No help for topic '%s'", str); Warn("Try one of"); char *matches=StringEndS(); PrintS(matches); omFree(matches); PrintLn(); return; } // no idx file, let Browsers deal with it, if they can strcpy(hentry.key, str); *hentry.node = '\0'; *hentry.url = '\0'; hentry.chksum = 0; heBrowserHelp(&hentry); } static void feBrowserFile() { FILE *f=feFopen("help.cnf","r",NULL,TRUE); int br=0; if (f!=NULL) { char buf[512]; while (fgets( buf, sizeof(buf), f)) { if ((buf[0]!='#') && (buf[0]>' ')) br++; } fseek(f,0,SEEK_SET); // for the 4(!) default browsers heHelpBrowsers=(heBrowser_s*)omAlloc0((br+4)*sizeof(heBrowser_s)); br = 0; while (fgets( buf, sizeof(buf), f)) { if ((buf[0]!='#') && (buf[0]>' ')) { char *name=strtok(buf,"!"); char *req=strtok(NULL,"!"); char *cmd=strtok(NULL,"!"); if ((name!=NULL) && (req!=NULL) && (cmd!=NULL)) { while ((cmd[0]!='\0') && (cmd[strlen(cmd)-1]<=' ')) cmd[strlen(cmd)-1]='\0'; //Print("name %d >>%s<<\n\treq:>>%s<<\n\tcmd:>>%s<<\n",br,name,req,cmd); heHelpBrowsers[br].browser=(char *)omStrDup(name); heHelpBrowsers[br].init_proc=heGenInit; heHelpBrowsers[br].help_proc=heGenHelp; heHelpBrowsers[br].required=omStrDup(req); heHelpBrowsers[br].action=omStrDup(cmd); br++; } else { Print("syntax error in help.cnf, at line starting with %s\n",buf); } } } fclose(f); } else { // for the 4(!) default browsers heHelpBrowsers=(heBrowser_s*)omAlloc0(4*sizeof(heBrowser_s)); } heHelpBrowsers[br].browser="builtin"; heHelpBrowsers[br].init_proc=heGenInit; heHelpBrowsers[br].help_proc=heBuiltinHelp; heHelpBrowsers[br].required="i"; //heHelpBrowsers[br].action=NULL; br++; heHelpBrowsers[br].browser="dummy"; heHelpBrowsers[br].init_proc=heDummyInit; heHelpBrowsers[br].help_proc=heDummyHelp; //heHelpBrowsers[br].required=NULL; //heHelpBrowsers[br].action=NULL; br++; heHelpBrowsers[br].browser="emacs"; heHelpBrowsers[br].init_proc=heEmacsInit; heHelpBrowsers[br].help_proc=heEmacsHelp; //heHelpBrowsers[br].required=NULL; //heHelpBrowsers[br].action=NULL; //br++; //heHelpBrowsers[br].browser=NULL; //heHelpBrowsers[br].init_proc=NULL; //heHelpBrowsers[br].help_proc=NULL; //heHelpBrowsers[br].required=NULL; //heHelpBrowsers[br].action=NULL; } const char* feHelpBrowser(char* which, int warn) { int i = 0; // if no argument, choose first available help browser if (heHelpBrowsers==NULL) feBrowserFile(); if (which == NULL || *which == '\0') { // return, if already set if (heCurrentHelpBrowser != NULL) return heCurrentHelpBrowser->browser; // First, try emacs, if emacs-option is set if (feOptValue(FE_OPT_EMACS) != NULL) { while (heHelpBrowsers[i].browser != NULL) { if (strcmp(heHelpBrowsers[i].browser, "emacs") == 0 && (heHelpBrowsers[i].init_proc(0,i))) { heCurrentHelpBrowser = &(heHelpBrowsers[i]); heCurrentHelpBrowserIndex=i; goto Finish; } i++; } i=0; } while (heHelpBrowsers[i].browser != NULL) { if (heHelpBrowsers[i].init_proc(0,i)) { heCurrentHelpBrowser = &(heHelpBrowsers[i]); heCurrentHelpBrowserIndex=i; goto Finish; } i++; } // should never get here dReportBug("should never get here"); } // with argument, find matching help browser while (heHelpBrowsers[i].browser != NULL && strcmp(heHelpBrowsers[i].browser, which) != 0) {i++;} if (heHelpBrowsers[i].browser == NULL) { if (warn) Warn("No help browser '%s' available.", which); } else { // see whether we can init it if (heHelpBrowsers[i].init_proc(warn,i)) { heCurrentHelpBrowser = &(heHelpBrowsers[i]); heCurrentHelpBrowserIndex=i; goto Finish; } } // something went wrong if (heCurrentHelpBrowser == NULL) { feHelpBrowser(); assume(heCurrentHelpBrowser != NULL); if (warn) Warn("Setting help browser to '%s'.", heCurrentHelpBrowser->browser); return heCurrentHelpBrowser->browser; } else { // or, leave as is if (warn) Warn("Help browser stays at '%s'.", heCurrentHelpBrowser->browser); return heCurrentHelpBrowser->browser; } Finish: // update value of Browser Option if (feOptSpec[FE_OPT_BROWSER].value == NULL || strcmp((char*) feOptSpec[FE_OPT_BROWSER].value, heCurrentHelpBrowser->browser) != 0) { omfree(feOptSpec[FE_OPT_BROWSER].value); feOptSpec[FE_OPT_BROWSER].value = (void*) omStrDup(heCurrentHelpBrowser->browser); } return heCurrentHelpBrowser->browser; } void feStringAppendBrowsers(int warn) { int i; StringAppendS("Available HelpBrowsers: "); i = 0; if (heHelpBrowsers==NULL) feBrowserFile(); while (heHelpBrowsers[i].browser != NULL) { if (heHelpBrowsers[i].init_proc(warn,i)) StringAppend("%s, ", heHelpBrowsers[i].browser); i++; } StringAppend("\nCurrent HelpBrowser: %s ", feHelpBrowser()); } /***************************************************************** * * Implementation: local function * *****************************************************************/ // Remove whitspaces from beginning and end, return NULL if only whitespaces static char* strclean(char* str) { if (str == NULL) return NULL; char *s=str; while ((*s <= ' ') && (*s != '\0')) s++; if (*s == '\0') return NULL; char *ss=s; while (*ss!='\0') ss++; ss--; while ((*ss <= ' ') && (*ss != '\0')) { *ss='\0'; ss--; } if (*ss == '\0') return NULL; return s; } // Finds help entry for key: // returns filled-in hentry and TRUE, on success // FALSE, on failure // Assumes that lines of idx file have the following form // key\tnode\turl\tchksum\n (chksum ma be empty, then it is set to -1) // and that lines are sorted alpahbetically w.r.t. index entries static BOOLEAN heKey2Entry(char* filename, char* key, heEntry hentry) { FILE* fd; int c, k; int kl, i; *(hentry->key) = '\0'; *(hentry->url) = '\0'; *(hentry->node) = '\0'; hentry->chksum = 0; if (filename == NULL || key == NULL) return FALSE; fd = fopen(filename, "r"); if (fd == NULL) return FALSE; kl = strlen(key); k = key[0]; i = 0; while ((c = getc(fd)) != EOF) { if (c < k) { /* Skip line */ while (getc(fd) != '\n') {}; if (i) { i=0; k=key[0]; } } else if (c == k) { i++; if (i == kl) { // \t must follow, otherwise only substring match if (getc(fd) != '\t') goto Failure; // Now we found an exact match if (hentry->key != key) strcpy(hentry->key, key); // get node i = 0; while ((c = getc(fd)) != '\t' && c != EOF) { hentry->node[i] = c; i++; } if (c == EOF) goto Failure; if (hentry->node[0]=='\0') strcpy(hentry->node,hentry->key); // get url //hentry->node[i] = '\0'; i = 0; while ((c = getc(fd)) != '\t' && c != EOF) { hentry->url[i] = c; i++; } if (c == EOF) goto Failure; // get chksum hentry->url[i] = '\0'; if (si_fscanf(fd, "%ld\n", &(hentry->chksum)) != 1) { hentry->chksum = -1; } fclose(fd); return TRUE; } else if (i > kl) { goto Failure; } else { k = key[i]; } } else { goto Failure; } } Failure: fclose(fd); return FALSE; } // return TRUE if s matches re // FALSE, otherwise // does not distinguish lower and upper cases // inteprets * as wildcard static BOOLEAN strmatch(char* s, char* re) { if (s == NULL || *s == '\0') return (re == NULL || *re == '\0' || strcmp(re, "*") == 0); if (re == NULL || *re == '\0') return FALSE; int i; char ls[MAX_HE_ENTRY_LENGTH + 1]; char rs[MAX_HE_ENTRY_LENGTH + 1]; char *l, *r, *ll, *rr; // make everything to lower case i=1; ls[0] = '\0'; do { if (*s >= 'A' && *s <= 'Z') ls[i] = *s + ('a' - 'A'); else ls[i] = *s; i++; s++; } while (*s != '\0'); ls[i] = '\0'; l = &(ls[1]); i=1; rs[0] = '\0'; do { if (*re >= 'A' && *re <= 'Z') rs[i]= *re + ('a' - 'A'); else rs[i] = *re; i++; re++; } while (*re != '\0'); rs[i] = '\0'; r = &(rs[1]); // chopp of exact matches from beginning and end while (*r != '*' && *r != '\0' && *l != '\0') { if (*r != *l) return FALSE; *r = '\0'; *s = '\0'; r++; l++; } if (*r == '\0') return (*l == '\0'); if (*r == '*' && r[1] == '\0') return TRUE; if (*l == '\0') return FALSE; rr = &r[strlen(r) - 1]; ll = &l[strlen(l) - 1]; while (*rr != '*' && *rr != '\0' && *ll != '\0') { if (*rr != *ll) return FALSE; *rr = '\0'; *ll = '\0'; rr--; ll--; } if (*rr == '\0') return (*ll == '\0'); if (*rr == '*' && rr[-1] == '\0') return TRUE; if (*ll == '\0') return FALSE; // now *r starts with a * and ends with a * r++; *rr = '\0'; rr--; while (*r != '\0') { rr = r + 1; while (*rr != '*' && *rr != '\0') rr++; if (*rr == '*') { *rr = '\0'; rr++; } l = strstr(l, r); if (l == NULL) return FALSE; r = rr; } return TRUE; } // similar to heKey2Entry, except that // key is taken as regexp (see above) // and number of matches is returned // if number of matches > 0, then hentry contains entry for first match // if number of matches > 1, matches are printed as komma-separated // into global string static int heReKey2Entry (char* filename, char* key, heEntry hentry) { int i = 0; FILE* fd; char index_key[MAX_HE_ENTRY_LENGTH]; if (filename == NULL || key == NULL) return 0; fd = fopen(filename, "r"); if (fd == NULL) return 0; memset(index_key,0,MAX_HE_ENTRY_LENGTH); while (si_fscanf(fd, "%[^\t]\t%*[^\n]\n", index_key) == 1) { if ((index_key[MAX_HE_ENTRY_LENGTH-1]!='\0')) { index_key[MAX_HE_ENTRY_LENGTH-1]='\0'; Werror("index file corrupt at line >>%s<<",index_key); break; } else if (strmatch(index_key, key)) { i++; if (i == 1) { heKey2Entry(filename, index_key, hentry); } else if (i == 2) { StringAppend("?%s; ?%s;", hentry->key, index_key); } else { StringAppend(" ?%s;", index_key); } } } fclose(fd); return i; } // test for h being a string and print it static void hePrintHelpStr(const idhdl hh,const char *id,const char *pa) { if ((hh!=NULL) && (IDTYP(hh)==STRING_CMD)) { PrintS(IDSTRING(hh)); PrintLn(); } else Print("`%s` not found in package %s\n",id,pa); } // try to find the help string as a loaded procedure or library // if found, display the help and return TRUE // otherwise, return FALSE static BOOLEAN heOnlineHelp(char* s) { char *ss; idhdl h; if ((ss=strstr(s,"::"))!=NULL) { *ss='\0'; ss+=2; h=ggetid(s); if (h!=NULL) { Print("help for %s from package %s\n",ss,s); char s_help[200]; strcpy(s_help,ss); strcat(s_help,"_help"); idhdl hh=IDPACKAGE(h)->idroot->get(s_help,0); hePrintHelpStr(hh,s_help,s); return TRUE; } else Print("package %s not found\n",s); return TRUE; /* do not search the manual */ } h=IDROOT->get(s,myynest); // try help for a procedure if (h!=NULL) { if (IDTYP(h)==PROC_CMD) { char *lib=iiGetLibName(IDPROC(h)); if((lib!=NULL)&&(*lib!='\0')) { Print("// proc %s from lib %s\n",s,lib); s=iiGetLibProcBuffer(IDPROC(h), 0); if (s!=NULL) { PrintS(s); omFree((ADDRESS)s); } return TRUE; } } else if (IDTYP(h)==PACKAGE_CMD) { idhdl hh=IDPACKAGE(h)->idroot->get("info",0); hePrintHelpStr(hh,"info",s); return TRUE; } return FALSE; } // try help for a library int ls = strlen(s); char* str = NULL; // check that it ends with "[.,_]lib" if (strlen(s) >=4 && strcmp(&s[ls-3], "lib") == 0) { if (s[ls - 4] == '.') str = s; else { str = omStrDup(s); str[ls - 4] = '.'; } } else { return FALSE; } char libnamebuf[128]; FILE *fp=NULL; // first, search for library of that name if ((str[1]!='\0') && ((iiLocateLib(str, libnamebuf) && (fp=feFopen(libnamebuf, "rb")) !=NULL) || ((fp=feFopen(str,"rb", libnamebuf))!=NULL))) { extern FILE *yylpin; lib_style_types lib_style; // = OLD_LIBSTYLE; yylpin = fp; yylplex(str, libnamebuf, &lib_style, IDROOT, FALSE, GET_INFO); reinit_yylp(); if(lib_style == OLD_LIBSTYLE) { char buf[256]; fseek(fp, 0, SEEK_SET); Warn( "library %s has an old format. Please fix it for the next time", str); if (str != s) omFree(str); BOOLEAN found=FALSE; while (fgets( buf, sizeof(buf), fp)) { if (strncmp(buf,"//",2)==0) { if (found) return TRUE; } else if ((strncmp(buf,"proc ",5)==0)||(strncmp(buf,"LIB ",4)==0)) { if (!found) WarnS("no help part in library found"); return TRUE; } else { found=TRUE; PrintS(buf); } } } else { if (str != s) omFree(str); fclose( yylpin ); PrintS(text_buffer); omFree(text_buffer); text_buffer=NULL; } return TRUE; } if (str != s) omFree(str); return FALSE; } static long heKeyChksum(char* key) { if (key == NULL || *key == '\0') return 0; idhdl h=IDROOT->get(key,myynest); if ((h!=NULL) && (IDTYP(h)==PROC_CMD)) { procinfo *pi = IDPROC(h); if (pi != NULL) return pi->data.s.help_chksum; } return 0; } /***************************************************************** * * Implementation : Help Browsers * *****************************************************************/ static BOOLEAN feHelpCalled = FALSE; static void heBrowserHelp(heEntry hentry) { // check checksums of procs int kchksum = (hentry != NULL && hentry->chksum > 0 ? heKeyChksum(hentry->key) : 0); if (kchksum && kchksum != hentry->chksum && heOnlineHelp(hentry->key)) return; if (heCurrentHelpBrowser == NULL) feHelpBrowser(NULL, 0); assume(heCurrentHelpBrowser != NULL); if (! feHelpCalled) { Warn("Displaying help in browser '%s'.", heCurrentHelpBrowser->browser); //if (strcmp(heCurrentHelpBrowser->browser, "netscape") == 0 && // feResource('h', 0) == NULL) //{ // Warn("Using URL '%s'.", feResource('u', 0)); //} Warn("Use 'system(\"--browser\", );' to change browser,"); StringSetS("where can be: "); int i = 0; i = 0; while (heHelpBrowsers[i].browser != NULL) { if (heHelpBrowsers[i].init_proc(0,i)) StringAppend("\"%s\", ", heHelpBrowsers[i].browser); i++; } char *browsers=StringEndS(); if (browsers[strlen(browsers)-2] == ',') { browsers[strlen(browsers)-2] = '.'; browsers[strlen(browsers)-1] = '\0'; } WarnS(browsers); omFree(browsers); } heCurrentHelpBrowser->help_proc(hentry, heCurrentHelpBrowserIndex); feHelpCalled = TRUE; } #define MAX_SYSCMD_LEN MAXPATHLEN*2 static BOOLEAN heGenInit(int warn, int br) { if (heHelpBrowsers[br].required==NULL) return TRUE; const char *p=heHelpBrowsers[br].required; while (*p>'\0') { switch (*p) { case '#': break; case ' ': break; case 'i': /* singular.hlp */ case 'x': /* singular.idx */ case 'h': /* html dir */ if (feResource(*p, warn) == NULL) { if (warn) Warn("resource `%c` not found",*p); return FALSE; } break; case 'D': /* DISPLAY */ if (getenv("DISPLAY") == NULL) { if (warn) WarnS("resource `D` not found"); return FALSE; } break; case 'E': /* executable: E:xterm: */ case 'O': /* OS: O:ix86Mac-darwin/ppcMac-darwin: */ { char name[128]; char exec[128]; char op=*p; memset(name,0,128); int i=0; p++; while (((*p==':')||(*p<=' ')) && (*p!='\0')) p++; while((i<127) && (*p>' ') && (*p!=':')) { name[i]=*p; p++; i++; } if (i==0) return FALSE; if ((op=='O') && (strcmp(name,S_UNAME)!=0)) return FALSE; if ((op=='E') && (omFindExec(name,exec)==NULL)) { if (warn) Warn("executable `%s` not found",name); return FALSE; } } break; default: Warn("unknown char %c",*p); break; } p++; } return TRUE; } static void heGenHelp(heEntry hentry, int br) { char sys[MAX_SYSCMD_LEN]; const char *p=heHelpBrowsers[br].action; if (p==NULL) {PrintS("no action ?\n"); return;} memset(sys,0,MAX_SYSCMD_LEN); int i=0; while ((*p>'\0')&& (i "ManualUrl"*/); /* always defined */ if (hentry != NULL && *(hentry->url) != '\0') #ifdef HAVE_VSNPRINTF { if (*p=='H') snprintf(temp,256,"%s/%d-%d-%d/%s", htmldir, SINGULAR_VERSION/1000, (SINGULAR_VERSION % 1000)/100, (SINGULAR_VERSION % 100)/10, hentry->url); else snprintf(temp,256,"%s/%s", htmldir, hentry->url); } else { if (*p=='H') snprintf(temp,256,"%s/%d-%d-%d/index.htm", htmldir, SINGULAR_VERSION/1000, (SINGULAR_VERSION % 1000)/100, (SINGULAR_VERSION % 100)/10 ); else snprintf(temp,256,"%s/index.htm", htmldir); } #else { if (*p=='H') sprintf(temp,"%s/%d-%d-%d/%s", htmldir, SINGULAR_VERSION/1000, (SINGULAR_VERSION % 1000)/100, (SINGULAR_VERSION % 100)/10, hentry->url); else sprintf(temp,"%s/%d-%d-%d/%s", htmldir, hentry->url); } else if (*p=='H') sprintf(temp,"%s/%d-%d-%d/index.htm", htmldir, SINGULAR_VERSION/1000, (SINGULAR_VERSION % 1000)/100, (SINGULAR_VERSION % 100)/10 ); else sprintf(temp,"%s/index.htm", htmldir); } #endif strcat(sys,temp); if ((*p)=='f') { // remove #SEC char *pp=(char *)strchr(sys,'#'); if (pp!=NULL) { *pp='\0'; i=strlen(sys); memset(pp,0,MAX_SYSCMD_LEN-i); } } i=strlen(sys); break; } case 'i': /* singular.hlp */ { char *i_res=feResource('i'); if (i_res!=NULL) strcat(sys,i_res); else { WarnS("singular.hlp not found"); return; } i=strlen(sys); break; } case 'n': /* info node */ { char temp[256]; if ((hentry!=NULL) && (*(hentry->node) != '\0')) sprintf(temp,"%s",hentry->node); //else if ((hentry!=NULL) && (hentry->key!=NULL)) // sprintf(temp,"Index '%s'",hentry->key); else sprintf(temp,"Top"); strcat(sys,temp); i=strlen(sys); break; } case 'v': /* version number*/ { char temp[256]; sprintf(temp,"%d-%d-%d",SINGULAR_VERSION/1000, (SINGULAR_VERSION % 1000)/100, (SINGULAR_VERSION % 100)/10); strcat(sys,temp); i=strlen(sys); break; } default: break; } p++; } else { sys[i]=*p; p++;i++; } } Print("running `%s`\n",sys); (void) system(sys); } static BOOLEAN heDummyInit(int /*warn*/, int /*br*/) { return TRUE; } static void heDummyHelp(heEntry /*hentry*/, int /*br*/) { Werror("No functioning help browser available."); } static BOOLEAN heEmacsInit(int /*warn*/, int /*br*/) { return TRUE; } static void heEmacsHelp(heEntry hentry, int /*br*/) { WarnS("Your help command could not be executed. Use"); Warn("C-h C-s %s", (hentry != NULL && *(hentry->node) != '\0' ? hentry->node : "Top")); Warn("to enter the Singular online help. For general"); Warn("information on Singular running under Emacs, type C-h m."); } static int singular_manual(char *str, BOOLEAN isIndexEntry); static void heBuiltinHelp(heEntry hentry, int /*br*/) { char* node = omStrDup(hentry != NULL && *(hentry->key) != '\0' ? hentry->key : "Top"); singular_manual(node,(hentry != NULL) && (hentry->url!=NULL)); omFree(node); } /* ========================================================================== */ // old, stupid builtin_help // This could be implemented much more clever, but I'm too lazy to do this now // #define HELP_OK 0 #define FIN_INDEX '\037' #define HELP_NOT_OPEN 1 #define HELP_NOT_FOUND 2 #define BUF_LEN 256 #define IDX_LEN 256 #define MAX_LINES 21 static inline char tolow(char p) { if (('A'<=p)&&(p<='Z')) return p | 040; return p; } /*************************************************/ static int show(unsigned long offset, char *close) { char buffer[BUF_LEN+1]; int lines = 0; FILE * help; if( (help = fopen(feResource('i'), "rb")) == NULL) return HELP_NOT_OPEN; fseek(help, (long)(offset+1), (int)0); while( (!feof(help)) && (*fgets(buffer, BUF_LEN, help) != EOF) && (buffer[0] != FIN_INDEX)) { printf("%s", buffer); if(lines++> MAX_LINES) { printf("\n Press to continue or x to exit help.\n"); fflush(stdout); *close = (char)getchar(); if(*close=='x') { getchar(); break; } lines=0; } } if(*close!='x') { printf("\nEnd of part. Press to continue or x to exit help.\n"); fflush(stdout); *close = (char)getchar(); if(*close=='x') getchar(); } fclose(help); return HELP_OK; } /*************************************************/ static int singular_manual(char *str, BOOLEAN isIndexEntry) { FILE *index=NULL; unsigned long offset; char *p,close=' '; int done = 0; char buffer[BUF_LEN+1], Index[IDX_LEN+1], String[IDX_LEN+1]; Print("HELP >>%s>>\n",str); if( (index = fopen(feResource('i'), "rb")) == NULL) { return HELP_NOT_OPEN; } if (!isIndexEntry) { for(p=str; *p; p++) *p = tolow(*p);/* */ do { p--; } while ((p != str) && (*p<=' ')); p++; *p='\0'; (void)sprintf(String, " %s ", str); } else { (void)sprintf(String, " %s", str); } while(!feof(index) && (fgets(buffer, BUF_LEN, index) != (char *)0) && (buffer[0] != FIN_INDEX)); while(!feof(index)) { if (fgets(buffer, BUF_LEN, index)==NULL) break; /*fill buffer */ if (si_sscanf(buffer, "Node:%[^\177]\177%ld\n", Index, &offset)!=2) continue; if (!isIndexEntry) { for(p=Index; *p; p++) *p = tolow(*p);/* */ (void)strcat(Index, " "); if( strstr(Index, String)!=NULL) { done++; (void)show(offset, &close); } } else if( strcmp(Index, String)==0) { done++; (void)show(offset, &close); break; } Index[0]='\0'; if(close=='x') break; } if (index != NULL) (void)fclose(index); if(done==0) { Warn("`%s` not found",String); return HELP_NOT_FOUND; } return HELP_OK; } /*************************************************/ singular-4.0.3+ds/Singular/fehelp.h000066400000000000000000000013711266270727000171570ustar00rootroot00000000000000#ifndef FEHELP_H #define FEHELP_H /***************************************************************** * * help system (fehelp.cc) * *****************************************************************/ // if str != NULL display help for str // display general help, otherwise void feHelp(char* str = NULL); // if browser != NULL or feOpt("browser") != NULL // set HelpBrowser to browser // otherwise, if browser was already set, leave as is, // if not, choose first available browser // return string identifying current browser // keeps feOpt("browser") up-to-date // Optional warn argument is as in feResource const char* feHelpBrowser(char* browser = NULL, int warn = -1); void feStringAppendBrowsers(int warn = -1); #endif /* FEHELP_H */ singular-4.0.3+ds/Singular/fevoices.cc000066400000000000000000000373511266270727000176640ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: i/o system */ #include /* I need myfread in standalone_parser */ #ifndef STANDALONE_PARSER #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_PWD_H #include #endif #define fePutChar(c) fputc((unsigned char)(c),stdout) /*0 implementation */ char fe_promptstr[] =" "; FILE *File_Profiling=NULL; // output/print buffer: #define INITIAL_PRINT_BUFFER 24*1024L // line buffer for reading: // minimal value for MAX_FILE_BUFFER: 4*4096 - see Tst/Long/gcd0_l.tst // this is an upper limit for the size of monomials/numbers read via the interpreter #define MAX_FILE_BUFFER 4*4096 // static long feBufferLength=INITIAL_PRINT_BUFFER; static char * feBuffer=(char *)omAlloc(INITIAL_PRINT_BUFFER); /************************************************************************** * handling of 'voices' **************************************************************************/ extern int blocknest; /* scaner.l internal */ int yy_noeof=0; // the scanner "state" int yy_blocklineno; // to get the lineno of the block start from scanner Voice *currentVoice = NULL; // FILE *feFilePending; /*temp. storage for grammar.y */ //static const char * BT_name[]={"BT_none","BT_break","BT_proc","BT_example", // "BT_file","BT_execute","BT_if","BT_else"}; /*2 * the name of the current 'Voice': the procname (or filename) */ const char * sNoName_fe="_"; const char * VoiceName() { if ((currentVoice!=NULL) && (currentVoice->filename!=NULL)) return currentVoice->filename; return sNoName_fe; } /*2 * the calling chain of Voices */ void VoiceBackTrack() { Voice *p=currentVoice; while (p->prev!=NULL) { p=p->prev; char *s=p->filename; if (s==NULL) PrintS("-- called from ? --\n"); else Print("-- called from %s --\n",s); } } /*2 * init a new voice similar to the current */ void Voice::Next() { Voice *p=new Voice; // OB: ??? // Hmm... when Singular is used as batch file // then this voice is never freed omMarkAsStaticAddr(p); if (currentVoice != NULL) { currentVoice->curr_lineno=yylineno; currentVoice->next=p; } p->prev=currentVoice; currentVoice=p; //Print("Next:"); } feBufferTypes Voice::Typ() { switch(typ) { case BT_proc: case BT_example: case BT_file: return typ; default: if (prev==NULL) return (feBufferTypes)0; return prev->Typ(); } } /*2 * start the file 'fname' (STDIN is stdin) as a new voice (cf.VFile) * return FALSE on success, TRUE if an error occurs (file cannot be opened) */ BOOLEAN newFile(char *fname,FILE* f) { currentVoice->Next(); //Print(":File%d(%s):%s(%x)\n", // currentVoice->typ,BT_name[currentVoice->typ],fname,currentVoice); currentVoice->filename = omStrDup(fname); omMarkAsStaticAddr(currentVoice->filename); if (strcmp(fname,"STDIN") == 0) { currentVoice->files = stdin; currentVoice->sw = BI_stdin; currentVoice->start_lineno = 1; } else { currentVoice->sw = BI_file; /* needed by exitVoice below */ if (f!=NULL) currentVoice->files = f; else { currentVoice->files = feFopen(fname,"r",NULL,TRUE); if (currentVoice->files==NULL) { exitVoice(); return TRUE; } } currentVoice->start_lineno = 0; } yylineno=currentVoice->start_lineno; //Voice *p=currentVoice; //Print("-----------------\ncurr:"); //do //{ //Print("voice fn:%s\n",p->filename); //p=p->prev; //} //while (p!=NULL); //Print("----------------\n"); return FALSE; } void newBuffer(char* s, feBufferTypes t, procinfo* pi, int lineno) { currentVoice->Next(); //Print(":Buffer%d(%s):%s(%x)\n", // t,BT_name[t],pname,currentVoice); if (pi!=NULL) { long l=strlen(pi->procname); if (pi->libname!=NULL) l+=strlen(pi->libname); currentVoice->filename = (char *)omAlloc(l+3); *currentVoice->filename='\0'; if (pi->libname!=NULL) strcat(currentVoice->filename,pi->libname); strcat(currentVoice->filename,"::"); strcat(currentVoice->filename,pi->procname); currentVoice->pi = pi; } else { if(currentVoice->prev!=NULL) { currentVoice->filename = omStrDup(currentVoice->prev->filename); currentVoice->pi = currentVoice->prev->pi; } else { currentVoice->filename = omStrDup(""); currentVoice->pi = pi; } } currentVoice->buffer = s; currentVoice->sw = BI_buffer; currentVoice->typ = t; switch (t) { case BT_execute: yylineno-=2; break; case BT_proc: case BT_example: currentVoice->oldb=myynewbuffer(); yylineno = lineno+1; break; case BT_if: case BT_else: case BT_break: yylineno = yy_blocklineno-1; break; //case BT_file: default: yylineno = 1; break; } //Print("start body (%s) at line %d\n",BT_name[t],yylineno); currentVoice->start_lineno = yylineno; //printf("start buffer typ %d\n",t); //Voice *p=currentVoice; //Print("-----------------\ncurr:"); //do //{ //Print("voice fn:%s\n",p->filename); //p=p->prev; //} //while (p!=NULL); //Print("----------------\n"); } /*2 * exit Buffer of type 'typ': * returns 1 if buffer type could not be found */ BOOLEAN exitBuffer(feBufferTypes typ) { //printf("exitBuffer: %d(%s),(%x)\n", // typ,BT_name[typ], currentVoice); //Voice *p=currentVoice; //Print("-----------------\ncurr:"); //do //{ //Print("voice fn:%s\n",p->filename); //p=p->prev; //} //while (p!=NULL); //Print("----------------\n"); if (typ == BT_break) // valid inside for, while. may skip if, else { /*4 first check for valid buffer type, skip if/else*/ Voice *p=currentVoice; loop { if ((p->typ != BT_if) &&(p->typ != BT_else)) { if (p->typ == BT_break /*typ*/) { while (p != currentVoice) { exitVoice(); } exitVoice(); return FALSE; } else return TRUE; } if (p->prev==NULL) break; p=p->prev; } /*4 break not inside a for/while: return an error*/ if (/*typ*/ BT_break != currentVoice->typ) return 1; return exitVoice(); } if ((typ == BT_proc) || (typ == BT_example)) { Voice *p=currentVoice; loop { if ((p->typ == BT_proc) || (p->typ == BT_example)) { while (p != currentVoice) { exitVoice(); } exitVoice(); return FALSE; } if (p->prev==NULL) break; p=p->prev; } } /*4 return not inside a proc: return an error*/ return TRUE; } /*2 * jump to the beginning of a buffer */ BOOLEAN contBuffer(feBufferTypes typ) { //printf("contBuffer: %d(%s),(%x)\n", // typ,BT_name[typ], currentVoice); if (typ == BT_break) // valid inside for, while. may skip if, else { // first check for valid buffer type Voice *p=currentVoice; loop { if ((p->typ != BT_if) &&(p->typ != BT_else)) { if (p->typ == BT_break /*typ*/) { while (p != currentVoice) { exitVoice(); } yylineno = currentVoice->start_lineno; currentVoice->fptr=0; return FALSE; } else return TRUE; } if (p->prev==NULL) break; p=p->prev; } } return TRUE; } /*2 * leave a voice: kill local variables * setup everything from the previous level * return 1 if leaving the top level, 0 otherwise */ BOOLEAN exitVoice() { //printf("exitVoice: %d(%s),(%x)\n", // currentVoice->typ,BT_name[currentVoice->typ], currentVoice); //{ //Voice *p=currentVoice; //Print("-----------------\ncurr:"); //do //{ //Print("voice fn:%s\n",p->filename); //p=p->prev; //} //while (p!=NULL); //Print("----------------\n"); //} if (currentVoice!=NULL) { if (currentVoice->oldb!=NULL) { myyoldbuffer(currentVoice->oldb); currentVoice->oldb=NULL; } if ((currentVoice->prev==NULL)&&(currentVoice->sw==BI_file)) { currentVoice->prev=feInitStdin(currentVoice); } if (currentVoice->prev!=NULL) { //printf("exitVoice typ %d(%s)\n", // currentVoice->typ,BT_name[currentVoice->typ]); if (currentVoice->typ==BT_if) { currentVoice->prev->ifsw=2; } else { currentVoice->prev->ifsw=0; } if ((currentVoice->sw == BI_file) && (currentVoice->files!=NULL)) { fclose(currentVoice->files); } if (currentVoice->filename!=NULL) { omFree((ADDRESS)currentVoice->filename); currentVoice->filename=NULL; } if (currentVoice->buffer!=NULL) { omFree((ADDRESS)currentVoice->buffer); currentVoice->buffer=NULL; } yylineno=currentVoice->prev->curr_lineno; currentVoice->prev->next=NULL; } Voice *p=currentVoice->prev; delete currentVoice; currentVoice=p; } return currentVoice==NULL; } /*2 * set prompt_char * only called with currentVoice->sw == BI_stdin */ static void feShowPrompt(void) { fe_promptstr[0]=prompt_char; } /*2 * print echo (si_echo or TRACE), set my_yylinebuf */ static int fePrintEcho(char *anf, char */*b*/) { char *ss=strrchr(anf,'\n'); int len_s; if (ss==NULL) { len_s=strlen(anf); } else { len_s=ss-anf+1; } // my_yylinebuf: int mrc=si_min(len_s,79)-1; strcpy(my_yylinebuf,anf+(len_s-1)-mrc); if (my_yylinebuf[mrc] == '\n') my_yylinebuf[mrc] = '\0'; mrc--; // handle echo: if (((si_echo>myynest) && ((currentVoice->typ==BT_proc) || (currentVoice->typ==BT_example) || (currentVoice->typ==BT_file) || (currentVoice->typ==BT_none) ) && (strncmp(anf,";return();",10)!=0) ) || (traceit&TRACE_SHOW_LINE) || (traceit&TRACE_SHOW_LINE1)) { if (currentVoice->typ!=BT_example) { if (currentVoice->filename==NULL) Print("(none) %3d%c ",yylineno,prompt_char); else Print("%s %3d%c ",currentVoice->filename,yylineno,prompt_char); } { fwrite(anf,1,len_s,stdout); mflush(); } if (traceit&TRACE_SHOW_LINE) { while(fgetc(stdin)!='\n'); } } else if (traceit&TRACE_SHOW_LINENO) { Print("{%d}",yylineno); mflush(); } else if (traceit&TRACE_PROFILING) { if (File_Profiling==NULL) File_Profiling=fopen("smon.out","a"); if (File_Profiling==NULL) traceit &= (~TRACE_PROFILING); else { if (currentVoice->filename==NULL) fprintf(File_Profiling,"(none) %d\n",yylineno); else fprintf(File_Profiling,"%s %d\n",currentVoice->filename,yylineno); } } #ifdef HAVE_SDB if ((blocknest==0) && (currentVoice->pi!=NULL) && (currentVoice->pi->trace_flag!=0)) { sdb(currentVoice, anf, len_s); } #endif prompt_char = '.'; return len_s; } int feReadLine(char* b, int l) { char *s=NULL; int offset = 0; /* will not be used if s==NULL*/ // try to read from the buffer into b, max l chars if (currentVoice!=NULL) { if((currentVoice->buffer!=NULL) && (currentVoice->buffer[currentVoice->fptr]!='\0')) { NewBuff: register int i=0; long startfptr=currentVoice->fptr; long tmp_ptr=currentVoice->fptr; l--; loop { register char c= b[i]=currentVoice->buffer[tmp_ptr/*currentVoice->fptr*/]; i++; if (yy_noeof==noeof_block) { if (c<' ') yylineno++; else if (c=='}') break; } else { if ((c<' ') || (c==';') || (c==')') ) break; } if (i>=l) break; tmp_ptr++;/*currentVoice->fptr++;*/ if(currentVoice->buffer[tmp_ptr/*currentVoice->fptr*/]=='\0') break; } currentVoice->fptr=tmp_ptr; b[i]='\0'; if (currentVoice->sw==BI_buffer) { if (startfptr==0) { char *anf=currentVoice->buffer; const char *ss=strchr(anf,'\n'); long len; if (ss==NULL) len=strlen(anf); else len=ss-anf; char *s=(char *)omAlloc(len+2); strncpy(s,anf,len+2); s[len+1]='\0'; fePrintEcho(s,b); omFree((ADDRESS)s); } else if (/*(startfptr>0) &&*/ (currentVoice->buffer[startfptr-1]=='\n')) { char *anf=currentVoice->buffer+startfptr; const char *ss=strchr(anf,'\n'); long len; if (ss==NULL) len=strlen(anf); else len=ss-anf; char *s=(char *)omAlloc(len+2); strncpy(s,anf,len+2); s[len+1]='\0'; yylineno++; fePrintEcho(s,b); omFree((ADDRESS)s); } } currentVoice->fptr++; return i; } // no buffer there or e-o-buffer or eoln: if (currentVoice->sw!=BI_buffer) { currentVoice->fptr=0; if (currentVoice->buffer==NULL) { currentVoice->buffer=(char *)omAlloc(MAX_FILE_BUFFER-sizeof(ADDRESS)); omMarkAsStaticAddr(currentVoice->buffer); } } offset=0; NewRead: yylineno++; if (currentVoice->sw==BI_stdin) { feShowPrompt(); s=fe_fgets_stdin(fe_promptstr, &(currentVoice->buffer[offset]), omSizeOfAddr(currentVoice->buffer)-1-offset); //int i=0; //if (s!=NULL) // while((s[i]!='\0') /*&& (isw==BI_file) { s=fgets(currentVoice->buffer+offset,(MAX_FILE_BUFFER-1-sizeof(ADDRESS))-offset, currentVoice->files); } //else /* BI_buffer */ s==NULL => return 0 // done by the default return } if (s!=NULL) { // handle prot: if (feProt&SI_PROT_I) { fputs(s,feProtFile); } int rc=fePrintEcho(s,b)+1; //s[strlen(s)+1]='\0'; add an second \0 at the end of the string s[rc]='\0'; // handel \\ : rc-=3; if ((s[rc]=='\\')&&(currentVoice->sw!=BI_buffer)) { s[rc]='\0'; offset+=rc; if (offset<(int)omSizeOfAddr(currentVoice->buffer)) goto NewRead; } goto NewBuff; } /* else if (s==NULL) */ { const char *err; switch(yy_noeof) { case noeof_brace: case noeof_block: err="{...}"; break; case noeof_asstring: err="till `.`"; break; case noeof_string: err="string"; break; case noeof_bracket: err="(...)"; break; case noeof_procname: err="proc"; break; case noeof_comment: err="/*...*/"; break; default: return 0; } Werror("premature end of file while reading %s",err); return 0; } } /*2 * init all data structures */ #ifndef STDIN_FILENO #define STDIN_FILENO 0 #endif Voice * feInitStdin(Voice *pp) { Voice *p = new Voice; p->files = stdin; p->sw = (isatty(STDIN_FILENO)) ? BI_stdin : BI_file; if ((pp!=NULL) && (pp->files==stdin)) { p->files=freopen("/dev/tty","r",stdin); //stdin=p->files; p->sw = BI_stdin; } p->filename = omStrDup("STDIN"); p->start_lineno = 1; omMarkAsStaticAddr(p); omMarkAsStaticAddr(p->filename); return p; } #else /* ! STANDALONE_PARSER */ #include #endif singular-4.0.3+ds/Singular/fevoices.h000066400000000000000000000046261266270727000175250ustar00rootroot00000000000000#ifndef FEVOICES_H #define FEVOICES_H /**************************************** * * Computer Algebra System SINGULAR * * ****************************************/ /* * * ABSTRACT: class Voice * */ #include #include #include enum feBufferTypes { BT_none = 0, // entry level BT_break = 1, // while, for BT_proc, // proc BT_example, // example BT_file, // <"file" BT_execute, // execute BT_if, // if BT_else // else }; enum feBufferInputs { BI_stdin = 1, BI_buffer, BI_file }; enum noeof_t { noeof_brace = 1, noeof_asstring, noeof_block, noeof_bracket, noeof_comment, noeof_procname, noeof_string }; /* for scanner.l */ extern int yylineno; extern char my_yylinebuf[80]; #ifdef __cplusplus /* the C++-part: */ // LANG_TOP : Toplevel package only // LANG_SINGULAR: // LANG_C : // class Voice { public: Voice * next; Voice * prev; char * filename; // file name or proc name procinfo * pi; // proc info void * oldb; // internal scanner buffer // for files only: FILE * files; // file handle // for buffers only: char * buffer; // buffer pointer long fptr; // current position in buffer int start_lineno; // lineno, to restore in recursion int curr_lineno; // current lineno feBufferInputs sw; // BI_stdin: read from STDIN // BI_buffer: buffer // BI_file: files char ifsw; // if-switch: /*1 ifsw==0: no if statement, else is invalid * ==1: if (0) processed, execute else * ==2: if (1) processed, else allowed but not executed */ feBufferTypes typ; // buffer type: see BT_.. Voice() { memset(this,0,sizeof(*this));} feBufferTypes Typ(); void Next(); } ; extern Voice *currentVoice; Voice * feInitStdin(Voice *pp); const char * VoiceName(); void VoiceBackTrack(); BOOLEAN contBuffer(feBufferTypes typ); BOOLEAN exitBuffer(feBufferTypes typ); BOOLEAN exitVoice(); void monitor(void *F, int mode); /* FILE*, int */ BOOLEAN newFile(char* fname, FILE *f=NULL); void newBuffer(char* s, feBufferTypes t, procinfo *pname = NULL, int start_lineno = 0); void * myynewbuffer(); void myyoldbuffer(void * oldb); #endif #endif singular-4.0.3+ds/Singular/fglm.cc000066400000000000000000000405341266270727000170030ustar00rootroot00000000000000// emacs edit mode for this file is -*- C++ -*- /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT - The FGLM-Algorithm plus extension * Calculate a reduced groebner basis for one ordering, given a * reduced groebner basis for another ordering. * In this file the input is checked. Furthermore we decide, if * the input is 0-dimensional ( then fglmzero.cc is used ) or * if the input is homogeneous ( then fglmhom.cc is used. Yet * not implemented ). * The extension (finduni) finds minimal univariate Polynomials * lying in a 0-dimensional ideal. */ #include #include #include #include #include #include #include #include #include #include #include #include #include // internal Version: 1.18.1.6 // enumeration to handle the various errors to occour. enum FglmState{ FglmOk, FglmHasOne, FglmNoIdeal, FglmNotReduced, FglmNotZeroDim, FglmIncompatibleRings, // for fglmquot: FglmPolyIsOne, FglmPolyIsZero }; // Has to be called, if currRing->qideal != NULL. ( i.e. qring-case ) // Then a new ideal is build, consisting of the generators of sourceIdeal // and the generators of currRing->qideal, which are completely reduced by // the sourceIdeal. This means: If sourceIdeal is reduced, then the new // ideal will be reduced as well. // Assumes that currRing == sourceRing ideal fglmUpdatesource( const ideal sourceIdeal ) { int k, l, offset; BOOLEAN found; ideal newSource= idInit( IDELEMS( sourceIdeal ) + IDELEMS( currRing->qideal ), 1 ); for ( k= IDELEMS( sourceIdeal )-1; k >=0; k-- ) (newSource->m)[k]= pCopy( (sourceIdeal->m)[k] ); offset= IDELEMS( sourceIdeal ); for ( l= IDELEMS( currRing->qideal )-1; l >= 0; l-- ) { if ( (currRing->qideal->m)[l] != NULL ) { found= FALSE; for ( k= IDELEMS( sourceIdeal )-1; (k >= 0) && (found == FALSE); k-- ) if ( pDivisibleBy( (sourceIdeal->m)[k], (currRing->qideal->m)[l] ) ) found= TRUE; if ( ! found ) { (newSource->m)[offset]= pCopy( (currRing->qideal->m)[l] ); offset++; } } } idSkipZeroes( newSource ); return newSource; } // Has to be called, if currRing->qideal != NULL, i.e. in qring-case. // Gets rid of the elements of result which are contained in // currRing->qideal and skips Zeroes. // Assumes that currRing == destRing void fglmUpdateresult( ideal & result ) { int k, l; BOOLEAN found; for ( k= IDELEMS( result )-1; k >=0; k-- ) { if ( (result->m)[k] != NULL ) { found= FALSE; for ( l= IDELEMS( currRing->qideal )-1; (l >= 0) && ( found == FALSE ); l-- ) if ( pDivisibleBy( (currRing->qideal->m)[l], (result->m)[k] ) ) found= TRUE; if ( found ) pDelete( & ((result->m)[k]) ); } } idSkipZeroes( result ); } // Checks if the two rings sringHdl and dringHdl are compatible enough to // be used for the fglm. This means: // 1) Same Characteristic, 2) globalOrderings in both rings, // 3) Same number of variables, 4) same number of parameters // 5) variables in one ring are permutated variables of the other one // 6) parameters in one ring are permutated parameters of the other one // 7) either both rings are rings or both rings are qrings // 8) if they are qrings, the quotientIdeals of both must coincide. // vperm must be a vector of length pVariables+1, initialized by 0. // If both rings are compatible, it stores the permutation of the // variables if mapped from sringHdl to dringHdl. // if the rings are compatible, it returns FglmOk. // Should be called with currRing= IDRING( sringHdl ); FglmState fglmConsistency( idhdl sringHdl, idhdl dringHdl, int * vperm ) { int k; FglmState state= FglmOk; ring dring = IDRING( dringHdl ); ring sring = IDRING( sringHdl ); if ( rChar(sring) != rChar(dring) ) { WerrorS( "rings must have same characteristic" ); state= FglmIncompatibleRings; } if ( (sring->OrdSgn != 1) || (dring->OrdSgn != 1) ) { WerrorS( "only works for global orderings" ); state= FglmIncompatibleRings; } if ( sring->N != dring->N ) { WerrorS( "rings must have same number of variables" ); state= FglmIncompatibleRings; } if ( rPar(sring) != rPar(dring) ) { WerrorS( "rings must have same number of parameters" ); state= FglmIncompatibleRings; } if ( state != FglmOk ) return state; // now the rings have the same number of variables resp. parameters. // check if the names of the variables resp. parameters do agree: int nvar = sring->N; int npar = rPar(sring); int * pperm; if ( npar > 0 ) pperm= (int *)omAlloc0( (npar+1)*sizeof( int ) ); else pperm= NULL; maFindPerm( sring->names, nvar, rParameter(sring), npar, dring->names, nvar, rParameter(dring), npar, vperm, pperm, dring->cf->type); for ( k= nvar; (k > 0) && (state == FglmOk); k-- ) if ( vperm[k] <= 0 ) { WerrorS( "variable names do not agree" ); state= FglmIncompatibleRings; } for ( k= npar-1; (k >= 0) && (state == FglmOk); k-- ) if ( pperm[k] >= 0 ) { WerrorS( "parameter names do not agree" ); state= FglmIncompatibleRings; } if (pperm != NULL) // OB: ???? omFreeSize( (ADDRESS)pperm, (npar+1)*sizeof( int ) ); if ( state != FglmOk ) return state; // check if both rings are qrings or not if ( sring->qideal != NULL ) { if ( dring->qideal == NULL ) { Werror( "%s is a qring, current ring not", sringHdl->id ); return FglmIncompatibleRings; } // both rings are qrings, now check if both quotients define the same ideal. // check if sring->qideal is contained in dring->qideal: rSetHdl( dringHdl ); nMapFunc nMap=n_SetMap(currRing->cf, sring->cf ); ideal sqind = idInit( IDELEMS( sring->qideal ), 1 ); for ( k= IDELEMS( sring->qideal )-1; k >= 0; k-- ) (sqind->m)[k]= p_PermPoly( (sring->qideal->m)[k], vperm, sring, currRing, nMap); ideal sqindred = kNF( dring->qideal, NULL, sqind ); if ( ! idIs0( sqindred ) ) { WerrorS( "the quotients do not agree" ); state= FglmIncompatibleRings; } idDelete( & sqind ); idDelete( & sqindred ); rSetHdl( sringHdl ); if ( state != FglmOk ) return state; // check if dring->qideal is contained in sring->qideal: int * dsvperm = (int *)omAlloc0( (nvar+1)*sizeof( int ) ); maFindPerm( dring->names, nvar, NULL, 0, sring->names, nvar, NULL, 0, dsvperm, NULL, sring->cf->type); nMap=n_SetMap(currRing->cf, dring->cf); ideal dqins = idInit( IDELEMS( dring->qideal ), 1 ); for ( k= IDELEMS( dring->qideal )-1; k >= 0; k-- ) (dqins->m)[k]=p_PermPoly( (dring->qideal->m)[k], dsvperm, sring, currRing, nMap); ideal dqinsred = kNF( sring->qideal, NULL, dqins ); if ( ! idIs0( dqinsred ) ) { WerrorS( "the quotients do not agree" ); state= FglmIncompatibleRings; } idDelete( & dqins ); idDelete( & dqinsred ); omFreeSize( (ADDRESS)dsvperm, (nvar+1)*sizeof( int ) ); if ( state != FglmOk ) return state; } else { if ( dring->qideal != NULL ) { Werror( "current ring is a qring, %s not", sringHdl->id ); return FglmIncompatibleRings; } } return FglmOk; } // Checks if the ideal "theIdeal" is zero-dimensional and minimal. It does // not check, if it is reduced. // returns FglmOk if we can use theIdeal for CalculateFunctionals (this // function reports an error if theIdeal is not reduced, // so this need not to be tested here) // FglmNotReduced if theIdeal is not minimal // FglmNotZeroDim if it is not zero-dimensional // FglmHasOne if 1 belongs to theIdeal FglmState fglmIdealcheck( const ideal theIdeal ) { FglmState state = FglmOk; int power; int k; BOOLEAN * purePowers = (BOOLEAN *)omAlloc0( currRing->N*sizeof( BOOLEAN ) ); for ( k= IDELEMS( theIdeal ) - 1; (state == FglmOk) && (k >= 0); k-- ) { poly p = (theIdeal->m)[k]; if (p!=NULL) { if( pIsConstant( p ) ) state= FglmHasOne; else if ( (power= pIsPurePower( p )) > 0 ) { fglmASSERT( 0 < power && power <= currRing->N, "illegal power" ); if ( purePowers[power-1] == TRUE ) state= FglmNotReduced; else purePowers[power-1]= TRUE; } for ( int l = IDELEMS( theIdeal ) - 1; state == FglmOk && l >= 0; l-- ) if ( (k != l) && pDivisibleBy( p, (theIdeal->m)[l] ) ) state= FglmNotReduced; } } if ( state == FglmOk ) { for ( k= currRing->N-1 ; (state == FglmOk) && (k >= 0); k-- ) if ( purePowers[k] == FALSE ) state= FglmNotZeroDim; } omFreeSize( (ADDRESS)purePowers, currRing->N*sizeof( BOOLEAN ) ); return state; } // The main function for the fglm-Algorithm. // Checks the input-data, and calls fglmzero (see fglmzero.cc). // Returns the new groebnerbasis or 0 if an error occoured. BOOLEAN fglmProc( leftv result, leftv first, leftv second ) { FglmState state = FglmOk; idhdl destRingHdl = currRingHdl; // ring destRing = currRing; ideal destIdeal = NULL; idhdl sourceRingHdl = (idhdl)first->data; rSetHdl( sourceRingHdl ); // ring sourceRing = currRing; int * vperm = (int *)omAlloc0( (currRing->N+1)*sizeof( int ) ); state= fglmConsistency( sourceRingHdl, destRingHdl, vperm ); omFreeSize( (ADDRESS)vperm, (currRing->N+1)*sizeof(int) ); if ( state == FglmOk ) { idhdl ih = currRing->idroot->get( second->Name(), myynest ); if ( (ih != NULL) && (IDTYP(ih)==IDEAL_CMD) ) { ideal sourceIdeal; if ( currRing->qideal != NULL ) sourceIdeal= fglmUpdatesource( IDIDEAL( ih ) ); else sourceIdeal = IDIDEAL( ih ); state= fglmIdealcheck( sourceIdeal ); if ( state == FglmOk ) { // Now the settings are compatible with FGLM assumeStdFlag( (leftv)ih ); if ( fglmzero( IDRING(sourceRingHdl), sourceIdeal, IDRING(destRingHdl), destIdeal, FALSE, (currRing->qideal != NULL) ) == FALSE ) state= FglmNotReduced; } } else state= FglmNoIdeal; } if ( currRingHdl != destRingHdl ) rSetHdl( destRingHdl ); switch (state) { case FglmOk: if ( currRing->qideal != NULL ) fglmUpdateresult( destIdeal ); break; case FglmHasOne: destIdeal= idInit(1,1); (destIdeal->m)[0]= pOne(); state= FglmOk; break; case FglmIncompatibleRings: Werror( "ring %s and current ring are incompatible", first->Name() ); destIdeal= NULL; break; case FglmNoIdeal: Werror( "Can't find ideal %s in ring %s", second->Name(), first->Name() ); destIdeal= NULL; break; case FglmNotZeroDim: Werror( "The ideal %s has to be 0-dimensional", second->Name() ); destIdeal= NULL; break; case FglmNotReduced: Werror( "The ideal %s has to be given by a reduced SB", second->Name() ); destIdeal= NULL; break; default: destIdeal= idInit(1,1); } result->rtyp = IDEAL_CMD; result->data= (void *)destIdeal; setFlag( result, FLAG_STD ); return (state != FglmOk); } // fglmQuotProc: Calculate I:f with FGLM methods. // Checks the input-data, and calls fglmquot (see fglmzero.cc). // Returns the new groebnerbasis if I:f or 0 if an error occoured. BOOLEAN fglmQuotProc( leftv result, leftv first, leftv second ) { FglmState state = FglmOk; // STICKYPROT("quotstart\n"); ideal sourceIdeal = (ideal)first->Data(); poly quot = (poly)second->Data(); ideal destIdeal = NULL; state = fglmIdealcheck( sourceIdeal ); if ( state == FglmOk ) { if ( quot == NULL ) state= FglmPolyIsZero; else if ( pIsConstant( quot ) ) state= FglmPolyIsOne; } if ( state == FglmOk ) { assumeStdFlag( first ); if ( fglmquot( sourceIdeal, quot, destIdeal ) == FALSE ) state= FglmNotReduced; } switch (state) { case FglmOk: break; case FglmHasOne: destIdeal= idInit(1,1); (destIdeal->m)[0]= pOne(); state= FglmOk; break; case FglmNotZeroDim: Werror( "The ideal %s has to be 0-dimensional", first->Name() ); destIdeal= NULL; break; case FglmNotReduced: Werror( "The poly %s has to be reduced", second->Name() ); destIdeal= NULL; break; case FglmPolyIsOne: int k; destIdeal= idInit( IDELEMS(sourceIdeal), 1 ); for ( k= IDELEMS( sourceIdeal )-1; k >=0; k-- ) (destIdeal->m)[k]= pCopy( (sourceIdeal->m)[k] ); state= FglmOk; break; case FglmPolyIsZero: destIdeal= idInit(1,1); (destIdeal->m)[0]= pOne(); state= FglmOk; break; default: destIdeal= idInit(1,1); } result->rtyp = IDEAL_CMD; result->data= (void *)destIdeal; setFlag( result, FLAG_STD ); // STICKYPROT("quotend\n"); return (state != FglmOk); } // fglmQuotProt // The main function for finduni(). // Checks the input-data, and calls FindUnivariateWrapper (see fglmzero.cc). // Returns an ideal containing the univariate Polynomials or 0 if an error // has occoured. BOOLEAN findUniProc( leftv result, leftv first ) { ideal sourceIdeal; ideal destIdeal = NULL; FglmState state; sourceIdeal = (ideal)first->Data(); assumeStdFlag( first ); state= fglmIdealcheck( sourceIdeal ); if ( state == FglmOk ) { // check for special cases: if the input contains // univariate polys, try to reduce the problem int i,k; int count=0; BOOLEAN * purePowers = (BOOLEAN *)omAlloc0( currRing->N*sizeof( BOOLEAN ) ); for ( k= IDELEMS( sourceIdeal ) - 1; k >= 0; k-- ) { if((i=pIsUnivariate(sourceIdeal->m[k]))>0) { if (purePowers[i-1]==0) { purePowers[i-1]=k; count++; if (count==currRing->N) break; } } } if (count==currRing->N) { destIdeal=idInit(currRing->N,1); for(k=currRing->N-1; k>=0; k--) destIdeal->m[k]=pCopy(sourceIdeal->m[purePowers[k]]); } omFreeSize((ADDRESS)purePowers, currRing->N*sizeof( BOOLEAN ) ); if (destIdeal!=NULL) state = FglmOk; else if ( FindUnivariateWrapper( sourceIdeal, destIdeal ) == FALSE ) state = FglmNotReduced; } switch (state) { case FglmOk: break; case FglmHasOne: destIdeal= idInit(1,1); (destIdeal->m)[0]= pOne(); state= FglmOk; break; case FglmNotZeroDim: Werror( "The ideal %s has to be 0-dimensional", first->Name() ); destIdeal= NULL; break; case FglmNotReduced: Werror( "The ideal %s has to be reduced", first->Name() ); destIdeal= NULL; break; default: destIdeal= idInit(1,1); } result->rtyp = IDEAL_CMD; result->data= (void *)destIdeal; return FALSE; } // ---------------------------------------------------------------------------- // Local Variables: *** // compile-command: "make Singular" *** // page-delimiter: "^\\( \\|//!\\)" *** // fold-internal-margins: nil *** // End: *** singular-4.0.3+ds/Singular/fglm.h000066400000000000000000000024351266270727000166430ustar00rootroot00000000000000#ifndef SINGULAR_FGLM_H #define SINGULAR_FGLM_H #include #include #include // fglmproc(...): // The procedure which has to be called from the interpreter for fglm. // first is the sourceRing, second is the given ideal in sourceRing. // Returns the groebnerbasis of the sourceIdeal in the currentRing. // Checks, if the ideal is really a reduced groebner basis of a // 0-dimensional Ideal. Returns TRUE if an error occoured. BOOLEAN fglmProc( leftv result, leftv first, leftv second ); // fglmquotproc(...): // The procedure which has to be called from the interpreter for fglmquot. // first is the ideal I, second is the polynomial q. The polynomial must // be reduced with respect to I. // Returns the groebnerbasis of I:q in the currentRing. // Checks, if the ideal is really a reduced groebner basis of a // 0-dimensional Ideal and if q is really reduced. // Returns TRUE if an error occoured. BOOLEAN fglmQuotProc( leftv result, leftv first, leftv second ); // FindUnivariatePolys (test) BOOLEAN FindUnivariateWrapper( ideal source, ideal & dest ); // wrapper for FindUnivariatePolys (test) BOOLEAN findUniProc( leftv result, leftv first); // homogeneous FGLM ideal fglmhomProc(leftv first, leftv second); #endif // #ifndef SINGULAR_FGLM_H singular-4.0.3+ds/Singular/gentable.cc000066400000000000000000000634361266270727000176450ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: generate iparith.inc etc. */ #include #include #include #include #include #include #include #include // need global defines: #include "kernel/mod2.h" // need to include all tokens: *_CMD: #include "grammar.h" #include "tok.h" inline int RingDependend(int t) { return (BEGIN_RING0, .. */ short valid_for; }; struct sValAssign_sys { int p; short res; short arg; }; struct sValAssign { int p; short res; short arg; }; struct sConvertTypes { int i_typ; int o_typ; int p; int pl; }; #define jjWRONG 1 #define jjWRONG2 1 #define jjWRONG3 1 #define D(A) 2 #define NULL_VAL 0 #define IPARITH #define GENTABLE #define IPCONV #define IPASSIGN #include "table.h" const char * Tok2Cmdname(int tok) { if (tok < 0) { return cmds[0].name; } if (tok==COMMAND) return "command"; if (tok==ANY_TYPE) return "any_type"; if (tok==NONE) return "nothing"; //if (tok==IFBREAK) return "if_break"; //if (tok==VECTOR_FROM_POLYS) return "vector_from_polys"; //if (tok==ORDER_VECTOR) return "ordering"; //if (tok==REF_VAR) return "ref"; //if (tok==OBJECT) return "object"; //if (tok==PRINT_EXPR) return "print_expr"; if (tok==IDHDL) return "identifier"; #ifdef SINGULAR_4_1 if (tok==CRING_CMD) return "(c)ring"; #endif // we do not blackbox objects during table generation: //if (tok>MAX_TOK) return getBlackboxName(tok); int i = 0; while (cmds[i].tokval!=0) { if ((cmds[i].tokval == tok)&&(cmds[i].alias==0)) { return cmds[i].name; } i++; } i=0;// try again for old/alias names: while (cmds[i].tokval!=0) { if (cmds[i].tokval == tok) { return cmds[i].name; } i++; } #if 0 char *s=(char*)malloc(10); sprintf(s,"(%d)",tok); return s; #else return cmds[0].name; #endif } /*---------------------------------------------------------------------*/ /** * @brief compares to entry of cmdsname-list @param[in] a @param[in] b @return **/ /*---------------------------------------------------------------------*/ static int _gentable_sort_cmds( const void *a, const void *b ) { cmdnames *pCmdL = (cmdnames*)a; cmdnames *pCmdR = (cmdnames*)b; if(a==NULL || b==NULL) return 0; /* empty entries goes to the end of the list for later reuse */ if(pCmdL->name==NULL) return 1; if(pCmdR->name==NULL) return -1; /* $INVALID$ must come first */ if(strcmp(pCmdL->name, "$INVALID$")==0) return -1; if(strcmp(pCmdR->name, "$INVALID$")==0) return 1; /* tokval=-1 are reserved names at the end */ if (pCmdL->tokval==-1) { if (pCmdR->tokval==-1) return strcmp(pCmdL->name, pCmdR->name); /* pCmdL->tokval==-1, pCmdL goes at the end */ return 1; } /* pCmdR->tokval==-1, pCmdR goes at the end */ if(pCmdR->tokval==-1) return -1; return strcmp(pCmdL->name, pCmdR->name); } static int _texi_sort_cmds( const void *a, const void *b ) { cmdnames *pCmdL = (cmdnames*)a; cmdnames *pCmdR = (cmdnames*)b; if(a==NULL || b==NULL) return 0; /* empty entries goes to the end of the list for later reuse */ if(pCmdL->name==NULL) return 1; if(pCmdR->name==NULL) return -1; /* $INVALID$ must come first */ if(strcmp(pCmdL->name, "$INVALID$")==0) return -1; if(strcmp(pCmdR->name, "$INVALID$")==0) return 1; char *ls=strdup(pCmdL->name); char *rs=strdup(pCmdR->name); char *s=ls; while (*s) { *s=tolower(*s); s++; } s=rs; while (*s) { *s=tolower(*s); s++; } /* tokval=-1 are reserved names at the end */ if (pCmdL->tokval==-1) { if (pCmdR->tokval==-1) { int r=strcmp(ls,rs); free(ls); free(rs); return r; } /* pCmdL->tokval==-1, pCmdL goes at the end */ free(ls);free(rs); return 1; } /* pCmdR->tokval==-1, pCmdR goes at the end */ if(pCmdR->tokval==-1) { free(ls);free(rs);return -1;} { int r=strcmp(ls,rs); free(ls); free(rs); return r; } } /*generic*/ const char * iiTwoOps(int t) { if (t<127) { static char ch[2]; switch (t) { case '&': return "and"; case '|': return "or"; default: ch[0]=t; ch[1]='\0'; return ch; } } switch (t) { case COLONCOLON: return "::"; case DOTDOT: return ".."; //case PLUSEQUAL: return "+="; //case MINUSEQUAL: return "-="; case MINUSMINUS: return "--"; case PLUSPLUS: return "++"; case EQUAL_EQUAL: return "=="; case LE: return "<="; case GE: return ">="; case NOTEQUAL: return "<>"; default: return Tok2Cmdname(t); } } // // automatic conversions: // /*2 * try to convert 'inputType' in 'outputType' * return 0 on failure, an index (<>0) on success * GENTABLE variant! */ int iiTestConvert (int inputType, int outputType) { if ((inputType==outputType) || (outputType==DEF_CMD) || (outputType==IDHDL) || (outputType==ANY_TYPE)) { return -1; } // search the list int i=0; while (dConvertTypes[i].i_typ!=0) { if((dConvertTypes[i].i_typ==inputType) &&(dConvertTypes[i].o_typ==outputType)) { //Print("test convert %d to %d (%s -> %s):%d\n",inputType,outputType, //Tok2Cmdname(inputType), Tok2Cmdname(outputType),i+1); return i+1; } i++; } //Print("test convert %d to %d (%s -> %s):0\n",inputType,outputType, // Tok2Cmdname(inputType), Tok2Cmdname(outputType)); return 0; } char *iparith_inc; void ttGen1() { iparith_inc=strdup("iparith.xxxxxx"); int pid=getpid(); iparith_inc[8]=(pid %10)+'0'; pid/=10; iparith_inc[9]=(pid %10)+'0'; pid/=10; iparith_inc[10]=(pid %10)+'0'; pid/=10; iparith_inc[11]=(pid %10)+'0'; pid/=10; iparith_inc[12]=(pid %10)+'0'; pid/=10; iparith_inc[13]=(pid %10)+'0'; FILE *outfile = fopen(iparith_inc,"w"); int i,j,l1=0,l2=0; fprintf(outfile, "/****************************************\n" "* Computer Algebra System SINGULAR *\n" "****************************************/\n\n"); /*-------------------------------------------------------------------*/ fprintf(outfile,"// syntax table for Singular\n//\n"); fprintf(outfile,"// - search for an exact match of the argument types\n"); fprintf(outfile,"// - otherwise search for the first possibility\n"); fprintf(outfile,"// with converted types of the arguments\n"); fprintf(outfile,"// - otherwise report an error\n//\n"); int op; i=0; while ((op=dArith1[i].cmd)!=0) { if (dArith1[i].p==jjWRONG) fprintf(outfile,"// DUMMY "); const char *s = iiTwoOps(op); fprintf(outfile,"// operation: %s (%s) -> %s\n", s, Tok2Cmdname(dArith1[i].arg), Tok2Cmdname(dArith1[i].res)); if (RingDependend(dArith1[i].res) && (!RingDependend(dArith1[i].arg))) { fprintf(outfile,"// WARNING: %s requires currRing\n",s); } i++; } fprintf(outfile,"/*---------------------------------------------*/\n"); i=0; while ((op=dArith2[i].cmd)!=0) { if (dArith2[i].p==jjWRONG2) fprintf(outfile,"// DUMMY "); const char *s = iiTwoOps(op); fprintf(outfile,"// operation: %s (%s, %s) -> %s\n", s, Tok2Cmdname(dArith2[i].arg1), Tok2Cmdname(dArith2[i].arg2), Tok2Cmdname(dArith2[i].res)); if (RingDependend(dArith2[i].res) && (!RingDependend(dArith2[i].arg1)) && (!RingDependend(dArith2[i].arg2))) { fprintf(outfile,"// WARNING: %s requires currRing\n",s); } i++; } fprintf(outfile,"/*---------------------------------------------*/\n"); i=0; while ((op=dArith3[i].cmd)!=0) { const char *s = iiTwoOps(op); if (dArith3[i].p==jjWRONG3) fprintf(outfile,"// DUMMY "); fprintf(outfile,"// operation: %s (%s, %s, %s) -> %s\n", s, Tok2Cmdname(dArith3[i].arg1), Tok2Cmdname(dArith3[i].arg2), Tok2Cmdname(dArith3[i].arg3), Tok2Cmdname(dArith3[i].res)); if (RingDependend(dArith3[i].res) && (!RingDependend(dArith3[i].arg1)) && (!RingDependend(dArith3[i].arg2)) && (!RingDependend(dArith3[i].arg3))) { fprintf(outfile,"// WARNING: %s requires currRing\n",s); } i++; } fprintf(outfile,"/*---------------------------------------------*/\n"); i=0; while ((op=dArithM[i].cmd)!=0) { const char *s = iiTwoOps(op); fprintf(outfile,"// operation: %s (...) -> %s", s, Tok2Cmdname(dArithM[i].res)); switch(dArithM[i].number_of_args) { case -2: fprintf(outfile," ( number of arguments >0 )\n"); break; case -1: fprintf(outfile," ( any number of arguments )\n"); break; default: fprintf(outfile," ( %d arguments )\n",dArithM[i].number_of_args); break; } i++; } fprintf(outfile,"/*---------------------------------------------*/\n"); i=0; while ((op=dAssign[i].res)!=0) { fprintf(outfile,"// assign: %s = %s\n", Tok2Cmdname(op/*dAssign[i].res*/), Tok2Cmdname(dAssign[i].arg)); i++; } /*-------------------------------------------------------------------*/ fprintf(outfile,"/*---------------------------------------------*/\n"); FILE *doctable; if (produce_convert_table) { doctable=fopen("convert_table.texi","w"); fprintf(doctable,"@multitable @columnfractions .05 .18 .81\n"); } int doc_nr=1; for (j=257;j<=MAX_TOK+1;j++) { for(i=257;i<=MAX_TOK+1;i++) { if ((i!=j) && (j!=IDHDL) && (j!=DEF_CMD) && (j!=ANY_TYPE) && iiTestConvert(i,j)) { fprintf(outfile,"// convert %s -> %s\n", Tok2Cmdname(i), Tok2Cmdname(j)); if (produce_convert_table) { fprintf(doctable, "@item\n@ %d. @tab @code{%s} @tab @expansion{} @code{%s}\n", doc_nr,Tok2Cmdname(i),Tok2Cmdname(j)); doc_nr++; } if (j==ANY_TYPE) break; } } } if (produce_convert_table) { fprintf(doctable,"@end multitable\n"); fclose(doctable); } fprintf(outfile,"/*---------------------------------------------*/\n"); char ops[]="=><+*/[.^,%(;"; for(i=0;ops[i]!='\0';i++) fprintf(outfile,"// token %d : %c\n", (int)ops[i], ops[i]); for (i=257;i<=MAX_TOK;i++) { const char *s=iiTwoOps(i); if (s[0]!='$') { fprintf(outfile,"// token %d : %s\n", i, s); } } /*-------------------------------------------------------------------*/ fprintf(outfile,"/*--max. token: %d, gr: %d --*/\n",MAX_TOK,UMINUS); /*-------------------------------------------------------------------*/ fprintf(outfile,"/*---------------------------------------------*/\n"); fprintf(outfile, "struct sValCmdTab dArithTab1[]=\n" "{\n"); for (j=1;j<=MAX_TOK+1;j++) { for(i=0;dArith1[i].cmd!=0;i++) { if (dArith1[i].cmd==j) { fprintf(outfile," { %d,%d },\n",j,i); l1++; break; } } } fprintf(outfile," { 10000,0 }\n};\n"); fprintf(outfile,"#define JJTAB1LEN %d\n",l1); /*-------------------------------------------------------------------*/ fprintf(outfile, "struct sValCmdTab dArithTab2[]=\n" "{\n"); for (j=1;j<=MAX_TOK+1;j++) { for(i=0;dArith2[i].cmd!=0;i++) { if (dArith2[i].cmd==j) { fprintf(outfile," { %d,%d },\n",j,i); l2++; break; } } } fprintf(outfile," { 10000,0 }\n};\n"); fprintf(outfile,"#define JJTAB2LEN %d\n",l2); fclose(outfile); } /*---------------------------------------------------------------------*/ /** * @brief generate cmds initialisation **/ /*---------------------------------------------------------------------*/ void ttGen2b() { int cmd_size = (sizeof(cmds)/sizeof(cmdnames))-1; FILE *outfile = fopen(iparith_inc,"a"); fprintf(outfile, "/****************************************\n" "* Computer Algebra System SINGULAR *\n" "****************************************/\n\n"); /*-------------------------------------------------------------------*/ fprintf(outfile,"// identifier table for Singular\n//\n"); fprintf( outfile, "#ifdef MODULE_GENERATOR\n" "#define omAlloc0(A) malloc(A)\n" "#endif\n" "void iiInitCmdName()\n{\n" " sArithBase.nCmdUsed = 0;\n" " sArithBase.nCmdAllocated = %d;\n" " sArithBase.sCmds = (cmdnames*)omAlloc0(sArithBase.nCmdAllocated*sizeof(cmdnames));\n" "\n" " // name-string alias tokval toktype index\n", cmd_size); int m=0; int id_nr=0; qsort(&cmds, cmd_size, sizeof(cmdnames), (&_gentable_sort_cmds)); for(m=0; m0) id_nr++; fprintf(outfile," iiArithAddCmd(\"%s\", %*d, %3d, ",cmds[m].name, (int)(20-strlen(cmds[m].name)), cmds[m].alias, cmds[m].tokval); switch(cmds[m].toktype) { case CMD_1: fprintf(outfile,"CMD_1"); break; case CMD_2: fprintf(outfile,"CMD_2"); break; case CMD_3: fprintf(outfile,"CMD_3"); break; case CMD_12: fprintf(outfile,"CMD_12"); break; case CMD_123 : fprintf(outfile,"CMD_123"); break; case CMD_23: fprintf(outfile,"CMD_23"); break; case CMD_M: fprintf(outfile,"CMD_M"); break; case SYSVAR: fprintf(outfile,"SYSVAR"); break; case ROOT_DECL: fprintf(outfile,"ROOT_DECL"); break; case ROOT_DECL_LIST: fprintf(outfile,"ROOT_DECL_LIST"); break; case RING_DECL: fprintf(outfile,"RING_DECL"); break; case NONE: fprintf(outfile,"NONE"); break; default: if((cmds[m].toktype>' ') &&(cmds[m].toktype<127)) { fprintf(outfile,"'%c'",cmds[m].toktype); } else { fprintf(outfile,"%d",cmds[m].toktype); } break; #if 0 fprintf(outfile," iiArithAddCmd(\"%s\", %*d, -1, 0 );\n", cmds[m].name, 20-strlen(cmds[m].name), 0/*cmds[m].alias*/ /*-1 cmds[m].tokval*/ /*0 cmds[m].toktype*/); #endif } fprintf(outfile,", %d);\n", m); } fprintf(outfile, "/* end of list marker */\n"); fprintf(outfile, " sArithBase.nLastIdentifier = %d;\n", id_nr); fprintf(outfile, "}\n" "#define LAST_IDENTIFIER %d\n" ,id_nr); fclose(outfile); } int is_ref_cmd(cmdnames *c) { if( c->tokval==0) return 0; if (c->alias > 0) return 0; if ((c->toktype==CMD_1) || (c->toktype==CMD_2) || (c->toktype==CMD_3) || (c->toktype==CMD_M) || (c->toktype==CMD_12) || (c->toktype==CMD_13) || (c->toktype==CMD_23) || (c->toktype==CMD_123)) return 1; return 0; } void ttGen2c() { int cmd_size = (sizeof(cmds)/sizeof(cmdnames))-1; FILE *outfile = fopen("reference_table.texi","w"); fprintf(outfile, "@menu\n"); /*-------------------------------------------------------------------*/ qsort(&cmds, cmd_size, sizeof(cmdnames), (&_texi_sort_cmds)); int m; for(m=0; m0)&& (is_ref_cmd(&cmds[mm]))) mm--; if((mm>0)&& (is_ref_cmd(&cmds[mm]))) fprintf(outfile,"%s,",cmds[mm].name); else fprintf(outfile,","); // prev: mm=m+1; while((mm>0)&& (is_ref_cmd(&cmds[mm]))) mm++; if((mm>0)&& (is_ref_cmd(&cmds[mm]))) fprintf(outfile,"%s,",cmds[m-1].name); else fprintf(outfile,","); // up:, and header fprintf(outfile,"Functions\n" "@subsection %s\n" "@cindex %s\n",cmds[m].name,cmds[m].name); fprintf(outfile,"@include %s.part\n",cmds[m].name); char partName[50]; sprintf(partName,"%s.part",cmds[m].name); struct stat buf; if (lstat(partName,&buf)!=0) { int op,i; int only_field=0,only_comm=0,no_zerodiv=0; FILE *part=fopen(partName,"w"); fprintf(part,"@table @code\n@item @strong{Syntax:}\n"); if ((cmds[m].toktype==CMD_1) || (cmds[m].toktype==CMD_12) || (cmds[m].toktype==CMD_13) || (cmds[m].toktype==CMD_123)) { op= cmds[m].tokval; i=0; while ((dArith1[i].cmd!=op) && (dArith1[i].cmd!=0)) i++; while (dArith1[i].cmd==op) { if (dArith1[i].p!=jjWRONG) { fprintf(part,"@code{%s (} %s @code{)}\n",cmds[m].name,Tok2Cmdname(dArith1[i].arg)); fprintf(part,"@item @strong{Type:}\n%s\n",Tok2Cmdname(dArith1[i].res)); if ((dArith1[i].valid_for & ALLOW_PLURAL)==0) only_comm=1; if ((dArith1[i].valid_for & ALLOW_RING)==0) only_field=1; if ((dArith1[i].valid_for & ZERODIVISOR_MASK)==NO_ZERODIVISOR) no_zerodiv=1; } i++; } } if ((cmds[m].toktype==CMD_23) || (cmds[m].toktype==CMD_12) || (cmds[m].toktype==CMD_2) || (cmds[m].toktype==CMD_123)) { op= cmds[m].tokval; i=0; while ((dArith2[i].cmd!=op) && (dArith2[i].cmd!=0)) i++; while (dArith2[i].cmd==op) { if (dArith2[i].p!=jjWRONG) { fprintf(part,"@code{%s (} %s, %s @code{)}\n",cmds[m].name,Tok2Cmdname(dArith2[i].arg1),Tok2Cmdname(dArith2[i].arg2)); fprintf(part,"@item @strong{Type:}\n%s\n",Tok2Cmdname(dArith2[i].res)); if ((dArith2[i].valid_for & ALLOW_PLURAL)==0) only_comm=1; if ((dArith2[i].valid_for & ALLOW_RING)==0) only_field=1; if ((dArith2[i].valid_for & ZERODIVISOR_MASK)==NO_ZERODIVISOR) no_zerodiv=1; } i++; } } if ((cmds[m].toktype==CMD_23) || (cmds[m].toktype==CMD_13) || (cmds[m].toktype==CMD_3) || (cmds[m].toktype==CMD_123)) { op= cmds[m].tokval; i=0; while ((dArith3[i].cmd!=op) && (dArith3[i].cmd!=0)) i++; while (dArith3[i].cmd==op) { if (dArith3[i].p!=jjWRONG) { fprintf(part,"@code{%s (} %s, %s, %s @code{)}\n",cmds[m].name, Tok2Cmdname(dArith3[i].arg1), Tok2Cmdname(dArith3[i].arg2), Tok2Cmdname(dArith3[i].arg3)); fprintf(part,"@item @strong{Type:}\n%s\n",Tok2Cmdname(dArith3[i].res)); if ((dArith3[i].valid_for & ALLOW_PLURAL)==0) only_comm=1; if ((dArith3[i].valid_for & ALLOW_RING)==0) only_field=1; if ((dArith3[i].valid_for & ZERODIVISOR_MASK)==NO_ZERODIVISOR) no_zerodiv=1; } i++; } } if (cmds[m].toktype==CMD_M) { op= cmds[m].tokval; i=0; while ((dArithM[i].cmd!=op) && (dArithM[i].cmd!=0)) i++; while (dArithM[i].cmd==op) { if (dArithM[i].p!=jjWRONG) { fprintf(part,"@code{%s (} ... @code{)}\n",cmds[m].name); fprintf(part,"@item @strong{Type:}\n%s\n",Tok2Cmdname(dArithM[i].res)); if ((dArithM[i].valid_for & ALLOW_PLURAL)==0) only_comm=1; if ((dArithM[i].valid_for & ALLOW_RING)==0) only_field=1; if ((dArithM[i].valid_for & ZERODIVISOR_MASK)==NO_ZERODIVISOR) no_zerodiv=1; } i++; } } if (only_comm) fprintf(part,"@item @strong{Remark:}\n" "only for commutive polynomial rings\n"); if (only_field) fprintf(part,"@item @strong{Remark:}\n" "only for polynomial rings over fields\n"); if (no_zerodiv) fprintf(part,"@item @strong{Remark:}\n" "only for polynomial rings over domains\n"); fprintf(part,"@item @strong{Purpose:}\n" "@item @strong{Example:}\n" "@smallexample\n" "@c example\n" "@c example\n" "@end smallexample\n" "@c ref\n" "@c See\n" "@c ref{....};\n" "@c ref{....}.\n" "@c ref\n"); fclose(part); } } } fclose(outfile); } /*-------------------------------------------------------------------*/ void ttGen4() { FILE *outfile = fopen("plural_cmd.xx","w"); int i; const char *old_s=""; fprintf(outfile, "@c *****************************************\n" "@c * Computer Algebra System SINGULAR *\n" "@c *****************************************\n\n"); /*-------------------------------------------------------------------*/ fprintf(outfile,"@multicolumn .45 .45\n"); int op; i=0; while ((op=dArith1[i].cmd)!=0) { if (dArith1[i].p!=jjWRONG) { const char *s = iiTwoOps(op); if ((s!=NULL) && (isalpha(s[0])) && (strcmp(s,old_s)!=0)) { old_s=s; #ifdef HAVE_PLURAL switch (dArith1[i].valid_for & PLURAL_MASK) { case NO_PLURAL: fprintf(outfile,"@item @ref{%s} @tab @code{---}\n",s); break; case ALLOW_PLURAL: fprintf(outfile,"@item @ref{%s} @tab @ref{%s (plural)}\n",s,s); break; case COMM_PLURAL: fprintf(outfile,"@item @ref{%s} @tab %s\n",s,s); break; } #endif #ifdef HAVE_RINGS #endif } } i++; } fprintf(outfile,"@c ---------------------------------------------\n"); i=0; while ((op=dArith2[i].cmd)!=0) { if (dArith2[i].p!=jjWRONG2) { const char *s = iiTwoOps(op); if ((s!=NULL) && (isalpha(s[0])) && (strcmp(s,old_s)!=0)) { old_s=s; #ifdef HAVE_PLURAL switch (dArith2[i].valid_for & PLURAL_MASK) { case NO_PLURAL: fprintf(outfile,"@item @ref{%s} @tab @code{---}\n",s); break; case ALLOW_PLURAL: fprintf(outfile,"@item @ref{%s} @tab @ref{%s (plural)}\n",s,s); break; case COMM_PLURAL: fprintf(outfile,"@item @ref{%s} @tab %s\n",s,s); break; } #endif #ifdef HAVE_RINGS #endif } } i++; } fprintf(outfile,"@c ---------------------------------------------\n"); i=0; while ((op=dArith3[i].cmd)!=0) { const char *s = iiTwoOps(op); if (dArith3[i].p!=jjWRONG3) { if ((s!=NULL) && (isalpha(s[0])) && (strcmp(s,old_s)!=0)) { old_s=s; #ifdef HAVE_PLURAL switch (dArith3[i].valid_for & PLURAL_MASK) { case NO_PLURAL: fprintf(outfile,"@item @ref{%s} @tab @code{---}\n",s); break; case ALLOW_PLURAL: fprintf(outfile,"@item @ref{%s} @tab @ref{%s (plural)}\n",s,s); break; case COMM_PLURAL: fprintf(outfile,"@item @ref{%s} @tab %s\n",s,s); break; } #endif #ifdef HAVE_RINGS #endif } } i++; } fprintf(outfile,"@c ---------------------------------------------\n"); i=0; while ((op=dArithM[i].cmd)!=0) { const char *s = iiTwoOps(op); if ((s!=NULL) && (isalpha(s[0])) && (strcmp(s,old_s)!=0)) { old_s=s; #ifdef HAVE_PLURAL switch (dArithM[i].valid_for & PLURAL_MASK) { case NO_PLURAL: fprintf(outfile,"@item @ref{%s} @tab @code{---}\n",s); break; case ALLOW_PLURAL: fprintf(outfile,"@item @ref{%s} @tab @ref{%s (plural)}\n",s,s); break; case COMM_PLURAL: fprintf(outfile,"@item @ref{%s} @tab %s\n",s,s); break; } #endif #ifdef HAVE_RINGS #endif } i++; } fprintf(outfile,"@c ---------------------------------------------\n"); fprintf(outfile,"@end table\n"); fclose(outfile); rename("plural_cmd.xx","plural_cmd.inc"); } /*-------------------------------------------------------------------*/ int main(int argc, char** argv) { if (argc>1) { produce_convert_table=1; /* for ttGen1 */ ttGen1(); unlink(iparith_inc); ttGen4(); ttGen2c(); } else { ttGen1(); ttGen2b(); rename(iparith_inc,"iparith.inc"); } return 0; } singular-4.0.3+ds/Singular/gms.cc000066400000000000000000000057201266270727000166420ustar00rootroot00000000000000/***************************************** * Computer Algebra System SINGULAR * *****************************************/ /* * ABSTRACT: Gauss-Manin system normal form */ #include #ifdef HAVE_GMS #include "gms.h" #include #include #include "ipid.h" lists gmsNF(ideal p,ideal g,matrix B,int D,int K) { ideal r=idInit(IDELEMS(p),1); ideal q=idInit(IDELEMS(p),1); matrix B0=mpNew(MATROWS(B),MATCOLS(B)); for(int i=1;i<=MATROWS(B0);i++) for(int j=1;j<=MATCOLS(B0);j++) if(MATELEM(B,i,j)!=NULL) MATELEM(B0,i,j)=pDiff(MATELEM(B,i,j),i+1); for(int k=0;km[k]!=NULL&&pGetExp(p->m[k],1)<=K) { int j=0; while(jm[j],p->m[k])) j++; if(jm[k]),pHead(g->m[j])); p->m[k]=pSub(p->m[k],ppMult_mm(g->m[j],m)); pIncrExp(m,1); pSetm(m); for(int i=0;im[k]=pAdd(p->m[k],ppMult_mm(MATELEM(B0,i+1,j+1),m)); if(MATELEM(B,i+1,j+1)!=NULL&&m0!=NULL) p->m[k]=pAdd(p->m[k],ppMult_mm(MATELEM(B,i+1,j+1),m0)); pDelete(&m0); } pDelete(&m); } else { poly p0=p->m[k]; pIter(p->m[k]); pNext(p0)=NULL; r->m[k]=pAdd(r->m[k],p0); } while(p->m[k]!=NULL&&pGetExp(p->m[k],1)<=K&&pWTotaldegree(p->m[k])>D) { int i=pGetExp(p->m[k],1); do { poly p0=p->m[k]; pIter(p->m[k]); pNext(p0)=NULL; q->m[k]=pAdd(q->m[k],p0); }while(p->m[k]!=NULL&&pGetExp(p->m[k],1)==i); } pNormalize(p->m[k]); } q->m[k]=pAdd(q->m[k],p->m[k]); p->m[k]=NULL; } idDelete(&p); idDelete((ideal *)&B0); id_Normalize(r, currRing); id_Normalize(q, currRing); lists l=(lists)omAllocBin(slists_bin); l->Init(2); l->m[0].rtyp=IDEAL_CMD; l->m[0].data=r; l->m[1].rtyp=IDEAL_CMD; l->m[1].data=q; return l; } BOOLEAN gmsNF(leftv res,leftv h) { if(currRingHdl) { if(h&&h->Typ()==IDEAL_CMD) { ideal p=(ideal)h->CopyD(); h=h->next; if(h&&h->Typ()==IDEAL_CMD) { ideal g=(ideal)h->Data(); h=h->next; if(h&&h->Typ()==MATRIX_CMD) { matrix B=(matrix)h->Data(); h=h->next; if(h&&h->Typ()==INT_CMD) { int D=(int)(long)h->Data(); h=h->next; if(h&&h->Typ()==INT_CMD) { int K=(int)(long)h->Data(); res->rtyp=LIST_CMD; res->data=(void *)gmsNF(p,g,B,D,K); return FALSE; } } } } } WerrorS(",,,, expected"); return TRUE; } WerrorS("no ring active"); return TRUE; } #endif /* HAVE_GMS */ singular-4.0.3+ds/Singular/gms.h000066400000000000000000000007071266270727000165040ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: Gauss-Manin system normal form */ #ifndef GMS_H #define GMS_H #include #include #include #include #include lists gmsNF(ideal p, ideal g, matrix B, int D, int K); BOOLEAN gmsNF(leftv res, leftv h); #endif /* GMS_H */ singular-4.0.3+ds/Singular/grammar.cc000066400000000000000000004555201266270727000175110ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.4.3. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 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 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* 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.4.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ #line 7 "grammar.y" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if 0 void debug_list(leftv v) { idhdl r=basePackHdl; idhdl h; BOOLEAN found=FALSE; const char *nn=v->name; h=IDROOT->get(nn,myynest); if (h!=NULL) { Print("Curr::%s, (%s)\n",nn,Tok2Cmdname((int)IDTYP(h))); found=TRUE; } else Print("`%s` not found in IDROOT\n",nn); while (r!=NULL) { if ((IDTYP(r)==PACKAGE_CMD) || (IDTYP(r)==RING_CMD) || (IDTYP(r)==QRING_CMD)) { h=IDPACKAGE(r)->idroot->get(nn,myynest); if (h!=NULL) { Print("%s::%s, (%s)\n",r->id,nn,Tok2Cmdname((int)IDTYP(h))); found=TRUE; } else Print("%s::%s not found\n",r->id,nn); } if (r==basePackHdl) r=IDPACKAGE(r)->idroot; r=r->next; if (r==basePackHdl) break; } if (!found) { listall(TRUE); } } #endif /* From the bison docu: By defining the macro `YYMAXDEPTH', you can control how deep the parser stack can become before a stack overflow occurs. Define the macro with a value that is an integer. This value is the maximum number of tokens that can be shifted (and not reduced) before overflow. It must be a constant expression whose value is known at compile time. The stack space allowed is not necessarily allocated. If you specify a large value for `YYMAXDEPTH', the parser actually allocates a small stack at first, and then makes it bigger by stages as needed. This increasing allocation happens automatically and silently. Therefore, you do not need to make `YYMAXDEPTH' painfully small merely to save space for ordinary inputs that do not need much stack. The default value of `YYMAXDEPTH', if you do not define it, is 10000. */ #define YYMAXDEPTH MAX_INT_VAL extern int yylineno; extern FILE* yyin; const char * currid; BOOLEAN yyInRingConstruction=FALSE; BOOLEAN expected_parms; int cmdtok; int inerror = 0; #define TESTSETINT(a,i) \ if ((a).Typ() != INT_CMD) \ { \ WerrorS("no int expression"); \ YYERROR; \ } \ (i) = (int)((long)(a).Data());(a).CleanUp() #define MYYERROR(a) { WerrorS(a); YYERROR; } void yyerror(const char * fmt) { BOOLEAN old_errorreported=errorreported; errorreported = TRUE; if (currid!=NULL) { killid(currid,&IDROOT); currid = NULL; } if(inerror==0) { { if ((strlen(fmt)>1) && (strncmp(fmt,"parse",5)!=0) && (strncmp(fmt,"syntax",6)!=0)) WerrorS(fmt); Werror( "error occurred in or before %s line %d: `%s`" ,VoiceName(), yylineno, my_yylinebuf); } if (cmdtok!=0) { const char *s=Tok2Cmdname(cmdtok); if (expected_parms) { Werror("expected %s-expression. type \'help %s;\'",s,s); } else { Werror("wrong type declaration. type \'help %s;\'",s); } } if (!old_errorreported && (lastreserved!=NULL)) { Werror("last reserved name was `%s`",lastreserved); } inerror=1; } if ((currentVoice!=NULL) && (currentVoice->prev!=NULL) && (myynest>0) #ifdef HAVE_SDB && ((sdb_flags &1)==0) #endif ) { Werror("leaving %s",VoiceName()); } } /* Line 189 of yacc.c */ #line 242 "grammar.cc" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 1 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { DOTDOT = 258, EQUAL_EQUAL = 259, GE = 260, LE = 261, MINUSMINUS = 262, NOT = 263, NOTEQUAL = 264, PLUSPLUS = 265, COLONCOLON = 266, ARROW = 267, GRING_CMD = 268, BIGINTMAT_CMD = 269, INTMAT_CMD = 270, PROC_CMD = 271, RING_CMD = 272, BEGIN_RING = 273, IDEAL_CMD = 274, MAP_CMD = 275, MATRIX_CMD = 276, MODUL_CMD = 277, NUMBER_CMD = 278, POLY_CMD = 279, RESOLUTION_CMD = 280, VECTOR_CMD = 281, BETTI_CMD = 282, COEFFS_CMD = 283, COEF_CMD = 284, CONTRACT_CMD = 285, DEGREE_CMD = 286, DEG_CMD = 287, DIFF_CMD = 288, DIM_CMD = 289, DIVISION_CMD = 290, ELIMINATION_CMD = 291, E_CMD = 292, FAREY_CMD = 293, FETCH_CMD = 294, FREEMODULE_CMD = 295, KEEPRING_CMD = 296, HILBERT_CMD = 297, HOMOG_CMD = 298, IMAP_CMD = 299, INDEPSET_CMD = 300, INTERRED_CMD = 301, INTERSECT_CMD = 302, JACOB_CMD = 303, JET_CMD = 304, KBASE_CMD = 305, KOSZUL_CMD = 306, LEADCOEF_CMD = 307, LEADEXP_CMD = 308, LEAD_CMD = 309, LEADMONOM_CMD = 310, LIFTSTD_CMD = 311, LIFT_CMD = 312, MAXID_CMD = 313, MINBASE_CMD = 314, MINOR_CMD = 315, MINRES_CMD = 316, MODULO_CMD = 317, MONOM_CMD = 318, MRES_CMD = 319, MULTIPLICITY_CMD = 320, ORD_CMD = 321, PAR_CMD = 322, PARDEG_CMD = 323, PREIMAGE_CMD = 324, QUOTIENT_CMD = 325, QHWEIGHT_CMD = 326, REDUCE_CMD = 327, REGULARITY_CMD = 328, RES_CMD = 329, SBA_CMD = 330, SIMPLIFY_CMD = 331, SORTVEC_CMD = 332, SRES_CMD = 333, STD_CMD = 334, SUBST_CMD = 335, SYZYGY_CMD = 336, VAR_CMD = 337, VDIM_CMD = 338, WEDGE_CMD = 339, WEIGHT_CMD = 340, VALTVARS = 341, VMAXDEG = 342, VMAXMULT = 343, VNOETHER = 344, VMINPOLY = 345, END_RING = 346, CMD_1 = 347, CMD_2 = 348, CMD_3 = 349, CMD_12 = 350, CMD_13 = 351, CMD_23 = 352, CMD_123 = 353, CMD_M = 354, ROOT_DECL = 355, ROOT_DECL_LIST = 356, RING_DECL = 357, RING_DECL_LIST = 358, EXAMPLE_CMD = 359, EXPORT_CMD = 360, HELP_CMD = 361, KILL_CMD = 362, LIB_CMD = 363, LISTVAR_CMD = 364, SETRING_CMD = 365, TYPE_CMD = 366, STRINGTOK = 367, BLOCKTOK = 368, INT_CONST = 369, UNKNOWN_IDENT = 370, RINGVAR = 371, PROC_DEF = 372, APPLY = 373, ASSUME_CMD = 374, BREAK_CMD = 375, CONTINUE_CMD = 376, ELSE_CMD = 377, EVAL = 378, QUOTE = 379, FOR_CMD = 380, IF_CMD = 381, SYS_BREAK = 382, WHILE_CMD = 383, RETURN = 384, PARAMETER = 385, SYSVAR = 386, UMINUS = 387 }; #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif /* Copy the second part of user declarations. */ /* Line 264 of yacc.c */ #line 415 "grammar.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 defined YYENABLE_NLS && 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 yyi) #else static int YYID (yyi) int yyi; #endif { return yyi; } #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_alloc; YYSTYPE yyvs_alloc; }; /* 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_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 2531 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 150 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 45 /* YYNRULES -- Number of rules. */ #define YYNRULES 174 /* YYNRULES -- Number of states. */ #define YYNSTATES 396 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 387 #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, 143, 2, 146, 147, 2, 135, 141, 136, 148, 137, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 144, 142, 133, 132, 134, 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, 138, 2, 139, 140, 2, 149, 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, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 145 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 4, 7, 9, 12, 15, 17, 19, 21, 24, 26, 28, 30, 32, 34, 36, 38, 40, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 64, 66, 68, 72, 76, 80, 85, 89, 91, 93, 95, 100, 105, 110, 114, 119, 124, 128, 133, 138, 143, 148, 155, 162, 169, 176, 185, 194, 203, 212, 216, 221, 230, 235, 244, 249, 253, 257, 259, 261, 263, 267, 274, 279, 286, 293, 300, 307, 314, 321, 325, 331, 337, 338, 344, 347, 350, 352, 355, 358, 362, 366, 370, 374, 378, 382, 386, 390, 394, 398, 401, 404, 407, 410, 412, 416, 419, 422, 425, 428, 437, 440, 444, 447, 449, 451, 457, 459, 461, 466, 468, 472, 474, 478, 480, 482, 484, 486, 487, 492, 496, 499, 503, 506, 509, 513, 518, 523, 528, 533, 538, 543, 548, 553, 560, 567, 574, 581, 588, 595, 602, 606, 608, 617, 620, 625, 628, 630, 632, 635, 638, 640, 646, 649, 655, 657, 659, 663, 669, 673, 677, 682, 685, 688, 693 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { 151, 0, -1, -1, 151, 152, -1, 153, -1, 155, 142, -1, 167, 142, -1, 194, -1, 127, -1, 142, -1, 1, 142, -1, 189, -1, 190, -1, 154, -1, 191, -1, 192, -1, 176, -1, 178, -1, 179, -1, 104, 113, -1, 156, -1, 180, -1, 181, -1, 182, -1, 193, -1, 184, -1, 185, -1, 187, -1, 188, -1, 165, 158, -1, 116, -1, 166, -1, 157, 11, 157, -1, 159, 148, 157, -1, 157, 146, 147, -1, 157, 146, 158, 147, -1, 138, 158, 139, -1, 114, -1, 131, -1, 168, -1, 16, 146, 159, 147, -1, 100, 146, 159, 147, -1, 101, 146, 158, 147, -1, 101, 146, 147, -1, 102, 146, 159, 147, -1, 103, 146, 158, 147, -1, 103, 146, 147, -1, 92, 146, 159, 147, -1, 95, 146, 159, 147, -1, 96, 146, 159, 147, -1, 98, 146, 159, 147, -1, 93, 146, 159, 141, 159, 147, -1, 95, 146, 159, 141, 159, 147, -1, 97, 146, 159, 141, 159, 147, -1, 98, 146, 159, 141, 159, 147, -1, 94, 146, 159, 141, 159, 141, 159, 147, -1, 96, 146, 159, 141, 159, 141, 159, 147, -1, 97, 146, 159, 141, 159, 141, 159, 147, -1, 98, 146, 159, 141, 159, 141, 159, 147, -1, 99, 146, 147, -1, 99, 146, 158, 147, -1, 175, 146, 159, 141, 159, 141, 159, 147, -1, 175, 146, 159, 147, -1, 17, 146, 169, 141, 169, 141, 173, 147, -1, 17, 146, 159, 147, -1, 166, 12, 113, -1, 158, 141, 159, -1, 159, -1, 164, -1, 157, -1, 146, 158, 147, -1, 159, 138, 159, 141, 159, 139, -1, 159, 138, 159, 139, -1, 118, 146, 159, 141, 92, 147, -1, 118, 146, 159, 141, 95, 147, -1, 118, 146, 159, 141, 96, 147, -1, 118, 146, 159, 141, 98, 147, -1, 118, 146, 159, 141, 99, 147, -1, 118, 146, 159, 141, 159, 147, -1, 161, 159, 163, -1, 161, 159, 132, 159, 163, -1, 162, 159, 141, 159, 163, -1, -1, 123, 146, 160, 159, 147, -1, 124, 146, -1, 119, 146, -1, 147, -1, 159, 10, -1, 159, 7, -1, 159, 135, 159, -1, 159, 136, 159, -1, 159, 137, 159, -1, 159, 140, 159, -1, 159, 133, 159, -1, 159, 143, 159, -1, 159, 9, 159, -1, 159, 4, 159, -1, 159, 3, 159, -1, 159, 144, 159, -1, 8, 159, -1, 136, 159, -1, 167, 174, -1, 158, 132, -1, 115, -1, 149, 159, 149, -1, 100, 157, -1, 101, 157, -1, 102, 157, -1, 103, 157, -1, 175, 157, 138, 159, 139, 138, 159, 139, -1, 175, 157, -1, 167, 141, 157, -1, 16, 157, -1, 112, -1, 159, -1, 146, 159, 141, 158, 147, -1, 115, -1, 170, -1, 170, 146, 158, 147, -1, 171, -1, 171, 141, 172, -1, 171, -1, 146, 172, 147, -1, 132, -1, 21, -1, 15, -1, 14, -1, -1, 133, 168, 177, 142, -1, 106, 112, 142, -1, 106, 142, -1, 104, 112, 142, -1, 105, 158, -1, 107, 157, -1, 181, 141, 157, -1, 109, 146, 100, 147, -1, 109, 146, 101, 147, -1, 109, 146, 102, 147, -1, 109, 146, 103, 147, -1, 109, 146, 17, 147, -1, 109, 146, 175, 147, -1, 109, 146, 16, 147, -1, 109, 146, 157, 147, -1, 109, 146, 157, 141, 100, 147, -1, 109, 146, 157, 141, 101, 147, -1, 109, 146, 157, 141, 102, 147, -1, 109, 146, 157, 141, 103, 147, -1, 109, 146, 157, 141, 17, 147, -1, 109, 146, 157, 141, 175, 147, -1, 109, 146, 157, 141, 16, 147, -1, 109, 146, 147, -1, 17, -1, 183, 157, 174, 169, 141, 169, 141, 173, -1, 183, 157, -1, 183, 157, 174, 157, -1, 131, 168, -1, 110, -1, 41, -1, 186, 159, -1, 111, 159, -1, 158, -1, 126, 146, 159, 147, 113, -1, 122, 113, -1, 126, 146, 159, 147, 120, -1, 120, -1, 121, -1, 128, 112, 113, -1, 125, 112, 112, 112, 113, -1, 16, 166, 113, -1, 117, 112, 113, -1, 117, 112, 112, 113, -1, 130, 167, -1, 130, 159, -1, 129, 146, 158, 147, -1, 129, 146, 147, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 363, 363, 365, 399, 400, 402, 404, 408, 413, 415, 466, 467, 468, 469, 470, 471, 472, 473, 477, 480, 481, 482, 483, 484, 485, 486, 487, 488, 491, 498, 503, 507, 511, 515, 519, 532, 560, 584, 590, 596, 600, 604, 608, 612, 616, 620, 624, 628, 632, 636, 640, 644, 648, 652, 656, 660, 664, 668, 672, 676, 682, 686, 690, 694, 698, 705, 716, 722, 727, 728, 729, 733, 737, 741, 745, 749, 753, 757, 761, 765, 782, 789, 788, 806, 814, 822, 831, 835, 839, 843, 847, 851, 855, 859, 863, 867, 871, 875, 879, 891, 898, 899, 918, 919, 931, 936, 941, 945, 949, 985, 1011, 1032, 1040, 1044, 1045, 1059, 1067, 1076, 1121, 1122, 1131, 1132, 1138, 1145, 1147, 1149, 1159, 1158, 1166, 1171, 1178, 1186, 1198, 1214, 1233, 1237, 1241, 1246, 1250, 1254, 1258, 1262, 1267, 1273, 1279, 1285, 1291, 1297, 1303, 1315, 1322, 1326, 1363, 1370, 1378, 1384, 1384, 1387, 1459, 1463, 1492, 1505, 1522, 1531, 1536, 1544, 1556, 1575, 1585, 1604, 1627, 1633, 1645, 1651 }; #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", "DOTDOT", "EQUAL_EQUAL", "GE", "LE", "MINUSMINUS", "NOT", "NOTEQUAL", "PLUSPLUS", "COLONCOLON", "ARROW", "GRING_CMD", "BIGINTMAT_CMD", "INTMAT_CMD", "PROC_CMD", "RING_CMD", "BEGIN_RING", "IDEAL_CMD", "MAP_CMD", "MATRIX_CMD", "MODUL_CMD", "NUMBER_CMD", "POLY_CMD", "RESOLUTION_CMD", "VECTOR_CMD", "BETTI_CMD", "COEFFS_CMD", "COEF_CMD", "CONTRACT_CMD", "DEGREE_CMD", "DEG_CMD", "DIFF_CMD", "DIM_CMD", "DIVISION_CMD", "ELIMINATION_CMD", "E_CMD", "FAREY_CMD", "FETCH_CMD", "FREEMODULE_CMD", "KEEPRING_CMD", "HILBERT_CMD", "HOMOG_CMD", "IMAP_CMD", "INDEPSET_CMD", "INTERRED_CMD", "INTERSECT_CMD", "JACOB_CMD", "JET_CMD", "KBASE_CMD", "KOSZUL_CMD", "LEADCOEF_CMD", "LEADEXP_CMD", "LEAD_CMD", "LEADMONOM_CMD", "LIFTSTD_CMD", "LIFT_CMD", "MAXID_CMD", "MINBASE_CMD", "MINOR_CMD", "MINRES_CMD", "MODULO_CMD", "MONOM_CMD", "MRES_CMD", "MULTIPLICITY_CMD", "ORD_CMD", "PAR_CMD", "PARDEG_CMD", "PREIMAGE_CMD", "QUOTIENT_CMD", "QHWEIGHT_CMD", "REDUCE_CMD", "REGULARITY_CMD", "RES_CMD", "SBA_CMD", "SIMPLIFY_CMD", "SORTVEC_CMD", "SRES_CMD", "STD_CMD", "SUBST_CMD", "SYZYGY_CMD", "VAR_CMD", "VDIM_CMD", "WEDGE_CMD", "WEIGHT_CMD", "VALTVARS", "VMAXDEG", "VMAXMULT", "VNOETHER", "VMINPOLY", "END_RING", "CMD_1", "CMD_2", "CMD_3", "CMD_12", "CMD_13", "CMD_23", "CMD_123", "CMD_M", "ROOT_DECL", "ROOT_DECL_LIST", "RING_DECL", "RING_DECL_LIST", "EXAMPLE_CMD", "EXPORT_CMD", "HELP_CMD", "KILL_CMD", "LIB_CMD", "LISTVAR_CMD", "SETRING_CMD", "TYPE_CMD", "STRINGTOK", "BLOCKTOK", "INT_CONST", "UNKNOWN_IDENT", "RINGVAR", "PROC_DEF", "APPLY", "ASSUME_CMD", "BREAK_CMD", "CONTINUE_CMD", "ELSE_CMD", "EVAL", "QUOTE", "FOR_CMD", "IF_CMD", "SYS_BREAK", "WHILE_CMD", "RETURN", "PARAMETER", "SYSVAR", "'='", "'<'", "'>'", "'+'", "'-'", "'/'", "'['", "']'", "'^'", "','", "';'", "'&'", "':'", "UMINUS", "'('", "')'", "'.'", "'`'", "$accept", "lines", "pprompt", "flowctrl", "example_dummy", "command", "assign", "elemexpr", "exprlist", "expr", "$@1", "quote_start", "assume_start", "quote_end", "expr_arithmetic", "left_value", "extendedid", "declare_ip_variable", "stringexpr", "rlist", "ordername", "orderelem", "OrderingList", "ordering", "cmdeq", "mat_cmd", "filecmd", "$@2", "helpcmd", "examplecmd", "exportcmd", "killcmd", "listcmd", "ringcmd1", "ringcmd", "scriptcmd", "setrings", "setringcmd", "typecmd", "ifcmd", "whilecmd", "forcmd", "proccmd", "parametercmd", "returncmd", 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, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 61, 60, 62, 43, 45, 47, 91, 93, 94, 44, 59, 38, 58, 387, 40, 41, 46, 96 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 150, 151, 151, 152, 152, 152, 152, 152, 152, 152, 153, 153, 153, 153, 153, 153, 153, 153, 154, 155, 155, 155, 155, 155, 155, 155, 155, 155, 156, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 158, 158, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 160, 159, 161, 162, 163, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 165, 165, 166, 166, 167, 167, 167, 167, 167, 167, 167, 167, 168, 169, 169, 170, 171, 171, 172, 172, 173, 173, 174, 175, 175, 175, 177, 176, 178, 178, 179, 180, 181, 181, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 183, 184, 184, 184, 185, 186, 186, 187, 188, 188, 189, 189, 189, 189, 189, 190, 191, 192, 192, 192, 193, 193, 194, 194 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 2, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 3, 3, 4, 3, 1, 1, 1, 4, 4, 4, 3, 4, 4, 3, 4, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 8, 3, 4, 8, 4, 8, 4, 3, 3, 1, 1, 1, 3, 6, 4, 6, 6, 6, 6, 6, 6, 3, 5, 5, 0, 5, 2, 2, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 8, 2, 3, 2, 1, 1, 5, 1, 1, 4, 1, 3, 1, 3, 1, 1, 1, 1, 0, 4, 3, 2, 3, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 3, 1, 8, 2, 4, 2, 1, 1, 2, 2, 1, 5, 2, 5, 1, 1, 3, 5, 3, 3, 4, 2, 2, 4, 3 }; /* 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[] = { 2, 0, 1, 0, 0, 126, 125, 0, 151, 124, 157, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 113, 37, 103, 30, 0, 0, 0, 164, 165, 0, 0, 0, 0, 0, 8, 0, 0, 0, 38, 0, 0, 0, 9, 0, 0, 3, 4, 13, 0, 20, 69, 160, 67, 0, 0, 68, 0, 31, 0, 39, 0, 16, 17, 18, 21, 22, 23, 0, 25, 26, 0, 27, 28, 11, 12, 14, 15, 24, 7, 10, 0, 0, 0, 0, 0, 0, 38, 99, 0, 0, 69, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 69, 0, 69, 0, 69, 0, 19, 132, 0, 130, 69, 0, 159, 0, 0, 85, 162, 82, 84, 0, 0, 0, 0, 0, 172, 171, 155, 127, 100, 0, 0, 0, 5, 0, 0, 102, 0, 0, 0, 88, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 123, 0, 6, 101, 0, 69, 0, 69, 158, 0, 0, 0, 0, 0, 0, 67, 168, 0, 114, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 67, 43, 0, 67, 46, 0, 131, 129, 0, 0, 0, 0, 0, 0, 150, 69, 0, 0, 169, 0, 0, 0, 0, 166, 174, 0, 0, 36, 70, 104, 32, 34, 0, 66, 97, 96, 95, 93, 89, 90, 91, 0, 92, 94, 98, 33, 0, 86, 79, 0, 65, 69, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 40, 67, 64, 0, 47, 0, 0, 0, 48, 0, 49, 0, 0, 50, 60, 41, 42, 44, 45, 141, 139, 135, 136, 137, 138, 0, 142, 140, 170, 0, 0, 0, 0, 173, 128, 35, 72, 0, 0, 0, 0, 62, 0, 69, 114, 0, 42, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 167, 161, 163, 0, 80, 81, 0, 0, 0, 0, 0, 51, 0, 52, 0, 0, 53, 0, 54, 149, 147, 143, 144, 145, 146, 148, 73, 74, 75, 76, 77, 78, 71, 0, 0, 0, 115, 116, 0, 117, 121, 0, 0, 0, 0, 0, 0, 0, 0, 119, 0, 0, 63, 55, 56, 57, 58, 61, 109, 152, 0, 122, 0, 120, 118 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 1, 55, 56, 57, 58, 59, 60, 145, 62, 219, 63, 64, 247, 65, 66, 67, 68, 69, 189, 370, 371, 381, 372, 173, 98, 71, 225, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -363 static const yytype_int16 yypact[] = { -363, 326, -363, -129, 1852, -363, -363, 1910, -95, -363, -363, -75, -67, -58, -42, -37, -30, -25, -13, 1970, 2028, 2088, 2146, -87, 1852, -104, 1852, -5, -363, 1852, -363, -363, -363, -363, -71, 20, 29, -363, -363, 58, 39, 77, -68, 83, -363, 130, 98, 2206, 137, 137, 1852, 1852, -363, 1852, 1852, -363, -363, -363, 112, -363, 35, -111, 1335, 1852, 1852, -363, 1852, 247, -122, -363, 2264, -363, -363, -363, -363, 131, -363, 1852, -363, -363, 1852, -363, -363, -363, -363, -363, -363, -363, -363, -363, 127, -95, 129, 132, 133, 134, -363, 30, 135, 1852, 359, 1335, -8, 2324, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1498, 1852, 375, 1556, 405, 1852, 447, 1616, 469, 140, -363, 142, 143, -363, 92, 1674, 1335, -53, 1852, -363, -363, -363, -363, 172, 1852, 174, 1734, 1910, 1335, 147, -363, -363, 30, -52, -105, 120, -363, 1852, 1792, -363, 1852, 1852, 1852, -363, 1852, -363, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 1852, 236, 531, 142, 176, -363, 1852, -363, -363, 1852, 220, 1852, 72, 1335, 1852, 1852, 1556, 1852, 1616, 1852, 545, -363, 1852, 561, 149, 577, 593, 735, 2, 267, 749, 341, -363, -102, 763, -363, -98, 779, -363, -93, -363, -363, -55, -50, -46, -39, -32, -27, -363, 74, -15, 178, -363, 795, 1852, 180, 809, -363, -363, -85, 152, -363, -363, -363, -363, -363, -69, 1335, 1349, 1389, 1389, 169, 25, 25, 30, 54, 21, 1363, 25, -363, 1852, -363, -363, 1852, -363, 622, 483, 1852, 95, 2324, 545, 763, -66, 779, -65, 483, -363, 825, -363, 2324, -363, 1852, 1852, 1852, -363, 1852, -363, 1852, 1852, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, 1012, -363, -363, -363, 2382, 839, 182, -86, -363, -363, -363, -363, 1852, 855, 855, 1852, -363, 997, 42, 1335, 156, -363, -363, 1852, 157, 1011, 1027, 1041, 1057, 499, 515, 154, 163, 164, 175, 177, 181, 183, 70, 79, 101, 105, 115, 1071, -363, -363, -363, -363, 1087, -363, -363, 1101, 161, 2324, -61, -113, -363, 1852, -363, 1852, 1852, -363, 1852, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, 1852, 1852, 162, -363, -363, 204, 179, -363, 184, 1115, 1257, 1273, 1289, 1305, 1321, -113, 188, 185, 1852, -363, -363, -363, -363, -363, -363, -363, -363, 204, -363, -57, -363, -363 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -363, -363, -363, -363, -363, -363, -363, -4, -1, 48, -363, -363, -363, -206, -363, -363, 316, 286, 217, -240, -363, -362, -56, -43, 160, 0, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363, -363 }; /* 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 -155 static const yytype_int16 yytable[] = { 61, 70, 368, 100, 169, 152, 153, 380, 123, 154, 170, 155, 156, 89, 306, 113, 115, 117, 119, 171, 172, 150, 125, 122, 310, 120, 121, 332, 154, 380, 151, 156, 154, 369, 333, 156, 151, 154, 124, 151, 156, 128, 227, 151, 134, 275, 148, 70, 151, 277, 144, 103, 97, 148, 279, 101, 151, 152, 153, 216, 217, 154, 294, 155, 156, 168, 175, 101, 101, 101, 101, 104, 151, 177, 101, 151, 151, 127, 296, 105, 151, 307, 308, 148, 151, 148, 367, 226, 106, 151, 395, 179, 280, 335, 336, 139, 103, 281, 143, 366, 180, 282, 146, 148, 107, 186, 148, 181, 283, 108, 198, 166, 167, 201, 182, 284, 109, 204, 101, 183, 285, 110, 214, 152, 153, 101, 215, 154, 178, 155, 156, 184, 288, 111, 100, 157, 224, 158, 159, 160, 161, 126, 162, 268, 229, 163, 164, 185, 231, 269, 165, 188, 190, 191, 192, 193, 194, 195, 196, 161, 199, 244, 160, 161, 202, 162, 129, 250, 161, 165, 162, 131, 253, 165, 101, 130, 154, 218, 165, 156, 257, 149, 259, 221, -154, 132, 101, 157, 149, 158, 159, 160, 161, 297, 162, 298, 101, 163, 164, 232, 233, 234, 165, 235, 170, 236, 237, 238, 239, 240, 241, 242, 243, 101, -153, 286, 104, 357, 149, 101, 149, 287, 251, 133, 101, 107, 358, 255, 256, 135, 258, 148, 260, -133, -133, 262, -134, -134, 149, 152, 153, 149, 136, 154, 137, 155, 156, 108, 359, 30, 304, 110, 360, 157, 147, 158, 159, 160, 161, 169, 162, 111, 361, 163, 164, 141, 142, 291, 165, 228, 152, 153, 176, 179, 154, 180, 155, 156, 181, 182, 183, 184, 205, 151, 220, 206, 323, 222, 171, 249, 264, 289, 292, 299, 295, 331, 300, 339, 341, 365, 303, 350, 305, 379, 158, 159, 160, 161, 340, 162, 351, 352, 305, 164, 311, 312, 313, 165, 314, 368, 315, 316, 353, 102, 354, 382, 2, 3, 355, 391, 356, 383, 392, 140, 4, 394, 390, 254, 329, 0, 5, 6, 7, 8, 152, 153, 334, 9, 154, 337, 155, 156, -110, 0, 0, 0, 0, 0, 252, 0, 0, -110, -110, 0, 0, 0, 149, 10, 245, 157, 148, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 393, 0, 246, 165, 0, 148, 305, 0, 0, 0, 373, 0, 374, 375, 0, 376, 0, 0, 0, 157, 0, 158, 159, 160, 161, 0, 162, 270, 0, 163, 164, 377, 378, 271, 165, 148, 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 27, 28, 29, 30, 0, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 148, 49, 0, 0, 50, 0, 51, 0, 0, 0, 52, 0, 0, 0, 53, 0, 157, 54, 158, 159, 160, 161, 148, 162, 273, 0, 163, 164, 152, 153, 274, 165, 154, -112, 155, 156, 0, 0, 0, 0, 0, 0, -112, -112, 152, 153, 0, 149, 154, -105, 155, 156, 0, 0, 0, 0, 0, 0, -105, -105, 152, 153, 0, 149, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, -106, 154, 0, 155, 156, 0, 0, 0, 0, -106, -106, 152, 153, 0, 149, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, -107, 152, 153, 0, 0, 154, 0, 155, 156, -107, -107, 0, 0, 0, 149, 0, 0, 152, 153, 0, 0, 154, -108, 155, 156, 0, 0, 0, 0, 0, 0, -108, -108, 0, 0, 0, 149, 157, 0, 158, 159, 160, 161, 0, 162, 301, 0, 163, 164, 0, 0, 302, 165, 157, 148, 158, 159, 160, 161, 0, 162, 346, 0, 163, 164, 0, 0, 347, 165, 157, 0, 158, 159, 160, 161, 0, 162, 348, 0, 163, 164, 0, 0, 349, 165, 157, 0, 158, 159, 160, 161, 0, 162, 248, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 261, 165, 157, 0, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 263, 165, 157, 0, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 265, 165, 157, 0, 158, 159, 160, 161, 0, 162, 266, 0, 163, 164, 152, 153, 0, 165, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 152, 153, -111, 0, 154, 0, 155, 156, 0, 0, 0, -111, -111, 0, 152, 153, 149, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 157, 0, 158, 159, 160, 161, 0, 162, 267, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 272, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 276, 165, 157, 0, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 278, 165, 157, 0, 158, 159, 160, 161, 0, 162, 290, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 293, 165, 157, 0, 158, 159, 160, 161, 0, 162, 309, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 330, 165, 157, 0, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 152, 153, 246, 165, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 5, 6, 317, 318, 152, 153, 0, 9, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 319, 320, 321, 322, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 157, 0, 158, 159, 160, 161, 338, 162, 0, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 342, 165, 157, 0, 158, 159, 160, 161, 0, 162, 343, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 344, 165, 157, 0, 158, 159, 160, 161, 0, 162, 345, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 362, 165, 157, 0, 158, 159, 160, 161, 363, 162, 0, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 364, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 152, 153, 384, 165, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 152, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, -155, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 154, 0, 155, 156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 157, 0, 158, 159, 160, 161, 154, 162, 0, 156, 163, 164, 0, 0, 385, 165, 157, 0, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 386, 165, 157, 0, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 387, 165, 157, 0, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 388, 165, 157, 0, 158, 159, 160, 161, 389, 162, 0, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 163, 164, 0, 0, 157, 165, 158, 159, 160, 161, 0, 162, 0, 0, 4, 164, 0, 0, 0, 165, 5, 6, 90, 91, 0, 0, 0, 9, 0, 0, 157, 0, 158, 159, 160, 161, 0, 162, 0, 0, 0, 164, 0, 0, 0, 165, 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, 4, 0, 0, 0, 0, 0, 5, 6, 90, 91, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 53, 197, 0, 54, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 207, 208, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 53, 200, 0, 54, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 53, 203, 0, 54, 11, 12, 13, 14, 15, 16, 17, 18, 209, 210, 211, 212, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 53, 213, 0, 54, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 53, 223, 0, 54, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 53, 230, 0, 54, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 53, 0, 0, 54, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 99, 0, 0, 54, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 112, 0, 0, 54, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 114, 0, 0, 54, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 138, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 116, 0, 0, 54, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 118, 0, 0, 54, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 53, 0, 0, 54, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 4, 0, 0, 0, 0, 96, 5, 6, 90, 91, 50, 0, 51, 9, 0, 0, 0, 0, 0, 0, 174, 0, 0, 54, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 50, 0, 51, 0, 0, 0, 0, 0, 0, 0, 187, 0, 0, 54, 324, 12, 13, 325, 326, 16, 327, 328, 92, 93, 94, 95, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 32, 33, 0, 35, 36, 0, 0, 0, 40, 41, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 50, 0, 51, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0, 54 }; static const yytype_int16 yycheck[] = { 1, 1, 115, 7, 12, 3, 4, 369, 112, 7, 132, 9, 10, 142, 254, 19, 20, 21, 22, 141, 142, 132, 26, 24, 264, 112, 113, 113, 7, 391, 141, 10, 7, 146, 120, 10, 141, 7, 142, 141, 10, 112, 147, 141, 112, 147, 11, 47, 141, 147, 51, 146, 4, 11, 147, 7, 141, 3, 4, 112, 113, 7, 147, 9, 10, 66, 70, 19, 20, 21, 22, 146, 141, 77, 26, 141, 141, 29, 147, 146, 141, 147, 147, 11, 141, 11, 147, 139, 146, 141, 147, 146, 147, 299, 300, 47, 146, 147, 50, 339, 146, 147, 54, 11, 146, 113, 11, 146, 147, 146, 111, 63, 64, 114, 146, 147, 146, 118, 70, 146, 147, 146, 126, 3, 4, 77, 126, 7, 80, 9, 10, 146, 147, 146, 138, 133, 137, 135, 136, 137, 138, 146, 140, 141, 148, 143, 144, 99, 149, 147, 148, 103, 104, 105, 106, 107, 108, 109, 110, 138, 112, 165, 137, 138, 116, 140, 146, 171, 138, 148, 140, 113, 176, 148, 126, 146, 7, 129, 148, 10, 181, 146, 183, 135, 142, 146, 138, 133, 146, 135, 136, 137, 138, 139, 140, 141, 148, 143, 144, 151, 152, 153, 148, 155, 132, 157, 158, 159, 160, 161, 162, 163, 164, 165, 142, 141, 146, 147, 146, 171, 146, 147, 174, 146, 176, 146, 147, 179, 180, 146, 182, 11, 184, 141, 142, 187, 141, 142, 146, 3, 4, 146, 112, 7, 146, 9, 10, 146, 147, 112, 254, 146, 147, 133, 142, 135, 136, 137, 138, 12, 140, 146, 147, 143, 144, 48, 49, 219, 148, 149, 3, 4, 141, 146, 7, 146, 9, 10, 146, 146, 146, 146, 142, 141, 112, 142, 286, 113, 141, 113, 141, 113, 112, 245, 142, 113, 248, 141, 141, 138, 252, 147, 254, 141, 135, 136, 137, 138, 309, 140, 147, 147, 264, 144, 266, 267, 268, 148, 270, 115, 272, 273, 147, 7, 147, 146, 0, 1, 147, 141, 147, 147, 147, 47, 8, 391, 379, 177, 290, -1, 14, 15, 16, 17, 3, 4, 298, 21, 7, 301, 9, 10, 132, -1, -1, -1, -1, -1, 138, -1, -1, 141, 142, -1, -1, -1, 146, 41, 132, 133, 11, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, 382, -1, 147, 148, -1, 11, 339, -1, -1, -1, 343, -1, 345, 346, -1, 348, -1, -1, -1, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, 364, 365, 147, 148, 11, -1, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, -1, 109, 110, 111, 112, -1, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 11, 133, -1, -1, 136, -1, 138, -1, -1, -1, 142, -1, -1, -1, 146, -1, 133, 149, 135, 136, 137, 138, 11, 140, 141, -1, 143, 144, 3, 4, 147, 148, 7, 132, 9, 10, -1, -1, -1, -1, -1, -1, 141, 142, 3, 4, -1, 146, 7, 132, 9, 10, -1, -1, -1, -1, -1, -1, 141, 142, 3, 4, -1, 146, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, 132, 7, -1, 9, 10, -1, -1, -1, -1, 141, 142, 3, 4, -1, 146, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, 132, 3, 4, -1, -1, 7, -1, 9, 10, 141, 142, -1, -1, -1, 146, -1, -1, 3, 4, -1, -1, 7, 132, 9, 10, -1, -1, -1, -1, -1, -1, 141, 142, -1, -1, -1, 146, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 147, 148, 133, 11, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, 3, 4, -1, 148, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, 3, 4, 132, -1, 7, -1, 9, 10, -1, -1, -1, 141, 142, -1, 3, 4, 146, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, 3, 4, 147, 148, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, 14, 15, 16, 17, 3, 4, -1, 21, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, 100, 101, 102, 103, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, 133, -1, 135, 136, 137, 138, 139, 140, -1, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, 139, 140, -1, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, 141, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, 3, 4, 147, 148, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, 3, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, 7, -1, 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 133, -1, 135, 136, 137, 138, 7, 140, -1, 10, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 147, 148, 133, -1, 135, 136, 137, 138, 139, 140, -1, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 143, 144, -1, -1, 133, 148, 135, 136, 137, 138, -1, 140, -1, -1, 8, 144, -1, -1, -1, 148, 14, 15, 16, 17, -1, -1, -1, 21, -1, -1, 133, -1, 135, 136, 137, 138, -1, 140, -1, -1, -1, 144, -1, -1, -1, 148, -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, 8, -1, -1, -1, -1, -1, 14, 15, 16, 17, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, 147, -1, 149, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, 147, -1, 149, -1, -1, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, 147, -1, 149, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, 147, -1, 149, -1, -1, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, 147, -1, 149, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, 147, -1, 149, -1, -1, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149, -1, -1, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149, -1, -1, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149, -1, -1, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, 8, -1, -1, -1, -1, 131, 14, 15, 16, 17, 136, -1, 138, 21, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149, -1, -1, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, -1, -1, -1, -1, -1, 131, -1, -1, -1, -1, 136, -1, 138, -1, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, -1, -1, -1, -1, -1, -1, 112, -1, 114, 115, 116, -1, 118, 119, -1, -1, -1, 123, 124, -1, -1, -1, -1, -1, -1, 131, -1, -1, -1, -1, 136, -1, 138, -1, -1, -1, -1, -1, -1, -1, 146, -1, -1, 149 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 151, 0, 1, 8, 14, 15, 16, 17, 21, 41, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 133, 136, 138, 142, 146, 149, 152, 153, 154, 155, 156, 157, 158, 159, 161, 162, 164, 165, 166, 167, 168, 175, 176, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 142, 16, 17, 100, 101, 102, 103, 131, 159, 175, 146, 157, 159, 166, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 157, 146, 157, 146, 157, 146, 157, 112, 113, 158, 112, 142, 157, 146, 159, 112, 146, 146, 113, 146, 146, 112, 146, 112, 146, 16, 159, 167, 168, 168, 159, 158, 158, 159, 142, 11, 146, 132, 141, 3, 4, 7, 9, 10, 133, 135, 136, 137, 138, 140, 143, 144, 148, 159, 159, 158, 12, 132, 141, 142, 174, 146, 157, 141, 157, 159, 146, 146, 146, 146, 146, 146, 159, 113, 146, 159, 169, 159, 159, 159, 159, 159, 159, 159, 147, 158, 159, 147, 158, 159, 147, 158, 142, 142, 16, 17, 100, 101, 102, 103, 147, 157, 175, 112, 113, 159, 160, 112, 159, 113, 147, 158, 177, 139, 147, 149, 157, 147, 158, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 157, 132, 147, 163, 141, 113, 157, 159, 138, 157, 174, 159, 159, 158, 159, 158, 159, 147, 159, 147, 141, 147, 141, 141, 141, 147, 141, 147, 141, 141, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 141, 147, 147, 113, 141, 159, 112, 147, 147, 142, 147, 139, 141, 159, 159, 141, 147, 159, 157, 159, 169, 147, 147, 141, 169, 159, 159, 159, 159, 159, 159, 16, 17, 100, 101, 102, 103, 175, 92, 95, 96, 98, 99, 159, 147, 113, 113, 120, 159, 163, 163, 159, 139, 141, 158, 141, 147, 141, 147, 141, 141, 147, 141, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 139, 141, 138, 169, 147, 115, 146, 170, 171, 173, 159, 159, 159, 159, 159, 159, 141, 171, 172, 146, 147, 147, 147, 147, 147, 147, 139, 173, 141, 147, 158, 172, 147 }; #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. However, YYFAIL appears to be in use. Nevertheless, it is formally deprecated in Bison 2.4.2's NEWS entry, where a plan to phase it out is discussed. */ #define YYFAIL goto yyerrlab #if defined YYFAIL /* This is here to suppress warnings from the GCC cpp's -Wunused-macros. Normally we don't worry about that warning, but some users do, and we want to make it easy for users to remove YYFAIL uses, which will produce warnings from Bison 2.5. */ #endif #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 defined YYLTYPE_IS_TRIVIAL && 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 (&yylval, YYLEX_PARAM) #else # define YYLEX yylex (&yylval) #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 *yybottom, yytype_int16 *yytop) #else static void yy_stack_print (yybottom, yytop) yytype_int16 *yybottom; yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } 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++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (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 */ /*-------------------------. | yyparse or yypush_parse. | `-------------------------*/ #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 { /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yytoken = 0; yyss = yyssa; yyvs = yyvsa; yystacksize = YYINITDEPTH; 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_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, 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)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead 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; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ 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 3: /* Line 1464 of yacc.c */ #line 366 "grammar.y" { if (timerv) { writeTime("used time:"); startTimer(); } if (rtimerv) { writeRTime("used real time:"); startRTimer(); } prompt_char = '>'; #ifdef HAVE_SDB if (sdb_flags & 2) { sdb_flags=1; YYERROR; } #endif if(siCntrlc) { WerrorS("abort..."); while((currentVoice!=NULL) && (currentVoice->prev!=NULL)) exitVoice(); if (currentVoice!=NULL) currentVoice->ifsw=0; } if (errorreported) /* also catches abort... */ { yyerror(""); } if (inerror==2) PrintLn(); errorreported = inerror = cmdtok = 0; lastreserved = currid = NULL; expected_parms = siCntrlc = FALSE; ;} break; case 5: /* Line 1464 of yacc.c */ #line 401 "grammar.y" {currentVoice->ifsw=0;;} break; case 6: /* Line 1464 of yacc.c */ #line 403 "grammar.y" { (yyvsp[(1) - (2)].lv).CleanUp(); currentVoice->ifsw=0;;} break; case 7: /* Line 1464 of yacc.c */ #line 405 "grammar.y" { YYACCEPT; ;} break; case 8: /* Line 1464 of yacc.c */ #line 409 "grammar.y" { currentVoice->ifsw=0; iiDebug(); ;} break; case 9: /* Line 1464 of yacc.c */ #line 414 "grammar.y" {currentVoice->ifsw=0;;} break; case 10: /* Line 1464 of yacc.c */ #line 416 "grammar.y" { #ifdef SIQ siq=0; #endif yyInRingConstruction = FALSE; currentVoice->ifsw=0; if (inerror) { /* bison failed here*/ if ((inerror!=3) && ((yyvsp[(1) - (2)].i)' ')) { // 1: yyerror called // 2: scanner put actual string // 3: error rule put token+\n inerror=3; Print(" error at token `%s`\n",iiTwoOps((yyvsp[(1) - (2)].i))); } /**/ } if (!errorreported) WerrorS("...parse error"); yyerror(""); yyerrok; #ifdef HAVE_SDB if ((sdb_flags & 1) && currentVoice->pi!=NULL) { currentVoice->pi->trace_flag |=1; } else #endif if (myynest>0) { feBufferTypes t=currentVoice->Typ(); //PrintS("leaving yyparse\n"); exitBuffer(BT_proc); if (t==BT_example) YYACCEPT; else YYABORT; } else if (currentVoice->prev!=NULL) { exitVoice(); } #ifdef HAVE_SDB if (sdb_flags &2) sdb_flags=1; #endif ;} break; case 18: /* Line 1464 of yacc.c */ #line 474 "grammar.y" {if (currentVoice!=NULL) currentVoice->ifsw=0;;} break; case 19: /* Line 1464 of yacc.c */ #line 477 "grammar.y" { omFree((ADDRESS)(yyvsp[(2) - (2)].name)); ;} break; case 29: /* Line 1464 of yacc.c */ #line 492 "grammar.y" { if(iiAssign(&(yyvsp[(1) - (2)].lv),&(yyvsp[(2) - (2)].lv))) YYERROR; ;} break; case 30: /* Line 1464 of yacc.c */ #line 499 "grammar.y" { if (currRing==NULL) MYYERROR("no ring active"); syMake(&(yyval.lv),omStrDup((yyvsp[(1) - (1)].name))); ;} break; case 31: /* Line 1464 of yacc.c */ #line 504 "grammar.y" { syMake(&(yyval.lv),(yyvsp[(1) - (1)].name)); ;} break; case 32: /* Line 1464 of yacc.c */ #line 508 "grammar.y" { if(iiExprArith2(&(yyval.lv), &(yyvsp[(1) - (3)].lv), COLONCOLON, &(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 33: /* Line 1464 of yacc.c */ #line 512 "grammar.y" { if(iiExprArith2(&(yyval.lv), &(yyvsp[(1) - (3)].lv), '.', &(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 34: /* Line 1464 of yacc.c */ #line 516 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(1) - (3)].lv),'(')) YYERROR; ;} break; case 35: /* Line 1464 of yacc.c */ #line 520 "grammar.y" { if ((yyvsp[(1) - (4)].lv).rtyp==UNKNOWN) { // for x(i)(j) if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (4)].lv),'(',&(yyvsp[(3) - (4)].lv))) YYERROR; } else { (yyvsp[(1) - (4)].lv).next=(leftv)omAllocBin(sleftv_bin); memcpy((yyvsp[(1) - (4)].lv).next,&(yyvsp[(3) - (4)].lv),sizeof(sleftv)); if(iiExprArithM(&(yyval.lv),&(yyvsp[(1) - (4)].lv),'(')) YYERROR; } ;} break; case 36: /* Line 1464 of yacc.c */ #line 533 "grammar.y" { if (currRingHdl==NULL) MYYERROR("no ring active"); int j = 0; memset(&(yyval.lv),0,sizeof(sleftv)); (yyval.lv).rtyp=VECTOR_CMD; leftv v = &(yyvsp[(2) - (3)].lv); while (v!=NULL) { int i,t; sleftv tmp; memset(&tmp,0,sizeof(tmp)); i=iiTestConvert((t=v->Typ()),POLY_CMD); if((i==0) || (iiConvert(t /*v->Typ()*/,POLY_CMD,i,v,&tmp))) { pDelete((poly *)&(yyval.lv).data); (yyvsp[(2) - (3)].lv).CleanUp(); MYYERROR("expected '[poly,...'"); } poly p = (poly)tmp.CopyD(POLY_CMD); pSetCompP(p,++j); (yyval.lv).data = (void *)pAdd((poly)(yyval.lv).data,p); v->next=tmp.next;tmp.next=NULL; tmp.CleanUp(); v=v->next; } (yyvsp[(2) - (3)].lv).CleanUp(); ;} break; case 37: /* Line 1464 of yacc.c */ #line 561 "grammar.y" { memset(&(yyval.lv),0,sizeof((yyval.lv))); int i = atoi((yyvsp[(1) - (1)].name)); /*remember not to omFree($1) *because it is a part of the scanner buffer*/ (yyval.lv).rtyp = INT_CMD; (yyval.lv).data = (void *)(long)i; /* check: out of range input */ int l = strlen((yyvsp[(1) - (1)].name))+2; number n; if (l >= MAX_INT_LEN) { char tmp[MAX_INT_LEN+5]; sprintf(tmp,"%d",i); if (strcmp(tmp,(yyvsp[(1) - (1)].name))!=0) { n_Read((yyvsp[(1) - (1)].name),&n,coeffs_BIGINT); (yyval.lv).rtyp=BIGINT_CMD; (yyval.lv).data = n; } } ;} break; case 38: /* Line 1464 of yacc.c */ #line 585 "grammar.y" { memset(&(yyval.lv),0,sizeof((yyval.lv))); (yyval.lv).rtyp = (yyvsp[(1) - (1)].i); (yyval.lv).data = (yyval.lv).Data(); ;} break; case 39: /* Line 1464 of yacc.c */ #line 591 "grammar.y" { memset(&(yyval.lv),0,sizeof((yyval.lv))); (yyval.lv).rtyp = STRING_CMD; (yyval.lv).data = (yyvsp[(1) - (1)].name); ;} break; case 40: /* Line 1464 of yacc.c */ #line 597 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 41: /* Line 1464 of yacc.c */ #line 601 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 42: /* Line 1464 of yacc.c */ #line 605 "grammar.y" { if(iiExprArithM(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 43: /* Line 1464 of yacc.c */ #line 609 "grammar.y" { if(iiExprArithM(&(yyval.lv),NULL,(yyvsp[(1) - (3)].i))) YYERROR; ;} break; case 44: /* Line 1464 of yacc.c */ #line 613 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 45: /* Line 1464 of yacc.c */ #line 617 "grammar.y" { if(iiExprArithM(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 46: /* Line 1464 of yacc.c */ #line 621 "grammar.y" { if(iiExprArithM(&(yyval.lv),NULL,(yyvsp[(1) - (3)].i))) YYERROR; ;} break; case 47: /* Line 1464 of yacc.c */ #line 625 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 48: /* Line 1464 of yacc.c */ #line 629 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 49: /* Line 1464 of yacc.c */ #line 633 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 50: /* Line 1464 of yacc.c */ #line 637 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 51: /* Line 1464 of yacc.c */ #line 641 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(3) - (6)].lv),(yyvsp[(1) - (6)].i),&(yyvsp[(5) - (6)].lv),TRUE)) YYERROR; ;} break; case 52: /* Line 1464 of yacc.c */ #line 645 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(3) - (6)].lv),(yyvsp[(1) - (6)].i),&(yyvsp[(5) - (6)].lv),TRUE)) YYERROR; ;} break; case 53: /* Line 1464 of yacc.c */ #line 649 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(3) - (6)].lv),(yyvsp[(1) - (6)].i),&(yyvsp[(5) - (6)].lv),TRUE)) YYERROR; ;} break; case 54: /* Line 1464 of yacc.c */ #line 653 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(3) - (6)].lv),(yyvsp[(1) - (6)].i),&(yyvsp[(5) - (6)].lv),TRUE)) YYERROR; ;} break; case 55: /* Line 1464 of yacc.c */ #line 657 "grammar.y" { if(iiExprArith3(&(yyval.lv),(yyvsp[(1) - (8)].i),&(yyvsp[(3) - (8)].lv),&(yyvsp[(5) - (8)].lv),&(yyvsp[(7) - (8)].lv))) YYERROR; ;} break; case 56: /* Line 1464 of yacc.c */ #line 661 "grammar.y" { if(iiExprArith3(&(yyval.lv),(yyvsp[(1) - (8)].i),&(yyvsp[(3) - (8)].lv),&(yyvsp[(5) - (8)].lv),&(yyvsp[(7) - (8)].lv))) YYERROR; ;} break; case 57: /* Line 1464 of yacc.c */ #line 665 "grammar.y" { if(iiExprArith3(&(yyval.lv),(yyvsp[(1) - (8)].i),&(yyvsp[(3) - (8)].lv),&(yyvsp[(5) - (8)].lv),&(yyvsp[(7) - (8)].lv))) YYERROR; ;} break; case 58: /* Line 1464 of yacc.c */ #line 669 "grammar.y" { if(iiExprArith3(&(yyval.lv),(yyvsp[(1) - (8)].i),&(yyvsp[(3) - (8)].lv),&(yyvsp[(5) - (8)].lv),&(yyvsp[(7) - (8)].lv))) YYERROR; ;} break; case 59: /* Line 1464 of yacc.c */ #line 673 "grammar.y" { if(iiExprArithM(&(yyval.lv),NULL,(yyvsp[(1) - (3)].i))) YYERROR; ;} break; case 60: /* Line 1464 of yacc.c */ #line 677 "grammar.y" { int b=iiExprArithM(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i)); // handle branchTo if (b==TRUE) YYERROR; if (b==2) YYACCEPT; ;} break; case 61: /* Line 1464 of yacc.c */ #line 683 "grammar.y" { if(iiExprArith3(&(yyval.lv),(yyvsp[(1) - (8)].i),&(yyvsp[(3) - (8)].lv),&(yyvsp[(5) - (8)].lv),&(yyvsp[(7) - (8)].lv))) YYERROR; ;} break; case 62: /* Line 1464 of yacc.c */ #line 687 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(3) - (4)].lv),(yyvsp[(1) - (4)].i))) YYERROR; ;} break; case 63: /* Line 1464 of yacc.c */ #line 691 "grammar.y" { if(iiExprArith3(&(yyval.lv),RING_CMD,&(yyvsp[(3) - (8)].lv),&(yyvsp[(5) - (8)].lv),&(yyvsp[(7) - (8)].lv))) YYERROR; ;} break; case 64: /* Line 1464 of yacc.c */ #line 695 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(3) - (4)].lv),RING_CMD)) YYERROR; ;} break; case 65: /* Line 1464 of yacc.c */ #line 699 "grammar.y" { if (iiARROW(&(yyval.lv),(yyvsp[(1) - (3)].name),(yyvsp[(3) - (3)].name))) YYERROR; ;} break; case 66: /* Line 1464 of yacc.c */ #line 706 "grammar.y" { leftv v = &(yyvsp[(1) - (3)].lv); while (v->next!=NULL) { v=v->next; } v->next = (leftv)omAllocBin(sleftv_bin); memcpy(v->next,&((yyvsp[(3) - (3)].lv)),sizeof(sleftv)); (yyval.lv) = (yyvsp[(1) - (3)].lv); ;} break; case 67: /* Line 1464 of yacc.c */ #line 717 "grammar.y" { (yyval.lv) = (yyvsp[(1) - (1)].lv); ;} break; case 68: /* Line 1464 of yacc.c */ #line 723 "grammar.y" { /*if ($1.typ == eunknown) YYERROR;*/ (yyval.lv) = (yyvsp[(1) - (1)].lv); ;} break; case 69: /* Line 1464 of yacc.c */ #line 727 "grammar.y" { (yyval.lv) = (yyvsp[(1) - (1)].lv); ;} break; case 70: /* Line 1464 of yacc.c */ #line 728 "grammar.y" { (yyval.lv) = (yyvsp[(2) - (3)].lv); ;} break; case 71: /* Line 1464 of yacc.c */ #line 730 "grammar.y" { if(iiExprArith3(&(yyval.lv),'[',&(yyvsp[(1) - (6)].lv),&(yyvsp[(3) - (6)].lv),&(yyvsp[(5) - (6)].lv))) YYERROR; ;} break; case 72: /* Line 1464 of yacc.c */ #line 734 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (4)].lv),'[',&(yyvsp[(3) - (4)].lv))) YYERROR; ;} break; case 73: /* Line 1464 of yacc.c */ #line 738 "grammar.y" { if (iiApply(&(yyval.lv), &(yyvsp[(3) - (6)].lv), (yyvsp[(5) - (6)].i), NULL)) YYERROR; ;} break; case 74: /* Line 1464 of yacc.c */ #line 742 "grammar.y" { if (iiApply(&(yyval.lv), &(yyvsp[(3) - (6)].lv), (yyvsp[(5) - (6)].i), NULL)) YYERROR; ;} break; case 75: /* Line 1464 of yacc.c */ #line 746 "grammar.y" { if (iiApply(&(yyval.lv), &(yyvsp[(3) - (6)].lv), (yyvsp[(5) - (6)].i), NULL)) YYERROR; ;} break; case 76: /* Line 1464 of yacc.c */ #line 750 "grammar.y" { if (iiApply(&(yyval.lv), &(yyvsp[(3) - (6)].lv), (yyvsp[(5) - (6)].i), NULL)) YYERROR; ;} break; case 77: /* Line 1464 of yacc.c */ #line 754 "grammar.y" { if (iiApply(&(yyval.lv), &(yyvsp[(3) - (6)].lv), (yyvsp[(5) - (6)].i), NULL)) YYERROR; ;} break; case 78: /* Line 1464 of yacc.c */ #line 758 "grammar.y" { if (iiApply(&(yyval.lv), &(yyvsp[(3) - (6)].lv), 0, &(yyvsp[(5) - (6)].lv))) YYERROR; ;} break; case 79: /* Line 1464 of yacc.c */ #line 762 "grammar.y" { (yyval.lv)=(yyvsp[(2) - (3)].lv); ;} break; case 80: /* Line 1464 of yacc.c */ #line 766 "grammar.y" { #ifdef SIQ siq++; if (siq>0) { if (iiExprArith2(&(yyval.lv),&(yyvsp[(2) - (5)].lv),'=',&(yyvsp[(4) - (5)].lv))) YYERROR; } else #endif { memset(&(yyval.lv),0,sizeof((yyval.lv))); (yyval.lv).rtyp=NONE; if (iiAssign(&(yyvsp[(2) - (5)].lv),&(yyvsp[(4) - (5)].lv))) YYERROR; } #ifdef SIQ siq--; #endif ;} break; case 81: /* Line 1464 of yacc.c */ #line 783 "grammar.y" { iiTestAssume(&(yyvsp[(2) - (5)].lv),&(yyvsp[(4) - (5)].lv)); memset(&(yyval.lv),0,sizeof((yyval.lv))); (yyval.lv).rtyp=NONE; ;} break; case 82: /* Line 1464 of yacc.c */ #line 789 "grammar.y" { #ifdef SIQ siq--; #endif ;} break; case 83: /* Line 1464 of yacc.c */ #line 795 "grammar.y" { #ifdef SIQ if (siq<=0) (yyvsp[(4) - (5)].lv).Eval(); #endif (yyval.lv)=(yyvsp[(4) - (5)].lv); #ifdef SIQ siq++; #endif ;} break; case 84: /* Line 1464 of yacc.c */ #line 807 "grammar.y" { #ifdef SIQ siq++; #endif ;} break; case 85: /* Line 1464 of yacc.c */ #line 815 "grammar.y" { #ifdef SIQ siq++; #endif ;} break; case 86: /* Line 1464 of yacc.c */ #line 823 "grammar.y" { #ifdef SIQ siq--; #endif ;} break; case 87: /* Line 1464 of yacc.c */ #line 832 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(1) - (2)].lv),PLUSPLUS)) YYERROR; ;} break; case 88: /* Line 1464 of yacc.c */ #line 836 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(1) - (2)].lv),MINUSMINUS)) YYERROR; ;} break; case 89: /* Line 1464 of yacc.c */ #line 840 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),'+',&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 90: /* Line 1464 of yacc.c */ #line 844 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),'-',&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 91: /* Line 1464 of yacc.c */ #line 848 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),(yyvsp[(2) - (3)].i),&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 92: /* Line 1464 of yacc.c */ #line 852 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),'^',&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 93: /* Line 1464 of yacc.c */ #line 856 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),(yyvsp[(2) - (3)].i),&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 94: /* Line 1464 of yacc.c */ #line 860 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),(yyvsp[(2) - (3)].i),&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 95: /* Line 1464 of yacc.c */ #line 864 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),NOTEQUAL,&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 96: /* Line 1464 of yacc.c */ #line 868 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),EQUAL_EQUAL,&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 97: /* Line 1464 of yacc.c */ #line 872 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),DOTDOT,&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 98: /* Line 1464 of yacc.c */ #line 876 "grammar.y" { if(iiExprArith2(&(yyval.lv),&(yyvsp[(1) - (3)].lv),':',&(yyvsp[(3) - (3)].lv))) YYERROR; ;} break; case 99: /* Line 1464 of yacc.c */ #line 880 "grammar.y" { if (siq>0) { if (iiExprArith1(&(yyval.lv),&(yyvsp[(2) - (2)].lv),NOT)) YYERROR; } else { memset(&(yyval.lv),0,sizeof((yyval.lv))); int i; TESTSETINT((yyvsp[(2) - (2)].lv),i); (yyval.lv).rtyp = INT_CMD; (yyval.lv).data = (void *)(long)(i == 0 ? 1 : 0); } ;} break; case 100: /* Line 1464 of yacc.c */ #line 892 "grammar.y" { if(iiExprArith1(&(yyval.lv),&(yyvsp[(2) - (2)].lv),'-')) YYERROR; ;} break; case 101: /* Line 1464 of yacc.c */ #line 898 "grammar.y" { (yyval.lv) = (yyvsp[(1) - (2)].lv); ;} break; case 102: /* Line 1464 of yacc.c */ #line 900 "grammar.y" { if ((yyvsp[(1) - (2)].lv).rtyp==0) { Werror("`%s` is undefined",(yyvsp[(1) - (2)].lv).Fullname()); YYERROR; } else if (((yyvsp[(1) - (2)].lv).rtyp==MODUL_CMD) // matrix m; m[2]=... && ((yyvsp[(1) - (2)].lv).e!=NULL) && ((yyvsp[(1) - (2)].lv).e->next==NULL)) { MYYERROR("matrix must have 2 indices"); } (yyval.lv) = (yyvsp[(1) - (2)].lv); ;} break; case 104: /* Line 1464 of yacc.c */ #line 920 "grammar.y" { if ((yyvsp[(2) - (3)].lv).Typ()!=STRING_CMD) { MYYERROR("string expression expected"); } (yyval.name) = (char *)(yyvsp[(2) - (3)].lv).CopyD(STRING_CMD); (yyvsp[(2) - (3)].lv).CleanUp(); ;} break; case 105: /* Line 1464 of yacc.c */ #line 932 "grammar.y" { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (2)].lv),myynest,(yyvsp[(1) - (2)].i),&((yyvsp[(2) - (2)].lv).req_packhdl->idroot))) YYERROR; ;} break; case 106: /* Line 1464 of yacc.c */ #line 937 "grammar.y" { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (2)].lv),myynest,(yyvsp[(1) - (2)].i),&((yyvsp[(2) - (2)].lv).req_packhdl->idroot))) YYERROR; ;} break; case 107: /* Line 1464 of yacc.c */ #line 942 "grammar.y" { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (2)].lv),myynest,(yyvsp[(1) - (2)].i),&(currRing->idroot), TRUE)) YYERROR; ;} break; case 108: /* Line 1464 of yacc.c */ #line 946 "grammar.y" { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (2)].lv),myynest,(yyvsp[(1) - (2)].i),&(currRing->idroot), TRUE)) YYERROR; ;} break; case 109: /* Line 1464 of yacc.c */ #line 950 "grammar.y" { int r; TESTSETINT((yyvsp[(4) - (8)].lv),r); int c; TESTSETINT((yyvsp[(7) - (8)].lv),c); leftv v; idhdl h; if ((yyvsp[(1) - (8)].i) == MATRIX_CMD) { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (8)].lv),myynest,(yyvsp[(1) - (8)].i),&(currRing->idroot), TRUE)) YYERROR; v=&(yyval.lv); h=(idhdl)v->data; idDelete(&IDIDEAL(h)); IDMATRIX(h) = mpNew(r,c); if (IDMATRIX(h)==NULL) YYERROR; } else if ((yyvsp[(1) - (8)].i) == INTMAT_CMD) { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (8)].lv),myynest,(yyvsp[(1) - (8)].i),&((yyvsp[(2) - (8)].lv).req_packhdl->idroot))) YYERROR; v=&(yyval.lv); h=(idhdl)v->data; delete IDINTVEC(h); IDINTVEC(h) = new intvec(r,c,0); if (IDINTVEC(h)==NULL) YYERROR; } else /* BIGINTMAT_CMD */ { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (8)].lv),myynest,(yyvsp[(1) - (8)].i),&((yyvsp[(2) - (8)].lv).req_packhdl->idroot))) YYERROR; v=&(yyval.lv); h=(idhdl)v->data; delete IDBIMAT(h); IDBIMAT(h) = new bigintmat(r, c, coeffs_BIGINT); if (IDBIMAT(h)==NULL) YYERROR; } ;} break; case 110: /* Line 1464 of yacc.c */ #line 986 "grammar.y" { if ((yyvsp[(1) - (2)].i) == MATRIX_CMD) { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (2)].lv),myynest,(yyvsp[(1) - (2)].i),&(currRing->idroot), TRUE)) YYERROR; } else if ((yyvsp[(1) - (2)].i) == INTMAT_CMD) { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (2)].lv),myynest,(yyvsp[(1) - (2)].i),&((yyvsp[(2) - (2)].lv).req_packhdl->idroot))) YYERROR; leftv v=&(yyval.lv); idhdl h; do { h=(idhdl)v->data; delete IDINTVEC(h); IDINTVEC(h) = new intvec(1,1,0); v=v->next; } while (v!=NULL); } else /* BIGINTMAT_CMD */ { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (2)].lv),myynest,(yyvsp[(1) - (2)].i),&((yyvsp[(2) - (2)].lv).req_packhdl->idroot))) YYERROR; } ;} break; case 111: /* Line 1464 of yacc.c */ #line 1012 "grammar.y" { int t=(yyvsp[(1) - (3)].lv).Typ(); sleftv r; memset(&r,0,sizeof(sleftv)); if ((BEGIN_RINGidroot), TRUE)) YYERROR; } else { if (iiDeclCommand(&r,&(yyvsp[(3) - (3)].lv),myynest,t,&((yyvsp[(3) - (3)].lv).req_packhdl->idroot))) YYERROR; } leftv v=&(yyvsp[(1) - (3)].lv); while (v->next!=NULL) v=v->next; v->next=(leftv)omAllocBin(sleftv_bin); memcpy(v->next,&r,sizeof(sleftv)); (yyval.lv)=(yyvsp[(1) - (3)].lv); ;} break; case 112: /* Line 1464 of yacc.c */ #line 1033 "grammar.y" { if (iiDeclCommand(&(yyval.lv),&(yyvsp[(2) - (2)].lv),myynest,(yyvsp[(1) - (2)].i),&((yyvsp[(2) - (2)].lv).req_packhdl->idroot))) YYERROR; ;} break; case 115: /* Line 1464 of yacc.c */ #line 1046 "grammar.y" { leftv v = &(yyvsp[(2) - (5)].lv); while (v->next!=NULL) { v=v->next; } v->next = (leftv)omAllocBin(sleftv_bin); memcpy(v->next,&((yyvsp[(4) - (5)].lv)),sizeof(sleftv)); (yyval.lv) = (yyvsp[(2) - (5)].lv); ;} break; case 116: /* Line 1464 of yacc.c */ #line 1060 "grammar.y" { // let rInit take care of any errors (yyval.i)=rOrderName((yyvsp[(1) - (1)].name)); ;} break; case 117: /* Line 1464 of yacc.c */ #line 1068 "grammar.y" { memset(&(yyval.lv),0,sizeof((yyval.lv))); intvec *iv = new intvec(2); (*iv)[0] = 1; (*iv)[1] = (yyvsp[(1) - (1)].i); (yyval.lv).rtyp = INTVEC_CMD; (yyval.lv).data = (void *)iv; ;} break; case 118: /* Line 1464 of yacc.c */ #line 1077 "grammar.y" { memset(&(yyval.lv),0,sizeof((yyval.lv))); leftv sl = &(yyvsp[(3) - (4)].lv); int slLength; { slLength = exprlist_length(sl); int l = 2 + slLength; intvec *iv = new intvec(l); (*iv)[0] = slLength; (*iv)[1] = (yyvsp[(1) - (4)].i); int i = 2; while ((iTyp() == INT_CMD) { (*iv)[i++] = (int)((long)(sl->Data())); } else if ((sl->Typ() == INTVEC_CMD) ||(sl->Typ() == INTMAT_CMD)) { intvec *ivv = (intvec *)(sl->Data()); int ll = 0,l = ivv->length(); for (; l>0; l--) { (*iv)[i++] = (*ivv)[ll++]; } } else { delete iv; (yyvsp[(3) - (4)].lv).CleanUp(); MYYERROR("wrong type in ordering"); } sl = sl->next; } (yyval.lv).rtyp = INTVEC_CMD; (yyval.lv).data = (void *)iv; } (yyvsp[(3) - (4)].lv).CleanUp(); ;} break; case 120: /* Line 1464 of yacc.c */ #line 1123 "grammar.y" { (yyval.lv) = (yyvsp[(1) - (3)].lv); (yyval.lv).next = (sleftv *)omAllocBin(sleftv_bin); memcpy((yyval.lv).next,&(yyvsp[(3) - (3)].lv),sizeof(sleftv)); ;} break; case 122: /* Line 1464 of yacc.c */ #line 1133 "grammar.y" { (yyval.lv) = (yyvsp[(2) - (3)].lv); ;} break; case 123: /* Line 1464 of yacc.c */ #line 1139 "grammar.y" { expected_parms = TRUE; ;} break; case 124: /* Line 1464 of yacc.c */ #line 1146 "grammar.y" { (yyval.i) = (yyvsp[(1) - (1)].i); ;} break; case 125: /* Line 1464 of yacc.c */ #line 1148 "grammar.y" { (yyval.i) = (yyvsp[(1) - (1)].i); ;} break; case 126: /* Line 1464 of yacc.c */ #line 1150 "grammar.y" { (yyval.i) = (yyvsp[(1) - (1)].i); ;} break; case 127: /* Line 1464 of yacc.c */ #line 1159 "grammar.y" { if ((yyvsp[(1) - (2)].i) != '<') YYERROR; if((feFilePending=feFopen((yyvsp[(2) - (2)].name),"r",NULL,TRUE))==NULL) YYERROR; ;} break; case 128: /* Line 1464 of yacc.c */ #line 1162 "grammar.y" { newFile((yyvsp[(2) - (4)].name),feFilePending); ;} break; case 129: /* Line 1464 of yacc.c */ #line 1167 "grammar.y" { feHelp((yyvsp[(2) - (3)].name)); omFree((ADDRESS)(yyvsp[(2) - (3)].name)); ;} break; case 130: /* Line 1464 of yacc.c */ #line 1172 "grammar.y" { feHelp(NULL); ;} break; case 131: /* Line 1464 of yacc.c */ #line 1179 "grammar.y" { singular_example((yyvsp[(2) - (3)].name)); omFree((ADDRESS)(yyvsp[(2) - (3)].name)); ;} break; case 132: /* Line 1464 of yacc.c */ #line 1187 "grammar.y" { if (basePack!=(yyvsp[(2) - (2)].lv).req_packhdl) { if(iiExport(&(yyvsp[(2) - (2)].lv),0,currPack)) YYERROR; } else if (iiExport(&(yyvsp[(2) - (2)].lv),0)) YYERROR; ;} break; case 133: /* Line 1464 of yacc.c */ #line 1199 "grammar.y" { leftv v=&(yyvsp[(2) - (2)].lv); if (v->rtyp!=IDHDL) { if (v->name!=NULL) { Werror("`%s` is undefined in kill",v->name); } else WerrorS("kill what ?"); } else { killhdl((idhdl)v->data,v->req_packhdl); } ;} break; case 134: /* Line 1464 of yacc.c */ #line 1215 "grammar.y" { leftv v=&(yyvsp[(3) - (3)].lv); if (v->rtyp!=IDHDL) { if (v->name!=NULL) { Werror("`%s` is undefined in kill",v->name); } else WerrorS("kill what ?"); } else { killhdl((idhdl)v->data,v->req_packhdl); } ;} break; case 135: /* Line 1464 of yacc.c */ #line 1234 "grammar.y" { list_cmd((yyvsp[(3) - (4)].i),NULL,"// ",TRUE); ;} break; case 136: /* Line 1464 of yacc.c */ #line 1238 "grammar.y" { list_cmd((yyvsp[(3) - (4)].i),NULL,"// ",TRUE); ;} break; case 137: /* Line 1464 of yacc.c */ #line 1242 "grammar.y" { if ((yyvsp[(3) - (4)].i)==QRING_CMD) (yyvsp[(3) - (4)].i)=RING_CMD; list_cmd((yyvsp[(3) - (4)].i),NULL,"// ",TRUE); ;} break; case 138: /* Line 1464 of yacc.c */ #line 1247 "grammar.y" { list_cmd((yyvsp[(3) - (4)].i),NULL,"// ",TRUE); ;} break; case 139: /* Line 1464 of yacc.c */ #line 1251 "grammar.y" { list_cmd(RING_CMD,NULL,"// ",TRUE); ;} break; case 140: /* Line 1464 of yacc.c */ #line 1255 "grammar.y" { list_cmd((yyvsp[(3) - (4)].i),NULL,"// ",TRUE); ;} break; case 141: /* Line 1464 of yacc.c */ #line 1259 "grammar.y" { list_cmd(PROC_CMD,NULL,"// ",TRUE); ;} break; case 142: /* Line 1464 of yacc.c */ #line 1263 "grammar.y" { list_cmd(0,(yyvsp[(3) - (4)].lv).Fullname(),"// ",TRUE); (yyvsp[(3) - (4)].lv).CleanUp(); ;} break; case 143: /* Line 1464 of yacc.c */ #line 1268 "grammar.y" { if((yyvsp[(3) - (6)].lv).Typ() == PACKAGE_CMD) list_cmd((yyvsp[(5) - (6)].i),NULL,"// ",TRUE); (yyvsp[(3) - (6)].lv).CleanUp(); ;} break; case 144: /* Line 1464 of yacc.c */ #line 1274 "grammar.y" { if((yyvsp[(3) - (6)].lv).Typ() == PACKAGE_CMD) list_cmd((yyvsp[(5) - (6)].i),NULL,"// ",TRUE); (yyvsp[(3) - (6)].lv).CleanUp(); ;} break; case 145: /* Line 1464 of yacc.c */ #line 1280 "grammar.y" { if((yyvsp[(3) - (6)].lv).Typ() == PACKAGE_CMD) list_cmd((yyvsp[(5) - (6)].i),NULL,"// ",TRUE); (yyvsp[(3) - (6)].lv).CleanUp(); ;} break; case 146: /* Line 1464 of yacc.c */ #line 1286 "grammar.y" { if((yyvsp[(3) - (6)].lv).Typ() == PACKAGE_CMD) list_cmd((yyvsp[(5) - (6)].i),NULL,"// ",TRUE); (yyvsp[(3) - (6)].lv).CleanUp(); ;} break; case 147: /* Line 1464 of yacc.c */ #line 1292 "grammar.y" { if((yyvsp[(3) - (6)].lv).Typ() == PACKAGE_CMD) list_cmd((yyvsp[(5) - (6)].i),NULL,"// ",TRUE); (yyvsp[(3) - (6)].lv).CleanUp(); ;} break; case 148: /* Line 1464 of yacc.c */ #line 1298 "grammar.y" { if((yyvsp[(3) - (6)].lv).Typ() == PACKAGE_CMD) list_cmd((yyvsp[(5) - (6)].i),NULL,"// ",TRUE); (yyvsp[(3) - (6)].lv).CleanUp(); ;} break; case 149: /* Line 1464 of yacc.c */ #line 1304 "grammar.y" { if((yyvsp[(3) - (6)].lv).Typ() == PACKAGE_CMD) list_cmd((yyvsp[(5) - (6)].i),NULL,"// ",TRUE); (yyvsp[(3) - (6)].lv).CleanUp(); ;} break; case 150: /* Line 1464 of yacc.c */ #line 1316 "grammar.y" { list_cmd(-1,NULL,"// ",TRUE); ;} break; case 151: /* Line 1464 of yacc.c */ #line 1322 "grammar.y" { yyInRingConstruction = TRUE; ;} break; case 152: /* Line 1464 of yacc.c */ #line 1331 "grammar.y" { const char *ring_name = (yyvsp[(2) - (8)].lv).name; ring b= rInit(&(yyvsp[(4) - (8)].lv), /* characteristik and list of parameters*/ &(yyvsp[(6) - (8)].lv), /* names of ringvariables */ &(yyvsp[(8) - (8)].lv)); /* ordering */ idhdl newRingHdl=NULL; if (b!=NULL) { newRingHdl=enterid(ring_name, myynest, RING_CMD, &((yyvsp[(2) - (8)].lv).req_packhdl->idroot),FALSE); (yyvsp[(2) - (8)].lv).CleanUp(); if (newRingHdl!=NULL) { IDRING(newRingHdl)=b; } else { rKill(b); } } yyInRingConstruction = FALSE; if (newRingHdl==NULL) { MYYERROR("cannot make ring"); } else { rSetHdl(newRingHdl); } ;} break; case 153: /* Line 1464 of yacc.c */ #line 1364 "grammar.y" { const char *ring_name = (yyvsp[(2) - (2)].lv).name; if (!inerror) rDefault(ring_name); yyInRingConstruction = FALSE; (yyvsp[(2) - (2)].lv).CleanUp(); ;} break; case 154: /* Line 1464 of yacc.c */ #line 1371 "grammar.y" { yyInRingConstruction = FALSE; if (iiAssignCR(&(yyvsp[(2) - (4)].lv),&(yyvsp[(4) - (4)].lv))) YYERROR; ;} break; case 155: /* Line 1464 of yacc.c */ #line 1379 "grammar.y" { if (((yyvsp[(1) - (2)].i)!=LIB_CMD)||(jjLOAD((yyvsp[(2) - (2)].name),TRUE))) YYERROR; ;} break; case 158: /* Line 1464 of yacc.c */ #line 1388 "grammar.y" { if (((yyvsp[(1) - (2)].i)==KEEPRING_CMD) && (myynest==0)) MYYERROR("only inside a proc allowed"); const char * n=(yyvsp[(2) - (2)].lv).Name(); if ((((yyvsp[(2) - (2)].lv).Typ()==RING_CMD)||((yyvsp[(2) - (2)].lv).Typ()==QRING_CMD)) && ((yyvsp[(2) - (2)].lv).rtyp==IDHDL)) { idhdl h=(idhdl)(yyvsp[(2) - (2)].lv).data; if ((yyvsp[(2) - (2)].lv).e!=NULL) h=rFindHdl((ring)(yyvsp[(2) - (2)].lv).Data(),NULL); //Print("setring %s lev %d (ptr:%x)\n",IDID(h),IDLEV(h),IDRING(h)); if ((yyvsp[(1) - (2)].i)==KEEPRING_CMD) { if (h!=NULL) { if (IDLEV(h)!=0) { if (iiExport(&(yyvsp[(2) - (2)].lv),myynest-1)) YYERROR; #if 1 idhdl p=IDRING(h)->idroot; idhdl root=p; int prevlev=myynest-1; while (p!=NULL) { if (IDLEV(p)==myynest) { idhdl old=root->get(IDID(p),prevlev); if (old!=NULL) { if (BVERBOSE(V_REDEFINE)) Warn("redefining %s",IDID(p)); killhdl2(old,&root,IDRING(h)); IDRING(h)->idroot=root; } IDLEV(p)=prevlev; } p=IDNEXT(p); } #endif } #ifdef USE_IILOCALRING iiLocalRing[myynest-1]=IDRING(h); #endif procstack->cRing=IDRING(h); procstack->cRingHdl=h; } else { Werror("%s is no identifier",n); (yyvsp[(2) - (2)].lv).CleanUp(); YYERROR; } } if (h!=NULL) rSetHdl(h); else { Werror("cannot find the name of the basering %s",n); (yyvsp[(2) - (2)].lv).CleanUp(); YYERROR; } (yyvsp[(2) - (2)].lv).CleanUp(); } else { Werror("%s is no name of a ring/qring",n); (yyvsp[(2) - (2)].lv).CleanUp(); YYERROR; } ;} break; case 159: /* Line 1464 of yacc.c */ #line 1460 "grammar.y" { type_cmd(&((yyvsp[(2) - (2)].lv))); ;} break; case 160: /* Line 1464 of yacc.c */ #line 1464 "grammar.y" { //Print("typ is %d, rtyp:%d\n",$1.Typ(),$1.rtyp); #ifdef SIQ if ((yyvsp[(1) - (1)].lv).rtyp!=COMMAND) { #endif if ((yyvsp[(1) - (1)].lv).Typ()==UNKNOWN) { if ((yyvsp[(1) - (1)].lv).name!=NULL) { Werror("`%s` is undefined",(yyvsp[(1) - (1)].lv).name); omFree((ADDRESS)(yyvsp[(1) - (1)].lv).name); } YYERROR; } #ifdef SIQ } #endif (yyvsp[(1) - (1)].lv).Print(&sLastPrinted); (yyvsp[(1) - (1)].lv).CleanUp(currRing); if (errorreported) YYERROR; ;} break; case 161: /* Line 1464 of yacc.c */ #line 1493 "grammar.y" { int i; TESTSETINT((yyvsp[(3) - (5)].lv),i); if (i!=0) { newBuffer( (yyvsp[(5) - (5)].name), BT_if); } else { omFree((ADDRESS)(yyvsp[(5) - (5)].name)); currentVoice->ifsw=1; } ;} break; case 162: /* Line 1464 of yacc.c */ #line 1506 "grammar.y" { if (currentVoice->ifsw==1) { currentVoice->ifsw=0; newBuffer( (yyvsp[(2) - (2)].name), BT_else); } else { if (currentVoice->ifsw!=2) { Warn("`else` without `if` in level %d",myynest); } omFree((ADDRESS)(yyvsp[(2) - (2)].name)); } currentVoice->ifsw=0; ;} break; case 163: /* Line 1464 of yacc.c */ #line 1523 "grammar.y" { int i; TESTSETINT((yyvsp[(3) - (5)].lv),i); if (i) { if (exitBuffer(BT_break)) YYERROR; } currentVoice->ifsw=0; ;} break; case 164: /* Line 1464 of yacc.c */ #line 1532 "grammar.y" { if (exitBuffer(BT_break)) YYERROR; currentVoice->ifsw=0; ;} break; case 165: /* Line 1464 of yacc.c */ #line 1537 "grammar.y" { if (contBuffer(BT_break)) YYERROR; currentVoice->ifsw=0; ;} break; case 166: /* Line 1464 of yacc.c */ #line 1545 "grammar.y" { /* -> if(!$2) break; $3; continue;*/ char * s = (char *)omAlloc( strlen((yyvsp[(2) - (3)].name)) + strlen((yyvsp[(3) - (3)].name)) + 36); sprintf(s,"whileif (!(%s)) break;\n%scontinue;\n " ,(yyvsp[(2) - (3)].name),(yyvsp[(3) - (3)].name)); newBuffer(s,BT_break); omFree((ADDRESS)(yyvsp[(2) - (3)].name)); omFree((ADDRESS)(yyvsp[(3) - (3)].name)); ;} break; case 167: /* Line 1464 of yacc.c */ #line 1557 "grammar.y" { /* $2 */ /* if (!$3) break; $5; $4; continue; */ char * s = (char *)omAlloc( strlen((yyvsp[(3) - (5)].name))+strlen((yyvsp[(4) - (5)].name))+strlen((yyvsp[(5) - (5)].name))+36); sprintf(s,"forif (!(%s)) break;\n%s%s;\ncontinue;\n " ,(yyvsp[(3) - (5)].name),(yyvsp[(5) - (5)].name),(yyvsp[(4) - (5)].name)); omFree((ADDRESS)(yyvsp[(3) - (5)].name)); omFree((ADDRESS)(yyvsp[(4) - (5)].name)); omFree((ADDRESS)(yyvsp[(5) - (5)].name)); newBuffer(s,BT_break); s = (char *)omAlloc( strlen((yyvsp[(2) - (5)].name)) + 3); sprintf(s,"%s;\n",(yyvsp[(2) - (5)].name)); omFree((ADDRESS)(yyvsp[(2) - (5)].name)); newBuffer(s,BT_if); ;} break; case 168: /* Line 1464 of yacc.c */ #line 1576 "grammar.y" { idhdl h = enterid((yyvsp[(2) - (3)].name),myynest,PROC_CMD,&IDROOT,TRUE); if (h==NULL) {omFree((ADDRESS)(yyvsp[(2) - (3)].name));omFree((ADDRESS)(yyvsp[(3) - (3)].name)); YYERROR;} iiInitSingularProcinfo(IDPROC(h),"", (yyvsp[(2) - (3)].name), 0, 0); IDPROC(h)->data.s.body = (char *)omAlloc(strlen((yyvsp[(3) - (3)].name))+31);; sprintf(IDPROC(h)->data.s.body,"parameter list #;\n%s;return();\n\n",(yyvsp[(3) - (3)].name)); omFree((ADDRESS)(yyvsp[(3) - (3)].name)); omFree((ADDRESS)(yyvsp[(2) - (3)].name)); ;} break; case 169: /* Line 1464 of yacc.c */ #line 1586 "grammar.y" { idhdl h = enterid((yyvsp[(1) - (3)].name),myynest,PROC_CMD,&IDROOT,TRUE); if (h==NULL) { omFree((ADDRESS)(yyvsp[(1) - (3)].name)); omFree((ADDRESS)(yyvsp[(2) - (3)].name)); omFree((ADDRESS)(yyvsp[(3) - (3)].name)); YYERROR; } char *args=iiProcArgs((yyvsp[(2) - (3)].name),FALSE); omFree((ADDRESS)(yyvsp[(2) - (3)].name)); iiInitSingularProcinfo(IDPROC(h),"", (yyvsp[(1) - (3)].name), 0, 0); IDPROC(h)->data.s.body = (char *)omAlloc(strlen((yyvsp[(3) - (3)].name))+strlen(args)+14);; sprintf(IDPROC(h)->data.s.body,"%s\n%s;return();\n\n",args,(yyvsp[(3) - (3)].name)); omFree((ADDRESS)args); omFree((ADDRESS)(yyvsp[(3) - (3)].name)); omFree((ADDRESS)(yyvsp[(1) - (3)].name)); ;} break; case 170: /* Line 1464 of yacc.c */ #line 1605 "grammar.y" { omFree((ADDRESS)(yyvsp[(3) - (4)].name)); idhdl h = enterid((yyvsp[(1) - (4)].name),myynest,PROC_CMD,&IDROOT,TRUE); if (h==NULL) { omFree((ADDRESS)(yyvsp[(1) - (4)].name)); omFree((ADDRESS)(yyvsp[(2) - (4)].name)); omFree((ADDRESS)(yyvsp[(4) - (4)].name)); YYERROR; } char *args=iiProcArgs((yyvsp[(2) - (4)].name),FALSE); omFree((ADDRESS)(yyvsp[(2) - (4)].name)); iiInitSingularProcinfo(IDPROC(h),"", (yyvsp[(1) - (4)].name), 0, 0); omFree((ADDRESS)(yyvsp[(1) - (4)].name)); IDPROC(h)->data.s.body = (char *)omAlloc(strlen((yyvsp[(4) - (4)].name))+strlen(args)+14);; sprintf(IDPROC(h)->data.s.body,"%s\n%s;return();\n\n",args,(yyvsp[(4) - (4)].name)); omFree((ADDRESS)args); omFree((ADDRESS)(yyvsp[(4) - (4)].name)); ;} break; case 171: /* Line 1464 of yacc.c */ #line 1628 "grammar.y" { // decl. of type proc p(int i) if ((yyvsp[(1) - (2)].i)==PARAMETER) { if (iiParameter(&(yyvsp[(2) - (2)].lv))) YYERROR; } else { if (iiAlias(&(yyvsp[(2) - (2)].lv))) YYERROR; } ;} break; case 172: /* Line 1464 of yacc.c */ #line 1634 "grammar.y" { // decl. of type proc p(i) sleftv tmp_expr; if ((yyvsp[(1) - (2)].i)==ALIAS_CMD) MYYERROR("alias requires a type"); if ((iiDeclCommand(&tmp_expr,&(yyvsp[(2) - (2)].lv),myynest,DEF_CMD,&IDROOT)) || (iiParameter(&tmp_expr))) YYERROR; ;} break; case 173: /* Line 1464 of yacc.c */ #line 1646 "grammar.y" { iiRETURNEXPR.Copy(&(yyvsp[(3) - (4)].lv)); (yyvsp[(3) - (4)].lv).CleanUp(); if (exitBuffer(BT_proc)) YYERROR; ;} break; case 174: /* Line 1464 of yacc.c */ #line 1652 "grammar.y" { if ((yyvsp[(1) - (3)].i)==RETURN) { iiRETURNEXPR.Init(); iiRETURNEXPR.rtyp=NONE; if (exitBuffer(BT_proc)) YYERROR; } ;} break; /* Line 1464 of yacc.c */ #line 4315 "grammar.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 lookahead 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 lookahead 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); } *++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; #if !defined(yyoverflow) || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (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); } singular-4.0.3+ds/Singular/grammar.h000066400000000000000000000112541266270727000173430ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 2.4.3. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 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 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* 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 { DOTDOT = 258, EQUAL_EQUAL = 259, GE = 260, LE = 261, MINUSMINUS = 262, NOT = 263, NOTEQUAL = 264, PLUSPLUS = 265, COLONCOLON = 266, ARROW = 267, GRING_CMD = 268, BIGINTMAT_CMD = 269, INTMAT_CMD = 270, PROC_CMD = 271, RING_CMD = 272, BEGIN_RING = 273, IDEAL_CMD = 274, MAP_CMD = 275, MATRIX_CMD = 276, MODUL_CMD = 277, NUMBER_CMD = 278, POLY_CMD = 279, RESOLUTION_CMD = 280, VECTOR_CMD = 281, BETTI_CMD = 282, COEFFS_CMD = 283, COEF_CMD = 284, CONTRACT_CMD = 285, DEGREE_CMD = 286, DEG_CMD = 287, DIFF_CMD = 288, DIM_CMD = 289, DIVISION_CMD = 290, ELIMINATION_CMD = 291, E_CMD = 292, FAREY_CMD = 293, FETCH_CMD = 294, FREEMODULE_CMD = 295, KEEPRING_CMD = 296, HILBERT_CMD = 297, HOMOG_CMD = 298, IMAP_CMD = 299, INDEPSET_CMD = 300, INTERRED_CMD = 301, INTERSECT_CMD = 302, JACOB_CMD = 303, JET_CMD = 304, KBASE_CMD = 305, KOSZUL_CMD = 306, LEADCOEF_CMD = 307, LEADEXP_CMD = 308, LEAD_CMD = 309, LEADMONOM_CMD = 310, LIFTSTD_CMD = 311, LIFT_CMD = 312, MAXID_CMD = 313, MINBASE_CMD = 314, MINOR_CMD = 315, MINRES_CMD = 316, MODULO_CMD = 317, MONOM_CMD = 318, MRES_CMD = 319, MULTIPLICITY_CMD = 320, ORD_CMD = 321, PAR_CMD = 322, PARDEG_CMD = 323, PREIMAGE_CMD = 324, QUOTIENT_CMD = 325, QHWEIGHT_CMD = 326, REDUCE_CMD = 327, REGULARITY_CMD = 328, RES_CMD = 329, SBA_CMD = 330, SIMPLIFY_CMD = 331, SORTVEC_CMD = 332, SRES_CMD = 333, STD_CMD = 334, SUBST_CMD = 335, SYZYGY_CMD = 336, VAR_CMD = 337, VDIM_CMD = 338, WEDGE_CMD = 339, WEIGHT_CMD = 340, VALTVARS = 341, VMAXDEG = 342, VMAXMULT = 343, VNOETHER = 344, VMINPOLY = 345, END_RING = 346, CMD_1 = 347, CMD_2 = 348, CMD_3 = 349, CMD_12 = 350, CMD_13 = 351, CMD_23 = 352, CMD_123 = 353, CMD_M = 354, ROOT_DECL = 355, ROOT_DECL_LIST = 356, RING_DECL = 357, RING_DECL_LIST = 358, EXAMPLE_CMD = 359, EXPORT_CMD = 360, HELP_CMD = 361, KILL_CMD = 362, LIB_CMD = 363, LISTVAR_CMD = 364, SETRING_CMD = 365, TYPE_CMD = 366, STRINGTOK = 367, BLOCKTOK = 368, INT_CONST = 369, UNKNOWN_IDENT = 370, RINGVAR = 371, PROC_DEF = 372, APPLY = 373, ASSUME_CMD = 374, BREAK_CMD = 375, CONTINUE_CMD = 376, ELSE_CMD = 377, EVAL = 378, QUOTE = 379, FOR_CMD = 380, IF_CMD = 381, SYS_BREAK = 382, WHILE_CMD = 383, RETURN = 384, PARAMETER = 385, SYSVAR = 386, UMINUS = 387 }; #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif singular-4.0.3+ds/Singular/grammar.y000066400000000000000000001256251266270727000173740ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: SINGULAR shell grammatik */ %{ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if 0 void debug_list(leftv v) { idhdl r=basePackHdl; idhdl h; BOOLEAN found=FALSE; const char *nn=v->name; h=IDROOT->get(nn,myynest); if (h!=NULL) { Print("Curr::%s, (%s)\n",nn,Tok2Cmdname((int)IDTYP(h))); found=TRUE; } else Print("`%s` not found in IDROOT\n",nn); while (r!=NULL) { if ((IDTYP(r)==PACKAGE_CMD) || (IDTYP(r)==RING_CMD) || (IDTYP(r)==QRING_CMD)) { h=IDPACKAGE(r)->idroot->get(nn,myynest); if (h!=NULL) { Print("%s::%s, (%s)\n",r->id,nn,Tok2Cmdname((int)IDTYP(h))); found=TRUE; } else Print("%s::%s not found\n",r->id,nn); } if (r==basePackHdl) r=IDPACKAGE(r)->idroot; r=r->next; if (r==basePackHdl) break; } if (!found) { listall(TRUE); } } #endif /* From the bison docu: By defining the macro `YYMAXDEPTH', you can control how deep the parser stack can become before a stack overflow occurs. Define the macro with a value that is an integer. This value is the maximum number of tokens that can be shifted (and not reduced) before overflow. It must be a constant expression whose value is known at compile time. The stack space allowed is not necessarily allocated. If you specify a large value for `YYMAXDEPTH', the parser actually allocates a small stack at first, and then makes it bigger by stages as needed. This increasing allocation happens automatically and silently. Therefore, you do not need to make `YYMAXDEPTH' painfully small merely to save space for ordinary inputs that do not need much stack. The default value of `YYMAXDEPTH', if you do not define it, is 10000. */ #define YYMAXDEPTH MAX_INT_VAL extern int yylineno; extern FILE* yyin; const char * currid; BOOLEAN yyInRingConstruction=FALSE; BOOLEAN expected_parms; int cmdtok; int inerror = 0; #define TESTSETINT(a,i) \ if ((a).Typ() != INT_CMD) \ { \ WerrorS("no int expression"); \ YYERROR; \ } \ (i) = (int)((long)(a).Data());(a).CleanUp() #define MYYERROR(a) { WerrorS(a); YYERROR; } void yyerror(const char * fmt) { BOOLEAN old_errorreported=errorreported; errorreported = TRUE; if (currid!=NULL) { killid(currid,&IDROOT); currid = NULL; } if(inerror==0) { { if ((strlen(fmt)>1) && (strncmp(fmt,"parse",5)!=0) && (strncmp(fmt,"syntax",6)!=0)) WerrorS(fmt); Werror( "error occurred in or before %s line %d: `%s`" ,VoiceName(), yylineno, my_yylinebuf); } if (cmdtok!=0) { const char *s=Tok2Cmdname(cmdtok); if (expected_parms) { Werror("expected %s-expression. type \'help %s;\'",s,s); } else { Werror("wrong type declaration. type \'help %s;\'",s); } } if (!old_errorreported && (lastreserved!=NULL)) { Werror("last reserved name was `%s`",lastreserved); } inerror=1; } if ((currentVoice!=NULL) && (currentVoice->prev!=NULL) && (myynest>0) #ifdef HAVE_SDB && ((sdb_flags &1)==0) #endif ) { Werror("leaving %s",VoiceName()); } } %} /* %expect 22 */ %pure_parser /* special symbols */ %token DOTDOT %token EQUAL_EQUAL %token GE %token LE %token MINUSMINUS %token NOT %token NOTEQUAL %token PLUSPLUS %token COLONCOLON %token ARROW /* types, part 1 (ring indep.)*/ %token GRING_CMD %token BIGINTMAT_CMD %token INTMAT_CMD %token PROC_CMD %token RING_CMD /* valid when ring defined ! */ %token BEGIN_RING /* types, part 2 */ %token IDEAL_CMD %token MAP_CMD %token MATRIX_CMD %token MODUL_CMD %token NUMBER_CMD %token POLY_CMD %token RESOLUTION_CMD %token VECTOR_CMD /* end types */ /* ring dependent cmd:*/ %token BETTI_CMD %token COEFFS_CMD %token COEF_CMD %token CONTRACT_CMD %token DEGREE_CMD %token DEG_CMD %token DIFF_CMD %token DIM_CMD %token DIVISION_CMD %token ELIMINATION_CMD %token E_CMD %token FAREY_CMD %token FETCH_CMD %token FREEMODULE_CMD %token KEEPRING_CMD %token HILBERT_CMD %token HOMOG_CMD %token IMAP_CMD %token INDEPSET_CMD %token INTERRED_CMD %token INTERSECT_CMD %token JACOB_CMD %token JET_CMD %token KBASE_CMD %token KOSZUL_CMD %token LEADCOEF_CMD %token LEADEXP_CMD %token LEAD_CMD %token LEADMONOM_CMD %token LIFTSTD_CMD %token LIFT_CMD %token MAXID_CMD %token MINBASE_CMD %token MINOR_CMD %token MINRES_CMD %token MODULO_CMD %token MONOM_CMD %token MRES_CMD %token MULTIPLICITY_CMD %token ORD_CMD %token PAR_CMD %token PARDEG_CMD %token PREIMAGE_CMD %token QUOTIENT_CMD %token QHWEIGHT_CMD %token REDUCE_CMD %token REGULARITY_CMD %token RES_CMD %token SBA_CMD %token SIMPLIFY_CMD %token SORTVEC_CMD %token SRES_CMD %token STD_CMD %token SUBST_CMD %token SYZYGY_CMD %token VAR_CMD %token VDIM_CMD %token WEDGE_CMD %token WEIGHT_CMD /*system variables in ring block*/ %token VALTVARS %token VMAXDEG %token VMAXMULT %token VNOETHER %token VMINPOLY %token END_RING /* end of ring definitions */ %token CMD_1 %token CMD_2 %token CMD_3 %token CMD_12 %token CMD_13 %token CMD_23 %token CMD_123 %token CMD_M %token ROOT_DECL /* put variables of this type into the idroot list */ %token ROOT_DECL_LIST /* put variables of this type into the idroot list */ %token RING_DECL /* put variables of this type into the currRing list */ %token RING_DECL_LIST /* put variables of this type into the currRing list */ %token EXAMPLE_CMD %token EXPORT_CMD %token HELP_CMD %token KILL_CMD %token LIB_CMD %token LISTVAR_CMD %token SETRING_CMD %token TYPE_CMD %token STRINGTOK BLOCKTOK INT_CONST %token UNKNOWN_IDENT RINGVAR PROC_DEF /* control */ %token APPLY %token ASSUME_CMD %token BREAK_CMD %token CONTINUE_CMD %token ELSE_CMD %token EVAL %token QUOTE %token FOR_CMD %token IF_CMD %token SYS_BREAK %token WHILE_CMD %token RETURN %token PARAMETER /* system variables */ %token SYSVAR %type extendedid %type rlist ordering OrderingList orderelem %type stringexpr %type expr elemexpr exprlist expr_arithmetic %type declare_ip_variable left_value %type error %type ordername %type cmdeq %type setrings %type ringcmd1 %type mat_cmd %type '=' '<' '>' '+' '-' COLONCOLON %type '/' '[' ']' '^' ',' ';' /*%nonassoc '=' PLUSEQUAL DOTDOT*/ /*%nonassoc '=' DOTDOT COLONCOLON*/ %nonassoc '=' DOTDOT %left ',' %left '&' %left EQUAL_EQUAL NOTEQUAL %left '<' %left '+' '-' ':' %left '/' %left UMINUS NOT %left '^' %left '[' ']' %left '(' ')' %left PLUSPLUS MINUSMINUS %left COLONCOLON %left '.' %left ARROW %% lines: /**/ | lines pprompt { if (timerv) { writeTime("used time:"); startTimer(); } if (rtimerv) { writeRTime("used real time:"); startRTimer(); } prompt_char = '>'; #ifdef HAVE_SDB if (sdb_flags & 2) { sdb_flags=1; YYERROR; } #endif if(siCntrlc) { WerrorS("abort..."); while((currentVoice!=NULL) && (currentVoice->prev!=NULL)) exitVoice(); if (currentVoice!=NULL) currentVoice->ifsw=0; } if (errorreported) /* also catches abort... */ { yyerror(""); } if (inerror==2) PrintLn(); errorreported = inerror = cmdtok = 0; lastreserved = currid = NULL; expected_parms = siCntrlc = FALSE; } ; pprompt: flowctrl /* if, while, for, proc */ | command ';' /* commands returning no value */ {currentVoice->ifsw=0;} | declare_ip_variable ';' /* default initialization */ { $1.CleanUp(); currentVoice->ifsw=0;} | returncmd { YYACCEPT; } | SYS_BREAK { currentVoice->ifsw=0; iiDebug(); } | ';' /* ignore empty statements */ {currentVoice->ifsw=0;} | error ';' { #ifdef SIQ siq=0; #endif yyInRingConstruction = FALSE; currentVoice->ifsw=0; if (inerror) { /* bison failed here*/ if ((inerror!=3) && ($1' ')) { // 1: yyerror called // 2: scanner put actual string // 3: error rule put token+\n inerror=3; Print(" error at token `%s`\n",iiTwoOps($1)); } /**/ } if (!errorreported) WerrorS("...parse error"); yyerror(""); yyerrok; #ifdef HAVE_SDB if ((sdb_flags & 1) && currentVoice->pi!=NULL) { currentVoice->pi->trace_flag |=1; } else #endif if (myynest>0) { feBufferTypes t=currentVoice->Typ(); //PrintS("leaving yyparse\n"); exitBuffer(BT_proc); if (t==BT_example) YYACCEPT; else YYABORT; } else if (currentVoice->prev!=NULL) { exitVoice(); } #ifdef HAVE_SDB if (sdb_flags &2) sdb_flags=1; #endif } ; flowctrl: ifcmd | whilecmd | example_dummy | forcmd | proccmd | filecmd | helpcmd | examplecmd {if (currentVoice!=NULL) currentVoice->ifsw=0;} ; example_dummy : EXAMPLE_CMD BLOCKTOK { omFree((ADDRESS)$2); } ; command: assign | exportcmd | killcmd | listcmd | parametercmd | ringcmd | scriptcmd | setringcmd | typecmd ; assign: left_value exprlist { if(iiAssign(&$1,&$2)) YYERROR; } ; elemexpr: RINGVAR { if (currRing==NULL) MYYERROR("no ring active"); syMake(&$$,omStrDup($1)); } | extendedid { syMake(&$$,$1); } | elemexpr COLONCOLON elemexpr { if(iiExprArith2(&$$, &$1, COLONCOLON, &$3)) YYERROR; } | expr '.' elemexpr { if(iiExprArith2(&$$, &$1, '.', &$3)) YYERROR; } | elemexpr '(' ')' { if(iiExprArith1(&$$,&$1,'(')) YYERROR; } | elemexpr '(' exprlist ')' { if ($1.rtyp==UNKNOWN) { // for x(i)(j) if(iiExprArith2(&$$,&$1,'(',&$3)) YYERROR; } else { $1.next=(leftv)omAllocBin(sleftv_bin); memcpy($1.next,&$3,sizeof(sleftv)); if(iiExprArithM(&$$,&$1,'(')) YYERROR; } } | '[' exprlist ']' { if (currRingHdl==NULL) MYYERROR("no ring active"); int j = 0; memset(&$$,0,sizeof(sleftv)); $$.rtyp=VECTOR_CMD; leftv v = &$2; while (v!=NULL) { int i,t; sleftv tmp; memset(&tmp,0,sizeof(tmp)); i=iiTestConvert((t=v->Typ()),POLY_CMD); if((i==0) || (iiConvert(t /*v->Typ()*/,POLY_CMD,i,v,&tmp))) { pDelete((poly *)&$$.data); $2.CleanUp(); MYYERROR("expected '[poly,...'"); } poly p = (poly)tmp.CopyD(POLY_CMD); pSetCompP(p,++j); $$.data = (void *)pAdd((poly)$$.data,p); v->next=tmp.next;tmp.next=NULL; tmp.CleanUp(); v=v->next; } $2.CleanUp(); } | INT_CONST { memset(&$$,0,sizeof($$)); int i = atoi($1); /*remember not to omFree($1) *because it is a part of the scanner buffer*/ $$.rtyp = INT_CMD; $$.data = (void *)(long)i; /* check: out of range input */ int l = strlen($1)+2; number n; if (l >= MAX_INT_LEN) { char tmp[MAX_INT_LEN+5]; sprintf(tmp,"%d",i); if (strcmp(tmp,$1)!=0) { n_Read($1,&n,coeffs_BIGINT); $$.rtyp=BIGINT_CMD; $$.data = n; } } } | SYSVAR { memset(&$$,0,sizeof($$)); $$.rtyp = $1; $$.data = $$.Data(); } | stringexpr { memset(&$$,0,sizeof($$)); $$.rtyp = STRING_CMD; $$.data = $1; } | PROC_CMD '(' expr ')' { if(iiExprArith1(&$$,&$3,$1)) YYERROR; } | ROOT_DECL '(' expr ')' { if(iiExprArith1(&$$,&$3,$1)) YYERROR; } | ROOT_DECL_LIST '(' exprlist ')' { if(iiExprArithM(&$$,&$3,$1)) YYERROR; } | ROOT_DECL_LIST '(' ')' { if(iiExprArithM(&$$,NULL,$1)) YYERROR; } | RING_DECL '(' expr ')' { if(iiExprArith1(&$$,&$3,$1)) YYERROR; } | RING_DECL_LIST '(' exprlist ')' { if(iiExprArithM(&$$,&$3,$1)) YYERROR; } | RING_DECL_LIST '(' ')' { if(iiExprArithM(&$$,NULL,$1)) YYERROR; } | CMD_1 '(' expr ')' { if(iiExprArith1(&$$,&$3,$1)) YYERROR; } | CMD_12 '(' expr ')' { if(iiExprArith1(&$$,&$3,$1)) YYERROR; } | CMD_13 '(' expr ')' { if(iiExprArith1(&$$,&$3,$1)) YYERROR; } | CMD_123 '(' expr ')' { if(iiExprArith1(&$$,&$3,$1)) YYERROR; } | CMD_2 '(' expr ',' expr ')' { if(iiExprArith2(&$$,&$3,$1,&$5,TRUE)) YYERROR; } | CMD_12 '(' expr ',' expr ')' { if(iiExprArith2(&$$,&$3,$1,&$5,TRUE)) YYERROR; } | CMD_23 '(' expr ',' expr ')' { if(iiExprArith2(&$$,&$3,$1,&$5,TRUE)) YYERROR; } | CMD_123 '(' expr ',' expr ')' { if(iiExprArith2(&$$,&$3,$1,&$5,TRUE)) YYERROR; } | CMD_3 '(' expr ',' expr ',' expr ')' { if(iiExprArith3(&$$,$1,&$3,&$5,&$7)) YYERROR; } | CMD_13 '(' expr ',' expr ',' expr ')' { if(iiExprArith3(&$$,$1,&$3,&$5,&$7)) YYERROR; } | CMD_23 '(' expr ',' expr ',' expr ')' { if(iiExprArith3(&$$,$1,&$3,&$5,&$7)) YYERROR; } | CMD_123 '(' expr ',' expr ',' expr ')' { if(iiExprArith3(&$$,$1,&$3,&$5,&$7)) YYERROR; } | CMD_M '(' ')' { if(iiExprArithM(&$$,NULL,$1)) YYERROR; } | CMD_M '(' exprlist ')' { int b=iiExprArithM(&$$,&$3,$1); // handle branchTo if (b==TRUE) YYERROR; if (b==2) YYACCEPT; } | mat_cmd '(' expr ',' expr ',' expr ')' { if(iiExprArith3(&$$,$1,&$3,&$5,&$7)) YYERROR; } | mat_cmd '(' expr ')' { if(iiExprArith1(&$$,&$3,$1)) YYERROR; } | RING_CMD '(' rlist ',' rlist ',' ordering ')' { if(iiExprArith3(&$$,RING_CMD,&$3,&$5,&$7)) YYERROR; } | RING_CMD '(' expr ')' { if(iiExprArith1(&$$,&$3,RING_CMD)) YYERROR; } | extendedid ARROW BLOCKTOK { if (iiARROW(&$$,$1,$3)) YYERROR; } ; exprlist: exprlist ',' expr { leftv v = &$1; while (v->next!=NULL) { v=v->next; } v->next = (leftv)omAllocBin(sleftv_bin); memcpy(v->next,&($3),sizeof(sleftv)); $$ = $1; } | expr { $$ = $1; } ; expr: expr_arithmetic { /*if ($1.typ == eunknown) YYERROR;*/ $$ = $1; } | elemexpr { $$ = $1; } | '(' exprlist ')' { $$ = $2; } | expr '[' expr ',' expr ']' { if(iiExprArith3(&$$,'[',&$1,&$3,&$5)) YYERROR; } | expr '[' expr ']' { if(iiExprArith2(&$$,&$1,'[',&$3)) YYERROR; } | APPLY '(' expr ',' CMD_1 ')' { if (iiApply(&$$, &$3, $5, NULL)) YYERROR; } | APPLY '(' expr ',' CMD_12 ')' { if (iiApply(&$$, &$3, $5, NULL)) YYERROR; } | APPLY '(' expr ',' CMD_13 ')' { if (iiApply(&$$, &$3, $5, NULL)) YYERROR; } | APPLY '(' expr ',' CMD_123 ')' { if (iiApply(&$$, &$3, $5, NULL)) YYERROR; } | APPLY '(' expr ',' CMD_M ')' { if (iiApply(&$$, &$3, $5, NULL)) YYERROR; } | APPLY '(' expr ',' expr ')' { if (iiApply(&$$, &$3, 0, &$5)) YYERROR; } | quote_start expr quote_end { $$=$2; } | quote_start expr '=' expr quote_end { #ifdef SIQ siq++; if (siq>0) { if (iiExprArith2(&$$,&$2,'=',&$4)) YYERROR; } else #endif { memset(&$$,0,sizeof($$)); $$.rtyp=NONE; if (iiAssign(&$2,&$4)) YYERROR; } #ifdef SIQ siq--; #endif } | assume_start expr ',' expr quote_end { iiTestAssume(&$2,&$4); memset(&$$,0,sizeof($$)); $$.rtyp=NONE; } | EVAL '(' { #ifdef SIQ siq--; #endif } expr ')' { #ifdef SIQ if (siq<=0) $4.Eval(); #endif $$=$4; #ifdef SIQ siq++; #endif } ; quote_start: QUOTE '(' { #ifdef SIQ siq++; #endif } ; assume_start: ASSUME_CMD '(' { #ifdef SIQ siq++; #endif } ; quote_end: ')' { #ifdef SIQ siq--; #endif } ; expr_arithmetic: expr PLUSPLUS %prec PLUSPLUS { if(iiExprArith1(&$$,&$1,PLUSPLUS)) YYERROR; } | expr MINUSMINUS %prec MINUSMINUS { if(iiExprArith1(&$$,&$1,MINUSMINUS)) YYERROR; } | expr '+' expr { if(iiExprArith2(&$$,&$1,'+',&$3)) YYERROR; } | expr '-' expr { if(iiExprArith2(&$$,&$1,'-',&$3)) YYERROR; } | expr '/' expr { if(iiExprArith2(&$$,&$1,$2,&$3)) YYERROR; } | expr '^' expr { if(iiExprArith2(&$$,&$1,'^',&$3)) YYERROR; } | expr '<' expr { if(iiExprArith2(&$$,&$1,$2,&$3)) YYERROR; } | expr '&' expr { if(iiExprArith2(&$$,&$1,$2,&$3)) YYERROR; } | expr NOTEQUAL expr { if(iiExprArith2(&$$,&$1,NOTEQUAL,&$3)) YYERROR; } | expr EQUAL_EQUAL expr { if(iiExprArith2(&$$,&$1,EQUAL_EQUAL,&$3)) YYERROR; } | expr DOTDOT expr { if(iiExprArith2(&$$,&$1,DOTDOT,&$3)) YYERROR; } | expr ':' expr { if(iiExprArith2(&$$,&$1,':',&$3)) YYERROR; } | NOT expr { if (siq>0) { if (iiExprArith1(&$$,&$2,NOT)) YYERROR; } else { memset(&$$,0,sizeof($$)); int i; TESTSETINT($2,i); $$.rtyp = INT_CMD; $$.data = (void *)(long)(i == 0 ? 1 : 0); } } | '-' expr %prec UMINUS { if(iiExprArith1(&$$,&$2,'-')) YYERROR; } ; left_value: declare_ip_variable cmdeq { $$ = $1; } | exprlist '=' { if ($1.rtyp==0) { Werror("`%s` is undefined",$1.Fullname()); YYERROR; } else if (($1.rtyp==MODUL_CMD) // matrix m; m[2]=... && ($1.e!=NULL) && ($1.e->next==NULL)) { MYYERROR("matrix must have 2 indices"); } $$ = $1; } ; extendedid: UNKNOWN_IDENT | '`' expr '`' { if ($2.Typ()!=STRING_CMD) { MYYERROR("string expression expected"); } $$ = (char *)$2.CopyD(STRING_CMD); $2.CleanUp(); } ; declare_ip_variable: ROOT_DECL elemexpr { if (iiDeclCommand(&$$,&$2,myynest,$1,&($2.req_packhdl->idroot))) YYERROR; } | ROOT_DECL_LIST elemexpr { if (iiDeclCommand(&$$,&$2,myynest,$1,&($2.req_packhdl->idroot))) YYERROR; } | RING_DECL elemexpr { if (iiDeclCommand(&$$,&$2,myynest,$1,&(currRing->idroot), TRUE)) YYERROR; } | RING_DECL_LIST elemexpr { if (iiDeclCommand(&$$,&$2,myynest,$1,&(currRing->idroot), TRUE)) YYERROR; } | mat_cmd elemexpr '[' expr ']' '[' expr ']' { int r; TESTSETINT($4,r); int c; TESTSETINT($7,c); leftv v; idhdl h; if ($1 == MATRIX_CMD) { if (iiDeclCommand(&$$,&$2,myynest,$1,&(currRing->idroot), TRUE)) YYERROR; v=&$$; h=(idhdl)v->data; idDelete(&IDIDEAL(h)); IDMATRIX(h) = mpNew(r,c); if (IDMATRIX(h)==NULL) YYERROR; } else if ($1 == INTMAT_CMD) { if (iiDeclCommand(&$$,&$2,myynest,$1,&($2.req_packhdl->idroot))) YYERROR; v=&$$; h=(idhdl)v->data; delete IDINTVEC(h); IDINTVEC(h) = new intvec(r,c,0); if (IDINTVEC(h)==NULL) YYERROR; } else /* BIGINTMAT_CMD */ { if (iiDeclCommand(&$$,&$2,myynest,$1,&($2.req_packhdl->idroot))) YYERROR; v=&$$; h=(idhdl)v->data; delete IDBIMAT(h); IDBIMAT(h) = new bigintmat(r, c, coeffs_BIGINT); if (IDBIMAT(h)==NULL) YYERROR; } } | mat_cmd elemexpr { if ($1 == MATRIX_CMD) { if (iiDeclCommand(&$$,&$2,myynest,$1,&(currRing->idroot), TRUE)) YYERROR; } else if ($1 == INTMAT_CMD) { if (iiDeclCommand(&$$,&$2,myynest,$1,&($2.req_packhdl->idroot))) YYERROR; leftv v=&$$; idhdl h; do { h=(idhdl)v->data; delete IDINTVEC(h); IDINTVEC(h) = new intvec(1,1,0); v=v->next; } while (v!=NULL); } else /* BIGINTMAT_CMD */ { if (iiDeclCommand(&$$,&$2,myynest,$1,&($2.req_packhdl->idroot))) YYERROR; } } | declare_ip_variable ',' elemexpr { int t=$1.Typ(); sleftv r; memset(&r,0,sizeof(sleftv)); if ((BEGIN_RINGidroot), TRUE)) YYERROR; } else { if (iiDeclCommand(&r,&$3,myynest,t,&($3.req_packhdl->idroot))) YYERROR; } leftv v=&$1; while (v->next!=NULL) v=v->next; v->next=(leftv)omAllocBin(sleftv_bin); memcpy(v->next,&r,sizeof(sleftv)); $$=$1; } | PROC_CMD elemexpr { if (iiDeclCommand(&$$,&$2,myynest,$1,&($2.req_packhdl->idroot))) YYERROR; } ; stringexpr: STRINGTOK ; rlist: expr | '(' expr ',' exprlist ')' { leftv v = &$2; while (v->next!=NULL) { v=v->next; } v->next = (leftv)omAllocBin(sleftv_bin); memcpy(v->next,&($4),sizeof(sleftv)); $$ = $2; } ; ordername: UNKNOWN_IDENT { // let rInit take care of any errors $$=rOrderName($1); } ; orderelem: ordername { memset(&$$,0,sizeof($$)); intvec *iv = new intvec(2); (*iv)[0] = 1; (*iv)[1] = $1; $$.rtyp = INTVEC_CMD; $$.data = (void *)iv; } | ordername '(' exprlist ')' { memset(&$$,0,sizeof($$)); leftv sl = &$3; int slLength; { slLength = exprlist_length(sl); int l = 2 + slLength; intvec *iv = new intvec(l); (*iv)[0] = slLength; (*iv)[1] = $1; int i = 2; while ((iTyp() == INT_CMD) { (*iv)[i++] = (int)((long)(sl->Data())); } else if ((sl->Typ() == INTVEC_CMD) ||(sl->Typ() == INTMAT_CMD)) { intvec *ivv = (intvec *)(sl->Data()); int ll = 0,l = ivv->length(); for (; l>0; l--) { (*iv)[i++] = (*ivv)[ll++]; } } else { delete iv; $3.CleanUp(); MYYERROR("wrong type in ordering"); } sl = sl->next; } $$.rtyp = INTVEC_CMD; $$.data = (void *)iv; } $3.CleanUp(); } ; OrderingList: orderelem | orderelem ',' OrderingList { $$ = $1; $$.next = (sleftv *)omAllocBin(sleftv_bin); memcpy($$.next,&$3,sizeof(sleftv)); } ; ordering: orderelem | '(' OrderingList ')' { $$ = $2; } ; cmdeq: '=' { expected_parms = TRUE; } ; mat_cmd: MATRIX_CMD { $$ = $1; } | INTMAT_CMD { $$ = $1; } | BIGINTMAT_CMD { $$ = $1; } ; /* --------------------------------------------------------------------*/ /* section of pure commands */ /* --------------------------------------------------------------------*/ filecmd: '<' stringexpr { if ($1 != '<') YYERROR; if((feFilePending=feFopen($2,"r",NULL,TRUE))==NULL) YYERROR; } ';' { newFile($2,feFilePending); } ; helpcmd: HELP_CMD STRINGTOK ';' { feHelp($2); omFree((ADDRESS)$2); } | HELP_CMD ';' { feHelp(NULL); } ; examplecmd: EXAMPLE_CMD STRINGTOK ';' { singular_example($2); omFree((ADDRESS)$2); } ; exportcmd: EXPORT_CMD exprlist { if (basePack!=$2.req_packhdl) { if(iiExport(&$2,0,currPack)) YYERROR; } else if (iiExport(&$2,0)) YYERROR; } ; killcmd: KILL_CMD elemexpr { leftv v=&$2; if (v->rtyp!=IDHDL) { if (v->name!=NULL) { Werror("`%s` is undefined in kill",v->name); } else WerrorS("kill what ?"); } else { killhdl((idhdl)v->data,v->req_packhdl); } } | killcmd ',' elemexpr { leftv v=&$3; if (v->rtyp!=IDHDL) { if (v->name!=NULL) { Werror("`%s` is undefined in kill",v->name); } else WerrorS("kill what ?"); } else { killhdl((idhdl)v->data,v->req_packhdl); } } ; listcmd: LISTVAR_CMD '(' ROOT_DECL ')' { list_cmd($3,NULL,"// ",TRUE); } | LISTVAR_CMD '(' ROOT_DECL_LIST ')' { list_cmd($3,NULL,"// ",TRUE); } | LISTVAR_CMD '(' RING_DECL ')' { if ($3==QRING_CMD) $3=RING_CMD; list_cmd($3,NULL,"// ",TRUE); } | LISTVAR_CMD '(' RING_DECL_LIST ')' { list_cmd($3,NULL,"// ",TRUE); } | LISTVAR_CMD '(' RING_CMD ')' { list_cmd(RING_CMD,NULL,"// ",TRUE); } | LISTVAR_CMD '(' mat_cmd ')' { list_cmd($3,NULL,"// ",TRUE); } | LISTVAR_CMD '(' PROC_CMD ')' { list_cmd(PROC_CMD,NULL,"// ",TRUE); } | LISTVAR_CMD '(' elemexpr ')' { list_cmd(0,$3.Fullname(),"// ",TRUE); $3.CleanUp(); } | LISTVAR_CMD '(' elemexpr ',' ROOT_DECL ')' { if($3.Typ() == PACKAGE_CMD) list_cmd($5,NULL,"// ",TRUE); $3.CleanUp(); } | LISTVAR_CMD '(' elemexpr ',' ROOT_DECL_LIST ')' { if($3.Typ() == PACKAGE_CMD) list_cmd($5,NULL,"// ",TRUE); $3.CleanUp(); } | LISTVAR_CMD '(' elemexpr ',' RING_DECL ')' { if($3.Typ() == PACKAGE_CMD) list_cmd($5,NULL,"// ",TRUE); $3.CleanUp(); } | LISTVAR_CMD '(' elemexpr ',' RING_DECL_LIST ')' { if($3.Typ() == PACKAGE_CMD) list_cmd($5,NULL,"// ",TRUE); $3.CleanUp(); } | LISTVAR_CMD '(' elemexpr ',' RING_CMD ')' { if($3.Typ() == PACKAGE_CMD) list_cmd($5,NULL,"// ",TRUE); $3.CleanUp(); } | LISTVAR_CMD '(' elemexpr ',' mat_cmd ')' { if($3.Typ() == PACKAGE_CMD) list_cmd($5,NULL,"// ",TRUE); $3.CleanUp(); } | LISTVAR_CMD '(' elemexpr ',' PROC_CMD ')' { if($3.Typ() == PACKAGE_CMD) list_cmd($5,NULL,"// ",TRUE); $3.CleanUp(); } //| LISTVAR_CMD '(' elemexpr ',' elemexpr ')' // { // //if($3.Typ() == PACKAGE_CMD) // // list_cmd($5,NULL,"// ",TRUE); // $3.CleanUp(); // } | LISTVAR_CMD '(' ')' { list_cmd(-1,NULL,"// ",TRUE); } ; ringcmd1: RING_CMD { yyInRingConstruction = TRUE; } ; ringcmd: ringcmd1 elemexpr cmdeq rlist ',' /* description of coeffs */ rlist ',' /* var names */ ordering /* list of (multiplier ordering (weight(s))) */ { const char *ring_name = $2.name; ring b= rInit(&$4, /* characteristik and list of parameters*/ &$6, /* names of ringvariables */ &$8); /* ordering */ idhdl newRingHdl=NULL; if (b!=NULL) { newRingHdl=enterid(ring_name, myynest, RING_CMD, &($2.req_packhdl->idroot),FALSE); $2.CleanUp(); if (newRingHdl!=NULL) { IDRING(newRingHdl)=b; } else { rKill(b); } } yyInRingConstruction = FALSE; if (newRingHdl==NULL) { MYYERROR("cannot make ring"); } else { rSetHdl(newRingHdl); } } | ringcmd1 elemexpr { const char *ring_name = $2.name; if (!inerror) rDefault(ring_name); yyInRingConstruction = FALSE; $2.CleanUp(); } | ringcmd1 elemexpr cmdeq elemexpr { yyInRingConstruction = FALSE; if (iiAssignCR(&$2,&$4)) YYERROR; } ; scriptcmd: SYSVAR stringexpr { if (($1!=LIB_CMD)||(jjLOAD($2,TRUE))) YYERROR; } ; setrings: SETRING_CMD | KEEPRING_CMD ; setringcmd: setrings expr { if (($1==KEEPRING_CMD) && (myynest==0)) MYYERROR("only inside a proc allowed"); const char * n=$2.Name(); if ((($2.Typ()==RING_CMD)||($2.Typ()==QRING_CMD)) && ($2.rtyp==IDHDL)) { idhdl h=(idhdl)$2.data; if ($2.e!=NULL) h=rFindHdl((ring)$2.Data(),NULL); //Print("setring %s lev %d (ptr:%x)\n",IDID(h),IDLEV(h),IDRING(h)); if ($1==KEEPRING_CMD) { if (h!=NULL) { if (IDLEV(h)!=0) { if (iiExport(&$2,myynest-1)) YYERROR; #if 1 idhdl p=IDRING(h)->idroot; idhdl root=p; int prevlev=myynest-1; while (p!=NULL) { if (IDLEV(p)==myynest) { idhdl old=root->get(IDID(p),prevlev); if (old!=NULL) { if (BVERBOSE(V_REDEFINE)) Warn("redefining %s",IDID(p)); killhdl2(old,&root,IDRING(h)); IDRING(h)->idroot=root; } IDLEV(p)=prevlev; } p=IDNEXT(p); } #endif } #ifdef USE_IILOCALRING iiLocalRing[myynest-1]=IDRING(h); #endif procstack->cRing=IDRING(h); procstack->cRingHdl=h; } else { Werror("%s is no identifier",n); $2.CleanUp(); YYERROR; } } if (h!=NULL) rSetHdl(h); else { Werror("cannot find the name of the basering %s",n); $2.CleanUp(); YYERROR; } $2.CleanUp(); } else { Werror("%s is no name of a ring/qring",n); $2.CleanUp(); YYERROR; } } ; typecmd: TYPE_CMD expr { type_cmd(&($2)); } | exprlist { //Print("typ is %d, rtyp:%d\n",$1.Typ(),$1.rtyp); #ifdef SIQ if ($1.rtyp!=COMMAND) { #endif if ($1.Typ()==UNKNOWN) { if ($1.name!=NULL) { Werror("`%s` is undefined",$1.name); omFree((ADDRESS)$1.name); } YYERROR; } #ifdef SIQ } #endif $1.Print(&sLastPrinted); $1.CleanUp(currRing); if (errorreported) YYERROR; } ; /* --------------------------------------------------------------------*/ /* section of flow control */ /* --------------------------------------------------------------------*/ ifcmd: IF_CMD '(' expr ')' BLOCKTOK { int i; TESTSETINT($3,i); if (i!=0) { newBuffer( $5, BT_if); } else { omFree((ADDRESS)$5); currentVoice->ifsw=1; } } | ELSE_CMD BLOCKTOK { if (currentVoice->ifsw==1) { currentVoice->ifsw=0; newBuffer( $2, BT_else); } else { if (currentVoice->ifsw!=2) { Warn("`else` without `if` in level %d",myynest); } omFree((ADDRESS)$2); } currentVoice->ifsw=0; } | IF_CMD '(' expr ')' BREAK_CMD { int i; TESTSETINT($3,i); if (i) { if (exitBuffer(BT_break)) YYERROR; } currentVoice->ifsw=0; } | BREAK_CMD { if (exitBuffer(BT_break)) YYERROR; currentVoice->ifsw=0; } | CONTINUE_CMD { if (contBuffer(BT_break)) YYERROR; currentVoice->ifsw=0; } ; whilecmd: WHILE_CMD STRINGTOK BLOCKTOK { /* -> if(!$2) break; $3; continue;*/ char * s = (char *)omAlloc( strlen($2) + strlen($3) + 36); sprintf(s,"whileif (!(%s)) break;\n%scontinue;\n " ,$2,$3); newBuffer(s,BT_break); omFree((ADDRESS)$2); omFree((ADDRESS)$3); } ; forcmd: FOR_CMD STRINGTOK STRINGTOK STRINGTOK BLOCKTOK { /* $2 */ /* if (!$3) break; $5; $4; continue; */ char * s = (char *)omAlloc( strlen($3)+strlen($4)+strlen($5)+36); sprintf(s,"forif (!(%s)) break;\n%s%s;\ncontinue;\n " ,$3,$5,$4); omFree((ADDRESS)$3); omFree((ADDRESS)$4); omFree((ADDRESS)$5); newBuffer(s,BT_break); s = (char *)omAlloc( strlen($2) + 3); sprintf(s,"%s;\n",$2); omFree((ADDRESS)$2); newBuffer(s,BT_if); } ; proccmd: PROC_CMD extendedid BLOCKTOK { idhdl h = enterid($2,myynest,PROC_CMD,&IDROOT,TRUE); if (h==NULL) {omFree((ADDRESS)$2);omFree((ADDRESS)$3); YYERROR;} iiInitSingularProcinfo(IDPROC(h),"", $2, 0, 0); IDPROC(h)->data.s.body = (char *)omAlloc(strlen($3)+31);; sprintf(IDPROC(h)->data.s.body,"parameter list #;\n%s;return();\n\n",$3); omFree((ADDRESS)$3); omFree((ADDRESS)$2); } | PROC_DEF STRINGTOK BLOCKTOK { idhdl h = enterid($1,myynest,PROC_CMD,&IDROOT,TRUE); if (h==NULL) { omFree((ADDRESS)$1); omFree((ADDRESS)$2); omFree((ADDRESS)$3); YYERROR; } char *args=iiProcArgs($2,FALSE); omFree((ADDRESS)$2); iiInitSingularProcinfo(IDPROC(h),"", $1, 0, 0); IDPROC(h)->data.s.body = (char *)omAlloc(strlen($3)+strlen(args)+14);; sprintf(IDPROC(h)->data.s.body,"%s\n%s;return();\n\n",args,$3); omFree((ADDRESS)args); omFree((ADDRESS)$3); omFree((ADDRESS)$1); } | PROC_DEF STRINGTOK STRINGTOK BLOCKTOK { omFree((ADDRESS)$3); idhdl h = enterid($1,myynest,PROC_CMD,&IDROOT,TRUE); if (h==NULL) { omFree((ADDRESS)$1); omFree((ADDRESS)$2); omFree((ADDRESS)$4); YYERROR; } char *args=iiProcArgs($2,FALSE); omFree((ADDRESS)$2); iiInitSingularProcinfo(IDPROC(h),"", $1, 0, 0); omFree((ADDRESS)$1); IDPROC(h)->data.s.body = (char *)omAlloc(strlen($4)+strlen(args)+14);; sprintf(IDPROC(h)->data.s.body,"%s\n%s;return();\n\n",args,$4); omFree((ADDRESS)args); omFree((ADDRESS)$4); } ; parametercmd: PARAMETER declare_ip_variable { // decl. of type proc p(int i) if ($1==PARAMETER) { if (iiParameter(&$2)) YYERROR; } else { if (iiAlias(&$2)) YYERROR; } } | PARAMETER expr { // decl. of type proc p(i) sleftv tmp_expr; if ($1==ALIAS_CMD) MYYERROR("alias requires a type"); if ((iiDeclCommand(&tmp_expr,&$2,myynest,DEF_CMD,&IDROOT)) || (iiParameter(&tmp_expr))) YYERROR; } ; returncmd: RETURN '(' exprlist ')' { iiRETURNEXPR.Copy(&$3); $3.CleanUp(); if (exitBuffer(BT_proc)) YYERROR; } | RETURN '(' ')' { if ($1==RETURN) { iiRETURNEXPR.Init(); iiRETURNEXPR.rtyp=NONE; if (exitBuffer(BT_proc)) YYERROR; } } ; singular-4.0.3+ds/Singular/idrec.h000066400000000000000000000022111266270727000167740ustar00rootroot00000000000000#ifndef IDREC_H #define IDREC_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT interpreter type for variables */ #include #include #include class bigintmat; typedef union uutypes utypes; union uutypes { int i; ring uring; poly p; number n; ideal uideal; map umap; matrix umatrix; char * ustring; intvec * iv; bigintmat * bim; lists l; si_link li; package pack; procinfo * pinf; }; class idrec { public: /* !! do not change the first 6 entries !! (see subexpr.h: sleftv) */ idhdl next; const char *id; utypes data; attr attribute; BITSET flag; int typ; short lev; short ref; int id_i; idrec() { memset(this,0,sizeof(*this)); } idhdl get(const char * s, int lev); idhdl set(const char * s, int lev, int t/*typ*/, BOOLEAN init=TRUE); char * String(BOOLEAN typed = FALSE); // ~idrec(); }; #endif singular-4.0.3+ds/Singular/iparith.cc000066400000000000000000007041041266270727000175160ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: table driven kernel interface, used by interpreter */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SINGULAR_4_1 #include #endif # include #include #include #include //#include #include #include #include #include #include #include #include #include #include lists rDecompose(const ring r); ring rCompose(const lists L, const BOOLEAN check_comp=TRUE); // defaults for all commands: NO_PLURAL | NO_RING | ALLOW_ZERODIVISOR #ifdef HAVE_PLURAL #include #include #include #include #define PLURAL_MASK 3 #else /* HAVE_PLURAL */ #define PLURAL_MASK 0 #endif /* HAVE_PLURAL */ #ifdef HAVE_RINGS #define RING_MASK 4 #define ZERODIVISOR_MASK 8 #else #define RING_MASK 0 #define ZERODIVISOR_MASK 0 #endif #define ALLOW_PLURAL 1 #define NO_PLURAL 0 #define COMM_PLURAL 2 #define ALLOW_RING 4 #define NO_RING 0 #define NO_ZERODIVISOR 8 #define ALLOW_ZERODIVISOR 0 // bit 4 for warning, if used at toplevel #define WARN_RING 16 static BOOLEAN check_valid(const int p, const int op); #ifdef SINGULAR_4_1 // helper routine to catch all library/test parts which need to be changed // shall go away after the transition static void iiReWrite(const char *s) { Print("please rewrite the use of >>%s<< in >>%s<<\n" "%s is depreciated or changed in Singular 4-1\n",s,my_yylinebuf,s); } #endif /*=============== types =====================*/ struct sValCmdTab { short cmd; short start; }; typedef sValCmdTab jjValCmdTab[]; struct _scmdnames { char *name; short alias; short tokval; short toktype; }; typedef struct _scmdnames cmdnames; typedef char * (*Proc1)(char *); struct sValCmd1 { proc1 p; short cmd; short res; short arg; short valid_for; }; typedef BOOLEAN (*proc2)(leftv,leftv,leftv); struct sValCmd2 { proc2 p; short cmd; short res; short arg1; short arg2; short valid_for; }; typedef BOOLEAN (*proc3)(leftv,leftv,leftv,leftv); struct sValCmd3 { proc3 p; short cmd; short res; short arg1; short arg2; short arg3; short valid_for; }; struct sValCmdM { proc1 p; short cmd; short res; short number_of_args; /* -1: any, -2: any >0, .. */ short valid_for; }; typedef struct { cmdnames *sCmds; /**< array of existing commands */ struct sValCmd1 *psValCmd1; struct sValCmd2 *psValCmd2; struct sValCmd3 *psValCmd3; struct sValCmdM *psValCmdM; int nCmdUsed; /**< number of commands used */ int nCmdAllocated; /**< number of commands-slots allocated */ int nLastIdentifier; /**< valid indentifieres are slot 1..nLastIdentifier */ } SArithBase; /*---------------------------------------------------------------------* * File scope Variables (Variables share by several functions in * the same file ) * *---------------------------------------------------------------------*/ static SArithBase sArithBase; /**< Base entry for arithmetic */ /*---------------------------------------------------------------------* * Extern Functions declarations * *---------------------------------------------------------------------*/ static int _gentable_sort_cmds(const void *a, const void *b); extern int iiArithRemoveCmd(char *szName); extern int iiArithAddCmd(const char *szName, short nAlias, short nTokval, short nToktype, short nPos=-1); /*============= proc =======================*/ static int iiTabIndex(const jjValCmdTab dArithTab, const int len, const int op); static Subexpr jjMakeSub(leftv e); /*============= vars ======================*/ extern int cmdtok; extern BOOLEAN expected_parms; #define ii_div_by_0 "div. by 0" int iiOp; /* the current operation*/ /*=================== simple helpers =================*/ static int iin_Int(number &n,coeffs cf) { long l=n_Int(n,cf); int i=(int)l; if ((long)i==l) return l; return 0; } poly pHeadProc(poly p) { return pHead(p); } int iiTokType(int op) { for (int i=0;iData(); int bb = (int)(long)(v->Data()); if (errorreported) return TRUE; bigintmat *cc=NULL; switch (iiOp) { case '+': cc=bimAdd(aa,bb); break; case '-': cc=bimSub(aa,bb); break; case '*': cc=bimMult(aa,bb); break; } res->data=(char *)cc; return cc==NULL; } static BOOLEAN jjOP_I_BIM(leftv res, leftv u, leftv v) { return jjOP_BIM_I(res, v, u); } static BOOLEAN jjOP_BIM_BI(leftv res, leftv u, leftv v) { bigintmat* aa= (bigintmat *)u->Data(); number bb = (number)(v->Data()); if (errorreported) return TRUE; bigintmat *cc=NULL; switch (iiOp) { case '*': cc=bimMult(aa,bb,coeffs_BIGINT); break; } res->data=(char *)cc; return cc==NULL; } static BOOLEAN jjOP_BI_BIM(leftv res, leftv u, leftv v) { return jjOP_BIM_BI(res, v, u); } static BOOLEAN jjOP_IV_I(leftv res, leftv u, leftv v) { intvec* aa= (intvec *)u->CopyD(INTVEC_CMD); int bb = (int)(long)(v->Data()); if (errorreported) return TRUE; switch (iiOp) { case '+': (*aa) += bb; break; case '-': (*aa) -= bb; break; case '*': (*aa) *= bb; break; case '/': case INTDIV_CMD: (*aa) /= bb; break; case '%': (*aa) %= bb; break; } res->data=(char *)aa; return FALSE; } static BOOLEAN jjOP_I_IV(leftv res, leftv u, leftv v) { return jjOP_IV_I(res,v,u); } static BOOLEAN jjOP_IM_I(leftv res, leftv u, leftv v) { intvec* aa= (intvec *)u->CopyD(INTVEC_CMD); int bb = (int)(long)(v->Data()); int i=si_min(aa->rows(),aa->cols()); switch (iiOp) { case '+': for (;i>0;i--) IMATELEM(*aa,i,i) += bb; break; case '-': for (;i>0;i--) IMATELEM(*aa,i,i) -= bb; break; } res->data=(char *)aa; return FALSE; } static BOOLEAN jjOP_I_IM(leftv res, leftv u, leftv v) { return jjOP_IM_I(res,v,u); } static BOOLEAN jjCOLON(leftv res, leftv u, leftv v) { int l=(int)(long)v->Data(); if (l>=0) { int d=(int)(long)u->Data(); intvec *vv=new intvec(l); int i; for(i=l-1;i>=0;i--) { (*vv)[i]=d; } res->data=(char *)vv; } return (l<0); } static BOOLEAN jjDOTDOT(leftv res, leftv u, leftv v) { res->data=(char *)new intvec((int)(long)u->Data(),(int)(long)v->Data()); return FALSE; } static void jjEQUAL_REST(leftv res,leftv u,leftv v); static BOOLEAN jjCOMPARE_IV(leftv res, leftv u, leftv v) { intvec* a = (intvec * )(u->Data()); intvec* b = (intvec * )(v->Data()); int r=a->compare(b); switch (iiOp) { case '<': res->data = (char *) (r<0); break; case '>': res->data = (char *) (r>0); break; case LE: res->data = (char *) (r<=0); break; case GE: res->data = (char *) (r>=0); break; case EQUAL_EQUAL: case NOTEQUAL: /* negation handled by jjEQUAL_REST */ res->data = (char *) (r==0); break; } jjEQUAL_REST(res,u,v); if(r==-2) { WerrorS("size incompatible"); return TRUE; } return FALSE; } static BOOLEAN jjCOMPARE_BIM(leftv res, leftv u, leftv v) { bigintmat* a = (bigintmat * )(u->Data()); bigintmat* b = (bigintmat * )(v->Data()); int r=a->compare(b); switch (iiOp) { case '<': res->data = (char *) (r<0); break; case '>': res->data = (char *) (r>0); break; case LE: res->data = (char *) (r<=0); break; case GE: res->data = (char *) (r>=0); break; case EQUAL_EQUAL: case NOTEQUAL: /* negation handled by jjEQUAL_REST */ res->data = (char *) (r==0); break; } jjEQUAL_REST(res,u,v); if(r==-2) { WerrorS("size incompatible"); return TRUE; } return FALSE; } static BOOLEAN jjCOMPARE_IV_I(leftv res, leftv u, leftv v) { intvec* a = (intvec * )(u->Data()); int b = (int)(long)(v->Data()); int r=a->compare(b); switch (iiOp) { case '<': res->data = (char *) (r<0); break; case '>': res->data = (char *) (r>0); break; case LE: res->data = (char *) (r<=0); break; case GE: res->data = (char *) (r>=0); break; case EQUAL_EQUAL: case NOTEQUAL: /* negation handled by jjEQUAL_REST */ res->data = (char *) (r==0); break; } jjEQUAL_REST(res,u,v); return FALSE; } static BOOLEAN jjCOMPARE_P(leftv res, leftv u, leftv v) { poly p=(poly)u->Data(); poly q=(poly)v->Data(); int r=pCmp(p,q); if (r==0) { number h=nSub(pGetCoeff(p),pGetCoeff(q)); /* compare lead coeffs */ r = -1+nIsZero(h)+2*nGreaterZero(h); /* -1: <, 0:==, 1: > */ nDelete(&h); } else if (p==NULL) { if (q==NULL) { /* compare 0, 0 */ r=0; } else if(pIsConstant(q)) { /* compare 0, const */ r = 1-2*nGreaterZero(pGetCoeff(q)); /* -1: <, 1: > */ } } else if (q==NULL) { if (pIsConstant(p)) { /* compare const, 0 */ r = -1+2*nGreaterZero(pGetCoeff(p)); /* -1: <, 1: > */ } } switch (iiOp) { case '<': res->data = (char *) (r < 0); break; case '>': res->data = (char *) (r > 0); break; case LE: res->data = (char *) (r <= 0); break; case GE: res->data = (char *) (r >= 0); break; //case EQUAL_EQUAL: //case NOTEQUAL: /* negation handled by jjEQUAL_REST */ // res->data = (char *) (r == 0); // break; } jjEQUAL_REST(res,u,v); return FALSE; } static BOOLEAN jjCOMPARE_S(leftv res, leftv u, leftv v) { char* a = (char * )(u->Data()); char* b = (char * )(v->Data()); int result = strcmp(a,b); switch (iiOp) { case '<': res->data = (char *) (result < 0); break; case '>': res->data = (char *) (result > 0); break; case LE: res->data = (char *) (result <= 0); break; case GE: res->data = (char *) (result >= 0); break; case EQUAL_EQUAL: case NOTEQUAL: /* negation handled by jjEQUAL_REST */ res->data = (char *) (result == 0); break; } jjEQUAL_REST(res,u,v); return FALSE; } static BOOLEAN jjOP_REST(leftv res, leftv u, leftv v) { if (u->Next()!=NULL) { u=u->next; res->next = (leftv)omAllocBin(sleftv_bin); return iiExprArith2(res->next,u,iiOp,v); } else if (v->Next()!=NULL) { v=v->next; res->next = (leftv)omAllocBin(sleftv_bin); return iiExprArith2(res->next,u,iiOp,v); } return FALSE; } static BOOLEAN jjPOWER_I(leftv res, leftv u, leftv v) { int b=(int)(long)u->Data(); int e=(int)(long)v->Data(); int rc = 1; BOOLEAN overflow=FALSE; if (e >= 0) { if (b==0) { rc=(e==0); } else if ((e==0)||(b==1)) { rc= 1; } else if (b== -1) { if (e&1) rc= -1; else rc= 1; } else { int oldrc; while ((e--)!=0) { oldrc=rc; rc *= b; if (!overflow) { if(rc/b!=oldrc) overflow=TRUE; } } if (overflow) WarnS("int overflow(^), result may be wrong"); } res->data = (char *)((long)rc); if (u!=NULL) return jjOP_REST(res,u,v); return FALSE; } else { WerrorS("exponent must be non-negative"); return TRUE; } } static BOOLEAN jjPOWER_BI(leftv res, leftv u, leftv v) { int e=(int)(long)v->Data(); number n=(number)u->Data(); if (e>=0) { n_Power(n,e,(number*)&res->data,coeffs_BIGINT); } else { WerrorS("exponent must be non-negative"); return TRUE; } if (u!=NULL) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjPOWER_N(leftv res, leftv u, leftv v) { int e=(int)(long)v->Data(); number n=(number)u->Data(); int d=0; if (e<0) { n=nInvers(n); e=-e; d=1; } number r; nPower(n,e,(number*)&r); res->data=(char*)r; if (d) nDelete(&n); if (u!=NULL) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjPOWER_P(leftv res, leftv u, leftv v) { int v_i=(int)(long)v->Data(); if (v_i<0) { WerrorS("exponent must be non-negative"); return TRUE; } poly u_p=(poly)u->CopyD(POLY_CMD); if ((u_p!=NULL) && ((v_i!=0) && ((long)pTotaldegree(u_p) > (signed long)currRing->bitmask / (signed long)v_i/2))) { Werror("OVERFLOW in power(d=%ld, e=%d, max=%ld)", pTotaldegree(u_p),v_i,currRing->bitmask/2); pDelete(&u_p); return TRUE; } res->data = (char *)pPower(u_p,v_i); if (u!=NULL) return jjOP_REST(res,u,v); return errorreported; /* pPower may set errorreported via Werror */ } static BOOLEAN jjPOWER_ID(leftv res, leftv u, leftv v) { res->data = (char *)id_Power((ideal)(u->Data()),(int)(long)(v->Data()), currRing); if (u!=NULL) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjPLUSMINUS_Gen(leftv res, leftv u, leftv v) { u=u->next; v=v->next; if (u==NULL) { if (v==NULL) return FALSE; /* u==NULL, v==NULL */ if (iiOp=='-') /* u==NULL, v<>NULL, iiOp=='-'*/ { do { if (res->next==NULL) res->next = (leftv)omAlloc0Bin(sleftv_bin); leftv tmp_v=v->next; v->next=NULL; BOOLEAN b=iiExprArith1(res->next,v,'-'); v->next=tmp_v; if (b) return TRUE; v=tmp_v; res=res->next; } while (v!=NULL); return FALSE; } loop /* u==NULL, v<>NULL, iiOp=='+' */ { res->next = (leftv)omAlloc0Bin(sleftv_bin); res=res->next; res->data = v->CopyD(); res->rtyp = v->Typ(); v=v->next; if (v==NULL) return FALSE; } } if (v!=NULL) /* u<>NULL, v<>NULL */ { do { res->next = (leftv)omAlloc0Bin(sleftv_bin); leftv tmp_u=u->next; u->next=NULL; leftv tmp_v=v->next; v->next=NULL; BOOLEAN b=iiExprArith2(res->next,u,iiOp,v); u->next=tmp_u; v->next=tmp_v; if (b) return TRUE; u=tmp_u; v=tmp_v; res=res->next; } while ((u!=NULL) && (v!=NULL)); return FALSE; } loop /* u<>NULL, v==NULL */ { res->next = (leftv)omAlloc0Bin(sleftv_bin); res=res->next; res->data = u->CopyD(); res->rtyp = u->Typ(); u=u->next; if (u==NULL) return FALSE; } } static BOOLEAN jjCOLCOL(leftv res, leftv u, leftv v) { idhdl packhdl; switch(u->Typ()) { case 0: { int name_err=0; if(isupper(u->name[0])) { const char *c=u->name+1; while((*c!='\0')&&(islower(*c)||(isdigit(*c)))) c++; if (*c!='\0') name_err=1; else { Print("%s of type 'ANY'. Trying load.\n", u->name); if(iiTryLoadLib(u, u->name)) { Werror("'%s' no such package", u->name); return TRUE; } syMake(u,u->name,NULL); } } else name_err=1; if(name_err) { Werror("'%s' is an invalid package name",u->name);return TRUE;} // and now, after the loading: use next case !!! no break !!! } case PACKAGE_CMD: packhdl = (idhdl)u->data; if((!IDPACKAGE(packhdl)->loaded) && (IDPACKAGE(packhdl)->language > LANG_TOP)) { Werror("'%s' not loaded", u->name); return TRUE; } if(v->rtyp == IDHDL) { v->name = omStrDup(v->name); } else if (v->rtyp!=0) { WerrorS("reserved name with ::"); return TRUE; } v->req_packhdl=IDPACKAGE(packhdl); syMake(v, v->name, packhdl); memcpy(res, v, sizeof(sleftv)); memset(v, 0, sizeof(sleftv)); break; case DEF_CMD: break; default: WerrorS(":: expected"); return TRUE; } return FALSE; } static BOOLEAN jjPLUS_I(leftv res, leftv u, leftv v) { unsigned int a=(unsigned int)(unsigned long)u->Data(); unsigned int b=(unsigned int)(unsigned long)v->Data(); unsigned int c=a+b; res->data = (char *)((long)c); if (((Sy_bit(31)&a)==(Sy_bit(31)&b))&&((Sy_bit(31)&a)!=(Sy_bit(31)&c))) { WarnS("int overflow(+), result may be wrong"); } return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjPLUS_BI(leftv res, leftv u, leftv v) { res->data = (char *)(n_Add((number)u->Data(), (number)v->Data(),coeffs_BIGINT)); return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjPLUS_N(leftv res, leftv u, leftv v) { res->data = (char *)(nAdd((number)u->Data(), (number)v->Data())); return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjPLUS_P(leftv res, leftv u, leftv v) { res->data = (char *)(pAdd((poly)u->CopyD(POLY_CMD) , (poly)v->CopyD(POLY_CMD))); return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjPLUS_IV(leftv res, leftv u, leftv v) { res->data = (char *)ivAdd((intvec*)(u->Data()), (intvec*)(v->Data())); if (res->data==NULL) { WerrorS("intmat size not compatible"); return TRUE; } return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjPLUS_BIM(leftv res, leftv u, leftv v) { res->data = (char *)bimAdd((bigintmat*)(u->Data()), (bigintmat*)(v->Data())); if (res->data==NULL) { WerrorS("bigintmat/cmatrix not compatible"); return TRUE; } return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjPLUS_MA(leftv res, leftv u, leftv v) { matrix A=(matrix)u->Data(); matrix B=(matrix)v->Data(); res->data = (char *)(mp_Add(A , B, currRing)); if (res->data==NULL) { Werror("matrix size not compatible(%dx%d, %dx%d)", MATROWS(A),MATCOLS(A),MATROWS(B),MATCOLS(B)); return TRUE; } return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjPLUS_MA_P(leftv res, leftv u, leftv v) { matrix m=(matrix)u->Data(); matrix p= mp_InitP(m->nrows,m->ncols,(poly)(v->CopyD(POLY_CMD)),currRing); if (iiOp=='+') res->data = (char *)mp_Add(m , p,currRing); else res->data = (char *)mp_Sub(m , p,currRing); idDelete((ideal *)&p); return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjPLUS_P_MA(leftv res, leftv u, leftv v) { return jjPLUS_MA_P(res,v,u); } static BOOLEAN jjPLUS_S(leftv res, leftv u, leftv v) { char* a = (char * )(u->Data()); char* b = (char * )(v->Data()); char* r = (char * )omAlloc(strlen(a) + strlen(b) + 1); strcpy(r,a); strcat(r,b); res->data=r; return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjPLUS_ID(leftv res, leftv u, leftv v) { res->data = (char *)idAdd((ideal)u->Data(),(ideal)v->Data()); return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjMINUS_I(leftv res, leftv u, leftv v) { void *ap=u->Data(); void *bp=v->Data(); int aa=(int)(long)ap; int bb=(int)(long)bp; int cc=aa-bb; unsigned int a=(unsigned int)(unsigned long)ap; unsigned int b=(unsigned int)(unsigned long)bp; unsigned int c=a-b; if (((Sy_bit(31)&a)!=(Sy_bit(31)&b))&&((Sy_bit(31)&a)!=(Sy_bit(31)&c))) { WarnS("int overflow(-), result may be wrong"); } res->data = (char *)((long)cc); return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjMINUS_BI(leftv res, leftv u, leftv v) { res->data = (char *)(n_Sub((number)u->Data(), (number)v->Data(),coeffs_BIGINT)); return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjMINUS_N(leftv res, leftv u, leftv v) { res->data = (char *)(nSub((number)u->Data(), (number)v->Data())); return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjMINUS_P(leftv res, leftv u, leftv v) { res->data = (char *)(pSub((poly)u->CopyD(POLY_CMD) , (poly)v->CopyD(POLY_CMD))); return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjMINUS_IV(leftv res, leftv u, leftv v) { res->data = (char *)ivSub((intvec*)(u->Data()), (intvec*)(v->Data())); if (res->data==NULL) { WerrorS("intmat size not compatible"); return TRUE; } return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjMINUS_BIM(leftv res, leftv u, leftv v) { res->data = (char *)bimSub((bigintmat*)(u->Data()), (bigintmat*)(v->Data())); if (res->data==NULL) { WerrorS("bigintmat/cmatrix not compatible"); return TRUE; } return jjPLUSMINUS_Gen(res,u,v); } static BOOLEAN jjMINUS_MA(leftv res, leftv u, leftv v) { matrix A=(matrix)u->Data(); matrix B=(matrix)v->Data(); res->data = (char *)(mp_Sub(A , B, currRing)); if (res->data==NULL) { Werror("matrix size not compatible(%dx%d, %dx%d)", MATROWS(A),MATCOLS(A),MATROWS(B),MATCOLS(B)); return TRUE; } return jjPLUSMINUS_Gen(res,u,v); return FALSE; } static BOOLEAN jjTIMES_I(leftv res, leftv u, leftv v) { int a=(int)(long)u->Data(); int b=(int)(long)v->Data(); int64 c=(int64)a * (int64)b; if ((c>INT_MAX)||(cdata = (char *)((long)((int)c)); if ((u->Next()!=NULL) || (v->Next()!=NULL)) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjTIMES_BI(leftv res, leftv u, leftv v) { res->data = (char *)(n_Mult( (number)u->Data(), (number)v->Data(),coeffs_BIGINT)); if ((v->next!=NULL) || (u->next!=NULL)) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjTIMES_N(leftv res, leftv u, leftv v) { res->data = (char *)(nMult( (number)u->Data(), (number)v->Data())); number n=(number)res->data; nNormalize(n); res->data=(char *)n; if ((v->next!=NULL) || (u->next!=NULL)) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjTIMES_P(leftv res, leftv u, leftv v) { poly a; poly b; if (v->next==NULL) { a=(poly)u->CopyD(POLY_CMD); // works also for VECTOR_CMD if (u->next==NULL) { b=(poly)v->CopyD(POLY_CMD); // works also for VECTOR_CMD if ((a!=NULL) && (b!=NULL) && ((long)pTotaldegree(a)>si_max((long)rVar(currRing),(long)currRing->bitmask/2)-(long)pTotaldegree(b))) { Warn("possible OVERFLOW in mult(d=%ld, d=%ld, max=%ld)", pTotaldegree(a),pTotaldegree(b),currRing->bitmask/2); } res->data = (char *)(pMult( a, b)); pNormalize((poly)res->data); return FALSE; } // u->next exists: copy v b=pCopy((poly)v->Data()); if ((a!=NULL) && (b!=NULL) && (pTotaldegree(a)+pTotaldegree(b)>si_max((long)rVar(currRing),(long)currRing->bitmask/2))) { Warn("possible OVERFLOW in mult(d=%ld, d=%ld, max=%ld)", pTotaldegree(a),pTotaldegree(b),currRing->bitmask/2); } res->data = (char *)(pMult( a, b)); pNormalize((poly)res->data); return jjOP_REST(res,u,v); } // v->next exists: copy u a=pCopy((poly)u->Data()); b=(poly)v->CopyD(POLY_CMD); // works also for VECTOR_CMD if ((a!=NULL) && (b!=NULL) && ((unsigned long)(pTotaldegree(a)+pTotaldegree(b))>=currRing->bitmask/2)) { pDelete(&a); pDelete(&b); WerrorS("OVERFLOW"); return TRUE; } res->data = (char *)(pMult( a, b)); pNormalize((poly)res->data); return jjOP_REST(res,u,v); } static BOOLEAN jjTIMES_ID(leftv res, leftv u, leftv v) { res->data = (char *)idMult((ideal)u->Data(),(ideal)v->Data()); id_Normalize((ideal)res->data,currRing); if ((v->next!=NULL) || (u->next!=NULL)) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjTIMES_IV(leftv res, leftv u, leftv v) { res->data = (char *)ivMult((intvec*)(u->Data()), (intvec*)(v->Data())); if (res->data==NULL) { WerrorS("intmat size not compatible"); return TRUE; } if ((v->next!=NULL) || (u->next!=NULL)) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjTIMES_BIM(leftv res, leftv u, leftv v) { res->data = (char *)bimMult((bigintmat*)(u->Data()), (bigintmat*)(v->Data())); if (res->data==NULL) { WerrorS("bigintmat/cmatrix not compatible"); return TRUE; } if ((v->next!=NULL) || (u->next!=NULL)) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjTIMES_MA_BI1(leftv res, leftv u, leftv v) { nMapFunc nMap=n_SetMap(coeffs_BIGINT,currRing->cf); if (nMap==NULL) return TRUE; number n=nMap((number)v->Data(),coeffs_BIGINT,currRing->cf); poly p=pNSet(n); ideal I= (ideal)mp_MultP((matrix)u->CopyD(MATRIX_CMD),p,currRing); res->data = (char *)I; return FALSE; } static BOOLEAN jjTIMES_MA_BI2(leftv res, leftv u, leftv v) { return jjTIMES_MA_BI1(res,v,u); } static BOOLEAN jjTIMES_MA_P1(leftv res, leftv u, leftv v) { poly p=(poly)v->CopyD(POLY_CMD); int r=pMaxComp(p);/* recompute the rank for the case ideal*vector*/ ideal I= (ideal)mp_MultP((matrix)u->CopyD(MATRIX_CMD),p,currRing); if (r>0) I->rank=r; id_Normalize(I,currRing); res->data = (char *)I; return FALSE; } static BOOLEAN jjTIMES_MA_P2(leftv res, leftv u, leftv v) { poly p=(poly)u->CopyD(POLY_CMD); int r=pMaxComp(p);/* recompute the rank for the case ideal*vector*/ ideal I= (ideal)pMultMp(p,(matrix)v->CopyD(MATRIX_CMD),currRing); if (r>0) I->rank=r; id_Normalize(I,currRing); res->data = (char *)I; return FALSE; } static BOOLEAN jjTIMES_MA_N1(leftv res, leftv u, leftv v) { number n=(number)v->CopyD(NUMBER_CMD); poly p=pNSet(n); res->data = (char *)mp_MultP((matrix)u->CopyD(MATRIX_CMD),p,currRing); id_Normalize((ideal)res->data,currRing); return FALSE; } static BOOLEAN jjTIMES_MA_N2(leftv res, leftv u, leftv v) { return jjTIMES_MA_N1(res,v,u); } static BOOLEAN jjTIMES_MA_I1(leftv res, leftv u, leftv v) { res->data = (char *)mp_MultI((matrix)u->CopyD(MATRIX_CMD),(int)(long)v->Data(),currRing); id_Normalize((ideal)res->data,currRing); return FALSE; } static BOOLEAN jjTIMES_MA_I2(leftv res, leftv u, leftv v) { return jjTIMES_MA_I1(res,v,u); } static BOOLEAN jjTIMES_MA(leftv res, leftv u, leftv v) { matrix A=(matrix)u->Data(); matrix B=(matrix)v->Data(); res->data = (char *)mp_Mult(A,B,currRing); if (res->data==NULL) { Werror("matrix size not compatible(%dx%d, %dx%d) in *", MATROWS(A),MATCOLS(A),MATROWS(B),MATCOLS(B)); return TRUE; } id_Normalize((ideal)res->data,currRing); if ((v->next!=NULL) || (u->next!=NULL)) return jjOP_REST(res,u,v); return FALSE; } static BOOLEAN jjGE_BI(leftv res, leftv u, leftv v) { number h=n_Sub((number)u->Data(),(number)v->Data(),coeffs_BIGINT); res->data = (char *) (n_GreaterZero(h,coeffs_BIGINT)||(n_IsZero(h,coeffs_BIGINT))); n_Delete(&h,coeffs_BIGINT); return FALSE; } static BOOLEAN jjGE_I(leftv res, leftv u, leftv v) { res->data = (char *)(long)((int)((long)u->Data()) >= (int)((long)v->Data())); return FALSE; } static BOOLEAN jjGE_N(leftv res, leftv u, leftv v) { res->data = (char *)(long) (nGreater((number)u->Data(),(number)v->Data()) || nEqual((number)u->Data(),(number)v->Data())); return FALSE; } static BOOLEAN jjGT_BI(leftv res, leftv u, leftv v) { number h=n_Sub((number)u->Data(),(number)v->Data(),coeffs_BIGINT); res->data = (char *)(long) (n_GreaterZero(h,coeffs_BIGINT)&&(!n_IsZero(h,coeffs_BIGINT))); n_Delete(&h,coeffs_BIGINT); return FALSE; } static BOOLEAN jjGT_I(leftv res, leftv u, leftv v) { res->data = (char *)(long)((int)((long)u->Data()) > (int)((long)v->Data())); return FALSE; } static BOOLEAN jjGT_N(leftv res, leftv u, leftv v) { res->data = (char *)(long)(nGreater((number)u->Data(),(number)v->Data())); return FALSE; } static BOOLEAN jjLE_BI(leftv res, leftv u, leftv v) { return jjGE_BI(res,v,u); } static BOOLEAN jjLE_I(leftv res, leftv u, leftv v) { res->data = (char *)(long)((int)((long)u->Data()) <= (int)((long)v->Data())); return FALSE; } static BOOLEAN jjLE_N(leftv res, leftv u, leftv v) { return jjGE_N(res,v,u); } static BOOLEAN jjLT_BI(leftv res, leftv u, leftv v) { return jjGT_BI(res,v,u); } static BOOLEAN jjLT_I(leftv res, leftv u, leftv v) { res->data = (char *)(long)((int)((long)u->Data()) < (int)((long)v->Data())); return FALSE; } static BOOLEAN jjLT_N(leftv res, leftv u, leftv v) { return jjGT_N(res,v,u); } static BOOLEAN jjDIVMOD_I(leftv res, leftv u, leftv v) { if (iiOp=='/') Warn("int division with `/`: use `div` instead in line >>%s<<",my_yylinebuf); int a= (int)(long)u->Data(); int b= (int)(long)v->Data(); if (b==0) { WerrorS(ii_div_by_0); return TRUE; } int c=a%b; int r=0; switch (iiOp) { case '%': r=c; break; case '/': case INTDIV_CMD: r=((a-c) /b); break; } res->data=(void *)((long)r); return FALSE; } static BOOLEAN jjDIV_BI(leftv res, leftv u, leftv v) { number q=(number)v->Data(); if (n_IsZero(q,coeffs_BIGINT)) { WerrorS(ii_div_by_0); return TRUE; } q = n_Div((number)u->Data(),q,coeffs_BIGINT); n_Normalize(q,coeffs_BIGINT); res->data = (char *)q; return FALSE; } static BOOLEAN jjDIV_N(leftv res, leftv u, leftv v) { number q=(number)v->Data(); if (nIsZero(q)) { WerrorS(ii_div_by_0); return TRUE; } q = nDiv((number)u->Data(),q); nNormalize(q); res->data = (char *)q; return FALSE; } static BOOLEAN jjDIV_P(leftv res, leftv u, leftv v) { poly q=(poly)v->Data(); if (q==NULL) { WerrorS(ii_div_by_0); return TRUE; } poly p=(poly)(u->Data()); if (p==NULL) { res->data=NULL; return FALSE; } if ((pNext(q)!=NULL) && (!rField_is_Ring(currRing))) { /* This means that q != 0 consists of at least two terms. Moreover, currRing is over a field. */ if(pGetComp(p)==0) { res->data=(void*)(singclap_pdivide(p /*(poly)(u->Data())*/ , q /*(poly)(v->Data())*/ ,currRing)); } else { int comps=pMaxComp(p); ideal I=idInit(comps,1); p=pCopy(p); poly h; int i; // conversion to a list of polys: while (p!=NULL) { i=pGetComp(p)-1; h=pNext(p); pNext(p)=NULL; pSetComp(p,0); I->m[i]=pAdd(I->m[i],p); p=h; } // division and conversion to vector: h=NULL; p=NULL; for(i=comps-1;i>=0;i--) { if (I->m[i]!=NULL) { h=singclap_pdivide(I->m[i],q,currRing); pSetCompP(h,i+1); p=pAdd(p,h); } } idDelete(&I); res->data=(void *)p; } } else { /* This means that q != 0 consists of just one term, or that currRing is over a coefficient ring. */ #ifdef HAVE_RINGS if (!rField_is_Domain(currRing)) { WerrorS("division only defined over coefficient domains"); return TRUE; } if (pNext(q)!=NULL) { WerrorS("division over a coefficient domain only implemented for terms"); return TRUE; } #endif res->data = (char *)pDivideM(pCopy(p),pHead(q)); } pNormalize((poly)res->data); return FALSE; } static BOOLEAN jjDIV_Ma(leftv res, leftv u, leftv v) { poly q=(poly)v->Data(); if (q==NULL) { WerrorS(ii_div_by_0); return TRUE; } matrix m=(matrix)(u->Data()); int r=m->rows(); int c=m->cols(); matrix mm=mpNew(r,c); int i,j; for(i=r;i>0;i--) { for(j=c;j>0;j--) { if (pNext(q)!=NULL) { MATELEM(mm,i,j) = singclap_pdivide( MATELEM(m,i,j) , q /*(poly)(v->Data())*/, currRing ); } else MATELEM(mm,i,j) = pDivideM(pCopy(MATELEM(m,i,j)),pHead(q)); } } id_Normalize((ideal)mm,currRing); res->data=(char *)mm; return FALSE; } static BOOLEAN jjEQUAL_BI(leftv res, leftv u, leftv v) { res->data = (char *)((long)n_Equal((number)u->Data(),(number)v->Data(),coeffs_BIGINT)); jjEQUAL_REST(res,u,v); return FALSE; } static BOOLEAN jjEQUAL_I(leftv res, leftv u, leftv v) { res->data = (char *)((int)((long)u->Data()) == (int)((long)v->Data())); jjEQUAL_REST(res,u,v); return FALSE; } static BOOLEAN jjEQUAL_Ma(leftv res, leftv u, leftv v) { res->data = (char *)((long)mp_Equal((matrix)u->Data(),(matrix)v->Data(),currRing)); jjEQUAL_REST(res,u,v); return FALSE; } static BOOLEAN jjEQUAL_N(leftv res, leftv u, leftv v) { res->data = (char *)((long)nEqual((number)u->Data(),(number)v->Data())); jjEQUAL_REST(res,u,v); return FALSE; } static BOOLEAN jjEQUAL_P(leftv res, leftv u, leftv v) { poly p=(poly)u->Data(); poly q=(poly)v->Data(); res->data = (char *) ((long)pEqualPolys(p,q)); jjEQUAL_REST(res,u,v); return FALSE; } static void jjEQUAL_REST(leftv res,leftv u,leftv v) { if ((res->data) && (u->next!=NULL) && (v->next!=NULL)) { int save_iiOp=iiOp; if (iiOp==NOTEQUAL) iiExprArith2(res,u->next,EQUAL_EQUAL,v->next); else iiExprArith2(res,u->next,iiOp,v->next); iiOp=save_iiOp; } if (iiOp==NOTEQUAL) res->data=(char *)(!(long)res->data); } static BOOLEAN jjAND_I(leftv res, leftv u, leftv v) { res->data = (char *)((long)u->Data() && (long)v->Data()); return FALSE; } static BOOLEAN jjOR_I(leftv res, leftv u, leftv v) { res->data = (char *)((long)u->Data() || (long)v->Data()); return FALSE; } static BOOLEAN jjINDEX_I(leftv res, leftv u, leftv v) { res->rtyp=u->rtyp; u->rtyp=0; res->data=u->data; u->data=NULL; res->name=u->name; u->name=NULL; res->e=u->e; u->e=NULL; if (res->e==NULL) res->e=jjMakeSub(v); else { Subexpr sh=res->e; while (sh->next != NULL) sh=sh->next; sh->next=jjMakeSub(v); } if (u->next!=NULL) { leftv rn=(leftv)omAlloc0Bin(sleftv_bin); BOOLEAN bo=iiExprArith2(rn,u->next,iiOp,v); res->next=rn; return bo; } return FALSE; } static BOOLEAN jjINDEX_IV(leftv res, leftv u, leftv v) { if ((u->rtyp!=IDHDL)||(u->e!=NULL)) { WerrorS("indexed object must have a name"); return TRUE; } intvec * iv=(intvec *)v->Data(); leftv p=NULL; int i; sleftv t; memset(&t,0,sizeof(t)); t.rtyp=INT_CMD; for (i=0;ilength(); i++) { t.data=(char *)((long)(*iv)[i]); if (p==NULL) { p=res; } else { p->next=(leftv)omAlloc0Bin(sleftv_bin); p=p->next; } p->rtyp=IDHDL; p->data=u->data; p->name=u->name; p->flag=u->flag; p->e=jjMakeSub(&t); } u->rtyp=0; u->data=NULL; u->name=NULL; return FALSE; } static BOOLEAN jjINDEX_P(leftv res, leftv u, leftv v) { poly p=(poly)u->Data(); int i=(int)(long)v->Data(); int j=0; while (p!=NULL) { j++; if (j==i) { res->data=(char *)pHead(p); return FALSE; } pIter(p); } return FALSE; } static BOOLEAN jjINDEX_P_IV(leftv res, leftv u, leftv v) { poly p=(poly)u->Data(); poly r=NULL; intvec *iv=(intvec *)v->CopyD(INTVEC_CMD); int i; int sum=0; for(i=iv->length()-1;i>=0;i--) sum+=(*iv)[i]; int j=0; while ((p!=NULL) && (sum>0)) { j++; for(i=iv->length()-1;i>=0;i--) { if (j==(*iv)[i]) { r=pAdd(r,pHead(p)); sum-=j; (*iv)[i]=0; break; } } pIter(p); } delete iv; res->data=(char *)r; return FALSE; } static BOOLEAN jjINDEX_V(leftv res, leftv u, leftv v) { poly p=(poly)u->CopyD(VECTOR_CMD); poly r=p; // pointer to the beginning of component i poly o=NULL; int i=(int)(long)v->Data(); while (p!=NULL) { if (pGetComp(p)!=i) { if (r==p) r=pNext(p); if (o!=NULL) { if (pNext(o)!=NULL) pLmDelete(&pNext(o)); p=pNext(o); } else pLmDelete(&p); } else { pSetComp(p, 0); p_SetmComp(p, currRing); o=p; p=pNext(o); } } res->data=(char *)r; return FALSE; } static BOOLEAN jjINDEX_V_IV(leftv res, leftv u, leftv v) { poly p=(poly)u->CopyD(VECTOR_CMD); if (p!=NULL) { poly r=pOne(); poly hp=r; intvec *iv=(intvec *)v->Data(); int i; loop { for(i=0;ilength();i++) { if (((int)pGetComp(p))==(*iv)[i]) { poly h; pSplit(p,&h); pNext(hp)=p; p=h; pIter(hp); break; } } if (p==NULL) break; if (i==iv->length()) { pLmDelete(&p); if (p==NULL) break; } } pLmDelete(&r); res->data=(char *)r; } return FALSE; } static BOOLEAN jjKLAMMER_rest(leftv res, leftv u, leftv v); static BOOLEAN jjKLAMMER(leftv res, leftv u, leftv v) { if(u->name==NULL) return TRUE; char * nn = (char *)omAlloc(strlen(u->name) + 14); sprintf(nn,"%s(%d)",u->name,(int)(long)v->Data()); omFree((ADDRESS)u->name); u->name=NULL; char *n=omStrDup(nn); omFree((ADDRESS)nn); syMake(res,n); if (u->next!=NULL) return jjKLAMMER_rest(res,u->next,v); return FALSE; } static BOOLEAN jjKLAMMER_IV(leftv res, leftv u, leftv v) { intvec * iv=(intvec *)v->Data(); leftv p=NULL; int i; long slen = strlen(u->name) + 14; char *n = (char*) omAlloc(slen); for (i=0;ilength(); i++) { if (p==NULL) { p=res; } else { p->next=(leftv)omAlloc0Bin(sleftv_bin); p=p->next; } sprintf(n,"%s(%d)",u->name,(*iv)[i]); syMake(p,omStrDup(n)); } omFree((ADDRESS)u->name); u->name = NULL; omFreeSize(n, slen); if (u->next!=NULL) return jjKLAMMER_rest(res,u->next,v); return FALSE; } static BOOLEAN jjKLAMMER_rest(leftv res, leftv u, leftv v) { leftv tmp=(leftv)omAllocBin(sleftv_bin); memset(tmp,0,sizeof(sleftv)); BOOLEAN b; if (v->Typ()==INTVEC_CMD) b=jjKLAMMER_IV(tmp,u,v); else b=jjKLAMMER(tmp,u,v); if (b) { omFreeBin(tmp,sleftv_bin); return TRUE; } leftv h=res; while (h->next!=NULL) h=h->next; h->next=tmp; return FALSE; } BOOLEAN jjPROC(leftv res, leftv u, leftv v) { void *d; Subexpr e; int typ; BOOLEAN t=FALSE; idhdl tmp_proc=NULL; if ((u->rtyp!=IDHDL)||(u->e!=NULL)) { tmp_proc=(idhdl)omAlloc0(sizeof(idrec)); tmp_proc->id="_auto"; tmp_proc->typ=PROC_CMD; tmp_proc->data.pinf=(procinfo *)u->Data(); tmp_proc->ref=1; d=u->data; u->data=(void *)tmp_proc; e=u->e; u->e=NULL; t=TRUE; typ=u->rtyp; u->rtyp=IDHDL; } BOOLEAN sl; if (u->req_packhdl==currPack) sl = iiMake_proc((idhdl)u->data,NULL,v); else sl = iiMake_proc((idhdl)u->data,u->req_packhdl,v); if (t) { u->rtyp=typ; u->data=d; u->e=e; omFreeSize(tmp_proc,sizeof(idrec)); } if (sl) return TRUE; memcpy(res,&iiRETURNEXPR,sizeof(sleftv)); iiRETURNEXPR.Init(); return FALSE; } static BOOLEAN jjMAP(leftv res, leftv u, leftv v) { //Print("try to map %s with %s\n",$3.Name(),$1.Name()); leftv sl=NULL; if ((v->e==NULL)&&(v->name!=NULL)) { map m=(map)u->Data(); sl=iiMap(m,v->name); } else { Werror("%s() expected",u->Name()); } if (sl==NULL) return TRUE; memcpy(res,sl,sizeof(sleftv)); omFreeBin((ADDRESS)sl, sleftv_bin); return FALSE; } static BOOLEAN jjCHINREM_BI(leftv res, leftv u, leftv v) { intvec *c=(intvec*)u->Data(); intvec* p=(intvec*)v->Data(); int rl=p->length(); number *x=(number *)omAlloc(rl*sizeof(number)); number *q=(number *)omAlloc(rl*sizeof(number)); int i; for(i=rl-1;i>=0;i--) { q[i]=n_Init((*p)[i], coeffs_BIGINT); x[i]=n_Init((*c)[i], coeffs_BIGINT); } CFArray iv(rl); number n=n_ChineseRemainderSym(x,q,rl,FALSE,iv,coeffs_BIGINT); for(i=rl-1;i>=0;i--) { n_Delete(&(q[i]),coeffs_BIGINT); n_Delete(&(x[i]),coeffs_BIGINT); } omFree(x); omFree(q); res->data=(char *)n; return FALSE; } #if 0 static BOOLEAN jjCHINREM_P(leftv res, leftv u, leftv v) { lists c=(lists)u->CopyD(); // list of poly intvec* p=(intvec*)v->Data(); int rl=p->length(); poly r=NULL,h, result=NULL; number *x=(number *)omAlloc(rl*sizeof(number)); number *q=(number *)omAlloc(rl*sizeof(number)); int i; for(i=rl-1;i>=0;i--) { q[i]=nlInit((*p)[i]); } loop { for(i=rl-1;i>=0;i--) { if (c->m[i].Typ()!=POLY_CMD) { Werror("poly expected at pos %d",i+1); for(i=rl-1;i>=0;i--) { nlDelete(&(q[i]),currRing); } omFree(x); omFree(q); // delete c return TRUE; } h=((poly)c->m[i].Data()); if (r==NULL) r=h; else if (pLmCmp(r,h)==-1) r=h; } if (r==NULL) break; for(i=rl-1;i>=0;i--) { h=((poly)c->m[i].Data()); if (pLmCmp(r,h)==0) { x[i]=pGetCoeff(h); h=pLmFreeAndNext(h); c->m[i].data=(char*)h; } else x[i]=nlInit(0); } number n=n_ChineseRemainder(x,q,rl,currRing->cf); for(i=rl-1;i>=0;i--) { nlDelete(&(x[i]),currRing); } h=pHead(r); pSetCoeff(h,n); result=pAdd(result,h); } for(i=rl-1;i>=0;i--) { nlDelete(&(q[i]),currRing); } omFree(x); omFree(q); res->data=(char *)result; return FALSE; } #endif static BOOLEAN jjALIGN_V(leftv res, leftv u, leftv v) { poly p=(poly)u->CopyD(); int s=(int)(long)v->Data(); if (s+p_MinComp(p,currRing)<=0) { p_Delete(&p,currRing);return TRUE;} p_Shift(&p,s,currRing); res->data=p; return FALSE; } static BOOLEAN jjALIGN_M(leftv res, leftv u, leftv v) { ideal M=(ideal)u->CopyD(); int s=(int)(long)v->Data(); for(int i=IDELEMS(M)-1; i>=0;i--) { if (s+p_MinComp(M->m[i],currRing)<=0) { id_Delete(&M,currRing);return TRUE;} } id_Shift(M,s,currRing); res->data=M; return FALSE; } static BOOLEAN jjCHINREM_ID(leftv res, leftv u, leftv v) { coeffs cf; lists c=(lists)u->CopyD(); // list of ideal or bigint/int lists pl=NULL; intvec *p=NULL; if (v->Typ()==LIST_CMD) pl=(lists)v->Data(); else p=(intvec*)v->Data(); int rl=c->nr+1; ideal result; ideal *x=(ideal *)omAlloc(rl*sizeof(ideal)); number *xx=NULL; int i; int return_type=c->m[0].Typ(); if ((return_type!=IDEAL_CMD) && (return_type!=MODUL_CMD) && (return_type!=MATRIX_CMD) && (return_type!=POLY_CMD)) { if((return_type!=BIGINT_CMD)&&(return_type!=INT_CMD)) { WerrorS("poly/ideal/module/matrix expected"); omFree(x); // delete c return TRUE; } else return_type=BIGINT_CMD; } if (return_type==BIGINT_CMD) cf=coeffs_BIGINT; else { cf=currRing->cf; if (nCoeff_is_Extension(cf) && (cf->extRing!=NULL)) cf=cf->extRing->cf; } nMapFunc nMap=n_SetMap(coeffs_BIGINT,cf); if (return_type!=BIGINT_CMD) { for(i=rl-1;i>=0;i--) { if (c->m[i].Typ()!=return_type) { Werror("%s expected at pos %d",Tok2Cmdname(return_type),i+1); omFree(x); // delete c return TRUE; } if (return_type==POLY_CMD) { x[i]=idInit(1,1); x[i]->m[0]=(poly)c->m[i].CopyD(); } else { x[i]=(ideal)c->m[i].CopyD(); } //c->m[i].Init(); } } else { if (nMap==NULL) { Werror("not implemented: map bigint -> %s", nCoeffString(cf)); return TRUE; } xx=(number *)omAlloc(rl*sizeof(number)); for(i=rl-1;i>=0;i--) { if (c->m[i].Typ()==INT_CMD) { xx[i]=n_Init(((int)(long)c->m[i].Data()),cf); } else if (c->m[i].Typ()==BIGINT_CMD) { xx[i]=nMap((number)c->m[i].Data(),coeffs_BIGINT,cf); } else { Werror("bigint expected at pos %d",i+1); omFree(x); // delete c omFree(xx); // delete c return TRUE; } } } number *q=(number *)omAlloc(rl*sizeof(number)); if (p!=NULL) { for(i=rl-1;i>=0;i--) { q[i]=n_Init((*p)[i], cf); } } else { for(i=rl-1;i>=0;i--) { if (pl->m[i].Typ()==INT_CMD) { q[i]=n_Init((int)(long)pl->m[i].Data(),cf); } else if (pl->m[i].Typ()==BIGINT_CMD) { q[i]=nMap((number)(pl->m[i].Data()),coeffs_BIGINT,cf); } else { Werror("bigint expected at pos %d",i+1); for(i++;idata=(char *)n; } else { result=id_ChineseRemainder(x,q,rl,currRing); // deletes also x c->Clean(); if ((return_type==POLY_CMD) &&(result!=NULL)) { res->data=(char *)result->m[0]; result->m[0]=NULL; idDelete(&result); } else res->data=(char *)result; } for(i=rl-1;i>=0;i--) { n_Delete(&(q[i]),cf); } omFree(q); res->rtyp=return_type; return result==NULL; } static BOOLEAN jjCOEF(leftv res, leftv u, leftv v) { poly p=(poly)v->Data(); if ((p==NULL)||(pNext(p)!=NULL)) return TRUE; res->data=(char *)mp_CoeffProc((poly)u->Data(),p /*(poly)v->Data()*/,currRing); return FALSE; } static BOOLEAN jjCOEFFS_Id(leftv res, leftv u, leftv v) { int i=pVar((poly)v->Data()); if (i==0) { WerrorS("ringvar expected"); return TRUE; } res->data=(char *)mp_Coeffs((ideal)u->CopyD(),i,currRing); return FALSE; } static BOOLEAN jjCOEFFS2_KB(leftv res, leftv u, leftv v) { poly p = pInit(); int i; for (i=1; i<=currRing->N; i++) { pSetExp(p, i, 1); } pSetm(p); res->data = (void*)idCoeffOfKBase((ideal)(u->Data()), (ideal)(v->Data()), p); pDelete(&p); return FALSE; } static BOOLEAN jjCONTRACT(leftv res, leftv u, leftv v) { res->data=(char *)idDiffOp((ideal)u->Data(),(ideal)v->Data(),FALSE); return FALSE; } static BOOLEAN jjDEG_M_IV(leftv res, leftv u, leftv v) { short *iv=iv2array((intvec *)v->Data(),currRing); ideal I=(ideal)u->Data(); int d=-1; int i; for(i=IDELEMS(I);i>=0;i--) d=si_max(d,(int)p_DegW(I->m[i],iv,currRing)); omFreeSize( (ADDRESS)iv, (rVar(currRing)+1)*sizeof(short) ); res->data = (char *)((long)d); return FALSE; } static BOOLEAN jjDEG_IV(leftv res, leftv u, leftv v) { poly p=(poly)u->Data(); if (p!=NULL) { short *iv=iv2array((intvec *)v->Data(),currRing); const long d = p_DegW(p,iv,currRing); omFreeSize( (ADDRESS)iv, (rVar(currRing)+1)*sizeof(short) ); res->data = (char *)(d); } else res->data=(char *)(long)(-1); return FALSE; } static BOOLEAN jjDIFF_P(leftv res, leftv u, leftv v) { int i=pVar((poly)v->Data()); if (i==0) { WerrorS("ringvar expected"); return TRUE; } res->data=(char *)pDiff((poly)(u->Data()),i); return FALSE; } static BOOLEAN jjDIFF_ID(leftv res, leftv u, leftv v) { int i=pVar((poly)v->Data()); if (i==0) { WerrorS("ringvar expected"); return TRUE; } res->data=(char *)idDiff((matrix)(u->Data()),i); return FALSE; } static BOOLEAN jjDIFF_ID_ID(leftv res, leftv u, leftv v) { res->data=(char *)idDiffOp((ideal)u->Data(),(ideal)v->Data()); return FALSE; } static BOOLEAN jjDIM2(leftv res, leftv v, leftv w) { assumeStdFlag(v); #ifdef HAVE_RINGS if (rField_is_Ring(currRing)) { //ring origR = currRing; //ring tempR = rCopy(origR); //coeffs new_cf=nInitChar(n_Q,NULL); //nKillChar(tempR->cf); //tempR->cf=new_cf; //rComplete(tempR); ideal vid = (ideal)v->Data(); int i = idPosConstant(vid); if ((i != -1) && (n_IsUnit(pGetCoeff(vid->m[i]),currRing->cf))) { /* ideal v contains unit; dim = -1 */ res->data = (char *)-1; return FALSE; } //rChangeCurrRing(tempR); //ideal vv = idrCopyR(vid, origR, currRing); ideal vv = id_Copy(vid, currRing); //ideal ww = idrCopyR((ideal)w->Data(), origR, currRing); ideal ww = id_Copy((ideal)w->Data(), currRing); /* drop degree zero generator from vv (if any) */ if (i != -1) pDelete(&vv->m[i]); long d = (long)scDimInt(vv, ww); if (rField_is_Ring_Z(currRing) && (i == -1)) d++; res->data = (char *)d; idDelete(&vv); idDelete(&ww); //rChangeCurrRing(origR); //rDelete(tempR); return FALSE; } #endif if(currRing->qideal==NULL) res->data = (char *)((long)scDimInt((ideal)(v->Data()),(ideal)w->Data())); else { ideal q=idSimpleAdd(currRing->qideal,(ideal)w->Data()); res->data = (char *)((long)scDimInt((ideal)(v->Data()),q)); idDelete(&q); } return FALSE; } static BOOLEAN jjDIVISION(leftv res, leftv u, leftv v) { ideal vi=(ideal)v->Data(); int vl= IDELEMS(vi); ideal ui=(ideal)u->Data(); int ul= IDELEMS(ui); ideal R; matrix U; ideal m = idLift(vi,ui,&R, FALSE,hasFlag(v,FLAG_STD),TRUE,&U); if (m==NULL) return TRUE; // now make sure that all matices have the corect size: matrix T = id_Module2formatedMatrix(m,vl,ul,currRing); int i; if (MATCOLS(U) != ul) { int mul=si_min(ul,MATCOLS(U)); matrix UU=mpNew(ul,ul); int j; for(i=mul;i>0;i--) { for(j=mul;j>0;j--) { MATELEM(UU,i,j)=MATELEM(U,i,j); MATELEM(U,i,j)=NULL; } } idDelete((ideal *)&U); U=UU; } // make sure that U is a diagonal matrix of units for(i=ul;i>0;i--) { if(MATELEM(U,i,i)==NULL) MATELEM(U,i,i)=pOne(); } lists L=(lists)omAllocBin(slists_bin); L->Init(3); L->m[0].rtyp=MATRIX_CMD; L->m[0].data=(void *)T; L->m[1].rtyp=u->Typ(); L->m[1].data=(void *)R; L->m[2].rtyp=MATRIX_CMD; L->m[2].data=(void *)U; res->data=(char *)L; return FALSE; } static BOOLEAN jjELIMIN(leftv res, leftv u, leftv v) { res->data=(char *)idElimination((ideal)u->Data(),(poly)v->Data()); //setFlag(res,FLAG_STD); return v->next!=NULL; //do not allow next like in eliminate(I,a(1..4)) } static BOOLEAN jjELIMIN_IV(leftv res, leftv u, leftv v) { poly p=pOne(); intvec *iv=(intvec*)v->Data(); for(int i=iv->length()-1; i>=0; i--) { pSetExp(p,(*iv)[i],1); } pSetm(p); res->data=(char *)idElimination((ideal)u->Data(),p); pLmDelete(&p); //setFlag(res,FLAG_STD); return FALSE; } static BOOLEAN jjEXPORTTO(leftv, leftv u, leftv v) { //Print("exportto %s -> %s\n",v->Name(),u->Name() ); return iiExport(v,0,IDPACKAGE((idhdl)u->data)); } static BOOLEAN jjERROR(leftv, leftv u) { WerrorS((char *)u->Data()); extern int inerror; inerror=3; return TRUE; } static BOOLEAN jjEXTGCD_BI(leftv res, leftv u, leftv v) { number uu=(number)u->Data();number vv=(number)v->Data(); lists L=(lists)omAllocBin(slists_bin); number a,b; number p0=n_ExtGcd(uu,vv,&a,&b,coeffs_BIGINT); L->Init(3); L->m[0].rtyp=BIGINT_CMD; L->m[0].data=(void *)p0; L->m[1].rtyp=BIGINT_CMD; L->m[1].data=(void *)a; L->m[2].rtyp=BIGINT_CMD; L->m[2].data=(void *)b; res->rtyp=LIST_CMD; res->data=(char *)L; return FALSE; } static BOOLEAN jjEXTGCD_I(leftv res, leftv u, leftv v) { int uu=(int)(long)u->Data();int vv=(int)(long)v->Data(); int p0=ABS(uu),p1=ABS(vv); int f0 = 1, f1 = 0, g0 = 0, g1 = 1, q, r; while ( p1!=0 ) { q=p0 / p1; r=p0 % p1; p0 = p1; p1 = r; r = g0 - g1 * q; g0 = g1; g1 = r; r = f0 - f1 * q; f0 = f1; f1 = r; } int a = f0; int b = g0; if ( uu /*(int)(long)u->Data()*/ < 0 ) a=-a; if ( vv /*(int)(long)v->Data()*/ < 0 ) b=-b; lists L=(lists)omAllocBin(slists_bin); L->Init(3); L->m[0].rtyp=INT_CMD; L->m[0].data=(void *)(long)p0; L->m[1].rtyp=INT_CMD; L->m[1].data=(void *)(long)a; L->m[2].rtyp=INT_CMD; L->m[2].data=(void *)(long)b; res->rtyp=LIST_CMD; res->data=(char *)L; return FALSE; } static BOOLEAN jjEXTGCD_P(leftv res, leftv u, leftv v) { poly r,pa,pb; BOOLEAN ret=singclap_extgcd((poly)u->Data(),(poly)v->Data(),r,pa,pb,currRing); if (ret) return TRUE; lists L=(lists)omAllocBin(slists_bin); L->Init(3); res->data=(char *)L; L->m[0].data=(void *)r; L->m[0].rtyp=POLY_CMD; L->m[1].data=(void *)pa; L->m[1].rtyp=POLY_CMD; L->m[2].data=(void *)pb; L->m[2].rtyp=POLY_CMD; return FALSE; } extern int singclap_factorize_retry; static BOOLEAN jjFAC_P2(leftv res, leftv u,leftv dummy) { intvec *v=NULL; int sw=(int)(long)dummy->Data(); int fac_sw=sw; if ((sw<0)||(sw>2)) fac_sw=1; singclap_factorize_retry=0; ideal f=singclap_factorize((poly)(u->CopyD()), &v, fac_sw,currRing); if (f==NULL) return TRUE; switch(sw) { case 0: case 2: { lists l=(lists)omAllocBin(slists_bin); l->Init(2); l->m[0].rtyp=IDEAL_CMD; l->m[0].data=(void *)f; l->m[1].rtyp=INTVEC_CMD; l->m[1].data=(void *)v; res->data=(void *)l; res->rtyp=LIST_CMD; return FALSE; } case 1: res->data=(void *)f; return FALSE; case 3: { poly p=f->m[0]; int i=IDELEMS(f); f->m[0]=NULL; while(i>1) { i--; p=pMult(p,f->m[i]); f->m[i]=NULL; } res->data=(void *)p; res->rtyp=POLY_CMD; } return FALSE; } WerrorS("invalid switch"); return TRUE; } static BOOLEAN jjFACSTD2(leftv res, leftv v, leftv w) { ideal_list p,h; h=kStdfac((ideal)v->Data(),NULL,testHomog,NULL,(ideal)w->Data()); p=h; int l=0; while (p!=NULL) { p=p->next;l++; } lists L=(lists)omAllocBin(slists_bin); L->Init(l); l=0; while(h!=NULL) { L->m[l].data=(char *)h->d; L->m[l].rtyp=IDEAL_CMD; p=h->next; omFreeSize(h,sizeof(*h)); h=p; l++; } res->data=(void *)L; return FALSE; } static BOOLEAN jjFAREY_BI(leftv res, leftv u, leftv v) { if (rField_is_Q(currRing)) { number uu=(number)u->Data(); number vv=(number)v->Data(); res->data=(char *)n_Farey(uu,vv,currRing->cf); return FALSE; } else return TRUE; } static BOOLEAN jjFAREY_ID(leftv res, leftv u, leftv v) { ideal uu=(ideal)u->Data(); number vv=(number)v->Data(); res->data=(void*)id_Farey(uu,vv,currRing); res->rtyp=u->Typ(); return FALSE; } static BOOLEAN jjFETCH(leftv res, leftv u, leftv v) { ring r=(ring)u->Data(); idhdl w; int op=iiOp; nMapFunc nMap; if ((w=r->idroot->get(v->Name(),myynest))!=NULL) { int *perm=NULL; int *par_perm=NULL; int par_perm_size=0; BOOLEAN bo; if ((nMap=n_SetMap(r->cf,currRing->cf))==NULL) { // Allow imap/fetch to be make an exception only for: if ( (rField_is_Q_a(r) && // Q(a..) -> Q(a..) || Q || Zp || Zp(a) (rField_is_Q(currRing) || rField_is_Q_a(currRing) || (rField_is_Zp(currRing) || rField_is_Zp_a(currRing)))) || (rField_is_Zp_a(r) && // Zp(a..) -> Zp(a..) || Zp (rField_is_Zp(currRing, r->cf->ch) || rField_is_Zp_a(currRing, r->cf->ch))) ) { par_perm_size=rPar(r); } else { goto err_fetch; } } if ((iiOp!=FETCH_CMD) || (r->N!=currRing->N) || (rPar(r)!=rPar(currRing))) { perm=(int *)omAlloc0((r->N+1)*sizeof(int)); if (par_perm_size!=0) par_perm=(int *)omAlloc0(par_perm_size*sizeof(int)); op=IMAP_CMD; if (iiOp==IMAP_CMD) { int r_par=0; char ** r_par_names=NULL; if (r->cf->extRing!=NULL) { r_par=r->cf->extRing->N; r_par_names=r->cf->extRing->names; } int c_par=0; char ** c_par_names=NULL; if (currRing->cf->extRing!=NULL) { c_par=currRing->cf->extRing->N; c_par_names=currRing->cf->extRing->names; } maFindPerm(r->names, r->N, r_par_names, r_par, currRing->names,currRing->N,c_par_names, c_par, perm,par_perm, currRing->cf->type); } else { int i; if (par_perm_size!=0) for(i=si_min(rPar(r),rPar(currRing))-1;i>=0;i--) par_perm[i]=-(i+1); for(i=si_min(r->N,currRing->N);i>0;i--) perm[i]=i; } } if ((iiOp==FETCH_CMD) &&(BVERBOSE(V_IMAP))) { int i; for(i=0;iN,currRing->N);i++) { Print("// var nr %d: %s -> %s\n",i,r->names[i],currRing->names[i]); } for(i=0;i %s\n", i,rParameter(r)[i],rParameter(currRing)[i]); } } if (IDTYP(w)==ALIAS_CMD) w=(idhdl)IDDATA(w); sleftv tmpW; memset(&tmpW,0,sizeof(sleftv)); tmpW.rtyp=IDTYP(w); tmpW.data=IDDATA(w); if ((bo=maApplyFetch(op,NULL,res,&tmpW, r, perm,par_perm,par_perm_size,nMap))) { Werror("cannot map %s of type %s(%d)",v->name, Tok2Cmdname(w->typ),w->typ); } if (perm!=NULL) omFreeSize((ADDRESS)perm,(r->N+1)*sizeof(int)); if (par_perm!=NULL) omFreeSize((ADDRESS)par_perm,par_perm_size*sizeof(int)); return bo; } else { Werror("identifier %s not found in %s",v->Fullname(),u->Fullname()); } return TRUE; err_fetch: Werror("no identity map from %s (%s -> %s)",u->Fullname(), nCoeffString(r->cf), nCoeffString(currRing->cf)); return TRUE; } static BOOLEAN jjFIND2(leftv res, leftv u, leftv v) { /*4 * look for the substring what in the string where * return the position of the first char of what in where * or 0 */ char *where=(char *)u->Data(); char *what=(char *)v->Data(); char *found = strstr(where,what); if (found != NULL) { res->data=(char *)((found-where)+1); } /*else res->data=NULL;*/ return FALSE; } static BOOLEAN jjFWALK(leftv res, leftv u, leftv v) { res->data=(char *)fractalWalkProc(u,v); setFlag( res, FLAG_STD ); return FALSE; } static BOOLEAN jjGCD_I(leftv res, leftv u, leftv v) { int uu=(int)(long)u->Data();int vv=(int)(long)v->Data(); int p0=ABS(uu),p1=ABS(vv); int r; while ( p1!=0 ) { r=p0 % p1; p0 = p1; p1 = r; } res->rtyp=INT_CMD; res->data=(char *)(long)p0; return FALSE; } static BOOLEAN jjGCD_BI(leftv res, leftv u, leftv v) { number n1 = (number) u->Data(); number n2 = (number) v->Data(); res->data = n_Gcd(n1,n2,coeffs_BIGINT); return FALSE; } static BOOLEAN jjGCD_N(leftv res, leftv u, leftv v) { number a=(number) u->Data(); number b=(number) v->Data(); if (nIsZero(a)) { if (nIsZero(b)) res->data=(char *)nInit(1); else res->data=(char *)nCopy(b); } else { if (nIsZero(b)) res->data=(char *)nCopy(a); //else res->data=(char *)n_Gcd(a, b, currRing->cf); else res->data=(char *)n_SubringGcd(a, b, currRing->cf); } return FALSE; } static BOOLEAN jjGCD_P(leftv res, leftv u, leftv v) { res->data=(void *)singclap_gcd((poly)(u->CopyD(POLY_CMD)), (poly)(v->CopyD(POLY_CMD)),currRing); return FALSE; } static BOOLEAN jjHILBERT2(leftv res, leftv u, leftv v) { #ifdef HAVE_RINGS if (rField_is_Ring_Z(currRing)) { ring origR = currRing; ring tempR = rCopy(origR); coeffs new_cf=nInitChar(n_Q,NULL); nKillChar(tempR->cf); tempR->cf=new_cf; rComplete(tempR); ideal uid = (ideal)u->Data(); rChangeCurrRing(tempR); ideal uu = idrCopyR(uid, origR, currRing); sleftv uuAsLeftv; memset(&uuAsLeftv, 0, sizeof(uuAsLeftv)); uuAsLeftv.rtyp = IDEAL_CMD; uuAsLeftv.data = uu; uuAsLeftv.next = NULL; if (hasFlag(u, FLAG_STD)) setFlag(&uuAsLeftv,FLAG_STD); assumeStdFlag(&uuAsLeftv); Print("// NOTE: computation of Hilbert series etc. is being\n"); Print("// performed for generic fibre, that is, over Q\n"); intvec *module_w=(intvec*)atGet(&uuAsLeftv,"isHomog",INTVEC_CMD); intvec *iv=hFirstSeries(uu,module_w,currRing->qideal); int returnWithTrue = 1; switch((int)(long)v->Data()) { case 1: res->data=(void *)iv; returnWithTrue = 0; case 2: res->data=(void *)hSecondSeries(iv); delete iv; returnWithTrue = 0; } if (returnWithTrue) { WerrorS(feNotImplemented); delete iv; } idDelete(&uu); rChangeCurrRing(origR); rDelete(tempR); if (returnWithTrue) return TRUE; else return FALSE; } #endif assumeStdFlag(u); intvec *module_w=(intvec*)atGet(u,"isHomog",INTVEC_CMD); intvec *iv=hFirstSeries((ideal)u->Data(),module_w,currRing->qideal); switch((int)(long)v->Data()) { case 1: res->data=(void *)iv; return FALSE; case 2: res->data=(void *)hSecondSeries(iv); delete iv; return FALSE; } WerrorS(feNotImplemented); delete iv; return TRUE; } static BOOLEAN jjHOMOG_P(leftv res, leftv u, leftv v) { int i=pVar((poly)v->Data()); if (i==0) { WerrorS("ringvar expected"); return TRUE; } poly p=pOne(); pSetExp(p,i,1); pSetm(p); int d=pWTotaldegree(p); pLmDelete(p); if (d==1) res->data = (char *)p_Homogen((poly)u->Data(), i, currRing); else WerrorS("variable must have weight 1"); return (d!=1); } static BOOLEAN jjHOMOG_ID(leftv res, leftv u, leftv v) { int i=pVar((poly)v->Data()); if (i==0) { WerrorS("ringvar expected"); return TRUE; } pFDegProc deg; if (currRing->pLexOrder && (currRing->order[0]==ringorder_lp)) deg=p_Totaldegree; else deg=currRing->pFDeg; poly p=pOne(); pSetExp(p,i,1); pSetm(p); int d=deg(p,currRing); pLmDelete(p); if (d==1) res->data = (char *)id_Homogen((ideal)u->Data(), i, currRing); else WerrorS("variable must have weight 1"); return (d!=1); } static BOOLEAN jjHOMOG1_W(leftv res, leftv v, leftv u) { intvec *w=new intvec(rVar(currRing)); intvec *vw=(intvec*)u->Data(); ideal v_id=(ideal)v->Data(); pFDegProc save_FDeg=currRing->pFDeg; pLDegProc save_LDeg=currRing->pLDeg; BOOLEAN save_pLexOrder=currRing->pLexOrder; currRing->pLexOrder=FALSE; kHomW=vw; kModW=w; pSetDegProcs(currRing,kHomModDeg); res->data=(void *)(long)idHomModule(v_id,currRing->qideal,&w); currRing->pLexOrder=save_pLexOrder; kHomW=NULL; kModW=NULL; pRestoreDegProcs(currRing,save_FDeg,save_LDeg); if (w!=NULL) delete w; return FALSE; } static BOOLEAN jjINDEPSET2(leftv res, leftv u, leftv v) { assumeStdFlag(u); res->data=(void *)scIndIndset((ideal)(u->Data()),(int)(long)(v->Data()), currRing->qideal); return FALSE; } static BOOLEAN jjINTERSECT(leftv res, leftv u, leftv v) { res->data=(char *)idSect((ideal)u->Data(),(ideal)v->Data()); if (TEST_OPT_RETURN_SB) setFlag(res,FLAG_STD); return FALSE; } static BOOLEAN jjINTERPOLATION (leftv res, leftv l, leftv v) { const lists L = (lists)l->Data(); const int n = L->nr; assume (n >= 0); std::vector V(n + 1); for(int i = n; i >= 0; i--) V[i] = (ideal)(L->m[i].Data()); res->data=interpolation(V, (intvec*)v->Data()); setFlag(res,FLAG_STD); return errorreported; } static BOOLEAN jjJanetBasis2(leftv res, leftv u, leftv v) { extern BOOLEAN jjStdJanetBasis(leftv res, leftv v,int flag); return jjStdJanetBasis(res,u,(int)(long)v->Data()); } static BOOLEAN jjJanetBasis(leftv res, leftv v) { extern BOOLEAN jjStdJanetBasis(leftv res, leftv v,int flag); return jjStdJanetBasis(res,v,0); } static BOOLEAN jjJET_P(leftv res, leftv u, leftv v) { res->data = (char *)pJet((poly)u->CopyD(), (int)(long)v->Data()); return FALSE; } static BOOLEAN jjJET_ID(leftv res, leftv u, leftv v) { res->data = (char *)id_Jet((ideal)u->Data(),(int)(long)v->Data(),currRing); return FALSE; } static BOOLEAN jjKBASE2(leftv res, leftv u, leftv v) { assumeStdFlag(u); intvec *w_u=(intvec *)atGet(u,"isHomog",INTVEC_CMD); res->data = (char *)scKBase((int)(long)v->Data(), (ideal)(u->Data()),currRing->qideal, w_u); if (w_u!=NULL) { atSet(res,omStrDup("isHomog"),ivCopy(w_u),INTVEC_CMD); } return FALSE; } static BOOLEAN jjPREIMAGE(leftv res, leftv u, leftv v, leftv w); static BOOLEAN jjKERNEL(leftv res, leftv u, leftv v) { return jjPREIMAGE(res,u,v,NULL); } static BOOLEAN jjKoszul(leftv res, leftv u, leftv v) { return mpKoszul(res, u,v,NULL); } static BOOLEAN jjKoszul_Id(leftv res, leftv u, leftv v) { sleftv h; memset(&h,0,sizeof(sleftv)); h.rtyp=INT_CMD; h.data=(void *)(long)IDELEMS((ideal)v->Data()); return mpKoszul(res, u, &h, v); } static BOOLEAN jjLIFT(leftv res, leftv u, leftv v) { int ul= IDELEMS((ideal)u->Data()); int vl= IDELEMS((ideal)v->Data()); ideal m = idLift((ideal)u->Data(),(ideal)v->Data(),NULL,FALSE, hasFlag(u,FLAG_STD)); if (m==NULL) return TRUE; res->data = (char *)id_Module2formatedMatrix(m,ul,vl,currRing); return FALSE; } static BOOLEAN jjLIFTSTD(leftv res, leftv u, leftv v) { if ((v->rtyp!=IDHDL)||(v->e!=NULL)) return TRUE; idhdl h=(idhdl)v->data; // CopyD for IDEAL_CMD and MODUL_CMD are identical: res->data = (char *)idLiftStd((ideal)u->Data(), &(h->data.umatrix),testHomog); setFlag(res,FLAG_STD); v->flag=0; return FALSE; } static BOOLEAN jjLOAD2(leftv /*res*/, leftv, leftv v) { return jjLOAD((char*)v->Data(),TRUE); } static BOOLEAN jjLOAD_E(leftv /*res*/, leftv v, leftv u) { char * s=(char *)u->Data(); if(strcmp(s, "with")==0) return jjLOAD((char*)v->Data(), TRUE); if (strcmp(s,"try")==0) return jjLOAD_TRY((char*)v->Data()); WerrorS("invalid second argument"); WerrorS("load(\"libname\" [,option]);"); return TRUE; } static BOOLEAN jjMODULO(leftv res, leftv u, leftv v) { intvec *w_u=(intvec *)atGet(u,"isHomog",INTVEC_CMD); tHomog hom=testHomog; if (w_u!=NULL) { w_u=ivCopy(w_u); hom=isHomog; } intvec *w_v=(intvec *)atGet(v,"isHomog",INTVEC_CMD); if (w_v!=NULL) { w_v=ivCopy(w_v); hom=isHomog; } if ((w_u!=NULL) && (w_v==NULL)) w_v=ivCopy(w_u); if ((w_v!=NULL) && (w_u==NULL)) w_u=ivCopy(w_v); ideal u_id=(ideal)u->Data(); ideal v_id=(ideal)v->Data(); if (w_u!=NULL) { if ((*w_u).compare((w_v))!=0) { WarnS("incompatible weights"); delete w_u; w_u=NULL; hom=testHomog; } else { if ((!idTestHomModule(u_id,currRing->qideal,w_v)) || (!idTestHomModule(v_id,currRing->qideal,w_v))) { WarnS("wrong weights"); delete w_u; w_u=NULL; hom=testHomog; } } } res->data = (char *)idModulo(u_id,v_id ,hom,&w_u); if (w_u!=NULL) { atSet(res,omStrDup("isHomog"),w_u,INTVEC_CMD); } delete w_v; //if (TEST_OPT_RETURN_SB) setFlag(res,FLAG_STD); return FALSE; } static BOOLEAN jjMOD_BI(leftv res, leftv u, leftv v) { number q=(number)v->Data(); if (n_IsZero(q,coeffs_BIGINT)) { WerrorS(ii_div_by_0); return TRUE; } res->data =(char *) n_IntMod((number)u->Data(),q,coeffs_BIGINT); return FALSE; } static BOOLEAN jjMOD_N(leftv res, leftv u, leftv v) { number q=(number)v->Data(); if (nIsZero(q)) { WerrorS(ii_div_by_0); return TRUE; } res->data =(char *) n_IntMod((number)u->Data(),q,currRing->cf); return FALSE; } static BOOLEAN jjMONITOR2(leftv res, leftv u,leftv v); static BOOLEAN jjMONITOR1(leftv res, leftv v) { return jjMONITOR2(res,v,NULL); } static BOOLEAN jjMONITOR2(leftv, leftv u,leftv v) { #if 0 char *opt=(char *)v->Data(); int mode=0; while(*opt!='\0') { if (*opt=='i') mode |= SI_PROT_I; else if (*opt=='o') mode |= SI_PROT_O; opt++; } monitor((char *)(u->Data()),mode); #else si_link l=(si_link)u->Data(); if (slOpen(l,SI_LINK_WRITE,u)) return TRUE; if(strcmp(l->m->type,"ASCII")!=0) { Werror("ASCII link required, not `%s`",l->m->type); slClose(l); return TRUE; } SI_LINK_SET_CLOSE_P(l); // febase handles the FILE* if ( l->name[0]!='\0') // "" is the stop condition { const char *opt; int mode=0; if (v==NULL) opt=(const char*)"i"; else opt=(const char *)v->Data(); while(*opt!='\0') { if (*opt=='i') mode |= SI_PROT_I; else if (*opt=='o') mode |= SI_PROT_O; opt++; } monitor((FILE *)l->data,mode); } else monitor(NULL,0); return FALSE; #endif } static BOOLEAN jjMONOM(leftv res, leftv v) { intvec *iv=(intvec *)v->Data(); poly p=pOne(); int i,e; BOOLEAN err=FALSE; for(i=si_min(currRing->N,iv->length()); i>0; i--) { e=(*iv)[i-1]; if (e>=0) pSetExp(p,i,e); else err=TRUE; } if (iv->length()==(currRing->N+1)) { res->rtyp=VECTOR_CMD; e=(*iv)[currRing->N]; if (e>=0) pSetComp(p,e); else err=TRUE; } pSetm(p); res->data=(char*)p; if(err) { pDelete(&p); WerrorS("no negative exponent allowed"); } return err; } static BOOLEAN jjNEWSTRUCT2(leftv, leftv u, leftv v) { // u: the name of the new type // v: the elements newstruct_desc d=newstructFromString((const char *)v->Data()); if (d!=NULL) newstruct_setup((const char *)u->Data(),d); return d==NULL; } static BOOLEAN jjPARSTR2(leftv res, leftv u, leftv v) { idhdl h=(idhdl)u->data; int i=(int)(long)v->Data(); int p=0; if ((0data=omStrDup(rParameter(IDRING(h))[i-1]); else { Werror("par number %d out of range 1..%d",i,p); return TRUE; } return FALSE; } #ifdef HAVE_PLURAL static BOOLEAN jjPlural_num_poly(leftv res, leftv a, leftv b) { if( currRing->qideal != NULL ) { WerrorS("basering must NOT be a qring!"); return TRUE; } if (iiOp==NCALGEBRA_CMD) { return nc_CallPlural(NULL,NULL,(poly)a->Data(),(poly)b->Data(),currRing,false,true,false,currRing); } else { ring r=rCopy(currRing); BOOLEAN result=nc_CallPlural(NULL,NULL,(poly)a->Data(),(poly)b->Data(),r,false,true,false,currRing); res->data=r; if (r->qideal!=NULL) res->rtyp=QRING_CMD; return result; } } static BOOLEAN jjPlural_num_mat(leftv res, leftv a, leftv b) { if( currRing->qideal != NULL ) { WerrorS("basering must NOT be a qring!"); return TRUE; } if (iiOp==NCALGEBRA_CMD) { return nc_CallPlural(NULL,(matrix)b->Data(),(poly)a->Data(),NULL,currRing,false,true,false,currRing); } else { ring r=rCopy(currRing); BOOLEAN result=nc_CallPlural(NULL,(matrix)b->Data(),(poly)a->Data(),NULL,r,false,true,false,currRing); res->data=r; if (r->qideal!=NULL) res->rtyp=QRING_CMD; return result; } } static BOOLEAN jjPlural_mat_poly(leftv res, leftv a, leftv b) { if( currRing->qideal != NULL ) { WerrorS("basering must NOT be a qring!"); return TRUE; } if (iiOp==NCALGEBRA_CMD) { return nc_CallPlural((matrix)a->Data(),NULL,NULL,(poly)b->Data(),currRing,false,true,false,currRing); } else { ring r=rCopy(currRing); BOOLEAN result=nc_CallPlural((matrix)a->Data(),NULL,NULL,(poly)b->Data(),r,false,true,false,currRing); res->data=r; if (r->qideal!=NULL) res->rtyp=QRING_CMD; return result; } } static BOOLEAN jjPlural_mat_mat(leftv res, leftv a, leftv b) { if( currRing->qideal != NULL ) { WerrorS("basering must NOT be a qring!"); return TRUE; } if (iiOp==NCALGEBRA_CMD) { return nc_CallPlural((matrix)a->Data(),(matrix)b->Data(),NULL,NULL,currRing,false,true,false,currRing); } else { ring r=rCopy(currRing); BOOLEAN result=nc_CallPlural((matrix)a->Data(),(matrix)b->Data(),NULL,NULL,r,false,true,false,currRing); res->data=r; if (r->qideal!=NULL) res->rtyp=QRING_CMD; return result; } } static BOOLEAN jjBRACKET(leftv res, leftv a, leftv b) { res->data=NULL; if (rIsPluralRing(currRing)) { const poly q = (poly)b->Data(); if( q != NULL ) { if( (poly)a->Data() != NULL ) { poly p = (poly)a->CopyD(POLY_CMD); // p = copy! res->data = nc_p_Bracket_qq(p,q, currRing); // p will be destroyed! } } } return FALSE; } static BOOLEAN jjOPPOSE(leftv res, leftv a, leftv b) { /* number, poly, vector, ideal, module, matrix */ ring r = (ring)a->Data(); if (r == currRing) { res->data = b->Data(); res->rtyp = b->rtyp; return FALSE; } if (!rIsLikeOpposite(currRing, r)) { Werror("%s is not an opposite ring to current ring",a->Fullname()); return TRUE; } idhdl w; if( ((w=r->idroot->get(b->Name(),myynest))!=NULL) && (b->e==NULL)) { int argtype = IDTYP(w); switch (argtype) { case NUMBER_CMD: { /* since basefields are equal, we can apply nCopy */ res->data = nCopy((number)IDDATA(w)); res->rtyp = argtype; break; } case POLY_CMD: case VECTOR_CMD: { poly q = (poly)IDDATA(w); res->data = pOppose(r,q,currRing); res->rtyp = argtype; break; } case IDEAL_CMD: case MODUL_CMD: { ideal Q = (ideal)IDDATA(w); res->data = idOppose(r,Q,currRing); res->rtyp = argtype; break; } case MATRIX_CMD: { ring save = currRing; rChangeCurrRing(r); matrix m = (matrix)IDDATA(w); ideal Q = id_Matrix2Module(mp_Copy(m, currRing),currRing); rChangeCurrRing(save); ideal S = idOppose(r,Q,currRing); id_Delete(&Q, r); res->data = id_Module2Matrix(S,currRing); res->rtyp = argtype; break; } default: { WerrorS("unsupported type in oppose"); return TRUE; } } } else { Werror("identifier %s not found in %s",b->Fullname(),a->Fullname()); return TRUE; } return FALSE; } #endif /* HAVE_PLURAL */ static BOOLEAN jjQUOT(leftv res, leftv u, leftv v) { res->data = (char *)idQuot((ideal)u->Data(),(ideal)v->Data(), hasFlag(u,FLAG_STD),u->Typ()==v->Typ()); id_DelMultiples((ideal)(res->data),currRing); if (TEST_OPT_RETURN_SB) setFlag(res,FLAG_STD); return FALSE; } static BOOLEAN jjRANDOM(leftv res, leftv u, leftv v) { int i=(int)(long)u->Data(); int j=(int)(long)v->Data(); if (j-i <0) {WerrorS("invalid range for random"); return TRUE;} res->data =(char *)(long)((i > j) ? i : (siRand() % (j-i+1)) + i); return FALSE; } static BOOLEAN jjRANK2(leftv res, leftv u, leftv v) { matrix m =(matrix)u->Data(); int isRowEchelon = (int)(long)v->Data(); if (isRowEchelon != 1) isRowEchelon = 0; int rank = luRank(m, isRowEchelon); res->data =(char *)(long)rank; return FALSE; } static BOOLEAN jjREAD2(leftv res, leftv u, leftv v) { si_link l=(si_link)u->Data(); leftv r=slRead(l,v); if (r==NULL) { const char *s; if ((l!=NULL)&&(l->name!=NULL)) s=l->name; else s=sNoName; Werror("cannot read from `%s`",s); return TRUE; } memcpy(res,r,sizeof(sleftv)); omFreeBin((ADDRESS)r, sleftv_bin); return FALSE; } static BOOLEAN jjREDUCE_P(leftv res, leftv u, leftv v) { ideal vi=(ideal)v->Data(); if (currRing->qideal!=NULL || vi->ncols>1 || rIsPluralRing(currRing)) assumeStdFlag(v); res->data = (char *)kNF(vi,currRing->qideal,(poly)u->Data()); return FALSE; } static BOOLEAN jjREDUCE_ID(leftv res, leftv u, leftv v) { ideal ui=(ideal)u->Data(); ideal vi=(ideal)v->Data(); if (currRing->qideal!=NULL || vi->ncols>1 || rIsPluralRing(currRing)) assumeStdFlag(v); res->data = (char *)kNF(vi,currRing->qideal,ui); return FALSE; } #if 0 static BOOLEAN jjRES(leftv res, leftv u, leftv v) { int maxl=(int)(long)v->Data(); if (maxl<0) { WerrorS("length for res must not be negative"); return TRUE; } int l=0; //resolvente r; syStrategy r; intvec *weights=NULL; int wmaxl=maxl; ideal u_id=(ideal)u->Data(); maxl--; if (/*(*/ maxl==-1 /*)*/) /*&& (iiOp!=MRES_CMD)*/ { maxl = currRing->N-1+2*(iiOp==MRES_CMD); if (currRing->qideal!=NULL) { Warn( "full resolution in a qring may be infinite, setting max length to %d", maxl+1); } } weights=(intvec*)atGet(u,"isHomog",INTVEC_CMD); if (weights!=NULL) { if (!idTestHomModule(u_id,currRing->qideal,weights)) { WarnS("wrong weights given:");weights->show();PrintLn(); weights=NULL; } } intvec *ww=NULL; int add_row_shift=0; if (weights!=NULL) { ww=ivCopy(weights); add_row_shift = ww->min_in(); (*ww) -= add_row_shift; } else idHomModule(u_id,currRing->qideal,&ww); weights=ww; if ((iiOp == RES_CMD) || (iiOp == MRES_CMD)) { r=syResolution(u_id,maxl, ww, iiOp==MRES_CMD); } else if (iiOp==SRES_CMD) // r=sySchreyerResolvente(u_id,maxl+1,&l); r=sySchreyer(u_id,maxl+1); else if (iiOp == LRES_CMD) { int dummy; if((currRing->qideal!=NULL)|| (!idHomIdeal (u_id,NULL))) { WerrorS ("`lres` not implemented for inhomogeneous input or qring"); return TRUE; } r=syLaScala3(u_id,&dummy); } else if (iiOp == KRES_CMD) { int dummy; if((currRing->qideal!=NULL)|| (!idHomIdeal (u_id,NULL))) { WerrorS ("`kres` not implemented for inhomogeneous input or qring"); return TRUE; } r=syKosz(u_id,&dummy); } else { int dummy; if((currRing->qideal!=NULL)|| (!idHomIdeal (u_id,NULL))) { WerrorS ("`hres` not implemented for inhomogeneous input or qring"); return TRUE; } r=syHilb(u_id,&dummy); } if (r==NULL) return TRUE; //res->data=(void *)liMakeResolv(r,l,wmaxl,u->Typ(),weights); r->list_length=wmaxl; res->data=(void *)r; if ((r->weights!=NULL) && (r->weights[0]!=NULL)) { intvec *w=ivCopy(r->weights[0]); if (weights!=NULL) (*w) += add_row_shift; atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); w=NULL; } else { //#if 0 // need to set weights for ALL components (sres) if (weights!=NULL) { atSet(res,omStrDup("isHomog"),ivCopy(weights),INTVEC_CMD); r->weights = (intvec**)omAlloc0Bin(char_ptr_bin); (r->weights)[0] = ivCopy(weights); } //#endif } if (ww!=NULL) { delete ww; ww=NULL; } return FALSE; } #else static BOOLEAN jjRES(leftv res, leftv u, leftv v) { int maxl=(int)(long)v->Data(); if (maxl<0) { WerrorS("length for res must not be negative"); return TRUE; } syStrategy r; intvec *weights=NULL; int wmaxl=maxl; ideal u_id=(ideal)u->Data(); maxl--; if (/*(*/ maxl==-1 /*)*/) /*&& (iiOp!=MRES_CMD)*/ { maxl = currRing->N-1+2*(iiOp==MRES_CMD); if (currRing->qideal!=NULL) { Warn( "full resolution in a qring may be infinite, setting max length to %d", maxl+1); } } weights=(intvec*)atGet(u,"isHomog",INTVEC_CMD); if (weights!=NULL) { if (!idTestHomModule(u_id,currRing->qideal,weights)) { WarnS("wrong weights given:");weights->show();PrintLn(); weights=NULL; } } intvec *ww=NULL; int add_row_shift=0; if (weights!=NULL) { ww=ivCopy(weights); add_row_shift = ww->min_in(); (*ww) -= add_row_shift; } if ((iiOp == RES_CMD) || (iiOp == MRES_CMD)) { r=syResolution(u_id,maxl, ww, iiOp==MRES_CMD); } else if (iiOp==SRES_CMD) // r=sySchreyerResolvente(u_id,maxl+1,&l); r=sySchreyer(u_id,maxl+1); else if (iiOp == LRES_CMD) { int dummy; if((currRing->qideal!=NULL)|| (!idHomIdeal (u_id,NULL))) { WerrorS ("`lres` not implemented for inhomogeneous input or qring"); return TRUE; } if(currRing->N == 1) WarnS("the current implementation of `lres` may not work in the case of a single variable"); r=syLaScala3(u_id,&dummy); } else if (iiOp == KRES_CMD) { int dummy; if((currRing->qideal!=NULL)|| (!idHomIdeal (u_id,NULL))) { WerrorS ("`kres` not implemented for inhomogeneous input or qring"); return TRUE; } r=syKosz(u_id,&dummy); } else { int dummy; if((currRing->qideal!=NULL)|| (!idHomIdeal (u_id,NULL))) { WerrorS ("`hres` not implemented for inhomogeneous input or qring"); return TRUE; } ideal u_id_copy=idCopy(u_id); idSkipZeroes(u_id_copy); r=syHilb(u_id_copy,&dummy); idDelete(&u_id_copy); } if (r==NULL) return TRUE; //res->data=(void *)liMakeResolv(r,l,wmaxl,u->Typ(),weights); r->list_length=wmaxl; res->data=(void *)r; if ((weights!=NULL) && (ww!=NULL)) { delete ww; ww=NULL; } if ((r->weights!=NULL) && (r->weights[0]!=NULL)) { ww=ivCopy(r->weights[0]); if (weights!=NULL) (*ww) += add_row_shift; atSet(res,omStrDup("isHomog"),ww,INTVEC_CMD); } else { if (weights!=NULL) { atSet(res,omStrDup("isHomog"),ivCopy(weights),INTVEC_CMD); } } // test the La Scala case' output assume( ((iiOp == LRES_CMD) || (iiOp == HRES_CMD)) == (r->syRing != NULL) ); assume( (r->syRing != NULL) == (r->resPairs != NULL) ); if(iiOp != HRES_CMD) assume( (r->minres != NULL) || (r->fullres != NULL) ); // is wrong for HRES_CMD... else assume( (r->orderedRes != NULL) || (r->res != NULL) ); // analog for hres... return FALSE; } #endif static BOOLEAN jjPFAC2(leftv res, leftv u, leftv v) { number n1; int i; if ((u->Typ() == BIGINT_CMD) || ((u->Typ() == NUMBER_CMD) && rField_is_Q(currRing))) { n1 = (number)u->CopyD(); } else if (u->Typ() == INT_CMD) { i = (int)(long)u->Data(); n1 = n_Init(i, coeffs_BIGINT); } else { return TRUE; } i = (int)(long)v->Data(); lists l = primeFactorisation(n1, i); n_Delete(&n1, coeffs_BIGINT); res->data = (char*)l; return FALSE; } static BOOLEAN jjRSUM(leftv res, leftv u, leftv v) { ring r; int i=rSum((ring)u->Data(),(ring)v->Data(),r); res->data = (char *)r; return (i==-1); } #define SIMPL_LMDIV 32 #define SIMPL_LMEQ 16 #define SIMPL_MULT 8 #define SIMPL_EQU 4 #define SIMPL_NULL 2 #define SIMPL_NORM 1 static BOOLEAN jjSIMPL_ID(leftv res, leftv u, leftv v) { int sw = (int)(long)v->Data(); // CopyD for IDEAL_CMD and MODUL_CMD are identical: ideal id = (ideal)u->CopyD(IDEAL_CMD); if (sw & SIMPL_LMDIV) { id_DelDiv(id,currRing); } if (sw & SIMPL_LMEQ) { id_DelLmEquals(id,currRing); } if (sw & SIMPL_MULT) { id_DelMultiples(id,currRing); } else if(sw & SIMPL_EQU) { id_DelEquals(id,currRing); } if (sw & SIMPL_NULL) { idSkipZeroes(id); } if (sw & SIMPL_NORM) { id_Norm(id,currRing); } res->data = (char * )id; return FALSE; } extern int singclap_factorize_retry; static BOOLEAN jjSQR_FREE2(leftv res, leftv u, leftv dummy) { intvec *v=NULL; int sw=(int)(long)dummy->Data(); int fac_sw=sw; if (sw<0) fac_sw=1; singclap_factorize_retry=0; ideal f=singclap_sqrfree((poly)(u->CopyD()), &v, fac_sw, currRing); if (f==NULL) return TRUE; switch(sw) { case 0: case 2: { lists l=(lists)omAllocBin(slists_bin); l->Init(2); l->m[0].rtyp=IDEAL_CMD; l->m[0].data=(void *)f; l->m[1].rtyp=INTVEC_CMD; l->m[1].data=(void *)v; res->data=(void *)l; res->rtyp=LIST_CMD; return FALSE; } case 1: res->data=(void *)f; return FALSE; case 3: { poly p=f->m[0]; int i=IDELEMS(f); f->m[0]=NULL; while(i>1) { i--; p=pMult(p,f->m[i]); f->m[i]=NULL; } res->data=(void *)p; res->rtyp=POLY_CMD; } return FALSE; } WerrorS("invalid switch"); return FALSE; } static BOOLEAN jjSTATUS2(leftv res, leftv u, leftv v) { res->data = omStrDup(slStatus((si_link) u->Data(), (char *) v->Data())); return FALSE; } static BOOLEAN jjSTATUS2L(leftv res, leftv u, leftv v) { res->data = (void *)(long)slStatusSsiL((lists) u->Data(), (int)(long) v->Data()); //return (res->data== (void*)(long)-2); return FALSE; } static BOOLEAN jjSIMPL_P(leftv res, leftv u, leftv v) { int sw = (int)(long)v->Data(); // CopyD for POLY_CMD and VECTOR_CMD are identical: poly p = (poly)u->CopyD(POLY_CMD); if (sw & SIMPL_NORM) { pNorm(p); } res->data = (char * )p; return FALSE; } static BOOLEAN jjSTD_HILB(leftv res, leftv u, leftv v) { ideal result; intvec *w=(intvec *)atGet(u,"isHomog",INTVEC_CMD); tHomog hom=testHomog; ideal u_id=(ideal)(u->Data()); if (w!=NULL) { if (!idTestHomModule(u_id,currRing->qideal,w)) { WarnS("wrong weights:");w->show();PrintLn(); w=NULL; } else { w=ivCopy(w); hom=isHomog; } } result=kStd(u_id,currRing->qideal,hom,&w,(intvec *)v->Data()); idSkipZeroes(result); res->data = (char *)result; setFlag(res,FLAG_STD); if (w!=NULL) atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); return FALSE; } static BOOLEAN jjSTD_1(leftv res, leftv u, leftv v) { ideal result; assumeStdFlag(u); ideal i1=(ideal)(u->Data()); ideal i0; int r=v->Typ(); if ((/*v->Typ()*/r==POLY_CMD) ||(r==VECTOR_CMD)) { i0=idInit(1,i1->rank); // TODO: rank is wrong (if v is a vector!) i0->m[0]=(poly)v->Data(); int ii0=idElem(i0); /* size of i0 */ i1=idSimpleAdd(i1,i0); // memset(i0->m,0,sizeof(poly)*IDELEMS(i0)); idDelete(&i0); intvec *w=(intvec *)atGet(u,"isHomog",INTVEC_CMD); tHomog hom=testHomog; if (w!=NULL) { if (!idTestHomModule(i1,currRing->qideal,w)) { // no warnung: this is legal, if i in std(i,p) // is homogeneous, but p not w=NULL; } else { w=ivCopy(w); hom=isHomog; } } BITSET save1; SI_SAVE_OPT1(save1); si_opt_1|=Sy_bit(OPT_SB_1); /* ii0 appears to be the position of the first element of il that does not belong to the old SB ideal */ result=kStd(i1,currRing->qideal,hom,&w,NULL,0,ii0); SI_RESTORE_OPT1(save1); idDelete(&i1); idSkipZeroes(result); if (w!=NULL) atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); res->data = (char *)result; } else /*IDEAL/MODULE*/ { i0=(ideal)v->CopyD(); int ii0=idElem(i0); /* size of i0 */ i1=idSimpleAdd(i1,i0); // memset(i0->m,0,sizeof(poly)*IDELEMS(i0)); idDelete(&i0); intvec *w=(intvec *)atGet(u,"isHomog",INTVEC_CMD); tHomog hom=testHomog; if (w!=NULL) { if (!idTestHomModule(i1,currRing->qideal,w)) { // no warnung: this is legal, if i in std(i,p) // is homogeneous, but p not w=NULL; } else { w=ivCopy(w); hom=isHomog; } } if (ii0*4 >= 3*IDELEMS(i1)) // MAGIC: add few poly to large SB: 3/4 { BITSET save1; SI_SAVE_OPT1(save1); si_opt_1|=Sy_bit(OPT_SB_1); /* ii0 appears to be the position of the first element of il that does not belong to the old SB ideal */ result=kStd(i1,currRing->qideal,hom,&w,NULL,0,ii0); SI_RESTORE_OPT1(save1); } else { result=kStd(i1,currRing->qideal,hom,&w); } idDelete(&i1); idSkipZeroes(result); if (w!=NULL) atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); res->data = (char *)result; } if(!TEST_OPT_DEGBOUND) setFlag(res,FLAG_STD); return FALSE; } static BOOLEAN jjVARSTR2(leftv res, leftv u, leftv v) { idhdl h=(idhdl)u->data; int i=(int)(long)v->Data(); if ((0N)) res->data=omStrDup(IDRING(h)->names[i-1]); else { Werror("var number %d out of range 1..%d",i,IDRING(h)->N); return TRUE; } return FALSE; } static BOOLEAN jjWAIT1ST2(leftv res, leftv u, leftv v) { // input: u: a list with links of type // ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch // v: timeout for select in milliseconds // or 0 for polling // returns: ERROR (via Werror): timeout negative // -1: the read state of all links is eof // 0: timeout (or polling): none ready // i>0: (at least) L[i] is ready lists Lforks = (lists)u->Data(); int t = (int)(long)v->Data(); if(t < 0) { WerrorS("negative timeout"); return TRUE; } int i = slStatusSsiL(Lforks, t*1000); if(i == -2) /* error */ { return TRUE; } res->data = (void*)(long)i; return FALSE; } static BOOLEAN jjWAITALL2(leftv res, leftv u, leftv v) { // input: u: a list with links of type // ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch // v: timeout for select in milliseconds // or 0 for polling // returns: ERROR (via Werror): timeout negative // -1: the read state of all links is eof // 0: timeout (or polling): none ready // 1: all links are ready // (caution: at least one is ready, but some maybe dead) lists Lforks = (lists)u->CopyD(); int timeout = 1000*(int)(long)v->Data(); if(timeout < 0) { WerrorS("negative timeout"); return TRUE; } int t = getRTimer()/TIMER_RESOLUTION; // in seconds int i; int ret = -1; for(int nfinished = 0; nfinished < Lforks->nr+1; nfinished++) { i = slStatusSsiL(Lforks, timeout); if(i > 0) /* Lforks[i] is ready */ { ret = 1; Lforks->m[i-1].CleanUp(); Lforks->m[i-1].rtyp=DEF_CMD; Lforks->m[i-1].data=NULL; timeout = si_max(0,timeout - 1000*(getRTimer()/TIMER_RESOLUTION - t)); } else /* terminate the for loop */ { if(i == -2) /* error */ { return TRUE; } if(i == 0) /* timeout */ { ret = 0; } break; } } Lforks->Clean(); res->data = (void*)(long)ret; return FALSE; } static BOOLEAN jjWEDGE(leftv res, leftv u, leftv v) { res->data = (char *)mp_Wedge((matrix)u->Data(),(int)(long)v->Data(),currRing); return FALSE; } #define jjWRONG2 (proc2)jjWRONG #define jjWRONG3 (proc3)jjWRONG static BOOLEAN jjWRONG(leftv, leftv) { return TRUE; } /*=================== operations with 1 arg.: static proc =================*/ /* must be ordered: first operations for chars (infix ops), * then alphabetically */ static BOOLEAN jjDUMMY(leftv res, leftv u) { res->data = (char *)u->CopyD(); return FALSE; } static BOOLEAN jjNULL(leftv, leftv) { return FALSE; } //static BOOLEAN jjPLUSPLUS(leftv res, leftv u) //{ // res->data = (char *)((int)(long)u->Data()+1); // return FALSE; //} //static BOOLEAN jjMINUSMINUS(leftv res, leftv u) //{ // res->data = (char *)((int)(long)u->Data()-1); // return FALSE; //} static BOOLEAN jjPLUSPLUS(leftv, leftv u) { if (IDTYP((idhdl)u->data)==INT_CMD) { int i=IDINT((idhdl)u->data); if (iiOp==PLUSPLUS) i++; else i--; IDDATA((idhdl)u->data)=(char *)(long)i; return FALSE; } return TRUE; } static BOOLEAN jjUMINUS_BI(leftv res, leftv u) { number n=(number)u->CopyD(BIGINT_CMD); n=n_InpNeg(n,coeffs_BIGINT); res->data = (char *)n; return FALSE; } static BOOLEAN jjUMINUS_I(leftv res, leftv u) { res->data = (char *)(-(long)u->Data()); return FALSE; } static BOOLEAN jjUMINUS_N(leftv res, leftv u) { number n=(number)u->CopyD(NUMBER_CMD); n=nInpNeg(n); res->data = (char *)n; return FALSE; } static BOOLEAN jjUMINUS_P(leftv res, leftv u) { res->data = (char *)pNeg((poly)u->CopyD(POLY_CMD)); return FALSE; } static BOOLEAN jjUMINUS_MA(leftv res, leftv u) { poly m1=pISet(-1); res->data = (char *)mp_MultP((matrix)u->CopyD(MATRIX_CMD),m1,currRing); return FALSE; } static BOOLEAN jjUMINUS_IV(leftv res, leftv u) { intvec *iv=(intvec *)u->CopyD(INTVEC_CMD); (*iv)*=(-1); res->data = (char *)iv; return FALSE; } static BOOLEAN jjUMINUS_BIM(leftv res, leftv u) { bigintmat *bim=(bigintmat *)u->CopyD(BIGINTMAT_CMD); (*bim)*=(-1); res->data = (char *)bim; return FALSE; } static BOOLEAN jjPROC1(leftv res, leftv u) { return jjPROC(res,u,NULL); } static BOOLEAN jjBAREISS(leftv res, leftv v) { //matrix m=(matrix)v->Data(); //lists l=mpBareiss(m,FALSE); intvec *iv; ideal m; sm_CallBareiss((ideal)v->Data(),0,0,m,&iv, currRing); lists l=(lists)omAllocBin(slists_bin); l->Init(2); l->m[0].rtyp=MODUL_CMD; l->m[1].rtyp=INTVEC_CMD; l->m[0].data=(void *)m; l->m[1].data=(void *)iv; res->data = (char *)l; return FALSE; } //static BOOLEAN jjBAREISS_IM(leftv res, leftv v) //{ // intvec *m=(intvec *)v->CopyD(INTMAT_CMD); // ivTriangMat(m); // res->data = (char *)m; // return FALSE; //} static BOOLEAN jjBI2N(leftv res, leftv u) { BOOLEAN bo=FALSE; number n=(number)u->CopyD(); nMapFunc nMap=n_SetMap(coeffs_BIGINT,currRing->cf); if (nMap!=NULL) res->data=nMap(n,coeffs_BIGINT,currRing->cf); else { Werror("cannot convert bigint to cring %s", nCoeffString(currRing->cf)); bo=TRUE; } n_Delete(&n,coeffs_BIGINT); return bo; } static BOOLEAN jjBI2IM(leftv res, leftv u) { bigintmat *b=(bigintmat*)u->Data(); res->data=(void *)bim2iv(b); return FALSE; } static BOOLEAN jjBI2P(leftv res, leftv u) { sleftv tmp; BOOLEAN bo=jjBI2N(&tmp,u); if (!bo) { number n=(number) tmp.data; if (nIsZero(n)) { res->data=NULL;nDelete(&n); } else { res->data=(void *)pNSet(n); } } return bo; } static BOOLEAN jjCALL1MANY(leftv res, leftv u) { return iiExprArithM(res,u,iiOp); } static BOOLEAN jjCHAR(leftv res, leftv v) { res->data = (char *)(long)rChar((ring)v->Data()); return FALSE; } static BOOLEAN jjCOLS(leftv res, leftv v) { res->data = (char *)(long)MATCOLS((matrix)(v->Data())); return FALSE; } static BOOLEAN jjCOLS_BIM(leftv res, leftv v) { res->data = (char *)(long)((bigintmat*)(v->Data()))->cols(); return FALSE; } static BOOLEAN jjCOLS_IV(leftv res, leftv v) { res->data = (char *)(long)((intvec*)(v->Data()))->cols(); return FALSE; } static BOOLEAN jjCONTENT(leftv res, leftv v) { // CopyD for POLY_CMD and VECTOR_CMD are identical: poly p=(poly)v->CopyD(POLY_CMD); if (p!=NULL) p_Cleardenom(p, currRing); res->data = (char *)p; return FALSE; } static BOOLEAN jjCOUNT_BI(leftv res, leftv v) { res->data = (char *)(long)n_Size((number)v->Data(),coeffs_BIGINT); return FALSE; } static BOOLEAN jjCOUNT_N(leftv res, leftv v) { res->data = (char *)(long)nSize((number)v->Data()); return FALSE; } static BOOLEAN jjCOUNT_L(leftv res, leftv v) { lists l=(lists)v->Data(); res->data = (char *)(long)(lSize(l)+1); return FALSE; } static BOOLEAN jjCOUNT_M(leftv res, leftv v) { matrix m=(matrix)v->Data(); res->data = (char *)(long)(MATROWS(m)*MATCOLS(m)); return FALSE; } static BOOLEAN jjCOUNT_IV(leftv res, leftv v) { res->data = (char *)(long)((intvec*)(v->Data()))->length(); return FALSE; } static BOOLEAN jjCOUNT_RG(leftv res, leftv v) { ring r=(ring)v->Data(); int elems=-1; if (rField_is_Zp(r)||rField_is_GF(r)) elems=r->cf->ch; else if (rField_is_Zp_a(r) && (r->cf->type==n_algExt)) { extern int ipower ( int b, int n ); /* factory/cf_util */ elems=ipower(r->cf->ch,r->cf->extRing->pFDeg(r->cf->extRing->qideal->m[0],r->cf->extRing)); } res->data = (char *)(long)elems; return FALSE; } static BOOLEAN jjDEG(leftv res, leftv v) { int dummy; poly p=(poly)v->Data(); if (p!=NULL) res->data = (char *)currRing->pLDeg(p,&dummy,currRing); else res->data=(char *)-1; return FALSE; } static BOOLEAN jjDEG_M(leftv res, leftv u) { ideal I=(ideal)u->Data(); int d=-1; int dummy; int i; for(i=IDELEMS(I)-1;i>=0;i--) if (I->m[i]!=NULL) d=si_max(d,(int)currRing->pLDeg(I->m[i],&dummy,currRing)); res->data = (char *)(long)d; return FALSE; } static BOOLEAN jjDEGREE(leftv res, leftv v) { SPrintStart(); #ifdef HAVE_RINGS if (rField_is_Ring_Z(currRing)) { ring origR = currRing; ring tempR = rCopy(origR); coeffs new_cf=nInitChar(n_Q,NULL); nKillChar(tempR->cf); tempR->cf=new_cf; rComplete(tempR); ideal vid = (ideal)v->Data(); rChangeCurrRing(tempR); ideal vv = idrCopyR(vid, origR, currRing); sleftv vvAsLeftv; memset(&vvAsLeftv, 0, sizeof(vvAsLeftv)); vvAsLeftv.rtyp = IDEAL_CMD; vvAsLeftv.data = vv; vvAsLeftv.next = NULL; if (hasFlag(v, FLAG_STD)) setFlag(&vvAsLeftv,FLAG_STD); assumeStdFlag(&vvAsLeftv); Print("// NOTE: computation of degree is being performed for\n"); Print("// generic fibre, that is, over Q\n"); intvec *module_w=(intvec*)atGet(&vvAsLeftv,"isHomog",INTVEC_CMD); scDegree(vv,module_w,currRing->qideal); idDelete(&vv); rChangeCurrRing(origR); rDelete(tempR); } #endif assumeStdFlag(v); intvec *module_w=(intvec*)atGet(v,"isHomog",INTVEC_CMD); scDegree((ideal)v->Data(),module_w,currRing->qideal); char *s=SPrintEnd(); int l=strlen(s)-1; s[l]='\0'; res->data=(void*)s; return FALSE; } static BOOLEAN jjDEFINED(leftv res, leftv v) { if ((v->rtyp==IDHDL) && ((myynest==IDLEV((idhdl)v->data))||(0==IDLEV((idhdl)v->data)))) { res->data=(void *)(long)(IDLEV((idhdl)v->data)+1); } else if (v->rtyp!=0) res->data=(void *)(-1); return FALSE; } /// Return the denominator of the input number /// NOTE: the input number is normalized as a side effect static BOOLEAN jjDENOMINATOR(leftv res, leftv v) { number n = reinterpret_cast(v->Data()); res->data = reinterpret_cast(n_GetDenom(n, currRing)); return FALSE; } /// Return the numerator of the input number /// NOTE: the input number is normalized as a side effect static BOOLEAN jjNUMERATOR(leftv res, leftv v) { number n = reinterpret_cast(v->Data()); res->data = reinterpret_cast(n_GetNumerator(n, currRing)); return FALSE; } static BOOLEAN jjDET(leftv res, leftv v) { matrix m=(matrix)v->Data(); poly p; if (sm_CheckDet((ideal)m,m->cols(),TRUE, currRing)) { ideal I=id_Matrix2Module(mp_Copy(m, currRing),currRing); p=sm_CallDet(I, currRing); idDelete(&I); } else p=singclap_det(m,currRing); res ->data = (char *)p; return FALSE; } static BOOLEAN jjDET_BI(leftv res, leftv v) { bigintmat * m=(bigintmat*)v->Data(); int i,j; i=m->rows();j=m->cols(); if(i==j) res->data = (char *)(long)singclap_det_bi(m,coeffs_BIGINT); else { Werror("det of %d x %d bigintmat",i,j); return TRUE; } return FALSE; } static BOOLEAN jjDET_I(leftv res, leftv v) { intvec * m=(intvec*)v->Data(); int i,j; i=m->rows();j=m->cols(); if(i==j) res->data = (char *)(long)singclap_det_i(m,currRing); else { Werror("det of %d x %d intmat",i,j); return TRUE; } return FALSE; } static BOOLEAN jjDET_S(leftv res, leftv v) { ideal I=(ideal)v->Data(); poly p; if (IDELEMS(I)<1) return TRUE; if (sm_CheckDet(I,IDELEMS(I),FALSE, currRing)) { matrix m=id_Module2Matrix(id_Copy(I,currRing),currRing); p=singclap_det(m,currRing); idDelete((ideal *)&m); } else p=sm_CallDet(I, currRing); res->data = (char *)p; return FALSE; } static BOOLEAN jjDIM(leftv res, leftv v) { assumeStdFlag(v); #ifdef HAVE_RINGS if (rField_is_Ring(currRing)) { //ring origR = currRing; //ring tempR = rCopy(origR); //coeffs new_cf=nInitChar(n_Q,NULL); //nKillChar(tempR->cf); //tempR->cf=new_cf; //rComplete(tempR); ideal vid = (ideal)v->Data(); int i = idPosConstant(vid); if ((i != -1) && (n_IsUnit(pGetCoeff(vid->m[i]),currRing->cf))) { /* ideal v contains unit; dim = -1 */ res->data = (char *)-1; return FALSE; } //rChangeCurrRing(tempR); //ideal vv = idrCopyR(vid, origR, currRing); ideal vv = id_Head(vid,currRing); /* drop degree zero generator from vv (if any) */ if (i != -1) pDelete(&vv->m[i]); long d = (long)scDimInt(vv, currRing->qideal); if (rField_is_Ring_Z(currRing) && (i == -1)) d++; res->data = (char *)d; idDelete(&vv); //rChangeCurrRing(origR); //rDelete(tempR); return FALSE; } #endif res->data = (char *)(long)scDimInt((ideal)(v->Data()),currRing->qideal); return FALSE; } static BOOLEAN jjDUMP(leftv, leftv v) { si_link l = (si_link)v->Data(); if (slDump(l)) { const char *s; if ((l!=NULL)&&(l->name!=NULL)) s=l->name; else s=sNoName; Werror("cannot dump to `%s`",s); return TRUE; } else return FALSE; } static BOOLEAN jjE(leftv res, leftv v) { res->data = (char *)pOne(); int co=(int)(long)v->Data(); if (co>0) { pSetComp((poly)res->data,co); pSetm((poly)res->data); } else WerrorS("argument of gen must be positive"); return (co<=0); } static BOOLEAN jjEXECUTE(leftv, leftv v) { char * d = (char *)v->Data(); char * s = (char *)omAlloc(strlen(d) + 13); strcpy( s, (char *)d); strcat( s, "\n;RETURN();\n"); newBuffer(s,BT_execute); return yyparse(); } static BOOLEAN jjFACSTD(leftv res, leftv v) { lists L=(lists)omAllocBin(slists_bin); if (currRing->cf->convSingNFactoryN!=NULL) /* conversion to factory*/ { ideal_list p,h; h=kStdfac((ideal)v->Data(),NULL,testHomog,NULL); if (h==NULL) { L->Init(1); L->m[0].data=(char *)idInit(1); L->m[0].rtyp=IDEAL_CMD; } else { p=h; int l=0; while (p!=NULL) { p=p->next;l++; } L->Init(l); l=0; while(h!=NULL) { L->m[l].data=(char *)h->d; L->m[l].rtyp=IDEAL_CMD; p=h->next; omFreeSize(h,sizeof(*h)); h=p; l++; } } } else { WarnS("no factorization implemented"); L->Init(1); iiExprArith1(&(L->m[0]),v,STD_CMD); } res->data=(void *)L; return FALSE; } static BOOLEAN jjFAC_P(leftv res, leftv u) { intvec *v=NULL; singclap_factorize_retry=0; ideal f=singclap_factorize((poly)(u->CopyD()), &v, 0,currRing); if (f==NULL) return TRUE; ivTest(v); lists l=(lists)omAllocBin(slists_bin); l->Init(2); l->m[0].rtyp=IDEAL_CMD; l->m[0].data=(void *)f; l->m[1].rtyp=INTVEC_CMD; l->m[1].data=(void *)v; res->data=(void *)l; return FALSE; } static BOOLEAN jjGETDUMP(leftv, leftv v) { si_link l = (si_link)v->Data(); if (slGetDump(l)) { const char *s; if ((l!=NULL)&&(l->name!=NULL)) s=l->name; else s=sNoName; Werror("cannot get dump from `%s`",s); return TRUE; } else return FALSE; } static BOOLEAN jjHIGHCORNER(leftv res, leftv v) { assumeStdFlag(v); ideal I=(ideal)v->Data(); res->data=(void *)iiHighCorner(I,0); return FALSE; } static BOOLEAN jjHIGHCORNER_M(leftv res, leftv v) { assumeStdFlag(v); intvec *w=(intvec*)atGet(v,"isHomog",INTVEC_CMD); BOOLEAN delete_w=FALSE; ideal I=(ideal)v->Data(); int i; poly p=NULL,po=NULL; int rk=id_RankFreeModule(I,currRing); if (w==NULL) { w = new intvec(rk); delete_w=TRUE; } for(i=rk;i>0;i--) { p=iiHighCorner(I,i); if (p==NULL) { WerrorS("module must be zero-dimensional"); if (delete_w) delete w; return TRUE; } if (po==NULL) { po=p; } else { // now po!=NULL, p!=NULL int d=(currRing->pFDeg(po,currRing)-(*w)[pGetComp(po)-1] - currRing->pFDeg(p,currRing)+(*w)[i-1]); if (d==0) d=pLmCmp(po,p); if (d > 0) { pDelete(&p); } else // (d < 0) { pDelete(&po); po=p; } } } if (delete_w) delete w; res->data=(void *)po; return FALSE; } static BOOLEAN jjHILBERT(leftv, leftv v) { #ifdef HAVE_RINGS if (rField_is_Ring_Z(currRing)) { ring origR = currRing; ring tempR = rCopy(origR); coeffs new_cf=nInitChar(n_Q,NULL); nKillChar(tempR->cf); tempR->cf=new_cf; rComplete(tempR); ideal vid = (ideal)v->Data(); rChangeCurrRing(tempR); ideal vv = idrCopyR(vid, origR, currRing); sleftv vvAsLeftv; memset(&vvAsLeftv, 0, sizeof(vvAsLeftv)); vvAsLeftv.rtyp = IDEAL_CMD; vvAsLeftv.data = vv; vvAsLeftv.next = NULL; if (hasFlag(v, FLAG_STD)) setFlag(&vvAsLeftv,FLAG_STD); assumeStdFlag(&vvAsLeftv); Print("// NOTE: computation of Hilbert series etc. is being\n"); Print("// performed for generic fibre, that is, over Q\n"); intvec *module_w=(intvec*)atGet(&vvAsLeftv,"isHomog",INTVEC_CMD); //scHilbertPoly(vv,currRing->qideal); hLookSeries(vv,module_w,currRing->qideal); idDelete(&vv); rChangeCurrRing(origR); rDelete(tempR); return FALSE; } #endif assumeStdFlag(v); intvec *module_w=(intvec*)atGet(v,"isHomog",INTVEC_CMD); //scHilbertPoly((ideal)v->Data(),currRing->qideal); hLookSeries((ideal)v->Data(),module_w,currRing->qideal); return FALSE; } static BOOLEAN jjHILBERT_IV(leftv res, leftv v) { #ifdef HAVE_RINGS if (rField_is_Ring_Z(currRing)) { Print("// NOTE: computation of Hilbert series etc. is being\n"); Print("// performed for generic fibre, that is, over Q\n"); } #endif res->data=(void *)hSecondSeries((intvec *)v->Data()); return FALSE; } static BOOLEAN jjHOMOG1(leftv res, leftv v) { intvec *w=(intvec*)atGet(v,"isHomog",INTVEC_CMD); ideal v_id=(ideal)v->Data(); if (w==NULL) { res->data=(void *)(long)idHomModule(v_id,currRing->qideal,&w); if (res->data!=NULL) { if (v->rtyp==IDHDL) { char *s_isHomog=omStrDup("isHomog"); if (v->e==NULL) atSet((idhdl)(v->data),s_isHomog,w,INTVEC_CMD); else atSet((idhdl)(v->LData()),s_isHomog,w,INTVEC_CMD); } else if (w!=NULL) delete w; } // if res->data==NULL then w==NULL } else { res->data=(void *)(long)idTestHomModule(v_id,currRing->qideal,w); if((res->data==NULL) && (v->rtyp==IDHDL)) { if (v->e==NULL) atKill((idhdl)(v->data),"isHomog"); else atKill((idhdl)(v->LData()),"isHomog"); } } return FALSE; } static BOOLEAN jjidMaxIdeal(leftv res, leftv v) { res->data = (char *)idMaxIdeal((int)(long)v->Data()); setFlag(res,FLAG_STD); return FALSE; } static BOOLEAN jjIDEAL_Ma(leftv res, leftv v) { matrix mat=(matrix)v->CopyD(MATRIX_CMD); IDELEMS((ideal)mat)=MATCOLS(mat)*MATROWS(mat); if (IDELEMS((ideal)mat)==0) { idDelete((ideal *)&mat); mat=(matrix)idInit(1,1); } else { MATROWS(mat)=1; mat->rank=1; idTest((ideal)mat); } res->data=(char *)mat; return FALSE; } static BOOLEAN jjIDEAL_Map(leftv res, leftv v) { map m=(map)v->CopyD(MAP_CMD); omFree((ADDRESS)m->preimage); m->preimage=NULL; ideal I=(ideal)m; I->rank=1; res->data=(char *)I; return FALSE; } static BOOLEAN jjIDEAL_R(leftv res, leftv v) { if (currRing!=NULL) { ring q=(ring)v->Data(); if (rSamePolyRep(currRing, q)) { if (q->qideal==NULL) res->data=(char *)idInit(1,1); else res->data=(char *)idCopy(q->qideal); return FALSE; } } WerrorS("can only get ideal from identical qring"); return TRUE; } static BOOLEAN jjIm2Iv(leftv res, leftv v) { intvec *iv = (intvec *)v->CopyD(INTMAT_CMD); iv->makeVector(); res->data = iv; return FALSE; } static BOOLEAN jjIMPART(leftv res, leftv v) { res->data = (char *)n_ImPart((number)v->Data(),currRing->cf); return FALSE; } static BOOLEAN jjINDEPSET(leftv res, leftv v) { assumeStdFlag(v); res->data=(void *)scIndIntvec((ideal)(v->Data()),currRing->qideal); return FALSE; } static BOOLEAN jjINTERRED(leftv res, leftv v) { ideal result=kInterRed((ideal)(v->Data()), currRing->qideal); #ifdef HAVE_RINGS if(rField_is_Ring(currRing)) Warn("interred: this command is experimental over the integers"); #endif if (TEST_OPT_PROT) { PrintLn(); mflush(); } res->data = result; return FALSE; } static BOOLEAN jjIS_RINGVAR_P(leftv res, leftv v) { res->data = (char *)(long)pVar((poly)v->Data()); return FALSE; } static BOOLEAN jjIS_RINGVAR_S(leftv res, leftv v) { res->data = (char *)(long)(r_IsRingVar((char *)v->Data(), currRing->names, currRing->N)+1); return FALSE; } static BOOLEAN jjIS_RINGVAR0(leftv res, leftv) { res->data = (char *)0; return FALSE; } static BOOLEAN jjJACOB_P(leftv res, leftv v) { ideal i=idInit(currRing->N,1); int k; poly p=(poly)(v->Data()); for (k=currRing->N;k>0;k--) { i->m[k-1]=pDiff(p,k); } res->data = (char *)i; return FALSE; } static BOOLEAN jjDIFF_COEF(leftv res, leftv u, leftv v) { if (!nCoeff_is_transExt(currRing->cf)) { WerrorS("differentiation not defined in the coefficient ring"); return TRUE; } number n = (number) u->Data(); number k = (number) v->Data(); res->data = ntDiff(n,k,currRing->cf); return FALSE; } /*2 * compute Jacobi matrix of a module/matrix * Jacobi(M) := ( diff(Mt,var(1))|, ... ,| diff(Mt,var(currRing->N)) ), * where Mt := transpose(M) * Note that this is consistent with the current conventions for jacob in Singular, * whereas M2 computes its transposed. */ static BOOLEAN jjJACOB_M(leftv res, leftv a) { ideal id = (ideal)a->Data(); id = id_Transp(id,currRing); int W = IDELEMS(id); ideal result = idInit(W * currRing->N, id->rank); poly *p = result->m; for( int v = 1; v <= currRing->N; v++ ) { poly* q = id->m; for( int i = 0; i < W; i++, p++, q++ ) *p = pDiff( *q, v ); } idDelete(&id); res->data = (char *)result; return FALSE; } static BOOLEAN jjKBASE(leftv res, leftv v) { assumeStdFlag(v); res->data = (char *)scKBase(-1,(ideal)(v->Data()),currRing->qideal); return FALSE; } static BOOLEAN jjL2R(leftv res, leftv v) { res->data=(char *)syConvList((lists)v->Data(),FALSE); if (res->data != NULL) return FALSE; else return TRUE; } static BOOLEAN jjLEADCOEF(leftv res, leftv v) { poly p=(poly)v->Data(); if (p==NULL) { res->data=(char *)nInit(0); } else { res->data=(char *)nCopy(pGetCoeff(p)); } return FALSE; } static BOOLEAN jjLEADEXP(leftv res, leftv v) { poly p=(poly)v->Data(); int s=currRing->N; if (v->Typ()==VECTOR_CMD) s++; intvec *iv=new intvec(s); if (p!=NULL) { for(int i = currRing->N;i;i--) { (*iv)[i-1]=pGetExp(p,i); } if (s!=currRing->N) (*iv)[currRing->N]=pGetComp(p); } res->data=(char *)iv; return FALSE; } static BOOLEAN jjLEADMONOM(leftv res, leftv v) { poly p=(poly)v->Data(); if (p == NULL) { res->data = (char*) NULL; } else { poly lm = pLmInit(p); pSetCoeff(lm, nInit(1)); res->data = (char*) lm; } return FALSE; } static BOOLEAN jjLOAD1(leftv /*res*/, leftv v) { return jjLOAD((char*)v->Data(),FALSE); } static BOOLEAN jjLISTRING(leftv res, leftv v) { ring r=rCompose((lists)v->Data()); if (r==NULL) return TRUE; if (r->qideal!=NULL) res->rtyp=QRING_CMD; res->data=(char *)r; return FALSE; } static BOOLEAN jjPFAC1(leftv res, leftv v) { /* call method jjPFAC2 with second argument = 0 (meaning that no valid bound for the prime factors has been given) */ sleftv tmp; memset(&tmp, 0, sizeof(tmp)); tmp.rtyp = INT_CMD; return jjPFAC2(res, v, &tmp); } static BOOLEAN jjLU_DECOMP(leftv res, leftv v) { /* computes the LU-decomposition of a matrix M; i.e., M = P * L * U, where - P is a row permutation matrix, - L is in lower triangular form, - U is in upper row echelon form Then, we also have P * M = L * U. A list [P, L, U] is returned. */ matrix mat = (const matrix)v->Data(); if (!idIsConstant((ideal)mat)) { WerrorS("matrix must be constant"); return TRUE; } matrix pMat; matrix lMat; matrix uMat; luDecomp(mat, pMat, lMat, uMat); lists ll = (lists)omAllocBin(slists_bin); ll->Init(3); ll->m[0].rtyp=MATRIX_CMD; ll->m[0].data=(void *)pMat; ll->m[1].rtyp=MATRIX_CMD; ll->m[1].data=(void *)lMat; ll->m[2].rtyp=MATRIX_CMD; ll->m[2].data=(void *)uMat; res->data=(char*)ll; return FALSE; } static BOOLEAN jjMEMORY(leftv res, leftv v) { omUpdateInfo(); switch(((int)(long)v->Data())) { case 0: res->data=(char *)n_Init(om_Info.UsedBytes,coeffs_BIGINT); break; case 1: res->data = (char *)n_Init(om_Info.CurrentBytesSystem,coeffs_BIGINT); break; case 2: res->data = (char *)n_Init(om_Info.MaxBytesSystem,coeffs_BIGINT); break; default: omPrintStats(stdout); omPrintInfo(stdout); omPrintBinStats(stdout); res->data = (char *)0; res->rtyp = NONE; } return FALSE; res->data = (char *)0; return FALSE; } //static BOOLEAN jjMONITOR1(leftv res, leftv v) //{ // return jjMONITOR2(res,v,NULL); //} static BOOLEAN jjMSTD(leftv res, leftv v) { int t=v->Typ(); ideal r,m; r=kMin_std((ideal)v->Data(),currRing->qideal,testHomog,NULL,m); lists l=(lists)omAllocBin(slists_bin); l->Init(2); l->m[0].rtyp=t; l->m[0].data=(char *)r; setFlag(&(l->m[0]),FLAG_STD); l->m[1].rtyp=t; l->m[1].data=(char *)m; res->data=(char *)l; return FALSE; } static BOOLEAN jjMULT(leftv res, leftv v) { assumeStdFlag(v); res->data = (char *)(long)scMultInt((ideal)(v->Data()),currRing->qideal); return FALSE; } static BOOLEAN jjMINRES_R(leftv res, leftv v) { intvec *weights=(intvec*)atGet(v,"isHomog",INTVEC_CMD); syStrategy tmp=(syStrategy)v->Data(); tmp = syMinimize(tmp); // enrich itself! res->data=(char *)tmp; if (weights!=NULL) atSet(res, omStrDup("isHomog"),ivCopy(weights),INTVEC_CMD); return FALSE; } static BOOLEAN jjN2BI(leftv res, leftv v) { number n,i; i=(number)v->Data(); nMapFunc nMap=n_SetMap(currRing->cf,coeffs_BIGINT); if (nMap!=NULL) n=nMap(i,currRing->cf,coeffs_BIGINT); else goto err; res->data=(void *)n; return FALSE; err: WerrorS("cannot convert to bigint"); return TRUE; } static BOOLEAN jjNAMEOF(leftv res, leftv v) { res->data = (char *)v->name; if (res->data==NULL) res->data=omStrDup(""); v->name=NULL; return FALSE; } static BOOLEAN jjNAMES(leftv res, leftv v) { res->data=ipNameList(((ring)v->Data())->idroot); return FALSE; } static BOOLEAN jjNAMES_I(leftv res, leftv v) { res->data=ipNameListLev((IDROOT),(int)(long)v->Data()); return FALSE; } static BOOLEAN jjNOT(leftv res, leftv v) { res->data=(char*)(long)((long)v->Data()==0 ? 1 : 0); return FALSE; } static BOOLEAN jjNVARS(leftv res, leftv v) { res->data = (char *)(long)(((ring)(v->Data()))->N); return FALSE; } static BOOLEAN jjOpenClose(leftv, leftv v) { si_link l=(si_link)v->Data(); if (iiOp==OPEN_CMD) return slOpen(l, SI_LINK_OPEN,v); else return slClose(l); } static BOOLEAN jjORD(leftv res, leftv v) { poly p=(poly)v->Data(); res->data=(char *)( p==NULL ? -1 : currRing->pFDeg(p,currRing) ); return FALSE; } static BOOLEAN jjPAR1(leftv res, leftv v) { int i=(int)(long)v->Data(); int p=0; p=rPar(currRing); if ((0data=(char *)n_Param(i,currRing); } else { Werror("par number %d out of range 1..%d",i,p); return TRUE; } return FALSE; } static BOOLEAN jjPARDEG(leftv res, leftv v) { number nn=(number)v->Data(); res->data = (char *)(long)n_ParDeg(nn, currRing); return FALSE; } static BOOLEAN jjPARSTR1(leftv res, leftv v) { if (currRing==NULL) { WerrorS("no ring active"); return TRUE; } int i=(int)(long)v->Data(); int p=0; if ((0data=omStrDup(rParameter(currRing)[i-1]); else { Werror("par number %d out of range 1..%d",i,p); return TRUE; } return FALSE; } static BOOLEAN jjP2BI(leftv res, leftv v) { poly p=(poly)v->Data(); if (p==NULL) { res->data=(char *)n_Init(0,coeffs_BIGINT); return FALSE; } if ((pNext(p)!=NULL)|| (!pIsConstant(p))) { WerrorS("poly must be constant"); return TRUE; } number i=pGetCoeff(p); number n; nMapFunc nMap=n_SetMap(currRing->cf,coeffs_BIGINT); if (nMap!=NULL) n=nMap(i,currRing->cf,coeffs_BIGINT); else goto err; res->data=(void *)n; return FALSE; err: WerrorS("cannot convert to bigint"); return TRUE; } static BOOLEAN jjP2I(leftv res, leftv v) { poly p=(poly)v->Data(); if (p==NULL) { /*res->data=(char *)0;*/ return FALSE; } if ((pNext(p)!=NULL)|| (!pIsConstant(p))) { WerrorS("poly must be constant"); return TRUE; } res->data = (char *)(long)iin_Int(pGetCoeff(p),currRing->cf); return FALSE; } static BOOLEAN jjPREIMAGE_R(leftv res, leftv v) { map mapping=(map)v->Data(); syMake(res,omStrDup(mapping->preimage)); return FALSE; } static BOOLEAN jjPRIME(leftv res, leftv v) { int i = IsPrime((int)(long)(v->Data())); res->data = (char *)(long)(i > 1 ? i : 2); return FALSE; } static BOOLEAN jjPRUNE(leftv res, leftv v) { intvec *w=(intvec *)atGet(v,"isHomog",INTVEC_CMD); ideal v_id=(ideal)v->Data(); if (w!=NULL) { if (!idTestHomModule(v_id,currRing->qideal,w)) { WarnS("wrong weights"); w=NULL; // and continue at the non-homog case below } else { w=ivCopy(w); intvec **ww=&w; res->data = (char *)idMinEmbedding(v_id,FALSE,ww); atSet(res,omStrDup("isHomog"),*ww,INTVEC_CMD); return FALSE; } } res->data = (char *)idMinEmbedding(v_id); return FALSE; } static BOOLEAN jjP2N(leftv res, leftv v) { number n; poly p; if (((p=(poly)v->Data())!=NULL) && (pIsConstant(p))) { n=nCopy(pGetCoeff(p)); } else { n=nInit(0); } res->data = (char *)n; return FALSE; } static BOOLEAN jjRESERVEDNAME(leftv res, leftv v) { char *s= (char *)v->Data(); int i = 1; for(i=0; i>%s<<, tab:>>%s<<\n",i,s,sArithBase.sCmds[i].name); if (strcmp(s, sArithBase.sCmds[i].name) == 0) { res->data = (char *)1; return FALSE; } } //res->data = (char *)0; return FALSE; } static BOOLEAN jjRANK1(leftv res, leftv v) { matrix m =(matrix)v->Data(); int rank = luRank(m, 0); res->data =(char *)(long)rank; return FALSE; } static BOOLEAN jjREAD(leftv res, leftv v) { return jjREAD2(res,v,NULL); } static BOOLEAN jjREGULARITY(leftv res, leftv v) { res->data = (char *)(long)iiRegularity((lists)v->Data()); return FALSE; } static BOOLEAN jjREPART(leftv res, leftv v) { res->data = (char *)n_RePart((number)v->Data(),currRing->cf); return FALSE; } static BOOLEAN jjRINGLIST(leftv res, leftv v) { ring r=(ring)v->Data(); if (r!=NULL) res->data = (char *)rDecompose((ring)v->Data()); return (r==NULL)||(res->data==NULL); } #ifdef SINGULAR_4_1 static BOOLEAN jjRINGLIST_C(leftv res, leftv v) { coeffs r=(coeffs)v->Data(); if (r!=NULL) return rDecompose_CF(res,r); return TRUE; } #endif static BOOLEAN jjROWS(leftv res, leftv v) { ideal i = (ideal)v->Data(); res->data = (char *)i->rank; return FALSE; } static BOOLEAN jjROWS_BIM(leftv res, leftv v) { res->data = (char *)(long)((bigintmat*)(v->Data()))->rows(); return FALSE; } static BOOLEAN jjROWS_IV(leftv res, leftv v) { res->data = (char *)(long)((intvec*)(v->Data()))->rows(); return FALSE; } static BOOLEAN jjRPAR(leftv res, leftv v) { res->data = (char *)(long)rPar(((ring)v->Data())); return FALSE; } static BOOLEAN jjSLIM_GB(leftv res, leftv u) { #ifdef HAVE_PLURAL const bool bIsSCA = rIsSCA(currRing); #else const bool bIsSCA = false; #endif if ((currRing->qideal!=NULL) && !bIsSCA) { WerrorS("qring not supported by slimgb at the moment"); return TRUE; } if (rHasLocalOrMixedOrdering_currRing()) { WerrorS("ordering must be global for slimgb"); return TRUE; } intvec *w=(intvec *)atGet(u,"isHomog",INTVEC_CMD); // tHomog hom=testHomog; ideal u_id=(ideal)u->Data(); if (w!=NULL) { if (!idTestHomModule(u_id,currRing->qideal,w)) { WarnS("wrong weights"); w=NULL; } else { w=ivCopy(w); // hom=isHomog; } } assume(u_id->rank>=id_RankFreeModule(u_id, currRing)); res->data=(char *)t_rep_gb(currRing, u_id,u_id->rank); //res->data=(char *)t_rep_gb(currRing, u_id); if(!TEST_OPT_DEGBOUND) setFlag(res,FLAG_STD); if (w!=NULL) atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); return FALSE; } static BOOLEAN jjSBA(leftv res, leftv v) { ideal result; ideal v_id=(ideal)v->Data(); intvec *w=(intvec *)atGet(v,"isHomog",INTVEC_CMD); tHomog hom=testHomog; if (w!=NULL) { if (!idTestHomModule(v_id,currRing->qideal,w)) { WarnS("wrong weights"); w=NULL; } else { hom=isHomog; w=ivCopy(w); } } result=kSba(v_id,currRing->qideal,hom,&w,1,0); idSkipZeroes(result); res->data = (char *)result; if(!TEST_OPT_DEGBOUND) setFlag(res,FLAG_STD); if (w!=NULL) atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); return FALSE; } static BOOLEAN jjSBA_1(leftv res, leftv v, leftv u) { ideal result; ideal v_id=(ideal)v->Data(); intvec *w=(intvec *)atGet(v,"isHomog",INTVEC_CMD); tHomog hom=testHomog; if (w!=NULL) { if (!idTestHomModule(v_id,currRing->qideal,w)) { WarnS("wrong weights"); w=NULL; } else { hom=isHomog; w=ivCopy(w); } } result=kSba(v_id,currRing->qideal,hom,&w,(int)(long)u->Data(),0); idSkipZeroes(result); res->data = (char *)result; if(!TEST_OPT_DEGBOUND) setFlag(res,FLAG_STD); if (w!=NULL) atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); return FALSE; } static BOOLEAN jjSBA_2(leftv res, leftv v, leftv u, leftv t) { ideal result; ideal v_id=(ideal)v->Data(); intvec *w=(intvec *)atGet(v,"isHomog",INTVEC_CMD); tHomog hom=testHomog; if (w!=NULL) { if (!idTestHomModule(v_id,currRing->qideal,w)) { WarnS("wrong weights"); w=NULL; } else { hom=isHomog; w=ivCopy(w); } } result=kSba(v_id,currRing->qideal,hom,&w,(int)(long)u->Data(),(int)(long)t->Data()); idSkipZeroes(result); res->data = (char *)result; if(!TEST_OPT_DEGBOUND) setFlag(res,FLAG_STD); if (w!=NULL) atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); return FALSE; } static BOOLEAN jjSTD(leftv res, leftv v) { ideal result; ideal v_id=(ideal)v->Data(); intvec *w=(intvec *)atGet(v,"isHomog",INTVEC_CMD); tHomog hom=testHomog; if (w!=NULL) { if (!idTestHomModule(v_id,currRing->qideal,w)) { WarnS("wrong weights"); w=NULL; } else { hom=isHomog; w=ivCopy(w); } } result=kStd(v_id,currRing->qideal,hom,&w); idSkipZeroes(result); res->data = (char *)result; if(!TEST_OPT_DEGBOUND) setFlag(res,FLAG_STD); if (w!=NULL) atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); return FALSE; } static BOOLEAN jjSort_Id(leftv res, leftv v) { res->data = (char *)idSort((ideal)v->Data()); return FALSE; } static BOOLEAN jjSQR_FREE(leftv res, leftv u) { singclap_factorize_retry=0; intvec *v=NULL; ideal f=singclap_sqrfree((poly)(u->CopyD()), &v, 0, currRing); if (f==NULL) return TRUE; ivTest(v); lists l=(lists)omAllocBin(slists_bin); l->Init(2); l->m[0].rtyp=IDEAL_CMD; l->m[0].data=(void *)f; l->m[1].rtyp=INTVEC_CMD; l->m[1].data=(void *)v; res->data=(void *)l; return FALSE; } #if 1 static BOOLEAN jjSYZYGY(leftv res, leftv v) { intvec *w=NULL; res->data = (char *)idSyzygies((ideal)v->Data(),testHomog,&w); if (w!=NULL) delete w; if (TEST_OPT_RETURN_SB) setFlag(res,FLAG_STD); return FALSE; } #else // activate, if idSyz handle module weights correctly ! static BOOLEAN jjSYZYGY(leftv res, leftv v) { intvec *w=(intvec *)atGet(v,"isHomog",INTVEC_CMD); ideal v_id=(ideal)v->Data(); tHomog hom=testHomog; int add_row_shift=0; if (w!=NULL) { w=ivCopy(w); add_row_shift=w->min_in(); (*w)-=add_row_shift; if (idTestHomModule(v_id,currRing->qideal,w)) hom=isHomog; else { //WarnS("wrong weights"); delete w; w=NULL; hom=testHomog; } } res->data = (char *)idSyzygies(v_id,hom,&w); if (w!=NULL) { atSet(res,omStrDup("isHomog"),w,INTVEC_CMD); } return FALSE; } #endif static BOOLEAN jjTRACE_IV(leftv res, leftv v) { res->data = (char *)(long)ivTrace((intvec*)(v->Data())); return FALSE; } static BOOLEAN jjTRANSP_BIM(leftv res, leftv v) { res->data = (char *)(((bigintmat*)(v->Data()))->transpose()); return FALSE; } static BOOLEAN jjTRANSP_IV(leftv res, leftv v) { res->data = (char *)ivTranp((intvec*)(v->Data())); return FALSE; } #ifdef HAVE_PLURAL static BOOLEAN jjOPPOSITE(leftv res, leftv a) { ring r = (ring)a->Data(); //if (rIsPluralRing(r)) if (r->OrdSgn==1) { res->data = rOpposite(r); } else { WarnS("opposite only for global orderings"); res->data = rCopy(r); } return FALSE; } static BOOLEAN jjENVELOPE(leftv res, leftv a) { ring r = (ring)a->Data(); if (rIsPluralRing(r)) { // ideal i; // if (a->rtyp == QRING_CMD) // { // i = r->qideal; // r->qideal = NULL; // } ring s = rEnvelope(r); // if (a->rtyp == QRING_CMD) // { // ideal is = idOppose(r,i); /* twostd? */ // is = idAdd(is,i); // s->qideal = i; // } res->data = s; } else res->data = rCopy(r); return FALSE; } static BOOLEAN jjTWOSTD(leftv res, leftv a) { if (rIsPluralRing(currRing)) res->data=(ideal)twostd((ideal)a->Data()); else res->data=(ideal)a->CopyD(); setFlag(res,FLAG_STD); setFlag(res,FLAG_TWOSTD); return FALSE; } #endif static BOOLEAN jjTYPEOF(leftv res, leftv v) { int t=(int)(long)v->data; switch (t) { #ifdef SINGULAR_4_1 case CRING_CMD: #endif case INT_CMD: case POLY_CMD: case VECTOR_CMD: case STRING_CMD: case INTVEC_CMD: case IDEAL_CMD: case MATRIX_CMD: case MODUL_CMD: case MAP_CMD: case PROC_CMD: case RING_CMD: case QRING_CMD: case INTMAT_CMD: case BIGINTMAT_CMD: case NUMBER_CMD: #ifdef SINGULAR_4_1 case CNUMBER_CMD: #endif case BIGINT_CMD: case LIST_CMD: case PACKAGE_CMD: case LINK_CMD: case RESOLUTION_CMD: res->data=omStrDup(Tok2Cmdname(t)); break; case DEF_CMD: case NONE: res->data=omStrDup("none"); break; default: { if (t>MAX_TOK) res->data=omStrDup(getBlackboxName(t)); else res->data=omStrDup("?unknown type?"); break; } } return FALSE; } static BOOLEAN jjUNIVARIATE(leftv res, leftv v) { res->data=(char *)(long)pIsUnivariate((poly)v->Data()); return FALSE; } static BOOLEAN jjVAR1(leftv res, leftv v) { int i=(int)(long)v->Data(); if ((0N)) { poly p=pOne(); pSetExp(p,i,1); pSetm(p); res->data=(char *)p; } else { Werror("var number %d out of range 1..%d",i,currRing->N); return TRUE; } return FALSE; } static BOOLEAN jjVARSTR1(leftv res, leftv v) { if (currRing==NULL) { WerrorS("no ring active"); return TRUE; } int i=(int)(long)v->Data(); if ((0N)) res->data=omStrDup(currRing->names[i-1]); else { Werror("var number %d out of range 1..%d",i,currRing->N); return TRUE; } return FALSE; } static BOOLEAN jjVDIM(leftv res, leftv v) { assumeStdFlag(v); res->data = (char *)(long)scMult0Int((ideal)v->Data(),currRing->qideal); return FALSE; } BOOLEAN jjWAIT1ST1(leftv res, leftv u) { // input: u: a list with links of type // ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch // returns: -1: the read state of all links is eof // i>0: (at least) u[i] is ready lists Lforks = (lists)u->Data(); int i = slStatusSsiL(Lforks, -1); if(i == -2) /* error */ { return TRUE; } res->data = (void*)(long)i; return FALSE; } BOOLEAN jjWAITALL1(leftv res, leftv u) { // input: u: a list with links of type // ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch // returns: -1: the read state of all links is eof // 1: all links are ready // (caution: at least one is ready, but some maybe dead) lists Lforks = (lists)u->CopyD(); int i; int j = -1; for(int nfinished = 0; nfinished < Lforks->nr+1; nfinished++) { i = slStatusSsiL(Lforks, -1); if(i == -2) /* error */ { return TRUE; } if(i == -1) { break; } j = 1; Lforks->m[i-1].CleanUp(); Lforks->m[i-1].rtyp=DEF_CMD; Lforks->m[i-1].data=NULL; } res->data = (void*)(long)j; Lforks->Clean(); return FALSE; } BOOLEAN jjLOAD(const char *s, BOOLEAN autoexport) { char libnamebuf[256]; lib_types LT = type_of_LIB(s, libnamebuf); #ifdef HAVE_DYNAMIC_LOADING extern BOOLEAN load_modules(const char *newlib, char *fullpath, BOOLEAN autoexport); #endif /* HAVE_DYNAMIC_LOADING */ switch(LT) { default: case LT_NONE: Werror("%s: unknown type", s); break; case LT_NOTFOUND: Werror("cannot open %s", s); break; case LT_SINGULAR: { char *plib = iiConvName(s); idhdl pl = IDROOT->get(plib,0); if (pl==NULL) { pl = enterid( plib,0, PACKAGE_CMD, &(basePack->idroot), TRUE ); IDPACKAGE(pl)->language = LANG_SINGULAR; IDPACKAGE(pl)->libname=omStrDup(plib); } else if (IDTYP(pl)!=PACKAGE_CMD) { Werror("can not create package `%s`",plib); omFree(plib); return TRUE; } package savepack=currPack; currPack=IDPACKAGE(pl); IDPACKAGE(pl)->loaded=TRUE; char libnamebuf[256]; FILE * fp = feFopen( s, "r", libnamebuf, TRUE ); BOOLEAN bo=iiLoadLIB(fp, libnamebuf, s, pl, autoexport, TRUE); currPack=savepack; IDPACKAGE(pl)->loaded=(!bo); return bo; } case LT_BUILTIN: SModulFunc_t iiGetBuiltinModInit(const char*); return load_builtin(s,autoexport, iiGetBuiltinModInit(s)); case LT_MACH_O: case LT_ELF: case LT_HPUX: #ifdef HAVE_DYNAMIC_LOADING return load_modules(s, libnamebuf, autoexport); #else /* HAVE_DYNAMIC_LOADING */ WerrorS("Dynamic modules are not supported by this version of Singular"); break; #endif /* HAVE_DYNAMIC_LOADING */ } return TRUE; } static int WerrorS_dummy_cnt=0; static void WerrorS_dummy(const char *) { WerrorS_dummy_cnt++; } BOOLEAN jjLOAD_TRY(const char *s) { void (*WerrorS_save)(const char *s) = WerrorS_callback; WerrorS_callback=WerrorS_dummy; WerrorS_dummy_cnt=0; BOOLEAN bo=jjLOAD(s,TRUE); if (TEST_OPT_PROT && (bo || (WerrorS_dummy_cnt>0))) Print("loading of >%s< failed\n",s); WerrorS_callback=WerrorS_save; errorreported=0; return FALSE; } static BOOLEAN jjstrlen(leftv res, leftv v) { res->data = (char *)strlen((char *)v->Data()); return FALSE; } static BOOLEAN jjpLength(leftv res, leftv v) { res->data = (char *)(long)pLength((poly)v->Data()); return FALSE; } static BOOLEAN jjidElem(leftv res, leftv v) { res->data = (char *)(long)idElem((ideal)v->Data()); return FALSE; } static BOOLEAN jjidFreeModule(leftv res, leftv v) { res->data = (char *)id_FreeModule((int)(long)v->Data(), currRing); return FALSE; } static BOOLEAN jjidVec2Ideal(leftv res, leftv v) { res->data = (char *)id_Vec2Ideal((poly)v->Data(), currRing); return FALSE; } static BOOLEAN jjrCharStr(leftv res, leftv v) { #ifdef SINGULAR_4_1 iiReWrite("charstr"); #endif res->data = rCharStr((ring)v->Data()); return FALSE; } static BOOLEAN jjpHead(leftv res, leftv v) { res->data = (char *)pHead((poly)v->Data()); return FALSE; } static BOOLEAN jjidHead(leftv res, leftv v) { res->data = (char *)id_Head((ideal)v->Data(),currRing); setFlag(res,FLAG_STD); return FALSE; } static BOOLEAN jjidMinBase(leftv res, leftv v) { res->data = (char *)idMinBase((ideal)v->Data()); return FALSE; } static BOOLEAN jjsyMinBase(leftv res, leftv v) { res->data = (char *)syMinBase((ideal)v->Data()); return FALSE; } static BOOLEAN jjpMaxComp(leftv res, leftv v) { res->data = (char *)pMaxComp((poly)v->Data()); return FALSE; } static BOOLEAN jjmpTrace(leftv res, leftv v) { res->data = (char *)mp_Trace((matrix)v->Data(),currRing); return FALSE; } static BOOLEAN jjmpTransp(leftv res, leftv v) { res->data = (char *)mp_Transp((matrix)v->Data(),currRing); return FALSE; } static BOOLEAN jjrOrdStr(leftv res, leftv v) { #ifdef SINGULAR_4_1 iiReWrite("ordstr"); #endif res->data = rOrdStr((ring)v->Data()); return FALSE; } static BOOLEAN jjrVarStr(leftv res, leftv v) { #ifdef SINGULAR_4_1 iiReWrite("varstr"); #endif res->data = rVarStr((ring)v->Data()); return FALSE; } static BOOLEAN jjrParStr(leftv res, leftv v) { #ifdef SINGULAR_4_1 iiReWrite("varstr"); #endif res->data = rParStr((ring)v->Data()); return FALSE; } static BOOLEAN jjCOUNT_RES(leftv res, leftv v) { res->data=(char *)(long)sySize((syStrategy)v->Data()); return FALSE; } static BOOLEAN jjDIM_R(leftv res, leftv v) { res->data = (char *)(long)syDim((syStrategy)v->Data()); return FALSE; } static BOOLEAN jjidTransp(leftv res, leftv v) { res->data = (char *)id_Transp((ideal)v->Data(),currRing); return FALSE; } static BOOLEAN jjnInt(leftv res, leftv u) { number n=(number)u->CopyD(); // n_Int may call n_Normalize res->data=(char *)(long)iin_Int(n,currRing->cf); n_Delete(&n,currRing->cf); return FALSE; } static BOOLEAN jjnlInt(leftv res, leftv u) { number n=(number)u->Data(); res->data=(char *)(long)iin_Int(n,coeffs_BIGINT ); return FALSE; } /*=================== operations with 3 args.: static proc =================*/ /* must be ordered: first operations for chars (infix ops), * then alphabetically */ static BOOLEAN jjBRACK_S(leftv res, leftv u, leftv v,leftv w) { char *s= (char *)u->Data(); int r = (int)(long)v->Data(); int c = (int)(long)w->Data(); int l = strlen(s); if ( (r<1) || (r>l) || (c<0) ) { Werror("wrong range[%d,%d] in string %s",r,c,u->Fullname()); return TRUE; } res->data = (char *)omAlloc((long)(c+1)); sprintf((char *)res->data,"%-*.*s",c,c,s+r-1); return FALSE; } static BOOLEAN jjBRACK_Im(leftv res, leftv u, leftv v,leftv w) { intvec *iv = (intvec *)u->Data(); int r = (int)(long)v->Data(); int c = (int)(long)w->Data(); if ((r<1)||(r>iv->rows())||(c<1)||(c>iv->cols())) { Werror("wrong range[%d,%d] in intmat %s(%d x %d)", r,c,u->Fullname(),iv->rows(),iv->cols()); return TRUE; } res->data=u->data; u->data=NULL; res->rtyp=u->rtyp; u->rtyp=0; res->name=u->name; u->name=NULL; Subexpr e=jjMakeSub(v); e->next=jjMakeSub(w); if (u->e==NULL) res->e=e; else { Subexpr h=u->e; while (h->next!=NULL) h=h->next; h->next=e; res->e=u->e; u->e=NULL; } return FALSE; } static BOOLEAN jjBRACK_Bim(leftv res, leftv u, leftv v, leftv w) { bigintmat *bim = (bigintmat *)u->Data(); int r = (int)(long)v->Data(); int c = (int)(long)w->Data(); if ((r<1)||(r>bim->rows())||(c<1)||(c>bim->cols())) { Werror("wrong range[%d,%d] in bigintmat %s(%d x %d)", r,c,u->Fullname(),bim->rows(),bim->cols()); return TRUE; } res->data=u->data; u->data=NULL; res->rtyp=u->rtyp; u->rtyp=0; res->name=u->name; u->name=NULL; Subexpr e=jjMakeSub(v); e->next=jjMakeSub(w); if (u->e==NULL) res->e=e; else { Subexpr h=u->e; while (h->next!=NULL) h=h->next; h->next=e; res->e=u->e; u->e=NULL; } return FALSE; } static BOOLEAN jjBRACK_Ma(leftv res, leftv u, leftv v,leftv w) { matrix m= (matrix)u->Data(); int r = (int)(long)v->Data(); int c = (int)(long)w->Data(); //Print("gen. elem %d, %d\n",r,c); if ((r<1)||(r>MATROWS(m))||(c<1)||(c>MATCOLS(m))) { Werror("wrong range[%d,%d] in matrix %s(%d x %d)",r,c,u->Fullname(), MATROWS(m),MATCOLS(m)); return TRUE; } res->data=u->data; u->data=NULL; res->rtyp=u->rtyp; u->rtyp=0; res->name=u->name; u->name=NULL; Subexpr e=jjMakeSub(v); e->next=jjMakeSub(w); if (u->e==NULL) res->e=e; else { Subexpr h=u->e; while (h->next!=NULL) h=h->next; h->next=e; res->e=u->e; u->e=NULL; } return FALSE; } static BOOLEAN jjBRACK_Ma_I_IV(leftv res, leftv u, leftv v,leftv w) { sleftv t; sleftv ut; leftv p=NULL; intvec *iv=(intvec *)w->Data(); int l; BOOLEAN nok; if ((u->rtyp!=IDHDL)||(u->e!=NULL)) { WerrorS("cannot build expression lists from unnamed objects"); return TRUE; } memcpy(&ut,u,sizeof(ut)); memset(&t,0,sizeof(t)); t.rtyp=INT_CMD; for (l=0;l< iv->length(); l++) { t.data=(char *)(long)((*iv)[l]); if (p==NULL) { p=res; } else { p->next=(leftv)omAlloc0Bin(sleftv_bin); p=p->next; } memcpy(u,&ut,sizeof(ut)); if (u->Typ() == MATRIX_CMD) nok=jjBRACK_Ma(p,u,v,&t); else if (u->Typ() == BIGINTMAT_CMD) nok=jjBRACK_Bim(p,u,v,&t); else /* INTMAT_CMD */ nok=jjBRACK_Im(p,u,v,&t); if (nok) { while (res->next!=NULL) { p=res->next->next; omFreeBin((ADDRESS)res->next, sleftv_bin); // res->e aufraeumen !!!! res->next=p; } return TRUE; } } return FALSE; } static BOOLEAN jjBRACK_Ma_IV_I(leftv res, leftv u, leftv v,leftv w) { sleftv t; sleftv ut; leftv p=NULL; intvec *iv=(intvec *)v->Data(); int l; BOOLEAN nok; if ((u->rtyp!=IDHDL)||(u->e!=NULL)) { WerrorS("cannot build expression lists from unnamed objects"); return TRUE; } memcpy(&ut,u,sizeof(ut)); memset(&t,0,sizeof(t)); t.rtyp=INT_CMD; for (l=0;l< iv->length(); l++) { t.data=(char *)(long)((*iv)[l]); if (p==NULL) { p=res; } else { p->next=(leftv)omAlloc0Bin(sleftv_bin); p=p->next; } memcpy(u,&ut,sizeof(ut)); if (u->Typ() == MATRIX_CMD) nok=jjBRACK_Ma(p,u,&t,w); else if (u->Typ() == BIGINTMAT_CMD) nok=jjBRACK_Bim(p,u,&t,w); else /* INTMAT_CMD */ nok=jjBRACK_Im(p,u,&t,w); if (nok) { while (res->next!=NULL) { p=res->next->next; omFreeBin((ADDRESS)res->next, sleftv_bin); // res->e aufraeumen !! res->next=p; } return TRUE; } } return FALSE; } static BOOLEAN jjBRACK_Ma_IV_IV(leftv res, leftv u, leftv v,leftv w) { sleftv t1,t2,ut; leftv p=NULL; intvec *vv=(intvec *)v->Data(); intvec *wv=(intvec *)w->Data(); int vl; int wl; BOOLEAN nok; if ((u->rtyp!=IDHDL)||(u->e!=NULL)) { WerrorS("cannot build expression lists from unnamed objects"); return TRUE; } memcpy(&ut,u,sizeof(ut)); memset(&t1,0,sizeof(sleftv)); memset(&t2,0,sizeof(sleftv)); t1.rtyp=INT_CMD; t2.rtyp=INT_CMD; for (vl=0;vl< vv->length(); vl++) { t1.data=(char *)(long)((*vv)[vl]); for (wl=0;wl< wv->length(); wl++) { t2.data=(char *)(long)((*wv)[wl]); if (p==NULL) { p=res; } else { p->next=(leftv)omAlloc0Bin(sleftv_bin); p=p->next; } memcpy(u,&ut,sizeof(ut)); if (u->Typ() == MATRIX_CMD) nok=jjBRACK_Ma(p,u,&t1,&t2); else if (u->Typ() == BIGINTMAT_CMD) nok=jjBRACK_Bim(p,u,&t1,&t2); else /* INTMAT_CMD */ nok=jjBRACK_Im(p,u,&t1,&t2); if (nok) { res->CleanUp(); return TRUE; } } } return FALSE; } static BOOLEAN jjPROC3(leftv res, leftv u, leftv v, leftv w) { v->next=(leftv)omAllocBin(sleftv_bin); memcpy(v->next,w,sizeof(sleftv)); memset(w,0,sizeof(sleftv)); return jjPROC(res,u,v); } static BOOLEAN jjBAREISS3(leftv res, leftv u, leftv v, leftv w) { intvec *iv; ideal m; lists l=(lists)omAllocBin(slists_bin); int k=(int)(long)w->Data(); if (k>=0) { sm_CallBareiss((ideal)u->Data(),(int)(long)v->Data(),(int)(long)w->Data(),m,&iv, currRing); l->Init(2); l->m[0].rtyp=MODUL_CMD; l->m[1].rtyp=INTVEC_CMD; l->m[0].data=(void *)m; l->m[1].data=(void *)iv; } else { m=sm_CallSolv((ideal)u->Data(), currRing); l->Init(1); l->m[0].rtyp=IDEAL_CMD; l->m[0].data=(void *)m; } res->data = (char *)l; return FALSE; } static BOOLEAN jjCOEFFS3_Id(leftv res, leftv u, leftv v, leftv w) { if ((w->rtyp!=IDHDL)||(w->e!=NULL)) { WerrorS("3rd argument must be a name of a matrix"); return TRUE; } ideal i=(ideal)u->Data(); int rank=(int)i->rank; BOOLEAN r=jjCOEFFS_Id(res,u,v); if (r) return TRUE; mp_Monomials((matrix)res->data, rank, pVar((poly)v->Data()),(matrix)w->Data(),currRing); return FALSE; } static BOOLEAN jjCOEFFS3_KB(leftv res, leftv u, leftv v, leftv w) { res->data=(void*)idCoeffOfKBase((ideal)(u->Data()), (ideal)(v->Data()),(poly)(w->Data())); return FALSE; } static BOOLEAN jjCOEFFS3_P(leftv res, leftv u, leftv v, leftv w) { if ((w->rtyp!=IDHDL)||(w->e!=NULL)) { WerrorS("3rd argument must be a name of a matrix"); return TRUE; } // CopyD for POLY_CMD and VECTOR_CMD are identical: poly p=(poly)u->CopyD(POLY_CMD); ideal i=idInit(1,1); i->m[0]=p; sleftv t; memset(&t,0,sizeof(t)); t.data=(char *)i; t.rtyp=IDEAL_CMD; int rank=1; if (u->Typ()==VECTOR_CMD) { i->rank=rank=pMaxComp(p); t.rtyp=MODUL_CMD; } BOOLEAN r=jjCOEFFS_Id(res,&t,v); t.CleanUp(); if (r) return TRUE; mp_Monomials((matrix)res->data, rank, pVar((poly)v->Data()),(matrix)w->Data(),currRing); return FALSE; } static BOOLEAN jjELIMIN_HILB(leftv res, leftv u, leftv v, leftv w) { res->data=(char *)idElimination((ideal)u->Data(),(poly)v->Data(), (intvec *)w->Data()); //setFlag(res,FLAG_STD); return FALSE; } static BOOLEAN jjFIND3(leftv res, leftv u, leftv v, leftv w) { /*4 * look for the substring what in the string where * starting at position n * return the position of the first char of what in where * or 0 */ int n=(int)(long)w->Data(); char *where=(char *)u->Data(); char *what=(char *)v->Data(); char *found; if ((1>n)||(n>(int)strlen(where))) { Werror("start position %d out of range",n); return TRUE; } found = strchr(where+n-1,*what); if (*(what+1)!='\0') { while((found !=NULL) && (strncmp(found+1,what+1,strlen(what+1))!=0)) { found=strchr(found+1,*what); } } if (found != NULL) { res->data=(char *)((found-where)+1); } return FALSE; } static BOOLEAN jjFWALK3(leftv res, leftv u, leftv v, leftv w) { if ((int)(long)w->Data()==0) res->data=(char *)walkProc(u,v); else res->data=(char *)fractalWalkProc(u,v); setFlag( res, FLAG_STD ); return FALSE; } static BOOLEAN jjHILBERT3(leftv res, leftv u, leftv v, leftv w) { intvec *wdegree=(intvec*)w->Data(); if (wdegree->length()!=currRing->N) { Werror("weight vector must have size %d, not %d", currRing->N,wdegree->length()); return TRUE; } #ifdef HAVE_RINGS if (rField_is_Ring_Z(currRing)) { ring origR = currRing; ring tempR = rCopy(origR); coeffs new_cf=nInitChar(n_Q,NULL); nKillChar(tempR->cf); tempR->cf=new_cf; rComplete(tempR); ideal uid = (ideal)u->Data(); rChangeCurrRing(tempR); ideal uu = idrCopyR(uid, origR, currRing); sleftv uuAsLeftv; memset(&uuAsLeftv, 0, sizeof(uuAsLeftv)); uuAsLeftv.rtyp = IDEAL_CMD; uuAsLeftv.data = uu; uuAsLeftv.next = NULL; if (hasFlag(u, FLAG_STD)) setFlag(&uuAsLeftv,FLAG_STD); assumeStdFlag(&uuAsLeftv); Print("// NOTE: computation of Hilbert series etc. is being\n"); Print("// performed for generic fibre, that is, over Q\n"); intvec *module_w=(intvec*)atGet(&uuAsLeftv,"isHomog",INTVEC_CMD); intvec *iv=hFirstSeries(uu,module_w,currRing->qideal,wdegree); int returnWithTrue = 1; switch((int)(long)v->Data()) { case 1: res->data=(void *)iv; returnWithTrue = 0; case 2: res->data=(void *)hSecondSeries(iv); delete iv; returnWithTrue = 0; } if (returnWithTrue) { WerrorS(feNotImplemented); delete iv; } idDelete(&uu); rChangeCurrRing(origR); rDelete(tempR); if (returnWithTrue) return TRUE; else return FALSE; } #endif assumeStdFlag(u); intvec *module_w=(intvec *)atGet(u,"isHomog",INTVEC_CMD); intvec *iv=hFirstSeries((ideal)u->Data(),module_w,currRing->qideal,wdegree); switch((int)(long)v->Data()) { case 1: res->data=(void *)iv; return FALSE; case 2: res->data=(void *)hSecondSeries(iv); delete iv; return FALSE; } WerrorS(feNotImplemented); delete iv; return TRUE; } static BOOLEAN jjHOMOG_ID_W(leftv res, leftv u, leftv v, leftv /*w*/) { PrintS("TODO\n"); int i=pVar((poly)v->Data()); if (i==0) { WerrorS("ringvar expected"); return TRUE; } poly p=pOne(); pSetExp(p,i,1); pSetm(p); int d=pWTotaldegree(p); pLmDelete(p); if (d==1) res->data = (char *)id_Homogen((ideal)u->Data(), i, currRing); else WerrorS("variable must have weight 1"); return (d!=1); } static BOOLEAN jjHOMOG_P_W(leftv res, leftv u, leftv v,leftv /*w*/) { PrintS("TODO\n"); int i=pVar((poly)v->Data()); if (i==0) { WerrorS("ringvar expected"); return TRUE; } poly p=pOne(); pSetExp(p,i,1); pSetm(p); int d=pWTotaldegree(p); pLmDelete(p); if (d==1) res->data = (char *)p_Homogen((poly)u->Data(), i, currRing); else WerrorS("variable must have weight 1"); return (d!=1); } static BOOLEAN jjINTMAT3(leftv res, leftv u, leftv v,leftv w) { intvec* im= new intvec((int)(long)v->Data(),(int)(long)w->Data(), 0); intvec* arg = (intvec*) u->Data(); int i, n = si_min(im->cols()*im->rows(), arg->cols()*arg->rows()); for (i=0; idata = (char *)im; return FALSE; } static BOOLEAN jjJET_P_IV(leftv res, leftv u, leftv v, leftv w) { short *iw=iv2array((intvec *)w->Data(),currRing); res->data = (char *)ppJetW((poly)u->Data(),(int)(long)v->Data(),iw); omFreeSize( (ADDRESS)iw, (rVar(currRing)+1)*sizeof(short) ); return FALSE; } static BOOLEAN jjJET_P_P(leftv res, leftv u, leftv v, leftv w) { if (!pIsUnit((poly)v->Data())) { WerrorS("2nd argument must be a unit"); return TRUE; } res->data = (char *)p_Series((int)(long)w->Data(),(poly)u->CopyD(),(poly)v->CopyD(),NULL,currRing); return FALSE; } static BOOLEAN jjJET_ID_IV(leftv res, leftv u, leftv v, leftv w) { res->data = (char *)id_JetW((ideal)u->Data(),(int)(long)v->Data(), (intvec *)w->Data(),currRing); return FALSE; } static BOOLEAN jjJET_ID_M(leftv res, leftv u, leftv v, leftv w) { if (!mp_IsDiagUnit((matrix)v->Data(), currRing)) { WerrorS("2nd argument must be a diagonal matrix of units"); return TRUE; } res->data = (char *)idSeries((int)(long)w->Data(),(ideal)u->CopyD(), (matrix)v->CopyD()); return FALSE; } static BOOLEAN currRingIsOverIntegralDomain () { /* true for fields and Z, false otherwise */ if (rField_is_Ring_PtoM(currRing)) return FALSE; if (rField_is_Ring_2toM(currRing)) return FALSE; if (rField_is_Ring_ModN(currRing)) return FALSE; return TRUE; } static BOOLEAN jjMINOR_M(leftv res, leftv v) { /* Here's the use pattern for the minor command: minor ( matrix_expression m, int_expression minorSize, optional ideal_expression IasSB, optional int_expression k, optional string_expression algorithm, optional int_expression cachedMinors, optional int_expression cachedMonomials ) This method here assumes that there are at least two arguments. - If IasSB is present, it must be a std basis. All minors will be reduced w.r.t. IasSB. - If k is absent, all non-zero minors will be computed. If k is present and k > 0, the first k non-zero minors will be computed. If k is present and k < 0, the first |k| minors (some of which may be zero) will be computed. If k is present and k = 0, an error is reported. - If algorithm is absent, all the following arguments must be absent too. In this case, a heuristic picks the best-suited algorithm (among Bareiss, Laplace, and Laplace with caching). If algorithm is present, it must be one of "Bareiss", "bareiss", "Laplace", "laplace", "Cache", "cache". In the cases "Cache" and "cache" two more arguments may be given, determining how many entries the cache may have at most, and how many cached monomials there are at most. (Cached monomials are counted over all cached polynomials.) If these two additional arguments are not provided, 200 and 100000 will be used as defaults. */ matrix m; leftv u=v->next; v->next=NULL; int v_typ=v->Typ(); if (v_typ==MATRIX_CMD) { m = (const matrix)v->Data(); } else { if (v_typ==0) { Werror("`%s` is undefined",v->Fullname()); return TRUE; } // try to convert to MATRIX: int ii=iiTestConvert(v_typ,MATRIX_CMD); BOOLEAN bo; sleftv tmp; if (ii>0) bo=iiConvert(v_typ,MATRIX_CMD,ii,v,&tmp); else bo=TRUE; if (bo) { Werror("cannot convert %s to matrix",Tok2Cmdname(v_typ)); return TRUE; } m=(matrix)tmp.data; } const int mk = (const int)(long)u->Data(); bool noIdeal = true; bool noK = true; bool noAlgorithm = true; bool noCacheMinors = true; bool noCacheMonomials = true; ideal IasSB; int k; char* algorithm; int cacheMinors; int cacheMonomials; /* here come the different cases of correct argument sets */ if ((u->next != NULL) && (u->next->Typ() == IDEAL_CMD)) { IasSB = (ideal)u->next->Data(); noIdeal = false; if ((u->next->next != NULL) && (u->next->next->Typ() == INT_CMD)) { k = (int)(long)u->next->next->Data(); noK = false; assume(k != 0); if ((u->next->next->next != NULL) && (u->next->next->next->Typ() == STRING_CMD)) { algorithm = (char*)u->next->next->next->Data(); noAlgorithm = false; if ((u->next->next->next->next != NULL) && (u->next->next->next->next->Typ() == INT_CMD)) { cacheMinors = (int)(long)u->next->next->next->next->Data(); noCacheMinors = false; if ((u->next->next->next->next->next != NULL) && (u->next->next->next->next->next->Typ() == INT_CMD)) { cacheMonomials = (int)(long)u->next->next->next->next->next->Data(); noCacheMonomials = false; } } } } } else if ((u->next != NULL) && (u->next->Typ() == INT_CMD)) { k = (int)(long)u->next->Data(); noK = false; assume(k != 0); if ((u->next->next != NULL) && (u->next->next->Typ() == STRING_CMD)) { algorithm = (char*)u->next->next->Data(); noAlgorithm = false; if ((u->next->next->next != NULL) && (u->next->next->next->Typ() == INT_CMD)) { cacheMinors = (int)(long)u->next->next->next->Data(); noCacheMinors = false; if ((u->next->next->next->next != NULL) && (u->next->next->next->next->Typ() == INT_CMD)) { cacheMonomials = (int)(long)u->next->next->next->next->Data(); noCacheMonomials = false; } } } } else if ((u->next != NULL) && (u->next->Typ() == STRING_CMD)) { algorithm = (char*)u->next->Data(); noAlgorithm = false; if ((u->next->next != NULL) && (u->next->next->Typ() == INT_CMD)) { cacheMinors = (int)(long)u->next->next->Data(); noCacheMinors = false; if ((u->next->next->next != NULL) && (u->next->next->next->Typ() == INT_CMD)) { cacheMonomials = (int)(long)u->next->next->next->Data(); noCacheMonomials = false; } } } /* upper case conversion for the algorithm if present */ if (!noAlgorithm) { if (strcmp(algorithm, "bareiss") == 0) algorithm = (char*)"Bareiss"; if (strcmp(algorithm, "laplace") == 0) algorithm = (char*)"Laplace"; if (strcmp(algorithm, "cache") == 0) algorithm = (char*)"Cache"; } v->next=u; /* here come some tests */ if (!noIdeal) { assumeStdFlag(u->next); } if ((!noK) && (k == 0)) { WerrorS("Provided number of minors to be computed is zero."); return TRUE; } if ((!noAlgorithm) && (strcmp(algorithm, "Bareiss") != 0) && (strcmp(algorithm, "Laplace") != 0) && (strcmp(algorithm, "Cache") != 0)) { WerrorS("Expected as algorithm one of 'B/bareiss', 'L/laplace', or 'C/cache'."); return TRUE; } if ((!noAlgorithm) && (strcmp(algorithm, "Bareiss") == 0) && (!currRingIsOverIntegralDomain())) { Werror("Bareiss algorithm not defined over coefficient rings %s", "with zero divisors."); return TRUE; } res->rtyp=IDEAL_CMD; if ((mk < 1) || (mk > m->rows()) || (mk > m->cols())) { ideal I=idInit(1,1); if (mk<1) I->m[0]=p_One(currRing); //Werror("invalid size of minors: %d (matrix is (%d x %d))", mk, // m->rows(), m->cols()); res->data=(void*)I; return FALSE; } if ((!noAlgorithm) && (strcmp(algorithm, "Cache") == 0) && (noCacheMinors || noCacheMonomials)) { cacheMinors = 200; cacheMonomials = 100000; } /* here come the actual procedure calls */ if (noAlgorithm) res->data = getMinorIdealHeuristic(m, mk, (noK ? 0 : k), (noIdeal ? 0 : IasSB), false); else if (strcmp(algorithm, "Cache") == 0) res->data = getMinorIdealCache(m, mk, (noK ? 0 : k), (noIdeal ? 0 : IasSB), 3, cacheMinors, cacheMonomials, false); else res->data = getMinorIdeal(m, mk, (noK ? 0 : k), algorithm, (noIdeal ? 0 : IasSB), false); if (v_typ!=MATRIX_CMD) idDelete((ideal *)&m); return FALSE; } static BOOLEAN jjNEWSTRUCT3(leftv, leftv u, leftv v, leftv w) { // u: the name of the new type // v: the parent type // w: the elements newstruct_desc d=newstructChildFromString((const char *)v->Data(), (const char *)w->Data()); if (d!=NULL) newstruct_setup((const char *)u->Data(),d); return (d==NULL); } static BOOLEAN jjPREIMAGE(leftv res, leftv u, leftv v, leftv w) { // handles preimage(r,phi,i) and kernel(r,phi) idhdl h; ring rr; map mapping; BOOLEAN kernel_cmd= (iiOp==KERNEL_CMD); if ((v->name==NULL) || (!kernel_cmd && (w->name==NULL))) { WerrorS("2nd/3rd arguments must have names"); return TRUE; } rr=(ring)u->Data(); const char *ring_name=u->Name(); if ((h=rr->idroot->get(v->name,myynest))!=NULL) { if (h->typ==MAP_CMD) { mapping=IDMAP(h); idhdl preim_ring=IDROOT->get(mapping->preimage,myynest); if ((preim_ring==NULL) || (IDRING(preim_ring)!=currRing)) { Werror("preimage ring `%s` is not the basering",mapping->preimage); return TRUE; } } else if (h->typ==IDEAL_CMD) { mapping=IDMAP(h); } else { Werror("`%s` is no map nor ideal",IDID(h)); return TRUE; } } else { Werror("`%s` is not defined in `%s`",v->name,ring_name); return TRUE; } ideal image; if (kernel_cmd) image=idInit(1,1); else { if ((h=rr->idroot->get(w->name,myynest))!=NULL) { if (h->typ==IDEAL_CMD) { image=IDIDEAL(h); } else { Werror("`%s` is no ideal",IDID(h)); return TRUE; } } else { Werror("`%s` is not defined in `%s`",w->name,ring_name); return TRUE; } } if (((currRing->qideal!=NULL) && (rHasLocalOrMixedOrdering_currRing())) || ((rr->qideal!=NULL) && (rHasLocalOrMixedOrdering(rr)))) { WarnS("preimage in local qring may be wrong: use Ring::preimageLoc instead"); } res->data=(char *)maGetPreimage(rr,mapping,image,currRing); if (kernel_cmd) idDelete(&image); return (res->data==NULL/* is of type ideal, should not be NULL*/); } static BOOLEAN jjRANDOM_Im(leftv res, leftv u, leftv v, leftv w) { int di, k; int i=(int)(long)u->Data(); int r=(int)(long)v->Data(); int c=(int)(long)w->Data(); if ((r<=0) || (c<=0)) return TRUE; intvec *iv = new intvec(r, c, 0); if (iv->rows()==0) { delete iv; return TRUE; } if (i!=0) { if (i<0) i = -i; di = 2 * i + 1; for (k=0; klength(); k++) { (*iv)[k] = ((siRand() % di) - i); } } res->data = (char *)iv; return FALSE; } #ifdef SINGULAR_4_1 static BOOLEAN jjRANDOM_CF(leftv res, leftv u, leftv v, leftv w) // , par1, par2 -> number2 { coeffs cf=(coeffs)w->Data(); if ((cf==NULL) ||(cf->cfRandom==NULL)) { Werror("no random function defined for coeff %d",cf->type); return TRUE; } else { number n= n_Random(siRand,(number)v->Data(),(number)w->Data(),cf); number2 nn=(number2)omAlloc(sizeof(*nn)); nn->cf=cf; nn->n=n; res->data=nn; return FALSE; } return TRUE; } #endif static BOOLEAN jjSUBST_Test(leftv v,leftv w, int &ringvar, poly &monomexpr) { monomexpr=(poly)w->Data(); poly p=(poly)v->Data(); #if 0 if (pLength(monomexpr)>1) { Werror("`%s` substitutes a ringvar only by a term", Tok2Cmdname(SUBST_CMD)); return TRUE; } #endif if ((ringvar=pVar(p))==0) { if ((p!=NULL) && (currRing->cf->extRing!=NULL)) { number n = pGetCoeff(p); ringvar= -n_IsParam(n, currRing); } if(ringvar==0) { WerrorS("ringvar/par expected"); return TRUE; } } return FALSE; } static BOOLEAN jjSUBST_P(leftv res, leftv u, leftv v,leftv w) { int ringvar; poly monomexpr; BOOLEAN nok=jjSUBST_Test(v,w,ringvar,monomexpr); if (nok) return TRUE; poly p=(poly)u->Data(); if (ringvar>0) { if ((monomexpr!=NULL) && (p!=NULL) && (pTotaldegree(p)!=0) && ((unsigned long)pTotaldegree(monomexpr) > (currRing->bitmask / (unsigned long)pTotaldegree(p)/2))) { Warn("possible OVERFLOW in subst, max exponent is %ld, subtituting deg %d by deg %d",currRing->bitmask/2, pTotaldegree(monomexpr), pTotaldegree(p)); //return TRUE; } if ((monomexpr==NULL)||(pNext(monomexpr)==NULL)) res->data = pSubst((poly)u->CopyD(res->rtyp),ringvar,monomexpr); else res->data= pSubstPoly(p,ringvar,monomexpr); } else { res->data=pSubstPar(p,-ringvar,monomexpr); } return FALSE; } static BOOLEAN jjSUBST_Id(leftv res, leftv u, leftv v,leftv w) { int ringvar; poly monomexpr; BOOLEAN nok=jjSUBST_Test(v,w,ringvar,monomexpr); if (nok) return TRUE; ideal id=(ideal)u->Data(); if (ringvar>0) { BOOLEAN overflow=FALSE; if (monomexpr!=NULL) { long deg_monexp=pTotaldegree(monomexpr); for(int i=IDELEMS(id)-1;i>=0;i--) { poly p=id->m[i]; if ((p!=NULL) && (pTotaldegree(p)!=0) && ((unsigned long)deg_monexp > (currRing->bitmask / (unsigned long)pTotaldegree(p)/2))) { overflow=TRUE; break; } } } if (overflow) Warn("possible OVERFLOW in subst, max exponent is %ld",currRing->bitmask/2); if ((monomexpr==NULL)||(pNext(monomexpr)==NULL)) { if (res->rtyp==MATRIX_CMD) id=(ideal)mp_Copy((matrix)id,currRing); else id=id_Copy(id,currRing); res->data = id_Subst(id, ringvar, monomexpr, currRing); } else res->data = idSubstPoly(id,ringvar,monomexpr); } else { res->data = idSubstPar(id,-ringvar,monomexpr); } return FALSE; } // we do not want to have jjSUBST_Id_X inlined: static BOOLEAN jjSUBST_Id_X(leftv res, leftv u, leftv v,leftv w, int input_type); static BOOLEAN jjSUBST_Id_I(leftv res, leftv u, leftv v,leftv w) { return jjSUBST_Id_X(res,u,v,w,INT_CMD); } static BOOLEAN jjSUBST_Id_N(leftv res, leftv u, leftv v,leftv w) { return jjSUBST_Id_X(res,u,v,w,NUMBER_CMD); } static BOOLEAN jjSUBST_Id_X(leftv res, leftv u, leftv v,leftv w, int input_type) { sleftv tmp; memset(&tmp,0,sizeof(tmp)); // do not check the result, conversion from int/number to poly works always iiConvert(input_type,POLY_CMD,iiTestConvert(input_type,POLY_CMD),w,&tmp); BOOLEAN b=jjSUBST_Id(res,u,v,&tmp); tmp.CleanUp(); return b; } static BOOLEAN jjMATRIX_Id(leftv res, leftv u, leftv v,leftv w) { int mi=(int)(long)v->Data(); int ni=(int)(long)w->Data(); if ((mi<1)||(ni<1)) { Werror("converting ideal to matrix: dimensions must be positive(%dx%d)",mi,ni); return TRUE; } matrix m=mpNew(mi,ni); ideal I=(ideal)u->CopyD(IDEAL_CMD); int i=si_min(IDELEMS(I),mi*ni); //for(i=i-1;i>=0;i--) //{ // m->m[i]=I->m[i]; // I->m[i]=NULL; //} memcpy(m->m,I->m,i*sizeof(poly)); memset(I->m,0,i*sizeof(poly)); id_Delete(&I,currRing); res->data = (char *)m; return FALSE; } static BOOLEAN jjMATRIX_Mo(leftv res, leftv u, leftv v,leftv w) { int mi=(int)(long)v->Data(); int ni=(int)(long)w->Data(); if ((mi<1)||(ni<1)) { Werror("converting module to matrix: dimensions must be positive(%dx%d)",mi,ni); return TRUE; } res->data = (char *)id_Module2formatedMatrix((ideal)u->CopyD(MODUL_CMD), mi,ni,currRing); return FALSE; } static BOOLEAN jjMATRIX_Ma(leftv res, leftv u, leftv v,leftv w) { int mi=(int)(long)v->Data(); int ni=(int)(long)w->Data(); if ((mi<1)||(ni<1)) { Werror("converting matrix to matrix: dimensions must be positive(%dx%d)",mi,ni); return TRUE; } matrix m=mpNew(mi,ni); matrix I=(matrix)u->CopyD(MATRIX_CMD); int r=si_min(MATROWS(I),mi); int c=si_min(MATCOLS(I),ni); int i,j; for(i=r;i>0;i--) { for(j=c;j>0;j--) { MATELEM(m,i,j)=MATELEM(I,i,j); MATELEM(I,i,j)=NULL; } } id_Delete((ideal *)&I,currRing); res->data = (char *)m; return FALSE; } static BOOLEAN jjLIFT3(leftv res, leftv u, leftv v, leftv w) { if (w->rtyp!=IDHDL) return TRUE; int ul= IDELEMS((ideal)u->Data()); int vl= IDELEMS((ideal)v->Data()); ideal m = idLift((ideal)u->Data(),(ideal)v->Data(),NULL,FALSE,hasFlag(u,FLAG_STD), FALSE, (matrix *)(&(IDMATRIX((idhdl)(w->data))))); if (m==NULL) return TRUE; res->data = (char *)id_Module2formatedMatrix(m,ul,vl,currRing); return FALSE; } static BOOLEAN jjLIFTSTD3(leftv res, leftv u, leftv v, leftv w) { if ((v->rtyp!=IDHDL)||(v->e!=NULL)) return TRUE; if ((w->rtyp!=IDHDL)||(w->e!=NULL)) return TRUE; idhdl hv=(idhdl)v->data; idhdl hw=(idhdl)w->data; // CopyD for IDEAL_CMD and MODUL_CMD are identical: res->data = (char *)idLiftStd((ideal)u->Data(), &(hv->data.umatrix),testHomog, &(hw->data.uideal)); setFlag(res,FLAG_STD); v->flag=0; w->flag=0; return FALSE; } static BOOLEAN jjREDUCE3_CP(leftv res, leftv u, leftv v, leftv w) { assumeStdFlag(v); if (!idIsZeroDim((ideal)v->Data())) { Werror("`%s` must be 0-dimensional",v->Name()); return TRUE; } res->data = (char *)redNF((ideal)v->CopyD(),(poly)u->CopyD(), (poly)w->CopyD()); return FALSE; } static BOOLEAN jjREDUCE3_CID(leftv res, leftv u, leftv v, leftv w) { assumeStdFlag(v); if (!idIsZeroDim((ideal)v->Data())) { Werror("`%s` must be 0-dimensional",v->Name()); return TRUE; } res->data = (char *)redNF((ideal)v->CopyD(),(ideal)u->CopyD(), (matrix)w->CopyD()); return FALSE; } static BOOLEAN jjREDUCE3_P(leftv res, leftv u, leftv v, leftv w) { assumeStdFlag(v); res->data = (char *)kNF((ideal)v->Data(),currRing->qideal,(poly)u->Data(), 0,(int)(long)w->Data()); return FALSE; } static BOOLEAN jjREDUCE3_ID(leftv res, leftv u, leftv v, leftv w) { assumeStdFlag(v); res->data = (char *)kNF((ideal)v->Data(),currRing->qideal,(ideal)u->Data(), 0,(int)(long)w->Data()); return FALSE; } #ifdef OLD_RES static BOOLEAN jjRES3(leftv res, leftv u, leftv v, leftv w) { int maxl=(int)v->Data(); ideal u_id=(ideal)u->Data(); int l=0; resolvente r; intvec **weights=NULL; int wmaxl=maxl; maxl--; if ((maxl==-1) && (iiOp!=MRES_CMD)) maxl = currRing->N-1; if ((iiOp == RES_CMD) || (iiOp == MRES_CMD)) { intvec * iv=(intvec*)atGet(u,"isHomog",INTVEC_CMD); if (iv!=NULL) { l=1; if (!idTestHomModule(u_id,currRing->qideal,iv)) { WarnS("wrong weights"); iv=NULL; } else { weights = (intvec**)omAlloc0Bin(char_ptr_bin); weights[0] = ivCopy(iv); } } r=syResolvente(u_id,maxl,&l, &weights, iiOp==MRES_CMD); } else r=sySchreyerResolvente((ideal)u->Data(),maxl+1,&l); if (r==NULL) return TRUE; int t3=u->Typ(); iiMakeResolv(r,l,wmaxl,w->name,t3,weights); return FALSE; } #endif static BOOLEAN jjRING3(leftv res, leftv u, leftv v, leftv w) { res->data=(void *)rInit(u,v,w); return (res->data==NULL); } static BOOLEAN jjSTATUS3(leftv res, leftv u, leftv v, leftv w) { int yes; jjSTATUS2(res, u, v); yes = (strcmp((char *) res->data, (char *) w->Data()) == 0); omFree((ADDRESS) res->data); res->data = (void *)(long)yes; return FALSE; } static BOOLEAN jjSTD_HILB_W(leftv res, leftv u, leftv v, leftv w) { intvec *vw=(intvec *)w->Data(); // weights of vars if (vw->length()!=currRing->N) { Werror("%d weights for %d variables",vw->length(),currRing->N); return TRUE; } ideal result; intvec *ww=(intvec *)atGet(u,"isHomog",INTVEC_CMD); tHomog hom=testHomog; ideal u_id=(ideal)(u->Data()); if (ww!=NULL) { if (!idTestHomModule(u_id,currRing->qideal,ww)) { WarnS("wrong weights"); ww=NULL; } else { ww=ivCopy(ww); hom=isHomog; } } result=kStd(u_id, currRing->qideal, hom, &ww, // module weights (intvec *)v->Data(), // hilbert series 0,0, // syzComp, newIdeal vw); // weights of vars idSkipZeroes(result); res->data = (char *)result; setFlag(res,FLAG_STD); if (ww!=NULL) atSet(res,omStrDup("isHomog"),ww,INTVEC_CMD); return FALSE; } /*=================== operations with many arg.: static proc =================*/ /* must be ordered: first operations for chars (infix ops), * then alphabetically */ static BOOLEAN jjBREAK0(leftv, leftv) { #ifdef HAVE_SDB sdb_show_bp(); #endif return FALSE; } static BOOLEAN jjBREAK1(leftv, leftv v) { #ifdef HAVE_SDB if(v->Typ()==PROC_CMD) { int lineno=0; if((v->next!=NULL) && (v->next->Typ()==INT_CMD)) { lineno=(int)(long)v->next->Data(); } return sdb_set_breakpoint(v->Name(),lineno); } return TRUE; #else return FALSE; #endif } static BOOLEAN jjCALL1ARG(leftv res, leftv v) { return iiExprArith1(res,v,iiOp); } static BOOLEAN jjCALL2ARG(leftv res, leftv u) { leftv v=u->next; u->next=NULL; BOOLEAN b=iiExprArith2(res,u,iiOp,v, (iiOp > 255)); u->next=v; return b; } static BOOLEAN jjCALL3ARG(leftv res, leftv u) { leftv v = u->next; leftv w = v->next; u->next = NULL; v->next = NULL; BOOLEAN b = iiExprArith3(res, iiOp, u, v, w); u->next = v; v->next = w; return b; } static BOOLEAN jjCOEF_M(leftv, leftv v) { short t[]={5,VECTOR_CMD,POLY_CMD,MATRIX_CMD,MATRIX_CMD,IDHDL}; if (iiCheckTypes(v,t)) return TRUE; idhdl c=(idhdl)v->next->next->data; if (v->next->next->next->rtyp!=IDHDL) return TRUE; idhdl m=(idhdl)v->next->next->next->data; idDelete((ideal *)&(c->data.uideal)); idDelete((ideal *)&(m->data.uideal)); mp_Coef2((poly)v->Data(),(poly)v->next->Data(), (matrix *)&(c->data.umatrix),(matrix *)&(m->data.umatrix),currRing); return FALSE; } static BOOLEAN jjDIVISION4(leftv res, leftv v) { // may have 3 or 4 arguments leftv v1=v; leftv v2=v1->next; leftv v3=v2->next; leftv v4=v3->next; assumeStdFlag(v2); int i1=iiTestConvert(v1->Typ(),MODUL_CMD); int i2=iiTestConvert(v2->Typ(),MODUL_CMD); if((i1==0)||(i2==0) ||(v3->Typ()!=INT_CMD)||((v4!=NULL)&&(v4->Typ()!=INTVEC_CMD))) { WarnS(",,[,] expected!"); return TRUE; } sleftv w1,w2; iiConvert(v1->Typ(),MODUL_CMD,i1,v1,&w1); iiConvert(v2->Typ(),MODUL_CMD,i2,v2,&w2); ideal P=(ideal)w1.Data(); ideal Q=(ideal)w2.Data(); int n=(int)(long)v3->Data(); short *w=NULL; if(v4!=NULL) { w = iv2array((intvec *)v4->Data(),currRing); short * w0 = w + 1; int i = currRing->N; while( (i > 0) && ((*w0) > 0) ) { w0++; i--; } if(i>0) WarnS("not all weights are positive!"); } matrix T; ideal R; idLiftW(P,Q,n,T,R,w); w1.CleanUp(); w2.CleanUp(); if(w!=NULL) omFreeSize( (ADDRESS)w, (rVar(currRing)+1)*sizeof(short) ); lists L=(lists) omAllocBin(slists_bin); L->Init(2); L->m[1].rtyp=v1->Typ(); if(v1->Typ()==POLY_CMD||v1->Typ()==VECTOR_CMD) { if(v1->Typ()==POLY_CMD) p_Shift(&R->m[0],-1,currRing); L->m[1].data=(void *)R->m[0]; R->m[0]=NULL; idDelete(&R); } else if(v1->Typ()==IDEAL_CMD||v1->Typ()==MATRIX_CMD) L->m[1].data=(void *)id_Module2Matrix(R,currRing); else { L->m[1].rtyp=MODUL_CMD; L->m[1].data=(void *)R; } L->m[0].rtyp=MATRIX_CMD; L->m[0].data=(char *)T; res->data=L; res->rtyp=LIST_CMD; return FALSE; } //BOOLEAN jjDISPATCH(leftv res, leftv v) //{ // WerrorS("`dispatch`: not implemented"); // return TRUE; //} //static BOOLEAN jjEXPORTTO_M(leftv res, leftv u) //{ // int l=u->listLength(); // if (l<2) return TRUE; // BOOLEAN b; // leftv v=u->next; // leftv zz=v; // leftv z=zz; // u->next=NULL; // do // { // leftv z=z->next; // b=iiExprArith2(res,u,iiOp,z, (iiOp > 255)); // if (b) break; // } while (z!=NULL); // u->next=zz; // return b; //} static BOOLEAN jjIDEAL_PL(leftv res, leftv v) { int s=1; leftv h=v; if (h!=NULL) s=exprlist_length(h); ideal id=idInit(s,1); int rank=1; int i=0; poly p; while (h!=NULL) { switch(h->Typ()) { case POLY_CMD: { p=(poly)h->CopyD(POLY_CMD); break; } case INT_CMD: { number n=nInit((int)(long)h->Data()); if (!nIsZero(n)) { p=pNSet(n); } else { p=NULL; nDelete(&n); } break; } case BIGINT_CMD: { number b=(number)h->Data(); nMapFunc nMap=n_SetMap(coeffs_BIGINT,currRing->cf); if (nMap==NULL) return TRUE; number n=nMap(b,coeffs_BIGINT,currRing->cf); if (!nIsZero(n)) { p=pNSet(n); } else { p=NULL; nDelete(&n); } break; } case NUMBER_CMD: { number n=(number)h->CopyD(NUMBER_CMD); if (!nIsZero(n)) { p=pNSet(n); } else { p=NULL; nDelete(&n); } break; } case VECTOR_CMD: { p=(poly)h->CopyD(VECTOR_CMD); if (iiOp!=MODUL_CMD) { idDelete(&id); pDelete(&p); return TRUE; } rank=si_max(rank,(int)pMaxComp(p)); break; } default: { idDelete(&id); return TRUE; } } if ((iiOp==MODUL_CMD)&&(p!=NULL)&&(pGetComp(p)==0)) { pSetCompP(p,1); } id->m[i]=p; i++; h=h->next; } id->rank=rank; res->data=(char *)id; return FALSE; } static BOOLEAN jjFETCH_M(leftv res, leftv u) { ring r=(ring)u->Data(); leftv v=u->next; leftv perm_var_l=v->next; leftv perm_par_l=v->next->next; if ((perm_var_l->Typ()!=INTVEC_CMD) ||((perm_par_l!=NULL)&&(perm_par_l->Typ()!=INTVEC_CMD)) ||((u->Typ()!=RING_CMD)&&(u->Typ()!=QRING_CMD))) { WerrorS("fetch(,[,[,])"); return TRUE; } intvec *perm_var_v=(intvec*)perm_var_l->Data(); intvec *perm_par_v=NULL; if (perm_par_l!=NULL) perm_par_v=(intvec*)perm_par_l->Data(); idhdl w; nMapFunc nMap; if ((w=r->idroot->get(v->Name(),myynest))!=NULL) { int *perm=NULL; int *par_perm=NULL; int par_perm_size=0; BOOLEAN bo; if ((nMap=n_SetMap(r->cf,currRing->cf))==NULL) { // Allow imap/fetch to be make an exception only for: if ( (rField_is_Q_a(r) && // Q(a..) -> Q(a..) || Q || Zp || Zp(a) (rField_is_Q(currRing) || rField_is_Q_a(currRing) || (rField_is_Zp(currRing) || rField_is_Zp_a(currRing)))) || (rField_is_Zp_a(r) && // Zp(a..) -> Zp(a..) || Zp (rField_is_Zp(currRing, r->cf->ch) || rField_is_Zp_a(currRing, r->cf->ch))) ) { par_perm_size=rPar(r); } else { goto err_fetch; } } else par_perm_size=rPar(r); perm=(int *)omAlloc0((rVar(r)+1)*sizeof(int)); if (par_perm_size!=0) par_perm=(int *)omAlloc0(par_perm_size*sizeof(int)); int i; if (perm_par_l==NULL) { if (par_perm_size!=0) for(i=si_min(rPar(r),rPar(currRing))-1;i>=0;i--) par_perm[i]=-(i+1); } else { if (par_perm_size==0) WarnS("source ring has no parameters"); else { for(i=rPar(r)-1;i>=0;i--) { if (ilength()) par_perm[i]=(*perm_par_v)[i]; if ((par_perm[i]<-rPar(currRing)) || (par_perm[i]>rVar(currRing))) { Warn("invalid entry for par %d: %d\n",i,par_perm[i]); par_perm[i]=0; } } } } for(i=rVar(r)-1;i>=0;i--) { if (ilength()) perm[i+1]=(*perm_var_v)[i]; if ((perm[i]<-rPar(currRing)) || (perm[i]>rVar(currRing))) { Warn("invalid entry for var %d: %d\n",i,perm[i]); perm[i]=0; } } if (BVERBOSE(V_IMAP)) { for(i=1;i<=si_min(rVar(r),rVar(currRing));i++) { if (perm[i]>0) Print("// var nr %d: %s -> var %s\n",i,r->names[i-1],currRing->names[perm[i]-1]); else if (perm[i]<0) Print("// var nr %d: %s -> par %s\n",i,r->names[i-1],rParameter(currRing)[-perm[i]-1]); } for(i=1;i<=si_min(rPar(r),rPar(currRing));i++) // possibly empty loop { if (par_perm[i-1]<0) Print("// par nr %d: %s -> par %s\n", i,rParameter(r)[i-1],rParameter(currRing)[-par_perm[i-1]-1]); else if (par_perm[i-1]>0) Print("// par nr %d: %s -> var %s\n", i,rParameter(r)[i-1],currRing->names[par_perm[i-1]-1]); } } if (IDTYP(w)==ALIAS_CMD) w=(idhdl)IDDATA(w); sleftv tmpW; memset(&tmpW,0,sizeof(sleftv)); tmpW.rtyp=IDTYP(w); tmpW.data=IDDATA(w); if ((bo=maApplyFetch(IMAP_CMD,NULL,res,&tmpW, r, perm,par_perm,par_perm_size,nMap))) { Werror("cannot map %s of type %s(%d)",v->name, Tok2Cmdname(w->typ),w->typ); } if (perm!=NULL) omFreeSize((ADDRESS)perm,(rVar(r)+1)*sizeof(int)); if (par_perm!=NULL) omFreeSize((ADDRESS)par_perm,par_perm_size*sizeof(int)); return bo; } else { Werror("identifier %s not found in %s",v->Fullname(),u->Fullname()); } return TRUE; err_fetch: Werror("no identity map from %s (%s -> %s)",u->Fullname(), nCoeffString(r->cf), nCoeffString(currRing->cf)); return TRUE; } static BOOLEAN jjINTERSECT_PL(leftv res, leftv v) { leftv h=v; int l=v->listLength(); resolvente r=(resolvente)omAlloc0(l*sizeof(ideal)); BOOLEAN *copied=(BOOLEAN *)omAlloc0(l*sizeof(BOOLEAN)); int t=0; // try to convert to IDEAL_CMD while (h!=NULL) { if (iiTestConvert(h->Typ(),IDEAL_CMD)!=0) { t=IDEAL_CMD; } else break; h=h->next; } // if failure, try MODUL_CMD if (t==0) { h=v; while (h!=NULL) { if (iiTestConvert(h->Typ(),MODUL_CMD)!=0) { t=MODUL_CMD; } else break; h=h->next; } } // check for success in converting if (t==0) { WerrorS("cannot convert to ideal or module"); return TRUE; } // call idMultSect h=v; int i=0; sleftv tmp; while (h!=NULL) { if (h->Typ()==t) { r[i]=(ideal)h->Data(); /*no copy*/ h=h->next; } else if(iiConvert(h->Typ(),t,iiTestConvert(h->Typ(),t),h,&tmp)) { omFreeSize((ADDRESS)copied,l*sizeof(BOOLEAN)); omFreeSize((ADDRESS)r,l*sizeof(ideal)); Werror("cannot convert arg. %d to %s",i+1,Tok2Cmdname(t)); return TRUE; } else { r[i]=(ideal)tmp.Data(); /*now it's a copy*/ copied[i]=TRUE; h=tmp.next; } i++; } res->rtyp=t; res->data=(char *)idMultSect(r,i); while(i>0) { i--; if (copied[i]) idDelete(&(r[i])); } omFreeSize((ADDRESS)copied,l*sizeof(BOOLEAN)); omFreeSize((ADDRESS)r,l*sizeof(ideal)); return FALSE; } static BOOLEAN jjLU_INVERSE(leftv res, leftv v) { /* computation of the inverse of a quadratic matrix A using the L-U-decomposition of A; There are two valid parametrisations: 1) exactly one argument which is just the matrix A, 2) exactly three arguments P, L, U which already realise the L-U-decomposition of A, that is, P * A = L * U, and P, L, and U satisfy the properties decribed in method 'jjLU_DECOMP'; see there; If A is invertible, the list [1, A^(-1)] is returned, otherwise the list [0] is returned. Thus, the user may inspect the first entry of the returned list to see whether A is invertible. */ matrix iMat; int invertible; short t1[]={1,MATRIX_CMD}; short t2[]={3,MATRIX_CMD,MATRIX_CMD,MATRIX_CMD}; if (iiCheckTypes(v,t1)) { matrix aMat = (matrix)v->Data(); int rr = aMat->rows(); int cc = aMat->cols(); if (rr != cc) { Werror("given matrix (%d x %d) is not quadratic, hence not invertible", rr, cc); return TRUE; } if (!idIsConstant((ideal)aMat)) { WerrorS("matrix must be constant"); return TRUE; } invertible = luInverse(aMat, iMat); } else if (iiCheckTypes(v,t2)) { matrix pMat = (matrix)v->Data(); matrix lMat = (matrix)v->next->Data(); matrix uMat = (matrix)v->next->next->Data(); int rr = uMat->rows(); int cc = uMat->cols(); if (rr != cc) { Werror("third matrix (%d x %d) is not quadratic, hence not invertible", rr, cc); return TRUE; } if (!idIsConstant((ideal)pMat) || (!idIsConstant((ideal)lMat)) || (!idIsConstant((ideal)uMat)) ) { WerrorS("matricesx must be constant"); return TRUE; } invertible = luInverseFromLUDecomp(pMat, lMat, uMat, iMat); } else { Werror("expected either one or three matrices"); return TRUE; } /* build the return structure; a list with either one or two entries */ lists ll = (lists)omAllocBin(slists_bin); if (invertible) { ll->Init(2); ll->m[0].rtyp=INT_CMD; ll->m[0].data=(void *)(long)invertible; ll->m[1].rtyp=MATRIX_CMD; ll->m[1].data=(void *)iMat; } else { ll->Init(1); ll->m[0].rtyp=INT_CMD; ll->m[0].data=(void *)(long)invertible; } res->data=(char*)ll; return FALSE; } static BOOLEAN jjLU_SOLVE(leftv res, leftv v) { /* for solving a linear equation system A * x = b, via the given LU-decomposition of the matrix A; There is one valid parametrisation: 1) exactly four arguments P, L, U, b; P, L, and U realise the L-U-decomposition of A, that is, P * A = L * U, and P, L, and U satisfy the properties decribed in method 'jjLU_DECOMP'; see there; b is the right-hand side vector of the equation system; The method will return a list of either 1 entry or three entries: 1) [0] if there is no solution to the system; 2) [1, x, H] if there is at least one solution; x is any solution of the given linear system, H is the matrix with column vectors spanning the homogeneous solution space. The method produces an error if matrix and vector sizes do not fit. */ short t[]={4,MATRIX_CMD,MATRIX_CMD,MATRIX_CMD,MATRIX_CMD}; if (!iiCheckTypes(v,t)) { WerrorS("expected exactly three matrices and one vector as input"); return TRUE; } matrix pMat = (matrix)v->Data(); matrix lMat = (matrix)v->next->Data(); matrix uMat = (matrix)v->next->next->Data(); matrix bVec = (matrix)v->next->next->next->Data(); matrix xVec; int solvable; matrix homogSolSpace; if (pMat->rows() != pMat->cols()) { Werror("first matrix (%d x %d) is not quadratic", pMat->rows(), pMat->cols()); return TRUE; } if (lMat->rows() != lMat->cols()) { Werror("second matrix (%d x %d) is not quadratic", lMat->rows(), lMat->cols()); return TRUE; } if (lMat->rows() != uMat->rows()) { Werror("second matrix (%d x %d) and third matrix (%d x %d) do not fit", lMat->rows(), lMat->cols(), uMat->rows(), uMat->cols()); return TRUE; } if (uMat->rows() != bVec->rows()) { Werror("third matrix (%d x %d) and vector (%d x 1) do not fit", uMat->rows(), uMat->cols(), bVec->rows()); return TRUE; } if (!idIsConstant((ideal)pMat) ||(!idIsConstant((ideal)lMat)) ||(!idIsConstant((ideal)uMat)) ) { WerrorS("matrices must be constant"); return TRUE; } solvable = luSolveViaLUDecomp(pMat, lMat, uMat, bVec, xVec, homogSolSpace); /* build the return structure; a list with either one or three entries */ lists ll = (lists)omAllocBin(slists_bin); if (solvable) { ll->Init(3); ll->m[0].rtyp=INT_CMD; ll->m[0].data=(void *)(long)solvable; ll->m[1].rtyp=MATRIX_CMD; ll->m[1].data=(void *)xVec; ll->m[2].rtyp=MATRIX_CMD; ll->m[2].data=(void *)homogSolSpace; } else { ll->Init(1); ll->m[0].rtyp=INT_CMD; ll->m[0].data=(void *)(long)solvable; } res->data=(char*)ll; return FALSE; } static BOOLEAN jjINTVEC_PL(leftv res, leftv v) { int i=0; leftv h=v; if (h!=NULL) i=exprlist_length(h); intvec *iv=new intvec(i); i=0; while (h!=NULL) { if(h->Typ()==INT_CMD) { (*iv)[i]=(int)(long)h->Data(); } else if (h->Typ()==INTVEC_CMD) { intvec *ivv=(intvec*)h->Data(); for(int j=0;jlength();j++,i++) { (*iv)[i]=(*ivv)[j]; } i--; } else { delete iv; return TRUE; } i++; h=h->next; } res->data=(char *)iv; return FALSE; } static BOOLEAN jjJET4(leftv res, leftv u) { short t1[]={4,POLY_CMD,POLY_CMD,POLY_CMD,INTVEC_CMD}; short t2[]={4,VECTOR_CMD,POLY_CMD,POLY_CMD,INTVEC_CMD}; short t3[]={4,IDEAL_CMD,MATRIX_CMD,INT_CMD,INTVEC_CMD}; short t4[]={4,MODUL_CMD,MATRIX_CMD,INT_CMD,INTVEC_CMD}; leftv u1=u; leftv u2=u1->next; leftv u3=u2->next; leftv u4=u3->next; if (iiCheckTypes(u,t1)||iiCheckTypes(u,t2)) { if(!pIsUnit((poly)u2->Data())) { WerrorS("2nd argument must be a unit"); return TRUE; } res->rtyp=u1->Typ(); res->data=(char*)pSeries((int)(long)u3->Data(),pCopy((poly)u1->Data()), pCopy((poly)u2->Data()),(intvec*)u4->Data()); return FALSE; } else if (iiCheckTypes(u,t3)||iiCheckTypes(u,t4)) { if(!mp_IsDiagUnit((matrix)u2->Data(), currRing)) { WerrorS("2nd argument must be a diagonal matrix of units"); return TRUE; } res->rtyp=u1->Typ(); res->data=(char*)idSeries( (int)(long)u3->Data(), idCopy((ideal)u1->Data()), mp_Copy((matrix)u2->Data(), currRing), (intvec*)u4->Data() ); return FALSE; } else { Werror("%s(`poly`,`poly`,`int`,`intvec`) exppected", Tok2Cmdname(iiOp)); return TRUE; } } static BOOLEAN jjKLAMMER_PL(leftv res, leftv u) { if ((yyInRingConstruction) && ((strcmp(u->Name(),"real")==0) || (strcmp(u->Name(),"complex")==0))) { memcpy(res,u,sizeof(sleftv)); memset(u,0,sizeof(sleftv)); return FALSE; } leftv v=u->next; BOOLEAN b; if(v==NULL) b=iiExprArith1(res,u,iiOp); else { u->next=NULL; b=iiExprArith2(res,u,iiOp,v); u->next=v; } return b; } BOOLEAN jjLIST_PL(leftv res, leftv v) { int sl=0; if (v!=NULL) sl = v->listLength(); lists L; if((sl==1)&&(v->Typ()==RESOLUTION_CMD)) { int add_row_shift = 0; intvec *weights=(intvec*)atGet(v,"isHomog",INTVEC_CMD); if (weights!=NULL) add_row_shift=weights->min_in(); L=syConvRes((syStrategy)v->Data(),FALSE,add_row_shift); } else { L=(lists)omAllocBin(slists_bin); leftv h=NULL; int i; int rt; L->Init(sl); for (i=0;inext=v; } h=v; v=v->next; h->next=NULL; rt=h->Typ(); if (rt==0) { L->Clean(); Werror("`%s` is undefined",h->Fullname()); return TRUE; } if ((rt==RING_CMD)||(rt==QRING_CMD)) { L->m[i].rtyp=rt; L->m[i].data=h->Data(); ((ring)L->m[i].data)->ref++; } else L->m[i].Copy(h); } } res->data=(char *)L; return FALSE; } static BOOLEAN jjNAMES0(leftv res, leftv) { res->data=(void *)ipNameList(IDROOT); return FALSE; } static BOOLEAN jjOPTION_PL(leftv res, leftv v) { if(v==NULL) { res->data=(char *)showOption(); return FALSE; } res->rtyp=NONE; return setOption(res,v); } static BOOLEAN jjREDUCE4(leftv res, leftv u) { leftv u1=u; leftv u2=u1->next; leftv u3=u2->next; leftv u4=u3->next; if((u3->Typ()==INT_CMD)&&(u4->Typ()==INTVEC_CMD)) { int save_d=Kstd1_deg; Kstd1_deg=(int)(long)u3->Data(); kModW=(intvec *)u4->Data(); BITSET save2; SI_SAVE_OPT2(save2); si_opt_2|=Sy_bit(V_DEG_STOP); u2->next=NULL; BOOLEAN r=jjCALL2ARG(res,u); kModW=NULL; Kstd1_deg=save_d; SI_RESTORE_OPT2(save2); u->next->next=u3; return r; } else if((u1->Typ()==IDEAL_CMD)&&(u2->Typ()==MATRIX_CMD)&&(u3->Typ()==IDEAL_CMD)&& (u4->Typ()==INT_CMD)) { assumeStdFlag(u3); if(!mp_IsDiagUnit((matrix)u2->Data(), currRing)) { WerrorS("2nd argument must be a diagonal matrix of units"); return TRUE; } res->rtyp=IDEAL_CMD; res->data=(char*)redNF( idCopy((ideal)u3->Data()), idCopy((ideal)u1->Data()), mp_Copy((matrix)u2->Data(), currRing), (int)(long)u4->Data() ); return FALSE; } else if((u1->Typ()==POLY_CMD)&&(u2->Typ()==POLY_CMD)&&(u3->Typ()==IDEAL_CMD)&& (u4->Typ()==INT_CMD)) { assumeStdFlag(u3); if(!pIsUnit((poly)u2->Data())) { WerrorS("2nd argument must be a unit"); return TRUE; } res->rtyp=POLY_CMD; res->data=(char*)redNF(idCopy((ideal)u3->Data()),pCopy((poly)u1->Data()), pCopy((poly)u2->Data()),(int)(long)u4->Data()); return FALSE; } else { Werror("%s(`poly`,`ideal`,`int`,`intvec`) expected",Tok2Cmdname(iiOp)); return TRUE; } } static BOOLEAN jjREDUCE5(leftv res, leftv u) { leftv u1=u; leftv u2=u1->next; leftv u3=u2->next; leftv u4=u3->next; leftv u5=u4->next; if((u1->Typ()==IDEAL_CMD)&&(u2->Typ()==MATRIX_CMD)&&(u3->Typ()==IDEAL_CMD)&& (u4->Typ()==INT_CMD)&&(u5->Typ()==INTVEC_CMD)) { assumeStdFlag(u3); if(!mp_IsDiagUnit((matrix)u2->Data(), currRing)) { WerrorS("2nd argument must be a diagonal matrix of units"); return TRUE; } res->rtyp=IDEAL_CMD; res->data=(char*)redNF( idCopy((ideal)u3->Data()), idCopy((ideal)u1->Data()), mp_Copy((matrix)u2->Data(),currRing), (int)(long)u4->Data(), (intvec*)u5->Data() ); return FALSE; } else if((u1->Typ()==POLY_CMD)&&(u2->Typ()==POLY_CMD)&&(u3->Typ()==IDEAL_CMD)&& (u4->Typ()==INT_CMD)&&(u5->Typ()==INTVEC_CMD)) { assumeStdFlag(u3); if(!pIsUnit((poly)u2->Data())) { WerrorS("2nd argument must be a unit"); return TRUE; } res->rtyp=POLY_CMD; res->data=(char*)redNF(idCopy((ideal)u3->Data()),pCopy((poly)u1->Data()), pCopy((poly)u2->Data()), (int)(long)u4->Data(),(intvec*)u5->Data()); return FALSE; } else { Werror("%s(`ideal`,`ideal`,`matrix`,`int`,`intvec`) exppected", Tok2Cmdname(iiOp)); return TRUE; } } static BOOLEAN jjRESERVED0(leftv, leftv) { int i=1; int nCount = (sArithBase.nCmdUsed-1)/3; if((3*nCount)data = omStrDup(""); return FALSE; } int n = v->listLength(); if (n == 1) { res->data = v->String(); return FALSE; } char** slist = (char**) omAlloc(n*sizeof(char*)); int i, j; for (i=0, j=0; inext) { slist[i] = v->String(); assume(slist[i] != NULL); j+=strlen(slist[i]); } char* s = (char*) omAlloc((j+1)*sizeof(char)); *s='\0'; for (i=0;idata = s; return FALSE; } static BOOLEAN jjTEST(leftv, leftv v) { do { if (v->Typ()!=INT_CMD) return TRUE; test_cmd((int)(long)v->Data()); v=v->next; } while (v!=NULL); return FALSE; } #if defined(__alpha) && !defined(linux) extern "C" { void usleep(unsigned long usec); }; #endif static BOOLEAN jjFactModD_M(leftv res, leftv v) { /* compute two factors of h(x,y) modulo x^(d+1) in K[[x]][y], see a detailed documentation in /kernel/linear_algebra/linearAlgebra.h valid argument lists: - (poly h, int d), - (poly h, int d, poly f0, poly g0), optional: factors of h(0,y), - (poly h, int d, int xIndex, int yIndex), optional: indices of vars x & y in list of ring vars, - (poly h, int d, poly f0, poly g0, int xIndex, int yIndec), optional: all 4 optional args (The defaults are xIndex = 1, yIndex = 2, f0 and g0 polynomials as found by singclap_factorize and h(0, y) has exactly two distinct monic factors [possibly with exponent > 1].) result: - list with the two factors f and g such that h(x,y) = f(x,y)*g(x,y) mod x^(d+1) */ poly h = NULL; int d = 1; poly f0 = NULL; poly g0 = NULL; int xIndex = 1; /* default index if none provided */ int yIndex = 2; /* default index if none provided */ leftv u = v; int factorsGiven = 0; if ((u == NULL) || (u->Typ() != POLY_CMD)) { WerrorS("expected arguments (poly, int [, poly, poly] [, int, int])"); return TRUE; } else h = (poly)u->Data(); u = u->next; if ((u == NULL) || (u->Typ() != INT_CMD)) { WerrorS("expected arguments (poly, int [, poly, poly] [, int, int])"); return TRUE; } else d = (int)(long)u->Data(); u = u->next; if ((u != NULL) && (u->Typ() == POLY_CMD)) { if ((u->next == NULL) || (u->next->Typ() != POLY_CMD)) { WerrorS("expected arguments (poly, int [, poly, poly] [, int, int])"); return TRUE; } else { f0 = (poly)u->Data(); g0 = (poly)u->next->Data(); factorsGiven = 1; u = u->next->next; } } if ((u != NULL) && (u->Typ() == INT_CMD)) { if ((u->next == NULL) || (u->next->Typ() != INT_CMD)) { WerrorS("expected arguments (poly, int [, poly, poly] [, int, int])"); return TRUE; } else { xIndex = (int)(long)u->Data(); yIndex = (int)(long)u->next->Data(); u = u->next->next; } } if (u != NULL) { WerrorS("expected arguments (poly, int [, poly, poly] [, int, int])"); return TRUE; } /* checks for provided arguments */ if (pIsConstant(h) || (factorsGiven && (pIsConstant(f0) || pIsConstant(g0)))) { WerrorS("expected non-constant polynomial argument(s)"); return TRUE; } int n = rVar(currRing); if ((xIndex < 1) || (n < xIndex)) { Werror("index for variable x (%d) out of range [1..%d]", xIndex, n); return TRUE; } if ((yIndex < 1) || (n < yIndex)) { Werror("index for variable y (%d) out of range [1..%d]", yIndex, n); return TRUE; } if (xIndex == yIndex) { WerrorS("expected distinct indices for variables x and y"); return TRUE; } /* computation of f0 and g0 if missing */ if (factorsGiven == 0) { poly h0 = pSubst(pCopy(h), xIndex, NULL); intvec* v = NULL; ideal i = singclap_factorize(h0, &v, 0,currRing); ivTest(v); if (i == NULL) return TRUE; idTest(i); if ((v->rows() != 3) || ((*v)[0] =! 1) || (!nIsOne(pGetCoeff(i->m[0])))) { WerrorS("expected h(0,y) to have exactly two distinct monic factors"); return TRUE; } f0 = pPower(pCopy(i->m[1]), (*v)[1]); g0 = pPower(pCopy(i->m[2]), (*v)[2]); idDelete(&i); } poly f; poly g; henselFactors(xIndex, yIndex, h, f0, g0, d, f, g); lists L = (lists)omAllocBin(slists_bin); L->Init(2); L->m[0].rtyp = POLY_CMD; L->m[0].data=(void*)f; L->m[1].rtyp = POLY_CMD; L->m[1].data=(void*)g; res->rtyp = LIST_CMD; res->data = (char*)L; return FALSE; } static BOOLEAN jjSTATUS_M(leftv res, leftv v) { if ((v->Typ() != LINK_CMD) || (v->next->Typ() != STRING_CMD) || (v->next->next->Typ() != STRING_CMD) || (v->next->next->next->Typ() != INT_CMD)) return TRUE; jjSTATUS3(res, v, v->next, v->next->next); #if defined(HAVE_USLEEP) if (((long) res->data) == 0L) { int i_s = (int)(long) v->next->next->next->Data(); if (i_s > 0) { usleep((int)(long) v->next->next->next->Data()); jjSTATUS3(res, v, v->next, v->next->next); } } #elif defined(HAVE_SLEEP) if (((int) res->data) == 0) { int i_s = (int) v->next->next->next->Data(); if (i_s > 0) { si_sleep((is - 1)/1000000 + 1); jjSTATUS3(res, v, v->next, v->next->next); } } #endif return FALSE; } static BOOLEAN jjSUBST_M(leftv res, leftv u) { leftv v = u->next; // number of args > 0 if (v==NULL) return TRUE; leftv w = v->next; if (w==NULL) return TRUE; leftv rest = w->next;; u->next = NULL; v->next = NULL; w->next = NULL; BOOLEAN b = iiExprArith3(res, iiOp, u, v, w); if ((rest!=NULL) && (!b)) { sleftv tmp_res; leftv tmp_next=res->next; res->next=rest; memset(&tmp_res,0,sizeof(tmp_res)); b = iiExprArithM(&tmp_res,res,iiOp); memcpy(res,&tmp_res,sizeof(tmp_res)); res->next=tmp_next; } u->next = v; v->next = w; // rest was w->next, but is already cleaned return b; } static BOOLEAN jjQRDS(leftv res, leftv INPUT) { if ((INPUT->Typ() != MATRIX_CMD) || (INPUT->next->Typ() != NUMBER_CMD) || (INPUT->next->next->Typ() != NUMBER_CMD) || (INPUT->next->next->next->Typ() != NUMBER_CMD)) { WerrorS("expected (matrix, number, number, number) as arguments"); return TRUE; } leftv u = INPUT; leftv v = u->next; leftv w = v->next; leftv x = w->next; res->data = (char *)qrDoubleShift((matrix)(u->Data()), (number)(v->Data()), (number)(w->Data()), (number)(x->Data())); return FALSE; } static BOOLEAN jjSTD_HILB_WP(leftv res, leftv INPUT) { ideal result; leftv u = INPUT; /* an ideal, weighted homogeneous and standard */ leftv v = u->next; /* one additional polynomial or ideal */ leftv h = v->next; /* Hilbert vector */ leftv w = h->next; /* weight vector */ assumeStdFlag(u); ideal i1=(ideal)(u->Data()); ideal i0; if (((u->Typ()!=IDEAL_CMD)&&(u->Typ()!=MODUL_CMD)) || (h->Typ()!=INTVEC_CMD) || (w->Typ()!=INTVEC_CMD)) { WerrorS("expected `std(`ideal/module`,`poly/vector`,`intvec`,`intvec`)"); return TRUE; } intvec *vw=(intvec *)w->Data(); // weights of vars /* merging std_hilb_w and std_1 */ if (vw->length()!=currRing->N) { Werror("%d weights for %d variables",vw->length(),currRing->N); return TRUE; } int r=v->Typ(); BOOLEAN cleanup_i0=FALSE; if ((r==POLY_CMD) ||(r==VECTOR_CMD)) { i0=idInit(1,i1->rank); i0->m[0]=(poly)v->Data(); cleanup_i0=TRUE; } else if (r==IDEAL_CMD)/* IDEAL */ { i0=(ideal)v->Data(); } else { WerrorS("expected `std(`ideal/module`,`poly/vector`,`intvec`,`intvec`)"); return TRUE; } int ii0=idElem(i0); i1 = idSimpleAdd(i1,i0); if (cleanup_i0) { memset(i0->m,0,sizeof(poly)*IDELEMS(i0)); idDelete(&i0); } intvec *ww=(intvec *)atGet(u,"isHomog",INTVEC_CMD); tHomog hom=testHomog; /* u_id from jjSTD_W is now i1 as in jjSTD_1 */ if (ww!=NULL) { if (!idTestHomModule(i1,currRing->qideal,ww)) { WarnS("wrong weights"); ww=NULL; } else { ww=ivCopy(ww); hom=isHomog; } } BITSET save1; SI_SAVE_OPT1(save1); si_opt_1|=Sy_bit(OPT_SB_1); result=kStd(i1, currRing->qideal, hom, &ww, // module weights (intvec *)h->Data(), // hilbert series 0, // syzComp, whatever it is... IDELEMS(i1)-ii0, // new ideal vw); // weights of vars SI_RESTORE_OPT1(save1); idDelete(&i1); idSkipZeroes(result); res->data = (char *)result; if (!TEST_OPT_DEGBOUND) setFlag(res,FLAG_STD); if (ww!=NULL) atSet(res,omStrDup("isHomog"),ww,INTVEC_CMD); return FALSE; } static Subexpr jjMakeSub(leftv e) { assume( e->Typ()==INT_CMD ); Subexpr r=(Subexpr)omAlloc0Bin(sSubexpr_bin); r->start =(int)(long)e->Data(); return r; } #define D(A) (A) #define NULL_VAL NULL #define IPARITH #include "table.h" #include "iparith.inc" /*=================== operations with 2 args. ============================*/ /* must be ordered: first operations for chars (infix ops), * then alphabetically */ static BOOLEAN iiExprArith2TabIntern(leftv res, leftv a, int op, leftv b, BOOLEAN proccall, struct sValCmd2* dA2, int at, int bt, struct sConvertTypes *dConvertTypes) { memset(res,0,sizeof(sleftv)); BOOLEAN call_failed=FALSE; if (!errorreported) { int i=0; iiOp=op; while (dA2[i].cmd==op) { if ((at==dA2[i].arg1) && (bt==dA2[i].arg2)) { res->rtyp=dA2[i].res; if (currRing!=NULL) { if (check_valid(dA2[i].valid_for,op)) break; } else { if (RingDependend(dA2[i].res)) { WerrorS("no ring active"); break; } } if (traceit&TRACE_CALL) Print("call %s(%s,%s)\n",iiTwoOps(op),Tok2Cmdname(at),Tok2Cmdname(bt)); if ((call_failed=dA2[i].p(res,a,b))) { break;// leave loop, goto error handling } a->CleanUp(); b->CleanUp(); //Print("op: %d,result typ:%d\n",op,res->rtyp); return FALSE; } i++; } // implicite type conversion ---------------------------------------------- if (dA2[i].cmd!=op) { int ai,bi; leftv an = (leftv)omAlloc0Bin(sleftv_bin); leftv bn = (leftv)omAlloc0Bin(sleftv_bin); BOOLEAN failed=FALSE; i=0; /*iiTabIndex(dArithTab2,JJTAB2LEN,op);*/ //Print("op: %c, type: %s %s\n",op,Tok2Cmdname(at),Tok2Cmdname(bt)); while (dA2[i].cmd==op) { //Print("test %s %s\n",Tok2Cmdname(dA2[i].arg1),Tok2Cmdname(dA2[i].arg2)); if ((ai=iiTestConvert(at,dA2[i].arg1,dConvertTypes))!=0) { if ((bi=iiTestConvert(bt,dA2[i].arg2,dConvertTypes))!=0) { res->rtyp=dA2[i].res; if (currRing!=NULL) { if (check_valid(dA2[i].valid_for,op)) break; } else { if (RingDependend(dA2[i].res)) { WerrorS("no ring active"); break; } } if (traceit&TRACE_CALL) Print("call %s(%s,%s)\n",iiTwoOps(op), Tok2Cmdname(dA2[i].arg1),Tok2Cmdname(dA2[i].arg2)); failed= ((iiConvert(at,dA2[i].arg1,ai,a,an)) || (iiConvert(bt,dA2[i].arg2,bi,b,bn)) || (call_failed=dA2[i].p(res,an,bn))); // everything done, clean up temp. variables if (failed) { // leave loop, goto error handling break; } else { // everything ok, clean up and return an->CleanUp(); bn->CleanUp(); omFreeBin((ADDRESS)an, sleftv_bin); omFreeBin((ADDRESS)bn, sleftv_bin); a->CleanUp(); b->CleanUp(); return FALSE; } } } i++; } an->CleanUp(); bn->CleanUp(); omFreeBin((ADDRESS)an, sleftv_bin); omFreeBin((ADDRESS)bn, sleftv_bin); } // error handling --------------------------------------------------- const char *s=NULL; if (!errorreported) { if ((at==0) && (a->Fullname()!=sNoName)) { s=a->Fullname(); } else if ((bt==0) && (b->Fullname()!=sNoName)) { s=b->Fullname(); } if (s!=NULL) Werror("`%s` is not defined",s); else { i=0; /*iiTabIndex(dArithTab2,JJTAB2LEN,op);*/ s = iiTwoOps(op); if (proccall) { Werror("%s(`%s`,`%s`) failed" ,s,Tok2Cmdname(at),Tok2Cmdname(bt)); } else { Werror("`%s` %s `%s` failed" ,Tok2Cmdname(at),s,Tok2Cmdname(bt)); } if ((!call_failed) && BVERBOSE(V_SHOW_USE)) { while (dA2[i].cmd==op) { if(((at==dA2[i].arg1)||(bt==dA2[i].arg2)) && (dA2[i].res!=0) && (dA2[i].p!=jjWRONG2)) { if (proccall) Werror("expected %s(`%s`,`%s`)" ,s,Tok2Cmdname(dA2[i].arg1),Tok2Cmdname(dA2[i].arg2)); else Werror("expected `%s` %s `%s`" ,Tok2Cmdname(dA2[i].arg1),s,Tok2Cmdname(dA2[i].arg2)); } i++; } } } } res->rtyp = UNKNOWN; } a->CleanUp(); b->CleanUp(); return TRUE; } BOOLEAN iiExprArith2Tab(leftv res, leftv a, int op, struct sValCmd2* dA2, int at, struct sConvertTypes *dConvertTypes) { leftv b=a->next; a->next=NULL; int bt=b->Typ(); BOOLEAN bo=iiExprArith2TabIntern(res,a,op,b,TRUE,dA2,at,bt,dConvertTypes); a->next=b; a->CleanUp(); return bo; } BOOLEAN iiExprArith2(leftv res, leftv a, int op, leftv b, BOOLEAN proccall) { memset(res,0,sizeof(sleftv)); if (!errorreported) { #ifdef SIQ if (siq>0) { //Print("siq:%d\n",siq); command d=(command)omAlloc0Bin(sip_command_bin); memcpy(&d->arg1,a,sizeof(sleftv)); //a->Init(); memcpy(&d->arg2,b,sizeof(sleftv)); //b->Init(); d->argc=2; d->op=op; res->data=(char *)d; res->rtyp=COMMAND; return FALSE; } #endif int at=a->Typ(); int bt=b->Typ(); // handling bb-objects ---------------------------------------------------- if (at>MAX_TOK) { blackbox *bb=getBlackboxStuff(at); if (bb!=NULL) { if (!bb->blackbox_Op2(op,res,a,b)) return FALSE; if (errorreported) return TRUE; // else: no op defined } else return TRUE; } else if ((bt>MAX_TOK)&&(op!='(')) { blackbox *bb=getBlackboxStuff(bt); if (bb!=NULL) { if(!bb->blackbox_Op2(op,res,a,b)) return FALSE; if (errorreported) return TRUE; // else: no op defined } else return TRUE; } int i=iiTabIndex(dArithTab2,JJTAB2LEN,op); return iiExprArith2TabIntern(res,a,op,b,proccall,dArith2+i,at,bt,dConvertTypes); } a->CleanUp(); b->CleanUp(); return TRUE; } /*==================== operations with 1 arg. ===============================*/ /* must be ordered: first operations for chars (infix ops), * then alphabetically */ BOOLEAN iiExprArith1Tab(leftv res, leftv a, int op, struct sValCmd1* dA1, int at, struct sConvertTypes *dConvertTypes) { memset(res,0,sizeof(sleftv)); BOOLEAN call_failed=FALSE; if (!errorreported) { BOOLEAN failed=FALSE; iiOp=op; int i = 0; while (dA1[i].cmd==op) { if (at==dA1[i].arg) { if (currRing!=NULL) { if (check_valid(dA1[i].valid_for,op)) break; } else { if (RingDependend(dA1[i].res)) { WerrorS("no ring active"); break; } } if (traceit&TRACE_CALL) Print("call %s(%s)\n",iiTwoOps(op),Tok2Cmdname(at)); res->rtyp=dA1[i].res; if ((call_failed=dA1[i].p(res,a))) { break;// leave loop, goto error handling } if (a->Next()!=NULL) { res->next=(leftv)omAllocBin(sleftv_bin); failed=iiExprArith1(res->next,a->next,op); } a->CleanUp(); return failed; } i++; } // implicite type conversion -------------------------------------------- if (dA1[i].cmd!=op) { leftv an = (leftv)omAlloc0Bin(sleftv_bin); i=0; //Print("fuer %c , typ: %s\n",op,Tok2Cmdname(at)); while (dA1[i].cmd==op) { int ai; //Print("test %s\n",Tok2Cmdname(dA1[i].arg)); if ((ai=iiTestConvert(at,dA1[i].arg,dConvertTypes))!=0) { if (currRing!=NULL) { if (check_valid(dA1[i].valid_for,op)) break; } else { if (RingDependend(dA1[i].res)) { WerrorS("no ring active"); break; } } if (traceit&TRACE_CALL) Print("call %s(%s)\n",iiTwoOps(op),Tok2Cmdname(dA1[i].arg)); res->rtyp=dA1[i].res; failed= ((iiConvert(at,dA1[i].arg,ai,a,an,dConvertTypes)) || (call_failed=dA1[i].p(res,an))); // everything done, clean up temp. variables if (failed) { // leave loop, goto error handling break; } else { if (an->Next() != NULL) { res->next = (leftv)omAllocBin(sleftv_bin); failed=iiExprArith1(res->next,an->next,op); } // everything ok, clean up and return an->CleanUp(); omFreeBin((ADDRESS)an, sleftv_bin); a->CleanUp(); return failed; } } i++; } an->CleanUp(); omFreeBin((ADDRESS)an, sleftv_bin); } // error handling if (!errorreported) { if ((at==0) && (a->Fullname()!=sNoName)) { Werror("`%s` is not defined",a->Fullname()); } else { i=0; const char *s = iiTwoOps(op); Werror("%s(`%s`) failed" ,s,Tok2Cmdname(at)); if ((!call_failed) && BVERBOSE(V_SHOW_USE)) { while (dA1[i].cmd==op) { if ((dA1[i].res!=0) && (dA1[i].p!=jjWRONG)) Werror("expected %s(`%s`)" ,s,Tok2Cmdname(dA1[i].arg)); i++; } } } } res->rtyp = UNKNOWN; } a->CleanUp(); return TRUE; } BOOLEAN iiExprArith1(leftv res, leftv a, int op) { memset(res,0,sizeof(sleftv)); if (!errorreported) { #ifdef SIQ if (siq>0) { //Print("siq:%d\n",siq); command d=(command)omAlloc0Bin(sip_command_bin); memcpy(&d->arg1,a,sizeof(sleftv)); //a->Init(); d->op=op; d->argc=1; res->data=(char *)d; res->rtyp=COMMAND; return FALSE; } #endif int at=a->Typ(); // handling bb-objects ---------------------------------------------------- if(op>MAX_TOK) // explicit type conversion to bb { blackbox *bb=getBlackboxStuff(op); if (bb!=NULL) { res->rtyp=op; res->data=bb->blackbox_Init(bb); if(!bb->blackbox_Assign(res,a)) return FALSE; if (errorreported) return TRUE; } else return TRUE; } else if (at>MAX_TOK) // argument is of bb-type { blackbox *bb=getBlackboxStuff(at); if (bb!=NULL) { if(!bb->blackbox_Op1(op,res,a)) return FALSE; if (errorreported) return TRUE; // else: no op defined } else return TRUE; } iiOp=op; int i=iiTabIndex(dArithTab1,JJTAB1LEN,op); return iiExprArith1Tab(res,a,op, dArith1+i,at,dConvertTypes); } a->CleanUp(); return TRUE; } /*=================== operations with 3 args. ============================*/ /* must be ordered: first operations for chars (infix ops), * then alphabetically */ static BOOLEAN iiExprArith3TabIntern(leftv res, int op, leftv a, leftv b, leftv c, struct sValCmd3* dA3, int at, int bt, int ct, struct sConvertTypes *dConvertTypes) { memset(res,0,sizeof(sleftv)); BOOLEAN call_failed=FALSE; assume(dA3[0].cmd==op); if (!errorreported) { int i=0; iiOp=op; while (dA3[i].cmd==op) { if ((at==dA3[i].arg1) && (bt==dA3[i].arg2) && (ct==dA3[i].arg3)) { res->rtyp=dA3[i].res; if (currRing!=NULL) { if (check_valid(dA3[i].valid_for,op)) break; } if (traceit&TRACE_CALL) Print("call %s(%s,%s,%s)\n", iiTwoOps(op),Tok2Cmdname(at),Tok2Cmdname(bt),Tok2Cmdname(ct)); if ((call_failed=dA3[i].p(res,a,b,c))) { break;// leave loop, goto error handling } a->CleanUp(); b->CleanUp(); c->CleanUp(); return FALSE; } i++; } // implicite type conversion ---------------------------------------------- if (dA3[i].cmd!=op) { int ai,bi,ci; leftv an = (leftv)omAlloc0Bin(sleftv_bin); leftv bn = (leftv)omAlloc0Bin(sleftv_bin); leftv cn = (leftv)omAlloc0Bin(sleftv_bin); BOOLEAN failed=FALSE; i=0; //while ((dA3[i].cmd!=op)&&(dA3[i].cmd!=0)) i++; while (dA3[i].cmd==op) { if ((ai=iiTestConvert(at,dA3[i].arg1,dConvertTypes))!=0) { if ((bi=iiTestConvert(bt,dA3[i].arg2,dConvertTypes))!=0) { if ((ci=iiTestConvert(ct,dA3[i].arg3,dConvertTypes))!=0) { res->rtyp=dA3[i].res; if (currRing!=NULL) { if (check_valid(dA3[i].valid_for,op)) break; } if (traceit&TRACE_CALL) Print("call %s(%s,%s,%s)\n", iiTwoOps(op),Tok2Cmdname(dA3[i].arg1), Tok2Cmdname(dA3[i].arg2),Tok2Cmdname(dA3[i].arg3)); failed= ((iiConvert(at,dA3[i].arg1,ai,a,an,dConvertTypes)) || (iiConvert(bt,dA3[i].arg2,bi,b,bn,dConvertTypes)) || (iiConvert(ct,dA3[i].arg3,ci,c,cn,dConvertTypes)) || (call_failed=dA3[i].p(res,an,bn,cn))); // everything done, clean up temp. variables if (failed) { // leave loop, goto error handling break; } else { // everything ok, clean up and return an->CleanUp(); bn->CleanUp(); cn->CleanUp(); omFreeBin((ADDRESS)an, sleftv_bin); omFreeBin((ADDRESS)bn, sleftv_bin); omFreeBin((ADDRESS)cn, sleftv_bin); a->CleanUp(); b->CleanUp(); c->CleanUp(); //Print("op: %d,result typ:%d\n",op,res->rtyp); return FALSE; } } } } i++; } an->CleanUp(); bn->CleanUp(); cn->CleanUp(); omFreeBin((ADDRESS)an, sleftv_bin); omFreeBin((ADDRESS)bn, sleftv_bin); omFreeBin((ADDRESS)cn, sleftv_bin); } // error handling --------------------------------------------------- if (!errorreported) { const char *s=NULL; if ((at==0) && (a->Fullname()!=sNoName)) { s=a->Fullname(); } else if ((bt==0) && (b->Fullname()!=sNoName)) { s=b->Fullname(); } else if ((ct==0) && (c->Fullname()!=sNoName)) { s=c->Fullname(); } if (s!=NULL) Werror("`%s` is not defined",s); else { i=0; //while ((dA3[i].cmd!=op)&&(dA3[i].cmd!=0)) i++; const char *s = iiTwoOps(op); Werror("%s(`%s`,`%s`,`%s`) failed" ,s,Tok2Cmdname(at),Tok2Cmdname(bt),Tok2Cmdname(ct)); if ((!call_failed) && BVERBOSE(V_SHOW_USE)) { while (dA3[i].cmd==op) { if(((at==dA3[i].arg1) ||(bt==dA3[i].arg2) ||(ct==dA3[i].arg3)) && (dA3[i].res!=0)) { Werror("expected %s(`%s`,`%s`,`%s`)" ,s,Tok2Cmdname(dA3[i].arg1) ,Tok2Cmdname(dA3[i].arg2) ,Tok2Cmdname(dA3[i].arg3)); } i++; } } } } res->rtyp = UNKNOWN; } a->CleanUp(); b->CleanUp(); c->CleanUp(); //Print("op: %d,result typ:%d\n",op,res->rtyp); return TRUE; } BOOLEAN iiExprArith3(leftv res, int op, leftv a, leftv b, leftv c) { memset(res,0,sizeof(sleftv)); if (!errorreported) { #ifdef SIQ if (siq>0) { //Print("siq:%d\n",siq); command d=(command)omAlloc0Bin(sip_command_bin); memcpy(&d->arg1,a,sizeof(sleftv)); //a->Init(); memcpy(&d->arg2,b,sizeof(sleftv)); //b->Init(); memcpy(&d->arg3,c,sizeof(sleftv)); //c->Init(); d->op=op; d->argc=3; res->data=(char *)d; res->rtyp=COMMAND; return FALSE; } #endif int at=a->Typ(); // handling bb-objects ---------------------------------------------- if (at>MAX_TOK) { blackbox *bb=getBlackboxStuff(at); if (bb!=NULL) { if(!bb->blackbox_Op3(op,res,a,b,c)) return FALSE; if (errorreported) return TRUE; // else: no op defined } else return TRUE; if (errorreported) return TRUE; } int bt=b->Typ(); int ct=c->Typ(); iiOp=op; int i=0; while ((dArith3[i].cmd!=op)&&(dArith3[i].cmd!=0)) i++; return iiExprArith3TabIntern(res,op,a,b,c,dArith3+i,at,bt,ct,dConvertTypes); } a->CleanUp(); b->CleanUp(); c->CleanUp(); //Print("op: %d,result typ:%d\n",op,res->rtyp); return TRUE; } BOOLEAN iiExprArith3Tab(leftv res, leftv a, int op, struct sValCmd3* dA3, int at, struct sConvertTypes *dConvertTypes) { leftv b=a->next; a->next=NULL; int bt=b->Typ(); leftv c=b->next; b->next=NULL; int ct=c->Typ(); BOOLEAN bo=iiExprArith3TabIntern(res,op,a,b,c,dA3,at,bt,ct,dConvertTypes); b->next=c; a->next=b; a->CleanUp(); return bo; } /*==================== operations with many arg. ===============================*/ /* must be ordered: first operations for chars (infix ops), * then alphabetically */ BOOLEAN jjANY2LIST(leftv res, leftv v, int cnt) { // cnt = 0: all // cnt = 1: only first one leftv next; BOOLEAN failed = TRUE; if(v==NULL) return failed; res->rtyp = LIST_CMD; if(cnt) v->next = NULL; next = v->next; // saving next-pointer failed = jjLIST_PL(res, v); v->next = next; // writeback next-pointer return failed; } BOOLEAN iiExprArithM(leftv res, leftv a, int op) { memset(res,0,sizeof(sleftv)); if (!errorreported) { #ifdef SIQ if (siq>0) { //Print("siq:%d\n",siq); command d=(command)omAlloc0Bin(sip_command_bin); d->op=op; res->data=(char *)d; if (a!=NULL) { d->argc=a->listLength(); // else : d->argc=0; memcpy(&d->arg1,a,sizeof(sleftv)); switch(d->argc) { case 3: memcpy(&d->arg3,a->next->next,sizeof(sleftv)); a->next->next->Init(); /* no break */ case 2: memcpy(&d->arg2,a->next,sizeof(sleftv)); a->next->Init(); a->next->next=d->arg2.next; d->arg2.next=NULL; /* no break */ case 1: a->Init(); a->next=d->arg1.next; d->arg1.next=NULL; } if (d->argc>3) a->next=NULL; a->name=NULL; a->rtyp=0; a->data=NULL; a->e=NULL; a->attribute=NULL; a->CleanUp(); } res->rtyp=COMMAND; return FALSE; } #endif if ((a!=NULL) && (a->Typ()>MAX_TOK)) { blackbox *bb=getBlackboxStuff(a->Typ()); if (bb!=NULL) { if(!bb->blackbox_OpM(op,res,a)) return FALSE; if (errorreported) return TRUE; // else: no op defined } else return TRUE; } BOOLEAN failed=FALSE; int args=0; if (a!=NULL) args=a->listLength(); iiOp=op; int i=0; while ((dArithM[i].cmd!=op)&&(dArithM[i].cmd!=0)) i++; while (dArithM[i].cmd==op) { if ((args==dArithM[i].number_of_args) || (dArithM[i].number_of_args==-1) || ((dArithM[i].number_of_args==-2)&&(args>0))) { res->rtyp=dArithM[i].res; if (currRing!=NULL) { if (check_valid(dArithM[i].valid_for,op)) break; } if (traceit&TRACE_CALL) Print("call %s(... (%d args))\n", iiTwoOps(op),args); if ((failed=dArithM[i].p(res,a))==TRUE) { break;// leave loop, goto error handling } if (a!=NULL) a->CleanUp(); //Print("op: %d,result typ:%d\n",op,res->rtyp); return failed; } i++; } // error handling if (!errorreported) { if ((args>0) && (a->rtyp==0) && (a->Name()!=sNoName)) { Werror("`%s` is not defined",a->Fullname()); } else { const char *s = iiTwoOps(op); Werror("%s(...) failed",s); } } res->rtyp = UNKNOWN; } if (a!=NULL) a->CleanUp(); //Print("op: %d,result typ:%d\n",op,res->rtyp); return TRUE; } /*=================== general utilities ============================*/ int IsCmd(const char *n, int & tok) { int i; int an=1; int en=sArithBase.nLastIdentifier; loop //for(an=0; an=en-1) { if (strcmp(n, sArithBase.sCmds[an].name) == 0) { i=an; break; } else if ((an!=en) && (strcmp(n, sArithBase.sCmds[en].name) == 0)) { i=en; break; } else { // -- blackbox extensions: // return 0; return blackboxIsCmd(n,tok); } } i=(an+en)/2; if (*n < *(sArithBase.sCmds[i].name)) { en=i-1; } else if (*n > *(sArithBase.sCmds[i].name)) { an=i+1; } else { int v=strcmp(n,sArithBase.sCmds[i].name); if(v<0) { en=i-1; } else if(v>0) { an=i+1; } else /*v==0*/ { break; } } } lastreserved=sArithBase.sCmds[i].name; tok=sArithBase.sCmds[i].tokval; if(sArithBase.sCmds[i].alias==2) { Warn("outdated identifier `%s` used - please change your code", sArithBase.sCmds[i].name); sArithBase.sCmds[i].alias=1; } #if 0 if (currRingHdl==NULL) { #ifdef SIQ if (siq<=0) { #endif if ((tok>=BEGIN_RING) && (tok<=END_RING)) { WerrorS("no ring active"); return 0; } #ifdef SIQ } #endif } #endif if (!expected_parms) { switch (tok) { case IDEAL_CMD: case INT_CMD: case INTVEC_CMD: case MAP_CMD: case MATRIX_CMD: case MODUL_CMD: case POLY_CMD: case PROC_CMD: case RING_CMD: case STRING_CMD: cmdtok = tok; break; } } return sArithBase.sCmds[i].toktype; } static int iiTabIndex(const jjValCmdTab dArithTab, const int len, const int op) { // user defined types are not in the pre-computed table: if (op>MAX_TOK) return 0; int a=0; int e=len; int p=len/2; do { if (op==dArithTab[p].cmd) return dArithTab[p].start; if (opMAX_TOK) return getBlackboxName(tok); int i; for(i=0; i **/ /*---------------------------------------------------------------------*/ static int _gentable_sort_cmds( const void *a, const void *b ) { cmdnames *pCmdL = (cmdnames*)a; cmdnames *pCmdR = (cmdnames*)b; if(a==NULL || b==NULL) return 0; /* empty entries goes to the end of the list for later reuse */ if(pCmdL->name==NULL) return 1; if(pCmdR->name==NULL) return -1; /* $INVALID$ must come first */ if(strcmp(pCmdL->name, "$INVALID$")==0) return -1; if(strcmp(pCmdR->name, "$INVALID$")==0) return 1; /* tokval=-1 are reserved names at the end */ if (pCmdL->tokval==-1) { if (pCmdR->tokval==-1) return strcmp(pCmdL->name, pCmdR->name); /* pCmdL->tokval==-1, pCmdL goes at the end */ return 1; } /* pCmdR->tokval==-1, pCmdR goes at the end */ if(pCmdR->tokval==-1) return -1; return strcmp(pCmdL->name, pCmdR->name); } /*---------------------------------------------------------------------*/ /** * @brief initialisation of arithmetic structured data @retval 0 on success **/ /*---------------------------------------------------------------------*/ int iiInitArithmetic() { //printf("iiInitArithmetic()\n"); memset(&sArithBase, 0, sizeof(sArithBase)); iiInitCmdName(); /* fix last-identifier */ #if 0 /* we expect that gentable allready did every thing */ for(sArithBase.nLastIdentifier=sArithBase.nCmdUsed-1; sArithBase.nLastIdentifier>0; sArithBase.nLastIdentifier--) { if(sArithBase.sCmds[sArithBase.nLastIdentifier].tokval>=0) break; } #endif //Print("L=%d\n", sArithBase.nLastIdentifier); //iiArithAddCmd(szName, nAlias, nTokval, nToktype); //iiArithAddCmd("mygcd", 1, GCD_CMD, CMD_2); //iiArithAddCmd("Top", 0,-1,0); //for(i=0; i=en-1) { if (strcmp(szName, sArithBase.sCmds[an].name) == 0) { //Print("RET-an=%d %s\n", an, sArithBase.sCmds[an].name); return an; } else if (strcmp(szName, sArithBase.sCmds[en].name) == 0) { //Print("RET-en=%d %s\n", en, sArithBase.sCmds[en].name); return en; } else { //Print("RET- 1\n"); return -1; } } i=(an+en)/2; if (*szName < *(sArithBase.sCmds[i].name)) { en=i-1; } else if (*szName > *(sArithBase.sCmds[i].name)) { an=i+1; } else { v=strcmp(szName,sArithBase.sCmds[i].name); if(v<0) { en=i-1; } else if(v>0) { an=i+1; } else /*v==0*/ { //Print("RET-i=%d %s\n", i, sArithBase.sCmds[i].name); return i; } } } //if(i>=0 && i=sArithBase.nCmdUsed) { Print("'%s' not found (%d)\n", szName, nIndex); return -1; } omFree(sArithBase.sCmds[nIndex].name); sArithBase.sCmds[nIndex].name=NULL; qsort(sArithBase.sCmds, sArithBase.nCmdUsed, sizeof(cmdnames), (&_gentable_sort_cmds)); sArithBase.nCmdUsed--; /* fix last-identifier */ for(sArithBase.nLastIdentifier=sArithBase.nCmdUsed-1; sArithBase.nLastIdentifier>0; sArithBase.nLastIdentifier--) { if(sArithBase.sCmds[sArithBase.nLastIdentifier].tokval>=0) break; } //Print("L=%d\n", sArithBase.nLastIdentifier); return 0; } int iiArithAddCmd( const char *szName, short nAlias, short nTokval, short nToktype, short nPos ) { //printf("AddCmd(%s, %d, %d, %d, %d)\n", szName, nAlias, // nTokval, nToktype, nPos); if(nPos>=0) { // no checks: we rely on a correct generated code in iparith.inc assume(nPos < sArithBase.nCmdAllocated); assume(szName!=NULL); sArithBase.sCmds[nPos].name = omStrDup(szName); sArithBase.sCmds[nPos].alias = nAlias; sArithBase.sCmds[nPos].tokval = nTokval; sArithBase.sCmds[nPos].toktype = nToktype; sArithBase.nCmdUsed++; //if(nTokval>0) sArithBase.nLastIdentifier++; } else { if(szName==NULL) return -1; int nIndex = iiArithFindCmd(szName); if(nIndex>=0) { Print("'%s' already exists at %d\n", szName, nIndex); return -1; } if(sArithBase.nCmdUsed>=sArithBase.nCmdAllocated) { /* needs to create new slots */ unsigned long nSize = (sArithBase.nCmdAllocated+1)*sizeof(cmdnames); sArithBase.sCmds = (cmdnames *)omRealloc(sArithBase.sCmds, nSize); if(sArithBase.sCmds==NULL) return -1; sArithBase.nCmdAllocated++; } /* still free slots available */ sArithBase.sCmds[sArithBase.nCmdUsed].name = omStrDup(szName); sArithBase.sCmds[sArithBase.nCmdUsed].alias = nAlias; sArithBase.sCmds[sArithBase.nCmdUsed].tokval = nTokval; sArithBase.sCmds[sArithBase.nCmdUsed].toktype = nToktype; sArithBase.nCmdUsed++; qsort(sArithBase.sCmds, sArithBase.nCmdUsed, sizeof(cmdnames), (&_gentable_sort_cmds)); for(sArithBase.nLastIdentifier=sArithBase.nCmdUsed-1; sArithBase.nLastIdentifier>0; sArithBase.nLastIdentifier--) { if(sArithBase.sCmds[sArithBase.nLastIdentifier].tokval>=0) break; } //Print("L=%d\n", sArithBase.nLastIdentifier); } return 0; } static BOOLEAN check_valid(const int p, const int op) { #ifdef HAVE_PLURAL if (rIsPluralRing(currRing)) { if ((p & PLURAL_MASK)==0 /*NO_PLURAL*/) { WerrorS("not implemented for non-commutative rings"); return TRUE; } else if ((p & PLURAL_MASK)==2 /*, COMM_PLURAL */) { Warn("assume commutative subalgebra for cmd `%s`",Tok2Cmdname(op)); return FALSE; } /* else, ALLOW_PLURAL */ } #endif #ifdef HAVE_RINGS if (rField_is_Ring(currRing)) { if ((p & RING_MASK)==0 /*NO_RING*/) { WerrorS("not implemented for rings with rings as coeffients"); return TRUE; } /* else ALLOW_RING */ else if (((p & ZERODIVISOR_MASK)==NO_ZERODIVISOR) &&(!rField_is_Domain(currRing))) { WerrorS("domain required as coeffients"); return TRUE; } /* else ALLOW_ZERODIVISOR */ else if(((p & WARN_RING)==WARN_RING)&&(myynest==0)) { WarnS("considering the image in Q[...]"); } } #endif return FALSE; } singular-4.0.3+ds/Singular/ipassign.cc000066400000000000000000001434661266270727000177030ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: interpreter: * assignment of expressions and lists to objects or lists */ #include #include #include #include #include #include #define TRANSEXT_PRIVATES #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include "weight.h" #include "tok.h" #include "ipid.h" #include "idrec.h" #include "subexpr.h" #include "lists.h" #include "ipconv.h" #include "attrib.h" #include "links/silink.h" #include "ipshell.h" #include "blackbox.h" #include "Singular/number2.h" /*=================== proc =================*/ static BOOLEAN jjECHO(leftv, leftv a) { si_echo=(int)((long)(a->Data())); return FALSE; } static BOOLEAN jjPRINTLEVEL(leftv, leftv a) { printlevel=(int)((long)(a->Data())); return FALSE; } static BOOLEAN jjCOLMAX(leftv, leftv a) { colmax=(int)((long)(a->Data())); return FALSE; } static BOOLEAN jjTIMER(leftv, leftv a) { timerv=(int)((long)(a->Data())); initTimer(); return FALSE; } #ifdef HAVE_GETTIMEOFDAY static BOOLEAN jjRTIMER(leftv, leftv a) { rtimerv=(int)((long)(a->Data())); initRTimer(); return FALSE; } #endif static BOOLEAN jjMAXDEG(leftv, leftv a) { Kstd1_deg=(int)((long)(a->Data())); if (Kstd1_deg!=0) si_opt_1 |=Sy_bit(OPT_DEGBOUND); else si_opt_1 &=(~Sy_bit(OPT_DEGBOUND)); return FALSE; } static BOOLEAN jjMAXMULT(leftv, leftv a) { Kstd1_mu=(int)((long)(a->Data())); if (Kstd1_mu!=0) si_opt_1 |=Sy_bit(OPT_MULTBOUND); else si_opt_1 &=(~Sy_bit(OPT_MULTBOUND)); return FALSE; } static BOOLEAN jjTRACE(leftv, leftv a) { traceit=(int)((long)(a->Data())); return FALSE; } static BOOLEAN jjSHORTOUT(leftv, leftv a) { if (currRing != NULL) { BOOLEAN shortOut = (BOOLEAN)((long)a->Data()); #if HAVE_CAN_SHORT_OUT if (!shortOut) currRing->ShortOut = 0; else { if (currRing->CanShortOut) currRing->ShortOut = 1; } #else currRing->ShortOut = shortOut; coeffs cf = currRing->cf; while (nCoeff_is_Extension(cf)) { cf->extRing->ShortOut = shortOut; assume(cf->extRing != NULL); cf = cf->extRing->cf; } #endif } return FALSE; } static void jjMINPOLY_red(idhdl h) { switch(IDTYP(h)) { case NUMBER_CMD: { number n=(number)IDDATA(h); number one = nInit(1); number nn=nMult(n,one); nDelete(&n);nDelete(&one); IDDATA(h)=(char*)nn; break; } case VECTOR_CMD: case POLY_CMD: { poly p=(poly)IDDATA(h); IDDATA(h)=(char*)p_MinPolyNormalize(p, currRing); break; } case IDEAL_CMD: case MODUL_CMD: case MAP_CMD: case MATRIX_CMD: { int i; ideal I=(ideal)IDDATA(h); for(i=IDELEMS(I)-1;i>=0;i--) I->m[i]=p_MinPolyNormalize(I->m[i], currRing); break; } case LIST_CMD: { lists L=(lists)IDDATA(h); int i=L->nr; for(;i>=0;i--) { jjMINPOLY_red((idhdl)&(L->m[i])); } } default: //case RESOLUTION_CMD: Werror("type %d too complex...set minpoly before",IDTYP(h)); break; } } static BOOLEAN jjMINPOLY(leftv, leftv a) { if( !nCoeff_is_transExt(currRing->cf) && (currRing->idroot == NULL) && n_IsZero((number)a->Data(), currRing->cf) ) { #ifndef SING_NDEBUG WarnS("Set minpoly over non-transcendental ground field to 0?!"); Warn("in >>%s<<",my_yylinebuf); #endif return FALSE; } if ( !nCoeff_is_transExt(currRing->cf) ) { WarnS("Trying to set minpoly over non-transcendental ground field..."); if(!nCoeff_is_algExt(currRing->cf) ) { WerrorS("cannot set minpoly for these coeffients"); return TRUE; } } if ((rVar(currRing->cf->extRing)!=1) && !n_IsZero((number)a->Data(), currRing->cf) ) { WerrorS("only univarite minpoly allowed"); return TRUE; } if ( currRing->idroot != NULL ) { // return TRUE; #ifndef SING_NDEBUG idhdl p = currRing->idroot; WarnS("no minpoly allowed if there are local objects belonging to the basering: "); while(p != NULL) { PrintS(p->String(TRUE)); PrintLn(); p = p->next; } #endif } // assume (currRing->idroot==NULL); number p = (number)a->CopyD(NUMBER_CMD); n_Normalize(p, currRing->cf); if (n_IsZero(p, currRing->cf)) { n_Delete(&p, currRing); if( nCoeff_is_transExt(currRing->cf) ) { #ifndef SING_NDEBUG WarnS("minpoly is already 0..."); #endif return FALSE; } WarnS("cannot set minpoly to 0 / alg. extension?"); return TRUE; } // remove all object currently in the ring while(currRing->idroot!=NULL) { #ifndef SING_NDEBUG Warn("killing a local object due to minpoly change: %s", IDID(currRing->idroot)); #endif killhdl2(currRing->idroot,&(currRing->idroot),currRing); } AlgExtInfo A; A.r = rCopy(currRing->cf->extRing); // Copy ground field! // if minpoly was already set: if( currRing->cf->extRing->qideal != NULL ) id_Delete(&(A.r->qideal),A.r); ideal q = idInit(1,1); if ((p==NULL) ||(NUM((fraction)p)==NULL)) { Werror("Could not construct the alg. extension: minpoly==0"); // cleanup A: TODO rDelete( A.r ); return TRUE; } if (DEN((fraction)(p)) != NULL) // minpoly must be a fraction with poly numerator...!! { poly z=NUM((fraction)p); poly n=DEN((fraction)(p)); z=p_Mult_nn(z,pGetCoeff(n),currRing->cf->extRing); NUM((fraction)p)=z; DEN((fraction)(p))=NULL; p_Delete(&n,currRing->cf->extRing); } q->m[0] = NUM((fraction)p); A.r->qideal = q; #if 0 PrintS("\nTrying to conver the currRing into an algebraic field: "); PrintS("Ground poly. ring: \n"); rWrite( A.r ); PrintS("\nGiven MinPOLY: "); p_Write( A.i->m[0], A.r ); #endif // :( // NUM((fractionObject *)p) = NULL; // makes 0/ NULL fraction - which should not happen! // n_Delete(&p, currRing->cf); // doesn't expect 0/ NULL :( if(true) { extern omBin fractionObjectBin; NUM((fractionObject *)p) = NULL; // not necessary, but still... omFreeBin((ADDRESS)p, fractionObjectBin); } coeffs new_cf = nInitChar(n_algExt, &A); if (new_cf==NULL) { Werror("Could not construct the alg. extension: llegal minpoly?"); // cleanup A: TODO rDelete( A.r ); return TRUE; } else { nKillChar(currRing->cf); currRing->cf=new_cf; } return FALSE; } static BOOLEAN jjNOETHER(leftv, leftv a) { poly p=(poly)a->CopyD(POLY_CMD); pDelete(&(currRing->ppNoether)); (currRing->ppNoether)=p; return FALSE; } /*=================== proc =================*/ static void jiAssignAttr(leftv l,leftv r) { // get the attribute of th right side // and set it to l leftv rv=r->LData(); if (rv!=NULL) { if (rv->e==NULL) { if (rv->attribute!=NULL) { attr la; if (r->rtyp!=IDHDL) { la=rv->attribute; rv->attribute=NULL; } else { la=rv->attribute->Copy(); } l->attribute=la; } l->flag=rv->flag; } } if (l->rtyp==IDHDL) { idhdl h=(idhdl)l->data; IDATTR(h)=l->attribute; IDFLAG(h)=l->flag; } } static BOOLEAN jiA_INT(leftv res, leftv a, Subexpr e) { if (e==NULL) { res->data=(void *)a->Data(); jiAssignAttr(res,a); } else { int i=e->start-1; if (i<0) { Werror("index[%d] must be positive",i+1); return TRUE; } intvec *iv=(intvec *)res->data; if (e->next==NULL) { if (i>=iv->length()) { intvec *iv1=new intvec(i+1); (*iv1)[i]=(int)((long)(a->Data())); intvec *ivn=ivAdd(iv,iv1); delete iv; delete iv1; res->data=(void *)ivn; } else (*iv)[i]=(int)((long)(a->Data())); } else { int c=e->next->start; if ((i>=iv->rows())||(c<1)||(c>iv->cols())) { Werror("wrong range [%d,%d] in intmat %s(%d,%d)",i+1,c,res->Name(),iv->rows(),iv->cols()); return TRUE; } else IMATELEM(*iv,i+1,c) = (int)((long)(a->Data())); } } return FALSE; } static BOOLEAN jiA_NUMBER(leftv res, leftv a, Subexpr) { number p=(number)a->CopyD(NUMBER_CMD); if (res->data!=NULL) nDelete((number *)&res->data); nNormalize(p); res->data=(void *)p; jiAssignAttr(res,a); return FALSE; } #ifdef SINGULAR_4_1 static BOOLEAN jiA_NUMBER2(leftv res, leftv a, Subexpr e) { number2 n=(number2)a->CopyD(CNUMBER_CMD); if (e==NULL) { if (res->data!=NULL) { number2 nn=(number2)res->data; n2Delete(nn); } res->data=(void *)n; jiAssignAttr(res,a); } else { int i=e->start-1; if (i<0) { Werror("index[%d] must be positive",i+1); return TRUE; } bigintmat *iv=(bigintmat *)res->data; if (e->next==NULL) { WerrorS("only one index given"); return TRUE; } else { int c=e->next->start; if ((i>=iv->rows())||(c<1)||(c>iv->cols())) { Werror("wrong range [%d,%d] in cmatrix %s(%d,%d)",i+1,c,res->Name(),iv->rows(),iv->cols()); return TRUE; } else if (iv->basecoeffs()==n->cf) { n_Delete((number *)&BIMATELEM(*iv,i+1,c),iv->basecoeffs()); BIMATELEM(*iv,i+1,c) = n->n; } else { WerrorS("different base"); return TRUE; } } } jiAssignAttr(res,a); return FALSE; } static BOOLEAN jiA_NUMBER2_I(leftv res, leftv a, Subexpr e) { if (e==NULL) { if (res->data!=NULL) { number2 nn=(number2)res->data; number2 n=n2Init((long)a->Data(),nn->cf); n2Delete(nn); res->data=(void *)n; } else { WerrorS("no (c)ring avialable for conversion from int"); return TRUE; } } else { int i=e->start-1; if (i<0) { Werror("index[%d] must be positive",i+1); return TRUE; } bigintmat *iv=(bigintmat *)res->data; if (e->next==NULL) { WerrorS("only one index given"); return TRUE; } else { int c=e->next->start; if ((i>=iv->rows())||(c<1)||(c>iv->cols())) { Werror("wrong range [%d,%d] in cmatrix %s(%d,%d)",i+1,c,res->Name(),iv->rows(),iv->cols()); return TRUE; } else { n_Delete((number *)&BIMATELEM(*iv,i+1,c),iv->basecoeffs()); BIMATELEM(*iv,i+1,c) = n_Init((long)a->Data(),iv->basecoeffs()); } } } return FALSE; } static BOOLEAN jiA_NUMBER2_N(leftv res, leftv a, Subexpr e) { if (e==NULL) { if (res->data!=NULL) { number2 nn=(number2)res->data; if (currRing->cf==nn->cf) { number2 n=(number2)omAlloc(sizeof(*n)); n->cf=currRing->cf; n->cf++; n->n=(number)a->CopyD(NUMBER_CMD); n2Delete(nn); res->data=(void *)n; } else { WerrorS("different base"); return TRUE; } } else { WerrorS("no (c)ring avialable for conversion from number"); return TRUE; } } else { int i=e->start-1; if (i<0) { Werror("index[%d] must be positive",i+1); return TRUE; } bigintmat *iv=(bigintmat *)res->data; if (e->next==NULL) { WerrorS("only one index given"); return TRUE; } else { int c=e->next->start; if ((i>=iv->rows())||(c<1)||(c>iv->cols())) { Werror("wrong range [%d,%d] in cmatrix %s(%d,%d)",i+1,c,res->Name(),iv->rows(),iv->cols()); return TRUE; } else if (iv->basecoeffs()==currRing->cf) { n_Delete((number *)&BIMATELEM(*iv,i+1,c),iv->basecoeffs()); BIMATELEM(*iv,i+1,c) = (number)(a->CopyD(NUMBER_CMD)); } else { WerrorS("different base"); return TRUE; } } } return FALSE; } #endif static BOOLEAN jiA_BIGINT(leftv res, leftv a, Subexpr e) { number p=(number)a->CopyD(BIGINT_CMD); if (e==NULL) { if (res->data!=NULL) n_Delete((number *)&res->data,coeffs_BIGINT); res->data=(void *)p; } else { int i=e->start-1; if (i<0) { Werror("index[%d] must be positive",i+1); return TRUE; } bigintmat *iv=(bigintmat *)res->data; if (e->next==NULL) { WerrorS("only one index given"); return TRUE; } else { int c=e->next->start; if ((i>=iv->rows())||(c<1)||(c>iv->cols())) { Werror("wrong range [%d,%d] in bigintmat %s(%d,%d)",i+1,c,res->Name(),iv->rows(),iv->cols()); return TRUE; } else { n_Delete((number *)&BIMATELEM(*iv,i+1,c),iv->basecoeffs()); BIMATELEM(*iv,i+1,c) = p; } } } jiAssignAttr(res,a); return FALSE; } static BOOLEAN jiA_LIST_RES(leftv res, leftv a,Subexpr) { syStrategy r=(syStrategy)a->CopyD(RESOLUTION_CMD); if (res->data!=NULL) ((lists)res->data)->Clean(); int add_row_shift = 0; intvec *weights=(intvec*)atGet(a,"isHomog",INTVEC_CMD); if (weights!=NULL) add_row_shift=weights->min_in(); res->data=(void *)syConvRes(r,TRUE,add_row_shift); //jiAssignAttr(res,a); return FALSE; } static BOOLEAN jiA_LIST(leftv res, leftv a,Subexpr) { lists l=(lists)a->CopyD(LIST_CMD); if (res->data!=NULL) ((lists)res->data)->Clean(); res->data=(void *)l; jiAssignAttr(res,a); return FALSE; } static BOOLEAN jiA_POLY(leftv res, leftv a,Subexpr e) { poly p=(poly)a->CopyD(POLY_CMD); pNormalize(p); if (e==NULL) { if ((p!=NULL) && TEST_V_QRING && (currRing->qideal!=NULL) && (!hasFlag(a,FLAG_QRING))) { jjNormalizeQRingP(p); setFlag(res,FLAG_QRING); } if (res->data!=NULL) pDelete((poly*)&res->data); res->data=(void*)p; jiAssignAttr(res,a); } else { int i,j; matrix m=(matrix)res->data; i=e->start; if (e->next==NULL) { j=i; i=1; // for all ideal like data types: check indices if (j>MATCOLS(m)) { if (TEST_V_ALLWARN) { Warn("increase ideal %d -> %d in %s",MATCOLS(m),j,my_yylinebuf); } pEnlargeSet(&(m->m),MATCOLS(m),j-MATCOLS(m)); MATCOLS(m)=j; } else if (j<=0) { Werror("index[%d] must be positive",j/*e->start*/); return TRUE; } } else { // for matrices: indices are correct (see ipExprArith3(..,'['..) ) j=e->next->start; } if ((p!=NULL) && TEST_V_QRING && (currRing->qideal!=NULL)) { jjNormalizeQRingP(p); } pDelete(&MATELEM(m,i,j)); MATELEM(m,i,j)=p; /* for module: update rank */ if ((p!=NULL) && (pGetComp(p)!=0)) { m->rank=si_max(m->rank,pMaxComp(p)); } } return FALSE; } static BOOLEAN jiA_1x1INTMAT(leftv res, leftv a,Subexpr e) { if (/*(*/ res->rtyp!=INTMAT_CMD /*)*/) /*|| (e!=NULL) - TRUE because of type int */ { // no error message: assignment simply fails return TRUE; } intvec* am=(intvec*)a->CopyD(INTMAT_CMD); if ((am->rows()!=1) || (am->cols()!=1)) { WerrorS("must be 1x1 intmat"); delete am; return TRUE; } intvec* m=(intvec *)res->data; // indices are correct (see ipExprArith3(..,'['..) ) int i=e->start; int j=e->next->start; IMATELEM(*m,i,j)=IMATELEM(*am,1,1); delete am; return FALSE; } static BOOLEAN jiA_1x1MATRIX(leftv res, leftv a,Subexpr e) { if (/*(*/ res->rtyp!=MATRIX_CMD /*)*/) /*|| (e!=NULL) - TRUE because of type poly */ { // no error message: assignment simply fails return TRUE; } matrix am=(matrix)a->CopyD(MATRIX_CMD); if ((MATROWS(am)!=1) || (MATCOLS(am)!=1)) { WerrorS("must be 1x1 matrix"); idDelete((ideal *)&am); return TRUE; } matrix m=(matrix)res->data; // indices are correct (see ipExprArith3(..,'['..) ) int i=e->start; int j=e->next->start; pDelete(&MATELEM(m,i,j)); pNormalize(MATELEM(am,1,1)); MATELEM(m,i,j)=MATELEM(am,1,1); MATELEM(am,1,1)=NULL; idDelete((ideal *)&am); return FALSE; } static BOOLEAN jiA_STRING(leftv res, leftv a, Subexpr e) { if (e==NULL) { void* tmp = res->data; res->data=(void *)a->CopyD(STRING_CMD); jiAssignAttr(res,a); omfree(tmp); } else { char *s=(char *)res->data; if ((e->start>0)&&(e->start<=(int)strlen(s))) s[e->start-1]=(char)(*((char *)a->Data())); else { Werror("string index %d out of range 1..%d",e->start,(int)strlen(s)); return TRUE; } } return FALSE; } static BOOLEAN jiA_PROC(leftv res, leftv a, Subexpr) { extern procinfo *iiInitSingularProcinfo(procinfo *pi, const char *libname, const char *procname, int line, long pos, BOOLEAN pstatic=FALSE); if(res->data!=NULL) piKill((procinfo *)res->data); if(a->Typ()==STRING_CMD) { res->data = (void *)omAlloc0Bin(procinfo_bin); ((procinfo *)(res->data))->language=LANG_NONE; iiInitSingularProcinfo((procinfo *)res->data,"",res->name,0,0); ((procinfo *)res->data)->data.s.body=(char *)a->CopyD(STRING_CMD); } else res->data=(void *)a->CopyD(PROC_CMD); jiAssignAttr(res,a); return FALSE; } static BOOLEAN jiA_INTVEC(leftv res, leftv a, Subexpr) { //if ((res->data==NULL) || (res->Typ()==a->Typ())) { if (res->data!=NULL) delete ((intvec *)res->data); res->data=(void *)a->CopyD(INTVEC_CMD); jiAssignAttr(res,a); return FALSE; } #if 0 else { intvec *r=(intvec *)(res->data); intvec *s=(intvec *)(a->Data()); int i=si_min(r->length(), s->length())-1; for(;i>=0;i--) { (*r)[i]=(*s)[i]; } return FALSE; //(r->length()< s->length()); } #endif } static BOOLEAN jiA_BIGINTMAT(leftv res, leftv a, Subexpr) { if (res->data!=NULL) delete ((bigintmat *)res->data); res->data=(void *)a->CopyD(BIGINTMAT_CMD); jiAssignAttr(res,a); return FALSE; } static BOOLEAN jiA_IDEAL(leftv res, leftv a, Subexpr) { if (res->data!=NULL) idDelete((ideal*)&res->data); res->data=(void *)a->CopyD(MATRIX_CMD); if (a->rtyp==IDHDL) id_Normalize((ideal)a->Data(), currRing); else id_Normalize((ideal)res->data, currRing); jiAssignAttr(res,a); if (((res->rtyp==IDEAL_CMD)||(res->rtyp==MODUL_CMD)) && (IDELEMS((ideal)(res->data))==1) && (currRing->qideal==NULL) && (!rIsPluralRing(currRing)) ) { setFlag(res,FLAG_STD); } if (TEST_V_QRING && (currRing->qideal!=NULL)&& (!hasFlag(res,FLAG_QRING))) jjNormalizeQRingId(res); return FALSE; } static BOOLEAN jiA_RESOLUTION(leftv res, leftv a, Subexpr) { if (res->data!=NULL) syKillComputation((syStrategy)res->data); res->data=(void *)a->CopyD(RESOLUTION_CMD); jiAssignAttr(res,a); return FALSE; } static BOOLEAN jiA_MODUL_P(leftv res, leftv a, Subexpr) /* module = poly */ { if (res->data!=NULL) idDelete((ideal*)&res->data); ideal I=idInit(1,1); I->m[0]=(poly)a->CopyD(POLY_CMD); if (I->m[0]!=NULL) pSetCompP(I->m[0],1); pNormalize(I->m[0]); res->data=(void *)I; if (TEST_V_QRING && (currRing->qideal!=NULL)) { if (hasFlag(a,FLAG_QRING)) setFlag(res,FLAG_QRING); else jjNormalizeQRingId(res); } return FALSE; } static BOOLEAN jiA_IDEAL_M(leftv res, leftv a, Subexpr) { if (res->data!=NULL) idDelete((ideal*)&res->data); matrix m=(matrix)a->CopyD(MATRIX_CMD); if (TEST_V_ALLWARN) if (MATROWS(m)>1) Warn("assign matrix with %d rows to an ideal in >>%s<<",MATROWS(m),my_yylinebuf); IDELEMS((ideal)m)=MATROWS(m)*MATCOLS(m); ((ideal)m)->rank=1; MATROWS(m)=1; id_Normalize((ideal)m, currRing); res->data=(void *)m; if (TEST_V_QRING && (currRing->qideal!=NULL)) jjNormalizeQRingId(res); return FALSE; } static BOOLEAN jiA_LINK(leftv res, leftv a, Subexpr) { si_link l=(si_link)res->data; if (l!=NULL) slCleanUp(l); if (a->Typ() == STRING_CMD) { if (l == NULL) { l = (si_link) omAlloc0Bin(sip_link_bin); res->data = (void *) l; } return slInit(l, (char *) a->Data()); } else if (a->Typ() == LINK_CMD) { if (l != NULL) omFreeBin(l, sip_link_bin); res->data = slCopy((si_link)a->Data()); return FALSE; } return TRUE; } // assign map -> map static BOOLEAN jiA_MAP(leftv res, leftv a, Subexpr) { if (res->data!=NULL) { omFree((ADDRESS)((map)res->data)->preimage); ((map)res->data)->preimage=NULL; idDelete((ideal*)&res->data); } res->data=(void *)a->CopyD(MAP_CMD); jiAssignAttr(res,a); return FALSE; } // assign ideal -> map static BOOLEAN jiA_MAP_ID(leftv res, leftv a, Subexpr) { map f=(map)res->data; char *rn=f->preimage; // save the old/already assigned preimage ring name f->preimage=NULL; idDelete((ideal *)&f); res->data=(void *)a->CopyD(IDEAL_CMD); f=(map)res->data; id_Normalize((ideal)f, currRing); f->preimage = rn; return FALSE; } static BOOLEAN jiA_QRING(leftv res, leftv a,Subexpr e) { // the follwing can only happen, if: // - the left side is of type qring AND not an id if ((e!=NULL)||(res->rtyp!=IDHDL)) { WerrorS("qring_id expected"); return TRUE; } ring old_ring=(ring)res->Data(); coeffs newcf = currRing->cf; ideal id = (ideal)a->Data(); //? const int cpos = idPosConstant(id); if(rField_is_Ring(currRing)) if (cpos >= 0) { newcf = n_CoeffRingQuot1(p_GetCoeff(id->m[cpos], currRing), currRing->cf); if(newcf == NULL) return TRUE; } //qr=(ring)res->Data(); //if (qr!=NULL) omFreeBin((ADDRESS)qr, ip_sring_bin); ring qr = rCopy(currRing); assume(qr->cf == currRing->cf); if ( qr->cf != newcf ) { nKillChar ( qr->cf ); // ??? qr->cf = newcf; } // we have to fill it, but the copy also allocates space idhdl h=(idhdl)res->data; // we have res->rtyp==IDHDL IDRING(h)=qr; ideal qid; #ifdef HAVE_RINGS if((rField_is_Ring(currRing)) && (cpos != -1)) { int i, j; int *perm = (int *)omAlloc0((qr->N+1)*sizeof(int)); for(i=qr->N;i>0;i--) perm[i]=i; nMapFunc nMap = n_SetMap(currRing->cf, newcf); qid = idInit(IDELEMS(id)-1,1); for(i = 0, j = 0; im[j++] = p_PermPoly(id->m[i], perm, currRing, qr, nMap, NULL, 0); } else #endif qid = idrCopyR(id,currRing,qr); idSkipZeroes(qid); //idPrint(qid); if ((idElem(qid)>1) || rIsSCA(currRing) || (currRing->qideal!=NULL)) assumeStdFlag(a); if (currRing->qideal!=NULL) /* we are already in a qring! */ { ideal tmp=idSimpleAdd(qid,currRing->qideal); // both ideals should be GB, so dSimpleAdd is sufficient idDelete(&qid); qid=tmp; // delete the qr copy of quotient ideal!!! idDelete(&qr->qideal); } if (idElem(qid)==0) { qr->qideal = NULL; id_Delete(&qid,currRing); IDTYP(h)=RING_CMD; } else qr->qideal = qid; // qr is a copy of currRing with the new qideal! #ifdef HAVE_PLURAL if(rIsPluralRing(currRing) &&(qr->qideal!=NULL)) { if (!hasFlag(a,FLAG_TWOSTD)) { Warn("%s is no twosided standard basis",a->Name()); } if( nc_SetupQuotient(qr, currRing) ) { // WarnS("error in nc_SetupQuotient"); } } #endif //rWrite(qr); rSetHdl((idhdl)res->data); if (old_ring!=NULL) { rDelete(old_ring); } return FALSE; } static BOOLEAN jiA_RING(leftv res, leftv a, Subexpr e) { BOOLEAN have_id=TRUE; if ((e!=NULL)||(res->rtyp!=IDHDL)) { //WerrorS("id expected"); //return TRUE; have_id=FALSE; } ring r=(ring)a->Data(); if (have_id) { idhdl rl=(idhdl)res->data; if (IDRING(rl)!=NULL) rKill(rl); IDRING(rl)=r; if ((IDLEV((idhdl)a->data)!=myynest) && (r==currRing)) currRingHdl=(idhdl)res->data; } else { if (e==NULL) res->data=(char *)r; else { WerrorS("id expected"); return TRUE; } } r->ref++; jiAssignAttr(res,a); return FALSE; } static BOOLEAN jiA_PACKAGE(leftv res, leftv a, Subexpr) { res->data=(void *)a->CopyD(PACKAGE_CMD); jiAssignAttr(res,a); return FALSE; } static BOOLEAN jiA_DEF(leftv res, leftv, Subexpr) { res->data=(void *)0; return FALSE; } #ifdef SINGULAR_4_1 static BOOLEAN jiA_CRING(leftv res, leftv a, Subexpr e) { res->data=(void *)a->CopyD(CRING_CMD); jiAssignAttr(res,a); return FALSE; } #endif /*=================== table =================*/ #define IPASSIGN #define D(A) A #define NULL_VAL NULL #include "table.h" /*=================== operations ============================*/ /*2 * assign a = b */ static BOOLEAN jiAssign_1(leftv l, leftv r, BOOLEAN toplevel) { int rt=r->Typ(); if (rt==0) { if (!errorreported) Werror("`%s` is undefined",r->Fullname()); return TRUE; } int lt=l->Typ(); if (lt==0) { if (!errorreported) Werror("left side `%s` is undefined",l->Fullname()); return TRUE; } if(rt==NONE) { WarnS("right side is not a datum, assignment ignored"); // if (!errorreported) // WerrorS("right side is not a datum"); //return TRUE; return FALSE; } if (lt==DEF_CMD) { if (TEST_V_ALLWARN && (rt!=RING_CMD) && (rt!=QRING_CMD) && (l->name!=NULL) && (l->e==NULL) && (iiCurrArgs==NULL) /* not in proc header */ ) { Warn("use `%s` instead of `def` in %s:%d:%s",Tok2Cmdname(rt), currentVoice->filename,yylineno,my_yylinebuf); } if (l->rtyp==IDHDL) { IDTYP((idhdl)l->data)=rt; } else if (l->name!=NULL) { sleftv ll; iiDeclCommand(&ll,l,myynest,rt,&IDROOT); memcpy(l,&ll,sizeof(sleftv)); } else { l->rtyp=rt; } lt=rt; } else { if ((l->data==r->data)&&(l->e==NULL)&&(r->e==NULL)) return FALSE; } leftv ld=l; if (l->rtyp==IDHDL) { if ((lt!=QRING_CMD)&&(lt!=RING_CMD)) ld=(leftv)l->data; } else if (toplevel) { WerrorS("error in assign: left side is not an l-value"); return TRUE; } if (lt>MAX_TOK) { blackbox *bb=getBlackboxStuff(lt); #ifdef BLACKBOX_DEVEL Print("bb-assign: bb=%lx\n",bb); #endif return (bb==NULL) || bb->blackbox_Assign(l,r); } int start=0; while ((dAssign[start].res!=lt) && (dAssign[start].res!=0)) start++; int i=start; while ((dAssign[i].res==lt) && (dAssign[i].arg!=rt)) i++; if (dAssign[i].res==lt) { if (traceit&TRACE_ASSIGN) Print("assign %s=%s\n",Tok2Cmdname(lt),Tok2Cmdname(rt)); BOOLEAN b; b=dAssign[i].p(ld,r,l->e); if(l!=ld) /* i.e. l is IDHDL, l->data is ld */ { l->flag=ld->flag; l->attribute=ld->attribute; } return b; } // implicite type conversion ---------------------------------------------- if (dAssign[i].res!=lt) { int ri; leftv rn = (leftv)omAlloc0Bin(sleftv_bin); BOOLEAN failed=FALSE; i=start; //while ((dAssign[i].res!=lt) // && (dAssign[i].res!=0)) i++; while (dAssign[i].res==lt) { if ((ri=iiTestConvert(rt,dAssign[i].arg))!=0) { failed= iiConvert(rt,dAssign[i].arg,ri,r,rn); if(!failed) { failed= dAssign[i].p(ld,rn,l->e); if (traceit&TRACE_ASSIGN) Print("assign %s=%s ok? %d\n",Tok2Cmdname(lt),Tok2Cmdname(rn->rtyp),!failed); } // everything done, clean up temp. variables rn->CleanUp(); omFreeBin((ADDRESS)rn, sleftv_bin); if (failed) { // leave loop, goto error handling break; } else { if(l!=ld) /* i.e. l is IDHDL, l->data is ld */ { l->flag=ld->flag; l->attribute=ld->attribute; } // everything ok, return return FALSE; } } i++; } // error handling --------------------------------------------------- if (!errorreported) { if ((l->rtyp==IDHDL) && (l->e==NULL)) Werror("`%s`(%s) = `%s` is not supported", Tok2Cmdname(lt),l->Name(),Tok2Cmdname(rt)); else Werror("`%s` = `%s` is not supported" ,Tok2Cmdname(lt),Tok2Cmdname(rt)); if (BVERBOSE(V_SHOW_USE)) { i=0; while ((dAssign[i].res!=lt) && (dAssign[i].res!=0)) i++; while (dAssign[i].res==lt) { Werror("expected `%s` = `%s`" ,Tok2Cmdname(lt),Tok2Cmdname(dAssign[i].arg)); i++; } } } } return TRUE; } /*2 * assign sys_var = val */ static BOOLEAN iiAssign_sys(leftv l, leftv r) { int rt=r->Typ(); if (rt==0) { if (!errorreported) Werror("`%s` is undefined",r->Fullname()); return TRUE; } int i=0; int lt=l->rtyp; while (((dAssign_sys[i].res!=lt) || (dAssign_sys[i].arg!=rt)) && (dAssign_sys[i].res!=0)) i++; if (dAssign_sys[i].res!=0) { if (!dAssign_sys[i].p(l,r)) { // everything ok, clean up return FALSE; } } // implicite type conversion ---------------------------------------------- if (dAssign_sys[i].res==0) { int ri; leftv rn = (leftv)omAlloc0Bin(sleftv_bin); BOOLEAN failed=FALSE; i=0; while ((dAssign_sys[i].res!=lt) && (dAssign_sys[i].res!=0)) i++; while (dAssign_sys[i].res==lt) { if ((ri=iiTestConvert(rt,dAssign_sys[i].arg))!=0) { failed= ((iiConvert(rt,dAssign_sys[i].arg,ri,r,rn)) || (dAssign_sys[i].p(l,rn))); // everything done, clean up temp. variables rn->CleanUp(); omFreeBin((ADDRESS)rn, sleftv_bin); if (failed) { // leave loop, goto error handling break; } else { // everything ok, return return FALSE; } } i++; } // error handling --------------------------------------------------- if(!errorreported) { Werror("`%s` = `%s` is not supported" ,Tok2Cmdname(lt),Tok2Cmdname(rt)); if (BVERBOSE(V_SHOW_USE)) { i=0; while ((dAssign_sys[i].res!=lt) && (dAssign_sys[i].res!=0)) i++; while (dAssign_sys[i].res==lt) { Werror("expected `%s` = `%s`" ,Tok2Cmdname(lt),Tok2Cmdname(dAssign_sys[i].arg)); i++; } } } } return TRUE; } static BOOLEAN jiA_INTVEC_L(leftv l,leftv r) { /* right side is intvec, left side is list (of int)*/ BOOLEAN nok; int i=0; leftv l1=l; leftv h; sleftv t; intvec *iv=(intvec *)r->Data(); memset(&t,0,sizeof(sleftv)); t.rtyp=INT_CMD; while ((ilength())&&(l!=NULL)) { t.data=(char *)(long)(*iv)[i]; h=l->next; l->next=NULL; nok=jiAssign_1(l,&t,TRUE); l->next=h; if (nok) return TRUE; i++; l=h; } l1->CleanUp(); r->CleanUp(); return FALSE; } static BOOLEAN jiA_VECTOR_L(leftv l,leftv r) { /* right side is vector, left side is list (of poly)*/ BOOLEAN nok; leftv l1=l; ideal I=idVec2Ideal((poly)r->Data()); leftv h; sleftv t; int i=0; while (l!=NULL) { memset(&t,0,sizeof(sleftv)); t.rtyp=POLY_CMD; if (i>=IDELEMS(I)) { t.data=NULL; } else { t.data=(char *)I->m[i]; I->m[i]=NULL; } h=l->next; l->next=NULL; nok=jiAssign_1(l,&t,TRUE); l->next=h; t.CleanUp(); if (nok) { idDelete(&I); return TRUE; } i++; l=h; } idDelete(&I); l1->CleanUp(); r->CleanUp(); //if (TEST_V_QRING && (currRing->qideal!=NULL)) jjNormalizeQRingP(l); return FALSE; } static BOOLEAN jjA_L_LIST(leftv l, leftv r) /* left side: list/def, has to be a "real" variable * right side: expression list */ { int sl = r->listLength(); lists L=(lists)omAllocBin(slists_bin); lists oldL; leftv h=NULL,o_r=r; int i; int rt; L->Init(sl); for (i=0;inext=r; } h=r; r=r->next; h->next=NULL; rt=h->Typ(); if ((rt==0)||(rt==NONE)||(rt==DEF_CMD)) { L->Clean(); Werror("`%s` is undefined",h->Fullname()); //listall(); goto err; } //if ((rt==RING_CMD)||(rt==QRING_CMD)) //{ // L->m[i].rtyp=rt; // L->m[i].data=h->Data(); // ((ring)L->m[i].data)->ref++; //} //else L->m[i].CleanUp(); L->m[i].Copy(h); if(errorreported) { L->Clean(); goto err; } } oldL=(lists)l->Data(); if (oldL!=NULL) oldL->Clean(); if (l->rtyp==IDHDL) { IDLIST((idhdl)l->data)=L; IDTYP((idhdl)l->data)=LIST_CMD; // was possibly DEF_CMD if (lRingDependend(L)) ipMoveId((idhdl)l->data); } else { l->LData()->data=L; if ((l->e!=NULL) && (l->rtyp==DEF_CMD)) l->rtyp=LIST_CMD; } err: o_r->CleanUp(); return errorreported; } static BOOLEAN jjA_L_INTVEC(leftv l,leftv r,intvec *iv) { /* left side is intvec/intmat, right side is list (of int,intvec,intmat)*/ leftv hh=r; int i = 0; while (hh!=NULL) { if (i>=iv->length()) { if (traceit&TRACE_ASSIGN) { Warn("expression list length(%d) does not match intmat size(%d)", iv->length()+exprlist_length(hh),iv->length()); } break; } if (hh->Typ() == INT_CMD) { (*iv)[i++] = (int)((long)(hh->Data())); } else if ((hh->Typ() == INTVEC_CMD) ||(hh->Typ() == INTMAT_CMD)) { intvec *ivv = (intvec *)(hh->Data()); int ll = 0,l = si_min(ivv->length(),iv->length()); for (; l>0; l--) { (*iv)[i++] = (*ivv)[ll++]; } } else { delete iv; return TRUE; } hh = hh->next; } if (l->rtyp==IDHDL) { if (IDINTVEC((idhdl)l->data)!=NULL) delete IDINTVEC((idhdl)l->data); IDINTVEC((idhdl)l->data)=iv; } else { if (l->data!=NULL) delete ((intvec*)l->data); l->data=(char*)iv; } return FALSE; } static BOOLEAN jjA_L_BIGINTMAT(leftv l,leftv r,bigintmat *bim) { /* left side is bigintmat, right side is list (of int,intvec,intmat)*/ leftv hh=r; int i = 0; if (bim->length()==0) { WerrorS("bigintmat is 1x0"); delete bim; return TRUE; } while (hh!=NULL) { if (i>=bim->cols()*bim->rows()) { if (traceit&TRACE_ASSIGN) { Warn("expression list length(%d) does not match bigintmat size(%d x %d)", exprlist_length(hh),bim->rows(),bim->cols()); } break; } if (hh->Typ() == INT_CMD) { number tp = n_Init((int)((long)(hh->Data())), coeffs_BIGINT); bim->set(i++, tp); n_Delete(&tp, coeffs_BIGINT); } else if (hh->Typ() == BIGINT_CMD) { bim->set(i++, (number)(hh->Data())); } /* ((hh->Typ() == INTVEC_CMD) ||(hh->Typ() == INTMAT_CMD)) { intvec *ivv = (intvec *)(hh->Data()); int ll = 0,l = si_min(ivv->length(),iv->length()); for (; l>0; l--) { (*iv)[i++] = (*ivv)[ll++]; } }*/ else { delete bim; return TRUE; } hh = hh->next; } if (IDBIMAT((idhdl)l->data)!=NULL) delete IDBIMAT((idhdl)l->data); IDBIMAT((idhdl)l->data)=bim; return FALSE; } static BOOLEAN jjA_L_STRING(leftv l,leftv r) { /* left side is string, right side is list of string*/ leftv hh=r; int sl = 1; char *s; char *t; int tl; /* find the length */ while (hh!=NULL) { if (hh->Typ()!= STRING_CMD) { return TRUE; } sl += strlen((char *)hh->Data()); hh = hh->next; } s = (char * )omAlloc(sl); sl=0; hh = r; while (hh!=NULL) { t=(char *)hh->Data(); tl=strlen(t); memcpy(s+sl,t,tl); sl+=tl; hh = hh->next; } s[sl]='\0'; omFree((ADDRESS)IDDATA((idhdl)(l->data))); IDDATA((idhdl)(l->data))=s; return FALSE; } static BOOLEAN jiA_MATRIX_L(leftv l,leftv r) { /* right side is matrix, left side is list (of poly)*/ BOOLEAN nok=FALSE; int i; matrix m=(matrix)r->CopyD(MATRIX_CMD); leftv h; leftv ol=l; leftv o_r=r; sleftv t; memset(&t,0,sizeof(sleftv)); t.rtyp=POLY_CMD; int mxn=MATROWS(m)*MATCOLS(m); loop { i=0; while ((im[i]; m->m[i]=NULL; h=l->next; l->next=NULL; idhdl hh=NULL; if ((l->rtyp==IDHDL)&&(l->Typ()==DEF_CMD)) hh=(idhdl)l->data; nok=jiAssign_1(l,&t,TRUE); if (hh!=NULL) { ipMoveId(hh);hh=NULL;} l->next=h; if (nok) { idDelete((ideal *)&m); goto ende; } i++; l=h; } idDelete((ideal *)&m); h=r; r=r->next; if (l==NULL) { if (r!=NULL) { Warn("list length mismatch in assign (l>r)"); nok=TRUE; } break; } else if (r==NULL) { Warn("list length mismatch in assign (lTyp()==IDEAL_CMD)||(r->Typ()==MATRIX_CMD)) { m=(matrix)r->CopyD(MATRIX_CMD); mxn=MATROWS(m)*MATCOLS(m); } else if (r->Typ()==POLY_CMD) { m=mpNew(1,1); MATELEM(m,1,1)=(poly)r->CopyD(POLY_CMD); pNormalize(MATELEM(m,1,1)); mxn=1; } else { nok=TRUE; break; } } ende: o_r->CleanUp(); ol->CleanUp(); return nok; } static BOOLEAN jiA_STRING_L(leftv l,leftv r) { /*left side are strings, right side is a string*/ /*e.g. s[2..3]="12" */ /*the case s=t[1..4] is handled in iiAssign, * the case s[2..3]=t[3..4] is handled in iiAssgn_rec*/ BOOLEAN nok=FALSE; sleftv t; leftv h,l1=l; int i=0; char *ss; char *s=(char *)r->Data(); int sl=strlen(s); memset(&t,0,sizeof(sleftv)); t.rtyp=STRING_CMD; while ((inext; l->next=NULL; nok=jiAssign_1(l,&t,TRUE); if (nok) { break; } i++; l=h; } r->CleanUp(); l1->CleanUp(); return nok; } static BOOLEAN jiAssign_list(leftv l, leftv r) { int i=l->e->start-1; if (i<0) { Werror("index[%d] must be positive",i+1); return TRUE; } if(l->attribute!=NULL) { atKillAll((idhdl)l); l->attribute=NULL; } l->flag=0; lists li; if (l->rtyp==IDHDL) { li=IDLIST((idhdl)l->data); } else { li=(lists)l->data; } if (i>li->nr) { if (TEST_V_ALLWARN) { Warn("increase list %d -> %d in %s",li->nr,i,my_yylinebuf); } li->m=(leftv)omreallocSize(li->m,(li->nr+1)*sizeof(sleftv),(i+1)*sizeof(sleftv)); memset(&(li->m[li->nr+1]),0,(i-li->nr)*sizeof(sleftv)); int j=li->nr+1; for(;j<=i;j++) li->m[j].rtyp=DEF_CMD; li->nr=i; } leftv ld=&(li->m[i]); ld->e=l->e->next; BOOLEAN b; if (/*(ld->rtyp!=LIST_CMD) &&*/(ld->e==NULL) && (ld->Typ()!=r->Typ())) { sleftv tmp; memset(&tmp,0,sizeof(sleftv)); tmp.rtyp=DEF_CMD; b=iiAssign(&tmp,r,FALSE); ld->CleanUp(); memcpy(ld,&tmp,sizeof(sleftv)); } else if ((ld->e==NULL) && (ld->Typ()==r->Typ()) && (ld->Typ()Typ(); tmp.data=(char*)idrecDataInit(r->Typ()); b=iiAssign(&tmp,r,FALSE); ld->CleanUp(); memcpy(ld,&tmp,sizeof(sleftv)); } else { b=iiAssign(ld,r,FALSE); if (l->e!=NULL) l->e->next=ld->e; ld->e=NULL; } return b; } static BOOLEAN jiAssign_rec(leftv l, leftv r) { leftv l1=l; leftv r1=r; leftv lrest; leftv rrest; BOOLEAN b; do { lrest=l->next; rrest=r->next; l->next=NULL; r->next=NULL; b=iiAssign(l,r); l->next=lrest; r->next=rrest; l=lrest; r=rrest; } while ((!b)&&(l!=NULL)); l1->CleanUp(); r1->CleanUp(); return b; } BOOLEAN iiAssign(leftv l, leftv r, BOOLEAN toplevel) { if (errorreported) return TRUE; int ll=l->listLength(); int rl; int lt=l->Typ(); int rt=NONE; BOOLEAN b; if (l->rtyp==ALIAS_CMD) { Werror("`%s` is read-only",l->Name()); } if (l->rtyp==IDHDL) { atKillAll((idhdl)l->data); IDFLAG((idhdl)l->data)=0; l->attribute=NULL; toplevel=FALSE; } else if (l->attribute!=NULL) atKillAll((idhdl)l); l->flag=0; if (ll==1) { /* l[..] = ... */ if(l->e!=NULL) { BOOLEAN like_lists=0; blackbox *bb=NULL; int bt; if (((bt=l->rtyp)>MAX_TOK) || ((l->rtyp==IDHDL) && ((bt=IDTYP((idhdl)l->data))>MAX_TOK))) { bb=getBlackboxStuff(bt); like_lists=BB_LIKE_LIST(bb); // bb like a list } else if (((l->rtyp==IDHDL) && (IDTYP((idhdl)l->data)==LIST_CMD)) || (l->rtyp==LIST_CMD)) { like_lists=2; // bb in a list } if(like_lists) { if (traceit&TRACE_ASSIGN) PrintS("assign list[..]=...or similar\n"); if (like_lists==1) { // check blackbox/newtype type: if(bb->blackbox_CheckAssign(bb,l,r)) return TRUE; } b=jiAssign_list(l,r); if((!b) && (like_lists==2)) { //Print("jjA_L_LIST: - 2 \n"); if((l->rtyp==IDHDL) && (l->data!=NULL)) { ipMoveId((idhdl)l->data); l->attribute=IDATTR((idhdl)l->data); l->flag=IDFLAG((idhdl)l->data); } } r->CleanUp(); Subexpr h; while (l->e!=NULL) { h=l->e->next; omFreeBin((ADDRESS)l->e, sSubexpr_bin); l->e=h; } return b; } } if (lt>MAX_TOK) { blackbox *bb=getBlackboxStuff(lt); #ifdef BLACKBOX_DEVEL Print("bb-assign: bb=%lx\n",bb); #endif return (bb==NULL) || bb->blackbox_Assign(l,r); } // end of handling elems of list and similar rl=r->listLength(); if (rl==1) { /* system variables = ... */ if(((l->rtyp>=VECHO)&&(l->rtyp<=VPRINTLEVEL)) ||((l->rtyp>=VALTVARS)&&(l->rtyp<=VMINPOLY))) { b=iiAssign_sys(l,r); r->CleanUp(); //l->CleanUp(); return b; } rt=r->Typ(); /* a = ... */ if ((lt!=MATRIX_CMD) &&(lt!=BIGINTMAT_CMD) &&(lt!=CMATRIX_CMD) &&(lt!=INTMAT_CMD) &&((lt==rt)||(lt!=LIST_CMD))) { b=jiAssign_1(l,r,toplevel); if (l->rtyp==IDHDL) { if ((lt==DEF_CMD)||(lt==LIST_CMD)) { ipMoveId((idhdl)l->data); } l->attribute=IDATTR((idhdl)l->data); l->flag=IDFLAG((idhdl)l->data); l->CleanUp(); } r->CleanUp(); return b; } if (((lt!=LIST_CMD) &&((rt==MATRIX_CMD) ||(rt==BIGINTMAT_CMD) ||(rt==CMATRIX_CMD) ||(rt==INTMAT_CMD) ||(rt==INTVEC_CMD) ||(rt==MODUL_CMD))) ||((lt==LIST_CMD) &&(rt==RESOLUTION_CMD)) ) { b=jiAssign_1(l,r,toplevel); if((l->rtyp==IDHDL)&&(l->data!=NULL)) { if ((lt==DEF_CMD) || (lt==LIST_CMD)) { //Print("ipAssign - 3.0\n"); ipMoveId((idhdl)l->data); } l->attribute=IDATTR((idhdl)l->data); l->flag=IDFLAG((idhdl)l->data); } r->CleanUp(); Subexpr h; while (l->e!=NULL) { h=l->e->next; omFreeBin((ADDRESS)l->e, sSubexpr_bin); l->e=h; } return b; } } if (rt==NONE) rt=r->Typ(); } else if (ll==(rl=r->listLength())) { b=jiAssign_rec(l,r); return b; } else { if (rt==NONE) rt=r->Typ(); if (rt==INTVEC_CMD) return jiA_INTVEC_L(l,r); else if (rt==VECTOR_CMD) return jiA_VECTOR_L(l,r); else if ((rt==IDEAL_CMD)||(rt==MATRIX_CMD)) return jiA_MATRIX_L(l,r); else if ((rt==STRING_CMD)&&(rl==1)) return jiA_STRING_L(l,r); Werror("length of lists in assignment does not match (l:%d,r:%d)", ll,rl); return TRUE; } leftv hh=r; BOOLEAN nok=FALSE; BOOLEAN map_assign=FALSE; switch (lt) { case INTVEC_CMD: nok=jjA_L_INTVEC(l,r,new intvec(exprlist_length(r))); break; case INTMAT_CMD: { nok=jjA_L_INTVEC(l,r,new intvec(IDINTVEC((idhdl)l->data))); break; } case BIGINTMAT_CMD: { nok=jjA_L_BIGINTMAT(l, r, new bigintmat(IDBIMAT((idhdl)l->data))); break; } case MAP_CMD: { // first element in the list sl (r) must be a ring if (((rt == RING_CMD)||(rt == QRING_CMD))&&(r->e==NULL)) { omFree((ADDRESS)IDMAP((idhdl)l->data)->preimage); IDMAP((idhdl)l->data)->preimage = omStrDup (r->Fullname()); /* advance the expressionlist to get the next element after the ring */ hh = r->next; //r=hh; } else { WerrorS("expected ring-name"); nok=TRUE; break; } if (hh==NULL) /* map-assign: map f=r; */ { WerrorS("expected image ideal"); nok=TRUE; break; } if ((hh->next==NULL)&&(hh->Typ()==IDEAL_CMD)) return jiAssign_1(l,hh,toplevel); /* map-assign: map f=r,i; */ //no break, handle the rest like an ideal: map_assign=TRUE; } case MATRIX_CMD: case IDEAL_CMD: case MODUL_CMD: { sleftv t; matrix olm = (matrix)l->Data(); int rk; char *pr=((map)olm)->preimage; BOOLEAN module_assign=(/*l->Typ()*/ lt==MODUL_CMD); matrix lm ; int num; int j,k; int i=0; int mtyp=MATRIX_CMD; /*Type of left side object*/ int etyp=POLY_CMD; /*Type of elements of left side object*/ if (lt /*l->Typ()*/==MATRIX_CMD) { rk=olm->rows(); num=olm->cols()*rk /*olm->rows()*/; lm=mpNew(olm->rows(),olm->cols()); int el; if ((traceit&TRACE_ASSIGN) && (num!=(el=exprlist_length(hh)))) { Warn("expression list length(%d) does not match matrix size(%d)",el,num); } } else /* IDEAL_CMD or MODUL_CMD */ { num=exprlist_length(hh); lm=(matrix)idInit(num,1); if (module_assign) { rk=0; mtyp=MODUL_CMD; etyp=VECTOR_CMD; } else rk=1; } int ht; loop { if (hh==NULL) break; else { matrix rm; ht=hh->Typ(); if ((j=iiTestConvert(ht,etyp))!=0) { nok=iiConvert(ht,etyp,j,hh,&t); hh->next=t.next; if (nok) break; lm->m[i]=(poly)t.CopyD(etyp); pNormalize(lm->m[i]); if (module_assign) rk=si_max(rk,(int)pMaxComp(lm->m[i])); i++; } else if ((j=iiTestConvert(ht,mtyp))!=0) { nok=iiConvert(ht,mtyp,j,hh,&t); hh->next=t.next; if (nok) break; rm = (matrix)t.CopyD(mtyp); if (module_assign) { j = si_min(num,rm->cols()); rk=si_max(rk,(int)rm->rank); } else j = si_min(num-i,rm->rows() * rm->cols()); for(k=0;km[i]=rm->m[k]; pNormalize(lm->m[i]); rm->m[k]=NULL; } idDelete((ideal *)&rm); } else { nok=TRUE; break; } t.next=NULL;t.CleanUp(); if (i==num) break; hh=hh->next; } } if (nok) idDelete((ideal *)&lm); else { idDelete((ideal *)&olm); if (module_assign) lm->rank=rk; else if (map_assign) ((map)lm)->preimage=pr; l=l->LData(); if (l->rtyp==IDHDL) IDMATRIX((idhdl)l->data)=lm; else l->data=(char *)lm; } break; } case STRING_CMD: nok=jjA_L_STRING(l,r); break; //case DEF_CMD: case LIST_CMD: nok=jjA_L_LIST(l,r); break; case NONE: case 0: Werror("cannot assign to %s",l->Fullname()); nok=TRUE; break; default: WerrorS("assign not impl."); nok=TRUE; break; } /* end switch: typ */ if (nok && (!errorreported)) WerrorS("incompatible type in list assignment"); r->CleanUp(); return nok; } void jjNormalizeQRingId(leftv I) { if ((currRing->qideal!=NULL) && (!hasFlag(I,FLAG_QRING))) { if (I->e==NULL) { ideal I0=(ideal)I->Data(); switch (I->Typ()) { case IDEAL_CMD: case MODUL_CMD: { ideal F=idInit(1,1); ideal II=kNF(F,currRing->qideal,I0); idDelete(&F); if (I->rtyp!=IDHDL) { idDelete((ideal*)&(I0)); I->data=II; } else { idhdl h=(idhdl)I->data; idDelete((ideal*)&IDIDEAL(h)); IDIDEAL(h)=II; setFlag(h,FLAG_QRING); } break; } default: break; } setFlag(I,FLAG_QRING); } } } void jjNormalizeQRingP(poly &p) { if((p!=NULL) && (currRing->qideal!=NULL)) { ideal F=idInit(1,1); poly p2=kNF(F,currRing->qideal,p); pNormalize(p2); idDelete(&F); pDelete(&p); p=p2; } } BOOLEAN jjIMPORTFROM(leftv, leftv u, leftv v) { //Print("importfrom %s::%s ->.\n",v->Name(),u->Name() ); assume(u->Typ()==PACKAGE_CMD); char *vn=(char *)v->Name(); idhdl h=((package)(u->Data()))->idroot->get(vn /*v->Name()*/, myynest); if (h!=NULL) { //check for existence if (((package)(u->Data()))==basePack) { WarnS("source and destination packages are identical"); return FALSE; } idhdl t=basePack->idroot->get(vn /*v->Name()*/, myynest); if (t!=NULL) { Warn("redefining `%s`",vn); killhdl(t); } sleftv tmp_expr; if (iiDeclCommand(&tmp_expr,v,myynest,DEF_CMD,&IDROOT)) return TRUE; sleftv h_expr; memset(&h_expr,0,sizeof(h_expr)); h_expr.rtyp=IDHDL; h_expr.data=h; h_expr.name=vn; return iiAssign(&tmp_expr,&h_expr); } else { Werror("`%s` not found in `%s`",v->Name(), u->Name()); return TRUE; } return FALSE; } singular-4.0.3+ds/Singular/ipconv.cc000066400000000000000000000263531266270727000173570ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: automatic type conversions */ #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include #include typedef void * (*iiConvertProc)(void * data); typedef void (*iiConvertProcL)(leftv out,leftv in); struct sConvertTypes { int i_typ; int o_typ; iiConvertProc p; iiConvertProcL pl; }; // all of these static conversion routines work destructive on their input static void * iiI2P(void *data) { poly p=pISet((int)(long)data); return (void *)p; } static void * iiBI2P(void *data) { nMapFunc nMap=n_SetMap(coeffs_BIGINT,currRing->cf); if (nMap==NULL) { Werror("no conversion from bigint to %s", nCoeffString(currRing->cf)); return NULL; } number n=nMap((number)data,coeffs_BIGINT,currRing->cf); n_Delete((number *)&data, coeffs_BIGINT); poly p=p_NSet(n, currRing); return (void *)p; } static void * iiI2V(void *data) { poly p=pISet((int)(long)data); if (p!=NULL) pSetComp(p,1); return (void *)p; } static void * iiBI2V(void *data) { nMapFunc nMap=n_SetMap(coeffs_BIGINT,currRing->cf); if (nMap==NULL) { Werror("no conversion from bigint to %s", nCoeffString(currRing->cf)); return NULL; } number n=nMap((number)data,coeffs_BIGINT,currRing->cf); n_Delete((number *)&data, coeffs_BIGINT); poly p=p_NSet(n, currRing); if (p!=NULL) pSetComp(p,1); return (void *)p; } static void * iiI2Id(void *data) { ideal I=idInit(1,1); I->m[0]=pISet((int)(long)data); return (void *)I; } static void * iiBI2Id(void *data) { ideal I=idInit(1,1); nMapFunc nMap=n_SetMap(coeffs_BIGINT,currRing->cf); if (nMap==NULL) { Werror("no conversion from bigint to %s", nCoeffString(currRing->cf)); return NULL; } number n=nMap((number)data,coeffs_BIGINT,currRing->cf); n_Delete((number *)&data,coeffs_BIGINT); poly p=pNSet(n); I->m[0]=p; return (void *)I; } static void * iiP2V(void *data) { poly p=(poly)data; if (p!=NULL) pSetCompP(p,1); return (void *)p; } static void * iiP2Id(void *data) { ideal I=idInit(1,1); if (data!=NULL) { poly p=(poly)data; I->m[0]=p; if (pGetComp(p)!=0) I->rank=pMaxComp(p); } return (void *)I; } static void * iiV2Ma(void *data) { matrix m=(matrix)idVec2Ideal((poly)data); int h=MATCOLS(m); MATCOLS(m)=MATROWS(m); MATROWS(m)=h; m->rank=h; pDelete((poly *)&data); return (void *)m; } static void * iiN2P(void *data); static void * iiDummy(void *data) { return data; } static void * iiMo2Ma(void *data) { void *res=id_Module2Matrix((ideal)data,currRing); return res; } static void * iiMa2Mo(void *data) { void *res=id_Matrix2Module((matrix)data,currRing); return res; } static void * iiI2Iv(void *data) { int s=(int)(long)data; intvec *iv=new intvec(s,s); return (void *)iv; } static void * iiI2N(void *data) { number n=nInit((int)(long)data); return (void *)n; } static void * iiI2BI(void *data) { number n=n_Init((int)(long)data, coeffs_BIGINT); return (void *)n; } #ifdef SINGULAR_4_1 static void * iiI2NN(void *data) { if (currRing==NULL) { WerrorS("missing basering while converting int to Number"); return NULL; } number n=nInit((int)(long)data); number2 nn=(number2)omAlloc(sizeof*nn); nn->cf=currRing->cf; nn->cf->ref++; nn->n=n; return (void *)nn; } #endif static void * iiBI2N(void *data) { if (currRing==NULL) return NULL; nMapFunc nMap=n_SetMap(coeffs_BIGINT,currRing->cf); if (nMap==NULL) { Werror("no conversion from bigint to %s", nCoeffString(currRing->cf)); return NULL; } number n=nMap((number)data,coeffs_BIGINT,currRing->cf); n_Delete((number *)&data, coeffs_BIGINT); return (void*)n; } #ifdef SINGULAR_4_1 static void * iiBI2NN(void *data) { if (currRing==NULL) { WerrorS("missing basering while converting bigint to Number"); return NULL; } nMapFunc nMap=n_SetMap(coeffs_BIGINT,currRing->cf); if (nMap==NULL) { Werror("no conversion from bigint to %s",currRing->cf->cfCoeffString(currRing->cf)); return NULL; } number n=nMap((number)data,coeffs_BIGINT,currRing->cf); n_Delete((number *)&data, coeffs_BIGINT); number2 nn=(number2)omAlloc(sizeof*nn); nn->cf=currRing->cf; nn->cf->ref++; return (void*)nn; } #endif #ifdef SINGULAR_4_1 static void * iiNN2N(void *data) { number2 d=(number2)data; if ((currRing==NULL) || (currRing->cf!=d->cf)) { WerrorS("cannot convert: incompatible"); return NULL; } number n = n_Copy(d->n, d->cf); n2Delete(d); return (void*)n; } #endif #ifdef SINGULAR_4_1 static void * iiNN2P(void *data) { number2 d=(number2)data; if ((currRing==NULL) || (currRing->cf!=d->cf)) { WerrorS("cannot convert: incompatible"); return NULL; } number n = n_Copy(d->n, d->cf); n2Delete(d); return (void*)p_NSet(n,currRing); } #endif static void * iiIm2Ma(void *data) { int i, j; intvec *iv = (intvec *)data; matrix m = mpNew(iv->rows(), iv->cols()); for (i=iv->rows(); i>0; i--) { for (j=iv->cols(); j>0; j--) { MATELEM(m, i, j) = pISet(IMATELEM(*iv, i, j)); } } delete iv; return (void *)m; } static void * iiIm2Bim(void *data) { intvec *iv=(intvec*)data; void *r=(void *)iv2bim(iv,coeffs_BIGINT); delete iv; return r; } static void * iiN2P(void *data) { poly p=NULL; if (!nIsZero((number)data)) { p=pNSet((number)data); } //else //{ // nDelete((number *)&data); //} return (void *)p; } static void * iiN2Ma(void *data) { ideal I=idInit(1,1); if (!nIsZero((number)data)) { poly p=pNSet((number)data); I->m[0]=p; } //else //{ // nDelete((number *)&data); //} return (void *)I; } static void * iiS2Link(void *data) { si_link l=(si_link)omAlloc0Bin(ip_link_bin); slInit(l, (char *) data); omFree((ADDRESS)data); return (void *)l; } /* static void * iiR2L(void * data) { syStrategy tmp=(syStrategy)data; return (void *)syConvRes(tmp,TRUE); } */ static void iiR2L_l(leftv out, leftv in) { int add_row_shift = 0; intvec *weights=(intvec*)atGet(in,"isHomog",INTVEC_CMD); if (weights!=NULL) add_row_shift=weights->min_in(); syStrategy tmp=(syStrategy)in->CopyD(); out->data=(void *)syConvRes(tmp,TRUE,add_row_shift); } static void * iiL2R(void * data) { return (void *)syConvList((lists)data,TRUE); } // // automatic conversions: // #define IPCONV #define D(A) A #define NULL_VAL NULL #include /*2 * try to convert 'input' of type 'inputType' to 'output' of type 'outputType' * return FALSE on success */ BOOLEAN iiConvert (int inputType, int outputType, int index, leftv input, leftv output,struct sConvertTypes *dConvertTypes) { memset(output,0,sizeof(sleftv)); if ((inputType==outputType) || (outputType==DEF_CMD) || ((outputType==IDHDL)&&(input->rtyp==IDHDL))) { memcpy(output,input,sizeof(*output)); memset(input,0,sizeof(*input)); return FALSE; } else if (outputType==ANY_TYPE) { output->rtyp=ANY_TYPE; output->data=(char *)(long)input->Typ(); /* the name of the object:*/ if (input->e==NULL) { if (input->rtyp==IDHDL) /* preserve name: copy it */ output->name=omStrDup(IDID((idhdl)(input->data))); else if (input->name!=NULL) { if (input->rtyp==ALIAS_CMD) output->name=omStrDup(input->name); else { output->name=input->name; input->name=NULL; } } else if ((input->rtyp==POLY_CMD) && (input->name==NULL)) { if (input->data!=NULL) { int nr=pIsPurePower((poly)input->data); if (nr!=0) { if (pGetExp((poly)input->data,nr)==1) { output->name=omStrDup(currRing->names[nr-1]); } else { char *tmp=(char *)omAlloc(4); sprintf(tmp,"%c%d",*(currRing->names[nr-1]), (int)pGetExp((poly)input->data,nr)); output->name=tmp; } } else if(pIsConstant((poly)input->data)) { StringSetS(""); number n=(pGetCoeff((poly)input->data)); n_Write(n, currRing->cf); (pGetCoeff((poly)input->data))=n; output->name=StringEndS(); } } } else if ((input->rtyp==NUMBER_CMD) && (input->name==NULL)) { StringSetS(""); number n=(number)input->data; n_Write(n, currRing->cf); input->data=(void*)n; output->name=StringEndS(); } else { /* no need to preserve name: use it */ output->name=input->name; memset(input,0,sizeof(*input)); } } output->next=input->next; input->next=NULL; return errorreported; } if (index!=0) /* iiTestConvert does not returned 'failure' */ { index--; if((dConvertTypes[index].i_typ==inputType) &&(dConvertTypes[index].o_typ==outputType)) { if(traceit&TRACE_CONV) { Print("automatic conversion %s -> %s\n", Tok2Cmdname(inputType),Tok2Cmdname(outputType)); } if ((currRing==NULL) && (outputType>BEGIN_RING) && (outputTypertyp=outputType; if (dConvertTypes[index].p!=NULL) { output->data=dConvertTypes[index].p(input->CopyD()); } else { dConvertTypes[index].pl(output,input); } if ((output->data==NULL) && ((outputType!=INT_CMD) &&(outputType!=POLY_CMD) &&(outputType!=VECTOR_CMD) &&(outputType!=NUMBER_CMD))) { return TRUE; } if (errorreported) return TRUE; output->next=input->next; input->next=NULL; //if (outputType==MATRIX_CMD) Print("convert %d -> matrix\n",inputType); return FALSE; } } return TRUE; } /*2 * try to convert 'inputType' in 'outputType' * return 0 on failure, an index (<>0) on success */ int iiTestConvert (int inputType, int outputType,struct sConvertTypes *dConvertTypes) { if ((inputType==outputType) || (outputType==DEF_CMD) || (outputType==IDHDL) || (outputType==ANY_TYPE)) { return -1; } if ((currRing==NULL) && (outputType>BEGIN_RING) && (outputType %s):%d\n",inputType,outputType, //Tok2Cmdname(inputType), Tok2Cmdname(outputType),i+1); return i+1; } i++; } //Print("test convert %d to %d (%s -> %s):0, tested:%d\n",inputType,outputType, // Tok2Cmdname(inputType), Tok2Cmdname(outputType),i); return 0; } singular-4.0.3+ds/Singular/ipconv.h000066400000000000000000000010101266270727000172000ustar00rootroot00000000000000#ifndef IPCONVERT_H #define IPCONVERT_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: interpreter: converting types */ #include #include int iiTestConvert (int inputType, int outputType, struct sConvertTypes *dCT=dConvertTypes); BOOLEAN iiConvert (int inputType, int outputType, int index, leftv input, leftv output, struct sConvertTypes *dCT=dConvertTypes); #endif singular-4.0.3+ds/Singular/ipid.cc000066400000000000000000000442301266270727000170000ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: identfier handling */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SINGULAR_4_1 #include #endif #ifdef HAVE_DYNAMIC_LOADING #include #endif /* HAVE_DYNAMIC_LOADING */ #include omBin sip_command_bin = omGetSpecBin(sizeof(sip_command)); omBin sip_package_bin = omGetSpecBin(sizeof(sip_package)); //omBin ip_package_bin = omGetSpecBin(sizeof(ip_package)); omBin idrec_bin = omGetSpecBin(sizeof(idrec)); coeffs coeffs_BIGINT; FILE *feFilePending; /*temp. storage for grammar.y */ proclevel *procstack=NULL; //idhdl idroot = NULL; idhdl currPackHdl = NULL; idhdl basePackHdl = NULL; package currPack =NULL; package basePack =NULL; idhdl currRingHdl = NULL; const char* iiNoName="_"; void paCleanUp(package pack); /*0 implementation*/ int iiS2I(const char *s) { int i; i=s[0]; if (s[1]!='\0') { i=(i<<8)+s[1]; if (s[2]!='\0') { i=(i<<8)+s[2]; if (s[3]!='\0') { i=(i<<8)+s[3]; } } } return i; } idhdl idrec::get(const char * s, int level) { assume(s!=NULL); assume((level>=0) && (level<=1000)); //not really, but if it isnt in that bounds.. idhdl h = this; idhdl found=NULL; int l; const char *id_; int i=iiS2I(s); int less4=(i < (1<<24)); while (h!=NULL) { omCheckAddr((ADDRESS)IDID(h)); l=IDLEV(h); if ((l==0)||(l==level)) { if (i==h->id_i) { id_=IDID(h); if (less4 || (0 == strcmp(s+4,id_+4))) { if (l==level) return h; found=h; } } } h = IDNEXT(h); } return found; } //idrec::~idrec() //{ // if (id!=NULL) // { // omFree((ADDRESS)id); // id=NULL; // } // /* much more !! */ //} void *idrecDataInit(int t) { switch (t) { //the type with init routines: #ifdef SINGULAR_4_1 case CNUMBER_CMD: return (void*)n2Init(0,NULL); case CMATRIX_CMD: #endif case BIGINTMAT_CMD: return (void *)new bigintmat(); case INTVEC_CMD: case INTMAT_CMD: return (void *)new intvec(); case NUMBER_CMD: return (void *) nInit(0); case BIGINT_CMD: return (void *) n_Init(0, coeffs_BIGINT); case IDEAL_CMD: case MODUL_CMD: case MATRIX_CMD: return (void*) idInit(1,1); case MAP_CMD: { map m = (map)idInit(1,1); m->preimage = omStrDup(IDID(currRingHdl)); return (void *)m; } case STRING_CMD: return (void *)omAlloc0(1); case LIST_CMD: { lists l=(lists)omAllocBin(slists_bin); l->Init(); return (void*)l; } //the types with the standard init: set the struct to zero case LINK_CMD: return (void*) omAlloc0Bin(sip_link_bin); case RING_CMD: return (void*) omAlloc0Bin(sip_sring_bin); case PACKAGE_CMD: { package pa=(package)omAlloc0Bin(sip_package_bin); pa->language=LANG_NONE; pa->loaded = FALSE; return (void*)pa; } case PROC_CMD: { procinfov pi=(procinfov)omAlloc0Bin(procinfo_bin); pi->ref=1; pi->language=LANG_NONE; return (void*)pi; } case RESOLUTION_CMD: return (void *)omAlloc0(sizeof(ssyStrategy)); //other types: without init (int,script,poly,def,package) #ifdef SINGULAR_4_1 case CRING_CMD: #endif case INT_CMD: case DEF_CMD: case POLY_CMD: case VECTOR_CMD: case QRING_CMD: return (void*)0L; default: { if (t>MAX_TOK) { #ifdef BLACKBOX_DEVEL Print("bb-type %d\n",t); #endif blackbox *bb=getBlackboxStuff(t); if (bb!=NULL) return (void *)bb->blackbox_Init(bb); } else Werror("unknown type in idrecDataInit:%d",t); break; } } return (void *)0L; } idhdl idrec::set(const char * s, int level, int t, BOOLEAN init) { //printf("define %s, %x, level: %d, typ: %d\n", s,s,level,t); idhdl h = (idrec *)omAlloc0Bin(idrec_bin); IDID(h) = s; IDTYP(h) = t; IDLEV(h) = level; IDNEXT(h) = this; BOOLEAN at_start=(this==IDROOT); h->id_i=iiS2I(s); if (init) { if ((t==IDEAL_CMD)||(t==MODUL_CMD)) IDFLAG(h) = Sy_bit(FLAG_STD); IDSTRING(h)=(char *)idrecDataInit(t); // additional settings:-------------------------------------- #if 0 // this leads to a memory leak if (t == QRING_CMD) { // IDRING(h)=rCopy(currRing); /* QRING_CMD is ring dep => currRing !=NULL */ } #endif } // -------------------------------------------------------- if (at_start) IDNEXT(h) = IDROOT; return h; } char * idrec::String(BOOLEAN typed) { sleftv tmp; memset(&tmp,0,sizeof(sleftv)); tmp.rtyp=IDTYP(this); tmp.data=IDDATA(this); tmp.name=IDID(this); return tmp.String(NULL, typed); } idhdl enterid(const char * s, int lev, int t, idhdl* root, BOOLEAN init, BOOLEAN search) { if (s==NULL) return NULL; if (root==NULL) return NULL; idhdl h; s=omStrDup(s); // idhdl *save_root=root; if (t==PACKAGE_CMD) { if (root!=&(basePack->idroot)) { root=&(basePack->idroot); } } // is it already defined in root ? if ((h=(*root)->get(s,lev))!=NULL) { if (IDLEV(h)==lev) { if ((IDTYP(h) == t)||(t==DEF_CMD)) { if ((IDTYP(h)==PACKAGE_CMD) && (strcmp(s,"Top")==0)) { goto errlabel; } if (BVERBOSE(V_REDEFINE)) Warn("redefining %s **",s); if (s==IDID(h)) IDID(h)=NULL; killhdl2(h,root,currRing); } else goto errlabel; } } // is it already defined in currRing->idroot ? else if (search && (currRing!=NULL)&&((*root) != currRing->idroot)) { if ((h=currRing->idroot->get(s,lev))!=NULL) { if (IDLEV(h)==lev) { if ((IDTYP(h) == t)||(t==DEF_CMD)) { if (BVERBOSE(V_REDEFINE)) Warn("redefining %s **",s); if (s==IDID(h)) IDID(h)=NULL; killhdl2(h,&currRing->idroot,currRing); } else goto errlabel; } } } // is it already defined in idroot ? else if (search && (*root != IDROOT)) { if ((h=IDROOT->get(s,lev))!=NULL) { if (IDLEV(h)==lev) { if ((IDTYP(h) == t)||(t==DEF_CMD)) { if (BVERBOSE(V_REDEFINE)) Warn("redefining `%s` **",s); if (s==IDID(h)) IDID(h)=NULL; killhdl2(h,&IDROOT,NULL); } else goto errlabel; } } } *root = (*root)->set(s, lev, t, init); #ifndef SING_NDEBUG checkall(); #endif return *root; errlabel: //Werror("identifier `%s` in use(lev h=%d,typ=%d,t=%d, curr=%d)",s,IDLEV(h),IDTYP(h),t,lev); Werror("identifier `%s` in use",s); //listall(); omFree((ADDRESS)s); return NULL; } void killid(const char * id, idhdl * ih) { if (id!=NULL) { idhdl h = (*ih)->get(id,myynest); // id not found in global list, is it defined in current ring ? if (h==NULL) { if ((currRing!=NULL) && (*ih != (currRing->idroot))) { h = currRing->idroot->get(id,myynest); if (h!=NULL) { killhdl2(h,&(currRing->idroot),currRing); return; } } Werror("`%s` is not defined",id); return; } killhdl2(h,ih,currRing); } else Werror("kill what ?"); } void killhdl(idhdl h, package proot) { int t=IDTYP(h); if (((BEGIN_RINGidroot,currRing); else { if(t==PACKAGE_CMD) { killhdl2(h,&(basePack->idroot),NULL); } else { idhdl s=proot->idroot; while ((s!=h) && (s!=NULL)) s=s->next; if (s!=NULL) killhdl2(h,&(proot->idroot),NULL); else if (basePack!=proot) { idhdl s=basePack->idroot; while ((s!=h) && (s!=NULL)) s=s->next; if (s!=NULL) killhdl2(h,&(basePack->idroot),currRing); else killhdl2(h,&(currRing->idroot),currRing); } } } } void killhdl2(idhdl h, idhdl * ih, ring r) { //printf("kill %s, id %x, typ %d lev: %d\n",IDID(h),(int)IDID(h),IDTYP(h),IDLEV(h)); idhdl hh; if (TEST_V_ALLWARN && (IDLEV(h)!=myynest) &&(IDLEV(h)==0)) { if (((*ih)==basePack->idroot) || ((currRing!=NULL)&&((*ih)==currRing->idroot))) Warn("kill global `%s` at line >>%s<<\n",IDID(h),my_yylinebuf); } if (h->attribute!=NULL) { //h->attribute->killAll(r); MEMORY LEAK! h->attribute=NULL; } if (IDTYP(h) == PACKAGE_CMD) { if (strcmp(IDID(h),"Top")==0) { WarnS("can not kill `Top`"); return; } // any objects defined for this package ? if ((IDPACKAGE(h)->ref<=0) && (IDPACKAGE(h)->idroot!=NULL)) { if (currPack==IDPACKAGE(h)) { currPack=basePack; currPackHdl=NULL; } idhdl * hd = &IDRING(h)->idroot; idhdl hdh = IDNEXT(*hd); idhdl temp; while (hdh!=NULL) { temp = IDNEXT(hdh); killhdl2(hdh,&(IDPACKAGE(h)->idroot),NULL); hdh = temp; } killhdl2(*hd,hd,NULL); if (IDPACKAGE(h)->libname!=NULL) omFree((ADDRESS)(IDPACKAGE(h)->libname)); } paKill(IDPACKAGE(h)); if (currPackHdl==h) currPackHdl=packFindHdl(currPack); iiCheckPack(currPack); } else if ((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD)) rKill(h); else if (IDDATA(h)!=NULL) s_internalDelete(IDTYP(h),IDDATA(h),r); // general ------------------------------------------------------------- // now dechain it and delete idrec if (IDID(h)!=NULL) // OB: ????? omFree((ADDRESS)IDID(h)); IDID(h)=NULL; IDDATA(h)=NULL; if (h == (*ih)) { // h is at the beginning of the list *ih = IDNEXT(h) /* ==*ih */; } else if (ih!=NULL) { // h is somethere in the list: hh = *ih; loop { if (hh==NULL) { PrintS(">>?<< not found for kill\n"); return; } idhdl hhh = IDNEXT(hh); if (hhh == h) { IDNEXT(hh) = IDNEXT(hhh); break; } hh = hhh; } } omFreeBin((ADDRESS)h, idrec_bin); } idhdl ggetid(const char *n, BOOLEAN /*local*/, idhdl *packhdl) { idhdl h = IDROOT->get(n,myynest); idhdl h2=NULL; *packhdl = NULL; if ((currRing!=NULL) && ((h==NULL)||(IDLEV(h)!=myynest))) { h2 = currRing->idroot->get(n,myynest); } if (h2==NULL) return h; return h2; } idhdl ggetid(const char *n) { idhdl h = IDROOT->get(n,myynest); if ((h!=NULL)&&(IDLEV(h)==myynest)) return h; idhdl h2=NULL; if (currRing!=NULL) { h2 = currRing->idroot->get(n,myynest); } if (h2!=NULL) return h2; if (h!=NULL) return h; if (basePack!=currPack) return basePack->idroot->get(n,myynest); return NULL; } void ipListFlag(idhdl h) { if (hasFlag(h,FLAG_STD)) PrintS(" (SB)"); #ifdef HAVE_PLURAL if (hasFlag(h,FLAG_TWOSTD)) PrintS(" (2SB)"); #endif } lists ipNameList(idhdl root) { idhdl h=root; /* compute the length */ int l=0; while (h!=NULL) { l++; h=IDNEXT(h); } /* allocate list */ lists L=(lists)omAllocBin(slists_bin); L->Init(l); /* copy names */ h=root; l=0; while (h!=NULL) { /* list is initialized with 0 => no need to clear anything */ L->m[l].rtyp=STRING_CMD; L->m[l].data=omStrDup(IDID(h)); l++; h=IDNEXT(h); } return L; } lists ipNameListLev(idhdl root, int lev) { idhdl h=root; /* compute the length */ int l=0; while (h!=NULL) { if (IDLEV(h)==lev) l++; h=IDNEXT(h); } /* allocate list */ lists L=(lists)omAllocBin(slists_bin); L->Init(l); /* copy names */ h=root; l=0; while (h!=NULL) { if (IDLEV(h)==lev) { /* list is initialized with 0 => no need to clear anything */ L->m[l].rtyp=STRING_CMD; L->m[l].data=omStrDup(IDID(h)); l++; } h=IDNEXT(h); } return L; } /* * move 'tomove' from root1 list to root2 list */ static int ipSwapId(idhdl tomove, idhdl &root1, idhdl &root2) { idhdl h; /* search 'tomove' in root2 : if found -> do nothing */ h=root2; while ((h!=NULL) && (h!=tomove)) h=IDNEXT(h); if (h!=NULL) return FALSE; /*okay */ /* search predecessor of h in root1, remove 'tomove' */ h=root1; if (tomove==h) { root1=IDNEXT(h); } else { while ((h!=NULL) && (IDNEXT(h)!=tomove)) h=IDNEXT(h); if (h==NULL) return TRUE; /* not in the list root1 -> do nothing */ IDNEXT(h)=IDNEXT(tomove); } /* add to root2 list */ IDNEXT(tomove)=root2; root2=tomove; return FALSE; } void ipMoveId(idhdl tomove) { if ((currRing!=NULL)&&(tomove!=NULL)) { if (((QRING_CMD!=IDTYP(tomove)) && RingDependend(IDTYP(tomove))) || ((IDTYP(tomove)==LIST_CMD) && (lRingDependend(IDLIST(tomove))))) { /*move 'tomove' to ring id's*/ if (ipSwapId(tomove,IDROOT,currRing->idroot)) ipSwapId(tomove,basePack->idroot,currRing->idroot); } else { /*move 'tomove' to global id's*/ ipSwapId(tomove,currRing->idroot,IDROOT); } } } const char * piProcinfo(procinfov pi, const char *request) { if((pi == NULL)||(pi->language==LANG_NONE)) return "empty proc"; else if (strcmp(request, "libname") == 0) return pi->libname; else if (strcmp(request, "procname") == 0) return pi->procname; else if (strcmp(request, "type") == 0) { switch (pi->language) { case LANG_SINGULAR: return "singular"; break; case LANG_C: return "object"; break; case LANG_NONE: return "none"; break; default: return "unknow language"; } } else if (strcmp(request, "ref") == 0) { char p[8]; sprintf(p, "%d", pi->ref); return omStrDup(p); // MEMORY-LEAK } return "??"; } BOOLEAN piKill(procinfov pi) { Voice *p=currentVoice; while (p!=NULL) { if (p->pi==pi && pi->ref <= 1) { Warn("`%s` in use, can not be killed",pi->procname); return TRUE; } p=p->next; } (pi->ref)--; if (pi->ref <= 0) { if (pi->libname != NULL) // OB: ???? omFree((ADDRESS)pi->libname); if (pi->procname != NULL) // OB: ???? omFree((ADDRESS)pi->procname); if( pi->language == LANG_SINGULAR) { if (pi->data.s.body != NULL) // OB: ???? omFree((ADDRESS)pi->data.s.body); } if( pi->language == LANG_C) { } memset((void *) pi, 0, sizeof(procinfo)); pi->language=LANG_NONE; omFreeBin((ADDRESS)pi, procinfo_bin); } return FALSE; } void paCleanUp(package pack) { (pack->ref)--; if (pack->ref < 0) { #ifndef HAVE_STATIC if( pack->language == LANG_C) { Print("//dlclose(%s)\n",pack->libname); #ifdef HAVE_DYNAMIC_LOADING dynl_close (pack->handle); #endif /* HAVE_DYNAMIC_LOADING */ } #endif /* HAVE_STATIC */ omFree((ADDRESS)pack->libname); memset((void *) pack, 0, sizeof(sip_package)); pack->language=LANG_NONE; } } void proclevel::push(char *n) { //Print("push %s\n",n); proclevel *p=(proclevel*)omAlloc0(sizeof(proclevel)); p->cRing=currRing; p->cRingHdl=currRingHdl; p->name=n; p->cPackHdl=currPackHdl; p->cPack=currPack; p->next=this; procstack=p; } void proclevel::pop() { //Print("pop %s\n",name); //if (currRing!=::currRing) PrintS("currRing wrong\n");; //::currRing=this->currRing; //if (r==NULL) Print("set ring to NULL at lev %d(%s)\n",myynest,name); //::currRingHdl=this->currRingHdl; //if((::currRingHdl==NULL)||(IDRING(::currRingHdl)!=(::currRing))) // ::currRingHdl=rFindHdl(::currRing,NULL,NULL); //Print("restore pack=%s,1.obj=%s\n",IDID(currPackHdl),IDID(currPack->idroot)); currPackHdl=this->cPackHdl; currPack=this->cPack; iiCheckPack(currPack); proclevel *p=this; procstack=next; omFreeSize(p,sizeof(proclevel)); } idhdl packFindHdl(package r) { idhdl h=basePack->idroot; while (h!=NULL) { if ((IDTYP(h)==PACKAGE_CMD) && (IDPACKAGE(h)==r)) return h; h=IDNEXT(h); } return NULL; } BOOLEAN iiAlias(leftv p) { if (iiCurrArgs==NULL) { Werror("not enough arguments for proc %s",VoiceName()); p->CleanUp(); return TRUE; } leftv h=iiCurrArgs; iiCurrArgs=h->next; h->next=NULL; if (h->rtyp!=IDHDL) { BOOLEAN res=iiAssign(p,h); h->CleanUp(); omFreeBin((ADDRESS)h, sleftv_bin); return res; } if ((h->Typ()!=p->Typ()) &&(p->Typ()!=DEF_CMD)) { WerrorS("type mismatch"); return TRUE; } idhdl pp=(idhdl)p->data; switch(pp->typ) { #ifdef SINGULAR_4_1 case CRING_CMD: nKillChar((coeffs)pp); break; #endif case DEF_CMD: case INT_CMD: break; case INTVEC_CMD: case INTMAT_CMD: delete IDINTVEC(pp); break; case NUMBER_CMD: nDelete(&IDNUMBER(pp)); break; case BIGINT_CMD: n_Delete(&IDNUMBER(pp),coeffs_BIGINT); break; case MAP_CMD: { map im = IDMAP(pp); omFree((ADDRESS)im->preimage); } // continue as ideal: case IDEAL_CMD: case MODUL_CMD: case MATRIX_CMD: idDelete(&IDIDEAL(pp)); break; case PROC_CMD: case RESOLUTION_CMD: case STRING_CMD: omFree((ADDRESS)IDSTRING(pp)); break; case LIST_CMD: IDLIST(pp)->Clean(); break; case LINK_CMD: omFreeBin(IDLINK(pp),sip_link_bin); break; // case ring: cannot happen default: Werror("unknown type %d",p->Typ()); return TRUE; } pp->typ=ALIAS_CMD; IDDATA(pp)=(char*)h->data; int eff_typ=h->Typ(); if ((RingDependend(eff_typ)) || ((eff_typ==LIST_CMD) && (lRingDependend((lists)h->Data())))) { ipSwapId(pp,IDROOT,currRing->idroot); } h->CleanUp(); omFreeBin((ADDRESS)h, sleftv_bin); return FALSE; } singular-4.0.3+ds/Singular/ipid.h000066400000000000000000000077271266270727000166540ustar00rootroot00000000000000#ifndef IPID_H #define IPID_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: identfier handling */ #include //#include #include #include #include extern idhdl currPackHdl; extern idhdl basePackHdl; extern package currPack; extern package basePack; #define IDROOT (currPack->idroot) struct sip_command; typedef struct sip_command ip_command; typedef ip_command * command; struct sip_command { sleftv arg1; /*arg1 to build_in, proc to proc_call*/ sleftv arg2; /*NULL or arg2 to build_in, args to proc_call*/ sleftv arg3; /*NULL or arg3*/ short argc; /*0,1,2,3 to build_in, -1 otherwise*/ short op; /* build_in or PROC_CMD*/ }; struct sip_package { idhdl idroot; /* local objects */ char *libname; short ref; language_defs language; BOOLEAN loaded; void *handle; }; inline package paCopy(package pack) { pack->ref++; return pack; } inline void paKill(package pack) { pack->ref--; } class proclevel { public: proclevel * next; idhdl cRingHdl; ring cRing; idhdl cPackHdl; package cPack; char * name; proclevel() { memset(this,0,sizeof(*this)); } void push(char *); void pop(); }; extern proclevel *procstack; typedef struct { int (*iiAddCproc)(const char *libname, const char *procname, BOOLEAN pstatic, BOOLEAN(*func)(leftv res, leftv v)); int (*iiArithAddCmd)(const char *szName, short nAlias, short nTokval, short nToktype, short nPos); } SModulFunctions; extern idhdl currRingHdl; /* ================================================================== */ /* module support */ typedef int (*SModulFunc_t)(SModulFunctions*); BOOLEAN load_builtin(const char *newlib, BOOLEAN autoexport, SModulFunc_t init); void module_help_main(const char *newlib,const char *help); void module_help_proc(const char *newlib,const char *p, const char *help); /* ================================================================== */ /*extern ring currRing; in ring.h */ idhdl enterid(const char * a, int lev, int t, idhdl* root, BOOLEAN init=TRUE, BOOLEAN serach=TRUE); idhdl ggetid(const char *n); idhdl ggetid(const char *n, BOOLEAN local, idhdl *packhdl); void killid(const char * a, idhdl * i); void killhdl(idhdl h, package prooti=currPack); void killhdl2(idhdl h, idhdl * ih, ring r); lists ipNameList(idhdl root); lists ipNameListLev(idhdl root, int lev); void ipMoveId(idhdl h); BOOLEAN checkPackage(package pack); idhdl packFindHdl(package r); void jjNormalizeQRingP(poly &p); void jjNormalizeQRingId(leftv I); void *idrecDataInit(int t); #define FLAG_STD 0 #define FLAG_TWOSTD 3 #define FLAG_QRING 4 #define hasFlag(A,F) Sy_inset((F),(A)->flag) #define setFlag(A,F) (A)->flag|=Sy_bit(F) #define resetFlag(A,F) (A)->flag&=~Sy_bit(F) void ipListFlag(idhdl h); #define IDNEXT(a) ((a)->next) #define IDTYP(a) ((a)->typ) #define IDFLAG(a) ((a)->flag) #define IDLEV(a) ((a)->lev) #define IDID(a) ((a)->id) #define IDATTR(a) ((a)->attribute) #define IDINT(a) ((int)(long)((a)->data.ustring)) #define IDDATA(a) ((a)->data.ustring) #define IDRING(a) ((a)->data.uring) #define IDINTVEC(a) ((a)->data.iv) #define IDBIMAT(a) ((a)->data.bim) #define IDPOLY(a) ((a)->data.p) #define IDBIGINT(a) ((a)->data.n) #define IDNUMBER(a) ((a)->data.n) #define IDIDEAL(a) ((a)->data.uideal) #define IDMATRIX(a) ((a)->data.umatrix) #define IDMAP(a) ((a)->data.umap) #define IDSTRING(a) ((a)->data.ustring) #define IDLIST(a) ((a)->data.l) #define IDLINK(a) ((a)->data.li) #define IDPACKAGE(a) ((a)->data.pack) #define IDPROC(a) ((a)->data.pinf) extern omBin sip_command_bin; extern omBin sip_package_bin; extern omBin idrec_bin; extern omBin sleftv_bin; extern coeffs coeffs_BIGINT; extern FILE *feFilePending; /*temp. storage for grammar.y */ #endif singular-4.0.3+ds/Singular/iplib.cc000066400000000000000000001062721266270727000171570ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: interpreter: LIB and help */ #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #if SIZEOF_LONG == 8 #define SI_MAX_NEST 500 #elif defined(__CYGWIN__) #define SI_MAX_NEST 480 #else #define SI_MAX_NEST 1000 #endif #if defined(ix86Mac_darwin) || defined(x86_64Mac_darwin) || defined(ppcMac_darwin) # define MODULE_SUFFIX bundle #elif defined(__CYGWIN__) # define MODULE_SUFFIX dll #else # define MODULE_SUFFIX so #endif #define MODULE_SUFFIX_STRING EXPANDED_STRINGIFY(MODULE_SUFFIX) #ifdef HAVE_DYNAMIC_LOADING BOOLEAN load_modules(const char *newlib, char *fullname, BOOLEAN autoexport); #endif #ifdef HAVE_LIBPARSER # include "libparse.h" #else /* HAVE_LIBPARSER */ procinfo *iiInitSingularProcinfo(procinfov pi, const char *libname, const char *procname, int line, long pos, BOOLEAN pstatic=FALSE); #endif /* HAVE_LIBPARSER */ #define NS_LRING (procstack->cRing) extern int iiArithAddCmd(const char *szName, short nAlias, short nTokval, short nToktype, short nPos); #include #ifdef HAVE_LIBPARSER void yylprestart (FILE *input_file ); int current_pos(int i=0); extern int yylp_errno; extern int yylplineno; extern char *yylp_errlist[]; void print_init(); libstackv library_stack; #endif //int IsCmd(char *n, int tok); char mytolower(char c); /*2 * return TRUE if the libray libname is already loaded */ BOOLEAN iiGetLibStatus(char *lib) { idhdl hl; char *plib = iiConvName(lib); hl = basePack->idroot->get(plib,0); omFree(plib); if((hl==NULL) ||(IDTYP(hl)!=PACKAGE_CMD)) { return FALSE; } return (strcmp(lib,IDPACKAGE(hl)->libname)==0); } /*2 * find the library of an proc: * => return (pi->libname) */ char * iiGetLibName(procinfov pi) { return pi->libname; } /*2 * given a line 'proc[ ]+{name}[ \t]*' * return a pointer to name and set the end of '\0' * changes the input! * returns: e: pointer to 'end of name' * ct: changed char at the end of s */ char* iiProcName(char *buf, char & ct, char* &e) { char *s=buf+5; while (*s==' ') s++; e=s+1; while ((*e>' ') && (*e!='(')) e++; ct=*e; *e='\0'; return s; } /*2 * given a line with args, return the argstr */ char * iiProcArgs(char *e,BOOLEAN withParenth) { while ((*e==' ') || (*e=='\t') || (*e=='(')) e++; if (*e<' ') { if (withParenth) { // no argument list, allow list # return omStrDup("parameter list #;"); } else { // empty list return omStrDup(""); } } BOOLEAN in_args; BOOLEAN args_found; char *s; char *argstr=(char *)omAlloc(127); // see ../omalloc/omTables.inc int argstrlen=127; *argstr='\0'; int par=0; do { args_found=FALSE; s=e; // set s to the starting point of the arg // and search for the end // skip leading spaces: loop { if ((*s==' ')||(*s=='\t')) s++; else if ((*s=='\n')&&(*(s+1)==' ')) s+=2; else // start of new arg or \0 or ) break; } e=s; while ((*e!=',') &&((par!=0) || (*e!=')')) &&(*e!='\0')) { if (*e=='(') par++; else if (*e==')') par--; args_found=args_found || (*e>' '); e++; } in_args=(*e==','); if (args_found) { *e='\0'; // check for space: if ((int)strlen(argstr)+12 /* parameter + ;*/ +(int)strlen(s)>= argstrlen) { argstrlen*=2; char *a=(char *)omAlloc( argstrlen); strcpy(a,argstr); omFree((ADDRESS)argstr); argstr=a; } // copy the result to argstr if(strncmp(s,"alias ",6)!=0) { strcat(argstr,"parameter "); } strcat(argstr,s); strcat(argstr,"; "); e++; // e was pointing to ',' } } while (in_args); return argstr; } /*2 * locate `procname` in lib `libname` and find the part `part`: * part=0: help, between, but excluding the line "proc ..." and "{...": * => return * part=1: body, between "{ ..." and "}", including the 1. line, w/o "{" * => set pi->data.s.body, return NULL * part=2: example, between, but excluding the line "exapmle {..." and "}": * => return */ char* iiGetLibProcBuffer(procinfo *pi, int part ) { char buf[256], *s = NULL, *p; long procbuflen; FILE * fp = feFopen( pi->libname, "rb", NULL, TRUE ); if (fp==NULL) { return NULL; } fseek(fp, pi->data.s.proc_start, SEEK_SET); if(part==0) { // load help string int i, offset=0; long head = pi->data.s.def_end - pi->data.s.proc_start; procbuflen = pi->data.s.help_end - pi->data.s.help_start; if (procbuflen<5) { fclose(fp); return NULL; // help part does not exist } //Print("Help=%ld-%ld=%d\n", pi->data.s.body_start, // pi->data.s.proc_start, procbuflen); s = (char *)omAlloc(procbuflen+head+3); myfread(s, head, 1, fp); s[head] = '\n'; fseek(fp, pi->data.s.help_start, SEEK_SET); myfread(s+head+1, procbuflen, 1, fp); fclose(fp); s[procbuflen+head+1] = '\n'; s[procbuflen+head+2] = '\0'; offset=0; for(i=0;i<=procbuflen+head+2; i++) { if(s[i]=='\\' && (s[i+1]=='"' || s[i+1]=='{' || s[i+1]=='}' || s[i+1]=='\\')) { i++; offset++; } if(offset>0) s[i-offset] = s[i]; } return(s); } else if(part==1) { // load proc part - must exist procbuflen = pi->data.s.def_end - pi->data.s.proc_start; char *ss=(char *)omAlloc(procbuflen+2); //fgets(buf, sizeof(buf), fp); myfread( ss, procbuflen, 1, fp); char ct; char *e; s=iiProcName(ss,ct,e); char *argstr=NULL; *e=ct; argstr=iiProcArgs(e,TRUE); assume(pi->data.s.body_end > pi->data.s.body_start); procbuflen = pi->data.s.body_end - pi->data.s.body_start; pi->data.s.body = (char *)omAlloc( strlen(argstr)+procbuflen+15+ strlen(pi->libname) ); //Print("Body=%ld-%ld=%d\n", pi->data.s.body_end, // pi->data.s.body_start, procbuflen); assume(pi->data.s.body != NULL); fseek(fp, pi->data.s.body_start, SEEK_SET); strcpy(pi->data.s.body,argstr); myfread( pi->data.s.body+strlen(argstr), procbuflen, 1, fp); fclose( fp ); procbuflen+=strlen(argstr); omFree(argstr); omFree(ss); pi->data.s.body[procbuflen] = '\0'; strcat( pi->data.s.body+procbuflen, "\n;return();\n\n" ); strcat( pi->data.s.body+procbuflen+13,pi->libname); s=(char *)strchr(pi->data.s.body,'{'); if (s!=NULL) *s=' '; return NULL; } else if(part==2) { // example if ( pi->data.s.example_lineno == 0) return NULL; // example part does not exist // load example fseek(fp, pi->data.s.example_start, SEEK_SET); /*char *dummy=*/ (void) fgets(buf, sizeof(buf), fp); // skip line with "example" procbuflen = pi->data.s.proc_end - pi->data.s.example_start - strlen(buf); //Print("Example=%ld-%ld=%d\n", pi->data.s.proc_end, // pi->data.s.example_start, procbuflen); s = (char *)omAlloc(procbuflen+14); myfread(s, procbuflen, 1, fp); s[procbuflen] = '\0'; strcat(s+procbuflen-3, "\n;return();\n\n" ); p=(char *)strchr(s,'{'); if (p!=NULL) *p=' '; return(s); } return NULL; } // see below: struct soptionStruct { const char * name; unsigned setval; unsigned resetval; }; extern struct soptionStruct optionStruct[]; extern struct soptionStruct verboseStruct[]; BOOLEAN iiAllStart(procinfov pi, char *p,feBufferTypes t, int l) { // see below: BITSET save1=si_opt_1; BITSET save2=si_opt_2; newBuffer( omStrDup(p /*pi->data.s.body*/), t /*BT_proc*/, pi, l ); BOOLEAN err=yyparse(); if (sLastPrinted.rtyp!=0) { sLastPrinted.CleanUp(); } // the access to optionStruct and verboseStruct do not work // on x86_64-Linux for pic-code if ((TEST_V_ALLWARN) && (t==BT_proc) && ((save1!=si_opt_1)||(save2!=si_opt_2)) && (pi->libname!=NULL) && (pi->libname[0]!='\0')) { if ((pi->libname!=NULL) && (pi->libname[0]!='\0')) Warn("option changed in proc %s from %s",pi->procname,pi->libname); else Warn("option changed in proc %s",pi->procname); int i; for (i=0; optionStruct[i].setval!=0; i++) { if ((optionStruct[i].setval & si_opt_1) && (!(optionStruct[i].setval & save1))) { Print(" +%s",optionStruct[i].name); } if (!(optionStruct[i].setval & si_opt_1) && ((optionStruct[i].setval & save1))) { Print(" -%s",optionStruct[i].name); } } for (i=0; verboseStruct[i].setval!=0; i++) { if ((verboseStruct[i].setval & si_opt_2) && (!(verboseStruct[i].setval & save2))) { Print(" +%s",verboseStruct[i].name); } if (!(verboseStruct[i].setval & si_opt_2) && ((verboseStruct[i].setval & save2))) { Print(" -%s",verboseStruct[i].name); } } PrintLn(); } return err; } /*2 * start a proc * parameters are built as exprlist * TODO:interrupt * return FALSE on success, TRUE if an error occurs */ BOOLEAN iiPStart(idhdl pn, sleftv * v) { procinfov pi=NULL; int old_echo=si_echo; BOOLEAN err=FALSE; char save_flags=0; /* init febase ======================================== */ /* we do not enter this case if filename != NULL !! */ if (pn!=NULL) { pi = IDPROC(pn); if(pi!=NULL) { save_flags=pi->trace_flag; if( pi->data.s.body==NULL ) { iiGetLibProcBuffer(pi); if (pi->data.s.body==NULL) return TRUE; } // omUpdateInfo(); // int m=om_Info.UsedBytes; // Print("proc %s, mem=%d\n",IDID(pn),m); } } else return TRUE; /* generate argument list ======================================*/ if (v!=NULL) { iiCurrArgs=(leftv)omAllocBin(sleftv_bin); memcpy(iiCurrArgs,v,sizeof(sleftv)); memset(v,0,sizeof(sleftv)); } else { iiCurrArgs=NULL; } iiCurrProc=pn; /* start interpreter ======================================*/ myynest++; if (myynest > SI_MAX_NEST) { WerrorS("nesting too deep"); err=TRUE; } else { err=iiAllStart(pi,pi->data.s.body,BT_proc,pi->data.s.body_lineno-(v!=NULL)); #ifdef USE_IILOCALRING #if 0 if(procstack->cRing != iiLocalRing[myynest]) Print("iiMake_proc: 1 ring not saved procs:%x, iiLocal:%x\n",procstack->cRing, iiLocalRing[myynest]); #endif if (iiLocalRing[myynest-1] != currRing) { if (iiRETURNEXPR.RingDependend()) { //idhdl hn; const char *n; const char *o; idhdl nh=NULL, oh=NULL; if (iiLocalRing[myynest-1]!=NULL) oh=rFindHdl(iiLocalRing[myynest-1],NULL); if (oh!=NULL) o=oh->id; else o="none"; if (currRing!=NULL) nh=rFindHdl(currRing,NULL); if (nh!=NULL) n=nh->id; else n="none"; Werror("ring change during procedure call: %s -> %s (level %d)",o,n,myynest); iiRETURNEXPR.CleanUp(); err=TRUE; } currRing=iiLocalRing[myynest-1]; } if ((currRing==NULL) && (currRingHdl!=NULL)) currRing=IDRING(currRingHdl); else if ((currRing!=NULL) && ((currRingHdl==NULL)||(IDRING(currRingHdl)!=currRing) ||(IDLEV(currRingHdl)>=myynest-1))) { rSetHdl(rFindHdl(currRing,NULL)); iiLocalRing[myynest-1]=NULL; } #else /* USE_IILOCALRING */ if (procstack->cRing != currRing) { //if (procstack->cRingHdl!=NULL) //Print("procstack:%s,",IDID(procstack->cRingHdl)); //if (currRingHdl!=NULL) //Print(" curr:%s\n",IDID(currRingHdl)); //Print("pr:%x, curr: %x\n",procstack->cRing,currRing); if (iiRETURNEXPR.RingDependend()) { //idhdl hn; const char *n; const char *o; if (procstack->cRing!=NULL) { //PrintS("reset ring\n"); procstack->cRingHdl=rFindHdl(procstack->cRing,NULL); o=IDID(procstack->cRingHdl); currRing=procstack->cRing; currRingHdl=procstack->cRingHdl; } else o="none"; if (currRing!=NULL) n=IDID(currRingHdl); else n="none"; if (currRing==NULL) { Werror("ring change during procedure call: %s -> %s (level %d)",o,n,myynest); iiRETURNEXPR.CleanUp(); err=TRUE; } } if (procstack->cRingHdl!=NULL) { rSetHdl(procstack->cRingHdl); } else { currRingHdl=NULL; currRing=NULL; } } #endif /* USE_IILOCALRING */ //Print("kill locals for %s (level %d)\n",IDID(pn),myynest); killlocals(myynest); #ifndef SING_NDEBUG checkall(); #endif //Print("end kill locals for %s (%d)\n",IDID(pn),myynest); } myynest--; si_echo=old_echo; if (pi!=NULL) pi->trace_flag=save_flags; // omUpdateInfo(); // int m=om_Info.UsedBytes; // Print("exit %s, mem=%d\n",IDID(pn),m); return err; } #ifdef USE_IILOCALRING ring *iiLocalRing; #endif sleftv iiRETURNEXPR; int iiRETURNEXPR_len=0; #ifdef RDEBUG static void iiShowLevRings() { int i; #ifdef USE_IILOCALRING for (i=0;i<=myynest;i++) { Print("lev %d:",i); if (iiLocalRing[i]==NULL) PrintS("NULL"); else Print("%lx",(long)iiLocalRing[i]); PrintLn(); } #endif #if 0 i=myynest; proclevel *p=procstack; while (p!=NULL) { Print("lev %d:",i); if (p->cRingHdl==NULL) PrintS("NULL"); else Print("%s",IDID(p->cRingHdl)); PrintLn(); p=p->next; } #endif if (currRing==NULL) PrintS("curr:NULL\n"); else Print ("curr:%lx\n",(long)currRing); } #endif /* RDEBUG */ static void iiCheckNest() { if (myynest >= iiRETURNEXPR_len-1) { #ifdef USE_IILOCALRING iiLocalRing=(ring *)omreallocSize(iiLocalRing, iiRETURNEXPR_len*sizeof(ring), (iiRETURNEXPR_len+16)*sizeof(ring)); memset(&(iiLocalRing[iiRETURNEXPR_len]),0,16*sizeof(ring)); #endif iiRETURNEXPR_len+=16; } } BOOLEAN iiMake_proc(idhdl pn, package pack, sleftv* sl) { int err; procinfov pi = IDPROC(pn); if(pi->is_static && myynest==0) { Werror("'%s::%s()' is a local procedure and cannot be accessed by an user.", pi->libname, pi->procname); return TRUE; } iiCheckNest(); #ifdef USE_IILOCALRING iiLocalRing[myynest]=currRing; //Print("currRing(%d):%s(%x) in %s\n",myynest,IDID(currRingHdl),currRing,IDID(pn)); #endif iiRETURNEXPR.Init(); procstack->push(pi->procname); if ((traceit&TRACE_SHOW_PROC) || (pi->trace_flag&TRACE_SHOW_PROC)) { if (traceit&TRACE_SHOW_LINENO) PrintLn(); Print("entering%-*.*s %s (level %d)\n",myynest*2,myynest*2," ",IDID(pn),myynest); } #ifdef RDEBUG if (traceit&TRACE_SHOW_RINGS) iiShowLevRings(); #endif switch (pi->language) { default: case LANG_NONE: WerrorS("undefined proc"); err=TRUE; break; case LANG_SINGULAR: if ((pi->pack!=NULL)&&(currPack!=pi->pack)) { currPack=pi->pack; iiCheckPack(currPack); currPackHdl=packFindHdl(currPack); //Print("set pack=%s\n",IDID(currPackHdl)); } else if ((pack!=NULL)&&(currPack!=pack)) { currPack=pack; iiCheckPack(currPack); currPackHdl=packFindHdl(currPack); //Print("set pack=%s\n",IDID(currPackHdl)); } err=iiPStart(pn,sl); break; case LANG_C: leftv res = (leftv)omAlloc0Bin(sleftv_bin); err = (pi->data.o.function)(res, sl); memcpy(&iiRETURNEXPR,res,sizeof(iiRETURNEXPR)); omFreeBin((ADDRESS)res, sleftv_bin); break; } if ((traceit&TRACE_SHOW_PROC) || (pi->trace_flag&TRACE_SHOW_PROC)) { if (traceit&TRACE_SHOW_LINENO) PrintLn(); Print("leaving %-*.*s %s (level %d)\n",myynest*2,myynest*2," ",IDID(pn),myynest); } //const char *n="NULL"; //if (currRingHdl!=NULL) n=IDID(currRingHdl); //Print("currRing(%d):%s(%x) after %s\n",myynest,n,currRing,IDID(pn)); #ifdef RDEBUG if (traceit&TRACE_SHOW_RINGS) iiShowLevRings(); #endif if (err) { iiRETURNEXPR.CleanUp(); //iiRETURNEXPR.Init(); //done by CleanUp } if (iiCurrArgs!=NULL) { if (!err) Warn("too many arguments for %s",IDID(pn)); iiCurrArgs->CleanUp(); omFreeBin((ADDRESS)iiCurrArgs, sleftv_bin); iiCurrArgs=NULL; } procstack->pop(); if (err) return TRUE; return FALSE; } /*2 * start an example (as a proc), * destroys the string 'example' */ BOOLEAN iiEStart(char* example, procinfo *pi) { BOOLEAN err; int old_echo=si_echo; iiCheckNest(); procstack->push(example); #ifdef USE_IILOCALRING iiLocalRing[myynest]=currRing; #endif if (traceit&TRACE_SHOW_PROC) { if (traceit&TRACE_SHOW_LINENO) printf("\n"); printf("entering example (level %d)\n",myynest); } myynest++; err=iiAllStart(pi,example,BT_example,(pi != NULL ? pi->data.s.example_lineno: 0)); killlocals(myynest); myynest--; si_echo=old_echo; if (traceit&TRACE_SHOW_PROC) { if (traceit&TRACE_SHOW_LINENO) printf("\n"); printf("leaving -example- (level %d)\n",myynest); } #ifdef USE_IILOCALRING if (iiLocalRing[myynest] != currRing) { if (iiLocalRing[myynest]!=NULL) { rSetHdl(rFindHdl(iiLocalRing[myynest],NULL)); iiLocalRing[myynest]=NULL; } else { currRingHdl=NULL; currRing=NULL; } } #else /* USE_IILOCALRING */ #endif /* USE_IILOCALRING */ if (NS_LRING != currRing) { if (NS_LRING!=NULL) { idhdl rh=procstack->cRingHdl; if ((rh==NULL)||(IDRING(rh)!=NS_LRING)) rh=rFindHdl(NS_LRING,NULL); rSetHdl(rh); } else { currRingHdl=NULL; currRing=NULL; } } //#endif /* USE_IILOCALRING */ procstack->pop(); return err; } extern "C" { # define SI_GET_BUILTIN_MOD_INIT0(name) int SI_MOD_INIT0(name)(SModulFunctions*); SI_FOREACH_BUILTIN(SI_GET_BUILTIN_MOD_INIT0) # undef SI_GET_BUILTIN_MOD_INIT0 }; SModulFunc_t iiGetBuiltinModInit(const char* libname) { # define SI_GET_BUILTIN_MOD_INIT(name) if (strcmp(libname, #name ".so") == 0){ return SI_MOD_INIT0(name); } SI_FOREACH_BUILTIN(SI_GET_BUILTIN_MOD_INIT) # undef SI_GET_BUILTIN_MOD_INIT return NULL; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ BOOLEAN iiTryLoadLib(leftv v, const char *id) { BOOLEAN LoadResult = TRUE; char libnamebuf[128]; char *libname = (char *)omAlloc(strlen(id)+5); const char *suffix[] = { "", ".lib", ".so", ".sl", NULL }; int i = 0; // FILE *fp; // package pack; // idhdl packhdl; lib_types LT; for(i=0; suffix[i] != NULL; i++) { sprintf(libname, "%s%s", id, suffix[i]); *libname = mytolower(*libname); if((LT = type_of_LIB(libname, libnamebuf)) > LT_NOTFOUND) { char *s=omStrDup(libname); #ifdef HAVE_DYNAMIC_LOADING char libnamebuf[256]; #endif if (LT==LT_SINGULAR) LoadResult = iiLibCmd(s, FALSE, FALSE,TRUE); #ifdef HAVE_DYNAMIC_LOADING else if ((LT==LT_ELF) || (LT==LT_HPUX)) LoadResult = load_modules(s,libnamebuf,FALSE); #endif else if (LT==LT_BUILTIN) { LoadResult=load_builtin(s,FALSE, iiGetBuiltinModInit(s)); } if(!LoadResult ) { v->name = iiConvName(libname); break; } } } omFree(libname); return LoadResult; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ /* check, if library lib has already been loaded if yes, writes filename of lib into where and returns TRUE, no, returns FALSE */ BOOLEAN iiLocateLib(const char* lib, char* where) { char *plib = iiConvName(lib); idhdl pl = basePack->idroot->get(plib,0); if( (pl!=NULL) && (IDTYP(pl)==PACKAGE_CMD) && (IDPACKAGE(pl)->language == LANG_SINGULAR)) { strncpy(where,IDPACKAGE(pl)->libname,127); return TRUE; } else return FALSE;; } BOOLEAN iiLibCmd( char *newlib, BOOLEAN autoexport, BOOLEAN tellerror, BOOLEAN force ) { char libnamebuf[128]; // procinfov pi; // idhdl h; idhdl pl; // idhdl hl; // long pos = 0L; char *plib = iiConvName(newlib); FILE * fp = feFopen( newlib, "r", libnamebuf, tellerror ); // int lines = 1; BOOLEAN LoadResult = TRUE; if (fp==NULL) { return TRUE; } pl = basePack->idroot->get(plib,0); if (pl==NULL) { pl = enterid( plib,0, PACKAGE_CMD, &(basePack->idroot), TRUE ); IDPACKAGE(pl)->language = LANG_SINGULAR; IDPACKAGE(pl)->libname=omStrDup(newlib); } else { if(IDTYP(pl)!=PACKAGE_CMD) { WarnS("not of type package."); fclose(fp); return TRUE; } if (!force) return FALSE; } LoadResult = iiLoadLIB(fp, libnamebuf, newlib, pl, autoexport, tellerror); omFree((ADDRESS)newlib); if(!LoadResult) IDPACKAGE(pl)->loaded = TRUE; omFree((ADDRESS)plib); return LoadResult; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ static void iiCleanProcs(idhdl &root) { idhdl prev=NULL; loop { if (root==NULL) return; if (IDTYP(root)==PROC_CMD) { procinfo *pi=(procinfo*)IDDATA(root); if ((pi->language == LANG_SINGULAR) && (pi->data.s.body_start == 0L)) { // procinfo data incorrect: // - no proc body can start at the beginning of the file killhdl(root); if (prev==NULL) root=IDROOT; else { root=prev; prev=NULL; } continue; } } prev=root; root=IDNEXT(root); } } static void iiRunInit(package p) { idhdl h=p->idroot->get("mod_init",0); if (h==NULL) return; if (IDTYP(h)==PROC_CMD) { int save=yylineno; myynest++; // procinfo *pi=(procinfo*)IDDATA(h); //PrintS("mod_init found\n"); iiMake_proc(h,p,NULL); myynest--; yylineno=save; } } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ BOOLEAN iiLoadLIB(FILE *fp, const char *libnamebuf, const char*newlib, idhdl pl, BOOLEAN autoexport, BOOLEAN tellerror) { extern FILE *yylpin; libstackv ls_start = library_stack; lib_style_types lib_style; yylpin = fp; #if YYLPDEBUG > 1 print_init(); #endif extern int lpverbose; if (BVERBOSE(V_DEBUG_LIB)) lpverbose=1; else lpverbose=0; // yylplex sets also text_buffer if (text_buffer!=NULL) *text_buffer='\0'; yylplex(newlib, libnamebuf, &lib_style, pl, autoexport); if(yylp_errno) { Werror("Library %s: ERROR occured: in line %d, %d.", newlib, yylplineno, current_pos(0)); if(yylp_errno==YYLP_BAD_CHAR) { Werror(yylp_errlist[yylp_errno], *text_buffer, yylplineno); omFree((ADDRESS)text_buffer); text_buffer=NULL; } else Werror(yylp_errlist[yylp_errno], yylplineno); Werror("Cannot load library,... aborting."); reinit_yylp(); fclose( yylpin ); iiCleanProcs(IDROOT); return TRUE; } if (BVERBOSE(V_LOAD_LIB)) Print( "// ** loaded %s %s\n", libnamebuf, text_buffer); if( (lib_style == OLD_LIBSTYLE) && (BVERBOSE(V_LOAD_LIB))) { Warn( "library %s has old format. This format is still accepted,", newlib); Warn( "but for functionality you may wish to change to the new"); Warn( "format. Please refer to the manual for further information."); } reinit_yylp(); fclose( yylpin ); fp = NULL; iiRunInit(IDPACKAGE(pl)); { libstackv ls; for(ls = library_stack; (ls != NULL) && (ls != ls_start); ) { if(ls->to_be_done) { ls->to_be_done=FALSE; iiLibCmd(ls->get(),autoexport,tellerror,FALSE); ls = ls->pop(newlib); } } #if 0 PrintS("--------------------\n"); for(ls = library_stack; ls != NULL; ls = ls->next) { Print("%s: LIB-stack:(%d), %s %s\n", newlib, ls->cnt, ls->get(), ls->to_be_done ? "not loaded" : "loaded"); } PrintS("--------------------\n"); #endif } if(fp != NULL) fclose(fp); return FALSE; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ procinfo *iiInitSingularProcinfo(procinfov pi, const char *libname, const char *procname, int line, long pos, BOOLEAN pstatic) { pi->libname = omStrDup(libname); pi->procname = omStrDup(procname); pi->language = LANG_SINGULAR; pi->ref = 1; pi->pack = NULL; pi->is_static = pstatic; pi->data.s.proc_start = pos; pi->data.s.def_end = 0L; pi->data.s.help_start = 0L; pi->data.s.help_end = 0L; pi->data.s.body_start = 0L; pi->data.s.body_end = 0L; pi->data.s.example_start = 0L; pi->data.s.proc_lineno = line; pi->data.s.body_lineno = 0; pi->data.s.example_lineno = 0; pi->data.s.body = NULL; pi->data.s.help_chksum = 0; return(pi); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ int iiAddCproc(const char *libname, const char *procname, BOOLEAN pstatic, BOOLEAN(*func)(leftv res, leftv v)) { procinfov pi; idhdl h; #ifndef SING_NDEBUG int dummy; if (IsCmd(procname,dummy)) { Werror(">>%s< is a reserved name",procname); return 0; } #endif h = enterid(procname,0, PROC_CMD, &IDROOT, TRUE); if ( h!= NULL ) { pi = IDPROC(h); pi->libname = omStrDup(libname); pi->procname = omStrDup(procname); pi->language = LANG_C; pi->ref = 1; pi->is_static = pstatic; pi->data.o.function = func; return(1); } else { PrintS("iiAddCproc: failed.\n"); } return(0); } int iiAddCprocTop(const char *libname, const char *procname, BOOLEAN pstatic, BOOLEAN(*func)(leftv res, leftv v)) { int r=iiAddCproc(libname,procname,pstatic,func); package s=currPack; currPack=basePack; if (r) r=iiAddCproc(libname,procname,pstatic,func); currPack=s; return r; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #ifdef HAVE_DYNAMIC_LOADING BOOLEAN load_modules(const char *newlib, char *fullname, BOOLEAN autoexport) { #ifdef HAVE_STATIC WerrorS("mod_init: static version can not load modules"); return TRUE; #else /* typedef int (*fktn_t)(int(*iiAddCproc)(const char *libname, const char *procname, BOOLEAN pstatic, BOOLEAN(*func)(leftv res, leftv v))); */ SModulFunc_t fktn; idhdl pl; char *plib = iiConvName(newlib); BOOLEAN RET=TRUE; int token; char FullName[256]; memset(FullName,0,256); if( *fullname != '/' && *fullname != '.' ) sprintf(FullName, "./%s", newlib); else strncpy(FullName, fullname,255); if(IsCmd(plib, token)) { Werror("'%s' is resered identifier\n", plib); goto load_modules_end; } pl = basePack->idroot->get(plib,0); /* packages only in top level (see enterid) */ if (pl==NULL) { pl = enterid( plib,0, PACKAGE_CMD, &IDROOT, TRUE ); IDPACKAGE(pl)->language = LANG_C; IDPACKAGE(pl)->libname=omStrDup(newlib); } else { if(IDTYP(pl)!=PACKAGE_CMD) { Warn("not of type package."); goto load_modules_end; } } if (dynl_check_opened(FullName)) { if (BVERBOSE(V_LOAD_LIB)) Warn( "%s already loaded", fullname); return FALSE; } if((IDPACKAGE(pl)->handle=dynl_open(FullName))==(void *)NULL) { Werror("dynl_open failed:%s", dynl_error()); Werror("%s not found", newlib); killhdl2(pl,&(basePack->idroot),NULL); // remove package goto load_modules_end; } else { SModulFunctions sModulFunctions; package s=currPack; currPack=IDPACKAGE(pl); fktn = (SModulFunc_t)dynl_sym(IDPACKAGE(pl)->handle, "mod_init"); if( fktn!= NULL) { sModulFunctions.iiArithAddCmd = iiArithAddCmd; if (autoexport) sModulFunctions.iiAddCproc = iiAddCprocTop; else sModulFunctions.iiAddCproc = iiAddCproc; int ver=(*fktn)(&sModulFunctions); if (ver==MAX_TOK) { if (BVERBOSE(V_LOAD_LIB)) Print( "// ** loaded %s\n", fullname); } else { Warn("// ** loaded %s for a different version of Singular(expected: %d, got %d)",fullname,MAX_TOK,ver); } currPack->loaded=1; currPack=s; RET=FALSE; } else { Werror("mod_init not found:: %s\nThis is probably not a dynamic module for Singular!\n", dynl_error()); killhdl2(pl,&(basePack->idroot),NULL); // remove package } } load_modules_end: return RET; #endif /*STATIC */ } #endif /* HAVE_DYNAMIC_LOADING */ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ BOOLEAN load_builtin(const char *newlib, BOOLEAN autoexport, SModulFunc_t init) { int iiAddCproc(const char *libname, const char *procname, BOOLEAN pstatic, BOOLEAN(*func)(leftv res, leftv v)); /* typedef int (*fktn_t)(int(*iiAddCproc)(const char *libname, const char *procname, BOOLEAN pstatic, BOOLEAN(*func)(leftv res, leftv v))); */ // SModulFunc_t fktn; idhdl pl; char *plib = iiConvName(newlib); // BOOLEAN RET=TRUE; // int token; pl = IDROOT->get(plib,0); if (pl!=NULL) { if (BVERBOSE(V_LOAD_LIB)) Warn( "(builtin) %s already loaded", newlib); omFree(plib); return FALSE; } pl = enterid( plib,0, PACKAGE_CMD, &IDROOT, TRUE ); IDPACKAGE(pl)->language = LANG_C; IDPACKAGE(pl)->libname=omStrDup(newlib); IDPACKAGE(pl)->handle=(void *)NULL; SModulFunctions sModulFunctions; package s=currPack; currPack=IDPACKAGE(pl); if( init!= NULL) { sModulFunctions.iiArithAddCmd = iiArithAddCmd; if (autoexport) sModulFunctions.iiAddCproc = iiAddCprocTop; else sModulFunctions.iiAddCproc = iiAddCproc; (*init)(&sModulFunctions); } if (BVERBOSE(V_LOAD_LIB)) Print( "// ** loaded (builtin) %s \n", newlib); currPack->loaded=1; currPack=s; return FALSE; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void module_help_main(const char *newlib,const char *help) { char *plib = iiConvName(newlib); idhdl pl = basePack->idroot->get(plib,0); if ((pl==NULL)||(IDTYP(pl)!=PACKAGE_CMD)) Werror(">>%s<< is not a package (trying to add package help)",plib); else { package s=currPack; currPack=IDPACKAGE(pl); idhdl h=enterid(omStrDup("info"),0,STRING_CMD,&IDROOT,FALSE); IDSTRING(h)=omStrDup(help); currPack=s; } } void module_help_proc(const char *newlib,const char *p, const char *help) { char *plib = iiConvName(newlib); idhdl pl = basePack->idroot->get(plib,0); if ((pl==NULL)||(IDTYP(pl)!=PACKAGE_CMD)) Werror(">>%s<< is not a package(trying to add help for %s)",plib,p); else { package s=currPack; currPack=IDPACKAGE(pl); char buff[256]; buff[255]='\0'; strncpy(buff,p,255); strncat(buff,"_help",255-strlen(p)); idhdl h=enterid(omStrDup(buff),0,STRING_CMD,&IDROOT,FALSE); IDSTRING(h)=omStrDup(help); currPack=s; } } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ // loads a dynamic module from the binary path and returns a named function // returns NULL, if something fails void* binary_module_function(const char* newlib, const char* funcname) { void* result = NULL; #if defined(HAVE_STATIC) || !defined(HAVE_DYNAMIC_LOADING) WerrorS("static version can not load function from dynamic modules"); #else const char* bin_dir = feGetResource('b'); if (!bin_dir) { return NULL; } char path_name[MAXPATHLEN]; sprintf(path_name, "%s%s%s.%s", bin_dir, DIR_SEPP, newlib, MODULE_SUFFIX_STRING); void* openlib = dynl_open(path_name); if(!openlib) { Werror("dynl_open of %s failed:%s", path_name, dynl_error()); return NULL; } result = dynl_sym(openlib, funcname); if (!result) Werror("%s: %s\n", funcname, dynl_error()); #endif return result; } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ char mytoupper(char c) { if(c>=97 && c<=(97+26)) c-=32; return(c); } char mytolower(char c) { if(c>=65 && c<=(65+26)) c+=32; return(c); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ //#if defined(WINNT) //# define FS_SEP '\\' //#else //# define FS_SEP '/' //#endif char *iiConvName(const char *libname) { char *tmpname = omStrDup(libname); char *p = strrchr(tmpname, DIR_SEP); char *r; if(p==NULL) p = tmpname; else p++; r = (char *)strchr(p, '.'); if( r!= NULL) *r = '\0'; r = omStrDup(p); *r = mytoupper(*r); // printf("iiConvName: '%s' '%s' => '%s'\n", libname, tmpname, r); omFree((ADDRESS)tmpname); return(r); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #if 0 /* debug only */ void piShowProcList() { idhdl h; procinfo *proc; char *name; Print( "%-15s %20s %s,%s %s,%s %s,%s\n", "Library", "function", "line", "start", "line", "body", "line", "example"); for(h = IDROOT; h != NULL; h = IDNEXT(h)) { if(IDTYP(h) == PROC_CMD) { proc = IDPROC(h); if(strcmp(proc->procname, IDID(h))!=0) { name = (char *)omAlloc(strlen(IDID(h))+strlen(proc->procname)+4); sprintf(name, "%s -> %s", IDID(h), proc->procname); Print( "%d %-15s %20s ", proc->is_static ? 1 : 0, proc->libname, name); omFree((ADDRESS)name); } else Print( "%d %-15s %20s ", proc->is_static ? 1 : 0, proc->libname, proc->procname); if(proc->language==LANG_SINGULAR) Print("line %4d,%-5ld %4d,%-5ld %4d,%-5ld\n", proc->data.s.proc_lineno, proc->data.s.proc_start, proc->data.s.body_lineno, proc->data.s.body_start, proc->data.s.example_lineno, proc->data.s.example_start); else if(proc->language==LANG_C) Print("type: object\n"); } } } #endif /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ //char *iiLineNo(char *procname, int lineno) //{ // char buf[256]; // idhdl pn = ggetid(procname); // procinfo *pi = IDPROC(pn); // // sprintf(buf, "%s %3d\0", procname, lineno); // //sprintf(buf, "%s::%s %3d\0", pi->libname, pi->procname, // // lineno + pi->data.s.body_lineno); // return(buf); //} /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #ifdef HAVE_LIBPARSER void libstack::push(const char */*p*/, char *libn) { libstackv lp; if( !iiGetLibStatus(libn)) { for(lp = this;lp!=NULL;lp=lp->next) { if(strcmp(lp->get(), libn)==0) break; } if(lp==NULL) { libstackv ls = (libstack *)omAlloc0Bin(libstack_bin); ls->next = this; ls->libname = omStrDup(libn); ls->to_be_done = TRUE; if(this != NULL) ls->cnt = this->cnt+1; else ls->cnt = 0; library_stack = ls; } } } libstackv libstack::pop(const char */*p*/) { libstackv ls = this; //omFree((ADDRESS)ls->libname); library_stack = ls->next; omFreeBin((ADDRESS)ls, libstack_bin); return(library_stack); } #endif /* HAVE_LIBPARSER */ /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ singular-4.0.3+ds/Singular/ipprint.cc000066400000000000000000000241731266270727000175440ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: interpreter: printing */ #include #include #include #include #include #include #include "tok.h" #include "ipid.h" #include "subexpr.h" #include "ipshell.h" #include "ipprint.h" #include "attrib.h" /*2 * print for: int, string, poly, vector, ideal */ /*2 * print for: intvec */ static BOOLEAN ipPrint_INTVEC(leftv u) { intvec *v=(intvec *)u->Data(); v->show(); PrintLn(); return FALSE; } /*2 * print for: intmat */ static BOOLEAN ipPrint_INTMAT(leftv u) { intvec *v=(intvec *)u->Data(); int i,j; for(i=0;irows();i++) { for(j=0;jcols();j++) { Print(" %5d",IMATELEM(*v,i+1,j+1)); } PrintLn(); } return FALSE; } /*2 * internal print for: matrix */ static void ipPrint_MA0(matrix m, const char *name) { if ((MATCOLS(m)>0)&&(MATROWS(m)>0)) { char **s=(char **)omAlloc(MATCOLS(m)*MATROWS(m)*sizeof(char*)); char *ss; int *l=(int *)omAlloc0(MATCOLS(m)*sizeof(int)); int i,j,k; int vl=si_max(colmax/MATCOLS(m),8); /* make enough space for the "largest" name*/ ss=(char *)omAlloc(14+strlen(name)); sprintf(ss,"%s[%d,%d]",name,MATCOLS(m),MATROWS(m)); vl=si_max(vl,(int)strlen(ss)); omFree(ss); /* convert all polys to string */ i=MATCOLS(m)*MATROWS(m)-1; ss=pString(m->m[i]); if ((int)strlen(ss)>colmax) { s[i]=NULL; omFree(ss); } else s[i]=ss; for(i--;i>=0;i--) { StringSetS(""); pString0(m->m[i]); StringAppendS(","); ss=StringEndS(); if ((int)strlen(ss)>colmax) s[i]=NULL; else s[i]=ss; } /* look up the width of all columns, put it in l[col_nr] */ /* insert names for very long entries */ for(i=MATROWS(m)-1;i>=0;i--) { for(j=MATCOLS(m)-1;j>=0;j--) { if (s[i*MATCOLS(m)+j]==NULL) { ss=(char *)omAlloc(14+strlen(name)); s[i*MATCOLS(m)+j]=ss; ss[0]='\0'; sprintf(ss,"%s[%d,%d]",name,i+1,j+1); if ((i!=MATROWS(m)-1) || (j!=MATCOLS(m)-1)) { strcat(ss,","); vl=si_max(vl,(int)strlen(ss)); } } k=strlen(s[i*MATCOLS(m)+j]); if (k>l[j]) l[j]=k; } } /* does it fit on a line ? */ int maxlen=0; for(j=MATCOLS(m)-1;j>=0;j--) { maxlen+=l[j]; } if (maxlen>colmax) { /* NO, it does not fit, so retry: */ /* look up the width of all columns, clear very long entriess */ /* put length in l[col_nr] */ /* insert names for cleared entries */ for(j=MATCOLS(m)-1;j>=0;j--) { for(i=MATROWS(m)-1;i>=0;i--) { k=strlen(s[i*MATCOLS(m)+j]); if (/*strlen(s[i*MATCOLS(m)+j])*/ k > vl) { omFree((ADDRESS)s[i*MATCOLS(m)+j]); ss=(char *)omAlloc(14+strlen(name)); s[i*MATCOLS(m)+j]=ss; ss[0]='\0'; sprintf(ss,"%s[%d,%d]",name,i+1,j+1); if ((i!=MATROWS(m)-1) || (j!=MATCOLS(m)-1)) { strcat(ss,","); } l[j]=strlen(s[i*MATCOLS(m)+j]); if (l[j]>vl) { //#ifdef TEST // PrintS("pagewidth too small in print(matrix)\n"); //#endif vl=l[j]; /* make large names fit*/ } i=MATROWS(m); } else { if (k>l[j]) l[j]=k; } } } } /*output of the matrix*/ for(i=0;icolmax) { PrintS("\n "); k=2; } k+=l[j]; Print("%-*.*s",l[j],l[j],s[i*MATCOLS(m)+j]); omFree(s[i*MATCOLS(m)+j]); } PrintLn(); } /* clean up */ omFreeSize((ADDRESS)s,MATCOLS(m)*MATROWS(m)*sizeof(char*)); omFreeSize((ADDRESS)l,MATCOLS(m)*sizeof(int)); } else Print("%d x %d zero matrix\n",MATROWS(m),MATCOLS(m)); } /*2 * print for: matrix */ static BOOLEAN ipPrint_MA(leftv u) { matrix m=(matrix)u->Data(); ipPrint_MA0(m,u->Name()); return FALSE; } /*2 * print for: ring */ static BOOLEAN ipPrint_RING(leftv u) { ring r=(ring)u->Data(); PrintS("polynomial ring, over a "); if (rField_is_Ring(r)) { if (rField_is_Domain(r)) PrintS("domain"); else PrintS("ring (with zero-divisors)"); } else PrintS("field"); if (r->OrdSgn==1) PrintS(", global"); else PrintS(", local/mixed"); PrintS(" ordering\n"); rWrite(r, TRUE); return FALSE; } #ifdef SINGULAR_4_1 static BOOLEAN ipPrint_CRING(leftv u) { coeffs r=(coeffs)u->Data(); if (nCoeff_is_Ring(r)) { if (nCoeff_is_Domain(r)) PrintS("domain: "); else PrintS("ring (with zero-divisors): "); } else PrintS("field: "); PrintS(nCoeffName(r)); return FALSE; } #endif /*2 * print for: vector */ static BOOLEAN ipPrint_V(leftv u) { polyset m=NULL; int l,j; /*convert into an array of the components*/ p_Vec2Polys((poly)u->Data(), &m, &l, currRing); /*output*/ PrintS("["); j=0; loop { PrintS(pString(m[j])); j++; if (j=0;j--) pDelete(&m[j]); omFreeSize((ADDRESS)m,l*sizeof(poly)); return FALSE; } BOOLEAN jjPRINT(leftv res, leftv u) { SPrintStart(); BOOLEAN bo=FALSE; switch(u->Typ()) { case INTVEC_CMD: bo=ipPrint_INTVEC(u); break; case INTMAT_CMD: bo=ipPrint_INTMAT(u); break; case MATRIX_CMD: bo=ipPrint_MA(u); break; case IDEAL_CMD: { char* s = u->String(NULL, FALSE, 2); PrintS(s); PrintLn(); omFree(s); break; } case MODUL_CMD: { matrix m = id_Module2Matrix(id_Copy((ideal) u->Data(),currRing),currRing); ipPrint_MA0(m, u->Name()); id_Delete((ideal *) &m,currRing); break; } case VECTOR_CMD: bo=ipPrint_V(u); break; case RING_CMD: case QRING_CMD: bo=ipPrint_RING(u); break; #ifdef SINGULAR_4_1 case CRING_CMD: bo=ipPrint_CRING(u); break; #endif default: u->Print(); break; } char *s=SPrintEnd(); if (u->next==NULL) { int l=strlen(s); if (s[l-1]=='\n') s[l-1]='\0'; } res->data=(void*)s; return bo; } /*2 * dbprint */ BOOLEAN jjDBPRINT(leftv res, leftv u) { BOOLEAN print=(printlevel>myynest); if ((u->next!=NULL)&&(u->Typ()==INT_CMD)) { print= (((int)((long)(u->Data()))) > 0); u=u->next; } if (print) { // BOOLEAN r=FALSE; leftv h=u; leftv hh; while (h!=NULL) { hh=h->next; h->next=NULL; if (jjPRINT(res, h)) return TRUE; PrintS((char*)res->data); omFree(res->data); PrintLn(); h->next=hh; h=hh; } } return FALSE; } static void ipPrintBetti(leftv u) { int i,j; int row_shift=(int)((long)(atGet(u,"rowShift",INT_CMD))); intvec * betti=(intvec *)u->Data(); // head line -------------------------------------------------------- PrintS(" "); // 6 spaces for no. and : for(j=0;jcols();j++) Print(" %5d",j); // 6 spaces pro column PrintS("\n------"); // 6 spaces for no. and : for(j=0;jcols();j++) PrintS("------"); // 6 spaces pro column PrintLn(); // the table -------------------------------------------------------- for(i=0;irows();i++) { Print("%5d:",i+row_shift); for(j=1;j<=betti->cols();j++) { int m=IMATELEM(*betti,i+1,j); if (m==0) PrintS(" -"); else Print(" %5d",m); } PrintLn(); } // sum -------------------------------------------------------------- PrintS("------"); // 6 spaces for no. and : for(j=0;jcols();j++) PrintS("------"); // 6 spaces pro column PrintS("\ntotal:"); for(j=0;jcols();j++) { int s=0; for(i=0;irows();i++) { s+=IMATELEM(*betti,i+1,j+1); } Print(" %5d",s); // 6 spaces pro column } PrintLn(); } /*2 * print(...,"format") */ BOOLEAN jjPRINT_FORMAT(leftv res, leftv u, leftv v) { /* ==================== betti ======================================== */ if ((u->Typ()==INTMAT_CMD)&&(strcmp((char *)v->Data(),"betti")==0)) { SPrintStart(); ipPrintBetti(u); char *s = SPrintEnd(); s[strlen(s)]='\0'; res->data=s; } else /* ======================== end betti ================================= */ { char* ns = omStrDup((char*) v->Data()); int dim = 1; if (strlen(ns) == 3 && ns[1] == '2') { dim = 2; ns[1] = ns[2]; ns[2] = '\0'; } if (strcmp(ns,"%l") == 0) { res->data = (char*) u->String(NULL, TRUE, dim); if (dim == 2) { char* ns = (char*) omAlloc(strlen((char*) res->data) + 2); strcpy(ns, (char*) res->data); omFree(res->data); strcat(ns, "\n"); res->data = ns; } } else if (strcmp(ns,"%t") == 0) { SPrintStart(); type_cmd(u); res->data = SPrintEnd(); if (dim != 2) ((char*)res->data)[strlen((char*)res->data) -1] = '\0'; } else if (strcmp(ns,"%;") == 0) { SPrintStart(); u->Print(); if (dim == 2) PrintLn(); res->data = SPrintEnd(); } else if (strcmp(ns,"%p") == 0) { iiExprArith1(res, u, PRINT_CMD); } else if (strcmp(ns,"%b") == 0 && (u->Typ()==INTMAT_CMD)) { SPrintStart(); ipPrintBetti(u); if (dim == 2) PrintLn(); res->data = SPrintEnd(); } else { res->data = u->String(NULL, FALSE, dim); if (dim == 2) { char* ns = (char*) omAlloc(strlen((char*) res->data) + 2); strcpy(ns, (char*) res->data); omFree(res->data); strcat(ns, "\n"); res->data = ns; } } omFree(ns); } return FALSE; } singular-4.0.3+ds/Singular/ipprint.h000066400000000000000000000006301266270727000173760ustar00rootroot00000000000000#ifndef IPPRINT_H #define IPPRINT_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: interpreter: printing */ #include class sleftv; typedef sleftv * leftv; BOOLEAN jjPRINT(leftv res, leftv u); BOOLEAN jjPRINT_FORMAT(leftv res, leftv u, leftv v); BOOLEAN jjDBPRINT(leftv res, leftv u); #endif singular-4.0.3+ds/Singular/ipshell.cc000066400000000000000000004731101266270727000175160ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // denominator_list #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // define this if you want to use the fast_map routine for mapping ideals #define FAST_MAP #ifdef FAST_MAP #include #endif #ifdef SINGULAR_4_1 #include #include #endif leftv iiCurrArgs=NULL; idhdl iiCurrProc=NULL; const char *lastreserved=NULL; static BOOLEAN iiNoKeepRing=TRUE; /*0 implementation*/ const char * iiTwoOps(int t) { if (t<127) { static char ch[2]; switch (t) { case '&': return "and"; case '|': return "or"; default: ch[0]=t; ch[1]='\0'; return ch; } } switch (t) { case COLONCOLON: return "::"; case DOTDOT: return ".."; //case PLUSEQUAL: return "+="; //case MINUSEQUAL: return "-="; case MINUSMINUS: return "--"; case PLUSPLUS: return "++"; case EQUAL_EQUAL: return "=="; case LE: return "<="; case GE: return ">="; case NOTEQUAL: return "<>"; default: return Tok2Cmdname(t); } } int iiOpsTwoChar(const char *s) { /* not handling: &&, ||, ** */ if (s[1]=='\0') return s[0]; else if (s[2]!='\0') return 0; switch(s[0]) { case '.': if (s[1]=='.') return DOTDOT; else return 0; case ':': if (s[1]==':') return COLONCOLON; else return 0; case '-': if (s[1]=='-') return MINUSMINUS; else return 0; case '+': if (s[1]=='+') return PLUSPLUS; else return 0; case '=': if (s[1]=='=') return EQUAL_EQUAL; else return 0; case '<': if (s[1]=='=') return LE; else if (s[1]=='>') return NOTEQUAL; else return 0; case '>': if (s[1]=='=') return GE; else return 0; case '!': if (s[1]=='=') return NOTEQUAL; else return 0; } return 0; } static void list1(const char* s, idhdl h,BOOLEAN c, BOOLEAN fullname) { char buffer[22]; int l; char buf2[128]; if(fullname) sprintf(buf2, "%s::%s", "", IDID(h)); else sprintf(buf2, "%s", IDID(h)); Print("%s%-30.30s [%d] ",s,buf2,IDLEV(h)); if (h == currRingHdl) PrintS("*"); PrintS(Tok2Cmdname((int)IDTYP(h))); ipListFlag(h); switch(IDTYP(h)) { case ALIAS_CMD: Print(" for %s",IDID((idhdl)IDDATA(h))); break; case INT_CMD: Print(" %d",IDINT(h)); break; case INTVEC_CMD:Print(" (%d)",IDINTVEC(h)->length()); break; case INTMAT_CMD:Print(" %d x %d",IDINTVEC(h)->rows(),IDINTVEC(h)->cols()); break; case POLY_CMD: case VECTOR_CMD:if (c) { PrintS(" ");wrp(IDPOLY(h)); if(IDPOLY(h) != NULL) { Print(", %d monomial(s)",pLength(IDPOLY(h))); } } break; case MODUL_CMD: Print(", rk %d", (int)(IDIDEAL(h)->rank)); case IDEAL_CMD: Print(", %u generator(s)", IDELEMS(IDIDEAL(h))); break; case MAP_CMD: Print(" from %s",IDMAP(h)->preimage); break; case MATRIX_CMD:Print(" %u x %u" ,MATROWS(IDMATRIX(h)) ,MATCOLS(IDMATRIX(h)) ); break; case PACKAGE_CMD: paPrint(IDID(h),IDPACKAGE(h)); break; case PROC_CMD: if((IDPROC(h)->libname!=NULL) && (strlen(IDPROC(h)->libname)>0)) Print(" from %s",IDPROC(h)->libname); if(IDPROC(h)->is_static) PrintS(" (static)"); break; case STRING_CMD: { char *s; l=strlen(IDSTRING(h)); memset(buffer,0,22); strncpy(buffer,IDSTRING(h),si_min(l,20)); if ((s=strchr(buffer,'\n'))!=NULL) { *s='\0'; } PrintS(" "); PrintS(buffer); if((s!=NULL) ||(l>20)) { Print("..., %d char(s)",l); } break; } case LIST_CMD: Print(", size: %d",IDLIST(h)->nr+1); break; case QRING_CMD: case RING_CMD: if ((IDRING(h)==currRing) && (currRingHdl!=h)) PrintS("(*)"); /* this is an alias to currRing */ #ifdef RDEBUG if (traceit &TRACE_SHOW_RINGS) Print(" <%lx>",(long)(IDRING(h))); #endif break; #ifdef SINGULAR_4_1 case CNUMBER_CMD: { number2 n=(number2)IDDATA(h); Print(" (%s)",nCoeffName(n->cf)); break; } case CMATRIX_CMD: { bigintmat *b=(bigintmat*)IDDATA(h); Print(" %d x %d (%s)", b->rows(),b->cols(), nCoeffName(b->basecoeffs())); break; } #endif /*default: break;*/ } PrintLn(); } void type_cmd(leftv v) { BOOLEAN oldShortOut = FALSE; if (currRing != NULL) { oldShortOut = currRing->ShortOut; currRing->ShortOut = 1; } int t=v->Typ(); Print("// %s %s ",v->Name(),Tok2Cmdname(t)); switch (t) { case MAP_CMD:Print(" from %s\n",((map)(v->Data()))->preimage); break; case INTMAT_CMD: Print(" %d x %d\n",((intvec*)(v->Data()))->rows(), ((intvec*)(v->Data()))->cols()); break; case MATRIX_CMD:Print(" %u x %u\n" , MATROWS((matrix)(v->Data())), MATCOLS((matrix)(v->Data())));break; case MODUL_CMD: Print(", rk %d\n", (int)(((ideal)(v->Data()))->rank));break; case LIST_CMD: Print(", size %d\n",((lists)(v->Data()))->nr+1); break; case PROC_CMD: case RING_CMD: case IDEAL_CMD: case QRING_CMD: PrintLn(); break; //case INT_CMD: //case STRING_CMD: //case INTVEC_CMD: //case POLY_CMD: //case VECTOR_CMD: //case PACKAGE_CMD: default: break; } v->Print(); if (currRing != NULL) currRing->ShortOut = oldShortOut; } static void killlocals0(int v, idhdl * localhdl, const ring r) { idhdl h = *localhdl; while (h!=NULL) { int vv; //Print("consider %s, lev: %d:",IDID(h),IDLEV(h)); if ((vv=IDLEV(h))>0) { if (vv < v) { if (iiNoKeepRing) { //PrintS(" break\n"); return; } h = IDNEXT(h); //PrintLn(); } else //if (vv >= v) { idhdl nexth = IDNEXT(h); killhdl2(h,localhdl,r); h = nexth; //PrintS("kill\n"); } } else { h = IDNEXT(h); //PrintLn(); } } } void killlocals_rec(idhdl *root,int v, ring r) { idhdl h=*root; while (h!=NULL) { if (IDLEV(h)>=v) { // Print("kill %s, lev %d for lev %d\n",IDID(h),IDLEV(h),v); idhdl n=IDNEXT(h); killhdl2(h,root,r); h=n; } else if (IDTYP(h)==PACKAGE_CMD) { // Print("into pack %s, lev %d for lev %d\n",IDID(h),IDLEV(h),v); if (IDPACKAGE(h)!=basePack) killlocals_rec(&(IDRING(h)->idroot),v,r); h=IDNEXT(h); } else if ((IDTYP(h)==RING_CMD) ||(IDTYP(h)==QRING_CMD)) { if ((IDRING(h)!=NULL) && (IDRING(h)->idroot!=NULL)) // we have to test IDRING(h)!=NULL: qring Q=groebner(...): killlocals { // Print("into ring %s, lev %d for lev %d\n",IDID(h),IDLEV(h),v); killlocals_rec(&(IDRING(h)->idroot),v,IDRING(h)); } h=IDNEXT(h); } else { // Print("skip %s lev %d for lev %d\n",IDID(h),IDLEV(h),v); h=IDNEXT(h); } } } BOOLEAN killlocals_list(int v, lists L) { if (L==NULL) return FALSE; BOOLEAN changed=FALSE; int n=L->nr; for(;n>=0;n--) { leftv h=&(L->m[n]); void *d=h->data; if (((h->rtyp==RING_CMD) || (h->rtyp==QRING_CMD)) && (((ring)d)->idroot!=NULL)) { if (d!=currRing) {changed=TRUE;rChangeCurrRing((ring)d);} killlocals0(v,&(((ring)h->data)->idroot),(ring)h->data); } else if (h->rtyp==LIST_CMD) changed|=killlocals_list(v,(lists)d); } return changed; } void killlocals(int v) { BOOLEAN changed=FALSE; idhdl sh=currRingHdl; ring cr=currRing; if (sh!=NULL) changed=((IDLEV(sh)ref>0)); //if (changed) Print("currRing=%s(%x), lev=%d,ref=%d\n",IDID(sh),IDRING(sh),IDLEV(sh),IDRING(sh)->ref); killlocals_rec(&(basePack->idroot),v,currRing); if (iiRETURNEXPR_len > myynest) { int t=iiRETURNEXPR.Typ(); if ((/*iiRETURNEXPR.Typ()*/ t==RING_CMD) || (/*iiRETURNEXPR.Typ()*/ t==QRING_CMD)) { leftv h=&iiRETURNEXPR; if (((ring)h->data)->idroot!=NULL) killlocals0(v,&(((ring)h->data)->idroot),(ring)h->data); } else if (/*iiRETURNEXPR.Typ()*/ t==LIST_CMD) { leftv h=&iiRETURNEXPR; changed |=killlocals_list(v,(lists)h->data); } } if (changed) { currRingHdl=rFindHdl(cr,NULL); if (currRingHdl==NULL) currRing=NULL; else if(cr!=currRing) rChangeCurrRing(cr); } if (myynest<=1) iiNoKeepRing=TRUE; //Print("end killlocals >= %d\n",v); //listall(); } void list_cmd(int typ, const char* what, const char *prefix,BOOLEAN iterate, BOOLEAN fullname) { package savePack=currPack; idhdl h,start; BOOLEAN all = typ<0; BOOLEAN really_all=FALSE; if ( typ==0 ) { if (strcmp(what,"all")==0) { if (currPack!=basePack) list_cmd(-1,NULL,prefix,iterate,fullname); // list current package really_all=TRUE; h=basePack->idroot; } else { h = ggetid(what); if (h!=NULL) { if (iterate) list1(prefix,h,TRUE,fullname); if (IDTYP(h)==ALIAS_CMD) PrintS("A"); if ((IDTYP(h)==RING_CMD) || (IDTYP(h)==QRING_CMD) //|| (IDTYP(h)==PACKE_CMD) ) { h=IDRING(h)->idroot; } else if(IDTYP(h)==PACKAGE_CMD) { currPack=IDPACKAGE(h); //Print("list_cmd:package\n"); all=TRUE;typ=PROC_CMD;fullname=TRUE;really_all=TRUE; h=IDPACKAGE(h)->idroot; } else { currPack=savePack; return; } } else { Werror("%s is undefined",what); currPack=savePack; return; } } all=TRUE; } else if (RingDependend(typ)) { h = currRing->idroot; } else h = IDROOT; start=h; while (h!=NULL) { if ((all && (IDTYP(h)!=PROC_CMD) &&(IDTYP(h)!=PACKAGE_CMD) #ifdef SINGULAR_4_1 &&(IDTYP(h)!=CRING_CMD) #endif ) || (typ == IDTYP(h)) #ifdef SINGULAR_4_1 || ((IDTYP(h)==CRING_CMD) && (typ==RING_CMD)) #else || ((IDTYP(h)==QRING_CMD) && (typ==RING_CMD)) #endif ) { list1(prefix,h,start==currRingHdl, fullname); if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD)) && (really_all || (all && (h==currRingHdl))) && ((IDLEV(h)==0)||(IDLEV(h)==myynest))) { list_cmd(0,IDID(h),"// ",FALSE); } if (IDTYP(h)==PACKAGE_CMD && really_all) { package save_p=currPack; currPack=IDPACKAGE(h); list_cmd(0,IDID(h),"// ",FALSE); currPack=save_p; } } h = IDNEXT(h); } currPack=savePack; } void test_cmd(int i) { int ii; if (i<0) { ii= -i; if (ii < 32) { si_opt_1 &= ~Sy_bit(ii); } else if (ii < 64) { si_opt_2 &= ~Sy_bit(ii-32); } else WerrorS("out of bounds\n"); } else if (i<32) { ii=i; if (Sy_bit(ii) & kOptions) { Warn("Gerhard, use the option command"); si_opt_1 |= Sy_bit(ii); } else if (Sy_bit(ii) & validOpts) si_opt_1 |= Sy_bit(ii); } else if (i<64) { ii=i-32; si_opt_2 |= Sy_bit(ii); } else WerrorS("out of bounds\n"); } int exprlist_length(leftv v) { int rc = 0; while (v!=NULL) { switch (v->Typ()) { case INT_CMD: case POLY_CMD: case VECTOR_CMD: case NUMBER_CMD: rc++; break; case INTVEC_CMD: case INTMAT_CMD: rc += ((intvec *)(v->Data()))->length(); break; case MATRIX_CMD: case IDEAL_CMD: case MODUL_CMD: { matrix mm = (matrix)(v->Data()); rc += mm->rows() * mm->cols(); } break; case LIST_CMD: rc+=((lists)v->Data())->nr+1; break; default: rc++; } v = v->next; } return rc; } BOOLEAN iiWRITE(leftv,leftv v) { sleftv vf; if (iiConvert(v->Typ(),LINK_CMD,iiTestConvert(v->Typ(),LINK_CMD),v,&vf)) { WerrorS("link expected"); return TRUE; } si_link l=(si_link)vf.Data(); if (vf.next == NULL) { WerrorS("write: need at least two arguments"); return TRUE; } BOOLEAN b=slWrite(l,vf.next); /* iiConvert preserves next */ if (b) { const char *s; if ((l!=NULL)&&(l->name!=NULL)) s=l->name; else s=sNoName; Werror("cannot write to %s",s); } vf.CleanUp(); return b; } leftv iiMap(map theMap, const char * what) { idhdl w,r; leftv v; int i; nMapFunc nMap; r=IDROOT->get(theMap->preimage,myynest); if ((currPack!=basePack) &&((r==NULL) || ((r->typ != RING_CMD) && (r->typ != QRING_CMD)))) r=basePack->idroot->get(theMap->preimage,myynest); if ((r==NULL) && (currRingHdl!=NULL) && (strcmp(theMap->preimage,IDID(currRingHdl))==0)) { r=currRingHdl; } if ((r!=NULL) && ((r->typ == RING_CMD) || (r->typ== QRING_CMD))) { ring src_ring=IDRING(r); if ((nMap=n_SetMap(src_ring->cf, currRing->cf))==NULL) { Werror("can not map from ground field of %s to current ground field", theMap->preimage); return NULL; } if (IDELEMS(theMap)N) { theMap->m=(polyset)omReallocSize((ADDRESS)theMap->m, IDELEMS(theMap)*sizeof(poly), (src_ring->N)*sizeof(poly)); for(i=IDELEMS(theMap);iN;i++) theMap->m[i]=NULL; IDELEMS(theMap)=src_ring->N; } if (what==NULL) { WerrorS("argument of a map must have a name"); } else if ((w=src_ring->idroot->get(what,myynest))!=NULL) { char *save_r=NULL; v=(leftv)omAlloc0Bin(sleftv_bin); sleftv tmpW; memset(&tmpW,0,sizeof(sleftv)); tmpW.rtyp=IDTYP(w); if (tmpW.rtyp==MAP_CMD) { tmpW.rtyp=IDEAL_CMD; save_r=IDMAP(w)->preimage; IDMAP(w)->preimage=0; } tmpW.data=IDDATA(w); // check overflow BOOLEAN overflow=FALSE; if ((tmpW.rtyp==IDEAL_CMD) || (tmpW.rtyp==MODUL_CMD) || (tmpW.rtyp==MAP_CMD)) { ideal id=(ideal)tmpW.data; for(int j=IDELEMS(theMap)-1;j>=0 && !overflow;j--) { if (theMap->m[j]!=NULL) { long deg_monexp=pTotaldegree(theMap->m[j]); for(int i=IDELEMS(id)-1;i>=0;i--) { poly p=id->m[i]; if ((p!=NULL) && (p_Totaldegree(p,src_ring)!=0) && ((unsigned long)deg_monexp > (currRing->bitmask / (unsigned long)p_Totaldegree(p,src_ring)/2))) { overflow=TRUE; break; } } } } } else if (tmpW.rtyp==POLY_CMD) { for(int j=IDELEMS(theMap)-1;j>=0 && !overflow;j--) { if (theMap->m[j]!=NULL) { long deg_monexp=pTotaldegree(theMap->m[j]); poly p=(poly)tmpW.data; if ((p!=NULL) && (p_Totaldegree(p,src_ring)!=0) && ((unsigned long)deg_monexp > (currRing->bitmask / (unsigned long)p_Totaldegree(p,src_ring)/2))) { overflow=TRUE; break; } } } } if (overflow) Warn("possible OVERFLOW in map, max exponent is %ld",currRing->bitmask/2); #if 0 if (((tmpW.rtyp==IDEAL_CMD)||(tmpW.rtyp==MODUL_CMD)) && idIs0(IDIDEAL(w))) { v->rtyp=tmpW.rtyp; v->data=idInit(IDELEMS(IDIDEAL(w)),IDIDEAL(w)->rank); } else #endif { #ifdef FAST_MAP if ((tmpW.rtyp==IDEAL_CMD) && (nMap == ndCopyMap) #ifdef HAVE_PLURAL && (!rIsPluralRing(currRing)) #endif ) { v->rtyp=IDEAL_CMD; char *tmp = theMap->preimage; theMap->preimage=(char*)1L; // map gets 1 as its rank (as an ideal) v->data=fast_map(IDIDEAL(w), src_ring, (ideal)theMap, currRing); theMap->preimage=tmp; // map gets its preimage back } else #endif if (maApplyFetch(MAP_CMD,theMap,v,&tmpW,src_ring,NULL,NULL,0,nMap)) { Werror("cannot map %s(%d)",Tok2Cmdname(w->typ),w->typ); omFreeBin((ADDRESS)v, sleftv_bin); if (save_r!=NULL) IDMAP(w)->preimage=save_r; return NULL; } } if (save_r!=NULL) { IDMAP(w)->preimage=save_r; IDMAP((idhdl)v)->preimage=omStrDup(save_r); v->rtyp=MAP_CMD; } return v; } else { Werror("%s undefined in %s",what,theMap->preimage); } } else { Werror("cannot find preimage %s",theMap->preimage); } return NULL; } #ifdef OLD_RES void iiMakeResolv(resolvente r, int length, int rlen, char * name, int typ0, intvec ** weights) { lists L=liMakeResolv(r,length,rlen,typ0,weights); int i=0; idhdl h; char * s=(char *)omAlloc(strlen(name)+5); while (i<=L->nr) { sprintf(s,"%s(%d)",name,i+1); if (i==0) h=enterid(s,myynest,typ0,&(currRing->idroot), FALSE); else h=enterid(s,myynest,MODUL_CMD,&(currRing->idroot), FALSE); if (h!=NULL) { h->data.uideal=(ideal)L->m[i].data; h->attribute=L->m[i].attribute; if (BVERBOSE(V_DEF_RES)) Print("//defining: %s as %d-th syzygy module\n",s,i+1); } else { idDelete((ideal *)&(L->m[i].data)); Warn("cannot define %s",s); } //L->m[i].data=NULL; //L->m[i].rtyp=0; //L->m[i].attribute=NULL; i++; } omFreeSize((ADDRESS)L->m,(L->nr+1)*sizeof(sleftv)); omFreeBin((ADDRESS)L, slists_bin); omFreeSize((ADDRESS)s,strlen(name)+5); } #endif //resolvente iiFindRes(char * name, int * len, int *typ0) //{ // char *s=(char *)omAlloc(strlen(name)+5); // int i=-1; // resolvente r; // idhdl h; // // do // { // i++; // sprintf(s,"%s(%d)",name,i+1); // h=currRing->idroot->get(s,myynest); // } while (h!=NULL); // *len=i-1; // if (*len<=0) // { // Werror("no objects %s(1),.. found",name); // omFreeSize((ADDRESS)s,strlen(name)+5); // return NULL; // } // r=(ideal *)omAlloc(/*(len+1)*/ i*sizeof(ideal)); // memset(r,0,(*len)*sizeof(ideal)); // i=-1; // *typ0=MODUL_CMD; // while (i<(*len)) // { // i++; // sprintf(s,"%s(%d)",name,i+1); // h=currRing->idroot->get(s,myynest); // if (h->typ != MODUL_CMD) // { // if ((i!=0) || (h->typ!=IDEAL_CMD)) // { // Werror("%s is not of type module",s); // omFreeSize((ADDRESS)r,(*len)*sizeof(ideal)); // omFreeSize((ADDRESS)s,strlen(name)+5); // return NULL; // } // *typ0=IDEAL_CMD; // } // if ((i>0) && (idIs0(r[i-1]))) // { // *len=i-1; // break; // } // r[i]=IDIDEAL(h); // } // omFreeSize((ADDRESS)s,strlen(name)+5); // return r; //} static resolvente iiCopyRes(resolvente r, int l) { int i; resolvente res=(ideal *)omAlloc0((l+1)*sizeof(ideal)); for (i=0; iData(); intvec *weights=(intvec*)atGet(v,"isHomog",INTVEC_CMD); int add_row_shift = 0; if (weights==NULL) weights=(intvec*)atGet(&(L->m[0]),"isHomog",INTVEC_CMD); if (weights!=NULL) add_row_shift=weights->min_in(); resolvente rr=liFindRes(L,&len,&typ0); if (rr==NULL) return TRUE; resolvente r=iiCopyRes(rr,len); syMinimizeResolvente(r,len,0); omFreeSize((ADDRESS)rr,len*sizeof(ideal)); len++; res->data=(char *)liMakeResolv(r,len,-1,typ0,NULL,add_row_shift); return FALSE; } BOOLEAN jjBETTI(leftv res, leftv u) { sleftv tmp; memset(&tmp,0,sizeof(tmp)); tmp.rtyp=INT_CMD; tmp.data=(void *)1; if ((u->Typ()==IDEAL_CMD) || (u->Typ()==MODUL_CMD)) return jjBETTI2_ID(res,u,&tmp); else return jjBETTI2(res,u,&tmp); } BOOLEAN jjBETTI2_ID(leftv res, leftv u, leftv v) { lists l=(lists) omAllocBin(slists_bin); l->Init(1); l->m[0].rtyp=u->Typ(); l->m[0].data=u->Data(); attr *a=u->Attribute(); if (a!=NULL) l->m[0].attribute=*a; sleftv tmp2; memset(&tmp2,0,sizeof(tmp2)); tmp2.rtyp=LIST_CMD; tmp2.data=(void *)l; BOOLEAN r=jjBETTI2(res,&tmp2,v); l->m[0].data=NULL; l->m[0].attribute=NULL; l->m[0].rtyp=DEF_CMD; l->Clean(); return r; } BOOLEAN jjBETTI2(leftv res, leftv u, leftv v) { resolvente r; int len; int reg,typ0; lists l=(lists)u->Data(); intvec *weights=NULL; int add_row_shift=0; intvec *ww=(intvec *)atGet(&(l->m[0]),"isHomog",INTVEC_CMD); if (ww!=NULL) { weights=ivCopy(ww); add_row_shift = ww->min_in(); (*weights) -= add_row_shift; } //Print("attr:%x\n",weights); r=liFindRes(l,&len,&typ0); if (r==NULL) return TRUE; res->data=(char *)syBetti(r,len,®,weights,(int)(long)v->Data()); omFreeSize((ADDRESS)r,(len)*sizeof(ideal)); atSet(res,omStrDup("rowShift"),(void*)(long)add_row_shift,INT_CMD); if (weights!=NULL) delete weights; return FALSE; } int iiRegularity(lists L) { int len,reg,typ0; resolvente r=liFindRes(L,&len,&typ0); if (r==NULL) return -2; intvec *weights=NULL; int add_row_shift=0; intvec *ww=(intvec *)atGet(&(L->m[0]),"isHomog",INTVEC_CMD); if (ww!=NULL) { weights=ivCopy(ww); add_row_shift = ww->min_in(); (*weights) -= add_row_shift; } //Print("attr:%x\n",weights); intvec *dummy=syBetti(r,len,®,weights); if (weights!=NULL) delete weights; delete dummy; omFreeSize((ADDRESS)r,len*sizeof(ideal)); return reg+1+add_row_shift; } BOOLEAN iiDebugMarker=TRUE; #define BREAK_LINE_LENGTH 80 void iiDebug() { #ifdef HAVE_SDB sdb_flags=1; #endif Print("\n-- break point in %s --\n",VoiceName()); if (iiDebugMarker) VoiceBackTrack(); char * s; iiDebugMarker=FALSE; s = (char *)omAlloc(BREAK_LINE_LENGTH+4); loop { memset(s,0,80); fe_fgets_stdin("",s,BREAK_LINE_LENGTH); if (s[BREAK_LINE_LENGTH-1]!='\0') { Print("line too long, max is %d chars\n",BREAK_LINE_LENGTH); } else break; } if (*s=='\n') { iiDebugMarker=TRUE; } #if MDEBUG else if(strncmp(s,"cont;",5)==0) { iiDebugMarker=TRUE; } #endif /* MDEBUG */ else { strcat( s, "\n;~\n"); newBuffer(s,BT_execute); } } lists scIndIndset(ideal S, BOOLEAN all, ideal Q) { int i; indset save; lists res=(lists)omAlloc0Bin(slists_bin); hexist = hInit(S, Q, &hNexist, currRing); if (hNexist == 0) { intvec *iv=new intvec(rVar(currRing)); for(i=0; iInit(1); res->m[0].rtyp=INTVEC_CMD; res->m[0].data=(intvec*)iv; return res; } else if (hisModule!=0) { res->Init(0); return res; } save = ISet = (indset)omAlloc0Bin(indlist_bin); hMu = 0; hwork = (scfmon)omAlloc(hNexist * sizeof(scmon)); hvar = (varset)omAlloc((rVar(currRing) + 1) * sizeof(int)); hpure = (scmon)omAlloc((1 + (rVar(currRing) * rVar(currRing))) * sizeof(long)); hrad = hexist; hNrad = hNexist; radmem = hCreate(rVar(currRing) - 1); hCo = rVar(currRing) + 1; hNvar = rVar(currRing); hRadical(hrad, &hNrad, hNvar); hSupp(hrad, hNrad, hvar, &hNvar); if (hNvar) { hCo = hNvar; memset(hpure, 0, (rVar(currRing) + 1) * sizeof(long)); hPure(hrad, 0, &hNrad, hvar, hNvar, hpure, &hNpure); hLexR(hrad, hNrad, hvar, hNvar); hDimSolve(hpure, hNpure, hrad, hNrad, hvar, hNvar); } if (hCo && (hCo < rVar(currRing))) { hIndMult(hpure, hNpure, hrad, hNrad, hvar, hNvar); } if (hMu!=0) { ISet = save; hMu2 = 0; if (all && (hCo+1 < rVar(currRing))) { JSet = (indset)omAlloc0Bin(indlist_bin); hIndAllMult(hpure, hNpure, hrad, hNrad, hvar, hNvar); i=hMu+hMu2; res->Init(i); if (hMu2 == 0) { omFreeBin((ADDRESS)JSet, indlist_bin); } } else { res->Init(hMu); } for (i=0;im[i].data = (void *)save->set; res->m[i].rtyp = INTVEC_CMD; ISet = save; save = save->nx; omFreeBin((ADDRESS)ISet, indlist_bin); } omFreeBin((ADDRESS)save, indlist_bin); if (hMu2 != 0) { save = JSet; for (i=hMu;im[i].data = (void *)save->set; res->m[i].rtyp = INTVEC_CMD; JSet = save; save = save->nx; omFreeBin((ADDRESS)JSet, indlist_bin); } omFreeBin((ADDRESS)save, indlist_bin); } } else { res->Init(0); omFreeBin((ADDRESS)ISet, indlist_bin); } hKill(radmem, rVar(currRing) - 1); omFreeSize((ADDRESS)hpure, (1 + (rVar(currRing) * rVar(currRing))) * sizeof(long)); omFreeSize((ADDRESS)hvar, (rVar(currRing) + 1) * sizeof(int)); omFreeSize((ADDRESS)hwork, hNexist * sizeof(scmon)); hDelete(hexist, hNexist); return res; } int iiDeclCommand(leftv sy, leftv name, int lev,int t, idhdl* root,BOOLEAN isring, BOOLEAN init_b) { BOOLEAN res=FALSE; const char *id = name->name; memset(sy,0,sizeof(sleftv)); if ((name->name==NULL)||(isdigit(name->name[0]))) { WerrorS("object to declare is not a name"); res=TRUE; } else { if (TEST_V_ALLWARN && (name->rtyp!=0) && (name->rtyp!=IDHDL) && (currRingHdl!=NULL) && (IDLEV(currRingHdl)==myynest)) { Warn("`%s` is %s in %s:%d:%s",name->name,Tok2Cmdname(name->rtyp), currentVoice->filename,yylineno,my_yylinebuf); } { sy->data = (char *)enterid(id,lev,t,root,init_b); } if (sy->data!=NULL) { sy->rtyp=IDHDL; currid=sy->name=IDID((idhdl)sy->data); // name->name=NULL; /* used in enterid */ //sy->e = NULL; if (name->next!=NULL) { sy->next=(leftv)omAllocBin(sleftv_bin); res=iiDeclCommand(sy->next,name->next,lev,t,root, isring); } } else res=TRUE; } name->CleanUp(); return res; } BOOLEAN iiDefaultParameter(leftv p) { attr at=NULL; if (iiCurrProc!=NULL) at=iiCurrProc->attribute->get("default_arg"); if (at==NULL) return FALSE; sleftv tmp; memset(&tmp,0,sizeof(sleftv)); tmp.rtyp=at->atyp; tmp.data=at->CopyA(); return iiAssign(p,&tmp); } BOOLEAN iiBranchTo(leftv r, leftv args) { // , // known: args!=NULL, l>=1 int l=args->listLength(); int ll=0; if (iiCurrArgs!=NULL) ll=iiCurrArgs->listLength(); if (ll!=(l-1)) return FALSE; leftv h=args; short *t=(short*)omAlloc(l*sizeof(short)); t[0]=l-1; int b; int i; for(i=1;inext) { if (h->Typ()!=STRING_CMD) { omFree(t); Werror("arg %d is not a string",i); return TRUE; } int tt; b=IsCmd((char *)h->Data(),tt); if(b) t[i]=tt; else { omFree(t); Werror("arg %d is not a type name",i); return TRUE; } } if (h->Typ()!=PROC_CMD) { omFree(t); Werror("last arg (%d) is not a proc",i); return TRUE; } b=iiCheckTypes(iiCurrArgs,t,0); omFree(t); if (b && (h->rtyp==IDHDL) && (h->e==NULL)) { BOOLEAN err; //Print("branchTo: %s\n",h->Name()); iiCurrProc=(idhdl)h->data; procinfo * pi=IDPROC(iiCurrProc); if( pi->data.s.body==NULL ) { iiGetLibProcBuffer(pi); if (pi->data.s.body==NULL) return TRUE; } if ((pi->pack!=NULL)&&(currPack!=pi->pack)) { currPack=pi->pack; iiCheckPack(currPack); currPackHdl=packFindHdl(currPack); //Print("set pack=%s\n",IDID(currPackHdl)); } err=iiAllStart(pi,pi->data.s.body,BT_proc,pi->data.s.body_lineno-(iiCurrArgs==NULL)); exitBuffer(BT_proc); if (iiCurrArgs!=NULL) { if (!err) Warn("too many arguments for %s",IDID(iiCurrProc)); iiCurrArgs->CleanUp(); omFreeBin((ADDRESS)iiCurrArgs, sleftv_bin); iiCurrArgs=NULL; } return 2-err; } return FALSE; } BOOLEAN iiParameter(leftv p) { if (iiCurrArgs==NULL) { if (strcmp(p->name,"#")==0) return iiDefaultParameter(p); Werror("not enough arguments for proc %s",VoiceName()); p->CleanUp(); return TRUE; } leftv h=iiCurrArgs; leftv rest=h->next; /*iiCurrArgs is not NULL here*/ BOOLEAN is_default_list=FALSE; if (strcmp(p->name,"#")==0) { is_default_list=TRUE; rest=NULL; } else { h->next=NULL; } BOOLEAN res=iiAssign(p,h); if (is_default_list) { iiCurrArgs=NULL; } else { iiCurrArgs=rest; } h->CleanUp(); omFreeBin((ADDRESS)h, sleftv_bin); return res; } static BOOLEAN iiInternalExport (leftv v, int toLev) { idhdl h=(idhdl)v->data; //Print("iiInternalExport('%s',%d)%s\n", v->name, toLev,""); if (IDLEV(h)==0) { if (BVERBOSE(V_REDEFINE)) Warn("`%s` is already global",IDID(h)); } else { h=IDROOT->get(v->name,toLev); idhdl *root=&IDROOT; if ((h==NULL)&&(currRing!=NULL)) { h=currRing->idroot->get(v->name,toLev); root=&currRing->idroot; } BOOLEAN keepring=FALSE; if ((h!=NULL)&&(IDLEV(h)==toLev)) { if (IDTYP(h)==v->Typ()) { if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD)) && (v->Data()==IDDATA(h))) { IDRING(h)->ref++; keepring=TRUE; IDLEV(h)=toLev; //WarnS("keepring"); return FALSE; } if (BVERBOSE(V_REDEFINE)) { Warn("redefining %s",IDID(h)); } #ifdef USE_IILOCALRING if (iiLocalRing[0]==IDRING(h) && (!keepring)) iiLocalRing[0]=NULL; #else proclevel *p=procstack; while (p->next!=NULL) p=p->next; if ((p->cRing==IDRING(h)) && (!keepring)) { p->cRing=NULL; p->cRingHdl=NULL; } #endif killhdl2(h,root,currRing); } else { return TRUE; } } h=(idhdl)v->data; IDLEV(h)=toLev; if (keepring) IDRING(h)->ref--; iiNoKeepRing=FALSE; //Print("export %s\n",IDID(h)); } return FALSE; } BOOLEAN iiInternalExport (leftv v, int toLev, package rootpack) { idhdl h=(idhdl)v->data; if(h==NULL) { Warn("'%s': no such identifier\n", v->name); return FALSE; } package frompack=v->req_packhdl; if (frompack==NULL) frompack=currPack; if ((RingDependend(IDTYP(h))) || ((IDTYP(h)==LIST_CMD) && (lRingDependend(IDLIST(h))) ) ) { //Print("// ==> Ringdependent set nesting to 0\n"); return (iiInternalExport(v, toLev)); } else { IDLEV(h)=toLev; v->req_packhdl=rootpack; if (h==frompack->idroot) { frompack->idroot=h->next; } else { idhdl hh=frompack->idroot; while ((hh!=NULL) && (hh->next!=h)) hh=hh->next; if ((hh!=NULL) && (hh->next==h)) hh->next=h->next; else { Werror("`%s` not found",v->Name()); return TRUE; } } h->next=rootpack->idroot; rootpack->idroot=h; } return FALSE; } BOOLEAN iiExport (leftv v, int toLev) { BOOLEAN nok=FALSE; leftv r=v; while (v!=NULL) { if ((v->name==NULL)||(v->rtyp==0)||(v->e!=NULL)) { Werror("cannot export:%s of internal type %d",v->name,v->rtyp); nok=TRUE; } else { if(iiInternalExport(v, toLev)) { r->CleanUp(); return TRUE; } } v=v->next; } r->CleanUp(); return nok; } /*assume root!=idroot*/ BOOLEAN iiExport (leftv v, int toLev, package pack) { #ifdef SINGULAR_4_1 if ((pack==basePack)&&(pack!=currPack)) { Warn("'exportto' to Top is depreciated in >>%s<<",my_yylinebuf);} #endif BOOLEAN nok=FALSE; leftv rv=v; while (v!=NULL) { if ((v->name==NULL)||(v->rtyp==0)||(v->e!=NULL) ) { Werror("cannot export:%s of internal type %d",v->name,v->rtyp); nok=TRUE; } else { idhdl old=pack->idroot->get( v->name,toLev); if (old!=NULL) { if ((pack==currPack) && (old==(idhdl)v->data)) { if (BVERBOSE(V_REDEFINE)) Warn("`%s` is already global",IDID(old)); break; } else if (IDTYP(old)==v->Typ()) { if (BVERBOSE(V_REDEFINE)) { Warn("redefining %s",IDID(old)); } v->name=omStrDup(v->name); killhdl2(old,&(pack->idroot),currRing); } else { rv->CleanUp(); return TRUE; } } //Print("iiExport: pack=%s\n",IDID(root)); if(iiInternalExport(v, toLev, pack)) { rv->CleanUp(); return TRUE; } } v=v->next; } rv->CleanUp(); return nok; } BOOLEAN iiCheckRing(int i) { if (currRing==NULL) { #ifdef SIQ if (siq<=0) { #endif if (RingDependend(i)) { WerrorS("no ring active"); return TRUE; } #ifdef SIQ } #endif } return FALSE; } poly iiHighCorner(ideal I, int ak) { int i; if(!idIsZeroDim(I)) return NULL; // not zero-dim. poly po=NULL; if (rHasLocalOrMixedOrdering_currRing()) { scComputeHC(I,currRing->qideal,ak,po); if (po!=NULL) { pGetCoeff(po)=nInit(1); for (i=rVar(currRing); i>0; i--) { if (pGetExp(po, i) > 0) pDecrExp(po,i); } pSetComp(po,ak); pSetm(po); } } else po=pOne(); return po; } void iiCheckPack(package &p) { if (p==basePack) return; idhdl t=basePack->idroot; while ((t!=NULL) && (IDTYP(t)!=PACKAGE_CMD) && (IDPACKAGE(t)!=p)) t=t->next; if (t==NULL) { WarnS("package not found\n"); p=basePack; } return; } idhdl rDefault(const char *s) { idhdl tmp=NULL; if (s!=NULL) tmp = enterid(s, myynest, RING_CMD, &IDROOT); if (tmp==NULL) return NULL; // if ((currRing->ppNoether)!=NULL) pDelete(&(currRing->ppNoether)); if (sLastPrinted.RingDependend()) { sLastPrinted.CleanUp(); memset(&sLastPrinted,0,sizeof(sleftv)); } ring r = IDRING(tmp); r->cf = nInitChar(n_Zp, (void*)32003); // r->cf->ch = 32003; r->N = 3; /*r->P = 0; Alloc0 in idhdl::set, ipid.cc*/ /*names*/ r->names = (char **) omAlloc0(3 * sizeof(char_ptr)); r->names[0] = omStrDup("x"); r->names[1] = omStrDup("y"); r->names[2] = omStrDup("z"); /*weights: entries for 3 blocks: NULL*/ r->wvhdl = (int **)omAlloc0(3 * sizeof(int_ptr)); /*order: dp,C,0*/ r->order = (int *) omAlloc(3 * sizeof(int *)); r->block0 = (int *)omAlloc0(3 * sizeof(int *)); r->block1 = (int *)omAlloc0(3 * sizeof(int *)); /* ringorder dp for the first block: var 1..3 */ r->order[0] = ringorder_dp; r->block0[0] = 1; r->block1[0] = 3; /* ringorder C for the second block: no vars */ r->order[1] = ringorder_C; /* the last block: everything is 0 */ r->order[2] = 0; /* complete ring intializations */ rComplete(r); rSetHdl(tmp); return currRingHdl; } idhdl rFindHdl(ring r, idhdl n) { idhdl h=rSimpleFindHdl(r,IDROOT,n); if (h!=NULL) return h; if (IDROOT!=basePack->idroot) h=rSimpleFindHdl(r,basePack->idroot,n); if (h!=NULL) return h; proclevel *p=procstack; while(p!=NULL) { if ((p->cPack!=basePack) && (p->cPack!=currPack)) h=rSimpleFindHdl(r,p->cPack->idroot,n); if (h!=NULL) return h; p=p->next; } idhdl tmp=basePack->idroot; while (tmp!=NULL) { if (IDTYP(tmp)==PACKAGE_CMD) h=rSimpleFindHdl(r,IDPACKAGE(tmp)->idroot,n); if (h!=NULL) return h; tmp=IDNEXT(tmp); } return NULL; } void rDecomposeCF(leftv h,const ring r,const ring R) { lists L=(lists)omAlloc0Bin(slists_bin); L->Init(4); h->rtyp=LIST_CMD; h->data=(void *)L; // 0: char/ cf - ring // 1: list (var) // 2: list (ord) // 3: qideal // ---------------------------------------- // 0: char/ cf - ring L->m[0].rtyp=INT_CMD; L->m[0].data=(void *)(long)r->cf->ch; // ---------------------------------------- // 1: list (var) lists LL=(lists)omAlloc0Bin(slists_bin); LL->Init(r->N); int i; for(i=0; iN; i++) { LL->m[i].rtyp=STRING_CMD; LL->m[i].data=(void *)omStrDup(r->names[i]); } L->m[1].rtyp=LIST_CMD; L->m[1].data=(void *)LL; // ---------------------------------------- // 2: list (ord) LL=(lists)omAlloc0Bin(slists_bin); i=rBlocks(r)-1; LL->Init(i); i--; lists LLL; for(; i>=0; i--) { intvec *iv; int j; LL->m[i].rtyp=LIST_CMD; LLL=(lists)omAlloc0Bin(slists_bin); LLL->Init(2); LLL->m[0].rtyp=STRING_CMD; LLL->m[0].data=(void *)omStrDup(rSimpleOrdStr(r->order[i])); if (r->block1[i]-r->block0[i] >=0 ) { j=r->block1[i]-r->block0[i]; if(r->order[i]==ringorder_M) j=(j+1)*(j+1)-1; iv=new intvec(j+1); if ((r->wvhdl!=NULL) && (r->wvhdl[i]!=NULL)) { for(;j>=0; j--) (*iv)[j]=r->wvhdl[i][j]; } else switch (r->order[i]) { case ringorder_dp: case ringorder_Dp: case ringorder_ds: case ringorder_Ds: case ringorder_lp: for(;j>=0; j--) (*iv)[j]=1; break; default: /* do nothing */; } } else { iv=new intvec(1); } LLL->m[1].rtyp=INTVEC_CMD; LLL->m[1].data=(void *)iv; LL->m[i].data=(void *)LLL; } L->m[2].rtyp=LIST_CMD; L->m[2].data=(void *)LL; // ---------------------------------------- // 3: qideal L->m[3].rtyp=IDEAL_CMD; if (nCoeff_is_transExt(R->cf)) L->m[3].data=(void *)idInit(1,1); else { ideal q=idInit(IDELEMS(r->qideal)); q->m[0]=p_Init(R); pSetCoeff0(q->m[0],(number)(r->qideal->m[0])); L->m[3].data=(void *)q; // I->m[0] = pNSet(R->minpoly); } // ---------------------------------------- } #ifdef SINGULAR_4_1 static void rDecomposeC(leftv h,const coeffs C) /* field is R or C */ { lists L=(lists)omAlloc0Bin(slists_bin); if (nCoeff_is_long_C(C)) L->Init(3); else L->Init(2); h->rtyp=LIST_CMD; h->data=(void *)L; // 0: char/ cf - ring // 1: list (var) // 2: list (ord) // ---------------------------------------- // 0: char/ cf - ring L->m[0].rtyp=INT_CMD; L->m[0].data=(void *)0; // ---------------------------------------- // 1: lists LL=(lists)omAlloc0Bin(slists_bin); LL->Init(2); LL->m[0].rtyp=INT_CMD; LL->m[0].data=(void *)(long)si_max(C->float_len,SHORT_REAL_LENGTH/2); LL->m[1].rtyp=INT_CMD; LL->m[1].data=(void *)(long)si_max(C->float_len2,SHORT_REAL_LENGTH); L->m[1].rtyp=LIST_CMD; L->m[1].data=(void *)LL; // ---------------------------------------- // 2: list (par) if (nCoeff_is_long_C(C)) { L->m[2].rtyp=STRING_CMD; L->m[2].data=(void *)omStrDup(*n_ParameterNames(C)); } // ---------------------------------------- } #else static void rDecomposeC(leftv h,const ring R) /* field is R or C */ { lists L=(lists)omAlloc0Bin(slists_bin); if (rField_is_long_C(R)) L->Init(3); else L->Init(2); h->rtyp=LIST_CMD; h->data=(void *)L; // 0: char/ cf - ring // 1: list (var) // 2: list (ord) // ---------------------------------------- // 0: char/ cf - ring L->m[0].rtyp=INT_CMD; L->m[0].data=(void *)0; // ---------------------------------------- // 1: lists LL=(lists)omAlloc0Bin(slists_bin); LL->Init(2); LL->m[0].rtyp=INT_CMD; LL->m[0].data=(void *)(long)si_max(R->cf->float_len,SHORT_REAL_LENGTH/2); LL->m[1].rtyp=INT_CMD; LL->m[1].data=(void *)(long)si_max(R->cf->float_len2,SHORT_REAL_LENGTH); L->m[1].rtyp=LIST_CMD; L->m[1].data=(void *)LL; // ---------------------------------------- // 2: list (par) if (rField_is_long_C(R)) { L->m[2].rtyp=STRING_CMD; L->m[2].data=(void *)omStrDup(*rParameter(R)); } // ---------------------------------------- } #endif #ifdef SINGULAR_4_1 #ifdef HAVE_RINGS void rDecomposeRing(leftv h,const coeffs C) /* field is R or C */ { lists L=(lists)omAlloc0Bin(slists_bin); if (nCoeff_is_Ring(C)) L->Init(1); else L->Init(2); h->rtyp=LIST_CMD; h->data=(void *)L; // 0: char/ cf - ring // 1: list (module) // ---------------------------------------- // 0: char/ cf - ring L->m[0].rtyp=STRING_CMD; L->m[0].data=(void *)omStrDup("integer"); // ---------------------------------------- // 1: modulo if (nCoeff_is_Ring_Z(C)) return; lists LL=(lists)omAlloc0Bin(slists_bin); LL->Init(2); LL->m[0].rtyp=BIGINT_CMD; LL->m[0].data=nlMapGMP((number) C->modBase, C, coeffs_BIGINT); LL->m[1].rtyp=INT_CMD; LL->m[1].data=(void *) C->modExponent; L->m[1].rtyp=LIST_CMD; L->m[1].data=(void *)LL; } #endif #else #ifdef HAVE_RINGS void rDecomposeRing(leftv h,const ring R) /* field is R or C */ { lists L=(lists)omAlloc0Bin(slists_bin); if (rField_is_Ring_Z(R)) L->Init(1); else L->Init(2); h->rtyp=LIST_CMD; h->data=(void *)L; // 0: char/ cf - ring // 1: list (module) // ---------------------------------------- // 0: char/ cf - ring L->m[0].rtyp=STRING_CMD; L->m[0].data=(void *)omStrDup("integer"); // ---------------------------------------- // 1: module if (rField_is_Ring_Z(R)) return; lists LL=(lists)omAlloc0Bin(slists_bin); LL->Init(2); LL->m[0].rtyp=BIGINT_CMD; LL->m[0].data=nlMapGMP((number) R->cf->modBase, R->cf, R->cf); // TODO: what is this?? // extern number nlMapGMP(number from, const coeffs src, const coeffs dst); // FIXME: replace with n_InitMPZ(R->cf->modBase, coeffs_BIGINT); ? LL->m[1].rtyp=INT_CMD; LL->m[1].data=(void *) R->cf->modExponent; L->m[1].rtyp=LIST_CMD; L->m[1].data=(void *)LL; } #endif #endif #ifdef SINGULAR_4_1 BOOLEAN rDecompose_CF(leftv res,const coeffs C) { assume( C != NULL ); // sanity check: require currRing==r for rings with polynomial data if ( nCoeff_is_algExt(C) && (C != currRing->cf)) { WerrorS("ring with polynomial data must be the base ring or compatible"); return TRUE; } if (nCoeff_is_numeric(C)) { rDecomposeC(res,C); } #ifdef HAVE_RINGS else if (nCoeff_is_Ring(C)) { rDecomposeRing(res,C); } #endif else if ( C->extRing!=NULL )// nCoeff_is_algExt(r->cf)) { rDecomposeCF(res, C->extRing, currRing); } else if(nCoeff_is_GF(C)) { lists Lc=(lists)omAlloc0Bin(slists_bin); Lc->Init(4); // char: Lc->m[0].rtyp=INT_CMD; Lc->m[0].data=(void*)(long)C->m_nfCharQ; // var: lists Lv=(lists)omAlloc0Bin(slists_bin); Lv->Init(1); Lv->m[0].rtyp=STRING_CMD; Lv->m[0].data=(void *)omStrDup(*n_ParameterNames(C)); Lc->m[1].rtyp=LIST_CMD; Lc->m[1].data=(void*)Lv; // ord: lists Lo=(lists)omAlloc0Bin(slists_bin); Lo->Init(1); lists Loo=(lists)omAlloc0Bin(slists_bin); Loo->Init(2); Loo->m[0].rtyp=STRING_CMD; Loo->m[0].data=(void *)omStrDup(rSimpleOrdStr(ringorder_lp)); intvec *iv=new intvec(1); (*iv)[0]=1; Loo->m[1].rtyp=INTVEC_CMD; Loo->m[1].data=(void *)iv; Lo->m[0].rtyp=LIST_CMD; Lo->m[0].data=(void*)Loo; Lc->m[2].rtyp=LIST_CMD; Lc->m[2].data=(void*)Lo; // q-ideal: Lc->m[3].rtyp=IDEAL_CMD; Lc->m[3].data=(void *)idInit(1,1); // ---------------------- res->rtyp=LIST_CMD; res->data=(void*)Lc; } else { res->rtyp=INT_CMD; res->data=(void *)(long)C->ch; } // ---------------------------------------- return FALSE; } #endif #ifdef SINGULAR_4_1 lists rDecompose(const ring r) { assume( r != NULL ); const coeffs C = r->cf; assume( C != NULL ); // sanity check: require currRing==r for rings with polynomial data if ( (r!=currRing) && ( (nCoeff_is_algExt(C) && (C != currRing->cf)) || (r->qideal != NULL) #ifdef HAVE_PLURAL || (rIsPluralRing(r)) #endif ) ) { WerrorS("ring with polynomial data must be the base ring or compatible"); return NULL; } // 0: char/ cf - ring // 1: list (var) // 2: list (ord) // 3: qideal // possibly: // 4: C // 5: D lists L=(lists)omAlloc0Bin(slists_bin); if (rIsPluralRing(r)) L->Init(6); else L->Init(4); // ---------------------------------------- // 0: char/ cf - ring L->m[0].rtyp=CRING_CMD; L->m[0].data=(char*)r->cf; r->cf->ref++; // ---------------------------------------- // 1: list (var) lists LL=(lists)omAlloc0Bin(slists_bin); LL->Init(r->N); int i; for(i=0; iN; i++) { LL->m[i].rtyp=STRING_CMD; LL->m[i].data=(void *)omStrDup(r->names[i]); } L->m[1].rtyp=LIST_CMD; L->m[1].data=(void *)LL; // ---------------------------------------- // 2: list (ord) LL=(lists)omAlloc0Bin(slists_bin); i=rBlocks(r)-1; LL->Init(i); i--; lists LLL; for(; i>=0; i--) { intvec *iv; int j; LL->m[i].rtyp=LIST_CMD; LLL=(lists)omAlloc0Bin(slists_bin); LLL->Init(2); LLL->m[0].rtyp=STRING_CMD; LLL->m[0].data=(void *)omStrDup(rSimpleOrdStr(r->order[i])); if(r->order[i] == ringorder_IS) // || r->order[i] == ringorder_s || r->order[i] == ringorder_S) { assume( r->block0[i] == r->block1[i] ); const int s = r->block0[i]; assume( -2 < s && s < 2); iv=new intvec(1); (*iv)[0] = s; } else if (r->block1[i]-r->block0[i] >=0 ) { int bl=j=r->block1[i]-r->block0[i]; if (r->order[i]==ringorder_M) { j=(j+1)*(j+1)-1; bl=j+1; } else if (r->order[i]==ringorder_am) { j+=r->wvhdl[i][bl+1]; } iv=new intvec(j+1); if ((r->wvhdl!=NULL) && (r->wvhdl[i]!=NULL)) { for(;j>=0; j--) (*iv)[j]=r->wvhdl[i][j+(j>bl)]; } else switch (r->order[i]) { case ringorder_dp: case ringorder_Dp: case ringorder_ds: case ringorder_Ds: case ringorder_lp: for(;j>=0; j--) (*iv)[j]=1; break; default: /* do nothing */; } } else { iv=new intvec(1); } LLL->m[1].rtyp=INTVEC_CMD; LLL->m[1].data=(void *)iv; LL->m[i].data=(void *)LLL; } L->m[2].rtyp=LIST_CMD; L->m[2].data=(void *)LL; // ---------------------------------------- // 3: qideal L->m[3].rtyp=IDEAL_CMD; if (r->qideal==NULL) L->m[3].data=(void *)idInit(1,1); else L->m[3].data=(void *)idCopy(r->qideal); // ---------------------------------------- #ifdef HAVE_PLURAL // NC! in rDecompose if (rIsPluralRing(r)) { L->m[4].rtyp=MATRIX_CMD; L->m[4].data=(void *)mp_Copy(r->GetNC()->C, r, r); L->m[5].rtyp=MATRIX_CMD; L->m[5].data=(void *)mp_Copy(r->GetNC()->D, r, r); } #endif return L; } #endif #ifndef SINGULAR_4_1 lists rDecompose(const ring r) { assume( r != NULL ); const coeffs C = r->cf; assume( C != NULL ); // sanity check: require currRing==r for rings with polynomial data if ( (r!=currRing) && ( (nCoeff_is_algExt(C) && (C != currRing->cf)) || (r->qideal != NULL) #ifdef HAVE_PLURAL || (rIsPluralRing(r)) #endif ) ) { WerrorS("ring with polynomial data must be the base ring or compatible"); return NULL; } // 0: char/ cf - ring // 1: list (var) // 2: list (ord) // 3: qideal // possibly: // 4: C // 5: D lists L=(lists)omAlloc0Bin(slists_bin); if (rIsPluralRing(r)) L->Init(6); else L->Init(4); // ---------------------------------------- // 0: char/ cf - ring if (rField_is_numeric(r)) { rDecomposeC(&(L->m[0]),r); } #ifdef HAVE_RINGS else if (rField_is_Ring(r)) { rDecomposeRing(&(L->m[0]),r); } #endif else if ( r->cf->extRing!=NULL )// nCoeff_is_algExt(r->cf)) { rDecomposeCF(&(L->m[0]), r->cf->extRing, r); } else if(rField_is_GF(r)) { lists Lc=(lists)omAlloc0Bin(slists_bin); Lc->Init(4); // char: Lc->m[0].rtyp=INT_CMD; Lc->m[0].data=(void*)(long)r->cf->m_nfCharQ; // var: lists Lv=(lists)omAlloc0Bin(slists_bin); Lv->Init(1); Lv->m[0].rtyp=STRING_CMD; Lv->m[0].data=(void *)omStrDup(*rParameter(r)); Lc->m[1].rtyp=LIST_CMD; Lc->m[1].data=(void*)Lv; // ord: lists Lo=(lists)omAlloc0Bin(slists_bin); Lo->Init(1); lists Loo=(lists)omAlloc0Bin(slists_bin); Loo->Init(2); Loo->m[0].rtyp=STRING_CMD; Loo->m[0].data=(void *)omStrDup(rSimpleOrdStr(ringorder_lp)); intvec *iv=new intvec(1); (*iv)[0]=1; Loo->m[1].rtyp=INTVEC_CMD; Loo->m[1].data=(void *)iv; Lo->m[0].rtyp=LIST_CMD; Lo->m[0].data=(void*)Loo; Lc->m[2].rtyp=LIST_CMD; Lc->m[2].data=(void*)Lo; // q-ideal: Lc->m[3].rtyp=IDEAL_CMD; Lc->m[3].data=(void *)idInit(1,1); // ---------------------- L->m[0].rtyp=LIST_CMD; L->m[0].data=(void*)Lc; } else { L->m[0].rtyp=INT_CMD; L->m[0].data=(void *)(long)r->cf->ch; } // ---------------------------------------- // 1: list (var) lists LL=(lists)omAlloc0Bin(slists_bin); LL->Init(r->N); int i; for(i=0; iN; i++) { LL->m[i].rtyp=STRING_CMD; LL->m[i].data=(void *)omStrDup(r->names[i]); } L->m[1].rtyp=LIST_CMD; L->m[1].data=(void *)LL; // ---------------------------------------- // 2: list (ord) LL=(lists)omAlloc0Bin(slists_bin); i=rBlocks(r)-1; LL->Init(i); i--; lists LLL; for(; i>=0; i--) { intvec *iv; int j; LL->m[i].rtyp=LIST_CMD; LLL=(lists)omAlloc0Bin(slists_bin); LLL->Init(2); LLL->m[0].rtyp=STRING_CMD; LLL->m[0].data=(void *)omStrDup(rSimpleOrdStr(r->order[i])); if(r->order[i] == ringorder_IS) // || r->order[i] == ringorder_s || r->order[i] == ringorder_S) { assume( r->block0[i] == r->block1[i] ); const int s = r->block0[i]; assume( -2 < s && s < 2); iv=new intvec(1); (*iv)[0] = s; } else if (r->block1[i]-r->block0[i] >=0 ) { int bl=j=r->block1[i]-r->block0[i]; if (r->order[i]==ringorder_M) { j=(j+1)*(j+1)-1; bl=j+1; } else if (r->order[i]==ringorder_am) { j+=r->wvhdl[i][bl+1]; } iv=new intvec(j+1); if ((r->wvhdl!=NULL) && (r->wvhdl[i]!=NULL)) { for(;j>=0; j--) (*iv)[j]=r->wvhdl[i][j+(j>bl)]; } else switch (r->order[i]) { case ringorder_dp: case ringorder_Dp: case ringorder_ds: case ringorder_Ds: case ringorder_lp: for(;j>=0; j--) (*iv)[j]=1; break; default: /* do nothing */; } } else { iv=new intvec(1); } LLL->m[1].rtyp=INTVEC_CMD; LLL->m[1].data=(void *)iv; LL->m[i].data=(void *)LLL; } L->m[2].rtyp=LIST_CMD; L->m[2].data=(void *)LL; // ---------------------------------------- // 3: qideal L->m[3].rtyp=IDEAL_CMD; if (r->qideal==NULL) L->m[3].data=(void *)idInit(1,1); else L->m[3].data=(void *)idCopy(r->qideal); // ---------------------------------------- #ifdef HAVE_PLURAL // NC! in rDecompose if (rIsPluralRing(r)) { L->m[4].rtyp=MATRIX_CMD; L->m[4].data=(void *)mp_Copy(r->GetNC()->C, r, r); L->m[5].rtyp=MATRIX_CMD; L->m[5].data=(void *)mp_Copy(r->GetNC()->D, r, r); } #endif return L; } #endif void rComposeC(lists L, ring R) /* field is R or C */ { // ---------------------------------------- // 0: char/ cf - ring if ((L->m[0].rtyp!=INT_CMD) || (L->m[0].data!=(char *)0)) { Werror("invald coeff. field description, expecting 0"); return; } // R->cf->ch=0; // ---------------------------------------- // 1: if (L->m[1].rtyp!=LIST_CMD) Werror("invald coeff. field description, expecting precision list"); lists LL=(lists)L->m[1].data; int r1=(int)(long)LL->m[0].data; int r2=(int)(long)LL->m[1].data; if (L->nr==2) // complex R->cf = nInitChar(n_long_C, NULL); else if ((r1<=SHORT_REAL_LENGTH) && (r2=SHORT_REAL_LENGTH)) R->cf = nInitChar(n_R, NULL); else { LongComplexInfo* p = (LongComplexInfo *)omAlloc0(sizeof(LongComplexInfo)); p->float_len=r1; p->float_len2=r2; R->cf = nInitChar(n_long_R, NULL); } if ((r1<=SHORT_REAL_LENGTH) // should go into nInitChar && (r2=SHORT_REAL_LENGTH)) { R->cf->float_len=SHORT_REAL_LENGTH/2; R->cf->float_len2=SHORT_REAL_LENGTH; } else { R->cf->float_len=si_min(r1,32767); R->cf->float_len2=si_min(r2,32767); } // ---------------------------------------- // 2: list (par) if (L->nr==2) { //R->cf->extRing->N=1; if (L->m[2].rtyp!=STRING_CMD) { Werror("invald coeff. field description, expecting parameter name"); return; } //(rParameter(R))=(char**)omAlloc0(rPar(R)*sizeof(char_ptr)); rParameter(R)[0]=omStrDup((char *)L->m[2].data); } // ---------------------------------------- } #ifdef HAVE_RINGS void rComposeRing(lists L, ring R) /* field is R or C */ { // ---------------------------------------- // 0: string: integer // no further entries --> Z mpz_ptr modBase = NULL; unsigned int modExponent = 1; modBase = (mpz_ptr) omAlloc(sizeof(mpz_t)); if (L->nr == 0) { mpz_init_set_ui(modBase,0); modExponent = 1; } // ---------------------------------------- // 1: else { if (L->m[1].rtyp!=LIST_CMD) Werror("invald data, expecting list of numbers"); lists LL=(lists)L->m[1].data; if ((LL->nr >= 0) && LL->m[0].rtyp == BIGINT_CMD) { number tmp= (number) LL->m[0].data; // never use CopyD() on list elements // assume that tmp is integer, not rational n_MPZ (modBase, tmp, coeffs_BIGINT); } else if (LL->nr >= 0 && LL->m[0].rtyp == INT_CMD) { mpz_init_set_ui(modBase,(unsigned long) LL->m[0].data); } else { mpz_init_set_ui(modBase,0); } if (LL->nr >= 1) { modExponent = (unsigned long) LL->m[1].data; } else { modExponent = 1; } } // ---------------------------------------- if ((mpz_cmp_ui(modBase, 1) == 0) && (mpz_cmp_ui(modBase, 0) < 0)) { Werror("Wrong ground ring specification (module is 1)"); return; } if (modExponent < 1) { Werror("Wrong ground ring specification (exponent smaller than 1"); return; } // module is 0 ---> integers if (mpz_cmp_ui(modBase, 0) == 0) { R->cf=nInitChar(n_Z,NULL); } // we have an exponent else if (modExponent > 1) { //R->cf->ch = R->cf->modExponent; if ((mpz_cmp_ui(modBase, 2) == 0) && (modExponent <= 8*sizeof(unsigned long))) { /* this branch should be active for modExponent = 2..32 resp. 2..64, depending on the size of a long on the respective platform */ R->cf=nInitChar(n_Z2m,(void*)(long)modExponent); // Use Z/2^ch omFreeSize (modBase, sizeof(mpz_t)); } else { //ringtype 3 ZnmInfo info; info.base= modBase; info.exp= modExponent; R->cf=nInitChar(n_Znm,(void*) &info); } } // just a module m > 1 else { //ringtype = 2; //const int ch = mpz_get_ui(modBase); ZnmInfo info; info.base= modBase; info.exp= modExponent; R->cf=nInitChar(n_Zn,(void*) &info); } } #endif static void rRenameVars(ring R) { int i,j; BOOLEAN ch; do { ch=0; for(i=0;iN-1;i++) { for(j=i+1;jN;j++) { if (strcmp(R->names[i],R->names[j])==0) { ch=TRUE; Warn("name conflict var(%d) and var(%d): `%s`, rename to `@%s`",i+1,j+1,R->names[i],R->names[i]); omFree(R->names[j]); R->names[j]=(char *)omAlloc(2+strlen(R->names[i])); sprintf(R->names[j],"@%s",R->names[i]); } } } } while (ch); for(i=0;iN;j++) { if (strcmp(rParameter(R)[i],R->names[j])==0) { Warn("name conflict par(%d) and var(%d): `%s`, renaming the VARIABLE to `@@(%d)`",i+1,j+1,R->names[j],i+1); // omFree(rParameter(R)[i]); // rParameter(R)[i]=(char *)omAlloc(10); // sprintf(rParameter(R)[i],"@@(%d)",i+1); omFree(R->names[j]); R->names[j]=(char *)omAlloc(10); sprintf(R->names[j],"@@(%d)",i+1); } } } } ring rCompose(const lists L, const BOOLEAN check_comp) { if ((L->nr!=3) #ifdef HAVE_PLURAL &&(L->nr!=5) #endif ) return NULL; int is_gf_char=0; // 0: char/ cf - ring // 1: list (var) // 2: list (ord) // 3: qideal // possibly: // 4: C // 5: D ring R = (ring) omAlloc0Bin(sip_sring_bin); // ------------------------------------------------------------------ // 0: char: #ifdef SINGULAR_4_1 if (L->m[0].Typ()==CRING_CMD) { R->cf=(coeffs)L->m[0].Data(); R->cf->ref++; } else #endif if (L->m[0].Typ()==INT_CMD) { int ch = (int)(long)L->m[0].Data(); assume( ch >= 0 ); if (ch == 0) // Q? R->cf = nInitChar(n_Q, NULL); else { int l = IsPrime(ch); // Zp? if( l != ch ) { Warn("%d is invalid characteristic of ground field. %d is used.", ch, l); ch = l; } R->cf = nInitChar(n_Zp, (void*)(long)ch); } } else if (L->m[0].Typ()==LIST_CMD) // something complicated... { lists LL=(lists)L->m[0].Data(); #ifdef HAVE_RINGS if (LL->m[0].Typ() == STRING_CMD) // 1st comes a string? { rComposeRing(LL, R); // Ring!? } else #endif if (LL->nr < 3) rComposeC(LL,R); // R, long_R, long_C else { if (LL->m[0].Typ()==INT_CMD) { int ch = (int)(long)LL->m[0].Data(); while ((ch!=fftable[is_gf_char]) && (fftable[is_gf_char])) is_gf_char++; if (fftable[is_gf_char]==0) is_gf_char=-1; if(is_gf_char!= -1) { GFInfo param; param.GFChar = ch; param.GFDegree = 1; param.GFPar_name = (const char*)(((lists)(LL->m[1].Data()))->m[0].Data()); // nfInitChar should be able to handle the case when ch is in fftables! R->cf = nInitChar(n_GF, (void*)¶m); } } if( R->cf == NULL ) { ring extRing = rCompose((lists)L->m[0].Data(),FALSE); if (extRing==NULL) { WerrorS("could not create the specified coefficient field"); goto rCompose_err; } if( extRing->qideal != NULL ) // Algebraic extension { AlgExtInfo extParam; extParam.r = extRing; R->cf = nInitChar(n_algExt, (void*)&extParam); } else // Transcendental extension { TransExtInfo extParam; extParam.r = extRing; assume( extRing->qideal == NULL ); R->cf = nInitChar(n_transExt, &extParam); } } } } #ifdef SINGULAR_4_1 else if (L->m[0].Typ()==CRING_CMD) { R->cf=(coeffs)L->m[0].Data(); R->cf->ref++; } #endif else { WerrorS("coefficient field must be described by `int` or `list`"); goto rCompose_err; } if( R->cf == NULL ) { WerrorS("could not create coefficient field described by the input!"); goto rCompose_err; } // ------------------------- VARS --------------------------- if (L->m[1].Typ()==LIST_CMD) { lists v=(lists)L->m[1].Data(); R->N = v->nr+1; if (R->N<=0) { WerrorS("no ring variables"); goto rCompose_err; } R->names = (char **)omAlloc0(R->N * sizeof(char_ptr)); int i; for(i=0;iN;i++) { if (v->m[i].Typ()==STRING_CMD) R->names[i]=omStrDup((char *)v->m[i].Data()); else if (v->m[i].Typ()==POLY_CMD) { poly p=(poly)v->m[i].Data(); int nr=pIsPurePower(p); if (nr>0) R->names[i]=omStrDup(currRing->names[nr-1]); else { Werror("var name %d must be a string or a ring variable",i+1); goto rCompose_err; } } else { Werror("var name %d must be `string`",i+1); goto rCompose_err; } } } else { WerrorS("variable must be given as `list`"); goto rCompose_err; } // ------------------------ ORDER ------------------------------ if (L->m[2].Typ()==LIST_CMD) { lists v=(lists)L->m[2].Data(); int n= v->nr+2; int j; // initialize fields of R R->order=(int *)omAlloc0(n*sizeof(int)); R->block0=(int *)omAlloc0(n*sizeof(int)); R->block1=(int *)omAlloc0(n*sizeof(int)); R->wvhdl=(int**)omAlloc0(n*sizeof(int_ptr)); // init order, so that rBlocks works correctly for (j=0; j < n-1; j++) R->order[j] = (int) ringorder_unspec; // orderings for(j=0;jm[j].Typ()!=LIST_CMD) { WerrorS("ordering must be list of lists"); goto rCompose_err; } lists vv=(lists)v->m[j].Data(); if ((vv->nr!=1) || (vv->m[0].Typ()!=STRING_CMD) || ((vv->m[1].Typ()!=INTVEC_CMD) && (vv->m[1].Typ()!=INT_CMD))) { WerrorS("ordering name must be a (string,intvec)"); goto rCompose_err; } R->order[j]=rOrderName(omStrDup((char*)vv->m[0].Data())); // assume STRING if (j==0) R->block0[0]=1; else { int jj=j-1; while((jj>=0) && ((R->order[jj]== ringorder_a) || (R->order[jj]== ringorder_aa) || (R->order[jj]== ringorder_am) || (R->order[jj]== ringorder_c) || (R->order[jj]== ringorder_C) || (R->order[jj]== ringorder_s) || (R->order[jj]== ringorder_S) )) { //Print("jj=%, skip %s\n",rSimpleOrdStr(R->order[jj])); jj--; } if (jj<0) R->block0[j]=1; else R->block0[j]=R->block1[jj]+1; } intvec *iv; if (vv->m[1].Typ()==INT_CMD) iv=new intvec((int)(long)vv->m[1].Data(),(int)(long)vv->m[1].Data()); else iv=ivCopy((intvec*)vv->m[1].Data()); //assume INTVEC int iv_len=iv->length(); R->block1[j]=si_max(R->block0[j],R->block0[j]+iv_len-1); if (R->block1[j]>R->N) { R->block1[j]=R->N; iv_len=R->block1[j]-R->block0[j]+1; } //Print("block %d from %d to %d\n",j,R->block0[j], R->block1[j]); int i; switch (R->order[j]) { case ringorder_ws: case ringorder_Ws: R->OrdSgn=-1; case ringorder_aa: case ringorder_a: case ringorder_wp: case ringorder_Wp: R->wvhdl[j] =( int *)omAlloc(iv_len*sizeof(int)); for (i=0; iwvhdl[j][i]=(*iv)[i]; } break; case ringorder_am: R->wvhdl[j] =( int *)omAlloc((iv->length()+1)*sizeof(int)); for (i=0; iwvhdl[j][i]=(*iv)[i]; } R->wvhdl[j][i]=iv->length() - iv_len; //printf("ivlen:%d,iv->len:%d,mod:%d\n",iv_len,iv->length(),R->wvhdl[j][i]); for (; ilength(); i++) { R->wvhdl[j][i+1]=(*iv)[i]; } break; case ringorder_M: R->wvhdl[j] =( int *)omAlloc((iv->length())*sizeof(int)); for (i=0; ilength();i++) R->wvhdl[j][i]=(*iv)[i]; R->block1[j]=si_max(R->block0[j],R->block0[j]+(int)sqrt((double)(iv->length()-1))); if (R->block1[j]>R->N) { WerrorS("ordering matrix too big"); goto rCompose_err; } break; case ringorder_ls: case ringorder_ds: case ringorder_Ds: case ringorder_rs: R->OrdSgn=-1; case ringorder_lp: case ringorder_dp: case ringorder_Dp: case ringorder_rp: break; case ringorder_S: break; case ringorder_c: case ringorder_C: R->block1[j]=R->block0[j]=0; break; case ringorder_s: break; case ringorder_IS: { R->block1[j] = R->block0[j] = 0; if( iv->length() > 0 ) { const int s = (*iv)[0]; assume( -2 < s && s < 2 ); R->block1[j] = R->block0[j] = s; } break; } case 0: case ringorder_unspec: break; } delete iv; } // sanity check j=n-2; if ((R->order[j]==ringorder_c) || (R->order[j]==ringorder_C) || (R->order[j]==ringorder_unspec)) j--; if (R->block1[j] != R->N) { if (((R->order[j]==ringorder_dp) || (R->order[j]==ringorder_ds) || (R->order[j]==ringorder_Dp) || (R->order[j]==ringorder_Ds) || (R->order[j]==ringorder_rp) || (R->order[j]==ringorder_rs) || (R->order[j]==ringorder_lp) || (R->order[j]==ringorder_ls)) && R->block0[j] <= R->N) { R->block1[j] = R->N; } else { Werror("ordering incomplete: size (%d) should be %d",R->block1[j],R->N); goto rCompose_err; } } if (R->block0[j]>R->N) { Werror("not enough variables (%d) for ordering block %d, scanned so far:",R->N,j+1); for(int ii=0;ii<=j;ii++) Werror("ord[%d]: %s from v%d to v%d",ii+1,rSimpleOrdStr(R->order[ii]),R->block0[ii],R->block1[ii]); goto rCompose_err; } if (check_comp) { BOOLEAN comp_order=FALSE; int jj; for(jj=0;jjorder[jj]==ringorder_c) || (R->order[jj]==ringorder_C)) { comp_order=TRUE; break; } } if (!comp_order) { R->order=(int*)omRealloc0Size(R->order,n*sizeof(int),(n+1)*sizeof(int)); R->block0=(int*)omRealloc0Size(R->block0,n*sizeof(int),(n+1)*sizeof(int)); R->block1=(int*)omRealloc0Size(R->block1,n*sizeof(int),(n+1)*sizeof(int)); R->wvhdl=(int**)omRealloc0Size(R->wvhdl,n*sizeof(int_ptr),(n+1)*sizeof(int_ptr)); R->order[n-1]=ringorder_C; R->block0[n-1]=0; R->block1[n-1]=0; R->wvhdl[n-1]=NULL; n++; } } } else { WerrorS("ordering must be given as `list`"); goto rCompose_err; } // ------------------------ ??????? -------------------- rRenameVars(R); rComplete(R); /*#ifdef HAVE_RINGS // currently, coefficients which are ring elements require a global ordering: if (rField_is_Ring(R) && (R->OrdSgn==-1)) { WerrorS("global ordering required for these coefficients"); goto rCompose_err; } #endif*/ // ------------------------ Q-IDEAL ------------------------ if (L->m[3].Typ()==IDEAL_CMD) { ideal q=(ideal)L->m[3].Data(); if (q->m[0]!=NULL) { if (R->cf != currRing->cf) //->cf->ch!=currRing->cf->ch) { #if 0 WerrorS("coefficient fields must be equal if q-ideal !=0"); goto rCompose_err; #else ring orig_ring=currRing; rChangeCurrRing(R); int *perm=NULL; int *par_perm=NULL; int par_perm_size=0; nMapFunc nMap; if ((nMap=nSetMap(orig_ring->cf))==NULL) { if (rEqual(orig_ring,currRing)) { nMap=n_SetMap(currRing->cf, currRing->cf); } else // Allow imap/fetch to be make an exception only for: if ( (rField_is_Q_a(orig_ring) && // Q(a..) -> Q(a..) || Q || Zp || Zp(a) (rField_is_Q(currRing) || rField_is_Q_a(currRing) || (rField_is_Zp(currRing) || rField_is_Zp_a(currRing)))) || (rField_is_Zp_a(orig_ring) && // Zp(a..) -> Zp(a..) || Zp (rField_is_Zp(currRing, rInternalChar(orig_ring)) || rField_is_Zp_a(currRing, rInternalChar(orig_ring)))) ) { par_perm_size=rPar(orig_ring); // if ((orig_ring->minpoly != NULL) || (orig_ring->qideal != NULL)) // naSetChar(rInternalChar(orig_ring),orig_ring); // else ntSetChar(rInternalChar(orig_ring),orig_ring); nSetChar(currRing->cf); } else { WerrorS("coefficient fields must be equal if q-ideal !=0"); goto rCompose_err; } } perm=(int *)omAlloc0((orig_ring->N+1)*sizeof(int)); if (par_perm_size!=0) par_perm=(int *)omAlloc0(par_perm_size*sizeof(int)); int i; #if 0 // use imap: maFindPerm(orig_ring->names,orig_ring->N,orig_ring->parameter,orig_ring->P, currRing->names,currRing->N,currRing->parameter, currRing->P, perm,par_perm, currRing->ch); #else // use fetch if ((rPar(orig_ring)>0) && (rPar(currRing)==0)) { for(i=si_min(rPar(orig_ring),rVar(currRing))-1;i>=0;i--) par_perm[i]=i+1; } else if (par_perm_size!=0) for(i=si_min(rPar(orig_ring),rPar(currRing))-1;i>=0;i--) par_perm[i]=-(i+1); for(i=si_min(orig_ring->N,rVar(currRing));i>0;i--) perm[i]=i; #endif ideal dest_id=idInit(IDELEMS(q),1); for(i=IDELEMS(q)-1; i>=0; i--) { dest_id->m[i]=p_PermPoly(q->m[i],perm,orig_ring, currRing,nMap, par_perm,par_perm_size); // PrintS("map:");pWrite(dest_id->m[i]);PrintLn(); pTest(dest_id->m[i]); } R->qideal=dest_id; if (perm!=NULL) omFreeSize((ADDRESS)perm,(orig_ring->N+1)*sizeof(int)); if (par_perm!=NULL) omFreeSize((ADDRESS)par_perm,par_perm_size*sizeof(int)); rChangeCurrRing(orig_ring); #endif } else R->qideal=idrCopyR(q,currRing,R); } } else { WerrorS("q-ideal must be given as `ideal`"); goto rCompose_err; } // --------------------------------------------------------------- #ifdef HAVE_PLURAL if (L->nr==5) { if (nc_CallPlural((matrix)L->m[4].Data(), (matrix)L->m[5].Data(), NULL,NULL, R, true, // !!! true, false, currRing, FALSE)) goto rCompose_err; // takes care about non-comm. quotient! i.e. calls "nc_SetupQuotient" due to last true } #endif return R; rCompose_err: if (R->N>0) { int i; if (R->names!=NULL) { i=R->N-1; while (i>=0) { if (R->names[i]!=NULL) omFree(R->names[i]); i--; } omFree(R->names); } } if (R->order!=NULL) omFree(R->order); if (R->block0!=NULL) omFree(R->block0); if (R->block1!=NULL) omFree(R->block1); if (R->wvhdl!=NULL) omFree(R->wvhdl); omFree(R); return NULL; } // from matpol.cc /*2 * compute the jacobi matrix of an ideal */ BOOLEAN mpJacobi(leftv res,leftv a) { int i,j; matrix result; ideal id=(ideal)a->Data(); result =mpNew(IDELEMS(id),rVar(currRing)); for (i=1; i<=IDELEMS(id); i++) { for (j=1; j<=rVar(currRing); j++) { MATELEM(result,i,j) = pDiff(id->m[i-1],j); } } res->data=(char *)result; return FALSE; } /*2 * returns the Koszul-matrix of degree d of a vectorspace with dimension n * uses the first n entrees of id, if id <> NULL */ BOOLEAN mpKoszul(leftv res,leftv c/*ip*/, leftv b/*in*/, leftv id) { int n=(int)(long)b->Data(); int d=(int)(long)c->Data(); int k,l,sign,row,col; matrix result; ideal temp; BOOLEAN bo; poly p; if ((d>n) || (d<1) || (n<1)) { res->data=(char *)mpNew(1,1); return FALSE; } int *choise = (int*)omAlloc(d*sizeof(int)); if (id==NULL) temp=idMaxIdeal(1); else temp=(ideal)id->Data(); k = binom(n,d); l = k*d; l /= n-d+1; result =mpNew(l,k); col = 1; idInitChoise(d,1,n,&bo,choise); while (!bo) { sign = 1; for (l=1;l<=d;l++) { if (choise[l-1]<=IDELEMS(temp)) { p = pCopy(temp->m[choise[l-1]-1]); if (sign == -1) p = pNeg(p); sign *= -1; row = idGetNumberOfChoise(l-1,d,1,n,choise); MATELEM(result,row,col) = p; } } col++; idGetNextChoise(d,n,&bo,choise); } if (id==NULL) idDelete(&temp); res->data=(char *)result; return FALSE; } // from syz1.cc /*2 * read out the Betti numbers from resolution * (interpreter interface) */ BOOLEAN syBetti2(leftv res, leftv u, leftv w) { syStrategy syzstr=(syStrategy)u->Data(); BOOLEAN minim=(int)(long)w->Data(); int row_shift=0; int add_row_shift=0; intvec *weights=NULL; intvec *ww=(intvec *)atGet(u,"isHomog",INTVEC_CMD); if (ww!=NULL) { weights=ivCopy(ww); add_row_shift = ww->min_in(); (*weights) -= add_row_shift; } res->data=(void *)syBettiOfComputation(syzstr,minim,&row_shift,weights); //row_shift += add_row_shift; //Print("row_shift=%d, add_row_shift=%d\n",row_shift,add_row_shift); atSet(res,omStrDup("rowShift"),(void*)(long)add_row_shift,INT_CMD); return FALSE; } BOOLEAN syBetti1(leftv res, leftv u) { sleftv tmp; memset(&tmp,0,sizeof(tmp)); tmp.rtyp=INT_CMD; tmp.data=(void *)1; return syBetti2(res,u,&tmp); } /*3 * converts a resolution into a list of modules */ lists syConvRes(syStrategy syzstr,BOOLEAN toDel,int add_row_shift) { resolvente fullres = syzstr->fullres; resolvente minres = syzstr->minres; const int length = syzstr->length; if ((fullres==NULL) && (minres==NULL)) { if (syzstr->hilb_coeffs==NULL) { // La Scala fullres = syReorder(syzstr->res, length, syzstr); } else { // HRES minres = syReorder(syzstr->orderedRes, length, syzstr); syKillEmptyEntres(minres, length); } } resolvente tr; int typ0=IDEAL_CMD; if (minres!=NULL) tr = minres; else tr = fullres; resolvente trueres=NULL; intvec ** w=NULL; if (length>0) { trueres = (resolvente)omAlloc0((length)*sizeof(ideal)); for (int i=(length)-1;i>=0;i--) { if (tr[i]!=NULL) { trueres[i] = idCopy(tr[i]); } } if ( id_RankFreeModule(trueres[0], currRing) > 0) typ0 = MODUL_CMD; if (syzstr->weights!=NULL) { w = (intvec**)omAlloc0(length*sizeof(intvec*)); for (int i=length-1;i>=0;i--) { if (syzstr->weights[i]!=NULL) w[i] = ivCopy(syzstr->weights[i]); } } } lists li = liMakeResolv(trueres, length, syzstr->list_length,typ0, w, add_row_shift); if (w != NULL) omFreeSize(w, length*sizeof(intvec*)); if (toDel) syKillComputation(syzstr); else { if( fullres != NULL && syzstr->fullres == NULL ) syzstr->fullres = fullres; if( minres != NULL && syzstr->minres == NULL ) syzstr->minres = minres; } return li; } /*3 * converts a list of modules into a resolution */ syStrategy syConvList(lists li,BOOLEAN toDel) { int typ0; syStrategy result=(syStrategy)omAlloc0(sizeof(ssyStrategy)); resolvente fr = liFindRes(li,&(result->length),&typ0,&(result->weights)); if (fr != NULL) { result->fullres = (resolvente)omAlloc0((result->length+1)*sizeof(ideal)); for (int i=result->length-1;i>=0;i--) { if (fr[i]!=NULL) result->fullres[i] = idCopy(fr[i]); } result->list_length=result->length; omFreeSize((ADDRESS)fr,(result->length)*sizeof(ideal)); } else { omFreeSize(result, sizeof(ssyStrategy)); result = NULL; } if (toDel) li->Clean(); return result; } /*3 * converts a list of modules into a minimal resolution */ syStrategy syForceMin(lists li) { int typ0; syStrategy result=(syStrategy)omAlloc0(sizeof(ssyStrategy)); resolvente fr = liFindRes(li,&(result->length),&typ0); result->minres = (resolvente)omAlloc0((result->length+1)*sizeof(ideal)); for (int i=result->length-1;i>=0;i--) { if (fr[i]!=NULL) result->minres[i] = idCopy(fr[i]); } omFreeSize((ADDRESS)fr,(result->length)*sizeof(ideal)); return result; } // from weight.cc BOOLEAN kWeight(leftv res,leftv id) { ideal F=(ideal)id->Data(); intvec * iv = new intvec(rVar(currRing)); polyset s; int sl, n, i; int *x; res->data=(char *)iv; s = F->m; sl = IDELEMS(F) - 1; n = rVar(currRing); double wNsqr = (double)2.0 / (double)n; wFunctional = wFunctionalBuch; x = (int * )omAlloc(2 * (n + 1) * sizeof(int)); wCall(s, sl, x, wNsqr, currRing); for (i = n; i!=0; i--) (*iv)[i-1] = x[i + n + 1]; omFreeSize((ADDRESS)x, 2 * (n + 1) * sizeof(int)); return FALSE; } BOOLEAN kQHWeight(leftv res,leftv v) { res->data=(char *)id_QHomWeight((ideal)v->Data(), currRing); if (res->data==NULL) res->data=(char *)new intvec(rVar(currRing)); return FALSE; } /*==============================================================*/ // from clapsing.cc #if 0 BOOLEAN jjIS_SQR_FREE(leftv res, leftv u) { BOOLEAN b=singclap_factorize((poly)(u->CopyD()), &v, 0); res->data=(void *)b; } #endif BOOLEAN jjRESULTANT(leftv res, leftv u, leftv v, leftv w) { res->data=singclap_resultant((poly)u->CopyD(),(poly)v->CopyD(), (poly)w->CopyD(), currRing); return errorreported; } BOOLEAN jjCHARSERIES(leftv res, leftv u) { res->data=singclap_irrCharSeries((ideal)u->Data(), currRing); return (res->data==NULL); } // from semic.cc #ifdef HAVE_SPECTRUM // ---------------------------------------------------------------------------- // Initialize a spectrum deep from a singular lists // ---------------------------------------------------------------------------- void copy_deep( spectrum& spec, lists l ) { spec.mu = (int)(long)(l->m[0].Data( )); spec.pg = (int)(long)(l->m[1].Data( )); spec.n = (int)(long)(l->m[2].Data( )); spec.copy_new( spec.n ); intvec *num = (intvec*)l->m[3].Data( ); intvec *den = (intvec*)l->m[4].Data( ); intvec *mul = (intvec*)l->m[5].Data( ); for( int i=0; iInit( 6 ); intvec *num = new intvec( spec.n ); intvec *den = new intvec( spec.n ); intvec *mult = new intvec( spec.n ); for( int i=0; im[0].rtyp = INT_CMD; // milnor number L->m[1].rtyp = INT_CMD; // geometrical genus L->m[2].rtyp = INT_CMD; // # of spectrum numbers L->m[3].rtyp = INTVEC_CMD; // numerators L->m[4].rtyp = INTVEC_CMD; // denomiantors L->m[5].rtyp = INTVEC_CMD; // multiplicities L->m[0].data = (void*)(long)spec.mu; L->m[1].data = (void*)(long)spec.pg; L->m[2].data = (void*)(long)spec.n; L->m[3].data = (void*)num; L->m[4].data = (void*)den; L->m[5].data = (void*)mult; return L; } // from spectrum.cc // ---------------------------------------------------------------------------- // print out an error message for a spectrum list // ---------------------------------------------------------------------------- typedef enum { semicOK, semicMulNegative, semicListTooShort, semicListTooLong, semicListFirstElementWrongType, semicListSecondElementWrongType, semicListThirdElementWrongType, semicListFourthElementWrongType, semicListFifthElementWrongType, semicListSixthElementWrongType, semicListNNegative, semicListWrongNumberOfNumerators, semicListWrongNumberOfDenominators, semicListWrongNumberOfMultiplicities, semicListMuNegative, semicListPgNegative, semicListNumNegative, semicListDenNegative, semicListMulNegative, semicListNotSymmetric, semicListNotMonotonous, semicListMilnorWrong, semicListPGWrong } semicState; void list_error( semicState state ) { switch( state ) { case semicListTooShort: WerrorS( "the list is too short" ); break; case semicListTooLong: WerrorS( "the list is too long" ); break; case semicListFirstElementWrongType: WerrorS( "first element of the list should be int" ); break; case semicListSecondElementWrongType: WerrorS( "second element of the list should be int" ); break; case semicListThirdElementWrongType: WerrorS( "third element of the list should be int" ); break; case semicListFourthElementWrongType: WerrorS( "fourth element of the list should be intvec" ); break; case semicListFifthElementWrongType: WerrorS( "fifth element of the list should be intvec" ); break; case semicListSixthElementWrongType: WerrorS( "sixth element of the list should be intvec" ); break; case semicListNNegative: WerrorS( "first element of the list should be positive" ); break; case semicListWrongNumberOfNumerators: WerrorS( "wrong number of numerators" ); break; case semicListWrongNumberOfDenominators: WerrorS( "wrong number of denominators" ); break; case semicListWrongNumberOfMultiplicities: WerrorS( "wrong number of multiplicities" ); break; case semicListMuNegative: WerrorS( "the Milnor number should be positive" ); break; case semicListPgNegative: WerrorS( "the geometrical genus should be nonnegative" ); break; case semicListNumNegative: WerrorS( "all numerators should be positive" ); break; case semicListDenNegative: WerrorS( "all denominators should be positive" ); break; case semicListMulNegative: WerrorS( "all multiplicities should be positive" ); break; case semicListNotSymmetric: WerrorS( "it is not symmetric" ); break; case semicListNotMonotonous: WerrorS( "it is not monotonous" ); break; case semicListMilnorWrong: WerrorS( "the Milnor number is wrong" ); break; case semicListPGWrong: WerrorS( "the geometrical genus is wrong" ); break; default: WerrorS( "unspecific error" ); break; } } // ---------------------------------------------------------------------------- // this is the main spectrum computation function // ---------------------------------------------------------------------------- enum spectrumState { spectrumOK, spectrumZero, spectrumBadPoly, spectrumNoSingularity, spectrumNotIsolated, spectrumDegenerate, spectrumWrongRing, spectrumNoHC, spectrumUnspecErr }; // from splist.cc // ---------------------------------------------------------------------------- // Compute the spectrum of a spectrumPolyList // ---------------------------------------------------------------------------- /* former spectrumPolyList::spectrum ( lists*, int) */ spectrumState spectrumStateFromList( spectrumPolyList& speclist, lists *L,int fast ) { spectrumPolyNode **node = &speclist.root; spectrumPolyNode *search; poly f,tmp; int found,cmp; Rational smax( ( fast==0 ? 0 : rVar(currRing) ), ( fast==2 ? 2 : 1 ) ); Rational weight_prev( 0,1 ); int mu = 0; // the milnor number int pg = 0; // the geometrical genus int n = 0; // number of different spectral numbers int z = 0; // number of spectral number equal to smax while( (*node)!=(spectrumPolyNode*)NULL && ( fast==0 || (*node)->weight<=smax ) ) { // --------------------------------------- // determine the first normal form which // contains the monomial node->mon // --------------------------------------- found = FALSE; search = *node; while( search!=(spectrumPolyNode*)NULL && found==FALSE ) { if( search->nf!=(poly)NULL ) { f = search->nf; do { // -------------------------------- // look for (*node)->mon in f // -------------------------------- cmp = pCmp( (*node)->mon,f ); if( cmp<0 ) { f = pNext( f ); } else if( cmp==0 ) { // ----------------------------- // we have found a normal form // ----------------------------- found = TRUE; // normalize coefficient number inv = nInvers( pGetCoeff( f ) ); pMult_nn( search->nf,inv ); nDelete( &inv ); // exchange normal forms tmp = (*node)->nf; (*node)->nf = search->nf; search->nf = tmp; } } while( cmp<0 && f!=(poly)NULL ); } search = search->next; } if( found==FALSE ) { // ------------------------------------------------ // the weight of node->mon is a spectrum number // ------------------------------------------------ mu++; if( (*node)->weight<=(Rational)1 ) pg++; if( (*node)->weight==smax ) z++; if( (*node)->weight>weight_prev ) n++; weight_prev = (*node)->weight; node = &((*node)->next); } else { // ----------------------------------------------- // determine all other normal form which contain // the monomial node->mon // replace for node->mon its normal form // ----------------------------------------------- while( search!=(spectrumPolyNode*)NULL ) { if( search->nf!=(poly)NULL ) { f = search->nf; do { // -------------------------------- // look for (*node)->mon in f // -------------------------------- cmp = pCmp( (*node)->mon,f ); if( cmp<0 ) { f = pNext( f ); } else if( cmp==0 ) { search->nf = pSub( search->nf, ppMult_nn( (*node)->nf,pGetCoeff( f ) ) ); pNorm( search->nf ); } } while( cmp<0 && f!=(poly)NULL ); } search = search->next; } speclist.delete_node( node ); } } // -------------------------------------------------------- // fast computation exploits the symmetry of the spectrum // -------------------------------------------------------- if( fast==2 ) { mu = 2*mu - z; n = ( z > 0 ? 2*n - 1 : 2*n ); } // -------------------------------------------------------- // compute the spectrum numbers with their multiplicities // -------------------------------------------------------- intvec *nom = new intvec( n ); intvec *den = new intvec( n ); intvec *mult = new intvec( n ); int count = 0; int multiplicity = 1; for( search=speclist.root; search!=(spectrumPolyNode*)NULL && ( fast==0 || search->weight<=smax ); search=search->next ) { if( search->next==(spectrumPolyNode*)NULL || search->weightnext->weight ) { (*nom) [count] = search->weight.get_num_si( ); (*den) [count] = search->weight.get_den_si( ); (*mult)[count] = multiplicity; multiplicity=1; count++; } else { multiplicity++; } } // -------------------------------------------------------- // fast computation exploits the symmetry of the spectrum // -------------------------------------------------------- if( fast==2 ) { int n1,n2; for( n1=0, n2=n-1; n1 degenerate // principal part // --------------------------------------------- *L = (lists)omAllocBin( slists_bin); (*L)->Init( 1 ); (*L)->m[0].rtyp = INT_CMD; // milnor number (*L)->m[0].data = (void*)(long)mu; return spectrumDegenerate; } } *L = (lists)omAllocBin( slists_bin); (*L)->Init( 6 ); (*L)->m[0].rtyp = INT_CMD; // milnor number (*L)->m[1].rtyp = INT_CMD; // geometrical genus (*L)->m[2].rtyp = INT_CMD; // number of spectrum values (*L)->m[3].rtyp = INTVEC_CMD; // nominators (*L)->m[4].rtyp = INTVEC_CMD; // denomiantors (*L)->m[5].rtyp = INTVEC_CMD; // multiplicities (*L)->m[0].data = (void*)(long)mu; (*L)->m[1].data = (void*)(long)pg; (*L)->m[2].data = (void*)(long)n; (*L)->m[3].data = (void*)nom; (*L)->m[4].data = (void*)den; (*L)->m[5].data = (void*)mult; return spectrumOK; } spectrumState spectrumCompute( poly h,lists *L,int fast ) { int i; #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << "spectrumCompute\n"; if( fast==0 ) cout << " no optimization" << endl; if( fast==1 ) cout << " weight optimization" << endl; if( fast==2 ) cout << " symmetry optimization" << endl; #else fprintf( stdout,"spectrumCompute\n" ); if( fast==0 ) fprintf( stdout," no optimization\n" ); if( fast==1 ) fprintf( stdout," weight optimization\n" ); if( fast==2 ) fprintf( stdout," symmetry optimization\n" ); #endif #endif #endif // ---------------------- // check if h is zero // ---------------------- if( h==(poly)NULL ) { return spectrumZero; } // ---------------------------------- // check if h has a constant term // ---------------------------------- if( hasConstTerm( h, currRing ) ) { return spectrumBadPoly; } // -------------------------------- // check if h has a linear term // -------------------------------- if( hasLinearTerm( h, currRing ) ) { *L = (lists)omAllocBin( slists_bin); (*L)->Init( 1 ); (*L)->m[0].rtyp = INT_CMD; // milnor number /* (*L)->m[0].data = (void*)0;a -- done by Init */ return spectrumNoSingularity; } // ---------------------------------- // compute the jacobi ideal of (h) // ---------------------------------- ideal J = NULL; J = idInit( rVar(currRing),1 ); #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << "\n computing the Jacobi ideal...\n"; #else fprintf( stdout,"\n computing the Jacobi ideal...\n" ); #endif #endif #endif for( i=0; im[i] = pDiff( h,i+1); //j ); #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << " "; #else fprintf( stdout," " ); #endif pWrite( J->m[i] ); #endif #endif } // -------------------------------------------- // compute a standard basis stdJ of jac(h) // -------------------------------------------- #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << endl; cout << " computing a standard basis..." << endl; #else fprintf( stdout,"\n" ); fprintf( stdout," computing a standard basis...\n" ); #endif #endif #endif ideal stdJ = kStd(J,currRing->qideal,isNotHomog,NULL); idSkipZeroes( stdJ ); #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT for( i=0; im[i] ); } #endif #endif idDelete( &J ); // ------------------------------------------ // check if the h has a singularity // ------------------------------------------ if( hasOne( stdJ, currRing ) ) { // ------------------------------- // h is smooth in the origin // return only the Milnor number // ------------------------------- *L = (lists)omAllocBin( slists_bin); (*L)->Init( 1 ); (*L)->m[0].rtyp = INT_CMD; // milnor number /* (*L)->m[0].data = (void*)0;a -- done by Init */ return spectrumNoSingularity; } // ------------------------------------------ // check if the singularity h is isolated // ------------------------------------------ for( i=rVar(currRing); i>0; i-- ) { if( hasAxis( stdJ,i, currRing )==FALSE ) { return spectrumNotIsolated; } } // ------------------------------------------ // compute the highest corner hc of stdJ // ------------------------------------------ #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << "\n computing the highest corner...\n"; #else fprintf( stdout,"\n computing the highest corner...\n" ); #endif #endif #endif poly hc = (poly)NULL; scComputeHC( stdJ,currRing->qideal, 0,hc ); if( hc!=(poly)NULL ) { pGetCoeff(hc) = nInit(1); for( i=rVar(currRing); i>0; i-- ) { if( pGetExp( hc,i )>0 ) pDecrExp( hc,i ); } pSetm( hc ); } else { return spectrumNoHC; } #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << " "; #else fprintf( stdout," " ); #endif pWrite( hc ); #endif #endif // ---------------------------------------- // compute the Newton polygon nph of h // ---------------------------------------- #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << "\n computing the newton polygon...\n"; #else fprintf( stdout,"\n computing the newton polygon...\n" ); #endif #endif #endif newtonPolygon nph( h, currRing ); #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT cout << nph; #endif #endif // ----------------------------------------------- // compute the weight corner wc of (stdj,nph) // ----------------------------------------------- #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << "\n computing the weight corner...\n"; #else fprintf( stdout,"\n computing the weight corner...\n" ); #endif #endif #endif poly wc = ( fast==0 ? pCopy( hc ) : ( fast==1 ? computeWC( nph,(Rational)rVar(currRing), currRing ) : /* fast==2 */computeWC( nph, ((Rational)rVar(currRing))/(Rational)2, currRing ) ) ); #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << " "; #else fprintf( stdout," " ); #endif pWrite( wc ); #endif #endif // ------------- // compute NF // ------------- #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT #ifdef SPECTRUM_IOSTREAM cout << "\n computing NF...\n" << endl; #else fprintf( stdout,"\n computing NF...\n" ); #endif #endif #endif spectrumPolyList NF( &nph ); computeNF( stdJ,hc,wc,&NF, currRing ); #ifdef SPECTRUM_DEBUG #ifdef SPECTRUM_PRINT cout << NF; #ifdef SPECTRUM_IOSTREAM cout << endl; #else fprintf( stdout,"\n" ); #endif #endif #endif // ---------------------------- // compute the spectrum of h // ---------------------------- // spectrumState spectrumStateFromList( spectrumPolyList& speclist, lists *L, int fast ); return spectrumStateFromList(NF, L, fast ); } // ---------------------------------------------------------------------------- // this procedure is called from the interpreter // ---------------------------------------------------------------------------- // first = polynomial // result = list of spectrum numbers // ---------------------------------------------------------------------------- void spectrumPrintError(spectrumState state) { switch( state ) { case spectrumZero: WerrorS( "polynomial is zero" ); break; case spectrumBadPoly: WerrorS( "polynomial has constant term" ); break; case spectrumNoSingularity: WerrorS( "not a singularity" ); break; case spectrumNotIsolated: WerrorS( "the singularity is not isolated" ); break; case spectrumNoHC: WerrorS( "highest corner cannot be computed" ); break; case spectrumDegenerate: WerrorS( "principal part is degenerate" ); break; case spectrumOK: break; default: WerrorS( "unknown error occurred" ); break; } } BOOLEAN spectrumProc( leftv result,leftv first ) { spectrumState state = spectrumOK; // ------------------- // check consistency // ------------------- // check for a local ring if( !ringIsLocal(currRing ) ) { WerrorS( "only works for local orderings" ); state = spectrumWrongRing; } // no quotient rings are allowed else if( currRing->qideal != NULL ) { WerrorS( "does not work in quotient rings" ); state = spectrumWrongRing; } else { lists L = (lists)NULL; int flag = 1; // weight corner optimization is safe state = spectrumCompute( (poly)first->Data( ),&L,flag ); if( state==spectrumOK ) { result->rtyp = LIST_CMD; result->data = (char*)L; } else { spectrumPrintError(state); } } return (state!=spectrumOK); } // ---------------------------------------------------------------------------- // this procedure is called from the interpreter // ---------------------------------------------------------------------------- // first = polynomial // result = list of spectrum numbers // ---------------------------------------------------------------------------- BOOLEAN spectrumfProc( leftv result,leftv first ) { spectrumState state = spectrumOK; // ------------------- // check consistency // ------------------- // check for a local polynomial ring if( currRing->OrdSgn != -1 ) // ?? HS: the test above is also true for k[x][[y]], k[[x]][y] // or should we use: //if( !ringIsLocal( ) ) { WerrorS( "only works for local orderings" ); state = spectrumWrongRing; } else if( currRing->qideal != NULL ) { WerrorS( "does not work in quotient rings" ); state = spectrumWrongRing; } else { lists L = (lists)NULL; int flag = 2; // symmetric optimization state = spectrumCompute( (poly)first->Data( ),&L,flag ); if( state==spectrumOK ) { result->rtyp = LIST_CMD; result->data = (char*)L; } else { spectrumPrintError(state); } } return (state!=spectrumOK); } // ---------------------------------------------------------------------------- // check if a list is a spectrum // check for: // list has 6 elements // 1st element is int (mu=Milnor number) // 2nd element is int (pg=geometrical genus) // 3rd element is int (n =number of different spectrum numbers) // 4th element is intvec (num=numerators) // 5th element is intvec (den=denomiantors) // 6th element is intvec (mul=multiplicities) // exactly n numerators // exactly n denominators // exactly n multiplicities // mu>0 // pg>=0 // n>0 // num>0 // den>0 // mul>0 // symmetriy with respect to numberofvariables/2 // monotony // mu = sum of all multiplicities // pg = sum of all multiplicities where num/den<=1 // ---------------------------------------------------------------------------- semicState list_is_spectrum( lists l ) { // ------------------- // check list length // ------------------- if( l->nr < 5 ) { return semicListTooShort; } else if( l->nr > 5 ) { return semicListTooLong; } // ------------- // check types // ------------- if( l->m[0].rtyp != INT_CMD ) { return semicListFirstElementWrongType; } else if( l->m[1].rtyp != INT_CMD ) { return semicListSecondElementWrongType; } else if( l->m[2].rtyp != INT_CMD ) { return semicListThirdElementWrongType; } else if( l->m[3].rtyp != INTVEC_CMD ) { return semicListFourthElementWrongType; } else if( l->m[4].rtyp != INTVEC_CMD ) { return semicListFifthElementWrongType; } else if( l->m[5].rtyp != INTVEC_CMD ) { return semicListSixthElementWrongType; } // ------------------------- // check number of entries // ------------------------- int mu = (int)(long)(l->m[0].Data( )); int pg = (int)(long)(l->m[1].Data( )); int n = (int)(long)(l->m[2].Data( )); if( n <= 0 ) { return semicListNNegative; } intvec *num = (intvec*)l->m[3].Data( ); intvec *den = (intvec*)l->m[4].Data( ); intvec *mul = (intvec*)l->m[5].Data( ); if( n != num->length( ) ) { return semicListWrongNumberOfNumerators; } else if( n != den->length( ) ) { return semicListWrongNumberOfDenominators; } else if( n != mul->length( ) ) { return semicListWrongNumberOfMultiplicities; } // -------- // values // -------- if( mu <= 0 ) { return semicListMuNegative; } if( pg < 0 ) { return semicListPgNegative; } int i; for( i=0; i= (*num)[j]*(*den)[i] ) { return semicListNotMonotonous; } } // --------------------- // check Milnor number // --------------------- for( mu=0, i=0; im[0].Data( )) ) { return semicListMilnorWrong; } // ------------------------- // check geometrical genus // ------------------------- for( pg=0, i=0; im[1].Data( )) ) { return semicListPGWrong; } return semicOK; } // ---------------------------------------------------------------------------- // this procedure is called from the interpreter // ---------------------------------------------------------------------------- // first = list of spectrum numbers // second = list of spectrum numbers // result = sum of the two lists // ---------------------------------------------------------------------------- BOOLEAN spaddProc( leftv result,leftv first,leftv second ) { semicState state; // ----------------- // check arguments // ----------------- lists l1 = (lists)first->Data( ); lists l2 = (lists)second->Data( ); if( (state=list_is_spectrum( l1 )) != semicOK ) { WerrorS( "first argument is not a spectrum:" ); list_error( state ); } else if( (state=list_is_spectrum( l2 )) != semicOK ) { WerrorS( "second argument is not a spectrum:" ); list_error( state ); } else { spectrum s1= spectrumFromList ( l1 ); spectrum s2= spectrumFromList ( l2 ); spectrum sum( s1+s2 ); result->rtyp = LIST_CMD; result->data = (char*)(getList(sum)); } return (state!=semicOK); } // ---------------------------------------------------------------------------- // this procedure is called from the interpreter // ---------------------------------------------------------------------------- // first = list of spectrum numbers // second = integer // result = the multiple of the first list by the second factor // ---------------------------------------------------------------------------- BOOLEAN spmulProc( leftv result,leftv first,leftv second ) { semicState state; // ----------------- // check arguments // ----------------- lists l = (lists)first->Data( ); int k = (int)(long)second->Data( ); if( (state=list_is_spectrum( l ))!=semicOK ) { WerrorS( "first argument is not a spectrum" ); list_error( state ); } else if( k < 0 ) { WerrorS( "second argument should be positive" ); state = semicMulNegative; } else { spectrum s= spectrumFromList( l ); spectrum product( k*s ); result->rtyp = LIST_CMD; result->data = (char*)getList(product); } return (state!=semicOK); } // ---------------------------------------------------------------------------- // this procedure is called from the interpreter // ---------------------------------------------------------------------------- // first = list of spectrum numbers // second = list of spectrum numbers // result = semicontinuity index // ---------------------------------------------------------------------------- BOOLEAN semicProc3 ( leftv res,leftv u,leftv v,leftv w ) { semicState state; BOOLEAN qh=(((int)(long)w->Data())==1); // ----------------- // check arguments // ----------------- lists l1 = (lists)u->Data( ); lists l2 = (lists)v->Data( ); if( (state=list_is_spectrum( l1 ))!=semicOK ) { WerrorS( "first argument is not a spectrum" ); list_error( state ); } else if( (state=list_is_spectrum( l2 ))!=semicOK ) { WerrorS( "second argument is not a spectrum" ); list_error( state ); } else { spectrum s1= spectrumFromList( l1 ); spectrum s2= spectrumFromList( l2 ); res->rtyp = INT_CMD; if (qh) res->data = (void*)(long)(s1.mult_spectrumh( s2 )); else res->data = (void*)(long)(s1.mult_spectrum( s2 )); } // ----------------- // check status // ----------------- return (state!=semicOK); } BOOLEAN semicProc ( leftv res,leftv u,leftv v ) { sleftv tmp; memset(&tmp,0,sizeof(tmp)); tmp.rtyp=INT_CMD; /* tmp.data = (void *)0; -- done by memset */ return semicProc3(res,u,v,&tmp); } #endif BOOLEAN loNewtonP( leftv res, leftv arg1 ) { res->data= (void*)loNewtonPolytope( (ideal)arg1->Data() ); return FALSE; } BOOLEAN loSimplex( leftv res, leftv args ) { if ( !(rField_is_long_R(currRing)) ) { WerrorS("Ground field not implemented!"); return TRUE; } simplex * LP; matrix m; leftv v= args; if ( v->Typ() != MATRIX_CMD ) // 1: matrix return TRUE; else m= (matrix)(v->CopyD()); LP = new simplex(MATROWS(m),MATCOLS(m)); LP->mapFromMatrix(m); v= v->next; if ( v->Typ() != INT_CMD ) // 2: m = number of constraints return TRUE; else LP->m= (int)(long)(v->Data()); v= v->next; if ( v->Typ() != INT_CMD ) // 3: n = number of variables return TRUE; else LP->n= (int)(long)(v->Data()); v= v->next; if ( v->Typ() != INT_CMD ) // 4: m1 = number of <= constraints return TRUE; else LP->m1= (int)(long)(v->Data()); v= v->next; if ( v->Typ() != INT_CMD ) // 5: m2 = number of >= constraints return TRUE; else LP->m2= (int)(long)(v->Data()); v= v->next; if ( v->Typ() != INT_CMD ) // 6: m3 = number of == constraints return TRUE; else LP->m3= (int)(long)(v->Data()); #ifdef mprDEBUG_PROT Print("m (constraints) %d\n",LP->m); Print("n (columns) %d\n",LP->n); Print("m1 (<=) %d\n",LP->m1); Print("m2 (>=) %d\n",LP->m2); Print("m3 (==) %d\n",LP->m3); #endif LP->compute(); lists lres= (lists)omAlloc( sizeof(slists) ); lres->Init( 6 ); lres->m[0].rtyp= MATRIX_CMD; // output matrix lres->m[0].data=(void*)LP->mapToMatrix(m); lres->m[1].rtyp= INT_CMD; // found a solution? lres->m[1].data=(void*)(long)LP->icase; lres->m[2].rtyp= INTVEC_CMD; lres->m[2].data=(void*)LP->posvToIV(); lres->m[3].rtyp= INTVEC_CMD; lres->m[3].data=(void*)LP->zrovToIV(); lres->m[4].rtyp= INT_CMD; lres->m[4].data=(void*)(long)LP->m; lres->m[5].rtyp= INT_CMD; lres->m[5].data=(void*)(long)LP->n; res->data= (void*)lres; return FALSE; } BOOLEAN nuMPResMat( leftv res, leftv arg1, leftv arg2 ) { ideal gls = (ideal)(arg1->Data()); int imtype= (int)(long)arg2->Data(); uResultant::resMatType mtype= determineMType( imtype ); // check input ideal ( = polynomial system ) if ( mprIdealCheck( gls, arg1->Name(), mtype, true ) != mprOk ) { return TRUE; } uResultant *resMat= new uResultant( gls, mtype, false ); if (resMat!=NULL) { res->rtyp = MODUL_CMD; res->data= (void*)resMat->accessResMat()->getMatrix(); if (!errorreported) delete resMat; } return errorreported; } BOOLEAN nuLagSolve( leftv res, leftv arg1, leftv arg2, leftv arg3 ) { poly gls; gls= (poly)(arg1->Data()); int howclean= (int)(long)arg3->Data(); if ( !(rField_is_R(currRing) || rField_is_Q(currRing) || rField_is_long_R(currRing) || rField_is_long_C(currRing)) ) { WerrorS("Ground field not implemented!"); return TRUE; } if ( !(rField_is_R(currRing) || rField_is_long_R(currRing) || \ rField_is_long_C(currRing)) ) { unsigned long int ii = (unsigned long int)arg2->Data(); setGMPFloatDigits( ii, ii ); } if ( gls == NULL || pIsConstant( gls ) ) { WerrorS("Input polynomial is constant!"); return TRUE; } int ldummy; int deg= currRing->pLDeg( gls, &ldummy, currRing ); // int deg= pDeg( gls ); // int len= pLength( gls ); int i,vpos=0; poly piter; lists elist; lists rlist; elist= (lists)omAlloc( sizeof(slists) ); elist->Init( 0 ); if ( rVar(currRing) > 1 ) { piter= gls; for ( i= 1; i <= rVar(currRing); i++ ) if ( pGetExp( piter, i ) ) { vpos= i; break; } while ( piter ) { for ( i= 1; i <= rVar(currRing); i++ ) if ( (vpos != i) && (pGetExp( piter, i ) != 0) ) { WerrorS("The input polynomial must be univariate!"); return TRUE; } pIter( piter ); } } rootContainer * roots= new rootContainer(); number * pcoeffs= (number *)omAlloc( (deg+1) * sizeof( number ) ); piter= gls; for ( i= deg; i >= 0; i-- ) { //if ( piter ) Print("deg %d, pDeg(piter) %d\n",i,pTotaldegree(piter)); if ( piter && pTotaldegree(piter) == i ) { pcoeffs[i]= nCopy( pGetCoeff( piter ) ); //nPrint( pcoeffs[i] );PrintS(" "); pIter( piter ); } else { pcoeffs[i]= nInit(0); } } #ifdef mprDEBUG_PROT for (i=deg; i >= 0; i--) { nPrint( pcoeffs[i] );PrintS(" "); } PrintLn(); #endif roots->fillContainer( pcoeffs, NULL, 1, deg, rootContainer::onepoly, 1 ); roots->solver( howclean ); int elem= roots->getAnzRoots(); char *dummy; int j; rlist= (lists)omAlloc( sizeof(slists) ); rlist->Init( elem ); if (rField_is_long_C(currRing)) { for ( j= 0; j < elem; j++ ) { rlist->m[j].rtyp=NUMBER_CMD; rlist->m[j].data=(void *)nCopy((number)(roots->getRoot(j))); //rlist->m[j].data=(void *)(number)(roots->getRoot(j)); } } else { for ( j= 0; j < elem; j++ ) { dummy = complexToStr( (*roots)[j], gmp_output_digits, currRing->cf ); rlist->m[j].rtyp=STRING_CMD; rlist->m[j].data=(void *)dummy; } } elist->Clean(); //omFreeSize( (ADDRESS) elist, sizeof(slists) ); // this is (via fillContainer) the same data as in root //for ( i= deg; i >= 0; i-- ) nDelete( &pcoeffs[i] ); //omFreeSize( (ADDRESS) pcoeffs, (deg+1) * sizeof( number ) ); delete roots; res->rtyp= LIST_CMD; res->data= (void*)rlist; return FALSE; } BOOLEAN nuVanderSys( leftv res, leftv arg1, leftv arg2, leftv arg3) { int i; ideal p,w; p= (ideal)arg1->Data(); w= (ideal)arg2->Data(); // w[0] = f(p^0) // w[1] = f(p^1) // ... // p can be a vector of numbers (multivariate polynom) // or one number (univariate polynom) // tdg = deg(f) int n= IDELEMS( p ); int m= IDELEMS( w ); int tdg= (int)(long)arg3->Data(); res->data= (void*)NULL; // check the input if ( tdg < 1 ) { WerrorS("Last input parameter must be > 0!"); return TRUE; } if ( n != rVar(currRing) ) { Werror("Size of first input ideal must be equal to %d!",rVar(currRing)); return TRUE; } if ( m != (int)pow((double)tdg+1,(double)n) ) { Werror("Size of second input ideal must be equal to %d!", (int)pow((double)tdg+1,(double)n)); return TRUE; } if ( !(rField_is_Q(currRing) /* || rField_is_R() || rField_is_long_R() || rField_is_long_C()*/ ) ) { WerrorS("Ground field not implemented!"); return TRUE; } number tmp; number *pevpoint= (number *)omAlloc( n * sizeof( number ) ); for ( i= 0; i < n; i++ ) { pevpoint[i]=nInit(0); if ( (p->m)[i] ) { tmp = pGetCoeff( (p->m)[i] ); if ( nIsZero(tmp) || nIsOne(tmp) || nIsMOne(tmp) ) { omFreeSize( (ADDRESS)pevpoint, n * sizeof( number ) ); WerrorS("Elements of first input ideal must not be equal to -1, 0, 1!"); return TRUE; } } else tmp= NULL; if ( !nIsZero(tmp) ) { if ( !pIsConstant((p->m)[i])) { omFreeSize( (ADDRESS)pevpoint, n * sizeof( number ) ); WerrorS("Elements of first input ideal must be numbers!"); return TRUE; } pevpoint[i]= nCopy( tmp ); } } number *wresults= (number *)omAlloc( m * sizeof( number ) ); for ( i= 0; i < m; i++ ) { wresults[i]= nInit(0); if ( (w->m)[i] && !nIsZero(pGetCoeff((w->m)[i])) ) { if ( !pIsConstant((w->m)[i])) { omFreeSize( (ADDRESS)pevpoint, n * sizeof( number ) ); omFreeSize( (ADDRESS)wresults, m * sizeof( number ) ); WerrorS("Elements of second input ideal must be numbers!"); return TRUE; } wresults[i]= nCopy(pGetCoeff((w->m)[i])); } } vandermonde vm( m, n, tdg, pevpoint, FALSE ); number *ncpoly= vm.interpolateDense( wresults ); // do not free ncpoly[]!! poly rpoly= vm.numvec2poly( ncpoly ); omFreeSize( (ADDRESS)pevpoint, n * sizeof( number ) ); omFreeSize( (ADDRESS)wresults, m * sizeof( number ) ); res->data= (void*)rpoly; return FALSE; } BOOLEAN nuUResSolve( leftv res, leftv args ) { leftv v= args; ideal gls; int imtype; int howclean; // get ideal if ( v->Typ() != IDEAL_CMD ) return TRUE; else gls= (ideal)(v->Data()); v= v->next; // get resultant matrix type to use (0,1) if ( v->Typ() != INT_CMD ) return TRUE; else imtype= (int)(long)v->Data(); v= v->next; if (imtype==0) { ideal test_id=idInit(1,1); int j; for(j=IDELEMS(gls)-1;j>=0;j--) { if (gls->m[j]!=NULL) { test_id->m[0]=gls->m[j]; intvec *dummy_w=id_QHomWeight(test_id, currRing); if (dummy_w!=NULL) { WerrorS("Newton polytope not of expected dimension"); delete dummy_w; return TRUE; } } } } // get and set precision in digits ( > 0 ) if ( v->Typ() != INT_CMD ) return TRUE; else if ( !(rField_is_R(currRing) || rField_is_long_R(currRing) || \ rField_is_long_C(currRing)) ) { unsigned long int ii=(unsigned long int)v->Data(); setGMPFloatDigits( ii, ii ); } v= v->next; // get interpolation steps (0,1,2) if ( v->Typ() != INT_CMD ) return TRUE; else howclean= (int)(long)v->Data(); uResultant::resMatType mtype= determineMType( imtype ); int i,count; lists listofroots= NULL; number smv= NULL; BOOLEAN interpolate_det= (mtype==uResultant::denseResMat)?TRUE:FALSE; //emptylist= (lists)omAlloc( sizeof(slists) ); //emptylist->Init( 0 ); //res->rtyp = LIST_CMD; //res->data= (void *)emptylist; // check input ideal ( = polynomial system ) if ( mprIdealCheck( gls, args->Name(), mtype ) != mprOk ) { return TRUE; } uResultant * ures; rootContainer ** iproots; rootContainer ** muiproots; rootArranger * arranger; // main task 1: setup of resultant matrix ures= new uResultant( gls, mtype ); if ( ures->accessResMat()->initState() != resMatrixBase::ready ) { WerrorS("Error occurred during matrix setup!"); return TRUE; } // if dense resultant, check if minor nonsingular if ( mtype == uResultant::denseResMat ) { smv= ures->accessResMat()->getSubDet(); #ifdef mprDEBUG_PROT PrintS("// Determinant of submatrix: ");nPrint(smv);PrintLn(); #endif if ( nIsZero(smv) ) { WerrorS("Unsuitable input ideal: Minor of resultant matrix is singular!"); return TRUE; } } // main task 2: Interpolate specialized resultant polynomials if ( interpolate_det ) iproots= ures->interpolateDenseSP( false, smv ); else iproots= ures->specializeInU( false, smv ); // main task 3: Interpolate specialized resultant polynomials if ( interpolate_det ) muiproots= ures->interpolateDenseSP( true, smv ); else muiproots= ures->specializeInU( true, smv ); #ifdef mprDEBUG_PROT int c= iproots[0]->getAnzElems(); for (i=0; i < c; i++) pWrite(iproots[i]->getPoly()); c= muiproots[0]->getAnzElems(); for (i=0; i < c; i++) pWrite(muiproots[i]->getPoly()); #endif // main task 4: Compute roots of specialized polys and match them up arranger= new rootArranger( iproots, muiproots, howclean ); arranger->solve_all(); // get list of roots if ( arranger->success() ) { arranger->arrange(); listofroots= listOfRoots(arranger, gmp_output_digits ); } else { WerrorS("Solver was unable to find any roots!"); return TRUE; } // free everything count= iproots[0]->getAnzElems(); for (i=0; i < count; i++) delete iproots[i]; omFreeSize( (ADDRESS) iproots, count * sizeof(rootContainer*) ); count= muiproots[0]->getAnzElems(); for (i=0; i < count; i++) delete muiproots[i]; omFreeSize( (ADDRESS) muiproots, count * sizeof(rootContainer*) ); delete ures; delete arranger; nDelete( &smv ); res->data= (void *)listofroots; //emptylist->Clean(); // omFreeSize( (ADDRESS) emptylist, sizeof(slists) ); return FALSE; } // from mpr_numeric.cc lists listOfRoots( rootArranger* self, const unsigned int oprec ) { int i,j; int count= self->roots[0]->getAnzRoots(); // number of roots int elem= self->roots[0]->getAnzElems(); // number of koordinates per root lists listofroots= (lists)omAlloc( sizeof(slists) ); // must be done this way! if ( self->found_roots ) { listofroots->Init( count ); for (i=0; i < count; i++) { lists onepoint= (lists)omAlloc(sizeof(slists)); // must be done this way! onepoint->Init(elem); for ( j= 0; j < elem; j++ ) { if ( !rField_is_long_C(currRing) ) { onepoint->m[j].rtyp=STRING_CMD; onepoint->m[j].data=(void *)complexToStr((*self->roots[j])[i],oprec, currRing->cf); } else { onepoint->m[j].rtyp=NUMBER_CMD; onepoint->m[j].data=(void *)n_Copy((number)(self->roots[j]->getRoot(i)), currRing->cf); } onepoint->m[j].next= NULL; onepoint->m[j].name= NULL; } listofroots->m[i].rtyp=LIST_CMD; listofroots->m[i].data=(void *)onepoint; listofroots->m[j].next= NULL; listofroots->m[j].name= NULL; } } else { listofroots->Init( 0 ); } return listofroots; } // from ring.cc void rSetHdl(idhdl h) { ring rg = NULL; if (h!=NULL) { // Print(" new ring:%s (l:%d)\n",IDID(h),IDLEV(h)); rg = IDRING(h); if (rg==NULL) return; //id <>NULL, ring==NULL omCheckAddrSize((ADDRESS)h,sizeof(idrec)); if (IDID(h)) // OB: ???? omCheckAddr((ADDRESS)IDID(h)); rTest(rg); } // clean up history if (sLastPrinted.RingDependend()) { sLastPrinted.CleanUp(); memset(&sLastPrinted,0,sizeof(sleftv)); } if ((rg!=currRing)&&(currRing!=NULL)) { denominator_list dd=DENOMINATOR_LIST; if (DENOMINATOR_LIST!=NULL) { if (TEST_V_ALLWARN) Warn("deleting denom_list for ring change to %s",IDID(h)); do { n_Delete(&(dd->n),currRing->cf); dd=dd->next; omFree(DENOMINATOR_LIST); DENOMINATOR_LIST=dd; } while(DENOMINATOR_LIST!=NULL); } } // test for valid "currRing": if ((rg!=NULL) && (rg->idroot==NULL)) { ring old=rg; rg=rAssure_HasComp(rg); if (old!=rg) { rKill(old); IDRING(h)=rg; } } /*------------ change the global ring -----------------------*/ rChangeCurrRing(rg); currRingHdl = h; } static leftv rOptimizeOrdAsSleftv(leftv ord) { // change some bad orderings/combination into better ones leftv h=ord; while(h!=NULL) { BOOLEAN change=FALSE; intvec *iv = (intvec *)(h->data); // ws(-i) -> wp(i) if ((*iv)[1]==ringorder_ws) { BOOLEAN neg=TRUE; for(int i=2;ilength();i++) if((*iv)[i]>=0) { neg=FALSE; break; } if (neg) { (*iv)[1]=ringorder_wp; for(int i=2;ilength();i++) (*iv)[i]= - (*iv)[i]; change=TRUE; } } // Ws(-i) -> Wp(i) if ((*iv)[1]==ringorder_Ws) { BOOLEAN neg=TRUE; for(int i=2;ilength();i++) if((*iv)[i]>=0) { neg=FALSE; break; } if (neg) { (*iv)[1]=ringorder_Wp; for(int i=2;ilength();i++) (*iv)[i]= -(*iv)[i]; change=TRUE; } } // wp(1) -> dp if ((*iv)[1]==ringorder_wp) { BOOLEAN all_one=TRUE; for(int i=2;ilength();i++) if((*iv)[i]!=1) { all_one=FALSE; break; } if (all_one) { intvec *iv2=new intvec(3); (*iv2)[0]=1; (*iv2)[1]=ringorder_dp; (*iv2)[2]=iv->length()-2; delete iv; iv=iv2; h->data=iv2; change=TRUE; } } // Wp(1) -> Dp if ((*iv)[1]==ringorder_Wp) { BOOLEAN all_one=TRUE; for(int i=2;ilength();i++) if((*iv)[i]!=1) { all_one=FALSE; break; } if (all_one) { intvec *iv2=new intvec(3); (*iv2)[0]=1; (*iv2)[1]=ringorder_Dp; (*iv2)[2]=iv->length()-2; delete iv; iv=iv2; h->data=iv2; change=TRUE; } } // dp(1)/Dp(1)/rp(1) -> lp(1) if (((*iv)[1]==ringorder_dp) || ((*iv)[1]==ringorder_Dp) || ((*iv)[1]==ringorder_rp)) { if (iv->length()==3) { if ((*iv)[2]==1) { (*iv)[1]=ringorder_lp; change=TRUE; } } } // lp(i),lp(j) -> lp(i+j) if(((*iv)[1]==ringorder_lp) && (h->next!=NULL)) { intvec *iv2 = (intvec *)(h->next->data); if ((*iv2)[1]==ringorder_lp) { leftv hh=h->next; h->next=hh->next; hh->next=NULL; if ((*iv2)[0]==1) (*iv)[2] += 1; // last block unspecified, at least 1 else (*iv)[2] += (*iv2)[2]; hh->CleanUp(); omFree(hh); change=TRUE; } } // ------------------- if (!change) h=h->next; } return ord; } BOOLEAN rSleftvOrdering2Ordering(sleftv *ord, ring R) { int last = 0, o=0, n = 1, i=0, typ = 1, j; ord=rOptimizeOrdAsSleftv(ord); sleftv *sl = ord; // determine nBlocks while (sl!=NULL) { intvec *iv = (intvec *)(sl->data); if (((*iv)[1]==ringorder_c)||((*iv)[1]==ringorder_C)) i++; else if ((*iv)[1]==ringorder_L) { R->bitmask=(*iv)[2]; n--; } else if (((*iv)[1]!=ringorder_a) && ((*iv)[1]!=ringorder_a64) && ((*iv)[1]!=ringorder_am)) o++; n++; sl=sl->next; } // check whether at least one real ordering if (o==0) { WerrorS("invalid combination of orderings"); return TRUE; } // if no c/C ordering is given, increment n if (i==0) n++; else if (i != 1) { // throw error if more than one is given WerrorS("more than one ordering c/C specified"); return TRUE; } // initialize fields of R R->order=(int *)omAlloc0(n*sizeof(int)); R->block0=(int *)omAlloc0(n*sizeof(int)); R->block1=(int *)omAlloc0(n*sizeof(int)); R->wvhdl=(int**)omAlloc0(n*sizeof(int_ptr)); int *weights=(int*)omAlloc0((R->N+1)*sizeof(int)); // init order, so that rBlocks works correctly for (j=0; j < n-1; j++) R->order[j] = (int) ringorder_unspec; // set last _C order, if no c/C order was given if (i == 0) R->order[n-2] = ringorder_C; /* init orders */ sl=ord; n=-1; while (sl!=NULL) { intvec *iv; iv = (intvec *)(sl->data); if ((*iv)[1]!=ringorder_L) { n++; /* the format of an ordering: * iv[0]: factor * iv[1]: ordering * iv[2..end]: weights */ R->order[n] = (*iv)[1]; typ=1; switch ((*iv)[1]) { case ringorder_ws: case ringorder_Ws: typ=-1; case ringorder_wp: case ringorder_Wp: R->wvhdl[n]=(int*)omAlloc((iv->length()-1)*sizeof(int)); R->block0[n] = last+1; for (i=2; ilength(); i++) { R->wvhdl[n][i-2] = (*iv)[i]; last++; if (weights[last]==0) weights[last]=(*iv)[i]*typ; } R->block1[n] = si_min(last,R->N); break; case ringorder_ls: case ringorder_ds: case ringorder_Ds: case ringorder_rs: typ=-1; case ringorder_lp: case ringorder_dp: case ringorder_Dp: case ringorder_rp: R->block0[n] = last+1; if (iv->length() == 3) last+=(*iv)[2]; else last += (*iv)[0]; R->block1[n] = si_min(last,R->N); if (rCheckIV(iv)) return TRUE; for(i=si_min(rVar(R),R->block1[n]);i>=R->block0[n];i--) { if (weights[i]==0) weights[i]=typ; } break; case ringorder_s: // no 'rank' params! { if(iv->length() > 3) return TRUE; if(iv->length() == 3) { const int s = (*iv)[2]; R->block0[n] = s; R->block1[n] = s; } break; } case ringorder_IS: { if(iv->length() != 3) return TRUE; const int s = (*iv)[2]; if( 1 < s || s < -1 ) return TRUE; R->block0[n] = s; R->block1[n] = s; break; } case ringorder_S: case ringorder_c: case ringorder_C: { if (rCheckIV(iv)) return TRUE; break; } case ringorder_aa: case ringorder_a: { R->block0[n] = last+1; R->block1[n] = si_min(last+iv->length()-2 , R->N); R->wvhdl[n] = (int*)omAlloc((iv->length()-1)*sizeof(int)); for (i=2; ilength(); i++) { R->wvhdl[n][i-2]=(*iv)[i]; last++; if (weights[last]==0) weights[last]=(*iv)[i]*typ; } last=R->block0[n]-1; break; } case ringorder_am: { R->block0[n] = last+1; R->block1[n] = si_min(last+iv->length()-2 , R->N); R->wvhdl[n] = (int*)omAlloc(iv->length()*sizeof(int)); if (R->block1[n]- R->block0[n]+2>=iv->length()) WarnS("missing module weights"); for (i=2; i<=(R->block1[n]-R->block0[n]+2); i++) { R->wvhdl[n][i-2]=(*iv)[i]; last++; if (weights[last]==0) weights[last]=(*iv)[i]*typ; } R->wvhdl[n][i-2]=iv->length() -3 -(R->block1[n]- R->block0[n]); for (; ilength(); i++) { R->wvhdl[n][i-1]=(*iv)[i]; } last=R->block0[n]-1; break; } case ringorder_a64: { R->block0[n] = last+1; R->block1[n] = si_min(last+iv->length()-2 , R->N); R->wvhdl[n] = (int*)omAlloc((iv->length()-1)*sizeof(int64)); int64 *w=(int64 *)R->wvhdl[n]; for (i=2; ilength(); i++) { w[i-2]=(*iv)[i]; last++; if (weights[last]==0) weights[last]=(*iv)[i]*typ; } last=R->block0[n]-1; break; } case ringorder_M: { int Mtyp=rTypeOfMatrixOrder(iv); if (Mtyp==0) return TRUE; if (Mtyp==-1) typ = -1; R->wvhdl[n] =( int *)omAlloc((iv->length()-1)*sizeof(int)); for (i=2; ilength();i++) R->wvhdl[n][i-2]=(*iv)[i]; R->block0[n] = last+1; last += (int)sqrt((double)(iv->length()-2)); R->block1[n] = si_min(last,R->N); for(i=R->block1[n];i>=R->block0[n];i--) { if (weights[i]==0) weights[i]=typ; } break; } case ringorder_no: R->order[n] = ringorder_unspec; return TRUE; default: Werror("Internal Error: Unknown ordering %d", (*iv)[1]); R->order[n] = ringorder_unspec; return TRUE; } } if (last>R->N) { Werror("mismatch of number of vars (%d) and ordering (>=%d vars)", R->N,last); return TRUE; } sl=sl->next; } // check for complete coverage while ( n >= 0 && ( (R->order[n]==ringorder_c) || (R->order[n]==ringorder_C) || (R->order[n]==ringorder_s) || (R->order[n]==ringorder_S) || (R->order[n]==ringorder_IS) )) n--; assume( n >= 0 ); if (R->block1[n] != R->N) { if (((R->order[n]==ringorder_dp) || (R->order[n]==ringorder_ds) || (R->order[n]==ringorder_Dp) || (R->order[n]==ringorder_Ds) || (R->order[n]==ringorder_rp) || (R->order[n]==ringorder_rs) || (R->order[n]==ringorder_lp) || (R->order[n]==ringorder_ls)) && R->block0[n] <= R->N) { R->block1[n] = R->N; } else { Werror("mismatch of number of vars (%d) and ordering (%d vars)", R->N,R->block1[n]); return TRUE; } } // find OrdSgn: R->OrdSgn = 1; for(i=1;i<=R->N;i++) { if (weights[i]<0) { R->OrdSgn=-1;break; }} omFree(weights); return FALSE; } BOOLEAN rSleftvList2StringArray(sleftv* sl, char** p) { while(sl!=NULL) { if (sl->Name() == sNoName) { if (sl->Typ()==POLY_CMD) { sleftv s_sl; iiConvert(POLY_CMD,ANY_TYPE,-1,sl,&s_sl); if (s_sl.Name() != sNoName) *p = omStrDup(s_sl.Name()); else *p = NULL; sl->next = s_sl.next; s_sl.next = NULL; s_sl.CleanUp(); if (*p == NULL) return TRUE; } else return TRUE; } else *p = omStrDup(sl->Name()); p++; sl=sl->next; } return FALSE; } const short MAX_SHORT = 32767; // (1 << (sizeof(short)*8)) - 1; //////////////////// // // rInit itself: // // INPUT: s: name, pn: ch & parameter (names), rv: variable (names) // ord: ordering // RETURN: currRingHdl on success // NULL on error // NOTE: * makes new ring to current ring, on success // * considers input sleftv's as read-only //idhdl rInit(char *s, sleftv* pn, sleftv* rv, sleftv* ord) ring rInit(sleftv* pn, sleftv* rv, sleftv* ord) { #ifdef HAVE_RINGS //unsigned int ringtype = 0; mpz_ptr modBase = NULL; unsigned int modExponent = 1; #endif int float_len=0; int float_len2=0; ring R = NULL; //BOOLEAN ffChar=FALSE; /* ch -------------------------------------------------------*/ // get ch of ground field // allocated ring R = (ring) omAlloc0Bin(sip_sring_bin); coeffs cf = NULL; assume( pn != NULL ); const int P = pn->listLength(); #ifdef SINGULAR_4_1 if (pn->Typ()==CRING_CMD) { cf=(coeffs)pn->CopyD(); if(P>1) /*parameter*/ { pn = pn->next; const int pars = pn->listLength(); assume( pars > 0 ); char ** names = (char**)omAlloc0(pars * sizeof(char_ptr)); if (rSleftvList2StringArray(pn, names)) { WerrorS("parameter expected"); goto rInitError; } TransExtInfo extParam; extParam.r = rDefault( cf, pars, names); // Q/Zp [ p_1, ... p_pars ] for(int i=pars-1; i>=0;i--) { omFree(names[i]); } omFree(names); cf = nInitChar(n_transExt, &extParam); } assume( cf != NULL ); } else #endif if (pn->Typ()==INT_CMD) { int ch = (int)(long)pn->Data(); /* parameter? -------------------------------------------------------*/ pn = pn->next; if (pn == NULL) // no params!? { if (ch!=0) { int ch2=IsPrime(ch); if ((ch<2)||(ch!=ch2)) { Warn("%d is invalid as characteristic of the ground field. 32003 is used.", ch); ch=32003; } cf = nInitChar(n_Zp, (void*)(long)ch); } else cf = nInitChar(n_Q, (void*)(long)ch); } else { const int pars = pn->listLength(); assume( pars > 0 ); // predefined finite field: (p^k, a) if ((ch!=0) && (ch!=IsPrime(ch)) && (pars == 1)) { GFInfo param; param.GFChar = ch; param.GFDegree = 1; param.GFPar_name = pn->name; cf = nInitChar(n_GF, ¶m); } else // (0/p, a, b, ..., z) { if ((ch!=0) && (ch!=IsPrime(ch))) { WerrorS("too many parameters"); goto rInitError; } char ** names = (char**)omAlloc0(pars * sizeof(char_ptr)); if (rSleftvList2StringArray(pn, names)) { WerrorS("parameter expected"); goto rInitError; } TransExtInfo extParam; extParam.r = rDefault( ch, pars, names); // Q/Zp [ p_1, ... p_pars ] for(int i=pars-1; i>=0;i--) { omFree(names[i]); } omFree(names); cf = nInitChar(n_transExt, &extParam); } } // if (cf==NULL) goto rInitError; assume( cf != NULL ); } else if ((pn->name != NULL) && ((strcmp(pn->name,"real")==0) || (strcmp(pn->name,"complex")==0))) { BOOLEAN complex_flag=(strcmp(pn->name,"complex")==0); if ((pn->next!=NULL) && (pn->next->Typ()==INT_CMD)) { float_len=(int)(long)pn->next->Data(); float_len2=float_len; pn=pn->next; if ((pn->next!=NULL) && (pn->next->Typ()==INT_CMD)) { float_len2=(int)(long)pn->next->Data(); pn=pn->next; } } if (!complex_flag) complex_flag= pn->next != NULL; if( !complex_flag && (float_len2 <= (short)SHORT_REAL_LENGTH)) cf=nInitChar(n_R, NULL); else // longR or longC? { LongComplexInfo param; param.float_len = si_min (float_len, 32767); param.float_len2 = si_min (float_len2, 32767); // set the parameter name if (complex_flag) { if (param.float_len < SHORT_REAL_LENGTH) { param.float_len= SHORT_REAL_LENGTH; param.float_len2= SHORT_REAL_LENGTH; } if (pn->next == NULL) param.par_name=(const char*)"i"; //default to i else param.par_name = (const char*)pn->next->name; } cf = nInitChar(complex_flag ? n_long_C: n_long_R, (void*)¶m); } assume( cf != NULL ); } #ifdef HAVE_RINGS else if ((pn->name != NULL) && (strcmp(pn->name, "integer") == 0)) { // TODO: change to use coeffs_BIGINT!? modBase = (mpz_ptr) omAlloc(sizeof(mpz_t)); mpz_init_set_si(modBase, 0); if (pn->next!=NULL) { if (pn->next->Typ()==INT_CMD) { mpz_set_ui(modBase, (int)(long) pn->next->Data()); pn=pn->next; if ((pn->next!=NULL) && (pn->next->Typ()==INT_CMD)) { modExponent = (long) pn->next->Data(); pn=pn->next; } while ((pn->next!=NULL) && (pn->next->Typ()==INT_CMD)) { mpz_mul_ui(modBase, modBase, (int)(long) pn->next->Data()); pn=pn->next; } } else if (pn->next->Typ()==BIGINT_CMD) { number p=(number)pn->next->CopyD(); // FIXME: why CopyD() here if nlGMP should not overtake p!? nlGMP(p,(number)modBase,coeffs_BIGINT); // TODO? // extern void nlGMP(number &i, number n, const coeffs r); // FIXME: n_MPZ( modBase, p, coeffs_BIGINT); ? n_Delete(&p,coeffs_BIGINT); } } else cf=nInitChar(n_Z,NULL); if ((mpz_cmp_ui(modBase, 1) == 0) && (mpz_cmp_ui(modBase, 0) < 0)) { Werror("Wrong ground ring specification (module is 1)"); goto rInitError; } if (modExponent < 1) { Werror("Wrong ground ring specification (exponent smaller than 1"); goto rInitError; } // module is 0 ---> integers ringtype = 4; // we have an exponent if (modExponent > 1 && cf == NULL) { if ((mpz_cmp_ui(modBase, 2) == 0) && (modExponent <= 8*sizeof(unsigned long))) { /* this branch should be active for modExponent = 2..32 resp. 2..64, depending on the size of a long on the respective platform */ //ringtype = 1; // Use Z/2^ch cf=nInitChar(n_Z2m,(void*)(long)modExponent); mpz_clear(modBase); omFreeSize (modBase, sizeof (mpz_t)); } else { if (mpz_cmp_ui(modBase,0)==0) { WerrorS("modulus must not be 0 or parameter not allowed"); goto rInitError; } //ringtype = 3; ZnmInfo info; info.base= modBase; info.exp= modExponent; cf=nInitChar(n_Znm,(void*) &info); //exponent is missing } } // just a module m > 1 else if (cf == NULL) { if (mpz_cmp_ui(modBase,0)==0) { WerrorS("modulus must not be 0 or parameter not allowed"); goto rInitError; } //ringtype = 2; ZnmInfo info; info.base= modBase; info.exp= modExponent; cf=nInitChar(n_Zn,(void*) &info); } assume( cf != NULL ); } #endif // ring NEW = OLD, (), (); where OLD is a polynomial ring... else if ((pn->Typ()==RING_CMD) && (P == 1)) { TransExtInfo extParam; extParam.r = (ring)pn->Data(); cf = nInitChar(n_transExt, &extParam); } else if ((pn->Typ()==QRING_CMD) && (P == 1)) // same for qrings - which should be fields!? { AlgExtInfo extParam; extParam.r = (ring)pn->Data(); cf = nInitChar(n_algExt, &extParam); // Q[a]/ } else { Werror("Wrong or unknown ground field specification"); #ifndef SING_NDEBUG sleftv* p = pn; while (p != NULL) { Print( "pn[%p]: type: %d [%s]: %p, name: %s", (void*)p, p->Typ(), Tok2Cmdname(p->Typ()), p->Data(), (p->name == NULL? "NULL" : p->name) ); PrintLn(); p = p->next; } #endif goto rInitError; } // pn=pn->next; /*every entry in the new ring is initialized to 0*/ /* characteristic -----------------------------------------------*/ /* input: 0 ch=0 : Q parameter=NULL ffChar=FALSE float_len * 0 1 : Q(a,...) *names FALSE * 0 -1 : R NULL FALSE 0 * 0 -1 : R NULL FALSE prec. >6 * 0 -1 : C *names FALSE prec. 0..? * p p : Fp NULL FALSE * p -p : Fp(a) *names FALSE * q q : GF(q=p^n) *names TRUE */ if (cf==NULL) { Werror("Invalid ground field specification"); goto rInitError; // const int ch=32003; // cf=nInitChar(n_Zp, (void*)(long)ch); } assume( R != NULL ); R->cf = cf; /* names and number of variables-------------------------------------*/ { int l=rv->listLength(); if (l>MAX_SHORT) { Werror("too many ring variables(%d), max is %d",l,MAX_SHORT); goto rInitError; } R->N = l; /*rv->listLength();*/ } R->names = (char **)omAlloc0(R->N * sizeof(char_ptr)); if (rSleftvList2StringArray(rv, R->names)) { WerrorS("name of ring variable expected"); goto rInitError; } /* check names and parameters for conflicts ------------------------- */ rRenameVars(R); // conflicting variables will be renamed /* ordering -------------------------------------------------------------*/ if (rSleftvOrdering2Ordering(ord, R)) goto rInitError; // Complete the initialization if (rComplete(R,1)) goto rInitError; /*#ifdef HAVE_RINGS // currently, coefficients which are ring elements require a global ordering: if (rField_is_Ring(R) && (R->OrdSgn==-1)) { WerrorS("global ordering required for these coefficients"); goto rInitError; } #endif*/ rTest(R); // try to enter the ring into the name list // need to clean up sleftv here, before this ring can be set to // new currRing or currRing can be killed beacuse new ring has // same name if (pn != NULL) pn->CleanUp(); if (rv != NULL) rv->CleanUp(); if (ord != NULL) ord->CleanUp(); //if ((tmp = enterid(s, myynest, RING_CMD, &IDROOT))==NULL) // goto rInitError; //memcpy(IDRING(tmp),R,sizeof(*R)); // set current ring //omFreeBin(R, ip_sring_bin); //return tmp; return R; // error case: rInitError: if ((R != NULL)&&(R->cf!=NULL)) rDelete(R); if (pn != NULL) pn->CleanUp(); if (rv != NULL) rv->CleanUp(); if (ord != NULL) ord->CleanUp(); return NULL; } ring rSubring(ring org_ring, sleftv* rv) { ring R = rCopy0(org_ring); int *perm=(int *)omAlloc0((org_ring->N+1)*sizeof(int)); int n = rBlocks(org_ring), i=0, j; /* names and number of variables-------------------------------------*/ { int l=rv->listLength(); if (l>MAX_SHORT) { Werror("too many ring variables(%d), max is %d",l,MAX_SHORT); goto rInitError; } R->N = l; /*rv->listLength();*/ } omFree(R->names); R->names = (char **)omAlloc0(R->N * sizeof(char_ptr)); if (rSleftvList2StringArray(rv, R->names)) { WerrorS("name of ring variable expected"); goto rInitError; } /* check names for subring in org_ring ------------------------- */ { i=0; for(j=0;jN;j++) { for(;iN;i++) { if (strcmp(org_ring->names[i],R->names[j])==0) { perm[i+1]=j+1; break; } } if (i>org_ring->N) { Werror("variable %d (%s) not in basering",j+1,R->names[j]); break; } } } //Print("perm="); //for(i=1;iN;i++) Print("v%d -> v%d\n",i,perm[i]); /* ordering -------------------------------------------------------------*/ for(i=0;iblock0[i];j<=R->block1[i];j++) { if (perm[j]>0) { if (min_var==-1) min_var=perm[j]; max_var=perm[j]; } } if (min_var!=-1) { //Print("block %d: old %d..%d, now:%d..%d\n", // i,R->block0[i],R->block1[i],min_var,max_var); R->block0[i]=min_var; R->block1[i]=max_var; if (R->wvhdl[i]!=NULL) { omFree(R->wvhdl[i]); R->wvhdl[i]=(int*)omAlloc0((max_var-min_var+1)*sizeof(int)); for(j=org_ring->block0[i];j<=org_ring->block1[i];j++) { if (perm[j]>0) { R->wvhdl[i][perm[j]-R->block0[i]]= org_ring->wvhdl[i][j-org_ring->block0[i]]; //Print("w%d=%d (orig_w%d)\n",perm[j],R->wvhdl[i][perm[j]-R->block0[i]],j); } } } } else { if(R->block0[i]>0) { //Print("skip block %d\n",i); R->order[i]=ringorder_unspec; if (R->wvhdl[i] !=NULL) omFree(R->wvhdl[i]); R->wvhdl[i]=NULL; } //else Print("keep block %d\n",i); } } i=n-1; while(i>0) { // removed unneded blocks if(R->order[i-1]==ringorder_unspec) { for(j=i;j<=n;j++) { R->order[j-1]=R->order[j]; R->block0[j-1]=R->block0[j]; R->block1[j-1]=R->block1[j]; if (R->wvhdl[j-1] !=NULL) omFree(R->wvhdl[j-1]); R->wvhdl[j-1]=R->wvhdl[j]; } R->order[n]=ringorder_unspec; n--; } i--; } n=rBlocks(org_ring)-1; while (R->order[n]==0) n--; while (R->order[n]==ringorder_unspec) n--; if ((R->order[n]==ringorder_c) || (R->order[n]==ringorder_C)) n--; if (R->block1[n] != R->N) { if (((R->order[n]==ringorder_dp) || (R->order[n]==ringorder_ds) || (R->order[n]==ringorder_Dp) || (R->order[n]==ringorder_Ds) || (R->order[n]==ringorder_rp) || (R->order[n]==ringorder_rs) || (R->order[n]==ringorder_lp) || (R->order[n]==ringorder_ls)) && R->block0[n] <= R->N) { R->block1[n] = R->N; } else { Werror("mismatch of number of vars (%d) and ordering (%d vars) in block %d", R->N,R->block1[n],n); return NULL; } } omFree(perm); // find OrdSgn: R->OrdSgn = org_ring->OrdSgn; // IMPROVE! //for(i=1;i<=R->N;i++) //{ if (weights[i]<0) { R->OrdSgn=-1;break; }} //omFree(weights); // Complete the initialization if (rComplete(R,1)) goto rInitError; rTest(R); if (rv != NULL) rv->CleanUp(); return R; // error case: rInitError: if (R != NULL) rDelete(R); if (rv != NULL) rv->CleanUp(); return NULL; } void rKill(ring r) { if ((r->ref<=0)&&(r->order!=NULL)) { #ifdef RDEBUG if (traceit &TRACE_SHOW_RINGS) Print("kill ring %lx\n",(long)r); #endif if (r->qideal!=NULL) { id_Delete(&r->qideal, r); r->qideal = NULL; } int j; #ifdef USE_IILOCALRING for (j=0;jnext) { if (nshdl->cRing==r) { Warn("killing the basering for level %d",lev); nshdl->cRing=NULL; nshdl->cRingHdl=NULL; } } } #endif /* USE_IILOCALRING */ // any variables depending on r ? while (r->idroot!=NULL) { r->idroot->lev=myynest; // avoid warning about kill global objects killhdl2(r->idroot,&(r->idroot),r); } if (r==currRing) { // all dependend stuff is done, clean global vars: if ((currRing->ppNoether)!=NULL) pDelete(&(currRing->ppNoether)); if (sLastPrinted.RingDependend()) { sLastPrinted.CleanUp(); } //if ((myynest>0) && (iiRETURNEXPR.RingDependend())) //{ // WerrorS("return value depends on local ring variable (export missing ?)"); // iiRETURNEXPR.CleanUp(); //} currRing=NULL; currRingHdl=NULL; } /* nKillChar(r); will be called from inside of rDelete */ rDelete(r); return; } r->ref--; } void rKill(idhdl h) { ring r = IDRING(h); int ref=0; if (r!=NULL) { ref=r->ref; rKill(r); } if (h==currRingHdl) { if (ref<=0) { currRing=NULL; currRingHdl=NULL;} else { currRingHdl=rFindHdl(r,currRingHdl); } } } idhdl rSimpleFindHdl(ring r, idhdl root, idhdl n) { //idhdl next_best=NULL; idhdl h=root; while (h!=NULL) { if (((IDTYP(h)==RING_CMD)||(IDTYP(h)==QRING_CMD)) && (h!=n) && (IDRING(h)==r) ) { // if (IDLEV(h)==myynest) // return h; // if ((IDLEV(h)==0) || (next_best==NULL)) // next_best=h; // else if (IDLEV(next_best)next; else { while ((h!=NULL) &&(h->next!=new_ring)) h=h->next; if (h!=NULL) h->next=h->next->next; } if (h!=NULL) omFreeSize(h,sizeof(*h)); } currRingHdl=save_ringhdl; u.CleanUp(); v.CleanUp(); return resid; } static void jjINT_S_TO_ID(int n,int *e, leftv res) { if (n==0) n=1; ideal l=idInit(n,1); int i; poly p; for(i=rVar(currRing);i>0;i--) { if (e[i]>0) { n--; p=pOne(); pSetExp(p,i,1); pSetm(p); l->m[n]=p; if (n==0) break; } } res->data=(char*)l; setFlag(res,FLAG_STD); omFreeSize((ADDRESS)e,(rVar(currRing)+1)*sizeof(int)); } BOOLEAN jjVARIABLES_P(leftv res, leftv u) { int *e=(int *)omAlloc0((rVar(currRing)+1)*sizeof(int)); int n=pGetVariables((poly)u->Data(),e); jjINT_S_TO_ID(n,e,res); return FALSE; } BOOLEAN jjVARIABLES_ID(leftv res, leftv u) { int *e=(int *)omAlloc0((rVar(currRing)+1)*sizeof(int)); ideal I=(ideal)u->Data(); int i; int n=0; for(i=I->nrows*I->ncols-1;i>=0;i--) { int n0=pGetVariables(I->m[i],e); if (n0>n) n=n0; } jjINT_S_TO_ID(n,e,res); return FALSE; } void paPrint(const char *n,package p) { Print(" %s (",n); switch (p->language) { case LANG_SINGULAR: PrintS("S"); break; case LANG_C: PrintS("C"); break; case LANG_TOP: PrintS("T"); break; case LANG_NONE: PrintS("N"); break; default: PrintS("U"); } if(p->libname!=NULL) Print(",%s", p->libname); PrintS(")"); } BOOLEAN iiApplyINTVEC(leftv res, leftv a, int op, leftv proc) { intvec *aa=(intvec*)a->Data(); sleftv tmp_out; sleftv tmp_in; leftv curr=res; BOOLEAN bo=FALSE; for(int i=0;ilength(); i++) { memset(&tmp_in,0,sizeof(tmp_in)); tmp_in.rtyp=INT_CMD; tmp_in.data=(void*)(long)(*aa)[i]; if (proc==NULL) bo=iiExprArith1(&tmp_out,&tmp_in,op); else bo=jjPROC(&tmp_out,proc,&tmp_in); if (bo) { res->CleanUp(currRing); Werror("apply fails at index %d",i+1); return TRUE; } if (i==0) { memcpy(res,&tmp_out,sizeof(tmp_out)); } else { curr->next=(leftv)omAllocBin(sleftv_bin); curr=curr->next; memcpy(curr,&tmp_out,sizeof(tmp_out)); } } return FALSE; } BOOLEAN iiApplyBIGINTMAT(leftv res, leftv a, int op, leftv proc) { WerrorS("not implemented"); return TRUE; } BOOLEAN iiApplyIDEAL(leftv res, leftv a, int op, leftv proc) { WerrorS("not implemented"); return TRUE; } BOOLEAN iiApplyLIST(leftv res, leftv a, int op, leftv proc) { lists aa=(lists)a->Data(); sleftv tmp_out; sleftv tmp_in; leftv curr=res; BOOLEAN bo=FALSE; for(int i=0;i<=aa->nr; i++) { memset(&tmp_in,0,sizeof(tmp_in)); tmp_in.Copy(&(aa->m[i])); if (proc==NULL) bo=iiExprArith1(&tmp_out,&tmp_in,op); else bo=jjPROC(&tmp_out,proc,&tmp_in); tmp_in.CleanUp(); if (bo) { res->CleanUp(currRing); Werror("apply fails at index %d",i+1); return TRUE; } if (i==0) { memcpy(res,&tmp_out,sizeof(tmp_out)); } else { curr->next=(leftv)omAllocBin(sleftv_bin); curr=curr->next; memcpy(curr,&tmp_out,sizeof(tmp_out)); } } return FALSE; } BOOLEAN iiApply(leftv res, leftv a, int op, leftv proc) { memset(res,0,sizeof(sleftv)); res->rtyp=a->Typ(); switch (res->rtyp /*a->Typ()*/) { case INTVEC_CMD: case INTMAT_CMD: return iiApplyINTVEC(res,a,op,proc); case BIGINTMAT_CMD: return iiApplyBIGINTMAT(res,a,op,proc); case IDEAL_CMD: case MODUL_CMD: case MATRIX_CMD: return iiApplyIDEAL(res,a,op,proc); case LIST_CMD: return iiApplyLIST(res,a,op,proc); } WerrorS("first argument to `apply` must allow an index"); return TRUE; } BOOLEAN iiTestAssume(leftv a, leftv b) { // assume a: level if ((a->Typ()==INT_CMD)&&((long)a->Data()>=0)) { if ((TEST_V_ALLWARN) && (myynest==0)) WarnS("ASSUME at top level is of no use: see documentation"); char assume_yylinebuf[80]; strncpy(assume_yylinebuf,my_yylinebuf,79); int lev=(long)a->Data(); int startlev=0; idhdl h=ggetid("assumeLevel"); if ((h!=NULL)&&(IDTYP(h)==INT_CMD)) startlev=(long)IDINT(h); if(lev <=startlev) { BOOLEAN bo=b->Eval(); if (bo) { WerrorS("syntax error in ASSUME");return TRUE;} if (b->Typ()!=INT_CMD) { WerrorS("ASUMME(,)");return TRUE; } if (b->Data()==NULL) { Werror("ASSUME failed:%s",assume_yylinebuf);return TRUE;} } } b->CleanUp(); a->CleanUp(); return FALSE; } #include "libparse.h" BOOLEAN iiARROW(leftv r, char* a, char *s) { char *ss=(char*)omAlloc(strlen(a)+strlen(s)+30); /* max. 27 currently */ // find end of s: int end_s=strlen(s); while ((end_s>0) && ((s[end_s]<=' ')||(s[end_s]==';'))) end_s--; s[end_s+1]='\0'; char *name=(char *)omAlloc(strlen(a)+strlen(s)+30); sprintf(name,"%s->%s",a,s); // find start of last expression int start_s=end_s-1; while ((start_s>=0) && (s[start_s]!=';')) start_s--; if (start_s<0) // ';' not found { sprintf(ss,"parameter def %s;return(%s);\n",a,s); } else // s[start_s] is ';' { s[start_s]='\0'; sprintf(ss,"parameter def %s;%s;return(%s);\n",a,s,s+start_s+1); } memset(r,0,sizeof(*r)); // now produce procinfo for PROC_CMD: r->data = (void *)omAlloc0Bin(procinfo_bin); ((procinfo *)(r->data))->language=LANG_NONE; iiInitSingularProcinfo((procinfo *)r->data,"",name,0,0); ((procinfo *)r->data)->data.s.body=ss; omFree(name); r->rtyp=PROC_CMD; //r->rtyp=STRING_CMD; //r->data=ss; return FALSE; } BOOLEAN iiAssignCR(leftv r, leftv arg) { int t=arg->Typ(); char* ring_name=omStrDup((char*)r->Name()); if ((t==RING_CMD) ||(t==QRING_CMD)) { sleftv tmp; memset(&tmp,0,sizeof(tmp)); tmp.rtyp=IDHDL; tmp.data=(char*)rDefault(ring_name); if (tmp.data!=NULL) { BOOLEAN b=iiAssign(&tmp,arg); if (b) return TRUE; rSetHdl(ggetid(ring_name)); omFree(ring_name); return FALSE; } else return TRUE; } #ifdef SINGULAR_4_1 else if (t==CRING_CMD) { sleftv tmp; sleftv n; memset(&n,0,sizeof(n)); n.name=ring_name; if (iiDeclCommand(&tmp,&n,myynest,CRING_CMD,&IDROOT)) return TRUE; if (iiAssign(&tmp,arg)) return TRUE; //Print("create %s\n",r->Name()); //Print("from %s(%d)\n",Tok2Cmdname(arg->Typ()),arg->Typ()); return FALSE; } #endif //Print("create %s\n",r->Name()); //Print("from %s(%d)\n",Tok2Cmdname(arg->Typ()),arg->Typ()); return TRUE;// not handled -> error for now } static void iiReportTypes(int nr,int t,const short *T) { char *buf=(char*)omAlloc(250); buf[0]='\0'; if (nr==0) sprintf(buf,"wrong length of parameters(%d), expected ",t); else sprintf(buf,"par. %d is of type `%s`, expected ",nr,Tok2Cmdname(t)); for(int i=1;i<=T[0];i++) { strcat(buf,"`"); strcat(buf,Tok2Cmdname(T[i])); strcat(buf,"`"); if (ilistLength(); if (l!=(int)type_list[0]) { if (report) iiReportTypes(0,l,type_list); return FALSE; } for(int i=1;i<=l;i++,args=args->next) { short t=type_list[i]; if (t!=ANY_TYPE) { if (((t==IDHDL)&&(args->rtyp!=IDHDL)) || (t!=args->Typ())) { if (report) iiReportTypes(i,args->Typ(),type_list); return FALSE; } } } return TRUE; } singular-4.0.3+ds/Singular/ipshell.h000066400000000000000000000233261266270727000173600ustar00rootroot00000000000000#ifndef IPSHELL_H #define IPSHELL_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT */ #include //#include #include #include #include struct _ssubexpr; typedef struct _ssubexpr *Subexpr; BOOLEAN spectrumProc ( leftv,leftv ); BOOLEAN spectrumfProc( leftv,leftv ); BOOLEAN spaddProc ( leftv,leftv,leftv ); BOOLEAN spmulProc ( leftv,leftv,leftv ); BOOLEAN semicProc ( leftv,leftv,leftv ); BOOLEAN semicProc3 ( leftv,leftv,leftv,leftv ); BOOLEAN iiAssignCR(leftv, leftv); BOOLEAN iiARROW (leftv, char*,char *); extern leftv iiCurrArgs; extern idhdl iiCurrProc; extern int iiOp; /* the current operation*/ extern const char * currid; extern int iiRETURNEXPR_len; extern sleftv iiRETURNEXPR; #ifdef USE_IILOCALRING extern ring *iiLocalRing; #endif //extern cmdnames cmds[]; extern const char *lastreserved; extern const char *singular_date; /* tesths.cc, set by final compile */ extern int myynest; extern int printlevel; extern int si_echo; extern BOOLEAN yyInRingConstruction; /* 1: during ring construction */ int IsCmd(const char *n, int & tok); BOOLEAN iiPStart(idhdl pn, sleftv * sl); BOOLEAN iiEStart(char* example, procinfo *pi); BOOLEAN iiAllStart(procinfov pi, char *p,feBufferTypes t, int l); void type_cmd(leftv v); void test_cmd(int i); void list_cmd(int typ, const char* what, const char * prefix, BOOLEAN iterate, BOOLEAN fullname=FALSE); //char * iiStringMatrix(matrix im, int dim, char ch=','); void killlocals(int v); int exprlist_length(leftv v); const char * Tok2Cmdname(int i); const char * iiTwoOps(int t); int iiOpsTwoChar(const char *s); BOOLEAN iiWRITE(leftv res,leftv exprlist); BOOLEAN iiExport(leftv v, int toLev); BOOLEAN iiExport(leftv v, int toLev, package pack); BOOLEAN iiInternalExport (leftv v, int toLev, package pack); char * iiGetLibName(procinfov v); char * iiGetLibProcBuffer( procinfov pi, int part=1 ); char * iiProcName(char *buf, char & ct, char* &e); char * iiProcArgs(char *e,BOOLEAN withParenth); BOOLEAN iiLibCmd( char *newlib, BOOLEAN autoexport, BOOLEAN tellerror, BOOLEAN force ); /* sees wheter library lib has already been loaded if yes, writes filename of lib into where and returns TRUE, if no, returns FALSE */ /// load lib/module given in v BOOLEAN jjLOAD(const char *s, BOOLEAN autoexport = FALSE); BOOLEAN jjLOAD_TRY(const char *s); BOOLEAN iiLocateLib(const char* lib, char* where); leftv iiMap(map theMap, const char * what); void iiMakeResolv(resolvente r, int length, int rlen, char * name, int typ0, intvec ** weights=NULL); BOOLEAN jjMINRES(leftv res, leftv v); BOOLEAN jjBETTI(leftv res, leftv v); BOOLEAN jjBETTI2(leftv res, leftv u, leftv v); BOOLEAN jjBETTI2_ID(leftv res, leftv u, leftv v); BOOLEAN jjIMPORTFROM(leftv res, leftv u, leftv v); BOOLEAN jjLIST_PL(leftv res, leftv v); BOOLEAN jjVARIABLES_P(leftv res, leftv u); BOOLEAN jjVARIABLES_ID(leftv res, leftv u); int iiRegularity(lists L); leftv singular_system(sleftv h); BOOLEAN jjSYSTEM(leftv res, leftv v); void iiDebug(); BOOLEAN iiCheckRing(int i); poly iiHighCorner(ideal i, int ak); char * iiConvName(const char *libname); BOOLEAN iiLoadLIB(FILE *fp, const char *libnamebuf, const char *newlib, idhdl pl, BOOLEAN autoexport, BOOLEAN tellerror); // converts a resolution into a list of modules lists syConvRes(syStrategy syzstr,BOOLEAN toDel=FALSE,int add_row_shift=0); // converts a list of modules into a minimal resolution syStrategy syForceMin(lists li); // converts a list of modules into a resolution syStrategy syConvList(lists li,BOOLEAN toDel); BOOLEAN syBetti1(leftv res, leftv u); BOOLEAN syBetti2(leftv res, leftv u, leftv w); /* ================================================================== */ /* Expressions : */ BOOLEAN iiExprArith1(leftv res, sleftv* a, int op); BOOLEAN iiExprArith2(leftv res, sleftv* a, int op, sleftv* b, BOOLEAN proccall=FALSE); BOOLEAN iiExprArith3(leftv res, int op, leftv a, leftv b, leftv c); BOOLEAN iiExprArithM(leftv res, sleftv* a, int op); BOOLEAN iiApply(leftv res,leftv a, int op, leftv proc); typedef BOOLEAN (*proc1)(leftv,leftv); #ifdef GENTABLE typedef char * (*Proc1)(char *); struct sValCmd1 { proc1 p; short cmd; short res; short arg; short valid_for; }; typedef BOOLEAN (*proc2)(leftv,leftv,leftv); struct sValCmd2 { proc2 p; short cmd; short res; short arg1; short arg2; short valid_for; }; typedef BOOLEAN (*proc3)(leftv,leftv,leftv,leftv); struct sValCmd3 { proc3 p; short cmd; short res; short arg1; short arg2; short arg3; short valid_for; }; struct sValCmdM { proc1 p; short cmd; short res; short number_of_args; /* -1: any, -2: any >0, .. */ short valid_for; }; extern struct sValCmd2 dArith2[]; extern struct sValCmd1 dArith1[]; extern struct sValCmd3 dArith3[]; extern struct sValCmdM dArithM[]; #endif /* ================================================================== */ /* Assigments : */ BOOLEAN iiAssign(leftv left, leftv right, BOOLEAN toplevel=TRUE); typedef BOOLEAN (*proci)(leftv,leftv,Subexpr); struct sValAssign_sys { proc1 p; short res; short arg; }; struct sValAssign { proci p; short res; short arg; }; BOOLEAN iiParameter(leftv p); BOOLEAN iiAlias(leftv p); int iiTokType(int op); /* ================================================================== */ int iiDeclCommand(leftv sy, leftv name, int lev, int t, idhdl* root, BOOLEAN isring = FALSE, BOOLEAN init_b=TRUE); BOOLEAN iiMake_proc(idhdl pn, package pack, sleftv* sl); // from misc.cc: char * showOption(); BOOLEAN setOption(leftv res, leftv v); /* ================================================================== */ char * versionString(); /* ================================================================== */ void singular_example(char *str); BOOLEAN iiTryLoadLib(leftv v, const char *id); int iiAddCproc(const char *libname, const char *procname, BOOLEAN pstatic, BOOLEAN(*func)(leftv res, leftv v)); void iiCheckPack(package &p); #ifndef SING_NDEBUG void checkall(); #endif void rSetHdl(idhdl h); ring rInit(sleftv* pn, sleftv* rv, sleftv* ord); idhdl rDefault(const char *s); idhdl rSimpleFindHdl(ring r, idhdl root, idhdl n=NULL); idhdl rFindHdl(ring r, idhdl n); void rKill(idhdl h); void rKill(ring r); lists scIndIndset(ideal S, BOOLEAN all, ideal Q); BOOLEAN mpKoszul(leftv res,leftv c/*ip*/, leftv b/*in*/, leftv id); BOOLEAN mpJacobi(leftv res,leftv a); BOOLEAN jjRESULTANT(leftv res, leftv u, leftv v, leftv w); BOOLEAN kQHWeight(leftv res,leftv v); BOOLEAN kWeight(leftv res,leftv id); BOOLEAN loSimplex( leftv res, leftv args ); BOOLEAN loNewtonP( leftv res, leftv arg1 ); BOOLEAN nuMPResMat( leftv res, leftv arg1, leftv arg2 ); BOOLEAN nuLagSolve( leftv res, leftv arg1, leftv arg2, leftv arg3 ); BOOLEAN nuVanderSys( leftv res, leftv arg1, leftv arg2, leftv arg3); BOOLEAN nuUResSolve( leftv res, leftv args ); BOOLEAN jjCHARSERIES(leftv res, leftv u); /* BOOLEAN jjRESULTANT(leftv res, leftv u, leftv v, leftv w); #if 0 BOOLEAN jjIS_SQR_FREE(leftv res, leftv u); #endif */ /* ================================================================== */ void paPrint(const char *n,package p); /* ================================================================== */ BOOLEAN iiTestAssume(leftv a, leftv b); /* table inteface for iiAddCproc */ /// apply an operation 'op' to an argument a /// return TRUE on failure BOOLEAN iiExprArith1Tab(leftv res,///< [out] pre-allocated result leftv a, ///< [in] argument int op, ///< [in] operation struct sValCmd1* dA1, ///< [in] table of possible proc ///< assumes dArith1[0].cmd==op int at, ///< [in] a->Typ() struct sConvertTypes *dConvertTypes ///< [in] table of type conversions ); /// apply an operation 'op' to arguments a and a->next /// return TRUE on failure BOOLEAN iiExprArith2Tab(leftv res,///< [out] pre-allocated result leftv a, ///< [in] 2 arguments int op, ///< [in] operation struct sValCmd2* dA2,///< [in] table of possible proc ///< assumes dA2[0].cmd==op int at, ///< [in] a->Typ() struct sConvertTypes *dConvertTypes ///< [in] table of type conversions ); /// apply an operation 'op' to arguments a, a->next and a->next->next /// return TRUE on failure BOOLEAN iiExprArith3Tab(leftv res, ///< [out] pre-allocated result leftv a, ///< [in] 3 arguments int op, ///< [in] operation struct sValCmd3* dA3,///< [in] table of possible proc ///< assumes dA3[0].cmd==op int at, ///< [in] a->Typ() struct sConvertTypes *dConvertTypes ///< [in] table of type conversions ); /// check a list of arguemys against a given field of types /// return TRUE if the types match /// return FALSE (and, if report) report an error via Werror otherwise BOOLEAN iiCheckTypes(leftv args,/// < [in] argument list (may be NULL) const short *type_list,///< [in] field of types ///< len, t1,t2,... int report=0 /// ;in] report error? ); BOOLEAN iiBranchTo(leftv r, leftv args); #ifdef SINGULAR_4_1 BOOLEAN rDecompose_CF(leftv res,const coeffs C); #endif #endif singular-4.0.3+ds/Singular/libparse.cc000066400000000000000000003253431266270727000176630ustar00rootroot00000000000000#define yy_create_buffer yylp_create_buffer #define yy_delete_buffer yylp_delete_buffer #define yy_scan_buffer yylp_scan_buffer #define yy_scan_string yylp_scan_string #define yy_scan_bytes yylp_scan_bytes #define yy_flex_debug yylp_flex_debug #define yy_init_buffer yylp_init_buffer #define yy_flush_buffer yylp_flush_buffer #define yy_load_buffer_state yylp_load_buffer_state #define yy_switch_to_buffer yylp_switch_to_buffer #define yyin yylpin #define yyleng yylpleng #define yylex yylplex #define yyout yylpout #define yyrestart yylprestart #define yytext yylptext #define yywrap yylpwrap /* 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 /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ #ifdef c_plusplus #ifndef __cplusplus #define __cplusplus #endif #endif #ifdef __cplusplus #include #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 ) /* 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 )); 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; \ yytext_ptr -= yy_more_len; \ yyleng = (int) (yy_cp - yytext_ptr); \ yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; #define YY_NUM_RULES 96 #define YY_END_OF_BUFFER 97 static yyconst short int yy_accept[485] = { 0, 0, 0, 0, 0, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 95, 1, 92, 93, 2, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 20, 19, 20, 20, 20, 20, 20, 20, 20, 20, 29, 28, 27, 29, 29, 29, 29, 29, 29, 29, 29, 96, 30, 96, 96, 96, 39, 32, 36, 33, 34, 38, 35, 43, 43, 96, 43, 43, 43, 43, 43, 43, 42, 47, 46, 47, 45, 49, 51, 48, 50, 63, 62, 53, 58, 59, 63, 60, 61, 63, 56, 57, 83, 82, 75, 78, 79, 83, 80, 81, 76, 77, 88, 87, 84, 88, 73, 72, 70, 73, 91, 90, 91, 66, 65, 64, 69, 68, 67, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 31, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 42, 42, 44, 49, 52, 0, 74, 86, 85, 71, 89, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 13, 0, 0, 0, 0, 0, 0, 28, 28, 28, 28, 22, 21, 0, 0, 0, 0, 0, 0, 37, 37, 0, 0, 0, 41, 0, 42, 0, 0, 0, 0, 0, 52, 0, 74, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 13, 13, 0, 0, 0, 0, 0, 0, 0, 28, 22, 21, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 40, 0, 41, 0, 0, 0, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, 16, 0, 17, 0, 15, 21, 0, 0, 0, 0, 23, 0, 25, 0, 24, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 7, 0, 0, 5, 0, 0, 0, 0, 12, 0, 0, 0, 18, 0, 0, 0, 26, 0, 0, 0, 0, 0, 55, 0, 0, 8, 8, 0, 9, 0, 0, 3, 0, 0, 8, 8, 8, 5, 5, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0, 0, 8, 8, 8, 0, 3, 3, 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, 6, 0, 0, 12, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 4, 0, 0, 6, 6, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 11, 16, 11, 10, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 20, 11, 21, 11, 11, 12, 22, 23, 22, 22, 22, 22, 22, 24, 25, 22, 22, 26, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 27, 28, 29, 30, 31, 11, 32, 22, 33, 34, 35, 36, 37, 22, 38, 22, 22, 39, 40, 41, 42, 43, 22, 44, 45, 46, 47, 48, 22, 49, 50, 22, 51, 11, 52, 11, 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[53] = { 0, 1, 2, 3, 4, 2, 1, 5, 6, 1, 5, 1, 7, 8, 9, 5, 10, 5, 11, 5, 1, 1, 7, 7, 7, 7, 7, 1, 1, 1, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 4, 1 } ; static yyconst short int yy_base[533] = { 0, 0, 47, 6, 93, 140, 187, 235, 287, 339, 391, 5, 11, 443, 0, 9, 12, 63, 69, 493, 543, 0, 0, 593, 643, 72, 80, 81, 90, 26, 31, 24, 52, 54, 95, 0, 0, 0, 0, 1250, 2200, 1202, 2200, 2200, 1226, 2200, 1213, 1221, 1183, 1164, 1170, 1162, 1105, 1106, 1114, 2200, 2200, 1131, 61, 1115, 1105, 1100, 1108, 1117, 1096, 2200, 84, 2200, 1121, 95, 1105, 1095, 1091, 1098, 1100, 1073, 2200, 2200, 1109, 1099, 1101, 2200, 2200, 2200, 2200, 2200, 1083, 2200, 2200, 694, 0, 0, 125, 745, 144, 151, 157, 2200, 2200, 2200, 1048, 2200, 99, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 1080, 2200, 2200, 1052, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 1073, 2200, 2200, 2200, 2200, 2200, 2200, 2200, 4, 2200, 2200, 2200, 14, 2200, 2200, 1071, 2200, 2200, 2200, 2200, 2200, 2200, 1041, 1066, 1056, 1071, 1029, 1042, 1032, 1024, 1033, 1024, 1002, 163, 1039, 1027, 984, 992, 983, 976, 986, 966, 111, 796, 985, 972, 941, 945, 936, 874, 894, 874, 2200, 908, 2200, 900, 906, 895, 0, 0, 172, 0, 179, 191, 207, 2200, 904, 903, 219, 902, 74, 847, 198, 2200, 119, 0, 866, 0, 2200, 2200, 2200, 2200, 865, 0, 889, 213, 0, 869, 760, 757, 659, 645, 263, 645, 245, 82, 672, 0, 671, 651, 643, 274, 639, 132, 650, 665, 651, 649, 642, 0, 632, 612, 601, 278, 593, 133, 601, 0, 611, 318, 324, 330, 0, 375, 612, 0, 0, 381, 0, 609, 0, 578, 0, 576, 349, 594, 0, 562, 555, 368, 161, 559, 404, 509, 547, 548, 547, 0, 0, 560, 538, 500, 412, 522, 536, 422, 564, 0, 0, 0, 551, 530, 550, 530, 559, 527, 571, 553, 586, 610, 2200, 622, 628, 0, 307, 2200, 536, 226, 214, 2200, 2200, 507, 509, 600, 660, 577, 514, 898, 918, 495, 491, 500, 501, 475, 637, 969, 975, 2200, 473, 2200, 502, 2200, 491, 459, 650, 981, 990, 2200, 457, 2200, 491, 2200, 996, 1001, 0, 646, 1051, 1010, 1101, 1005, 453, 406, 1014, 1151, 121, 2200, 2200, 433, 432, 0, 431, 430, 390, 396, 1203, 384, 1022, 381, 2200, 369, 1055, 362, 2200, 1029, 227, 370, 270, 526, 2200, 269, 0, 287, 2200, 349, 2200, 380, 358, 0, 357, 350, 288, 318, 343, 2200, 348, 1046, 312, 0, 1255, 311, 274, 1068, 254, 1089, 1093, 1076, 345, 403, 405, 1223, 2200, 290, 1118, 1124, 241, 1231, 1216, 1244, 1237, 1275, 1287, 1110, 101, 1307, 1293, 1314, 1344, 1334, 1351, 1364, 1374, 1394, 254, 1445, 1449, 1455, 1469, 1475, 1481, 662, 1300, 238, 0, 239, 1313, 154, 1490, 1510, 245, 200, 0, 199, 192, 1562, 1590, 1596, 1591, 605, 214, 1035, 2200, 1610, 1332, 1607, 190, 184, 0, 143, 137, 2200, 126, 0, 1641, 103, 1622, 155, 1692, 1655, 1673, 1722, 1712, 2200, 104, 1618, 0, 91, 1685, 220, 1728, 656, 230, 1734, 2200, 1765, 1776, 1787, 1798, 1809, 1820, 1831, 1842, 1853, 1864, 1875, 1886, 1897, 1908, 1919, 1926, 1933, 1944, 1955, 1966, 1977, 1988, 1999, 2010, 2021, 2032, 2042, 2048, 2054, 2064, 2065, 2076, 92, 2081, 2092, 2102, 2112, 2118, 2124, 2129, 51, 2140, 2150, 2160, 2167, 2177, 2183, 2188 } ; static yyconst short int yy_def[533] = { 0, 485, 485, 486, 486, 487, 487, 488, 488, 489, 489, 490, 490, 484, 13, 491, 491, 492, 492, 493, 493, 492, 492, 494, 494, 495, 495, 496, 496, 497, 497, 498, 498, 499, 499, 492, 492, 492, 492, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 500, 484, 501, 484, 484, 484, 484, 484, 484, 484, 484, 484, 89, 89, 89, 484, 89, 89, 89, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 502, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 500, 484, 484, 501, 503, 89, 89, 89, 93, 89, 89, 89, 484, 93, 93, 93, 93, 93, 484, 89, 484, 484, 504, 484, 505, 484, 484, 484, 484, 484, 502, 502, 484, 506, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 507, 508, 484, 484, 484, 484, 484, 484, 165, 165, 165, 165, 509, 510, 484, 484, 484, 484, 484, 484, 503, 503, 89, 93, 93, 193, 93, 93, 193, 193, 484, 193, 193, 504, 484, 505, 484, 484, 484, 506, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 507, 508, 508, 484, 484, 484, 484, 484, 484, 484, 165, 509, 510, 510, 484, 484, 484, 484, 484, 484, 484, 89, 89, 484, 93, 93, 193, 484, 484, 193, 511, 484, 484, 484, 484, 484, 484, 484, 512, 484, 484, 484, 484, 484, 484, 508, 484, 484, 484, 484, 484, 484, 484, 484, 484, 510, 484, 484, 484, 484, 484, 484, 484, 484, 484, 193, 193, 193, 511, 513, 511, 513, 514, 484, 484, 484, 484, 515, 484, 484, 310, 310, 310, 310, 310, 484, 484, 516, 484, 484, 484, 484, 484, 484, 484, 484, 484, 340, 517, 340, 340, 484, 339, 340, 518, 484, 484, 484, 345, 345, 345, 345, 345, 515, 515, 515, 484, 310, 484, 484, 519, 516, 390, 484, 484, 484, 484, 520, 521, 518, 518, 518, 484, 484, 345, 484, 484, 484, 484, 484, 484, 484, 484, 484, 522, 484, 523, 520, 520, 523, 521, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 524, 484, 525, 418, 484, 417, 417, 484, 484, 423, 423, 423, 423, 423, 526, 484, 484, 524, 484, 484, 484, 484, 527, 528, 524, 439, 439, 439, 439, 439, 484, 423, 529, 526, 464, 530, 484, 531, 527, 527, 531, 528, 484, 439, 532, 471, 484, 470, 470, 532, 484, 484, 532, 0, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484 } ; static yyconst short int yy_nxt[2253] = { 0, 484, 41, 42, 43, 41, 484, 82, 83, 56, 82, 200, 99, 82, 83, 99, 82, 44, 84, 85, 45, 202, 86, 57, 84, 85, 46, 139, 86, 136, 47, 140, 201, 48, 136, 49, 58, 100, 50, 59, 100, 137, 202, 51, 60, 52, 137, 53, 54, 41, 42, 43, 41, 61, 62, 139, 87, 142, 453, 140, 101, 143, 87, 101, 44, 102, 103, 45, 102, 156, 104, 102, 103, 46, 102, 128, 104, 47, 157, 129, 48, 245, 49, 128, 132, 50, 164, 129, 133, 164, 51, 217, 52, 132, 53, 54, 56, 133, 142, 396, 130, 196, 143, 166, 196, 483, 267, 268, 130, 134, 57, 473, 167, 164, 105, 432, 164, 433, 134, 63, 105, 196, 465, 58, 196, 246, 59, 182, 185, 185, 182, 60, 185, 461, 277, 288, 64, 277, 288, 383, 61, 62, 66, 67, 474, 66, 182, 185, 185, 182, 473, 185, 384, 182, 185, 185, 182, 68, 185, 182, 185, 185, 182, 307, 185, 216, 307, 435, 216, 432, 69, 433, 217, 70, 182, 185, 185, 182, 71, 185, 218, 182, 185, 185, 182, 437, 185, 72, 73, 66, 67, 473, 66, 182, 185, 185, 182, 473, 185, 462, 182, 185, 185, 182, 68, 185, 461, 461, 194, 182, 185, 185, 182, 74, 185, 256, 341, 69, 256, 341, 70, 242, 243, 243, 242, 71, 257, 435, 337, 365, 75, 337, 365, 477, 72, 73, 76, 76, 76, 76, 76, 76, 77, 477, 76, 450, 76, 216, 76, 76, 216, 479, 461, 455, 217, 76, 76, 339, 194, 340, 366, 482, 76, 76, 76, 264, 264, 264, 264, 454, 244, 371, 365, 445, 371, 365, 274, 274, 274, 274, 285, 285, 285, 285, 265, 424, 76, 76, 76, 76, 76, 76, 76, 76, 77, 275, 76, 402, 76, 286, 76, 76, 214, 366, 410, 399, 383, 76, 76, 296, 296, 296, 296, 223, 76, 76, 76, 235, 400, 384, 290, 291, 291, 290, 407, 241, 242, 243, 243, 242, 391, 241, 242, 243, 243, 242, 383, 241, 76, 76, 76, 76, 76, 76, 76, 76, 79, 406, 76, 384, 76, 256, 76, 76, 256, 385, 301, 403, 297, 76, 76, 383, 257, 399, 402, 402, 76, 76, 76, 292, 305, 305, 305, 305, 384, 244, 400, 293, 294, 294, 293, 244, 241, 296, 296, 296, 296, 402, 249, 306, 76, 76, 76, 76, 76, 76, 76, 76, 79, 401, 76, 397, 76, 395, 76, 76, 264, 264, 264, 264, 261, 76, 76, 394, 274, 274, 274, 274, 76, 76, 76, 399, 393, 399, 277, 265, 295, 277, 392, 321, 388, 387, 297, 275, 400, 322, 400, 386, 385, 385, 385, 376, 76, 76, 88, 89, 90, 91, 89, 92, 93, 92, 94, 92, 92, 94, 92, 92, 92, 92, 92, 94, 92, 92, 92, 95, 95, 95, 95, 95, 92, 96, 92, 92, 92, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 97, 92, 107, 375, 364, 363, 108, 361, 316, 316, 316, 316, 109, 110, 282, 360, 111, 309, 309, 309, 309, 359, 310, 357, 271, 356, 112, 317, 113, 355, 318, 318, 318, 318, 365, 319, 265, 365, 285, 285, 285, 285, 114, 354, 334, 335, 335, 334, 273, 275, 115, 116, 107, 348, 343, 342, 108, 286, 326, 326, 326, 326, 109, 110, 333, 366, 111, 328, 328, 328, 328, 330, 329, 325, 324, 323, 112, 327, 113, 288, 320, 315, 288, 314, 331, 307, 286, 313, 307, 312, 332, 311, 114, 336, 290, 291, 291, 290, 284, 185, 115, 116, 118, 308, 304, 303, 119, 302, 305, 305, 305, 305, 120, 121, 347, 300, 122, 299, 290, 291, 291, 290, 298, 185, 435, 241, 123, 306, 124, 449, 293, 294, 294, 293, 240, 241, 293, 294, 294, 293, 289, 241, 450, 292, 287, 316, 316, 316, 316, 284, 125, 126, 118, 283, 337, 282, 119, 337, 326, 326, 326, 326, 120, 121, 317, 279, 122, 292, 344, 344, 344, 344, 227, 345, 227, 477, 123, 327, 124, 295, 481, 435, 432, 339, 433, 295, 449, 306, 227, 278, 276, 273, 272, 482, 271, 155, 266, 263, 262, 450, 125, 126, 180, 181, 181, 180, 182, 183, 182, 184, 182, 182, 184, 182, 182, 182, 182, 182, 184, 182, 182, 182, 185, 185, 185, 185, 185, 182, 186, 182, 182, 182, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 187, 182, 188, 189, 189, 188, 188, 190, 188, 191, 188, 188, 191, 188, 188, 188, 188, 188, 191, 188, 188, 188, 189, 189, 189, 189, 189, 188, 192, 188, 188, 188, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 193, 188, 227, 261, 260, 227, 227, 228, 227, 229, 227, 227, 229, 227, 227, 227, 227, 230, 229, 227, 227, 227, 228, 228, 228, 228, 228, 227, 227, 227, 227, 227, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 227, 227, 247, 248, 248, 247, 247, 249, 247, 250, 247, 247, 250, 247, 247, 247, 247, 247, 250, 247, 247, 247, 248, 248, 248, 248, 248, 247, 251, 247, 247, 247, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 247, 247, 309, 309, 309, 309, 259, 310, 206, 255, 253, 241, 241, 241, 240, 177, 176, 174, 238, 237, 236, 265, 349, 350, 350, 349, 349, 351, 349, 352, 349, 349, 352, 349, 349, 349, 349, 349, 352, 349, 349, 349, 350, 350, 350, 350, 350, 349, 353, 349, 349, 349, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 349, 349, 358, 358, 358, 358, 235, 319, 318, 318, 318, 318, 234, 319, 362, 362, 362, 362, 233, 329, 232, 317, 231, 328, 328, 328, 328, 275, 329, 334, 335, 335, 334, 327, 334, 335, 335, 334, 341, 226, 225, 341, 286, 365, 365, 365, 365, 344, 344, 344, 344, 224, 345, 223, 367, 358, 358, 358, 358, 222, 319, 221, 365, 365, 365, 365, 306, 374, 451, 451, 451, 451, 339, 367, 317, 220, 219, 215, 336, 404, 404, 404, 404, 336, 365, 365, 365, 365, 362, 362, 362, 362, 370, 329, 214, 367, 213, 212, 405, 211, 368, 408, 408, 408, 408, 210, 209, 327, 208, 413, 207, 370, 413, 369, 206, 414, 204, 452, 387, 203, 409, 199, 411, 411, 411, 411, 413, 198, 197, 413, 195, 179, 414, 370, 371, 365, 365, 371, 419, 177, 393, 412, 416, 413, 176, 367, 413, 174, 173, 414, 368, 404, 404, 404, 404, 417, 172, 422, 422, 422, 422, 395, 423, 369, 171, 372, 170, 169, 168, 165, 405, 163, 414, 162, 161, 160, 405, 159, 158, 155, 154, 153, 152, 370, 377, 378, 378, 377, 377, 379, 377, 380, 377, 377, 380, 377, 377, 377, 377, 377, 380, 377, 377, 377, 378, 378, 378, 378, 378, 377, 381, 377, 377, 377, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 378, 377, 377, 389, 389, 151, 389, 389, 389, 389, 150, 389, 149, 389, 148, 389, 389, 408, 408, 408, 408, 391, 389, 389, 420, 420, 420, 420, 147, 389, 389, 389, 425, 425, 425, 425, 409, 146, 428, 428, 428, 428, 145, 421, 144, 427, 427, 427, 427, 484, 319, 426, 484, 389, 389, 389, 389, 429, 389, 389, 389, 389, 484, 389, 409, 389, 484, 389, 389, 484, 484, 484, 401, 484, 389, 389, 411, 411, 411, 411, 407, 389, 389, 389, 484, 484, 410, 484, 430, 430, 430, 430, 484, 329, 413, 412, 484, 413, 484, 484, 414, 451, 451, 451, 451, 389, 389, 412, 413, 484, 416, 413, 367, 484, 414, 413, 484, 484, 413, 435, 432, 414, 433, 417, 436, 435, 484, 432, 484, 433, 436, 416, 484, 466, 484, 413, 466, 437, 413, 467, 484, 414, 484, 437, 417, 413, 484, 432, 413, 433, 452, 414, 420, 420, 420, 420, 435, 432, 484, 433, 484, 436, 472, 484, 419, 438, 438, 438, 438, 484, 439, 421, 484, 484, 437, 422, 422, 422, 422, 484, 423, 484, 484, 484, 421, 484, 484, 484, 484, 484, 484, 484, 484, 484, 405, 440, 441, 441, 440, 440, 442, 440, 443, 440, 440, 443, 440, 440, 440, 440, 440, 443, 440, 440, 440, 441, 441, 441, 441, 441, 440, 444, 440, 440, 440, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 440, 440, 425, 425, 425, 425, 446, 446, 446, 446, 484, 319, 427, 427, 427, 427, 484, 319, 484, 484, 484, 426, 484, 484, 484, 426, 428, 428, 428, 428, 484, 409, 447, 447, 447, 447, 484, 329, 430, 430, 430, 430, 484, 329, 484, 429, 484, 438, 438, 438, 438, 429, 439, 484, 484, 484, 484, 412, 484, 484, 484, 484, 484, 484, 484, 484, 421, 456, 457, 457, 456, 456, 458, 456, 459, 456, 456, 459, 456, 456, 456, 456, 456, 459, 456, 456, 456, 457, 457, 457, 457, 457, 456, 460, 456, 456, 456, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 457, 456, 456, 463, 463, 484, 463, 463, 463, 463, 484, 463, 484, 463, 484, 463, 463, 484, 484, 484, 484, 465, 463, 463, 484, 484, 484, 484, 484, 463, 463, 463, 446, 446, 446, 446, 484, 319, 447, 447, 447, 447, 484, 329, 435, 484, 484, 484, 484, 449, 484, 426, 466, 463, 463, 466, 484, 429, 467, 484, 435, 432, 450, 433, 466, 449, 484, 466, 469, 484, 467, 477, 432, 484, 433, 484, 481, 484, 450, 484, 484, 470, 463, 463, 484, 463, 463, 463, 463, 482, 463, 484, 463, 467, 463, 463, 484, 466, 484, 484, 466, 463, 463, 467, 484, 484, 484, 484, 463, 463, 463, 484, 484, 469, 484, 466, 484, 484, 466, 484, 484, 467, 484, 484, 484, 484, 470, 432, 484, 433, 484, 469, 463, 463, 466, 484, 484, 466, 477, 484, 467, 484, 484, 478, 470, 477, 432, 484, 433, 484, 478, 484, 484, 484, 466, 484, 479, 466, 484, 484, 467, 484, 484, 479, 466, 484, 432, 466, 433, 484, 467, 484, 484, 484, 484, 477, 432, 484, 433, 484, 478, 477, 484, 472, 484, 484, 481, 477, 432, 484, 433, 484, 481, 479, 484, 484, 484, 484, 484, 482, 484, 484, 484, 484, 484, 482, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 175, 175, 175, 484, 484, 175, 175, 178, 178, 178, 484, 484, 178, 178, 205, 205, 484, 205, 205, 205, 205, 205, 205, 205, 205, 239, 239, 484, 239, 239, 239, 239, 239, 239, 239, 239, 252, 252, 484, 252, 252, 252, 252, 252, 252, 252, 252, 254, 254, 484, 254, 254, 254, 254, 254, 254, 254, 254, 258, 258, 484, 258, 258, 258, 258, 258, 258, 258, 258, 269, 269, 484, 269, 269, 269, 269, 269, 269, 269, 269, 270, 270, 484, 270, 270, 270, 270, 270, 270, 270, 270, 280, 280, 484, 280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 484, 281, 281, 281, 281, 281, 281, 281, 281, 338, 484, 484, 484, 484, 338, 346, 484, 484, 484, 484, 346, 366, 366, 366, 484, 484, 366, 366, 484, 484, 366, 373, 484, 484, 484, 484, 373, 382, 484, 484, 484, 382, 390, 390, 484, 390, 390, 390, 390, 390, 390, 390, 390, 398, 484, 484, 484, 398, 389, 389, 484, 389, 389, 389, 389, 389, 389, 389, 389, 415, 484, 484, 484, 415, 415, 484, 484, 484, 415, 418, 484, 484, 484, 418, 418, 431, 484, 484, 484, 431, 431, 434, 484, 484, 484, 434, 434, 434, 434, 434, 434, 448, 448, 448, 448, 448, 464, 464, 484, 464, 464, 464, 464, 464, 464, 464, 464, 468, 484, 484, 484, 468, 468, 484, 484, 484, 468, 471, 484, 484, 484, 471, 471, 463, 463, 484, 463, 463, 463, 463, 463, 463, 463, 463, 475, 484, 484, 484, 475, 475, 476, 484, 484, 484, 476, 476, 476, 476, 476, 476, 480, 480, 480, 480, 480, 39, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484 } ; static yyconst short int yy_chk[2253] = { 0, 0, 1, 1, 1, 1, 0, 11, 11, 3, 11, 130, 15, 12, 12, 16, 12, 1, 11, 11, 1, 134, 11, 3, 12, 12, 1, 31, 12, 29, 1, 31, 130, 1, 30, 1, 3, 15, 1, 3, 16, 29, 134, 1, 3, 1, 30, 1, 1, 2, 2, 2, 2, 3, 3, 32, 11, 33, 525, 32, 15, 33, 12, 16, 2, 17, 17, 2, 17, 58, 17, 18, 18, 2, 18, 25, 18, 2, 58, 25, 2, 192, 2, 26, 27, 2, 66, 26, 27, 66, 2, 217, 2, 28, 2, 2, 4, 28, 34, 517, 25, 102, 34, 69, 102, 477, 217, 217, 26, 27, 4, 474, 69, 164, 17, 414, 164, 414, 28, 4, 18, 196, 465, 4, 196, 192, 4, 92, 92, 92, 92, 4, 92, 462, 225, 237, 4, 225, 237, 346, 4, 4, 5, 5, 460, 5, 94, 94, 94, 94, 459, 94, 346, 95, 95, 95, 95, 5, 95, 96, 96, 96, 96, 262, 96, 155, 262, 437, 155, 467, 5, 467, 155, 5, 182, 182, 182, 182, 5, 182, 155, 184, 184, 184, 184, 437, 184, 5, 5, 6, 6, 457, 6, 185, 185, 185, 185, 456, 185, 444, 194, 194, 194, 194, 6, 194, 443, 441, 96, 186, 186, 186, 186, 6, 186, 207, 300, 6, 207, 300, 6, 190, 190, 190, 190, 6, 207, 450, 299, 366, 6, 299, 366, 479, 6, 6, 7, 7, 7, 7, 7, 7, 7, 482, 7, 450, 7, 216, 7, 7, 216, 479, 440, 435, 216, 7, 7, 299, 186, 299, 366, 482, 7, 7, 7, 214, 214, 214, 214, 433, 190, 371, 368, 424, 371, 368, 223, 223, 223, 223, 235, 235, 235, 235, 214, 406, 7, 7, 8, 8, 8, 8, 8, 8, 8, 223, 8, 403, 8, 235, 8, 8, 214, 368, 394, 373, 382, 8, 8, 296, 296, 296, 296, 223, 8, 8, 8, 235, 373, 382, 241, 241, 241, 241, 392, 241, 242, 242, 242, 242, 391, 242, 243, 243, 243, 243, 383, 243, 8, 8, 9, 9, 9, 9, 9, 9, 9, 388, 9, 383, 9, 256, 9, 9, 256, 386, 256, 381, 296, 9, 9, 384, 256, 398, 380, 378, 9, 9, 9, 241, 261, 261, 261, 261, 384, 242, 398, 245, 245, 245, 245, 243, 245, 249, 249, 249, 249, 377, 249, 261, 9, 9, 10, 10, 10, 10, 10, 10, 10, 375, 10, 367, 10, 363, 10, 10, 264, 264, 264, 264, 261, 10, 10, 361, 274, 274, 274, 274, 10, 10, 10, 399, 359, 400, 277, 264, 245, 277, 357, 277, 355, 354, 249, 274, 399, 277, 400, 353, 352, 350, 349, 343, 10, 10, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 19, 342, 332, 330, 19, 325, 273, 273, 273, 273, 19, 19, 324, 322, 19, 265, 265, 265, 265, 320, 265, 315, 314, 313, 19, 273, 19, 312, 275, 275, 275, 275, 369, 275, 265, 369, 285, 285, 285, 285, 19, 311, 298, 298, 298, 298, 273, 275, 19, 19, 20, 308, 304, 303, 20, 285, 284, 284, 284, 284, 20, 20, 289, 369, 20, 286, 286, 286, 286, 287, 286, 283, 282, 278, 20, 284, 20, 288, 276, 272, 288, 271, 288, 307, 286, 268, 307, 267, 288, 266, 20, 298, 290, 290, 290, 290, 284, 290, 20, 20, 23, 263, 260, 259, 23, 257, 305, 305, 305, 305, 23, 23, 307, 255, 23, 253, 291, 291, 291, 291, 251, 291, 449, 246, 23, 305, 23, 449, 293, 293, 293, 293, 240, 293, 294, 294, 294, 294, 238, 294, 449, 290, 236, 316, 316, 316, 316, 234, 23, 23, 24, 233, 337, 232, 24, 337, 326, 326, 326, 326, 24, 24, 316, 230, 24, 291, 306, 306, 306, 306, 229, 306, 228, 481, 24, 326, 24, 293, 481, 431, 431, 337, 431, 294, 431, 306, 227, 226, 224, 222, 221, 481, 220, 218, 215, 213, 212, 431, 24, 24, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 165, 211, 210, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 309, 309, 309, 309, 209, 309, 206, 204, 198, 191, 189, 188, 179, 178, 177, 175, 173, 172, 171, 309, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 310, 317, 317, 317, 317, 170, 317, 318, 318, 318, 318, 169, 318, 327, 327, 327, 327, 168, 327, 167, 317, 166, 328, 328, 328, 328, 318, 328, 334, 334, 334, 334, 327, 335, 335, 335, 335, 341, 163, 162, 341, 328, 339, 339, 339, 339, 344, 344, 344, 344, 161, 344, 160, 339, 358, 358, 358, 358, 159, 358, 158, 365, 365, 365, 365, 344, 341, 451, 451, 451, 451, 339, 365, 358, 157, 156, 154, 334, 387, 387, 387, 387, 335, 338, 338, 338, 338, 362, 362, 362, 362, 339, 362, 153, 338, 152, 151, 387, 150, 338, 393, 393, 393, 393, 149, 148, 362, 147, 397, 146, 365, 397, 338, 145, 397, 144, 451, 387, 137, 393, 122, 395, 395, 395, 395, 396, 114, 111, 396, 100, 86, 396, 338, 340, 340, 340, 340, 397, 80, 393, 395, 396, 413, 79, 340, 413, 78, 75, 413, 340, 404, 404, 404, 404, 396, 74, 405, 405, 405, 405, 395, 405, 340, 73, 340, 72, 71, 70, 68, 404, 64, 413, 63, 62, 61, 405, 60, 59, 57, 54, 53, 52, 340, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 345, 356, 356, 51, 356, 356, 356, 356, 50, 356, 49, 356, 48, 356, 356, 408, 408, 408, 408, 356, 356, 356, 401, 401, 401, 401, 47, 356, 356, 356, 407, 407, 407, 407, 408, 46, 410, 410, 410, 410, 44, 401, 41, 409, 409, 409, 409, 39, 409, 407, 0, 356, 356, 390, 390, 410, 390, 390, 390, 390, 0, 390, 409, 390, 0, 390, 390, 0, 0, 0, 401, 0, 390, 390, 411, 411, 411, 411, 407, 390, 390, 390, 0, 0, 410, 0, 412, 412, 412, 412, 0, 412, 416, 411, 0, 416, 0, 0, 416, 432, 432, 432, 432, 390, 390, 412, 415, 0, 416, 415, 432, 0, 415, 417, 0, 0, 417, 415, 415, 417, 415, 416, 415, 436, 436, 417, 436, 417, 436, 417, 0, 454, 0, 419, 454, 415, 419, 454, 0, 419, 0, 436, 417, 418, 0, 419, 418, 419, 432, 418, 420, 420, 420, 420, 418, 418, 0, 418, 0, 418, 454, 0, 419, 421, 421, 421, 421, 0, 421, 420, 0, 0, 418, 422, 422, 422, 422, 0, 422, 0, 0, 0, 421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 422, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 425, 425, 425, 425, 426, 426, 426, 426, 0, 426, 427, 427, 427, 427, 0, 427, 0, 0, 0, 425, 0, 0, 0, 426, 428, 428, 428, 428, 0, 427, 429, 429, 429, 429, 0, 429, 430, 430, 430, 430, 0, 430, 0, 428, 0, 438, 438, 438, 438, 429, 438, 0, 0, 0, 0, 430, 0, 0, 0, 0, 0, 0, 0, 0, 438, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 445, 445, 0, 445, 445, 445, 445, 0, 445, 0, 445, 0, 445, 445, 0, 0, 0, 0, 445, 445, 445, 0, 0, 0, 0, 0, 445, 445, 445, 446, 446, 446, 446, 0, 446, 447, 447, 447, 447, 0, 447, 448, 448, 0, 448, 0, 448, 0, 446, 453, 445, 445, 453, 0, 447, 453, 0, 455, 455, 448, 455, 466, 455, 0, 466, 453, 0, 466, 475, 475, 0, 475, 0, 475, 0, 455, 0, 0, 453, 464, 464, 0, 464, 464, 464, 464, 475, 464, 0, 464, 466, 464, 464, 0, 469, 0, 0, 469, 464, 464, 469, 0, 0, 0, 0, 464, 464, 464, 0, 0, 469, 0, 470, 0, 0, 470, 0, 0, 470, 0, 0, 0, 0, 469, 470, 0, 470, 0, 470, 464, 464, 468, 0, 0, 468, 478, 478, 468, 478, 0, 478, 470, 468, 468, 0, 468, 0, 468, 0, 0, 0, 472, 0, 478, 472, 0, 0, 472, 0, 0, 468, 471, 0, 472, 471, 472, 0, 471, 0, 0, 0, 0, 471, 471, 0, 471, 0, 471, 480, 480, 472, 480, 0, 480, 483, 483, 0, 483, 0, 483, 471, 0, 0, 0, 0, 0, 480, 0, 0, 0, 0, 0, 483, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 486, 487, 487, 487, 487, 487, 487, 487, 487, 487, 487, 487, 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 490, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 491, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 492, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 494, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 498, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, 500, 500, 500, 0, 0, 500, 500, 501, 501, 501, 0, 0, 501, 501, 502, 502, 0, 502, 502, 502, 502, 502, 502, 502, 502, 503, 503, 0, 503, 503, 503, 503, 503, 503, 503, 503, 504, 504, 0, 504, 504, 504, 504, 504, 504, 504, 504, 505, 505, 0, 505, 505, 505, 505, 505, 505, 505, 505, 506, 506, 0, 506, 506, 506, 506, 506, 506, 506, 506, 507, 507, 0, 507, 507, 507, 507, 507, 507, 507, 507, 508, 508, 0, 508, 508, 508, 508, 508, 508, 508, 508, 509, 509, 0, 509, 509, 509, 509, 509, 509, 509, 509, 510, 510, 0, 510, 510, 510, 510, 510, 510, 510, 510, 511, 0, 0, 0, 0, 511, 512, 0, 0, 0, 0, 512, 513, 513, 513, 0, 0, 513, 513, 0, 0, 513, 514, 0, 0, 0, 0, 514, 515, 0, 0, 0, 515, 516, 516, 0, 516, 516, 516, 516, 516, 516, 516, 516, 518, 0, 0, 0, 518, 519, 519, 0, 519, 519, 519, 519, 519, 519, 519, 519, 520, 0, 0, 0, 520, 520, 0, 0, 0, 520, 521, 0, 0, 0, 521, 521, 522, 0, 0, 0, 522, 522, 523, 0, 0, 0, 523, 523, 523, 523, 523, 523, 524, 524, 524, 524, 524, 526, 526, 0, 526, 526, 526, 526, 526, 526, 526, 526, 527, 0, 0, 0, 527, 527, 0, 0, 0, 527, 528, 0, 0, 0, 528, 528, 529, 529, 0, 529, 529, 529, 529, 529, 529, 529, 529, 530, 0, 0, 0, 530, 530, 531, 0, 0, 0, 531, 531, 531, 531, 531, 531, 532, 532, 532, 532, 532, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, 484 } ; 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 static int yy_more_flag = 0; static int yy_more_len = 0; #define yymore() (yy_more_flag = 1) #define YY_MORE_ADJ yy_more_len #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "libparse.l" #define INITIAL 0 #line 2 "libparse.l" /**************************************** * Computer Algebra System SINGULAR * ****************************************/ #include #include #include #include #include #ifdef STANDALONE_PARSER #include #define HAVE_LIBPARSER #define YYLPDEBUG 1 #define myfread fread #else #include #include #include #include #include #include #include #endif #include #ifdef HAVE_LIBPARSER #define YY_SKIP_YYWRAP typedef enum { LP_NONE, LP_INFO, LP_CATEGORY, LP_URL, LP_VERSION} lib_cmds; int libread(FILE* f, char* buf, int max_size); int current_pos(int i); void print_version(lp_modes mode, char *p); void copy_string(lp_modes mode); void make_version(char *p, int what); int brace1 = 0; /* { } */ int brace2 = 0; /* ( ) */ int brace3 = 0; /* [ ] */ int quote = 0; /* " */ int offset = 0; BOOLEAN p_static = FALSE; int old_state = 0; lib_cmds last_cmd = LP_NONE; char libnamebuf[128]; char *text_buffer=NULL; long string_start; char *yylp_buffer_start; #ifndef NEW_FLEX int yylplineno = 1; #endif /* NEW_FLEX */ int lpverbose = 0, check = 0; int texinfo_out = 0; int found_info=0, found_cat=0, found_version=0, found_oldhelp = 0, found_proc_in_proc = 0; const char *yylp_errlist[]= { "", "missing close bracket ')' for proc definition in line %d.", /* 1 */ "missing close bracket ')' for procbody in line %d.", /* 2 */ "missing close bracket ']' for procbody in line %d.", /* 3 */ "too many ')' closed brackets in line %d.", /* 4 */ "too many ']' closed brackets in line %d.", /* 5 */ "missing close bracket ')' for example in line %d.", /* 6 */ "missing close bracket ']' for example in line %d.", /* 7 */ "cannot assign character '%c' in line %d to any group.", /* 8 */ "there must be a quote missing somewhere before line %d.", /* 9 */ "missing close bracket '}' at end of library in line %d.", /* 10 */ "missing close bracket ')' at end of library in line %d.", /* 11 */ "missing close bracket ']' at end of library in line %d.", /* 12 */ NULL }; int yylp_errno = 0; #ifdef STANDALONE_PARSER procinfov pi; int category_out = 0; void printpi(procinfov pi); void pi_clear(procinfov pi); extern "C" { int yylpwrap(); } void main_init(int argc, char *argv[]); void main_result(char *libname); #else /* STANDALONE_PARSER */ idhdl h0; idhdl h_top; #define pi IDPROC(h0) extern "C" { int yylpwrap(); } extern libstackv library_stack; #endif /* STANDALONE_PARSER */ static unsigned long help_chksum; #define SET_DEF_END(mode, pi, p) \ if ( mode == LOAD_LIB) pi->data.s.def_end = p; #define SET_HELP_START(mode, pi, p) \ if ( mode == LOAD_LIB) {pi->data.s.help_start = p; help_chksum = 0;} #define SET_HELP_END(mode, pi, p) \ if ( mode == LOAD_LIB) {pi->data.s.help_end = p; \ pi->data.s.help_chksum = help_chksum;} #define SET_BODY_START(mode, pi, l, p) \ if ( mode == LOAD_LIB) \ { \ pi->data.s.body_lineno = l; \ pi->data.s.body_start = p; \ } #define SET_BODY_END(mode, pi, p) \ if ( mode == LOAD_LIB) \ { \ pi->data.s.body_end = p-1; \ pi->data.s.proc_end = p-1; \ } #define SET_EXAMPLE_START(mode, pi, l, p) \ if ( mode == LOAD_LIB) \ { \ pi->data.s.example_lineno = l; \ pi->data.s.example_start = p; \ } #define SET_PROC_END(mode, pi, p) \ if ( mode == LOAD_LIB) \ { \ pi->data.s.proc_end = p-1; \ if(pi->data.s.body_end==0) \ pi->data.s.body_end = p-1; \ } #define ROTATE_RIGHT(c) if ((c) & 01) (c) = ((c) >>1) + 0x8000; else (c) >>= 1; #define IncrCheckSum(c) \ do \ { \ ROTATE_RIGHT(help_chksum); \ help_chksum += c; \ help_chksum &= 0xffff; \ } \ while(0) #undef YY_DECL #define YY_DECL int yylex(const char *newlib, const char *libfile, \ lib_style_types *lib_style, \ idhdl pl, BOOLEAN autoexport, lp_modes mode) #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( ((result = libread( (yyin), (char *) buf, max_size )) < 0 ) \ && ferror( yyin ) ) \ YY_FATAL_ERROR( "read in flex scanner failed" ); #define YY_USER_INIT { \ BEGIN(header); \ yylplineno = 1; \ yylp_errno = 0; \ *lib_style = OLD_LIBSTYLE; \ strcpy(libnamebuf,"(**unknown version**)"); \ } #if 0 proc[ \t]+{name} { printf("MISSING: PROC-cmd found. ERROR!\n"); } example[ \t]*\n { yylplineno++; printf("MISSING: EXAMPLE-cmd found. ERROR!\n"); } info=+"\"" { #endif /* %start START */ #define header 1 #define help 2 #define libcmd 3 #define libcmd2 4 #define pdef 5 #define phead 6 #define poldhelp 7 #define phelp 8 #define pbody 9 #define pstr 10 #define pexample 11 #define pestr 12 #define string 13 #define comment 14 #define info 15 #define category 16 #define url 17 #define version 18 /* 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 \ if ( yyleng > 0 ) \ yy_current_buffer->yy_at_bol = \ (yytext[yyleng - 1] == '\n'); \ YY_USER_ACTION YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 229 "libparse.l" 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_more_len = 0; if ( yy_more_flag ) { yy_more_len = yy_c_buf_p - yytext_ptr; yy_more_flag = 0; } 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_current_state += YY_AT_BOL(); 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 >= 485 ) 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] != 2200 ); 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 230 "libparse.l" { } YY_BREAK case 2: YY_RULE_SETUP #line 231 "libparse.l" { old_state = YYSTATE; BEGIN(comment); } YY_BREAK case 3: YY_RULE_SETUP #line 233 "libparse.l" { yyless(4); old_state = YYSTATE; BEGIN(info); } YY_BREAK case 4: YY_RULE_SETUP #line 236 "libparse.l" { yyless(8); old_state = YYSTATE; BEGIN(category); } YY_BREAK case 5: YY_RULE_SETUP #line 239 "libparse.l" { if ( mode != GET_INFO ) { #ifdef STANDALONE_PARSER if (texinfo_out) { char *c = yytext; printf("$url = \""); while ((*c != '\0') && (*c != '"')) c++; c++; while ((*c != '\0') && (*c != '"')) { if (*c != '\r') putchar(*c); c++; } printf("\";\n"); } #endif } } YY_BREAK case 6: YY_RULE_SETUP #line 260 "libparse.l" { found_version++; if ( mode != GET_INFO ) { make_version(yytext,1); #ifdef STANDALONE_PARSER if (texinfo_out) { char *c = libnamebuf; printf("$version = \""); while (*c != '\0') { if (*c == '$' || *c == '@') putchar('\\'); if (*c != '\r') putchar(*c); if (*c == '\\') { c++; if (*c != '"') putchar('\\'); } else c++; } printf("\";\n"); } else if (!category_out) printf("Version:%s;\n", libnamebuf); #else if (text_buffer!=NULL) omFree((ADDRESS)text_buffer); text_buffer = omStrDup(libnamebuf); omMarkAsStaticAddr(text_buffer); #endif } } YY_BREAK case 7: YY_RULE_SETUP #line 294 "libparse.l" { p_static=TRUE; } YY_BREAK case 8: YY_RULE_SETUP #line 296 "libparse.l" { char proc[256]; BEGIN(pdef); found_proc_in_proc = 0; proc[0]='\0'; sscanf( yytext, "%*[^p]proc %s", proc); if(strlen(proc)<1) sscanf( yytext, "proc %s", proc); #if YYLPDEBUG > 1 printf("Newlib:%s\n", newlib); #endif #ifdef STANDALONE_PARSER if ( pi != NULL ) { printpi(pi); pi_clear(pi); } pi = (procinfo *)malloc(sizeof(procinfo)); iiInitSingularProcinfo(pi, newlib, proc, yylplineno, current_pos(0), p_static); #else /*STANDALONE_PARSER*/ if( mode == LOAD_LIB) { h0 = enterid( proc, 0 /*myynest*/, PROC_CMD, &(IDPACKAGE(pl)->idroot), TRUE, !p_static); if (h0==NULL) return(1); if((!p_static) && autoexport) { package save=currPack; currPack=basePack; h_top = enterid( proc, 0 /*myynest*/, PROC_CMD, &(basePack->idroot), FALSE ); currPack=save; if (h_top==NULL) return(1); } /* omCheckAddr(IDID(h0)); */ if (h0!=NULL) { iiInitSingularProcinfo(IDPROC(h0), newlib, proc, yylplineno, current_pos(0),p_static); if ((!p_static) && (h_top != NULL) && autoexport) { if(IDPROC(h_top)!=NULL) piKill((procinfo *)IDPROC(h_top)); IDPROC(h_top)=IDPROC(h0); IDPROC(h_top)->ref++; } IDPROC(h0)->pack=IDPACKAGE(pl); if (BVERBOSE(V_LOAD_PROC)) Warn( " proc '%s' registered", proc ); } #endif /*STANDALONE_PARSER*/ SET_DEF_END(mode, pi, current_pos(yyleng+1)); #if YYLPDEBUG if(lpverbose) { printf("// PROCEDURE '%s' status: %s, ", proc, p_static ? "local" : "global"); printf("starting at line %d,%d: definition end: %d (%d).\n", yylplineno, current_pos(0), (int)pi->data.s.def_end, brace1); } #endif p_static=FALSE; #ifndef STANDALONE_PARSER } #endif /*STANDALONE_PARSER*/ } YY_BREAK case 9: YY_RULE_SETUP #line 361 "libparse.l" { BEGIN(pexample); SET_EXAMPLE_START(mode, pi, yylplineno, current_pos(0)); #if YYLPDEBUG if(lpverbose) { printf("// EXAMPLE at line %d,%d (%d)\n", yylplineno, current_pos(0), brace1); } #endif } YY_BREAK case 10: YY_RULE_SETUP #line 373 "libparse.l" { quote++; BEGIN(libcmd); } YY_BREAK case 11: YY_RULE_SETUP #line 377 "libparse.l" { quote++; brace2++; BEGIN(libcmd2); } YY_BREAK case 12: YY_RULE_SETUP #line 381 "libparse.l" { make_version(yytext, 0); #if YYLPDEBUG > 1 printf("+(id)HEAD:%s\n", yytext); #endif } YY_BREAK case 13: YY_RULE_SETUP #line 387 "libparse.l" { #if YYLPDEBUG printf("+(cmt)HEAD:%s\n", yytext); #endif } YY_BREAK case 14: YY_RULE_SETUP #line 392 "libparse.l" { #if YYLPDEBUG > 1 printf("-HEAD:%s\n", yytext); #endif } YY_BREAK case 15: YY_RULE_SETUP #line 397 "libparse.l" { yyless(0); BEGIN(INITIAL); yymore(); } YY_BREAK case 16: YY_RULE_SETUP #line 401 "libparse.l" { yyless(0); *lib_style = NEW_LIBSTYLE; BEGIN(INITIAL); yymore(); } YY_BREAK case 17: YY_RULE_SETUP #line 408 "libparse.l" { quote++; BEGIN(libcmd); } YY_BREAK case 18: YY_RULE_SETUP #line 411 "libparse.l" { quote++; brace2++; BEGIN(libcmd2); } YY_BREAK case 19: YY_RULE_SETUP #line 414 "libparse.l" { yylplineno++; } YY_BREAK case 20: YY_RULE_SETUP #line 415 "libparse.l" { #if YYLPDEBUG > 1 printf(" HEAD:%s\n", yytext); #endif yyless(0); BEGIN(help); } YY_BREAK case 21: YY_RULE_SETUP #line 422 "libparse.l" { #if YYLPDEBUG > 1 printf(" HELP:%s\n", yytext); #endif BEGIN(INITIAL); } YY_BREAK case 22: YY_RULE_SETUP #line 427 "libparse.l" { #if YYLPDEBUG > 1 printf(" HELP:%s\n", yytext); #endif BEGIN(INITIAL); } YY_BREAK case 23: YY_RULE_SETUP #line 433 "libparse.l" { yyless(0); *lib_style = NEW_LIBSTYLE; BEGIN(INITIAL); yymore(); } YY_BREAK case 24: YY_RULE_SETUP #line 439 "libparse.l" { yyless(0); //printf("2) proc found.\n"); BEGIN(INITIAL); yymore(); } YY_BREAK case 25: YY_RULE_SETUP #line 445 "libparse.l" { quote++; BEGIN(libcmd); } YY_BREAK case 26: YY_RULE_SETUP #line 448 "libparse.l" { quote++; brace2++; BEGIN(libcmd2); } YY_BREAK case 27: YY_RULE_SETUP #line 452 "libparse.l" { yylplineno++; } YY_BREAK case 28: YY_RULE_SETUP #line 453 "libparse.l" { #if YYLPDEBUG if(lpverbose>2) printf("--->%s<---\n", yytext); #endif } YY_BREAK case 29: YY_RULE_SETUP #line 458 "libparse.l" { found_oldhelp=1; #if YYLPDEBUG > 1 printf("-HELP:%s\n", yytext); #endif } YY_BREAK case 30: YY_RULE_SETUP #line 466 "libparse.l" { quote--; yytext[yyleng-1] = '\0'; #ifndef STANDALONE_PARSER if ( mode == LOAD_LIB ) { library_stack->push(newlib, yytext); } #endif /* STANDALONE_PARSER */ #if YYLPDEBUG if(lpverbose>1) printf("LIB:'%s'\n", yytext); #endif BEGIN(INITIAL); } YY_BREAK case 31: YY_RULE_SETUP #line 479 "libparse.l" { quote--; brace2--; yytext[yyleng-1] = '\0'; #ifndef STANDALONE_PARSER if ( mode == LOAD_LIB ) { library_stack->push(newlib, yytext); } #endif /* STANDALONE_PARSER */ #if YYLPDEBUG if(lpverbose>1) printf("LIB:'%s'\n", yytext); #endif BEGIN(INITIAL); } YY_BREAK case 32: YY_RULE_SETUP #line 493 "libparse.l" { } YY_BREAK case 33: YY_RULE_SETUP #line 494 "libparse.l" { brace2++; #if YYLPDEBUG > 1 printf("%s", yytext); #endif } YY_BREAK case 34: YY_RULE_SETUP #line 500 "libparse.l" { brace2--; #if YYLPDEBUG > 1 printf(">%s<\n", yytext); printf("{=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif if(brace2<=0) { #if YYLPDEBUG > 1 printf("BEGIN(phead){=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif SET_DEF_END(mode, pi, current_pos(yyleng)); BEGIN(phead); } } YY_BREAK case 35: YY_RULE_SETUP #line 515 "libparse.l" { if(brace2>0) { #if YYLPDEBUG > 1 printf("{=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif yylp_errno = YYLP_DEF_BR2; return(1); } else { brace1++; BEGIN(pbody); if(lpverbose) printf("// BODY at line %d,%d (%d)\n", yylplineno, current_pos(0), brace1); SET_BODY_START(mode, pi, yylplineno, current_pos(0)); } } YY_BREAK case 36: YY_RULE_SETUP #line 533 "libparse.l" { yylplineno++; if(brace2<=0) { #if YYLPDEBUG > 1 printf("BEGIN(phead-2){=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif BEGIN(phead); } } YY_BREAK case 37: YY_RULE_SETUP #line 542 "libparse.l" { } YY_BREAK case 38: YY_RULE_SETUP #line 543 "libparse.l" { old_state = YYSTATE; BEGIN(comment); } YY_BREAK case 39: YY_RULE_SETUP #line 544 "libparse.l" { if(brace2<=0) { BEGIN(phead); yyless(0); } } YY_BREAK case 40: YY_RULE_SETUP #line 552 "libparse.l" { #if YYLPDEBUG if(lpverbose>2)printf("0-Len=%d;\n", yyleng); #endif if(check) { printf("Procedure %s (line %d) has OLD-STYLE-HELP!\n", pi->procname, pi->data.s.proc_lineno); } SET_HELP_START(mode, pi, current_pos(0)); BEGIN(poldhelp); yyless(0); } YY_BREAK case 41: YY_RULE_SETUP #line 565 "libparse.l" { #if YYLPDEBUG if(lpverbose>2)printf("1-Len=%d;\n", yyleng); #endif BEGIN(phelp); yyless(0); } YY_BREAK case 42: YY_RULE_SETUP #line 572 "libparse.l" { if(check && yyleng>2) { printf("Procedure %s (line %d) has OLD-STYLE-HELP!\n", pi->procname, pi->data.s.proc_lineno); } #if YYLPDEBUG if(lpverbose>2 && yyleng>2) printf("2-Len=%d, %s;\n", yyleng, pi->procname); #endif SET_HELP_START(mode, pi, current_pos(0)); BEGIN(poldhelp); yyless(0); } YY_BREAK case 43: YY_RULE_SETUP #line 586 "libparse.l" { printf("[%s]", yytext); } YY_BREAK case 44: YY_RULE_SETUP #line 588 "libparse.l" { } YY_BREAK case 45: YY_RULE_SETUP #line 589 "libparse.l" { SET_HELP_END(mode, pi, current_pos(0)); brace1++; BEGIN(pbody); if(lpverbose) { printf("// HELP from %d to %d\n", (int)pi->data.s.help_start, (int)pi->data.s.help_end); printf("// BODY at line %d,%d (%d)\n", yylplineno, current_pos(0), brace1); } #if YYLPDEBUG > 1 printf("BEGIN(pbody){=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif SET_BODY_START(mode, pi, yylplineno, current_pos(0)); #if YYLPDEBUG > 1 printf("BODY at %d/%d", yylplineno, current_pos(0)); #endif } YY_BREAK case 46: YY_RULE_SETUP #line 607 "libparse.l" { yylplineno++; } YY_BREAK case 47: YY_RULE_SETUP #line 608 "libparse.l" { } YY_BREAK case 48: YY_RULE_SETUP #line 610 "libparse.l" { old_state = YYSTATE; BEGIN(string); SET_HELP_START(mode, pi, current_pos(1)); } YY_BREAK case 49: YY_RULE_SETUP #line 615 "libparse.l" {} YY_BREAK case 50: YY_RULE_SETUP #line 616 "libparse.l" { brace1++; BEGIN(pbody); if(lpverbose) { printf("// HELP from %d to %d\n", (int)pi->data.s.help_start, (int)pi->data.s.help_end); printf("// BODY at line %d,%d (%d)\n", yylplineno, current_pos(0), brace1); } #if YYLPDEBUG > 1 printf("BEGIN(pbody){=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif SET_BODY_START(mode, pi, yylplineno, current_pos(0)); #if YYLPDEBUG > 1 printf("BODY at %d/%d", yylplineno, current_pos(0)); #endif } YY_BREAK case 51: YY_RULE_SETUP #line 633 "libparse.l" { yylplineno++;} YY_BREAK case 52: YY_RULE_SETUP #line 635 "libparse.l" { } YY_BREAK case 53: YY_RULE_SETUP #line 636 "libparse.l" { quote++; old_state = YYSTATE; BEGIN(string); /* printf("%s", yytext); */ } YY_BREAK case 54: YY_RULE_SETUP #line 640 "libparse.l" { if(check) printf("*** found 2 proc whithin procedure '%s'.\n", pi->procname); yyless(yyleng-1); } YY_BREAK case 55: YY_RULE_SETUP #line 645 "libparse.l" { if(check) printf("*** found 1 proc whithin procedure '%s'.\n", pi->procname); yyless(yyleng-1); } YY_BREAK case 56: YY_RULE_SETUP #line 650 "libparse.l" { brace1++; #if YYLPDEBUG > 1 printf("line: %d, (%d)%s\n", yylplineno, brace1, yytext); #endif } YY_BREAK case 57: YY_RULE_SETUP #line 656 "libparse.l" { #if YYLPDEBUG > 1 printf("line: %d, (%d)%s\n", yylplineno, brace1, yytext); #endif brace1--; if(brace2>0) { yylp_errno = YYLP_BODY_BR2; return(1); } if(brace3>0) { yylp_errno = YYLP_BODY_BR3; return(1); } if(brace1<=0) { SET_BODY_END(mode, pi, current_pos(yyleng)); SET_PROC_END(mode, pi, current_pos(yyleng)); #if YYLPDEBUG > 1 printf("-%d\n", current_pos(0)); #endif BEGIN(INITIAL); } } YY_BREAK case 58: YY_RULE_SETUP #line 682 "libparse.l" { brace2++; /* printf("%s", yytext); */ } YY_BREAK case 59: YY_RULE_SETUP #line 685 "libparse.l" { brace2--; /* printf("%s", yytext); */ if(brace2<0) { yylp_errno = YYLP_BODY_TMBR2; return(1); } } YY_BREAK case 60: YY_RULE_SETUP #line 692 "libparse.l" { brace3++; /* printf("%s", yytext); */ } YY_BREAK case 61: YY_RULE_SETUP #line 695 "libparse.l" { brace3--; /* printf("%s", yytext); */ if(brace3<0) { yylp_errno = YYLP_BODY_TMBR3; return(1); } } YY_BREAK case 62: YY_RULE_SETUP #line 702 "libparse.l" { yylplineno++; } YY_BREAK case 63: YY_RULE_SETUP #line 703 "libparse.l" { } YY_BREAK case 64: YY_RULE_SETUP #line 705 "libparse.l" { quote++; BEGIN(string); found_info++; string_start = current_pos(yyleng); *lib_style = NEW_LIBSTYLE; last_cmd = LP_INFO; } YY_BREAK case 65: YY_RULE_SETUP #line 712 "libparse.l" { yylplineno++; } YY_BREAK case 66: YY_RULE_SETUP #line 713 "libparse.l" { } YY_BREAK case 67: YY_RULE_SETUP #line 715 "libparse.l" { quote++; BEGIN(string); found_cat++; string_start = current_pos(yyleng); *lib_style = NEW_LIBSTYLE; last_cmd = LP_CATEGORY; } YY_BREAK case 68: YY_RULE_SETUP #line 722 "libparse.l" { yylplineno++; } YY_BREAK case 69: YY_RULE_SETUP #line 723 "libparse.l" { } YY_BREAK case 70: YY_RULE_SETUP #line 726 "libparse.l" { quote--; copy_string(mode); last_cmd = LP_NONE; if(old_state==phelp) { SET_HELP_END(mode, pi, current_pos(0)); } BEGIN(old_state); /* printf("%s", yytext); */ } YY_BREAK case 71: YY_RULE_SETUP #line 735 "libparse.l" { if (old_state == phelp) IncrCheckSum(*yytext);} YY_BREAK case 72: YY_RULE_SETUP #line 736 "libparse.l" { yylplineno++; if (old_state == phelp) IncrCheckSum('\n');} YY_BREAK case 73: YY_RULE_SETUP #line 737 "libparse.l" { if (old_state == phelp) IncrCheckSum(*yytext);} YY_BREAK case 74: YY_RULE_SETUP #line 739 "libparse.l" { } YY_BREAK case 75: YY_RULE_SETUP #line 740 "libparse.l" { quote++; old_state = YYSTATE; BEGIN(string); /* printf("%s", yytext); */ } YY_BREAK case 76: YY_RULE_SETUP #line 743 "libparse.l" { brace1++; /* printf("(%d)%s", brace1, yytext); */ } YY_BREAK case 77: YY_RULE_SETUP #line 746 "libparse.l" { brace1--; /* printf("(%d)%s", brace1, yytext); */ if(brace1<=0) { if(brace2>0) { yylp_errno=YYLP_EX_BR2; return(1); } if(brace3>0) { yylp_errno=YYLP_EX_BR3; return(1); } BEGIN(INITIAL); SET_PROC_END(mode, pi, current_pos(yyleng)); } } YY_BREAK case 78: YY_RULE_SETUP #line 755 "libparse.l" { brace2++; /* printf("%s", yytext); */ } YY_BREAK case 79: YY_RULE_SETUP #line 758 "libparse.l" { brace2--; /* printf("%s", yytext); */ } YY_BREAK case 80: YY_RULE_SETUP #line 761 "libparse.l" { brace3++; /* printf("%s", yytext); */ } YY_BREAK case 81: YY_RULE_SETUP #line 764 "libparse.l" { brace3--; /* printf("%s", yytext); */ } YY_BREAK case 82: YY_RULE_SETUP #line 767 "libparse.l" { yylplineno++; } YY_BREAK case 83: YY_RULE_SETUP #line 768 "libparse.l" { } YY_BREAK case 84: YY_RULE_SETUP #line 770 "libparse.l" { quote--; BEGIN(pexample); /* printf("%s", yytext); */ } YY_BREAK case 85: YY_RULE_SETUP #line 773 "libparse.l" { } YY_BREAK case 86: YY_RULE_SETUP #line 774 "libparse.l" { } YY_BREAK case 87: YY_RULE_SETUP #line 775 "libparse.l" { yylplineno++; } YY_BREAK case 88: YY_RULE_SETUP #line 776 "libparse.l" { } YY_BREAK case 89: YY_RULE_SETUP #line 778 "libparse.l" { BEGIN(old_state); } YY_BREAK case 90: YY_RULE_SETUP #line 779 "libparse.l" { yylplineno++; } YY_BREAK case 91: YY_RULE_SETUP #line 780 "libparse.l" { } YY_BREAK case 92: YY_RULE_SETUP #line 782 "libparse.l" { yylplineno++; } YY_BREAK case 93: YY_RULE_SETUP #line 783 "libparse.l" { } YY_BREAK case 94: YY_RULE_SETUP #line 784 "libparse.l" { p_static = FALSE; #if YYLPDEBUG > 1 printf("%s", yytext); #endif } YY_BREAK case 95: YY_RULE_SETUP #line 789 "libparse.l" { p_static = FALSE; yylp_errno = YYLP_BAD_CHAR; #ifdef STANDALONE_PARSER printf("[%d]", *yytext); #else if (text_buffer!=NULL) omFree((ADDRESS)text_buffer); text_buffer = omStrDup(yytext); omMarkAsStaticAddr(text_buffer); #endif #if YYLPDEBUG > 1 printf("[%s]", yytext); #endif return(1); } YY_BREAK case 96: YY_RULE_SETUP #line 804 "libparse.l" ECHO; YY_BREAK case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(header): case YY_STATE_EOF(help): case YY_STATE_EOF(libcmd): case YY_STATE_EOF(libcmd2): case YY_STATE_EOF(pdef): case YY_STATE_EOF(phead): case YY_STATE_EOF(poldhelp): case YY_STATE_EOF(phelp): case YY_STATE_EOF(pbody): case YY_STATE_EOF(pstr): case YY_STATE_EOF(pexample): case YY_STATE_EOF(pestr): case YY_STATE_EOF(string): case YY_STATE_EOF(comment): case YY_STATE_EOF(info): case YY_STATE_EOF(category): case YY_STATE_EOF(url): case YY_STATE_EOF(version): yyterminate(); 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; yy_current_state += YY_AT_BOL(); 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 >= 485 ) 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 >= 485 ) 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 == 484); 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 */ #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; yy_current_buffer->yy_at_bol = (c == '\n'); return c; } #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 ); } #ifndef YY_ALWAYS_INTERACTIVE #ifndef YY_NEVER_INTERACTIVE extern int isatty YY_PROTO(( int )); #endif #endif #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 804 "libparse.l" int current_pos(int i) { return(i+offset+(int)(yytext-yylp_buffer_start)); } int libread(FILE* f, char* buf, int max_size) { int rc; offset = ftell(f); rc = myfread( buf, 1, max_size, f ); #if YYLPDEBUG >2 printf("fread: %d of %d\n", rc, max_size); #endif yylp_buffer_start = buf; return rc; } extern "C" { int yylpwrap() { //printf("======================= YYWRAP ====================\n"); if(brace1>0) { yylp_errno=YYLP_MISS_BR1; } if(brace2>0) { yylp_errno=YYLP_MISS_BR2; } if(brace3>0) { yylp_errno=YYLP_MISS_BR3; } if(quote>0) { yylp_errno=YYLP_MISSQUOT; } //printf("{=%d, (=%d, [=%d\n", brace1, brace2, brace3); if(feof(yyin)) return 1; else return 0; } } void reinit_yylp() { brace1 = 0; brace2 = 0; brace3 = 0; quote = 0; yy_init=1; yy_delete_buffer(YY_CURRENT_BUFFER); } void make_version(char *p,int what) { char ver[10]; char date[16]; ver[0]='?'; ver[1]='.'; ver[2]='?'; ver[3]='\0'; date[0]='?'; date[1]='\0'; if(what) sscanf(p,"%*[^=]= %*s %*s %10s %16s",ver,date); else sscanf(p,"// %*s %*s %10s %16s",ver,date); strcpy(libnamebuf,"("); strcat(libnamebuf,ver); strcat(libnamebuf,","); strcat(libnamebuf,date); strcat(libnamebuf,")"); if(what && strcmp(libnamebuf, "(?.?,?)")==0) { sscanf(p,"%*[^\"]\"%[^\"]\"",libnamebuf); } //printf("ID=(%d)%s; \n", what, p); } void copy_string(lp_modes mode) { #ifdef STANDALONE_PARSER if ((texinfo_out && (last_cmd == LP_INFO || last_cmd == LP_CATEGORY || last_cmd == LP_URL)) || (category_out && last_cmd == LP_CATEGORY) ) { long current_location = ftell(yylpin), i = string_start, quote = 0; char c; if (texinfo_out) { if (last_cmd == LP_INFO) { printf("$info = <0) text_buffer[i-offset] = text_buffer[i]; } } #endif /* STANDALONE_PARSER */ } void print_init() { printf("Init=%d\n", yy_init); } void print_version(lp_modes mode, char *p) { #ifdef STANDALONE_PARSER //printf("loading %s%s", p, libnamebuf); #else if ( mode == LOAD_LIB ) { if (BVERBOSE(V_LOAD_LIB) && p!=NULL ) Print(" %s...", p); //Warn( "loading %s%s", p, libnamebuf); } #endif } #ifdef STANDALONE_PARSER int main( int argc, char *argv[] ) { lib_style_types lib_style; main_init(argc, argv); if(yyin == NULL) { fprintf(stderr, "No library found to parse.\n"); return 1; } if (! (texinfo_out || category_out)) { if(lpverbose)printf("Verbose level=%d\n", lpverbose); if(check)printf("Reporting most possible annomalies.\n"); if(lpverbose||check)printf("\n"); printf( " %-15s %20s %s,%s %s,%s %s,%s\n", "Library", "function", "line", "start-eod", "line", "body-eob", "line", "example-eoe"); } yylplex(argv[0], argv[0], &lib_style,NULL); if(yylp_errno) { printf("ERROR occured: [%d] ", yylp_errno); printf(yylp_errlist[yylp_errno], yylplineno); printf("\n"); } else if(pi!=NULL) printpi(pi); if (texinfo_out) printf("1;"); return 0; } #endif /* STANDALONE_PARSER */ #endif /* HAVE_LIBPARSE */ singular-4.0.3+ds/Singular/libparse.h000066400000000000000000000053721266270727000175220ustar00rootroot00000000000000#ifndef LIBPARSE_H #define LIBPARSE_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: lib parsing */ typedef enum { OLD_LIBSTYLE, NEW_LIBSTYLE } lib_style_types; typedef enum { LOAD_LIB, GET_INFO } lp_modes; #ifdef STANDALONE_PARSER #define idhdl void* #define leftv void* #define package void* #define BOOLEAN int typedef enum { LANG_NONE, LANG_TOP, LANG_SINGULAR, LANG_C, LANG_MAX} language_defs; // LANG_TOP : Toplevel package only // LANG_SINGULAR: // LANG_C : // class proc_singular { public: long proc_start; // position where proc is starting long def_end; // position where proc header is ending long help_start; // position where help is starting long help_end; // position where help is starting long body_start; // position where proc-body is starting long body_end; // position where proc-body is ending long example_start; // position where example is starting long proc_end; // position where proc is ending int proc_lineno; int body_lineno; int example_lineno; char *body; long help_chksum; }; struct proc_object { //public: BOOLEAN (*function)(leftv res, leftv v); }; union uprocinfodata { public: proc_singular s; // data of Singular-procedure struct proc_object o; // pointer to binary-function }; typedef union uprocinfodata procinfodata; class procinfo; typedef procinfo * procinfov; class procinfo { public: char *libname; char *procname; package pack; language_defs language; short ref; char is_static; // if set, proc not accessible for user char trace_flag; procinfodata data; }; #endif procinfo *iiInitSingularProcinfo(procinfo* pi, const char *libname, const char *procname, int line, long pos, BOOLEAN pstatic=FALSE); int yylplex(const char *libname, const char *libfile, lib_style_types *lib_style, idhdl pl, BOOLEAN autoexport=FALSE, lp_modes=LOAD_LIB); void reinit_yylp(); extern char * text_buffer; # define YYLP_ERR_NONE 0 # define YYLP_DEF_BR2 1 # define YYLP_BODY_BR2 2 # define YYLP_BODY_BR3 3 # define YYLP_BODY_TMBR2 4 # define YYLP_BODY_TMBR3 5 # define YYLP_EX_BR2 6 # define YYLP_EX_BR3 7 # define YYLP_BAD_CHAR 8 # define YYLP_MISSQUOT 9 # define YYLP_MISS_BR1 10 # define YYLP_MISS_BR2 11 # define YYLP_MISS_BR3 12 # ifdef STANDALONE_PARSER #ifndef unix extern FILE* myfopen(char *path, char *mode); extern size_t myfread(void *ptr, size_t size, size_t nmemb, FILE *stream); #else #define myfopen fopen #define myfread fread #endif # endif #endif /* LIBPARSE_H */ singular-4.0.3+ds/Singular/libparse.ll000066400000000000000000000740571266270727000177100ustar00rootroot00000000000000%{ /**************************************** * Computer Algebra System SINGULAR * ****************************************/ #include #include #include #include #include #ifdef STANDALONE_PARSER #include #define HAVE_LIBPARSER #define YYLPDEBUG 1 #define myfread fread #else #include #include #include #include #include #include #include #endif #include #ifdef HAVE_LIBPARSER #define YY_SKIP_YYWRAP typedef enum { LP_NONE, LP_INFO, LP_CATEGORY, LP_URL, LP_VERSION} lib_cmds; int libread(FILE* f, char* buf, int max_size); int current_pos(int i); void print_version(lp_modes mode, char *p); void copy_string(lp_modes mode); void make_version(char *p, int what); int brace1 = 0; /* { } */ int brace2 = 0; /* ( ) */ int brace3 = 0; /* [ ] */ int quote = 0; /* " */ int offset = 0; BOOLEAN p_static = FALSE; int old_state = 0; lib_cmds last_cmd = LP_NONE; char libnamebuf[128]; char *text_buffer=NULL; long string_start; char *yylp_buffer_start; #ifndef NEW_FLEX int yylplineno = 1; #endif /* NEW_FLEX */ int lpverbose = 0, check = 0; int texinfo_out = 0; int found_info=0, found_cat=0, found_version=0, found_oldhelp = 0, found_proc_in_proc = 0; const char *yylp_errlist[]= { "", "missing close bracket ')' for proc definition in line %d.", /* 1 */ "missing close bracket ')' for procbody in line %d.", /* 2 */ "missing close bracket ']' for procbody in line %d.", /* 3 */ "too many ')' closed brackets in line %d.", /* 4 */ "too many ']' closed brackets in line %d.", /* 5 */ "missing close bracket ')' for example in line %d.", /* 6 */ "missing close bracket ']' for example in line %d.", /* 7 */ "cannot assign character '%c' in line %d to any group.", /* 8 */ "there must be a quote missing somewhere before line %d.", /* 9 */ "missing close bracket '}' at end of library in line %d.", /* 10 */ "missing close bracket ')' at end of library in line %d.", /* 11 */ "missing close bracket ']' at end of library in line %d.", /* 12 */ NULL }; int yylp_errno = 0; #ifdef STANDALONE_PARSER procinfov pi; int category_out = 0; void printpi(procinfov pi); void pi_clear(procinfov pi); extern "C" { int yylpwrap(); } void main_init(int argc, char *argv[]); void main_result(char *libname); #else /* STANDALONE_PARSER */ idhdl h0; idhdl h_top; #define pi IDPROC(h0) extern "C" { int yylpwrap(); } extern libstackv library_stack; #endif /* STANDALONE_PARSER */ static unsigned long help_chksum; #define SET_DEF_END(mode, pi, p) \ if ( mode == LOAD_LIB) pi->data.s.def_end = p; #define SET_HELP_START(mode, pi, p) \ if ( mode == LOAD_LIB) {pi->data.s.help_start = p; help_chksum = 0;} #define SET_HELP_END(mode, pi, p) \ if ( mode == LOAD_LIB) {pi->data.s.help_end = p; \ pi->data.s.help_chksum = help_chksum;} #define SET_BODY_START(mode, pi, l, p) \ if ( mode == LOAD_LIB) \ { \ pi->data.s.body_lineno = l; \ pi->data.s.body_start = p; \ } #define SET_BODY_END(mode, pi, p) \ if ( mode == LOAD_LIB) \ { \ pi->data.s.body_end = p-1; \ pi->data.s.proc_end = p-1; \ } #define SET_EXAMPLE_START(mode, pi, l, p) \ if ( mode == LOAD_LIB) \ { \ pi->data.s.example_lineno = l; \ pi->data.s.example_start = p; \ } #define SET_PROC_END(mode, pi, p) \ if ( mode == LOAD_LIB) \ { \ pi->data.s.proc_end = p-1; \ if(pi->data.s.body_end==0) \ pi->data.s.body_end = p-1; \ } #define ROTATE_RIGHT(c) if ((c) & 01) (c) = ((c) >>1) + 0x8000; else (c) >>= 1; #define IncrCheckSum(c) \ do \ { \ ROTATE_RIGHT(help_chksum); \ help_chksum += c; \ help_chksum &= 0xffff; \ } \ while(0) #undef YY_DECL #define YY_DECL int yylex(const char *newlib, const char *libfile, \ lib_style_types *lib_style, \ idhdl pl, BOOLEAN autoexport, lp_modes mode) #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( ((result = libread( (yyin), (char *) buf, max_size )) < 0 ) \ && ferror( yyin ) ) \ YY_FATAL_ERROR( "read in flex scanner failed" ); #define YY_USER_INIT { \ BEGIN(header); \ yylplineno = 1; \ yylp_errno = 0; \ *lib_style = OLD_LIBSTYLE; \ strcpy(libnamebuf,"(**unknown version**)"); \ } #if 0 proc[ \t]+{name} { printf("MISSING: PROC-cmd found. ERROR!\n"); } example[ \t]*\n { yylplineno++; printf("MISSING: EXAMPLE-cmd found. ERROR!\n"); } info=+"\"" { #endif %} digit [0-9] letter [@a-zA-Z\'] name ({letter}({letter}*{digit}*_*)*|_) varname ({letter}({letter}*{digit}*_*\(\))*|_|#) letters ({letter}|{digit}|[_./#%^*:,]) string ({letters}*) comment [\/][\/] dolar [$] nls [\n\r] symbols [~!@#$%^&*()_+-=\\\|\[\];:,<.>/\?\' \t\~\`] asymbols ({symbols}|[{}]) bsymbols ({symbols}|{escbrack}|[}]) aletters ({letter}|{digit}|{asymbols}|{dolar}|{escquote}|{nls}) bletters ({letter}|{digit}|{bsymbols}|{dolar}|{quote}|{nls}) cletters ({letter}|{digit}|{asymbols}|{dolar}|{quote}) strings ({aletters}*) escstrings ({bletters}*) fstring ({cletters}*) param ({name}+{tos}+{varname}) parameters ({param}(,{param})*) paramlist ("("{parameters}")") quote [\"] escquote (\\\") escbrack (\\\{) tnl ([ \t\n\r]*) eos ({quote}+{tnl}+"{") tos ([ \t]*) eq ([ \t]*+=[ \t]*) eqnl ([ \t\n\r]*+=[ \t\n\r]*) /* %start START */ %x header %x help %x libcmd %x libcmd2 %x pdef %x phead %x poldhelp %x phelp %x pbody %x pstr %x pexample %x pestr %x string %x comment %x info %x category %x url %x version %% (\/\/[^\n]*)|(^#![^\n]*)|([ \t]) { } \/\/* { old_state = YYSTATE; BEGIN(comment); } (info+{eqnl}+{quote}+{strings}+{quote}) { yyless(4); old_state = YYSTATE; BEGIN(info); } (category+{eqnl}+{quote}+{strings}+{quote}) { yyless(8); old_state = YYSTATE; BEGIN(category); } (url+{eqnl}+{quote}+{strings}+{quote}) { if ( mode != GET_INFO ) { #ifdef STANDALONE_PARSER if (texinfo_out) { char *c = yytext; printf("$url = \""); while ((*c != '\0') && (*c != '"')) c++; c++; while ((*c != '\0') && (*c != '"')) { if (*c != '\r') putchar(*c); c++; } printf("\";\n"); } #endif } } (version+{eqnl}+{quote}+{strings}+{quote}) { found_version++; if ( mode != GET_INFO ) { make_version(yytext,1); #ifdef STANDALONE_PARSER if (texinfo_out) { char *c = libnamebuf; printf("$version = \""); while (*c != '\0') { if (*c == '$' || *c == '@') putchar('\\'); if (*c != '\r') putchar(*c); if (*c == '\\') { c++; if (*c != '"') putchar('\\'); } else c++; } printf("\";\n"); } else if (!category_out) printf("Version:%s;\n", libnamebuf); #else if (text_buffer!=NULL) omFree((ADDRESS)text_buffer); text_buffer = omStrDup(libnamebuf); omMarkAsStaticAddr(text_buffer); #endif } } static { p_static=TRUE; } (proc[ \t]+{name})|([ \t]proc[ \t]+{name}) { char proc[256]; BEGIN(pdef); found_proc_in_proc = 0; proc[0]='\0'; sscanf( yytext, "%*[^p]proc %s", proc); if(strlen(proc)<1) sscanf( yytext, "proc %s", proc); #if YYLPDEBUG > 1 printf("Newlib:%s\n", newlib); #endif #ifdef STANDALONE_PARSER if ( pi != NULL ) { printpi(pi); pi_clear(pi); } pi = (procinfo *)malloc(sizeof(procinfo)); iiInitSingularProcinfo(pi, newlib, proc, yylplineno, current_pos(0), p_static); #else /*STANDALONE_PARSER*/ if( mode == LOAD_LIB) { h0 = enterid( proc, 0 /*myynest*/, PROC_CMD, &(IDPACKAGE(pl)->idroot), TRUE, !p_static); if (h0==NULL) return(1); if((!p_static) && autoexport) { package save=currPack; currPack=basePack; h_top = enterid( proc, 0 /*myynest*/, PROC_CMD, &(basePack->idroot), FALSE ); currPack=save; if (h_top==NULL) return(1); } /* omCheckAddr(IDID(h0)); */ if (h0!=NULL) { iiInitSingularProcinfo(IDPROC(h0), newlib, proc, yylplineno, current_pos(0),p_static); if ((!p_static) && (h_top != NULL) && autoexport) { if(IDPROC(h_top)!=NULL) piKill((procinfo *)IDPROC(h_top)); IDPROC(h_top)=IDPROC(h0); IDPROC(h_top)->ref++; } IDPROC(h0)->pack=IDPACKAGE(pl); if (BVERBOSE(V_LOAD_PROC)) Warn( " proc '%s' registered", proc ); } #endif /*STANDALONE_PARSER*/ SET_DEF_END(mode, pi, current_pos(yyleng+1)); #if YYLPDEBUG if(lpverbose) { printf("// PROCEDURE '%s' status: %s, ", proc, p_static ? "local" : "global"); printf("starting at line %d,%d: definition end: %d (%d).\n", yylplineno, current_pos(0), (int)pi->data.s.def_end, brace1); } #endif p_static=FALSE; #ifndef STANDALONE_PARSER } #endif /*STANDALONE_PARSER*/ } example { BEGIN(pexample); SET_EXAMPLE_START(mode, pi, yylplineno, current_pos(0)); #if YYLPDEBUG if(lpverbose) { printf("// EXAMPLE at line %d,%d (%d)\n", yylplineno, current_pos(0), brace1); } #endif } LIB[ \t]+"\"" { quote++; BEGIN(libcmd); } LIB[ \t]*"(\"" { quote++; brace2++; BEGIN(libcmd2); }

({comment}+{tos}+{dolar}+Id:+{string}+[^\n]*)|({comment}+{tos}+{dolar}+Header:+{string}+[^\n]*) { make_version(yytext, 0); #if YYLPDEBUG > 1 printf("+(id)HEAD:%s\n", yytext); #endif }
(^{comment}+[^\n]*) { #if YYLPDEBUG printf("+(cmt)HEAD:%s\n", yytext); #endif }
(^#![^\n]*) { #if YYLPDEBUG > 1 printf("-HEAD:%s\n", yytext); #endif }
^proc\ { yyless(0); BEGIN(INITIAL); yymore(); }
(info+{eqnl}+{quote})|(version+{eqnl}+{quote})|(category+{eqnl}+{quote})|(url+{eqnl}+{quote}) { yyless(0); *lib_style = NEW_LIBSTYLE; BEGIN(INITIAL); yymore(); }
^LIB[ \t]+"\"" { quote++; BEGIN(libcmd); }
^LIB[ \t]+"(\"" { quote++; brace2++; BEGIN(libcmd2); }
\n { yylplineno++; }
. { #if YYLPDEBUG > 1 printf(" HEAD:%s\n", yytext); #endif yyless(0); BEGIN(help); } (^{comment}+[^\n]*) { #if YYLPDEBUG > 1 printf(" HELP:%s\n", yytext); #endif BEGIN(INITIAL); } (^#![^\n]*) { #if YYLPDEBUG > 1 printf(" HELP:%s\n", yytext); #endif BEGIN(INITIAL); } (info+{eqnl}+{quote})|(version+{eqnl}+{quote})|(category+{eqnl}+{quote})|(url+{eqnl}+{quote}) { yyless(0); *lib_style = NEW_LIBSTYLE; BEGIN(INITIAL); yymore(); } ^proc\ { yyless(0); //printf("2) proc found.\n"); BEGIN(INITIAL); yymore(); } ^LIB[ \t]+"\"" { quote++; BEGIN(libcmd); } ^LIB[ \t]+"(\"" { quote++; brace2++; BEGIN(libcmd2); } \n { yylplineno++; } ({tos}|{comment}+{fstring}) { #if YYLPDEBUG if(lpverbose>2) printf("--->%s<---\n", yytext); #endif } . { found_oldhelp=1; #if YYLPDEBUG > 1 printf("-HELP:%s\n", yytext); #endif } {string}"\"" { quote--; yytext[yyleng-1] = '\0'; #ifndef STANDALONE_PARSER if ( mode == LOAD_LIB ) { library_stack->push(newlib, yytext); } #endif /* STANDALONE_PARSER */ #if YYLPDEBUG if(lpverbose>1) printf("LIB:'%s'\n", yytext); #endif BEGIN(INITIAL); } {string}"\")" { quote--; brace2--; yytext[yyleng-1] = '\0'; #ifndef STANDALONE_PARSER if ( mode == LOAD_LIB ) { library_stack->push(newlib, yytext); } #endif /* STANDALONE_PARSER */ #if YYLPDEBUG if(lpverbose>1) printf("LIB:'%s'\n", yytext); #endif BEGIN(INITIAL); } [ \t] { } \( { brace2++; #if YYLPDEBUG > 1 printf("%s", yytext); #endif } \) { brace2--; #if YYLPDEBUG > 1 printf(">%s<\n", yytext); printf("{=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif if(brace2<=0) { #if YYLPDEBUG > 1 printf("BEGIN(phead){=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif SET_DEF_END(mode, pi, current_pos(yyleng)); BEGIN(phead); } } "{" { if(brace2>0) { #if YYLPDEBUG > 1 printf("{=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif yylp_errno = YYLP_DEF_BR2; return(1); } else { brace1++; BEGIN(pbody); if(lpverbose) printf("// BODY at line %d,%d (%d)\n", yylplineno, current_pos(0), brace1); SET_BODY_START(mode, pi, yylplineno, current_pos(0)); } } \n { yylplineno++; if(brace2<=0) { #if YYLPDEBUG > 1 printf("BEGIN(phead-2){=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif BEGIN(phead); } } ({comment}[^\n]*) { } \/\/* { old_state = YYSTATE; BEGIN(comment); } . { if(brace2<=0) { BEGIN(phead); yyless(0); } } ({tnl}+{quote}+{strings}+{escquote}+{tnl}+"{") { #if YYLPDEBUG if(lpverbose>2)printf("0-Len=%d;\n", yyleng); #endif if(check) { printf("Procedure %s (line %d) has OLD-STYLE-HELP!\n", pi->procname, pi->data.s.proc_lineno); } SET_HELP_START(mode, pi, current_pos(0)); BEGIN(poldhelp); yyless(0); } ({tnl}+{quote}+{strings}+{eos}) { #if YYLPDEBUG if(lpverbose>2)printf("1-Len=%d;\n", yyleng); #endif BEGIN(phelp); yyless(0); } {escstrings}+"{" { if(check && yyleng>2) { printf("Procedure %s (line %d) has OLD-STYLE-HELP!\n", pi->procname, pi->data.s.proc_lineno); } #if YYLPDEBUG if(lpverbose>2 && yyleng>2) printf("2-Len=%d, %s;\n", yyleng, pi->procname); #endif SET_HELP_START(mode, pi, current_pos(0)); BEGIN(poldhelp); yyless(0); } . { printf("[%s]", yytext); } {escbrack} { } "{" { SET_HELP_END(mode, pi, current_pos(0)); brace1++; BEGIN(pbody); if(lpverbose) { printf("// HELP from %d to %d\n", (int)pi->data.s.help_start, (int)pi->data.s.help_end); printf("// BODY at line %d,%d (%d)\n", yylplineno, current_pos(0), brace1); } #if YYLPDEBUG > 1 printf("BEGIN(pbody){=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif SET_BODY_START(mode, pi, yylplineno, current_pos(0)); #if YYLPDEBUG > 1 printf("BODY at %d/%d", yylplineno, current_pos(0)); #endif } \n { yylplineno++; } . { } {quote} { old_state = YYSTATE; BEGIN(string); SET_HELP_START(mode, pi, current_pos(1)); } {tos} {} "{" { brace1++; BEGIN(pbody); if(lpverbose) { printf("// HELP from %d to %d\n", (int)pi->data.s.help_start, (int)pi->data.s.help_end); printf("// BODY at line %d,%d (%d)\n", yylplineno, current_pos(0), brace1); } #if YYLPDEBUG > 1 printf("BEGIN(pbody){=%d, (=%d, [=%d\n", brace1, brace2, brace3); #endif SET_BODY_START(mode, pi, yylplineno, current_pos(0)); #if YYLPDEBUG > 1 printf("BODY at %d/%d", yylplineno, current_pos(0)); #endif } \n { yylplineno++;} ({comment}[^\n]*) { } {quote} { quote++; old_state = YYSTATE; BEGIN(string); /* printf("%s", yytext); */ } proc+{tos}+{name}+{tnl}+{paramlist}+{tnl}+"{" { if(check) printf("*** found 2 proc whithin procedure '%s'.\n", pi->procname); yyless(yyleng-1); } proc+{tos}+{name}+{tnl}+"{" { if(check) printf("*** found 1 proc whithin procedure '%s'.\n", pi->procname); yyless(yyleng-1); } "{" { brace1++; #if YYLPDEBUG > 1 printf("line: %d, (%d)%s\n", yylplineno, brace1, yytext); #endif } "}" { #if YYLPDEBUG > 1 printf("line: %d, (%d)%s\n", yylplineno, brace1, yytext); #endif brace1--; if(brace2>0) { yylp_errno = YYLP_BODY_BR2; return(1); } if(brace3>0) { yylp_errno = YYLP_BODY_BR3; return(1); } if(brace1<=0) { SET_BODY_END(mode, pi, current_pos(yyleng)); SET_PROC_END(mode, pi, current_pos(yyleng)); #if YYLPDEBUG > 1 printf("-%d\n", current_pos(0)); #endif BEGIN(INITIAL); } } "(" { brace2++; /* printf("%s", yytext); */ } ")" { brace2--; /* printf("%s", yytext); */ if(brace2<0) { yylp_errno = YYLP_BODY_TMBR2; return(1); } } "[" { brace3++; /* printf("%s", yytext); */ } "]" { brace3--; /* printf("%s", yytext); */ if(brace3<0) { yylp_errno = YYLP_BODY_TMBR3; return(1); } } \n { yylplineno++; } . { } {quote} { quote++; BEGIN(string); found_info++; string_start = current_pos(yyleng); *lib_style = NEW_LIBSTYLE; last_cmd = LP_INFO; } \n { yylplineno++; } . { } {quote} { quote++; BEGIN(string); found_cat++; string_start = current_pos(yyleng); *lib_style = NEW_LIBSTYLE; last_cmd = LP_CATEGORY; } \n { yylplineno++; } . { } "\"" { quote--; copy_string(mode); last_cmd = LP_NONE; if(old_state==phelp) { SET_HELP_END(mode, pi, current_pos(0)); } BEGIN(old_state); /* printf("%s", yytext); */ } (\\\\)|(\\\") { if (old_state == phelp) IncrCheckSum(*yytext);} \n { yylplineno++; if (old_state == phelp) IncrCheckSum('\n');} . { if (old_state == phelp) IncrCheckSum(*yytext);} (\/\/[^\n]*) { } "\"" { quote++; old_state = YYSTATE; BEGIN(string); /* printf("%s", yytext); */ } "{" { brace1++; /* printf("(%d)%s", brace1, yytext); */ } "}" { brace1--; /* printf("(%d)%s", brace1, yytext); */ if(brace1<=0) { if(brace2>0) { yylp_errno=YYLP_EX_BR2; return(1); } if(brace3>0) { yylp_errno=YYLP_EX_BR3; return(1); } BEGIN(INITIAL); SET_PROC_END(mode, pi, current_pos(yyleng)); } } "(" { brace2++; /* printf("%s", yytext); */ } ")" { brace2--; /* printf("%s", yytext); */ } "[" { brace3++; /* printf("%s", yytext); */ } "]" { brace3--; /* printf("%s", yytext); */ } \n { yylplineno++; } . { } "\"" { quote--; BEGIN(pexample); /* printf("%s", yytext); */ } \\\\ { } \\\" { } \n { yylplineno++; } . { } \*\/ { BEGIN(old_state); } \n { yylplineno++; } . { } \n { yylplineno++; } \r { } ; { p_static = FALSE; #if YYLPDEBUG > 1 printf("%s", yytext); #endif } . { p_static = FALSE; yylp_errno = YYLP_BAD_CHAR; #ifdef STANDALONE_PARSER printf("[%d]", *yytext); #else if (text_buffer!=NULL) omFree((ADDRESS)text_buffer); text_buffer = omStrDup(yytext); omMarkAsStaticAddr(text_buffer); #endif #if YYLPDEBUG > 1 printf("[%s]", yytext); #endif return(1); } %% int current_pos(int i) { return(i+offset+(int)(yytext-yylp_buffer_start)); } int libread(FILE* f, char* buf, int max_size) { int rc; offset = ftell(f); rc = myfread( buf, 1, max_size, f ); #if YYLPDEBUG >2 printf("fread: %d of %d\n", rc, max_size); #endif yylp_buffer_start = buf; return rc; } extern "C" { int yylpwrap() { //printf("======================= YYWRAP ====================\n"); if(brace1>0) { yylp_errno=YYLP_MISS_BR1; } if(brace2>0) { yylp_errno=YYLP_MISS_BR2; } if(brace3>0) { yylp_errno=YYLP_MISS_BR3; } if(quote>0) { yylp_errno=YYLP_MISSQUOT; } //printf("{=%d, (=%d, [=%d\n", brace1, brace2, brace3); if(feof(yyin)) return 1; else return 0; } } void reinit_yylp() { brace1 = 0; brace2 = 0; brace3 = 0; quote = 0; yy_init=1; yy_delete_buffer(YY_CURRENT_BUFFER); } void make_version(char *p,int what) { char ver[10]; char date[16]; ver[0]='?'; ver[1]='.'; ver[2]='?'; ver[3]='\0'; date[0]='?'; date[1]='\0'; if(what) sscanf(p,"%*[^=]= %*s %*s %10s %16s",ver,date); else sscanf(p,"// %*s %*s %10s %16s",ver,date); strcpy(libnamebuf,"("); strcat(libnamebuf,ver); strcat(libnamebuf,","); strcat(libnamebuf,date); strcat(libnamebuf,")"); if(what && strcmp(libnamebuf, "(?.?,?)")==0) { sscanf(p,"%*[^\"]\"%[^\"]\"",libnamebuf); } //printf("ID=(%d)%s; \n", what, p); } void copy_string(lp_modes mode) { #ifdef STANDALONE_PARSER if ((texinfo_out && (last_cmd == LP_INFO || last_cmd == LP_CATEGORY || last_cmd == LP_URL)) || (category_out && last_cmd == LP_CATEGORY) ) { long current_location = ftell(yylpin), i = string_start, quote = 0; char c; if (texinfo_out) { if (last_cmd == LP_INFO) { printf("$info = <0) text_buffer[i-offset] = text_buffer[i]; } } #endif /* STANDALONE_PARSER */ } void print_init() { printf("Init=%d\n", yy_init); } void print_version(lp_modes mode, char *p) { #ifdef STANDALONE_PARSER //printf("loading %s%s", p, libnamebuf); #else if ( mode == LOAD_LIB ) { if (BVERBOSE(V_LOAD_LIB) && p!=NULL ) Print(" %s...", p); //Warn( "loading %s%s", p, libnamebuf); } #endif } #ifdef STANDALONE_PARSER int main( int argc, char *argv[] ) { lib_style_types lib_style; main_init(argc, argv); if(yyin == NULL) { fprintf(stderr, "No library found to parse.\n"); return 1; } if (! (texinfo_out || category_out)) { if(lpverbose)printf("Verbose level=%d\n", lpverbose); if(check)printf("Reporting most possible annomalies.\n"); if(lpverbose||check)printf("\n"); printf( " %-15s %20s %s,%s %s,%s %s,%s\n", "Library", "function", "line", "start-eod", "line", "body-eob", "line", "example-eoe"); } yylplex(argv[0], argv[0], &lib_style,NULL); if(yylp_errno) { printf("ERROR occured: [%d] ", yylp_errno); printf(yylp_errlist[yylp_errno], yylplineno); printf("\n"); } else if(pi!=NULL) printpi(pi); if (texinfo_out) printf("1;"); return 0; } #endif /* STANDALONE_PARSER */ #endif /* HAVE_LIBPARSE */ singular-4.0.3+ds/Singular/libsingular.h000066400000000000000000000015541266270727000202320ustar00rootroot00000000000000#ifndef LIBSINGULAR__H #define LIBSINGULAR__H #include // Why this? #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void siInit(char *); /* we need this function in Sage*/ number nr2mMapZp(number from); // TODO: replace with something else... #endif // #ifndef LIBSINGULAR__H singular-4.0.3+ds/Singular/linearAlgebra_ip.cc000066400000000000000000000073021266270727000212720ustar00rootroot00000000000000 #include #include #include /** * Computes all eigenvalues of a given real quadratic matrix with * multiplicites. * * The method assumes that the current ground field is the complex numbers. * Computations are based on the QR double shift algorithm involving * Hessenberg form and householder transformations. * If the algorithm works, then it returns a list with two entries which * are again lists of the same size: * _[1][i] is the i-th mutually distinct eigenvalue that was found, * _[2][i] is the (int) multiplicity of _[1][i]. * If the algorithm does not work (due to an ill-posed matrix), a list with * the single entry (int)0 is returned. * 'tol1' is used for detection of deflation in the actual qr double shift * algorithm. * 'tol2' is used for ending Heron's iteration whenever square roots * are being computed. * 'tol3' is used to distinguish between distinct eigenvalues: When * the Euclidean distance between two computed eigenvalues is less then * tol3, then they will be regarded equal, resulting in a higher * multiplicity of the corresponding eigenvalue. * * @return a list with one entry (int)0, or two entries which are again lists **/ lists qrDoubleShift( const matrix A, /**< [in] the quadratic matrix */ const number tol1, /**< [in] tolerance for deflation */ const number tol2, /**< [in] tolerance for square roots */ const number tol3, /**< [in] tolerance for distinguishing eigenvalues */ const ring r= currRing ); lists qrDoubleShift(const matrix A, const number tol1, const number tol2, const number tol3, const ring R) { int n = MATROWS(A); matrix* queue = new matrix[n]; queue[0] = mp_Copy(A,R); int queueL = 1; number* eigenVs = new number[n]; int eigenL = 0; /* here comes the main call: */ bool worked = qrDS(n, queue, queueL, eigenVs, eigenL, tol1, tol2,R); lists result = (lists)omAlloc(sizeof(slists)); if (!worked) { for (int i = 0; i < eigenL; i++) nDelete(&eigenVs[i]); delete [] eigenVs; for (int i = 0; i < queueL; i++) idDelete((ideal*)&queue[i]); delete [] queue; result->Init(1); result->m[0].rtyp = INT_CMD; result->m[0].data = (void*)0; /* a list with a single entry which is the int zero */ } else { /* now eigenVs[0..eigenL-1] contain all eigenvalues; among them, there may be equal entries */ number* distinctEVs = new number[n]; int distinctC = 0; int* mults = new int[n]; for (int i = 0; i < eigenL; i++) { int index = similar(distinctEVs, distinctC, eigenVs[i], tol3); if (index == -1) /* a new eigenvalue */ { distinctEVs[distinctC] = nCopy(eigenVs[i]); mults[distinctC++] = 1; } else mults[index]++; nDelete(&eigenVs[i]); } delete [] eigenVs; lists eigenvalues = (lists)omAlloc(sizeof(slists)); eigenvalues->Init(distinctC); lists multiplicities = (lists)omAlloc(sizeof(slists)); multiplicities->Init(distinctC); for (int i = 0; i < distinctC; i++) { eigenvalues->m[i].rtyp = NUMBER_CMD; eigenvalues->m[i].data = (void*)nCopy(distinctEVs[i]); multiplicities->m[i].rtyp = INT_CMD; multiplicities->m[i].data = (void*)(long)mults[i]; nDelete(&distinctEVs[i]); } delete [] distinctEVs; delete [] mults; result->Init(2); result->m[0].rtyp = LIST_CMD; result->m[0].data = (char*)eigenvalues; result->m[1].rtyp = LIST_CMD; result->m[1].data = (char*)multiplicities; } return result; } singular-4.0.3+ds/Singular/linearAlgebra_ip.h000066400000000000000000000032521266270727000211340ustar00rootroot00000000000000#ifndef LINEARALGEBRA_H #define LINEARALGEBRA_H #include #include /** * Computes all eigenvalues of a given real quadratic matrix with * multiplicites. * * The method assumes that the current ground field is the complex numbers. * Computations are based on the QR double shift algorithm involving * Hessenberg form and householder transformations. * If the algorithm works, then it returns a list with two entries which * are again lists of the same size: * _[1][i] is the i-th mutually distinct eigenvalue that was found, * _[2][i] is the (int) multiplicity of _[1][i]. * If the algorithm does not work (due to an ill-posed matrix), a list with * the single entry (int)0 is returned. * 'tol1' is used for detection of deflation in the actual qr double shift * algorithm. * 'tol2' is used for ending Heron's iteration whenever square roots * are being computed. * 'tol3' is used to distinguish between distinct eigenvalues: When * the Euclidean distance between two computed eigenvalues is less then * tol3, then they will be regarded equal, resulting in a higher * multiplicity of the corresponding eigenvalue. * * @return a list with one entry (int)0, or two entries which are again lists **/ lists qrDoubleShift( const matrix A, /**< [in] the quadratic matrix */ const number tol1, /**< [in] tolerance for deflation */ const number tol2, /**< [in] tolerance for square roots */ const number tol3, /**< [in] tolerance for distinguishing eigenvalues */ const ring r= currRing ); #endif singular-4.0.3+ds/Singular/links/000077500000000000000000000000001266270727000166615ustar00rootroot00000000000000singular-4.0.3+ds/Singular/links/asciiLink.cc000066400000000000000000000257601266270727000211100ustar00rootroot00000000000000/**************************************** * * Computer Algebra System SINGULAR * * ****************************************/ /* * ABSTRACT: ascii links (standard) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* declarations */ static BOOLEAN DumpAscii(FILE *fd, idhdl h); static BOOLEAN DumpAsciiIdhdl(FILE *fd, idhdl h); static const char* GetIdString(idhdl h); static int DumpRhs(FILE *fd, idhdl h); static BOOLEAN DumpQring(FILE *fd, idhdl h, const char *type_str); static BOOLEAN DumpAsciiMaps(FILE *fd, idhdl h, idhdl rhdl); extern si_link_extension si_link_root; /* =============== ASCII ============================================= */ BOOLEAN slOpenAscii(si_link l, short flag, leftv /*h*/) { const char *mode; if (flag & SI_LINK_OPEN) { if (l->mode[0] != '\0' && (strcmp(l->mode, "r") == 0)) flag = SI_LINK_READ; else flag = SI_LINK_WRITE; } if (flag == SI_LINK_READ) mode = "r"; else if (strcmp(l->mode, "w") == 0) mode = "w"; else mode = "a"; if (l->name[0] == '\0') { // stdin or stdout if (flag == SI_LINK_READ) { l->data = (void *) stdin; mode = "r"; } else { l->data = (void *) stdout; mode = "a"; } } else { // normal ascii link to a file FILE *outfile; char *filename=l->name; if(filename[0]=='>') { if (filename[1]=='>') { filename+=2; mode = "a"; } else { filename++; mode="w"; } } outfile=myfopen(filename,mode); if (outfile!=NULL) l->data = (void *) outfile; else return TRUE; } omFree(l->mode); l->mode = omStrDup(mode); SI_LINK_SET_OPEN_P(l, flag); return FALSE; } BOOLEAN slCloseAscii(si_link l) { SI_LINK_SET_CLOSE_P(l); if (l->name[0] != '\0') { return (fclose((FILE *)l->data)!=0); } return FALSE; } leftv slReadAscii2(si_link l, leftv pr) { FILE * fp=(FILE *)l->data; char * buf=NULL; if (fp!=NULL && l->name[0] != '\0') { fseek(fp,0L,SEEK_END); long len=ftell(fp); fseek(fp,0L,SEEK_SET); buf=(char *)omAlloc((int)len+1); if (BVERBOSE(V_READING)) Print("//Reading %ld chars\n",len); myfread( buf, len, 1, fp); buf[len]='\0'; } else { if (pr->Typ()==STRING_CMD) { buf=(char *)omAlloc(80); fe_fgets_stdin((char *)pr->Data(),buf,80); } else { WerrorS("read(,) expected"); buf=omStrDup(""); } } leftv v=(leftv)omAlloc0Bin(sleftv_bin); v->rtyp=STRING_CMD; v->data=buf; return v; } leftv slReadAscii(si_link l) { sleftv tmp; memset(&tmp,0,sizeof(sleftv)); tmp.rtyp=STRING_CMD; tmp.data=(void*) "? "; return slReadAscii2(l,&tmp); } BOOLEAN slWriteAscii(si_link l, leftv v) { FILE *outfile=(FILE *)l->data; BOOLEAN err=FALSE; char *s; while (v!=NULL) { s = v->String(); // free v ?? if (s!=NULL) { fprintf(outfile,"%s\n",s); omFree((ADDRESS)s); } else { Werror("cannot convert to string"); err=TRUE; } v = v->next; } fflush(outfile); return err; } const char* slStatusAscii(si_link l, const char* request) { if (strcmp(request, "read") == 0) { if (SI_LINK_R_OPEN_P(l)) return "ready"; else return "not ready"; } else if (strcmp(request, "write") == 0) { if (SI_LINK_W_OPEN_P(l)) return "ready"; else return "not ready"; } else return "unknown status request"; } /*------------------ Dumping in Ascii format -----------------------*/ BOOLEAN slDumpAscii(si_link l) { FILE *fd = (FILE *) l->data; idhdl h = IDROOT, rh = currRingHdl; BOOLEAN status = DumpAscii(fd, h); if (! status ) status = DumpAsciiMaps(fd, h, NULL); if (currRingHdl != rh) rSetHdl(rh); fprintf(fd, "option(set, intvec(%d, %d));\n", si_opt_1, si_opt_2); fprintf(fd, "RETURN();\n"); fflush(fd); return status; } // we do that recursively, to dump ids in the the order in which they // were actually defined static BOOLEAN DumpAscii(FILE *fd, idhdl h) { if (h == NULL) return FALSE; if (DumpAscii(fd, IDNEXT(h))) return TRUE; // need to set the ring before writing it, otherwise we get in // trouble with minpoly if (IDTYP(h) == RING_CMD || IDTYP(h) == QRING_CMD) rSetHdl(h); if (DumpAsciiIdhdl(fd, h)) return TRUE; if (IDTYP(h) == RING_CMD || IDTYP(h) == QRING_CMD) return DumpAscii(fd, IDRING(h)->idroot); else return FALSE; } static BOOLEAN DumpAsciiMaps(FILE *fd, idhdl h, idhdl rhdl) { if (h == NULL) return FALSE; if (DumpAsciiMaps(fd, IDNEXT(h), rhdl)) return TRUE; if (IDTYP(h) == RING_CMD || IDTYP(h) == QRING_CMD) return DumpAsciiMaps(fd, IDRING(h)->idroot, h); else if (IDTYP(h) == MAP_CMD) { char *rhs; rSetHdl(rhdl); rhs = h->String(); if (fprintf(fd, "setring %s;\n", IDID(rhdl)) == EOF) return TRUE; if (fprintf(fd, "%s %s = %s, %s;\n", Tok2Cmdname(MAP_CMD), IDID(h), IDMAP(h)->preimage, rhs) == EOF) { omFree(rhs); return TRUE; } else { omFree(rhs); return FALSE; } } else return FALSE; } static BOOLEAN DumpAsciiIdhdl(FILE *fd, idhdl h) { const char *type_str = GetIdString(h); int type_id = IDTYP(h); if ((type_id == PACKAGE_CMD) &&(strcmp(IDID(h), "Top") == 0)) return FALSE; // we do not throw an error if a wrong type was attempted to be dumped if (type_str == NULL) return FALSE; // handle qrings separately if (type_id == QRING_CMD) return DumpQring(fd, h, type_str); // C-proc not to be dumped if ((type_id == PROC_CMD) && (IDPROC(h)->language == LANG_C)) return FALSE; // put type and name if (fprintf(fd, "%s %s", type_str, IDID(h)) == EOF) return TRUE; // for matricies, append the dimension if (type_id == MATRIX_CMD) { ideal id = IDIDEAL(h); if (fprintf(fd, "[%d][%d]", id->nrows, id->ncols)== EOF) return TRUE; } else if (type_id == INTMAT_CMD) { if (fprintf(fd, "[%d][%d]", IDINTVEC(h)->rows(), IDINTVEC(h)->cols()) == EOF) return TRUE; } if (type_id == PACKAGE_CMD) { return (fprintf(fd, ";\n") == EOF); } // write the equal sign if (fprintf(fd, " = ") == EOF) return TRUE; // and the right hand side if (DumpRhs(fd, h) == EOF) return TRUE; // semicolon und tschuess if (fprintf(fd, ";\n") == EOF) return TRUE; return FALSE; } static const char* GetIdString(idhdl h) { int type = IDTYP(h); switch(type) { case LIST_CMD: { lists l = IDLIST(h); int i, nl = l->nr + 1; for (i=0; im[i])) == NULL) return NULL; } case PACKAGE_CMD: case INT_CMD: case INTVEC_CMD: case INTMAT_CMD: case STRING_CMD: case RING_CMD: case QRING_CMD: case PROC_CMD: case NUMBER_CMD: case POLY_CMD: case IDEAL_CMD: case VECTOR_CMD: case MODUL_CMD: case MATRIX_CMD: return Tok2Cmdname(type); case MAP_CMD: case LINK_CMD: return NULL; default: Warn("Error dump data of type %s", Tok2Cmdname(IDTYP(h))); return NULL; } } static BOOLEAN DumpQring(FILE *fd, idhdl h, const char *type_str) { char *ring_str = h->String(); if (fprintf(fd, "%s temp_ring = %s;\n", Tok2Cmdname(RING_CMD), ring_str) == EOF) return TRUE; if (fprintf(fd, "%s temp_ideal = %s;\n", Tok2Cmdname(IDEAL_CMD), iiStringMatrix((matrix) IDRING(h)->qideal, 1, currRing, n_GetChar(currRing->cf))) == EOF) return TRUE; if (fprintf(fd, "attrib(temp_ideal, \"isSB\", 1);\n") == EOF) return TRUE; if (fprintf(fd, "%s %s = temp_ideal;\n", type_str, IDID(h)) == EOF) return TRUE; if (fprintf(fd, "kill temp_ring;\n") == EOF) return TRUE; else { omFree(ring_str); return FALSE; } } static int DumpRhs(FILE *fd, idhdl h) { int type_id = IDTYP(h); if (type_id == LIST_CMD) { lists l = IDLIST(h); int i, nl = l->nr; fprintf(fd, "list("); for (i=0; im[i])) == EOF) return EOF; fprintf(fd, ","); } if (nl > 0) { if (DumpRhs(fd, (idhdl) &(l->m[nl])) == EOF) return EOF; } fprintf(fd, ")"); } else if (type_id == STRING_CMD) { char *pstr = IDSTRING(h); fputc('"', fd); while (*pstr != '\0') { if (*pstr == '"' || *pstr == '\\') fputc('\\', fd); fputc(*pstr, fd); pstr++; } fputc('"', fd); } else if (type_id == PROC_CMD) { procinfov pi = IDPROC(h); if (pi->language == LANG_SINGULAR) { if( pi->data.s.body==NULL) iiGetLibProcBuffer(pi); char *pstr = pi->data.s.body; fputc('"', fd); while (*pstr != '\0') { if (*pstr == '"' || *pstr == '\\') fputc('\\', fd); fputc(*pstr, fd); pstr++; } fputc('"', fd); } else fputs("(null)", fd); } else { char *rhs = h->String(); if (rhs == NULL) return EOF; BOOLEAN need_klammer=FALSE; if (type_id == INTVEC_CMD) { fprintf(fd, "intvec(");need_klammer=TRUE; } else if (type_id == IDEAL_CMD) { fprintf(fd, "ideal(");need_klammer=TRUE; } else if (type_id == MODUL_CMD) { fprintf(fd, "module(");need_klammer=TRUE; } if (fprintf(fd, "%s", rhs) == EOF) return EOF; omFree(rhs); if ((type_id == RING_CMD || type_id == QRING_CMD) && IDRING(h)->cf->type==n_algExt) { StringSetS(""); p_Write(IDRING(h)->cf->extRing->qideal->m[0],IDRING(h)->cf->extRing); rhs = StringEndS(); if (fprintf(fd, "; minpoly = %s", rhs) == EOF) { omFree(rhs); return EOF;} omFree(rhs); } else if (need_klammer) fprintf(fd, ")"); } return 1; } BOOLEAN slGetDumpAscii(si_link l) { if (l->name[0] == '\0') { Werror("getdump: Can not get dump from stdin"); return TRUE; } else { BOOLEAN status = newFile(l->name); if (status) return TRUE; int old_echo=si_echo; si_echo=0; status=yyparse(); si_echo=old_echo; if (status) return TRUE; else { // lets reset the file pointer to the end to reflect that // we are finished with reading FILE *f = (FILE *) l->data; fseek(f, 0L, SEEK_END); return FALSE; } } } void slStandardInit() { si_link_extension s; si_link_root=(si_link_extension)omAlloc0Bin(s_si_link_extension_bin); si_link_root->Open=slOpenAscii; si_link_root->Close=slCloseAscii; si_link_root->Kill=NULL; si_link_root->Read=slReadAscii; si_link_root->Read2=slReadAscii2; si_link_root->Write=slWriteAscii; si_link_root->Dump=slDumpAscii; si_link_root->GetDump=slGetDumpAscii; si_link_root->Status=slStatusAscii; si_link_root->type="ASCII"; s = si_link_root; s->next = NULL; } singular-4.0.3+ds/Singular/links/dbm_sl.h000066400000000000000000000011421266270727000202700ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /*************************************************************** * File: dbm_sl.h * Purpose: declaration of sl_link routines for dbm * Author: obachman (Olaf Bachmann) * Created: 12/00 *******************************************************************/ LINKAGE BOOLEAN dbOpen(si_link l, short flag, leftv u); LINKAGE BOOLEAN dbWrite(si_link l, leftv v); LINKAGE leftv dbRead1(si_link l); LINKAGE leftv dbRead2(si_link l, leftv key); LINKAGE BOOLEAN dbClose(si_link l); singular-4.0.3+ds/Singular/links/ndbm.cc000066400000000000000000000310041266270727000201060ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ //**************************************************************************/ // // //**************************************************************************/ // 'ndbm.cc' containes all low-level functions to manipulate dbm-files // for the original Copyright of this file and 'ndbm.h' see below . // // some minor change where needed to compile and run under MacOS/MPW // //**************************************************************************/ #include #include #ifdef HAVE_DBM #ifndef HPUX_9 #include #endif /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * for details see ndbm.h */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)ndbm.c 5.3 (Berkeley) 3/9/86"; #endif //**************************************************************************/ #include /* alternative: * # define EPERM 1 * # define ENOMEM 23 * # define ENOSPC 28 * # define L_SET SEEK_SET */ #include #include #include #include #include #include #include #include #ifndef HAVE_BCOPY # define bcopy(a,b,c) memmove(b,a,c) #endif /* not HAVE_BCOPY */ #include #define BYTESIZ 8 #undef setbit static void dbm_access(register DBM *db, long hash); static int getbit(register DBM *db); static void setbit(register DBM *db); static datum makdatum(char buf[PBLKSIZ], int n); static int finddatum(char buf[PBLKSIZ], datum item); static long dcalchash(datum item); static int delitem(char buf[PBLKSIZ], int n); static int additem(char buf[PBLKSIZ], datum item, datum item1); // extern int errno; extern "C" int singular_fstat(int fd, struct stat *buf); DBM * dbm_open(char *file, int flags, int mode) { struct stat statb; register DBM *db; if ((db = (DBM *)malloc(sizeof *db)) == 0) { errno = ENOMEM; return ((DBM *)0); } #ifdef MSDOS // default mode of open is ascii, we need binary mode. flags |= O_BINARY; #endif db->dbm_flags = (flags & 03) == O_RDONLY ? _DBM_RDONLY : 0; if ((flags & 03) == O_WRONLY) flags = (flags & ~03) | O_RDWR; strcpy(db->dbm_pagbuf, file); strcat(db->dbm_pagbuf, ".pag"); db->dbm_pagf = si_open(db->dbm_pagbuf, flags, mode); if (db->dbm_pagf < 0) goto bad; strcpy(db->dbm_pagbuf, file); strcat(db->dbm_pagbuf, ".dir"); db->dbm_dirf = si_open(db->dbm_pagbuf, flags, mode); if (db->dbm_dirf < 0) goto bad1; singular_fstat(db->dbm_dirf, &statb); db->dbm_maxbno = statb.st_size*BYTESIZ-1; db->dbm_pagbno = db->dbm_dirbno = -1; return (db); bad1: (void) si_close(db->dbm_pagf); bad: free((char *)db); return ((DBM *)0); } void dbm_close(DBM *db) { (void) si_close(db->dbm_dirf); (void) si_close(db->dbm_pagf); free((char *)db); } long dbm_forder(register DBM *db, datum key) { long hash; hash = dcalchash(key); for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) { db->dbm_blkno = hash & db->dbm_hmask; db->dbm_bitno = db->dbm_blkno + db->dbm_hmask; if (getbit(db) == 0) break; } return (db->dbm_blkno); } datum dbm_fetch(register DBM *db, datum key) { register int i; datum item; if (dbm_error(db)) goto err; dbm_access(db, dcalchash(key)); if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) { item = makdatum(db->dbm_pagbuf, i+1); if (item.dptr != NULL) return (item); } err: item.dptr = NULL; item.dsize = 0; return (item); } int dbm_delete(register DBM *db, datum key) { register int i; // datum item; if (dbm_error(db)) return (-1); if (dbm_rdonly(db)) { errno = EPERM; return (-1); } dbm_access(db, dcalchash(key)); if ((i = finddatum(db->dbm_pagbuf, key)) < 0) return (-1); if (!delitem(db->dbm_pagbuf, i)) goto err; db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET); if (si_write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { err: db->dbm_flags |= _DBM_IOERR; return (-1); } return (0); } int dbm_store(register DBM *db, datum key, datum dat, int replace) { register int i; int ret; datum item, item1; char ovfbuf[PBLKSIZ]; if (dbm_error(db)) return (-1); if (dbm_rdonly(db)) { errno = EPERM; return (-1); } _loop: dbm_access(db, dcalchash(key)); if ((i = finddatum(db->dbm_pagbuf, key)) >= 0) { if (!replace) return (1); if (!delitem(db->dbm_pagbuf, i)) { db->dbm_flags |= _DBM_IOERR; return (-1); } } if (!additem(db->dbm_pagbuf, key, dat)) goto split; db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET); if ( (ret=si_write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ)) != PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; return (-1); } return (0); split: if (key.dsize+dat.dsize+3*sizeof(short) >= PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; errno = ENOSPC; return (-1); } memset(ovfbuf, 0, PBLKSIZ); for (i=0;;) { item = makdatum(db->dbm_pagbuf, i); if (item.dptr == NULL) break; if (dcalchash(item) & (db->dbm_hmask+1)) { item1 = makdatum(db->dbm_pagbuf, i+1); if (item1.dptr == NULL) { fprintf(stderr, "ndbm: split not paired\n"); db->dbm_flags |= _DBM_IOERR; break; } if (!additem(ovfbuf, item, item1) || !delitem(db->dbm_pagbuf, i)) { db->dbm_flags |= _DBM_IOERR; return (-1); } continue; } i += 2; } db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET); if (si_write(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; return (-1); } (void) lseek(db->dbm_pagf, (db->dbm_blkno+db->dbm_hmask+1)*PBLKSIZ, L_SET); if (si_write(db->dbm_pagf, ovfbuf, PBLKSIZ) != PBLKSIZ) { db->dbm_flags |= _DBM_IOERR; return (-1); } setbit(db); goto _loop; } datum dbm_firstkey(DBM *db) { db->dbm_blkptr = 0L; db->dbm_keyptr = 0; return (dbm_nextkey(db)); } datum dbm_nextkey(register DBM *db) { struct stat statb; datum item; if (dbm_error(db) || singular_fstat(db->dbm_pagf, &statb) < 0 ) goto err; statb.st_size /= PBLKSIZ; for (;;) { if (db->dbm_blkptr != db->dbm_pagbno) { db->dbm_pagbno = db->dbm_blkptr; (void) lseek(db->dbm_pagf, db->dbm_blkptr*PBLKSIZ, L_SET); if (si_read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) memset(db->dbm_pagbuf, 0, PBLKSIZ); #ifdef DEBUG else if (chkblk(db->dbm_pagbuf) < 0) db->dbm_flags |= _DBM_IOERR; #endif } if (((short *)db->dbm_pagbuf)[0] != 0) { item = makdatum(db->dbm_pagbuf, db->dbm_keyptr); if (item.dptr != NULL) { db->dbm_keyptr += 2; return (item); } db->dbm_keyptr = 0; } if (++db->dbm_blkptr >= statb.st_size) break; } err: item.dptr = NULL; item.dsize = 0; return (item); } static void dbm_access(register DBM *db, long hash) { for (db->dbm_hmask=0;; db->dbm_hmask=(db->dbm_hmask<<1)+1) { db->dbm_blkno = hash & db->dbm_hmask; db->dbm_bitno = db->dbm_blkno + db->dbm_hmask; if (getbit(db) == 0) break; } if (db->dbm_blkno != db->dbm_pagbno) { db->dbm_pagbno = db->dbm_blkno; (void) lseek(db->dbm_pagf, db->dbm_blkno*PBLKSIZ, L_SET); if (si_read(db->dbm_pagf, db->dbm_pagbuf, PBLKSIZ) != PBLKSIZ) memset(db->dbm_pagbuf, 0, PBLKSIZ); #ifdef DEBUG else if (chkblk(db->dbm_pagbuf) < 0) db->dbm_flags |= _DBM_IOERR; #endif } } static int getbit(register DBM *db) { long bn; register int b, i, n; if (db->dbm_bitno > db->dbm_maxbno) return (0); n = db->dbm_bitno % BYTESIZ; bn = db->dbm_bitno / BYTESIZ; i = bn % DBLKSIZ; b = bn / DBLKSIZ; if (b != db->dbm_dirbno) { db->dbm_dirbno = b; (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET); if (si_read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) memset(db->dbm_dirbuf, 0, DBLKSIZ); } return (db->dbm_dirbuf[i] & (1<dbm_bitno > db->dbm_maxbno) db->dbm_maxbno = db->dbm_bitno; n = db->dbm_bitno % BYTESIZ; bn = db->dbm_bitno / BYTESIZ; i = bn % DBLKSIZ; b = bn / DBLKSIZ; if (b != db->dbm_dirbno) { db->dbm_dirbno = b; (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET); if (si_read(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) memset(db->dbm_dirbuf, 0, DBLKSIZ); } db->dbm_dirbuf[i] |= 1<dbm_dirbno = b; (void) lseek(db->dbm_dirf, (long)b*DBLKSIZ, L_SET); if (si_write(db->dbm_dirf, db->dbm_dirbuf, DBLKSIZ) != DBLKSIZ) db->dbm_flags |= _DBM_IOERR; } static datum makdatum(char buf[PBLKSIZ], int n) { register short *sp; register int t; datum item; sp = (short *)buf; if ((unsigned)n >= (unsigned)sp[0]) { item.dptr = NULL; item.dsize = 0; return (item); } t = PBLKSIZ; if (n > 0) t = sp[n]; item.dptr = buf+sp[n+1]; item.dsize = t - sp[n+1]; return (item); } static int finddatum(char buf[PBLKSIZ], datum item) { register short *sp; register int i, n, j; sp = (short *)buf; n = PBLKSIZ; for (i=0, j=sp[0]; i= 0; ) { c = *cp++; for (j=0; j>= 4; } } return (long)(hashl); } /* * Delete pairs of items (n & n+1). */ static int delitem(char buf[PBLKSIZ], int n) { register short *sp, *sp1; register int i1, i2; sp = (short *)buf; i2 = sp[0]; if ((unsigned)n >= (unsigned)i2 || (n & 1)) return (0); if (n == i2-2) { sp[0] -= 2; return (1); } i1 = PBLKSIZ; if (n > 0) i1 = sp[n]; i1 -= sp[n+2]; if (i1 > 0) { i2 = sp[i2]; bcopy(&buf[i2], &buf[i2 + i1], sp[n+2] - i2); } sp[0] -= 2; for (sp1 = sp + sp[0], sp += n+1; sp <= sp1; sp++) sp[0] = sp[2] + i1; return (1); } /* * Add pairs of items (item & item1). */ static int additem(char buf[PBLKSIZ], datum item, datum item1) { register short *sp; register int i1, i2, tmp; sp = (short *)buf; i1 = PBLKSIZ; i2 = sp[0]; if (i2 > 0) i1 = sp[i2]; i1 -= item.dsize + item1.dsize; tmp = (i2+3) * sizeof(short); if (i1 <= tmp) return (0); sp[0] += 2; sp[++i2] = i1 + item1.dsize; bcopy(item.dptr, &buf[i1 + item1.dsize], item.dsize); sp[++i2] = i1; bcopy(item1.dptr, &buf[i1], item1.dsize); return (1); } #ifdef DEBUG static chkblk(char buf[PBLKSIZ]) { register short *sp; register t, i; sp = (short *)buf; t = PBLKSIZ; for (i=0; i t) return (-1); t = sp[i+1]; } if (t < (sp[0]+1)*sizeof(short)) return (-1); return (0); } #endif #endif /* HAVE_DBM */ singular-4.0.3+ds/Singular/links/ndbm.h000066400000000000000000000101561266270727000177550ustar00rootroot00000000000000#ifndef NDBM_H #define NDBM_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: DBM */ /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ndbm.h 5.1 (Berkeley) 5/30/85 * * Par. 3 removed due to a license change (1999) * see ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change */ /* * Hashed key data base library. */ #define PBLKSIZ 1024 #define DBLKSIZ 4096 typedef struct { int dbm_dirf; /* open directory file */ int dbm_pagf; /* open page file */ int dbm_flags; /* flags, see below */ long dbm_maxbno; /* last ``bit'' in dir file */ long dbm_bitno; /* current bit number */ long dbm_hmask; /* hash mask */ long dbm_blkptr; /* current block for dbm_nextkey */ int dbm_keyptr; /* current key for dbm_nextkey */ long dbm_blkno; /* current page to read/write */ long dbm_pagbno; /* current page in pagbuf */ char dbm_pagbuf[PBLKSIZ]; /* page file block buffer */ long dbm_dirbno; /* current block in dirbuf */ char dbm_dirbuf[DBLKSIZ]; /* directory file block buffer */ } DBM; #define _DBM_RDONLY 0x01 /* data base open read-only */ #define _DBM_IOERR 0x02 /* data base I/O error */ #define dbm_rdonly(db) ((db)->dbm_flags & _DBM_RDONLY) #define dbm_error(db) ((db)->dbm_flags & _DBM_IOERR) /* use this one at your own risk! */ #define dbm_clearerr(db) ((db)->dbm_flags &= ~_DBM_IOERR) /* for flock(2) and fstat(2) */ #define dbm_dirfno(db) ((db)->dbm_dirf) #define dbm_pagfno(db) ((db)->dbm_pagf) typedef struct { char *dptr; int dsize; } datum; /* * flags to dbm_store() */ #define DBM_INSERT 0 #define DBM_REPLACE 1 DBM *dbm_open(char *file, int flags, int mode); void dbm_close(DBM *db); datum dbm_fetch(register DBM *db, datum key); datum dbm_firstkey(DBM *db); datum dbm_nextkey(register DBM *db); long dbm_forder(register DBM *db, datum key); int dbm_delete(register DBM *db, datum key); int dbm_store(register DBM *db, datum key, datum dat, int replace); #endif /* NDBM_H */ singular-4.0.3+ds/Singular/links/pipeLink.cc000066400000000000000000000116571266270727000207550ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /*************************************************************** * File: pipeLink.h * Purpose: declaration of sl_link routines for pipe ***************************************************************/ #include #include #include #include "tok.h" #include "ipid.h" #include "subexpr.h" #include "links/silink.h" #include "lists.h" #include "pipeLink.h" #include #include #include #include #include #include #include /* for portability */ #include #include typedef struct { FILE *f_read; FILE *f_write; pid_t pid; /* only valid for fork/tcp mode*/ int fd_read,fd_write; /* only valid for fork/tcp mode*/ char level; } pipeInfo; //**************************************************************************/ BOOLEAN pipeOpen(si_link l, short flag, leftv /*u*/) { pipeInfo *d=(pipeInfo*)omAlloc0(sizeof(pipeInfo)); if (flag & SI_LINK_OPEN) { flag = SI_LINK_READ| SI_LINK_WRITE; } int pc[2]; int cp[2]; pipe(pc); pipe(cp); pid_t pid=fork(); if (pid==0) /*child*/ { /* close unnecessary pipe descriptors for a clean environment */ si_close(pc[1]); si_close(cp[0]); /* dup pipe read/write to stdin/stdout */ si_dup2( pc[0], STDIN_FILENO ); si_dup2( cp[1], STDOUT_FILENO ); int r=system(l->name); si_close(pc[0]); si_close(cp[1]); exit(r); /* never reached*/ } else if (pid>0) { d->pid=pid; si_close(pc[0]); si_close(cp[1]); d->f_read=fdopen(cp[0],"r"); d->fd_read=cp[0]; d->f_write=fdopen(pc[1],"w"); d->fd_write=pc[1]; SI_LINK_SET_RW_OPEN_P(l); } else { Werror("fork failed (%d)",errno); omFreeSize(d,sizeof(*d)); return TRUE; } l->data=d; return FALSE; } //**************************************************************************/ LINKAGE BOOLEAN pipeClose(si_link l) { pipeInfo *d = (pipeInfo *)l->data; if (d!=NULL) { if (d->f_read!=NULL) fclose(d->f_read); if (d->f_write!=NULL) fclose(d->f_write); if (d->pid!=0) { kill(d->pid,15); kill(d->pid,9); } } SI_LINK_SET_CLOSE_P(l); return FALSE; } //**************************************************************************/ LINKAGE BOOLEAN pipeKill(si_link l) { if(SI_LINK_OPEN_P(l)) pipeClose(l); pipeInfo *d = (pipeInfo *)l->data; if (d!=NULL) { omFreeSize((ADDRESS)d,(sizeof *d)); } l->data=NULL; return FALSE; } //**************************************************************************/ LINKAGE leftv pipeRead1(si_link l) { pipeInfo *d = (pipeInfo *)l->data; leftv res=(leftv)omAlloc0(sizeof(sleftv)); char *s=(char *)omAlloc0(1024); char *ss=fgets(s,1024,d->f_read); if (ss==NULL) { omFreeSize(s,1024); pipeClose(l);return NULL; } int i=strlen(s)-1; if ((i>=0) && (s[i]=='\n')) s[i]='\0'; res->rtyp=STRING_CMD; res->data=s; return res; } //**************************************************************************/ extern si_link pipeLastLink; LINKAGE BOOLEAN pipeWrite(si_link l, leftv data) { if(!SI_LINK_W_OPEN_P(l)) slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL); pipeInfo *d = (pipeInfo *)l->data; FILE *outfile=d->f_write;; BOOLEAN err=FALSE; char *s; pipeLastLink=l; while (data!=NULL) { s = data->String(); // free data ?? if (s!=NULL) { fprintf(outfile,"%s\n",s); omFree((ADDRESS)s); } else { Werror("cannot convert to string"); err=TRUE; } if (pipeLastLink==NULL) return TRUE; data = data->next; } fflush(outfile); pipeLastLink=NULL; return err; } const char* slStatusPipe(si_link l, const char* request) { pipeInfo *d=(pipeInfo*)l->data; if (d==NULL) return "not open"; if(strcmp(request, "read") == 0) { int s; if ((!SI_LINK_R_OPEN_P(l)) || (feof(d->f_read))) s=0; else { fd_set mask/*, fdmask*/; struct timeval wt; /* Don't block. Return socket status immediately. */ wt.tv_sec = 0; wt.tv_usec = 0; FD_ZERO(&mask); FD_SET(d->fd_read, &mask); //Print("test fd %d\n",d->fd_read); /* check with select: chars waiting: no -> not ready */ s=si_select(d->fd_read+1, &mask, NULL, NULL, &wt); } switch (s) { case 0: /* not ready */ return "not ready"; case -1: /*error*/ return "error"; default: /*1: ready ? */return "ready"; } } else if (strcmp(request, "write") == 0) { if (SI_LINK_W_OPEN_P(l)) return "ready"; return "not ready"; } return "unknown status request"; } si_link_extension slInitPipeExtension(si_link_extension s) { s->Open=pipeOpen; s->Close=pipeClose; s->Kill=pipeKill; s->Read=pipeRead1; s->Read2=(slRead2Proc)NULL; s->Write=pipeWrite; s->Status=slStatusPipe; s->type="pipe"; return s; } singular-4.0.3+ds/Singular/links/pipeLink.h000066400000000000000000000006711266270727000206110ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /*************************************************************** * File: pipeLink.h * Purpose: declaration of sl_link routines for pipe ***************************************************************/ #ifndef PIPELINK_H #define PIPELINK_H si_link_extension slInitPipeExtension(si_link_extension s); #endif singular-4.0.3+ds/Singular/links/semaphore.c000066400000000000000000000061331266270727000210130ustar00rootroot00000000000000 #include #ifdef HAVE_SIMPLEIPC #include #include #include #include #include #include #include #include # include "simpleipc.h" #include #include // Not yet implemented: SYSV IPC Semaphores // They are more difficult to clean up after a process crash // but are supported more widely. sem_t *semaphore[SIPC_MAX_SEMAPHORES]; int sem_acquired[SIPC_MAX_SEMAPHORES]; /* return 1 on success, * 0 if already initialized, * -1 for errors */ int sipc_semaphore_init(int id, int count) { char buf[100]; sem_t *sem; if ((id<0) || (id >= SIPC_MAX_SEMAPHORES)) return -1; // Already initialized? if (semaphore[id]) return 0; // to make it completely safe, we should generate a name // from /dev/urandom. #if USE_SEM_INIT // TODO: This should really use mapped memory so that processes // can keep using the semaphore after fork + exec. sem = malloc(sizeof(sem_t)); if (!sem) return -1; if (sem_init(sem, 1, count) < 0) { free(sem); return -1; } #else sprintf(buf, "/%d:sem%d", getpid(), id); sem_unlink(buf); sem = sem_open(buf, O_CREAT, 0600, count); #endif if (sem == SEM_FAILED || !sem) return -1; semaphore[id] = sem; #if !USE_SEM_INIT sem_unlink(buf); #endif return 1; } int sipc_semaphore_exists(int id) { if ((id<0) || (id >= SIPC_MAX_SEMAPHORES)) return -1; return semaphore[id] != NULL; } int sipc_semaphore_acquire(int id) { if ((id<0) || (id >= SIPC_MAX_SEMAPHORES) || (semaphore[id]==NULL)) return -1; defer_shutdown++; si_sem_wait(semaphore[id]); sem_acquired[id]++; defer_shutdown--; if (!defer_shutdown && do_shutdown) m2_end(1); return 1; } int sipc_semaphore_try_acquire(int id) { if ((id<0) || (id >= SIPC_MAX_SEMAPHORES) || (semaphore[id]==NULL)) return -1; defer_shutdown++; int trywait = si_sem_trywait(semaphore[id]); if (!trywait) { sem_acquired[id]++; } defer_shutdown--; if (!defer_shutdown && do_shutdown) m2_end(1); return !trywait; } int sipc_semaphore_release(int id) { if ((id<0) || (id >= SIPC_MAX_SEMAPHORES) || (semaphore[id]==NULL)) return -1; defer_shutdown++; sem_post(semaphore[id]); sem_acquired[id]--; defer_shutdown--; if (!defer_shutdown && do_shutdown) m2_end(1); return 1; } int sipc_semaphore_get_value(int id) { int val; if ((id<0) || (id >= SIPC_MAX_SEMAPHORES) || (semaphore[id]==NULL)) return -1; sem_getvalue(semaphore[id], &val); return val; } int simpleipc_cmd(char *cmd, int id, int v) { if (strcmp(cmd,"init")==0) return sipc_semaphore_init(id,v); else if (strcmp(cmd,"exists")==0) return sipc_semaphore_exists(id); else if (strcmp(cmd,"acquire")==0) return sipc_semaphore_acquire(id); else if (strcmp(cmd,"try_acquire")==0) return sipc_semaphore_try_acquire(id); else if (strcmp(cmd,"release")==0) return sipc_semaphore_release(id); else if (strcmp(cmd,"get_value")==0) return sipc_semaphore_get_value(id); else printf("unknown\n"); return -2; } #endif singular-4.0.3+ds/Singular/links/silink.cc000066400000000000000000000232101266270727000204570ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: general interface to links */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "feOpt.h" #include #include #include #include #include // #ifdef HAVE_DBM // #ifdef __CYGWIN__ // #define USE_GDBM // #endif // #endif omBin s_si_link_extension_bin = omGetSpecBin(sizeof(s_si_link_extension)); omBin sip_link_bin = omGetSpecBin(sizeof(sip_link)); omBin ip_link_bin = omGetSpecBin(sizeof(ip_link)); /* ====================================================================== */ static si_link_extension slTypeInit(si_link_extension s, const char* type); si_link_extension si_link_root=NULL; BOOLEAN slInit(si_link l, char *istr) { char *type = NULL, *mode = NULL, *name = NULL; int i = 0, j; // set mode and type if (istr != NULL) { // find the first colon char in istr i = 0; while (istr[i] != ':' && istr[i] != '\0') i++; if (istr[i] == ':') { // if found, set type if (i > 0) { istr[i] = '\0'; type = omStrDup(istr); istr[i] = ':'; } // and check for mode j = ++i; while (istr[j] != ' ' && istr[j] != '\0') j++; if (j > i) { mode = omStrDup(&(istr[i])); mode[j - i] = '\0'; } // and for the name while (istr[j] == ' '&& istr[j] != '\0') j++; if (istr[j] != '\0') name = omStrDup(&(istr[j])); } else // no colon find -- string is entire name { j=0; while (istr[j] == ' '&& istr[j] != '\0') j++; if (istr[j] != '\0') name = omStrDup(&(istr[j])); } } // set the link extension if (type != NULL) { si_link_extension s = si_link_root; si_link_extension prev = s; while (strcmp(s->type, type) != 0) { if (s->next == NULL) { prev = s; s = NULL; break; } else { s = s->next; } } if (s != NULL) l->m = s; else { l->m = slTypeInit(prev, type); } omFree(type); } else l->m = si_link_root; if (l->m == NULL) return TRUE; l->name = (name != NULL ? name : omStrDup("")); l->mode = (mode != NULL ? mode : omStrDup("")); l->ref = 1; return FALSE; } void slCleanUp(si_link l) { defer_shutdown++; (l->ref)--; if (l->ref == 0) { if (SI_LINK_OPEN_P(l)) { if (l->m->Close != NULL) l->m->Close(l); } if ((l->data != NULL) && (l->m->Kill != NULL)) l->m->Kill(l); omFree((ADDRESS)l->name); omFree((ADDRESS)l->mode); memset((void *) l, 0, sizeof(ip_link)); } defer_shutdown--; if (!defer_shutdown && do_shutdown) m2_end(1); } void slKill(si_link l) { defer_shutdown++; slCleanUp(l); if ((l!=NULL) &&(l->ref == 0)) omFreeBin((ADDRESS)l, ip_link_bin); defer_shutdown--; if (!defer_shutdown && do_shutdown) m2_end(1); } const char* slStatus(si_link l, const char *request) { if (l == NULL) return "empty link"; else if (l->m == NULL) return "unknown link type"; else if (strcmp(request, "type") == 0) return l->m->type; else if (strcmp(request, "mode") == 0) return l->mode; else if (strcmp(request, "name") == 0) return l->name; else if (strcmp(request, "exists") ==0) { struct stat buf; if (si_lstat(l->name,&buf)==0) return "yes"; else return "no"; } else if (strcmp(request, "open") == 0) { if (SI_LINK_OPEN_P(l)) return "yes"; else return "no"; } else if (strcmp(request, "openread") == 0) { if (SI_LINK_R_OPEN_P(l)) return "yes"; else return "no"; } else if (strcmp(request, "openwrite") == 0) { if (SI_LINK_W_OPEN_P(l)) return "yes"; else return "no"; } else if (l->m->Status == NULL) return "unknown status request"; else return l->m->Status(l, request); } //-------------------------------------------------------------------------- BOOLEAN slSetRingDummy(si_link, ring r, BOOLEAN send) { if (currRing!=r) rChangeCurrRing(r); return FALSE; } BOOLEAN slOpen(si_link l, short flag, leftv h) { BOOLEAN res = TRUE; if (l!=NULL) { if (l->m == NULL) slInit(l, ((char*)"")); if (feOptValue(FE_OPT_NO_SHELL)) {WerrorS("no links allowed");return TRUE;} const char *c="_";; if (h!=NULL) c=h->Name(); if (SI_LINK_OPEN_P(l)) { Warn("open: link of type: %s, mode: %s, name: %s is already open", l->m->type, l->mode, l->name); return FALSE; } else if (l->m->Open != NULL) { res = l->m->Open(l, flag, h); if (res) Werror("open: Error for link %s of type: %s, mode: %s, name: %s", c, l->m->type, l->mode, l->name); } if (l->m->SetRing==NULL) l->m->SetRing=slSetRingDummy; } return res; } BOOLEAN slPrepClose(si_link l) { if(! SI_LINK_OPEN_P(l)) return FALSE; BOOLEAN res = TRUE; if (l->m->PrepClose != NULL) { res = l->m->PrepClose(l); if (res) Werror("close: Error for link of type: %s, mode: %s, name: %s", l->m->type, l->mode, l->name); } return res; } BOOLEAN slClose(si_link l) { if(! SI_LINK_OPEN_P(l)) return FALSE; defer_shutdown++; BOOLEAN res = TRUE; if (l->m->Close != NULL) { res = l->m->Close(l); if (res) Werror("close: Error for link of type: %s, mode: %s, name: %s", l->m->type, l->mode, l->name); } defer_shutdown--; if (!defer_shutdown && do_shutdown) m2_end(1); return res; } leftv slRead(si_link l, leftv a) { leftv v = NULL; if( ! SI_LINK_R_OPEN_P(l)) // open r ? { #ifdef HAVE_DBM #ifdef USE_GDBM if (! SI_LINK_CLOSE_P(l)) { if (slClose(l)) return NULL; } #endif #endif if (slOpen(l, SI_LINK_READ,NULL)) return NULL; } if (SI_LINK_R_OPEN_P(l)) { // open r if (a==NULL) { if (l->m->Read != NULL) v = l->m->Read(l); } else { if (l->m->Read2 != NULL) v = l->m->Read2(l,a); } } else { Werror("read: Error to open link of type %s, mode: %s, name: %s for reading", l->m->type, l->mode, l->name); return NULL; } // here comes the eval: if (v != NULL) { if (v->Eval() && !errorreported) WerrorS("eval: failed"); } else Werror("read: Error for link of type %s, mode: %s, name: %s", l->m->type, l->mode, l->name); return v; } BOOLEAN slWrite(si_link l, leftv v) { BOOLEAN res; if(! SI_LINK_W_OPEN_P(l)) // open w ? { #ifdef HAVE_DBM #ifdef USE_GDBM if (! SI_LINK_CLOSE_P(l)) { if (slClose(l)) return TRUE; } #endif #endif if (slOpen(l, SI_LINK_WRITE,NULL)) return TRUE; } if (SI_LINK_W_OPEN_P(l)) { // now open w if (l->m->Write != NULL) res = l->m->Write(l,v); else res = TRUE; if (res) Werror("write: Error for link of type %s, mode: %s, name: %s", l->m->type, l->mode, l->name); return res; } else { Werror("write: Error to open link of type %s, mode: %s, name: %s for writing", l->m->type, l->mode, l->name); return TRUE; } } BOOLEAN slDump(si_link l) { BOOLEAN res; if(! SI_LINK_W_OPEN_P(l)) // open w ? { if (slOpen(l, SI_LINK_WRITE,NULL)) return TRUE; } if(SI_LINK_W_OPEN_P(l)) { // now open w if (l->m->Dump != NULL) res = l->m->Dump(l); else res = TRUE; if (res) Werror("dump: Error for link of type %s, mode: %s, name: %s", l->m->type, l->mode, l->name); if (!SI_LINK_R_OPEN_P(l)) slClose(l); // do not close r/w links return res; } else { Werror("dump: Error to open link of type %s, mode: %s, name: %s for writing", l->m->type, l->mode, l->name); return TRUE; } } BOOLEAN slGetDump(si_link l) { BOOLEAN res; if(! SI_LINK_R_OPEN_P(l)) // open r ? { if (slOpen(l, SI_LINK_READ,NULL)) return TRUE; } if(SI_LINK_R_OPEN_P(l)) { // now open r if (l->m->GetDump != NULL) res = l->m->GetDump(l); else res = TRUE; if (res) Werror("getdump: Error for link of type %s, mode: %s, name: %s", l->m->type, l->mode, l->name); //res|=slClose(l); return res; } else { Werror("dump: Error open link of type %s, mode: %s, name: %s for reading", l->m->type, l->mode, l->name); return TRUE; } } /*------------Initialization at Start-up time------------------------*/ #include static si_link_extension slTypeInit(si_link_extension s, const char* type) { assume(s != NULL); s->next = NULL; si_link_extension ns = (si_link_extension)omAlloc0Bin(s_si_link_extension_bin); if (0) ; // dummy #ifdef HAVE_DBM else if (strcmp(type, "DBM") == 0) s->next = slInitDBMExtension(ns); #endif #if 1 else if (strcmp(type, "ssi") == 0) s->next = slInitSsiExtension(ns); #endif #if 1 else if (strcmp(type, "|") == 0) s->next = slInitPipeExtension(ns); #endif else { Warn("Found unknown link type: %s", type); Warn("Use default link type: %s", si_link_root->type); omFreeBin(ns, s_si_link_extension_bin); return si_link_root; } if (s->next == NULL) { Werror("Can not initialize link type %s", type); omFreeBin(ns, s_si_link_extension_bin); return NULL; } return s->next; } singular-4.0.3+ds/Singular/links/silink.h000066400000000000000000000067411266270727000203330ustar00rootroot00000000000000#ifndef SILINK_H #define SILINK_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: general interface to links */ #include #include #include #include #include struct sip_link; typedef struct sip_link ip_link; typedef ip_link * si_link; // extension links: typedef BOOLEAN (*slOpenProc)(si_link l, short flag, leftv h); typedef BOOLEAN (*slWriteProc)(si_link l, leftv lv); typedef BOOLEAN (*slCloseProc)(si_link l); typedef BOOLEAN (*slPrepCloseProc)(si_link l); typedef BOOLEAN (*slKillProc)(si_link l); typedef leftv (*slReadProc)(si_link l); typedef leftv (*slRead2Proc)(si_link l, leftv a); typedef BOOLEAN (*slDumpProc)(si_link l); typedef BOOLEAN (*slGetDumpProc)(si_link l); typedef const char* (*slStatusProc)(si_link l, const char *request); typedef BOOLEAN (*slSetRingProc)(si_link l, ring r, BOOLEAN send); struct s_si_link_extension { si_link_extension next; slOpenProc Open; slCloseProc Close; slPrepCloseProc PrepClose; slKillProc Kill; slReadProc Read; slRead2Proc Read2; slWriteProc Write; slDumpProc Dump; slGetDumpProc GetDump; slStatusProc Status; slSetRingProc SetRing; const char *type; }; struct sip_link { si_link_extension m; // methods char *mode; char *name; // used for filename and/or further specs void *data; // the link itself BITSET flags; // 0=close open = 1: read = 2: write = 3 short ref; // reference counter }; // flags: #define SI_LINK_CLOSE 0 #define SI_LINK_OPEN 1 #define SI_LINK_READ 2 #define SI_LINK_WRITE 4 // tests: #define SI_LINK_CLOSE_P(l) (!(l)->flags) #define SI_LINK_OPEN_P(l) ((l)->flags & SI_LINK_OPEN) #define SI_LINK_W_OPEN_P(l) ((l)->flags & SI_LINK_WRITE) #define SI_LINK_R_OPEN_P(l) ((l)->flags & SI_LINK_READ) #define SI_LINK_RW_OPEN_P(l) (SI_LINK_W_OPEN_P(l) && SI_LINK_R_OPEN_P(l)) #define SI_LINK_SET_CLOSE_P(l) ((l)->flags = SI_LINK_CLOSE) #define SI_LINK_SET_OPEN_P(l, flag) ((l)->flags |= SI_LINK_OPEN |flag) #define SI_LINK_SET_W_OPEN_P(l) ((l)->flags |= (SI_LINK_OPEN | SI_LINK_WRITE)) #define SI_LINK_SET_R_OPEN_P(l) ((l)->flags |= (SI_LINK_OPEN | SI_LINK_READ)) #define SI_LINK_SET_RW_OPEN_P(l) ((l)->flags |= (SI_LINK_OPEN | SI_LINK_READ | SI_LINK_WRITE)) BOOLEAN slOpen(si_link l, short flag, leftv h); BOOLEAN slClose(si_link l); BOOLEAN slPrepClose(si_link l); leftv slRead(si_link l,leftv a=NULL); BOOLEAN slWrite(si_link l, leftv v); BOOLEAN slDump(si_link l); BOOLEAN slGetDump(si_link l); const char* slStatus(si_link l, const char *request); BOOLEAN slInit(si_link l, char *str); void slKill(si_link l); void slCleanUp(si_link l); void slStandardInit(); inline si_link slCopy(si_link l) { l->ref++; return l; } #include inline char* slString(si_link l) { if (l->name != NULL) { return omStrDup(l->name); } else { return omStrDup(""); } } extern omBin s_si_link_extension_bin; extern omBin sip_link_bin; extern omBin ip_link_bin; int slStatusSsiL(lists L, int timeout); int ssiBatch(const char *host, const char * port); typedef struct { leftv u; si_link l; void * next; } link_struct; typedef link_struct* link_list; extern link_list ssiToBeClosed; extern volatile BOOLEAN ssiToBeClosed_inactive; #endif // SILINK_H singular-4.0.3+ds/Singular/links/simpleipc.h000066400000000000000000000010661266270727000210220ustar00rootroot00000000000000#include #ifndef _SIMPLEIPC_H #define _SIMPLEIPC_H #ifdef __cplusplus extern "C" { #endif #define SIPC_MAX_SEMAPHORES 256 #define USE_SEM_INIT 0 extern sem_t *semaphore[SIPC_MAX_SEMAPHORES]; extern int sem_acquired[SIPC_MAX_SEMAPHORES]; int sipc_semaphore_init(int id, int count); int sipc_semaphore_exists(int id); int sipc_semaphore_acquire(int id); int sipc_semaphore_try_acquire(int id); int sipc_semaphore_get_value(int id); int sipc_semaphore_release(int id); int simpleipc_cmd(char *cmd, int id, int v); #ifdef __cplusplus } #endif #endif singular-4.0.3+ds/Singular/links/sing_dbm.cc000066400000000000000000000261031266270727000207540ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ //**************************************************************************/ // 'sing_dbm.cc' containes command to handle dbm-files under // Singular. // //**************************************************************************/ #include # include # include # include #ifdef HAVE_DBM # include # include # include # include # include // #ifdef __CYGWIN__ // # define USE_GDBM // # define BLOCKSIZE 1 // # define GDBM_STATIC // # include // #endif #ifdef USE_GDBM typedef struct { GDBM_FILE db; // pointer to open database int first; // firstkey to look for? datum actual; // the actual key } GDBM_info; //**************************************************************************/ LINKAGE BOOLEAN dbOpen(si_link l, short flag, leftv u) { char *mode = "r"; GDBM_info *db; datum d_key; // int dbm_flags = O_RDONLY | O_CREAT; // open database readonly as default int read_write= GDBM_READER; if(flag & SI_LINK_WRITE) { // if((l->mode==NULL) // || ((l->mode[0]!='w')&&(l->mode[1]!='w'))) // { // // request w- open, but mode is not "w" nor "rw" => fail // return TRUE; // } // dbm_flags = O_RDWR | O_CREAT; read_write = GDBM_WRCREAT | GDBM_NOLOCK; mode = "rw"; } if(flag & SI_LINK_READ) { if (strcmp(l->mode,"rw")==0) mode="rw"; } //if (((db = (DBM_info *)omAlloc(sizeof *db)) != NULL) //&&((db->db = dbm_open(l->name, dbm_flags, 0664 )) != NULL )) db = (GDBM_info *)omAlloc0(sizeof *db); if((db->db = gdbm_open(l->name, BLOCKSIZE, read_write, 0664, 0)) != NULL ) { // if (db->first) // first created? // { // db->actual=gdbm_firstkey(db->db); // } // else // { // d_key=db->actual; // if (d_key.dptr!=NULL) // { // db->actual=gdbm_nextkey(db->db,db->actual); // } // else { db->actual=gdbm_firstkey(db->db); } // } db->first=1; if(flag & SI_LINK_WRITE) SI_LINK_SET_W_OPEN_P(l); else SI_LINK_SET_R_OPEN_P(l); l->data=(void *)(db); omFree(l->mode); l->mode=omStrDup(mode); return FALSE; } Print("%d/%s",gdbm_errno,gdbm_strerror(gdbm_errno)); return TRUE; } //**************************************************************************/ LINKAGE BOOLEAN dbClose(si_link l) { GDBM_info *db = (GDBM_info *)l->data; gdbm_sync(db->db); gdbm_close(db->db); omFreeSize((ADDRESS)db,(sizeof *db)); l->data=NULL; SI_LINK_SET_CLOSE_P(l); return FALSE; } //**************************************************************************/ static datum d_value; LINKAGE leftv dbRead2(si_link l, leftv key) { GDBM_info *db = (GDBM_info *)l->data; // GDBM_info *db; // db = (GDBM_info *)omAlloc0(sizeof *db); // db = (GDBM_info *)l->data; leftv v=NULL; datum d_key; int flag; if (!SI_LINK_R_OPEN_P(l)) //exceptions // if (strcmp(l->mode,"rw")==0) //rw-mode { if (!SI_LINK_CLOSE_P(l)) { if (!dbClose(l)) {Print("cannot close link!\n");} } //(SI_LINK_CLOSE_P(l)) automatically if (dbOpen(l, SI_LINK_READ)) return NULL; } if (SI_LINK_RW_OPEN_P(l)) {Print("I/O Error!\n");} if(key!=NULL) { if (key->Typ()==STRING_CMD) { d_key.dptr = (char*)key->Data(); d_key.dsize = strlen(d_key.dptr)+1; d_value = gdbm_fetch(db->db, d_key); v=(leftv)omAlloc0Bin(sleftv_bin); if (d_value.dptr!=NULL) v->data=omStrDup(d_value.dptr); else v->data=omStrDup(""); v->rtyp=STRING_CMD; } else { WerrorS("read(`GDBM link`,`string`) expected"); } } else { if (db->first) { db->first=0; d_key = gdbm_firstkey(db->db); // db->actual=d_key; // Print("firstkey:%s\n",d_key.dptr); } else { if (db->actual.dptr==NULL) { db->actual=gdbm_firstkey(db->db); } d_key = gdbm_nextkey(db->db,db->actual); db->actual=d_key; if (d_key.dptr==NULL) { db->first=1; // Print("nextkey:NULL\n"); } // else // Print("nextkey:%s\n",d_key.dptr); } if (d_key.dptr!=NULL) d_value = gdbm_fetch(db->db, d_key); else d_value.dptr=NULL; v=(leftv)omAlloc0Bin(sleftv_bin); v->rtyp=STRING_CMD; if (d_value.dptr!=NULL) { v->data=omStrDup(d_key.dptr); db->first = 0; } else { v->data=omStrDup(""); // db->first = 1; } } return v; } LINKAGE leftv dbRead1(si_link l) { return dbRead2(l,NULL); } //**************************************************************************/ LINKAGE BOOLEAN dbWrite(si_link l, leftv key) { GDBM_info *db = (GDBM_info *)l->data; // GDBM_info *db; // db = (GDBM_info *)omAlloc0(sizeof *db); // db = (GDBM_info *)l->data; BOOLEAN b=TRUE; register int ret; if (strcmp(l->mode,"rw")!=0) // r-mode { Print("Write error on readonly source\n"); } else //rw-mode { if (!SI_LINK_W_OPEN_P(l)) //exceptions { if (!SI_LINK_CLOSE_P(l)) { if (!dbClose(l)) {Print("close error\n");}; } if (!dbOpen(l,SI_LINK_WRITE)) {Print("open_for_write error\n");} } } if((key!=NULL) && (key->Typ()==STRING_CMD) ) { if (key->next!=NULL) // have a second parameter ? { if(key->next->Typ()==STRING_CMD) // replace (key,value) { datum d_key, d_value; d_key.dptr = (char *)key->Data(); d_key.dsize = strlen(d_key.dptr)+1; d_value.dptr = (char *)key->next->Data(); d_value.dsize = strlen(d_value.dptr)+1; ret = gdbm_store(db->db, d_key, d_value, GDBM_REPLACE); // db->actual=d_key; if (ret==-1) {Print("reader calls gdbm_store!");} if (ret==0) { b=FALSE; } else { // if(gdbm_error(db->db)) if (gdbm_errno != 0) { Werror("GDBM link I/O error: '%s' ", gdbm_errno); // Print(gdbm_strerror(gdbm_errno)); //dbm_clearerr(db->db); // gdbm_errno=0; } } } } else { // delete (key) datum d_key; d_key.dptr = (char *)key->Data(); d_key.dsize = strlen(d_key.dptr)+1; // db->actual=gdbm_nextkey(db->db,d_key); gdbm_delete(db->db, d_key); b=FALSE; } } else { WerrorS("write(`GDBM link`,`key string` [,`data string`]) expected"); } gdbm_sync(db->db); return b; } #endif /* USE_GDBM */ #ifndef USE_GDBM /* These are the routines in dbm. */ # include "ndbm.h" typedef struct { DBM *db; // pointer to open database int first; // firstkey to look for? } DBM_info; //**************************************************************************/ LINKAGE BOOLEAN dbOpen(si_link l, short flag, leftv /*u*/) { const char *mode = "r"; DBM_info *db; int dbm_flags = O_RDONLY | O_CREAT; // open database readonly as default if((l->mode!=NULL) && ((l->mode[0]=='w')||(l->mode[1]=='w'))) { dbm_flags = O_RDWR | O_CREAT; mode = "rw"; flag|=SI_LINK_WRITE|SI_LINK_READ; } else if(flag & SI_LINK_WRITE) { // request w- open, but mode is not "w" nor "rw" => fail return TRUE; } //if (((db = (DBM_info *)omAlloc(sizeof *db)) != NULL) //&&((db->db = dbm_open(l->name, dbm_flags, 0664 )) != NULL )) db = (DBM_info *)omAlloc(sizeof *db); if((db->db = dbm_open(l->name, dbm_flags, 0664 )) != NULL ) { db->first=1; if(flag & SI_LINK_WRITE) SI_LINK_SET_RW_OPEN_P(l); else SI_LINK_SET_R_OPEN_P(l); l->data=(void *)(db); omFree(l->mode); l->mode=omStrDup(mode); return FALSE; } return TRUE; } //**************************************************************************/ LINKAGE BOOLEAN dbClose(si_link l) { DBM_info *db = (DBM_info *)l->data; dbm_close(db->db); omFreeSize((ADDRESS)db,(sizeof *db)); l->data=NULL; SI_LINK_SET_CLOSE_P(l); return FALSE; } //**************************************************************************/ static datum d_value; LINKAGE leftv dbRead2(si_link l, leftv key) { DBM_info *db = (DBM_info *)l->data; leftv v=NULL; datum d_key; if(key!=NULL) { if (key->Typ()==STRING_CMD) { d_key.dptr = (char*)key->Data(); d_key.dsize = strlen(d_key.dptr)+1; d_value = dbm_fetch(db->db, d_key); v=(leftv)omAlloc0Bin(sleftv_bin); if (d_value.dptr!=NULL) v->data=omStrDup(d_value.dptr); else v->data=omStrDup(""); v->rtyp=STRING_CMD; } else { WerrorS("read(`DBM link`,`string`) expected"); } } else { if(db->first) d_value = dbm_firstkey((DBM *)db->db); else d_value = dbm_nextkey((DBM *)db->db); v=(leftv)omAlloc0Bin(sleftv_bin); v->rtyp=STRING_CMD; if (d_value.dptr!=NULL) { v->data=omStrDup(d_value.dptr); db->first = 0; } else { v->data=omStrDup(""); db->first = 1; } } return v; } LINKAGE leftv dbRead1(si_link l) { return dbRead2(l,NULL); } //**************************************************************************/ LINKAGE BOOLEAN dbWrite(si_link l, leftv key) { DBM_info *db = (DBM_info *)l->data; BOOLEAN b=TRUE; register int ret; // database is opened if((key!=NULL) && (key->Typ()==STRING_CMD) ) { if (key->next!=NULL) // have a second parameter ? { if(key->next->Typ()==STRING_CMD) // replace (key,value) { datum d_key, d_value; d_key.dptr = (char *)key->Data(); d_key.dsize = strlen(d_key.dptr)+1; d_value.dptr = (char *)key->next->Data(); d_value.dsize = strlen(d_value.dptr)+1; ret = dbm_store(db->db, d_key, d_value, DBM_REPLACE); if(!ret ) b=FALSE; else { if(dbm_error(db->db)) { Werror("DBM link I/O error. Is '%s' readonly?", l->name); dbm_clearerr(db->db); } } } } else { // delete (key) datum d_key; d_key.dptr = (char *)key->Data(); d_key.dsize = strlen(d_key.dptr)+1; dbm_delete(db->db, d_key); b=FALSE; } } else { WerrorS("write(`DBM link`,`key string` [,`data string`]) expected"); } return b; } //**************************************************************************/ //char *dbStatus(si_link l, char *request) //{ // if (strcmp(request, "read") == 0) // { // if (SI_LINK_R_OPEN_P(l)) // return "ready"; // else // return "not ready"; // } // else if (strcmp(request, "write") == 0) // { // if (SI_LINK_W_OPEN_P(l)) // return "ready"; // else // return "not ready"; // } // else return "unknown status request"; //} //**************************************************************************/ #endif /* USE_GDBM */ #endif /* HAVE_DBM */ singular-4.0.3+ds/Singular/links/sing_dbm.h000066400000000000000000000005441266270727000206170ustar00rootroot00000000000000#ifndef SING_DBM_H #define SING_DBM_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: interface to DBM links */ struct s_si_link_extension; typedef struct s_si_link_extension *si_link_extension; si_link_extension slInitDBMExtension(si_link_extension s); #endif singular-4.0.3+ds/Singular/links/slInit.h000066400000000000000000000011721266270727000202750ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /*************************************************************** * File: slInit.h * Purpose: declarations of link initialization functions * Author: obachman (Olaf Bachmann) * Created: 12/00 *******************************************************************/ #ifndef SL_INIT_H #define SL_INIT_H #include #ifdef HAVE_DBM si_link_extension slInitDBMExtension(si_link_extension s); #endif const char* slStatusAscii(si_link l,const char* request); #endif // SL_INIT_H singular-4.0.3+ds/Singular/links/slInit_Dynamic.cc000066400000000000000000000025411266270727000221000ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /*************************************************************** * File: slInit_Dynamic.cc * Purpose: link initialization for dynamic linking * Author: obachman (Olaf Bachmann) * Created: 12/00 *******************************************************************/ #include #include #include #include #ifdef HAVE_DL #ifdef HAVE_DBM #include "dbm_sl.h" static void* dbm_so_handle = NULL; static void* slInitDBMHandle() { if (dbm_so_handle == NULL) dbm_so_handle = dynl_open_binary_warn("dbmsr"); return dbm_so_handle; } si_link_extension slInitDBMExtension(si_link_extension s) { void* handle = slInitDBMHandle(); if (handle == NULL) return NULL; s->Open=(slOpenProc)dynl_sym_warn(handle, "dbOpen"); s->Close=(slCloseProc)dynl_sym_warn(handle, "dbClose"); s->Kill=NULL; s->Read=(slReadProc)dynl_sym_warn(handle, "dbRead1"); s->Read2=(slRead2Proc)dynl_sym_warn(handle, "dbRead2"); s->Write=(slWriteProc)dynl_sym_warn(handle, "dbWrite"); if (s->Open == NULL || s->Close == NULL || s->Read == NULL || s->Read2 == NULL) return NULL; s->Status=slStatusAscii; s->type="DBM"; return s; } #endif #endif singular-4.0.3+ds/Singular/links/slInit_Static.cc000066400000000000000000000015741266270727000217500ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /*************************************************************** * File: slInit_Static.cc * Purpose: link initialization for static linking * Author: obachman (Olaf Bachmann) * Created: 12/00 *******************************************************************/ #include #include #include #ifdef HAVE_DBM # ifndef USE_GDBM # include # else # include #endif si_link_extension slInitDBMExtension(si_link_extension s) { s->Open=dbOpen; s->Close=dbClose; s->Kill=dbClose; s->Read=dbRead1; s->Read2=dbRead2; s->Write=dbWrite; s->Status=slStatusAscii; s->type="DBM"; return s; } #endif /* #ifdef HAVE_DBM */ singular-4.0.3+ds/Singular/links/ssiLink.cc000066400000000000000000001520651266270727000206150ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /*************************************************************** * File: ssiLink.h * Purpose: declaration of sl_link routines for ssi ***************************************************************/ #define TRANSEXT_PRIVATES 1 /* allow access to transext internals */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SIMPLEIPC #include #endif #include #include #include #include #include #include #include /* for portability */ #include #include #include #include /*for isdigit*/ #include #include #include #define SSI_VERSION 9 // 5->6: changed newstruct representation // 6->7: attributes // 7->8: qring // 8->9: module: added rank #define SSI_BASE 16 typedef struct { s_buff f_read; FILE *f_write; ring r; pid_t pid; /* only valid for fork/tcp mode*/ int fd_read,fd_write; /* only valid for fork/tcp mode*/ char level; char send_quit_at_exit; char quit_sent; } ssiInfo; link_list ssiToBeClosed=NULL; volatile BOOLEAN ssiToBeClosed_inactive=TRUE; // forward declarations: void ssiWritePoly_R(const ssiInfo *d, int typ, poly p, const ring r); void ssiWriteIdeal(const ssiInfo *d, int typ,ideal I); poly ssiReadPoly_R(const ssiInfo *D, const ring r); ideal ssiReadIdeal_R(const ssiInfo *d,const ring r); // the helper functions: void ssiSetCurrRing(const ring r) { // if (currRing!=NULL) // Print("need to change the ring, currRing:%s, switch to: ssiRing%d\n",IDID(currRingHdl),nr); // else // Print("no ring, switch to ssiRing%d\n",nr); if (!rEqual(r,currRing,1)) { char name[20]; int nr=0; do { sprintf(name,"ssiRing%d",nr); nr++; } while(IDROOT->get(name, 0)!=NULL); idhdl h=enterid(omStrDup(name),0,RING_CMD,&IDROOT,FALSE); IDRING(h)=r; r->ref++; rSetHdl(h); } } // the implementation of the functions: void ssiWriteInt(const ssiInfo *d,const int i) { fprintf(d->f_write,"%d ",i); //if (d->f_debug!=NULL) fprintf(d->f_debug,"int: %d ",i); } void ssiWriteString(const ssiInfo *d,const char *s) { fprintf(d->f_write,"%d %s ",(int)strlen(s),s); //if (d->f_debug!=NULL) fprintf(d->f_debug,"stringi: %d \"%s\" ",strlen(s),s); } void ssiWriteBigInt(const ssiInfo *d, const number n) { n_WriteFd(n,d->f_write,coeffs_BIGINT); } void ssiWriteNumber_CF(const ssiInfo *d, const number n, const coeffs cf) { // syntax is as follows: // case 1 Z/p: 3 // case 2 Q: 3 4 // or 3 0 // or 3 1 dto. // or 3 3 // or 3 5 // or 3 6 // or 3 8 if (getCoeffType(cf)==n_transExt) { fraction f=(fraction)n; ssiWritePoly_R(d,POLY_CMD,NUM(f),cf->extRing); ssiWritePoly_R(d,POLY_CMD,DEN(f),cf->extRing); } else if (getCoeffType(cf)==n_algExt) { ssiWritePoly_R(d,POLY_CMD,(poly)n,cf->extRing); } else if (cf->cfWriteFd!=NULL) { n_WriteFd(n,d->f_write,cf); } else WerrorS("coeff field not implemented"); } void ssiWriteNumber(const ssiInfo *d, const number n) { ssiWriteNumber_CF(d,n,d->r->cf); } void ssiWriteRing_R(ssiInfo *d,const ring r) { /* 5 ... .... */ /* ch=-1: transext, coeff ring follows */ /* ch=-2: algext, coeff ring and minpoly follows */ if (r!=NULL) { if (rField_is_Q(r) || rField_is_Zp(r)) fprintf(d->f_write,"%d %d ",n_GetChar(r->cf),r->N); else if (rFieldType(r)==n_transExt) fprintf(d->f_write,"-1 %d ",r->N); else if (rFieldType(r)==n_algExt) fprintf(d->f_write,"-2 %d ",r->N); else /*dummy*/ fprintf(d->f_write,"0 %d ",r->N); int i; for(i=0;iN;i++) { fprintf(d->f_write,"%d %s ",(int)strlen(r->names[i]),r->names[i]); } /* number of orderings:*/ i=0; // remember dummy ring: everything 0: if (r->order!=NULL) while (r->order[i]!=0) i++; fprintf(d->f_write,"%d ",i); /* each ordering block: */ i=0; if (r->order!=NULL) while(r->order[i]!=0) { fprintf(d->f_write,"%d %d %d ",r->order[i],r->block0[i], r->block1[i]); switch(r->order[i]) { case ringorder_a: case ringorder_wp: case ringorder_Wp: case ringorder_ws: case ringorder_Ws: case ringorder_aa: { int ii; for(ii=r->block0[i];ii<=r->block1[i];ii++) fprintf(d->f_write,"%d ",r->wvhdl[i][ii-r->block0[i]]); } break; case ringorder_a64: case ringorder_M: case ringorder_L: case ringorder_IS: Werror("ring oder not implemented for ssi:%d",r->order[i]); break; default: break; } i++; } if ((rFieldType(r)==n_transExt) || (rFieldType(r)==n_algExt)) { ssiWriteRing_R(d,r->cf->extRing); if (rFieldType(r)==n_algExt) { ssiWritePoly_R(d,POLY_CMD,r->cf->extRing->qideal->m[0],r->cf->extRing); } } /* Q-ideal :*/ if (r->qideal!=NULL) { ssiWriteIdeal(d,IDEAL_CMD,r->qideal); } else { fprintf(d->f_write,"0 "/*ideal with 0 entries */); } } else /* dummy ring r==NULL*/ { fprintf(d->f_write,"0 0 0 0 "/*,r->ch,r->N, blocks, q-ideal*/); } } void ssiWriteRing(ssiInfo *d,const ring r) { /* 5 ... .... */ /* ch=-1: transext, coeff ring follows */ /* ch=-2: algext, coeff ring and minpoly follows */ if (r==currRing) // see recursive calls for transExt/algExt { if (d->r!=NULL) rKill(d->r); d->r=r; } if (r!=NULL) { /*d->*/r->ref++; } ssiWriteRing_R(d,r); } void ssiWritePoly_R(const ssiInfo *d, int typ, poly p, const ring r) { fprintf(d->f_write,"%d ",pLength(p));//number of terms while(p!=NULL) { ssiWriteNumber_CF(d,pGetCoeff(p),r->cf); //nWrite(fich,pGetCoeff(p)); fprintf(d->f_write,"%ld ",p_GetComp(p,r));//component for(int j=1;j<=rVar(r);j++) { fprintf(d->f_write,"%ld ",p_GetExp(p,j,r ));//x^j } pIter(p); } } void ssiWritePoly(const ssiInfo *d, int typ, poly p) { ssiWritePoly_R(d,typ,p,d->r); } void ssiWriteIdeal(const ssiInfo *d, int typ,ideal I) { // syntax: 7 # of elements ..... // syntax: 8 ..... matrix M=(matrix)I; int mn; if (typ==MATRIX_CMD) { mn=MATROWS(M)*MATCOLS(M); fprintf(d->f_write,"%d %d ", MATROWS(M),MATCOLS(M)); } else { mn=IDELEMS(I); fprintf(d->f_write,"%d ",IDELEMS(I)); } int i; int tt; if (typ==MODUL_CMD) tt=VECTOR_CMD; else tt=POLY_CMD; for(i=0;im[i]); } } void ssiWriteCommand(si_link l, command D) { ssiInfo *d=(ssiInfo*)l->data; // syntax: .... fprintf(d->f_write,"%d %d ",D->argc,D->op); if (D->argc >0) ssiWrite(l, &(D->arg1)); if (D->argc < 4) { if (D->argc >1) ssiWrite(l, &(D->arg2)); if (D->argc >2) ssiWrite(l, &(D->arg3)); } } void ssiWriteProc(const ssiInfo *d,procinfov p) { if (p->data.s.body==NULL) iiGetLibProcBuffer(p); if (p->data.s.body!=NULL) ssiWriteString(d,p->data.s.body); else ssiWriteString(d,""); } void ssiWriteList(si_link l,lists dd) { ssiInfo *d=(ssiInfo*)l->data; int Ll=lSize(dd); fprintf(d->f_write,"%d ",Ll+1); int i; for(i=0;i<=Ll;i++) { ssiWrite(l,&(dd->m[i])); } } void ssiWriteIntvec(const ssiInfo *d,intvec * v) { fprintf(d->f_write,"%d ",v->length()); int i; for(i=0;ilength();i++) { fprintf(d->f_write,"%d ",(*v)[i]); } } void ssiWriteIntmat(const ssiInfo *d,intvec * v) { fprintf(d->f_write,"%d %d ",v->rows(),v->cols()); int i; for(i=0;ilength();i++) { fprintf(d->f_write,"%d ",(*v)[i]); } } void ssiWriteBigintmat(const ssiInfo *d,bigintmat * v) { fprintf(d->f_write,"%d %d ",v->rows(),v->cols()); int i; for(i=0;ilength();i++) { ssiWriteBigInt(d,(*v)[i]); } } char *ssiReadString(const ssiInfo *d) { char *buf; int l; l=s_readint(d->f_read); buf=(char*)omAlloc0(l+1); int c =s_getc(d->f_read); /* skip ' '*/ int ll=s_readbytes(buf,l,d->f_read); //if (ll!=l) printf("want %d, got %d bytes\n",l,ll); buf[l]='\0'; return buf; } int ssiReadInt(s_buff fich) { return s_readint(fich); } number ssiReadNumber_CF(const ssiInfo *d, const coeffs cf) { if (cf->cfReadFd!=NULL) { return n_ReadFd(d->f_read,cf); } else if (getCoeffType(cf) == n_transExt) { // poly poly fraction f=(fraction)n_Init(1,cf); p_Delete(&NUM(f),cf->extRing); NUM(f)=ssiReadPoly_R(d,cf->extRing); DEN(f)=ssiReadPoly_R(d,cf->extRing); return (number)f; } else if (getCoeffType(cf) == n_algExt) { // poly return (number)ssiReadPoly_R(d,cf->extRing); } else Werror("coeffs not implemented in ssiReadNumber"); return NULL; } number ssiReadBigInt(const ssiInfo *d) { number n=ssiReadNumber_CF(d,coeffs_BIGINT); if ((SR_HDL(n) & SR_INT)==0) { if (n->s!=3) Werror("invalid sub type in bigint:%d",n->s); } return n; } number ssiReadNumber(const ssiInfo *d) { return ssiReadNumber_CF(d,d->r->cf); } ring ssiReadRing(const ssiInfo *d) { /* syntax is ... .... */ int ch, N,i; char **names; ch=s_readint(d->f_read); N=s_readint(d->f_read); if (N!=0) { names=(char**)omAlloc(N*sizeof(char*)); for(i=0;if_read); int *ord=(int *)omAlloc0((num_ord+1)*sizeof(int)); int *block0=(int *)omAlloc0((num_ord+1)*sizeof(int)); int *block1=(int *)omAlloc0((num_ord+1)*sizeof(int)); int **wvhdl=(int**)omAlloc0((num_ord+1)*sizeof(int*)); for(i=0;if_read); block0[i]=s_readint(d->f_read); block1[i]=s_readint(d->f_read); switch(ord[i]) { case ringorder_a: case ringorder_wp: case ringorder_Wp: case ringorder_ws: case ringorder_Ws: case ringorder_aa: { wvhdl[i]=(int*)omAlloc((block1[i]-block0[i]+1)*sizeof(int)); int ii; for(ii=block0[i];ii<=block1[i];ii++) wvhdl[i][ii-block0[i]]=s_readint(d->f_read); } break; case ringorder_a64: case ringorder_M: case ringorder_L: case ringorder_IS: Werror("ring oder not implemented for ssi:%d",ord[i]); break; default: break; } } if (N==0) { omFree(ord); omFree(block0); omFree(block1); omFree(wvhdl); return NULL; } else { ring r=NULL; if (ch>=0) /* Q, Z/p */ r=rDefault(ch,N,names,num_ord,ord,block0,block1,wvhdl); else if (ch==-1) /* trans ext. */ { TransExtInfo T; T.r=ssiReadRing(d); coeffs cf=nInitChar(n_transExt,&T); r=rDefault(cf,N,names,num_ord,ord,block0,block1,wvhdl); } else if (ch==-2) /* alg ext. */ { TransExtInfo T; T.r=ssiReadRing(d); T.r->qideal=idInit(1,1); T.r->qideal->m[0]=ssiReadPoly_R(d,T.r); coeffs cf=nInitChar(n_algExt,&T); r=rDefault(cf,N,names,num_ord,ord,block0,block1,wvhdl); } else { Werror("ssi: read unknown coeffs type (%d)",ch); return NULL; } ideal q=ssiReadIdeal_R(d,r); if (IDELEMS(q)==0) omFreeBin(q,sip_sideal_bin); else r->qideal=q; return r; } } poly ssiReadPoly_R(const ssiInfo *D, const ring r) { // < # of terms> < term1> < ..... int n,i,l; n=ssiReadInt(D->f_read); //Print("poly: terms:%d\n",n); poly p; poly ret=NULL; poly prev=NULL; for(l=0;lcf)); int d; d=s_readint(D->f_read); p_SetComp(p,d,r); for(i=1;i<=rVar(r);i++) { d=s_readint(D->f_read); p_SetExp(p,i,d,r); } p_Setm(p,r); p_Test(p,r); if (ret==NULL) ret=p; else pNext(prev)=p; prev=p; } return ret; } poly ssiReadPoly(const ssiInfo *D) { // < # of terms> < term1> < ..... return ssiReadPoly_R(D,D->r); } ideal ssiReadIdeal_R(const ssiInfo *d,const ring r) { int n,i; ideal I; n=s_readint(d->f_read); I=idInit(n,1); for(i=0;im [i]=ssiReadPoly_R(d,r); } return I; } ideal ssiReadIdeal(const ssiInfo *d) { return ssiReadIdeal_R(d,d->r); } matrix ssiReadMatrix(const ssiInfo *d) { int n,m; m=s_readint(d->f_read); n=s_readint(d->f_read); matrix M=mpNew(m,n); poly p; for(int i=1;i<=MATROWS(M);i++) for(int j=1;j<=MATCOLS(M);j++) { p=ssiReadPoly(d); MATELEM(M,i,j)=p; } return M; } command ssiReadCommand(si_link l) { ssiInfo *d=(ssiInfo*)l->data; // syntax: .... command D=(command)omAlloc0(sizeof(*D)); int argc,op; argc=s_readint(d->f_read); op=s_readint(d->f_read); D->argc=argc; D->op=op; leftv v; if (argc >0) { v=ssiRead1(l); memcpy(&(D->arg1),v,sizeof(*v)); omFreeBin(v,sleftv_bin); } if (argc <4) { if (D->argc >1) { v=ssiRead1(l); memcpy(&(D->arg2),v,sizeof(*v)); omFreeBin(v,sleftv_bin); } if (D->argc >2) { v=ssiRead1(l); memcpy(&(D->arg3),v,sizeof(*v)); omFreeBin(v,sleftv_bin); } } else { leftv prev=&(D->arg1); argc--; while(argc >0) { v=ssiRead1(l); prev->next=v; prev=v; argc--; } } return D; } procinfov ssiReadProc(const ssiInfo *d) { char *s=ssiReadString(d); procinfov p=(procinfov)omAlloc0Bin(procinfo_bin); p->language=LANG_SINGULAR; p->libname=omStrDup(""); p->procname=omStrDup(""); p->data.s.body=s; return p; } lists ssiReadList(si_link l) { ssiInfo *d=(ssiInfo*)l->data; int nr; nr=s_readint(d->f_read); lists L=(lists)omAlloc(sizeof(*L)); L->Init(nr); int i; leftv v; for(i=0;im[i]),v,sizeof(*v)); omFreeBin(v,sleftv_bin); } return L; } intvec* ssiReadIntvec(const ssiInfo *d) { int nr; nr=s_readint(d->f_read); intvec *v=new intvec(nr); for(int i=0;if_read); } return v; } intvec* ssiReadIntmat(const ssiInfo *d) { int r,c; r=s_readint(d->f_read); c=s_readint(d->f_read); intvec *v=new intvec(r,c,0); for(int i=0;if_read); } return v; } bigintmat* ssiReadBigintmat(const ssiInfo *d) { int r,c; r=s_readint(d->f_read); c=s_readint(d->f_read); bigintmat *v=new bigintmat(r,c,coeffs_BIGINT); for(int i=0;idata; int throwaway; throwaway=s_readint(d->f_read); char *name=ssiReadString(d); int tok; blackboxIsCmd(name,tok); if (tok>MAX_TOK) { blackbox *b=getBlackboxStuff(tok); res->rtyp=tok; b->blackbox_deserialize(&b,&(res->data),l); } else { Werror("blackbox %s not found",name); } } void ssiReadAttrib(leftv res, si_link l) { ssiInfo *d=(ssiInfo*)l->data; BITSET fl=(BITSET)s_readint(d->f_read); int nr_of_attr=s_readint(d->f_read); if (nr_of_attr>0) { for(int i=1;i0) { } res->flag=fl; } //**************************************************************************/ BOOLEAN ssiOpen(si_link l, short flag, leftv u) { if (l!=NULL) { const char *mode; ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo)); if (flag & SI_LINK_OPEN) { if (l->mode[0] != '\0' && (strcmp(l->mode, "r") == 0)) flag = SI_LINK_READ; else flag = SI_LINK_WRITE; } if (flag == SI_LINK_READ) mode = "r"; else if (strcmp(l->mode, "w") == 0) mode = "w"; else if (strcmp(l->mode, "fork") == 0) mode = "fork"; else if (strcmp(l->mode, "tcp") == 0) mode = "tcp"; else if (strcmp(l->mode, "connect") == 0) mode = "connect"; else mode = "a"; SI_LINK_SET_OPEN_P(l, flag); l->data=d; omFree(l->mode); l->mode = omStrDup(mode); if (l->name[0] == '\0') { if (strcmp(mode,"fork")==0) { link_list n=(link_list)omAlloc(sizeof(link_struct)); n->u=u; n->l=l; n->next=(void *)ssiToBeClosed; ssiToBeClosed=n; int pc[2]; int cp[2]; pipe(pc); pipe(cp); pid_t pid = fork(); if (pid == -1 && errno == EAGAIN) // RLIMIT_NPROC too low? { raise_rlimit_nproc(); pid = fork(); } if (pid == -1) { WerrorS("could not fork"); } if (pid==0) /*fork: child*/ { /* block SIGINT */ sigset_t sigint; sigemptyset(&sigint); sigaddset(&sigint, SIGINT); sigprocmask(SIG_BLOCK, &sigint, NULL); link_list hh=(link_list)ssiToBeClosed->next; /* we know: l is the first entry in ssiToBeClosed-list */ while(hh!=NULL) { SI_LINK_SET_CLOSE_P(hh->l); ssiInfo *dd=(ssiInfo*)hh->l->data; s_close(dd->f_read); s_free(dd->f_read); fclose(dd->f_write); if (dd->r!=NULL) rKill(dd->r); omFreeSize((ADDRESS)dd,(sizeof *dd)); hh->l->data=NULL; link_list nn=(link_list)hh->next; omFree(hh); hh=nn; } ssiToBeClosed->next=NULL; #ifdef HAVE_SIMPLEIPC memset(sem_acquired, 0, SIPC_MAX_SEMAPHORES*sizeof(sem_acquired[0])); #endif // HAVE_SIMPLEIPC si_close(pc[1]); si_close(cp[0]); d->f_write=fdopen(cp[1],"w"); d->f_read=s_open(pc[0]); d->fd_read=pc[0]; d->fd_write=cp[1]; //d->r=currRing; //if (d->r!=NULL) d->r->ref++; l->data=d; omFree(l->mode); l->mode = omStrDup(mode); singular_in_batchmode=TRUE; SI_LINK_SET_RW_OPEN_P(l); //myynest=0; fe_fgets_stdin=fe_fgets_dummy; if ((u!=NULL)&&(u->rtyp==IDHDL)) { idhdl h=(idhdl)u->data; h->lev=0; } loop { leftv h=ssiRead1(l); /*contains an exit.... */ if (feErrors != NULL && *feErrors != '\0') { // handle errors: PrintS(feErrors); /* currently quite simple */ *feErrors = '\0'; } ssiWrite(l,h); h->CleanUp(); omFreeBin(h, sleftv_bin); } /* never reached*/ } else if (pid>0) /*fork: parent*/ { d->pid=pid; si_close(pc[0]); si_close(cp[1]); d->f_write=fdopen(pc[1],"w"); d->f_read=s_open(cp[0]); d->fd_read=cp[0]; d->fd_write=pc[1]; SI_LINK_SET_RW_OPEN_P(l); d->send_quit_at_exit=1; //d->r=currRing; //if (d->r!=NULL) d->r->ref++; } else { Werror("fork failed (%d)",errno); l->data=NULL; omFree(d); return TRUE; } } // --------------------------------------------------------------------- else if (strcmp(mode,"tcp")==0) { int sockfd, newsockfd, portno, clilen; struct sockaddr_in serv_addr, cli_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd < 0) { WerrorS("ERROR opening socket"); l->data=NULL; omFree(d); return TRUE; } memset((char *) &serv_addr,0, sizeof(serv_addr)); portno = 1025; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; do { portno++; serv_addr.sin_port = htons(portno); if(portno > 50000) { WerrorS("ERROR on binding (no free port available?)"); l->data=NULL; omFree(d); return TRUE; } } while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0); Print("waiting on port %d\n", portno);mflush(); listen(sockfd,1); newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen); if(newsockfd < 0) { WerrorS("ERROR on accept"); l->data=NULL; omFree(d); return TRUE; } PrintS("client accepted\n"); d->fd_read = newsockfd; d->fd_write = newsockfd; d->f_read = s_open(newsockfd); d->f_write = fdopen(newsockfd, "w"); SI_LINK_SET_RW_OPEN_P(l); si_close(sockfd); } // no ssi-Link on stdin or stdout else { Werror("invalid mode >>%s<< for ssi",mode); l->data=NULL; omFree(d); return TRUE; } } // ========================================================================= else /*l->name=NULL*/ { // tcp mode if(strcmp(mode,"tcp")==0) { int sockfd, newsockfd, portno, clilen; struct sockaddr_in serv_addr, cli_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd < 0) { WerrorS("ERROR opening socket"); l->data=NULL; omFree(d); return TRUE; } memset((char *) &serv_addr,0, sizeof(serv_addr)); portno = 1025; serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; do { portno++; serv_addr.sin_port = htons(portno); if(portno > 50000) { WerrorS("ERROR on binding (no free port available?)"); l->data=NULL; return TRUE; } } while(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0); //Print("waiting on port %d\n", portno);mflush(); listen(sockfd,1); char* cli_host = (char*)omAlloc(256); char* path = (char*)omAlloc(1024); int r = si_sscanf(l->name,"%255[^:]:%s",cli_host,path); if(r == 0) { WerrorS("ERROR: no host specified"); l->data=NULL; omFree(d); omFree(path); omFree(cli_host); return TRUE; } else if(r == 1) { WarnS("program not specified, using /usr/local/bin/Singular"); strcpy(path,"/usr/local/bin/Singular"); } char* ssh_command = (char*)omAlloc(256); char* ser_host = (char*)omAlloc(64); gethostname(ser_host,64); sprintf(ssh_command,"ssh %s %s -q --batch --link=ssi --MPhost=%s --MPport=%d &",cli_host,path,ser_host,portno); //Print("client on %s started:%s\n",cli_host,path); omFree(path); omFree(cli_host); if (TEST_OPT_PROT) { Print("running >>%s<<\n",ssh_command); } system(ssh_command); omFree(ssh_command); omFree(ser_host); clilen = sizeof(cli_addr); newsockfd = si_accept(sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen); if(newsockfd < 0) { WerrorS("ERROR on accept"); l->data=NULL; omFree(d); return TRUE; } //PrintS("client accepted\n"); d->fd_read = newsockfd; d->fd_write = newsockfd; d->f_read = s_open(newsockfd); d->f_write = fdopen(newsockfd, "w"); si_close(sockfd); SI_LINK_SET_RW_OPEN_P(l); d->send_quit_at_exit=1; link_list newlink=(link_list)omAlloc(sizeof(link_struct)); newlink->u=u; newlink->l=l; newlink->next=(void *)ssiToBeClosed; ssiToBeClosed=newlink; fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2); } // ---------------------------------------------------------------------- else if(strcmp(mode,"connect")==0) { char* host = (char*)omAlloc(256); int sockfd, portno; struct sockaddr_in serv_addr; struct hostent *server; si_sscanf(l->name,"%255[^:]:%d",host,&portno); //Print("connect to host %s, port %d\n",host,portno);mflush(); if (portno!=0) { sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { WerrorS("ERROR opening socket"); return TRUE; } server = gethostbyname(host); if (server == NULL) { WerrorS("ERROR, no such host"); return TRUE; } memset((char *) &serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length); serv_addr.sin_port = htons(portno); if (si_connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr)) < 0) { Werror("ERROR connecting(errno=%d)",errno); return TRUE; } //PrintS("connected\n");mflush(); d->f_read=s_open(sockfd); d->fd_read=sockfd; d->f_write=fdopen(sockfd,"w"); d->fd_write=sockfd; SI_LINK_SET_RW_OPEN_P(l); omFree(host); } else { l->data=NULL; omFree(d); return TRUE; } } // ====================================================================== else { // normal link to a file FILE *outfile; char *filename=l->name; if(filename[0]=='>') { if (filename[1]=='>') { filename+=2; mode = "a"; } else { filename++; mode="w"; } } outfile=myfopen(filename,mode); if (outfile!=NULL) { if (strcmp(l->mode,"r")==0) { fclose(outfile); d->f_read=s_open_by_name(filename); } else { d->f_write = outfile; fprintf(d->f_write,"98 %d %d %u %u\n",SSI_VERSION,MAX_TOK,si_opt_1,si_opt_2); } } else { omFree(d); l->data=NULL; return TRUE; } } } } return FALSE; } //**************************************************************************/ BOOLEAN ssiPrepClose(si_link l) { if (l!=NULL) { ssiInfo *d = (ssiInfo *)l->data; if (d!=NULL) { if (d->send_quit_at_exit) { fputs("99\n",d->f_write); fflush(d->f_write); } d->quit_sent=1; } } return FALSE; } BOOLEAN ssiClose(si_link l) { if (l!=NULL) { SI_LINK_SET_CLOSE_P(l); ssiInfo *d = (ssiInfo *)l->data; if (d!=NULL) { if ((d->send_quit_at_exit) && (d->quit_sent==0)) { fputs("99\n",d->f_write); fflush(d->f_write); if (d->f_read!=NULL) { s_close(d->f_read);s_free(d->f_read);} if (d->f_write!=NULL) { fclose(d->f_write); d->f_write=NULL; } } if (d->r!=NULL) rKill(d->r); si_waitpid(d->pid,NULL,WNOHANG); if ((d->pid!=0) && (kill(d->pid,0)==0)) // child is still running { struct timespec t; t.tv_sec=0; t.tv_nsec=100000000; // <=100 ms struct timespec rem; int r; loop { r = nanosleep(&t, &rem); t = rem; // child finished: if (si_waitpid(d->pid,NULL,WNOHANG) != 0) break; // other signal, waited s>= 100 ms: if ((r==0) || (errno != EINTR)) break; } if (kill(d->pid,0) == 0) { kill(d->pid,15); t.tv_sec=5; // <=5s t.tv_nsec=0; loop { r = nanosleep(&t, &rem); t = rem; // child finished: if (si_waitpid(d->pid,NULL,WNOHANG) != 0) break; // other signal, waited s>= 100 ms: if ((r==0) || (errno != EINTR)) break; } if (kill(d->pid,0) == 0) { kill(d->pid,9); // just to be sure si_waitpid(d->pid,NULL,0); } } } if (d->f_read!=NULL) { s_close(d->f_read);s_free(d->f_read);} if (d->f_write!=NULL) { fclose(d->f_write); d->f_write=NULL; } if ((strcmp(l->mode,"tcp")==0) || (strcmp(l->mode,"fork")==0)) { link_list hh=ssiToBeClosed; if (hh!=NULL) { if (hh->l==l) { ssiToBeClosed=(link_list)hh->next; omFreeSize(hh,sizeof(link_struct)); } else while(hh->next!=NULL) { link_list hhh=(link_list)hh->next; if (hhh->l==l) { hh->next=hhh->next; omFreeSize(hhh,sizeof(link_struct)); break; } else hh=(link_list)hh->next; } } } omFreeSize((ADDRESS)d,(sizeof *d)); } l->data=NULL; } return FALSE; } //**************************************************************************/ leftv ssiRead1(si_link l) { ssiInfo *d = (ssiInfo *)l->data; leftv res=(leftv)omAlloc0(sizeof(sleftv)); int t=0; t=s_readint(d->f_read); //Print("got type %d\n",t); switch(t) { case 1:res->rtyp=INT_CMD; res->data=(char *)(long)ssiReadInt(d->f_read); break; case 2:res->rtyp=STRING_CMD; res->data=(char *)ssiReadString(d); break; case 3:res->rtyp=NUMBER_CMD; res->data=(char *)ssiReadNumber(d); break; case 4:res->rtyp=BIGINT_CMD; res->data=(char *)ssiReadBigInt(d); break; case 15: case 5:{ d->r=ssiReadRing(d); res->data=(char*)d->r; if (d->r->qideal==NULL) res->rtyp=RING_CMD; else res->rtyp=QRING_CMD; // we are in the top-level, so set the basering to d->r: if (d->r!=NULL) { d->r->ref++; ssiSetCurrRing(d->r); } if (t==15) return ssiRead1(l); } break; case 6:res->rtyp=POLY_CMD; if (d->r==NULL) goto no_ring; res->data=(char*)ssiReadPoly(d); break; case 7:res->rtyp=IDEAL_CMD; if (d->r==NULL) goto no_ring; res->data=(char*)ssiReadIdeal(d); break; case 8:res->rtyp=MATRIX_CMD; if (d->r==NULL) goto no_ring; res->data=(char*)ssiReadMatrix(d); break; case 9:res->rtyp=VECTOR_CMD; if (d->r==NULL) goto no_ring; res->data=(char*)ssiReadPoly(d); break; case 10:res->rtyp=MODUL_CMD; if (d->r==NULL) goto no_ring; { int rk=s_readint(d->f_read); ideal M=ssiReadIdeal(d); M->rank=rk; res->data=(char*)M; } break; case 11: { res->rtyp=COMMAND; res->data=ssiReadCommand(l); int nok=res->Eval(); if (nok) WerrorS("error in eval"); break; } case 12: /*DEF_CMD*/ { res->rtyp=0; res->name=(char *)ssiReadString(d); int nok=res->Eval(); if (nok) WerrorS("error in name lookup"); break; } case 13: res->rtyp=PROC_CMD; res->data=ssiReadProc(d); break; case 14: res->rtyp=LIST_CMD; res->data=ssiReadList(l); break; case 16: res->rtyp=NONE; res->data=NULL; break; case 17: res->rtyp=INTVEC_CMD; res->data=ssiReadIntvec(d); break; case 18: res->rtyp=INTMAT_CMD; res->data=ssiReadIntmat(d); break; case 19: res->rtyp=BIGINTMAT_CMD; res->data=ssiReadBigintmat(d); break; case 20: ssiReadBlackbox(res,l); break; case 21: ssiReadAttrib(res,l); break; // ------------ case 98: // version { int n98_v,n98_m; BITSET n98_o1,n98_o2; n98_v=s_readint(d->f_read); n98_m=s_readint(d->f_read); n98_o1=s_readint(d->f_read); n98_o2=s_readint(d->f_read); if ((n98_v!=SSI_VERSION) ||(n98_m!=MAX_TOK)) { Print("incompatible versions of ssi: %d/%d vs %d/%d", SSI_VERSION,MAX_TOK,n98_v,n98_m); } #ifndef SING_NDEBUG if (TEST_OPT_DEBUG) Print("// opening ssi-%d, MAX_TOK=%d\n",n98_v,n98_m); #endif si_opt_1=n98_o1; si_opt_2=n98_o2; return ssiRead1(l); } case 99: ssiClose(l); m2_end(0); case 0: if (s_iseof(d->f_read)) { ssiClose(l); } res->rtyp=DEF_CMD; break; default: Werror("not implemented (t:%d)",t); omFreeSize(res,sizeof(sleftv)); res=NULL; break; } // if currRing is required for the result, but lost // define "ssiRing%d" as currRing: if ((d->r!=NULL) && (currRing!=d->r) && (res->RingDependend())) { ssiSetCurrRing(d->r); } return res; no_ring: WerrorS("no ring"); omFreeSize(res,sizeof(sleftv)); return NULL; } //**************************************************************************/ BOOLEAN ssiSetRing(si_link l, ring r, BOOLEAN send) { if(SI_LINK_W_OPEN_P(l)==0) if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE; ssiInfo *d = (ssiInfo *)l->data; if (d->r!=r) { if (send) { fputs("15 ",d->f_write); ssiWriteRing(d,r); } d->r=r; } if (currRing!=r) rChangeCurrRing(r); return FALSE; } //**************************************************************************/ BOOLEAN ssiWrite(si_link l, leftv data) { if(SI_LINK_W_OPEN_P(l)==0) if (slOpen(l,SI_LINK_OPEN|SI_LINK_WRITE,NULL)) return TRUE; ssiInfo *d = (ssiInfo *)l->data; d->level++; //FILE *fich=d->f; while (data!=NULL) { int tt=data->Typ(); void *dd=data->Data(); attr *aa=data->Attribute(); BOOLEAN with_attr=FALSE; if (((*aa)!=NULL)||(data->flag!=0)) { attr a=*aa; int n=0; while(a!=NULL) { n++; a=a->next;} fprintf(d->f_write,"21 %d %d ",data->flag,n); a=*aa; } if ((dd==NULL) && (data->name!=NULL) && (tt==0)) tt=DEF_CMD; // return pure undefined names as def switch(tt /*data->Typ()*/) { case 0: /*error*/ case NONE/* nothing*/:fputs("16 ",d->f_write); break; case STRING_CMD: fputs("2 ",d->f_write); ssiWriteString(d,(char *)dd); break; case INT_CMD: fputs("1 ",d->f_write); ssiWriteInt(d,(int)(long)dd); break; case BIGINT_CMD:fputs("4 ",d->f_write); ssiWriteBigInt(d,(number)dd); break; case NUMBER_CMD: if (d->r!=currRing) { fputs("15 ",d->f_write); ssiWriteRing(d,currRing); if (d->level<=1) fputc('\n',d->f_write); } fputs("3 ",d->f_write); ssiWriteNumber(d,(number)dd); break; case QRING_CMD: case RING_CMD:fputs("5 ",d->f_write); ssiWriteRing(d,(ring)dd); break; case POLY_CMD: case VECTOR_CMD: if (d->r!=currRing) { fputs("15 ",d->f_write); ssiWriteRing(d,currRing); if (d->level<=1) fputc('\n',d->f_write); } if(tt==POLY_CMD) fputs("6 ",d->f_write); else fputs("9 ",d->f_write); ssiWritePoly(d,tt,(poly)dd); break; case IDEAL_CMD: case MODUL_CMD: case MATRIX_CMD: if (d->r!=currRing) { fputs("15 ",d->f_write); ssiWriteRing(d,currRing); if (d->level<=1) fputc('\n',d->f_write); } if(tt==IDEAL_CMD) fputs("7 ",d->f_write); else if(tt==MATRIX_CMD) fputs("8 ",d->f_write); else { ideal M=(ideal)dd; fprintf(d->f_write,"10 %d ",M->rank); } ssiWriteIdeal(d,tt,(ideal)dd); break; case COMMAND: fputs("11 ",d->f_write); ssiWriteCommand(l,(command)dd); break; case DEF_CMD: /* not evaluated stuff in quotes */ fputs("12 ",d->f_write); ssiWriteString(d,data->Name()); break; case PROC_CMD: fputs("13 ",d->f_write); ssiWriteProc(d,(procinfov)dd); break; case LIST_CMD: fputs("14 ",d->f_write); ssiWriteList(l,(lists)dd); break; case INTVEC_CMD: fputs("17 ",d->f_write); ssiWriteIntvec(d,(intvec *)dd); break; case INTMAT_CMD: fputs("18 ",d->f_write); ssiWriteIntmat(d,(intvec *)dd); break; case BIGINTMAT_CMD: fputs("19 ",d->f_write); ssiWriteBigintmat(d,(bigintmat *)dd); break; default: if (tt>MAX_TOK) { blackbox *b=getBlackboxStuff(tt); fputs("20 ",d->f_write); b->blackbox_serialize(b,dd,l); } else { Werror("not implemented (t:%d, rtyp:%d)",tt, data->rtyp); d->level=0; return TRUE; } break; } if (d->level<=1) { fputc('\n',d->f_write); fflush(d->f_write); } data=data->next; } d->level--; return FALSE; } BOOLEAN ssiGetDump(si_link l); BOOLEAN ssiDump(si_link l); si_link_extension slInitSsiExtension(si_link_extension s) { s->Open=ssiOpen; s->Close=ssiClose; s->Kill=ssiClose; s->Read=ssiRead1; s->Read2=(slRead2Proc)NULL; s->Write=ssiWrite; s->Dump=ssiDump; s->GetDump=ssiGetDump; s->Status=slStatusSsi; s->SetRing=ssiSetRing; s->type="ssi"; return s; } const char* slStatusSsi(si_link l, const char* request) { ssiInfo *d=(ssiInfo*)l->data; if (d==NULL) return "not open"; if (((strcmp(l->mode,"fork")==0) ||(strcmp(l->mode,"tcp")==0) ||(strcmp(l->mode,"connect")==0)) && (strcmp(request, "read") == 0)) { fd_set mask; struct timeval wt; if (s_isready(d->f_read)) return "ready"; loop { /* Don't block. Return socket status immediately. */ wt.tv_sec = 0; wt.tv_usec = 0; FD_ZERO(&mask); FD_SET(d->fd_read, &mask); //Print("test fd %d\n",d->fd_read); /* check with select: chars waiting: no -> not ready */ switch (si_select(d->fd_read+1, &mask, NULL, NULL, &wt)) { case 0: /* not ready */ return "not ready"; case -1: /*error*/ return "error"; case 1: /*ready ? */ break; } /* yes: read 1 char*/ /* if \n, check again with select else ungetc(c), ready*/ int c=s_getc(d->f_read); //Print("try c=%d\n",c); if (c== -1) return "eof"; /* eof or error */ else if (isdigit(c)) { s_ungetc(c,d->f_read); return "ready"; } else if (c>' ') { Werror("unknown char in ssiLink(%d)",c); return "error"; } /* else: next char */ } } else if (strcmp(request, "read") == 0) { if (SI_LINK_R_OPEN_P(l) && (!s_iseof(d->f_read)) && (s_isready(d->f_read))) return "ready"; else return "not ready"; } else if (strcmp(request, "write") == 0) { if (SI_LINK_W_OPEN_P(l)) return "ready"; else return "not ready"; } else return "unknown status request"; } int slStatusSsiL(lists L, int timeout) { // input: L: a list with links of type // ssi-connect, ssi-fork, ssi-tcp, MPtcp-fork or MPtcp-launch. // Note: Not every entry in L must be set. // timeout: timeout for select in micro-seconds // or -1 for infinity // or 0 for polling // returns: ERROR (via Werror): L has wrong elements or link not open // -2: select returns an error // -1: the read state of all links is eof // 0: timeout (or polling): none ready, // i>0: (at least) L[i] is ready si_link l; ssiInfo *d; int d_fd; fd_set mask, fdmask; FD_ZERO(&fdmask); FD_ZERO(&mask); int max_fd=0; /* 1 + max fd in fd_set */ /* timeout */ struct timeval wt; struct timeval *wt_ptr=&wt; int startingtime = getRTimer()/TIMER_RESOLUTION; // in seconds if (timeout== -1) { wt_ptr=NULL; } else { wt.tv_sec = timeout / 1000000; wt.tv_usec = timeout % 1000000; } /* auxiliary variables */ int i; int j; int k; int s; char fdmaskempty; /* check the links and fill in fdmask */ /* check ssi links for ungetc_buf */ for(i=L->nr; i>=0; i--) { if (L->m[i].Typ()!=DEF_CMD) { if (L->m[i].Typ()!=LINK_CMD) { WerrorS("all elements must be of type link"); return -2;} l=(si_link)L->m[i].Data(); if(SI_LINK_OPEN_P(l)==0) { WerrorS("all links must be open"); return -2;} if (((strcmp(l->m->type,"ssi")!=0) && (strcmp(l->m->type,"MPtcp")!=0)) || ((strcmp(l->mode,"fork")!=0) && (strcmp(l->mode,"tcp")!=0) && (strcmp(l->mode,"launch")!=0) && (strcmp(l->mode,"connect")!=0))) { WerrorS("all links must be of type ssi:fork, ssi:tcp, ssi:connect"); return -2; } if (strcmp(l->m->type,"ssi")==0) { d=(ssiInfo*)l->data; d_fd=d->fd_read; if (!s_isready(d->f_read)) { FD_SET(d_fd, &fdmask); if (d_fd > max_fd) max_fd=d_fd; } else return i+1; } else { Werror("wrong link type >>%s<<",l->m->type); return -2; } } } max_fd++; do_select: /* copy fdmask to mask */ FD_ZERO(&mask); for(k = 0; k < max_fd; k++) { if(FD_ISSET(k, &fdmask)) { FD_SET(k, &mask); } } /* check with select: chars waiting: no -> not ready */ s = si_select(max_fd, &mask, NULL, NULL, wt_ptr); if (s==-1) { WerrorS("error in select call"); return -2; /*error*/ } if (s==0) { return 0; /*poll: not ready */ } else /* s>0, at least one ready (the number of fd which are ready is s)*/ { j=0; while (j<=max_fd) { if (FD_ISSET(j,&mask)) break; j++; } for(i=L->nr; i>=0; i--) { if (L->m[i].rtyp==LINK_CMD) { l=(si_link)L->m[i].Data(); if (strcmp(l->m->type,"ssi")==0) { d=(ssiInfo*)l->data; d_fd=d->fd_read; if(j==d_fd) break; } else { Werror("wrong link type >>%s<<",l->m->type); return -2; } } } // only ssi links: loop { /* yes: read 1 char*/ /* if \n, check again with select else ungetc(c), ready*/ /* setting: d: current ssiInfo, j current fd, i current entry in L*/ int c=s_getc(d->f_read); //Print("try c=%d\n",c); if (c== -1) /* eof */ { FD_CLR(j,&fdmask); fdmaskempty = 1; for(k = 0; k < max_fd; k++) { if(FD_ISSET(k, &fdmask)) { fdmaskempty = 0; break; } } if(fdmaskempty) { return -1; } if(timeout != -1) { timeout = si_max(0, timeout - 1000000*(getRTimer()/TIMER_RESOLUTION - startingtime)); wt.tv_sec = timeout / 1000000; wt.tv_usec = (timeout % 1000000); } goto do_select; } else if (isdigit(c)) { s_ungetc(c,d->f_read); return i+1; } else if (c>' ') { Werror("unknown char in ssiLink(%d)",c); return -2; } /* else: next char */ goto do_select; } } } int ssiBatch(const char *host, const char * port) /* return 0 on success, >0 else*/ { si_link l=(si_link) omAlloc0Bin(sip_link_bin); char *buf=(char*)omAlloc(256); sprintf(buf,"ssi:connect %s:%s",host,port); slInit(l, buf); if (slOpen(l,SI_LINK_OPEN,NULL)) return 1; SI_LINK_SET_RW_OPEN_P(l); idhdl id = enterid(omStrDup("link_ll"), 0, LINK_CMD, &IDROOT, FALSE); IDLINK(id) = l; loop { leftv h=ssiRead1(l); /*contains an exit.... */ if (feErrors != NULL && *feErrors != '\0') { // handle errors: PrintS(feErrors); /* currently quite simple */ *feErrors = '\0'; } ssiWrite(l,h); h->CleanUp(); omFreeBin(h, sleftv_bin); } /* never reached*/ exit(0); } static int ssiReserved_P=0; static int ssiReserved_sockfd; static struct sockaddr_in ssiResverd_serv_addr; static int ssiReserved_Clients; int ssiReservePort(int clients) { if (ssiReserved_P!=0) { WerrorS("ERROR already a reverved port requested"); return 0; } int portno; ssiReserved_sockfd = socket(AF_INET, SOCK_STREAM, 0); if(ssiReserved_sockfd < 0) { WerrorS("ERROR opening socket"); return 0; } memset((char *) &ssiResverd_serv_addr,0, sizeof(ssiResverd_serv_addr)); portno = 1025; ssiResverd_serv_addr.sin_family = AF_INET; ssiResverd_serv_addr.sin_addr.s_addr = INADDR_ANY; do { portno++; ssiResverd_serv_addr.sin_port = htons(portno); if(portno > 50000) { WerrorS("ERROR on binding (no free port available?)"); return 0; } } while(bind(ssiReserved_sockfd, (struct sockaddr *) &ssiResverd_serv_addr, sizeof(ssiResverd_serv_addr)) < 0); ssiReserved_P=portno; listen(ssiReserved_sockfd,clients); ssiReserved_Clients=clients; return portno; } extern si_link_extension si_link_root; si_link ssiCommandLink() { if (ssiReserved_P==0) { WerrorS("ERROR no reverved port requested"); return NULL; } struct sockaddr_in cli_addr; int clilen = sizeof(cli_addr); int newsockfd = si_accept(ssiReserved_sockfd, (struct sockaddr *) &cli_addr, (socklen_t *)&clilen); if(newsockfd < 0) { Werror("ERROR on accept (errno=%d)",errno); return NULL; } si_link l=(si_link) omAlloc0Bin(sip_link_bin); si_link_extension s = si_link_root; si_link_extension prev = s; while (strcmp(s->type, "ssi") != 0) { if (s->next == NULL) { prev = s; s = NULL; break; } else { s = s->next; } } if (s != NULL) l->m = s; else { si_link_extension ns = (si_link_extension)omAlloc0Bin(s_si_link_extension_bin); prev->next=slInitSsiExtension(ns); l->m = prev->next; } l->name=omStrDup(""); l->mode=omStrDup("tcp"); l->ref=1; ssiInfo *d=(ssiInfo*)omAlloc0(sizeof(ssiInfo)); l->data=d; d->fd_read = newsockfd; d->fd_write = newsockfd; d->f_read = s_open(newsockfd); d->f_write = fdopen(newsockfd, "w"); SI_LINK_SET_RW_OPEN_P(l); ssiReserved_Clients--; if (ssiReserved_Clients<=0) { ssiReserved_P=0; si_close(ssiReserved_sockfd); } return l; } /*---------------------------------------------------------------------*/ /** * @brief additional default signal handler // some newer Linux version cannot have SIG_IGN for SIGCHLD, // so use this nice routine here: // SuSe 9.x reports -1 always // Redhat 9.x/FC x reports sometimes -1 // see also: hpux_system // also needed by getrusage (timer etc.) @param[in] sig **/ /*---------------------------------------------------------------------*/ void sig_chld_hdl(int) { pid_t kidpid; int status; loop { kidpid = si_waitpid(-1, &status, WNOHANG); if (kidpid==-1) { /* continue on interruption (EINTR): */ if (errno == EINTR) continue; /* break on anything else (EINVAL or ECHILD according to manpage): */ break; } else if (kidpid==0) break; /* no more children to process, so break */ //printf("Child %ld terminated\n", kidpid); link_list hh=ssiToBeClosed; while((hh!=NULL)&&(ssiToBeClosed_inactive)) { if((hh->l!=NULL) && (hh->l->m->Open==ssiOpen)) { ssiInfo *d = (ssiInfo *)hh->l->data; if(d->pid==kidpid) { if(ssiToBeClosed_inactive) { ssiToBeClosed_inactive=FALSE; slClose(hh->l); ssiToBeClosed_inactive=TRUE; break; } else break; } else hh=(link_list)hh->next; } else hh=(link_list)hh->next; } } } static BOOLEAN DumpSsiIdhdl(si_link l, idhdl h) { int type_id = IDTYP(h); // C-proc not to be dumped, also LIB-proc not if (type_id == PROC_CMD) { if (IDPROC(h)->language == LANG_C) return FALSE; if (IDPROC(h)->libname != NULL) return FALSE; } // do not dump links if (type_id == LINK_CMD) return FALSE; // do not dump ssi internal rings: ssiRing* if ((type_id == RING_CMD) && (strncmp(IDID(h),"ssiRing",7)==0)) return FALSE; command D=(command)omAlloc0(sizeof(*D)); sleftv tmp; memset(&tmp,0,sizeof(tmp)); tmp.rtyp=COMMAND; tmp.data=D; if (type_id == PACKAGE_CMD) { // do not dump Top if (strcmp(IDID(h), "Top") == 0) return FALSE; package p=(package)IDDATA(h); // dump Singular-packages as load("..."); if (p->language==LANG_SINGULAR) { D->op=LOAD_CMD; D->argc=1; D->arg1.rtyp=STRING_CMD; D->arg1.data=p->libname; ssiWrite(l,&tmp); omFree(D); return FALSE; } } // handle qrings separately //if (type_id == QRING_CMD) // return DumpSsiQringQring(l, h); // put type and name //Print("generic dump:%s,%s\n",IDID(h),Tok2Cmdname(IDTYP(h))); D->op='='; D->argc=2; D->arg1.rtyp=DEF_CMD; D->arg1.name=IDID(h); D->arg2.rtyp=IDTYP(h); D->arg2.data=IDDATA(h); ssiWrite(l,&tmp); omFree(D); return FALSE; } static BOOLEAN ssiDumpIter(si_link l, idhdl h) { if (h == NULL) return FALSE; if (ssiDumpIter(l, IDNEXT(h))) return TRUE; // need to set the ring before writing it, otherwise we get in // trouble with minpoly if (IDTYP(h) == RING_CMD || IDTYP(h) == QRING_CMD) rSetHdl(h); if (DumpSsiIdhdl(l, h)) return TRUE; // do not dump ssi internal rings: ssiRing* // but dump objects of all other rings if ((IDTYP(h) == RING_CMD || IDTYP(h) == QRING_CMD) && (strncmp(IDID(h),"ssiRing",7)!=0)) return ssiDumpIter(l, IDRING(h)->idroot); else return FALSE; } BOOLEAN ssiDump(si_link l) { idhdl h = IDROOT, rh = currRingHdl; BOOLEAN status = ssiDumpIter(l, h); //if (! status ) status = DumpAsciiMaps(fd, h, NULL); if (currRingHdl != rh) rSetHdl(rh); //fprintf(fd, "option(set, intvec(%d, %d));\n", si_opt_1, si_opt_2); return status; } BOOLEAN ssiGetDump(si_link l) { ssiInfo *d=(ssiInfo*)l->data; loop { if (!SI_LINK_OPEN_P(l)) break; if (s_iseof(d->f_read)) break; leftv h=ssiRead1(l); /*contains an exit.... */ if (feErrors != NULL && *feErrors != '\0') { // handle errors: PrintS(feErrors); /* currently quite simple */ return TRUE; *feErrors = '\0'; } h->CleanUp(); omFreeBin(h, sleftv_bin); } return FALSE; } // ---------------------------------------------------------------- // format // 1 int %d // 2 string %s // 3 number // 4 bigint 4 %d or 3 // 5 ring // 6 poly // 7 ideal // 8 matrix // 9 vector // 10 module // 11 command // 12 def %s // 13 proc %s // 14 list %d .... // 15 setring ....... // 16 nothing // 17 intvec ... // 18 intmat // 19 bigintmat ... // 20 blackbox 1 ... // 21 attrib ... // // 98: verify version: // 99: quit Singular singular-4.0.3+ds/Singular/links/ssiLink.h000066400000000000000000000013441266270727000204500ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /*************************************************************** * File: ssiLink.h * Purpose: declaration of sl_link routines for ssi ***************************************************************/ #ifndef SSILINK_H #define SSILINK_H #include BOOLEAN ssiOpen(si_link l, short flag, leftv u); BOOLEAN ssiWrite(si_link l, leftv v); leftv ssiRead1(si_link l); leftv ssiRead2(si_link l, leftv key); BOOLEAN ssiClose(si_link l); const char* slStatusSsi(si_link l, const char* request); si_link_extension slInitSsiExtension(si_link_extension s); void sig_chld_hdl(int sig); #endif singular-4.0.3+ds/Singular/lists.cc000066400000000000000000000213471266270727000172150ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: handling of the list type */ // to produce a non-inline version from lists.h #define LISTS_CC #include #include //#include "ipid.h" #include #include #include #include #include #include omBin slists_bin = omGetSpecBin(sizeof(slists)); int lSize(lists L) { int n=L->nr; while ((n>=0)&&((L->m[n].rtyp==DEF_CMD)||(L->m[n].rtyp==0))) n--; return n; } lists lCopy(lists L) { lists N=(lists)omAlloc0Bin(slists_bin); int n=L->nr; if (L->nr>=0) N->Init(n+1); else N->Init(); for(;n>=0;n--) { N->m[n].Copy(&L->m[n]); } //Print("copy list with %d -> %d elems\n",L->nr,N->nr); return N; } /*2 * concat 2 lists */ BOOLEAN lAdd(leftv res, leftv u, leftv v) { lists l=(lists) omAllocBin(slists_bin); lists ul=(lists)u->CopyD(); lists vl=(lists)v->CopyD(); l->Init(ul->nr+vl->nr+2); int i; for(i=0;i<=ul->nr;i++) { //Print("u[%d]->r[%d]\n",i,i); l->m[i].rtyp=ul->m[i].rtyp; l->m[i].data=ul->m[i].data; } for(i=0;i<=vl->nr;i++) { //Print("v[%d]->r[%d]\n",i,i+ul->nr+1); l->m[i+ul->nr+1].rtyp=vl->m[i].rtyp; l->m[i+ul->nr+1].data=vl->m[i].data; } if (ul->m != NULL) omFreeSize((ADDRESS)ul->m,(ul->nr+1)*sizeof(sleftv)); omFreeBin((ADDRESS)ul, slists_bin); if (vl->m != NULL) omFreeSize((ADDRESS)vl->m,(vl->nr+1)*sizeof(sleftv)); omFreeBin((ADDRESS)vl, slists_bin); memset(u,0,sizeof(*u)); memset(v,0,sizeof(*v)); res->data = (char *)l; //res->Print(); return FALSE; } /*2 * insert v into list ul, destroys u */ lists lInsert0(lists ul, leftv v, int pos) { if ((pos<0)||(v->rtyp==NONE)) return NULL; lists l=(lists) omAllocBin(slists_bin); l->Init(si_max(ul->nr+2,pos+1)); int i,j; for(i=j=0;i<=ul->nr;i++,j++) { if(j==pos) j++; l->m[j]=ul->m[i]; } for(j=ul->nr+1;jm[j].rtyp=DEF_CMD; // memset(&(l->m[pos]),0,sizeof(sleftv)); - done by Init l->m[pos].rtyp=v->Typ(); l->m[pos].data=v->CopyD(); l->m[pos].flag=v->flag; attr *a=v->Attribute(); if ((a!=NULL)&&(*a!=NULL)) { l->m[pos].attribute=(*a)->Copy(); } if (ul->m != NULL) omFreeSize((ADDRESS)ul->m,(ul->nr+1)*sizeof(sleftv)); omFreeBin((ADDRESS)ul, slists_bin); return l; } /*2 * insert v into list u, at the beginning */ BOOLEAN lInsert(leftv res, leftv u, leftv v) { lists ul=(lists)u->CopyD(); res->data=(char *)lInsert0(ul,v,0); if (res->data==NULL) { Werror("cannot insert type `%s`",Tok2Cmdname(v->Typ())); return TRUE; } return FALSE; } /*2 * insert v into list u at pos w */ BOOLEAN lInsert3(leftv res, leftv u, leftv v, leftv w) { lists ul=(lists)u->CopyD(); res->data=(char *)lInsert0(ul,v,(int)(long)w->Data()); if (res->data==NULL) { Werror("cannot insert type `%s` at pos. %d", Tok2Cmdname(v->Typ()),(int)(long)w->Data()); return TRUE; } return FALSE; } /*2 * append v to list u */ BOOLEAN lAppend(leftv res, leftv u, leftv v) { lists ul=(lists)u->CopyD(); res->data=(char *)lInsert0(ul,v,ul->nr+1); return (res->data==NULL); } /*2 * delete v-th element from list u */ BOOLEAN lDelete(leftv res, leftv u, leftv v) { lists ul=(lists)u->Data(); int VIndex=(int)(long)v->Data()-1; int EndIndex=lSize(ul); if((0<=VIndex)&&(VIndex<=ul->nr)) { ul=(lists)u->CopyD(); int i,j; lists l=(lists) omAllocBin(slists_bin); l->Init(EndIndex+(VIndex>EndIndex)); for(i=j=0;i<=EndIndex;i++,j++) { if (i!=VIndex) { l->m[j]=ul->m[i]; memset(&ul->m[i],0,sizeof(ul->m[i])); } else { j--; ul->m[i].CleanUp(); } } omFreeSize((ADDRESS)ul->m,(ul->nr+1)*sizeof(sleftv)); omFreeBin((ADDRESS)ul, slists_bin); res->data = (char *)l; return FALSE; } Werror("wrong index %d in list(%d)",VIndex+1,ul->nr+1); return TRUE; } /*2 * check, if a list contains any ring dependend data */ BOOLEAN lRingDependend(lists L) { if (L==NULL) return FALSE; int i=0; while (i<=L->nr) { if ((L->m[i].rtyp!=QRING_CMD) && (BEGIN_RINGm[i].rtyp) && (L->m[i].rtypm[i].rtyp==LIST_CMD)&&lRingDependend((lists)L->m[i].data)) return TRUE; i++; } return FALSE; } lists liMakeResolv(resolvente r, int length, int reallen, int typ0, intvec ** weights, int add_row_shift) { lists L=(lists)omAlloc0Bin(slists_bin); if (length<=0) { // handle "empty" resolutions L->Init(0); } else { int oldlength=length; while (r[length-1]==NULL) length--; if (reallen<=0) reallen=currRing->N; reallen=si_max(reallen,length); L->Init(reallen); int i=0; while (im[i].rtyp=typ0; int j=IDELEMS(r[0])-1; while ((j>0) && (r[0]->m[j]==NULL)) j--; j++; if (j!=IDELEMS(r[0])) { pEnlargeSet(&(r[0]->m),IDELEMS(r[0]),j-IDELEMS(r[0])); IDELEMS(r[0])=j; } } else { L->m[i].rtyp=MODUL_CMD; int rank=IDELEMS(r[i-1]); if (idIs0(r[i-1])) { idDelete(&(r[i])); r[i]=id_FreeModule(rank, currRing); } else { r[i]->rank=si_max(rank,(int)id_RankFreeModule(r[i], currRing)); } idSkipZeroes(r[i]); } L->m[i].data=(void *)r[i]; if ((weights!=NULL) && (weights[i]!=NULL)) { intvec *w=ivCopy(weights[i]); (*w) += add_row_shift; atSet((idhdl)&L->m[i],omStrDup("isHomog"),w,INTVEC_CMD); weights[i] = NULL; } } #ifdef TEST else { // should not happen: Warn("internal NULL in resolvente"); L->m[i].data=(void *)idInit(1,1); } #endif i++; } omFreeSize((ADDRESS)r,oldlength*sizeof(ideal)); if (i==0) { L->m[0].rtyp=typ0; L->m[0].data=(char *)idInit(1,1); i=1; } while (im[i].rtyp=MODUL_CMD; ideal I=(ideal)L->m[i-1].data; ideal J; int rank=IDELEMS(I); if (idIs0(I)) { J=idFreeModule(rank); } else { J=idInit(1,rank); } L->m[i].data=(void *)J; i++; } //Print("make res of length %d (0..%d) L:%d\n",length,length-1,L->nr); } return L; } resolvente liFindRes(lists L, int * len, int *typ0,intvec *** weights) { resolvente r; intvec ** w=NULL,*tw=NULL; *len=L->nr+1; if (*len<=0) { WerrorS("empty list"); return NULL; } r=(ideal *)omAlloc0((*len)*sizeof(ideal)); w=(intvec**)omAlloc0((*len)*sizeof(intvec*)); int i=0; *typ0=MODUL_CMD; while (i<(*len)) { if (L->m[i].rtyp != MODUL_CMD) { if (L->m[i].rtyp!=IDEAL_CMD) { Werror("element %d is not of type module",i+1); omFreeSize((ADDRESS)r,(*len)*sizeof(ideal)); return NULL; } *typ0=IDEAL_CMD; } if ((i>0) && (idIs0(r[i-1]))) { //*len=i-1; break; } r[i]=(ideal)L->m[i].data; tw=(intvec*)atGet((idhdl)&L->m[i],"isHomog",INTVEC_CMD); if (tw!=NULL) { w[i]=ivCopy(tw); } tw = NULL; i++; } BOOLEAN hom_complex=TRUE; int j=0; while ((jnr); return r; } char* lString(lists l, BOOLEAN typed, int dim) { if (l->nr == -1) { if (typed) return omStrDup("list()"); return omStrDup(""); } char** slist = (char**) omAlloc((l->nr+1) * sizeof(char*)); int i, j, k; char *s; for (i=0, j = 0, k = 0; i<=l->nr; i++) { slist[i] = l->m[i].String(NULL, typed, dim); assume(slist[i] != NULL); omCheckAddr(slist[i]); if (*(slist[i]) != '\0') { j += strlen(slist[i]); k++; } } s = (char*) omAlloc(j+k+2+(typed ? 10 : 0) + (dim == 2 ? k : 0)); if (typed) sprintf(s, "list("); else *s = '\0'; for (i=0; i<=l->nr; i++) { if (*(slist[i]) != '\0') { strcat(s, slist[i]); strcat(s, ","); if (dim == 2) strcat(s, "\n"); } omCheckAddr(s); omFree(slist[i]); } if (k > 0) s[strlen(s) - (dim == 2 ? 2 : 1)] = '\0'; if (typed) strcat(s, ")"); omCheckAddr(s); omFreeSize(slist, (l->nr+1) * sizeof(char*)); return s; } singular-4.0.3+ds/Singular/lists.h000066400000000000000000000035001266270727000170460ustar00rootroot00000000000000#ifndef LISTS_H #define LISTS_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: handling of the list type */ #include #include #include #include #include #ifdef MDEBUG #define INLINE_THIS #else #define INLINE_THIS inline #endif extern omBin slists_bin; class slists { public: void Clean(ring r=currRing) { assume (this!=NULL); if (nr>=0) { int i; for(i=nr;i>=0;i--) { if (m[i].rtyp!=DEF_CMD) m[i].CleanUp(r); } omFreeSize((ADDRESS)m, (nr+1)*sizeof(sleftv)); nr=-1; } //omFreeSize((ADDRESS)this, sizeof(slists)); omFreeBin((ADDRESS)this,slists_bin); } INLINE_THIS void Init(int l=0); int nr; /* the number of elements in the list -1 */ /* -1: empty list */ sleftv *m; /* field of sleftv */ }; typedef slists * lists; int lSize(lists L); lists lCopy(lists L); lists lInsert0(lists ul, leftv v, int pos); BOOLEAN lInsert(leftv res, leftv u, leftv v); BOOLEAN lInsert3(leftv res, leftv u, leftv v, leftv w); BOOLEAN lAppend(leftv res, leftv u, leftv v); BOOLEAN lDelete(leftv res, leftv u, leftv v); BOOLEAN lAdd(leftv res, leftv u, leftv v); BOOLEAN lRingDependend(lists L); char* lString(lists l, BOOLEAN typed = FALSE, int dim = 1); lists liMakeResolv(resolvente r, int length, int reallen, int typ0, intvec ** weights,int add_row_shift); resolvente liFindRes(lists L, int * len, int *typ0,intvec *** weights=NULL); #if ! defined(MDEBUG) || defined(LISTS_CC) INLINE_THIS void slists::Init(int l) { nr=l-1; m=(sleftv *)((l>0) ? omAlloc0(l*sizeof(sleftv)): NULL); } #endif #undef INLINE_THIS #endif singular-4.0.3+ds/Singular/locals.h000066400000000000000000000007631266270727000171750ustar00rootroot00000000000000/* * part of modgen */ // #include #include #include //#include #include //#include #include #include BOOLEAN jjANY2LIST(leftv res, leftv v, int cnt); #if 0 extern "C" { void Print(char* fmt, ...); void PrintLn(); void PrintS(char* s); void Werror(char *fmt, ...); void WerrorS(const char *s); } #endif const char *Tok2Cmdname( int tok); singular-4.0.3+ds/Singular/make_alllib.sh000077500000000000000000000003761266270727000203420ustar00rootroot00000000000000#!/bin/sh #C="$1" #C=`readlink -f "$C"` #C=`dirname "$C"` #C=`ls -d1 "$C"` cp $1 all.lib.n chmod u+rw all.lib.n shift for i in $* do echo "LIB \"$i\";" >> all.lib.n done # [ ! -e "$i" ] && (cp -nv "$C/$i" .) chmod u-w all.lib.n mv -f all.lib.n all.lib singular-4.0.3+ds/Singular/maps_ip.cc000066400000000000000000000270051266270727000175040ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT - the mapping of polynomials to other rings */ #define TRANSEXT_PRIVATES #include #include #include #include #include #include #include #include #include //#include // #include #include #include "maps_ip.h" #include "ipid.h" #include "lists.h" #include "tok.h" /* debug output: Tok2Cmdname in maApplyFetch*/ #include "ipshell.h" // define this if you want to use the fast_map routine for mapping ideals //#define FAST_MAP #ifdef FAST_MAP #include #endif /*2 * maps the expression w to res, * switch what: MAP_CMD: use theMap for mapping, N for preimage ring * //FETCH_CMD: use pOrdPoly for mapping * IMAP_CMD: use perm for mapping, N for preimage ring * default: map only poly-structures, * use perm and par_perm, N and P, */ BOOLEAN maApplyFetch(int what,map theMap,leftv res, leftv w, ring preimage_r, int *perm, int *par_perm, int P, nMapFunc nMap) { int i; int N = preimage_r->N; #if 0 Print("N=%d what=%s ",N,Tok2Cmdname(what)); if (perm!=NULL) for(i=1;i<=N;i++) Print("%d -> %d ",i,perm[i]); PrintS("\n"); Print("P=%d ",P); if (par_perm!=NULL) for(i=0;i %d ",i,par_perm[i]); PrintS("\n"); #endif void *data=w->Data(); res->rtyp = w->rtyp; switch (w->rtyp) { case NUMBER_CMD: if (P!=0) { // poly n_PermNumber(const number z, const int *par_perm, const int OldPar, const ring src, const ring dst); res->data= (void *) n_PermNumber((number)data, par_perm, P, preimage_r, currRing); res->rtyp=POLY_CMD; if (nCoeff_is_algExt(currRing->cf)) res->data=(void *)p_MinPolyNormalize((poly)res->data, currRing); pTest((poly) res->data); } else { assume( nMap != NULL ); number a = nMap((number)data, preimage_r->cf, currRing->cf); if (nCoeff_is_Extension(currRing->cf)) { n_Normalize(a, currRing->cf); /* number a = (number)res->data; number one = nInit(1); number product = nMult(a, one ); nDelete(&one); nDelete(&a); res->data=(void *)product; */ } #ifdef LDEBUG n_Test(a, currRing->cf); #endif res->data=(void *)a; } break; case POLY_CMD: case VECTOR_CMD: if ((what==FETCH_CMD)&& (preimage_r->cf==currRing->cf)) res->data=(void *)prCopyR( (poly)data, preimage_r, currRing); else if ( (what==IMAP_CMD) || /*(*/ (what==FETCH_CMD) /*)*/) /* && (nMap!=nCopy)*/ res->data=(void *)p_PermPoly((poly)data,perm,preimage_r,currRing, nMap,par_perm,P); else /*if (what==MAP_CMD)*/ { p_Test((poly)data,preimage_r); matrix s=mpNew(N,maMaxDeg_P((poly)data, preimage_r)); res->data=(void *)maEval(theMap, (poly)data, preimage_r, nMap, (ideal)s, currRing); idDelete((ideal *)&s); } if (nCoeff_is_Extension(currRing->cf)) res->data=(void *)p_MinPolyNormalize((poly)res->data, currRing); pTest((poly)res->data); break; case MODUL_CMD: case MATRIX_CMD: case IDEAL_CMD: case MAP_CMD: { int C=((matrix)data)->cols(); int R; if (w->rtyp==MAP_CMD) R=1; else R=((matrix)data)->rows(); matrix m=mpNew(R,C); char *tmpR=NULL; if(w->rtyp==MAP_CMD) { tmpR=((map)data)->preimage; ((matrix)data)->rank=((matrix)data)->rows(); } if ((what==FETCH_CMD)&& (preimage_r->cf == currRing->cf)) { for (i=R*C-1;i>=0;i--) { m->m[i]=prCopyR(((ideal)data)->m[i], preimage_r, currRing); pTest(m->m[i]); } } else if ((what==IMAP_CMD) || (what==FETCH_CMD)) { for (i=R*C-1;i>=0;i--) { m->m[i]=p_PermPoly(((ideal)data)->m[i],perm,preimage_r,currRing, nMap,par_perm,P); pTest(m->m[i]); } } else /* (what==MAP_CMD) */ { assume(what==MAP_CMD); matrix s=mpNew(N,maMaxDeg_Ma((ideal)data,preimage_r)); for (i=R*C-1;i>=0;i--) { m->m[i]=maEval(theMap, ((ideal)data)->m[i], preimage_r, nMap, (ideal)s, currRing); pTest(m->m[i]); } idDelete((ideal *)&s); } if (nCoeff_is_algExt(currRing->cf)) { for (i=R*C-1;i>=0;i--) { m->m[i]=p_MinPolyNormalize(m->m[i], currRing); pTest(m->m[i]); } } if(w->rtyp==MAP_CMD) { ((map)data)->preimage=tmpR; ((map)m)->preimage=omStrDup(tmpR); } else { m->rank=((matrix)data)->rank; } res->data=(char *)m; idTest((ideal) m); break; } case LIST_CMD: { lists l=(lists)data; lists ml=(lists)omAllocBin(slists_bin); ml->Init(l->nr+1); for(i=0;i<=l->nr;i++) { if (((l->m[i].rtyp>BEGIN_RING)&&(l->m[i].rtypm[i].rtyp==LIST_CMD)) { if (maApplyFetch(what,theMap,&ml->m[i],&l->m[i], preimage_r,perm,par_perm,P,nMap)) { ml->Clean(); omFreeBin((ADDRESS)ml, slists_bin); res->rtyp=0; return TRUE; } } else { ml->m[i].Copy(&l->m[i]); } } res->data=(char *)ml; break; } default: { return TRUE; } } return FALSE; } /*2 * substitutes the parameter par (from 1..N) by image, * does not destroy p and image */ poly pSubstPar(poly p, int par, poly image) { const ring R = currRing->cf->extRing; ideal theMapI = idInit(rPar(currRing),1); nMapFunc nMap = n_SetMap(R->cf, currRing->cf); int i; for(i = rPar(currRing);i>0;i--) { if (i != par) theMapI->m[i-1]= p_NSet(n_Param(i, currRing), currRing); else theMapI->m[i-1] = p_Copy(image, currRing); p_Test(theMapI->m[i-1],currRing); } //iiWriteMatrix((matrix)theMapI,"map:",1,currRing,0); map theMap=(map)theMapI; theMap->preimage=NULL; leftv v=(leftv)omAllocBin(sleftv_bin); sleftv tmpW; poly res=NULL; p_Normalize(p,currRing); if (currRing->cf->rep==n_rep_rat_fct ) { while (p!=NULL) { memset(v,0,sizeof(sleftv)); number d = n_GetDenom(p_GetCoeff(p, currRing), currRing); p_Test((poly)NUM((fraction)d), R); if ( n_IsOne (d, currRing->cf) ) { n_Delete(&d, currRing); d = NULL; } else if (!p_IsConstant((poly)NUM((fraction)d), R)) { WarnS("ignoring denominators of coefficients..."); n_Delete(&d, currRing); d = NULL; } number num = n_GetNumerator(p_GetCoeff(p, currRing), currRing); memset(&tmpW,0,sizeof(sleftv)); tmpW.rtyp = POLY_CMD; p_Test((poly)NUM((fraction)num), R); tmpW.data = NUM ((fraction)num); // a copy of this poly will be used p_Normalize(NUM((fraction)num),R); if (maApplyFetch(MAP_CMD,theMap,v,&tmpW,R,NULL,NULL,0,nMap)) { WerrorS("map failed"); v->data=NULL; } n_Delete(&num, currRing); //TODO check for memory leaks poly pp = pHead(p); //PrintS("map:");pWrite(pp); if( d != NULL ) { pSetCoeff(pp, n_Invers(d, currRing->cf)); n_Delete(&d, currRing); // d = NULL; } else pSetCoeff(pp, nInit(1)); //PrintS("->");pWrite((poly)(v->data)); poly ppp = pMult((poly)(v->data),pp); //PrintS("->");pWrite(ppp); res=pAdd(res,ppp); pIter(p); } } else if (currRing->cf->rep==n_rep_poly ) { while (p!=NULL) { memset(v,0,sizeof(sleftv)); number num = n_GetNumerator(p_GetCoeff(p, currRing), currRing); memset(&tmpW,0,sizeof(sleftv)); tmpW.rtyp = POLY_CMD; p_Test((poly)num, R); p_Normalize((poly)num,R); if (num==NULL) num=(number)R->qideal->m[0]; tmpW.data = num; // a copy of this poly will be used if (maApplyFetch(MAP_CMD,theMap,v,&tmpW,R,NULL,NULL,0,nMap)) { WerrorS("map failed"); v->data=NULL; } if (num!=(number)R->qideal->m[0]) n_Delete(&num, currRing); //TODO check for memory leaks poly pp = pHead(p); //PrintS("map:");pWrite(pp); pSetCoeff(pp,n_Init(1,currRing)); //PrintS("cf->");pWrite((poly)(v->data)); poly ppp = pMult((poly)(v->data),pp); //PrintS("->");pWrite(ppp); res=pAdd(res,ppp); pIter(p); } } else { WerrorS("cannot apply subst for these coeffcients"); } idDelete((ideal *)(&theMap)); omFreeBin((ADDRESS)v, sleftv_bin); return res; } /*2 * substitute the n-th parameter by the poly e in id * does not destroy id and e */ ideal idSubstPar(ideal id, int n, poly e) { int k=MATROWS((matrix)id)*MATCOLS((matrix)id); ideal res=(ideal)mpNew(MATROWS((matrix)id),MATCOLS((matrix)id)); res->rank = id->rank; for(k--;k>=0;k--) { res->m[k]=pSubstPar(id->m[k],n,e); } return res; } /*2 * substitutes the variable var (from 1..N) by image, * does not destroy p and image */ poly pSubstPoly(poly p, int var, poly image) { if (p==NULL) return NULL; #ifdef HAVE_PLURAL if (rIsPluralRing(currRing)) { return pSubst(pCopy(p),var,image); } #endif map theMap=(map)idMaxIdeal(1); theMap->preimage=NULL; pDelete(&(theMap->m[var-1])); theMap->m[var-1]=pCopy(image); poly res=NULL; #ifdef FAST_MAP if (pGetComp(p)==0) { ideal src_id=idInit(1,1); src_id->m[0]=p; char *tmp = theMap->preimage; theMap->preimagei=(char*)1L; // map gets 1 as its rank (as an ideal) ideal res_id=fast_map(src_id,currRing,(ideal)theMap,currRing); theMap->preimage=tmp; // map gets its preimage back res=res_id->m[0]; res_id->m[0]=NULL; idDelete(&res_id); src_id->m[0]=NULL; idDelete(&src_id); } else #endif { sleftv tmpW; memset(&tmpW,0,sizeof(sleftv)); tmpW.rtyp=POLY_CMD; tmpW.data=p; leftv v=(leftv)omAlloc0Bin(sleftv_bin); if (maApplyFetch(MAP_CMD,theMap,v,&tmpW,currRing,NULL,NULL,0, n_SetMap(currRing->cf, currRing->cf))) { WerrorS("map failed"); v->data=NULL; } res=(poly)(v->data); omFreeBin((ADDRESS)v, sleftv_bin); } idDelete((ideal *)(&theMap)); return res; } /*2 * substitute the n-th variable by the poly e in id * does not destroy id and e */ ideal idSubstPoly(ideal id, int n, poly e) { #ifdef HAVE_PLURAL if (rIsPluralRing(currRing)) { int k=MATROWS((matrix)id)*MATCOLS((matrix)id); ideal res=(ideal)mpNew(MATROWS((matrix)id),MATCOLS((matrix)id)); res->rank = id->rank; for(k--;k>=0;k--) { res->m[k]=pSubst(pCopy(id->m[k]),n,e); } return res; } #endif map theMap=(map)idMaxIdeal(1); theMap->preimage=NULL; pDelete(&(theMap->m[n-1])); theMap->m[n-1]=pCopy(e); leftv v=(leftv)omAlloc0Bin(sleftv_bin); sleftv tmpW; memset(&tmpW,0,sizeof(sleftv)); tmpW.rtyp=IDEAL_CMD; tmpW.data=id; if (maApplyFetch(MAP_CMD,theMap,v,&tmpW,currRing,NULL,NULL,0, n_SetMap(currRing->cf, currRing->cf))) { WerrorS("map failed"); v->data=NULL; } ideal res=(ideal)(v->data); idDelete((ideal *)(&theMap)); omFreeBin((ADDRESS)v, sleftv_bin); return res; } singular-4.0.3+ds/Singular/maps_ip.h000066400000000000000000000020061266270727000173400ustar00rootroot00000000000000#ifndef MAPS_IP_H #define MAPS_IP_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT - the mapping of polynomials to other rings */ #include #include #include #include #include poly pSubstPoly(poly p, int var, poly image); poly pSubstPar(poly p, int par, poly image); ideal idSubstPoly(ideal id, int n, poly e); ideal idSubstPar(ideal id, int n, poly e); /* * maps the expression w to res, * switch what: MAP_CMD: use theMap for mapping, N for preimage ring * //FETCH_CMD: use pOrdPoly for mapping * IMAP_CMD: use perm for mapping, N for preimage ring * default: map only poly-structures, * use perm and par_perm, N and P, */ BOOLEAN maApplyFetch(int what,map theMap,leftv res, leftv w, ring preimage_r, int *perm, int *par_perm, int P, nMapFunc nMap); #endif singular-4.0.3+ds/Singular/misc_ip.cc000066400000000000000000001017641266270727000175040ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file misc_ip.cc * * This file provides miscellaneous functionality. * * For more general information, see the documentation in misc_ip.h. * **/ /*****************************************************************************/ // include header files #define PLURAL_INTERNAL_DECLARATIONS 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SIMPLEIPC #include #endif #include "misc_ip.h" #include "ipid.h" #include "feOpt.h" #include "links/silink.h" #include "mod_lib.h" static FORCE_INLINE void number2mpz(number n, mpz_t m){ number2mpz(n, coeffs_BIGINT, m); } static FORCE_INLINE number mpz2number(mpz_t m){ return mpz2number(m, coeffs_BIGINT); } void setListEntry(lists L, int index, mpz_t n) { /* assumes n > 0 */ /* try to fit nn into an int: */ if (mpz_size1(n)<=1) { int ui=(int)mpz_get_si(n); if ((((ui<<3)>>3)==ui) && (mpz_cmp_si(n,(long)ui)==0)) { L->m[index].rtyp = INT_CMD; L->m[index].data = (void*)(long)ui; return; } } number nn = mpz2number(n); L->m[index].rtyp = BIGINT_CMD; L->m[index].data = (void*)nn; } void setListEntry_ui(lists L, int index, unsigned long ui) { /* assumes n > 0 */ /* try to fit nn into an int: */ int i=(int)ui; if ((((unsigned long)i)==ui) && (((i<<3)>>3)==i)) { L->m[index].rtyp = INT_CMD; L->m[index].data = (void*)(long)i; } else { number nn = n_Init(ui, coeffs_BIGINT); L->m[index].rtyp = BIGINT_CMD; L->m[index].data = (void*)nn; } } /* Factoring with Pollard's rho method. stolen from GMP/demos */ static unsigned add[] = {4, 2, 4, 2, 4, 6, 2, 6}; static int factor_using_division (mpz_t t, unsigned int limit,lists primes, int *multiplicities,int &index, unsigned long bound) { mpz_t q, r; unsigned long int f; int ai; unsigned *addv = add; unsigned int failures; int bound_not_reached=1; mpz_init (q); mpz_init (r); f = mpz_scan1 (t, 0); mpz_div_2exp (t, t, f); if (f>0) { setListEntry_ui(primes, index, 2); multiplicities[index++] = f; } f=0; loop { mpz_tdiv_qr_ui (q, r, t, 3); if (mpz_cmp_ui (r, 0) != 0) break; mpz_set (t, q); f++; } if (f>0) { setListEntry_ui(primes, index, 3); multiplicities[index++] = f; } f=0; loop { mpz_tdiv_qr_ui (q, r, t, 5); if (mpz_cmp_ui (r, 0) != 0) break; mpz_set (t, q); f++; } if (f>0) { setListEntry_ui(primes, index, 5); multiplicities[index++] = f; } failures = 0; f = 7; ai = 0; unsigned long last_f=0; while (mpz_cmp_ui (t, 1) != 0) { mpz_tdiv_qr_ui (q, r, t, f); if (mpz_cmp_ui (r, 0) != 0) { f += addv[ai]; if (mpz_cmp_ui (t, f) < 0) break; ai = (ai + 1) & 7; failures++; if (failures > limit) break; if ((bound!=0) && (f>bound)) { bound_not_reached=0; break; } } else { mpz_swap (t, q); if (f!=last_f) { setListEntry_ui(primes, index, f); multiplicities[index]++; index++; } else { multiplicities[index-1]++; } last_f=f; failures = 0; } } mpz_clear (q); mpz_clear (r); //printf("bound=%d,f=%d,failures=%d, reached=%d\n",bound,f,failures,bound_not_reached); return bound_not_reached; } static void factor_using_pollard_rho (mpz_t n, unsigned long a, lists primes, int * multiplicities,int &index) { mpz_t x, x1, y, P; mpz_t t1, t2; mpz_t last_f; unsigned long long k, l, i; mpz_init (t1); mpz_init (t2); mpz_init_set_si (last_f, 0); mpz_init_set_si (y, 2); mpz_init_set_si (x, 2); mpz_init_set_si (x1, 2); mpz_init_set_ui (P, 1); k = 1; l = 1; while (mpz_cmp_ui (n, 1) != 0) { loop { do { mpz_mul (t1, x, x); mpz_mod (x, t1, n); mpz_add_ui (x, x, a); mpz_sub (t1, x1, x); mpz_mul (t2, P, t1); mpz_mod (P, t2, n); if (k % 32 == 1) { mpz_gcd (t1, P, n); if (mpz_cmp_ui (t1, 1) != 0) goto factor_found; mpz_set (y, x); } } while (--k != 0); mpz_gcd (t1, P, n); if (mpz_cmp_ui (t1, 1) != 0) goto factor_found; mpz_set (x1, x); k = l; l = 2 * l; for (i = 0; i < k; i++) { mpz_mul (t1, x, x); mpz_mod (x, t1, n); mpz_add_ui (x, x, a); } mpz_set (y, x); } factor_found: do { mpz_mul (t1, y, y); mpz_mod (y, t1, n); mpz_add_ui (y, y, a); mpz_sub (t1, x1, y); mpz_gcd (t1, t1, n); } while (mpz_cmp_ui (t1, 1) == 0); mpz_divexact (n, n, t1); /* divide by t1, before t1 is overwritten */ if (!mpz_probab_prime_p (t1, 10)) { do { mp_limb_t a_limb; mpn_random (&a_limb, (mp_size_t) 1); a = a_limb; } while (a == 0); factor_using_pollard_rho (t1, a, primes,multiplicities,index); } else { if (mpz_cmp(t1,last_f)==0) { multiplicities[index-1]++; } else { mpz_set(last_f,t1); setListEntry(primes, index, t1); multiplicities[index++] = 1; } } mpz_mod (x, x, n); mpz_mod (x1, x1, n); mpz_mod (y, y, n); if (mpz_probab_prime_p (n, 10)) { if (mpz_cmp(n,last_f)==0) { multiplicities[index-1]++; } else { mpz_set(last_f,n); setListEntry(primes, index, n); multiplicities[index++] = 1; } mpz_set_ui(n,1); break; } } mpz_clear (P); mpz_clear (t2); mpz_clear (t1); mpz_clear (x1); mpz_clear (x); mpz_clear (y); mpz_clear (last_f); } static void factor_gmp (mpz_t t,lists primes,int *multiplicities,int &index,unsigned long bound) { unsigned int division_limit; if (mpz_sgn (t) == 0) return; /* Set the trial division limit according the size of t. */ division_limit = mpz_sizeinbase (t, 2); if (division_limit > 1000) division_limit = 1000 * 1000; else division_limit = division_limit * division_limit; if (factor_using_division (t, division_limit,primes,multiplicities,index,bound)) { if (mpz_cmp_ui (t, 1) != 0) { if (mpz_probab_prime_p (t, 10)) { setListEntry(primes, index, t); multiplicities[index++] = 1; mpz_set_ui(t,1); } else factor_using_pollard_rho (t, 1L, primes,multiplicities,index); } } } /* n and pBound are assumed to be bigint numbers */ lists primeFactorisation(const number n, const int pBound) { int i; int index=0; mpz_t nn; number2mpz(n, nn); lists primes = (lists)omAllocBin(slists_bin); primes->Init(1000); int* multiplicities = (int*)omAlloc0(1000*sizeof(int)); int positive=1; if (!n_IsZero(n, coeffs_BIGINT)) { if (!n_GreaterZero(n, coeffs_BIGINT)) { positive=-1; mpz_neg(nn,nn); } factor_gmp(nn,primes,multiplicities,index,pBound); } lists primesL = (lists)omAllocBin(slists_bin); primesL->Init(index); for (i = 0; i < index; i++) { primesL->m[i].rtyp = primes->m[i].rtyp; primesL->m[i].data = primes->m[i].data; primes->m[i].rtyp=0; primes->m[i].data=NULL; } primes->Clean(NULL); lists multiplicitiesL = (lists)omAllocBin(slists_bin); multiplicitiesL->Init(index); for (i = 0; i < index; i++) { multiplicitiesL->m[i].rtyp = INT_CMD; multiplicitiesL->m[i].data = (void*)(long)multiplicities[i]; } omFree(multiplicities); lists L=(lists)omAllocBin(slists_bin); L->Init(3); if (positive==-1) mpz_neg(nn,nn); L->m[0].rtyp = LIST_CMD; L->m[0].data = (void*)primesL; L->m[1].rtyp = LIST_CMD; L->m[1].data = (void*)multiplicitiesL; setListEntry(L, 2, nn); mpz_clear(nn); return L; } #include #include #include #include #include #include #include #include #include #include #include "subexpr.h" #include "cntrlc.h" #include "ipid.h" #include "ipshell.h" #include "fehelp.h" #ifdef HAVE_STATIC #undef HAVE_DYN_RL #endif //#ifdef HAVE_LIBPARSER //# include "libparse.h" //#endif /* HAVE_LIBPARSER */ /*2 * the renice routine for very large jobs * works only on unix machines, * testet on : linux, HP 9.0 * *#include *#include *extern "C" int setpriority(int,int,int); *void very_nice() *{ *#ifndef NO_SETPRIORITY * setpriority(PRIO_PROCESS,0,19); *#endif * sleep(10); *} */ #include #include #include #include #include #include void singular_example(char *str) { assume(str!=NULL); char *s=str; while (*s==' ') s++; char *ss=s; while (*ss!='\0') ss++; while (*ss<=' ') { *ss='\0'; ss--; } idhdl h=IDROOT->get(s,myynest); if ((h!=NULL) && (IDTYP(h)==PROC_CMD)) { char *lib=iiGetLibName(IDPROC(h)); if((lib!=NULL)&&(*lib!='\0')) { Print("// proc %s from lib %s\n",s,lib); s=iiGetLibProcBuffer(IDPROC(h), 2); if (s!=NULL) { if (strlen(s)>5) { iiEStart(s,IDPROC(h)); omFree((ADDRESS)s); return; } else omFree((ADDRESS)s); } } } else { char sing_file[MAXPATHLEN]; FILE *fd=NULL; char *res_m=feResource('m', 0); if (res_m!=NULL) { sprintf(sing_file, "%s/%s.sing", res_m, s); fd = feFopen(sing_file, "r"); } if (fd != NULL) { int old_echo = si_echo; int length, got; char* s; fseek(fd, 0, SEEK_END); length = ftell(fd); fseek(fd, 0, SEEK_SET); s = (char*) omAlloc((length+20)*sizeof(char)); got = fread(s, sizeof(char), length, fd); fclose(fd); if (got != length) { Werror("Error while reading file %s", sing_file); } else { s[length] = '\0'; strcat(s, "\n;return();\n\n"); si_echo = 2; iiEStart(s, NULL); si_echo = old_echo; } omFree(s); } else { Werror("no example for %s", str); } } } struct soptionStruct { const char * name; unsigned setval; unsigned resetval; }; struct soptionStruct optionStruct[]= { {"prot", Sy_bit(OPT_PROT), ~Sy_bit(OPT_PROT) }, {"redSB", Sy_bit(OPT_REDSB), ~Sy_bit(OPT_REDSB) }, {"notBuckets", Sy_bit(OPT_NOT_BUCKETS), ~Sy_bit(OPT_NOT_BUCKETS) }, {"notSugar", Sy_bit(OPT_NOT_SUGAR), ~Sy_bit(OPT_NOT_SUGAR) }, {"interrupt", Sy_bit(OPT_INTERRUPT), ~Sy_bit(OPT_INTERRUPT) }, {"sugarCrit", Sy_bit(OPT_SUGARCRIT), ~Sy_bit(OPT_SUGARCRIT) }, {"teach", Sy_bit(OPT_DEBUG), ~Sy_bit(OPT_DEBUG) }, {"notSyzMinim", Sy_bit(OPT_NO_SYZ_MINIM), ~Sy_bit(OPT_NO_SYZ_MINIM) }, /* 9 return SB in syz, quotient, intersect */ {"returnSB", Sy_bit(OPT_RETURN_SB), ~Sy_bit(OPT_RETURN_SB) }, {"fastHC", Sy_bit(OPT_FASTHC), ~Sy_bit(OPT_FASTHC) }, /* 11-19 sort in L/T */ {"staircaseBound",Sy_bit(OPT_STAIRCASEBOUND),~Sy_bit(OPT_STAIRCASEBOUND) }, {"multBound", Sy_bit(OPT_MULTBOUND), ~Sy_bit(OPT_MULTBOUND) }, {"degBound", Sy_bit(OPT_DEGBOUND), ~Sy_bit(OPT_DEGBOUND) }, /* 25 no redTail(p)/redTail(s) */ {"redTail", Sy_bit(OPT_REDTAIL), ~Sy_bit(OPT_REDTAIL) }, {"redThrough", Sy_bit(OPT_REDTHROUGH), ~Sy_bit(OPT_REDTHROUGH) }, {"lazy", Sy_bit(OPT_OLDSTD), ~Sy_bit(OPT_OLDSTD) }, {"intStrategy", Sy_bit(OPT_INTSTRATEGY), ~Sy_bit(OPT_INTSTRATEGY) }, {"infRedTail", Sy_bit(OPT_INFREDTAIL), ~Sy_bit(OPT_INFREDTAIL) }, /* 30: use not regularity for syz */ {"notRegularity",Sy_bit(OPT_NOTREGULARITY), ~Sy_bit(OPT_NOTREGULARITY) }, {"weightM", Sy_bit(OPT_WEIGHTM), ~Sy_bit(OPT_WEIGHTM) }, /*special for "none" and also end marker for showOption:*/ {"ne", 0, 0 } }; struct soptionStruct verboseStruct[]= { {"mem", Sy_bit(V_SHOW_MEM), ~Sy_bit(V_SHOW_MEM) }, {"yacc", Sy_bit(V_YACC), ~Sy_bit(V_YACC) }, {"redefine", Sy_bit(V_REDEFINE), ~Sy_bit(V_REDEFINE) }, {"reading", Sy_bit(V_READING), ~Sy_bit(V_READING) }, {"loadLib", Sy_bit(V_LOAD_LIB), ~Sy_bit(V_LOAD_LIB) }, {"debugLib", Sy_bit(V_DEBUG_LIB), ~Sy_bit(V_DEBUG_LIB) }, {"loadProc", Sy_bit(V_LOAD_PROC), ~Sy_bit(V_LOAD_PROC) }, {"defRes", Sy_bit(V_DEF_RES), ~Sy_bit(V_DEF_RES) }, {"usage", Sy_bit(V_SHOW_USE), ~Sy_bit(V_SHOW_USE) }, {"Imap", Sy_bit(V_IMAP), ~Sy_bit(V_IMAP) }, {"prompt", Sy_bit(V_PROMPT), ~Sy_bit(V_PROMPT) }, {"length", Sy_bit(V_LENGTH), ~Sy_bit(V_LENGTH) }, {"notWarnSB",Sy_bit(V_NSB), ~Sy_bit(V_NSB) }, {"contentSB",Sy_bit(V_CONTENTSB), ~Sy_bit(V_CONTENTSB) }, {"cancelunit",Sy_bit(V_CANCELUNIT),~Sy_bit(V_CANCELUNIT)}, {"modpsolve",Sy_bit(V_MODPSOLVSB),~Sy_bit(V_MODPSOLVSB)}, {"geometricSB",Sy_bit(V_UPTORADICAL),~Sy_bit(V_UPTORADICAL)}, {"findMonomials",Sy_bit(V_FINDMONOM),~Sy_bit(V_FINDMONOM)}, {"coefStrat",Sy_bit(V_COEFSTRAT), ~Sy_bit(V_COEFSTRAT)}, {"qringNF", Sy_bit(V_QRING), ~Sy_bit(V_QRING)}, {"warn", Sy_bit(V_ALLWARN), ~Sy_bit(V_ALLWARN)}, {"intersectSyz",Sy_bit(V_INTERSECT_SYZ), ~Sy_bit(V_INTERSECT_SYZ)}, {"intersectElim",Sy_bit(V_INTERSECT_ELIM), ~Sy_bit(V_INTERSECT_ELIM)}, /*special for "none" and also end marker for showOption:*/ {"ne", 0, 0 } }; BOOLEAN setOption(leftv res, leftv v) { const char *n; do { if (v->Typ()==STRING_CMD) { n=(const char *)v->CopyD(STRING_CMD); } else { if (v->name==NULL) return TRUE; if (v->rtyp==0) { n=v->name; v->name=NULL; } else { n=omStrDup(v->name); } } int i; if(strcmp(n,"get")==0) { intvec *w=new intvec(2); (*w)[0]=si_opt_1; (*w)[1]=si_opt_2; res->rtyp=INTVEC_CMD; res->data=(void *)w; goto okay; } if(strcmp(n,"set")==0) { if((v->next!=NULL) &&(v->next->Typ()==INTVEC_CMD)) { v=v->next; intvec *w=(intvec*)v->Data(); si_opt_1=(*w)[0]; si_opt_2=(*w)[1]; #if 0 if (TEST_OPT_INTSTRATEGY && (currRing!=NULL) && rField_has_simple_inverse() #ifdef HAVE_RINGS && !rField_is_Ring(currRing) #endif ) { si_opt_1 &=~Sy_bit(OPT_INTSTRATEGY); } #endif goto okay; } } if(strcmp(n,"none")==0) { si_opt_1=0; si_opt_2=0; goto okay; } for (i=0; (i==0) || (optionStruct[i-1].setval!=0); i++) { if (strcmp(n,optionStruct[i].name)==0) { if (optionStruct[i].setval & validOpts) { si_opt_1 |= optionStruct[i].setval; // optOldStd disables redthrough if (optionStruct[i].setval == Sy_bit(OPT_OLDSTD)) si_opt_1 &= ~Sy_bit(OPT_REDTHROUGH); } else Warn("cannot set option"); #if 0 if (TEST_OPT_INTSTRATEGY && (currRing!=NULL) && rField_has_simple_inverse() #ifdef HAVE_RINGS && !rField_is_Ring(currRing) #endif ) { test &=~Sy_bit(OPT_INTSTRATEGY); } #endif goto okay; } else if ((strncmp(n,"no",2)==0) && (strcmp(n+2,optionStruct[i].name)==0)) { if (optionStruct[i].setval & validOpts) { si_opt_1 &= optionStruct[i].resetval; } else Warn("cannot clear option"); goto okay; } } for (i=0; (i==0) || (verboseStruct[i-1].setval!=0); i++) { if (strcmp(n,verboseStruct[i].name)==0) { si_opt_2 |= verboseStruct[i].setval; #ifdef YYDEBUG #if YYDEBUG /*debugging the bison grammar --> grammar.cc*/ extern int yydebug; if (BVERBOSE(V_YACC)) yydebug=1; else yydebug=0; #endif #endif goto okay; } else if ((strncmp(n,"no",2)==0) && (strcmp(n+2,verboseStruct[i].name)==0)) { si_opt_2 &= verboseStruct[i].resetval; #ifdef YYDEBUG #if YYDEBUG /*debugging the bison grammar --> grammar.cc*/ extern int yydebug; if (BVERBOSE(V_YACC)) yydebug=1; else yydebug=0; #endif #endif goto okay; } } Werror("unknown option `%s`",n); okay: if (currRing != NULL) currRing->options = si_opt_1 & TEST_RINGDEP_OPTS; omFree((ADDRESS)n); v=v->next; } while (v!=NULL); // set global variable to show memory usage extern int om_sing_opt_show_mem; if (BVERBOSE(V_SHOW_MEM)) om_sing_opt_show_mem = 1; else om_sing_opt_show_mem = 0; return FALSE; } char * showOption() { int i; BITSET tmp; StringSetS("//options:"); if ((si_opt_1!=0)||(si_opt_2!=0)) { tmp=si_opt_1; if(tmp) { for (i=0; optionStruct[i].setval!=0; i++) { if (optionStruct[i].setval & tmp) { StringAppend(" %s",optionStruct[i].name); tmp &=optionStruct[i].resetval; } } for (i=0; i<32; i++) { if (tmp & Sy_bit(i)) StringAppend(" %d",i); } } tmp=si_opt_2; if (tmp) { for (i=0; verboseStruct[i].setval!=0; i++) { if (verboseStruct[i].setval & tmp) { StringAppend(" %s",verboseStruct[i].name); tmp &=verboseStruct[i].resetval; } } for (i=1; i<32; i++) { if (tmp & Sy_bit(i)) StringAppend(" %d",i+32); } } return StringEndS(); } StringAppendS(" none"); return StringEndS(); } /* version strings */ #ifdef HAVE_FLINT extern "C" { #ifndef __GMP_BITS_PER_MP_LIMB #define __GMP_BITS_PER_MP_LIMB GMP_LIMB_BITS #endif #include } #endif char * versionString(/*const bool bShowDetails = false*/ ) { StringSetS(""); StringAppend("Singular for %s version %s (%d, %d bit) %s #%s", S_UNAME, VERSION, // SINGULAR_VERSION, SINGULAR_VERSION, SIZEOF_VOIDP*8, singular_date, GIT_VERSION); StringAppendS("\nwith\n\t"); #if defined(mpir_version) StringAppend("MPIR(%s)~GMP(%s),", mpir_version, gmp_version); #elif defined(gmp_version) // #if defined (__GNU_MP_VERSION) && defined (__GNU_MP_VERSION_MINOR) // StringAppend("GMP(%d.%d),",__GNU_MP_VERSION,__GNU_MP_VERSION_MINOR); StringAppend("GMP(%s),", gmp_version); #endif #ifdef HAVE_NTL #include StringAppend("NTL(%s),",NTL_VERSION); #endif #ifdef HAVE_FLINT StringAppend("FLINT(%s),",version); #endif StringAppend("factory(%s),\n\t", factoryVersion); #if defined(HAVE_DYN_RL) if (fe_fgets_stdin==fe_fgets_dummy) StringAppendS("no input,"); else if (fe_fgets_stdin==fe_fgets) StringAppendS("fgets,"); if (fe_fgets_stdin==fe_fgets_stdin_drl) StringAppendS("dynamic readline,"); #ifdef HAVE_FEREAD else if (fe_fgets_stdin==fe_fgets_stdin_emu) StringAppendS("emulated readline,"); #endif else StringAppendS("unknown fgets method,"); #else #if defined(HAVE_READLINE) && !defined(FEREAD) StringAppendS("static readline,"); #else #ifdef HAVE_FEREAD StringAppendS("emulated readline,"); #else StringAppendS("fgets,"); #endif #endif #endif #ifdef HAVE_PLURAL StringAppendS("Plural,"); #endif #ifdef HAVE_DBM StringAppendS("DBM,\n\t"); #else StringAppendS("\n\t"); #endif #ifdef HAVE_DYNAMIC_LOADING StringAppendS("dynamic modules,"); #endif if (p_procs_dynamic) StringAppendS("dynamic p_Procs,"); #if YYDEBUG StringAppendS("YYDEBUG=1,"); #endif #ifdef HAVE_ASSUME StringAppendS("ASSUME,"); #endif #ifdef MDEBUG StringAppend("MDEBUG=%d,",MDEBUG); #endif #ifdef OM_CHECK StringAppend("OM_CHECK=%d,",OM_CHECK); #endif #ifdef OM_TRACK StringAppend("OM_TRACK=%d,",OM_TRACK); #endif #ifdef OM_NDEBUG StringAppendS("OM_NDEBUG,"); #endif #ifdef SING_NDEBUG StringAppendS("SING_NDEBUG,"); #endif #ifdef PDEBUG StringAppendS("PDEBUG,"); #endif #ifdef KDEBUG StringAppendS("KDEBUG,"); #endif #ifdef __OPTIMIZE__ StringAppendS("CC:OPTIMIZE,"); #endif #ifdef __OPTIMIZE_SIZE__ StringAppendS("CC:OPTIMIZE_SIZE,"); #endif #ifdef __NO_INLINE__ StringAppendS("CC:NO_INLINE,"); #endif #ifdef HAVE_EIGENVAL StringAppendS("eigenvalues,"); #endif #ifdef HAVE_GMS StringAppendS("Gauss-Manin system,"); #endif #ifdef HAVE_RATGRING StringAppendS("ratGB,"); #endif StringAppend("random=%d\n",siRandomStart); #define SI_SHOW_BUILTIN_MODULE(name) StringAppend(" %s", #name); StringAppendS("built-in modules: {"); SI_FOREACH_BUILTIN(SI_SHOW_BUILTIN_MODULE) StringAppendS("}\n"); #undef SI_SHOW_BUILTIN_MODULE StringAppend("AC_CONFIGURE_ARGS = %s,\n" "CC = %s,FLAGS : %s,\n" "CXX = %s,FLAGS : %s,\n" "DEFS : %s,CPPFLAGS : %s,\n" "LDFLAGS : %s,LIBS : %s " #ifdef __GNUC__ "(ver: " __VERSION__ ")" #endif "\n",AC_CONFIGURE_ARGS, CC,CFLAGS, CXX,CXXFLAGS, DEFS,CPPFLAGS, LDFLAGS,LIBS); feStringAppendResources(0); feStringAppendBrowsers(0); StringAppendS("\n"); return StringEndS(); } #ifdef PDEBUG #if (OM_TRACK > 2) && defined(OM_TRACK_CUSTOM) void p_SetRingOfLeftv(leftv l, ring r) { switch(l->rtyp) { case INT_CMD: case BIGINT_CMD: case IDHDL: case DEF_CMD: break; case POLY_CMD: case VECTOR_CMD: { poly p=(poly)l->data; while(p!=NULL) { p_SetRingOfLm(p,r); pIter(p); } break; } case IDEAL_CMD: case MODUL_CMD: case MATRIX_CMD: { ideal I=(ideal)l->data; int i; for(i=IDELEMS(I)-1;i>=0;i--) { poly p=I->m[i]; while(p!=NULL) { p_SetRingOfLm(p,r); pIter(p); } } break; } case COMMAND: { command d=(command)l->data; p_SetRingOfLeftv(&d->arg1, r); if (d->argc>1) p_SetRingOfLeftv(&d->arg2, r); if (d->argc>2) p_SetRingOfLeftv(&d->arg3, r); break; } default: printf("type %d not yet implementd in p_SetRingOfLeftv\n",l->rtyp); break; } } #endif #endif #if 0 /* debug only */ void listall(int showproc) { idhdl hh=basePack->idroot; PrintS("====== Top ==============\n"); while (hh!=NULL) { if (showproc || (IDTYP(hh)!=PROC_CMD)) { if (IDDATA(hh)==(void *)currRing) PrintS("(R)"); else if (IDDATA(hh)==(void *)currPack) PrintS("(P)"); else PrintS(" "); Print("::%s, typ %s level %d data %lx", IDID(hh),Tok2Cmdname(IDTYP(hh)),IDLEV(hh),(long)IDDATA(hh)); if ((IDTYP(hh)==RING_CMD) || (IDTYP(hh)==QRING_CMD)) Print(" ref: %d\n",IDRING(hh)->ref); else PrintLn(); } hh=IDNEXT(hh); } hh=basePack->idroot; while (hh!=NULL) { if (IDDATA(hh)==(void *)basePack) Print("(T)::%s, typ %s level %d data %lx\n", IDID(hh),Tok2Cmdname(IDTYP(hh)),IDLEV(hh),(long)IDDATA(hh)); else if ((IDTYP(hh)==RING_CMD) || (IDTYP(hh)==QRING_CMD) || (IDTYP(hh)==PACKAGE_CMD)) { Print("====== %s ==============\n",IDID(hh)); idhdl h2=IDRING(hh)->idroot; while (h2!=NULL) { if (showproc || (IDTYP(h2)!=PROC_CMD)) { if ((IDDATA(h2)==(void *)currRing) && ((IDTYP(h2)==RING_CMD)||(IDTYP(h2)==QRING_CMD))) PrintS("(R)"); else if (IDDATA(h2)==(void *)currPack) PrintS("(P)"); else PrintS(" "); Print("%s::%s, typ %s level %d data %lx\n", IDID(hh),IDID(h2),Tok2Cmdname(IDTYP(h2)),IDLEV(h2),(long)IDDATA(h2)); } h2=IDNEXT(h2); } } hh=IDNEXT(hh); } Print("currRing:%lx, currPack:%lx,basePack:%lx\n",(long)currRing,(long)currPack,(long)basePack); iiCheckPack(currPack); } #endif #ifndef SING_NDEBUG void checkall() { idhdl hh=basePack->idroot; while (hh!=NULL) { omCheckAddr(hh); omCheckAddr((ADDRESS)IDID(hh)); if (RingDependend(IDTYP(hh))) { Print("%s typ %d in Top (should be in ring)\n",IDID(hh),IDTYP(hh)); } hh=IDNEXT(hh); } hh=basePack->idroot; while (hh!=NULL) { if (IDTYP(hh)==PACKAGE_CMD) { idhdl h2=IDPACKAGE(hh)->idroot; if (IDPACKAGE(hh)!=basePack) { while (h2!=NULL) { omCheckAddr(h2); omCheckAddr((ADDRESS)IDID(h2)); if (RingDependend(IDTYP(h2))) { Print("%s typ %d in %s (should be in ring)\n",IDID(h2),IDTYP(h2),IDID(hh)); } h2=IDNEXT(h2); } } } hh=IDNEXT(hh); } } #endif #include #include #include extern "C" int singular_fstat(int fd, struct stat *buf) { return si_fstat(fd,buf); } /*2 * the global exit routine of Singular */ extern "C" { /* Note: We cannot use a mutex here because mutexes are not async-safe, but * m2_end is called by sig_term_hdl(). Anyway, the race condition in the first * few lines of m2_end() should not matter. */ volatile BOOLEAN m2_end_called = FALSE; void m2_end(int i) { if (!m2_end_called) { extern FILE* File_Profiling; if (File_Profiling!=NULL) { fclose(File_Profiling); File_Profiling=NULL; } m2_end_called = TRUE; #ifdef HAVE_SIMPLEIPC for (int j = SIPC_MAX_SEMAPHORES-1; j >= 0; j--) { if (semaphore[j] != NULL) { while (sem_acquired[j] > 0) { sem_post(semaphore[j]); sem_acquired[j]--; } } } #endif // HAVE_SIMPLEIPC fe_reset_input_mode(); monitor(NULL,0); #ifdef PAGE_TEST mmEndStat(); #endif fe_reset_input_mode(); if (ssiToBeClosed_inactive) { link_list hh=ssiToBeClosed; while(hh!=NULL) { //Print("close %s\n",hh->l->name); slPrepClose(hh->l); hh=(link_list)hh->next; } ssiToBeClosed_inactive=FALSE; idhdl h = currPack->idroot; while(h != NULL) { if(IDTYP(h) == LINK_CMD) { idhdl hh=h->next; //Print("kill %s\n",IDID(h)); killhdl(h, currPack); h = hh; } else { h = h->next; } } hh=ssiToBeClosed; while(hh!=NULL) { //Print("close %s\n",hh->l->name); slClose(hh->l); hh=ssiToBeClosed; } } if (!singular_in_batchmode) { if (i<=0) { if (TEST_V_QUIET) { if (i==0) printf("Auf Wiedersehen.\n"); else printf("\n$Bye.\n"); } //#ifdef sun // #ifndef __svr4__ // _cleanup(); // _exit(0); // #endif //#endif i=0; } else { printf("\nhalt %d\n",i); } } exit(i); } } } const char *singular_date=__DATE__ " " __TIME__; extern "C" { void omSingOutOfMemoryFunc() { fprintf(stderr, "\nSingular error: no more memory\n"); omPrintStats(stderr); m2_end(14); /* should never get here */ exit(1); } } #ifdef SINGULAR_4_1 static n_coeffType n_pAE=n_unknown; static BOOLEAN ii_pAE_init(leftv res,leftv a) { if (a->Typ()!=INT_CMD) { WerrorS("`int` expected"); return TRUE; } else { res->rtyp=CRING_CMD; res->data=(void*)nInitChar(n_pAE,(void*)a->Data()); return FALSE; } } #endif /*2 * initialize components of Singular */ void siInit(char *name) { // factory default settings: ----------------------------------------------- On(SW_USE_EZGCD); On(SW_USE_CHINREM_GCD); //On(SW_USE_FF_MOD_GCD); On(SW_USE_EZGCD_P); On(SW_USE_QGCD); Off(SW_USE_NTL_SORT); // may be changed by an command line option factoryError=WerrorS; // memory initialization: ----------------------------------------------- om_Opts.OutOfMemoryFunc = omSingOutOfMemoryFunc; #ifndef OM_NDEBUG #ifndef __OPTIMIZE__ om_Opts.ErrorHook = dErrorBreak; #else om_Opts.Keep = 0; /* !OM_NDEBUG, __OPTIMIZE__*/ #endif #else om_Opts.Keep = 0; /* OM_NDEBUG */ #endif omInitInfo(); // options --------------------------------------------------------------- si_opt_1=0; // interpreter tables etc.: ----------------------------------------------- memset(&sLastPrinted,0,sizeof(sleftv)); sLastPrinted.rtyp=NONE; extern int iiInitArithmetic(); iiInitArithmetic(); // iparith.cc basePack=(package)omAlloc0(sizeof(*basePack)); currPack=basePack; idhdl h; h=enterid("Top", 0, PACKAGE_CMD, &IDROOT, TRUE); IDPACKAGE(h)->language = LANG_TOP; IDPACKAGE(h)=basePack; currPackHdl=h; basePackHdl=h; coeffs_BIGINT = nInitChar(n_Q,(void*)1); #if 1 // def HAVE_POLYEXTENSIONS if(TRUE) { n_coeffType type = nRegister(n_algExt, naInitChar); assume(type == n_algExt); type = nRegister(n_transExt, ntInitChar); assume(type == n_transExt); (void)type; } #endif // random generator: ----------------------------------------------- int t=initTimer(); if (t==0) t=1; initRTimer(); siSeed=t; factoryseed(t); siRandomStart=t; feOptSpec[FE_OPT_RANDOM].value = (void*) ((long)siRandomStart); // ressource table: ---------------------------------------------------- // Don't worry: ifdef OM_NDEBUG, then all these calls are undef'ed // hack such that all shared' libs in the bindir are loaded correctly feInitResources(name); // singular links: -------------------------------------------------- slStandardInit(); myynest=0; // semapohore 0 ----------------------------------------------------- int cpus=2; int cpu_n; #ifdef _SC_NPROCESSORS_ONLN if ((cpu_n=sysconf(_SC_NPROCESSORS_ONLN))>cpus) cpus=cpu_n; #elif defined(_SC_NPROCESSORS_CONF) if ((cpu_n=sysconf(_SC_NPROCESSORS_CONF))>cpus) cpus=cpu_n; #endif feSetOptValue(FE_OPT_CPUS, cpus); #ifdef SINGULAR_4_1 // default coeffs { idhdl h; h=enterid(omStrDup("QQ"),0/*level*/, CRING_CMD,&(basePack->idroot),FALSE /*init*/,FALSE /*search*/); IDDATA(h)=(char*)nInitChar(n_Q,NULL); h=enterid(omStrDup("ZZ"),0/*level*/, CRING_CMD,&(basePack->idroot),FALSE /*init*/,FALSE /*search*/); IDDATA(h)=(char*)nInitChar(n_Z,NULL); //h=enterid(omStrDup("RR"),0/*level*/, CRING_CMD,&(basePack->idroot),FALSE /*init*/,FALSE /*search*/); //IDDATA(h)=(char*)nInitChar(n_R,NULL); //h=enterid(omStrDup("CC"),0/*level*/, CRING_CMD,&(basePack->idroot),FALSE /*init*/,FALSE /*search*/); //IDDATA(h)=(char*)nInitChar(n_long_C,NULL); n_coeffType t=nRegister(n_unknown,n_AEInitChar); if (t!=n_unknown) { h=enterid(omStrDup("AE"),0/*level*/, CRING_CMD,&(basePack->idroot),FALSE /*init*/,FALSE /*search*/); IDDATA(h)=(char*)nInitChar(t,NULL); } t=nRegister(n_unknown,n_QAEInitChar); if (t!=n_unknown) { h=enterid(omStrDup("QAE"),0/*level*/, CRING_CMD,&(basePack->idroot),FALSE /*init*/,FALSE /*search*/); IDDATA(h)=(char*)nInitChar(t,NULL); } n_pAE=nRegister(n_unknown,n_pAEInitChar); if (n_pAE!=n_unknown) { iiAddCproc("kernel","pAE",FALSE,ii_pAE_init); } #ifdef HAVE_FLINT t=nRegister(n_unknown,flintQ_InitChar); if (t!=n_unknown) { h=enterid(omStrDup("flint_poly_Q"),0/*level*/, CRING_CMD,&(basePack->idroot),FALSE /*init*/,FALSE /*search*/); IDDATA(h)=(char*)nInitChar(t,NULL); } #endif } #endif // setting routines for PLURAL QRINGS: nc_NF=k_NF; gnc_gr_bba=k_gnc_gr_bba; gnc_gr_mora=k_gnc_gr_mora; sca_bba=k_sca_bba; sca_mora=k_sca_mora; sca_gr_bba=k_sca_gr_bba; // loading standard.lib ----------------------------------------------- if (! feOptValue(FE_OPT_NO_STDLIB)) { BITSET save1,save2; SI_SAVE_OPT(save1,save2); si_opt_2 &= ~Sy_bit(V_LOAD_LIB); iiLibCmd(omStrDup("standard.lib"), TRUE,TRUE,TRUE); SI_RESTORE_OPT(save1,save2); } errorreported = 0; } singular-4.0.3+ds/Singular/misc_ip.h000066400000000000000000000051171266270727000173410ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file misc_ip.h * * This file provides miscellaneous functionality. * * ABSTRACT: This file provides the following miscellaneous functionality: * - prime factorisation of bigints with prime factors < 2^31 * (This will require at most 256 MByte of RAM.) * - approximate square root of a bigint * * Most of the functioanlity implemented here had earlier been * coded in SINGULAR in some library. Due to performance reasons * these algorithms have been moved to the C/C++ kernel. * * @author Frank Seelisch * * **/ /*****************************************************************************/ #ifndef MISC_H #define MISC_H #include #include #include #include /** * Factorises a given bigint number n into its prime factors less * than or equal to a given bound, with corresponding multiplicities. * * The method finds all prime factors with multiplicities. If a positive * bound is given, then only the prime factors <= pBound are being found. * In this case, there may remain an unfactored portion m of n. * Also, when n is negative, m will contain the sign. If n is zero, m will * be zero. * The method returns a list L filled with three entries: * L[1] a list; L[1][i] contains the i-th prime factor of |n| as int or * bigint (sorted in ascending order), * L[2] a list; L[2][i] contains the multiplicity of L[1, i] in |n| as int * L[3] contains the remainder m as int or bigint, depending on the size, * * We thus have: n = L[1][1]^L[2][1] * ... * L[1][k]^L[2][k] * L[3], where * k is the number of mutually distinct prime factors (<= a provided non- * zero bound). * Note that for n = 0, L[1] and L[2] will be emtpy lists and L[3] will be * zero. * * @return the factorisation data in a SINGULAR-internal list **/ lists primeFactorisation( const number n, /**< [in] the bigint > 0 to be factorised */ const int pBound /**< [in] bound on the prime factors seeked */ ); #ifdef PDEBUG #if (OM_TRACK > 2) && defined(OM_TRACK_CUSTOM) // #include /* Needed for debug Version of p_SetRingOfLeftv, Oliver */ #include void p_SetRingOfLeftv(leftv l, ring r); #endif #endif #endif /* MISC_H */ singular-4.0.3+ds/Singular/mkinstalldirs000077500000000000000000000012101266270727000203410ustar00rootroot00000000000000#!/bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Last modified: 1994-03-25 # Public domain errstatus=0 for file in ${1+"$@"} ; do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d in ${1+"$@"} ; do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" 1>&2 mkdir "$pathcomp" || errstatus=$? fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here singular-4.0.3+ds/Singular/mmalloc.h000066400000000000000000000007231266270727000173400ustar00rootroot00000000000000#ifndef MMEMORY_H #define MMEMORY_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: declaration of routines for memory stuff */ #include #undef reallocSize #undef freeSize #ifdef __cplusplus extern "C" { #endif void* reallocSize(void* old_addr, size_t old_size, size_t new_size); void freeSize(void* addr, size_t size); #ifdef __cplusplus } #endif #endif singular-4.0.3+ds/Singular/mmstd.c000066400000000000000000000026031266270727000170320ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: standard version of C-memory management alloc func * i.e. (malloc/realloc/free) */ #include #include /* we provide these functions, so that the settings of OM_CHECK * and OM_TRACK are used, but only provide them if omalloc is not based * on them * already provided in libomalloc */ #if !defined(OMALLOC_USES_MALLOC) && !defined(X_OMALLOC) /* in mmstd.c, for some architectures freeSize() unconditionally uses the *system* free() */ /* sage ticket 5344: http://trac.sagemath.org/sage_trac/ticket/5344 */ /* solution: correctly check OMALLOC_USES_MALLOC from omalloc.h, */ /* do not rely on the default in Singular as libsingular may be different */ /* define this so that all addr allocated there are marked * as static, i.e. not metioned by omPrintUsedAddr*/ #define OM_MALLOC_MARK_AS_STATIC #define strdup_ strdup__ #include /// UGLY!!!!!!!!!!!!!!!! #else #include void freeSize(void* addr, size_t size) { (void) size; if (addr) free(addr); } void* reallocSize(void* old_addr, size_t old_size, size_t new_size) { if (old_addr && new_size) { return realloc(old_addr, new_size); } else { freeSize(old_addr, old_size); return malloc(new_size); } } #endif singular-4.0.3+ds/Singular/mod_lib.cc000066400000000000000000000064441266270727000174650ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #define SI_BUILTIN_LIBSTR(name) (char*) #name ".so", const char * const si_builtin_libs[] = { SI_FOREACH_BUILTIN(SI_BUILTIN_LIBSTR) NULL }; #undef SI_BUILTIN_LIBSTR #define BYTES_TO_CHECK 7 lib_types type_of_LIB(const char *newlib, char *libnamebuf) { const unsigned char mach_o[]={0xfe,0xed,0xfa,0xce,0}; const unsigned char mach_O[]={0xce,0xfa,0xed,0xfe,0}; const unsigned char mach_o64[]={0xfe,0xed,0xfa,0xcf,0}; const unsigned char mach_O64[]={0xcf,0xfa,0xed,0xfe,0}; const unsigned char mach_FAT[]={0xca,0xfe,0xba,0xbe,0}; const unsigned char mach_fat[]={0xbe,0xba,0xfe,0xca,0}; const unsigned char utf16be[]={0xfe,0xff,0}; const unsigned char utf16le[]={0xff,0xfe,0}; const unsigned char utf8ms[]={0xEF,0xBB,0xBF,0}; int i=0; while(si_builtin_libs[i]!=NULL) { if (strcmp(newlib,si_builtin_libs[i])==0) { if(libnamebuf!=NULL) strcpy(libnamebuf,newlib); return LT_BUILTIN; } i++; } char buf[BYTES_TO_CHECK+1]; /* one extra for terminating '\0' */ struct stat sb; int nbytes = 0; int ret; lib_types LT=LT_NONE; FILE * fp = feFopen( newlib, "r", libnamebuf, FALSE ); do { ret = stat(libnamebuf, &sb); } while((ret < 0) and (errno == EINTR)); if (fp==NULL) { return LT_NOTFOUND; } if((sb.st_mode & S_IFMT) != S_IFREG) { goto lib_type_end; } if ((nbytes = fread((char *)buf, sizeof(char), BYTES_TO_CHECK, fp)) == -1) { goto lib_type_end; /*NOTREACHED*/ } if (nbytes == 0) goto lib_type_end; else { buf[nbytes++] = '\0'; /* null-terminate it */ } if( (strncmp(buf, "\177ELF", 4)==0)) /* generic ELF */ { LT = LT_ELF; //omFree(newlib); //newlib = omStrDup(libnamebuf); goto lib_type_end; } if( (strncmp(buf, (const char *)mach_o, 4)==0) || (strncmp(buf, (const char *)mach_O, 4)==0)) /* generic Mach-O module */ { LT = LT_MACH_O; //omFree(newlib); //newlib = omStrDup(libnamebuf); goto lib_type_end; } if( (strncmp(buf, (const char *)mach_o64, 4)==0) || (strncmp(buf, (const char *)mach_O64, 4)==0)) /* generic Mach-O 64-bit module */ { LT = LT_MACH_O; //omFree(newlib); //newlib = omStrDup(libnamebuf); goto lib_type_end; } if( (strncmp(buf, (const char *)mach_FAT, 4)==0) || (strncmp(buf, (const char *)mach_fat, 4)==0)) /* generic Mach-O fat universal module */ { LT = LT_MACH_O; //omFree(newlib); //newlib = omStrDup(libnamebuf); goto lib_type_end; } if( (strncmp(buf, "\02\020\01\016\05\022@", 7)==0)) { LT = LT_HPUX; //omFree(newlib); //newlib = omStrDup(libnamebuf); goto lib_type_end; } if ((strncmp(buf,(const char *)utf16be,2)==0) ||(strncmp(buf,(const char *)utf16le,2)==0)) { WerrorS("UTF-16 not supported"); LT=LT_NOTFOUND; goto lib_type_end; } if (strncmp(buf,(const char *)utf8ms,3)==0) { WarnS("UTF-8 detected - may not work"); LT=LT_SINGULAR; goto lib_type_end; } if(isprint(buf[0]) || buf[0]=='\n') { LT = LT_SINGULAR; goto lib_type_end; } lib_type_end: fclose(fp); return LT; } singular-4.0.3+ds/Singular/mod_lib.h000066400000000000000000000020521266270727000173160ustar00rootroot00000000000000#ifndef MOD_LIB_H #define MOD_LIB_H #define SI_MOD_INIT0(name) name##_mod_init #ifdef STATIC_VERSION # define SI_MOD_INIT(name) SI_MOD_INIT0(name) #elif defined(DYNAMIC_VERSION) # define SI_MOD_INIT(name) mod_init #endif // Note that STATIC_VERSION and DYNAMIC_VERSION should not be defined in the following config header mod2.h! #include /* for SI_BUILTINMODULES_ADD */ /// Data for @c type_of_LIB to determine built-in modules, /// use @c add(name) to add built-in library to macro #define SI_FOREACH_BUILTIN(add) SI_BUILTINMODULES_ADD(add) #include /* for lib_types */ lib_types type_of_LIB(const char *newlib, char *fullname); #endif /* #if HAVE_GFANLIB #define SI_BUILTIN_GFANLIB(add) add(gfanlib) #endif #ifdef HAVE_MATHICGB # define SI_BUILTIN_MATHIC(add) add(singmathic) #endif #ifdef EMBED_PYTHON //TODO: the line above means that syzextra should be staticly embedded IFF pyobjects do so :((((( #define SI_BUILTIN_PYOBJECT(add) add(pyobject) add(syzextra) SI_BUILTIN_GFANLIB(add) SI_BUILTIN_MATHIC(add) #endif */ singular-4.0.3+ds/Singular/newstruct.cc000066400000000000000000000560411266270727000201140ustar00rootroot00000000000000#include #include #include #include #include #include #include #include struct newstruct_member_s; typedef struct newstruct_member_s *newstruct_member; struct newstruct_member_s { newstruct_member next; char * name; int typ; int pos; }; struct newstruct_proc_s; typedef struct newstruct_proc_a *newstruct_proc; struct newstruct_proc_a { newstruct_proc next; int t; /*tok id */ int args; /* number of args */ procinfov p; }; struct newstruct_desc_s { newstruct_member member; newstruct_desc parent; newstruct_proc procs; int size; // number of mebers +1 int id; // the type id assigned to this bb }; int newstruct_desc_size() { return sizeof(newstruct_desc_s); } char * newstruct_String(blackbox *b, void *d) { if (d==NULL) return omStrDup("oo"); else { newstruct_desc ad=(newstruct_desc)(b->data); newstruct_proc p=ad->procs; while((p!=NULL)&&(p->t!=STRING_CMD)) p=p->next; if (p!=NULL) { BOOLEAN sl; sleftv tmp; memset(&tmp,0,sizeof(tmp)); tmp.rtyp=ad->id; void * newstruct_Copy(blackbox*, void *); //forward declaration tmp.data=(void*)newstruct_Copy(b,d); idrec hh; memset(&hh,0,sizeof(hh)); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; sl=iiMake_proc(&hh,NULL,&tmp); if ((!sl)&& (iiRETURNEXPR.Typ() == STRING_CMD)) { char *res = omStrDup((char*)iiRETURNEXPR.CopyD()); iiRETURNEXPR.CleanUp(); iiRETURNEXPR.Init(); return res; } iiRETURNEXPR.CleanUp(); iiRETURNEXPR.Init(); } lists l=(lists)d; newstruct_member a=ad->member; StringSetS(""); loop { StringAppendS(a->name); StringAppendS("="); if ((!RingDependend(a->typ)) || ((l->m[a->pos-1].data==(void *)currRing) && (currRing!=NULL))) { if (l->m[a->pos].rtyp==LIST_CMD) { StringAppendS(""); } else { char *tmp2=omStrDup(l->m[a->pos].String()); if ((strlen(tmp2)>80)||(strchr(tmp2,'\n')!=NULL)) { StringAppendS("<"); StringAppendS(Tok2Cmdname(l->m[a->pos].rtyp)); StringAppendS(">"); } else StringAppendS(tmp2); omFree(tmp2); } } else StringAppendS("??"); if (a->next==NULL) break; StringAppendS("\n"); if(errorreported) break; a=a->next; } return StringEndS(); } } lists lCopy_newstruct(lists L) { lists N=(lists)omAlloc0Bin(slists_bin); int n=L->nr; ring save_ring=currRing; N->Init(n+1); for(;n>=0;n--) { if (RingDependend(L->m[n].rtyp) ||((L->m[n].rtyp==LIST_CMD)&&lRingDependend((lists)L->m[n].data))) { assume((L->m[n-1].rtyp==RING_CMD) || (L->m[n-1].data==NULL)); if(L->m[n-1].data!=NULL) { if (L->m[n-1].data!=(void*)currRing) rChangeCurrRing((ring)(L->m[n-1].data)); N->m[n].Copy(&L->m[n]); } else { N->m[n].rtyp=L->m[n].rtyp; N->m[n].data=idrecDataInit(L->m[n].rtyp); } } else if(L->m[n].rtyp==LIST_CMD) { N->m[n].rtyp=L->m[n].rtyp; N->m[n].data=(void *)lCopy((lists)(L->m[n].data)); } else if(L->m[n].rtyp>MAX_TOK) { N->m[n].rtyp=L->m[n].rtyp; blackbox *b=getBlackboxStuff(N->m[n].rtyp); N->m[n].data=(void *)b->blackbox_Copy(b,L->m[n].data); } else N->m[n].Copy(&L->m[n]); } if (currRing!=save_ring) rChangeCurrRing(save_ring); return N; } void * newstruct_Copy(blackbox*, void *d) { lists n1=(lists)d; return (void*)lCopy_newstruct(n1); } // Used by newstruct_Assign for overloaded '=' BOOLEAN newstruct_Assign_user(int op, leftv l, leftv r) { blackbox *ll=getBlackboxStuff(op); assume(ll->data != NULL); newstruct_desc nt=(newstruct_desc)ll->data; newstruct_proc p=nt->procs; while( (p!=NULL) && ((p->t!='=')||(p->args!=1)) ) p=p->next; if (p!=NULL) { BOOLEAN sl; idrec hh; memset(&hh,0,sizeof(hh)); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; sleftv tmp; memset(&tmp,0,sizeof(sleftv)); tmp.Copy(r); sl = iiMake_proc(&hh, NULL, &tmp); if (!sl) { if (iiRETURNEXPR.Typ() == op) { l->Copy(&iiRETURNEXPR); iiRETURNEXPR.Init(); return FALSE; } iiRETURNEXPR.CleanUp(); iiRETURNEXPR.Init(); } } return TRUE; } void lClean_newstruct(lists l) { if (l->nr>=0) { int i; ring r=NULL; for(i=l->nr;i>=0;i--) { if ((i>0) && (l->m[i-1].rtyp==RING_CMD)) r=(ring)(l->m[i-1].data); else r=NULL; l->m[i].CleanUp(r); } omFreeSize((ADDRESS)l->m, (l->nr+1)*sizeof(sleftv)); l->nr=-1; } omFreeBin((ADDRESS)l,slists_bin); } static BOOLEAN newstruct_Assign_same(leftv l, leftv r) { assume(l->Typ() == r->Typ()); if (l->Data()!=NULL) { lists n1=(lists)l->Data(); lClean_newstruct(n1); } lists n2=(lists)r->Data(); n2=lCopy_newstruct(n2); r->CleanUp(); if (l->rtyp==IDHDL) { IDDATA((idhdl)l->data)=(char *)n2; } else { l->data=(void *)n2; } return FALSE; } BOOLEAN newstruct_Op1(int op, leftv res, leftv arg) { // interpreter: arg is newstruct blackbox *a=getBlackboxStuff(arg->Typ()); newstruct_desc nt=(newstruct_desc)a->data; newstruct_proc p=nt->procs; while((p!=NULL) &&( (p->t!=op) || (p->args!=1) )) p=p->next; if (p!=NULL) { BOOLEAN sl; sleftv tmp; memset(&tmp,0,sizeof(sleftv)); tmp.Copy(arg); idrec hh; memset(&hh,0,sizeof(hh)); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; sl=iiMake_proc(&hh,NULL,&tmp); if (sl) return TRUE; else { res->Copy(&iiRETURNEXPR); iiRETURNEXPR.Init(); return FALSE; } } return blackboxDefaultOp1(op,res,arg); } BOOLEAN newstruct_Assign(leftv l, leftv r) { assume(l->Typ() > MAX_TOK); if (l->Typ()==r->Typ()) { return newstruct_Assign_same(l,r); } if (r->Typ()>MAX_TOK) { blackbox *rr=getBlackboxStuff(r->Typ()); if (l->Typ()!=r->Typ()) { newstruct_desc rrn=(newstruct_desc)rr->data; if (rrn==NULL) // this is not a newstruct { Werror("custom type %s(%d) cannot be assigned to newstruct %s(%d)", Tok2Cmdname(r->Typ()), r->Typ(), Tok2Cmdname(l->Typ()), l->Typ()); return TRUE; } // try to find a parent newstruct: newstruct_desc rrp=rrn->parent; while ((rrp!=NULL)&&(rrp->id!=l->Typ())) rrp=rrp->parent; if (rrp!=NULL) { if (l->rtyp==IDHDL) { IDTYP((idhdl)l->data)=r->Typ(); } else { l->rtyp=r->Typ(); } } else // unrelated types - look for custom conversion { sleftv tmp; if (! newstruct_Op1(l->Typ(), &tmp, r)) return newstruct_Assign(l, &tmp); if(!newstruct_Assign_user(l->Typ(), &tmp, r)) return newstruct_Assign(l, &tmp); } } if (l->Typ()==r->Typ()) { return newstruct_Assign_same(l,r); } } else { sleftv tmp; if(!newstruct_Assign_user(l->Typ(), &tmp, r)) return newstruct_Assign(l, &tmp); } Werror("assign %s(%d) = %s(%d)", Tok2Cmdname(l->Typ()),l->Typ(),Tok2Cmdname(r->Typ()),r->Typ()); return TRUE; } BOOLEAN newstruct_Op2(int op, leftv res, leftv a1, leftv a2) { // interpreter: a1 or a2 is newstruct blackbox *a=getBlackboxStuff(a1->Typ()); newstruct_desc nt; lists al=(lists)a1->Data(); if (a!=NULL) { nt=(newstruct_desc)a->data; switch(op) { case '.': { if (a2->name!=NULL) { BOOLEAN search_ring=FALSE; newstruct_member nm=nt->member; while ((nm!=NULL)&&(strcmp(nm->name,a2->name)!=0)) nm=nm->next; if ((nm==NULL) && (strncmp(a2->name,"r_",2)==0)) { nm=nt->member; while ((nm!=NULL)&&(strcmp(nm->name,a2->name+2)!=0)) nm=nm->next; if ((nm!=NULL)&&(RingDependend(nm->typ))) search_ring=TRUE; else nm=NULL; } if (nm==NULL) { Werror("member %s not found", a2->name); return TRUE; } if (search_ring) { ring r; res->rtyp=RING_CMD; res->data=al->m[nm->pos-1].data; r=(ring)res->data; if (r==NULL) { res->data=(void *)currRing; r=currRing; if (r!=NULL) r->ref++; else Werror("ring of this member is not set and no basering found"); } return r==NULL; } else if (RingDependend(nm->typ) || (al->m[nm->pos].RingDependend())) { if (al->m[nm->pos].data==NULL) { // NULL belongs to any ring ring r=(ring)al->m[nm->pos-1].data; if (r!=NULL) { r->ref--; al->m[nm->pos-1].data=NULL; al->m[nm->pos-1].rtyp=DEF_CMD; } } else { //Print("checking ring at pos %d for dat at pos %d\n",nm->pos-1,nm->pos); if ((al->m[nm->pos-1].data!=(void *)currRing) &&(al->m[nm->pos-1].data!=(void*)0L)) { Werror("different ring %lx(data) - %lx(basering)", (long unsigned)(al->m[nm->pos-1].data),(long unsigned)currRing); Werror("name of basering: %s",IDID(currRingHdl)); rWrite(currRing,TRUE);PrintLn(); idhdl hh=rFindHdl((ring)(al->m[nm->pos-1].data),NULL); const char *nn="??"; if (hh!=NULL) nn=IDID(hh); Werror("(possible) name of ring of data: %s",nn); rWrite((ring)(al->m[nm->pos-1].data),TRUE);PrintLn(); return TRUE; } } if ((currRing!=NULL)&&(al->m[nm->pos-1].data==NULL)) { // remember the ring, if not already set al->m[nm->pos-1].data=(void *)currRing; al->m[nm->pos-1].rtyp=RING_CMD; currRing->ref++; } } else if ((nm->typ==DEF_CMD)||(nm->typ==LIST_CMD)) { if (al->m[nm->pos-1].data==NULL) { al->m[nm->pos-1].data=(void*)currRing; if (currRing!=NULL) currRing->ref++; } } Subexpr r=(Subexpr)omAlloc0Bin(sSubexpr_bin); r->start = nm->pos+1; memcpy(res,a1,sizeof(sleftv)); memset(a1,0,sizeof(sleftv)); if (res->e==NULL) res->e=r; else { Subexpr sh=res->e; while (sh->next != NULL) sh=sh->next; sh->next=r; } return FALSE; } else { WerrorS("name expected"); return TRUE; } } } } else { a=getBlackboxStuff(a2->Typ()); nt=(newstruct_desc)a->data; al=(lists)a2->Data(); } newstruct_proc p=nt->procs; while((p!=NULL) && ( (p->t!=op) || (p->args!=2) )) p=p->next; if (p!=NULL) { BOOLEAN sl; sleftv tmp; memset(&tmp,0,sizeof(sleftv)); tmp.Copy(a1); tmp.next=(leftv)omAlloc0(sizeof(sleftv)); tmp.next->Copy(a2); idrec hh; memset(&hh,0,sizeof(hh)); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; sl=iiMake_proc(&hh,NULL,&tmp); if (sl) return TRUE; else { res->Copy(&iiRETURNEXPR); iiRETURNEXPR.Init(); return FALSE; } } return blackboxDefaultOp2(op,res,a1,a2); } // BOOLEAN opM(int op, leftv res, leftv args) BOOLEAN newstruct_OpM(int op, leftv res, leftv args) { // interpreter: args->1. arg is newstruct blackbox *a=getBlackboxStuff(args->Typ()); newstruct_desc nt=(newstruct_desc)a->data; switch(op) { case STRING_CMD: { res->data=(void *)a->blackbox_String(a,args->Data()); res->rtyp=STRING_CMD; return FALSE; } default: break; } newstruct_proc p=nt->procs; while((p!=NULL) &&( (p->t!=op) || (p->args!=4) )) p=p->next; if (p!=NULL) { BOOLEAN sl; sleftv tmp; memset(&tmp,0,sizeof(sleftv)); tmp.Copy(args); idrec hh; memset(&hh,0,sizeof(hh)); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; sl=iiMake_proc(&hh,NULL,&tmp); if (sl) return TRUE; else { res->Copy(&iiRETURNEXPR); iiRETURNEXPR.Init(); return FALSE; } } return blackboxDefaultOpM(op,res,args); } void newstruct_destroy(blackbox */*b*/, void *d) { if (d!=NULL) { lists n=(lists)d; lClean_newstruct(n); } } void *newstruct_Init(blackbox *b) { newstruct_desc n=(newstruct_desc)b->data; lists l=(lists)omAlloc0Bin(slists_bin); l->Init(n->size); newstruct_member nm=n->member; while (nm!=NULL) { l->m[nm->pos].rtyp=nm->typ; if (RingDependend(nm->typ) ||(nm->typ==DEF_CMD)||(nm->typ==LIST_CMD)) l->m[nm->pos-1].rtyp=RING_CMD; l->m[nm->pos].data=idrecDataInit(nm->typ); nm=nm->next; } return l; } BOOLEAN newstruct_CheckAssign(blackbox */*b*/, leftv L, leftv R) { int lt=L->Typ(); int rt=R->Typ(); if ((lt!=DEF_CMD)&&(lt!=rt)) { const char *rt1=Tok2Cmdname(rt); const char *lt1=Tok2Cmdname(lt); if ((rt>0) && (lt>0) && ((strcmp(rt1,Tok2Cmdname(0))==0)||(strcmp(lt1,Tok2Cmdname(0))==0))) { Werror("can not assign %s(%d) to member of type %s(%d)", rt1,rt,lt1,lt); } else { Werror("can not assign %s to member of type %s",rt1,lt1); } return TRUE; } return FALSE; } /* check internal structure: * BOOLEAN newstruct_Check(blackbox *b, void *d) { newstruct_desc n=(newstruct_desc)b->data; lists l=(lists)d; newstruct_member nm=n->member; while (nm!=NULL) { if ((l->m[nm->pos].rtyp!=nm->typ) &&( nm->typ!=DEF_CMD)) { Werror("type change in member %s (%s(%d) -> %s(%d))",nm->name, Tok2Cmdname(nm->typ),nm->typ, Tok2Cmdname(l->m[nm->pos].rtyp),l->m[nm->pos].rtyp); return TRUE; } nm=nm->next; } return FALSE; } */ BOOLEAN newstruct_serialize(blackbox *b, void *d, si_link f) { newstruct_desc dd=(newstruct_desc)b->data; sleftv l; memset(&l,0,sizeof(l)); l.rtyp=STRING_CMD; l.data=(void*)getBlackboxName(dd->id); f->m->Write(f, &l); lists ll=(lists)d; int Ll=lSize(ll); l.rtyp=INT_CMD; l.data=(void*)(long)Ll; f->m->Write(f, &l); // set all entries corresponding to "real" mebers to 1 in rings char *rings=(char*)omAlloc0(Ll+1); newstruct_member elem=dd->member; while (elem!=NULL) { rings[elem->pos]='\1'; elem=elem->next; } int i; BOOLEAN ring_changed=FALSE; ring save_ring=currRing; for(i=0;i<=Ll;i++) { if (rings[i]=='\0') // ring entry for pos i+1 { if (ll->m[i].data!=NULL) { ring_changed=TRUE; f->m->SetRing(f,(ring)ll->m[i].data,TRUE); } } f->m->Write(f,&(ll->m[i])); } if (ring_changed) f->m->SetRing(f,save_ring,FALSE); return FALSE; } BOOLEAN newstruct_deserialize(blackbox **b, void **d, si_link f) { // newstruct is serialiazed as analog to a list, // just read a list and take data, // rtyp must be set correctly (to the blackbox id) by routine calling // newstruct_deserialize leftv l=f->m->Read(f); // int: length of list int Ll=(int)(long)(l->data); omFree(l); lists L=(lists)omAllocBin(slists_bin); L->Init(Ll+1); for(int i=0;i<=Ll;i++) { l=f->m->Read(f); memcpy(&(L->m[i]),l,sizeof(sleftv)); omFree(l); } //newstruct_desc n=(newstruct_desc)b->data; //TODO: check compatibility of list l->data with description in n *d=L; return FALSE; } void newstruct_Print(blackbox *b,void *d) { newstruct_desc dd=(newstruct_desc)b->data; newstruct_proc p=dd->procs; while((p!=NULL)&&(p->t!=PRINT_CMD)) p=p->next; if (p!=NULL) { BOOLEAN sl; sleftv tmp; memset(&tmp,0,sizeof(tmp)); tmp.rtyp=dd->id; tmp.data=(void*)newstruct_Copy(b,d); idrec hh; memset(&hh,0,sizeof(hh)); hh.id=Tok2Cmdname(p->t); hh.typ=PROC_CMD; hh.data.pinf=p->p; sl=iiMake_proc(&hh,NULL,&tmp); if (!sl) { if (iiRETURNEXPR.Typ()!=NONE) Warn("ignoring return value (%s)",Tok2Cmdname(iiRETURNEXPR.Typ())); iiRETURNEXPR.CleanUp(); } iiRETURNEXPR.Init(); } else blackbox_default_Print(b,d); } void newstruct_setup(const char *n, newstruct_desc d ) { blackbox *b=(blackbox*)omAlloc0(sizeof(blackbox)); // all undefined entries will be set to default in setBlackboxStuff // the default Print is quite useful, // all other are simply error messages b->blackbox_destroy=newstruct_destroy; b->blackbox_String=newstruct_String; b->blackbox_Print=newstruct_Print;//blackbox_default_Print; b->blackbox_Init=newstruct_Init; b->blackbox_Copy=newstruct_Copy; b->blackbox_Assign=newstruct_Assign; b->blackbox_Op1=newstruct_Op1; b->blackbox_Op2=newstruct_Op2; //b->blackbox_Op3=blackboxDefaultOp3; b->blackbox_OpM=newstruct_OpM; b->blackbox_CheckAssign=newstruct_CheckAssign; b->blackbox_serialize=newstruct_serialize; b->blackbox_deserialize=newstruct_deserialize; b->data=d; b->properties=1; // list_like int rt=setBlackboxStuff(b,n); d->id=rt; //Print("create type %d (%s)\n",rt,n); } static newstruct_desc scanNewstructFromString(const char *s, newstruct_desc res) { char *ss=omStrDup(s); char *p=ss; char *start; int t; char c; newstruct_member elem; idhdl save_ring=currRingHdl; currRingHdl=(idhdl)1; // fake ring detection loop { // read type: while ((*p!='\0') && (*p<=' ')) p++; start=p; while (isalnum(*p)) p++; *p='\0'; IsCmd(start,t); if (t==0) { Werror("unknown type `%s`",start); omFree(ss); omFree(res); currRingHdl=save_ring; return NULL; } if (RingDependend(t) || (t==DEF_CMD)||(t==LIST_CMD)) res->size++; // one additional field for the ring (before the data) //Print("found type %s at real-pos %d",start,res->size); elem=(newstruct_member)omAlloc0(sizeof(*elem)); // read name: p++; while ((*p!='\0') && (*p<=' ')) p++; start=p; while (isalnum(*p)) p++; c=*p; *p='\0'; elem->typ=t; elem->pos=res->size; if ((*start=='\0') /*empty name*/||(isdigit(*start))) { WerrorS("illegal/empty name for element"); goto error_in_newstruct_def; } elem->name=omStrDup(start); //Print(" name:%s\n",start); elem->next=res->member; res->member=elem; res->size++; // next ? *p=c; while ((*p!='\0') && (*p<=' ')) p++; if (*p!=',') { if (*p!='\0') { Werror("unknown character in newstruct:>>%s<<",p); goto error_in_newstruct_def; } break; // end-of-list } p++; } omFree(ss); currRingHdl=save_ring; //Print("new type with %d elements\n",res->size); //newstructShow(res); return res; error_in_newstruct_def: omFree(elem); omFree(ss); omFree(res); currRingHdl=save_ring; return NULL; } newstruct_desc newstructFromString(const char *s) { newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res)); res->size=0; return scanNewstructFromString(s,res); } newstruct_desc newstructChildFromString(const char *parent, const char *s) { // find parent: int parent_id=0; blackboxIsCmd(parent,parent_id); if (parent_id>%s< not found",parent); return NULL; } blackbox *parent_bb=getBlackboxStuff(parent_id); // check for the correct type: if (parent_bb->blackbox_destroy!=newstruct_destroy) { Werror(">>%s< is not a user defined type",parent); return NULL; } // setup for scanNewstructFromString: newstruct_desc res=(newstruct_desc)omAlloc0(sizeof(*res)); newstruct_desc parent_desc=(newstruct_desc)parent_bb->data; res->size=parent_desc->size; res->member=parent_desc->member; res->parent=parent_desc; return scanNewstructFromString(s,res); } void newstructShow(newstruct_desc d) { newstruct_member elem; Print("id: %d\n",d->id); elem=d->member; while (elem!=NULL) { Print(">>%s<< at pos %d, type %d (%s)\n",elem->name,elem->pos,elem->typ,Tok2Cmdname(elem->typ)); if (RingDependend(elem->typ)|| (elem->typ==DEF_CMD) ||(elem->typ==LIST_CMD)) Print(">>r_%s<< at pos %d, shadow ring\n",elem->name,elem->pos-1); elem=elem->next; } newstruct_proc p=d->procs; while (p!=NULL) { Print("op:%d(%s) with %d args -> %s\n",p->t,iiTwoOps(p->t),p->args,p->p->procname); p=p->next; } } BOOLEAN newstruct_set_proc(const char *bbname,const char *func, int args,procinfov pr) { int id=0; blackboxIsCmd(bbname,id); if (id>%s<< is not a newstruct type",bbname); return TRUE; } blackbox *bb=getBlackboxStuff(id); newstruct_desc desc=(newstruct_desc)bb->data; newstruct_proc p=(newstruct_proc)omAlloc(sizeof(*p)); p->next=desc->procs; desc->procs=p; idhdl save_ring=currRingHdl; currRingHdl=(idhdl)1; // fake ring detection int tt; if(!(tt=IsCmd(func,p->t))) { int t; if((t=iiOpsTwoChar(func))!=0) { p->t=t; tt=CMD_2; /* ..,::, ==, <=, <>, >= !=i and +,-,*,/,%,.... */ if ((t==PLUSPLUS) ||(t==MINUSMINUS) ||(t=='=')) tt=CMD_1; /* ++,--,= */ else if (t=='(') /* proc call */ tt=CMD_M; else if (t=='-') /* unary and binary - */ tt=CMD_12; } else { desc->procs=p->next; omFreeSize(p,sizeof(*p)); Werror(">>%s<< is not a kernel command",func); currRingHdl = save_ring; return TRUE; } } switch(tt) { // type conversions: case BIGINTMAT_CMD: case MATRIX_CMD: case INTMAT_CMD: case RING_CMD: case RING_DECL: case RING_DECL_LIST: case ROOT_DECL: case ROOT_DECL_LIST: // operations: case CMD_1: if(args!=1) { Warn("args must be 1 in %s",my_yylinebuf);args=1;} break; case CMD_2: if(args!=2) { Warn("args must be 2 in %s",my_yylinebuf);args=2;} break; case CMD_3: if(args!=3) { Warn("args must be 3 in %s",my_yylinebuf);args=3;} break; case CMD_12: if((args!=1)&&(args!=2)) { Werror("args must in 1 or 2 in %s",my_yylinebuf);} break; case CMD_13: if((args!=1)&&(args!=3)) { Werror("args must in 1 or 3 in %s",my_yylinebuf);} break; case CMD_23: if((args<2)||(args>3)) { Werror("args must in 2..3 in %s",my_yylinebuf);} break; case CMD_123: if((args<1)||(args>3)) { Werror("args must in 1..3 in %s",my_yylinebuf);} break; case CMD_M: if(args!=4) { Warn("args must be 4 in %s",my_yylinebuf);args=4;} break; default: Werror("unknown token type %d in %s",tt,my_yylinebuf); break; } currRingHdl = save_ring; if (errorreported) { desc->procs=p->next; omFreeSize(p,sizeof(*p)); return TRUE; } p->args=args; p->p=pr; pr->ref++; pr->is_static=0; return FALSE; } singular-4.0.3+ds/Singular/newstruct.h000066400000000000000000000006541266270727000177550ustar00rootroot00000000000000#ifndef NEWTYPES_H #define NEWTYPES_H typedef struct newstruct_desc_s *newstruct_desc; void newstruct_setup(const char * name, newstruct_desc d); int newstruct_desc_size(); newstruct_desc newstructFromString(const char *s); newstruct_desc newstructChildFromString(const char *p, const char *s); BOOLEAN newstruct_set_proc(const char *name,const char *func,int args, procinfov p); void newstructShow(newstruct_desc d); #endif singular-4.0.3+ds/Singular/number2.cc000066400000000000000000000172321266270727000174270ustar00rootroot00000000000000#include "kernel/mod2.h" // general settings/macros #ifdef SINGULAR_4_1 #include // for Print, WerrorS #include // nRegister, coeffs.h #include // ZnmInfo #include // bigintmat #include // BIGINTs: nlGMP #include // IsPrime #include // blackbox type #include // IsPrime #include // for SModulFunctions, leftv #include char *crString(coeffs c) { if (c==NULL) { return omStrDup("oo"); } return omStrDup(nCoeffName(c)); } void crPrint(coeffs c) { char *s=crString(c); PrintS(s); omFree(s); } // ----------------------------------------------------------- // interpreter stuff for cring/coeffs // ----------------------------------------------------------- BOOLEAN jjCRING_Zp(leftv res, leftv a, leftv b) { coeffs c1=(coeffs)a->Data(); int i2=(int)(long)b->Data(); if (c1->type==n_Z) { if (i2==IsPrime(i2)) { res->data=(void *)nInitChar(n_Zp,(void*)(long)i2); } else { ZnmInfo info; mpz_ptr modBase= (mpz_ptr) omAlloc(sizeof(mpz_t)); mpz_init_set_ui(modBase,i2); info.base= modBase; info.exp= 1; res->data=(void *)nInitChar(n_Zn,&info); } return FALSE; } return TRUE; } BOOLEAN jjCRING_Zm(leftv res, leftv a, leftv b) { coeffs c1=(coeffs)a->Data(); number i2=(number)b->Data(); if (c1->type==n_Z) { ZnmInfo info; number modBase= (number) omAlloc(sizeof(mpz_t)); nlGMP(i2,modBase,coeffs_BIGINT); // FIXME? TODO? // extern void nlGMP(number &i, number n, const coeffs r); // to be replaced with n_MPZ(modBase,i2,coeffs_BIGINT); // ? info.base= (mpz_ptr)modBase; info.exp= 1; res->data=(void *)nInitChar(n_Zn,&info); return FALSE; } return TRUE; } // ----------------------------------------------------------- // interpreter stuff for Number/number2 // ----------------------------------------------------------- BOOLEAN jjNUMBER2_OP2(leftv res, leftv a, leftv b) { int op=iiOp; // binary operations for number2 number2 a2=NULL; number aa=NULL; number2 b2=NULL; number bb=NULL; if (a->Typ()==CNUMBER_CMD) { a2=(number2)a->Data(); aa=a2->n; } if (b->Typ()==CNUMBER_CMD) { b2=(number2)b->Data(); if ((a2!=NULL) && (a2->cf!=b2->cf)) { WerrorS("Number not compatible"); return TRUE; } bb=b2->n; } number2 r=(number2)omAlloc(sizeof(*r)); if (a2!=NULL) r->cf=a2->cf; else r->cf=b2->cf; if (r->cf==NULL) op=0; // force error else if (a2==NULL) { if (a->Typ()==INT_CMD) aa=n_Init((long)a->Data(),r->cf); else if (a->Typ()==BIGINT_CMD) { //aa=n_Init_bigint((number)a->Data(),coeffs_BIGINT,r->cf); nMapFunc nMap=n_SetMap(coeffs_BIGINT,r->cf); aa=nMap((number)a->Data(),coeffs_BIGINT,r->cf); } else op=0; } if ((b2==NULL) &&(op!='^') &&(op!=0)) { if (b->Typ()==INT_CMD) bb=n_Init((long)b->Data(),r->cf); else if (b->Typ()==BIGINT_CMD) { //bb=n_Init_bigint((number)b->Data(),coeffs_BIGINT,r->cf); nMapFunc nMap=n_SetMap(coeffs_BIGINT,r->cf); bb=nMap((number)b->Data(),coeffs_BIGINT,r->cf); } else op=0; } switch(op) { case '+': r->n=n_Add(aa,bb,r->cf);break; case '-': r->n=n_Sub(aa,bb,r->cf);break; case '*': r->n=n_Mult(aa,bb,r->cf);break; case '/': r->n=n_Div(aa,bb,r->cf);break; case '%': r->n=n_IntMod(aa,bb,r->cf);break; case '^': n_Power(aa,(int)(long)b->Data(),&(r->n),r->cf); break; default: Werror("unknown binary operation %s(%d)",Tok2Cmdname(op),op); omFree(r); return TRUE; } res->data=(void*)r; r->cf->ref++; return FALSE; } BOOLEAN jjNUMBER2_OP1(leftv res, leftv a) { int op=iiOp; // unary operations for number2 number2 a2=(number2)a->Data(); number2 r=(number2)omAlloc(sizeof(*r)); r->cf=a2->cf; if (a2->cf==NULL) op=0; // force error switch(op) { case '-': r->n=n_Copy(a2->n,a2->cf);r->n=n_InpNeg(r->n,a2->cf);break; default: Werror("unknown unary operation %s(%d)",Tok2Cmdname(op),op); omFree(r); return TRUE; } res->data=(void*)r; r->cf->ref++; return FALSE; } BOOLEAN jjNUMBER2CR(leftv res, leftv a, leftv b) { number2 r=(number2)omAlloc(sizeof(*r)); r->cf=(coeffs)b->CopyD(); BOOLEAN bo=FALSE; switch(a->Typ()) { case INT_CMD: r->n=n_Init((long)a->Data(),r->cf); break; case BIGINT_CMD: { nMapFunc nMap=n_SetMap(coeffs_BIGINT,r->cf); r->n=nMap((number)a->Data(),coeffs_BIGINT,r->cf); break; } case NUMBER_CMD: { nMapFunc nMap=n_SetMap(currRing->cf,r->cf); if (nMap!=NULL) r->n=nMap((number)a->Data(),currRing->cf,r->cf); else bo=TRUE; break; } case CNUMBER_CMD: { number2 a2=(number2)a->Data(); if (a2->cf==NULL) bo=TRUE; else { nMapFunc nMap=n_SetMap(a2->cf,r->cf); if (nMap!=NULL) r->n=nMap(a2->n,a2->cf,r->cf); else bo=TRUE; } break; } default: bo=TRUE; break; } if (bo) { Werror("no conversion to Number from %s",Tok2Cmdname(a->Typ())); omFreeSize(r,sizeof(*r)); } else res->data=(void*)r; return bo; } BOOLEAN jjN2_CR(leftv res, leftv a) // number2 ->cring { number2 n=(number2)a->Data(); n->cf->ref++; res->data=(void*)n->cf; return FALSE; } BOOLEAN jjCM_CR(leftv res, leftv a) // cmatrix ->cring { bigintmat *b=(bigintmat*)a->Data(); coeffs cf=b->basecoeffs(); if (cf!=NULL) { cf->ref++; } res->data=(void*)cf; return FALSE; } BOOLEAN jjCMATRIX_3(leftv res, leftv r, leftv c,leftv cf) { bigintmat *b=new bigintmat((int)(long)r->Data(), (int)(long)c->Data(), (coeffs)cf->Data()); res->data=(char*)b; return FALSE; } BOOLEAN jjN2_N(leftv res, leftv a) // number2 ->number { number2 n2=(number2)a->Data(); BOOLEAN bo=TRUE; if (currRing!=NULL) { nMapFunc nMap=n_SetMap(n2->cf,currRing->cf); if (nMap!=NULL) { res->data=(void*)nMap(n2->n,n2->cf,currRing->cf); bo=FALSE; } } return bo; } BOOLEAN jjEQUAL_CR(leftv res, leftv a, leftv b) { coeffs a2=(coeffs)a->Data(); coeffs b2=(coeffs)b->Data(); res->data=(void*)(long)(a2==b2); return FALSE; } // ----------------------------------------------------------- // operations with Number/number2 // ----------------------------------------------------------- number2 n2Copy(const number2 d) { number2 r=NULL; if ((d!=NULL)&&(d->cf!=NULL)) { r=(number2)omAlloc(sizeof(*r)); d->cf->ref++; r->cf=d->cf; if (d->cf!=NULL) r->n=n_Copy(d->n,d->cf); else r->n=NULL; } return r; } void n2Delete(number2 &d) { if (d!=NULL) { if (d->cf!=NULL) { n_Delete(&d->n,d->cf); nKillChar(d->cf); } omFreeSize(d,sizeof(*d)); d=NULL; } } char *n2String(number2 d, BOOLEAN typed) { StringSetS(""); if ((d!=NULL) && (d->cf!=NULL)) { if (typed) StringAppendS("Number("); n_Write(d->n,d->cf); if (typed) StringAppendS(")"); } else StringAppendS("oo"); return StringEndS(); } void n2Print(number2 d) { char *s=n2String(d,FALSE); PrintS(s); omFree(s); } #include BOOLEAN jjBIM2_CR(leftv res, leftv a) // bigintmat ->cring { bigintmat *b=(bigintmat*)a->Data(); coeffs cf=b->basecoeffs(); cf->ref++; res->data=(void*)cf; return FALSE; } BOOLEAN jjR2_CR(leftv res, leftv a) // ring ->cring { ring r=(ring)a->Data(); coeffs cf=r->cf; cf->ref++; res->data=(void*)cf; return FALSE; } #endif singular-4.0.3+ds/Singular/number2.h000066400000000000000000000025421266270727000172670ustar00rootroot00000000000000#ifndef NUMBER2_H #define NUMBER2_H #include #ifdef SINGULAR_4_1 #include #include #include struct snumber2; typedef struct snumber2 * number2; struct snumber2 { coeffs cf; number n; }; static inline number2 n2Init(long i, coeffs c) { number2 N=(number2)omAlloc0(sizeof(snumber2)); if (c!=NULL) { N->cf=c; N->n=n_Init(i,c);} return N;} char *crString(coeffs c); void crPrint(coeffs cf); BOOLEAN jjCRING_Zp(leftv res, leftv a, leftv b); BOOLEAN jjCRING_Zm(leftv res, leftv a, leftv b); BOOLEAN jjEQUAL_CR(leftv res, leftv a, leftv b); // compare cring // type conversion: BOOLEAN jjNUMBER2CR(leftv res, leftv a, leftv b); // ,cring ->number2 BOOLEAN jjN2_CR(leftv res, leftv a); // number2 ->cring BOOLEAN jjCM_CR(leftv res, leftv a); // cmatrix ->cring BOOLEAN jjBIM2_CR(leftv res, leftv a); // bigint ->cring BOOLEAN jjR2_CR(leftv res, leftv a); // ring ->cring BOOLEAN jjN2_N(leftv res, leftv a); // number2 ->number // operations: BOOLEAN jjNUMBER2_OP1(leftv res, leftv a); BOOLEAN jjNUMBER2_OP2(leftv res, leftv a, leftv b); number2 n2Copy(const number2 d); void n2Delete(number2 &d); char *n2String(number2 d, BOOLEAN typed); void n2Print(number2 d); BOOLEAN jjCMATRIX_3(leftv, leftv, leftv,leftv); #endif #endif singular-4.0.3+ds/Singular/pcv.cc000066400000000000000000000175211266270727000166460ustar00rootroot00000000000000/***************************************** * Computer Algebra System SINGULAR * *****************************************/ /* * ABSTRACT: conversion between polys and coef vectors */ #include #ifdef HAVE_PCV #include #include #include #include #include #include #include #include #include static int pcvMaxDegree; static int pcvTableSize; static int pcvIndexSize; static unsigned* pcvTable=NULL; static unsigned** pcvIndex=NULL; lists pcvLAddL(lists l1,lists l2) { lists l0=(lists)omAllocBin(slists_bin); int i=l1->nr; if(l1->nrnr) i=l2->nr; l0->Init(i+1); for(;i>=0;i--) { if(i<=l1->nr&&(l1->m[i].rtyp==POLY_CMD||l1->m[i].rtyp==VECTOR_CMD)) { l0->m[i].rtyp=l1->m[i].rtyp; l0->m[i].data=pCopy((poly)l1->m[i].data); if(i<=l2->nr&&l2->m[i].rtyp==l1->m[i].rtyp) l0->m[i].data=pAdd((poly)l0->m[i].data,pCopy((poly)l2->m[i].data)); } else if(i<=l2->nr&&(l2->m[i].rtyp==POLY_CMD||l2->m[i].rtyp==VECTOR_CMD)) { l0->m[i].rtyp=l2->m[i].rtyp; l0->m[i].data=pCopy((poly)l2->m[i].data); } } return(l0); } lists pcvPMulL(poly p,lists l1) { lists l0=(lists)omAllocBin(slists_bin); l0->Init(l1->nr+1); for(int i=l1->nr;i>=0;i--) { if(l1->m[i].rtyp==POLY_CMD) { l0->m[i].rtyp=POLY_CMD; l0->m[i].data=ppMult_qq(p,(poly)l1->m[i].data); } } return(l0); } BOOLEAN pcvLAddL(leftv res,leftv h) { short t[]={2,LIST_CMD,LIST_CMD}; if (iiCheckTypes(h,t,1)) { lists l1=(lists)h->Data(); h=h->next; lists l2=(lists)h->Data(); res->rtyp=LIST_CMD; res->data=(void*)pcvLAddL(l1,l2); return FALSE; } return TRUE; } BOOLEAN pcvPMulL(leftv res,leftv h) { short t[]={2,POLY_CMD,LIST_CMD}; if (iiCheckTypes(h,t,1)) { poly p=(poly)h->Data(); h=h->next; lists l=(lists)h->Data(); res->rtyp=LIST_CMD; res->data=(void*)pcvPMulL(p,l); return FALSE; } return TRUE; } int pcvDeg(poly p) { int d=0; for(int i=currRing->N;i>=1;i--) d+=pGetExp(p,i); return d; } int pcvMinDeg(poly p) { if(!p) return -1; int md=pcvDeg(p); pIter(p); while(p) { int d=pcvDeg(p); if(d=0&&md>d)||md==-1) md=d; } } return(md); } BOOLEAN pcvMinDeg(leftv res,leftv h) { if(h) { if(h->Typ()==POLY_CMD) { res->rtyp=INT_CMD; res->data=(void*)(long)pcvMinDeg((poly)h->Data()); return FALSE; } else if(h->Typ()==MATRIX_CMD) { res->rtyp=INT_CMD; res->data=(void*)(long)pcvMinDeg((matrix)h->Data()); return FALSE; } } WerrorS(" expected"); return TRUE; } void pcvInit(int d) { if(d<0) d=1; pcvMaxDegree=d+1; pcvTableSize=currRing->N*pcvMaxDegree*sizeof(unsigned); pcvTable=(unsigned*)omAlloc0(pcvTableSize); pcvIndexSize=currRing->N*sizeof(unsigned*); pcvIndex=(unsigned**)omAlloc(pcvIndexSize); for(int i=0;iN;i++) pcvIndex[i]=pcvTable+i*pcvMaxDegree; for(int i=0;iN;i++) { k=0; for(int j=0;junsigned(~0)-k) { j=pcvMaxDegree; i=currRing->N; WerrorS("unsigned overflow"); } else pcvIndex[i][j]=k+=l; } } } void pcvClean() { if(pcvTable) { omFreeSize(pcvTable,pcvTableSize); pcvTable=NULL; } if(pcvIndex) { omFreeSize(pcvIndex,pcvIndexSize); pcvIndex=NULL; } } int pcvM2N(poly m) { unsigned n=0,dn,d=0; for(int i=0;iN;i++) { d+=pGetExp(m,i+1); dn=pcvIndex[i][d]; if(dn>MAX_INT_VAL-n) { i=currRing->N; WerrorS("component overflow"); } else n+=dn; } return n+1; } poly pcvN2M(int n) { n--; poly m=pOne(); int i,j=0,k; for(i=currRing->N-1;i>=0;i--) { k=j; for(j=0; (jN-1) pSetExp(m,i+2,k-j); } if(n==0) { pSetExp(m,1,j); pSetm(m); return m; } else { pLmDelete(&m); return NULL; } } poly pcvP2CV(poly p,int d0,int d1) { poly cv=NULL; while(p) { int d=pcvDeg(p); if(d0<=d&&dInit(pl->nr+1); pcvInit(d1); for(int i=pl->nr;i>=0;i--) { if(pl->m[i].rtyp==POLY_CMD) { cvl->m[i].rtyp=VECTOR_CMD; cvl->m[i].data=pcvP2CV((poly)pl->m[i].data,d0,d1); } } pcvClean(); return cvl; } lists pcvCV2P(lists cvl,int d0,int d1) { lists pl=(lists)omAllocBin(slists_bin); pl->Init(cvl->nr+1); pcvInit(d1); for(int i=cvl->nr;i>=0;i--) { if(cvl->m[i].rtyp==VECTOR_CMD) { pl->m[i].rtyp=POLY_CMD; pl->m[i].data=pcvCV2P((poly)cvl->m[i].data,d0,d1); } } pcvClean(); return pl; } BOOLEAN pcvP2CV(leftv res,leftv h) { if(currRing) { short t[]={3,LIST_CMD,INT_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { lists p=(lists)h->Data(); h=h->next; int d0=(int)(long)h->Data(); h=h->next; int d1=(int)(long)h->Data(); res->rtyp=LIST_CMD; res->data=(void*)pcvP2CV(p,d0,d1); return FALSE; } return TRUE; } WerrorS("no ring active"); return TRUE; } BOOLEAN pcvCV2P(leftv res,leftv h) { if(currRing) { short t[]={3,LIST_CMD,INT_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { lists pl=(lists)h->Data(); h=h->next; int d0=(int)(long)h->Data(); h=h->next; int d1=(int)(long)h->Data(); res->rtyp=LIST_CMD; res->data=(void*)pcvCV2P(pl,d0,d1); return FALSE; } return TRUE; } WerrorS("no ring active"); return TRUE; } int pcvDim(int d0,int d1) { if(d0<0) d0=0; if(d1<0) d1=0; pcvInit(d1); int d=pcvIndex[currRing->N-1][d1]-pcvIndex[currRing->N-1][d0]; pcvClean(); return d; } BOOLEAN pcvDim(leftv res,leftv h) { if(currRing) { short t[]={2,INT_CMD,INT_CMD}; if (iiCheckTypes(h,t,1)) { int d0=(int)(long)h->Data(); h=h->next; int d1=(int)(long)h->Data(); res->rtyp=INT_CMD; res->data=(void*)(long)pcvDim(d0,d1); return FALSE; } return TRUE; } WerrorS("no ring active"); return TRUE; } int pcvBasis(lists b,int i,poly m,int d,int n) { if(nN) { for(int k=0,l=d;k<=l;k++,d--) { pSetExp(m,n,k); i=pcvBasis(b,i,m,d,n+1); } } else { pSetExp(m,n,d); pSetm(m); b->m[i].rtyp=POLY_CMD; b->m[i++].data=pCopy(m); } return i; } lists pcvBasis(int d0,int d1) { if(d0<0) d0=0; if(d1<0) d1=0; lists b=(lists)omAllocBin(slists_bin); b->Init(pcvDim(d0,d1)); poly m=pOne(); for(int d=d0,i=0;dData(); h=h->next; int d1=(int)(long)h->Data(); res->rtyp=LIST_CMD; res->data=(void*)pcvBasis(d0,d1); return FALSE; } return TRUE; } WerrorS("no ring active"); return TRUE; } #endif /* HAVE_PCV */ singular-4.0.3+ds/Singular/pcv.h000066400000000000000000000020051266270727000164770ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: conversion between polys and coef vectors */ #ifndef PCV_H #define PCV_H lists pcvLAddL(lists l1,lists l2); lists pcvPMulL(poly p,lists l1); BOOLEAN pcvLAddL(leftv res,leftv h); BOOLEAN pcvPMulL(leftv res,leftv h); int pcvDeg(poly p); int pcvMinDeg(poly p); int pcvMinDeg(matrix m); BOOLEAN pcvMinDeg(leftv res,leftv h); void pcvInit(int d); void pcvClean(); int pcvM2N(poly m); poly pcvN2M(int n); poly pcvP2CV(poly p,int d0,int d1); poly pcvCV2P(poly cv,int d0,int d1); lists pcvP2CV(lists pl,int d0,int d1); ideal pcvP2CV(ideal p,int d0,int d1); lists pcvCV2P(lists cvl,int d0,int d1); ideal pcvCV2P(ideal cv,int d0,int d1); BOOLEAN pcvP2CV(leftv res,leftv h); BOOLEAN pcvCV2P(leftv res,leftv h); int pcvDim(int d0,int d1); BOOLEAN pcvDim(leftv res,leftv h); int pcvBasis(lists b,int i,poly m,int d,int n); lists pcvBasis(int d0,int d1); BOOLEAN pcvBasis(leftv res,leftv h); #endif singular-4.0.3+ds/Singular/pyobject_setup.cc000066400000000000000000000030021266270727000211020ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file pyobject_setup.cc * * @author Alexander Dreyer * @date 2010-12-15 * * This header file defines the @c blackbox setup operations for the pyobject * * @par Copyright: * (c) 2010 by The Singular Team, see LICENSE file **/ //***************************************************************************** #include #include #include static BOOLEAN pyobject_load() { return jjLOAD("pyobject.so", TRUE); } /// blackbox support - initialization via autoloading void* pyobject_autoload(blackbox* bbx) { assume(bbx != NULL); return (pyobject_load() || (bbx->blackbox_Init == pyobject_autoload)? NULL: bbx->blackbox_Init(bbx)); } void pyobject_default_destroy(blackbox */*b*/, void */*d*/) { Werror("Python-based functionality not available!"); } // Setting up an empty blackbox type, which can be filled with pyobject void pyobject_setup() { blackbox *bbx = (blackbox*)omAlloc0(sizeof(blackbox)); bbx->blackbox_Init = pyobject_autoload; bbx->blackbox_destroy = pyobject_default_destroy; setBlackboxStuff(bbx, "pyobject"); } /// Explicitely load, if not loaded already BOOLEAN pyobject_ensure() { int tok = -1; blackbox* bbx = (blackboxIsCmd("pyobject", tok) == ROOT_DECL? getBlackboxStuff(tok): (blackbox*)NULL); if (bbx == NULL) return TRUE; return (bbx->blackbox_Init == pyobject_autoload? pyobject_load(): FALSE); } singular-4.0.3+ds/Singular/pyobject_setup.h000066400000000000000000000012401266270727000207460ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file pyobject_setup.h * * @author Alexander Dreyer * @date 2010-12-15 * * This header file defines the @c blackbox setup interface for the pyobject * * @par Copyright: * (c) 2010 by The Singular Team, see LICENSE file **/ //***************************************************************************** #ifndef SINGULAR_PYOBJECT_SETUP_H #define SINGULAR_PYOBJECT_SETUP_H /// initialize blackbox support for @c pyobject; functionilty os autoloaded on demand void pyobject_setup(); /// force leading of pyobject functionality BOOLEAN pyobject_ensure(); #endif singular-4.0.3+ds/Singular/run.h000066400000000000000000000101141266270727000165130ustar00rootroot00000000000000// #define DEBUG // #define DEBUGALL // B19 - egcs automatically defines CYGWIN32 but not CYGWIN // B20 - egcs automatically defines both CYGWIN32 and CYGWIN // Bfuture - (???) defines CYGWIN but not CYGWIN32 #if defined(__CYGWIN32__) #if !defined(__CYGWIN__) #define B19 #define __CYGWIN__ #else #define B20 #endif #else #if defined(__CYGWIN__) #define B21 #endif #endif // Now: use __CYGWIN__ to represent any version // distinguish using B19, B20, or B21 #if defined(__CYGWIN__) #ifdef B19 #define CYGWIN_ATTACH_HANDLE_TO_FD(a) cygwin32_attach_handle_to_fd a #define CYGWIN_CONV_TO_FULL_POSIX_PATH(a) cygwin32_conv_to_full_posix_path a #define CYGWIN_CONV_TO_FULL_WIN32_PATH(a) cygwin32_conv_to_full_win32_path a #define CYGWIN_CONV_TO_POSIX_PATH(a) cygwin32_conv_to_posix_path a #define CYGWIN_CONV_TO_WIN32_PATH(a) cygwin32_conv_to_win32_path a #define CYGWIN_DETACH_DLL(a) cygwin32_detach_dll a #define CYGWIN_GETSHARED(a) cygwin32_getshared a #define CYGWIN_INTERNAL(a) cygwin32_internal a #define CYGWIN_POSIX_PATH_LIST_P(a) cygwin32_posix_path_list_p a #define CYGWIN_POSIX_TO_WIN32_PATH_LIST(a) cygwin32_posix_to_win32_path_list a #define CYGWIN_POSIX_TO_WIN32_PATH_LIST_BUF_SIZE(a) cygwin32_posix_to_win32_path_list_buf_size a #define CYGWIN_SPLIT_PATH(a) cygwin32_split_path a #define CYGWIN_WIN32_TO_POSIX_PATH_LIST(a) cygwin32_win32_to_posix_path_list a #define CYGWIN_WIN32_TO_POSIX_PATH_LIST_BUF_SIZE(a) cygwin32_win32_to_posix_path_list_buf_size a #define CYGWIN_WINPID_TO_PID(a) cygwin32_winpid_to_pid a #else #define CYGWIN_ATTACH_HANDLE_TO_FD(a) cygwin_attach_handle_to_fd a #define CYGWIN_CONV_TO_FULL_POSIX_PATH(a) cygwin_conv_to_full_posix_path a #define CYGWIN_CONV_TO_FULL_WIN32_PATH(a) cygwin_conv_to_full_win32_path a #define CYGWIN_CONV_TO_POSIX_PATH(a) cygwin_conv_to_posix_path a #define CYGWIN_CONV_TO_WIN32_PATH(a) cygwin_conv_to_win32_path a #define CYGWIN_DETACH_DLL(a) cygwin_detach_dll a #define CYGWIN_GETSHARED(a) cygwin_getshared a #define CYGWIN_INTERNAL(a) cygwin_internal a #define CYGWIN_POSIX_PATH_LIST_P(a) cygwin_posix_path_list_p a #define CYGWIN_POSIX_TO_WIN32_PATH_LIST(a) cygwin_posix_to_win32_path_list a #define CYGWIN_POSIX_TO_WIN32_PATH_LIST_BUF_SIZE(a) cygwin_posix_to_win32_path_list_buf_size a #define CYGWIN_SPLIT_PATH(a) cygwin_split_path a #define CYGWIN_WIN32_TO_POSIX_PATH_LIST(a) cygwin_win32_to_posix_path_list a #define CYGWIN_WIN32_TO_POSIX_PATH_LIST_BUF_SIZE(a) cygwin_win32_to_posix_path_list_buf_size a #define CYGWIN_WINPID_TO_PID(a) cygwin_winpid_to_pid a #endif #endif #if defined(__CYGWIN__) #define PATH_SEP_CHAR_STR "/" #define SEP_CHARS ":" #else #define PATH_SEP_CHAR_STR "\\" #define SEP_CHARS ";" #endif #ifndef RC_INVOKED #define MAX_ARGS 20 #ifdef DEBUG #define Trace(x) Trace_ x #else #define Trace(x) #endif #define NUM_EXTENSIONS 2 const char* exts[NUM_EXTENSIONS] = { "", ".exe" }; char* pfopen(char *retval, const char *name, const char *dirs); void error(char* fmt, ...); void message(char* fmt, ...); void Trace_(char* fmt, ...); int get_exec_name_and_path(char* execname, char* execpath); char* my_strtok(char* s, const char* delim, char** lasts); int parse_cmdline_to_arg_array(char* argv[MAX_ARGS], char* cmdline); void strip_exe(char* s); int start_child(char* cmdline, int wait_for_child); void xemacs_special(char* exec); int build_cmdline(char* new_cmdline, char* exec, int argc, char* argv[]); void process_execname(char *exec, const char* execname, const char* execpath); int fileExists(char* fullname, const char* path, const char* name); int endsWith(const char* s1, const char* s2); int fileExistsMulti(char* fullname, const char* path, const char* name_noext, const char* exts[], const int extcnt); #endif /* RC_INVOKED */ singular-4.0.3+ds/Singular/scanner.cc000066400000000000000000001707771266270727000175240ustar00rootroot00000000000000/* 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 /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ #ifdef c_plusplus #ifndef __cplusplus #define __cplusplus #endif #endif #ifdef __cplusplus #include #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 ) /* 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 )); 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; \ yytext_ptr -= yy_more_len; \ yyleng = (int) (yy_cp - yytext_ptr); \ yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; #define YY_NUM_RULES 66 #define YY_END_OF_BUFFER 67 static yyconst short int yy_accept[171] = { 0, 0, 0, 0, 0, 30, 30, 0, 0, 0, 0, 0, 0, 20, 20, 0, 0, 67, 65, 40, 40, 50, 34, 64, 59, 65, 64, 65, 65, 65, 65, 65, 57, 65, 65, 65, 65, 6, 55, 64, 64, 64, 64, 64, 64, 64, 24, 65, 35, 64, 36, 39, 36, 30, 25, 30, 32, 33, 26, 29, 26, 13, 11, 12, 15, 14, 17, 16, 21, 20, 21, 18, 23, 19, 9, 66, 10, 51, 46, 64, 64, 64, 53, 44, 43, 54, 41, 61, 3, 1, 61, 0, 0, 57, 42, 48, 52, 45, 49, 6, 64, 64, 64, 64, 64, 64, 64, 47, 2, 38, 37, 30, 30, 28, 27, 21, 20, 21, 0, 21, 9, 0, 1, 61, 63, 61, 63, 58, 64, 64, 5, 64, 64, 64, 64, 64, 2, 30, 31, 22, 0, 0, 0, 64, 64, 6, 64, 64, 64, 61, 62, 0, 64, 0, 60, 64, 0, 4, 64, 64, 0, 0, 7, 56, 0, 0, 8, 0, 0, 7, 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, 5, 6, 7, 8, 1, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 21, 22, 23, 24, 25, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 26, 1, 1, 27, 1, 28, 10, 29, 10, 30, 31, 10, 32, 33, 10, 10, 34, 35, 36, 37, 38, 39, 40, 10, 41, 42, 10, 43, 44, 10, 10, 45, 46, 47, 48, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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[49] = { 0, 1, 2, 3, 1, 1, 4, 1, 1, 1, 5, 6, 7, 1, 1, 7, 1, 8, 9, 10, 1, 11, 1, 1, 1, 1, 1, 12, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 1, 4, 1 } ; static yyconst short int yy_base[192] = { 0, 0, 299, 43, 44, 45, 46, 47, 48, 50, 54, 295, 294, 74, 92, 75, 76, 296, 561, 561, 561, 269, 561, 561, 561, 267, 40, 250, 229, 84, 38, 69, 92, 221, 60, 194, 181, 99, 561, 86, 87, 93, 98, 99, 100, 102, 561, 154, 561, 177, 561, 561, 62, 0, 561, 158, 561, 561, 561, 561, 109, 561, 561, 561, 561, 561, 561, 561, 0, 129, 134, 561, 561, 561, 0, 561, 561, 561, 561, 114, 124, 125, 561, 561, 561, 561, 561, 128, 561, 0, 136, 129, 149, 143, 561, 561, 561, 561, 561, 154, 144, 146, 147, 148, 151, 136, 151, 561, 0, 561, 561, 0, 177, 561, 561, 0, 187, 190, 144, 0, 0, 171, 0, 180, 561, 176, 193, 193, 180, 186, 188, 190, 192, 201, 203, 204, 0, 236, 0, 561, 119, 103, 97, 207, 244, 246, 222, 231, 223, 80, 39, 243, 224, 266, 561, 238, 252, 242, 252, 256, 286, 70, 288, 245, 192, 291, 561, 292, 293, 296, 561, 320, 332, 344, 356, 368, 380, 392, 400, 408, 418, 430, 442, 454, 466, 478, 490, 502, 514, 526, 537, 548 } ; static yyconst short int yy_def[192] = { 0, 170, 1, 171, 171, 172, 172, 173, 173, 174, 174, 175, 175, 176, 176, 177, 177, 170, 170, 170, 170, 170, 170, 170, 170, 170, 178, 170, 170, 170, 170, 170, 179, 170, 170, 170, 170, 170, 170, 178, 178, 178, 178, 178, 178, 178, 170, 170, 170, 170, 170, 170, 170, 180, 170, 180, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 181, 170, 182, 170, 170, 170, 183, 170, 170, 170, 170, 178, 178, 178, 170, 170, 170, 170, 170, 170, 170, 184, 179, 185, 170, 179, 170, 170, 170, 170, 170, 170, 178, 178, 178, 178, 178, 100, 100, 170, 186, 170, 170, 180, 187, 170, 170, 181, 170, 182, 188, 181, 183, 170, 184, 179, 170, 170, 170, 179, 100, 100, 100, 100, 100, 100, 100, 100, 186, 187, 189, 170, 170, 170, 170, 100, 100, 144, 100, 100, 100, 170, 170, 179, 100, 170, 170, 100, 190, 100, 100, 100, 191, 170, 144, 100, 170, 191, 170, 191, 191, 170, 0, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170 } ; static yyconst short int yy_nxt[610] = { 0, 18, 19, 20, 19, 21, 22, 23, 24, 25, 26, 18, 18, 27, 28, 18, 29, 30, 31, 32, 33, 18, 34, 35, 36, 37, 38, 23, 26, 26, 39, 40, 41, 26, 26, 26, 42, 26, 43, 44, 26, 26, 26, 45, 26, 46, 47, 18, 48, 51, 51, 54, 54, 59, 59, 86, 62, 87, 150, 80, 62, 63, 64, 55, 55, 63, 64, 81, 109, 52, 52, 65, 164, 60, 60, 65, 69, 69, 75, 75, 70, 166, 88, 95, 96, 71, 72, 89, 110, 73, 56, 56, 57, 57, 69, 69, 76, 76, 70, 149, 84, 99, 99, 71, 72, 80, 80, 73, 85, 91, 92, 93, 80, 81, 81, 113, 151, 80, 80, 80, 81, 80, 150, 102, 101, 81, 81, 81, 103, 81, 100, 116, 116, 80, 106, 114, 118, 118, 149, 104, 119, 81, 105, 80, 80, 118, 118, 87, 125, 118, 139, 81, 81, 170, 170, 123, 99, 99, 121, 126, 91, 92, 93, 80, 79, 80, 80, 80, 127, 134, 80, 81, 128, 81, 81, 81, 112, 129, 81, 79, 111, 131, 108, 138, 135, 140, 130, 140, 133, 116, 116, 132, 118, 118, 164, 87, 119, 170, 170, 123, 107, 118, 118, 166, 98, 118, 121, 141, 79, 141, 170, 142, 127, 79, 79, 143, 79, 97, 79, 79, 79, 79, 138, 79, 138, 79, 146, 144, 145, 79, 147, 79, 79, 156, 79, 79, 79, 79, 148, 111, 79, 94, 138, 83, 144, 152, 153, 153, 99, 99, 79, 79, 79, 157, 156, 155, 79, 79, 158, 79, 170, 142, 151, 82, 79, 154, 79, 170, 153, 153, 79, 79, 79, 79, 159, 79, 78, 79, 79, 161, 79, 138, 162, 138, 79, 79, 163, 154, 164, 79, 169, 169, 77, 164, 164, 164, 170, 166, 169, 169, 67, 67, 166, 166, 166, 167, 49, 170, 170, 170, 167, 167, 167, 168, 170, 170, 170, 170, 168, 168, 168, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 79, 170, 170, 170, 170, 79, 170, 79, 90, 170, 170, 90, 90, 90, 111, 111, 111, 170, 111, 111, 111, 111, 111, 111, 111, 111, 115, 170, 170, 115, 115, 170, 170, 115, 115, 115, 115, 115, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 120, 120, 170, 120, 120, 120, 120, 120, 120, 120, 170, 120, 122, 122, 170, 122, 122, 122, 122, 122, 122, 122, 122, 122, 124, 124, 124, 124, 124, 124, 124, 170, 124, 124, 124, 124, 136, 136, 170, 136, 136, 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, 138, 138, 170, 138, 138, 138, 138, 138, 138, 138, 138, 138, 160, 170, 170, 160, 170, 170, 170, 170, 170, 170, 160, 165, 170, 170, 165, 165, 170, 170, 170, 165, 170, 165, 17, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170 } ; static yyconst short int yy_chk[610] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4, 5, 6, 7, 8, 30, 9, 30, 150, 26, 10, 9, 9, 5, 6, 10, 10, 26, 52, 3, 4, 9, 161, 7, 8, 10, 13, 13, 15, 16, 13, 161, 31, 34, 34, 13, 13, 31, 52, 13, 5, 6, 5, 6, 14, 14, 15, 16, 14, 149, 29, 37, 37, 14, 14, 39, 40, 14, 29, 32, 32, 32, 41, 39, 40, 60, 142, 42, 43, 44, 41, 45, 141, 41, 40, 42, 43, 44, 42, 45, 39, 69, 69, 79, 45, 60, 70, 70, 140, 43, 70, 79, 44, 80, 81, 70, 70, 87, 91, 70, 118, 80, 81, 90, 90, 90, 99, 99, 87, 91, 93, 93, 93, 100, 105, 101, 102, 103, 92, 105, 104, 100, 100, 101, 102, 103, 55, 100, 104, 106, 112, 102, 49, 112, 106, 121, 101, 121, 104, 116, 116, 103, 117, 117, 164, 125, 117, 123, 123, 123, 47, 117, 117, 164, 36, 117, 125, 126, 128, 126, 127, 127, 127, 128, 129, 128, 130, 35, 131, 129, 132, 130, 112, 131, 112, 132, 132, 129, 131, 133, 133, 134, 135, 147, 133, 143, 134, 135, 135, 137, 143, 33, 137, 28, 134, 143, 144, 144, 145, 145, 146, 148, 152, 148, 156, 146, 148, 152, 152, 147, 151, 151, 151, 27, 147, 144, 155, 145, 153, 153, 157, 155, 144, 163, 155, 157, 25, 144, 163, 156, 158, 137, 158, 137, 159, 158, 159, 153, 160, 159, 162, 162, 21, 165, 167, 168, 17, 160, 169, 169, 12, 11, 165, 167, 168, 160, 2, 0, 0, 162, 165, 167, 168, 160, 0, 0, 0, 0, 165, 167, 168, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 178, 0, 0, 0, 0, 178, 0, 178, 179, 0, 0, 179, 179, 179, 180, 180, 180, 0, 180, 180, 180, 180, 180, 180, 180, 180, 181, 0, 0, 181, 181, 0, 0, 181, 181, 181, 181, 181, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 183, 183, 0, 183, 183, 183, 183, 183, 183, 183, 0, 183, 184, 184, 0, 184, 184, 184, 184, 184, 184, 184, 184, 184, 185, 185, 185, 185, 185, 185, 185, 0, 185, 185, 185, 185, 186, 186, 0, 186, 186, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 189, 189, 0, 189, 189, 189, 189, 189, 189, 189, 189, 189, 190, 0, 0, 190, 0, 0, 0, 0, 0, 0, 190, 191, 0, 0, 191, 191, 0, 0, 0, 191, 0, 191, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170 } ; 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 static int yy_more_flag = 0; static int yy_more_len = 0; #define yymore() (yy_more_flag = 1) #define YY_MORE_ADJ yy_more_len #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "" #define INITIAL 0 #line 2 "" /**************************************** * Computer Algebra System SINGULAR * ****************************************/ #include #include #include #include #include #include #include #include #include #include #include int feReadLine(char* b, int l); #define ALLOC(a) omAlloc((a)) #ifndef NEW_FLEX #endif /* NEW_LEX */ int blocknest = 0; extern char * yytext; //extern unsigned char * yytext; extern int yyleng; extern int inerror; // this is to shadow the malloc/realloc // used by yy_flex_malloc/yy_flex_realloc // so that we can mark stuff as static static void* my_malloc(size_t size) { void* addr = omAlloc(size); omMarkAsStaticAddr(addr); return addr; } static void* my_realloc(void* addr, size_t size) { void* new_addr = omRealloc(addr, size); omMarkAsStaticAddr(new_addr); return new_addr; } static void my_free(void* addr) { omFree(addr); } #undef malloc #define malloc my_malloc #undef realloc #define realloc my_realloc #undef free #define free my_free static char * dupyytext() { char* s; if (yyleng>0) yytext[yyleng-1] = '\0'; s = omStrDup((char *)yytext); omMarkAsStaticAddr(s); return s; } static char * dupyytextNL() { int i = yyleng;//strlen((char *)yytext); char * rc = (char*)omAlloc( 3 + i ); omMarkAsStaticAddr(rc); if (i>0) { strncpy( rc, (char *)yytext, i-1 ); } else { i++; } rc[i-1] = '\n'; rc[i] = '\n'; rc[i+1] = '\0'; return rc; } #undef YY_DECL #define YY_DECL int yylex(YYSTYPE* lvalp) #undef yywrap extern "C" { int yywrap() { return exitVoice(); } } #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ result = feReadLine( (char *) (buf), (max_size) ) #undef YY_USER_ACTION #define YY_USER_ACTION \ if ((inerror==1)&&(*yytext>=' '))\ { Print(" skipping text from `%s`",yytext);inerror=2; } /* %start START */ #define YY_ALWAYS_INTERACTIVE 1 #define string 1 #define block 2 #define blockstr 3 #define brace 4 #define bracestr 5 #define bracket 6 #define asstring 7 /* 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 \ if ( yyleng > 0 ) \ yy_current_buffer->yy_at_bol = \ (yytext[yyleng - 1] == '\n'); \ YY_USER_ACTION YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 121 "" 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_more_len = 0; if ( yy_more_flag ) { yy_more_len = yy_c_buf_p - yytext_ptr; yy_more_flag = 0; } 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_current_state += YY_AT_BOL(); 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 >= 171 ) 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] != 561 ); 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 122 "" { } YY_BREAK case 2: YY_RULE_SETUP #line 123 "" { } YY_BREAK case 3: YY_RULE_SETUP #line 124 "" { yy_noeof=noeof_comment; loop { register int c; while ( (c = yyinput()) != '*' && c != EOF ); if ( c == '*' ) { while ( (c = yyinput()) == '*' ); if ( c == '/' ) break; /* found the end */ } else { break; } } yy_noeof=0; } YY_BREAK case 4: YY_RULE_SETUP #line 142 "" { prompt_char='.'; blocknest = 0; yy_noeof = noeof_brace; BEGIN(brace); return WHILE_CMD;} YY_BREAK case 5: YY_RULE_SETUP #line 145 "" { prompt_char='.'; blocknest = 0; yy_noeof = noeof_brace; BEGIN(brace); return FOR_CMD;} YY_BREAK case 6: YY_RULE_SETUP #line 149 "" { yy_noeof = noeof_asstring; BEGIN(asstring); return HELP_CMD; } YY_BREAK case 7: YY_RULE_SETUP #line 154 "" { yy_noeof = noeof_asstring; BEGIN(asstring); return EXAMPLE_CMD; } YY_BREAK case 8: YY_RULE_SETUP #line 159 "" { char c; char *cp; lvalp->name = omStrDup(iiProcName((char *)yytext,c,cp)); yy_noeof = noeof_procname; blocknest = 1; BEGIN(brace); return PROC_DEF; } YY_BREAK case 9: YY_RULE_SETUP #line 167 "" { lvalp->name = omStrDup((char *)yytext); yy_noeof = 0; BEGIN(INITIAL); return STRINGTOK; } YY_BREAK case 10: YY_RULE_SETUP #line 172 "" { yy_noeof = 0; BEGIN(INITIAL); return *yytext; } YY_BREAK case 11: YY_RULE_SETUP #line 177 "" { yy_noeof = noeof_string; BEGIN(bracestr); yymore(); } YY_BREAK case 12: YY_RULE_SETUP #line 182 "" { if (blocknest++) yymore(); } YY_BREAK case 13: YY_RULE_SETUP #line 183 "" { if (blocknest) yymore(); } YY_BREAK case 14: YY_RULE_SETUP #line 184 "" { if (blocknest) { lvalp->name = dupyytext(); return STRINGTOK; } } YY_BREAK case 15: YY_RULE_SETUP #line 191 "" { if (--blocknest <= 0) { yy_noeof = 0; BEGIN(INITIAL); lvalp->name = dupyytext(); return STRINGTOK; } yymore(); } YY_BREAK case 16: YY_RULE_SETUP #line 201 "" { yy_noeof = noeof_brace; BEGIN(brace); yymore(); } YY_BREAK case 17: YY_RULE_SETUP #line 206 "" { yymore(); } YY_BREAK case 18: YY_RULE_SETUP #line 207 "" { return '('; } YY_BREAK case 19: YY_RULE_SETUP #line 208 "" { return ','; } YY_BREAK case 20: YY_RULE_SETUP #line 209 "" { ; } YY_BREAK case 21: YY_RULE_SETUP #line 210 "" { lvalp->name = omStrDup((char *)yytext); return STRINGTOK; } YY_BREAK case 22: YY_RULE_SETUP #line 214 "" { lvalp->name = omStrDup((char *)yytext); return STRINGTOK; } YY_BREAK case 23: YY_RULE_SETUP #line 218 "" { yy_noeof = 0; BEGIN(INITIAL); return ')'; } YY_BREAK case 24: YY_RULE_SETUP #line 223 "" { yy_blocklineno = yylineno; blocknest = 1; yy_noeof = noeof_block; BEGIN(block); } YY_BREAK case 25: YY_RULE_SETUP #line 229 "" { yy_noeof = noeof_string; BEGIN(blockstr); yymore(); } YY_BREAK case 26: YY_RULE_SETUP #line 234 "" { yymore(); } YY_BREAK case 27: YY_RULE_SETUP #line 235 "" { yymore(); } YY_BREAK case 28: YY_RULE_SETUP #line 236 "" { yymore(); } YY_BREAK case 29: YY_RULE_SETUP #line 237 "" { yy_noeof = noeof_block; BEGIN(block); yymore(); } YY_BREAK case 30: YY_RULE_SETUP #line 242 "" { yymore(); } YY_BREAK case 31: YY_RULE_SETUP #line 243 "" { yymore(); } YY_BREAK case 32: YY_RULE_SETUP #line 244 "" { blocknest++; yymore(); } YY_BREAK case 33: YY_RULE_SETUP #line 245 "" { if (--blocknest <= 0) { BEGIN(INITIAL); yy_noeof = 0; lvalp->name = dupyytextNL(); return BLOCKTOK; } yymore(); } YY_BREAK case 34: YY_RULE_SETUP #line 255 "" { BEGIN(string); yy_noeof = noeof_string;} YY_BREAK case 35: YY_RULE_SETUP #line 256 "" { return SYS_BREAK; } YY_BREAK case 36: YY_RULE_SETUP #line 257 "" { yymore(); } YY_BREAK case 37: YY_RULE_SETUP #line 258 "" { yymore(); } YY_BREAK case 38: YY_RULE_SETUP #line 259 "" { yymore(); } YY_BREAK case 39: YY_RULE_SETUP #line 260 "" { char * s; yy_noeof = 0; BEGIN(INITIAL); s = lvalp->name = dupyytext(); while (*yytext) { if (*yytext == '\\') yytext++; *s++ = *yytext++; } *s++ = *yytext++; return STRINGTOK; } YY_BREAK case 40: YY_RULE_SETUP #line 274 "" /* skip whitespace */ YY_BREAK case 41: YY_RULE_SETUP #line 275 "" { return DOTDOT; } YY_BREAK case 42: YY_RULE_SETUP #line 276 "" { return COLONCOLON; } YY_BREAK case 43: YY_RULE_SETUP #line 277 "" { return MINUSMINUS; } YY_BREAK case 44: YY_RULE_SETUP #line 278 "" { return PLUSPLUS ; } YY_BREAK case 45: YY_RULE_SETUP #line 279 "" { return EQUAL_EQUAL; } YY_BREAK case 46: YY_RULE_SETUP #line 280 "" { lvalp->i='&'; return LOGIC_OP; } YY_BREAK case 47: YY_RULE_SETUP #line 281 "" { lvalp->i='|'; return LOGIC_OP; } YY_BREAK case 48: YY_RULE_SETUP #line 282 "" { lvalp->i=LE; return COMP_OP; } YY_BREAK case 49: YY_RULE_SETUP #line 283 "" { lvalp->i=GE; return COMP_OP; } YY_BREAK case 50: YY_RULE_SETUP #line 284 "" { return NOT; } YY_BREAK case 51: YY_RULE_SETUP #line 285 "" { return NOTEQUAL; } YY_BREAK case 52: YY_RULE_SETUP #line 286 "" { return NOTEQUAL; } YY_BREAK case 53: YY_RULE_SETUP #line 287 "" { return '^'; } YY_BREAK case 54: YY_RULE_SETUP #line 288 "" { return ARROW; } YY_BREAK case 55: YY_RULE_SETUP #line 289 "" { return '\\'; } YY_BREAK case 56: YY_RULE_SETUP #line 290 "" { lvalp->name = omStrDup("\n"); return STRINGTOK; } YY_BREAK case 57: YY_RULE_SETUP #line 294 "" { lvalp->name = (char *)yytext; return INT_CONST; } YY_BREAK case 58: YY_RULE_SETUP #line 298 "" { lvalp->name = (char *)yytext; return RINGVAR; } YY_BREAK case 59: YY_RULE_SETUP #line 302 "" { m2_end(-1); } YY_BREAK case 60: YY_RULE_SETUP #line 305 "" { #ifdef MM_STAT mmStat(-500); #endif #ifdef OM_TRACK #ifndef SING_NDEBUG omPrintUsedTrackAddrs(stdout, 10); #endif #endif m2_end(0); } YY_BREAK case 61: YY_RULE_SETUP #line 317 "" { lvalp->name = (char *)yytext; return RINGVAR; } YY_BREAK case 62: YY_RULE_SETUP #line 321 "" { lvalp->name = (char *)yytext; return RINGVAR; } YY_BREAK case 63: *yy_cp = yy_hold_char; /* undo effects of setting up yytext */ yy_c_buf_p = yy_cp -= 1; YY_DO_BEFORE_ACTION; /* set up yytext again */ YY_RULE_SETUP #line 325 "" { lvalp->name = (char *)yytext; return RINGVAR; } YY_BREAK case 64: YY_RULE_SETUP #line 330 "" { /* {name} */ int rc=0; if (yytext[strlen((char *)yytext)-1] == '\n') { yytext[strlen((char *)yytext)-1] = '\0'; } if (yyleng > 1) { rc = IsCmd((char *)yytext,lvalp->i); if (rc) return rc; } lvalp->name = omStrDup((char *)yytext); return UNKNOWN_IDENT; } YY_BREAK case 65: YY_RULE_SETUP #line 346 "" { /*if (*yytext == '\n') REJECT;*/ register char ch= *yytext; lvalp->i = ch; switch(ch) { /* case '&': */ case '|': return LOGIC_OP; /* case '/': */ case '%': case '*': return MULDIV_OP; /* case '<': */ case '>': return COMP_OP; default: break; } return ch; } YY_BREAK case 66: YY_RULE_SETUP #line 367 "" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(string): case YY_STATE_EOF(block): case YY_STATE_EOF(blockstr): case YY_STATE_EOF(brace): case YY_STATE_EOF(bracestr): case YY_STATE_EOF(bracket): case YY_STATE_EOF(asstring): yyterminate(); 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; yy_current_state += YY_AT_BOL(); 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 >= 171 ) 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 >= 171 ) 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 == 170); 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 */ #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; yy_current_buffer->yy_at_bol = (c == '\n'); return c; } #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 ); } #ifndef YY_ALWAYS_INTERACTIVE #ifndef YY_NEVER_INTERACTIVE extern int isatty YY_PROTO(( int )); #endif #endif #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 367 "" void * myynewbuffer() { void * oldb = YY_CURRENT_BUFFER; yy_switch_to_buffer(yy_create_buffer(NULL, YY_BUF_SIZE)); return oldb; } void myyoldbuffer(void * oldb) { yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer((YY_BUFFER_STATE)oldb); //yy_flush_buffer((YY_BUFFER_STATE)oldb); } void my_yy_flush() { YY_FLUSH_BUFFER;BEGIN(0); } singular-4.0.3+ds/Singular/sdb.cc000066400000000000000000000167141266270727000166310ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: Singular debugger */ #include #include #include #include #include #include #include #include #include #include #include // for unlink,fork,execlp,getpid #include // for wait #ifdef HAVE_SDB // We use 8 breakpoints - corresponding to a bit in a char variable in procinfo // bit 1..7 force a breakpoint, if lineno==sdb_lines[i-1], // (for displaying only: file sdb_files[i-1]) // bit 0 force a breakpoint in every line (used for 'n') int sdb_lines[]={-1,-1,-1,-1,-1,-1,-1,-1}; char * sdb_files[6]; int sdb_flags=0; int sdb_checkline(char f) { int i; char ff=f>>1; for(i=0;i<7;i++) { if((ff & 1) && (yylineno==sdb_lines[i])) return i+1; ff>>=1; if (ff==0) return 0; } return 0; } static char *sdb_find_arg(char *p) { p++; while (*p==' ') p++; char *pp=p; while (*pp>' ') pp++; *pp='\0'; return p; } void sdb_show_bp() { for(int i=0; i<7;i++) if (sdb_lines[i]!= -1) Print("Breakpoint %d: %s::%d\n",i+1,sdb_files[i],sdb_lines[i]); } BOOLEAN sdb_set_breakpoint(const char *pp, int given_lineno) { idhdl h=ggetid(pp); if ((h==NULL)||(IDTYP(h)!=PROC_CMD)) { PrintS(" not found\n"); return TRUE; } else { procinfov p=(procinfov)IDDATA(h); #ifdef HAVE_DYNAMIC_LOADING if (p->language!=LANG_SINGULAR) { PrintS("is not a Singular procedure\n"); return TRUE; } #endif int lineno; if (given_lineno >0) lineno=given_lineno; else lineno=p->data.s.body_lineno; int i; if (given_lineno== -1) { i=p->trace_flag; p->trace_flag &=1; Print("breakpoints in %s deleted(%#x)\n",p->procname,i &255); return FALSE; } i=0; while((i<7) && (sdb_lines[i]!=-1)) i++; if (sdb_lines[i]!= -1) { PrintS("too many breakpoints set, max is 7\n"); return TRUE; } sdb_lines[i]=lineno; sdb_files[i]=p->libname; i++; p->trace_flag|=(1<procname); return FALSE; } } void sdb_edit(procinfo *pi) { char * filename = omStrDup("/tmp/sd000000"); sprintf(filename+7,"%d",getpid()); FILE *fp=fopen(filename,"w"); if (fp==NULL) { Print("cannot open %s\n",filename); omFree(filename); return; } if (pi->language!= LANG_SINGULAR) { Print("cannot edit type %d\n",pi->language); fclose(fp); fp=NULL; } else { const char *editor=getenv("EDITOR"); if (editor==NULL) editor=getenv("VISUAL"); if (editor==NULL) editor="vi"; editor=omStrDup(editor); if (pi->data.s.body==NULL) { iiGetLibProcBuffer(pi); if (pi->data.s.body==NULL) { PrintS("cannot get the procedure body\n"); fclose(fp); si_unlink(filename); omFree(filename); return; } } fwrite(pi->data.s.body,1,strlen(pi->data.s.body),fp); fclose(fp); int pid=fork(); if (pid!=0) { si_wait(&pid); } else if(pid==0) { if (strchr(editor,' ')==NULL) { execlp(editor,editor,filename,NULL); Print("cannot exec %s\n",editor); } else { char *p=(char *)omAlloc(strlen(editor)+strlen(filename)+2); sprintf(p,"%s %s",editor,filename); system(p); } exit(0); } else { PrintS("cannot fork\n"); } fp=fopen(filename,"r"); if (fp==NULL) { Print("cannot read from %s\n",filename); } else { fseek(fp,0L,SEEK_END); long len=ftell(fp); fseek(fp,0L,SEEK_SET); omFree((ADDRESS)pi->data.s.body); pi->data.s.body=(char *)omAlloc((int)len+1); myfread( pi->data.s.body, len, 1, fp); pi->data.s.body[len]='\0'; fclose(fp); } } si_unlink(filename); omFree(filename); } static char sdb_lastcmd='c'; void sdb(Voice * currentVoice, const char * currLine, int len) { int bp=0; if ((len>1) && ((currentVoice->pi->trace_flag & 1) || (bp=sdb_checkline(currentVoice->pi->trace_flag))) ) { loop { char gdb[80]; char *p=(char *)currLine+len-1; while ((*p<=' ') && (p!=currLine)) { p--; len--; } if (p==currLine) return; currentVoice->pi->trace_flag&= ~1; // delete flag for "all lines" Print("(%s,%d) >>",currentVoice->filename,yylineno); fwrite(currLine,1,len,stdout); Print("<<\nbreakpoint %d (press ? for list of commands)\n",bp); p=fe_fgets_stdin(">>",gdb,80); while (*p==' ') p++; if (*p >' ') { sdb_lastcmd=*p; } Print("command:%c\n",sdb_lastcmd); switch(sdb_lastcmd) { case '?': case 'h': { PrintS( "b - print backtrace of calling stack\n" "B [] - define breakpoint\n" "c - continue\n" "d - delete current breakpoint\n" "D - show all breakpoints\n" "e - edit the current procedure (current call will be aborted)\n" "h,? - display this help screen\n" "n - execute current line, break at next line\n" "p - display type and value of the variable \n" "q - quit debugger, set debugger flags(0,1,2)\n" " 0: stop debug, 1:continue, 2: throw an error, return to toplevel\n" "Q - quit Singular\n"); int i; for(i=0;i<7;i++) { if (sdb_lines[i] != -1) Print("breakpoint %d at line %d in %s\n", i,sdb_lines[i],sdb_files[i]); } break; } case 'd': { Print("delete break point %d\n",bp); currentVoice->pi->trace_flag &= (~Sy_bit(bp)); if (bp!=0) { sdb_lines[bp-1]=-1; } break; } case 'D': sdb_show_bp(); break; #if 0 case 'l': { extern void listall(int showproc); listall(FALSE); break; } #endif case 'n': currentVoice->pi->trace_flag|= 1; return; case 'e': { sdb_edit(currentVoice->pi); sdb_flags=2; return; } case 'p': { p=sdb_find_arg(p); extern int myynest; Print("variable `%s`at level %d",p,myynest); idhdl h=ggetid(p); if (h==NULL) PrintS(" not found\n"); else { sleftv tmp; memset(&tmp,0,sizeof(tmp)); tmp.rtyp=IDHDL; tmp.data=h; Print("(type %s):\n",Tok2Cmdname(tmp.Typ())); tmp.Print(); } break; } case 'b': VoiceBackTrack(); break; case 'B': { p=sdb_find_arg(p); Print("procedure `%s` ",p); sdb_set_breakpoint(p); break; } case 'q': { p=sdb_find_arg(p); if (*p!='\0') { sdb_flags=atoi(p); Print("new sdb_flags:%d\n",sdb_flags); } return; } case 'Q': m2_end(999); case 'c': default: return; } } } } #endif singular-4.0.3+ds/Singular/sdb.h000066400000000000000000000010071266270727000164600ustar00rootroot00000000000000#ifndef SDB_H #define SDB_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: Singular debugger */ #define HAVE_SDB #ifdef HAVE_SDB #include extern int sdb_lines[]; extern char * sdb_files[]; extern int sdb_flags; void sdb_edit(procinfo *pi); void sdb_show_bp(); BOOLEAN sdb_set_breakpoint(const char *p, int lineno=0); void sdb(Voice * currentVoice, const char * currLine, int len); #endif #endif singular-4.0.3+ds/Singular/singular-libs000066400000000000000000000052261266270727000202440ustar00rootroot00000000000000# # Singular libraries which go into distribution # (they should be ordered alphabetically) # MAKE SURE THAT THIS IS UP_TO_DATE # and use: # svn propset svn:keywords "Id" yourlib.lib # for new libs # SLIB0 = absfact.lib ainvar.lib aksaka.lib alexpoly.lib algebra.lib \ arcpoint.lib assprimeszerodim.lib atkins.lib brnoeth.lib \ cisimplicial.lib classify.lib \ compregb.lib control.lib crypto.lib curvepar.lib decodegb.lib \ deform.lib elim.lib equising.lib finvar.lib general.lib gmspoly.lib \ gmssing.lib graphics.lib grobcov.lib groups.lib grwalk.lib \ hnoether.lib \ homolog.lib hyperel.lib integralbasis.lib inout.lib intprog.lib \ jacobson.lib \ kskernel.lib latex.lib linalg.lib makedbm.lib \ matrix.lib modstd.lib mondromy.lib monomialideal.lib \ mprimdec.lib mregular.lib \ noether.lib normal.lib normaliz.lib ntsolve.lib \ paraplanecurves.lib phindex.lib \ pointid.lib poly.lib \ presolve.lib primdec.lib primdecint.lib \ primitiv.lib qhmoduli.lib random.lib realclassify.lib \ realrad.lib reesclos.lib resbinomial.lib \ resgraph.lib resjung.lib resolve.lib \ reszeta.lib ring.lib rinvar.lib rootsmr.lib rootsur.lib \ sagbi.lib sheafcoh.lib sing.lib sing4ti2.lib signcond.lib \ solve.lib spcurve.lib spectrum.lib standard.lib stratify.lib \ surf.lib surfacesignature.lib surfex.lib \ teachstd.lib toric.lib triang.lib \ weierstr.lib zeroset.lib # libs in beta testing: # the will be included in share.tar.gz, but not in all.lib # (they should be ordered alphabetically) # and use: # svn propset svn:keywords "Id" yourlib.lib # for new libs SLIB1 = classifyceq.lib classifyci.lib classify_aeq.lib nfmodstd.lib \ dmodloc.lib divisors.lib \ ffsolve.lib decomp.lib template.lib \ findifs.lib finitediff.lib \ gitfan.lib gradedModules.lib \ locnormal.lib modnormal.lib modular.lib \ JMBTest.lib JMSConst.lib multigrading.lib\ numerAlg.lib numerDecom.lib \ orbitparam.lib parallel.lib polymake.lib\ realizationMatroids.lib resources.lib ringgb.lib \ schreyer.lib symodstd.lib deRham.lib polybori.lib ellipticcovers.lib \ schubert.lib tasks.lib tropical.lib hdepth.lib gradedModules.lib \ arr.lib brillnoether.lib chern.lib cimonom.lib GND.lib \ graal.lib hess.lib modwalk.lib rwalk.lib swalk.lib PLIBS = bimodules.lib bfun.lib central.lib dmod.lib dmodapp.lib dmodvar.lib\ fpadim.lib \ freegb.lib gkdim.lib involut.lib ncalg.lib ncdecomp.lib \ ncfactor.lib ncpreim.lib nctools.lib perron.lib qmatrix.lib \ purityfiltration.lib nchomolog.lib ratgb.lib \ ncall.lib # contributed libs, status not yet decided SLIB2 = KVequiv.lib deflation.lib lejeune.lib \ mathml.lib maxlike.lib recover.lib redcgs.lib singular-4.0.3+ds/Singular/singularsurf000077500000000000000000000004231266270727000202120ustar00rootroot00000000000000#!/bin/sh echo "width=400;" >$1.pic echo "height=400;" >>$1.pic cat $1 >>$1.pic echo "color_file_format = jpg;">>$1.pic echo "filename = \"/tmp/surf.jpg\";">>$1.pic echo "save_color_image;">>$1.pic surf $1.pic command rm $1.pic display /tmp/surf.jpg command rm /tmp/surf.jpg singular-4.0.3+ds/Singular/stype.h000066400000000000000000000006401266270727000170560ustar00rootroot00000000000000#ifndef STYPE_H #define STYPE_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: flex/bison interface */ #include #include typedef union { int i; char * name; sleftv lv; } MYYSTYPE; #define YYSTYPE MYYSTYPE extern YYSTYPE yylval; int yylex(MYYSTYPE *l); #endif singular-4.0.3+ds/Singular/subexpr.cc000066400000000000000000001324201266270727000175420ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: handling of leftv */ #include #include #include #include #include #include #include // nfShowMipo // minpoly printing... #include #include #include // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include omBin sSubexpr_bin = omGetSpecBin(sizeof(_ssubexpr)); omBin sleftv_bin = omGetSpecBin(sizeof(sleftv)); omBin procinfo_bin = omGetSpecBin(sizeof(procinfo)); omBin libstack_bin = omGetSpecBin(sizeof(libstack)); static omBin size_two_bin = omGetSpecBin(2); sleftv sLastPrinted; const char sNoName[]="_"; #ifdef SIQ BOOLEAN siq=FALSE; #endif int sleftv::listLength() { int n = 1; leftv sl = next; while (sl!=NULL) { n++; sl=sl->next; } return n; } void sleftv::Print(leftv store, int spaces) { int t=Typ(); if (errorreported) return; #ifdef SIQ if (rtyp==COMMAND) { command c=(command)data; char ch[2]; ch[0]=c->op;ch[1]='\0'; const char *s=ch; if (c->op>127) s=iiTwoOps(c->op); ::Print("##command %d(%s), %d args\n", c->op, s, c->argc); if (c->argc>0) c->arg1.Print(NULL,spaces+2); if(c->argc<4) { if (c->argc>1) c->arg2.Print(NULL,spaces+2); if (c->argc>2) c->arg3.Print(NULL,spaces+2); } PrintS("##end"); } else #endif { const char *n=Name(); char *s; void *d=Data(); if (errorreported) return; if ((store!=NULL)&&(store!=this)) store->CleanUp(); switch (t /*=Typ()*/) { #ifdef SINGULAR_4_1 case CRING_CMD: crPrint((coeffs)d); break; case CNUMBER_CMD: n2Print((number2)d); break; case CMATRIX_CMD: // like BIGINTMAT #endif case BIGINTMAT_CMD: ((bigintmat *)d)->pprint(80); break; case UNKNOWN: case DEF_CMD: PrintNSpaces(spaces); PrintS("`");PrintS(n);PrintS("`"); break; case PACKAGE_CMD: PrintNSpaces(spaces); paPrint(n,(package)d); break; case NONE: return; case INTVEC_CMD: case INTMAT_CMD: ((intvec *)d)->show(t,spaces); break; case RING_CMD: case QRING_CMD: { PrintNSpaces(spaces); const ring r = (const ring)d; rWrite(r, currRing == r); break; } case MATRIX_CMD: iiWriteMatrix((matrix)d,n,2, currRing, spaces); break; case MODUL_CMD: case IDEAL_CMD: if ((TEST_V_QRING) &&(currRing->qideal!=NULL) &&(!hasFlag(this,FLAG_QRING))) { jjNormalizeQRingId(this); d=Data(); } // no break: case MAP_CMD: iiWriteMatrix((matrix)d,n,1, currRing, spaces); break; case POLY_CMD: case VECTOR_CMD: if ((e==NULL) && (TEST_V_QRING) &&(currRing->qideal!=NULL) &&(!hasFlag(this,FLAG_QRING))) { setFlag(this,FLAG_QRING); poly p=(poly)d; jjNormalizeQRingP(p); if (p!=(poly)d) { d=(void*)p; if ((rtyp==POLY_CMD)||(rtyp==VECTOR_CMD)) data=d; else if (rtyp==IDHDL) { idhdl h=(idhdl)data; IDPOLY(h)=p; setFlag(h,FLAG_QRING); } } } PrintNSpaces(spaces); pWrite0((poly)d); break; case RESOLUTION_CMD: { syStrategy tmp=(syStrategy)d; syPrint(tmp,IDID(currRingHdl)); break; } case STRING_CMD: PrintNSpaces(spaces); PrintS((char *)d); break; case INT_CMD: PrintNSpaces(spaces); ::Print("%d",(int)(long)d); break; case PROC_CMD: { procinfov pi=(procinfov)d; PrintNSpaces(spaces); PrintS("// libname : "); PrintS(piProcinfo(pi, "libname")); PrintLn(); PrintNSpaces(spaces); PrintS("// procname : "); PrintS(piProcinfo(pi, "procname")); PrintLn(); PrintNSpaces(spaces); PrintS("// type : "); PrintS(piProcinfo(pi, "type")); // ::Print("%-*.*s// ref : %s",spaces,spaces," ", // piProcinfo(pi, "ref")); break; } case LINK_CMD: { si_link l=(si_link)d; PrintNSpaces(spaces); ::Print("// type : %s\n", slStatus(l, "type")); PrintNSpaces(spaces); ::Print("// mode : %s\n", slStatus(l, "mode")); PrintNSpaces(spaces); ::Print("// name : %s\n", slStatus(l, "name")); PrintNSpaces(spaces); ::Print("// open : %s\n", slStatus(l, "open")); PrintNSpaces(spaces); ::Print("// read : %s\n", slStatus(l, "read")); PrintNSpaces(spaces); ::Print("// write: %s", slStatus(l, "write")); break; } case NUMBER_CMD: case BIGINT_CMD: if (t==NUMBER_CMD) { number n=(number)d; nNormalize(n); d=n; } s=String(d); if (s==NULL) return; PrintNSpaces(spaces); PrintS(s); omFree((ADDRESS)s); break; case LIST_CMD: { lists l=(lists)d; if (lSize(l)<0) { PrintNSpaces(spaces); PrintS("empty list\n"); } else { int i=0; for (;i<=l->nr;i++) { if (l->m[i].rtyp!=DEF_CMD) { PrintNSpaces(spaces); ::Print("[%d]:\n",i+1); l->m[i].Print(NULL,spaces+3); } } } break; } default: if (t>MAX_TOK) { blackbox * bb=getBlackboxStuff(t); PrintNSpaces(spaces); if (bb!=NULL) { bb->blackbox_Print(bb,d); } else { ::Print("Print: blackbox %d(bb=NULL)",t); } } else ::Print("Print:unknown type %s(%d)", Tok2Cmdname(t),t); } /* end switch: (Typ()) */ } if (next!=NULL) { if (t==COMMAND) PrintLn(); else if (t!=LIST_CMD) PrintS(" "); next->Print(NULL,spaces); } else if (t!=LIST_CMD) { PrintLn(); } #ifdef SIQ if (rtyp!=COMMAND) #endif { if ((store!=NULL) && (store!=this)) { if((t/*Typ()*/!=LINK_CMD) && (t/*Typ()*/!=PACKAGE_CMD) && (t/*Typ()*/!=DEF_CMD) ) { store->rtyp=t/*Typ()*/; store->data=CopyD(); if(attribute!=NULL) { store->attribute=CopyA(); } store->flag=flag; } } } } void sleftv::CleanUp(ring r) { if ((name!=NULL) && (name!=sNoName) && (rtyp!=IDHDL) && (rtyp!=ALIAS_CMD)) { //::Print("free %x (%s)\n",name,name); omFree((ADDRESS)name); } //name=NULL; //flag=0; if (data!=NULL) { if (rtyp==IDHDL) attribute=NULL; // is only a pointer to attribute of id else s_internalDelete(rtyp,data,r); //data=NULL; // will be done by Init() at the end } if (attribute!=NULL) { switch (rtyp) { case PACKAGE_CMD: case IDHDL: case ANY_TYPE: case VECHO: case VPRINTLEVEL: case VCOLMAX: case VTIMER: case VRTIMER: case VOICE: case VMAXDEG: case VMAXMULT: case TRACE: case VSHORTOUT: case VNOETHER: case VMINPOLY: case LIB_CMD: case 0: //attribute=NULL; // will be done by Init() at the end break; default: { attribute->killAll(r); } } } Subexpr h; while (e!=NULL) { h=e->next; omFreeBin((ADDRESS)e, sSubexpr_bin); e=h; } //rtyp=NONE; // will be done by Init() at the end if (next!=NULL) { leftv tmp_n; do { tmp_n=next->next; //next->name=NULL; next->next=NULL; next->CleanUp(r); omFreeBin((ADDRESS)next, sleftv_bin); next=tmp_n; } while (next!=NULL); } Init(); } BOOLEAN sleftv::RingDependend() { int rt=Typ(); if(::RingDependend(rt) && (rt!=QRING_CMD)) return TRUE; if (rt==LIST_CMD) return lRingDependend((lists)Data()); if (this->next!=NULL) return this->next->RingDependend(); return FALSE; } static inline void * s_internalCopy(const int t, void *d) { switch (t) { #ifdef SINGULAR_4_1 case CRING_CMD: { coeffs cf=(coeffs)d; cf->ref++; return (void*)d; } case CNUMBER_CMD: return (void*)n2Copy((number2)d); case CMATRIX_CMD: // like BIGINTMAT #endif case BIGINTMAT_CMD: return (void*)bimCopy((bigintmat *)d); case INTVEC_CMD: case INTMAT_CMD: return (void *)ivCopy((intvec *)d); case MATRIX_CMD: return (void *)mp_Copy((matrix)d, currRing); case IDEAL_CMD: case MODUL_CMD: return (void *)idCopy((ideal)d); case STRING_CMD: return (void *)omStrDup((char *)d); case PACKAGE_CMD: return (void *)paCopy((package) d); case PROC_CMD: return (void *)piCopy((procinfov) d); case POLY_CMD: case VECTOR_CMD: return (void *)pCopy((poly)d); case INT_CMD: return d; case NUMBER_CMD: return (void *)nCopy((number)d); case BIGINT_CMD: return (void *)n_Copy((number)d, coeffs_BIGINT); case MAP_CMD: return (void *)maCopy((map)d, currRing); case LIST_CMD: return (void *)lCopy((lists)d); case LINK_CMD: return (void *)slCopy((si_link) d); case RING_CMD: case QRING_CMD: { ring r=(ring)d; if (r!=NULL) r->ref++; //Print("+ ring %d, ref %d\n",r,r->ref); return d; } case RESOLUTION_CMD: return (void*)syCopy((syStrategy)d); case DEF_CMD: case NONE: case 0: /* type in error case */ break; /* error recovery: do nothing */ //case COMMAND: default: { if (t>MAX_TOK) { blackbox *b=getBlackboxStuff(t); if (b!=NULL) return b->blackbox_Copy(b,d); return NULL; } else Warn("s_internalCopy: cannot copy type %s(%d)", Tok2Cmdname(t),t); } } return NULL; } void s_internalDelete(const int t, void *d, const ring r) { assume(d!=NULL); switch (t) { #ifdef SINGULAR_4_1 case CRING_CMD: nKillChar((coeffs)d); break; case CNUMBER_CMD: { number2 n=(number2)d; n2Delete(n); break; } case CMATRIX_CMD: //like BIGINTMAT #endif case BIGINTMAT_CMD: { bigintmat *v=(bigintmat*)d; delete v; break; } case INTVEC_CMD: case INTMAT_CMD: { intvec *v=(intvec*)d; delete v; break; } case MAP_CMD: { map m=(map)d; omFreeBinAddr((ADDRESS)m->preimage); m->preimage=NULL; /* no break: continue as IDEAL*/ } case MATRIX_CMD: case IDEAL_CMD: case MODUL_CMD: { ideal i=(ideal)d; id_Delete(&i,r); break; } case STRING_CMD: omFree(d); break; //case PACKAGE_CMD: // return (void *)paCopy((package) d); case PROC_CMD: piKill((procinfo*)d); break; case POLY_CMD: case VECTOR_CMD: { poly p=(poly)d; p_Delete(&p,r); break; } case NUMBER_CMD: { number n=(number)d; n_Delete(&n,r); break; } case BIGINT_CMD: { number n=(number)d; n_Delete(&n,coeffs_BIGINT); break; } case LIST_CMD: { lists l=(lists)d; l->Clean(r); break; } case LINK_CMD: { si_link l=(si_link)d; slKill(l); break; } case RING_CMD: case QRING_CMD: { ring R=(ring)d; if ((R!=currRing)||(R->ref>=0)) rKill(R); #ifdef TEST else Print("currRing? ref=%d\n",R->ref); #endif break; } case RESOLUTION_CMD: { syStrategy s=(syStrategy)d; if (s!=NULL) syKillComputation(s,r); break; } case COMMAND: { command cmd=(command)d; if (cmd->arg1.rtyp!=0) cmd->arg1.CleanUp(r); if (cmd->arg2.rtyp!=0) cmd->arg2.CleanUp(r); if (cmd->arg3.rtyp!=0) cmd->arg3.CleanUp(r); omFreeBin((ADDRESS)d, sip_command_bin); break; } case INT_CMD: case DEF_CMD: case ALIAS_CMD: case PACKAGE_CMD: case IDHDL: case NONE: case ANY_TYPE: case VECHO: case VPRINTLEVEL: case VCOLMAX: case VTIMER: case VRTIMER: case VOICE: case VMAXDEG: case VMAXMULT: case TRACE: case VSHORTOUT: case VNOETHER: case VMINPOLY: case LIB_CMD: case 0: /* type in error case */ break; /* error recovery: do nothing */ //case COMMAND: //case COMMAND: default: { if (t>MAX_TOK) { blackbox *b=getBlackboxStuff(t); if (b!=NULL) b->blackbox_destroy(b,d); break; } else Warn("s_internalDelete: cannot delete type %s(%d)", Tok2Cmdname(t),t); } } } void * slInternalCopy(leftv source, const int t, void *d, Subexpr e) { if (t==STRING_CMD) { if ((e==NULL) || (source->rtyp==LIST_CMD) || ((source->rtyp==IDHDL) &&((IDTYP((idhdl)source->data)==LIST_CMD) || (IDTYP((idhdl)source->data)>MAX_TOK))) || (source->rtyp>MAX_TOK)) return (void *)omStrDup((char *)d); else if (e->next==NULL) { char *s=(char*)omAllocBin(size_two_bin); s[0]=*(char *)d; s[1]='\0'; return s; } #ifdef TEST else { Werror("not impl. string-op in `%s`",my_yylinebuf); return NULL; } #endif } return s_internalCopy(t,d); } void sleftv::Copy(leftv source) { Init(); rtyp=source->Typ(); void *d=source->Data(); if(!errorreported) { data=s_internalCopy(rtyp,d); if ((source->attribute!=NULL)||(source->e!=NULL)) attribute=source->CopyA(); flag=source->flag; if (source->next!=NULL) { next=(leftv)omAllocBin(sleftv_bin); next->Copy(source->next); } } } void * sleftv::CopyD(int t) { if ((rtyp!=IDHDL)&&(rtyp!=ALIAS_CMD)&&(e==NULL)) { if (iiCheckRing(t)) return NULL; void *x = data; if (rtyp==VNOETHER) x = (void *)pCopy((currRing->ppNoether)); else if ((rtyp==VMINPOLY) && nCoeff_is_algExt(currRing->cf) && (!nCoeff_is_GF(currRing->cf))) { const ring A = currRing->cf->extRing; assume( A != NULL ); assume( A->qideal != NULL ); x=(void *)p_Copy(A->qideal->m[0], A); } data=NULL; return x; } void *d=Data(); // will also do a iiCheckRing if ((!errorreported) && (d!=NULL)) return slInternalCopy(this,t,d,e); return NULL; } //void * sleftv::CopyD() //{ //if ((rtyp!=IDHDL)&&(e==NULL) //&&(rtyp!=VNOETHER)&&(rtyp!=LIB_CMD)&&(rtyp!=VMINPOLY)) //{ // void *x=data; // data=NULL; // return x; //} // return CopyD(Typ()); //} attr sleftv::CopyA() { attr *a=Attribute(); if ((a!=NULL) && (*a!=NULL)) return (*a)->Copy(); return NULL; } char * sleftv::String(void *d, BOOLEAN typed, int dim) { #ifdef SIQ if (rtyp==COMMAND) { ::Print("##command %d\n",((command)data)->op); if (((command)data)->arg1.rtyp!=0) ((command)data)->arg1.Print(NULL,2); if (((command)data)->arg2.rtyp!=0) ((command)data)->arg2.Print(NULL,2); if (((command)data)->arg3.rtyp==0) ((command)data)->arg3.Print(NULL,2); PrintS("##end\n"); return omStrDup(""); } #endif if (d==NULL) d=Data(); if (!errorreported) { char *s; int t=Typ(); switch (t /*Typ()*/) { case INT_CMD: if (typed) { s=(char *)omAlloc(MAX_INT_LEN+7); sprintf(s,"int(%d)",(int)(long)d); } else { s=(char *)omAlloc(MAX_INT_LEN+2); sprintf(s,"%d",(int)(long)d); } return s; case STRING_CMD: if (d == NULL) { if (typed) return omStrDup("\"\""); return omStrDup(""); } if (typed) { s = (char*) omAlloc(strlen((char*) d) + 3); sprintf(s,"\"%s\"", (char*) d); return s; } else { return omStrDup((char*)d); } case POLY_CMD: case VECTOR_CMD: if (typed) { char* ps = pString((poly) d); s = (char*) omAlloc(strlen(ps) + 10); sprintf(s,"%s(%s)", (t /*Typ()*/ == POLY_CMD ? "poly" : "vector"), ps); omFree(ps); return s; } else return pString((poly)d); #ifdef SINGULAR_4_1 case CNUMBER_CMD: return n2String((number2)d,typed); #endif case NUMBER_CMD: StringSetS((char*) (typed ? "number(" : "")); if ((rtyp==IDHDL)&&(IDTYP((idhdl)data)==NUMBER_CMD)) { nWrite(IDNUMBER((idhdl)data)); } else if (rtyp==NUMBER_CMD) { number n=(number)data; nWrite(n); data=(char *)n; } else if((rtyp==VMINPOLY)&&(rField_is_GF(currRing))) { nfShowMipo(currRing->cf); } else { number n=nCopy((number)d); nWrite(n); nDelete(&n); } StringAppendS((char*) (typed ? ")" : "")); return StringEndS(); case BIGINT_CMD: { StringSetS((char*) (typed ? "bigint(" : "")); number nl=(number)d; n_Write(nl,coeffs_BIGINT); StringAppendS((char*) (typed ? ")" : "")); return StringEndS(); } case MATRIX_CMD: s= iiStringMatrix((matrix)d,dim, currRing); if (typed) { char* ns = (char*) omAlloc(strlen(s) + 40); sprintf(ns, "matrix(ideal(%s),%d,%d)", s, ((ideal) d)->nrows, ((ideal) d)->ncols); omCheckAddr(ns); return ns; } else { return omStrDup(s); } case MODUL_CMD: case IDEAL_CMD: case MAP_CMD: s= iiStringMatrix((matrix)d,dim, currRing); if (typed) { char* ns = (char*) omAlloc(strlen(s) + 10); sprintf(ns, "%s(%s)", (t/*Typ()*/==MODUL_CMD ? "module" : "ideal"), s); omCheckAddr(ns); return ns; } return omStrDup(s); case INTVEC_CMD: case INTMAT_CMD: { intvec *v=(intvec *)d; s = v->String(dim); if (typed) { char* ns; if (t/*Typ()*/ == INTMAT_CMD) { ns = (char*) omAlloc(strlen(s) + 40); sprintf(ns, "intmat(intvec(%s),%d,%d)", s, v->rows(), v->cols()); } else { ns = (char*) omAlloc(strlen(s) + 10); sprintf(ns, "intvec(%s)", s); } omCheckAddr(ns); omFree(s); return ns; } else return s; } case BIGINTMAT_CMD: { bigintmat *bim=(bigintmat*)d; s = bim->String(); if (typed) { char* ns = (char*) omAlloc0(strlen(s) + 40); sprintf(ns, "bigintmat(bigintvec(%s),%d,%d)", s, bim->rows(), bim->cols()); omCheckAddr(ns); return ns; } else return omStrDup(s); } case RING_CMD: case QRING_CMD: s = rString((ring)d); if (typed) { char* ns; if (t/*Typ()*/ == QRING_CMD) { char* id = iiStringMatrix((matrix) ((ring) d)->qideal, dim, currRing); ns = (char*) omAlloc(strlen(s) + strlen(id) + 20); sprintf(ns, "\"%s\";%sideal(%s)", s,(dim == 2 ? "\n" : " "), id); } else { ns = (char*) omAlloc(strlen(s) + 4); sprintf(ns, "\"%s\"", s); } omFree(s); omCheckAddr(ns); return ns; } return s; case RESOLUTION_CMD: { lists l = syConvRes((syStrategy)d); s = lString(l, typed, dim); l->Clean(); return s; } case PROC_CMD: { procinfo* pi = (procinfo*) d; if((pi->language == LANG_SINGULAR) && (pi->data.s.body!=NULL)) s = (pi->data.s.body); else s = (char *)""; if (typed) { char* ns = (char*) omAlloc(strlen(s) + 4); sprintf(ns, "\"%s\"", s); omCheckAddr(ns); return ns; } return omStrDup(s); } case LINK_CMD: s = slString((si_link) d); if (typed) { char* ns = (char*) omAlloc(strlen(s) + 10); sprintf(ns, "link(\"%s\")", s); omFreeBinAddr(s); omCheckAddr(ns); return ns; } return s; case LIST_CMD: return lString((lists) d, typed, dim); default: if(t> MAX_TOK) { blackbox *bb=getBlackboxStuff(t); if (bb!=NULL) return bb->blackbox_String(bb,d); } } /* end switch: (Typ()) */ } return omStrDup(""); } int sleftv::Typ() { if (e==NULL) { switch (rtyp) { case IDHDL: return IDTYP((idhdl)data); case ALIAS_CMD: { idhdl h=(idhdl)data; return ((idhdl)h->data.ustring)->typ; } case VECHO: case VPRINTLEVEL: case VCOLMAX: case VTIMER: case VRTIMER: case VOICE: case VMAXDEG: case VMAXMULT: case TRACE: case VSHORTOUT: return INT_CMD; case VMINPOLY: data=NULL; return NUMBER_CMD; case VNOETHER: data=NULL; return POLY_CMD; //case COMMAND: // return COMMAND; default: return rtyp; } } int r=0; int t=rtyp; void *d=data; if (t==IDHDL) t=IDTYP((idhdl)d); else if (t==ALIAS_CMD) { idhdl h=(idhdl)IDDATA((idhdl)data); t=IDTYP(h);d=IDDATA(h); } switch (t) { #ifdef SINGULAR_4_1 case CMATRIX_CMD: { bigintmat *b=(bigintmat*)d; if ((currRing!=NULL)&&(currRing->cf==b->basecoeffs())) return NUMBER_CMD; else return CNUMBER_CMD; } #endif case INTVEC_CMD: case INTMAT_CMD: r=INT_CMD; break; case BIGINTMAT_CMD: r=BIGINT_CMD; break; case IDEAL_CMD: case MATRIX_CMD: case MAP_CMD: r=POLY_CMD; break; case MODUL_CMD: r=VECTOR_CMD; break; case STRING_CMD: r=STRING_CMD; break; default: { blackbox *b=NULL; if (t>MAX_TOK) { b=getBlackboxStuff(t); } if ((t==LIST_CMD)||((b!=NULL)&&BB_LIKE_LIST(b))) { lists l; if (rtyp==IDHDL) l=IDLIST((idhdl)d); else l=(lists)d; if ((0start)&&(e->start<=l->nr+1)) { Subexpr tmp=l->m[e->start-1].e; l->m[e->start-1].e=e->next; r=l->m[e->start-1].Typ(); e->next=l->m[e->start-1].e; l->m[e->start-1].e=tmp; } else { //Warn("out of range: %d not in 1..%d",e->start,l->nr+1); r=DEF_CMD; } } else Werror("cannot index type %s(%d)",Tok2Cmdname(t),t); break; } } return r; } int sleftv::LTyp() { lists l=NULL; int r; if (rtyp==LIST_CMD) l=(lists)data; else if ((rtyp==IDHDL)&& (IDTYP((idhdl)data)==LIST_CMD)) l=IDLIST((idhdl)data); else return Typ(); //if (l!=NULL) { if ((e!=NULL) && (e->next!=NULL)) { if ((0start)&&(e->start<=l->nr+1)) { l->m[e->start-1].e=e->next; r=l->m[e->start-1].LTyp(); l->m[e->start-1].e=NULL; } else { //Warn("out of range: %d not in 1..%d",e->start,l->nr+1); r=NONE; } return r; } return LIST_CMD; } return Typ(); } #ifdef SINGULAR_4_1 static snumber2 iiNumber2Data[4]; static int iiCmatrix_index=0; #endif void * sleftv::Data() { if ((rtyp!=IDHDL) && iiCheckRing(rtyp)) return NULL; if (e==NULL) { switch (rtyp) { case ALIAS_CMD: { idhdl h=(idhdl)data; return ((idhdl)h->data.ustring)->data.ustring; } case VECHO: return (void *)(long)si_echo; case VPRINTLEVEL:return (void *)(long)printlevel; case VCOLMAX: return (void *)(long)colmax; case VTIMER: return (void *)(long)getTimer(); case VRTIMER: return (void *)(long)getRTimer(); case VOICE: return (void *)(long)(myynest+1); case VMAXDEG: return (void *)(long)Kstd1_deg; case VMAXMULT: return (void *)(long)Kstd1_mu; case TRACE: return (void *)(long)traceit; case VSHORTOUT: return (void *)(long)(currRing != NULL ? currRing->ShortOut : 0); case VMINPOLY: if ( (currRing != NULL) && nCoeff_is_algExt(currRing->cf) && !nCoeff_is_GF(currRing->cf)) { /* Q(a), Fp(a), but not GF(q) */ const ring A = currRing->cf->extRing; assume( A != NULL ); assume( A->qideal != NULL ); return (void *)A->qideal->m[0]; } else return (void *)currRing->cf->nNULL; case VNOETHER: return (void *) (currRing->ppNoether); case IDHDL: return IDDATA((idhdl)data); case COMMAND: //return NULL; default: return data; } } /* e != NULL : */ int t=rtyp; void *d=data; if (t==IDHDL) { t=((idhdl)data)->typ; d=IDDATA((idhdl)data); } else if (t==ALIAS_CMD) { idhdl h=(idhdl)IDDATA((idhdl)data); t=IDTYP(h); d=IDDATA(h); } if (iiCheckRing(t)) return NULL; char *r=NULL; int index=e->start; switch (t) { case INTVEC_CMD: { intvec *iv=(intvec *)d; if ((index<1)||(index>iv->length())) { if (!errorreported) Werror("wrong range[%d] in intvec %s(%d)",index,this->Name(),iv->length()); } else r=(char *)(long)((*iv)[index-1]); break; } case INTMAT_CMD: { intvec *iv=(intvec *)d; if ((index<1) ||(index>iv->rows()) ||(e->next->start<1) ||(e->next->start>iv->cols())) { if (!errorreported) Werror("wrong range[%d,%d] in intmat %s(%dx%d)",index,e->next->start, this->Name(),iv->rows(),iv->cols()); } else r=(char *)(long)(IMATELEM((*iv),index,e->next->start)); break; } case BIGINTMAT_CMD: { bigintmat *m=(bigintmat *)d; if ((index<1) ||(index>m->rows()) ||(e->next->start<1) ||(e->next->start>m->cols())) { if (!errorreported) Werror("wrong range[%d,%d] in bigintmat %s(%dx%d)",index,e->next->start, this->Name(),m->rows(),m->cols()); } else r=(char *)(BIMATELEM((*m),index,e->next->start)); break; } #ifdef SINGULAR_4_1 case CMATRIX_CMD: { bigintmat *m=(bigintmat *)d; if ((index<1) ||(index>m->rows()) ||(e->next->start<1) ||(e->next->start>m->cols())) { if (!errorreported) Werror("wrong range[%d,%d] in matrix %s(%dx%d)",index,e->next->start, this->Name(),m->rows(),m->cols()); } else { iiNumber2Data[iiCmatrix_index].cf=m->basecoeffs(); iiNumber2Data[iiCmatrix_index].n=BIMATELEM((*m),index,e->next->start); r=(char*)&iiNumber2Data[iiCmatrix_index]; iiCmatrix_index=(iiCmatrix_index+1) % 4; } break; } #endif case IDEAL_CMD: case MODUL_CMD: case MAP_CMD: { ideal I=(ideal)d; if ((index<1)||(index>IDELEMS(I))) { if (!errorreported) Werror("wrong range[%d] in ideal/module %s(%d)",index,this->Name(),IDELEMS(I)); } else r=(char *)I->m[index-1]; break; } case STRING_CMD: { // this was a memory leak // we evalute it, cleanup and replace this leftv by it's evalutated form // the evalutated form will be build in tmp sleftv tmp; tmp.Init(); tmp.rtyp=STRING_CMD; r=(char *)omAllocBin(size_two_bin); if ((index>0)&& (index<=(int)strlen((char *)d))) { r[0]=*(((char *)d)+index-1); r[1]='\0'; } else { r[0]='\0'; } tmp.data=r; if ((rtyp==IDHDL)||(rtyp==STRING_CMD)) { tmp.next=next; next=NULL; //if (rtyp==STRING_CMD) { omFree((ADDRESS)data); } //data=NULL; d=NULL; CleanUp(); memcpy(this,&tmp,sizeof(tmp)); } // and, remember, r is also the result... else { // ??? // here we still have a memory leak... // example: list L="123","456"; // L[1][2]; // therefore, it should never happen: assume(0); // but if it happens: here is the temporary fix: // omMarkAsStaticAddr(r); } break; } case MATRIX_CMD: { if ((index<1) ||(index>MATROWS((matrix)d)) ||(e->next->start<1) ||(e->next->start>MATCOLS((matrix)d))) { if (!errorreported) Werror("wrong range[%d,%d] in matrix %s(%dx%d)", index,e->next->start, this->Name(), MATROWS((matrix)d),MATCOLS((matrix)d)); } else r=(char *)MATELEM((matrix)d,index,e->next->start); break; } default: { blackbox *b=NULL; if (t>MAX_TOK) { b=getBlackboxStuff(t); } if ((t==LIST_CMD)||((b!=NULL)&&(BB_LIKE_LIST(b)))) { lists l=(lists)d; if ((0nr+1)) { if ((e->next!=NULL) && (l->m[index-1].rtyp==STRING_CMD)) // string[..].Data() modifies sleftv, so let's do it ourself { char *dd=(char *)l->m[index-1].data; int j=e->next->start-1; r=(char *)omAllocBin(size_two_bin); if ((j>=0) && (j<(int)strlen(dd))) { r[0]=*(dd+j); r[1]='\0'; } else { r[0]='\0'; } } else { Subexpr tmp=l->m[index-1].e; l->m[index-1].e=e->next; r=(char *)l->m[index-1].Data(); e->next=l->m[index-1].e; l->m[index-1].e=tmp; } } else //if (!errorreported) Werror("wrong range[%d] in list %s(%d)",index,this->Name(),l->nr+1); } else Werror("cannot index %s of type %s(%d)",this->Name(),Tok2Cmdname(t),t); break; } } return r; } attr * sleftv::Attribute() { if (e==NULL) return &attribute; if ((rtyp==LIST_CMD) ||((rtyp==IDHDL)&&(IDTYP((idhdl)data)==LIST_CMD)) || (rtyp>MAX_TOK) || ((rtyp==IDHDL)&&(IDTYP((idhdl)data)>MAX_TOK))) { leftv v=LData(); return &(v->attribute); } return NULL; } leftv sleftv::LData() { if (e!=NULL) { lists l=NULL; blackbox *b=getBlackboxStuff(rtyp); if ((rtyp==LIST_CMD) || ((b!=NULL)&&(BB_LIKE_LIST(b)))) l=(lists)data; else if ((rtyp==IDHDL)&& (IDTYP((idhdl)data)==LIST_CMD)) l=IDLIST((idhdl)data); else if ((rtyp==IDHDL)&& (IDTYP((idhdl)data)>MAX_TOK)) { b=getBlackboxStuff(IDTYP((idhdl)data)); if (BB_LIKE_LIST(b)) l=IDLIST((idhdl)data); } else if (rtyp==ALIAS_CMD) { idhdl h=(idhdl)data; l= (lists)(((idhdl)h->data.ustring)->data.ustring); } if (l!=NULL) { if ((0>=e->start)||(e->start>l->nr+1)) return NULL; if (e->next!=NULL) { l->m[e->start-1].e=e->next; leftv r=l->m[e->start-1].LData(); l->m[e->start-1].e=NULL; return r; } return &(l->m[e->start-1]); } } return this; } #if 0 leftv sleftv::LHdl() { if (e!=NULL) { lists l=NULL; if (rtyp==LIST_CMD) l=(lists)data; if ((rtyp==IDHDL)&& (IDTYP((idhdl)data)==LIST_CMD)) l=IDLIST((idhdl)data); if (l!=NULL) { if ((0>=e->start)||(e->start>l->nr+1)) return NULL; if (e->next!=NULL) { l->m[e->start-1].e=e->next; leftv r=l->m[e->start-1].LHdl(); l->m[e->start-1].e=NULL; return r; } return &(l->m[e->start-1]); } } return this; } #endif BOOLEAN assumeStdFlag(leftv h) { if (h->e!=NULL) { leftv hh=h->LData(); if (h!=hh) return assumeStdFlag(h->LData()); } if (!hasFlag(h,FLAG_STD)) { if (!TEST_VERB_NSB) { if (TEST_V_ALLWARN) Warn("%s is no standard basis in >>%s<<",h->Name(),my_yylinebuf); else Warn("%s is no standard basis",h->Name()); } return FALSE; } return TRUE; } /*2 * transforms a name (as an string created by omAlloc or omStrDup) * into an expression (sleftv), deletes the string * utility for grammar and iparith */ void syMake(leftv v,const char * id, idhdl packhdl) { /* resolv an identifier: (to DEF_CMD, if siq>0) * 1) reserved id: done by scanner * 2) `basering` / 'Current` * 3) existing identifier, local * 4) ringvar, ringpar, local ring * 5) existing identifier, global * 6) monom (resp. number), local ring: consisting of: * 6') ringvar, ringpar,global ring * 6'') monom (resp. number), local ring * 7) monom (resp. number), non-local ring * 8) basering * 9) `_` * 10) everything else is of type 0 */ #ifdef TEST if ((*id<' ')||(*id>(char)126)) { Print("wrong id :%s:\n",id); } #endif idhdl save_ring=currRingHdl; v->Init(); if(packhdl != NULL) { // Print("setting req_packhdl to %s\n",IDID(packhdl)); v->req_packhdl = IDPACKAGE(packhdl); } else v->req_packhdl = currPack; // if (v->req_packhdl!=basePack) // Print("search %s in %s\n",id,v->req_packhdl->libname); idhdl h=NULL; #ifdef SIQ if (siq<=0) #endif { if (!isdigit(id[0])) { if (strcmp(id,"basering")==0) { if (currRingHdl!=NULL) { if (id!=IDID(currRingHdl)) omFreeBinAddr((ADDRESS)id); h=currRingHdl; goto id_found; } else { v->name = id; return; /* undefined */ } } else if (strcmp(id,"Current")==0) { if (currPackHdl!=NULL) { omFreeBinAddr((ADDRESS)id); h=currPackHdl; goto id_found; } else { v->name = id; return; /* undefined */ } } if(v->req_packhdl!=currPack) { h=v->req_packhdl->idroot->get(id,myynest); } else h=ggetid(id); /* 3) existing identifier, local */ if ((h!=NULL) && (IDLEV(h)==myynest)) { if (id!=IDID(h)) omFreeBinAddr((ADDRESS)id); /*assume strlen(id) <1000 */ goto id_found; } } if (yyInRingConstruction) { currRingHdl=NULL; } /* 4. local ring: ringvar */ if ((currRingHdl!=NULL) && (IDLEV(currRingHdl)==myynest) /*&& (!yyInRingConstruction)*/) { int vnr; if ((vnr=r_IsRingVar(id, currRing->names,currRing->N))>=0) { poly p=pOne(); pSetExp(p,vnr+1,1); pSetm(p); v->data = (void *)p; v->name = id; v->rtyp = POLY_CMD; return; } if((n_NumberOfParameters(currRing->cf)>0) &&((vnr=r_IsRingVar(id, (char**)n_ParameterNames(currRing->cf), n_NumberOfParameters(currRing->cf))>=0))) { BOOLEAN ok=FALSE; poly p = pmInit(id,ok); if (ok && (p!=NULL)) { v->data = pGetCoeff(p); pGetCoeff(p)=NULL; pLmFree(p); v->rtyp = NUMBER_CMD; v->name = id; return; } } } /* 5. existing identifier, global */ if (h!=NULL) { if (id!=IDID(h)) omFreeBinAddr((ADDRESS)id); /*assume strlen(id) <1000 */ goto id_found; } /* 6. local ring: number/poly */ if ((currRingHdl!=NULL) && (IDLEV(currRingHdl)==myynest)) { BOOLEAN ok=FALSE; /*poly p = (!yyInRingConstruction) ? pmInit(id,ok) : (poly)NULL;*/ poly p = pmInit(id,ok); if (ok) { if (p==NULL) { v->data = (void *)nInit(0); v->rtyp = NUMBER_CMD; #ifdef HAVE_PLURAL // in this case we may have monomials equal to 0 in p_Read v->name = id; #else omFreeBinAddr((ADDRESS)id); #endif } else if (pIsConstant(p)) { v->data = pGetCoeff(p); pGetCoeff(p)=NULL; pLmFree(p); v->rtyp = NUMBER_CMD; v->name = id; } else { v->data = p; v->rtyp = POLY_CMD; v->name = id; } return; } } /* 7. non-local ring: number/poly */ { BOOLEAN ok=FALSE; poly p = ((currRing!=NULL) /* ring required */ && (currRingHdl!=NULL) /*&& (!yyInRingConstruction) - not in decl */ && (IDLEV(currRingHdl)!=myynest)) /* already in case 4/6 */ ? pmInit(id,ok) : (poly)NULL; if (ok) { if (p==NULL) { v->data = (void *)nInit(0); v->rtyp = NUMBER_CMD; #ifdef HAVE_PLURAL // in this case we may have monomials equal to 0 in p_Read v->name = id; #else omFreeBinAddr((ADDRESS)id); #endif } else if (pIsConstant(p)) { v->data = pGetCoeff(p); pGetCoeff(p)=NULL; pLmFree(p); v->rtyp = NUMBER_CMD; v->name = id; } else { v->data = p; v->rtyp = POLY_CMD; v->name = id; } //if (TEST_V_ALLWARN /*&& (myynest>0)*/ //&& ((r_IsRingVar(id, currRing->names,currRing->N)>=0) // || ((n_NumberOfParameters(currRing->cf)>0) // &&(r_IsRingVar(id, (char**)n_ParameterNames(currRing->cf), // n_NumberOfParameters(currRing->cf))>=0)))) //{ //// WARNING: do not use ring variable names in procedures // Warn("use of variable >>%s<< in a procedure in line %s",id,my_yylinebuf); //} return; } } /* 8. basering ? */ if ((myynest>1)&&(currRingHdl!=NULL)) { if (strcmp(id,IDID(currRingHdl))==0) { if (IDID(currRingHdl)!=id) omFreeBinAddr((ADDRESS)id); /*assume strlen (id) <1000 */ h=currRingHdl; goto id_found; } } if((v->req_packhdl!=basePack) && (v->req_packhdl==currPack)) { h=basePack->idroot->get(id,myynest); if (h!=NULL) { if (id!=IDID(h)) omFreeBinAddr((ADDRESS)id); /*assume strlen(id) <1000 */ v->req_packhdl=basePack; goto id_found; } } } #ifdef SIQ else v->rtyp=DEF_CMD; #endif /* 9: _ */ if (strcmp(id,"_")==0) { omFreeBinAddr((ADDRESS)id); v->Copy(&sLastPrinted); } else { /* 10: everything else */ /* v->rtyp = UNKNOWN;*/ v->name = id; } currRingHdl=save_ring; return; id_found: // we have an id (in h) found, to set the data in from h if (IDTYP(h)!=ALIAS_CMD) { v->rtyp = IDHDL; v->flag = IDFLAG(h); v->attribute=IDATTR(h); } else { v->rtyp = ALIAS_CMD; } v->name = IDID(h); v->data = (char *)h; currRingHdl=save_ring; } int sleftv::Eval() { BOOLEAN nok=FALSE; leftv nn=next; next=NULL; if(rtyp==IDHDL) { int t=Typ(); if (t!=PROC_CMD) { void *d=CopyD(t); data=d; rtyp=t; name=NULL; e=NULL; } } else if (rtyp==COMMAND) { command d=(command)data; if(d->op==PROC_CMD) //assume d->argc==2 { char *what=(char *)(d->arg1.Data()); idhdl h=ggetid(what); if((h!=NULL)&&(IDTYP(h)==PROC_CMD)) { nok=d->arg2.Eval(); if(!nok) { nok=iiMake_proc(h,req_packhdl,&d->arg2); this->CleanUp(currRing); if (!nok) { memcpy(this,&iiRETURNEXPR,sizeof(sleftv)); memset(&iiRETURNEXPR,0,sizeof(sleftv)); } } } else nok=TRUE; } else if (d->op=='=') //assume d->argc==2 { if ((d->arg1.rtyp!=IDHDL)&&(d->arg1.rtyp!=DEF_CMD)) { nok=d->arg1.Eval(); } if (!nok) { const char *n=d->arg1.name; nok=(n == NULL) || d->arg2.Eval(); if (!nok) { int save_typ=d->arg1.rtyp; omCheckAddr((ADDRESS)n); if (d->arg1.rtyp!=IDHDL) syMake(&d->arg1,n); omCheckAddr((ADDRESS)d->arg1.name); if (d->arg1.rtyp==IDHDL) { n=omStrDup(IDID((idhdl)d->arg1.data)); killhdl((idhdl)d->arg1.data); d->arg1.Init(); //d->arg1.data=NULL; d->arg1.name=n; } d->arg1.rtyp=DEF_CMD; sleftv t; if(save_typ!=PROC_CMD) save_typ=d->arg2.rtyp; if (::RingDependend(d->arg2.rtyp)) nok=iiDeclCommand(&t,&d->arg1,0,save_typ,&currRing->idroot); else nok=iiDeclCommand(&t,&d->arg1,0,save_typ,&IDROOT); memcpy(&d->arg1,&t,sizeof(sleftv)); omCheckAddr((ADDRESS)d->arg1.name); nok=nok||iiAssign(&d->arg1,&d->arg2); omCheckIf(d->arg1.name != NULL, // OB: ???? omCheckAddr((ADDRESS)d->arg1.name)); if (!nok) { memset(&d->arg1,0,sizeof(sleftv)); this->CleanUp(); rtyp=NONE; } } } else nok=TRUE; } else { sleftv tmp; tmp.Init(); int toktype=iiTokType(d->op); if ((toktype==CMD_M) ||( toktype==ROOT_DECL_LIST) ||( toktype==RING_DECL_LIST)) { if (d->argc <=3) { if (d->argc>=1) nok=d->arg1.Eval(); if ((!nok) && (d->argc>=2)) { nok=d->arg2.Eval(); d->arg1.next=(leftv)omAllocBin(sleftv_bin); memcpy(d->arg1.next,&d->arg2,sizeof(sleftv)); d->arg2.Init(); } if ((!nok) && (d->argc==3)) { nok=d->arg3.Eval(); d->arg1.next->next=(leftv)omAllocBin(sleftv_bin); memcpy(d->arg1.next->next,&d->arg3,sizeof(sleftv)); d->arg3.Init(); } if (d->argc==0) nok=nok||iiExprArithM(&tmp,NULL,d->op); else nok=nok||iiExprArithM(&tmp,&d->arg1,d->op); } else { nok=d->arg1.Eval(); nok=nok||iiExprArithM(&tmp,&d->arg1,d->op); } } else if (d->argc==1) { nok=d->arg1.Eval(); nok=nok||iiExprArith1(&tmp,&d->arg1,d->op); } else if(d->argc==2) { nok=d->arg1.Eval(); nok=nok||d->arg2.Eval(); nok=nok||iiExprArith2(&tmp,&d->arg1,d->op,&d->arg2); } else if(d->argc==3) { nok=d->arg1.Eval(); nok=nok||d->arg2.Eval(); nok=nok||d->arg3.Eval(); nok=nok||iiExprArith3(&tmp,d->op,&d->arg1,&d->arg2,&d->arg3); } else if(d->argc!=0) { nok=d->arg1.Eval(); nok=nok||iiExprArithM(&tmp,&d->arg1,d->op); } else // d->argc == 0 { nok = iiExprArithM(&tmp, NULL, d->op); } this->CleanUp(); memcpy(this,&tmp,sizeof(tmp)); } } else if (((rtyp==0)||(rtyp==DEF_CMD)) &&(name!=NULL)) { syMake(this,name); } #ifdef MDEBUG switch(Typ()) { case NUMBER_CMD: #ifdef LDEBUG nTest((number)Data()); #endif break; case BIGINT_CMD: #ifdef LDEBUG n_Test((number)Data(),coeffs_BIGINT); #endif break; case POLY_CMD: pTest((poly)Data()); break; case IDEAL_CMD: case MODUL_CMD: case MATRIX_CMD: { ideal id=(ideal)Data(); omCheckAddrSize(id,sizeof(*id)); int i=id->ncols*id->nrows-1; for(;i>=0;i--) pTest(id->m[i]); } break; } #endif if (nn!=NULL) nok=nok||nn->Eval(); next=nn; return nok; } const char *iiSleftv2name(leftv v) { return(v->name); } void * sattr::CopyA() { omCheckAddrSize(this,sizeof(sattr)); return s_internalCopy(atyp,data); } singular-4.0.3+ds/Singular/subexpr.h000066400000000000000000000116401266270727000174040ustar00rootroot00000000000000#ifndef SUBEXPR_H #define SUBEXPR_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: handling of leftv */ #include #include //#include #include #include #include typedef enum { LANG_NONE, LANG_TOP, LANG_SINGULAR, LANG_C, LANG_MAX} language_defs; class proc_singular { public: long proc_start; // position where proc is starting long def_end; // position where proc header is ending long help_start; // position where help is starting long help_end; // position where help is starting long body_start; // position where proc-body is starting long body_end; // position where proc-body is ending long example_start; // position where example is starting long proc_end; // position where proc is ending int proc_lineno; int body_lineno; int example_lineno; char *body; long help_chksum; }; struct proc_object { //public: BOOLEAN (*function)(leftv res, leftv v); }; union uprocinfodata { public: proc_singular s; // data of Singular-procedure struct proc_object o; // pointer to binary-function }; typedef union uprocinfodata procinfodata; class procinfo { public: char *libname; char *procname; package pack; language_defs language; short ref; char is_static; // if set, proc not accessible for user char trace_flag; procinfodata data; }; typedef procinfo * procinfov; struct _ssubexpr { struct _ssubexpr * next; int start; }; typedef struct _ssubexpr *Subexpr; extern const char sNoName[]; extern BOOLEAN siq; extern const char *iiSleftv2name(leftv v); class sleftv; typedef sleftv * leftv; /// Class used for (list of) interpreter objects class sleftv { public: /* !! do not change the first 6 entries !! (see ipid.h: idrec) */ leftv next; const char *name; void * data; attr attribute; BITSET flag; int rtyp; /* the type of the expression, describes the data field * (E) markes the type field in iparith * (S) markes the rtyp in sleftv * ANY_TYPE: data is int: real type or 0 (E) * DEF_CMD: all types, no change in sleftv (E) * IDHDL: existing variable (E) * IDHDL: variable, data is idhdl (S) * COMMAND: data is command (S) * INT_CMD: int constant, data is int (E,S) * INTVEC_CMD: intvec constant, data is intvec * (E,S) * POLY_CMD: poly constant, data is poly (E,S) * .... */ Subexpr e; /* holds the indices for indexed values */ package req_packhdl; inline void Init() { memset(this,0,sizeof(*this)); } void CleanUp(ring r=currRing); /// Called by type_cmd (e.g. "r;") or as default in jPRINT void Print(leftv store=NULL,int spaces=0); /// Called for conversion to string (used by string(..), write(..),..) char * String(void *d=NULL, BOOLEAN typed = FALSE, int dim = 1); void Copy(leftv e); attr CopyA(); void * CopyD(int t); void * CopyD() { return CopyD(Typ()); } inline const char * Name() { if ((name!=NULL) && (e==NULL)) return name; else return sNoName; } inline const char * Fullname() { if ((name!=NULL) && (e==NULL)) return(iiSleftv2name(this)); else return sNoName; } int Typ(); int LTyp(); /* returns LIST_CMD for l[i], otherwise returns Typ() */ void * Data(); leftv LData(); /* returns &(l[i]) for l[i], otherwise returns this */ //leftv LHdl(); attr * Attribute(); inline leftv Next() { return next; } int listLength(); int Eval(); /*replace a COMMAND by its result otherwise by CopyD*/ BOOLEAN RingDependend(); }; inline BOOLEAN RingDependend(int t) { return (BEGIN_RINGref++; return pi; } BOOLEAN piKill(procinfov l); const char *piProcinfo(procinfov pi, const char *request); void piShowProcinfo(procinfov pi, char *txt); #ifdef HAVE_LIBPARSER class libstack; typedef libstack * libstackv; class libstack { public: libstackv next; char *libname; BOOLEAN to_be_done; int cnt; void push(const char *p, char * libname); libstackv pop(const char *p); inline char *get() { return(libname); } }; #endif /* HAVE_LIBPARSER */ extern omBin sSubexpr_bin; extern omBin procinfo_bin; extern omBin libstack_bin; void s_internalDelete(const int t, void *d, const ring r); #endif singular-4.0.3+ds/Singular/table.h000066400000000000000000002755431266270727000170210ustar00rootroot00000000000000#ifdef IPARITH // additional to the usual types: INT_CMD etc. // thre are special types: // for the input: // IDHDL: argument must have a name // DEF_CMD: no restriktions on the argument // ANY_TYPE: changes to pseudo data (for "defined", "typeof", etc.) // with the following subfields // - name !=NULL // - data := original type id // for the output: // NONE: does not return a value // ANY_TYPE: various types, the routines have to set it // the procedures have to be wrapped into the macro D(...) // with the exception of jjWRONG... (which always fails) /*=================== operations with 1 arg.: table =================*/ struct sValCmd1 dArith1[]= { // operations: // proc cmd res arg context {D(jjPLUSPLUS), PLUSPLUS, NONE, IDHDL , ALLOW_PLURAL |ALLOW_RING} ,{D(jjPLUSPLUS), MINUSMINUS, NONE, IDHDL , ALLOW_PLURAL |ALLOW_RING} ,{D(jjUMINUS_I), '-', INT_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjUMINUS_BI), '-', BIGINT_CMD, BIGINT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjUMINUS_N), '-', NUMBER_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjNUMBER2_OP1),'-', CNUMBER_CMD, CNUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjUMINUS_P), '-', POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjUMINUS_P), '-', VECTOR_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjUMINUS_MA), '-', MATRIX_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjUMINUS_IV), '-', INTVEC_CMD, INTVEC_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjUMINUS_IV), '-', INTMAT_CMD, INTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjUMINUS_BIM), '-', BIGINTMAT_CMD, BIGINTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjUMINUS_BIM), '-', CMATRIX_CMD, CMATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjPROC1), '(', ANY_TYPE/*set by p*/,PROC_CMD , ALLOW_PLURAL |ALLOW_RING} // and the procedures with 1 argument: ,{D(atATTRIB1), ATTRIB_CMD, NONE, DEF_CMD , ALLOW_PLURAL |ALLOW_RING} //,{D(jjBAREISS_IM), BAREISS_CMD, INTMAT_CMD, INTMAT_CMD , NO_PLURAL |ALLOW_RING | NO_ZERODIVISOR} ,{D(jjBAREISS), BAREISS_CMD, LIST_CMD, MODUL_CMD , NO_PLURAL |ALLOW_RING | NO_ZERODIVISOR} ,{D(jjBETTI), BETTI_CMD, INTMAT_CMD, LIST_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(syBetti1), BETTI_CMD, INTMAT_CMD, RESOLUTION_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBETTI), BETTI_CMD, INTMAT_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjBETTI), BETTI_CMD, INTMAT_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), BIGINT_CMD, BIGINT_CMD, BIGINT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjN2BI), BIGINT_CMD, BIGINT_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjP2BI), BIGINT_CMD, BIGINT_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), BIGINTMAT_CMD, BIGINTMAT_CMD, BIGINTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCHAR), CHARACTERISTIC_CMD, INT_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCHARSERIES), CHAR_SERIES_CMD, MATRIX_CMD, IDEAL_CMD , NO_PLURAL |NO_RING} ,{D(jjrCharStr), CHARSTR_CMD, STRING_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjOpenClose), CLOSE_CMD, NONE, LINK_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), CMATRIX_CMD, CMATRIX_CMD, CMATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} //,{ jjWRONG , COLS_CMD, 0, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOLS), COLS_CMD, INT_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOLS), COLS_CMD, INT_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOLS), COLS_CMD, INT_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOLS_IV), COLS_CMD, INT_CMD, INTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOLS_BIM), COLS_CMD, INT_CMD, BIGINTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjCOLS_BIM), COLS_CMD, INT_CMD, CMATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} #endif ,{ jjWRONG , COLS_CMD, 0, INTVEC_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCONTENT), CONTENT_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCONTENT), CONTENT_CMD, VECTOR_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOUNT_BI), COUNT_CMD, INT_CMD, BIGINT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOUNT_N), COUNT_CMD, INT_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOUNT_RES), COUNT_CMD, INT_CMD, RESOLUTION_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjstrlen), COUNT_CMD, INT_CMD, STRING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjpLength), COUNT_CMD, INT_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjpLength), COUNT_CMD, INT_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjidElem), COUNT_CMD, INT_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjidElem), COUNT_CMD, INT_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOUNT_M), COUNT_CMD, INT_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOUNT_IV), COUNT_CMD, INT_CMD, INTVEC_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOUNT_IV), COUNT_CMD, INT_CMD, INTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOUNT_L), COUNT_CMD, INT_CMD, LIST_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOUNT_RG), COUNT_CMD, INT_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjN2_CR), CRING_CMD, CRING_CMD, CNUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCM_CR), CRING_CMD, CRING_CMD, CMATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjBIM2_CR), CRING_CMD, CRING_CMD, BIGINTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjR2_CR), CRING_CMD, CRING_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjNULL), DEF_CMD, DEF_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{ jjWRONG , DEF_CMD, 0, ANY_TYPE , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDEG), DEG_CMD, INT_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDEG), DEG_CMD, INT_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDEG_M), DEG_CMD, INT_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDEGREE), DEGREE_CMD, STRING_CMD, IDEAL_CMD , NO_PLURAL |ALLOW_RING | NO_ZERODIVISOR} ,{D(jjDEGREE), DEGREE_CMD, STRING_CMD, MODUL_CMD , NO_PLURAL |ALLOW_RING | NO_ZERODIVISOR} ,{D(jjDEFINED), DEFINED_CMD, INT_CMD, DEF_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDENOMINATOR),DENOMINATOR_CMD, NUMBER_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjNUMERATOR), NUMERATOR_CMD, NUMBER_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDET_BI), DET_CMD, BIGINT_CMD, BIGINTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDET_I), DET_CMD, INT_CMD, INTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDET), DET_CMD, POLY_CMD, MATRIX_CMD , NO_PLURAL |ALLOW_RING} ,{D(jjDET_S), DET_CMD, POLY_CMD, MODUL_CMD , NO_PLURAL |NO_RING} ,{D(jjDIM), DIM_CMD, INT_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIM), DIM_CMD, INT_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIM_R), DIM_CMD, INT_CMD, RESOLUTION_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMP), DUMP_CMD, NONE, LINK_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjE), E_CMD, VECTOR_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjEXECUTE), EXECUTE_CMD, NONE, STRING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjERROR), ERROR_CMD, NONE, STRING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjFAC_P), FAC_CMD, LIST_CMD, POLY_CMD , NO_PLURAL |NO_RING} ,{D(findUniProc), FINDUNI_CMD, IDEAL_CMD, IDEAL_CMD , NO_PLURAL |NO_RING} ,{D(jjidFreeModule),FREEMODULE_CMD, MODUL_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjFACSTD), FACSTD_CMD, LIST_CMD, IDEAL_CMD , NO_PLURAL |NO_RING} ,{D(jjGETDUMP), GETDUMP_CMD, NONE, LINK_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjHIGHCORNER), HIGHCORNER_CMD, POLY_CMD, IDEAL_CMD , NO_PLURAL |ALLOW_RING} ,{D(jjHIGHCORNER_M), HIGHCORNER_CMD,VECTOR_CMD, MODUL_CMD , NO_PLURAL |ALLOW_RING} ,{D(jjHILBERT), HILBERT_CMD, NONE, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING | NO_ZERODIVISOR} ,{D(jjHILBERT), HILBERT_CMD, NONE, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING | NO_ZERODIVISOR} ,{D(jjHILBERT_IV), HILBERT_CMD, INTVEC_CMD, INTVEC_CMD , ALLOW_PLURAL |ALLOW_RING | NO_ZERODIVISOR} ,{D(jjHOMOG1), HOMOG_CMD, INT_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjHOMOG1), HOMOG_CMD, INT_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), IDEAL_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjidVec2Ideal),IDEAL_CMD, IDEAL_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIDEAL_Ma), IDEAL_CMD, IDEAL_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIDEAL_R), IDEAL_CMD, IDEAL_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIDEAL_Map), IDEAL_CMD, IDEAL_CMD, MAP_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIMPART), IMPART_CMD, NUMBER_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjINDEPSET), INDEPSET_CMD, INTVEC_CMD, IDEAL_CMD , NO_PLURAL |NO_RING} ,{D(jjDUMMY), INT_CMD, INT_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjnlInt), INT_CMD, INT_CMD, BIGINT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjnInt), INT_CMD, INT_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjP2I), INT_CMD, INT_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjINTERRED), INTERRED_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |NO_RING} ,{D(jjINTERRED), INTERRED_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |NO_RING} ,{D(jjBI2IM), INTMAT_CMD, INTMAT_CMD, BIGINTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), INTMAT_CMD, INTMAT_CMD, INTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIm2Iv), INTVEC_CMD, INTVEC_CMD, INTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), INTVEC_CMD, INTVEC_CMD, INTVEC_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIS_RINGVAR_P), IS_RINGVAR, INT_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIS_RINGVAR_S), IS_RINGVAR, INT_CMD, STRING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIS_RINGVAR0),IS_RINGVAR, INT_CMD, ANY_TYPE , ALLOW_PLURAL |ALLOW_RING} ,{D(jjJACOB_P), JACOB_CMD, IDEAL_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(mpJacobi), JACOB_CMD, MATRIX_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjJACOB_M), JACOB_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjJanetBasis), JANET_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |NO_RING} ,{D(jjKBASE), KBASE_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING|WARN_RING} /*ring-cf: warning at top level*/ ,{D(jjKBASE), KBASE_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING|WARN_RING} /*ring-cf: warning at top level*/ ,{D(jjLU_DECOMP), LU_CMD, LIST_CMD, MATRIX_CMD , NO_PLURAL |NO_RING} ,{D(jjPFAC1), PFAC_CMD, LIST_CMD, BIGINT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjPFAC1), PFAC_CMD, LIST_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(atKILLATTR1), KILLATTR_CMD, NONE, IDHDL , ALLOW_PLURAL |ALLOW_RING} ,{D(jjpHead), LEAD_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjidHead), LEAD_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjpHead), LEAD_CMD, VECTOR_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjidHead), LEAD_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLEADCOEF), LEADCOEF_CMD, NUMBER_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLEADCOEF), LEADCOEF_CMD, NUMBER_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLEADEXP), LEADEXP_CMD, INTVEC_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLEADEXP), LEADEXP_CMD, INTVEC_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLEADMONOM), LEADMONOM_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLEADMONOM), LEADMONOM_CMD, VECTOR_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), LINK_CMD, LINK_CMD, LINK_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL1MANY), LIST_CMD, LIST_CMD, DEF_CMD , ALLOW_PLURAL |ALLOW_RING} ,{ jjWRONG , MAP_CMD, 0, ANY_TYPE , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), MATRIX_CMD, MATRIX_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjidMaxIdeal), MAXID_CMD, IDEAL_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjMEMORY), MEMORY_CMD, BIGINT_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjidMinBase), MINBASE_CMD, IDEAL_CMD, IDEAL_CMD , NO_PLURAL |NO_RING} ,{D(jjidMinBase), MINBASE_CMD, MODUL_CMD, MODUL_CMD , NO_PLURAL |NO_RING} ,{D(jjMINRES), MINRES_CMD, LIST_CMD, LIST_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjMINRES_R), MINRES_CMD, RESOLUTION_CMD, RESOLUTION_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), MODUL_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjMONITOR1), MONITOR_CMD, NONE, LINK_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjMONOM), MONOM_CMD, POLY_CMD, INTVEC_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjMULT), MULTIPLICITY_CMD, INT_CMD, IDEAL_CMD , NO_PLURAL |ALLOW_RING} ,{D(jjMULT), MULTIPLICITY_CMD, INT_CMD, MODUL_CMD , NO_PLURAL |ALLOW_RING} ,{D(jjMSTD), MSTD_CMD, LIST_CMD, IDEAL_CMD , NO_PLURAL |ALLOW_RING} ,{D(jjMSTD), MSTD_CMD, LIST_CMD, MODUL_CMD , NO_PLURAL |ALLOW_RING} ,{D(jjNAMEOF), NAMEOF_CMD, STRING_CMD, ANY_TYPE , ALLOW_PLURAL |ALLOW_RING} ,{D(jjNAMES_I), NAMES_CMD, LIST_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjNAMES), NAMES_CMD, LIST_CMD, PACKAGE_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjNAMES), NAMES_CMD, LIST_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjNOT), NOT, INT_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjN2_N), NUMBER_CMD, NUMBER_CMD, CNUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjDUMMY), NUMBER_CMD, NUMBER_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjN2_N), NUMBER_CMD, NUMBER_CMD, CNUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjP2N), NUMBER_CMD, NUMBER_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjBI2N), NUMBER_CMD, NUMBER_CMD, BIGINT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), CNUMBER_CMD, CNUMBER_CMD, CNUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjRPAR), NPARS_CMD, INT_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjNVARS), NVARS_CMD, INT_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjOpenClose), OPEN_CMD, NONE, LINK_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL1MANY), OPTION_CMD, NONE, DEF_CMD , ALLOW_PLURAL |ALLOW_RING} /*libsing*/ ,{D(jjORD), ORD_CMD, INT_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjORD), ORD_CMD, INT_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjrOrdStr), ORDSTR_CMD, STRING_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjPAR1), PAR_CMD, NUMBER_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjPARDEG), PARDEG_CMD, INT_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjPARSTR1), PARSTR_CMD, STRING_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjrParStr), PARSTR_CMD, STRING_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), POLY_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjBI2P), POLY_CMD, POLY_CMD, BIGINT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjPREIMAGE_R), PREIMAGE_CMD, RING_CMD, MAP_CMD , NO_PLURAL |ALLOW_RING} ,{D(jjPRIME), PRIME_CMD, INT_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjPRINT), PRINT_CMD, STRING_CMD, LIST_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjPRINT), PRINT_CMD, STRING_CMD, DEF_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), PROC_CMD, PROC_CMD, PROC_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjPRUNE), PRUNE_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(kQHWeight), QHWEIGHT_CMD, INTVEC_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(kQHWeight), QHWEIGHT_CMD, INTVEC_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), QRING_CMD, QRING_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjRANK1), RANK_CMD, INT_CMD, MATRIX_CMD , ALLOW_PLURAL |NO_RING} ,{D(jjREAD), READ_CMD, STRING_CMD, LINK_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjREGULARITY), REGULARITY_CMD, INT_CMD, LIST_CMD , NO_PLURAL |ALLOW_RING} ,{D(jjREPART), REPART_CMD, NUMBER_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjRESERVEDNAME),RESERVEDNAME_CMD, INT_CMD, STRING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjL2R), RESOLUTION_CMD, RESOLUTION_CMD, LIST_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), RESOLUTION_CMD, RESOLUTION_CMD, RESOLUTION_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRINGLIST), RINGLIST_CMD, LIST_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjRINGLIST_C), RINGLIST_CMD, LIST_CMD, CRING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjN2_CR), RING_CMD, CRING_CMD, CNUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCM_CR), RING_CMD, CRING_CMD, CMATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjDUMMY), RING_CMD, RING_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLISTRING), RING_CMD, RING_CMD, LIST_CMD , ALLOW_PLURAL |ALLOW_RING} //,{ jjWRONG , ROWS_CMD, 0, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjpMaxComp), ROWS_CMD, INT_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjROWS), ROWS_CMD, INT_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjROWS), ROWS_CMD, INT_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjROWS_IV), ROWS_CMD, INT_CMD, INTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjROWS_BIM), ROWS_CMD, INT_CMD, BIGINTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjROWS_BIM), ROWS_CMD, INT_CMD, CMATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjCOUNT_IV), ROWS_CMD, INT_CMD, INTVEC_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSBA), SBA_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSBA), SBA_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSLIM_GB), SLIM_GB_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL } ,{D(jjSLIM_GB), SLIM_GB_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL } ,{D(jjSort_Id), SORTVEC_CMD, INTVEC_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSort_Id), SORTVEC_CMD, INTVEC_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSQR_FREE), SQR_FREE_CMD, LIST_CMD, POLY_CMD , NO_PLURAL |NO_RING} ,{D(jjSTD), STD_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTD), STD_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), STRING_CMD, STRING_CMD, STRING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSYZYGY), SYZYGY_CMD, MODUL_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSYZYGY), SYZYGY_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef HAVE_PLURAL ,{D(jjENVELOPE), ENVELOPE_CMD, RING_CMD, RING_CMD , ALLOW_PLURAL |NO_RING} ,{D(jjOPPOSITE), OPPOSITE_CMD, RING_CMD, RING_CMD , ALLOW_PLURAL |NO_RING} ,{D(jjTWOSTD), TWOSTD_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |NO_RING} #endif ,{ jjWRONG , TRACE_CMD, 0, INTVEC_CMD , ALLOW_PLURAL |ALLOW_RING} ,{ jjWRONG , TRACE_CMD, 0, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjTRACE_IV), TRACE_CMD, INT_CMD, INTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjmpTrace), TRACE_CMD, POLY_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjTRANSP_IV), TRANSPOSE_CMD, INTMAT_CMD, INTVEC_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjTRANSP_IV), TRANSPOSE_CMD, INTMAT_CMD, INTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjTRANSP_BIM), TRANSPOSE_CMD, BIGINTMAT_CMD, BIGINTMAT_CMD , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjTRANSP_BIM), TRANSPOSE_CMD, CMATRIX_CMD, CMATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjmpTransp), TRANSPOSE_CMD, MATRIX_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjidTransp), TRANSPOSE_CMD, MODUL_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjTYPEOF), TYPEOF_CMD, STRING_CMD, ANY_TYPE , ALLOW_PLURAL |ALLOW_RING} ,{D(jjUNIVARIATE), UNIVARIATE_CMD, INT_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjVARIABLES_P),VARIABLES_CMD, IDEAL_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjVARIABLES_ID),VARIABLES_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjVARIABLES_ID),VARIABLES_CMD, IDEAL_CMD, MATRIX_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDUMMY), VECTOR_CMD, VECTOR_CMD, VECTOR_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjVDIM), VDIM_CMD, INT_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING |WARN_RING} /*ring-cf: warning at top level*/ ,{D(jjVDIM), VDIM_CMD, INT_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING |WARN_RING} /*ring-cf: warning at top level*/ ,{D(jjVAR1), VAR_CMD, POLY_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjVARSTR1), VARSTR_CMD, STRING_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjrVarStr), VARSTR_CMD, STRING_CMD, RING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(kWeight), WEIGHT_CMD, INTVEC_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(kWeight), WEIGHT_CMD, INTVEC_CMD, MODUL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLOAD1), LOAD_CMD, NONE, STRING_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(loNewtonP), NEWTONPOLY_CMD, IDEAL_CMD, IDEAL_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjWAIT1ST1), WAIT1ST_CMD, INT_CMD, LIST_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjWAITALL1), WAITALL_CMD, INT_CMD, LIST_CMD , ALLOW_PLURAL |ALLOW_RING} ,{NULL_VAL, 0, 0, 0 , NO_PLURAL |NO_RING} }; /*=================== operations with 2 arg.: table =================*/ struct sValCmd2 dArith2[]= { // operations: // proc cmd res arg1 arg2 context {D(jjCOLCOL), COLONCOLON, ANY_TYPE, DEF_CMD, DEF_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_I), '+', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_BI), '+', BIGINT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_N), '+', NUMBER_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjNUMBER2_OP2),'+', CNUMBER_CMD, CNUMBER_CMD,CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'+', CNUMBER_CMD, INT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'+', CNUMBER_CMD, CNUMBER_CMD,INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'+', CNUMBER_CMD, BIGINT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'+', CNUMBER_CMD, CNUMBER_CMD,BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjPLUS_P), '+', POLY_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_P), '+', VECTOR_CMD, VECTOR_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_ID), '+', IDEAL_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_ID), '+', MODUL_CMD, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_P_MA), '+', MATRIX_CMD, POLY_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_MA_P), '+', MATRIX_CMD, MATRIX_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_MA), '+', MATRIX_CMD, MATRIX_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_S), '+', STRING_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_BIM), '+', BIGINTMAT_CMD, BIGINTMAT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_BIM_I), '+', BIGINTMAT_CMD, BIGINTMAT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_I_BIM), '+', BIGINTMAT_CMD, INT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_BIM_BI), '+', BIGINTMAT_CMD, BIGINTMAT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_BI_BIM), '+', BIGINTMAT_CMD, BIGINT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), '+', INTVEC_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_I_IV), '+', INTVEC_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IM_I), '+', INTMAT_CMD, INTMAT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_I_IM), '+', INTMAT_CMD, INT_CMD, INTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_IV), '+', INTVEC_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_IV), '+', INTMAT_CMD, INTMAT_CMD, INTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjPLUS_BIM), '+', CMATRIX_CMD, CMATRIX_CMD, CMATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(lAdd), '+', LIST_CMD, LIST_CMD, LIST_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjRSUM), '+', RING_CMD, RING_CMD, RING_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMINUS_I), '-', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMINUS_BI), '-', BIGINT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMINUS_N), '-', NUMBER_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjNUMBER2_OP2),'-', CNUMBER_CMD, CNUMBER_CMD,CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'-', CNUMBER_CMD, INT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'-', CNUMBER_CMD, CNUMBER_CMD,INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'-', CNUMBER_CMD, BIGINT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'-', CNUMBER_CMD, CNUMBER_CMD,BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjMINUS_P), '-', POLY_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMINUS_P), '-', VECTOR_CMD, VECTOR_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPLUS_MA_P), '-', MATRIX_CMD, MATRIX_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMINUS_MA), '-', MATRIX_CMD, MATRIX_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMINUS_BIM), '-', BIGINTMAT_CMD, BIGINTMAT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_BIM_I), '-', BIGINTMAT_CMD, BIGINTMAT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_I_BIM), '-', BIGINTMAT_CMD, INT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_BIM_BI), '-', BIGINTMAT_CMD, BIGINTMAT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_BI_BIM), '-', BIGINTMAT_CMD, BIGINT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), '-', INTVEC_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IM_I), '-', INTMAT_CMD, INTMAT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMINUS_IV), '-', INTVEC_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMINUS_IV), '-', INTMAT_CMD, INTMAT_CMD, INTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjMINUS_BIM), '-', CMATRIX_CMD, CMATRIX_CMD,CMATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{ jjWRONG2 , '-', NONE, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{ jjWRONG2 , '-', NONE, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_I), '*', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_BI), '*', BIGINT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_N), '*', NUMBER_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjNUMBER2_OP2),'*', CNUMBER_CMD, CNUMBER_CMD,CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'*', CNUMBER_CMD, INT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'*', CNUMBER_CMD, CNUMBER_CMD,INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'*', CNUMBER_CMD, BIGINT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'*', CNUMBER_CMD, CNUMBER_CMD,BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjTIMES_P), '*', POLY_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_P), '*', VECTOR_CMD, POLY_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_P), '*', VECTOR_CMD, VECTOR_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_P1),'*', IDEAL_CMD, IDEAL_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_P2),'*', IDEAL_CMD, POLY_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_P1),'*', MODUL_CMD, MODUL_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_P2),'*', MODUL_CMD, POLY_CMD, MODUL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_ID), '*', IDEAL_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_P1),'*', MODUL_CMD, IDEAL_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_P2),'*', MODUL_CMD, VECTOR_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_ID), '*', MODUL_CMD, IDEAL_CMD, MODUL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_ID), '*', MODUL_CMD, MODUL_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_P1),'*', MATRIX_CMD, MATRIX_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_P2),'*', MATRIX_CMD, POLY_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_N1),'*', MATRIX_CMD, MATRIX_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_N2),'*', MATRIX_CMD, NUMBER_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_I1),'*', MATRIX_CMD, MATRIX_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_I2),'*', MATRIX_CMD, INT_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA), '*', MATRIX_CMD, MATRIX_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_BI1),'*', MATRIX_CMD, MATRIX_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_MA_BI2),'*', MATRIX_CMD, BIGINT_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_BIM), '*', BIGINTMAT_CMD, BIGINTMAT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_BIM_I), '*', BIGINTMAT_CMD, BIGINTMAT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_I_BIM), '*', BIGINTMAT_CMD, INT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_BIM_BI), '*', BIGINTMAT_CMD, BIGINTMAT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_BI_BIM), '*', BIGINTMAT_CMD, BIGINT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), '*', INTVEC_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_I_IV), '*', INTVEC_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), '*', INTMAT_CMD, INTMAT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_I_IV), '*', INTMAT_CMD, INT_CMD, INTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_IV), '*', INTVEC_CMD, INTMAT_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_IV), '*', INTMAT_CMD, INTMAT_CMD, INTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjTIMES_IV), '*', INTMAT_CMD, INTVEC_CMD, INTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjTIMES_BIM), '*', CMATRIX_CMD, CMATRIX_CMD, CMATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjDIV_N), '/', NUMBER_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjNUMBER2_OP2),'/', CNUMBER_CMD, CNUMBER_CMD,CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'/', CNUMBER_CMD, INT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'/', CNUMBER_CMD, CNUMBER_CMD,INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'/', CNUMBER_CMD, BIGINT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'/', CNUMBER_CMD, CNUMBER_CMD,BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjDIV_P), '/', POLY_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjDIV_P), '/', VECTOR_CMD, VECTOR_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjDIV_Ma), '/', MATRIX_CMD, MATRIX_CMD, POLY_CMD, ALLOW_PLURAL | NO_RING} ,{D(jjDIVMOD_I), '/', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjDIV_BI), '/', BIGINT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), '/', INTVEC_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), '/', INTMAT_CMD, INTMAT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjCRING_Zp), '/', CRING_CMD, CRING_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCRING_Zm), '/', CRING_CMD, CRING_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjDIVMOD_I), INTDIV_CMD, INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjDIV_BI), INTDIV_CMD, BIGINT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), INTDIV_CMD, INTVEC_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), INTDIV_CMD, INTMAT_CMD, INTMAT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjDIVMOD_I), '%', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMOD_BI), '%', BIGINT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), '%', INTVEC_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOP_IV_I), '%', INTMAT_CMD, INTMAT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMOD_N), '%', NUMBER_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjNUMBER2_OP2),'%', CNUMBER_CMD, CNUMBER_CMD,CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'%', CNUMBER_CMD, INT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'%', CNUMBER_CMD, CNUMBER_CMD,INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'%', CNUMBER_CMD, BIGINT_CMD, CNUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjNUMBER2_OP2),'%', CNUMBER_CMD, CNUMBER_CMD,BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjPOWER_I), '^', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPOWER_BI), '^', BIGINT_CMD, BIGINT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPOWER_N), '^', NUMBER_CMD, NUMBER_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjNUMBER2_OP2),'^', CNUMBER_CMD, CNUMBER_CMD,INT_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjPOWER_P), '^', POLY_CMD, POLY_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPOWER_ID), '^', IDEAL_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjLE_I), LE, INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjLE_BI), LE, INT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjLE_N), LE, INT_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_S), LE, INT_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV_I),LE, INT_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV),LE, INT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_P), LE, INT_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_P), LE, INT_CMD, VECTOR_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjLT_I), '<', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjLT_BI), '<', INT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjLT_N), '<', INT_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV_I),'<', INT_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV),'<', INT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_S), '<', INT_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_P), '<', INT_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_P), '<', INT_CMD, VECTOR_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjGE_I), GE, INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjGE_BI), GE, INT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjGE_N), GE, INT_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_S), GE, INT_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV_I),GE, INT_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV),GE, INT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_P), GE, INT_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_P), GE, INT_CMD, VECTOR_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjGT_I), '>', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjGT_BI), '>', INT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjGT_N), '>', INT_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_S), '>', INT_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV_I),'>', INT_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV),'>', INT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_P), '>', INT_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_P), '>', INT_CMD, VECTOR_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjAND_I), '&', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjOR_I), '|', INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjEQUAL_CR), EQUAL_EQUAL, INT_CMD, CRING_CMD, CRING_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjEQUAL_I), EQUAL_EQUAL, INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_BI), EQUAL_EQUAL, INT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_N), EQUAL_EQUAL, INT_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_S), EQUAL_EQUAL, INT_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_P), EQUAL_EQUAL, INT_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_P), EQUAL_EQUAL, INT_CMD, VECTOR_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV_I),EQUAL_EQUAL, INT_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV),EQUAL_EQUAL, INT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV),EQUAL_EQUAL, INT_CMD, INTMAT_CMD, INTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_BIM),EQUAL_EQUAL, INT_CMD, BIGINTMAT_CMD, BIGINTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjCOMPARE_BIM),EQUAL_EQUAL, INT_CMD, CMATRIX_CMD, CMATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} #endif ,{D(jjEQUAL_Ma), EQUAL_EQUAL, INT_CMD, MATRIX_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{ jjWRONG2 , EQUAL_EQUAL, 0, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{ jjWRONG2 , EQUAL_EQUAL, 0, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{ jjWRONG2 , EQUAL_EQUAL, 0, IDEAL_CMD, MODUL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{ jjWRONG2 , EQUAL_EQUAL, 0, MODUL_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_I), NOTEQUAL, INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_BI), NOTEQUAL, INT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_N), NOTEQUAL, INT_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_S), NOTEQUAL, INT_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_P), NOTEQUAL, INT_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_P), NOTEQUAL, INT_CMD, VECTOR_CMD, VECTOR_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV),NOTEQUAL, INT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOMPARE_IV),NOTEQUAL, INT_CMD, INTMAT_CMD, INTMAT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjEQUAL_Ma), NOTEQUAL, INT_CMD, MATRIX_CMD, MATRIX_CMD, ALLOW_PLURAL | ALLOW_RING} ,{ jjWRONG2 , NOTEQUAL, 0, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{ jjWRONG2 , NOTEQUAL, 0, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{ jjWRONG2 , NOTEQUAL, 0, IDEAL_CMD, MODUL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{ jjWRONG2 , NOTEQUAL, 0, MODUL_CMD, IDEAL_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjDOTDOT), DOTDOT, INTVEC_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_I), '[', INT_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_IV), '[', INT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_I), '[', POLY_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_I), '[', POLY_CMD, MAP_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_IV), '[', POLY_CMD, IDEAL_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_I), '[', VECTOR_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_IV), '[', VECTOR_CMD, MODUL_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_I), '[', STRING_CMD, STRING_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_IV), '[', STRING_CMD, STRING_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_I), '[', ANY_TYPE/*set by p*/,LIST_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_IV), '[', ANY_TYPE/*set by p*/,LIST_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_P), '[', POLY_CMD, POLY_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_P_IV),'[', POLY_CMD, POLY_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_V), '[', POLY_CMD, VECTOR_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjINDEX_V_IV),'[', VECTOR_CMD, VECTOR_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjPROC), '(', ANY_TYPE/*set by p*/,PROC_CMD, DEF_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjMAP), '(', ANY_TYPE/*set by p*/,MAP_CMD, DEF_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjLOAD2), '(', NONE, LIB_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjKLAMMER), '(', ANY_TYPE/*set by p*/,ANY_TYPE, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjKLAMMER_IV),'(', ANY_TYPE/*set by p*/,ANY_TYPE, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjCOLON), ':', INTVEC_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} // and the procedures with 2 arguments: ,{D(jjALIGN_V), ALIGN_CMD, VECTOR_CMD, VECTOR_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjALIGN_M), ALIGN_CMD, MODUL_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(atATTRIB2), ATTRIB_CMD, NONE/*set by p*/,DEF_CMD, STRING_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjBETTI2), BETTI_CMD, INTMAT_CMD, LIST_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(syBetti2), BETTI_CMD, INTMAT_CMD, RESOLUTION_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjBETTI2_ID), BETTI_CMD, INTMAT_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} ,{D(jjBETTI2_ID), BETTI_CMD, INTMAT_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING} #ifdef HAVE_PLURAL ,{D(jjBRACKET), BRACKET_CMD, POLY_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL | NO_RING} #endif ,{D(jjCHINREM_BI),CHINREM_CMD, BIGINT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} //,{D(jjCHINREM_P), CHINREM_CMD, POLY_CMD, LIST_CMD, INTVEC_CMD, ALLOW_PLURAL} ,{D(jjCHINREM_ID),CHINREM_CMD, ANY_TYPE/*set by p*/,LIST_CMD,INTVEC_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjCHINREM_ID),CHINREM_CMD, ANY_TYPE/*set by p*/,LIST_CMD,LIST_CMD, ALLOW_PLURAL |NO_RING} #ifdef SINGULAR_4_1 ,{D(jjNUMBER2CR), CNUMBER_CMD, CNUMBER_CMD, INT_CMD, CRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjNUMBER2CR), CNUMBER_CMD, CNUMBER_CMD, BIGINT_CMD, CRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjNUMBER2CR), CNUMBER_CMD, CNUMBER_CMD, NUMBER_CMD, CRING_CMD, ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjCOEF), COEF_CMD, MATRIX_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEFFS_Id), COEFFS_CMD, MATRIX_CMD, IDEAL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEFFS_Id), COEFFS_CMD, MATRIX_CMD, MODUL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEFFS2_KB),COEFFS_CMD, MATRIX_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEFFS2_KB),COEFFS_CMD, MATRIX_CMD, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCONTRACT), CONTRACT_CMD, MATRIX_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDEG_IV), DEG_CMD, INT_CMD, POLY_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDEG_IV), DEG_CMD, INT_CMD, VECTOR_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDEG_M_IV), DEG_CMD, INT_CMD, MATRIX_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(lDelete), DELETE_CMD, LIST_CMD, LIST_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIFF_P), DIFF_CMD, POLY_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIFF_P), DIFF_CMD, VECTOR_CMD, VECTOR_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIFF_ID), DIFF_CMD, IDEAL_CMD, IDEAL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIFF_ID_ID),DIFF_CMD, MATRIX_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIFF_ID), DIFF_CMD, MODUL_CMD, MODUL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIFF_ID), DIFF_CMD, MATRIX_CMD, MATRIX_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIFF_COEF), DIFF_CMD, NUMBER_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIM2), DIM_CMD, INT_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjDIM2), DIM_CMD, INT_CMD, MODUL_CMD, IDEAL_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjDIVISION), DIVISION_CMD, LIST_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIVISION), DIVISION_CMD, LIST_CMD, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjELIMIN), ELIMINATION_CMD,IDEAL_CMD, IDEAL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjELIMIN), ELIMINATION_CMD,MODUL_CMD, MODUL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjELIMIN_IV), ELIMINATION_CMD,IDEAL_CMD, IDEAL_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjELIMIN_IV), ELIMINATION_CMD,MODUL_CMD, MODUL_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjEXPORTTO), EXPORTTO_CMD, NONE, PACKAGE_CMD, IDHDL, ALLOW_PLURAL |ALLOW_RING} ,{D(jjEXTGCD_I), EXTGCD_CMD, LIST_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjEXTGCD_BI), EXTGCD_CMD, LIST_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjEXTGCD_P), EXTGCD_CMD, LIST_CMD, POLY_CMD, POLY_CMD, NO_PLURAL |NO_RING} ,{D(jjFAC_P2), FAC_CMD, IDEAL_CMD, POLY_CMD, INT_CMD, NO_PLURAL |NO_RING} ,{D(jjFACSTD2), FACSTD_CMD, LIST_CMD, IDEAL_CMD, IDEAL_CMD, NO_PLURAL |NO_RING} ,{D(jjFAREY_BI), FAREY_CMD, NUMBER_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjFAREY_ID), FAREY_CMD, ANY_TYPE/*set by p*/,IDEAL_CMD,BIGINT_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjFAREY_ID), FAREY_CMD, ANY_TYPE/*set by p*/,MODUL_CMD,BIGINT_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjFAREY_ID), FAREY_CMD, ANY_TYPE/*set by p*/,MATRIX_CMD,BIGINT_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjFETCH), FETCH_CMD, ANY_TYPE/*set by p*/,RING_CMD, ANY_TYPE, ALLOW_PLURAL |ALLOW_RING} ,{D(fglmProc), FGLM_CMD, IDEAL_CMD, RING_CMD, DEF_CMD, NO_PLURAL |NO_RING} ,{D(fglmQuotProc),FGLMQUOT_CMD, IDEAL_CMD, IDEAL_CMD, POLY_CMD, NO_PLURAL |NO_RING} ,{D(jjFIND2), FIND_CMD, INT_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjFWALK), FWALK_CMD, IDEAL_CMD, RING_CMD, DEF_CMD, NO_PLURAL |NO_RING} ,{D(jjGCD_I), GCD_CMD, INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjGCD_N), GCD_CMD, NUMBER_CMD, NUMBER_CMD, NUMBER_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjGCD_BI), GCD_CMD, BIGINT_CMD, BIGINT_CMD, BIGINT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjGCD_P), GCD_CMD, POLY_CMD, POLY_CMD, POLY_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjHILBERT2), HILBERT_CMD, INTVEC_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING | NO_ZERODIVISOR} ,{D(jjHILBERT2), HILBERT_CMD, INTVEC_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL | ALLOW_RING | NO_ZERODIVISOR} ,{D(jjHOMOG1_W), HOMOG_CMD, INT_CMD, IDEAL_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjHOMOG1_W), HOMOG_CMD, INT_CMD, MODUL_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjHOMOG_P), HOMOG_CMD, POLY_CMD, POLY_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjHOMOG_P), HOMOG_CMD, VECTOR_CMD, VECTOR_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjHOMOG_ID), HOMOG_CMD, IDEAL_CMD, IDEAL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjHOMOG_ID), HOMOG_CMD, MODUL_CMD, MODUL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRES), HRES_CMD, RESOLUTION_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |NO_RING} ,{D(jjFETCH), IMAP_CMD, ANY_TYPE/*set by p*/,RING_CMD, ANY_TYPE, ALLOW_PLURAL |ALLOW_RING} ,{D(jjIMPORTFROM),IMPORTFROM_CMD, NONE, PACKAGE_CMD, ANY_TYPE, ALLOW_PLURAL |ALLOW_RING} ,{D(jjINDEPSET2), INDEPSET_CMD, LIST_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |NO_RING} ,{D(lInsert), INSERT_CMD, LIST_CMD, LIST_CMD, DEF_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjINTERPOLATION),INTERPOLATE_CMD,IDEAL_CMD, LIST_CMD, INTVEC_CMD, NO_PLURAL |NO_RING} ,{D(jjINTERSECT), INTERSECT_CMD, IDEAL_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjINTERSECT), INTERSECT_CMD, MODUL_CMD, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJanetBasis2), JANET_CMD, IDEAL_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjJET_P), JET_CMD, POLY_CMD, POLY_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_ID), JET_CMD, IDEAL_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_P), JET_CMD, VECTOR_CMD, VECTOR_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_ID), JET_CMD, MODUL_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_ID), JET_CMD, MATRIX_CMD, MATRIX_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjKBASE2), KBASE_CMD, IDEAL_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING |WARN_RING} /*ring-cf: warning at top level*/ ,{D(jjKBASE2), KBASE_CMD, MODUL_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING |WARN_RING} /*ring-cf: warning at top level*/ ,{D(jjKERNEL), KERNEL_CMD, IDEAL_CMD, RING_CMD, ANY_TYPE, ALLOW_PLURAL |ALLOW_RING} ,{D(atKILLATTR2), KILLATTR_CMD, NONE, IDHDL, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjKoszul), KOSZUL_CMD, MATRIX_CMD, INT_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjKoszul_Id), KOSZUL_CMD, MATRIX_CMD, INT_CMD, IDEAL_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjRES), KRES_CMD, RESOLUTION_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |NO_RING} ,{D(jjLIFT), LIFT_CMD, MATRIX_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjLIFT), LIFT_CMD, MATRIX_CMD, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjLIFTSTD), LIFTSTD_CMD, IDEAL_CMD, IDEAL_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjLIFTSTD), LIFTSTD_CMD, MODUL_CMD, MODUL_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjLOAD_E), LOAD_CMD, NONE, STRING_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRES), LRES_CMD, RESOLUTION_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |NO_RING} ,{D(jjMODULO), MODULO_CMD, MODUL_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjMODULO), MODULO_CMD, MODUL_CMD, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjMONITOR2), MONITOR_CMD, NONE, LINK_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} //,{D(jjRES), MRES_CMD, LIST_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} //,{D(jjRES), MRES_CMD, LIST_CMD, MODUL_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} ,{D(nuMPResMat), MPRES_CMD, MODUL_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |NO_RING} ,{D(jjNEWSTRUCT2),NEWSTRUCT_CMD, NONE, STRING_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRES), MRES_CMD, RESOLUTION_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRES), MRES_CMD, RESOLUTION_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} //,{D(nuMPResMat), MPRES_CMD, MODUL_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjNUMBER2CR), CNUMBER_CMD, CNUMBER_CMD, INT_CMD, CRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjNUMBER2CR), CNUMBER_CMD, CNUMBER_CMD, BIGINT_CMD, CRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjNUMBER2CR), CNUMBER_CMD, CNUMBER_CMD, NUMBER_CMD, CRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjNUMBER2CR), CNUMBER_CMD, CNUMBER_CMD, CNUMBER_CMD,CRING_CMD, ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjPFAC2), PFAC_CMD, LIST_CMD, BIGINT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjPFAC2), PFAC_CMD, LIST_CMD, NUMBER_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} #ifdef HAVE_PLURAL ,{D(jjPlural_num_poly), NCALGEBRA_CMD,NONE, POLY_CMD, POLY_CMD , NO_PLURAL |NO_RING} ,{D(jjPlural_num_mat), NCALGEBRA_CMD,NONE, POLY_CMD, MATRIX_CMD, NO_PLURAL |NO_RING} ,{D(jjPlural_mat_poly), NCALGEBRA_CMD,NONE, MATRIX_CMD, POLY_CMD , NO_PLURAL |NO_RING} ,{D(jjPlural_mat_mat), NCALGEBRA_CMD,NONE, MATRIX_CMD, MATRIX_CMD, NO_PLURAL |NO_RING} ,{D(jjPlural_num_poly), NC_ALGEBRA_CMD,RING_CMD, POLY_CMD, POLY_CMD , NO_PLURAL |NO_RING} ,{D(jjPlural_num_mat), NC_ALGEBRA_CMD,RING_CMD, POLY_CMD, MATRIX_CMD, NO_PLURAL |NO_RING} ,{D(jjPlural_mat_poly), NC_ALGEBRA_CMD,RING_CMD, MATRIX_CMD, POLY_CMD , NO_PLURAL |NO_RING} ,{D(jjPlural_mat_mat), NC_ALGEBRA_CMD,RING_CMD, MATRIX_CMD, MATRIX_CMD, NO_PLURAL |NO_RING} ,{D(jjOPPOSE), OPPOSE_CMD, ANY_TYPE/*set by p*/, RING_CMD, DEF_CMD, ALLOW_PLURAL |NO_RING} #endif ,{D(jjPARSTR2), PARSTR_CMD, STRING_CMD, RING_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjPRINT_FORMAT), PRINT_CMD, STRING_CMD, DEF_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjQUOT), QUOTIENT_CMD, IDEAL_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjQUOT), QUOTIENT_CMD, MODUL_CMD, MODUL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjQUOT), QUOTIENT_CMD, IDEAL_CMD, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRANDOM), RANDOM_CMD, INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRANK2), RANK_CMD, INT_CMD, MATRIX_CMD, INT_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjREAD2), READ_CMD, STRING_CMD, LINK_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE_P), REDUCE_CMD, POLY_CMD, POLY_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE_P), REDUCE_CMD, VECTOR_CMD, VECTOR_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE_P), REDUCE_CMD, VECTOR_CMD, VECTOR_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE_ID), REDUCE_CMD, IDEAL_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE_ID), REDUCE_CMD, MODUL_CMD, MODUL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE_ID), REDUCE_CMD, MODUL_CMD, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRES), RES_CMD, RESOLUTION_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRES), RES_CMD, RESOLUTION_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSQR_FREE2), SQR_FREE_CMD, IDEAL_CMD, POLY_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjSTATUS2), STATUS_CMD, STRING_CMD, LINK_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTATUS2L), STATUS_CMD, INT_CMD, LIST_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSIMPL_P), SIMPLIFY_CMD, POLY_CMD, POLY_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSIMPL_P), SIMPLIFY_CMD, VECTOR_CMD, VECTOR_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSIMPL_ID), SIMPLIFY_CMD, IDEAL_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSIMPL_ID), SIMPLIFY_CMD, MODUL_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} //,{D(jjRES), SRES_CMD, LIST_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} //,{D(jjRES), SRES_CMD, LIST_CMD, MODUL_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjRES), SRES_CMD, RESOLUTION_CMD, IDEAL_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjRES), SRES_CMD, RESOLUTION_CMD, MODUL_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjSBA_1), SBA_CMD, IDEAL_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSBA_1), SBA_CMD, MODUL_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTD_1), STD_CMD, IDEAL_CMD, IDEAL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTD_1), STD_CMD, MODUL_CMD, MODUL_CMD, VECTOR_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTD_1), STD_CMD, IDEAL_CMD, IDEAL_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTD_1), STD_CMD, MODUL_CMD, MODUL_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTD_HILB), STD_CMD, IDEAL_CMD, IDEAL_CMD, INTVEC_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjSTD_HILB), STD_CMD, MODUL_CMD, MODUL_CMD, INTVEC_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjVARSTR2), VARSTR_CMD, STRING_CMD, RING_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjWAIT1ST2), WAIT1ST_CMD, INT_CMD, LIST_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjWAITALL2), WAITALL_CMD, INT_CMD, LIST_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjWEDGE), WEDGE_CMD, MATRIX_CMD, MATRIX_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} ,{NULL_VAL, 0, 0, 0, 0, NO_PLURAL |NO_RING} }; /*=================== operations with 3 args.: table =================*/ struct sValCmd3 dArith3[]= { // operations: // proc cmd res arg1 arg2 arg3 context {D(jjBRACK_S), '[', STRING_CMD, STRING_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Im), '[', INT_CMD, INTMAT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Bim), '[', BIGINT_CMD, BIGINTMAT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjBRACK_Bim), '[', CNUMBER_CMD, CMATRIX_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjBRACK_Ma_I_IV), '[', INT_CMD, INTMAT_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Ma_I_IV), '[', BIGINT_CMD, BIGINTMAT_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Ma_IV_I), '[', INT_CMD, INTMAT_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Ma_IV_I), '[', BIGINT_CMD, BIGINTMAT_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Ma_IV_IV), '[', INT_CMD, INTMAT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Ma_IV_IV), '[', BIGINT_CMD, BIGINTMAT_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Ma), '[', POLY_CMD, MATRIX_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Ma_I_IV), '[', POLY_CMD, MATRIX_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Ma_IV_I), '[', POLY_CMD, MATRIX_CMD, INTVEC_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBRACK_Ma_IV_IV), '[', POLY_CMD, MATRIX_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjPROC3), '(', ANY_TYPE, PROC_CMD, DEF_CMD, DEF_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(atATTRIB3), ATTRIB_CMD, NONE, IDHDL, STRING_CMD, DEF_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjBAREISS3), BAREISS_CMD,LIST_CMD, MODUL_CMD, INT_CMD, INT_CMD, NO_PLURAL |ALLOW_RING|NO_ZERODIVISOR} ,{D(jjCOEFFS3_P), COEFFS_CMD, MATRIX_CMD, POLY_CMD, POLY_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEFFS3_P), COEFFS_CMD, MATRIX_CMD, VECTOR_CMD, POLY_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEFFS3_Id), COEFFS_CMD, MATRIX_CMD, IDEAL_CMD, POLY_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEFFS3_Id), COEFFS_CMD, MATRIX_CMD, MODUL_CMD, POLY_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEFFS3_KB), COEFFS_CMD, MATRIX_CMD, IDEAL_CMD, IDEAL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEFFS3_KB), COEFFS_CMD, MATRIX_CMD, MODUL_CMD, MODUL_CMD, POLY_CMD, ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjCMATRIX_3), CMATRIX_CMD, CMATRIX_CMD,INT_CMD, INT_CMD, CRING_CMD, ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjELIMIN_HILB), ELIMINATION_CMD,IDEAL_CMD, IDEAL_CMD, POLY_CMD, INTVEC_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjELIMIN_HILB), ELIMINATION_CMD,MODUL_CMD, MODUL_CMD, POLY_CMD, INTVEC_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjFIND3), FIND_CMD, INT_CMD, STRING_CMD, STRING_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjFWALK3), FWALK_CMD, IDEAL_CMD, RING_CMD, DEF_CMD, INT_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjHILBERT3), HILBERT_CMD,INTVEC_CMD, IDEAL_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING | NO_ZERODIVISOR} ,{D(jjHILBERT3), HILBERT_CMD,INTVEC_CMD, MODUL_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL | ALLOW_RING | NO_ZERODIVISOR} ,{D(jjHOMOG_P_W), HOMOG_CMD, POLY_CMD, POLY_CMD, POLY_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjHOMOG_P_W), HOMOG_CMD, VECTOR_CMD, VECTOR_CMD, POLY_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjHOMOG_ID_W), HOMOG_CMD, IDEAL_CMD, IDEAL_CMD, POLY_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjHOMOG_ID_W), HOMOG_CMD, MODUL_CMD, MODUL_CMD, POLY_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(lInsert3), INSERT_CMD, LIST_CMD, LIST_CMD, DEF_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjINTMAT3), INTMAT_CMD, INTMAT_CMD, INTMAT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_P_IV), JET_CMD, POLY_CMD, POLY_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_ID_IV), JET_CMD, IDEAL_CMD, IDEAL_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_P_IV), JET_CMD, VECTOR_CMD, VECTOR_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_ID_IV), JET_CMD, MODUL_CMD, MODUL_CMD, INT_CMD, INTVEC_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_P_P), JET_CMD, POLY_CMD, POLY_CMD, POLY_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_P_P), JET_CMD, VECTOR_CMD, VECTOR_CMD, POLY_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_ID_M), JET_CMD, IDEAL_CMD, IDEAL_CMD, MATRIX_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET_ID_M), JET_CMD, MODUL_CMD, MODUL_CMD, MATRIX_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{ jjWRONG3 , JET_CMD, POLY_CMD, POLY_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(mpKoszul), KOSZUL_CMD, MATRIX_CMD, INT_CMD, INT_CMD, IDEAL_CMD, NO_PLURAL |NO_RING} ,{D(jjLIFT3), LIFT_CMD, MATRIX_CMD, IDEAL_CMD, IDEAL_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjLIFT3), LIFT_CMD, MATRIX_CMD, MODUL_CMD, MODUL_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjLIFTSTD3), LIFTSTD_CMD,IDEAL_CMD, IDEAL_CMD, MATRIX_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjLIFTSTD3), LIFTSTD_CMD,MODUL_CMD, MODUL_CMD, MATRIX_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjMATRIX_Id), MATRIX_CMD, MATRIX_CMD, IDEAL_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjMATRIX_Mo), MATRIX_CMD, MATRIX_CMD, MODUL_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjMATRIX_Ma), MATRIX_CMD, MATRIX_CMD, MATRIX_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} #ifdef OLD_RES ,{D(jjRES3), MRES_CMD, NONE, IDEAL_CMD, INT_CMD, ANY_TYPE, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRES3), MRES_CMD, NONE, MODUL_CMD, INT_CMD, ANY_TYPE, ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjNEWSTRUCT3), NEWSTRUCT_CMD, NONE, STRING_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjPREIMAGE), PREIMAGE_CMD, IDEAL_CMD, RING_CMD, ANY_TYPE, ANY_TYPE, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRANDOM_Im), RANDOM_CMD, INTMAT_CMD, INT_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjRANDOM_CF), RANDOM_CMD, CNUMBER_CMD, CNUMBER_CMD, CNUMBER_CMD, CRING_CMD, ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjREDUCE3_P), REDUCE_CMD, POLY_CMD, POLY_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE3_P), REDUCE_CMD, VECTOR_CMD, VECTOR_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE3_P), REDUCE_CMD, VECTOR_CMD, VECTOR_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE3_ID), REDUCE_CMD, IDEAL_CMD, IDEAL_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE3_ID), REDUCE_CMD, MODUL_CMD, MODUL_CMD, MODUL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE3_ID), REDUCE_CMD, MODUL_CMD, MODUL_CMD, IDEAL_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE3_CP), REDUCE_CMD, POLY_CMD, POLY_CMD, POLY_CMD, IDEAL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE3_CP), REDUCE_CMD, VECTOR_CMD, VECTOR_CMD, POLY_CMD, MODUL_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE3_CID), REDUCE_CMD, IDEAL_CMD, IDEAL_CMD, IDEAL_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE3_CID), REDUCE_CMD, MODUL_CMD, MODUL_CMD, MODUL_CMD, MATRIX_CMD, ALLOW_PLURAL |ALLOW_RING} #ifdef OLD_RES ,{D(jjRES3), RES_CMD, NONE, IDEAL_CMD, INT_CMD, ANY_TYPE, ALLOW_PLURAL |ALLOW_RING} ,{D(jjRES3), RES_CMD, NONE, MODUL_CMD, INT_CMD, ANY_TYPE, ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjRESULTANT), RESULTANT_CMD, POLY_CMD,POLY_CMD, POLY_CMD, POLY_CMD, NO_PLURAL |ALLOW_RING} ,{D(jjRING3), RING_CMD, RING_CMD, DEF_CMD, DEF_CMD, DEF_CMD, ALLOW_PLURAL |ALLOW_RING} #ifdef OLD_RES ,{D(jjRES3), SRES_CMD, NONE, IDEAL_CMD, INT_CMD, ANY_TYPE, NO_PLURAL |ALLOW_RING} ,{D(jjRES3), SRES_CMD, NONE, MODUL_CMD, INT_CMD, ANY_TYPE, NO_PLURAL |ALLOW_RING} #endif ,{D(jjSBA_2), SBA_CMD, IDEAL_CMD, IDEAL_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSBA_2), SBA_CMD, MODUL_CMD, MODUL_CMD, INT_CMD, INT_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTATUS3), STATUS_CMD, INT_CMD, LINK_CMD, STRING_CMD, STRING_CMD, ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTD_HILB_W), STD_CMD, IDEAL_CMD, IDEAL_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjSTD_HILB_W), STD_CMD, MODUL_CMD, MODUL_CMD, INTVEC_CMD, INTVEC_CMD, ALLOW_PLURAL |NO_RING} ,{D(jjSUBST_P), SUBST_CMD, POLY_CMD, POLY_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSUBST_P), SUBST_CMD, POLY_CMD, POLY_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSUBST_P), SUBST_CMD, VECTOR_CMD, VECTOR_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSUBST_Id), SUBST_CMD, IDEAL_CMD, IDEAL_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSUBST_Id), SUBST_CMD, MODUL_CMD, MODUL_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSUBST_Id), SUBST_CMD, MATRIX_CMD, MATRIX_CMD, POLY_CMD, POLY_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSUBST_Id_I), SUBST_CMD, MATRIX_CMD, MATRIX_CMD, POLY_CMD, INT_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSUBST_Id_N), SUBST_CMD, MATRIX_CMD, MATRIX_CMD, POLY_CMD, NUMBER_CMD , ALLOW_PLURAL |ALLOW_RING} ,{D(nuLagSolve), LAGSOLVE_CMD,LIST_CMD, POLY_CMD, INT_CMD, INT_CMD , NO_PLURAL |NO_RING} ,{D(nuVanderSys), VANDER_CMD, POLY_CMD, IDEAL_CMD, IDEAL_CMD, INT_CMD , NO_PLURAL |NO_RING} ,{NULL_VAL, 0, 0, 0, 0, 0 , NO_PLURAL |NO_RING} }; /*=================== operations with many arg.: table =================*/ /* number_of_args: -1: any), -2: any >0, .. */ struct sValCmdM dArithM[]= { // operations: // proc cmd res number_of_args context {D(jjKLAMMER_PL), '(', ANY_TYPE, -2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjBREAK0), BREAKPOINT_CMD, NONE, 0 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjBREAK1), BREAKPOINT_CMD, NONE, -2 , ALLOW_PLURAL |ALLOW_RING} ,{D(iiBranchTo), BRANCHTO_CMD, NONE, -2 , ALLOW_PLURAL |ALLOW_RING} #ifdef SINGULAR_4_1 ,{D(jjCALL3ARG), CMATRIX_CMD, CMATRIX_CMD, 3 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL2ARG), CNUMBER_CMD, CNUMBER_CMD, 2 , ALLOW_PLURAL |ALLOW_RING} #endif ,{D(jjCALL2ARG), COEF_CMD, MATRIX_CMD, 2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCOEF_M), COEF_CMD, NONE, 4 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL2ARG), DIVISION_CMD, ANY_TYPE/*or set by p*/,2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjDIVISION4), DIVISION_CMD, ANY_TYPE/*or set by p*/,3 , NO_PLURAL |NO_RING} ,{D(jjDIVISION4), DIVISION_CMD, ANY_TYPE/*or set by p*/,4 , NO_PLURAL |NO_RING} ,{D(jjDBPRINT), DBPRINT_CMD, NONE, -2 , ALLOW_PLURAL |ALLOW_RING} //,{D(jjEXPORTTO_M), EXPORTTO_CMD, NONE, -2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL2ARG), FETCH_CMD, ANY_TYPE/*or set by p*/,2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjFETCH_M), FETCH_CMD, ANY_TYPE/*or set by p*/,3 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjFETCH_M), FETCH_CMD, ANY_TYPE/*or set by p*/,4 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL1ARG), IDEAL_CMD, IDEAL_CMD, 1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIDEAL_PL), IDEAL_CMD, IDEAL_CMD, -1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL2ARG), INTERSECT_CMD, IDEAL_CMD, 2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjINTERSECT_PL),INTERSECT_CMD, IDEAL_CMD, -2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL1ARG), INTVEC_CMD, INTVEC_CMD, 1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjINTVEC_PL), INTVEC_CMD, INTVEC_CMD, -2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL2ARG), JET_CMD, POLY_CMD,/*or set by p*/ 2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL3ARG), JET_CMD, POLY_CMD,/*or set by p*/ 3 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjJET4), JET_CMD, POLY_CMD,/*or set by p*/ 4 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL1ARG), LIB_CMD, NONE, 1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLIST_PL), LIST_CMD, LIST_CMD, -1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjLU_INVERSE),LUI_CMD, LIST_CMD, -2 , NO_PLURAL |NO_RING} ,{D(jjLU_SOLVE), LUS_CMD, LIST_CMD, -2 , NO_PLURAL |NO_RING} ,{ jjWRONG , MINOR_CMD, NONE, 1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjMINOR_M), MINOR_CMD, IDEAL_CMD, -2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL1ARG), MODUL_CMD, MODUL_CMD, 1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjIDEAL_PL), MODUL_CMD, MODUL_CMD, -1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL1ARG), NAMES_CMD, LIST_CMD, 1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjNAMES0), NAMES_CMD, LIST_CMD, 0 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL2ARG), CNUMBER_CMD, CNUMBER_CMD, 2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjOPTION_PL), OPTION_CMD, STRING_CMD/*or set by p*/,-1, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL2ARG), REDUCE_CMD, IDEAL_CMD/*or set by p*/, 2, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL3ARG), REDUCE_CMD, IDEAL_CMD/*or set by p*/, 3, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE4), REDUCE_CMD, IDEAL_CMD/*or set by p*/, 4, ALLOW_PLURAL |ALLOW_RING} ,{D(jjREDUCE5), REDUCE_CMD, IDEAL_CMD/*or set by p*/, 5, ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL1ARG), RESERVEDNAME_CMD, INT_CMD, 1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjRESERVED0), RESERVEDNAME_CMD, NONE, 0 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTRING_PL), STRING_CMD, STRING_CMD, -1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL3ARG), SUBST_CMD, NONE/*set by p*/, 3 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSUBST_M), SUBST_CMD, NONE/*set by p*/, -2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSYSTEM), SYSTEM_CMD, NONE/*or set by p*/,-2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjTEST), TEST_CMD, NONE, -2 , ALLOW_PLURAL |ALLOW_RING} ,{D(iiWRITE), WRITE_CMD, NONE, -2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL2ARG), STATUS_CMD, STRING_CMD, 2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL3ARG), STATUS_CMD, INT_CMD, 3 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjSTATUS_M), STATUS_CMD, INT_CMD, 4 , ALLOW_PLURAL |ALLOW_RING} ,{D(loSimplex), SIMPLEX_CMD, LIST_CMD, 6 , NO_PLURAL |NO_RING} ,{D(nuUResSolve), URSOLVE_CMD, LIST_CMD, 4 , NO_PLURAL |NO_RING} ,{D(jjCALL1ARG), STD_CMD, IDEAL_CMD, 1 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL2ARG), STD_CMD, IDEAL_CMD, 2 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjCALL3ARG), STD_CMD, IDEAL_CMD, 3 , NO_PLURAL |ALLOW_RING} ,{D(jjSTD_HILB_WP), STD_CMD, IDEAL_CMD, 4 , NO_PLURAL |NO_RING} ,{D(jjQRDS), QRDS_CMD, LIST_CMD, 4 , ALLOW_PLURAL |ALLOW_RING} ,{D(jjFactModD_M),FMD_CMD, LIST_CMD, -2 , NO_PLURAL |NO_RING} ,{NULL_VAL, 0, 0, 0 , NO_PLURAL |NO_RING} }; #ifdef GENTABLE // this table MUST be order alphabetically by its first entry: cmdnames cmds[] = // alias: 0: real name, 1: this is an alias, 2: this is an outdated alias { // name-string alias tokval toktype { "$INVALID$", 0, -1, 0}, { "ASSUME", 0, ASSUME_CMD, ASSUME_CMD}, { "LIB", 0, LIB_CMD , SYSVAR}, { "alias", 0, ALIAS_CMD , PARAMETER}, { "align", 0, ALIGN_CMD , CMD_2}, { "and", 0, '&' , LOGIC_OP}, { "apply", 0, APPLY, APPLY}, { "attrib", 0, ATTRIB_CMD , CMD_123}, { "bareiss", 0, BAREISS_CMD , CMD_13}, { "betti", 0, BETTI_CMD , CMD_12}, { "bigint", 0, BIGINT_CMD , ROOT_DECL}, { "bigintmat", 0, BIGINTMAT_CMD , BIGINTMAT_CMD}, { "branchTo", 0, BRANCHTO_CMD , CMD_M}, #ifdef HAVE_PLURAL { "bracket", 0, BRACKET_CMD , CMD_2}, #endif { "break", 0, BREAK_CMD , BREAK_CMD}, { "breakpoint", 0, BREAKPOINT_CMD , CMD_M}, { "char", 0, CHARACTERISTIC_CMD ,CMD_1}, { "char_series", 0, CHAR_SERIES_CMD , CMD_1}, { "charstr", 0, CHARSTR_CMD , CMD_1}, { "chinrem", 0, CHINREM_CMD , CMD_2}, { "cleardenom", 0, CONTENT_CMD , CMD_1}, { "close", 0, CLOSE_CMD , CMD_1}, #ifdef SINGULAR_4_1 { "cmatrix", 0, CMATRIX_CMD , ROOT_DECL_LIST}, { "cnumber", 0, CNUMBER_CMD , ROOT_DECL_LIST}, #endif { "coef", 0, COEF_CMD , CMD_M}, { "coeffs", 0, COEFFS_CMD , CMD_23}, { "continue", 0, CONTINUE_CMD , CONTINUE_CMD}, { "contract", 0, CONTRACT_CMD , CMD_2}, { "convhull", 0, NEWTONPOLY_CMD, CMD_1}, #ifdef SINGULAR_4_1 { "cring", 0, CRING_CMD, ROOT_DECL}, #endif { "dbprint", 0, DBPRINT_CMD , CMD_M}, { "def", 0, DEF_CMD , ROOT_DECL}, { "defined", 0, DEFINED_CMD , CMD_1}, { "deg", 0, DEG_CMD , CMD_12}, { "degree", 0, DEGREE_CMD , CMD_1}, { "delete", 0, DELETE_CMD , CMD_2}, { "denominator", 0, DENOMINATOR_CMD , CMD_1}, { "det", 0, DET_CMD , CMD_1}, { "diff", 0, DIFF_CMD , CMD_2}, { "dim", 0, DIM_CMD , CMD_12}, { "div", 0, INTDIV_CMD , MULDIV_OP}, { "division", 0, DIVISION_CMD , CMD_M}, { "dump", 0, DUMP_CMD, CMD_1}, { "extgcd", 0, EXTGCD_CMD , CMD_2}, { "ERROR", 0, ERROR_CMD , CMD_1}, { "eliminate", 0, ELIMINATION_CMD, CMD_23}, { "else", 0, ELSE_CMD , ELSE_CMD}, #ifdef HAVE_PLURAL { "envelope", 0, ENVELOPE_CMD , CMD_1}, #endif { "eval", 0, EVAL , EVAL}, { "example", 0, EXAMPLE_CMD , EXAMPLE_CMD}, { "execute", 0, EXECUTE_CMD , CMD_1}, { "export", 0, EXPORT_CMD , EXPORT_CMD}, { "exportto", 0, EXPORTTO_CMD , CMD_2}, { "facstd", 0, FACSTD_CMD , CMD_12}, { "factmodd", 0, FMD_CMD , CMD_M}, { "factorize", 0, FAC_CMD , CMD_12}, { "farey", 0, FAREY_CMD , CMD_2}, { "fetch", 0, FETCH_CMD , CMD_M}, { "fglm", 0, FGLM_CMD , CMD_2}, { "fglmquot", 0, FGLMQUOT_CMD, CMD_2}, { "find", 0, FIND_CMD , CMD_23}, { "finduni", 0, FINDUNI_CMD, CMD_1}, { "forif", 0, IF_CMD , IF_CMD}, { "freemodule", 0, FREEMODULE_CMD , CMD_1}, { "frwalk", 0, FWALK_CMD , CMD_23}, { "gen", 0, E_CMD , CMD_1}, { "getdump", 0, GETDUMP_CMD, CMD_1}, { "gcd", 0, GCD_CMD , CMD_2}, { "GCD", 2, GCD_CMD , CMD_2}, { "hilb", 0, HILBERT_CMD , CMD_123}, { "highcorner", 0, HIGHCORNER_CMD, CMD_1}, { "homog", 0, HOMOG_CMD , CMD_123}, { "hres", 0, HRES_CMD , CMD_2}, { "ideal", 0, IDEAL_CMD , RING_DECL_LIST}, { "if", 0, IF_CMD , IF_CMD}, { "imap", 0, IMAP_CMD , CMD_2}, { "impart", 0, IMPART_CMD , CMD_1}, { "importfrom", 0, IMPORTFROM_CMD , CMD_2}, { "indepSet", 0, INDEPSET_CMD , CMD_12}, { "insert", 0, INSERT_CMD , CMD_23}, { "int", 0, INT_CMD , ROOT_DECL}, { "interpolation",0,INTERPOLATE_CMD , CMD_2}, { "interred", 0, INTERRED_CMD , CMD_1}, { "intersect", 0, INTERSECT_CMD , CMD_M}, { "intmat", 0, INTMAT_CMD , INTMAT_CMD}, { "intvec", 0, INTVEC_CMD , ROOT_DECL_LIST}, { "jacob", 0, JACOB_CMD , CMD_1}, { "janet", 0, JANET_CMD , CMD_12}, { "jet", 0, JET_CMD , CMD_M}, { "kbase", 0, KBASE_CMD , CMD_12}, { "keepring", 0, KEEPRING_CMD , KEEPRING_CMD}, { "kernel", 0, KERNEL_CMD , CMD_2}, { "kill", 0, KILL_CMD , KILL_CMD}, { "killattrib", 0, KILLATTR_CMD , CMD_12}, { "koszul", 0, KOSZUL_CMD , CMD_23}, { "kres", 0, KRES_CMD , CMD_2}, { "laguerre", 0, LAGSOLVE_CMD, CMD_3}, { "lead", 0, LEAD_CMD , CMD_1}, { "leadcoef", 0, LEADCOEF_CMD , CMD_1}, { "leadexp", 0, LEADEXP_CMD , CMD_1}, { "leadmonom", 0, LEADMONOM_CMD , CMD_1}, { "lift", 0, LIFT_CMD , CMD_23}, { "liftstd", 0, LIFTSTD_CMD , CMD_23}, { "link", 0, LINK_CMD , ROOT_DECL}, { "listvar", 0, LISTVAR_CMD , LISTVAR_CMD}, { "list", 0, LIST_CMD , ROOT_DECL_LIST}, { "load", 0, LOAD_CMD , CMD_12}, { "lres", 0, LRES_CMD , CMD_2}, { "ludecomp", 0, LU_CMD , CMD_1}, { "luinverse", 0, LUI_CMD , CMD_M}, { "lusolve", 0, LUS_CMD , CMD_M}, { "map", 0, MAP_CMD , RING_DECL}, { "matrix", 0, MATRIX_CMD , MATRIX_CMD}, { "maxideal", 0, MAXID_CMD , CMD_1}, { "memory", 0, MEMORY_CMD , CMD_1}, { "minbase", 0, MINBASE_CMD , CMD_1}, { "minor", 0, MINOR_CMD , CMD_M}, { "minres", 0, MINRES_CMD , CMD_1}, { "mod", 0, '%' , MULDIV_OP}, { "module", 0, MODUL_CMD , RING_DECL_LIST}, { "modulo", 0, MODULO_CMD , CMD_2}, { "monitor", 0, MONITOR_CMD , CMD_12}, { "monomial", 0, MONOM_CMD , CMD_1}, { "mpresmat", 0, MPRES_CMD, CMD_2}, { "mult", 0, MULTIPLICITY_CMD , CMD_1}, #ifdef OLD_RES { "mres", 0, MRES_CMD , CMD_23}, #else { "mres", 0, MRES_CMD , CMD_2}, #endif { "mstd", 0, MSTD_CMD , CMD_1}, { "nameof", 0, NAMEOF_CMD , CMD_1}, { "names", 0, NAMES_CMD , CMD_M}, { "newstruct", 0, NEWSTRUCT_CMD , CMD_23}, #ifdef HAVE_PLURAL { "ncalgebra", 2, NCALGEBRA_CMD , CMD_2}, { "nc_algebra", 0, NC_ALGEBRA_CMD , CMD_2}, #endif { "ncols", 0, COLS_CMD , CMD_1}, { "not", 0, NOT , NOT}, { "npars", 0, NPARS_CMD , CMD_1}, #ifdef OLD_RES { "nres", 0, RES_CMD , CMD_23}, #else { "nres", 0, RES_CMD , CMD_2}, #endif { "nrows", 0, ROWS_CMD , CMD_1}, { "number", 0, NUMBER_CMD , RING_DECL}, { "numerator", 0, NUMERATOR_CMD , CMD_1}, { "nvars", 0, NVARS_CMD , CMD_1}, { "open", 0, OPEN_CMD , CMD_1}, #ifdef HAVE_PLURAL { "oppose", 0, OPPOSE_CMD , CMD_2}, { "opposite", 0, OPPOSITE_CMD , CMD_1}, #endif { "option", 0, OPTION_CMD , CMD_M}, { "or", 0, '|' , LOGIC_OP}, { "ord", 0, ORD_CMD , CMD_1}, { "ordstr", 0, ORDSTR_CMD , CMD_1}, { "package", 0, PACKAGE_CMD , ROOT_DECL}, { "par", 0, PAR_CMD , CMD_1}, { "parameter", 0, PARAMETER , PARAMETER}, { "pardeg", 0, PARDEG_CMD , CMD_1}, { "parstr", 0, PARSTR_CMD , CMD_12}, { "poly", 0, POLY_CMD , RING_DECL}, { "preimage", 0, PREIMAGE_CMD , CMD_13}, { "prime", 0, PRIME_CMD , CMD_1}, { "primefactors",0, PFAC_CMD , CMD_12}, { "print", 0, PRINT_CMD , CMD_12}, { "prune", 0, PRUNE_CMD , CMD_1}, { "proc", 0, PROC_CMD , PROC_CMD}, { "qhweight", 0, QHWEIGHT_CMD , CMD_1}, { "qrds", 0, QRDS_CMD , CMD_M}, { "qring", 0, QRING_CMD , ROOT_DECL}, { "quote", 0, QUOTE , QUOTE}, { "quotient", 0, QUOTIENT_CMD , CMD_2}, { "random", 0, RANDOM_CMD , CMD_23}, { "rank", 0, RANK_CMD , CMD_12}, { "read", 0, READ_CMD , CMD_12}, { "reduce", 0, REDUCE_CMD , CMD_M}, { "regularity", 0, REGULARITY_CMD , CMD_1}, { "repart", 0, REPART_CMD , CMD_1}, { "reservedName",0, RESERVEDNAME_CMD , CMD_M}, { "resolution", 0, RESOLUTION_CMD , RING_DECL}, { "resultant", 0, RESULTANT_CMD, CMD_3}, { "return", 0, RETURN , RETURN}, { "RETURN", 0, END_GRAMMAR , RETURN}, { "ring", 0, RING_CMD , RING_CMD}, { "ringlist", 0, RINGLIST_CMD , CMD_1}, #ifdef SINGULAR_4_1 { "ring_list", 0, RING_LIST_CMD , CMD_1}, #endif { "rvar", 0, IS_RINGVAR , CMD_1}, { "sba", 0, SBA_CMD , CMD_123}, { "setring", 0, SETRING_CMD , SETRING_CMD}, { "simplex", 0, SIMPLEX_CMD, CMD_M}, { "simplify", 0, SIMPLIFY_CMD , CMD_2}, { "size", 0, COUNT_CMD , CMD_1}, { "slimgb", 0, SLIM_GB_CMD , CMD_1}, { "sortvec", 0, SORTVEC_CMD , CMD_1}, { "sqrfree", 0, SQR_FREE_CMD , CMD_12}, #ifdef OLD_RES { "sres", 0, SRES_CMD , CMD_23}, #else /* OLD_RES */ { "sres", 0, SRES_CMD , CMD_2}, #endif /* OLD_RES */ { "status", 0, STATUS_CMD, CMD_M}, { "std", 0, STD_CMD , CMD_M}, { "string", 0, STRING_CMD , ROOT_DECL_LIST}, { "subst", 0, SUBST_CMD , CMD_M}, { "system", 0, SYSTEM_CMD, CMD_M}, { "syz", 0, SYZYGY_CMD , CMD_1}, { "test", 0, TEST_CMD , CMD_M}, { "trace", 0, TRACE_CMD , CMD_1}, { "transpose", 0, TRANSPOSE_CMD , CMD_1}, #ifdef HAVE_PLURAL { "twostd", 0, TWOSTD_CMD , CMD_1}, #endif /* HAVE_PLURAL */ { "type", 0, TYPE_CMD , TYPE_CMD}, { "typeof", 0, TYPEOF_CMD , CMD_1}, { "univariate", 0, UNIVARIATE_CMD, CMD_1}, { "uressolve", 0, URSOLVE_CMD, CMD_M}, { "vandermonde", 0, VANDER_CMD, CMD_3}, { "var", 0, VAR_CMD , CMD_1}, { "variables", 0, VARIABLES_CMD, CMD_1}, { "varstr", 0, VARSTR_CMD , CMD_12}, { "vdim", 0, VDIM_CMD , CMD_1}, { "vector", 0, VECTOR_CMD , RING_DECL}, { "waitfirst", 0, WAIT1ST_CMD , CMD_12}, { "waitall", 0, WAITALL_CMD , CMD_12}, { "wedge", 0, WEDGE_CMD , CMD_2}, { "weight", 0, WEIGHT_CMD , CMD_1}, { "whileif", 0, IF_CMD , IF_CMD}, { "write", 0, WRITE_CMD , CMD_M}, /* delete for next version:*/ { "IN", 1, LEAD_CMD , CMD_1}, { "NF", 1, REDUCE_CMD , CMD_M}, { "multiplicity",1, MULTIPLICITY_CMD , CMD_1}, { "verbose", 2, OPTION_CMD , CMD_M}, // { "rank", 1, ROWS_CMD , CMD_1}, // { "Current", 0, -1 , SYSVAR}, // { "Top", 0, -1 , SYSVAR}, // { "Up", 0, -1 , SYSVAR}, /* set sys vars*/ { "degBound", 0, VMAXDEG , SYSVAR}, { "echo", 0, VECHO , SYSVAR}, { "minpoly", 0, VMINPOLY , SYSVAR}, { "multBound", 0, VMAXMULT , SYSVAR}, { "noether", 0, VNOETHER , SYSVAR}, { "pagewidth", 0, VCOLMAX , SYSVAR}, { "printlevel", 0, VPRINTLEVEL , SYSVAR}, { "short", 0, VSHORTOUT , SYSVAR}, { "timer", 0, VTIMER , SYSVAR}, { "rtimer", 0, VRTIMER, SYSVAR}, { "TRACE", 0, TRACE , SYSVAR}, { "voice", 0, VOICE , SYSVAR}, /* other reserved words:scanner.l */ { "pause", 2, -1 , 0}, { "while", 0, -1 , 0}, { "for", 0, -1 , 0}, { "help", 0, -1 , 0}, { "newline", 0, -1 , 0}, { "exit", 0, -1 , 0}, { "quit", 0, -1 , 0}, /* end of list marker */ { NULL, 0, 0, 0} }; #endif /* GENTABLE */ #endif #ifdef IPCONV struct sConvertTypes dConvertTypes[] = { // input type output type convert procedure // int -> bigint { INT_CMD, BIGINT_CMD, D(iiI2BI) , NULL_VAL }, // int -> number { INT_CMD, NUMBER_CMD, D(iiI2N) , NULL_VAL }, { BIGINT_CMD, NUMBER_CMD, D(iiBI2N) , NULL_VAL }, #ifdef SINGULAR_4_1 { INT_CMD, CNUMBER_CMD, D(iiI2NN) , NULL_VAL }, { BIGINT_CMD, CNUMBER_CMD, D(iiBI2NN) , NULL_VAL }, { CNUMBER_CMD, NUMBER_CMD, D(iiNN2N) , NULL_VAL }, { CNUMBER_CMD, POLY_CMD, D(iiNN2P) , NULL_VAL }, #endif // int -> poly { INT_CMD, POLY_CMD, D(iiI2P) , NULL_VAL }, { BIGINT_CMD, POLY_CMD, D(iiBI2P) , NULL_VAL }, // int -> vector { INT_CMD, VECTOR_CMD, D(iiI2V) , NULL_VAL }, { BIGINT_CMD, VECTOR_CMD, D(iiBI2V) , NULL_VAL }, // int -> ideal { INT_CMD, IDEAL_CMD, D(iiI2Id) , NULL_VAL }, { BIGINT_CMD, IDEAL_CMD, D(iiBI2Id) , NULL_VAL }, // int -> matrix { INT_CMD, MATRIX_CMD, D(iiI2Id) , NULL_VAL }, { BIGINT_CMD, MATRIX_CMD, D(iiBI2Id) , NULL_VAL }, // int -> intvec { INT_CMD, INTVEC_CMD, D(iiI2Iv) , NULL_VAL }, // intvec -> intmat { INTVEC_CMD, INTMAT_CMD, D(iiDummy), NULL_VAL }, // intvec -> matrix { INTVEC_CMD, MATRIX_CMD, D(iiIm2Ma) , NULL_VAL }, // intmat -> bigintmat { INTMAT_CMD, BIGINTMAT_CMD, D(iiIm2Bim) , NULL_VAL }, // intmat -> matrix { INTMAT_CMD, MATRIX_CMD, D(iiIm2Ma) , NULL_VAL }, // number -> poly { NUMBER_CMD, POLY_CMD, D(iiN2P) , NULL_VAL }, // number -> matrix { NUMBER_CMD, MATRIX_CMD, D(iiN2Ma) , NULL_VAL }, // number -> ideal // number -> vector // number -> module // poly -> number // poly -> ideal { POLY_CMD, IDEAL_CMD, D(iiP2Id) , NULL_VAL }, // poly -> vector { POLY_CMD, VECTOR_CMD, D(iiP2V) , NULL_VAL }, // poly -> matrix { POLY_CMD, MATRIX_CMD, D(iiP2Id) , NULL_VAL }, // vector -> module { VECTOR_CMD, MODUL_CMD, D(iiP2Id) , NULL_VAL }, // vector -> matrix { VECTOR_CMD, MATRIX_CMD, D(iiV2Ma) , NULL_VAL }, // ideal -> module { IDEAL_CMD, MODUL_CMD, D(iiMa2Mo) , NULL_VAL }, // ideal -> matrix { IDEAL_CMD, MATRIX_CMD, D(iiDummy) , NULL_VAL }, // module -> matrix { MODUL_CMD, MATRIX_CMD, D(iiMo2Ma) , NULL_VAL }, // matrix -> ideal // matrix -> module { MATRIX_CMD, MODUL_CMD, D(iiMa2Mo) , NULL_VAL }, // intvec // link { STRING_CMD, LINK_CMD, D(iiS2Link) , NULL_VAL }, // resolution -> list { RESOLUTION_CMD, LIST_CMD, NULL_VAL /*iiR2L*/ , D(iiR2L_l) }, // list -> resolution { LIST_CMD, RESOLUTION_CMD, D(iiL2R) , NULL_VAL}, // qring -> ring { QRING_CMD, RING_CMD, D(iiDummy), NULL_VAL}, // end of list { 0, 0, NULL_VAL , NULL_VAL } }; #else extern struct sConvertTypes dConvertTypes[]; #endif #ifdef IPASSIGN struct sValAssign dAssign[]= { // same res types must be grouped together // proc res arg {D(jiA_IDEAL), IDEAL_CMD, IDEAL_CMD } ,{D(jiA_IDEAL_M), IDEAL_CMD, MATRIX_CMD } ,{D(jiA_RESOLUTION),RESOLUTION_CMD,RESOLUTION_CMD } ,{D(jiA_INT), INT_CMD, INT_CMD } ,{D(jiA_1x1INTMAT), INT_CMD, INTMAT_CMD } ,{D(jiA_IDEAL), MATRIX_CMD, MATRIX_CMD } ,{D(jiA_MAP_ID), MAP_CMD, IDEAL_CMD } ,{D(jiA_MAP), MAP_CMD, MAP_CMD } ,{D(jiA_IDEAL), MODUL_CMD, MODUL_CMD } ,{D(jiA_MODUL_P), MODUL_CMD, POLY_CMD } ,{D(jiA_POLY), POLY_CMD, POLY_CMD } ,{D(jiA_1x1MATRIX),POLY_CMD, MATRIX_CMD } ,{D(jiA_RING), RING_CMD, RING_CMD } ,{D(jiA_QRING), QRING_CMD, IDEAL_CMD } ,{D(jiA_RING), QRING_CMD, QRING_CMD } ,{D(jiA_RING), QRING_CMD, RING_CMD } ,{D(jiA_STRING), STRING_CMD, STRING_CMD } ,{D(jiA_PROC), PROC_CMD, STRING_CMD } ,{D(jiA_PROC), PROC_CMD, PROC_CMD } ,{D(jiA_POLY), VECTOR_CMD, VECTOR_CMD } ,{D(jiA_INTVEC), INTVEC_CMD, INTVEC_CMD } ,{D(jiA_INTVEC), INTMAT_CMD, INTMAT_CMD } ,{D(jiA_BIGINTMAT),BIGINTMAT_CMD, BIGINTMAT_CMD} ,{D(jiA_BIGINTMAT),CMATRIX_CMD, CMATRIX_CMD} ,{D(jiA_NUMBER), NUMBER_CMD, NUMBER_CMD } #ifdef SINGULAR_4_1 ,{D(jiA_NUMBER2), CNUMBER_CMD, CNUMBER_CMD } #endif ,{D(jiA_BIGINT), BIGINT_CMD, BIGINT_CMD } ,{D(jiA_LIST_RES), LIST_CMD, RESOLUTION_CMD } ,{D(jiA_LIST), LIST_CMD, LIST_CMD } ,{D(jiA_LINK), LINK_CMD, STRING_CMD } ,{D(jiA_LINK), LINK_CMD, LINK_CMD } ,{D(jiA_PACKAGE), PACKAGE_CMD, PACKAGE_CMD } ,{D(jiA_DEF), DEF_CMD, DEF_CMD } #ifdef SINGULAR_4_1 ,{D(jiA_BIGINTMAT),CMATRIX_CMD, CMATRIX_CMD} ,{D(jiA_NUMBER2), CNUMBER_CMD, CNUMBER_CMD } ,{D(jiA_NUMBER2_I),CNUMBER_CMD, INT_CMD } ,{D(jiA_NUMBER2_N),CNUMBER_CMD, NUMBER_CMD } ,{D(jiA_CRING), CRING_CMD, CRING_CMD } #endif ,{NULL_VAL, 0, 0 } }; struct sValAssign_sys dAssign_sys[]= { // sysvars: {D(jjECHO), VECHO, INT_CMD } ,{D(jjPRINTLEVEL), VPRINTLEVEL, INT_CMD } ,{D(jjCOLMAX), VCOLMAX, INT_CMD } ,{D(jjTIMER), VTIMER, INT_CMD } #ifdef HAVE_GETTIMEOFDAY ,{D(jjRTIMER), VRTIMER, INT_CMD } #endif ,{D(jjMAXDEG), VMAXDEG, INT_CMD } ,{D(jjMAXMULT), VMAXMULT, INT_CMD } ,{D(jjTRACE), TRACE, INT_CMD } ,{D(jjSHORTOUT), VSHORTOUT, INT_CMD } ,{D(jjMINPOLY), VMINPOLY, NUMBER_CMD } ,{D(jjNOETHER), VNOETHER, POLY_CMD } ,{NULL_VAL, 0, 0 } }; #endif singular-4.0.3+ds/Singular/test.cc000066400000000000000000000220231266270727000170260ustar00rootroot00000000000000 #include #include #include #include // :( #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // HEADERS: #include #include #include #include #include #include #include #include #include #include /// #include // TODO: install polys/this! //+ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include // TODO: needs si_link// already moved to Singular/! // #include "CCRing.h" // Too old! #include #include #include #include #include #include #include #include ////////#include "F5cData.h" #include #include #include #include ////////#include #include #include // #include // Too old? #include #include #include #include #include #include // #include "lplist.h" // Too old! #include #include // #include // Too old? // #include // Too old? // #include // Too old? #include #include #include #include #include #include #include #include #include #include // #include // Too old? #include #include #include #include #include #include #include // #include // due to factory? :( // #include // :( // #include // uses tgb_internal // :( // #include // :( // headers in Singular/ #include //#include // moved to Singular #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void siInit(char *); int main( int, char *argv[] ) { assume( sizeof(long) == SIZEOF_LONG ); if( sizeof(long) != SIZEOF_LONG ) { WerrorS("Bad config.h: wrong size of long!"); return(1); } // init path names etc. // feInitResources(argv[0]); //??? siInit(argv[0]); // ? if( char *s = versionString() ) { PrintS(s); omFree(s); } StringSetS("ressources in use (as reported by feStringAppendResources(0):\n"); feStringAppendResources(0); StringAppendS("\n"); if( char * s = StringEndS() ) { PrintS(s); omFree(s); } // Libpolys tests: // construct the ring Z/32003[x,y,z] // the variable names char **n=(char**)omalloc(3*sizeof(char*)); n[0]=omStrDup("x"); n[1]=omStrDup("y"); n[2]=omStrDup("z2"); /* ring R=rDefault(32003,3,n); // make R the default ring: rChangeCurrRing(R); // create the polynomial 1 poly p1=pISet(1); // create tthe polynomial 2*x^3*z^2 poly p2=p_ISet(2,R); pSetExp(p2,1,3); pSetExp(p2,3,2); pSetm(p2); // print p1 + p2 pWrite(p1); printf(" + \n"); pWrite(p2); printf("\n"); // compute p1+p2 p1=p_Add_q(p1,p2,R); p2=NULL; pWrite(p1); // clean up: pDelete(&p1); rDelete(R); rChangeCurrRing(NULL); */ currentVoice=feInitStdin(NULL); int err=iiEStart(omStrDup("ring R = (0, a), x, dp; R; system(\"r\", R); minpoly=a*a+1; R; system(\"r\", R); kill R; return();\n"),NULL); printf("interpreter returns %d\n",err); if (err) errorreported = 0; // reset error handling assume( err == 0 ); // hook for error handling: // WerrorS_callback=......; of type p(const char *) err=iiEStart(omStrDup("int ver=system(\"version\");export ver;return();\n"),NULL); printf("interpreter returns %d\n",err); if (err) errorreported = 0; // reset error handling assume( err == 0 ); idhdl h=ggetid("ver"); if (h != NULL) printf("singular variable ver of type %d contains %d\n",h->typ,(int)(long)IDDATA(h)); else printf("variable ver does not exist\n"); assume( h != NULL ); err = iiEStart( omStrDup("system(\"--version\");return();\n"), NULL); printf("interpreter returns %d\n",err); if (err) errorreported = 0; // reset error handling assume( err == 0 ); // calling a singular-library function idhdl datetime=ggetid("datetime"); if (datetime==NULL) printf("datetime not found\n"); else { const BOOLEAN res=iiMake_proc(datetime,NULL,NULL); if (res) { printf("iiMake_proc: datetime return an error\n"); errorreported = 0; } else { printf("iiMake_proc: datetime returned type %d, >>%s<<\n", iiRETURNEXPR.Typ(), (char *)iiRETURNEXPR.Data()); iiRETURNEXPR.CleanUp(); // calls Init afterwards } } // changing a ring for the interpreter // re-using n and R from above ring R = rDefault(32003, 3, n); idhdl newRingHdl=enterid("R" /* ring name*/, 0, /*nesting level, 0=global*/ RING_CMD, &IDROOT, FALSE); IDRING(newRingHdl)=R; // make R the default ring (include rChangeCurrRing): rSetHdl(newRingHdl); err=iiEStart(omStrDup("R; system(\"r\", R); poly p=x; p; system(\"p\", p); \"\"; poly pp = p * p; pp; listvar(); return();\n"),NULL); // calling a kernel function via the interpreter interface sleftv r1; memset(&r1,0,sizeof(r1)); sleftv arg; memset(&arg,0,sizeof(r1)); arg.rtyp=STRING_CMD; arg.data=omStrDup("huhu"); err=iiExprArith1(&r1,&arg,TYPEOF_CMD); printf("interpreter returns %d\n",err); if (err) errorreported = 0; // reset error handling else printf("typeof returned type %d, >>%s<<\n",r1.Typ(),(char*)r1.Data()); // clean up r1: r1.CleanUp(); return 0; } singular-4.0.3+ds/Singular/tesths.cc000066400000000000000000000140351266270727000173650ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT - initialize SINGULARs components, run Script and start SHELL */ #include #include #include #include #include #include #include #include // #ifdef HAVE_FANS // #include // #include // #include // #include // #endif #include "ipshell.h" #include "cntrlc.h" #include "links/silink.h" #include "ipid.h" #include "sdb.h" #include "feOpt.h" #include "distrib.h" #include "mmalloc.h" #include "tok.h" #include "fegetopt.h" #include #include #include #include #include #include #include #include extern int siInit(char *); int mmInit( void ) { #if defined(OMALLOC_USES_MALLOC) || defined(X_OMALLOC) /* in mmstd.c, for some architectures freeSize() unconditionally uses the *system* free() */ /* sage ticket 5344: http://trac.sagemath.org/sage_trac/ticket/5344 */ /* do not rely on the default in Singular as libsingular may be different */ mp_set_memory_functions(omMallocFunc,omReallocSizeFunc,omFreeSizeFunc); #else mp_set_memory_functions(malloc,reallocSize,freeSize); #endif return 1; } /*0 implementation*/ int main( /* main entry to Singular */ int argc, /* number of parameter */ char** argv) /* parameter array */ { mmInit(); // Don't worry: ifdef OM_NDEBUG, then all these calls are undef'ed omInitRet_2_Info(argv[0]); omInitGetBackTrace(); siInit(argv[0]); init_signals(); // parse command line options int optc, option_index; const char* errormsg; while((optc = fe_getopt_long(argc, argv, SHORT_OPTS_STRING, feOptSpec, &option_index)) != EOF) { if (optc == '?' || optc == 0) { fprintf(stderr, "Use '%s --help' for a complete list of options\n", feArgv0); exit(1); } if (optc != LONG_OPTION_RETURN) option_index = feGetOptIndex(optc); assume(option_index >= 0 && option_index < (int) FE_OPT_UNDEF); if (fe_optarg == NULL && (feOptSpec[option_index].type == feOptBool || feOptSpec[option_index].has_arg == optional_argument)) errormsg = feSetOptValue((feOptIndex) option_index, (int) 1); else errormsg = feSetOptValue((feOptIndex) option_index, fe_optarg); if (errormsg) { if (fe_optarg == NULL) fprintf(stderr, "Error: Option '--%s' %s\n", feOptSpec[option_index].name, errormsg); else fprintf(stderr, "Error: Option '--%s=%s' %s\n", feOptSpec[option_index].name, fe_optarg, errormsg); fprintf(stderr, "Use '%s --help' for a complete list of options\n", feArgv0); exit(1); } if (optc == 'h') exit(0); switch(option_index) { case FE_OPT_DUMP_VERSIONTUPLE: exit(0); break; default: ; } } /* say hello */ if (TEST_V_QUIET) { (printf)( " SINGULAR /" #ifndef MAKE_DISTRIBUTION " Development" #endif "\n" " A Computer Algebra System for Polynomial Computations / version %s\n" " 0<\n" " by: W. Decker, G.-M. Greuel, G. Pfister, H. Schoenemann \\ %s\n" "FB Mathematik der Universitaet, D-67653 Kaiserslautern \\\n" , VERSION, VERSION_DATE); if (feOptValue(FE_OPT_NO_SHELL)) Warn("running in restricted mode:" " shell invocation and links are disallowed"); } else { if (feOptValue(FE_OPT_SORT)) On(SW_USE_NTL_SORT); dup2(1,2); /* alternative: * memcpy(stderr,stdout,sizeof(FILE)); */ } #ifdef SINGULAR_PYOBJECT_SETUP_H pyobject_setup(); #endif #ifdef SI_COUNTEDREF_AUTOLOAD countedref_init(); #endif // #ifdef HAVE_FANS // bbcone_setup(); // bbpolytope_setup(); // bbfan_setup(); // gitfan_setup(); // #endif /* HAVE_FANS */ errorreported = 0; // -- example for "static" modules ------ //load_builtin("huhu.so",FALSE,(SModulFunc_t)huhu_mod_init); //module_help_main("huhu.so","Help for huhu\nhaha\n"); //module_help_proc("huhu.so","p","Help for huhu::p\nhaha\n"); setjmp(si_start_jmpbuf); // Now, put things on the stack of stuff to do // Last thing to do is to execute given scripts if (fe_optind < argc) { int i = argc - 1; FILE *fd; while (i >= fe_optind) { if ((fd = feFopen(argv[i], "r")) == NULL) { Warn("Can not open %s", argv[i]); } else { fclose(fd); newFile(argv[i]); } i--; } } else { currentVoice=feInitStdin(NULL); } // before scripts, we execute -c, if it was given if (feOptValue(FE_OPT_EXECUTE) != NULL) newBuffer(omStrDup((char*) feOptValue(FE_OPT_EXECUTE)), BT_execute); // first thing, however, is to load .singularrc from Singularpath // and cwd/$HOME (in that order). if (! feOptValue(FE_OPT_NO_RC)) { char buf[MAXPATHLEN]; FILE * rc = feFopen("." DIR_SEPP ".singularrc", "r", buf); if (rc == NULL) rc = feFopen("~" DIR_SEPP ".singularrc", "r", buf); if (rc == NULL) rc = feFopen(".singularrc", "r", buf); if (rc != NULL) { if (BVERBOSE(V_LOAD_LIB)) Print("// ** executing %s\n", buf); fclose(rc); newFile(buf); } } /* start shell */ if (fe_fgets_stdin==fe_fgets_dummy) { singular_in_batchmode=TRUE; char *linkname=(char*) feOptValue(FE_OPT_LINK); if((linkname!=NULL)&&(strcmp(linkname,"ssi")==0)) { return ssiBatch((char*) feOptValue(FE_OPT_MPHOST),(char*) feOptValue(FE_OPT_MPPORT)); //Print("batch: p:%s, h:%s\n",(char*) feOptValue(FE_OPT_MPPORT),(char*) feOptValue(FE_OPT_MPHOST)); //exit(0); } } setjmp(si_start_jmpbuf); yyparse(); m2_end(0); return 0; } singular-4.0.3+ds/Singular/tok.h000066400000000000000000000056111266270727000165120ustar00rootroot00000000000000#ifndef TOK_H #define TOK_H /**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: tokens, types for interpreter; general macros */ #ifndef UMINUS #include #endif extern int yylineno; extern char my_yylinebuf[80]; #if defined(__cplusplus) extern int yyparse(void); #endif /* Define to use old mechanismen for saving currRing with procedures */ #define USE_IILOCALRING 1 /* the follwing defines for infix operators should not be changed: * * grammar.y does not use the symbolic names * * scanner.l uses the identies for some optimzations */ #define LOGIC_OP '&' #define MULDIV_OP '/' #define COMP_OP '<' #define COMMAND UMINUS+2 /* in tok.h */ #define ANY_TYPE UMINUS+3 #define IDHDL UMINUS+4 enum { ALIAS_CMD = UMINUS + 15, ALIGN_CMD, ATTRIB_CMD, BAREISS_CMD, BIGINT_CMD, BRANCHTO_CMD, BRACKET_CMD, BREAKPOINT_CMD, CHARACTERISTIC_CMD, CHARSTR_CMD, CHAR_SERIES_CMD, CHINREM_CMD, CMATRIX_CMD, CNUMBER_CMD, CLOSE_CMD, COLS_CMD, CONTENT_CMD, COUNT_CMD, CRING_CMD, DBPRINT_CMD, DEF_CMD, DEFINED_CMD, DELETE_CMD, DENOMINATOR_CMD, DET_CMD, DUMP_CMD, END_GRAMMAR, ENVELOPE_CMD, ERROR_CMD, EXECUTE_CMD, EXPORTTO_CMD, EXTGCD_CMD, FAC_CMD, FIND_CMD, FACSTD_CMD, FMD_CMD, FWALK_CMD, FGLM_CMD, FGLMQUOT_CMD, FINDUNI_CMD, GCD_CMD, GETDUMP_CMD, HIGHCORNER_CMD, HRES_CMD, IMPART_CMD, IMPORTFROM_CMD, INSERT_CMD, INT_CMD, INTDIV_CMD, INTERPOLATE_CMD, INTVEC_CMD, IS_RINGVAR, JANET_CMD, KERNEL_CMD, KILLATTR_CMD, KRES_CMD, LAGSOLVE_CMD, LINK_CMD, LIST_CMD, LOAD_CMD, LRES_CMD, LU_CMD, LUI_CMD, LUS_CMD, MEMORY_CMD, MONITOR_CMD, MPRES_CMD, MSTD_CMD, NAMEOF_CMD, NAMES_CMD, NEWSTRUCT_CMD, NCALGEBRA_CMD, NC_ALGEBRA_CMD, NEWTONPOLY_CMD, NPARS_CMD, NUMERATOR_CMD, NVARS_CMD, OPEN_CMD, OPPOSE_CMD, OPPOSITE_CMD, OPTION_CMD, ORDSTR_CMD, PACKAGE_CMD, PARSTR_CMD, PFAC_CMD, PRIME_CMD, PRINT_CMD, PRUNE_CMD, QRING_CMD, QRDS_CMD, RANDOM_CMD, RANK_CMD, READ_CMD, REPART_CMD, RESERVEDNAME_CMD, RESULTANT_CMD, RINGLIST_CMD, #ifdef SINGULAR_4_1 RING_LIST_CMD, #endif ROWS_CMD, SIMPLEX_CMD, SLIM_GB_CMD, SQR_FREE_CMD, STATUS_CMD, STRING_CMD, SYSTEM_CMD, TEST_CMD, TRANSPOSE_CMD, TRACE_CMD, TWOSTD_CMD, TYPEOF_CMD, UNIVARIATE_CMD, UNLOAD_CMD, /* unused*/ URSOLVE_CMD, VANDER_CMD, VARIABLES_CMD, VARSTR_CMD, WAIT1ST_CMD, WAITALL_CMD, WRITE_CMD, /* start system var section: VECHO */ VECHO, VCOLMAX, VTIMER, VRTIMER, TRACE, VOICE, VSHORTOUT, VPRINTLEVEL, /* end system var section: VPRINTLEVEL */ MAX_TOK /* must be the last, biggest token number */ }; #define NONE END_RING #define UNKNOWN 0 #endif singular-4.0.3+ds/Singular/utils.cc000066400000000000000000000163201266270727000172120ustar00rootroot00000000000000#include #ifdef STANDALONE_PARSER #include #include #include #include #include #include #include extern FILE *yylpin; extern char *optarg; extern int optind, opterr, optopt; extern int lpverbose, check; extern int texinfo_out; extern int category_out; extern int found_version, found_info, found_oldhelp, found_proc_in_proc; int warning_info = 0, warning_version = 0; static void usage(char *progname) { printf("libparse: a syntax-checker for Singular Libraries.\n"); printf("USAGE: %s [options] singular-library\n", progname); printf("Options:\n"); printf(" -f : performs syntax-checks\n"); printf(" -d [digit] : digit=1,..,4 increases the verbosity of the checks\n"); printf(" -s : turns on reporting about violations of unenforced syntax rules\n"); printf(" -i : perl output of examples and help of procs\n"); printf(" -c : print category of lib to stdout and exit\n"); printf(" -h : print this message\n"); exit(1); } static char* lib_file = NULL; /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void main_init(int argc, char *argv[]) { char c; while((c=fe_getopt(argc, argv, "ihdc:sf:"))>=0) { switch(c) { case 'd': lpverbose = 1; if(isdigit(argv[fe_optind-1][0])) sscanf(optarg, "%d", &lpverbose); else fe_optind--; break; case 'f': lib_file = argv[fe_optind-1]; break; case 's': check++; break; case 'i': texinfo_out = 1; break; case 'c': category_out = 1; break; case 'h' : usage(argv[0]); break; case -1 : printf("no such option:%s\n", argv[fe_optind]); usage(argv[0]); break; default: printf("no such option.%x, %c %s\n", c&0xff, c, argv[fe_optind]); usage(argv[0]); } } if (texinfo_out || category_out) lpverbose = 0; if(lib_file!=NULL) { yylpin = fopen( lib_file, "rb" ); if (! (texinfo_out || category_out)) printf("Checking library '%s'\n", lib_file); else if (! category_out) printf("$library = \"%s\";\n", lib_file); } else { while(argc>fe_optind && yylpin==NULL) { yylpin = fopen( argv[fe_optind], "rb" ); if(yylpin!=NULL) { lib_file = argv[fe_optind]; if (! (texinfo_out || category_out) ) printf("Checking library '%s'\n", argv[fe_optind]); else if (! category_out) printf("$library = \"%s\";\n", lib_file); } else fe_optind++; } } if(yylpin == NULL) { printf("No library found to parse.\n"); usage(argv[0]); } } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void main_result(char */*libname*/) { if(!found_info) printf("*** No info-string found!\n"); if(!found_version) printf("*** No version-string found!\n"); if(found_oldhelp) printf("*** Library has stil OLD library-format.\n"); if(found_info && warning_info) printf("*** INFO-string should come before every procedure definition.\n"); if(found_version && warning_version) printf("*** VERSION-string should come before every procedure definition.\n"); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ procinfo *iiInitSingularProcinfo(procinfo* pi, const char *libname, const char *procname, int line, long pos, BOOLEAN pstatic /*= FALSE*/) { pi->libname = (char *)malloc(strlen(libname)+1); memcpy(pi->libname, libname, strlen(libname)); *(pi->libname+strlen(libname)) = '\0'; pi->procname = (char *)malloc(strlen(procname)+1); strcpy(pi->procname, procname/*, strlen(procname)*/); pi->language = LANG_SINGULAR; pi->ref = 1; pi->is_static = pstatic; pi->data.s.proc_start = pos; pi->data.s.def_end = 0L; pi->data.s.help_start = 0L; pi->data.s.body_start = 0L; pi->data.s.body_end = 0L; pi->data.s.example_start = 0L; pi->data.s.proc_lineno = line; pi->data.s.body_lineno = 0; pi->data.s.example_lineno = 0; pi->data.s.body = NULL; pi->data.s.help_chksum = 0; return(pi); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ void pi_clear(procinfov pi) { free(pi->libname); free(pi->procname); free(pi); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #ifndef SEEK_SET #define SEEK_SET 0 #endif static void PrintOut(FILE *fd, int pos_start, int pos_end) { if (pos_start <= 0 || pos_end - pos_start <= 4) return; char c = 0; fseek(fd, pos_start, SEEK_SET); while (pos_start++ <= pos_end) { if (c == '\\') { c = fgetc(fd); if (c != '"') putchar('\\'); } else c = fgetc(fd); if (c == '@' || c == '$') putchar('\\'); if (c != '\r') putchar(c); } if (c == '\\') putchar('\\'); } void printpi(procinfov pi) { // char *buf, name[256]; // int len1, len2; /* pi->libname is badly broken -- use file, instead */ FILE *fp = fopen( lib_file, "rb"); if (fp == NULL) { printf("Can not open %s\n", lib_file); return; } if(!found_info && !warning_info) warning_info++; if(!found_version && !warning_version) warning_version++; if(pi->data.s.body_end==0) pi->data.s.body_end = pi->data.s.proc_end; if (texinfo_out) { if ((! pi->is_static) && (pi->data.s.body_start - pi->data.s.def_end > 10) && (! found_proc_in_proc)) { printf("push(@procs, \"%s\");\n", pi->procname); printf("$help{\"%s\"} = <procname); PrintOut(fp, pi->data.s.help_start, pi->data.s.body_start-3); printf("\nEOT\n"); if ((pi->data.s.example_start > 0) && (pi->data.s.proc_end - pi->data.s.example_start > 10)) { printf("$example{\"%s\"} = <procname); PrintOut(fp, pi->data.s.example_start, pi->data.s.proc_end); printf("\nEOT\n"); } printf("$chksum{\"%s\"} = %ld;\n", pi->procname, pi->data.s.help_chksum); } } else if (! category_out) { if(lpverbose) printf("// "); printf( "%c %-15s %20s ", pi->is_static ? 'l' : 'g', pi->libname, pi->procname); printf("line %4d,%5ld-%-5ld %4d,%5ld-%-5ld %4d,%5ld-%-5ld\n", pi->data.s.proc_lineno, pi->data.s.proc_start, pi->data.s.def_end, pi->data.s.body_lineno, pi->data.s.body_start, pi->data.s.body_end, pi->data.s.example_lineno, pi->data.s.example_start, pi->data.s.proc_end); if(check) { if(!pi->is_static && (pi->data.s.body_start-pi->data.s.def_end)<4) printf("*** Procedure '%s' is global and has no help-section.\n", pi->procname); if(!pi->is_static && !pi->data.s.example_start) printf("*** Procedure '%s' is global and has no example-section.\n",\ pi->procname); if(found_proc_in_proc) printf("*** found proc within procedure '%s'.\n", pi->procname); } } if (fp != NULL) fclose(fp); } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #endif singular-4.0.3+ds/Singular/utils.h000066400000000000000000000001371266270727000170530ustar00rootroot00000000000000/* */ #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif singular-4.0.3+ds/Singular/walk.cc000066400000000000000000007267161266270727000170310ustar00rootroot00000000000000/***************************************** * Computer Algebra System SINGULAR * *****************************************/ /* $Id$ */ /* * ABSTRACT: Implementation of the Groebner walk */ // define if the Buchberger alg should be used // to compute a reduced GB of a omega-homogenoues ideal // default: we use the hilbert driven algorithm. #define BUCHBERGER_ALG //we use the improved Buchberger alg. //#define UPPER_BOUND //for the original "Tran" algorithm //#define REPRESENTATION_OF_SIGMA //if one perturbs sigma in Tran //#define TEST_OVERFLOW #define CHECK_IDEAL_MWALK //to print intermediate results //#define NEXT_VECTORS_CC //#define PRINT_VECTORS //to print weight vectors #define INVEPS_SMALL_IN_FRACTAL //to choose the small invers of epsilon #define INVEPS_SMALL_IN_MPERTVECTOR //to choose the small invers of epsilon #define INVEPS_SMALL_IN_TRAN //to choose the small invers of epsilon #define FIRST_STEP_FRACTAL // to define the first step of the fractal #define MSTDCC_FRACTAL // apply Buchberger alg to compute a red GB, if tau doesn't stay in the correct cone //#define TIME_TEST // print the used time of each subroutine //#define ENDWALKS //print the size of the last omega-homogenoues Groebner basis /* includes */ #include #include #include #include #include #include #include #include #include #include #include #include /* include Hilbert-function */ #include /** kstd2.cc */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include // === Zeit & System (Holger Croeni === #include #include #include #include #include #include #include #include int nstep; extern BOOLEAN ErrorCheck(); extern BOOLEAN pSetm_error; void Set_Error( BOOLEAN f) { pSetm_error=f; } BOOLEAN Overflow_Error = FALSE; clock_t xtif, xtstd, xtlift, xtred, xtnw; clock_t xftostd, xtextra, xftinput, to; /**************************** * utilities for TSet, LSet * ****************************/ inline static intset initec (int maxnr) { return (intset)omAlloc(maxnr*sizeof(int)); } inline static unsigned long* initsevS (int maxnr) { return (unsigned long*)omAlloc0(maxnr*sizeof(unsigned long)); } inline static int* initS_2_R (int maxnr) { return (int*)omAlloc0(maxnr*sizeof(int)); } /************************************ * construct the set s from F u {P} * ************************************/ // unused /* static void initSSpecialCC (ideal F, ideal Q, ideal P,kStrategy strat) { int i,pos; if (Q!=NULL) i=((IDELEMS(Q)+(setmaxTinc-1))/setmaxTinc)*setmaxTinc; else i=setmaxT; strat->ecartS=initec(i); strat->sevS=initsevS(i); strat->S_2_R=initS_2_R(i); strat->fromQ=NULL; strat->Shdl=idInit(i,F->rank); strat->S=strat->Shdl->m; // - put polys into S - if (Q!=NULL) { strat->fromQ=initec(i); memset(strat->fromQ,0,i*sizeof(int)); for (i=0; im[i]!=NULL) { LObject h; h.p = pCopy(Q->m[i]); //if (TEST_OPT_INTSTRATEGY) //{ // //pContent(h.p); // h.pCleardenom(); // also does a pContent //} //else //{ // h.pNorm(); //} strat->initEcart(&h); if (rHasLocalOrMixedOrdering_currRing()) { deleteHC(&h,strat); } if (h.p!=NULL) { if (strat->sl==-1) pos =0; else { pos = posInS(strat,strat->sl,h.p,h.ecart); } h.sev = pGetShortExpVector(h.p); h.SetpFDeg(); strat->enterS(h,pos,strat, strat->tl+1); enterT(h, strat); strat->fromQ[pos]=1; } } } } //- put polys into S - for (i=0; im[i]!=NULL) { LObject h; h.p = pCopy(F->m[i]); if (rHasGlobalOrdering(currRing)) { //h.p=redtailBba(h.p,strat->sl,strat); h.p=redtailBba(h.p,strat->sl,strat); } else { deleteHC(&h,strat); } strat->initEcart(&h); if (h.p!=NULL) { if (strat->sl==-1) pos =0; else pos = posInS(strat,strat->sl,h.p,h.ecart); h.sev = pGetShortExpVector(h.p); strat->enterS(h,pos,strat, strat->tl+1); h.length = pLength(h.p); h.SetpFDeg(); enterT(h,strat); } } } #ifdef INITSSPECIAL for (i=0; im[i]!=NULL) { LObject h; h.p=pCopy(P->m[i]); strat->initEcart(&h); h.length = pLength(h.p); if (TEST_OPT_INTSTRATEGY) { h.pCleardenom(); } else { h.pNorm(); } if(strat->sl>=0) { if (rHasGlobalOrdering(currRing)) { h.p=redBba(h.p,strat->sl,strat); if (h.p!=NULL) h.p=redtailBba(h.p,strat->sl,strat); } else { h.p=redMora(h.p,strat->sl,strat); strat->initEcart(&h); } if(h.p!=NULL) { if (TEST_OPT_INTSTRATEGY) { h.pCleardenom(); } else { h.is_normalized = 0; h.pNorm(); } h.sev = pGetShortExpVector(h.p); h.SetpFDeg(); pos = posInS(strat->S,strat->sl,h.p,h.ecart); enterpairsSpecial(h.p,strat->sl,h.ecart,pos,strat,strat->tl+1); strat->enterS(h,pos,strat, strat->tl+1); enterT(h,strat); } } else { h.sev = pGetShortExpVector(h.p); h.SetpFDeg(); strat->enterS(h,0,strat, strat->tl+1); enterT(h,strat); } } } #endif } */ /***************** *interreduce F * *****************/ static ideal kInterRedCC(ideal F, ideal Q) { int j; kStrategy strat = new skStrategy; /* if (TEST_OPT_PROT) { writeTime("start InterRed:"); mflush(); } strat->syzComp = 0; */ strat->kHEdgeFound = (currRing->ppNoether) != NULL; strat->kNoether=pCopy((currRing->ppNoether)); strat->ak = id_RankFreeModule(F, currRing); initBuchMoraCrit(strat); strat->NotUsedAxis = (BOOLEAN *)omAlloc((currRing->N+1)*sizeof(BOOLEAN)); for(j=currRing->N; j>0; j--) { strat->NotUsedAxis[j] = TRUE; } strat->enterS = enterSBba; strat->posInT = posInT0; strat->initEcart = initEcartNormal; strat->sl = -1; strat->tl = -1; strat->tmax = setmaxT; strat->T = initT(); strat->R = initR(); strat->sevT = initsevT(); if(rHasLocalOrMixedOrdering_currRing()) { strat->honey = TRUE; } //initSCC(F,Q,strat); initS(F,Q,strat); /* timetmp=clock();//22.01.02 initSSpecialCC(F,Q,NULL,strat); tininitS=tininitS+clock()-timetmp;//22.01.02 */ if(TEST_OPT_REDSB) { strat->noTailReduction=FALSE; } updateS(TRUE,strat); if(TEST_OPT_REDSB && TEST_OPT_INTSTRATEGY) { completeReduce(strat); } pDelete(&strat->kHEdge); omFreeSize((ADDRESS)strat->T,strat->tmax*sizeof(TObject)); omFreeSize((ADDRESS)strat->ecartS,IDELEMS(strat->Shdl)*sizeof(int)); omFreeSize((ADDRESS)strat->sevS,IDELEMS(strat->Shdl)*sizeof(unsigned long)); omFreeSize((ADDRESS)strat->NotUsedAxis,(currRing->N+1)*sizeof(BOOLEAN)); omfree(strat->sevT); omfree(strat->S_2_R); omfree(strat->R); if(strat->fromQ) { for(j=0; jShdl); j++) { if(strat->fromQ[j]) { pDelete(&strat->Shdl->m[j]); } } omFreeSize((ADDRESS)strat->fromQ,IDELEMS(strat->Shdl)*sizeof(int)); strat->fromQ = NULL; } /* if (TEST_OPT_PROT) { writeTime("end Interred:"); mflush(); } */ ideal shdl=strat->Shdl; idSkipZeroes(shdl); delete(strat); return shdl; } #ifdef TIME_TEST static void TimeString(clock_t tinput, clock_t tostd, clock_t tif,clock_t tstd, clock_t tlf,clock_t tred, clock_t tnw, int step) { double totm = ((double) (clock() - tinput))/1000000; double ostd,mostd, mif, mstd, mlf, mred, mnw, mxif,mxstd,mxlf,mxred,mxnw,tot; // double mextra Print("\n// total time = %.2f sec", totm); Print("\n// tostd = %.2f sec = %.2f", ostd=((double) tostd)/1000000, mostd=((((double) tostd)/1000000)/totm)*100); Print("\n// tif = %.2f sec = %.2f", ((double) tif)/1000000, mif=((((double) tif)/1000000)/totm)*100); Print("\n// std = %.2f sec = %.2f", ((double) tstd)/1000000, mstd=((((double) tstd)/1000000)/totm)*100); Print("\n// lift = %.2f sec = %.2f", ((double) tlf)/1000000, mlf=((((double) tlf)/1000000)/totm)*100); Print("\n// ired = %.2f sec = %.2f", ((double) tred)/1000000, mred=((((double) tred)/1000000)/totm)*100); Print("\n// nextw = %.2f sec = %.2f", ((double) tnw)/1000000, mnw=((((double) tnw)/1000000)/totm)*100); PrintS("\n Time for the last step:"); Print("\n// xinfo = %.2f sec = %.2f", ((double) xtif)/1000000, mxif=((((double) xtif)/1000000)/totm)*100); Print("\n// xstd = %.2f sec = %.2f", ((double) xtstd)/1000000, mxstd=((((double) xtstd)/1000000)/totm)*100); Print("\n// xlift = %.2f sec = %.2f", ((double) xtlift)/1000000, mxlf=((((double) xtlift)/1000000)/totm)*100); Print("\n// xired = %.2f sec = %.2f", ((double) xtred)/1000000, mxred=((((double) xtred)/1000000)/totm)*100); Print("\n// xnextw= %.2f sec = %.2f", ((double) xtnw)/1000000, mxnw=((((double) xtnw)/1000000)/totm)*100); tot=mostd+mif+mstd+mlf+mred+mnw+mxif+mxstd+mxlf+mxred+mxnw; double res = (double) 100 - tot; Print("\n// &%d&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f&%.2f(%.2f)\\ \\", step, ostd, totm, mostd,mif,mstd,mlf,mred,mnw,mxif,mxstd,mxlf,mxred,mxnw,tot,res, ((((double) xtextra)/1000000)/totm)*100); } static void TimeStringFractal(clock_t tinput, clock_t tostd, clock_t tif,clock_t tstd, clock_t textra, clock_t tlf,clock_t tred, clock_t tnw) { double totm = ((double) (clock() - tinput))/1000000; double ostd, mostd, mif, mstd, mextra, mlf, mred, mnw, tot, res; Print("\n// total time = %.2f sec", totm); Print("\n// tostd = %.2f sec = %.2f", ostd=((double) tostd)/1000000, mostd=((((double) tostd)/1000000)/totm)*100); Print("\n// tif = %.2f sec = %.2f", ((double) tif)/1000000, mif=((((double) tif)/1000000)/totm)*100); Print("\n// std = %.2f sec = %.2f", ((double) tstd)/1000000, mstd=((((double) tstd)/1000000)/totm)*100); Print("\n// xstd = %.2f sec = %.2f", ((double) textra)/1000000, mextra=((((double) textra)/1000000)/totm)*100); Print("\n// lift = %.2f sec = %.2f", ((double) tlf)/1000000, mlf=((((double) tlf)/1000000)/totm)*100); Print("\n// ired = %.2f sec = %.2f", ((double) tred)/1000000, mred=((((double) tred)/1000000)/totm)*100); Print("\n// nextw = %.2f sec = %.2f", ((double) tnw)/1000000, mnw=((((double) tnw)/1000000)/totm)*100); tot = mostd+mif+mstd+mextra+mlf+mred+mnw; res = (double) 100.00-tot; Print("\n// &%.2f &%.2f&%.2f &%.2f &%.2f &%.2f &%.2f &%.2f &%.2f&%.2f&%.2f\\ \\ ", ostd,totm,mostd,mif,mstd,mextra,mlf,mred,mnw,tot,res); } #endif #ifdef CHECK_IDEAL_MWALK static void idString(ideal L, const char* st) { int i, nL = IDELEMS(L); Print("\n// ideal %s = ", st); for(i=0; im[i])); } Print(" %s;", pString(L->m[nL-1])); } #endif /* #if defined(CHECK_IDEAL_MWALK) || defined(ENDWALKS) static void headidString(ideal L, char* st) { int i, nL = IDELEMS(L); Print("\n// ideal %s = ", st); for(i=0; im[i]))); } Print(" %s;", pString(pHead(L->m[nL-1]))); } #endif #if defined(CHECK_IDEAL_MWALK) || defined(ENDWALKS) static void idElements(ideal L, char* st) { int i, nL = IDELEMS(L); int *K=(int *)omAlloc(nL*sizeof(int)); Print("\n// #monoms of %s = ", st); for(i=0; im[i]); } int j, nsame; // int nk=0; for(i=0; ilength()-1; Print("\n// intvec %s = ", ch); for(int i=0; ilength()-1; int i; PrintS("\n// ("); for(i=0; i (", (*iva)[nV]); for(i=0; i= 0 && p1 >= 0); if(p0 < 0) { p0 = -p0; } if(p1 < 0) { p1 = -p1; } while(p1 != 0) { r = p0 % p1; p0 = p1; p1 = r; } return p0; } /***************************************************************************** * compute the gcd of the entries of the vectors curr_weight and diff_weight * *****************************************************************************/ static int simplify_gcd(intvec* curr_weight, intvec* diff_weight) { int j; int nRing = currRing->N; int gcd_tmp = (*curr_weight)[0]; for (j=1; j= 0 && nenner > 0); mpz_t g; mpz_init(g); mpz_gcd(g, zaehler, nenner); mpz_div(zaehler , zaehler, g); mpz_div(nenner , nenner, g); mpz_clear(g); } //unused #if 0 static int isVectorNeg(intvec* omega) { int i; for(i=omega->length(); i>=0; i--) { if((*omega)[i]<0) { return 1; } } return 0; } #endif /******************************************************************** * compute a weight degree of a monomial p w.r.t. a weight_vector * ********************************************************************/ static inline int MLmWeightedDegree(const poly p, intvec* weight) { /* 2147483647 is max. integer representation in SINGULAR */ mpz_t sing_int; mpz_init_set_ui(sing_int, 2147483647); int i, wgrad; mpz_t zmul; mpz_init(zmul); mpz_t zvec; mpz_init(zvec); mpz_t zsum; mpz_init(zsum); for (i=currRing->N; i>0; i--) { mpz_set_si(zvec, (*weight)[i-1]); mpz_mul_ui(zmul, zvec, pGetExp(p, i)); mpz_add(zsum, zsum, zmul); } wgrad = mpz_get_ui(zsum); if(mpz_cmp(zsum, sing_int)>0) { if(Overflow_Error == FALSE) { PrintLn(); PrintS("\n// ** OVERFLOW in \"MwalkInitialForm\": "); mpz_out_str( stdout, 10, zsum); PrintS(" is greater than 2147483647 (max. integer representation)"); Overflow_Error = TRUE; } } mpz_clear(zmul); mpz_clear(zvec); mpz_clear(zsum); mpz_clear(sing_int); return wgrad; } /******************************************************************** * compute a weight degree of a polynomial p w.r.t. a weight_vector * ********************************************************************/ static inline int MwalkWeightDegree(poly p, intvec* weight_vector) { assume(weight_vector->length() >= currRing->N); int max = 0, maxtemp; while(p != NULL) { maxtemp = MLmWeightedDegree(p, weight_vector); pIter(p); if (maxtemp > max) { max = maxtemp; } } return max; } /******************************************************************** * compute a weight degree of a monomial p w.r.t. a weight_vector * ********************************************************************/ static void MLmWeightedDegree_gmp(mpz_t result, const poly p, intvec* weight) { /* 2147483647 is max. integer representation in SINGULAR */ mpz_t sing_int; mpz_init_set_ui(sing_int, 2147483647); int i; mpz_t zmul; mpz_init(zmul); mpz_t zvec; mpz_init(zvec); mpz_t ztmp; mpz_init(ztmp); for (i=currRing->N; i>0; i--) { mpz_set_si(zvec, (*weight)[i-1]); mpz_mul_ui(zmul, zvec, pGetExp(p, i)); mpz_add(ztmp, ztmp, zmul); } mpz_init_set(result, ztmp); mpz_clear(ztmp); mpz_clear(sing_int); mpz_clear(zvec); mpz_clear(zmul); } /***************************************************************************** * return an initial form of the polynom g w.r.t. a weight vector curr_weight * *****************************************************************************/ static poly MpolyInitialForm(poly g, intvec* curr_weight) { if(g == NULL) { return NULL; } mpz_t max; mpz_init(max); mpz_t maxtmp; mpz_init(maxtmp); poly hg, in_w_g = NULL; while(g != NULL) { hg = g; pIter(g); MLmWeightedDegree_gmp(maxtmp, hg, curr_weight); if(mpz_cmp(maxtmp, max)>0) { mpz_set(max, maxtmp); if (in_w_g!=NULL) pDelete(&in_w_g); in_w_g = pHead(hg); } else { if(mpz_cmp(maxtmp, max)==0) { in_w_g = pAdd(in_w_g, pHead(hg)); } } } mpz_clear(maxtmp); mpz_clear(max); return in_w_g; } /************************************************************************ * compute the initial form of an ideal w.r.t. a weight vector iva * ************************************************************************/ ideal MwalkInitialForm(ideal G, intvec* ivw) { BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; int i, nG = IDELEMS(G); ideal Gomega = idInit(nG, 1); for(i=nG-1; i>=0; i--) { Gomega->m[i] = MpolyInitialForm(G->m[i], ivw); } if(Overflow_Error == FALSE) { Overflow_Error = nError; } return Gomega; } /************************************************************************ * test whether the weight vector iv is in the cone of the ideal G * * i.e. test whether in(in_w(g)) = in(g) for all g in G * ************************************************************************/ static int test_w_in_ConeCC(ideal G, intvec* iv) { if(G->m[0] == NULL) { PrintS("//** the result may be WRONG, i.e. 0!!\n"); return 0; } BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; int i, nG = IDELEMS(G); poly mi, gi; for(i=nG-1; i>=0; i--) { mi = MpolyInitialForm(G->m[i], iv); //Print("\n **// test_w_in_ConeCC: lm(initial)= %s \n",pString(mi)); gi = G->m[i]; //Print("\n **// test_w_in_ConeCC: lm(ideal)= %s \n",pString(gi)); if(mi == NULL) { if(Overflow_Error == FALSE) { Overflow_Error = nError; } return 0; } if(!pLmEqual(mi, gi)) { pDelete(&mi); if(Overflow_Error == FALSE) { Overflow_Error = nError; } return 0; } pDelete(&mi); } if(Overflow_Error == FALSE) { Overflow_Error = nError; } return 1; } /*************************************************** * compute a least common multiple of two integers * ***************************************************/ static inline long Mlcm(long &i1, long &i2) { long temp = gcd(i1, i2); return ((i1 / temp)* i2); } /*************************************************** * return the dot product of two intvecs a and b * ***************************************************/ static inline long MivDotProduct(intvec* a, intvec* b) { assume( a->length() == b->length()); int i, n = a->length(); long result = 0; for(i=n-1; i>=0; i--) { result += (*a)[i] * (*b)[i]; } return result; } /***************************************************** * Substract two given intvecs componentwise * *****************************************************/ static intvec* MivSub(intvec* a, intvec* b) { assume( a->length() == b->length()); int i, n = a->length(); intvec* result = new intvec(n); for(i=n-1; i>=0; i--) { (*result)[i] = (*a)[i] - (*b)[i]; } return result; } /***************************************************** * return the "intvec" lead exponent of a polynomial * *****************************************************/ static intvec* MExpPol(poly f) { int i, nR = currRing->N; intvec* result = new intvec(nR); for(i=nR-1; i>=0; i--) { (*result)[i] = pGetExp(f,i+1); } return result; } /***************************************************** * Compare two given intvecs and return 1, if they * * are the same, otherwise 0 * *****************************************************/ int MivSame(intvec* u , intvec* v) { assume(u->length() == v->length()); int i, niv = u->length(); for (i=0; ilength() == u->length() && u->length() == v->length()); if((MivSame(temp, u)) == 1) { return 0; } if((MivSame(temp, v)) == 1) { return 1; } return 2; } /***************************************************** * compute a Groebner basis of an ideal * *****************************************************/ static ideal MstdCC(ideal G) { BITSET save1,save2; SI_SAVE_OPT(save1,save2); si_opt_1|=(Sy_bit(OPT_REDTAIL)|Sy_bit(OPT_REDSB)); ideal G1 = kStd(G, NULL, testHomog, NULL); SI_RESTORE_OPT(save1,save2); idSkipZeroes(G1); return G1; } /***************************************************** * compute a Groebner basis of an homogeneous ideal * *****************************************************/ static ideal MstdhomCC(ideal G) { BITSET save1,save2; SI_SAVE_OPT(save1,save2); si_opt_1|=(Sy_bit(OPT_REDTAIL)|Sy_bit(OPT_REDSB)); ideal G1 = kStd(G, NULL, isHomog, NULL); SI_RESTORE_OPT(save1,save2); idSkipZeroes(G1); return G1; } /***************************************************************************** * create a weight matrix order as intvec of an extra weight vector (a(iv),lp)* ******************************************************************************/ intvec* MivMatrixOrder(intvec* iv) { int i, nR = iv->length(); intvec* ivm = new intvec(nR*nR); for(i=0; ilength())*(iv->length()) == iw->length()); int i,j, nR = iv->length(); intvec* ivm = new intvec(nR*nR); for(i=0; i=0; i--) { (*ivm)[i] = 1; } return ivm; } /********************************** * return intvvec = (1,0, ..., 0) * **********************************/ intvec* Mivlp(int nR) { intvec* ivm = new intvec(nR); (*ivm)[0] = 1; return ivm; } //unused /***************************************************************************** * print the max total degree and the max coefficient of G * *****************************************************************************/ /* static void checkComplexity(ideal G, char* cG) { int nV = currRing->N; int nG = IDELEMS(G); intvec* ivUnit = Mivdp(nV); int i, tmpdeg, maxdeg=0; number tmpcoeff , maxcoeff=currRing->cf->nNULL; poly p; for(i=nG-1; i>=0; i--) { tmpdeg = MwalkWeightDegree(G->m[i], ivUnit); if(tmpdeg > maxdeg ) { maxdeg = tmpdeg; } } for(i=nG-1; i>=0; i--) { p = pCopy(G->m[i]); while(p != NULL) { //tmpcoeff = pGetCoeff(pHead(p)); tmpcoeff = pGetCoeff(p); if(nGreater(tmpcoeff,maxcoeff)) { maxcoeff = nCopy(tmpcoeff); } pIter(p); } pDelete(&p); } p = pNSet(maxcoeff); char* pStr = pString(p); delete ivUnit; Print("// max total degree of %s = %d\n",cG, maxdeg); Print("// max coefficient of %s = %s", cG, pStr);//ing(p)); Print(" which consists of %d digits", (int)strlen(pStr)); PrintLn(); } */ /***************************************************************************** * If target_ord = intmat(A1, ..., An) then calculate the perturbation * * vectors * * tau_p_dep = inveps^(p_deg-1)*A1 + inveps^(p_deg-2)*A2 +... + A_p_deg * * where * * inveps > totaldegree(G)*(max(A2)+...+max(A_p_deg)) * * intmat target_ord is an integer order matrix of the monomial ordering of * * basering. * * This programm computes a perturbated vector with a p_deg perturbation * * degree which smaller than the numbers of variables * ******************************************************************************/ intvec* MPertVectors(ideal G, intvec* ivtarget, int pdeg) { // ivtarget is a matrix order of a degree reverse lex. order int nV = currRing->N; //assume(pdeg <= nV && pdeg >= 0); int i, j, nG = IDELEMS(G); intvec* v_null = new intvec(nV); // Check that the perturbed degree is valid if(pdeg > nV || pdeg <= 0) { WerrorS("//** The perturbed degree is wrong!!"); return v_null; } delete v_null; if(pdeg == 1) { return ivtarget; } mpz_t *pert_vector = (mpz_t*)omAlloc(nV*sizeof(mpz_t)); mpz_t *pert_vector1 = (mpz_t*)omAlloc(nV*sizeof(mpz_t)); for(i=0; i maxAi) { maxAi = ntemp; } } maxA += maxAi; } // Calculate inveps = 1/eps, where 1/eps > totaldeg(p)*max1 for all p in G. intvec* ivUnit = Mivdp(nV); mpz_t tot_deg; mpz_init(tot_deg); mpz_t maxdeg; mpz_init(maxdeg); mpz_t inveps; mpz_init(inveps); for(i=nG-1; i>=0; i--) { mpz_set_ui(maxdeg, MwalkWeightDegree(G->m[i], ivUnit)); if (mpz_cmp(maxdeg, tot_deg) > 0 ) { mpz_set(tot_deg, maxdeg); } } delete ivUnit; mpz_mul_ui(inveps, tot_deg, maxA); mpz_add_ui(inveps, inveps, 1); // takes "small" inveps #ifdef INVEPS_SMALL_IN_MPERTVECTOR if(mpz_cmp_ui(inveps, pdeg)>0 && pdeg > 3) { // Print("\n// choose the\"small\" inverse epsilon := %d / %d = ", mpz_get_si(inveps), pdeg); mpz_fdiv_q_ui(inveps, inveps, pdeg); // mpz_out_str(stdout, 10, inveps); } #else // PrintS("\n// the \"big\" inverse epsilon: "); mpz_out_str(stdout, 10, inveps); #endif // pert(A1) = inveps^(pdeg-1)*A1 + inveps^(pdeg-2)*A2+...+A_pdeg, // pert_vector := A1 for( i=1; i < pdeg; i++ ) { for(j=0; j=0) { for(j=0; j=0) { ntrue++; } } if(ntrue > 0 || test_w_in_ConeCC(G,result)==0) { ntrue=0; for(i=0; i=0) { ntrue++; if(Overflow_Error == FALSE) { Overflow_Error = TRUE; PrintS("\n// ** OVERFLOW in \"MPertvectors\": "); mpz_out_str( stdout, 10, pert_vector[i]); PrintS(" is greater than 2147483647 (max. integer representation)"); Print("\n// So vector[%d] := %d is wrong!!", i+1, (*result)[i]); } } } if(Overflow_Error == TRUE) { ivString(result, "pert_vector"); Print("\n// %d element(s) of it is overflow!!", ntrue); } } mpz_clear(ztemp); mpz_clear(sing_int); mpz_clear(check_int); omFree(pert_vector); omFree(pert_vector1); mpz_clear(tot_deg); mpz_clear(maxdeg); mpz_clear(inveps); rComplete(currRing); for(j=0; jm[j]; while(p!=NULL) { p_Setm(p,currRing); pIter(p); } } return result; } /***************************************************************************** * The following procedure returns * * Pert(A1) = 1/eps^(pdeg-1)*A_1 + 1/eps^(pdeg-2)*A_2+...+A_pdeg, * * where the A_i are the i-th rows of the matrix target_ord and * * 1/eps > deg(p)*(max(A_2) + max(A_3)+...+max(A_pdeg)) * *****************************************************************************/ intvec* MPertVectorslp(ideal G, intvec* ivtarget, int pdeg) { // ivtarget is a matrix order of the lex. order int nV = currRing->N; //assume(pdeg <= nV && pdeg >= 0); int i, j, nG = IDELEMS(G); intvec* pert_vector = new intvec(nV); //Checking that the perturbated degree is valid if(pdeg > nV || pdeg <= 0) { WerrorS("//** The perturbed degree is wrong!!"); return pert_vector; } for(i=0; i maxAi) { maxAi = ntemp; } } maxA += maxAi; } // Calculate inveps := 1/eps, where 1/eps > deg(p)*max1 for all p in G. int inveps, tot_deg = 0, maxdeg; intvec* ivUnit = Mivdp(nV);//19.02 for(i=nG-1; i>=0; i--) { // maxdeg = pTotaldegree(G->m[i], currRing); //it's wrong for ex1,2,rose maxdeg = MwalkWeightDegree(G->m[i], ivUnit); if (maxdeg > tot_deg ) { tot_deg = maxdeg; } } delete ivUnit; inveps = (tot_deg * maxA) + 1; #ifdef INVEPS_SMALL_IN_FRACTAL // Print("\n// choose the\"small\" inverse epsilon := %d / %d = ", inveps, pdeg); if(inveps > pdeg && pdeg > 3) { inveps = inveps / pdeg; } // Print(" %d", inveps); #else PrintS("\n// the \"big\" inverse epsilon %d", inveps); #endif // Pert(A1) = inveps^(pdeg-1)*A1 + inveps^(pdeg-2)*A2+...+A_pdeg for ( i=1; i < pdeg; i++ ) { for(j=0; jlength(); intvec* ivM = new intvec(nV*nV); for(i=0; ilength(); intvec* ivM = new intvec(nV*nV); for(i=0; i=0; i--) { (*ivM)[i] = 1; } return(ivM); } /************************************************************************ * compute a perturbed weight vector of a matrix order w.r.t. an ideal * *************************************************************************/ int Xnlev; intvec* Mfpertvector(ideal G, intvec* ivtarget) { int i, j, nG = IDELEMS(G); int nV = currRing->N; int niv = nV*nV; // Calculate maxA = Max(A2) + Max(A3) + ... + Max(AnV), // where the Ai are the i-te rows of the matrix 'targer_ord'. int ntemp, maxAi, maxA=0; for(i=1; i maxAi) { maxAi = ntemp; } } maxA = maxA + maxAi; } intvec* ivUnit = Mivdp(nV); // Calculate inveps = 1/eps, where 1/eps > deg(p)*maxA for all p in G. mpz_t tot_deg; mpz_init(tot_deg); mpz_t maxdeg; mpz_init(maxdeg); mpz_t inveps; mpz_init(inveps); for(i=nG-1; i>=0; i--) { mpz_set_ui(maxdeg, MwalkWeightDegree(G->m[i], ivUnit)); if (mpz_cmp(maxdeg, tot_deg) > 0 ) { mpz_set(tot_deg, maxdeg); } } delete ivUnit; //inveps = (tot_deg * maxA) + 1; mpz_mul_ui(inveps, tot_deg, maxA); mpz_add_ui(inveps, inveps, 1); // takes "small" inveps #ifdef INVEPS_SMALL_IN_FRACTAL if(mpz_cmp_ui(inveps, nV)>0 && nV > 3) { mpz_cdiv_q_ui(inveps, inveps, nV); } // choose the small inverse epsilon #endif // PrintLn(); mpz_out_str(stdout, 10, inveps); // Calculate the perturbed target orders: mpz_t *ivtemp=(mpz_t *)omAlloc(nV*sizeof(mpz_t)); mpz_t *pert_vector=(mpz_t *)omAlloc(niv*sizeof(mpz_t)); for(i=0; i < nV; i++) { mpz_init_set_si(ivtemp[i], (*ivtarget)[i]); mpz_init_set_si(pert_vector[i], (*ivtarget)[i]); } mpz_t ztmp; mpz_init(ztmp); // BOOLEAN isneg = FALSE; for(i=1; i0) { if(nflow == FALSE) { Xnlev = i / nV; nflow = TRUE; Overflow_Error = TRUE; Print("\n// Xlev = %d and the %d-th element is", Xnlev, i+1); PrintS("\n// ** OVERFLOW in \"Mfpertvector\": "); mpz_out_str( stdout, 10, pert_vector[i]); PrintS(" is greater than 2147483647 (max. integer representation)"); Print("\n// So vector[%d] := %d is wrong!!", i+1, (*result)[i]); } } } if(Overflow_Error == TRUE) { ivString(result, "new_vector"); } omFree(pert_vector); omFree(ivtemp); mpz_clear(ztmp); mpz_clear(tot_deg); mpz_clear(maxdeg); mpz_clear(inveps); mpz_clear(sing_int); rComplete(currRing); for(j=0; jm[j]; while(p!=NULL) { p_Setm(p,currRing); pIter(p); } } return result; } /**************************************************************** * Multiplication of two ideals element by element * * i.e. Let be A := (a_i) and B := (b_i), return C := (a_i*b_i) * * destroy A, keeps B * ****************************************************************/ static ideal MidMult(ideal A, ideal B) { int mA = IDELEMS(A), mB = IDELEMS(B); if(A==NULL || B==NULL) { return NULL; } if(mB < mA) { mA = mB; } ideal result = idInit(mA, 1); int i, k=0; for(i=0; im[k] = pMult(A->m[i], pCopy(B->m[i])); A->m[i]=NULL; if (result->m[k]!=NULL) { k++; } } idDelete(&A); idSkipZeroes(result); return result; } /********************************************************************* * G is a red. Groebner basis w.r.t. <_1 * * Gomega is an initial form ideal of w.r.t. a weight vector w * * M is a subideal of and M selft is a red. Groebner basis * * of the ideal w.r.t. <_w * * Let m_i = h1.gw1 + ... + hs.gws for each m_i in M; gwi in Gomega * * return F with n(F) = n(M) and f_i = h1.g1 + ... + hs.gs for each i* ********************************************************************/ static ideal MLifttwoIdeal(ideal Gw, ideal M, ideal G) { ideal Mtmp = idLift(Gw, M, NULL, FALSE, TRUE, TRUE, NULL); // If Gw is a GB, then isSB = TRUE, otherwise FALSE // So, it is better, if one tests whether Gw is a GB // in ideals.cc: // idLift (ideal mod, ideal submod,ideal * rest, BOOLEAN goodShape, // BOOLEAN isSB,BOOLEAN divide,matrix * unit) // Let be Mtmp = {m1,...,ms}, where mi=sum hij.in_gj, for all i=1,...,s // We compute F = {f1,...,fs}, where fi=sum hij.gj int i, j, nM = IDELEMS(Mtmp); ideal idpol, idLG; ideal F = idInit(nM, 1); for(i=0; im[i]); idLG = MidMult(idpol, G); idpol = NULL; F->m[i] = NULL; for(j=IDELEMS(idLG)-1; j>=0; j--) { F->m[i] = pAdd(F->m[i], idLG->m[j]); idLG->m[j]=NULL; } idDelete(&idLG); } idDelete(&Mtmp); return F; } //unused /* static void checkidealCC(ideal G, char* Ch) { int i,nmon=0,ntmp; int nG = IDELEMS(G); int n = nG-1; Print("\n//** Ideal %s besteht aus %d Polynomen mit ", Ch, nG); for(i=0; im[i]); nmon += ntmp; if(i != n) { Print("%d, ", ntmp); } else { Print(" bzw. %d ", ntmp); } } PrintS(" Monomen.\n"); Print("//** %s besitzt %d Monome.", Ch, nmon); PrintLn(); } */ //unused /* static void HeadidString(ideal L, char* st) { int i, nL = IDELEMS(L)-1; Print("// The head terms of the ideal %s = ", st); for(i=0; im[i]))); } Print(" %s;\n", pString(pHead(L->m[nL]))); } */ static inline int MivComp(intvec* iva, intvec* ivb) { assume(iva->length() == ivb->length()); int i; for(i=iva->length()-1; i>=0; i--) { if((*iva)[i] - (*ivb)[i] != 0) { return 0; } } return 1; } /********************************************** * Look for the smallest absolut value in vec * **********************************************/ static int MivAbsMax(intvec* vec) { int i,k; if((*vec)[0] < 0) { k = -(*vec)[0]; } else { k = (*vec)[0]; } for(i=1; i < (vec->length()); i++) { if((*vec)[i] < 0) { if(-(*vec)[i] > k) { k = -(*vec)[i]; } } else { if((*vec)[i] > k) { k = (*vec)[i]; } } } return k; } /************************************************************** * Look for the position of the smallest absolut value in vec * **************************************************************/ static int MivAbsMaxArg(intvec* vec) { int k = MivAbsMax(vec); int i=0; while(1) { if((*vec)[i] == k || (*vec)[i] == -k) { break; } i++; } return i; } /********************************************************************** * Compute a next weight vector between curr_weight and target_weight * * with respect to an ideal . * **********************************************************************/ /* static intvec* MwalkNextWeightCC(intvec* curr_weight, intvec* target_weight, ideal G) { BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; assume(currRing != NULL && curr_weight != NULL && target_weight != NULL && G != NULL); int nRing = currRing->N; int checkRed, j, nG = IDELEMS(G); intvec* ivtemp; mpz_t t_zaehler, t_nenner; mpz_init(t_zaehler); mpz_init(t_nenner); mpz_t s_zaehler, s_nenner, temp, MwWd; mpz_init(s_zaehler); mpz_init(s_nenner); mpz_init(temp); mpz_init(MwWd); mpz_t sing_int; mpz_init(sing_int); mpz_set_si(sing_int, 2147483647); mpz_t sing_int_half; mpz_init(sing_int_half); mpz_set_si(sing_int_half, 3*(1073741824/2)); mpz_t deg_w0_p1, deg_d0_p1; mpz_init(deg_w0_p1); mpz_init(deg_d0_p1); mpz_t sztn, sntz; mpz_init(sztn); mpz_init(sntz); mpz_t t_null; mpz_init(t_null); mpz_t ggt; mpz_init(ggt); mpz_t dcw; mpz_init(dcw); int gcd_tmp; intvec* diff_weight = MivSub(target_weight, curr_weight); intvec* diff_weight1 = MivSub(target_weight, curr_weight); poly g; for (j=0; jm[j]; if (g != NULL) { ivtemp = MExpPol(g); mpz_set_si(deg_w0_p1, MivDotProduct(ivtemp, curr_weight)); mpz_set_si(deg_d0_p1, MivDotProduct(ivtemp, diff_weight)); delete ivtemp; pIter(g); while (g != NULL) { ivtemp = MExpPol(g); mpz_set_si(MwWd, MivDotProduct(ivtemp, curr_weight)); mpz_sub(s_zaehler, deg_w0_p1, MwWd); if(mpz_cmp(s_zaehler, t_null) != 0) { mpz_set_si(MwWd, MivDotProduct(ivtemp, diff_weight)); mpz_sub(s_nenner, MwWd, deg_d0_p1); // check for 0 < s <= 1 if( (mpz_cmp(s_zaehler,t_null) > 0 && mpz_cmp(s_nenner, s_zaehler)>=0) || (mpz_cmp(s_zaehler, t_null) < 0 && mpz_cmp(s_nenner, s_zaehler)<=0)) { // make both positive if (mpz_cmp(s_zaehler, t_null) < 0) { mpz_neg(s_zaehler, s_zaehler); mpz_neg(s_nenner, s_nenner); } //compute a simple fraction of s cancel(s_zaehler, s_nenner); if(mpz_cmp(t_nenner, t_null) != 0) { mpz_mul(sztn, s_zaehler, t_nenner); mpz_mul(sntz, s_nenner, t_zaehler); if(mpz_cmp(sztn,sntz) < 0) { mpz_add(t_nenner, t_null, s_nenner); mpz_add(t_zaehler,t_null, s_zaehler); } } else { mpz_add(t_nenner, t_null, s_nenner); mpz_add(t_zaehler,t_null, s_zaehler); } } } pIter(g); delete ivtemp; } } } //Print("\n// Alloc Size = %d \n", nRing*sizeof(mpz_t)); mpz_t *vec=(mpz_t*)omAlloc(nRing*sizeof(mpz_t)); // there is no 0 0) { for (j=0; j 2^31. // If vec[j] doesn't overflow, define a weight vector. Otherwise, // report that overflow appears. In the second case, test whether the // the correctness of the new vector plays an important role for (j=0; j0) { mpz_mul_ui(s_zaehler, t_zaehler, (*diff_weight)[j]); } else { mpz_mul_ui(s_zaehler, t_zaehler, -(*diff_weight)[j]); mpz_neg(s_zaehler, s_zaehler); } mpz_add(sntz, s_nenner, s_zaehler); mpz_init_set(vec[j], sntz); #ifdef NEXT_VECTORS_CC Print("\n// j = %d ==> ", j); PrintS("("); mpz_out_str( stdout, 10, t_nenner); Print(" * %d)", (*curr_weight)[j]); Print(" + ("); mpz_out_str( stdout, 10, t_zaehler); Print(" * %d) = ", (*diff_weight)[j]); mpz_out_str( stdout, 10, s_nenner); PrintS(" + "); mpz_out_str( stdout, 10, s_zaehler); PrintS(" = "); mpz_out_str( stdout, 10, sntz); Print(" ==> vector[%d]: ", j); mpz_out_str(stdout, 10, vec[j]); #endif if(j==0) { mpz_set(ggt, sntz); } else { if(mpz_cmp_si(ggt,1) != 0) { mpz_gcd(ggt, ggt, sntz); } } } // reduce the vector with the gcd if(mpz_cmp_si(ggt,1) != 0) { for (j=0; j= 0) { goto REDUCTION; } } checkRed = 1; for (j=0; j10000) { for(j=0; j=0) { if(Overflow_Error == FALSE) { Overflow_Error = TRUE; PrintS("\n// ** OVERFLOW in \"MwalkNextWeightCC\": "); mpz_out_str( stdout, 10, vec[j]); PrintS(" is greater than 2147483647 (max. integer representation)\n"); //Print("// So vector[%d] := %d is wrong!!\n",j+1, vec[j]);// vec[j] is mpz_t } } } FINISH: delete diff_weight1; mpz_clear(t_zaehler); mpz_clear(t_nenner); mpz_clear(s_zaehler); mpz_clear(s_nenner); mpz_clear(sntz); mpz_clear(sztn); mpz_clear(temp); mpz_clear(MwWd); mpz_clear(deg_w0_p1); mpz_clear(deg_d0_p1); mpz_clear(ggt); omFree(vec); mpz_clear(sing_int_half); mpz_clear(sing_int); mpz_clear(dcw); mpz_clear(t_null); if(Overflow_Error == FALSE) { Overflow_Error = nError; } rComplete(currRing); for(j=0; jm[j]; while(p!=NULL) { p_Setm(p,currRing); pIter(p); } } return diff_weight; } */ /********************************************************************** * Compute a next weight vector between curr_weight and target_weight * * with respect to an ideal . * **********************************************************************/ static intvec* MwalkNextWeightCC(intvec* curr_weight, intvec* target_weight, ideal G) { BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; assume(currRing != NULL && curr_weight != NULL && target_weight != NULL && G != NULL); int nRing = currRing->N; int j, nG = IDELEMS(G); intvec* ivtemp; mpz_t t_zaehler, t_nenner; mpz_init(t_zaehler); mpz_init(t_nenner); mpz_t s_zaehler, s_nenner, temp, MwWd; mpz_init(s_zaehler); mpz_init(s_nenner); mpz_init(temp); mpz_init(MwWd); mpz_t sing_int; mpz_init(sing_int); mpz_set_si(sing_int, 2147483647); mpz_t sing_int_half; mpz_init(sing_int_half); mpz_set_si(sing_int_half, 3*(1073741824/2)); mpz_t deg_w0_p1, deg_d0_p1; mpz_init(deg_w0_p1); mpz_init(deg_d0_p1); mpz_t sztn, sntz; mpz_init(sztn); mpz_init(sntz); mpz_t t_null; mpz_init(t_null); mpz_t ggt; mpz_init(ggt); mpz_t dcw; mpz_init(dcw); int gcd_tmp; //intvec* diff_weight = MivSub(target_weight, curr_weight); intvec* diff_weight1 = new intvec(nRing); //MivSub(target_weight, curr_weight); poly g; // reduce the size of the entries of the current weight vector if(TEST_OPT_REDSB) { for (j=0; j10000 && test_w_in_ConeCC(G,diff_weight1)==1) { for(j=0; j100000) { for(j=0; j1000) { (*curr_weight)[j] = (*diff_weight1)[j]; j = MivAbsMaxArg(diff_weight1); (*diff_weight1)[j] = floor(0.1*(*diff_weight1)[j] + 0.5); } } } intvec* diff_weight = MivSub(target_weight, curr_weight); // compute a suitable next weight vector for (j=0; jm[j]; if (g != NULL) { ivtemp = MExpPol(g); mpz_set_si(deg_w0_p1, MivDotProduct(ivtemp, curr_weight)); mpz_set_si(deg_d0_p1, MivDotProduct(ivtemp, diff_weight)); delete ivtemp; pIter(g); while (g != NULL) { ivtemp = MExpPol(g); mpz_set_si(MwWd, MivDotProduct(ivtemp, curr_weight)); mpz_sub(s_zaehler, deg_w0_p1, MwWd); if(mpz_cmp(s_zaehler, t_null) != 0) { mpz_set_si(MwWd, MivDotProduct(ivtemp, diff_weight)); mpz_sub(s_nenner, MwWd, deg_d0_p1); // check for 0 < s <= 1 if( (mpz_cmp(s_zaehler,t_null) > 0 && mpz_cmp(s_nenner, s_zaehler)>=0) || (mpz_cmp(s_zaehler, t_null) < 0 && mpz_cmp(s_nenner, s_zaehler)<=0)) { // make both positive if (mpz_cmp(s_zaehler, t_null) < 0) { mpz_neg(s_zaehler, s_zaehler); mpz_neg(s_nenner, s_nenner); } //compute a simple fraction of s cancel(s_zaehler, s_nenner); if(mpz_cmp(t_nenner, t_null) != 0) { mpz_mul(sztn, s_zaehler, t_nenner); mpz_mul(sntz, s_nenner, t_zaehler); if(mpz_cmp(sztn,sntz) < 0) { mpz_add(t_nenner, t_null, s_nenner); mpz_add(t_zaehler,t_null, s_zaehler); } } else { mpz_add(t_nenner, t_null, s_nenner); mpz_add(t_zaehler,t_null, s_zaehler); } } } pIter(g); delete ivtemp; } } } //Print("\n// Alloc Size = %d \n", nRing*sizeof(mpz_t)); mpz_t *vec=(mpz_t*)omAlloc(nRing*sizeof(mpz_t)); // there is no 0 2^31. // If vec[j] doesn't overflow, define a weight vector. Otherwise, report that overflow // appears. In the second case, test whether the the correctness of the new vector plays // an important role for (j=0; j0) { mpz_mul_ui(s_zaehler, t_zaehler, (*diff_weight)[j]); } else { mpz_mul_ui(s_zaehler, t_zaehler, -(*diff_weight)[j]); mpz_neg(s_zaehler, s_zaehler); } mpz_add(sntz, s_nenner, s_zaehler); mpz_init_set(vec[j], sntz); #ifdef NEXT_VECTORS_CC Print("\n// j = %d ==> ", j); PrintS("("); mpz_out_str( stdout, 10, t_nenner); Print(" * %d)", (*curr_weight)[j]); Print(" + ("); mpz_out_str( stdout, 10, t_zaehler); Print(" * %d) = ", (*diff_weight)[j]); mpz_out_str( stdout, 10, s_nenner); PrintS(" + "); mpz_out_str( stdout, 10, s_zaehler); PrintS(" = "); mpz_out_str( stdout, 10, sntz); Print(" ==> vector[%d]: ", j); mpz_out_str(stdout, 10, vec[j]); #endif if(j==0) { mpz_set(ggt, sntz); } else { if(mpz_cmp_si(ggt,1) != 0) { mpz_gcd(ggt, ggt, sntz); } } } // reduce the vector with the gcd if(mpz_cmp_si(ggt,1) != 0) { for (j=0; j=0) { if(Overflow_Error == FALSE) { Overflow_Error = TRUE; PrintS("\n// ** OVERFLOW in \"MwalkNextWeightCC\": "); mpz_out_str( stdout, 10, vec[j]); PrintS(" is greater than 2147483647 (max. integer representation)\n"); //Print("// So vector[%d] := %d is wrong!!\n",j+1, vec[j]);// vec[j] is mpz_t } } } FINISH: delete diff_weight1; mpz_clear(t_zaehler); mpz_clear(t_nenner); mpz_clear(s_zaehler); mpz_clear(s_nenner); mpz_clear(sntz); mpz_clear(sztn); mpz_clear(temp); mpz_clear(MwWd); mpz_clear(deg_w0_p1); mpz_clear(deg_d0_p1); mpz_clear(ggt); omFree(vec); mpz_clear(sing_int_half); mpz_clear(sing_int); mpz_clear(dcw); mpz_clear(t_null); if(Overflow_Error == FALSE) { Overflow_Error = nError; } rComplete(currRing); for(j=0; jm[j]; while(p!=NULL) { p_Setm(p,currRing); pIter(p); } } return diff_weight; } /********************************************************************** * Compute an intermediate weight vector from iva to ivb w.r.t. * * the reduced Groebner basis G. * * Return NULL, if it is equal to iva or iva = avb. * **********************************************************************/ intvec* MkInterRedNextWeight(intvec* iva, intvec* ivb, ideal G) { intvec* tmp = new intvec(iva->length()); intvec* result; if(G == NULL) { return tmp; } if(MivComp(iva, ivb) == 1) { return tmp; } result = MwalkNextWeightCC(iva, ivb, G); if(MivComp(result, iva) == 1) { delete result; return tmp; } delete tmp; return result; } /******************************************************************** * define and execute a new ring which order is (a(vb),a(va),lp,C) * * ******************************************************************/ /*static ring VMrHomogeneous(intvec* va, intvec* vb) { if ((currRing->ppNoether)!=NULL) { pDelete(&(currRing->ppNoether)); } if (((sLastPrinted.rtyp>BEGIN_RING) && (sLastPrinted.rtypN; r->cf = currRing->cf; r->N = currRing->N; int nb = 4; //names char* Q; // In order to avoid the corrupted memory, do not change. r->names = (char **) omAlloc0(nv * sizeof(char_ptr)); for(i=0; inames[i]; r->names[i] = omStrDup(Q); } //weights: entries for 3 blocks: NULL Made:??? r->wvhdl = (int **)omAlloc0(nb * sizeof(int_ptr)); r->wvhdl[0] = (int*) omAlloc(nv*sizeof(int)); r->wvhdl[1] = (int*) omAlloc((nv)*sizeof(int)); for(i=0; iwvhdl[1][i] = (*vb)[i]; r->wvhdl[0][i] = (*va)[i]; } r->wvhdl[0][nv] = (*va)[nv]; // order: (1..1),a,lp,C r->order = (int *) omAlloc(nb * sizeof(int *)); r->block0 = (int *)omAlloc0(nb * sizeof(int *)); r->block1 = (int *)omAlloc0(nb * sizeof(int *)); // ringorder a for the first block: var 1..nv r->order[0] = ringorder_a; r->block0[0] = 1; r->block1[0] = nv; // ringorder a for the second block: var 2..nv r->order[1] = ringorder_a; r->block0[1] = 1; r->block1[1] = nv; // ringorder lp for the third block: var 2..nv r->order[2] = ringorder_lp; r->block0[2] = 1; r->block1[2] = nv; // ringorder C for the 4th block // it is very important within "idLift", // especially, by ring syz_ring=rCurrRingAssure_SyzComp(); // therefore, nb must be (nBlocks(currRing) + 1) r->order[3] = ringorder_C; // polynomial ring r->OrdSgn = 1; // complete ring intializations rComplete(r); return r; //rChangeCurrRing(r); } */ /************************************************************** * define and execute a new ring which order is (a(va),lp,C) * * ************************************************************/ static ring VMrDefault(intvec* va) { ring r = rCopy0(currRing,FALSE,FALSE); int i, nv = currRing->N; int nb = 4; /*weights: entries for 3 blocks: NULL Made:???*/ r->wvhdl = (int **)omAlloc0(nb * sizeof(int_ptr)); r->wvhdl[0] = (int*) omAlloc(nv*sizeof(int)); for(i=0; iwvhdl[0][i] = (*va)[i]; /* order: a,lp,C,0 */ r->order = (int *) omAlloc(nb * sizeof(int *)); r->block0 = (int *)omAlloc0(nb * sizeof(int *)); r->block1 = (int *)omAlloc0(nb * sizeof(int *)); // ringorder a for the first block: var 1..nv r->order[0] = ringorder_a; r->block0[0] = 1; r->block1[0] = nv; // ringorder lp for the second block: var 1..nv r->order[1] = ringorder_lp; r->block0[1] = 1; r->block1[1] = nv; // ringorder C for the third block // it is very important within "idLift", // especially, by ring syz_ring=rCurrRingAssure_SyzComp(); // therefore, nb must be (nBlocks(currRing) + 1) r->order[2] = ringorder_C; // the last block: everything is 0 r->order[3] = 0; // polynomial ring r->OrdSgn = 1; // complete ring intializations rComplete(r); return r; //rChangeCurrRing(r); } /**************************************************************** * define and execute a new ring with ordering (a(va),Wp(vb),C) * * **************************************************************/ static ring VMrRefine(intvec* va, intvec* vb) { ring r = rCopy0(currRing,FALSE,FALSE); int i, nv = currRing->N; int nb = 5; //weights: entries for 3 blocks: NULL Made:??? r->wvhdl = (int **)omAlloc0(nb * sizeof(int_ptr)); r->wvhdl[0] = (int*) omAlloc(nv*sizeof(int)); r->wvhdl[1] = (int*) omAlloc(nv*sizeof(int)); for(i=0; iwvhdl[0][i] = (*vb)[i]; r->wvhdl[1][i] = (*va)[i]; } // order: (1..1),a,lp,C r->order = (int *) omAlloc(nb * sizeof(int *)); r->block0 = (int *)omAlloc0(nb * sizeof(int *)); r->block1 = (int *)omAlloc0(nb * sizeof(int *)); // ringorder a for the first block: var 1..nv r->order[0] = ringorder_a; r->block0[0] = 1; r->block1[0] = nv; // ringorder Wp for the second block: var 1..nv r->order[1] = ringorder_a; r->block0[1] = 1; r->block1[1] = nv; // ringorder lp for the third block: var 1..nv r->order[2] = ringorder_lp; r->block0[2] = 1; r->block1[2] = nv; // ringorder C for the 4th block // it is very important within "idLift", // especially, by ring syz_ring=rCurrRingAssure_SyzComp(); // therefore, nb must be (nBlocks(currRing) + 1) r->order[3] = ringorder_C; // the last block: everything is 0 r->order[4] = 0; // complete ring intializations rComplete(r); //rChangeCurrRing(r); return r; } /***************************************************** * define and execute a new ring with ordering (M,C) * *****************************************************/ static ring VMatrDefault(intvec* va) { ring r = rCopy0(currRing,FALSE,FALSE); int i, nv = currRing->N; int nb = 4; /*weights: entries for 3 blocks: NULL Made:???*/ r->wvhdl = (int **)omAlloc0(nb * sizeof(int_ptr)); r->wvhdl[0] = (int*) omAlloc(nv*nv*sizeof(int)); r->wvhdl[1] =NULL; // (int*) omAlloc(nv*sizeof(int)); r->wvhdl[2]=NULL; r->wvhdl[3]=NULL; for(i=0; iwvhdl[0][i] = (*va)[i]; /* order: a,lp,C,0 */ r->order = (int *) omAlloc(nb * sizeof(int *)); r->block0 = (int *)omAlloc0(nb * sizeof(int *)); r->block1 = (int *)omAlloc0(nb * sizeof(int *)); // ringorder a for the first block: var 1..nv r->order[0] = ringorder_M; r->block0[0] = 1; r->block1[0] = nv; // ringorder C for the second block r->order[1] = ringorder_C; r->block0[1] = 1; r->block1[1] = nv; // ringorder C for the third block: var 1..nv r->order[2] = ringorder_C; r->block0[2] = 1; r->block1[2] = nv; // the last block: everything is 0 r->order[3] = 0; // complete ring intializations rComplete(r); //rChangeCurrRing(r); return r; } /*********************************************************** * define and execute a new ring with ordering (a(vb),M,C) * ***********************************************************/ static ring VMatrRefine(intvec* va, intvec* vb) { ring r = rCopy0(currRing,FALSE,FALSE); int i, nv = currRing->N; int nvs = nv*nv; int nb = 4; /*weights: entries for 3 blocks: NULL Made:???*/ r->wvhdl = (int **)omAlloc0(nb * sizeof(int_ptr)); r->wvhdl[0] = (int*) omAlloc(nv*sizeof(int)); r->wvhdl[1] = (int*) omAlloc(nvs*sizeof(int)); r->wvhdl[2]=NULL; r->wvhdl[3]=NULL; for(i=0; iwvhdl[1][i] = (*va)[i]; } for(i=0; iwvhdl[0][i] = (*vb)[i]; } /* order: a,lp,C,0 */ r->order = (int *) omAlloc(nb * sizeof(int *)); r->block0 = (int *)omAlloc0(nb * sizeof(int *)); r->block1 = (int *)omAlloc0(nb * sizeof(int *)); // ringorder a for the first block: var 1..nv r->order[0] = ringorder_a; r->block0[0] = 1; r->block1[0] = nv; // ringorder M for the second block: var 1..nv r->order[1] = ringorder_M; r->block0[1] = 1; r->block1[1] = nv; // ringorder C for the third block: var 1..nv r->order[2] = ringorder_C; r->block0[2] = 1; r->block1[2] = nv; // the last block: everything is 0 r->order[3] = 0; // complete ring intializations rComplete(r); //rChangeCurrRing(r); return r; } /********************************************************************** * define and execute a new ring which order is a lexicographic order * ***********************************************************************/ static void VMrDefaultlp(void) { ring r = rCopy0(currRing,FALSE,FALSE); int i, nv = currRing->N; int nb = rBlocks(currRing) + 1; /*weights: entries for 3 blocks: NULL Made:???*/ r->wvhdl = (int **)omAlloc0(nb * sizeof(int_ptr)); /* order: lp,C,0 */ r->order = (int *) omAlloc(nb * sizeof(int *)); r->block0 = (int *)omAlloc0(nb * sizeof(int *)); r->block1 = (int *)omAlloc0(nb * sizeof(int *)); /* ringorder lp for the first block: var 1..nv */ r->order[0] = ringorder_lp; r->block0[0] = 1; r->block1[0] = nv; /* ringorder C for the second block */ r->order[1] = ringorder_C; /* the last block: everything is 0 */ r->order[2] = 0; /*polynomial ring*/ r->OrdSgn = 1; /* complete ring intializations */ rComplete(r); rChangeCurrRing(r); } /*************************************************** * define a ring with parameters und change to it * * DefRingPar and DefRingParlp corrupt still memory * ****************************************************/ static void DefRingPar(intvec* va) { int i, nv = currRing->N; int nb = rBlocks(currRing) + 1; ring res=rCopy0(currRing,FALSE,FALSE); /*weights: entries for 3 blocks: NULL Made:???*/ res->wvhdl = (int **)omAlloc0(nb * sizeof(int_ptr)); res->wvhdl[0] = (int*) omAlloc(nv*sizeof(int)); for(i=0; iwvhdl[0][i] = (*va)[i]; /* order: a,lp,C,0 */ res->order = (int *) omAlloc(nb * sizeof(int *)); res->block0 = (int *)omAlloc0(nb * sizeof(int *)); res->block1 = (int *)omAlloc0(nb * sizeof(int *)); // ringorder a for the first block: var 1..nv res->order[0] = ringorder_a; res->block0[0] = 1; res->block1[0] = nv; // ringorder lp for the second block: var 1..nv res->order[1] = ringorder_lp; res->block0[1] = 1; res->block1[1] = nv; // ringorder C for the third block // it is very important within "idLift", // especially, by ring syz_ring=rCurrRingAssure_SyzComp(); // therefore, nb must be (nBlocks(currRing) + 1) res->order[2] = ringorder_C; // the last block: everything is 0 res->order[3] = 0; // polynomial ring res->OrdSgn = 1; // complete ring intializations rComplete(res); // execute the created ring rChangeCurrRing(res); } static void DefRingParlp(void) { int i, nv = currRing->N; ring r=rCopy0(currRing,FALSE,FALSE); int nb = rBlocks(currRing) + 1; /*weights: entries for 3 blocks: NULL Made:???*/ r->wvhdl = (int **)omAlloc0(nb * sizeof(int_ptr)); /* order: lp,C,0 */ r->order = (int *) omAlloc(nb * sizeof(int *)); r->block0 = (int *)omAlloc0(nb * sizeof(int *)); r->block1 = (int *)omAlloc0(nb * sizeof(int *)); /* ringorder lp for the first block: var 1..nv */ r->order[0] = ringorder_lp; r->block0[0] = 1; r->block1[0] = nv; /* ringorder C for the second block */ r->order[1] = ringorder_C; /* the last block: everything is 0 */ r->order[2] = 0; /*polynomial ring*/ r->OrdSgn = 1; // if (rParameter(currRing)!=NULL) // { // r->cf->extRing->qideal->m[0]=p_Copy(currRing->cf->extRing->qideal->m[0], currRing->cf->extRing); // int l=rPar(currRing); // r->cf->extRing->names=(char **)omAlloc(l*sizeof(char_ptr)); // // for(i=l-1;i>=0;i--) // { // rParameter(r)[i]=omStrDup(rParameter(currRing)[i]); // } // } // complete ring intializations rComplete(r); // execute the created ring rChangeCurrRing(r); } /************************************************************* * check whether one or more components of a vector are zero * *************************************************************/ static int isNolVector(intvec* hilb) { int i; for(i=hilb->length()-1; i>=0; i--) { if((* hilb)[i]==0) { return 1; } } return 0; } /************************************************************* * check whether one or more components of a vector are <= 0 * *************************************************************/ static int isNegNolVector(intvec* hilb) { int i; for(i=hilb->length()-1; i>=0; i--) { if((* hilb)[i]<=0) { return 1; } } return 0; } /************************************************************************** * Gomega is the initial ideal of G w. r. t. the current weight vector * * curr_weight. Check whether curr_weight lies on a border of the Groebner * * cone, i. e. check whether a monomial is divisible by a leading monomial * ***************************************************************************/ static ideal middleOfCone(ideal G, ideal Gomega) { BOOLEAN middle = FALSE; int i,j,N = IDELEMS(Gomega); poly p,lm,factor1,factor2; ideal Go = idCopy(G); // check whether leading monomials of G and Gomega coincide // and return NULL if not for(i=0; im[i]),pCopy(pHead(G->m[i]))))) { idDelete(&Go); return NULL; } } for(i=0; im[i]); lm = pCopy(Gomega->m[j]); pIter(p); while(p!=NULL) { if(pDivisibleBy(lm,p)) { if(middle == FALSE) { middle = TRUE; } factor1 = singclap_pdivide(pHead(p),lm,currRing); factor2 = pMult(pCopy(factor1),pCopy(Go->m[j])); pDelete(&factor1); Go->m[i] = pAdd((Go->m[i]),pNeg(pCopy(factor2))); pDelete(&factor2); } pIter(p); } pDelete(&lm); pDelete(&p); } } } if(middle == TRUE) { return Go; } idDelete(&Go); return NULL; } /****************************** Februar 2002 **************************** * G is a Groebner basis w.r.t. (a(curr_weight),lp) and * * we compute a GB of w.r.t. the lex. order by the perturbation walk * * its perturbation degree is tp_deg * * We call the following subfunction LastGB, if * * the computed intermediate weight vector or * * if the perturbed target weight vector does NOT lie n the correct cone * **************************************************************************/ static ideal LastGB(ideal G, intvec* curr_weight,int tp_deg) { BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; int i, nV = currRing->N; int nwalk=0, endwalks=0, nnwinC=1; int nlast = 0; ideal Gomega, M, F, Gomega1, Gomega2, M1,F1,result,ssG; ring newRing, oldRing, TargetRing; intvec* iv_M_lp; intvec* target_weight; intvec* iv_lp = Mivlp(nV); //define (1,0,...,0) intvec* pert_target_vector; intvec* ivNull = new intvec(nV); intvec* extra_curr_weight = new intvec(nV); intvec* next_weight; #ifndef BUCHBERGER_ALG intvec* hilb_func; #endif // to avoid (1,0,...,0) as the target vector intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) { (*last_omega)[i] = 1; } (*last_omega)[0] = 10000; ring EXXRing = currRing; // compute a pertubed weight vector of the target weight vector if(tp_deg > 1 && tp_deg <= nV) { //..25.03.03 VMrDefaultlp();// VMrDefault(target_weight); if (rParameter (currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } TargetRing = currRing; ssG = idrMoveR(G,EXXRing,currRing); iv_M_lp = MivMatrixOrderlp(nV); //target_weight = MPertVectorslp(ssG, iv_M_lp, tp_deg); target_weight = MPertVectors(ssG, iv_M_lp, tp_deg); delete iv_M_lp; pert_target_vector = target_weight; rChangeCurrRing(EXXRing); G = idrMoveR(ssG, TargetRing,currRing); } else { target_weight = Mivlp(nV); } //Print("\n// ring r%d_%d = %s;\n", tp_deg, nwalk, rString(currRing)); while(1) { nwalk++; nstep++; to=clock(); // compute a next weight vector next_weight = MkInterRedNextWeight(curr_weight,target_weight, G); xtnw=xtnw+clock()-to; #ifdef PRINT_VECTORS MivString(curr_weight, target_weight, next_weight); #endif if(Overflow_Error == TRUE) { newRing = currRing; nnwinC = 0; if(tp_deg == 1) { nlast = 1; } delete next_weight; //idElements(G, "G"); //Print("\n// ring r%d_%d = %s;\n", tp_deg, nwalk, rString(currRing)); break; } if(MivComp(next_weight, ivNull) == 1) { //Print("\n// ring r%d_%d = %s;\n", tp_deg, nwalk, rString(currRing)); newRing = currRing; delete next_weight; break; } if(MivComp(next_weight, target_weight) == 1) endwalks = 1; for(i=nV-1; i>=0; i--) { (*extra_curr_weight)[i] = (*curr_weight)[i]; } /* 06.11.01 NOT Changed */ for(i=nV-1; i>=0; i--) { (*curr_weight)[i] = (*next_weight)[i]; } oldRing = currRing; to=clock(); // compute an initial form ideal of w.r.t. "curr_vector" Gomega = MwalkInitialForm(G, curr_weight); xtif=xtif+clock()-to; #ifdef ENDWALKS if(endwalks == 1) { Print("\n// ring r%d_%d = %s;\n", tp_deg, nwalk, rString(currRing)); /* idElements(Gomega, "Gw"); headidString(Gomega, "Gw"); */ } #endif #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) { hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); } else { hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); } #endif // BUCHBERGER_ALG /* define a new ring that its ordering is "(a(curr_weight),lp) */ //..25.03.03 VMrDefault(curr_weight); if (rParameter (currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); to=clock(); /* compute a reduced Groebner basis of w.r.t. "newRing" */ #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif // BUCHBERGER_ALG xtstd=xtstd+clock()-to; /* change the ring to oldRing */ rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); to=clock(); /* compute a reduced Groebner basis of w.r.t. "newRing" */ F = MLifttwoIdeal(Gomega2, M1, G); xtlift=xtlift+clock()-to; idDelete(&M1); idDelete(&G); /* change the ring to newRing */ rChangeCurrRing(newRing); F1 = idrMoveR(F, oldRing,currRing); to=clock(); /* reduce the Groebner basis w.r.t. new ring */ G = kInterRedCC(F1, NULL); xtred=xtred+clock()-to; idDelete(&F1); if(endwalks == 1) { //Print("\n// ring r%d_%d = %s;\n", tp_deg, nwalk, rString(currRing)); break; } delete next_weight; }//while delete ivNull; if(tp_deg != 1) { //..25.03.03 VMrDefaultlp();//define and execute the ring "lp" if (rParameter (currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } F1 = idrMoveR(G, newRing,currRing); if(nnwinC == 0 || test_w_in_ConeCC(F1, pert_target_vector) != 1) { oldRing = currRing; rChangeCurrRing(newRing); G = idrMoveR(F1, oldRing,currRing); Print("\n// takes %d steps and calls the recursion of level %d:", nwalk, tp_deg-1); F1 = LastGB(G,curr_weight, tp_deg-1); } TargetRing = currRing; rChangeCurrRing(EXXRing); result = idrMoveR(F1, TargetRing,currRing); } else { if(nlast == 1) { //OMEGA_OVERFLOW_LASTGB: /* if(MivSame(curr_weight, iv_lp) == 1) if (rParameter(currRing) != NULL) DefRingParlp(); else VMrDefaultlp(); else if (rParameter(currRing) != NULL) DefRingPar(curr_weight); else VMrDefault(curr_weight); */ //..25.03.03 VMrDefaultlp();//define and execute the ring "lp" if (rParameter (currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } F1 = idrMoveR(G, newRing,currRing); //Print("\n// Apply \"std\" in ring r%d_%d = %s;\n", tp_deg, nwalk, rString(currRing)); G = MstdCC(F1); idDelete(&F1); newRing = currRing; } rChangeCurrRing(EXXRing); result = idrMoveR(G, newRing,currRing); } delete target_weight; delete last_omega; delete iv_lp; if(Overflow_Error == FALSE) { Overflow_Error = nError; } return(result); } /********************************************************** * check whether a polynomial of G has least 4 monomials * **********************************************************/ static int lengthpoly(ideal G) { int i; for(i=IDELEMS(G)-1; i>=0; i--) { if((G->m[i]!=NULL) /* len >=0 */ && (G->m[i]->next!=NULL) /* len >=1 */ && (G->m[i]->next->next!=NULL) /* len >=2 */ && (G->m[i]->next->next->next!=NULL) /* len >=3 */ && (G->m[i]->next->next->next->next!=NULL) /* len >=4*/ ) { return 1; } } return 0; } /***************************************** * return maximal polynomial length of G * *****************************************/ static int maxlengthpoly(ideal G) { int i,k,length=0; for(i=IDELEMS(G)-1; i>=0; i--) { k = pLength(G->m[i]); if(k>length) { length = k; } } return length; } /********************************************************* * check whether a polynomial of G has least 2 monomials * **********************************************************/ static int islengthpoly2(ideal G) { int i; for(i=IDELEMS(G)-1; i>=0; i--) { if((G->m[i]!=NULL) /* len >=0 */ && (G->m[i]->next!=NULL) /* len >=1 */ && (G->m[i]->next->next!=NULL)) /* len >=2 */ { return 1; } } return 0; } /* Implementation of the improved Groebner walk algorithm which is written by Quoc-Nam Tran (2000). One perturbs the original target weight vector, only if the next intermediate weight vector is equal to the current target weight vector. This must be repeated until the wanted reduced Groebner basis to reach. If the numbers of variables is big enough, the representation of the origin weight vector may be very big. Therefore, it is possible the intermediate weight vector doesn't stay in the correct Groebner cone. In this case we have just a reduced Groebner basis of the given ideal with respect to another monomial order. Then we have to compute a wanted reduced Groebner basis of it with respect to the given order. At the following subroutine we use the improved Buchberger algorithm or the changed perturbation walk algorithm with a decrased degree. */ /*************************************** * return the initial term of an ideal * ***************************************/ static ideal idHeadCC(ideal h) { int i, nH =IDELEMS(h); ideal m = idInit(nH,h->rank); for (i=nH-1;i>=0; i--) { if (h->m[i]!=NULL) { m->m[i]=pHead(h->m[i]); } } return m; } /********************************************** * check whether two head-ideals are the same * **********************************************/ static inline int test_G_GB_walk(ideal H0, ideal H1) { int i, nG = IDELEMS(H0); if(nG != IDELEMS(H1)) { return 0; } for(i=nG-1; i>=0; i--) { /* poly t; if((t=pSub(pCopy(H0->m[i]), pCopy(H1->m[i]))) != NULL) { pDelete(&t); return 0; } pDelete(&t); */ if(!pEqualPolys(H0->m[i],H1->m[i])) { return 0; } } return 1; } //unused /***************************************************** * find the maximal total degree of polynomials in G * *****************************************************/ /* static int Trandegreebound(ideal G) { int i, nG = IDELEMS(G); // int np=1; int nV = currRing->N; int degtmp, result = 0; intvec* ivUnit = Mivdp(nV); for(i=nG-1; i>=0; i--) { // find the maximal total degree of the polynomial G[i] degtmp = MwalkWeightDegree(G->m[i], ivUnit); if(degtmp > result) { result = degtmp; } } delete ivUnit; return result; } */ //unused /************************************************************************ * perturb the weight vector iva w.r.t. the ideal G. * * the monomial order of the current ring is the w_1 weight lex. order * * define w := d^(n-1)w_1+ d^(n-2)w_2, ...+ dw_(n-1)+ w_n * * where d := 1 + max{totdeg(g):g in G}*m, or * * d := (2*maxdeg*maxdeg + (nV+1)*maxdeg)*m; * ************************************************************************/ #if 0 static intvec* TranPertVector(ideal G, intvec* iva) { BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; int i, j; // int nG = IDELEMS(G); int nV = currRing->N; // define the sequence which expresses the current monomial ordering // w_1 = iva; w_2 = (1,0,..,0); w_n = (0,...,0,1,0) intvec* ivMat = MivMatrixOrder(iva); int mtmp, m=(*iva)[0]; for(i=ivMat->length(); i>=0; i--) { mtmp = (*ivMat)[i]; if(mtmp <0) { mtmp = -mtmp; } if(mtmp > m) { m = mtmp; } } // define the maximal total degree of polynomials of G mpz_t ndeg; mpz_init(ndeg); // 12 Juli 03 #ifndef UPPER_BOUND mpz_set_si(ndeg, Trandegreebound(G)+1); #else mpz_t ztmp; mpz_init(ztmp); mpz_t maxdeg; mpz_init_set_si(maxdeg, Trandegreebound(G)); //ndeg = (2*maxdeg*maxdeg + (nV+1)*maxdeg)*m;//Kalkbrenner (1999) mpz_pow_ui(ztmp, maxdeg, 2); mpz_mul_ui(ztmp, ztmp, 2); mpz_mul_ui(maxdeg, maxdeg, nV+1); mpz_add(ndeg, ztmp, maxdeg); mpz_mul_ui(ndeg, ndeg, m); mpz_clear(ztmp); //PrintS("\n// with the new upper degree bound (2d^2+(n+1)d)*m "); //Print("\n// where d = %d, n = %d and bound = %d", maxdeg, nV, ndeg); #endif //UPPER_BOUND #ifdef INVEPS_SMALL_IN_TRAN if(mpz_cmp_ui(ndeg, nV)>0 && nV > 3) { mpz_cdiv_q_ui(ndeg, ndeg, nV); } //PrintS("\n// choose the \"small\" inverse epsilon:"); //mpz_out_str(stdout, 10, ndeg); #endif mpz_t deg_tmp; mpz_init_set(deg_tmp, ndeg); mpz_t *ivres=( mpz_t *) omAlloc(nV*sizeof(mpz_t)); mpz_init_set_si(ivres[nV-1],1); for(i=nV-2; i>=0; i--) { mpz_init_set(ivres[i], deg_tmp); mpz_mul(deg_tmp, deg_tmp, ndeg); } mpz_t *ivtmp=(mpz_t *)omAlloc(nV*sizeof(mpz_t)); for(i=0; i= 0 ) { mpz_mul_ui(ivres[i], ivres[i], (*ivMat)[i*nV+j]); } else { mpz_mul_ui(ivres[i], ivres[i], -(*ivMat)[i*nV+j]); mpz_neg(ivres[i], ivres[i]); } mpz_add(ivtmp[j], ivtmp[j], ivres[i]); } } delete ivMat; int ntrue=0; for(i=0; i=0) { ntrue++; if(Overflow_Error == FALSE) { Overflow_Error = TRUE; PrintS("\n// ** OVERFLOW in \"Repr.Vector\": "); mpz_out_str( stdout, 10, ivtmp[i]); PrintS(" is greater than 2147483647 (max. integer representation)"); Print("\n// So vector[%d] := %d is wrong!!\n",i+1,(*repr_vector)[i]); } } } if(Overflow_Error == TRUE) { ivString(repr_vector, "repvector"); Print("\n// %d element(s) of it are overflow!!", ntrue); } if(Overflow_Error == FALSE) Overflow_Error=nError; omFree(ivres); omFree(ivtmp); mpz_clear(sing_int); mpz_clear(deg_tmp); mpz_clear(ndeg); return repr_vector; } #endif //unused #if 0 static intvec* TranPertVector_lp(ideal G) { BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; // int j, nG = IDELEMS(G); int i; int nV = currRing->N; // define the maximal total degree of polynomials of G mpz_t ndeg; mpz_init(ndeg); // 12 Juli 03 #ifndef UPPER_BOUND mpz_set_si(ndeg, Trandegreebound(G)+1); #else mpz_t ztmp; mpz_init(ztmp); mpz_t maxdeg; mpz_init_set_si(maxdeg, Trandegreebound(G)); //ndeg = (2*maxdeg*maxdeg + (nV+1)*maxdeg);//Kalkbrenner (1999) mpz_pow_ui(ztmp, maxdeg, 2); mpz_mul_ui(ztmp, ztmp, 2); mpz_mul_ui(maxdeg, maxdeg, nV+1); mpz_add(ndeg, ztmp, maxdeg); // PrintS("\n// with the new upper degree bound (2d^2+(n+1)d)*m "); // Print("\n// where d = %d, n = %d and bound = %d", // mpz_get_si(maxdeg), nV, mpz_get_si(ndeg)); mpz_clear(ztmp); #endif #ifdef INVEPS_SMALL_IN_TRAN if(mpz_cmp_ui(ndeg, nV)>0 && nV > 3) mpz_cdiv_q_ui(ndeg, ndeg, nV); //PrintS("\n// choose the \"small\" inverse epsilon:"); // mpz_out_str(stdout, 10, ndeg); #endif mpz_t deg_tmp; mpz_init_set(deg_tmp, ndeg); mpz_t *ivres=(mpz_t *)omAlloc(nV*sizeof(mpz_t)); mpz_init_set_si(ivres[nV-1], 1); for(i=nV-2; i>=0; i--) { mpz_init_set(ivres[i], deg_tmp); mpz_mul(deg_tmp, deg_tmp, ndeg); } mpz_t sing_int; mpz_init_set_ui(sing_int, 2147483647); intvec* repr_vector = new intvec(nV); int ntrue=0; for(i=0; i=0) { ntrue++; if(Overflow_Error == FALSE) { Overflow_Error = TRUE; PrintS("\n// ** OVERFLOW in \"Repr.Vector\": "); mpz_out_str( stdout, 10, ivres[i]); PrintS(" is greater than 2147483647 (max. integer representation)"); Print("\n// So vector[%d] := %d is wrong!!\n",i+1,(*repr_vector)[i]); } } } if(Overflow_Error == TRUE) { ivString(repr_vector, "repvector"); Print("\n// %d element(s) of it are overflow!!", ntrue); } if(Overflow_Error == FALSE) Overflow_Error = nError; omFree(ivres); mpz_clear(ndeg); mpz_clear(sing_int); return repr_vector; } #endif //unused #if 0 static intvec* RepresentationMatrix_Dp(ideal G, intvec* M) { BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; int i, j; int nV = currRing->N; intvec* ivUnit = Mivdp(nV); int degtmp, maxdeg = 0; for(i=IDELEMS(G)-1; i>=0; i--) { // find the maximal total degree of the polynomial G[i] degtmp = MwalkWeightDegree(G->m[i], ivUnit); if(degtmp > maxdeg) maxdeg = degtmp; } mpz_t ztmp; mpz_init_set_si(ztmp, maxdeg); mpz_t *ivres=(mpz_t *)omAlloc(nV*sizeof(mpz_t)); mpz_init_set_si(ivres[nV-1], 1); // (*ivres)[nV-1] = 1; for(i=nV-2; i>=0; i--) { mpz_init_set(ivres[i], ztmp); //(*ivres)[i] = ztmp; mpz_mul_ui(ztmp, ztmp, maxdeg); //ztmp *=maxdeg; } mpz_t *ivtmp=(mpz_t*)omAlloc(nV*sizeof(mpz_t)); for(i=0; i0) { ntrue++; if(Overflow_Error == FALSE) { Overflow_Error = TRUE; PrintS("\n// ** OVERFLOW in \"Repr.Matrix\": "); mpz_out_str( stdout, 10, ivtmp[i]); PrintS(" is greater than 2147483647 (max. integer representation)"); Print("\n// So vector[%d] := %d is wrong!!\n",i+1,(*repvector)[i]); } } } if(Overflow_Error == TRUE) { ivString(repvector, "repvector"); Print("\n// %d element(s) of it are overflow!!", ntrue); } if(Overflow_Error == FALSE) Overflow_Error = nError; mpz_clear(sing_int); mpz_clear(ztmp); omFree(ivtmp); omFree(ivres); return repvector; } #endif /***************************************************************************** * The following subroutine is the implementation of our first improved * * Groebner walk algorithm, i.e. the first altervative algorithm. * * First we use the Grobner walk algorithm and then we call the changed * * perturbation walk algorithm with decreased degree, if an intermediate * * weight vector is equal to the current target weight vector. * * This call will be only repeated until we get the wanted reduced Groebner * * basis or n times, where n is the numbers of variables. * *****************************************************************************/ // npwinc = 0, if curr_weight doesn't stay in the correct Groebner cone static ideal Rec_LastGB(ideal G, intvec* curr_weight, intvec* orig_target_weight, int tp_deg, int npwinc) { BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; // BOOLEAN nOverflow_Error = FALSE; clock_t tproc=0; clock_t tinput = clock(); int i, nV = currRing->N; int nwalk=0, endwalks=0, nnwinC=1; int nlast = 0; ideal Gomega, M, F, Gomega1, Gomega2, M1,F1,result,ssG; ring newRing, oldRing, TargetRing; intvec* iv_M_lp; intvec* target_weight; intvec* ivNull = new intvec(nV); //define (0,...,0) ring EXXRing = currRing; //int NEG=0; //19 juni 03 intvec* next_weight; #ifndef BUCHBERGER_ALG //08 Juli 03 intvec* hilb_func; #endif // to avoid (1,0,...,0) as the target vector intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) (*last_omega)[i] = 1; (*last_omega)[0] = 10000; BOOLEAN isGB = FALSE; // compute a pertubed weight vector of the target weight vector if(tp_deg > 1 && tp_deg <= nV) { ideal H0 = idHeadCC(G); if (rParameter (currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } TargetRing = currRing; ssG = idrMoveR(G,EXXRing,currRing); ideal H0_tmp = idrMoveR(H0,EXXRing,currRing); ideal H1 = idHeadCC(ssG); // Apply Lemma 2.2 in Collart et. al (1997) to check whether cone(k-1) is equal to cone(k) if(test_G_GB_walk(H0_tmp,H1)==1) { idDelete(&H0_tmp); idDelete(&H1); G = ssG; ssG = NULL; newRing = currRing; delete ivNull; if(npwinc != 0) { goto LastGB_Finish; } else { isGB = TRUE; goto KSTD_Finish; } } idDelete(&H0_tmp); idDelete(&H1); iv_M_lp = MivMatrixOrderlp(nV); target_weight = MPertVectors(ssG, iv_M_lp, tp_deg); delete iv_M_lp; //PrintS("\n// Input is not GB!!"); rChangeCurrRing(EXXRing); G = idrMoveR(ssG, TargetRing,currRing); if(Overflow_Error == TRUE) { //nOverflow_Error = Overflow_Error; //NEG = 1; newRing = currRing; goto JUNI_STD; } } while(1) { nwalk ++; nstep++; if(nwalk==1) { goto FIRST_STEP; } to=clock(); // compute an initial form ideal of w.r.t. "curr_vector" Gomega = MwalkInitialForm(G, curr_weight); xtif=xtif+clock()-to; #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) { hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); } else { hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); } #endif // BUCHBERGER_ALG oldRing = currRing; // defiNe a new ring that its ordering is "(a(curr_weight),lp) if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); to=clock(); // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif // BUCHBERGER_ALG xtstd=xtstd+clock()-to; // change the ring to oldRing rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); to=clock(); // compute a reduced Groebner basis of w.r.t. "newRing" by the lifting process F = MLifttwoIdeal(Gomega2, M1, G); xtlift=xtlift+clock()-to; idDelete(&M1); idDelete(&Gomega2); idDelete(&G); // change the ring to newRing rChangeCurrRing(newRing); F1 = idrMoveR(F, oldRing,currRing); to=clock(); // reduce the Groebner basis w.r.t. new ring G = kInterRedCC(F1, NULL); xtred=xtred+clock()-to; idDelete(&F1); if(endwalks == 1) { break; } FIRST_STEP: to=clock(); Overflow_Error = FALSE; // compute a next weight vector next_weight = MkInterRedNextWeight(curr_weight,target_weight, G); xtnw=xtnw+clock()-to; #ifdef PRINT_VECTORS MivString(curr_weight, target_weight, next_weight); #endif if(Overflow_Error == TRUE) { //PrintS("\n// ** The next vector does NOT stay in Cone!!\n"); #ifdef TEST_OVERFLOW goto LastGB_Finish; #endif nnwinC = 0; if(tp_deg == nV) { nlast = 1; } delete next_weight; break; } if(MivComp(next_weight, ivNull) == 1) { //newRing = currRing; delete next_weight; break; } if(MivComp(next_weight, target_weight) == 1) { if(tp_deg == nV) { endwalks = 1; } else { // REC_LAST_GB_ALT2: //nOverflow_Error = Overflow_Error; tproc=tproc+clock()-tinput; /*Print("\n// takes %d steps and calls \"Rec_LastGB\" (%d):", nwalk, tp_deg+1); */ G = Rec_LastGB(G,curr_weight, orig_target_weight, tp_deg+1,nnwinC); newRing = currRing; delete next_weight; break; } } for(i=nV-1; i>=0; i--) { (*curr_weight)[i] = (*next_weight)[i]; } delete next_weight; }//while delete ivNull; if(tp_deg != nV) { newRing = currRing; if (rParameter(currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } F1 = idrMoveR(G, newRing,currRing); if(nnwinC == 0 || test_w_in_ConeCC(F1, target_weight) != 1 ) { // nOverflow_Error = Overflow_Error; //Print("\n// takes %d steps and calls \"Rec_LastGB (%d):", tp_deg+1); tproc=tproc+clock()-tinput; F1 = Rec_LastGB(F1,curr_weight, orig_target_weight, tp_deg+1,nnwinC); } delete target_weight; TargetRing = currRing; rChangeCurrRing(EXXRing); result = idrMoveR(F1, TargetRing,currRing); } else { if(nlast == 1) { JUNI_STD: newRing = currRing; if (rParameter(currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } KSTD_Finish: if(isGB == FALSE) { F1 = idrMoveR(G, newRing,currRing); } else { F1 = G; } to=clock(); // Print("\n// apply the Buchberger's alg in ring = %s",rString(currRing)); // idElements(F1, "F1"); G = MstdCC(F1); xtextra=xtextra+clock()-to; idDelete(&F1); newRing = currRing; } LastGB_Finish: rChangeCurrRing(EXXRing); result = idrMoveR(G, newRing,currRing); } if(Overflow_Error == FALSE) { Overflow_Error=nError; } #ifdef TIME_TEST //Print("\n// \"Rec_LastGB\" (%d) took %d steps and %.2f sec.Overflow_Error (%d)", tp_deg, nwalk, ((double) tproc)/1000000, nOverflow_Error); #endif return(result); } /* The following subroutine is the implementation of our second improved Groebner walk algorithm, i.e. the second altervative algorithm. First we use the Grobner walk algorithm and then we call the changed perturbation walk algorithm with increased degree, if an intermediate weight vector is equal to the current target weight vector. This call will be only repeated until we get the wanted reduced Groebner basis or n times, where n is the numbers of variables. */ /****************************** * walk + recursive LastGB * ******************************/ ideal MAltwalk2(ideal Go, intvec* curr_weight, intvec* target_weight) { Set_Error(FALSE); Overflow_Error = FALSE; //BOOLEAN nOverflow_Error = FALSE; //Print("// pSetm_Error = (%d)", ErrorCheck()); #ifdef TIME_TEST xtif=0; xtstd=0; xtlift=0; xtred=0; xtnw=0; xtextra=0; xftinput = clock(); clock_t tostd, tproc; #endif nstep = 0; int i, nV = currRing->N; int nwalk=0, endwalks=0; // int nhilb = 1; ideal Gomega, M, F, Gomega1, Gomega2, M1, F1, G; //ideal G1; //ring endRing; ring newRing, oldRing; intvec* ivNull = new intvec(nV); intvec* next_weight; //intvec* extra_curr_weight = new intvec(nV); //intvec* hilb_func; intvec* exivlp = Mivlp(nV); ring XXRing = currRing; //Print("\n// ring r_input = %s;", rString(currRing)); #ifdef TIME_TEST to = clock(); #endif /* compute the reduced Groebner basis of the given ideal w.r.t. a "fast" monomial order, e.g. degree reverse lex. order (dp) */ G = MstdCC(Go); #ifdef TIME_TEST tostd=clock()-to; Print("\n// Computation of the first std took = %.2f sec", ((double) tostd)/1000000); #endif if(currRing->order[0] == ringorder_a) { goto NEXT_VECTOR; } while(1) { nwalk ++; nstep ++; #ifdef TIME_TEST to = clock(); #endif /* compute an initial form ideal of w.r.t. "curr_vector" */ Gomega = MwalkInitialForm(G, curr_weight); #ifdef TIME_TEST xtif=xtif+clock()-to; #endif /* if(Overflow_Error == TRUE) { for(i=nV-1; i>=0; i--) (*curr_weight)[i] = (*extra_curr_weight)[i]; delete extra_curr_weight; goto LAST_GB_ALT2; } */ oldRing = currRing; /* define a new ring that its ordering is "(a(curr_weight),lp) */ if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); #ifdef TIME_TEST to = clock(); #endif /* compute a reduced Groebner basis of w.r.t. "newRing" */ M = MstdhomCC(Gomega1); #ifdef TIME_TEST xtstd=xtstd+clock()-to; #endif /* change the ring to oldRing */ rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); #ifdef TIME_TEST to = clock(); #endif /* compute the reduced Groebner basis of w.r.t. "newRing" by the liftig process */ F = MLifttwoIdeal(Gomega2, M1, G); #ifdef TIME_TEST xtlift=xtlift+clock()-to; #endif idDelete(&M1); idDelete(&Gomega2); idDelete(&G); /* change the ring to newRing */ rChangeCurrRing(newRing); F1 = idrMoveR(F, oldRing,currRing); #ifdef TIME_TEST to = clock(); #endif /* reduce the Groebner basis w.r.t. newRing */ G = kInterRedCC(F1, NULL); #ifdef TIME_TEST xtred=xtred+clock()-to; #endif idDelete(&F1); if(endwalks == 1) break; NEXT_VECTOR: #ifdef TIME_TEST to = clock(); #endif /* compute a next weight vector */ next_weight = MkInterRedNextWeight(curr_weight,target_weight, G); #ifdef TIME_TEST xtnw=xtnw+clock()-to; #endif #ifdef PRINT_VECTORS MivString(curr_weight, target_weight, next_weight); #endif if(Overflow_Error == TRUE) { /* ivString(next_weight, "omega"); PrintS("\n// ** The weight vector does NOT stay in Cone!!\n"); */ #ifdef TEST_OVERFLOW goto TEST_OVERFLOW_OI; #endif newRing = currRing; if (rParameter(currRing) != NULL) { DefRingPar(target_weight); } else { rChangeCurrRing(VMrDefault(target_weight)); // Aenderung } F1 = idrMoveR(G, newRing,currRing); G = MstdCC(F1); idDelete(&F1); newRing = currRing; break; } if(MivComp(next_weight, ivNull) == 1) { newRing = currRing; delete next_weight; break; } if(MivComp(next_weight, target_weight) == 1) { if(MivSame(target_weight, exivlp)==1) { // LAST_GB_ALT2: //nOverflow_Error = Overflow_Error; #ifdef TIME_TEST tproc = clock()-xftinput; #endif //Print("\n// takes %d steps and calls the recursion of level 2:", nwalk); /* call the changed perturbation walk algorithm with degree 2 */ G = Rec_LastGB(G, curr_weight, target_weight, 2,1); newRing = currRing; delete next_weight; break; } endwalks = 1; } for(i=nV-1; i>=0; i--) { //(*extra_curr_weight)[i] = (*curr_weight)[i]; (*curr_weight)[i] = (*next_weight)[i]; } delete next_weight; } #ifdef TEST_OVERFLOW TEST_OVERFLOW_OI: #endif rChangeCurrRing(XXRing); G = idrMoveR(G, newRing,currRing); delete ivNull; delete exivlp; #ifdef TIME_TEST /*Print("\n// \"Main procedure\" took %d steps dnd %.2f sec. Overflow_Error (%d)", nwalk, ((double) tproc)/1000000, nOverflow_Error); */ TimeStringFractal(xftinput, tostd, xtif, xtstd, xtextra,xtlift, xtred,xtnw); //Print("\n// pSetm_Error = (%d)", ErrorCheck()); //Print("\n// Overflow_Error? (%d)", nOverflow_Error); //Print("\n// Awalk2 took %d steps!!", nstep); #endif return(G); } /************************************** * perturb the matrix order of "lex" * **************************************/ static intvec* NewVectorlp(ideal I) { int nV = currRing->N; intvec* iv_wlp = MivMatrixOrderlp(nV); intvec* result = Mfpertvector(I, iv_wlp); delete iv_wlp; return result; } int ngleich; intvec* Xsigma; intvec* Xtau; int xn; intvec* Xivinput; intvec* Xivlp; /******************************** * compute a next weight vector * ********************************/ static intvec* MWalkRandomNextWeight(ideal G, intvec* orig_M, intvec* target_weight, int weight_rad, int pert_deg) { assume(currRing != NULL && orig_M != NULL && target_weight != NULL && G->m[0] != NULL); //BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; BOOLEAN found_random_weight = FALSE; int i,nV = currRing->N; intvec* curr_weight = new intvec(nV); for(i=0; i 0) { while(k<10) { weight_norm = 0; while(weight_norm == 0) { for(i=0; i 1) { curr_weight1 = MPertVectors(G,orig_M,pert_deg); next_weight = MkInterRedNextWeight(curr_weight1,target_weight,G); delete curr_weight1; } else { next_weight = MkInterRedNextWeight(curr_weight,target_weight,G); } if(MivSame(curr_weight,next_weight)==1 || Overflow_Error == TRUE) { Overflow_Error = FALSE; delete next_weight; next_weight = MkInterRedNextWeight(curr_weight,target_weight,G); } G_test=MwalkInitialForm(G,next_weight); G_test1=MwalkInitialForm(G,next_weight1); // compare next weights if(Overflow_Error == FALSE) { if(found_random_weight == TRUE) { // random next weight vector found if(G_test1->m[0] != NULL && maxlengthpoly(G_test1) < maxlengthpoly(G_test)) { if(G_test2->m[0] != NULL && maxlengthpoly(G_test2) < maxlengthpoly(G_test1)) { for(i=0; im[0] != NULL && maxlengthpoly(G_test2) < maxlengthpoly(G_test)) { for(i=0; im[0] != NULL && maxlengthpoly(G_test1) < maxlengthpoly(G_test)) { for(i=0; im[0] != NULL && maxlengthpoly(G_test2) < maxlengthpoly(G_test)) { for(i=1; i w.r.t. the weight order * * otw, where G is a reduced GB w.r.t. the weight order cw. * * The new procedure Mwalk calls REC_GB. * ***************************************************************************/ static ideal REC_GB_Mwalk(ideal G, intvec* curr_weight, intvec* orig_target_weight, int tp_deg, int npwinc) { BOOLEAN nError = Overflow_Error; Overflow_Error = FALSE; int i, nV = currRing->N; int nwalk=0, endwalks=0, nnwinC=1, nlast = 0; ideal Gomega, M, F, Gomega1, Gomega2, M1,F1,result,ssG; ring newRing, oldRing, TargetRing; intvec* target_weight; intvec* ivNull = new intvec(nV); #ifndef BUCHBERGER_ALG intvec* hilb_func; // to avoid (1,0,...,0) as the target vector intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) { (*last_omega)[i] = 1; } (*last_omega)[0] = 10000; #endif BOOLEAN isGB = FALSE; ring EXXRing = currRing; // compute a pertubed weight vector of the target weight vector if(tp_deg > 1 && tp_deg <= nV) { ideal H0 = idHeadCC(G); if (rParameter(currRing) != NULL) { DefRingPar(orig_target_weight); } else { rChangeCurrRing(VMrDefault(orig_target_weight)); } TargetRing = currRing; ssG = idrMoveR(G,EXXRing,currRing); ideal H0_tmp = idrMoveR(H0,EXXRing,currRing); ideal H1 = idHeadCC(ssG); id_Delete(&H0,EXXRing); if(test_G_GB_walk(H0_tmp,H1)==1) { //Print("\n//REC_GB_Mwalk: input in %d-th recursive is a GB!\n",tp_deg); idDelete(&H0_tmp); idDelete(&H1); G = ssG; ssG = NULL; newRing = currRing; delete ivNull; if(npwinc == 0) { isGB = TRUE; goto KSTD_Finish; } else { goto LastGB_Finish; } } idDelete(&H0_tmp); idDelete(&H1); target_weight = MPertVectors(ssG, MivMatrixOrder(orig_target_weight), tp_deg); rChangeCurrRing(EXXRing); G = idrMoveR(ssG, TargetRing,currRing); } while(1) { nwalk ++; nstep++; if(nwalk == 1) { goto NEXT_STEP; } //Print("\n//REC_GB_Mwalk: Entering the %d-th step in the %d-th recursive:\n",nwalk,tp_deg); to = clock(); // compute an initial form ideal of w.r.t. "curr_vector" Gomega = MwalkInitialForm(G, curr_weight); xtif = xtif + clock()-to; #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) { hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); } else { hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); } #endif oldRing = currRing; // define a new ring with ordering "(a(curr_weight),lp) if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); to = clock(); // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif xtstd = xtstd + clock() - to; // change the ring to oldRing rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); to = clock(); F = MLifttwoIdeal(Gomega2, M1, G); xtlift = xtlift + clock() -to; idDelete(&M1); idDelete(&Gomega2); idDelete(&G); // change the ring to newRing rChangeCurrRing(newRing); F1 = idrMoveR(F, oldRing,currRing); to = clock(); // reduce the Groebner basis w.r.t. new ring G = kInterRedCC(F1, NULL); xtred = xtred + clock() -to; idDelete(&F1); if(endwalks == 1) { break; } NEXT_STEP: to = clock(); // compute a next weight vector intvec* next_weight = MkInterRedNextWeight(curr_weight,target_weight, G); xtnw = xtnw + clock() - to; #ifdef PRINT_VECTORS MivString(curr_weight, target_weight, next_weight); #endif if(Overflow_Error == TRUE) { //PrintS("\n//REC_GB_Mwalk: The computed vector does NOT stay in the correct cone!!\n"); nnwinC = 0; if(tp_deg == nV) { nlast = 1; } delete next_weight; break; } if(MivComp(next_weight, ivNull) == 1) { newRing = currRing; delete next_weight; break; } if(MivComp(next_weight, target_weight) == 1) { if(tp_deg == nV) { endwalks = 1; } else { G = REC_GB_Mwalk(G,curr_weight, orig_target_weight, tp_deg+1,nnwinC); newRing = currRing; delete next_weight; break; } } for(i=nV-1; i>=0; i--) { (*curr_weight)[i] = (*next_weight)[i]; } delete next_weight; } delete ivNull; if(tp_deg != nV) { newRing = currRing; if (rParameter(currRing) != NULL) { DefRingPar(orig_target_weight); } else { rChangeCurrRing(VMrDefault(orig_target_weight)); } F1 = idrMoveR(G, newRing,currRing); if(nnwinC == 0) { F1 = REC_GB_Mwalk(F1,curr_weight, orig_target_weight, tp_deg+1,nnwinC); } else { if(test_w_in_ConeCC(F1, target_weight) != 1) { F1 = REC_GB_Mwalk(F1,curr_weight, orig_target_weight,tp_deg+1,nnwinC); } } delete target_weight; TargetRing = currRing; rChangeCurrRing(EXXRing); result = idrMoveR(F1, TargetRing,currRing); } else { if(nlast == 1) { if (rParameter(currRing) != NULL) { DefRingPar(orig_target_weight); } else { rChangeCurrRing(VMrDefault(orig_target_weight)); } KSTD_Finish: if(isGB == FALSE) { F1 = idrMoveR(G, newRing,currRing); } else { F1 = G; } to=clock(); // apply Buchberger alg to compute a red. GB of F1 G = MstdCC(F1); xtextra=clock()-to; idDelete(&F1); newRing = currRing; } LastGB_Finish: rChangeCurrRing(EXXRing); result = idrMoveR(G, newRing,currRing); } if(Overflow_Error == FALSE) { Overflow_Error = nError; } #ifndef BUCHBERGER_ALG delete last_omega; #endif return(result); } // THE NEW GROEBNER WALK ALGORITHM // Groebnerwalk with a recursive "second" alternative GW, called REC_GB_Mwalk that only computes the last reduced GB ideal MwalkAlt(ideal Go, intvec* curr_weight, intvec* target_weight) { Set_Error(FALSE); Overflow_Error = FALSE; //Print("// pSetm_Error = (%d)", ErrorCheck()); clock_t tinput, tostd, tif=0, tstd=0, tlift=0, tred=0, tnw=0; xtif=0; xtstd=0; xtlift=0; xtred=0; xtnw=0; tinput = clock(); clock_t tim; nstep=0; int i; int nV = currRing->N; int nwalk=0; int endwalks=0; ideal Gomega, M, F, Gomega1, Gomega2, M1, F1, G; ring newRing, oldRing; intvec* ivNull = new intvec(nV); intvec* exivlp = Mivlp(nV); #ifndef BUCHBERGER_ALG intvec* hilb_func; #endif intvec* tmp_weight = new intvec(nV); for(i=nV-1; i>=0; i--) (*tmp_weight)[i] = (*curr_weight)[i]; // to avoid (1,0,...,0) as the target vector intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) (*last_omega)[i] = 1; (*last_omega)[0] = 10000; ring XXRing = currRing; to = clock(); // the monomial ordering of this current ring would be "dp" G = MstdCC(Go); tostd = clock()-to; if(currRing->order[0] == ringorder_a) goto NEXT_VECTOR; while(1) { nwalk ++; nstep ++; to = clock(); // compute an initial form ideal of w.r.t. "curr_vector" Gomega = MwalkInitialForm(G, curr_weight); tif = tif + clock()-to; oldRing = currRing; if(endwalks == 1) { /* compute a reduced Groebner basis of Gomega w.r.t. >>_cw by the recursive changed perturbation walk alg. */ tim = clock(); #ifdef CHECK_IDEAL_MWALK Print("\n// **** Groebnerwalk took %d steps and ", nwalk); PrintS("\n// **** call the rec. Pert. Walk to compute a red GB of:"); idString(Gomega, "Gomega"); #endif if(MivSame(exivlp, target_weight)==1) M = REC_GB_Mwalk(idCopy(Gomega), tmp_weight, curr_weight, 2,1); else goto NORMAL_GW; #ifdef TIME_TEST Print("\n// time for the last std(Gw) = %.2f sec", ((double) (clock()-tim)/1000000)); #endif /* #ifdef CHECK_IDEAL_MWALK idElements(Gomega, "G_omega"); headidString(Gomega, "Gw"); idElements(M, "M"); //headidString(M, "M"); #endif */ to = clock(); F = MLifttwoIdeal(Gomega, M, G); xtlift = xtlift + clock() - to; idDelete(&Gomega); idDelete(&M); idDelete(&G); oldRing = currRing; // create a new ring newRing if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } newRing = currRing; F1 = idrMoveR(F, oldRing,currRing); } else { NORMAL_GW: #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) { hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); } else { hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); } #endif // BUCHBERGER_ALG // define a new ring that its ordering is "(a(curr_weight),lp) if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); to = clock(); // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif tstd = tstd + clock() - to; // change the ring to oldRing rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); to = clock(); // compute a representation of the generators of submod (M) with respect // to those of mod (Gomega). // Gomega is a reduced Groebner basis w.r.t. the current ring. F = MLifttwoIdeal(Gomega2, M1, G); tlift = tlift + clock() - to; idDelete(&M1); idDelete(&Gomega2); idDelete(&G); // change the ring to newRing rChangeCurrRing(newRing); F1 = idrMoveR(F, oldRing,currRing); } to = clock(); // reduce the Groebner basis w.r.t. new ring G = kInterRedCC(F1, NULL); if(endwalks != 1) { tred = tred + clock() - to; } else { xtred = xtred + clock() - to; } idDelete(&F1); if(endwalks == 1) { break; } NEXT_VECTOR: to = clock(); // compute a next weight vector intvec* next_weight = MkInterRedNextWeight(curr_weight,target_weight,G); tnw = tnw + clock() - to; #ifdef PRINT_VECTORS MivString(curr_weight, target_weight, next_weight); #endif //if(test_w_in_ConeCC(G, next_weight) != 1) if(Overflow_Error == TRUE) { newRing = currRing; PrintS("\n// ** The computed vector does NOT stay in Cone!!\n"); if (rParameter(currRing) != NULL) { DefRingPar(target_weight); } else { rChangeCurrRing(VMrDefault(target_weight)); } F1 = idrMoveR(G, newRing,currRing); G = MstdCC(F1); idDelete(&F1); newRing = currRing; break; } if(MivComp(next_weight, ivNull) == 1) { newRing = currRing; delete next_weight; break; } if(MivComp(next_weight, target_weight) == 1) { endwalks = 1; } for(i=nV-1; i>=0; i--) { (*tmp_weight)[i] = (*curr_weight)[i]; (*curr_weight)[i] = (*next_weight)[i]; } delete next_weight; } rChangeCurrRing(XXRing); G = idrMoveR(G, newRing,currRing); delete tmp_weight; delete ivNull; delete exivlp; #ifdef TIME_TEST TimeString(tinput, tostd, tif, tstd, tlift, tred, tnw, nstep); //Print("\n// pSetm_Error = (%d)", ErrorCheck()); Print("\n// Overflow_Error? (%d)\n", Overflow_Error); #endif return(G); } /******************************* * THE GROEBNER WALK ALGORITHM * *******************************/ ideal Mwalk(ideal Go, intvec* orig_M, intvec* target_M, ring baseRing, int reduction, int printout) { // save current options BITSET save1 = si_opt_1; if(reduction == 0) { si_opt_1 &= (~Sy_bit(OPT_REDSB)); // no reduced Groebner basis si_opt_1 &= (~Sy_bit(OPT_REDTAIL)); // not tail reductions } Set_Error(FALSE); Overflow_Error = FALSE; //BOOLEAN endwalks = FALSE; #ifdef TIME_TEST clock_t tinput, tostd, tif=0, tstd=0, tlift=0, tred=0, tnw=0; xtif=0; xtstd=0; xtlift=0; xtred=0; xtnw=0; tinput = clock(); clock_t tim; #endif nstep=0; int i,nwalk; int nV = baseRing->N; ideal Gomega, M, F, FF, Gomega1, Gomega2, M1; ring newRing; ring XXRing = baseRing; ring targetRing; intvec* ivNull = new intvec(nV); intvec* curr_weight = new intvec(nV); intvec* target_weight = new intvec(nV); intvec* exivlp = Mivlp(nV); /* intvec* tmp_weight = new intvec(nV); for(i=0; i0; i--) { (*last_omega)[i] = 1; } (*last_omega)[0] = 10000; #endif rComplete(currRing); #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(Go,"//** Mwalk: Go"); } #endif if(target_M->length() == nV) { // define the target ring targetRing = VMrDefault(target_weight); } else { targetRing = VMatrDefault(target_M); } if(orig_M->length() == nV) { // define a new ring with ordering "(a(curr_weight),lp) //newRing = VMrDefault(curr_weight); newRing=VMrRefine(target_weight, curr_weight); } else { newRing = VMatrRefine(target_M,curr_weight); //newRing = VMatrDefault(orig_M); } rChangeCurrRing(newRing); if(printout > 2) { Print("\n//** Mrwalk: Current ring r = %s;\n", rString(currRing)); } #ifdef TIME_TEST to = clock(); #endif ideal G = MstdCC(idrMoveR(Go,baseRing,currRing)); #ifdef TIME_TEST tostd = clock()-to; #endif baseRing = currRing; nwalk = 0; while(1) { nwalk ++; nstep ++; //compute an initial form ideal of w.r.t. "curr_vector" #ifdef TIME_TEST to = clock(); #endif Gomega = MwalkInitialForm(G, curr_weight); #ifdef TIME_TEST tif = tif + clock()-to; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 1) { idString(Gomega,"//** Mwalk: Gomega"); } #endif if(reduction == 0) { FF = middleOfCone(G,Gomega); if(FF != NULL) { PrintS("middle of Cone"); idDelete(&G); G = idCopy(FF); idDelete(&FF); goto NEXT_VECTOR; } } #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) { hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); } else { hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); } #endif if(nwalk == 1) { if(orig_M->length() == nV) { // define a new ring with ordering "(a(curr_weight),lp) //newRing = VMrDefault(curr_weight); newRing=VMrRefine(target_weight, curr_weight); } else { newRing = VMatrRefine(target_M,curr_weight);//newRing = VMatrDefault(orig_M); } } else { if(target_M->length() == nV) { //define a new ring with ordering "(a(curr_weight),lp)" //newRing = VMrDefault(curr_weight); newRing=VMrRefine(target_weight, curr_weight); } else { //define a new ring with matrix ordering newRing = VMatrRefine(target_M,curr_weight); } } rChangeCurrRing(newRing); if(printout > 2) { Print("\n// Current ring r = %s;\n", rString(currRing)); } Gomega1 = idrMoveR(Gomega, baseRing,currRing); idDelete(&Gomega); // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef TIME_TEST to = clock(); #endif #ifndef BUCHBERGER_ALG M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #else M = kStd(Gomega1,NULL,testHomog,NULL,NULL,0,0,NULL); #endif #ifdef TIME_TEST tstd = tstd + clock() - to; #endif idSkipZeroes(M); #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(M, "//** Mwalk: M"); } #endif //change the ring to baseRing rChangeCurrRing(baseRing); M1 = idrMoveR(M, newRing,currRing); idDelete(&M); Gomega2 = idrMoveR(Gomega1, newRing,currRing); idDelete(&Gomega1); #ifdef TIME_TEST to = clock(); #endif // compute a representation of the generators of submod (M) with respect to those of mod (Gomega), // where Gomega is a reduced Groebner basis w.r.t. the current ring F = MLifttwoIdeal(Gomega2, M1, G); #ifdef TIME_TEST tlift = tlift + clock() - to; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(F, "//** Mwalk: F"); } #endif idDelete(&Gomega2); idDelete(&M1); rChangeCurrRing(newRing); // change the ring to newRing G = idrMoveR(F,baseRing,currRing); idDelete(&F); idSkipZeroes(G); #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(G, "//** Mwalk: G"); } #endif rChangeCurrRing(targetRing); G = idrMoveR(G,newRing,currRing); // test whether target cone is reached if(reduction !=0 && test_w_in_ConeCC(G,curr_weight) == 1) { baseRing = currRing; break; //endwalks = TRUE; } rChangeCurrRing(newRing); G = idrMoveR(G,targetRing,currRing); baseRing = currRing; NEXT_VECTOR: #ifdef TIME_TEST to = clock(); #endif intvec* next_weight = MwalkNextWeightCC(curr_weight,target_weight,G); #ifdef TIME_TEST tnw = tnw + clock() - to; #endif #ifdef PRINT_VECTORS if(printout > 0) { MivString(curr_weight, target_weight, next_weight); } #endif if(reduction ==0) { if(MivComp(curr_weight,next_weight)==1) { break; } } if(MivComp(target_weight,curr_weight) == 1) { break; } for(i=nV-1; i>=0; i--) { //(*tmp_weight)[i] = (*curr_weight)[i]; (*curr_weight)[i] = (*next_weight)[i]; } delete next_weight; } rChangeCurrRing(XXRing); ideal result = idrMoveR(G,baseRing,currRing); idDelete(&Go); idDelete(&G); //delete tmp_weight; delete ivNull; delete exivlp; #ifndef BUCHBERGER_ALG delete last_omega; #endif #ifdef TIME_TEST TimeString(tinput, tostd, tif, tstd, tlift, tred, tnw, nstep); //Print("\n// pSetm_Error = (%d)", ErrorCheck()); //Print("\n// Overflow_Error? (%d)\n", Overflow_Error); #endif if(printout > 0) { Print("\n//** Mwalk: Groebner Walk took %d steps.\n", nstep); } si_opt_1 = save1; //set original options return(result); } // THE RANDOM WALK ALGORITHM ideal Mrwalk(ideal Go, intvec* orig_M, intvec* target_M, int weight_rad, int pert_deg, int reduction, int printout) { BITSET save1 = si_opt_1; // save current options if(reduction == 0) { si_opt_1 &= (~Sy_bit(OPT_REDSB)); // no reduced Groebner basis si_opt_1 &= (~Sy_bit(OPT_REDTAIL)); // not tail reductions } Set_Error(FALSE); Overflow_Error = FALSE; BOOLEAN endwalks = FALSE; #ifdef TIME_TEST clock_t tinput, tostd, tif=0, tstd=0, tlift=0, tred=0, tnw=0; xtif=0; xtstd=0; xtlift=0; xtred=0; xtnw=0; tinput = clock(); clock_t tim; #endif nstep=0; int i,nwalk;//polylength; int nV = currRing->N; //check that weight radius is valid if(weight_rad < 0) { Werror("Invalid radius.\n"); return NULL; } //check that perturbation degree is valid if(pert_deg > nV || pert_deg < 1) { Werror("Invalid perturbation degree.\n"); return NULL; } ideal Gomega, M, F,FF, Gomega1, Gomega2, M1; ring newRing; ring targetRing; ring baseRing = currRing; ring XXRing = currRing; intvec* iv_M; intvec* ivNull = new intvec(nV); intvec* curr_weight = new intvec(nV); intvec* target_weight = new intvec(nV); intvec* next_weight= new intvec(nV); for(i=0; i0; i--) { (*last_omega)[i] = 1; } (*last_omega)[0] = 10000; #endif rComplete(currRing); if(target_M->length() == nV) { targetRing = VMrDefault(target_weight); // define the target ring } else { targetRing = VMatrDefault(target_M); } if(orig_M->length() == nV) { //newRing = VMrDefault(curr_weight); // define a new ring with ordering "(a(curr_weight),lp) newRing=VMrRefine(target_weight, curr_weight); } else { newRing = VMatrRefine(target_M,curr_weight);//newRing = VMatrDefault(orig_M); } rChangeCurrRing(newRing); #ifdef TIME_TEST to = clock(); #endif ideal G = MstdCC(idrMoveR(Go,baseRing,currRing)); #ifdef TIME_TEST tostd = clock()-to; #endif baseRing = currRing; nwalk = 0; #ifdef TIME_TEST to = clock(); #endif Gomega = MwalkInitialForm(G, curr_weight); // compute an initial form ideal of w.r.t. "curr_vector" #ifdef TIME_TEST tif = tif + clock()-to; //time for computing initial form ideal #endif while(1) { nwalk ++; nstep ++; #ifdef CHECK_IDEAL_MWALK if(printout > 1) { idString(Gomega,"//** Mrwalk: Gomega"); } #endif if(reduction == 0) { FF = middleOfCone(G,Gomega); if(FF != NULL) { idDelete(&G); G = idCopy(FF); idDelete(&FF); goto NEXT_VECTOR; } } #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) { hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); } else { hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); } #endif if(nwalk == 1) { if(orig_M->length() == nV) { /*newRing = VMrDefault(curr_weight); // define a new ring with ordering "(a(curr_weight),lp)*/ newRing=VMrRefine(target_weight, curr_weight); } else { newRing = VMatrRefine(target_M,curr_weight);//newRing = VMatrDefault(orig_M); } } else { if(target_M->length() == nV) { /*newRing = VMrDefault(curr_weight); // define a new ring with ordering "(a(curr_weight),lp)*/ newRing=VMrRefine(target_weight, curr_weight); } else { newRing = VMatrRefine(target_M,curr_weight); } } rChangeCurrRing(newRing); Gomega1 = idrMoveR(Gomega, baseRing,currRing); idDelete(&Gomega); // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef TIME_TEST to = clock(); #endif #ifndef BUCHBERGER_ALG M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #else M = kStd(Gomega1,NULL,testHomog,NULL,NULL,0,0,NULL); #endif #ifdef TIME_TEST tstd = tstd + clock() - to; #endif idSkipZeroes(M); #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(M, "//** Mrwalk: M"); } #endif //change the ring to baseRing rChangeCurrRing(baseRing); M1 = idrMoveR(M, newRing,currRing); idDelete(&M); Gomega2 = idrMoveR(Gomega1, newRing,currRing); idDelete(&Gomega1); #ifdef TIME_TEST to = clock(); #endif // compute a representation of the generators of submod (M) with respect to those of mod (Gomega), // where Gomega is a reduced Groebner basis w.r.t. the current ring F = MLifttwoIdeal(Gomega2, M1, G); #ifdef TIME_TEST tlift = tlift + clock() - to; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(F,"//** Mrwalk: F"); } #endif idDelete(&Gomega2); idDelete(&M1); rChangeCurrRing(newRing); // change the ring to newRing G = idrMoveR(F,baseRing,currRing); idDelete(&F); baseRing = currRing; #ifdef TIME_TEST to = clock(); tstd = tstd + clock() - to; #endif idSkipZeroes(G); #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(G,"//** Mrwalk: G"); } #endif rChangeCurrRing(targetRing); G = idrMoveR(G,newRing,currRing); // test whether target cone is reached if(reduction !=0 && test_w_in_ConeCC(G,curr_weight) == 1) { baseRing = currRing; break; } rChangeCurrRing(newRing); G = idrMoveR(G,targetRing,currRing); baseRing = currRing; NEXT_VECTOR: #ifdef TIME_TEST to = clock(); #endif next_weight = MwalkNextWeightCC(curr_weight,target_weight,G); #ifdef TIME_TEST tnw = tnw + clock() - to; #endif #ifdef TIME_TEST to = clock(); #endif Gomega = MwalkInitialForm(G, next_weight); // compute an initial form ideal of w.r.t. "curr_vector" #ifdef TIME_TEST tif = tif + clock()-to; //time for computing initial form ideal #endif //lengthpoly(Gomega) = 1 if there is a polynomial in Gomega with at least 3 monomials and 0 otherwise //polylength = lengthpoly(Gomega); if(lengthpoly(Gomega) > 0) { //there is a polynomial in Gomega with at least 3 monomials, //low-dimensional facet of the cone delete next_weight; if(target_M->length() == nV) { //iv_M = MivMatrixOrder(curr_weight); iv_M = MivMatrixOrderRefine(curr_weight,target_M); } else { iv_M = MivMatrixOrderRefine(curr_weight,target_M); } #ifdef TIME_TEST to = clock(); #endif next_weight = MWalkRandomNextWeight(G, iv_M, target_weight, weight_rad, pert_deg); #ifdef TIME_TEST tnw = tnw + clock() - to; #endif idDelete(&Gomega); #ifdef TIME_TEST to = clock(); #endif Gomega = MwalkInitialForm(G, next_weight); #ifdef TIME_TEST tif = tif + clock()-to; //time for computing initial form ideal #endif delete iv_M; } // test whether target weight vector is reached if(MivComp(next_weight, ivNull) == 1 || MivComp(target_weight,curr_weight) == 1) { baseRing = currRing; delete next_weight; break; } if(reduction ==0) { if(MivComp(curr_weight,next_weight)==1) { break; } } #ifdef PRINT_VECTORS if(printout > 0) { MivString(curr_weight, target_weight, next_weight); } #endif for(i=nV-1; i>=0; i--) { (*curr_weight)[i] = (*next_weight)[i]; } delete next_weight; } baseRing = currRing; rChangeCurrRing(XXRing); ideal result = idrMoveR(G,baseRing,currRing); idDelete(&G); delete ivNull; #ifndef BUCHBERGER_ALG delete last_omega; #endif if(printout > 0) { Print("\n//** Mrwalk: Groebner Walk took %d steps.\n", nstep); } #ifdef TIME_TEST TimeString(tinput, tostd, tif, tstd, tlift, tred, tnw, nstep); //Print("\n// pSetm_Error = (%d)", ErrorCheck()); //Print("\n// Overflow_Error? (%d)\n", Overflow_Error); #endif si_opt_1 = save1; //set original options return(result); } /**************************************************************/ /* Implementation of the perturbation walk algorithm */ /**************************************************************/ /* If the perturbed target weight vector or an intermediate weight vector doesn't stay in the correct Groebner cone, we have only a reduced Groebner basis for the given ideal with respect to a monomial order which differs to the given order. Then we have to compute the wanted reduced Groebner basis for it. For this, we can use 1) the improved Buchberger algorithm or 2) the changed perturbation walk algorithm with a decreased degree. */ // if nP = 0 use kStd, else call LastGB ideal Mpwalk(ideal Go, int op_deg, int tp_deg,intvec* curr_weight, intvec* target_weight, int nP, int reduction, int printout) { BITSET save1 = si_opt_1; // save current options if(reduction == 0) { si_opt_1 &= (~Sy_bit(OPT_REDSB)); // no reduced Groebner basis si_opt_1 &= (~Sy_bit(OPT_REDTAIL)); // not tail reductions } Set_Error(FALSE ); Overflow_Error = FALSE; //Print("// pSetm_Error = (%d)", ErrorCheck()); #ifdef TIME_TEST clock_t tinput, tostd, tif=0, tstd=0, tlift=0, tred=0, tnw=0; xtextra=0; xtif=0; xtstd=0; xtlift=0; xtred=0; xtnw=0; tinput = clock(); clock_t tim; #endif nstep = 0; int i, ntwC=1, ntestw=1, nV = currRing->N; //check that perturbation degree is valid if(op_deg < 1 || tp_deg < 1 || op_deg > nV || tp_deg > nV) { Werror("Invalid perturbation degree.\n"); return NULL; } BOOLEAN endwalks = FALSE; ideal Gomega, M, F, FF, G, Gomega1, Gomega2, M1,F1,Eresult,ssG; ring newRing, oldRing, TargetRing; intvec* iv_M_dp; intvec* iv_M_lp; intvec* exivlp = Mivlp(nV); intvec* orig_target = target_weight; intvec* pert_target_vector = target_weight; intvec* ivNull = new intvec(nV); intvec* iv_dp = MivUnit(nV);// define (1,1,...,1) #ifndef BUCHBERGER_ALG intvec* hilb_func; #endif intvec* next_weight; // to avoid (1,0,...,0) as the target vector intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) (*last_omega)[i] = 1; (*last_omega)[0] = 10000; ring XXRing = currRing; #ifdef TIME_TEST to = clock(); #endif // perturbs the original vector if(MivComp(curr_weight, iv_dp) == 1) //rOrdStr(currRing) := "dp" { G = MstdCC(Go); #ifdef TIME_TEST tostd = clock()-to; #endif if(op_deg != 1){ iv_M_dp = MivMatrixOrderdp(nV); //ivString(iv_M_dp, "iv_M_dp"); curr_weight = MPertVectors(G, iv_M_dp, op_deg); } } else { //define ring order := (a(curr_weight),lp); /* if (rParameter(currRing) != NULL) DefRingPar(curr_weight); else rChangeCurrRing(VMrDefault(curr_weight)); */ rChangeCurrRing(VMrRefine(target_weight,curr_weight)); G = idrMoveR(Go, XXRing,currRing); G = MstdCC(G); #ifdef TIME_TEST tostd = clock()-to; #endif if(op_deg != 1){ iv_M_dp = MivMatrixOrder(curr_weight); curr_weight = MPertVectors(G, iv_M_dp, op_deg); } } delete iv_dp; if(op_deg != 1) delete iv_M_dp; ring HelpRing = currRing; // perturbs the target weight vector if(tp_deg > 1 && tp_deg <= nV) { /* if (rParameter(currRing) != NULL) DefRingPar(target_weight); else rChangeCurrRing(VMrDefault(target_weight)); */ rChangeCurrRing(VMrRefine(target_weight,curr_weight)); TargetRing = currRing; ssG = idrMoveR(G,HelpRing,currRing); if(MivSame(target_weight, exivlp) == 1) { iv_M_lp = MivMatrixOrderlp(nV); target_weight = MPertVectors(ssG, iv_M_lp, tp_deg); } else { iv_M_lp = MivMatrixOrder(target_weight); target_weight = MPertVectors(ssG, iv_M_lp, tp_deg); } delete iv_M_lp; pert_target_vector = target_weight; rChangeCurrRing(HelpRing); G = idrMoveR(ssG, TargetRing,currRing); } if(printout > 0) { Print("\n//** Mpwalk: Perturbation Walk of degree (%d,%d):",op_deg,tp_deg); #ifdef PRINT_VECTORS ivString(curr_weight, "//** Mpwalk: new current weight"); ivString(target_weight, "//** Mpwalk: new target weight"); #endif } while(1) { nstep ++; #ifdef TIME_TEST to = clock(); #endif // compute an initial form ideal of w.r.t. the weight vector // "curr_weight" Gomega = MwalkInitialForm(G, curr_weight); #ifdef TIME_TEST tif = tif + clock()-to; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 1) { idString(Gomega,"//** Mpwalk: Gomega"); } #endif if(reduction == 0 && nstep > 1) { FF = middleOfCone(G,Gomega); if(FF != NULL) { idDelete(&G); G = idCopy(FF); idDelete(&FF); goto NEXT_VECTOR; } } #ifdef ENDWALKS if(endwalks == TRUE) { if(printout > 0) { Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); } //idElements(G, "G"); //headidString(G, "G"); } #endif #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); else hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); #endif // BUCHBERGER_ALG oldRing = currRing; // define a new ring with ordering "(a(curr_weight),lp) /* if (rParameter(currRing) != NULL) DefRingPar(curr_weight); else rChangeCurrRing(VMrDefault(curr_weight)); */ rChangeCurrRing(VMrRefine(target_weight,curr_weight)); newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); #ifdef ENDWALKS if(endwalks==TRUE) { if(printout > 0) { Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); //idElements(Gomega1, "Gw"); //headidString(Gomega1, "headGw"); PrintS("\n// compute a rGB of Gw:\n"); } #ifndef BUCHBERGER_ALG ivString(hilb_func, "w"); #endif } #endif #ifdef TIME_TEST tim = clock(); to = clock(); #endif // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif if(endwalks == TRUE) { #ifdef TIME_TEST xtstd = xtstd+clock()-to; #endif #ifdef ENDWALKS if(printout > 1) { Print("\n// time for the last std(Gw) = %.2f sec\n", ((double) clock())/1000000 -((double)tim) /1000000); } #endif } else { #ifdef TIME_TEST tstd=tstd+clock()-to; #endif } #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(M,"//** Mpwalk: M"); } #endif // change the ring to oldRing rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); #ifdef TIME_TEST to=clock(); #endif /* compute a representation of the generators of submod (M) with respect to those of mod (Gomega). Gomega is a reduced Groebner basis w.r.t. the current ring */ F = MLifttwoIdeal(Gomega2, M1, G); #ifdef TIME_TEST if(endwalks == FALSE) tlift = tlift+clock()-to; else xtlift=clock()-to; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(F,"//** Mpwalk: F"); } #endif idDelete(&M1); idDelete(&Gomega2); idDelete(&G); // change the ring to newRing rChangeCurrRing(newRing); if(reduction == 0) { G = idrMoveR(F,oldRing,currRing); } else { F1 = idrMoveR(F, oldRing,currRing); if(printout > 2) { PrintS("\n //** Mpwalk: reduce the Groebner basis.\n"); } #ifdef TIME_TEST to=clock(); #endif G = kInterRedCC(F1, NULL); #ifdef TIME_TEST if(endwalks == FALSE) tred = tred+clock()-to; else xtred=clock()-to; #endif idDelete(&F1); } if(endwalks == TRUE) break; NEXT_VECTOR: #ifdef TIME_TEST to=clock(); #endif // compute a next weight vector next_weight = MkInterRedNextWeight(curr_weight,target_weight, G); #ifdef TIME_TEST tnw=tnw+clock()-to; #endif #ifdef PRINT_VECTORS if(printout > 0) { MivString(curr_weight, target_weight, next_weight); } #endif if(Overflow_Error == TRUE) { ntwC = 0; //ntestomega = 1; //Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); //idElements(G, "G"); delete next_weight; goto FINISH_160302; } if(MivComp(next_weight, ivNull) == 1){ newRing = currRing; delete next_weight; //Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); break; } if(MivComp(next_weight, target_weight) == 1) endwalks = TRUE; for(i=nV-1; i>=0; i--) (*curr_weight)[i] = (*next_weight)[i]; delete next_weight; }//end of while-loop if(tp_deg != 1) { FINISH_160302: if(MivSame(orig_target, exivlp) == 1) { /* if (rParameter(currRing) != NULL) DefRingParlp(); else VMrDefaultlp(); else if (rParameter(currRing) != NULL) DefRingPar(orig_target); else*/ rChangeCurrRing(VMrDefault(orig_target)); } TargetRing=currRing; F1 = idrMoveR(G, newRing,currRing); /* #ifdef CHECK_IDEAL_MWALK headidString(G, "G"); #endif */ // check whether the pertubed target vector stays in the correct cone if(ntwC != 0){ ntestw = test_w_in_ConeCC(F1, pert_target_vector); } if( ntestw != 1 || ntwC == 0) { if(ntestw != 1 && printout >2) { ivString(pert_target_vector, "tau"); PrintS("\n// ** perturbed target vector doesn't stay in cone!!"); Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); //idElements(F1, "G"); } // LastGB is "better" than the kStd subroutine to=clock(); ideal eF1; if(nP == 0 || tp_deg == 1 || MivSame(orig_target, exivlp) != 1){ // PrintS("\n// ** calls \"std\" to compute a GB"); eF1 = MstdCC(F1); idDelete(&F1); } else { // PrintS("\n// ** calls \"LastGB\" to compute a GB"); rChangeCurrRing(newRing); ideal F2 = idrMoveR(F1, TargetRing,currRing); eF1 = LastGB(F2, curr_weight, tp_deg-1); F2=NULL; } xtextra=clock()-to; ring exTargetRing = currRing; rChangeCurrRing(XXRing); Eresult = idrMoveR(eF1, exTargetRing,currRing); } else{ rChangeCurrRing(XXRing); Eresult = idrMoveR(F1, TargetRing,currRing); } } else { rChangeCurrRing(XXRing); Eresult = idrMoveR(G, newRing,currRing); } si_opt_1 = save1; //set original options, e. g. option(RedSB) delete ivNull; if(tp_deg != 1) delete target_weight; if(op_deg != 1 ) delete curr_weight; delete exivlp; delete last_omega; #ifdef TIME_TEST TimeStringFractal(tinput, tostd, tif+xtif, tstd+xtstd,0, tlift+xtlift, tred+xtred, tnw+xtnw); //Print("\n// pSetm_Error = (%d)", ErrorCheck()); //Print("\n// It took %d steps and Overflow_Error? (%d)\n", nstep, Overflow_Error); #endif if(printout > 0) { Print("\n//** Mpwalk: Perturbation Walk took %d steps.\n", nstep); } return(Eresult); } /******************************************************* * THE PERTURBATION WALK ALGORITHM WITH RANDOM ELEMENT * *******************************************************/ ideal Mprwalk(ideal Go, intvec* orig_M, intvec* target_M, int weight_rad, int op_deg, int tp_deg, int nP, int reduction, int printout) { BITSET save1 = si_opt_1; // save current options if(reduction == 0) { si_opt_1 &= (~Sy_bit(OPT_REDSB)); // no reduced Groebner basis si_opt_1 &= (~Sy_bit(OPT_REDTAIL)); // not tail reductions } Set_Error(FALSE); Overflow_Error = FALSE; //Print("// pSetm_Error = (%d)", ErrorCheck()); #ifdef TIME_TEST clock_t tinput, tostd, tif=0, tstd=0, tlift=0, tred=0, tnw=0; xtextra=0; xtif=0; xtstd=0; xtlift=0; xtred=0; xtnw=0; tinput = clock(); clock_t tim; #endif nstep = 0; int i, ntwC=1, ntestw=1, nV = currRing->N; //polylength //check that weight radius is valid if(weight_rad < 0) { Werror("Invalid radius.\n"); return NULL; } //check that perturbation degree is valid if(op_deg < 1 || tp_deg < 1 || op_deg > nV || tp_deg > nV) { Werror("Invalid perturbation degree.\n"); return NULL; } BOOLEAN endwalks = FALSE; ideal Gomega, M, F, FF, G, Gomega1, Gomega2, M1,F1,Eresult,ssG; ring newRing, oldRing, TargetRing; intvec* iv_M; intvec* iv_M_dp; intvec* iv_M_lp; intvec* exivlp = Mivlp(nV); intvec* curr_weight = new intvec(nV); intvec* target_weight = new intvec(nV); for(i=0; i0; i--) (*last_omega)[i] = 1; (*last_omega)[0] = 10000; ring XXRing = currRing; // perturbs the original vector if(orig_M->length() == nV) { if(MivComp(curr_weight, iv_dp) == 1) //rOrdStr(currRing) := "dp" { #ifdef TIME_TEST to = clock(); #endif G = MstdCC(Go); #ifdef TIME_TEST tostd = clock()-to; #endif if(op_deg != 1) { iv_M_dp = MivMatrixOrderdp(nV); curr_weight = MPertVectors(G, iv_M_dp, op_deg); } } else { //define ring order := (a(curr_weight),lp); if (rParameter(currRing) != NULL) DefRingPar(curr_weight); else rChangeCurrRing(VMrDefault(curr_weight)); G = idrMoveR(Go, XXRing,currRing); #ifdef TIME_TEST to = clock(); #endif G = MstdCC(G); #ifdef TIME_TEST tostd = clock()-to; #endif if(op_deg != 1) { iv_M_dp = MivMatrixOrder(curr_weight); curr_weight = MPertVectors(G, iv_M_dp, op_deg); } } } else { rChangeCurrRing(VMatrDefault(orig_M)); G = idrMoveR(Go, XXRing,currRing); #ifdef TIME_TEST to = clock(); #endif G = MstdCC(G); #ifdef TIME_TEST tostd = clock()-to; #endif if(op_deg != 1) { curr_weight = MPertVectors(G, orig_M, op_deg); } } delete iv_dp; if(op_deg != 1) delete iv_M_dp; ring HelpRing = currRing; // perturbs the target weight vector if(target_M->length() == nV) { if(tp_deg > 1 && tp_deg <= nV) { if (rParameter(currRing) != NULL) DefRingPar(target_weight); else rChangeCurrRing(VMrDefault(target_weight)); TargetRing = currRing; ssG = idrMoveR(G,HelpRing,currRing); if(MivSame(target_weight, exivlp) == 1) { iv_M_lp = MivMatrixOrderlp(nV); target_weight = MPertVectors(ssG, iv_M_lp, tp_deg); } else { iv_M_lp = MivMatrixOrder(target_weight); target_weight = MPertVectors(ssG, iv_M_lp, tp_deg); } delete iv_M_lp; pert_target_vector = target_weight; rChangeCurrRing(HelpRing); G = idrMoveR(ssG, TargetRing,currRing); } } else { if(tp_deg > 1 && tp_deg <= nV) { rChangeCurrRing(VMatrDefault(target_M)); TargetRing = currRing; ssG = idrMoveR(G,HelpRing,currRing); target_weight = MPertVectors(ssG, target_M, tp_deg); } } if(printout > 0) { Print("\n//** Mprwalk: Random Perturbation Walk of degree (%d,%d):",op_deg,tp_deg); ivString(curr_weight, "//** Mprwalk: new current weight"); ivString(target_weight, "//** Mprwalk: new target weight"); } #ifdef TIME_TEST to = clock(); #endif Gomega = MwalkInitialForm(G, curr_weight); // compute an initial form ideal of w.r.t. "curr_vector" #ifdef TIME_TEST tif = tif + clock()-to; //time for computing initial form ideal #endif while(1) { nstep ++; #ifdef CHECK_IDEAL_MWALK if(printout > 1) { idString(Gomega,"//** Mprwalk: Gomega"); } #endif if(reduction == 0 && nstep > 1) { FF = middleOfCone(G,Gomega); if(FF != NULL) { idDelete(&G); G = idCopy(FF); idDelete(&FF); goto NEXT_VECTOR; } } #ifdef ENDWALKS if(endwalks == TRUE) { if(printout > 0) { Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); //idElements(G, "G"); //headidString(G, "G"); } } #endif #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); else hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); #endif // BUCHBERGER_ALG oldRing = currRing; if(target_M->length() == nV) {/* // define a new ring with ordering "(a(curr_weight),lp) if (rParameter(currRing) != NULL) DefRingPar(curr_weight); else rChangeCurrRing(VMrDefault(curr_weight)); */ rChangeCurrRing(VMrRefine(target_M,curr_weight)); } else { rChangeCurrRing(VMatrRefine(target_M,curr_weight)); } newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); #ifdef ENDWALKS if(endwalks == TRUE) { if(printout > 0) { Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); //idElements(Gomega1, "Gw"); //headidString(Gomega1, "headGw"); PrintS("\n// compute a rGB of Gw:\n"); } #ifndef BUCHBERGER_ALG ivString(hilb_func, "w"); #endif } #endif #ifdef TIME_TEST tim = clock(); to = clock(); #endif // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(M,"//** Mprwalk: M"); } #endif #ifdef TIME_TEST if(endwalks == TRUE) { xtstd = xtstd+clock()-to; #ifdef ENDWALKS Print("\n// time for the last std(Gw) = %.2f sec\n", ((double) clock())/1000000 -((double)tim) /1000000); #endif } else tstd=tstd+clock()-to; #endif /* change the ring to oldRing */ rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); #ifdef TIME_TEST to=clock(); #endif /* compute a representation of the generators of submod (M) with respect to those of mod (Gomega). Gomega is a reduced Groebner basis w.r.t. the current ring */ F = MLifttwoIdeal(Gomega2, M1, G); #ifdef TIME_TEST if(endwalks == FALSE) tlift = tlift+clock()-to; else xtlift=clock()-to; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(F,"//** Mprwalk: F"); } #endif idDelete(&M1); idDelete(&Gomega2); idDelete(&G); // change the ring to newRing rChangeCurrRing(newRing); if(reduction == 0) { G = idrMoveR(F,oldRing,currRing); } else { F1 = idrMoveR(F, oldRing,currRing); if(printout > 2) { PrintS("\n //** Mprwalk: reduce the Groebner basis.\n"); } #ifdef TIME_TEST to=clock(); #endif G = kInterRedCC(F1, NULL); #ifdef TIME_TEST if(endwalks == FALSE) tred = tred+clock()-to; else xtred=clock()-to; #endif idDelete(&F1); } if(endwalks == TRUE) break; NEXT_VECTOR: #ifdef TIME_TEST to = clock(); #endif next_weight = next_weight = MkInterRedNextWeight(curr_weight,target_weight, G); #ifdef TIME_TEST tnw = tnw + clock() - to; #endif #ifdef TIME_TEST to = clock(); #endif // compute an initial form ideal of w.r.t. "next_vector" Gomega = MwalkInitialForm(G, next_weight); #ifdef TIME_TEST tif = tif + clock()-to; //time for computing initial form ideal #endif //lengthpoly(Gomega) = 1 if there is a polynomial in Gomega with at least 3 monomials and 0 otherwise if(lengthpoly(Gomega) > 0) { if(printout > 1) { Print("\n Mpwalk: there is a polynomial in Gomega with at least 3 monomials.\n"); } // low-dimensional facet of the cone delete next_weight; if(target_M->length() == nV) { iv_M = MivMatrixOrder(curr_weight); } else { iv_M = MivMatrixOrderRefine(curr_weight,target_M); } #ifdef TIME_TEST to = clock(); #endif next_weight = MWalkRandomNextWeight(G, iv_M, target_weight, weight_rad, op_deg); #ifdef TIME_TEST tnw = tnw + clock() - to; #endif idDelete(&Gomega); #ifdef TIME_TEST to = clock(); #endif Gomega = MwalkInitialForm(G, next_weight); #ifdef TIME_TEST tif = tif + clock()-to; //time for computing initial form ideal #endif delete iv_M; } #ifdef PRINT_VECTORS if(printout > 0) { MivString(curr_weight, target_weight, next_weight); } #endif if(Overflow_Error == TRUE) { ntwC = 0; //Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); //idElements(G, "G"); delete next_weight; goto FINISH_160302; } if(MivComp(next_weight, ivNull) == 1){ newRing = currRing; delete next_weight; //Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); break; } if(MivComp(next_weight, target_weight) == 1) endwalks = TRUE; for(i=nV-1; i>=0; i--) (*curr_weight)[i] = (*next_weight)[i]; delete next_weight; }// end of while-loop if(tp_deg != 1) { FINISH_160302: if(target_M->length() == nV) { if(MivSame(orig_target, exivlp) == 1) if (rParameter(currRing) != NULL) DefRingParlp(); else VMrDefaultlp(); else if (rParameter(currRing) != NULL) DefRingPar(orig_target); else rChangeCurrRing(VMrDefault(orig_target)); } else { rChangeCurrRing(VMatrDefault(target_M)); } TargetRing=currRing; F1 = idrMoveR(G, newRing,currRing); // check whether the pertubed target vector stays in the correct cone if(ntwC != 0) { ntestw = test_w_in_ConeCC(F1, pert_target_vector); } if(ntestw != 1 || ntwC == 0) { if(ntestw != 1 && printout > 2) { #ifdef PRINT_VECTORS ivString(pert_target_vector, "tau"); #endif PrintS("\n// **Mprwalk: perturbed target vector doesn't stay in cone."); Print("\n// ring r%d = %s;\n", nstep, rString(currRing)); //idElements(F1, "G"); } // LastGB is "better" than the kStd subroutine #ifdef TIME_TEST to=clock(); #endif ideal eF1; if(nP == 0 || tp_deg == 1 || MivSame(orig_target, exivlp) != 1 || target_M->length() != nV) { if(printout > 2) { PrintS("\n// ** Mprwalk: Call \"std\" to compute a Groebner basis.\n"); } eF1 = MstdCC(F1); idDelete(&F1); } else { if(printout > 2) { PrintS("\n// **Mprwalk: Call \"LastGB\" to compute a Groebner basis.\n"); } rChangeCurrRing(newRing); ideal F2 = idrMoveR(F1, TargetRing,currRing); eF1 = LastGB(F2, curr_weight, tp_deg-1); F2=NULL; } #ifdef TIME_TEST xtextra=clock()-to; #endif ring exTargetRing = currRing; rChangeCurrRing(XXRing); Eresult = idrMoveR(eF1, exTargetRing,currRing); } else { rChangeCurrRing(XXRing); Eresult = idrMoveR(F1, TargetRing,currRing); } } else { rChangeCurrRing(XXRing); Eresult = idrMoveR(G, newRing,currRing); } si_opt_1 = save1; //set original options, e. g. option(RedSB) delete ivNull; if(tp_deg != 1) delete target_weight; if(op_deg != 1 ) delete curr_weight; delete exivlp; delete last_omega; #ifdef TIME_TEST TimeStringFractal(tinput, tostd, tif+xtif, tstd+xtstd,0, tlift+xtlift, tred+xtred, tnw+xtnw); //Print("\n// pSetm_Error = (%d)", ErrorCheck()); //Print("\n// It took %d steps and Overflow_Error? (%d)\n", nstep, Overflow_Error); #endif if(printout > 0) { Print("\n//** Mprwalk: Perturbation Walk took %d steps.\n", nstep); } return(Eresult); } intvec* XivNull; /***************************** * define a matrix (1 ... 1) * *****************************/ intvec* MMatrixone(int nV) { int i,j; intvec* ivM = new intvec(nV*nV); for(i=0; i0) { Print("\n\n// Entering the %d-th recursion:", nlev); } int i, nV = currRing->N; ring new_ring, testring; //ring extoRing; ideal Gomega, Gomega1, Gomega2, FF, F, F1, Gresult, Gresult1, G1, Gt; int nwalks = 0; intvec* Mwlp; #ifndef BUCHBERGER_ALG intvec* hilb_func; #endif //intvec* extXtau; intvec* next_vect; intvec* omega2 = new intvec(nV); intvec* omtmp = new intvec(nV); //intvec* altomega = new intvec(nV); for(i = nV -1; i>=0; i--)//Aenderung!! { (*omtmp)[i] = (*ivtarget)[i]; } //BOOLEAN isnewtarget = FALSE; // to avoid (1,0,...,0) as the target vector (Hans) intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) (*last_omega)[i] = 1; (*last_omega)[0] = 10000; intvec* omega = new intvec(nV); for(i=0; ilength() == nV) (*omega)[i] = (*Xsigma)[i]; else (*omega)[i] = (*Xsigma)[(nV*(nlev-1))+i]; (*omega2)[i] = (*Xtau)[(nlev-1)*nV+i]; } if(nlev == 1) Xcall = 1; else Xcall = 0; ring oRing = currRing; while(1) { #ifdef FIRST_STEP_FRACTAL // perturb the current weight vector only on the top level or // after perturbation of the both vectors, nlev = 2 as the top level if((nlev == 1 && Xcall == 0) || (nlev == 2 && Xngleich == 1)) if(islengthpoly2(G) == 1) { Mwlp = MivWeightOrderlp(omega); Xsigma = Mfpertvector(G, Mwlp); delete Mwlp; Overflow_Error = FALSE; } #endif nwalks ++; NEXT_VECTOR_FRACTAL: #ifdef TIME_TEST to=clock(); #endif // determine the next border next_vect = MkInterRedNextWeight(omega,omega2,G); #ifdef TIME_TEST xtnw=xtnw+clock()-to; #endif oRing = currRing; // We only perturb the current target vector at the recursion level 1 if(Xngleich == 0 && nlev == 1) //(ngleich == 0) important, e.g. ex2, ex3 if (MivComp(next_vect, omega2) == 1) { // to dispense with taking initial (and lifting/interreducing // after the call of recursion if(printout > 0) { Print("\n//** rec_fractal_call: Perturb the both vectors with degree %d.",nlev); //idElements(G, "G"); } Xngleich = 1; nlev +=1; if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) DefRingPar(omtmp); else rChangeCurrRing(VMrDefault(omtmp)); */ rChangeCurrRing(VMrRefine(ivtarget,omtmp)); } else { //rChangeCurrRing(VMatrDefault(ivtarget)); rChangeCurrRing(VMatrRefine(ivtarget,omtmp)); } testring = currRing; Gt = idrMoveR(G, oRing,currRing); // perturb the original target vector w.r.t. the current GB if(ivtarget->length() == nV) { delete Xtau; Xtau = NewVectorlp(Gt); } else { delete Xtau; Xtau = Mfpertvector(Gt,ivtarget); } rChangeCurrRing(oRing); G = idrMoveR(Gt, testring,currRing); // perturb the current vector w.r.t. the current GB Mwlp = MivWeightOrderlp(omega); Xsigma = Mfpertvector(G, Mwlp); delete Mwlp; for(i=nV-1; i>=0; i--) { (*omega2)[i] = (*Xtau)[nV+i]; (*omega)[i] = (*Xsigma)[nV+i]; } delete next_vect; #ifdef TIME_TEST to=clock(); #endif // to avoid the value of Overflow_Error that occur in Mfpertvector Overflow_Error = FALSE; next_vect = MkInterRedNextWeight(omega,omega2,G); #ifdef TIME_TEST xtnw=xtnw+clock()-to; #endif }// end of (if MivComp(next_vect, omega2) == 1) #ifdef PRINT_VECTORS if(printout > 0) { MivString(omega, omega2, next_vect); } #endif // check whether the the computed vector is in the correct cone. // If no, compute the reduced Groebner basis of an omega-homogeneous // ideal with Buchberger's algorithm and stop this recursion step if(Overflow_Error == TRUE || test_w_in_ConeCC(G, next_vect) != 1) //e.g. Example s7, cyc6 { delete next_vect; if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) DefRingPar(omtmp); else rChangeCurrRing(VMrDefault(omtmp)); */ rChangeCurrRing(VMrRefine(ivtarget,omtmp)); } else { //rChangeCurrRing(VMatrDefault(ivtarget)); rChangeCurrRing(VMatrRefine(ivtarget,omtmp)); } #ifdef TEST_OVERFLOW Gt = idrMoveR(G, oRing,currRing); Gt = NULL; return(Gt); #endif if(printout > 0) { Print("\n//** rec_fractal_call: Applying Buchberger's algorithm in ring r = %s;", rString(currRing)); } #ifdef TIME_TEST to=clock(); #endif Gt = idrMoveR(G, oRing,currRing); G1 = MstdCC(Gt); #ifdef TIME_TEST xtextra=xtextra+clock()-to; #endif Gt = NULL; delete omega2; //delete altomega; if(printout > 0) { Print("\n//** rec_fractal_call: Overflow. (4) Leaving the %d-th recursion with %d steps.\n", nlev, nwalks); //Print(" ** Overflow_Error? (%d)", Overflow_Error); } nnflow ++; Overflow_Error = FALSE; return (G1); } /* If the perturbed target vector stays in the correct cone, return the current GB, otherwise, return the computed GB by the Buchberger-algorithm. Then we update the perturbed target vectors w.r.t. this GB. */ /* the computed vector is equal to the origin vector, since t is not defined */ if (MivComp(next_vect, XivNull) == 1) { if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) DefRingPar(omtmp); else rChangeCurrRing(VMrDefault(omtmp)); */ rChangeCurrRing(VMrRefine(ivtarget,omtmp)); } else { //rChangeCurrRing(VMatrDefault(ivtarget)); rChangeCurrRing(VMatrRefine(ivtarget,omtmp)); } testring = currRing; Gt = idrMoveR(G, oRing,currRing); if(test_w_in_ConeCC(Gt, omega2) == 1) { delete omega2; delete next_vect; //delete altomega; if(printout > 0) { Print("\n//** rec_fractal_call: Correct cone. (5) Leaving the %d-th recursion with %d steps.\n", nlev, nwalks); } if(printout>2) { idString(Gt,"//** rec_fractal_call: Gt"); } return (Gt); } else { if(printout > 0) { Print("\n//** rec_fractal_call: Wrong cone. Tau doesn't stay in the correct cone.\n"); } #ifndef MSTDCC_FRACTAL intvec* Xtautmp; if(ivtarget->length() == nV) { Xtautmp = Mfpertvector(Gt, MivMatrixOrder(omtmp)); } else { Xtautmp = Mfpertvector(Gt, ivtarget); } #ifdef TEST_OVERFLOW if(Overflow_Error == TRUE) Gt = NULL; return(Gt); #endif if(MivSame(Xtau, Xtautmp) == 1) { if(printout > 0) { Print("\n//** rec_fractal_call: Updated vectors are equal to the old vectors.\n"); } delete Xtautmp; goto FRACTAL_MSTDCC; } Xtau = Xtautmp; Xtautmp = NULL; for(i=nV-1; i>=0; i--) (*omega2)[i] = (*Xtau)[(nlev-1)*nV+i]; rChangeCurrRing(oRing); G = idrMoveR(Gt, testring,currRing); goto NEXT_VECTOR_FRACTAL; #endif FRACTAL_MSTDCC: if(printout > 0) { Print("\n//** rec_fractal_call: Wrong cone. Applying Buchberger's algorithm in ring = %s.\n", rString(currRing)); } #ifdef TIME_TEST to=clock(); #endif G = MstdCC(Gt); #ifdef TIME_TEST xtextra=xtextra+clock()-to; #endif oRing = currRing; // update the original target vector w.r.t. the current GB if(ivtarget->length() == nV) { /* if(MivSame(Xivinput, Xivlp) == 1) if (rParameter(currRing) != NULL) DefRingParlp(); else VMrDefaultlp(); else if (rParameter(currRing) != NULL) DefRingPar(Xivinput); else rChangeCurrRing(VMrDefault(Xivinput)); */ rChangeCurrRing(VMrRefine(ivtarget,Xivinput)); } else { rChangeCurrRing(VMatrRefine(ivtarget,Xivinput)); } testring = currRing; Gt = idrMoveR(G, oRing,currRing); // perturb the original target vector w.r.t. the current GB if(ivtarget->length() == nV) { delete Xtau; Xtau = NewVectorlp(Gt); } else { delete Xtau; Xtau = Mfpertvector(Gt,ivtarget); } rChangeCurrRing(oRing); G = idrMoveR(Gt, testring,currRing); delete omega2; delete next_vect; //delete altomega; if(printout > 0) { Print("\n//** rec_fractal_call: Vectors updated. (6) Leaving the %d-th recursion with %d steps.\n", nlev, nwalks); //Print(" ** Overflow_Error? (%d)", Overflow_Error); } if(Overflow_Error == TRUE) nnflow ++; Overflow_Error = FALSE; return(G); } }// end of (if next_vect==nullvector) for(i=nV-1; i>=0; i--) { //(*altomega)[i] = (*omega)[i]; (*omega)[i] = (*next_vect)[i]; } delete next_vect; #ifdef TIME_TEST to=clock(); #endif // Take the initial form of w.r.t. omega Gomega = MwalkInitialForm(G, omega); #ifdef TIME_TEST xtif=xtif+clock()-to; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 1) { idString(Gomega,"//** rec_fractal_call: Gomega"); } #endif if(reduction == 0) { // Check whether the intermediate weight vector lies in the interior of the cone. // If so, only perform reductions. Otherwise apply Buchberger's algorithm. FF = middleOfCone(G,Gomega); if( FF != NULL) { idDelete(&G); G = idCopy(FF); idDelete(&FF); // Compue next vector. goto NEXT_VECTOR_FRACTAL; } } #ifndef BUCHBERGER_ALG if(isNolVector(omega) == 0) hilb_func = hFirstSeries(Gomega,NULL,NULL,omega,currRing); else hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); #endif if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) DefRingPar(omega); else rChangeCurrRing(VMrDefault(omega)); */ rChangeCurrRing(VMrRefine(ivtarget,omega)); } else { rChangeCurrRing(VMatrRefine(ivtarget,omega)); } Gomega1 = idrMoveR(Gomega, oRing,currRing); // Maximal recursion depth, to compute a red. GB // Fractal walk with the alternative recursion // alternative recursion if(nlev == Xnlev || lengthpoly(Gomega1) == 0) { if(printout > 1) { Print("\n//** rec_fractal_call: Maximal recursion depth.\n"); } #ifdef TIME_TEST to=clock(); #endif #ifdef BUCHBERGER_ALG Gresult = MstdhomCC(Gomega1); #else Gresult =kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,omega); delete hilb_func; #endif #ifdef TIME_TEST xtstd=xtstd+clock()-to; #endif } else { rChangeCurrRing(oRing); Gomega1 = idrMoveR(Gomega1, oRing,currRing); Gresult = rec_fractal_call(idCopy(Gomega1),nlev+1,omega,reduction,printout); } #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(Gresult,"//** rec_fractal_call: M"); } #endif //convert a Groebner basis from a ring to another ring new_ring = currRing; rChangeCurrRing(oRing); Gresult1 = idrMoveR(Gresult, new_ring,currRing); Gomega2 = idrMoveR(Gomega1, new_ring,currRing); #ifdef TIME_TEST to=clock(); #endif // Lifting process F = MLifttwoIdeal(Gomega2, Gresult1, G); #ifdef TIME_TEST xtlift=xtlift+clock()-to; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(F,"//** rec_fractal_call: F"); } #endif id_Normalize(F,currRing); idDelete(&Gresult1); idDelete(&Gomega2); idDelete(&G); rChangeCurrRing(new_ring); G = idrMoveR(F,oRing,currRing); /* F1 = idrMoveR(F, oRing,currRing); #ifdef TIME_TEST to=clock(); #endif // Interreduce G G = kInterRedCC(F1, NULL); #ifdef TIME_TEST xtred=xtred+clock()-to; #endif idDelete(&F1); */ } } /************************************************************************ * Perturb the start weight vector at the top level with random element * ************************************************************************/ static ideal rec_r_fractal_call(ideal G, int nlev, intvec* ivtarget, int weight_rad, int reduction, int printout) { Overflow_Error = FALSE; //Print("\n\n// Entering the %d-th recursion:", nlev); int nwalks = 0,i,nV=currRing->N;//polylength ring new_ring, testring; //ring extoRing; ideal Gomega, Gomega1, Gomega2, F, FF, F1, Gresult, Gresult1, G1, Gt; intvec* Mwlp; #ifndef BUCHBERGER_ALG intvec* hilb_func; #endif // intvec* extXtau; intvec* next_vect; intvec* iv_M; intvec* omega2 = new intvec(nV); intvec* omtmp = new intvec(nV); intvec* altomega = new intvec(nV); //BOOLEAN isnewtarget = FALSE; for(i = nV -1; i>=0; i--) { (*omtmp)[i] = (*ivtarget)[i]; } // to avoid (1,0,...,0) as the target vector (Hans) intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) (*last_omega)[i] = 1; (*last_omega)[0] = 10000; intvec* omega = new intvec(nV); for(i=0; ilength() == nV) (*omega)[i] = (*Xsigma)[i]; else (*omega)[i] = (*Xsigma)[(nV*(nlev-1))+i]; (*omega2)[i] = (*Xtau)[(nlev-1)*nV+i]; } if(nlev == 1) Xcall = 1; else Xcall = 0; ring oRing = currRing; while(1) { #ifdef FIRST_STEP_FRACTAL /* perturb the current weight vector only on the top level or after perturbation of the both vectors, nlev = 2 as the top level */ if((nlev == 1 && Xcall == 0) || (nlev == 2 && Xngleich == 1)) if(islengthpoly2(G) == 1) { Mwlp = MivWeightOrderlp(omega); Xsigma = Mfpertvector(G, Mwlp); delete Mwlp; Overflow_Error = FALSE; } #endif nwalks ++; NEXT_VECTOR_FRACTAL: #ifdef TIME_TEST to=clock(); #endif /* determine the next border */ next_vect = MkInterRedNextWeight(omega,omega2,G); #ifdef TIME_TEST xtnw=xtnw+clock()-to; #endif if(lengthpoly(MwalkInitialForm(G, next_vect)) > 0 && G->m[0] != NULL) { if(printout > 0) { PrintS("\n**// rec_r_fractal_call: there is a polynomial in Gomega with at least 3 monomials.\n"); } delete next_vect; iv_M = MivMatrixOrder(omega); #ifdef TIME_TEST to=clock(); #endif next_vect = MWalkRandomNextWeight(G,iv_M,omega2,weight_rad,nlev); #ifdef TIME_TEST xtnw=xtnw+clock()-to; #endif if(isNegNolVector(next_vect) == 1) { delete next_vect; #ifdef TIME_TEST to=clock(); #endif next_vect = MkInterRedNextWeight(omega,omega2,G); #ifdef TIME_TEST xtnw=xtnw+clock()-to; #endif } } oRing = currRing; // We only perturb the current target vector at the recursion level 1 if(Xngleich == 0 && nlev == 1) //(ngleich == 0) important, e.g. ex2, ex3 if (MivComp(next_vect, omega2) == 1) { // to dispense with taking initials and lifting/interreducing // after the call of recursion. if(printout > 0) { Print("\n//** rec_r_fractal_call: Perturb both vectors with degree %d.",nlev); //idElements(G, "G"); } Xngleich = 1; nlev +=1; if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) DefRingPar(omtmp); else rChangeCurrRing(VMrDefault(omtmp)); */ rChangeCurrRing(VMrRefine(ivtarget,omtmp)); } else { //rChangeCurrRing(VMatrDefault(ivtarget)); rChangeCurrRing(VMatrRefine(ivtarget,omtmp)); } testring = currRing; Gt = idrMoveR(G, oRing,currRing); // perturb the original target vector w.r.t. the current GB if(ivtarget->length() == nV) { delete Xtau; Xtau = NewVectorlp(Gt); } else { delete Xtau; Xtau = Mfpertvector(Gt,ivtarget); } rChangeCurrRing(oRing); G = idrMoveR(Gt,testring,currRing); // perturb the current vector w.r.t. the current GB Mwlp = MivWeightOrderlp(omega); if(ivtarget->length() > nV) { delete Mwlp; Mwlp = MivMatrixOrderRefine(omega,ivtarget); } Xsigma = Mfpertvector(G, Mwlp); delete Mwlp; for(i=nV-1; i>=0; i--) { (*omega2)[i] = (*Xtau)[nV+i]; (*omega)[i] = (*Xsigma)[nV+i]; } delete next_vect; //to avoid the value of Overflow_Error that occur in Mfpertvector Overflow_Error = FALSE; #ifdef TIME_TEST to=clock(); #endif next_vect = MkInterRedNextWeight(omega,omega2,G); #ifdef TIME_TEST xtnw=xtnw+clock()-to; #endif if(lengthpoly(MwalkInitialForm(G, next_vect)) > 0 && G->m[0] != NULL) { // there is a polynomial in Gomega with at least 3 monomials iv_M = MivMatrixOrder(omega); delete next_vect; #ifdef TIME_TEST to=clock(); #endif next_vect = MWalkRandomNextWeight(G,iv_M,omega2,weight_rad,nlev); #ifdef TIME_TEST xtnw=xtnw+clock()-to; #endif delete iv_M; if(isNegNolVector(next_vect) == 1) { delete next_vect; #ifdef TIME_TEST to=clock(); #endif next_vect = MkInterRedNextWeight(omega,omega2,G); #ifdef TIME_TEST xtnw=xtnw+clock()-to; #endif } } } #ifdef PRINT_VECTORS if(printout > 0) { MivString(omega, omega2, next_vect); } #endif /* check whether the the computed vector is in the correct cone If no, the reduced GB of an omega-homogeneous ideal will be computed by Buchberger algorithm and stop this recursion step */ if(Overflow_Error == TRUE || test_w_in_ConeCC(G,next_vect) != 1)//e.g. Example s7, cyc6 { delete next_vect; if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) { DefRingPar(omtmp); } else { rChangeCurrRing(VMrDefault(omtmp)); } */ rChangeCurrRing(VMrRefine(ivtarget,omtmp)); } else { //rChangeCurrRing(VMatrDefault(ivtarget)); rChangeCurrRing(VMatrRefine(ivtarget,omtmp)); } #ifdef TEST_OVERFLOW Gt = idrMoveR(G, oRing,currRing); Gt = NULL; return(Gt); #endif if(printout > 0) { Print("\n//** rec_r_fractal_call: applying Buchberger's algorithm in ring r = %s;", rString(currRing)); } Gt = idrMoveR(G, oRing,currRing); #ifdef TIME_TEST to=clock(); #endif G1 = MstdCC(Gt); #ifdef TIME_TEST xtextra=xtextra+clock()-to; #endif Gt = NULL; delete omega2; delete altomega; if(printout > 0) { Print("\n//** rec_r_fractal_call: (1) Leaving the %d-th recursion with %d steps.\n", nlev, nwalks); //Print(" ** Overflow_Error? (%d)", Overflow_Error); } nnflow ++; Overflow_Error = FALSE; return (G1); } /* If the perturbed target vector stays in the correct cone, return the current Groebner basis. Otherwise, return the Groebner basis computed with Buchberger's algorithm. Then we update the perturbed target vectors w.r.t. this GB. */ if (MivComp(next_vect, XivNull) == 1) { // The computed vector is equal to the origin vector, // because t is not defined if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) DefRingPar(omtmp); else rChangeCurrRing(VMrDefault(omtmp)); */ rChangeCurrRing(VMrRefine(ivtarget,omtmp)); } else { //rChangeCurrRing(VMatrDefault(ivtarget)); rChangeCurrRing(VMatrRefine(ivtarget,omtmp)); } testring = currRing; Gt = idrMoveR(G, oRing,currRing); if(test_w_in_ConeCC(Gt, omega2) == 1) { delete omega2; delete next_vect; delete altomega; if(printout > 0) { Print("\n//** rec_r_fractal_call: (2) Leaving the %d-th recursion with %d steps.\n", nlev, nwalks); //Print(" ** Overflow_Error? (%d)", Overflow_Error); } return (Gt); } else { if(printout > 0) { Print("\n//** rec_r_fractal_call: target weight doesn't stay in the correct cone.\n"); } #ifndef MSTDCC_FRACTAL #ifdef PRINT_VECTORS if(printout > 0) { ivString(Xtau, "old Xtau"); } #endif intvec* Xtautmp; if(ivtarget->length() == nV) { Xtautmp = Mfpertvector(Gt, MivMatrixOrder(omtmp)); } else { Xtautmp = Mfpertvector(Gt, ivtarget); } #ifdef TEST_OVERFLOW if(Overflow_Error == TRUE) Gt = NULL; return(Gt); #endif if(MivSame(Xtau, Xtautmp) == 1) { //PrintS("\n// Update vectors are equal to the old vectors!!"); delete Xtautmp; goto FRACTAL_MSTDCC; } Xtau = Xtautmp; Xtautmp = NULL; #ifdef PRINT_VECTORS if(printout > 0) { ivString(Xtau, "new Xtau"); } #endif for(i=nV-1; i>=0; i--) (*omega2)[i] = (*Xtau)[(nlev-1)*nV+i]; //Print("\n// ring tau = %s;", rString(currRing)); rChangeCurrRing(oRing); G = idrMoveR(Gt, testring,currRing); goto NEXT_VECTOR_FRACTAL; #endif FRACTAL_MSTDCC: if(printout > 0) { Print("\n//** rec_r_fractal_call: apply Buchberger's algorithm in ring = %s.\n", rString(currRing)); } #ifdef TIME_TEST to=clock(); #endif G = MstdCC(Gt); #ifdef TIME_TEST xtextra=xtextra+clock()-to; #endif oRing = currRing; // update the original target vector w.r.t. the current GB if(ivtarget->length() == nV) { /* if(MivSame(Xivinput, Xivlp) == 1) if (rParameter(currRing) != NULL) DefRingParlp(); else VMrDefaultlp(); else if (rParameter(currRing) != NULL) DefRingPar(Xivinput); else rChangeCurrRing(VMrDefault(Xivinput)); */ rChangeCurrRing(VMrRefine(ivtarget,Xivinput)); } else { rChangeCurrRing(VMatrRefine(ivtarget,Xivinput)); } testring = currRing; Gt = idrMoveR(G, oRing,currRing); // perturb the original target vector w.r.t. the current GB if(ivtarget->length() == nV) { delete Xtau; Xtau = NewVectorlp(Gt); } else { delete Xtau; Xtau = Mfpertvector(Gt,ivtarget); } rChangeCurrRing(oRing); G = idrMoveR(Gt, testring,currRing); delete omega2; delete next_vect; delete altomega; if(printout > 0) { Print("\n//** rec_r_fractal_call: (3) Leaving the %d-th recursion with %d steps.\n", nlev,nwalks); //Print(" ** Overflow_Error? (%d)", Overflow_Error); } if(Overflow_Error == TRUE) nnflow ++; Overflow_Error = FALSE; return(G); } } //end of if(MivComp(next_vect, XivNull) == 1) for(i=nV-1; i>=0; i--) { (*altomega)[i] = (*omega)[i]; (*omega)[i] = (*next_vect)[i]; } delete next_vect; #ifdef TIME_TEST to=clock(); #endif // Take the initial form of w.r.t. omega Gomega = MwalkInitialForm(G, omega); #ifdef TIME_TEST xtif=xtif+clock()-to; #endif //polylength = 1 if there is a polynomial in Gomega with at least 3 monomials and 0 otherwise //polylength = lengthpoly(Gomega); #ifdef CHECK_IDEAL_MWALK if(printout > 1) { idString(Gomega,"//** rec_r_fractal_call: Gomega"); } #endif if(reduction == 0) { /* Check whether the intermediate weight vector lies in the interior of the cone. * If so, only perform reductions. Otherwise apply Buchberger's algorithm. */ FF = middleOfCone(G,Gomega); if( FF != NULL) { idDelete(&G); G = idCopy(FF); idDelete(&FF); /* Compue next vector. */ goto NEXT_VECTOR_FRACTAL; } } #ifndef BUCHBERGER_ALG if(isNolVector(omega) == 0) hilb_func = hFirstSeries(Gomega,NULL,NULL,omega,currRing); else hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); #endif if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) DefRingPar(omega); else rChangeCurrRing(VMrDefault(omega)); */ rChangeCurrRing(VMrRefine(ivtarget,omega)); } else { rChangeCurrRing(VMatrRefine(ivtarget,omega)); } Gomega1 = idrMoveR(Gomega, oRing,currRing); // Maximal recursion depth, to compute a red. GB // Fractal walk with the alternative recursion // alternative recursion if(nlev == Xnlev || lengthpoly(Gomega1) == 0) { #ifdef TIME_TEST to=clock(); #endif #ifdef BUCHBERGER_ALG Gresult = MstdhomCC(Gomega1); #else Gresult =kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,omega); delete hilb_func; #endif #ifdef TIME_TEST xtstd=xtstd+clock()-to; #endif } else { rChangeCurrRing(oRing); Gomega1 = idrMoveR(Gomega1, oRing,currRing); Gresult = rec_r_fractal_call(idCopy(Gomega1),nlev+1,omega,weight_rad,reduction,printout); } #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(Gresult,"//** rec_r_fractal_call: M"); } #endif //convert a Groebner basis from a ring to another ring new_ring = currRing; rChangeCurrRing(oRing); Gresult1 = idrMoveR(Gresult, new_ring,currRing); Gomega2 = idrMoveR(Gomega1, new_ring,currRing); #ifdef TIME_TEST to=clock(); #endif // Lifting process F = MLifttwoIdeal(Gomega2, Gresult1, G); #ifdef TIME_TEST xtlift=xtlift+clock()-to; #endif #ifdef CHECK_IDEAL_MWALK if(printout > 2) { idString(F,"//** rec_r_fractal_call: F"); } #endif id_Normalize(F,currRing); idDelete(&Gresult1); idDelete(&Gomega2); idDelete(&G); rChangeCurrRing(new_ring); //F1 = idrMoveR(F, oRing,currRing); G = idrMoveR(F,oRing,currRing); /* #ifdef TIME_TEST to=clock(); #endif // Interreduce G G = kInterRedCC(F1, NULL); #ifdef TIME_TEST xtred=xtred+clock()-to; #endif idDelete(&F1); */ } } /******************************************************************************* * The implementation of the fractal walk algorithm * * * * The main procedure Mfwalk calls the recursive Subroutine * * rec_fractal_call to compute the wanted Groebner basis. * * At the main procedur we compute the reduced Groebner basis w.r.t. a "fast" * * order, e.g. "dp" and a sequence of weight vectors which are row vectors * * of a matrix. This matrix defines the given monomial order, e.g. "lp" * *******************************************************************************/ ideal Mfwalk(ideal G, intvec* ivstart, intvec* ivtarget, int reduction, int printout) { BITSET save1 = si_opt_1; // save current options if(reduction == 0) { si_opt_1 &= (~Sy_bit(OPT_REDSB)); // no reduced Groebner basis //si_opt_1 &= (~Sy_bit(OPT_REDTAIL)); // not tail reductions } Set_Error(FALSE); Overflow_Error = FALSE; //Print("// pSetm_Error = (%d)", ErrorCheck()); //Print("\n// ring ro = %s;", rString(currRing)); nnflow = 0; Xngleich = 0; Xcall = 0; #ifdef TIME_TEST xtif=0; xtstd=0; xtlift=0; xtred=0; xtnw=0; xtextra=0; xftinput = clock(); #endif ring oldRing = currRing; int i, nV = currRing->N; XivNull = new intvec(nV); Xivinput = ivtarget; ngleich = 0; #ifdef TIME_TEST to=clock(); #endif ideal I = MstdCC(G); G = NULL; #ifdef TIME_TEST xftostd=clock()-to; #endif Xsigma = ivstart; Xnlev=nV; #ifdef FIRST_STEP_FRACTAL ideal Gw = MwalkInitialForm(I, ivstart); for(i=IDELEMS(Gw)-1; i>=0; i--) { if((Gw->m[i]!=NULL) // len >=0 && (Gw->m[i]->next!=NULL) // len >=1 && (Gw->m[i]->next->next!=NULL)) // len >=2 { intvec* iv_dp = MivUnit(nV); // define (1,1,...,1) intvec* Mdp; if(ivstart->length() == nV) { if(MivSame(ivstart, iv_dp) != 1) Mdp = MivWeightOrderdp(ivstart); else Mdp = MivMatrixOrderdp(nV); } else { Mdp = ivstart; } Xsigma = Mfpertvector(I, Mdp); Overflow_Error = FALSE; delete Mdp; delete iv_dp; break; } } idDelete(&Gw); #endif ideal I1; intvec* Mlp; Xivlp = Mivlp(nV); if(ivtarget->length() == nV) { if(MivComp(ivtarget, Xivlp) != 1) { if (rParameter(currRing) != NULL) DefRingPar(ivtarget); else rChangeCurrRing(VMrDefault(ivtarget)); I1 = idrMoveR(I, oldRing,currRing); Mlp = MivWeightOrderlp(ivtarget); Xtau = Mfpertvector(I1, Mlp); } else { if (rParameter(currRing) != NULL) DefRingParlp(); else VMrDefaultlp(); I1 = idrMoveR(I, oldRing,currRing); Mlp = MivMatrixOrderlp(nV); Xtau = Mfpertvector(I1, Mlp); } } else { rChangeCurrRing(VMatrDefault(ivtarget)); I1 = idrMoveR(I,oldRing,currRing); Mlp = ivtarget; Xtau = Mfpertvector(I1, Mlp); } delete Mlp; Overflow_Error = FALSE; //ivString(Xsigma, "Xsigma"); //ivString(Xtau, "Xtau"); id_Delete(&I, oldRing); ring tRing = currRing; if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) DefRingPar(ivstart); else rChangeCurrRing(VMrDefault(ivstart)); */ rChangeCurrRing(VMrRefine(ivtarget,ivstart)); } else { //rChangeCurrRing(VMatrDefault(ivstart)); rChangeCurrRing(VMatrRefine(ivtarget,ivstart)); } I = idrMoveR(I1,tRing,currRing); #ifdef TIME_TEST to=clock(); #endif ideal J = MstdCC(I); idDelete(&I); #ifdef TIME_TEST xftostd=xftostd+clock()-to; #endif ideal resF; ring helpRing = currRing; J = rec_fractal_call(J,1,ivtarget,reduction,printout); //idString(J,"//** Mfwalk: J"); rChangeCurrRing(oldRing); //Print("\n//Mfwalk: (2)\n"); resF = idrMoveR(J, helpRing,currRing); //Print("\n//Mfwalk: (3)\n"); idSkipZeroes(resF); //Print("\n//Mfwalk: (4)\n"); si_opt_1 = save1; //set original options, e. g. option(RedSB) delete Xivlp; //delete Xsigma; delete Xtau; delete XivNull; //Print("\n//Mfwalk: (5)\n"); #ifdef TIME_TEST TimeStringFractal(xftinput, xftostd, xtif, xtstd, xtextra, xtlift, xtred, xtnw); //Print("\n// pSetm_Error = (%d)", ErrorCheck()); Print("\n// Overflow_Error? (%d)\n", Overflow_Error); Print("\n// the numbers of Overflow_Error (%d)", nnflow); #endif //Print("\n//Mfwalk: (6)\n"); //idString(resF,"//** Mfwalk: resF"); return(idCopy(resF)); } /******************************************************************************* * The implementation of the fractal walk algorithm with random element * * * * The main procedur Mfwalk calls the recursive Subroutine * * rec_r_fractal_call to compute the wanted Groebner basis. * * At the main procedure we compute the reduced Groebner basis w.r.t. a "fast" * * order, e.g. "dp" and a sequence of weight vectors which are row vectors * * of a matrix. This matrix defines the given monomial order, e.g. "lp" * *******************************************************************************/ ideal Mfrwalk(ideal G, intvec* ivstart, intvec* ivtarget, int weight_rad, int reduction, int printout) { BITSET save1 = si_opt_1; // save current options //check that weight radius is valid if(weight_rad < 0) { Werror("Invalid radius.\n"); return NULL; } if(reduction == 0) { si_opt_1 &= (~Sy_bit(OPT_REDSB)); // no reduced Groebner basis si_opt_1 &= (~Sy_bit(OPT_REDTAIL)); // not tail reductions } Set_Error(FALSE); Overflow_Error = FALSE; //Print("// pSetm_Error = (%d)", ErrorCheck()); //Print("\n// ring ro = %s;", rString(currRing)); nnflow = 0; Xngleich = 0; Xcall = 0; #ifdef TIME_TEST xtif=0; xtstd=0; xtlift=0; xtred=0; xtnw=0; xtextra=0; xftinput = clock(); #endif ring oldRing = currRing; int i, nV = currRing->N; XivNull = new intvec(nV); Xivinput = ivtarget; ngleich = 0; #ifdef TIME_TEST to=clock(); #endif ideal I = MstdCC(G); G = NULL; #ifdef TIME_TEST xftostd=clock()-to; #endif Xsigma = ivstart; Xnlev=nV; #ifdef FIRST_STEP_FRACTAL ideal Gw = MwalkInitialForm(I, ivstart); for(i=IDELEMS(Gw)-1; i>=0; i--) { if((Gw->m[i]!=NULL) // len >=0 && (Gw->m[i]->next!=NULL) // len >=1 && (Gw->m[i]->next->next!=NULL)) // len >=2 { intvec* iv_dp = MivUnit(nV); // define (1,1,...,1) intvec* Mdp; if(ivstart->length() == nV) { if(MivSame(ivstart, iv_dp) != 1) Mdp = MivWeightOrderdp(ivstart); else Mdp = MivMatrixOrderdp(nV); } else { Mdp = ivstart; } Xsigma = Mfpertvector(I, Mdp); Overflow_Error = FALSE; delete Mdp; delete iv_dp; break; } } idDelete(&Gw); #endif ideal I1; intvec* Mlp; Xivlp = Mivlp(nV); if(ivtarget->length() == nV) { if(MivComp(ivtarget, Xivlp) != 1) { if (rParameter(currRing) != NULL) DefRingPar(ivtarget); else rChangeCurrRing(VMrDefault(ivtarget)); I1 = idrMoveR(I, oldRing,currRing); Mlp = MivWeightOrderlp(ivtarget); Xtau = Mfpertvector(I1, Mlp); } else { if (rParameter(currRing) != NULL) DefRingParlp(); else VMrDefaultlp(); I1 = idrMoveR(I, oldRing,currRing); Mlp = MivMatrixOrderlp(nV); Xtau = Mfpertvector(I1, Mlp); } } else { rChangeCurrRing(VMatrDefault(ivtarget)); I1 = idrMoveR(I,oldRing,currRing); Mlp = ivtarget; Xtau = Mfpertvector(I1, Mlp); } delete Mlp; Overflow_Error = FALSE; //ivString(Xsigma, "Xsigma"); //ivString(Xtau, "Xtau"); id_Delete(&I, oldRing); ring tRing = currRing; if(ivtarget->length() == nV) { /* if (rParameter(currRing) != NULL) DefRingPar(ivstart); else rChangeCurrRing(VMrDefault(ivstart)); */ rChangeCurrRing(VMrRefine(ivtarget,ivstart)); } else { //rChangeCurrRing(VMatrDefault(ivstart)); rChangeCurrRing(VMatrRefine(ivtarget,ivstart)); } I = idrMoveR(I1,tRing,currRing); #ifdef TIME_TEST to=clock(); #endif ideal J = MstdCC(I); idDelete(&I); #ifdef TIME_TEST xftostd=xftostd+clock()-to; #endif ideal resF; ring helpRing = currRing; J = rec_r_fractal_call(J,1,ivtarget,weight_rad,reduction,printout); //idString(J,"//*** Mfrwalk: J"); //Print("\n//** Mfrwalk hier (1)\n"); rChangeCurrRing(oldRing); //Print("\n//** Mfrwalk hier (2)\n"); resF = idrMoveR(J, helpRing,currRing); //Print("\n//** Mfrwalk hier (3)\n"); //idSkipZeroes(resF); //Print("\n//** Mfrwalk hier (4)\n"); si_opt_1 = save1; //set original options, e. g. option(RedSB) delete Xivlp; //delete Xsigma; delete Xtau; delete XivNull; //Print("\n//** Mfrwalk hier (5)\n"); #ifdef TIME_TEST TimeStringFractal(xftinput, xftostd, xtif, xtstd, xtextra, xtlift, xtred, xtnw); // Print("\n// pSetm_Error = (%d)", ErrorCheck()); Print("\n// Overflow_Error? (%d)\n", Overflow_Error); Print("\n// the numbers of Overflow_Error (%d)", nnflow); #endif //Print("\n//** Mfrwalk hier (6)\n"); //idString(resF,"resF"); //Print("\n//** Mfrwalk hier (7)\n"); return(resF); } /******************************************************* * Tran's algorithm * * * * use kStd, if nP = 0, else call Ab_Rec_Pert (LastGB) * *******************************************************/ ideal TranMImprovwalk(ideal G,intvec* curr_weight,intvec* target_tmp, int nP) { #ifdef TIME_TEST clock_t mtim = clock(); #endif Set_Error(FALSE ); Overflow_Error = FALSE; //Print("// pSetm_Error = (%d)", ErrorCheck()); //Print("\n// ring ro = %s;", rString(currRing)); clock_t tostd, tif=0, tstd=0, tlift=0, tred=0, tnw=0, textra=0; #ifdef TIME_TEST clock_t tinput = clock(); #endif int nsteppert=0, i, nV = currRing->N, nwalk=0, npert_tmp=0; int *npert=(int*)omAlloc(2*nV*sizeof(int)); ideal Gomega, M,F, G1, Gomega1, Gomega2, M1, F1; //ring endRing; ring newRing, oldRing, lpRing; intvec* next_weight; intvec* ivNull = new intvec(nV); //define (0,...,0) intvec* iv_dp = MivUnit(nV);// define (1,1,...,1) intvec* iv_lp = Mivlp(nV); //define (1,0,...,0) ideal H0; //ideal H1; ideal H2, Glp; int nGB, endwalks = 0, nwalkpert=0, npertstep=0; intvec* Mlp = MivMatrixOrderlp(nV); intvec* vector_tmp = new intvec(nV); #ifndef BUCHBERGER_ALG intvec* hilb_func; #endif // to avoid (1,0,...,0) as the target vector intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) (*last_omega)[i] = 1; (*last_omega)[0] = 10000; // intvec* extra_curr_weight = new intvec(nV); intvec* target_weight = new intvec(nV); for(i=nV-1; i>=0; i--) (*target_weight)[i] = (*target_tmp)[i]; ring XXRing = currRing; newRing = currRing; to=clock(); // compute a red. GB w.r.t. the help ring if(MivComp(curr_weight, iv_dp) == 1) //rOrdStr(currRing) = "dp" G = MstdCC(G); else { //rOrdStr(currRing) = (a(.c_w..),lp,C) if (rParameter(currRing) != NULL) DefRingPar(curr_weight); else rChangeCurrRing(VMrDefault(curr_weight)); G = idrMoveR(G, XXRing,currRing); G = MstdCC(G); } tostd=clock()-to; #ifdef REPRESENTATION_OF_SIGMA ideal Gw = MwalkInitialForm(G, curr_weight); if(islengthpoly2(Gw)==1) { intvec* MDp; if(MivComp(curr_weight, iv_dp) == 1) MDp = MatrixOrderdp(nV); //MivWeightOrderlp(iv_dp); else MDp = MivWeightOrderlp(curr_weight); curr_weight = RepresentationMatrix_Dp(G, MDp); delete MDp; ring exring = currRing; if (rParameter(currRing) != NULL) DefRingPar(curr_weight); else rChangeCurrRing(VMrDefault(curr_weight)); to=clock(); Gw = idrMoveR(G, exring,currRing); G = MstdCC(Gw); Gw = NULL; tostd=tostd+clock()-to; //ivString(curr_weight,"rep. sigma"); goto COMPUTE_NEW_VECTOR; } idDelete(&Gw); delete iv_dp; #endif while(1) { to=clock(); /* compute an initial form ideal of w.r.t. "curr_vector" */ Gomega = MwalkInitialForm(G, curr_weight); tif=tif+clock()-to; #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); else hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); #endif // BUCHBERGER_ALG oldRing = currRing; /* define a new ring that its ordering is "(a(curr_weight),lp) */ if (rParameter(currRing) != NULL) DefRingPar(curr_weight); else rChangeCurrRing(VMrDefault(curr_weight)); newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); to=clock(); /* compute a reduced Groebner basis of w.r.t. "newRing" */ #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif // BUCHBERGER_ALG tstd=tstd+clock()-to; /* change the ring to oldRing */ rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); to=clock(); /* compute a representation of the generators of submod (M) with respect to those of mod (Gomega). Gomega is a reduced Groebner basis w.r.t. the current ring */ F = MLifttwoIdeal(Gomega2, M1, G); tlift=tlift+clock()-to; idDelete(&M1); idDelete(&Gomega2); idDelete(&G); /* change the ring to newRing */ rChangeCurrRing(newRing); F1 = idrMoveR(F, oldRing,currRing); to=clock(); /* reduce the Groebner basis w.r.t. new ring */ G = kInterRedCC(F1, NULL); tred=tred+clock()-to; idDelete(&F1); COMPUTE_NEW_VECTOR: newRing = currRing; nwalk++; nwalkpert++; to=clock(); // compute a next weight vector next_weight = MwalkNextWeightCC(curr_weight,target_weight, G); tnw=tnw+clock()-to; #ifdef PRINT_VECTORS MivString(curr_weight, target_weight, next_weight); #endif /* check whether the computed intermediate weight vector is in the correct cone; sometimes it is very big e.g. s7, cyc7. If it is NOT in the correct cone, then compute directly a reduced Groebner basis with respect to the lexicographic ordering for the known Groebner basis that it is computed in the last step. */ //if(test_w_in_ConeCC(G, next_weight) != 1) if(Overflow_Error == TRUE) { OMEGA_OVERFLOW_TRAN_NEW: //Print("\n// takes %d steps!", nwalk-1); //Print("\n//ring lastRing = %s;", rString(currRing)); #ifdef TEST_OVERFLOW goto BE_FINISH; #endif /* #ifdef CHECK_IDEAL_MWALK idElements(G, "G"); //headidString(G, "G"); #endif */ if(MivSame(target_tmp, iv_lp) == 1) if (rParameter(currRing) != NULL) DefRingParlp(); else VMrDefaultlp(); else if (rParameter(currRing) != NULL) DefRingPar(target_tmp); else rChangeCurrRing(VMrDefault(target_tmp)); lpRing = currRing; G1 = idrMoveR(G, newRing,currRing); to=clock(); /*apply kStd or LastGB to compute a lex. red. Groebner basis of */ if(nP == 0 || MivSame(target_tmp, iv_lp) == 0){ //Print("\n\n// calls \"std in ring r_%d = %s;", nwalk, rString(currRing)); G = MstdCC(G1);//no result for qnt1 } else { rChangeCurrRing(newRing); G1 = idrMoveR(G1, lpRing,currRing); //Print("\n\n// calls \"LastGB\" (%d) to compute a GB", nV-1); G = LastGB(G1, curr_weight, nV-1); //no result for kats7 rChangeCurrRing(lpRing); G = idrMoveR(G, newRing,currRing); } textra=clock()-to; npert[endwalks]=nwalk-npert_tmp; npert_tmp = nwalk; endwalks ++; break; } /* check whether the computed Groebner basis is really a Groebner basis. If not, we perturb the target vector with the maximal "perturbation" degree.*/ if(MivComp(next_weight, target_weight) == 1 || MivComp(next_weight, curr_weight) == 1 ) { //Print("\n//ring r_%d = %s;", nwalk, rString(currRing)); //compute the number of perturbations and its step npert[endwalks]=nwalk-npert_tmp; npert_tmp = nwalk; endwalks ++; /*it is very important if the walk only uses one step, e.g. Fate, liu*/ if(endwalks == 1 && MivComp(next_weight, curr_weight) == 1){ rChangeCurrRing(XXRing); G = idrMoveR(G, newRing,currRing); goto FINISH; } H0 = id_Head(G,currRing); if(MivSame(target_tmp, iv_lp) == 1) if (rParameter(currRing) != NULL) DefRingParlp(); else VMrDefaultlp(); else if (rParameter(currRing) != NULL) DefRingPar(target_tmp); else rChangeCurrRing(VMrDefault(target_tmp)); lpRing = currRing; Glp = idrMoveR(G, newRing,currRing); H2 = idrMoveR(H0, newRing,currRing); /* Apply Lemma 2.2 in Collart et. al (1997) to check whether cone(k-1) is equal to cone(k) */ nGB = 1; for(i=IDELEMS(Glp)-1; i>=0; i--) { poly t; if((t=pSub(pHead(Glp->m[i]), pCopy(H2->m[i]))) != NULL) { pDelete(&t); idDelete(&H2);//5.5.02 nGB = 0; //i.e. Glp is no reduced Groebner basis break; } pDelete(&t); } idDelete(&H2);//5.5.02 if(nGB == 1) { G = Glp; Glp = NULL; break; } /* perturb the target weight vector, if the vector target_tmp stays in many cones */ poly p; BOOLEAN plength3 = FALSE; for(i=IDELEMS(Glp)-1; i>=0; i--) { p = MpolyInitialForm(Glp->m[i], target_tmp); if(p->next != NULL && p->next->next != NULL && p->next->next->next != NULL) { Overflow_Error = FALSE; for(i=0; i=0; i--) (*curr_weight)[i] = (*next_weight)[i]; delete next_weight; }//while #ifdef TEST_OVERFLOW BE_FINISH: #endif rChangeCurrRing(XXRing); G = idrMoveR(G, lpRing,currRing); FINISH: delete ivNull; delete next_weight; delete iv_lp; omFree(npert); /* #ifdef TIME_TEST Print("\n// Computation took %d steps and %.2f sec", nwalk, ((double) (clock()-mtim)/1000000)); TimeStringFractal(tinput, tostd, tif, tstd, textra, tlift, tred, tnw); // Print("\n// pSetm_Error = (%d)", ErrorCheck()); Print("\n// Overflow_Error? (%d)\n", Overflow_Error); #endif */ return(G); } #if 0 /******************************************************* * Tran's algorithm with random element * * * * use kStd, if nP = 0, else call Ab_Rec_Pert (LastGB) * *******************************************************/ ideal TranMrImprovwalk(ideal G,intvec* curr_weight,intvec* target_tmp, int nP, int weight_rad, int pert_deg) { #ifdef TIME_TEST clock_t mtim = clock(); #endif Set_Error(FALSE ); Overflow_Error = FALSE; //Print("// pSetm_Error = (%d)", ErrorCheck()); //Print("\n// ring ro = %s;", rString(currRing)); clock_t tostd, tif=0, tstd=0, tlift=0, tred=0, tnw=0, textra=0; #ifdef TIME_TEST clock_t tinput = clock(); #endif int nsteppert=0, i, nV = currRing->N, nwalk=0, npert_tmp=0; int *npert=(int*)omAlloc(2*nV*sizeof(int)); ideal Gomega, M,F, G1, Gomega1, Gomega2, M1, F1; //ring endRing; ring newRing, oldRing, lpRing; intvec* next_weight; intvec* ivNull = new intvec(nV); //define (0,...,0) intvec* iv_dp = MivUnit(nV);// define (1,1,...,1) intvec* iv_lp = Mivlp(nV); //define (1,0,...,0) ideal H0; //ideal H1; ideal H2, Glp; int weight_norm, nGB, endwalks = 0, nwalkpert=0, npertstep=0; intvec* Mlp = MivMatrixOrderlp(nV); intvec* vector_tmp = new intvec(nV); #ifndef BUCHBERGER_ALG intvec* hilb_func; #endif // to avoid (1,0,...,0) as the target vector intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) { (*last_omega)[i] = 1; } (*last_omega)[0] = 10000; //intvec* extra_curr_weight = new intvec(nV); intvec* target_weight = new intvec(nV); for(i=nV-1; i>=0; i--) { (*target_weight)[i] = (*target_tmp)[i]; } ring XXRing = currRing; newRing = currRing; to=clock(); // compute a red. GB w.r.t. the help ring if(MivComp(curr_weight, iv_dp) == 1) { //rOrdStr(currRing) = "dp" G = MstdCC(G); } else { //rOrdStr(currRing) = (a(.c_w..),lp,C) if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } G = idrMoveR(G, XXRing,currRing); G = MstdCC(G); } tostd=clock()-to; #ifdef REPRESENTATION_OF_SIGMA ideal Gw = MwalkInitialForm(G, curr_weight); if(islengthpoly2(Gw)==1) { intvec* MDp; if(MivComp(curr_weight, iv_dp) == 1) { MDp = MatrixOrderdp(nV); //MivWeightOrderlp(iv_dp); } else { MDp = MivWeightOrderlp(curr_weight); } curr_weight = RepresentationMatrix_Dp(G, MDp); delete MDp; ring exring = currRing; if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } to=clock(); Gw = idrMoveR(G, exring,currRing); G = MstdCC(Gw); Gw = NULL; tostd=tostd+clock()-to; //ivString(curr_weight,"rep. sigma"); goto COMPUTE_NEW_VECTOR; } idDelete(&Gw); delete iv_dp; #endif while(1) { to=clock(); // compute an initial form ideal of w.r.t. "curr_vector" Gomega = MwalkInitialForm(G, curr_weight); tif=tif+clock()-to; #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) { hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); } else { hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); } #endif // BUCHBERGER_ALG oldRing = currRing; // define a new ring with ordering "(a(curr_weight),lp) if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); to=clock(); // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif tstd=tstd+clock()-to; // change the ring to oldRing rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); to=clock(); // compute a representation of the generators of submod (M) with respect to those of mod (Gomega). // Gomega is a reduced Groebner basis w.r.t. the current ring F = MLifttwoIdeal(Gomega2, M1, G); tlift=tlift+clock()-to; idDelete(&M1); idDelete(&Gomega2); idDelete(&G); // change the ring to newRing rChangeCurrRing(newRing); F1 = idrMoveR(F, oldRing,currRing); to=clock(); // reduce the Groebner basis w.r.t. new ring G = kInterRedCC(F1, NULL); tred=tred+clock()-to; idDelete(&F1); COMPUTE_NEW_VECTOR: newRing = currRing; nwalk++; nwalkpert++; to=clock(); // compute a next weight vector //next_weight = MwalkNextWeightCC(curr_weight,target_weight, G); next_weight = MWalkRandomNextWeight(G, curr_weight, target_weight, weight_rad, pert_deg); /* next_weight = MkInterRedNextWeight(curr_weight,target_weight,G); if(MivComp(next_weight, target_weight) != 1) { // compute a perturbed next weight vector "next_weight1" intvec* next_weight1 = MkInterRedNextWeight(MPertVectors(G, MivMatrixOrder(curr_weight), pert_deg), target_weight, G); // compare next_weight and next_weight1 ideal G_test = MwalkInitialForm(G, next_weight); ideal G_test1 = MwalkInitialForm(G, next_weight1); if(IDELEMS(G_test1) <= IDELEMS(G_test)) { next_weight = ivCopy(next_weight1); } delete next_weight1; // compute a random next weight vector "next_weight2" intvec* next_weight22 = ivCopy(target_weight); // Print("\n// size of target_weight = %d", sizeof((*target_weight))); k = 0; while(test_w_in_ConeCC(G, next_weight22) == 0 && k < 11) { k++; if(k>10) { break; } weight_norm = 0; while(weight_norm == 0) { for(i=nV-1; i>=0; i--) { // Print("\n// next_weight[%d] = %d", i, (*next_weight)[i]); (*next_weight22)[i] = rand() % 60000 - 30000; weight_norm = weight_norm + (*next_weight22)[i]*(*next_weight22)[i]; } weight_norm = 1 + floor(sqrt(weight_norm)); } for(i=nV-1; i>=0; i--) { if((*next_weight22)[i] < 0) { (*next_weight22)[i] = 1 + (*curr_weight)[i] + floor(weight_rad*(*next_weight22)[i]/weight_norm); } else { (*next_weight22)[i] = (*curr_weight)[i] + floor(weight_rad*(*next_weight22)[i]/weight_norm); } // Print("\n// next_weight22[%d] = %d", i, (*next_weight22)[i]); } } if(test_w_in_ConeCC(G, next_weight22) == 1) { // compare next_weight and next_weight2 // Print("\n// ZUFALL IM KEGEL"); intvec* next_weight2 = MkInterRedNextWeight(next_weight22, target_weight, G); ideal G_test2 = MwalkInitialForm(G, next_weight2); if(IDELEMS(G_test2) <= IDELEMS(G_test)) { if(IDELEMS(G_test2) <= IDELEMS(G_test1)) { // Print("\n// ZUFALL BENUTZT!\n"); next_weight = ivCopy(next_weight2); } } idDelete(&G_test2); delete next_weight2; } delete next_weight22; idDelete(&G_test); idDelete(&G_test1); }*/ tnw=tnw+clock()-to; #ifdef PRINT_VECTORS MivString(curr_weight, target_weight, next_weight); #endif /* check whether the computed intermediate weight vector is in the correct cone; sometimes it is very big e.g. s7, cyc7. If it is NOT in the correct cone, then compute directly a reduced Groebner basis with respect to the lexicographic ordering for the known Groebner basis that it is computed in the last step. */ //if(test_w_in_ConeCC(G, next_weight) != 1) if(Overflow_Error == TRUE) { OMEGA_OVERFLOW_TRAN_NEW: //Print("\n// takes %d steps!", nwalk-1); //Print("\n//ring lastRing = %s;", rString(currRing)); #ifdef TEST_OVERFLOW goto BE_FINISH; #endif #ifdef CHECK_IDEAL_MWALK idElements(G, "G"); //headidString(G, "G"); #endif if(MivSame(target_tmp, iv_lp) == 1) { if (rParameter(currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } } else { if (rParameter(currRing) != NULL) { DefRingPar(target_tmp); } else { rChangeCurrRing(VMrDefault(target_tmp)); } } lpRing = currRing; G1 = idrMoveR(G, newRing,currRing); to=clock(); // apply kStd or LastGB to compute a lex. red. Groebner basis of if(nP == 0 || MivSame(target_tmp, iv_lp) == 0) { //Print("\n\n// calls \"std in ring r_%d = %s;", nwalk, rString(currRing)); G = MstdCC(G1);//no result for qnt1 } else { rChangeCurrRing(newRing); G1 = idrMoveR(G1, lpRing,currRing); //Print("\n\n// calls \"LastGB\" (%d) to compute a GB", nV-1); G = LastGB(G1, curr_weight, nV-1); //no result for kats7 rChangeCurrRing(lpRing); G = idrMoveR(G, newRing,currRing); } textra=clock()-to; npert[endwalks]=nwalk-npert_tmp; npert_tmp = nwalk; endwalks ++; break; } // check whether the computed Groebner basis is really a Groebner basis. // If not, we perturb the target vector with the maximal "perturbation" degree. if(MivComp(next_weight, target_weight) == 1 || MivComp(next_weight, curr_weight) == 1 ) { //Print("\n//ring r_%d = %s;", nwalk, rString(currRing)); //compute the number of perturbations and its step npert[endwalks]=nwalk-npert_tmp; npert_tmp = nwalk; endwalks ++; // it is very important if the walk only uses one step, e.g. Fate, liu if(endwalks == 1 && MivComp(next_weight, curr_weight) == 1) { rChangeCurrRing(XXRing); G = idrMoveR(G, newRing,currRing); goto FINISH; } H0 = id_Head(G,currRing); if(MivSame(target_tmp, iv_lp) == 1) { if (rParameter(currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } } else { if (rParameter(currRing) != NULL) { DefRingPar(target_tmp); } else { rChangeCurrRing(VMrDefault(target_tmp)); } } lpRing = currRing; Glp = idrMoveR(G, newRing,currRing); H2 = idrMoveR(H0, newRing,currRing); // Apply Lemma 2.2 in Collart et. al (1997) to check whether cone(k-1) is equal to cone(k) nGB = 1; for(i=IDELEMS(Glp)-1; i>=0; i--) { poly t; if((t=pSub(pHead(Glp->m[i]), pCopy(H2->m[i]))) != NULL) { pDelete(&t); idDelete(&H2);//5.5.02 nGB = 0; //i.e. Glp is no reduced Groebner basis break; } pDelete(&t); } idDelete(&H2);//5.5.02 if(nGB == 1) { G = Glp; Glp = NULL; break; } // perturb the target weight vector, if the vector target_tmp stays in many cones poly p; BOOLEAN plength3 = FALSE; for(i=IDELEMS(Glp)-1; i>=0; i--) { p = MpolyInitialForm(Glp->m[i], target_tmp); if(p->next != NULL && p->next->next != NULL && p->next->next->next != NULL) { Overflow_Error = FALSE; for(i=0; i=0; i--) { (*curr_weight)[i] = (*next_weight)[i]; } delete next_weight; } // end of while #ifdef TEST_OVERFLOW BE_FINISH: #endif rChangeCurrRing(XXRing); G = idrMoveR(G, lpRing,currRing); FINISH: delete ivNull; delete next_weight; delete iv_lp; omFree(npert); #ifdef TIME_TEST Print("\n// Computation took %d steps and %.2f sec", nwalk, ((double) (clock()-mtim)/1000000)); TimeStringFractal(tinput, tostd, tif, tstd, textra, tlift, tred, tnw); Print("\n// pSetm_Error = (%d)", ErrorCheck()); Print("\n// Overflow_Error? (%d)\n", Overflow_Error); #endif return(G); } #endif /***************************************************************** * compute the reduced Groebner basis of an ideal w.r.t. lp * *****************************************************************/ static ideal Mpwalk_MAltwalk1(ideal Go, intvec* curr_weight, int tp_deg) { Overflow_Error = FALSE; // BOOLEAN nOverflow_Error = FALSE; clock_t tproc=0; clock_t tinput=clock(); int i, nV = currRing->N; //check that perturbation degree is valid if(tp_deg < 1 || tp_deg > nV) { Werror("Invalid perturbation degree.\n"); return NULL; } int nwalk=0, endwalks=0, ntestwinC=1; int tp_deg_tmp = tp_deg; ideal Gomega, M, F, G, M1, F1, Gomega1, Gomega2, G1; ring newRing, oldRing, TargetRing; intvec* next_weight; intvec* ivNull = new intvec(nV); ring YXXRing = currRing; intvec* iv_M_dpp = MivMatrixOrderlp(nV); intvec* target_weight;// = Mivlp(nV); ideal ssG; // perturb the target vector while(1) { if(Overflow_Error == FALSE) { if (rParameter(currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } TargetRing = currRing; ssG = idrMoveR(Go,YXXRing,currRing); } Overflow_Error = FALSE; if(tp_deg != 1) { target_weight = MPertVectors(ssG, iv_M_dpp, tp_deg); } else { target_weight = Mivlp(nV); break; } if(Overflow_Error == FALSE) { break; } Overflow_Error = TRUE; tp_deg --; } if(tp_deg != tp_deg_tmp) { Overflow_Error = TRUE; //nOverflow_Error = TRUE; } // Print("\n// tp_deg = %d", tp_deg); // ivString(target_weight, "pert target"); delete iv_M_dpp; #ifndef BUCHBERGER_ALG intvec* hilb_func; #endif // to avoid (1,0,...,0) as the target vector intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) { (*last_omega)[i] = 1; } (*last_omega)[0] = 10000; rChangeCurrRing(YXXRing); G = idrMoveR(ssG, TargetRing,currRing); while(1) { nwalk ++; nstep ++; if(nwalk==1) { goto FIRST_STEP; } to=clock(); // compute an initial form ideal of w.r.t. "curr_vector" Gomega = MwalkInitialForm(G, curr_weight); xtif=xtif+clock()-to; #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); else hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); #endif oldRing = currRing; // define a new ring that its ordering is "(a(curr_weight),lp) if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); /* #ifdef ENDWALKS if(endwalks == 1) { Print("\n// it is %d-th step!!", nwalk); idString(Gomega1, "Gw"); PrintS("\n// compute a rGB of Gw:"); } #endif */ to=clock(); // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif // BUCHBERGER_ALG xtstd=xtstd+clock()-to; // change the ring to oldRing rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); to=clock(); // if(endwalks == 1){PrintS("\n// Lifting is still working:");} // compute a reduced Groebner basis of w.r.t. "newRing" by the lifting process F = MLifttwoIdeal(Gomega2, M1, G); xtlift=xtlift+clock()-to; idDelete(&M1); idDelete(&Gomega2); idDelete(&G); // change the ring to newRing rChangeCurrRing(newRing); F1 = idrMoveR(F, oldRing,currRing); to=clock(); //if(endwalks == 1){ PrintS("\n// InterRed is still working:");} // reduce the Groebner basis w.r.t. the new ring G = kInterRedCC(F1, NULL); xtred=xtred+clock()-to; idDelete(&F1); if(endwalks == 1) break; FIRST_STEP: Overflow_Error=FALSE; to=clock(); // compute a next weight vector next_weight = MkInterRedNextWeight(curr_weight,target_weight, G); xtnw=xtnw+clock()-to; #ifdef PRINT_VECTORS MivString(curr_weight, target_weight, next_weight); #endif if(Overflow_Error == TRUE) { delete next_weight; if(tp_deg > 1){ //nOverflow_Error = Overflow_Error; tproc = tproc+clock()-tinput; //Print("\n// A subroutine takes %d steps and calls \"Mpwalk\" (1,%d):", nwalk, tp_deg-1); G1 = Mpwalk_MAltwalk1(G, curr_weight, tp_deg-1); goto MPW_Finish; } else { newRing = currRing; ntestwinC = 0; break; } } if(MivComp(next_weight, ivNull) == 1) { newRing = currRing; delete next_weight; break; } if(MivComp(next_weight, target_weight) == 1) { endwalks = 1; } for(i=nV-1; i>=0; i--) { //(*extra_curr_weight)[i] = (*curr_weight)[i]; (*curr_weight)[i] = (*next_weight)[i]; } delete next_weight; }//while // check whether the pertubed target vector is correct //define and execute ring with lex. order if (rParameter(currRing) != NULL) { DefRingParlp(); } else { VMrDefaultlp(); } G1 = idrMoveR(G, newRing,currRing); if( test_w_in_ConeCC(G1, target_weight) != 1 || ntestwinC == 0) { //PrintS("\n// The perturbed target vector doesn't STAY in the correct cone!!"); if(tp_deg == 1) { //Print("\n// subroutine takes %d steps and applys \"std\"", nwalk); to=clock(); ideal G2 = MstdCC(G1); xtextra=xtextra+clock()-to; idDelete(&G1); G1 = G2; G2 = NULL; } else { //nOverflow_Error = Overflow_Error; tproc = tproc+clock()-tinput; // Print("\n// B subroutine takes %d steps and calls \"Mpwalk\" (1,%d) :", nwalk, tp_deg-1); G1 = Mpwalk_MAltwalk1(G1, curr_weight, tp_deg-1); } } MPW_Finish: newRing = currRing; rChangeCurrRing(YXXRing); ideal result = idrMoveR(G1, newRing,currRing); delete ivNull; delete target_weight; //Print("\n// \"Mpwalk\" (1,%d) took %d steps and %.2f sec. Overflow_Error (%d)", tp_deg, nwalk, ((double) clock()-tinput)/1000000, nOverflow_Error); //Print("\n// Mprwalk took %d steps. Ring= %s;\n", nwalk, rString(currRing)); return(result); } /******************************************************************* * Implementation of the first alternative Groebner Walk Algorithm * *******************************************************************/ ideal MAltwalk1(ideal Go, int op_deg, int tp_deg, intvec* curr_weight, intvec* target_weight) { Set_Error(FALSE ); Overflow_Error = FALSE; #ifdef TIME_TEST BOOLEAN nOverflow_Error = FALSE; #endif // Print("// pSetm_Error = (%d)", ErrorCheck()); xtif=0; xtstd=0; xtlift=0; xtred=0; xtnw=0; xtextra=0; xftinput = clock(); clock_t tostd, tproc; nstep = 0; int i, nV = currRing->N; int nwalk=0, endwalks=0; int op_tmp = op_deg; ideal Gomega, M, F, G, Gomega1, Gomega2, M1, F1; ring newRing, oldRing; intvec* next_weight; intvec* iv_M_dp; intvec* ivNull = new intvec(nV); intvec* iv_dp = MivUnit(nV);// define (1,1,...,1) intvec* exivlp = Mivlp(nV); //intvec* extra_curr_weight = new intvec(nV); #ifndef BUCHBERGER_ALG intvec* hilb_func; #endif intvec* cw_tmp = curr_weight; // to avoid (1,0,...,0) as the target vector intvec* last_omega = new intvec(nV); for(i=nV-1; i>0; i--) { (*last_omega)[i] = 1; } (*last_omega)[0] = 10000; ring XXRing = currRing; to=clock(); /* compute a pertubed weight vector of the original weight vector. The perturbation degree is recursive decrease until that vector stays inn the correct cone. */ while(1) { if(Overflow_Error == FALSE) { if(MivComp(curr_weight, iv_dp) == 1) { //rOrdStr(currRing) = "dp" if(op_tmp == op_deg) { G = MstdCC(Go); if(op_deg != 1) { iv_M_dp = MivMatrixOrderdp(nV); } } } } else { if(op_tmp == op_deg) { //rOrdStr(currRing) = (a(...),lp,C) if (rParameter(currRing) != NULL) { DefRingPar(cw_tmp); } else { rChangeCurrRing(VMrDefault(cw_tmp)); } G = idrMoveR(Go, XXRing,currRing); G = MstdCC(G); if(op_deg != 1) iv_M_dp = MivMatrixOrder(cw_tmp); } } Overflow_Error = FALSE; if(op_deg != 1) { curr_weight = MPertVectors(G, iv_M_dp, op_deg); } else { curr_weight = cw_tmp; break; } if(Overflow_Error == FALSE) { break; } Overflow_Error = TRUE; op_deg --; } tostd=clock()-to; if(op_tmp != 1 ) delete iv_M_dp; delete iv_dp; if(currRing->order[0] == ringorder_a) goto NEXT_VECTOR; while(1) { nwalk ++; nstep ++; to = clock(); // compute an initial form ideal of w.r.t. "curr_vector" Gomega = MwalkInitialForm(G, curr_weight); xtif=xtif+clock()-to; #if 0 if(Overflow_Error == TRUE) { for(i=nV-1; i>=0; i--) (*curr_weight)[i] = (*extra_curr_weight)[i]; delete extra_curr_weight; newRing = currRing; goto MSTD_ALT1; } #endif #ifndef BUCHBERGER_ALG if(isNolVector(curr_weight) == 0) { hilb_func = hFirstSeries(Gomega,NULL,NULL,curr_weight,currRing); } else { hilb_func = hFirstSeries(Gomega,NULL,NULL,last_omega,currRing); } #endif // BUCHBERGER_ALG oldRing = currRing; // define a new ring which ordering is "(a(curr_weight),lp) if (rParameter(currRing) != NULL) { DefRingPar(curr_weight); } else { rChangeCurrRing(VMrDefault(curr_weight)); } newRing = currRing; Gomega1 = idrMoveR(Gomega, oldRing,currRing); to=clock(); // compute a reduced Groebner basis of w.r.t. "newRing" #ifdef BUCHBERGER_ALG M = MstdhomCC(Gomega1); #else M=kStd(Gomega1,NULL,isHomog,NULL,hilb_func,0,NULL,curr_weight); delete hilb_func; #endif // BUCHBERGER_ALG xtstd=xtstd+clock()-to; // change the ring to oldRing rChangeCurrRing(oldRing); M1 = idrMoveR(M, newRing,currRing); Gomega2 = idrMoveR(Gomega1, newRing,currRing); to=clock(); // compute a reduced Groebner basis of w.r.t. "newRing" by the lifting process F = MLifttwoIdeal(Gomega2, M1, G); xtlift=xtlift+clock()-to; idDelete(&M1); idDelete(&Gomega2); idDelete(&G); // change the ring to newRing rChangeCurrRing(newRing); F1 = idrMoveR(F, oldRing,currRing); if (oldRing!=IDRING(currRingHdl)) rDelete(oldRing); // do not delete the global currRing oldRing=NULL; to=clock(); // reduce the Groebner basis w.r.t. new ring G = kInterRedCC(F1, NULL); xtred=xtred+clock()-to; idDelete(&F1); if(endwalks == 1) { break; } NEXT_VECTOR: to=clock(); // compute a next weight vector next_weight = MkInterRedNextWeight(curr_weight,target_weight, G); xtnw=xtnw+clock()-to; #ifdef PRINT_VECTORS MivString(curr_weight, target_weight, next_weight); #endif if(Overflow_Error == TRUE) { newRing = currRing; if (rParameter(currRing) != NULL) { DefRingPar(target_weight); } else { rChangeCurrRing(VMrDefault(target_weight)); } F1 = idrMoveR(G, newRing,currRing); G = MstdCC(F1); idDelete(&F1); newRing = currRing; break; //for while } /* G is the wanted Groebner basis if next_weight == curr_weight */ if(MivComp(next_weight, ivNull) == 1) { newRing = currRing; delete next_weight; break; //for while } if(MivComp(next_weight, target_weight) == 1) { if(tp_deg == 1 || MivSame(target_weight, exivlp) == 0) endwalks = 1; else { // MSTD_ALT1: #ifdef TIME_TEST nOverflow_Error = Overflow_Error; #endif tproc = clock()-xftinput; //Print("\n// main routine takes %d steps and calls \"Mpwalk\" (1,%d):", nwalk, tp_deg); // compute the red. GB of w.r.t. the lex order by the "recursive-modified" perturbation walk alg (1,tp_deg) G = Mpwalk_MAltwalk1(G, curr_weight, tp_deg); delete next_weight; break; // for while } } //NOT Changed, to free memory for(i=nV-1; i>=0; i--) { //(*extra_curr_weight)[i] = (*curr_weight)[i]; (*curr_weight)[i] = (*next_weight)[i]; } delete next_weight; }//while rChangeCurrRing(XXRing); ideal result = idrMoveR(G, newRing,currRing); id_Delete(&G, newRing); delete ivNull; if(op_deg != 1 ) { delete curr_weight; } delete exivlp; #ifdef TIME_TEST /* Print("\n// \"Main procedure\" took %d steps, %.2f sec. and Overflow_Error(%d)", nwalk, ((double) tproc)/1000000, nOverflow_Error); TimeStringFractal(xftinput, tostd, xtif, xtstd,xtextra, xtlift, xtred, xtnw); */ // Print("\n// pSetm_Error = (%d)", ErrorCheck()); // Print("\n// Overflow_Error? (%d)", Overflow_Error); // Print("\n// Awalk1 took %d steps.\n", nstep); #endif return(result); } singular-4.0.3+ds/Singular/walk.h000066400000000000000000000053111266270727000166500ustar00rootroot00000000000000/***************************************** * Computer Algebra System SINGULAR * *****************************************/ /* * ABSTRACT: Declaration of the Groebner walk */ #ifndef WALK_H #define WALK_H #include ideal MwalkInitialForm(ideal G, intvec* curr_weight); //compute the next weight vector intvec* MwalkNextWeight(intvec* curr_weight,intvec* target_weight, ideal G); int MivSame(intvec* u , intvec* v); int M3ivSame(intvec* next_weight, intvec* u , intvec* v); intvec* Mivdp(int nR); intvec* Mivlp(int nR); intvec* MivMatrixOrder(intvec* iv); intvec* MivMatrixOrderdp(int iv); intvec* MPertVectors(ideal G, intvec* ivtarget, int pdeg); intvec* MPertVectorslp(ideal G, intvec* ivtarget, int pdeg); intvec* MivMatrixOrderlp(int nV); intvec* Mfpertvector(ideal G, intvec* iv); intvec* MivUnit(int nV); intvec* MivWeightOrderlp(intvec* ivstart); intvec* MivWeightOrderdp(intvec* ivstart); ideal MidLift(ideal Gomega, ideal M); ideal MLiftLmalG(ideal L, ideal G); ideal MLiftLmalGNew(ideal Gomega, ideal M, ideal G); ideal MLiftLmalGMin(ideal L, ideal G); intvec* MkInterRedNextWeight(intvec* iva, intvec* ivb, ideal G); intvec* MPertNextWeight(intvec* iva, ideal G, int deg); intvec* Mivperttarget(ideal G, int ndeg); intvec* MSimpleIV(intvec* iv); /* Okt -- Nov'01 */ // compute a Groebner basis of an ideal G w.r.t. lexicographic order //ideal Mwalk(ideal Go, intvec* orig_M, intvec* target_M); ideal Mwalk(ideal Go, intvec* orig_M, intvec* target_M, ring baseRing, int reduction, int printout); // random walk algorithm to compute a Groebner basis ideal Mrwalk(ideal Go, intvec* orig_M, intvec* target_M, int weight_rad, int pert_deg, int reduction, int printout); /* the perturbation walk algorithm */ ideal Mpwalk(ideal Go, int op_deg, int tp_deg,intvec* curr_weight,intvec* target_weight, int nP, int reduction, int printout); /* the perturbation walk algorithm with random element */ ideal Mprwalk(ideal Go, intvec* orig_M, intvec* target_M, int weight_rad, int op_deg, int tp_deg, int nP, int reduction, int printout); /* The fractal walk algorithm */ ideal Mfwalk(ideal G, intvec* ivstart, intvec* ivtarget, int reduction, int printout); /* The fractal walk algorithm with random element */ ideal Mfrwalk(ideal G, intvec* ivstart, intvec* ivtarget, int weight_rad, int reduction, int printout); /* Implement Tran's idea */ intvec* TranMPertVectorslp(ideal G); ideal TranMImprovwalk(ideal Go, intvec* curr_weight,intvec* target_weight, int nP); /* the first alternative algorithm */ ideal MAltwalk1(ideal G,int op,int tp,intvec* curr_weight,intvec* target_weight); /* the second alternative algorithm */ ideal MAltwalk2(ideal G, intvec* curr_weight, intvec* target_weight); #endif //WALK_H singular-4.0.3+ds/Singular/walk_ip.cc000066400000000000000000000231131266270727000174760ustar00rootroot00000000000000/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* * ABSTRACT: frwalk: interpreter link */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include //#include //#include #include #include #include #include #include #include #include //#include #include #include #include #include /////////////////////////////////////////////////////////////////// //walkProc /////////////////////////////////////////////////////////////////// //Description: The main function for the Walk-Algorithm. Checks the //input-data, and calls walk64 (see walkMain.cc). Returns the new //groebner basis or something else if an error occoured. /////////////////////////////////////////////////////////////////// //Uses: omAlloc0,walkConsistency,rGetGlobalOrderWeightVec, //omFreeSize,sizeof,IDIDEAL,walk64,rSetHdl,idrMoveR,Werror,idInit /////////////////////////////////////////////////////////////////// ideal walkProc(leftv first, leftv second) { WalkState state = WalkOk; BITSET save1,save2; SI_SAVE_OPT(save1,save2); si_opt_1 &= (~Sy_bit(OPT_REDSB)); //make sure option noredSB is set ring destRing = currRing; ideal destIdeal = NULL; idhdl sourceRingHdl = (idhdl)first->data; ring sourceRing = IDRING(sourceRingHdl); rChangeCurrRing( sourceRing ); if(state==WalkOk) { int * vperm = (int *)omAlloc0( (currRing->N+1)*sizeof( int ) ); state= walkConsistency( sourceRing, destRing, vperm ); omFreeSize( (ADDRESS)vperm, (currRing->N+1)*sizeof(int) ); } int64vec* currw64=rGetGlobalOrderWeightVec(sourceRing); int64vec* destVec64=rGetGlobalOrderWeightVec(destRing); ideal sourceIdeal; BOOLEAN sourcIdealIsSB=FALSE; if ( state == WalkOk ) { idhdl ih = currRing->idroot->get( second->Name(), myynest ); if ( (ih != NULL) && (IDTYP(ih)==IDEAL_CMD) ) { sourceIdeal = idCopy(IDIDEAL( ih )); if(hasFlag((leftv)ih,FLAG_STD)){ sourcIdealIsSB=TRUE; } } else { state=WalkNoIdeal; } } if ( state == WalkOk ) { // Now the settings are compatible with Walk state=walk64(sourceIdeal,currw64,destRing,destVec64, destIdeal,sourcIdealIsSB); } SI_RESTORE_OPT(save1,save2);//making sure options are as before function call ring almostDestRing=currRing; rChangeCurrRing(destRing); switch (state) { case WalkOk: destIdeal=idrMoveR(destIdeal,currRing,almostDestRing); break; case WalkIncompatibleRings: Werror("ring %s and current ring are incompatible\n", first->Name() ); destIdeal= NULL; break; case WalkIncompatibleDestRing: Werror( "Order of basering not allowed,\n must be a combination of a,A,lp,dp,Dp,wp,Wp,M and C.\n"); destIdeal= NULL; break; case WalkIncompatibleSourceRing: Werror( "Order of %s not allowed,\n must be a combination of a,A,lp,dp,Dp,wp,Wp,M and C.\n",first->Name()); rChangeCurrRing(destRing); destIdeal= NULL; break; case WalkNoIdeal: Werror( "Can't find ideal %s in ring %s.\n", second->Name(), first->Name() ); destIdeal= NULL; break; case WalkOverFlowError: Werror( "Overflow occured.\n"); destIdeal= NULL; break; default: destIdeal= NULL; } return destIdeal; } /////////////////////////////////////////////////////////////////// //fractalWalkProc /////////////////////////////////////////////////////////////////// //Description: The main function for the Fractalwalk-Algorithm. //Responsible for contact between user and walk64. Checks the //input-data, and calls fractalWalk64. Returns the new groebner //basis or something else if an error occured. /////////////////////////////////////////////////////////////////// //Uses: omAlloc0,fractalWalkConsistency,omFreeSize,sizeof,IDIDEAL, //fractalWalk64,rSetHdl,idrMoveR,Werror,idInit /////////////////////////////////////////////////////////////////// ideal fractalWalkProc(leftv first, leftv second) { //unperturbedStartVectorStrategy SHOULD BE SET BY THE USER THROUGH //A THIRD ARGUMENT. TRUE MEANS THAT THE UNPERTURBED START //VECTOR STRATEGY IS USED AND FALSE THAT THE START VECTOR IS //MAXIMALLY PERTURBED BOOLEAN unperturbedStartVectorStrategy=TRUE; WalkState state = WalkOk; BITSET save1,save2; SI_SAVE_OPT(save1,save2); si_opt_1 &= (~Sy_bit(OPT_REDSB)); //make sure option noredSB is set ring destRing = currRing; ideal destIdeal = NULL; idhdl sourceRingHdl = (idhdl)first->data; rSetHdl( sourceRingHdl ); ring sourceRing = currRing; int * vperm = (int *)omAlloc0( (currRing->N+1)*sizeof( int ) ); state= fractalWalkConsistency( sourceRing, destRing, vperm ); omFreeSize( (ADDRESS)vperm, (currRing->N+1)*sizeof(int) ); ideal sourceIdeal; BOOLEAN sourcIdealIsSB=FALSE; if ( state == WalkOk ) { idhdl ih = currRing->idroot->get( second->Name(), myynest ); if ( (ih != NULL) && (IDTYP(ih)==IDEAL_CMD) ) { sourceIdeal = IDIDEAL( ih ); if(hasFlag((leftv)ih,FLAG_STD)){ sourcIdealIsSB=TRUE; } } else { state=WalkNoIdeal; } } if ( state == WalkOk ) { // Now the settings are compatible with Walk state=fractalWalk64(sourceIdeal,destRing,destIdeal, sourcIdealIsSB, unperturbedStartVectorStrategy); } SI_RESTORE_OPT(save1,save2);//making sure options are as before functiocall if ( state == WalkOk ) { ring almostDestRing=currRing; rChangeCurrRing(destRing); destIdeal=idrMoveR(destIdeal, almostDestRing, destRing); } switch (state) { case WalkOk: destIdeal=sortRedSB(destIdeal); return(destIdeal); break; case WalkIncompatibleRings: Werror( "ring %s and current ring are incompatible\n", first->Name() ); rChangeCurrRing(destRing); destIdeal= NULL; return destIdeal; break; case WalkIncompatibleDestRing: Werror( "Order of basering not allowed,\n must be a combination of lp,dp,Dp,wp,Wp and C or just M.\n"); rChangeCurrRing(destRing); destIdeal= NULL; return destIdeal; break; case WalkIncompatibleSourceRing: Werror( "Order of %s not allowed,\n must be a combination of lp,dp,Dp,wp,Wp and C or just M.\n", first->Name()); rChangeCurrRing(destRing); destIdeal= NULL; return destIdeal; break; case WalkNoIdeal: Werror( "Can't find ideal %s in ring %s.\n", second->Name(), first->Name() ); rChangeCurrRing(destRing); destIdeal= NULL; return destIdeal; break; case WalkOverFlowError: Werror( "Overflow occured in ring %s.\n", first->Name() ); rChangeCurrRing(destRing); destIdeal= NULL; return destIdeal; break; default: rChangeCurrRing(destRing); destIdeal= idInit(1,1); return destIdeal; } return NULL; } /////////////////////////////////////////////////////////////////// //getiv64 /////////////////////////////////////////////////////////////////// //Description: retrieves the int64vec from input list l /////////////////////////////////////////////////////////////////// //Assumes: that the first entry of l is an int64vec /////////////////////////////////////////////////////////////////// //Uses: none /////////////////////////////////////////////////////////////////// int64vec* getiv64(lists l) { return (int64vec*)(l->m[0].data); } /////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// //getint64 /////////////////////////////////////////////////////////////////// //Description: retrieves the int64 from input list l /////////////////////////////////////////////////////////////////// //Assumes: that the second entry of l is an int64 /////////////////////////////////////////////////////////////////// //Uses: none /////////////////////////////////////////////////////////////////// // not used, bad impl. //int64 getint64(lists l) //{ // return (int64)(long)(l->m[1].data); //} /////////////////////////////////////////////////////////////////// singular-4.0.3+ds/Singular/wrapper.cc000066400000000000000000000054571266270727000175430ustar00rootroot00000000000000#include #include #include #include #include #include #include #include //extern int (*ListGreatMove)(jList *,jList *,poly); static BOOLEAN jInitBasis(ideal v, jList **TT,jList **QQ) { if (rHasLocalOrMixedOrdering_currRing()) { WerrorS("janet only for well-orderings"); return TRUE; } Initialization(rOrdStr(currRing)); jList *Q=(jList *)GCM(sizeof(jList)); Q->root=NULL; jList *T=(jList *)GCM(sizeof(jList)); T->root=NULL; for (int i=0; i < IDELEMS(v); i++) { if (v->m[i]!=NULL) { Poly *beg=NewPoly(pCopy(v->m[i])); InitHistory(beg); InitProl(beg); InitLead(beg); InsertInCount(Q,beg); } } BOOLEAN r= !(ComputeBasis(T,Q)); *TT=T; *QQ=Q; return r; } /// flag: 0: JB, 1: SB BOOLEAN jjStdJanetBasis(leftv res, leftv v, int flag) { ideal result; jList *T; jList *Q; ideal I=(ideal)v->Data(); BOOLEAN is_zero=TRUE; for (int i=0; i < IDELEMS(I); i++) { if ((I->m[i]!=NULL)&& (pIsConstant(I->m[i]))) { goto zero; } else is_zero=FALSE; } if (is_zero) goto zero; if (!jInitBasis(I,&T,&Q)) { int dpO=(strstr(rOrdStr(currRing),"dp")!=NULL); int ideal_length; if (flag==1) ideal_length= dpO ? GB_length() : CountList(T); else ideal_length=CountList(T); result=idInit(ideal_length,1); int ideal_index=0; LCI iT=T->root; while(iT) { pTest(iT->info->root); if ((flag==1) && dpO) { //if (pTotaldegree(iT->info->lead) == pTotaldegree(iT->info->history)) if (p_Deg(iT->info->lead,currRing) == p_Deg(iT->info->history,currRing)) { result->m[ideal_length-ideal_index-1]=pCopy(iT->info->root); if (!nGreaterZero(pGetCoeff(iT->info->root))) result->m[ideal_length-ideal_index-1] =pNeg(result->m[ideal_length-ideal_index-1]); ideal_index++; } } else { result->m[ideal_length-ideal_index-1]=pCopy(iT->info->root); if (!nGreaterZero(pGetCoeff(iT->info->root))) result->m[ideal_length-ideal_index-1] =pNeg(result->m[ideal_length-ideal_index-1]); ideal_index++; } iT=iT->next; } if ((flag==1) && (dpO==0)) { //Print ("interred\n"); result=kInterRedOld(result); idSkipZeroes(result); } res->data = (char *)result; res->rtyp = IDEAL_CMD; DestroyList(Q); DestroyList(T); return FALSE; } else return TRUE; zero: result=idInit(1,1); if (!is_zero) result->m[0]=pOne(); res->data = (char *)result; res->rtyp = IDEAL_CMD; return FALSE; } singular-4.0.3+ds/autogen.sh000077500000000000000000000001171266270727000157550ustar00rootroot00000000000000#! /bin/sh cd `dirname "$0"` # -d --warnings=all autoreconf -v -f -i cd - singular-4.0.3+ds/configure.ac000066400000000000000000000201731266270727000162460ustar00rootroot00000000000000AC_INIT([singular], [4.0.3], [singular@mathematik.uni-kl.de]) AC_DEFINE([VERSION_DATE],["Jan 2016"],[release date]) _AC_SRCDIRS(["$ac_dir"]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_SRCDIR([Singular/tesths.cc]) AC_CONFIG_HEADER([_config.h]) # Add pre'prefixed config AX_PREFIX_CONFIG_H([singularconfig.h],[],[_config.h]) dnl Apparently, this is required for using an AC_CHECK_HEADER within AS_IF(...), at least on Cygwin. AC_USE_SYSTEM_EXTENSIONS AM_MAINTAINER_MODE([enable]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) # -Wno-extra-portability -Werror silent-rules m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) dnl Check if build env is sane AM_SANITY_CHECK SING_RESET_FLAGS() SING_CHECK_SET_ARGS() #! # AC_PROG_CC # AC_PROG_CXX AC_PROG_CPP AC_PROG_CXXCPP AM_PROG_CC_C_O ### AM_PROG_LEX AC_PROG_LN_S AC_PROG_INSTALL m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AC_HEADER_STDC AC_CHECK_HEADERS(unistd.h iostream.h sys/time.h sys/times.h asm/sigcontext.h) AC_CHECK_FUNCS(readlink getcwd getwd setenv putenv qsort_r) AC_CHECK_PROGS([DOXYGEN], [doxygen]) if test -z "$DOXYGEN"; then AC_MSG_WARN([Doxygen not found - continuing without Doxygen support]) fi AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"]) LT_INIT link_all_deplibs=yes link_all_deplibs_CXX=yes # Checks for libraries. # This test for -lpthread etc has to come before AX_PTHREAD, # because libtool tends to ignore -pthread in linking shared C++-libs # see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 # (happens with ubuntu 14.04) AC_SEARCH_LIBS(sem_wait,[rt pthreads pthread],[],[ AC_MSG_ERROR([sem_wait not found in rt,pthreads,pthread]) ]) AX_PTHREAD([], [ AC_MSG_ERROR([Pthread library not found. Please set PTHREAD_CFLAGS and PTHREAD_LIBS correctly for your setup]) ]) AC_MSG_CHECKING([Found Pthread, PTHREAD_CC:]) AC_MSG_RESULT(${PTHREAD_CC:-unset}) AC_MSG_CHECKING([ PTHREAD_CFLAGS:]) AC_MSG_RESULT(${PTHREAD_CFLAGS:-unset}) AC_MSG_CHECKING([ PTHREAD_LIBS:]) AC_MSG_RESULT(${PTHREAD_LIBS:-unset}) # Set the correct PTHREAD flags and, if needed, change the compiler to one that is pthread-enabled. CC="$PTHREAD_CC" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LDFLAGS" AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_LDFLAGS) AC_SUBST(PTHREAD_LIBS) AC_SUBST(CC) AC_CHECK_LIB(rt,clock_gettime) LB_CHECK_GMP(4.0,,AC_MSG_ERROR([Unable to find GMP on your machine: please use --with-gmp=PATH_TO_DIR_CONTAINING_LIB_AND_INCLUDE (see also ./configure --help if you do not understand what we are talking about)])) LB_CHECK_NTL(5.0,,AC_MSG_WARN([Unable to find NTL (which is strongly recommended) on your machine: please use --with-ntl=PATH_TO_DIR_CONTAINING_LIB_AND_INCLUDE (see also ./configure --help if you do not understand what we are talking about)])) LB_CHECK_FLINT(2.3,,AC_MSG_WARN([Unable to find FLINT (which is strongly recommended) on your machine: please use --with-flint=PATH_TO_DIR_CONTAINING_LIB_AND_INCLUDE (see also ./configure --help if you do not understand what we are talking about)])) AC_CONFIG_GOOGLE_PERFTOOLS() AX_PYTHON_DEFAULT() AX_PYTHON_WITH_VERSION([2.4]) LB_CHECK_MATHICGB AC_FUNC_ERROR_AT_LINE AC_FUNC_MALLOC # check for cpu properties AC_CHECK_SIZEOF(long,4) SING_CHECK_CPU #check for host: AC_CANONICAL_HOST case $host_os in *cygwin* ) AX_APPEND_LINK_FLAGS([-Wl,-Bdynamic]);; esac PKG_REQUIRE="$PKG_REQUIRE" AC_SUBST(PKG_REQUIRE) SING_USE_OMALLOC() SING_USE_RESOURCES() SING_USE_FACTORY() SING_CHECK_P_PROCS SING_CHECK_READLINE SING_CHECK_DBM SING_CHECK_GFANLIB SING_CHECK_POLYMAKE SING_CHECK_PLURAL SING_BUILTIN_MODULES AC_ARG_ENABLE(countedref, AS_HELP_STRING([--enable-countedref], [Enable autoloading of reference counted types]), [if test "x$enableval" = "xyes"; then ENABLE_COUNTEDREF_AUTOLOAD=yes fi], ENABLE_COUNTEDREF_AUTOLOAD=no) if test x"${ENABLE_COUNTEDREF_AUTOLOAD}" == xyes; then AC_DEFINE([SI_COUNTEDREF_AUTOLOAD],1,[Enable autoloading of reference counted types]) AC_SUBST(SI_COUNTEDREF_AUTOLOAD) fi dnl AC_CONFIG_FILES conditionalization requires using AM_COND_IF, however dnl AM_COND_IF is new to Automake 1.11. To use it on new Automake without dnl requiring same, a fallback implementation for older Autoconf is provided. dnl Note that disabling of AC_CONFIG_FILES requires Automake 1.11, this code dnl is correct only in terms of m4sh generated script. m4_ifndef([AM_COND_IF], [AC_DEFUN([AM_COND_IF], [ if test -z "$$1_TRUE"; then : m4_n([$2])[]dnl m4_ifval([$3], [else $3 ])dnl fi[]dnl ])]) AC_DEFINE_UNQUOTED([CC],"$CC",[CC]) AC_DEFINE_UNQUOTED([CXX],"$CXX",[CXX]) AC_DEFINE_UNQUOTED([CFLAGS],"$CFLAGS",[CFLAGS]) AC_DEFINE_UNQUOTED([CXXFLAGS],"$CXXFLAGS",[CXXFLAGS]) AC_DEFINE_UNQUOTED([DEFS],"$DEFS",[DEFS]) AC_DEFINE_UNQUOTED([CPPFLAGS],"$CPPFLAGS",[CPPFLAGS]) AC_DEFINE_UNQUOTED([LDFLAGS],"$LDFLAGS",[LDFLAGS]) AC_DEFINE_UNQUOTED([LIBS],"$LIBS",[LIBS]) AC_DEFINE_UNQUOTED([AC_CONFIGURE_ARGS],"$ac_configure_args",[ac_configure_args]) # AC_DEFINE_UNQUOTED([AC_CT_CC], "$ac_ct_CC",[ac_ct_CC]) AC_DEFINE_UNQUOTED([NTL_CFLAGS],"$NTL_CFLAGS",[NTL_CFLAGS]) AC_DEFINE_UNQUOTED([NTL_LIBS],"$NTL_LIBS",[NTL_LIBS]) AC_DEFINE_UNQUOTED([GMP_CFLAGS],"$GMP_CFLAGS",[GMP_CFLAGS]) AC_DEFINE_UNQUOTED([GMP_LIBS],"$GMP_LIBS",[GMP_LIBS]) AC_DEFINE_UNQUOTED([FLINT_CFLAGS],"$FLINT_CFLAGS",[FLINT_CFLAGS]) AC_DEFINE_UNQUOTED([FLINT_LIBS],"$FLINT_LIBS",[FLINT_LIBS]) ##### SEE http://www.gnu.org/prep/standards/html_node/Directory-Variables.html AX_RECURSIVE_EVAL([[$]prefix], [config_prefix]) AX_NORMALIZE_PATH([config_prefix],['/']) AC_DEFINE_UNQUOTED([PREFIX],"$config_prefix",[prefix]) AX_RECURSIVE_EVAL([[$]exec_prefix], [config_exec_prefix]) AX_NORMALIZE_PATH([config_exec_prefix],['/']) AC_DEFINE_UNQUOTED([EXEC_PREFIX],"$config_exec_prefix",[exec_prefix]) AX_RECURSIVE_EVAL([[$]libexecdir], [config_libexecdir]) AX_NORMALIZE_PATH([config_libexecdir],['/']) AC_DEFINE_UNQUOTED([LIBEXEC_DIR],"$config_libexecdir",[libexecdir]) AX_RECURSIVE_EVAL([[$]libdir], [config_libdir]) AX_NORMALIZE_PATH([config_libdir],['/']) AC_DEFINE_UNQUOTED([LIB_DIR],"$config_libdir",[libdir]) AX_RECURSIVE_EVAL([[$]bindir], [config_bindir]) AX_NORMALIZE_PATH([config_bindir],['/']) AC_DEFINE_UNQUOTED([BIN_DIR],"$config_bindir",[bindir]) AX_RECURSIVE_EVAL([[$]datadir], [config_datadir]) AX_NORMALIZE_PATH([config_datadir],['/']) AC_DEFINE_UNQUOTED([DATA_DIR],"$config_datadir",[datadir]) AC_SUBST(DATA_DIR) AX_RECURSIVE_EVAL([[$]docdir], [config_docdir]) AX_NORMALIZE_PATH([config_docdir],['/']) AC_DEFINE_UNQUOTED([DOC_DIR],"$config_docdir",[docdir]) AC_SUBST(DOC_DIR) SING_SHOW_FLAGS([Compiler/linker flags: ]) ## AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([dox/Doxyfile])]) AC_CONFIG_FILES([dox/Makefile]) AC_CONFIG_SUBDIRS([resources]) AC_CONFIG_SUBDIRS([omalloc]) if test "x$ENABLE_FACTORY" = xyes; then AC_CONFIG_SUBDIRS([factory]) fi AC_CONFIG_SUBDIRS([libpolys]) AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([xalloc/Makefile]) AC_CONFIG_FILES([kernel/Makefile]) AC_CONFIG_FILES([kernel/numeric/Makefile]) AC_CONFIG_FILES([kernel/fglm/Makefile]) AC_CONFIG_FILES([kernel/groebner_walk/Makefile]) AC_CONFIG_FILES([kernel/combinatorics/Makefile]) AC_CONFIG_FILES([kernel/spectrum/Makefile]) AC_CONFIG_FILES([kernel/linear_algebra/Makefile]) AC_CONFIG_FILES([kernel/maps/Makefile]) AC_CONFIG_FILES([kernel/GBEngine/Makefile]) AC_CONFIG_FILES([kernel/oswrapper/Makefile]) AC_CONFIG_SUBDIRS([gfanlib]) AC_CONFIG_FILES([Singular/dyn_modules/Makefile]) AC_CONFIG_FILES([Singular/dyn_modules/bigintm/Makefile]) AC_CONFIG_FILES([Singular/dyn_modules/Order/Makefile]) AC_CONFIG_FILES([Singular/dyn_modules/syzextra/Makefile]) AC_CONFIG_FILES([Singular/dyn_modules/gfanlib/Makefile]) AC_CONFIG_FILES([Singular/dyn_modules/polymake/Makefile]) AC_CONFIG_FILES([Singular/dyn_modules/pyobject/Makefile]) AC_CONFIG_FILES([Singular/dyn_modules/singmathic/Makefile]) AC_CONFIG_FILES([Singular/dyn_modules/staticdemo/Makefile]) AC_CONFIG_FILES([Singular/Makefile]) AC_CONFIG_FILES([IntegerProgramming/Makefile]) AC_CONFIG_FILES([libsingular-config Singular.pc]) AC_CONFIG_FILES([emacs/Makefile]) AC_CONFIG_FILES([redhat/Makefile]) AC_CONFIG_FILES([redhat/singular.spec]) AC_CONFIG_FILES([desktop/Makefile desktop/Singular.desktop desktop/Singular-manual.desktop]) AC_OUTPUT singular-4.0.3+ds/desktop/000077500000000000000000000000001266270727000154265ustar00rootroot00000000000000singular-4.0.3+ds/desktop/Makefile.am000066400000000000000000000004261266270727000174640ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../m4 iconsdir = $(datadir)/icons icons_DATA = Singular.png desktopdir = $(datadir)/applications desktop_DATA = Singular.desktop Singular-manual.desktop desktop_in = Singular.desktop.in Singular-manual.desktop.in EXTRA_DIST = $(icons_DATA) $(desktop_in) singular-4.0.3+ds/desktop/Singular-manual.desktop.in000066400000000000000000000007311266270727000224660ustar00rootroot00000000000000[Desktop Entry] Version=@PACKAGE_VERSION@ Name=Singular Manual Name[de]=Singular-Handbuch Comment=read the user manual for Singular @PACKAGE_VERSION@ Comment[de]=im Benutzerhandbuch zu Singular @PACKAGE_VERSION@ lesen Comment[es]= Comment[fr]=lire le manuel d'utilisation de Singular @PACKAGE_VERSION@ Comment[ru]= Type=Link URL=file://@DOC_DIR@/html/index.htm Icon=@DATA_DIR@/icons/Singular.png Categories=Math;Science;Development;Education;Documentation; Encoding=UTF-8 singular-4.0.3+ds/desktop/Singular.desktop.in000066400000000000000000000006141266270727000212130ustar00rootroot00000000000000[Desktop Entry] Version=@PACKAGE_VERSION@ Name=Singular Comment=run Singular @PACKAGE_VERSION@ in a terminal Comment[de]=Singular @PACKAGE_VERSION@ in einem Terminal starten Comment[es]= Comment[fr]=démarrer Singular @PACKAGE_VERSION@ dans un terminal Comment[ru]= Type=Application Exec=Singular Terminal=true Categories=Math;Science;Education; Icon=@DATA_DIR@/icons/Singular.png Encoding=UTF-8 singular-4.0.3+ds/desktop/Singular.png000066400000000000000000000115531266270727000177250ustar00rootroot00000000000000‰PNG  IHDRPdú·bKGDÿÿÿ ½§“ pHYs  šœtIMEÝ Â!æøIDATxÚí]wT×þîl¥K°*‰¨±€=Kxš¢"1h”c4‰æi4±æ%//–Dž_â3&vc‹‰¢QŒ]»‚Š% ±€" ½mŸûþØÝq‡Y˜AyçÈÂ=Ç#3»wÊwõ»¿{—`ÂJŠúÒX Äô¯š¯«*›©ÀQ 9FD„ OëÈÐÚ‘y}ÀÏ×Ý 9qc¸ã¬¢ N] 8(žúÚL}PÛ%ÑÝx§<œ0$"¤V.ÏØ»ê‚1áB°ôFÚ ”¶4¦'dŒÐi$¤ÜnPTúÁ[ÝZVrÓ·ŸdL€b­h|\AÌa‹È-çÓ¦Àê!Ø>a`¥S W3ð0¯¬Ön#·Wõ ôD#g«SÀÛkŽòÚ“û”@½ËGõäÅʄ䖨‘W®­µLÄn káƒ[pºâ@­e ö  Áˆ´¯¤Ñ·óJpöVV­JŸ]èìä€q=ÛœÇò£×Eí›|ûR¬z»@út#–ü~áÿrK;C;4ç΄ÌÞypTŠÞFÖDyÕÀNÚ€,ðÃØ¾pTȹÀÙÒV¿^½í£ôm‹‡‹cñׂQhêé"D»ÐA)Ãø^miÛìç VëDÀ§øï¨^ðsS!ÈÇ çç ôÆz ‘ÅÔí cAÚ¶2ñ: —UÛ}ÆàŽœº€¬iž]èá∯‡uؾu§n¢°L#jûÞëÊë;}ûiÉيܤïÃ>Ïó$ˆR µÞˆñEmŸ\Î Ä×Ý*‰aé®d²¡ÎK ³J‰ùÃ"qßïWîÁh™DªÆömx§ïÔýÂr”ˆÙL»¥øvDAÜ#:,šu8«”ÌSߨ5GëIH)@€ñ½CÒ÷íáT7¶~ÏÆ5õ¡”"«¨I7Ô(Ý«»6œ™5ÔæGŸüzF½ñ¼ ÇÀï¾|¯ÆL5SW¥ÏÏU…ˆ>I›´9 F 1\dÇ–P)å¼þ“·ž¬1ÙPgUøìì¡ „ð²–R¬=uS\Š4zÌÔ”R®ÿš“¨3Ôƒ\˜R |¾)š{¹ ÇàïöA­¡Cˆú´öçÿíá«¢·}HL\Iu òË58xý>ÀQçñ]LOøgnç"õNn=`cŒ,¶XK!@ÏE»À²TTzý9£w+ BÞÝpPÈìÀÐ@OLé&8¿'57Š;Bphê+Vr d”ázVx_ƒã{…âom›ò˜y]’¾„ñ ¿å;JÑÌË¡þ¼¾=í’dw׿×±ÝZ¼§m@~™ºH)æEE ¥7ßqB0qS"ʵzq 2²83só÷!HË)Ffa¹h¾ JÕ±¥•$Ó:¤Â”Â×Í sÌa‡uÆ‘YP†\RôkÛþμk \¶Wœ8¥ßì(¥HË)F~‰š»ç3 Ã0¸òùp^Ìg¡WÜni™ƒÞˆ_&खRн©¸—S,)_žÜ/Œë;mûiSól¨7 nxWø¹9 òݸý—‘‘W"Iúfé/çÇ52„|´å¤xÜgdÌÞxXˆ=gÓꈦ¯t ´í¥çcƯ§Å9;J–â«×»ð$÷›?.áNN‘ñ'X5¦ú—{’'‡: ¹0rÇûm²*á vJ#< ÁÑCýü})âÒG)¢;qÀ)ŶÓ7Ÿ€¡Ð9ƒÞÏ5A[x»ª c€ ­eHÉÌÇ­»LY€B.ž H¸gÚü‘PÚxÉÉ[’PT®¿¥ ôBßÖþœý"„àõåûQZ¡­3";p}Ç®9bÓÞV ËÂE¥Ä[][abïçб™·è{Ÿ»“‹íoãk™¸z÷‘i”k ¦‘ÅŠØy4»E ö]ËÄòý—%‡Ëe .ÌÆËZî–cOê=IÒÒÌá-|9 H¸ši³_•Fw Æö‰kôîá-|ÑÒqÑÝS¢Æ˜µGqâÖChôi4Ë":<ï¿øÔ‰ÿПPP\aSíå¶n~åË7Ñ®‰çäùà ?7L ½‘Åø ‰ØtCÔîtöÇö‰ÙK)šÌܵNÚ@tkå¾Ö™“B6žIãRµ´4Ñï¹î9F¯>\e¸Ä?«Ñáò—#ž<[@€œ!XÿN_dÆÅ¢kK_S鄿¤ãÈôW’GÁ˜5G‘W&ñå5zÄø2/æË.®@ìªÃÒúSŠO4mäÈ/× ·TSe_¹uÇŸ?ŒDû&^Ûcy¡ ‘šU€‡EÐY¸«”hêé‚öžðp®ÌÀFN83k(í¿Œ™¿œâK£Þˆë FÁÑ#²þô-l9uK[bd±í£A\Ühyö蕇jDÕ5$œ{ö“éÙÕª½Üž‡³ÞêÚJÄ_º‹wÖGQa™éAÆDeP )`0Bå®Â´í1ºk+„6ö€o‘†‘0ð¹@ôŠÛ ­plæ4÷r ZJfÆ®8¨”’$§w›@ŒèĻƊã×qòÆ}@)-íg‚ȶM¸þ_ü~±zmÄ•,ÅùϢХ¹à =¾‰Çé¿r¤ÏP WG%öOŒn-}9à¬Õ’R ËÂ}Ê:Lî†EÑ]m«õäÕPK©Q¡îNx´8ræqʧÖà6e- ¬ôj+G… …KÇÂQ!ƒZo€Óøª¬ìòuUeËÀE¥@‡&^|ã `Èòý8–]³™*BPªÑ¡ÇÂx4÷vű鯡…·«@2ò–¼ 'óÄNeŠªé,éN¸ñå(¬¼.K&37Á`dk6ø Δ\¹_ êøpuTòFŽR J)þ¸–ùd R‚{ù¥hùéFLÞz’“Dž„™Õª2x‘Ëp¿ L¢ÓÐáç÷úÃß݉çu?Úš„‚rMÍfÙ(EÿÐ@nPÒr‹EߟKÑ.ÀSàùNý• ½Þ€§tÇ€RŽå‡¯¢ëÂ(Ó¸Á±!D „`Ᾰ–)9nœþZ¼e^8hy‡)w°âÀ•š×CS ³ÅŒSÎ-v ”ò ¸¥JÏ7ëüÔœÁ¹»ÐlÖ&XVPi¡×7ŸKÇœí§%‡šyãßÑÝ`=E:D}·ïÉ–²RŠ@ÇÌON‰FÚœcãYÔþBvµÞXí*Éšªœ»Ù;[÷Pë ûtJÃ× 1 Áý"áÒ'“G®%)Eˆ2Žâœ†ð+“_ ÃÇ{AZy-!Hü3 Rx§ý=œ°þýÀ“˜BS¢æ½\¥\Ê,ཥ/µñ‡\.{jà 3 &"ióbàãê(ÈT¬í.¥KÞèŽNÍ}¤(c0wÛIìMÍàÅ­±ÝZcL¯çž@àʃî0ÈÛMô9‚–ò¼Cºù,}2àX>n*œúl8¶Œï/ˆM‘÷â/΂·«JˆŽJ Y¾¥=Ï›¯~»\ä5[™DŽÝÌâ[z»Š¾?¥:Ü~T"ðĉŸ¾ŽV=jöæïnß9qcÐ=ØÏf -ælÁ²Ã©‚û@Æ×oH¤ÂŒ,‹³7ÃÀ²Ü½2™ßŒS:d—¨¡7šŒh›Æî€Á( ÐoÉ›véÚ?ßÀòQ½ÁdW¬GIJ¶Bg0©jxÎÍ‚nÅ{m•ZçW¦…Ïô xXTŽ©ÛNáZVà¾*… §¾Th%½xA¹Ñ?äI¡»J‰Ï_í"¹âÞ”–³&G ÀÝŒ£²Z"ܾ1,E”AÖ¬J2áèÍ,\}P€‡Å`)…³ƒÍ<]Ð.Àš{óc:ƒAÁÚS71níÑÇû·˜ç-r—Ž…·‹ƒ@Í—JÅ´­I€L™°wÊ` n×LÀ¦dæKgÃçDˆ¯`ÂÆDütâ†ÍèÀ×U•Mxïè ¸7†7*€¨ê¸ªïç—k»öRîØL|]‘µh "t2‘ˤ×z# ¿w•’³©·óJ2k“´ê+JñIdÄ 7íô‘’‘Nó«2æç)J9‚çn1¸¾ª<*O((ż„dxÿ}-R3ª|‰ÜR †,ÿCòQJñû¤H8;(¤Ùb… ÃVàåÝÁ>nøolɶ|ÉÁ+VŽÄÅfœl›P5?pãO7bNü¹'Œ\(÷ÿ›NÀëãõøÇÎó’Fïå{˜øó ˆ„(å2d- ™Ä¼üØõûXzè ÿYúƲ€F¿Æè×&ažhìæ†*tFd”"%3ÇneAWª1—O»¥ˆ‘Ńűpw|4jÕal9—.ib¨GHcœœ1„g§û/݃#׈j—æ>8?g×W5y54•¼¹Ð‰<+R8(d¨øþ]t—äUФ%¼æD¡³%B0ï%ã8i´bý+´È^>¾®¦’Îów ùÞ#ÞÀ=»»·­ÞˆwÖ³d'Ï.-C¢]ìPŸ ì`Š_E2So¸Ïw´O>»µ1„`Câ ¬JúS@>´ h„™ƒ^¨r†G­PŠyfÂÁ2󆆣q#gQ î·”;œÖ±%Ý~j½ÝÓ ô:µNä\z6ÖœüSpþÎAôtUeJ)"—íå‡6ö@ëê8OBüq-“½‘U•jÝZ©$—áÃÍ'yÅÒ’çF‰«2!HË.¹»¹<3ðí›=ªç AÔ²}˜oþxYMwÖ¹µrZA Ê”Røº©Ð#ØOÜ¡0ŒiS +30(¬)Ú4õ ©$$ã— ñOÝ[lÈÄ_º‹ür C92íU($°>I©™¸pïOŠ?z©­xHdcï:¹^˜RŠˆ…;ª¬”ËLS bE¥ÄW{“yqᤗÚ>Ѷ usÁ5!¸ý¨Wîç ìÞš·ûHb®w_¼ TbÓ¿Ñ­Æû ÖéM'ÂÆÛühþ°I¶pøÊC<©Žî$-³± N§Çæ³éõžñ²¶…!8xã>&kæé‚NA~õh÷6†Áä­I•p%ˬ×OˆÒr-ö^Íà©ñ¦wûÕ 4·ÂR æíMHáˆÎA&`ª‘!ˆ±Rcöqƒ‹£²þ†`Ù‘«¶ÆÅQÅ#ºW !(Óêq'¯„ë«1ˆlÛDÜ“Û €„ ¯¨ RÁõÔ~ap«´8ÐVÿgÓy}—èê €æï«„d͵1)$„`L·Ö¢å‹]x쪪O*ln­Û.ÜÄ…ßì ™B|eæg»Î£Lk@n©½¾Ù%yb7¿©D Ðýô>¯`>Ü|+Ž‰ï£ KE?#íw—ìë7•ˆI•÷]ÍØÂ…úb{bªž15*3¶¯}¤ ÁØuGq¡»J‰ ‘/ü‚ØY+,VcëùtAÒ´íD‹%4rø÷+꿟B›x5ü”v1=3òçLÜðcR¥pÂÆDAzàî 7G%P‹k`ì@Bp)3eZ=Oe ÁÊѽ=Û Xcc*íÈK)ELx¼<œ”Æ_º‹‚r $äÎ-%“õ@X¿%ßÖÿ‰éY£¥õ@sz6ñç‚ÀZ!c0à… J‘Bjd±#ùŽà£Fb4W€æ&c0sÇYÞ©R­ÛϤÕÊåëÅï §çÃðb(òJ5XwúV­ý8©7?n^Rf‘ÊÚh¾®Ž9ÿ¯cPj xÙIEND®B`‚singular-4.0.3+ds/doc/000077500000000000000000000000001266270727000145225ustar00rootroot00000000000000singular-4.0.3+ds/doc/doc.tbz2000066400000000000000000155710461266270727000161150ustar00rootroot00000000000000BZh91AY&SY‹¹Ç]"ãÿ„ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿcÕ/·cvä0vÐÂ…Î\Ü®àÐUP ƒéˆ;ìñ¸!pÞs^òò=gmF¸ ·V WZv—FSîÇSÓ®”Û(MaI¾úÓ޺¾×2,£"…T’[hîáдnêç´0z4  .ÅOcª¨Š=ô½{}ëéÙ¡ª=¡¯{Þõ¢¦XÛÊQ6û¸è5–ŒH”L¶Ë -hi›h@÷¹×™ªRªªÝÝR)Ù‘ŒÊ‹@¬Ù±Q€‘ëRŽí±`dUÙjÖ4.Û£*™*LšPÊÖ)QõÜ•Rµ¦Í¶ˆ¯m#@’Ø[š‹l‹-–цÚÐ!{gmlÔ%OAÔw»\¨ÊÙm›6g»©#•l«lÌ$ÔŠÔ¢[&6Á«é  è@(   Ì17`t.ØRîÝ"—}÷m µlÛfH©MVîêúôPkǧ<¢ãè9§UT ¬Ý¸æ°ßn€(}Þìö+c6i ÚVØííïylöÏl÷AÚÅ•hG@Ï{ ­Ð}ƒ@@€Ϫ`6Øv¹à·¼î>]àëÙJõÁÓ`Áëï[À>¼„Ûª%%]AiJ4j`(@¥(áñžó.û‡vÏ·»ù»]©¸/@+S¯cãŸm¾µîjÐú{eBJª(Š€"‹\ó»7¯o“mÎÁŸ_¹ÅÛ¾ûÜlÖÌ­2ú‹½ŸWŸuó|ûÝÉR=}ïN—^®Û»¯ºƒ¾Ü}îÓ=-sÎ÷dí*_}žûÒà}ï¦Öu³¾ûï‘/¶%h ;ÏS—K÷;Ã-µÑÎ@4Û*Ó¾æ»5½«w«yé¥ë­M;{@»µë“»4j 6À&€¹®Ï %ª÷^ûí®bÊ  ú›Ùìew§¼;’ö{‹ T”®,+±ŠoRB©èÓȨ ÛˆÝÞjk»M^†Ìm÷WÐëÛ$ɤTd2]‡G™òù0Yh¬Ûg·½²ŽV6Þ¸;½¯¾ÏY>²¹·ØA]ÀWÓZöùϯx%W¶™9Å6Û–úî vÝ×|ÈÞõ¢û¸:{¾4òÝÛ׆š &€È DôŒ™4ÐSi¡„§êz§êz&S@‚A@d˜DÚJ~Ièi¤Ñ’mmHô'©“@ÐD¦ÒH“B#MO&“dÓBSdSÚ#LÊž§©úHÀ=OD¤z!‰£ÔõR"š54ÓSИS I´i=M4É£M‘ˆi h¤ˆ A FÔL¦iOÈÔžSÚ26 MDA€4C@€4TÿF•<ôÒ¦Óü…§²˜“õA£ÿ÷ôÿÙÀ¯[ýž˜¿µ‚ˆžÀ„B^¡'¹¾.¤¤ý’+Èã8"½R("ƒ~®ÏÿÁÝUP(!‘¨Uóä¼åõ †ÿ\¼9Pí1˜Pô¸ñ/~&ùóD' û”Q<ïˆàWϼ=à]ÃxE6ܶ°Œ4l½Å-5ÿø$A2Ñ¥Tð‹÷÷ïüÙ×Ý~íoÇg»ÿëÆý§þóþo ]Ï!™%4½½—wÜé?éômzƒæ$'þÉŽÏõÃÏåsŸa3î­‚©L=Á¥ F}?ü¦Ê_ø}\Xr%qWîÓ…|¦5Ø=<Š%ÿ7àÊ„¯9b: <ÝJkþ§ñ(ò¡13(éµZñæPžŠø¿ú x¹OQ5Uf6»¨"˜-h†¦}81&^Ž­¸ë¨e·÷Þ3V¤ÿ½ûå¥3ZìCÓL6Ô¥¯Ù24 ðö(Â]n%}¯éúnå=Ì@Ù[x†ø;žÉœN*)‡Ìü»çy‚ÏGý{=˜îº4ë¯ÿ´ëE_[8Ûð‰ Ú|yÔ¯U™œ¸ý;sÔøÎ@±% w¸zß úð9àõáÛ¥Wý;¿Ê+=é°#."Ë'Gêÿã|Ã# =:Þ*¾OÁÿÉg&¦¬yþ;¡\*E“ Àÿ×ѽ‹/賄ñϤ¦Ò§„ïèsÁóîÓoËÕº@}“Ípï]}:^Èää E¹˜£{æ ÿ/’ƒ‡ehñwÜ©8!*êOgå¤~õJi(}íÎl¿‹•Ø€}ø9Ô¢®á‡3€·Î Hq­D! BB§ïŽÒ Ižcƒf˜Ul9ÙMÊbªÊð®?–¦âùÎüaü%qß—žNG=r›5{(ç~îúÓújUÖ&Ì&£†süE†‡ÔfÛCÒ“Ç AÿA.ë™WÉ©U˜ãBòò_hÎBÄ9E ã® ùvM"#8ípµïe@ nÓþ«O. ?Ø­öÿòôíÃÚ4&Áæ˜jôÿõRU­ ¡œ{ÿúYZ;>×î>8\rV¾6kμõ”1œø#—:/Ò(Qvð~|y|\¥2(gq3ê#ú—ÊÞ|¬(_þˆ,,*Ì$¢*E/PÕ±Aî܈ŠK?´ˆþÅøCû þÕ€IÖ¨-!0 8 é"ç(@߇¿É›¡Ûîôý§À´f|…¼ý5 ‡CU :Zñßӌۧ=]¯Sß.íºaq³G®Šý+¶¹ËvP–•ëµÑQ°Õ³ëvOŒÍö­ðWˆ½jëƒo–¬ì lHeiÚôûDÕ(•eðsCh0ªT²N€\/ÇÔ)ª”ª ḻküjÍÿ.jªšá.J°á „lÜØ,ƒa Úbý?EÜÒ´Œ"ˆçjÚku^…íAyu¯áú¼ß ÷oü–Go|}„ôB} ¤Ê˜HGáºZyùXåü4ã3¦ð¥7iä¹ó&£‘uÛí¢+ûÓF¯¥[ü–wxê~ƒËÔ¤·ÊÜȈŸÿ¸ßó¿·@’téÝâî$}Ä~Tûpùà8šÊ)NÊ×gìTG{—:[ǽS§_€î-”gTàœŽWÜgüøcãè'ðQ³dyteÓ†.tê¹ÞXhדzƒ¥mˆ4]&0û')Z;´µ›'TÎvü){Y£ðt0}¶Ã“ÚÑa{ª²Åf7R·fíV«„c¥ÑtÚ»[PUsÅu#£eÛL%L•ƪP’>Ûì0¨Œ–§Ôõ‡p”}7Öí=Mm¶ÛK´¶ÌD!]ÎRËÝä«N¬í‹Þ×¾¾Wá¬Íî[:Ñ, dž¿·:xsÑ¢A4£Â\t¢ýúy.ÑæwÅËÆp‰p× éó "rÕãÎ÷— À€8¹%uçú¿Ýƒ÷«_„Gò¿×yë=|ÇÞà.?ã‚Èʲig®]Ží¬}o²¿7‡ôPE&LJF%Hü•,ñ®³ûh2û5£?%Î\nࢉI§…ÝmÕ#¨}óÃáÁ ½f„öFÐp‡"žÄ>VÙeÿ-àÌ2CvÒj$ åÓl ä´~¸1ü@¤ ªSýÍ‚ì.w2!!'ŸÏ\­ªaGÒj ›ahüœ÷‡v©þX÷]xé9c·øÇÏBú²hÈîR’Ró«D¬W˜—£ú¥~°qO¢E ³î„@ü!ª÷évrÂ5ïÜÌà'=ÇÍoÛý¿ýÿƒ©þÇÿ¶Þ¯ï­÷mÁWðÿ×!Ò8Üë/ ÂNÔ&܃Yßï”òNÿüY9ü.¨Q4Ü‘ïäøCP/Oü}ü\•ÿWб¾] &­ûtœ¡”÷É•ELÕßv°õN]›ú³¯þýNÿþüðuW‘TÖ˜Âz£þqÜÊ5PkQ7Òº“ä¯Çé®ôû·=]$ÅûωP^>nÿÀ|?Þ@ï!þ“Þtˆ"¾üw§qåúC·ÕwÇrªkD(dwôÙ¡õ‘ü¿ÔzNùŠÙÔbFÏBk“Qbs½}…4•Ò¢ßR ñ(&@àÏÜ'=9Þò‡Ë% ‡ugjœ¤$“»k8”é7D¨L"ÓKŠ1º¥T©BKÍDÂr`|RжOÉtw§rK:îúÓ‡ÍKÖêÃóâî(žÛοäÉùû£ Fسlƒ&“?:a9¢muût>n2ãè~·vfqøw³³³ öåÍgW?5ÝŽÏ´¢§,Í%NSr3y™S!õÞœvº·©§ Ê£¶þmµ–tßOìîDëÑÇÜîôd_çA–ßhØâÏV  š™Ðsš1¨âXÆ=`îeoA«™fRk]wó2-öú/܇#§ŽÞzâ c5m”ú›ox1™h@S¸@Åà±*8ªZ‰²p#€âñ˜) ¨d]JõzœÐPl (”,‘Ý tðQ–!db&©£›k!à‡VwÈ:œºÜ± )Ò û¨œà±”ë™Eôuçÿ»ž;sBc®¦1³w5H{ã¯ýÿ>ô}?k°|ý»(ªõ½¿%veíCÙæ¯p›š(=y‘:A¬BÍ®GVÊë¥KŸÆ>k=ŠÅŒP O'ßÔ›fÕ<Š ‰AÕR!ë×®Mó'ËäÖòu9«‡^YŽ´±š0÷§äCÌ9~+6É“¸Ä:|žßÚ{?WÕƒP?öúú= ÂjþOž¡%]¬ K£GÚ–Å õ*(`Í¡”:àõsŠˆ¡.þ¦²’l‡PÑ`KR‘\v…×óäÔýµÁ ‚h‰@ÂŽî×mä'“0Ï¿|ì8^l „Ž%uk•Ý1º(!åIÞªœ:KqÍ"õí¢~Ï^8;+ ãêAÜì.¯¯»el ý¶íT|üöx˜)ƒÛ›n´ îÅË–&.Rª(*0-ˆœ"L° IaµÀÖ76ÃeÂaØ„ì+AÛN%“xr{éz1×¢õ£C|Òr ^~ò<1¸ 3 të¹4YŽš€¨›ñ/jÿ=`1ëDd#¯ëûx3ÇhÊ »£É7UM' °Y^$‘ ùuwÆØVHªÌsQj#L9,jø‘D<öŠ7L¿Ó³ï+É–Õ @êû)ÞÝ;K”$—1Æ$ˆý…e€ŒdbAÆ Ùe>)´MÄ%i bÖ×— ©O¶<ÁrFM K!(¡0…ët®µÇãD†¸2B­‹´ÍC®©sʨÒ5ªê9N\vš?ŒdG^Ùöíg><:LÍ=„L|I}µùW+êm_zAN‰É€¢Êg:$§]”¿ëQhH@º× <ûöà~ß}M>á%O1Ió"L¯hÍ, G=,|f ¤2>Ô+r§/¿.Â1(f„Í“¼z,£¿›Ÿ=l88søç²ìÄßéÅ2<ÑÛ±Ã^¨Š÷à]²8Z«~C¨ËæÕwÞï6Q "²˜Ã”©ÛµRP{ÜÅ ”|àhqàs*¦ÁRÎÑe°…å@Ô+~ùéË •'G£ô_,—£¼dq¢Ó¼Üý£íïãŠj3èqòå*óßñëY¹®ÍuBI’›øêz\ <èi…rÕ¤AÙ³‡¹TiY*²ªƒŸÆŒÁ`Ré3æÿãÉèÕ˜™Ð>Ædðré·†#ÐÏa—c†| ÇIqÒ=vX"‘k &[ÕQŠæC’Îz¹ •¤ 5û+APŽ~Uº®v¸î#ApÿZ™<†ÂŒqkEjHé7+\žpë8³½„Þøy"ªŒÅS6hª,CQDDþ¨t\8…U*@¸ˆ dA^…@ÛN{å<_pÉf/¹øJ3 ií+K‹ÿÒå>K˜îzóºBEÒ:—2›†jºU4(“­QJú/K@­ue©Ü 3”Aß C¤i:HpJ@kÖDpÛ'TíÚ3L„™+ƧQüYAwH;ꆶÐkh6¡‚É’²!Ê­‘qªˆ¬KL c¥Õ<'–h©aRѬA£sܺá9öiï5kÆžçœ%î¬p­@¶û%G{fG;²Qy¨VLâS¯²;úyë~·¤OºàïPãLrëÇPâŒ}‘) lœ½Ç3–/¯XŒºª¦ÚªÄ.p¸6X¸rïc 02a`8‹u6®“výï¿]ç<@}æÍ¶eÙ¾ŽÞý»²"Ø‚ Ì Æ¸vëÊlbŽ sÿœuóiøäçÔGFØÌ7â·AÚù®×¿p’Ö@’Õ¬oé‚â§»¯ŽlŸo4aZw6ˆ©´½˹ÎA°ŒÓ~€£q( ³½ÈÄÊe“Ýî·_£ðü¢²ãŸ^BÉúë¹–?&™dÓªëböe›œ¸a+' Ñ£O›‘CÕ00%“+sÉe C¡Õ|Qîf8”ŀݲ-É\Ø"´ølÖ«(ÚV$Q‚ “MÑW";5’_Íë´§uš=â[Hݼ7g¯f¯÷À7ªÜ¯’G¢vï4‡X*P¯‰WœŽÀj÷¿æŸ užudõ;+qÄוúä¢çbg.qÙZR²;Á«šÌQ9ëTŠ…k«§L8À YU¡P.“„]œì¾â¦Ù éd§ÇtróA+.#˰E/’@¥&rbåÏ'Mæ" ‹0)]_ׯñ i¥ª´üÍÂÑjrAB# ™Ëb¹³ma¯ziF‘Ú$+j§¤9Ƭl#dëªÄ‰2Š]x#¸P&ûýìûe‚[ŸÐSoVC9õþå³õŸ¦×*@k’……l®™®oGåÇFÉVð‘KóËAl ´Æ9·éR&'ùÇâµn2->_‚µLÄñŸèú<¾ó]Xòc¹W]’ òÎIWžúÙ dƒ;Gá]x5,Cµ¹«Aâe¿NŽo§fÿÎð×þØŒD3ô>*º)ƒŸœ&ô÷>ÕÖ¸Býx#ÉáþK‰9P;·t)'Þ|}9Q·cÙš¼>“ÇânÙ†z.Ñ߀=Ÿ6D©¯`š0%j)Áud®Ð‡ÁÙ÷¸"Ù÷)8Y¡É?-#vÉk`5U˜ÓS¯I*—Û :êÄE\àäœÀ.ÍÊ"ç˜î!üÝ*ÚJU¦ ¼=Újä"CþètQBÑÉ]átbH§CɶŸb‰ûŸ†!~?]¾L*:ë°ŸrÉ.WGÒàšM/J#éQH þÓE¾œr|sÂaÛfzÛ‚l|ní™2½ü µCøá7]¢š'ªy¼–Vú“ÉÇ«ÇVho¿"¬#±„*XI£êdTUnâììèê¸2n¢ô¼•-áÁŠ]‡“|Wš½i0À÷§¶CPå ÷öæÜzºYGNŽ4ê|[­Œ‹\©×Õ¿™É³|„¬ÐŠ@†³2ÿ`•Oœ¡)ë_MY,BÒR§`“Mwõûë-œ5*ޏÐA*W)0UY2È.÷ôáóŸK¼íM¡RÂýé ÷€Pôf¶Õš ™R ŽkàÃ]½Ì"|»#s‡ieÛLŸ3mâ^Núö¯,WêܼÏiÕ¢œ°û¹•5k2£ºµz6ì|²T¬ûਃ¸¤ýÎA:9JkÂ_’  J‰ ™øYΘD!¨Èpœ%"‚Ÿ.a–¾^>ÿ-K>‡Žbòåò6“æ)æªüŠ€ð &£íûŠr%CÀÓ©ƒÿ9arÙCAÊr…_ª6%K¹œ•°€rmŽÄ’È‘#úO§ÜùûjÍŸ ®‘M¡$Íœ„¢»×hr.áW49‚¸"$ þc¸¿»úlYfjß±ÜsÛÍEŽõÿÎ"A¯ÊM’šøúûñŸÑ±òÙåÿ‰ûIoé&E³ž3 ‘³mª56 >£¯®@?¸þéÿ4ÿ«ï“ˆÉG˜ìÞýçóH¦"gßëöÔ°0×ó•=é,D lç—+ç(Nø0ð}Ž}ûO˜œkåNtÚ}ƒô^2},Ém ÷¿Í~û¡IÀÿÜøpýÿ™ýõKUUÿ_ëÉxËUMúß6J¨ë+íÃùî7ꇞzT¯Ûö?gžÑÎ9ˆúJ”G§˜ª­ÖFX"+ôDDOn¯#NQ‡öaõ}]Ýú×Òt>ºZ©I!¿”܇‚õ°ÿìJ{AÈ‚HÖ …P@ó‘×øýÈÎß,Új}H¢¦ v ¢#ü9(ûë‚ÈÄ éàw/èX2¯çÁâpBX¾y×; % ÙX®ÔÀ){’.#èªB_|ëµà.ît`“<—Uìß¶{6sX¡ýÙÉ=³øßÌ›e8JôŸGŸê™¡óåbsx_t™R.ÕVmþtVjýKEäÑçÌñÖI#%µr‘’•0Ñd@þ >ϬéùlüýÚñ¼oéƒì—×=~—‹—bnp»©icŽV5+K)?BvÌw]ØŠ Æ«T<_0Ÿ*d‘¾Ë ‡Õ!åS²3»ÇæäONÛ!ü'*ž?Â9=PÃêÐAÏÌ È#èOî“f¶Ë¾ ^éûd×͇)òñŒŒJ´Ñü}›Ã­Fµ%”«²Tn~Löœu:ÓlM§è§¢iü×ÈP:…ª§4qÙî'®Û¼ZfJªÖˆ~ª}ÿ»=zû¼ûB«æ`ѯÐ"½˜õ×n€·Ý é%•À½“Ò†WÄn’Ä2nå¨?ˆËE”íù8^.RàCpÙœäè ¯W¥ 4Ö‘{Üš_ü/±º};>x"‡T"Ô8Ž”Ø$ÄJ+"v0óújv0´FZœ™Lé}< vØýù³C‚8¤ùq“¬›Ò‚µRòˆÁBÍÙ•²rÌEÉÁªªgÓ(ußÙh¯ U™PIG<5ùacˆCs4ËA¡7«óŒ£¥ž|+dMžÙÂ^/x”„Ø_D¾P(>”ÿsÊèÛ@Q×].Ÿ¦«BIRßS>—ÙƒªÍŸÊøb¡ãßÙÖš™ÍTÎ1uF‰9 ]ÝD7âÿi—ûÄ·¦Å޾sË321‡ åOÞZ:„:‰ _ö¨•áA¶êÏ“4Öm‚«"}à}ÿ‰þmrߌàIHо›š†Š‹Ñ8Äÿ^b{°2>ÿ/ç¨'»ÒëÊl¿ÒMUPžÍ¾‘Ujø2 ø*¹UïóùgM¥Ü"Þƒê!¨! í¨$4Џ‰ˆðü”{++HŠ­U©œ Ö?ùÿð¡÷>ÁÜžÇ –ªÓì«Â”M¥þ[g°h?^ýc§èƒ,ƒËx'm_…ŸÛð»š3ÿîÇwûë¯N‹/˜ËÌðÿî WåÙ|ýÕÒ¨:+¡øt)£-e¨3…Q8EzõJñ~šî’&’1­^f+ ‡V÷ì×bÉõ@£Ÿ$ÍÓÃó0›wu— à“±?ËÙ@j¡;Óèaºx•èù»òŒqF¶]ý1€ðíÒ¦cŸ§^öÆd¸õÚ€k¯‘ ßÿ(n•óÊ#k‡oÔžíGþÕØÙ‚˜èó6“CâÊ1©By õ_qG‘mñXá§é­Þ&D"” e¾üßÑãCžÝ=üÛV.m·ñƬ;‡ráDŠ„r¥VY'ž ÖÁ…8Œã=ŸáPÃê¯kzfì¨’Ò T–R(²KasÊÀ]ö;Èý‚Ý-áá„+W2—ŸÊäÍÚ?¢_GÙˆ˜áá…9oP@ÔCõã¶ƒÉÆÚìh?Plç¯J€'zÚFÒ€K¡Fƒ¦íüâûùvHuD ÀeLùtCñë¼³Ï ìñ|Á¯‚°M$‚ž²€ZBrÄ kä™HiëbF˜pÔ£Q ´§§—6xÂ÷"ÉS— Œ‚ ¢f4*"1«†ê†Òþóß>ø‡lþ¥ 4V¸@ø¨òè[‘ñÄðlÙ¹—” ¸žçÊ¢yNÂ,ÇU{><59ÖŽNRwÙØ=)£=˜ù,“S¼9Üö^94c£MUþyWŸ'“ÕÃáêθ?èØ‡D×ó­ÙÙè¹ã©YG((—›€xSRÎff,Ä‚½í¡¨Ûå  =“ÚŸ_Ð{rwì*iêÜõòûŒ £poG>r,ŽÆÞ‚ñ²½»gŠ$&£køýÃïùµ/'ŽÈ¹Ú¨ NO‡£Ã GÛå÷:\*Bušü>5qztX±ÁSzxfvéãšžÎʇ#@LÈÚ@é/MÂ@õìŠlcÈ£iF‚Í ©§6…FXt1 #A]Í /¬Ì€DÃv¬ª©@²}u;X^SíN¡ý/.¼i )¼ƒ1ÂÆ{8ZJ—QuÈpLßÍ-¹C”Ý—V/ªN¸O,¿»:¼sÛ wʧ-cJ{“é{‘çÎø')ê|+iq¹Cœ:}þ«Ÿ.ºYSf›˜[ª/p¼‹â½ À Œñ Ì]ƒ=GNµ³Èg¹™9)ð®káÝíÆƒ¿n·§„ ð©B…¤HÔç°¥­ÚàÌ$B]Áo±f$ia‡1îÇu»hœ^æGÓ¢Ú螥~ª]XRjø1yD¤T`tsy:7rÂâŸGÂïVTÄ K úT&[©T¤›3økó__£N®t¾×èë¢À‡}ó´¹÷o÷¹œµ†ö\YTÉÕ*(4àªqás ¤ˆ/Bªd}¯q…,ÁI;Œ! X÷÷/Ó››—Ù n@6`¨–Jv(R$t”÷ŽáµOiŸZ‡_RÖ`Dl‹eô§Òàüü.I×áG&rõA°ô}iô¿VO=€yŽâAB@–_ ‡•ðè”ûjòäç6s¬ëØ*óØ¨×Ø×ṑü‹ˆRU+¾mÏÅî<ÛÚÓÀ€‹°Ú4¦÷ §Ï3cÕt í`Ù’DÞ«©D nÁCç ñ}“ÐHlfæ>ˬâñ ‡2ìlyëd(+1¸Z é^.<õLž§k``ê/¡@SüÓ¸i xZžÊ_$g©‚W£‡‹"œ{jeç•('R„M]qëpÕÌïr2»4ñòG@\çºÌqÚÈ-ø[M„ø¢@™hB—òÂ5á· ?§ h»·]µ}¢Kiÿ+¹µPñ%\ƒfq?šH¬HÐÜÒwRÉ:iT)CÀÝ]ÙëÝç¨Gý;x0½ÿÕ=LúÁq:NŒ»pCMu -;tÿšðÝÒ1¿nØÈ9׌68í|ŒX~äÓ¸è>^Üï¹¼’y"€’ÈSçÂD9ÎÄД'…´qƒiÞÉzœc& j?Ú´ §è—Å'ðåù«šx´ä•yhóuQ(:óîM»Þh‹ºÔ_çØd‚®„¿(™{a Ðh(6@÷¨ptj¾œwR”‡W›ýºÞÞ0’ÌC F3Õxü¹Ï®uªÓòð«W˜Qï×Ïœ*vVœd;³˜µMý8°Ã†ÕÐD4ãV"ˆŒ5VRJ?ÕƒcU±MS_Hˆ®Ž¡ˆ˜ *+gUQ/Aªj(–Ø5CT“}äiªÇ#¨ˆ ¨™ ’¢Z*òög¯$Ä‘SEͧoõa‘¿û3² ¥)¦š© §¾ÝÅ?ϾƒC¤f¥Ä+ ÛüâCB…!Tþ¨ 4E÷¯ƒM.„õoÇi( ¢‡ßÏ®!÷qħ@š4v NƒZÑ Ù Ñî<•âPù´‡J…{¿MД*I¡OR:G®á[â.ÕZñmº žùhY”Õ+B¯ ç™ðÙîÍj0¯t¯"ÃÂÏø=Øßd,uµ#¹>›GFÙ×[¾Ê,àTݱ~fþç®-ÙL¡‡T^çʰ28Øç¸àBˆ¹Ìàñ ÅpÏÕÌ–ŽôŽ2¹2f±‡m{{ª ºï:ç‰æëXµ5xªÆ²âÔç}‹šø~qYç†ø®w8ß⡽5ߣM~5ZîÌ>Ÿ{¬)ã&F8Pfž“<\Y×­ˆÍæåƒZÚᙣ%T-/<”Ĝ٠ÑhÑ&ܨ&j®ìœ©—š>¥ÍEJ)FŠƒE¢¨ ê7…£èÍLØ‘B ›¼´N—<²ã©±ô¤ŸooRý_JB®Ë¤a)!rª==yôU@æ·ÓÏáeLO)Rs5)Ì\B/>[`a °>'Ó }?º|¤+j¨ É7UÕ´‚§;%}–BÒ Çná—M¯Ø»2».½± ý<ðVŽˆ±Q ÙΡî“@é$¾%{'g^mý)ˆvÊŸLä.R4ÐzOÞG¨¤ªQ×s (œJ%Uª f¯©qÐæ!(?÷¢.˜ ZÞ¼ÝÝÿ<ŽÓ¿»`é>ô3. ~;Pd‡P =X›ìg\T#ÓžVLÏÙ½ë¡ÑÕ·ïlÈNO§ÂC?ªè:]óúÁ÷ø÷Ɔ‘#½ã‰!${–ûA)Ž>¾¯²©”¾õ½è\HÃs›3äé Ê3{,/(hJ¥ZH€ü’v@t—Ï®wÀ:ö1zvá£Ìvš…Œ* {¤Æ¥\ó⨦ªÞ\»îìòZ¹M ¼ ïììr˜®ïÍ^Ô½ß/ÔoÍmfT§u´ò‘?Ø@oêGÆO‹ÏŠëÍqïôo¤ætѨO'„hv•(2Dó]rWŒ<)•éÓ•´#±˜Â7ŽÝt€áÙ€s®8®Ý1é;Q±/H´ J­Ü7o\"…ÒA‘¨1D<º)XúpðÄJr€^‹†Öhƒ…'‹‡gT´*^AÃE\‹.Ÿ,6Ú€áVNº1³Aç‚9|¼**‚…åa8ž)Žì·m8ŽUÿ×'‘^+: œ«°zÆx4®@#0àóŽóªhðÁ’" äbÓ 30©Âìüý5zÛÆXÈ)ú¥PD@éTD:A9¢âùÃî»;±ò} ç!íñú6nü3(ÿFAþ}‡üò1 ð¼<¢{߉!9xŸÐt‰SÐ%“ËšCl^‡—m™ÄÞ4 y¤x€((†CÎ'½ÛŸÇxOAãÏs·öÉæ&0aǽÂi!±“çž±AY,”Â#€T†„`†à¿çÀ@ùgÏ"|1A:ÃùIôY T”Ìž®Ó\m€¦–p±Ž =%è@; B¨˜H‚©b¢£ïØÔ*T‡)# œs(8ÿn_ÎfÍ*QfÞÎ9ÙÚÒÉL ½PÀIÇ—Iž|² €³r###¬¢ÒBÍWðéIEZÎðeÉö¹9³úÁÃíG†Lë@Ã3#í•J@JTJð”EÉB…(V€(@bAã(>¦AhEB…PF€=ä­ *žÀÌ<"©ˆ›ÌŸÁÈò× úÖx[ÊYä„ñöùM¬òÙ͆é0¶„5ŽžSjî’=öúYe”Ɇ`GË~ý všË5+D‹åÄ'xb» ©L5Œ‰^ß?=!ì(;Ë7!ppPÊ„ÀÂûÊ /¶îÊèoRjD“£ˆµà—«^@šé@èÈC`<`@îð8¦“½§Bèg«9øVgÖCœ6ðàC>æN ‡Þ&ê'Jäºû¶69°MŸ£©tCuÁÔ!¼ ÒTÉ¥:@P…#JD 4Rèñ4mD5!@óÛèÐò€AÜ ;§ ãÕ‚š…òB=`†¥CŒª#Ö0þN}NŸÍÛŸg£°ÒHãtiiJZQ¸õ+Ù°P‚àD U8MÞAiSU@! e2F•<ºž¸^ÿ7XéÜò¨¾#š™ß–Ü;÷÷žn>Ñõ¬}£ì¿·—PPý?`H„í hH§«w­ùâ9­Ü!ìóÏ8 É5ÝÐ6"d-¡4; ”Ë%P΀ݮu¯Ù­Á&cT I¶S hM8#ž+”€3 =`%)N!ãþ‚VµŽ$³§¬%ƒäØ? ôdª% jXPì@ yGÕ÷ñOªÈP[ˆ_Ýæîy›­òóŒP ‚ï+@/—[ÕÀq}VWÒƒ^õöÃ{Þ6ì©„ö_Q x @ n§‹µ@-…]¢«E™N0¸uFˆÈDØX¾ ž¸X¼Îu³r ™fô–ÏÝÈæÓ±Š ­ÜÞxþÝ 2¨øR5ÿòPaO[ôTPŠ žãš/£ï³ãoŸþYä=ýéó÷âíCÐA1DÒMLI13AM1 AQâÅR„ÁýŒ—Ÿvoû¶ $ ’ÚÓçõBCÏ‚iðkB‰Á½!!«Õƒ1÷Õg™a(Ô„1¼>< yÁÜ£=•â^Á÷ƒø¿ˆ4üz9ú`t‡|ßp—öoWï_‡Ý({½Íø7çúÝýÙ¦Œ»ú€ãëÄ€!ïd«Àªòt½à²( ¨$PD“òÇO¨üVj%Àœ'Á «ëZ&ŒºT2ZDŽfi8ÁÏá山仔P„Q 7Ž_o='l™ \üCÕù8°ÏÌcº2~}tüØ!lÙ®#D’KáÞ›ˆ¢ññ7]öhó~"NvõÄl‘;¿o˜¸ŠÆd¾›>hŒ ‘w OTxlý±TIÿ‘ÚíúýâñÕÛ†I¿Êtn̰ÁB ›žîį«>ä¥ã/ ª0ÝKûtШ ŸuL„þÕaÎ2áv¿ š»û·åçÈîæ°hë­ÔöP0@1Èh`žîÌ]ëñãÊ%í¦ÏôùðÂÿ£n¡í««îóÞÙx‘~_ñЂŠåÒ;Hº¡ ÂHˆ9D@9ØSGyÖ<áý@Éý äÁPø¡ÑäÁ<“õäÄDþÈ#Ãçòoå&B·ˆQËš;Q#º~Ú‡´¨¶a>+»C¶ ëp;lÐQGÃtïD¼D$—:èK9Un=%8{Öð `vš2N.^`ü1âéû»67†^ðÎåO¸xÅG¼oqf_eW~šD“W&– ÒD¹¼¬v¨'0ª:¼ÀV›kâÝ7®NÔ[‰Aâˆ×0X9GAŽÑ´I"ûS^ogˆ­jlqêdtâ æõav”ªéBìU&&€$Lé< DßQ¦ƒ“¼T¬H‚çzm‹C¸0ßS›÷w°•È;¹mxß¿bWL´þ>]ãÉ‚p´iV?d‚ÚÎ ð’LOI : J@S=Ã*ubO•pµèÌä­ ˆÜù×Ó쯋–ݯmnÃó%7Øg£çŠ#÷!mÃö÷pÃp¥ƒ¾¶XÀ1*º¢ÿ€›^ªsQ4k£hÔ+¤)Ésáµ [UùÆNæ"¤glqÝú°¬Éþî}h£²19àqãF9©”¿³KZ%=t¤Ðç©ÌEO Pü'¤9òÒyqs}ºtx{^þ=Éì [ÌêIOÕw†Á²Ã b§Õæ…/bw{“’ŠN$DCu–›'8vÄRSXÎdç/¬cÍÆìÎTì–atï¹¢œ‚ܹ= [ŠQއ ô õ““ðžÿª/o¯=ÇðR뚣ÅIh Jò¨ f`­¡ê>Ykà5¼hû¯A –žÚûFnÃ{&*aü5,Í{›–8vWøéO9‚PÄ+«ç‰neåD“Ó›ç'>ÙÂbn¸át]>µ]~ïOáIb(*PJuX£àô&„kÙ—|û”sÝóÏmÑ»É+bR÷‡Bƒs@õN›˜)B~$:@š§\Óý)¥ Ks:ER¦Õì磼]º ‚/ÀbSi …§ÍÜŠ%¬Ž™l°n‚gìP{ºªFÁËVU³Liis*X;uTáì ‘À ÅÿÚ–.7oƒ:,FàAK`y\µIñhÎÖ§%d*Œÿìî$¹(Ãj¢Ðð½8ùÿ:b#†®4ƒ„{`û€ó° m qùl“òë ²Ìö ÇÚ; ÁÇ¡Z¹ÂÙv0XÑ^ÈŠ\¼ð|S½ü/¯´õg¬ñÝñAÑþŽ‹«³æzŒÌ×øv»Þ__@<•lpE7Ü“pµì}tÁº­Ñ*‚E!G  }z%}ÅXI˜½ÅÊ PaÔ¯ŽøþïÕðÒŸ#ŠHàx\*QŠù ôÁ{Ì>Á}à¤à]™;!™¶ÅÔO÷ê¿Ó¾ÍòD~øü{s‘r€IƒíLÔŽÅì uhçj[ZÜ®ÔÚ§‘hœ#Ê/«M«U‘!í¸ ©óh¾Ÿ±¶=ƒ‡Âûu0ƒÞqjÃÚ„ 7¼Ž£5…@ü×ÓŸ>ŒÒ•@£§ªÞçh_NŒr¾ºæ*Ñg—‰aCFªHQ@&§’3!Õ-.Mâù©]C ¶sëÒj੘Áª$b]¤f-(ÍçoGš>zg[=þ¹# YŒ=ß®ó¡TkªÊ“Ñۭͱê÷«GK¦ÉùA9²%™6ÏòB þH;özãÚn~¦ûeOËñbè#'~’”}§õHa:t>Á¹>G7Džk¥úýœ¯³f Cðˆi%óWJΫ~xz¼8nÁîâÕÓçï«?›Õ¢¿êå6ý‰ÔAþZefztè{´¶:tÕ§N5ø'ÌhúˆˆƒnÛÔäÌxEÅ_-P•TŽÔ~O¶€Â"‰Öºly~7÷L5ú´®Uއ,yér~x'çDf”w¥õÕBlåÑ Ž ‹—šiDÑÊö )Ä5’ýüö˜ëÈ )¢–!?Ô!Ó}r:ª(¶Ç¹t O•!¾žùC¡üeÝ`_$>`4s(ÒD{³¤>ÿ=ÀHþ2<öM-´Ñát£Ùž=Ÿ¡ÑާQú0~ãßø ZÞY®Èof0q9ø}îýÜáòÕ° uޤBDSVQ^páÑù'˶Cu‚ÄÖ|º*öõ‹±æ:÷ŠÉy\¾Ÿ. yM8…å–Z¸X8]ãÿðqò=ãom}ߎ퀦¿™z vÏ-¼ß„<Ä·4ºÆÏ ½X}}}Jï šd:*GlýþoÅ8„™\ÿP¯Î¸gLñ/9àI!õŒþãÒd5˜û!=_•Üþs§Ú_ob‚§óœ\Œ,â66ªH„(]ú0}£ùn%¯ƒmpGPDJÑAîM°ìuÅÅZ1;Sš„Ú™ŠM££µ (00Å€î;¬J±¶tLj"¢J3M†!)¦†ˆ%i“¢´í¶8šÛ5€ÆY™] ?ãäO5KhøOd”/äýç¿îϸ ïÕ!ÙÏ Ày¬pÀƒï0ÿxp=)ñpj@ Ð|=\øöÙÛG;Ñ–o ÛX£‘äBü—d’úíKÅŸ9çxå!!‚W†µÍüÐá©9ЉJîjÇÐv’’àÂ@6V{ ôÛ6Q/à:¢J1|Y8ı³‰6SA,A@PÕ’ É Onä!Êøpo? —þc¬ñú^ÆËp&`ÎÝlÛkbwâã$HCõ‡¤ÕT *T•"ÿm ¹ sKãšå¦†œ+Íeõï±ÏÕ)ômÙÇxóSß!ñɼ!蓌É ¿õ`$>5€Ûçǘ}Ã¸èæž”ŒêaŠøq¶ež äíâj£'0Ð*ÏÁB0D2æPŽ)Gkx…ÝZaÐEÈ*E$O«r¼qWç¸ ‘›àä˜ÿ\/} (Ý?Ü¢Bvsº¨¿[±ŠJ42å'RR”,²¨-Šá”÷çYuÓóíõýº³ŽoU GlB['€LèÁ°Ê¼õ¹ÏÂå?.½ì TMB ó£÷MÜ—ø/§?zA¿.çÃÛÇÔý5¬™TÜý91ÇñËòmì¿¥á±IÌÔ©}ô0@·.ÉÚÛ5sȾªœ b>BÊB?@œ^“ÊNp Œ¯ƒ¦ˆrBŒ“èTä(ÃJÈNÛXmz‘±@`õG T[¿’7½fzîßõ>Ez÷Ã:ÌéxÇgӃćé‡dv1(“÷T•É!±å‡ÿŽÿQ×ôêY >]üó^·×˳§MaµwZ ÝÈ,KHòcFs¤T)¹½Ÿ%%u?9Ëp2ÂQ(£¾ºvr0’!@ÎÈÊ H” ®">DÎê…I«žVâxK$% ñ h`¥ìU¯]åïJ:ç*+#Ž?öbÌÕ’@ FjAV9p¸Z’±Š.¼TË+C¬­Ë›m¶Yx½ ŽÈîµÎ‘wK…z„Eó2ì(<ÉwE€C©Á„Æñ¢¤4O%âÕÇGë Ì€{~Ín¬Lß´/³ÒFI#ëJÿ )»ó÷â¨Ö>?1°š­="°½Ÿ«Ú\'7€ãíð\¥æœz–=EãE¤pk—d!½¥ÄÚPFd"€À¨ŽÐb–aV:éhÉ\–B™êXÓö¸GÎHŽˆhv=ü3þ‚KöLâ½Câ^EUÓ³ÓxG°šûVTzsž)0ã[0ß±øŒ¯† meÃM0w#SE ì˜ŽÃnDbØÊß)™¹¢Y.Wyù6ÑÓ±ü}´};5 Æ€v‡†r¤y/â€Ø‰|ߺ -•SŸSmöD@¢½¼àC ­\8Äê éøAøæs1Ç­Ä\N§X ¤$vÆþc¡œˆ w_GÄEDPîe!^z–|IJˆ©JS¶c¬¬ÞuQüÇaõü³µ<žSØåE SÄý_¿ü0húaÝó3íñ4ÁG£êÛ•§»—//£ãûuy–áðòÎñØ6žv[tp–{Ò˼èærýèÀ%ôaÂwy³Çã}áïT¦>¬uÖÌ–íÞÌgèßývrZ*¯„g€@RY #W\b¤øiЛÄ7Çâ±È!ꉄ†2ºÍWÔŸ´T9ÎÐëuhw ËÛ(´'Çb¨â;‡ 3Ý"Þ]•¹+º÷¸´zӶ΄º4Ö)=ëîa_DÔ ­Q"T÷"/oШ€l#õ à€l“¦\Bà <áÀRé€0•ãÓÙ܇½õ\3…ÙrÖ…ðÂg ]È ç- mŽa$GŒÃ‰ÛËÛåæˆÍ<à6‹›ÍŸ4¹îKaVžBáãáN…£A«“õóáÁ*(ßË›ën¦‡$¾‡ÑwPTFCËÄ$Ù.Îøf®!=x/…JôNÓ Â-®sö¥nP¾ïfë+Jûeäm)bT”;¬݈À…ïYS7y¼ªÞg kHõÌwPörª^Þšrù§æÕë[¯ÓˆÕuo°ï-óúé‚ËC£õú­³ u†Åއ\éÓ¦ü|‡ùY?yýj(=…žö&usdòÿ&sr(±Ë,§®@k*¹é#ø»š¨€1¢š&)ó@6úþïKŸÇ¾8<ŽS[»¤–Èg¥×TT;ÂJó²Ñ'JÈ0iYR:T4¬må­Å+ZW]y ‘”ç d<È?ªë8$;,û¹8ååéwú `-øáZoQ²  T=¹¶ªæšœFš¢'Ä*©QM¿é‚éÞBX´¥u®¢’Õfç”÷ÿ›¨GUJˆØ±¡³ç³Þûóƒ½pL°Nð7°šˆ5U}íH ÜØ/c.$UÒE1-‘²·N1e£|ÒÁPU¡+!HjÕZ§¹ÊÂÆeÝRÉ Z ù;úÃ?vìCArÀ%.;9ž¤4Cqý ÌÂJ“'2éÒ˱ƒÄöZ|“ÎV=JqòA¯í0x8dR‚Rr¹ì69^RÖœi²àÐÂ)Ó gTåkµþTM¸°ò©Èˆ;^úÛù=,Óo×s_%””(+-Àjp`ù rE­æá²rH@¥a–×½‚¾×ÅÜ#t¦°®îÉ,Lâ€é« O£Kܪ 6 և̠„f¢½Ù':d6 âC›4É5ÓCÇ1WŒökuÏDõJ’ô>ÚúDÁOªj˜Ò\É+4Feyñ×óH8=Á  •ù„xÜì@p«t<5¥[ª¶qãˆn ¤ƒqO™¬ 5Ž…()X“0åz=œˆQ äf´ctDh’I8P´·\Ùö„7â8\3gfýâV€òÑ&_[“©âçÁ[9$Xssª&À/çÑ©öÊóA€8¢[Jn(Ñ ¯uáà@W€ ÁÏëã¶ÇPèÝðø€ìòr=>I•š'Ê þ:tgŠv!k·ÉÏ~²ÊÉêC±•'÷!eöžŽ>Be‹´ªx8-zÆŸ73vE#1§:éxQ¸8Gð@‰±¤ n«ìi´%Wذ«èø¸rOm‚Á×ôhìÛÕ·`TFv‡ Qteð‚;À¥øËLCœµ€Fvê" ±›{hUE©ðŒ^žX>¿ Ë{™âOWh* Ø™†ò?:T)¨Ã{´ÎúMoÝÖOŽ º¯]ÙU·NAT¯Í[ÜȬcz€¯våÀÆxÐ9qÅ0…R^ ÝXCµÁÀšm‡çw1T)ï Š@Ÿ1AÎè=·)³|•ö|'0 ™VæºMåùMHv½žs‰õÿ^Ìœ ÊÜ,¦>ƒŒ$Í?X¾r¼ü;ßòyMüÔWßExxm6X¬YšËcˆUƒëª²ª“Ut"ÄNî™æó‡uóÐÓ8Ý>ÜÂ4Ò‰'Ú†Yò¡‹ÖåÙVsbyŽFM#hˆÛسQ˜‰¹t (‘ÙFËÔìAÝ"ðÛ®’E³”UÄJX™'˜ ­m¨K†Ï þTkÜ îŒýûl‡cøÄðð:YD=H]ù{ŽoN­‚$m®A*)87ëË–I+a¾+ðQJ6Äô Q7(\í¥É}ŒÈÅ·ñ nšX ¬±ý§âxOÍÚw=/®}ðsŸ}¹S¤…Ec'ÔýIP~+Ì8ˆZëzëîþ^Î-×Á‡w•åæ-üæÒ"@\ëÀ *°çDD‚º´ofcgh¯Ž%$‘JߥÈtêzcbŒ°Q0Ql…8ë0ÂèÚ Ÿ.L7ª,€áÆi¯‹ÔVu¹6·>ý5@ édœ˜g”ªÞ¦åã~üiðUí×\Ü~)TXTVƒùqJÚ1Pi½ÅWr¤h_0F¤„áìõÌB`êïz'3Ÿ›¦@N”BV¾DçðÔòYçèè÷ª€úÂÊDAHÑR„Ñ¡‰4dfNfUM?øcj;¾—Åï{ÅuŸ'àëœ9ñ9(Ü¢šF]ͨ¢ªŒµZICέÛi~_¬8‡Û¤Òøøºk¤Ÿc.%§ߟÁÂwÛHs»°RPà“2Ÿ¯KÇÃÔ [Ìr«‚mÍÂችdÔò’NÝ´¤S­kÀ=:w}O¬Wt\=†¼Fü%Ͼ(¬"“zòÀD¢G4/3˜è©úEQäK,*BÄÓiäH‹«0ååO†|\/Ð ²t°mT^×ß© P—©nkæª /J¼qÜñÄèôL?Uö'~ùÉÏ…cw&È wýI“ A~íGê¼91h[6QÛæa!'Û®RJ0ìŠm­Éà?˜ç`ÈP…Ni¢]]ì%š€à#?OÒï2å%mà¥l(ð9•Î ä®)Yzñá—«DÎ*‹¹ýdÕýE©zÖfä“€åÎzC`MgEqúÏËY¡ò:F#ò]‹LÃYœª öh/ïòŒŸ q8X^~¦fJôg•ÁáC7Ji´^‘øê­!½ñ›‘FˆíámË ;J]2Cë §;Ö4¥ä# uZhƒuw—Ó„¬SRÆúoöa±÷ÆýìòY—L‘ø—Ùzû{…¿˜$‚`T¶ê¹a ¢Ú¼´â9yNíÎfŠP Yh°9Àfø€–Cf´Èg“#ÇŠóÅã­\$©¤"|,³$$ i×8Þaû“M*KKÎo¢uméùƒŸŽG^\á4C³¤œéÎ ƒÛÌü{ë r|‘Kt`‘t“†ÕÀÝx¸¸31ÉT‰g5¹2`©ºäiOoÄ Rò{:Tu…€MIÚRÏEHÈÞ†`ÐæµW££æQòýWV)E ÌžNòV÷M¢÷ö}+¯XûÀývÙ µ@z0K채ïÁà‡Ðv‘_/™éX®²ð'·-ÁãPÀ K;ÃÔ5U[Q:­J¸~Ÿ@}|ž3IÔ¡CÜÁŠÿ"£Œ4¹ÈÈÌ™8`—µ± ˜ïm©®ëȹ5”m C\âCks)Äù›7ãÃô~ÏßEÉ,þXIº:4YçÐÑYÓxçMd’½ý¯Õºý½G=¾|9À±ÉYߺ¤‡[f mox(¢÷.p2š¾'bÍâ³ñ@¿¼þÃWO•øk®Ø-pЇÎ>WŒw¸`ܯ •õq®IÛ_,ÄáÎÈÌó çܺ)dAl‰ok‘Γrá˜+®ÂUI*d·gmC £êÚ¹‡B£,ªœÔCõj„” ”DŽ"œ°VÎ wCWleòÚËh^¢–ÙF›,ALÀ#0oÄÊF2µ«§â¥uƵ£2Ùï\sƒñçïGdg>tª7§>üŸwiyñõæpo~Úz­zɆ>gÆ“%Ùß·Xò#„Ã`#²lãÉ¥U·ÑɃôÇm¾kbyä!Ö‘XOçÓttl}ã =.Ûgƒšå®5ߊÐ\¶‰%bûÖIcÊ,˜¸-/“ÔÅäÔCF1ƒÞkUF„h_öÃWš¾p«ŸpÞ2øúYáÙÄ€¸nù;†Cì 8Èg?ÌÆG5Æ]™&F\rÌÎÿ§Çìý?áÖ{sÕ‡Z!Ù/Œ ‡VJ¤¨)”ó wöwXx5÷q¦{vó¾Nm>÷v\­ZàºX ̉ªdeîá&iŠ(€óð¬Dª2ÓIÀ˜ëìl™óÿ[§aóï^Ææ ÝáüE‡åáÃûP$pÎa^‡4ˆ±©Î¹•ƒ|T•OÉ“e`¢“g)†[JI¢e 8R’iµL ñbÓ<Q«R:pÛ€¯„‡Ë\­`ë@qº0;T?ý'QíЙI¢<(Ù-˜EŸ —”™Q´èÒl‚CßP(þc­oCúnc5`pRaòy(⨰0€ºy¨þæm¥½‘Ì+ƒÔ±µ¾¥B“A5S³Q“Ip[·¼Q”ÚÅ“pN!Í ‹€ä@€SÉ:Ý ¦ÙÅIw£1Nº‡X¬ƒ5R(œ=Ûpf¢ÄéѸ€‚„#TГhútÙöíq…îpÿcúGl~…}/Z?W€v¬¹ÒçFÌ£çT&»°Ê©5bëUWCe#Á«{=×p¤çÔâþ]àfåLÂsуba™ÐÔRNÎÌèoÍBKÏT=æqÇ;võžß%„é‡NK©kýk¼ªÅbOø¬'sÌð²Ä¤ã)ˆl¸UE3vœb)³°Ï;¡Ý±Gs %Ä”’…¼’¸°uWÈÀR \3¸Or8 ÑÌ[š‹†&º\ÃK³ž=òv“Úc%ÜÉe켕±å´¯)Ö–ÏF)3p×G‘ð#ã<<‰W¶qÙzèÆ&ؾÁÙ„&A1â8«†BM) @HFpSz#®Z ØŠM  Ç]™L¸LéI‹?¡ÚÓ áë“ýj¸å†óêÅ ‹8S®¤¦ìÿ,ƒŸ™“ï-í]_Æ8þ2bþûß³ïžÏ¬Axês‘°ÑÄ1)¸š‹Ú’;¿Ÿ¼âüQœüŸ¶nì[cE;©œ=rc··P¯¥çÁÒ¨5F.¡cAð9›PÒ·Ga±.¬* Ê4û´¹5„T]c¯^<ßqS9\*šŸ]çÆ ¨qq¾w®>­‹4y~>˜³Åj¹£œáƒmpvIºªÞ˜é©šãPªb…wË彈Á¦in,çûìoǦãVq¬‡ÇÐGˆ=ëyˆ2w:ÇŸYkŽ÷ði¯íqç>‘::v©í6ôI9+Ú¹úá,®Õ¸|îñìq»®ñ^ öÎg|ós;Do•þû¼Ýrç4ò¯d%)÷Û3ÇZ“×–Dú¹Ê=õÎ6cìãQÓÚÚž÷ÁÝpî”SùF6´C5LùàÙø0ü÷Ö>ÏühÝb§‡RO¦¶D×øa;…Ý¥¶;ý—˜‹5ªwõvѽÑ/Yˆ ˜ƒÝèû畾—¶§¹ª&_ã¿o‹è~«›‚ï\ù¹Ôõu±g~Ü3â`%S­è|¢Õ`ÿû箂µ½[Øç+œfìØ;u;o“Ó1IÀ”è|ï‡ø:ŠnwòíÑS0çp.š=8Nú»>ŒkRÉ3==xSƳÅÜšD(|1á»ûLÔÈ j;Ý×Y…ˆÓšéÌ¢~çj×lÌNȈF³Ù»¬ñƒ K;s‹é9{ßls§WmuÉ,d¦:4A@äÑÏs©hN9iãÂ-sd… ¥¶dm¾½ÌÅJ=áŸÔæ ¼YU¥¨`}ÁPZiÏùTúZ¹8Ž<¿†A꫇qå¢;ïÁÀ¡çyï›­Ó’@äå$åLL³BŠ‘Ä$˜‹ê´K&p˜Ö5e—XëU'´‚r«ÌA2?Jl,—d3i$ĦöQðúÌ–%Ó·*‡Mâ(Že[LC—Æ"…0©S±èã ,5¾°ã‰ŒQBQ˜;KÉÌEªS-Ç•šfçb¡Î”K¾Eq„slâd~+¼.Eˆq@89ÝIØŽ£uÅMv«Î3ËÐLú?v…3ÇêÇn×ÂVoŒSFÝ uðÄòúÏsvMfZùÇÝ/“®Í¶Ù¥N5LK©/~&u‘Åž"óX1›”¿«DËË6ðvI#rTé­HÚº&n q….‘ l“©tÃéÎ×- ö]ÄöN³ÁפÏls‰7‹£s™¤•fHò˜…ç1ÓéJtó i}¨Çwzgc®¶qá麪&¨®9Q¹Ne6×Ir%äw…Ëeq¼‘aÇã“…¾ñ'9Ãt›€BŒ'L$åÞ‚J+9é³iŠdnü`½L2‹aÄ,0G?-­Žmáùé÷ÞñÞ“Ä^]¹GdÚV„!CŽëŽ*ŠÇO¤µ1K¬4›Ä`æŽ=ñÆsP¼#°o=$MxÚ”5#J£iЙÐë2B5â8šÎ“Û57ñl‚ˆ2r¼a""Üqa¸+¦ûik’¨Í¨rWXEA‡pó“<(瀜dâ3ÊXi[ƒ”MæËÖÀ5ª† ‹‘U‹4 yù·¤ü£¼ë>Ûx(~¡ÑÀ¨î8âÛZý+ã/h¾¤:)I·îùü»:ü;=CÛq‘µ\g/ˆàÌp®ÌÏ]s/< B†ŠÖ*!óðð_I“´gq>\¤¹¹}çŽ80Á§ N(ã7à g¥´ÇÓéäa€šæî> *!¼J]jšÕ¶Ô‰QWưê÷¹ÐI užjÐÂ*踫ä®hh¨Š|·tâ Öd¬HÜYæ•nªñ?¼ø£ɃQÈ¬ìŠÆ}Û<ßË·>šÚçšxl´¸Û½Q4Bq4}×@¥5 hŽ‘¹9²w¤íƒ8\€ôϰFèe)»‹dá`óô9Ä8Mjá{á~jƒ²á¨~›"l©­šTP¡TT4ó|JÍ%“{„§Ÿ‹i³v©p³~©Ûs-Rº¸ | 3c/\~·àÁ[3õû+ÏÔëá\†ÖôyÓ·=›_*£f#œ=I_¢aÓ©$Æ÷X&W[OƒcöY¦¾F« 3­Ú€Y1ô(ÒW ‘ªÑ•ÑüÑ¥YÙ1ÙúÓ@3mN`ï#!B ¦¹ü›½¨í“á'v2Ú®8qµê¨•E&ÚU"õi†£nëåé}u¨¦Ä×$@ù< ½‘ ÇD¹ÎDH?Õêûe éG8^ h(:…–ç…\‘®aQ/›Žbʾ;èöA&V锿?½ã’z[vsIebÂU a&‚ø[Z¢b£`žP0!ë}âëš¡Âð+²—óÝé»7­m€a7¯UÞ¦†YÎS CŸ€µÀEé µª(‹jxþnsFr%Û[[ƒCÉ}ßK‚P ÄUÊ ¨Y Äj}{c¢ §ÏPœŠ”ØžiIÐPÛXp”ý¦ñ_­uc!Dîu}ßB×§H:¾~m ;ÇDXv”¾H#ÑïýÎG8ëd^ŸIà6ê½|@ÀuêÁÛ´MNš;£¡èŸêÝEGsD”}±Â>ÜLÞ±Fw~ëKë4Üã˜,!ù¢Q+ônÛYãk·W\,¬víú`Ù€qi®KSžD•f«lí.«‰…ÛÄã¼FKÒ'uM5$Ì}9°uâ ¢ïaµÂ·+Œžö:Bˆ¹fP( -ü=œ_嚺£ÂŠ«ãád ¼â–›ý‹BdÌ3Þ>Îê ¦R“a9ý¾î\òsvº—sª%(2ÉRé<õ#‡÷=§(¥Dfª`Ù9\£ixr¸XóvÆä¶ 4ÁQÃW©•ÃçÔp-óö^îH÷žîЊ/­¬£—ÿèZˆÒDˆŽ¡çaÀ?8a±‡”Ã'³+ e>áè9ôÑ»®h<¶/Vÿ|µý0é•(¯mV< ±TB[frvöªDàZÅ”¤œþ¿'\&xRš5µJð¢¹5ä÷6X³Y@Õ4кÇ,ÁZm¦f`‘«‰®&ù” v:¨RßÞ¦›3Ó—Ó4½¹ÔË U Y @e’»H9 ¬zŽŠŸøD_KêXäÊÄ!ÁÁ×ÍðGyh.JÍö½î@—™t ˆes[1nœÖzy#Øiu¤U×`²®N!ú•-o{Ø×F–¿8?¿uË÷zÿ¥–òåϯY¹:2á-ö?­°çEÍó °þú_*Ѧã M©ÓD&’žÒ×Î:rXøA§‡ JÇq+úõ=K™‚oÝHê}#Ч:bê*ØE]v8X¢Â!­Oü«ºº *”†J*ÛöÀs#´‘=›´¿If$ømÑ¥-€ÃÔ–D´ÌzâÂ"/oŘ×X{MÖ™Íc-6ˆEùûÖ}Íxã/¯xÏUÕ žÛ–š“dM3|ÂXHãÙÞ{Æ8Ì&f6’àáœ&«çDµÓŽz èÕ¬÷;Ÿ¿Zíú=·8ßǼ ¢¹…7^Q²­\è¥aâÖŸÓA1Ù(‰-k|’~Š„^À¸Xß%VÎjCæGƒ7ÇŒôP‡ñvÊ€ðŠ›%ÑÅ;…àH À…*(£cqy¿Ä>Ò9EðvÖ£‚ºŒ*e,Љ?9ŽyVN ~IyÌT|mîî‡wn/âÝ~û:r>òkhÇ~Gs‡I ÷„ûG ªP¼ŸX[CŽ6 Ä~þHçâ¢w *çʹ¬_ Z ¤¤5ëäëjZ%ÈEÓ ¥J”Ub,pAKn‚¤žÍ¯ÃI>–CË\m&ÖBV§œ9>‚_éb +ÉÜÅðO‡t¶íαÀ¡ ßoò²*ß<{/Ý™¿žS…)è9îèØ%’Š‚&¢š&!Š»}Yâˆ)÷ƒzLóŒØÉ!)žXˆßTNÚEƒÛo6¢#!óÏÅÞŠÔÄLMU&hD,¾äÝüãäR&©Ô¢ªªeàSÕÎpè†Ë&…6i§UñÖð83™avÿ(ø!úæßÔi‚õ¢â¯¥¶Ø;ÒSÂéǼg’A› DÙ‰ÁÄÝE ·š†ÀœØBî%ÂI6‚N¥QdÀ³o$æÐ°-úŽ×®º×wƒŽQLs!ü¦¡\D©Ô4FIt TS¼"©îœÀˆ†Û²]ân3sa-Ó)’gµ×…95yʧqäk¨vóɬiN\a¯U—\æ§â‡{ÑSƒˆHMè©xîPÈE °´þkG¥Ù×e‰1ê©¡CfwsœÍ4Ô[¯+3hæ%x³ýÂQܯβN4¸Ð9yòæü·?Ó£æ›ôÁÿ*–Ë Õ܆æà¿­ÿI/“ó_­å:L)[­ôí²k*±GÇ N0ÉUBÀ^GÙ‚iþVFxÂåÎ×7Ãá!'DæäÐá Lx½—5Í‘P@(S¯Ì?ùêÃô•yú~?Ûõ¸ýŽ?GÐã0Ä¢‰ I¦UµƒÒ0 7Vx”°»† ,Ù% í[ /¡é§E‚KÀ [âœ$.8J §1bF áÌfÍ1Ÿ *ž²Ç€N†À¾/Ë ôeH|ÎgàÁàŽ“†™¥ŽÄx<ÃR¦ÂzPÏeCÞéôô°§‚R_à©nÜkD™*Þt#F—ý.ð‡Á¨`墢[ŽèiCnÂYd C ´±4`m‰–+µó(Ÿ—’õM÷Ù.÷4«À*"Åç­N¨Õ“ô ¾Û‰]èOÓÄ®ÖS !5ùQ ¦P.0–œ›þ{Ð|5©ìvG¡DR§[–ípªP%–¶º_(×¥I¾ÀY$QœL×k _W9‰eÕ¹}¨m©G^µJæð¹Ø>|ÔU~8m›¦ŸÀ‡¤âÓ¿N5}ÛVéÊB2s«Œ É3;œ[ñÔåP³æaÁNß:Ož&Д¯©Àíš =Ž?Tþœw[Z_VTL„EœbUtqªÇ _×&±hÃŒ\YßRIGÊ"‹ß¯“;¥õ÷3-žаc³¥{)Ÿbm(*p–jš®+¬[¯ ½dCÇ#ø²*ož¨i@šžUËelyàŽg©¨70X}8­gÖø—þŸ“šé­ä¤+Í^yPׄfÜ©¶ÌlBaŠÐ2 MEK° •ÍÊÂò7šÌé®ëg©¡ Á`Íf¸¹.‡4‡Í ,9Š[v}Xâ `š×ì~ù–#‰ˆz9À·óRI½O¶úïJ„ÌhT¡ ©b»de€sʾ¶°<d5AÉéÅ=CðL~ïÞ@õ0­®g­×CÍw’JíO*&ƒÝê™âàŽæL:Ý’Ç”Ý ŠHC‚!"eû³zƒ¸ß_Ÿ%ãx°øž¡à“–~[.\Ï/#×aäùjâ*wßâ£ÌbkÀþ´Üi†?«©'ý¼Ø6Ýœ,-­ŒÄ4lC@zBCfú¼—r˜¿.-–ŸËìÛüw@_Ê=,.‘~Eضrêz‡¿(*° ¤¹„´9üðrs^®HTµÇ8 ·j_ŠiVJ8ä1ZƼØØ †¢g· É Xšö‰@;“®« ÞÃOG;NŸì°ëÏš÷GYÚ…ËJ†‡ÌÉá$%øû·»8<,|qÅÉ•\F%Û„ #§N0vÝRF¨PšÞÞcè¨ÞPó/¹¡¼ÕÏœRÑ$qè|1 ‘X‡F—„ WM‰m©¥  ›ôêÂi&˜p¸°´,­¯!üÃÙ7)«²ª…ˆçžM2fu é( ë`zÙBOmâÎÔ>®ÜY§bŠ'b»*âÜ 8…HÛb‰&¯Å1KqÐÑãaaÑ~‚?{ÇËáMWGßûý$•­îÔoô;H6Dç|QM¢Öõ¥Ƀà9.{Ú-ë7é4,ÄäQլơêηBñº8L¾íh@BƪÈ]©2ƒÇáX=]Û1Tç£7ËcƒÄÔ@‹¶l "â3µGо;Åé“7͘ñö@ðGÑÎX­ü»]Ù I£´Ãâ¼à¡*‚$ˆ`½:Ú1좽^8¡>{•Õ´øb_:•¢Ë½û6) •eâ ÿ] àEÉ?n¢ ÿvR2¶S ‘É(‡ŠŸrod@AV¥lÅc5ü« p€Ì|·BT´ ·žë£^šÆá¢Ðæ`ü»*ïÌ¡œäËeêDk»ßH®vðÑL:jpÎFâ!9jtZóp !Å×7#ƒž4tßd¡ñ҃毃Ü(—ª’;ó–²Q`Õù&œÖ¨_z¢û•Ú¨±Ò„ "§ Î xkÐçb*ìžÎ®$Z‘Á“ƒ ¬ Æ•8s¹@‹vÔBˆ!ô¼o¹ÍÌ„¤í­Ù!ð5¡ˆcä§©1Grc­$æ3‘G:ÆK*„ ˜•uV£$h¾Í)‡±Qn/¯³É}p´ÊrÇåq48ÝÏ¥O{!HlÊ®Z¹ܲ¦v¿ý;np:«Äf€fXM×Lv_P¥/$ú{3Y¨HI$ÉÝÇCžÝóh?ìİMÊf`Ú –ˆ€‘ÀŸ !í¸s6õ¤Z5ˆù‰µõÒö“„D]½Gªøz–¨ÑT+¢`8ì˜úÙÖ…ëA[Y¹ƒóúAª#Ö5Ep»ëüEµü…ÜË{¼KÞ÷p¦~®69\£‰*¨^Wœ†–®ø@läûxÎ4{©ÕÜ窂°œ,ôVcxr“Ìb;îˆrtc¼Ñ‚]³>—dpD@@ Êa Iª|ãÏ@yú{ú „obP%Bâoœ¯åßòĘøsº]¢ÅÚ·§ÝSÔTÓÕTUUUU5–ðùã\-Óï|+æ"ËŽ`ç—çœms\ðÔïÊp¡¢Ò”¨ÑëJ…ffñq+*ßsžF8x(Óʺ÷sfà]ݵ¶”¢N“«3©´c ¬1D$a ¢€bü/³Û+ºhåé æâTó7yøå¹‘ÿÖßµ¹è†;+œjDÏ2“N †êy0‹@ÁV˜ÿÏæê×ͳ¾>açC.Ú„ú7Ž`×àšHZ\¢ó°±H½Î­È1.¥‰èÃ$ É‘µ4…Z‡¢vYX° ŽåaÝ×~­¯‹…Þ›%Ìe¸Xeµö{Óµ²°­›ÕÌEå8$*ZÔ™`¶¿ •<¸óX–Ö+Øt[¡ÁÊ—úCÊXâXt* V•†×™úõáÒjA Kj?H¸oP”ŽQâÿ!­Ö®«˜vPt„LAôúäÈþKt¿Ä\s?)èù°B5ƒ…ò#Â4x±ûÓû˜ÎUåõN¯.Ã]NDö&zÓQW§]_4ð÷'•/XЇ˜ýGÀÁž¾7ŠÏ)ÒÒdâÿ‡¯³/`,ZË3>ù§nÑÙþÙh>ùã:5t»<®—¸+–.Ï€çÈ ˜³OXÉ2¦HrD9è<ü‰Z]h=»˜ÎåmGä*쬡hþ‚–{5ý‡f“y ö÷¯tAª>!Ÿö?Þ÷FŸçÊó„ûŠúüêe;^ ÜçÞùÿJÀMÑñáîßmW)ÏÈ”¨Mzh(Y×äøóx4m³Û¿9ËgqMˆî)$Þm!+5‚´)ˆÝ_.àøQ M{*ˆ‚Š…(¨ö©¨_ç H]:ŽÉZè ÁW@ùã$›ÆÊÕó.¶PŠEàlÔš€ª.Óø„GÞt*Ñ']8ºˆJJ }Õ… BiùµhLÒË6*Ô„‚EˆþŽßÙöô`î} ž›gNjïøMuG§aù˜H­Á²úë2€aå]üÛ©‘ŒrܱI1t$*ÔºTÌ¡ü;¥-üµ\J×Ý¿jfØ–¿g¼öš¹c9vá5ã“\ øVç:©¼I f6ÅDCc/câd„ZjUô¨ñ»Mðfç'Œ?îñSµÂ[úëF0èðÜo»pHBBeUûv±×ÇÝ‹Ñ:ÌtK˜ênô¯Õ%®„ÞSAqPþp-¨ +,VmnamÂ…Âa«¨D»®õsë•)Xk"%G?ÊÀçLöêÁ<Äæu|32Lõ½fšô¨òÊýiäÀ™è”÷R@qʦp á÷â§ñF’®§š"”ó®i¬Zè:æ&%:y\ž3"àäYm"úž¤¾,Ó1+ é†)„& ?²~0½—´ûÁƼç׺ï‚o ·¸™y‰™™™™™™&fUW¦Cб‚5N·ôñ\´f2mÜë³óÎ9í\nºº#ŠƒŽŽ1ž+q\bâ-qÃñÆuÅg‰x:ký[æ‹IÎeùç;æºÝuuuéâ|O&£Ýã2i?ŠIýχÔò¡:# “Ž¢xþ ¦>‚=î^!4wû5æÌ$O­aØ2†6k²(P‚ ÁP —w KCµó™1Û-¬ÐãÄz;šç†ƒŠs/ûõ8‰qÔn¸hp‰wýH“MeI€øÿ阚XNdu$ÖëÈÍ ÈGL81;7¦¶y6DZ¾™…owÓö¢¼}=ciçl‘ezwé:e­Éé}é¥aW²¸!|G§«DþxRÉ6!ËÒ«wA ê=/šŠÆ/´8‚x¬ŽD\ŽpQÑdïV,b9RÞžq8¨Ö£°«\+× fp@G"…É&F»ÚÉ¡Õ>#GX –‹Š] ƒÁôl <<.KRÀó>!KÒø$óÄJÔ¾I(ÉýnG9;mã­¬-]νºƒœÌæc©kX¦NS2åMz?=B$„é œxFkÄ–ÈÝÓëÑrËž¼e™ ØW­; þn#öKý7ô'|ðLN2z êô°ØGk™â‚›-ÕL'Ë¥ Ž& ÷owõýÌϘ’˜uZæèÒ0xxz åëWôgŽH¹$ÝUë|’d@Uñý³v÷ѵú%ª§'¾Žò2^’ì{ÔX9oÒqÔ3o§ýÞþÞó:Ü|Ýg23D'A'¡ÒO½lÂüµ `Ÿî{ €ØGJ7Ÿ3êïÐÂD^dðJßz)…¯Ð*AQ©õ=9¯¨anÀÈ&}Qk F‘;q©ÚkX9ÈÒfF´¸Œˆ¤‰JPÃ@—!å{$.+qzÝbÇ#Ýçoä=î”O6¥µ(ãfðçŽe×;?·õ­Ä Hî¿›×¶{P³y.'Õ'ÙWÅaù;ÃäŽ~5I]ËŽ1¯€ãSŒ”_x|M¼™% 8á]i³“FË0jµFz1T¼,—I‰nxá_[l¸#Oâ#>Ô&CL`£®¬¹}.RÍ’[Ý4òœ ¨¡ó¤‚º+1[¤ÏkÈùZ¬­­ññOƾÖË’wòÆá÷!õø?Ó哿ÔêNðc85Îáì¼!tTì©øßí†Cíf%‰Ã¨=šÂZ)""cnï/Ní“9ëÁàXD\Õr&Á7÷&‰<Ûó;Сflk'uÛ°yããFËûxü6Oó#)—´A•‰™‘ –«†"Q :Æ#Sï³·¸@< .¦ m¶¢ Ê#ácåŸÌ ˆ›¶úŸè^K¯~£lío ˜¿úh,*ˆ†‘\&Bõ^iAÂçÐD… ¸_X“:,ãß&¤"áW*Šñµ7òÝ è:ây*õ %Sá”ЖU99å‡ñé ¯¡?‹f ?Ž`ÏÄÚë'ò=ó¿Ç§Þþ/ÚªIf33&w!à•qG–øÇÆFf"3‰#ÒÝᙄ»ó.6R,Gq7c[ìçÀ;ÊJ ¼«•È2(6[ âqÍ~³HôÓßV1x šÚéÑo·töbˆ·uôþ%ûJü9>µ'ÃÈûixàMþ|¯=ƒ-œ67§­?¸Ç¡ò u.Í-3zy×øüïÚ^“䫱§Ÿ“©AfÏ éGÜ8ꢲP‰h¹w§a‹ðóA$C„n’õEþ,…Ò|h“ {hîS«8óBa^±¢ªâtä“©ÜPY- /ÓI’uû¥Aó ÝE vÜ/W†âš”7+$[C¦ú@¥(–HVr,è¬[ªmb&Z’†YUרÞÿ{²ÄZ#“´ø¡²äü xI‘–%ŸJ¢ÇâÈÌæI9åµ%郗%~¡¸MÛ;HWc»ÞàÆ¤Q& ¦žG26•`zJð{\« ™‚Dªàà®yäý™ 4­£Û‰Ë»²qÀܰˆÉ6aƒèmfýZˈ¶Ò·AXJ"z¹uf*W* TîªX( ÆÔàt3¯“·àƾp‹ƒ_=öÌÇö$€ñLþbˆvŸ1¬ÏµæÇù#PÞˆ|×'ojèëá_ëå§]áó†/=K[d¶âN4ˆ”ŸrYŠRðD±ÊŠ t Ã"QÊ€4Àl^‡8©ã‹Ôd/ånÇR_-Oïz}5á>D3èa?F¼ Òž pˆ‡Êy'¿\¹–××y“²vºBQ‹8¸ðåkÂÍÒ¥U »ÑpªšÍº.ßU¼LHb~¯ÇRñ×l{_9ìG¿¡Ï-²plt¹Áƒ·¤ð¯ ŒY4Ÿ—^·9{gº…<.×¼cY?J%Îcq°Ö]ŸOcçSëÇÿi­ï®4´ŽseƸΠQ„5AB;^4øÒ¦aoÔÞjö1j”ubµ«Jyë\zV¤§Á˜ã?¨Hì^Íu¶ÁQ’5. ¦WñFÐyÈ]e:ŽHB‹) ô]‚Dç¦;”Z}oÉèלÂEH ][ßAWUIzB@ ¿î°w[–aÚôeÅp¼}yg€ˆœTd$·þ#ÙZf""¨É¦jÐä`îQò,JNeèÆï.¨ja¬Ä±•{ħäÛð„Q‚ƒ‹…6E ÃÌä\À}×À°°9@aÆ9 Ü8lfR#‘P}Âîg”PD(X"“{±ÿ¿o¾þ äuÌŒ†ˆ8-ƒ\fS( ÄJ€b4&„ î˜R‡'„Ε7᡽ß”; `‘»3ž†ÜújÕH#¢Ï  …|¹3Ù;Q^ÖÑòwø'c „©Ð]L’o+©0 Ÿ›®ßqÉ¢#€¿1¡Ì1¼>á¬Á!Îß\Ôw YågÍfC:0¼âœè¦ #¨à¬‰¥Ö›sŽ|T¼œ7æÌŽ¤×ƒ'á·ˆÇ`üÁÿi’z÷¯9¼á"ûz˜œÝ}Œ”©ËªËV6%3&m. ¹.ªnŠ¡'wöŸÒAKøvÎ~ÿ§ 3/“³ Ã!ÇC07å'ÊîÚx=÷eÊœöª*hY#µ˜]mÚî÷^s¦œþa˜Mú$ìݰ~9ön8¡ùÉ2C@¡Üëš$OHsßã€Æþ,ÚÁCª;s æ—øtm­ÒMxÍþ£f&U”‚ar®*äD¸!(ÚEÃúZü´‡–®G¡î^U[³Œ?[xÔ¯¼H^ÜK›?Àšç:&{`=›õ¬ƒúùÑþ\/=øþÞ—yÀ°½„S7}Âîù@8õËòˆeÃz›¿9|'¾QÉ;Ä•z“ž_Ó÷e˜ˆ¹ÈÌ$E«DÑÄ-nPšPÊ ê":W#rgœ,=FDÝ?Ô&môVÑsÉèkpƒƒ ×Ù˃;ªPƒPIÈ@ÑÂЬþ/aò^NA±GK¹+(ø{Oâí:ý‹ ,ùûf&9ý! Ô~_×-&BÇ÷!™~ˆröyYlæí  þ»h£Jd4í€ÀÆ€æU,Е °×j‚X:~ÉÞP%wÔ%$R¤6Å(¶>Š3ÈÒûúõa›ä™N 49M-‚»nCµ ïwß^*b¾« ýx¢]N<ÒIØ÷G^5í1üÎê‡á~H·‚Æ"·ë‘n$‰oL„[3¥âô$‡—ˆš©ƒ*(«0”!x¾;ÎÍ||wÛG' ÚáNô¯ ÅS’ ½]õ$à‹PÃË$ 3= ¯IÀ·Zlþ(F¾H nNJÅ­D†òèÎËöB_Ÿ•{8sõkå‡9³{<=4=Ò€ôM\F½N:2Ò!ÂáamŠ­}`^ì¶€ÕÀ=NC’Ú÷Êôì#š)Pˆ“îMKä'DùìÎã^QS6G2ëQ,BÌ4Kû7VÓ x}È6^«m¤,m†ÛŠJ³4³JãY(7÷0…ÒÐîÙª½ÅC¨ò¢JŠHÓª.¾3‹>eçH¦-^í "AÕJW2Å6H¿òx{‡®á…bÊGsµÂÓT*-d†˜¶‹n}Qè‚9ùÉl [>NòZé‹ì°¸‹AË—[Ǽ£´rÈrh vîÞ‘¾žüòÏÚ9ÂÇu‹}¨{‚œVµžª&þ·0Œf#aD:®÷AÜ&ÞÏ`€?§ôné uù6»É%‚laxžÇ¹Ðž>:ÿ ß_ ݶáç<žiRy³Í[­Zû¤$HŽ<ÑÃ;Ÿn»<)U×Uz7V ¥ b«­KÞã3H:gK‚×,•»ú¦(*çÅ‚‹Ë ,ëw”èLdá(ê×Ðñu‘ 2Bƽ–WfZTIªÙ*t‚rÌF†‰ò Gyç÷˜ŽÞ…öÔî?Øb¬I’MÝ$za妟Üîh>L^Y÷ˆÚ®x³D¥9QS2Â2Hò(•ÑøwùxòjQX¯ºu‡MZ@¾sŒšŠ¸à£[nºœ’:y`üüêc¶•[ýÑõág+ÅDüèÃÚö:Ë»cÆØŠäÉ´ôp¦ƒzŽXjpý†´mwz8+Óö>HäuãÝ~*#ኼ¶È7X~à[oœ[w–•·£Ñãé®Ízž¿Ì~ǹw~ùŒçGãðÆdŒƒˆþQûÐÅKºiërÄÖñäQýÛjeH(;¹™ƒÐé`Ê&d"à%ΟÍQ{ÕR¦FüÕëTQ%EÇó`Õ‹@nJ‹Ó±~³ù¸l8LT4º¤„j¦B¼Æ_%XÅMâ¡mõúxÏùð9ÃÎ)¡Õ©YL%'0íøÎëЊ‡gM}Ûü‘ÝIQj—)CæÇ?”C/øñŠÏ²Æãy­åÏ ¬øPö›ô,O'ø8œóˆÄhÝÔgj‰³­¤/²(#µÒ¹â¸GR3z–eÇÇÆ‹8Ü3á¸iÏǼW:áãC[J{$íž3ÆëPç î õþ ±ÎPSf›ô,°2†P••KòY¾´y<…_¥log(AîÿùùkLr!ƒC"tœqEåÐô=édf¶ÝfO—(^ëÕPÕ 0…^®-'L$%AtF’ ɤlÎ8YRbʰƒ†#x8Èq#ϺäØ/½“`pqlA½èàŽ Ûë£.•ÞBÜ¡$SY¹;m}ƒ®zEFÊîfƒÕ·r:{á7-“¤_MüK;ºá†aù¥'û ß%Ákõe yƒŠóÔDËú@.ñ¸Q ÎLž¨Éò aùEž³~{M Ñ_ßvq߇– ¤IÜ8W»¶ô9úLwtÇN‡¼šuJjP®j†1ÛÏv¨r<­2´Z}œļ&fHëæKß¿¯Ã¹ ú®ŽÜµÈ[7ê‰i ßï-,ÒAAnõ¡'Ç3Rx]ýzXŠB:a`òV‹XIV c˜òúê’ù2/Ê{N7²g_zRñ(A&׺ ±B#ðž XSiÖ^“åÛÕðo¯­ˆI1,‘67"3çÙhšYZZµм‚Ÿ‹µç ^·¥0Ø»ÆÈþë/¥ñÄûó9pïÌéÉ8%=Š–qÐ6Íb ²±Ýûy~ª€™R£ Y"40ÉÛEòr#äÎs­VÊ!SÀáGZÃp„c Œ_?ƒÊb Ÿ¡úÚzSÏQ [Âèš‹Aâ&g…¹ ‚Ï›®½ùî½öÐÉtÆ(ì§ìùxM2ñ<Êô³MrI'T„QÛºÙ@<2Tç]¤ƒR¨9tÅÛ¯}H”Û1…'5Y½ñûî­.ïfFïT[mÓE¬^Iñw=QúÕÀ¢2¢B¦`@Ü®Ácž)ÂáÏ·ô¾˜fÙ­ŸtЖªà³ãˆë­~ª>{1”Iî…]±O6´×èT[’B‹IÚŒ2Z"1Š$…ÒéÞ–%–æà[ôÑ/IÁÁT¬ªª G»i^–ÌFzÓBpœGZC½Ï¬;|~ÍùK¥íñaÊziÆqÌ}ýÏ¥“Îvõú=ž®‡ §‡£péβs»!j+5ªYÉÑ-NìF¨iHA÷òÜÏ¥_é²î…ËßéùˆaÛ@ìÕGn£l…3㬲g‘Ù§ÇË¡Ka|Wn\UëÄø ¹ffø~0ÚhF°ŒwŽOÖaÂç$tÙWl§éÉ/JßzÀ e 0Ì ­wë»K!}Mb`=»åшš R…Ú‘Î!ÏS<9IB†ÿ"¹ˆÔþ“©@W´¨Á‰Éé/·ìt›è¾ªRÿ–ê¤Á’ ‹¥‰YÈÞt0Trv¨aÈÁÅç-qdnYI+D®A}SsV[{9…ø!Z  ‘ü6°ß>ÞÏÓÚ­y ‘~ÀAä|±HÄ3œŽpìdf¦Êë»nÐcVj˵ñ6«"ÉhYYê1Ì(ª­vˆ{ÞŠ.`CÙIÕÌörq9ï0¦‡QßÜs=y:bè€NBšÕFn*‘~qõ±;¹¬×\rF²¤w7422"‚%£'å÷¼-.Á5ßliGl{ÛÇËaó}tÈm6 >=ûò4ànnŽCRÈî ‹œø Ѱµz EõP!Ð6ÎÉõÀÖni'wC «6d5*z㯷õöžáô‰Ô¡´È=4VàÑ6=.»–²C@9*ôƒøìfˆySÊ dÎ"nPN©›lèxѱ¯"׿j{9w3¶r4"ý’ŒÑ’âõ¯XŒß € ë0yr6á¤L70"«ƒØ:É Ã!¾8p˜»E9¹ªJ«tüÉyK™à‹™³ ´jóµp0I‘Ý¥ñ‡ r#ÅÍ똜&N§£ÃÃÓâéò öªtw¯]Bp’ØJ+#ÜÅÈw9檷>ƒªµÁ^Ì¥íUŽÆ¼.žà•í É;˜$ÇtÆ (ÏU@w‰E#œeaKy–õQqøjƒzˆ dO G)¸)“Ýòy/wEï:£AüfkúŸVò¿G=Z\Vûq÷fob^2ÏÝMô@P!BKžùÄÜFqîQB™ÇØñ8Èh9žbâZh…¡o`å³bl\Ç+·92V†hn)êh½PF\òf&#c(9”*(¹2ÏC±H—Ö–Õzt©lΗ3õàÂb»4šã«’Cöq½û, ÑKÈU¡t<$#df ”œÆ ¨CÜÐm…Wy#T¢ }cèÉâÍP²Œñ+D4Äy:f6¦Ð>:ÙN ïƒ<ÝUr8òY®Öö¼êõNÓÕR+ZòÐÑPRå(Š¢¶föØ—ÞHòlì©ÜµÃ1ôIݯo[¼;BE+½.iEÈà¨T!|µ^í#8Ž¡ïA˶I¬c(–á\ _X³ˆåçl`‘‡)h=¬u­d™²BÁXåoŸP(c‰õÌÀ‚ÿK×­ï ®¨ ä X'³­cðoÄ݇~ˆ¡´„Gà˜þöÕù,k¯¬ê—×ùÏCÑ 4å5dvwŸWs鳂NjLŒ&,•ÏÒØ"ª)èÈ7* 0À‘°^ž)Ùú÷\üó¤¡?°Ói ¾ƒ…·Oȃ1Og 66O*e¸iUıe¤/Ƨ\.©8«·æ'´Ó¡ØÚ(ªìhöá’`feçO­!P(iDÎN²n ÌAÒÖ &Z£aŒ×êdËP÷®œÓ‘ã<§¤‡hU©ƒª£—éÕb>Á0–mPO²¶ŠF0´À± ›4‹†<``bÂÙÁˆ'‘&·_–háRH4¾ŠEÈ»Èí|(Ö ¿†ÊŽ'm$›‘lªÛ. Šèõ7x¾C÷r“ƒ’·l!& —09ÇOZàÃT+m ‹Ò½PNo”L05‘‚¤:xçUóþ~#Ãr.ÝqÛ’;hBC¸!i¨ŠÞ‚„5™Bnyj?iç)M£ÓÜôpN@É‘„Þ¼þ6×v}ß´•ÔË`¦¯³·ª†K¾†W4ÒIô^{ý Œ¹Ç¼»ûŸæçÐï>fþŒðã§ìATèU|Χãö¿!½ÅíÙs¿¤•|õ0jbÀ¦ñcÝRäƒw`û´,ôN§ER¾3é…;ï²ÊÍ0h½»Å€† ŸÕ\ÞD¬ôrÒßfÉÌ샩e^ë©´úJhG€÷«¨ö¤k›i’„µ*½ÙIO¦ž„¢VŇrÜúë¯òç¿o[jä& ãl‰»`„ͳøŒìdXX×¥QÚ~cá¾N‰ü‰¢ çÖ t“Éû)©}naóèöÞ»`¬ßu±4Цx½”—n[Ù¶ 03‹¹$÷ 0±ÊYD Þµ\oxv>] ÜÜ$š>L0ߣ×ÑÁìG(ó.ã—§¥ÂõÎn][>!ñ¶PA¡Ý#%7—#¬Ž½½ß§Õ˜nšÀô)‹"ð¸2G€=nFÜ×a›‚[0eUÍ‘äu‡«ÔsÛ©î–îuGËz_Œ«° •ëm´DºV¹ÐÉ Ý3Žu—fóêìe(ÔTºôÖ ¨+r5 ãÍŠZä DŠ#ŠÔ: Ê[éŠU©RÃ5ë[’¦xñ4ä‡åƒbÁF 1.¡aRAÎ`¡w‘®UРF#Ž¢ò Í8»&Òˇ`–ßf÷èßc®Õ?¼í/ì]S3‰5TU`3õ¯2zr¾±~Âa ›àuÅ]í?§÷gá9Ðç9~ÞìÈ;0zÌÈ_!$Õ$ kÁ•%A}™e :_Tàs•Îê;W—„ƒ:ôgB+’·p ÓLÔ¨P3I€ÄAJú(™s—pîgB¿ª7»÷FÖ.ÿ³S$íaÏúçPÝÈf‰°¼¢[ÉW›ºT²¢”LYÄ .\À"%EQ~3)¼']£ËG,ãÔ8eX›È9Å#‡bË#†u8v2£óÃm$ÓÎ ÚIª;²t9k€÷`æ1f©ûì:kI]UaÃ4Z{¹¿ßrZð"ƒOkÑÀ9QêÈSµœŽG4 ‡Kbì°p>Þ€¢øòs¨p/®×6R:9Ü1´cÓ¾GM*IrR£®Ý§5/N4Ët›ýhú5}øRßgÊÈk:sö™v(ij춆|Pá’¼I[ù|Ýs»›1ž^|mÑ ºÆ‘]- ²ÂkáR7B8UxŤÂ$?LŸRK^ÏGO†2%Ìz¬·®¿»Zlà2+ZËÝL”3„bêžì^˜¡ÄUZµÚâ–ÉÀáªðû÷_˜‚ÉS[w[<¸µ+(Yµ„ b–ª  À°ÔL*å *D¶ÝÆ‚¹Ý-’†(׆ÑÁpÜ·®ñ˺½&È^‰›Nu‡ú=+. ‹˜sÜÎòSÔnŸDþ¹Q„ØIY5ï››`SuæT]÷}dÆÐäôæ~µù—x³ŸÜ¢%ÓoÊ÷íà£Ñ2'e‡ˆ;Á4ÕR°‡™NDE8ó-­½ó‰}Ã¥ŸíqÅWá%”{(n?ݶ‘´é‡þÕÐÙÄJøàÅ‘í"â¥8r@E«j,™J<~ÅÖeJ3ÖMo€¹˜‚g‚ÂnT#’d\ž^âZÑŽü½G<…°d¼«#©LÞb$ñ˜eÓòSý©ýÞróûfs÷ÛCXüüñMI’"<.ú³ÊþÌ׿‰/>Õ{õìùÓ±÷ SR‰}Í3LÌU í#Ñß½`iÅ“w‡¯¦1zËÃç[‚ó¼q&1¿†jï *ydak÷ÔX£åÈ›+O»öl zÔâ¡îÞãƒYìŒ5ŒgB‹ÅQ#괮 JÏ[üîn©Î´^Â`hlß}{³EJÄ¨Šž•þ-Q8ÄŠ jÉËBã°pÙŽÄr…º}ټ̙YvËõ%ÜÜ»´É <Ÿ»`²·\Û먴°›qްgÈL˜î/Z˜Oöm¸”*ê$I¥¥“nU,FNº•†D Hó¢šé¨g(mEÆÚœ' Ö_ð§\ 1h‰¥b¹L(m8ÒE»QuIp~òHÙÿ=cAê5R@; M1j( Cl™/A/é5&!"ð链îmÜìïö¿ëÔæŽÎ6¾œïcJÚ”|Þâ•NT"e¥¥ ×{»g MAµUþ™líÛ9wE¬¦&zIû¹›r‹áœ4΂°ç¢dI†ÅÓž5')™íÊÞg¼!'3«Öbàãc,Å#B–¡<wÆgæù׳‡‰Fž!ÑqD%+è œÑ ¾j‘#•é7“ ŽËr¢›¤]oýoÙß:`vª±8HRih½¦ìž\I°[p@NÞVïyŽÑÉfŒfš—5Ñ»Ø+’Zf©L±ÓRܸ´s\úˆ¹Ç¬ciñ£2ó$&šÝ=N:pL;~ˆÄëõTGq\(It!ÐÑ#±&ÜôP“u,ÔÞØEá„Úw–bqär!;ÕÆ°C¸E;w©¢©ÌÂîžNß›dhX0™AÜ¥\un]¼·—ZÝϧ2_¢¡¾•Ý›–t›×É=Û¨†+……ͽIó©z¨8On>2@•™Aú=R©ý54 G’ˆ7 Û%é:ºRñCZŒà¶Vþ¡ù޲<5$2õ¶¶ÌG‘ø@vç8•ï|gŠåÓÌÌÌÌÌÌÌDDjÂsxÿ‰[ê»f¹Ò˜nvî¶·½ãu­©ˆÛšZÖ±ªÑ\>Ö÷½nµÂ•I»}Lÿ…‹è^ÈÆqSBOolûþm©³^—9U4›m,ïòA$Ý4‚Hų̂=ÕF¡¬×Y€ó~nëØwôþë)sÅ’ÙYåìÒ=•Pðê:ckŒØ±Ä¤#.甿7eaö…úðȪÞÌí¦/Ö 0ʱS›Q¬YòK„•%2Å<{ƨúøêiWS¶é£•ö-¿ÅKþƒÍZöœnýSæ;ÌáÿOÁñŸÛŒ›øZEO¥€©Â ',yŽüui?Už2%špóù£{lÕý%0Õybéqbˆ´^ 3 ýgV& ,%Ä<‡ÞþS¢ÿWw^Ìs•–(Q¼+“¡,Ü׌þ¾©äÓ] ðœÍˆD<ªÉ81Ƥ¬õT‚=%伋µsX ¯L®ƒæ«Uí9,݇麲ˆ‚Q¥Š­‘]. dÖ/¶+„¡G·È.Ê]!I ˜I’»›—žTC¨|ÝÉVáP³P •*K˜ØÊ<ÏÎ(wn}cWvþ’°$¤þºs]˜f=‚ñnK/†Œ‘÷D`›ù»G±ºå¤ó¡Ï³º ¼q°B§ ÒÖÈ)5 ÎïR:=$â AåŠä+š'Ò¢©‡Vâ—vEÚÇ1¤ÍÞ(½ô¬bµÄ ¸‡—ëêž>!È'k1qB~m?71Ý®ë é˜uY¿qBø(ÍTVê|º. ‘P;q¯MØ%¶/\"ª„™.=6à;½tùåxKb*¢wµD£XŽäšË<Å9ªè””Ó aãÚ¢éKÔL($0TQk¤n[‰Ê- Ö)$ Š ;ìNÞåE¡jµkE _!ææÇ8ê€-O#¾BÈ:RÜ[B¹“ÂBLúœ®GHþ±ÝÈ7ù˜l,h4J)ðCQ]±GÝQ˜\RµÐ/W†Ðía¤VUNØj#Ø¢±ZáS†ä0PKRçiRéTÈÚç1X‹­ WÃ= u‚ˬ˜1ab€Ž=Ži¤f‚(%|ÙFËF%nW¢Q(Xw9õ„°fà=0þ— Ú½‹®¥0k\,î} ó±ÏÁˆënë?^‰úW|úgŸ©é3¿ZÅ.| ‰bŠòÂM¿7ûòWŠž€<‹²{ŠË–/Ó=×?Âz)¢o«$g®˜ è5¥½±pÅ€Æ#a{ '”gdVk…N{K·¨óã`’Z;\}07;pÙÇjä[MÊ õ>ÑPe8²ÇˆÐgΑ ϬCD;;ßî=Ïê-­2³†±e¡C‡Má1˽‘·M¡SÃùÿ³ë8óùÁ §#£»Œ„€ Jlv‡§6žÔç½íÖç—¸¬"['D=ëøÛþ¯¹ùDé3„$/S¿~¥0®ýG8:Í Éø[kB‡Ôò,AB”’æ„Û,˜”| 0_ü1¬ç¡¶ìæYã~(ZŠÇƒ¢¨M–[n¹ï@ •H 2µaš¼´®œ¢w1VÊhk‡íšƒwÔÒ¯sßcIöþ¿'¡Åd–oa$œ¤o(y•BÇ*Trf àɱÁDHT8²°ÎÕ7¥VRºÁY/Æ‹33êñpî­NMhVý§òg2ÚØòî–ÒÔ:Ìïx6ÓôC4 ¥JOÌ1¹àÉ'“»y‚öàèI¿M’ÀçÄ Å°¼^ÃɦÈ4•) ]/Ú™ ìª0IÊH4“n‚¯ß½7tÔ½½™û{>4ÒM7’^[ FTžˆz”@ ôÑa2.Q¹ÎdD@zl€©*A®R³…Þ]|Ò`3¢Ú©!Ù´%ýõ"À®"~Ec¿FÆ‹žO>(BeVÙsÀhåTY"9¡Ý¸@Ac@¼À0[eJa,›\a“³Lîàì¾iÅ—xÎfiÌý§%N8r?VHÒóS“!ÍAÅ\ÙOéIiô7Äñöþžg†XìÎ$ÑìÊyë*`ªR'Ï9ö*º‘HFMÊêœò¡iÔ^%un©\:ejoÍŸ$Ýâ0é'X¼ÍÅP8ˆ—qÁS¯@Ý\sÄO ðð(%¥Áà£mD\Êœ‘úÈTÌ¢½‚¿<Ü;ò5û ®ãõ.ÑÄÞn}Y˜nü¨xþÑéZ÷á9 ÚPØéY!ìõvNu‡«*…}ʵ Ö«¼×@®8ª('Kí[t §îgI:⋽Ƀ i€==·Ü©GÕ46u³—2›L«}ª ýDÇJÀ¾àþ犿.Þúi‚Béõ9SÄ…r¥·ŒdPeH^yŠæ2Ø+Ù¹‘½JÊ7d7+¼‚Ûè#Ñh ]+Ÿ^„ìBæ…ã<ÔWqCRiä=Põû:‹ÌRµQÚulÖÜ@ãr5Éå¶ÑéªÐH¢Ø†â<Í”&™:•u=©«9öUÁ²5v¢à<Üg‰ƒ~±ES™g³YyÉŸ‡ØY¥Jû´¥Ê+8ÜZ𶃧;¦ÿWð6ðÓ'i\¦®§è~Þ»9ÑúNy€ aÌþò®XtÉ32–öbç~)…KÙ*P øqð¹üçÁìeæ0Sj²“µ…Z3C±Ý.F€Ö+êGdå(ig #!Œ0ýœíÓ!ùè}®šþ3ë<Ã[»Âd’;Ÿ<Ø]–¥®ÛmâÁÕá\zUd*BÅv‘W(dŠQ,šô×ͬê‚Lt,:Í÷òJX‚žÂYRŸcl³S$©àÌðÏM6îÞŸg=±jz«mq›úu®$Ñ(¢—ÑÚI$wtz;ë,Î?ˆ77ô¨0?O-å2å±±´ ë1+ÞnnLJ¬Ö˜ÝQUÛè—v†4"½9ÅG ÝŒEË HòåëÒØ¾.:@$ è~–Üä/»b—›8yy%![öë5ZÝ,|˜ ÙS›*þœís.Fk;B>ž>‰bÐ…! MÏÝæì›íÅs<3ÐWCjr`‡ø¼½—•-ÄQcš>™Àâ&íÒB0îôœ˜UòÉ-4Þ¾DÇÈÖFI¥tþ“¿±Ã ¾¤ŽÒ5#ÔX«»ÇzëÍ~å8ß|‘é#†ä}¤š£›àÂ3Xâ åã‚&ð,üÞ&3º)ªèu/CwS´%€DŽÂæb¦þ^D䊿³|ɽÿRb¸•Јú¬P±·ÃŽ»æ>ì_œ9L°@ԤΌ¹°ýX%˜%a²DäKG(Ó­±$åmc»(hΛk[Í\­2î¸$L¿—Û£'ZF”`L£{Éf‘4˰Šè!–¯³¬3€*–ií«®Ëž4õ…BT2b£ÇZlEEÃvª ÒÞpý‹çÛ¨y¿e\M–ÖžDÞ\ð…(ÿ6HäÊ1à!{ï…gÊPNúÊfWO~’CšS³=OÄBø• Ô'íµQÖB) ‘Ó—\³¿¤tÖÇ2Dxi“c&/Ktëøþ^šxåªúKfXÅŒÍ Î ý½9óL~ô úGÒâ~aû»=oºâ*R’\Hv:ÕšpŽƒCB†V‘¢õsÞ`ÎE"Ž\ÙóÓ¦„}u«H[€+1¶Ÿ†¤´±;TdòÌlÐ/x:9ÂYaðvL±(ÛB­e l½z:¬w{dwñîxj÷ëø"2Fun,ôÝš³CûÁ¦é[eÀylqýò¡¹;r>P$ÛwáÝb¶bìB¤ërÁÄrUzkw+œŽv{üûQ’P ‚B+ß #…Wd9 Ñå…ÈÒèØešˆ¦¨½,Pö±˜ëÉᦱG[ããØýz“W¥Qn@8¬À“²{ŸrŠ’Ï zôäŒêBc)£Ä ¯)9Êí¸ÒaäÄÙó™û M5ÏŽ>¥Ï.Φm_aé÷U[ç5¨‹Ì@;¾§šµÂañÄFÔ¤Ý}ÃKJëÝL«dR“ÃH°‹ çýÃCGCÓEI ùñ®#S–à«°â’ jc¬ÃJÐfòî}i]o@/•™!ÒR8Y "ñ]O“„ŸìƒÙ膺Ëû&´ ¡A,{A‹.ó ãÚ•¨Â@€^/oT÷Åà{®TÞ¨7”‰ÀU ZÞ@NÂÉ¢’TÚ"O@ªׂ2;è•WÆìŸeóI rpʤˆßVbÝ\XeLa¾ñ-5`jä Wô-9õÉžC[ߦÆ9]¬#¶ÐO\ÇK3h£VÆ3w“Ù´¶îhǬñFJÚÈc\Ìüx’äÎIÑøfEÒGö}öt béöÛÚèéD&<ïar‚«z*ÄDÑÁOöÍ>¬íÙ»zzéÄÐsò÷ ùUå^ÕA SÄ«Ž¦Ç­)ž,£©ÝÓ¶«¾¦6E ´Á~Mov¼íC:j7ØRW\3‡Çð¼Ï\ž3Ä:¿=ÎDÞú‰pÁñõõQãùpÙÓ¤Æý9¶÷êò›®¤ßÆÕŒ6OSŸ!ž#¼’xra—hørLKz¦.§Ãã&+ ;Š_ ܯä$™ šY·k8²ÎéQôî|þßÖý<<9Ûoú~†s ë°Úþ÷ §b ëÙši%a²)Hì̽âDd n7°Ønš¯=æ· Y@Í–úó<;wÓSQ?z…9ÙÆ{õâ™vþ›¶ >ÔæòI"!ø ûF/Pk瀺iëf© Q§—mBH÷áZHDrMÛÞHÝTí#HdÕ®rUG¼ aè¬ ´T7”sàÅ<ŠæÎ5ÅÖ3t¨,Ã;{Ø1D±öúG•(ªq"Ì(Ô4ñzi²Æ¤^I Œ—ààzCÉô3œAqIë¾Cm¿×U„ ÷œt¥(œaKŸÓ*u”¥€dtOml…(¨*Þl»J¤\òî½;¾TIîi™ÏÌ6rP˜hIám2eFq`Å€;ËLYî®ýý¢¨*›î‚ÊÌbS°ãb)£.|9¨¡ÜƒÑ !ÔzWÍ +Ξ¢'³“ËŠg“dÆ-1÷þ3zü}ojtKч!7+ûròþä´éŒ¤‹x9ßÍ@škdò©áVø—ïdN{á²)˜½®g)ê®çqO•8Ì•N°lcªçƒ:ÚÞkS7o‰7®±ÍëÆKbe©:%sƒž&dq Ý60:ì@æwÃv½Ý(?zƒ*(Gn{U÷ס—¨J8óÍßKÁ|À½¶ÈJC”28,¦fhÍ ]rñ/ßK Ó ¦ïš(Ú«··FB$k'S:“刃ý{ÎÜ8ÖüI•®XÐÿ:¦ÆuqÅNãÏˣᰂìBC„¦%&Ò“>ô|$Ͼ³Ùå"õ×}û÷íÆ«Öe›ç.½ÙŠ’¿1­ñÂÏaͼ<¼¦ˆCe>‡¥žxs¹Ã×SáHïɪøë™í¯7ÃKM^W …9Fû%Åg ?‡£·š»w˜|ÞgßÃYÚü>*”žz¢ä¤Tˆñ¼Oü>«þXŽN*uÄCïÕ€t üf/µµË§s9ѾÂÌ:r°Ülšû¸nø^¨øýNá”ϡے\BiÒìz»pƒ„m8Ô-Î{Pòè;ÓÒ0d¤6¡£â<£*¡ÕL ^\Äfáá¤wDÔißñy9ôM_œi”±3GW°–BžyÙ%ÖrÕºÇ täûâSpøX9X•ýŸ¿å46î1 uÍz—{ó¯=¨µh«IÖž‘ÔÜ;©ë0Ȳð‰cŸ7‰*à6©é\2kc¶ZÉh| @èrámczY"Qö+_J†Ð12KJ™”ä¼#Î "k¢i÷s yPïEaü\`í“•îs.J-ë½W| Šr"<Óžíª½<|œÄ%vJ«0Z0Ò˜O"̨BÈBéÇkhÖ%+ ÙS7†œà^Â5ÛÝC¾â9¬´ˆàçëï~_Ü~2MÎEÛ¡ÃÀ5Zõ­ôr.¾§*yrn¢–¥C<ÑßÙÝIÎÒXå";û¦bÚƒ„ås>ÙaÚ®„Ïâž§ª Û3ÈìEÑ¢Žûzbw¬á¸AâŒQ0¨ÂÛ‘7PM¿ £É.](l¹iGÂ8œC¹ÎÔ(âŽÈ¼eŽdY‹ ãÞZ‹Bž79Úߤ´ëÌc^þw\.H¢qGò·åÊ5ßzOïÁ¿YƱêp°¯ZàF•mýV‘.‹M«•¬ÁÞ,¡ÞW74¹÷¤F×ã¡m¾f²Ê÷(×X]|fì¦æ—¶xV{ü<´·s.yÇtÜc‚ìà‘q½I™G˰æ¼;†‡¼ò¹Êæ]Sò­®DZlãgŽ[w ÐÈŒíøð8Mòޤ” vï×s±=®0¤ ¿ðdÇnÙŒS¡ÌèÙ¨•E ¾Q}3yZ0áO›M³¬r޳œc¸ý]å¥Ù½0ð!ß^ÓÖ‡ãKÂŒWgž”Æñìˆôòý–Þ††r8–‡]üW×±‘ò?=Ôc³ *zz=ðøÓ˦µã>cÌ úíÏmÏZ×ð;_g;OÇ&0üaÄîgk+ƒô&%:ÑÁxU6ÏÐy‹,yÐtuPc+·<¨tCõ§†´(§¯°,0‚‚‡_HÄþÓïíý~uß;£¢ñࣷT¤;çO›f¶Bå”jõ5Ò“ïâ`Îrª¶°¢âr ÷Ù¦(YÕ&–ŒUÑŽ—8ˆ ˆð†yðÙûâïòÄÁûäÉYŽw­|fä—?WÓÛîZæ6úáþ 8¬ÿNN[EàÌ.%žhBFâR¦_è¦þUcÞEÝÛ·K­zôߢ£ìÞŠÛÞGšÂsü Ÿ÷O òßôV\Kˆ"x¦Í+Q¿]æY&EŽ5xsFq#L6'·¶hÊs^qT¹xÃEñ©ûª&ÝßG¦Ûaó’>SoTþ+«egWx+7‹ç¶˜ÀµS{(¦Œ1Jpœã-Útã³'ެ¸ƒ`oïíÓÝ!~‡eØ›Kÿ2fÓpŒæóÚG××|[o»½ÔP¨÷w¯»Öô»&åg9ã¡Ê½C:1‰Ž\‹f‡{º¯=M$Nž?ÙoäfËv{ç}Ñ|#rv¡ò³ôÄRàìÒ˜ü"Væ¦Zu 0ºqUúÓÞ/8gks=ýèBù8ç~Ï£î9(œqÌ¢cóPîÑå,Ì]॒ҷ]zÕ£‘Ç«‘’º wëùóÆüúATª*AšE®të}ïÓ ŒdÀ°~´Av™m¹æ>59O.÷{@ªÞ윅ÚMM(…èWä %c¤§è˜ÏÊB€F5i9É[×XŽæ\Ò¦PXD*sç8ô¶­)fšŽU¢8à•€cŒëÙÕºîL¹žéFàŽ åR+VbõK*Y7X‚ù¥×æÂøúéºEÈêYCöš¿Êœòª‘Ûjê(äôŽ}J󌚂CÙrá8 ÞPÉG<ÀŽv4¬ÉÂLAñç© ’¨ŠØÏwj+Š• ŸÊzNOeêó'x\OÛñÕY„Àpp€‚xÐÉ3:hbÐQtÔÁóJÈw×íÀcâÏý>cG§Ãu!Ê quð˜ñŒcnÜÄSïã·>«zšŽ˜·Ìò£Nžu6¹w~q>ëŽæ8°,"í ˆvs²(ß­²ªÌ*á¨à&Và»ZÀr‰8Â;¥¡)A‰Þ \@Xè±Ed^Ë5Ú\0O¿ÊŽÑ¡ (ÑÎ6*}. "ìNьˡ—3]3¶´æ¤DÖê†R˜KJ«>­ó²§¡šÚ—²!²>/m_mô¥©ªoÊ?/üUîJµÓNÁmZtLj˜ ’ÜPr„ÉÙ²b 1óG{ûŸ ~ÿK8FÐ%£_Й×ãõÀƒ_KÍ¡ #âôõ·åeÍg!…\Á(ôÍã9[YºƒëC¨^œ±ÔŸ!šó/Ùê±Kµ|<žÑ#¶‹íL⥋yõ—t©Ð“x•6¤Ph¹ÌÒ±‡.ø¼æÌÏìùž£µˆÍŸ?»ÒøoZ*©hÞ÷‡ da£]¨ñµQDn³-.ÓzÖ,UшÜÄH̳³{ÀÈsü(¡Úá‚?WóQ3á€æÙXQŠ­y¬¸²"ÔõB·7 =R•S¥ñ™„€ó†Äõ÷É7?Kaн‘ÇÜñÑEnã@Ö“Ã\w@7GÚÏo_Q‚±FÖ˜Û™.l*" ïn.ƒ†ˆ"±>òµìʵ º y5:«ñ²O(ƒîñ´Cê¸I}Ø·4™¿¬¤Æ¤–Ê,ÔæñìÀjDÓßþX†÷˜·=•T/_V1·D¡çˆä’ô}|}pD AT j-·r°«‘dgE…(¡ýãD´^NŒÙ ’i>ìr:v'ÈÌ……1´Œ3ä)E=H,0ôÊùðËÛ‚iƒTd,|šÕJÞ£¦ŒRT„àçìþÚù#l×;vÖÐ)cöóMƒÇ‘"Ìj£^õˆ+TZ²Žð^4RP”…dBâåmå~äºôðm„TüHùvC„x û¶ôé4ÓÐ&çv1¿ øó3ä¼cîžÑ>$-Žôíÿpšþ¯äTÃrïÇu 1½PHe½ÓÛ_$óšn7ˆXȰuëÁ„ ñ\Col•{nsº]ã÷KvËŠÛþ­<­˜®r—@ Ïå«qa ðE œÅ\¶n‹è “4‘¯‹4KïàäuC¯Kjì†ÌE‡S¹óù\àв“GuÄ?"“ù7Åã6Ù”JR>¹Ê—ÊÂOâ?rŸ³Å¼ÃãWUQJQ0qsœZ’`ÀÊÉÊé M· X5ÉoL2â¹ú¼¸a©c@ŒDXMV¯‡ŽÜe˜I¦j”QRª„V P«ïNR¶_òHØ*çD,ôûþr¥ÓŽú_“1UÝUÎJ¡ÅYÉ“ŸÊ}'z'wíóÐç&™©¢ ‹.–ÅÁòõž†³h(PnSmŒ„‡ÜTUæ‹I “¼QNþeå’i ßkñøëý>3Ö9d1úäÓúrgäó)ÅîÑv|£œ§&(MëMªRã©ü÷ÑÇ&2[«²Ïívõˆ]âóÏ©ûÐjü5|\i…ï® R0Ç/—Ô³Áè|À(X1ꄯ¬ó‰ÇyÓIéÈyüø÷§¥ËRP.ÍjÅ3#Ú‡`“Ú )ë¾Ò“DI ÕDMtS@™Ïì¶ ‚˜ž¥.#â¼û³øxVHœS, /BÙúAÃlíQ£&rQ›¿ÁÎȲ“™V*},•¢çà‰Yþ(ÃÃÝgÀ~»|Ý•…ç‰Q¬Î"°UAfªhl %û!ÑaIDãP±ëR!¤°(PRI$5´µn˺\-Qänb P^ÌHa.EpTGê^h·‘@“JZ0†:+-~?8ðÆ×<…e=ßêçÊãæ‘îAš‡tô›¡[†’þ_ËSUîI OÅ(EH?¸¢‰wN#€¿ÒŸ_±2ƬH¸{³¿bû¿®‚ýÿ\q¿?V™Lv@yDSž#-ÏWUsä`ò9j¶ÐzíÊ;ÿMOT&Ø‹±°(Ÿ=Ó{‡­†™ä&GO/6ðw‘P%‰Å”2‚ RUóOo½ÿIw“ráâÛõâ.WÞ‰ƒ¦× ¢ãÌÒ˜‰iñš‹µKj;yZŒ~+k½y»5LxÞü*Z¬U>šènañà”þ[jÆý[r˜É 4\Ù O<)cóÇ?Û~ÃT©¦«64wq©µa9Ò®¾¹…¹<£Ä{¾œxæGÈ|Ýø¸lý+V´LÝ÷²{º{[ãZlsÿƒ£e\ þY§7ÕÐÿgù½÷CØ1×Óøpáh¿S¬ŽVTá›ÏÛKºЏ¶ÆZ’ à휽-l•vöÓôuÝ7Û˜±øSš7VEÚ¼ð.“Y––«e{½Ÿ/1ó }Iõ}B^ä–ç¨êT„ÁÚÓÖ™m*SW¤#lÔ7"òˆb6èá=}°«Ѷra‡'¿—Ï£1Ìzcj@¸ëÌY¶ÂÜ÷PtSÕÐïd8 Õ]û?¾š¨Kí—%Tz¢ÍkÛ¦u9Ê0Ww@£Åµã®À¶”ág8 ×Õ`´RÁ[œ Á#Ñ€¸võ§üH”]íþ¾µö©{‚¸…2–cµQP„ÿ÷Ü{ö ·ê_‡¸~¿g6Î2E äßV×qö7AÊrBADBP?©ÖWÉÈÑÈwÒPõå,ºìäg,´?^µóC[a§¹èa‡Ñì¬UÑÜA æ`Aû_»ùu3óþéÈoYxrt5+ÉB/þ$ÝB¹‚3Ë¢; ÁÜ"˜îq; _j,C!f¯½åÑùzŒ·4°¡DpÈx CoÓEŽDXU–q*Ih"£´ãÇŽXrdq°=#äÌÃ|ª0¯rN]ŠeëÒæÿø—©Ã›;ÅÄèLàY¶ÿ¢ì$ &Cº‡7½7g´²@“) 3á™ ª)ÿÛº§Ž0! öŽ^\ ×Ë„}·Lëròº ×Îïè⨯L1ÈóÛóšf‚|–ã—Ðïs³IÑ-üù{æåÉÉ2ú]ª@x\æù¶Y'(ܜХoû‡¬“Äþ¨I5ÑÖmT;V.ìå?»–ºjbcÔÕÀDÑöÁ™4s¹îû¬©þ‰%M2Ègö9„Ñ?õœB‰|·ý_^{|žp-D“»>Öáþ2O˜[ûìŽóCªßô‚~[<¶«Ãy|©ôl¹ý Ÿcar€ˆQ?°=ß·¿·óøw~ªßãìåÞt!Xe0eQ> 1@xaüzo¯T¶&Ï—J§ÏóáÃpeY îbÐýlê–žé€AÎqpJ¸ Dï²+Çð!/µF^€ÿ"Ôr7ùFJ*ý#ôêº_çüíê¥ P‹J ÿÀ÷ÜŸ(û÷ ûû¡x±EDÈ1CUI-3E ÓÔÅ1D“ %@h¶¢¨¨‰ˆš ¨‚*¢v5ÓWí8ÁûÑm^œrª»v8[&ÌKIÇÍTÅUTAÇX6¤‚Û:O|c‰ Š¨ši'I‚ŽÊi*õ±TÔTC䘖@ˆZŠ(7œsDP51QTRJ`ÄÔEQTDU1¨*ç·üò$ÚR⽕‡" û;û¿èè\#árÿ“Ó,ÌG´öãâ zFh@üÈRIZðòI¦Wß"}Þ&GØm¥înް¼¼S½Û섇{7G[&´¢(ÈH?R40™bŒ¼Îþ›ÕGù¸zÀt¨>…CËÜ©_Z¿Ë²»¥/®Ô³p‰@?ŒÓ$è$“A "&6EÃýß5¾Š‘‚d—X¡?* óI<»À övØ$LE’‰(/¾°kìòqëýpÚÔ·êdD¼@§a·…°ŽìRÚ8{¾$äúóù|§¼Ô‡üˈfO(ÁÈ‚]AÿùÄ>ô Ž­p •y­E@èk$ @ýìÈtç“O÷SÖ驮𨝠¿beáöu~Ù žÊ¯ÍÖ^›¥ï³ö´øpÛDýßçþžñÆ¢ÐG¦ûû~6ÿ¼½°¦{óÛþ_Ø7§X¨ í`Ãé]—±è9ÿbÁø³iد‹ÑP@wâôË,ùº~|ngÆôùX;©MØ™~íÿ²¿Ù/·âðéã~ãÕHyeÑ ©~É2ÿGÈ|¿º2@ÉxµéÚÍg%I 5üãëøŠê»óêéï†L¾¿Žç¬Ÿ§<ï¾÷å¥ïh0šp½4ˆÆSf3j‹9lýõiÝJ½¿>ÎjçÙï™BmåÈrÒ. rTGá͚ߟ?Œí2Þ=¿ßÕßÓKd´s½ÃpéÐþ½sÝÇ«B"3™qØðˆD4üæúÿ«öðÕýmm*ü><£ÛþxxòÖ·i¶ÝI¯Üï¤V*Ö>˜Uø^µž‚½äj{¼®F _ÄÕ'õ0ø|?h”q§æOO¯ltDAŸ›eë¶8øy8óx¿Á…|ÐιzE{Ð'ž±õ!—fyJsOÈ–>OÖ?E ,Î8ïèññ#ä‚c \ì<¤;?ˆ³Ëônkd‹ã{¿±ý Z¹â«zy?ƒsåï¼~Á¯¨zÂ8{z±êÄÏÃ£ÎØ p属©Ž¨ËT9yF[ÿHŠ7Ž’¹hîÍß-y±F .î¿ê÷qòî´_€¥ÎûÁuxñû~°GìW‹ ×mÿn<7¯¤ÁÊoÑŽš®­ëÀ&`zG]%œ=¸y/ˆ=#ÉO>iƒá…-P#exkà3‰>ø –hüç(ηëéµÖ€fŠ %á `,)¶]IÛ:„nO3SíŸÂ•øè°0¦Cì¾û Lzmçð—Žcº½}$”$¸8~ 08ª²¤ß&°ì—|'åžïn¯Çòzû(Ctö™tq‡K÷µ+âš/O4«O76Ž:iÕÇÓ×÷K»Xïÿ—§‡ïþ©ø¾l&h&a(ˆ„ŠSçL1dHIT„¿ü yþ__š=Žö&·û}Zü›ÝéŽÊæùö®úë†OmJŒ"ÇÖU0a ¿2?Q‚¨*q±&5tІÇ=KTL:ÝÔMÈüWä»n«¡xc;z]ü“ØíÉ«ÑGx€•u¼y­¬×ÇÙu˜áÀi|{áåñø “ée=$ÍÓÝæö5Ç‘ùˆâ7Y>±“¸ç½kóâ•zxqÒ ánÜÃSÇ‘éСky@,ëëò|¿çñû¼lÄøiôÛúÐ "2 TúìådÆœ»]+.zRÀR "®{%ÿ——Ÿon=»ù¾£:»|ÿg¿å8O“<Ž)ASå!ÄIé©ãôù?ê5¯>åƒÏÉÏ5+ñµ=¥O"ÐhŒ~pÀd9 ù`°ZD¥¶œÛvÅÉÖ ("QçR+,Fÿ¯Î·è˜ÝQ| =ž?`ò”|¾>ª…<Üyš™b&5ä)ÝØuýãûýã€éù“žð=>W³öèÃá©°îÞÖ㭀ѵ£!ÕZzJøñòÛ/'箊m»G7( §aA‰«—_‘îäð†©†oq‚`AT… öÀ|4H…ñ°??8)Ÿƒ'Ù#ß/ç;™;žQ4Mjâ!jQ.!€@>€øéâßMeÛ÷ü8÷7‰—´;Áb§›«ä¬`ñ¢‘1¯% —Ó½G0ÐÌ9éÈ7çq¶Pû¸ö Wäúl¾]q‡7‡i¥Þß©áʼÑêJ^á»åß$ Å;>¿¼SÙàž^t¾ýU÷e¥«‚íÒ¢Ý+MZÛ’µûà!B’M‰­áÐxŸäý­ó·VAÉ'Ø;xñd_¼rߣ“]¿}Ü eí*P€Š„ž@5æ­}ººÍž_lãjD ’^ÑÇŒº,Ö9’ÎÉö}ð;Å¿<2šùÉUMNx“z|$Œ_›âŽ#ØêãÓ»äµÊ"øeÐ-ÀJ±áû>»;ÃæÜ/ü)hòsþQ«ž9ã÷YëàšƒÇS¸T‹WO ú¸Ø‹ÖéÒÄY`­Už7jЄ?æç•â>¼n¯L®küz|’[?Kj–¡%ðýµ¿`ŠU|§Wuý4Qá>ßÏ×rJ%4ëN6ÃÄM58Žºsòظ/wº Ú³µpݾ«üþéñ¨îï_ÇëõCÃo7ã=Øéîèêl>ôðð¼otãW›d»>£wòçäêAêzéèËÙ«D¬Ê¾í}~¾‰×apŸ—¿ÍæÓÔ ?Û'toК<ê‹ûqè®ví—VÈÃw«cºÏg¥DÝu£š¯n® òÑË¥ÃpáÊîœÇe:¹4Ç]Ћ¼½ÕêZeMüòïìv‰ì®¿#¶÷sÿ_^œóÇ pÒþ|¿s¨F:ðåýÿr Ùzù'm(¶Ãu»äGiä‡p{2‰|¶°6ØØ%ýŒÿD?žª}^jðýç3ûù Ìáyü^Ëä×_ÝgUÁÚƒ›g <Ì Í'fiê7._ü%A‰g*'2×»À1áΓ8÷XSY ‹ ¨‡ßs ?Ò‘“ÐÊšˆDÉ­dLX}½Ž ‰åP`v²èkþÏ¥w0kÞÏûÌ ·‰ y„✚NA‰RIϯ¡¡¿®0rV› ò¤ÛØdÖaHsƒÏ,sÂÉhÖ˜˜'àÒî~î8 `~X0äÈô&Òäº75¬rÎuöó 0->ã¹ü»ž8¼/ÉïK+×*ó’sÁ‡óûñ¨–kÆ Àl©˜c”3ÒÙˆ|˜|^b×] M ½µHtR=ƒ|p:¶œªŒtÂðšênÀ'BˆHÄ$»6›Ew|KOg"~µQ§dâký”É¡ÿ›2ݹÆÝñzþ€Ôëd2E3s*Ù¥þãìH7sßN/ ·7Y’¨]cäTÉOøÍäPF{é›ðWg¨4í£Ë–Iœ”|ì]|¿U†VgW£­³ü_Ñäåä|¶Éçg;Ô¸}@”:>!¾ÇwÏîÏV¿Ë;j¡˜ýõÖı }BÙÖ8€+(JêPŒ¿ÓˇëWss$'\aýi4)¾†Œ `b$ô¶ñÇ#¬ñ¾ ÀXA®¦c¨aå »s¨ùbÕκÞ…¨ñd0—Bà‚[ü§s¯È“šÑWjø×mî€ûA™dv—„Úè7éþŒ“ß5” ‹ÃT%eŸåöÝ»ˆ*ºu²L<ém ƒ}\÷½ˆÝåóÏĦä¡}áBsT¢3’uÑRG¹ÊÛ]}¼&FbŠPdôvzù`Ò¹ÕP,QD/ai€hÎfÀ1·ÖõÚÛ<¹`á7bÃAŽÛÿ£Œk¬iݦ \ªçIVžªa6£¬Ðÿ6{“Œsvgcˆ›V%çÞ4­)Ñõæ³( +Ë`Är‘´H¡xê,¶v#è¾vaóû(åýÚ<”Ði‘ß9À$œ ð])±•"Q•ü^µ j·/•0p•'sÊŽä†Üxs'ù/F5:AªÈ4/Q†üÞ6™ld:²Kvhføê¿”ÂÏÈîAð$;w'ÁÖ:G&ùnÁbðëÜýkW2ÐEúØJT›ì©Éš@{þ¡¡ à¦J.»¹F€ÃÊÌb4J^ ñS¢‰9"Ÿ\°XÑ¡ô ,AW¾$ÊVì ¢Œ*©!髾/Ȇ˜‡Çû^ƒå ÈÿcÖÀH5Éâ–‘`dÀ…Ä~ô¡ƒ‚‘ô Ü•WM{Á”@ŠŽþÙÂ@šÙ7î4 ^¦ °Ñ\*r ­5˜£ú9o9a½65«5F szï-†=bQ…Î<=IÔ2x9Šc ³w£5¶ó~¶½;h³†½†:G¤ÅtåE ž['´L¼ª0'–åÆFA›R„)•í4ìå kaO‡ÑÆ“ëfÂh÷Ÿ2!¦h2~?ÙC½ö&?x˜,3÷` xV§BËûADô'I@h~}ÎÏŽ ¬ó—:WP à.‚"‹”&¬/dHIiÅÜBƒ-ú$‡ÎJ­G„x¶{ÎŒ#ü¨o‡4só£ùÉîäü“ðiËÆ«©¢W‚ü¸4D©¤Æ4†……"´J» ž)ÉÈ ÝûOdÿü 2w†‚rÄ¿årLîKÅ¥ãìºêÝ8bÄbEðe?ö›™×ïùÎF“¸xpõ.çE4›GVŒA¾^Æ?hâ8%b`æÏèÁw‡C1'ò¢‡œ‡¯œóèýžž€éãuÎ8£~‡a½–'[,öAß4žtÞtC¼<ñôù.%c¾•ŠŸê@´†¹ Ä °»W­2Œ†Ì‚"äN ÜîæwüÝG7í×ñqíÉÿ/‰•K¤Ý[ÈŠýn{I|–;õÛ½ó‘ß¿–‰x8¨'ž¡46´ðæ8äŒW}õ¬¬Ì;LÇØK÷—P ¢†ª¬²­ß9lz~þÍ$ç  ÚÃa‰¤¨„Y6`mÙ—KÊ»A±b¶[ *%€FD‚à +%3÷ןâ¹ñfp;¦õÛ×ót¿—ý]Èî÷DhsÅúÆ({P&«¢'?kü‚Ÿ…Ÿz‰i~O_ìÜû;]‚f+Ô$TÒ UC­Á.ájþ^-pô-V/í j­ =dæ!UayFöJ=ÜpòG–5ÎGj^Ç~å³69Ýa6~}fGt­°K~|Ä›@G“—Ã7þÙT…t8«ÄÛ3¸ù÷6ª¿?ËÇŸwPÁT ô"ÎÒ”ÒT[ò†Œ¦îûL ‡õÄ” UM á–.ñ¢Èl»Y#Ô³ƒb„M¡‚&‡´±Ía.!hXh%æƒ$W¢Êy¼ß›žlGzðé·`pí&”I‡˜kÞ•Oág˜²ZÇ•”¶Äýß½ý·3UˬC2xä¤`‚ *”P­Eà3gåÖT¹?äœü»gwŒð­}Ž¡ããa“ãÏhòŒz¡ôy 9ÿKßVœtƒ' ‰=-ííß»L•UŽ%–9Í ’Kd7JDþ˜gdøs3B ZÜ糫D¨ü>LÀj5 ¬ôøCJ¢\ »JDÄòÀxVMPA¡D !5(CÜüëMãç„Óu»+©Á›ñ£;Ñ×+àUhTŸ7ëÄ«ŠGCnL‡Â±t_/yså°i⇂˜# «¥èr³“çϬÖfœžº‚å¯ö>™³ªÉñÁ§@÷‚=éëôëø ñ¸( ¢@DDí‡!/>(¦ˆP+ßQ‰ÀÇ¿ÃÕÛÁw‡ýh§#çO-±°~rË>Ο$’7hW3zj)ÃM0qAÊ£z óÝQ”€ <¤ù‡ª˜j'òCÕusÀNÚò¤í­MðkÆp¹ÜÁEpˆ¯ïFê†ëÞ¸-˜*CHw$Ÿ¤@Ý>Fg­?À¹ßPñ¾ì4÷XÿG8 Z`ºO²ù´·`šLvéJ² ˆ€¥QP¢" ÊÌ0šü+ƒ Öº4Š‹tê;3=O<] Ëï{vz^ÞV@®}În£ƒ¸o@æ>Qé·ò`=ˬþ{Š ž ÖÚÜ©b h3áÔD5<ÿ¬#`kQX#àmˆ}¨•ÚT¡)üsòèÃC‡ ™‡èüÍ¿W¾âãÞ˜}:FZ4·HÞ€5?o×X^C7éºþ”6z4Ž7“@Ûjý;zºûxàˆI'¹„Õ‚¡OÜ4ŽÂ—zEÿÇó¨^S.zÈÓµE!Óû“™æhéTÉè>à `øžô“éáþÃP㕸•Ïá€Ò °p‡^laòä ýV÷jû?Fÿ›·_ÓÖ-£d¢ü¬“äÍ/Çõ€í£àƒq¥zÕ€¡Üþ\ýûý¼½GሶÈb£Ê9ïÊ_úSèô|UîÜ4N»=Œ;PȵT äär'>(˜£ÝÆÎ†×\p#û*$Kòq¬è§ñ¢‚€i úH”D$C™ ¯ÔFe’#ùG(òCᆠ.;å:´>φLÀ\ðÝ®_Vm°è0»ìËRØ‹¶Iô¸Ï­üG´=0€gÁ@ë(s‚gÕ'û¥Ý!ü¶Ëò°sV·Rš°!Qÿ5¯ŠõÎÏ^®¿ÕöµñäÒvå!ä*R:õÓÏðLÇ»ÛZ:Xåö¢…iR}Š-e/¥ÉúOãÔÑ:ù/¼%³Ô=Z4sjC“xÿ.¿~Êmì¸ñá›ý±Û~Žþ} P,x}"6˜ÐÒáˆêÆî±À×ð±&¿0¯ž²/4ҺˠDüHw¬ÊM•Ea \.Íb%W+0tH×쀮Õ=œ$—©ôR—rñ£"GmJþO°RªOÊê3®ªxÐýcc€ê;Çü{kð¸|ë¶}Y»=C˜T@ÿ ¬èÓHœ$ÓøwÖãX<›GÍ8W]Ç´¢qȰæŒ|°Ê5M¾Ä_ªÞ:|™õ{|¿Xaóß¾ñ³V¢ÚanÁÕ°q»<… ¾#H¹ï컑žy†õE¹3eƒh{¥'Ë8WvÝ;f>6z)Pùåë»…ÁõgÌ×í×>žMùñ?ú¥î­Wjlê<Ö>:Cn]yKîhï¾f°@¶PƒŒ¨¨DÔ ßxt}Ñõ/Lƒá–0{ù·_)'E0Îé=þk wòfb5Ö>nO¿WXÏ@ŸÕ’Tó¿[á-^ªý’××Ì·y,úºqvÞµ¿% .?¢?&ž"ëKVÆNHòFÍœ Ò®±$ª¹}œ‘?Þ@RH&fñ…öîÊQ»Ù1ÎîÊ—Ïñ áiÙŸ×"û€p¥Ü‚^ÛlUM„M'ù±¤â@ФH%ä¡<”:Aè)(F”„r=Q‡ãÇÍþÝü÷^ãôBD•5JˆŠ¡²W‰R`=-YóÿW³—ZèC—9Á(ê˪ý[oØéÅÖÆz‘Ú$&eí¯é¿ò´|LvEk ! w dÅ"Ûݧ(X‡dhnjÄÚ© RáS§;Y(›}{!uXL@—]R×G=æ·U!%,Ç#aK~ÐìóëùÕY¿ÂÙ,„Y>óúžoÞ§|`9)d}÷þ{y^í š&hÃdŸpñú¾ ^<½û…c~òà,sƒ pm!}ºks¼ÑGôó·¸áìÚ- æKŽÔä]ÿ¹ÝqÝØ^_Ø=?0×ÕãG éZòq³Ï)Z%)d*šÄ4"£HÕ¯ùS Ñ]T<‹ÄzÖÍ»µUÉ瀊Ÿ QÉDÊþYi•¤-Œ5Ô£–‚1Ñ´Ñÿ<å-P¿ ôݯ gJñk­±òÆWYt5äÔx²×,BhvÜxrþ….«@ ßZßîÂÁh|¼QdM‹Ó?3ñ…úšÞ]z¡O ÷ÿ •Ř+â8¤~[T"÷¢„挄 õE[ßòåó™æäB‘ÒP‚€/¨y˜AØ•«ÉÐk«e€›>›´\èêõ˜'·Ü ^éN™Y´ÏÔBúœÓÂ*S°( Nþìxjúqú/ÌqÝž¹Ai ßâšÏ°ËÀ`}\06¥öùtꊉÚjÝkù±Ç$ÖÍm¢’&¨jËMÆB]LÞ¯TL™8³t†N• W ¤ëª5qâza½¾…9«‰-v6.W&¥×„âHð"¿n“Ñõî:ïÆ´}ƒÑ.Ï!˜‚Ñ–ðNºþy[¸&§Ì£mŠºÇýÈ ¨“ÛûܯüÎ;²Ï}b ¥ì¡T†b@ÑÁ|þ­úõútä"x¨.Hdö?Èîm ;ŠÄ¬Ag‚¾f±UêÂQ?¡Å" rþ§Êu ¤0£ŽÔòÒÞŠIKÖÅÅåñªæ†üa úÚÎ…õ³­’ÙƒfAkJó+ªÚàëâmmÕòøa„#P²á%x…~V6? þã]\ÕÇ^„­ùT JÃС¹®{/É—G^z Ûú¨uãnNœ›$ëÈZ9&S7ØX\ÚÏ&PåùÏE#H˧„%ÝlþðºáywÝS\ûy<—6és{C¹;t³Ú¥Ô"é m×—áøA³d’2AÁ«½ŸÁTÎÿswà/äÃv‹ÅsR¹X84/µÚéaXzé2hª¨«¿±Ú]V]sß¶¥X%±Ûà¿N W.•Þåïõµuô Ú»i†áã-V‘èîìêÕ¬d¾^!énUéªÖF€íEK^ûÄÇL!5©õÍEã¨p>é ü–d8ó.ù­ö4„‡.u¦« ª©ÏÜ’hWšÖàU‚¸]ëÆ·"qžsÃ_&5ž¨F¹…Õã¬h”ô yk}ô¸}Á_·cøwO'uἪêü#ñë«”òä¼ÙUœ¶Ö–‡OÇM_€ùÆÑåÐx>/aöt_$M^öÑݽ9ìÂhîp=Ǭœ,ÈÚ,Å—yDë0º?¼º»ÑSw?âð⻦tÍDº'!L0ÎÂ:IÑ<þÿåÒ<àØúå8@Ð!@4”J4«0“H¦1ë9ƃL$²SÛ×)¿£ áw%ODŠuçèÜ÷sྦÐq€…0É(»1CâMÂWc¯7PòÏÅßV”y„?Nã. @™Tð$BüphD:¡(?ÓÆ@ ”ŸÄ'M(§T If|·B€¤˜P,Åpcö‰ëþ!ÙI"¢@ˆªˆH¦"bd©ˆ!‰%¥P()U F‘Jt)¿—*§Ã TJ x, ¢iW¡J‡÷á@è~l¥‡¹€´ÕªÈ#ˆóz¹¶oø·îL„ž„|ïŸÇoqó‰‚x½êŸüàõH†’0–íME+#ùÿ…ãªPíJØý /¸&Ÿ—ѳ`I¬(OXŸÒ°fPŸA3éö÷k³©>Ï“Ûý¿ÆuQ^5¹é ä#_Ó¯áù´’Oc {OA¡¡ë`AcœQrïÎUGÆP›ÑÔ>¼6Á’d7!n2åiú´õ?¿Øô !ê?|ëêáÙNXžƒÈ3Ìä X!0ØcD.ËEØit™q•‘=ˆY‡Žú§Eáe w|þ¥”èp` [.2flLžø 9k¦ØÈÝjVÝ u21 ( Ô=htí$«Ãùº:©*¥]ù”Þç²×_˜P8ã1Ä©ý6Š?¯û3áyj‡@Ýìݘ‰U𪂵9$Á¤¿ùB €ƒÒwž;®èÀ¯«Ôz«ZÿòópD{yZ ùð,0@/ês€$ÇÜùË©õšsõ‡*ùËÔ™€<Œ âÌÊÎOÅÿ—žÔýÎÀ„üù;¿¬ó£…ñTa,ÑïÈ`ŠÎ"AÂHŸ›z€ô{`çˆ5Ûí4À,ï.ÿ »°b IQÔ¡w\ÑÐX ð’°XdmÃ?GpÓ#Fª³úýŠ5˜w(œK}èœF‡J‘Thh§ˆtÐèÄÕL)Bšum ]h1³IEæ::é(GKIÊV1LUˆZtä‘«j=Zùy¨´ˆ û5 7^¨BìbÅ•H*QAs“f²WŽðôtKî¡ÌŽ^¹‰HiUz…Wzï Ëæaà"s;I y½ß‡9ülÚüy”R)CÝuÆ—Ðö½*‰Ÿ¬~ÁgÙàÃe·Nh¤*©"ÚÜÀqÀ`"ô’Þ ØO¨ü#¬ê/Ì&t-̼nÙ³eˆ™=·íÜfž«£Ý¶Éù Lž"od<SðÞ“ì}Ìú!_Ç"Ìür™?, &Ðo*yÿ7ôxÀþq}ôosæ9 ¢Ècÿ^ˆY<åÙ,ö (UÓ²/0Cpê“ðœ²Ôb>®ŸÞIîÉÁAâ€ä !û” ]{9BrTGÝŽ"Si`ºþçTC²X¹Ûu5P…Nˆ¨üó¿^ö†§¯hE,8|-hyì“bU𢍽‚•Y@‰ƒ šU×½"À§Ÿ1³œ½4\©n«h^ûØ‘µ Qcn@ãæ Õ*B×ÁžÂ»T0DŸ;?˜‰ ?ŽÌ”!ËVãýŽ_¨Ÿçôñü‰ÊgØ$ÃèÀ0¨p¼† Gˆì®u¯£t‚HrñèÔ5Ó0&õ†A‚±û ¤´½;žÁó¬;}P¦“¯nÙùMä3è„`v½üh-;^H»ìêNy:vÜÙlþSB§HB;2§hrh~"MÓYòùa§?òl–”IŽ£S£·ª•báïª4¨¯»“.‘¬À&©$—Dî8vƒ¤Ë©=‰®uÿ-y¼”ü*akqrò¼Ü­¬ü:0ÛÏA3+çFmúØù%8?2K•ô>“ì´Ü rø¹)´*Í]»ÐiÞs·w7² ú½©àëF!xlÆå0½•®g=…Âå[2['p~Æ †C´Dr‹Gh­:ý¼ppÖ…I@ë”r ûÿÂ#AAœÀ&™ ©ŸÕþ™¨¤RbOÝŸ3ðT°êúÜñš¢ Õ|û‘+Jg׈pw—ùϤ_U¥¿˜pº6é©L(A€®wBE®tQÕZ̳aÏï†*A»N:kì}ðÓÆ,€û¿¦g÷?¶Ð¸ø9‰$Ô\î )Ò(N˜r“Ï/|…À߆9%š”2yR©ß¤[½+WE‰KÕIÊ#å“ûM, `úl ¹cãªÝ©ghTDëÞsb‘ÍxŽâ«h–†óX 0¿„§Në¼qø¾?d§¡ò>ÈÀvÀAöÕ‘®ì!2f}l†¼ã ª)ÇAR¤“z8„&\îw´™H‰§BX3=y¶Ž-Ä劾Îm&šx…ß(&œeZE!ç«MÈcÒ˜?ªé²`{†¦›± þ=ÛPÄ÷°(‰©~Òʉ]awÌÀLÚ eš¢€Ð¾®¯jY—Gúº¿µ—wÓ )Ô©¤úø×瀣Áø-ü±'º¨þ¢8§÷¯ø¡ôA4¢ú…~‹†«vœ¶ÙIÕ×-œG q‹öåpH‚z…@çz‘.=d3uÈ(™Y*†g@+|pN¤š¥°, òë%Ÿ¬þ:¹Ž´Dé<*PÀ§œ­Žxåçedßýô¾Þ{Dß$`dö%–nsŠ^ ÷s2" ³yxÊ¿‹êd#Î?Èq1B—{Vì5|5X‘ÿ1ãA 4äí¯A ܵé-×0³{„ËÂÃL:ï[+M%!: ¨\WÕeûŒ‘%B1Ê1R JY""¹fŸ?W_•áÀ¢a>éMR°ëµíÈŠ‡b‚ʨQ:Kˆ˜z×|•®2耤Ï*œnJ‹ÒÛ×¾BØ" XôªK®«ú“‡–yÌ¥â²i4­¨:¹ñk"yLtgSB‰@B…µC5D)g³ ò™ðá§vçgV»î3çÀ X?“¹ zÑëäß91‡” ÆÕ݆oí餗WJfw,${‡`¾ðJ$)k¯-õaXÞµ¸Z_G†å[,sË™\Ê\ª ŽËU¯+ƒ1Ê»[Û¹](òBuDzŠ’s¿¢°pÌÖ¾5¸é[i»$»Í-Ž1t0ýzÖ~JÑî²uíø0•ÕPXjH $ÕM°±z 5è÷êÐÞl4Kª².Ö£S‚“è!KÏ3y‹Å—~¶ÞdÊ)ÁDg3‰—”¥£üˆ5œô‰8§>Ä5eä\"Ó=ñöcêë”=ܾÅà)8¨Ã‡t_é2Á§äj¾¥Ö3Tp¹aO_)½`ěߎ|j~z˜sè)톆"ÞúFVVʬ`­}lnboÃMOfƒ¤û/-Å©:Þâ C(±EϬÈ߃ÊÕ]]ÓÓjÓTêŸmãĦWe“¯ªÀÄ“a$9Ükº×iDL’dªçIÕ>"½Ï­úàÃaá1ÒÇ×tg‹Æ[¾ZK+)éq<®i¯Xu™[w’càþjé­kx‹^—3Ò¤¢®°ÁAU}ÄY,)9ée®ùÀÛzÚES•õ6Š<‹èíãžDéÛ™ž;ñ+_÷f¬­þ©Œ;ãÙÎÆÜéZðî“2šŽÞ^ NóÍâG]Ñš}6¹ûÐsŒ¥P£¾à×U6]<ôÔôéMð› qX8ÚÎròÅå·ßu–>uìž­0M…Ä@ºýS †Ñ Œy°r¾Ê–Ä'-|;y¡]qïQ&3:ã]ükB9æ¾>ÙŒsÃÅ9-³i UN¾Ž¾«ìr—;<^ë-F$•.fUÈCï÷+Þ\†é¯d´ÿR¬(ËÎüöó¬èð.4nÕ Ùc\òc–³E\;³w·nZg>²ËURÿf÷LwÝZ3—Vü;ÆÜ9QG_ÃFO†8׺©,„’Úìˆ]E=ɬ8Zrï 1Ú=çµÞûâmŠrá_þé!pKùÎ$õÙ¾ŠÇÃÇã8;x¼Ô  DãE©Ê;„jz@•Ô£·Ò5Ò–Ó U›˜WѵèƒÌ´U\Œ'—‹rQ+/D—1¨ê¨( ŒJ8Ö1`ûUC뵕™šUÉ×>,TJ•_ê¾MeB–F ª D¥’0†*óª«]”*›ó…\-aD7ð.€ád´:Û{á߯ž˜Â7à…˜®u×Vò¯'¶üõ7Ž>QŽ+‡ênЊaÄ)rPfdß»×8âu>Œý½8†Ò2ƒšù ùÞÖðЃG>yxë/צ[~³Ä³:/– Þæýîfß ¹Ês÷Ü}üoG\-BY5l±¡àNü;ÃÊr4î.œ!ëŠ.NHòÁæØ<æë+P¨Ml’riJ€Ou$¶w3!ãF™€Þ¥½ŒÀ2æüMq*À9B¡´…EP㚤Çw8þtŸã;&ýUaßåíìóú¼‚ šPV-üƒ\·lNý<¾H$÷¨Ûó£È›ä©´\2ñ!!CÀ<½žy»Ž¬ù!Ÿ¼Ëe&‰5~šJBAA8?Ô'ªžs´U¼írŽÞöµ÷AÍ[d×6²÷š0V j E•HØWP)žJu[,yJfñœ‘Ò 1^Ù¥Õþ*¤Ufžÿ&8õàO_Ë4Àff C“¨à #î*]=ð(tÍáû½û<‘„û8ÄVúÓ“Eíí«†Àld³«'8“ÛÉsSïZ‘@ù¤A±TÛêéòlWj·»ø¶ºôªbìVZõ¤·EBjV}žÿ¡®v&÷þƒ6…]cð¬Øç'®3Ü_ áòëÖ ³gCÿÝÐQÁÃ}û:¸H¡ÙÅÜtg'UãFW7ä Æª¦:C­æ¼¥.Uº¨¨ÝÇÚÚwrcbs/V»vèp¹õ`tÿ‡‘áû¬^—ñ…º•Í ÚĨpWñŠ3Áï 9d—ϵ`ùÍëÙÕ¢•¨&pvyŸÚ$¾¯(žáÍõ;òAý­îîæý¾Ü´eÍ»CÉÙ¨ïÙÍ s5ïžÑÆ| pv¯AÿˆJµ_z5J$!æó¨ì~"G¦¼@XhøâiÞiôÅ%<öúályö^6Ûc”­º5PS ñúDLµM\S›ó‡)‘ª Ò_:bu(Ý(~"]ôaœ¥ÿ_§èï#Ãn×› @MÄgì¥$îHSƒ¦,¨­E4ñ.ýÝ:AhRà 9rÁòê¥2qÝV3²Ã<þ«†üjjìê’eÎþ¼cGñ&ØÈ†FQùѺý ^á›zçñÿ;xp þêÍŠßÛ¡Ÿ?³ò½Ö¼Nê¼Éô]ä›ö†ên«åFgç0¾AbÕÝT+YZèìÑ " Àjñ˜˜–Эuc QuÒ5MøèzO$UczùåØ>°,I›Š‚7Ų_Ö~fz~9àç\áûbáÐ4‹Ü$@S›¯KµÓ–釋AƒÆ…hß…ž½7ícÂËjz ÝÄ2Áj,l­²w¦:®¯D`lç Pk9­vI­âã8]U]á÷nª¬žZà Uí®VQ†à Þã4’°l"C¦SÌ£å^Ÿ²¯]+¶Úþjïï×+k½XrT‘Û‡森¾-y:œ SÈa9âŽm­øïuíýÓKi~6¿§-w&¬„ú£"™FZ„bö±õZâ£ìàcâɱGÓ_À–[ªÙò9ƨååß¼ÉTUTâf!ʳ¾ÈKöúc=TxáÏÛú¢ätÔ”wuà4+Ãï‘ø}˜[Xçǯмjèo¿ztòŒ”x|´{hhó"üº:4óŽèŒö$ùÖ¦fzéØ!Gwd$rÇžåȈTèÛÜD´§#ÖøŒ@›ÂU¢lËB:PåÑWüÆÝvD%ÉeÒ!„È£ßÙ!›NÝz3XצIû«ºâ¤,»49û*ò~‡®rÆñcú´¯…K`‘qº.å½îнÖ^þ‡ÎîM¦ì@œ€Pü·8 \ö“EÊ4é^Ru°WGwçZè}®h6;ßÕ\Þ®|¯ÛeÑy¼UÏ¿}ðÙuR}¤¡]C’éuÒ@¯„tÀDùÞÛA«³žÿT4J®qUÁÖž¬CÑû.ã[^&•ÃE&ÖšÙƒƒsÖÛé ;m­’ŸÑ,¬b´iŒýàÐ:õÉdeÈ܆0ä6ˆ¿zˆ ŽhˆêüwkçôŸªÂÏuÃoïß&fl‚Þ"z&p=ÔȽü¢;åÌË®4ân®#MØC“uïlŸhÊÂ¢í¨™î¨+V>²»u¬k2µÏV²Ñ›EU‹Õä1Ä©ôÁZ5bêQ¢ô±c`6t:ůE!Æ KKÍ ëJX!9¤ê|-Ó'ö\PëN©m©öî°˜ôáÏŸCá>5ÑãHÕ'~jÚGªVƒ_³ÝÇM¨«¿®ÇÜå ozÎãkÎy† zÍÆùŽ$^v˜šÔ+ É.áF©Ðb \ QªfúsŠýUîp¿Ëƒg$÷_;Y=§aÍWdç(ï‡Æ^3Ôú¢²“IÚ×W üØ’…|ÀSS8>ëY(»;oGú.ÒYö…¡gd*‹qÑhÁ.†YXê¼Z–ÉõY7=ó¹yý«&4÷¤=,m÷ ñ qfJ“ÜåäR¡®-À-yF¿_F½2Îvȵ>—éŒò„QUñ2…$[Ib»—Gd¥–¸"댟ªØVøØŠå ªÈwöÝEy§†I«ÝÉ5:ƒQô–´ÒÛª +¢ËU;H…V}ž®ÙH\*^ŠPHKˆ1\ðs«!CÚh!Ï…^¾ç5uƒ¤j $7;_„8Ùã½ÿ9‹ôÓØ÷5ƒŒ[íÆ§\õÊÑS§×¬B £¡|þ^ÇÃÑÍuY^iûºg¡Ë›uÏXJ íÿ}×l¤yýJ‚ã¥Ötõˆ<1æt‘öœƒ•ÒupV<ÆÛœÙX`ýkmƒ®¿G-ö[~ôÉäõÙ£”o˜0ö Òˆk{¯¢é‚>ÉG®ê깈PA)ùúo_@ªUL6Ý»9VY©åUo™Zšj9vU ª†NF&}ðÞPô” 7»Ý<]5õÚ­‡æü÷,LÔûXô=žÏÝÙó‡òÔ€}“G…â0{†“0‹ÂðJ˜„±*PG·ïÒ‚PˆR%#‡³=¿1¶|±xß\j#iŒ0—æ‰`*´yÝþ|2È6)éÑ@BÛlèÌmÍ<÷üñìä¼]‚ÕP'*1àQ!”4Ä ê·ZüÌ¢¬Ù¹J»êÁù™QêQq% ¾èpmo×ñ}·ÈÅL„ÒQîø÷”Å㬗› ’,sîÀYA ´*ÃØ…7n•®K-HÒª÷\îoÅ€ö¿=VO”[½õôḺ腬ããàáÐú±fP«0 ^w”ÙsëƒïÛüý8«OOf> ÚôNÐ…!A=6Пœâ~–âCvF'·[b6é|.¤P(A Èu2MɆ‹:¸åÏ;{êUêexw«*á™Ãè/·§¬^*ÂÉ^¤bæBŽN+'T–M|å__…WL¿{íxpAXïš±a«†(¿3K<·Atx³µ½³P•µØ (¬´áWbŠ*ÃÖ…‡´‰V£IONëì²Qž$­U _-¾ÊïÆH¬¡•FTf O¬›™Ô>Lñl–õ®Èl6¹–dª…^">+\ìøïì·É „péÇht½ž u": !#NßqÚ·«G3Dþý“ÇŒ¥‡r÷‘v|ϸD÷ù„d³B ‚s6\\Ç4ÊpÅ¿A¡B\ ™ièKHsÓɶ…/nvF´üðþ‚cRí(üÒ™=eèT’¤1)cYÛ´ ˆ+=ÞF·çÍ×v»¡é㾚z:¡§{ÌÔ™!’On°¾dã*ü'T‰5ÆaåpP]Ì©«]É’TÉ%&gªf®qÚDíãÓçÁå]ôãÓ_ŠCÚïD^Qñkbªž•4ºœªW7CÒ“QˆWß&[;r) ¶Mº–‡ª³u³ Ý4[‰3-F#9×çÃîŒ\ÿ¯÷ßðFüÏwðØ õÃøW¿êïXABÀža²ä^€9Óñ Þ%.œ½›·A¯ÆãÔŸp ÷Ázä©RŽp(þÔý„z_O€ÊáŽÇc㕜ÄCó`E@ýÉáºWN°®z 6rÝÅ¿.Vm^ @Hå–ddrBŸM€òQêôsÑíA¤9€ˆÚ}ªáלQ“Ù•“ Ù˜²@j'ƒƒû¶M~Œ”fÛ'ïáAç°TQ0p„£ìE²¨âÙÈÓÛ9í;yùú§³ib°8ñ%@ñ#Qvcì:çGð¾¯ü±y+!Ö@Ò HÌPU)øð|% MBÃLÈKR´†Á „Ùäîêî+s¹5†ƒ¡º /ÁœA„ßÁ vöúMöB@ðÉæ¾\öç)ƒÛ¨^‡\šš‡ÕíÈ}NÃ'³„ÇÔA+›ÂŠéMŽ ¿æ!C^‰Ž/K^Ïèzk³DÔ°¦¥Rò<£éQ?KDc‹àF¾ªÅàC“`=\ð¨’/ÚÙãˆ+Upê¹X5€%:0;¸FB!°£ºS„AP (Pi` æ 2êTÛétEOßV½¼ËP’à2¿›ß_êíÜ*çດz4Ÿ«šá« ”Ro¹ðæ¡ÿN;ÀÕCŸ6”´pAßïË]µ=&¼àK¬'»HH2õw7ùBÞ‚½5m¨i›j€* n‡L?žò‰ú¿ªcÖ;Az+qñóyWÉ ƒ@?ªM;’ÎYxš33eÙµC DÖ†Y<|²¤É_ÏcK—«¤,D`˜‰2*Z©ÔætjSl¤ˆ3ÌSçpµþ¸mäßf…š´® ÷ùzñrêÜCJ„aqòô&ú[šdreÇd’!8‘Êl³ü>gÜšzßøw7T‡~ p,},Ì\0øXx,N/扆–F­ÙÕŸÃù¨ù.,}•-N…‚ÅWgRÓÔP’@MÚs–@Ô°Zªµ˜EÙrLö>0ì Û!²+¼=*I­ï£Ó±_jv@ãUsÇž‹´“}6Cå@˜ŸðXhGZv8Pñì~ž}¹lëZ4í¡ö¤$žd5Û†o´t *n¬‘ªÆIžeŒèg[Ƚ*fhÖ0¯ŽŸþÿåüiþ€?Ò7ú ÷øa°·Å¶ˆhD!Êü®¬@ÿzYIa‹¸þ&¾ðý¿ªŽv?ݹe)z¸ã&Æfü‘ÿÛ: „4õÈÿ$À¤ý;z4Ÿ?ä'–å Åó^ú ;EL —ÉÇ ‰ ìkw8øýÅ %! 2+  tÀD{À‘ðgA×ÉEòãM—•×­áÚ±‡MYΨª ¨ÙØ­® — *Š:½'©?¸oùœá!…=éÿ,„Öæ2Sïûèp}\i 4$?Ý÷TOaÉÔûïOó ëè!"Ïàºþʾ—˜2!¿j€Ù'¸0Ô4•Uy²{Ωþliô;‹¸#êX–Â×¶–bügoà4ÜÆ‚\Oœ5¨ôt…ÏŠQB’ ]7À§Ï_§ñ”ÃÏ#PÜqGõÝЗý™Êû-óŸÊ `ÛúËM€ïxûÄ·þ7zí‚kZ ñaþf¾’¼ùÈ:¯°å¼—+/ ÿõÊ1r(œŽ"{\W*WÞ··šÏ‰+±C÷Ç–©^ otå'Á¥ þQÿ€tJ'ì?p^¶H˜œ1LÄ:~ììù´KùÍ8A¶iÇG-òëè}3àúµ÷Ù;ó/ô®Ü˜¢eG‚½ª+BH,Áæ÷À7¯hUµ(‹,Ë@ª+O1ÅÝ]å}ð ”þ[Òœa/¯Ùâ8¦rÆÞž|‹‹…ˆ‚¾ú™þÚs°VÓV4„¬Q·Ò'ûbÄ@ÁîÀÁê‡÷èÀˆ"P›ëŽïÉðáóNVd âGKqÙüh–}îòL§ø%aþò7ùF–þÞŸÄ(åöqÍç-Nž2È—DžšBbîÚö:c¦J”ð¯ÊÀi¡鯗æ¼yG*‹ÐæBžïÑÌ0«Ûè@ñˆØTñ,Ê)Ë÷øu‘ϰvyíô8‘é —* =Öâ «?¬™Éüª쌄’ »2 0•€@îCÀùµ=Äm-ýZ½>¬“fî¾ûFèwð0uè5a˜òOoS3“oWM©Ÿ²\oAh WXåñ˜‰j×Á @à£v‘Ù?»5«ÛÝÚNõ‚¨((é<&!þV»d¹òQ¥*'Nzœ±~ôþКn É’9¼)4Þ‰ì=åñZ"Ë`tRzœôrxû8h”º’Ø ±¤^è_²1Cˆ"«N>B–„ý2l¬’´]DP.Èò¼Å†b©ß¼*DPƒ05T‚׋Ð(X&VÐ;ô"Yp´\&š9üü—`‚ÔJ€ª– k†ˆ©Ý4_ªºÁ¢p0xr¨ÛS#itâA4T¸hsjE‚¡+(:ÇÄ* €_DI{?KÉ< \þ\}xMÐ@Áˆ£ s<}CV¼j<À›3ç°⩨IÂß¼aë,9d@ù€•ÞåïîOí”iP?Ž)ñ·õ[S”{íjW·¤¥Õøcà €üÚu»™±nãx¬€gÀi$š»ª1F^·`à’ œ,5 zµû±¸_ïD«1ù\¯PÎŽ Ѥ𽓎ÞÑv¾©®ÁççÕùï5u PGÔ¨‚b¬@ö ×ÊÃ}¨{]ñù¦5 ê4Ÿx ‘´iö`‰€éçé%$”ß×ÔÉ´:ÏåèÍ(7×¶¼Œ'4XùÁG°H*¶±!ö¹XT¬%9°s­6³û¼Í¹ÂÓp åIóVõ/´awß.5LMÓ Æ·£‹¤‹† Hã¦N$Æuå¦!^Súê ;;M’ aèM{5,R0lLÞ‘;¿š/-ÿ*¦•‚“þ|p¹+ýðÆAr"—­=ñ飵ÿOû “‚Ïâèu Àlq87eI/¡ò„—ñOçõù ú½ÿ_Ñs¬¿§Ë€wyx¯ØÌ*hJ©ÎËÞï®Ëì•ɵJ†8Ž·Òî3é3ŸôY*|Ö¡¤Î\“‰=›æ Š¥ÞŠ…ÃŽÉw×U»®%×ú"ö¸„çüÅw¯TvU«x³Þ,xR? ùA_^ó,JÒˆ˜«Õø¶'ÚXRGÒgou÷týbì÷â{]k½eø™þ…Øsaæ}ºÎaü‹¦µÃ ¯ÉI]7,"ðD6ªí¤N*qV†°wÜ4|ß;éU¼Zäë„írÇòÃ³Ž‘ Î~O'w|!—\ôÐ6²»O q†­*$DÌ~+uU6›ß>)#7*¯m+²¾QLó¼.î ³W–°ŽFž—¶·¤EVRvE"{ù<·ÊókDhí&ÝVîžxÿœ¹«ÑÄFq0$~q?üÌ`]ÜÝ>{sùÍœSÜŸ˜¿ë³ˆe@Ø£Mª9£6ç‚n("@°íac¨ô3ÿPÛ±ÀfÓ U¸´¯c„ÕðÏ éTêzUš³ÆÇlñ—ÄÎJ8K=Ùoø s÷;£¯òòL£O‘[Ýs „ë5õ:cœ`¶-6Ä*JX$ô2"fÎçY ^®ÍYŸ5 7+é%Ôµh©F‹qÍÃ8Úâ;}Yª¸[Ì´¾ØO¡êº`º¦•Ž¿ltÒñó¤ƒ ŒÛ¥X=öT£W÷®¨Å®f™5Æ×ÔºìC×:i¸\?];¿éªnÝŽ¯ªtX§³ëwì>ºµ¶™šœcO¨téB71“]ðW®\á󪈛}ã_:£×—¸ÛEuàʹB¨‹ŸÅø9Æ6×ÔUvH-–G±5¥úíçÚÉ_i‡®nx[:»Ùtœ"̾.s¤¤' ÈúÌf%eµnÐŽ¸J¿e=MAkÒÖ±¡[9éuî|ù¦ÀU¸çu\›;ä$ð®Ù*ãÍc&ºƒ™©(fv˜-w—?¼‡ïs‡ŠçÑVRïªÍ<Ì*‘EyD«mÏ,¯f““S6àt¹*²©ACs,8KÑgL«–±—\r“ .¾ìXUæž ­1¯ ‘J3JŸÞç¦<ÐÕ«à­\²[}:§\¤ Ç™µ»T!H4Y•>¾íKhÕ Õ–üÿÉ=‹s¥gßôß§bùÐà¡[û-ÿ]`' W ÿˆõiuØD³•Z#hÙ­ÃâÖž…s")‡ ›ØøX5zºx/'nßVi²SÜ©Py·Uoé8kœœ² Oú¸:²¬ÄòÆ7DU5]ÓÖ/›KÔ-Sª‹Ê*Ƨ¹i³/óp¤mk¶|+Uó?‹Ý{ª,ã|Äíl@DDwo¿]2­<¤Gÿ@º!§öú>w,ÿ¢m)gé9ÝÌË¡tz–jîø÷ù:¾?g×—Ÿœu_¨Ÿ+´nçÍ*sÔʦ§½Íȼ@<0›w¾ÊGŒ<¬®©moµÎ„Ÿ_sî²þÞ…˜Æ& ´Ë•n0{´× |Þ¥ldÍmª¾v`èbËEÅÌ历„Cæi>ãüf§OÞ O¹ £¿¢ô`STŸû~}YŠ˜ÿÅ\Ñ'jó¯Xë~È‹ïºBUÎÁ"ûœv•ò™Ûô}öì5\0’Nñ¾vÔ"Yxšt„ùƒ£Ðµq’ߎöÆt«ûðÙ[˜Ð0í«@ˆ~ªëÏ{/ºÉðgõ-]ë\E¼UÙªhâ²Èûÿ y£~Î{²?fõCò.¢'{[¾2©œéœ¿%±êà¸ï—n¨È1•zœí§¶ÈtzO 6õáJJÄÏ¡Ìþ®Ì;]týT‹Ï¢M‹ºãÏ¡)Usª<Ï¸Š¦û 9ûñ³¥1â9Àª€ÞEd@çg¹¡^G¹¹å ö³wA£xIENekeÖq*‰\çyµ–XÊÖ³ìÆ\gwÜwv6ZkLXd4Z¼ëLÌð³Æ¦tˆyÓUŠÆ—~s ¯yˆˆ‡I$·ríbL˜€§Ûñ‘ñš‹D¼­Ä×¢u™wwwwK,Ûl;cw’RYO“sµXÈùÄÔ *fa†•30Ưhaà01£NZ¬–j4ÅDAR`†…hã£Uv*ªËÈ‚¬?oÕúÿ˜­I‡Jý.¤ùÿTõÿWí’{¥Øžï"‡„pñçîýŸDP‚>÷Í4¢‘ñÒ7áùw8LCûh÷uW‘ŸÚÃàê“?—ýÞÑèÌ{e @;ƒ€ŸˆÎÏO‡ü~.Àì$&–‡önr}·iP*!x–®ýÎ?ÔcÏüßÕ½ÕæëÙõQÁà1 ÎA$P"2IKhvc¦ Çúô_/¾VûÙЩu BºA,YrJ¹¡ºçzwmÌ×NÐkA‰¥èø-IKaìž3ºãCb~ýžŸwæ2¥b ÉWÿ¶œõ¢u\ÍÈ_ÀáË®”×fAÕò÷›F7A"tÅurdÞØ§üO?õpå•‹ÏžêÐu2Mé4ª7£ÖN>”;àGãmŸ4‡óüŸK»D%àzýžþßCþÿ~@Ý"‰Aê žPSDˆR©(4¢©HÀ{oÁ»:Ö~ÔO§êWLÊä þg»w(ñ‡6P'ùcyüÜõ”ö‰óÿäš4ò#üå*@ÿÌ$ÿVßÃA„ï}óŽßôá°¿Ù ÷Ê,ðÓ`ò0ÛÈò‰ Ì! 0ÆËyócÝNØßRú]ÿ÷ÙÃÐO¸gœ„*˜üѸ›(d„ëië|ÌÎi½/ `¯÷ç&4t.î¿õÿ¯ÿ:۪¥Šþ05ÿÁÇD‹¥ ²>*W— JŠpÊ  eˆtžr°"èsÿ|5K­Yd‹þüG+þ¤ZnBÖ]›”¼£õ«Ýž°wŪR›aŠ‚„‡=ó2“}D9¡¿¸c<»²´Ÿü8pÊM?þjZjëÛƒ_ôÿýuêÛ[%" ¡ªLÝC¢F~ú¸ÍJý§aEºöT­õ†Û’ßz²'ì'QöOÂøA¤ÃÞØNzÉÒóŽ-Ÿþ5Å(êJo‰P%¤S3vž:È«ÔßtcÑ­ÂÆ_—47æã–gÃïCwÖ•dw·~.1;KÉPßO6­Ÿ.æa—IœMbg\&¤™J”‘å}|M}¬£=}œú¸íª“–üqŒq¢Ù}¥—®{ªÂ ¢ª ¨¨.‹“½ÁŠE”É£WpjÍêP”¸ayøÍb–a¡13¿Þñ ÐÕAAüœèÙÓJñCB&õ@j‡*øy0ïú¿gü¿æ¿ÊøúN¡þní¸}1°?þ;(Y ¥õ]­³ò&¶V?ßÂÏò]±¨ßs¸äÎhaÐýœ92ƒMrJŠuÿMG)ý‰LàÅÒª9 ¸—Õ¢¦%© ÿVà”̇''g†2‚ nêÝ!T¾a9Rd%憮ƒÕÔÏAýßýˆAãþµùâ`þ­?AN óÄžƒûIç7çœø%Cö¸ Î“ÎÏËöî â9â/@á§ûÑŠté†ô5GY ‹2‰Æƒ¼írw¿'–¬¼pò”oÖbY‚|â—Où¼«)F<à~_Ø‘ºòœ§@©º=­ŠÀ¹È®¾MZÑ6 òD@;c¦°²©P/w £R³Znoíº#º{ÃuDH»J¿Ÿ÷ “ËÕµau›³´g“ÍÈÆC®O7ª¡.ñüWâÃû„D§oô¨Ìäê:¼‘q…OÍM“¨›Å“þß@8è<0_¯üUã¯áµÛ#ãûóø~Çpà““'Ù Øb[RÌT.ê?=‡ý /óþÏ×üXý¸¿Û¬€p‚æãÝcFÃË*p!€Þh[# ÿ…0ÏEêžm¶´Ø)Æ îÒÉwS“=·yYê’p âÉõ+«75»¨õè9~ŒLÛÿ Oý¡ô7œ%é'þùOt1ûpöY¤ìVw.Ë“0ÌMb Täž®³÷v¢ïâ´!Ä&Ø®4¨ª\(÷™‚< ÷äm<ýªó/b;@îìÁ0yqy“Ì)zñ]Ñ^? üc™š—oYàt~ÿYtÝÖ•A•·¦æIËœY|'%$Ð8ž…Þ»@Ð/g’ØšþšN¡rÒÿ “R ®ë†l ô´•Ì™ûu3§³8`2z=ÈPö!J'¹=}UÿŽ0žÙ³Ž¶Cç0>—êòŠo ÖØÍÁ ºëc©‡ú¤ÝáU+Þ/”–khÛü%ç ï"Ÿ7nŸ—–$áà ¢ ªTˆ)H!fœáöqÙ2_ÿ©Ór‚a¼G¤û¥ó¿9î!3—Üϰ©=zie{z¸Þpa» ×«~çɪ&Xû‘¡¨b ( ‚„¡(’(¦D6Ë*ª# EQóPR¾I¬âÂÑÁ‰R”4û®¤PHCIÖiwçÉvhÕÌDÓ ÔGÿ.,dªd%BòØ ¢”R¢#Llo~y@øÁDT¾ÙuÄÉÁ4™¾<áäëÃŒùØá 4&>,*\1W054ÅäQÕ§Ó‡…aÔŒcUW™A¬`¡£&Î$Â)¡T¹ž§7·ËSæ!42š&Ùê¼1ȤÏ!]*ä L.^´Jx€RARÑi9ý°~^=n¼=[Xx²,šÔëÀîjºöŒF‘вdƒœš) ’gøÿ!\nŽ ô›!ýºäéþ£ûê JIºSãð$†MTÃàáøóΦ÷‘=uØñ=pTyµö>šè´MÈØMÊ Ù¸`% |;Bf M¡uø™¶¬~Ž´Ç¾ÜÒæoÂlg%8(ß…`W=õ. Òk½â³ô¼ˆ° S¹Ùa¾ 2ðÞ0e¦ÆqGŒjòbî$Õ‘ÞI'Nÿïqꦚh_ênØ_6fBýÂy>Ld[T•JžÃ »»ç\°fçêo0€€-Ù¡X™½¬\‹7?–ÖNâž”ñè Ú) iHöQ„²Sä©Þ¾~I h›Ž}SçËtæ…è…ᢖ‰”aþÐÏY¸ÁQ9ôü7K QMTòwG™·÷8㎋!"ÈŠ}í÷ã™ëèwO¸{”=:}úµQ—£ ©p놣¤\6[:y?즽pi}`Ù…®*oe3ªgfÌ-—oXçiÂàÆ ñ½tÿ‚ÛðvJ¦†R“Wª¨ZÈ7{ç±  &QÀááï>.@™,aÎî˜wNí$zmÏ'…äQ–ð× ÑhÁ¶)%iÒ¤¸¬TY¾/õÕ_ø‘×U­¨Qºs÷E}&N;*–§tòLøw´Ø^ì3xCÈ{q |׈þrìÃæýŸIù»zv­&îA4g‹þ¿B¿±SZ2ƒø}/`u0öQ·™œ“b’•ú–U4Oœ!èg)ÿ¦³Ìpåû±ÿ—뀮HS–|›xDÈ°Ž‚š€/ÞK¢iC»€äÿ”GzDD™U µ.«I}ñhÇ‹v0x5‰íÓ`È Z;ä5&ÈS¥W•èÁ°õSQ¨x@(cXTõ»ÔØ€ð—–!GÖ aM:ÜðšhêÚ5çÔàx9„=JÃ/š@¼åÿŽožÔ[Z®‹eØWÊ-£Ä{gßýÄé}I}|{ýlž F2fŒ4Z®qu‚§V þôÃ;Ôf½Å”ÜÍk’¨`:‰YH,sP›à¢ñÝóà°·æe ©˜Œ¤Ú$©0”6,hGB|LY8¹`ÍÉe»FfÌ??„3 þg}èê¿NZ”Šk–|Ϊˆ¸œ1Œ¿øUžYõuZGÖ°z#õùcü#N»¸8 ›ª`¿Z)ÿ¸2z£!‰0U¯ÎÁ"K0Òö…úÊ(’½ëËUŒ:A‰-“”º~ æQT(Ó¹ÃïãñçxÁ"=Bµ¼2DÕGð¸àŸ¯ïZ[LauþŸ&/ÍÏüp©™¨q(25­¶IÙ*Ë[ä÷,!‹T:¶9ÅÂê2}[‡ñœõ•›ý8³ú´ >‡ÞνÜGV`–f>ÓŽìÉ`Û™?)à…ã–ÿžygͤÐuJ%°Kª¡hOÉôËw9VŠ)àr˜’~ÔùÏ®‰šš¢ ²ÑkÚàŽ#êq2 GH’˜?×óy¢"}Ÿ’¦ñ¯­ˆ£sr™K2ÛøÍÙû|ë:‡=Þ˜<h0òKðËAêÓ½o âš¼¾Z ƱoKŽÝÍz+ÐCtzÉMî`RbF`Ã.l$ÞüwøœÏîz»Ô¤ SX¤“¨ÜáÆµ¶ÄÁS­ Ž4ðÙº»§9œMK˜Ú@‘q ÊÙ•ˆDÌ R[hp´‹©q†E‚H‘•ËÁ„ØM# ü‘ïžï÷uô =gä~pe›= ³ò; X;¯K£pCj…åx@CV•ˆáa-¦²÷,UàoªÃç¿æšù!Yp0 LŠ·uý•¾m23D"§|yôúhöTEdÈ—Ëçíó·ùGÈ<ì= ¡Ý„èz@è°& á;0i1èÐ}á‡4y#ò}QA¸ãYÇ_#f²¶ßLa‹+¬e2Úegyœ™ëë”3û_ÿ_ík|ïóÿñ,^ŽÖv–W;î™ÍÊûëƒjqûvl!&ü&hÔÅèYµðë·pMü÷²%áBþ¡¡o†]xŽ³ÚŒÇ©¶$^S’²ðH«Å~«Ô<=2%þ"€w=)j$n„Æ\¾Àñ&·è=ÛuŸô@Õ³Ÿ“xË=3«ÊéØèŠ*Û¦´u vBAv°‹H(‰@p¶€@%foD ¥BoF`Úõˆ¸z8i½È»Ê6W Æ SCk×DpÐ.Ay =¯ó7£ÂÆ»SÔk×ê à4íAðgù·? ü Ù &x Ÿ`ß,Õ|p gÒɵPŒº‰N‡ÍQ%éÎÿñ¦ù|ñ¦<¥ènQÇ‹Hø…â †ä@D…þKS Ãàc†´ŽxÒ03[£‘fzHPl:ȳˆX×’nd¶pä~ÉóŽ¼Ì¤yÃQì-ö쎅)ìÙ¿ÉËd#}ó çǘX™Èác’ýo[w¡ µ@OVýYãÜÛav_ :'£²¦%ºk:=×b’Ãrd8^ü;ó2ß]:2†ðËñAù¬©G]ËüOo€Œ¸;Ñeï¿Ù²Èyæfæj‡Q íöÃõu<„©Š$ç™+5û´m³Ÿft ™Ñ!M!xžñ(ϳ{dÃö[ž$Ü2tÞ• {¸gûmÎȆцù=Sáñ,$~è4æF@ Ø›ÛöÌÞÿ€ªì¢Ù]`7·­{9£Íöº·»9Ëœb¬˜Å¦ûoÃäú`2ÐÀ]Që'IœÿÑîšN¿+¹uAþˆH©óÇÏm Ê1>RÃŒÐá¾)ä&‚€¥‚–’"‚™(dŠ g!CH„ %Ä9*†@?gôáÍüÌ¢Iô³¹ØùÕ=<xz{R)wØ‚õbðêÄ>TB­Êë?Iún <ãZð€úÿ–·µ‘µ«rM~D ¶_±FIÿr‡=S‚ýmÁ]ЩÞôîLC “6$}ˆK*Z(ÏÄW쪂Ȉ:«8V÷…H?çAv+u”ª ʲv©8­åœR¦¹(äšEܾáh6PÂ$IAXBcïÒvÔÑÔÇÛøÛsÀæÉÈÖ¹ÁŠ.’ßì¿P:)ÖE¼zWÁ;5}ÿÙªøMËÛŸn*Š¡¿àþ·êr³f÷Tiƒ—æ[µ8o@ &àG¼"Úži³Ä ëÉÖûvÚ‰Ë!\+zCÐù89ÈÿˆNPV}ª@bâj! (<\Ç—»û¡õ^¯(ÒìÄ’ˆºP³¹SY Ÿ@êpМ°ñ Õ{TF‚žE8³\qÑéÌ;ÛCaÉ2ÈO}Ø|<í@H•QÐ>õ%ÖPfÊà¥*}»k„—S¢:¾Øô¼vj×Ì^ûû?ÿ‡ŸË(ë¨E,NÊgjÒ®Ð=déý–BáÒš)¤#'ªè…¨ˆ"Sø &ÀpÌ-!ù{.ϧy”$ǧßë¿›®Ñcè…$ žõÃò$½™ÊìfDý>s‡ÍŠöiaÓËêB|µA꺔 j{ô~œµ„Ë$ñá›î#8§áƯ]Í‚ AQÚ¿ÿ9 «ñü«§·ñQcÀ(á䱇¨…húððLþ’3sÞ ±„éÇM?(ÕÖÖYëÕîzû«A´ „rg®‘‡ãñïL›õþÆùùx~<ÏÑŽ{e!'uÊÐd¤~if¿ŽÔ¼}œ8Ÿ7CÁ DMN•ÁÈ4´aÌhöÚâ‡ãƒ³_™MÎOì9œ5èü—\ctÝK4‰ôõt äÌ_Ûñ ÃŸÛýODwZÄ©Ë∂Þh²0€ÌuŽ _€¢Äw³W5Ñ4°f?Kêë ’xY',W4Å {¯_5*´Ò•bÌÿAȾ9®>^r†ËŠnÒiµwã[ùv!äœñÈV(ãqHqÅ8*£é·¦5Ò¡«Fb5ôwâÐ9a ­¤P8"B†ž¦ìnΦPøŒ†Â@4IÈX#A-#¡Ü{Bê"žJ»¶…DØ„ *<Ò’R^ÜtùØgó!JEyþ}èàÍM-«—€tÃWÃç ܶK]µ2æ„gSó¹?¥Q2z5u~-ÿ€„p»Ÿ0©$¢1<÷DqpPÚ#(¨QtU‡^οÓý?‡†°Ë_f¾ÿw¯4{8³‚[$È Âa…²Òîí!M$)¦ÕR…BÙ XOûPävsßÀŸ°%âQ…ÎìˆÁÐ{½pq7ŠjI€5ñ /%ÅI+OXŠwßí}¶CUB²żÁÀ¡Zæ` 1U¡€ˆµÂÃíë©~ªá£åLý$Ìåzðâ}ùë=qeüMóG3¨+6<NAHsOs…$È¥þ!YÏx7€Ž93¹a‚8±ðFÿººÜµ¬’ý2w(¾@ d¿´iØ%„B&q¿xT È¬ Á0véZDÆD –nŽû¤®¸EEÛÆÚ\E¯IL?íŠ×À­Aj“%©‰ƒ6½jØÁ§iÁ9)1ߤJ̽HM›ã¿¬Îø¼è¥ä ;&HXb‚dƹDT(MUÈý¬*÷ïŒÃÎûãCG…SJš,9©å îé?Ö¾ûx‰{ÈDq¼?–ÕÕO£ÚñTú¡Uü˶2t ?%öË@° ƒD Ï¥ºcX¨l†‚#1Xð¾_¶>ÁKýN‰(j‘?"šÜ/šèÍ Ÿ¦1å ª‚xWXÊx/Æ›÷ã-óšhõ°Ñžr€lŠÔ¡Ågý–<|ºNø&OKŸÈC´zB ÔœAüÇg=/¼]4?³ºÝÃhû:ÿí×@H€:Y‰ ?xïü“ó#  QJ;t;º|= H¿º> ×ôàѨ€Sîé‚"#Õõ¸‘Y$<—;d % š&f•Ö Š!¡Fââ…U(}¬¿G”?a_E—©øï4¢$ñ äÌÿ‡ ÷ã¸çŠÍ 1:ýùž³-ÐÕÙafµòxu„O˜ÅIÓé;|1´íã}]Xª0¡*Z+ùÇïûÁDG&•Yü–uØ¿¤ rk'!Æ$~‘ºŠ *±l¤- ü(•¹I (Y*ûŒL/„Fbëãw scuž%Ù¤N{˜‚| xÌ](°ÂDþN¬:¶ÅrÈ|v ŒxiŸà>ò"@M±a ‚‚ô•u‡tµçs¼4¾rEù´?¯å/ù¾‹ä†GùÞ,÷´íŸo’ŒQØh ‚›Õ¿"»°”nÅ€ò‚ýöv_9FŸ¿{¥þ(Âúì<¨Ô àè®NDÂ×&΃ïÍAMy¼Î7ÇÕr@áÆë…ö®µ t21η3å7(œïŸÛ[˜£?:Ž8WÐçÙšû0N°_æ,¡”É“väÀäN×nRöùº}Ãæ*dCñ=¡-q_ mx^´ækàeĘͲ]|œ…$9ÜšhþS³”Û—ƒ¹Lܨ“òÊUœ8²u5û¸ÏØ…€2‰t R¯ÉñÁù§£Âþ¸ŸIåÀz\%ƒ‚MÎCroðð%ƒD¬H7*NÉ9;<*:ã=´^O²÷Þ€ó°ƒ´æ{ä»ô¼ì0=»ß]”7“ÇXÑà/åwpK$'­qÒ`Ó´ëØfPº* BuA ; ÞÉñ£HsÚò˜Qª¤¦$.e âÂd?ÙÖƒY°™ŽÍÝA¬Ä5ø‹¦kBÀ@ûÈI;ÄÁÈÜ£;tǤ¤”%k âY·OG¼v fä¯Új PA® «ÜЍ Š¡F”—o¦=>¯‹êâJÓíøŒéî:ZaåsÛIUUTܧ¦óT¡Ö?š ZNê%) Hƒ'Ž3ËÍø8gŧN]WõboïA˜ÙZ{4^X½…²¨,&EA²}rÀ2‹J?±œ9êÓ—æc:çÝàÃO·†¨Þ—ô÷£®ŸhÉr"¤ªQØg³ŽçÈ©ÇiØ?¾ÆB ­,ÒˆŒ³Üàà „‚ÛGœcp8(¯•\÷(A1)#½ªÁ¡£*ñ|Æ!Bªy¤lJRhá(`1D±6—oªUjØ=Ät kÙ!mšRèÌt]„á.4jhÆ"j³Ø.Þ•æ?~cß!Éí€ö*Oš‰°Pq 6Õ1h–e}â±Òá#­T8< Î^å`©ºT|ä²j”S§ ro”¤Dª€yÃÔº™¬ø ·qç0û~Ìýû°ª ú'hx„OËdRÄjÖ±X_ªÒß߈d%8Q™J¦1k1iq4D "Le’‘„ɳ*§aôz<‡ÐäcøtÇmµ~Ã;-Ùá[ÛðÑ) IU2S¦ò`fó?Ó;t×nU¸PZrŒ-ÍJHÁb&_™&¸Ï=L‡¶e ›²µª´zÕ‘Êþó}U‘«C•P^G€"ÓhrI+"ïç¡ÚýG=ÑkÐøÐ߯;RnDWÕÔá_zÕ;ËÙòÜû‡õô“dÏòv’Óî<þÿÜ?"…ç©ysd`³PÍÈ´r‚žµ –씜4Eƒ¹U‰¾zIU`ÌÆËMdÝ]uíôÒš!ÔîŒÂ™ÇÓJéRÌÀY'}Q)ùù\§äÆŒØý‚BÒ<¼ãTРtEúš]D*¡ê íZ\±‹kϳÐèúj‹(‚1…OÓÓ?«i½íò¸võ4aT©-Uú@à]𵆹¥›™ÐÒ-†ª£ÇÏb8Ê·ä¸bÓÒèƒø$›Âï5dàw™# B•Ö¢÷ô;4¾ûC“ç¬ ¬eÃ-oJ8ú«ÙuzG•à“bŠ$åá×òß–ÃêV(pYï5tu°¦4—¼€b¼¼áÅN4AR,Ši€°×OT<þÓ\;w÷öæåÏéÄÙ)%õÁÜRÈ !&*+1ƒM’aŸ‡#¿læ:œ^<|iKm8æ²] €ãh» ë«%”ÞÕÁ«,&ª¤j¦”w<ÄhÈ3ç/ÉPØ:08ØR›æ®Œq§ófoˆ@P¢ –ª˜‡Á ¤º‰‹bè;ÅÊÙ­9V½åÛÞ<…þÀEó˜)Ö-æëåïôÔœè… ‹¬8…¤šò PÌ…¶P Wä?¤ˆsP‚‰¿¦ŸÀb+®É›«pmâ-yKžº°nå]¥ø4&”Õ5ÁÐÂ?G?=¹+ò®˜VïÀZ_cMÍ2®Ë uÊ]N&æç¡g<ôsá~Šä'ØZ¾É0l.zV„DŠ=ˆšº§ ª€V¬yX~pN$oB@ðV}Ù8_6}nv—‹N=­±µØýtxs€&Õµ¬|+ö‡¸;|³<÷× X±W˜¤pTâ<ª­¹‚¹ÂºÙ¿Eù6ÖÏ‘ž[§\ÊGï„Èrk÷\Ó8‹ÎÝÛ·^}§¼ww™rÑð|åV ôÌ–|?W 73ά°c«’‘CâØ½ÿGNÏWÉYñ?wŒôO“ÃÊõâŠ!>gÍ3¥Y A—u` ÝÃZI—?—Î>ŽÇiÿå¸ÙÕµ&ºÀ]UOº?8Jž›éÈ#ÏhŠ ^òPñÏc‚zÈáéÛ¼kyëNk» ó–Ñb0d’^L¼vDZ¦±Œ`]¦C'¼Eváÿ`òŽ|± †8ç˜mý[Uë“4‡—›ã¡ü½KP‚÷¸1 8Ca‘0˜ˆù‘/'’í»ñ9ì[1 QPã GL$ÙÖ‹aTˆ)3Pˆ¡Iަ¿èáeÕRã´Äº¾‚ÃŽ‚®ED)[çAHŠƒ1_Ž/ˆ,:o‚ 6Š.ë¦hPsç"[ÔBÉ=ÒlØh.Ôû£WDCÀ“E¤iUWÔ<²«@݉+_g³·×Éá¸DY48ß3àjùC-cžAÍûÈnƒ…pHÄ‹ ú—O8à¨ä%U·`ª1Ï 0‡xéI6Ž.KQ9»f¹ÉCe X³•U 6OÖÆÓ[½ŽÇÚ~K[ßü.Û×ÓËæ^w©’#w7èb7ÛwWFû¬­#"ë ˆêä²ÛŒžy üðú¶%â÷Uèýwî/›_ãó¼êÛMK~eB™®R`»÷/êÿO`ø!!!&cáíxE•©ðž•“vìÆ[ÁòP­žÇÄÃ1¸ÑœgèÚᦸÔ{çà³ÖN¶fc‡‘|º«Õó;7ØSŽ8Q[ü1Kà|:wdÚ®]#’DD”R¨AÝeÕÔÁÃõª©ÖÛž•åD“,€1ãÍ /€[f\©m|™¤ÌRç©Ų́HLìX &ºÍ€†Ë=ªçAFÒ-žØWZÐFGQ¹-Þ¥L™„ éUµi0Öüª¯ü,¯cÈ$?$¶°ºmåÎ/×_ÝóÅvê.±ÛXƒGCq$¦ž.ëä|Ñó—0Ù.Öº5ò;ØgÍõ/Ï<,_¥².zlÙ¦:ó]Oqñþþºï;[AsU黄Á6¡^g¨. F æ ËPåzªŽ ü—$Ô4]1Œ^¼ˆ€î((‰ý0Ùà¯ö0‡’2ôa!V¯‹|ð{T`‚¦pp‹£gêgö}Åß²¿ì£:¤t>„D…ùå•±í´›çK4ªŽJ»çL|mî«lÎ&‡ÜnÊD¼gý’Üú4ˆ;úˆû+A+´l“ÆGáù‡jtbpxoqÕA}q‰×7°zG0ôTç™èÑ ˆbú;bW@Åø½­ ¤–?Ʀ|„788‰”{Èu®lv„?í§º «Rÿ ¿†Žn!BG>2~ˆï”‰±ðFÛˆã®ýz¯Èq#îÕ¶Á7Ïý.øG{8ï8dtŸÓÒòcAùqË3›»À¹RJfϺž ‚…$ˆQ(H)Eh¤@‰@hAhE„BãFœýÑùœ·ÇÊj‡Ýå_—ó~Epo{A AxAŠ!BJ!«´ÿ {Jÿã½®øG¯-[Bz(ëŠüHaž~oüñ êËïDÑûúy¢š1ó@€J%><݃5š¢ L$™AOò^¯ü^_c8ŸçÇ»—œ¼Ö]»¿Ÿá÷ýw³¿³ª¸ªÄŠª÷ö€n语»€Ø©s-¢¬Šªþ5ª«¦[EUb"¿úæ5›˜¥Ëhõ“L¢´ÆØ¾ÿŸwUëñîë"ú´•U|fT•¹m?ØýÞaÎqU|ùÝÞf•?еõœ]󡻪ªªª³š®doì-æåµXŒ_â)jª±zÂ5UÄgÐöÞ„çAmýÕUWí¶ªÎ ¢É#s jªªÓ%¢ªöSÏ39NE¸[UUÿÉ-Wp¶Šú„þ?¸?‹÷¼žPÞ>vuT)‰M*¸*ŒE¯Ú…k3Ñ3Ô³)n¾ìÃÏ9:$UU‘~amîÛªÈ¬Šªªü°Ëm Ê«(,¬HªS+$ª«"ª½ü¿ŒyÎ*ª½ÖEUUUWBÛL¶ªªª«pÁò8ó 2qUY£k"ª¯ÒÛݵUz1·£Üý{Î+ÒRQU|ù6ÍUUUUUUUæhIYÚÛËjªªõÇuU|~³ww-¾ýnê²øÛ¶Ûª¯áûû»êfRÕUUUUUU{÷37øsÔ¶«¶ÕkeUUUUUï? Ýö¶õmUö[zsÔ ÒI%UUXÈDüü Þíªª­ùÂnêªü­ª«àÊÏìMªª¨ª½ÛU§¯XsgVER…eU‰‡®îªªªª¬iùÛª«ËjªÛjªü­ªÛjªª¯ÒÚªª«LÊÕUUUUô̬ªª”+*¬HŠ«ªª´ hÉ"ªª±‰p¬ª«"¨ª¬ú6ª¯‹jª«À-£$Šªª«"ªª¬ñZªªÇ¨ÕUWÿžeµUUUUc [}?Gƒ g8ªªúeyKbDUU}ÏŸ·Çñ÷ßjªª±"¯€ÌÂÛ ôõæñ_R²ÈŠª¯Äìàç<[YUUŒ„M2Ù*¬ŸIjª«ímU^eeU>c|žíçêþÏ<\*Üi(ȱü„j»–Ñ‘ ÅUUUý¯ŸÓ÷zë¥UUWç0·Í¶…µcñÛU‰¶«äËhÉ"«ŸU¶òdÝß6ïížÇ©þϜλô’*ªÄŠªªª¾ÖÕUWéîMÝõ¶ªªªûÛw>“œçL3 ÕUUUUWÆ_‡GÆõÒªª¯®•ñmYDU}-ª«Ì¶ýoÓ¿Póöótêȇƒ~_BóÏ·œÝÕU÷õëœâ¾{ºMWÿ1ž|·ˆ@n¿ozãÈ6P&Wéµ;œð>Î_y±œ”\$Œ¡’…"Ä€R(URÐB«ÒBЇ?P{<‚‡Qr{E}·É»¼ì÷ªAþ,ƒç)íVr9÷*ªˆoaž0]z(o…×Àͽñ÷½œÖljìžo©/þå¨vÇŒ;93Ú\ê>9çSyé÷h§Dl]P£ƒ;ÄF`Þ§\ÌKô¦1µ»íM½á?sm½Ì.ߌbŸuÇ5Äozéo§ò®"ác{ï|ݧ¼ muôÄÚj~pø¨˜.¼þ‹Ž÷Ž#®(~Ñåf_[QªxuŒ¼L¥3ÅwÄɺ'œê¼VeS­ú9MU?Xñ“6úõs}úì¤%,- ’£¾?¯ÒõŒÎ$‘=9réÔ‡T1ýÊ ÖT½®2e¹R3™ƒ88§üwž ¦…$š¤øì‡8AðLÓ—Àï¤t‰ª…ÙùAIÝ8Ü/(÷ÆyûÇoekÐð|äÊÔõŒ|w“;r¹í»¥ÃœÁÏkîouóïœâ±%¿¼rJ!b6ÓñùÏndîbX>,뢰­‹`/¬)ÅÖØ—Õˆ.U&×=Ž{ó¹œoŒtûDkÄW$µ{wï뤒¯E½5õÞvœ½àïÚûê’X};Ã&†Ì#3;}žtv‡“’%w Ø…Sx']5Ä(¢ÙÈ.Öú‘Éé±Î8zfDÒg< }ªì¼§™I&n§Íkéˆ÷ÃÉ^ü† ®ž!$Ÿ93#xr^â}ÞÑÄ»jsÇÎ0Úƒ")ëÅELû¾}õ‘x… SÁmpÇtÚ<™Q 1ZU¤Ç˜ñŽeeÑ ¿Hó׃žxêüg¨×U>2*¼á¥O| ¥F—dâ1LÝ+K¨1ÛÃ̓˵–?"Ó¶ºvݫﻫôF;c•Æú­ž•<íwí°BRðËÏIcƒ§NñÛŽk—7‰Aé©É(”’Å£¦IòÚÇ™œ®ÙçŒfþΰ¢Ý·ÔnNDè[˜HP«¶Órš•S`u¬ÚXë&Z!üSÑÊê~s×X¿ ȆvnŽŸF70MTòk-­æ³3Jßæ§ü<ËÛ>»vYt¡ck±ð·I9IÖë:Ô¬* ,FCïµ]c[X“œôv˜“©…­µIMÜ*à;Ó+®…FãUeAÑ¥•äÆÔT1eqI»ût¶ï÷¬½æ—92KɦI:+3^ÑX5}ã¶¿=äÖºÆåu5nù| y/5Dy¢Öš»4Y-¬Tvzîøˆrp«NÝÞ0ì¶ÔFV»="Ž\á­[Ú:·-xâ¸cc—…£/ T%3¨¢­ºÂW˜åF-âÇ3U/lÙÁÝ5{<‘rÒ/AÛ :w\ÇÁfâö.8a àºÍ¯Êó4ëïEIÕ!ñÇbsþ^™ …~_òGLcž¤„‚xyX|â8ÅͿɔîÏ)3þDéŒð¸Ñ=I¨÷†¾¢$Ò|"”ÖMž¾×öåîŒëÞƒ­»Câ!1Âoñ¹l,E—<Ûé<;yY»=e±ÚT)õ—›L{k·çЇuåàßIº®ð+w„Ó‰¼háj<¡þnÑëðå¨çìC÷Èy Nšòèo3¹í‡Ž ë’„€ °U@-) Á-Á†‚Õkbú¹iÍ (·æv€IÕÃXt; èÜçÓħ*lÓ àìòÌÂlUÈ×±¦éóíÓݳkÅ×ÏÕüBþeD&”B<¤ drb¡4¼Ep>9ˆrÿiT䌩®¡‰%ô$hãvá|n«}3¼’*FÁéxkˆâ_¨HgèpëÏ~žƒÂ‚×ÝxÍìQÙ(eN`’²ÕØøØ*ömZꪭÏîdÀ^X 6õ£«OÈ"pù¾ß: 'ä´_óDÚ?ÒãeJ›Eõ¯ÑY£“?N$)A<_eÜú „¤ß•¼aîF`<,®NãÁ@êÜ7° @Õú& Éw­S4"æ¢ ²+:bÊéWgyFsz&Œû$Œ!¨+¬(ç_x´_Rzÿ{'ˆ¾²ŠQmîôîþ7“)#ѽa‚6c×"fõÀ¶^ô=×ê)çŠfø¶*Ùé.`«¤ÚÐ&õάc:Mê°5‚j˜-HÙ ÚRÛ÷ÀwFÙ˜„=ÇôÓ©„pƒËc ¸¨%åY7w/ ˆ ­ ÚÈL›S ôÇgƒ˜y}kNšôã’›Nîç;m{·?Œj©$¢¨D‹œ$ËK wQ¯º¾3\*“¡í÷°NMÌ“GhsÞê<í[ó"S™ªÇ¾:ÚúÚU €ès¡TåS«J–/"gu>kBÙý “L&°Q¾ë Ó¶§²Âåfˆ˜h2ûܬ…ž².K`·ünÍò¹BLÊov¶ê¶³g*ÌHÙM%³·ìs¡Îr:~0AJáß{úvXÎÁG>Nh ¢ENInKzßBàTiƒ3•’Žz•w3‚u¨€Ÿ"‹Èðô.pg×ùe>yïüïé}<ûL(»¬rC.Ù,Ý«Ùûµp—ƒgÿ×ñQÂÏê¶à:b¡m)™ ¼€6ÃôÂú JÚ~xGÒG)Œ!ÞÍþ¯9Ãß™>?›éÎ^Vöá¨6—( ч֚óãËÙš²,ÇÍæ«9rùAðO"­!ÚA@\öyG}7åЃâ[G}?—¢ l(;w¨"*iË!ú´V$xàdÇ@ï:J雳ބø½Là“®¼Ðòþåå¯`ùëϲ+^:@ÅÐI9¤ O}I¨ìÅ{u1ìÁg"sþž9Eøf¸_’åwf>ÉóȽ|±yIú&„Ši&šX=ìK“J,DM ÇíY1òU<çwqêk®•òã–Æ‰•4•×[²} ômRpë£aE>ŽÌ`†c/@ôÔ¼`%Ü÷»Ëø³mr†eŸ.0w°ÇN†ž¬Yt`ü̓è¼|,W“ÃYš`5 E(E2,%ÕCÉEÙùÃøœóáe?…*OW죯=yN÷],æõn9»Eêˆÿ•IK¤¿Uëpƒ]Ž•ÉÑ壥óç¢iä"h2¨ú©i`¥Õª#ieÜé:à ‚‰þ„'ayM"£ÇÙSi hÔ8¶ª—é•lo 1,pšýe"©æóém„½Cx¨R•9•koT/{F?>ëvOâ|‚µ¡JµEFdõœíYx‘”ºéÆ3y &’¸X®«”ø?|]%ë$Ïíó¸šA}6®ç¦ˆð{ŠYbàWΰ¹câ )g®Á;§é•syt-dÞ¢°qÀß#eY—îžZHj_š£ben^ðTóÀ4Ül°ÁÜ×l´:¡bPeW ™…#‹­Yƒ#aÝð\s˜ ŒÛaۦΘFé-d˜×~†AðÞ°lj½ZNPò‰27øµÆ Õ8æ 'ç\÷'÷8ïß‘Žé&5¿Ëm&víõÓÇ1Ç£Â=,r—ÛCÈ$È;®#×—;/ÙÜÕ—?|ˆûÏ}béR©ojÝ6н4TG´ópTÁê™â¤QáemŸT™áÙbñ(LDbB—Ÿ¥sÇor[®Á§;k[§|Õæa~ þx.‰?U¯Tïmìñ%EKƒZ„êP=·åS¾ÔË 0Ò¥ L»`¢köz››ÝÓ‡iŸJaÔ°*PjàÁ¯ ^3hŽùèæ˜Î¤¬IEôTe°ÜgZ¢=X0¸¬T•r¸¼ƒ¹]¡V èws%DH»|sY½HM7+js»<~á9ŠeŬ!Qýu=/ ;º¯1wIXªJ;z~b?ô¤°ð§m s·©Ð¨Û]Xäê#A¬¤Jë]ØĘ̈jÛ=d7Z!@‰0I'½3„ãòAùŽzØW®¶YAðÎŽåE(Àeöéa\…¡TP[tã[ÓÐ}<;Ù…Ki Î$7Nr€{´¨O‰”ØtvëÆ¡[Ð §Q)—@ů9˜,~¯×iAaÀú+¯Jõ0åì•ðîíó¾mg’ŒÕÍÀu‡O<Ùï ]æàÐ;xmk ¼hõ2'eaPsŸ)ô2)áË”'ó=6mE!Íq16r™’ :§¹>¼®ûmæóF·*9>oä}îÏ@Þ%Û4Ë·†¿»¾6ôóÓוÃ/’Qç#ÏèNŸ/ ÖÃ]Y@zÁÊÀ‘%'ŸK'†Å–õ¼ÌúÜ£ª,eµÈ©þ×acŒ¢»:{›AÈQ ‹ UÞ“€ÝÞ |Þ×ÌìhºˆÖ¼ïâð‡¦öqÿ†rEï*Ú¡ý€óùx2~Ô‚¸% Eóu~ývFäAW<2J[{GF¢ ‡åÓ=‰ÿ_޼èär¬¿Héú=ÖSåÚç¦ubèøâÈ(›^£ m,õsb7AIþ°>ޖꧤý&›ž¡íþ>Pþ$¥bV#”w/)heç)øÿÄðÿ~?±öv)ÞÉÂ#«9ó— ÉdWæ,~“ž³ñOo®¾¯G ™ƒ'jIl“ÿÑ|T<7 üä5²×Ä š@+Ô?¢ΡÀû„P)F!f‚þŒ/9•¬úSÈ’Ÿõdèô=žAû L‡ÜÇä±ý4q.ßð*Оê8RtŸÙúÕþ†OîÓHž ƒ¯»Ô{ }Ÿ4¯sÝ °É7á· mäSეpÿf*p$X€N¢çó‹awxÄ»W›„‡í`r`"ð<ÈIJÝú%*¯ŸÚš¦ÅÇÛÐ3ð^~G3¦¾usrEìÅ1 |¦×ööüSÌö÷uã2‹ HeŸ9›@ Pçþ>¤ /§ª¬\>³þ=‹ó㩇ÕÑóŠÃ¿,0A½ ?ìÁF¯²ÿêŒÓ÷arg€«nÐDÀA£ø€yʦþ8¤p?È ¸ ‚<á(z': ídÀHd¯}Õög°Úy'„×ÙáðÙãéôŸ•Ýÿ³á@pQÅüÃL[˜—¡RÎB†¤ÓJ—U-þ–Uñú°mµCgþÇc·ë0ûXC»¯þ®|ƒ¸ôž„&çêôüqÙ7<'¢cäyy8ŸŒŠ2M~SÇPø²èôYNÌ¢¯üo)iD†Œ9€Áíz€4¤Ôí„6>f,ÂñŠ*6²ŽÔØ r ¡Y „ʨÜð±ËÙ»ÄïÛE|8Bvù ^æÓ´ÅȈu ÃH®‡¢ÂЇ¥ }È‹¹ôf9ï!‰É!ó²}Oúw”y{s??f?žCÕÓ>É' ?L;„y}?¬ùBq!÷ÃË ÐøxÔÜ44¸Iý¢Cߌg䟙]ytÒCM¨O8Ÿ=Èm¶›žª­gNóbb3Nì`Á-“Dœ¿]e'O^‡µâ*B³@ÞéØ1p¯¹·l6øø‡ÏêUC៖ÿñÀxáƒÓH¼§Ò#ý"?Êbá§çxaËvÖð•j5û‡x×ôÕßèAÑ«üÛaKŽ¥VU$ÕÏpíÐ4tèuØŒF‘V=ÿµ‚;dæ »éåç­;@j¶Ó/ðôû‡ÝÏãרhÙzKJf‚ ¨Êä–ÁÖudõõãM³b P’ ]¬y÷Â7‡T޹;ñÐ5ÙUIá±9k6ÕAà6î0A3°¢  ‘ê!¬-`ƒ_¡P[ʾoÉÌô$ óÉén•Qý­ÏâýOO½ÀÏ!D6(‘Îø™›ŸKÈ @ÎÅQ¹‰¥ߪáÛz–<šq²ç™@å¾Ù£ÂG¸Å ÿ’JŸ¦WÀ‘ßéìíÙUíþœóÊœˆÕ Çåÿ‘ø÷þ³õ|¶CÎ÷çÇ϶H›“b¶@þ- ð)GÓÿÎ1 ¶Ì?-ÆýÆøfn(}ó•× P> Š»ëЧv(ÄŠŒe¹ª?Ç'J Òsr(’H¨9 #"sƒòÂÐ,)ÈH€“ )H$A!$ „@¨¾@»cAœ=Ùݾ&õÂWR '—3•òcgùWñD@ŽÐƒÉ¦ðpAù”%2ÿ$ÿÿÑ =0pþ<-þ³Jkó¢œ$ó쀾¯ù•…USX•mܨœYüSÓï>“s*riÙ£jµs.™±åÜø„ÿ¤?Í<§ú§bGõH†_ßæÇü0ã¯ëž»%¶eëÃâµ׎`:ÏÜìclh†¶ÿ'Îi6qAB‘d#×ù0¼½Œ™ò‰™¾}©):Cš3ýrÀO?ïÿ|Dè¨zLÒÔiÏýƒ=ÃɆ¸p3–/Y @^ìΗ•øÓü€<¸äâaS‰)‡ïü8zÿ·¯˜þÀ9§ò¤ƒÿ®3€1%8³´×@‡ýОjë!?íågÙä@çþ‚h‚ ÿÛm#1²ˆ‡ÌíERN;Å™­´ Ë›Þ=ü½Xw'çÑíû‡ì8lÉÂOdóƒzÕ&Þj–‡å°ÂÂöŒ¦@5Þ©ó/É JQ¡Ó2D>ÎÇü­¤îL!Ÿu¸h?—åTŠª"£„:3T­(ÿÙ6eª)»l‡®{‚Qà ~® ÆÍë3¤;CÛ"þŽGãÏ/Ó/W`¼Åáˆa_GLù˜6eúLhˆä‰¥ª©$!¿~Ü|±³x×Oô¼ö|„{»zhbvé^Ú£×Ýäú€þˆürVSc^?)Ðù–Gõ}¿;O¥ˆ¿Xð B6þß«Ö7E;äû {'¼ƒË.± _¢û¨ChSÂ7ˆ¤fËø×Á"ìx‡Ënò†:!†öÇþZL€‡‰ú¿¦õMÛvI24¡ffE*Ê´…у(á$¯øm¼[€}Ýõ ŒôIÖ˜0¡å1x mŸí/ £܇çùêÄ¿éª,£Ú„¡’!öò/ð3áéé_Ûût“e`¥}c g•XŠÈHøQÒ‰Ö—$Ñ9‰Á?ôÉæéÿäÌØ ÷_Øu”x±O/rO!ä$Ça‘Ú ’(}¯Úbìú?oìC`¹íÖØI ØûRú@câ©,Pùa2O‡ùðDâÈHíf;Èüà`‹@.ð:ð\Û{>Å à}ð_èø]ÞsþÂå3…›lÑô²“{¸r믽h(¡§6 ÅÇíÿ-A'úÒJŸ6XhÈáýÄS*fÆ¥ãËõ¬\ØVµ;F²ëÑó7 ØÖAd7òÛoýÀx=Ú~Íàß3Yn §ó¬ƒ–/œÛ¹ˆøö¿»Ì· û~!Ñè„—j¢›~Ä1¯¸nIÒO6ısž¾]éþÖ¾ø, =,¥ ËÏëâgq=Ô‰ GÏñéwÌìÚè€Þw"—yBføó"‹SKGë—y±€É(6ÈÎ…¾5Ï¡QGú1 ÷nF½y±£lWÐ2~Æz¾íò`„èëd?¿n)À‹šž*ÀéÊJ8N<ª}£õÆî2Šá,¡MÜK2•_ažó@>d5@XqÞV›lxâçÖ8O• n‹>¬ÿ0¬¸dßÐdï63æë”ÕP£""€ð}hX”ŽÐÇ!ÂrSù€_ó9Ñ~c^ò¬UPPTGãÅ;K6D6ˆ¾,C `|-ü–Òìf±mˆÚ ’³ °˜¢ÑhÁåÞû¼<Á¢¢KFÌA4Ä‘Ü~õMiJJ> Ìô6ÖQá‚èj¥UçCæ`"CÀx¥Ó˯gÿ!f²1ñœö†Xs2B0N•÷Çô|XŒàURÿóýÚîÄõç|½_FÍ ÙÚŠ òè9Dœ£xï‡"‡P6¾LaOùæ‰ ŠŦçüXZÒˆ^”R¹üø ’ßSP44Q@4r$ü8¢}]ÝoŸëePÖ ÅàSà4¶éy@÷‰#P¢}ÉkFôõ¬¯ñþ ¦@î¿–w¶#àLî’‡9%™& œgŒO÷)¶|‚‰£b F¡~‹qX5PhÒ|ÏÈw­¤¦š âógа8Q7Ѩ(R)Iö„CÛ?dÉgäùpÊã˜f£ñÿ÷Ön@ð$z÷±ø 5ð;œ11dv-HiF oƒÊáGPl<#zX¦žžLÔNÒþÿUgßÄôv;ø/´s1L=È(Y™¹ˆI?YëÍ•zXh9JöÖ÷–¹fu‰Ûï"TAî|€}bˆúà Úþ_Ü|gäÏ€¸ß‰¼0}€'1Oå6M<úÃDÒøøè~‘áûÀ_ãúÀë¢n¼yMq†u—JälþLé¤ýbÙ)Ð…2r§b[$ÿ ©ºqÅ`HWCù¬—àWYÎø–5oeQß–^l_ÂÉ?$ú·s±íÀ×ù¡ç4‰¦ƒÔ?‘ lÜ%]Rh”ýI?š!Cø9z·› (d‚!Á«Ä5Õƒ‘ïæù0ìw~gí¶yã•?¶ëƒÉr¨"j¹‡Ÿ <€YLþ™Õ¨öuö}Ÿ—ëÇîbŒƒ U_å 3”…e‚¢ ,^U 8©p$>¿¿èv£õí*ÕUVe>%û”þg¯lËOgmYÈaeàK…)ÈÚgA^£â^IŸDNi'ˆƒÚg óI IÆ¿«PãÝçqM¨rÆ (é` ùÇ”'À`!3UÏæh0HWŠß§•k„—ÀQØú``œâæá$¼#šèó²AP/éñ¶óüSèCé4Õ&y¸Øuýr¯–×Ñ‚óäfbŠ>´G¨Ý¿·ñ–¨pBƒñëõyŠÐQþ}3§¾qÐZa®”;“ |žú Ñ4@¤žT=OÖB† ePæPå&Ð}Œ-åüßWû!ù7™'tŸT¦£æƒÊ¡d؈¯ô¯z§o“!övöèCÇ)úsÂG-ugƒòþÐú“¸*~|™q=èPzö¥3ïChÌ÷T¡ñaLY :ûË4a1ïÛÃÌKC5B‰Õîj sï…ûúù†Àá’Lk‹-s![uÒ~L™M„7õGTǪ{gÖE>~ M"J‘ Á‡…º­éwÀdâø¤û y€h€ _^¤^ö:x§óšü§ñÞ¡‡‡_GîzBuâO–έ͆÷ÿ§ÂÿC<ÿÃÿOôÿÇ„à’yDõóIáwN3v` ÇÒ[G¶û•߈FãD˜ÛÁ© ÕŠêÞõ‡ªëŸ¿â02o¤0Dä!9òŧ´Ñúôí `í$Ñ÷î–{þrüw¼=Éç8®îÔiSüÈ×åû?±ÇP^£ØBcÜ'Ú‡ñ°-§í]Smµ¦c½CϾ"pçø´kˆ8ÌÏÝŽ/ üOÛ‡Pƒ¦ëû6ý=¦DøÙgá q¨Tü=ùñM¾:,”P,’ÞËõȆÐp¯Íú´&¡ žXº[¸¥GË.´kþ˜îmSB4*¨Ñš)F9Ø0TÁýº$1,NL)Xêû?¨óÇá.µë&ž=~˜‡ÑùÏÚDáé%| @££&Dþ¨½N`m÷ípx³ö®¹èg3Â7WÏ’O”UŒÂQ5¡*€ž„D²UãÕe0[cû¥—HU}À4o_ºó~˯}ݼ káƒÔ;+È¡)v›uϳøè=$wú‡dEäùu¦]^¬Ä€½ÁCZÌRü r>)®/)ö}r®m÷mý6» ;a› )¡‰úüïž(ž`7Ù/9÷@ûñ|~o×ÙÖ<,³ ^8„¼TU»R8 îQµ2á€@ÄÔ|@ :™ú`'¡ ì5¯4e yYO‹Ý|nÿ·ßüZ©"*¿ÒþŽaíÛ™‡AÇûÿÕ""­âÀíì\ÔênÔUWÙ¥CÓö~› O=ìOOòkC°€J ГÎhå›ëʺÛlàŠ¯T?ú}úÌÇK°J%ë%î ñ=ˆÕ%Uè þžFÆ´Á6‘C‘Ë`Á•Q>!©|Ç­!Üš ü ‹9¡„Ngmoì™ËßûŠXÀ~AU4É )õÙ$Tì `ú,”ôÈhýPt¬ÀD D&%è8Š*‘iH>Ì‹ÐzDÑIªÜÜïufŨ’c•IHŠåÁ‘Á¸‰ÆÿN!.Þg†2‹™íÙN„yïD)ÂÉ_«øÑ?˜TÛñ¦ïéd“â;à‰ì}Ñáƒc¾Ím#|Œšf·î?`|»0dÄý¡,?|:¹Hk¨€jmŘ癕ˆb„º!¹¶’O§ÛŠúî•(Å }×’˜E S^ÀÓõBˆ>ù§Ò`6& :è?4~X›püc½Û‰H‡£ã¾LthXI?ŠåTýþK†egÒÿÈç Oì’°ƒÍâyå¿béð5Ù!|¼¾CÃéþ=þç‹û›۵†S5³S‰ z¿¼Ž‘ÆÎÜ ö|ÚrÃ-JZ•%}_æ¿ÑÂÃÚ!Ž0÷uŽÜjw0ùð*wؾ[—I:K/²Ã܆ýʲ¼%ÙëpÇH[N8¼ŒP€,, †ä`µM -GáïÊð/Ü56#Rvò=þžºŸß²Z•ÜS )¡œ@?*@éºÓӡÖöÛwy_ùã“«ˆï¿ÜÜúN_óXcòð¹ 9Ïûz`Œí 8/¿ÏfÂ`d ±µ¶k`Ä-[&­‚5zäë´V´E³´fÚÐÆ±EZ-¢1goéŽ|·‘¢ŠbŠÚtES¶¶ æc‰éÄÍPZÖ¨¬Ñó±ÓcA5½n!’ãlll³ “Y¬khµ¶­­ZÃFƒUID4ùßéö©òvôF˜¸¢E:1Œc ÐOgsoáþ¾ò>Æõß7qø#\¦Ù$‰›A¡Ô}}î"–‡ÿôëÔkýý˜¨:6ÃFJÖãHÐŽ§«ETQq$ò´ÐK ³Òfô¬0ÿ†~m)è…É:Ï'™‚½¨ü2ŸÅ;ï—ñü[Ï(Oåzû—å6UöÀ;Ü m¯Œvÿùƒ„ÿx'âCëï@¶QS¾@Gñø>¨ÕÙ$;€þ° ´„ýáÀøôKýÙ•ÿ¾'Ç<.œ›0bMçk¯3b?),oL†¡D‡1¹ÿOelÉDßÙìpcø€‚S½But°Œ™ñö^ØŠª­¶yÃÏ_½ +±¨6}úÔ_ÇWQ˜ŽˆpýgØbþÒý÷º_§÷!¤óuJœ@òuSµ­Õ2„¡*‚O6 ^IŠ*É„?•¼ö@9&j,CîÂÂzAû°þ7ËÇCù+L_ÙXùåNF@ø0Ó3£ßÿ_Oû‡·þè… -E¸s%’£?êÇý´U`N¼eü?Î¥P@„&h§sy'¦Ý­ˆ9ëùƒûYÔ¶@Vç–Œ„ªœLâ‚eÆR&\‘«æP~=y·¸È¾AØ€Tá–:¤L³™¢Ä…~yŠ„RQ+2™Ìc Œ™³DÂÎrØõBL|ràü´ìß¹;=µ¸š>>jÒ´KñÔBI9‰€IÍ*ë]jÎþ ¬ÓZÕ–¨Iƒüâ É#Aÿµ‘ï ÿÖú¯Ç‹>8g«*¬Ç(-Ë}²ÿ÷ÿõþ©&ÿßõÌ?ÿbßôÄ©þ~Oõ…êé*lKØÒÙÇúóÿ?þô¤ï(”—.û¸âdkpaÁÁ‡€ ?üãÀvCÀ{j*¥à)•ru! ]ˆ¯[Sاõ'õŸ½çÅCö/?ÉéÐ÷ìdD#SeOÌœ“] Ý4fMt‰2ˆ‹$™Ñ@ÅI|%NnÕƒôÿûÿ¸üãþcWšÛóÿ‡ÖØ2Ï–¥ÛEUXªÉ>÷¯÷Þ„ƒxà‹bþÖñ"D  àš d‚¼wóü(ÿ˜çÛ¦2ÀÒÂ~ÄŸ·_Ïûyïãþw?è|»Úù=PË$)'aýÓ¿ž$úÙ'6Éí²©/J)ÿ§ÕÃ|^•ÍFNBû¨Áæá¹üÙöú'ùë0röT*0ö»ñ\tZɇíTȉߎa‚i®áÿHý ¢t‚€IUÒ^!ˆ‡>4Pþý¨ì~ð®–áÆ¶DCTí0ž^n:@¸uB?E™>›µmõú¯'¦ö7P1t®>Æ@æ1 ®Ùš'aD"îÉ×­ò®lî¢ÈäÕÊí¢àtu#µ®’|å€w99ÃÐXŸB‡—P? ”üðûù÷ü¿»öpΣ2Ì5èù æï<1 uäÎ}Z|3Ôž](âØ“a/ãAô”jQETïKÓÊÈ*µ@Šy“ Ü9. ÑT'oe_ÉAðåìÒÂÓÇÝÃÃë£fs7* öFÌzcÒOâïì?Æ>Þgb˜})f›wý¶ôÔ…‡‰¶sxŽÑÂÿ,8MG:«/K+AÎãå Ê‘ìj¬E^ƒöÔÆ‡v“{Î~¿´K;'Øœ@oš$ŸJ{“Ýð>6Èl@À…š•íØÖóävÚ¦‰°¤PžE B;ÊŠƒ¹/E”à và©H¸‚EQ&Fß¼z'ÿ FÒ›9?Ú¡˜¨Cà:Âã‘^=^`µ¯þŸè?öé¤ótÉ?øü[›:üÐõÿÌK×·ôïÃCÒ1!¿®qÖwøÎ97ò£ÔkÛz?÷jC‡û¬0™,ˆÇü*‡D$O¹8˜úf…oÊ$®<8ùÌÏþ=Û}æ¶:tÄCÏoŽ ¢ÌvFq¹ÿgüÔ*yV ~¿¾^¥gDý’§Sþª€ËÉÌŸüúÁ…8/äÉ/¬j@0 +Ñú:‘…rÂdv5ÇLdcù8`Ývjü "³¢âx¥v§ãÂÖßÓÓ«kLèÍ?Ϋê£*ø#…ï.ˆrÙBKõsÉ-Å;;,w’e6¸–*K÷æ}!…ÏfpûýäÊn²n |™?­ ö‡ðuÆ`;}Áçlìs²)4ˆN:‹ß§ýveuʶ$\¡cZ%Wù½1e‰a|È!f*5GE?ó‡šr•ú=sÑ:óÛ½ŒPàÒ°éRÁ$±F®º¾º0˜dÂF!Ëüßw]÷ÎѽîÈ•,×$É6©¹.†°‡(^jC!½p¹ NsrÉ›’0é—,() Q&DÉÕ¯Ý)R/{˜™ºËk5U2:¤î!Çq‘ŽÄ–dž|íÎLƒÃ÷þÔ9«ý¥ûi’%¡\K‰È~ï)–/}Q O.龟ž£Ó®¢[–Öäuq –=ùU>E˜Ä´V%ÂûÕ¦ÅMädZ^ºà×¢g_=èušÂ…Œa#$4©LêýÑ$IJ @g‰y®o…ðx|,È ˜paö·©gxÙ‹Õ-n–àE€O%æœ<^ï[{ï¾ÑîÝèã"Ü,¶‘sšYã7\‚@6¦",B=oW™œÄÎnÉÉfï†Ø³z’M¦e6Ñd²BL` êÓ7d‚r]Ãp ÒÂ¥N½49Ã.‰ÓUÆ[VJš„Ê^e«.TÜ=¢&èt93Q,ñCdÈôu/ ò^QËâs›½sž;:烷Ǥ“ÂF `Á†IÎwÂq7’¹b=4»’rÓ!ËLº}iÓZˆD–D44åÚeS[$™;ÊØ;ýæ•]è»y® æ¥ÄÔ¸%ËRe™ “$_³¥Ñœz†pß)§N“• ÔŠ’Šn.ÄÉŠ|Î )-&,†F#L„åÝ%L"G{²H%á­Lb1zAhf›šÆq*ÐHº‰'’<‚ x’o¦¼8[K+“Ü‚4“»†Ï|s®u…‹È!’‘:’ç…ðì&õ2AeË˲aK*«¼Ÿ¹õ¦ÕHèL¢ p`N i û<ÇíwÓ£8¾ž9ƒb`/ƒY‘¶†4(& *k vîuëIp#Ý@Žòû†Õ€ƒ_“ä5I8[ÍÈS!ëæêõNýc¼Q–¯êk…$0¶×‚IBæ?l$ ,WÜéApƒjOt‘Õx,ç%EEò TRP©ø$Xxã,ÑQÊtU‘ôÆ*eT'pÞåù©Ó£<ÍMŸÛWƒ([Ãä±%2èAøæ¡ þï~Ÿ£Ë X,TJ¢C7Øðâ1ƒí&ýSÛ¿¬Q÷XhcØ^Xú¦'[3ÈRp$›a‹ßé¸H+l„qGWqÌ×g³µ~ØÜm‚#}Bzî{L°aÊÊ™‘ù„I&Â.N[݈ ,¹ê?¢3ÇãŠü«r‰[: ´®¯ýt¦G«”E +Q׆±P+¯çݘΨßÿ¹VÙ7°?¼÷ž?‚VðÃòž§äý_Gõ hë!þÍ']þ¾ó¤D‰Ç›]¿h@ïO’ö1Ñ¿â¨,G‡?Û¨rüÑÑŸÞ?Ç_Òü˜.¿vCfHóA¢Ï³ÐÞF ÓTB' {ÞèWhÇ\¯–ࡱ€ÓÙä@´˜ïHýJû]¨$½ÖîùÒ€€]¬ 'ÛOýM_?Ìù“üË´!ûº~>§èüzäÿ¼Ãâü ·û;¹|~ŽÀ:àooÑòþFˆše˜’ŠHš"" %` ¨ˆ!ÿrÄÐLÄ ! ÒDÄ@ÑBGý]’jH¨ bj R‚! ""ˆ‚B$)£cAýp¸¥b‚ (¤ªT„€h¥ˆJ¢¿Ü6` B‡Dc+CCˆª°Á¢‚©¾/àóþCøzKÅø8ÌüOàîçgø:#>§ˆý,ýkýÄ!Ý"Ÿ§ÏöøOÙhÀ€d4³€r‹ÑÀ/µÐ*O‚{I:33çwàt3–Ž!ÁÛŽß÷vv黦dâ?gþ’rÖg§â£sJz®¶Û8ÌòNš¨ž]¤Vu‡ Då̘¬Æ"‹¬»²¤[ÝAEˆ´c(—hpr£â„‘‡œ±—&à¢Y´]A.B©õdή3ŒCa¤q{vŒ¹›±C¤Ö‡kL”:¥A.ƨqi b®1f*a„ìà‡2[³ÞoÚÌ(¼©Pñ 3™˜„!)Õ¶fa±¦†RúÊXVHÑ£ [,;ÄUÙƒø‘œÚ < &³}/g|ìßB°„{@&6˜CÑ9¦@”2¢ÁÇ- ®ž$‚£…/-¨ÌªÇMjÖP˜3ZÉØŒÑèVX–nñáb]&t3Y Aw!‹Ì„ÊGxóiÍK4’hˆÎ:îéËy4ðCj-/L(ÉB¢’d-è†Í²É#Ivº®Ôˆˆ0ÙCµ4 bˆ1Z{ƒX M`‡kI\£œ,MÄ$Є"B@û¥fôUέz}ÁÌÿš|Ò£úÿË̱Àš²|zAa‚»³1å¶Ðׄ͂ !4pÖ@o¹àTRþÑ>^iº#n#tÃ{ƒ°Îžg§zš”ÿ(šSX%áq7wƒÁVbš¯n¾u½p·¸÷ÞµÚ7lº¤qãý?£á}:Ú¥M·¨ZT0\–Ê—(Á‚Ë_GíÌžc¾M¡ÏrA31æh’x$=ð/±€ø·^SBL{ä}¯—‘Ú÷ôÔøï2…éÁe&¨†Èz;‡Mêd¦¢œ”C:bHHùHåÈ…Kõq5ØX“T'ÓÖ’Ï8a˜fðIÄ5õÎàt3ÓŽ˜Ð'ˆŒ‰%JvcÖ윉ú¿xl׎pòÃìÿPÆ=cô³~1¬|“Õå"ó#ç‘¿ÃËødÓm“X›o˯¼"›Ñì\¾P6†à§3`;û»No¨¹ÅûÏq¦iDNᥟÐ41?ç:»xÛUÙ×þYÇ‘;ÔÛ^¿!?O…ãݱôîQIþߺˆãOÂÿŽ%Bi¥OÀ€’5HM£@š5IóÞ”÷Hƒ3L˳C°¦+мT>†2r^žŸ7Uôî­4¯ºR3s›) „“ÜÈIm¡Z–… w÷p8ŽþÖG@®‘t­%/€j‚$¢"$4Uièæ úÁöÎýù×\,ìu+ðV¼,’ÌST(*©ÀKÃF!±AlGåã/ö9ÏBÐô6pÉ8Ý[]¶M©©n9f-D8@QÞtß„¤MP< „Gñ2ç&L!„ŠWd» •( $=H˜: 2S$¿@Þ±Ìwepsáü½ƒèCã÷R¿Q—õ'mTPÎŒÑ,T~ʳPÇýÿ7í„Ò2Áäþ½ºJ)O\rŸ^ؘE»˜_ûŽÙâYz`§Nó=æ5ÒÐF‚6ô„SFS-Š[‡ @Nû…ΰÝð¼' ’•}\3ú~Ï£ÙLJäÌ3Tö!Ÿ´¤òñ/-qçqÐOm6>ûŠü¸v#œlZpK$²m¬U–‡ (vËmêyó$|n¿tjƒûøAuµÿ:»ˆ¢,X§5“T;`²g0Kó⃋QŠrhùžº6,lF”ž( ÂÇ$õ’ ÷ÂÜb„êx·«+å§AÙp`ðìCpZ}‹€é4?ùxã²ñ8/¤úg: zÖ0– ‹Îë¡¢14ǧ±…æ¸%†‚W ˜,V&Ë!bC-)>í)`á3¬DÌA"’QˆŒcÌÑkw/cA3ÛŽ"£ ˜03ŠØÒTWÓ{ß&妀Ñê‰7&ø$òŠóÀV90pÌHTŒŽÌÿL¤‡y4z¥4$Ç1$ñÙ âûöäõ>°xe¶µ“ø”™ˆÈ ìC Lí¨$:\…жpHyÝܘ# õ¸yu³CGêîòƒÖÞ;4lɈ(ª:èã;5IÞgÑÓîzb_q!å=ù3´“„ÅQQ¤õS×0šµV'ÎÁGlÜÍz’Õ‰2 `é@Qbi¥˜ƒ/IÕ§€¶€Ð|\q„ÁÁÇvì’uÊa»Àå|ŠxÅùg®ŒC&K)BüI¨9piR’G#~Ž9¾p™£˜ $ÝRé3ç“$˜„ù1£ŒdÆ Þ£IõÈi…<•Æå8î X™! #±šchÑEU,px™¯®0ú¼ì­#Œ8¬í™»‹´ó½÷DãƒdÔÑï9B/&c\SÒrMÎê„îÏÖ<ŠW‚õ]îå8d¢ì)?gÓO¡…Ÿ[ñCàÌ ¡‰« H7Áãþsú«úîýÓ͇©×8ÿw<ÕT@Gw‰§õÏwóþ~-!òB¸M¾ÿÜCÅ™L¸<'·[‹ ‹ Ô BVÕÐÒO/÷6?~·/áBš8Nª’¯÷+šç•RÓC4sðÒXaG¦²Ãt‹X¨ªÄEŒG¦Ûtíá“&uM)ÛÑ71$` ¾• Õ¨¦a€S²_ꢔQ؈𓄿d„ñ´Šä´h_FøƒÎTÜÝÁRa(ó‡iÚL7”;e£n·|4É夡CŒÆå…×†àœ¥¥@£ŒˆtŠW¤B#ÆW!!2Oв< á s‘x}X òã“{MÕ{‹H›B ÆE(¤9Y :vŠ@:J©¼!©Nð—„=’Îxȇ)GòÈ™(ç™ +£‚óÒé=f"QJ¬ðt•:@º’ PÚ  ÉTÈ–Uµ°àv¡›«tŸ<ýOjMR{gÙXÍJÏåö]‰‚‰>^|þSÍÿv„!f#Pç 3gM c’}‘í;c»`¨a M¸ÊgóüÅöhrjžÃï;6C¶ërf-Çnr@/—~ßöã¥èIêî;§oÒÙš†Ðîc¡8âoisCܧvÍÙ»ûyâZ‰0")“0f|ïðî#·wÆšk½ó÷xÏ4rùŽf éÃ3“™Ž•x."÷¨FUØ#ø/øv5{Ðf p/ÉîÔ¥îa3 #ûÀQþ7ä`¦i¼¢‚yt¾ßYÇ€XÀC| bòš”JôN÷úàt#$*!|'qËTYËÚN¯Crí/Ò%ãæª^~h“x—.³ˆÎ,ùª‰ë÷\4ørjk9ÐVÑòÖæw=QÄ|¡_-˜¼ƒ‰h!ìíuŠ'øbþ-ÄEÃRšû®á$¸eÆÙ ÌkóFΠÅaÒõÞ¶ÉLÀ„´´œ`­ÑL%k7¸¡Ð'@§Th1‹bDNí<¥qó!~¦†… ºàõŸw«@ñaÿ?-==YüßO´Ïôß?K†çOi>>¼LƒP1&N1QL$öÃKkÎùþ´¬V¹b(Àµ¤Ã³V0ævŠ!¤0±¶Ž#Š‹h89² ›‰2LÙ·6›7si&ËšÚ$„ÞZbzÑI¯9ñ91x'OžxöªµJÿPÃ?èÆ‚’˜ÓZ ¥h*‹5|€?Á8@v÷Ÿàœº‰åøƒc»’Ïó@ J4 £ˆ£õtà$žI:‰ÿe«îø÷|Tïÿ7VV¾„mm›zp55lF4¢§y¼‘° Ä‰¨ö`¦0\¸£Ä 9` H”C@¤E²ñŽJâyýD~‹&$³˜~«ì/&ÆQ@»š Z*J*J"¢ –&!Þ|_¶¨¤ˆ2Ä€¥‰‚B¡:`Rý‰'˜ùϱã ’ ™r$G‰ÔÀu¦$ ­D§Âv í ì=ßã»Æj™H|\•`d©Ë#ñõèÌÍ rÛüt›ÛÏ’hó§øoü==OÁ§ü³è:`u}?Âꨵ¢É†,ðü<¼G2‡y?¤€ü}Ÿ´¶ï'· !8ÏŒð)ç“Ýl½(¢SÍbýg¯OŒV •ȰAÁ‘E‘ÆDrÎ ´“´hÆè¨³w éˆ!£ünÍs£Ú]™p·ª$¨ØñLUæÈrç x '?—ÿ}=$“.Çÿ`…md ,üÀC‹<êÁ A“=?ÊÇNÇ$c3ðY°fÀ˜¡ÐôÄóŠã!i)B.-f %„ÂS$ LƒDØÛà¶ñ]à>v¡øçäÀrÒ¾þÙB˜‘ãùö=Q 3 «îÀ~6;hŸ8±† ÿsóhn˜Bz$ o5’UfÊ«Aú[QA<«‡#.4 vCÃ'²‡k†‚ O”Ũ›©…‚iª’8}±VI½=÷ÌívSŒ×Õ4ݶ:ãßË޶Ǹދ@ÌÑE³ôøé£0Xš3 †Ó»aŒT&d ŒŠh@ œL.eÍ0ï xŽéÍܻٙÛZ1‚—‘—´bÞDS´fɌٕAlCE¹$3`ª°%‰²–ˆÀ&œ1J°3­ËT”Ž]«4d2@Úk,ÒTÕL`Ä 4…í„kX32¥Â„¼M5‘=x{·‘Å{Ÿž·­$’Ôk Æ£’ú ŸOËuëÝÁ}¼ #ÒÐÜVÁ*;ˆ$Í7Kw!åóÞ†OWs¹ëCyœæÉYmó9)y⤨ÂcÞ%'^$’Μa‚l¦ÓsW1Ï–+­`&AX‘ÍØ6Ó°d €,¢k…¤0r0@K¤ò^¨„z yÞ/ëîNÇ‚'óŸDxéð‘3êøtüX`Éá–dfcÓÉuü²)GM'“á6ËåÛz}Õ áj®zí¼´ž¶¯vô{ƒ€õ ã@MCDÌG¸qLÄv-­¶Æ¥¿÷Aд?ÜÆ)B#Q.¤ªi*‡Ô!íNIóx¢f¹ÇÐz:ÃÖŽ¡X¹‚UÈUQ žàáæJtuoQ˜¹0:vÏ_k|6#áG—|/ú?vhžîfUqseØO3ý¿³‡…ý:š y,°›$-œ´¤ÉC¡DÒêÍäï%7…"Bhÿ›,a%ˆV+`ʇg‰¤×O_onv7ÓŸüöLi$&G®ëj€Í=CálÃì,>¬õÆYa~ÚfÌ\õöç3¢Ä欻12‡âƒ*wiÍr[XÛo.—si—òÌÜú÷óÿËŸ#áŸ)ÿoѶ§FAxÃÎ^㸙»°Äª&$¬ãA4„TA2UUAM--bÎdûÈô?Ëù=ÞKªÛPAAVÛA¤˜4ùŠ/T#ÎõÈä'T"íUôbï¾ .Ü|ˆ~.¬^¸ü`Fnrœ>Ç´ÄõÿŠa)OèŒÃ ˆ¡P=y‰RR$ÍCPÈÒ@Ê QM2D@PPôÐC;!£H¸$þiÓ„zEH¡¨A¥*Š! zÀVPð?“øüã?7C’æî|oU„Ÿ'!_ÆBx#’I°\uC‰ðÜ ²±û@,¤ðüx5kmuÔâAÊS~[Ž¥eîžaË(70ôg“§Ÿ–459WËŒ(w!I$ÐÇUÌ02… î ‡ËGflYvœÝžü(=ñ“À‚¶”¡LÀöòT6ëÇst5t€Â¥QñÜÄ6É2g‰a(ä0Dñs¼ˆˆ¤&`㸈È`º.Ø…!i€( 9M¦Býfô G!úxÓ|H¶U.}<þ.ß+U£ôü«¡E5ªT $A7ºí!"Éré(¶àkaõûû=[¤óÚ@õh=zˆz•:úûÊtit@fJ¤Gɱ{†“ª·¾ï<áâV?|˜ÎíXÊ€ñÁò `ä0Ãýc2¦`fa>ï—Ë!ðóÂu‡P|¨ @‡È|ÿ¯õõ¨4)Ýd¢d=OÉØ·ëCä~r\÷~ÿ£ç۬낂 ˜ ‰ iŒý|K-¤Àò %þ§Ã˜'Xûøô×RAǹEâ{Iìð˜}Æî<>€¢þLê´m!©J.­šÈ!Ü M O­áöÔ…˜æÈzu^ýÄì„@Nî&yàe óïž¶R/§óGGÌ1ÕBd'»˜ïÓ‘äÏæ°óxž'‡)»º˜†“ÌÁB(¨®ÞAŽ# ¶’†þŽÝD²ttŽ#ìEGŸÐPòÀT#J½—ìö£Ä7U6g^1óùÈ:z‚²îƒ™Î¼¿¥$£éAÂàggõ¿P –€‚O¬ý]ç6Cr¤h|—Ôtzã°¢V!;WLJp{`˜žÙfMÜa™l0Ü´ ÙŸ+¨‘AI4Õݰ3Ö½CÇ ¶ia{TžÓ0\ÖFb*H¤4 ´Ð­ ½ɳ¼rÛmç,š26Lƒ•¶ØD'ñ‡LêpAPÜÓâŒ`u‰8÷Õ¤©¥eðM¾üñDÝÉüb´ÌL Jˆsx<¼ÿW‰ÈSÉ·í x O‹p|Æe*y]èÒ€>Mã‡h=`š ‡R!Oo4ÁGtõ`»û0SÅIWJ‡’%*RP‡ž$|Aä%!@;»)ê]Û‰æÅ?h_r¥ t&”Ò¿ 1~ß$Ððp—œ!BIf^€g// ’$x(ùŽB}*s>¨Ù Ô§³o‰ýN<‚’€¡¡  É)ª„&˜Zi(A )V¥ÿÏ­õàÍ(Ã#BE(>áOªL^çòú¼žKÍIÀ`§‡r´Øæ Øœ‰ó¤ÃÃðz 2L5 Îg³³~\¿V“g0žÀéïêÜñÊT>Ù;ˆ´âW,ʪ(ЦIGôڶ՜汵Vز[mXÆC ÉœŸÀÁG×)¶4K#ˆjM²$æñÇD0BwÚ9€~¤ø£ÂšB)d’DßñúPôÈü’ y òÈy¬„tf3QW9x°l0äbO<*\€e<‡ž”ÞWò?Ý™ˆN™; ’~˜¥Õ2XÔ½5²'@Œv,F±]÷ÏHox7/ãã!ö x€ê%È `Àÿ<:6.t‡g)°ãD¤ˆJ” ’ÛA`’©*†´S,Òí§óÛ¶ vu,é@¦PþMˆ99$65ŠÛ)Aeÿ™8?{QD2iÃ(ˆòÉ” ,DxØCñbb6(#×Ç{å|{f%_€ÿ7—  iùÃ1„‰ø ùíh ¡)F…† !} Ÿ<á±óSÔß» ‰~ Ù6Ò}¦~3z:9ÁÎ噸qÍìkžu«œQæ ×2Ø›2œ UUcŽü6H!­ :BX—ÛÈØ¦bž‘(²Ÿ:‰2ë07¿Ùˆc\Ô5ÄMªHª°5B`Be„6ë&0©ëˈšnúì¦”Š˜°ªª§Â—5¶h«o±àeÐÌÐÃh±ÙsŠdΩ Ra✉±íÇ [ps¤šK>¤š8!·QЊ!ø@B˜y(—컀0@?2Vƒ‚PG»ÛÂY@5y5ù.ààxys¸à)ˆ|+ÉKO›¹gŒÒìË Oœ-ÑUÝ ¦¸”âç,[nÝÒ”°a¨ÉnpH€†3(&X‡kP¡5 ›°pâZŒ$>ˆ‡„ŠäŠ2>AI0D˜Ü—¦t4Ž —@#.Ù•m¾ LÖš(¢\&ñ3wL‰5EQ1bâ‚s3‰¬:Âòã=:™ Nƒ–=[†„¼¢DÕ—…a Δ¹x·­3 ÖZÙhVÀœèã­œ·ö.§£ÝñJ á 3žŠ ¡Ñj\HNâ9w£ZÉ9ÎÞE†¢bñÆÇrN¡9éÌêaίOé§&N×°/-E€,Ô)½h5¬ÅI V*ÍSBJRÐÍžNØ4hl¶0$A“:|g4¥”!6I67 riaj™EX¦oDbdç‹È&‘:=Å&„9žì yàUÆÆlg^ˆI#k4‹…§ú°Ç_äãQöuÁ1Î6ïöû‰¢Q€¦‰‚ùä ‚ö~Ó¿_¢ — ;FМðŠT^oäÝÀìôàÀOîš)(— |À2I¶hÏ—÷œíå=1;,¨µYŒÍDÑÈ>ü}–þNíþ°üþ5<õE¥~ÿCþJQÅ™‡ï÷}ý3êÇúv…ïR«[ûÓ{ Ã÷`˜"ÙŒ·I e ˆZL‡ œb~ :´,ß®mv?ÑÃO‡gü:t{g_ÝÛO…§ŸþgˆXÿEÍï)N5Ò@uBæ 3>˜!'×ì&¨ "×|½§TÒ&aPI']îðœî2yäú} `»ìÁâÉú/‰¡ýfmXnh”½þòLý•©œ±ý¹Z‹Cü¾b~HäuÏNcJÌŸ$.÷â| çÑæ†êíiº8±Ü¬¸³§ncXuõvH[% ž2㜎ó#«Àø±NéUý²ww´Pôÿ‰¨_ýÀYÞÚ$A¨:’u"Ñ:ušB„3)ÝÛËŸµý=={ÝãT†³¢¼Ù7ý_9YýŽÆô"¥½vL\‡-•S<¼½}oG>m(î€Óå sž¦T‰A õK‡W³ÀÑ‹è.×Htü?n±¢ÇÚÇ4ÕU¿ÐãIÜk£)¾}†€N'BCyèIÚ¶ˆk ñhF‚ƒ÷uÿéØ9@¼¡ ªèTø“¶ (bF† J?Û9sÖ@ð€BÕ!HÄÎ] LþBûŽÓ)|ÊžYxŦ% 3Â|N8 ü:‡üxR¯;£PƒÝ">/‘Ò©J%*qi < é%]Ÿ Ý"ô Pƒ‰J§Ä„JòÐô Z€MÄ~y´/¤¡&‚ÿ?"ÀÔ´¡ÊAî:@œ$x‚!OZþ6åÏ„II¸ ûžè@óÏ3ü{â}ÝýäZ×Ð 8`øß'¨38*ù¹aN¡ð¯±ÍØ&I$™& ©¤ty:Œä{3ß&Ç™FÅ…:¯º_Ê*î˜þ½öîÇó˾¡ðI2ö#ÇýšåHÝŒ¤|Ü´õÞSÑ4‚v>&Nõ·§8À8ÁœIT©‰'áãëÎÉÁð›Ñi>F àS(TḠç€!Oæ t ÃHjÈJ†a)¼ž›||±°r$¢!Û0‰@Ð!¢*R ˆŒÂÄ4„2±.$MQN™Á†‰&¢¦¢X!ˆ‰)°LLRM¢±¤Äë@RDL‘Fs’¼Q•UÒmdu[dà Ÿhç†ú1¤N‘¨¡øË¨é-ï~ëU6>>’L@ÐD %9þ-LSàžÓÔ.(÷3ÝTv[}?ò;ÓÑîà‹ÊòJ>žaò¾v5= 6ð¿y‚qP‡^íÍlmÔ‰*¥£”=×t“É® 5ËDÛ¼¹LŸ.yŸ1ŠfÉ»º¢è gûÃíwΩòùÕùæÑ†kXôR ~£tä†:@êÄ:áè.¸<¡0ËÒ2ƒþóàÕ.ý=žSoÛ'¢¥„¯2bÉ*aÔ(ãõ|^_ŽÅ›ªÒ6yÈsé)´Ž‰N”DÒ%>¡\H¯-QOq ä…D ;ÊЩ©•228Bä)ɇ‡v?Ýäé¶~í!ŒÂx>~Ð)D)_ÇùÎ5õ3]qž•YÛOŸN9ôç{y%Éêh÷chcÂb¡­ØäÀ’¥Ÿ›Èü/IˆMºšŒb¬îÈMتR\ÈI‚}HQ¯64ppmŠÚ 0½rˆ’cŒÜ/«Î8ML$TV’!(‰H|ü³Ç€i­™s.ÿ°ìtÈZ\C¹`Ì.³™õÆC¾áí<øëêü¦÷œ]®3¾–_Žb9röæòÓ›sò~—:EøucpÉ~Q†0s`¯ø¯Üðâ÷pFa•÷½†¹Ø›†¡¡–‰VÂȈÈQÚ'xŸµ±ÿú¶çøOïÍo±àœh“î6±ˆ–&šVf)ˆB`‰ˆb%(f˜a&H–%¡šŠ úSÞŽÿd…%G‚À^l§as—­€žF4¹-PŽÑÀWŒ… ÇI’>24!Æ(i _4¡¢8›BwZ*@­BüÖqC°ÇRR¿,óÀÛtp;~· 6ë\;'èÛ@ÈÎy©]@Û§¨Wó¾ÿ:Æ%1Šn÷1‘Ò‹´9%žÄ߉$ÏuǽŽÝ|²Ã}°88å!vþ%kƒ>$ßR€ø˜ˆ´7§‡_ôàì›ÉÍ¡Œìuë¸Ø©{±QÈF €·mŒ:ýXÁŒe I¢ áaÔDQãÙ‹ów!‰‚éÐHTLTÑÖ* „¶‘.Љº1Ái| sµ åá&„𪓣ǻ9š<ÚªVÈv »lN$ë¹Îƒ€€‘ÙÊ^^AåAIåQžãlèè̘¤¢*BÐ÷.†EÅê*î—QÖ‚{¸ÌX` å'g‚vs云«À¦ŠP)… wâö@€Oó`«ÿ õ߈3Ïm 'ÅÞžF–€å#ÆWÙßp'¬@¥JJ–í墑R(ˆªÆîØ1ŠíЇP×exëK¤¬.*/§cÒs‚” Cyc`Úþó5;Б„·‹©ùœß ø˜Ñ¥<þŸåßu:Ìçk)ßHÈÀåΘ™=¥ƒ°åÔU•W`羡ü>oïêåñ§iê==<È}8'¨OkK*^ ©;g‰˜??c•Ò‚£:gãgsuTÁAÂá…1ƒ%âq5ÿe ȪBÏoœ¡‡hO(zÔOƒBû–R´‘UǸ1>Ä‹N— æ@c‘šBåérÁ<ÈqI ;«šAP,8ùNˆzxà¥0²XSRÄ´ a $Âi}æµ-&,5©¢‘`±ó~ÍñÕReJCB´%>eâ¥ñ‡ì郧•£5 pæÔKO„ãSÒ6'cz€é*€÷bV#ÅL='RµrÎÉÒQÐæà!R!±(a–š³uC;ÑÚÀ¶M”áQ#ÕÔànAK²HõRD1£ ’ç Ò¡<…¥‚bJJR„ˆZ#Gø D•äÄ  £F¡ ˆ&"H$)<$SM @ÁDŸŸ™:†j šI’’" ˆ  ‚HT†ïØè!±C¶Á0˜ž€>H‚†’Lp™]’ÑB¾å~¢0H½*ïñYãKQ)ˆDýô?—î2g&äÁ÷þŽÕUmª³¶¹ü¸ zºô)RÊÕ!•TIÉ”áëÅ÷Âó¶X&4P‹!å‹l½6ÈéZOWJt-:è:N„ЯφMŒÉ“c&Æ_¤¨Û|G³0ve?êf¼vÓÕòéw$8Â=QÒ£IôŠCC ¥i]F©N!Þâ`c€k“%®ï@V?½ˆ¤#Æå4”'a á{ÉØ»}ÙÂDë½Óf@Þõ:S> !D8õT)‰ô=C¿¥2•O®Pvç‰æé·+ r04i4P|íöÁ=þA&¤‡É+“Hœ Nýe_è( u™‰”Ø?$%¸.¤‚.ƒ‚"ˆ(cÂTltªëAî1Ú’ç<'cÑPï^o<ÓMhÄto‰: \Kå¤ÀR„EEW¶ñ Òlw"PàP4˽Ï.w;c,¤QnŽŽ šf·aí9‚6&·Om¡ætj‚íœÎ82ñ<$ìTFµ¨¤ëŽÖnìôeãDYãô÷3&¬` Q‹XǙ렬6bqõãý0'«ÃÉ5H±DvÐI¼¹ˆ`5·øÛa *ƒrS÷°èL”‡Šq¼¤#B…}X Jˆ 6’ˆ`š $¨˜ˆ¦%(µšD18HJt¬BÁ(u  0 hr{:÷úÄ`Êê.8>`>Y<¾ŒGy 54ÒvAþô& Ì+”'"xQ7Âe%¾‰t³‰šW—ðÿ”ÝNÏn§«¿Œõ3\©ðεqŪ“T• eêŒ`;¸gð¾¼›ÕUƒ51ŒX"ÖúÙŒow¢]Â3ZUÈ Åԩŵñ¨k‰v÷Õƒm*JSîJN ¸ Õ¤ÄQPMÝÌlÖ(ËžE××DEe0ܲ)H¨Æ“ œcS…–AT$4Ñýøø.Ž&H„óxSÕ©™G¡¾4³BñDY0Ù2lcŽ¡D™´¤ú”ÐF¾†÷ÙölÈÿSŒwxáé6tLÇΚSÝÂa¯dʹ²@I1=Œ\l´$ÇÏÆ(ñ"kc£§È£n1ˆ‚½Éˆ'­ÁÝÄI|¤¥SÞ04-&¤`¶0qcÍ£8ÂW$Tù·tÕÕ?<ê ¤ˆ}fô>poGú>ýa~/sDüãÑsSñ‚bŠªJbY–*b¢& ¬yå>Ò¯¿Hj!’fcØP4¡JLQèA󼆨 ‰‰ý¸ò^!CìJ£ ‰gÞÇÒ¢F^(7a¦)ˆÉ3Es8 a•pÅöÀcëFàáÁG‘ª†ˆ/+j»ã¹ (=AŠˆ†`ˆ£­ œ‰® DC0äè–uf­ÌÓT´É¡tDyt¡WÌšÞ‚‘ˆ "ШP­D¨U _0`ó!¡àŒM]¢öF•¥i¦j˜b&:ÌÁƒé: >>FÄ­>¾½Èý!Ò­ë!¥i )ZéÁ|ê‰ âYb”€§|”jÊA`°Q—7ÛLæÄ80†‹ÂLž¶„úo{¸½E4 |G%$ÄÌ45øc5 E1|wu3M0},DºƒRST’Sk¶“@yðy³ðõÅa‚‚aâ`ó¹s†Y•#3Óñ—e4Ömמž{p¢b‚ª’à3€ÄG­’Ž´‡©pU!²^A b=g=%%;#èIµ†={sŶŒè C4£Ë‰#ƒ& VœóNû†TÁC±j ¢d”­|HTRS÷—-ó˜ Û}-0Ó4î( טеé‡ÑA¤ .«Ùñ/^ˆiBPâ| C!Úr©¢ƒŒ eŒ qˆ:\dzhÓ¡¢$h" $4‘W™ÃPñ³ P %æé8[̇=b²:¶2ÇlÒTã Ýcêm'„Ðè)Z&‹øNÜ’ÁEAµdÖ>ô;)Š1¸a$„frKIG ÞK˜äÆd3}¾;txL™Ðó“¹ ’qÙ†·«¹ëé^„Þ¶!*ê ÞÔhƒwÓ³Éö7u| ®†Å¦"“ªO“ƒñôø½•L)Š0(§*º"mžO—‚Âë¡Ø4Ô™¥UŽEöõΦ¹í{<&’M©™¦féL‚…N'?Àò¬æx:«ýG<9Ó‡„B¤F¿Åw‚…iŸˆõÿDÍbÉõ‚qC¦«Œæg6°ùÊ—§Š|ç3WlòÙŒËH—£óúžZ„:R!¡i5˜² §% q‡Ø”Ûbef ’Ü.Ê[°:JP‘(‰N”|sÐÞÇ ^'°–Çæzòþ½û°! áX¾Züw321èç ¬¦¤R‡%"É!m§ŠNg%I²À»£B1ÛÈ3ãa§£Î8ü㡨‡u°±œ€31ˆ4¥„’ÁÜA$ îã´ˆ„­# îmÓ‚{ûΪ>x¢ñ–fùH@ãùŒã @4¢å®,L f3’SY¶c¨yVTË㸆ñèàèû“‰vvé4AîÒw«!l2d±«ñ|˜ÆDt ˜¶µÂ›7@ž&ìaÎu¤äá73FÌÒåȉ›k[{1gÝUnÞedÃ3Ý.QÀÍú‰íÝqR8î!M-4~Wæ}S8÷‰úIBè ¢(ˆ„ˆAÀànÞìÖE?@và˜Od‚ü°'>8¼_Ó>1™…Q>-½ ÚrH°gu„ný¶c…ٌهªh&JÅ…LI ²¼®™ÉÞâ^Lò0¬¦çy „ÒWkÜwÄÊL!Y0cRÉßÐ:”ëÉEAk+ÊZj¤Çv EYáE9¢RE&”UOç~˜ù]oSPupͪÂèt­äº[%°7HaBèKõ—ŽœÐÕ&”)&ù¯}<™5©Lyí@²bèìm˜BÙ$\ ã­Ü4tª!LR™O®êŠÍɬ\jO ßf°ïrû¥ÿBM¶$·Î>×´gÖ %C@2EUt[Œ2’[il Þÿ¯…t"'\ñ}ÓµÕÓŒ*3m¨-N"o¦ð°0!òÃH±'ÚEAåî::ÄEAû'k'®ÀäžN#pzHPù»Îœñºžú Ì*3XùCtÔ3Ao_˜=gQ×=0ÇpNþ=’yîùë… ¿’ N„ï• ’€pCu"î¨slš‚ƒà§óË «úüüb |Œ_þ­Æ.žJ¸.±Û'$Øíðß}šç)„pZ‰¦ƒˆz6Ø9M(†ì‚êì/Ý&ÎØ¿¸ÃËΤòé: ê­÷ò”(*„=}qF©ä²Clóé}|>Êï*SÐLà>ñeNƒÊšÑ¯€/X,sÀÛ<ž•vD9/2N“°9 ð xïÞ,øóÓê3ewž¸B…Ê«#"%‰ SÚxÒ›IyœÿwQ´E@m53³§Û'Õ7Ê&ºba÷ [BÝ1C®+®¦ó&#C}ª¶þÅQKçßu àˆ1˜º¶,i†ýáç¼;Ù窤÷Øì”Á÷1SP/µØ€.a†‰²´ÉÆ’(ÎÕI *³F 0Ò„ƒ“kÙÉŠ”f’„ P¼9CUŒÁ¥A»5 ùΣ´áºÓÖOl ·ðÇÛ:Û‘=²áÙÒ;WéÁ½ÔR˜ÐzƒÂáåäyt¾RnšOOÆižÅ{êT6Ö†vPGÐ ˜ÇÞ臠¨fCPCŠœXyX@0Ïp’€cÚ‡½™J#£PËú ±%?‡L^°>»–ÊÙΜ €„!È^Ôò‰ËÔÄ¡‚ìJŒ@ PK@‘ J<Ê¡ryô&>ÃV}Ûqñ‚'k×­üÙsE ÕË&Sªg‰ç„ͺéEB’¢ˆÒ{%õüYO\j1y|v »’šâC®TÌÜT†MãÈ9MÈ킘|¨yF;ƒGlJÀã¹Ø9™E$^ö=m³F#ÚéO¬Þ}ïX)™Ø„©‹€gjå¯ñâø¾‚¡]µ7çÅ„‚…4¢—Ü΀4è ) &Rh!˜&”$žC¹Û&À¨¯—«c<ÝV¯ZŒÁËä>¬wªªôÎQí²œ;Ôtâ \›Añ÷ú§½í7úðîßo‹ÉàûœÜÍKGt5PB%©î]ƒ§ŽñÒGs ^eøs;~±$ ëÃë÷â¸&Òö©ÀÆÅŸŽ3Iñ¹8“ò™ŸªT='ƒTLh=O¢ A% ¡$™œNÎ ´Å¬etª³¥þžGŽòq×c˜oÅ€Ù¼uV/M¥¡¡k»Ï.˜L&ÂåÁ»ÆøíßM=;µqY“k…ÝêË( QÍÚÎÉЙk‚œ(åë/ØMBhc„é–y©äU·g‘>²á]ìãSÊ™6Ð%I5§ÌÌÖªÛøÑpOng}œKÔËöþïPñ9:Ä“§ä¢¦ˆ=ü¸JîÑ3¯ ¦œuSJ?r\WÃt]zY&—1Û™êr·­™Ûô®=b5ìƒeÍÏPsØu~0 ×(½¸ƒµÆi6‡ Ýîìã¾üßnb½Ÿ¾µk ]u|®¯¾ë:ß+”Œœõ"4SÎm…õoly¼õêŸÚju\"…¸2BɾÁ™RäsÞöJêiJ»§Çù©éKp¡×ÄZy‚0"ñ3/—%wÿM\±Ýi Ùg—kÓð©u[PÛAÝâ¤ôFVv¦½â<GÆÜÍ?£qßž{^öaª3¼ÀZχ’: Zôƒ½¿Ü·ç3ò‡"P•;»Ç š{ae6“f1ÔÝq|>QŸÍÍé»sËõÔÆ \KtŽC"ׂí¦Éh H òÑØìˆ<\&]óˆ·Tθ™• ¾ÝªÁÌ; ¸˜‡)$’ ;¦‚ªôÇE°q'œDë–ìd|A¾ïݵ®ŸF¯]ŒÓAŽË0p']ûjœw’xî°üœÈ9œ¿m?O¯™6¹Û±ÕGaDÄÌLÌDDË)p™ˆ ™ek ÉÅÙ5¦ƒ˜Öû!ƒ# ¨ÃZ¢M¶zXõï·C30ê£ç9D,æk¯ `a),Ê#ÒN¹6”n¾›ï‡IÄ~[o²ï‡ 3¨MééÚûäAa–â ‰ª5/ÛŠ.éŽIà©'gÏ™a.LAÜdwx!2oÓ²Sm›híËä52É©›;3rC…#ÐòKf<‘&Eϱ4$—t†6Œ&Œ5fL}^d™‡d, zàpA” Õ(«X€I™’'Fg¼p¥‘«°Ì­ÁD€èž.·9ŽPy0¤ê­ j£ T%²œ‚ nÑMDM¤+•&†åÈ@ààXÀĹ:•6á‹,3RÖžÞaßf‚ZY!ØL›Y9aÆ<œ0"ÊDjî„fèˆ\Á93TX!ɘÛ7h2—i\óˆÓ&M‚PѱœkÓé4Œí1×za «ñXêÂV‘¬9ßHáÛ•ß{kžÈg芢‚&@waù$¥Ë 7¸b4ìÃÉc¦Ù³3¬&k¡8õÚñtÜaŒ†|Z|e‹Þ¦ÍÕ6,±PÉ‘|³fŽ.Q›T¦\Ô‰GâöZILñƒAÐüç=2ÃS_x†d±Q°ÄÊAD2í™7Iúí]³9§H~LÉ:dªq¯|äá6 ¤gt¶«qÅPBn;ÜH»-‰l]78i†á Šg—t›pØU¼bÑJ$™fÌMñN!C>EDY©'ðýÛºf£nÛqC68é0ÐñÚ[—zøÜzpl¹×N†Gs¨a[yx„’ˆ¤²¥†Â YLÄ·8qºRš5C³Á¬tU­ñl0æìبÀ•ýøn%iÛ¹…’”›D •®‹å¤ô!¤ÆÈ3Õ×3N9Oñãý/0‰ dÖ_ QÁMÛSK3r™›^^‘µÕyãÝ®¸³ªIÁ n;íwQ¢‹œÕ¶ñ8éa€Òš„Í‘8ŽÌš!´HTÍ)FØFYË&¬7”C0Å&­ZF)ÊEiû²nFJ`ãŽÊÝÚyÁСž¾]x™†egZkcŒ<¥{*Cy¡ÉÙæ‡;7I†•FfárÁ ´Ã¥U!(Ȫ[¯ds­½UÊB&Á™Lc¦ ´1*!ÊÉ[;%#ˆ&àcçã{ˆçj³UŸŽ3a5°Ü3†‘h·Zí³l׎ÌùÞ‹‹Wmל5"[+{“M4u,é‹ivYÆtƒ ê×+Á¥ŒÀS0yOy·$ßWÏ´|¨,NÂw°-ÔÅ4oÆ!‚šBС벴d ê “5ß±åê8e!×—~§úni'(HØÜ‰õ,Ï_§¦ØÍiÄ—)õÐüÃqWëljüFï˜Ð-ðìÏbúoµºl ÓéÞÌΈ¤$ÌÏf aNeõ=ÒüEcí~ ê<>†5ñ„<$8J;‰*Ò“ÉÇËË¿™—DOœ·TyŸ=/B±zâa룴” L¯a¾¢„^1£™x›†ä®€€ÂdšÓt!”ë–x®²ÌÙs‹“:„ )˜‘a&@èÛìᚈuÄY>Ž9·´Á´6PÐêÏ¡ÈgÆ,c”;µ9ÞzŠdã¹+ šXtd†1‚›iQÎØ Qð2 @з‰¼Ebe¹ÍqÄ®`ôˆfÃ7fm&9W›::Æ(sd¡`¤fÉϘÕlˆFmä`eÌ4˜rYو룴êP¡Nöí—œïÊq}áAÁÛi k¢Nún2C&Bó–bYa2Ç“®æ÷óXy;sE¯¯Š‰ñ“[®—h‚²ËÄÆhœQãÊ¢ÇÖ±Æû7}3£¨ €–(,7œy`k—9 ‡J‰­Ø2!q:¤¤N“sÆ—]î½1„±6@E*ÝÑ-æ*ï6sA»´éØ'™li«³s*4˃ÑÅj+.Œt_{í]³;êF àš:¦NJxíÚà]Ù•åÆáH&o vëÅPå b‘'Z€Pܺγ[÷ôÀCŽÊãÀ…ì(tÃ’;k[’¸k"·$ÄÐÙ8QF6s˜bZQÅ”€m ÐëÍ¡ØgrG¥ÝÇnuߺš'V[3+†kªMª•‹ÉÀ […iŠ:Ö ¦YØeK×›bà®±(ƒ p¤%âC“å<ä–nÝöb#ÅÃRÎà¡üÀÙQ¾£Y€I¦¬T¸. ÙÖíƒø*eÚà ¶• F)E•æÍ°8å¯oLõËÇœ³WóBlÀ/©'ÈóÌó3Ðk¬¸9„ä¦-بZ»mͺ0 #l«VçnG`…Ѐ„0ÈJ™Üѫ㧱ßsùL…Û.ÈÆ¼ï´âû‰×kñœÖNÖcNö»›!ܬ>˜’“¹ÄñŠc‚ RNg†'Ä+¯)î‹!,Òi]’¼®^¹M0¼£mÉDå8ù+ ]Zéptצ2?LìC3¸}ï²¶*ÚãÔѵÍb9Pàã }EŽj-Q—¾É’W 1ÍñŠyã}¹¼>ë¢1—iÎ îîp×-ÌìÈ›z· g{´ÝkÌÕ uƒdQ¤8Ú|ñµmàå(`Ö•鑈yàïEÝKò¯‹…AQ¡!Mg˜äàâl@ö]0ª\›Ö1XŸO.m•ÚM¥ÊðÞøâŽÇ$/X’^+Û‰†o‰žH‹”I†·eƒ|ìb™nAáÁÂK!yÍ@$ZÄK¦¦Á1Žã§Cxcsf_ƒ†qe$j™UGLÚé-ÙšQØR›*Év4†¼;Ü®¸›~Ž€j³&¶ƒ9à¾[L\G‡t¢¶£,å,vÛ‡1I‹Äv ¸Wƒ¦ “Rh“°ðN† J ¡Dàê‚ÂÞêY‰½†"¹;‰¼§^GÈïÏbúI1ƒC§vcúÏ]—ŽOvó!ðHDý;$öšj ¦©–LÌ:fbI–Ò×2d¢˜L„°HpåGRL5¥V•&bžBNÙë‰[íÍ> å 䮈ˆê;3t9ÝôÈjA ‚Ò]WB2ç+„ÎM?]š«YfÉ‚˜w"雉:žu–Yk+¢¬xu]BIJ˻½ úI StyÏ$i§¢ÄO¤6iÌ("Ÿ?9ذ‰OG‡¯¿ÓØ'Jý¡^ª"øÆÐ ™¨"4jíVÁ¾õ¹ƒ•aª£6:nÂ1-BiLÌ•TÀRiTÃLÛ]ñ0M(ĵeÚÚ(¨jÀ¦1¤IÇynÔ#®Y»x19L Ù1T$âÍ” «VgZ•wÏ6…8]k“p@PâM²Y¥gØÁ}K'Kæüß•¦«³ ý¹ ܦ s³3x‡ éå “0¨f¤e63 »i´Îzc¦!ÙY‚ª­ª{ºßM>çRiÕñö9Ã'âT8?Ð ‚ÙFÙ°&(k§`w,IMò9„3övLr#B© ©—·5÷0ÐîÌÛÙÞ‹c ÿ_Pnͦæ[<8\çPâÍ`Œ!Úm¡ÊbËÍÔ AYIÄ`f §X¥Ì!Q9³’¡‡éc»Ìþ‰Î‹](nüâb«Šœ%4\jíÇiÚÊcX˜ïØLTçœó!œ§RyÉ-Ìcª­83&ŒÏ"ÜL½G¿7xWÎë8c›/œO…(iéö›}=Vç,~D;¨zMÛÅ;S»_lê\WY”C#¨ˆÖ ë† ØaaÊÉžaÉÒ×9‘]dS›² Àñ5ÄLªŽ ²”¶’†âò±¡Cá ÍÆæX½[kZ¾Éž˜Ñ 9gb ‹ŒõàŠ]±K˜çEmŸºf4‘ní§d¢uF¸*™9ÏÙéXF©ÛÆŸj™DÕïmÉ’Ö‡•ϲ4J qp²n¨NmeŠ„l \ lh…¨ÉÑÅ `ìÜ·5H4ÍVF¢\ÃåÚ“oôFtüÖ°^ñ¹Ê£Î9Öp`ò¨äQÛnrãœSi¡¤ußJSîUôc6÷DS†p=;vˆÀõª!ã— \Þz² ˜mvñ¶·îý–:ñÚu¹“mHBW\ ‚’îÅr’KnÍžŠÀ¹ŒÔ¹3HÜ}¿ú}xþãTŒâtî¢C’ŽåËtÝ!!££8…h’èÿ#8ó0ÕÓÑ+"…$ÌÆ’áÔí¤;MEšMNÚñN/‘±ÙºL“<¡Ý9•U¬d.©¨y”Å  LLg8¹à"#) MjÝ*oy„‰U‹½žñ†6ÔÖp×­ ´¤À‘rìêV Noy£3¼I!‘;Ô”IôdòT¼šî3ºdƒH€­ÏʾP>DÔØÌ®å6’Ç+“‡Òk±öŸ3ËÀ••ºì7yó:G‚ËœúéDÕ¨­óüÑßòOÞÑ4Ë4Ë=mšäë¢y¹IÕš´±+в·+X•ÒI¡×SÚëkŒ¬<|ø­'¾Ðü)"ê$çK›Ô¬ÊÖùg7ÔoŒN°áb:‘T q<ñ˜UºåÝGKOÑPôü©ÊÄñu+\>xÆúßqÖ^k3¬§®oUòñ_;ÞdámóÒÊ+O½;C©k!ÑЙ .hºgjÍôNû„UÉ'‰ÌTmÇ;ÏRnS;+Cñ0¡Ä™)CÊgf5Ú!UŠ1º32+ÊYŠí‹—ÑT/’Ïcž ~xI1ÜOú|Lœ¸9ÒB!Ù±%öìäS®ÐD¦|PÜ'Uª*MŠØ€‘âà>öqÓ̇­øiÚk­#í¼¡þÆc#+Eeoü·:ŽÚ)ìêõb všû¢?kP|¾ì1C{ïs-Pæ¾ï¿“à 0è•h¤‹NävÀAõÀ>©×ðuóÐ=ò‘ D1!M¤¢Ò™»0@Ó¤çdqp‹pòàÑØZ6Ë’‘Ö@ç’LqgÎ9åÉÜr'’3f HA„‚!iB`$ˆBeHabB$`˜X"FQe””•‰“4€0\éDv©h•ÙÜ™N±‹ŒT¥‚Þ&ÎÕß]k§Âé%Òê_­t‹¸ëîkWœæ•=ô°ºDK3¢µ0<¤>ùvl¿0åî’5Wx9‘ªuzÏ9•8xÉeTmP£fòZJÝ<6rø85,ŒZ%C8¤K¥dWO5)$ˆÂxfŠ6ÌÔÎß)茷÷¼~D‰#T‰³œ8D¸ÝŠN`1K|¥™ž{~¡ @Š‚Ú¨¬£V§/ ‡ˆŠ¢/€1$ÀÀ÷Í×€lj+»Éè<„Ї09uÕADTS4*3UWùv(ô½þAïU®ÿ7wzv¾/ðvx”òp9›d߭†‹Hx“ÖsŠqJ^‡†·7|G€{lkÅ J;®ˆ)‰‰¨o[ó:ħµG耤ýä&îsLæë¬Å!˜SõÎð&XZ…#¢¶ÆŠ™£Ë$ÂJ6LЮ …IuA…-"º'ò@¯4¡¥)@™ ( hY($”  a’H…VFP¡¼Ep.yé€DLÇUÿYAƒ ˆD«ú%€ ó—aMH9æÎ­@ø -b{'~ÔèØ 0b@°> ɶdÏ÷⦃RH"xñYm$••’‡˜D=R#Jõll>!ÿ|‡§¡Z>6™*LA˜¢¨©ÉÀàKîw«ÈO$gœbðó(%^yƒ×±Ä…5E^Iìû bA“]sã­L1TemqÃP´º“îì'’ÐPšŒ8€¯›Èé"¢“ÜÖÆèx=²Ó¾+æÛ+ðÐCþ°‹H 0DB J†CH><_iIR½ŠŠ"²] ïˆm Çï ‰®æhB(PLÁk7@ô/kƒÏNrrTõ‰ænh!(:è"çDD3ð~b‚z­gÛÖyï#ĵaÝ9‰$±wùÿŒO„u½u¾5|þFÊ üñ¿hZ§l¾Cû˜ã¶ŠÆ­NögÙóB !üÁ3äx§¯=+–îl…Îx+Ùúc°›•Bܰ’@*úà‚Œ"ÌA”ÙEˆKhtr³‡rŽ)ŽrÝ‘´::‡fŽ B8s³j;‹Óyã¿ó£Âµ¶T¾)¥ÔÉ›‹‘¦ÖR=(±eżeÛÄãÚÕ)ÓÌˈ–°$Íáì·q5§5„Ë»«b±bÇ¥Ix©ZÔÈ:H*ÖiíJ,²^"Ý&6zyd®œ»»TcX¢n^×£œ:4C§˜£H pŸ{â•i¡½ê`ÉfÝÈI¹ø—.áG„ÑoZÄ0¦"Úl‰¡>®LPùBMÜz÷–ç³àïÃÄ8aqéƒÌsåÍrîÇ«±`¡`V˜|Os=c/Þ }#b…ט2F{T°Ãç»BêÏ3®0•{‡¿”“rgtίœÊé0eR¹Ã>²ì ÁH⥡Ÿ,ì\±’0˜mz |—xõBIÙn|Ïv)Å~›ã-öõ¤ÝoºáóõëáÑÉW²^a“ªxÑÞ^£•Ž©ZóvãÊ(N2w‡«~¦qÎ4Ĉ¼@ÖPB%Ç€åar¨O§öË–³ÙúM¦åá8CžZãoBDV_׉HO|át­±n@ñÆýXÏ{ŸѸê!!éȇGaYN%´èÛ â0ÌeWazö´BMàBlâ¤+dÖU¤·Ò4UøµãÔ¤µƒ-H!ÐwŽ; è§Q”±Lb3áÍ òû`h½éÆÆ»8ëO‚ó|"àx/T¨åœÉŒ<ÖV rÓáð×ßQ>‰$ÊÈ”—àœ¦Œ¡=EÁ’NÄ yÃ¥´±¹´ÔkË·e Y¼éÒ†‚õ‚p èz×`󄹟>Ï=“·d½“9íëQ>dXܘÁÅœSq—o=Ù>×§™iª± ?/…K¬9˜tã¦T̸^5‰‡J%ɹ£ÓŒxf·×™fÜâAÜI¡“KqZ#ó¦ ”/u¼h|ó80H©™l?uÑÆ`‚"Ü‚³Ô—èùŒà;GW’ÝsÔ¡Î1-ØÆu%úâ#‚—ØóÄ_aÛ·œ´`»w¿X#(AÊ™‹wx‡1§Ý¹ ñ¾$¿/Æ Q.÷'‘JDj¡0‘äT(q?díUwxu…¸Ä^óèˆÇžÓ æ¾b^’N\<Á讽"÷¿[­öÀ­Å8Ⓨµ™¹˜²ñ:ÙYÝWŒ ¼ždòÖ9 ˜.Ãò]²pMç‹ï~9Oѯ“¹C´MqC…‡t¢HR2¢óAòî 4á"©ƒK»"´-@QIBRˆB­"4–@4%FΈ4áÚR† Cù~|ðòrÑ´‘4 ШÚÈ…PEþu©®*Cçy²Z•&th¡®J|\ð{Êè¨ µ™Tk3åæbuJ›ŽC_”løŠˆ0W3 ÷Bºh!–Óóïùª§éü0ü.¦Ê›ESHMu™4ÅýÁUßZìÈX©S'À§v”O®J!GaõÈQ$'}§Ã}ݰ ’J‰áÙÞøIä몱•(¢• ” ¨ „)q+΃TRà c£@ù”t…7¥S[ÀÆä³ ‘T,QDBD©‹ìP=Ð>õ6O2/Ï>)ÖÈëöfÈDTÀ}PÅoÏžÁ€ÔŽG@zÆŠ«MgÛõàÈ©— ¼óSIE!;y€ü0‰ô¼Pí•]m½Hu^ùÍ#ìOÔʹ%({!r@¾¼UÔ¿ Ú é”êêu€ÌO¯—çB_vYûMLõv 2~n´=?ø<•hHjöæ|@ý‘§êˆ ׳Ϻb‡DFÀrÒ)!Q1‚R’q-·ùç¡‘.×*®$ì `½Dt(=÷ßpË1€–È£ Ø;"Ð…H-& Os¦"-´†$èîÇÌÒ žysÑOQU¶c„:–‘Ãþo¿?°°úÂ'[l¦ÁûOtZ7N¡Og¥ù@;ŽõGÄ|³ömDÐH^•L ÿ€t@êÏü†×gÇUù¯-îdõþpxžLŸ’gÔ¯×7õãŸdÌßœÆà§HVd)ü±ìÜH}µÊlzi+9ÄÝ×p%ž~É4Ó˜ƒD“y'®,’Jq”ßF(r“-à)Cœ¸“¾PžØ—pDjxXP&•†ÁÞ¬·¢K͘ÉRh2"o‹-CGT«¡5!vŸ;¶à “IUÓëš=pz÷ç{‘ÀÁvà9l‚óÞ|Ša"÷XÈÕ+ÙÙ<|è¾q’‚£¯Šã¥ÞÓãí’@Wê@™÷‰«HUžqʨ ÆIZ–С4!ÇeáÙ5J—w¡0rÛhœª÷õìñC¤&‰³¤'iÊJNÓßÔ•šV¨lH|\%¡UP.¥"¦`Œ&º8¸ba3JU†fBé]n °6INŽpã0B¨ 5û¥:ƒ°¢×Ý×þ÷Ý:Ãe œ}ü“ÎMqÄò8ë[³×Õ$ˆ 7¦*®a×SšM4°—oÏÏÛœ uŸ¨‘í‰$ŠT‚’¡ •F ”bY‚•PÛÅNÞžËÆø/¶“Чé•Ï×õ{‘íù¡×ú»ùýüú©Ä AÙ½P†Þn…?îPrsÈA‚=Ö€)î" %(ªU¥ e Š8qDzF(¤æx>Sâ9Ö½$ûç&|ú°!`H_k–\Ç Ë97¨Åý¸ýQÞÇjƒ@NØß‡¾Ç ŒÖ 3-"cT†v<¼£¢ô$1æ;\ƒÄf´ÔÁ2›‚µZÝ'¢Œ\„§,2Þ Éf3õëz¤õÎÔ CI!C·?'áðêMà<ÅlƒKÄf[hI“£fTÉC©”À]AQ{ ä B¬ÈH&Þ¡"½Ã“6 1éu×EBL+/”bŒH»ÐdäòY"¢§ýÛß©ÀÑT•3RTDÉ>lADñÁ2•d*©tqΑ±Öøö¹&Î$Ô%Q Í(aû$¢/Ì=Õ˜u u"†Ý‡ ©9CÆNØûCÑå®ûÂ#BÌ4@IR¤ð㊙*©?ýŽ¥2È^Þ¿ B–©)çN“IÛ!Ätb©5¿tøI¢aýCHèMyhØÄ ï\ð'T1@z‡Iz±Õ¢ˆMf*ˆDãWöñú#:ð×ÞÆE/d¤E!Û)˜_g—éû³Â©Nš+§9e°#"*‚‹Q.Â*cÅ~Ú/c·Ðq!|¨¡È ʾ1è=Àò»ƒöI² ’ÐS@ëNïy†BqŸ¤ (&xHäÄ éR ‘øä„?4‹í^`¨“¸P¡ÈÊõΠ"ŸaùM ÜõÜ4iVG„v\ƒÞœÁ•ÅM@@ãä31™šÇlP#zi6*3‰n>6¯cÄà¥ð¬îÑ >P´Ù™gvS$Ñ`ÿ6’Þòª2WnØ…S©hª])Ic,ßgiÔÍ“ÃÊ0K™)œ¾ˆÂ¦IQÙ³Ô®¨c2Š$Üpåw›À@bpTN³¢õƒë-œ”ƒ2´!|oIDòFÙ¬v㿲͎í}£·=?EÄæÆ¨e’c©¦rÁ!ÚSwhÊqÈÜ4ñcºtÄÑÄ>°ý§PªeaÞÑlNF®«Œh„'Rv¼ÓŒ\™‹”.ön0(‘ÏŽfgvA¬ª"[žG(LeÖ!d¨»ÖI¢òæuA.bfq&ËÙÛfKC1¢É­¶éxœ,ÍlB“%nUn=°L]¹A¤2ï$xbAû~XD “ 2L‹„.]!€ÚóÇKç%“|qÞ¬*± ô®†™Ôþ{S"[OHíÁ•Ö¡ŒÕ]K¦RïÑb,åfK¢nuDÍo–"ö¶IÒt#(6WI“»Žûpx5•âøøM›ÍÜÙ¡*LÊ’ËVÞ¬[hâW:-vuIb)Ó•‘Ê)¼60’1²D#‰êS˜¿m`ÎYµÆ°îì.›b~0R*ª¢šE33™¦+;‘|pÓúC~K}ØŒÉ.ÛK'Œ6Þû7{ºµÔÏ1%öœ)ÃõYë•Ú6.Úáë‹ÁŒb©çbp¯ báðΣÉ1£öT²eGLc¤asYÓöo3ž¨Û¹ ´aÚ'º)3)m*@也MV*^Y :;ËsÇ=ë‘mÛ•žiÓÉ+pULŠŽ± "-fû©bQ=NJ;åÖÜòì¸/=¬¢†CÞåÑF*Å-,…"±ÃÏ€“lÍ­¤•UETLÖÙ H$à_fÊZÒ¤BÌP&KË’û:þ¤ópPîäb(qˆ”d ² ßbˆPN+8ªª(¢hŠÌJƒI¢Úª1©³¬ˆbB¨B‚•Z ièytÜ?âðûä)•7—"„ ‚Lï0ÀòÑ8L®òv€ô(ž3’쉥PcHzÂÍà;:Ÿ2÷èÀí?' pð)¤—Ÿ£ŸR¨ *~t+h „ 0–& ‚1D)"‘ BˆšŠ *Z`‰h ¢ ±j ¦ ’˜–`€¦"*ˆ¤!–šš¦H`bid’% Tã•h~B™ó8¾Ç÷IY2ÌÇô˜êG ú;0ÌA`õ€u†ÂŽÀ§ý8Vqöõf¢)™)üþTØïWÜ‚ÿ$óëòº¤C±‘{¼»«¤ô$å óqöHi!Ðf(©áænKª­šxž‚ýn%ÅIAÒ KÂu„²h›1Ĉu^ÞW4hõF‰õôïâƒÕ·… oÊõs:D=|¾¹8p˜ž2žØò¤%€Á5_+¥IrDÆíêƒÈ÷1~IM‹¥¹ˆ¥;ðsY›'%dÂ$¬ó·¼?ƒ"±¿Ž&Ò… MHÐ/68C.:edÅÈõ¸`z·‰0 4¡±ã%G#ô0’X`q€8! ™<8û—ׯ»5yiŠ/Ÿ§öѼ3!ÒI,°%ƒ^Þþ²Ì寒*ÊIlCæbŸ4{sMž[¶Uc Ï=îg§ã¨çœpµÆÿGdÖSð£{L“<;­8îSo(ª>÷|+‚<,kÛÞeñÇÝŒÃešÏ>tAâÞ,C¡Üw·z·}ŽÓ‚qM¡]­‘;†khqÙÄΙàé†z1eä7 Â2ïêO]ð<×$Þ>ìOxcœÃu}4'Å`Ï ‡5 Z‰¨ä²¡cLOxhOMóÉ,—Í! iÒ&«ÒÔ™–ž;O0“!Ma¥¯[&)SCSåcœSÚó¢%‰<Ž{Ér:f|´êxë¡A”qORæy°„ ¬xmpↄº‚Ʀ²`gf¬¾X'µZ‚cË™çÒ8Ÿ†Ë­sˆ Jížöíb}×[¡`ÕI*±¡m¦¯бžõç\á(î¤\ª%„Zt¦‹¬ÜÓıƒ³Åo6e2»|[ËÉ 5Õåqœ³-'CPùÔôîK´ÕÁ\Ôݳưh 7XÔÝZbQ”5¨qÝîçcÌ[ƒã‚-ÒžfcbÖ¹#]\Ë $¼ÒQ€ld™ª ·i ¾5â œ?2Ó æV%ݦÃ\Þ|мP3:áóûCçžÈœŠ€zï²),ðPw!;8Ž¡Âå󱂌ãD£Xþh‰~SÚ!âÊœd(¤ QWÄî>J~Ÿ©F´_tÇ*qݰDñO䂌¤ ‹1zü„ˆèMÈ(ù³F‚ 4H˜žXD Z”¡JA¢E¤š ¦†e QJQ•ISBˆTv~n>]ž' ¥LÏ%!Bi’\Æ1Tã.f „·!‰ #¿VL‘7¬cc5Mzão='í¨C„+ZU(E E*zÔ†—R…>§æ ë·—"c÷ÓÄôfTËP0Cf`PQ{ð TáKÆÓ)‘J=Kßì´)Á>Ï“ãÇ C#÷á•ITÌÁ¤ŸtdîÅýª£Ë¸¿yô‡/Ûå:¬ùPþ† °íþ¿Üd¯íê¯$ÌLO²‹›:ÃD)>gý³­±MæBÌÄ´½S­*š"É,õjíœyç+7tºø÷ù›ã­ûÛçÓt Ì/H;ƒKÄq褶ƒ@àxÃ(! ¤˜ {°è)S ‹¡Ñ ²@}Ô€øB|½@ÛLÅ´ ¢ÂZ\µ2…hõH&„i„ 8Š@ѼG!¡h(éQӄдÉÐ&!(¶â>²tºĚ΅)5õøOR€+?¯|Ä:è¤-™,¨Hˆ ÃÑÅé‰Òy!AG’”$(¯_=Ë2>„(@›d`Ä^‹õïÎô@„Ãã'¸^¢ÈÎ*@+¥ÂKÔ †PÆRj8Æ4f]³Á»—‰G¥^¾C‰÷"cÌ<ò§ÜÙàp2‹q”‘âNè_fÁÒ>ƒ˜â‰Æ9\”w¬A&Ø€ø‘^(¼η`øÊñ Á#£G«Ðx¹šŸ Ö’‘ʆ©JM *iÓ@ÑE‹Pit2ʵJ8.ØÈŠÒ¼HÄ!‰ f$눦…+Jè‰C—Gw<£Ö;&“C¢`ÙŒ¥8€¥1ˆ¨ÔhÄK¤¡Ò'BvËT8,à1l˜)J¡Û!¡(E¥ht¡@D j¢0mŠ LÉ¢¿\êL>Z%ø·äön›Ï]ޤµ)üuà~¸vVÅžñߣ `¨r]d¡3¡ŠÔ‘ÒqwBYç¹S&’»{µÕ:;S°†¼zöyô`¶0>Hu2:² »”?)D.(†l³ÈÖœÞGQH¦úg{“öŸÈz¹œÌàúýï¿Éú§)wnÆFÛ%׈M™-Ùašeò—¸wâ ÒX`øîZ,Ö!×eªÉ”íþýÄz44×Ãix(Œ¨Zˆb‡~þ0óÔØÇ7]:§ž ޽Üe¿ I0=2Q·á›AJ<2ˆ:Ì­Ž—)UÍq^Möz,»=X*ÄFìÄn(Ãz#ÕPòU¥$Æ}òvUR˜ê»*àœ`Èè`N¦\•ÿŠ!ÃÕw'?W3btSOH~S¨8èy…BÒÙ']iíÜsé‡8˜ö $Á×:?“3ÐF¸dŒ)ò“¯kÁs|rj)=p-~y7©)va2ªšO!í0~(ÒúLà ›Py£ªÂMOÅ“MùðÿéjŽ ß“éËíöG¢Ž·0Žèì¯04?ÜÙB*ebŠa‡Y×£&Yèv…vG–¼,ƒ Áz'@G¨Äüz1Ñ%V„Q‡!ĈŠÿ†×ô'¨@àDÊlx§¨W‰dW›Òq'ÙºC’P~’ËUF,åŠQ-SŒTšÔYõçð”1Q(~B¡Eþ-zˆÀ TÈxýeþ8:CB‚…îÀÔ­*︀z!¤×¤’DÎQ) ”!²wwZZx¬<`°2Ñ_Í‚ñ„꓃ft×õCД#Þ˜ÁFŸ>&§µñ•(¡bAPÀÔŸ¾0Òcdï@Ž›?ù{::|`,Ä s!§D!4.‰ pÅ\³€i·:A‘“‡ÓòC®®Òóë´û0”ðŸ”MÎçßÞÓa=||Ê}!¤Ó°=€(J¦…ÔO ’” tóáÇëÌ9pÑžøå:©L…6µ(o2šÐð€èJ|´´~™t({ŠD"”>gH |@t t*p“P®B;K´+ÊQÞÞÚˆ7ƒ&•¡Si0ΊtrŸd<åì"ŽGÉÖªèÔ?â‡HÁ|„§ªé¬£æÈª i©€ü{8Ÿ¾(¤i¬‘éÍ>BFÒÆ’v7âXPr ·ÌœéaݹŒìÏÙ<®/ÖHKÕbN¡ŠñÉÅöÁäjèdž‘KÎG!jLb‚dJ %SÏÑ’”ã÷‡›áfþ½dèö(ô¤£Ò- “ÔUËóÑ  ^ó&¤Ò5™9! †H !ÞÒu¥“2è¿e]ÕϵŠàö]]~äM„>)}&büø¾éÈ iORš]…&†„=‘ˆˆbZ‰’ÈëíÄÌÅÚMþ~¥×Ö»þ¾ã¯¹ÖØafa8%‡Zä˜ù!´ÖF1 šº`Ú‚;ËyÚ(ƒÔâ!¿ F’%Š¥‘¤Ùw¹ŽÎ0¨Š{1;þÌ;·›<ÜL00xhÐi;>¦œØÒ}!Àò(cÎìì Õw|´²' L)ü˜"R":ü x4äIã)çó§’ˆC€hEL"‘:û¥|ð‡¸‘1†„u!’E>‰_5HÄ@Ò4”':O!4ŒH¥4’™`òUæö˜+ñ€†Ü!(á˜sŠCÄ€ô:ÓŸ—‡Ùù {á~ø|¡ÓÃ-åÒw¬vZôóàŽÉ·¥X!±Û²“!˜4‡À¨HwrΤÚ&©¸/ǧîÞÊOõ¶dįìR @Òì•Ð7ÚIÜžS %ò€þd ç”H4P‹g3”?¨aƒP l;쯎—ªÜÞ< Sî% j’˜*ÆO—{I¤dT`Nñ¯ìÈ}_´ýWÁÿÅý§wŒÒs•6•kwUEo¾»Íâzšb!îeÜ ™È6Ž·Æ~~÷wvncøFiâhšb(˜¿¿±­Ú0߆C?{=ßv‡R›†þ÷!üÓwàè…ã d !E40MT2AõÎ¥:]ó`e€¨ó˜ó: ¢”ˆ…™‰€‰‰ˆ¡–f$™šHh–ˆ‚¡’(ø”ǨÓ'¢W"2DP; X&Š "éMQ10QTz“%>Bd¨˜~ö¢a‚†‚)c¥4Ã4ÐRð‘:]6,¨SE -&ÒèR%Ä1ôÞùÉä8™€ª‚ØË$Õ*P(ÓÛEéœ8E e.Êû°kŸªuä'£„Ì×mƒ·:BFÓÞÀU0g±ŽóRpÖ€dN¨Q)?+ËuøJ?¦†t»Ú$5A¥¢€"i_Ї|)ÎÈWÆMb£§[éúè‹×J(Ò*ÐR¥ P-Ò” KHДCBR­4£@1-!¾BŽ„¡BŠR’¢%‚ !$‚€¡)  ¥‰H†ˆhX Fˆhš@¡X•HŠ ¢„X”h(¡hiH’R¥ "dbŠ¢‚‚‚‰–$ BŠ¢•J¢%Z”¦‚•h B€‰D¢ ()¦„Jh „)‚!¡¤R$X%¥ª T¥U¡H‘ ŠJBˆ”) B¦Š ŠZ ª(Š)h‚ˆ˜€¤ ¢ Zh% H˜„¦! hˆ‘ˆ„"¨‘ "¨„ Pˆ@¢  ! ¤B„ªˆJ ¥@¥*€i) ˆŠT¥¦!JE‚ªU¡J” ™)’©(’€(X‚„¥i)R”š¨šR–„ibiJ¢©JV%h¤i–¡¥(†”(©!(¤bU(i¦ªª‘*šB&ŠA JEh¤F%¡Š") b¡¦hZB”h(B„iYª%¡(†©"„ R†$JŠ¢ „ª(B¢h(ZE‚() F€H•)\cÊàgA8rïÜ|dP©ª¤1h‚¢&€‡ïPþîJt’ hBÑèt:'$ÀÈ~‰ûá¾Ñ˜™ &¿>“m`/Ç¥àðöObO?ÄkŒv ‡WfvžœC#œQ:1¶âeê©§­ ÓY ŽÔiHÝŽãtDtMØéâ¡:]ii(®ë]c¶HõáÅíÍ'õGÉfrä@oÈ8ı‡¤•¥R…)((T& ߬Yh°yU;¢=øxAâÀG‘M#nÑe: ÙTë·ò¾S!û‚ûB#ò:i 6š¡ "˜& ñ9¼@NiÙp8QTÄ,E 3 |¾3âqíÙù¬ÀžŸ­)%Nw N/@ ÉÈ\êO9ŠwËãëÎ0þPÛ¢(ˆOqf¦0 ˆ³µÅ•gê UÖA‘Š§Í„ð<ñàêšDóšóˆ1ðÈà¡"^2¿/< ~ÒY¢fX ©I"‰’©)Š"¢Æ(𢙢fŠªiffb`‰j’i¦”¦¤˜™•’&X„ô¤òÞÊxô9'¶ö§è@ è*,‰ÅÉ8iSDÈÁx°‡º]°ŸRf)Ô¼a÷ÅHr8üû1£éðL}ß*áïù\÷ðgØÓ’OstêxuÑ-úꎅæÉçf¬ØqDiß^Dñ“€yæA1‰èñ·-¶MÐú¤ßÔìI3K'¿ú‰Ìo§G¿ãâ@é$Õ¾• á˜ÐêB ¨%å—^ÌòF•çµ ósT7öÃà™äe¿6šÂkœÃå Oí5¨/gmðaÿ®´Ì™ü+×g÷$+‡î½=%eûâ#Âl…%wÕö&Öê&h©÷3ÓÞ¡—õüŸ³ýLnQ õ¶Ï™i tôì9åP ׫P•d¸éƒõA:uº&b‡r\y†ü¤o¿â¿¬çÔ_•éÛúDo; KKHœ6‘aå ¸vah$<ž®ývêïÊ;£'m°å¥>á°ˆjR<0ûí¤µÒP”ÃI$@(",ÑònëÔb¿â¨{}€3 FQý†l: ö* d´ýùæH/ð»xx#(;‘mÓ«EBt¨E‰H©àkA²† JiÉÄð†1Ã5è®z» /CSÅYˆ²Žâ÷`À_Ñ´SAçDÌQÛ1 1ŒD·ó…uf4|lœPÀ‹ªGh1ê†.µ>º§øÜ¯¤Ã Ì(ú½ÙàûºSŠìˆ[äíeÔXOBv² í( Î …yB @ðé‡l¿íýæn Ja56ÚÊ㸙èâ ׇ£Òsg¡!ÜÂègó•[BVéf5 'þƧÄÿƒÕÕ¼‘2J))pØ ýþãøÐ?•}ÉÁP#ÕÝ„ƒ‰J›¡øót@9e PZ³BPEBùÝÀŒÑB†BR¤K‰C&KDgdІRTâ¢e(<;¸بã@˜,QCÛÃ}†¯±; Qÿ"·Ë¡ãÏÐŒBSœüšê`OH ú&’HöJƒˆÄ(ÃH@°KAL!4H)BRÑHH¡BºtCaykAJr—‰$ñe4% Q A q?§%$¤ªd•¢¨ª¡¡"‚¦Š ˆ TU V¹ba÷å=šæf;?NÈ Ì0èC£çEó9:(ò³’‡ºöÈåeq&ZNF +¬kE=Ì<ÝÃZm÷à•(@cƒñ¢Q,›FÙœJS5“›p½_\èþß]„% —=“3™t¯ª&SAŒû!öϤ>~0ð\{@¢fy{¶¤@ç«ÉÙ‡^lô 0Š>À€3ƒS‰ÁM0¸Œ@M6ßNÓŒçñ㨀ñ])’°¹ÞüÍå­áç«Â2Ã1Î¥^P ¼'çMÿ—nbõ¢ ŽßÎwL8o¾û)nþ 'z˜{ó«w`£Ç0çÜ<×Öo›nØç‡ôåxÔ¦ÒŠY©é=dÃì:ʧás꿪Èd~¦_!ä=G¿¿o`IBP11êŒLÌ¥¦Œ á¬æ§ÔGò’b#í²ì6:t‹CCL=ÇôÏEÎ’ š¨Âý9àÄ9¼ê˨+×™àžCy¼cÃɨ Èi\2×ådI£2 9Àš¤Ò¨Çnp([_ßø¼_áC;ƒ ü p…D`N É ¦­×QõÂt¸o„cpP˜ ¦l¼–]-Y dý•)’Lf:4€YXh¢JGaÑCÑÍÒPgÙ1¯ ›¡IŠõ,µÄÀêI&g\<‹³i]£h™B!¡¤<ÄV¤ª(bôGF•"8Ê;‘tÅÚûÂ])Âá+AÎ=¯•ó°3æ°߃„°E1ó¯Ù»·«‘Òz¤)@ȯâ'QCC “˜ƒÁJ"§ØGfª<ÎaëÆ„þ=¾ ×¯å+%-‰ Œ‡ÌYñº¼Øn§ïëþ§öe™D"‚SîÑ¿RøtÂç–#LáFn0,z¶1ˆ* ©X†’¢"ƒ’z:c$¸”ˆ<'»›Šz„9ø„ÑŸDþ‰êK‰ (|¨ÙHrPœÚ²©EtÍqD4ºâæ|[LFƒ¤iêþþè^#ÔæôF6Óî2TÖ‡ÓëA¢›/M2·Í鸒¦  †H*+FÛDS­@RÐUMQN£ÇÔ9ß¶!IÖ ÃÎ æ"up{9SƒƒÇ¸A‹ýÊ#ñ÷Éâ"lR¢Ì’0ÂP„JtM ‘!@—Š‘& 2B—¢Ày:üàhxà/Æ0¯Œ¢Dêø~2s°ò„ÑÒ=q&4­–¥×Áìßà‘ö)¦DR4ö¶8…d?'ÌUìtá•ø}_•õ¹DÓ¤š¼ z0'˜ ÓþHÿjðò,ÑvÀS$²d9v„‰”&H ÉÈè/’çOŒäÌÒ'æ…OB‡"uø L§„Ÿ§ÌSùôHa¸9<ÈF%fDˆcµw »cÊE@ˆý¥þHU”¤"X˜‹èJb Øáä Cû³`* ¦†*Q)I&™¢ cY‡B‘„Q @q¬Tòë×`O§‰ø'?.úp$1/ÄaBzZ*îZޝUÔX[ªeÀ2PÈ0ÂWÈ'ÏUþi¡R`CžjM˜NZÅìoj“}膬™:ª3(CV´ ¢¡¥ÚSRs F •)¢’íÉ£@ù/~¼«ÒôºD÷)¥>||à G’–À[áJSÔ¡ê_)ÃÅʃ ˆ°Ë!l"™L Q4MáÚw€7†—-ü˜c-4mŒ<#Áåýɳ𠨎âØL 2†mJÖ#9ø î`ríRFéûŸÚp8/5_yïî>+­ãÔ2}Y}ãhça=úòH L„Æ M‚hãb² ~´øŽ¸( ¦ j‚Äê_zúgÔÓÖùp)÷”AؾvÂ|!t ;œíî­? |® ×!ÇÞx;›ûûñFîs—¿àïBªƒÁñà¸_¸L]åÖ>YȈK)=>ü_—Jµ€2 µ™Á€Naõ ûÂ&:?._– ì–‡ÈôTUU²¤)Ãõ—Ñi "Ô{#¤»u!¶°XíÌÓPCBDIÄ©AìÛØÀØ€rÊ3õö/¬òaëüF!ÝÖ;z*M¡Û2 ÃDLÔ`jÚÉp³uÔÁ7ÓÕ¤Ô0ÿD ó}G-ÒôXL³„á†cð $š~ýÆä’’“õ¥¡„ÂJHzO‡ZAúê)2(8B¨ëmŠ©äSß;.Žuv޶ª‹E¾jVäX‚Z'%Å0è)5oò”:‰†„†§‚Lý‚9›·f·%:ì5“Ú«–¦¿ªšˆ €½PI%Œ±»#Š/Ž:`µXÂIL¡ r ‘:8€7.3 Ø[vé4ý¡\Sh ÍŸ Ë ¯ æ–FCJLü0`èà Ü —gLŽ"åÿY)¨j—j@æhx‰ 3á]Ç7ÏÛ‰½‰¶ƒl]ôè{|1ÂÖj§Z4q8Þ4KøÓ“Ê噠ǯï¾Y~a³„7)žâZÃZóN™˜®K.]$ÆL‰Æ°-»ŽI¢Ø”ÄZ+ræc%5½1á4šÝÃYLÌG… ÍK˜C°Á]¹{nÇw°Þ¡6ç ˆLgºrÖ31)¡ÉQ>¾pÅ'H’nm6\I†¥¡¼ÓT†î$·j‡ì‹PÒÎaðÒ4Æ÷vO’‹F¹f‚e!É3œgªë0)$RN;Ð(%ÜjL@•©í¢›JdìÃX˜ikwlÅ'Ç\åŠM+ŒADÄÄ(%ŒG¬À˜–jd™$šnÜ‹cUDs»Ž—¶†n·E5©‹ ÛFš,Çǯ§'©Bô²Þø35=vç Â.©ôf-iéÒ!LÛ53 1`‚.®n%0éTCæªf‚˜")VI4â¥Oˆ"&Eÿ&ãÃuIÕTïd¥Æ(I A’áaI|qÌ{ö^U¶ /]°ô”Ô"äˆs#I÷©JJbJššŠ”¡("FA‰JA$ˆ¨bФÛÙ‘|ÝB}±RŒËJ31Vbb†?/Þîl‡ßrš“|0VÅ›"=TµäSë€ 0†dª(B•{ï¶EÑ-4 ›{ûƒ« z@>P)² @°qšC"”Ê‚€30¦>éíp¢£ë”N½þ ûŠ›°³å¢ 9*HSí÷”šV„‘í¸ÁJ`dŸ\ž1³eFÒ”& p MýwO÷`Ä߯jã:ãƒ[…¹…ïf&Ä VyÿÊÉÐsL8cg ]Và¹(¾(Š© ¤D’L‘Hoì·†w¾Št±o¥†%í°‡u1ùž¢¡0´A2d"S΢íÍDRß`Û¶ÐÖð’UUI²¿ñ8uç&Š$’/'»£èç—Þðc3Ó3걘Wûêl¾tñÝÝÝ}ˆóÁðóÏ Ïúì¼ ’C FHß„ â€Çgv;ôΘj5T…´i}µ Ëý­¦O9§ø»ß§Íò@‡bPÔuËO_ìÎmn©.,ƒ T¥¦û ̓I÷oÎà‡H F„®`X*W3 ¥ TÒ~þÊÑT±£È "Z»ñœçOgAÁRò%ï² •íâ8éØ1ý2!(‰] ¬šL¾Þ5*lCO…“©S}4RAIl™Lƒ!ü?”ß855¬Ô +1U¬ðé ƒ‚C@a½y`8Û¦8´)ÂΰTQ>_>õ!pE_BÀú2`Ο»Â§ðÈ'†gUQDEUOz»±Ç«Q¹òŠˆ¡"ªQNÍBÑTtŒO rë ªªJJJF#Ó…Ï ¥È‚ÒÉÿë#ù Ô»Kàpó†>aèßç¸gÜ)4¾7º†02T¤­ JvËñ}!€¤eEˆŠ€±QÍôc•þCÇ0ûÏëNs®™ UüÒ|gN¾»m<ð?, @ÆÁøü2Pú AÆIÍ«C1£–º>3¦#Á@;qóM|ã¾?×úõ©ÑìôãÃöõ §è… ª^;ˆbkÀÆ12O1ž¶2šBˆ mlfˆ”ÀUFij.‚¤"s4ŒH2<ò©Sã•ÞJ¤ˆB…ˆ)H½°™¤ö¢z\¡Ò¯’ÈI挡lþ¨)|’mo5=ê<"Œ@Ì“ä™`yP„ò éM¨qñŒ¨zƒ‚ç/©\AHzÑ'Ë._$÷{bð O%¼È,”å¼ìùΤ¢Hˆâ–R–#Hà ÈyñÆJõ €‚)IÇZ:L§?(t>žFúÁ¤aòF•!i¢h£Ë )ôcF!H…¨•)†Zõe   ÆÈÁ!0Jd–…ò>%EÒs ÒÒ£J¯ƧOrsÆ'N4Âhs„"*‡óÁëöc²E\qÁ¢¨Šx¼, äJ-?ËüçžÒMörläþ`àŧ1ÄÙ$Ø »ÿ¶Ž ƒÁžJ»ü^çà€íó|? [|?!ÄЪl{qv„¤S‹ëО—ü!Í“¨¹N/"f2ÂËš é SI$SJCT›ÆÞ¥¼‡ “Š=@ÈpS‰ÛÛx(B. 瀼ÜO¢X_Ý aB”(Ñû$¨€æZ$ÀRR ›íˆ(P Ožà6Wrøÿ ‡¹P|žŒ9L=ÙÙÌ9Äæé³Å|®€<õìÎôY‹´ÌD3m`”X|NpÇ^w¨!¿“6ZÆ,Ó‚bærí`Rù)d7åãRŸ“JlêœfEµùÑ„hŸ/¸¯Yì{5h(cÑÙ[%¿UÜ48Ä$‚¤‘ãÚlÎru»&ÑFJ1ŸÃÆÔ5 çŸpÜüØ?óO¿òï-K#€øŠxxL%4IHÊ÷ ß!ç… „ ¡G ( ©Qð‘ m­QJ;m"DBT0‚P£2ƒíø@Çœ`Èë‚”Qd à†@&Wî‡b~{¢"ŒHOá‚g~P(ä…"h%0(fQá*†ãê-ððü;Y¹7 ýÅ2U;¨ä­“$c mpmCÖ ½=k»ÔÁÒ]Ä:"F2Dgý_R—`¸Àr@D‰®Ú‰¹ 5%x—‡£ôðmºmŠSFHuM—UV_“òÿ;ÍûOé£ù?òÒò—‰i÷¾oƒ·×ö¿¨‡CQƒAÂÝw(vv°,/ú›öäåÑ8t¸:&§vÿ{,ŠD) ~¼chœËÖnÃØ“¿€j? í 5Ò€îIò¿ËÕW4ãÏåÜ;à8^bÂò²t -Ìü0Tñ^^{Þ,:æ:WfK±‰;×Ï[(ž ƒå`¨A:–Ü8?²¦ƒAõ£Ùékéêù¿'/ þzeè©ê“ȇޞRùE©ùÌ‹±Õᇼ9ˆf>.<2øMyvBfËaÎ\ÐÕofæ8ZýP;C® æo4Œ3N× a•@Åk¥åd¶Vš·J°uÅê‰2ÒV1EÖ\åÀj@ô-“ÃgëìxzAó±ÔÌc+wü’õC°&¥? ÀïÔZBMB–1^Åé¿?Îs 4!J¤)ô9µ*‡‡ˆ0SX6Ýç›ZWzd{¼†tîM•J2 *(ˆx{YäÈäHîàé›—ü~Ôvéÿ1û‰¡7Ñä,à¦)è…9½hö@kt@=};H yÀdáRãÔu–síñ ÄPP9¡*5T„Ä¥AT$ЀÂN™^äè6ÚìOGr\&Ä4ÔKÖ‚ÃÚPgø¨0š²taë`v q;(ž‘qNô~Ïtâ¤R¾ð‡'ª¤s€^¸}„;×.³°ì‡wf;è§¶©{«HÍ ÌY&þ:‡Õ øtžw«Ã.±E7É?ÕòÁ?ã¿…Ë­0:=~¡óSŸ>“ßµþ¢?)©&°}ŽîS²i$Ù|£wë‰kVl…ÆÊ\ã ²-%!'P_®óè“MÃÊjK"f@ÿÓIöO´¾ú]ywö@?„£øT$ì˜>6†€ªS­ h$âoÜO—öJñ Ä›yÇw®££ è¤Š ˆ«â7é>sБ ŒƒGô›*t¥iÐQ‰ƒæM!ÈÝ‚bü·‰ª'kŽ|™[Ò)0'Ì'§JAhHé©‹ûxèé¡ÓäŸsÃ,=£Åàyå¼¢:ø‡ï)Ð/…THi l8ZóÖãoÓ·£)‰€‚¦ 4¶Å½ÜðI£o˜CTU"TžϸÂÌ+3$ÓPÏdó²4ÔDABôÒh¦€õ1t›È×Xi×”Q¶¢‘– J¦(‚Y!Q»±ëÌš^`ˆöO{œ¢{‚©ÑB˜ÌÒA,D5OŽÍ!Ó™* =K˜¦H`‘JiPLžqÅÅwj&hª‰R¢“i"€–@B…ìcòæχsÖ¨…ªKÜ4$ UðxO\à: |åà<Âi=íÄz…é Ëñ>HDšuÊDDA 'òüz8ôA•­¨Ä[:¤Íˆ¤Nrê C¨ç!©§õ[ŸR&*mQ>“mžžOP7æÑàFö*n>Ïh(þÑXXîdóôqƒŸ r5 Cè4ÎÜp6ùå:A‰ŽÚ sÎgÇÁîÝš^Ø !Ùb¿fÿë¸Þh‡C•y‹d Ÿ̳5ᆀò Ì=îÍ Qp‰0Ô»­êï›3!ò•‡†šÞ %þ$Û¯…Og±Ò ´=„ZqÏÑüÜO)¨Põ ?Óè?£ŸÜúäy|'v/»Ÿ{|‡¿CüÿoŽƒ´Š¿ŽXŠ(‰ƒ¯7Þ|ü•ì…óBäÌà’#Aè€TM-ø”Tè½]˜û`ðþ> ‡NxÚ¼8ŠúxÑÎ.¦B FÆ\ Õcôz8žºM&œbìs<ÙÀ™%.E% Ý@™Ý:&ž â÷_Gby`çÕJ.äƒá½`ƒØJ‡¤æ~n";ví5†-u±.%ññšˆçÝdžØâå“f8й:"¬ƒ/gcm‚fˆ¢\G$9ZÇke%–, ä ˜Mµ$ÔÚ“ºë\ôAذ£ÂîÕ¬ˆ¤'+ÍÆ’4ÏTD¨šÑ[è8»áÊ`¤Äí“¢¨îªÓGC@ô»‹·M AsR$:t>§˜ùl2’U«p—%TÎҥ͌ƒêÇcâÀ8' ¸á²Ê¾ÒRÿn»|—µÅÌ1Â4‰Ý/BT=œÿÓäq ª j, ‡#.8µ‚L.Ho*Fa~ƒÚ<8Ad÷ W…Tª€xx…’ò¹¥ˆpî°;Qï¡J@‘E?¢Š8ìšàw*lœã²2h=—¸Syá߬÷nïÜ}¼Æ¤)‚wsöñ.”žŒI1ØØîÉ’¸ŒOmWGZ/gqE^xÜ$K1…?àϫנ߯jB˜øÚ+ÒzÀ˜íI2u‡’ã™uØl$6¬Ëid„© r?â®Å` ?º“áŽÖsgà E‚§J’£ŠŒZ½ÜˆÎÝú÷1\Р(ÊyÏç±êò^Øo#ðàR> Á2Tô{ñøvå ðCIÎCª^£<½n¦a ñ„±ž¯F š¡hZ)bAH•B†b•¥b("Z¥ªJEiZ¡ F”j‘ ‰ ‰‰Jó§—´î¸ΨúqLON+È•5 !lçz½þl7TyzB>ƒshÎt7xS#怯Y+Y¶r„ò @‰d Ðt:i5z0ÉV¤p¿ºöž€õ3žü\øhvúŽ`KNo¸ºSÚ:ÓêÌ^ÉS<CºÄ/¾ TI-–À@KmPmMº¡øÓ¢;röãAè"Ì{írƒl'$Ó¬ %9ÛIñŸß „(•ÇXqÛ%ü<Þ™;ÌpfWß=r<¡ƒ¯¡ üɸ†y!áŒІª,(Î*O•⦬UNaaÉÛc”qž¸ œ”2ø¬¤r^ÞK0Ì¥6Û£Èb©šðÝÚÔ†É>˜îN´²Š(〨iv,þà£Ö^F›Ñ5‚Òy.º].žØzr>A¼´ SK>eS&*múBs3M‰³›Ò©x]Þ"C© ’·<)’N\Ç™Os =È)ÝÚÊ C J6ì Àž¢él@¾3Ò=åð€øŸÑ"R• _Óòk&̃µWeá!†1Î_¬( Í,7 å„Òì xôaøê¼z´aÍÌêÅ öèƒÍ©%4ì»ÀfÈMuüý|Mm!ã.Ip„¿¸íþæï†³‰ йûðþØÉÛ€ÁÁ‡É€ìµä»íÔï8§÷l¢‡ÔÍ|9„”àG-ä³aB ºcõ‚Ä>táÇîÛç„>SwèÂǧÃ!öºéÇÔ¾ çIoNóËPT’`¸ì$KÐ= ’Y5¤éS‹¯L‡’ù%&´øDâ2Ä”¯Óeùƒr¹MGèc½Ô—ÃÝxzxÙ4¾l‘ W©|ËÜ ÓÏL^ˆ Íz ·eOÐr?Yö™ÿ`w¤ý@j=ä D Rˆ’ȃ=€v•^0l›$Š„È¿*nöwžl >M…ù¾M¸7|ꯟõtQE뎧‡.F'js@üУÒ?d§) É'܇lÒ©±+á‹Gð}Zéx‘Ö¯F²˜~vŒª²Cf¶Í‚ÀSmj$†1PÏ9»Útø±wÀ†›Ìñ9„ ð’fOEmFp8bÀŒ8ÿ¥àÀÃíBHÝæ%­fʧ¤ÒÃ$L8=[”u‰·k§àTĘ83Û·ôÿ…†Ó[áÆùŠæ#xš tLr„î ÀÄBÍ!àìøÿ«¯¿=Dù{£'¯Í%¨'‡=ó0ÑËÍæ0!©‰Sf¨ªd˜ÈUñ'£›2e»²¸–w‡ŠIàp*( rtä‚…@¤˜ i ‚@ª@Ò:4QBPj"Y‚È q(â¼8_êþ¡ê†ˆÃús\°! Â^p¦@9À0”ôO²Š{ˆ T0ŸgØ…%àPC ‘›¡¾qÆLYS1×K ’§ü²øûŒ.j-¸í­Æi#Ú’KÐ d)ÊHW0Dϼ³ë8˜|Â|¼Ê‡`š!lݽh˜CjM ³0&ŒœPjˆÐuH¹)© ƒüˆƒ•³ÌºƒÌwëï‰þ$ |ˆF¹°wÏrwivÙyMP´…¯§ R ŒØ(¡2S$‡Ñ(‡Dã|_HwÈ!H HŠPÓ0J”PQ€¾äçu ­¸už¬ö¼3¯ÝWt?ËëêD_†5¥"#bmE[Hj iŸÀÈhéT Ìõ5%©ÃÞx¸ªØÉ‚'úÉÓ€’3ŠÛ”bÖ!$œhCNš%jI–h&õ."ë-¬Ùí¢b‰ ˆŠ*Ÿ[Ilæc„²A$ÄK¦#ÅnbŸKXTéÉ{%û `øÂ·ÀÁ3(Iñ ä8ñÆž')¹•ˆÈqFÚªª­ ÑŠ õ(zåç†8™™q£DÄ[ü\¸ê±oxÏFyžÙâª=l•yh„ˆˆ1*4ê‹Ý€òÀ‚‰£Í½—²éôËGyåÚªAòs‰Æ ©ŒQ#NõÜSx»Cäh$øü3šnj’ e¢ˆ²@ɧ ”„5,DOº«ˆÉ‰˜¦IÑé aµ›C‰ˆ¥jˆÕ4¦dÃ7ŽÁTôbmŒ†ð?säÁɈ î@,AG¼IÐ@ö¡ èfµÂ‚¢Hƒ·msõF»¤å¯qn$9²nÂqÎìÒ0¼B¬ãgš0;½·^ÏÉÝÜl>^E¦ÆƒÔ…LP2‘)H_‡õÜ·nЋÕ>Rï 9+îà`"'®¤I‡¨ûlP9.胸'>8€Ê¿³šzo;AÞ‹ï”ð7øN@ÔHU>âÂx1'¤ ˆ‚‡i«§Ç‡óí€jU’‘žŠÓào’S|&¾ý°¹ö1]„ dI룕™VJšêf;$¼ q²sæ˜%LäœBÈk”´ƒ©•áp¤pà té±Ä€óIŽZÞ3áz1œ…ˆ°7uTXZKf.¨pB“ 3Ö;ZXJ‡ÂafëaÄÛ!‡d0È¥•ÚP­¢ÜMJu'3gzDÇ00-X0Õ†ˆEDÚÀRü†ÈÕ BPà¡ûaÕàúÄã ø½<1~(’3œSÔÄyŒC”u Hü‘¿n#Æ( ZÈ@ÛIL%$Á·sa¨£4`,/—– [IHz¿ò 7ƒý’gØ”5vB=rÔ%伆gDm,ÇàCèÌ^’?_™ùCÈì², Ìåå~ì"²`™ZÅ–f(ˆ™Î9áˆ9æà@üAoGž'ÖÂ9õ°X¢"ˆB•¥"E@-'ËÀ5¤BС‰DôäDÌ>@¡X£×˜uòöàìuzH$`£ ˆânñ H#Šx†ƒß)ßËÉú.ëhþv4¯—uº­û3åͬ±$ZÈžN8çw•ÑEÖ‹V¨º)°o²§z( ×Ü«UU'ô“~kKY˜LàjGoÜt{I€l~Îä€K!½“OFÂKx“ЕHR"‚ ƒe)˜ ¡;gØ(™ä!ñ„ã<¬Ö"õ©ÁDJõbøýqéó†§DQó¡O§}ç_© 4W¨ž?5H@3“„ÏSG4Šæê2N¿+xˆÕ1vî4×7$vîx«;·YÚoôm¤6äÊæÂòÑ„zmÇF³ó!— ±L¡f+/i¡m ^ʦ&5Áîl7GÚYšáÛÍl ŠšfwNÕT±-Â+§ C:bÝÎ¥¡S"‚ÛKïM»„%– ‰k{Þqט’_xi2´ä‚R”@p§ûf!šððÒû ñ×…“áeñôX¿kŽ•œl ÂfîòB§:MzuAÎG‰àg¸GMÄT‘zÍ`ÂB󯲡Ԫ ¡ÃMt½°KÃ*O¬üçp/™Ám¤«Œ¸CèwŸº†7-Ø4“¥IA”‹+´*®¨x%‡wòÕ ™bkF–8,ĉf¡%É-šèz»xEµÄêãã¾%|Šóf}§! õp³6gexаÀ`ç¤è+¤~Xð©<ƒÐcÅ{ˆš¶CIZGé ‚}aG¤CßéxúGÊ$\EÁ›Ó¶’êîÝj_Ñ5×ÏjèµX ÒQÖØ‹ÂNe:k̓HêMLPr4„Áœ ÇC4CtEFz;¹ã=£¼¸ñ_±uǸø‚S °ìòá‚d绳d·a*À-ð8Æ®,œ]šãXAš^‘¥‹nÙAKˆÄD Žj¨Y‚‹i1+â” ~°q›È5)”(Ä=ÜܘN>ôÁáÀíóë^c‹$É”Œ¶b m p³&i»@ýòn_‡úç!ƒ¤Ë™ +HB¥Q |áCrb ¡â_xs8 2Ê4 ¶6éâ}·y:é 1‘^@^y&*¯2hÙΉ‘¢ dc”É‹)•>K/(a„ª*Ï Á41óC•„Ù=o˜-fé–C] Ùĺ9ÔFÅ9» ¦fdY…)bª!¦#Ô `ª(7]GUOqõòóQ0”|góÆ"Ó½û®“‰ëAÄü]/}L§ÍÐ|¾ðP=íîH2‡Z÷(#K¶Kˆ’(³¾èXqß i…öÙ-?¦®Áhö©‚”‡Nù$܉2¥OD,žl-ĘBBÀLî4„ è[):Ø„F§^mÕ¦§#8¦ðØoPòШ BôŠ`zUt ä¤D<Áøyî6ð¹ë¤H«KDU÷” â1çG¸´}©ª*"‚îó[n¯Ýãëd¼Õ  ægšƒ0“$‚ƒ¾sê‡Yɨ£îv˜÷À}äàñ½èYb×oÕºuÊf7 Iía©Ä!Xdù×ra ²²åBÇ= |»‘™`áê…:È3©‡§C³L O=%!¥)%-Ê =| o2IƒÜe'Ãd¯E÷¼ò5³ö¼–“§ÂÒ{Ü­3ƒq)Hj™#Ži€¨c)‰éöì‡ZZ:Çc™=BoŒš=v4/lPžÞôYÑæÔ4? X<Š~Ÿ>™4•ôo‚K¾mÇèÇpL‘E캈9š7Ïpôò{´ÑæÃÖwÎ ÑPN'$ÁDldzãÏGŒöõ'Ö3%Œ`Á4s±¸©°™³†›Ñ½½IE¸4D^ü” Ýçõî*Nƒ^4‘I¨˜øÎS£Ô)‰J+à3†öm‚5ý¹ýžø»áüw»(ªTX<.ð".VŽ&•S~ÓüõÎëëÒÌ-j墇Ó&”q.#Ö†¡4¦4æK6e–)›LnK,Ò‚P†## ¨¤m€£²Â2ÀºòÇy›p‚‚ðã‘Ãæ}¾É7£Ž^!ƒÜB¶ Hna¬x\¾ΓT-4pà3Sódɨy=š–3ýïäø”¡Ù|ù5ší%VS#Ž.Iô!ÈoDØÏ¡Ò>“L¹¯¬‹`N“ɉ±äâìϨ‡8º÷Ôþ$–2B6{ÂvÓxõ²éú®nÉŒQ))t/ÅÌÓ©t‡áÍÂF³¡¦lm v !Þr 褜œžcÂ{àÈš™.ùÝú3ˆªŠg\ÝέáG_!»ºŸŒ»ºã`åЯ\ŽÉôlž1¶ \,ãïCÞpŧx÷xf¥¶ÁÉh S}a·†fJ€ÆgRÜ"ÀÂŽX²mˆ;d&>^hînp7^¼Áp¶%Lµ8à#xgNu €ÌÌu}vÉ5î™—ÏŸÒaåsåÏ¡…Œs) +¡|ïCœ{dm=ƒˆÂs†X®‡ð¥Ï?·û4z‹36»ßýœ¼ÉÕ‚öË0I)¥ ‘•q @Mdhód~íb?”áÕ¿#Ë2rjŒ$ÉR#'$!¨t´iC0¦6@Á²5«ät“ThL·²ÑK=¡£ßœ‡ç_X!­Œ,ÒRTKKE~£1"D}p×1‰¥«`Ç`þˆ_á”Ò&þL'¸úºSb{߈…ðxUšªcz™ºA\4:~a²çmIÁ†¬2e«C¢BÆHÞ›r½ZÓ.mh=R+ —ˆAÒS¤¦ xº]§².1N'åPôtô†#ùo×ä¨ÓBPDWí6Å´8Fòä+ qÎG¨8#±ÄÂ@øêà¦3 A,9‰lѲ§L ÂI°úѵÏPm L¿àŒX²?„š¡šŠ8Ÿ|¨Áªˆ¢(-»»ÎÊ/1EQR`C@}^Þ‹u¤Õ™af—ä…Ñ í$ùü‡#ÇÔûKâäÖ£×Öº¹Ö؉¿œÄîQ¡öÛí ëÕ7±-‹bRbT•´£Ó§£TAóŒWë‘õ&ÒQooBT€Ft¸B¯êPËhÜ‚€Â…xN÷ ì9DŸD>Š%Õ1#É+º_Rš{8{œ‡—ª.! =ô“žvÀ—ÉÐ=)ïÌ„D"tPš¤)ÙBi4ºõœ#@˜ƒXnƒ×DÐh ¤®·–!`˜W@øB%{ñ¯&6ÝzîÁ˜”¤¤HêõK×@¾G„׸ôöÃçh% TІƒÔk#&îLJ@qDS)–ãÆ=H–?l†½í“T‡A@R*¡¡(¢d"B„‚J1*("YØ4E%D: HA ‘ ‘D2QMRûvVP;Zf?vN–ŠšeÜi?)Õ4ASõ¾Ê£…òHžWxf"𪇠¢®ì±%:Š(”(TZPfhÄ&…§AM'‘†(aSt˜d09ahQX±éO<ó—ÙfÞ©Ò¡änÖ ©(#ˆ ;¥)'³e>ÏIèÒf¬1&:Îb§d‰p[«ÆîîD< [q˜¡ B¶|„$ UED‡HJ(n†!fUÒR‘5Tgçþ,uµHQÈFN{—îÎi³Dm˜(EK2ÔJöœŒ”S1žeiÊçÙ©;t”=ˆUO´e’î·áá3¹ŒBž^Xå<¯å~_K·È™†Ž8ߘ=~!BAã¥/牵(´¥EJðÕÝãÈu”Öòí!LÅ(¢Sò=g#äØ=`)Å0GhJ0˜aV…iD(i>­ @Ò"&€8 WJ•@D(‹J”Š{…Sª‘­"‹R ¬À Ò Ò‰J%-!CT ] Et §@Bt’¦$J!Ò t 'öHx„*¾†|i¢! pdÈ’qëÄ‚•xfã+Ъô,ªA‮˜bDbQQ)ÀÓƒI²jx.¶‘ÙBv¬®øy¼‘áÌ9¢.ÚÈ™ˆa…‚£ã~.6Î ‰â !>pêN©Š"®y(§œAB̽!¬wb×!²Í¸ÖMè=I@ŸÁ/éà®Q;§}@d2‚ô•@š\‚kÉr¡”(Ìß*ûøŒëÚš ’%‰¡J©P€òp% IUEGX©¥¥(ŽÀ§@t¦½ž,OŠ.4·Ãýè×öMO¡ ¥2 ]ºwz¾W¬áAK"TÌ ×ôŠÄ”$L-M÷Þ rŸ_®pOB èé@Šcm(ú.HíÉ { XˆB¸/™§ÄˆM$žg “Wó\CàhtôuöìUy0Æšb*Šª&˜Ì" ¤("ŠBB ) b€fRˆ…&*Š‚¢¦––†T ‚¢i*Ji`¨¨(¤š!º1TÍ1ILLEER1TRE3QCLC5ÔSBéˆïÕ€ù`ì’¢[âÀêd2ý:ÁÞrP/ûØíJ0­#Wï§wÈhSÁ#Oqú¶I0f&RÝûL!Ê3!³ô¶üýv\âßÎ ,‰Î~(¡Ë$ˆ.$g+&ˆˆš XY+‰"uJøÇ6¡Þ2 ´B”Ò>ˆR )vâEðgŒ†a™g¤Ÿæ—‰s®CP ©@‚|w"c+J}Å÷M&?µ“bëšI¯r> ñ;ŽJýäR´§ÇžîÅ9ò@:Jô†h” ZQœ~6л·"2* ‚#‚ûTEé±f'«8 ÓÈOäÙ^¯eÊEGè—S–ºkH}6F øË¨6šC#xE ÆCJß1·<_âPÒ”O©ïAÄ! ÷Œ!ë:pû… ~ò†Iã«Ù(Òœra‡Òø—¨ML­z¢tIúsIvU{8ïðÒV“_¬ ‡pAê`:¡N€ Ä©“ÕAçÃå¯=åˆGJtyµŠ¿„'B’ŒZV•Ê$ŸìO‚w±L€ç €t)âH[ ;¨.Ä¢¶»^;2¨u‘py QC·% 65}0†$‰±ÁЙ”J¥¦*"¢iB"¦‹N ’™°Ñ0LUPÍ£$&°EÁ˜8Ù¢—LšµJÌ ÏiøžïËaïáÕ”Lµ"lhЙ % ¦™SNЉ©1%Æ0’$ð”…d‘pA4’Rh R)­QlÙ4:sÃ툒"B—ñIrmTle”‡aLšª‰ :¥¥ÀÁrl¦£IlSP1)¤ º1-=uHAÓ˜ŠFƒ8©Ûi¯Ëù,ñåê},ýüôÒ´,DÂ>¥S D‰J=%•éÀUØITÉZÒV‡m¡%6sRli"«Ã."!Ln8Å¥Ð~ˆ1XaÃàÏ”O½«ŸlÎ þ,ØhŸ#-Õ"î0oþêÖ¿ôišÕ&aôö$‰xï¹)bÐÇÊ©#”Já6–Êü9zC¦Òmâµ6@àÖ>”0PXB-©a›óV™”:§ƒrƒo„¶-É…ÙØ6š-Û$MYGéM?ª.yóÄš”å!#r^¹5˜¦¥7†µ ’ P­ÒôÖiÅYp¢2•XĆØ(ÂsÞMì˪†)×›ì' % (  "$!í‡D‡­ŽÜ;Ó¦m[àj^“43W"a2’ÌæY ŒãlĤ6d“F‘f¨]Ô4E ‰u&ÆN†BE‡ Óºe m˜jLܪ¡éB .ÀâñJl-ÉÁ›Îh ¦ÔmTQ¤»(IŠ,¹›?’Φ pa© w !#jÓ4¡ŽÃ*wËÃt¶ñ9Á•›²¢nW“µQQ£X:¼CŒwÏ¢p­ O"ÑÉ Ö9Ô0kž :&dÛr÷´ÊL,à§)ß,/D4ºîŒp '‰)OB•áC·±4ûíT?X¢$%•ÒKBô!Ô‘':t¡¯I©Ôd’ó ÉNÓ§Ä„çÏ]YšjÀ \ª€ƒÕE+7ŸÒù,%zo$#³ŒÃ9z3îÿlò!–ø[ô¦)ü,)ˆ2ž­1s¼H-¸šÝÄ@®YYõ¯ühºN’tïªøäðÞrùŸã£ .Žþa>~ÚÔRL”ˆs‚XQ´’ –&@s½v•—hi%uêk´•Pþ³XÉDf’ §ö0¾D)782Ìíÿ¡ <ø@Ù"Š0PAD˜“ú6*N´åþcýl>x }pØÓ¡‹µ¼}³ÎîôsQ¾r¤’VH 'p„€q 4¿Ã¯ŠK€(þd 5+åc€|Ý•$-D«ß{ñ“N ^Èñ‡[bÈno¡ÆB»ëNÔ;¿Ýì½$e™ÊNs°˜ŒbœÅ-àÍÑC8ÃýÅB8}¾'p0S‰®‚['#(Q%!š¤€J)©jŠi=Áä:û[‚*¬|@¢i)$ïÆÎnhGUTP@T—q"½;A)¿dÐk1E-!ˆ…»•_XHD*¥(¬J#B«H©%*Ò(Q0´ Ä AQH]_Z™ø˜¯Êâà°‚k¤xH!PÒb   8Ó§.qб’=²_dà@„–3Fn5zô>Ÿ¤Ù9*—Ï$„¡øƒùVÈ['¦4KIª¬«Bÿ™4'^âö©øÛÝ"âv#óKõ=¨¦È½°ŠÄ2„€04,IJÊB¥*1"”0Iø@v¯”!‚V‘ZQøã'µ{¼—D’ŒHAª¬@ØJP"hš”¤@ Š(a’B‰JU( ZA ¡H“¦¾5Œ¶°OWi€”žBoœ!¨€?‚5Ò'æ1© ZPrHÌy€Ò‘ýùÃ'åƒ" 4D~¹êñÀ6B˜¤ç’ÂÝé½®~Ðmú8^•=ç#HQAë=&è‡l+xë•9$£²uF'|"ž,@‡l!ˆãø¥‹¤hM ‡H*Ÿ0ü @º¾Í€)“•ŸfJG&úšQ'aÊ=P©2^Ù9×LÉu<á>îðçà¦ˆŠ€)„€”¥}H›ÛƒÛ"ȇÑB1vHämÙ/RÃàéLFé×€§# ¨~Ö‘éJP°Â¹()@‘+Ø4êÅ_I9Û â õÈ>ËË  qÅxH}û`ì¤x©ŠÑ 1ÉžÖ€%¤y{n0£HíÌ eññABœâ–”«—a(vý±ç„4H1Dz ­ x§îõ¾ñ’=êÁCŸi2TÁ4!>Œ¯õ§ëy>i®Ù8~«èއYý6ŒæJåI« ¦LŸ9+»ü}9qþz[ƒÒ2N! xܺCw ÜSC\„Ý´4#Ó§£RHm~Ò¡Äb §ú NQüЄ2Ozýlùýq¼0ü±\Èþüý)íD$þßCs¹ŽÄ\g|-Ò¬±Ò„»µ\Wêpé‘}–ËüºèXpaÂÇh­¸'c(FSv[.•Ax¹Â!¶4Сmiz!f”L6T$í²þóqã Ý¦4Ŭ/ÄPPÝ’–'0Û$ÌOé.‚¼´?1õ£Ÿsß]Šúcbˆ5i–ˆKç ¡â¶BÎ]–«Ÿ i.o¯“%ZÜ2’‘ꬪ˜4T·ÔDwpè)äleÑêAÐQOEo:¸¢è}ÀôÁƒÑµdòâôNƒíuá”ÆØñ™’h`Ѝ®({vßaìQ6a¸õ9µö¼½ÛÖ ŒŸÉ•Üxq/­˜æË¾WHpÒ#,áK°À¬à±#-ŽSåÃÁÎó£rð¹B¡Ü6îYáÁ,À°h¼6€ôAò>cñ% R z£Üш°çYù´üCäú<Ð~1ªzÜ}#ëñôÙXaëF)ÓǨÉR™ÔBסrÂaf;<ËãiH*ÓÆÁ‚Ô±…‚Íq|JÍ… 5K/ÃàÃ臛Àä£L©1uƒHmƒE4¶,µ ˆ­œ$PÐy°Fܱ­ñÜv¤ˆu r–Æ2ÌïKÍ8êLÒj$Ñ‘HRµp%QÍ’å˜aE¤vC{©‰ýªã£<ÔP{C™ %PI)·M±Ãœ=´Ü×:ÂË@ËS8$Ó:Y-» ¶R[·'; r7M ™lÖŒ¶‚˜d™pµB¬ú ­ÙÆçÔ\ÝFª•[.–‡C–D6 óòàt<#¨'@ú »Íbâ{à šxAÛ ß&B†¤( É{äóJP ¢£DäÒÎØÙï!è<Å Ö.´‰§¡t¼%26 ªL”ÚSèÚ½Hë°;1NÿÅ]òÀÇÅÖÈrX‚(ƒÊì«sÎzéñvzÄ].±ª|äaQ0E››1D¾wÜò;ž?¯˜ò:M¿hr~ŸçSÇ»ùO‡‡õuº_ÍqGÕ‹ä¶UÞøhUïèw«1 LÀP~ø ±~S@'ìÐ.¦!GD 1XL–#ʸóü¾±`Ø@8¯(;à\¦‰¡) 'AÄ” À/@us¸ÙzMªMBvÁ¼ïf`: %zÏÎíødCSWóFxØëÆÌÐéMM©2b¨*ØC/å·‚"!Çy±Ã`ÄüóàÔð—ц­J2¿Ÿš}¿I_Ûý˜7&uI»¸(Ëpë¦ HÌÂM¨?W޼{¿7}ó? õú¾4~~.å=÷b]3çÁf-†‰20B¢ò#oßì1‹ È…QE €ÄÐÐEU$jkxêôí´R"zef™jO«šý&„Ú"ZF!_+Ò€ > 12 ˜ ¢è#ëàú÷ê^ãö‡òŒæ;Âé›1pHPù!u"@!S)Ÿf øóðãL€t¦”?ŽáûÄzñæH…¼ò‹aù¹ãK/ðì@%P” Q7­"Ö$&¨‚¦BŠR JbV’ŠJJˆªV¢‚Š©¨b1 &€¥B”FF„)J0¸˜!N ¤b]å‚1:ôøÅ1G+*=Û‘M¬Ï²Æ/«³¤£V›°`£ü8¬Êz7ü\ êB˜ þIi¤È!¡¢i6{§® »DÿfD逞¯‡p;ã"=“?tØÇüŠ,Bš)"JJJ„åýP§Høpiˆ‚XCã’’~èÈi©>Cs®,öF²Â}¥²NÀ¦82‡/&ÜÑÇ@rðͧü׃Âþjç9ì!Hòòö¡å…™‹ø$!wâfh•üŸHt8¯Þ§޼30=“®ˆþÑPHÑL4sAŸv!ƒïÁÕä©Ýj^dÑ4º… ˆb0]ÑÃü !$ªL$8þóã¯ϬØ®Ú'Π<CëÜ—»‹ø¶èž `F§M`Z-hC ¾~аŸA"Ìví%„èÀý¹ ×rnÍ‚¤„þk® Yl˜Œ®¿›ŸXJÎC)]y§9a®…FnŽJ!!ÉÌÍš].Öîl¬&ª -¥#’hÑŠA™f M¾ÛðíhûxiTÚ’¡ ˜b$÷òó¤ˆCÐ}ˆ=±xtl'|OËRÁïéqÛkØ[AÑ@×h¡h¦ ¸A?¯ø8¢9ÌŸyýôÿrtâ@Ð=£xlúsšªŒ¡QB¾š.Š¿Óý\o‚ò¥ºÿcño¾RîàOä7þ.&óŽã¨M®a f„5ãg­ö“pæwà8ž’‡çûîÜô„Ïn³†Be°g4ÄÀ8ûÖ˜˜½~³J|úÓ”a˜L‚€tÒšD25D/"¶hxÝÁTMî¡wá3¾d˜ÈÓºt+–cÉÿz¡š#FK…–RkŠö2BÁ€qB—[8^šQ'çø]ÍÒn\«# ó<ÿͳwFŸLWÖŽÄþ+{×úEô û¸¦#©ðŽM›Àª²µˆuôb¡ŒKå*süùáÐðθ˥áðòü’𠾇_yëƒ7Ó Ä 0À²Y<ý^Gò@h;üU<`Ц$ÊHt£_Ã~i²yR×­š‹IówÜ&© b*•¦cG›*JS8Å…ãÐ\¬W¯%0/Á=ì)–<;9bµu¯I“r·`õ^£ÎqÑê½øpÚáQUQu™í±ð6ñ=ãúÙ™ I„ûöWË \0^ê€ÈJCà;€ÁÚ>9tA=¢ô>ãì6z®p¼è×P/yn¦AQU_\ÅÜ—8àò'SŸ Ð~sñ|Ã¥O+>ÉyËþ©r6ò`lK¨ Âñµ K{€à5ØöâéeÞBÀ_Jáä)`:÷8r^QêS—ÓdýÒùæ±Qu¸lLaå‚€âNI—e¼¯TóÙ×ôh{sPôEðí÷ùWêOÒQ³2`ƒ%Ê‘øeÌ þqB&!X…q!ÁA• e…(hˆÊjZš‰ª˜"´‚¡’‚_ñLîÙÔ€)ìX„aFæ{ú—-Ö]Æõ d íH8u!.ó‚ :SiM3˜#á²¶ŒzQyÀÖËÎANd¨¨• &³ÅÅÆxñïßÚ$ˬyd¯.$¸‡,P ”P;Müÿƒä8 W“p¸¯³¯ó,¢K˸1¡¸µÜi3ÔbõYÃDù` W + ƒÝÌ,G¾Éˆ‹ç!ØÎ4çØç_ÐàñAy¿Ç;—²C8ºÄ:„¥Áö’” Ãç€È•"JX!¤éC!DLHQzHЈpJ¦¿ÓÉ€¢˜f Šáo”Ð`[CFy˜:i* ÀÒmË]7ïô?C!!%œ8&”¡×t±,ƒ©ì£Èq?Va ATžx‘óììºëÀÍäÆH<˜…ä ÈöÈð€†ú}?íÃßÙ.‘Òcœ1/˜ÜåüÁÛË!¤w»ûõ%yqvœ½á¶„Ø )a”’$ËH1&Ö¹ç™ÀÎC÷Ô™`õ>]eäçBÓóFöȵKTLåÅA¾Ë°é'MìÌË!:@zàÉ)™Ÿg›Bp8æ?P`ä$"±0 u…ñà |ð‘ ò] Pº4œ=ñƒ"õ|œ'y¢” O Mú¥â*Š`¥(\ïìÒu¼10ÄÀ÷~(ä~?€)–H#Fi?Wóãá_}ècŠ¢«Òs2䊑8Ü)7L Ò¹œ¦¦¸VZ‘•.?¹<„NQÊc†2B²EQEΙÁuùï8ÎÍ CžA1ãcM0þ/M¤6dñdå§@¸e"‚Ì$ÂBÒÐÈÄXƒé0ÍÌÝ€ ­ç>WÕ+ó@„¦výà‰d¡é• ë&`2UÀ4*Î#‰èò•ç¹>é @t•¿¿ë÷‡æŸhøfJƒ}/f)»‘fpÂÝÚ°jŠ% ÆKH´/ŠýØoš0Áô¨cÔ>ú(óD8 ¼P¦S7Cº ¿nÚ`:>”< ˆL0À{Õ>¤Ãï7m´MOÖnÚS&@’?^—"ø¼Ž-DA/®AÛ?åDãšÑ”º1 Üxw'’Y£d4g ÏÑ¢€ÄãÇ}cÙÎSÖ 7²7K @X´3„æHÝü?O®“!ŸÆbÕùV«¤™ 5¸«#† àøk… ?Í•í5Õ->Lï×|‡«Ø˜;@œŽ3Ͱí )]ø³6ðÁQY~C&/é1C†Jíù6’õó›?dCbî„Ëœ£Òh“œ:¨(òÒù$ô~Ìää/© ¤„Ú CHD—Ù!«ŸŽþÎû òÉÆ õÕNuè E(vJ½d«ö7œ.Š?"IÞeø€ýcÃÀ?ŽJkqGò¤2½Ùz”â\C|M®/wÊüÙ6ÂvÙ3IF&%RfÄüELü‚T5K»O¬Þpþ¢ŠVHò>«ïï“GßÙO¤·y!lÆû,†Ϩ hMDé[H„it(4„ñƒJÄ .„âO͆± JP¦ÊonNI¼ðØQúŸPó8 y%6NÐü*)ŠhÑaBU°TSDZÄ °MPP$”5BCTPÄ¥ _šˆÀ"×sÓý'0;i (š–û=$Ì–0-¦ ”5rXøŒ:ý¯1š¦p 5x%b`71Œ²mí¡šáti­Éek`¶_§¸ÿD3sA;„Z¢×»ó´Õ}=Ç`d\N8&?-œ½ŸäMö3`}~˜îìÞwSnÆÀ5#ƒËµÀí*ð˜ýÀ¨Eo§é%Ìrê áÊ~ÞIBàh#dÿ(h_*$ ëÜèù퇧„8ë{DžæM8™*Næ‹0Huû» ¥DÂá§Hž™42ͧdú Ù$>Òü)¸¾¦8¦8¦8¦8¦ uδî8ØUNIDQA X¿Cü~'SX‚*‚b™²”Å÷æ­'ƒHa LQK «šEƵËI[:ñ§6BCµ&HHI¨ô¤“õ£! HN±]£nQ!+ŒÈQþ–5Q Õ]ôã¢ã>K%E1TOBd‡_ tpoûw›ìðqæt™0l} ñØŽ癉Šj†¤¨aŠØé÷Çž8(,bdƒ,š×Sfë‚dªP¾kÓmÏ>: ä¨Möá#§Ù,²½UXXˆE2ä-S.Å cÕÍMDú´Íô…õØ$©Zˆ!‰B¢”i¦¢Š(‚"@™ˆŠ ‰–ŠIŠ£ÔÑ¡¬mKT-%DA²hª¦‚O§IID|%€"I™¼SC]´ J G“‘¦`%!"j’J ºÇ“ë¨ÌìðFäÄ„M%DùPh¼ÚŠ*ªñðàGq¢+Â;€Ó6a†š^mL‘PkgQU=´U³¼ƒ+±‚(š`àÍæK͉èÄÉ%F`¼q§mKÒi)¤¤‚}lÄDUSØòï®0y¼ìËAE^ËTÒµÙ tÐz¼óS:!C¨¦/œªùsRÀf¨ke"M³˜œÆ`šH€š7\>„Œ!=cP'STÍ@¤oCº hJ½qÌ·EHUD…TD¡Ó…¡ ‹‰d´¤i$¨d(D†u‚J†fH©A&o'UUSEE5Œ…æKÇ»Ìb§«)¦hŠª§±­:ŒìÁ°i«ÂÂÑÆ„œ•1SHù*¨`}ÒîƒTNžŽ~ûQñë:à­çuÃDï:ˆª4ÂjQ!Bj—½qC:êÍ© ¨‰%i(Ë'/&b4e+2Ä:\Juü÷IÐyõÇG}µ‰@§8¿–L@Ò3‘Îå³Û­—C™€Àb\u·‡¯w·¬zY`ËÛ‰‘êô[¶{»MPnç†Üm®ìLc4îrtnj§ŽŠ3wDeƒºm9Þ¬ÿ7†ñó~\ûwIú¡sˉ…Äž,qÌò ß0àZtM!" † 6ÛSI²¬øª&Åâ@Áÿ†á9/Øà $ |¿ß÷×ÑêÖx?ç¾ó”Iè¾Bˆ£UQF,šp)°Å‡uÃ.ƒ%W@ X'žňhã¡  š`0•Z‹Öïˆ|[ qÿ„ﮇ!ÿbBŽ+ó]ˆ*wà–8('“øýÉRÿo#ÚÙŽ£×Ðé$œOâd6ê®gƒIC*š ØT{þpñCºCÁŽ ç¡=IÈD€¥‰/‚” x€s"lÙ &<}Šƒß´ŒD'¢_íÛd~Ýû³oÑì0_é6'bþaéttsñ ÜqŸc:œu¬J,Ç 2B!)jaQ‚¨úã!Œ…Ýü>{ÈJ (WíîáÄ ¦Îˆ7µ ›ó¹33 „C QMUUQUUEQP¥UUUTTÉRP4MUUUTTAUÖh&ªª¨ªª¢¦¦Ñ¥ 4   C$Y €@éºpçåðóy‚—€vóOX@Ng”è%?ÉÜ/"H÷°TåzWŠ<0º¡ˆq8šü÷¥˜rŠÓ;tlb4C„”ÄMP"‘Lá or,ÃWûdà§LÖt wy±g×&xsk«*Á‹i/¤8£ˆ/+&#‹Ì3‹ÄkŽ ³?c‰ftBäÀœ±ÓL’·E<ð: D@V«»ÊCƒ„Ì!ŠÐè1QÓ¨ãh#Í—Ì,vpe$Ã#ž°eç& yl`ÔðÁûÏ¥ðì ¦IG×ø3Ì•Š0ô`»ˆ¦ ªÝŠï}ŽÃãržwRæ4ž¡|”˜èLUR^`Ú{s¸ÃbÝph]R•vA‰5$½Ñ|  #.08IãÄêðÑšîm=bqj«ÈÔy]Ü&„z:êALHÒ“MñssáÖ†’òg[HNBfȃ£rŽ@“Bm!m(éü¿k`½zž4袋×s@a‰{¿&·°þp0^2l¾vCÓéOÑ=ÐtÇŸìÚO»ë=EÛßá+¾Ø•9§Õrø®3¸UÜúÕ‰!ídà§Ô0©€œ$æ¥Ùs Ô¾ÿË›`“!ò,²g Üöú¤8¦»5¯`b»ÀÉv°Ü÷’U2{! ÌçîêÌÛθŽ×©_\=igÑǨ‘ô謒Ç)2†‹n%̸§ÜBÜ¥ÆLá !K“ƒ \9½|¡†"€%m6wÄ1½…Âqd„ûF|ß7}Ÿ„ܨuͨ§­ zM=ÚN õgÍ4Óf1«D†Cù™úf„å›Xè:°%‚Š2í> ™– !Lš¨OÉ0uEWv0éÀ¥Š 6•Ž´dpC£Q$T%®´ˆ{†ØÔ€7 ›8šZÕ±wV®ìˆ‹¹»ÛÓ³Ýݪl xâv€– áñ…@Ù˜„™!K:"èÃE0b#€Á¤f̦ú·¶½åù9Ñ,zÏ9¥\žD>wZ(¦ZMà p’³áÑô”@%{=`7Áä}>ƒ•èô@i„îÄ@¶R”®ŒÁQ=ÖH¢ ‹`Ä+$†")-—ê ˜"‰CD€hšF(š=È ëêúÕ(íœsEˆR¢‚w ï8ÑÎS¸ëÁ/Š,Y”„¤PäÀ¦Ž.ЧÝRsƒ]øyAN@u±ËòâÐm²â±ñAþûŸ°±û õœѧÓúá:F§)!¬¶[º öé†úcŽdßc°¸‚¬ƒ!SH‡ØÎ¢¬ ’L´ÔLÆ­Ÿ‹IvKdŒÛwi;÷»rZ“9ÐIYˆ5°jÌʰËêèõ*Þ˜ÝS‘O‰?Ñ{=‡K!%) T¡*"HMÉôO¶]n-Ë ‰hæ"B u¶îV8?‹Í î9©üÀþÓÞ§NÙ'Šº}ꤨñ¢¯ãÇ `~40W莇E0½4‡Õ]ï@Q©T¬¡hU¶”ÙG÷$mÑÉÁm$DQVî1Í`ë44t£‹FR®KÇÓ¹?5òÌ@ì_«›-Jù>®Ï?g`vùƒÞ@Ž-Qhuâ™B4Ò)Öaæ¢Z"fbÜŒ%ÏÄòfÌ%FÉË”.~Î<õ‡.’ú÷áˆeÍU—Å =‰_éÏæ½I•j0õÜ[ê`˜‰f'¡¼6dˆ•,ÈR˜€v†nfNo 2’‰ 3ЦÜbâ|¦’(³Z%X¦´¾Ëà{s•òBó‹ï&09‡á ß…ºhfCßš ¬º‘i+¸h1X–Ì„ƒÒÌðmÉGJR’z° DDh h+ÿ¿Ç®_Ó(J’pÙ£}ˆÝ‰¾Öâ1¾q’ ½ xX¨u~Wp`œE-cÎR@ô¸ÍÜñ¸X 䋘jbýÄïXÌbÎ ?Žz¼SCõ’åÒã°vü\ མ¤t×åõ Ž‘Þ ¡ŸMÈmH°í©q ±Žy•’ŸŸTsü } ’u`]Ëš»éy*›á¤)0fgR0ëÌ ý©Ù!òWUPïì€ãÛV×NáÆžEL³BY€³A|H…Ï#…§Âï¶å”„¤B=ÜÓAÑjÆŠ"$7Æwm³¡Ó¶ˆ¿UÃÆ×—DÑÆùîÒûñéŸ4oµµ´†&(3ô^:`"Žìb(ð=zÏDž³ŽýM>˜”ÞG¼-˺þ®Žº¼NvòbqõóãÔ—“²q!3—$ˆ4a6`¢1™öŒ,™4ƒ È"$ ‘"4Õüó¨ìDÚýÝ™=ëÍú.ŽUa"‰Q6‰f rä’Å“pá´ïŒ«ˆ’c3 çß28QÖ)ðT4 $ ><@rH‚*R}`ðú\>γŽÂŸº BBÏÝ&~¯‘ýrh„쇭@ÑÐC"Q8îè70ïÁ¾&Ó>,‘!ÒA $ ÒSHƒB,œŠbT"¥i‚ ˆZ $¡¨—£ÍHhSBèDă&3i2 ²€sBà8$ ¥äŒ,ª*®£o”Î žFÄ¢jøbùç£òl>„väJMæÌ9z!:lsÆCg°žHTì¢@ ýÙñ÷ò†ÄI ~Ï)ž°£5H#tThm´ð"Žd¶At¡Ü]£ƒo(6€9Ç 'QwE±Ì F`¢*JP¸™FDW$†ÐÝq†lÂ)Ì£R©0¹£¬l<3ưPE]Î9–š3Id‹äËÐq:TÄìåª QPË1ãYû*½ÿ¢éñmSº Ì+؈‡HÑurÔåÞ‘þ¸¸ÂÐ ÒR—ÀNB#M2ÿAˆ$Ã40‚Exx)~ÿîsÒÄ·ø>šêÓ—ÔÃÍ·X5é_ø¹ž •ˆ_Þ†‘@¿?@&EšWÚ×ü”NÊÒI¹+ ªMRŲ}\›¡*Pg1L8BõéËç"ÔäÌS›Æf/nP)@,\1*:&¨™·¶–"âÈY?ƒHSv Fp:Ú'2ðë¤íÓ'׈Øa:)ˆ¾G↴{pá}ŠÑ­./¬ÓÂïòëE± æ-hµ Kâr`J¹zþèG ‰”lye†R¯2bðEy>ªÖvT‰v9¶7É3¤Ò ñ&.{•bç\ØžúBÓSæ[Ó[ã}öõ;ÖgS¤ñ1˜P½è»}¹îgËéWÃïŽözèç§:X7ÅvCf]™¥ÝƒÎËîCð€Ò|lŸŒ&fùËäùÞqK»¹ª378ç´/\hçNt.HgòîÉ+íÑj‘K¨ø^Nøº“‚dï—YéÔRôÇfÞàëw‚.üË9„òT—™mïªt^W<ñŽ8̶ŸQNfëD<ôì0ÜäÜË7«"ö¶lØÖ©ü“k/—É˳ªôPÞÒwôìAì Á'À„º™|§‘ŸâLqóï‰ð‡\êY_l‚c¼x¥ˆ+*V±£L½ëC¤£ .NKgw'¼°{ÃSÏÊ'án]týÊæL)—òämÇžÜ·é¥æ+©E)2AAIJTÑQ3T³2K&L›ßwk– â¸dO<,S¶²Œ1ï–$;ñ‘M5©ØÑ- ‚a‘EdD±IÇH ›u„v…™›ùI$–&Iù}ÿ³Ú¥°]ƒFÐÝüŠUk4´¥†€†@.TR$`ÚC+,¡Üq&YR {LU;+g»;°0æŽÊáÜýD#%Z£`eÜ÷¼Aù  Âïdo”žÃv`Ô·†ÿ¯eÚHmS#àA4àù,Eö¢Å±`¬Åv?øÄj[Ÿœµ á}NÏv[2Õé³Åñž 7,Ù›C;ä`¼GÝ©a|ð;S7šâmë[TLß´ˆâßûê'"|(§KD¼·ß««€¶I“+]Õ©L<û«°Á6!/nùq5œ¼<î7\ôÞºÚIÔõ.= ñž:NLÆÑ³f áC΃‘ž°9('(õ9ðèN“­A»cršn¶”˱Ýa3-dƒ21ršŽÌxŒ$ŸMñ6o"í päJÕ-2aê²j&I„ÄSra˹ѧ 3fW$ÅE“#={Òö³“;Ç$w;b4ñ1ξ6)ì[IæáÎ48çRDááQÅw\E±cHöÛo@ÐìâQSÑÁ»ŒKëÒôYÄ¢„ìjù^QÆ †‡yQ Òî”Ðn6€†hZH3 Ð Ähb5Bé¾ý“:ÔkM5º`Ò_šYÜÕ)'¸#ê¡Ï¼…UUžs3 ÔÉòÎ5è`Rü2rã‚ñ~Ôñǧ´×OäÇdCe” §$zö{«5&b$ÁÚi¨¤&,žWnur[0, Ã1˜Ìà¶&ð³ ô5E¤1âæ¡­$r¢”З,Zlj®js0z·6qÁ¬SZá=;áÇVÉÒÞšžm18N•D5ú— ¬9íÃoЦ­;¦!àÓ°ôåDCw žÕ æjâ2cx¼ÌÞBPŸž Xs !9j¬ÍUˆaú›ÌâÒN‹‰I“³Êfx»ë½œr¯»X0dMzŒÊxÑä!²©m5,Á$~ù£K“»ã´%»c®êK¼^:ø® jŒ—«©7`gL5ÓÕ½lÇÊCUµ˜r[x½‰Ö#‡Ò\x)ƒ» Ý; ¼·À$©vd¹,à5S¯1.$Øš†¡ž\ž èaÑ"n±¨P;7Ùq¤B¹k}[e¾ ´’P7\VìàÆ@=Qå‘€îÎãt›¨«®{½rBöàÐà¨h`*’†•éÍ/”tü¹i†¾³r‰vÃhvd†l¦×:|œîØnwÁ½fQåßÊ+{‘éÝÞÜ™¯Kšâf=fâÒÇ1XcI¾35Ž?ÇâÐ#H"j_{øhÃ"„6ÆnMåòµ’ÒfÊçç¶XYº†Û!’fù­H9Ýn=9¦<>Ûx+ÑݱUÝòHîï7‚;ñ©oŠÜv†o9p¡µ7]\›Ï§}]ÉC¨t\¥Òx^Ñ8Læ÷…»ÝnÑŽÛ&¨È¤€ð ˆ*!iòÎ'˜báš>H*T§Ôŕ˳¶ýº†a&…Á‡Ú;ãj–LC¢ï}ñ‰²Ldn`É·;÷5‰Çe(á ç·©móóð!vK{ºØX‡Fãš'ÄŠììšbrí)^"`k­ÄK°îÎ]z±Ç°çÂ<óR%G›®""h¡‚Ö™3 DÃTÔÍ7¢˜‹X†^\¨æéqbnêM­Á/ê¡äžR¬µö©ã7 áÔ!ØÌŠœ7Vø£‰ÁK]9Âniz6>,i —ë‹.Al‰fn0ÂîSß' ©3¸dé9°z½ª“¤í®;ÆÕrí)º î! ˆ<ÊM]Sjèá8ÍÇ/×zwÇ¢*V˜¿;£' áav–v=ù~FJ'L¹[]a¹XT(CÖDZ÷â ªœÞ¼S†…uÖ¬–0PwÏ>ÑâÊÌ}4® £Ìñ$,òÏ´G+/~bDƒHôG¢`v—”uœiSëpÂmÃýhÇC¿›ô™LÌEˆwnŸ®BC©zdÒ ´Ì`®EèÝh•y惽¾u™STd† xÿ9ÖÆíðlÛǾ~”©¡’&û^3›¿\)OWo󓪾†›¿ª ³Jâ7“0­¬Îæ9J‡;úf!9Ü)3R·$ë 8x áÍ\z15#d3,éà`ù0LÀ;ðß"Z¹ŒD€ŽD¹wûëzs·ƒ<¡vúsvº?8ŽF§­üû_¦y‡Ê+.SW,BÙàº1[©*hFhˆüþmò^—C>³­ïÆ»=>oj³«ºXÖ7iߟ|ïußNV9ÃÆs[¹è!!vÆj©©Ò!)¸g$–BÄŸ­9@CÔ>(²ඪª‰ÚÓ}Y›Þ=Z.)h»ÊaüîTü!<ˆ¥z9>TçœJÎð¹1ÏF­fÊpˆcNY"!ÚÏÂ*ôespˆQ̹nƒ9`ψ=<î›Ï#s¹Ò£00Xª«,(¨§m[] ´óq©Ç|3STÄF!¡0$ÂL8åá—¤@EÄ^]¿+pÒ˃¦îøBáÎð±Þ|¤"“åÚ:}>­á¦Rç„¡ÓKðˆ`w} % œ7£®°³•í—½®ê*ƒ6xðÓ©Û›Ž–—d6ÖVã¿2yD_–ˆâr©éÙT½eót†’¢FÚ®ÙÙy‡Pæ0 ã V©Ù›õæ'gsœ\|=óÚƒÓËó§ÛãÉnZÝUåóÁž]£±E'=¢Ò3{žúrfÌK­Êd4)¯h¼[õÍÊéZ!)Ò¬s{‡n¥àãim/M9k.S´[fŸÍQ¬_i^Ýž+hÆÏ^\™u¯â3ð\öÞ%‘ÇIÈí1d4Þ¡÷é^vø3®w1›m)ÛG¢1w/¸‰ÇgÂùýÇ‹Q¾(â”§ˆãÆrý\«+ZÄócÏÚÞÌö˜Ýßn7›|GÄôlɵéB–Û,ñß&…ÎÍ•èUâxÝÞ´ð¢ÜYÇt¯§á ÏuoÏÉX¥u,Uu¢ 1Ó(ÈaҘ̉éõÔË£rM˨ÆGxMÏÝuN—~Ç ¬R¹nÛˆu]zÌnâ­ÞE˜‘:8lUOó=âÔ™xF³œë3ˆ1’Òúæ8Y´‹ võêó¡Çh¡C¿e+Hzxì<áù²õpADsç—³sŒ‰EbÉÆ—~Ó:Œö.$µÑ9lT›_5q§±%A¦’²% „(ÑP;ñìÐ;:ã%ULÄ9 ]ú<„b|*W @ùEfÊŸ*R˜Ä?5cýéÁ†Ÿ>~R}Dù+†~KwO= ôbXý6æ-ˆÇU…LÏÉxY¸kxÞ¼ Q˜T5MgÑh|c<ãî£Éé>?%ž¡u[Åò«Üz|Ó'Âù|˜^ªÚåÐCÌ8s™N®Tpg·LÁKá[ŽQæëIv¼ˆ—HsöU]Ã5™ÙÇ¢7ý †È’3œ¹Jš ݤ禅עËE›d«b¢ (¯[[PÞT,­F ŸÇ52?ðˆ‡xI÷‘ZhÛúmÂڇץFT®lg §§9ÓÒjÔ ’f$Â3Ž93þî;ÏXUrÞ÷—AÛ^a½(&ÁÛ–8_®YÚÓ·QлǃVªñS{ç0×Y Èp“‰²¢—@Çz/;$M.¼Ä‘$Îý+$Ê"é3â‹Í M\\£A4K–oR÷+!;Ôã…Ê #nfP>þ©s€äª¹„™BšwºÏ‰ä½ø™GNWW/ÛÊk)“ò¦ÈŽ5 Ѫ¶†(„ŸóÿrŠLlάÈÞ¢#\Ô;0õMÑ?8§8ðôG!Šõ‹Á °¡…€|óüÓ²9#Å\æèêâm#ö$¤›ý›—d½|0xD Hrrx2 BGŒy î†B´&È …çÓÒ*}­Éý¥ÓUKÆ·ÇnGT]gW•=Oµò;)RºxM4ÑO^´xð3óü˜ ü¢DaÃó$<Óöàòö“ú„‡, Ä^}Ù<Žô’‘ˆŠ / s¨ û_Ç®»ò|ŸpuÔn¼çàƒ£&ºœ²~àø3°y‹þ Û±‘ Kæ7–Aó°dÁ¸IzËM\HPB‘ÒN{òðKÉšœñ<$H>5•?w®³¨Ùø Y=ǹ9¶•Gl‘ÂW°V€˜vÊzh²Š%¡K ˜B DW6wã¼ÜÍï9$Ǫî"°%/ ²\‘4Q‰R·8ƒOÂrMÄdÞY'Ì—I¹™Óe¬ÍÓ‚Ànæ†ÒLè©!0Ù—£k3¾Í÷Aîôò“pí94ÞRNMæÍ›3¹–! 1G›®”ŽŽvsjp½æ©™k!à–L˜{ŒqÏžqŸÊ0@¬Eí"="N‚c#½^¥d­±-JÇNRd$¢#]Á¨óhìhb‚õtvðî õ˜µÓž¨‰õ*="€ÝËMt®¸Œ™—PC¿s>$÷?ú ™í—å!ɉFß()i¤0€ÉpÀ—DõšÀëD¦ï²¢ëã$œU¨M­Óë=DÏ3ËÕ)ëJذ-u,´x! Œ-VWÔŠîÝWM¶—¡5nN–±Ì´=ï«Ô)ê8¥¨Ñ¡j•áä”&§—cBTDôà ª*`*&b¦`˜­6ÑAL­(èM(P4¢L“P% ”£H1!H‹QÁ ±Eg.•2MĶd×"‡xÂN_4?˜ nµý„=»|¡Ãú øÄët¸a'œ)|±J¡œ±_§Cå Hu²WÕAÅ x ±'Q×S‹šÏŸÁŠc÷òéÐ$‘1LÍWìºØ2%U HSP$MS,NGY/:$£®0NªxôåÊé8°0 µìðÙš ¬rا×a¹ÚnyéÎhÌÂbTË–_C0Æ&Yk¥TX[ˆ“§º´÷†Ì‘òá*z"‡ôQPeÜOŽøø0mofaM ™ õ:WÆbܾ’êÎ@ªÖzCAË;ÙàQRQEºšÞ±*(¯è£K¦& l[6jm˜ŠÆýû$îcÉà§Iløòm¹ú^k‘8ð¾ðñúñÄ|ŸBØ\»ñâ‰ïÁTÂl ª'¢ ¢Iã©„ƒ³l³'ÃC·ì™¹Dþ?òI‡ßõ8wökK0íc³ ÒIå!^‰Xã$äŒO5Ãt¦cþ]Çæ/!:5í(ð;ΛO£IÓ¶ˆj=`ÊdFF7K4…!@ÑåF›ÞGø¬ÀC ¢NÙ0Õ–´þØŠf©"ˆŠd¥¨†_€/)"à 'ŒŒQ4¤LÂ&„‚üþCß×Ï|˜ÓŸNêÔLi="P/¾CHæÒúiˆ/ÍÞWk1A KI A;f(9<v”wP=HˆŒ2ìè ’ëÕR`ÑíÎ_™ëƒ²+çŒÏZtγ³y~Ôyõz(ý˜wH%z„ÝfëÇA2uup™ÁG$‘y0ìBý4lmÜ‹t—àhÉ4œ|úQÆ\å…æÍ(¢í1ænni “@˜å;‘:J”UP5äƒEÃ#tAb$Ø*˜Re£P»h"ñ\õÜ`Ó_–ñè‡ÆbÅHóè;dt„î ÐV2×vwf-l=´zŽÜA­Æ†€ªš±3ƒ‚8”&3 ¢+.1˜Á\ ! )£@W‡GIIñt„n "‰À» èAð°·`ÇTN|;C4%Ø@ß±ò ˆP”ª - ¨bêPs`ò!Òdº€9B¡ÂRÉ×Ê´!œï1`ûcÈN• Ђ…Âa…wªßÇ©©÷¾cѱ&˜¼OB01XªÁšÊ#D'ßd}žóÖÁÒá¤=ôQ?³–þp=?úMÇøRú»Fé°jQׇŽ)ôå蜵 ã£|ÇèB=^aÀÛíü?!´©J„’õf$2 @{A^Nh~ óþÎÈ—©nw•βü8=J4%*±+¶5BP4$ÂR¥)™á¾Y™D]ñ–æîø?!ˆ‡HòÀ™.ñ^‚MA«ÑóáßÚ‡Tû >ž÷ìp’|=ûªŽ`ß ãˆd8ÌÔ„ÑÛÚuž~Hø§«ø]“··JlKG3¨K«0Š$°„ÈDè óÀP ˆ6,ró8"vÃJ‚'šyœpOæ8›lÀ ‡r¦˜g…–o+"\ä²f٠ɃÃò[;öIy¹ÑËs'I&“ á%"ª«Zœ5ÕÍQPûO’ujN  oSkÚø²"—4»š]âb°ÂÀ=Å"mµëТsÞž½î=Ãq¨ Šh ]T‰"“‰¤N‚Pàt y2ãÆ 4ç0„%À”åå4$ 9!¢QÀp!É‚%9ÉÝǯ@% ±åäúÞ“Â:Nð xÒ̰ÎPÝç0.N°ãÓÌæÎØÀ4H¸Àç8¸#„¡HhStbË¥—¶f°“ç9}Êè_€ƒÖpL&',6νü_cz÷½•]Øê­¥R’½Óa'qŒ0Î(7Ö5 ÇuZ#k{姦#½ùõ}ãçc- #mÕA´(£Mg ‹lÇF¤tw»í»)zƒBù£Ù LIòÂiZ)wz4iý»R:Cåô~áÒ§0ËŠò Àû¸hP‡Ô•}M ü›#Òbj…ÝŽœ_CíRTA²æ/ÑÝáßyЦ`hP!ÒI$23ñ™Þá×Jt%q6Ô1.Ã4K”#ÕVVÀ—¬±}âÕ2d…½¬ÜÜL̨™ššªO]Á)›ÅÄQ¥—&ˆ®LÌæ°Pþž½þø±í9Ko›ºD’nJeäIËÒ vžs׆ALzµhØTý’»GÖ¼ !¿ æ|«ð̰~?MÁ@ƒäû°öz88ƒ‚²aÏÞ¶ÝOqÉØð—Û/É&¥êšM׋ä×/,”hƒõ=˜™ˆ¯Óîûðº Ñ“ÖÓY°ÒP‘ „5@Lô|Nt{üêy]Ç ‹ÁÍ`Šfù€a$¥ç•=RdüDóš2ã‹Ow¤;¬€yœˆÄ6MØCÓ̳0ùõö®ÇbÇCz‡%¤@Ù`Aç!—Ý÷ÚÉ´*²Ó@rd&ÉèIm§`N6¤é"ks¸$É á{˜5'_o·K”†Â]º`ò•6½ðÿô'æ‚Ð›Í ž“Ó q1Ä’²äÜß@êõª~m€;˜ôñǶÂõÁa‚Ó–¡>]ƒÌNÕjÊ„$žØ[Þy¸—¬à;C D’¯9_0JF ½gOøËÔ¿g«È–Q_Ÿgädç:Èͧ«“Ю (3gñÎO ÄòY6³åO’K¶é ºûŸÓœÎF!×ì:“ð†„zHð/®ÊdÔ@2 ²L¡pYâŸÉmÛü0do×¢¯É:ùeì%¡¤Hf†`f'ƒ‘xq<·cí>­ R4À r¢YjÔˆúh£Å«ü«$5EY'yú3åè'Ùâ|6}>Úóã&hÕ¾ºy¦ÑÂ@3A1ƒ_CöÞ`q=ñO1RpLZJÌ4+¦8ïüß×(S|foS(©â¹Ÿ³[Ôgx2SàäÖ¤ÞOE¡çŽvW‡Œ QŠÙE—ÕÛ—ˆZF&5!þI8Pô>7Å“¢é”D·fD.hÔ3Øp¶ŠŒLcPæ:œ`cméNçs‰Aþòs{Æ:œÆsyEàãÓ¨:¶Æ•övƼÇek7¤ƒSðšìt§‚|&Ú³×bDVS㎯‹š|%ÂÊnW4`Þù“(DZ¸PNGqåõ2ŽÙ¨VWU­E>!ñ™em^áÚ«ŠÎæõåE3^s±µ¸OO¼k¬F©aˆ,IÓÊJÇ#¥·rê‹–ÞÚê\Ðï§Õȶ«%ÓK hyÑù»œ²µ¯å¥»ï=åÂj`tÍdÇ/2*P!Î{ï8¶ÒÛKm-´¥)pšT7ßê¸ôäÖ¾™Í̇‹ïß+É‚uݯò“ÍÙòúበ|£³}u3¥ºzë—¨™$:™¿Ô ~%û‹”`9FMnû»‚g†Ç4 Ô¬ç© £e$0^$¡ÔJd{ÝýgÊé i}aíêäPÞ6ðÌ9¾_|'¢vËqôõhKˆ‰ˆ3QÂjO6ÕPïU&#´ïå¾¾žèÎà"yœë»×]Þ\X«Å™”µ†Œ`¬Æf -å3‘Q0Ñ•w­YœŽx›BTçODw«#;™Üó\çE¨¶Â$C•s4%/.ÑœÕ!&2€Å§têœÜ†Ó „g‚¤[¨ Ù¥K<]ì–2Q[&À;’jeÔ2RðòiŒ´Ð• ’CÑ‹âJ=ýÓ¤I¸Øau‡$¸F›QF ó1– xspDî3ág] çÓšÈûCiˆv‘0†o©\g4ŽšsÖhtQ¬q¥0ä ¡Ë%‹SššyiqÓ0bs|öcQf‰v—ÇPÐÒ™;”É¿$j•®$³.ænÚD©S´¤s,“dLÕž Æ ¢”Aã$`FÔ ì3®S6²îb‹ƒ”Ï›††]'AŒ¬â©¡Žk0“¼ˆ”‡ÑvÖÙÄÐGpn§˜¾ÈlÛãd`Å' €°êf‹[|áTíèNàR“m³')`pŠìècæ9-´’Ú[ZKh]ëæ½o]KÝ8µ… ¬7&Ü(µåD.0Ðdß:G‹‹¼’¦È¨£]°Ä–Ppy– |UèTeûÎSb8ØÆ2Ë•½N <3á®iáA ÆpÈÛ›–Ì$íAçƒjкLaËÔ"e@ !€Òi’tAOYJ9F ­p >D‚“8úbÎ¡Ž Ï *øˆßM¹hú»8]VóËE\‘à¶vy·‰%@˜Âu-‰ÃM£«Xi¶„ö[0Žc]¡ˆF±†©%S)ê:©rùsj0;9FÂ<±ÕN™ÛlbLŒGUßQž)ÝÙ&ÇêwLqÆg©‡ˆ½…ßWÕò ¼fwôg¥±úÄŽè]·sð^ÐäÖ§ï=íÞWMÄ7{ÄbÜléu aÜšËےΉÁ…Ë0˜‡ÈÚPdi¹e*áï~fÜ2.)ÀEQ4ún#EtÐ}1Ÿšõ˜g®å<пW)”¶ôt´xU‰*dÜæzŠÌgF´fUƒC8ÀÌE{šSâCG’¡x·A‚f6¤ÎŠåZC„Ó~S3Ëñ Ò~·cˆj/œË[ؤÓïÁJÜ–æ]2ƒÖb ±ô9ÎÑ8:íT“DÿTyÙ“„èñ––”VàÈN‹J@|@˜#:C“ÈŒ'ûÑœ2¼­×‹3uЪ1HôͯIÆ-óòy=ÞIÊusWG4O1WŽ\~)§:çœn9Ž4¶A˜©Ô¼½‹Eó¬®Pêš1/¬:V©U'S­Û«syÜqÇ/Ï&öF§0WEÛbÇ3CÁP j^ËM‹«– ØsfkV°î•«wMz99X-®¯WT™2w)¦b ´!4o%Êæ˜'±) Rí-¸3[¸QO‚[&ш|&1Äšºç¥xåÑ ëþ“€±%\ÅŽ£R; HMæË¢Ü…Äl@‹©SZ •þRÁÕV§&'/"l BN”B& &ÍðÜ_(ÀY¹Ë˜ÞŬEûÎ'j2$Â’iG9/]lõç‚z̞ςYÝOµû6 %:9Óœ,#—yŒD=¼4ô™øZ3¬f €Ç×}Ý,ž…§©í-Äïž“{|K µˆÔ-Ö'. ¤ÌÁš\ržÂY¶Ã¦ÎÞÃZÁ^4% J‡ÝgˆËÃ"žv–î"ÿneR6øF¡½ Ý<~ Õ[2 U_ý˜8 ŠAÑ==þ=Ó¬ô`¢bèsG‘<É©Eå• ¾¼Bô|J.`âÞ7€2Ø…€—·¦À4½3‡4?Ù·Ä»¨vÛÆžc.å½gt¸âei}M¹’AøTðL½ÜWF~ÜS`ÅÄ@é=&4žÝŒs¨!:4¡^Ñ1§¥±­ç•]¶]mØÖ-˜Ó[Û;цFÜe)Ç7áX1ƃƒÛ_-Ê «m”z€îbD#èòå5“Ý.›)L7Ÿd2QrSmš(ßÃŽ à ÀJ™È4À¦fŒ Á«$®ÉŽÏ×AÞΩÒÂï­ðx§yaíÅxJH‘%J(4lYÛs±À4L. :T´Pt‡ßÌà9`׎á¾ù]…Õ¤)fÖš†@†‘…0´¨~Õ<ƃö G§ì8bð]õE¸ãetÑÎ`" +$­gâ¡“LQ³8Z N áºß£ymO*œ,b«¾È•´ÍÁ4ƒý¬!J+À D ù¿'xw–ÅŠœ:’ÌLʦ,2H±Œ o¡ôÕ%ñ~~Î ˆ"T¡ "¢I•ƒ«†j¸Q­»ë»ÒÐ@›&ž±ÁUØÁc`f#°˜)™"j%`žMøÚ#¬^\vf-4>η‰BŽš”y5éCï*'”¡à*ª[üP/ì=…œšµKA‰Œdrè~XOÜÑ‘ÉCû >>Käû´¼AF…Ðb€ŠÇß‚ío;μ8Z¡ÓÇEýà{¬›Õ;Àwxø¬¨t§“2Œ@É@’="[‡vM$QD±Q¸â ÜÝÇAÕȆˆ<Ž%zîÊq”<'É|—Î&²<$œâZB6°œI³/¬£Ã=¸ÃrôFÀSÄ2³BtbTÎÛ4LõÐWqÄQÆÂxÁˆ|¼"‚`¥¥Z,Ê“°m• Û#ˆ)£lÌöÅ2´U‚×&_/ 1‚ÀB] ÚͲEÍ$\ˆ tKvry%'€xé ³Û ÉÇ›¶ëº¢ÙºûÍ76ó Œ™« MC?ky`H€rðnÙ¸®×Ch“-*$Ò3œOæì“‘Ë—pò6Û6~0ØîmðÔža£ÏSV(£P2L¡Ä=CI§‡¼,5†ÇZo‚Vb=D®Þº¤èèñ¬ÈÐO&Q6JpAɃVÔ†P¢"gk…³TÊTMR»¹hm—ÛJB¦hÕDÌC‰ 6`ÖãrÌm§aœ¸Î8jKÑôb¤fb…œg8JšÓ8™¬—%¿AŠÕa¢rL‹f}ç ~#±ä'˜c ÌO5,¶ûJéÝÃr¸ñÇ­ˆE‚"T=½vÁ:<_NÒíÙ˜N7Q:r,²ž^âbÈfbJî¹yq™Í"6ÝÉí·ypã@€a3 ÌQ’9R)ݾݑIØÆf‰3K RÓRT¥*ƒJU(û8söçÛ}éŽîçÒb >™„Ôgv'Z;:=#Æ0„§~3¾€ ȃ…CXIø¼M®“”Ý3PÞ#vgDs DKŒUûÃNLä°vÄœ§Ä¥ày¤ÇÃ(¥(d/ ]9ÎG§!PÃŒÉ'™,ùk…e=I¶|å2La†xÁ%îlf–ª†hp‘UÌ §f#|$“Ô‰ 7‰($ÿJ ™ÒdO¸æ!8 ÊUô£`õ&DrSÍ&@B$¦2 ܆áÀ© H‘èP?dC"¿Oš"†®›bªš*€‚fÛ™8"§¬´ÔA{Ø aìeë׆»Œ#ÌÈB„•:™!øôvjÌÈ'Tæ²êÈIx¶%PÒó¸ã‡‰ÉÁ†$4µVÂÉ!­fM,¨æ6ê3¥ÍÕY’ΤœÎGáû3yrž"BÕ¸Ùó7êÛçѱS{‡êîÈ•‰¡ôfZóæ¥DîÀgɽBz/H&‡DùfƒªSÛ)“ÃûŒÞzÈÞL“úR\a4r™H@ÓòÙúwô'åpl2³’'Úú’£ß­î/0z;ž1*R/’yl}9õ´øJú#„<ˆ"ìÐiü²×Ô!Ñ'ß ¸ ùƒæWÐÏ’÷¼ »ý„çº0wÂîÒk¢/ª(Ÿ¶:6Ð…(ùµ*Пà†—¢•âJ¡}¤¾ÉÞRÚJú„ J½(½#  hGJ)H#’)IÑ a#JÐR´„ƒ’(R­ Ð *Dº¥ ûŸs¡@¬!ˆ(=…4J½ ¤u.Ò †ÄŸÍo 4íP¦€éF•N‡ÝÁ ¥î4Š>¤>.€»¸”ziÒ4¦–’%ëJèO$ #H Ä>¡Bš¡òt BbT§Ð!­%Ðt.!òAÒ¾TˆÐ›Î䨆…ò + Z×Û!ñ— ò^ƒ»)Òè4€í€_RŸ©Gy…4M-)êhèéB‚iF” Z    <ÙCÈ¡:P¤ˆ CÈà…é4#¥]*>˜7úùCT¾HŸò@t=h–„J„  (t‹è.µÐ&‘:=ʺ)„ ¤Z‘òW7Bôšˆ) ¤G@AÐ3&CHéKHt!¥ €È]Hä¾2¦J¾Ü@ÔªŽÊ?¿J|ÇŸ/Ñð离Š ­™d²d3Jå‚Ñͦl(2,”Kp` J@Ec?® °Û!%ŒÄ˜ ®ÝÙ¦áëÃ%Á^G+ÓµŸG°ùd^Þ¬CªG ¨àÀ9*ò!)ˆ– "Y €á)Â'!}ª3!ÕÔ ó>h9a›Šu’…œ¿å*tƒbp„¬žØMZ¢(4œ°ôבê§HhP¶ê:½½j/œÆ~.¼æ¬8×’—SJ°Ož¾,PY?@_xÙ…ˆŸèƒƒŒŠµýÕ„ùC¥)&yˆúd2˜i|É¿ªÄÇ›5æ÷I)éã7Ž,Ð(Á’a¤~‘@Ö€ÞÒc¡åY,Üß} ZÄCP€ZHøMP)±, :jHõ76 ˜ï1þ¡®5ë&úœNè FNö €Å e=Ììï³FWì*|äiQû~Ú¸ŽL1»Þ­Ks¹üû·e£›ÒÁ†VÑ’µ¬Ö0g e—U„J“s AS»s , ¶ìlfm}/qƒÖœì8N^z:j¸âúç˜n´…±-“F\ÆMÝܳ4¤BØÏ›¬QÇN¼ž 8¨à‰ªL5 ˜ælª74Ù’€Ã4“S72·Ip³=^^^]¥ëY:Ž«O³DoaÎxŽ‚6 Ñ™š‡!DÛ”€ÈEÑÊ«2Ì9\$8Vç& HÎW7HH³ ¡´´äë:C„.¸a²ÄÈ!É…×qÚ  )IÔL»sc6¹a°òéFd4 å¹L¼Ä8p `yJ@í4Ø$mÆ„2jÐI‰kxÅtæS¤Ý¶&ak%6 ‚VI eÆ4¥vºŒ¡…™¼·µŠX$˜ ˜A2M·dI)4(«²ÐKØn.p›",Yƒ0’5m»ÄŠ£‹8 'ˆ ôç9°ÖÔIfá)-H¶lrlf]š)¸Ú»ÎiЗœ^æ[¨¹pQ¥dˆã9,É2Q5­ 3–í׎•9S›»» „„'¢r¤ç-fê_'b×ó÷žš“Îë’kÔk’†± mÜ#Ú@ËÄ™€é4ìõÅi5€.˜x=>£u£ÎÆíFêÚP:z$¦€é¶«ÕZ.ós2í@r¡­‡I¶Š*!§Xi!ØM]ŸW0ºÅwÍÄF#$¥ïÎ.‚t^øÄÜê=çq¶Ç0i`"hàm C¬°•n,È£†Ž«Ë×Viïx8ñµÝžòÈA åëÖð Ò-.ŒLLTE4QEEEÀè)+0$Ìäa“η«×7w %¶£F.‡y¼ž€×½Ùq&ŠáÛ`Õh´QhB‡¥Ñ:µ¬¢³,KµWx{·â2=h»(n§zrä ¤("¢bc1kë'4W9‚"Ñ0i0ZÐÄ›amœ!5ˆÌæ4š†’ 7\PÌÒLÅ9…ÀäzÏ2wíøx\Ý*&Ör̃Mcmlh1¬FÐÑòwiUSÇ¯Š‡?â=>îÿ/1:HÙ ;£ªWPû ÈÉ gx9B’o&ó0ÒŽBRá-C;AÕQ1OšMF„é:W¥) ^†”h: *tô&ƒBýÿ §H'£Ä…t{(:¡kJ’×°ú FQõ?rAÒ¨y²bˆt ¡hGJµ¡(_pj4û¡2ó@¯RÓ¯!š=ú½ ¶Cà;û@𷘑g0Äèq:8¨b)zµõ±¶/ipCG,S¬º@`ÌŸ“7%+ë·ùScOn>à$6@æ¾y†‚‚b)ýì3ŠpTWÙl’Ô„‘U @uŠŠY*ЍšI¦€ ˆd(¨MR.¨ª LA¨%"FÅlêØÄh΃»h$Ûðå3PP””WcZÄ ˆo˧áåm*¹ñ3-ATÑQ31A3$LGmAı HP„ÅIc B¡ªIXñŠ È‰Ê%i6߉×!GŒ!ãð¾*Bûƒ©Üæº}{{%80|Ÿß &™ëçZûÔ×pÏA|¿6!àq%<ÀD7=¥0yÍ猆$§=1& þ'ÖQø”f~MæÕ±÷ÞCÇNq VØ›kÊrZ±OR).9‡]~ËËÊ"@AÂÁ 0‹Ð‡°W° y"÷êËÀx+HPý  ˆÄLiCRª´…*“ÊDETH% P RA(9)/_ ~œ„<™ÌPäp€xÀ‚{w}f”v$i4P¯,ìšà=s2ÐPa÷Y2JÒƒfòKl+¥q¯sŽkwA·&%“;vsP$ÃÅN¡%Rw²ÞocçœÉ¯yËÞï—‡OaoqÔ¥ ‡rp88OªÂh)…vAŠbmÈFDÌ™x^î0úÄ™‚½·,©Ñ”¡Ç’s¢ç0“ Þé§O0ðÚ›Äé¡wIüîî%â ÃÖÍÉlj—Bmà._I²úuÍÞS9[åä ÇÁfNµŒKq £ wã¼Ês˜Ël(,ì[Œ!à¼6Ì™::ù/ëmº:õpe1tHBHZž„»k‡ƒin[\Ë ä‡i¤ÓQÕ ´Û2jÐTJS†û0* 11µ<,¢JI: =áuªªvç.p<^ïa6uM»8yÚfÍœªJÚ2[HIòU>K†\2n"–íÂ2ù‡9(Û.^Î7ktÂC0ÂVžÒD‹Fž”µü/ª¹ãF­­ÝÛm]ݧMókM.âœYɬL‡ xvI&•¸®ZkD9,»aaî@«Å iOGS4e¶¢ÕÙ Ýmbp›:è|“Èz>!C—wç&PÈÒ©':i )Kœå¢MB Ž&Ÿ&!u"px=ˆóq(ŸÀ^Wæž/ ´öÓ¿¸æ‰×³Â^—’4~ñ²hÛ`„"ŠŠJhN í:K0R€Ò(¾L½Aýȼ¯¸;• ˜e–ª” jdÎá9(;íåÄèŒAJ–M@j÷À{¤rSè_}SkÔÈ~ÀòÀgQ×Á<—D øñ×FòíÐtâ tò?”#Ūä> Êï5 ïly!‡-•¥ÂÒB½ãÃþ¥¨š¼} IÄ4Xº\Ñ–¸'m¸®Ä¸ú'á`ô«œ¸¦ÒÐ%!AÁdz¼WP½«·‰EóÝ‘ÏüÎiÖ?óƒt‘Ö‘ ‡×‡ûawzì;¡O˜>OùýÆ10ùÌPʃ»}ONÄ –> ¤(Ì1‰Q¦YD¡R_q-ï†1‘<¢ƒÀ@õÂÒ*4PR”-›pñìw <ñ¥Ñ:ÖJw!èÀäª<€ÑϦZ')’Š ¢$bˆHX•‚ÑßÞ·†]À<ʦ‚•pšG ådÌô¢"PJPÉ!X¡¤‰ãÓ@éɺÓIßS÷îo¹²:öyÔÅ ë•É {OYÄ󪃲 µJˆp‡d|W‚>èÁGýæÊvòy§å‘qF?ôL:Ï«_¤ÏÜFê§õ:‡B ì‘h$A!JeXj©–– ¤ D¨ŸhªmJ®Ó×èš@?>ÇX›=Ûyó>Ö¼^:ƒê3ÔCNŽ«Þ˜ý%EReœ†yÐI£ eŸ 6 ´?»§ÿQå¦iÐGÁõÀÀ@”äƒh(ѧÑ!¯úOØ¢Š(T}ù þÿ&Ú3 ÚJ§bÙ<+Æ2Üá´/‰ÎÙŠùßÒü@ðጠÊHDrsºDù¦ _ámÖû$eXù {]@d_ð”@XÜA¤ød DLBºÔ•C¸1Õ4çÀÇVq£âÐÑ$ Þ» »²rv(¬Hš¤JZU¤bB©ˆ*š¦˜ª$¡ (¨ ì÷’îlÈp€ú%û×B^h€õ¤€!¡êE—–ÛªzáZ@‚†H–¾´#a¤ }°ùUˆŠ,H\¿`“ƒ7©_/¦o¡Ó»·Mr;¤À ÉêB0ÀÂk‹ &lS!Ël$mÙž¨Ø§ÁáÂüÐ>ˆMçª}öAB{IÈ=Òo.’ÞrCi2~ƒ5 D:“Ã?ÓSP‰Â^P&¥Jð%7=­±W¿xd Z¡¤Ð?ITõ Ò‡“ÒôwÐ3¥èo®ˆ£ü­ÄŽð‰TÐt rxQr†„È CäÞ.‹ˆy¹§4ðôÒ¿q ¥Yãç1l•!P̧DìS¾;‰ððüóDÄϧ0 ³& bîü66²ØàŒgV6(5h΢°~×qDy>\kE0öÝŠÄBZd­]8)BÐÕ-AfÃüpsOf ¼±Û=À´iÚÔf˜*-.üì”!+ɳÛܺË Ì3)JR´Ó0`aƒºúÙËãNn`!± á•:ðgÂ:ɰ]Îã=æòZb½â¼<R ðƒÉ<º±bM&;¤#¶ht¼‘ö…åDʇ¨=BôémÛpŽ"„ᔑI¢JJÁ±=¿äl!Ðòd ÷œ¸4SAÑÔ}„;ÌÚ Z4©l¸¸%ÅF‘Ð= ô:ŽÔ}e ¼ÚåSƒ~¿‘Aüˆ KåQ"× V1Jl ·ï uâ¿1ùñåL´‡sýÛ+÷S>Ÿ½þk׫ …‰îõ}ìÁV•`T§ØP8…8Ëæ©Ú#&µEÓ`°újÛ¢*)TQMJIáe°RÊæðsé¯+DWQr ìåêZ[X|,Á¤|{^Ã\3‰'ÚÏvfƒVz½#¼ÿŒú´ýûȰ÷Ÿñi„ÆPAk|ç–Oøgm' wx.4'û`ÐׂÛðŸL t?L‰ÀS“ç-(r…(‚5¡÷AOÀT'uFºƒ*) Ø-€<¡EmPú_çM0†P H( S+¿{—ÔÔ9„`­¸pa¥Ïoò˜ÆhXÖùë{pHéŽ^¯.iÉ®°›³z•mŠÖ¾Òsq%lc}„üÂWó•2é¤JfD ¥hÔFÁ°¿ªqÁƒ@˜‘û2t%Îp üPE–W&%á"nõø\®<8pg‹!EĘyÄh(ñ=>ƒB‡ÒÓŠu/TF q¹+é…ÍÂX úî¾ÏF¶Ìà®óËIÖ´”_žýÅAQy ä Òù=p#2b3)Zý½¦“cÄglQ^`óÌ Æ2ãb¦ÛQ²˜‘kJÖ½l=Ÿ<|Ža™RÄ¡ ª1èõ–H+)-°64Dí°j<®\Š^`xòôÎ:U rëÏv ^…è÷ªËÅL•óNµ4Æ eqt€°¦¨¿ÛØÈ\`O Àä!ä3R[((¡I3§gNÁííÄÀZnˆß«½Zw˜Èøÿ`Žex %LŠPZR ß„N #B¥R ¡Ì´¢xŽdŸo§kàïRDqTP—†0Tš1DkE(S‚£4DQZ ’GŸM08†ÊÍ!A z"ï·‹µèô‹ÅIïmê‡$ý»ŽÓOßsdŒ€rV7¹ˆÃñfÄÊ,éeE,*‚†Lpì*¥vaî]ÍŒKN0VAÑ@ö¯$ñ»¥zäƒÙõ>^ ¦‚) ()i E‘ß•™_†Âá®6Ô¤ØF©.ª¶ØÄZÍÜ@ÅO·µ¯·ñ$¤dØ|gNFç–Ÿ}§¸0ÝMßl)¿ðéà <ãý#³qò°‰é¤¤IùhP÷ 1»ùÞq>ì¸Îúg=/öM)¯¤åxQî~„µ†‘AHYÑÍó|`à¾.[ &¿{Þjå"d"b6<ަ(L"3!‚èt«¥¯ï]û‹¨[ çC>J¤%+ÖõõÖÞv wÿj—õO ÆLñ>c¯U“€îOÀ@¥š¢×ž ÁÉ>8û¥7B´ºburº½)¥ôýÆ*ò“PŸZR7\€jDpzH$ç.ÜÞ'R„Cç0fà"#gfªó¸UR ƒæÏnð“!;¥å%t-å*ŠHŠOÃô4ÕÆ!û3éï>8OA*y âȘ¯âÐ`yö`´š¸‡¢’•Òh¤t$ž vr:éü¡ò•<"„- PŒJÿÝ#á4€¡ŒC­!U@ÐÖØîŶDš`‰h(Zvßiþ®™€¡3'£·ØZ>¨W•KÒ……N z«`öãäA{Ñ<$.ÙO,£I© »_Õ €øH¼å‰F   © ݃AÐ~‰¡<Ƚ t“Sy y/ÞdM ä.€‰Câ6•Ô‹BÒ;E(™Êš€OcÔœñ¿$—H…ê}ÀyÆ‹¼Îà}ÚT<üài€#'gn§˜æþìÍø§c:µ©Ä/A“®Ê XHD ûB¼«2Ÿ?£BûøV…o>SrÃúܽŽÑÃÜ•¹)ÀxFʦ&'jx(A/ˆ:î]hè ‡®éÔ§ ÞEN†ùž(®ÊñIO˜> _£Ä$¿Ñž®?á4¬É i¨g,›ÁECP¬øÿIípñ’Ä‘S 2sÄWÊRÅIR?—:©¾’»þ¯¿ JéÂúÎkO±¦L”`IbP€k_n<ÐEùÊzI÷ xh§ÚêòõSîsGzÏ„q/ž¼ðþ zÉŠ,@oxÑ%¤Ó/Ï_–àð#¾ñó>;ÔŠ‰~9MÈy9ö;`?Í Ä”¥È(¨–pß Ý²æ©ÃŽˆø<Ú?¾@Žæ—W {Ê£¤ppb²Þ³jH¨¡j §ò†Ø€3û8³(_ø'NlFöb,\ ‡C^®á³&$ÏžßÄŸ_êZ)åLd€IL}nš™"_‰úF?ùÓäûZ²B$ÃöÐ;+Îd è´†¤w„FÚÈSaiÅj2ŒÞ±5Ñ»À¢ö³çI¸ˆMÖÐñ…‰–1ŒA¯Ùš:£$ â…:»Å»ðæ?Ÿ>?®ˆ/ÿI‡ÎλA„öXÿ¯·väFuV* nAR°lGJ4´§•d‚ë]Pö¹AQëôðŒ°lkbù·…¨nž\Mï²áÒoÐoŒh´^hnìž.ÿ;¾}'£ÒÕSEo¤…]²e£¡6eYT…5Ÿ/^nDãž®¼b“¼»©^têÓ?·ÅÖ龺o¾„›#0`Ïy$S+Ù ¶!3.ÑºŠ *†aˆC0% 4$sÉà§Æx¹<õw‡ÛÒÔ\ÊG{Ë¥°ò¦°àhOàåFrnjn‡6’p¿ >%a™ÿ¿•,zã|Dv ‡¨?]ncµîe1í¨S(wMÖ8G™W™Ì7¶'Û·¸¶ºŽV ö†³Vrf³ ¹ÆC=R†héÜqͦ…øí8¤ö"5Ä`Ë~,ŠunÑÌ få¸åé“c>™c¾ŽNž°™Ì›#¶e!&Ë¥—ôÃÆëáØâëˆÁKél3›{0LE·äpZc]—ÃWs2ÚÔÛ»fTÓE¿I*°#ÚÚÚY2ccè!Ã9±l¦øLµ°µ"ç—‡AÈÒ@H ò¹«ËUÁøÒ!²¢ŠWAÚ4‹v¼ig¦B"U™•+q…ŒºÊ_VàFnãÈ}žú.HBABPmø9œ‘ãU××Òk¥&{õ!¤K´SÒ ƒŽ9øþ†4Çã„ádý7߇x:xÖÀégð{»¯IÃ5áí1u¶›_ïî ø£™fXlFO(™Œ½q¢ŒñÌÞKL&ºûôÈÆb„©”HRi†ÕðuÈ7hÀ?IÐIÑÚ¬FY¶µ]“Ì?õÀ#;ÅP¤*3Lš6î"ÁŽ: áûe’$• UeŠ%EŠY""Tó‰ÝÙxøùm·?ßéä'8T¥iiC£$‘GaøÌþ¹Dä }Ì(~bM wÔ³*È …ý^CÇJ± ”*kÕÖ}w_øÕ¿ÊYæ,úÓfü•Meº,¦ËÀŠV8ýȲICÂ^ß É O4™#‡yÁù~x/‹¯ŸÁèVà pðkÑ”9Ëê3Í È5$ô@:•™GËáyjmq£ã #8uœçƒùËýxŒ”^"ŠÁ%‘»#ºÌ"GB3T}1n\`z!”šœ»þ^ îŒ+Ê!tóÍ?¢L.Öw.¹ÛJ×NÞÿ¼~t&´Îæ=êNÕ߃¸ðA¶ëÖª±Ÿ2Ü6Ã'›ðºn µŽ|S_V“èùœ‘²HlÃz94HÙXþK}VïÜÕÑPøh¶¨s¡ûó_ûTîŸ ¼4ðˆì9 ‰C—ÎCèx‹éÀ}ƒXîQÈGÕbÆ3˜‹d"½D¦¡>bAœiõò×ûO_žÍ|1ç‹nÇnÏ·Õ¢êÙC&G.`œõ¸:9ó|Ûò^§UXõÒ˜Îu¾„“úÕµ¼¾ˆ©¡íñ–<ËõX…kæóÎÄN5ÖO›æ9$¨Ùó€ŠD“º;ÑÇîíQá7ÐÞ¡• ¦ù=Y©®»™õÇd®½ö$r¹u¹ƒ*{žözÅXJ:XšBT?‚d«§R°SŽò†&ÿå¤fg!â\”ó½ÒŒ½îvU<Çl¶N)‚þ•ý³<>HAOvMòT½Q\3•ƤVY xo®¸B3û|ü®ÜšÌç½LŒ’Ì92ŸSô…Á>˜ÀüFò€˜‘õcÔ:7ÍÝR´Àk ë¢9Ç}r!]&'ˆÕ X$Ò´â aìf‡ˆb¼XóH7ŒÁ:Ã90ßßD‰„ eÁwëýÓDçP<1x€T0ÑD¤…+CQ40“2â¤ÔׄAX,?ÎCJn tCS&éñxm‹3ƒ"-…8`9¡âwß;pÜœíÌá@Ž90†èfnL2$!0è£^橉¯S†õš2lǬAÈð÷¾ aæŒ"Œ‘DÌÂï³K;ÞSêI—E%‡tCNí5ä´Ã;ôrÞâ{ïw» j«µØkÖïÖCf\Š)­^¢šSzÝçbasz9lcÑ…ª±.Šd>ÈÞvù†Ü‹OI½m=ÙN±ÀÒÓ,¨bF¥€ÑeòcXŠ™œM °fák‹ÑÌ/…ÖS&BL6m• ŽI¶+ ‹ A- ÑÍÕ.ª Õ #à¾K¾ Ãëh±ô”9<ž”‰Ês †S› ¥Ä`¹´““I·”ºœð²¥æÈFÈÖŒ·†TÁ|I&Hœ¡":˜–j ÌíÏc®I'!ß;𤄠“Gë™GI’ãaá`hSâQÑî|¨ŠŸ-ë ‰}cMêw™Ì¶·ÁÙ{w+,²t;¹6+Á²Û¦Ü¿w£Ó;™@Nø• šQ†D˜á¨bJ&l>‹rZl² ^0›ª°áŒ‚örzÃ0BVañ“ñã°kXD;ãölxEƒšÐë®ìfG—Ó`'–©C4žTíõz0ÎÛSM+ iq})eŒ‚·A7ëºY…‘ @_›ƒ¹E%ŠíYlÃX߀I¶GbPßbaƒ»» NE}g˜ç9Ü’s‡Öt¿W>^zCC¤ ¡'c&Üê•n€XD0”ÂÓ?êNš³Y6˜ÏIÕÀ77(£Â‹Øý_Éúß’u" 4–¬2H˜>L<9‰P§õ~©ývt"‰žÒê˜_[X{m"áá¥Í5¶ß¢ÜœÜ‹rÏ_v¯¡*ÓR0D¦ÀökfR4C 周¯Òcµ½2ñ”ð'Û³çýªb!ÒATL‚2GÜrÁ™›UÛÛ5-ö¢Ç AI  ô`À}w®t†´Ä>Ø×Cê;h~‡mǸæ½è!ðã˜S{|ã_‡Íýpv}‰zŽàï{$‰©~QPz¡¡J±ëü›½7¬²ðÆ­ØÀn!$†é«œȜI¤¨ccÊÊ.‰ƒ‹&1E½C™×Â=SáÝã§–¨çô”rÐuÌ43DC;øqÛ¿®‰=—ºŠÃû5>p>îDÚl  õ)*ä$äX½ÊªÝN@ãA¯“X`£ÁFL0v¯#ò TíÊL(•ÔO¸ópáw˼vz2­—Ÿ›Ý¸6v½µÙ“i4’ñf)gÛõdGìðø1‚ƒ‚C¥ú"ûrTrú ¯o:B$ë&V_ºó¦¦Ç&í½ÚZ¥OÜøeÙÜMpp¬&P`™cRÜ!®“,Ã\<¦C’:NGØ©M „$@ïœÂÅ#}8ŒLÅÂjÛLÊ·s…¸Œ¼YQLì!¯Ph›¹ÁŒÔ*V è ßtð§fÙŠl$r÷o]s¹Â÷¢ç½¯ó(âtõ"nü¯ ªLŽãá7¯\Øej* êÒÎ"ëßÚsܧy€ <çVèˆ"àÕ?nÛŒüË–1Á¹‘“ Òå=_û¾€Þèô÷õWåï/ËA…*~sMmª™w4ቊ4×3M§‰ñDøÙÚ6IÞtöÆ íèà0´¡¸E(zó`ÈÁ2.\‹fCàƒ¨ñoÙz•DH›Ši*‘‚ìK˜á· gˆÎ·šK äÊõÝ©0€2Îq5%yy~Î팈R ;y?qû›s´ãåîHSÞCmŸ¿ásÚpUĪèÞFC_`C‡ÞÜ$— d´7³ß óªè=,)ÍUXOõöê@Å@65'Ù?¦  49êò@S±ÇŸM,\!D“B m‡`/ñËB4§þ°ã ¨÷t<âX„Y‘R’EšDJTBöŸê B  ,¬BP4PíÐ:ñ:ä¥ ‰ € ’"8g`¯jT‰)EMR µÁSåX?\ ù}%&ê)Dq¨óëaî ¸gxÒjåøüB™¯Ã^òå¨tn…òäB}´]’˜( §ç/ì&º(ÊJšfxË<èÚBhîÿ»6Nc9²}¹NPçó¹ëë;òMøçŽ­þfá3•(ŽZ?ÊÿÞ݉"…dXª\L,³—°î"˜(ƒ( #,’~|çKçÜiõîºíñ5qšžÙø8 5ëÍœn"±ró'-¶6Ùf%•–+L\LÌŽîÐ:G壃‰òµlêãü5D¼õo4ª5vÜ oô˜®Ä·Ú/»ÌëÅ$Û¿úÛ¯ñêS'»û –ß9PN{díO–Û$†$P5ÑÓÑ׳ã÷¥kÙlü7OÌ9ˇقGW~ÍýÍæý°iÀþxtáDÞú–i$XüLMvfe’YÂKi†‘ÓÎNÅÑvuÚy«¶"}¾YªIvm(!® óµ”PˆÃP¦‘úsõú¥yc“Þuq¢Œd*ngBøöçÉ$eðŽœu:ÖŒ;`õÓÁè›i¢s°Æ¥Xǹ.Sb ãáÚM€²È×ce4Ù˜tb±uòhm—Ã#ß¶c/ÄHÞ8ü÷ƳÒ}om-ÊÅá:W¼a<Ú?Ešäè¼ën…œ!K…›òœ28Ve.·¡ô÷3a&fôÑWBwËW<¤§ æ"ÎÓëˆjº7#¬”Ñ Z鋊I(>ÇÚ–½M=f š.îß=¨,V@éÔEL©SB‹È4¸Î‚û÷~²÷Å+ˆjaAAz¢±B(7c4 Pøþ@I»‡¹-ÅCÏî%uHJv6>Ë·ñIñæD‚÷«Tù¾l·çÃhD8óóÁEýÝY¦Ë ÅÀ È3ð“ZÆ¢D”f.@dðòu¸ÙôíÜlLÓu•ܹ„8o?RÃ|^ÒB<È‘@(€=ܼàÁ}£þ‰úšOükÿ¶¹fÒp“úaÊ?¹'{‘t“ô~€2õŸåôþ¿}i°ùD‡ðÅi>u.qÜ“iPêîã®NT+ZÛ‚á…Ãr0¿ë³,Œ•‡ï{Øä0vØ~ü\=ÿòò÷¯>?/ø`=gú÷§îÂ>p7^…2E@:v88ú>eFœÛéñþƒiÛ2…¨œªÿáÜO܃†§êúŸ«gÄÏàHüæ7zz.gëîê ÑQXžá_ŸïœÑÙágoO$ÔÁݯ»ÅVlÖ…ž¡V†¢ ýŸêöƒËƒü»ÉNeˆÂä{3o;àÍìúMØüØïVYÙ:÷äMÏ»ÁÅ5Œ¿í©Rœ›G]O˜µqú¾ÿÈ~( ý¨ÓØ„S³¥“ûSöÿ˜ ¬“)¬Ï„˜÷ŒÿÄ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€@1À¿y@ ïa¡ôè +T"ÞûkÏÛÞ³¹¯^cw—¾·6/7”îö¶Ç±¶ÌO¾{»ÝÏÍê±[Þw—­ïwÐ&òàϳŸg¥^Ìê&öÑÑ»[$@÷0H]÷°ûwOnPA>–zæöÛ9»œbõÞpÞzîÙ›Zé¨ ûï¾ùÀ}êöàRÓÝ×o§ºíÊ—kdÞ¢Ök4)½€5Ûhï»QNm²­+!wpo¸w`ß=Ÿ{Ñ×ÛlÜnìï–ð‘PF6¦±Ó;Εm¦ØÑ¬¤ƒ×v­€¦±öÁ]]Q9†"ž]±Ð”Ò€7Xt¶šŽç]GZrh u–€í®öõäå½ÔÜJ…¨ª'mžºæ3/¾÷¶Çªt e:Ó»¸uݺ ŠAt‚ÕÛ+ݨ:_fª©\³f5ˆƒLì¹M}€Ðf¢‰°Ïc(©NÍD%î²€ÖxvàZÔ Y“žäº}[œ3ÛvП}Ïzc¸îz»|M¶ŠÑô+íéÎŽ´éEÖ 4]íÞ´ÞíÀÙõñ¯{0Pöžùw½òû<øØ ÓÐ.­;xÓ³,äñöVóæø7yÛß;¯9sؾκÏo½4UT“Mìv6Ö/N诵ÍÔcof¨ Q:ÔÛ§Ð$T(w›½{^\·wtõ¶ïž·8gÜÎlžØ¼Ý€c;Nûâ·½¾ø1æS5²e¤×!¡»IoA©žï÷}o·a«@Ý®²€òÌ|}o¦+Ûêõ÷¯8ù½Ý®]ྒR_#7ظ¾Û¾­ÞöâÚ}:ì÷T]»¾ûzqÜ}ãrc­WÕñ”÷|yïY¤$ôu®µ¥+­ fG>]:5 ¾ÕדּÞÊ£L ózíÏaï0è TT ï'qõ«¹ï¾t·¶Ö¯»ìÏ»áÒ_>Á§J ;¾XïWÛG­²÷t·ræ*”Žûwm¦>ûyæ­KQT&ïw½‹€ îÜ-2{Þô½ÜrFÆv ÖB)BÛ7a¼3s|¦€÷À€Éè Ù×}³<µ¯ ƒ&ïp¡@ûµ]ÚI¢}Áâð€`[r§.k¥íéí½MÎõ»ww½³7£GOºàßU½©Örb¢SÛto¯»çÆ*è[C[jÖ½žæ¹µ³OmÓvõÕlÛÝ.l׬©ôÓpºM/Y·w³èï|Ü´mwt¨¡Gl‚Ùªò}Îy³…¸ûÛ½lH–Õ¢+ù:÷ÙóÛ=>Û½™êÓ{7Ü.àÏtãGx]Mf'¼x—cƒéÞöì—q¯‘$ã/»uš½2ÉgmÞ1M^í¸ä¹‹0nä`ÂŽÙwÝ÷«BaKvžvÓ×¶-μ=¯çÑ´:ÜÜ>ß{ÑéˆQ.À÷Ôûç½HØY÷nÇ®q,Áï³Þh¥"ž@Çz=o=ÛèÏÆm6ë]﻽ÌÛäŸFmž­­%,ˆ”[vnû¾Ö€WÖÖ¶4©U­/¦vÕ"ßm;ÓhÞÚC`;šSÐ4‰¯¹«®€‘Ë}ðÞónzßwwƒÖÖ³0Ø<½P×Ûw`}̾ùîÓíòO}æžé‡³NuDŽšzÞ=}CïsµðôJ4g=™µ€ 7»¾ó8ßo:¾÷}½¾€ÛOfŠ•ØÐ´û™s5J)HVA½ÝÁC888‹¶Z …+:;œû{¥žRûzû®xMoh4›S}tÀ6>îk«çN]˜`½¥z׫ÓPP@•ôÕß\ãgU Ýõ@tùï®Ô>vûÐ l}ö{ÛÍÙÝBæÛÕ5®.ƒRiYb` ÛûßU$CßnjŽ·Ã‰“¶¸˜ÔPÍ)ÞvkºÖ»jã¼oQ]™mmEW­ÞpÒ·¶÷Ó¶^÷6Ú¼‹FìPRæÀ @€ö €›=¾õjÛŸ>>" K³¥NÌŠÈѯLà  R¶e*­j¨Smµö®×|×C>øÚ"ö9ØÞÍv4÷g6,Ó2ÚÀ 4 k[ç;s{;já‘PÛl 8î[ ³ÎÜÚi&žŠÕ k7.}ˆ{·Ö#­ïŠúÐ¾ÓØmF‰ØÎã  m)€=íwuâ@Bô5Ù´âzÅï—²y[jj|€bâl»vÞëﻓyw¸èzj>žZ>€È AÝÜúÏoe•ÜÌZÐï³Î+ÌÀxÛt/­¾[ÎyºžìT $U->÷Þ·Ç éÈó"¡ö3ŸSêÙ·z}^Ûx.ëÏ$¥ …–Ã` Ýumõx¯N`m„o·Ûyëm°ÄU[|\·¼òž÷Ûdû°óÍäú|P \¼óm{æ’øê_`©åõNi#¸ÛF÷Þô}÷ÝvÑõïw½à4.¹õõsÀ¾»Û´íòïJ{½òûšA d ¦€ Ðhd#F“h5&jc&%4! &Œ‚dÈ4hÒž§‚Sõ4˜eSMP4‘@šjhŒ›JŸ“IâOE?Jiµ§¨Èi‰“MFž¡ dšd‰h4©à4Ó'¥ªzž§¤õ<¦ÓPÑêÈÆ¦€¤&€@ L€ši¤Ó&& 0žSÉ#Ñ¡ª~)é š“ÔMDA@&ÐÑ 12h§ª~BOi2§íBŸªyGéQµ ?þçü 6ćãÿïúˆkòÖñÐ.èBŸì„Gmé¨Bˆ¼ÆR‘?²UïûA¨T@<=dD`TyJ†héŽ1©vTMìº5(ˆ>¯$ïpˆhá"Ò)ÉQ@‚EAæ,R r;Ó^YA/0ÛàK08y+ˆQ’!o:•ư+k @DAó8i}‹¥ò 5H9s`_PµJPÈÈ ºA;"=퓜P¥§piÑÁâŽ8`QÝ0"œæGwvï:u÷¼C½†:=îAÑ…Ïx&éSH|‡ÑôËþ ÓÿïöÀÿÅ®…[ÿâ£ÿ¤T¿ü!˜Êê¿uXNÿþÇþî|!&ÂyO÷¹Ëòç¿?Ó¥Çó˜E¿/CåöÞòl±vßûá¬^uÙä$Âtuûë“ÿÝW¿ÕŒ§õÄcþJˆL,“ÛàPÿ¶ÿâ1+Ó*uuÕ¦MiMB!­ÿ¦ýöEL×  •ßÝL²œÏñÐõ²kz…Iês9KŒ¤éÊ/Ý\†Úô(Q³^Iëç‹é¡ß‡ÿÎCI$F˜&J `·_þ4Ó©ÿÝSaþ®Wn6VTè¥J?þ E©¢ˆºÆ‹á"o°÷ÝL÷õª³gZn_uñÎ_Tm÷ÿà>“Àì{ÕH«®Êª8áT©/} |¿,.³ oî®í:(khj—4í„õ=¹ÅéŒÿ›ªâ§<ãD­ÕÆ›/ç…%BÍ\–·|åªøÃ*Œwñ–ª­k?÷…’’¡à󄬮gd ¬BäÚáþ‘ê»/$J· {m¤€x;Ž0I«LZ¤è÷' ²ƒ}뤢¸s»ÂQžvj̹E‡ÉTiCUêM9Ã@B»¥Ãâ¢ÊhëëíÏGTbúý[¨áuòuDQ·óŇƒÑÑ9R~Å…ÏsáTú¿Àt½½PšK¢¥A7öž¹³ÕËçê‰>N'›é?îwô_¯÷)þïÝÕOô¦(ýÈfþ¨:Çlóç^e®sóëó©SÎŽ’ÊÏÿsy:]߯7KÄØŒ“/\ðì6öÖ:¸A Eï$Åuæõè•nYf]¯ZÁîf¾×RªèFÁÛã®è”åúë÷Üe°ÁêëfÔb&<\Ò›†PP?¡:–èÑåó¯§ãﺃê©g_þtÑ4“áeÕÙ /þræ)‡¨%M‰XJ¨Ò§K^mMD xRYÕúOÍŒh¿T,*t”]›ìMeÎ+Þ´š¬P#cé×Í{eK0}j+)Ä¢µíŽg]ßµWÒ AýN?N1ˆg ÿø8A3Zà›ñˆ†ÿσF ‡Ý‘ß/(2eñ (¬ó =CM4­vƒ6Å:>—g€êSFhâ†ìLè¢ÍxoÝk÷=t¼´îŸÓP\ºnÏ_ò•~K!Ø =´ÓžŽ£uy×}‹hŒãj ÿâ½×xÔÔIÍFYлmpÿºf¹¼i Õ-ùǃÑ\unp¤XCj·În°4Õ> ‘aØœNdàE¾ü'KFQŸ*Ê9‡¡€ §=oi(S-2à ÇZíñ'µÙ¨uEEHëu˜'ª¬ç ¨æù§Eâër»â¸åSIô‹×^¸ZÓóÌŸÛè“ÒT^i ÈÚBÎùôi 1HÇ8×/.÷Ï ·UÑAXšJB,PÿÛN‚XZÛ9àb§†È]À½,Rü.&NØ_ÆùU,ð0ÀÍíÖ¨$õÛâÿ0ŒnÄUo–²eø´Œ7Ÿ°au¾ˆ;x‹¤‡Âàtz½®áδÛ\ÏR!ÚÊú>ZóãªàH_‚Š¥-Õ%)KT PAB´Kœãÿ;¶ÝÖ„œA¼ÈQa?òüÚy2d 4g2m‰Š#gòÁ˜è=E(ÐP´P% HU%P5½ UP³ûòõRÿWò¡ïòï¸~ßmOú,DñDÓ¦©1ý&ÿöLÞÜiëü¿·N?ùN뢉~TÃý²úúí+QÖáro¥}èãb{鯶ÿÇö¹B_´}êê_žV—ý×Eý²|»—«úk¿lçž9¬›«úß+;¾_/&ªTsºOÄ\h§+4ïxDî|ê1Qá÷k·ïâŸH<)2.»DãŽÑÑ+]C¹H§¬­FìÞ…Û[T·hêîÄ'ÎÔs›iß%O w³H\•Òua¸b„ò;Ãóé¾ âóãÆ?<.{uªëKݵç2ž,¤K9Ác7"š„Û88Ôª­²¤Åg$oºmySÑoAãÂF¸Ù´~ªóªÒéÖ‡…—Û[R­¡é6)ÿsëÕe»ï¾ùTé­¢¬$F©žuÑåÉ«ŽÄc{í5ÈxaC„ã»Eþ¨^OûÔ7SýŠOI£€lòò2QP dCÔºWÛßøÁÓ៪6$ b=<Üt±HÕ np=â"Ÿ›%}÷Ó© €l¬ŸYš–#@LÿИF7øªƒü»< ôSˆÆšéùæÍ!w‰¹29¿ÓÿÇU¬Š>W”ðôÑt¼í¡¤³¢;7H5 V¦G]:^`E‘˺¿zºu ÒÂé½þ„ÿ7óâýÒ¶f@¡Wtä§8CïÀû?H|;7‚#ÝÚ=‰‡$üòŒÁ³(Iò&·|èòìGûÏŬÆAX´tUÓ}EøÖÀv‹ÌERED‡)߈I‡Ë$|§ƒEý‡°oC|”Õƒ‰“VX]ÇÄãÏ’{wõWØàÜ¢ô2Vj‘À(«ÀÆ‚ÁkŠ­Ö¸,Ý1•PS j•¶”[eµÍŽmÊâTF8QG ÂáLN‚Ø¢áµËEÂ4pã¸Ä8ÖÓQ<´ÓqÚŠåªÑ·<;ÌV²Ì&*l¨¬3G¡;´>£ri3Ђ/7IÅC˜[HꥋSdSJÍiƳÆ2Ì×áÆéÎøË,œÇÊFŽ‘[BÆ\¶b„j‚nù7ƒøÜáqÓ‘ŒEÃ¥å¸LJü~ïÇñÿû™p?î@ІŠ3vþ¿òœ@5€t»žýÐíðŒ6ö벪®Ú, Ã8pO•*¸x¸O½Ÿx‰uÊÇ\Xåu! BòB@ÐÂi™™´Ö†Z{ÃÛ· ÈãLYÒÕwtFU­éG@íD‹DI"ðÂ5ôý@Øn+g žs@íøŸûߎ0Fìþ€;ânX÷6ò&HÒvÀ J[»»3·K ‚xB@ì‰ð:Á`iá|«0ƒŠÂ 30@ÇÙ÷#´Ðñ C ™ŠA0i»;=uSnü`MwÖõ*NœKú RÒàK‘¢òªXÁ«¢ˆ.¥¿25q5y<6“±Oom†aQLÕ?Ê£ôÔN’`¢f Êý7_WVî䃘ÄQ‘9ŠÏþ[ ð:Mj…÷§á»G¯èOˆIí îù:ß8K%aƒ£`ÁˆÄF0c¯žtú‡8ýAþW¯‡ÇÃ3ëÐLAU)ÀÆ=s'0(ž÷‡¼×‚†±ŸëDù6øqáe‹%¢EøÍï3Iˆ©Oð)9#ᬇ1-üHª(!…CY9R×M:•šk© #•ÔÿþsÖuqáåjd3GÍ(¯ ?Wñ¦EîÅè€ÂM9TÂÒ%$Ч,T¦@Щ'rºŒô$eŸv’8þ¾Ý%Lg`E™›©|°vT¸€Ø—ö@›x`ònÚÿßþ‡†XËO;’Ez¹1! „0Ä ¤f|IqiªI”ÐËJ|šú%ú½Â·õ|þ9}áðù:“icÉâÖ;‡3˜9K™¯g‡@C3Ä• 0ŽnYÞþXß ‘^y4$&;ûݘ¥&lþ¶vÇËÍöðÒü!Ž@ïÆ½‰!¹/Fœ«mw15 cVƒõ,8;¥É›^… 2†cn¾xTPígçvOýSòkDõ9ÒžÈÚ EHÄ,A0ÄEHбEÎ #§1¿«ùcP4~ØR…d†”/¿ÊPgeÿé X›F‡XÃ8óŸ–,Ýô'2DÔP7¢½)=Š'S}Ý “Ÿ§>\,ÏþÛE¸?mÙªeýŸ~Ÿq×»úq9Á ½U93E ‰JÌ`1xå8ꋦ8x q…¡Ö?ÑNUÆ•4ÏÿÚØ70MlOèêìY馘¤h½;ªãD‰ðªˆó”ªb’ËrþÏ7³'sïüŒYü»èç2q¢‡òÕ–ƒ£S»áxÔ¡ªU íhlû†¢)mgãää¬öç{Õ_BtQk´‡ÿ01§3÷Äïó¼Ðª·i S´0âba ­‰¼êdñõŒùLs}Ÿ/ý}»VWQ~/ñwçÙúzò“­Ì÷Ä·ÏhQg œæk¨f¯"0’ÉT^ª#ü÷Üß“z'¾›ßAÁÇ4ݘœb!ˆP6.0Å4cü‡ârK†ø}Y†,«‰!=?Ìã×Û™wIÌé60×>µ£Ypåoáó„#bÅÚ%­¥+-§É@dV¾¦s¤½ú}žpînUŠ"›ö€IùbóöÝkQjÝý>½9Qš¸üÔ§&jŠ‚5Ëʽ 9(ÊdÌQêº`{,ƒDƒ’ê2lëä÷éÿ»×¶ ƒ£ð—Õµõ…%Â!I&aN‰ÚôsN¥cÖƒ;ª=°š$WCXZÏU–ÓÙ&bäþÑùâZ³-W¶’rx÷\7¹–*Q-îÛÒB*ÉV©Ò^ŸºÕô÷ìú#0Ãöàœµ\\È&gèßSŒ'wHXd\2_3_+†:=•1˜xq$’!òâqž¥¡(iš€à¸©¸EÔJ…¹Ž®õ "cHaQ1ýIõFpR|¯õéTï¥jɸAic‡b ú A}NÆpq#¥š¼ÝµÂ,Ð(f²Ð4‹¿ÎåI&·Tè¿Â;µÙ°5ò;ÞŽ£áŒÖ†ÃÙÿf[õâh_ v雞y+$ÑlO^×6-ú¦§Nri¼~~w²Í˽² |fhhY~uŠU8Æ„V釴ž"b¦Úɇc ¸¡bë°MMpbݪ³wZ–ÈŽk±¼ÂØ®fTË4˵DÁQ¨×Õü &dò;ža•µE‡C4Bòl3ˆg'/ˆè­å@E¯ËŒЛ§”5ve•ynÆZè‡/<8¬¡µ¢; VÀ3AŽ=¨êK¢Ê;t.˜šÓ[˜³>$½óqŸMD3$û³lЗ·m‚ôP&”Ù„Kº3Ÿçþ¶ëõGÿºqVUbqóV]*”&ŸL,ûÇ¢sFýo¯lÏt“°ÜY½zsÁ"‘}ÒÐ 8ŸÜþ·õןØp<ÜŒøxcà] •4Ä$‚ôe",Ñ”"½u P=U6°?ÃJ6ÉBê…=|41þ‰”Í6PÒTb'ÏpÜ£¾ï)oíÆn¹“ÁF;°„ý*Ejïlé´yÚìÆà£¯Ù.6É„ 7¯ cºa;jÎá5^»ÌáX¥ÿÖrbf¡1oÕ¼9d™˜¬MHŠ[BžTý4R8®ÅŒÉ¸ù=”Æk}[Yè5} óÕ{‘ú3×oæõÇWÉ‚÷ ³ ßk Hß¶QØYA±iOj§(Û캙îÇ5Ÿ·oS†)û Rf}ÿeáo…¼S·²ÚŽ7Û¼@ÈIšöZ6Í$@54vÁ(`"1AϱwÅ…Hªð6Ë*áŒõę魻ç;½÷™#Œíø Õk·ðÙ$[™Þ‡øþÁ¿g" ÛÀ8•CŸ\ªîa_£z [M-ò^޽žjqDUpôikdÚe•«,ÎhR˜¥^?J-GEWsÀ:8_™¥gEžœ%^Š˜#_VX4·(ÔYÉFä:M[ƒãm‹^f¸‘]ÒðY qWkÌGet ̾êø&´åƒskõ#}¿ÇA^IBl®¯¶FDD*£—ÕÓÍ9R¼l{ƒs-í 9öΨ¾&ËC¦-{- Ð]Ô¿•[n—´t[Yg!Kš¦!Zú÷q´ºðÞ~ïžcË\›ˆdkaÚÕî~g‘ËWÆÞd6øÜ€Yh¡¢K"£m¦«v÷<ö__™Ö-}§£éHŠÞ…ŸþÂ;¶9PÌkìqáT*[v>ÿ·â-½sêüãù >Þ3?¿¼ÏÌâ¦Ö­¯•ycsm¸T†.Û!4E¨u÷õF_¯””o©–%[š°ˆÍpƒlœâ¦fìh cU‡“i©UT馩¢Z%ª¶NõaUlóª…GÞ_^ƒÙŽÝœæ– *«Ï]îSOÙÊŒš´v»se­l˜qR†º5Ï£íȨ­áb4¶5IXvvi>yñ:|?¶µkrE­¢ œK§sh(LãÇ¥ áy 2…œÊZŸM¨E;-B5»¤sÎbßñ9Ÿ«’š›†ç›eÞwøªï¥SóÝ1•ò°ÅßMé[LD}ñ¶%³”ç¼k°Ôv·î?§®/ëÕ¨ðïR\,X»¬±OöÚ4ù¶lt&:§gLEÜEï<µ½6ʲúR¹M 盟þøM‚;pZl³* D޾êVŠXftÍÑ{èw³ò^Kö¤ Oáô¿×ø{¯}wÃãQåRØÈx¹Í<ñaos=j;PY×µy¯»3ìóuŸÕ²óˆ=8g³¤ H<¢/¸Ÿ… lc8ÝA¼;¹Ti6:AŽÐ1µeAQ4¤Ýh1œŠâî‹á¾1=Ë_¶«W W©u-sßIÑÜL*àßÇMÎ×­Ì<' ôÔ}Å¿c£®‹#Œã¨ªO jˆ®†Š²F—£¦4j"‹ÖÉñÛœgé6Î*WSÍi5(ß\kšæ¢ɵ#WIʤ•bqÌÁ<(§–H£‰íÄP{Pþ4ÃÿZúâ¸þÅ_絞ƒeåKñÕ8’Wé}•óé,Âxº=þJ&Ç;¾æÏvQµ’\VV¦ƒ´b÷B”T_DP:Ò¿v¦°)Í[ØŸ7z•B:ýÝ’ŒÄ’e¶žV ﹘žÓwQ$’KL" Ïlá:•=nð~5î ÓÞ¢ÌkËãCGÈûw;î7>—jSñØÁ8D¡3ª ˆ"YÙP‡’y$¦W¾¬×ÆÏpŸkÓ—>“\îtÅ“©K«Ø2sv:è¿ /“8=É<éâÀýÉæ~Ô´†àüžªÓê̆YÜ÷wøü+ã˜{ÃùÔŸµn$an݇4`;5Bû=uQ$LMú÷¼eŽã饚P“;⯃0üèÁy¤áÞ¹·ÿNŽ™hAµà vÙv>é°ì^9Ñ-!×dÖ~—;õ€àtn£Œ ×ãú}›ëÖQ[wHdˆ ©‹R·DÝVÈX¤èo»^Œ5íòÀ v'¨ì &HÇ"ORtÕ£"C§BL…Zy¹mÕÛãÊ›®-\ ì©xÎx¾¬ž5»ö9’# îî懲è4È4‘ú¹¢K9ÛUo-£ÒFå>ØjEü4Ý1ÏÑF]ïÊòNÔÐè,TyÞ±àÐÜúë—/ÿR–áÎnºê+·…ñL–¹N¿À×ë®Y.{PéSmƒ||Ïl|¨zLÓT° N~‰OG{À:g­ÍÖÛ)qÆ…’“–?]Uq»™žªïˆL¦"Çz“ÎñazÞm×¾†ClŸsU÷bc¨¡e/RωQBÈU< ¶|”’k m. øë<…Í×Ýötù¿7³¬$ù¸pÚŽ£©ãzò«Ù§šQ $'²êyêsa-‡Ðɘów€’iÈ­(“]ž^¯®¾\³\jäÖNÖZ„#…pƒ§[Üܵ@³««»Ny½V+¤ð±Ì^0ÊZoyöã(ŽêݸP÷Æ4=8Ö¾h¹Ä1¿8ƒ„Çãõd€í}h'ïü÷8Iú>½NUN¨sST6QAµ­¥§¹;,,TÑ'–TZz²Ž Ù“#Ù l̹Ó~nsxòÝò¨7¨D˜ÐKåX‡oŒz«…Ø"ý™Ä¿S»¼…_‰ä„Ìyý…ôÅxi?[<s>-mç»^æ¶©+VX¢¡è“/Lž±S ~RMØ¿£]‘鉭O΂á_OÖûàeÕ»É]99JåUÔE†(Î=óu«8QÖST(~¥å»Î—¹›¡¹S\½ÐÕ¹ó‡lB¢õA.àÑÇË›óŠ?·žO—_ŽŒõŽ&ZF«Ú•õ2Å;æ½* GlíÍÌyõݛׯNg:ò–ER‘ˆÐX0%9†¾kµnômk®Yç TPúyh32ÅÑq£]¶•2({+|/’ û B ~Žm÷K£N!Ž”Ã\²á†“xî; Ìï7-ÝZ®ýØmƒ¿ÍþtC;ýµ@¬:4Q|vZŽBÿA)CR*È)ù¡RÈ¢™`çR7¡¹•\'Ë¢ßñåX~}|Ø6I–}š£7ã¿¿—¢ã­‰Ï¿6b±n9“0TPÛ۴П‡UP©Ó7OQTè'“b½ˆ¹ ÌÓUv³$Ö–ó-*ˆíެÎþÿÔxÂw>½;ô¾ÿsJ­M*zuü³Í5G¦¤¾–u‚ô[±\´I×Òå&jJÿt¡›ÎŸÓ“­wºÎˆSd c9ì§EeánZ1»62O¯âÿý¥¿Dm7jêæôÝD9{6Ý}2%³ž3=Ý–ã,'l¥ >qcœ]Õ½Y;ÓœÔ}6ó™iõh»UX]oýz*×^6x×ÍagEõ_·fßÎÝ\šìüÖ˜¿cºª˜Bí¹Ë¥’$™'ÅÄ/SDК!­-xQ“+ó_˜ÒCòÝEõ{؀˧l#Ó|>¨9$ÇJÄÄ>—º.I7—O•Û™+öAW²Èê×®è’Ø‚p+ƒ9ÎçGF:§‹Enå}©¯º¸ýz¨£hCk¸*\gBA‚iùÞ©9Õ'’inv'†ŒâëJn„Q½ÃbêÉ;4P\.ºhz‘¦‡Ôœž§yAUþ[´RDÎ=x«%{ž ¹w £Fñ†í›X™ïùĪOÿò.”;]á¶èÚ¹áMhÞí8µ1Tµ®‡sͦƒfÌ£*ÃÑä•GLT?5ú#›ÉY§–×ÍOomãDÌMГ0Áû¿Âa{Üf^?ÂpOR^`><ÒMŠ3ÏiY“,1Dç¹å½ïsýu)îöTâ;>Uwö`Äÿ°÷ÿ§ý™˜Ç|Ê*Æh’Ä|<·êìÊ>”@¨BÅu!á¥Lmó¹ :‡ç¥œ8®á:<¡Ðh‰yÙD%a0í¨· tG¢Ë |4–B0£8ÄÂp¼¸rmìµh×ÐNý}þ¿ÕftÕ•Ò‡™Û,§Û´ÖCô”éƒõC}ÅmHm „Ñ4à A3$É"pMÖàdyì0ø¥Ñsût}4míòC¿¬ßugZa-))ÿš`º¦eц>ºš²z>Œ–}S7ýWW5KN¤P  Fqª†Pîô¡à᪈Êw.sΆuóÉË“­è•Î_ õê‘ÐQŽ’^h÷|âT$]˲ó¦V¦7;¶;kƒoªT3螎ÝEÕØ9ìP²ê¼a"i™ÏÁüŠßïŽøg{¨cn·ºŽiœú0½©î•]I¹Ó $Äê–ø†x@4kŸ£~™ï{3\zVs^Ï×*Äž–E€°ŠqBëÂÝ}kmzŠôÓ$ÈKqö©û±}¿/°ÅQÙe¢äRÒiæŒcv:*T@Öün¬N—Y=pˇ#u1cu{©•ˆž{8ÞS·©í{ð¢}·mÎozjPQ R P"PW©S0€•˜í›Ê¼<ôBHŽz4Hš“/êˆe¦z<¼©£}3Ï•³#§ž/‡bÚ‡BFjM™Zž‘‰ü~G²ªWïöÉ+{võ‘Î=WÞñš=nxó0¾W÷>˜¡¶<àÔ:«<ï颅_Ðù¦aEØè—öBÙK–·Œ‡·^ºüwð»{{Oë…¤¢—Œ(zõÊðÛ|`º3´3—Ûï”è²–u]ÁQ4Çt†«¥Ì&×J•´ÓL‰Áö®d1$Þú×þõÐCû!YFQ£ºŸ%uè‡|Ljûeb½ü”FÙÝøõÂg¯-qá9Bò£i£e;tEL°ï„WONߥfúðÕeÕjúi֥ƫbÏ£ý'-˜èÎNYm«ZP½)öç¢âÙŠÚé1¡ÍyaM\ÑŒñ·gí„®ûÿWá»yøÊRý×i«.ëráFh¡ ¨ÜÑ–©l‰*_^ɺ¢°¯…6|µþ'“”!¿NUÖfä5B;%Q–Q«É£:Nª´ß£EÒ§»Y]ó}y>’œ«Îøãe|õޝŒ?oþ>zßd´³3<ï·ýy²5QçQß>’iv5üŸ³õE÷c)'„»ÿw$ÊO)¸‹â|Ýk¥…lé­jE»¹š 7Ó5åèp~ûLý_Òþ"Kú›m6÷~0Åg­í»815¯Ã~Ó»ˆtk¼4tò¦G÷§ŽØý3ŸWþ·9‰€È„±­«ÃÇ|U#NæV½çÇÄ×ÜNØûÕÿ.µñ¼3¢æKŒs_g¼{·–Þ >q=¾´Ç\¿~µ™4ï´f»A¯ƒùU:Ûž)µÇ_NOOXñ»DOS¦ü'‚>¿B=ŠÒÆ‘ÞWWž¾|ûzë;EMWýò£WÝ,k}v9S½²ÂZ$òĽ֨·D!£¶˜ÙeÅõꬂ?>ìwBoÿói¿ù| `0¬šLîÁÁL¨Æ¸/áæ àž 4þÇç©+ Œ»ŠbWÔ'8ô@Ž!ëÇ|òÀ¸8¥º<áÁX;ÅÊV9çN]Ð÷»×G'V§ îy/NpŽ'˜íǵÅÜœ> þ×GØLÎÉ¿ZJ6ñÒ *rѼéSÖ•Tþÿðþÿñÿñÿ›È=…ÿ_û>ñ5»JITAwè]Š‚ˆóÀî,6Ò"ihþ`%sM¥ÇJ¯õy¸Ûö݆ò3ëŽ'€û‡HaTí?¥Ãñ“ŒÖ»ØGÍ >ª*íª¯ÍÜvc-Þÿ«ÇöÜÌ-¸oþ<2iÖÿ_®]CýU¹/ó„ ÿ(¾ùŸ?Â!ÿÖ_Ÿöÿ?ÃþŸ¦Ïö^íûÿéþèfäÃû¥ÿ˸QÿçóÛ¡DïçÿÇ0O–Õ(†bÿ·1y@¿>œ‚ô›ÒŸöªý¾‡ø¸ß܆ýÕÿ'öÿíÿO–%L\;9üÝëþ×òLª~ì'¦XH ”È~'!8þÿ@èD¡Þ¶‰Çpÿü[þ§üð¡÷ ?Ïj€ìOïö þIJŠ ¹ký—LªÙߌsA2DLDW¤Q)ü!5ˆùD€R% H BÒ (”Ä%üRLÈ€ ‚‹åÿg'—û?Êàv;‘o@;BÁD@㎞剀8™ ÁÖ—™Ì!zd(B€Åž$2Z¡mµÌš°5Ô5 $#m‡Î f¼½>Jç î;„’íC0"s•®TûÉ@ëÈ;¥S$V©Tq õJ(åH/`EB Рº)Q²¢ƒþ†DD¬J‡É¿Ò$@D a<Çr@˜fÖÐiÿêéÀ4&Ç…°eÆÙ( ,HA9ÊPP-"RJ”ŒIJUXèdáÇ3ð æ@˜óWÒá@•‰H¦X9ƒ"ŒÂŸ2(ŽXP DN`˜j äºärþpb‚ì¢R†‘_@œÂ"©"1ð…Ç™ +ûÄ¡749–YžL„>TQ†èO÷QÄ“ÉÓ°Á7oD:m£ ÉpÔðânÇênÛ+ˆîe&N!ߦÚ@‘ÃÀ?7ž…CÀ<ÃKa4™r™dìuA„âËøAW)†CLFbÅùg-±ÿ»æqÞõö×Hí—ùù„>™LL…b?Ï~/§×?럤;+Ö™˜føLôœ‘:—ªñØ; È”S-ଠ§4¦é2ÀÜ!ùåíç›Û] 1MÏG ®isÊ)Š?Ï G×Õ ,•ý¿V¬fÞz€vI„Ú)€ë˜ØV$µT¾€ žWpuUôDî¶s(ùe®@Šs)óz@!è§cçNRmÒsZ,…¿7´LÌ|~ý>°_9oà°™€>`ð˜2€ WÊù2bák¥¾.À‡{ ÓZ „ÑÆ!„xOB9ðò3^,HÇï¶ŽŸ¾*ûlÛ}ô„8~„v`½Þߟ@â¬G·ni±#&´ùÔV® "ÙNjÅC{U´ ÍN¸ex]V85Nü’:H`Äi®í.<¢ç³—?Ÿ§ð[û¿ço·U_—^ˆuꨰ÷6ÒfºfM$‘±Çb§vò2ÛŸ™˜ÝZ|¨Æ†¶¡›1D«è !3tˆá"(²gC¸}wQCc(чËûó”=vëöm¢H±»4±Ä®=­Çë;>Ì=Åݧt·óç¼¾–`fƒÌn<ôS¹º|{¨‘çaYqb OÙ×å?»üy|®Ý×e×êùÕ…7•ÔkÓaÀýÿuí2lM‹ßùû:çÄÂ-Ü/Ï¢Ësù;WyÄ< ´ÂhG,7 ™|:Z)ý5¦9¡n-7‡¹à}n{?CBŽ U1y[©òú…„o–³bß²]2}çÏI&«idõYwsî§îǘÙôLÐY£Ö^G< ÙfQÒ"MM&º,ÎÝXÉ+sê”H¾ê*C\üœF³ ‡L?£—ÚÅuP|m”rWl:\nÍÛ¬¢Z¡^¹èûï•^KiëÓ`Y[KQQècîîq¦ôÀ±œ¶ä©•$WøÇ¦“d¢ MG6‡wÓgš“IÕïã}×]_Z^B\¼œzb`jz¬glU³Âg™Z:i: t^!ªSþ„KÑ[,7Ciî÷‚^î˜P-Hü8ó5Ø@Öö¨~d£®Ûûi)èµ&~Wç߯óÝÇ:éâú>‚¼o­Ob¯Ùß ¢¨Ý8Ö:„l^TT„¥EõRÓ§*aEµ"ñ÷ÔF®{Koÿ„5ZQ  ÌÚ>ÖèlâÍÈm æû¢ ²á/m_F¦I2„0‰ÅmŸ2cÕ(Tn¦ØDŒßô§?,ÆLc m?E[ó8Vì®cw•y‘%ÓAOkÖtâÈàwiâ 3~}{º¤eÀìY'DŠ¢kDóiêÿª·’Ó–÷ŸªÍ/ “5wÿ?Ô³<“‘/_+ü§›%´GUç7àÔ5¤ªú*ñ“ó÷@ôö*D>–ˆªF²×! Žt5 pá‡tŽTPOŸ»ãülð£ÕSޱlÃ8E„$P=§£!5]NÒÃâd©A”†"(ŸO¯m&G¥εüHÓC}Á<ônì‚¢•G¥¿Í ÀZ*I8ýíâÔÐĆq'ŸMgÒ©ëõi¬èEz1k¢£•£žîlLX«c'*XË¿¯ëo¥ýÞ]ßþ¾<uúHŠyíôŸ'ÞÅÛðͲ–v—LèÜ®Ü|¢JÁ€ˆ‡I†ƒaL$îÎ$²ú>žÊ´ªz¹K²üujã;^,fi¦˜C¾þ @£5MòÚì34¼N×fëý»$"ÕcPm¤Ø£°T44,˜1¤«fµÅ‹TTÛÀÆØÑl̆ƒJDÄÁtÂDÅ0e#X˜a ©L…¦`¦ÖƒSaªˆ(­¬šØ´Ah«hΨ"¦J‹«¼  QI†RPû’zmêpÁǯ00H^ÉOWw"½ ƒyøôtm¶!ÌýUžÎw4[ªMn½OÐÅæÃÀZƒ@”¡‡ÓÓãÑßÐð2ïpÊã­sG¨²wñsö”Tº !âHI$; v1ªÜ{¾ƒ÷~ümËø ÇÎY"ÁTè…HDIAlíkNyú¹ÄèÒb"tQIZtU¶Ù]Êh(¢!ÄhŠÎÑ2à"ˆ le0YζhÆ¿pŽ8ÍK¡ÉYÁm˜‚ÄU³°F$ÿ-Ö4vÆ#4´ë~\;?&9¬ÄœOÇ®ùâY\rI–Ú[iaL ãU2Ó)\/Ìp€iÌI œ$8Hs9  ©n5M«½÷r;y×Ô)­“\³Ø0*ý»Ù©k¶8&¹vgl®=û²ù—¿®_5ßðܳTê›!6@æÛ kê£ÚÉç嬒8ß·7úuÏiÑ߯ÛzV.Ë wPBFb¡·o³Ë¡ö’v#J*LEdJÒÖ™Ösm N¾’»Uî_›«Çg6ý_öÑ4FÑ&5YÞ—s„@Ëp;4¡¦þX+M>š¼é!S3¸; ô‰Áˆ~¦4,t Š”!U‚1Z{Î;°uräöÕëG†…ukûòÐ!{a·ÓC ð…]ýòÈíäf¬Búûn+®Ú·»ˆ¾3#JÎL÷m›±XþÙi öûÖ¬–ÁhþÏhjY¡Ô2ÅWÐ&Øð]uTÅLW?©Ú`iMÝ3dü½ 6Fú‘)¹áÅ3«0€ œMµ¶ÔÒLäAá[1g;‡#f}™öºm:ÓáÄ­Äœd÷“Ë;ðÓ†£†ª+Ñ@³8ÖóÙŠ}%ìœkmSQ¤¨ô}%ŠØC&ó/T»sö?©imÞ*SÅj9!¡”hf½yŒ°Ã*ŠþFuá\¯ãP˜oË„grähAî¼{;dÕ‡q})¹ÔÝpwÅ,ÐüÎZ»i/þż/¯³†ÙK! F%ÇþÈ—,Üøì(Î8(ÑôÔ+ÀÚÃP‡®èÕà;ŒÍ÷¶Î·œ”6t{CK{fȇ伹7ÎsÆnu2ÏE—²( 2Â`2RB]½IŸ6µ¿>‚ÙÖ{57qYÉ'3ÈÇ/ô† y¬ë(õQÖÓ"‡ŽþîÞœÙõÁK ãdΩèJQÓÔL¢ÒLlÚ åøkÇ$å:hÞŒ•JzÒÒ1ë!¢X!Úq©δôÐèг^ÉÙ ®«@£R¸¤‰µ3Zx)ørÌÿF-V`ÕC8Å5ÙóùúÅþ¿Êó«¥g`ÿœ,›>ãÎðx}Ófl¹Í!Þ{ØkNÒÌ¢û?Aô÷E€|X#gUAvÊàW"&ˆz{@Ÿ'Úݵ/ŽýZm©‹Íáßow/K|Ö àš—²Ìü/1¹m«¡›$ ÙÙ:Mg/¬´qh°kQ27²R™£õ.ß»«ÑU=U¼1Ýî€i>gcr-ý~“T½‹YÍàG"VN$¸³Uo›S3²DEË,“yÓ¥Ë1НåA®`b¬,Bš’,ãWd¦Kßó^Pš&i.Š>¤>0×9³gd„5“u…µTuÛ§úi ¥_ãk•µ3eº¿½‰yŸ÷Û>ÆgôSÎâ¯6߆Ð7•òÛß0:ÄoìÑ”J¬È{ªô•·+OW90-ôí»½>½Q9¹Ï”wwsi¯vJoô[A q¿VM§_Túâë׳…†ƒ¼øôùL{'û·wì•¡oâÔq޳t=>ëÀôû¿nŠØÓÊãbY)2b‘;Xòßú`}ùâ{÷ûÏj‡Ð›ËôYý{os`hc?Wõ·§Ý§©›ÊÅ onž‚õÌwD4¤¶ùfbB0TúKCgšæÈ™¹U[S¬‡IŸg/9ìÂÆõàÍå Âè+h†‡ÕåÄÛ“n ñªF[ŒB&>æ”t#-øïн1¿t|8y¨¥¢…D®áçéou~«èÙÍ´7ÐìÛšÏWx^ÞúZèy›Pu‘·5¾NUuiÆÊdeC¶­m£žCöë>Ç4œÛêç·»ÊÌ-ûeC‹3²d”ׂÏÞí~Íé PÑ,úø'ày`P{|†_H“ŽA ¡Ø9 ’ÜÔröéæêl©¦Vyµhöÿ„¸ÒuvÖÙüM[ÖÞŠùîÑG_Fý¨áË¿N“ËÆ^bºÊxJÚú1æaåì­ àªÓÑ·D! öˆÜŸeÕìµ}ZÍs/ìÛ¤Ùz¶ÝDI6œM¼1lÉö°U‡“¡@^°¨rŠª Â=‘Öv]#•9ês–Q.î{Zؽ°ësÏ´$Ç ™š6lDóÝöüîËëQ£õÁPÑ$ÛÚC¿Ý]iÙÕê¬êÄøm%ÝÛ^7I¢g[r®£*áµ¥Ï׆4ËΘ‡é‡d‘‚ç¿úÌë³ËÃ`æÈð]*Ùwíþ ã̬Âe t»g›Ð3âpŽ˜±¢‚­Û¬ŽÚÖˆC%Ä”683²;óƒÄ”|™¯¹Þi¿±0ÆH½¿Ÿ,CUÌæTa¹-æHÌH¡® –õas)åṘtë­ez0u=5åf¤ìÚà “0õ¨#&®EVH¹¡'ðÜl™|õk§y2u5WlºÈ$É$“C“º*4»åÓAgÖü6`÷\ô[EÆ*W×*h‘¯qѧ,.áLRxt댛&iÎ1hñßfì[JJ†^Šâ4Üp®Úz ¬¡¥ß467ðL-;TꡦjyÚåÆ=£^Ô@Ù·¡,:ÞîXŸ¶NkS¼ÆêÀ󑉞Õ*k—%Ž·† †Yú´×ßôjë·ˆée ig¦A`¤ËÝBJ1“43 Ì«8ü8 êÀrü÷ë“Ûÿ‚ç‚€Å=ÞFpM«ÊºsäuÎě鸝WM[«ú$ ¯Q3Mœÿšè´éâš­—\Rmž¸‰8ô^:iâ×8“0“VÌÌÍJÎmü+=´gºš®Œ±¦ÛKµKHssã;·_d{ÊdOñ§ì½áNBO¿äzuY!•Õm…TPÅáaÄ!Ø9z§Ž›ó̺v0û½[²|g-šÖé„5pƒA©ºû£]r`'‰-×uMwñ«“ã¡ùÕä–·ÕÅÂsJ£?â\sCšÒò1 måÂÆ²§›wàC-«kZèÞ’›o­Ëª §.ßZn¾ö ÿ?³ÓWt™SI1¾}Ž-®_ÁÐÄM›ìKöÐÔšè…ižÛfU€h¦½¬u²½ ÖJôF拪»œ¢PÛ¦æ$€òöp¨“–kþMm”–Õ ,øžË/M¦;KÖú÷CÄf=JN;7.|1æ4Ñ(g –*K‘)ÃÃ^~Ü$/ž„™SN¯·:žz³×Óâ$¶‘Mi¹# ôQwS=»^ˆ‚ùU I­Ûh«Âßp~‰²Ÿc‘7¿ÆŠèõ>‚,òt`ü%ÙØ÷ܯš¥vE†Y¬ó¶É5H ¾Á§´I)ôãkñsµzÒü+QîžñçÝg÷œ+y7 Y;²ÒÂ\iRJ½ïo/ P]ac‹7Õ‘TŸBÄ9ai‘‹H·Y]™RKªÜžåœ¤ ©w@€¡}IÓ YDˆ¯mΧÞwb²7÷x`Öƒ®£Âè7N}Ü:c—}ÛÒ¸ïX~Q„nìåT«~iP.¥Æ¶›}Xk?…/—·O]\Z£cÎâëÈìÆÕØü jš”3}›õU°/Áºw.W˜?ÕŒàÅŸb1 (s¤lÜA¡ “€ÂÄf9×Òì醦¬ž\‹°²çÞ>¥}YgÈÂõqɃ&r«¦;#ê_rÙ³Øá³±3¥8ÛEDMeû[]‹]¥{ÙNèšµé߬„û A»Ý¢S¡Û µaawÀ<—³©¢L¤;GÌ ÈfÌÅ—f˜«Ú›;鲞—<é²úM„í<³¯•¥ÂBtúµÍ­×ç!n‚piÙ}žD˜Ll6›bÒgÛµ–öyŠÎm´›6Á¢øC©àʦ#š8ôBoÏ;j‹ôHxjJ‡4«“ª•ÌX'¨Lªè¯8m&€ªˆ+j!ÊoË|œØA£í6O:¹ žË„½3Äù¦ˆs£dµx öfa·ïé-ÓS&4u¾[¾>¯àúµã·A ‰®ôˆ_KÃ%Y å;r`ç¡ÚÍfø—ùæÜ¯wf`™£  Ü;hhP€ä™¸,ˆLù7k´¥¯VÎØá@tS^æ­–íOh&É9q;ž$(Ç›YÏ¢ñé£B‹Õ‰lV‰ ÊÙΆù}[¬×ÝàŽ–{SGÏ:¾ qÁðôjo_i—¯Æðë!Q_-Ý&‘P ïó˜{`õ_§1Ù€n>ßGhÍ2wð›ÿ>–¥ëV…š•R øªð3þ·m†Ã†²Äüyû܉m!VX3§|ÞZ-~Ñ üñ±3öóZVÍ\°é–jí-¢Z5,ÉSC™_í¼œ4¸ã•RŠ~ãcjÂÑ;¸‹æ×öÈÆÇwQPßW0XJ¾Ûîì)R2ÚÛ~0n^DËi¯6ÃtX@åÒÕ/L­š›\O¿ƒ¶ûk³]mE ÊÜ;¸É¢¶Oâ†fh}i‰*·­dãÃÈíF½¼Ñ`‡;JþªbÑVÛk-Du3³§lï,ÆídÊ Ë \ôœŽ’âºk7«% ¨(‰:ÜoXn“u@ÔÛ ”ê,Õ åp3C¡£•Ñ,dÔÃŽç“^Xô\bì£àµ‡ý³–ÅM3îèÈß$X¡å“S,÷ûû1³ðßÏMM&œ*5ÎÇÝŒ<PtB§|ävà”˜Ž©[9û`èü–äÄ'²:ØØQú|ç †˜($•´U«/–:ç^°#V"¶H>Ø= €ÍfÒCE0s ¨ŒJÑb±¯¡ÕÛ9úboQIÖ'ŸÑ>H¢¹?T‰Zì÷– £[g½´7Ÿª²½%4»æÓ™.°æXSiÄõª¡½ƒÃ=ü¶Ã¦Eþ]èûÉtÇß§÷ð!õÈŠ„´ºwÜ!XÐe‹ÔÖz…„ÔaL&Ã`“RR®ÿ´(éËßGQ­·ß¾¬+Ýaȃ£}PgŒk¹åÊdün× XÉ×V[ëÆi¶2O´‘û4꼦œ/ŸkÙéÇM·:s¡nl.ëƒBÎýìÙ‘ŽDqá^EWl–ê©Ñ^‹¾|L¹&Ik½Wç™Ù†éêÂ7[«˜¬møEú+ÛlÞ:_ÕA@[¥ƒRgÝuäMè$£„*¶»è1T³‹r6­µr‹E¢ZÁ|s=r,à>D®£zÎSbýÚmjÆÅ'Ø«#«Sµ-âã;·0’Ñ¢ºšuk§ª˜j5ÜBn™Ig4²z.+äëM--rMiœV ƒš°u™£çÛYúæÚÔïéùŸéŒ9PÜ<ó-¡3gTè‘£o¾ pm$à•ÓYµÄZ‚/°/ÃÃ|sÎÖ%Ô¥U Æyê›ì(µú=¾}~Í¿|û×ÒNÊÕÕQ‘MTíì%Ž ”B ˆ¿Ã<³)"á+]¢ã GŽ-U-ªMë{ŽÇ†çݣˤû.ÁDÑÕ=^bx¾³Ûv#ëm½uáÂø¸G¥a¡XòªUsE]W:žý±œB‹ -‡°öFŒ0Æq®3¶¶+yË4àú{°òŸ¶y³·Lnõ5kšoåÒš¼ÝÝÝÝÑÜŒ›™Dª"6/“êÖ’þxªçêÒÚ8g:ø¡-Ku×v;Øf`6 …ŒnZÈÑ»P=¥<ÁŽV÷R¶²¦Õ¶ 9DbÈE5B&ïÃD ´øìÒ“]…Oˆ<–] WŽš¼'F&,4kLÛÜɶ|4¯7E€¡ +é(ÑE!uÙÑÙÝ,¢»¶oèòJ‘R±T®§eeäZ/=£O‹!Ö!D!‡Šô¬UFK.! Ò‰zNQ&¥M/Ç:™œ‚z‚O\Îþ͉ó²Ã¯Á¿øäCžçcõråYmlõY«-›+ÜÑîÀyqf¯Mm›Cž’Ü-¶¨Èa˜Û05µdšÔMòá´ãU6ÙKRLìž h2Åà˜•õªªI ã5÷Ÿ?KÆTü|Ǩ»H,(Εw'i„¤Ñ$Ñq†žË`'™~EÝ wH¨l».©òUèéÖ¥V*ª¯P½+ßt?ã±<<çfåŽ\¾³Àí™ø”ö5`ñª>N‚"±gÞu·mq&qáÜåä¨r{Fäw3N¡Žq·è×SøÕâ̰å…ÌÌ&a€ñ•%PÉQ¨4y=Üqîá®Ê3mÞgáûqŸÃì¡U‘Ìã‹Xø^~¡bÎcQöæØ¼\çèî»^—™¿‡>Ó%ˆƒ“ þÓ9΢÷œÙõ«ë1¦ÃjåÆ`ŽÇ䌫&=§uÝt°ZäŒ(!3Ç(aÜì<8ë›"“#{a¯är5,ÐZßg³[W¤Téí;yê€ï‚=}3'nñlÌÁ©Üã}*£ÆXƒ/å±<óß#·BŠÎ™„˜s¦Ú®l•ÇŠ¸Öì"¼ÑÇ¥PKƒ‘“=4/]wwv3Ös©Ê›­.ø ÃfØbÓ©y嘊íêNFeD¥²yÎfãk»u72ßÏnÜj±^%ïœ ÎÆhïC’IëØÂÖc´lÖÝùÍ>Þo¶1ËâÒ§ßø>§§ãf·®xÅ‹ ¯¬Ä e‘ì8ÆÛ·úa‚Ùkpë8ìß›w‹îë@Ì쟘Q våÙ܃Ôþ*`3 ¯=^h¨Ò “Þe#9~Q´ØÞ:ÿïÝc8á2ˆ! ]pô"”}QÐyO}A;ÜêJŒ¼™yµe:wv|(ã ñ#¹ˆÄÕ!^TÅï疶ݰrÃ~.˜ÕpZj~W¢—R†å:F·ð×U´0ИGÏ\-ÝÄïÁDšcXgGÃÿ53Zß‘‘bð<é9ð‡„ôºÄøþÔ¸„Sæ%Æ‚?™Ú»|Äz3—ÁõS}A %:áÞn#ŒA ]ƲùôÄ„š4­Ws‡ý¡;Üzϧ½öÕ3[·]ÿ?nÁü .G苆;„9Í8¹gÉôò탾—ëj¤Þã±H˜~ÞÞ 'ß¡¾Ö§þ»§ßÌwóS¤ñUÒôñ„ªtçQ‚ôÿ.GôÖ`Ì´³ü“³ç² zjŽû¯nZ¿¥]?ÌzÏ:ž¢ßzÑê&¿3 ™VÑÁ¨ÞWŸ—Çùçø!±¥$?óÓÂÛ¿s´n" „7‚b[”™PÔwçPž={ü,ÙæÐñ·Ù·¿„1(Öjf¡ûe+¢•?nª…[Ýjj*ôK§$wor 5f\Ô¾V0<“üÐøñ¶’oGgŸö&ý%¬êx¦ŠUê]3$µ¸¶@¯ ²™ã¹£HZÄkì–„ÞŽÿð—õáSdD»zA–M‹wxê[·Øíùè꙲Køñ§Úß‹¤n}÷žü_4çÓ¾øí‚ ˆu5§påAó‚šxYñõæ‹f(Ðþ{ýˆ†œhÑAáLŒÓ¦Ž åJ:§Ìc5ç5ÄÖVZfœuãr[s±œ»¹¼$zx‡0é Ì—i?¸QŒÒk( @L¥eC´|ox—n;ÞºÓe‹Þšj.ôviϼë7iŒH·µÙ÷á”F³"‹às‘9ÍFQ§qiA›KbÖÃR‡ ¥\'t'çó;äÓkpÀv+!õáWz‘ÄVXÞŸýhõöv(Ê!ñö®‚å¥å?EšPŸeþúßû}_^¼ß¹þØ4¯ã}ŠhÑm™a‰¦Peʦª™TP˜süR“;nÜ9 %mxtg¾1)\Ï»øÙQÙ+©ªäÓ.È£ÕÑÞ_Z¶4`± ¨ ª«» BŽ‹—Oq©ü°g¿£ƒ¸o Oº]¥GLò…9òñyÀ S1ZYNÈs¼/gC£> ZM9‰ìº¾4ñÎeó¡È0RžQH÷§UcôÇÙeÍT]:¥þ4ò¨í]“§´ði9Òˆg@Ëê¬)8±ü!öäÅñ]&¯‚7xh7{¡;vu¼ü¿WYÞ­§÷ÄM.s1NŒçJ( ž ?½8/òbïo*gòú¤ŒQ‚ÌuÃô¿ur6Ÿ±oÌRñ Á¸Ú~3%>i¯(RéæôtðmnÏÖìý>YŠÁ=ˆp×ùá«ti,°²Â½ r±€ùh†ˆ€â,NÍpê9hNøý±ñ×ÊÜ—X»zo¸f ™ T•Å4Óô½UtŸ•ÝS›‰¿÷<}<¶'5Ë£ï[™#ÔYPî#šUеHtÆŸW ¼‘¨%„É]ÎõZÅt–ËAdÌ#bj†Ÿëöü¿ª÷aFhð!ûíB¡ü©†òáj¤£LG;Ó…c|ˆQ †ìlçû¾Ò.²˜W…II[EÕšß\ñûaÊ?ÆS!KƒˆvÀ†0tY qLåZú6ÄFÊþp]ÏcéåD†5¬EU!êÃTP:Ê-—Ês”—ÂE£‹ÎZÆøî‹ˆ©´–~²œèô"º1íÓ5›§×>ïìæã³¸U¶jýsÐŒ+òÃe%RóØëž$êéh]÷ò©±¥ˆÛXY×øÙ<&¨¹ãæ÷zãÇõ7)5S7ÕÀïob,— ôÒ¯[ì‹Ñ,tc »›Âð]š#&¼Yë˲:òð §ø.-åÓr«ûÎÚ&ðcÙ®¶c6o顚”DcÛˆÞimcÕìxK>ÿÑÙà4Ó `ó‚Ȫ›¨Ýæ«è™.­Á'ºên®}¾XÍ÷óGú?÷ñûé =ùÂÙçdR®Y7»£î–em/I ë¦xÏÁ_V>Š£8¯UðÞDœ;‚¹ÁSª{-ÆèU­gªÚáå®ûsë³—´{ð0®rów kéå/wYöY4;PyÝ«GÞw›HÃö@ ¬Î‰”%5wQߘ߲Ü9Wä­?Œ2 }H~½1]rkýNÕ ±6®‡»i>iÜe=, šº•äÞ_Šç`›¤¬Uõp¨ Ðý=·ÔÙ&Î_AN[÷mº æÐìS­K}…ð ;êTýcÊKÇÍ,6$Ä®LÙ«;+«X{¤i®¨]}:0óÂwØ«B Ç®Ôa0Æ7Ã>Ý8Ñʳ“aá\ðŒ6ÝO5ðí£r)ð߉²VhŽø½…äŒÏ—C_‡Õ]ÖuXìz?6¿fùï}0=8@/kV¾ W×Gu^ÚýÔî¼rîø{N›ÔŸYí…QNtÕ‡–?˜ì*o1ñ‹a-aþ·q}iÛÖÇ 2¿†ï2I/:n êCfEÎåÑçõÚ¨k“éãm]%3SbˆÙóÞÁ& –«ßîUYZ*×x¯…ÈöŽö±l™³U¬ÃðáÁ¶ósá)4zsŒZ<ð ÐUᘨ9¸¹¿39Š—=Ÿ¶ÈFL {hPÒrÝ÷ç‰ëÝ«æ|i9”b›ïGGÑÃS‘©ÁøÂQ&°\×Ê sCÝ(FoJõ¯&Z ã‰«šy» sáèôÕ,ž¸8™€¹{,gýñß'çšÅRoF†ë¾¸rU#˜÷5Çm˜Èº—2ªUƱ¤Ã¾~¨mM:èedƒ‹!Z§'0]_ÕL€ÁaØWk‰–™zLÎ.{i:*w-…S :œgke~jc÷µúÆÝ¼;1í‚T¤# ª„ï1X1ٔYô§éw†e}ÐdÛB„JÊ‘cEÿ›ÕâÖ^­× #”¢„¯Wˆ‘bUÙžü§[-sš Ø‚îƒ#¿d¦›,ʨ™­F÷òé;åR-åçúö•”/>P§G† 3½S§A?Lï>â›Îú}e#µ®T ÁþHþ˜tK;!6»~U~.ßpÓÕ“ÁÂ÷ö¨¨¿‚¤  dŽùUÇãñ¿{㧌䄪_^ Xëûý*ƒtVLÒ«õÃVOÅàë7.›×³Wê“ ßäÁÒ&¤˜N¯nÙG*±º|†:®žÒ^Þ¾ú™×O9œ¨ '~œÕÓ~Œë’[êMȺŠé4Q_-ü týôyÖ ‘“Èôw:ï¾)Û­ÎL¿»¾„*b¼[{Wî­ ›Y&mÚPP ¿R¥7ÒøI›-Ð+—X´¢÷„ ñB Þšp»UU'zڑعéÇç« mgÀ ”NÏd›®ùo—Ê}tXÍ*öeU‘!C³J¾òìëTÁºbG6* ÒdÛ{PÜ"šÝ˜¨‰ Æ ×`Û#iRC4äº.Å u$–jcL’D¿ÍG5>>»¿OªöD òkÖbyú‚w»'G´p‹°”ÉEy¬)„äéÉå“­ãg|X?>ä5q—‚¤“j¨¢—µÑ¥šah…®YJ)O#ÂÊê5Öè˜GZ«H–ƒŒè9&<Ê0uõ¾“5…úÝ­†—r”Ðõ@¯sÉNUP‰ Ý|¬¡šŠ^–ÀøSðá?Òôíú òû©«ÇLôb×]DZIÕãB‚³Ü'6¢~Y{ò)«ÅÁçFQwêLxã¶-!eYšŠD¬NúÒE¥½IvðQ É& Ì“,JkVšv­±$¬@ BbÈK Öc­ÓÌÒáÄÛ¡ZÑ>¼p‘¼ËÅõ§×OÕ~0O•-îÏæI<-Ñò?Û}÷ÕæîO¡7rÄ…Ó2ÃSÁ)Ȉ›ªû ªþ˜þ¯¾Û_-H„$~Õ §"ø»—rƒîŸ®c”¡ç5èpp4 Þlé9K'lżøÏ\¼ÊJ.$m’£‚)Z• ¡MácœG>ß3?¥Ùý˜@†I©¾:öÀæ”=|õÃ}°kuËmšìÕ&Õ(³÷Èu ,ùi7ÄѪڗÏ]õIÕí~%hFӫ>¬õo$¤!× `CvrJçTp‰\q:îq«D>Úœã½äóº.Ð0ú¡žÐ«“C”ň"±Cd¿jÄptlO7nñ:ÝSi°Ç4¢ótáR±?²šúsîå¨b¸_c5°ùó‰„>oW+µ‚.ô8ÒE”» fZðF÷Æü¥V¦&ÖƒB`¸"¯)zUǪƒ¯7iÔ.|z¯Lʸš]KÌÖ|>S|PÀzÿ}?»w,RáJRì ¤ßø@½Üz¢š ˜ü+ŒÓJ‡BëwÒ‹fá µ…$àÏÁñÚ6©N¼{îO¡  ZE×cª6óÝCRï]žÙ0Ñ+|`nµ¾¦zK¼Ó¾`WÖM)ç‡54ÿ i·õ„ìþç#¹ 8[¯:E›ì$œ¼Žz4 ì}é°ñ'wàBLõøñ&>û7?oQæF¶LŠT‚F)Ðh£Ÿg)Ò¶Ûó ñ0i>Y‹à‹º£õãÓdgoºã¾s-Uצ0¡Þ´ëÛ^ˆúªé÷Î V=E½Pá)Êãµ­Æø6Ôô&-D1,‰G2NŨšü_zŠ.ÐCfÎñ=OcàŠ.^!$„"çÎæÉåÌS‰ËryÃÆñ ¡ Tø]C3WÄyAõ!+i‰}rŒbR²®Ã·¢ãÑãÓ”Z=Wcö×êõû=ê_±NTZiÎó¡è†œàЭÙéÙ†·iI®Ú¸¶àX¤|8Å¢Ã8å8XÔXy@ýó›KɇM5Í×ß}=ÛEV o¢êw5 Fκ Rp24D‹]eåЕ­Œ©* §b í!v~ÿÓ]ùÔÐÔè~7iÍ•hü[á–®²ânÎí#òìÎW÷áëÃ÷KÞ³!´›†ú$rÛÙdæ%‘.žSÆ®šzr,`¹ yªÐÌ!;9oÍ­ø·pµø¹ðݮʾ9ˆ]cN¢¡2‘ºa]­Ÿ3óÚýYô.N`¾ÍúOŽç ¤“Y1/)Jxºå1±Åë­ S ,,‹· ?4»¼¥ )AΙ¬KHëÝj~ˆPŠ vÊÊ!·¢“kKˆª)²º¢hDÔ ’…ÅŒ‘‚jT"¶›ÐÑ5›|”Ûv³Ï†æ†Ñ†¼(¨Ú;™ ŠcS8P ë×ÂXê ´§\ÌmÙ$3SäfÄrõûpª¿±ŠFtÓ”†ŒÏc›+“ÑV&Ž!ªIGx}¿Êù¶ãã¬E|µmòn6nÛGvM'¯ºhY Ùz#—ÚhÎV(Ý ä)Ò­Tª ©ƒA´8zÆ—³ŸóÂ(.Þë<#²-EN³'}],@ȨÎÓ‹>çI½Éºþœ”Z†sžþÞÒS -îäóbBì¡7HÒPóu_òÇùï û×Âi†=ÄdÞj_ŒÏ²>ÿx;ú¤Tz¯«‹†^ÒkX—“155"…9†úIR”üríé3P~¿òxwƒ.´(Õ]ÌÍO!\Î{µxÄȼ£ýøêŠïŸ^i¦Ý¿tb$­òr/y~Þ°S9(wL~qÔHrI¾hÐE´R …{è7N¸`Vî„;㋤‹•r¡´Îó¿ Ärº„£t™¾ÃæÏð2w@Qóêññt8ú{ø§ºT …H ËÒ¢Ú±•¥v×'–P‰þ·í\%h¼+ÔVp¿!³?ìÑhÞÚï„Ú‰ãX8Ã¥gÙ†á33M7ý}õÈÜ&âW (±8PÃÌÈvr0dw4ô§™µy•LܾˆaU„¡G§Ûä§Ô6h·¸M ›tÑ¡Ém6þZñ+n•§]Óç ‰QSùµÕز1½³(楨“QM-ÃRrZ¾žVM¼SQÅ]Õ" xÕ<}Á²Ý°¹Þ0´€µ5 C÷p¬“ZÕΡŒE`ŽÞ±.}: ŒÍ¡™›Ž¨K6Ë9 E#yýؾc1ò“:8IÎn‹Ô',C¼dÄK€ØY-’L{'Gí²ºîß¡îÔR1nêýˆ: Öá »Q#Mÿzm†×g‰/“vHÖ[×--ðÊ-K‚ˆ}ÒèkSHf † ßc«ð÷m¨äƒBâ\å¿<9Ï+5³V~¾²Q»AaÙ(Yx1>RÛTŽÉŽ7©> Á÷S}QKQ:éaÌ^8Ó† ×{t»$™UHaljS¼iY_¸%Tš±òHh–QwøàÙù]žwTZÙ—è¦3ûLønpÜzgÉ‚§àºau Ê9©x„ný9¢@Ñæœmßm¢‘®än#9Œ¼5-hð•›y¹ÈóÄÛÔ^^×u•C¤*Gº©6¤n¡©èÐYÕóP†_¢T¢:±ç‰Lž·²•ÂBÉ_;ÇåÙUjÔÀÏ¿™®¡Ì‘U žøT=þ›ÂÏmÁ,$9±ß °ËñÒÚý.Ïñvt0šl€êDH€ª, 4E¦í9¸v¦ Ölàêµ3 $°Z6´ÑVã úxU;®_¢É˜Äóú·tijÏ uJÚÍ’òÁ§§¿>ΞûÖúù°T:îW¨Ó€=x¤¸˜µ°¼EÊ·fî‡-"jƒ‘/!+碖‡ ’¹ÎY;¢SùbwÕÑmñiš1 -¥¦”°äØòßIKØJçájˆâ#kåèò_¿¼.?ž¯C˜:•ùtgfìœø!¹è–yûÜÒ£L™Žœc¿ Î3~sÖ¨“£‘n£/úÚzB ‚M+¡ÐÌïiýzOaspÐæ~: <¿ 1κn²·:5d#Í“z?GnzÚ:ùë…M§¬š]—ZÚ+}zÉ!à<0OWaº3“y“™Ôr‚ez‘4’L±·y)×´Ä‹Ë{ZrqfÝH¢@µèã ˜•6¾š½;˜ã“û…Z 4G4g›Âq›Ps=2¥Œ«¦ž™ÐÑ ·KAÛ ûG^÷ IʧºmÀí§aÑýx5¯šoªõbßá£ýÏ"ÃÖé%ÕÊhMö´) ·q{+MÑȯ ~½ŒnktP’h~îrî ú‰‰iÇ{L‘•Ìñy÷ý ¤_ñõÄ÷Lþ¯Î$†iMîÁ_˜Ò€v„«Gú»ëÍûǺµ¯kq 6m±ãÓÎ'®4I¢7²0'˜èÉf;Ð$ćx;@‘ÓºIV¦ã´«Î§á™iÃ{ØÞ ш⸠€Ö]ÛZÕBísRœ\³ˆ/žk¦ú¼¼‹&Eáü«®‡¿á'Œvn"ôÌ醟žÛ1;vÖqÕ6ÏoõÉ¥uâÇYndÌ1± !±;¥ÏW䨶Pã…ŠÅMtž_C—’zTE;Þç\*$ÑC0¦Ž@%1%^WËŒ‚<8‰ùÕWª²»;ºã?c?KÚíÿÉs[>™„êŽõ^mBsh«M·Hàû£NtB­YȈêèGDÆd½£’ËAžQ¹œ™b1âå èÂñÊ/|)}4ôj­É7*[à¯jr£uÖU+j{ŒC…EeÏEöÇ*vÓß§Õ¨Ó65ç¢]›ªDˆµ8AIá|+6nÑŽðÔ—§%oü.=ž¹ùy“Ǩþmç~·Óãeë§­¾”׉õÅ’™ãǼ›Î2[vLsÆ?m¹ÌæÉJq¢¤;>ßë¹Û¢" “¢¼U™Ô¹ÓN8<ˆ—zã:‰ ï®o6àÖsÊE# É<¤iÒ_7ÅVÊ©¦ºœ¬,jÇ`Šç9¼œ›¼×4 3O¡˜²HôãǯŒÄº=½YãÛ'éw‹5¹Ø_Ó\l.Zi®ŸfT66Î ¡4i`(ƒC ‰zi>õÈân -°<Ÿq $Tòçõ?îS#‹ðŽúAúJ6Âò‘°Ž|Ýe)'*2_ëÿ%ö®Ø|v¼Fқ˖^yUaC¬|¾º/ÍÞm6®.Ø'½¬ôú˜õ‘5¦hMÛ4GÙ×ÒÝ;[fÝFþŽç”¬OÛs\Š«Q úzè…t8,7¤ÿ Õ­(ê?V(ˆ“å[ÍßÎÌ…Á5,ë®â/7‘)&û•¬‰š „hkñšßžöÞ{ÝŸÏ84vã1Ú<]žÔÚ¹¡há tl›zjÜ@ö«[…JgWƒ[@1Eh¡,λßAúN*›~¹ž}]h¿:#ø$¢4œëñœšvÙª­>ö&lÎ ¡”‹ãY!tn]ýI´ò-*ã –—Åi‹BÌ‹»û÷wUJ™­µ^ ‘PSÕM/VÚþªÝ&û´FÎç…•À€‰ã®·;8y Ы*A¾)íôáÂ;ƒE¬é.I®g“³Œs8ã4©1¬æ-³Óvmq•\úPôSäÛ³øcÙ"pª¢–ñxI?8?"ÓÕuåÚ_Pt£DóŒ“U×ÈõYk9ïß2-OºzòŒŠA#®´|Œê ì®)Á zô2iÆÓ«éHZ«-:†ê÷v×§ÍÒC9JÚ¬Ù¦}©£Ž…¤½6‘ÍÓE,Œ`U ¢ C–¤p–˜’½Ëy¬jmÓ7m0@­€ª“|„k‹Ëkͺ8ᎷW”h¯ŒØ¦zk ÐêoKʯø=H$#•û›\YÔTùž¦…pÂŒ[‘¶ÆX{d›ìPTAƒÎF4]þÙªþ"©þñù뢘zŽ–³*¸öôÃáHܳӊú«ºÉW»së©íýèÕÕñ,òJ¯ÄÔÐÒ‡-~Zm®YÇ8e•sÔâžõk4ðT(·p¤-W”ùºÛ§æìý½hcú Ðçv­Ùî:Ñ“¶uk ÌQjÌ’¥ú5Ìk‡‡ç`>2b …"í¶C^M”h)zQÝS"‡ñP,ÕCVª¨ÅªÎoCê6ÔWÞHØÑØE36)íÑ,6-®9‚ é©à×8ðK8ÜÉ­óàÙW^%+]>”`¢ÅPlz>‹7tàØÈA §x3–+%“¾Nb  ˜Â‰ßÕœræÐ¸õ×»‡Vñß<ð¡í 9tSUB.ºr„Õ<9/F>†aój¤)¡šhe½ÏB¢cMB;vBí³…äÛÆëŒr¶qÛÒ'M”m‡µ¦F0ýœ Aª…ݹۨ 0ÍúârþÞ2æ~3If:VrÒ+„µ`•1¡VT¯éÛ4~p‚×]#[nºq&ëà9dž³ V×eGƒ4—%}l.wQ‰Ê¤Þ!¾qø{§»— Œ'2Lpœ<º¹ÜùÕmÝ ùG!%„ƒé™ÐÍ’ŒU±ýœN* o¬4£EUx%yñw^+.úºùIŠÅq­AoHƒñN²î…N?ä¸G%Ì$}nn=üÝxhZãMs g1SÜC\V0Ê™Ñ?[·Þ¤ô0;s}ì:Ýßœ§aÄ šˆAÃgã tŒ­Æ¢;ycÔší\ïh¨«S‡üŽ¡ü0q¯m¹j†‚—›…ãÓ7¦Y }7ƒ„iÃ3L|:®È0y3쥺j{­¶à€Â\õaCãeÔG)ÊÌÄ8ˆ5©ùø{³i²ž*8Q]Ñ2È38™Š}>·–»¡‡"Ýõ¶â2îwÁÊ`þ«=ã³”(º¨'¨ß|ÇRÝ”D{ð†‹ÿ½Fó_„)¼ÂaNÁæ›Ø@PjéÎYË,žu|x*H7ò*ÉÚ­sê=4A¤¯Ã,0ª†õmåLnZºžŒIC^<‰G¦wÂyïíÆ¨þ˜PBoϯ_'ÄiQyË&np„Ù´è4i¯z"ƸƒÊÚ[¸µg\¨¬(t÷-Ë…ªøEï’bâPTKw«tºq¦™0Å„M0›çM4ª_²ê‹s•öå íp‡B^K¹i#+wE¶WŒmldWMWÐí¶ŸCn$ÌI´xqͤ°º‹ÊÛV7TãdBÅÌ™ ¯²¶¶ZöM©¿ÍE´SRbb.ËT¢|+¾ˆümË¢Éý”V¢½µ¾T_wT¬Ðäï¡èî¢wQ¢Êw8—u.¿|5/©&¯¶p/ÓcZ¾¢­‚ÓFH„ÒOۧ׭îpæ2ënpGh5‰¿jŸµû30‚ÂêªÓ-*¤®#‰|ðƒ‘¶æ…#a'¦»¶Gç®?Ú–fÈËy`çnŠ;:5ÌádkkÑÍU…WÈ…?›lhÙ*"},»&Ò¥‚Z}¯á«úOñèþ%ÿ4ÙúÝ›¤m6«Ø›êbqȃíEê:š¡08,΋“…6”„GÕòÑß*¹YdUwóxsÊ Ýƒ ÔÌG+w)Ý£›uÔ[s <]W%óÈŒ“£}q4.ê²=7Ûæ>¶$–×"2b…åÀèØØþý›ÓŽ3ýË(b®†A•’ÉÆºåzb1ø¼EÅ„]£G0_s•pj`ÖŽ]*,ÖnŸÆ·h#?&²R8·|YÏ#³´®•5©ærјΦoŠh³S…InÕ’ã¬MKG%u:¹á¡*]*¬sØäi¿w¥ºìú®Ÿ£Û®Åg«Ýý“3ù^õç{ifkÔCؤWge€ß¿g”„¼Ç­é‚„>žø›5U JÌ™õÙa÷iÄ>UWøã©šumfçßÁG¿ßÍ¥hdüÑ´0«³^ÌÊŽÛH×=•ú'Ësl  dlPåþ:07U .Û±£ewe¾³V7•©€s’Sá:Í&†VSÍ…ÈŸùo ÷ø»sMÊõ8pGA`íãf®øù|òÏÍž®8gÃÉxî¿‘?%—Œ9aè••µÞØåIŒãÈc½1æ£ÒŠNm:¹ü9ßQAeØõoÄÑG–œ—m ¼[Ñ·°:íÇÕ•£÷íê»MÊíÜÜ`^0Jg6JPÝÄÁq)ý?8ßU¢Üä}v…JÜ/¦„¼ g'ê «Ó>¸nË»tJu˜›ôthëooán±~¿ž1f7}{þÕ§]&Ý’ý°ÖwÖeÇ¢oT!ò–¥(ß´^¾üs—?C¼ÈpÑ+óB Y/öcª<ê_ÜçÆê1j‘x>¼¼W»žWú1Ì££Â [HêÀ†4ÁTVÖ_¸•uãc—Û<äÁNyiºâS^÷‹TÏ/¦tœcѦêoüÅVdg´Žt1æmÅ[«¼È(²f~JiõTÙÀ–^^W‘¦-N©T)›q«1)5ɨ†>Hפ·FuÈ™iAÃ;¡q§GfÕ"”]®ÝwXqõ?^¬,ÜU6«¦æÝ_åV7h|»½ÏD=îfm6º«~=vçaz«ç°6QÑAG“³¤´]}S³o?…ÍæŽPã§ã]Æ~(׿}}™^Áä±y¸‡·6§†%–QW~Çõ6º¬ûì·glŠ­ «â¨_ºUv·ÙVܯÙpÖ}>yË£Ó÷æôì¶áe=ôÅ Æ)7G®Óe5 Þªï-)íÓÃ^ý*eܾ®§ËÕ¿D¯>wÛáÕe-®sÙ*>4P†Œ9½wOHk2þ’ªê¶>¹>àñhiÞ†ȇ͌ã[ë8öB–©MP")Ä6œ=~‚¨PË UT¥"1~Y=´àãáwC€nÏwǘõž·bŒþ°Ïæ”wùÆ góŒý¢þHè3C9«³Ô㻳˜|`Ð-v{õêêíu¹öïbˆœm%Á6È-Àžîãpü-}X*3©·Ô 7þ$ºÒ«Ã¤x±Û†ð÷.}½gyßÝ’³aþ©ï¿&/Çù]õ5¦íw­9ÿ‘ç‚›cu½5¢„Qpzõa›×Ø\îÛ·6¾.ÏÅÙꦆϧk`Ï´gÚ3¸Ê3¸Îã>ÑŸpΣ>ážž ¿JÛ¯xO«÷pë!Òš* ¥ùO‡ï%>]n_]xÞÉûgújh hr²«­ö kF‚ùc(¡—k³ýµ~Ëcå·:]°Ýæ¡£p}]ÜšŽçgív~窛f“4r˜q  ‚LÜ:|cÖQ)Åâok5#Z$  ¡Ÿ\"yD!S3¦½·[–9Ç/Œ$ƒV¢«mÑ~6o5GLÐßf–&M‚IÐo”[»¶4³t 0'zÛ£¾ÆªsÝ7‚¢ØvNÄ—”¼¶€ÖŸË<Û>0jÄÆÄT£4¢ml,›yB¦¢WsçD÷×V=B„:87/-F›ß쌡O¶ƒ^oÃßTêLlh_Ôh S¾å /a Ä1kŸ¥ÜB qˆ¶ê ¨ÿÞê¥ )HITÇxÜJ³¤kÛ@ P³!B"ÑrÁxš)ùò¢®)ÓLÜüü|œå];ò„C_)’‹Úª`m¨Ü°4·ªïú½'ãò=u®ý«Æu¼¡=h/ˆÌ[f®y^œ›*êÔÕZo/#ò*÷:ÉݼÉe[A]äÂQ†õÔÅ€DP­;,¼C£.Ó¯8꼟„K•.·Ou_8Ú‰Pû”}#v7!ZŽ—LÆ­_¦±Ð¸5’`Ž …2ÂðΣ҉IôA‹‰QÑq퇶ÕÊádé\ä$W”x×°ÃL‚œÈU€^D Sj†·½õ§ñ&½ý*–ÜÎ ©§4¿W‹!ŠÃ"`år¿·nq/‘/ü´ÕÃtš+Ÿ[)ÿ+–Þ¶¶DE[ËC­ÿÁ'v'PgÂ:Ý&sìÜÖxún,¿uÙ~ºë¶×^Zê_MUÖ¾»]M/¦×SK›]=·ràë¹d‡ .\7°¹­FMíw¥®ê×zÚëI}¶»Þ×{Zï{]ík­%Þ×zZïK]ék¹[®¿Ÿêòù>ÌõcßÁq>¯‘ïæy«Ä~4žþŸt‡wÖ&µ¹Ÿ]õ˜ë&u×eû>|ã Ì™Þùp¾¶É¥É™# ñ'žŠM–5ðÒ9UAœ[9Ÿy&Õ,4¨ôÂÛYÈdçÕÓ]cª§æ GÔñ†Íôeв3¦mme¤½ÛÆ…ÅA—j˜õý7éîuå}Ä6_\®Í˜j£ÿ¢›«2éó}­ÊòçÓÖŽn…˺…¡O¤ôzÄðsV½>îÏFXÕ\ËJWá€D§I?hF¡QF èp£î±(áÙ»x«î¬ëžÿ~Ú/©¢U»ŸSÏ…Š Pþh÷¼}ºô,£8iÛ²·&ôÂýµóÖP¶9™ ÈŽ˜€¾òM ;³ù(ƒxiv“GhÂ#‰ï²ô¤…L!ŠØEÜÃÑ*]Þh{l—’ˆiÛvøóWï/±#â¬.OúÓ@©]zHM -º³ó=™ãy…-v[÷]Žþª¤˜‡bå…+”üB¶{íS=i~‹ökq\}'4 êë1¡sú´7©4;gžçi³ÆªökI3/g,âËʬ€Ô\œóËR¥"¥ØíŒ $!®LîÏËaªd10,ÏÏF;ùÉ¢Èn(=ÂbIˆ‰‰¡2mz9¶²Óyæ¨áHçÃÑÙí[«mýÎvökˆš“\R³Dó4äöÕSõ¦¤…Z½-°Ø«í¤‚4;Æš‚7;Ñ—gÈ<—ÝÚe®¶šSßé>aŒÊkÇ&>päð*;ò“‚" Ê\÷™wåc¹ìÕáÌs2™¬AÇ¢§|p$\‰ÒX¡LG===z›Wªœ’-ÑaÕ”zÓö±ã×ð˘¨·µMÉ%×è~xý³Î!¶&~´hm÷𪖉P™’4¥"ZõéÏZ£J¤òÚZ·Û3R+€ìï&DÐ]l|­™ìêim0ÐõÜDuíg6àh.&„by¿<ì”/Å[YU:Šµäø¿±s}AÅÔõÞûf4aqp›¢;ÑUÄ Ð*2KhBÀʲò-Q}iPZÒ¹íºRX´9´¶>Wg¬g·.øÃßj™C²tâ;¶»×yÇɓ˟ËÜ.k*¢e~467ÞÔè0çYV¾že„Z“+>ËzätP×ðfú`Ôþ‡£ç,¼ÑÜ_O´_ž¾G㤥û³ë†Ñ"’¯BΙ8{D|Á­›…°Bd2×Óßî*jr¸¦éOQ¶n ù¬˜ÒìCb¥6õö妛Œ2ÞËÿ{¥™kõu~ÄüÀ¥†Î/#;^|—†¤ŽÅNM¥"ž+ë*¬æ_~¹éå)X@ôÇd ÇõCvê«(ltÀÑ¥@f8㆖m«2Ôÿ 9 °eÚåÐm:·g O pê$®n¿Ý0¡üýW?zœupjNˆ¤Hsâ¡)|/ôGÕ†½—阌;ñd"ÿ+³LE™âVºk·ùôÔàpΖÍÕUˆŠ­;ÜÈ¢j%iê猤ŠÍLáí®aò9 ßœ(°ýx®fÛáZÅïnhSI´*81íÄÇ¥çnK<ÇãZ>X¢”Ú2~ÝSDŽ&†À‰yçÌ'uƒãÑe¡ae|=×Ã=fH¿M³îêp¾®uÇ »â4OÅ#ÿ]»ié/ [€!ÇÐûh÷ð䵎ɾXx«8Ñýˆµ¡PÅÎÜa@§æÿ gš'Ošþ®3I.7¬ùª?}ÝI§¢,´Å;#:ÝÁÅÚ1Ñîr„ K Q }é4©¨æ^û/óx™üõ)_×n—‚kˆsÏœms«þá?wßçªo:}sPKTjžd+ê|ûóƒ÷?ލÒ/&qvG’Ý\¢ÛÝë…ÐQÌ:å‹ -xL¡›ÓÓûc·>rI®g%wlO«–6b?D S± §æC«%(κý›½gã°?"Ò]?á |9&çÉ›­Á‰ýWJÑ4]d3Kö/>¬÷ÂøT?ËlsÍzkI4$‹ñ‰B$ïÜ­5‹|¥2ùüY•Õlƒ,W“3 ý&~E¯îK×›×Í'à°S7ÑçkÝÞôç{†—’ ]‘ÆN~-Ö™ý¿¿ï ¨¢zÚ˜P_쎮Ý_]üß *%$i·5nfLaÐxkp==›o5DLð [2ñòU’^h!úñ$—Õ}Ó'ˇü'®$7ÎÚÚ`VO_áÙ3ä>°ø|ã$'TÉüÙ©­|Ó„Eïšr?Mª¿ªf„dà w¯C~׎ºa÷÷CT¹÷÷–¤d""ý§á¬Cµ ;v3þ´&$ƨ#û´m(0t†ó ¥ãó¬Oœ˜ ×Ñ qÅ$8‚¿+nþ/ŒsÔσ–yñQÆì–™M˜¢=£ò¨Ú¦¦B 16ï=¾nš‘ˆÙ¬ÁvÐ<_omh ™MøwÇá±èë]˜×†TE†Ç\i!‡ÌoLAÈz;šõLõ­ êÄ:Á8\§4“½7åÆr½mÓú/óçIŠl«c ”Ì:ã¾·t1R2D_¶}ˆ? fîš2©©wL-•ߺVsš£¦Žõ õü÷m?›Û8SQB—¼}Ïñÿ7UÑbZf+¦{ã6)Ñ ‹jMøƒmý]õ®ºüpigôë¤[ÀÄ9´ÿ¹˜í€Ñ4Œh¯Cßm’¶GXvp§l|.ÃÌ3I”ù¦Ùൠ4»Ãýq}ÑP»Û?‚¥Ï'î‰Ñµré~ˆ ¤· Ì Ký 9#7Éïþo,ºq†`s{ˆŒÖä›·#÷s>×€Àzr3±C˾«Ý÷YºÖðKrÔi³ER²’³Câõ>,ÑHóõÓâ•b'ýiñˇ W¾ºÇ/hf2ñòª"¨Þ}¶ÔŒ£•¥…zº’–ééæ“•U ð”©!éÀÈÕE¤ªTkL'6[ù¬nYe.¶«®„\3ƒ_ÎþãYÌ5¼às&jÊ&wV ‚¥ÈZTŒ¡Qm‹º7Äý5›VʧCà˜t6Ô kLÌX˜@™]ßÍvTü߯[–s¾v?Oæûã²\ê©÷@õa-~ȌӉŽJF•¬ƒÛUÒì6esåýOyƒ„pòèr7þ$r»åðs#ýÿ9ûƒŸ^ Èe¦Õ~¬O’Ê™(©oYðÑF@_M.üãŒsf_é rŒ"“6?¦)^iÄ!Gîç'į0NO‰ÃqÞàtgTz“¬ôÞžwÈc‡:Ë ‹¤Ô°Æm!´¶ün]êtKavðïÁ«P‹êX¼‚á Ñy™Ý¼¡W#^ŒÉ¶?¦Æ°ò¸çàì탳·‘ÇlÇcòMh v諨ºªki¾ÇìC;TãÐõžVÁÔX,ÕäáX"M|4µ4Ä0iÌR¬ÉœR8}­p핱ݛíÈæ1Qyén2ø£0”þ÷xÅ|«Â~pŽïŸÙTiV©`²ΦuÞ!Pÿ^ÜÙB)µÕø“ b¾øããYŽìõ㋃>3“^˜O¬+§a\40VxIïüØm¾z£ŽF%VÄy»AòU8½sÂÁ<]Ü” „aTÜxëmuɫà ­;Ï.RØÑ‚×l¡ËÊ)€a\·ÁŸk³Ó\ tØìnb8¹ðìÌá×C4Ÿ,[huFô½øTRŠ¢¼}5Ú9Þ‚Ù4 û»Ý¡>yã|±©ˆ»ßÛú½®_¶x¢ôѼ}ðæº¶Â%„Nüš ;h©\øM¨’¿}îqk¾–Z*‡s3TqkFl ‰™€„ÊäÁU¶ßB)€j¼žà·—׸ñOÿ;vkâ5¬¦÷nN€Ù KÓU>*ˆÁ…ÎÁ­0P&-<ÜðžIAÃ6s“ÀMõd¦X5u(J\pk«–C¶©Üd/-ÙÂÊôÅ}Ò¾ ªË(/3î‰àŸÐ Ÿ„Möáq!)èe÷ã¾wT÷3É•áRÑ`§_  pæµò1Ú$Í*n<÷—Ìÿ*qÜ_¹šÖ6irU>5|碷øN:kUñ‹Å’BluÀ©þ?ŽÚëÏýfhmÇl\,†&ÝÉ »¦Óçv}ŽÌzÓm¨jÝ•¯›E±ÂT0?WeÔÎ;cϪÃS¼ ËÎDÒÒUÑ~½¼’:˜Q¢ÒÒ™*Øò&Å®Û ,YÌ´†´‘Ù}û/q«o]ùîwúj(Î5Ûö„™tìÐ׺a¶Õ^ÅS”XÌAÈçf Auz4r×’/FÔͽ À “ T Ÿ{WÂ]«-D4wW:«ÛZ«7å JˆÙ?Œ÷LëãEÀ—VÕÏŸY­ÆË _I¥ðkK¨ÉMò+ê|C×Ðý»Ýp{þM»úoM†¢K’æÒ›•B0ŒM2åº%¼ðƒAz=@ÓƒCg‹Êø9­Ú ºtg&†Žª(kö& ÙØ~Þîa1%d”®É;Kw+ýÔKw~ uõ µã,yŸ|òXQGNÆ’Ól ïףƭYmýsÎÃIíž·ÍO§®¾Î<ÚÎCÓ²¯aÊä$Ê`ƒñð›´î‡íüöeLô xd\Ki;³|iœ¡æ…¿LO DL(!Óö÷o²›Æ#l‡Cúòi‚kuKíÑBLɹœ`bÕJ†¡ÀÖ‹¹ËˆáyÂUªþñ&$ïÒc„0ˆÏnNh–±ó/Úî¤|®æaÄÔõ(µëŸmKÅ1rG¥é™m0Û£û°;#ˆœÂày3=i¤[ ³¤­G[¡mPÐð";¦‚†ž“õ[§)(j€»FÞ‘gT_Æç¥µËFޱ ù‘6mSŒÙ@î¿FŒ *X Á›IÌ[$&pÑ8ûOší·øöNλ×'zw¡ØäÉ ñ¢g‰–OKÅ%oâ\Ù,¯]zT`½3B~;˜¦ŠØ€‰‚8Âhƒ"C“>¹Qù¼}ú:I]u+b(W§-/ãÙCEtâ6{áåŸO¿Äpgân¿•¡ª¥9w§V&­š¾ßOtôúªWßE{3.__ ÉÄ”¨ÅÜëFõ¥3h$ìyÓÑN¨Æ'„§=DêSG]aõÕ`XÃírbßeð74»jŒY_Œø´ÚNÉÄÆSsàˆ.<ùS:¯¬ ÃÐ…n„ˆf÷W— €p2ˆ¾“¿ÚÓ¦ŸÐZ>9#%õi™ÇñâÆ:s2Ìî¹шìhû?ͼ閑¶A; 8@[2™ô³Ù¦¬×MˆãðÉž¦i,˟ɲJCá\Ë1ùÕýv êUËø\„~r’æa°M®,Ã|®3,–¨UŠ[td$NsŸ4g!äj½¬÷\A¡ªŽzV ¥ÙóÐÄÂØàú1ŠbgIÌ@I0?nVµ¼Ö!++f n|“àí ì¥Ï`¶žúÆ eþÅîÙFøÚÇ=3B'•awŠùáÛ7òã^~…ÈÇ Œ+¤Ý¥6ð÷Ãæi¾óòÐCi›^¾Ù¹¿ΪÍ?ôÇ-µNLÊÈyÃÝlûfsöG¨hl®Éq¢³Kš²ÿ?´ÛeŒîëS±•PÝsµÁÁÏ¿Ž8êJT÷ñ(£K͆ÒÉ `½$É1Ï6€Ž'-ÚœøãÏ`Y–žiD‚#)Ìfo6ºt‡‘6›·Óܧá"Ûßb!ê‡Ø0ìá¹wˆ°çÑ+0Nh±‰ÅÔXz˵DÐÌ¢‰å£5Ý3©cçrñ|ÎÌXñå\õ¯î}]GŸ…§. ”2Y»± áŸ-ÞFLÄl‹ Ì™G`A‚ˆQ¥0P¢›NƒChËÑCz–døÄ„t¬{¹höýº„¶™ýqÇzÕm$HaÛ‘-$Bøê ó«ãÓå]`I™$k(ì£ñ÷ =?qôüâSB´¬B÷öûl½xD™ü÷Æyó××G3ì£I·;“‰7M"ÅÂÕJD«`æØöjmVµÔ–eºÑ LƒGË>zºKâY*áTZ©¤§)n#ïµ÷q¬²W€SylY_w3›Ñj|(ämm´»>«ôXÔµp‡ª–¦°¾fv'¢³um]7ä+€©}ʹAÜIyJ¬¿¤òA¯Óg;JÃ8b‰Öî+íN̼zIèPöµ\µÛ³0ãÜV½’5–í~£d¥bƒ]÷l‡ÏÙ\Ó¦ås9îš  êº tWFc|Vî%'¤£µ·ìmѮ颮45èž·u¯%}åüïö6•ôÛêöÄ_”Ïî°Ý*qд‚$ž~¡áƒ·nÌøûæ”S8ä«Ò¢µ)ë¹àÖÌÀéì€ÅT_”Eú¡#ËXG^”Õ¼Ó9*`ð°ÊQòÆŽËÉg9«Îêc1c¶q/²ˆ<Ñõ Wxoš8îî±9çžÙLgy[¡ƒfÎnÐìïÃãs­¶e;'iûc·¤^=c‚+^k¨*‰ß‹²Ü,[¥ÃÝÁlÎE’²ŽsPmW‰\Iñ£¬â±YÓ‹šq8±쥈§~¶^²]ji.º¦fº}ßU2D2Ý{Ç`¾Äæ<¹®Å”Ù¯2ø»›Æ±‰zRaÈÇ.“ÿ[žçÖ Æ!d0xóÛ‰:…Œ©Ç{ïm‚ô/Æ5ÂUã·wNÅÃûAŸÊk]§ Ú›¶ã½u£Š¾Ðú .Ä/QçxŠÓÒ<ÏÇ½ã¼æ˜±°S²V $•'íN(å‹]‡Ìzt󥓭›y&œˆ’1ràÍDvJ£.Ÿ¼E–ŽŸz‰— /nã¡ÛäÈê+<[´˜À‡—ç¿¿|ÿ\±ÏBßmu_%|ù4±1Ãø{ï ¤üë aõôüøŸ\E6 Âb˜˜â;|ìÆG¬¨¼vïy·äΡ&”êƒÒ>˜²1Ãg,-;Ó‰»åÆ„ öÄíßFZKÌÌ8œ,vh˾ãpÓê‰ÕBòîãùÝzsPb:®fK‹n_Ò'ÛÉÝÏÆŽŽ÷›â8‡™ñöh¢{Þ%Ìͯsã³Ö1ëÆ7Û9;‚n¹vÎW4&#ÑÚ³ŠÐ”SuMIcó¶«¶9ORéÓfu`ðü#Îî™`Á}.+ ‰¬gJõÅ[ÁÒÅ\¡­½ÉØŠ,H’ˆï·†r°t㤇—Öâ'z]<±—Iyìä÷â ÀBÃYçQ‹§óB„’Ûz·ß5ŠÜ •pï”ÔÓê¢Û Â.;vÉ’E~?z¹)pÆp8>é¾f:¬Ô¬w™Þ EE¥·Ã\Ô]øœëðƒ],šœ;J1pÃ÷²š÷QøVê»:áÑ1XDܶúçrðçŵÍv‡ÊVá‘]Æ÷–löx¬ÔÉçš{âK]Ùðgäæì½Öº=|G]?'¦|Ó;mîþ\Åû{>E)ÙÎIBx.˜|ê.[ëfcÛÕ÷¼DpøÞ/Ò=G\ÑÆxë=‹HÅñÍÕñQk¬ïœÆù¾mï˜Ã@øžÛ¾Ý±–|ï"®cw ´t$¢u™!>œ@¶ý­ì0*wÔÞá¶Ñþi´kCØs¸—ߘU­!óáï!ò‹Ìk^Üxϱz3»T;ô¸Áñ¹ÍFE&ó®#±\úFR -ÜcÞ#SÈÑ\k˜—W¸çþ(Ѥæøâv°nŸ ôøþN#Oœ`jÃ]д Ó—%oŠå^ë”±{ZÅtÖáÀÚåÿ–h œq¦è¶¶Š±A÷Y¿\a~Z‚tB ~6ù¥¹;*RÑlªjS®Ïj( T-#€úcR«E˜ú¹X½×صù÷åêÿ_?‡ïã8ßK°õuV§áÊå¯ÈŸOl?…âWéœå˜—¼õAëúâ³³•‹’Üè#ýê¥UŽßr8PÈ”õØŽzó#ÕpÆ{*Ì8ÌÎò; ‚Ñcœ÷Ämr.uk!è”%C»×.dU,so™˜c”Øÿ7èߟö;>ð¸l ‚°€ÅNlŸ‘i~½Ïæï¯R;áÂ]©®_:ü”oN§'èÛœË#•U©UáÚÉ»“…1,!9œ‡¦'$Óü#ò–vhöØò¶˜w ŒÍÆpoñ˜öi¹†!DDÆàþ}î£á]‚gR‰Ö¥ThìzªP%k´UNÇ¢‡‹Ý¿[£m…ýÝФ¤ÁQA,zYQ6«ÛQt!Áì`µÜ‚f³(û3—6.T¦ž1AÒ o8¤öße·ô”êÃ#nç&¿nμ7ÕLêü]J‡³@Ðëø”ò<‹ë옢ì3 5*£~Óú|}·õ×㞺«é,n§øxíÆ«˜;}#Ëï+èv2üdµßÓÄ ÇÇkœÙ¸Æ9d4çz5FbïYã»dXãaëA¾‚ŸŽTa‹Âüm_D‹GhíÉÅœA_mUhHvψ‰ˆI/x!kíùS¨·Ñ„T.ó\}ºÅäJM¾«¢‘å)¢ºy „lUÜíMBf Ìh4ï, ™´É›/.(.„ÍU5Š‚,…‚,òØÙéŒÅ‹º>él(Ë7†«yéüpŽšôÖE¯ÙÏ™uTbèXþÎñÊ<0®ňœÅX$GÃê©2ƒþòÙÁæ)s‘>n_”/Lv–Œú³GAꃜ7†‚Ñ(Ò}Í9:24ãÎY‡HZm¤ó~1Ù.–R iºu“¶šQ7§+XÊò¢E{\¯î7Æ´Û\¹ô¹¦G|(MƉFÒÂëòE̸mŠüi†¿ÞÖi&;b³¯ycFŒæ'¸ÕE”ÂOî´ƒo¢¡ŽäÅ–UÌ£u»¡AÂ:*±,õBYÂ,8îo— i„ (£¦°Äé;åÍ—V¥´™šį^¡”Ÿ·IºW¤øF`ÿ¹AÅ(ê7’öìè"|@ÃJn‡ÎWçÖE1ÓÑá°a43óÇÄåIÓsPàì!ÍAoá²F-'®±õa®ˆ}tWÖb‡³ãúÂÚçL¥©ÈUÑbåkG{Ó,ÓÝDy+}Š<äZ’þ ÙF(ºRˆÍ¡›K´Üd6,ã¼v/ý”öe¾¨Ál‚ÓN];sÛBš]›çÃ'?¦ ìtІû„v0LÌÌc„Ú>]œ´‹Ÿ¦’Ae¥ ÕÆ¥jÀgb¤_ß“ìàòœåG·Ïifcß‹é±ßÇŒ# áá+yîîIÙn0ž>X£¿Z;Liæ$o.yìo¼}íýù1àM»7 þDÔ†¢¨Žèå~úÕÖ°ý“r¸ýõû¥™ðþ‡g&û“Hš0y¢ õ$6˜`Ã_•ß4í¿g%r«ý¿Ñ]õWÜÂíŒi»¶TDÎ3‘¼Âd4¢ ^ú7ámT»U8Û_QA&q0„ÜG0PÍ×K 0n…R­ …Ô~~c­½QëÂ\4ÐÔ[ÞÄÒÝ—¯ÑtíÆ¿|3T?ÉÉ©?«·ÂØ}~À|ÞÞ3¬¼:sŽ£²Å¦èÃAð&ÊlYóõóóÆ£öNdýJ½9ú±½ Õç*ò(ÃÌ!ݾ_ƒ‡åíkkü¸çšûiR‚¬ç¼£àãpMf¿oºA Æ"Ý4„ÙÙ·ŒààÑõ|y̓øw¯Vöø{­êgÃû™ŠËä[Q“4êzcL•’”y$_+ã ï1(m7AL —¹®†¶MÑö»;4My˜Á²ArŽR87é2Â2PFµ qó`ØF4¼Ä‡s „_Ò¥.|ŸÞñ‹H¥c¦JPÉÌáñf­ä4‹W_vóøñŽÓÏꣅ££ˆäŸ‹ÃxRŒ žšLÆP‡b‚Fè†ÆÍØl a—0:'vË 3 Aîùø}ÿ‡V`Ôí×ß¡«%dœÆL3UƒÙ+Ñ5¶ñÊ“s‘{¢–5¾*%±®9BZIªœ’œ;é˜V¾l½bmBЙ‰L ¦Ï¡1Šâ˜bŸº³dïMj°ŸFÛ—³®¡J’fH-åANù¡áªõÞëþ`œgÓú¿žXçêç{}ÀtŸÃº×ï‹Ò2¡ñO¼Õªˆ½s„–×”8ã|b5+ìÆ `§±ÍVÌáJ­æ÷ë­FgõáÔ.èn=L´Ûóæü× °uYf$uû5= bÿ)´†Kß9í™gu›¡ï[jA^52ÓÛ2àþÄéƒ*¨í?IøírUÕªw“n[è%3Ž=µÊUg^í (g@ÓÝÍM¥Å”qè$¾¼ùåÚûƒ ªøVXËD¨xkt4§N!*—Î;?üsžøk!ç??y!Z¥fzÂñZsdZa:Š®ÐsWéþyÇ×Í{òr0§Ôèá¶íúó–Û>oZ xú§Î[¶µÃk:€GŽö¥×£_;ð±ÔàÍ89ûÔS¯“@*”vÊh¯J¼,›^»AøÓgu¦ÑÛÙÊ,.ϲ™ˆ,[Öukîgë[óêŒÖÛglwg/Ê$tJ£œ3†~ú#!¶™tJ]TÛkþYaÏ™¿]ìùtûa&rÕ 7ô¡©OÁñºgøN»·36[^=”¿[Ýge‘6¹®9«ý–j²ª}Cìéé÷ÅŽ]6o÷ý††3Óÿ l©¸6z¤Gs°E7\lGeµv*i. C)jع5½^ôäd/9±ãÓJ9³P° Ém¶›òr[\s„¥w[.áœ6‰¡ÉÆž²6jìÍtm ñ=¢(ª‰‡ë5us3aúfÒÒúÚn뉘å‚úHAEã÷™‡C»Ñ_Ùr{a=œ³1êÞ¾ã„!–8TSﺄˆ$#‹ “†Þš-ä@õÝ?—Ąߖ¿Ë÷u»w‡W ®ìé2$ò_BdÈÙ}ŽE[ŽlQb”Ô}a 0éʈ΅dÓÆ¶ÙßïaöÝçSòù›ãÖÍ‹ÃîƒbnJt&C»B(9‰`Mˇð[¹Éís—8p3 ‹Ö˜   Ø‚f2ÍÆ2µùçM¹¿/“çQPÈC_9î”êw<×q¬1áj[«Ë}\.»œ®ÛÊëc:7aÍ"8¾õaÅÂ0€8›—À±!%$w¦‚ð\\XoyQ Útg f•Y³qÅÁ¨r]8þ ô†>E+a‰·fÓ篔¦ú~î\xk9R›æ'n ²¡VÃ{&—B¨¨’!&ü6×9)ÖÄ( G»·m¶NttêŽ[!ÿçS[þù©ª} Ü3ú2ªŽ%3hŸuLm¡NpÓè9J‹(VS hô7[6@„$„‘›òÇ(Ë;ý©A“[y†‘àeÊZì“úi¨é¿MvM7û¬”OãG÷aFñêó¬®ÈH…D>–ÙŽ¡ iò/¡÷áe«I”6ˆáÏ€ö€Uú<,o&¥d-f:Å×±ºg¸¼ÖÀsÜÚ/®ç•ÿW¨ø}2ÓþéS“'þ™ÿ|÷7g^뺽G€×-4ü tvM÷o²RÝÓÎt!2ž¿þ›Ðõ ßÀf×ÖÇ€&lÔb; Dœ16< ýÐë‘ @Îó×ÃŽQô¡˜b·v=IšÄÐCkÈÅk—2‚6Zü}×{Oµ±ò=-,Ù¯JÑaðk»ø&/ý1`Än¡ÒœžÓšVˆ•4KY ËAI1ûjnÉÌzŽV5“Jü÷OwN®E³IÇÈÈ!ä/‘ß<çdøú=¸#£i§Ïóÿýà |žŒyë‡ –ç?§¦ Xž’ôqÀòq¼Æb?ÏЮ{ Ïv Ä¥Æyÿñ£O|dnC¸Kº€pE)nž¶±‰BN+Öy!ç×Ô—õaº¦{* «þXþ}~¯}µÿ´‡üº?Y…‹ä|=þ„±øuD<ƒù·õ§Ëéû¿¯çÕÍòóÿ?qíÛõ·>ª>5}Õ‡6åm[ª$t_=ŸUcÃOð—þVŽcžïŸ3lì²âåW?bQÝýºÿOiˆJ®Ìt\¦ÕcÃ2}ÖË^^_̵iîæïßû[&\ö­zxã£"éî+J¹óoíÇšUµU qAx>•D .ä)v©Éy|—¡äSRj˜Fèµ IIû‘™£Eù›+³ÏôTJ=ªxk¿ÎŽ£a?å¥ÿ^Ïü»¥+Åã×Ù»ºŠÿ¯e_Ý4B½ÐïÒÛxþœÔªú?oë…ÿ^yß ì¿gMæÏNÞŠõ&©˜ó¡‹¢?ÏÕEyÔ9¤ÛÛãJûh£¯Ã»zèÒgÃtÍŒO„ã½ÃN®°„àQN󛢈Æ÷±l«E˜cä©­¢5a§Í†â|tÙÑaßzùÿÉdmþú.?Æ×‡ÑAý6N%›)¨óCßÌ~ÉÂ- A6 U§ºC¶Ÿñï|Ù‘³‚”~VиËÑ®É->´ùstK«väÞ¶/‹|'„®•ÃÓȯHI²¨q«öóháäÓ×¾º±~«~¿e´ã—«—„aµªùQÛÆ0g‡“†>®×—Où“ñsî÷iAïÐCé,:û’Q¢ôÀgþ&MiG³Ú*‡¶ƒ¨Z*¬§ûâBÅ_"Ì`5=Ç©)ƒîÚä_¼ï, t*Ú^ 83׸½Ør”é; À«Eã_Ä•ül?­&œ—§†óý…Š@“ó¦Ñ¥7¿/иÿüú=l½³åËŽßåïÚûéñv‘ãüÕM \×ðr˜‘ÜßÇ€@Ášþ–]ÓuGÎs[ýfÙQ çJ-Е‹ÿYï<{Žl_¶ÌFkô0fj?§ÑÎsëýÝTn ûM,3kfÖìÌìbÂâ2r漣l£ÖæÐm¤‚݆£S-l‚…rÃcÔzÅDQÇ¡óÜ0,D¤j™KWÌpXª¾¡Ôwi Zˆ Áh΄à.íØÆ)b‰s¬æ(¢)8}DbšBË)¾Èå¼öþ'Ø_&Î\É¢I9(ƒMÝ†Õø¾ólòŽ5».Æ1ÌÅC Š il`1 8Z;ÒÔ‚f¯IŠk\u(hNãæi÷׃;Ë”‚(aÊib?Täú0tÄ7Ã,îX’H;øšN“<£Ô@ýæ«7  ’mwb/d$Ô·Ö9Ýú׺Î]ŒºþfNZÑ2Ïßg·þ D¨%WÕ¦3!ÝõQ@ˆþÞï¹¹¦pj–ÕåÉ÷­!Ÿ|`Iá0v4V"%¨ô¢ A)‘äf409²Xu}oô÷Ïìõi¿Ü]ûÿ“ûÿèÿ7ìù:.ye£ÆÚ€U'Ñb0Aó&ÆáÜ—ÚÿÇÃàY3è„ ;¤ãƒ‚KÔMwX¿«óú|wÆÚù»ÔÖ&n\7`nÃ$2C%‡ð`.b 3µ:‹@Y Öƒº€¦j,–´Ý&!1`XCm ì°îöà ‚BPm6MŠk•hmŒªZ?=lX.Ð ïè¿ ;©ü+©œ!º^X¼<$Í;)/ ^0EÚøAT^–•ãDr „àO7*nÿ–#4«ûµj½whkb0Ðf@)¹ cQDY³ÚD6çÐzèÁ9‡—’†*Õžš¢•zò=“‘û™=”ÅR¡J ¤"?Eç¼rêžMëb&´`¦˜^r¢é$à‡ˆXas‹¼ß¹SÅHU¤S³NšÊ¾îñ^PÜìN<ù™†×’ÀÌ'gìîu³×Ï1¸þ¥Ñµhçç-³šê÷föŽ%W-]ºÊQÞƒÙö°/uà³7…d©`™!ü5çs­ïò’Ë;ÛSÚ”ÙÆqCi ãCz!8’‰‘<Ê"S÷=”ý&ójÏw#ž<‘ššžä²âVÃAÖ˜lêÒ—ºc A €äào3)N8&X\3wôf‚â=§­<¼#œÿ€XßÍÆI÷7ƈ^ìyrX$ÿ]—lJ\G$™“rp¯!ô¦×7O^ÍM¨s²ßA‚p.pü|À&]ƒðéùÑÃÏsZ$.k_U²›C¸^’ÁÎnpMeÛ]4Z,çe±h´CóDc–ª'CP&v>ŠêªE!{«ª B>z¾‚"ýÏx]dÈá…Àá—Ï$pÂŒnˆ¤ÆÖMÍÀM$̉#ßËßðÀc¢›lͦǽ8;1”Ó]E’‘êÆõ0!‚ÚyÐtCâè‹Z6ñÎ8nj»Àj=YÛÛ˜–dÎã{j}=é,iâOÙû8øïÎ{I®y¬»Ä­€ým­€`/€_Åâ¼vÓž ¦%íÏXו:ò4 Ä …° p†Íä£ ÿÛëwwðîpHd›¨ððþ“ðýC¸uxYpMT¾ï<&QC?În3¦ä™¾[ë.þZ'þ1q›ÍïOë®û<7à#ñ|î_p$¯ê¸ðÖ¡!=¤ÅUK~ÉÎO['_mKþú ,å/ª0L+@Bõ~³ßž ÷rÿ«ÂMYk"áòêêv ²b¿‹¯ôÐéëèÐ÷5úfnVß§}Q^Ÿìb¸7jmŽù7û0<ætÜ?ï;:ï#áÿ~І—Ê‘‹ Ú5Nëøm·d!VT åžš”ÄÂIÞDHׯÆÙáìGÇPS¢eS/Êíä“¿ç¯rѸ4NW¡þÆ&oÍôÏÛéözøù¯ný¼íÂ.ÉK[a·®¹}Ó•’×dVSÃÍÆø} ¸ÈßM„,…ðÏ*ç9¼y—û!>7m“VJùOSÿÍ–Cæ¬Ï\´!Çm‘Ø $Ö%8”Ñ?*$†¯l‚5M¦ag<·_êþxã:ð¯šÓa«]k^c€K×ìî÷q,‘ÿ°¯¢ší«·26H´¨º¼tá¶ö­mZn†µ£Zö_8f£‰J\”Ò‘‡Ý7ÅOžùÎÃ=~9ok+Ó.’)D´|aõÕCµ9¸íG6êZ¡OMÇÀ€~'¢§;%Ad`Hìåx[Ýqóϕ쩶o_?µZ˜âï¿»Í癀ïÆ0ºF[&-eí U,©¾@•ÃÇ-ƃô&ú¸ôKçyÑt§iÒ®òá†ÙCøp¦ýkþ†°2LÜÎP!?!ÃЩ:™0„«ïU°zó¢Í¸¸ýØUO¶â²ï)?”Œïžd‡½;-©wñóIÉœt5îaV²êŒKÀƒóh :””â›3 㢌ºúck³­Y¿ß¢ÒYæÊZF’Ƨ¹Î§(­±kšË«€{39S|Ä'2ÂXžÒc×5f‚fj»-ˆò½ÏQ;H$+ÊõÎÚ Xiòú|y*œüßwæü?Æ?£×òl¼7ßûOÀö¿ÚÐzÙgÝ%c5K1âÿ/ŠÑÃû @ÜÇ¥ »;¤Hý9t÷ª`¹è(üŠÎsªÓìÄ“PÐ.n0ú9+ÈÑ£J:(D†"D ·MC¤ÖF?c¯÷š—¯ø×Œp I€Û0œL5øÏ£ö4UžBÜßË–—æ &ÐaðÉ›Nð>wf/ß$˜ÛJ5˜A+ÎÓýMI¯WNéŽù·÷N´Ä ¦ì‡ô^c‰&2Ó8#Á —ÓûElÏñ ¼e (¹OéNÍx¢•¥'§)å~V‘› QIümu8RDÏCæÈ€Ô…«®±ü>'ìñ*:++7þzoüØ&#> }h„_nÄ·kç} È­î™ù·Â‰Ñlvˆ¤sµ´e“~|òá…xG;¥ô.ûâ=êèÒoË'ó¦§ð¬¬Òú‡ˆÏþPýüu¼wK’ð¿ÁïüpÜz›Ml~£­ž8¿ §ÎÏx‚>¼39ØfïAÜ‚¬ß•xµX6:ˆïî{ŽÏYŸ>œC`ŸyÏǪwÅKÓÏ\™”â±÷@ñ›\†§7?G0 œNñ#õIÑ@󠌡aÚ—î4þL¾Öuëèãt/Ö ¯õqWÌ¿?Ë9šç¾a k¶ÀÐ@à ½Ñò÷~»Ÿt?#íz¹ÞÄIé]CÚÀRJhMâ™ðsüCêh€É¡º 4[ãonðᆔvÏŒcBŒhðaòYÆçGD†H~&JÜ×UÏ“=j·ºÁdÒl4mÓZ”«BM~ÃßVR%6ÊF)†H‹Œ™Øo pêèW ¤ÔÓ2Â.Qß¿t ¾¢ZCÙ'‰*8š·ÃQÝ´ œæX’*CÕGº¢¥ä–ëÑzoÓ·qgô¶mãàxœ±¾•ˆŠý76UK꿬‰ÈŽûþ/8-·Ðö]‚G˜+÷D˜?76ŠÞœ-ã‹ì°¥=…CFOS²zMCoC¿¸úSbæ·£g3ˆºý}ÕÊPŠÊ‚–4)]+G8Aàøï߯]Æ]\K¬Â X˜ik…7"-–q™ðCƒŠ‡oSrM[lC—¿…¬åTÍËö±À½A™ÐݸåýnÖ¬^ˆ˜ Û:«¾®¬©…fS±V3öKN…ö6—¸ƒfñV ©+è°eiËÿ&з€Ù¨©é'ª=gÀ£·ÈE¡Æ¥bØ„ÖÈ5&=:CïÎ3g¶ß¤ÈñºHí&§êÙè­ÇFb“NÈçCrDSHLb5ÅáMÀz |P“;|3²Œöl5`\œç:;®À1Ý€Ó[y4HÒ9(  ŽzZêà8;_VqÿL‰.0rs”þÊ£O¯vºÀI<=Ò„|d™ÛÍØ1º-®É–)´5Ä»«U6õ4ˆf3wA !—4G<ºùõ&7 +j¢4˜¡4"Ñô¹FqàCv7{(†¶ŒWôñÏãùžäéôxÛDÏãg÷b/”!àíÃCßïØÿ2ŸÆ;ŒLùWìÒ­¸úlô•&º¼TÞúþòõÞ­ùÿé_ù|£4Þýõ §»D°]Öˆi@„ÊQƒ ü>¯ç?cpõ5Ì^“:B&׫OÉýôµ,R ¾/&•‚Àˆ…õï—·Ä»—u䆽Yégxã2P4:¨Ä´Löh:¥å"¨6YHðB~ø7¥†Hn33 …sÜú‰˜Ç©û¦ŸÏµšÿ×vš/jÜŸÝÈd˜7¦´w؈§ó•—ø”’¿“#¾–”v¶ü…ÊšœbŽ59\+¶¦ /‚bÔÆ¿žîM⇧•ì}LY” ì¾nì2H^ iXd)Ä:7¦=æÙ¯©pÐÏݰ@ÈCQE2É‚M¯K)¿¦Ž®‹&â†*vW³vï„X±Ÿ¬¬÷×ÒÝ7´Á½êŒma^C¢¼`ì3°¦Îpö±¿òþwîò/0™#ø ï^3Œ£[ÿ” ?‰üˆ¯£îþÔ¡¦$,.»ª ÿÂ|çÙä»Ñú÷Û¯¡ë?wŸ\1¯ô|%EÕC ŽŸøµ‡ã¾˜ÏùÉÿ<Éö7GG.˜Æ=Ÿônž­µUóê×ìËÙ¸îyö.[ô°Ž©q‡˜äCµz{ëc(ˇ»´ø¤¼?n|ZÏ£ÆÏËf³fü£ÏìEÏe9Ó”_ÛV©"¢ÎVB,•¾ÂD{¹2ä_l€Ä°`CÉPïRÌ'ft!—È+´®[˜üXÎØ”# ÎÞ ¨.(²ï?+Ãk;æšÍ í¸4UŠeœ¥DEKO^ë†\¸}“®·4pÙæùÓ«d¾»zr¹ù½|râå¶pãÍÏvߣ,ï>]œ²å‘˜z_/‡®q¦’†¸n¢ Â8#€úÞˆ³ÇÛµüº÷tÝBñ­AÍS9¿–:ôUD5ÛôÒ×{V£Úúì{_ÑÀö· ¥–!ÚjAà©#ïc·AG^uÜ‹ªùXfAÍI/Ýt›9O麃Ѻ¦ºX×$kS¿çñ”×¹Ê ;%ø;ÁÔdÍ|¾?i/”æ,f– f°£îƒ(]ó>!£Õ÷ñïèg¾Xbž…¦Éú}g«ÑÍ^Ðm·B­z¶xPÌeg9Îs›f3Œ `cæ12@È@Ó7ú¶Í¶m°Øl6 Óm¡²Ùl™2hF$Ñ“&H²dÉ“%4dq›&L™3›Î´ì6sœç7œ¦ZÎsœã:ÖŸZÞµ­F†ƒ;$·Ö î‡JÆ.®ó­d -kUœæÙŒàc`ÐÆY²@Ôi™´0ìhm6Ólm†Ca°É í¶ÒÓ¶ÛlÙ³eÛ3hÑ¢I5½ìÙ²†m›6lÙFkCÀ64kWj6& kZÖ/Z@ÛÖsœçH6™µ­ïZÖ³“6±¸QÓEãíîÝÃò>Çëú1öý•teÚLÞˆ·uqiU=3ŒÚª¾Q£åñ­½;þÓà¨î¦ÞÍžÝ.¼Â9o|ðÛ8gæð¢ê¿¿tØáÇïå‡7n´û®r¥VZº qб«%Ê»-¿àýöíŒþ‚{aöÙ£.s¯¨…CE2AóÓÁ~?-Û<×ÍÛõmúŠvdto§gýÎî6Ÿ³lì™×=ðõwû`­ú4/7WUœ†è(-£/%Š1-áWáÊ*‰å~Çúío!äƒ}bÈÃ_ÙbÎ?®­]S¹äÿ¡Øm³ËàÓ7y¤)^éû~]/¸xÆq²ªê}(݉³zñ9ùùè¶×ã\½¤¢™{þ˜êóð·•xû>ïä\|Žóf;zù¹¹¹iŒcÏÎÛ,åU]7îðãOiÎüüÊé¼8ô3@Ó%‘ÙØaU⡌lãô|9½1ËntÚcŸmØ,>«D}–¯ e«ÏQ›ïª>}hÓïqÎFŒ­£ÐŽUÆ­Äz£§—D9øÙéçòi96ÍŸÉ wêÃÕžz¹ö~§´`‰ÈFÌ}:€Ó´_M\éþ®Vo뻫ÈKm‚ü5{väSF¬7ü¥=÷9|¨ü÷Új9·~ãËáÊxz+¶»Î®G#ÝßTyxêÓªÿFWc‰íÞKÔȨÀó•žÓÚ{J`¨¨ûÊÊÊÊÍ›6[hÀ °0Ø–dW6²b!™%’ÒıŸ‹–·îqñϯLpøž×Z}¢þ}šÏ6Öfz}/oé5e÷k{zpúôùi„£:6µ^~þß¶Ê6¹ÏÍ·ž¥lñ hÙF»´JB„É$„ÛÝÒB@’zrðè)7ácáÅ„7GÈôðžÒé×.€~%m©é÷'ã±è8ûh¯øÑ³.žìþÚ²] (ãݸ¦ W[aL'$SŸ4‘a`+½Ôþ»þVÑó‘ʎߥúŽ_ϲ¾ìæÅ¯û9°ëÓæé̱ỻ§Ÿ`{Îz~z|¼:Ó¨ÑGµàYÝ_Ñ¡2±]b­4#Gð?KåEa*"Ãa’«õ‰À9ÚzqK­Â} –)ߤ ëH}./õbÔyÂÊ ®`Žo`tÆdàñ#c§~¨ 8ùzÜ^EURêæá¹ŒHñJï™ûF„ªZH´! B&½ƒuB–/$žäa^Ú ‰w>…v~\)›#(‚WÜ@xºý›¼ŽÜôu¦!’)’ô‰  ÂHEà Bš×¬=Ð~ÎcV°çÓ·z»›×’³sKð;¢ÌÇÑãæ³Ë/’ÚøwgÑ–iQ×ð‰Àµïœéð[>Lt²b+qÙÓ¡ØEüG¿®o˜¦Í÷ÆW£ë@t²îÃüÉÁ‰»­k†4Ñä]Ò•4iÒ–zhÞ3¢”ùÕÇ`Šb–ôJ©}X`FñØ‚fçL4Pu¡rsvŽ—‘EGrä?Q­ì_OÍBí‚®À »Ât·š_›ÖîDqZH­€ëEþó~m‘Iä€sAãXÒ¢nm05Ç¡q_«A«Pú’‘ṽb™˜€(1”äUò”Ü&}.ûÝãUÔwÎéºô¹Ù^_õçÇd¦O¦h ÜÞƒó'Âs!“×L{4ßÁÚI«Ùª¸·‡gƒÇÝe{i<1·'ØsÆ0†¯’ .º=?h/lo´^2:!³èèz#¯}Uê+o ™™õá*¼;·åó{°V=ÔcÞ~j0ñôýç9×W+G!´2Ò•lâS­~íYuñ=Þ{uy©Ò_—Ïáß³ÑÝM[]!uk^Æzcà‹Ýø&=]ŠTy¬äÊ>έœíÄ̱ýˆ¼úéhQ3W‹Âo=V{VÂÜU ë°%_——]WÑ/U‹c:þÞ\!nOÍäTù^t>ˆ­¸ëÓ =ÿ(+° °èç -4óƼ\ß§žíf ùkÕøÝv[¾½ßaQwÊpWv[¿m$%#j˜ðsËpjN8ŸŒ¤ÚÄ!9©ÙĤæä`þJ:8î€%ZuL Ð+Kã®ÚÊa_}Xã¬Víx(gì5C×wfê°T_Õ•W­<®ô]‰ F£ÑäÔ‰bº–+Ÿ,£ðóIQtømXWõBøYíà zJø_fÛ¥ß|#Íæs#M¶Ó>nÙD 6d7¶G{´¾S¶ËŽ–õ[­°z¯¢*õ¯ÔŸ 1)WÒkÆ4K.Tøš{S—4hœ-ðꉿÛᕊíÍ5ŬME ¸…ÅLëx_äó9R@¨… ªî1}R/“w3ã£ÛåŒ'¢W1 $ù8ßNs^g¶åÕôsV×wúsØ¢ôwwTe«7tþµÈϾ~cà§ÞÊ? µë«vp»”k”Œ²<`°÷O§ßEGNº‡‡Hºþ’[1¼žÍ–ÐH–Fq”CVo$ĽØú«Œšg|_áÆ¢%o*)ÓzÑ–Ì4ܰ¼½_G¦˜QÚÌÙrÜÖAq›xðá½iZtêôšvÃÞîR›ªžèšÂÕov5’‰Æ->˜C®:~üåŠ×aAÔx|'£³“Nª®Oåê…†~ݳ’×A—®¶nÁ݈yk†ucôUl%„V¯e¬$±@e[š“ˆ¸›C(–õC£«›_}lìºùsäfL³¥µFI“ZlUZÈ5¶ }~‚wsÑÓºžý³=Þ ƒu+º¬…3Ýû¡äT¶S•ºR«Óç¢45ËTñžÛU$Eóß*W?W—4%¦º¨BkôÑ5ï÷<Ì ø~gÓì~ñò—œEVì( f?Œa“÷@–.KeuÉûªîÛÂWØJuÙÓÅ ãÍ_§—^[n‡5…šo(ð¿L±;͸ÇcVÇW^¸z¨áe_MYpÁF¬Ž<±íž|Ï:ßRžsÝ.9dr1ÇT,¿Ñ~¼ÜõÁùômyÉΪ= «e®êuÝ>n¸<«c£Ý³°æ7TlÊË­'m¯`†nVôjžÍS×pÔ_ú#[$÷Ñ:e[V·¬Š_;6g¨kðÊî¬L1™UÄM®cî&Z*Ž{Þ©uéÎŒlÏOC:Ä ßTXŠ ]»ÍHŒ 2=Kî:| 7Q€ìÛ*ñM(†ÆMƒƒ¶Ž÷+›Þ£¼ õ<`Ç.n†“&e'¨á@ãÎ}>Ÿ§£¥+io}%{tJEXóq%Þ™­èóÖGª[Û¢O-ÉÙrñèùëéçõS£©Î¸8@L±-ßÿGDí“wùzˆ”üñd#Q:½%°¯Ç|÷ÉQX£cýÝsÕè6ïò;ƒÑÍÒ5÷Ÿ«,^Ÿ /#ÍÉŸ*#_vÓF\¨zÈ}Í'G„é¢äU›<áÓ§È·ÝÜWzz²äíëKQ÷=QŒ ð4‰ú}þ§à”Íj¿_¢Þt){1=¿d»ž‚ïÛÌh6y¬Ñ‹»ç?UšáLZ$iƒƒ9ôŸDZèSKÓ›‘‹»úw:–z5ÕIíƒBÆ; @„?aOu‹×f]Vi‹––†ÿÓá» šë¬¬OÂR¢ÝzÞ‰CMUä;ã6,£ë“$Öû¯#R6T}/¢áp)ÁU„-@*¨(üý=uèS)~ªº~e~—˜ªM~ŸiqäòÞ¾ÎUh(MœˆnÖñÁÎŒ^<où=“§Þ¨¶¢U›*kÒa-Z]ÅHìÉÓ4ÈíZ²{(µói}qñ5tJžbD^«HmN£ #ä\H97 )!A¤}Ý¢„‰uQ”@ ‹†Pá(uZŸnîhª(”{´ÇÅËTŽ"M¼,öøÃ ¼ø!ƒàŽf]CIMö;ˆ€´ºfûõþã4¡EJJ: æPmÈ”N¨R´ÙÔ•¬!ç9Îs´ÙÞµœgpÈ»ÊÅÆ"5˜4JM3ŒhÁœ´¹¢«U«²åã&“¡(¸°i»r »R­6¶ú—†ÆçëzJµ¨}kÖ–œËš4;Ö]ÍhÚmlwÒ4âÞ”6¡ ™$Ø™$–vhtO¨ÂË©$Õ£næ¶>á¯8A´™ö=›|Æå·1¬»ÃèJM ôëFš]Ì)™UF[Zr_{…­>ájtžãxÑs3Q•œæZK¬ç-fõZZEâb $¡A7ƒªŒÎ1ŠaF• ðú´b²±kCÄgSo ê÷4­\AHe1‘âuQ“Žd±—ád´.à˵¢òd»²sJ‡(wæí1¹f²‹sxÿ?ãúØ`ûA †H" E í¦?§Ø$ærÄŒDˆÁ±$¤ ,’M@¢4”• ‰LL°¬TL$R3PA0ÈÀ2HH)ÐP-()DIB¥-@SDª4P"#M#@±,B´‘€úeEI)CS)·øý_.ðáÆA§iéú顪}› M,K0Qüv‘©$«çâ|táå°"4‘t% øQ…gØ’ʬ*];…€bm¡MIÑï±NˆÿD?du@œbB• U¯«ž ^\8ðS°/ØŸ¬(.GJ¤„ŸŸ}|í~;ÎȾ‰ˆOr4âPõ&@¡Ñ‰„A¾W/âkÐw§öðù{ûü’Ã'Ð'é~1>&^Þ,b±™Àºþ»±xPb2ÌÔ¯¬ù‹˜>B‰(¨1 IöiÌÏ¿^Lh‚?íW +Vì\º.°k{ò7yξØê‡K§E`F6è%T™jŽðkD1vMƒ„õŸÅÕÏqqJ¢¡E;vT¥>c]9ÏïþzwÑFóÀJBu¨ )tTUÒá2.¸keP³È8#IHܰR¬ìTI%ÛÀÒ{±G)óO˜»¸–!S´²ƒB !¨Múy?C™$ý 0A£$ˆÑG1_WŠÓºaMŸQ—|^Á‘~v“·d#Eúÿ3 ¤ì_UNt®¶EÅãŒçAfŒïxcC¼¤ð’mQ„¡J’R‹<ãGWÁïW5^ÂóAGÌ ;^•Å$OcŸ…àXÀ„΄_—†E=Cˆü_ò¹ÓiØÈhŠD)Z­la(C'‡3Éá ØÆWûœÏ×.È÷ºßÐüNx?‰ÖÒêd+úhõ•q5®&T3„ûtž4²!ÅàC¦XÍâ외 æ:+Ä1pã¿”À¡‡œ¾¢?dLå[vô|¦·6-ØgC jì¸áqW;t<Ó'f4þšº„,36†¦.¥CÅÄ2fŸIrª„M¢PýAý˜õÍ«¼DeÁŸè¾4?¨ ë·¼gŠObŒ¼â Ä!â¦AB3F[-ïÙêÉ3î¹9(‡m%˜˜µ\ÄI æ †† s”Àí,Üà–ê{S)߯}·8ÞUfjdxSBœkŒkk¢‹ŽçP;å’¶4GÔ>Òøwã­@>Îã€B6Ð9ëÉzE¦\.M'Ð7ÌÏ´ûݘŒì¹ðéò"H²$Qy©Š"–á8—Ãz]ù{Ó#ŽW¹ß;Tè£ K§ÉC·#°èkC¶‡…`#¦ôPc‰xÆ&VŽnFà‡’¶4L¸™©ó‰ðe,ô1£ i™ÚuÜKÀ]UÓkj 4¨Ê‡ƒêèÖ&´§hýcª?£w-,X±@€Ô‰gKZR4xù‡,÷„rhÝúó‡z|ÏGÎ¥¨AnÖÉ»*D©Þš* tÍ‹—{‹âE£[>'Ý÷Ôi(1°ÐE¾ã·¡ŠÐ…Ϙ“;HC´Baz™ûŸS^œYöòÞ9eW„vêuæû« ÓáDXŠ~’E„Óqœ5ïÊ%AÁ¬´ˆ*~0& ’‘•Ä8”Ž2>¿ç†á±Â¹‡îI$A¤$ܳB"”ã'é°úeD¨¥Ž¦ prµ} u•»áç±þÜ1tðîŠÒFØOþ!þB©²àŠjímF-é‹v#RÜy<½¡L|³â·ËÙu4Y™‚ÕC ìÙtY¸h ¡àA±i£ý<àTIýÍ.Ìu]ÈœóS&¥¨Äçç› ŸÏ³÷9W[ÉPôŠQí>1i5%³Ž{|båØÃ0ß·¢í/\?^ñw×&Ÿ91¼i°ÒF"ˆóQw[íoTõžÎ^Z¼ZçÏÊ™ÛUî͠Ƙ;èN€‡vK²>ã¿¥N¦=ÿ“b›[nˆƒ¾¿9 AÙâXÝ$^§øsúh&!H¬®™.ïL ÁÙióˆëÙùD£ÒÞÙäÿ9 %˜tqfâ}*8]!ª]mî6?ÇÁ1çrj}d"…:žÊ¡ãZ¬¿cC 4VS,ƒâäC9QíqºZ^]D6•p®™aAi4_Èë‚¡ì¶ ú‘pÂ\ˆø³à²23”Ô—Ä·$÷=‹Í[ 0“.äsèþè㜠Ë;*¤Ö©ÄP× âú R»î7èzJÛ¬iDÙåUbùqÁßá;DÖI§µ ¡Ê,“uXi|§>§”¸ù·© Oµ“Ðñ®JYïØÏUK¢LåDwçäBj`ƒ‡ÁÍæÀÎTJp âäœgbŠ>÷n)÷{ÏE1_ŽqeºJma™¯†Åo#¸‰ø¢âÜ ì#»²}oƒ :gÕ}.w¡à6ÉŒšv`û«E| /ä,üt螺>¥rß_ÙDwáŽÃÌák#íA‡Ûxλ[üL?ÆtÃ!8;0Ö}‰›aÍìgDœŠ¢X’yår •ˆ ôÔ@î7¥±òö:Šã¨ö“d´?޳"eRé-Fˆ‘µQ^ŠBkÌéÖ xôóóo~Ð磤ÁcÛœ¹ !ü»®ö=¸ƒ^†÷2v/€‚'ÑL…žÆŽ¨¦Œ1•2Éò‚®¤Šìar¨ôˆ üp™43Ž1™öÉÉ]±P>Y Ðzd<xƈŽ%ïìz–˜Œwx[eÛàø;…e;p²É1HÜ]ä …¦Èᣃ¼ðXS†5¿„m¶lüŠõÒë í\=®g# p„ ‹\aå]T8M+“Â…ÍE:ÁXu=¼G‚”׈ G»Ÿí×ôfã}u%$ –·6ÅÀ¡XcMú Kò¯ç‘ÈCŽ>"cnŸu_AFÏ,aóaN$J“i(\©>0„£àC÷óí‹ý_áÿLiop¢~fH=¾þþ~Ì&p4äµ÷3BK÷Æ3÷ôHa~hr ð~D0áJÇ94û—m8Hˆ§!çóú约CA¾Kú]¯”ÆPÜpÌË%íùžâDÝ û/z~Ëh+¨Hn†S´&²ç ¨À!Ë:É“T6wJ2(%J(ª(³s‰Ì£ÌPœg¡Ï6n3t(Š€wge奣¢“Â~zÅ„˜ÖƒY`×»ÃÊDb eu< ueÓúàÍöæL,Áè¶‚Ý@ý NeH„ù¨‚wô¤ï7~)tVǯǮ/·í$…Ó¿CövUV;«tîä9˃4(:‹(æàÁ¸Ô¸ ˆîˆ¡DƒÞVDD$Âç+CFÆÈƒkiQbòÕfÜ\ÿ_]jôJ‡’Œ˜ î4`È… (EÀÎ`MH›s©/š¸¼¹Mà&8ÿm&Ãæn~‡­¨¼„'M†c†bƉvD ¥È‚í8_ÌÅ “8!0[’Ñ$I›Ä‹“M$Ñ ^!;Ìca‹"儚ÍO…:q…ä„óß qá1$|b»[߉¹G¨ÌÆû^ˆ`©öYPµQtºõ,Þó)î 4xî J‹p©¬Œ ®…MɺOqÖÒ‚±&IŠn,6`CLgPè¨G¤“éˆfx€'r@™ÿ¬ç !_ЯðÞdÈ`Ïelâlj Ùªoy 9ðÙ¦¢üçã-¯|7Û~M~è ü؈Öâdˆ»‚r²1×ËÛÌòӣĬ”PŠÕ¢ú“ýÄp®õEéô]ñÈæ`¹/V¼4K²úñ ]Ãr9.Nó¤ãRΠÀä²B=d±c.ÿ6b^ΜzôšÆÅ…$–•#£àóžeiŒ]Wf·‰Ù 2¢õó¬1Do–½©€¬K)2V™ìŒ EfL¸Y)ê)ÇéàÊfÎ^““‰žq"³¾ÚŒœ²z)“…FÒÍ$„Rí¥:grþ_;²¹^ß,ŽÄ+·F/ ïƒ$"މʑJ%:åŠhßFÃN®Ç¥ŸÓÐçkÍvýï¦Fª‚¥Rë~UçtgûëÇÙ>ÿŽ]FÕœy°ðÀôBƒ¶óžªâW§”ûº¨«éÀÀ¿vÔóXÌÈ8« ì”!(’ßß;ª Ú— Üìæ‰" b©xz¾»ávxU³¹ó½N9ÃLfh-ÒAUm™^óP[Øò’úV3¡Í#sï‘@R É1°Ë³GD+}:µg¥¥—VØÎÞا~k¬°ì6hykÂoûé‰ÈRPRœMß?Ou8l¯©V¼müc^ß]T6BËЃWcú¶¿‡9­xRà:I€ƒ¸)ÐÌË‹·rÔ"ŠŸzb´['T¹ÙZ{•É¢[·:ŽW¸Üðeš­8i1üœñaç—gw›»aÝ `]B¹k_>·í¨Uº,9ÌÛÛÕdîÅ'º¥t  @ÐQ”´;™:»3rH¥¸BÙÑì@·–JülñÚø`$ÚªÖn¤\ÙõT`äDXš”£òƒ¨:L_­éñëå³ìxvâ}çp1ÑíU H LÍ)1M%#G$ü ¾zG ÓÊ#È ¯;ky “»¸ì“ØmAä:I³ÏŽŽíöT©1a6ï¥wvh}±8IÚ+ÛÑǪƒg®5v¢µõZâÆÈ76×âÞ—TåWŸš;§F:Äõâ!þÇjMÇWƒªu—…0¾Åñ¿ºaf]•h¦õ+µÃ¥ê(TY†ú§ ì£êîã*´õ×Wò®c«òýl´k寔äã—Úø[õQÑž£2½îmé»ì[í™^xÏ7ÊŠ¯OžžhmJþ°ÍU³8ÍÞù^]¿L&©¬¾šgŒxì»ëK¢¸FÊ¥9y0ÃJŸÉÝÏQETÍW]'Ds}zªƒçžçßî·Ñm*áew½»é‡Âÿåg sÕ(ÿìÆˆõ•WÃ#¥ä´ßä³WãvÇ”$…¦r¶0ÁÊÖ½6­¸Û)MüŸ[ÂO‚Î1rôž¬¹†f•ް,УÔ!uœ¡Ùkµ<¹c•N üRH›ýñ´Æ=ßÛËʔƸÔ3»Ì¹…ác0+—lªWÀøU¡kŽüj*›Pµ”ùríÚS¾Q¢/ÁWmû'nOs¬ò¾x5aªU]̰¢P/¼µ(h»D´ÞSQ$ÔʸP¼cì[Òôã_·~øÎ¼:!ü¾çСGžL¥Þñ=µ‰æ¨”ó|¹W¦U"ª.|—Žà Ý "ñ%–g<àU®/®Úm-yW[ËË-1ÛÓd(îïZüžñèR£ËÝ*ºê¥í7óaNåV¥'SQ®‡éÐy(*A-•nHó¿˜óNŽŽ¡î„cWªµ¢<¿ßãÍ^ ç[·ûÿ–?R«ß?_­m®Õ§ìONc³‹v×¶?9Æb?”gqÿ hÇeYõU¯wG¦ûLp¾¿NÇ·¬%‰­(çpÀ"MRæO¢q¤¿“;mWá¿ä›ëæd³D’wÇDŸšÎ‹ùΫ{ ÞeŸ¸X•Ôä&4Õ4eÖµ‘é¨W£ëŠ—ý>–~éñ©Ä­sÀSÙþÔN©]}~4PY\.ôÑRª•U•ÙYf+ÑÛ&¾À¯¢èsÙÅ-MÊJ§³_éÊË£ErÙgžϺ§Ð™-y¥CºXxB1%~»å|Šy¸qKç¼þ<⫬¦Š(óßz #2hmó·Eû%®pîé«u¶PðÝ]^‹˜öùgéRôè§JèÑ" LÞ¾ÜóìuÖä0ÎLéw=¸è„ú© ¦J˜ãD`cRÇC|ãN5ÂçÓæ;-ڸܥ]þ¸Aéù2©W—Ç~áhøoâpÀÏ?²qOй;}=»!"µðd„ã–‰0ÍŒÑGìþÆyp²£DVŸ0)ä‘ÔCûþ”]“ÔÖŸ÷Q8”aéÞ5Ý2¼³sÈzœ(B±¶&–û\¯Rm¢ <ô?c gC]À°ñÌÓ\V½‡³ÆÎø"²f Ø»%  ¦PŸ*yWWíÉé!òmEŽ¥Œ…º wé,,b‚†YC ’p.¤ÃTÝEÙ»¹Œ^¥~ÏíñùŠNãGjùŠêUbwô8Ž˜A+ï2£“¼dã¨'£b£<7bgäsû—4«¢&Q…íN§â-K˜§n°ÓF®O®‚¡ÜIÔÐi¿Ù”+§e”#ªü6vÈÝ,Zu#£™©5NÂ>]é·Êï)h ÑÝÍ*ŽËٮÅ7ÎÖݪ ‚ºð6=°ÑŸ”}W×ë³™Ê7& Ö—µTMàuÙ»fe¿§aª£šÎúzJ5å?‡7›»@ÍÏÏI£²ã<æÙ,=OÅ6õ`³ÔEwøÓ,L©þ”ïðÈä?æåÛk{ÙkGÀ5v³¥”µš°††Œg<Ê‘@¨ï)0µåDIè[n¿žÒs²ÛÝ"_˜¡ˆA¼ÝUÃôJ4áãàåýç„oæ…å9óÃJ¥5K¿¹ûv¶Ÿ WöÙ½£Œ0TØCÔÜ%o_©´µõKçV’ªÅGŽ8eóckžº¨£2£\-ýÖß«†—׉/×òÛö¥£áXÙró¹õG »Æ¨²¿¿{ýl~{½ß®¥Ã1שìãL̵°Å]±07Ö厬DÁ32_,k¾ÇboŽãßk;!ZÃ;oö¨fxò=7»¶‚? Ü!Yl-´#Ÿè_’—×#àïOâ<fc•S§®üO>ºê›âõìŒX÷\OŒ\éöÓâÑ¢|Öí;/¢u^ŤdÂLÿøôæ3N†–Pïj°êÓ—ƒk)¦T}-mxۿ֮̽ZáWìó9exPúª«LµÓVÄ*)ªZ(t¨îó3ÛGxÕÏ–ÌÊŒ~P5#~f¨N±ï£SéÙv$ç×+ʨ"+SsÊÂKcBªsÝ2º~Í]Õlthª›g d•Õº'ò–lÌõF¶ÐˆÔ_꨽Š $Ô;ÎæÜÛ“ º¾³ea²ûjË]²ÓIBíÒýYW"m*49,EZi펞5N»ò«oM}ó몓9O^a;´4¢9 6xµÀÙV!_…!F‡Ú¥~˜lÑL ì<ðíj™q™r·‰ š=’Zëƒ}–>ö£ óÕdJ/†wëÃ~WQ³ [žšUú(LObÀlϤzkáÅáïXÝÛ+SÜCLëîóºôã.2yrGujùuHË×Nså½}Úú§±·’»Aj §?.Škå–åa;*®0ª¦%†Ëéz¨(âpí¶2ó<ºîʉAÎzci×–lôÓi«U‡=tGÍ,hÊ1é¯fûŸîZójíî£Âü¢HƒsüÙÚÕ6Ž®»ŒeéºÆ1MßT÷òÚã;a¹9“°ôîëÎFú6eUJÉ@J*Õm4Y©›¯3o wÜvMžÉz×_}vÇá¹>ýZ×ý¹Ž MGÍL-Õñs6Ñ]|ÕjóIÍìAjÐm­Îú4羟V«¡Î=Óm´Ë/¼õ˜“‹D²©î^05´Ì®¦¶ß~Ë©~ÑØ£W1Ñyõd>[0þ_^\Í÷|þÿ·êŒc÷ù=E4ݳ=¥ð5n‡6ÚwD¼9-­ªÙBŸ¸tù±¾I+/¡b½ôE¡uH?/žs˾ˆùûþxÆå~…yì}ªÛ”o¦û"Rh J«zè ÂÆØ¤¥í¡5ÒÆ6S àah9^K:Ñ ù¶JÝc5襾¿nˆW ò^nmÜÚ>PçõÇ^ލ]«8zW»käþÍL&´ÊÝx™{ö[m¿¹f­ù5:j§ßˆõvÁ‡î,P§³fÕm³ê_žÝØçÐäÇQ;Çœù½åΉßùr¸‰ë³òDl;púoõdýK´y̬« ^ e…ÕÄ5P‰Z[®ˆ]$ø”Á¶è™Â/D™|׊©—öøÊb5lõ¦â+QŒ|>Þ§ñ>Xq®iî®ØÝcJúÚå\Ëa;›_}’PéöãMŒÓZo{æ–¸W¤êæ‡×pÞÁ¡ë¡M>˜˜ÊMuÕ&Ú÷ѷc1ì¾9?–þ|>FEy¸ÕE’«ÃƸkm&­VÛp¢0Ãèøh¶ÒæfŠ0+nï8?4ëCÿ+oQP½Mò|)ê-ÿϲ#h}˜*ú?¾PâKËÑI™Š“¦ò·7(i«LNªßáÕß ×9¡í7y‡kVÇ>ôÄðp9{8Õ>>ùç|àÍYé_)GÖ^ýôÕq ÆíyÁýSáý£ãÞÜ›é#A*n7p‹7y°òÚxsuv”§çõ8YÝEt!32uwÕæõû47žÊCDkvn6º% ÌnÌF=+ThÕ1h[åEcÔ»­,V WU<žÁÕœÕ+úòºÛ¼ €"zÈ\Ò—¯íÞh‹PyD;t!”÷ ßе¢}we°‹y³¹“ki!_By*Ú£Zýþý)úä8°Dš#–NV6c^/´“Ðz÷ (e÷¾&zu¹MÄ´åü}™9hRA‚ A`,b i ý\ÜÙZÁCª]"b|”4¼&ŠB&ª’X (t”ãgždA)Ó?æÃöaÀ8tc…6ª-­™ÆiiÏKÒÖ½3e>úèI9ÓDüÒŒÊ×;¢`g Ö±SZ·¬ÄQL9lꙤê1ö¡á“?ªÑèWH39Hi¢tå‹¡¢Xf¨Õ9¥çdÏwB§,~?›çÖ¼Ï ¤c N§Çs_Ãü?3Á#ˆÞDoæ>Æø ï+.ìï*#¨Ê}Œlž êºYô¿&Öw3]«;S03!Ð8ƒ¶„Á¡!˜„¤áÌpþKïÌBØSDHK¼ôw¨¼’OÎ…² 10ÕåÑÒì4#–;—ÙBf’µ :HWFQc˜æëø+Ó.K5—$Pò)y|Òš&>ÑüÐÆSòM ž3ô¹MZþ–hzDÁÝþXòóç`bsÏâwVf)ñÛú½üs®ŒÔÏñN¾¸ÔŒ HRÔ„Ùv7+öÇßš/‡)4Ðàâ$ Õ€˜ð²‘Ú(žvËÇ¢ÿ¦« B›â”þ$8uöæñœnÙ–S Š‚“3N³¾œGy¸} ~ì$ýÏ¿Y;Ü…LDEëÍÛÞÊNm<ÖZü¶„éTÜ©ÅÕ“(¡½TDM+¢tÅ2"RDóã§O "§ÏݤÑ%30»¡DMj˜‚%‰ÂÍD$°zô°¹O- >£D1êh}G×ôïXÓ­} ÈONØˆŽ‰Ôޝš IM¬ mªõwäâ8à‚\RYN¹¹*8dÔz"rEP"ÑÔ&R|33-‰á¹îaAæ-‚¸Uü>¿'«x¸Þ,!8‚ÅÑ.õ÷5#UãElîænÕÞfM ..T)ÏJN!Xˆ±Br l€¯Óc•8í¨Ê Ã%3ÓßÏÌå@ýÒþ\ú¹ûge]¹|¾?¶û6Q¤y¼ÿ°á¡êé³;-¾ÆXdZGãÓuú¨öì½U÷yúnãm¸NäÜ nUÙŠ%ÈŒ” ì¯Q3Ë[4EÚ¹\¡\AB$Â@«g@|6Ýß§{Á=Ú ¸!Æ e1·ëá®Q  µ«QÓq&¢£Ü§e„KxaýcxAäž\(7.ÌG¤8…dЬÁ†wAÇŠ á.N5ʇjJ3*á¿ÍXÕ«Ö9Ýž™é1Ÿ¹0Ê¢ [¿AHD[)˜ò×S_8ec2nœ‚ ºª“k“÷Á I¸tŒœ·÷@¡øgÍgr|SüÖ‰b‰«®­äÃyÞIl·E%V—wRu˜êöúhÔnÛ¦›L-C*œwé¤èxU“§ /dúHöb\5‰´5×Ù]Ì‚”þÆrl’Ø@mCME1@vmþ·9ée¨aÀu Ç™‰G®n ‘,1xl¡é$æÂÄØv@JfÙ#~szÎæ{îp9Z¨–Íþ²ØÐ:ç†Ès“”l’MC½® l#é Í<Ó0â’`âƒÐE&´¶a^’³tnؕ«ÌxoFz|ײìþÏ3®!äžvnmÒåBSRrê¢ð™ ¶Äê=“¾äqnÕ£Xè!©ùþÚ•ŠrÄší*¢t*á1i†PÛjú{=ôÛn2ðèÓ}SŽ2 2f ÁŒ î;=^ÞãsSs…U|l§N©Ãè¯-+}ˆUÙlRõ¸YñU¢ŒÓÒ] `¤š¦Å˜+4|¯½ëL̬B˜”=äj´xHš&~Î÷¿Æ`G´¢1¬ªg{dvÆ[-˜i©+lõõI¢ÑVg+çñ%zuX}uìšPIƒr{X:i(©ÙYGG‹0Ão0”õ›WêÃp{“äu¬,š˜iìXÆZÏW¦aO›à; „ÌÜõ5®5F6u‰~“7Iú;µöCª¤Î-=…ÛË[1µ„uߣ±‰Ý€ž|Þm)CERöD J³¬×äQH:ðêyºà<˜A3@¹võä¿Yþ>6\Ò]^$©òc q3Ïáú5êȯÓZ;ŠŒŠǶ†p@’˜:Ûçõty CkRÖ5_HàûèÕQë`ɈŒFè ¸&n‚ettkRÛFÓkDœcåN2GI[j×Ó],üí+ü¨‡˜+É€æeBmGÕnXê.¼xþ»…†?*>VD õêƒa©˜t“}­ÃnÜÇÓkSÏߢQàvvwŒœéÍš4Ð.#&EŸv¬¼<—WÂöo/Ã#óÝ«£œ¼¼Ûß³Îxk„>Bß›m¶ZÛqFffÓŽu›W>Í<´ >ÉŸvJ™’7s"Â#~¼MÄ ÿWû`ÌÜ?Q81>ÅFˆË›¥¼¿`8Þ¤Á13½:ÓG¹õõ}RbÂ7áÐÑ8u?NÓ0]à9‘K„Ó7@…éñëþÔ&,ëžs‰ÖÚi>ExÀxJ Q!CKM… RC(Wª Š"Zϼ`ß-(›=}æžÙìB=ÀÐ1žÑª ¥‹'¥J£…–~KqôÊ,Oó]aÕ‡7}—ßsôžêuMâVgE‡LÃÞF ÂC³Št&Y¢‰†GÃ¥Ø-°rÒé^cLVµ@áš#MXØNLä!hl&Es³ÒZý\Ljµ÷eœ6õU}ôÃCYD-§lÒ„ÞÛš!·Y"4x-•rð‹ œC(¦µ4N}Ì.aes²@ƒ>’«ˆ@¬­iPŽÃµÀf19Ì¡11%€¾©š£éqÈgh@æ·TsN˜7B NÚ¡§¯žûCu}rÇnuOãÕtöRÕéTvì€ÐúØÝI&ÝW –Œæ“fhãww?KèK±R„Ë %¿…º 5þI–¼Âx> ³@`A“§ªŽV‡"-»kuÛÍkóϘ#B¢« ÊõùÊ~ιB³[[®Ãt3éâ¤Æ¼BbÎ2…;|ý¾Xk ØuÀî-;o\>üâoêG‘çNku´Ù:çKÚ­>›¨wF‰”k¬k“4ì¾­w±6µ­ëìó7às¥4‚gÑô£‚?F/c~þ†f7gi‘µÜãmLjM:óƒü7oèó&áPñð…aÏ㸭¶<ÙÌ=)‡Òuê׃ߣN‚ÆB1LcbèNÆ.Fƒq‹}Ñ3VDÏœ¥Úx çLÙøærîÓf,DÛª$0Ä‹Š35[D‡žû_™Ú×zîj¼bùþì{S¯6:îJ´:Ò”ßÈò¬7ð6ØÓ&`¡¨.±û3&ÍË¢3‘:Óô‡?A­¼Þhôµ“6åS·¢ý_Ÿ<ˆ‰§£Ñ™ÎZRm¨ &60õÁÈ9ƒ» ÈþlW®Ÿ^æ“a²æ¦aFPÁ[#rç·X×à6ò &4×s.å7îL~¦L“xÞa»ÀÂ]}˜³‰mãÐQÉq[ÛÎh>u¢„ä ˆÖ‰4ÕùݰqhɃ‰> ð:7|úÞŽ'^ý'¨Ì€¨€~Oxz>„â`æZKß>5ùt»¶jXÃ"hÈg#_ˆ¿.ɽïU üÎFÐߌ·]¦@‡ÚÀ’g>êÁÇ4× ˆ¬:Ä&I85ž&„²d…BØ`E ´aœÀŒ\Cº@I1ŒcYqïóú˜¿‹ &²ýš>ïÏÃaQþÜQÌh)Sq®’”' jHúx|ᬙV†ÝaT{(hÑŸí Ñýÿú†nxf:Ç!È~¦hfm,F 1¬×·8þÆŽîýs'?ûKH1YüSmä:Açþ„Xó«Õü[ ùnDé“d+w²¨>´Éu¤ ³v ç%&ž—,ŠD}— \Ž;˜6ša»&Ó HMð«¼JB¸ÉúaàÏ! Îù1Êu´A— ̆ƒHys»âÉAÖÍz¨ššK^U𠻦;ÃR/ïþLYh‡89+­ÖŽÑhã‚0_÷JcÙÒÃʇðài劉r`tñL9뇺˜ÂPt4y|ÏTk£eÈWªm¹Þ'µ|Šl#ø&<ˆ!Šª÷A¢—õv<ļ_ãi&æÕ¦Ò[#@R‹ýÐGĪ™ÈI¢úŠÐå _hE:+£Nºç6÷žþL*¸YZè~-#‘ŽÎyáG›°Æoð©\{mÉvÖbÁdôSGcà˜÷Qb¤|än]n# Ž*‰˜f‹ "‘Ïååî8›ºnnÙߎôúùTbÍÆ!/ò*á'Î[‰ÐCêcê‘ÚÈko´moúkÓxÃaû8a±Ì}@ð(@úß¼`6}øWO­RêÊýð 2#`áVº›¢‡a¶ ^ÄZMk„¦ØÚîD¤A¼ÔðòçJm¡I:*|ýÉW¶r ÞÃÛŒú×åä3:4[z\pAо>]W‹×·o¼*j<«o¡5 å]š}¢â-£{·‘wV_CõôΚ{zÙ6é'ߺä?9¨ç#þ½=¹kÈ·U¯Ò4Y ŽœÇ<.ã@ÅzRk«ò‡Œ.x‘…òœø é&z²Ôš?‘:£Ê“[,aÉàD—ÈåÊÍÞ>لɰÔÛ5²˜[†ß#„˜£¯E‘F 5ªXšâîw4“]4ù=úé¿OnØåRÇ/òXÈ­ëš§\ ñrîCDššEuÔ9´;@¼uép÷€€£õQÿì¯×YŠíŠTîÌÖŽÁ§i@«³Áéí;]Ìò«X^0ÜÕC˜/IÆØc¨>Û¤Tx¶YK¹Õ¨ ðÔŒ4Æ— [aB¬›MÔÄ$±ÿ%¢.`=¡6,-1 L˜TgXœCi øõ2]1×·Kâ3oHý&IÝæŽtíz½í ŠÂ¨(Ú{L^#ÌÓƒUke¶À|‚[ÁÃå tQ[Òô$Z!gÚ-/@Ô\¤'üž ü:&×Á[{=CŠ“÷ññÃSodÚ;yl×-@j  ›ÿ´÷߈1Æ0S²rf vÚÌÐh¼N'Xâ$X›‰scJª qð/”ÆGαÏq´KsNÏg5ï¯ù~¾1ç]¼$àêºî}—E(0‚ÄÉð{ÅWö‘K>Æå¿3-¦Yl; -ìCóD6v?ÃÜnEsLÖÔbâa“þK^zÉ®»Ýv £ì4ýqMžj 8êûpß\¶…†C ¼IõÊó”ãõA$ÁÒaÓ,¹LÈÎLí&¢-ulÔY;3éj±²ì!U¦kÌGº¼~©§Õm8Ùá Œr3hÅ`Õͤ=-”ºìÐØÄÝ-ÐhIžÜr¨"έŒñÂŒZ°Ò×kK¼ˆDRbíd ’°Úh„BèÊ$‰tAT׎i­1™×¯j›PÈB+µ˜î: g3hÎí{ Ÿˆò½îJ¶?ô_4Þ ò¶±µFiª€uþ•“d”Òq'|†ð·ØAæSBO½±&ÎÉ™ $ÈôŸÕc‡|*ÒQMÌæó“â›ÓÍ»<ÔX æòxþËðcK ¦ÆkÏ0Úœý»fÄäZÙ,ƧfÏvˆ³U•h'äŒGxSòo¥ì˜&4Ø:J®—g}°¿¤í¦'?q.Ñ«ZÍ´[ ÍˆÉ›`¢àÕ·{z§ý®3PQGªy;WbþéîC$C€ñL$Å®æn­­´±ƒ÷_¯L‘ñ `5& XßI¦Š¨í·I­}ÆçŠc­‚Z ÐPWœ¬¦0SN0óÿe­yÆA vgD¢™›:SOßçC¸/// {Žß/3Žì6bâþͿԈà”_>Ú ÐI½¡=¼H†òc?¡Ø„RE'IÁ5 <ã íK}ðë8ËÕ·f5’T…4‰BD3ÓOSÿêQÆþ^šžsn/”ˆòÕ§ý1M¤CÊ&dÒÀX@ɪ &kËïÕé*ä?·Où<Ú<úO›Ô‚7ÑZ5næóQ¸oOç 6—g5æ¥þ\Áõ¢;z &U\íþÁ{ú4Â2Ü„ÈjDÛýÿãQ‹¯Åͧ±¼wsêçû½Ý-§ÃûÞì{™¢½_V=}{òŠÌÿÃõ51DEdN¦«ô¿¯òü.¾R(~(ûj=•Ÿ8ÁUkÛmµÎÛ`öB0’¤uD^²ê졤4ÿ¦‚1^Ú/äöÝa}.Ù9Ó ¿¡ ÚúC (TÄïhí=No)Љê)UãäjÃÚyE,·7¹”qݼL€üÒøFOä †Öš3'oåg¢0‘%•ÕVßÛqÌ(ú]YuTŒì#øeÀ­Ö50ÙÃÁ‡rWÏ'²b­ôÇáöY Ô÷éf¹tŒL(ã=É$gñ‡e}ÈûÝ­¿3OݦÎ-¹Ìç©Ø‚ÏbaÁ0¶` ž<ÿi–&¶C÷=þ›Ì•öçr‡~£H,ia3ä8ÉÇ´-.ÌÃ$ËËHŽ €Ý®ºvYùYüê \´S•^ ×ü*4P!JV=î /ûßã™1ø9Û/ÒÈ—ñsÛî~ݸ‚âúÂ$èv+8B›wÁ™†¢{uì磵¼tÓølyËò÷hóº/£÷~Pß¾ë)w“½š$¶Ë„å…8Ñtv¨»ÿœ# 9µWšßÛ–S°Û8Bˆ›Ý}Tn²‰¶2xD»Kÿ•G¾è¶Ï§NÍ/=θ'7g®&XeA]¤ûTp{P©äI5úa>§•:3•ž¿kèѤöøž{®0-c§,a!$“ —fq2ë#3ðFðülÝ @䛓;@³tššZlL±7٘׻ޯ^|þ½=¿#ÝÓllßnª&Ä‹s–nG;+ŸžTˆtF73ןD-ªæ¯uUÈ®”ö´œI¯¸{¡„Ss'irÖ²G¥í¶–•Ø<á„ ª¾s楿*¢·)I>Zý™MµšéʹoW›0¾ï‡Î ³XY®ëï‹ÑŒè{‘·t8H¿-é»tõ&Ñzò¾QËèr‹|uB®k'g-T~Ê%Óq~;%³†ûŠ~ôüè¢úë5öh‰µ½¼•UBÚ‰m Äú®ªtWºßf²Ð¬¸óWDcç§êË:5ÓT/Ž˜I>] ¯‡MåTâaì…º,ŽÉ]ßïv®ÃÔY<ž˜PAç¶¶A{*¦/±Û·<ÖR}V¹_ƒè¡åå†û{Ô¾t[ tð§Ë¯„&’†ƒz‰±†ff9ññºJüú.ºC¬tÂv˦§ÅWǮ;KvKXõäÚ1»IT—¯t¡Añÿ‡57ª–4nåw=ô¯–V/A庵\¬¾R9*å>}´’…ëoñ…oÓ| MTDóãùÇN“9Ç×c«,Ñá»éŽTγV§r´;“¾gLŽäEc;£Kü£„e]å—Óe¯ƹû|*²EªrŒv§ØkYk\©Â‹.õÈ•XØæžiòQò35¾’&œ¢ÉÝ¢¡=„Ž·¿s˶Ž&7ÆLµD¢Ÿ³þŸo¦óùÊ£‡¢–k9]¼«ê^¯ìo¬ÂÊ£KèE(^ˆ5ÅÃV˜ŸeOg[óß-µj8G«{öåÙGKÊ&ƒµ, ÿÓÕ~âÙý ÖDáGÍ@£ãº¨~T{{¦L—•ö—g4³¾'碪gÉÎlty»¿Î-8êz°î¸;ÆdóuÕ/Ú[U —Tñ^»g7Éô"wë ¢\º|2Â5lÜsW‹|Ëÿá~ùìÝN¸µá²G¢_Eô‡Ý~w7PðßI»²¿‘TYû1Kî\âÔ oÎB C¯Åšœr'Ò¢Œúukƹê‚ͧq;³0ì~oâ+N91¦ê±EmD ó„ú©=ï¯_çí߬äÍõ‰' ÒŽbÏWK´ý7úÇ‘efF¿ªUYHae—âþ¼t„$ €d‚þ?éÄåØçf¾rrÃÃéfóÅ€H†¹3 Ø™ÜÈâGþ(¤ˆ)Š#w  ªU& "•"– Hd D(¦–©¤iSëøclÜúõî7©ßiUSHLp™F£öAndÓ–2k»hV&”Š$† š`¥3335mÿN‡?°ýÒþu¾Ì=[èþ¸Cúþý¡ÅxÇ/O«Çþˆ÷po(+N À@0ØovbõônÇíþMP Û¶¨ìDƒIz -A‘qålkÝDäiÎ(ÐZ‰gçÒgüÏa¿Ý|†jXE$²ç©ôbŒ#U|æ‘fb#»33 ÀÉ„ÌнGkË:(ðýuqñ¢Šé®M”ôgŒ?Ü=«¼bžª5ìî4S!"QÛŽ1!D1ŠÂBÐQUUfšm{Öµ‘ÁžF9q›d+LÝcll^.õØ×­UUTUUUUEbªª«¶1µfôÓØÛ9ÑΖª»m[k¦šÝV1Y\±EEUWË\ë¬^0ªíá›0^1Œ>í{À «ÅbC,ç^TÑyÌeê ½á·bİC¬ã0ÌQECÚ{½@Þú¼Ôö^8ó©9lÔLL-kÄó³uoxÃÏœxlÃ7kªíÖ°3$ÂL̆Äâ걈!>7uœTšãÃŽ3q7icJ‚0jF6ÌÅõÓ‰iîºV§™`j&ªa©¥Ü—…2,Ì«ëË*Àí ÷uåqáÆvÎýúvÎxŸèÌj¿å}õ¯éêXgÙ^;²ŒxÁR?TrU5–aj–TZ­Êªócø·á…¿ªÜk.M”-\elæÒ÷ ìRŸüŸ¬?oû>cúcûUP|ª}íÛPŸÝ ŸÎͯöWö0Üé‚̨a™€?{Ÿ¦¶é—åG燆R†UO‚Ó9Zwf´ÌéE"‰/»¾1À˜l¶HÒUwÉšz™Oã¬àðÌr[v;ì9 õH®ä€Lí4 †ò SzöñN®ÀN)¸{ÂÃd: fwîM‹Dp!xÎdTêoÆÆß‹Ä„6‡0Íl‹³‰D‰³3³8ûº!ï=Ü+ùž÷…_J¥Eo1¼†Ã^gÊŸ¢Û3ù_†ˆè´àÀRÈfe†­½`ˆsOU¿zÿ*ú UÿÈÿ¡¡¢@¡d±(Šùý¿Ýç;”÷0ãú{MjÜã…(Ÿ!úû¹€|¯YýŸä Ü€H„:TˆˆE\J Ž #K Ræu!¤ÀéÉhÊ€Hb†m)ýx%_ùíÿ8%þ"¤YþÙV’ªD1/ëmrÿ@Zõ]æ"4­[<#?ô±ŽPX€÷üßø|9Å’4Õ‰‚‰³¶Ä̚Ɣ¦)ø9ΠÍÿgþ×N$ˆ§þÇýf’Ø¢‰«ÌÐ7o0F†š+ú*é‹üÚX½f)`݈sÇü‡¤&Þä_Üó׉Žók´w3PÐ!@éñ¯TÒŒûóLþ†«é×^‘cMÿD ñyî…Œ‡È.¹ÕÖÖ¾HÙþ¯þùÿÿ¾ÞçCÃÏý ÓÝ­ÏNF§=®”Äzu®ä#H ¼ôßN P(”•LŒ5(áQ}ÌwhÅ_M³(Ì!­J7ǦæO1¯—vÆÚ£T¯JòÍá3XóWLðêÁ®¢Û*YNÆRqlQTÙáçè¾O<ᥟ?—&0~;S<’³èq¹Weج¶ºñ`KaÒ±Ô®UÿùçÒi™oÍhó`xÿ÷Î[®vŠj‘n@Q¥3Û®<Ø„ rˆ~Êõ¼}–¹mÔ·ÿÔ”"-ÚK%‚˜Aœwwz²M¤¬øñ¬y"‘ FºQü™W¦}#0Žöoö³(nu/ØÍñ_ìÐŧï+Ôm«ü?4Æ#ÿ'rI!UÐB?Õ xáÕÓoj ÿ“Ì ¼;û¼M ÇýÉ8ãŸf!LïÃø”ÎÌ—¬À"TôͶ¹×7ÿjm ]Èf_ù˜^ïñ.Yy(=4ÐéýܦSHm€®íD9.ÑuÏxÎöäÿÄùü6|õëÑÏ'äÙ_ëõâOˆvy¢ tm]ûÿ¿„Nðl»³Êÿúö„“Á2GÁ0ÿZq×r &œÝ•”(~xÉŠ‡bÒŒ€¤R,âŸù¹ D$OÉTM  ]?¦éˆý1ô¨6‘B‘å¼ÙÊ#†'-ÝÇB‚O±!ÀƒÍI¿ÅÀýé&â[𢝳>Œ`T¢ˆ²…_ÕT<±s[¼"n…â ¸røÆ¥Ö†™Rí¶e0Q]õ}YÇgRåzá÷ÅÏ´lS=` CT2LS…«Ñ‘K)ŒJAQ×ÑãדNlôÙ\¢Òdµ'.wcBCù¡˜†¿9ÿµøJl7ýE:檂Ä’K‰Wˆ¨ªö$b˜A­¢¥§ºH´’ˆÙ+Ó‰4J²b¢÷‹ÁÍByFPgb¾8ðŒJ§JŠÎ4o…5.ãSâH’ıAþ°Ì]ŸNõrÌ~Ç–Gl/Yvhoc£è}ŸW׌-ha؆ѣFµ¬å.¸n»:]„›ŠÁ‚žhÅ»‹ºÁ'¤ƒÿí¡âFÀI8hC¦ô’ ߬ÇNÞ§*½nŽD8eЄ»#«pÁöv#+§s¤×.îC’fsÕâJw2zË2 ÓhWÆì33žóªšÃ;h“cyáßD{äd™råú¼#DB^GØ’ÆŽîO&fø0 I-<˜xö…'h‘ˆ‚ Í”–ÔU>?Ëaµ±¹hZÝ'ý†ÿ¥ü¹ÿûýïZÓ‹çV¢"v1Éü~›²Dĉý %!)$XÆG<+8þ—@-¡•lAúKôù¬ÀˆK#T”|LÜåï©3‚RJeY†Ñ¤ÂcjŒx–#”óêo³š¦b 3Šìe®+lm´vA¹£Øö6ì9Ð÷Ù–+°”A‚¥EQŠj*j—DérQ ¦.ÛþL¥ ¢öìÞ‡SUËQ‘Š,X¢,²¼±ØØuÚþWæM¢ð V‰pµ™L\å40ÄhЉ) J B: Š$Èô¥Œã½4ÃTÕ 3w%ÑB LóšLÙ-´U¹T³|候O¥¦`ž‹©¹ñÏ©1˜Š1Q†FPÀDP)J&"(¥¥„¥ˆ©jI‰H†’¢b$Ф¢"H*ˆ¢ej&Áëé1%Ó’ªÜ^3#’øýmSŽQ(»y´;$~܆ (ö`3Sù™´)ü’º^OH)xÁ#c_%qÀi¶J’Äâbj† ŠT(îÀã²h¢h{²¤1L†Í1ÆÕÃb 4Ri£²¢çÛ‡ b"˜(+í¹ ù´Á]·®>É:P© 4ÍE4Õï¡/›~¼üˆ‡Þ÷±ùÇTˆ%€¯Ÿ¦SUIøfA n«AD"1H±Å©iÞüÖpžž¤àòe„üö(J˜8ÊC)ٸᜈ˜b–ÊžP¿$p^×§ô”bbÈÂ'z Ϧ¥âÛù.M:… ÿ¡a«öÙpu*Š˜U•Wm .&¡‡‹¸ºNTÆ=’pªž ÍžËt3ŒøÁ¬5#Z3Â@æx;£uõ»qyðÚ¼d–b¤)€”ºWRtI@è < D,R~K÷ý^ñãf¾‹ùTOŠ6Ò\rù©NQ€˜T}ÎDFˆˆ DéÙî§óÄiª—Oþ #Û J¤é»D#úv¶›Zß~ƒOºÑ­[¢âœ9 0Ü-$pìáøŽs-m×*×÷z–Xï­ÇºH Hjì|œP=ü9ç6éËâ¢q¬Æ&MàYĶòxDª ²1S­£796ã¢ÉËÅjã0;ÆÞAªØ@Ãì4Åå….³DÛÅBÓÆ-¤%šß,+ ÿ¢Žbô¹f8®GˆâîáqÍsU‡ÁŽLç ¡¢L’vÞ-©“¼pÆm1Ú9ƒ<®6´ŠÅJ¤P „øc{ÍcsˆoyªÖ!Ø´,KÁ–Q…ÿ¹4&TÓM|pmêžËÉ—ÊÉè‹Íã2Ãâ¥Ìì}v€v=¾d¹DñgBÎÙ¤âÀOúU¥jDò›®e#±QXKܺÜÞêKú©…çac_-¹pËL]hëféÉ{ðóyoœº´Â,‹šÃä'˜Ÿv™“hûv@JÄ}©I‰“W~bß.Ѥ†c¤Ëٌٚ@±bÀA™’‘ãBÓÆ²øÔéD„¡3DèF˜û*i;Ó%†,‡ª^_\¶t. åØÐî‹7zõ{똤Y#ˆ,á,¸°CDÅÐÎt±õ ã]´?SZú 7ýõ‘ÍIQ}¶L“?SŸ§·ÌƳl²õú7Uj%‡ÄI)Ç¿\ÛœÚSªÿïf:«6ƋVæ•/¨.iÁ6ã%d!2p!aT~hÃaˆ#Ëkí$7ºšfÕÉÝ5!ÿK;U$ýÓ÷ËïØë}€Tä›÷TÙxÏ£¨–"h£ýj÷ñ.oU‡%»¦¤wX¾B±F«ŽE¨ëõ)6fä?­PEé¯[±ÆèR_„¦\xc3•,Âÿzò¢SððUBX?v–ÕNïY„v%#ÒHΡ¶(Ÿ —⪂*«ªÈéñÌ~Xw,^3$|^ãÉÈ«JÇ’ý>eøUøU¡› °0Â_…`- <˜ÎãæJ62}»DXN8™ ¯WouìÔLdP8È<™À†;ÿê¹#žg¤Ö €Ÿ/¯ûÍq:zò¡dI$×úØÿ]ÍÿoÏûÔ½›õåU'ý½ñûÑLî+mïøOöµÀÈú¼è„Á‡ýÙ¨fvúäÓ ÄÇY¦ß´X³LÓóŽÝubWf èÒþ¼­!EàFB0ã9tO¥†‘aÚ>Æ*ì)º«h—C5ÛÛÃøhýzëú?FÄv¤DA?ÈOîÙ+™¸°þêoþ°:í8£2—…õëßUE[U:£¨wÖOöŽú~° ¦µñ£Î§ñ ŠH„õݳNƒ‚Á*ÓäG¹¯Nc/oDè"8vþAúØ.X}çoîó,ðšh9‰Æ Œc cƒB `©íb/²ˆžz(@S¦ün´@,nÌü˜©aPÖ2N›œc{ ú+hª ­3A™²f±¬,,,®Ê[<èçENϸ²ÞÏê.Ø YP’fÊ„:÷”%þisçfËœÝ eÝÅò’}C‰¢ìŠU´diBu¬”"™¿«÷v‘±àÑœH +J œ˜oÔ–æWìÇÞåÐ •ƒyvîvæoÜÅ¥ÏÇì×Ù½=ÚFm³Òió݈š„†®dÇŠ`°]X¸B¢#àìÍJ¿©ts§s?eÅ,Ð<ÎÐ;u•PÃA›§ŒNcÆ*h‰ xÅŽ{@qµÁ?Éñã‡úã¼sÙò¸m»6ßè`•ΘÿòÃÀáýnà‰˜kFkÌwz{rvü­N,ÚúoS\Or88äÀ¦NI'4Q®éžŸUYšJ­®î…]©îK$õV*wtO¹‘RÇœóÄ`ØyÉ ƒ4ÎÃÏA5BtÖÚ Ý‡qà}‡<ì{v0äN;Hý«Sõ‚A"ŸgêªÞ¨z<ë·ps8ƒº?ÖT{[`-‘3^·Ü‘ÚâÅŽÊsƒBI¨D û5Çÿ]Uéf¬& •M‰&d5ƒZ vkà~ŸwªÀò:™É/ÕÛ9%2NÆ Ž‰û±Œa²¤ÏóBŒèfð;Ÿ6Ó!‚f*ÜV¿f6¿ÎâËeB„‚ÄVO»õsý_¨¼^0DÄÉ\áøHGÀ1±ã&fò/H"5ç¿æî†J¢PÃâÚ\tŒ;P=ŸŸçœö‰é ÓÎí$•c$ô*Ø`òÓ8îþI»»ûð|~í»ø×ƒ¹½pŠÝJJ ¡Þµ¹(Ý/$®¨ÿG°ßqŒFöÔ;m[µÑ` ´Ìu Ó4CÔ…|µá#|ã€?˜Ô£Ã˜xyBð-ÊûÂ|ˆF˜üêþh“ª8´${•KKÒ¼öK> ¤°ü¡¾!®%ŠWHĆDáe§¹}™žñ8¶1öàŸZ!$–—ð  ‘ìðÜ,˪<¢(¹Å?Ä@vO~÷©‚'ö–u»ÐáÄÁ1XŽŒ¨o­` *…’Ósь卵†„¼@Ø/=I%ëæ QXxÖ¨mQ(ñØH ÕÆ±!£žºr.!Ùz¼°–`§E¸‘‹U±_ÒæáÄïÉZQ$’ª¯%ŽR÷0^L¬Å·7œ ÀÌa‡L!ûÔ™—«f;‡#îsšþHÛo°ŸLF—oææìL|¦UùˆS\ü·_{i÷‘Iˆ Ûæ/ÛOWC Ä zMŸ?+4Oöµåj=Ë"ÿ!S¶yO†g‚š Hôí*ÇPõ¦’¹KúäÇøxŸñ`j¬:U:éðó7ÚCXÈlž‘ X׫ö,˜QQî‚@€õ0yd;úÉöû®wdzÿÑÅ´ÞZIðXb-ŒXì$ÃÐ;F ‡f"(AŠ‚Ïüè~iÛaNlhvÎêW2¼Í cæ`$£æ¬þk{û>ÉÈl.!ˆŸî~~ÖÄ®ùËê¾îãÛØ-—ÚÈGѱ‚1‹i «þmv–˜RÔ`Õˆ“&Ù;½QÑHѽUÓÇLi}ôñÿ¾¶’H 5i¬©ÔиhÒöìqã´M}aÃ1 g‡†Öí4ÌÒß—b†Ê“0“d˜mÒ™(‰šÐ:º 1Ù!ÈØÞM5³V5U×m¡Q¤fëøAèq̱Ó6»S!|AöËcæ9T*!ýËX»7øcwL_áMwAØçëÏ¥ÙÍĺß'ÓŸ@hLÁ¹©ÖÁ‚&mÛQ}z0Úì·ó‡4`á‡ÐÄJ£‹Ž347kÙº¢§=¨¡72`T×[Þ.n=2”{#=oX“Õ×RìkèŒË} L„4Ž¢ƒ1P²¹”IuúA¿…Ôé`w)X™¸¾Ž{yñì)¦Ê!ÙÕ!ÈÔN=EE7Ðúh.¦U2¢¶ŠD©0**²G}ÕÎüm(njé-¾g>At¥=»xž¤Pøü‡‹ºdžã~žœß-CÄaÆB×ÐB!0„—`^\6Èå¡åÆh‚ïÍ¿æ¹b0Šrõ‰@öfR{#CÌ釂cñ> uöóžSŒìð7³†ÈU‚A‰†rWe:ÐhsEñ8øK]æ>ëÇÇ8º`GâŒ#„ÙÎsøo“'[¶ª6nÈ×.Á­±34{Õšfå×·EíÇFÑÔr>»Ò®ÿ("NÎG¿š9ï=þøÿ¿ÿ˰ ,㣫¹²´Ê²QUN˜UKkè”h膫ì¸U…*®Ù÷˜#ž*bO«PÞøkµC»¿0ÃÍ'Þ‚a¬C…͘È!6¥a Rf8ÿÆ÷“##bft¡¬/L g–Aþwgÿ/M½äØöß­Šñ"^ŸJú§WôŒY’–&c‚pe6°qo·úã$"äw©éVp ˜#R`¶¹À  Û!8æE3ÿ×üŸF‚”0ÄÐèÂÕÿçÉ~*šÎlq‘±³§“åíÞ‡‘ãÃûÁ ÃdôÙˆ¤Æ÷©§¢jæhH™#}!f6›êÂÕI¼Þ˜æQW60¶‘l>Â,Ø;OzË}-~ÏÅå§x H°©7 À_VAŸJ~Ø® ÂÛV­#K‰Ç]f×3'3ó=ˆâþ¯­ÎôV.?\ëÚE¹é+:‡åŠÙ\¸”f÷OTNC (0–þQ*ŽcGôZÔ±&ëZQQˆ˜åË’òxåßôäÌfZmݸ3yC†Ì¡Í¸¬ŒyUŠ™Hð¥K’¦Kc3¹=²ârCU‚ “6ƒrÓTP Nç}ô†™+lÝôüøsâ4^ð¿]¿BéaÛî¡þ¿.l(vù×ÖIúº§ú1OŒòÖSÍ}nÈÃÔQQ2•¿MBÙþ…w¼2y’v½*¬kż4Æ"v«!zÿPö|"RV}íº¨‰öš_«ø~½ÞYÑNuÏ[Á¢~PÒAJCÁ'Pý‰‚zfòžø™ý‚–MhøêÏýúl(ª‘¸ú]gþþ¨ÿ”¿,ÆwÿÅ–ÿ¸½]¤’Šúæ†Ð€–"\Ü ¿7ôås¸·±ü¥´þ ×6È\‡áÓ9ò8Mús%üôW÷êÿ œ5oYµähÝuòþå)JPÒ¡ÿ|»Ø9wy½ŽKÜíîÑE1˜Š_·¹ýŒìŠÑ4V€ˆh!š¡JPÉYjÊ5óúµ³±Oäé”(©ééý;¶éxç"¾ÛœÈOîÈ iZJA‰JŸ<Çòy%(pØBÑA244éCò@äR.” 4 P‡Y’ò…s±$© nJ ɘâlò?óýãF*‡LÔžÉì" ©¥KÑuà=Õ§ð“öG‡ìÛÈØ>Ü2ÈBsƒL™E0xìþÄľámšµ=5F|Üá;呵ñ^ Î\|»}n@qÐuÓŽõšR‘o?Îåuc-±‡æùÂ=¦V›J..Wk²vÓqö‹èÈžbczé°z¶¹;ïÎçÄûO¹LTÖ¼ŒÁ1.’š¶A“2@5&†˜çÈ éo¸Çµ´dÌ‚®7Ÿáðz¾y;•¸}T;\é·›i ¿À½–@ëxΆHd†^ ˆ;V ‰ªwÓíö Œ(8S×ÂSAõõÑráïXún"¼˜ o³3ä56Y7ÞÉ.Hrè=BN³öºÔ!w`ægé8­U$£ l„-T @Ò‰£ ¢hÈ·§™³½Þ`ÙÒF.Ã# ÔØoéÔ…¶LÉé VxÂIÑ•B,.r©ƒ8¸±­p~»KºÁwŒq4ú@FÑS4µSòOOGŸ 1cVALÖR9wØOsC ‘É¡×ýÍãZgGˆê0¶† [%™àÝ^¥dÇehXŠ_‡‚NhLe‘1íô9,ª-7 㬶ÑТӅ´r,£•ÔË©½aSTš dC *XQ÷šã‘…ÐèF¬šÄ•ìþ›36”n$ö DÁƒ$¹Ók²Æ„ “ÜÈvG”‡…ÊWmˆ• —ßRÌ ñ*þŸ¬¢®ê@ÛDÎVÿ[/ê? ú¨åæÍ¦tÀÅÍÆú¬9sè@ìÞðÞù@ú ÛÄèêØWžüp)8öšmb½Ýt&ÜNIÀÜoÄÂqå)E)Üm1qWHC£ïïøÏ·ëû=7©ÙöÌ­’`¤" &XŸòcÅ3p´r§ŽbX§:©…ìä„ÿ| QxŠ|£³¦kú4}>_èUþo»UWwŒEÝàãFü~¸_&ô}®>§êPñ‹h q øÑ!Tþ®Ñ×Ç£Ê FÞIƒ²s˜²ÕÑÚÛV {ºbú4µ¶²¦üd÷ÖÈ€‚ª6¼ž¦ø²4Bè#O,lªØ[mÝyh×M“¸yx{øèÆg_ͦÝ62½FIø˜"î"yŠùÎ4IÙ“«Õ“¢N ùïLÇZQ.ñŽJf&ÕÊÊCbïòúè!÷‡ÍT‡Ë¡¥ø-‹n`"y.2¬z¤7£ÄïØNdQE-QÛŠï| C ²Pœw„®ÎÌ!“=qÔcRš2ÑEÃüü…}\êû<}IQùÏœ¬ç÷£¡u›¡‚ ÁÇ«aÒ—z8ˆMŸ½o:xjë/óÓO1ƒ.zèÖîâkïjiHgt[Y ¢i¨Dšp´Ã`5•XŸ@1>8¢O™™²ê|XuDÖ&“ȹ|¾Ñp3u'ýç+ÈbŠ|í ,ÖêRVæöFj@ú„ :ê›0ÜL™XMê쪆‘ @¹/`ž}<êo®Á2̵±ë+¨I5·§†4`²06´èÊ_[wp1¬é÷ ¼&.§ú“ &6TEçøÔíLÈ‚„T°ä;9D” K4­ð5MvKà˜jš™2nŒÞ 1‹úA©@@½¨!ÒÛf §Ý¨ØúAŒBÿTIVhø'[S†7¼IÈt l;Ð:ôCѶ’,î~ÿæ{jí—Â;Ï·åú>R³ì2Ы‘‘@p‡ZÊTÔj3YHÎ’:ƒh ùñúwž¯N⠿骮V©Ô(r‡ú•‡r Ù >ï×ý?~&d†k‡5A¨XT@ZVr‡Ëßôåù|±koL«(…§ûÙÈ¢Lþîe¼` Äü?c=*Ç ú0U¦v?µÙëX 4Rƒþj((›ï‰Îi2cï½·ø¾5;ÜÂn¯ÜûSëíxëæ£Oâ&°øÆ,Œ ¡ÅIA"ˆÆ)È íØ‡\ &]yuh`ýiªL Iy’I´À VÇŽ §®eXÿÇ`l.:«/…ÆÝ§·›”5ï³T7ì²ùS:n8ANRÇ ¥›Î"¾Ê°é5§¬’݈}I™“ìù¦íÞA¾ÐYù· ƒ«Ö¶Zï`1@Åv/»UÁ5†¹[V»ñ×·žý3NѦØ×Fª³Ôê—•³„n¶ÔQ;jÑa†ºU ›t±*ðš£Á‚(Ðj ÞLÖÀLCf¡.u¸À7[þð³~­ÛZ)Òú§\ÇAL Ί(‰§l§C¥6Ð6“~ãE&E£U÷,ïÜ~üAŠçq¸pÎ^?óÙs†<¸ÛºˆãÊëªg h®4ª)Ù:ÊgÉä¥dªQ“«©ë[ó|ü²GÙ/÷Èg¿‡7Œß>Ù¾¯O˜Íb™6p¢ ´Ñ%t²Ý„/kôÃ^Í*º9r–ÆÚ¾‘?=7ljÂѹœW[õëõù êx3¤Ù‡ÇÛÈ›þ¨sñ‚{€é­8=±îÿ¿Ç£ûã³…SP½Ï—)y­‰jõoh6**†‡ªë¡Då\®×l¸[A]¡¿Ï¨1Ã0m8ðào7ãÙlø}.=~:Ƕo ã*~z”ÆŒ4ˆÍbÜ—•,F²pS².z³â‡[[oFÖbLƒV®~Ô^‡ÃVfO®[5Dï­‹T¥G­§ S‘M³¹¥±:FÚ ·¥¦Ê®„­66Í»j ›6î« îу±a‘ž†"1˜îéÔeTˆèØìGm%5RS;°èÑ®‘V¯NF“[f)´ ‡Ûù#òa‡O£ðõÎ5—| y æß’?‡ãô×ÝôÒi´{,VéúÉ<‡Tád*F¾œ÷ PÓõõYˆG¦][(ýý.îì“>¿ú*?†êNÎ=—Ãofßå«qÀ¤´fs½–†€ÍÓÝàÀo0ã£LBq†ïAGœñï_xs †'Ç*ƒâÿd ýþïptú~.ða¹Ð2Ìô̵:ØKI!•øÑÛñqgíI$9rçáå’I‡?dzAý\ð(}! Č’WÖáÄÕlcBiÐ3$Ѥ+’'  i¥C™T̉@™,Í´¡’€áGÈ|¥ä~mˆ—ð.„“ý7ÓÛ‡䊇ÇÖïj¾¥ Š&˜(@b ‚9ÐGÍÁÖª÷àú.°æuƒÈ”¥s¼` …‚„ý¬X²凌‚–1˜y[Tª' ßç8ìõd/Úˆ(Û*¿¾é*Á¨ˆ§ÅÞ™¼™ì•¥wþË“ÛÝ­pº ÓÈ!ÈÅŒá?U³Óéïj²`Rñrwâ%?t¾˜‘.U«Å†:Àßð6—‡s{2  ¹¨a’Ò† Å×þÝ·<­+”5éÁ0&@'N:t$õh9µ÷#ŸŸªïµáBª%O:b4(ø6ÑŸ­ÜA„) A?W¿;ÁŒA‘é•sçºäŒ Œµý Ò6†xîot.‹øž‰káDš=Ü£rʈ ØO´I@ðïÒqÐÿ󳣿(¹üzÑÔF”hSÄ/Î^+~ÎÞ¹ïÒ]šÈQÄíYpÇ¢ƒ÷ñà6 Pœè9(b·eŒ)Ù†™Å˜q.¢¬bN¹_HÆáÄŽKx8NwšÒÑ«PÎÇ8¸Ñ„äØ÷ú/rVA&úFm|g)Û‡Ÿè–¾V_®[¼®jBWå 1Äf#ˆ|ÒZÐp¬óW°‹4€µÙÆ ©¥Teíèz ¹!d÷4¼ûHzP†DÔ‰C´ƒ¶F§4´Ê¯¿6¤jœÄ’©«‘`†‚I„™’zÍæÃCIöÕ¿é­X9^»£C×)B‰=©âã‚*ø?t/³77äeáþ~l8I‰ˆd{΃#›ºî®í]œv[º­FÍ÷;9ùuöDë@1>gÜwƈô5Ýå­yÀ6ŽlqÃd$À‡µnLh›$Š ÍET’i E'‡‡‡&)¥tÁšŸ[J*"EJAÜ)—a)vÑtèã¾ÝD4C¬éDúÌŸa“LK–OYŠ‚`„6Ií“ávËî€ð”çÁN  é'ßßß ªf=•°¶–¬,)²ÉY  ;9s³¢žg3!ËJºô.uÔJ¶{1KŠ]˜¼ù“¡žÝ\õnc.8çæ¥‹¨dR(i%X7Vý¾=æŠ/œH‰yý'̆ÆØz…y¬«Ðwøù|®î'ÂêfÅѱý‘ Žß$ <ò8–˜î(àoê ¶IŽæ Ã5’ÄÎñ  ØÖ<&9òΩµËÓ{QZ)¼Úd4 ƒ\ ‚´9#%drk(Í´bìÝŒÐw,¢ƒU»!5¼M =mË$: '‰g„cH‚Š#;¼? Î ož­†ðź›XSë˯¾6íåh˜êµµ²¦ž2‰è"FŸ—]õ àtùu:’Þ–=ÏÌïx|G]Aí£Ãb©$–A‹i)çíƒ ÛZ—|@ìŽd˜4¥_D¥RŒñ=Õû{†i°Ðn®Äzq«M ¨¼¸£¸£ÈÜkGB›“%'eâ–yu¸I¨ëçz÷œÈt••UUVá(ÚQtPˆªˆŠÝRžÃ(r&JÓ.’MB…]žŠa k%:&E>—ïŸöͼR]õ-ä·!ŒD“T&­®g&†¹àu_@O¦&eŒÊo©ä*3Uè%jr0’(Ãð_,û§uélÿí †h.§2ÝŒÔ#'=%ì6ånzqZªŒ v´òٜ艧¡å\'zë5wÇUôª¸]ƒ^jFÃfȳb$».íYååàmåoéPóœPƽk̦ñ4fÆÜVìË‘k>ê.ËKÙCòœâñzl+Ù¸„.®4’*ߺÛm¤h„`€B°pãnŸ~¶ ‹Lñ¨)=]xåë7^Þq¼g.c1äw”§ˆÈî–_Omýžÿð°je£dô b4[ti5£,å¢1$Aų~ÍBIQ¯[ó\ø9;žôbfóOªð¥ÔÝé«:’¦ªóÛ£~šë4é"ÝÈô¶Çq{©.ÔÉñ¿VÙ>¸èööêõw&«]Jϧ¶}½•<ƒa¢7Ãà$R«êøÕІ­ü¥ò¨rj…Ä¢vpóBÃý]qæ.kšê¾cŽ}¾1øDÑ‘ñ­Pìœq >#2ƒ@Ž¿mÆö Í.sOyV†R÷öK·É:{V‡t(,’ŸKngÆÌé7~~˜åˆ€<áé¸q=ºvH¥"B¸j´9($‰3°¨Z­-+ 3"…(V„&R‡B¡úÀø³ú¤Á†.Èõˆ§·àÀ_šY@šbIä¶Ôî`íP¢•'oDtà@Þ– Þç@÷â®%à>"£^KÌıH¤KD¿S¹¯ `¦IÂ0ÃW+äQ> Çý´Ô¦Z×—Nsà›Xzk·â˜”1÷®0ݼC|ßD'‰,Ú ¯ Ô3ݲ”¯FÈ»gòïí†5ùØ=¡öñã>½{§<³×VtÅFˆì ¯û¾Ï«¡™¤uB×\‰M$:h-¥ƒ@Dâ"Cºrht‡æ‘ï9á#ÈO‡«÷;øa¿‡ÔŸiv=#H`‰¼|¥Á<ò¾{œïã ˆ¹0Sb^Ò$3q6ñÝŠªqªj¤ß½ lÞ÷ÛyÇvò• ßDéœ@€RÈRü¤§^ÞÈÅïúŒàËăwoGnÙ˜LW{@3ÊÍŽz“VX8‘œ(Žéu i c@˜ÂÓn×cm–¡‰¶LO6FÖŒ€•#Œ6 ˆDý’h‡Š—t/w«{³£Èضͮ39ÄÐï'Y\ƒ»kfÂVµÉÙpŒ®¾X= aðÊ[¡!n`„>ÈcÄ[¿Z¡¤û<¤øy¡Ìº5YdaPâV( 5sÊöŽâ„Òþ@#ðœ—R9@jŠþ´A‚]\“ÝTbœGp]¯ÜU°å>óŒ×y¯*|xòÅc—Ââ5Ä×l½Rüú|wxÇÛžvSfaöqÞ±vCÒ®ƒ§™ju“8S 5˜wd:Þiýð§2ãf< ×ŸoNÇuÏ]ÈXîŠÜ"ã˜I3:Ý*¬{§Sg¸Î䞥Õ[Ï#%•¹öw°žO=ý~Ÿf'‘uÚs-ïQéa"•(¤(À~—Ó`ÜKo5Ü Aùå¾H ÆBer! z{½|±”!ÝÅ„œ*¥Œ˜ªZP°`LÈ´3'vf;{¢H?ÃK†<\-évh¦ÂS©ˆ²hjw).Îâõü"ýÆÕ¬¹•÷*¦ãôD #‘Ž80»8v½Í¦]w£èðT‹û™ä¾v»±‡´§s¸¢g¶z¯f§UY*j 耦TrÅø==¼×ò6,#:HQÐIÉÊÚP'Â~3Ä õ†œ6ÆŽ×åþFõ=Qà|pPŸam¼Ñ‰Ìy Ömd„Üwr-©{dا»iÊ„™-v<^pp‡4hx~ÐŽO´žj”:!Bh_Ú<©õHcofÒqo>' ,Ú{£vb¶cë¦ ©W ú^•’Ç8¨/—v:èpÒ–{øñ²Þ7äõŽ)†Ü1G¿éðf+E42wyÇt$24Ì K" %‚4f EžÞÝ÷¥÷û¢B¦÷Èý'Õµ3×ò‡Bê±þÒh7‰±¯"3lÙ²ši;\a£Ee`Õ¢ºë™Sâ`‡³‰´‡)î@ê< Ëã'jdÐJ‡±ólµQü¾ôïððìØðCd-ÕáãȦï%[(ì3&odíã>„ fë-{ç·MZ²Fs³ Ù·¦RË9ξ›Ó©ážI`Ø€õò=ƒ&"\iÊY"v—$áUpE=]Žîþ`x“ ùèÈŒ¢›9G&’YìfÃJ"¢¿²°Ô`dB›íZfttˆP¤£T+àš¶éXSA gÔYçâT¾nQGÐá'·cA.Eh8&gÌÑEæ}ßsµEKžÌ(mßÌðÀžÇÕ’ø_¿›Æµ¦»~ŽíyHûç^^bªªªª Ѝ«¦*ÁEø4¨ *"q4•óXqN‡Rb#aqàÑLç øˆ‡IÝË”Mª;ƒ­A’ŸÙzïØíöOg\Ú ªH£¿Eã4ťЖC&¾mMÑÑ…}f­Q ê ö"NÉî˜q°qÜëÊîzñ'±ÕÇkÉË%s½ºÇçÓ8Ž;“ÕzL<õ߬a>1ÚEýØi¼-«£-*qµÇ*ê²¼õ3SŒôW (ÑÌW«ù‡ß©·K¶Sy Î<êeB Wnýú1Õúiõ¿l´g€§–釬%åÏ<-Þ£:)úò˜}bð ÇzìmÞ¢ç·;ïâyÔiGŽ:ã}˜tœèíâ/©å¸íé«7]ç·Žn0Ò+|SôÓããÃLhĶwÂÊ ­‰’ÏkÆDëi«1•,yh:ØÎo!¤Ö¼w놨¦Žs·¶*UÊ\àÚjЭٳ„¡ÇsöÓ¿Ì3Öù˜óÒùs¢R Š„¿)…%#2”%( eIÇZèmŠ—³£¿ßROHÝH®9|¬bQ6K1QÊáZ;A°ž2ßÔðÉðyÐÅà\™½í«3ÓÕ{Ìön8m8?SoØŽ8ô#ñÏÛé£{ôøõ:lß#¿ñT}&=ÝxöÉÏABÀéVe¸M>’žÚæ(@@8Ô<7¯’{’^“wâFÁ}?H}žÓß;8Ö?°ÏÐ'çí“·qØ+ZÓÃöýlÅ ¹q¨ó·4¸7†~Uñ/Y _ÇõÇ\ëÇok îiƒÙ ”µ¸è_¼{é´ n"8¦‘nR±®ª¹<|¯Õ>>t^®tô`â4Ï•›]"ˆ»ÙRêCC¬õà ëéë·`ØI³fðÌo{Ï!±Ë o›·'ÁÙ‰dŦ/+|IJ[&̺Ϻu.WnÛ,%§Ö¸[e¹î;‰uÛÑ0ì·{†úþf¾dîå‚àp%m,·&<“ˆˆÖ4‰ë *a“̶<2~B¥ŠÉ;Xát YÑÌ‚Þ;¦t¦ÊT‰Iç9ÅוÉÁœ86m‹³/‡tt$–P P9µÂ28@çè:3ƃrg¨¤ÞDN;¹wH$š ¸õý$%®¸1B(LʶC«£ZåÎ (qçz¡—8B4»¤ó0õSÂT›p$ZaÍ ;^ nÆr‘µ4ÎqzÞçˆÐwª\Ö¾ÈPô´fꨠœ,­¸™¸ÙÖùº§»X,æzïÜl¦dhú±ÇîsÆ9‹Ï3Ø©Æ_&+¾¬+¨éˆ±ÁömqRýú㉳ž+\âòØÏYÒ‡êQzn˜È›£~X惎t 7nÎitö`í–0î;Nù|F¯c£xŒœnð;´î1~×Þ´t;Ç:nZ§Tb'#°'Œ&;þþÝüŽïo\HUjúë¶q…~ ·î×XñÄæ «#½®ìâmúVÌîtýëµ÷xñOw‰ë/“ G+ÀwîÍ>¶wèR´ë¢3Ôùê£ šÖ“å¼JÅ_r‚$šïUsØÆ™„Wéns®z«Ù–Á$v׺æûÙ–/as–ìŒç´b™´ú,ôÛì¤yòb¼ÃÇwç¹¼Pu3œJøÂ“§¬`ë™}샟¶[1ŒÂå³ ñ£FŠhæÎÎ \ýŸž|ù”óÖL 4- ÂCÜÎtF—rMöÒÈ[çzU/Š &Ÿ¦êpt5Ø9Ï®sálµZÈ·»Ì²Ò¬zµòzkªôO‡˜"QzÖ±U)æ;±§…'p‘5²f’¹¬,ûU,Îu eÇz PÂGºu_ *·Wu0‚0˜[‚Ä pœ‡AT}L»Ù qÆ×n¾Â~ökCuGMΤ¬±å1Ûrææ¦Þ­8å§Nª6ZŒº€ÙÒéwh'âÚa¡X”ÖCÙÙéôçE-ªøö›áÛo‡NÃ-“jCMÐMJ¶ ÂÂf40ÕU¨®³45aa,°ÅeÁYYÑÆÃßsŒV¸Òí–\áD0¥ÛÇÕŠ`~1]5ÇÕ.0a&Xà5Æêw[´úWN{o³°æ¸Ö3•ż.6xì7\dã¯H­Ò::—íЭvĕްgyÏK6­>b³OÛ±‘1æ·¾F¾cbÔf¦#:§×ðãëœhä5Óuˆ)ú~ãĘ;{^»ÆõŒ# LpŽëúÚïÜ)LÓ.Ø'\£»åºœÚñ]#Ta"q|\ºF7îá›]Â`)ãnÎ×D3yi§Mþkž04-=þ/hY óN‚ÃÉ9=f¤=œÚ:“h~ë|ëä»u¨å·˜âÜÕäâŸæ´ˆ6UM¿«3Ñ~aI¼ðð?¾h~ê²î‚ƒ¶6.ßE)¯=ºï-åN¿4Ë· ·Äk½ŒjbIëƒÑÃ…#ž*ܲË…ܘŒÝÒ@¢âqÇwHBI+ï‡_k½)ϽRQEm¨âС‚€ÌÌÌÏ?Mm†ÞØ66lÞ÷¦cjø ›%¿ÇãóhngŸ«¿]¸äÏg/§O9¶ñÇZ•ÓXÇ×$æ"ª!9GWk9Ȫørž-…`š‚‘gË’h®8"]Ó›q¤L‹]×_ %º'Ú45M<·S¶å¦¼úX–1ˆOL´ÏuudjãeoÀÁކB€(,Xª(¢›öüqÞvkð¼uÄO ñƒëçëù}ݽhÊzwÑ?n´kll/®"Åá1—¼ÆÚÂjß|Vw5ŠíٙÈãß8;p°ØŽŸ3Ñ~iñÛ–1*Àî÷cްï¼õÜZê§ÓÄWœçÁ7…º¨§³H8–äGEŒ^E­lVJâ’9ÕFkŒûö‰ìRn!ާ›„ûò+ô‡lO¢ˆ~Ê5ÝõâL™â…Åt7MÌxÈKËu®Žå;®n;Ô®_¦lóÆB+yi©ÓHnîsGk Öby–[•j»ÎÔTpî§M=ºì÷Æc(ÞKÔ1ÏoNìzb–WnÝûýW«Ýô;ÛtéÅÅçî)>óÊ]û|É¥Úyã'Z·¨Ô@²ìØ•ÕΪh) hjç9öŒÅf%Öa¦.°Œ¹]D]…+—Þí·F÷†¼0\e¤*“Øxãê4xË㨠ˆ\©äL)g£±|…±Ý<ËD˜\#×Ïä{P’#¿yV>gúÛuÂgÁDcÍKR¥º²ëlÉñ-±¨tüú((ÑX¦~þÝ “áíé.¼ tÓ˜: ó÷*6bêÎîRî‹6¥@áåX8˜¿ŸD;ú=(ô%ä¸Ê,õ:è€Nå~Jl½øÆ­官å}÷Ið³žEÇ]– SB!Š…Ýt¯üŸNLy¿ÃJ9qs{1E‚ÌÌÌÏ<ë,`²Ë,k ,¨²áù6lçÙ…ò›ï>°s›‡ŽÏ ™mŒÞgé§ú1?x-8Æ*ô=(&‹6»ôãdåÚoé솹FJR‚—èf„‡Æ_Q-k0¦ý4„… ú*ÿŸ÷h‡Ï]ºÕ‚WlÎWûûWU‘ÉåËB¸×K{½pEd‘`²1RFY„š))b¨ eª©(–™(Hš)J*$¨ &¦@”)Љ‰&Š"¡©‘˜jš$ S]/Â4DOWÕÇW²>>˜KÝê÷Æ%)?B¤šÆLˆ3 (¿S6lÎ%å‘)®™ulÓ½“ÛfÞO» Çpßæ!JéMN®E zò``(°‹ÄTŒ@Ð1"ÐnÁ†ËÐÿgw È›ÃáÁÝšßy@ƒ±´[É}ç@µµ·P/ï„_lã9(,"1Qwwêþ“%2{ž[d¤m ûÛIë5¬VÉqvSOZЖ߮Ú5 -'™€[o¶Y€­¾æ¾ †õŠh‡F¡@øÛ@æÚK «m¶í§mZøyï{w¾æõ¼T”®ÛZús3W{íw¼¶^¨´1+l©RùÒYçïûr·›ð¶ÿ-·á¶–fãm÷Ût‘ž¾jŠ«3À*&cVÙûýÛ>…ëZwzþi™ì­ ÎûkZ½ºëZå¥E)Éóáž½û-jE$Ô¶ÞR¶€>ìi> Û¿º+“wP:°Œ¤îîï°œ±8”i¹C-5evU–™0[†¢Z•´2Ûþ'éËK#I}_?ÇÊgÃãò¿?ðxêxÎòŠžm{Dî¤À Ûaa@i–J“ @ T¹}–µ­ ¾³&  –û8ÓzÉ¢ªJm mµ§m­®33´ må[qPm6‹m´ Ÿ´ÌËñY™§A þ ¬IÛ@«hÛm´²ÛîÓY˜ZR$’ Òv©jVÐ?¶÷¶ïæÖµ  «HP­bS3‚…VØd(HHc¶U´¨Ì0 icÿÄÖµÊmÛrÛ%m´ I«n+î,µm({ü4¸Þ÷–Òbl´·Vô /âJ.xK‰Ç¤÷ú¹?f»tíÅ´$Îí,Ì;¨Öf[hâe˜›¶¢©@(A@@s!s´-·çôY™«o 'l—ôéýsà·½ˆ  P1ÛI $-´ ’á$–Y€‹òæ`ŠÛm –€‰[c«áÞI“m<ÞæpšvÚ•´ Ú¶Öíµ»mI;hq¦³2ñ™€cBòòõùuÆø„:&›mbÌÀ#$€HN­þ2©@Jêfe´1&­ –Ð*VÛm©[jI[ImR«o½5f`“N»(Û%Ä´1[rÚ,øDŒÊô–fªZiyÍk@…ûþÿ.§Ç ˜‘—‡Ë™’fí m¢m´’-¶.m W *¦[ðJ,̾±fe¶ë30-´ mÕyfg»¢nçÕm‡Ê«Ká ãíî]ïnï<¦ ªwö§ŠO]±†t³0?UVü­7òæÏ½WÝפ÷ sŸ›ƒ§^9!'²6(Cp`D‚ ÿ^1óÜ86^I¤†ÀrúÝ‚åƒÒ Ãlr¸J9Î=Gï½=œ ŒÂ¼ƒz7z”\ òðñ=Yõ± à<%¶]M*Ä ZP…§N&*UÔUI¢*¥¥˜ªW(¶M˜1*(£XˆY¢Ö‚“`2ÓŠ&#-)1É9 s$&°šH³ƒF“lè ‘]€Ã¼à‡$yjXj´bIØ0KA$Ò ¶ É€7ï­0RÍÞ¯#bÚ¢EK™Ú(bœÝüqü¶Ûui…NMd›õ(®œ¤vÛ”‹mÛuí‰'ÏWlqXµÞam [êS(E=†6ÑÆª¨¤’3±wd˜Ü™ÊœÑ­ÒöQ§ÿÌ™ÐC5l± S)„ÙýëW²v“ ²ÀDŠ!Mˆ_áä„›!òŽwÝS–RˆÞÅd3黵ÔüçheS²d̽ &¨)=Hâ>ÁÒ{/•QH¹)GË? D£÷NèCÕ9DÑßçš 8Beî² BãD´ox&’Á èø  Y!@sx.ÔZW^Ç|çîbÖSݤ |áÌÚØ|Rl§À¯í)*ôD‘äÿéGÑé©t|žœ+©<àÀ=,óm×}iº*2ã–ûj`”E 0ñtë¯íOkð@:Ù@€ëLÌD5(J4ô³\ÕaÈ£æÅ-Ö»Öv<ÿgîù1ÏÒ½Dr„öÂn‡ÑÕW|” Ü¬ˆž ©ýÜ}³›zDzpø6ж\ölr¨Qé®EæZ’Õœã'ÕY°öÝ„NÚ³˜{(;_±7­¹h–·xÚçtmvÂé7ž.Ç9ìÝík°[¼­v’õe»Gz숷ã+t6,ù)|KK¸ÇòðÕöÓoµåûÖø¸fˆvß*j[š ûPÌËu¹¬8 bƒŽ>u<Ñ–íçûÒ6zí ×M¶@{?ÀS}uÛ{GjÓEÃA%ú’óÌÍ=ü>•Û9“Ÿ~cÝÛ×U|)»:@ÅÞëP[^Í8•‘¡iÅéЇ5¾)‘Ÿ¿ÖhvúPæ§æˆÔí¬0  cã5ŒCÍ3 ün‹êyI qþZ®-û¤N§œ~h„fübñtû£Áù<0ÙŸ|,þêªE¨´‹¬éP×·U ‰•WSE$çg4ÎDÉUï¾».ݪóÓ\ãj„V•$(û¬ÃWβFi›J·'8«’ÉËù®x"Ìc{Ű}O®‰2:Jè)|'át¢BœQk¹$ëwö×Âq®8‹u AIHwü;χ'¢PŸ¢±îh%Ž›ÑŸ˜jKy¤ªß…«yxÜÔ<&ÓÐ×CdÇ4Csñ˜IV³á_4Y’¦ÚD…¼{¼PhA¶ iå „kpGMo¡:f­Pfþƒ÷k-/·¶ÿzº,÷s ƒÃiÚ<‹ˆí>fW6V—b2-;íãž7ƒ™^Qƒ¥(¨ã,ûín tu½¥uÐá@:a\cÂ8{ÆóÄ‹¨žÇª§§ êŒ*ˆáK¢qHî{+8Xh¿Q(hºÊ>%2§”8ùáÏj£«¦<Þ‡D$k„=¯“!# ÷óS¤@ù•]É(‘y ¶Ê—¾5ÙdÂ/"R¾iôGì%^ÂG‹ÍP`I®÷xFëî&ª>Œö]NÊuaf—[if06¼{q¯›j9§nšä1åa“§ì~5UC‘Ç’=© ‹¨Ñ}°/&V½UtƵfo]xB•Æ'•lM…º-£möþ2,BKZs\ì,y1™î£(¸ñr„îtݨÝKã¯Neš'Ý·Qlf²Ù§×&©Wˆª™™¢å÷óÂùKÚ¡ƒµefE°+ÓÝèÓuGM=¯(»tÊP›2î²í¶fôb×½Cކur­!oC¦(b·v^ø¹rí!2f‹¶)êp¼8¨‰B=…=WÁÍôz“£±6]Þ£TA´\ú^gg¢Â LoFômâø«·öÁ*–»i\èÏ$7©fKzq\º‰ÞÓ!ØäöTÂÕz™6þmM™SŸå² šÞXÌŒ±{ÑÂàì\’~‡zËyã·”¶YG9A‚ S]'°€Üýwù¨äNHn0q½>vp-MzçA Õ¹ÓתòG4(îú|…v4…$Ü©“4 OŠìïÑE?™E3y3j ´¡ØÆçÇ®·Ø!»êÿýL£Åëá½Ïf•ÍœOáÊ_D=É(#$6OÅøWâØ­ÐàÒ¹À>¶µÛH3+“LÅÚûywƤÑߺ  ÅÃiÉ­…HŠmIŠÅÔ‰&2˜¸ÌÅ+;†ýGÑ3_È3a0„zvâl׫¸zt0XŶŽÁß¶?ÉÉR™€î\DÌÅ;Ï™@ÑaŒÜG1¶M4Ói, þ$^h¦¤bf™ÆLÉ»GIàÒ.ërïo¢˜ìI1ƒ&†û¥„¼ëGC³5]ï#„°‹Š\µ9ׄ¨º-ûµT½þºy¼äšLqìˆ@‘™"8§Uøó3&Å5ŽéAÏÎãxÌö#—›tr8™Tšm-©ÒM “³55êÀë$äxœõáã²§¼ ˜ÔJL.…øÒÕm7Ë—š•I€’¡‚ý.T%mðfbé²G‚äïÔ×AÚn‰I¯ ©Gú|~Ïò¾ß4ð„ |ÿi|¨©‚Œþª®Ìó ?—ÐÿËúQõdûcA˜oö¬*Î×v‹ÅG›)zNÄÿÁÆcòá3µãÁÀL§×RfÚY±ýµlñ”åûô Å’ëý[@ÃTs”8 Ï ¥T/=gPÕ^H&!ëêñ’Žôl“Îe÷Ûæ¸ûUÿàÌÂ3¹áô_å­ŸâÖñsŸ­Ä©àU€=²\Od°¢ßkbå0±‰ÙhÌéyz‚ÃøD›köŸQ_—õÈ¡³MåÖøSˆ1 þv~ž|kz‰Ó?óCô0€{`Wá L)©ÿÖSþP p(‘?ã ¾GßèMðtƒ¨Ú¤ë_\®ÊÄJ¥ 愳ˆ€®PäwÂ)! ÿT¯w–T楠HúØU>²8„äe¶?h Ö~mcü’ä)^<ðóìŒ m(ox°8°-áP=3‰ ÷½‰ ÜÙ`tÃ3È X¼Þ«hÓ#ÙË3ÐÝŸÄŒ©•­»÷*åoã!Ó'ø}x{¿¡óåo Ÿ¯èîH·âî—«z»¥¾ßÇôqýfÃ^™›BfHÉ}z|š¨?¦Ó\·ôµºöÚéiÄC´bã¡üd鋽¦¾'ð“nöâwŒW¶î€÷Kå p€ÄAññ‰›#¾eHSÌtŒ/ú¾ß³ðØCé@Ì]¶B $žêXc— ý¯ÎJÚY`òï¤Ó$¿»¹ü4Yý.…êu­•¯ÙüÍL/…x–~5Úi)ý¦ú£ñ§m›k¯½3å=>ó粘qIŒ?Ûê¸X¢Í¿;ïTÒäÄß$@HJ-³Åâè„yƒ0…<+rçwCQ/]]ßâ@™(tk!Z¸ÑcI¹Ó 7ð›³è:Ç6K§ë{ºY,ÜwwŒ¾ž—ÕÔŨse2m¤®4½Œ•ŽSõ|6ô`†ì7wÐ+!è ‡LÍl1'R¸` ÿËË|:Q Ü vÎzS¦J™‰fgtœ{zÎÛ¿o“н§©0<ÜΗí”ëáŠ3ÈÏ2têõvãì!«õg°â/¡ÌPó_!õK׿§×ã¹WýWë•ü¥¸Ègé>:H>­ÍéìÜ‹¼?ˆi¤(?ŒP;BH”€?‘3@S!hhE€X…BšP¥ˆA(D¡ZQûˆbPT(¥(UàA ¦„`’‚_ÂP¤õóûdä¨+¾S À°ƒùˆÙýÿo÷EƒóVão¡Ê9z¼|’‘¾‡MèLðßbüºÇ:[-ÿê½$¾É]ädœÃ 2û½3²ÊÄ݉ýåwÒTÙúŽ¿áºðš)„ed›Ñ‰ò`ºÑÌA1$$:ç^ßœiޝKEd_Ë “D£Û–fbXýPf>ýŸxDdÍÜ3ëmÎ3a‡œ9âÁ»}M ·—–é4ŠCE~ IñÔãoc›ee§ÉÛÀnÇá}þ¯’\¾aÈï×êéÊð=h7Ãä m#:„y@~¡ˆ)d²ÒʲË?|F2gë{c䟟ézë­‚Á $Iœd #éùùš-Ðlê? 1Ýä³¶!É3b˜:xC+2fÌÈì½Àg¯™÷?40ú±¾&΀¶;÷sôhõhí³ 4úuÖj‘-ÐݤOŸYQc{KyöTÜyõ6žª›šÖøqvìå×»¶Ë¯ÔYèì¸üÕœ)¶- v Wôùøk7·NŒ)óÑíìÞƒìå6Õ·ÃÓ 5n_s^°;Лö/4Jé½…Ø$iκ7?:ÕÁŸE»ô›»þeõQ€ïL-œ*;]>ï£Ìwù¶^`î†Ð›~ªGl0¹5;=4ò›*SÈò£$vëìîý«ÔëÏÀvíýšE8524=&A!)ßdß~«_¬òþ#gšáÛ‚î”N¸>C^¥5ê0>éGóž¬~òG¾Ùóýré犽pÌJbß#nÛGk!®¬úËë”?Dþ;ûôÍóô&Ã]£ZTµ‚„ÄzÖ7æL ÷È??M“áóÞ3 JcZ´¶g2 *©7Ûbv0Ý"‚Ú‹&¡; “â«rXºð=é/O¸T@Êh”ðd÷ĆÉRwHuŒ¹½eò~9ñƒÛßš 9ð1üJÞéõØû –1æUdœäëOeÔ‡+©‹"D3M?RïGý_ñâÁ“}8ŽØdf…QBg…ÀdS™Ý‚v&ýÍKg»#â&ǤŒIݸ|±;€ ÌÃ@{¸€gûLõÝ'ƒŽœ¾šX ™K–P! K›µ° 1H=}ÝN¯¾ÈŸ« ›j¡æ÷Z–—ì¡w÷DË~²Ó†Š(£Ã‚ˆÉÔýRÌqð Ü–ý[çJU_ÄML‡@Ç>zFêú0F0 h¨¥ÇýQÒAú'MÃ.!ÃêåÔ°M0Ÿ¤žû9NÁÿŠEëÇ‹Ø7GkNeWêó2è»AT†ˆ|ñߪ‰§õzÿN èùt7P¬O† ¹‹©õŸ†~Y¤†GÁ4Z‰’"0ÁÏñÌCoú¶LþÌ_Íø1DUaûŽ/ʆ)$’@@Q ëúÚ±QZËáÓ¼€pÀ}î'ß%@üØèw§ÑFÞ•‹)Š^–tLj;ð·éº­¯Ñôqáµ­¶=AûП¿ÌRº9/AøÚ8G>B½ 2ù§ÚK¼ÞdGÛñ”d|E(BÐDx=À'Ã/ g²p!Aì)®­îU^J>@›z_\2§¡•fˆLÇ»%6žÔR“’åðú»åèNjóäT?îZ,ÈI’>‹Rc¿‚L‡º<|ÓãGñ­ÏY«îT0ßTÌ…!Á’°BñÁ3>3Âô=µžóÙaþ°r&·+úØ·©Ã€¼ì1î`ð¦+Ï„.Lß/˜+NG™ o“"BŒ…§3›õFað¸è¢‹±ˆþy»_°BPü[û‹ªM}àhÈO©ƒù~¼Ô{K¶ÉW‘þ˜ü¤7»&„úëÙóÃÃ˳tƘ¦óøÌ’ˆ¡l?åj»L1TI0ÌÑ‘-ÃŽLeFSIøîB‚?5š!©r°ÒÏò(Ë2°+K­“j8Õ;ûÊ/õ>¦~?ÝZötdéMBú¾f–öÌbucFy‘ƒD'®»J/³&Zþꇽ€a>F ™?-ýŸßPMU. ã院¢€á¥é!wlŠ€^¤3 ohŸÏ¶Åiþ•SèümZ,éÖ͈6p³Š7éS)îå}pÀyP÷Ü@s7®âù´~ÏíËãží±v€p!`^2ûþ«>ü0óø£_^v»)W±Ë1JTË??¿°ý;}ñåþa°‚èaî`<ѦÚ}Ñ, ‡›LÀɈÉ÷àþnBh‚‘$¨ 攡ª©ZÆâðÄìvýÆüdý¿û8ü"ÊŽEnxfH A´ü›ÚIyB„âtû/¶?’]Ì×íðÏ|E4P¿#$Nºó<Æg%U ðB˜« a²<" ‚•ÌÒ…Óþ\a¥Q"Æ0Ÿõ×o”Ø3`è\³„Yº¥‹900’Õ–0æÏÞô€ e ˆ°ü6•ݼ÷ð`'JýM&r8¡ŠDV6^D£ÅRË1e–PÐÔÖiáý0Cÿ$Ç¢¿wÕèÏfBâ8¾”áýŒ_ÕýºþU3øýdÒÒÜ“h,vÚRËHZ¸šµõ|$¤ü!‘% "°…$ÉDV´Ñb‘ Û5œ–Ë &‹ùµ‹Ìÿ\b<(ÆÄS%Ñ£3`2Ô©P« ê­À¼\ Ì~”Þ‚¨«.MsZ_ŽÀbaÑRtFDùDœÁ’u*Cóý’VúTÒ›AäØfƒ²†b ˆˆhoÇhÐKcOzê™ Øé:¨£TSz ÃVµ%|×m6_‹M¾:ÔU0<%€€ 2gye&¼(öºí5-m*#ðº†ì(N\ ®‚†6ƒ€ÍQ$éõÜÿ6Ÿè$þ«%jeàkþÞPB ÉÛE/Å6u_7—ÁŠÅEu›š Ù½ ÆçëHú”?ÙkST–¢@¤ C)œT0’ÒzƵ!^C¡]æØc:0ñâ8&ÿ,mØo³œòN¾ÜS$ÃŽ—XPÃ4øèýNó+'_õv¥QáI†ÎlY'!Ë©ý©²zð^Õ×|ʱ×Ï%›Ïoe鲪 D@þ?Ïùáí𸦯éž(öiØS ªÕÓjŒ"Ä6”¡¯Š>;n'Ÿß9eB,H!W0"bQˆäãTÀ-¨žj=•'˜»«ßóŸìšYõÚ§˜ö;äÂbºŽ˜K¢˜#9²ÀVÚÃØ8Ê`ÍX~ÆñxT.kP¤Y u.—[c~ïQ°ê( kŽ Çôä7Á%þè!Øð†!¤ð"ª qŠ6&#&¦$©‚‘ô}BâÈ'Zná+²/È?†¾¡S¢SíYàÇóFP÷ãö`Q@Ö®I!Âþ›õIJüV¤‰ù¤Â_å/Ó!ù£øú1|q–l¨(}/[”‘B1¤;¬Ÿä››Û7µG|Ò§Æ­b™a!’vF"¡}Jh5ˆ?Â]‘rËæ•!ý¼naàÏØzêR O²k•ݘ‘DÄ×òàö}ç«îz7ŸZ“‰@.x’Ž3¹*Ñ*þй5Í$ô÷^]RèïºOìŸv9“W»èÞñÛãûÌ\1".#£™Ï æOåþä‚ÑŒÕn }oQñ ·å"ƒ±s”?LŸ¶{=˜~Ÿ_IQJˆô Yøàu*½ Y?Ç»ö¶F–Ū§+ 4ïYC¼‡æ5}Û¥Ö³0§"à%«Ú­.A û„ÛÇã©É"Å÷Lqµ&ÿ8•8‡¤ -YÚßçÇÒ0ÅÑZÛ¡ÈÆKhÜýzdä†ÿ‚”ôã 0$YêõAŒ\Qx-6—ãMzïåÁ¾„^EÌ¥¹-¦I"N@æn?‹€Ï[Ÿ‡Ñ­1ƒã§ÞÈ÷é…Ez$Ü1ïÖP§¡\ùÀú>Ð̆øƒ^èQ6UO*©NÀõë¢B¿B…ý~Þzu…£3´}Ànî÷sí[½ýØA Äq­v&øÏàBž_6÷ŒÑAßÙÍ‹GäË“q(av|ECuŒÎᆭ±`‰Ìî…Þ•ÛtaJ]?&‚¢£`Ößh‚*•rã½H31š(8¢G‹}G·øþÞÇÕ÷pNŠ7ACN^AßÄsH‹6¤¢†Pãí@¹Ýþ !©€ æ™åö9A^= ùhM¿_âv»™Ü™qwhHŸ=ÿ´í{÷aä_A&¿߯"q¬¬ÈÌÍ“ì”ço²ƒÐÃÝö}±J‹MUU+YÆSNhÐä «÷ŸÐæª7Øâa>Ò§M›aq0r J·€#»§fƒã'ÉâdˆtŸèíú[Dã†8`ÔqÿS3ŒbÉd«§Çúxˆª"*ÅDE ¶O JB‡öxyvÀ\ÿ8§RßWÕ$AØW2?®«b4z`¢|ú»OÉDÈ»ÄÏ ×*ôy°TÈ$# Jb^¼p»3¨`*še„üCïØÆÙóìC¤oÍØGÊŠ&È€ ¿„9¹ëÙ{|ìyцY~cEó¸ ;ª¤?dÉgA†ŠC1¢i ?bíÚ^Wa'ëéU%bŽÎ½¶7KJc» € aã3 þdLÔN•_ÄÚ˜2ø„ùeõøQ÷h‚"Q d¨XþÑÃÊÑú_>”ò¶ŒåAâw§v X5çúW×ZÌ!‚XTï(Å“ü˜êØÚÃñúªˆ‚×åôOÛùl¤é5µSÌÌË–ävÜÇb.~Œitø§ê.Ÿx˜£’ ÷!Hx@B±GôÕH+¨ýÕPº{.›bÓ[œ_¦A  }°ß‘'<Ãà0¤;x";Pu©z@8¯„÷öxòÎo1ݲ&’†k‡q˜²Û•YŠf"ÌÅœoà„ÌØ€Ñ,\Ø®>~@RŒiú|½ÅhH}EÈÿâÍŸ›êÖ|MvÒieM"w ××½6¾Ñ=Sj„ ×/´vjåó€èI›o›Í²Ã|(6#Eƽ5k#ÐÝc”!ªa&Ô8Æä#À¨`ÉS(°1(çÎY;³<ô ’eÑÚÌG|¦”Òq„ýçã·Îuý®ö{Ï·zÈ~HöÔ¾côDLB“4”Ò5Œ‚L’¤ƒ¨6¶Œo§ÃÜkôÑŽëÜU¬‘)!¼è}õ0ínñVú.À6a• þÄ?ƒ Ha‚„Pˆ8þü4ë2r„á‡ÙÉÄä¾”3„ÿ¬¿,ìûn¿™t¢#Rª+Ç®?‡š…D¤¦„­¶µ¦Õ55QTUEÁü<£FSº Åb1@?„ã>æ²ÿë“1ELКºÞ_lXØ9•B|?-²&¢ZR“¬ù×ýb5j!ð b*9À©» ¢c÷£ùãèGo©w/hxeÝ—?"Úy [T¿µ†~0-‡8Œ'âñ'«]î˜Ï= [Ú­'÷¾“ù}›‡/¾~¦X©Jmó|˜—–¥eU]ïb’*’H&…NwWõÿg·—’¿U@æ·ƒmüÿÎ:ɵM·£ºf/$8¨%ÑL‹mϱ©à€pzC‡ô¿“Z8þZ噬Úݘ!ݲþñ6C0tcàIATÜ>½1‚·©ëg’ye¢£Ã…gëKd<š2æÁÁóÀýß_ä~?1XJ.­¬T”4…¤H™•/-*&RMJHb”¦d™§'¿ŸPDp6jvk QºžÇ¾»Ý£†?ª@ïçYµM‰Æ(å­Èæ lUjŠ‹EE mª*8ͨ]nm$ðÆpQc83ŒSŒTäŒU­üÜÇ wóg‘ˆåÁ„)Ûj†( ªØÍŒcNa–1¨ÒkF´VER[%ý§Ž‡‘ä' Óˆ¿˜Èê„ì\Éÿƒ¸®ØŠ„öAž8 ’_0r) €š€£l0‰ÊÌL•5=û¼4u´dÙ%à‹UŽ-HgÌQõ…Ös³I¢Å~ñ4,tÂ8½Øscãdp%ÂE<çû¶Û„ãpÂ~ïË÷üÀð>ã¤=.ï“=‰~¸ì ÷ª¦2‰wGùÐ߉rΕP “Ø'q‹ïTA߉oÃ|X †½æøl“pñŒ”â€tÓ3F’lÔNEiÐßgß äÌoáÌî!ÈtFò"¸òÿNãáâLE[º5­)°“ØÞ:Íã•øKíÞÕž²VèÅœñøýóãÿ¾À³àÉÖúg¥AQ&(ha©ŽïÙÅWÔšø}~_Ýû×þ“ŠôÍa(MC’ƒîÐF(° d6Ï£}x†~ H,Rä²-!9²­j¦ŠÎr²U¬ãŒ¬`Åáw7Uœ`¤\Ù¦Úíµ}\J ©RjJgûÓš£¥cì̆²Ë¾?ú_G¡Äߨåú((zÐ?씃l°nØE³l]±rÃa4ˆ‚Á¿õÌ>ß®ù!ÖŸ[4ËU¦Æ6ÅЊFLa%j)áþlçõò6ZQ šƒ†lT•n€wÊ¡½ƒÂSq¤àpuËp J÷Ú{ö@øé+æ|ñêä {”˜ Ó¦¸b›÷6†vÁ1”óóXÉÁw«Œ=8»CÇÄ$ˆšŸÖ‹3&F.—ս’nÒQ‰Çð$Ppcú"é×Ï®0ßë{^{"KçQÎQj\{WÔ¿<3Óü¤ ¿ml}!Êßáù’ÕJ?‚ª³åö ˜ß½§ü(cÚ|Å÷ûþÿÆë¿Â½Q)Ð~ÿü šuÃë¼Ó|¾©×IòûG3$S õˆ;£™¤Íçb'#"Ÿû¬Hÿßÿ¿ÿVi?÷ÁÌùø7þ#÷{Ñ@¤îüµ1~¦àv\ÅQ„Á£*ë?ªbÂb満›¶‘•A(AúzlH“ýN7mÿ·æHÚa±¾ºû¿ð¿ô#êÓL1”Ƶ˜ àv´ÍwplìÕUwþƒ±ŒbÕ Š™ª)Šªª(*¦¨¦¨ê‘Úeô߬_¯õüøšBcâídø=¦ò̇þV¦ !¥e,þ4ïøÉ*³¼a“ƒ¼%NŸ5Û½@°ôVI¨ (zLÇ(U9¹‚ö/ûÞ}ÿ»mg†É ÿ{Ì6õ‚#ûSü¡òö¾/Pêíô¶™•ìeŸ‹P²óV–P3IÝÿ£µða¾ì¬·úÙò}ûêP?Ñ&— Ã)‰8ýFL?¿½—é¥Lò0ym÷ü=âÜfö¡óÐ̰mðgtÙ›_EmÈà™½3ϯ?On.¡E¡“m4Æž~ú6j§„IɆV,Â5ýÑÕçü™”¡\€Ñÿ\—‹ÙöFà寅»†unëECòò?$OÈØ\tå±hÀ…³zQ ÐÚÀÁÚ&>gf³©Æ©|ð›m¯_å»$éžozÿ,’õÅlOÀ!÷™øëüeåËòã¶ÑÝÝç4+Á÷¸[Æíüq}"c_«Óꈨ8N;ivЈ;nDý.:И‚]æwÎGš:B#×öšÁCÂWóCØ”Y›rbº˜pfƒŸN¯o{56¡5%J™£ÒS0P[Qè,"•í´dùÑë+£N†³póiƒQ­†d$Õòº#u1|&P0€`ó°Ý¤˜)ÛG²fâ7>—nr”è2wÞŠ E0f*B;»Í‘ëGS×ôw¼ê!nŠoÆM„m*h1©$è;——4-MÔ‹–®ôx¼å²|8âÑ*]ø¿U¸ Cí ꓊@w}˜ì¼u‚{Ma•Ýï“ø(Æ._'M0„lj;îi³gqÊ¥ V‡éòy·ìp«BLõõtãäøü1_t¾¸w?)Ÿ¾&È!n9)»$AÝš„£¶×HËa Á¾Öï©ê^†¯d3t"äÆ(î禮‘Ðr äçˆr:!Ì xiN s 0sC¶,´8V8o„S ½p¦%Q7á¾S1²×f@™š±Ú:Ò<“Íäy¼ó*¸Åè!ížûÃÀÇÇ"1˜& f€†leÅŽåp¢Þ²í i™«¹ rf3Udc –¡dXÜZù³R"ôÁ}ÏuׯéÅ®g€“1L¨¦ÉPçIWÅA¨¤ƒõ ó…Ͼ»4¬t£HË÷ÎÆôÜ0r‰Ü;?.뿪ÁH?ŸÇ?úu1PªC¸ð׫o1é·¶e­‡Îi–om1XVH…C³4Aêvš³PÐo„ÿ/Öò±†÷QêõóV­SúV‚ÀÏÏͯ^àB@‚vYDèL=Wì_:^mR†þ5è9šba0:1ßóx‹¬‚÷iãê5Îgý<ÄŠôyÔæ¤súLä<Ͼ1K¬y ¥÷ç³›hS'×*ÿŸ­Óg€Q U#>ÔìÍ9û FÇgEr1ƒˆ©@Q½ÿ4ÃýPþŸÂqÿÚ“ÊÍKÿãþi9·Ì¡§7N]BºyÅ‘ ®üò·ÿN¢ ù³úýççÃöuõØÆ¬œ&¡û¶V}÷ÿ¯÷9fTVjÙoK„ý$% Åö“˜é‡úÓaÂÓIt?«ÓöM«ý5Ù¶Àü[rF¸»ãÕ šyüsËO·nø8ݽF;sŽÿ}Öõ‚aâë¨G­™³1™‹ï;ýCWý….8Ç?íô;|þ¥“VÎó¸ÿã¶&cÿ׌[µ{V³¼*Y/Ñÿ“–{·?;sÚ}M.<Ü¥"uCs6L †ùkøxuFAüáÖßú7êü:þºJ¡ÔÿéÆ?³ãP›×¿ò>ÎE͹ˆSÉîi£ÓaoSÏžÎø7»±ß×…ØYjïöUM4òvÊÚ\ûi–¥ü4é_†?§õ{Éáœ÷z/Ë0Âz=§\\üja‹h§sðmg#Œyºh |•ŸßÇÝ|¥áÀ3¨”ÞK)4A I¤Cš\»H]K–V‡—† Ò'[q¹uk:a«E<Уn¿ûYŽèJºË ©tï‘ýÝ=zbKlõä¬þêMõaWè+)Cõµ4]ÛÛO2*Àu|`Ó“±uÔnRb„‹w—d!ku5k°éC¤Gvç %vö×"‘sòN’H2I䎣Ñ2Y41óHáÓwËØÙhqwcã}SÇÅyï‡âaGbdîÒöú®T@v“'®ÊxÑ[2Uûëé4š¯$!$ɰ@#ÜíTEä’),tþêÿ­};^ñI‚[)Ikaöçôzý#ý§à.©ý‚þìZSjù|¿Ô³U–—5õmÑ-&l}™ß—G¼D ZJ$X¡àp¶p`>Y˜‘*DÌ 7â&ߪ.˜¨#ÑTÚ(’æ]”F‰õµÅíz!Ôx•íjnf…: f7æó:úð N{ö»§2œb)›ÍdµsµNAQpxl5¡²„!0&Î'‡ƒF‰(翯®w\õ÷y|÷UlßB:nÊŠ[n LõnËA}—=¶Û[>÷€Cw~óö•TU[œLJ©"ôÍÀdkÖž™:I¸MËûü1¼°ÁÇ–®6——$¢ÖZÔJ$ˆˆ]U©¥5UWXT±ÙA“"×Ýü…7$8¡ÇãÓÓoŽkÄÜ‹PÔL ó$ÓÔ -V²îå¬kXÁ3/“’y‚¢‡œacÊ!õ0£YŒj¦5:Öƒ&ÛŒ²Q.YzMåf#Ic¹¡S#¥J)¼ÖÂE¨èQvS43«¶Ã©¨ÍhŠ=Fj¶²5ˆs—{º˜¤Qãhd4 EÕÅ"‚D–!KÄ8 a $!)C4³I#€Ä(q4IY¢î½V=MÞûà§:3 QH‡€D,'QSQ1UÀÑD…Ø)ª‰HÁîè@PðóÌjÞsiÄG"ˆ ‘‰BBF¡Š(¨ ªôW¢½诂¼ðð#yÇ×w{º˜ˆˆ…!¦ˆŒÉb1H´êdLU1c¤4%Š{OSpçÃ_’œëYZP»$㣲p¢˜B9êIò‡2ÿœx“ã{L±¼b[ªyù<>‡'ºjBSŠ&™0´…9J­îR¡åÖg{Îòp6¶—Zñ^¯†ÊѸÄq"±µ]i(Ò£Cò¢I]BjÒÒÀUUUJ¥‚Y]MT!!LB•ƒP±Ž¢"#Zb ˆˆˆ›£†;Ë™%bƒšá\sˆp'”`®W Ãßÿ\³Ó&â‹Â“ÿO¦G.° ¤HC!“|ž5û Þ¢÷'F‡v£ên2jøùªŒòòÕâ‹eF„Ëæ:Jj»ûÏÒÍnÅ "‡ëÛM±‘4Oqä1rm¤ÓDâ¡ç£& È[aA‘¢[pQè+¬uVºÔVŒ‚Ýiukñ¥\øxë¢dOÑÀÂjñ@CŒæfÁK–YDÅCÁ‡(Ä E'ƒC†MÔDŒK: ¸ÓÏ<É,šö9ë­è^Ûî­Ð$t”ƒ,HQ¦.a¨XZQÔd32G¨[¸g@ÈfäÜÄ­«$1a5@ààóSÊdye¹$0ÒqèI“-Pv!š£B)žÒríFÏn[gI¹Ê¿@*Ü\­y1׬z™î`Áz8P¸4L–1LB¢Œ"ŠVò%‘XÃ"¸g$2[Y”D¼å{ÄÄ·w1±Ê¶>CòCÑG2”zØ=¾ÐÇ&þÃàg6Bd­fØ6좙¬ÙüÏLŠt‡qêÃbü5qeg!^Áôv4˜œ=¿º¦Svw„µ7ö>s ð7S›°L¤eì˜q!ÂA C‡ ·Ã¨K͘j änå•-ÌPšxlÙ? ²GvÐþÍeÖˆb†$`2z;ì¹ì1¶Ô²å¼YjÊÓbÆÏ_Liz,CÞ{ôö¼B´e† ÈÒ‡¡‚LŒ‡aDÑç5måªP™Ù5Š7“%?Õ]DîÝ6[Ôä¢fõª«×|ÍL"Yµ`B¦±À˜0L] e¥Ÿ.Ç£Ú³$?ê-H¦„ ¤;8sûÊ 4/ã¦u¾idÓ¾{jŸií×ÿI†U…Îzx‚³Dˆ™%Ñþ½ÒŽîmüh×MŸmÍcüú¼uC^ae™qU½“†öM³|<`ìïÏÂ$+}Ú¯ë@’rG H“°q;î:$MœݵÑöTÉ6½,H@W=<ÿìªÍïM`üíÎØð?ëÿ"@ŒK½dâÖ—÷Ú…ÐÖÁôì„Ó'«* #'âÞ=eã¢ü-&sTÂÏ AB x7}®zyÓC#ígYxXÁv«h"ÅgúÒÄKÀó7Fê0º‘¼ívíç7tròOTÝrÞiÒÀiBa0’5ðžÌôÕE ÈH9‘ÒX‚°Ú\Z\ÌlÔagù¯.›ƒ)™ßwÙ«Ìÿù[•ó<ÞQö;o‘ò§Ä3~šÜHÕkãåöûªÎ÷¾š¾¹gAõ¿eF´ž8ÒåѧMªŸjßC55-„ªÙ—B§ÓµêTuT]ZÎb\GnxjâñÂî˜C³¢ÍÕ5s’xïKJ8m»ï/î.¸iSînÊ잯£8mã·»’g‰Ðß}ñ7o¼ÿyÝÈGÞÕ4¾ÀWjJo^R½@ ä+¹ê]Ç@qQÞ.ãâ õ Ø`¨cÀ1 n€ 05Ÿ[]ÄÞ“á>æ³Î÷ÅGlkXã¶òW:íl¸ë|ï|Å×QÔ×9çRºÞk¶qoˆÇp뉼‹×n9—ž2^$ë›Ìâø¥Ö&9¾kQÖ#}a_³œÌ•”" ~Èl¡5™Yù—wF“aº“ôÍÓÛ?ÚïÛéÌúÿ~L-צºÔãÑý= å9;én s9-B4Cãq %•: Š0pjb©G }z6¸5Øv·xäç[ABµÆ9s´Ô‘d²ËÚÀ.aø3ŽÆ&¯–4B鵫]r£ {cžhiXçxßdärlŽÈˆŽz‹8ëw$ÀVz©¯CRÐYµyÖàE:o9U®ûbÎ ¥“’Z· _2u£]ŸX]´ZÐVÖøÀkµðl•Á¡.Ñ-ð·œs¹¶h¾q$•’(…VRÏÐ…r£wÞÚFúÊ42Ù—”ñÊm„!yÇð%ÕÕF˜¹±„ýi‡^lðí­¬j‡|·"ñ€ãFlìÓðŽŠØÞÍáÉ¥#§¸â–hŒ@>¤ÿâu‡Ò1`ÂÅ’´Ö¨úþмw÷ç8º$¤´—³Le†,Å2$18ç¦f½Äfl0+‚[ÊJË `ÓáÜh+,iõCÉËÇ‘óîæ(„yY¤ HB-UÝæfc3µÃMO×›Ü µ³©ûóø7z»z³Ãä_÷Ì’Œ… @äd-€þÈüB´»÷°ŠvIÙZ¢‘F´¸œ’š^Jp¨^N ]4ˆ}n@R‚SIÂR€h4ÅBƒ¡ÒÐ)@™™ûã5’d•ÿgóÿ'VÝqÓ# ÆÔ‘þ¸?ñýSYRj½‡$ çp$àM¿“Z™ƒ÷XÔ¦øLëÅÁ–Œ« Q¡–¿EXöæHi’€Cè@Ë&Œ Œ<º¢Â£3ELÄ×ʾô®_銒`Õ‚òHÀt,ü_ÌœÚ×`4({‡ù·2P (¨B¯Û‚Àþ’0?!’˜¶RÆ7e×+Žyb÷h¢h YCÙè ?D†âSD‡Œh˜€ä¦ @÷<…µ`O¤ªãdO%8D(1§Ïާ‰’þ°Û¸G0sçs‚{”JÓBs`Bºˆ hø.CÉHìŽ@í îaÝQJ;H1yR¥Çpq$ztf¥ ·ÉØÀ#•+¨^2® 9JJÅ@U2 yÈrQÔØ€?êÂtƒÒ_ '!Ô.Ïxe=›È}äM“ xéòÛI˜ù-想ÿk×çíÜý™tj²4­–öÇQu¼“©ŒÖÿíŽßûñOA˜|NJo »”ÈBeo†Nî9gAg/<»ž¤?#b16 &3„KÓ Š^ˆ”™E+É¿³¸?ÈþÚ?"!þVÓå ݃üƒê@FËuyWàáp™è¤ÊÖÀ׃šà½/û´àÖÓSOW±¸BçfC»7$ZõüÙŸj™›p.NáÑ8&£4;wzoèM²ÎÌÇÀ#Ú—,Å.>‚¡-$³ç¢èj:V‡ÝGØ ð×Ñ~Àô†y˜Æ!Ìu±C3h¤6ªIš èjí€Pe Q_- Sƒ ænñî¶ùIšÏo¥ÙÓ%æ*tiµp€ 0ê'),¸=;eÌD„ˆ%‚v·@ö‘õïw¾?SÈ8ÔºVŽ ŠNÍ‹lfJaKÄ n8Bçñ¤&A‘ÍÁh[ÃÐ'»C¾£.¢qÌç\úC'4Ï<Óh®mÄi£Àõ4uwšŒ@tG3,¤\—u!êÓÓr´¼BQjèïÐ|ºj÷ Ûžg!¸Üñc§qðK•‹_FéYÞg…Å?g¡n5ºlY®oœ½ºËû Â¥Ïx 7]ÚM í^Ç‘™ÕyŒ®ú §yæã^¹T_o€ÔS:Î9›‹µž¾T]Å$_ixø¯:ùÁ`_9¼Ökv”ïßøŸgš¶ò¯Rùœ[(íá½MîáúÞ“ñéã·[»œVâ»O5|ó¬íó§Ûõ§È‰\)EÄê-¼ÛUF°~¨<÷æ>Šd§'"Ï)¼¼÷> êè1Ò°=àžðûg¶]}Ñû0'Õ¤èUùS2a¸lèÇŸšPG'ëVuÁž cëWpü}w¥XñLTócƒ˜œ®·Øâ¾¦> Ìáï´œ!hr†:3¦–æã77ýg¥± »mjN¬îA”D ñÕÀìßß}Ò–ž°¬&FŠ,1]A±êeàZcn×8ðј_é~žç\z ÊçJ#ß»LËûqïW¿DÝã o—¥Á*&êÞ‰íÌã§t­ß®ÓßêÞ<ã¦Ô¬¸6úÆš u=Qƒ”ÇÝ: › FÍSÁQBu/N¢Ê“Š÷oïnvû'ÓÛ¶öPüjLŒJÅͬÅÒ( pØýGiúO·-“wþ\ v8J ÷†íüx§ÂA³ Ggÿ\ý›±s1d’¿Yç1]Jî£ÿ#FˆÀ€kÿYõkúßþ¬B$9uPòisÿ¸#ßèóF40À~ÔÀ°Œ6ÄÃð“Éè=)ïùŽzÐKŽ FC†,&aÁ‰ÙƒC4 ¸H3;˜+’œP×nmŒ´mý?ä%þˆP‰\/ô=ßåýBüƒ€mäuuÎö(b¾ÑOï"'ùŸÁ<åþÁäýY¨:0U@Ý!$>ÔÆIC6GÄÜ«IHÃHLÄ+5”¤Ñ#0%PTRA)"­Û¿ñ׺=|PTBþK§ã§ùn¿—vüoÓ¿”¼ž˜„èzð&O›1"JhÛ Ç`þCòl‡Á0+4%2È HÄ& ²Í’u¯SDžflÅ"À¿°“aÞ«Ù`Ä3!þ€hyœ¡Çˆúê©÷ž’òž ®Ðîd¥›]B,û¡*tÔ”w>oäžüïÐmZÛGl¹žNÛŠ7mŠˆ8½7îÖÈ!ä~=£ÒÿÎÏ£óòÜ`IÏþârÀ’ÃâÂoåDQ2DÄi×hÓCSða"UFŸŽÜNVÀ‚S0,RP%Eªpº8{twˆû@åü ù‰+ Bè#.áôÜûÇ£¨ 02" ª’„Da)©‹c«wý‰ õz=ÀÄ AœÁèü0iÑúG¤4ü‹¹ aذ•‡% UM.MK0ªxˆUhºZ ˆS!™É¨„ TnqK=`–Xáﬡ¤L ¸ÛÃB4p·[–3ŽØK•“…“€É­PR [Sïˆ+ÒQì!cã‡ð&‰†AÕ &´eK§rd¨m‰DtuYv)u9‚ÖˆxLâlaðCŸ1#PèŌۻ«ÅМ”ÂHT²c.é‘ojÅlA çdî½’b}ø{¤óÔ§4¾Œ; ›š¸c Ÿ)‚˜Ã¬àÌW&(vrdiŠæsÔ\‚ô+€\FªK¦ÄÚKiBnÕÌqE‘E˧yîô1È1T‘A 4DG¯^¡@5 ;'‚ALÌ`ïNËŒlª°@äʲÃõ^m¯viÒ©bDÖÅ@òÙeP’"|O7Ècw€èu¶DBDEE!@TCß¡q—˜Ö vôX>6( q²R[ÕP0X ÅZÕµ±ªÑIáíÇ¿˜áàGR lºá›d¢$Ù-—“LgX6Ì0Mˆç(¤¦Æ’o†jÊ7ÍÙ„ÒܓۘI’ÎY¦Y®¦ 7EÃÐT T’NÁÓTðÄÂ*·‚&jfq©,U@Öñ€«°³–%ÎŽF7ˆÆ›hÊI)À“‚M +8ÓGMV&°Ð!Š'jqLV1f¦F pÒHtaLô»8æns…l&Šó¼áØbéØ=CÉ ´Â>!8UØíTKžV³’‘&¢‰µ^£ ]3ŒÖ™pÁW%;°æ.¶©‚ ˜`=}ªïaã€sÎn"p}þ‚ËíÉœÿ¹ &˜éÎÝý%{Gžâ’DŒ@„#Œ#‚3„.?d³èÅÉ(ð-Hh 6—R&Š¿t:”Ô»N¦t`L)”‡€„»€Í@wœçM³ÁËøO—ˆ¿ÅãOöÊ ÑØ’}Ï$Òs‘œë_×*ò:h6Â~±NãÎøvw_Ç'®8ìg€fFDšŠ&"¨b/vнl·Ÿ,`ªªÅè\t€ã¹pç-ÉѸ›×ë“–w‡ÇØy¼Œ N5rI³.1bš£pÂÐÞðýé'Gaõ:BŸÝ—@üÊF ôC} £¸pÖ¯n躤B¼k!ó/›ö8q7Ûó Ð x(—VÑÀæ'Šï6Ë{þ™P>ˆ0‰ó¤òò*OJ¡~UŠ1W dóg¨ÄÄzPè®÷¥ÆB M-ÛT‘LŒQ-ª&¤¯®ÊD„A1Søúç /x1p· bd ’ h–1sd‰¨‰×’<& ª«!b§DDCNë £]<Œ‡S/£X‘DúKz§÷ÀÉ$Á¦ t.´ó¤ !þpp?ë£ú" þ(©BFÉŠ¨ Hi"F¡ Ø}C¯Ö@ªñTî_àÛ°'(¢„:ŸYˆqI“xh`új|(òrâ"ÃF$CÒ™í®piA’ý?gQƒÏ¥#™‚öÐ?\ 3æÏì!’¼”jó òúN!J@Ð¥G¸}}âàxA»<â{Ä™=ËC@BåR—eVD¶3܃E`*„¿Ù¡t_ êÇ‘ÓyÎ+¿Õ.ò3‰îíéÜ8‘/!t H[ÔÄ &à€ pyÃ‡¨?.‡°€ç+„A#SD^µä¼ñ<¥öÆA£aüMÛd‰Â2 ^ÐÄÔ€DM ñ€¢”6® ¬2NÑÁà3à/€i¶†bKÑsx[þcXÍtqÔ.CýJcˆ‚κæëÛE‚0†‘ £Bž~†Þ&O¼ÌH‚©C‰d=™€ÒбÕþÄz¶@Á%Ofô<;€C+Í$á“ZÂ~ùx@Y†Ú†ad4a”Qa'¥ H~“=ƒ†ó¯œDCë_>lä%TAˆ ø…†”‚ &ˆ^äsÄ !y—_·Œp#À¡#ƒ‰Í°rX€i+¼åÛ]ï ™Žs ödTµûˆ„œ¿¹^¼Ü¤8$£!€âñGŠ9UDÐOØEõðò(H ‰B`b(Dõ_9BvÝðxýÜßÎíâûä.´Åî“Q¨ñ͆ÌCØû9mÞm¾ŽH¥(÷È¡Õ*RИ¤ñ”M)øØ¢‡¤~R…rÌ»´jSÞG-Áçÿ_’<Nˆè”)¥ú ¡™f” …@^Æ܈Ϫ) ¤¦/±~¿ßm¸â~ã½ëEiCÖ)ÑÆ¦Ø5b-湚ÓÆÓ›Ðã30MÍd:©ªÅR–°&àéÉýèÀ¡¡šD¨~¤(hOQˣѰɼNgíóžpº§ÌïĪî~óv¨;bî²ú;ŽÇ¬VO=a<¦åD0šk(P!Ûæ”N¿'œª(|˜8”[mSŒSoÒ EÓ)‰CVáÐJeô¸c*DI-RÁ áO~´ï€Ë“ÑѶ«’eÕÊÕÕ©UÝDõ‰Ô½Ç/wWHÆ‘Ì/»JØûN9¨#Ã\t›Õ©dM=G¨K’(Ð!©à¡PÀ0};©Iæ1öŽ’œ$èç=‡Þ\aÚ(£æéÃdÌ´â±%RHÄŒ|NyèÁò°ù»eƒ§™4 …!J*L%µŒçJfCF2PRiÓŠ‡Ws‚ û ÉíHâ Ú`Š•fA ¡¦‰¡X}qOÜ2 (³ÐAP²‰„¢n¨õö'NB@:GÂÐFÐ:%; Ö±Q@ü7Ÿ Î%f&ADµ*õ Z”©NÝ1 ëa®“nc ð¤(¥!ó÷ú,´NFŒé1P(Z26   JEñ³§A#¥©ç8‡Tïzhh‰ä›55œjõÎ?(9>¶é£F5DFƒß2×çŒ%ÅSULðd¿æÊŒ\éRXÅLÐn_8Ü-E¶Æáѻڬœ Ç \n 8"»tî¶“mÜc†Å7!ç;höŸ‹®æÌÚmDÇõp/|ÍEÎQmÄeêA¥Òü<òû„öšºÌíåµ¶ET®Ù©¨|jëMj­¤â«+S*x„%4ƒ×’‘Z|’Äκ©•Œ0QJß&ñ$&ì^+’Ú"T×Ú…™’±>F’(ÚÜKQäi®UÖlY‹OQ‰Øz–PŠ«‚ —‡z˜ 2CMÏ$fPì‡tÙ(mHÓÛ˜Ö‡bØ‘==8?>—¼O_OsîÀ €’Ø3d4i:1A¤ûpÝ‹¬‡rçìHZÆ‘šX 7y')Ö°Šš‘BG€Ò•’*J¡ÂÙÊs21M(Z¥OŽfÔÕÆ\‘¥'8"NE¸µ&kj¬!±À™#Èàv ±>óìóf.Cº~Ç®œBRšàb59Ì™ÓBäV Ý(±(æá…˜Q&0µ˜bñeâ!£MK²êÒv1ÝÉ}GZ#ÈÕæêsÍ<êÖp±K—5VÝ5š‘%²Zkzˆ‰‰Ê´1šÅ‰`­dPBU([—õ§)’?ì ›ÕÖ( ‰f$ŸU®½q[Þ1{gt—ìâ¼àf%Pº…‚˜Š0¾0 qª¢­n¯ÝrfÛ¦˜”:„eT€ó$ÔТ&f©ÚQ* vµE:k{258EEb˜™w¢”´ÏIF*mËY6 $ÕâT¢Òµ:€z… ­ab_ áâIC5T¦†6½)åBô鯮xb†®6¤E„ àJ¸Bîâìc­¼»È§ƒP±A 4RÌ\FTá!Ä6Œ•¡VêQð‘¡¥(š”JD¢‘¦‚”¡ã©²zÇzôf'5…ÁÐz×ë±R–öTœÑï^ÂBH9ë¬6ëÀ×ì{P>E=[¹z·4D°¹Ü}Ä0ȵ†€ëí‹èLNù>­`š=È¡áž(z ϘMal'‡Ïáé1#ø“£wÔGÏ·Wƒ«) AJº—S­ñŒE´X,V¡D¨ÁU*VìqºÈãh{=ÊmêÃu%Q¬Ç§ø{?[æôÈ%ÿ»òOëïŸÛ=Rƒßleyo9ÍÌæ„ädÎwåæ3¨ŸîÀ >b±ÿk $Ð3r~KŒ¬”gƒöÙº½?f <Š2†f®|ÛF½ßÏÂî?;½Å]ˆG3$* —>'eQ]™™K*º / 2¶¬˜ß”u–LaÉAîy†‘¾,ì`ìH³Cœk wIœà Öíz&—¡Ë]Àv%' q1BÒô7èþ8î­ÙÚ`ñ÷/Ù9 Þ¼0&©¤oùÎBJhgT&BqáAÃ:€.?íâìÀôôÈè·Ïý¡0AÙÛÂÍœwl‡àÈkޝ®¹ôsEX¸sà¯ÔƒÃ÷¾n:D;ç3ldâ]5éty¡=(§ )3á†x\ûz§ƒÞáú^ƆaSÀ CEº>q/sZ‰½GwŸ®y²DM¢Sæ›t³¤B·j©,ÔàÀa µ#é°ÿ,4›Dˆzo&íœ9Ý1E𠘯QÊZó£]¨§ÒLœÝ;Ïc‚°:Ã×î/‡Ãˆ6ûƒë~§{½…9œGG¬Œƒ1éIÓû4†APdÂXcžånmÞu­Œ “oi´™Aº›˜ÅPüñ~[…ì|éf£2ò™;ºàá)eox™¸&%o¸õ[´÷ðÜ9K”Zãïˆ<)\MÂê8ŒÈæMR>•hËÝI J13à‘*Œ>ÇP)èÚ˜_ýÎÔOXÔ|+žZúÓ “|ö§}s¥=›Ùøôåå*Oeê=>8®qâ§ "0œî¦óðµ›ñ>!kKtuóxºÃÒ ·B(Nï*áùpy¼ö¢ |DÞï›É©‰R®g…pÇ ×–º¸.ýa ïa>GÔ† h¦fÅ´÷æÚ‘ØËÞ9ìõý2(úaúÃëÿÖnOâ‘Hx/€È÷v‡?W·Ïëϱ⟠¾Cç´1ÔæÎ¸‡Êéöxn_Ù%W®Èoñ-"+Òã7/ÉÐÐ$ú`ôÿPz—ã¼?Yëè4'èðÅwñÉFýç”Ü^2¡  h^FJ… ª‰ ")¬1 ùs‰ÙÓÕ’¥M†£‘’“ôÓš@O‰]IB}/%r@ˆ¢¦Ñ d–’Ø`dŒtÔ(Æ,Ó%¥ÿÉèÙ43Ú²ÝÏá’qttùdHÁ 8P9FCÔð5²þyˆ‡œíaâÓMûü]^/äK¢ã¶ÙÙÙÓùê:%ÿ ÄwÕU7Nšn=‚Ë…ÛY§aìîÙF ÓØîÞ·éÊIa‡B÷øß `òòº\ÞYN,Ajzk€"ÅLýeã_ÝOWé4½Ì¹‡…&xˆ¾±ç˜÷ÐCa$Ðæaqå]qÖwÄö:ï"¦ñ£I~Ô²D@&€Pâ¡EζMqwÚͳ;^7^°3,_~Ξïåû¢Ý˜ƒ2 kÓ§O0:» :ÁœS6{'¨Þ&Û†h8Ç”LdìÒ3÷Tç³3Fo”]RJKm.Bm\è¯}—Ž*¦¸<¢øo£ íëÀ®¼¨³ˆ4–ú¶lÁ‡Ó>å®óZµF{ªo;ø_"_òÖðIx³Ö¡#تrØö(nDÙw•vå'=wÓŽãû+ͦáU©8’èÉ Î#jgêøåý¾äü· *¨P¦*¦!&"ª¤`$ ’f*¢!þD>Þðhé]È.g^=²öÀ4…|ú§ðà›ãù°S¥YŠJŸÒ½À¾äòJqåtï‘7% P¥²ñNäa‰ˆ.UK@ÃäÌý‡äí¸ ‚C9' G‚ýŽÃ0ý?OÓ·Û°‚;û=Ý Ï£4Å Q‚wµl;ZDØÇç&¹g1ZÛŠ´E¨89ÔÒ’N1†3bÛADH@Å D¬2µ°Z‘?¯ a¹Îó¡çz' %ÜNêdšä”Ã(RvH)†ýØšGXªÀ3ÃsX'z¢ ûÝ;‡ÓÇ=êèáÍNÄwq0_Î{s cIÒ¾±>ç/M.™æžˆKP•'äíX5‰f1θ8mÓ§s§½ zéƒÄ` pN=)‚Ü00 b³Ÿi‡J×IÆKô¤Xs°NŒuEË)®ŒZ™"Š/é Ä©$ ÄÄHšL6Œcf£K´ˆÆÉˆÞqع¥û`0UÈÅ….NÃLŸµ••Ê›M6…b˜ÍK0˜=̼0Nþ˜Ç2m–µ;/éŠ@Ц˜&²^ÀëÑ¡)2‚RQŠ >H @ʩʔîmxZïéŸbgV0”•ì ,DT‘X ¬ ¦ ¤šN]À˜| ¶¹Î„ˆfÈ'P—$5$(å¶1.éåÁÑ“Në¥æL,&JSHÄy‚k™çt·B­ }R¡BmÃr‹Ã}ɾ$БÉ#¨rº2ŠŽ6`Â*š0PÌ„J[dÄ£¤"#Bdr‚h1)[%× Nç¼ôÿí×Ï·¡¶/½Tê7MÀøHqœöÉÚ'¬„éS˜›ižRw*Èœµ‚vwÿ èdÿÐê0Ó´©ˆõ~A£•AQA'§9ʈ]ó/X¡çÒò't‡º_]ËáUP ‘(¥ý¾«ËãüXc˜([5H%Bx"!KLĨ’Ðmóxä¤ÍÂØà@íÛí¬ä@€føä“ÀÜ– ÆBU± uÊä'Éò¡Ñ§·Òcd”ÑF`QƒÒOda< ª„>²ºÛ±ØyÞ)ßÍÉüè‹<È:yžžbÁÜæüAäACÔA”Å)è!}š‘»ø#£²Uâ>]ÙS[È_O©Ã‘ü¤ÁskU“œ4<jcìi¢a‚&á¾yÞ•È@Á´ö‚ ¶còÆíú|¬K>¯—‡.:TÅÀ?xn6)ÓdšA@öðpq,o°k‘¸d½lÜœÝ޹nj¬ÏœÃÝÄŽ·H’.7qÄ*Yl­ˆJD´”0±ÁE h$Ò¨´’BN´±E‘iÛ@e¦Þw¼¼äEÞ&` ª¨¥Z*¼ÙòcÁÏeãœMÜ™X€¢&Á¦j)„H¤Æ!¹’„$‰™QbŠ`¦ˆ¢ †ˆŠ"Q”Ý¥YœÍ.ˆ( »Jh†!MÐñÇ€ŸRB;L>28‘Àu"ü‡§4~è Ò;ï%DƒwУˆï@.¾—·î×B¼å(=I>/ñdsó3¤Û·»ª“›€]:]÷—a F)w'Žê`Áõ†Áß{a´Ïlcu@íD7Ï?ÓœI¦‹thº¥‚žêŽÔÆÜÕ‰sr¨DT *f1V®éϘÖŠŒV#¢S †¢&µ ¦6Ãì ½áŠŸõAji\ïVsáTÉ$I»Cñh[¢‘ÌÎÆâÄGT©Å¡k‰›¨h(-µÌ ÁTé MŒ}¨ó#²HSLHÄF”r¯©ƒ7 ôÈ}x¸§Ò^CHêQ)ÕaƒåqäbmD…!ñ ¦dˆ5’X=Ρ!`"BäVá­ ƒ¥¼Ô|mÈo#o8üI§æ_ëÏN7;ÃÕE4}|ƒDSæÊÂWGÄ>²½Ø‰@‡W»2 H„"±Øquqž\ªóh'âÓ? xM' áoˆÇl¬?;7—³AR0½·/\šœšÊe”Ê‚‹µU5TI¾ÐFˆ*‡í²F©òBÆJO›Ô p$€‚Ÿ¤lÉ쇎€ó^¬Î—’†=cRWŸN˜ì/„ð'UÒ„øIï¦IùØËb ¥Š©øÂžó‡§FW»Oz|ðÝ=ìiOSŒ?1¹ƒQ $Ô÷&‡Æ3A+UÃÉ &3¢'ÎvÁe‘ÇßLj¥‰µ57(Á·8·x5CxAÍèÒÒaÛh¯e"Æ(‰)™„«ÙœÑ¼ç±1ª$ˆ‚ &,ÒqMÜêäÛ$m¸d8q\ANÀijžä5 DöÏ–¢^`ÌÄ^òoFÀÀPvu@>á5CJD%@Ðhtš_R§"æ4E'©>’ð€»(h³¢š”¢š(¤¦š"$!õF øÁ¯ˆÔ_o6”¤) ª¡ÍË`Öea´6L ‚ã÷\š0 ¨jP²ÒHqÇ4d–,¼áxa‰ó2<¸ÇÑëŒ;0G'”AØðs'â"†rNfX.Šª¦håŒúæMÓCü8r}Žê]—i ÎäÎO"áÊàÎL¡„Ž¥ KÎhjRbQÃ6q++f4fœ­(µK7ΊÕ[SSn%mM*¢èyGn¼™€¨Âp]ý¾ØH¥ˆ¿Õ‘ ˆä.t6U¶]7VЋ3 I†6k®¹¯t(–׆’Õ 9JêÇDÜÌZ*ÄINT=2¸rnî *Ëù#œGì¨ß0~daa»³7ã|K¨Ú¦ÄFaRÍhð1Õ|ü¶ôyÙèô]kÍömÛ3©@­€ò&ƒ$ZÂ8¨f šÆ¨+nU@í‡/WugÁ`I ÂТDè!\ý—¦jL§¿>bæ„ì5–MY!Ã%—”áFYh±p)3fC'0÷, \f³WÉ#˜r<þn&^û+k.Ë¥ –xmPa½@‘ †ï›ã,ÿ7³¡ý8ljœA;`ðˆ4Ï'=|8L€ SK³8¨–ÊX®­¿U[ w«ñÀš|³ø¡å‘,íG¬rI2ÉÛLòÎÃ1z'GŽñµ³8';ª6cebø;ÁÑLâxRËÍ#Î¥HëêhåÙÔéÑ*õѾ²ìnhu%áïð]ž>: ÂÏß×Ùè’<'¦ã ôb&ô>`†(nPîåÒ¼Dò„X/ìÙª†j€*CjðÁ¹&.ìƒU$´å¬5ˆœ»Y'w §Nó 9¬sûÑlBof¶dçlÝg_ °k™Ûë½hcÔõl~M`¢°t”p65»~-œL€òCçïvѽ¬Û§ ¸ÌÌú–Á³¤1&÷{¼ædH©èI¤AÀ„ÄD UK’²£J¥ 4CL l :¡•1>Õ8g]øÃ´#ÄRZÊ•ÉïWÌîΟ Þ;èÍÊàï.Çßx;×xáÐÉ; övçyh4#¤h@ésÈ“¦ï¤ç¾ ág BÁ¶%Jq/ÕÙ4úÆŸîƒJ@Ð-*Dýó"3/ù Oü\ÂwÌ&J@ ZÒñ~KY+A¤Ò…)Ÿà?ßœSxlî’ëÃð—Ñ9Jš 5¿Lh'Ki—t¯¾ßHd}›ÃóÔ6µ~Š5òª4 h@—äÏ™„ŸÂ1úìwU¾—±ƒc âžQDUUUÃêݹn¿4‰ ÐvœvŒÀU܉JD—G= ú9NŒ4Nu@¡i¥ÓGâ¢T3Âcëàd9K)B`È]à›ÐâZ#Ä©¥i¬£]„Ѥ¡PØÇwá§|qär61¨1Tá¨%Ѻ'(††¤£yŠéR… ;(vEN¾åLø™™&­c,ö&€´•ãv\"JQ¨7ƒô˜ é’üÐF|Æ1-%N“öЇìó4SE#áüø}GiÂH ñÏÍÇž¢p÷äQH€ªª+·aÃ^=Ìjx%ˆˆÈp$ÒÏ>ÝãèöžrHEª@bZ~WÍ'äÿJbàUƒÒâu%SYög=ÿf·¢¼Ù>«7e…1•XëâºÕ!$oN¹8n¦éO¯jµ|lF6ù>ïŒý0h/ZÈaåm3+,„”´RÔ“aJCIéÀÕßé@èêyf4z™ì/ç/–áë½á¥8táæÁ×™ ˜ÐAÞ<âœ#„páW8Oé¬zxÑCFî6ƒðè|¡öža<ÙrB‚”Þu¸n¶ÌýÐò“P»_f9°t” ”=ŸÔ¸›äŽgN²­‘$‰äž¹7Ž•7|ÈzÎA$°ß³×@€9qˆ9Qú0WC¡…ô¤{> ²ä#ûĶG²L!Iv‡¾ßÁ寗ÿÈ{û†H|Šà¿Yˆ•Pü1Š/”?ÅŸauŸ(àóã½ë»IŠ9D(1rßc ¦–¥b©T)…¥R/W/Œ’÷.áÖ`”$W´8·$ê|òkÝÇR½+u£jŽ6hͪa˜}G’úƒ‘£IŒãÔ”‘Îð1¼ó‰kBeJ<¡3Ç•îxã^oªÄG<á&àÃYY5ÝÀ«BÍîWüÝî MÃd ,ÀI´˜ß¶ƒ¶À8sêÉ µÁQ‰E>¶Ì[B5°åI˜U–Xrã¶ÃÑÚ ˆà–•MïѽõÁÀ¹È·´?ñÑ™¦‚V¹S4,fÐÜödŽÝF*ùOÍyºúµö*5SÂþ†òÕTæ]&Y–L¼ŽÑ;@CJ%|„i5 Õ‰¯Æmí¿9~ú¶+çz¦`óü–0“eå5Ù^óÚÚ¿V ŒËA'¬;ð´E7F‰ÑÃW¢"}]…O(âwAÔ¡ÈÞwð£¯ÝÇ;çÌïÙ#½’aæÊdÕjúšÛØá‘£bˆËC¡·Ö¦~VÛ†cú–&J)Œ£I‹áÈø'þœ¸<â Ó²A´­_zäPý—!RÌw ÇXÁ¿G%Zº{O(qœE eã.ÂÂm¬&i•ž§Q¾'Ó#ç‰8âK ëšöÖ^ÃóèãNx$á!<’…ª™¤¶±mp‘\xÑàS;·õeü»¯g®eLã¨ÊCÃŽãÙ#–­8£ËKf;Ê‚IŸâ|êÆê:è…˜[Éì½-ÊéÚ¥Û•»siÐcC³BfMÌ) 6ŒŽ;0„›‡tš–)ØÂñsÍ¢|âsºËÂÇîç´óo™æã·ßÂîøÓõ壕"cÇ\GŽ0BÁ/<»ð9ÙŒ±Ä8ùgb³‹åš#33ùNCëÕ—9Þ3¤pÚÝÎ`(à®%û9|C§ËÙQ«ƒm«e¤Ã> Æ9k•l™‡'“6ìXèbG ‰Éå˜W‚ŒÝaÊP¦ÜYÍI‡>)™¾@+-’YM›KÁÁ1 •N8]`”î/¾&‡Le \¹®\6©[*BÚIVêƒ\ÄÚY½k|]©…àDí£•I˜V¾¸ó—ŒìBËÈÁ)‚S6æ v¼Éj2EJ”q1­˜¶JÎyåsQÃö·Ñ¨)¶¶{”nP™™WŽxk§Eβ·†Ä1EXK ˨o. ƒ½·÷$€%ÞM"I±Ä>„ÖðE"Pèq2j¸˜«B ],,á T×:ðVa¦ZTŒ¡‡GSBë7¬w4Ž(÷§Å$\BG‚œR ´]ÅzÄ ¥Ûº„E0¡ÂˆÒiL’!ZlÝ@÷ŠïÐÀà± ŽÂ½Úº Åwk2òšC¹8#ÕÇŒ3œTÄ©0q1 ¡iœ†üv&ºóvk~ ÐøÎå€`Ä[N¶àä'ÞâˆÍ;B³{uŽÔe‹dƇò«¬|ÝTLaSò’sge`g@ÛSØ“=}†Ü‰Â°æÊLk ƒuØoap¶‚»µ1›iÀú[ç®'wwU™:$Û´Ø×C;ºgµ— 2@XN´‹ÑdTX1ß”É.uðÙ8¡ƒfMØdD;݃3©ö!Á&èÎW iðôvÖz‘m:‰†¬È™ª×^Zc,ÑØ·Q£tÂn.‡\ö¨‡rSg’ЍZjÙœS±,‡ ὓ#'j5L³zÅT‘569Ðo˜É¢YR!äÔtÀ†lÅ÷ð:¢ˆ ñÙÕ¦˜sONÄ£¦S¸7)ø–-&eq³GRW’ÜÖ¸^d:2IŽ}[ò™å¥HpN¤""(•C±1k(–=\MLBÁË ÔåPã‚@wå,´à¬Ùž`™i;bÇBÉNp^ʱfø¹æR/¯Ûtà¦Nìƒ0†€ËeÜçs4¥Æ`8àYÁ°aÐNÜ%G»˜Évî'Ì9kæ”iÍ¢B“šjh8'MhÔKŒ–óáS¡9j› &Pß댋§C.Æì^ÊÅò¿x4ÓDoŽ£R¢(C1#tò|‘—LÎa‡oJÖîÂRwFÙ! @?ÿ¸k6ÚŽ¹‰ÂËß×Ä„ÇbèaêÆfpCñ´†‰ß½ãMd‚ÙµNø¬EUFbŒ: ­zäµè|8àðq2ÍÂf íže»u¨4dyM.íw ŒÈdZnär…KÖ˜ï¡Y;yph9].£•G!²ÉzW,<í“$†ŒìBS$8²“ -)‘@Â⇀âÅÀDsUµí‚IËi¯møç a§c›íœÚHéà†MÅñ/¨Ãóèåƒ"LqÓЧn2Cj\BîJ¹áâpQVW8æBÚà† ¦‚Ð!Ð\CA»r÷Í%ò•90m/m€Ù²Ù†®`ÊaÉœ±\g (&Œ^5½˜³x2‚\–Ó¤šìÔÚwÑÏ={bC}«i°ã89–`Lj¨¤4°ä™æãh`®%M„ä%-¤b Ip¸Ìï(4`lIªÄd ðÆPwh+0S€3t 1R©,d…ÈrC5A7ª-ïC, ¨šÚ—-£~U„‘/>œôúQð|(BR'OÓ¹žoÞhªÆ€Á@šmö¡Ž†ìË=¨Âf“Á‚l •œå‚e4k¿ŽZúÜe7 —Q9Li)ÝØ­n ±½EXŒi©JŽ?jk^Žæ«´[Èdî·2î6W ×§bm‚˜Eã©K©Ã0˜Xwpy(aG[ ï‰|ÃG$쫲,fãD»WæŽyvÕxïtM…Ђ•’8—S1*N›e1Í gNËC6!©Zîú4†ák ¤ÔÁåÔHÔßaãY4ÔòÁ©MÅZžá«á-‡Fu=१rÐØ‡bpáI&–‰¹ ÉVó‡˜ A;í¦KViòŒúHä=žãe8òޱ¹l+dÛ‡˜sCLŽCõ[».yÞæ%’Ú{É ncdìèðÆs²Í3à賉m›Ñ™z´ž(’T‘0éI¹Ýg—-Ë´L}¼|<º×l'jµhóo ²°ˆ…1“£s­“»‡LÕ9 UI[ç¡¥eDd:2 „Ë2Æ ›1¹ˆ›uX L¹6ދݵ]ÜG†ìYž·< ßpAÙ:¨q‡@ê¢!h,«ÑáÌvœbâ̳<#KÎøÜñ3ÃÅ ­ ‰uú N+¤+; ¹2í§ÓAè‹å²ºi#O2ì'Eá0‰óâq J&ù“ ¦WD»a²xiŠ¥XAF1„Œd=à ð6 Yr¤çÌ“Íç_?ÈpÌÊt; í9^NÌÕ¡$æ^ò‰΋ÔW ÕÙˆAÔÎb½‹0:pI l ý$‚ZÄ`ÕÄf™ÿÈìyÊÒC°‘£µé ùi6«òŸL;M£3|:;zIâ雤Ƈ¬­®`½GUˆ5ÑxûwßoZ\îz.¿7¢ó~ñ­ÙÛíß‹bø¢Xª|ãÖ(ÙtÑLož²ÆÄg€«½ì¶-£I¡2eåèoÝü¿}LDÑy´dJôÊ:-Žßw©A ƒåë€W8™úœ‰?,G¿Ùõ`sæ÷­ÃBúg³êÔFøÜКȜã{Œ£‡rpª1F×»6ø!­2Ýñ¹ŠøÄÜyP·—|zývQ¸ˆ:ì¿¶†fd¿ 4Z€¨y=¿ÕÀ^­£íÇtK¯5®#€ª[¼œ"L÷‚ãu[Ôgdu"u–F¡]E‚V™‰œbÝ¡å¦Å2MžÞ¨Óá6.JNëI,q_Ò|—ÈsQ„XBeÎÆãN™H´&ȆŸÍ_àrççýŠüóœDs.½ÊÃní¿ÖAêxsœ·s] ÔùNBê…]K¡Yòú6¤ÆwŠDf!ñ‡´U“÷;ìrŽã¨%¿˜¯¯pUZ/ ž'²«}F:ÍŵlébÅEA:7]SÅâ£ÇJõ¦6†fn²ß¯ÑÓ¤ŠJJ CFN­á’¸Ý=ÞïššøK!‚wñ¸(q÷‰h]“oHê2·Õ]Ô¢ÅùßîáŽk&X”®ÚâÔÿ·B‚;}å„Í-íÿ€ ¦Ï@–¢ò¸4H4YÎ\™´Âf%º;w!@/÷HŽ@jG Qè”S”¢dTEˆ(†z-Ìb}Ð.ÖCí¢¸ ul¢+àCÈ—Nkˆ¸¨Šª»ÐС<•Ð$Rè‘7)§xˆdÃ0Ŭə¸ çêìÑþ=uÖ=UDÒhjDn Åˆš¤}òa5ÕÐ&áµ %ÇHadbÃ!‘̘CXÏ“ Ù,2dÉ­­a$6ÇìÒhBcCd¤ 8Xôœ¶"€ÑƒL ¬ØÙƒ&C#`Á€j( bý…1EAdƒ ;M7¤(lõyÐîù»î'ËÀïØ|:½/éÂÓFvƃ’SJ”\ì^§ü£“D$}¹vé€Ðg5d+Њ ¥TZD‚ X‘…bBb6ívïz©Úµ Kàí¤´q^!¡ùºº˜Ü&Êôlh tCÛÿoÊ~å@;ò¨Šï•S©?Ãå;â¨2#RHfb¢a£˜b)GÃeÀÓ\ôŽ Ÿ`»ÛËŸùHïë^@zIÏH£ÕÏ—šbùíߺì‚ìÜ©°+2AC— †¥ <öÊd²_xŒöœÄ·¦‡ªåD`h…I‹˜FÒÈšxäYÄ•FÅÃÝÛY…öÜIJ*ÊycUdìs™ú÷{‘ ù‘Åœx¯@ÿ$€7’¨ïˆ‚r˜[!i””ù ´'ó€}³÷˜8uÉ(©¯*æsršö{û³ü)óü Ú`6ܨnºù\ñXiù.5¤¦s¸ˆ9jgÃâΗßçaRþ8¢Lös£½ï‡“v%Ã#På|öس!ܸlJHBL!¹®û¶gV‰`æ¹41.r–媛 ‰”b ßdv¶ç—Ì<¬)M•¹ˆ1Æna“a‰ˆTFàå1(ªÅ2"k2éC³“ÇC‘)~;ÖfQb0øÄ¶‘ã³'Bqå1o&a–’–'Z¹} J:µ§j)Ebk88±TTQ÷3ÀÇ(ý:™²ÂØ%¸ÔnÉÒ°—[*—ƒ¥Ðƒ¦Ïw9Ì“cbÞoˆ#ë™ñc Dh€âüQ.&g Ä^­{¨Æ1pîkz19¡èÎ ¼7;ÜBì‘]¹ç¶UŠ!fQÆ)HD„BI3¯…çK‹ õw–ªh 'wŠËU=—G‰‹Ç¨(D¼)¦Aßä§±,ˆ¦ìðœÀæ¹’ܢű ÒQ¥uã^Îã»Ä:Uk•éÙw žêJåŠÙ¢áÑ:«7yjâ\¤ïIÖ˜8ÐjË•U¶Ô–:WI2Å,2;¶±Fnk¹‰…Snë¾Ws¶û(»xÞܤå×Ô`)/Q-SðéåË‹³¬æâñ«PËhžÊ`dÙÛ_bdºgÚzà˜ë§ tz(LïgL‚[™@­2œ©B<•߬Þ½ø Ž.0ßs}º&NŸLj\ppv:ë«ÖñÇ(2Õ‰ uÚA ˜kD½­©¾ŒK žñèŠMà×âªfFuÉ¬Ôøç-ØHÌ$Ç î˜{ÉnR„€ïø’9†¨_…è0îÐCnÛµ‚‰)VcSŒV+h•ƒƒü–0ψ$zFãB›ô lÔ¨KTÐSP"M ÔPÖ¾ïCô\+Ö@?4/ÏêMJ¾“˜ôG5((_øØýý¦$|= ú½œÝ1áÉ×,“²„2MÕ©IVºWµd†M%]Þ5dçš•’Yðó×€Aññ“ ! )E(€AD¬Í-DÐ4ÙM&Èöòä/Dox†2ãL á0µÌÁlmþij;†Ó2„%Ò/Œyáÿ;&!îƒ$ülØ~§´çàxcšu™iÌi37G7-¡Ú2&YÑÎn) ™- mÛ+ FáG71XÐĤCŠª¦#`—4£j)¤3ii ùÊ;M5ê„*ý©ÎG3@bº^K RV;:œþBµ-%5zÅC±ØWz‡³Ô™™€Ý9l¿‰ìó&ƒ`]Õ %==?´OÔ!á!ñ¯°|º&ƒ`Ü«ü2švækTQŠÏ”=žŸ§<{5‹T%]GŒfßN9f/¿À.L™’Ûº¬œàÓïWŽ ‡t¨Šzf0D%‡gÆ›-|9âAÕÄ¿rûœ­· gFc8s:<.ˆ[.ˆsÍ4shCäm“¹zlö!¥•ÀpjL·mÚ`-‹ ¤ÓäÚß4M·ØÚ£/€›Ãa‡fœÖìÛHâl7Ã%k{cP—“¹ÃUáë”JɘtY¦o!ɲc̘Á¦ì“¼,©hKiÚÒ½;§d³$@2¦u˜±PÔÉn4‰Zb­Ž…˜/¥d Á3­Á’àAt:]Ê¢ ‰E¹ÁN™™† ºBàÓÔòÊÊr‡:bò5p¨W€ƒpÄÅ‘!Ö˜lp@a€ÚÐÜÉL&}“%ÖDANâMKD»J%Ì$”»Œå>ðîb5µµ ) Mb5}‰Mª`왩3f³ùØs¡2eDVCyfzGˆ‘ÊìP¡ReOÕF uç½pƒg†èH}= ÕŽd8°‘VdjUfL[×Ü3vmŽÊ;*8JáÔ„@èvˆ n1Ù¨#DÔ#@2X8‚íÙ[Ô:!¡”Y,W+š¥@±ïª8úéП‹oÑ•Ó6ÒÀØNÇjÕX÷Û™ˆ±@Œõ³GË5³5ƒ§%ªQ£tégI6C}:%7Í `N| :R X”’ !¢hPy !„~ïbžN„á ó‘N$˜Âêui„›ªW(@¥ÐšBe¡Ðóãª}´(Ÿl ÒƒQ#Ïý|öÎÂFú¬Ð ÀH)c"Ù€zU•°écƒÉì@:@$$ã$Ô?ÇÒ”9´U>k ‚R‚„‰ €a ça!5@¢TÈJÁÕ9@¡iiVT&H!  æ@1TET @D•DµSEMK11D#LÌPÑPJÊH¥ 8D§sðã‡+ÍU/aÍqã×¥Ðî¡ÅaGÒ§­ <‡­”HŸ¢ Zˆ¤7ðdfCÍàôDDUîv=$P=Øp}¾°ý2?l#KÀ;âsÊ$ŽGxŒ“&(‘`‡B×|²`^1í :®‡©›Ë6«Õlj¨]ª©Šo5àsS7„¾´eÄzŽr6MŸW …XÑ´q`BĨx‡‡Ñú pðIwb;hÄFÕå _<¦ÊBÔ7haˆj'ˆå[&¹à2f:SHø@D'—Wî8ü=†Q‘{ûy[lÓ“~j‘Ä@f˜:dÂÁúWv^dÿ?ÞõF©Ç„ü‰ùvY¥í]!G\ü<Õœ.0?!kÃNƒÍIÛ¸­½3¦JšÌ¦wQµ‹n£:ÕUR‡hwZfç'Ýͱ^9Ç]¯žÙKÇŠ¼ažM£ƒS3Çw9‚Ó‹¿5ÞN'FwTšóIàAÅ4*µ1hc Pì}Ɉ%ÛyXˆY™ÍAvGR=™ï]ø0klá®´šÉvkQšØ³wà’í®.ÏÛ†k‚Ëvl‚gœbM ¼`(·TçÞ°8# ò>3‡¡ÎÝW$;g¹Ö98ëÌgx­4ÐøLrr¸‹(l¸ãƒ¸fäU|n닦MŠ‚„Ý.FAs‡¥ßSÏ:Æz‘ÆÄ'Ñ-pí”pœ­_MÃäÕ¬ŠHgšÜ^°ú¡e“¤a sÈœfÂã¬ÖI{ÄÎîŒ ÒÁ·x‹ª¼ÂØ?à $!rT….ÔÂL@s&×Â]“iÌ5o¤¤gÓÙ‘œg0>6Ä’]éÚ vÌ”ÍnèVšöã°êHçX#§2²NÎÚNzÕ>æØ¦…—8ãM†¸Ô=ÂÕÝJÐ㤜™wkLdÈüeÜLæ„<2{¦f¤¨;ÔÑ/Æ\9APd±èÉ”&©É5Ú³ mK‰Æ€¦hóH¹h(]r»©5Y±N#…ÎÇãÅê|A«ÁòÊs˜« ‰ O¢Ûnºw/Šçðôì¾ÈNî6ÇÞ@üê©*"b·v(Ra0¢šÏ]B´ ` lnù¥h †ª/¢䆔à«î– Ùáç#äVãÝÒZâéUér ÊŠÏ<Ød1Dh—Q¸>Þ‘Äô!THH2PÑ*5"I°|CU$)ï7¼lúp;r P­+¼´iY°Ÿ÷ø/ŸaëM ¿Áêü¸ `?lw©Á;”êÀEÛÖ›¤„Òœù~¿O£Ü)¹MÝÜl”t)¾Âz=F”ýP¡Œ/àºtOÀ1®—€¸·'¬ÝŸ=™%ÙŠlDA Q¯vÛllpêÂ;%>éÉi2R•É_Ì&ïý¶/è¥Chý0qù(¤^, P Í ¡ÅÑ9êëGuÏ¢Y¨#ôÁ~o¯n©kšzm¦Þq¼ORdˆ4jüL‡ :Èh¦%dŸG^'Õ»¿wBéŽéø_€i˜ vHäk÷ nï«Íydy˜Še¨«Ñð—ÇÇ…mxCñ Á–ÂL¡L "ÎEI(RAaöþâ¬þ­=ûu´gGd h‡ðÿV î“pë>òMLIN©öÀUݢ罛HB@s#‡ D“ PIÙr„D0 "LÛR+EAŒ¨h8M¹q â\T9€8@P³æÄ° p‰‘ÊÓA,‰ BB”bØ‹rG‡0®F©¨]!H0…@Ä R¼•ÒíƒÁ¨NB‘#Â¥kp/¥™ºHY}qÂó^¹ûÒ>Ï23PùæGÃJ"Š!˜"DárߊÀ‡ XœOe C+"iªM Ö†%fàéÎ ö" q¶Â¥˜ ž˜ÀÅØþ·çDü"°<629OôOç;ñ¨"Æ3ŒãÜ ÒÒ•:X» P¦ ã(%Óž mÇ Yq¤Éb¬÷éyçcȱÿr^X¥:ÆhC‘ JR¦Š*Aª”0Qà$²hÂ`°èÀlpƒA¦€)쉤Ža{náȆ倥¡(ŸW†t¡¤& ( b) ± è‰JE¡(i¤)_¾Ü“²¼„ˆ8@ÐÉ JvVžÀœæZЬlét-…( 0¶’ÆøàNJ!ÃAFr 4|K‡†íÔÁ-7¨e°º¥ü u$ó35òCÃaL…¯Ì÷;ŒE[²öŒs'ú0ì»Ñ±,«bpŒæ ®BäëöäèËÓõæ…£HFøÀš/˜wÉʦ‚ž¹D wóìð×_w-‚àòp³Ã‡03é°”¥$€ƒ£‡D{¹á´Pù_©”õÂrITt4aþÒŸÍ QHþ)BИ¡éåùƒ#¯~×㼿 {£¬Œx¬‡`‡‚Žä»ÙMÐ #ÞL‡¡&)… [Ð’j9ŠNJh )ÔO–ãcüd"~¿R¿œ5ë•òƒ¦Gq…JHD¿N10@oHtÂ<@7ñXFƒ Þ§«ÙÑ€ô4à€öɾ}ÑÐ+Ú+‚ý„OIhí o{6- {@ö•Ñþɼ~à2‡Ä‚x!Ùhš›ÖEC!  büǪ¡$ ˜¤*‰’‚?ªÍ+'Ô_ÒŠÈÝç}us'rK9Êm¾O0Ÿx`º¡‰ñH °b’dˆrP£|½Ó¤”"ã¤Nø>iB–T»¨û´wYÛ¸Õÿ'ÞaŸãŒOöY`y*)Š„(hMƒ]Ùú4=p>œÝ³tä‚r)º_¥ œ{ %^ 2)•4 ©¦PÔ žéR(»¡<Þµ"‡è"¼ÆÑêC„‹ïãAô’²¯R,²+z$¶gï½0 Pà zîbQâ.È~ü|’i(:hPp ‰øãÃD52¡=ɃrÇ"4Ž“"Í!X–²XH’1U©7jÖ@hž™9Ê&ùèŠAÉPãõôn¹»áDš•tæMd)'sÌ €é üo>t>ƒR…$µ›;wdðH©$È­@ÁïâIé€=wó­Íèå4J'@¦Ãê4ƒ’4œ<ñáÕ² ; °‡¦mÁŠs{ôi¢´/x¸¨A»yü¨do1èŒ3ÞÐP¼Å?‚ ¤iB•h^‚ŽÒmÕÚæ— ˜…™¤hDˆ¨)ö À†4„Ù“0ò}`Ìrëµ7Ñ—ÛÏW3vb5U@¢wØÜÎsšÚl5›4 ¨Aˆ"¨z\é­a2ß´Ætü¥ÅÔˆ~Í ± EEp6ª!šKœç"PÄ<û8M„LUQR Ûif/2`©–…Šjij†¢¨ ¨‰’'Ãᆼ— ð*~ySS¨ôÈî„¡Š¦¨X„(fj’-õ` ”¦ôaвÊ2± ³Ì‘KHÄ4£»@DE8„ Ò:5Ù„š¢ƒŒ¨ËÏ cÙ§ºe´äJ1d²tßѺΗ&r6Q(öPÈ®ïúÝÝßá'ê‚ÙTÆMp¯(¸IÑ{Þ^dJ‚ÚÊ™Á £š›c OªZPj…8Þã  n¼BÍ…Žqmù½PÅÙ–VF8ÔD¢²Npy£KBÑRpjj§á]*mK= \ôA˜ù¦*Ù–£ö”šK„#v/eSbÁѶFMR’}§tC@ xŸ¢¤}°%õ=Bò‚­…8UUF¥’4´™˜N@„XEÀÓ£eƒÏ>i8wPEYbˆQI ¶ãAÀÄËÀ©ÍAÂ`©)±ð}`î…¡:b€0–’( BšJÇ‹Ø?t'Dôˆ#vqò%*‚‘à?p©¨?gÍï4h#oC’sX97¥>¶4uŽbÝš$zöY@Пš¿Ìâh4¼ó$"ÑŒ1':ª]¥5, ë“@y»ñÄS°2"i†š¶Ww³[€=+eOàŽy-SPÊ?}NíàF!Ë«F¸ yJ ÇDz‡øx'L”óKã !±{'S O­GÔ•Gºåüwÿ ü¿i¦âàùlµMe y 8'íd± SlÜËö3sŽLÛ@~”ì¡9;{\ˆZ 3试.=$ìÞøÒ’© ³“ZVÍÅ=šÀ£.ÚúIœT^ßüXŸM½ ˜2% Bt×~ž¢ô*Jž:r÷'ÍäãJÁ =Æ[ï 1ÅQv9ÿ=Iénö™©Õˆ¡BáÔwÔ†A˜çÝ&y±C"7á¿,P9†Ñ'cæ»Hjò*€²nÑr ̪4êËý$ÑÙ{»í!)ØÖþ–³é&ÆÇ¨Åp6;Sû3¡K4\<§ NOøk8¶l$ŒJvf÷G~íÒ.I`tkêË:=VxcÂkq™ñŒÕˆT¶‡·ïß¼˜? 'W÷{¬©—Š5ô»/@L:t”ðë6mËtΣXT‡ñö:JòNÄÓ=.Oa#+N;c#0‡ª¨^Ú©(ANô”š;\¤çÉÔófN Õ8ª×]ÜE“å%cËS ûk©2,©x +/ä&JÒ¦®ÈTÒrŽÝÓÀûNïwûžãßÀN?/ŸØE쀭T˜!æ€E>¯¯(ˆ3ƒYÖÙ´²IDE)ý+àÁÈ|’ ³G m°>¥ä´±Îp )@qà`Ô$¤Ö… jU‘Ù1 iH3“lie.ÌBvÕ4½´‡aßåèœC¡œh„†H±¤! ( P+o+ª64èg ?õG ‡êíé_±¯yĤ@nmïQUMKã.JR¨­@ÿ>§éŸ|ÑW³f‚†,TDÓª,9M cE%üÁÃü x‚<¥AX@Äâ‰Ù±Gױѡ Ê]Ýê¬×˜„ÚpI¥ŠÔ˜ô²;qj½Xçq‘ÛÃÄ{»[|ïSD0f 8¶…š´^*L@ïf$6Wz%àsžÃœ&é¯!§Øx±™HÊg`«¦CDµ‰™FF·̖¤M”Ñ”¹qÖÚ€­²)GkµàLÈÓÒq§ˆÓ}¿¡à‰Øª†ýCUŒÛÅÌÙRÅ”2îQM™‘M Xá˜,r™6a¢hƒ¢MÆj©•á²h†*åÎ"ˆ£"°»7ìÌò´þÌx q‚(9€þãç¥Þ¸8~Þ¹&$¤¡ ¨…L&ÞB†»‡¹ÁðšéáÂ:ÈW ?ÝŽäØŸ‘ï& þ3Ÿ§nÙ>ÓJ a –eç—‘e™ÒP:Ôßýûÿ‹¶F·Í²©½ÕÜéPκíkVÞÒgäõ”KœcåDÆ÷­à/¡ÛyiL~lìì7¡(TÄT’ì9N\O_HµZ¡`6´ÿs¨~–q‚/Ù€e_l¨~ˆ Ò”›ŠN(öã@E÷žÏ€ØÉ ê!\”‘’$»¿Ó;†›M?•ÅØÿOžqð ´Ö>3¥9!£… Fe/ñçvJªÁ¶-þ?§8v2G9Î6 ì‡úËÈ89Âiÿ-›ŽÍ4oW<ºpÓ§Þ  ÐÐ5§¯0!Ó›´:© ÿÐ=¾Žç³ç DçkI‡ùœsˆír²œÍ–¥¤j‚–ˆ• Tø[šÖÐêX9ÒàGù®T2pŸKý§©O— ~÷èÞp•z™LÞªì4‘'°"öâkâq Íò~œ{`Ö!÷x´JP?v?ˆþÙ‘Có¡8E˜×ùÿ»‡¼>Ö –di‰"R‰ÓFp4À}²êä…DÛe õPZDAE1å/¼;³ úÆŠ’ÞŽ&ã¶LS¼½ÄlI&‡Nˆ‚§eìiÓðŘ&æCrÀ_‹NìùÍVÕmäö;`‰‹›EATÆbv4E¶Bb… ÚÛg.Ú-ŒÔf92½!øù„üe_@‡É%“èo»þî<±êJ*!¤ÐfMÉ›caiHh2mPI¥4ô¬¤)&¥ ã+¨CS’2NHñ€Ë^”O@|³»¸<D¦G!l< ”—À&$i_ÖIxê¯~½1îpO¯óšFMD<5…BɲúêOwé  %…)ÞC«=0Òi¤áŒ¸ƒ Ö‚ŠÄ¦Œ H‹ô‡#ì#°!Ú÷…‰Ìä<~¦Àý¾~‚ÿï?˜¦0>ÂM• ƒ0mëëü[¸ö”nCÄh †w !|ƒÔ‰å ;1‘*?^QEÄÊjˆûP ýþž_¥#Ûæóv^q @ÈÌÁpžkÍŠÄ/뎭î»cð:â:_süнe- í80|:f| "`âG Ã,0³>ƒ¾¤õRèêýôÈPŸ5F뀉…²Ò“KCµË;:°h…lå\¹×ÙÀ0Ñèñ`ŠjVŸódõµEcû‘§T{=£ N°Ìн-ŠMP“1#C´a'-ãü%ô”ÿ ˆa'×=ˆEäL1”Q „§tòWº D†¤CØQª™‚IáSFºßײbŽH8é©õ"ª¢*ž™¶ì™ à2f õÆÉ2§aÐ'iu;Hz`ò5…!Óûäç;Aúã§1^«tìB.éôB¼„|¿G§vP¹‡ÕÉ_<÷À>Ò%ȧª†dvÀ?KAêmŸƒÖã´|Á£˜ Ò!ô.Í}à’20Þ´4P­|l‰êCó¥ )(\BkàÒýéÛëDjK„äŠhOV-²/¨Ns)GöCØ9,òrDä;8y°é@ÑJ rwšNÊÀ2“©vŒßŸVhÈDÆ­´à½ÒY~Gñs6@’M„#!¿p‰·áxˆÅØ=gªÏ^µª)R"ap©JXbì1êÖE)DDQE‚t‹Öži|™£Ìvyá>bZÙæ‰¿ÕäD;Òm÷$ü®á;“æþ<îfO"—Éë=5º¡ù÷ yD`Ž;1Œ­c† J M²Åèytþô4’È@óöðç!”ÜŒP”‰:tšH‰"2‰"5z*£çÜ´J…¼ia ˜5[¹sQïƒùàð!ÔÒ¿-ÿ¯$‡BNAaù_¯×P Æt°2uÑñŸm$›2jû5*¼hßöéf®Í˜eÏ â}9þ˜„HäêÕœ ½ŠÝwÏlܽÆÇ0åS;Ô22Il:˜hÍXC' ÌÆ¹H+î8>°?xA¬O2EéÂcï¢0ΡG -èõ8dš $Ë ZM ›ç¦88çí q;U ÙÏ6átž&FgÕY×êËbF4úÔŸ;«Ý™ÀÐÑæX½Ð•ÙÃ:TÌîQ‡—™îï9yÚH§–H€Š'—u+ðþ„ŒÖÝÖhë´ÃrÅe¹Å™®Ýá®õMníøA}=Ó Ã„èÁå'#×nîýc¹I¯2‰ ¹IºoجæèöäÌÕS‚sC(M^OM7«Îã$ d“Š3>\ftÌ Â|÷îŹS /×#õ,þ„uÌh¨îO~ÿ÷½x&Ú/fù ¥ÐoÛY‹¡›Ö8ã^ˆAd2‘•H˜J`¼5¼ìQ 2sÁ(ëÔÛ&dñ© BHJVÁ ÇMÁe±é›~[#0 Hxw@šÄì]L°./„É4éêœÖn°‹Gd7c/…G,ÎËÄ6isáâ_*ᓸ »Ã8» gTkusu#ÌÎý")ÕÃi®‹(s–qÓ"ÝÏI!Ø€HŸ½@)ç2Ÿ±g²èO%á&üð§Äû´¹1%zh„d¨¾õæRœA2¾ÚíEÌ#†¡±ð@ ²I*Ò°ˆ<£“±4±«÷úJ¹=û‰ŠI–‰U‰¥…€'ByÝ_®žbòO³ÚLÄÄT#AAª6È`ØeÀŸÅ ’„) ½ÚRA4”=AN•w*|vñz#ûa=ÉÍqì »ç’©"(À­ó¡ù„ÅMÛ ôÊý,âæ€'¼ÜóH LOq‡*‘ å ×êΉÄÒWï „P_€‡Pž«t¤O?eÈij-ÿº)!]ÃJüÚ²p Ál­ÝØ«ƒ{Ý·UdÒ®DSui½Ç JĭóZc»G‡‡ßÏwyÒ‚.cA\ê(äA°?xYºOjຖ%‚žÏyT8ß”<ƒJ¸€¤ÝžJPÿzÑær‘ ¡2Bh©Ä!@PÖÂÞ¶šuA >Ó‡»h|lEž€ºt~·´àìBò3ÌxLó*üH.HñCÏÈÈ– ÒS&ÄRò*uì IÀDAò™ÇLvÒÐÄ$lwæhp€ˆ%è#²ƒ³fD H4“Ðs÷ôªÌ5Ž-bwn)ϤïÖHh‡~bæb‡JC/%ä¸#©JüÇÉåòwúàúH‰J† R ZîPÐд”U!MA4=ò¦LT@ÌÍL@ÒÄ-LÐ %Rs™ˆ•™(i˜BhBHZFehˆZf )¤(¥4¡¥M  &BR)‰hI”-”4_±”ÌÄBÄ L$JA(ÉQÉ@ÐPœ HE+JU0LHÓHvд- HST«BR€45¢u„pÈC$Ô¡IB’@+B12ÊýÒ d PÒR-)@4-ЀPHHÒ‘ l*oª¡?ƒèº3¡_·)EÏÔàÐâœMë¡ú|Þ£Bš.Ë'Kù‚û:‡­$=ŠwwÚ)›ö׿÷{· ﻕø'Ý ”ˆPP,Ä1Pƒb}¾ž°Þ0Kwcfé F Š¬Ll£k2E Ú¨Š¨‘Á$J¤’D$|‘"PöZ TèP½HvÁ™H9`ìÐ8Û# t d]„b@(¤"´Y0Pf†ÂI!@ÙM$JÇ041)¢’’WB‘]äH‰‚™çRqd¬’œ$‚”‰H`aÕNÅÎp†^Âi•ì©€’B’¨BU.ZC².$ìWüráž$¸ÖEòT§Éb(’cl 0NÅš&bÈHÁfýèSŸ»äçs.ÂzcEH\BI’ &IŸŠ·4A&·x†¶dú0Ä™‰$’I ƒØŒfI‚`þÐ\ŽŒ|ǰ;‰øÁËã¤øl¡í€oŽ+†ì}ÆÁ¤cëÞú†íµ‚¤Ázhއt÷àXS”ëCc¬ ^Ô=wÎî¸à‡O @;¾"9Ú}0${’AOA"1ÐŽš4ñ> ATˆÐb‘±å¼^2AîƒyÄ ü4ŸEÖxu<Ka¢nCü}üڹユrè`,Ò&¬I4¬–{è§+H½ÝÃ ÐØfÕ—ýŒÌÛ?3€ÞBš‰"…>dK,¸®{+S$88ï$˜|¹¨(~Ôš$P—¬Þª„ƒ¼Ä9—ŒØárÌX’ Š®XÓM’6Ï3ÉÁ<†¨ý@h¢¢ Û%°PavÁŠI¶µ¶·×ð:¾¡Ì2H|‚r5ìàbN³í²ì°·€“â$Þ[F½*Þ“cz!®a;»-Ù_4ë€Ãjì•¥ÂV"8£ Œ0¹d™Í@ðC‰¥åôÐ1¨ÞoEÒB¡€QVy±«®fŽšÖo-ȯ´kѱ²4$úùžA³Òóº´-1λ1Añ‡Á2L“[2DlID“$É2WÅçæ„œSÕ`ÉŽûÆ—ÐB†-a¶:Q9fA¥‰Je–0%¢$¤iÍìÜ)¢%ª("|NÓ_îæI)t B…N\Ú¹q$ïû-#´”ñÚ‡TrDˆ˜=LÁÀ<ñÎhLD%l`Š ’,cMc(jŠ*{&*¥*ˆ½U†!§°Ž$ Æˆp0¥©˜±Š{€éo›4ÝžA¤ƒÉÞ$@Hcàhí>ÔÎ}ŸŸõÆ&Oû 3Ðîƒ&O¹_V)޵F•Q”%³×Koö2ÿƒ‰wú ’[Óì—HÓääv "IX¥ý•–œT–†‰Cœ™R3ÿ#¡dÄÓk”$9c¼7"òâÕ³öYÞGå[ªÚ—~8«ÉhK¢ÄÎÐ*Ù”‚ÑßPÝ&Æ¥ Bo¯ßöégk›Ùh[Žë.4uNËÀåA¤Ÿ,‡à’!'o¯Õd.¯HÓH?hªÄHðñ*U *¡UAýF˜7 oøŸbŠˆj8ÏL~Bˆ; #ìí¢|t£ºªj‹E{]Ù $?ƒ…ŸŸ×a¿‹Y$úF;'wFh@¢!jšü¥7rðQÈ_]<­=ûäÉš¬Ûtì%a…JlÓö0þ˜NA@Æ$1G!þíõí—ùI<{DGÀGZPÁ)…‡âA—3È@J151!H}.ÀrÒ'ÐàhŠ}IHµJ¨jD¨s< -? !Ê>ó©ˆÁPÄ{&)*1%]±¤Ç¨ÉH%AJÐRJ{Æ‚†dO˜Ò’0£ã>žå ¥b"‰H“›R$± E2D`öH:X!N΃°RÑ\¾,Br”h¹µ ФÔBTÑ ÀH|õÄJ!Ò$‡aÍÎnÏgH0ªøJPøN$Z/0b‰–ˆj&¦"¥ªP)h¢—ÖGuJ[VVˆ‰m.ȆZŠBžAïšNì:{áÄy̧bò0QA’ö"CÔœ€ïÄzàbe“†ç)8‘Ó/T³ƒÃ€˜œ"Uª ÈA‹ JբвÿbkÜ*¢èZ]‚ÕÖ Zp,•¡CRLˆk{Y)!=ެ5MPÙÇœãT%RtÝÑqó?aI›Ž8œxJ ‘ÏO[Ž#rX­$ *¢ªï&±\Ñ\–8Ñ“\44Ó# ²©‰7A#‚Âc²fÉ„„1fÓžs„„¤–ÅGêï£òùX?ܹGÆ7DHMbF|6ÍŸ™ç¼À¿òÇO­žã~Æ+¦E…gBŒM'í“H!ݼ­ÊêJH_dpü‡O,(ÙŸØ%€rMP",t8‡œ˜Äá+M‡dB|/ÍÜ5h @ÿõ!¥•~íÙ¢|ülú7q-,P$9¨t"hê'E‹$ÁÄ?Ÿýs/DèʓڛöPBûÝvø7ï[mÕ1§¤ÛÛfe›ùLcQU)13]ú¡›Øø ¯äà'€C^o““Èk€Báʪª–ª”ŒZL‘’^\ª¬É^ˆô‹»à·×ÈèØŸÜ¦´Lw'LJ$DaÀ’˜QØû ßÔf”‹:ì×ÚýrQ Èyå~œ>XNI6íØÌhj ûlht ½w¤ë“£¼îELHÑ!Ðì’@Ÿ“¨ã`ZBIy8A €f¬t£ûX$R‡¹r¸É"’è9knPòÓâG@*¥ ÿªtÁÄ‚¡„i³sßÿ—Yyä2ˆ)<>¼—‚ª˜µÙÂê ÄW1ˆÍËÍ…~ÍqÏ(9ÍW¬î.=Ø(Qý©Ťv¦œ*¤/A¿ÓV8¢J+¡X”W!b<ÂF]4Óóç—ÒÞ¬†gBª¶×KÆ&ñò„-ˆÈйÁ7Tn:yqá²çcÖrp؈'™4³nr½Ýxà"ìrâHN lMEÜÄ9ÙŒMPßjZªq ‚ǘ]IÄ’‰bµË¥¸Å õ‰$ %ÝG©á¼º¦¸JªÈãrp ¨(G«F÷Á×Â*Œ‚#ïQç™$ !Ûè ïü°kSäðçùe›Å5]ñD=p !üáëÏBo@9Âú OëäÖÚ˜¾KOYd"‰)JrF³£h BP)†@áÁÌ 4ôT !9'èþTÖõŸ§)æÓ&\:#cPU4­ljb"U*’ÙªMQ~™Ä@¥%´G$¤)=sœì<ŽԴМØ.Y`Û²)óäýÃ︘N•â›B¤2”ú”8öO Ð0Ÿßʸð€RvÜ’ úp ~:8ÔåvêêCš ÔË4Sžâ_€¨ÐÄ£ Ò-U12„Ð1)TĨ5BÁ44DMQ¤@È„‰MK5‘x`ÒÀĪRŒÅIRÌU2A0¦;Ç·À{T@€Œ¬ @‹á•E„© A„@+@½’¯d䀣„Ä¥ O”9]G˜¦RF˜•&îî‘]ù=¡Ààlng4XK©*CËÁ‡4ó-Ò—¬O4KÖ†!¡REɦ¡˜-Ç´íí׿AûqQèæa|3{!Ÿ†´”‘¤Û¨ôÁ׃(M¼²yly¦†¨Á >x?W†í.≓ødëÒëÚ ÿ{sŒŽtDJD4Á3zÆ*†ÀÄ8”(h™Fû!r$ù³c[á4Ñ-)ÆLür؇=’Ë"Xpæ\¼d tÁW ZD¡ær£s¦™ÝáKZCEF0ÜB’MP5×]v3ÁـÚ¾øK÷+²ÑV*34´+@’HµHò hŠ<¤ú$2QÒDДT[N¡Ý»Ä° DE\$Úžç„§V’rÖHB˜‡Ü ¤Ä´é1#ÂŒ‘ -4î;%H Û"eï‘•HÅC u^<‚N†ãB“L%“-' b9³ÂÆpäá"½…ÈI)ŃoÈ´éwÅ À"€¤ü4î7ïÑXɘaX‡0<Ð ùAéb?¹*VÜôÝÿTžñâ®(çÏÉ?®=@ Vƒ'猄;B2ø {DDaIõÈ ™.VaŒ¤°zAO"_X]ÆÏQ»ó®ÕˆõÞl¦èêÜŽèSt(u·Þ+ÐxãDÓJnp¢Ñ® ¢³/;\&ÚD@BØÀ€f`ì ª}ϼÕ<sN4ç;2ó8‡ÊŒ?¿ñ©QƒJp“¯‚>¥²¬Ø¥ð‡†y¢a@ôoôæ¹ÃŽëJTæÚï'·üc ¹Œèt÷FòtQm¼Bȶ6dmVà’¬]*D‘GP·hJÿS<¥ÙYjâ ,jæ-h¹úsÏæ¯¿ŸÐÙ•6ìþ§^Þ¼MâÞßÝëٛąxE‘qjå!FÛúÅ:ˆ¢väëãçǧœ/ÚP¸TBÆn˜ šb²Í%ÙdnwÑecÕTdP]S®¤º%¸è¼kDoìc…F8ˆ¦%30$ÇýèdÓa9Àõ§6¬‘Á ÍCxøÙŸ!$k8gÊ)Ç„ÒÁD:‹¹{]¹Ë×PK(ž5 !œÖ%ˆœkŒ;3îr¡®˜óøÃç»:ÿW=5Ö™P)šÅ¯ì¹5WI¶opIJôìœ|áG=Ì5u·¶˜];1ÝiG^p¢ïܨƒR5$à÷YÃ;üôw}Áðë•@â€áñN{¦giöƒqoÖÝkÞBÁJ§ßÉøoÓ‘§Éý}úp  †;*WÜ·feíøBOÒÀ½ÊÞ!ë œk÷¿v†›ü·ÄÅcÝH():®ND‡"P`.!»zïW˜¾d¨«]ƒw>숗ÿìý©½%êƒH›{b¹)Ô»b¡Ô PPD *ÁK‚÷¯i¸¾SK—㙡z"¦àÅ;À`à@z£ª JT)i(õí.´ J”©J”‰­ëönHrs‡B´444)CCCCB”444 -'P*h e`X¤ad…Ð †i“¨@~~w§5o±£6º$ÙqC+ª‰Ìa"‡ñaˆå<Ôk/Hý´¨,•¨6æ©§ ±ª¢ä ž¨S¼éÙrÿŸ.´”ú}Þ^ìãïá²)BÄÅÐQNÌZ§¨Iè,ÃM'w±+ˆ™¨ª¸šy—«ºª+K“QŽ4Éu×Êsêu„Q€©OùC»¢€eƒ®T^ÒC‚>¨:`è„<˜PÊUV ù}j„ÓJREr Í[&MˆÐJ?lÆCûpnÁú¤ãAR°Qþg³ñÂ) 4ú…ìt1PØû',™b†ˆa$bAî9s_—<´kzžË®¡ÆÛXg¨i 3šjš³b1dDš2šJ(ãI¢Œÿ#´š…z@ Mû1RtttqØ7¤€TT̉w¾T¼cPú ¯ž8Ì—nc$ö»¹Ü—<‹~±ë)HСüñ ëàƒJŠ‘"GP†åMÃÔ¾ó÷QxEEgö8’ðìÀrWS£fÕœšŒÇnQÍ92”Q1«6Qg8ΈÖj¦"UÍÎD¼Ú+a“XÖj^c0RÖAÏÓè/ãð[¬ÂŠBkœÏÝ8š,0†µù„–ìN;„$6;òD|ºHŠÓ­Ùj45 ) 4µ åê[¾»žñëqêëÐéè¬dXìç,º¢©iÖæ† ÐæŽHC$ýÿF<½UPÀ“;㛚5Tè5ó…4²•!2Äèøø?|!½•þÿÓíXRY¶¬ØÆ¸3Z’[ÅPƒ /8XSñ x÷éh[࣠R‘æÜŠ%$NgèGãà hþS9 ƒK­E$ˆ?#8ŠÖ嘱¤0Óð¤[»È1óq/¹i ˆzSˆ´„‰Íué·fc$ùhyõƒ„0I¦0ë%ßÕîâûsÈP‘úCü6‡¾²h>BÄHg» ìp0’9B»»'î[iì;TÎÿœþM";y›ËÄÃgá°úüµçà|‹ ÅòGÉUE]÷„8 ð¢ßN únÐä~˜$ëPÀð$˜5¡\Ö ~2 ;%Á‰ éƒÍ&øXŠúŒFæ(’‘jš4ø>àÑG!Þzá)W£h ïoˆj^RM[ Np=îþ>œœÂÑ×l sºÌ1®o âg*!Q†•p,BDö¶¯Z†´£ÐPk‰’¼"|FÐ)E\ë¦0ôQ%'ãÊÎ hvùÅÉ_,»“~»‚ïô8èéèèS¹ZZîu 4ÄD(þñG‚}~µÐ{a7@q2ì;x¨oØô°hÃ[ë.l(kç…㟮 ‡”È0à&¥š…) qÂjD?¹pS‚¦” ±R Tˆ@ÜX“í9nSJ"'nóϘÈx7òñ±ª”¶•[; «0D”ÚUj‰oEÅжŽþVïbáæ6³-µ6xpáðB ?Ðy‹øT>yN„ïô²|l‡‘˜(•Û"Ðs`üQöNv©šG\Dð±@B"Џ\&‡ 2 ~D>Ï®¦ª†j“º¶R¨'èah–>%]Y½Kžva..m²ÍRîKp‚XVàÑŠ42P¡m,¥ÈG¨]¦ZÉéÂÝÆù£|Dâšá‰"],þç *¡ú€ÍE¡~×”®CPðó/uWúæf´‘ âICÿ¨C1@)eÎ{Á8˜áµáeö-$ ï ‰œÛsÚVyÌ^ÀTdöøTòõ&Èržjší Ýžó†x_våMU<Ž@fÇ1ok)¸†:PZ¥ìÔ²QKK’ÀK÷)Þd4ÕÔSØôd3Oèª IÇ»ˆ=™ÆÀ^a™ áÌò8svZ6΢Wïñ`ò:Qy6¢vYsíÛš¥2‰E LЃ®ï|sy` Ð·ôàÑSõø†qßM*ã1MNêbW¥[DãW';´Ž¥ñÁ€I\’P!Y¦Ê†FMá¤8Y•`yô+%ˆ*kæ'N vDM!Þ¹Ü8›cœãÉNÈò&  _¿ž»âì82l$!eæŠÒbÝp—RfSe´ˆ‘5¡›C.ZÓŠiö¹tôuÕ‘­=ÿyï¼|Ç«¾ÀÏvÈCZ%‡ðÕÍ¡ô/'Ž–XÓ!Ò4—Ëß®•‰,#h*qs‚.2ª`¾ƒf'--£$+œç9(h@áP‡$B•ús@n9s9ä‹xXÍh§J­YCü?…¨P¤“à÷Ì\ÔüU0ÍD•4¿28€ùžÈxÆ`½8„…Ç0>öØoŒi¿(SHASÜçÎPÔÕSÊçRŒ X\,±*ª:¦‰lt#Ò~3óú1èÛbO'(ŽŠY¦Q’¥5@S³'°ÐcQ&‡=wç¯qé-]ÞRîÖì@Ò"ù ¼ R ÒÕtIÝ/!É3Re–‰ùTćâs'á êëÖ)mUá6¢¶Ð G"ÅÒË.®Á(ZL<*vM®uc_€²G¯«À[f‘Óf 7Ú"§ ü™2ɱœáÒª"IýdäDÓcw–yÓ@(Ð)Hzóh×*¬FÄj bÍ™€ˆªyÓ#„‡!ì|Ç„ö"] h#GœïÑ«ùqÆÝ.FÆ…ØõöÏ©æTïw‚ïß­ë½pCƒÄNÀºcëåùu»|¨›^|q|öfìÌãäEƒ0×6XzýþG!²± ?) ç9ÏÂO˜yPöòæ(V¤&VSÔ¡¡ {(¿Ç!ReÒO€Þ¶%âFï‘$Ìš9œªSÙ?WÈ•<9ŸdÒ ý¸À`½À‘å 84JÉ+ƒÜ!Ù]WÖó€P€{4ún0˜Žó*ydSc!s`Sžj@Rže*%•(ÝÊø0…)ôôûóÃÀæ=“ .-Hžf$DŠäyCá“k; }d:KàÑŠ'‡ÇÌ¡Å$:’½6ÁÑïÑ ‚¸cË'Ù0?©_o Ïy„=Ü“„àé$¸¶Õ—ƒóu;Œ v*Ð`Ù—$9RQG*[‹˜ÌT• ÁQ£[8„´` "ˆ¹b¥!†"jb`Ô9€H!Íܦí‚üÎ8„GÉ)ó@d rÒ`œ…`$¤&²2T¥|?<—z¸ 9' tkÀÉC-^xxôyËŠ€à§T#úÀ ‰^P¢7³‡æÝ@缇¸"ˆ0â~ Š~ÍŽ!ëI:†PŸRUÑB|”×îè‰R‘¡¢ªºh!äBˆLÈ©A¢EéJAôJuÈ)$¦Î±˜;"¡@´R€fÂ(P€‘ hì •M%""p¢䢣Š4-"P. TÄ-/ ¾H¥"ž™G’´!G¤…M<‘òE °i%†Età2ƒ!š•“ÀÊðIÑÄÄ@D†Dñè)ÐÀD³M@ÁDŒDITª€P€ú‚þpñw‚ÜßuI±ÔÉwŠœCCK@tK„œ9…¬HÌ9éн¯ÁÒKŽŒý%”ýî§b©K hBEòÌ`µš ‡!@L•ƒ};== )Ò- J]¦g&>m´'ù™Ëv~$&ø _óÎÒ ”uÀm.¯äÄöº Ñ JVùÈ' hÏŸçÜöù¯ò vÒa0°R”„I Sííöó:®ãgmjâ£ÊA‹ÐÐÑh@–BŠPÄH&UIQTÓHÿ@z½<º˜&º½JƒÍ92ú>£Ý÷û۩ᆼaGJÉ æþWFdüˆ^˜–á S5g‰['ñü¼Èàð㬤8¤X¥¡û>¼&3\D¾øãCX]øà~œÇüsÏ¥…χÚÚ)P£˜‡GC¬Ž™íãÓ£|'ài1-Ù«Œ1*c©$y¡Ã”ØT#޲˜ÅÚ-ƨ(0ƒÔÀ›˜;FCêX<šNxb{ÕÍícx ›‚_ÛQ-j!'Óü¡Š¡F¦)-FJVÓ~9·R¦Oçt3Uª#bdnL^¸TŸ‰Å܉q•ø`œ”@j¥rUÝãFá{u&– a!fhH]ÜÕbšg€g»G|8vä|—/1Ë¡‘É«1  —EŒÌY H9$~aÙw¹ ÂWÙÜñDÜĈ¹q,Q'–•Y´OºÚ;ˆÍÀ ÅÕH`ú·\¹¡”5|ŒK!.†"__©«5›Îy,¨m]æó‰«…û»oÓ›»è0’ù›’Ì“›ìÌZDíÌF„ܦå<¹'Ï „@EQ"5ýÎîPÈ@ðÌ„¢™ J”R€*OÊbB$ˆ¦Сí ä @OaPˆ=îÃr0Ã( D&\’s"SÓUX~UD ;Çmâû€ûÎ`„и’)ETÁfÁø®Ÿ¯õüÚ\µÖðVXi1¦e\6 ¾Çx˜)Ó>kíÝW§l!"€(;Œã†hƒa¶€?^è˜?/³!°vËÞòJúÊcë à™)OíÛ˜ÁcÖÓ]‹Z1kE³‹Mk[oˆó›+óg\Q<Š|É—Å<2ój$òœ=\ôEl˜³|ä>e{ëí€òÅ'›ÑÃCAŠSb‘,i–†ã +tJ`®¸•i±õÜêcß=Èt»€§bIŠO–Ý0nº7…âGXîË&Ÿ$âø®:†¨ø;ëÀôCÎIqÙ;¤é¾>“Ï>=ø7Æùõ½3¥2¾O.NBh6Â`$‰¡{`9&Ù5»ÎÓÊ#äŽî8qº{Á®iÕ& þÎh~•@¾a&zÄc…Äv ǬúºLA¶ · Ãé(9èIfÂð “^EîÜmñÕÐì¤!Š3ñìå„§wÂøéßù¾ðî ˜î2}ÏÏôžžÏM¼Ö\oÆð þ¿êFQÿ¡  ¥BþHCÛ ú¥30DJ*zB¨¸BœÔH§yšÆÈ_óL;õà; è„9)Ùr/9çÈ€¾d; ¢Ï_Øúc 2ª_)¢æ1Ä«€Çíã pn~×ï³_"n»A@y# 3*vœü¼°@üb¬ !¤9¢œ7‹žcoΪ‡¼LîôI¢öÆ^0‚bA!gèVá°!Á,’!MB!”Q¥JW$÷_Ìð<¼MhJüaé@èù£!xJQû—Ne;D¡ 9#AOHâ„#ö~ŸÏ¿®#ÖÁaLNÂcÀ`bæEC8=›>¿×¿…RQÐzh¤rÆkIU"ÖÞ·«œ{S Þb…#Ø^¶÷hr\g0él73xJÅ! DqQ Lb¸›øfò@]Ã*¬.”O’ àT_¼ƒÃðÈÿgœÄûû.$/ÞTrÊ °J7 TÖ€2DwvøÆq<ÒTùÒÜíAnüÎj®îœc! ˆª«â!óÙ¼ù‡¢)<¥îu€P1ƒð¼¤Ì×Ùô*5DÉ eËl¬b‹üNÅÅ!%LÿGßéDÙ(¥+å3·®zÆ8)èá‚N“ƒ$ªiÀ’g•CIÜW6ÞXx/cï/„!yÌãí)VÆ\‰ `mÉ€Os9:u°¢º´–ÝÊŠbËˆŽª²eo,TII*†WýäwƬø„¬IÓRh*“]Ý5àØì‡ó÷¨{$?Ÿõ¶!Ä£©3ˆ J ¬jO“â¥%ê­ ú•‡D}sX¬ÎAÛÚÇÀ`>‚ú‘̲#£L§ È‹ÙC!(ÂÌ>ûy!þ`ÔV;l@òŒMÉla *•(¨Y¦f“n[{Ø7äné~Í*c1ï®N«ßï_@€ÿ$m­D€˜«ÍrfI܈|tÈ\ª{oÚÿ[M›,I Ô´¹çûU4FìOR¹¾<0z‚é§šÞµ^‘-æ®TyŦH°ͧ„^RÎk¬4‰˜ê±u„|±Èµˆ6>PÎ"ctîˆ|›ëøÌþºÒpoUþéQCœûÐÀ\‡D ’R!;ž úà•È ·)@»û[tÃIØ"5ܶ¢šc9oÕeLÍ[`_¿Nw¬·—Õ»ö5××Ìû …ºz$‘>^µ@¿ÀTǹžšÛú‰ßÓ°ÌÌóJQ ²PÛæ‘þ„Ü”P5‡A鴃 MÂø÷<ÎŒ$H›Å“XjßOÍww~¼cá™âb2sN‹X”’kœ«a$C„Û’kÈ급.t«+É–ÒSLóëõµ~ÿ7›ûà¨ð‰âøž7£\¼¼ýþƒ­Ý;Ÿ”öiÚU © üôÆ! † €Ðí“ DU§âUßli á°Ä$U´RU ÄÒ”-µ“”ºÿÆqÂzx O–0yô¨CRGã»N‘;%GÄ ^¹G°Mßê=|CÖjp ֆNÉÙ=c}cµ‡2¨'Ûž›î5,7€ Æ1‹ 9dÆ [М@Ô7 §çº2'µ'´“`&çÉ|ówg¿ByÓ4Ã2YbÆbÿ³Z´‹GMêHL& ÿL©¨;¡;Z cdm#ü²jˆrÉ5Ò‡Z¦u/wØH!|¶®Ä™è0ÂEgå€ÉÂ/»²Ë[²Î~\%ª‡› ½IA36°Äv+@sy€ê"‚FF€_a "šìšçh•By´á)´7ñpëiõæuOÔDÒ›)qIÀ~öŽŒB —šQ{¥ EÞÏâÏÌ óoç´LCL— ˆb¤¤¶.î§km4EÓú{ª)ffîÏvþ¸ïñnòåÌó‘r÷´O1b6’tÒT¡úý?_WþΗŠ„(AX"‚¤*îÐ…À¨¦H6Ñí‡Û¿‡£5¬ê¨ÄÔP£ñ.øˆ&¯dóŸö N£ÞiCJNÎ"&$;fÚØ¡Š'f èaˆ‰$¼mLA1TQR@DL”TÁX*"""¸Øü¹Æ iY‹™•…i %íßvC$+\"âRe 4 6ZàÛŒihQI$JðõŽ yE®As ibó…Î7¶p´U  ˆ8w=è`"!ÈɇªBˆk™1P=œSÒ£I]á9¢`(®A‚‘÷¯1c·¼eìb†j^ÃmLÔâo2+­EjqFär! „5øç_‚cÛbŠ»’õŽ7*0¸ ´è3k$f(˜‚HžL{'@RIÚ¢Á,•HÀPI I>²t‘ä” úŒ¥ ÃJ¢I’‘D£È0Ïĺ“È?{†ô÷ÐuîDƒà†pš)øØ<œyyÍ©Éë9ƒBÃætÝ2†aêÖ;Ç M EÄ'–*í`ï37$ÄCN:W}8pŠbb Š‚–eašš*h¦‚""¢‹²`"(;‡RQM ´@”…(±$BN“Qc` (&B<µr5)üSϽjËF˜±a]™>¢¿Û¯<í‘ièÌ%à°DšÃ’JµšSêtêö™N½áJ¼©ˆI*ŠØÂ¦ÔSlîoÞ ‡\]'Úí÷ÀƒÔéÀB‡t×.%¤–D±l‘+Z¬ëù¸PJBöËÂ!aBbzC¯SŸ‡gÉ8sf“ÕA]¢¡0È8q“¹ù\笑ªq ^©XÇDS´–näRƒŠe…ŠE,‹UæLµ v¥.”È®¥±u'Ö4óßè«DKx Bý òN}/&á’a‚¥¦Œ»¤7íN$´fœcüu“®ñ@pš3¦­ƒþÁ!ͱ’ Ö—ÄILŠwÃÄ-‘h1ÊöM÷$Ó¸ó‰ŸìX0’v<Ë_Ûû|ùãTÇ‘5—)‡ûЦŒæ•u|w†™ПPc¿Í§ÇjL¯³kˆ„1¤ºaó2_)*j¯óÔr†PðIÎAF"zhõ7Ǹ®’†’ë7JãÖéºsõ|£Ë„¢ON:Ø8|©Ø(óNνƣÁˆ—8äË—sŽä.1¸àrDàã!†2™ÁH$T‡0‡èâ)ÂHÊz\y‘Gé( §J&Ü”ï†I;ºîüÏ—Ö_«Ã~ýàüÏ$¡킳ìçõýÌÀFÉTU6‰×‚î›ÃŽ&}FóuN‰›Ôy ú ÍÔßÖ(ŽÐ”ˆ£JD¨2Ep’‘‰ ¯<™õl;p„ßSúZ©C®6’–a$ÂZU\,ŠM4ìÚˆo 4l 7P¾[vtËD±ArÀ0J;ÐåòýøœDD¶œìCðórµzOå5q×.B‚+¿I3Œ[’îÅ@+õ$Ÿßâ¡ÞOxæØ,âÙéÜŒLyRí§Jd FHF„CB*°ÂC1”ÐbŠd=û9Î!¦4nrkKÃ<Ø ´s‡3kšJK‡\å\Gãrì1ØÉ.ÆRþNካ‘,QêÛ»Ðtáf8FFFÒU8ꮵX:Ò£±J„ÏYGze8M3!†ÅkqÐÁ#mŒ¿#pŽ85Þ‚‘+sHA%F1‡›™NBr‚¹ÎÐݽÁ¡#¹5/Lœ¢ª)¢bîï 4⮲Dް’AÀÆ2„¡¡h¬dÜ»ðfƒÉq8úeär m?QìçO¤QÉÑFí5Á]”˜ïÚIÔ J{5Ž0ýòr=!|æ€îõVÌÀº™´à¬t¦àã:ƒ6}Q™£ÂYb ‰ìÃ"vxýZk-%0FK;†¬uâL­­Í YbScž·•ÆÔ’º¸Þ®´Kh^߬k".öSÕ7õ]× ŸÕ¤§¾¾d™‡g  –”(% ±ãEÄ(`b€Ôr~ˆˆ/¨²4#õiO„hoPóˆe˜gÈÍpybÝ82Á¿SÕS´Ž’8’i_—ºßÎhÿ7ÕœâaÛ:U}{h@ÛëÇ%h) &JÈúgé÷Žû^áäÉŠœ$ð÷˜ÅTã ¦%$8€|9×J?+šˆ"iªJn¦ººñØJ@ý)8"Fk0S$L‰˜E‘²fO#04ÓÓs¡íìéiýõ-ûè)$Ë$*'âf˜ÀÜ ù?«Ôüœœ&ÄÈràk½âfÞðØ/\âìëé(u7 Žü>øY´Ô]Ãn–c±À9àB>G¤4 ýÓ!”Y®ëO˃Ó(ç›2Tã[ŽÈÂ?%oêÒá¢-……ZÁ†©UZ¥j`¹ QF‚ä`’ógB ÒbZ5ª?€=¿ëÉ=™%xG ¦“$ÈT"R“êIl8ñÔù† xGõiT$þ_϶~ë3þƒœh¥ZV¢{ d"©^£a7b.ß/ÖŠy{ª¥)|ˆkk(LœL‚ÿv‰B`HK¼ë¯G͹SB|‹¼4 —.ª”"#eÝÖ#EÇœ8òÔUQwtäU'XˆN !Ì7!Âcn*c‚FÕ¥MJ—Ü‘_."ÈKìË«÷L…=’ q57‹‚1½É ØÔ J'ôDàtÆ“Bb³ñâvøÏ‘çDÐ¥žcÎ{ñ80½ƒ©ÇˆlJ±7çJ›% „ 2 ³Œ–÷öïÇw‚¢Sä‡ ~Æ=8§ D…MÙœ`¢‹›ú(¼'šô–¬+ghY¢ïî󉔨¡„…uµ"%ÒÀ£•?af .µ³ˆÉm™Ö¶\K¾Þ?xëÁ#].‘%y ÀcAF0d€ ‚JJ+äCcÎ÷~w‹s¶¹¯¹<Å"œ%LZªEަ’óšÈ kûÀríA¶-–¯÷%C—“‹”qˆq}l¡’OPí™ØÉçц^PžËÓÝŠx¦Ó£éÇ?«õïß mH2ÎðáÔrœ0ˆ#IETB™Õ‘A‹*¸³œË>J¯k%ª£S \”h2BÁ3:®Ö ††,ÀTå; m&Moxk±G°Îovê)È8X¤]}z:g$ÙÝŽ½§hºÐtõÑ7^ˆÀÃIA&”R™N— I˜£Ç¼å@rZá¢KŒØNI^¬èª øEýÙAhÞÁ›Rs³~]ÇqœèCw`0æs~Á ß ¨o릅C¾L—¹/«ÞÀ`£P¹àí •EO" h"J)](¸—§í`=0 ƒ›%Ùò2›TH.ýÞgÃIéùö ÈòÌQJBÌ1 =dÛ@씪2ž# ifJ!’JI ¤„0dÐ'¡Ì ƒC2°˜H*0Ž&áw„¹Þ:=/ØlŠñUâH¯™I ƒ¦@É|Tó‡€ÈOÛ•ZTahb)”• JGÜèð?'5Uœ\³èô(0àJMPPU!H‡A˜BîyúAQÖT¾ îå8¾õ¿7'ƒÈ|aX©šGfjCh[bsë€>Ø”S¹1CØøÉÉGŠOt 1TÌF"i¶úFÚŸ#¾ï?×ó“DP™•reYR®Ü@Æ/ üã4;WÓï²CäI°‚WQǼÀ×Óh^å÷‹‚iéÞZ ðô¡Oaß@º ÀTÝæ" Ç4 Km‚‡ZÎquç…UÌdÑÀD8G:w DDQ%ÜâI˜b9r挴Mklc–$ÙãÍ#ËAÌd9<’æ*ªY³.$ÁU6 Ž<8ñ¦7°äãA]i¦8Hbá0VÛGœ à ƒ!"c4mµt0TÈC†Æ²¨…¢.ã@IDk%-:Ð2ÂŒ†vQÔ¦$¨lŒÐ‚¤l“óÀ8ǬcAi4_ÂID[ŽÜ#\5±¦ rI8Öw3…å±€¸Ä!pXC`Û: cl„úâœd¤!€d$‘´N¢ gf4Âm|Ì?<í8Ê™âÈÀÇñ“h‰8â4­ƒ ^ÑQøüp9³q ú‡·Ðü™½^´%i «LÝóFçe_ H!üõCEñà7Üo$Ûn6Nò äD‘ˆÖ#A¶ ˜3V•("ƒ˜ÑQr±Ž 1TCÇ… êª7 l¬‘ ÷tÆ!dn‘Õ%ȶÆšujÆÚ1ci31R&8•ÏëúÝæÏÇéEøumö ð›Àïí¦è“¹kƒ!¤!i„>»Ü±TÏZéáÞ4æiâOõýÕØÞûsè êøï:±Ð$W‡î»eÇxÑh$‰€D!èAJ_ÄÐ3d#¦ŒVšâ=ÝŠK™]ýZ!•ý§cvÍ¿ë¡=‹;’BGÔ‡éòµ§­f™×:h½xµ¬•:¯&¨N}ÕèI7 éq:?ökÿw=·ãZXwÓ9é.u-õHR‡>_m^c8õ©=&ú†gö@é&5ªzÖä+êˆÄ¿8×Ü »¡}OòLhö< ¶lLͰíÍLDK«™®i+Óžý±èî°Œ,»“Cª‰ELbêéÒ"ÞzÅ™úî8÷ÅÖ^ÝN_þ.÷ºì§3ëö§~Ù¾"ìòj;Z%’±ÞÒº*©ÑKÞ'Æ8ÆTOôÞ5^~¦Ò4iÅS,öz›ãq‚rÔ#0ð™að‡P›Â;å'ißœ›ŠÕ[Ì>Ô+·Ä6RP·Úì¦uœÇ|¾5Ö蘤YšªéV×î(§4èFcÆ8—çÅÆº×3Ä+†˜×*m:í…LÃÃ’fÆ.SoäxŸÚFv nƒ»–Ü¥$Ý;ÒÈ¿n*†Ãã×?T¬3þ§oXø+niq:^ÜžŠC 5º>¼£&ô¢"‹qT¢„(™OÆgRuŒ±çü¯Œ߆`¨w®çÙ&ó¨ôŸ®ôE·°™@%Á¨ðáî#žï6§`HúA¥‡ŽoçÔ†Uüútcþr¤é íñ<¢ä1+ØB¶L&%ÐÅÉ$ÌêTFŒTK“ÊEÛ'Â(ÅÚ4W m¢Iç¾)ÜÏ¡s‹FNQDH²Â)­Û¥íêö4k*þÊ!ê ÌLy'„Jùx+æé ñŒpó¼dí1oV¡ *W$N‡Q)H Ĩ,Š´–IJ! ‚Ý¢På$ Bk›™„®fsbªñ,dH ’ø×‘%9œRwj–n2%éÍV>ƒ_¡Œj®Â$þâ1qŽ¥T¤)­¨2¼Ÿmh""b«!žÄ2láÀ³ó">I=˜Ææ€ÂKjGXcÎ\cèŽmÀÁ§-6éêw"®…èåÖ)¾¦‚h&šQÄ8½73—r¹ˆâ2÷ï)ÓMÝN1«÷®‘´`vŽ;ÃÕê9¢yY“#/ñ«¢‚ FWKc‘ªh©Õ¦gB%9wØçŒ~ê–¡i³öbštó·T`Îi÷ÔŒG5FÁ刞ø‚U;úå³§t⣙˜¸2§¾â#Æ!„×ñÛN(Ô5Áz…=rþènWß'Êîv¶»µÕ>µnå™é™¢*ú~x›{¼³ÄåX‡Ç³–»h€×N…±µ6í»LæUní<âéÝåÓÌ7(`ÄÞÂuæ%ça[1™(^Â%ðÁ6ÌÏ ŒláÕ­“f’‹1EF%ŒK±Â”1¦˜†núBœaAîÜjh~A‚pØG¢tLÅFDÙLÁnø‹!wp{œ4¤Z¡{Øåûxó¾ó °åG˜c2ù8ñÅTO:† GÀ×¶×7u!M‘)‚üta‹RGp^ U@¡7Í7s½BL5Ÿð6=Zf*.#sÁ޲Mˆ4ÓDÕˆŒiñç3&Tgy•IÝ:c"Ћ§¬@âJé,k.-ËÄæ›ÑסÁÓŒà‡}æÀü*\÷ƒKZ§6÷úLÁ¹©¬Å’?.ü¤L|xÚ£>'wÇsß0 äÄóyñ•#Öòt{®wˆãˆÊKâìB$ù[ ÂRë«.˜÷ë‡x6šj_ýëÍÛz˱‡åÒ§˜ô.ÿ/b¬ñå²zy+ˆä9.¹Ã¬kѽèÒ)¹?Û—5ëVàÐ{m ÔÀ$œ)ùêjÏ£Eâ›Ã¬7“›*EO”Å•i=g2N&¬œ£Ø|7ƇŒ¸“eI.#éæJ!°>aÐkH•?C!µ®g[LžÁîªûÝó±aáÓ N5ɱ*±~-ˆZW€ÙéÄÕRjÂi¦æhÞ³Š}6R²CðÂx·ÅùUl1:ßb$Œ¾˜ŸÕÕõ£Žõ FS66Ñ3Pø²ñòÆð½E Ðþâ ™¤qPâºøeOIiسSªrõ†;·KEëóxt¿r÷rbRhˆ’"¢¨if¶%¨¢¬‹ ®ÓkÓ%Y <ATåy±|‚Èž¢K _¬ÌF*`gÏqRÉ!ðAšºÊlì鰯Ɉµª/×7hÀ˜Z˜~õ==r¶e4‚c‡iËMc§¦1Cj“*åJ‹&HÁbJb<«ÖŸÊú#K ¶a7 §~ÄCÂÔ&Å0j”Q puV v‘$FTN-]bt<¡'˜¹ˆì¦“t’¤¬Èì}OŒ H§»o ï¬ *4&e$S‚UÂS±9™:XQ2ÕÚ€žN Z-–Ð9Ö$Wª÷}æð˜|1ˆ2˜–GbŠ€–qéµMT8•;ކµlÆ0P:â1†‘’eHEÚ$#±R”mèyL,/×ÂdM¦ƒhÚÕts§:MÌkZxÓuG‡Á. [qÉ_:s¥àQEÚxܪr$+mZIZ¦Hؘ9ÝpQÍ”^JHHÅL§„mÄ6Iws"=ÁiS Ï y0QKà&—\ïQ &Ùz¼\y1'5ÇUÞlŠt“Za™ÞˆhIñ2Ù:gˆÐçmê-ˆzÉ0Ÿžø²Æ[N\ 74¸ìèwyL8ço2\Ñ!IºÛk-.AOâ(Ö³!r,åZï½›V]”kp +¡nŒ‘ƒ$[à¿fì§]<ž‚+5V¨ŒVERd„DRDêžW'N9šji¤(b³¤¼YI€W,nàº`v‘HÖ9Ófg²¬¼©íƒKN$´&(—/T¡lXE,j¨•¨Z‰¼ôàqL’Ù Ð&—Ê/oLרtOzc$û&ÃO…ÂÜp¤øáÂÒÜ—X~MT –Ía³=Û¨ñ‰ã‡uae#O£+lØY[i¢"óâòûšòO(ÛÞ´SJŒ]ÙÕjxΑ\‘”Nš·U,A¾ÅÜ鳘â–jgÓ`£Ž ‹w9yí+C08™!™‡r޳¾0ÈEŽ¡øÁRkÛ-•vã=Ù‰ËàÅ”(ÛúèÀ®œ4@‡8úû°ÎBK„®5Tt¦Ó»’Ú‘wÄ 0dÀj©ó ÉI§"œî¹œTÞ^tª9‹DòÛ©£XYÌnXuáÂa?e]|."ôþÉÙų^þm,ëÇòˆ_Úî_áƒr|á!i¬gžþ·¦ç›»:>$èÕYF&U!ì•1³¯7è‹Ý ‘=FÏÖ}QôŽHŒR"J¶Üs‡™Ïà€ûa´k`hˆä†¿œ–¹=%qùñƒ ¦sAcüÚÿm@Ù´P›Uèi?žß¨Õ¨(ÔJDZZtqÓ[6Ò˜|±”s‰$¢äÑ´•žëÊf°sÁ(m%#Ф¶PÃÆ÷ÿö.$2Á{B¥~­õ¿yT[5EXsg³t®Hqºâ’• íRzêËlctœÛvÎòB†ŠRyG8ã&n°2B†…õûävÿ4ºä?îÁ¥÷i?9w†Ôlciéuô3y6²ØŒ’‰Š’Í—îùæd½nçßCÎÁá¤"t*0 Í¡ºNN3ª¸‚¹ÕuT¢ “"†¤“.¡vŸ,ð«;!j&Äâ~¸·gqÔSÝ#ç‚¢ºny£øF 8ÐaæqÃ~ë—i gí%³+áÿ·aÛvA¾Úÿ×áaÏ9$Z9zÛ¹-CA âbb™íÜÞÌ }‚ V…mUérÏTľgÖ=™V?ÙM˜½(ÄGÏëÖ|ÛÉèÛæìNóöÄ¿¶õ|+bË=ôá84¦{â È>Qú­åx{”îÙüþÛœ¬À÷p—‡½s5Gé™+?ÅJÕq¡c+*OFéÖÓ4â’©xvt'rùW\E&Þ³uu¼q8—£-D×Ìd™µ|áÚi;¿ $îﵩuH1œVxÈŒœf”ò[‹8ac:–â“I¯ÒÃÝm9 [’Ù~4×Û8ýwÜaaˆ‰ýOI°›ƒ¬ÄËí7".wúE¦Û¹…¤3†âxO‰JÈX¥&¦áç°`ưÙP…áhy¥ƒX0ÕCßÊHR;¦ŸSúç4ìʱ¨?ÎŽU@ /qÓJw~Â%ÜÑÙ|´>ù\Àq¶z©n³‡j+ÃÃAâäB'’“ÎqÚ³LÐJO7MBê;MD*6veÙÆAo•Ø…’4ºå6Váæó G_µnTŽÞ–´ß½/§FºÝŒB *­Ñ룜•%Mâ¥ÈÐh[BAšúpåcîÂ)Íýéc,íÂ퉀ûY0ÜþàËFãÆ1= ç.ÈG<>»>ï8„—Þñ)L,áàw£»å6Št'<<±ŽËå¼Ú)°¾y} ó>‘Ã;Ö·˜êc‰ÕE¹ãDá¤ßS1ɦI”^"»MúõŽ"Œ1¾§KLoìœËèm¨Áaq€`Ájœ æs¹úžï…ußA˜›ÅËçR‰Î@6-þ¢ô¨»{!§Ð?r&˜Ž»ž/…ŸôÊS22“ŸKz4Be´ŸÝuœ›¤ }Z)fƱ͚(÷Êy§ Q>Oý#Y6jÈ8©nû¯•¶Ó¬EkéÎLrççïåwTá9û¼]¤IýÀ¸µo®^V®ÿ{pØ­=S‰!Ó…©‚@41ü‰l®¦dì éW@]è™í“Æ—ú¾>šž, htYIHŠZ´K…Kz0ÒÊvue4tî3ÌeoP@ø€pO Y,Î7dBdËZ7Žj þÎ5Åå¯91s«ƒŒÒóÇ®DF§®¤'½«4AÏ$iï‘;¼®êä:ft&`¦P¶Ù ~w¹µþQ×½/ÏFœ¨ë­W’?ÌúþüW/Æ ’8€fÁÅ´T@ & 3Yœ½À`üf°{»Vž÷u&ö¬MÊ×,„êRèCNÕ¡ê3@oãÇ´vC­C³Å䥹†*)P÷ò7ûýñTc€›Ü`äDD$º=‹È?` “HØÇôã»ÝñõÏÏ«øô¹¼kHŒa¯¹ù5ê‡Ôv9¸`µ˜@k4PHO‘"ž7Ýaà®ÕX¶Ð—îo_=ñn¸ƒ`ÐÄáÇBzÙ··è°ëLb@Ï£õ7á¼à&Æ_õª È!¼æ=÷ÿ»AÞ"rò”¸ Фàœ>Óçþ±í7š¸ØVzcoWÞÍ¿ð73K£ Sý‘¾êwt`o«ÕÉܨSA¸LpZ”lõ~°Òa½ÛZŠ.6N¸ îßôoµ€þAbð—‡f?5òó;ÅÄ…EÓÔʵ¢V±-éådJÇš[KBÃ0&A­µj¨8«`£³*¨ÇLÅ®2`Ô°–1@$Ö¥¦„ô©Â‡ly¬jŸ6§k hó“ï¾v(¬J*“ªUsU´peÌ숎Ñ*袊ÌW*Þù½(B!EϤڄñšH¢Dª'›\-;ÍÜÞï º{æïw"¬×0‚,ƒX€Œan߈šy»°O<PøT›Å™ ma„ùtšè;åê¬SJ‡! LÜDÈJ 8ÁªÒÒ®gî} `ªM‡ ,ÀEHž“¨âÑü&°C£áëȇ^` uf@²u5Ï£ío†""*£Ï$>Z° “¯ÊQßä!€Í&ÐRö"M!ƒ€ s‰‘Ô!¢Á“•C[„¡Xš¦û»³G ˉÉ“¡ œkYÁ‚C€’ØIÙb©FÉÞx CìE"zXÔhY!ß"cˆQLÍ3$ËT*A#$Ë%ýŽaPÄB¿sÄÙ1ª21ÿà ¨¥)B!Æ`dîs9ل׊{A?Òà$7…ÿY"z;±:ÿˆ=¥O|Æ–<„Ä=Þcí¼õÄ€õk‹þ‡áú}ß§gèøþŠªªªªý5SM–ZäY×p&£ £ôN¾®‡1MÓ-;& -Ä÷óÆI„J4T¿$¨d¯Çãhê (Ú*H†”˜ M×+Ü¿“í Ò»¤iO’ú cprI£ŽàúÀ×j¦•^Z$áÄn“ñ7¼?VƾîG¶ÃqÎ@çY‰ ÓŠCÓYÖÂL¯Û¾·ðÀ¤Ãž%ÏJ”w”UPë:2}ÙxKÉ¡@è[šŒ Ø 9§ˆÌ¶³Ê¹ÃlaîÇ#–þËúA¡ AOô@8JÄ@¦äá*fóÈDu/)v°Ý”é°Ðf×?©žCÓµÇwXP”Ò[¨´lk&…—9g§1w;€íêH)…žs¥îûÝ6ö ?|á8@"hЇ¬ñ$"äfUEL¤£‚I Ìøâéá†ÇijC·ë>8œ¹!Û¨(O¿@{%=;¿WÃölweFTᘇ8 –"%ƒ•ÛãÖo|úÚÚŒª!C²SBš‡Y‹yhºf­°s¦9-õX$î5Q†ÌÔ«O!î¼»+æ¸ ¤œO 1Vˆï³­£Ôd1ñáïzï1ê: œˆéÝ£À¦¢aŠ„£nµÈ ŸV•ΠìlÓM4Ç`zL¢EÕvâPG( ’ $“˜“ ’|WF#B”˜wÂ!ðNåH(iÕO‹5Á×}Ý;»¤€hôJ€ô¢~¬Ò˜†Àî¯ooš± hõz "ó{'¢t¤9“™Š‘GÏöU}iª–‰D5‰]¢duÐI/_ „e0þ¢ ÌàiŸÆˆ_îvaàá‚´IÞó]ÃÃ|àÒÄ0ÉŽYN!/±CœýÀ9ÇÆ Œ‡ppÀ¸hg¢É&HY¿ÅD_à¡ñ×Añ£à©•_GÑ?é:ÄõÃ#! wŠø_thù=½ûÍÈ¡Ú9JÑIZN½ª)õ¬l=ÀD@2²7|Ú¸»ìÞbj¦Ó«R`±hâê4&Í+V•ËËUIi­’‹gt]µ7áEŠšžÈ»»  ¢â_µÄ¼ª1”SM¨eÕ W„"Ðy'Ç|6«½Oƒyëžsð;6,)I½×˜ÔÖ]ÁzÎ9\êsŠ÷u6£yøñ,u4¢“éó†D;‰ç@1…è}ë'"Ÿ;Î4m›‡7ÃÒÛ²âO›Ë³0‘tº/ >²OG—^ “apK@¹"aЖ½üíADL†#óHŸGÓƒÙmÞ˜)½@Ð0ŸõG)>õ¶ŠKÍ€ÿoùßó’éz’,Ÿ0y$‡ãøòßÕ‚`yRÓšæ+UµN–4Ë (vÎèœd GøOÌ`øÈz|Àd¿²zé‘¡»1ï3£¬…òO$áP^Ñ%xÃY 혎C’‘?¤—·µî]z㔆#ÊÖ¨¢¶ —Õ¡f.©œ„7.€Ô2¡ !ò‹Ò 'Ã~¼˜—²\d½xh¸´Û7 „;j móÔÇJ+5 °<ŠÝH‰¶)m ±C%r…‡ÿs=Œ&X¼h s0&h)$ÕùظÑq õÞ(dÊJd€aÐÛY³ã£¯Ž¯ÎŸ=uRUh›S¸’ñ£ÿ†õiY̒Ъ_ßt-¡» KfÍYDAK¯Ÿé&ØÃZé Ù9B¹Î³£s¨I™ÌlBÛòäew¢?ó?;0ŸœibãR;áuQýQ½“ž|osk É zå¼ÍÞz”îry¢U†ÆZÖT×;ñ‰Â˪ˆÜÁÚ“lµãÝs<ö{å8‘•Ô$×Çhg sPs=jw4^*c9Y¼cL[ËÀ”ò£‹y¬EÓ?<§e¬eï¼ð£}oürÅGx9–þ+²’Ö†d-ÈŽy ¸]ç^5ÃX&0¸ÜÊÇ?¶e•wcs|ÛÂm ß2<–"h ô‘Aà®yVê?”9SCyâ®"Ž?•ÖÒ3vL¯ŒФ*#@‰tá‚b>gÂ,J—·Ã PÞá⨼qŽzÌ ´I#(€3{£¨‚ SÝ£2A6õ)@ÕÁ¦ Üµ€°Hj!ñ,˜%ÁÊ™aK $ìÿïŽe¦9¹Œ´?rQyFÑ%4Žq;VU”ªâ¦7-JBòU®€©'pÊ­:é})XUïorP.*ê½…oÃsÐö$¥ôÿ«¶øçó¡Ž3Ë£¶›ž«ÜDa|ÜfÁæz½s·Y¨t×RçgM& ‚‘‰P)ÐDBr£ÓœuÜT2§yÔÙ·½fµÛ|»ôT3š­`3•¦rk,jHQÝa%‡o7EÈV˜²iñ$ȱ5ˆW 4À²Ï à˜ 7ƒQ rk*Fx¤®HÍ'Re`[Æ=u®8N“á—wƒ7N〬Q‡çªȬ4ɵÌ£$œÎæÜÕRhË­iÝâ=]u}çǧ:èìôùÌr ÏGdív/Lèý|Çi}Xþø~dÂÏÊ! :û÷BlC´9 /! êBiiÇÜÆ»÷ï€Þ–JÌ-Ñ ™ Žœv6%Csà}Õ`˜2ñÓiÑ»¹-²ðuc$R_½DU!Ìzvíƒ*‘”`„÷AÞ2¬¶zRxzfåEÀäD8û"dg°cÍàžù|R¬(ÄÃMkŠ-{\êÄõZÓíÉ‹}e¬v_‚nÆ£x&Æi c®tÖ‹C@ nÜÃ-,@:\9C©­4ð¦ï¢C»FgÁÑ齊-quIVëÈœ7Íã‰u¥(ˆŒ`°44Æo¨è‰U¶àÔ¹ s#…j¥«¦’Ñ ^Wi‚v‘œNnä v·q(P<4#|M=µº Úx$T挻]½Ó‚î¬ân³Y) ؇ CÎÜLM&åìm*2ÙNõ’èQSJ²‰òŸpå6Dg’hLnTÁŠb÷ƒw‹clJâµ5NÐó¦4¡NE{ÒšpÇUQ†'718_9hÞ9«¡ré#”3¡¿“.S¡åô¶Ð-ÏQ6ú%›H¥qÙCM±™aï!"¦{c4Šd*˦ªHÐãɨÑæ…OrÁ£&¢B‰N fL’dÀ’q‡&"„Uæ¶¢;øšÀU1‘x Ë{“n9ÅÃC[!;æ!_„uË6)sŠíÄ;ºa: ŒÎу:¹-ö„ÃZ YŠ„Ëuw=ìkÛåAMÎeÁ %’L œu-Èù•¸61- 4¤ ¶*sL4'Æ1A<aWý§´Hk,Î2„Ì<=HÀウãÁ g©Ó‘®–ɺ[3ULËèt&\£ÌéÇb|#QvÙÓ4è;µ´³5ŸR1£VžÑå1{±vL»0Î¥jÈU: f@éʱ1Q„âä|®èš¨e0‘=8V–páh§K¡+Zdöð1n¹û»äÄÑë9¥E/—V¿NÊ0Ó¯BωmÅwLØN£Y>¹1‰¥^kiy/ŸyV¢5$BšôL dhˆÀòG—†Îg Oâ8ôŽ)ÍÖÅ„ÝÔJtïS]ÛH›~ CË=¨\ËBh¥”j#@,…×b‡öi*À—pÓ€í©&“§{1‚2™¢uÚMB´*ÃÒ• <š!MH@€)øüîp¹‘Ì{ÿ®ñÂwczL<¹£†­»Ë·T„Pìè$2 w dî¼æ«irDK*) ¢\tIJ * q‹0VüP¨hŽN6X=‚b"õrèHÞ¯¿v7Ý68B5"ïP©Ä– •ª™w\Ô‚jL]Ý.k1Ju€À®“h4à|ÏóÙ,a•òî=Ek|Q–áœ5þÿ‰ú„Ÿô?(æÌÄ1 ü°™?4 ©]@üðñeã*á”Á 3 (J›{<4bL]ý_°4Áx Õ“º‰D~§Å

È´-Ý€}…ò E¬Øüµ›ÆlFpfÖÔ v)Þ¯Vñ6p=*!È^<Ч¨*€Zׇ†ï ï@D&"HSS!:gM2ðU(QsNÓaÞk¤-µxÔ<Ù$¡VhÐkJåä¡§Î&2¾ö"¥ª~Na÷0èµ(`4„ÂR´$BƒÏ‚'„‡-ƒ•„ïÖ!Å•ÈCïˆf €‚š1¡ )ÙqÉ,©”â”KQ'Ú@bí•É(/Ú.…Ò©¼á@K 'SÄçÌP…,ÌQ2RÐ$E)Cå­¡´`"¢d)ŠŠ&*‰!  "*>ð¦2v‚i…»r`óîÚû·Ï[}½¢²¬O-Uiû—Ò½êø¨RÐ4‰2CQU …¤ ÷êÕxNÊ[èݘ‚5T[h5ÌÏ3ÎCAUÄç+&áËHD:0 ¤Ñ$¤Õ8Øh“†ãž/¶Ï›;ÍÂdïB%ʺrºd¥rl¡À‡G»¥Çr90 C€þÏ_ âëK`ÛÉê8:d.&!OX:wuG¸Á×¹ÜÚ^<ç 4¸•ÅAZ ²à‚†’±% ¤­Q‰ŒcUÌw†ì³'½’gÂÔÁÓƒÏ^tŽ r×*د+m—S1 ÝÑ8Ë…ÐŒž¬Ã!™&Æ´h O»0]ìHá3¨Yb^;yE¹§oÕ¨àç1È¥8JcñšÌÌûK†È8 ¦saBZ´›5¡žG#¤ðóh8Mi7œð:ªètk\ŒWÁ †+“lh³}N„bèòaÉ=#FPö« RŠŠ%6«6!úe•¦Ò|´ŽÁ$mà#²r"%9‘N¬GG¦µÖ¶„“4·Iê–%é(TWªµïׇžÁׯÍ}aEzÀ…†€gIÙ­¹ñå†:ÙUŒÁN“£Äz‰0·&Ê.î òþ˜=¿u§-$&Lzöd¸Û^{ʨw*S0z^ ÅRk—1q(W»SˆQ5švÃ)#TÅ  °¬2–Ì•EܨY¦—KºiŠRްî (ÞîÂNÀÊBdé´7‰Ô˜Â°Å´¿¦:@Þòæ€]hÈ¿_¥)ÈqbÓMP†„ÐØt‡ã6Ý8ì„JRÒÑ11! ~€€.ÙXO2›`¢³–áµÃe‚-© ,CJ- Y@Ò]¿*ôÝlq¥R` ^ÞÉ*°ÏÞÎ ™K7+\°îa÷Î/ãp;¹öºdÄ•O|5$¡ŽNðƒ»ˆcÿ&P×;þÜ~1?ø`æ0XÃi-˜¤’Ò»ðƒ' f›fdy}$ì ÜäI+ØÁÉB‡²:4Ñy8ˆ>àˆ‰ã,!DüöŽP¦uº4*½2I)ËŸE~ï†Ïú¶‡$ë`¨ôð§3ãÏŸOü:d/ ò€(h ÆÎ–#oáâ$„(òeØ•]HA(ĪP (½‚‡s LK@‡!스y!¢…NÊ9²hÄ¡@ºÐ’¡Â™/™A‘¥ Cï„=ÓÂh;}¼°«•óì™±‘T9TI†=q<-«fŸî7&7rôÿ‡¼ò Î`à“Ë€WÔû~hWîiSž…~ ¦ "%b"…èI+¾kñ¶dÕGtóæ†ó¢ ¤€d(PW¸ht§¿Ç"riT=ª¡Àæ‡Î' Srä[Ðq8BysÁßÐþC ÇûCõør1Y Û+ŒEÆ ?´?*þ—pº„‚ßn=Ò`XgTàv•wܦKdJÚÑ1vm1¸Bo™òq›†û1h '€™Èç¢ÜK¨ª(È`*eá,ƒ< ëPè”ã˜x¸›GvÍ‘ñx±ñ(%ÌšØc^óÊäWÒ 0BCëUÊa…¨¤* ¤d‚b(¡%H•(J‰‚db¨ˆ)¢!*˜%ˆ¤Ð‰">}.”ž@jàÃã‹æ†öáQɨªh‰’hŠˆ* ¢I”ˆ‰‚SÆÆ‚@4\u ð!)@ w9ÔŠuFwO2Ç#‘ÄéÌ}#j©+Àш ªöge(—q Õ(aÆãa`ã8¨qËR®>\ªt±-˰Q*q™Wnxº£TyÆ5škÒÖµ¡ãS›Ëš»ŽªâŠ&6 £PJÆQÊÂÄ»-L:‡"^R‘ÁÐÅÈãJjVͧ`H 3mï7ŒH'Æ<®a/5+fNÜ!¼u¦¶k‘CTÓàQ[@¬}žž¢íZ¡« ûÌå …€ê‰ª‘˜@‚^ Ÿ;‚(ŽŒiƒì§÷&Co—hœg‹x1Ú)çèt;…ÉF€Ü%²@"UØ8€}_"t}\xªø@x@—R‘÷@lbAúSÚóåÔ”‘ª•ôWêÚZ6l‚æ(hiÛøw“œÂù`ä“ÙÓ:ª†ì­fnZSº¶œP€uST½?pÂÙ„1$ tŒ˜5SfÍ, 5¾o÷•w§TÃô{ëÛIÐgñò²ß—s]=Ø€f^#†€0V.¦ÍŽ˜±¯*ñ4“²“K*iÉô?Z„¨(h…ús_›¿æ~ÞÂøð½¶×8„üâ¨$nDàC ×~î-Óßxêôž]ÝÖUP¨÷¶œXeË–@Á«ÞLÊcc=›¿r±³Îq1¬/ÓßûKûiþ´º z¯Æˆ{– xÒUé“R3Úðdá pÁMÐØ´qûT*”Ô•~jï”~Ç[—p‘ ÒAR+Ò =Ø"¨L¦¨Šî@ØG˜GÖ°©HÔ ³!LM D(q‡ô{7|étœ£¬òµöX’óšY"y¥’%0lR¸¬@Yoô®2>]¥C@E" ñ¿ünqqÔÀÁì?Üí(ìå3õ]z€· sáP?=ü§€oßiý}'eö4êB…—@h1•¤ÃŒ’’³* ™¡$¦PN¼´–†ý( ©½‰Eûàèb^ÃhÆ!ÿ)Á}9’à—.Â_ù`dų’4Ì)R}ž8N)Ab¬€Q76!99àX y´®+§°ä~ÓÞî:¸f`5«`2g('c ´Ÿm°4·PI†¡OvÊ94„H©@ªAET£@.Û* â ††C]Q×oâ0ŽKñ;»ERtuÇ»@¾óùÁ| @ëÂŽ€J@`ä'Äi=¡z;¹óó¾°_AÈ?‰ž™ˆ)SüÏ£ó~ðnYSø&ú07Þköö¦_f>)5¶ßhÒ€ÀIæü8#Ývɨ`yJ´!æxóôî'X'ãb¿"'xƒgözN–œOßΠUTžÎó‰'0Ÿ$‚BA©ú÷9lÅ|uÊ.†4±"×л§&š(¡©ç&‡Â襳ÀÁÎpˆâsœá‡(°˜¹n:F%JHŽJÁ>Ô$ø†89ü+铇(@2zø€A  À¢ýÛ€w€#üN`;ÖGø0úþÄ&¶Ew/8~»~½¬¿£>|ÕeÝE((4BôÞÉ‘®uºr¤c¹žaÏ0w*i #†eåܶ4Ã#ìšH(ª†©ª¿ŠÈ úÉA5 ’4+ñœ€6ù5¡ FB{ÈG*GÆ]ò'·¼?;؇O„Á€;=Ä(Ð4ņüÜ´ØàO§SD|ä7IÜUUIMª×à‘ÊÛ‚Æ®<íÉ(`:M$rr1/2Y$9d¨8l c5DòÌF·"aç uÁØ8}õáL”JË`„Ë CRã“BR3)BÒ%(µJ !æé¦OXÀb²Õ `<<ÀròO{Œè@ÑÒ¡Èð‚pr†`íÙ‰ v=C7âx(ДP£ìÀ:n¡7¡½x¾"‘9@ñ@R%R­#ÆG‹ ™ ;ïd„OväîÏeFÞïÎ~YòÓ5~€‹&>]“Æ'uÃ=ZÌØƒ;IÅä 1çSú]owìýXÄOR)EP(OÒxkȲPÃ)Ëi>±Ø}Ø“È|%¬EûÞw¯dÃñþ¼Ü™’ƒÄ—½ÍáuÚ{W ¸£ó%Á’:OœÎ0ÑFü6õŒwŠ—Õö?,!¢Æ>g¦qÕì2¹•é «Ý’(žaâÎ× L!e0dçÆsàÚ‡°l”°‘£m§ï·yÕ75x`o,L3iÐ4Þ«¬™D˜å |e"ée´?ƒ8Àœï%ÓAÖ¢i‘þŽ?›"d\×)–ýïÿ§Ž(Æs|W¢•ÕgÙ¥0¼·ŸqŽ©ø|ü„ó·$7@ïÚöì&ˆ(MÒàÅQÇo`@º WÉ>‘íÑá £n¥6×ò@> lBRù¬ãu€Ie¡¸å!?Ò¸.ðßÍ+’@žzb‡%J4»˜ 4!8@¸h¢–”h޳Y¨ÐT¦ Ô­VÒ¯%4‚jî`P šg44dáý`ūχ5¸ð‰W0ñ@~PǶšqB×:¬-àgsƒ¸“Å%Àðç1û•й•MMQ*ؘçf^÷/`t.'•ÎóRJĨRb͇°äQĉ¤]n„:fçw.®öŽÔƒÌlc’G\±¨ªhМ´*¢ÖM±[jãÉyÎ ~Ò€£øe.üCª4A¨u á%,ÕL‰•K T™LIShðÙ|h¢C•qe†óÄEý*0C I2EzBºP D’•¥( —‹‹ïÑä´(´±11TÉ>𧯵ÒXö{ßíp|'IúǸ³;` „T|‚¥$a‰Êå¡@Bl!œ ê£J ±+°»º®©Á"pHR¢=u* ¹Š&\Þ­—Н9dšNT5@D%4)NZMZrú) 1!¤D#ªÞøE<æ¼™ ¾ » ±á¹ I”ÇñÆÀk·Yˆ&ë–\ \ÃÖøsÀ  … Zï L’I#¯½JȤ©Ÿ‡ší4£pÙ¿ªŒ™ïKŸŠ«êhhXÄF¥Üj€äÜ1ɹKˆ[¸±Â"C±0¶'JR0K%Ãè_¿Ð›—À4رd˜IAÖ½açH2yé ®3Îÿ7ø è8Á D!êB[ c±íªâUqª¸œðœôié:Q%àñ[:™Ãg±Àë¢7-AÔo%ýQý¯¾CÚË“jÂcõcOë }M½0`õ¿7˜Ë4Õ"ÕzÄ“Ïò25%Û*0ß!J´=œÀp9§C$Oáq=G( ŽE¿¿m'ˆCüßÍ‚¼àKFª‚«C†gÙ åýª‰—f`n•!z®\ñ¡ru5öÎlb 5Òi)ÑAýøC\¶ŠnåÎ2‰ª\Ð(Ð[4DÅsœ¹‡’§-óüù?p B>7´!CSÃ0Q)ƒ T7©æ…wÀa ö[µ€Õ#À$hœ«’ÑT*rƒPw°®C´¡4èGìÈ4@ *MêMBBt¼ÄÿŠ)V  N¿57éœû؃lÊ\†èHz‹ÑÂNzÀß¶ƒš$ðƒ—“Tp´ ’;ˆr´ÓJ™!¦l¸e%ƒÔIÄøIÊO_Àˆ'ž0ˆ² ‹ÄÃ"ù?®ñþ’Ëì2Ì- Ÿ¿™Dkd‰äC织«ô –bÓ0ë çìýÃðQi^Ô% Ur;$"Ÿº Þ Vø|Dàì¸ÏeVrùQè´ÈùƒºsÇdž‚= ðà"?¯úóŽÂ‰ÐÀœT“œŠßìazÇÆ#Âó‹•Ìëý>CK÷óP†âs«uX¥f SðMšÌC x¨š ºô{ß-ß=1è‰ æä϶ÉRŠbF` ¶‘¬C‹h[¸­ª(A'"¸£‹1ÕD*ÛÈØ‹‘@ÅÝU™Í`—¥É:äŽÂÕÖ×/À›O¾CýÞu©9&å›Ù‚¶á2Qƒ!béêo±`à'!%ö1Ãu*(t9,À”% ͱ.67áD½H!À*ŠnË›Ì`9,`Å §^.‘ò™ vù3Üpƒ”üeøâìÙ„a"o|Ã),í2ˆùyªh V­5³H٢𚬀°–>Í5ÁF ¡ÂNÁA.K«üœy`’W0…,„Ï<‡7W\Öœ*PªæÐü˜¨] 9päRXðêBª2Ýe5JšªŒºt‚S ’Õ¿Ù ›PØð#õÖ4ù#ÄôFc¼9Ù:mš²Yª1fZ$§…ÀÆù7“mͳå[ ì`ÔÓÛ@a!Á»6ßWáZÙ$v¿Ùtì%"Óû ¹Š$¸„ {c1š™:tÿW<´“‰<’Q/ÚLzlíÒJÀírNëO K(Üœè¢7e’̉ױ]çÒnYÈÿâ{O#Áê ¿³‰ ˜%Oø}ÆŸ¹=ZäñK¬ä{{ñ×n/Œèâ©‹ +\ óàrÁÏŠõžA€çöÿ¼î©ª¨& T¦)1¼õc«Ò]0%¶‹Â樦…©Èb€¸”CS’knbrã`Iް™>3 õôĆ€•‹ RCJÐ cþ¦!ithRi°N~Œq ./7YxÊz*C,…ÖÝ5âMµà"0zzBÌËèôÀ»®›g‘Nl1lì™2Ô45 †”bs9ú²F Éb”9˜ÖÚ~“¤–?>!tÝrÜu'´”›ÉƉÊ0Ó±bãf²¤Y)ØZ µKi½5™Á¿uzý­á¯é…? Èç¿s¼²IŽp½úFQ¦B‚N ÜøXû7 PDš×GþXɇ’§w#ß~¤ŽK™Ç§›‘‚Ë F %‹’‰p¼ zôî3 c³&O9Íà‚òt,IGaT넯cpÄÀ=ÚÛÙ¡wº‚Gù“!hÉÚ[ÿM¥Â(@âê¡»›fì ƒ&Aäô Ñb;Ÿª»æ}…‚‡s‘jOöFyq.»»Žé× kÒ;rÈ´ØQ(òmÁ`ÆÌ²2x?ó÷óÝÎèœrq0Ctw&SWsžÛ÷º+žj»5êìØéÝV:ïØïÆy1~º‚ìZßqºÌyÁ£ ØÛF»ñx#¢U/Ü€Yt=ï±(zx3{,ŠRü8u˜¾8üši­²¦’jŠ˜ ×Ò„É­ˆNMÀ#ÚÁ{{˜¨«ÄЦÖÈcô  ÈŸ`>ãþ¦Á3¥ ÚŒ+•ƒ0™02„)džsâ“ð]ŽÞ5‹8OKìLšCÀÇŸ/Ž™ØÁ®E¬z*ÌÞ®}ŸX:Ä=ÜîèÏ¢OrQÏ ˜<\p«¡rH¿_J£‹µPŹ|ÄE‰iío7SÓ)½-8ĆŒ“UÕn6‡<àší¤žfŒƒµP‡F‘[¢ ‘7DÄ{Úèø\ßzt:œ[jj4¸¶:¶1o?N±¬sBø©“CÜpæþî~T:ø•õzŸ‘û½„3G% ”%¨tÖ;5`Ñ€‹þ£U kåüF9ð7QRRu—Àú`"‚¡ I“ìCàBzŸ§–¬×= P‚h¤¡#ÑÛ*Eÿ@¿¬ ÿÿóP¿ÝSbQćø¡§‚pì¡„ÝïÇEM-BMI'Ü#ATã:+øÂ@UÅ0ÂÁ4IE2P*@P€@AÊ”Á&¾[ÜxüïØß"3ùö5 ƒüâ¥ÖÔ*È÷Ê‹™ª¢Sw©gˆQ%ªë%‡Ë‹ŽˆuTC'){ûŒ©±áŒZ†YV¨”š¬Š¤QÛoIœ¯j±¾EÎamÎWƒ+ç·3ÅЖD/Œ}ÇùsM›€¿]YTz<œ¡"DUê]Û´ÑR¬ö^ð¾E÷¹¦·bµ™f ¿g m{‹¯QäÁïêÙªQÛåóú[ï,Øl.’ â!Ê~^N&OÂÇÇ5Ñì!ïf:¼óŸ§¿~}ÏÜÍc"³]®hmE ‚£fœl)*ÄM4 ÄdV*úðh8àq›om©kÛå®›TùXdV)3³xGö[“ÿSÎ^ã‰Q;GD–;@㈮ü0 å•oHú;äÀÉ2Êä}‹IŽâÁŠF¬~4”ÃåÏXs-Ò¿ãöêÎ?_¯˜%ú‘Ÿô¿×Œ6gû“U=²y1¼Ò*gü2šïãáÎc˜]˜7ÍSbNöÃMaÁ¥LñŠÕÍpJ‚¿ÅÖÖjË—2ÚÔoe0"Ví3lòaÏ8¿Ñ€b1óµù +HúqGX|¡±ÆôBÅÙ9Ù›âÉH Ñò¸%™Ó²m¡7š²AAšoe€Æ.Ë€ï,v{žuêâHèº~¸ò®±§)l(>p¢`„NB€ú•9È¿Œ·KÙàÜtkZÿÍxÔ¼°à¯õ«¦i(©=ÑNË€K%7¶Ñ±kæ…䤌ƒA"kØ^#]x+p­EãÍ{šv6ÐÕdé§J‹’Üî7,¹¡ ^÷²„Í’ˆ‚ ›Á•xÅë34Jwvuü•(©ËdžOOA¡8:ÖjÕ¦8&B»ÈÒN"4Y0ÓÈC• IV˜ÔöiâiM½©ÑÒ†-Ú®JÛ•S§i4 0;6,rc˜Ê()„öBN’Ââ]’·¨‚Ú.!µ /[‚ÝN$iNÒÏSº»ŒÙö —"1!H«êÉùõRÉ&×™K˜ö5q!‚܈-‰Š®8á­ò9Ö+‰É˜‡¢*]˜#'ij ¸C±y°…h«†”¢`Ê¡å<—áêÔÅà 6Ñš@èMðÆ,q¤²÷MI‹]õÛƒ‹ß2ùÔ:Ä6 ªŒ—°à”;P¡pÁÞ© íÎÌΣ@Ò)µ8˜\ÚCðVŒ»ÊKVª]¹ÝË…ÄQÖî f¦‚+/?9úìßs;ƒlHRÐH}D¸2\ïìðíç¸pªvÁÃ>CÎÄcb¦n“ÓöU 0kõ@w:eš»¢bD Eô8ˆé Að‹¸"SÑöHû w°ÞÇï€ö„ƒh…Šɧ¿|%]'GPõ°Âf>Σróÿ-Æ7© ¢ò»î¢3¨s”@ägRU;! ¡ÚЏÒÌÜ‘·»d‚•Mƺó5Ð|:tttð`geÎß«¡ À<©(¦Bã c6Jb=Ÿ'ödÁù‘ôœõÅNwåÃGw©D'5f^ÍM'-½ÌÀ(8nµs2µ–)h„5,,ɼó2ÅfŸ¾‰hhÉ©³?P…Š4))&^»³©ÇÙùÂ?Âg<¢|v¬Q)jhhù„_ÃðývdÀíÊlè¶Ö9C[>è—d •>[ å(Ùü#mÇUUÙHŸz=NÐPCƶJ A@ùdÞBÑ´½™°*áAôÙ< ™ÕÁôúüöLP êd–­Ç¤¸À‘J·{±é¼WGOAÑL©Áù‡‚ûº®‹æ„; ºYcÅŠÖ`ìê¯ß–g·V°Å—Ò%2߬¬Xa2I„r àì: „J\Z ^Äs[¤¿:™ÃpÐÝ=(éF.Îl¬} h`k¾%Wœ}î%?¾'²vi $ª9!ïo}Ê]hÈu®çBçYÙƒW]½U©¶õC,”ÂP™ö•«2©¿£ln_3n„‹ÖÁޤèƒè<´ñ~di&“ÕÎ@¹r¨:1d¡êNX?-̉}Øû¼ƒ§¶oA òÍ-ä! 8h:›ª¨;賟ÇÈúâúÁÅ?@Œ2ª©ù)‘,tYX?a«31‡zt„ô¶Æ“o1Ñã‘·£…„t³´wx0 ¢˜vHšf§áå Á¼¯œ£3‘[MŽ1›Nž£2Î!¼JI,ïöì£-( ý{Œ¹Ž{£Ïk›¾)øA¾ûÇŧåÛ=p ×?=…Í!ÿl²C‡Ó6G#‘^3ÍäÂt:lÇßøÐÝ­$ÈÓ¹ðŽèŸyöò sQê^sظɢ÷ὓ:á?_g<· ´»®@ È} ð w,½ýN*P{<Ö6|â2ç6DÈåDy&ŽD`ª­ªr$íÃþÔÅ{¾1¾\ïªÙÂÛõ x%²‰0bø,æ"n›Ñ?mh}X†›Ñ:€óÝÀ‡°ØnL’vXÁímÖ¶Üì)¨ˆVКáçnÖ釯<™tò#ÝØó¢mC$˜d´­!f}²eS»0ÚÖ¯W¾ö‡ÒlöAµÑE žŸå\Õ½‰ ærÍ3ygæú/–Û46¶ò÷HbN`tŸGyR)à‘)0uˆNßM%•áAgÏ^B)2™lŒŸ¨¸LôØã«ß8Û硺áÔs­   —c ød5ÁÂô½®¸Å(„.´MVãC‘b¥iÙÑ-ۜЦù*^¶ÄAa.‘‰ K—Ž’¼$moHÜyÊã … 3®#ï0a˜EuHu‡Pw‚]áàÍÛäÕ>øOÈ*¢“ã“ U˜Ht;ùكܙ¢‰$zÿ@rä7~‰B˜ÿOч¼Aú|ì¨i3ãzs&# È._1Љþ¤>ñIBXiI)–~d¾|$•+Ã%;aUØttŠvCý] ” ¿yÿ9W¸>'×Ìê‚”‰ˆ!®”ˆ{¢H J‚!¼Žp:积¬$`á×ÁŠ! ’@ÆÂÀPÁ1ˆV a0€$Òõí*¼Úpó]®:×ëOŒ™MuUcõ‹óèBLú}­›^Ëk¥|¬¡ß_/ˆ“˜%N¶tFùÙZyÑdÈYôçC‘^^;áÛôû«ö|„Ll $¯ÀINQÚŠRXAÆI¡φq M÷ÖT´„kACÖ$w·Ìüd JÄ/²ìå9ºqBžÔéƒ9‘R@ÇÁ2Õóù?ß\oÄãëk PúVDê˲@¹“ãã,™‡LÆYt $dòXëRìF¦_¥Ne$µ×ÅQØõòyÄ»87†"D)oãÂ<+1ŸŸLTaä£-92£ˆ]5žs!ðŽ&‡Æ ü=ýø€x@ô! QòðŸ''´§\ÏJëž0ÜN¤¦†%u]’BY¦Ø­öª½ãù^¯ÛMèdù} Ë#âŠÇDw b2ëË;–ïLÄ‘ ‡qîT|;ïåù¹7Œ ùGó-?Þn‹Ã?§f>4E»ZfRo8ÐR©V(¤»bùü!u%”s I™’•lvB |þPÓ_-$úoEÙk§A‚ Ù ƒf>Xk[ *R†]÷0ìOð òÖ[VNYwš!ÐJOl|Ñs—茴ÃOÑâ]ݦ]oéñj2œúzDZrË|>Sÿ$g°úÐz†¤ì8W‰ Š¯æ¸¾Ú¶Á¾35„c|Ö÷ט†ýo1cô-'l1¬¡&ÉØ-êìã™àù *xøxk–=xÉù¢ûwÙW>[Bðx,ßp¡Ú9ÁvÜg>y1í¢ÎÇ Øëgƒž½?g;6óJµ,é»}ï¾×¾ûpûžvî–ú ïs{ï½»—v|ÀÃÖÑåµ«ÛæÇEžÊpE@”w¾÷[m^÷œ÷f'f¥o½Þ—Zw³ )Jø 3½ëíÓ«%Œvû½ÔÔÛWmŽ®¡ï^ã}ë½í¹ïg¤u¾û8½í³=VÍ7Z-ÞáÞÀ œ‚M¾|ÞäËèû±TRo{ïËè}FïT°hâŒ36«ŠD‘õÝ+ ÛÛë-:mÜu½»”£ìm°M*†šÝë×bÞÚê¥"ØtwÛ¼ªXÄtQN 4ZÝhé¶}ÒC›hÅE¶;¶í"­Om†ÛAtîÀ̓)ŸmPÙînƒlÞîKO»»=0zÕÖ¾s½…aS0(ªP EUZjÝŽèf´6Ä¥ë‡[ݺ÷Ÿ\7bªæíîÚáÞgvôîλì÷—½Ì}¼}}e=b)vTûßpâÕìç¼èc‘íæcéásàõ®>Ýmôö.ç€ yÅR^YîúéÛp_;¾ïšP«F[·uŸ;e•ÛhÎ`·{jöÑëí|÷ž{T" õÚ>œ‰û‡Êu¢õ{h§»­ßl¥ÝkcÜצ¨y@èÖíûç/ŽéîûRªŽC©–{ï\ûÞö÷ UJ€ëß_sàú£­QÍJ÷¼môú’tÛJ+{×G‡<ßM÷Ç»½÷nc¡@;`¢èÅê¾}ãÛ;µWº³å}<}áÔîÙêÞ}½àhõ”(ú úòÄ>½öû®ãtôU»»½ç}ï¸÷ÜuKu>½q÷¨7|õ[æ­{Mo7}<û»½Îܧ¦öß7y²×½¡Ï]Ͼä|w“]g[ç›ÔNùï¼½ne¾÷ók[°ïxܾÀ>Þ¬wf½½Ïw<àt ¼P8¨£_s_`õ_sº¡UÖ³Ývdz'K•!ëÄvÀ_|î½ÛEǸYÞ7}±óÚë|Çwß ë³¼û[»»}Üê¹j#v»®ú3žÝÎn­–Û½y÷ýØ÷·˜o½®/›¾ûŸ4Ïpë»õÈow»ºô=Z¾ï]—ÞFûwßgíïšÛèõâ{æ÷³­(÷ÝÇÓ·»¡Ì¡c1AO¦ƒj­o±¨Úç"œwq¶Òû»·ÓQõêú†úúö÷®ºø½W¾åwï{ݾúÊKE°ÝÞúz¢ªõ¥ÑMv}±*Ûa;»¸æ—µk•©›»…ÝA»b3É]ëßv½îÏtnïV(ônNÛšóWC@·¯i±Ç{ÜO[Ý• »€l¡Á:U[§PUR”]}¬û{¼w¾õ¾øëAímBéÛgMÝÏ}×¾´ƒÝ,Ç©»íZzÖÉf½Ç*†½ë·nÞz¦ØíZ uuCŸ}Ûì¢5›ÇÕP½÷Û .îû=ï^»¯<ßs»z­uNªšË»Ê§mQ]ïo°Ü½Úóçªèõ÷·Ì»ºÄŒ=Ìt(4=¸úúôך­hû4×ÎuíØ9]׹l¼ÙØ iIØržö]7}»e¯+o‡uŸ^º¯k®ÎÕCvD´û²);nÛKÝ÷¸ÝΔ$`Ã{¶Rµ“@ÀÖ+ d}ãty÷eÝ/¯²ï¾íëΊ(^ÝvÍ÷¼ëÆÚu;®ë„D픾ûzÙ&¨ï†íÊÍÕ]ÞöÒ¤è›téÛ6¶#)IºÝ:ª¥RE; ‹^ûÇOz¾Þ¶(§®Ø:¥èk@[WC-º:Z>ìûï§]óï=7ØÈÖµš6ŠQ© +m”jëÜé¬Jªï»ºMy¯^í÷²×]tÉ»ƒ«¶R“µÇÞó¯T݆œ‚šéÛ·½cHïe­¥$¹š'UŶ¶d:¢…UÌt”>î.1w¤ £Ò‹µ6È„F˜JkU¬¡È 7º·;î½¾ëhcÐë¦+m·{Þ—´-iê¢]„·wjîø»{˜•(Ë[mi_MDû»ï·ÞûÖ·ÒÊÔß5wrçJ €4 ¶ZÓï’vÔ´¯Riµe8KÛuçñd½m0ÊÞsN³‹¢W7»ŠÞµdòo»¾}õÔÍwVk4Ú5Sjlúû|¾ûÚï¶úîûš£¦}ËßUïƒëfsÛj6Kß„7¾Þž¹æv nÙ»ë>^ûÑìf€>>$A 4Ð4d #šjy&C©¤ÄöTÉ„¦!@F# ié <”Þ©ê3(6¦È@õ4zŒ‚H ‚h™2h & ê›J~FFš f§©²ž¦§¨ÓÉ=FŒŒ@Ði¦ D"LMhÓM#i£TzSñ©éJoTýSÐÚ§½Si4ž¦õ#ÔôÔ ))  †š2„ò§äЛJzdÕÊz êSõ=LQµ”ô iê4~©ê¨’ AF¦F"fS50§µOFTÙ¤Ä5=M=A£C Ѧ€ûæüJ¢§øa?\ ìüæ(}éR(*J šNtˆŽJ¨°M¬ ª$‡ðš‚˜q@ÚÈM–A?ŠÈ’T qb"–……# •¶€_ÊÄ ÿ/ÿOþmö;Útõ‡þ÷—þ÷?úåêÈ‹ùÖéH%ö1ÿXh3þÙăgåGÏÿÌ5·ãøîÅ–“ÃÂuÿö9Þnù×gÇì·Ñ'²Ö¿÷¹¾µ¾û—ÌðÖáÿJaü*¯Î3ý¶½·ÇSÊ™õÆ ~.¿ („°·ÿ”&M~ænüG§ÇŸKÿüïž'À‡?®W[õø^;ãß$~H9ÛO‡jðó¿tGr{9»ѯúóVrûÈæºÊ~Èu‘>¼è>Mqf«O±úhª46í÷bùÏ)Û c©UsÓº»wSœ5ÕÛ–ØÛé¿.V5Ö46æCF÷¼`ædRïïÚÓ¯Nbºx^øŠìð¡AÇoy¥Ÿ‚ý²í®þ–绘v?èg6WÊ{âùZ_‘£†‘ïæ ÿæù¿°é”Ë4í.)ú‚ûÙ!~–Iumª›õp$r‰åŒ׳Ÿ•×ÛãÏ-,ç-÷i•-Åè†ú”.òèÙDú!³»" MT¬fŒ»žS¦ƒMvÿÔ«••š‹hÓí§[=4Y­é^£ÿÐSwöèþDS`Ç'œËd_ƒØ+þÚ&þïÚØâsí’äBü½h ž“7¨Z¹ÿÐÿtG6>Œi™Ô^ajLéö‹©PÕçüÕhÔ°âù½+ùÐkÑÌòæHðíÕÖ?†â—Í *LÎ÷ÿ¿ç¾“c¤þÜx¾¯þó?þÓŒšÂµL’~Ö~عt‹9æ"¿–ÌuŒrÛ_ f¿–šoþ§q0fí‡ø˜ƒà‚Ö:,t¨cC/E’nè ú굡65fìÔÙGt#F· òuõÃttÈXœXb…ÿÖ/Lޝ»‘´…ÄnC!A²ÿ½gÿI$[ÌQ žZd˜h¥­‚ ¡•ÌŠXd4Ÿ¿ê?ý¸¿‡·ûøÝ×*ýøç‘11DD_¿XÁÄù<4½]5G…®TIºº>¨œ:/Á¢°’t‡ŽëÉ·Û•›ï”Gô³oÚõ~¾Ð]š\±­ñîþ Q)ŽÌ̽íœW¶QÐJ¨šðôUbTãè# JÖ»¨å³ÿC†ÿVÕÆO®sžm¿~ÙÜ_ˆ?ŒÒ)÷"Lú…î Æ€É£÷[ê¢ÞiŠU•TÈÞC¤$~; ÍgämP<—.@¿Ééí0ÎÛw 1™.ÕŒç§ßç8dßc·h]/^g¥)˜_”\·Úê«ßÇfyG0ªÇ2¹õ¦¶YFÊ'óhy8ùwê>ÉÕzp蔟‡ü¾ûÉpïewG(I½q˜ m4@çÏþ;K©Û±Ãk 6–ƒvIPóžšFŽfç² ªš¡-Œœ…}Ÿc:®w ÃÅBÛ¼'áö1)êœL~ê`~–×÷/Áé§CC*AÞ:k‹e®æe^vTDß®¼ñÅØzš£M]ämk{0}ÒÍÒa(L|ÐÙ¶G8ñŒ ƒù?UP K@P´ SB”´ÓE%44QIHP”4 ]:ð) (JR•i¦¤0¢))) Z @ª(J JDûÕïöýPú>_ìÏôÓ/•RrlÄÚuA¤ÿëòÿÍÿá*>ߦÓíjÚÈ=Úš…ÿwkßû®yZ\øïѸÿºŸ¿?,õÆèñQ NóÁ)šOÙïÈ8¹¯/'íÇQ}u\æ"xñã²Ò¨í|w™ë£7Q1¸%Ò|¼YÏuïУ6äFÚÊî§Ì¿5…„,ÄÕ>ðO],¯NÏÿª,ïþÎñ™l¨—޼y÷µœ™œxŒÄç9=k|߯ž÷]wªž38~îé;ÌW1+°­,«ÑéÚp¸Ì.Åâ‚"¢™’ V¢B ‚iR!Y‚!(¡¥JA‚ô@q‡ø–¨½áßç~—Ã߆`²J݇âQ kÄFŸ{¿Ï?I)fœXND’Ém:`¤žnÍZ¨þ~›Ýzû²w-Y2²¤ì9ºéovZY]·ÝÝü/Œ·xüFZI±­ðíÕ/‰NJÝ ¥œFµ;‡W\>ˆ¥¦˜ÜÆÒÔKÛbtƒk8ÚÁ–_´³.õMS2“¹æÌƒýÀ1AÏÎmüB;gèß›öçáÓ=¢/!°‹¡ˆîH„ìð›Ä^^Z"èF¢(ê"M ®ñ‘N©£ÄcÌó“µòz>ª àCtçk&Ĥul¥´ØOrìºÏVÉ»i‡ÌµVÞœk«qÍØGˆ1¡;Äh#Îv¾Fyt×ËÇŽp×s¾`ÓO†va)!–†#†ÆûÆ÷¼X˜…x~$–«gÛp¯¸ a¬Eê›ËWY ®@EVi,²åeU,@E2ZgLóªÚ€ŒD1üÍ$h™ ß¼°‚¿^ ÐÎ=ÃöŸ‘9‰ÔžÂuá€+ÑSeˆ•(¦GÔw)|B±“5y»Í°|>LÑ5çÛ娸­· ß6*É$P„áGT7!‰j‰Íâç8² [°‡'È"¦™†!áÆè£ÊO°¼õót­4ޝ²:©]ŽÑD­•»Öb÷ãM ýÿ%ÔâqN ;A9AŠ\Ã# a–‡°ÂÁZH2OÆú¿i`¶ïœõ¬ycX·ˆÊõcâ##&oŠffaöž]ñ_v±öÆÀÁóÊEC ꪛZ° ¶kâfÝ@Òd†ì*£2J…ÑŒ^Aމ¥;˜ˆ/<¼Ån+QTjr6¢| èÿ•QEUDQEøÏÒÿþøû»};¿å¸Ü úÜDÙ¦?ósF™uG¾ƒN3SÒÄbº•#ŒÎ¨Db¢ÛH•÷ß"'ÏçÑôÕÿ efÂ!/@€5·ÖW­äÆ4Ùèá\+ìlÓò·lótti»esc‡G’Az^]zw¹÷°ÅUR"""7ÆžYó>?ša!ßhaC31ʲe0ø?@㘌r8ŸIX‹ñ V¢ãYåݹîÛ–&b ]îýÝÞë¾ ’‡ô@g\;m+.Îßô—?>rãÉôŸ†Gñ,e‹(¡2²Á7×_yÔþƽguyù†÷º­ä´2fe.ù>ƒ‰êND„©ñ¸FŸÃKQµ‡…‡þ®¯Ê®o|ݳ¹© þ`ý^l? œvfjg@Û “1DÀÉJ0ÌÀdþÝù©³Ù8;q@òfÊÄÁ©ÉÑÓk3WÉÓµy¦TЇXÖÀÁû ‡¶é/9ëR0Î@AkpÀb­¹Ø^~Gó6véV-Uþ^&Ì´ÇŒàÞA0­,:KÖ¥KdQ—É[Û‹²OzûžTÐæTQœ½Ò.!&ÿ(­ 6WDÎ#‹Â ݬ° =e¹9«®ês‚Ÿœ{ P hHv30µ i;TKGwþ úýÙ$qFö-"r(™3XC†RÐ4‹HÕ/®b¨º`n#¶_o‹T¤ÜÌV×·¹„o¢ÛòÛ/¤$ÂÞÎÉéu¥•ÜØÁç•© ¦„ýÐv=”ТOÒÎ Ø'NAMg¸¢uS^~™ìöÆï§VŽ3=;} µ¿n1coo8ïÉBôØ­q"m¿¦œÎx‚ÄŽ´æ!!©‡óxGŠû`öøˆCÅþFí7qÓïORpŠÖ?ïœ'üäØcצ¶…¤o$à#🕡Óíøs5ÅvQR0ˆ t/‚þññ’~t/ÔKTˆw'.B-Ðìz ÃâÌQ˜K# 0¦xm9•GÍ¡ÏÉËâáÞ®þÖá÷Uììýºú³óY»<Ú£6h·ï”D7?ÓŸm2›³øØ]Ü_öéí¾W"Ç·N´oÎ$r“U ~­žÕ‚ ÿ¾}Ò!Dœ¸¾œóÚzg¢Õè¾J•¥Š˜·²±ƒì¼OÐ3ñ3ãY‘%i ÄÛ©Töœ!µÄân>¦‰Ú|ªuïNÎc{s"dê W©hÅ4"¾ùÇ?ŸoÏgæp~\׃$•T!ã» Ò ÇÙŽEÍ÷ÈÍ«Uc2NU;ð}<Ö.{™=)ó—ó‘éé?§]gÌù,6…§ˆ2ô¢{V%í—Œæç›J!k‘j2«iæ™:þÊÞèã {y¶&ž€j§[Ë>üæ†l0Μ8•à#Å”‡N$Ýðô¡é›¹¢ä¯Tê”>ø4°Úéf1uÀò)C£ž<±>J߃±DL7…†ìSÅâ9-â]ëÑȖ潈| #ƒ·ÿÁÇ+Ζ½9¸Ú{ÖK*<³Lüú-Þu¡ž;øxÖ*2\3ú}± S~S×oÓ¿{M}Nëú~m*þ;…ó¨}-1åqjKaj~ÕU…QV ª¢ªªªªªªª©½Iª†•UUXç_mŽ—ÙM«à—”Å(~-D}dõˆÁ´R0àÍ©ÇÖË=ÚuµQ×ÈÕ)ΘÀãM¼7|gîïxòy:¤ð±ÓJŒ,’R”Ï.óÒ1ý»².»Ü4„†2åJ ψ±¼‹æàt±¡†¸½ì´¾Ü²êž72â¤Ã% LÈaÁ §qåR›²$½h„gÉÞ2~=ÿ¤˜çÕsÉåÍÚ¥ñÝrwíÆµ‚ޤÜp½gÓ2e—j|Ÿ´Óc‡îuÅ-¸Ö¾?öÿ+`5÷ÅAÇÍ”-eWþŽFQ¦èÞÊgç#ó$ߟß©)­zH(%qœY§¢ŠîB'±Í¢DàBDÍEÂ/gK“2›Ñi.tƒXM½ñtî:â3³uã0N‡Ìì¿æo¢ÇBÑ££Ðÿ³–ÃÎíwº[üìÁ¾NÒF©RÌ•DÓþD½1÷î•7)&³`Ž/d‹uàý3éú;ºgN2wC„=~ºfµl'éϳ1±ŒiŒLm³ïÂ#fôxQ\}*!¨`WO›ò¯M×÷£Åˆ Ù0˜¼&ÄþkÚÒÀxv<‘ZLì•iÏPoÒàô`(¥‘?w»ÍÓw4áVÆÏUùmáE2Œ7ARÏN ÿ4?§¾_TݶDZŽuÈßÂ@©¸–ôÿÝÛ|”GaŽPÈÐïiY¾â¤É¨{sçß…†;Ûþ–ì¥Ë'9öÿÒá_¯¨ì#á”´Õxú»O¨¾ÌÊC# 4œÊ‘樂š!mCžÞ¾ØTÆ÷rÁ²aÝý8¨?«‡+#º= ¯—Ýžk$ á9“Q!Ñ›2\õÁ›Ì<½˜óà¼.rt’’“åu¶ú1BŸë ïè5÷Ù#çV¤f;˜Žéö'€É“á­®HªMaƒM4™s&‹s”MŸˆÐeS•²1ÿ6d~.˜Ì}¶lF.øïÌUó9v>‡yÀÄ|¬1-7Ñ~¹ ¦Cö»üYkäõóúé›é£†êÍ-âyÙ$u;ZΩ7xaf å§ö4álúÛ€û!¸t^j†ÒÉØuߦŒ[±TaôêuP:\ø ¡ȱ@˜·qÑÜáóDÁB3n|•|"&«ªÁŠÄEÔñ¦ ¦ú Y&kFÔšñò¾Ìhª€êGîa|óæ¬QI†ÓC@;wÉVÚäô5 GšFŽ’~¯1Ä…gI[X{ž¨=¶À|Ð{áÎC»ÇŒCz‹(b ãÖiRnÂtìƒ äXQ˜d7õÉ14ÁQDÅZ²’( ¯DXåA5Q &ÐØ 9 ›¡陦¼¼'L^Ô,¼_¯· ¢¥I9dh¢C4:ŒT50‹WɶSN*/ÛD­Ý/I•Z`aEÔ¤^Â¥’Zgj ËþmõӞ邚#6;œzï¿ Ÿ}Ooi¯‹@îÆ¨=j¥n¹Ùu ¶ ŒÎ –¯´©Ô)`fµòh`ÛöÛÅ»ãUxw=ˆdË{h#]”ÛMÐ#y§Ÿ&OÑu§ÆßÑsû'£N('äIæÙá|xÁ¾v{/Q®[&¿ÖÆ[SQèón8Ý?vyDzq%×Ô=ÎÝb¯I2[)ÎóÒù©ëå?«yŒNñÇ›* LØ2fH“†1%Z˜xl")OS*°kMj‰`Ú†ƒ¿Ö¸±3} úužúâ:IVÚ@nÛ²°öîÄ 0¾—¦Îê#|a†5µ¯œùÇG[ T\+d¹0t1Ò5l¼Œ¹‰º³Î®ÇF0‰†“3"»\á£sÄÅos£Prèç¯kk6¶–…8TøédOªzYP4íê°—|ð”ãÕQïh5.ø;ñré9¿•ù'!(³b™Ë<ºÝ4»ó]¶W¾Ç~6{§ª t+§ò”í ±Ë¬¸…¶à5®ûÙÓ30ÑLøm~–=YÓ¿§~vØôÓ§( 0»¬Š0ýƒÊêu ä®1Ž+ÈjÑ¥,9ò¹hæVñ´r›ßá]9ßÛšŸ…ÖZdvžÜB÷õˆçPÛ¥ŠàÆŒ«(ë¶ŒÇQACåQv„ýÿßq÷sXÍ~¸N—àî…’õŒõ¯‚ž>Ód¤•|\!"ü>^¯]D$¢üz\õzog„ŽIÚé§ÌGÇå‹Ü£OYýH2Žíôà'øAµî6ײšòKØ@Þm>™vºwb>®x>»»vý$ýkFüOrh÷\Û‡äøüú ÉTÐ^q…²7S/…Ž‘dk›=2®ìÚä ”Ëÿ¤EE:ROÇk ›O&¼ÏkÒYûqÞÇŸ8jœ¸ÖñôcsóõÖáÖs97­Â»ñÚ R¤]yU‚nXÉýÐÌz *Âf†KY‡ß?,JaPíß´k_­âÄŽœ„…xÓß=“ÛËw))’²ï6è.’kÅ™ÐÂyv„ßE†¸{ˆ ¿çˆpsc%Ïëí%`ßÛC϶¨vÏoNÝñ>ήhóò±¥é„¶½¹]áÜžTOþ›=úoÑø»|?ÃÏ­OÃ3V{óõFU[YÖ­ñ÷Àçà±Dó|/Ë?’„„€ú·^Ñ(JÇ+ðÂÔáŽ&_E·ü÷¾¢ÿ&ˆÐÀ1äb¸µºïò4eŸ>‹HêyhþH% ßÕõñãí}“gÌÃ÷ÍçÎbJåB=Úù£(µÿKPœÙ®‰šqµâƒª(J,ì Âx¤§Pö€644¯ieåïÄù(á÷ãÙ~µl¶,´ûòG÷¹­*/ÁO•ÜÝn›fÑG†ÿ°6íê!! ÜIŒn,E é®~º1“îãS4æÇkå³ Î«»îEýÕt忬>ðÈs©.à»ÿ’sm&êÕž¼ÞëYlIÛÆÛ’bM-tQ]SÒÅRÌ~ŠÑº‡@òa«ìûMýå†_Í;ߢôãžuç“eôJÆÿÓ8s‘oFÝÙ>PÒÒÛt+ 5óÆVÈÿøiýM|­{k~µ;Y·±vÒ„ÁÐþy 5eÌrý\ÞnD#5Ÿš£mŒÑn UNײTSüùSt’Í-¦=Ö[_ç:1º¨mÆûÊíº†ÎÈ`QÑ HÙG¢—SCUôEL†£Û»çÒÓØÚ™´ñ¾º(« ¬ŽÈCÏ}”jÁéV}±²XYtЬ|«wÓ!,fãy´<;0Ø8¶~Lc/ÒëŽu„t1Áßð`Ÿ’È"†{©‚4ihëêùem'Ó.Þ¾“9šê;’Gêe1¤ÆOø’äèvEÌE’0»þôôuÏÿ©–sVúªá§÷äЮÞˆuõwlÛÕÃN5:Ƙݺ ÚÊsÞí+h„s†mßÔ†\oå§dcämß´~‰gGèðçša'Ayíb³T°ÃfÓOúco¦½-ö讋?Ý¿»ºÏÑ}­œíyß«ËÄ~úášöí|m¸ÞŒ©çÕɽ4U{ml-—³“ûŠgצ«Xñä{¿ûÓ:l{ØÓÚ×[9åÆª¹åÛL94·ÂêR£×I-^\ùµM¼”\JZoÂ3Z)…ÚºàôŒQDaì'ߟþ5_UUÖX܆œ²œíÿnÚqÑ›ŠmÖn´¢Q«K7)ùî'NešZÄä£Ùž7*%]ùjíÊmÓÝ‹]wøeNcUnQº› &—ñíq½Æ&úqn›+qÆñßË㿺§³ë/Ä·¯ŸÃ™×§Ó‰Ö¹&O·Ç'ïçãY¯%Öî0¦û™&^!ç~ìéùAEÌWc`!E“TQdTŸôIˆÃýÚ“HJ8 Î"$Ž‘ˆÁ€— X $Í$ÃRMhOé *K[Qýám@Á ¨DDS£Zu:s Q]*ˆ‚h§°¼•™þ“ GóÿÐæ™Å_ÂGùB޶Æ,A¥ "˜•{UQXaþg\;6iìÿ¡ÿ;¯õÏ|âjI?ºBm:”ÜÙ!´ªª @"<~ÝZuµS³Æ<¸e®âlêÙ—#I©±„å[Oæ:xIŽ(ta4ôÙ9=ŒnÆê`ö§¯÷Kø?'&ôœÞ㇕PªY,ñOM’ŸÄ•Pâ“?úù ¸GvÆÅ)Jj}<³¾Yawà¹ГÉT AÏ®üÆõŽC°! ÖÕ JĈzä"@6‚§@QL‚yÔD…%ÑH¡CJ‰ñ=è„¿LSßòàùl‡É\(•R\Âb•P¾8aBÍa3lŒY/:ÅU±JU"ÊK—´Ý©u2*œP@Ä]–s庥؉HB(2ìa¹7>o@‡NùÌí„®ua¼]JsDe4ä%X¬L«â NôÅŠ•ÚÜ“²ò?Ï3ñoý?×’HHDü5$CçbàP€00‚¢žþ$" ðÄ+£¸=„ÝE>šÏÌ~ï04«Ô>¡'ñðy› Š˜OS ´R†„+¹r%\žçë×µœ0h ™ 0•R Bð}ñÙ'X‰,„âÂ,P9+þ®ÿð6Ÿ_˜\„¨˜2$Èä=?‡g-¸Þ$’ªŒ‹=¿ŸôóÈÿÌw=®fIWTý2i}r/æ£é,9'þTÃù\È£<_ô·ît¸°sw~Îè¥gσfaqÆph¸ÞÕ @LDûÞ³Rÿ€€zÓ‹³\õ·á<“ðQâçEu†v{7GYÎVŠÌ8m™ uÐ(¬˜ÈS?)†hçüØ+ë3\h˜ÕCPÍ–¡=õW>Xä8!¶@`wMì„ÈRpmëí䘟êÓŽ‘©•*°‰âï6Û|Íö ÀÄí-L03Z‰4!šz:ųýÎ×õ }E¯C2–-²¸SQM Oö¾† iñÒR^E¢¬1q[–бQì†ìä ]ϳI å4þsæå`bÈ„v@Ã*+Ñôõ SiÃXŠìÁÅ?ò'£ƒ·Å´È$í2c¸;Ê Ùböc|(ª–u’6ócÃMV_³Ô¡ÎÛ_®¾fwŽLz‹Ð°Ûap¨ò®Ü3ã;ÉFøútÎ7güÈ=í°rìÚ¸­“ÞŠ7_³Žø¬t–·BÑüÐ$ ™ì ºò†a±¦”–Ã`èÅøtÌѦr BÿY·¯›ØýÝ”œæ$q1½ÎmœõK5æ¥9Âr]´Èái¶ªì¶ËKÓl¿Džh¶FpC{ºàyì–~—r—ƒ6Tyôü¼»éäþhýsæ„¥ÏøÓGôë«ôgÛï÷q6uÜ‹¶gé4.4Êá:÷ô5Û°ªª+ö?½5µèŒråíÔG¼Z?ú™EÞ,F(ÒqQ÷}Ú¬Øv½Vîs\Þ[›Á­ŽÒå c]”zžÂM3ÒØ #ƽšY%´>ñ9’£äË>žA4%ÄãÉm:<“©…À‚`rãì¢ýì—ÍÀ¡$£06å³-ñÃÍnmŸkžCÊ@ÛÓ“ŽÄëA÷ç=|$u~Ï?Ÿë´º/—“°v£ÇåøãàÛŒûtãûa>ûö4:0ćO§ý´¥çn–HBõœ¸•°ï-cëc~¯.ÓÌÔv¥(K Õå0½ƒºòÓ¨ÆÀöû΂`€q€H†¼‡\Ç_—Ýö5s_&îdš¶­éôÅ*~~ºRjqLÜÀ0â|LÏúÝGËåï‹ÝåÇ‹W,Ã?œ“Ö b*Ò©ïg¢Ãé¿Ccå8››¤pH —µ…ƒÜ2W\íçõ>øhú=ð ̅Ńè;`;ö§Uǃh>$)y>ïÉ"–C2NÁëœÞÝ5LVˆ ŒÐh5hÈgõ"w@Ìy(]ÓÎýïh@±1ýøÞ{ÿcYA;Ùˆì¦x¥ c0Ñÿòª¼§¯ãåðú»š¥ H=ÄŠRyi‹Z0Á³ Jˆb É"V" •¡hÌŲÌ0P ÌJ±‹0K,fU²Å0‚.ü5£K0Â"ªpqœ• È"*•‰0€¤LÁÒ„}§ë£Ð^H<ІE,%Rô0>}LËIõ­Sæq ÉÝ·—;Qo~œ$¿ks Zïc‰Òfýñ-ùWð:ÃA"`÷Ð@¼,2ÞñAhUµ” ¶BÀ&ÉuEúJÀó Ë&ktæ˜9 N=­®pº#Öèy$~ éWÉI’R‚B$jL%ÌPŒ%”¤¡À€ŒÂa&¢Ã ’‚¢`¢e! ‰ª1f‚ÀÈ–“š(L’J€0ŒŒ€¡‹ 2 °Ú8°è“! $1R!G 2h#2"U(PÀ…‰€iZR *ªÆQ s !„—$0ƒ À ÈpÌX*Qp„†sE‹¦gy9~¹‰2R™øe¸UÝ6S 1À¤F¢Â$†R=(hÔÐÓMGH’D¯ ܯØ:ü·ö¾Ûs¶Øhpµ/ºœE˜hláÊhбŠHV2b$É3J"jh1¡K‡râ3Àlp~#碇Æê¢k)ÓÚY]hÅ‚‰q ÔHFÊ’Wø@µŒ*†šÎ‚àèrN£@dÌNâD˜ùaðk¾a1¦žLù•ôd 5ãGo‰g}xðBÔwpœÞoL´¦»'!©=£ Æ 0›ÈëLŸ³f·âVP t·Ûiœ6Ð]Z7v•( ÏP¥_JxðÜÃTš ½’ ¡Â†»”G#ú]“ Ö÷Á¨Üî‚æ‰p°`¶ýà |aå‰×Øè¸Y›œª®{Tг‘MYKS—I´çÌZæ±¼“³Œ¼É„¡1쥡ϹÎò4øg8‘·?êro¸W¸‰q»äç¨älÉçQ¥ž~Da‹ClCT_÷F½ÿqojGÀüO‚0²Ö/­™lqÓ ²S†¨Щ‘(‰îtD¾"ívøwiÎ9÷™rCrHÞÏôÊ3çã®}DÖ#'~™-®ÝŽï„ÇGܘ&ë&ËÓ¨¾¹xFÆG ›¾ïrÝ€åõÊ!Ž“Ë†×W^º (F ºIj íÊ¢‹BÛ*j&n Krî5¾›¶’óH4<§¶bÍŸ›ÔÓò,ßÁPçŸz›Ð Íé§ÆpDhþó´ý 0‹Éx±ƒqR´Õ±ZЉˆ>$÷Ú¿7ÑþìêÂE‹ÌSâ¹ÕwÔ… Á0!ö(¦ ˆ …£]s ¤Êy(é4'7ÕÝz Q¿ôï?×íûfk87¬º«ÒêÔÇcïýcŸäVœc2žq™Ô •ò ¾ƒž²dûÿ¹G˜V}=,e¥B]vÝE]µ&a¢ãTÀÈgãg)µiï¼5ŸeŸ/íç̳ŒÅ)ÀŒK8›‘¶#”þ³<Å–—¯“|7¶<ÿ¬Ú<?—Þ[ÍÔ™\Þ§|2ß ßñúïϘ­À†“­÷†-9çÔ~æ<ð¦äPuÝmZ9B±†Øl¬í‘30µ¬¸Ça-QxÕû‡Ãû‹«rˆ§s›.ЊEFè…Ÿ†—üjz\]j·€r0½—ê9u3°ì:Äû!a§¶åõ~zHž ÎD]ÝD÷ÿîûôáÖ}Ÿ.’Ïçæå^«zÈ›jþD;ÅõwW_¡Ï=ËàéÒ˜3´|Tˆ¢‚ŸA͉éúú,‰˜={‚r×Dz•ZÎeµu…ÝÉJsÇy$½XÃî`r1¥ŠöŽuuðšú¼9I/)A¿Ú•Œk¿Á‘¨òÓÅ™˜fcŠ–û~‹…‰{°‹Ö-´ ”7!‚ïTé\ùNŸ³3i4•n?içtǘðª0à°ÞamºÎ]R3[„`IMK¥”€a†LOßî¯Ýo² ï÷J~þV †³ºlÝ)¨0í-15Y>©å-Ö¨*ƒRsLl§ëçòJš;’Þ–÷v8°öàjêÀbÎxâSR繟0hâxf8@ï£MÞ˜LÞÓS<. 4!@9óü@jeå'ÑGçÖó8îß»oL¯ÅÅòhAÓYdj:Ÿãèùìú+S LGöcaÍ^¿4òÀtÔP-,¨­ºÞƒ•ŽÌÍ®óOÆ%Q\Î>I2¯c…ø¸Ý¦/ifØi»q=·e·ï^„?Bu­wàÿ9åŒ$…‰Û¿Ÿú뙫4J&£UêUÅ;[[ÉѪº ½L»dfQÀxËüP ¿!°ªa‚ŠÓKTNÌ# «„æÅ_%q ÚÝ/ØT]b86Mõ㯷ŸyO**g}vÉAÜ‘ ‡ú}ºnÃfZ¯ºãbÉd ¢}S˜E‰A—'®; t>ëj{5Ú_ŽÙ³´l)µUˆ‹3©g _Ta¾@„…[ç81ù˜î^»9仸Ä’§;ŽÞHÑ¡3!Ù³‡â£iQöÇëç ©ÙºÛ)e¯|”©â, Ð‚ ÑDóµê£¹×qOµN,yOÕÅqþ§Ÿ:|÷k6ókÊ>¸@:§Y=Óo"ÄÍ“<´k–š?L2#­”K¤2I…°Züƒ”4ñníYÈÔ\ H.¹®JÁ†_ý›G]KŒYikÑÙ¿ôÙëwäõm~^ä´ 7ÍSôºzM Ãêå<4pÐRÚêÁ’ÒÔdt@«ÒÔKDçÕPUgý‚„ ׈ÀÃ9ïÔÛtVÊ<ðQŽè†]—ùB‡™µ ç6–¶§ˆÓFý#¦2Ȫ~Ëøî0öàw‡Pû|W¦bþœYÛ]ŸVý±¤Ûí„í;ìVU Ï“èÉÌ Õ*µÝºº¶Vgé²ÅdGþ Ì´´™K £—Áš©†Òý.v.KN iß<÷þ–à{á#íN/(5é;ûß „²#0à“R&œ AÊ3.;¼âçXvÊi[ôw×û<û­7—óv††*\ xêëF‹³ž€’M—£z’RŒ®"”bL»TuÕaÏ õ¸®Ýgÿ ¶­Ö¥qlê/å¬×;†)s0-ÇD­ó–¥¤¡@³BõT„EhÍ*°EŒÌ4w{§3,ò¬*1kÂ`\˜;w•³EÕê’æðtñ7÷½,ÒRŒcµÝŒ]ÎGöåÊŠ­Ô™¹+8KK"Á`v‹ºêÇߡ؞ü¸Þy¿•Ÿ?‰ñJ—†ñ}ó‰b;Lï˜BH€…Øü¼y¯C¤“22q8žªáÌcÒÉN× V†CÌk{ê,bš:uè×ð¥]¢[)¨ÖذRÚlÇÐ ¹¹=^šûšZéôìx5Ã<Ô?B•'î†aG'9B$7Ñ3ø{Úè~!Û—×l[Na{à÷c¡—¿ãnœ¼4yåñnÄݺÎÛQ Êç¤ù›°¸z3ºþ[ð¬>­j|‡%éK%>½ô;°ñ½¼úÍj<§™»a>p÷»÷ÀàšG¼õßn·ç­Oi"s¦r%0ñr$%”éá툂~–3';b2ƒ ‘K )M`ïð=Þ‡®X8† Ä !kO1°‚•N¼ïûPCêñœOk±áà9ܹƒæÃ$¢;`Ü…«ÒjwÎéûBNg›àø=ˆ!¼ JÆ-wá™uæʼnõË\hbz±ÃÛ3̲)¹¸Ó_m§egaì ÈÓ• Þ‹ˆmøE/¢±?ÔÕ–þ¾S8cÐ _b(§[ñy }¸£CŽ/1˰½C¸ùý¾9ÙÚ†(UèÓåÐé‚0¶ 3Ƹdˆ_€o³ÑàcõÖ¦šÓ\ƒè¢8íç;;bÓËnxšë+:Õ2®¤³í)^™¬}Ÿ {w•é–,‹ÈÁäí¥Ûd&ÄuwÜ®ØéöÑ ÛÓJùÖ¥ÏßÎ[£6ÓT+iUU§ªÙг`r:ÝC&+¢®Ÿ¬À2âfTßÐ5h#uW›êDZƒšž¤ÍöŸI¼¼,ÐîØ{1!òb»™í›¶vvs ˜æd‘cº’ꯂ§ñ8®ú{éÄ€‰T@r©@ª@ã¹Q¦ç¦ÑôªÀf±_¶r#,iti¶6ÊFûdIUo]»K&fLÁ4³z¢EgP—ħ;´¡B Vòã-†û«¹¢IðdìÛîv¶ÒqPwltæ·b)…QÜîUiÀ4ã­‡i~D &;ã‡;V¦}5†en¡áÕl¤ámT9¹2•tXÄ*ÙÍͼꂇk§„fZcŽÞ.¹Úzêvæ9xDz)#­õß¿>U*¦û£~ëg=61s 1Vˆ_· Ñ‘¶½¬²0¢þ73å*å|å–j>2OœüqÏÌü šv#“AÒc±ÎLçî΃$_öý½ºú¬óыպ»ë[ºz±G%¦ÜeŽÃr‘Cî„ð$'  .¹Ô°Q삳Ñ®Ù>c÷~Ú_{”×.±ñìw×:›ÿ¿îµ™ÇíqÚ^­ûZ¹jŸ((˜ 5œ+Ñ™ª¨ln¦“Cëòmn7Ë‘ÚRÕ»ƒ¦n´¿’‰"¢Bô¡Áìxų<`„Ê’+j€W ×°1‹“M,t&aš,¢Î5ãâÏv‚wÏV è$@èOp!!r½rìtøÕTZÒ8éò—–˜j”òÌ h{Ýj„*ØÌ÷픘Šj õ" áòZÄ”ñjLlªÚ”ᙪŪd”<¦$‘˜n`txë–ïÕtU±Ò–…S“åñµ©}xo!˜?kå=GWÛbª.x¯±¸í¶Ýf`ÒLSi;ÒëŽw…㌲ÅßE¤‘¥ëa…ܯxþèä}¡ñEzNÝPÃå{µ—o¢Ç¯¦0ùuÅõÉ ì¬Ï ²ŒKØ*§•ÓÕK#kj—ïáqu†¨sXêš¿}: ÛC®NqôjÙ6áy âÔÁ-zç>¶îÅæ'T=w¬“jõá… )ÍíØz–T¤R™2ffT‘‰Cq({¸Êà„JFŽ˜˜Db<4÷Z•ýC”Ñø—Â;LfølŠU y"x É‘èx)D]áo=öœÕYZ ”Þ ¬™CDhmb…g&©ùZO¶Å…Ôç‹É$Ç¥­†¦ A™ú c²&({(Äœ®¤¬Ç”–=Ђ†Ÿ7OPd«G6gh3ýL]Y\ zòÓ¼ØÂ5_ƒ Àrœ¿ýåõ“NË*)õˆ¥‡Uš†æ™P`W ºñôÕw£ôlQµ> ql‡“’fkQô„şb’`f¢ó ʳÏ ÈÜRÐõøó–ÚaÇÆ=xqplÐjÂJ"fâÓ{LÅù÷燮™mØ….†a‹;‹ZÚ°¤©  `nÞµ“|-~ï'ØmÁÒN€Âú¬Ë»dÀv× O'+å#IÀ o[tVÑØÁE8S µëCF,ä»7(õÊ lúÄh„—üA K+¾['ç’”¼·Cjäkö¹!†ffÒÉÝÚC3Ës›ü¾…UR7-TìUâîÕ\Pí•Bi/)´ÄzTØ_?#{k÷)ñaɧËom rtUªmøO·…» ž)g©¢ì±)"µ5¿(ª~nžß¤) ,#obJèn—›uƒbÒÐÊÜÏ{¼Tª>ÃPˆÿ6&Ëôpå/εã…5|Ï¥Mž*ôƒ‰ÄŽ,–ËJ”D„8b0‡Ðã†õ²×G Až[ê" Â–ÈD$ئ ܨ€E¿»±Ûsñ°¯–[òÔÛD·ea`0™¹LH™û½I æ4-e«ärÓ5^Q)fM‚˜­y2Ùá&ÒÚ㩞¢Ý£»†59WC¤»MÊ6"­‚Õ 3Áà 6;˳MÛw†´`â­˜þþ±Œ#,2@ž*G¦~sÇhyöΠS¶ýœvñë„”øÙÆŽPÕŽÆ6àÑ­ÃoC€Îý&õJ®ükÃîÚs(xò:ØtÁ¸åTjøcÈ#EÑôywPÑKYà‹ê Ú0»„î!ýªj]1ÛètL¨ý?ǃx^%»¿} ÷“L^ãÌû#ŒãBÞ¾qï£]M¦<-ñ5ë K Ý cûäÚÙÙnØ‘%äìã w íÇQQî{wÖ–Ì;B}1\Ot}©dùFš6^‡¦m³6»u|7¬¶uœ®&&ƒ‹s×5áå:ñH?17ôøtS'ƒ8ð‡ž‡GÙ¾ŒOÀ¼ü± †. ¹ÿö˜N3.ÇCÃ5sUÄÝ—«2_áPr&<`+PÇŒ>Gø®tÛM݉fØ;WMLÙ0`ÊÐÒw~‘ºßéŽtGÑ6  ÇHè[±Ó%¯žþR7*‡ÀG`÷ZŽü;t#10Ùø¿úXD´ç]AãW~­“˜ˆ™pÂ9'Ïj]%¶™®SQkbBB 7“Ž)óê¸mûoXt5‹ÈaæƒÈïepš×´äQ=ûó,š ™s˶/Ëœ,)L¡ð‡Lì›*qÁ$ªKq¹ÅšŸbmgÝÝLECLËadW^Ö1,ßauý5« Ûþ 8à 3°ˆ±§Fìá`±±¨z2Az²†®T`ăáV*¸ðŒT4ÑPµ°–²÷TªÆ{·¸C U—Á1•ºeç­Çåˆû72ùŸ6 zç†0„Ø© äímôƒñ´š|Aè u˜˜ ÷n²&º€¶>æã¤ã¦øe1݆$4Á¼~Ý™¿"„‹´‘hU‚ÄL 6@¼ôðƒ4Y¸÷k¬Ä>ÇV$+1rKkGÖ<_¼CÁæ‰l4«¯ôtê¢X½¦Õµ¼$o±1§bg“Ÿ#ǧÉÛ“:)%vGâéS ’§_âjzÛš°Òjqbñf `Ò­²4 Ôƒ±êB®5†.7.8±e–DxŸÕ<Ô®c#õq0¾Ø>úý\ÃtoTùôüE)õÌíQ¼Ç(z³ñžIž.òÿ—ôk´ø^·÷cã[bé^Áô§Ê¨žxáÍ„Zɘ­¥  ŠEd’§²šÒûgƒw ™”äSëÝ æôµv¯ß17ìl ½šüp<Ëñ9‡âzlüÑ %ms' ž* tQ©(ÂõÜܰޞ&?]Q?ñ[g0j£«*÷'ÉC«£áÞØ=á×üÇM|¿š8ü‡¯šÞ$LÞn~KjÑhèl}ö.4 nÿ? àzu&Àg {|ðë{)|Iùbµò®¹—ò»d%·(ã:5?l%?ðÑDäü§lšFŸõýP•MŽõþG²=ÓnÜ¢»ƒ>M“øÉi±ƒûGl8k‹¾îØ-ûîÕŠ¿™~æ}+¹wžʃkÒsîß~¿­¼«$Ú-bsºþãfú Žû<3ÚöñúˆV"ï^a¨¸Ãüzz…%üŠø]þUzØñÐ[õ[]mÓc‡MRc¦§\ϱp«ÛªÌlJÖü.è¡]°ïÈrœë:}ur#Õ¶ù!ôy% £Ý‘Ýà±Õ¶â¼Ìg¨ã•\¶Jr ¸5X©$Q±Ÿ;¨æ³(¯ÆŠ¥µˆ[G_~ŒÔÖL¢ûá9š«ò%J£ Ö„Å„´)5SuÆF¢ ¬jñ1¸ªZ?,¾ŸÝtiÝ!š“„3Ä[Â8CÊg2Ÿ¶¬m’<µk…ÌÙ~ŒÖÃŒéìo]9@£¡èªø[–žRªvY\oÑ´)”hdòp.bøžqyxK…µîOÖl­2ÇU#˜Äs7“ÜÞéÁ|¯ç·±R•R…-Al$ÑÚD]º}lZ|ÉÖͱèùèùªÅD&ÖÚ6ë{l9—{MPle•a0¬­…6Å 1tÚ\b®Y¹S 3äŠáØÈˆÚX:¸ýXF†eD üI±Ýž­<‘; ù=¦—ÄÈÊ€mC'æåÑ7s³~Q~lYݬ'TÀKåÆÏõ×»m«MõסȼπæI¶ŒÉ!Á“-¯Èè‘Äþ?—ãMSº×r¶W]™CÒÈzgŠúd`E<Ü£vƒ¾i êm_3„ø`F}<êTS”¶_I.Ýh!¾?óÌ·õy“_^Hˆä³Ovs"xaN? k«û$,cCPp¯ûÞÈËv¡Ø÷/x0~ruðø/†0#~Ùøç)ˆ9:†Ãeú÷â`8¢Ù<|‡–þÕC”vq Ñyç$¡›` = ! œ‡H')Úu1J%'J0p™&E’ØSNÔÄ!*V\|cÐþêàÔC~AŒç7<´5Õ¨©ë© ýŸ‡è–â‡o?8Ò¦£òçç™%Ów"³‹J ¶íRäéÅvº«èµ5“”]‚8Û& ãm4…uÙNM ÍÃâ¹fžëÚ‹¿t#Y~/4²…îÌ,’Žd¶2¾B=cN·*9˜Jèº`—œþ¾vêÇñ|5¸ÝÇøf®û³r`ûGi™6Pn6¨Üc£´}g•ÆlZéÌÕˆcæÄÝhX˜}»J5$VY4û #Û½WoÊY¡$ÍMNÝ‘þ ïøÔüÓw‡ps.}ûÉE2ßÚfV·DõçÝMÍæõ¢håµ, ‘èE4AÂ¥uDjf²²HÔºhÒ‘Ü\ýG«k·1 ”ˆŠþŽ}$þ Œ¹xœ“Ò¤ÐõdÅÃÑNâ÷4jFÖI6ù±œè'~4ÃÓ¹ssRtùtâ´xTªwO¢à°¹%•pÍf䘂òÚ]›9{..H³ë„Ü-#ƒ/F—ƒ»hZºwˆ7eVº<‚08¦“2«AS*4 Å¿DT0ªæAvÈÂ릱@aØ„ÅúË :Aü¥ Ö¶{kξ>Íy±òðx,6I§Å¡ø`Be "”ù‘•aŸvr'óâKà(Mu@\‚®0c9òüç'M¼x¾·Oú?ëtç3§áaxæÀÑ(&Ð"{”@¢Lkc2`€x§s,À@FŠðS¤‚¸»óí›Ýˆ2—3ãé5¶Å Ë^ÉÇŸ¹*€Õ^ t@J»²°D˜›*„BuLTa¢5ï¥;¸àPdIZŽ,¦Š4äBŒë&¿v½¼©ý~ÿ†F€ýÍNPÁ«aøÚ´Ú—Ö²øq“ÏBØwÚ£*þ\?5Qóé:k·±™qÕµçâš>žÉµë:©.Øû'Iñå%ò§fvœ`µÁiV&W«ŠiCTtw}4m´])¼A•Ì\ã £¸1 dD±qÁU·îÎgÊ› :æöZˆÖD#¹´å ^qÇa¹ôÂI×!WÈ4ú³… ˜ÕO…ÕEó}½<üµÜ<ÝÝ:SÚzs¬¿HQK}N·rÇlÑ°È õ À€¤DT;Â<¹Ê<Š=ƱٱgcjŽ!Å•sq¯>C//fsðE#Â:öÌpýàZ†€tÍ\;p¯c«†äŽ[#ù¦ÊàDûðÁø")‡’õsŠÙ¢Š ô‹§ÞŠ~OÃÝ ÇáÍU hÔsÉÐÑD†Eͽ´qåB‰å½^˹ƒŠ`úY]@WÒ~ÐëÛÔN¸3G2®üÇ‚v¶?Ÿ±ô‹»>¶(4w`} ÊÆÏ£¢+÷0»Îâ®5€¼ž¾l ™nÐe6ñ†åì˜gBÁú~$d 6Wá2Þ¦M±H€™×&[ù:~Ëõ{§ž…GwW“^(ÕÑX®cn½J’ÈNñr$ìÏ–ˆ‡‚åsü¦"[Æ'š‰À„‡dÇKJ¾ü_ËŸ¸‡Ñ-- õºÆüæäŽr’¦øÄ×/µ}¥ ^c|+r4;Rç] …kGj 7{õOÛÔus™”sKÒÊ{]¯Ó ×ëgþtO꜡|4Ëx¢_õ»NÚ—¦!4rÐŽ€Xï—˘΢57¤ ÒÓrvK9p¿ÃŸJ½¶1ËQìe®±"š1P\˜åãQSææŒõê’˜³9í¨H­NîEF‘˸ã8¨º)bÖB@îÀ€ðÓHÕ0y0_j“Ÿ§ž­Ê†9éàOÍiÊ!¹þIº‹XGªü—jqy5µ}Á¼z¥~ß'—óâÆ£ØŒË±ÈHn°c¬6qE‘¶žÿÕ"b¾ÉÔ³u6®Ø*1öàHÃÍUÊlÒ·pOŠ×‰íîšža¤½€a"µÌ’ò°êYfvøåâùÍ{r4:c‘üo¿,}¨ÂAíÆÿ2Ì:ðý1v‡?D™åó‘ß$ÏV’Û¡‡°­,®ÈPž—R‰äÒ¸@'c¨°s2yÌúŸ‚a@{ŒÔÕ® ‹[‹I3’ƒS æÄãgú)h ´Ø8iÔ91«,Æ“6–6ºRà³úbgmJ k<`œµ\¦~?gÊýg Ÿ™ªâ¸JGã•Ó5§jjk„®.£(ÛðŽ¶Í‘ÐÏÓ¯:÷6tó™tbc´»¢v–k…-¹†^0UÜ®°C{¬TáKQB·Y=1ÙR¹%êμ™ óßB R 7¹³AŒ‚(Ï×U„§7cA´Œj>UÇE ÜMÝ vN,Ú0Z<Žt:z9ABÞfÄ(Vò×X‹8Ûk¦ ã1¯¡_ÌR{ýAEXÒZ¨‚6&L,5Åc@÷2.bÀnÖ'ôy8 EEktênY{ T0go9Ó1E7^i½–+:ÞÌê‹Ó¾Þ,ù?m2Òvo’fHIƒ'+×»S…ÔtÙoWÀô.eIzÀè&Cº^)ñ¹’ùˆ15ˆhh` j‘‚ãQeÊyl°R*¶·0èç’Êýíä q=ßÀáÃ4íÛf)–ke„ÖKpê2WS<ªÔþòŠ49Û Ã*ûì[E¢‘QÕ©E*»W^ŒÜÃSb<§ÑQ›Gs1zO·#íùra$rgV[„] Èbèº8@¢ì ©ƒ‘™ 1“¶ªSéu¥OÉí³¨ŠÏdà‚†U ÊtÓBpMSTm"C·ŠªTôU!YWعV%>/V=î\éÎÙÆ(ò7 I1',P+Ý-PÑÿ ŠœåÓ¢6é–Ç[*vA©¯1ÑOÒϯQ¥ç²ˆø¼õͼy©ž©Ž°c+•QÆÁѳ¡É14Í:A bE•¨ø™CJŸ¬³n¿Mk´¶]+¹î‚‡‹§óºy:}Öš{Ú¨ìj © óLp›d1*ã/éò#‰c ÎýSŸ{›)eW#•jåݦ 5T?5¹ã¶H§ºÅe‚Šß6²¿¬ú'Ïãà ¯0lëaþ (܇B“l7½÷âæg™®ÌÊ)íÌÕž;;x}’Ìö§ž;bÔ ú]×ÄÍ1{X€ŠÁ˜#þ³ø•ÆÄÁ¯^»±‘ÝM+†ºt­y•Ä^B‹ F.S'¡ôë\ ‹¡AîÕ„lÎê”f[¾¢ Àωd®ÛÍô´š Èææ{†k±®Ãè{.6)–JØØ×àÚb@ü‘Nx& Ë=™¾ù»·lJš}á/|Æó¬®¼g.8=ž¢B´ÌÄ5ðÛヒøÚˆ¤JI5 Øa‡G+› tZñ‰nê«Ç^‡¡Ñ‰ìþk÷|støwD¢…Á÷¹{—éy%^ÉÎÂâ¯6B¿XX¹È+ÍÊ/CÊ5Ý…›˜ò¸& ÷íÇH4! /Zfj$6ÇÓõd’EøSírØàGé›í ? Ãrã"Ù Ó¢·fä'OüY\4wL‚¬T*Ú BB¬H«·ô±ó53V-¯²ì¿‡ÛîJoáÞ ÁP<‰ ugÀWå2¯4…  `ÂÍU6Ÿ ½^·E$xwý,oæ%ré‘!]…Åk‚q¯÷@œ‰( öNB–vf£èо²>c§)“¾Ó,ê3.j5ö®¯!¨;V¾5î‡KEÙš Çè`¦/A·+ñ›Žl]¥1¡4¯ìl}ø”?´ Ï/\qLûW ìsnþxšã÷”HÒòiS Ü­êVh²( Ó%»~_NŠ«7uIé·c.‰I8è•.çèu^×O¦»‘šî Ë oƒ¼¯sã=/—v’"§œgêÐeF‹½¼ÑðÔöšÛ ¨±3áåUn5Ö*ïßE iwÐ`“ R†“"úz¥20“²ÊþÎm+Š o¼¿Ïnß)׳VXۖ³VÎ"ÛŠ•h‘I»mSd9õ®hpçŠîw²‚¬‰Ý1t#æÊ"«×óÍË£Ms*¹©¬ .: ‚dd¸~æ­™“#êšÄ?C„*‹âvü»/3Î:eR‰}Ò’ŒÒV¹fÑæ/k'5@¨\ŽjÚáSKWf4N&3Z%øu”¨~5ýñ70ÓA¶»aûm.('I{œ;I9hIÃÏ활”„ÿõŽþœ4çPÕ•ËCâŸõú(¢?r€ÜÿÔhbf¹êw̲ƒ·×к8K¾è‘ƒö÷µ”Š-Ýj·½ùÖVïì!`2ó^RV’ôŽ‹(^ XzËOé'ËÙ°G´{"Ç]èÁ‹©’dÕ‚>¦Sz6™B*Ëà+I Õ»,%ðe&ƒàÌÉ’žå{(פ.±‚œ³ b’LÚÛB„, —¢Üf…\êWBª²•”öAî‰I,%Kg{ÕöZFéù1.8ëB™™™Œ‡(ÝKßn§xqf󽋶±‹S­¯Žã‹${ùvý[éªÊ™QL2G´Íµ “&¤®’4<2]ýÌɪöY–æH¬¸|½é©nÍàô;¯¨ê©Ÿ~F=šÜuÜTš<"ÃiŒ,ƒc}rz¾Ý×6×>Ûzcdkªõ:{ƵÞ"o75KÎ*S»é… uŸÐGºK+î·® öªá5‰Q‹åñuªcðÞpw6Ìa@­‘ð™!ÇÝ<¤&;]€Ó Eô³eZÔXÚr(µ‹¾ódÍ`p_ Ví¥´O²éh‰O¡Amºé£h»ÔD1B›>׫©4Û;^[ „4t#O­<÷Oèâóókc‰-}lvÇxh vuÍâL;9Û¶óMÆšJÕæÎK±V¸f°Â$Ï{*[›®­<¡®[<ûëÊÈSã óŸÖÄeùþpïñ‘…š4´³î³•ä-¯®í¶r“ öcXÐC0Ž5Ã#¼ºj$fœªˆæ­òÊ|3_<íìj» Þçý,½öl2s~~|7^ ÚHg¥ue;@䡸z‡4Õ}Ÿ:0þ,=k…¦ã+-g-Îg7Ôå@E®ZŒsÀ±†²a4cl,¿ÁyrWÈ(xYpíþ쪋ë{6?læU8H¶ìµä<ç]ÔÊ[2”•ÔVŠi¸‘…TI¥rñó»÷\Uwumìºm oŠT—„‹¿çÁ ÇXN Þ…ãïxzüi¬––$ ÉEw¸ÙFfƒ6³N2ã¾\[ÐÊtv«t™XhåN³í3<·,9·{*ÄfhFÍ ª•^·…JcWSÏÐàìÌ- CS…}¸^"‚öÅ£Õòb8]µä°øþÑO¯l»¢­Uf‡]ôù¬4æÊ¥dVÛ©G‰Ëè’ŒL&ÑB, 4}R²#êA÷AÚª^ vÇ©• PÀQæcn×÷%~V9“}œþ z®}íFa;»°“3U.Q?užnX7Ob5$+¯¯nsÍi3ùÅ´æÝÑò`®Åÿ_Ä«ó2T´õ÷ÃF¼lt¹cíÄn‚a 8ì …Ïü_A:ˆLòù™@&´õ«½^Ö*¢Ê|æêÃï«?›íÕSÿ.ì.­%ùvz5õh•Õ9°ÛÕ†fl©˜Áu'Ûº3bÍïˆPŠeÇWÔm( ×–Là=t™×¼¯·ÿ:ÿZ3( ¼Â_SjÓ¥ 5ö<(àŸèŒ®¾¼“#³ÓIùãŸÜåÑmÍru»àæt:ÓÓ¿_^AM \®h=vÊŸ»È$Œ3†¡ïõD8þ*ã—‡Fì rós’ý—Óhl?CbªD[]N7àßÞ§̼µ×W“¦ü×jÿ`Õû®ç»iI?~}]=ìG¨Øa—ªÐu¼e…dwø‘­[?"Ý=-¢šaEüÙ~Ý›û0^ë~þAxŒêÑ3*£…Õ­ Vâ‹èg|(¨D|²ßÛÏm¥Cèj!yKf¨®&&†ø¯"H +Ü+#×3• 8É5ÒÝíÝÃ=}®hXýG åÍ8a͸¿2Va¦³¹‹%þÔ}‚fL3쇳M˜PÝÏ‹ó}± ^—ÊöÙX¹€¯_ϯÉYõ}êþl6˜¹ ¾.¨[»ªÐy:ê'•„Ö£Ãw.IëZ+2bÝ«_U5cÍWqEjÍ_¢­}§¡qñÛú ¬ÄÛ¡lÖháéç’·“q·¶f\Xú>PÂ߬‰´Ò"´{»êáÝqÎZ£²ªqů“ÓªàäO‘&^dr×RÀgUzØÀ°Vè†ZÅ»¦Üj ¼È±)·Ô{µÜGCc’ƒÏQ¸ê!„aH›:É*¨F‡PP/£ [ËYE—ç^Á» [”«5m4è!(.ý¿Ó×¾‰%¸ÖÞ 2fXzçEèιLèÕçá¶u-¶³.r?·›L n|5VBíì}Qê¿b+¼:YgÈ-6bû¯Úy+çÄ`ÖÖ1Uq/Âͪ+Üsý^³ŸL¶]Ä Yîµÿ*²¥Ês„a°Ý#ƒÙC¨¨œ±Žý4–ŸÔÇ©RÔÈ‚}”§òÝ0¼Ž…C¤Uì·Ï9ôtºÒéηSßÔ&¢šŠd&E?³ú¼ñf¢Ÿë‹£Wí«ñô‹ZЧ­/ÔŒüøcv.<"ÏãUë÷ùýyg^ÔúÖ¦ûF†öÝYÚÇÃì¹_úÝ?áZ­8†$ï#@ 2b L!Gíë‘—EÐîMR#cxXá°_²Qi´I?šV?ƒó<üV;¢))â5÷(ƒ,7GÝãä÷úlZc·*ãý˜ °N^±Ò»ëÒÛJ ÿÇ1ʤ~G[¹?.¶W.<˧lRŒ¤KšPî„MUó†”ùÄtUm-¦\ÍTw>‰Fć&;ìtø=oMíöa…³~bmÿÄÉü·¼tkv6vúå·k—)a¢™\D\£žypÿéôç™9uÊ€Ók»SKb—•Š(Çõwú¡–Ø«ÀvjÇN5*2¨"}šWK§ÅÑÌÊ#má<ÊT{+=Y‰_AW&_ÇãÙ±ìq…¤0ŒY‹¥G™¬“©lë§U<"ö‘Í¡pÌkmüÂû‹®úÊú>ªîëd¸ðQÓ†aœû="/FŸN™‹`2 ˜C¹¨ÐèöZ·z*‚¾;(.d‹Õ{mDŽ—ù¨0àeš0àm5lÖiˆTŒš®¥¸Ñ$ÍÞöF¿WÈÍÐ)d€@î›ñ@0€Ùd£‰­ŽŒßëéóÿ±|~ž•óÖ=ÝZ#qŒô“³„¦~·Ò¡UzöõuNÆmdQYR˜êŠ×Øu#JaøËò«àGSV ¶“Ý®%ˆ{{dÓæŒ2ŸGõ? „”L^ä‰ÛV1 Œ]˜Ùz;ÉÊ!ünyâ¼'öXvbêþ‘©¶‘æ`—7c›daWTòIã­ì|f<í`‚¦×5L\Ì‚¶¿Éå>È–2ÅŸc*,ak† ×L21ž{á\Ô¾g·ñ‡[Ýï;C’ÃŽñ¶ß[]¨jÿß—8ÖpüA2É uÙW_1— ¡š,µ·r'DšjˆÉ ºÿ);Utm¦·f8}/#årðøç¦1Ò¹ÍW§C˜ @¬£AM&ÇBiÁ騙 ƒþáó&)Ù†L±T4¤É˜C&I—vÊCÛ*KR˜O”Y´g qÑxÓcxÕò`Þh™³}[¾¬j´"ÍH´ïÖ¾Ó=;l«ŠˆÜ2 œ0)#J³ö¾¼9†öm¬S8ê”yD‹lqˆ¤ÎçêÆL,§gz€…"rzÄàûšqD$§æÅi‹­XeÝQ|oV­üåD·ZZÅ×ÏÿB“Å@ Ëï¤×< OÎ+yˆgÏ`ëöÕ =¸ì.¦YGU$ûà‰oXïËíU[vlø%1Øs¡fì“|Ÿ¼Ù0C}Æt.Ì`¯gòÔ\!CyØB÷Ãyçe6•™´ðXK¬¬É/ƒ§ÃåÁÇš“´˜ÊO .§pº…úÄ|9þL¿"8SÍÊ»ˆž?Ù+šªz'WƒûxÒŠëì¤ñòˆñ´ç€[eŽeË‚å‰åyÚkaì Ê#ï ®L©2w“‘whœÑ­} m©Uéàn.F ŸwôU>ßœþÏékì¥Wôh3ms†+÷âŸ,'¾)¿cÀö±±”m¸¸÷L{S‡÷f±Ç> 4¿ ˆFÃçDG0ï‰î>ÚxÄ⌄6+§9Ý5}º×tðߦ1ÞéãBåªý{µaÐò!X”ø†þ÷Õ®WM!ÎéÛ™”¼ËÑl7ðÛs¡† N¿Éqfô9En¨Øu½˜À¥Ó˜Î\á‘׋CœÞ¥z†.,2%(bð% ôÑ—–<Ï {J72تFcgÏ¢<åÛÙ‡j3øÃ=“_ª2/n˜¿ßþW6t¢i#íL1+Ú_н§Ri”ýÆ0v Í£À’hfns Ï›Ô:C³WœJÚmi½p›ÄtÇ+¶ÍæýpoÇBê¹],¥-̪dº™:[Ù¹æ2nêÔ9±ìäõ8ÁÒa,iü.sÉÁá®§i:¤—jz öíÄd[57wÖÊMJ²~fZ®Ó^PFïEZ kôR9écök¦°ÑaëÈÒLlV³tZ>^k¶dò(¦”yY3 ±‰”,Þ"úâVÜKB؀腮Êaóð’¼.ÝÛ‹Éâfñüûîqþ$ Ó&e‹{ëùR[¶âVb€ Ôˆ9¡½vl‘ê¤åe‹e÷$0š÷¬2Ø©› ØÅ,ö!ï¯I ƒl ”F2ì ÌÌÚoŸ¦ï5KQ4éq¨ªó⓱™¶4àHh¤vœ·<Ó3r&g3gå$Áí0×iäO˹O¾w ÊÛφÌzyv‰e©/Ú}MŽQƒ·ËGâåä28»ú@vDuˆØt‘µ«VÜÉpÇax-IÊ ‘K%!“&\†W&*ºœ±T$­&y£6µ¶:‡×ŽeÙA”’˜Ê˜è2 9KmARšÛDbF3¶JJsS‚‚ãUS´üMPå¿LYù;ÕßÈÕ¾-r!î‘9@h€ÃŘ pôÄ^øçÁ+;xC ÀS 颳Xqi†·M‡”öp`†·Í깣ň/ѵÁˆ­ µÔGœXÍ’áìDþzneƒ>ô͆³&Ú‘iZ‘Y$¾5PÍ áŸmv‚æ¿—ËÎéÕ²cfÛýp'§r™|ˆ;Ë­ãNÊW£Ðy ýI/›ã ÀKa‘ú)ÃÍÛfA€w©“êã«G½Ò0Á‘ø2ÆsIÁúí'áÌÔµS‹R¿!´È;Øã p\ì¡ sA6žVѼ·8ê"GQ¡ ÜV dàh^,ð¡J—#ÅÅ‘_OÃo¶¤©9¼íÒ@Zdœ¾ÉŸR‚…Ùïp~G–!a>ê%bY2L£éX•n£M2ѧ‘e4è£öÝZÊÖNÒ†Õ¨ŒÒ¾'~„ïò›¶'×p–ÿ¾¿¶5g hcˆfá¿äpµv?gî9 ½ FÚÞ/˜…K‚F›ú¡Úöke šE™g9¦ˆ{ag waß„â YiBMi¼!r™B#MN—gðlÃKr3aN„A]ò‹h=”LßcãÖމի¾¬W”åâ\AÌ®²Ž þÈ|ÛŽ,«DbŸÛÖc¹5–ŠŒ<–hÞ¥çáªöÔ¤'®%O‰‹Ø>GZÉ¿Aù½á¥2k5ü%7„¦Gؾóç|Ǻž9I"óûJ„È>¶>ÿ¾šeØã yÿQ¸BòKM¹ƒ-€B°{¯aBaÜrI‚¡¾}Ã^ðÏ2f§L 3¬%T×ò#N¦êg*N†6Ï†Š B(H“=Õa²7idcYÙ‰ýãlZ…†—!´?ëYR£ýâˆÁzP’aÊɆv–ï·íG[Ï}al8)CI·.VökÊËJJ°;ãxv„I¿)ê-S=5:10˜A¸Ó©êÍX>i|‘½hÛéßUNò«¢wÈeâÀX´ì5ÔÍÇØH a "¿gûŽškf£„Œ™UÍI€0”R†}ät$)?מå-!#G[oh‚ú0ØBH&¶·ÅOƒU÷éKÁ!p¨¤_)91ª®ŒýoçÂ%4vð9ú˜² éüñ Œ([Œ÷ùßÑKvž!;i•;j ·ü•âËG’šã+UÜäó¶Â”>ӃǴøŽÉNXÐ.¦;T6ù.ÈéLPýžy™„ ½îTË–Áãþgleé¬ÛU 7–Œ2é;ÉÃ%Þ¨lœ9p8 ”ï8@›¢ç ª¦t9L2„"äM¨òúÞÆ>)Ίʩ‚Ó¤ua ϵ’)›˜Ô8fE 3µªhøhŸ•;PèÆD_µå y !Û+º!!TûcãM"å``îd'æã€¯¢251¤gY{Ïçf9qôàì$ïNCahÅÍŸgl‡e‚4ïÏ®Ô3Bmò9––ÕWæÛkfÄ¢úiÙ—E¸ѧ©¿âûµûÔ¡&â¢~üþênsâ;‚”X¨Ÿ$ž£åõàŠcm‡è‡ÞŸßø½óOÄF`ÔÊ-ár§çÌênÜq2ÜSI—£_ÁªÏ‚.oo]xs­èÚÇ¡jewúüðDƘàÝÿ=â›ÝÔ%Nôgæã²Hl#˜øI?^Ðè“´x¢¹ M “¸?Gn {ÏÇ˪R¨™Ù¸õ{¶òÁÇÚgá´ýX>W€0ç|Tjn¤bi6¹-ùkkNsÙõÃ/ï;‹dpï¯ô‚ƒÏ?.ЉßýŒ2‘Γñ({±Ã”d•EÃ4qkd5ÐBƒÛêN¥¢È šg'¯®ÅH§·Â¸y@úßjŠÜ˜ (йۓnŲB8•,¯&2etÈ……×WöÛv0Ò-ó Dkç×ßãøwvÖAß—ÿw¤3Ó(§9íH—%¬o–±næ_ʃÌ#oŸËËó1oðEã>x$Å7 ˆ™V±sJ>Kúïés¹r×tÖ©õm ™ÛÌû¢¥'…€Â‚ I …¸E[|'Z3ª‘Æ!jÖDX’’:Qˆ¸ô£Ae!Bô¯ò[+ª)‰/{—<õlNv×uªüQ.Ç…Ë5½&•´çyª±U­²ïmœ=¶Ðk^Hã= Äÿð¦p͘Ӕd¼SÛË2PÔsMKcJsk¤sùùÿ±¿·µ_`‡]P÷Ö|Õ‘ÎÚYÅ—ÃQÚNÈ„ÈHœqýÇòÝJ9æÒTh:8xNeމ9+r:C>˜;$†^š›JOî. Lö:î—êƒÚ׌=¸”ŒR|Îg7·³TV”³H†díìG‹D¥ï?¿ °×²»†D…5H{0ኧ^ÌD^í®{4?Òµ0/†Éø æ x Ñ©® PÀü"[ÁŽ8—lNÌh¸ái¥$s²ç‚'~Í@Œ·l‰2* · ¾SJI¬j#ÚGÝ_ •$¹ùeìçì߆÷òЇ¿‰d[…PöbïÄÅÓïÅ&è:ìï &#ÌÐ|ûÿ›Bò³…‡–²¬ò9ÃÿQõY1œÙh482vd0Q·ÿÄÞàý,y«K&M  ŒDv’Äyú4kú]Búá@¥x‡—‡ ü/üGób¾( ÚàÆ4q9¤E¹Ž”Ö˜)Ÿ£ãλí&Ã+n1,*µ²c"å3ôZ­ýN;~;B³AŠ ÔÜ«DhT>¬Æ#çhv3 ˆ²CéÊ6ÃE÷òá« ¨ÝRgE;`/V¼–ŸO£’»5U¤¤+BlÔã!™™QppƒÈƒìU°|=¸(X¬bAC{ëŽIKŒˆ(s8ýbŒH­O"%D»žÈ{——œ¨õ‰Š‡¦9=¤Gˆg{#vµAç®[¶Æ„É“2­  ¯Æ§Sb‹´•âéÌ>3ßt‡eÎ*]QÀ™ZdGª‹R­ƒœ=[^™:Bj—FÉd:yƒ¯Óö_؉¦¢ëÅ ¬F±ÅDÓÂË;L¿s¶G«Äï퇺ÇÅã[ê˜gdJ/‹^|Áû©éŽ^Î`Fp[Q*xȧ¡Fée \ΫëcL£òÕ&b—Õ÷ó¬Ìa§`lmLÑQ£žõ|nJM÷ˆÕi] •kc_Õz!À<üf–º¬S´Á÷¦ßa…%÷b~Ê!¦O¯êñ$íü}zn¬Þ€q §¯Y(LšÔΤ ²2î©YYeëÍ-L€ÜÀ Ð1¤ÄÁ‹_U¾¶bÀùÏ^b‘|Ci·©•3¹×è:~ŒÔ¥,#×Ê„¸-ã{[ˆÝQu‚¹Àa™Ìõš:'%c§àéç}8#hÜ ·œë=ôš‰æ1Za×T†A©”š·êˆU>¥¡h'µ/l‰T‘Qn-6Ê…B+šÄh¶¢8°²ÎTè%…Dw8ñu¹“­î£žýþ˜€¯ßFêvXÂtùAôÆMƒšl+’kàʲ˜ðïNtƒíê¥g·u„L¥¶ ëWro R2¡’fq‘ËUù´ˆ½<Ƕ­uº¦®Ke+“,Yj¢ªë{§£ÍôÉSãºu† Ådè,ˆíùó)gõÃeãî­«S;„’ée®¤’悇3¯K(Ij OLºYN+É8ã³…4¨@®.kdç|ú²[ÄX²ñ‘˜2aÏíÝØmOŸ§|&³T8,= ®:³Ëêå.MÑ(åT” /ÌxžHX¨7m,"Hä%&2É•T8ÌÅÌïàìTâZÖê'ÿ^b^£¯Ža éêé\Ðû§Õ½ ëï³Äå¶wãè‡}¼Í×áý¼ÃÁÆÅN§Šë[Õ-›³õ.{·áüoL®§,gŽóG·C»øvŸ«œIèJÁúàðê„“@¥7¸mr(œK%cd{Ó)ô ýF†&Ží ›ûÞg%Z;EWE©»Ìœ@&ÍFxè“»A¸Žœ2Þï-HÝ?H c.‹Î ŠBÊc¿Ò}Ì{l½‡Rm'm¾H‘tõQFÕ$}ââyr~ Ýë+C/ÁÕº‹žRšpÞ¹Ñ'OQåö‘Q<ΜÖM&ѹÃ+0I(Ü' #™¤êö ¥¥OÊñŒÆwg©µ:‡TòESí«ëóÆOZ·ÅQ|Îä†L*=ã }&ãOËwOÎéúvG©–¤{=WO53ÎÉ·C#¦…;âI@%Ìz{þ³ãßS÷Wf;aΟLÃ÷ö†¹‘ï qÞAõFPwº·ºÚ|L½›ª•ÆIºçûŽùÈ0 Ê—•Ä 1üÖ‹ØÇÄ^å¿;èë[ö}öDìm1¬Np¿&Œ=Ì8ô”^K ªjj›­™’þ’›Íƹr<ˆ¸yG]ÃÔ¹üùh1œqJi‡¤Ÿ»PwÎ%ê3ôgþÏÅžø©ñÂEÓ`ÂׇoN¦»G(‰Ä6bàD°ÖAÏø¼×«Ø—åª-|u‰â3òbªýà=†Ù‹$÷_5Ì IiwhÍì;vlã]B¼ôfÕ†!«‘ŠÒº Azu2 Ìž„ø(ýÿ|=|þCeYYéëFò_Iãó…âËŽ·Z|ØACk§<ÕA@t7_< |·ÐÔÍÃØC±I˜ÜÑž^Pm¡‰~Ýõ2ijhãKm547¢jdÍê8fýÉD{ g°:»8‚ŠîÙ(§ë°ê#Ú15£™êxá7)ðŽç׉ԓ4¾¢ìiôžÿÍåÆùª´Ê¾½ùp#Ìq¹ôsî?°ò'"0Ü›sm`¹®ÅÑzkÚSYYLM_DM%Y¾—!3áLbŸÖéû]>ã1ŽzعèTT@74–”âÍF”wë|˜h˜µ&Ú‡`g…ÁGÁ¼7aü]¾Ð8_'+ЧFFŠû·¤¿¦Šnx†a` AD-‹ Æ“"ó>Æd`óÏIOÜÑÓ-3{š%±Î¯¹êS2•ì;w7 —o#§âæG¾™¢è›¿á‚1“Ø;?Í[…¼CŽÜŸM7µe¸YóS©}²tMTmòC2;Ÿ¤_YÄZöŽ3yªý߼τ‰Æu©þ²¯À…Xz­…\wyÊÏ­ôÚg{Ú1抢|ú«ŽÓdB¦[íw‰çx ÓMÚ¼”ÉtSȇEAQÜÆI +Ô r貆ƒ3[M·fz0T5Q<ب’ì ±ò²qDenºè2ŠÄœgÙ5]ÆußÒ”¦–p6!C>í®½oI*^Ÿ€P†Cw Ô$J£®¹îxõÉ!¸O󓸝ܽÉÏAÔGuê/eð]vIõ^ËÖÆÓqeÇ¥NGc WOªJ['Mµ7ª:ð=Žla7 ›ß_o~I<7a6$)^ wö¶þ0Yëqàéàéì9 dÃcÍ #y–‹UN™-@ø¸¢`ϩزVêˆI²Cº*v” ,y7’þ¬Uó?¢±tâ£-_+1²ö_/†,×O,Œ0’4C<°Ö²œÉì|ëT¾è~v£ØŒéØ¡ÃF›ÂC\èzg¦Ê‰ìÏ1ñþ·k´Zc!ãà\šíô—fê³}<\D7—£ÍŸ³Œ‰MÜý ÄéhöX[ާ[<L¿3î@’™FÉ‘263€7<ÔÍâ̧×YókÑ„OàfG•pä™û ªÉGjÌÇÑt Á´(sæK·A=®ÚQéßÇnoLwö½Ë¹îšüw#@¸ÈüOx1÷¢,Eç¢Å%(Ùm ${߯þ¯ê0§êÛ~Ù«7ÂGM ‹!˜á|}Ï<Óç7”I+œÃ²#mèÎnÂ…Ï BÅfH™wE91%mG8²›ëô¨;ñžÌÒh”t»'Çf¥;±'÷Ìý_i.þNA—³u0-o-|d-­¼¢[íÖ ÊÈöwok#¬úU”îÖt¢K›õàRÖœ†vðCå³Ù̾Ø;65Q1lÆ'XÔ·gìj„Ç¢;}¼=^²zÑáqÞùàPƒùõãÄp ¿–ó¼£Ñ>œz|¾µu œÄÈÒ¶'—1O¤äކE¡e%߇ì{¶ ÍsÄùžž#Eðq÷•ZÙbxN}(òÅav3¥„"ÝŽT‚gšÝEOÿÌ Ši{ðí<9ú×¶Ó’‘nÄ<ÏoÕPì5S³² ¿S)7­3ÓûöŽæuW ÕÓ¹êã–MµA¹»màÌ Í1"bˆÅ8ßèXëÁz£2Ú”ÉtÔÌQáÇg©‘q¬fk)˜Uõ„›”1¡kýœÌ`ýðøðhïŽØ†Öz(ÇÕgœ& [ ÈE¶°=dŠ’š‚lk[X0ÍONçtóô}&Yw¦s75íp¨õƒ„i>/·n¹É}ú»Ó†¨tKÈFseNLÕvÆÎ%ióA2;>Pº¨Stš=ûæ8¶í ˆ¯sÍÊ%[3éßcå,_ôÞr|è̺õ§n+ÈwÊ´ÍßÇ_%`w~8êð†9 4 ¬>]Ûº+ ŽÒ1|äj%6÷ѬïË&bF6ܾ ÍýÏÄœ­I—EO$Jn8‚+ªZ›6Ö¹ð9Û¸Ÿ´²ÛÄj%ë%ë‹ãï¢Ì¸ûõ­Y‰~=8ªJrÐ^áÜN„! ÿŠ>0ßEB;#¤Ý&d›»×® #1š™ìNš4§«Ûê ôz`ïǼ ^/Z0Ž‘èîp>?î¸áÇOŒ¢¯T”Éum~6[5ÉDàðM8îU€Ús‹÷<êÏ>1,|t}¤—[[>Ô^>‚ope—Ï/ÓŸµ~rá+$Ÿ@Ùñõïa…µ6æÕCº &’x¿o%©ã¾{Cþ]ú I´ÄbÚ}…¹”!!0µp0—µmÚŸ p(¼f½à£ÚÛ[-ô-C2‘uñ0¡xt˜(÷ZA°²”Ä»…XÄÞØØ¯#’Ž'ÃT‡æï“uç83cËÃ.Õ’PÂlx¿ŸÆàBoÖdùDLïÀÃ÷ª€iÍj…ýôU®øUC4~Áágu×ꕚUʪ*ƈ EÆ8rª±Š­lÙi`Zó©MÝä6G€dùY× ¾ø™š*ŽbXçe Fê!“PMPwû(8eiU qÎ`UCbùޤòÑ]ïѬ(Gúüq8rŽÓÒMGB„f1A•£”(¡™Eìw0dᤶÊiFý­ÐcŒpß·UÿŒ~É]îè¯w˜Z¬·àÝ©âK´séaÕgŽQ"y~¸( ª • °d4Gl†~xÓhcƘMH³ÌG'_r+íì²î—ªfLÜÒ—YU3†OƒžC˜`ša»•„7Xw B=½åžðÜSiþ“Õ¶†»`KËznÑè´ŠkÑ÷Ìì§1âá•Uƒ ÓŠÿ³Åèv»>?&"R­Céð*»¦Öƒ†(¨™¢rçØ,Tµ‰\ÄF]£õŒnۛŌuø®Ü-p„•L×;Ô›Oå‡ÔüYÆ­]÷ýú&6‹¨·G¸:c÷r*ް5E¸‰4åÌ%Ã3¸!‚ëÜAWI@Õr `A!]…ðåw‹Ð¯ÎSÀ67E9š‡ÂÑŸRŠoÞÖùh†<çæåÇa“ŠGç02¡‰“0á[u„^lŽˆr‚œªýïÙQ…•ÏSðé‚lÚÍDHÒã“{ Ùô`¢fÕÏÙ;5|,<erœ¨M“œË´:¦U¹sÖŸ¡£Êºmç)CÄ„ðW“°ïFö:7XÀ7×7ËÌ#l ĸÇã_Ï[Ÿzs½\øt& ùCÐR°„Á®äé¤FR2ß… Ëi¼5ÎøOù#Ÿo—ç=ß™†û‘HS6 Û•˜Z£Rdáô"f¿>£kÆ—dÏÓ%¦Û„§äßr9ÛZNãS,˜K™¹ï¡Trm¦HʦðNΑå§à_–l4s"s…)W§lî'…ÒÙb\.´–YÅi§o0re±”-±¡W2)¦HhŠŒ³ ì²-Þ¦C¤7áÈï^“ÌãŠÓJ“ŠC½£Q%¿•6Wƒ¤äàRLÌï/… qû®WF¾SÍóHé$òC½çÝfgõ?ŸõœÁ´aBø¦Î]ïdzµnÛõãD¹àÌQ9Š–½¥!yOáR¾Ú¤+š(Ç̈I©‰Wvuæz½•ï§tÛön™ž8¢?bX™]æ×åæitýMWêŠÚT±©ºˆrÜñ[¶~—+Ã;ÃBªžcË2]>ÝFºÉBµ¥E¢æ1D­l"83$PÇ­‡V=ŽÛOÏèk×ýiýN0Zh5÷²£ó¿óxÒ¹ˆþÔy¯—˼ñë~Gõ!Œ¤áy³CÌÄZî¸ëy_7ú4BWÊÙ÷Îd2OÞÃâåÝ&4G ÁÛð*ôK¢±È÷F•UM@5¹ *•4eU{‡[Îy$e{²bFP,…¹w·Ÿ9Á1lÇ2¾AÙVQŸM9LgÇáõÿ‡©‚ð6s]YI¼Œ³‚‡¿ëyìW{¨á-þ3 ˹ýZ|äY¶”xd&7ë¶Ö3Îu–¯Â ùþËk)®†²Ї\ã*wXÎ]\ r(λôOɧÇçâ¼`Znì_ã;ÚËo¨ž5ãýRüûÇÖàÉ ‡×9õ!Ü™;!MU½_÷köÍèùã(ì;¯…ÐLTsW7¿A]™ÐPur·-ì‰è<õÍà w ƒ·cVÑ¢‹©<»kí?;ý\;À;.Ï^çDn:øé%]Ézïö8ÔdŸHÉñ=lJl“ ºŒ{d(7ÏÖCÃõz{øôÈ0øø÷)í¨ƒ ä%Fƒw⩯g<úõ¨t嘪økdØÛ`ЫK ZW|)aD!>C‰F2u«Kq°r2 ÔÙâÙiØÈ c±*j•ª3"2Á0™h?3ˆo©e ï'½çGÛîñƒˆVPà_C¶»m¥¹ø„ðû~Tª]Žˆ¦N;4F¸Ñ¦´ˆp³QÀg¸³¿”™z²3Âðƒ&íÛ]§s9™ÐÂP„!A•çéöÇÚh`ÚÇ¿Ÿ¬|›ßóê¶šGFÄŒm ëÒ"cŒˆìŒèÚt=Æ“§§±N@’äCpv"ê‚)Q@I‰2½DÕ«_C ÐÛ>íTV¹L©PÇ$üÌmÙ·óÖ²û|ܯTóÆ­cn³WLšÚU\g_ú8ŸCÒsWÌ.¾¿O½ko£~Î/Àæùƒ–RT}¸UÐúiÈÓçíÞz2¶¼6ʽ•””l†èǪgn˜ÉÃ¥yûàÅ䩟#s(Ë«\ÚÒ&ï ýE`°Ö4Ë7m< ]„  !øSg#˜J7êéú:vŒ)ú^„ ¨ëçÐò/Ó'c£4ëPV¡Ÿ.ŸÉ±‚”$ÐH;ÌWˆÂÂtÒɈÙ`Gúô¸<2ÐP‘³K£CUš¬€ªª«"ØÖ`d¢h]2`J›1iÄw§gvÿ̉ô£ÏDŽÇGÏÌvqù俌Hõx½8—mó–szýÑÎç’špªc/O—ëÇÄW\ˆL×ü9+{áH!!VFˆç±5ðÚ3 Û!•NÞÚ$§‹ª(£åÍuÓý:Ru'÷θV7ßùgÀþþ;.é# 'ázç>;˜¯O`uš†¯aªú*'*OÌ¥²T·ÕÆÊÌü àLÙ˜C«"þ¦æ[¹9 âJÂ\“¤s袌hl¾é–wÿVyÔ]`HºsçÖ¿>ºCQP¬ÌsXÜëì£G6¼3$}E7VS)•DüèÙôúð\Ç— LËÎüÍt]ÈŽE‡`Ɇr8ò„9Nlj/rµRèݬðªëI”Úú„oA|”bÜÿfýØ&ÀVà)a øu·˜È/9é\)HYŒÃ"ËÛÃpEIptNµu]jE,Œö”h7–‚ÍÞ5Fª%ôvÓ=Ç5·5¥!¤Æà—wUˆ£dî?mUBÛB–~lÁt=ÐÒjò¡’”¿ ¹þ£Ôîç&^šdmßDã@›7e]‰Ò¡}”<×K˜l/-íܤ½LH°°+(º¡uR} äÂØÈ+Xz1Lº¼#—ãø1àâvÄP2Œ … ¦C¨ýþ¡ÖxÅ{É(:~ìý¯˜xšNºdÄý‹Z’()“û ú1º^v£jH@Å÷ù%ÔkÈy;Ž rVXQJQ¸ð47Xák:³iHÔ·Ž 5˜˜ˆÜt“ቌ¯yåñ ¦4¦Å£X._\¸§Ò}æÏæ9‚rÃA¡Â3Äbp…ž³ [?VÝ›·káàñ”?é:vs³ –ù—À•A†• Âÿ0¹$’”Ë­ NÅlßbb¤l1¢?í%!´I…ˆfTt/XiCd‰k BVH€²‚)Pw ˆ‚PNH¥ÿÌÚ'_=u‰V=RÐó"u*R( ÔŽ9Œ¹†H‘íЛ(i{I>…Åbo_C¾ËEàDê…æƒzïu¢wÛÞ'pñŒ¤CrœiФr£ .õ¢k–fì6Û ¥-EØÃª”«`Ý™Z¢I„Æ ²á%…,Y©Š¢L#Tfœm1µÝdÊÎ0[¹ºð"¤k Ûì$À˜xÂÌû´[æaí] hCÉqÜyÐz¿æiÒ9!àø7ÁŒ‚|¥}9¶j5­°NÈ<žaÙþ›>õšñ1]ܼƒB‹,׿Y *‹Y‰ ¤ï»Êµ_;­c ò&œÌaXb„‚:ÌÖa·‰økiïºç³Ð<“Êl‚j[ÙaCJ”ÉtŠh@Q3xp2!:Ù ÒÈ‚¬ƒB5ªçE‡0JD@hhL˜ D´eŠ”¦Ø“),ØîÃ'Õ“ì_¿£šsKR”¬11RÖbÔÂS$8c¥Ò’“ ëÁÃd~Ä•]mÔRh)qÝÒП®¶µDÔÉÙ]«JGF—7RÉ!E ëíÓQ2RbÙbÊ'·BjFÊazë¢soi¾ùc,K[=ª@j“"6‘ ì|}ƽF=ºü 5¤ûtp’|Wéþ ØâéQ7¤}¾f<ûtzT«ò¬DÁ{$Õï3 ¯u2B†‡#Ô>TWS„f³‚¿ó3léŽC}Xì±å!åQ©Ù´‘©N‡'„îåºqmN%å“‚½l»Ü æ ñðsxE"Á2E\ƶÛùªS ±`Á2+†B¨È‚0<|<71n0ƒIˆÜ†˜lѦ„–JèV©ÓÑu÷Ý}ßgojíBÞ§v•Šf8hPÒàÌÐA¨‚!Á`KIÁ´_¦G„p9`㛇ho·íùƒc5BÃVŒÑ@” Aó‹€ÙE¤C!›xA3$`ÐHþ“Úl¼Îþ+qw:(¶›•¡DA(]Õ¬ÝB 5£–Ô_ÉvÝÑž¦Àì܆@Ò°KA†8¯RšŒd“æù1é…^#’`Dí¼¶Nç…Ö“÷½]ÞW¡8‡á¹Ò!ÒWAÙã­ö#à^§õÿvÿ£°ÚqˆŸ’ªX¬)àŸ¼cÝ÷âïýþ{æ§+¢‡<§¿ÿW³bL¦¡ÏÐŒh«ÿúêíø¬*= ÍÔ®Çþÿú¾ÈÌ(¿Oñ„qy”¡Kv@poÏè£ù³B˜:qÁκ¿ì¶ÁŠËWã–?-úh>†áÿgžaôÁDÜ€v£F4lz¥÷ܲ±>kÙ¯\Þ~ŒŠƒ »‚:fRža ¶Éš*»õVL°„~Ƥ”,Œ8êµýsçÑì:E¥…TÄø1æfA9óΉÙK½¬¤5qÊpgc<¯*Ò¼’¤ª×ÛÑ–ªÆ"Œÿ…9“ÇFŽˆU§këöF¢‘ß]»*ª…:,†Tв÷Î;eTÕN5iÇi-d• ÌðÐDÜÜûñY²¡Íì1Ïuí]»2dçL£Õȹ¤–¦“5û±Â;¦•J‹µÙ´†ç_æLA´d[×L‘`èf°¡«ºKSUp:Q¦º ØëѤª„7*¼œV–,-+ƒHdSñ,"«i”“±£¦@jökúÔälã§ÇMOªo;cʪ￟;уý¹òÿ*Ñ?_WÊ$vÞ@—ocïv5¯§ )¡§bMå‰\£-¹bh”¿®˜®ÅÑUÝ£³ŒÊ¶Óüÿ·D~:ÞüÞÿMN2\ÇVù¨e†.,¿ç<~w—‹µ­'å³—6¼Ç÷9¹éXñ7SÛ¡¸;†$(Zk R6fE÷Å´»KŸ®V䮣Þ×&ý‚Çü¼YGß”=“ä"ão”âàøN›ç·×ü²c¶µÖØ—ó™i…Æ¡¿¬‚–Ó¢#q:!NGê*pÔQ“Óu°DF±ãÎ~¿Ýpf*šªZ‰XÇ[ºŠýB¥ÿŠÞO-M¤(5—˜v‚èÁömCƒÞ0£ù pÿ½Ð~S!ØÙx‘Žc·C’†Oô\âÓOäÐý‹ãV0{qN€ôÏt’ÆÊªdt磓&ePÉØé˜RXæiZåI7K ªo=aÑÝÈ› „yåÇÑÐßÝ·ÑÅ^DBÒQø`ïÑŸü?ûG@YÈИKÿõζ¸;*çÈÔ5<Þ™”a&d%ú–¥ö=$Á®ûñ´Úÿ{ó'í¢q8’5ÞŽZ›—«Ò?¢ g.iñHþ*yÌ^;\xû6w•ýF¶§0:ŽüW`ÿIgé¿æÎcN`ƒà*_±;5½"¨„˜ºÞ®øCm“‹– Uª{÷^ïÐèçM]6ÝùGµP»˜Ó‹1£S4! # 72µ‡%ªFLkÊ-üýqÿ-*EWÖ@)󪥃QÐHg¡ë·×uY¿§÷j6jÔrŸìôųú¤5èýÓo¿»®¿%ßÓŒ›ßrðqWÝ|ÇØçDaª‡“j½õ\ÑûvÓ^=™T§ñp³³ïøtt“JªÊ,$àÀÌ»ìºèª6j×™\]ʤsÑœG/i§óƒ‚¾Nàý4Ž#ü”Ÿ‚&wRúçŸÜÎ&O nœy¹}÷i­üèÿÇÿßäÿï´9Ù§ô±2ÈøÔñ7ÑÚþmhÞ2?)xLöH„K[éîÖ3ÐAhÚüåÏVú‡†¸·‡èø¤ÑG‹Â(óH4ÊÔÆð ;™À.DŸ'Gëv±Ìk‡}Þ U1Mêš@ø³Ó¤&é­PÙß]lýþLš½¸jW;ÔÇ÷ÔЊëÒ{Ý$éá±ÇϤØ8ÑÛì`<Ò&¤1’ø~p¨qÂùîÇÒlÅ®Tñ™v ²êvÁ?¶;ŸtæÓÉ£\¾ŠÑD/¼xÍà!}ãqñÚ© Á8ý‹é‰A&÷ŸvXưéü}}ÍeêòEOG;ý ‰Ç`A*¯¦sdÁß#{#Åa³Ï9¶Ò=\9¶#ìã5ïGM@6°vEväÓPêX9îý§eå•ÉšaQXžÊ­;‘´†qšÏu +¡:‹ãáz‰2᪥س#š¸Ë¡~îÙ$C ¡ÈfF¥ˆ`MI&@ÉEÎy/سþ·çϹ¡ÿ%ü¿^‹k“÷ÛEë)UÓf“¼YS¢0)ÿÍ®oéèÖ•C3i¯(DO©ù¸/, )™ö¼ÛMÓém?tù£e§ú펧æË_ñŽ‹¹+%®ÏÎ?l?·ö‘WÊs¿„í¦Î$#¯êã^íÒcOiDøSqG³Í^Ý‘Â_ñ8®ß¯v{}‹C~½@i„º1Ü~›‘ DB@c´0„0Ïš{Üðär=G+‘Øäm¤á&Æ@€àín·-®Gcsò&*`Æ`R”•EäŸå2xA­†Œt¶¥#Qû‚߯ÜÁÖÌ?Käèìlh° h#& °ïÅSÂÑ OòyHÒªÆËU¤È—É÷Þ±ˆË *ªl«,+;˳f Óâ7 ‘Ïfl5Å^|)ƒÜÝüb°ZŠy³ ˜•pà óV7à u›!½J²ÔË0òÿ‡.,ðªïUO…ß®tqÅUUÏ<&üçŒG|ã€b¹M••ÑÁÏÈ&e&0€£ƒ È›°˜˜ÅP1Œ0Þ(ho±ŽË+ƒŒíÈ2tÖêfŠ %žèHU d$?>,=‹¿C±ü!æÑYì>$ˆlSÿu[Röy÷Y§ÓïúÍZÆ:wca޽ý´]u ”ÝØ·Œ2–טî뤲™<9ü,‡+VQmzkŠ6ß}™ÚÞf;™H=>Âýz›ÝÓHUøÂ¨Wëk ïWÛÉ}úOyG/¦úÏ }Ôo‰¹¯yÛk6Â{½ÙG͠ҨߘKÌzaª{N]™sùG¿®½›û:¨í¸ü|×uÄɘržFƒG–‚Œ=æÊM›¾¤Ýl<¨èÜôg?©¦kuT;Ò[ì_Eðé€ÿ„Lü ‡w|·ûëhCüd†oãü}(£íº,+Œf$¯^-õ>¾îAWRæÛÙî/7ŒE¤ã²e#Ä÷O3¨ø‹}ÞOn˜sú'§\yùxÇÑ9±†\Û¦ø‘œk” ÚîªíK•—ù+=7ëõólËÍÂG«J0²óaä·“[^ù{è$xYÛÎWXõsGFÅ~Ï»¾ ö+¨ž:7húv{Nƒ§ì‚Óþàg³fžÜ7s„uièÃé<žš–]vi»ûz ~µ·Ë²Sæ,ÿ,pÅ´[¼2u£ƒ Ða7d Nñæ‹4CìŽ[þMv\Û·ç³AO#>©dÕ—éZ¤go6˜½~o†>z§ Ò†-nÃC#UÜñ¿NÝQëìÅ™±æ¿KÃÛøf+wŸoߦ'»\uËç&8lÓÍ»…_®^íÞ'fªÿ‰9„6yº?+¡ž¨7MKÛÇÈD¹ fdyXNÓ†lî,¦ûþ÷“êoÊ›á˜$ª9Q²«Oᣮ-?¶Þ×%'P”¥˜f•…Ë<>ˆY“é×iÚ@±OwºÂ’íýr)3ñĶê|¡¼ü½g¿lü'ÕFN¹5£ª!­Ÿb6ˆþºŠhÆç¾¸LÍ€¾Úèõx›dˆüã2£Ù͟Ńð™†LÆ ÞRÆ`ôª`À¦+quó}ÿi¾þ‘vèE ƒ«›§ÂëQ½" nHòå˜8嫽þë­O‚§œÝ’K{êòÒš­ÛQ¥ªÖµsbÔiåÈ…šeVs/òÎ3Br²ÔÁQR95/51;ykzÖI$0 $ë8œkSªÁ¬ÅÖ«Z¬šwF5­\L<"óŒê^%Þ³œË½QT«ZÆÇœg9Ä3—g†˜4˜5¼#Ùm@q±ÍFë©²ÒÆÙS{e}5¬'RðR%I2¤ä¼ÜE3§yãjšÔÎfêâ`»©&gx1kP,ÎâU2cáëÚN0Âáÿ¥mnöï65‚d8˜¤$À&(K™—0Å‚UKU)lÏ,ëÖ&tU¾ýoS1̘å"ZGn×­Ì,"fff—Xˆ«xźR¢“ĨµkXþIŸO¥¬Ãî5·Ý"c375Œå¥“eì{|Uâ&f#*Ö²–5j3‰¦kùùÆùâs¿È´*žÌd°A‚Œ³X Cƒ˜aÁ¼Ñ´&R”1cGZw1eš7Q[°8M¢æo«,pÙeÆÑÆÞ×Ë_æ«üïAÔxNŸ·j¢¥É¼î:â2Tôj=~Êz5ÿODj–Ýôö˜{Í•–ã6f««ÒY&“ª-գˮ–§&‹.sÑlˆz¦_s7’FýoTòÓPŒx¸„qã“RÇ¢ìútp½òeõwlÐ@Ý?£fÖµ²÷ÜìGœåðni‘ß•þ±ñé躮r¿‰VâZ n ¾ê>Zh¬êøÌïë²¶­þçü¯‚ú|4Ê´5Œ0zìnîxôËÛËÖiTYg`5c2?‡ ØÉÖK‰¸dú¤PËÐb!™ïòíäoÓ‡ÇîtQÕõ?sÔ{Þâ#—2÷ú8w¡ÒöG·Ö.=<ý´îggoÓ¦Ú"Í)ê9Ú{4C°Úð»ô>I¬¶ÅLi³qÆÆ{X¬ï'WWWlZ•@øX´` W Ðñ€ó íú_9žg« û.-m~]Z@ùk€Þ<#BàE±ÍþŒ}«ê¶úª]¼âúÃvÆÝ<'²6ß?ÐÖ‡¢»6Gt;nz¯aüÕì×È‘]Ñú¾ˆq¨rÏV›0ú½5§ÍÉÉ>CM ¡öû~]e‚¥Ê,ö[ªΟÂèFvu¹ÛuE´tú ´½œ˜ò{»Þ¬(ªWcóüIåŠÕ¥éãP_CiÙ8»,K ©êÊžvät<ê4OÝñôY|£ ƒ¾W6º8Q@êv`Óæ1¯ž2ºÊ:ûz-·èT]¤…4ÐnU÷ÝÛ‡×Ew{ô4£+nŸD3êàúwåô»ßÒÒ­;´tiÕ‡»N0æªÖáku¹¿Ÿ|rƒyª»£ a+ô5“ÔÞªÈ5{9Ç ø~£´* Djfnå­ˆ;a†Ú¶Ñ`Û_euËËU—YdU¬×cagfîNVÉ‚ÏdÉÝŒø@ò¸òÙR8"HêFÌ­Ò°nfÕqÏñß.¤˜Ð(Øa°¦z*<º QuXÇ3UYמYìê³kòÐfQm¾qóÇ_£ý»,ß¼¤þuò¶Ýf>zTñ禿TŒ³·¶Õîñšn‰Àøów[¯ ?]0³q™ÕNí«=”h`j=MqCSÉܶ¼Õ ouU”‰ôi…ºÏU¤‹0 8_G¥+6U¢Ö–] ú2Ñ.Á=6GU%anÍÇ´®#QF6è¯|ÎFFaXÌš§ÇFnÄ–ôF0æ#)KÖV=Tjž¾ÌøhåYa3xv‡>ÐútžŒnråmZ¶{ŒÎWÓ«ãáêêw¸õ•S¤Áx´(íª7žš På:«¯ÝÕgWnvTw}лg„3^}i)Ã"µ.3Õk¹_šš¼l:›ÊUDú*]nÏ ;'6òtsû°ÓªãÒv7Ôî|ãuV¯†MK·É¡×ßvÔU…>¨lh­çáŒ8å¦âÛ‰…ÍlnƒiÁŠ6ÕÌ33®e÷,W§âz¿uI”3€¹Üù¹¹Ýu·¡~Æð¨rÓpwmÓéÜy6¦!1„G¯Q²ŽáO]³èóKyãß:+}m‚õvò펺¨‡{wš¸ù²ßËêÞÿ¡­!f‘kìŽK¬ßæúáÙç«¥àÜÃrí[ô\Z£ç¨ uŒ9‚[~§‘áãç`õ²e@Œºž¨=ºy ¬oý ¯îÃöðŸ¦ÌqØ3Øó©ú†44öBÓÓ '.;³šZˆizüi~jÍÅÓ\yÆÁ¹´¹1±V‚èÄBÂWïnÓVB­²ìk”Ѱ¢U%))IIeRTªlJPQiKƒ 2–¤ÖJºdTP𪢲55hèÌaH«ÅéÝ˪¸b¦ r`…ä *Ábþ !Fé­ J†6TÙ²kÅIŠ*¬™K†LS2Û¿.›ì­Ñ\˜˜†œhg7,MÔa¡†±”¸Tw% j­Áæ7pfUm®[RÊ$(Á4lbKa*%¤Ú!eÔÛQ¦Î릆 ZíhÔ`uéìï äÛÔcÝ“p]Üw<83kQ¬²çFJ°¢T¢RRTÑ$£Yädh²ìǸé°è‹£Q7ÈžÃ*â‘®ÎûÒ›c14¬ž$çØ}r­fÃÍ ¢˜C›«®Éu {ÊÃô‰ úTÿ²Ú2%?^`¤Fï Ì3+fâA˜)kû$Ê%Z¡@†–€¢©‰rÂD‰‚e)JT¡ hŠ„‰¥‰–Hf$‚¦"hI’H*P ‰i(¥ZQ¨• V¦”(W•re‚eQÈ D %ÔbJ$k‰S@¤ÁJ¸’†M%!1TµBÌ (8ŸùXI®îšzõéÙÿZ Xµ=BÎ,Id @B„Ò"ñíàäØªpDp’hˆÅTà"„ÄŸ¥ïöú>îrÞÆ(ðõèGÏR~fV*oX‚üb$f …½€_OúëØ1Žïbr±h½Ûäßµ~ø7ăö*$‰¹R')Ã$Ai<¨£ì‡—çóàœÝN¸tÃ:G”ƒ<ÔÈaGßîk"¸ô=‡ƒÚN„…CÐ O>¤?yßäãîèû¡âM¬T JQ«$ @ h(P’‰J@¹(Rjk'$2…u(eVXd¨ÈÔ!FIÒ¦³”’r2†— Lý#§oG› +0ý<*]”/¶«ÜŒs" ¦3ISà!ÐyÙ§êÏAº‡ýnJmÑëO4{†¸LÓ* $8g¶Œo!AeE†Û«hA·nÀ7õšñü@ù*Pü˜T,LUeS3H•X†„„„.^?Æ,Dš9Éáê¹’Ÿ<˜ÏLÍÆ·Ófføe¼„Æ[ÚF§Ò,šXÒ¡,»poÆrs.ÎK"lJ™D¤­v|¸o=§·9‚q”••I„À\K ”ˆî*Gòš7ƒC0\%i»l'ƒöª«*ÑÈ4Å+KŒd²Q)0šL4M ¤e2ï† ÔÅÌ„!Ð0¸ØÕÅa7ÊÎAʦ¥6&ËLjéÊ3Zt&‰XMýVlJM‰±1ŽXûUeß dÜÒQ‰UR˜¥)TRŠ)HÃû ³5J ·˜3F¡˜A”†ž›I[Þ8¤Ù[]Z4«¶Ú „`‹D Ó ÷¡®ûT³J¦¡å:J¤ŠO! IG킾L "†,Å´;Öåp4xLæj¨ÅI ´ôŒ±Êì{픯4Þ¸àÙá-z‹n‹V>±ñI¢×ë§ÔÁóÎÉ€þk-ú~î»}<²O|eå4MJE%&±)”šI¦”ši†D˜&‰¢SBa4L&‰¢a4MATši 1$®s™0ÂZ¶¢ÃΦí%iáž7Œg8EE¥<Ø™ ¥Qb±Ï‚yÑ7³F• (SBQ…:``Y¢˜a'!)¼¦ÆÆÄ6šmFÆMNOM¶{S€(nŠÅF*B J4f4a©S4Æ‘¥Zc¢S‰9NëÔÚ7R˜lg0Ä&a ÞTõ l¸MñƒÌ'£K!‡SDÂ×Û’o\Ûq·,7ª1(0ê¼i1aî‘k£"˜°ÇÏŽTC-âãAmí?ù:‚Ë• Oÿz>îÇ1ŒP|€È5:Ì>¡0.®C‚cµ?âùñÍF“öþá# Š#B(¢5Ò¼kØÜGˆŒ¡QEJ#a¡ÈI(ÐF„PŽb(„hF¡dlÖ0#aE‚(^ž}Çg!ÈFЊ"Ј#🕙0p ŸÏø{í|cökO^€Â)ìŸF›­…âÌN™=sï¶LMšSdXÀŠ7¡î6­ÝÍ·“¼Ö&¢ËÈ È\ÉfbuD`dÀ¼ýÒú8ÿö¸áu!%þîP4œ¿×Ë»ÜTtay;sO k­ä"ˆ´G!”G!}z„k>?NξÊW¢ßXû,½/¢¼E¢—Þ½ð‡Å#lÅÞ3Ë}ž«èã.6ñåèŽþˆÜùEQQAAuºož€îÒŠ­œ1š @c0ãJšL$ýûÎþ° Æšæï†öpð5§¢îlJ,:#ˆÐÊv8ÃG»P~ zx› G9Ö*õãž:ž|qÛ‘á¢;å(E¢7ØFÂ,Ö¹o+;,i¡È‡ ¡E:éÓG-z´ë,Ìju™"%Êe`0š†Î0TÐiÜ6¨¹Îå »¶ Šç§´#./q àÜšhëü¤¼]“ªüq,nøFø12ALÈßèÓžmú?»Ë7äTàÅу×$ƒó.–Ã|@paiÖÜqÀ„n#AžÞ‘Ço¨ãˆŽ0#§6åÑ ¬“)-ßÃd™dG}zØG@ŽB0G“—]îã9ˆ×1B8åw°ŽB4#zàFtß{Ê’7ꀱ…Scׄ{ÿ}åGì!çHÔ•r2rèw²î∟÷…ñ§ªÊ¬þXýgßÏëZzmÀ¿!Ò*; ÷RÔ-¤Iye ¬@AŒ¢foÙ#é~"y”ä¥<ô ÖAJàß¿&hXbàÓ¿#ÍÎBŠL΃†VY•^<û•TŒÛ®ílm²À¢©»Í~Ü™w9…/Ê`œ¸ÇÛëIrt¾,Ö§Y‚¢Z©2-8–þq'=G-M•$ªáLT´²…—LiŽ‚@@˜¥žqD”ö¹™.ÃJšI âƒÐöJŒ¸Ú]ɼ;ÅQr÷+&^:-‹préúA$P™‰ãÅÊ)52¡çe1 †¸mEïÙ7k3a4ö|šµÜÑß)&‡EáÁ‚ZNrÔTÁ3Œ&B-lËž‡fš˜N•‚<šùr?²¼þí´sP"®gf8—9ÄAý^]þS‰ß?_Íþ\¬ßÑ&HHMmæÌk u|}âoÚ#×dCï=8`õÈ!ÖæjÆwóOgv“3Èû1ÛjúDë¹—¥B‡%5*v•–˜ Jä>¶r Q)ç)²(5!—²íŒ¹„u RÑòA’IÚN˜ aõCi-)¹&U#8Æcl¬é›àˆÑF‰I ðåž\G;ªÌ]%võûþs½l•ŽÒl“9(v±Ý¨Àü²9Ë÷ól¼m2:ß(üÃŒöŒm2 ¾™žÕ;¾ÔXq<õÿJ1¯kô×W¿¸(ýQüüõï‡îEõÒÌt<.Ê6êá¾Û«æCt»ÄÝCA#Åÿ3>ˆÞÊ€÷'oíÆ]Ÿ…öàÁd‡àÒ:zdtHícaßk«²t¤æþtÐT1Ȋ±á*~šº5Ä£T9@æ»b<™Êù$Å…?D+¢*…ï„rúd0€9ý[Д€ÌšÇ"¡gü.’C² ˜%~ŠõeÑÏ/&uW9ž­³›eÆ+O!Í·<Îܺ#-;ãŒßÍ_-¯,ß»÷Ÿ•÷·«û]\ŒiÕ–®‰Ñ›plÞ£ÝB¸2¢ÎýS«O,4K½ÝáÓ„ÌjÜüK é·¦ÝCÏ8;F:ºíâÜÙi®˜ðœqµókÙ¡{á/$‹çQGepãla6¿›}Æë(¡°®8˜Oûðüi³V ¬á*-‰\:>2ñtƱ Žõå5éO®ú3^‹ÓÏ_®óæüÜâß9£„¥.ý·A>ª¶¾ s“„%t-ì¾Î­u×¥µ{¡asWP±â»î{>ñçëŸd:Bø¹ýݾ¨úâ°t…ÛË樚¾?Nc×Û‰í¶ø,Zæ1†‚póû_¥éuçYï/_ /[¾/uø¢¹qâçS]qü3á”§v§º·5¶Ò±õ .:tÇ¿F¶b’-‘d2ñßÙG—|ézîêìzYµñðÛ1¸@¹îÚäî›õ͸O§Ã•N}VK„m6;*³§¢›a¡¸¶sŸ¬¦î-6߿òþ¬^‹›.üÒA Úÿ^­™¯D|#ÏÇeøÌñßÝD6ánë4še|>©Õ¿x©|ñ‰9wÓ«‰á£?½_ÛíÃxÂR/Õïó+1T°©+]2Ÿ’[£è‰ŽR'²¦®†BÖ‹ê•+ÍÇcUÜÒ»®4ÙU,Þ,í–ø3Ì•kaD-Ñ‹xÓ•<ú4–Ñ* >4”˩ɱ&s“7o‰U0¦rm¾¦ÑæÝÆ™7,hxÝÓ¢PZVÔüúÚˆ@Õh‡<§¸°ñ\Ì W­Àö} ˜'kIX(}«W¸Û÷Íeqs!R}è–¢"|ø¨K†‚ùÆ6wižóëúðãD{!ÆíìréÁÍÜ÷ú8C¶×XL}ì½,!Ù˜Ès a'Ÿâ‡rhøcÔŸSÀth°UýÔm—0BZ¯v´pÊo)XSˆ0£ŒB”¤)i JR„ )iqAIK@Ð4­'ê2^ó©an]Á¹ O†JMí¹m’ѽ†õ  ê•0€Ü)—…á:ƒˆiu'fpÃrš†Ž$:•à€˜f÷Èx0e6IE‘60b¼Ôæ1·VŠ23.8Øì²!N<ó OÊæoÂ'w×HzŠö¢%õ(½qb[ †?„QL¹(h¡ÔªÙ†§ÂGGU•.͵u©yd¥_€öDœ²bâ¾?oF•±Ú0¢rª»I(Hçææ«ÍM%ôY¿=Xú)ßcwl6p¸ËeýVŸn­#R(#n˜n5ÜïÈÊššª^w„éµKW;¨TÇyE”Ð*+hS•&ˆï¯YCbýLn*øtÐqZíÂ0ÌtIïÕ/³A‹Q¤ÛYõDëÃH{c¬1Âs “tç¹4‰eªž©¼’ÆïÑîªÊ‰#§éè€ÇŒ´œå7ŒüÍ®Õ)×^¶¦9jT4¬5%ÒSâ6Mƒ{]±ëeEr½W}"ãÝ ‚ÙÛW?TKašM;Ú`Å­°ûHÓJ¹ô4O$ª×C‡˜¸è8W/ír³auݾ7ü¤W¶¢úuÅ­å 0þ촗ȸ5ó^j ¦× T«)¨1 öQà†WèXÒÕUF‡ß 0ÇD°¢—ûiv*_kÙÆäÐl¼‘zÎ{íl&B}Q+º0@Ì]XÏï·«†©Ô2¡¥_D 3„4ű¨·'œª8î½aë±ï;ß³Àéñž4Éd£‘YgD¹ÓESÛÿ=ž›¥ÚÚ@r¬.¶<“ØúµôLžZ?÷周:ЫmWr5,ilI\VÞ³ÚAyÃô~ŸA¦ÛM·îßÁ{~8,‰~¦‚7”ð~Rú Bp¢{÷œ´:ÙW÷óD­ i¼×ôû/Fžœ;IH¡¶œ;- ¦1ΜÛË wZ19ýƒ6ŽáÝ9,¯òKuqãw –ž©n¦rÐr)“_L¶=é—¤ðá ú 7X‘ƒß²›èTóŠ)ñ$ìXºŽí´Q×Е셌pÛ¤îõ™ê¬7¤ì‡¦ó.û·ôsØÕý=Ý5˜&}vFX<»*‘3(Np:cÛ-M {©!kpßmÚU0jý\$oÚ#ÉaF­ ‘¥T I…Ñ2ncNf±^•Ϭ¦Üçqí@jµÐX¬_¦4[$)ÆiÛdLF´hŠtì5–ͨ©&21×|~dxÂï»ìái²TëKæ3êFpÓʯ¾¶ÕaÕa»»]gŽ“egš9c"å2ŠjßîON4Í58÷CMÕâŠ6È+Ðïç—Ûú´S9¶HÓ§eêÍDDWH]ÇêòÅe›ûM1ß:¥®ÙÙÔXs‘§Ø•Ô+ä.x•7”ïÏ0š·º’®ø¯ž8Á´ællçÖ©$VщȹX¤L/ñÍû%»eâ+e:«(Ž‚ÖŠƒMzQé ‘L¥¼Û³}.5– Òøx× ŒxöŸ*RÆøþ•®8­àôrÞ| Ï®´}ŽÃì·ž÷–s9óÖ¼«™•jôDþÌlýzöy1ZÊto¬ã;yùèÑ%²}{yW²ë6¯1¼$T¬Çp~¦<³é)£„f ª³N3¥PñôgœâÔUìï.ù_6óÁ¼ºßÈ»£¢ú¤±:Oº’÷pÕ¶ßÓ¬;lyýn?žpðíÔieèºg~žÝ‡mþ´t^Œ²ßõ}Ë´ ¦Ÿùµáy²êa»£«é= ¹ÂµíyAÙƒ¶K })^yT×S+f¶ªJ!K L ¨SƒGZß¾`]ׯ Á‘ÎDt‹–ôïFu~`gj<à“Ÿz_ïʳQšrÁRú”"@v5/Çw›„–¡¤=ã„?ØHh;di hPQ­à9.NI8@)¶StB±<œJ5Šè"€ÒBrŸŽr]nX°{hÀ†|ò=º+«GÉ ÕúÍTÚ%É*’Š¢øŽŸ§…$5"(¤R”C+Ú8ϵy*ú`ÈŒ6V34ïÒÜPTÿQ¼ëèä÷5ªé8ÐÅ©qÔ9 ¼äÖ@ðL ÀkQE>Ù<¤|~ú*¿|Œcy=O}ý>Nx6m6 ¬‘kh]ø”lƒáÃÕß“QôÚÃ1ºox•¸M2Ô4¼³ÙÅ“ßñû( 3¤¤¸…Ö¶‚!¶‘êï$ŒZkÏÒ=a¶–š²0ÉS'ßñµ=Ž´ž9¹;+S¦q€V¡tígWšµ%dFVE Ù Ò7gµ‹6ãt·X妌bÝ‘ç©Tš…ï ËÛ1 0É¢lô éâô£U5š-Uþ˜Ý")Þ.¤Ê¤‰ÅÄ'¥ÐWLa%ZôÝMPßõ{ÎÓ#8dùδwèèaé{S^#7ñQ8¼¡]Œ2Àõæb4d>]ŒhØÖ“cM`ãBdXHYòÔüÿvì’Õ…ÊJ±‡ÍuZX<Ûá7˜ÝÍXéµo÷οK>˜s¾‚¡Û‚š“PœC‘ˆL:fü>Òá,ý‘¼'×®Öd‹ˆxŽ,UJ]&oîô÷ü”óN¶«ï{‚.á®÷(Ç Œ­ÄÃÛžŽõ 16*öÅžu>1ª`qª¨“ ùäŒë‹Du;Žqòü>Â6ê÷Žü·…°Âr ïb¢ÄX­ÜPðC»/¤›øfðµbã#Kg ‰¸RÝÌóÍ–âÖã!4ÓæSPšÊS8ˆ4yyõŸtfWÃÓïE#“I¸|_SX¾ÒÖÆy^Û›nKË/ dUëK—Fѧ=ç<™ns†ÑÑ®8NžâòÕxKôüÖ£l˜œÈ¦ƒx"Ø»°–rîÆÅ;¶qB±qYPܼ,™m %3¶i§ˆIÆ? móÇD‚sLš¦:”&¢BTšÕTû;öÐFgYþáù×êæƒî°Óo`O‚Çt¼säœùþPôæVô|㤇•·ŸGÕê8ñרøPµ÷"F&¹|’àpq™;6lì¡ Ó›2ßëþ×&Й!xv$‡cÉ)QënS&b0œY ìF.¹X¦Mï—Ðy<Ì·úÉëçù{T t€§¤¹l"‹7æ3³.f ¿>Æ ü$º6°ØM¸ŒÅ‡è0}" $«U¼[¡ˆòtƒˆËÐăqœ„ƒJÐÜW<o¦†ßž `Ì^ûçËhÇ3µ~|í.õøèøHñ§mélV hò (£§ !¿CÔÈvúÆïÇŽ N0ÅÆw]Èü¸Fªšˆ„n¸Æ{ŽQ²š‰Ä=þsÊŽõi·°*7s/–ÐÏP™öl€h`úXh]ìywÅCÛÓžp¤cöußB¡q]Ìy)Ö{‰žƒ€´š˜ø‡Ø»BK»îŠ7œo›A}<¬3žëY“A0æÁû„—ÛxiÒ)VÛoŽËôy+ {F“äV•Ý9—F½Žf.BˆaÍBîˆHê<æ>ݹ|'Ïéæ"Ê 7˜6ð/$-¤RÍÞο°©ÝL §aósR+惊ºéðç§’.FÃÐiPɽæº`Œ0€Œ©FѾ>'>Ó0þBCBCCÔh”ãR¥®±ƒ:RX˜ŽEbOPІ_Œé {T‡ØKd”³AíÞ¼šs8®ÛM8ÜœUˆè+æøö”¹ãÓÀ£ 4À>æ4*6iDÆ7sAû­}£aë8½…8A58TE/+–F“‘âX¬»§¤Áec¥c¼‡œv^Â^qF@jìÒ×–Wž Ó­72—š\Ä4óbŒRÖáV]ôÓÑÌ(ÞˆAVzöÝ«V®\¾o=+³jMáß·@ú£Nšƒæxìç«Ì¶6l¥sÚwxgÜŽnoN«¿¹w¯‚ 1¤ZE¤ZEÖ)ó AgGàÎ6¾hv®—//%.eY¿xõ8f®<Й²Ž»Ä¤L˜°ãx}žº³TŠÛÜ2f­‡`S²{äI†LÚ8N18ÈT~œù¸S©0cåd£êC’Ló£³Èޱ2êLT%%Ú ·ô®¸kï=:QÇJɌӉʷê“#l‚¦[ÈS ˧<|ãó`{ñÙ0æ.pG5ÑEäÁGô3vÛ%TG^ÉCÍÐcò÷œòºt#ƒvDpšgª[Yñû¿ÃÓF¾¶=8X•IºSðû5šÑÛ"täoŒŒŠJÐ5j@;U–o5éô¿ ê.iPâè:#†CPà\ö(ø0}šèE˜} ¨Œ¹å#²,ü>Unm¥MóåHGP¤„¶¨É„C%Ò Ò}(P’¦$@¢$j¥d'L Á¤ÌÌv@ÅÉãtÙmŒ×÷æ5­ÅêÈh8û.ÊTiîîñ7xûX€xtyÃ{¨n«lêÒÓE’èå#Èß<÷ã8Òì‰×«Æm$bÉ€&ÒB>?lå÷6߬Ï9J@ 6L°˜„Às˜ä;¦…¢e>#§¹8½9tŒWsŽSý÷Áþçú_çcÆ1~ý ƒ°ÿ$´µ  ³!¨ÿ² $!žTG?ïíÁ$Ñ‹îܰ0c”?Êkq=ÕI’@4†i&ÏOš ¦M-ò,‘è²{íŠ(Ä54ûI0HX¸!̆#ýaàhÇýä®=´’“NUé‰ÿ¢èŽBÄŽ C ‘¦Ð/ø„GE?eŒZNh¨FZîK$ÿÚ:ëþ;ü šõ‹æ>t}B07kzƒr®¬/MhÅvAERÄ­"Â}ßí×”ô^NÓ’Ä0Ô0¯?øý#iŠ“…%rÝÆ‡§ÑT'VÓC~(n_ˆôš>ûÉ·Fþ¢€ Àñaˆþ8Œ)õÙÕ ?¿Ã!“· úýúÔq(O—±ôJG¡"0 ‰Yú/(`˜0ºäÐêI ŠBbRe:Ö{­Ñ~5Ï“:ô/;ç9ïÍdu’~‘@ŠæÎ?›õØFÂIDs<Úœ]Õd›jsôùf·Â9¡DQE‚0EDp#cgËQ;zlÈG(Œ‚9Ðíð°F`Ø#vNOÈÝþoÆž üéÉ7N§”²í2¢‹…‰wÔU,BuŠvdõÚœp0Ur«0§8”KÅÀCjËkT[F½ ¥°tn\жê¶E*“-Ƴnª°·hX«¤'F @¡D‹éÿoÒ³©‚ÀÂq‘*»>¦hzë>³c‰­1{‚¥¡íü``É’ûŠ$ÅåbD,Ü™W hBßÚhoZtúxI§y¢cïø7$uaχQ-µ¼:D0ìÄG´MÓ”ˆåÆÊÈeÙ=Ž™ò6ôutä”§df±ãÙ­ìÅ6Êa³®TÇŠvH#Eâì•)r%¥!¦3sX•c—Zçô=HøÉ8rïŽ‚ØÆmž R(„š!#-²„MhF ÆÊ)7Q¡U£Nð¾k+MT3h‹p˜QŒvR :“v””ЧÑÑmÑ£Ý7õ“áêôàÛ ¶Z1G^ Q‚‘®%û_#Y°j#®H;¼²uß×ü#Ý=ït›pžB/1ÄT#ÈÁ#P+â44š]¼Í:¦=!M‚¨;ë²W´íÓÈîr±åI‚6]>=þ½¦U}ϧ\Âö‘ Y»D[2ˆbh0j1[­ %U鯂@·6Z… ZÅh¶‹€¶B¶¸d„L޽ 5¶a£*í´1&l¹Ï&¼ìñÄ**Úçûƒ“Oú­Ç§÷þŠÓÉTÌq‰÷ÿ?êÑ×k±—`Ù*N‰û%-~ÿdoÇâðkü/ýH ×1Ôu¸dãk˜,“30™½ž˜¬jS û¥cÞˆB‚ƒ{Æ£øùÕ”“Øaþ¹ø%H~¡/e‹ìJAú…hšýÁÜ+Ò×PT-Ø‚ ·#à 0·`d»òO0Ƀ¨ð5¯æúù~9> ¿•p›ÈÉ¢®…»ˆÃàÖÅN{ÕZhFìÈ€:ôµ°oŸ£õþØZÃÃñù3ì?#ÌÔ’“T«úµˆUR¥–*Ðê{¯wݸïú‘õxÿ#úˆ4ý2õöy&w€xô¶ÎÅ8íÐò”¡B"Í  …ˆõqçŸôæàîa™«©¯¨•š~Æ16ßE¨,oë 4Ô߯_¬õ¥ô/w­T{÷£ÈÈãɼ!ð­ÍGC0Ã]™Æ(ÓšêÚ¾îZŽÖ¥I_Ð'ï\‘ïÄêÌV¢ÙÚ¸ƒÜbUز̈xz®=Ü`p;o£qнÖxÏ8/YäÚÿ ân]&?‚ûDÿEQË"óïü~ý|}ã“ÃÏŽ};kf?|¦4ëBQAøàY0)°(yÜqÚJŸ”³ ýWBLÁÅ7oô—ƒÚ÷Ù#äTÔ2V°Ì1Ëšaogyâÿ»cƒòz i·Fš¸á‡¶l.ô`D~]m¶»²ÂHˆü’l7†I² ü î{00#"ÎgŒ$U8¶~äšyèAú™óÇè¸%kߥ?¢QÍ.¬áQD#m³E”Ocûy«d9*e¤v÷`í|ݦÊVÖ%† ”¢[¾š.œ+Ç~þíMœ |¨’TÈBèþґ ÅwÁt@Pº“,""fM¦´%ïÆØÈÂÉÀš¶iÇ'fH´³Y—'‹eã“É‹+±q„Ä›jt-{4T—ÕŸE i’*+EG¬œb¤«T'Œ_pœQR€?wèÕ/¸ánn® ynn,ók q>Ê)7 óuÞ¬æIi £—(¢p¤GN$D5¢.ö¦Ó6î˜×${Œt©`æ\ø‰%A{u¯CSÒß?»]ïÕÕWƒOCû¿7•OFHAgß=rû¨l½<ë»ëƃìÙeuå^èÌíÒŸì§9T¨þüz Bù=QNAˆ·§Â9lõMf1ã~pâö±`Ê'SŸ’£ëÿ8ß}U¯¼¾™TI©è"©r‡ Âð˜íó3ìúHÅ¿„hÿîþK[\*=Þ}µEc˜Ëçšݵ²Žl7N™³4HÖ˜Rã™i,u[(ÒÅ+¤ØY+ºü+:õtÛ¿ÇÖÛdE»ô?Î#Ÿ¿é=%‚iÈS („oX#<®1ÇšÔ‹«x@žˆ×¦rî{ n·¯JÒÊð·¥÷cÏ+ÏЙöËx¯ùøç+Û»›×눪5šwî®2lẽYŒæúU¡º|£*÷þªÝ†û© ²^‘àÑÌzÌöQ[(úΡìÇã'ÕñÔb;{Ñ,¦»Ç¼Hðû{/Ľ®úóëåÒíªüQç§–øy9çÆî鯌[¯¾ïÕÍ@б! [*ã.·37õÌ&Éžó¿Ìk5:ŸØ¹–ÆQ”(9ƒà| mŸ#寎íj‡·û<º›·ÆÝ–×¢Šº ¦ 39ÄbY¡¦~ÐõU ³÷:ô«G Q2ºvºÚ½ä Z/ˆÃïùxH"ÆÜ"OvÑ­ngãNŸ1ÑY¦Ç)™­¿ûHÖHóçjqUq·¶]T:<2ñµ-˜û]ñ”`ñ‹]ãÍ´I¦?1-ÄdùA úhæCÑÕqƒWØð×>’Ç‚g(_¢Ò ¢dÆìÍíì—pÄm÷ú ñž†0¤»M²£>jê§5jXBëצâ®LþcöþÛâe¢îº£¾ÏY1ü|usU¥5ðÜ­õ˜ÛlGý•K !)æ[í¬§*«Ù梘ð;*jVm,!ë‡9ñuh·£e”Coí—Ýêð‰n»½†ö»ŽSbhs¥¢Ûë«L´¦ÁtÙ«x6_SXÈ–ãÙ:üZrw¡ü†~™X‡»ø]æÿ{ij2k›¶íV©Û…s3Ž·<£¶ð†ä’7‘ªÒÛ#Ž×šÙW×.§©5Ô ö ×ª}ÿ ¸ T–\L¾¸KclLßÒÚ—#:´×á90U†Ý)í®µ…QJº¹™æCO‘í+ªƒðËe“àÝo2Å×ÖÈ)*=N Brý¿tr†üüÛ!é“õt¥çóÒz´u1Ïð޾p‰/÷7èèÐhÜ^ »Nx®:ï´Ù{Yñ3íç¼nÚs·Óôã>¦=ÝùåmÏ›X}±rÃæ¡¢5OecÞÌÕá®îϭʵQdJ2¯¥ÿ•4”z?‘†óyþåÛ±½ÃvZü#á‹iÄ{<ºEÍ•^ú6U½Z)?‡/ßäÚ\E–ñ[ôo¿·¯.ÔÃ.¾Øç/=œíɼ­A:òš;çFź^Iç4ùièÚÜyêûg¯²ÕbÓä×]ƒSO׫á yíf·» »F²<·¿¢R£ÃE;õQÚ¦5Zeúú~vÙßšÓ^#OrÓ5M=/CÅ]A¦±ð,­¢Ãl;v' h"ŸVóov¨ÍÁÁ‹Â6Ž)FTa3_ÁÔ€­ˆþË,ï®ØFkàÀžÇ9éóµWjwÝ[¦(ûwÂDá5‰ ývOÙ?Öc)J¥"!‡œÖyõYè °þå$‰ew<ècgýlŸGG/çß‘É3tÛ€aàþþ¥ß g÷ï?Ýü,JgQêÍ †@˜o0˜^ ³Gµ‰E‚. ©Á1€d«µ«!*ØyˆA¼nôÊ.ï8ÊTÿ©r*߉v½]eçXWDªÆUbñ¨Ô½X$’Ä‚ãY™|艥f+¨§@d¼Æ2ù|Udy.æ¢á :HkrêæUÚ¼c nàŠÁ$Ñc ytñt[Ä€’I$’I$öòªíÝá™$$„’.¦ä{š¢b¢ˆu— ”Ì¢â îÜWN3yÌÛ[ËηœÔ<9socY‡²µ®š´e$“¤îéÒI¶úo]àkñÍf†$GlJ¸ÔŒ‘Ù’d™¶ÎíÈqgg1#ÍsŒO^o:Ó‰ó5¥Ì#³ܸ :I$2¬k8Xíè’åfêÝg,¡ï8ÃÏᙳWÿB@™€¡™†Yf JRÒ%rxçWWÆQ›Æ*áãœå<ß‘­ë1 ˜HL jHQH HI8Ôn:`Ãk5Æ/¡÷\VêêfÔkCî!fw–„ìB²°®Ø€®1È7‰""tçL1ˆUÖ.Öfªñx}â·N±ž¦t“Žî‘¶ÌÌî3Y1‰ÂÅëow¤´žÒH:tÝÝ$!>c7rj.ébqšk‰‡f†a†ffff ‡ò|õþ“ù§-:)ÐeëûèûÂ]^Ÿ—ã*ÃôÓaó¸þÇŸ³mߥ®¹©ŸAüÿÑý»O‡Ø'úQª'ж3é…‘ßUH¬á¯áb©Ý kR°Y A’i8¤ß©äÈó)1 fM‡UæGÕjGK  `’ñ`òž$FÀHIFVí* Ĉ,? ¸l%£Wãž;§Â¹;SCQ*Ô¤l†q¨þuÕ¢¹ë¾¸~'_ñòŽÜ:ç(ߺï Û¹®ÎŠ`îÜ´"뛳Lñ‰óuðpQ×Fñ=Ä¢ºë„0"s`“K6Uv³Cvq0´åƒ‘Á\-,ÉïveÛÂa#|ä캇ÛQ*$4†öòG‘ ð Ü; òPëÍ«,ÝŠ3ñœ´ù¬N6¬B1¡¢KbÇb6f"³àŽ|´óˆê›¤0Þ5—{¢9Äë’' ì<.ËéÊ`¼«‚ùÌ*@P¦$Z–*ÔV$–J¥,PPˆ ÉI*Eay 'T”¨Gë 4¤åÖŒ@®–l1²H:Jªõœë£ Ù3!™02y¼ÈÞU!r°:|Ó>‚­‰Èïƒ×þñã_ÚWô(~ÿ{!Q•!‘Y˜T= ûmôÛ>ë¤Åß² þ³š†!¢ þ¢#ý)á†QŒ kBƒ2S3 F'ïµRV„‘æ4dØb aPd{[V‡Z‰-XØøòÿÏOü$x.‰O÷ë§¹#‘]ðïaª!ô{Ò'þíOû0šgþ_ö¿ðãÿwøìq"H Ó`ÐÎ&åDù(‚03Ïþ¬X'»›ÿ¿ÊŽàHïaHwŸøyâîO’Éâqù 1€òœ” bK¾/Æ5»ÿ,4eÎ854›Fä=ŽˆèÈÆ¬`jK–ú™îòí¢m—“uͰÀfFýÍ£‚fçNÆ{ê59 Ĩ`ÂÃF@ÿ9MÍôf PCÁ¥þó¯=½Ú<6'þGÈ6¹­ƒÑ&D= ¢þ?ãgû!ÿ9" Ø&BF˜f‘%$"ˆJ¯°ñÀëüˈö¢AÀ‹$ˆŒþ”¸kF¤æÛFi჊¤~v’$Mè#aB4#BA¡H(ŠJ"’A¥eRÖ†«»›ŒÑÔÓ!fûÇkä"„’ˆ¡E¡EB(E¢(’PŠ"¬â›µ‚(ŠDU™uœ)^0ViŠˆ`ÆA¤ÚWk×u¦¡VÚÁ$Њ"E IDÞô"½gú0À»ý 1´ó&¾R?"_z£÷°Í'sý˜Zk SZ¢M9â}AÖ~³ú#ûÖÚþ“ uÉM˜¹†.E?õe£ðÿüüJÅUã ?Qü™[*@n¼GüÜ”–¯ý6~ø“ŸÆçYž•þ«ô«¦r{æuMûŽŠùed †Ï8¹†©R‰²\1( Õÿ¿vHÿ£°H•eó5ã²_å±SþÞ'í?y3˜é$É.…`ÈLÀJ°á[Ýÿ«28c¾·í£æˆj€H`öåà{¿Ô~sý~¶~UþïþgÞÈ[/ú F*ã™U¯®;Oë“Iþ¶}ö±}ÑûÌ6.ÖcX÷ŽòÉP ‘€6ÌÒ?×@´G…¶¢Ÿ¾"m ÜÙyþÆÛ"là­FÒàQ¬:+È\ #1*È4Ê)ƒˆ=ðëw:ë:Š©Hª;yê¼[“¸tu°}f¢‚Š(ˆ(³úcF¢}xG³ÌôOG-Ý>îÀ€÷[ÝÍÃJ³EËŒ"ÉZ#‘ÀÆ7!Ø`Ê`as§à-3£­ïžî¯ûõ=žõŒ±vgvÝÔ\4V·k¾ÆQñnÂ6£XûÈuÈÝfš_áýß×Qù·èý:ª‹OCäô»áåäA-« Q@ ¥U• ¡T*åÎç³SUÒfIœi;‡ü/ýX•…+L•¦Þ¤Ò€¨p¡¾Ý#†l6ÜNDd\¢5àÑOvO_p;` Êo°TvÎukÑ»¢v¸¯óÉä/rTCÃ+C}<}ç‚Ü ¡éºT£‡ûöŸ'¶ ¤òFÑ7\’¸Øç^µ<•NgçfN:É&åP¶KbÐT}c†f¶K-±D5!@D$E(P´QNYSA’äÐM Б$QQDz_êѰ&Z¨9>¶&@ÂhUOð…VÇc )KJD’ÉÒQE$HKHULEH‘ 0“ÊÒP D2”Õ jÂ)iš㉊·0tC0?ȇ ˆR)†¦Š0ˆCÆX„)¨"D™¡h"¢Z–ˆ!iR šª(B!ZT¥ ¡)jie ¤‰ ¤ `&‘†j€"(Љ"`Š bRY`’¨€‘(–d" ‚ªª‰¦ H˜&2ƒTíÞÖ¾^É®õqÒQ¹80Òé<¢ŠR˜%(¤¦‚`¨*³ ª”ÑBD RD1UA M)$*D°UQ3TDŒ! AIA-D…AD60Q%,]”Ã?í ÔûàÜŸ×Îj}“çùòcl¸É¨Wµ¦a‰ˆD¡¥ ›",«1±2 Ìf¢B€’’  Yˆ¢ d(I„Š‚"(æ&äîi¡´`PR:¨B‰­Ø4I- …-%  ÙA"jX”)¡J8œ”‚ FRE)Ò@$Ô²HHR RÑLACIVñÈh31¥ h·)©u!LÚÌÖb$FCBD‘C“a È­¥EaîT‚64æ’i‰‰©tF)TÁM" oƒkªÈ-„?Ÿ¡…F˜i‘¨ZŠªbØNVF4…#¾úÐÅØ8(Š(ŠhæL‰”‚‚g&‚—;c“­±ƒOf¦1\&œ’99û š½U½tÄŽvbnÚ׎aÒ‹xlfÒ¨5£³&¤ Ì|ZZ‘ @ÝÕQ‘|ùг"¶°l¤ÚQ{ˆ Þ!`ºM‚´“h«×lƒEˆ3Ê!Iß“l"LšŠ*¨2ÞÙu–Ì’3D˜ÌèÉÌ‹ÌÃ$ ˜ÚhǤó<ó•èÖGàÀô»Ý³&"¨,å?uÌ}L63ý©›oÇžŒø/’}2Æ«YŸ ä’S‘S7“&1÷¦•6 ½I¼ôŸ[:Î¥y½‘É»áx A¦ÜÒ6èk™ÒCk ó ÿÕMŽH¬Æns¦zÓ60KA U[ªÓÆ\7¬0¨ÌäXùa¢øJµ¨ã6Kb% fÙj´÷Ei¶U”`l6µ 4p>Y¯’ÊŒFs¥@0àÐáÉ”cL9›2gF¢\#BY3_œà/;’µ‹8Q7¡,íèÉ/æî¢?øçm)O§³qÍ)6ùð,Ö”2à àhÄ= v¦ ïø¼¿¯ô™“»ÑÄ:ü´Î銯fefíà“隸ŒŒ²3êãžír¾{¶>"¥hGI!ƒ ŠÃ3%xcXÔj77&ù6¥u±ä_ŽVã%vÆŽ0öÝ…ûóá–Oú¬÷ý™ê0c ÚÁë’y¯ëSMºá8¶SÊu&ŒGøç*sM†Ãp¢.m{-ÙÃK UEªÞ´û4š6ݸÀdƒƒ¬¤ý ÎtŒ¦~]–kSl•äÓZÐ1¬òê±pÓfÆî‰Ïä«â@n&ª"lôzŽã¡À$1„!ÒÔp¾Hc ©c¼Ðí¢ƒÍ÷DÇî|>±xqPgžµU•H M$õò2opÉó19±Á­ 6h.Y‡ˆ¶Èa¬ÃXË|66R ‰dþÅ]£h:'jaÎèårqÊ®Û8ü88hÈ«`ìò•@;4Œ£ƒeëU­ø]1ä#Mí5q¡µõ·îýÿ¦›ÂÐa2.G²1cÞ”Á5& 0DŸ©Ã"|e†Œ\bj!¿ˆl¨Ò£‹¤ f'ݰ3 Âg84&éDdÇ_XÝc½Z›ª †l€d”ÉCæ.w ¯1·¼#Hš—^¡úËþ,¶QDWu•k2bR÷›ôZ&<0 j5Æ»ïÜ}Öæþ¬ ù ø¬ 7õýNÀ´é¾$GF,’  ˜s""(Àˆh($0LI¯jA¸ÞÉÊiÌÌ#&ÌC#ù¢­VÝ1X䪬xRÛŒM ÆZÉ™)í1Ú8Æï¯žjŽôä&¥á¥¥<ƒ™N$(x°Ÿ ÎqÝšÄ5pN²ÕŒ©¢8ë[Ô¨ÍKQ7¥ß!ºqÁ©`« úÉvN7G"_Ñ¥ó5NvÞ™jE;W};}´™áϱͭÚÈéj‡pÀS÷jNCJ ƒlÖ…®» >Ó[šV*\cžÌ‡%ާδ)¥mg*ÙíŸLñ;9Í^{0Ÿ«ðýã}ÞÊÈ(jýâä¥)·‡QÄâÁoP/æyÎÕô+Ï©p;ü,>|ˆW7ýŸiào\ÛIa2ô0ýZþþ¾i#œ{ð€Þløx¹Z²åx,ªý?¦Sv.3¦ „>ÃêspÐCÉð÷xy1ffVfÛm±ÈHã$nHÇ$’ríëeŽ}'ÀÖëј±:Îy#$b3(4E¢ID“óQ"¤’PŠD%µÁjìÝmO5-jO qQÄÖ.ú†¤Znµ@ÁEDd¯m“­mµN†¹µ9*Þ7ÜF„’ˆ¢IB(’PŠ" Æ´˜UìA$Ö:7á*ض?.¿fº^"ˆ Š"ˆ¢(„¢(’uÎz‚(EB3žÓÕMYø—nïÑ›ÜþÕD¨J/ä{$\ª î ¶Ú'KvJ HÀ|Y=Ê›”ðN+äê}º\y$›ùä‘ã˜DE’‰Lk”F #YIN¢nˆþ«C‡ºeJÓ}Ö  H… "ã†4ÆaoÓ¤Hv€:d eš™˜¡ÙA`J‡Þ¹ó†åhµ ¤dÉ ‹•«Y :j0ÜÍ!1l³,W UQZ ×Y52þ‹5ò£E"PM ,-TÀ†×=Ur \Ãß¼KC0À…`²Ö1táÑ $øÕ7Ìùîžø>4=ªŒØÄ¡KîßUÎÉ‹5*ÀR¹ŸyËy²K~9ÕM…o´Æ4ƒ@C»ee²|Œªí` ]4ÚmB¹0H$šôòhGŸƒéh#ÁÊûm3.=~ç~µxç0û4ùø†ä#cq/²ë,pàДñ°M…@"" o8uIDm¤÷¾9î5Êácå¡2Z”hߤ¡ia÷¾ [Dºtm/ –ªP*€‘ ŒìÁ`,îáí*Õ¢$ÀFoA{G­ag]NïdÐø \JÃÕ¯£ˆÃè¯ÇnëhTîÆU9Pi‡KÅHué˜äA“F€ÄXÑJ©Aé1ùLî0ûk? ¶–¡D‡âÿ3ÕG«é>Á/²?´-ûaøòûÅ»ç3gã÷ÐÈ.Ó„XÅT`P Šab9ŽogC$#êdE„ Ü …’PÈCR‰:³_¯HîƒßÈÄ2r r¥~©Íb¨Ù­&™i ZgX±´jn1u(u˜*ÒPHFæÀAÇ15`I©G"ᙬ][©äžIDà„rT5! JàT÷ +¼T¾úþeÅbëo¬§"øI|Ùfö#ö|<ö}? 5Îé›>켟_š*¶Úë-xÑGuäjo°èº]{üÏÄÌÇ û{ùæÉÀ™ƒ¾Ë–”MÓfC}ÅB¦KÞçÞ0Æ£Mk-¡¸D˜Ö0Hïv­Y/™o*s÷»Xž™áÕåÞÄîJr7sÌó£¥zŸÝ/-ßKæØÔÛ">z"ãv¼X™”$Å!PH‚^ŸmAQa¨3oÍ„’w=â}r1‡Š KŽ®~tA‰U…e®Ø¹ï£?6Úì¿û{°ß¾“ƒeM¸8™ ¼7t8ȆÌ3²ùåû-üìÁhØF‹¢q#EÌ{»¨Õ %lª¯D½–ˆøp9GÉ÷u/Ó®Á1uƒ°¿7WÀ"¯N¾PD¿%Gå­þI‚âÈ"ì„“ýi5‡¼oóíóùä¬ûÞ}DÝ?ŸüÿFá†`fe¢'ÝÜK·O¾•"—v—µÕŒHhµ1²²P‘ØßƒõûÎË7Øéºöæ=)c}ÓöS^ÏÁ­"âa;¬KsäŸo­|­1ð8;ìžÁ¨}ñû¾îØh„t¦ÄÑ1ü‹¸¥K²a0¤ÄÅjê9,Ҿ剛«"x’ÉÆÙ‰Žf *C2aH€Àò‚+m7º•woŽÚ»ÌïÇ}œSj-“‚QÉÎäÔ¦ÖH6XŽ8ÈåHü™ãšžT¨ü¬3i¥ÜÚïOA ôˆ¡¦°0¾=˜ÿ-º ^0’-·¼]¯&9oý‚>¡îDq¡"pwÝ®‹K´0UC©F’0Øð}[¦ÞÎJ]® v ñ·ƒ6[$)DŸ…$GáBr _mȬ_IhFáôÏ÷ò›kóÊîÙhÕdžÖ‘q’ŽP4b­<ÑÆÒŸi­¢›(¢X˜ÒhÌ—K&‹ ”Ù¸×?ÞÜwìx3Ë©mrÇÛÛé=^¿aÀ„H»H”W9E>]’¼Åÿú4úþ=\ ÷ŠÁc"imùe  v&ÌE sW¯_~­“8Ù/µŸ‹˜ÚÛ#qÕO¥ úÇ—D·ó,ܹ$vs”Z!¿ÐHvL^?b`Ò’—¼òÃÃßtY)Bcî0Ýêß‹1ßJ¯ìû“i4…ŸÓ\sÅïÊw°îÎÞd߈a`—†Ac(0XÅÐy|»^>ÍÈY£xQFš`ŽD÷ØQ*mÍ(Æ1–ßâjï5¯{%ÿ¹ èYÓ= ì®ñó>'z¯é5žnº¿`»NþÍbÄ`h/½½© ƒò¾Ý;×ÀÍ š(™ ›™¢hÜ®Vj]ͦëµM®2ûD~q$¢6”B`EDQ"ˆýn\'ˆÅ´ÆÛ6×VØ¿D»•M²î [Ù@EE LÔoI`#mØ4Í„“E[ذ/öt»SF·wF5ô:gö½/k³NÛ9û&N'UÔˆ[­Y,i¦Q«‘¥ZÒa¤Ff¥%XLYÈÈ@5õ~èwüŠ3d}…£Q×è¬,ŠYeE'¿À•ŽŸyÀê#‘{¾fÀ&ñëùq6¤tÆ,éxÞeg|™\h»/Bª¥3…/g‚€ÄÞÃPœ'Åy¤Õx°  3™Õ®aö›yº·\ݶ!Vvá@)T~˜??B@œý #ÿþ‹l$À•Æ6³3l¢múr„É­­3n†(²"‘ KaŒ^¶WœSÃÚ`LufAW¯)· *‚;Vj)cqJÒf¶§eAôD\S…ãPØ€)…W´Â倗<¢²8Ñ-Ž˜c °Yb ƒVç0U#)©å%®ûê-lÂZ!<ä5ÛlŒ_!ªÍ$ˆ‹@DJ®h"’Tgãø-(\˜Óa¹–mbpÛ8 Vf3Iõè¢a)›5X ­@ TÀÖ  ˆaÈ…B¸Cb´ L–dÍÜ)¡Õ‘em»-F€ˆtf'Ï &aL´¹÷ì_s¸Ö“´ö*p ªàÂièRµ!£ U•ØŠ":á!AMN«GñâuÊpŠŸ‡—&ËNއ´F¼dFïNÛYq¸ÀX¹´’©FŠa‚xF UÜ£,ïHD|÷ÌP3&ðnˆe©¾º~Hʯ—r—Î~̶y1£¸Ý×ù{Ë~Tuužà[ú°Cz(¡;o“ÔÞ×£=2‚G¸uB³ü yÁ©–ìŸÂÒì´Á<ÈÎŽí¨agûUžäª)aÑ¥‹9õRåP 7|€ßµ°³N¯Ð,l1ñÊ„@áWÖ'EïC£Lƒ‡Ôs?܈©+‘Wnƒ5­jhò‡Üsï÷öýÛ}±¸~Ä¥ùå÷ÂÝñÄÕöË”JR%"俎S5ˆ£f´"êJ JDWäo $ Z&!›U4ãCL[a¾²e&]RjµDÜF„bMJ¡¸ F$2§P‹‰H¬,á¥Cúýˆî~3ÌE"Q@Žñ"ˆÓøÄ`Š#ùäz.ÿö¦°Gü¤æ#ðÉI°ŠDsÀŽ~ã$ݰY‚8¡#v¡#¼”I?¤~6Ü#aœºèFâ7DiÒl#ùM˜#B0F„wš¸ŒDy¢I¡©ÝQÃ÷ä#fâ0EDt4Læ"ˆØGa"„p#ò„uÁ–Є¢(ŒÀ„lÀЏЄPä£ÇèµUUzåúü¨` CÀ>ßPëßïºf~1Ôh4Ö3*a”G>á&â?!rªÊâçYeçGºêo·ä–~Ms!uÕt&ýÉ ·íEY,ÙÀXÄÆ&ŎϦw0[. Ðéγ è·Ž»m>¹æGuÏ0éŽð.¸ËÙ‰Œòb[´]åal žWl¤º!ËËåU5Ç“¸Â2+°,²EE!B7S;ŒEL²6ÖAugàŸÏ¿?Õ7ëòqç÷qíÜ/¸YGŒoØFâK³)êk°YñÛú®¢ T@Ž&¸æŠ Mø²)…2”$(ž¢.Êùð*Gô¦áBh@øvK­·ëìÇ/ýEoøÑÁ…+¶'H瑪ݘofñåÉRÝéi¨ëÇ"67›džÍa†9»Â,c°ç‡pÞfÌç,Ê13íóú>"êµ¹Ø)Í/•ìøèßnµ†ôtc‹ë/¨ˆùFϳߙºüõÎýØLøWA3»÷ì$Ÿ°Fâ9NŽìÄ«ùz¾åy÷ï¢8„³C¥bcH§Ã^µõ/H&~œ×J˜Šë–YPýáç1HŸ;ÄLSÌÍŸáˆù½,ž‰€‡’‚, ÏmÇèáAÆz( ½æ¡Öé’¶Òèb á`˜„ãà†#amŠ‚¦Ž«´G2ê®ÂêÅ$(|)£‹ÔTN¬òHCÆÄ©Æ¢±€É™2VáAM¦cÖ6,õ\eÀ#ÄÀš¡Á]nZ+TÏFR¾²-u¹nØR#2Ú'³0Æ2Ì>FôTª¦ÛL@CayMUÙUé}|Ú ex‹(8ÀÆçjtw]u&Ffšòì0Æ»âÝà –ýªÐãK¥®ÅãMyDƒsŽŸbÓìvcŒa Ê"GW$˜PŽ´Gsºùøoa($ßQÙ¡;JçŽý˜ž>G: îöºv惗]óGL &ßñî Ðq®s†}egMUÒ•Ì3Ú‹Bܪ3 Èü¹zøª8=POÓóuZ~3f|íŒÂH¢-|;f´Þ¶B?ܵDLD:÷|±‚’#à\7ànº¯é‚2ÁØXþÁ».ÿQéi£ˆhšÃ²@³š”`xŸÚÉ&‰“eñ:Öƒ,%*)L…ðœÖ*9šÒ‚äЀœ*QÆð Q åTc1!„êR•‚0FIqTj…±µ ŠI¥Ú¤‡îâü“Þü®ã:%‹øóÈI+ñ0GëôÞðFÉô²gf.e óhÔáJ_SÇ”#yyë"v¸Ï-,}â¼Õ%#'HN3 dûŽùõf¹ÏÀ¥X 64×FÎ'âjãî¡¶Fw4+"Pö Dî’&š†Z6üž¯åøþCŸW$"]óhêõŸ ÅÞ¼©Y•8A@‚Ìh(•™)‚퓸Scù#²…|w0d£¶†múÙÅÚ5Šó¢¤v/áÎOXòËUtZIkãC¡‚Ô™|:SˆÑ{ »n•Ó¶úRúNããôûнLò{ºÁúvYô³Zž¡XW\taïžË¶°ƒÈ ‹¡À]{œ‰õ:Z’­Øm4žÂÍ÷ O*ŠfT¯Ë˜‘é†+ä{=OÇ·|Y8l¦©2Äç̶æLÄ9xCÉ@_؉<Æ ëì Àd³äs|»Ÿ‹sŸ>oSbt'‘Iõ+ë)4JJ6%L¦F ‡óSFkÃ-‡ÊfŠZµµVØDlz¾_›hHØ»ÔüS–x×ëL¢<”FbLmQ€!ÝiXjbËšª†„ج°ˆ¥ø@´ÏYƒ°e7DðXÞ|OIˆ¯Ò"êB Eþ÷Píû뙳Kt÷{ï Ù°[jo b=² ßÝÅM1Õ (P€Ìƒcñ‰Ú'E^R(øcÃÍò®ë"û˜Ö2;×áòµM2O»=^,ÙÑNo´èõoù¿G4Ò“‰+”kRSQžný™\¬Šh¢(„Z,ÅÊŒŒŠ(J¥*–©™^'‹¡ 8À¦;–Úð4½ÒNÄHõÊ¿LްiOêxUÜ«§±¤C~ÀpT8ߥÌë¥0xã’JmMNÃ{ÂÙÜ n† Hc®³²Zã—óh×èc@ÜüžŽiÎ~ÞÖCê%x^Æ–1Ú ss`1$ðÍÁúº~qÇ "ìÈ vŒöíåLt×»WRk@ÛK7éMíŸhðpuÉœrÆJ‰‰ÃbPôa7k ÇdFø(ìg|ƒ@Ãw;toGÏs[ DØA¢W0"³¦.ɘú}>^y7õ?¬Zl/"ãPPoƒZr+¥¡éyêò­¥ÜC#o7J=c92G‰OE>›ÝR¬Z-™gjf±#3ZALŠUM„¦äÖ©0 2 (Ô9(»4hЉBe’2²M]ª½ÑõÒ<ŸiÞò<Êî樌ðlžo-·o#m“˜ý:m—”}f„lmÓ§TÓ¨Š# Š¢5—~¡oôßÔ¾`Àóø{~Ú×#ªJHÿX–ˆùýçò‘yúxôëÃ`4V›µ)ã‡ÂÝ`‹®¾Ö£oíÛ~Ƈòû¬JŽ…ìÌŒÆøæ’ê¥ëqö/Å…fƒ éÊŸM8NUº,$«oZ©ÿ3qsá¹@¼;•ü³Ò]‡%›Ôs¡}Φ/¨g$èB“¡kttAäýúí4ŠSÓÇz¿êŽ|MÅò«M²ÎN6‹µ> .e個S‹¦2>)‰“Äá$mÅ2"PÝh‚[¯M•g¨%‡úÒ£ô~o8C‹ÁB6<‘Û"fΞµÐȽ’!S“iœÉŸ@>šˆ$‹Á¤µf2Z¶+³®SÌͪ^”Lq“ öý˜z±I›ÐõŽæQ“½N’¾LÔXÂÄV‹ž ™›ø¢éÖ»}æ ÓDJÉpEÅøÖm©ÑНÂÍÚúkoB=JL“ êžÉ¯n{Qêh£{ßñŒãð®­k­´qÄØÖ¦‚«3 >@žØ;zÈÁ1‡áh;´—‚s!/ãÅJâpŒbU´;E5ÎçM%‘&Ø9v‚ !²ŒÇ7‹)¢e3¿v›!l=÷,”©ðû0}«¿Æš|ÍŸ7l“‹¼ãX]3ËÇ`žP<8oºjø_Ÿ0K!רxoëéxãkõ}„°˜Ú_:ˆøŸ3ÙìôõÃ"WwÉEO®ÍëQÓÓ·³ætÛ$ƒ.Qs¹Žî²0 ïÖ éÓ¶š¹lèìÜ4sͪñq ò€g3kÀ¾ê3·ûŽA^­Ëhj3ÉO·ÛnË Œ;ðåsº¾ÇãªpKhô‰7aE™00Ç=8 y1‹§wÉôîÞ7ÈÍ„yõ£Fï 6"^¥¼ ÃÈÖ ?ŠE‘ªÂ–¬W †IóÍ”^u ¦m@Ò"R¯Îj‘¥ð$ºK¶Ž80ãÝÅb]KL„r’ôLXˆ# šºŽD˜a¼q³j) /8f^Î>÷ÂWÝÂF¿Xu;½úp5X˜Â¸«ÌQÜø³Pß'nTBCo?úž~å]~úÄéRIŸñp¯Æ1ûžï±g‰ú{V'AY›Ð`ú<~)yMO‡-i|XÑUT„“Á©\Œ#Œ‘ÀlJ(·ô‡«§ÐÝ7¹ó o¾ Ø6oëkàÂáÁ§1ñS…³ç7ÕË-ôè̉‹Ôr¸äæÞWe$ j, 4 ×à`cBß1Ï Ïk€nA®wÓ¦UuŽÃG¡Q‚ƒliðb: °í;öuÆ pS‚'YhhF9Àg' yåÕ†Ji§¶1 §ë’ÃU…oþÁV±¸Ú ⟭Á\†Éfc#ÉWžjY»AœUô!qðhÁkÔæŒãù’hYHL#”ì bM–]²Õª#B0FÂ(kY'µááo”ìiÈFºš…JcS£“ÄЈÛmóvÂIÐèÚñba6Á©Ç¯A´p"í8 <Ãà5ì‚N²éSwDÛ³m'íÂØÙ¾ mRZÉŽ¸ñºãïûšOC¸š4äM÷|¥³ìZãµð\®].¹ÓZÑ€iؤ¹ü‚†J. ÅLì†f33Çî%=ÙÖüè2u†dq¶åߪñÌÜ1žü%‡;î1Êü+w€ÖÁ‰ŠÐX5>£9¹å—¶ú9鿱ô´ÙªÃùpå.3Þ•e‰ùs¸0Ã^³žvožn)S³®éaQΖxPôl06ä·Ø3Œ…ìçªn·@Ï-Í›Âä¹nUœ÷ãŽá®{]·ªg|€ÌÔ.Ì<Çpnš¸žÛ®ùˆÜ£[Ù Ü7¿Éÿ"3ö£ë{ñÏlÀï$—ÌòÈ0ðFo™õôŒy¶ nsÖ,9¦xø³”Ñ}ú·òØKnQ£+Ή±s 36lé›dN v–b6f%e„l#`¶^ÃÕ¼›Ç>h`æ çð¯N®…„Å8íE|Å GýÉ_g÷ÿ—wËâNÉLBæZDú#ÜsŸ9z*g%ïµFKgþGÎ%­]ØÖ'rFÏþ É“œÒ^<5 Öµ$D¤2@%&Š{[ú]v éžßqw6tVØWEˆÿZ¸C¿~)ß’@÷tIB AÔ ¬E‰JXU)J‘EP¤BI \& $ƒÓýÝËì~çÜI2ß ùU×ÉöPLœ.ôßa¾uæ:roi>¸_6üáú›íõi³ãk×@™ÔJ+"ÿÝ 5.¨eº™+ûÙ™™˜™‚Veªš’ˆ †ŠJ"A˜¥’`‚˜¦ˆ* ‰!’*"h"* ¤…O¡þ…ò/¤,¤!O ’\°“O§Ó7¦·Í´Ý<‘m^æh£W–™3ÿ÷–>‚Æê­Ï{ ó)f¡Ðvÿ+má–þj|zLaU\¸Í~¼ÜS ÛÿMÐÕ¦<ßžã|>÷iŸY·Ì¹†È º÷ôƒ!$05éÁ‡0;,jªÖ•Uº£J’È4¨Ä†V,V´HÒ´Â©Š˜¤ÈHBì(SPÅV߉gµíé×âþ`ZÏÍ?³ž|sn ŠGÒFäªÛ$¶Úr¦ýŒmµÒÛ$ëm’9§,’I$’]šy™$õs°õ­~$´³2I$ª×–…¶Iôïø5›|ýfdœWW¨êÍRÖÍI’I$’7#æËáþhån¼Y¾ûÉ$—Ï1ã“Ùtó?7«3#Ò–É<í² t­¿o킋ûŴ̯‡ßÆ.­×ôLÓÔ’I«nÉܶÔ[|33JM| l’MIdœæfI-·-®I#rl$[jVÙ%VØÜ’Mff4PE–I$’i¶I–Ù$’I$’Fä¶Y‰Ë$Âàó$‘¹0VÙOn’JëRJ­ºÅ™’LV;0·èKff‚Û$’I$’I$x‰l’I$À-®QÊàät–É$’JÌÌ’I4‚Û¢Û$’I*ü‹KZÕJÖ -9Ÿ‚–¼,¶Û#rHårÉ$’I$’I$’vÄ3=¡mÒ-¶ÛeÜVÞÖ7`æ[\’Q{šÖxÑwß[éYÁ”mÙ&XìªÛ}×ó{½ßŸÛíý+•ê}»>³-¸|¨™’J}ÿ©i8*(¡Ýè„!ìÒ€ùL R$.ºWPÂa2ÎÕÞ€Å]G·An]L#Z`̼SA¹7˜.ç 3ž#'ˆG†]ï0%Ét:3 Ü £‘™8Ä&FFÙÜRêÜnB0ÙÞ 6Ò˜îG t › ÙV"•q&~lÑo­õÚäyhyƒf¨‘‘:(@‰¦IÕ¥HÕGÒk UŽIÚ0‡S–HáÞÖ`d¥^'uWZÃ[ÀÊ„4Ã"î1ˆ$­K‹f)b.f¤ ÄV‘g!Ä ˆC"Á°¢$ÈÉÂ+"’Àp‚ÌÄɱ1L–¨ ´K½bî ¨*˜Å12 ŒÉÉ"ÂLÄÅ&H¡(rÂqÅ8Æ f™=΢›DwŒÌ×ð_½¿×Én~¬çº!¦qœ¡|»4¹Õ_=&¶„¬k®ªºÊ£CÖèàóPþZ(îÏ ç<(„,ØCSPÌÚu92Ÿ†œ5ôO(Ó„L:yúºð÷o7 ô¤ ø%Í7Ĥlé2Z£²·#-Ë%܈L ?”…´ÿÑM'˪V½"0mäÞäâ©Âÿ¥Öß#{ ë¬g“CvEõCJ-ƒ E:þ_(J¦yü %¨³ÑUü8TTGWÂÇÕïÓ·¦û;=ò©vê±YøDàò»—Z=¸>E3¬QMÖËèz.æz‹ªÇEž¸Ô-1ÆÉõJÜ6qé×ÕÕÿf£.œcÎÛþûöðÖg:šl-¦Uwpè°äKþ»ô³ñ¸ÆtO•q–]/“]Œè¦4ÿ½¨šyʳlªn÷Œ<”QýpΈÊÉ7?Ê[°·›Kš§¹®Ý«u4ÿIÕŬ f5Ý\il ñm2ÎÝ4Ù'…‘3 õðí‹ÐU? _+/CbÕ.ïÒUµj4h#«ç–Üq'É©jbÁN½Ù~Œ*£#ÍÆÜ%ŒìSJ‚¢N¯œ”­`«úʘcü=Ÿ_/›UǬ>Êég·Æž…¬’v__³—,7¿Œe /sËř”œtÄX‹OXáÌʦs2ïa@×ÜXiÒNú}·é‹tVTWâ_õ"éé$Éï&a…^|òÕïmú²ƒ+›?Âtì¯D×üYÁ’4­$@ 0$­e&(kÃd¶Æ_ûïmbûjy¨åÜÇÆÃhzLžÍö4@boµ/8ÔС×/SöAð-Dm„Kó¸Hî…~R™'–ô~<ùÈ÷\å ´Œ$ÎâÀL…qòì·°°”ü˜”îCgõîÇÐ>4¾ü/”<.å*·Aäö8ú?ÂÖußôâÁÑs÷àrZ?XÀ:µ¦#M45Ze}ƒjd…{û»VóZ÷QßÐ9ñ])רhFÕtnGÉ/<ˆ'WßA»E 2XÚÙNïòH®Hóx¹æeæ)óY›o­ƒØÃÉÒçh ’ Æ¿f˜Ä ™(«¶=76É|ÛP#6KPÔ yëf¾¼”(‰M BPünnïô7 ÇÚq×›Ï~ØL¸íL”®þw»¦lcÄy2ößò‚*^ð{.„ÿ Yt/Q±‘|6&¢“J …jƒ×2ü¨íÖòwAYâRÏŠt©'ò!áÛŸ³qág—,¦‘íŽÁíÁÈ1ÌÅ~¯%±+`­gðyõI/NGnü d•ܾ߸~q‡â>CÂsÙovÇ÷p o q}F‰Ï6‹! 1R/¨gúó—ÆúÚ 4Õ:· fº¤Z›1‹÷ã)ÏÍÉBkaØïFyôT…ÒÞφZ_Ðõð¥CËÙoûUÇ ¤b>%g¾ #­jžT¼´FŠjB’¼`_S”zjõÇ6é/gÐÌ×SþÜò1æÜ»ør˜Íõ-wÉÿ'úˆ?ÔAøÒ'ˆÜ{1‘‘²FSZÇ÷’»~¯.£þ¿Þþö?§¿õOýISÌ_Ý÷ØcÛç¬ãöÖÖisšH…'‹ÀçD濉b|—þ¥b¿ûJ¬dó¼ès¨m…SæÈ4±ª#ýÕ!–}–Ê|%Чé¿ì'ÓÇÓKáÔK¸ò„àâ—’Gò›Ê§ˆã‘<‚AÝB¾Hõʽòu÷ùŒ™úa:ÂQ÷ÂáöIý§é•æQõCöBj›àBó!å 'Æ=öc‹ì—‰ȵ.B‡I9@'>¨Úš¯ÅëðùnØýFœpù´Üv@ íÊ· ë/«YI O:PUóBe‹ÏJ-¯<ޝ4ô©Ć!Œ!Ÿ—€I§ûp Ò¿°=ø‚ÿºTüÄyÈÃFy î’w46Zg.v ÀÄ:s{¢Í.üyDïSXúÌEË{°ß²vÃíçÏ]ª,"ƒ® –¥¡q &ëýxá éØï`s…g Ôd™1š–E{X5RÛ¼µ3-sFÞu`²j‡t[zÞ,Œ2løª(À{%•ð)r»” ûÇskq¡~ ÁÝ™8}û;ºõ]– ª@g_O¦":DÉ/°L‘À¡ÍtºGë âI•¹˜‡‘eó††tY–8>žáÊá1¬¸‡à„‡†nRr;'•"ñ€G°ƒ6*£„Ÿð¨irœXd±Ó»þ^þ[|õaÇNɧÉNäì{ý÷ì4–<~{zz÷ˆ#‚ý–~¥?ô*¯×:ý׬sˆ‰ ~-w]ü£´ò¼í?o ’ý£sÐçJÈè?Ÿfìñÿ8iýµê°øþþßµ= ŸçÏsL¹ÈUAùKæazo×> Iáo yúyªoÚjŽût=¬’]¬‚aM¿Ûú­%) Çú‰ð“þ¾í¯Ó°»¬ìzKACâ”Yé‚>š‰'Þ¢*„“ÿ_ëÈŽÏ‹$"iuSË\„$ó`oDÛ¨øH 2úHILÉÖŽ„%Ì~3>“ÕB„œi`ÕþÙM¾Í;߯S‚¨zÍ.!%{ÅyINÂI½Þ¤~)†b !¶v?a¼’&_¸‚]ûôîwzøXbe¸gw4ÿ„-Ö/¿§ðÕ#wp×¹µõÃŽ–M–ŠH¤³Ê“” á%Áj!ÉvRŠ××?–ËF&ï«Äá–g?v~¯¥åçk^ÐìŠr¡Æ^B}'Ì´‘Ðz¯5ÃØËWegîøè'¬ï«ÕØtÓóîªßè{ÁÏÕD·qì’õ>žì[ò7~vL»ÃÚ"j4ñ°Ôx9hC8Uè©™07~G™0?·%y>øßÄ/ÕÑÉu0êÃW=YïéYúÏK×C]ÇÏêí“åÎæ«Ð||Ò-^!£%ÔDb Ü/^¾LDIàB|ä òaƒ,0-2Hª ™è)e¢]¾}œ7oeï>¯Ð~cý¹–x°{êj‚tìЊúèŠ4û¡ß!6¨8<‘<˜4Ò@Æ·˜GÃŽãx9$|T± "o×h»û0@9ÏÙœ(îÙÑŠ%Ü0|™QêHöOªŸO°Óæ8˜àWœ‡RH¤0˜I\À"¦O°¥ÎDP½‹ÓóÒ/0‚}̈ K|{!óÙŸT Š£û¸ÉJ¡ ÿmHU"Ø5QqrÌpÛŽ…u˜€†27ì,ã ˆ¢‘ide—*•_óTi”µiBÐJ±r$Ý€(ßèíÖà„#åŽBÃ,ÊþGZAöÿnÿNœ`0H‡Þcu R£$OO¶Ðhi«ÂU Pó̈Ÿ§ÂWÑNϾíìòåyÞC¾´£¸GK nŸÈus‘q”6u¢µº€Ù÷iûš(?6GìãÛjêEÝ!8@;ºt7^WŸMÈíSÓél>~îsé©oç¼ÀòBPûæö¨°Ò…tÎæ]©\kÜ2WªÇ;þL¾'Ÿ“fǧ¼Þoñ“’n?ÕŸÙ4a:ŸA»þš|'år´{Cùh0 å† Ó ËL“u¯ö$mÄêÖn0zµð¿Ê¥ú ¨Ý€Çü-ì:Ž—‹A¾kW"æý°üöíñày&‘[Cÿ„GBìÖ?bœæÉâ‹9ßÇJª®QL4ØL"]îWoØÅ)UêBT†ó3€}­ú†>Ö2_š@ì(ÿÄ{Tt“ýP¨?Fwðs³Æùš*£ÇÛ'¥üIFŠqÊÌpÅùÇN8˜nfò!ø†>Ò-æ*N»ïÑI=¤ñ“ìžx"j#ÆÏƆWå12¿:ýâØ€B„IgÿrHBê()Ÿòb?zýÓ„ZkÙþ¡…gV˜Ñù>Ò?…ˆ(Ѷۙêݦ&- Ïû”Ft’ZÑc”ÉXC ½âbÂ&ËÌP皪¤D—g½Á,“ıÔO×ßöÎ)$ü…gõýŸã>6l"3F ݤ;p’’Ý&k[Òž¦V0þÈ‹ÄÚ*|S7ø\Pƒåý€}´dÁG^``Ïé=¯ŸGþî(Ÿôƒ¸ás‹·ŒÄH“¸'#—\˜ çÃ7Gb^–ÈØüت~Kü2ò~Wá®c¤ùLºº»H°b#Za÷ ó6Aã‘»7Écl ã–êMö1âÑ”sß Hí=ɯÈyþNèÈh«+°0VÿµØ~BŠ˜uû¬.”>vj¦›|ø¯w°Ù¯˜87ìö öƒi_×QË9E϶ÓýkÒ££K•K_£Ç"ðFÌJú°þ­_D+$> ”ĵõØÔ´§òWØnQ´Ï<%óÞÿ‰0ΨIÔù$T‹wrËõâ ÌŠHø*9…0Pðs ÜzüMÑõ‘MpÿÕÉ%bO#ÿÛÊÛzJj µ„ 8WåwL2"r9ºøDI±ìcy*þf{èúµý%4}GC!*f ÷û<¨;c)%£ÿðå¼ùo?â +ÕŽîw‹9tèï„£ç4ÓužÌê Ý«¸x¡úµÞTéÿ¿‹|ïÞA Ÿ¡{ÓH(̲ŸÄÓ¤EÃĈÄí5ƒ¥,bb-º|cõƒñY6Ä3cï”6BýÁ©$pqÊëA÷ð< ü$Ž7,´®W-µË. ýÁï'Öø?YØëyù1ú¿åsÃÖõ¯Ê9‰©ïôAÿKDöFñ‚¦RcíhëàÏG$%Bð øž“mÜÚMä¶fFÔL¦ì6Çt0É0"\tÞ?È$1—mFÖ),?Ã[Ô7kÌU;4ôþI“ 36«.L´Íá{…;0gÐÿ–J™Ùjq€#")÷'W¦‰™½ÄÏú´Qƒnж0>J|3’AÄÿØÝ¾(}ÿcUDT»ð9ÀŽÆ–BOøÔÞ¸C1ûïn³üèaü“óÌ€#šýdí§†Åž&Ù(»Oá¶J“ycò5ˆä£ú-J”¿t>ÓFý²sxO|2‡%’Ïw_=œ´Ý™y8ÂUþšíFOù<€ÿv„ä ’9TŽ—F×0b"ˆD`; #UOÕÏÀóÿ Ô’*¿’[Â66ùý:ÀÅÌŒ~àQ_J.âà0ó—„aZÅö)ÑwcG¢¥$$¯ðO‚È~À-¾ä0~½Õî®C!’ yue¡-èQLÒ8{¢0oköæ93ú½ËB( n¨ùSgÎÌ‹É7NÃ1¦Žlóû±Ö$úáú…uŸÃî4U>‘MSMÎÿ>&f´ ?µtoÝZÈ©Aóýƒ.í,Sn²"~»¾PÙÑÅ£+ó6nÿ„ý=ñ°ªô4<ÏlÁÈ šZ£`#ë]åxñÖ°ñô ÔÌEêLÊ­º¸¨‰Ó½j¿‰;‡÷8–  ‰âgéûÞTF;Œm+±s$Ì!º1ÿÏœJîy63£^¶FÙ÷4b" ц$²d¶q  b£Q§A(mÆy˃ Ë`AM|ºÄÖÜ–CpoÍ~(nù &øþPãgÉÎ$ úåOGÝÓq¨Oô’s‘ê$ •/©æizK¤`€“õÆBmó€þÙ(u›F+Lsd#ĸÇyéµÉ¯ üðö¨bGÀ²ó{ežZÕ×›³¥¦ŸDœ¹gWc€RRŽ ŒÁÂS -kZ¢? &ÜtœÇnl›þ؈t‰¦ 1ÀÐ.£Ùc­Œ¥\¡ãÃoÊåKb—––^–a†a†ËÇÇË~©;C³Ñ®ýý¦ÚS•‰D¢ËV©Ï ü_ã䛺Íá¼ ÚË×°$tÞ*ñ†"•¬I3:ìFÅ‹±¾Pî;Å£nÙ˜ýݱµ,mðô“5üf$Öši’ì³²ª†Yó&Y30U‹GÛ×IO8~ˆ0û— $h#Ø|=NnÁð’“‹µ¿ùh\äv¿Œ7i{HÂ9M5èêÑ$IRIp_÷tÿÝ;à—èøÏF„ôBSkóÖ‚¹æ|„“yÖ†î¼L *-h¶S/ë§uv£<~ÍXbÌ…Ÿ§Àù´›ž 0‚%¥…õÉÌ?{ý÷µ<Ó^ú¤ AkeX<õâiXu±‘J,´2èÔ¤Ò®‰¦M1¤Æp0Ö°ËF˜-·é>;»Ù™W¡nûã%âýÈÈÿ˜?j˜ #å!ÿèÓøÇ)ýŽ&Ý×üÌèµg­0ãõ5&÷Šz´*‹ ªÆc7!èϲî„k†pa[;‘;e¦´âJž–*৤’(ˆùs`ÚAïC|2(˜oN´O(}…BùšFø~S’0œÚ(âþ/ö™8,ônéðÌ 7#?X͟⽡èKè“”ãü³òC¯ì|[êDÆKØÞÆ2@GëÝÂ(t#Á@ÁpÑŸu«¹$HÐ^o¡ø\àî_<=»q¹¡=ä ëôÀ^¦‚”9,01)"Cz íá,kÜG"õ%QEMD,‹ U‘™bh$ΰŠn9ò$k¡ÞuõkâÇ€MáÃ(È&ÀÞ$ÀàïttŸŽ™ÏºA>fLØì$3C±PœëÖ뇒#’ÓÞ}ô@©%AmL_ì•ç8nõ© iZö¸5q„h}õ(Ðø –/Ùöþ­(ZÜ"i¸HLNXPi0ü“Â4`1P‚¤M‡µ¨¿—óôÄR&:fUf¾{E™ERÎD§¨°„½ß¸Íè%ÂHšM”GõžÊ"¢¬ÛGë©ýݨõÿ?Î??žØÉ›»-–ëS8Ôe+¡²U¾Úq÷—ÎkiêœÎ0Kå MJ‹ŒàÎ1Œ«Œ¬Î'ú†fÛqüìÜö&HSAlMÃòú8ÿ›‚"«†O@~*¿Íþô¾Ò°#ýPò)ÔpGr/¯\6 Ÿy8&JæÃA…pHxx'Pds†EE)©Æh)™¢\ –²%‘Š8Ó6ÙLZ>y¯²oÄ{Eþh#õ}Ö¤ñÖA8áY;Œ›Ãt~iöý)´ñœ2Éép@ g»k*ª³1~ñ:›8AZBì*Žd- ¿ß"ú‡Ï\,LQ¾uùH‚ª¨ ˆÄSèRúÚ§0(¯ËAJ³’7‹‹òt!öxz·Ó³vò ÊïÂER§ìü:Ô34F±2üè€ç#í_œ qxÉ9™Œ•Û×UDTBB}*}þË S$¾‘’,‘Nñ|Èž¢æPa“gåÄJÀ”ÏànѧöÇÎĆ֓¿¤_»¨dHfao#éöõdµؾ³°ì¨¦Âz¾÷¶šbÓ÷Ù£o®›”PFVÁøbqÏMâma9ýÅèÉ:¨ÃVP§êÂÂgѵp5QÜ¥©?ÓS?¯ÆbMSðq³Á³QáÏÝ.7Ø3$I3$ T$Ǽ6A|™ƒ™÷ÿÅøuŽ UEý¢qýpLDKUÔ;Ï>ÜŠ¯Rg‚ü-[Æ!ÖáÛéH*¢@}“þƒÎ&ÈÄëQ$O˜Ý9ì±6Ι˜n…‚5ö‚(ÆO¼QÇzè€ê(·(&`óã%[Ÿw¬òZQà; è’ŽX}Ðn À=ø

ÉvH/4„´º‘ÃX#ö^©ëõú´n6vÉñõ†FŒuŽ#41êšÐD|êÒâj­7R¨6²-N–fÎ5½ ùºõÍ&ôwÓ,ƒýu ”õóŒ#¹±ËÇfqº{®ÿÉŽEOÀp°ž6så:-OÝöºrçS/òOá”·þ]swŸFf‡õô2{káf§øñ¥ªcö[ÿÏvf|¾v̪*³F„3Ç<Äÿ3ô¦·rU¼Yáì‡Ý>ÍÏà’9% ªJ˜ˆš­Š ÿ^´Ã+ÔÒTi#ïÞ ?§?ÖƒKa†"AÂ)­ölm\ÛPó‰ÎÛ*T÷¥~7V9ó›±oÜ¿Çöçð_Õ*2׎òå7Åâ½3¹³5Kö;{¶ÊsWil×ÒÈÈV£ô„0AÆԣ㠌üŽ•ôŸ~í] /4ƒ(°;z“eΕ„Ø‘/iÀ2 ß¿÷¥Õ+G¤»™7/ˆq6$9Éý¢ÇÍ@“XÅŒÿ—ö)HÒ…€àáýh!÷¹ü;ÙI$ƒƒ’L0aö¸ÐØ6þô¡ãþp[‚( KÙ{·`nr=RïŸäy¥øy6(T8Ááœ@Ðþ gŸl¥(& ¼Ÿ(h***´&‰Ì¿ Mm¬!ëòøÔàm²æ2q°Ú$xòKóë„EÔ|„Û½”Û뛥¥ÐÀ¤FKóçèäA|¦ìb±³2õŽ9REUóš;Œ¡6ÃÁƒ˜$@4@«Q $4±µ['Ÿâë#•dŽë•Ý͋՛fmƒâÁ!ŒƒÑ¦|÷¯ ¢Bí,3³j‡üè‰çéèå’tyrŸ ÐÁ÷¤4i¯òhéñØpá!'õˆ²æÃZ„Š˜¡  H¦("gœÂ¦H›Úf#A$8æCBDASLIWöÿ Ö©tá’RPUTP0ÀTÌÅP%^Õ(ˆ‚˜""IJ!—Ä|ýºr4D!?œBý/Ü9´«7¨ãXCJ´ùæÓ0õvµ¨ˆ¦·ÉÂÿIæ7ê¸Srèh®Æd|±K ¨ÆkQje.øþäú_!ù߇´Þñöÿ@øôØ úcþ³àgþû°š¤a"Ir£! )îz"Bf‹9æþ…ÅÊ=_ÛÊÒgÄM»ð6“RýLðéžÌí¤Ü,¶5kš:t<µ}\Ô“VÕN>ô?DŰPìO‡ŽD‰'ë`Ûý/îÝÏÄ‹#f66šî¬ùЦµò» qðç"„¦jb¨¿c™nl·¶G ÄÌÄø¯ø‘6bTƇÉùËOãßî\»DÔè8¨C»Q•JÛE Ø™ X\x̆Añxìt]šÝ4u{åùÝßO@쪮»+2,Ã! š ¦û™M¬ß<ï'ßæö|ý$Ô0PÁ& |^(…Q13**]îF¦*¸.Þ™=TLÕS_Ï-ßoMx5½Ñc&f!™Ãþ,˜;¤×Œ˜rú€ç@¾IPH­%|}«ý|§hGˆã..‡÷pvÿ!™™o¦¥Ê$¿¸ù¿¶Ã_úßLÌæF Ì4qX«S¿¾_Ìö¼Ú+ʦ¦U‚û`ëõ^õö§^WÂrFf˜AGVÖFï¼ÊùÀ¶mYbØÆ0[T åßô|xó¡0 ©H¥Q ¡„"dÔÄMFSq™5çT‚ïaŒkf²jÜa‹-­šÉ»p²Üóéz×]` ÑÓœ­Ç‚oЏ]qÆ •'l@ļÀö‡†úÔšu ˜Eõõ‘/ù³Ûœz6jd¬oeMýªåƒ({y‘ÿȘ#žé2tk8$䔟þűºgPíÙWùv/ùœçÿ_þ”±I}¶¦÷U5mÓ׵͛Gq³Ýû(°Á´»‘ˆ"Ö= ña¦" ê•@€éH¿Å$ƒô€/æ.³ý:,*fdßÁ¿|5û^;k‡V^¢?¾¯•mƒš­ãWkç|>”,aý¿ù#ÿ±ºiDÒcÐaïÞ&£¦ ˜>Ìž¡ÄæO’ΰÿ—ØbªxÃÔ y“7ßÏvsÖÊ2þYÂ? h¬~Ö ›ì»‘Ƚ£¡9Y( 5 –]?·”5hS‘s"d"˜9ʽ$Õ@ù¯÷Y9R[*¼þÿ¯A»óa½€>D¨S×&B>x/7sC¢¥¡ {§öT£¦WêŒô?V<óhÄäÉj ”1'ó£Ô@p(®”RÀy9oŒ5ÆJ$×Ü=‚$0÷X½ù¾A4¹­š 5ˆFŒÖ‘5ˆŒfB1aaÈà Dûzß!C;Èú.lTÑ1ÊŸdO:”Ý®gG~Ño¥öÛ’b3ªtaŽÇ¹“ôe¾†!cÓƒÓ³ý…0 w·Ÿ¤„tXøµ$öÝôªd•L¿qQEN ø$ _$¾ à(ð:÷eYX¾9Ç<Óuê…Cöiº¿,uÔMB¯w¿ÞGß/$ :Ê…­/;AøŽòÖÄi13y‹‚ò<Â%»=Ÿnýù:ØÐ€ýqz}É‚,!æ®óSB1ÇÏ@Žñ€ü×q†¿=¤!´Õ,B:cVø=ñ´«ú%;O¹Ä ƒóÀxx`í¶ Î5t‡D¹ç;³Jxû7˜èv”{èý§¼„Ô€÷°Ì$P28ñ¯w\—^nÇ ¾öŠÖP§’÷âs'쉣aU”Q‰4¤yoÞýåuò=Ú hEXEXEXEXEQA( €NÛñ>iNòk̙ϼíåÇÏf]κo[xô¹»}ÿ³:áÉ÷sÞ$Q?Xª{’Aîáh¢ª†wg˜!»vÁ¸S‹S懵¥ÝÏ‚;ó~noæ˜ÄàúX¥"ãôÚ/ʼýóð,G$€ýò}ÏJþ[™)÷þ\^è:ÙWhNRŒœRL‰IÒV¼Œ…Á§ÐöEÅ”¤B 鮘ÂÍo§Çj½q[g–ÃÜϧ‹ÈÆ#|£²õ ô„nÎýû¯»v¹û½;mÜ^àŠž@x ^#À[é¨Ù Ù+‚EHÇc.u7Ty½½AÝ›¾–xh÷ó·Q-DQßñp©€ç`êjØ\N•Z£A¥RtLÏ[teDy©‚Õ‹‡$qqâ€â*gm¼l|ˆqÐ#¾{ãÕawz:ƒ»7›„¹ éÀá!&Kr©:vÙS35–l~j³†Ñ´µ jh¶ÏÐÏNìu²5³c ƒ„IÝ;#[;%¤Ôœ§Ò\ú™îÒ´ˆÒ…¥¤S›X­kÙ¯Æ #^lUË«''$ñxÞº_4åךϷý^ãý(ŒXù ìoÒÖý[µ€ž/D‡eölôB> ¦mpñôYLi¡Çù³Íüca?%7Nn¥ä•)°U}D—Úá„\À¾ÖPØé˜-÷bóòñà šÔ–Ù}ý™Âçù8ÎøY+‚v2uկŚM«{J+mLÌßž­xõý³íÑåˆí¡ø@«µœ"¾ðÁ}Ê^ï7#¾'OϽ îÌ“0Á¦sH ª%È"†CS¡R(0Öí*cý“bÂ= ¢ÞÃFŠ¿´íLþöÆmüßü?ëý°ý«V¥Ú¤ÃTýÙÿg]¿~çÒÔý¤ïsÓûÓÿwîGüóÆJ@¹“¦ùF79DÀÿÈAü"C0m"M‰ö2 \{Ÿ _Fâ7¶+º dt9àè1}:ƒ÷”ý?IOñŒzþE|WKÐÕTßÎ`ƒˆ±Ü,CšÕÖ!5v ’=ØTk:í›–ˆ`??-3½ U m5ÛÒ啯^_"ÇÍþ¬Ðé£9Išéç‘ÇCªÚì04Ï+~‡uÔÜQ«Õ ´ ¬U7üã+ì?£Ëò1ýšß_™Î¤“¹miªšÕvžEF[Çn&}Ñf¤!XÕqQÒ±'_UäàŸûÓaj/özí¬{* sáõåy–§‡áäóû[ÚZpÆñó·y¸÷ê¿r =ý ÒËž‚=ûN¹ÙœÏw0ä~#x 66:IáÚ9\+\S%aL<º3ºïlÎÒÛˆïÄ6•B{ŸïÄïp}ªüµ¨i ®}¤Bû|¯—æt{ì}tçŸå§½Zßz‡±-ë™ý™ÇùÖhÓGú‘ áÞàÞ`³Á<¿çOùÿ½ì¿ïòê¹MwÙïþoùë¶Ûhsb«£·šnñÁ1¡¿šzœbï Ze(Òº•y7Wœ .ÃsdÔæsò5y= šgãæí•d×á¾|n¢ÿ}wGM#.L«Œ±ÒSfÓie4ÿ*òÜîZÛlóG¼º9stý`tN}±¯*l•µ•€Þvw¢ ÷AåÏç5ZËc+9‘©I2;¿9K†„¾È IC÷A%¤ù,v`ÄÔUÙÓøÃ\˜!ÉS_¨‹V+f;¡zFÕfý0ñÉXkrFlhNúuE_:ΛtQæ¦=Îz1œ,7cr¼½æ“`wm†“·¢„Ó³åó×¶¾w~Ë,b1œªEÿ )Í¡IÓçU«*`ˆrs9Îs¥š·rH$ÑF 4hÑ 4Æ™´ÚmƒF)`œkÔ¦óXÍÖ›S§ÔfŠDéåÖû¹€¢U-ÑÄ:M÷ÞóÄ“žxÔE3™p‘³¢"QRg5WÎsÎVpmPQV5Ç9ËǨ±ÛmÏ9œíGHrݶHs&¤x¢ ‚b8–\œVž,É­kO5nRƒnovb¬ÂR¾8ÔÂÚöɵŽìÊEcÙí­ãßc7&ì­·cÃxòäM³e$”´¥»&MîúÛ|Ø`щsTlm¢Œƒ‘ÈDÇL(鎇¬²(¤BPH"ã‰my›êØõ«›íw˜{©Î–p£Vë.ùÖqªÒ-£.úœà°v¡ã·s}¦Šd6`˜-³’‰ÀÀ & ±míbfÄPÂ-³UºÄjn^3{¹.yàâ)Œ3¹u„kŽ)˜ óÎüs°°P[ŠŠŠŠŠŠŠŠ¥EEEQ u¨)µ8Í–1pM ÁÈN+S»¸»¸ŠR˜Û¸ø²îã§×»rÆìßkf¸Ô6Û—«59Ö[8ÜHçV̼ÙpÈZA—Y\áÊõdzÖVç3Y«ÍŒeÞéëDKv¢Ñö&ØK˜:1±¸Ü² »¢V›:¥Ž m¶ÞΤD@vqÄä“gN³—ƒ‚HˆÃ*PäˆEA% ä °BÉ©[»C&Ö‚H#EßNpåêt®ÑÚ<ƒS,”ÑMbâá­ô4 ›u¬-rofçŠÎwªç8ÔQM- œaf‰¨ÕTÆq޵£aDÐE°h»Ú¼ ʼšŒ3[——7µÃR•]ÆQà 5ª™² @¨À¶¶.îUÜ©.¤§%êf“ÊzwP„óD%LšÙá·´…ÔoÀec{ù‹Ap¡ãç¾2³|eD`xÚbò;££Dm(¢eJ2ÞÙ’Ã2ÚûJòÉ)á›k·¢%‰ZÖµyÆ´Ä“:ÓÑTìÛ8ÉÆhãÙuM¡XAq„edøùž x‰8A¢sO‘=3ºN<‡7k ‰Ìà9ELŒd–ae^-©-c5F)Å`šf#©f®tä¸Ö3Mme“g#c8ˆ1o9ÒXmPâ˜T‰Å™»¤YĨq šûÚýí„8–RYb‡N;,±ÄA©0M©ãƒYU3ÖsjZÄB‹¯,P׃ õ .ÙË‚—8ÜÓY¶m©¼"¶DhG!ˆÁn#˜„n#nÛlÆ9òÃk„U`ŒÔG1rÌFã—#2̹q¸Žb9àFÖÛã2Õè# ¡p# qˆä#}œ„oÂÙ $$à°–d¢;fDa½rF·[O¥0~¹²™É"â¨i¨ºªÜ9Å»ï­\Ve7.¢ ‚CrGlÀÂDaKI^Ñð´a†Ã8¦á˜[¥ e0i±¶4… %`‘2˜]÷Žšq5)†v0Ѩ¹%0à )…0±-L)…‡%Ö°É"‰Áªo fû1„  ZT61”`1 ,º(,ÓŠyF`«A²š&³WK!ƒ(4˜ª›òq¹¹¹…bV±É±†Æ`¥ Ðὡi¾6ËdlfjÁ“%É6âí•4T†Í@ƒCƒhnÓ„1-t:™yzšC¢ ². ÕĉKTâÚäEÝ==]*¼>b²å•™PK†Y§˜A3Uç:ÅŠôñ”Fb£)Ö58¸Ž¹¶gfã·nû¸ã30d¸EI+ˆÌãdhÒÉÄfˆÎq¡"'' lê3drêD+V&B&1(4`0Ö`ëLh–ìÅ¥57ÛF4 †ÐÞYXÛ'..&î›mU›ºË4øæ#gê2Ýg\œó–FKbãc1Œ–°¸Å™#yTq™k6y²Ú¨ÛcT8Ö\DŸ‰}½Ðxònòíö§pØSÖùÞú“$%ètkO#Õß v»c{ÈGàšÕ Tð'!Ty­ï-f”Á•œ¢LÝA¼°X<ä§}k^|PÉjã ‰.wÖÇk-Æ(ƒPgvv€]æ4ôjÛÛ¾4ÿĤĎêV†ˆ••ÁUŠû—æÃ’ý.Üþ_£‡/ÐLš§;4Gf¼;ëûF^þÂÕ¼ZÔ+‚jùÚ²) ÷å(¼2yf!¾?^+Üg8m›gÃÉV|)±S«›7Û}ëõt˜D¶9dQΆì=g·ÛÈ=r*„§2QŽæ,K Oeñ¤î¨ŽÊ['ü• ÅïrÁ¥1ƒý #mfWŒò_ô‹ÆôfÓ×õã¨È!ñ%åt£nŒµ{¶ù§fû²<Üý¼±º+v5ù=ºSˆ; s|ßvèõ‹Î¬QO‘P]ÕFÔÃ+$ºióçPl8M¦ÄøJ?=¦=¹cÌf •ÓInÖ0€›XÝÂEDéè²d‹³Ù“°i6ü{Î+·DδKfÖäb©ºÆ˜Qƒ5…Ćp:ðﱕõS¡­#ê{½ë˜ÆLୖĆæN ø5…ÒÃt±5¹ ™ H(¨’Ûç—JsA³¡Ä á[jWâ 2a·ýþ´áí)z‚§ðMá¦rÒ`¼ŸòÞÍfL†SœÜxÿ.Ÿ¸E~j@PL×íröÁÎPÉu,s:ò2n,¨d‹VZùÜ ™ é²êYÏT4nD$ãÐ÷]|X*£ZõoF@…é\@…µ”„Šó(+ϱJ™iZÄ}„ï#)ãɼHâI6›ÏY;áè“ÈDÐè½Ò¬ €øÄ˜‹b3[¢¯®Ûyå.0éñ•ÔÝk/.|oË™Ùàòê ‰Ng¨w¼s›;Ç”E½· ¼9;Ýó¾ó½vß”ùw'ËnbPÅFìÀ¾PÇü:1h Û¼0”â\ dz¤C y<”;¦6àw›Ÿð6À)U•It¬~v•‰¯fú>½:?¨¯È"ÏXŒD}§ð°Ñ4ÿnÿšå‡häPûãêM’bfw’†ù–‡V ¢Z×Q®Â7ð¨C‰‚.òÛf–n#êÞ#˜¤G1–a ÈÑ À’÷¨Iý'ggÀí'î4Áÿr?íBËåCÒÏП¾ƒ Ã…$FâÑ~oË20øìMBÉ‘çý…ƒ]Õî§\p}‡ÞÏÑ¿OþiO£Õ­û³’ÇÉõˆúÄ{[´#¸ü,>ÂiÎÑÄWïÚ&"ÇÍ—Öwã…5"~/äØGàåçä#À"ˆüB8¸{IJZFb’*ªJ¡óËÓHÞyzÆ>ˆ¾á"SÑ Ÿ¥½!–Iù>ñ´Lè#B<Â?”ùØG°EìÀ.]Ðn# ŽB5Ds)>”Ý‚?”Fè#‰óòZz¥†W©è’?M’x³g†8 íö™5žæ×éHEåà¡£B!õB¼ÿÅáÚßàÖÛRâV3A˜isã@ !—œ ,Ñ8ãÓô(~îLìwð›PÉ)QØW²M+óþÄwwIû|“Ã\ŽdzŒSlpÉ·óßÁË B÷´ Œ[Brš3á†5œVovz¥R‡‚êqA3’†à1X/$(——º3C•Æ&Ã9œ=íSXÎr(À›(  -ö¨Ó f¹¤0á3cB@ó(è…5;ÃD½iºÁ7¯{'-šÙ=Ú Ž§k¢8Hy¤#{NÙ¨¶£ºn^alíÇ[`'ƒ9Q t R¤&† dM6£V öSI0hÙ"¨Î Z·¶” ¸p’\Þ‡F·Á#p W’ Ûh°!†BsÉ2R5<’“Dj0ƒ¬³*µ( avÁ,ÁƒxVHÓÁkR:j@ÿB f‘å˱Ðþvªþ¢a3Dž¯(r“R6­Óù_R}°jØñËçåÀCí' ˆ-ëNŒÃ&!hþ;Q°¼Dî† º›½‡X}€7&H¢ÐM"RVýéáyUÚ'¬«-Šº„G•{ØŒ¨žõe‰¥A«4¤œš—^öª>êŠ>tùõÛô1u³N2Cr?Ó°Ë6Á’|ªÕœ&/¿ 9öô9óàÇÂ\[ #\‘ ^w§ÃfA^ÂÞ²,0½Ù¡|„0;¯aàö9ÞM LU$Ñ5EE%ãdš“‚ª£Îb*z³À1 ˆ©‰xŒÌ tX3D´TÄDT“ E¼–¡øàœ”å Ö\Á^RtÓº4r^ìIrEßñ"£ÉûHuæ_ñó™šE±Ð5£ÄŸ®ÐPIº ¢•É2pŸÃJ Ð{á{@Ý»Öxî>PDDDGÿ‡qû<°(.à×{ˆŸg¢ ?“~ýxùÀ‘õ;hD;Û–¡^p»à­¼ËÇDÁHÉi È`ƒ\†Š"¤)W9ãZÄ0 ÉŽÄáŽvcM=ÿmÖPÀUN·‰ÌÊäÍ­ò wÀªð=¡8èçKSÍbGövÈ-’FÔ‰”ˆÿd™!JP”ÒR†‰¤‹©i£D«å ©H‘ âÀ Ü¡’®E §ûç*E´ ìž/ ˆ+öÖ’J;R][ˆˆkó®Ù•Æ !êÞy{Ô΀’JÒp“}†ß™Ôç1Õ6ú×€ûšMzœ{0ÆdwR»HbkôÚÃãîÈ}t–-Ó¹ìx“•šBz!'ÞÁÆéÓÛëÒ2äOºÌ J8h³¬Å’7fúëíBNÏ(§,%veDöxû?nv*ˆ¿)FwÞVæ~3øÏï8)íeìÇ&@H“1À¬À1,˜ƒb2qa`†o†ä÷/Ä~åL}câ?Lv}Nc&‚T¥| ÒuI·#é¿€w»hʽSõoqm ʱDm`¸eCCâqMÒF’霈j–õFÌMˆçõF›Œ1ndÍLË™ŽfYœÃ~­ˆ%öPÂ@tJk:¹|üë•éJ¨„© v@»¹ÐDD… ET€P QBÁ)VË- ýYm#¤uöî“·Ð!ΧðÅ“Ëݤ'¶m’Òß_Ö5çß8é'²Qò€ˆVœ€¡ÎD2˲IËyÔÙðzãëy›ŠCßÖLz1V案>"óRû´±Ð÷I»ßßå{‹™RIi ÇbÂZhŠ€”´ÝÜŸ¡ øñ<¿.¡G®¸àxÃËa;I)]A:a@˜‘  Ç1Ò¤¡© #Òù)æì<=¸GTܵbØõò:×}õYb$JuÆ%*74%Å<\(ˆÊhXÚ£Få i¬-’t 8)ÕÜlgàAõHö¸,ÌlÔJcís„ˆBçåÖ*ODa ÇDüg&8Þn-àfpI¦(Ô‰¨Á‰"Ù/«z7€`M<““ÀÚ3ìÚìÂÎAåó£äúÈ×]†ˆemFR…,YF(¬FIa•YYBkDˆ2 ‚/ëh0k%V3øœÞ}cÔ>ÐãÁL˜&ˆi… U*bˆ‘ªW·‡§ÎPbâ`Ðkß;Ù²C@Ñô i5ÒÒÄ|O‰¤ÿiàà;¿>]¦ÌÇ”›Pa$Mâl4Îñ åà_‘Cçò?úUîU“ôvߪð±”IA²1 a‚O˜Çk,F˜3"ÆÄÃ%¬ Ä<˜]šMë.pš ™0Á#0‘DE`aÉ»7Ð:d–×*’ØÄhiªL»Ö+jßužô5ø¿–£ŠbÀ¥X–¨R"‚Bš€>6}ÿ…mÞíy\°’,ýeP.w GQD³t¤ IE"L #@}ˆf·‹)#ØHäyf7(ð«±&Ö$@Ó¶4‡XcÖÉிpìíÖk™:S)2ÓÑÖç 7˵ç$áÇqOŽŽ·‰¸£±Ë¸ë|IO&?AäÂ23ãö U&¤i­E¤dÚsØïÀóGñ(›Fˆ;ñ{22ÅXYkòç‚ç„îS:ñ—‹‰im5»ÐÀÕÜ/ÕHµ›-Ù~‘Ü5ä=¹ƒ$f›11=³ (ðF¨ újÚ1(-aJHAÈÉ… AÄÌ‹M#`ôR"¶Ø¤Ú™5UoµhMØi¼Ì ‡x„‹“hŠvHHT÷ í—¹ ÉP,'\ê0T9,mš‘¤eQIµ'2gFVÌkN-²¶lù.¸Cö@1 Ìfnnib™©ÈÎ*G£ “#Ò´òÏF!˜»q=¨%4F£ á«‹~‰~mq#N«ÊèÄTYQ±úýžÕõ®×ö±6K ‘9JÒ÷c]a)Ÿ“p$L¨iˆˆ®– Bؘ†2œ?7ÕÇ"oŸ6À¦!Ù•¯fþ??âUþéý¢?–ˆ¬SoùÕêl‘? ýW͇òÇFCŸŽ|Y­T´Æ¾œô%H(Є…ÃýÀ?èýõ‡Eâ•îÝk1 ÄyÃ#«ÉdÏ #£½ÑX\ W°…s3Y*5ìÙÑÝ>KÎÑý<§?Œ8ú?è&Hd˜ $YCâáϨfì )ÕAf2Œ¢2Êd¥£#ùQû’e@ãÄqÙk A‘ˆfÉ-l€­¼V øOK°ÀÅë ¢‘bJj`ÄA?Ùbÿ$„FÙõÏ[1Ç"Ÿø§òžž‰ç'ØÜÝäl’7%üNá"’?½ý扦áà#|Än#ad“ÉalB‰()ZöË’Ò¶Š£ènÀŒ¼Ž­Ž¤ÓB0GØ#¨G9ë§iQ‘Ð#¨Žj;¨·þ6xÇÆ³b–£Ó¢$GêvQÁþé `RÈ WPÊwRá ’Ù‘ã°èpOj{X$˜#Ö"ˆÁ¡„}ÿ¢L°OY>Õö½I¹ñ(]Ò›G¥‰ë×l—é@Y=Š1ìð_:+¸š¿÷ëÕÔô`ˆ¢¨Üa(f4£D+$´‘E’QSbB‚öbÆÏðD_†RuI/v±ÌÅ#0"@2ZB“ò¾·ÞhÜañþqzÞ·òû/K¸‹ °Èõ:Úµ0 “ˆÁ€ÐÈ0oèñÿ_¡¦T!T~NùBÿeRR¤Iæ‡Ê €ocÚvÁ³ÍoMJF ±Eõ+m¿HaÁqƒµ-ó²e¶¢XhüXWp”#„?<º…5 {É8̄β2Ä#ð„~!?ŽB=†¯¬¢~¾WˆzéµÙöiŹy±âN!]C‰«QûËS̆ @×ïýæŠ`F’cZí½)´f b9H8%¬& [0ù½[kdÄÉ´ò³*d" 6˜.@Ä-KS² 0PÀ$œcÔ»'´ìÈ7šÌÀúu©?5º[32‡#1 Â2Ħ()((j,pÄËŽâ5nœ€£  ²NeÈMf:“$ÔÖBRdd´…oF¢ªš-fo4Ck ŠXÅ7`Vƒ‘¡‘¹˜DP!¨Uæ6ÎI¨ÝNFU™–UAE™oQUZš ÔꨊÔdÜÉ‚çf¨#F@oXÛÞµ1FNC™™5FaŽCAEPQƒ.NJddÕY™ Ï=ð6›#‚ë¾Dô¡5†x—ƒïÏò uüývðUNýÕ íUÙiXÓa׿“Pv ¬PìJ î·ÜWÑÛáãÖiúÞƒÜxŸ¼ýŠÖk“‘Ý´3³1ÒóŸìÛh€¡HíŽóÊQÏ·ËÖ6uÏŠðææ#‚ãÑÏ¢ÏÒ™3-wô|ë*c˜<+]=cöz4 S3”¥äA`”À,C!Aø\Ún±V-*Úá)0EfÏUž/«Žøèý©4܆J•Ui‰úÀ}!æúûGrPK#JÍ*(wN,HÊÈK4ÈAP³*þó<Ùi¥ýy–Èâ/ ¢"df€ƒ CêC1RI5.$9zf@Z!é¼`5 ?p{Ð{×N$4?ÃÍÞ‡‡n…±—e8£ù½À$»¹_(à[ù^‚üî…Ft¨ 5¬"­;1Óš4A$.h1tK!Cd`@æaQVS¨Ò´A“:¬CRÁ6_1Ð)öƒh§*+–œ¬¸#‹šUÁ‚:ì±´!dr§ÕKmy$ÐŽ¢:ˆê÷ˆ N`'!yðð³Ä/úºð{çé—[ªjª×Ët¥+|~¶I ró ]/ŽÇY(;Ä™" ±uvµŒò‘À€l'´ì1d“„—,«,míîö„{ÄsÐ`Œ¹ô68&›ðhG!ˆØ#`{ÄtNþüT£ñX°¤‚Àªâb˜“1`ᎠQXF‚µ< £±c ’f°§395¤¦a"&Ø« ÷MÄCÀr€ÀÞÈiDßΕï'rí>DÅŠO]˜¬¢Ñﱤ¢Ä†A™‰}øa=¹˜zIÍDœf$CÞ —š„ ¾>˜:Û}1Ä ÝÆ@–ۇ‚™j­‰çS’´®K$<úÕ9xž^qj˳¯r#%zéíë}Ä òÚÜz˜âÍ…È<¶x&2MÊüŸ9“ÏIxúcV‰ò:Ä”åUÃÑ`ö v1Fe\x$3f ^6bè|¾´ý©â.ø%QΫác".° h†kDéÓ’aA™Œ.“ÀÉÔ©]—à üÿãÌÄÈfTícê¯ÛZ˜¹‹2ç|ðZðm‰ˆ3"YJQbêÃåaê#½ ¼šP¡)B$ìSŸéÖ Ü.ý¾ÿi™¦½Àü铪¹Œ¬×àÂeðÇšx”h)O$<íA4àhØ@LÑTÇΆ}?îÃQMñ .?nÓ´Œ¯ôf‡Ö–äü$†XI’µö§´@1Pã_œ<°íñau†Œv™)KÞC*’ÂT¾¼s1ˆdu,¯-Ä!@…„¡@Ad´£H•IAIÌI2]ð31\% hŠH‰¥$–‚!îJd¡•B- BÑCHÞÔs”RòÈE5×#{ibb†-TU--´ÒÂ!­ò„ËÌLšŠC’÷a€.¥"Gì‘5jQ‰ûà¡É“2ƒ˜O–†×¯„ë0Z\¸Ãõ­å“D´1@J§SæŸÄa…¨Ÿ€S ô‰‡"Rĺ„I]¼8f_—Å_«ŸIòlä"é²5˜á–„$¬ëHè4ÑX2”¦…Òõóìü¶dcËo¾SÍñ´,Ú1È"%‰0H?D* FzLQ£Ä‘‚’Aªö´¨ƒÀÆäi¨!ÄvÅGj"O ¢XÔÀL!›’(:Bè’Ëcd–`ÑQ¼ÍB$‰ŽY…Æch(²Æ‹ƒQHé( B&b)¦‚‹b¨Ô—m±”µ¬-Z¥‚da™Œ!ŽLµI‚QRM,Í&9˜Baj4ƒ™s'Ù$;Üy·ŸSºzhª1˜lt©“VB,(:Ò¡¨j„ Š@†¤Žùž(ñFÐ5KfèN²C$ôøl†¿G³Ì¦Y´žž—~Ù!Ä}qàC¹íjûÁ1 îÉ´9J–Tÿ/…èÕ>‚Æ7áµ+x<Êó£Œiyãyô•Qì°ØÇ,;qÐAMLûX¦¶×ÙÛ›µþ—¾;våÐ3Rr© Ûçh¶JöÕ©PÛîhÆV„bª0!êàÅÃ-àaÐq&A[1]Hñ¯­ÂÆ›Ê 4Æõ¶LÙ$Fä Sds˜oˆLyÉï¼ ÒYÉk6qª*€ƒŽÒõ)¾±bQÜŽ¦HíÎA’õ†Кn¦@åë€1"8°¦• ©AìÈÒ“8ÌjN AÛ‚Ñ=°DÙåStÚ¨bÌ•±— ÕÏ XKdcC}8TLBBmiGF¢Æ‚Š‘Æc¡bÌ/®B:HåH“ҫɘÝir!“s”øØzÅ)2é‰hu18Ÿ2wÏ9àÛ¥{Ov¢]3SC„¬T[Î5|I®,³L£ H­Ä¨­£žüÐQŒi&lpÅ”½Eˆ‰pÞ¶ï©44«¬ŒŠtO<«ŽmÖø?ƒ|¨ÀÝÝðŠ•@‰  ¶ ¾ ¢)þ¬MPqcPÄ¥» ïÊP¾¢<ì@nBàljÉðÞ©(¢”– ›¾°ÑÖŒj<7 T8Póß,i,i&ÅD†×#QßÇs¬6îñÎÉÇ^«9Ù)êRѽ¥‡rŒd5¬Ê˜=à†ÀÜÑQvkI„p×_Ü¡¸§+áÏE.y'Ÿ¸ ç‘b•‹—- …ºœw)‡*2üµøÂ>?«øÑ‚;¹ÿA¾`1 €Ç>éÍy&iöKàä?±ëSTò zÁ´£Ö«.Ú8ø®HêHô’•Æ{ÚH…†Le¤uMö>H”Aë#èø8m4ÈP”Ž’gLgEP €” ¾çŸ=üxtÂíÃ6é•8zS;!é\›Ë ?¼“ÑðÇ–"Vžl©!8°mHLkXÖjE( ½k©£tzžŸµéìMþ6„d#aÔö©5MÝn#a"ˆöh#¥ùdíg e¦éåöz3Í]ž¦>4Ë»ÑWÝìÍéóˆ*çäA-U¶÷LiDÛ©†ÄË@ÆÝ¿á[‰0ð°:ª‚”­\—2N‘”øïäº@âj™ ‘"cë ð«…’BHI7±´ÝLÌäc×ìöqMâGê1=£*¼çÆ„<œx‚£aìðzH;Œ¶àƒÆÌ¤Øä7âǰœ ª,c=è4È}é aù•â -«/>ë­ùéfü2m¢}AD~2Sö›ˆüb?ŽÑÍ6®…MO`Œ"I7ÔË.Ǿ‘'Ê-¡T!)"% H!*!J­$0Ñ @$Ó,¤DR ˆ²ÐP+"4!BÄÌ„ÈË#ð=l‰&êªþ5ÍwÀÞÀ_¬*jˆ©A ËÐ`AJ-èz÷)áy¾†%³n±û0ÒÒZRMShL­6YRÏ! 3ÿ{4”;Ÿî4˜†ÝäÐÈÿF!¢xp`Ì#Ö#_Y*qY$¥d¢XÈL‘2p£ ò>èvÂÐILg–¤%KËwƒMÆ9üAä@ÔÉ\¿iß AÑ!¸(ŠXö(a“€Hº„Ôôf A,›< †↗d…kt¡'¦4?å¹1 ¡ .2ãÔMœe²2f`¢f-%°¥2R "‚£·Cu(¯žE1)Òkæ0Â+œÄ±¡ìM9yæ ÏS,|.¶2L»T1B÷Ì|^œâ¼kP‡a0Í·y°ÈçDDµCV¸²Nh'Ãéü¨GÖ°Š#`ë¢GÅò>ÒiðD`ŽB9hED`ˆŒ¡€¿$þ/‡½}öª?ö{L+¤ñO€':ÌÌʤ?iÂýŒá†’:z/Ì¢K)é 6ZÊ¥­žqÿ®<éäÔg ÀC™±d’Æ [.aˆ×´±(B”7.@öN$l²ÔkS:³X2K9åÅó¼J@ÑæÔ>‘‘!¾$ËIl!u -¤¡ˆ¬yã9w׫gõxŒ4S3M-#õ±OÑ8 ˘JWæ}u ã›Ä×8 €{ &QÚDû쎊ï“WwûÍ ý;¼¢iœY(|†±GL¿Qi!ÿNn”äñoãn#R©áó‡­À\`h¤(Ø÷F¸ðO‘ã*p¤„mʈfQ¸g¨Á©pÁ¥",LÚêªyÌö:ñ¶ü­jìs ²ÀÂFýGŸ¬àuáQ>rŠh©†Z”ÆÌÄÃpdÄLvÚÅDNí3I!$°šX°¹%¯_µ¼*;:å-n1lI‹!Å2ì†bådX©D}ð»ÿ¸­”X#}â?(Fó¡(ø~Ý¿âÝ:ß~zoî<"û»ãÖ}½#Ôgl9¼\R áΑéÆrhÂ+G¿,M ×x~A£‡"ÔT.ÄsœiÖŒJøÜIàO4—^x=JC³ZhMšÖ®(`gòD V:MÕˇd40’çgy“|e¶”Œý3Âáaß¾D™R N(®t·B3ɸ‹¼9aŒgMPM›í:ÈóذkÏwÈÀΈ\·ÉrØ ·k-•3´±©5šÖuã {ˆ"–· &æP«—-)Q Uª§qâ"ª-ªåù1pØŠÉIAxž5¶ÉÛÄÖ˜]†ÐÙõwÉUÔ÷Ô›LÒ™ƒ“×5(§jG°É'NyaI–9ÒFÃö}k²¼½K0âºÐ&å°a´UbIDQM!J¯<‡Xïv{Y×^3¾(o)Æ Á†­:ðî³{ª#3Dó·]#NEŒ‡dšŽ.Ú4¦Š°:Q†Øf;ãv—|€ËydÒWܤ#Q¿t2¸Lû`݇M„ÂhÄ 3xÔ7‰Øá…¢zÔÝ‹VAµù‹-UŒXÂdvR¨Ð=¸¯#Št†Öû²èKÄØÁ Fã—.P‚RLR8ʨ°«IC%Ø€rŠ•˜`N¼±šF„æXŽÆõ$Ø·b&Þ§Æâº=d òeH« DoJzûø6ôfe$TÅ,Y€a‘’$7 ¶–Å<9¡=9@Ï*Ù9ÏŽq(n26¥Ð¹)O‡c0kC7k(…ÀøÿݱX—šè2v CzAu7­Ùæ>Ï"ˆŽnZxºYG]M‘6JÉ2<ʤ©»8Bî¸PÕm°Œ´PÈ:Dµ õ ôîÎå›+Áxr±×@áSâàÀhdÎ÷o˜S† qÞ G!>•ÌiνžL𑣇å½ú;ˆœìnȉC¨ ã1VðŒ­sÐ&fœ)F•(Ò¹Îb’O}D´$ËÖ¡-Ž–Ø(¬âïÀÏÀjÕN¬Ö2c9 `äŽ5JȪ!#P¶±Œ«p€#³Iº#de1¬ ÐÐê$L+$a…i´:GFUq˜,3-i]#! ŠÉ¦B$u(d¼Æ„-6É5:„É€-ŒkX@¥’¹VNf)’Ä™„Ë58 Ö$#¢H PÐÌ{(wzvØ·µs®÷‹|.Và˜z„¡j"Õ,k<â+oâ}Ø«c‘­¥²9 hÁÔ¢•iM/ê‹„E(¥4jÄqpY‹dvzì¦rYì\^WL¬Ì̬¬³,ÍŠùù Ï ¼ô<¯‚àÃì 9’¦OGqYÔOÑ4/޵JJ´2Fv¸"úNAË¡÷Ï)ÇŒù|»!í¨ŠoØRR½éˆ`†"^ùÆ÷ˆd¨D‚}ºA„hEV$$)ÁPâ5jCAaÁá$Tô~ ô¡ÃËÀäO”†y` pÊ:}~'À>‡ïEúGÐ!E÷¾JŸJ4 ‘ò€Ù‰’¨žN­Fz¶fʱ ñ²dˆ~Æ2Jm’!¢X°F=>·›Ö…IØG(Iï’T í²¢™ ‰3}¢j ¶S"‹$ûâ%ü¢ ´dëÎÅÔÀŠ’“°¹˜‘A?×±ŠU•kísÄ±ÏæÔŒ¡ºHôèí§lQCÄŽ9†&I̹:¨ža90±Éˆg‡À` Jf‹* ëùÝ:„ R¸^޹kº* 5Ó)™çÜÁ}ßMø~oÂÇv w&…¶Ê|ˆÇmYÁøcýÜ9à§>ìZ‰eÁº#}ù†òî?qãÀáçߨd a/¨ˆ–³»]#]áˆï$ 1ÄW±H ”‘¶ü{uajàèN‘Än›¸ƒPpÇ‚¡­ °œ[Æ$ÙÝXij‰¦šKl:¹ Řüd<‹¤† ?)4ßÊ&oì"WN8)pt8"£Ê|T‹c».Ÿ¶TLãEA›ð¯‡’Šqný&Í=EXˆà_.ÜCU2 ۰׃̡„Âì#(.†â57L›y† ,õ|å˜åAWÝq ƒÓ@,&vxžé#Õå 8òã3¡öÓ#ˆž\Ô\y.6pÍi˜¿Åp56™›Ç—,Vs}ã"¦ŠXk|4`Ë`Ó:f7“6ìÞÛ îÏB³'×,‡; ø•&=(K$UÚm‰lÜc.4%§qð>ß®X/IÙ­vxégèã{Uß°UpÊx²ŽýöæøÛ-€LÓ™ðÓ¢8Ö0ùÅ•T¤$ÎÓeÁ-PP ‘ÛÊ\“ß=ãï7ÙŒ±{LÎ‹Åæf‡uê¤ÃV®Ë‚ªðp[ø ž¡H‘ì3ÌòDd‰ñ‰ã¶jlÁùÏg=­\Ī¥ŠŠ¡v„3º”È `Š!‰€#• d‚}n'”v¿ô{¦$t±¥æé'DCq{>VØÄf5è‘Üýv c3)RTž‘÷ˆüâ?ÎD’Ô²o°!À#¼G4$”GŸp¢?@áÕÐû ü)위uì#¸F„v°G4#a„p#EÀ„l#qÄ`GçÞóŽCèRIåéhRoåR'»x„q»$xdµmdCU#@ö’ûÇM{÷7AÑÙkn))—´kÖ ìTO”=˜4‹A9*v, »ÎT‰(zT 7 Ç(¿3Ë’þu‡9ãO¦èÙNïÁ¼ª”Xa1R(öýݸ DF¶Á/é+ØŽ”ˆðñ‡Sá¢$÷@‰·‡àpo pnp.9MþÚœ˜;pMaS6Ô܆4PH•¡¶n, eIv(æ&Ƀš«öÊ”'ˆíWÏ"þá„×pøsHuã”|ðÏçGꆵ6ÁŒÈe°¯€È ¤bO±9Ъ‰¯/?!.[ŠãÝb-f1Aˆˆ ~B„¿0`fhªÒ ¼‘ÎÄAÀé;üißR µE,ÅC#F7žlÃØ]µ”'²l˜6»m"0(Èä#UûE`ZÉ\S#ˆ$ øz´£âÕ3¦F!Ý'1ÔïI<©<(&›Cø¼¦*&  ‚†šbI"ˆ7ÛíNaÀÒÈüIØïO Þþ¨bØzìo;r;/‡Á´–y’k[Õ8ÔÈÐj^´f“‚M3ÁšÖº… AÅ·ŽVf2WŒl(Ç÷I¨”cÏ^ÀfÓcfEnÍ%³OØÙÊHYe{È4–lkWf1K3Ñ9 *žöúÕ–¨'´Ûp¸†§² " ±]Avu}"þæñÿ/ðìâñaçy”ˆ32Ó)¨pžHŽÇ âCpgq7j±€a˜r;ÚôŸÀ¢Øué¯qmLI﨣úŸ9]ø‹±ÿ˧xÛ…3æýï¨ø 'è ¥¥SË@x/½G ã·<—Ïôs3Áó»Ðw¡ã†  á ‡*{é Ç¢zŠ‚©ªP˜J ˆd‰f ŠT BDŸx!ŠhŸÔΛ=û ÕÛá,œ¸¦\S.[näãfBF¶G6çzZU@k‘p¶ac=}ÑÄCKKrp]P)€‚º,Cc£ÞÃV8¸a]q­ó‹ÌŽª£:àJûpžÕŽéµ²À*Ú¶Ûƒ–NvÎÁ©Ã@K¤;è1‚¥…ßX:‹ÁòIDÂHÄ…PQ!Þ¦ÛÙ¶3‡4'y› ÁËñ’” ɘ¥% Eê]äã %§'0ƒLEêilLr,s ­ e$HA ˜§<ÀÐáa‘™˜K„Í„eI„xq­6Ì"‚”¢2L!ŠØ~õ:èD¾OPé}Ò1)÷mAìˆWæ’>H[iFP¢a-"DLPh:‰M ¡º(`ªöÜ,¯žEà”nûŠÞb¨ÿD›œI`™‹âËLõ’ä¦Áó”H"ŠB†ý7™ú3$‰"JQÿ<[›ÆÂ5m~Rø{#êUóa™‰´b‹SÃ=—Zú¥f5ý|—cÏæámJµ9‰§f·nÚ¾ÒOð ßÚ1@ÀsÊÞÇR°@C!Cð™<]œQÍfp‘ˆ/-v„ 9q]öøb£bch†hÌJ³†ÞŠN¥EÍ’`fK.tìh®ÙØ6¤Ðw‰G°†%ÎÈ¥{.J’è0eÅÅTK¿\òMhF8+cum”‰áhÎ#M 1ð;pe­ó‡Ü „Ü_|´3ŽÈ¤0dŠBñ q@²L8’ŒL’U GU†©¦`Ñš\4J°{X:3r%˜á±(YC wv£"[H¬)R–)GY|Òέ¦ŒƒOj¢k…ÄÛ`ij °Ñ€!5É•!…­AÝïË5³ÇÃQ¨[V4Â>†Qc9p!û‹¡-¢18—h‰`lõ™*llŒ A‚l6ýªíSn>>[¦kc˜Ø (s‘´ë»ð‚:xÌÞBdEiŒ7ÍæŒ@ÑÇ–ÒËj¯Pã‘ ÞhBšÚpr`Ωša{=½ÆØ•êƒÐʺ!âyhÈ :šˆbJ¥T„ñüðP<‹$6³r…#ô")d¡JŠ)`bözÙ\›#ŽFÒ¤ƒ Jë6-Œ ­<ÇÄ4¥ELK¨óˆ0DvŒ’Q`ˆ¢¦ h–&Bˆ ¢’\Àq”*¡â\*F–"ŠE€‰JŒ±îˆòvo ÷Xý#ÆaÌqÚÒ>2\îÿŽý/Á<œÇAy¼?ÂU˜J‰ñöD)¤`M 1¬U+žD££Ý#ŸCz“7}Év_ø¶jB­W7Û7ièÑ©]ÎDfkDr3#2˜Âs ÎA:Íf”DØÈzê'Ñ äLú+qbâ}ÞZ“o•&ÜbP{ƒpÔÑêÒl|?â ›RÁóHJ½ m¢îe'gtÚJ%Í)I¾òÌé,³Qœl;[ ½RÔ­‹–¹ãw'cªp‹Ã•X‚[2ÑzB·$VŸ´ÃýŸ¯ˆëVKºb¦PsFOŠkKœyù7Š&ÚAw ³6§]i6Ä×>âU!ë¼4^YbC"5;€«©ª-à+9L4ð&¢i²=ÜüÒä\ºÃC§T<…SÁÂh‡9ÐúAù¾F6Á&’¯yšv"€[⼊õãŽW~ösÞ‚?MËv)ᙥ¶¬³ÃºÏHdÓw;v,sÁ;;bÁµIKø£‹)W0"8ìÑIPá @R¥ $ALÈ´‘2,=¢ÂݘVxb˦²[¬˜ABª’_‘ bºšD<¾r*Ïæ”\øþ’EŸg‹"ASÞ˜ Ä͈À³2 œlÀÀl̆E…ñ0ÛŠtšˆX{@â©àó÷÷­?s.ÐDäÊ)Ì_#4ŸÔ² ¤#}jââŸÀØn·Á¤9âýPéÝŠŒ¿9¡Où.„ÒÀøÄóúŸËŸxð$ô®2Ë-{þ#`Ò@˜ƒ¿©Á˜šO¡û°ÁY$°¤”O(1 z7$ýV*–çArôÔ|ž^Í8‘WѤøÀ>Ëâzo×-±‡ ¯AÑç ôA”B©Hd¥j¤¶^Å>Í”|ýFˆå±'¹=ÌNïªÈHô“5ñQÊÏxu“6©Þ»£ì“ã_åSx‚‰d a‰Q!ŠtéIÇ» qÄPȉ’â Êœ&Nf!ò?I‰†a(à›¤JDä¯çúÃ]AúC‰õ•9Ro@d(Oíj<¦ H€%à+ÂèƒR 2¬ÑSHGLy‚(ëÃôö®µ©]‰—‘DªnË0_ƒø"Àùû0µ.6Y÷Ü;$é‰É6Ü~àÜ#÷¢>Ñ#ò¢(Š¡æøòëÜÿopõï´Ò;èþú–Ȥ¥{ïH£‰c|iÜ›³ì°xœ() W6™)Ç»#ÐÍ\Ä‘É)š M³÷ÁYOý‘ôÌHé^®`1‘’K„®0™ÓCe%Ó Œ(A% –"‚³ ©JL J0†’„,ƒZÔ¦ŒÀX²LeCRd&,ÄF`f%Œ&®( “Ñ#’¦@:eÔFÄÈö¬»ÑŒÖe`äR“*du¬)2H„Â]H™f`d)‡±ØQºz erA7iÑÒÕ‹12d†™G´¨žpb÷°%¼íð†QË0ÕH-©v° “%0µ!ˆ3+Ç  <¥sûöŽ!û'„â@2Ÿ!ª÷N(EOõÙÃàrãRcIERæd°ÛÄ:“ ­ °M¡ˆ­ʨÏ×õl-Ñ’åTNoÄpQ7ºÁÊHj“Dʺ].ØÖ!äeˆîP¥q³a¡ƒˆP8!Ñ3 a‘Ò¹R a %ä PBÐa…ŠØXL¢+@á(¥†#„ ’™S@ä „ „Ä1JaS Ù‹BÓ„XdX2d0¼ÊN¡\…Š…iHW$0rZ G’TÔˆR. ”ЪfѤgh3‰Ä:E\³·TUv_ir+QmÐRæwZ-ù`oà› ”ïüøw”æ™Þb¥iV™zÐ}çôô„Q0!„l"„hF„`F„Q=¿Ãìçþ{u¬ëÇÚ†ü„lãŽZ΢:x½[¼ãA¢ì.Kt|`$fÐ rD`Žáàlõ*•âú³ÒFæ;îÿ ßzü؆§‹‚q@ƒ¼á±›%›aåþüFªo¾'ˆGŽh"ˆÁDv‚4i†4b¤÷lI±±ŒIVÇŒ³Þæ#íç¾G”XË‘Ký¡ˆè#B;Äp#l#„n#‚=Î}^§/ªÝzíðÖ øûnFô´qÒHt-©YÿFt»¼qì¤×ñ,*¤%À솭’Á ¹ÒÈ=‰‚ õj`<‹|°ö§¶?Y‡M$Ý׿òû!Úúy,~—ìaÒZ“«ã)“ÂÔíŠNDÒm*è5ýðÿB…vûaCF‘ñO_OGqýÉ]è6D–Hü¶ÔhªH)¥¤‰p5Tá¢^ò/ÛjB©??õŸºjš*‚ù]Ô0í…#sxÄÂ4 І õRĤM$3[Ì„ÌÈÖf˜K²`ÇL€j²T}ý‚?Ò.pü±Ü;˜§¤ý:\"U•&X©…Þ­;u›±6±‚ØŽÌ"d… QN@L¦DI0HBäM…"ò/J0öÑ9ìÅtRfaÚBš(Ö;0±Õ­Df¬CÔŽå#¹=- Ö²2ŒJ ¥ß8Uu©pÖ›æB¶:Ê5[°+„ ØØÉyf9þŽtz|¿1ÅD×uÊ/¨!%({c¶ç™N`a $‘rVTK†…Iáët;—bˆøà: IBòñâVµš—És¶ÀÚ̱Êï™'UŽÃ")¥Ž¼ùH­AÀjE‰Â& µ9w«—9Â;³||ñÄÑá!•sÌ1YqS1±0Âc2Š‚&i–*FžjrìÉÐÛÃu‹Ä~/ÅÎs‘DæG““ícÍLvµì¯?LÙ6Ã)u­F’¨’MkKa!bæ±ÌXwš[ÇðOpH˜LØ1;‹Ðàb@Qfª®”®À2EŽƒc¬!!²Ö˜Èdy ѧ ]w¼‰÷"r_c)@î€j¥~RÈWôFKCAÄPæÄ±‹ _ÄNwãå½#ß¼ 0ʉ¯€{¥•|Àz(¨‹g¼LÔ&¡]H*a Œ,›½æ=±³ŒTÄB®[²np§\Æ,UNø/úy§m‹=äQTèÅè J°H»SÀÈùUƒŸ|švwRHz¬ZO#ã9'E>‘ÙTGÓüÂaÏ‚t>i®£o¶÷,ƒoãþÒij‚u? 1%¥"x$b¥bçÚPuaŠ’Žb0`âÕS®tÃb-£,.ÝÉV#$²:uáቂØ.fa‰ãNèв8M#uäCtÙ£z7-YVKHý)òûRU%"—CǸ}ð ŠúᤪvC–2Kn£iRŠ¡¥(VVB„ª"¤a ˜†ª… WØ€îæÀkÍñà¼ï<ݧå?›Ñ8¾Éiª8Ìw¼L‡üâ»F’!"öC°¦Õ0¯k0ÔU«[,cžL¨Ú˜²jÈY!™–%UDDÐDÐ3ELÀRKÌ%TÁÆM:ƒ"0Ìfe’R_K.- ATK”ºc3‹m³2Ã.úÃ0ÂÊH“#™ª*…©ªŠ©B‰†œÌ¬œš,À “XT\—#rº½“žŽ¶på–ÔÁ”Šôb’„-õwеØ=ÀaTLã…8 NôY’©X¡VSþšh®@mPýänd,õ’œ,AêòѳŽg— Ë’Í”WˆñŒn‰´#ûÏ"ŠSwŽ)Ÿ_èUU¶Õ–Ƹñçç|Ý#ÀQœœþè ˆYh€“æSOM‚S ¦Â@@ÈA&U j;•ü°9(>¡ú†úáÒ”)OòGsÅ~=(vjbT(F%P¤h(‘ jhiH‚%¥X„  ¤)&¤( A‰”‚•¡J…("¤iR„""H)F€B‘¥"Dh@¥J”F€¤ Y‘JAbª¨(…¢”‰F…¨‚’©¤bR ™ªhh•¥ZD B b&R`€JQj’%U)(P(E‰e„&@˜T™’>2™1¥%"Ò#± €Ò5@3R¥BL„ÓD”¥ÅªZ‹BÐZ•mYaQ, É 4Õ4"E0ƒ¨P‘)0HÓ0Dµ¥°´*h´e¢51+H„AE "3B<ôKRt0%D–J ¡¢#ªœÉ[›úþ³ƒr#x›¦HâýHÿf%=%h1 Á•Ц…  ªÀ6:.]o ÈDDJ*žp¡0£€•Ng ˜¹=÷ ÜŰiOh£À=Æ`‡¨îŒ*bu4‘$qÜTä=AÇTrûÚ•€)XXGL®ô—‹ÀOx}¤¿|<¯•Ü'¯©;üYØD1HÀ{LG¤Œ‚©D¢b¦ˆ(¦¢¢"ŠX%¨Š`ª%Š™¹¡ýÏYElóh(®ðN’@« PAî „¬Ú2IÉ4’4Èx¡ñNÍ)ÈÕèÉÄÍ.å–¦ù‚sÆèg´’4Tà¢ÿŸ‚è<Öû;ªbh¼™‘·N¬÷¦noT^ÆÁÕBÙ‚eðÓ™fbÿuå-¼„nHî’ª¬-6ªîÔÒŽ÷Ûé#æˆü¾ì$ pAü´:Å 5D4zK!Äý‡‘5ó:½o9³èXÈ{¾ÈídU ,‘ì|òCÚöóêÿüžž<ߨnð=#õÛΠŠO{RZÁ÷By—µû‚ƒ£ ¯ÓšØŽÁôßYZÁYûœ{½D ´U óÓõá1{Ø52édÃDÀe„"$¾ˆÀǰž3O†pLØrz3šËêH! \Z Þñ,¼S‡˜Ò;‰ÚGâÖra¬[ "5¤UÅÄ2øs+c®|…¹ÔÒèo”§V¼'Ø™€0*Ý£^šuï †­tàN·f<äÝRE„oækCöKºq^wP+GcædA¦6€Æë×™êÞ¡ø~æ¯mLn_·éN¾…‚—7ûßñZV¼ÜßÁÙ3ÍqÏ ÔPUK’^øôJ–H!©ÝìW™>ñ‡`°év}Á–fÍ}O‘Ôú ÌĶ_™û¶8=}º"^£H‰†!¸ñþÜ:å(Dà^‹º^â¹¥Mìù¦ÞQŒjH£ã$Q0|çÐ+"²­äò)ô ÏŸ¯ëšš7„ÚY œIˆÔÔªªð ºvÎs½×ðryLë´Ÿ¦_8 ÆDÚÓÛ+ógIM“~m–°sÆXÁí~7üïd=HpåicØ?t,“¨î®ß”íu­hw_[ð…Îã5!J(·îêŽP{É!$ppbl$aëûÌI&QŸl‚ý(¾¿y3U$S[C;Èö%¥w³ŒvÕ…à³h! @‘$+$jÄ€¨ j¢©1‹2$‡³©ÊF¡ÌðÙÊiwŒ†»œûÎ}F€g\ºŒã£_ïä‚#Ù`H•Ä1Å„Á`ûY|áë"©hF"Q ŠNÌXЙ¤ð(+ùÅŽQÓ㞞Ъ¯0—T:𙆠%°ácà0VO4l n¤\(X9¤ Ú›eH€*Asº¦ B<ªV-ÞBÓ ¦Éc+ Ì ;âåhá`0dTCÅo/Õ’êkw7inì ÞJ  NNážLÇ‹„3xƒÊ¼ñÃ,e›™œSsLNãN¶ØsÓÁMª†´æhŒ™x)IØg×¶p\FHâES‘nŒb®ˆ#±þã´å¥P/”Ÿ™>ÝIuò‹ióß™:‰Ô»Ôxù-'{ò–ñ›ô˜(òCáp÷¼4ÚÝ›èˆ>¬Ó0ÄCb(m× Z”P “סK…FÔ6óí¼\]¯Nœøs(2O¨„înâïyYÏ!c§y’\Áæ°cÐÃøo•¸2 ñ†ë²éÙ: drB)eÕ€á¤ê´­ÕiS¶‘Ifÿ’vàŽÝ~GÃéNPoRU©A÷TMO•+6ö5ýV:J)£3XŒEQ™qXTˆ´‹–30L#þ«iŠ •’«aPºÇLm*Q’*õ‰,H¤"A„)Z)>™pˆ”d`¶a‰)JËïx°Ôa¬MZÖ R™˜¼ïh%–âs,B,a˜;Z?—\ m>Né6UD¡ FBÂAZŸÜâlTÒgMO–/LÈ”31hF¢ ;ÂîDö ·œNg«g&\‚ðÒ‰²I¨VfCé=ÌÏó¨@yl£¹eßÐ ʈïƒÀú]Û¡ù¯Yô?GÉ×@ÊfHLÑ*´ódèlG²”ø †bÁRÐU˜Âb…Yb‘-1#ÆÚýþ_—àr$UÌäŒx_›N(¢‚,,¨k3‰"¨ÕÞÑP‹mŠGŒÃ ÁÔ!Æ`Ñ4UQ5²30\’P¨d©B¤˜ñ¢ä•(‡yÒ>´“'%ÆFˆã¬W 2( it:ÖQHBÐd¡JdRä™/þ™SDºPϧXé{ošâûÃy>˜ïV祃Ù\Jn£Q©É°¡­M*`o5eÚ7 41¶1€“"†Ø©Ð¯ÃäþŠøŸ<¶úKz›îŒ €ÆPûŸ,EÒ¢ry(‡bé@0™‰ÖI3š’@X·=ÛzÁiav{wŒN”nƒ‚iñ¯ð@õÓrœÆ'âè6fÐ%(b‘d‚OÌ=ŽC¦PÿÊŸ±a_(ý’9hÌ <‚tûÏ«ÃÕ®¸( (e£¿ÊÊqP6àú±À›Ñí?;ÑÀxÊî¶H‰† ¨û £òGºþˆ(³cL’‹4e’ae™aƒ…D„J¸Ø`‡a!M€Ž T„«“0—¬ú~~0ö0 ž2KÊ©}*Y„÷==1ÃÍ@x<@èiVŠ? PõŸµ>ãk(Ê!°äF•€òdCOlMª=Ô6>_P›“ñM0yû™*Ũ\zVÝG·ôGpíVÕUZ¼jL²O»#ßy»dZ‹,NÊž)DU • ¨¢ü¦ø'ðRb‰hmxþ ‘PÓê6GDÔ‹®ø‡XîR!h–t)&RK$Ø£UD´áÖj@…RÐ AC¹EûÁæypGZÙ[ë?œöáý½Ð§Ä¥L@¿â•"q_tæo‹ÑÍå$…Þ¢KÛÙÁÖ¹œñSʾù,Ñ%á`@”KIìXb™O`{` áù‡É‡ŸMxÈ ìC²<5ø7ÃjezÖeKHåGîSñéÃßãñŽíœ‡ù¡Ç‰“{6F#¢ ˜&v…I¸Æ‹Ža f #$µ.4cŽŽ3B› 6æ/³…_\z@™”= u ØuyWé—¶ :³óé>± <»ljHÚ8Þ>_'œnéG­±ãÌ•¡þÜ–¯Ó”@ìÆ#¯w-A³ìèšT¤j¬›ØIÜ ;7%=„$· O)«RÍá³ï™4s¯¡z`õ’ŠHó)œà Ž KŠ8íkFÛG¸Ìžæ©‹¯Ž`¼»Ú pßbÔÛü\hïD³QˆÝ?tÏŸ©Ôáp_ À<Æ…®ð8vI.UP'w¹@#Ë 6?N…º\pÐÆ·•Q#»e8E$+ÊÑXpÁmõéá Ý¢4’Óîs”€È– Fæþ|•7—˜2‚{æEC Âàẜ‚g>;$4kTÔ^ŒŒCY7G‡B’6…€™ßœâê¤;ÎzßYrd8'”ã Me/5c¸J”îô!Ù8›DfâÌBçÃC©+˜Âs“FôN5ÔâÃoÙƒÚÙÛ‚ÎÛÜì¶ö ›¡MŸYQ­èc6i!¿PÕê&—žÝÈw'=<½ïÀ™ÇZYóÏ­zf%„'>`ofQßG : ®!‰ DÂA‚U£2Ø¢²¦IJÃh$Fhw ¡•rðK˜]Ý¥в‘™Gœ Çe98€ï&àº7¶4©Ú™x”âG•ükÝx^Žã &ô±ƒ­2”Rtb4˽ÁI êBÁß!Ô@Á10,”Ô +!²²DÓIC´RÍMD$@ÄŠ±·znU¼Ñ ‰¤8ˆ'¸sØžÈ –) a™amá9‚Yá`°YŒÉQ†93ñ—(NC¢¨¦÷B„LÈ. KÇ‚š¢!šòq+Áæ?žP¼óƒ,r䪥Oœä”L'ê ˆ9¢‡0Å×ÔÈÛF*פƒ"ÈAÔ4)û)ëmæmW÷f’£Ú(GöálÖóXm±†a‘‘laY‹anR¤?èdÄ”5Œß*¡´NˆßLªAŽ«b'·àˆ†ž(™ô ÚÄYöÀiACÔÛJÂØ;]%LÔU6rð`@|nBd#¹ Q2\šSȉ (©J¤ (½óhtÁý+d%$AM ÀÄXIŠ!…Ge@ä'þ0e»-´5**ÃVvƒ¬´Hfó›#™È,Ì (0ʤ°ÌdÒã1`'áá´7=…É!Ä8—´¡„Å í²ËîRZmHQ3¥‹%ƒ%0RØþ¬ßÐmG—!½C¸0©ˆ(Â'Çõê—ï…˜d€â2:Ä÷K¨)‡(ƒv»k3Á‹¶¶Ê´-ªú+j–D\Qëßãþ ìã- ÄHĺr¦`š(” (@ J¥(€I†•š„¥J@¦‘J™’‘$$¥ˆ˜ R‚•™† )‚˜’¨¤š¦H–%()ˆŠ d¡„™iB)¡ "І‚†aVŠ …L„©¦ J™!ˆ‚F€¡) ‚I$ V˜˜(Š )‚jˆ€¨b~DPÐ"J  P2„“ÀÃ(Ò 3D¨ÒD P)Th5õ˜Iô¿ 8‘¼]J óü1{=<`#ßÑÏ£ÑÁöÉ; 0˜±Æž$ÚGKù$wDÖ‹8I)â£ÇÖJ÷$´ÒÐÆ!(OÕ@^EÍSöu|Uü"SNŽè¶•É™Ë!ÆÈ@釞ÐîŒñZÒ=!t@L%îÁ JˆîÞA8® Nˆ Ô¶ŒL¡dq5ˆ«PÕ†Q«ML±¬KQ R„ Ö„2«4Ð8¤ F¦‘À— @ˆ ‘)¥\š 3KKŠÀÄ&¡1ÈÑ êŠ–#ý±’ë'2rDD´*Ré€ÑÎ&´½¸ZÖQ‘š|§^?lìðâûËÎ|[t«¤t7r&I!‚¤ešd™À,0±’`‚JªI’H& ‚0’ö“‰0i (€¾ TËìò@úDûE:äwH8ŸÒ'¬ܧLä7sާ3’­­ü:yPÀÐ|lj³!9ð âC숲·Å”ýr=É?«­(hD¡DÉ^¢D_, Р»$Ü‚îG&ÃP!‰'òJî wû> Ö*‚(²áåïÔÚpHöpÊB±²Qã.ˆñ~ã·¬oy™oµìÍ˨¾|°¦°aF£Ü\†‡äŽJ‡¼;*~‰^°æ§‡B|dpŒÔ²V(“I> ·Ø9´7 J³ )îì§”VßJáé]©¹ÄBLCh‡­ê²˜’š"h¤¤j†ˆ)3"¨’"²Ä}=8”>ˆøB„Æaˆä™@PÈ8Ñ•­[@ÆI`Ia©(†g‰ÛK‡hÌ u%¬2²PåÄê FŽŠø¸&$UUyy¼£çÚ18ˆ‡†O7|g x¨7(M½`Ç]5,\¸VkÅ=½`ë ‚¦‘,0\ž¡Æf‹g@é2`%ö.B–Zqˆ %©×2]í·iÈ÷òG?8[߯lŒ¥±‚EŠƒÖ±h–„É,¥.`dY"(y)h’7„¡êm4ó’dK=H!·`ü U‰P:L•ˆP#»ô¸¬\‘ï"!UØ„©€¦I’V f(`’ŽHp"–!¤¦‚ ‘-Iâ.e‚˜B03øtî cQ½·Öz†¼¯É(½³ {iîã>¸U¹>Q~¡³û.ÙXÚÐ>m¯Ùý_Ç£¦ ‹ 8c¤''Ì5ý7ÂI$’…ÂþÝ !¯Ð~þÍŒ"-çdC1E~®¬Ã}¦Å‡½0Á‡»ý¿7§Ö’ðEì×¾–×@l¥l„r9$ƒ€Û1c5Ôü[uZS¹G«ùßV—©jŒ‚¨hwüaŠÃó^v4¿ýI«ÚàQyNC—|:b±wLD ˆfø_×8ú¬æÙ¬šlXMêŠ>R×»;¸õfVdqpÒv9ôørõQ²pò©¢¡®ÙÝ8|o?·±~”Ç·Éìç)ðÑàj*_qÿN¤jÇ`@ìÀÂæÿ ¢ûqY A î)Qއ#Þœ{›fE)†îWn² x­­œôs,_¯éê+.O(ŸQ:$Äô“Ï5¦«iÄÙŠ­tH¹Ò‚l¶T”̘%­‘Xƃþ'Q\0ZÎÔ£Ríck+lìAé 2E{›HÃjX ´¶BV=0ÓUÜä9óµëvÏÁQb“Å9`ª·¶>µ¿Çœ%ªh?—ùŒÛÖ}’™ÿÄrÆ&q{h‹v(µ0 CðáÜG*Ñ:M=êbèÖIã(Þɧã:íøq•zN<ù¾ÙxÚõ›° OlD7ê‘ÂA_ó×û4‘=@˜Á›Õ­¢”•¨FÜ*.á=Ž­d {ØrÀÊ­La"NÅA ÛI£DPnWÊû/äëÓEu‰BvÈÿ(ff!$ãC‘¼5ˆÙ,'îñÀoÄŒÌ a"¬H¡á#‰ ᛨ ´ÎIE f"QH™ ˜ƒ1I†+&dER ±P]™(TZˆh² «T«)TEŠ£‰8Ìɳt[Ì@¡LÌÑ*‹Œ9¬ƒ Ô¦M d!0§浡\´ ˆQF˜2V"JY5Q–Ñ*‰Y–XA¦øì-SRe$©ÄA½cbc–ÒÔ T…*›“ª)€˜ !dŠE ¤° B "h“RŒÌ H¶E*+Uˆ6Ì3bÑSjsôà»ãÈûà t'í1Q㢶ñO"”Ì… ·#Æ:éÁÒÂ'hîØ´¥õKÃ÷„¨ÐÌ"ëÛµìë\Ô‡Žë‚'%ÌLjz¸žŽ¬YV¢t*2›\(ÕÒÆÕ‰u¤Š8ãê8¢Ly¶Dk‚ÀÚ¸¹(Z‹KO=\kŒMž qÕ oN,±d‚Åø»µ¤9»éf+iÚfÃLUUV³ŒÅαªŒ–Àx.óåså‹çul=Þ½½]êWÔÛ0Àܹ0„kF†’,<ð¯%`C_aˆ:ª*¢’Jâ~ ?ðþÆ:Óý9“Ïп²ëabóÏùz›V2íübùæÑÊc‘4 &ȘѰrE§Ç..ö‹JrL ΂šä>œœéÏ-{Óø/ˆoá$¨ R” ¤&¤¬=æhìÝ ðCõññ=é!´ÝÍÚ‡ïsäë±?Ü X*‹ÏGØ<(§xQÔ)´‘ñJõ@QþR !Ý"}ãôû×ð{™oÁÌè‰çh˜½„,SF`k ZÈÕªJSÄ¥æ‰Ëè×o#¸ &!‹d#Ϭôa2Ž’¥XÉ!ÜåyAðcH’´. H0Šg0a¦f*FЇ0 #óšb”fE™wÇQfZ0˜0ÀÊ.òHÄn3,†"0ÃÖ!Ì#«D[RZÇHÕLÒp&1²ËGÃC­ÎôþçNµ•@80›ÙªT D$­…F”’M`ãÚPÇJšU‰VI B›Ä•ËV6$I2LiÏÓæ¯ ãd´~·¯¤?RF˽”íD<‚L=R§£¯’ÿÇqÁþŽ„í`´–EE-²—7à¨x&“¢ç=©ËA“b" VÓj@‘DZ‘¤©t@¡Hé˜I†‰ ŒÔá©2µYh†Òá‰'oè{ˆ·5×N ´°Pi“Ô8n± ¨üØ”€Ô«ìàd;K„¿‘_º9νèäÛ¤;–P8!(C KC"4‰JS(ÐŒ„¬‹AJRP¥,E(0E$È 15%';^¯£4yÌTò‡.á÷ ¾ÀEaFá 8*„ª°b ¯gZ‡€x‡¾_€yÃrT_uäMðr4'´“ÈÒf§;ÐÞÏW`ø|4z ¦€‡Ùͤ€‡˜Ù/¨‚$õô©s>5çþ.SDO#¬<\ÎËƪíd}¶(tíü¼·Ÿ¯—§ˆâ´HRA4­5däH ,´ÊPLR!DÁ}Ò& L’2C4%„Ê>/¥4ieO„†AXTdÐÐR50ÒD”†ùÎ¥"ý„lHÓú%2T¨ƒd†4 ²PËD‘+A ưÆ(iOpP"„ÂU»g]ŽûÎlò͇w¡Q]h ÄÃŽ&8o&<õ×;âê¦\šPñUcBfí˳;&dTÄØ=8p8òãϰ9r;Ò{a5#AIB¾¤9`Ž+„è•Qç”ÌP\Ì(©jˆv¬AÐZ*šÌ¬YVZm¤d)Lg×F­›á–R–ȺÃ(7ßtÕ5š6${8%6‹¸•7$ˆáŽ•mbŃ*CjŸ’mÆÈ~ý4¿zoú›§c Eña2Søÿq›7̉ ãöíOŒ!¹q&>L†“Í¥GÚ©ð3pCã@á ¤2§÷Êy’ ,}Щ4@|¼¿hø”8AÙ ]ã¨x.A™.‚|LÐÈ0„é_t_@Þ +àaJC  §²Ç×V¶ˆm G¼Dê±åA©! Üš€;óä·QI[aÝg #¢‰µ.ÙJ1Ñ,B"w=äý¨›œTY@šb`y!2*Òéüµ6 Šè=ë ¾ /¼Ðxm6*!×lÒúÔ1“1õeô@­¾D\S 5rã[J¿ß7KÒŒ3%7„M`õ~¦Ç ÷ăŠ˜o‹Z¸¦ñÚkES cx ©Ñ¥˜î"³LNà¨ÒT†µ?†åßkÎd:‚(±é7Á%ˆ`HºÉ ÑÁÄP:Äu)Dá`çW!lÛZ8ÚfÒ °ÁDvSš,& ÄAíóûËÏc.8l †Í^v¦M¢Ë¢”÷»ˆ™•/(Ì0;6‹¹oî“ELŠ‹)òK [+4Õƒ Øl5´`ë¾2¨ÄáJ¸¾»¤q¨´1B">½hH¸0øN3Zm²´– wd¹4Õ²:ݺÿ}WC‘q!!>*,Q^8†ÀÀb:@Ó%S+!ä4]ªº®IQ½J6j‘Q`û&l )˜È×lOåîÎÝUÐɉ\ca©IUÍÏ­»÷qùáNÄŽfZ ä¹ï¾ÃÈ¥‰™ä1Ì .Žé&f&7´Ù`Òyž®«RDF5ø!Î7ˆÜÚø¿ƒ;™„/<;Hƒè ö·ÔÌ<¹J!(sWZÃMᔘkQùôômÁÍ_ƒxKó?Yé›×¹0“o`αCrî! „ø ëãçùÒŒˆqÔGÄÔ‚¨ãà.ÁÓ`?¯N7dî’ÏAÀÑ̘7 E2ôyÀ÷wÆÒÌót–TùñÝêwNchuFGZrB`í`0_"ª‹…7±Ð'@oæ/U1ØŸyêØ9'&\R‚q Y­+-²Ž—™n`†ØS’Å,“âmÌÌÂ2ŒâÂÐIÅÐbfá Œ\¹ëO‹\}h!Þ;$ÜŽ ™NCÁ& $•„…!ª ‰*$H PEð톯bö=üx`9ÞaÖÝðõÀ•Bøf(uÎBC5!,IÖ†.#'ñ„™ eÉo¼ÛZãwhæ1¦wì >7ßÈ…h "…ìd¤É±àÝú€‹11 ¥ªh€2 >uØd$@ç²Cˆé`tøcT«C0ª±b[%z(SQäHŸ¶âŽH´„›Åæä¾‡_›VðƒŽNçÍtU˳¢À£ø‹%þÈžz?‰ß×щzÿ.y[ñq1Ÿã÷›ðQ•<ä߯2 ±ÝPd¥TZ-›*|ü^×–Î5£ÂFóPT€úÐC€ž<ÁCrø  ~§5¡ âµS³1 Kd†b“Ù(Û0`ÔÄ«Ç  É] AF2Á‚bÒ6’Ôš’B4C• ™˜Ì±i5:RÌ;¤ŒâÍë †e&£ù#MxÊ>®ÆÀ‘PíØJ¿MaˆE‘ù#˜6Vd’n 1\ÜáG<†·±£(1™™TøÀf²Œ˜ÁÍÑ|q¨„×.yqË{`+‘Y-§x%ʇs…ašÑ´494•¼Ê(ƒ¥ÿÖØ«å ßb-#ùÏ%´±… ¹Kôð: k§Ã¯íÔ›I$#³fˆ¤²S¹çÀ݃‡Èí|4Ö¤ÔЛýúÍÁ$O­ãDH>K:Ù&„O=ˆ9«<¬r8’9,-ŸÏQ”ÑcbÞxÏQ§«ôZYÐ’v²¶ªÈѱgÓÔxÏeZ—0Ë œtJš£µÄS` ½}QêqõÁV{q2 ;ájOî ÂÃ×bpo/ŸåÒš‚‚õ®÷ƒ¸jª‚žìDÚª:a€k‘”µip$ B¾œ ‚“ç#ùX[°6h—O;vXàåÁïßygOk"êxK?# Né9áo“Þ@ì¿jâ¨ý;½þ˜ãÜɲ† kÌaƒ—=`ÐÄP«J—iñ"‡m°IA“pæãøÐÇR¾â f´fÑÏm”$Ù>ÎÓw º}âh?xR2q±ûópK ª#nT.ŠS@®*’‚ÍhQ;ûö$ê ã¶šH²>Ž|äç'49ƒ‡€_?/«þ1c±[!bcØÓÖ±á—fšÖ޵ú£´°ÞÁºÄ‡íX‡`þ¿^‰&_¡QÙðÛ$‡©$>þ±Z^`I ¤ _²wC¢OXØI…îÑãY“¤;øBGÜ!â®Å qø‹ò)°€x ýJšðõÀÑ%ƒ˜ ä –™ëÈÚ*?)I©«Z8 †e†TªMÎÃCäAÍ1¥¤¡ðß0f80nHÌ»O$+ aýÕ˜õ !YP8F’g,s”Ïík×¥±O–An˜Ø>Oö¼L.uFéèjÅÂo×wŒ¸Ì2‹&† B ÓbrºBRX4y%3*@Øš“K©tÂjÄÇÓ•Ža[4`ë¬GD…k1vÇ‹ˆˆ¢ÌLt4li0FhÀ V´ pA:9‚$ÂÜȟ֗ãC É Ãu ÄÓUêÌ< Aªa*&œI,aΓRD”‚̳âªÍhE çÖÎÑÆ8i“9l“*£dpŒ…A,\4‚dÝÓ±à|—}„ƒÝ½’ ´U¢65S;YÖ@àŠ@‰¤ ¡¯ž/§Îu;t¥áBHPÒk¤$n@™™–ã,™d´¾¸doV×Óh˜³ZY%0Eð?Cº© Š‚¢(’!<Š…J Ä @¥he˜Ì¡S&*¢i¢ˆ±U—##'1Êa‰ÈÂ%Šr02ÌI¢s3%ˆÀ¨Èˆ ",° ÅÊ1Ò‡=JxÊ9Xaä…¤‚b,þüxdŸzš. ™:Ù>Õ}²Î˜`~ ÿ8º&VФ„Îb¹˜¯üOåÔD/½„Åå$ ’AT…tPk1h‰sõ{û3ß­qÞð¾Ë'iik "€™H‡®q\Ê’I"m¸!ÈmƒõBh£].‚>­(»h…(¢ˆ–„¡) ›—ɤƒî÷?Ts÷“©ÙRd¡1´Òh/øûbÄŽÆOùUy”ð 0w?èç‚7!Ãùk«#,ò)ëô¡'âd¡•xø‹³×›ÿùÇXŠ?«¤:ÇÚdkKôïªa(šˆtAÃ3miƉ¢,©ÆZC’"IB˜”ÍAÆŽ.Ù…®f‚!"ÂÄš‰& ›{4DéÌ Ôt0A’ä <Ès‡€“ »`§Pu'PwöÁÝÞ¶æÐMàƒ˜‘0Q%ˆU $%5²ÅSQDÙ(X#ã]´HêØÞxY&¥B‰ÒFI#hÑҌˌ«"\Œ¬Ä¢‚te­1˜’X‰”À((ÇC'0ʥܚ‡YˆcP KŒd¥aˆcNX”A…JLBa,NL“†cLHÈ™ƒPàA°ÐGx & (tÙŽ@a˜À4ÀLI†`3’`–!˜Xዱd&¦k³tBPDO‚P#Ð\±9 -V²4ÐÆ‚Ì0 \¢¤€bFªÖµ„¡¡`Ii ÁR šQ€Ê¡`·‚=‰€ˆJ¡@‚âm d¢1!Bi01 LlÄÀ•:5‚…¤E¤¢Ä›î~(q¨XjVj›A¥CÌYžœBA ¸ §B†<º]'²Ed—ˆ‘8ª±`(p€&pŒ³# œÆjR iLJœ1ÈlJ„¢ €¤4F1F9†ddÑ8TäVQC˜P4RC–IA•UM@R,8¯Ž(‰­!¯¥€{?§33ÉOn°J÷ØÎ È(Ø@a Í+¨¢}GÒa0˜L‰;X6²×¯¹;¾Ø=³‘uo“OG·…L•’D iY**¢ fad¨-l<ëÃZ׆{S”ƒ¨p ,“¶•NêHmf™-[üˆ?¹‘ÌÇ(@€dEÒuÖáGçÈæÍºãÈåßigvƒ'lrëgÞ‡û¡<Eêдn}Ñì´›oT™*v3{Oî;`›ä SƒX†çPD¡!šS$ßÁ5DQ9  ‘ÉML1˜Øf3ËÐç07†ì VQ ‰×âi&ûXiƒV?ºVJ-¤¦¸þüÙ±³È°§L¦>&iÕp¡GŠU™p"†eAØ`3.XΘA1ƒfi°0¤ZW³+CA¨»D´>V—)›kDth$6À¨üO§GÁÇC íæ>:•ä/ûÑ”$$ÙÿËí—•ªˆC €‰ÈæÑˉ‰ŠCB@“U\L?fï&•^:9¿f‹õ-Æ™&p:ysë:_ƒÀ<.hËŠ§YšŸ{ÓèøÁçèvNË}§ Ì)þYû¤Ij«âfW˜¤Ê¡ ÀFÄæ6¢|Gf{Ä’q4.£»½>«Ì¤’ÔP‰‰„¤FFvÑ£QE”9–ÇP¤‚Š„þÀ?ˆø§±0ˆa ø‚ŠÆ\€·iîÕû]*ivJY%2'¶XÜÑ>Ê8NëjAZT¤Ä_ìí ÄBP^8¸4­ Uð?ÄØ O“áO`÷Ð{ß4=€ Ì14¢ÂHùƒÈ¿þ¡ ý8¢B¢PД´ "ž¸ÈQ(Fùâ ‡ûaDÈJøä!h@ªT)22G™è‘P€QB+B‚R P¢#Ñä«B詊’-¨µ”Z m¡@þ’@ÉQ5(9(” „KJP)J4^øSR¤­*RÓB"Ò´(.Ö/è´øCÃÕ|Œ÷ú}N!dÆF?á¬UðÊ,Ì‘*¢™B±6Ð>ÜŽÈúÆ1ö ¡ TƒÛ•f$JÄzOW×7 ÅPì¦ßpüÁ÷ȲU„–C`âäAgþ€ßˆÝ(DA(›;Çê±Æ+ô@fÜx‚üÔ7}‡óv)õƒö’å=j‰Á Q¡èïKýÇ "j¢Õ{å ”¥¡¡V‚”H”A¨ ã6\üóM.“V=!Aô%Ë $£B‡á-ŸƒaÉ 'DŽdcff1‘Fa† àågKÄ›]¢ñ°Óͱ¦Wã1ÅBû"L—°ƒÎ ÒAðêbOj‰ÉgK,¥‰òñP–`ª¢ ÏŠC¯#28MªõÒJHP+@5H‹(CW Y*Z-H¥ ¡˜)"ZF’Š•Ab¥‰@¥hRf„˜ ša˜¥(f)`ˆ'@¯ÄÝ o“C  ^¹>ñ¢ˆš«R& ÁJIDÍ!ò²$€‰Ä"ðAEvÏžSL5\r…MºãJ†HŒH¸lÀx Z¼Ð»ì2ÂŒ6ÐBqÖ ¸S®W:.ĺ g,Õu¤Íu£ŠŒ¡è W³ƒCþ™µG¸Å­í-#rÄp&˜Ι 8ƒ$¦&U×6’\œÊ;ëC£† Ma’øàe³3s„Aá˜Q¥¡ ìN¥(ñƤÉ1´vÀ0-#Q&Ö—%ä°Þkx˜—9‹•àtX`Ê4F˜ëz*¨yHFN5Q‚ò ¤&û€[kJ6’ ™9 D‘ÂlIó<“éX~«ÆÙKWö'Á4ÛÛÔŽËíýšW57‡÷úvÚª¿>áß×!‘LäŽè³ç#©j•¡ˆi)MÉ’ ‰8åðîJ7v;تhŸH÷Tºý}b}[ø'#wö'‰¤öHÉ J $;”‹"¨wIù[Y ¥OÑ LÃ9ÉUû‚!>œG¶Šj†©kL¨‰ªB ”(Di i @€‚d‰‘R•’"T)[IA|Êv©ãøà‚\b*ˆ’¢I–‚¨#ÜIP‰M+$¥$‚Ø ¼9>µóÄrCÕ°»?óŽ XØ(~wï:Çq*ŒÑö±½˜ꈪ¯/qÄÆ2IŒÅD›i3¡¸4¦îHS’I‰‚–”gÖCBÝIq Áü õ¨sºÉGÏ*¤Â†‘OT ¸Ñþª'Ýnvw)î’ Pô½ûÅQy©  Ö„à}<`¯~8AÖ}Ì1#˜bÓRE4 +بäOeÔç#ù…ü!J¤ }Aã½ ÏR ø5ÖDX 鎉4ý!êä-¢'.ÙàQå÷ž~ïćNó× ùBEô–@äå™N|Ã˸}dú¤údqÝáò$—èÁO‡³¬ Sœ1L1x/ºü’&…AY õæ#ßÜ=zÓê”LâòˆôÖv‡ª»ùÊo0K'ðlËr'ÙˆpipT•oq“B” ©¨Pß)€i®´iÑ™­«°tÁbaЧ´Ò½|H‰‡gì>]]ÿ5ÍI¢¸=—tÊÒh·krEúéOûê’—}‰Õ;¸îm‡‡èÖ¦i§¶âî xæ$]gqÃì:Í´KÌ7“3¼O\´(ä¨k¢bm øÁPþL?‘í¯#“#ñ‡¤:xowL‹wá¿[Œgœs’éq¾ªO6‡ݪR0Sh“XÀ‡ô»€3Q/"¾×›“ –üq¦ØÝ:¿,ÿz°çAœ’¾¨kÊå9ªµ {9ì©%6ÓP/#DžäÙœ\3‰áË`a#YÔ&ìTƒ84A5.Ä’‚ƒZŸ®6M§7ë÷išYo©­E2„Z¢§ ‰+´Š'Ήév¢ö“dÚ¼Þ©Õ8ý˜fgȃS/xÐBʶPªˆk“s–]÷ö˜f]¾XóçwÉãŸk$Óa»‚äæPÐR¯A©§aÃ=Gt`ø‡Z# $»Ï‡óò-¨ôÀáœBo˜I(H ¬@‰ë“‚õsŒÑpçY÷æ/§þƱ(~LÕ†€æ1ŽLn5Ä—‚n«î9ðú"H:Œ@»´üb<:X€Ñ«fb1û#W³žýx©è{~œ#É& ²ÜÓ/¸ƒ’ AÑ*™-$tCì2PܤML1™.às=quežÈ ÄÅæ3¦`É"Á#JX¥Hª B Ô–=èçŸk{p1=IÍ‘t`'úcš!4Rg¯ø„BØòbïÀ‘Å|,2)uâíž(IÁávIý‘ÊLsÔž´7š ª½*FX¯îÞ`šß)’ÒLÑJjȠå4¦€?¡Nèj–êÙêöâü®PÌ?¥…ùë$úƒ?qÛxø‘§¤ò߯oÙòƒáb|%Z’KPª^’é+à

a´âì‡&yõî{ó¾u'daG~ìæ83“R´m×U ¢zhJ•¨PI¼lBBP,‡ˆ Cd7$‰1X¸D’쥢z}’¥E\³D¢…URÅŠ)@¥³Zdj³2ZL›K$ãôN§ú·ž.û”bžš¼|ºdf1„þGý:*ðàä²ÀÐ:¾^|6ó€o^§¯Ø¾d9 ôˆ¦dw9F”“ (dÈÜË BD;4>Ç›8 ¨&’ q’DU†ÎÈ#hTUÔM@'ip€´ûaø—SýnBX\†Ã_.A³! öwÜñTÈ65¾bÁZçA®¬·8¤Ta™@RÊ5¡±±Ë&R²ÆÈDÓ„ •)‡°tœB™ª8¨É&J’0LgHf…C#F¬ÉŽq %U/6èF>I´(Úá©eÞ™JDA…•;ãÌû5M#$DZqsØcˆRÄ3M É&$TE…„̨Â$ª‹1ÁˆbŒ p:Œ‰õf,S;h(¶à¦2ÀFË$¬ï5¦…¥E£vHÈ­.T[$‰"%31§ƒ¦™š6M³4j°¡‰Š¨™–ibÔ‡ï¥e6²ŒmƒÞ Ìl%.0 Úˆ‚‚l$›0AD‹ÄL¹N#!“$‘Q1`hÍ aH¤¢’MÀ‰´%UP(lƒ*-d“-Huˆñ¥3—Û¡ÊMÉ„BI6øÐkš'ÇD µD*ÐÄÓ9B-dh¤! ‰ha&Bd‰f%fJšh™ç )¢¢Z¢)h«U,YHÖÍkLÃ8©4áY E²çFPë0ÈĹ¹Òi?Ž0dcñùkN‰£4cÅ"0R!Ê*a¤“ a ÑÛ„‹¥ ´@†ââ.» ÉN 7$Ž7ä‘”R/ 0*cqŒÎ‹L_+›I>M«SK=ìå ;Ï 2è_WsˆIÇh:2 EBt¢ª€L§¬eÇàX66Š í~¿ á´ÐH`º'e"*ª¢""¡*€¢fƒé¾Üq øÃÚ =q¹5#AÉ% ÚÐɼÊ!àH @š«b›™™?ck&Ø=þŸ¶’rêòu Z†)ßò;t†¡(ï%ôI©"I’Žz~¥ô ôðåüRyÅPŒ@¤LTÜ Ž, °DÏjÙ $§È‰$ìŸj»ÝXœ¾/ô÷{wK–R¬-|{œ•fëæøÈЉ™R$Œ{ù¹ÁE’Ç2Z>u³«aýµŽV¥‘Il‡¦¦”Ò|èé0S{—T“¦Å³xžÒV–—Ò<ÂE5‰j âI;çzx‡‰üNèò~Z(¢ñpFñ6f´”$Žbäè1L@íµˆ1[RX‘,0BČԢŒ°¡f ˜¸8sÈLMkAÎöN¢3w²7ØÆ‡"±°"PdO)AÖœaiK! †  4:­©:¢ªÁø5ŒÈ¦ 0BBb£ŠÂ ¹P‘PMÍA–bèHtlÀ’¤ÆÊi7G;4tñÆZtl4ä$’HZ`ÐAj+TdÂ6Æšc2 0Vº°ª8¨ÏrŒŽ™˜ßgÍßõjÐܯҸ‡¿`Ÿ×¿Ó7áGÀ€7 ­÷ºGAðþ Â½Ì éÖ%5®Ä7Åî|ÈS¢ß]ž+Õ˜#2Idz¤J5£4RÂÔö²Ñœ€¾v¼¾® ÐЫ¥2%)ÊÚBà 3Ï^È#â}]¬q"(†±’ÄH£F“£m ‚P•ÄUH(iDQ×e–µ-M h+rÊ¢=_B§±¾ý§´ }‘¹OaðˆøŽ8útá»*ŠÉ‰&]‘ö ÄM?/q`0vŽå>Ã7E6³Ö|½5(á>uõg½iB„˜P-°úxâm"‡Àsƒ´<0vÜYÿúÆ[f›,øê6¢w{~%ZõNùƒb`nzøªüUy(@·Zp lît‰>¿Âˆ ¢ŠÁtès·Õ Hnr*`O^gç/b¢0­ÓÑ€îЯG|‰%~1“At`4˜Be-UGù®VЇ´äòœ¦þèåFX,M"”ÓÖ‡Z¼6m§­ÒþhÜ0ˆ))¦ƒ“$JUö+Ô`Š<>“l_jvJ'îú_§Ôت…¤¯‰¦\ÂóÔd»­ÈŽ”ä{Ú]°8 PCMíP‘U݈}H2;8̲LÁ˰a,CB !I‰FþÄÅ —G:aÏ‘½àÕßDDÁK# A)1PC÷)´Ñ¥<—º sÀG£Q5 T@¬1,¨±1TTSQSQ¯!d­Q P ܆´pp½7®±ÇùÑ!õºDÛ²&œ‘c™o9yaM¦”ãÂÈäÏÆ ‚1£hU€…Z•&òÀ©ƒD!Œc½ÂŒ †M 0ÚÅ2A0Ö,nرA Ù¼]㎀ÚDC$ã`P'c¼2”¢*¶óp6˜»„Õó´u[ÔQ_ÉdÑ@SцE¼0š Ã!i¬—S ³ZÓŠð ‰7E2¨ÛÕ˜of÷‚ÈS9‰³Îõ°„ÙP¥B2@q2¾ìU/øtÒ}%6e_Îà-'lÄ£ŽsFâH|,šbÂ- Œ7À‚–‘T4ØØ-0v©,£0°Ã¢$NCí6xo@ñÉÏ$ ØU/R\¡0©á›$bU\dÈ‹&U,üˆ†Òy·‡À‘§?vúà„zà|F¿zIÕYÎYbUÐ8 šIANÀ(—À¹ BeŒÇds^QƒRHJøiÆŠˆ€¡¥ „¤i ]º‚ jFßF’" "IaIÄ %UI |Ð&:E$Tܦ²d§íPøi7"§°!RýÒ|dtˆ@Š2‰J3DJŒÞáhYó`Yž;¯ÁÙܯÕˆ Á~€6VCyÉQDµTWÐ ÷'>Î<¹ÞA3vû³\sâP¾p<Ö„ P¬JÐRÐ5oSŒïe~\q_H[ Áâ „‹RFÔ’Cÿ\‘ñò k™‡% ²Dô°š ÑÄ›)Iº’˜$³ œ“`ŽX”E–f1˜co0™ o[€ÜZÌÌʈbjˆ‚°€É2W 0Ì*C,™`£:#PDE1•™˜šƒQ’ A0ˆZÅ[XE Ö‚«yŠ"@B2™±"fÔYdN¤ÛDj –Á+–`ˆR¦fKö ä-…JÅß FbŒ0©j”U9!¦I,[$Ó eYReH!@¡ÊIE0}'D<øú—åë_@ôäïÄC”6ð(ôñpö¨@#ÍNL¢þ÷xÞˆÍA» áµ£PêUœÄÉ œd•1ŒLÂFB`Ì b±: ÉÂ#VfY˜†d‘#"B´©„ºIîù3{•žò<£º—+‰ÀÁÔg× í®§{vƒg9Y„æE¾ÄJs’½~>wÖKNì%šõ“»ðOøXºlD™Öó n‚áaCcÍz&3ªýMÍfáOÚæÉMip™ñjYáðwrZÍ­®0ö„nà…ŸW8]$°ÐµsÔm~RøP²›ºáÓç´¹#üTãˆL±ŽÒI®DÏ¥•-å'ªÈÕŽØÛt<2¬9ÑL –í$«Lž¸.ûfü¸Å0Û£8ºÓ¾'ºžÜo@¼¡;1²+±îÓÝ8Ž“•ÙC¦ŸQ=Â6äÛuV «IC‹ŽÌ‚‘ÇD1«Ó™Ä;ÁÛüíïrîô ßÖØi]~þ-Š8LÖÔr²‰ çÒÇØ’&¯Þ>¶~Â^ƒ+W÷•Úœ(é ;:  ´m¡7¿¯.*ÒP‘P9~L™æ„ewtàÕzÞ{T¦^ä? %Sœ‚Ñ!”>ÖÎ8}†VŠ&ÝTÔÍUüòì”|âR% ÂË@‡oÉÉ9«Á¿»fV0n !×ÀÿÞ޳Fí.ÙådDÑâîÐ'OŠ÷yûaóŒ!}óùDíkz? ÔB­ë[Ÿ¦¯§F–pœž9xž 󵕾TÂãR«|êéÇda\Þdˆx¾pY:+|òožtÎí˼çnÑmû+ëÔ«Â9ZC‚m¥÷½ÓۉŔSQ™c4[¨Eb¸–ˆ~?]@™[Z6Û±Z+B¡Ím6S¨ªA8‚2ôþx*\41ù´þÍš"ñÓ=‘‹å§ŠG;F#Uú~‚Èw òaþþ³}ÞNH€vþŠ©Å-€ ¯ -“`Kd#1Ó1&2vŸÕ3äÎ=={c3V‚}åŠÙ1ѧÒ_†–Ú€­AïC¦4DUÛÝÐeÂp\ÙrWÀÉ0Òˆœ~¬¯”ÚúØð]ýˆËœ"Ðo²›x¹ÏZV‚¥ˆ‘hü¾ì?zw¦<£-ç¢õë ø—ÇOˆ{p.¤ü½˜«|vg†ù?½PN¡d’E]³ÒXÐØ$|X†Ñæ/ÆžÄ÷Êt†üÞK—W—IÎ%‡„N9Áˆù!ÿ)êÕu §ËT ãx2 ¦ÌU“än7ŒG$!0aàÏ ÒhtÕ¤ÞUY›7›æY²³y âI6œ‰©A»nï—O@nm ·3y7ÐÙÎdÀrÓˆAOfª‹# 4mœ9Ȱ:×nujÊ`¤"#’3ŽTZç¤ì.ÅÂáõ'Â÷Ké]H„"æ`©GN(äïâf2P‡hrt!K¨iØXfJ´!½Oåù5ÍTn¨ÞöévTöø¨{}i·ìâ!ª*Àz˜i|…ØAkA)ì†q4–Pë™ÝŒ£$žTjH»wÓBé~' x1¡{’Ÿ™ >ñ÷( ç‹ð(y‚ƒHˆáY޵ZÇcEg° Åñ¶B'‰ ú˜$!”™a¤ ’‚%–gþ°Ç‡!— YWýl2’‘lðö=„hÚ½5%¼˜M=Jh/{>£Gçÿ+{êýµ 55ZL¢ð5 IaÐÊ™’ÃÐhtœ°/­Ïï­ÃI2ÁWž¡ŠObu°¾ßMD܆ ž©7‡]S €R§WìÕÞ&&‘¡Ñ#¸ ; ÇÔ¿;ÊuäúøhˆÔî2‹bUÂÈ|K¤Ÿq íîkQaÈŸ»>Ï/•ääúCK¤Ò&YYfY6YXØMˆäãÌ}%¿ÂCŠniOöÚE~ìC‰êL‚"–”NÁ¢Š†ÀÅ2pˆÀ„†A þâàyS風ð‚N±tHPä¡‘IéTHîÅՒıa(NÆÀv¨Ü@ÌÄÕ!°{="DøYvé;/¨;ê-Àö„üŠÖ3Üš‚«Îû½ûÝàˆÖëï/$~³¹#ïI| $F€:Xe9%RAê‡ÐñLO9ÿ¤ù6‡;ùO‰d'Rå¤AY£R‚÷Š»u*}DE"P¿‰@ÒTD"EA1ÃX-0Gž%(¶«àÁiVÿÇxÄ_å0ù ‘ÿ"^Œëמ=ZÈ(á µEIश$5!ÛëÏAñ¦\ †œˆd’$õÆ)·"ÅrÉ'ªÈ3ÃôX`¤k³šI¢M”.×ÏSîûr|u*ÅJxH’sù6ðh|«•šÛ"¬vxÍVDŠÕ–ºBNl‹™R‘Ø= è›ußÈÀ¦Oÿé>ˆx}kÖlÝTEñ7°Þv? {O#Ý´³4))(Ò!˜ÄU‰Ð‘Õ¨1“ı ò‘ôfÑ-Ú1cQˬ0H³¤ÑÔìU˜¿3€v@F R$9¤|`;Ióo¶°ÿà F0‰ Æ!¶4Çd®4ì Ô5R•Jw"äøÉ £y L×7–ŠœÙÖ˜kEÖƒ1‰2&cvBü0ÄÕÒ&CŽó¤‰—a0 /›Ò¡Œ`Ý"‡vµ¤ÌY •Û*I$6Åp©±$b±iŠ6`RTøXZÀ ÚØf,=¥1S8y‘Õ Î—f.X6ŸÉ §;p›Æl ìÃHŠÈŠ¢š¦X`̤AÃAYÑ¡J1jÃ,á¸&0ŒôzsiMš–9âb‚A¼ªª*ˆ<õ…óJÜpõ¤w L¦Ä uDOeñô>Â7IÑ ðîpd\iíz°à°'¢œ0Àªü''ñ€Zù½Šyp>@>©™M)¥<Ô;UãqÎä¿–OqÀæÊÒÐâ(›=ô1É<»`@÷K‹ÄÇw» 1Ðóá>Jøãƒá³:‡·¤­ä¦VC$€ú×=01€Ù±cºéGªA¥F5HìGYI**~~ÇO߉}ªo®¯N¥ñ°®èu)@Ÿû§$(™—dx€Çu”íó†"Z†p£!aøQ~%6÷ :3RiªZ_s54.ç(ä ŒÙp^¥Ýc,ÏëþÏÉòÜÞűåLú“Å5«c>kÖZwlš…^i y‚×Eêÿ.>w‹–Žæ.81D'·©u¤¢xX'ìçVVE>àùMªËÔ½;ï¤4@îÛÇÒºÔ ÜÖðïšm2bn:bFðøåÜt´çÆ1Eë—Òveâ&&GïDÈÝ\¨X%ãÌyjQ å~EaÞ±%sPV ƒi²Œe5bZ"šxûjÌm³ êô"Ó˜Á0$£lì…9}!ÙC$y­úu¤m<¿8¬4æbTsyç«'§œ8„pŠíÓQ# ƒºÂ êNùưݮœÈq4¹ÈâuSù=ƒæ;ªbÃD( 6ì7ƒCJBôÎEÝä,îw{Q³Ðè:ÎαLÈˉÙc¶éÔ-PÂDnÁ¬ÔUÂÃf¨1jM¤‚ãž îÆcb˜*íƒTDio¡6F°£;oTb:¥¥h¸)]WÒ‹„ÒÌ £úeò°îZ„Þɇ†8wE~µ³}üNÄg޲ãŒõÄFQV†ÊìN/¹0:C%ÀÊ‹õè!7/Ñ—å &à Z³© ÛXà HßA B)Œ"3€T¦@$¤»•LíPÃbcˆàÒgmØæ3˜KE4ÌC<•¦¡´µTiÌ7Þ‰ŽT4®3˜mmѳM”Á±06¡5=‰ØcAÅËwŽ$ÒÇ"lŽáçÇO˃átd0ÊÓb\â=YûîûY†FÇaØqB2!‡`blDc0e,#)9‚‰Ž›R6Üi±Fx`Ð0:5--YY@¬aóŒÅ”²ÝØÕö‚ásRî@쎭Û˰nÖîØR&C2á(´:¶íšLPÎeŸ2D³Ñ‡s-Qh§â_%&mð>›ÐUƒíÚ¬HChHÈ0_uØÃµ‡1rÝ⥒r:솔ÆA:¸ /,(¶ðPØ aáêí &Û2M k`Ô:«Íž•OÈ06¡² pñŠ˜”ˆ¯·]fJ0"£Îí´Žnîîj44Ø1q ©k"*¢6‘í†rBŒÔnëfIßÍ×9®bI9-4‚\uÆË‰Ì8À41A¢í& m„ó`ÕK,je§,éQ°Àãmö˜«q¥ ìdÚœ!—‚À܃â v€àãÌ¡Á0‰¶Óg&(”6µ»³íN»¶GŒqÞE=dó†ö¼‡3£Ž'^¸¦±Ò%LΜ€1 §Á[ÆMI€Á¥”ÀÆÃ hL.Å LF“§1bªEwóÅ×XÝ+Tx&k´Ýu®Ý:w<ÁuÈÆ ­mÏQ³6åªl4 ÊW{À°ÍíÚÊOµ{z­À)ipÕ8{•¬ Ø2ÀoÍðšß[ À¥K&%8†qÜÖ·dŒC]Fø Ê5åÕÚŒ:¶#‹ƒƒX §g˳®ëf\É¡‡Dr¬ºuòmÜ„†Ú:Zã! üeî1M¦Àˆ°¬Ø2ÀûyA½  Ã5•<æðü×êèÅѣâ\]:КNឌs¨“ɦaæU‰†ÍzÅ[]SN.T dØ4“æÆL„ŽrŒÛï#³KoÜOnê`bõ÷£›Ö"ù£4b¯Èa¹ÜhZKÆÃÂ.„4`9ìŒí9Ôk ›M.YLkÙŠ—|Õ…‡±ûOCpáé¨ÚChL‡BtX ^3kÞ‚çCÏþ#óù¼uÇf0/qí×§œA1o/âcÒ½ Éäé{¦}'ãv²ZG­‘QÉ%á÷·œo\EmT;»—;ã5ÊQ baC™Í)‘2ˆáðYÆu·cX’ö¹±´…Íz¦'VUÇBL_Eè«„:èÅ„·$Z¨oX¨½vš0k«…}wŒu÷hFâ¾³¶vdÅèm Pçİ€ÅŽŽÕÝw.W.‡äÑSsL?•‚Ýzáâ¨{=Œ×ªâÞnÛ¥è¼È…ßœ¥èî©+½WÚš°{=DÕáó5¼›Ä»'Ž8¯|ògÞêb–!”ê3ø7i­øvbùÿ¨;.¾nÝ¿2¹m¯˜®1(¥? jAŧaMAPé3DÛÎ.ù•)ÅýeÝá~1KÎQåÿänÏâ1üžö¾4•Û#Øû:RUš¤÷P™”‹ZEÉ”ÈC¢¤I¡ H­(ÀßZžª²üû|MËÇN¾,}¦âþùég\6È"IM›?Ss÷†–Æ2»ý¯¤9ëèˆ>‚¢Þå¡@ÁO…4 Q*l"¤-bÒ¡ÝÐL–CÄtª*ª­€ÙQî!‚²ð‹ü½ƒï\^]#’¿(M÷ÍÛk˜ý>7Èë»vEÀ]ºD޽ÛwîŒ+I¾@í7©n:VoK¼IC‡Òþ¡”ÒÊ9ׄŽ„ /oˆ´CÙá.‘2NƒHȇ»yäy§+;áÑ$×°ƒCK’¨{fXAšï˜°"+ &Z-Š™*ð¢)šrb’I‹‹™™U‡†’bL)_R£ô¸z´ µ2ט¾»²hL4@XŠâzÐìÀ|«À´‘ ¢'dvg:$j&z¬@‰ËD0$!.:Ì–!Ö870›ØOiVáH`ÃXIãŽI§‹Ðk^P¾ÞóôûÉz§L†)ñÑúmz0pϦ&P”l„iÃz1â6eÔk¬y¸´„å˜\„h#Ç‹OÌšcL¦’ÔjSIv4…/$,Œ%HsR’DBáÆó )Ãn?Î^Sñ¨°j(âΉZ‘¤XžN{ñ Pð±l*‹E°Å•a">úZÄ¥Ö@´ „9*дRÒ!˜ˆD©@@dÕ"¥J0¸Â4…•BÃJ´-P…ÅJ9!’RŠý¡„% IBÐPEÐ4#F‰$ZOï“i¤ Jb  ¢”¡™Z¡"DªZ(hP9 P”4 R{`䎆V†„(„ÌÁR‚a’ZÜdÐ#@4«E­d¦K@î2JšU!¥B…(R• ZSD™%*…4… R HdR”#B(ÒU Ò­"ÐH42†äD¦ˆL¥ ] C%•}dZˆq¨ˆTýò™ QøÅéåWž42ÅF]Ö´…¹(E¨Û„m¦ÔKtëCe$7PÞK娧¼R›À4I(h8ž!¡;=“‡õ;S‰ hh‘jqRxÒiCW„Bu‰'Å"j5 ®Ìÿ›)æ…ðõÇ»>áFPñO!¢Ufd©“—¯’a`x°Õ#QÞóÐ&‰’—ˆ4ög·Zà.¥Øõ":Äs³¡7±¼rA³ªC­$-DÞ“‚K*UI):¼;ûE†>ÑZMhf°Ç‹Z+€€nžÏ¼›LÐ’bÒ“¨FªÔ[Ý\ÅqJÒ‰ïÉÇ%£ÉŒÔ§;†4Í24¤œÂp=›¦õDÑŽÓ¤¢­cKL*u3u‰rÅáHmŠìˆÛ~e7µ¹„µrÖX1¶1±:œvB7ÌL¹3Ç(ÁªjØZIV®A*b¤2<ÉFÀÊÛƒd+ÊCº4*¨4VÐe““‰ª²‚"Mc–Q™h 3ÍZª,¥%H(C‘B$QÆØ0jÁ ” MªÇ-¬j FR¬¬¦51ȉ´æ*j0£XdAd`j ¢rCI+É&¨5XcÚÂÜ;œ#zȵ‰F£‰Ô–ŽN3`PÔÈPÓÁ,FÜTÍNFðÈÞ¨ZXeXRª6ãX¬"¼‘··$±°XW G–Û%¥r'i’„)dlj6 hl+Xîd?z ´Ù„u•Æ eÞe®B¬‚ŒI„ÁYS "CÂÁœÀp(š(–FÛX¤Dxé í¹)Z<ÑN3%ATT;*rvQ o:Ô1ÄÒY ¶P˜î »Yc’Ûlr¦5Yà •dLi@rÚ™à! ™@ú¼(”ñ|{ sÝ^»mÓZh[%ª3)LY…–ˆÅ´I†ec‚YS™ÄT%-bdNb–ÒO¬7‹È }zÒ‚ÊTÖK§Ó©8ôõaÙňçpAåÀvè€ •¡Hb“'&%rA¡JTf )_\…xH†ÉCÈãu"C2Д‰’äÐúŽFɼíS§YïNaä8éN)úÀé¢õf‡ÍçNçÆÈEA>‹&BŠšiJˆŠE†$"*š* ˆŠ*N±åNϳ?cö4ŸöW¾nÈÕE­ïH:ZµjA M(M@D4Ä-!{qŠœ2êRˤMÁç˜SžkQ‚ùüârâh8¢ütï§î²nßt¢£R4>÷92o ´í)iÿuLPûa2{È:Ç€O­qxdÑUj[*¾ž9®Ö9ˆ;Îz÷£Œ>ùêC‡·Ô ñQÁ'2$;4œŽ+@),Å ¤JyX&‹XÄÈ7»sÐöÞq!Î'•½’FJ–>Ñ3æÃȶ DÒwÃ${ÇDQvl½ c`fAñ­¶Æ.ñG¬Ëfª: +^£T¹I»Ydu¥ô kL.Rç m®Q¦ÈÍ;«ShÙÜv†R%³Ií=²ï*˜îéã,ûÔ08a´"Fšf@C6Ç7‡ ™kL4gY‰Ä)¹a7 Ýf3qbdŒ)He§O7«Y‚˜xØ'¾+©›2§¦Æ6dX®odŒC‹1U2~Þ º%€Â)RËëx@sR<¹‹ŒA 8ÑÆkPsß EfZG·;xü“ctH$&Ä¡0/ÖïåúzøÍÍâQmDÑBäXÐR·0î#B /ˆ>lBY’½“. hóPîqˆžfQÔª;Îo@[¶öC¿‚â ¨NéL!è=äÁ†Y-D™@c!‰*BE)—œè—!ȤÐ,9YŠÅEPÄÌÛ‘tÅ Á2Q5U3ã’†YL‚Ec*g¿¡S´…xL„Æó2Ù¬SöýøÿÇΚýíð3“Ç7Š\[<Ú!‘ê8IRqÊW’MÕôOñ‰Æ²²•}£ètN Æ"@ Bƒû´È&¤iA5¼<%ýs#½ÃeEÀÉ‘‰#æd(TF nHB4ÒkŃåÌþð|?SÀ_Éäö÷ˆuÕ`éi'ÞESƒÎðDÿt‡äûºÑ’D£Ò?pßžû¾¯ÍýÎÐá VL“ß4*þCïÃê>:€ÿ_ý¸!Àd% F…„©RQß¼Oý…ßòô˜d¼;¶Òï[ÒVƒ‚PäÜ«¢Va§æäѾ_SòÙjbBO¿i ðì >äùHeôЫÉé‚{½ÞþB4¥`‘ßÄÚ)B˜ˆ‚d`j({‹iÅDCÚúc ©SÕ´WzŠžYT™r©Õ‡wzç׌·¨xùûÎËZZZ"$‚'ÒiWZ5Q£I¦jÒ˜‰´H 8 ”ÃADTWÀ¥7嗓ù6Îôº/idº%À· 4º1Â0Ã'# ñDœž•² CxTTˆž‰E‘¾ò!eHÚ'h.„Yç"FCºçs_±#Æ÷Ž¢6£ò¿ ‡Ñ×÷Ödý"‹õć¸ê?ÇË ™UW%Ï‹I>ê¿«£Épñ¢tÄÐ_KïDaêï$ ¶'õÏkîÌu£aEm(ôÓo£Uƒn7ŒU3Xk¿ö°ý,Ѳ6 @„º²µbĆjŒIM?¯k³@aŸBàÏ |å:êõK¡á˜NÂu´²_è´ýš}¿)67XýIp±B`1ªµfc‘ùH0ÐDT79š8eÔS €Â^ Á–bX´Te“ŸÈÜ ÑÚƒì!ÑôŽóõ(öå WŠ‚Jth @)ˆí_}F75 ,„¡?Ý ™Rƒ·‡àµ_¬±Ðgª»"Á‘„dCD1ˆŠË Ч6eƒeKéxf ‘2S‡‡ Jމ´ÙX”hAÕN'íÍ% ìaÉ ü¦ÔùªÔ{ë,ÒKcê;äÿ7 Ïé8ä÷¢¼é–2®d¹‘k(½1¦±V Z ób0’À£1ÌIJ °˜2ÈÌÒi 6N)€¼àf •‚i — kZ•tŒì¦Ã@.@»•BH¾Q_.ÈŽ '1ñ9DiÑ-vü|Tæ£ô§#ocöž âÇÁ—¿wß¹)/ÈîÀÐWæ°kóö†˜ùZ4àê"Â&¨Êi5nShüï£nÂOæ´Aâ?ÓØ~~·ú´nN‚KÓIÿT™ÓŠª}) BÚ)Ô R[Qø£Ë7¾[úÿ^Ó:¨ut¾ºW˜ÊúÒã !!r—c¹ž7¸”ºTã­þ_?í²Þo‘Þ«yS Ã1|«>ª°¬C”é\å{„yQBD5 }´„µ.îìC ÈÂ$­'Ða Ÿ‹û<-Îú}»ÛßÓçt_qg yH¦@qS¥´ QQ 7cÅ ל ” ¸†êZfh>´{ßlé*u{ðÏw·‚¢„G£ô±4È'FÈÙ­!´±1(È7§FŒÂ¥6E,igÞ·½ŽÀ•-Æ.âÚpÊ*WFmb10#Ac–ºÚÂ80RiŒ##ðŽEY a–TÍ„¦4š'r4ƒ†hÆËÄ2VR"¨˜"½‘û¢¿;¢:ÈU"Ø•aëÚ0NÎÝâJ²r A¡1Æn¸CD¤Æ`iÃb§&ñQ‰$`¬\â1ÆE3‹rõš4DÁTÄ1™þ]û|ñæªçÈtQJnBéõÑ›]ª2”ƒ­AÜ;Îj©,¶¥laTicQßHœŸwVM*¯/ Ê#AAvš;éŠ`"¢ì¨:Üú>^®Œžˆ WË]H SíNh‹ e©»·ãX¥2]AÈb´,Æjå`ƒ­»i œ¿Î/LÔvž—¬«XÊÄ0„3,1C”ÎgŽhÀ@Ç1 U–¿÷¶xCEqíx@“zØîk~>¦éeV1<÷<•å¹Ùg>]¬d]´Å øµIÐF[EN¿¸hºm»Ž‘§íß·£½VΓUåå A9ia* ‡² ¡ô³×s#MiZx#1EQ®(õúV{¶ýÌôöŸÅûÿ?»êçéjëmœ¤”®ºZîÈ_8%QˆÐhm[n€?a¿£hb0biÐuå÷즥~s’I· Šä»—âÉÂAá~ÕžU'8xTŽŠš,Z 09T5ðHrX¾Â €ª K“@KRÒµ’™-¨"T+ú½‰ŠQ ¾W¯¢½R©¹@ÔãC°4(sñ¤¤bT"P&WEˆB 2iO÷æ)!¢A2iÈ>ÿ`™ Ó$|#¬'I$5Ê"å‘K#éÌ bn#e1e²w;ÈÏ%) @{ŸxüørÌÝ‹øÞ› w²K>ÃÛ¾û³&Ãò8›Û[ñ¹U6£òÑ÷ñoˆäã™ã"ü{“]›aù/æ¾Ó•ŠÿÝW)¤Ø9Ä‚æ`’XòbŸ8³¿…Ã;¼¨·d J2T 8BeaÖà E:±¡†¹Øql—z‡ T÷Ï7_!áúg î'£GŠ“j“1Ð?øíÎÒœìá^½«H4Ã7u Á¢‚ePA$ÖaÁ†)…)¹ £U¨Þ–¬cúɃ§#Bíá䫸‡ÃŽž‡ï:;¼IØG# `3YQ¨` ‚`«´n‹"Fè A LÁ Á5„vo1šÀ{¯h%,âUÂãö7¼œŠÑ5•¦œ‘…0ŒM¦ÔŠP:»™ÑÀ(¨Rª©ˆÅi—6ÈŶYmdÂI„¨“bQ£RiUJTÅ*±2M!2bª©\“h6*X$rW#nÈËëe°ÀÐA¥5LM Æ£F)n¥Z pLÄ‹Cš 0p ÌX²µ2ÖD¢a˜ÖLŒtà’,Q–;BÊ¢#XQ£ZÖÍ X`)€F€ÒâéJ5(ht(1,B€Æ ±iDÒrLq,TU*•Jª•›”ÿ  ¡H0LR¢QF ÍìÔŒ †¥R©U† UUDUʳ}´l)UUJ6dË"Ù‹\ÙœJj ¢Â]Ia–‡'®8âg$ 8YBx 5âÃ8Vç†2L ±YÿTèÑúÁ™åWŒn6” ד6^ÃüpÍA%iL¤Í-ØíáÓ €þe“l¸h4Ðcjá­…¤aN—áÿ6}ÿ…‰D_Ü”ÈGè>}¡øŸf;†@Q™™cf ±`Ï?²  Ï>ZùðdBöwüÂá¾$&I„fÒ†dKBCZ/ƒsÄéãw'eÀñi̽f©"»µhásà¨þ¼þAͱ‡Ìmqìs×cÈç³PÀ$ 3!i†mÑXÙ³mab©$ž¤†Ù]áïÒæ÷·—NãAêañÓ%BDâ¶÷Ü­–™…1EpÂVH)Ö'¸ß­…3û¿U™ªµ3w]•³m˜5®ÐJ#ËÝ{iå™ùqyo0y(p–š& f Þl%ÓgÎHéH’Ó^=š)×§#,x„2jýF581´H¢üCˆêÔÄ64^³ÈTîwß~‡OdþÖ“¹3X̓§Ùñd¨a&l’Ž˜½ «©·BôpÆ—Õ¼_8¹Ì|ÏQÕÕ¤øøóÖÛ¶mqœ1µ×ˆm³,晵¹ëØ¡æT!&¼Fþžòèò|ä{;Ý4µ8âåÙÛmŽšì°áÚIŒ Yàä’Çט 2rdf×Q.t@UŒ¾qþ? ç'oŠ~sM„ÞodŠaçLž‚!XJb \@­¢’ŠDÊsJQjÝ+L€TJyF:&Ž{'®|ÂgX¹™# £Œ46_Çc|tFÒf}‘¡ß¿\hoÝ› }D_TÍ‘²4œm3ÇYþçìÃ&®þ4’w…¾ïãlc38}^Ú gà/".mHØyN¾>1AvÇ!x¢‡Ç¡z`‡Ê>JU|×}|{Þ,å7}ÀÕy¼dðryBÞ¹X ¶òÑ4uÐÑ#r5M3Óv´þ°6ï8²U“¾ˆB2Z÷Æ©Fè§ÄN&fóUv¯Â#+†½²óJÛ!#Ì£$½R&§ÖÇ©bé/+Ty”¦xýWáwÔŒn±¥ôÌÞÎ'ȼý™&Ó–"‘l-“EUb‚¯xJ¦æ n±¥–UŸå² ѹ%¦ïv±¦á¬ ÂôÇ'颪-…–È>噉Bz 8 ¡ìµ^$`èxÊŸ™@ÃÌîWàpæ»—˜lÁ$LQ "% /A@©@R!IÉ)ý¶JA¤£H Ї§?aùýØ{¸t霗Çd²Pe9vÑD™Š4µj]“ìÚ{)¢”=s2QCŠxs‚xP•áÚ›¹UÂj[@êV9–µ*zrXHn%>a}^Ù’j·?MŽvË‚?jàÍþÍyæóœb˜Ãï¶1É7 ¯áìB.ÞcšÚ‡ÎÓ¤xR)1)ã™ËõÐ÷õðÚn(+IΊ= y«¿Îx†¼'o'1nIuR­tqšÂý‹×£ìúdÏgúÒ_³óB¸Á¡$&ùõﯟs©LàŒ²Ä?¦¢6¡R,|êS0k{.øXW4å5ÜAˆ»»—¨oq7M´ãdÈX2xplh¸ªpï×À4àÊH•·ºŸ[õ­†7ã¾Sûdêgl\ç]Žx,¼vZ¸)çÐ=ŸìÌ£à™Åý(ÿ<¾WùÑv¢¢ ¢ƒ»6Ûuc& ôÇ»t4Á ²Íû¶éО~³Ðìùù`ö𗾔߯$h˜C˜8¸M˜Ç­Œ²ëPªâ°6ÒТ-·i8FKCÄΛaŠ+àKÉKãÁÈHÅå߇Í44y¡œô¸Îu›€1¦4vÕFšÀ„ÓÎ\' ½Fۆ©dÀ¡…cÝÄ÷–cB˜f÷f×.8;ÁÁ*Û0,ÅÂPq’˜B=cS­Ò 6 ±"b=ÁÝF$Y18aIÑÊlµKPõ‹…A°2&(Ÿ­‹¿Œ·ijÈΆ~ç{ä§RñÞsÞݰȕ…Λ…2ˆ‹}ÛÜ·=ô•k7Û-Qιɂ̂ß„ûŠ x‹ÐLPðíœöïÔ½¢‡s{B·Ì³NR7#p3P7W‡;VsCnXç2Ø2JäZ £@­äs€È0?¡ß›gÀJi¡‘ P‚‚¾ÆWàã™Jw-üg«íów'îÄÒ„¶=9®ŸÞÒwûÍ·ÊId,‘jTé¡„?œSA`Éb¶rñ\i4:0dÁÖ Õ‹mF}¸á¢OŶtàD•U=× ¼ä ¦õª³%l‚‰a2³êa …2Ï××åÇÏCÎhõ¤öǶ ·.\ÌËn$’Ž6˜I Q±Œüyáý”ÿˆS»Ÿ%OxzU=´–îÅæŸGèä8îÊ^“®Í/ñ^K{À©d»© ‘4l{‰ØUücýëÜÀ% „¥V"a%„À?Ï11 a©%‘àNÐyHr ~¯Ué}ÎvœTÿFïuâÕE“t/+o5Å+|;`YÀ™8¥P¥Ól蚊ó ¡ †ü:ÿ^¹õR¿¥Ý.î3rX¨­æ Ÿ ;¹Ë!?ãë3ÉE#é4üjÓ:fæîÃy..jã™k"ÔWí‰ ç2gPé3ûŠGñðߪÐuûiú!Û„ÌéD\ x|/Óz0ݰj;Ä+rVñÙçø¬ù<÷8ZiÛoþS¹ã²*FýÿËàu°ú±ÅbRC‚6WîÄ< 5©ªR’ÊÇ[¥¨×!»`Èm/Õ×Áî bI-&%£0®ÃÀ0¾Z*òc·lõDF—pO¦Ð:£7÷ô5¡#pT{ Pëþ^»õË71¦É p„¸@šÏZwyO4…þª”’æ=ò'1 ã ÓÓ¾Öz£Š-xûÍ¡ÍU¾yÐîä*ÏBsÏ;l7ªsä6&ߘÖ‹eq”C ™i‘åÆm¾E³TžãÕù Ðu˳Clܧì9ÇÏdWGqHàKjfI IvqKèÿ=˜B¯äðÙ•°gâŽÀΉäË“¿.q‘jÝ÷Z@!3,·Ãpˆx–E6Ú¥ò1[`žŽ–o=Éz}p‘Ú†Ê`vr­c¶m/Ñ7;>\oÚI$·­N†ÇC4u†@ücozb4AùÊÝìz¬`:­ÐÁ†dȦÇì°]‰´»á®um‰Å@cóØC^ŸwÔI«Áð>›Ìë³-ÓmXéåËz_]c5ã–Øìý³¸$íÚÞ'Õpì2x1‚£²fØØÓ æžKøúµù£ó}-Iã {IF•ÃdŠGë CmmÙG30k< Äñl£È6‚a˜™˜AIó\ƒ”¦€m:HøÖÁm¦íºÛsö§ Al‚¾4±B„E­Å: ¦â58©mgøRÌÇLW”‚ŠØ8r 'ÐþHÿ Ö¼üþÓÿ×ÿUz’&<ƒ‘2Q(ýÄÊдðÿŽÿj~–‡¥;\v¥š¾/ý¨‡‘ˆÐzq¿ôñnŠþæÿÓ’e5œP4æÐ ‚Oøÿÿÿÿßÿÿÿÿÿÿÿÿÿÿæo“í×’¼ûím6jÛb4(Š ¤IPeR€€(@P Šöè ( P¥@  @Õ˜D€ E(ªP…$‚€(@ÐÛ¶„P÷•T }³%2·ÝÔªN›#(ªi:ÕF¶Õ‰vh騰êëb©Ó'V4ª«ZÛT©u‹°1­lÚi)(Õ¶ƒVÖÅi¶ÃXØÕB­d Û]´k še-eT m¥[j*¶d-†­ƒvõi6e+¶WYJ" •’¥« ©£]jIÖ¥fÒ*U%J¢˜4Ýd»e°ÂVQ`Ô¢T¥vÒí«&ëveÒ²îaÒ‘+NæJ´klD(%$ªƒlÖÖÙšª±µMƒl5 QÓNí§ª[4m¢»»ªÛfm´’!*ˆÌVMdšÊÄÆÌ¤¨eÕ¨be„«£FìãUŠhQUE[Vmš4[Q­6Ô Y‰Au©UUÖkKc¢K©USfÛYgYU.Ú’U­U¦; ›´Õ÷¹ÕT‘\}Pï¯[ƒL¤F -hhÖm·×I9´ jÚM6´R¥V±_{žó'ZŠHs`RÙveq5‘¶ÓwsMT%)ÆÊ5DÝï7ok®ÜÜÛkÛ@#Z¶ÉuL¥B貆µ¶m©šÒ¹h’PP”¢vZÚ%b:°ÁU;aÛ Rƒ[g,îéÎîœ% J¥ZÂ-†¤¢—Y ÒVÍkY%mÜëst[.YÖ¨hÖ-˜ÖÚ´JµÝ®Lèî°ÐmYVµtjDFc»èèq%° hÐf[­š(­1Ñ»eŠÆª6ÝŒ[Ví’•¦… ¢T­ªµÑ¤—f ¤¢í¥!Û#ZÌÝgAXv+vi6n²QÛE-µVÙ°2ªjÙM–³¬¦Ö™• ›M¶«¾÷½̤¹¬jj(¥ZFšìÔ+’¨¨´jªéªGÝÃ’¨®}†ç|ßZÑØ2¹V*’"¥V™¶‹mVJj]šID”—N\6äwlºÉ£*U­–¤¶ H•P•5’-²bÔ¶³ 7i(i©Uí×lÉmªŠ’[meÓvuºgX¹hi›jA(Q¬•ÓlÄ*l1Ó*ªPšÔ¥¶—c¹MUºî£k]5³©J’¤4i]š»b’¡$ì×NÝv›¸ê[ @QT¶«wgl¥KZÛ'c]mšš³ ¨MÙ]rWa©mfÑ¥@²2lN»˜N²‰³-˜HtÊ´ë]JÌiË,™j‚Ö‚HKfµ†°7aÑÔ†**ìÕØY¡Õ‰Y®ã)m»nÚ„¥-™¶¥¦Û-wM(&Ú)vRÌ@U®ãØ¢”"¤Ùw:¥PEPJ:뵪vÆÚšÛÌ4Mò€-éê]´¤Š] ³p,îÝ Ê‚•Ñ©ÖMmh¶d]0æÄíÕvÕ¦ÆJ›u£­i(ˆ§FçsvQCm¶’‰Ù¹jPïyïK,BH‹Ù¥†7w'l:ttÖ.ÝËdlJˆT"­ºÜ]Ε vÊKC»•UÐ ª´Ä]:äRšÐݺ©Öºbvi,µ)mB¶Ê¶Â6­[hEFµKL%)+Ve[1€­« :lÊvµ·v:Sc:j¨Ñ¢€¥)JºÂU 6åÅÝnRWnÝÇFvè[uÕÆŒÚÓN˜îº‡6Å;0ˆÛD‘(ŽÛc*€)S¶ÌØiQNµ!m›aZе»k­7s\ª(D5ÜÒ¥)QÓDI¥ji¢Ökv˳b#LR“ZV–ÕRí”ìÌ‚ÙMPîÑ*æ Hª%vݵm®ÚUH/Û•í…[2m’Sc%*6£U¦Ö#FªR5Wm[j EÙ”¤"«mT¶É#®¶¢VͶJÛ1 PÖH6Ú³Bª+jîkµÙÑU%ÖÖ’UBm¥©ÔNÚ„vÉhamV³YCm"5³TkVJJ¥wuÁtÃI¶¥MeZ5¦I;e+³t‚êmµUÓR•DJ¤¶Ê;9Ú)]­…«n±U]m´­bKZÕb mÝœí§f…­Š)j‚a«b°#wrì5¦”UµS-j©£fÒ%j›aAumꌅRvÅPuª¶ÊìÊ•ÚÍAvÁÙ5Ù‘٪v˶ºíÜT´ ”)¦ƒ®¹ÖJV•lÛ³E]šèÂR©’ Euf©v×m•dJws¡.±RêÖY±¥*ÙIk)¶í¢ëTªëH)KÁÜä*“ÖÆ „IQ*ìíÜ-µÎµ;L¢¶ ­N´]4!¥²ªkK¦D$Š*¥T§F`Û*¨5J«T ­'Ytiwc¥u€J”;¹G;2%EJí§YHìÕ[-³F5ÑÖµ¶ÊµYB¢mRÓ)Uu¤ì0Û¹¨•: Jë]µRd›m’[3M"¡[b›V­†ÖEVÍFÆÐlm*‹ZQI(%B K¶]šÖ…F«$(Ò±B›1«1”¡RkZ#f¥µ”ÒšÖ2’¥Z«j4h›AT„hÂfÔÛkJ»d+±ªlÅUFÁ”RŠŠ«gpi!ÙªKmBJ´hØekU×v©W]tÒ E[bØ2»Mj‰$j5E³lÁUKf•UR»SxYêÆ©TÖ¢‹3(Ši¢@¤É×v2ÚÉm¶ÎµÛm»n²ÑŠÑ–Æh ­šbÔScRk,‹]Ú)HNÖ¬6b™j”›5J…­+ZPk"Šª*¢ºÊ¥ušÄLÖQUmÈt”ª ÛR¹c-Ü×Z­4Ö´c]±Ö%ÖElÝŒÐÜÍSfÙ•m–´QEHEÁˆ“£6´dJEEBŠ J¥ml¨%µ´F%Z¦ÛIa[eŠºÒˆ”Öim LC+Z©U[»º4i¢@;"µ£›i¢¡B‰¶Ð[,Æ$¨DÙµ¶ÕR­:]ÈÚ[QNƒK²ª­iURQÑRØ +bj§fÓBTKU6ųUJT¶VQ4a)lÒmŠÑ&îîJ¡¨÷Ϻ÷ÝT›rÔŠ*ª•RmJˆ¨› 5k4ÚÕRÖ¥£)¦E›Z6Û¶•Ù””¡Á¦±T«‘’³ S³£¹·LUt¶¶ÄIQP­Yµ¢†Ù×NÈhª•UvuËm¶•4ÛjQ)SYhÃU›kª"©TE¶W'%ÙEm•m©P YUI J©U¡¦)¦’ØÊ:Äu¤)(¢,ÚÐÕ[0ÚµZʺ5£§k æÒpÚµ¶2Qmši:À®Æ%e¨¢•–2²ËRR%Fu·`“²jVÝÚݸCm-›Õ¦ÛTkRTJ­šT(ÚÙC±ŠÛc*ÚÚŠŠ‚lÖËm²¨©C[lÕ5¬¥l)¶µA+6*IREJÓMj¨š¦5U¶Ö$¥¶ª¦[nì©:ÔFÚ¶iŠ%ÛvÐÖUJUÞMëÑQtÕÕV”DÛ#eM¥!% Q²ÕF«(¢!WcIekm™©VM–Kf§wuÖv¡€ÓD›šÉ£+»8KjĪ€®š—A¢©³]nÍu¥©…H”¤m¤”v¶šb hS[ZʲîÝ–.Ý2š­m2Õª-µ»»m³T¨ÛR‹mRHÕZ±Q:ÝdÙ€Š Mt8¢Š*ªí¤ŠfÖÙ ¶kZ›eN»ª5µ*.6¤Ëvʉ˻9fÚ‹mk%)mLíª¤Të6Ôµ¥mk[KlÖY˜ÌÂM°NÚ© (·gH¥»wU -46Vè5vÔ¤‚IE -µÛ¹¶ÔÛikm€«[ØwMuÍÚ¤TJ]e"Ö–Œ-ÝÂGl¤k"KUmiª–ªÂ²N°äfÚ’•³UÖri¶[¸äm× µLëIIU½n+ÖªÙF¥©–Ì–e*RlÈ4j­©¤¢¦ºâª³®²ª"ÒL­bºÊ£X‚¤’4¨¨¥"­-ª”6i-mŒ¢)-Q¤7n©ì– tÎm–R]ºvµ«mV•¤PÛl›DZÒšj6 m¨-±ŠÑšÍ¬Ú$)UJ›mª´’’A6Úγ­%m©¶lÖÚ5«¹»¹»VÖÁvçk­%Ù”kJ¶VÓ© Á­’ª•PAªÅ ¢©fÚ0»s¦»kGl¸Ò³m©`e$R“fuµ­[1 ‚íÜÇYÚÑlEtîÎÚ©u¤ÔÚQF·Aè£R®×qZ1kJm—mT.”Õ¡”Û"(SfšÊRI¶¶Ô¨KX%5¨›5m›bÖ‰J(ªvÜ•¤—Y§rÃXÔ”Û$‰”¢ñ¾ÈÖÙ}ÁÙ€@[ÞQP©=Œ”QU$E(TD¨Š‰%@ET¨)!RE P ÷¡{7mmÓŠè×uî€èP(H@PUÙe7c  ÛP´°QÐh€‡ È(›@iHA2ÒbѦ©újž(=@#G© Ó&€Š{FR”†•==I£   "žÓ&¦ÕU$@Њ~%)%5GéF Ðh  €Ð )‰&ŠhÊa ˆÄžS L'©µGšI¶Šzj=OÒ›Dgªz†ƒ@ÈÑ£AB@h1š&ž§54Ú“z4)šž™GµNÝy}ÿàûžVñ÷|¾\i¬½tY3ÓT³5¼^«jøš[Rö’3ýóIкÛ:/¶=TÕí÷Õ Ô¼Ø,GŽyYÏiOÝ:öú´tëìx·eo<Ø^UÝ2Û ÎkU-‡:=§ÜkkÜ äX P4]5Ñû sï€|lå_^‘óÿ¾¿æþPA ÝŒ¶~®–výs‚Ùm6íÌgéÙïÏú®¾ìn>Ç&þ~eÎ\¬vtüûÿ=!ÀÐåàSåÙá°»ýÿûÿìýצoô^!î³DÓÛ1>Ô€ítêãGêš—Û½†ÿ}Ðø›ôö?«ôwožÚ57Â@̳xk“ž—ÏZ F"»wþ¶çÇ÷Û…¤”o ðµùóåøC>yÛçŽ!Ûùðyk¿ÿ_ýqŸ±u¸ƒáø’ó?3ø×ÍxÓ©Òá(ês2.e½°õ0äTÓ_©î-Å5}ìØÏ¥XÁõß>pxyüíÙC¸ó°i¾M}Õþ8ñû­ÿ9oÒ??Â= ¸ˆ|>7”Í¥€Lñ>nW}󿾌îvypá1®úÓ—M¶Æ\håƒ6,@´°CÁÞÎþ‹x Ì‚Ì0yúØ+·àýzü]<ß’Fs B@$B·ÐÈ,AIB_'ÍÛðùû½Ï`«Ÿ»®¾÷Óóý8ýìcÚ¿ _OÕ™$ϽÛ[úû}ì?®½ýsêÃáþ á÷y±ñ|b;ü=2þ?×ñhëÃÇu·ðÚÖ4³‹i¿lËÉ¡6òØ—?J:(êü‡ÔŸizäñ#­ìOoãø§ãH÷7-~êÓ‡{÷8ß›òýÎÿƒŸ^–ËhJ~GÉýý^ÈÛ†«+_“õ\ûûËÇÃõð8ÍÛ‡ÉæWÑ¿ŽOÁù8^î§¾ÉZ¥ónp va¹òßϧ&ûÛ"éïl¶^ŠË¯>ùOÃÚh=Ý ­~ûùþ~ueí÷Aäw¥³ãúût¹üü{¤€‡£AÙyÚÃý×·™Ú0ιCY[ñD¿-­r)3ÏÕµï{ÞöÖ²'«½wbNr¤’¨)¨9Z¢B T$c©êµOº‚Œ½>ßZü…*{3«Ï9—¯ê³êËM6ilãIr&žÂªZƒØ|kæÓk›ÿ<ùØý!”„"~4öÃHzã”ÄD_ï¶-Zü¥·C”K ´ÏêÇŒìÛ"Õ*~^þK›³‹Nê¨H,Ðñ”yÊË᯷§·“ zºV½¶²„&¾_–¹EÃ0øWÊžl=Yš´Éå«cð׈>ž¾I¢Ýê>~üƒ3ã»ÿš@쇬‹ÿ“}ÛN^ºß·§+v^Øÿ–>§Ÿ^{¿6ÓOü7-cŠPv´UÜþmü8sécñï7ò¦®ç¥¶{¨yê=ž~µ¤­î]{tÜLÇ´çnúß,òòÔì×9ãÏ^ˆܾ·éÔ/Ñ}UHŽ©jú|j·ôé–?óÁøTªõuÈò¾˜S¿L—vû<|/nþË9t¼Cð3ôÞ€h®\{ûÖW’;¨ð qøèî«Ó´?9[ü»/c³v›éäÓ§2Û[ µú¦AÎLP«QQü%-Þ£V±¾Õß= iÝcŽ1‹•Xµö+<:ùðÔShdn›Þ]:[Ç+yU@œŠ=Qò“7<à=y̌Ž>½wúr4g owm¡\nü}åó9mÁ-ê«ÃZ }W¦²ˆµ­>-ëIŠ;†Ï®r7Æj³¼Òê†qBLìRýÓ3Mö´ñË­€çîënÏukìü•g•ozÑÅïí®—‡·ØfxN$ïû2ÓÕàñàjXÅÀ‡,á‹z¾ë›™OëN¦W:˜ ÃKxÀ¾:ñå·_3-Ù¾k§²Ý*ÆèÏvüºïóáiÂ%D'w¿ÆÏ>Ÿeަ•y&P^1:L ã~o¨~š}sÛå‹^ îÏÛM…ìõPÞVWü•ù¿/?OËÚuCÄßÛ'—§Õä9¸Ë¶‹ªJ{]©Ó:ày>“I¨…E÷D$@î=·iëß¿~ŠžŽTéç•·C­ô²í¿™zôYù¡ã¯«Õ»mC|KMÓÜ“µõ×P€Xî(9̓£ðÒçÐgð°eÇ€ZI Ý赉7=Ð˧…9ú(Ïf½žƒt˜ç§‘ÌÀc ä|}œs´÷_Ï1?ÛQžœ üÿ5_‡äykóy^ïø‘Ë üã0ô†wkë òb'—%‘ë¿'…Ͷã­^]Ú75Z5í¿Nî3uÂñ’I \cÇ\ûì^w¼çÊéë+ gç¾õ~Ÿ_É×Ú¸þžþ–ñõüö<65Ojwž“뿦Ôyi¯‡§pcÕ¦F§3ój±ëàüóÊዾ¼ŒÉŸ†|?–Ÿû  sÊ­*ùåìþ£Ë$ùø§çìí~ ö¯áÛ÷~šþßñyyjœîþ!½/ÁYß'¼õ×Éç÷!ýù??ãÁãÚ}üÚþ/t>ê‘[ðÕåMögí.ïÙˆfŠ]ã¹Ö›o6Ò?é›jè¿]v?­ûå¦ébpÓ²ùãëòËŸ²“³i2O\3Š€ÞqU‘@S÷#·×á» 'Ñηåê±o_WIÝÿŽ7ß?ÜX÷ñûwË_O¦Àfã4?^»Ï/?ÍÓu‚¢+ïÞ§ñÎÎMU=¯ÇÓv¡ßŒÚ¦Kì ïóçós‚Aý7øzA²ÐP5M M4­#T”~ÚAµŠYUAZ‚ áD AUUCðQý<ÏÓG”ý§·/õP~€ª3öÄâ('ãž®øT$œH–ÊcTºªBðCr|ý?YtPUÞ©PdEQMÅ!¸žÕ¹@D -È ñ²À„x¥ÊDE Ѝ °!‰üʸ?^+þÎé¡‘!$d!˜•MU2sbãç!>t‡m-¶ëÿã§Çéä½MÿSÝÏ´ÊPÈ›çUµ@"H dˆIHÞŠ÷¯›¸ºX½B@qkFÐ  ºBé¸D±ï(K3u%Œ©±•t­ e!ü‹øÝëÿ/ÆÞ¬qÀpP¡ …(ê°Ô¿7¾ÃÙçùÚ¹ê?3è/{ËÕ‹$¶¿VVôn,g‘è8¾›ù@°f´SæOGOGÖ}’Uz=Ÿæý|g™áRÃÄ÷÷[Ü ‰ãD8 ˆ«Ÿ²|£^}§gf|¹üùûçõ>¾:ìÚݽؼg©ñý?9¯*¸ý%ÃMÆî¹åËDɃØZlŸ­Eùú|» §»ãñ¿H¿Ëú¹è>¿›ãÓŒ¾ãÏ´íãæ x~Zô8=•Rv\ÊÞ˜k¿óØ šöp'¿/¯†´êor>>̯x÷öÛqnfûdc²t†FZ ~\ó:}=4ñÓþ Ðàá_W yébžÚÓÄÏ´%ƒ™Èélðq[ÂÛÃͶÇ}îã@÷ðî+¥|=82ûÓí¡8g`ï°íž2Iï(<+]€˜Øßõý™—{xþ’k÷ýèôŸ—ø)ÙÕ ðîÔó2@ä}[.cè2Zƒ‰ÀïòÏ6Y Ð[RåbpŸÒ|þëI®ª~Â! †ü'>.|;¾‚ÞÏ}§Ófö”ði#Ç=P7~Ÿ“°l‘# grû6OŸi’™¤XE~͹üÞàoî¾Rw–^FzCÙ M²ÝlôZ‰¢ù˜¹¾±™¦Û‚É5 nð’„dwÚÊ9FTª"R€‰E%E¨QE ªd«…ŠVÔHJ„j¥UCbp&þ2ÿóõ;ù-êñò:{ŒþsÑ«‘”ÜGãz¶?Sï¯IˆóÈ S"¶T%¼¾ÃÉ>ÞPö§CþÂF𛻞?·®ü ú§9Ve¼ü%¼ùÛÇ÷÷kù|WM=‡žÙåÏ»JÎÜü!Ý^ÞþÝÚÏ5škÜJG³ú»¿ý Ý©<'­7vþßÝ]Wwè<>:랇íìçË.<û¼|9ÚNÌìZeeÛ²ïÃÇ÷m¬Û]ï'.åÒ¸Òü»ÙÓ+òîßâèN¨pÖ3‰â_|m9eL\ ÏŽ3kçĺÔäݼr×3‰`û9¾3îïCuÍÇæ½I¿®}†Ñ”ù•p5™ áŸì;÷ð;üû.]ÓWÇ»Ùc»ÓMzµò/6épì-;é1.=ȇeï‹Xýi1y ì³øÐy®àzWĈy@ïÝÏh{ˆx“¼õ÷y8ûmfØw5fìxôZßÝFë6õzÁèv oõG#^þgñÞoøzºèÑ3–¶èœ8ž_4åz“<¨* ii¯mküÍóg#vŸÑgŸJkÃu›L·@6;=r¡ÙÔ³p¿qhÌú÷ÂŒ&ÿ^ß¾BÀn5ì•ÙÝã;íØ ‘Ç7³êçNS"¤µuÐÆib – „ ƒ?õø`îoÓÎÐåÙïñ[DÔxv£ìÄå>~îǺ0t:¥χ/~Tfño@UìÎãZžyœDÇ,òß×Ñ­âš»¢ßÇ/Žàaáçs­ÀPè÷$f†W5&¦l£Ýß±qÜUHñ‹%âˆ÷Ýç𦸠qyf2ÜBç Lëǿȹ yyvy}qG¹†^F3âü·|Nì]ìö߸íÆZW6ç×>¼7î†áøC°ß‘óq‰'Þ<:z5¿Küß"qÏ“c”ç•ÛX¾”dØ“ªSa ƒ<*¬ÒåIC<ñ—†”X+„©«{_×~í¯°(†óËŽ—Î[=ó<ˆ5(„ ~¿]Ïfÿ£{í·_;—±‘ƒŒûO^?/K\?‡Î}ÖÕ“±|ȧ¸±ÖÀ&¯u¸]PÎùòè6ö*n-@ÈM(ÖŸVÿ3~üÐëñáeGÔð¸ NÞ kÈ¡¢ ¶T3"‡¶x•ÍvÛ-íÍ5žÀÅí¥Qô{4Ünî)å5ÕuáÊ´Fe÷”VÄȵ¾›ò¾IjY™! ÑE¶^zÛ_ןXHm·M –#Ck÷C“;P:ŽÆ9ê>rk \-Q1mü*ä ¸V¤½¹¡7sÜ Ãuæï‰¯¡Î¥M&íÅ<%7­qM˜¬ë>yõÃÃsÈzîéú+ŒtùV˜ÛŸM¸w^qò,)äúÂqß­ñºœþº4é1¯.V Æ;d‚Ù`™Q˜[–t­ÐîËWœ»7èØÊ=ß5·\58'—¦¾&»aÎ<—‹7ÅiËv-Š&uÀýId·Êž_·®»p‚âýw›xiïÿ%í¡“ZoÛá,{ Úåöý³ØjqsSX…¾R‚Ið:ZÍê‚@Ä(‹-¤±\¥¿ ܳlJ>ìX|`X—âTJз(îêp1’^Ã$È/1‘‹ŒÖ,ToW¦Q’ý¶ÈÄ¿uë<ìeV…q$IE»<óÃɃG >oMBòz«8n«÷vð49C¡l<B^Þsb^¨ÿÓëFÖùJlÀ­Ž¶y¼tJ۲ɔpDMõR†~:.O¨BûTÒºÿÖ)%uf'·=G 7üÆE{ Œ²$!!1j‹Pì¹¶äÉ8¦,ÈX1ô]ÞA†OÐ^ÕÞ ®Ñ=6Üœ¨Û5UÚjZÝÇô^täØröZÅÝÞvÌ< Àh×ßr9z0rmAA•“-«ÇÈ·Xëùðþמóuº!cøuTC-ã§Úæhr=˜¸VìrC™ãuêmb©šÎœjSÀ*’–[?:©ÙAË|LÌ ‘ƒÍ|zó˜2e¢á¡ïú9¹ÐªNÊé$›ýUŠêSÙ_E\áo¼ y‡^ õ·QŸ¿á²f“>!’ç^£‡qÝs“|mKà^ÊNÞÛ¶þ>¿ç±Ù©P×yߦ5ò‡uôpÑ·‡ç©ÈŒ2‰· 4o]S5;ûâ"=T†èD$GÑ®rB`!yë"Xípp÷ó=99EÈÔ°û^îŸ7·sºgñÝ£Æz/Ç¢v@ôrÖWv2ïèg•Š7Mwù©ª•@¢èlƼ›µîËu«;Œý>îÇuœÞøi‹ä'«O5ÅÒ@¬=¦˜ êðÉ8nv3—¤øêw^wÔô&û䎚i‹¼/¾wíàdžÞnŸQ g°ó4¶a‘·JåâKg|zì:fZç+ó°Z[]wêjóüywݿ禽žX9ÃäZÿÝÇ«ìãÙeß{ô¹Ýå–—þ®Jÿ+Ñ»L ¥îôâåÈ–1‚Ò÷ññêøëôDãçåÀä‡ÂqÒÓ+Q•{KʹmW¥ä÷ú}:UÌòt½å}ïž¹ºÞ6 g_ÕûË•¬vÙçÏo†8Û ì-߉)·Í-펹·Ÿ ݃jý¿EÛõñ2Hï+ˆBÄlKHÑP·žqKÂñ=Àw€v®¼,ïÑë¿"(¹kK²ÑMõØ]0s†˜:@|zÐæE~Í›ÓÓÓI›¨WKzòÝךdÖ‚úi,Ú†«ë0X‡oÛ§ùyråÄ­4*ZBÑ7è´9E,K,ˆsvks2çÈú)é5Yž]™9’çµ ¯_“ƒß`÷ó&–ç dz}‡aü²×}Kœ¨gn-±Z ˆc´OOËÕ'³Ý>™ôàôr؇t(,Ñ÷Ù=ܳ9Ü÷Ë:t§lŽç^¾y¦ðã± u÷NX×*æAàXïŸ9ÑkÃÈd9ü,:÷éÓæ›Þ—RGW'(jkkn$¬¾cj¾)Å!‘cœ1µ ^Þ/ðÞ/Ë“ïéùûàòC_¾wxm~ÝÓŒÿßvÛ'G÷k¥½:åÛm@î=y¿Õà>º(6ýö·Ð7öxrÔú¼GOO£xw:£Ý•là<ñÂas/¤¡>º:Ür¹q¶Ö¶V»bX†·ëŒ²2ŒÖŠ‘µÌŒÃ6pÈ,­±ný#uÈ £õzƒ–8›ö Þ›&èßtwZÜy4ci\HµmÖ™WÇJ•F(©Û™híThÒk‘ËÀùý‹¦£öÛ²{~jÃËwS³ÑÝÖ‚æù|Ë—ëYêPIŠ(*Šd’H¼6é×—†{¦ý2ü},7ö2pd;ç Ï*,îÜr®³áöd{;´È;ÂÓy~¾ç¿ØßÓ#¬' êù­w¤ÄßR€ð; ûæ™é©Û”òâ_×ê?VîcÄðÅ«²[ YÇS¡æq™7‡Pàpý_>ØÌ4P¨}ôz=Ÿ@ØÞU»Ëñ-óùõíðÛ,£‚²æZß_aüuõhwár,»?|·Ó×0y·Õ¬z`X kn!ÜPÀ’pµË%ZÔÒv}ì}]ôK˜…ƒ¸œí_3gÂ0’Néñ2ùûö¿ÛÞ{1ºÑFòÃò›q}ZºÙ¶âŠ#\}¾iéç}úã¿j{cÀöÑÖÔ`û2ÕqeŽîèdoç¯ËÈ>9îçò\á àšoÿù{çÞwÃÇìýœo»´-ñ¶Ý»nôªzR¸' ®è2«ïdfOd8Ÿwc«íõeC­%CÉ™SÂéë¾¼éò†p} îûêèÈŒõCÂ+‚V/Dµ\{-á¡ |;“výÏG Ï¿w'yó)Èü½û<žšë{ú›fþãwy1ÆåÎ=½¿Úhs}Ø=þýtâwï;óñà^}›²ëû%ñy¬?§õÝù´Ç\=ó†îkv¦xßÇêŸqõý—î:c€oyïç“ɯ¢þEåxéã3ú ÑâþwÜóú|¼½>û¼¦€çŒ#Ç¥é¼÷Ä~¾ïô®ú$gù:¦øwCý-|¼!~ƒè;þBóã矇ofcèy_ùþ@¯=þ>6ü¤[úñûÖ´òÿX¦„'ì¦[þ~ª;@ýü´]CÔúïõw^ý1G¸÷úFÓ—ð±Ó‡«>3ß÷’(~ôÝÏÚUÝØ?;ûs¾y¾Þ~ýøô&¡¨8ÿB?[¸þ–€\ue~ÆoÈgKí«·§‡<àú…òßæs·êÃ)pso®¿þÞŽœÏGÈºŽÆþv7¯Ç™w#MK½þÍ~ÿ×Ó£Ó‡–CåÍþgÀ¨¿qÞ–ìÜn~Qîjùr£ñŽÌ²wü,ôðÕõgBGN{+®ªÔn4(H58¿¦×†p ™öÙ÷û“n—»/›Ÿôq{¿ÇNÝe¹¬£·^ÿו?×—,‹x'«ûtÓó{ƒåÀç£m«I$Ð瞆Ækí¾·5ÓG„ƒË+¥wð³™Õ΋Î?φw«ùz0o¿(bç `«(b^‚ –ËqèËLºè}[¾ú1OÔQÔý[º¾ž´[Ï.ó¼îê¾®ë!ØÖ¦VíÜlcÿÇ·èßÍÖ?A¸é¸çƯ«\>~AòräMGeåç¢Ý„ð2Æ£âcåå̶aÖ? ÆçÏ;:Çì;‡cá˜ävùÛܬ¬{ûž/Íö­{]‹iƒÊö.=õSÇ.póýy¼“»ûºó2'' Üc7–“·Žx3 XÐk¸xÁrèT -۴ݦ«3MäåøÐŠÉJ+Ö@ª8ZÆÚX,F2rM[×íàý>A]™iäMybìãLoêÓÔcH±:zÓq¥Ž‘¡4ˆà RF2 XŽëÓxn‡vú7Ãcè«ïìœOT?ª5÷ÍŽØB„„{­Ò·ö2îj1¬fXÓ;Èõ¥æëÞ‡«¨ð,É•ÎÞ[mãÓËËÁñÈ2z<|O³ÃN˜ ùt *»ç‘ äÌ[“ĵÎÞNYß3õÚá»ódú/ô­°Î¾õÃú¡O<ßQ|i¾Ä•éÊÅ®8¼%ËÆG+{:ò2Ó:Üæçmqê7h»‰þ­6î¥}ÖõdâK’ó\Ã8Äi™ƒÔÒcé|ªùWчßÙIFƒù×ÄSò7ˆ_Óêþc¥òÁ4µÎEZ! O„Úau^7 hù-ÎgÖ¹– Ϙ3l?”ëäÿ#¸“è@ž ÒbæØP  Ü) Òø.LZÅ­‹2·(ù[†Ffi–öˆ^¦®+ßslæ.Sº—¤Êåµ3œ‡á}-üîvò¾Ö•‘i¥FM®ÛuÜ&&ùiò±‘™bQ7›¬äÜþ®ð­¯¶×v¸iz¥¶m°ZöÎ;îâ'³%ÜjRTÏjÑQÑb76¶9`Ã6(u- mk@×5bo,PçÎÆ\ðáWà±1Ý'¯i²¸ì0ã0¶‰N 8Ãò#;]|BØr6ã{]™ÁwseÑå/qö`ù¦„Ë¢õÜHÐ6®c|Lç…¼!ŒbŒîš—BûÛ4ë¡Èa-ƒëò#ßéÞe¢v[Ä=ûbç8Ü›ÊS ;¨Ú‡n;ñ¦/ÅÇ60vœ ðÉ<§ú4kÐB}öÜe©UÞþ¾_;óüáØxgOYÛÛåD¥€¢ž´”ÃÛæZßi@sø÷¿uôÛ¸õLxŒ>éY–Óqއ²,ôÐa ±5¿îCŽüV rÓ;%û>=á®6ã ØÞO\NAàþ©Ž=œr9²óÆK½µûåˆb«ô–ðÚú¯»Z‰ôjß_´í×uX#þXVûžwKq;G•=añ”éœjÎî–ƒnXßï—}^9wðkÚ±ìðuêÉÎhœÐÔÏc`ý¤;mÀúþSž vϤ¿.œpsŽ/ŒÞ†y&ZÐgz×Ë"ÙÙélÎø”;÷Ñ{ÝÛIúû^þ[=Ï9¬K~¹óã–fý¶–Ysñ¹®yýË-ßãLuâ.[è^Éèç™k”ðÏȽޔíû4³mü,ÛßM~zk¾šú)®êkõS_ªšÆäë¿2¦½=®APƒ $|ý]mŒ'›øÂÕÛ‚ nüwîwZ{¡ÚÔ×Ot»©qïÈ~©D2ÿez|‹Zyy}|?ÅHçÿ¾>ìüõ'ŸÁ[p×Ñè߇ßbûé:ʵk¯ÃcØÜ×Ý32@¦¢ŽAP˯”ˆ}7 æùjkâê½h«ZºÚ‹Á¤¾~¹p¼8â‹N9—½Ã;Óê¾Æüs†Nikdá±vØjuò¢ï¾ÀØÈ/Sd£i—S,¸ÇÙ•Í2î=÷=O«`³c즾ÊháMmÛÓÝÏŸ·¿ËêÜîø¼Í$ìÄ64 žèµ\­”¯ÞƒLì¢æ3S‘.k]xäjC­ÌìNŸY‘qü0Û­÷óâ<ØyQÇåExSRh=Ÿ 3É˽žvjhöR9ƒ®m”@µG—o+ÈLBª­Lt¢ñ&p_‰¬ÆyrÍùgï54.xðî ²äc}jç¥ò¶þV´¬eé>“’u€öƵ‡ºíïÊÑ{NTx–!¡Î“Ñ{\9éãÝé®GŽ p8w߬qŒmIÇï7ï žØR$‡;WIÆXúã[ë§qµÌÍÂý¿/G«)* ièžÔ\Û§Ê£«l$!É—ÙÆøVFyùÓ¼½u:[ºÄ9雘o9·êk׋™çÅ™áŸ]7cgÑÅc.šoÝ8x:s}PÊÛ¼fpeåÍø^‰IË&×ËÛ¯Ï×éðíKZlz½2{䪯eŠžzÿ_§ÀÚeé¿9,föÐxÓÙ¦G½Õ}Ö¦jù|™_¬"ßIånûFš¹ ×!Ê\½VTgbÕ˜R`ƒ¦UÏ Ï|Ï!M3A}Ç¥äg²åýš´Y®>ŠÖz"vMÅšFú"^á¼Ë^yßFÅFƒ"|øk•n±¤ŽÚ¯‘ mBT g”©”$ *¶0÷6±4¼[¥j4u±®Ts'@ª°…Ê›mO´/±•’ŒÌ²-¹7N‡î=cœ¡ÁéÐ;² ôF è;ê¨oYé/füºfM3¶w߸ņHްšÛC}±v0¼:s½¸Gž kaHZ¦¥PoÎW&œP y\jxî8"È<¨æiÃÃ'ñç ›¯KßKfQ¹1®vÁEõ5«A9ð÷˜ÓLí]4½ë”0äi{Ü1Îó‡YD³sšQ¿Ù{qáÂÄ`0É6°Ý{r ÛÛ"ÿ>å߆ݑ—æ®{VÙî¶a‚r†ÜìZ€–1‚¹d=ÓE/3ªÏtÐ bÓ©*ÎÔe‘QËwv é+ŽÅSÉßµ¦·°X$¡ié9èbÙém¸ïšHk0ÝàÑ–ÁçvAÏ}çѹÕC×ãûžZ7œOÎÁ3ùýï÷<º¿A¡¾Fù#š'tgdz HZÆvåø{<~½K¤þzp86ý%—0å»/*­!Ó¦yïuµò¨ç¿•›† ßþ~^ŒžîU§:IÎÛ÷_-Öç=9Õ¿]V™iÆ\3_b·g4ð¿pç}_›íò~}Þ£Ê{?.>Óݵͱï±j½›oµ›eM}T÷Ñ^Œ¬ÚãZ†v-×tï§™U_LÈÙô¤=g˸ “Z 2×°à~— ý|<½›^msÑ 6•Gªtç–ÛéøÀן—{ßôwYó¾¡7U, N]ôø—ÝÒÖíÖåì|+‰áÃ/,w(m:ñÒõÛè¯ þ]]Ž­°slÒŒÒÛSHs ^ΕÜò7IÝç7r³=]M4¾eÇ™Ú~».ÊsŒ"áÖ¨¶Ú_Ãlh~-Ïóh[Û åj7Ùìâ:våAí ¥u‘w{>¸[œÄ×­yíÛ>üñyÊFß­;¦Æí\PÚÉVävuôL{§Õã¿]wèÿ –äRqúLg–ÿ㹿ãÝúAûC¿®8s4$é>¼þ`°tO^6L+ŽûCÓ<íg £ƒÂõÙÆØL뇾õô|Š/=µÀ½Ã\t²j…½¤ëmØã-ú³O ß9ÖPN¾½ Ý—ì±â`ÄwÜ(³» ÖÖÖG.wV¡º®N—Û²¸áþ¥Ïª ,…v±~W^—çÙ¡nMì^?®Z_ ¬¿ðùsÓ„×­t !±=þð-Á1<-‘ÒÇrZsòËÝ¡Äé©ôgÇú¶Á¼È™_Øpîçëû78qêWu;·X-ѵ‚›lÓZj6/v÷±kUÈÈ”!˜gBës »%@%µt§Xzåv¿W_W§"ÿ¶8x÷¿«ÃÑ쮣ov{=YOô|çpwB[ÆÚWþq ´eZ+Ž™]åýÒßcÓc×ì™vZ¿;Ùko?©$“Ðxèrý`}êÏáê?¼º àì6:¡Þ„e­c§g%À×**Zˆ"I4þÊlK±,ˆ¢ÿÌçß?Oòýe¥«¿/·ù÷‚®1«Ükÿ_Pý~pý>Ÿ¿.03Íü®6;«gþšØâùúO|D!Ëbeç¾`s°šå/¾?gœÕö·ñîM«¿Ñ$$dFD„ N!ÙsköVÙ Tsª+SŒ(jŠBH’uÿÐ& WÜ@4LÏ(3bZQ"gÿÓl±Õ®fä"X1Hµ†”֬ݢBhC,Šg ÿ sÓÐÊXª(¡nÖ¡¢ÙÞíáT—±R|7ŸÔôŽ€d4-ˆÂ«Ãfņ6ºõç®â22I$’He™vƒ(ØdÇ>˜ÆÍnÏœKíPa“HÛ~ë]ãO]Ku.<4}}2qsžèn¬ó¾y´ŽàÐá wÄœ>!©'ýýܨ›gÆ’Vü` úMï0Ë#‘—BU9æ[¦†kC‘ô\-kEZÛ=õ_§á6òýéÏßcøÙK¤Sð7iÓÿÞ'¢¸vMΉê ;a;lØ ^oº=Cµ:r2ÿ.F’E!±†Õ±Ã{Kc[Ñåî·ÝýóŸÖcÖý…úÿG7·›r<º×[ À7ŽïŸ¥G·íîïþêù}klÃþ= íÝØ /Ú1àOñÖuÅI½6£Í§Ó~‘üLW8ªÙÔ³7¸Á¼^yå|ˆ7ƒõ 8/Jðï™LŸdÔݦû_3wÙ©h;z¾Ûó¼îyK3ÖwÙâBO³RÄÈ;,ZŠ,!É´ñ´µ'mRíþÝ}?g j30øþÊ^ qvÛÊ—¦ö;$9àæj;‚ÙVú±¤1ôo·f¿Ç¿Þ[†iõôèXáŠ<`I $ ]î…O¦‚Jæ;Þß³þSEŸ‚ZAí¢„|54§»µâö>+oø¡v>?hêyù¼šبõ-x(}MÞ¿2®š×OŽ›VÆò}ø_ŸêåËvO379ûÿž|sÛüÙ,·¥¬_ʸ¼5I¥Á%Jº×kêÜcE5€ñ.z'ÍUŒÃ…ï!®WoêÜœüOîþõo§¥ç4zˆì~aèÿ·ë×ßù~Cá÷£Ï÷…~ƒñÐçþ¸“ûš¶>‹?!ø±ü‹z‰¿«ÏÑãMºkäi¤’¤OÃë¶üw>ëqÞx¾'>}¿Ï²ÞÏ)åÀÙßÓ´œ­îø|<¾¿¤çêçbß/ý3üsmáïùÿ><»ô»v<9øxnøÿoí^‰ðôo¡é×»ç>sß_úwvÑó}þ®Üצ¼_/Mœ>ŽƒëvÛžKë´WwÁ*-õðg.~Ï߻˳¿]uïî:Ûéãþ¯Óñüü½ŸW7›Ã¿®?ÈwåŒý›pû/öîsí­1¦§,q- ûh?;<‹ÙáäÚmèôt>§w×ÃççÛ—C¸®îµ>ì·—ËNù1U ´Ô³EB£RT®_…e4V Va÷ ’H!ñ*ª©e¡,9‰.ä:0Æ– ê¨ Ji A*‰Q…TɃfÖÚ­ß•[2Î{νKg&­W_›ÊïѸc—×Sº¼ñËù¹ö}=½>޽³Ù××ôço‰×»þ¨:öÌ£ÂרK·4|Oy“wÖkÃúOd+ë¹·R‰Ì¨ùKzª¤—¨•ËÈù½X×&§}ªÕ^¼8ØŸÆÛT –Ê9@ÌŸå¯GZ×(dØ ioáÛ,4eVÚ`mïObsÃŽ˜nNïAÎe͉%÷1¥ÕÒ‚£“K×ð–/‡ˆú£ÚeÚyÃt$ ü]øÛà`ýó-=ž¿†WãåYuëú{-ÃêßÏáÝé¿a™¾eœÚxî-òÏtwïçˬå»ç×·` ÀþƒÖwòÿ5ŠŸæÙàpüÓ»¸·èÒÉî¶n„í>­v¬~9ôÃvª-Ÿ¿“òÓñö Ó^ÿ¯Àãgfv¾¼uY[ùõåÝß׹ñÂÅ®½%òøù6½7õùýÞéßæâ;ɇ õƒ>ætÎŒ8|§> üTÇ?í?NZd’IŸÑd;eOuÔä~ƒ ß¶„ô[2}WÛòmú6}ß\Ë—§t·âî÷ü«í ‚ŽfÖªØ,äG)}Ù|/—Ó(׌’¼eòådùñôïí˜åòÏc´ÇÕ¥rÖpúþÒö>˜=MΜyr¸®¤ë[‡Mà?'ÈÀgòý£”:ÞÀ¿`D€B…XŽÑRÚCcq¯I¸ÜšŽ“I·÷(¤¸ËQï)+‰¤ìµeç÷ìaŠi‹Döϰð.œÊ=GaèñÈÁÜPi™s;n&¥cj…FGì…ÌWÝØ‹ƒW©Ý1Mר`!ºEùt¸àoq bà(ƒR\ÝéµÜø^æ!s|v–¿`ÙpòoR0ÍEÁn5lžLr!„r´À[Ç·Ùù¿£Âxêv½£³Öqïìµ³Á'8س: b7Œ•²Ô‘Ï…mñi;±M¢×Ù™å“\&Ð’Ú„†'wo1êÙ…ÜPªÿ3æþoêøß)Àšóëéì×ýÛ»Ko×ofXáŽVý¿]½](ÝÐü†íñü¹<:\åÅ­ƒ î:Wž—áÝo£/™c„œýü$̤ˆŒMgª'(‘‹-(„I $ D©@$dVD¬¹ï›röv‘®š|ÛoïÝ›ôë{å×#nÛÀífX/$°Ëû½º®º‹óxêœ3 Æl÷I«ùY®…±9¹ÃËÍì7ô/ø‘l4®pp£Éý½¼[Ã}„ãF½³äÌ~ǻԆ56æ½¼:¿.½ÖŽÇ®0öSåÙâU‚Ö‰mÀ©?}ßÈàe¶êÔª:mÛ™ü ‰•{© öÎ\HS!ÎÎ|ôìâö¸*…=s@—fö0±ÚÈ<Û{ƒï˜.]]·µØëÐ{ú…=¹ÎíÆhi9í#|îß“{çÃìæòWÒrÙÞÃé:h¯ÕU³khê;²á׳=&V Ög-Êš„‚É#"„…CæµZ¨w¹À7åÇ…@ì¯Ð!bâÇ_°~Ûßêë&“ïÓ½þî|:B%ßùi~ /ý¯ÉTóÓÐü¿˜åtÿÿvžsŸPÛG»Ø6Çüôëb¾:ëó4ãŽbñËw†~î‰ç”=Yk·`s€}ØñÏZÊó™ÝÙs³}_ÇÑÙ{— ~N]ywe2‡tžTí‡ÇoMÁõü´aNï>u¸õ«ÒXñ6›èá¼0r689¿ª·sw0î×Éú²xïÚzÛd KåbA±Ðæ‡òÀó˜×ºÇ6Ï3.­ní÷W)¦3™òöwï onó¾7â]¾-€\üeÈÖH£û{yþø¯Ažž½Gß—F=] ßtÏ7/W†›sÝæQ+‡ºÓ„¼¼|õÊB§ŸC·ŸžÞÓæ-x^%·q£Ì®\37kÔ°sç¦Ä/U'mÓÛ|µìtöñ†[óôÍuí-¯qŸ«¶» М¡:éë¾Xñ –ãÑç Pxå„(ˆi¸î“=Þ$§Ëßöq åX¯¾yvwäfý5^Çsë|ðOÙ¯kØx<¨¤‰Yå÷NWðåõÄ#ÚSØQÉý'J9}ï†G¤ïúwwq2f¹›?Q´Kœk7³Øwo87q· egµôz“Ìsù“.oo|Ô øè¼ƒvp8Ÿ#©—¯/³ômãBb»SÒA$þ»·g_0MdçÞ»Ã]y©ØÀv7Ü=>Gßg>&…Šìï’ŒVYX;ÎgÊ…öÙ ^]¸½ÝNEΜi3Û;÷ׂ£ÂŽl6ÁråŒ:ÌÛ†3…ýác,‰¬îá±® ©Ü*ïŽÃ]Km$dËymúüôFHÀ_ýàTÿø¦‚½Ö§ˆ/õysýŸÕýaÇê›—òž¡„ltðŸ0|›zÝÜ3sÜP{e碎šSÙÿÐüÔþ`•±±!À…íê²]ÖB"ÊÓܶ©-HvúÜÞ÷©˜gsÓY6ht˜¤,X¼¿g®æñ^Î}Ýý¾Þf]½¼a']Ï.ÕÑêvšs¯ˆà·i‘©æñuwwv|¨íñ z_]çÎ}9éמÑIž{üü¯ôû×='Àjì{ßê¶/¾Þ"ç ¼ Ù÷L²ðËþç+û¤¼>óçü€}áövñ?o‡^í29óºÎWË_P_Y>í—ÃïáóÂϧõ| Ú~è¶!;¾üÍ Óm½§/WÊÚdtgd‡mTùÛ <üõz±ë:{ž|mr®­mЇWƒâçˆzû<ÎñýòBè‰Èü9c´þ_QoFyéÚÿذ1—:—¶Ã­§½,i Ï í2Á¡ëú´Û]3ÞœóÕ0ï´2ÎÇÖûs韸ݿö=ô[qWæ;»þlÌ—éŸÑ[ãçóÛ쬒éÁíøà¨ˆkŒ¥¨Fÿ+}S]ôF›pÓ—~V}›í ³!®Ü7y1[ïàÔ÷üϲ¼K¦víy÷k¡u:Öäédtÿ Ù|çߟok ÝPƒqmûxÏ+Ös89ëø|%ÿ‘èϺƒª?ƒÌðÞ™ø|¾_Þ|gof?åbäß*ç,rë»ÃÃcLÌïV‹¯ïë–ï}¦\°÷öÅhŽYË&^³^Ãøøÿ?^¼7Ï#ÕÃìßþŸöz,nöþj<½-=Uóvÿ8>œ·í©ÓOÿï_Ó£þþN>©¿qÛVùç¶dU|0g¸Ÿo³é–ö:íïù4qµHdíï 7<•/G.‡ØSo µqãÕH‘ËcŒwQyj”BûWÓv6…ÔêPÙÆœ ˆüñPÔŠŸ|Y$VIýEŽÐØqy„Ãö²@ºÁ-?¨`Gî4€J/¤ *(Mh Ȩÿ`Oåö~ÏÇöc?ã­|iåÎ^˜»ª J©$’‹Ì$rBH㻃`q‰IŽsb¦âÃà”š‡[$’„!&F°]ÏC\gM2ÌL^I |ôü A;›¼ˆ]UW|0æ3¼ +„5·92ÔZè~ð9Êjª°HÙŽ-žÚiŠÂ)•+÷ÆX´À}:¯äû|>ÛËÿ–}Uþ¬‹U³üzÛi–>Ë(záç‰õžáOz=AôH±ü–5ÎÙ|Ó ú&èK’ë†UŠ­"’°X*%£©@-H—¹`úæŠÿ~`€p?hx$Ç„‹þg( ÃýûŽ‘PdTêþ°ûÒDHIŒRAçt:BþDÿ:¯Íl(ÿá—á¼ØRª¤½€`’¨ü T„ž%#ô_ûÌ üMÿ³i#ÿFðÁáú%W×ð¿Ç>~¥{>c¯ŽÐŽîO=§BiÝ<¾ê¤q{{/N–ŒxP© ¼³CWáÓ'ïàd¶OÜ*yxOç=ë®ø€9lBA0À¥?àHzuú2•zµv7Ñu’#!qÀAo_“ýIk\Ä ’;^¯Õ%âZÐÓógM<`•aS·F€kzó'Ygò^“ùy­€‰ƒ³<ÉxCŽ?*ªá•ÓlW-H„‹ÀéL!P)¨m"X„‚È„dŠB,"H ’B ˆP$„‘!Ò’¤XA*bÔÈj“bŽèœ¤‰ÖSII¸hܤ!!b$$„$$IÒa—IP(Å‘x¼Eú #¾¢ÉQî8PÜŒÙQ ʯÃMªòJ!¬3abHbºÖÚ˜{N¥›ë³3 ybÂæÏû¨ÿª’År½Ëx¹ÚÅÂ¥m‹¹òU59Ê+üS¯„·Jó¶;ú–¦p¥ÛÊÓLçFñ‘7ý»¾žÆ¦ªOSó­õhŒ[KåºI 6bÜÉ–·¸¶®¦¶Œwn —ö)nùvœÛ¨]oË~z5VÞ›¹°Rn^@.´å&–üÌÐò…b;6Æào¿²%Æ?yO|snlf²Ã½ZlM¨eªMµWh › âúU´&Øàs›­B0jÏÑä/¼Ûj[5‡+]™yñ¤õ«Œ :Fà­6ñ—M¹Ów…ät1¡š>Ñ«Y]6Ê=bÍ ®t_.rÙÛ5ŠWx3Öf<9¥‹ Æ%ó¡Xw‘Ý,š»NŠKº “›»x–j}HÔÛIh¿{Û;Ü´¼WG,P£$£]‚S+ςėv`nò³9s483µ)}]rÚÚË—Éké’)¢<Ÿ[³ÌÜFŠμWÔJ7Jvêvºò‘gµ#zéÙáKzÖ «ô÷UíŸz{?fhÔÿ~ƒrí¥H*`ØÖ*#•kÛ*É»æïšÒKjq£ÀöÜ¡ÝÔÝû`ÓrÖ×XfÐïwÇ^Öb h%Ñ䓞yÁÊ”ióHóË5ã)mECš;‚:㘣F·×{Eà~£ÍÛÖƒ² Ì*xµ“Jy§'«DËÙ¹« Í§¼"’‡… ž«Ì»fY·ÑõÛJ ;‹Çð¦1£[½¬ë¶ÒVîWìÉÞ¯¨n8ûž’†Ë1û ݼ¦¼lƒKíÔWõ*"QqüÃ.ZrnÓ½w³²&¨ÊáD„Ź›cÕt”gSÁ¾îúÈ¡lIS£–Ä©8ÚŽÕs¯àùAgu:•³ccm¯›Y[¡/.?'RöA'³oiÔ´]¡ÜZ•¸!Úï7vÐOvUïB§U•Ÿq‡^ GÓ ß7rœZÉ}~`o9JQMÑNn.,3“¦QÊ ŽgKÑL³ðh<î[CzbúÎû•ï#ÉAì®[ ÞBÄâ/Š%ÀöìÎÊ-?¯Ó®‡ .ºSNϳ‡YOË©LçYenu¥Q,˜àÀ6žŽÞs 5Ù~e@Ñtr•äËuå™m´=Â¥룘¶XXÊAVpÌn;RØÈ«^5\ÄÝëÇ`W2î´jÕ+¾´òI©T®”èZ{Ö±®V”¹õ4ä PS"í[ÃAµÅii»DfÐ݆Ãeܵ#cUÕƒy:u,°÷³„i)jÂÔ ¶{º°89˜M+m«à¥Ý•9ÑÁ@[½Ì(V'¡«<È٘Ͱa« \i‰¨ºåX¹Û‚¦ù4«B¡‹¥¬¥u—ºéJaé¾Z·ÓlÕAJ‚*‡x†yÜ«'•J#¡FýîÞÝjíîò‚¬dº: U›«Í.õöMp~ÎæqÉzÌ$oP&@Å8õ›«>÷¬a亥ón³Œ^TíAún˜5æžÖ.¾¬úðgVîÒ鉞ÅsÄðÞ•Ðòî…—©Vî{±¾¤qb~Û-(Nª™BoËK\ÍÎ]ìjËÚ7䢼ÚÌx’ƒ'q¾cš‹Àm:à½[:À8¢±»kXCÙžÈÌêÅÚ ‹PµÁüûÂÓ@íZa9°¬_.3ƒ7É <÷—ÇHìH…¤ïJowžL‡(km:{Û˜1óÖY”&âžòs4ÁœžDO ­eÔ\hW_Óx9¬Î»´ör7ت+rËóõ¸yoSJ9LÖ,fméõCÎEy+q<Õj`Eà´³]YÎzïEòË­€PÁ½^§ì6ÂGsžÈ¢ÇR˕Ծ½)NláÌßc¼Ë ié«Ü´q­‹W„KÙ2…>Ú»ås[ŠÉ‡v²Ï‹W¢T÷ŽòóEïR¤ob!/(B®Q—Ϧ¦V»¹3¥§V÷å`´\4B­cEfs —΢ÎðøßnûÎøDü Õ¼FºÅÔvè½MÕÄjávä+KVvýŒ÷¹ûÈ_eº§Z4?atNÖÝ RH)ºåm«Äe{†k“š¼× S‚T6üÕ"§jH‡!:e¬%[¹Úu[0ûØìÅÓd}¶²JºÔE'” 9ì8qùŽ„ÖR59±Ê¥^첓¯qòçº »:„x+'7ÌR·!p9áW:RÎÓß$%»)½§ .Ô³N%`ßK3(c³¢T¸àcwüÛ§í¼¾ÀNqJrÓVOm}p£!!ºÈ£NVéÄÍ ÉJïôyâsÀpäñ˜³2¯+s'vo…mwhmk“4_U¾¦Äýž”,uz­ÓëUwN™Ú>3>S}ÏÑÜtŠÊ;t‰«|7Y¡'siñSÃ¥¶n÷hçåïw¤Ì«ž½{žOI\ð=æ(tç’ÍnÍÝ£‹E[· Šm¿ÉIYW[¯™ Tëèô½¸d¦Ýü߀e_µ!—nµGç4°MP,WbÍ_êLÞaä¥Oqâ”hâ¹O6¯0Qfäc’”Ä/ ÌÎVXʾ…P3ORâ×,„?’W„“VXšU¯ê¬Ò¨ÖúƺRòÜÌhbŽ6Ô:*üÁ¨À&öÖøÅ^w{ètYÚ6Ë9Ao|ßyz ºkZóÆÚt+2D¨œ8VBDd¡A¸q,/sƒ®8*ÆvPÆ9Ó)íiG½N‹§d^hC1u;ÑnË_wQð¾ñzTíuðÊ‹ywVðU-¦³9w;ÌíÕdëF1óÅ·ñãÝ%ðٵºÀ§Ýšª¤vò¥A݉P*¶cv³{¬0…ݺW.šÈr[¾5îK±\7OöyÃÞhæû`Æ…ôñΈ³²É]˜o§´¼*›­Çéb¯Ü¤MZ¹Ìœ•j´Lx]½Þ&…w¶ñ$ÎU•*6ÒP£¸vFN…´Ü묳ÒéŽâÈÖ;·ʈɖ_s„e#EìHÉËÛ(³´.¼Å^^䬪è$æ½§ÛFë1êA¹‘o¬uk+íÜ4Ä›Yd,y‡7´ —!Ë£‰œ!*ȹÇL#]-I±ßÌÜiåç>èæ˜¦¥bD6îñ_VœçØâg‹F½:¥6œ÷¦¹Da4Ò»JuöÎ3˜7[˜–Ò`®××]J±ÀqÐ+©Z WB “:é—®€ì:ÜSöpÓuë}¥]ÍÐß©EíPÕÚáX³Š»˜b«Êé!ÝÐÄí¯•³×0>r®&«ž.'ª–¢žmQHîLÎBhfÅMé½Å\Vö;JtæOÊwez—WzóCvM¥>}®|Þ]óIvnÜ:¹F' •aÊSvÚ†*Ï–-f©‘hÝ®¬ªãÉv 7†µÞbú÷ià ¦Gò$82l÷R¦Žzp›~›‰lUë½<äæ[†¶ÒÅ!\NUŒmRá/e(KÄNF芎AMf¾&åÓ®×¼“ö!; ‚¼Baj÷¸!7gÄukÆãÇ(Öå^ßvÐ ,pµh]Ïnð¾ ½ ƒÞŸ›ýúm¦ìrçÌõyÎ[·‡‹®&ÒÈr®ž=¾·ÜÔ¾êš,w‚çÛ*øùö7A }Òiô=&YÚy„Ń{»yðR|–ŽBêHêéªðzýY¢<{ñŸgZ%Í;‚¯wݾÎÖ«7vdÓ–ÒÝ>‡Ÿ,/{·Âb¼—¡u&¤´ñWWÕµ>áFžÒzy»áŠÒƒ¾h:‚)™S5$]]ÓBŸ[Xª*¼©&×Kš7{×Ã3*òN®¤¹|ݦ¼x7«åÓ Ø.'Bv1ÉkAßvÔ½Q- ïDõk.³×‚Ë\ɩ޺4ÎùKº›rÎTöów2N©[ó  "˜¾ŠQj±îu)nÜɃˆÈ+Ûž²œÈ¼ ž`IeÉ~ºõ’è™7åSUœ^¹KNIxuÔófJ¹áÕM€¦‹öžé›÷gnc±;”¸ìÖí’éu ªçG,:½ Œà¼—PupÚoÚfó‡4^6¿Úß©*ÓísÙ©ÞæX9|%GMÔÍJò¼9¼ ïQ¡³Ýè‘:«ºÞdá[ÖÝ:tÞ#»LkݺìËæL8ù=¥HͪC‚)Š;¢·ˆµçîï\ãž”¡õqY¢ÚˆÝhÓ\º¶çHÜ»F垥¸O,fÑĨÔí6Ù¬€>t·ˆ˜^Öý~Z<Ë8§täÝáunbÛËàù*Šw/»9ÃE§{u€Èr’ÝT&GñgAø‰žÚk°®ðe{Ë yÎÒç4Öt â„ìöã•é­] ^÷T¼%óÁ;-fߩⳮ”glÞÞŸWšê¬åtçŽMÖ(…ú×-»’\Q‰Û¦ ƒì\*Ûá2ýEU“ݬv•´Ã«­4ýJ?KLn¯Nžd„Þá÷±“Ó1Õ…JŽï«ÉHÜÀ}+Q–wª ®ýx¸ ÂPòB[dø;¸Ê^Fxâ[;@Žï8q½ÕC%á,TîxV=œ.‰ hÔÝÏ]6]òÆj›û§éäÔ*‡Á÷‰ÜÒùh^£~ö×&>ܧtïÖ¬û Ñî´HÞ…w­`äsË ÷t€¶p;\¦RO»Õ  R;«~Í8ãßO‡ Ô@¶Õ.æ½½]«uÛDe¬îÈ{hÝ«v´MkÐuûÛV*ëõ ]mÚô²H‘ô9Ѿ}¦•‡ËŸL]´Û–ö£—’ÝÌÍ {'¢j_yë~I]*™.}ãÍ«ÅY‰ 8d‚4ö¯Ó}å^s²øPí³¢ƒR¥„/*w]¥Î‰‰ e= L—oSc“Ínè¤%bV÷©bû¼“µá^~BÙéKªô?`wBj·šœZGÑê}^Àô¾X_\í5ÌØñϳiFY£8­{{Ð ‰ W1›Öº*c8;Ô_]Ô/€ŽöìÄ+ó|×B±b 7ç^OvŽchÅ6ÑuÛŠ¹ÔMÙ))3”´@¬òxG;C†˜ˆäY/ºÉÝèž»Æó.†ˆùpirêe›Ì8vg.øqº#ÞɯÓ=¸ÔYÚ¤]Ó¬Hk!õIâ­R+Ó„YAÕÚiP6«’‹0Ûw~{“]ßR¹Ih—ì™ï\w@ êoÙíCÃgR¥i)|ÝåÃÛÀr½AÚ•b†Á¥˜”Ýù rÉËÞ§ÛŽó–:®®‚½¯9­Ç)Уm.y÷H2…©5’oÆ%tÛ[6§¯•r™šµ‰ÝYMÁ¼{¥Ÿ”ã­¼¨e-È6˜ä3«Z-ÝBÚßo• U‡ÏÖ¨áz5YÐàƒ KfN$^öP·¼ÈÏÚÔS¥F±<ÂöÒñ‰fåªöŒWêïxöÕš8šMïJÜãv oVð9`,>ÁbÏÞƒØ{‰s…Ý?M™t¯´âR®æÒ[~¾OÝÐ{7Dõ<ö*Ï“ÐÅ»AŒä%—:Z»Î.æñ×Rìé4Ê_s®Å¤\”Ðïmë8³ye‹Ú{&ö Í Yõè84õ ÍL»“«ºÂ¢^©…™ì Y‹o yJ õq­ ÍítKme0%ß‚fev=¸×Œ†¸±"yA¹VÚôêpÇ·“µ(j„M BÕîÝ›½¨¾’ÇT½`é΋×rŸNÙM˜]ôr^m[PûÝ~³†Òù@fÌ»>í á¼}'tÉI®€5½]».ù7¯å{ˆ\ •Ökn†R¥î£WÔµÇÒT²yòÏ#‡Y‡B¼.3F—»-ZÒ8Ôé镆R³™/ÒÑ¡ñÒ³Óo%Ø7Ïru•ß8@ôÆz¾ ˆfsÍÚ‚ùïAö:TÌfNƒU¥Ð…r˾ìÕä .Ó2ΉF%ÙnT¹¢Z±u-÷{®hòžB²íYGomb> êÚ: ã}±În¬^\-æMçl7Cq8“Þ¸óénòQâÏ!ƒ]Ò®¾§wJé& ·°¾e‹ä:–ñŽÛC@Ì£ˆl¸ ÙjÊ|Wc;gåÑ’n¸æ­Ü–Ù%n{ x7¥Ì¹-ïtS}Mô¬gpB)¤jëVü¨RÝýQjJè˜Ôw'¢Û}홳ðö=·È®ÑÌÖ’'¬×C2èH2Xìyuš„Š—&µ ‡Uð˜`W<—wA¦Ì!’1Õã€ÕÖŽ”˜FÍiÆH"È}_¹o8nƒ×³ìè%¢„y.CØLËë<&xôÀþ ¶ëN²Q­t¸"ÆÐ¼§{Ì\¹ƒ}6pÕãî„ß*dL ³´©ïL®¹k8nmƒ¶!Æëf¡GqQ^󎳖ñJ ìy.š: §~ê~½+ëR¼f•k¤îíQn•¾•k/¼»mÖjQm¼FÌsvµÉYÐeq‡&:êRRmÖJ|ô0r LmÉÉd §•†V÷,Ó²vÀ›[eÕfíèOU¾vJ ¨teö)ä›"œçÓF ñ¼ê·{øÝ×N gŸ§¦&ë²|1õ­»Èºõ,i¼Wá9Õælâ7;¤\…í#·j€¿Æ1=¥êëžÏJ°Ò#ËËMqtõSA"]Ù^ ¸Á#›»-£wÅ ÍD½®§ÝÑ…ÉúR9ÜžÊ^y轆L»¥=ë‘çÊü®Î“ÃF(}\ŒÚž°]vq›HùLŠú/}uz§j KI±VH8t!‚ÜuÛH«Ü;\j™Ö>³/ úöŸúÎ÷p®<ÀYiÁòì®Û•opWL×Dm&+RU¬áTCX©š·$ñƳ/¨é{(Ûv*X[ ¤:•g0Å® g\o¯·ß¦=Cy^{ÓÜŒŒÀáZ, å2Š.¤;“ ºdßt¬ŠÒnÓ{@3‘VäjñûŸ­°µòÌç¹ÔÊ€ŠõÐ!½c¯º-’¥vo$wR++˜£3_%I,ë®(û½¬'뛑:²®ú³ÙÅ)q}iQéáÙEln‰]aߨ±ŒàÙ{Y™Nˆ7ÞíÙW«_|¬uúë‡k)v@”k¥ZÎ}/ÝÀê·]u`˜=ÎÔçqY\¢}Ýï=ÖUeŒ£Ÿ;Θóp¿9A{iËQ*½|JAVèðÌÍUÒ[Ù|ï1À©[‡m¹@öQÔó¯q/•¹½ÕÆuxzOu<è ®^¬Ù%¤Ðæ1ìÚBê[.GεÃ\m«@ ×£{ ¾p¹Zºêò­:›ÛÚà qN¥’ZëÎPVɈLÇ-é›LÛ©º2÷[B%3eƒYLºî ¨w+.°»qè2¡CŸ#¥­©XÉ7œ©Qf–QyÆR¯/A²åõm¬Áã@U~ÁI½öݱ“39m¼˜ (þHW_kÑ[2z¤¤FuGWÃ2ÊkƘɤ¯Ûw-#=˜©¼s׬`uhSË4Õ¾pÆî¡À¤!ÏPejØÉºÖ¥=.µ ^b—3µP­8ð1[E9¸¸‡]2ªA ök{OwRfÕ=‡t¢±tR‹±ÞëÛŠü„ï½~»6“¶1!Ân <ÞqU@t&ýsJÕó5ŒL44_ Kéá”NcÇ,ɬÐìc*qÛ1kƒ¦‚”}§àÇ,‘6ž]‡.f‹×]«®Õtèo±“B–¤ôB/ž& N¹YrÆO_]ÁÙÙi¨ŸW }/àgS·™{Ù,8Öõ•”ôÍ—Q.îÑÀÍßrCì§(U£éï$Á@:Wq®Íè78ÙSm”®S¬é&¦1ݵ(âù¾ßH.šYÁ¶…Ýïj½§Õ½iB¶mÕ¾†OtïI=¾VÚ¼.û(-Oi^à*Bx®—A.~?xžÏ!ÏítBñŒ¢ò¶ˆ›:wNqÝÃȸø‰·¶¦t¥×²qu"¨¼Ö5„$û:ÁzQçWዯWz´{ktQT,ÖópÝnTdus:uÛ§é«Î3iõuŠÍ9J•§µxéXȨS>­Þˆèáë_O:îÊ(ô³w2‰ZÜû¶{†s^wnIœÔnöì(¥ÊUÞ"–íä/ØoÕ(^Ú [Á÷ #½ê5»¦ß<"hÃy|[«™‰ì@©ì¬.Å*ÚÄ#ö’æn]:Ȩár³Ddæpé¬Nì^!ZÖföQKà‰7Ô+ÔE+u„S`àëé­ÅÏ]chÚ®¬Ðä–!ÓAÑÚ¬Émd±t:ž+£G*9Ðq¬MíwÔG&¢z7u–±ªìêk+ì>Û)Îâ)‘[íöûÃòËžºð(”Œw©Åf[¸äÙÙ.jÓM ˜~ZÃãlÖÓ÷¶lì<[žx δ&Mó+|5ݱ…½®UÚ­ûÉb=OÇÜVž‡n³ÞÝ«/¤:Ýw&ºÙ(åùôòû¨^Þ™…v5¡ôåfÔ1B×V+dÅsžKöæS¦Aë» óESòœ¿|)röœë²7Õí<]DP§úßí¤§ï%ËÕ5âý¿â~'WKÈeõèQWì:¦¹Þa ]Pz€ÃÚÞSÛíÛ ‚" ¡ÌÐy}ãlvE —ÖU‘µ|#ÉÎny%^Õj£GU^ÊÚÝ0k.´·G]E<æd¢®ïëë3­‹ÛL}¯µY´×  ÷¥‰Gƒ *ÚËÜ•©W[VVñ´xÒ¾ÞM^¶5…Xz£@Ö:;ån¥ÌW}Ðᨢô á7­¶§[ÊïSoz1Ö°Þœ 1'“@®ä‚+Ë]#½Ö»Þ®µlY¨ô Ù2Ì9'~кóuVg<äú ”ÈúuëÉ(?eb@ö–÷¶°ç”ÞË™a««NLŠÐ+}`¹Ç0JE(”®÷EfÝÞ‡W…û†Ùár\6¼q “n߯¢ ü>5ù;çónoˆ‹¯¯f^³XûÇëó`Ù½yxpsº¯³¸AÝ¡EçÇzÙãÜö¯uîG_­¼ìAÈw»ÀŠÅK¡Èªí…>¬#Fæ¾[rk߳ݙ=LCãåöÛ½4¬ -Öc³â/ÈõÛû[Bi«iž©í SWîÞ$ZM<=\ŠïT»ÐáG±uÐ6°ÙèþÅ¥œ Q§º×f—!‡ƒ¹„Gwmfbw'VÞ‘îwÑoܽë®xTà”ON9´ÔsÞ5‚¾Ñ— ¬ û{˜…›g1gµ¸¦Úb1”#p²'QìÚo«„úÀtÖîÜ÷«pg[¯Á±Ìš˜pE—7pmÇx'©Þl‘7œ˜¥BÆöסauvPšÀÏ\W=lÀ-úTó[ØP›‰X¹ÄzñŠöM£½yb(›Øq9›U¹žØ‹ÖXéræ_¡Í:ϼs=^nID‘v;™k•;½K‹æçL³‹DÞ:‡MI¢ãеL­½4…Õ¾~{+AðV²­Þ7™a,=<¾I—Õ¯IÛamò»LVvÓ¾v¢™®,J¼²BY 5Ö¼ÌäVpìh;¯J†=^ÉÑ„]×5/y(77Kììpnré/DË{&ïUÍ…‡á¾©Qrà5dÁ‰«'9^]bóAYÃH§ceZÞ» º²².\÷tVòeìï¢ù+#t%ªë2›t++\a­ÊêéÙ[œ…c 2^[.ßw_qíÄÐgrº¶ŸX¡mŒåœsè¥qá­9Qµzws°NÚç]Çi¥»ã]µÕ2¸ünY·œØ—jw^K9‰já…λºSyÑȹªçss^_Ry&òyÖqWaXt“ìU¦S/qÔ±„Âö±ªâ†dùZáRÞö³Î…"eåNw*Ÿ-Çí¬ÌS©¶+Þ¼œÍ¤1GÜí¹ç„šìŠ‘³öÖŒ q{ëëµÓ¾òÃ%xé^€udæƒ>ÁwÎ8mÓ òLؾ™Bûj+Mˆ,‘ZPç+ËJ9»¡-ê[¥p7OîòkÕ—H‡2VõNû—ƒëÏ ÞWÜ'¸yTÇßC±*3± Ý<•¼¢æ WLŨÙXðÉžtòé]på¢S¸mJ]›×ªõú/kkÙª=מIeêZÓÚ å½,Ç9­Pä’án±ëÆ9šå5å°kz¸ w¶Dº·ƒ³K# C6X3–bf‹ì«®†³+½}nkEVe€±Ö1I² [E«†¨(ß bÞut§Yâ¤\b¹…êQèuÔžëâ»Û‹÷a(^S.?q+7&_l”掦Öcû¯ÖóF;ÂFù÷—F¯0õúÎb’–¶êé³” ûÚ-$оÀÛÁ\È·aVÍóÅë/¯™ùuÜÂ+wÇçÒ|%Šû0Ìm5òéÖ=›Èiäùt6Ï1ÀqÈøôg{˜‡eÐà³yl ®£b'T¶ó묱M0vËZ»£œœ‡n‰gºÙ¬Ü7ÒSÞ+ki"m·Fu]fà Vs¬:ù]¸*S;ÊÙ<#£ªë<¯7ÝZÌàÀë3—¯iTrØõ石•NÛwn$3ÒôeE‰¥‰<† ËWoÕêìB¬Z®É¸ÄS2Ž´µ Úµ»oÒ ÏvvÛß,×ÓÉRä6ýݸ•ÔÆùb®c«:8ûs-M7z<-1 ðÛayI¹íAû<¬å ÞTGZÞçTmMZ!w3$©jµÃQo^Œuˆç&„•ÓAíÕÆBôMiæ4T|6_5y2+x07aÁÝÕØ1ö{+¶ZwyñßX¤Hæf`yàîq¢çM¬ÎU'VÚvûQؤyÈÐ+Ÿd­íÝ©H }í±;·G]43Ä9Q»‚!xJjQ8œSÊ諾y•؈àÍMrÐjÞmXcr¶H¯¾Çp@vl¡}p*—€Ñ,‹Ag²n"¾fP ƒ^ë«8C€;£ë3ÙõJ:íguÙºÄ_lW‰ì&»ãLìbÚ«7#|­dSáïx_†N .ºë¸eÝ,Ù)¶Y̲³úY‡óStfõn…eß«wPžN€áµ#äó(¶è¹2ëZÓ«Æ»Ò=&)Ö0A™x W*÷ʻư:õ¹xý8ª w±¢´NŸ`ë©kFtÜÃ?èD·;çá‰öF÷²¨wtɧBÏBte]½}kt¾ QFpBþ ݇Ú/‰âßøu¹¬^ÇtƒäŽwÑUäà ‘©’,ÙLä¾C&áM4û‹KXË=Ù>{î§ @íZT•w~zk|ØKXmÝy @—{.ÚµÃhÃEt\l¿lŽSMÅ3m­L‡YKBL‰|ç;mÑ™¢´•Ѻ‰ZœºnÊZJ¯Ý'¦û@ ©Z; ÐˆÅ#èk³>Í{©*È{áyÇNÔ´ó(lF×D.a´2×g$zKÏaÕïqÑD"¬n'Œ)ÍÓjËôö{©7u„VISkµZèË{·-eÉ£ ο—dkÍÔzûaäú9j³N‡:zJ]›'‡d¬ËwÃ77^›|ie«ŠnÕÆ”Xl¶‹j&ótW¼÷K¹+¶°¬ï9OzE@MÔf~ñ=Í÷éC¥v¿Ýù†w}³±XK¨2KÒ¹AA¢DP™dУn!H¬!D‘t&й9qgvÚ$É®Rr|Öª;4BQ¬WsaÅqA¤g|4 ¬ÕM‹ÝvãˆtZeÝiãJ„‡xnýÊp¥Vr¦td(íqKÒüÍSÐáþ·ƒ Å{é»Bù_SÞCišZE?E!£æ J¦a¡kÚÿ‘á÷Þ+2ú$Oãäyo`Ó;/+r›åhœð«*À=î?„rÐÞXb¢¬)ž³´8×fvO? ˆzëÓÞíO·“’œ»Y9ÊðíU’ob‰#w«B·pñçïLu2º÷ìš”>šr݉o)<å5·| àPœÕ-¼MK!l§½ãY7d<<7) [ä1)u"Îk9ì™NzCFVÒ±ô}Y騗H6§mA¸{s†{ÖmOlØkɺ‹fY•wsK~»Ø{/7HIPü2£&­?•ÄÓ'¼ë°K£Þ~È;Wï|¨ï…OTrÌ®Ú×¶Ÿm×)yNÅÔN«'èFþ5Õ¹AÆfl¼¨Å­9Ý)£ÝQkVš“^i¼Ü+nò¢+i‚ ²ç_#k¹?{¬‹~öT,ÁCÓ—SíÞ{®0]à·Õûd¦±C2‰ ²vÇ,Ìg±ãG‰ åÎÝäò¥qÕ»ÌFW¼ Bz:½Íj'‡n®öøN½ó¢üŒô9j½u¦+^Åë|±«~>™å@¹=À¬Ø/`”n˜Ì[Z^òg+ÙPsÚ=Û®}yÕ{Z4Ôp(²À½ÙFïM/VruÄ‘]ÏÊ5Ìg[ÍÞ6¥ð]N¶­Yqú« éë½WV±÷aÅ“PÛ¬­êÌ>ïxb³‡¯%Ï9Ûk‰­v°.qr ½y¾téç=õÝÓ.ôIb]#Dx!Þ7£·9LŒæô*Kš¼Ó`sΫ¸Ò#.Hv½tã”{¬ÊaP/Âî>ÚÙ^Ý•ç“s{€¶cYË9ŒÝ<9ìîîV>cVGÞ­éìå§e×$¯jæT©uÑšº£B^ŽÿÇË—†Î¥Xà/Îe †‘Eå.•±ÔwHvÁImÀRíœå·ºE;®ÛݽѼ€U‹V:-”ÝI8hu·u–°0 ÎÝ_·ª6©Ïošwd•w7eJìío=ŠqlÄýãÖj\zú‡TàÅhsð_yzL×V¯·Å\5ÔëFÚ3»£ô‰\“W‚òe¡¡Õ»ÚyìFæ´õå%D¯#HYJѳÖkqA×ZŸ÷ØÏh¨î“.ëzŒÛŃ2H àpÔ3¤žwÊÉâäC:ñ}ÖÍÊQ¸…Ò#8ùz´.¶U©ãb¸³hJ{m½VäÝGŰP]¼Ò‹2ÒH,¼:“–gUû;¼pÉéX .…ÞîoXÞ¦88Ìw/Ë´MÙÁ6úrtã/]Vs³G¨«$ö ñ6\Ç ´ëi|:vÇÝÌ%DfÞä‘|;†î”;ŠÓÏ5PÉ\ªÉŠ?Zð­|íq{U-÷mšöD`½Ë÷dKÅÄÿD·†Zƒoày-Ùà ÛNÓ»œpRBø}næT‡u$ÄÇY@^-¨†WVv—VÔ݉ݙetÖ9ø/Lyq"=Ó´1&[ˆËÏ0Ȭ²Ù±J¶s(.ÃefÒÒ+&Ž‚h9//D]•ÄF»3¶Lza¿»1±£l[¡h${tŠ‹¶Cw†Okˆvml}gÌy\Öè3Š‹ê”·oD=%ðê¹æ)6Ê‚¹!Aœ´Pœî×FºÙE½™XyáÉÝÕ1Q44p ­ÎÓ”“Á_g´õö0s=q–C¬•r*•¬ðpå ÎaRw&;†¡‚¨<Ê³Ó Üá3»->ÌÝ93’º æuù2£œ;݇‹Ê˜º–Ù«écVaŠg”dm¨»,FÅ´ãpºWûZ"ïbÜÊ~ßÞ]C·Òwµ.}ÞÞÎI+>Â:^½çW+š—œ³DÝtx¥^ÛolÇÀ1Õ*"𠤚~ì N÷Ë`R,èê…íò¨¦w¥{ݵ‰¼$3ÎíSïs¨p¤(ŸW&QøªÜòOp笸†+ô¯#3Ts‡^¾wn×ͳ¯+Rz•[ä¹*aÑ@S8´ž9Û[ºšÅ«ŠN]¦Î­ì çt®g£9#ĘO½Þ†ñP¾‹Ö,Øé¼ÕÝí/ ±ÞŒÆ8‹â³‹F¯%è 0mžÚyoÏUQ ¹pÏ[¦2Ãäè‘! ÁJ*Þ"ƒˆá°s«¾Øòþê¥ØËWVÞAf—‰•‹&)زJYxvøP§›“\_vÓç9vFŽÚÁ©ÔÀ‘)Þsk­±·šW_¾‹e·s¢ØŠÜ†·ŽcÕ‘Nç6ÒOfæc×>Ô‰qÊ.]ˆ^Ý®EÆ_Vir\q¬ËÆóe†ß8¬S79íŠçbÝ«Äõ˜Nö§‘_S2ºÂÎuEÛW–ZéFB<4>Ç&IJ8+×\ö³tsÉÕ4Jò Ùî­ë»…ïb4û(€tE1óäçOo3=í£ẖ— /j±³ŠßVØêJêèµÕšIöž°Ù×ïI;í7+ŒÑÈw™ 7cõÇjmúøòÉ!É ÃãXû}z½œ”¨¯+F$Aö!‡&¶s,‚@yh*V{¡¼©%ö.¤àu˜Îฟ%OŸ[·¤£¬3…_>,fsÝÆð-ÕDnج·Vf^¨j¥›YS4…5Pb²5õ½‹ªqÉLÐZfòS©ÓYÂ÷,µÉ¿ï“­»î[EõÔ“ùN*<;ûBLÀÜЭF>Dª—PJð‰–»b¥·ú%+ÏŽy™zd»j­™ ŠÃX ÷Ï=¥ƒ25£‹>[oo¸hب+Ò«Õ(‹³Ìž Þù_#@+λ ¨«G„V‘¿yé¤9¯^Ö¼K}¦4òª>·Îg®îrê:;ª‡u°šöð« !O¹ jÒÉ5{D1`Š>K£F-m«‹—¹CÓÝ¥*8 ‚ÆÄUZ¼]Wu¦yéÜûz»íˆëÑö ²Äî2a÷jâ}ést© ‰ï·.þ&¼Þ^(åK{Šú>6 ëÙo‹%yڸ㜱Ç:vE'nfŽy${lj¥[B÷JzÊL¶¥Ü¼¡¤*-¶³›Â„±\NŒeV›nò›ʾpJºÍH+Y¯¸9ÛQä{wˆN΃uÝ0ÚÉÚ§¥½¡“ÍЍø·s·+@3‹™§jã(=íÆÍ€Ù’¶áK#¬qEk´®Ëæ·Š|àà7—wnŒ6Fï Ž£> Ï+Âú)—íä¤mRèñö.)ÃÆg\èÛ³xÑ1õ±˜oUdµ¢§ oO-J¸K ¸fä@£+Z×/BÒaÑ5Æ(µ÷.Û¸T×› ÜÊt•zß«ÒvÅÞUúñnSì½Û>¥uv:xÙuj[U0ººM¥JºÜÓW´²ÃX”ÆÇh—|]„öÅ*äNµ% …ØÐê†`àýí¬µò Ç=Ñ >©H½&*ÕÍ„ä~û=tšÅE É 9ÐÎìî=†¡®ñæó­ÏbÖÒöýÞÊ|RyK°äãfÙ]šbÒЈàz0¾£u w]"ì_x™Ü=^4*zfg#C:wã½¼¬S#Š©ØÏwh®¢ÆÝ[ÛBÖd¦ÈA®§ß`§1VÕÁ΂$ñ æpŸ´kö±/^Ó+¯Íö•Ee…jáÏËâ)dâ-±RUêZ‘šìê`ŠsÐsö椑â´r³½v{޾lgVåÊîWµÛ!nº0ž®Iæ„ÂÓÄÌ÷–›ì"gRž µ†&Õ´+¦•*R.öûklÖˆd:2ýž”cìlÒy–æöî»Ð­úuÀÚõÏ"¥ä޳ù/q¯ra~`]ƒ²År}÷*6*pnöùvòÁµÉÎr.¬e§–tJ·›«ѹ컩õä¾ñîÛÃ$~ŒÌ#¥ ,k¦^fçia_V]kJOT¥X4c½¹<Õ9iáWe2|6vMð*ûzû2Ï„‘)±†õF6ö¯=Ò³¡í{·Á?8¼^Ó]€+Xì”±½÷WYÁÔ œX;·ÕÝrõº’†ë¬'4ܽ†”ü’o§½sÝU¨­|ö×ìn\…øk¼ ZUš»|¡öVŸf_‡¸FN¤¯.﮼° }W):X ¡ƒUÕÕ]¯y-¿–¢·ŽP<4ËÙ^ÌçÅ=|4s€Û‹â¾~¬A Ä˰"vœa'B]¨½©@±¶ýµ2ïíï´o=h¨·Ò ÐøÅLÐטœ>Þ5í'™ÝË£¸™GdÍ<|ò‰ìP^ßkÚê#VN¸ØðZ‡xmwro±Y¨Qb¸Do_g.(íß1æq÷{„)J„T¡sÂI‹ìõÛ;Bˆ"èð)†µ ]uL­õ(>4ýä:Ú¯Jw ƺ{SvUF`ܤ£Àdy™inV³‹¨¼…fÚJXìïŠ5Ü Ý¡ ~.îu}¸¥q¬Ô¡érÚôÍ’=¡¸Ã¹—½j´%o ˜ö’‘ÉAœ~¡O»+E]Šg=îy±ªÏ^«Az£¿‚±ÚSïÓ{ÕvÎ SïÙ 7ùÞp<³Qµ•/… fe³[:.ë¹ÜÊh»Œ­¨xS-·u0ò£mº/jö(þ Ìr´ùýƒmì\ ®”nŽÅ®ˆÔÁÔò¶Åæê)RÞýžðŽä }´žêº=€Œï ñña¬¯ WÞÛî¨ìËÞ+«.VIدyjŒVËuîwï?[ì×j“¦¨SpZqÈÝûeÕ™Ô:Ú©ceT¦/D¬5«‚¬vC±òO(må¦OÇj}„UàÅ•o(tõmulµaG|g±øÌ·«!2װ訑 úó=ÖÇ@v¤;ÖŽñªFw9n puK€f¨z—Kê”zã«ÒÅrŠîê³Í+K;L­ÑHéå–µÑY{¶*ñë\YHlem<ë”Õ˜³/¡Ñ·Ù»…­¬ÚèñÒ5;â*±"¡6ÙótÎÄù°(âUYl*sµÝ%˜1ã¶îFŠC/qœzS(Vn%•tÚä»Ä-Ðîeß@žÖºŒjÌŸp®L¼·Q×-¢º2pÞ$£ÁÊï»Ã®í»ò¨¯ÙµtÞk‹EÊó]{QùC’ôy•$Þ>9Xöâ¢g /lºÊIkcÆöô¨ö@(Ÿe3•åAóW(«í³ƒäIÔ[XìæwÛóæñïÀ>Zk²JÊÇ6̓Ê+\]XIŒ×{Y0=æ€TëÓÂg)µéç×£ÚhäÊÏ82’´5Ü0O„¾»ÞºØ uvKöµ|V²Ýãîúˆ7feµ·O+ÐMìÁÆrIYาžfªx-Qt}†ˆ‡u½ÔãC&ß^a PK’±ˆjײTÜrµÞÌ$¹—rø[)‘µ»ËyüZk|ØïT„5°‡½ˆX:ËFw¹vó5̉StMæ©>Öôg³¨"OWÔ»º¸ºY½”!imsÃÐ ÷›LÝnóßS §Ê¯½Q(òJÅg“žÜÙ/³p.<„PŠMaIW34\›´§Òâ¢*:9X©]±¶±BSNž1SpEöÞ‘VuóÁ랤žÈEB­F‚õŽw3réMÞã†ýÄÔrúùä÷ /Š j{xgÃFVÒºj ×t¶ãêf¸R;/ãb¦åß>®[ `›mžQôO+™LáiÙ½Ê@*ÛçÕÄïµÉ‡¶7ÓgJ뫽õ¹É ò;è¬bf†× a2îížÄ¥ÊÎ'NEYxÞ‹é£ÜlݹCjc<ò­¨ u›ÁKÀ*Ú{‚£_°í«ZŸ—¸¥³Æok[ʸµâ:ÉpD¹éÜ¢=w–âîºé9Z#Uðá;³¢v8¢óuªì}« ¯"¼=d•¢¼dU·Ë@›Þî|粎kiWS[»”-zû!=y*äÞÕè~Vù¸wµ¸¸ÊåÛ`Uèã<ª#@N1NÎ^*³—vÖ£ÜBñx³ž à]ãä…€é3:¦ß,粞1R³…a¬kg|ÕÉufÕÅ:èõÞªV>è-©¡÷7²UÒãÁÜî à¦y ã‹»o*æ}q ¨{¡1¦§>VnÕæ};NmŒ¼Û8DjIöÞÅJºOÝ«~弇–Å~uµà9U±¥«å¸eö熲Xp•G .R×b^ëÍʃÜß·äGÏ>D¼9klã§Þœíú›œ7]³ˆÑV R]»ÌõmlE9´½:¥øz{}íš#LŠi{/)³Ù@çr‡kwsæß¼R>ðÛX9"ËR´%O½ÉVfuÜ øL:\S‰B‰Û0p<Å×U±°Úé;7¡›ioV‹Õ"TÖAÆÇ\dÊ{=¯ÜÆzet,ê­¯wžÅâ¨íðY}O™5€·ØÎ”Œê$V»›LÔé\â[ÛË^°µà¸mè㻜û{=ÏÚÇÜ®¢Ï7ÑlÐJÔã›ohÖ¶Âl¶·4ÞEÒû¹ßK=F4 °òÄ](›ï ÇÙcFS ïfAäû¡€Q‚V^›6…„Ô_ŒÄFJ–‹JXC…–„ì°„ë&š—K›9¿ºâ{Aìo=âÖ •ˆeSêÉzœvñ*ͱ ת¶ õæŽü ænM.áÑhä¥R™®ß -‡vsŽ‚TÔÆ-ÚÛâ{àƒ,¨â"‹âƺmüñµ/+*êJån§Ù¬â-Åó¿™W–Ù­ãcžbç¢:œ«!!Dß ÷]Qín,^KB¶Þmœ¥)Us&ú:åj—.µY‹¿#':úvÝì{qÔuc’‰à²òر†,|+" ºeÈ,yÔ«ysµµ™µï/K”žBذ†˜ÏJõvÕ«Þ]p»Âbà©ä|8d쩹˜>Â\‚†…,=1NŽQOºzbœ÷v^`vû(=ìy,«žËÌ—¹v}§AHÖà…Z-sŠ= ¡Bâ½%9t[c8‚ÆÄ+3&jã[S¥Úz­Û¶ºGIçw‡s9\••2Ÿga m>‘²Ï+UÁ5½o¯ŽØÚÍfg±äÉW¢\}“Ô µûryÐó‹pÕª˜æŠ6:õ¦•–µéºÖÖäÐÀ˵‘œí…Ôüjû+7Ý߹ݿb3—%ò÷wbºS¨dMÎÍ’lì^Æü>^o‡Cãž„nP=) íu«Ñ¹=#Z»ß8À±ÄRçU£©q¥Ÿuíð¶3–Ú{Fnœe\Þ‰2Æœ˜êù ›º'˜—7¦À˜ûɇ¥z]y¡ƒì"cV—Ôøul^¾îE·¸‡Ü³´ÜP:Ë䳕y^?]3Õä³^»¢@|5>{°Ész‹¾Ýz5C®;vi€6Ðî¤6‘‘l e')ßE•w-¹É¡Ï§i‰*Kk »)©–垀Tó)gݨœgƒâíiä¤u\;¡šÙ~}ìQ ß?fEt\ò˜˜ÜjÂíÎ=Ë_ ™†Ÿ åP*wó Ý^áÛôº™:L– 3%PÌŠõòè*#Rµ¬[X/§3Qî¿^©׈â}2w«HüÕ~ÙV¨%n¡"Waß•hc¯,шtÔ@è,nKQ>œ›à Ë YVÕ‡!ß ¢³F ‡PR |' Ìã¦HkëEÑÌ%ÕïV>Z÷y&ælã>a+ËIG;9Ù0'ô‘YV[üäc®Ê™ÔÐa¢ÙF]fkŽØ¯p¬•Ükíìºñ¢O’ž Y^šq³Èî:—2àNçuŠUw25ŠòìƒælKºq÷<ìsB~œ‰ë¾ °ê¨ÏCY»¼=V,ÝK׳¾ÕVkzšY¡W[kÏžk2 6²ï«V{ÙÚÌJPƒN¶AU`.°§i´|.ÖÓ÷’[µírž Ôݨ`=uë[æÔ¶‚ŒË¶¾íVð_;{ÙYkƒ¬Ëµz0F“Ü®©œÃ{y+dzšrÅš÷:oqX“Bµ|ô- çrY’ÒŽ ñtË"ÆŒ7J>K ™KAÕé¾è,åê­Ôõ %-¢eBº´ç>àíJŽŠu³q‚l:” ìïÖLg²Ï[ˆ*wó|EyÖzÊâ id圦7sbƒê $uMɲ¶Àá#=óßÄvæÒïy,¤hU–œZ¼ù(×´fŠK•ßå^oàzº]ø…qìØ¿i­ÑN‹k_Ž(üqò~™â,ÌçíÆM5J’V·/²é8v<«Ý©´§Ò™WT,„ŸF¦ëuÜÆw›/“ŠvÓ®Nßš]ÏwÓ/µe¡ŽÊÊ.öüç²ÇIÕâÖȹªº,Öxo(;"7ŽõeItÙŠ,£ÚVÌŠQŠ 4—Êõjï,|ùüêðVÈs§†^Lt8cû8P]N |z‹ë†Ö;¼AQvfÊ–‡Ñu,xz¡”°Žã¸\××Ò³(­Ñ×H•”êºÍs%ËÞJÃÝèoáTÎi3]=¹Þô‚>÷»pÄiUñ,&ƒÑŽöaØùWžß²’ƒðËå{æÍ³Å¥­¢LÒ[ðìxV`¥-¹g)Ô­1Ð온‘ÌG}Ê@j;ÌŠ¶¡ŠP@õ±u.Ýí9hIÇ´t˜-µ2,®]Ñé¹kw{ñ·ð"y·jL»®?;™ºpsFH}Ï®×1 êΨøóxíLT­6[åtD;²ÈÚžWO¨éY0õƒÚi7°‹Ðê ª‰ÐóÌœ„…lÖÍÐ|aÂ;­,­× ›rÀ7}½ vã# uqwr®Dd™6ÑW‡±Èö‚ÒtÒÂk–Xs1S›ªëîu7š…IRà”Ýf© s®"MÅÊ-T—ŠpæY÷jûG=¼×›V®ñ©³WJ—[ìY»Û|»—nǾNºz—{„ ­x¬%ûWºJ½=N° ÞÚ"w 5Ù£•ŒGçCκÔKÛ[Ö*å¾­¾9S/*êMé ™‡ÞõËñ4Ùd.õ'èqò(s“î˜Ï:¶H2º ´óØF!•çO·Ú}=(:[ãZº»¢©¹-4{Pʼ ä7öÏ+ÀÛí¹(ÎTL5ö®Éˆsy€ŠîºÕ®˜áw…{;88¶ú­´r¥î¨‹[Æß¸w{عêÎŒãxŸÓ'nàöU¤á®«-¢ft+2Ú•èUÞ¼÷±w·ÅÚÚE”°ÚÝSfÖ,w[9PlnYë*Ѐ4é… 5%±ËÃÙ´ŠI&ï¯tôœë2ÀóáH{/ tü³¡­.š´§·°c|2¸Ã˜]4¬ Ù¦àjÞW.Òöï‚K‹¾\/W.]†ƒ Ý’ Â×Û#pÈ–‹&¯lØì¸ êªiÖŽG}}“_´f]Œ×6·w6gÓ²/yY<ªË2–(Á–5#”Xr£ÌÜí)Ð\Õ›Z»mÊ{î¯nwº÷ÍÑ~svÝ0:¬Vž¼Z±UªX¥ƒd¡|°sž#, Œ ÛBà-µ}4eÖú*H»ÛM…ØE"3é7«•]äû™UnïÑÊnÅEDPy3@FY«ó ¯>çX³–}^-¡¢{Ô- ¼ZÚ#6ÔUÆg5àbȲM°U½Ëº§{£3oÕ7–ŽÖ#·ÖìGw,c¼†PݼfŒÜn(öä …Þâ¼ì÷£t´Kx ö»sÏ&—<žçZëJ§PŽü^ÝyÛ—cÙš—§KÑržÓì]±¡+c¬©)Q€½Ò5ÜSM)¼+ùÐj#ʺ:6*~î­}å¼@;E]»¡Ô:Ä«á {/¬ ” qÇË]ú9¾ágÕ¿ž4B¶[&d#V4g±îœX+±ÌÍ}S»syU꘶çY8¥ÉóÓ¹ÈðFªp¾“6±ºmæØÞlsISzø›®Öâ¡»h8F¾X¸šÄî]1‘V÷Da+s¶Åu[Á'oW^ê¼ÁÊP°;6ä±Ê^KÞ|y–¹iŒÔŒœiØhºÇlKþ³Ñ= ÞØ“+™™Ô„%§—ïëV…EÏœÊ>rôµ(n^n”…57J´Ž‡F¥\dÚokN˜âî³;dåpòßç)Ɉý…x¬y°©[ @+Ùl7[}bôí+šn˜o…Ðë4«Ùá~¶%Õh,Ý´îßœTZ’›Lo‹+‚ ou ÉfRIá”&ôúùËWÖØ7Ð$ÉÊäåÒ w¸dâ-m3ÏÁ7ܺ·+½).— ßu…÷,*žhßlêOE v¼Ýí¼‰€_®UóJýµ¸Êº‰±“¤jwª–U!:ªcŽ‚q+;;Ú¼í¸û€WX n–ï啿¯ÙtX+<(^u!yâTsÚõ§O¼Až©â–“':½×O„:ÎÒ“::È­õ™©–ñçOIÒ®VsKJcxZ «÷±Õ‹w‘q½ð)vâÏ„DKÂû¼«'{³¶83³‚¨ö·¥G™á«ïoʰædTÇ"wt¬ñ™âqsù’¶ó±ñm•’×)mÖæcÑJUˆ;1ðb×NᕾØ@ìoÇÜ$îó öLËÛ3ËaÐ/–,nÇÊó,Í–+³ˆK„ Ê”i­ÍçQJ)wmâ2_]vŒvfZ¬»ÉÕ•8öíLœó»ˆ‘xoà®¶oÕ«ƒn¸ÍË—î•“ßl‡™ÌÐï,˾â›Sb\ÜÙ.±31-®®è­ìŽaªmµZ³KÕ½Zvrùk°]Šži_žä])Ÿ^»5¥¯>Á1vur…ó§(@éõhvðM¾¤jÔ˜5ÔÓ·f˜2eìÛ¾Vê4н¥ÆúŒ±ö¬ˆëÁÇXu•Âî¹DšâOnñµxü7|q-ð»UξÓÙ]ÔÜÈÙÚÚ7Nm«¬|[]¼Âncdáݶ˜åÉÑ¡” ëÍ®ÛÒªŠù\âvlã½áî‹k}~¾Hí¼ „¾g5ÒƒÓZûhå»4¥(ò÷çÕ ”¸Ýå&[½ïe3²‹nëÈ)uì/Š8Ýðä¦[%Æ(^æ3 OÍñs±¼ÝÔ)tUS=l'\°Û~¬*‘ƒF: Õ5hÜÛ(Ìtëeµ¬R-Ò¶ Ñ ™`M󳆴©B‚¹+|oìì‘ ÆK” 6Ïèê®êf«åaªÛœBÊ’–½ë[tèÉÄí]»\ÂR•½Yào PØßzm]mû[ÚyY}†Øé³CM£Ç•kZ¼þu!äFn¡± GO»´=ž\Ćg*. L½º/~3)ªõ…VæçGK"Í©©Þ$ÒÃh(‚h*zk¢õj±ÊX+ôáwá2QÖó§XwrϧEW…ÛzbñýâÎÃûò½ìx°d¥`ÅŠ¬³Ã ÉÌôE…D§Ýnøäp»f+<¬´»-³ÈEè¡n¸Ý©ƒ—YqÅK—@7lá}Ю¾ø€{{Bº¥zÚXV.3× Ï2·Ÿ]Äó”Ù¦ëf%Ü΃{&ot­ëO³+ƒ‡C•5¤YxrðÚuËaNz.àMðÙÕŸYöo|wÀ½­ vºIJ¾W1öˆ.»²ÍdÔä7+uHRfœõÎŵîŠÑãë*ñÞuâ]¶æ¥ÑLyYÞÚïZêÁ™/=ÞÖ¥dÈ=!H/¯«¢S'VÙ®Í8éDs‡`ÄЭU6ë\ÚØnôõû[;䨸edBpÑÛ«:NUœ3YØb§FÎ_Žò“ÆàífóɼzXww}™7o“¹ÂUÕ p#Šé&uC*T´//¶²vN†Åaʘ¹û›Šï½PŸmëºÛ Ly¶Ç-VŽêÊY;e¯)À¼NÀhÐùÞfŸ¼7%è~nð:Þs­]Œ =;Žw‘¯ £v·k¨­wê:’K²ŒÅíã79¼™Ô í¼e6z­§æÅz*å1Ifánº\Y™žÍIuåešP"¶q™;…Ü<úEz§>– ÇÝ@wLÜX~*½yWža6¼…RýÙÊ–ëô­ŠäìÓÌÊÃå¸Òí]Mf^-øZ÷¾y¶®Až~µ^(ª3^ªŠRçÛu ¾X-*G aܤºÕt¸0IÛÇŽ+”¦^®Š(¤“)ðY+ࣻ£½É’±nùVÓõ¶¹vÁá—qvùËTAZ(¨# YìÁ…È(ß­Þ>—Þµ§Ô…M~jä€Ô·é¤59JyzñÞ ÷Æ…aqq¯iMõ.“#-ÖZÚÖá«=ªàG&ôŠonbtÍ—[Žï©°T¥¯ÎdQƒMª×Z@)‰ ö»hy§²W<¤ªìužñß Ìº^ï3\ð¬¾w(†/pLL ¡Ú×Ãð\ÖøÑÙV¼s®¿u»kq¯ÜÇC· Ç·™ÑñhbÜ=‰Ÿ7JV$9 hôẺøD<º˜ÌÜΰ t§†õÕêçZµSõn§&v5m¬7›+!“ÚÖï cÕ·BóßC]}‹w¶£ÑÁ +—Ûðšû ·9dO˜¨MM}x)áx·èçN¡j ó}íâ–ü&– rV]Jò ©t Î+I5ë¶±wÉuï=õ©ÎAµÐ)™‹Ÿ+ÚÅׯHÞÊ%׆rí«ÆHí £µåÜq;l¤цȥ•è˺Èó¨j­ ›äög ‚z>±Îïeݶ²þYycRó#wbÛ¦ïÏTfê\“^ ´ÇB˜šî§#‚êØîاd¼èÇUž[…›™ˆ„£WÛÊmr…­âô=¡©ày(‹è–K™W¥ó— ­'Ø\ѯ+ÙÛ];¡á~Tï}θhï_3îLå¡ >ÇÏv.®,°8ò¹Q°©Ø\ÛÌ¥sx ;N9>Üâö–1vô¸¢®kwDˆÚÚܱ¨ç&&mµPB¨¶y£,ÈÃì7'}›³¦à }>J¥ÞW[uÔ§ ÓÓ±T{ÂX|•^}ÇuÞ­à»5)‰>‰—˜%£ËLÛë”gváyʹÅDeGYí0{»½·…­t¥¹g 7°{®eåc•æ×‹Òm@¦5ÕX¯Wht*Fy_V©›Ýt1Q©Æ»n•õ;HÎäzj̾«ÑÕtrp˜µ‹{×FóWQ%Ô¥Ô:Ñ}f3WFñwž{ëíPn‘Z¼/g¬Ù¦Ÿ•ã)Ddó2¯ÅÅÚ¹¾¥l ᤼#ζÔLJï#ŠÝ21–ö 7×µ»ZŒ–ÏÆågIÝHQ !›Ï³gI½:_á½Üx°^a˜}<õâ»É…\™ŽŽggnÊNºƤ­átm°°LÎä­, àé/E+¼/‡R•¦®%zóHówRß›ðñÒ^Æ–%mæd²Ö9˜ìÔµ”²Íæ¦à±©ñ¼†–.ÜäWì÷r—9÷{Â÷bkž*É6Eçky§B FÚÜ»jRÝxpl%€¤¬sŒ;øZ˜ôv’Õsò^©ÔÓp¥Ö|/`öã­e <­–AY†¶:ÁS±´w©Y4¶[\wÚkÁ ìÎry’ÊYY¯ÄøÞSi£X;Y.ï48N*{—XÅêwîsç3Q("vkáÉL ŽÊ\¦åG«dc4²”kTV€Ñ™ƒx@È2VÑ® “ÕÓNÒ±\ù£k 'Ó§ µœ öYc=7DŠ[}R+Žg¼ÝpcʵF%œºS“•s&|i(ïgcã÷€Çî7í»åá¡¡žÜ‚+lñ@ëšymo:¼Øï–f“ÀF÷–{×i;£˜Á3VM¯sŸX•ËßR›C^TË)a[pG(œÛ³hG¡ÊLÞ{VmtcnÂÅ\-B ~a{¨bz±_‰»ïpAìîêÓÛ-‘*kó¹“m»Î‡š¥[w“AúXóùÈôBæ/)/Ú5@rƒÀ+ęŠåb”³VžæÑoöØçWåø#Π¿"ºŠ €3Rûöߨݵ˜øKav¯LTg6ŠTˆ”‘±Éâ3Ù`…ë Q¢£õ˼s W‹¶f…ã*“ ÚVI9µ! ³Ý–œÉguo b°¼ëϜ鬆3[nök÷s´WyÓAæÒO i¯w‚ ïϳ"¯1—ö£ícxz6ó8¬ü;%ÊʳÑ*¥ ï î°lè¨M¶¡ÞvîR”)U½uorƒ…Ü£¤>9Óq­ v—a]ÜW9"’ަͪÌÃÆåÞ_†k» qºÚðpã‚”jï*Pƒ)³(︬¾å¯J;j3‹£ãª¤Îãë> N^ôÊ<ó—Éð>ÜNÆa!"Õ›<üžÞtµ]Mã¬NHßuKÑ}-Ź—þÛ³_Tºc¶òõ%ï8/»^HÄÚ’‹Á:ܼ6ÏPҜ޴ÇÂáÎ×ZÎ˾{”‘•2ª~[Yëü,ÊY^ÆÓ{úÿn€pY¥õ¬t¼ràÂ+Ÿ=±ÂvB•*Ž11>æ]ªLU.”oi^åݳͧLû}|G93;ݸ¦“s’°M*å»¶­Õº]l vibà\mÀmÖ^«ºÎ§VjòWuCAËqéI¸f ÚñˆXuDûÔ@(ëµj3w5h|9Kb'9©zESâgcOr¯E¼£“>’Ë ×kÉÇ_deñ]8qjy¾JKö™*›í‘òR üéõ/Þ^²ÐýûØýyúEÅg—R9œåžÁ˜i-PY:Y+€7›]ïEO»šÕ ÏžÕÈM-¶ž}§¾kâS¿l>ʸ ÎkgfrÆ—:ZÛ7﫤ƈÍî‡Øòg¢]\†\¨d•›^Ë>c%õíeøób¸ö©~¹~è'¡¾KÀ½Hà™2U3z0¹ÉVû õʼ_y§[Õ7FrŠñ)iu½ÁuÃ1Ç©f)dLÎ'šÓb†-^½>𓨟±3ù2P”ÆPÝ$à9a'x©ü«Cw%T׎¿& æq îýÅY«SéJŒÑõéGÖ,ÇIh­Þ»w …ªP„º»¿ÝÌÙ±’øüwJÃQx½ÄâÞ¡—´]s]Bdº"òjcénõ­áPbƒQÊo.ÑV]ׄ^w‹g=Þ:^£žà LÅVèq±”Ez±í>ç—ÖÅufV¦—o*¶ FZ+ÇWZÍÛ4‰Ï™”s»ØîÖ1ޓ܀•›)ߺv«´ñ >\ñ>§dRõx•O‰Wi,6GŒß<ðÆo7¥ê®Ï]_ìáz×Qôä *áM7½Ænw°¦î’áÂ9WÂs²Øæòã³BM\Hc&÷ ¥æj“M»Jûh_›ƒ×®w‚9W±©`Þ^whšÍÒ“¶1^(ׇµù.žäü€Î•ǃÛwÙeŠb‚YAsÑÚî[K{*\¼Z“׬Y¾ˆÕÛÚcµ€ )e:èÞ±lÌáJýéJ°ÍñXTYrC@)4Xnf]^Ã^]OÙ½ÍH,FÕhYÞ}g$÷YYÒ;*Þ”ÌÓíÝ'q‡s½Ã‘æ«–¨¶ šžlwÇÊÁ/®(³Z„ê3CÝ(¿˜ÅÕÏn³T•Óˆ¤¹euJÚYfSE¹½œ&DæÌ¾×D—3†¬úý™àqÕí.è}­¦ÙmuLÔÐÌZÍ0믶<Û«U¯t’é”5:¨§ …BæšÓI3×rSîRb€Y£¡ãVEBxoEIι7¤èy¥žzæJ£«82-‡µšGƒƒišÀ<=)¡ÄËnP&¿nxy,',Ðïp~qàºf}®$iLÚâè3FÐ*¼UËð¤ 7ê×X#©t”Òw¢÷©nCå飿 é«/©R”Vô²ÁÔ±a«Ùz9H´‹YŒTÏŸQúdbemÇ6cÊBîm³” øœÊÀëº××2uXÕ¹h>'ï_´ ÷ÑeðØv€;Q»†÷]…µ‘W·¸ö½Ç’qhF_1¸« ƒ|¢ö+]òÔÛͨ°ðÉâST6ÚÑ—˜áðú#µt^‡—¥(X½÷,µL//½Nlb]Þºeúe¬ `•wt•ºžñhìövß¿§¼8sL[ü:—ìßÒÇéï7~[•àN½TºpØŸ†,°œµ^¨¯Ò‹Â£¸êä•ZÖ+#ã[Ù'º½ë©çÍž“„ð‡U7…å^jCÜ;FQ–:’9wÔCT¡mêí«Ë½Ðø·ìI{ÝY¦{’î+²Ö!ÀV½4¶“·„>ÞS-ÎçQîµÇ)4€³¨aš¤Y»×ðzHj™®§Mx¨õÞ:4믔ÐC*ÝÏ‚ *blÐÀNeçÁâW&62ù©BJ¹ÞXï»Tõöýc0€Z[‹¸_[Ç'trZ­P(ŒYQäëzeºê¿=9¤k¦ö.Ü7,·º#ÙîÇ„Šâ}±»ÅåC-¶¯3ÈÚ©­ôÏ»Y“K ÷=ÂaÚu×P§#‡‘ºÊœN7ÝÚˆ­¤rqèñ@U,Éz¹Ýó]wÏ+4’ÒZ.qªemµ¶sΜéITò¦€CË=w›šlu·Ã©Ξ/çŒbo;›z–UŸÄ\©qŠªÅ@}ÖÌŒW •ªäVæV«Å¦›® YÃÇsösóK«1g—h¤ö^vYé4e] ptEd½Y;ixÍ¢5 £«·ÝÛ˜¦zý>¿rKۭúÖc£!غ·ÛÙ®‹AF”69¢è¢ñ Ð6\Jzd½‰U· ñ3Ùf¶`Ûzåñè/ÃzžvŒÖsž ªµÃ;îµ½y¾ÔËÊsõÒÕÉïYCu^<ÄB×ZÇQ*3³LÌ-mbç€A·f.7ÄÝMò~ræê«áàŸe\œìâ¸mZ^B¯’–»EÅÕ&Iz…œ x‘¦Œã€0µ³Œ:„ðíÊ\Š—fërq—ÚÅï> îm!ò0Ê¡{•‰S¨SÛœ©U1Àð·®;È 2ýv½‚ý+pðò(†A´žË&fbE Õµ½94à.¸öº9ƒoqΧtw-C­ëHQ­µËCI–x¼¬úyB‹ô:ÎúDHsÄ–lF;žà÷ß"mÙ®¼8Á9Qó7x¶nwÀï7±©lŽ|;z¬Ý:£Ó˜Î¡óìOP¼†ÖðEÌsw³X”†dرŖÙä\ÛЃ[»E;F€û ]j«µÑÑ:ŠšKNų­-­Cc“e8Ê  çŠu+tAwxfÝq¾XL­*/DWGV0N_#5SèŠÌÐÞÜ|ÑyHpÚB(Û,a--Ð¾Å´Öæwi:wjT¹ÖŽÑ­é ·2A§€"·mã ¾Àú3®t6z¸iv÷ز£×•ÛÐÓlÂâÒo%½%˜û¬¬=uÑÇ(«L0…óâå]§KgrVÑÍ»}ÐÓpeñØO»—$îe{a÷oφPk99'\ ƒzQHÔkVpC.Öko6EÙ'N$HÚ$ ÊåÖílºUlݰÔv‡:ot4ÍJ´KfŠË»$óB»ðÔ²µ =;­¾¹kEâá¢ú—vVÐJò8NòçV¯‚ÝUkè&3+c9–uŒM,[i[¼KÀò|’NŠš_ 1ÑûX°€³©O•^å»-Ïú0㺃Ҷ\ƒD)$d„ „„`@’Bé$õ¸Ôª•Ç®|º˜91*P’Û_±Y½`Ç«ˆ øgèÛ>â.cÝ6"i>žî“-)–‡,FÍ¥ŠhäÎ é",ëâšâ¤äÖ—‡û „nÍé>“4ÿw~]Ä׬Ó;¦$H±ƒåç:Ü)91I¡ ¯®¯ôÝÀAtXB\b ÈÕ*p =©ˆFoÏþ¦«ÊMRoå$–,^T¨T¨z´nIoí”b‚¡o•7äþmׇD×Ô}xÖТ‘eNÛY '”=ä&'k7Ýžt|!|$ËjªÓ!1ž…‡tø¿Æà{KŸèðýâû0cpÜîõ} pî92з¯êæaŸT`š°I¾ªTž&Ð/wyKQA[fXÐòµá®•úæzT ¡E·¼²—[‰%f\ }žÙ:õ¯»éïÕ÷ñá™ïÎÃ:’ìûµ{^êYoç…=Oרâ4>îõs(­(`!±úSÝ«¸®“U•ä xÞª.Ý€´‰:úõ£;Š[¸ÙT¦YŸBšÇ(CÓy2Ï)ÁS-z©öëîqš¼µÈ¬Ö±Ç/e¾5•ß¹N ÷&>r׳¼ÖL«‚ü´îe´íæeôRÆÂáãbñý,B¦+Ø®Àz’¡ 6zÁ&س€<´’ÝÒ·Ü{Ô|‚¤ž7•zýA¿ºº¯‡Pùmf%H Þž¯ qœw,g¢g[zI{Ú-×¥|óqï=E^í¬¬™ìO Ôøwh~Lж11Ý&ºqÔÖ5 nÊØ¯§/‡,a#žÞîÊž¥}Bõìïœhã«rvX®±ÔkF]FÉjæmï,khÅË{²ÕtÍP…•Zóˆ ­ £nÓÐͬD§L¥»¼JÛe¶ª×yÚwæ„ò쮀úD‹æ]N›Ö…À½œñ¾±8°„×êîáÃZmäÝ«qf=ê‰7Òö· )*PØ¿ww öÞ5Õ®jòWWF™6ûa•·–ލŽ4  ¹ÖUÁ|qR®{V·8$UÝ,˜ÉY[e'Àk#7°²D…1PSLÚî“ wVß ö=í4 >±SËVC¹?XÊå‡M®Å‹i}`YT>8ƒÜ{ÊóC´†¡—uW º´¹îwCƹga £ˆ=Êc#¯_l‹K>êrޝ Žº®¤;ªÓIßoQê:ï„™N­ò*ûp邟“Z»ºÝÛÔ0ã×íõX5èŸFcëZÛœx6%´^ÌíÀåÌÔvEÛj±>œúïF´ªÂëhìíÍ£èÕÙÕu`½ó!)k­î÷bwó )ºm£“ƒµ4 à7›…ªÉÈs·‘æ&/, T°JP@ô•œ¡W“@eÝbùfƺÂçݵ¹z‚,eMÅJµ–Î]·JòÊój,eÜ?qØpGœ½ãÊ%¯ ¤,èH1¡ÞV9ªéöÁç!ms“º…  Í\8gÊÍÓ%Sx3°ÖgsêyLHJÊT¬íßQØÁàä6UßQé:,.†¢GMerì²Ä7o»6ØÓ.»Ü­µ:ÃN®·àðŠˆÐu#K._g¤2ŠÅáí+s6õ…{Ú$Ýë9.u *2q{FѺk–1J†Æ›­Î{Õ;ªø›Õg›wZïvÊ"ÔK|éMpßtV6ó%½5ÝTáÚéx » ÆÉõánMܬ¾çi+ã¨M ׊æR@”ÜÞÜÜBìjeä8àÏ9xžˆ6Ø2úÕû±LÌpGŽbuè✉-Oº³àʺŒ՛9©õ$º}c×n_Zaº)mp˜+£§&2W-&VÜ«µg³îàóB«OÎ;¦8Ä›‡¾8¯3Åç çÓºáôÁí/O²(ôþ¾áÓ¶÷½Cs$¦Í Ô»¤E* -±¾Ü©Ñá*Ë2Þ—×C…ó E¸IÀºøÖ÷žÑnz*$´¥ôúïÛ;ÚO¯3•—!^æŒLžÊ†B…a'æ½Ïü?»Í[yGàl%":Ø+,Q a$š+âÕ]HªÏåŸ ÂsøV’ºr:/`TÓKUï.® üM3\žó;úkæ"£;6Ħ¼©í¸À:zßߩ૟B˜ƒKû{'Ég…äÂT.ºêJÆ}2°Šz„$‚öñ4Aˆ¥»íÒÞf­ µyS5up…„-ÖþÂzü¯Óʶ¬\Å^XÜ©¼èÐzX ެ³w“œs»­‰w~GÓœÍZGEÀ¢g›:_;pe'½ÛzÏs»G ³ï5ÚCš½wçMݹ*ß©w¬ Éw Wæv}ÓÔ(wÈza…mo!¸úKBƒ9až~מ¯‚¡múSÎðVÄ Ó%õFVõ´²†Uë¨5£äËAÝê3:1yœÝØô5ÙÁª$VO1ENòTia Å\Ò=csÑŒÁê´÷qîN~í,©Sp<Ü®˜Ÿy–Z8ÖTOc¹Ùîžmñ¨C¾ÎêÞ­kѺ—¸¡]¾@ªzë¿`¬>Y §,Zí,îÎðf¦U6JÝÆiSCDX®fW:ÊPò޽®œi¥^© ¼5ƒååž2½~õ%cÒÔÔïJTöÇxu§Y»ÕÔëJU³2–oh°çQ™–].Íy4j•ÌÊÕ”‘ò9Ÿw*SÆ»vÐåw%Bû3ëÒÛ?)9êz»XÁ¸4¾ïo\g¹‰“8­3Ö¾Šƒéð»v Ækst¤\j·º Hõ‘S‚ô>—£6ií¿J^¿.¢3pXi-ÃíÆ4taLŽ— ¢ÐžR b§Ž+{™d[ËÕîß\~˜ç{®ê ˺ˆîö“ Æbax¿i»‡ ÅïÏKù,™n£²}Z±è©µbBÐwÜì%Ò±¨ 5µãZ»Ï+ÒsÆ¥¼»ºô¬ƒY+\î¶Æ’æG‘M›0ݨ+»V".%×{Í. òbú®ä¼É!ÃEÄŽßfŸ(áÐôì%óÛCªmJhJ™O °N#˜Ïœû¼x›&i µIÀYU.…oaù]ʰ«-»ç{—~ö²·ÃºïR’*>šn&!O}ªá8Ÿ=ûÜV¬ƒgLY{çN?zøTëÙŠÏ:˜_Û/¥aÎÙœw$vIy·Õc–êBËåx®LÅiÓ_YŒ6|{IùæeZöÉzôNÉ–o.LêŸ' ÕåŒ>ÉÏI-¾EÎ*€ð¯F¸uÛ¯ Y±ßŠº×.ëlZ ®ŽíÍHãz™6¹õuº·²VF¹žéÛ£ŠÈÆæÑ„á*[)n×#…oc«·pªW˜»"tÒé}‰¤n,ºZr£q²m;•‹-o)2‰jšØ'aÍ_^·çëºJ³<â^ ë=mFik½q»€1×};QŠCZ°9Ù¤™ F³R”òY‡g/®Ô7§]ã\ƒmr&·•G%˜œ¨«®¾ÍÅ+G*ʇnåŒ"V—É« ™Â#U0â'¨Ýw]\ve#›œ[ ^.R‘:æZYbø =ô†»¥5ÃÛ»WÑh aSÚ/{o–8üjuÌ2ûl;Ê÷8(5ZP"ÎR«•JÆÔ¥VÀجG[î™Ã›÷OksØ{°Ì,åmÝæ¨ìã*“d<Ýósá;è•ÝèÆm¥™”Ž ^'׫ÎNrz³ÂËu¥R^»wã¿0{ ê&¹6•l®ÌwicáÛ2+NÄÙoOŒ(Ô]„4qV}v«7¦ôÞ‚†ëÆ®­çvË•vÀ)Ö;…X?½î§•à·y)mØZÇâªK{sGì»EdÚkËE†^g§JºG%[iÒ¡WŽœh.ºj6ö²ÄÏskw÷SOôÜì ;&üE¯Þ’ÎZâá¸hñEµN C][×ÒÕ bq¸è:!,w µàœüg.|¸óåÎÖ»õè.à礯UYŽ1<©ÕW¶Î[(eà³ç{µ¾Æó©íØi¨B@Îuʃº8o¢º—zLœ*ÀÊ’ùív3¦]8¡è-®º¹oŒ†uï¼x‹ÖŽ"µKÐÊÇ}Zw†n[ר#…kèoH6g×z©{·¨2wÚ8šè~Ì(ÔÈi]ãåœ9ŒÝæ‰Ôx28pÍÝ[Äbg `ÔȺîÉEg‰-Ì\ô‘ÙÃYYÉ€†ÓCnñQ@1´\6>Ä;F=ãÖð=Y¸ó)E݇+XÁ1£Ç+:Bå? -ª²]IjÜ>¶ÓNÜÁ¼×­!áSëc|SœŒwuŒ¾ko:ð!—o¶ß]˜JPE,V®ìâ§}÷ßl¬ÞØâÚß]‰2ÜF&uíå. ™9Ùa>—cå¾–èÛdíÊv·NÓ2ÖU¼N¢™Šó"³k I!·›ƶ%µy1/„ÑØþÜjRÛX°[9‚eDq(ÄXn4(ÚÛë7Ûµ®Ò[Ä65-¹MÝ4÷hVî`›r<¦ÈeèÖh˺Ñó@mæ­é®÷rÚ Þ'mÖì…¹te”–m-­ÓQweö^°äw®C¥²µ¬S3b©·«#ǧw_[ÀZŽ‹´vÍh¥œ  l–ô(®ï^!qYc­ßž•)AÖ›).¸³KZ†ðƒ€Uä¹ñÝÕ`Ü[jȨ£¶qå+¤º`Vš`[§KU>Ó—µ}ÄËêc’Pê·ß ÷dz^ï?“ÉÆÏ§Qº[ë¼á”¸îŠ÷\î‚- ˆœÍRé]Ø~E%#öªŒ]«Oñîü†SËtwʴ瑦:2Å^ÝRjÆÓPIÐâÀä—ß¹[ìkÀ‡6›á={Eí%¹iÎ9öòrnÝ5í† §YËyXx:ݤ±ab?=$p.G×Üo¼Xë/}]g——]1é&œñÇè Á7ž±®÷Eó²UOJ‹–¬w`»:Eî¶S)|pŽ¥•u×BP²¶Œ·#êM­eo`¾oJíÁEð€sYd+SXY˜8%C]L ÊîÁN,Çw¯‘´âKIÕïef'i£Šù‰\1õ ÙåÞ—cç[ê@­Ðzz¨1W:âŽcöŠc<ô§Ö3k«s†Ç0t‹ ^Vîòêî€Ü Z¹ª³™•i–sw™»˜CzެÁ½'2ùõæ‹íz på!§+BºI ²(ZÒê.kºí_ÉáºÀ)±ßiClÕ•2´(AQ¾Kº$ÉQ ËC7Då[”tc ÆJ¤*=ì…^`VÑCnò¢Šv¶÷u±¢ÄÃ]ºÁ u8ÝJ—4=/µò€½ÞYB´F”ãÌ«¹çÜú„pÞ2À2`;åoƒ£u‘˜vì¥i ².=Ýu˜Mºco°lëZ¥Ž¡åÛVTì±7p»úõG8~ _••ÍYq«ò×\Ì#Ç:,¥S„í/†®»uàµ:´¸0áôáî¼ôWZ$ SëÒQ§B™ Ù%—é+/‘[ò® ¿#o§ždzÝÞqðؘ5*¼-W>HTô®o‘ìx÷aÞ§IEº'³³*òÙËZÜ4¶Ùÿrk{äpë¬ÝDœ¬%›-EÍÀЉ†ê6gN&-^õVz »=½™=ÜæàioóõºIÖsk¶ºQIຎú:Ùyœ½ãPµH'ð~«6”³ìÚ½¢rç“®©mvÚðIË™^ãöä¶`6yùeBzn颢l ”tÚRÏÏ5Ë<«„FÅY£ŸRB!´£XAK‘;F¬IŒ÷R†òZ;¼fæQÊl*½‰Dº²ìœkÐÕªßoï‘zNå¿KÅ¢—nä°·Ž:œÞï©=˜²ñ!‹šQX³¢Á‰gß+Íð€mGA–•hÚ—}=½È~É›½Wà›Ô9÷IÛÖºT-;Y|vÖ”Tî䶔ʸB$b(Ê꜈G5e,Û[táÝÒS«Ætrãp˜Yu—};± N¸òAVyLcß6növ¶Ã1š¼-+w¾ÇœÍç¨î âôz†›íÙ3=šìT”Ùz¯é$ZKÁ=»£ÊÔ¯\vðØ%ï ºój¯ºBqŸ!½ÉÕ´—¥òF®¼HÚ¶4…o_DîÎ+¢k.lj¢'÷#±sXdnƒëTC¨Î°aªã;8^ïy;4áîìÍ ù¹ËËë ÓðÁ8VË¥CªÆfÝÂuѰ´¬N³ÆR±e¨ªÎ t0ðÕÐâeÕzœîè0êNźpåÑרñSÛØ€Î[â__ºÜZLH{Ž{Çsº¼®uËݽíô¥#Ç3jÑcPöfÎøCW·k)µ¼ÑU­SÆTeL½¼.®2YÌíRñ"­¹Å.,„¡=›— ƱD*kЄ‡µVx À%d‡—.Àïh¸Þ¼Ñ»Q¡×1­y³v·S´w £lɵmt0í)\]îç.MXÉClnCÊbgÏ¢ÚÝ*³ÈzÊq*YßÌ5ôEyzËÕՠʶ!Þo{/º³;iU©Ñ;°SMÜó·ö¸›¶½îžåA£p]ÜèCXr­r°{2è®a ‹ëîf»°9c–†÷KP«Ö·ŸÓ+;M1O®È«®»i]MtÇS»{Íöï@¤'Õ£ÂיǺۡ3/¬Òì•æe¸}çáí¹‹®ðÝ¥•µÐ^øVjzM,SïV÷αZ‚÷‚l`»V6˜ÿÒq@>örbÌg‡îw™ƒ÷–w´áæVaÙЂÊë5)ûÉ@Üdéêõ½ŸC©g€—y[c³1Q8k­±Í£‰P µcAÁ‹…wgqêy¼QéÒóe&úøökxIyx©ðôí®]í–ðsj:ýHÄ¿{«;1xoв4·ž$šï·'h¾& Áj£¦¬¬'­>¬1¬É¸téÔ;wMÔî¶FãY‘®Å¶ÓÛº»ÔsܤúPÊMõZ{¦llpð+®T×eª¾ÎÐ:U³ëÍ~î{ š˜PNB¬œ  ÊܵÙzdX¶íÅ]Œº»Ô7yÛfåÙíËh{V|›ìãhÙÛïNÉ)n2vP¡MJÝœ¯y °à¶t0»ð¿°2µ*bõÙÐË}öò_,(¹»Ã¹à̓@;IÝG»‘¯%'O{– $ï`7^ë ô}" øç¯Mô‰UèöveNÅÏZj釛…Y9Ôjî¬1[[]k±m*J„ÂÆ¬æÓ×Úr|‡-ò7«¼z*z Ú~™èbʰVÄyžÔ.gMÉVqÖruÂ,o¦—º²λz–Bµ›LÝòÝõÉeì»—Y“xé2ÃG©ViT]’y›„7~ç‘í _;ëžmmRõí=ÉMÄûIî•XàÕ9® ö°pÐö7S,ÊG:î¯bõƸzuÞÎ *Ú-Éî­zî´´¯½6 àì—e§5‡©^täQ°Ñî›å8VÝèâww%lŒSà»& ½Ü<( 6¤ß¸à|À`Þà|ǧ<|}IŒ©Ç¤×>½‡*çnÒÖé‚v™v_Y†%óív—@¨ÚµO+2†KØÚ¥]-:ΗYN(Ô°θ˜å²ôYš™jÓn¹l¥¬[j€’ËMq9l&ûæºm`ñ‹§JÓ8æÖègÚa÷Žë÷5'”U›Cå'Ü2ÎXÓ±&àä´îV5;° ë:2ÉÄ œ'|ýëâ„UÕÕM'Ë<ǩѣÛ^û7cõ])±Šå#ÜvèÐZeù[Êð¬qô°NSÜ“NÍ7×Ûáwa4¥?Yóä+bcË'²…´ê¬(/«ËÏnÆ=ïd¼[—oÍx$ŽSðËØ¯9&míÕÉ/ígYÉŠtyµÆwÅ1)ÜåN©xŽºK=ö¾™«CÚEÝ‚ö×q F"!2ø-MSµ ‚‚Kè•F´ì¤e ØCcæesTîCSp‰VzÄ]î¼sÓªn½Ï|‰ÒþìäŸ[Ò¹šâ%ȧz.)4¬ ’V>jVKãPlºó2îPq]ÚlR—A*£û®Ð9 U‹íî´êA}Q÷_°•‘Ýø¿µÞ)®:že꓆yvw‡rWiÙÜo§6ÈÓJÓÕ¯Váhú…\²|Ôéí}@=˜²Ö–Y&]‰Ø5lE›cR¯W¡Úš'€öf:è33f:„ |7¹À ºì··µ)§Û£:öîö{ Í+%™q›Qè”ï×s†¼ÞåyÇtT·wånû3¶•»‘ä°ïf½÷ ¹CêgÉÑös¼º4KÞ ¨ð»@¼ÎN²È¶MÓÆ»Þ =éÅòwÖ)奣ÚKÐpÔWÂ{vZ–`›JpÌåZQôV¯ðÊï\a’<{ÎÞš5L¥õ»i­—ºû-ï=ÔVmB6Ò­”råštÕ‹{ëÊ;>TNýDfú´:^'ŸjTµY%æ`¬KLt[·µ ½V'Êzx ĵõì#ý,¿À39`zúQbò²õÊ5€O~š°ï’Äs¥Ç^aåf*¶l]z ¯e²þ£ÕvëbÓÛÑ]Xðk£j¶q»äIpö"”ròÕ§í…g06j­ðßU˜© ÊÑspȇ^äݘÇÚ½kº9Ôy9§ r™Q¥y¿gn\&=áV(ölÅ'w‚»n°4îu¡ÛJýÖµ,Uµ«íÃd¹Um#Ó@J¯r½-Š÷´ûÐò¿Ê~¾ù>€º˜§"QÜüó%H'YμƒûÙ‚—Œ2—º²Tö «R­´  Gqtð¥\ÞaPnæ`.1‡ÙÙ,%žF£ÃE{ùò¨Ô·É%Ìâó-äHE%Aw±“úo+ÛúÆÇíä ÌÙèívdPš(äTìŠâjç[`ºåà5>ÛNŸjÇWE–4UÒU¨Tê½$!N w.:µöì½ÄJ ëzuæÈݦxèÞK•ë ›0j—R·RïvIÒÏU×qNóŸv50:¯¡³Ü5TÉôëspÉym¿vÉu<¥òô­²†É~óÚ›i{ÊÒºZ›/Ԫʫ&*‹Ga€£šsð'Y ñsvš·,•Gwª¾›„v1[™†’ê[Û}VÖš}Sukr“7¼cNEÈfá‰Na[\½lä7e:§Úè**BÏF*´S’õñˆ×T̹–©&!¢Å<ÌÑÁ ³ó¹œö®Î¿&ís¿Có°ùQ™tKT&ûΧ°Iì ôö-¤=x–¸•dù€W–mk¾•æ8äÆì.솱õs/Ö <Ë™|Xº ®§‰ßfRà)tÜR®åÐr:ßrr:v¿z®½¹zî<ûD5+åwÙk¼i©zlìPÕ7v¹" ÷ ¸M)kÉMñJëÁGxÕp ¯w6×8Ú}s×5ÏF7z¢¬©bKCi—.îøVj®½GºÒ‡%Þ7‰ÎámÃWŸÆVÖ¨›UÈ1{lžŒW‚È!EXÄÙlSÑ—[Û‰âYÕwɲºxx5ž­D½ÆLEã͵1¬ê„\>Wf¨è»ÖØl:±E\Žò)¾¾P+F’¼èo.$s³BÜÈ ­ ÙÒï V‚ÌcGZ[–èo¼ËXr›I|ù+[ó«–gM -Uµf—g,ÒváÇ6¯#z@¤‚kr‡IÇ*œ :Ëãc°‹#¨¡ÍGÖšd´yJ¼Zƒ£ùOV™ƒÔZ(f¿ Ú,%cg ¡pQzº¥ÝÜf( †eu×([¹L^ݹr›åI2ôï>Òò­rBe¸77vœXCÄVD`U}+6séî]ìmVFŸ]v`YP*T†Jܸ«BÖÏÁMj*½‡¼Mû¢ÌÑR·®ÁÊX«@Y¯œ0t=õÏT6J®Ê˜ñü|@š)múpŽ‚µÂªeÆU^•ÜéRÞ®àzÎÕëFö…¡g]5s :È6iwjÉ™¼¹¬õpk FóVxŒ.%&Šßo>‘s<=iï§+~Ê …‚ƒ­ì£µÞl7žŸ ¨½ž€fsE½j»L6ã†êɶ Ò„ë›Ùû=§NÎr{hl£"¯}«Ï0J¬À».m®:Þñö¸®­ž>‡âo3zÓÛ‰zý2Ò¡t*úº¦ànõ4vTݼåÇ|‡Ä ‚iÇ„­ .ðÏYtµRËlzT$ò­™%Võ=W©SxštE-Ù]5smÍ-‚w„A­ÕáªÓËÖ ÃêêI¡ˆx'Pâ¬á33àGVp¾K X¥×Ôët­0=Xd¬GGrÂ)c÷¾åëò»¡Þ»ò0Ò¿c¡;@ÁÕÃß_gu›ßH÷GÔ"Æ)¶,‘S\ºÊLt1vîô*Ó¹²ÍC,ðÑMécÅ¿2vt}æfWfåu!j”¬ûÒ4qéoã[¼H®Ó‰|•Ü5o(‹y¼:Ɇ¹:ÀÙÓ—§v’°V‚2›»CT•ì| bkã·¤n@Ó(ÅꓼFW»‰Ãy:£¬ÓêÚ!åw£dðh=O&ŽÏ—wÜS`Dò«wXl0šïŽyÍŽÛâû+#c«–ÓcwkehÉK–ãåÐkº*3Ã[j—L>Ãxb§âM1{¹™G»²Š¡v9o 6»ãBAxŽª€qåôtâ™·u*‡DéJ¿9€ë~È«(“Ð\¶uÖÁÅ¢ڱTg.uhárÃS-ð£kvÙ§)[©Sj×ì8÷ƳÖÇ=,'ŽW™@@|,ê(“ÏÝÛ†•FùY‚IÝÊÆLîÇìïO‡hêU:½Ðñ)J›±e*WMiÏ üÀ°'¯eqE±yl/Ýg†?3›çÐð¨ên-ôÆ,Oo©»võUÞFÐòœÅYbš‡Q5 ­ÜZï¥ÈÔæ‡/uó'ÞÂëI²ºÖÍRB¸²Ÿ7Â} …³h]Ê›WÝ€÷wm@4õÃÒ#‚šWϱâæ‹1“†m+/fsXJÚè¡»6#³Re«Úå4± 5±W@;Š»§(:î+{‚/žò”îät´ö>Óf*“†áºd—€lI ³œÖYJSÎIëÛ]Ou˜e>‹;«V%­h̼¬ÿY£iÖ`ó ©N³W@YL]øÒ¸s?°Ì]wI ܵáÁêá9qšVCÌÒ$î¶EkWmÑìÑž%˜êíMï¸g£ä¯îç°p½±ä3:”ÝŠ†êˆõÞá^Zš^î¡®E+š(VÕÂ(öQO,ë“×iNÔö ?,ËÞ6ª:ñi&ñçV§I“"¹ü÷´_ïÛ´%ØðžëÚïM+Áû‰5,ɵ®iYÝé! ÍûÏÐàž¸-Àéñ:ˆóO\›Üìk¼,ïKYËKÊ·[D!ò#usx§Õx¿er¯ ÛäJ¤,l÷j”3¥Ö‹«®‚°T ž£Çx=δ(6Ön¿çm}¡ÏXô>—z¦¥ê5“’w=«¶û½ËÔ©¤b†eçóïQ,»Û/äw²´Ûßß«ßtì+W\Ï1wîOi@·ué *O “ö‚¿†1»§²»{x`A¼Œm¨ØB¦ƒ$<%^ ½/ Ì£g~Ú]:TdÞœïëoçϧ¥‘M,¦j¯×{Æ~ÐC÷Í{ÖöÐöáëx.çφmBõ]pŒ›ID7 Δæ ç¬n;zcÇë«è¬6™§ïcnóWqwVu!DNu›[«ôg¼‡½Ž†ö+‡{”&=ºw9âµá`Uøªzd@í¼£Ë½ë·‹ ]^Ó2NGn‹ñ2ÆâdGò¢ÞŒ¼ž•‡Ô4eùæ]bϺT›•%yñ;iÖ qV$¯/ÓO NÌÓÈÏ».ŽjÓåü©ö.™ëÜoå:ú’ ·VŠŽEÉtÝV ËߺL »ërûÍât®w¼WAh–t.Bî‚nÏJ»á‹jJ>è*ù¿GÏ;/ v´›µ‹4'ç]Wfù`ø;òñ5]£àTsœ9´³H nÝ[šäsì«\èW½<ÈšW‘|èXoÈ:kA$;Ê©jv0U äºÜµI‹«‹«Mû9/C‘ê6á¿R†^ãßE‹´Ó×ï&>·£/ T§£»¬0ûÔ¨rTÚÊ}¯˜qw:Î¥­Q®®S¾ësB­(å½w¬Â†uÞÖ¦kb\œñc¥qWÝxM;ªÞÇ“œ–Jߟvôy}€‘g—Mí>m'™šS{Øë9p [=°'»Ëë¿-YQs6÷,ìäêØ¾Hý¦ðf¶õÈ Z—ÜÖï>Å{kp<©KS+zçR®ææ¿èê01ùævýé55àpվɳ*î?k¥%ñ¬ÏåË”«} 3fô¦2w>6êyÊWžÉ‹|<ƒÇg)ÕÞ^7µn§eóèå´MÜÜÃÉ´ñR™ – ¢´Ú‰¨lCD.¦'o,Þ¦ Ù~8%÷¬¸XlŒô\`̬ÌVçFK9kÞ•‚C‰B¦!èð@îÑ·ÙêñXªZZºu­ ˜4Ò«úfxÝXw?*FॣBìè,Ýr6ŠñÃ+]ú¥£·rÊw6 ÖcÞ‚o;Áp•œåk(â;‡½ÁV)H:“µ^º™Àv,ZË¡œÜ·Y4Ótx(S@P:ÙäÔ5QlDR°2Ýp§:\î¦ï‹w†bÅ“Fd(wIoÕH“ŽPÌi“vña[¨¢v9ÄÉîóÜ<7“€æ+À½©=x¸ß§>‡uЏŠ!§£‹ãFJk¤¯zK¿^_­jâµÙ]×gCË­.è÷µà¸²„¡w/:'ºë}.ÏÇo›âSÞY7— ðõöïG®Q\²p³ Üû©vÜΓÈ]Œ=[Sn8‰·¢Ì«™'Ä°ÆæqÌ(©s7»”Ÿ8aœÒÁ¤« ÇS K[›Ë²»Q¶¶³Ÿ/V@Gº¦ª3׸½į́a;E1îs8Ѿ â)j¼=Õ)°¶`›¦†Ib奒ø—ð°rDoUîNE]©Â÷0&ïC§EeKÁ[¼s†¸Êã…pÖ'0Ҁ푹ݧ9Q[½¸„ÍÜá¨l>Í=;öß™Óí y¼h-9Þ]ìX·±¥NžÒRËà+—iÕ÷³ÈÝJ·»›t¸¤(N®àIeé\Õ¬žKÐ{×4̨^ùûÆÉÏ”³ƒµÚÅÉ!Q¸ÚZ_uícåÂdÚ)¥+)åÇIsူN¢ž@òÅshfŽœR«ÞÍÌ(‘ºZ iΩ½7VCµ­·Ë1ÎAî†t3S޼ξ w+C5dRž`I­bù…FK¶`¤¾(žQ¶›/N.NtËH°…y•g¯ðén¢75ûõ¶È_¿aËô÷Óu%íkèÈš\ ¶=I§V8Lœqë‘Vw¶÷—3Ú°±Ê‘Ø1?ñ»¯½«ew¼Vn@—3yV_m@[íêäÁØå:55Š­ÃÊ•L½¶Í¸1¥—˜&‘‡œ¨ðÝõ÷vô7Aã+l/O-ÅEhì«„qS~ŠŠej£¼üoÆ×”[— fÆÆ]ìø*÷,yôN´Æðèy×wgº'›—Îv0úgvKÅåZÇâ …ï¸Ò#È–ú6{™fÛ­Þ¶7¹¿0¯Ÿ_ØM¾Ì§Ö>…¿¶÷ÓbÞ°}-dü[©ÐÄ™¥Y´h«þLo3×+özú"³X‘ýÇek1:/»†$ŽŒºÀ[ó9…SIž…ÉS#ÉÈSÛ½°70ë¼4†gÇÛ·Þ'»ƒ}ÐÒSËÝ·åÛp]ú2óÒ•î­…änçi¡×AÜÓÏ®ÊÕ+pU“õì©:¥×ž]îå5M•[}î:‡L¶·¶·’κžC42yÍ< fNÉŦ%›lÜY“!X­æIbSk`ÇaÅj€²u)ʺ]LÝÃ&¹µ¤\„^I]O†‡[ŒÛΔ»rýØŒ ÓÏ7Ÿxº')?-ÁÚxškÕÕ§ […s[×C¦ÍvéÇQ'›žTSc†X‰8VØrVu$ľ’*z¬eç’EòÅô//°ëg÷« ìòˆ!\{½,ò£^ßíÒæåfªPUoev]Ò ù*\SKÓLYÊ‚• k›Ș1k-çcH,.uv0' dNXþY0”¦Æ[·-;¬RóJHН`=Çaíê=ÍëÓ³7”&>žwÇ¿E.Ðí™F"¤4«&"‚‹¤ë•ãmÙüªg¦Ÿb¼®§zЗ£å곺ò¬ÝrµšR,ˆ”ë·j_Qà:ïµ,ÑIªŽ&9WT´]Pí^g2uå!peŽRÞxÇPÅÐyäîLЦû$`«炱=wa0—‰Ï ®i).aØêWgÊt75®¾NAÞ7³ÙÝß÷òÁÇã‹‹…™ù›mþ‡ò×±pH‰?_ ~6lÓ—€ùgdºmV³] NŸ7Ÿ>{º© }ª˜­\¹‚-MÍ;*Õ©ÕÎUÓvw*Ô©œñôHŠ¢¥w¯^Kõ,÷¨à^¨B ô}¸ú8^÷…;¼|5øÕtPÆ.9p‘ê Vï›È«Ç>b‹Fym-èç T¸Ф­"ƒP·­NÅ„°5d>î ÂÌœp†“=^Pæéí,¢`5Ò÷•¡<3mœYqËf`É=Fœ ÀÇj%ñ¢:ïžÚ·—b+ë™Õ+±_k¯/˜&¹trrV›¬è›u|ÝwÝš¼ÒÐ1«ôÏ>cgC{ÞTQV‡j™d®¢m8ëwu;5W¦²fhБ­Sµ‰—¥U×'Ó˜![ƒT…Ýk}z]Ö¼ JoG*7g‡y|mm ÌÄÍ‚žpÍÅ˼NfR¹íQ‡]xg‡´xØó–d»¥]›h¬é«Ì-è|=æìXM SmÈà‚;öQÍæQι2µðÔ¤»Þ|©IrEŸq ¸RycfðÄêÝ*•uÔ¹ÓK«6éÃ3+Á÷ß9[U.¬Ã©VvH¸ì»aç d['gJËK¶Þð-³¸1Jšx‡ë4ÝÕZ ˜˜Þ„Ù ½LˆÃ¾bÅU¬]êꆮk+quK0S^šÈá§“’{æßaìŽÆ­8ÞlÌOBÌ팚Ö#Žs¥G¢‡†jº›pÉø±£|o©¤¬nyÓ:°ÏJ ¾ºÊ ¾Þã¸möcÀ0â­Á4ÕˆZÁù§ä†¯0ãñö¿VD¼8¯aï–¡ÒÆ6â×’Œ¡}v&,Vë{Mž¦ ,o^®íÞÀ+A°ãŒö[ª¸þ9ÝÃØ~š±ÐšnSæúDðYAñ—!·‚e•h>êÖ&ïR‚ù‘æqÖ0Eì·§#ãY&2š‘‚`—®¼ª_mñ¾VÔäEgCgŸ0ù¹Ø:>ˢÄ‹Ñ%mp¨¯Š°ꭻ%Ö¾ì:1M$£«=ç€ñÒ­[5¬æ‘SÔ½c.çtH ¼ž´Tž\hx‡zØ:<…‘K$tDW­«bß5ÛŒN&vWH¬ãRP•–æÜz‘Ƴ1†ôNmÊéðO9^âÝÞBÅ1Ì|ƒ¹,1 ®SãÅŠû$8r‚0R^jÒORöB©ô ½¹Š§½Þá^·ºv‚—V+|×jVº|Ð0«ÉØöç×{ðê57tƒÉÔ‚nðµšF÷d],y½‚œѰ´Žà©\®6&FöTE, Ûš«Êk^â¸2Œ¶‰/è6P5sÞ÷o€½(÷¡ôQä^÷‡]æ^#fÈUzÜß+I½,îÉf³ÃXF'—«_Szn “]qVÒX¹tåWl¦hcyfgJ–SG†å.ê´”V´ixðÛËÞ!ö¾ÑLUolœ9JTÀw†X®Ýì׸f>ôÚD¶ÐÄßÑùÛöf˜Ž£K¼©®‰ßU€ŽËçzåüúrƒPÊQ_ _›Ob †ÞÒÞe7âGiSÞ£êe0èxd2’ ÕcEzíOk­›wí×-·ã½Ñ ”ϳÖ<(!»ÝG„§b^>»…Vïm8ìü›¢Æ½7´¶hB¬z‰¹t¨'´}ÓVM¯oIFnÉïµ…#ýãJ]›( áp6×µn­lÞé;*йÜ.ìn˜·¸?¥»S*µs5®5¨'×|»jæ™ä¬Q\¬ç1™Ñ™»—Á<—ÍóëC0Ã^¬^S8ûÇ‚ÐIß?Z<ÎRf°¸N–“ÜÈ*À¼¢/+å¢úíiÌ‚ràêó~©äÊ3#c³t±©p¤‘‡kÓÚaàÞ¨Ú&’7Š œ&1Ò ‰lÍÒÓ¡L­Xï°óSµ|‘Êšü°oÍw§¾@]·Mô°±*U4ô½oVÏ’%ö4;¥=I'5A/O´6–ßzàål÷¥à®³JÏÁ–úëŒv}˜’­ÚF]îà®zÇ?9œîô¯Ð]ÒôyfãK«æ»õO’­,ûÙZN]¡xèŸ+{N–T£Î]ªàòÕ—Ïi'w¿;åyÓ’çs…“½£—JwÙÊ6_dÅnÕ•dëy¶ R+èèS›urqm'AÙ@; ×…ì•Ä o×]Ë—±h‡ÌTÓꜥNWªà¸2#=o¯­Œ¯e‰q èZ]§­TÁœ^'7FŸ$0®Õ{®VZV¬æ] ¯g·d®–“ôžæpí';%¾ Fq kÜßpõéµ€ó3’Ån¸zg«Ye×c/ÕNá—3Ž•ä!¡ë  7QŒŽÑaÖ¾§qÌêP6m:ÍìÉtW†7RÝNDZ.u’ÁÄ_½,d¿yì7…Ï+<ѵç±G“1Y4sybÁ©ñZ¨ …R]x(MlõÖ•VJ7Ú)Š=ynvƒ÷©½ºo‹Vb½yg¢®f²÷OWmûm`z^#°®Á­åGVAšÛ" ©Ù|‘/qE)0W–w=•£ž>5±b/©>–¯zæá°:§øg<ïhmúMÐQüuð«Y:Ž°ë€­Iä¶BÇŸŸ3w–¼Ï¶:ÉÑÅJMrg{1c=oà3»²DÁx»=u약$V_®’ʙە#`^ÎËo&¬éªÛÓvjj‘ïMÄô…B4ºõô¬~èw¶ å)±Z:€‚3»BQÁê}œÍînhÀïk#®h6ÛÃnä´kÜ«y‡`ç$Ò£Us'ÈÒêYb»¹ê÷Ú<öS<÷}£»ÜëÎ=Éo3Ç´yrhoŠñ¿ûÑë{­ì¬¬¹×g  qÖË´«fc¦^…Âh¾ká|Þ’éæ7XÞjœ÷†,ÓºsÁpõÉ=WžÏT½:nvö ¿y*é'®­ú)|},Ö*ß¹µ‘g{ÑM=ؽ4 óV÷fÔ»Kh/™[¹µ3ÙuFJÒ{é.`m Í[™Ÿ°*sî?7WO6ÀaùãI6&7°R¬¾+(ef@ûµöŒ®«÷o½·LøLÕ»,¶“Ëžuä7ª¥öȲlÛ¢™‡Û9Ôú³nBÀãnÓjŠ0Z¶6VÁ r¾zó•ŽÄ8=FÑ©É3öçkì«6¦,AÅU0WU¢¹V^È–´=ºþ´W›÷”>¨½ŠmÙy~¤<“&ð%K–ç¤ÔjôG„¤=v«Û¾ud†Óz7Y¯s¼s»Ú@—b+^i#‚E;í®vXš÷“ç^gm$«¾)¥]ãÑ›£n±^§·VÑöÓ»C̵Dü ¡ù›x¤šÒöP0GØ’ $¹â]˜-Qc˽Òu8³ªLEHï6éV/%KyV£¦ì×ÔéQvlk±=‰ðó¥Bý~\‡¸©ÝZ¦o´Þ+/Èß-gÇ oµZMD}­©C;h¬åo‡t³IÖu…‰·‡«o[Ðo1ÑÖ¬˜ÃWUjòHN,Y!†˜Ëöç^Þ¾ÃÏ=}˜8>¬:ñéßËÏÒº³ëæmšî¨›ò»4àjåSMø{-N}ç­Êä-Ölp³äÔîŠîèu6Fìr©Dêžt‘òÑ^Õ~Oo4j’EÞâ Þ‹_•bëÓï;(P<ÁdÏv»Ç„ãås³W]ë“Û$/ÏÚ塳& |Œç9ÏŸU™‚pi5;}ðu¤®«âõ2²û®e ÔïvÛˆŒÞVíôwËš[®!¯î–+›H—T‰/Xuà=°M5ÖܱÍA¹—§3y{A kÛ?+ÞNîùŽ l£Õ…WGë’ñ;'„ >¦jLÜáRf°·/P]é–ž©xlJ«0ªB0ÆÖVÕë„©:4ë0*9[‹oÝòiƒÚÖ¹ÇÜ…L¯iڞŚ=BˆCÙÁtžw2ÚJ•¦aÌ®½Å¯4gTbr øž"N}1)²!ݸ(Âz‡få`¦ÂTv#5‰Q„Ý߳ޱ:îd€˜€¸¢¿f:³â/'úh3«´eï^•h¨²pèé=à"·Æ}o'G‹U{[î©{G<4ðhacÑïv`=é™D)ŠX¥m›»[Ñr´ÊBêF Leó®{NŽTÑUá]gYíõ¼rÍË^£¶¯–Q¥²ì9-všÜáf•Cs¨ÙÙT^ÕlQÝÉ\bfqÑÜFo¡)ÖȃÚ÷Uë½™ÛÔ^x<¶òÉ]}k^|ÓÁ™’ Áö…Äß`Ä›lg^xÖq; «¬æçnNrÅZ¥Qobö½áíé¼­a¿‚OÀ,¶AÅžö ¶²ý=ùÛB¤Ép%|]©r±ùnþt‡¯+·EV¬ƒéÜ嬣¸zV°‡½Ô¾Ék•ÕÎáèØ·»Ü8Vf-Þ"ëw©Jެ˜:TS~¸¸=æ’­ o§sÊêך†ðͽçdšâñŠ Î•v–un*™†]é,؇<Ñ0°2yÕGs¦dì•tºæuE‹:—š²‚jž šq«W{3il9ö½CqŽ…2VècÝ^ss¾7¼íjö;ƒ[Ó 'ªb§)’3çvž>ȆÉd¾CÆøtö'BdáÞˆíÊLÛË[]]ˆ<+ˆµ3΂æ^=íwÕž¸Õö£UÓ˜ê;yÕ·l6:ñŸyŽ} îy4=Íï«-~Œ«ž>ô¹}λ5y``Aç»ÏŒj•I(]=¬¢ë€á3•Ìî ][ÕÖ¶vwD/Yg±â”9ÉRεR†o)¥…¯¨›¥Ùd“©œˆ¼ÅYÌ×—F¡{]ö’Æj¾J|–‹0G‘+qZ¡f½ÙÖ]5xë¾ëI Ú@餟 y¹QX¼Dõœ/iμÚîës£A]{)m…Zé^~û?zHE_ç+|e­|﨔Á»Û䘳v¬bÊÍär²ßÏS‡\°ÙSÒìhd§2íëh˜jšÁ¨è±*iRMú¶JSÞãÛªýs°%§Ù%ðK­šÓ¼M¾c¦¦½qNÌu{$Þ+¢íÏ ÛYbÍ»õ,ÙMյϓ•ÝFöÈ탠¿aëΰ™ïOgZK3&‚”å1uiS²Ê+²í[•µw¿ áÔJC^îca¨’3&ׯö´ÏJ˜ÌîÝíÜÍk.šwNbìtGd£{Ï-š×¼Î¥‰œìu©x^ZÑ1´+y6(`ÙçŽêK³{kº· ÞK—Ý„Ô=“Y,‰È#'Ñm¶u¹V·2ûv’3˜Ö›˜ñÞG/mvEsº`¹¼Ü«§–‡¼yw3Î+Åó/2Ýu­=™ØL—|»&nÌ·ä“åòBzJ=®ÂSpîÇÉ,Nš•1ï&î¯};rnuw„a©íÈ«> ©÷jËȲvª5¹•„]RøÍt7Cs+†²ŽC¥¯ ·tµÝ=crd66íÒQYt„WÎú´Î‰–4{¨çŠòåJÕLSQPW”yV]N •²Ü ý+rÍ5×”ŒÙÆÞYâ¬Ó4ðÃG/Bãù\4ž:Êï*UwIxø['¬Ë îc…KаÇx»§­]5Ûö3ä»C¾§7Èb¡Ú;¨N³ËW[ÑS¤ÜÊ[»šìÒÞaD“á!EÐä–ðg)[¹³;³Vò´m]ÕX‡N#–8<„én»‹bnŠ‹¸ÒÜû&œl´ÇÞS¯˜÷‡§€›sn߬]&†=wÜßj©¹°®»[Ç…"ž§3,JÆù›Ö¦oj*h-­aœ×V…Õ¬¸®ÔÞ}\ýîÒêò»ë]í2òÅH¾PÊÝ\:ûEsH´÷TÑ‘§£J^v«2½J¶ÝA¹±0†îµc«EE«ãvI-jzi£“mòòº›~š(íŒbó>He YzªL¤iÐz>ÊÆ×Tëéu‘ T8ò.mm5wko;Ã3®g•ô^Qé: ñ¶‚ãB((ÜY€ÉAŒP ´>SQP™œ4O·=@ç¯y–{·úGHuÓõãÄ·ˆˆóÌ"<ÂNÊWßÔjp>íÜ•£j;yp=wâï°#I%n òë…w³ÌJÅtl˱²nÔØLô>M{¶F©]ç×/¯À†W¹UР¸eõœ>žÝ¯AE½$:ÜR™ M\Qei¥Ø®—61aÅ»§%&1mO)[î÷¢tÒËá¿#:šËë[¢¦Í{”ú‰¿>²9­ê[ÁK¶ÕÝ w´žR rð¸ Ñ¢a·K¼”÷"+­%V9ð³²è>X(޳§ž9[€Ïôc°â¤¦wEž4]u¹¥OÓÛð´ý¾9äF{ã,kÚ×P‰+×Ä_¶’ëpÒu¶[׆hRˆÆšÒP¥÷D8µ3 ‹b§AôâÌ"¥o:Ã}eG2¦‹¥çZù áîA¼¶Á¨ˆ2‚Ö7»4¾ƒ9 ]€u×TÜî1 R f^96ܜ׷–G¼òäî£ÛòËPó&z°uµ·ÚÕï…ÔuTún°›gk 41f6º/”o¥ß‘F·n½ÉzvæºN7½îêbºÄìèã¾(?ekÍ¿p§Vìb6·2Íg)†Ýïïrs®ÆŒ>qQdè·$ðôö{ÃÚ)Þù SL—ºh¨˜ä¤ @—ÀrßŠÜæbäÃÙgbAë¬âïÌÐÊrE×ÚÃÁˆTX(¬û¶•MTjl¸õ×kº“2¨_;ªì.‘ðö¹6°cšjóÐea@ïJéVÊáÏ{E:Ö½5åæ@Š×—€Ò½Óœƒœؤ©Y‹ã†¶¶XžÄåî…Po]§XúÝκ4j÷‹mSŠã¢·#[V¸Y¤7MfÀå»Ê'·x­kÜvPöuq•éjÈ×YdÞ`œoåk¬¨p Åy+Ü¥%UsÞu„Ú4H àó§½³kor>þ}û½'¿V´ÿ«O¹eáÞ·E·']u×Fˆµ‹U>º²;!I‹Au¼.§v¥s/¸™¬o6aiF®–ŠRó KíŽ%3²¥öjƒ{sºUϤã»XRå­F”]j¹©‹’Æ•·M9+‡W°>i¶ï\–yÜ#_9î´úwB£Viuj[—¹IH†\üÓ÷KÞšY;~°gŸð»ŽÑ¨é1nìØ¯w×opí[qQÜÀÓ´!\ “3E×Y;º±j<•RÄq­¿´‰”e3véøèî]ÇÖïhÛºMÁ‰eë©»v§‡S•¢o Ëá^ó‰°R®µx¶îÜÜë +˜¶‘n™ö:ðÍ“‰ãÕðj&[£|“].©Ì™ÃmŒ¡ñS¸RÖ›½é‘ëÑÏn-qê2¸gºìÉVÜÙËRÚ;1Vãäù‹ì˜öº%¦nÓ<‚cRYÉ\NÐçÒ1IíeöæI0e ÔC)µ8q ‰¼’±óW”ð,kd°z“È­×jt²®…<öæ5ïr£¤.O˜MÙ š÷‰§•w €ž<ìz‡²Í¼óÖ÷ Ë0K—™PxD\ìÞòèÒýTìµ³+nŠ6k²ÂÍ~“5ÐÊÌÜtˆÙJ˜¼Ô"Δ±2ÄZF»®¡ „Ðo}ß?uÐnƒ>`pM}¾{uáY&Og¬’kÆðê\²üvm˺|Úa0ýKˆ}: ÌÒ´¥ÆÁB3†µöhÎæ‹ŒaÊ X†ïFÖ5kû~ŸGwh}¹’1Æ„±×o;ÝÅû)lPvëá§}âlSweÉy:"ìdvxÚ·Íy VžM5›ÛFj:¾ ig•Ý1ÈÓhfXÛ”Kw-ƒ7®)©ÖT4à¥x—uÔ§ ]lfåˆêú¸Ýv ž}nŠÍCÒüw^ªÛÅ”ç&nëØÕ†ÑQ«f2¯™ž^¶šÆRÍ‹(¢ï²q¬58CÐû5Nö/?V¾ðhŠ!Wb%Po7«¬Go€PþµW²¸EyÃØ4,Éø‹ƒ ¦2Åæ:µ)µgÈKÁ8 x³;:°wYXss€­Ž» &!Ø+º•°=çÌ_…{³¯K©™¢%”»µÑÊÛ´B*­Ñ¥¯–‘ïuJ­9Œ¢ÛǾd¡á›€Ø9–`qî°C]Ü”ddë&L 8$…JÅt2ô,Zdêíõe‰™+FZ¾½¬F{_;.MZÍ3ÉW1ffEN:;Êûĸ˪4d¾YÔï”ú­6&•1l­z¥çV/® Êy\­ŽG‰4¹B"ùØPmÇoL»{¤¸Úʼ;—,Q¬8y±1Ê™°÷*Ýx/† º¶ýÜð<Ö8^›>žô7Ò±¨$›ZÜóÍ]®ºÍÂ@Lõ,¶­æì!p©{ ¥{¼„^™¨ö›9«žm½UÔ&ÀW#^ô¿Ptix×zÑÔ}q*K(í>Ëæ¦WnrîŠ)9gyýPõŸJ8‡~žA7=+´I‰ÝÂÛ¥$â³*Ø ºXý…w—SÔ÷V ‘ÒÇ—5ÐV‹èâi¹³c*NLZ©rWp‹½²bµ¬U÷p©@êò¸¸m,˨°péBõ)mÝa°’Ò¢°`v¥^ã¦oiÅY5Õ±Õ‘`Èæ¤äH`8{Ÿi gY“S/;„¦ÖQ²-ÔñÝî¦L¾7)kïo«½WÔÆ Q°.‡9/ŽŠ;\ïŸX—¸ÕLQjRZßoét.±ûZ°Sã«r%Ǩma\¼¹â“ÔjëŸÀž¦ªÀXÑ,·ˆtMwpwÝqò”ø<ÚË+~[ª€Œ?v%uª³s‡#Ê“Ýu•eñ©Žé[hòŸ uD{½³‹í÷K*ú¢ÜÅ™ìö»ž}¼Ú/W»—P’·p{¤G{uÚÛØÉ>#ÍßUµX²ã7Ð`0—³^‹«Ô!T½ÒêÒ>(éí}0I{•ÊîŠTº Ô;¼†"Ý‘už;Éé£Ú3­VÝ·©åüœmwl•2I-,»“¢ÒÂo–pÓ2^]_-ûŽL²ú§Z[¹j°î*ê\cnV‹Qæ!BlpÍÐçX›;0ºÇ¨÷^Œž^¤ˆzÁ¡Cxi§&€0X#–©Ë¤{Õ¾âõÝšiìÈ’OrÚÚUØ­r”ËÖây+Èg«Ÿ]•Ž´£t©ÐÞ†|oDÛ#^SÛ½Ý=èÕîHmªuÚ¦:ï—`lš;mfö/#Ó%]‰¤¥€‘•´ã*‘Æmú“k›µQ³‡0dÔökÇP†ìa¶ô³N{9ô@Õ­B¥^ÚÉtB¶Öªž†ÐÏ;oÝeoMOƦ ­îW€Ôƒ2’îtÜv,pÀÞMKr(½Áâ^Ò¢á½Ã Ž÷më'Ü¢áI|÷‘ŸVù¤q@«i/±(Æú±ßÄ=vlø#îäøËCÒIyY̹ˆzw¶/=çã{BõÐôoR•… ¯ ìs¹:·hò÷%êc·|n;vmòC÷­Ä&£V{Ø)cëµ*s…ö³³omõ#]š™³Ççªøœ®V-4¯¾(ë±I¨Ý¹œ2ºmví'Q‘µÓi_ +£Ë7+b'Šk¡ÙW·G…Ý•.X·—ȰúBx%ȹ ÓÏNUkL^;`š-pEæ¶]Ju«zíòÅ«(‹Œ*Y|ƒ2ÖeÕìC93)U1g)‡¨ôô¾ÃÏž°KñvbÔýü¼x©“å·JVý¨IV…GŽÎÖ%4?Ý:öýÐåJ¸Å[¶µwtšïJ&$kFdõnu®ŒIZ8‹È÷$wÅÁ‰ž·àý™W§3/|•¬]ÆÝIžº|;˜;º½zù]Ûz3]ÓåÔ%¶0 æØZ‹hµä{ɾ1²tr©æÖ{Éó¾}¹ÃA›O·\éx®“{áÝ×¾ÌO)îJÉXêŠr-ïøgëüÆ~å GK?kÐÕ]f”­Ó€Ñ¥©^¸Ù«¿Ô›"½:³ ,Úû£07˜€È,XˆÓ—Äzû0Ë–¯Óµ˜5MÖÔ Û|ì$³€t]ö ‹ÞÇÆðuäñ15™Æã[îg}«rò£y‚ëåàŠr‘nòGA}^)Ý÷¦“¾^ñBø%tˆÑÊB„7|8Ÿ9b±àÞ ½­YÍcS6×É\SÞÚÃ9Á—Õ€cɵ¥‚[›Š{ è`sc?=Ütò¯mýÕeNê¼ÀåxKó…×W[’BPà†DÓëòAÓ¦è;ÒïžÛ ÷|®v- 9šO1Ï /“@è,B¯¹´sÞuwÙ•”K2B%“ˆŒaÉb³/6ÖR±M‹r²M“ÙŒTƒ˜V^ËQ#3J!å¦TA”EÄw4Ž&¦ƒ»¶®TÉÏR…€ÇXÒ«¡Ã³ç•ÔýŽ»¾”ÜÇ^µ,Ù"šua™.öö“Wƒ†s¹]=ï]n˜ÆGñWx¥_YÍo>Ø@›XÞÞƆžJÙX0Q ê” 3‰’·(„þñâä‡ï{¾Ù§ÔƲéP¼ ŽÜך5¦ÎÕÅXBR›|˜³¯;`Úv]œ[Ük˜j·“\r™¼Õ’´ºþ+Þ1u9ç˜U{1È»º¬š2]ÔONÖÌ3fDíp”=k Í5/ÄhEåêJjuÜ]Ç °%:åõ¦CblŸ[®;JŠhÂn4:otb±Å ŠÖ^<7Z³:€Ñ(´¸j»¿οl½©Ígª]öÒ€!@XÁÓuÝ»[Pû;•®*€žu˜eê67Yî;å>v2yDQÕµ*öWxåÞåyý| Y>±ˆõ5\ÙWí¥™|È"Æn¤ïuqºçÙ›W›H €É˜¢Öƒ¿dP¸žëAÖ>¬¨l0©[L=mU„"Íå+ÚùŒéeÜk»XÓ6e<ñ­ Îu>Þ&øs-vÄnuÖžÙËz­-ä§°W™k2t©Û:yL{[ïT ¯=²p¿JÝx‚8ÜqOqPÅÄ|¬æÃ–Î]Ù÷&…‰ÎAÕd°wk«ðƒ›16-c<–ÆNÑêcÀݪ~®d®;SŒ×d:ÊçX³~bð¤îN\©%¾½ÐƒÃ9>$¼<€0ÅcÊÎd,Z åvJCµÚg4ò˜€ ±°R¿a{j`s|æIæ×a"Xr íXѳ™I©SàŠšGo¨ÖŽê9E*íF…à› çº¢Ñ܈ÒêSâBx•øqcoªqÞÊœºåûN×[G3ÖçãŽá¬½«7 Úmœx*{Å 0úúÛôò•ý»$÷ HˆËwÕµžî®Î=ÙN甦ضpT¯ Ѓ0ùöç@ÛÊʇwZì“Øû†ã{Þ¶óÉÌzÜÆS¥st>%$€Ëì:ª<¢Ÿv§ró:ƒ°H @{Û˜ç%—ÍÌïç[»œ_ëüVcXÇèª/« Oxƒºv‘wƒzhW—l˜(ovåæM¤ÛÂtn­‰æŽÖ‚ <æ*Ù•±ŠŽé‡‚£0vÐg(é¦q¸ì íÞe„û í ãg^KúèßÈ wvsA‚mö<­ìÉzާ‹GÙ•í³Ké.7¥>xoÅŸKÆûIöâyqn¿eñ Õ¦µ®íŽ:&.}Y´Æ²w–UËH×<îξڊS±æp[Íf²<Ú÷;×¼²Ö€Çº°´­åñ¤Õ‡–Y¤V0ë®M8.s¾ˆ]S% ]2`ìçÛIÝ5¡lfŸ@³Ál5»¢TÆR¥z+¥(Lèý‘ud—i À³Ñ7Ö‹Ã|–Œ‡·e»¨_L=]4ÊX†5•¡]·HÑöá'X^YÏ)m׫y>c.-Ùj‡¢õÌèÆ»€† ½&oµú‹«g6ÑqÎì¶q¦Ù¡¨ ®]vñΡ[½{[¨c:7;©”ž81¹]X„nÇUøÛ/åXµ½]’8gcŽºHÍ.ì°/hLPöfáÁ^¶kÆJ=xÎmÁ¢½xzŽ ùígVœpíËô”êéÉp©ÌãmŽå¥´Û{E€e¸êT™W•nƒ¬¼ðu?[/©º]å¿¿$­d‰ÖÏUîÔf-}be] kI„Ojˆ.V{|7U«‘.Ü]Åóí~ê8-¯‰¾¾kŒãËΚ®ÜT•aŒ¾ÍÉO²ˆ2ž4œöooÑek¢íú¦na&fi[ö³ö§´í¡WQÏgz‹•5¾f¦’±×Žû~ÑdÌ®í“úv†Nƒá8>Ì^nÉNQ×¾é[‚d2ñ±A+Ùy»G‡t'BŸÜÆd8cRíµŽ{Ú¢³®|§ÁÆNen=ûƒ‘%Dc©» æ×&=äŽØ=ê!›#nÂyÈÞ=öäŠòž„§A1Lº”éƒqßÑVnX² MÙïH(ðJ»ºß,¼¯vµ¾h†z‰qOÁ¹Û^¦E¬Tý:ñÐLŽ¿MÒ‡gºCW=³vMî÷] 9dQöÔHªs×âÃnÊ^É‹žR˜#W}ÏËÎd\9Ò«»+2aåV"Úœå9É(Ìw€øá²·Ú9¨«-o½]{Øò´låàU³H¦ 'fíæ‘ª\ŠfÀÁ«Iš¶qÔB56› ¥Å”&ä§’†b7%nS¸ D+­¬\9‡BÔš c„;Õ|–ÙÇË,æ»po€u*²&f\¨ûH{ÉRóßuãVYÆúóÁ¦);ŽQ=¯ZÛÆ˜ûx5çnß Š™†TùÌ\Îer×ÍNG½F¶‚c!»™ÍgI†Ù›K‡<ʵĪ[Oâ‡/–]HŠtEÎÉ2vZfN<”1,´°†Ê°nùõ›O¸,`É¿u%g ¸öê"ËÕ*fÜ®.QPÊ™¸×RSuqãDñD ñ¯sº5 ›îHb>ò{‡{,éV34%{CJ熚іTFšRÆš=9EhIž[wìñ²€;çžļc ›œßcå­ÉGIJóRÓ:x%Ë\U¯N—¹XCµwP,=„óÒ¾z.¸b:X¡‘'‡qÞ= °îØ[ eåó£É] ™hÈ—‡GÕüùëêxº•܆/×]ê» ÃÝQ«‰-]ýœñt´W1F/l «tÂöî]XL µBæÀeÀ¤&¯Ó=´ÃéÇdUm¨¬‰¦v;—véúŒè§zÒêw)8UŠJ‰D^^”-«‰ê-3‚ïÕ¾·=µ”­,÷Ž!Þ`¬ÍÔº÷JÁZ6ïáHTKÂ¥«gfáó[Žýª^\÷—e¿+ù>ÈÕo²^Iì2’(CÙÁ¿H1×½•å:ô½-Œ–`?.²­ +í³ÊÎÓpÁ¯©òŠÀB¤3R\p.—‰à™ïqõ™@¿Bz‘ÖñY: mË¥wo>‡Ÿë*e¡ORÔ X‰£Vœóf£Ê ]úw{Ô½Ø'±Ús1'X{µeÓÑ"=ÕÆžÏ¡ ³U»4]3³jK¬  %hÌL«d¼´Q§­g­½°ß™†xÍLeúæeÉ…A܉î¬|ò_=Ì͘;"gàíneÒ}Kº¸lEM[ÍaìÏ>Ò-ä=¾ÅjêÑ]éÉ/.N4Ål›â켤sÚ}6¢N•(¶Ö¡£*÷R§7LÍŽí`ŠÁ,Ø&U$éQXãsÂÕª¾ÕÜÖñÁ½Y´cBÑ$ç6£:©Ö‹t¦­/{½ƒ`Ýxß,2™ð²²Ž –²Ä4yÊÈÞwì̵S»Œ$é|"”Í8)6.Êšêeöˆvè:vª`æXŽÍÕÑÑÊÆÖ¨pŸ=÷”ù)yø> •^Eç–ŸPÛÊXæÞyÖ<Ùéé`÷i›¸9¡Ô3ÔÝ+C@®Q括ß1zø»:qzµ,/ÝË×ϺŸ°ªC2ü€©½6VŠÑ‚5ÙH®§}Ôô¯+×ZÖ¯sôS935뙬¦»bXW¹ôÞCH eÌð¤ž,)†èæ ¡ê O3¯pbhÓÿkÇëßrò›GÛ+7¨åG?-)­Á¬ùYíÜôïw¨â¬"¯/“ÍÙ4(6ö‹²AØŒ•Ø„k~罎¹¹@澫ÎWVa.ŠÝp·”ï•ÓÙEྺc¤6îÔ]ÅŸáW]#pr†w]÷Mû©Vˇ(r·X,¯vl*¹åX³t늗Y)tW7o¾ÝÛ,d¸â}u®pãRÆÖ7Š"\ØÞ_—~ÏJe'§e1#÷1bg.ãb¯m¦•xÌuf=PU»X·jGmЫV‰Øã"±€ßqK ½l,1ƒV«Ýì—ÜDTIÅg\‘áÒjˆÔËWµÛɲƒz¦ñ‹Ê0„¥“z¥Õ„fÎ#´w[ƒÛ×B›¿øúò¦q¬å•Û¶§¯W–… ¸äjæjÝ-ñ4ô`Šïç‹F¬pÐÏmKéSV¯] ERƒ„7¸pެÝËy‹¶tË.)ÊÆeaÃÑœŸ™ðü2ýù×Q8?‚ßáoµ~vîz-exyfôqT±^é;§{r*°Z|ç(˜äÓ¢t >Pfîrí¬bKv‘õùÒfó®ÚèïÂT )Ó¹¯: 7á¨ÒòLBqé¢pòá¦Æð‹ÆeîP¸.¥uDÑyé÷ +³È/¥ ¿½´%eš:­÷;d¤‰ÎmK[£ÂýØßLK·he¿ ãpôHglWÔí·š=:)³ëÑõ ÏKÙ¨Ý?UÚ sݲ~VÑ<·gJvócôû¥¾O/G7ƒ'ÃFîÑÎÚຣÆÈŠSxô½PðÞÔºÔ4—3ü9‚25ó$5ÍF5ìàýáe˜U5žwWaü1iâ ðý|ßèRÍx€¤íÎ西g©Ajåñ4”¯Mpã|Hê¶{ÈR)^³åÒ+Ü)œÜ÷¾ÛÚsÆéUC{§íß¾¼øŽóqÈÆöŒ,3UÃ3Xó®8a¢5x·…®4xX&Pµ¸ 5v3·@-e¶ÎزzÇÐkWSºƒó¶Ež|Ë\“.7 EQлÐb£G|éT»Ùdºš"X©ÞbÄìVNtDZ5Ë¿¹V­îÑùÏ߇7}Äbr¤cžœ)Û¦¬ÉQôOx^ŠÁ¼vó“è2ݾR‚J¡W–ŒK‚1³¥`UÃ'žV"ö7w%\—©3Næô).Õ¯MN}#¡ÕTclì^Ú£ J­-ŸS%ÕšVö(m=ŒŠh_bS¾²gsaz9îA¬ C. ¨ÔĽܨ¶î*P0»³ÜæŒÑÍ ÚJËÇ á:’aÝæPå´KÜYÎMWAѶÖ®uA¿;Ñݲ›S{X5×~ Ûît'’â²¹ú[÷Vu¢ªÂÄM?\ùû‚ xK¹]Ù¶ ‰çhä°uã×u½}ŠMŠÅôµ2q êZîEá@û˜ãçÙ®#ª¥,ñU˜fGÝ;+ì÷–uɺÙj û×çwº+ˈ@Ùá9˜«©[;B¼­5Þ1î–}Á«¡¦ë!>ñî^ê¾ëÁõo¶i™¹ÕÏlY+ŸY÷‚¶ßbÏOvë«5Ú»eãj¯Æ+UŠøtžÊC`C¦+µÆNÝXüS×~ëû¿Gìýæ+c­9lL°x["¸­ v²ÛZÖgL‰Ýï°/m›[ª§ròµÒÄ&Dzšñop £jyÔ­ýïCØç&H¨zîŠöœ‚Q·v5ª¯¸Uà;,ÙèÛIJ´UÝRW é½w-Ú–QµÛ[L‚+sŒÉÀÈåOº¬™ùËÊN»Uî~í=gÔ9#¶,›ÅüÝϳªhhéV)­Ûîx¡6©ç`3·Ã©H}«Û—˜î ï{Ä!¢»‰ûrøãÙîœjEÇ6ÏË®®y#„õmÕÄ~õ°Õ.zÑ“ÎÕLÝ»u•íÊO Åž[amŧï–8¯Ü…ì[WëŽÂJ)|H£Œp Î; û·_µW{ŽGNýÈÑE7¦½…×u±Œí£S­n,؃ÜÜ Q©Ôq&ã©îºèG„|§¤`ëäíãÌ‘­áð«KÊôdêñˆÊ ÏK¾ãt¬]q_R²n˜(M»ãÔ-H¯F9O£«Å}J ËMñû™€EŒß36n¤(í?V4t+×AÖ¹WíRjÈ*­éW§žÜãS½w‘‹õEçÇÝܵ •æÝ6Ý×Ւ󇺊å7od$êÁ²{ =G“*ž]ÌìMréj”íìõ½ÕÝ÷˜‡-†õÛÞ»I:fXqõK=`ñCºk¡(âé¸Õ]®”‹ÞV`Ï5.·²žf-«È0'Wéq³Ç^} ]k×£ÈD(Çyœ ‰u•*BÛÞ\ïoqšÍ| n÷`@ß6yñ¥4ÈÕ…Ó(ÈFä_L® ¶sî^òk°ƒšÅy'UMó›®m@ym¦5ŠNþÂúÆš¹Lb ìÇ›ÄÑW­XÎGjê<·ÖÍ´w¹Vú™EÊIòKÔmÓ;‡T[ð !ÇðÝ*lžð^£í‚ºÃx󶺛¸ ºÍÑBˆ¥l„+5ØÑÃ&šÝWB„Vê0ǨöW’ôxF-º—¶3¤4Ù÷J»â[êÕ´œÕÂ7Kegr‘–[ç|Õ¶ÐåeÛm^5÷.©íÖùŒÃÅ[ÅKNë¥xÎWÆÏ\ ðR•ÓØÙšÏTÂò¬U¿LåÍì××ÁSPS¢mm û´‰7,UÍÀ©Pa뫽¨Iç@⥧K ¬³ÚÓ,_eø91V_e k~>yÌA#x²Úß+¾ówY&⦛¿¶«Ïæ2JpÓ%EêüÏß·Mq°=ƒåλ±½W WU¢vpôôÕ˜Õ•výÀ ;£ìhÞ×€ÊõMµ§.£;§µÖΛ¿z»O¨ e.?%¦¿Š£_Ÿ” J®m,Ïilˆ@‚áž[83);­×óõ~Ë¿'äçóøÿž¾NÀô÷[¸µ ß îK§Žêâþõ¯¢êWøæÄ&ˆ–vu_ž³×\o+®Ñº47ôõzýë‡ï¾ù©å4å‚rÕŠü:Ù¼TE˜³1°Ë6óÍIPín{ø›ïJ±@‘_«Î³Û!T–LE<Ù®;”1þ£[‹¶Ž«tvZÍÇ$´”TTl!”há•:@Î2GY½¨qÍËœž£­lõèGsÜA‰Ùg%ÿZý=žùðøZ|¾.ìþ_?ËÛéðú|K¼gæ¹§ÌÔKÀŸ¤ R’g4 ¥µÚ©YÚ[]Ýg¥$žN¤;u³…¬×ÌKMŠAìÚ;O(Säï5½®¨z•Ï|L¸÷#Û/e®7'vÞ†N\3²€o¯‹ÊÃÜ*v½Æ#rvîj"B;¦N±HCÏUf}ÒG8¾`E:®™|s4‚ݪ;uœêõ^«XÞ9wÏ2¤<€¢Þ­9¥­ÜÔ¢‘Þ˾a*–Óx7Ëzº:îÖ&0ó×h9ØíPÐ0G™˜]V± ¬™“w¯ü”õ¤ç†ºðèQÌ»çuÌî–(×!Ëv¸Ù]!ÕHƒŽÝf„ɦmñ=ÝßY\1>„kÞ4Y“«Ÿ@íî ˜â: Íw§Ë Ø//©÷[Ä«´ ÇŠ[OYÊs˜éA[ÐŒîÛ¸z+5„UË­QvÊDŠ}¶ÀäÊ·wN¯í¿®úœe@w³H·’„"cÎû”îxðU™}ˆ++Šà]^YͳjJŒo¥í‘#ÖÀ€$R2å3€ 6ƒ ‰*‚¤„BBi"H©!0b‘ƒ$"Šûß$ž× ú‘õÏ—Ôt, Ã$…•eÊåñ3?@å_ê'®åu7j.ìJ¤ÐP®Ïž·Ààn>µµáóoëˆ\ø:o”Ži4Ï~2Îü_IõVKèàoH®å¢©hóòÉ8ä< ;^8¦©--ºe¼¨ÚÙÉ?½¬ºjÄ—¨P}X ‡9Dá£EàõÕáøÐ€°T†MQS™=E¬Ú=X6îý4ú˜”túŒõ9_ý*¢ÑäUÁ[×WÍ,•”Û‰¤6¡××eš™Ø8—i9žäñL9àÊ9ó,/ÐþÝ ó626ÆEŒÿX^÷!‰càôçÁ7Ëu§•ÁO­œ¨Ù¤Ù¸ôø|r ¼| N/—^R¢ƒ¦:í%Þ+s’¬¡Mˆ,p C·nÝg>Vùk tìŒÖ…¶(úÏk6ÒÙÝMø®íΗŽWçÉÚÅ^ð÷¦ ­Û[Ÿ½Ó½{§ýx“¦õ@ÄkÙ¬:ÑûžÍÊ\N]›ç›[O"UtyäÎÞÞ]úÐß,T½ì}é|0üµPSE¯’Gmö9¨=7WCrÚ1lЇ—ØÛÙÍZ›&‘Œ¢}N·®AG`Ê%§ƒ°é眮 çC~m*êçÔ½®ºQÇÖ½ÒC,aØ];°¥ã«„Ÿ¦¶˜º^G~KŠ–½ÑÅ@ø…Néݱê>«ìº¹2dËEyì?‡µ]èw›„ôã×=î_•^{<%q(P7² (ìûÎê÷:ƒ«·B“mäk ÊWØû©»v'¶CÞÏöêÿ1Í{÷ºÜgECî:ö›‹Ykï½­x¬ÔÝÌÇ“yYí/_[1i*ƒ­ÌÞI}k•ò× íÊT< ìJsð½œiû_”ïkež\°¸ËÚ´ »¥}µwœ«´RÐÚ›ÆÇ}P°Ø›Vå±z&K\÷­_P´Ø]Üíìq$)mÝû¶9Y´Áy[/I¶o@ [ 7Vrkt{'êIWOÕrÀîÕg ð·è…ƒn"á=zæ‹ €.ÞÅ€ëWc9)óÀœh¡ÑðÑÂnŠDq ]9B-q÷]pz8®èÖuÔ˾=Û©pÙY7®Ço/†ÔrÙ¢íçO^S(oœùÚ¿KŸ@xoª[ò‹!Ðê û§h7Ä,[¼/jy=`yÞf‘%À‰Õvw3;–5„¬–r²¶ø³èHÀ†ñÚÄgLWk‡ˆœÌnY»W‚+ä†É0Öæ×¼GªiÖ1 Í}Ï7ek›Sß—ºÆÕ†Õ¨3uÒ²-“»Úõîõíûpy kÇÖ D]mfÍ›)Œî€îs©–:Zn]ZÌ×ÊWÐ(žå×km®{¯MæWs§@òéÑ"òßmq\^IÍ:ƽ§9õ÷v#„ùRzãCQñÜZ«U@o·Ïmõ³)ÜX{x¬hÏv¥{]©Í4]Ò9¥Þ•>¨Ýw{âR™®‚‘§z³Äk‚†ªï4„™s/t;K!íU~á+ 3ãdÑfQ­ß!õå÷Ø @:k¦Twµžµ}í!(ÖµáÞ¢ò^W‹Ùj™²³[èž^Önа‰¹K“s•]-æžuôÖÅœ®Ëç²C,[Ç­oS =ëºt9ÄÎo·µi«p÷*è's‰VòiT«´EoØ«‡RŸÃrÍ”4]¨tìí‡1p4ì™;5:0Ñô×;3zeÍ44Q·n½Vë³­Hmï†ó¨~º©Ù1m䕨 ˜ºHhn‡ÇE4¬"ÄçÔ ÒwOkcW3`^÷4Z\êÚ³Åýï!*O;J·<°òAÎyÙ'9Þ”øª]wž¢Ãöøâ±)2“Ôˆ¡Cbì©Û[Zk¶fÄêÑd®†íå]ctž\+³sc²j>z—ÒOXb»6Ýé†Ý=bíÅÆf ÞÝéËXy"Wkˆt[ƒÏqø¹]p"eï…çGÈ0A#ÌÎ9*VqžGçC¯ÊužSj$>ß[¬Y ŠÆÍmMŒè4ƒN»™ôR¹‹¾l'ïk.¸à󨵰&yÕÊÅÛF>Í>w3?geíÁd…­Ob=>Ï4¨:Å0ío½VžÏyÁÆ®[°{ÕjŒ×bû\Î5C»U`{ñë—G‡Ùʰ¹Ðjv†˜-nôÛuÌÊ‹7Jp܈]8×R Öååa÷K6,w˜§‚i4̳0¨ èü9ücÍ3‡÷ÇŽÂj¢¦|]¼<ÕÑyÏ ’¯I¶°d¼&wŠÚ L{O¦Ó§-¶%·³&äeî”Ñô׈ nM¼¸-&AÒ»Ýj²Ò]}yѶŸìÌ¥[7=»X§N>—çnÒ­'š²O‡„k­'²'§¨¹9iؤ6„½yܯEMêÄ@Ã`u&ñCí'sµ8qb0'S£ð%êU¼4»—3%“zéik\ Ü>QÇ<;å¡sy*îé óIú¹)#³7¬OrÛ}æì`¾’¹î^ÃQ¬/I½»Û·¾ò l—ñÎ 6!Ü<–m2Däzvgiš‹­¤¯{3K8%c2I‡Ý!€x›3Ú²¯ÒÁpé´ýX«¦:&úºÞ–Rb³O?#<|¨ÐÝí½LÕÚ6…o(oÝh[ؤ¬K¨nÞ\U‹‡jÈ–ÁBÅ ÆŽßT&X“¦\ãŒçÝKÃÏß`Ïdš|¥iöllè=ïZ‰ÏWn"ù%:Àc,QÜ) ϳ6[Ðc3Pîì°íÙQµÞ;§Âj«­Ÿ!7›’³%>|1òÜæ/g³Û²‘•/ªlób=¬é¹„èç žŠ›5e·“we»ì<êë,ªÃL*Ë`_‡72‰Ò»žÝЫnW»õjãîë*Ö&^cžîá£ë÷^½¾Îêvì5Ì´nŒ¨¾ÛQoÀ·%-ÔcYˆÁ›4'Ä¡™k©®Ævfx¸bܹš«À]>ƒÞ|’õð"Ý6ûxü‡L÷xùÕ§Šîó‚4 Æí_¶g‰T©M®œ6¯žÓ ⻦À›º*mu­–L¶ùÛ£{MKN<Þä¶ÄzJSž é=jàZ¤ë[ ÅÚÚȰäZ³‹Î¶öü|-×"ènÄÒ2‘~ỪÁ^^~àfŽÛ •zç¡­Ýrs³}¼úÛ¿ÅȮٷÏ:znlù”{µ:¹b*ßîYŸ†Qyøo§®X©~e Önè‹¡Li]ºÛñ®}’ûwÎú¦*Œ^ã];¥õåõTà‹ÊÄÜŠÊ×ñ”ÛÆ ­¤¹áì"ɧ–ÚΫ½¶¸F9Ñxz+}•FF”æ–Ð{d ²9.×Ûpü•Mê{ÂÞO´|x>¶ôEÝ- ¨óˆÖo:Ó·ãj´=áÐç¤Ã\¸4K—O I±z}FnZTê'ÎeÛá–²všÀõæªyL’2‰Ëmª:|û—£9]±S£Çlu¾Û•ž“o2uë<ÄN®í»ÖZ„7>Q©»Õ>ãÁZûï•ÒÛ·™•JÎóŠPIÖ&®Ì´LªÃÇfqÎ]J{Sœ¼ö½¯}L. Ý‰·Në"—R&&d§+Ù]qaLÝ̧Xz…ºR¸´¶Á®×³SÝ&†lŽ—Wbû`«~«©ÕÚsÂSÝ.Þ{~N ÝlC—a,¥E—íÄÅð=HJ¶ÔÈýÝéhnËMëVàRÜàö£™C)ù?]3‚“Û¬Ýʳ#ðËê±Î^xå·Â›õ>¡k2 Ø!;6ûœ¾¹¨VÏtÊï1{ï´š(ûpY9p<ÐNi¯SÌ1k®µÔÌ+ Ó»o¹ï\ìUƻآâ[À*aöct¨zýÜ C¹æz€ÆÒ^îØEBµ£tʺžœèØÜh­¥Y•™:Þçجa¡(W$–“C!Úž¾½ÂÇ<]c›lÇÊ`ÆË>Íï[g¸zKN˜•&[Å®åK”iÈ£½Æ¼®!›Õ} ­Â#›ï[àÝw¥öëñ§•³8+àûr›e)ßQÙNœ¬.ˆ!Ï·O´±¥Ñ×,œÁ%‘ ­{³æygrÎ{lï˜Ã'rœ,ž©žîÕYyl¹i.Ûµ’SvØ—ØÔìÞƒŽí@gtŒi'#mŽfÕõN¢…AÚ霷MM/·co„¦²¯E©C´›¬5év}¦)â|-ÜÞå9çÛݵ ÉÛ¨hÝ)„O†u`5S;jA¶ã–ÉÑʃ‚Èç†u õo{2ûÝ9®5íæ_}–([x‘;\n§&[ItWq‰ahÕÜ1ÔmWgißqöÌ«÷m቗G¨Ñ[2É ¸I£«&œRô‚î-Õk޶÷F晬gxlô°=¾¨…0CT‡)o«lîeÅ…[‘Žgy(g›ëgµW©nîO1ò»¤Ü]8¬£Ô¶òî[Öù½Z´1šÝ^¸ç<&vËVxònÙÇ(ãîž½kg°…ÞÏC/sYbR¨Ô&Eoó«øÿ j ÷ýž—d;B"þX3SÍPƒŸÎ}aŽËùŠà‹UÒˆG¨|V÷n5•ῦâF:ÛRÔŒêy^2¬—5¤¾=íwB¬)D ¼±+߬Óê½ÀÚµ ÊÕÚ»VîÛ!Ýa/‰94êJ‹²nEMna*lÛÆ©+WfW­/zrº V¯_®¡¯W¢Ec­‰VðD”©DôÐÆXô-öJ¬òÏ5ëP½õz/Óû+äàTü=²Ï‚h÷<ùõõc£ÚŒTû«Í©:¬«¦’O×ÅÓŸ¯¯9Òè‡P¿‚À¶EX³Fá/*úJ™vuN‘¶¬&ÃùJvѶàíqÜh¾fve²Ðo²kÙÛgo `’éŽÝv¡t¸û»°.u.{+'{¯7c¼MJb#;×0né¿U²„^1x&Þ!s(‹ÎÜP¬2-÷$=é}tö3o0ŸÉ £Üq¤l ã{/x€g§€×P´­’oi›ñòߦ÷Eî¼óCŽ&4Ö×k\s8h¬áªÝ,}%nqÖ¶†¥ ûÜåììF¸Ìž¥çËn>´öѯF¶–÷—FÆnøúµ ¶ºS»ÒåGœ²L!*ùe×g”wä-˜««HSÓ’VÇíØæÌ×B—Ly¡Î]Å&á–ñ»líGðß7޳ â S¤+¼uÆeÛG²Þã‰ç5&œyÑ¡NÞ¿¸¹j³Hå«")õ±r€éög ŠaÜÏ™žÚzýÏ`±G/¡;Þs ©’n±ƒy¦óíœIYzÚÈœW`ïñáy3Ÿ°4êÛ¯SFèU•˜òº1‰¾!EÐLñ=³Øþ‚#pwIfq¬¦5+®°:ðÚ7iޱ®òØÐPø1Yk³ºÝº¶ßåîÜÂC‰:iúzõFÙ£`Ö>y¹gMf½=OÅûÂ…ô^^êrºain=¡SQ»íœ _I‰”ýî8æ[¾ñxåœr±L hL½‰›uyÂÞãÔk¾äñz{ÜôÌ D™aÁ›wå“*Ý™iy¯E=uz½fäóÔ¡ìöå-ôq.Gd9èÒN5J[H±[îWÛÖï{Pbòy]Ö¥¤eˆïj:3¶VfëáCS¼ß/hmY!{]å;mBæªLÔ%X©ÜÙÛ£LªyÔ§uêï(ÄÅʈ33xa ‡‡«gjÝ‹kÞ;нß?¸ïHêÆ{Ûjå(é–qaY‰ÁîáסÁsºá¤´µ%æÑ¥¾Õ Ì퓇Ú]æe¡ˆ›­*)uxú‡w\wŽºšÅÐM5ÇìT’ܨ’¼©õàÑ&¡@ºKbëBÍ» Áw1¼½ûSû﫞<ŸgŠ÷¥Õ<¼ËÕI‘ =…WnXwÁáªàV¸:wÍ+`ÎÑ 5sWXV×%©ë¯ê÷ ÷`îÛðØvåí¡ÄTd& û ‡¨_g¿mòˆU4¡8ô‰5ƒAWðxרå'\ÆÉ—}…¼˜ ÓÇ+|8)ÜmuM1Ž7L+Ò,Bœx¶zA¹Ý «£C¡ì>·mŒ½EâYJ£ån;j¸RÓbñ4Vu€å-ËÙr¤~8¸Ì½ ¨ŽëÖ y¿o8]Çœî«ÃÓµÑäFwoŠtÍ]~3ÜîÐГ&›r‡•¾wãhå=êïá/ ÑQ\Oë¤.Çog>E;o€wŒVÍggÞ5|ãIl¯e%~á¯Fž&¿1®ê{Ï^;ÜÉ]§=ªÃí °"­ÚïnúqÔêÂ&ã6üïFRV²¬M×¾…ÓjM\CDÁtôÒyet^•̇ ¯uñqÐ/Áê&ÝÏ €°õávÕ; ì/‚¿œ`öK†Ö–rA×èÕ5t÷ÇÎÉoÕ§|`ƒ”~” ßuà%1oxvñÀPвs´ù]7ºpÝí§Co%°ð*\yvM Ù¶k DâÛÔÈ™’9|hÒþ@­Âi1WjÍv°ü©÷¶lÑÇhW¼fEk:=«B¨ma¼JnE+”«Xøå)g:âëKᆵ³/õïyÜ£~5Nó1„Ÿœm8ÏîçLõÊçmöîadÔÝ[eËÈ•ýö ÆS©IQÜé½²UˆlPµ×É^1 -eC´*lÚ.ÕÇ£H«îF§p? uš0Ö,„/–ZËíê/m—ó ¯4wŽÊKB½&ÍïY=/\.+{ +ºcâE,Â7°uè›…1‡Œ¦C´ŽŠÌÀp’­,œ„Șºs0^F¶e'%:ݧ#¨pX†™ÀÒ¤]ÙíÕw€ÑTñ.Á ¬$ w Ö $bn·”Ö­¬b”soa½ŠÄ­ ::æ¸)Øt)¬/´iK&VËý|ús‹,2æã²K×c-µ|0°>eUØxAS”Ù°/gÂDÒ¾§C,lm0T¨÷u9Ý@aºÂ9]“­Ñ½• æ²—¹OVÝ S^ÆFëhPHÊI@É7X †Â¡  C’âJËy­ºIm\†´¦ÎX”Ížw¹Ùæú¯k4¼¡‰Á¿sõ×{M*7öõ–ùQ†J,ã©:aAdV¦Žáå­µ´¾šÍÊÇx1Ì_1«OuÌG)Œ££ŠNÓ¾ÁËsk¥ ²°·*ºX)åZDøÙ XXM­¯Yदôñ@ÑÎX6’ÅyÀÔœ%!êiZ:f¡£yÝtmQ¡lô½ÒµmŽ­»v„ÔÖçW'"­“9\ýì÷»ÚdèŸ LÖÈ®ŽÇ„šÏV¦ÍèãYc›Ùs3²nöSõæøh ‡êa]L¹î MƒAw`à€ZຟTêë˜y"gVcˆÐHZS6®È‚‘9¸3Åh_ØD‘¦jCï_¸Õ¤70D©n^àj'gt¨ÝnÌ|žsmŽÙ+ŽÐ0ÝCµ0hV×Êb¾r_q÷³ÁÑÜñå[×íÊXö€×QÍžÖ9QÑjÉØ+±NÂõŠ ÌšâAìÊVÁÜÆd†ÎfíÌup$qjjÅ{¹º‡žUòäüÆg 7$9ÙÏeØì=‡J2­í»Ž‚{Á ºŸŒk‡f4œ¹kÕÇ÷œà;« çí’±áOÜrjKЊ®-¼é»½ºCw»åb±o=ŠÒ×òÜÐsŒ-.)#c¨óT±)ú¯¤d5$dwhm¸y½U礡³¦jIÀèá« A•yÐ:ã½ ¾zUøï;4 ÁFtÁçeMýÕ:vˆ+ŽÝ`òA]É…?T+ºC’z _h>µQÔCžã|ªeo¯nhív´lº°B÷Pl±CnX– æýÆAVŠ’åÑÚ-Äg=\éW[½§geKò€¹u¶¤Ò ÔÖ_{¦Œ^>¦V¬ÜKVYÆSâ)]Ù®¦‹ç4"·)æ*$P{Žf°né¼¢PŒeëuÛjÊÃeÆÙ[ˆß†0'é‡/7¹[1sKG&ÍÔùV%Š·©`ÚÖa$>PŽ…Ümí¹ÛY¹”vk‚÷$¹‰rœ£mR»iÚÚ›¶dÃwŽiåLÙX+!±ÁåÜ…š‚î÷wëêB“Á¢œu{o€Y5:ïƒÇšrÜ:' Ë »‹Êº=!»[ÈÇÁ‹·‡bE‘–èQ*ž>¨Ë©ÎøtÕ¹3gKÇÎønËç¶–1œWîòïK±ÂúÙÓÔŸœœYÒ­„ƒ7[ñ«”¶”TÀ½pÓ‡zbh‡±…ÌҺȩ½ÕnVZ?¼Â<ìžÙ´pHh›è­³ïjï…GN^#êðŒË—ëž1á,Â%eJ å€Âóˆ¹kRÛCÑÜ!ø€æX}¼ºò:zãvLÀuͳvèÞÉÖ+ ¾vWÊJj£íÇ®h÷¸—(a½( ]™k¯ ³{.?ð¯íûɳÏáêÌ7³vë³³yñåC´ÀÂùåP­šœ$*‡+ÍÎm·k³4VÕ÷UjBÖlj<ÉÔÄv \ÞxOs^„Úoã×…mw—1Z0Žö¶¯Îs¥ íã¡×hÛuËånzÌ®&”¡VºëTGÙ˜¯ÑÎòhíé-,xß»E7ºâÚö§¹eøN°ŒW ®¥ªú‘X§.`Žïkê›ÃR‘÷›"šÒŽfX—¹w°2¥îŒÚ[âH×S§Î£Bñz6ûÀ…®,‘g-v+®6½à’Ú«è¡EQ¿CÑ¡;^:;tëÞÄ«à©Ýß§ ®”cXê޾;ÕåŸaÕ‡éuëѯÃÖöúm§«ÜÔ} Å]Ø¡}]z‡[ËF^ê93k,§Ì¾a½{,öe_T…vr“…¾i&þËÊŠ'NUòèDwVrd{@웄¼×¥*ÅZksšsW厔³‰‘÷[ƒ/«úŸØ}ùú¹OAX%ÝÛ*·aiQw,L3óq‡Õ©ä9MûW Þ \GÔW^}-ƒÈ¯2Ç¥ÑÛ ®ïÕŠèvé²êß´Ž­n,F»ˆÄ´áBF¢<óz\­¿l¥D›Sœp3•hÓÚðÝð1^R±¨ÑUr)’º&Ü<]Cj³Fb›ec­­uï>¢:ùâ“«¼H¸b±»"uC¾U溇õ©ˆwŠ8è:f(V‡+PÎ!MÑ´¶Ò×õõ¾íçׯ°g³·5¼öùÚÄÈ¡a{㬉#=·Sø~ K?¿~uùÝoœ&öâÝÂCI›­‡“9.k­—5«JºEs™ww uŒ½^GéÄÅᬩº¸[¸Ò_ú@¸sDzÏu÷>(±YôÔ|;fÕw„〛*6”†ræ+3&¼ÚÑo.Áfž°Tͽ§; ®M 3¾ÌZkgNÎèÜêמV3V\Ö£ó=澬—˜Ffò]apÍm‘(Tù$ÔÞ†m¤Rغ}u ³¸Z+<í±À{‚º×\ D`„ǰÒS.À™Km7Õ°¥ö)8Ýqc!º‡o/\,‘zk¨²W0qкšj$çAÏbä3¤ÉC\:jÀPå´µuÃ]‰ÖM‰âÞ“F l—Þ5êßQн֮¾ó#Š:ï™+,3¶Ý§“»ÝL\§Ï,±\R·½Iöœ[ï(£=Á¿ ËúehE¡ó¢&]zïܨ"8@+b#‰Ê'Òx!ÓÙ¼2š/+…»c×ëï Á½ôÏã®ÚcÖõï>š½6»3·%·•u\äæ÷.ƒxþ¾¬ç]eë„LÂEBʘ+…‡Lé08xVFŠUÝÅeéêÓ]r-£bà§ŒˆåN ÍdO»­¸FlìÁV´tù°ŠïÌ…s³}øLៀ<¨ÓoóUgè°þ"jgÅÀ§çÐü*©÷?nQf»ná3 ó‚öÞXÄ7$'d¸ v‚nÁr•x=~äÎà¯ÊïÍF¨• Æ»æfòºs]i¹7vÇ+$t˜=‰ >­¾œÍŒÝGÒ°Ù !1ãÖ|9¶\âýˆæ#œ4mç…/C.LÀÖÇÙ;a$ ÀöK.)«y³Õ›]Ì<„;RÓ7ÁÎ"cy8œ±9YxK6Á–‡Ù¥®2÷j+{Ô‡>¾\=ÂIyz.°],O9æPAwÛiW(Y_^»tq¾˜Š»ciíË£DeÒ"S÷'öúýÅ”ó¿Wo u”ðÄ«…=- «+µ¬„Üç®s”hÖ:äîÓ‘•í:ëÝ;•æÃã›Õ’%ᆠ6#ÛÚ!Q¤Îõ²}MZlâÊßTåm„öŠÔñ6ô/ƒY—…òÊžYÏÜì¿qã¾Vz*´˜™‘§jñ›rš1(|n^ß)C¨ÑÙö`ä`ypsæqœƒŠ}Ñ…Ëmê»ÃÙ–»Œtæ×U¦;MÌY¿?^p5¶å#fü¶L3ço©`M ²CÐ`Våm£¹»÷sïzK©j#KÀ͘~Úçç^QVfÒ¨œ¿V)ì)æœïÝ‚wË[t@ÓzìÛ—=è)Æ”ÕÕîCÙhõürh!íµêf•;Tµ›QçR•‹S¼©X44n65ÑL.„—µc¦ãÖðÔ_›S>AÞCžÝ3fÛh¥”ž ‘Eu¾"ö^ÓÕ}ñ×—H¹–;bìpc«ä^©Re«ß»;uÓ×öÞá’UyŠÄdUãbŽÍù$—Z¢[a©qw#¼f<{ƒß}uÂS®¾n«žg êY8ßÆŽ AçQ®ÙŽš4Í|“t†Öß1xzÙ5m»½œB¢?{vuKK|ݪ^¨×Vú%í囸'½Ó/f-¢k¥ø^÷Ý˨º^§ŒOÞ|ZÎõuÜ‹Ú3¢ Äos)5µÃ(vÓkÖûÊ€õyùîaõfŠÝÒÓB”öU‘Q™Vb{ë­N»8tì ù•#Sc—Â\¬“¼‚÷[AÎg-Óo6Jl­ Âuz³Âîñ¿`º~«5d£é&ê6eefº¹"g¯uL:šDó£u3îÓÅmtꈷßSUZجj:Ǿâ<”re°üàëä2e‡—|f¼ò€ëíE Å+®ÞíYA¾Œ©:a|샰uý³‹Ñ˜ë=~]¼ ¿?ŒR­Ýu4Å àf%÷vÝ·}4ÔQ§•º‡"ÃÕŠÈjB÷%{½ ºé!áäd^ó¬Ùº%¾Hiý@·xù‰zé/·©öŒ‰·¸\÷:ƒrh}y³+e rìg‡R´-PE*o¹ÝÔ+°ž¼zž^˜åå¯bÙi«ì >¾à…Haxºd¾žÝÆÂ=zM­ÜEmG½ž1¼Î¨â¾À±ò]3Ò[Z(Þ"q‹Öí÷z„ób.í×|–xŽ]¸p4O@»W"[Æ‘ìnÓNCz’î|ñó¸r,råHë¶¼ðõ­óïS‹Û½F¯mðâj"ò¯†­ º,³7,€™»èíÒ°ƒ«'³V^ÒÒ+°ª™-2ál÷Âp½-ílfÐv¯³ Z܃”ôT´,ˆ5)W›qá¹ÁæºìpÉ=»<µ%Bø*RÇŸË“žéÀ15ŸÕùŽã»ì3º·áö‰âE¯{Bøõ3%B^Þ[W Û†00½&†è³„rØË‡+Ä•K^êT†_ÅneµN¼wZ£Â^JuÙ¦áã#U!sªvHôŽ±Þ¼¡¢û4áó|{U''w1£'=»A}·$¶+«vå%/«L’ ’›«Þ–=œ¡^¾÷7ŸkÕD`žeø|îŸ{µªÏb¯°XÎ-SçJdIA[qËäÇ.Rë2È]öerûa’H!y™«r³³Xã áb uZreó Ý6BA 7†’¾Uo¢˜W=º‘ -²ÝÔ±^mA·àÒáx¥á½ßwæ·T4Üøò̶ñÙ«']Î…<2á¦b}½¨%åÖÒYÝÚhj*é5ÜeW4®‹N_W.¦ŒM³Ç(;j®¼±Gb÷¯Ê­XåšßÔúA:DËwµÀHsabŸÛ³¹Víë—º/w’®Öµž–Ñ:ŠÆu„7vÏ'JƒÊ¹¦:¾(¢Æ´iÔ¡—C$Áؼ™~÷XÜài%;,ëRm.ÀãWdz0œ¡¬OLÙÏiá Òšöæ1œ„|ÜIqÜèöâß² Þ=/L®Mj°–¾¥RÎØ BT¹˜œ¹4ܺ}`!¢WO#Æ@p‰p×àªß{]à{×r€,Ϊº×@z>:źaŠ7{Vgs%º]Ø f_RntϬ¹ˆæ»L›=X˜Õ"èt+ÊÛaZ«°0”eJ+¶ÊA±s|г!vs®±([ÕÁmZÓ™«¸vfóî•·ÖUÒà|æN¬pжD°s¤^Zß^îã“;±&ïÚ×%ƒ§Ø¯NpñéEëÛWÜÖ.Ð÷¯JÏ]´ãO›t}=½ÐásI»‚çbº·K'èåm‡•bfZ,øv—½å‹á»‡ÀyØ~ŒlðÚV‡R¥[Äç[”&§W­vÜ—úäsyšêÏàe3$4:~fSvuv÷ ëB¶Â™ò¼°î‡&g=¼j9Dat€.fý«sfø÷¼»R«×y]$µÔK³wîuäq¤Ó‰œÚÊÌÓ$úåêtRj¼´W;}¦ìtI—Rr¬TûD~>ôð~/´íåúvÙ+-AÂsœãH{™»ËgŠHÒœ6ÑÊ p¬ç†1´‡¾ó8&=‚ReI˜&þ¥µ4¥Üu•k$Ø¡Àl:Æèûž~+ÇÞêòë…T½ËÜÃJ„8½'u£ÀMû«–ˆŠ<²ØwGì"èÕ+Øä®ºâ׈œÖín_“|rýt=9HRî}bÎÒÃãÞØhJHõX¼MmXjd¤Ûž2ú…§C7«4bZ–3LnšÊÑÇjãSVwŠòRZäÛ]Y\ù­Šóy+Ý5Š$Àí·nm‚Ä=»áïuû`/ž÷š¾åÅ#Y†A4™¾–tòæáíªàñk×›ºŠ¶(IÔy© o²zÉÑ5á®ÇrPÓØ7.®ÄcÎðÕ£¥ûuïštz 7äTÁB±'ayƒž¹S»là’eõCÆöÜ‚ÂzÖ+*ò(N ¦þï>\/¦.vš4‹‹Ê³"쉾õ¥v¡xçb¸Â«}’»5KqŽV'cT³²×i %ÚÆ"ù :N €íŽÚZ4ú8—Á^ç2ô`/6)55ÛÜò–Ô[¶Ü}h§›öUúJð²×Úyyç[QÍ–†‹øªÇ¡a‚ðÌO}¦ë†àвæâè¹ã¨ÅFlºöC¡³@Ñå1GÌ ¨¸õÃ=xÆÔн]]ƒ|PþÂëºóõm§DùLÑ=]}Jw}ÁE]Ó´S5j p:ÖRºjj›£ªòÅ÷CàwauÖöŸ˜Ê}·ƒ²…õtwRV²(À7cŽY¬ èŘÐr´~½ÁWo£ÍV QªkÂa» -/S8Ó(ÛË‹6hÕ­v÷uGªÐ²»'4¸Ýå¼¶ § [ØúFßιWnãvûS4¶®ö¹axmà+°¥C;dTÙ{ ‰`ø¶îø^ðËÈèvösöô®;H›j–ÊÅ”÷2Ý…Ó.N¥{y\²»}ºª`ô¢˜Ó<ijÝFè‚4ÑÚ9D*ÙS‡4•ÙÌ,¡˜·Mej¨xô€3­šOXîÏcÙX Ò¹ÓfYÜ]d.{®‰Å¦+&åB­bçqyñÓkÄFyÖh-WU¬Í, Yv:ûœ…Xy£2óëJ஄¤ðªìã¼+·³äßÇÂpôzÇ7i-zɃ\vgô1×…[ô(øgGÀŽË”;´Ô4öïÝ¡õE ̳9bP½ôÎonO%×jæ–“Í©½Ø½½+÷½ƒ¤ê ¹»¾¾.v4/dBOlÅ1kÛ™ËÜŧ4!ieª¸Í3@ªzbÇ"j\÷wtƒ¹îë­¾õ™íøï»›J8;›9~;Îw4RT@“@ˆÝŒWm¾Ê,îb“"ít-½É1ê£:d’†JUg;kMë[ttŠ®µŸ æL~‘]½¡—gFŒXgÁ~êÙÝÞO§æ%t²þÜ©û˜Ëç…]öN˜Î:|&Ð[stŽ·Ó \h}oÔ&.Ø”×xÎç×Ê–Hjñë§.?*vºv 1£!¼g… ^.]-†K“lu’«ÝìÔ©‹ „vÐ5·aäÖèé5‹ÛöÇŒa;vv1K6±à›ËÕ²´ÖÌhŠ\‘2´ï¶õË÷ˆÅ&éWÂpèÍ‹Èɦ²KÛȽŒœc«x£}B„1žÉ‚ð”tqv÷Ådu°›Zå3+n?3tâo—)wJïÑÀÐæÇb½ëô8¸©u¡È+†°àæ­ ¹IÒµKb´Àk^Äó=Ñǯ»íîz§R %#è¢ßÀc.W·³ÏÛCÄ]w'é6—'½Î·ŠËÓ»+Gñ~ž†²}KºxŸ™~$|ŽóÈgà E°f¸†u¨žÙÊg1Qc®ØæÖå¿ß-:°<¿ŸVÈ¥ÂU#à¯yMÊš´T@t©x®¼ü•æwŸ¯áÀat* ”m¥šräöâ¸9ZVञJ½ìÝÆxZ}w½.‚µP]rÓ“’Õ1+,X¢E ¶f]sØ O5N\…#CPr*’û–ÉpTì³n·YÓÛ™»|µá«¼µD‰i¥ ¨;¢ùhs»cq€òý¥¬[X÷oºŒ=²û5§X}Þ»í¯LÙÞCŽ÷˜ŽNÙã#ô9Å2˜„Ñ’ûªæ.Ó¬μªÓó¯~%ÔõmË»ÙíèUä2·iPºîâí‘ÍŠIáñ¬¶N߸ÃÕ`z¯fZ°IðÝyžC•u4Ç ^,Fp_Oza9ì)_=µ˜õÍììA‘av$¼‰r"#·u«ž'B;IƒòõÄÐuJ—£«#¹½M"¶¯³íxÀ3Ç)zHO&-س-yÓ¬çY}sÞÖ¹¡AåxQ­öc ¢vÕMÅÒjbV¾ÅSh$)Ú‚¦µ´(L-{É‚ú–@¯:®|fûå–â¦ëR|ò Ë#•XÜRŽ´Ž»Vüµ¯ˆì:6¥^±™&eÛ§{ÜUm½gu KÛ,PhfùùyÐÊë›Ä(3 º3Æ<´³RÃi[LnéV¶ ˆaˆVIêy]•ËØâ½{9,>—¼(U–…3f¶ï[ÒÆÚÍzÄé!WWßKI³—Z]Ä®º¥×< ‚÷33¶»»(6Xdz#וÙλߖ@ á/³ÏÕû%t[{Z*·lû;%ö¼"ĉn¶¬¶x:ض=˜7)gàB¸áâÑ/ÚôæõåØ`»ˆÕ¤q¹c^ö01¡{q<»Ö¶·»˜n§Ü¬ÎŠw…~Û.ñvqWV–×½éÊkÑ^37²àõ™mR=®ÙuÔö¬›Ü°gQä ìNìõ_²¤Û›u˜»Ýž )Pg¾ËÌ£P’:&І𡕒V,t ÌŒ,p› i`¬ÅÙôMös0Òë^¼ïkõJÓHP° ž™­‚ï ¿@º^>î®]!€àºfQ΀†5ÂéÜ${`Lõ*Ûj¶Ë†é_e÷ºAÝ™Õ2/yŽïѹ×CÃ×UÚ¥Úh}¦íL‹™iÀ†tÕÃ>ÇcÃzZӘ쌀øÌ q¦Â}ïh,Þd=W$PŠ¢ð}O@ ÷3Ï&AIgëx¼Ùž¼="‚_m^K`Ë¥^§-/A8:ò® ëÙ+7Å¢®#èznðùn>(ùÈ-<ãì˜=GÝ¥‹Žb©ãF‹¬W»}CÜÚo>ÝÍÒ>y/5±µìµàwy«P½óNî´suÄ£§yÃ|ü|¦”s^¿qá.%ÁÆ\¸ÏLz[§`e8}††'‰É|«kU]Ó:+f©ùRžèÀæÝîpB"†\~NfÕ†4ößׯxйÀ'|”Uˆñ¸k²V¹}WÜö´…Ék¼ÙÅÓ\}7½ú?•wê ÖêyÅ‹¿ÁfE·Ý•-üÉ”÷9 å›Ý¶âÓùá•îé~f ´üÖŽÑYk¥!Éwešåì÷^Ò¤ˆ[ïKðu—Ñ~©y‰ž^ÛèÑÖ„§r<ã~¼ÙH‹iì•”q@ºU×_)H¾•éæ>9Šò=¹u—éLÁ &rÛhÔ²ê?Uuú-Ë̵¢Ÿê¯Áô¾±½iŸÇ¶¤M\c£ýy™Š²¼XµSĪƪx©P@˜©zêÚ)Ф®Ÿv–À¶ÚÞ{@rùžé¢PYޏ~žãB¥bjÍàÙd?»,û¹,öáֺ̄]SfeiÞ´Î{|snº‹;œáU‡5!S{5®¶àK«,­’²’™2V„&â•*Ô‚Û¥¨tç2ì|à1wÝWF–xÕuò“),QäÙ9Õ(pIÉf…¡·ÔuÉ`d­Üô­÷¸2z¢°ñ ö08NǸ]0º’v‰V‹¢5˜V2íÍ”·­W%.늫"ù=áí÷U¡ã*ŒF3(•¤›ÌÜñ«n/£­ŠöË´WPQad¬îË r%pÞÇ– øoYjˆîò•ÂnqW7‘\õWÔ_9É îÝæÓÍ¿b>]Bášt‹õÏA÷<½fju_°b™Ù²M‰ùÇà—¤ N/AÄESñEE[¶cc5°Û[gKZX‰m»­ÚÌBrè*ðÎLõ7W*à$¥m=*;mªOŠ•7¾âE÷^L¥œ†c›˜Bî`ÐßžÚ§‹i ;žo7áÝÖEz—»a¥ÑÞ-µÕ×Ðr¥Èô§RíL£šl‹÷+%Ù¹×LÔ hYf˜‘.5Ý/8?§Õý‡ "]#ß“»?‚ÿ-Åø¹•5M{QÿGƒÕî*UiæZ¸¯Ïaçì¼›ÛŽ¹Dl•JvL•Á¼½w·W­w4zvñŸ.˜·¯Ÿ=Ãd%*õZouxb®'Ävlø!J7…¤*îÝ1W ­÷®RïrÊRzQ ÕN­ÏX±. ” ¿¹æ«\R{4«/iÖ“ÄKN¹WLì:â0pXCyAÙ» Ír¢°ßÅõoqÜC±)³/®¸Ç+8¾ÐG…ãÕÕ=Wt stLõø7)kŠhóg«^ûMë9$V3 ·¸*Ï Ñaµw;Þ[— {]—Ã×™àuØR{qÐ[éu¢Eu,}|ÝÔ^ƒÂƒáÚß—.È¡^g°4𱯦s_fÓ5š1æsŽLIÒ;@j£Ù”w&BÕžåÏ#­nÙ£Ïo»FÆ]{™7N.Þ–Y­{Þòùt #5¥Äîë\@YF_ÑæÇ·°ŒîCŠÂ8œ÷HÜ`Ŷ¨¤EÉp_¯t!ÝŽ¯Ë¶ÂYë‹‚'Dy¿MS>š1¢æö¶e¯xnRËßîƒkŠ«ƒéWm£ä7–k×W¼=,%ìîÈçNç³9š¹µ´i«‹ˆÐ½®AÌÛÛÇO¹â­SÞFâ»´YGv­Ôªò\Ý.ê·]7ÙšñÙ¸ëÒµ³ØûÔA¥ÚËå{ÝJÝO7DŒäô¯{‡j{Íž¯Nš—‰ð}[j0ùw\Õ•-®Q‘My[­‹ò³m¿ ‰fRµøXÔ¶_U7F'sÑôj~ôM¯Xµæ¯œÕbzÌ ˜ì¬toR€]íæpu-ÛWh™KV”ó{š•s 8²ó•© Q@HêìТsŠ(Jš:uI|ˆ®í)XîNÛ¼ÇÚCܛևQݺrÓ̊üê›w"Çn ¾·Uκ¤äÛß*aŒ°xÝú ½ZÈ<: f24hu\¡ìß;÷\½Â}A)²9oUÑcr•yq«ÞÓÜÃiû1Œù—X7w´zŸ»-iÎÅ÷nYÀ$xI%Y=ìÀ«Øû¹ʵ´¸‘Q*â7vk?Ôë´†½ÊîÑèþöŠUá}Æ›¥AD,Í¿Àí7ësÛž|(§S_%^ðãÎÍv»ë½f”Œne!£ qÙ=F>“L6,,VuS¸87¬¥n¦ Ú³±´.v;Ø5 Þ±tWE/œ­ËËjÊï,h÷rëqʾÀÙÕ¼jƒ%’Õážî—=ïs}¡^œW0¬ó›1VÌW°µ·àRˆÝ{n¯¨š}ä`wÔ«‡P¡qí¥—f²-¤!6s¥À7 åâL½ 3 Ä‡'¹é]›‡òU[⦓päÎôf!­ÌO5K´®Æîâî ‘Ë¤c CÇš¦UÜF-§—޲Ÿ¼çi«ó¼¾Â¹~ôXW©~G÷ö1û»SN[½-ýÞxöµÔu® ®˜(€Ý=à-}Ñ¡”m©µ´ÁXYFm”Œr¶–ÐM¡¤îFý!^´¶ÏX•¥ÓÖ‹è.IÔh‚7/ŸÝ\ó¶`5kð›Á#W³«¾…ÑÍÉܹµÈ¾»µµ–…YDƒ’š¾RPÍ‘:²6]šmóø_TÕô5®PWн:ñXÃØ}-U‹±‰ r×X¨ÚE÷Bò€j“ ~3ÕÄQ8ØãpŒâŽÑ À [t¼Æê½ñž$· kÌb·í»,éEjdÐÛbéû){ÕœÄÍÉ‚òóX^½åíÇ:ûCC€™Ž-ŠçZÕd6 9u;Â{Ò±Ko,»¼ß½ÁÚ$7؉͵^¾àhIã'Rò€¼• ¿bû¯g õ¢‹my'Žäö-^õ¿?4nñ´Ðç·½Máï]Tó9½íµšŠ›V5”ºð̼Ƕ™Õ[gH"Ç)Šw0zQ>—cU>­>õŠwÔÒÛ*BËSEo+Ÿv«›¦'ÜC½‰s÷8=~Õm{´Ìã¤ÌnîÐF»¬È”öŒè/£­Uni̇wYÑ&ò¡|à®Qw²ø¶ðÐ}rØ\­Kz®¯ÔB;ÑÚ%8¹7h,År€mÑ‚–5÷-l­Í1aX=s{%f¯Ck6‚,ol¨gÖ]ØÊêÊA¾#XË}ižrq„ Ê0v9Vø3ݮ͙å»2 ¿mÚ+¨ÛŒÏ$/×%©Ù·å㪞ܻõ¼»9Ý[ëÞOio²žmѤì®ÚÌub“ÊVŽ×ɾg‘ù‘ƒ†õq*{çvgB»Dt¬MôÏW¦odx; µ°î€Õ¦ågë²ðbòÎÑ+¢²a6ú/h£‚ò¹1‡žIØE›Î6{–üØ„«•ŽøƒÕÈÈT›Œ³ cí›(»ë†¹ýƒ­ç±i|¨íG° Iºy•ŸuéCY-<¥vRË·Ô–JÜQ+¡ëÔæ±æ+·6¹1ow•ä+v»®t¬qEµÛQ S°Ÿ/1ÀuÓ/Ý—z³ÛÌXxž+!qnú ].î¸Ú[L”\¡hï ¼²˜–Ø’ƒ¤Ëk>kWJíÑFÏO¯EÙá.8Å>¼[—#¡^ o/,÷V}(À) 7Ú1jÁ`ƒë¯³bu$ø˜óu_h;x®™íy.ÞªØ#¨¯¯q!±¬õãÀìï Š¢o­4G޽oˆ×µ^1-ñÑ}€û²¶ÇR§Q½ÜXÚ÷²IPo ©·Yu†l¿=)*ÎÍÞ´èN%-6c ÊÇ„ŠjšÃVÎÙsÆçqC&Þ£´n‚Êð›*ûÕxÛë{)›çPccvLq½Ê7 ^~·HǦ1OB |.õ#êY“›t»^ÛÙr…Íhݶ¸Íͬ¹H6äi¶k5ã70¬« .ê\ylõ’êÂl{†VfVù`Ìùáƒyyâq-v~›»Š¦i¸¾Òÿˆ—²ì^êÖ­M3K_ßÛ_¯ p¨)›R2£žèv¹£,qÕ˕݀ë8ôÖw¯ ¼}1ü*è#‹#Ùe í"µ SOIEªÁ烴žð]Kî}´vî^âðu8' ‰Alìn…û°Ò'Qo!’´î+d?è*÷Ø tKµ! ÏkñÃVwz˜>ª{ÝÅSÂö=4ØÜ5Ó¨ÀÊjûBÞµìôeâÒj½Ê{¬ñø‰Ýa¾#^÷¾:“jž*{ÎúºøÞ™v“š¶0RR’´y´ú \U¤î¾îzŽCÃ\åÕ™%*—´ÉËgÛ¨‹bÖwF×HO ¯±Õ•¯è°r¢ÓA8…Ùëy¼2¶A®ñ%·‚cÎÍòÕv€ŸI9ãïSW>Rûï´‡îÁÀç¼ùƒEù8ŸÄ}쬎}Ž­ååhyÞã %(¬ ;â÷Û)å äÞÊ+ žøå¡ÍÞÑVËǫ껩b î”´UÒL[4åÙ=yr¤¥F•Ç]ÊŠk[vì ëÄ/w‹¨„½â<îdÉÂø<=æl£ÛG¶9Ñ­7ÔÄ•8L®½ÉÖ¹™}V”'¹guÓßQŽ1B¥ÊéÝÏä¯ÙiÊ>Ú'K~½Z=©{Y»à&¨-‰·èxöt}îÚ̉Êóm&ye…*ÅÜ&KÆoœÊ[µb·¦ Â0éà§/›¾Á,v³M‡Ù–’­GwX®’C8`9G3¹¿sÝw¶¼GÅDµGfÐvÍXÑah¿q?mp5¦älGÙØžíʲÓ`FsY¹‚á÷Ž—àá÷vl^%t½ðNW^:N¹áì´u“±?x;ÄK6kÅc´­Q8ó­õ$áX·si5¦—V»pœUÇ8<·J—. ,r÷vXXjï¹×@cl—Ù1ØÎË}ÔqyäuÃGÙ¹@ R½ÆïzVN¾kt5»PǸiÞ4Þºõ]NͬŒ™Nâ÷DéìLib©z ôlwnn Jfp‹²†Öº×l-&$}0ð|Ò®ê¹)i~PúN]ÞˆƒU§akÉÖ¥[‹3” àSM>°•­lî/r:Ë{\/z¦¬«_*2äÖô9@hòò­òÂÅÛS5gjöR;‡znRŒ7Ü>·$ëêûJÆÕWkfèxGÇHÄ6AØGUŸpâÖžµ'ž7(X `u½BÑQÉ s§<á•}½ ̬¦‚,UÒ%j¶Í*³çRÄfÍnu^–h =îbßxÖQv–‰>Ù~ã´%0¼z<Úï K™×q«uhr³bS§}µäÊÎÞµ)ùr¦Õµ¦It3m : öÁ~÷ =àz çÜúʹ’u ÍÝÞV×Ôœ²2¸2¹ÞÒñ°o km`¸BØêß`÷r<<Øge{¦UÑ›¼ò7-+oyr2›³}ë–‘ë™Õàž ûsk iÜð¿4[@nqUº³2 .ó·Ø6ÉŽ­Â•'1_¯/àñeׯqêSIv"^;™«2ç/NúúM;ˆ–aµµ(»‡¢Â¶†¡:®¹×Ýá ±Å:îy½;hŽÝ•¼(2úêšï-]3ì°}/Á{9‚ë_)¶y‚•t±©Ý^m߆9ƒÒ‡¡Þ^¢Ó½Sm®Áu}jµGÈ{–oßN“²?fvŽ+ͱ¥y¿)F²—fü}îßuÎæh„QO'n+®â¹Y # )gµ¶eÞï[ñ=xNÎBNe»ºöÓ§5Û÷ÐÐCΩåŽrÝ"PbëUÛË·ÙqÚ 1½ÌvñÉã—™·CeNø4ò²`­­öîóöRž»ÙÆ6|ö샳qßeõ5EÛC6êtÏÏ£Ìd`KÀ¡Ë ˜™aŽ—«1·Àå€óöu²ã†v©«†dÊ~y]o _Çä0÷tj¬Ô½+º|ƒöÌ>twk£ׯËV¤n¤µéEñ¢íië Ž ìîo;¥kw”ɼë^ª÷,~{GV-›GÂ’É@‰*ï,ƒÙteddzÈ!³¬×¯—£7^»M ÓHPÏ• ÛíàôG>¹xÞ«"³ÑÈðë¸C—]y×3§íMÜ¿bæ0%\ÒGÒŽfpp_˜Û4öˆã÷ZÒtØæüŸ¹%\裯NsÙLÊ܃sk+qöûª·Ø"®·Þà ÷z’Ëž¡g²tHšÁkV å@®¸0Óæ²Q¬ÚÚ©C*eØ—˜Æ `“R¢ÚJ"Þ+.»©íñÝvrv‘$ä—VkPÝ¿ƒÝÂ+Áµµ˜±ÝŠÅÊ¥;Ë®Dmúô|7¹r’_Ù³ÜÅÂñokíãÛ;…Qu¢âƒÃ•%Ç>縦7‰oczÐjÖ;<®7|­9̤é à=cKª/x†=¥l„ÜN÷v‰ éSua=Y/ªºœ¸(£Ù-wn\Aloµ³}vòZ¼ÚQ¬Šº‰æØ{ºé”XÖÑ€íy.VdñMz{Ù(±Ôó4ã¸I»^õÈt2…:»®ÃC¼ëµdíoé¿c¸ÙOÙLíYÌó÷¯ ¨ÎQéêÍŒ:ðÁÔµARú…kc¢ o'‰>voFíÜk£šÒ‰Z³{†ûœ'¹º¼x-ÞFû_Çs›¾[ Õµ6îD[•}oi[]Ú±Y¬.¹idÑÁPºÔîß Ì‚±UÙëI¬EóYyìï< ¨bTVõúüëYé> žœ‘"´ÂK'¬h¤‡U¨2¹_bËo.Fîo_+Ëå öêyžˆ\îhE{ŠŽ ¾U²µ¢]fò=u™ìòÝß>ì¼íÏr–ÀiAÍ–Éšã½qyûÝ(Ñ7Ie÷U5í¬b½gÅy¸Ò²ÆéMfX·YäE©†|Œ¹Ä)ÖáÉ{¥¢²qû{”÷òYç„»¯+=H˜û™p¶iE ÑC)áÎ4k®ºò ‹Uß[¸4ù»ÕZë³µ'IæöàH÷užs‡¼ ÛåQdÉÞKÐ1±gc¹­‰ ®IM?t§B5½ZøL?ÝåwfÉÂO_’qX[!ŽÜïŽNXàæÙ¶ˆ`åm-”‘‚’¶ù+ƒJ¢jkjÝ]Õ·Ëò˨ð­} z…Zyñ q.cÝWÚ¢uØU”«9?;Íå´Uè¬%7^MçE½‰q™‘rš*”w¯1+©[A6“eBH¨Z­Ð{….Ë’®²dí5—“:áʵu4û¼èWrųxÇÓæ½®çß?1Ü2®û);Ù~çêª(z·@Ó†­Í½©¨ÇÎYÐÍìE¹ >’Þƒ8 9•­H h÷:Ícβ¼ñhŠÉïKàñv 0ìŒ>ëçƒÊ+ìí÷VZ.#½Ï•ß«L^{Õƒr£ÈO+.šmEiðyïfŽ[uì¾»~»­¬’Úá-ãĉ{Ý©o`ÅeË}jÇi©6±9´àE¼×´K­:£æ»„±¼¥Š¡Ü¢¥@,Þ£5ˆoδf®ì›')âêüyWnÝ‚±²ý¯Úœ×fŒºSoŒZïrtLî/w›zä/_cÝ -þ‰”{³6½¡g½§1TJº¦kr°›«ÁbéM6ÅY®uÅžê”Ij±Z܇ƒ«¬Î+N„ËãǪЃd Æ•g[¥ŽNO6é;¼¼¹8ܦݧOUÌhz­ŠbÍ}mÅú¼)ÁODà51MŽÊ´ŸúVót>S›®ÉÔ…*Rà¬ÒWOo…¦¨X¨£xjÄDBê¬í í¹Ëƒ›!ì€BÏ= eZ^^`q'LƒËØ3›öP_ ÍüÝOÛÔè_MÍ7ݺ¦ˆö•–Ÿ³Âˆ+ÞnfÖÑW>ÕÈÜ µoÆÊN*q¶°õõhxp>XVsmaÙâ¼ëÛ´=Œ¢^;nc¿r&ÇC«-#í³ð¶Ç’Çç뢄¼­yæj^c«zl‹Ü¹äKåj™îÌØO€½kQÞcp].Áu·|x9éÈIÉV5Š5€k­[¶bùÙ±z÷Ý9òµ‰Z7Cub[tƒun3+·­sJ™VíæÂ¯²É<«Öͧ†íÎ:OŒ¥SŽZb<˜ yfœå½Ë {«ÍuÝ·ç¾8]{3§Ý+*sÁl3ØìO·¶Ûn®ŸÇo»à®î» L¿K“É-U+¥_ $9™Ôò`&•[Á¯g…×=VtT;Ø;³-SBLöu4ž,´û'u+·³ zªó ƒVßšÞSFqôí{>2Š\ýêp·¿xÙÒÉ­ö7îm"3œ´…ñϯ¸×MÚyb°aM:êécêá}è5;u1÷ÞÐ!Q>wkxÎùŸ^nßVË^pxÑvM•Mœº¶Hàõ4uï'×4]×Né®Ú°ÀdY걜‡*ÚµQk½TF±¹œg8wi‚óp¾ì—³¶«‹rU…]j g'ÔLØ•©6‘¥.*Eä˜l0Y4æU…I¬Í‡j—»V2”ÑÀ, )í<]J ú’Ø67¥èY“.Fä¿Ͳ¯Õâ$äìvñ±{CWr¯ÁÁq¸¤u‹¤2®dºƒL®¸ƒ*ß±©(ÅÈΰåóµ(ªÈÞŽfuí{|U{]±gVœ«zfàÕBb9¥T‡ó»é×SŽØJ£žw|¹ ]PVf|ªñ Ôèn ¬]Ç2鵊P]–Ç:Ü3ªèí·ÛlšÛÙÐz« qÀÖ¥IrulŽ^&\0ϰSÔÅßiÝÄ{nàÓÛ¯‚%ç ÄèçʹähÓϽ°-ò¯Tèábùå¯u,ƒ¶b,ôQöfª›‹=Ôúw]sÞ…÷dº2÷X0í’Ü»ƒéÝC{:D«©g~ÔºÙ»ŒèjæñšÚ©îÛBI–rN¬ÆYb®8| ¦ À]Ówu:˜&NÓX¶·*IÃãÎŽMà«ïŽ7}1¸ˆºá´úÒÄqµ¥çoáq„*Y†¢‰/ºô•0"Ÿ²­w^X«œßeG­Z­}rLS<©gº òîöbd3¢š¥èúUü¼ZñÀ1ä2× ¾ÀgîïÑwîoq¾mߥß-rµµÃ„"¦¾½nÒwÇ{„ê_ í~K½ŠÛ÷¸œMÖ*À+­‹'_S·AÛJMvž¶‰Âµ^÷ •÷IN¬<ó¥ÃŒ#Ûu4gLÀŽ*…l#ÏíLJíë{Â6„mß· ~·wîR½¿]Õ²öëÑÜÆwžFe“v_–e —jIR{/Ä)#%ÖvW€C½‡Î·¡×´$§ Ug2¯Q¥èê÷‡cÁYuv7¦ár¦b謑pÖ!ŒyªVÈ^¿,„Ò:xóËg;‘Ö9Ì‚¼ºŸS^¾èn¥ŽÓ¥MFºÃ|ƒ¤c½ˆ|•oLBKÇ N$oTc«LVIÎ…[Ky¼„yúA&Öèúý’¬]CaÁ\Ä%kÚ¼ Rö!ÅyÁƒ kr â¸j3)k=´â"åO· ÑŲ!H£¸ôFª*ÁæÜóõÛ*yòuÉ#pƒ{ª2°.m¾”Íèëݱ¦pKÞ‡ XÕ4È«K.Ýï"'¬Æ–ò*rÔ«ÝeV4=ƒ´vTU½µ´ìÏÕxháw޳å»*PÍ•z€ˆûÅs¬ó­Ôä÷‰7ÙØÌЯvènדŽüÝÑÞêÒ…ë×}PÐÔumCƒ§¼ZÕµãÖÎv«ŒÒÚÏ7sDÜØ{¾<÷¥ ‰XÔÃ^¢fSË)ËÛ­ »Eûrºf†|èm¡^ñòuwð5¹%O‹ :9Än0q¦\U·™”€½á'1uÎK[¦³jZçyÚ뮳ÎmüB]š¾}l|ñ RÜκ“¡ŒfšOÞîá½RÇ/JgºóG1½Ë W<¶´Ë¦öН12´ ðAyêßOAã ?T4œ¡Á(ó„åúž}æÓ[iÑ©ÎICGéyÞ6õܵ|!mwFÝõC½Š7Õy¬^v¦1Þ/ ÛjëZ2¼Òå—¤ómõœaU ® 3†ð¹ U%%¬‘M^¬§ë>Òo+Ë5öבÇ—uã]™×:ö{`ruËá ¤ëµvC/áÚ=Å=¦ž›nöésù'¡Óv\{áÜE>žÝJîÚïÞËëôS³Y#W¹Ô‹LwB²U—Úœ–N«ViXÂ"Ñ"c’É`tÆ8ì +ª–ÝÈì¡@ŠàŽ÷RŠs€{eJ|5l^ÅM¾ŠØÙ•¿,'²Žww¼Åê²|¥ÐœÄ>fK¢Ýûd\­H(ß"óÝïnŸXo®ÙÅ….îw‘âÍ” ®ÏJIb|·®üò.#oM/¸¶Úß^.Ø5¡ØFVÔÁòs‘šBîŽPNÅw}ðºt¢®Üû3*D¾Ít´»¥4@hnãg”¯w°‰Ja[癩ñ¥Ô:骱ұú{žX9ШÙW¥û«PRÞÊZó‰Ì¸ ¬ h)¾Y¼&ÒX·ºÚ‹y,–Òageæ.ñ©÷œYY/(gž,mÂK¯9å½ë2Nm,Ý;{–Ko6 ñ©¶ò$å!oze9†›(æzÇ6Åq¾=ó­éûe[+¼ÏQÖ*yêOeQ5`u&Mnµ:çVº_<¦%զ혮'Ï£yZZì9Šè‹”ó·6D¬V̽›ÏÞááÉŽ°ç9~piñwîã!\c ÃÛvv-%)nzê.Éc,÷µ°àC‚²Æuk-‹ð"®Ö q$Eó¡y>Ë»Ë1ª‘­·×³/Z³ÖØ(”ß Z6ó… ósŠ7<1Y~“Ãî·àœõ;k¸J͇i矰ñ÷z³/UžÄsÅ›³~z”vYŠ":˜µó|3›½ÐrX*ÖîTZ54ÔŸ•6é]½Ä)gEjrù1W†”6²L¶Fk»Ú.· 7;Z;õ¬~Ø;|*cÀâ¼Nð|óZÍcÕ-ºº·Û˜3s˜•Þk´0ÉTñ"²›-Òe%HHÄ3°¬^hôìóÔö¥Bßœó¬dêy‘¸'&äZSÙw/¦ æé§{<Ä+¸ä³×ÙBW!4 Êgk ÖkáäÙ,,kô ly‡„û¬:o.´\u{‘‡œh»íO­*E‹ì;ÂrÒÞ `È­bn ˜-WA·uÉÍÃWS ¢ù1G%X¹]÷6Œä®ñÔð†ÁaØ~t¶²K§ƒ;ôâ܈vhšFŒ¡´ÿ¥g¶œˆWNT¯mV2ˆ‘jöÖÌkMŒ½ëØg1¤_.£½œb¡C­Ñ\²:›l‰jÑ'y´¥ªG»UæLÞìÁ»ºä‚êüÕöJ^ÌíÊASOxÞ=[=‚ $¨¯dÚ]<Ø£ëÀ•›1Ý`$!äWµ-àûMLÛY>ÏP< æïs«ì÷V1Yä@¾ž»=•f$*DDÝg*ÇÂÚWî(òç]áF—¶öã°æ«§¸[¢€%’2ß w#qy»Mï™Oƒê ƒÞ¨…z4©ùuÚÑÛ#ož}…[Ä‹¶¦õ×/»º î©JìÄŠv©1oÄõg Óx’è.Ëõºµ`yû9 Õ¡¸vYÙ™AýÉ_Uïf{ÉÓÞ\i+¯t.U’à©:Í1ƒ™µ–r®–[b—ð­Ûdƒ(Bª¬6,$àQȺһÞðgÓJBú–Ž^UˬL¤zÊ6Xz6(Š| ÷§¯nF+tXGe`ƒsDJõá_–­K7µÅȃ—“í}á”ÇÁ$Ý€¬Vըǽ´êÉ9ªm ý¾Ï ÖÝF=FÕ=²«×C±öïR;b•}JþêwIì7|#³}…R:_Nr´zú>bz´·}ޤ½Ä¯Ø0U׃ÁÖ±ZÈÁ§˜v[Z¯_Hê¿rÖôÂÒ…Ÿ«žÏe=u*׆âÐמ!¥Û¹uØÉiÞt®±¼BÃ7%ÝЫ”U ãMÊ\}Q+‰.ò-ðUš¯׋²uóc4ìç­E6Î÷y6Õ&:PBïíìusžn_G±v‰¼ò=éZU_º…zwjʲ6¯–?"ý+]„Öäozfî4©•¹Î¦pm¥y­qçÞ®Uw’2Û~³GÝx„Iw¦-ÝÓËÛOíëóZž!ƒFòD˜gO½ 3 m¦·´«51½ì€ªï/»¦‰^yr¤ëN ±ý(~Íü; óô[¾˜ÄœöŽâGboo);•Ò¥tÈà=›‡Š6ÚuΣ@!ܬ Ú褎•nN–˜c6"6ï¿ã™Õ½ä jp<$ß¾»a´úryÒa“*]öYØžÑç˜4´NÓ¯_«×a_I[@gVë7N†çCc »g.ú¥§:Þ=öuÊ}›îo÷¤³¡èY<óÛ*m&âÓ=F˜ˆŽemuØG™]Wc±5’Ox‰Û»!âý}r_JjêUÕ®-'ªlá"ËsuÎ×B–“jàŠpÃä½ÚVÃCt‰ï:'^JôÚ÷"¡+¥×ˆ¾·DŽÕNÜ'ÂkÅØæí`w^ Ë"qc•zö*õ9 ¡Ý\Ù•ÖþáYu"÷o{nÍ?’\êfHLDÍšX×gµ‹¹z.ê*·5ûËÞJb£6¥ûU£“½%,ë2veºlÜô‹Uï®»ÙÑCC¡jöÒ!-ÖîÎ}RͶRh×rW˜tÖ™7yPµéKHUù$1oµ(¾[«kÇ‘îË ázµ4¾Õ<'Ô÷xNÖbžuºï®¶næâãW™XUùºw¦Ž²ï…;¾Î¡—¼Óî*oK§}[TÚíº3¦éâ—‰œ™‹sÛ¹ÞW«Ä}vÚ÷¦¾ÝYsiK¹ÃëžËžó]{å%L|ÚêÌ‹Šž/¾¡™0uߣֳ¸Ã]Jªx†›þÚW”mñ>ìãz9 –µà TÓYÜ.ÉBTÎQ襷w—)ŠYÉÝèàª/1pÀá«7:Q)æ«:áRpÍÒ1§²¸gw]®`w!Ÿj&3­³C¶i§bìñ˜±ùW;¼CTÕ!g#¸t¶V¥¾{õútg†”iñìòÙË­i‰Ò´în»x>‡<Ãa†3ôÇqÎÑÝ\ KK‰ˆo,èÃ3§°`hg[*PVN›ê• “¥=®v˜) r>êâDQg[¬ºs5Nø‹ÊQœÁeªÀ¡l[Ö±eµ­–®a<;ºÜ¥zêo«Í„ünŽi´B+<¬ÝåyX²¬©Ðo]#|žRÉ[ÊCÙ]¹^}´fúèmwzÈ’£ÍÛŠ›;›ê|èÇ]›VÝÙ;WHÕîT®= ±S¥ÔáE]b2”µGmqJ‘9¯×KÀg'it5›Aß+º—³™ÍC{¦fNà€YÇMãÈÐÌe±Ñ<1Öåž©Obî]SYqfbó“w¼¬oùeæ]’ Æ”Hu%7‚˜WÑÔùÙH“ARÙ€MæÝ#ÛQvïaº³Ok¸ÂŒ¼Ô¾§Ãær*³Veâ’ò<ïxáKÇÞT‘¼å³´ˆ¨ÝFøª-¨ØíN"èd8Å ÊÊB=%nŽñu¸"âÉî–‰¹ B_JV{´';ZìVö5º¡z6Ñ ¶x=+(ñ”ßq/]uq›“2 #îÛ|àÖ»ºLê¼OÛr¯@5´Ã·–kíWâÖq[‡šª[g.×®Wäæºïx\u„műYÞMdÖ¦ãÌåÌ ¦\®ç1:½ÕV:÷H½zN}ja®>2{Z#nN/…£Ý};U+°å¤ûw^móƒ¼ò½û¹Ñ5–Ÿ1NtLÚ'qnl°i×NÓ8ð–·ŽMì­¼¾'uŠ m›ëz.:œÎøÕÚÙ”ÜUØÚÑ2AŸdºAEÂÅÕ²°ì–0D;åtØ3ÄÚ’¢ncmå õÞƒ§" -1Ü`«¡Ó þ{;Yx+Ùì•Åb›ïÏa*œYsÑWuÞ„W™·qç˜-æ[¤%û»G·0¶ùdv=™\ë{½íÉá«§^ô@9ð5*3«®1…Îý{šíÓ†ø ¨uIÝ©³9=_uãNÉÍ[B¶³NåÙwX3¯MŒìU‰y²/{°âG)& >i«‘+^Úk(ºo²tÏ]÷à‰[^1½+wËÚ£—©Í™rygºæeÊõ’€Á5ÛÝ;ZýšsÔ½—w+k‰­u.þz–´ßcÕ¦0ùMÝèœÁSWW²ån†9y鍸Ü69?=¯®ÉºÓuÛ²,z{½4ÞT®+Š&!•Ùïkõ+¸äÜlVzÂK»Gu–qÕ­ƒ-™™¤Þl‰‡ ¶°sf£ç½“çÁ88”BàíwSDHlx÷;Œ4Æ‚$ÅÕ+—: Ÿf­ +óüxÀÓYŠ»Žß¤´Î؃ó¤Àǵ²8û=òî°ÒVvª™*oÖ>þÃáùÏàÍö2Oç&#íù—ø€z{zŸO6í\¯‡³»[{3ñ¤ºzœÁ”XB!^QKÉ]±é:vòÊQêîX°j+Kz%rêîò¢(dVMÝ©*¹Ëœffíó¥Y”Ù .¦h»¾Ê] 7‹—;Gb²žßL<,)Ï/˜4el|&5‰‰XRO"/o9e·k·‘Å׸û†;6âZ™ú<6Eð‹œÍ—e4iK–ò†án•…xî kj<¿­å–^.U›V1­"û€Âžw ”M¦Ö_:u¬Ö:{nÐtµt"ÙZ§]£¶Ž,deîFú'—mân ’JÀ×h8±ö}È“\@ï{guLÎë¾{tõ8…g`&VÒÙ·%‰¢4€uº-š#£vK¾ HGR¹;#®‡°Ðíâ—wÔíöEØU*kʳºþ‡•^ …UÈÈLR# Äü’Õ(Š|júÙNd­­Uk†R¬Q­¼cªðÎÈ?"Ð~ ‰wýáXû4)€@ŸÞ:ûü›‘öó¿-å‘”!KàÐâPAÍiÍÞ\!ÐOYÈŠX…´€ÒeU Kž„Fß(F?LåÏ{¶ÅùÕÀ÷ÏðáAŠMõÚmkÉÛ£=•¡ÙÉ)ã¦8Xeü³…Ê…Le­ñoÉ -íñ× Ÿ4*` eKHG¾ã@Ëp–#ãÊ…o~Â<ËDÙàVcÔëV½Ê²Ú/ƒ=~¿oŽaªëÓå‚òÔÆ­-–óáAË.á: Ù¤ôm5ö®ç¦ÆÓ¾òi©ßcV®à6!ksÛ¶;,è(ò9@d==·/׃Ø&ó®éæeñ?¥š?5vyüEOë6Ñô9%¤åŠ)Ú.¦ðeå7v·RµÑ`»¦Ëät>rørØc뵃¯×Äðíjÿgï}|XÝ©¿’H½-;$w…ç ò’ˆˆD.bÆx‘²ó7Q¬ g­K1mß‹¡w ­*n Ït© Ðò—Âò”?ª#rµ–¥jœÅšÅL¥—» ¼—9‹µÕ¼vœ¬ˆ¥³šÜJe,¤¨äÔÞsF®Ÿr·]ªñ `Åz8nÑâ+5]p³¼}Úf¥döª* ®®Ê• Í)ÀmgN=-ð7cVY¥Î]Âd=Ï:ÍïnRÁ @Ò¶®®·¥Š\-ÊŸK”y= ,ȺE£|ÏOu‡Îºµ™ë™CÜŒa»¢"¼ò¬K° ýóÛÏiÕ°Pž†íþ:³´"Ï}{8ŠÚ‹õ„©…íó¯ à_ïvt£=àTiyGjøn\’¤`)VeÝß•8EÅ媼Z1k¨³€îƒe ÒEgJ¶’–×ßNëRÂÀáMìANI+y’ÍHë¬Üö_ÆÝv¬lÜc½¡œ¾úcpvvܯ½™hJtÑÆQ€e â+†uMï.™^âÝ 6”¾Ò^mÅi¾3Ô)ùëß:9”sRruÓí*Ñ9”p#«9<úíµÝ^f³·8¶áâ€óó­³±÷†¹ÒfrRu#¹[oU”¯ÐuíjskËG^`”t‹­½lL5½g„ˆdEàxúë›ëmi•ȇuÎ÷¯9A®p—ŒßšuŒ? !>áåëc.<ëk®Åµ­»W­]+<+HÁrÚ¬[~HRÚ¨µF*ﲇ¡u|ⵋ‰!VQMEÑæ¯˜b£Ý;¯­ÈµÙ›Ü•ÜÏnמriîÕzý TÂ#!£cc ½]R¸nðª<#ä ÷´§Š»••b;¹BíÉÎýÄ*ÍKíãtGÝQÞZÓ©äòOŽ;Õ0dwjœ7GÌ«ÂÁÜO-)Ü)Í–˜Á3²µ2Â;ƒ<½ÑƒË†‡Ê)Ò›Ù›Y‹‹j¦°8öṴñãì4㦲‹Õ´z-/1m©jî~ÝÉ$Y]Ûí×Ko¸CFüiá7‡-qòUž­T®zó¤–êÆÓ]5dÝèˆð#õ¾ãÖ( ÐÔè/Ü‹0I*N FyƨD·…×ë]ï{ÏÝJöfúï&ËñÚõ†k™½!ðæN½‡SÓµÛÑ…ö’X%åu3ƺÕ]àÈËÓhñc\B5“5â¡ìô¢2òûÖzVœ¿@õèj¤žƒ\ië²mL”É»ë§ßŠøxP¬ì¶qŪêñrDkÛV-™h¥Š +í$ßVÅcà‚| Tó O3‚QÑ»WËf9mˆ5gAË/žÐ}Ãr¥’óeôŽ^J\§Zé]H¸ßTš÷øÍI]¶pð£Zw€Uy*ìBÏ•òî3×õÌ ¦ÔÆktn·×uXNueæø °7j¼²0X ºÁYµu…ˆÄ/DC™yç6ôÐyh:Utíð’Rß®óî rêñvTtÞÛÈ÷mŽOÓË®Ó Šýžˆj›bÕë.Š}(LT.÷<³ÅÖL8¶:„sÍŠïʱ++Îî[«Í¥e° §îí°&m«"B{ÞëØé/ $™2³å¶nžŸ‡^Ë»eÀ:Hg39Ò?\oÀZ±Øgá4ø ÓÌ…À·ð¤ËÂåÖ@»‘Þ;u{& –4©,Z"û)‚B竨ö”5hfÐÒ¯tÉuÉèÉ™¯³ŸcÀ-uà¦M¶]sÁq®ƒ¦îsÊk{HÕ.EЛCPT¹ZUuÆÕmbéJìòî à§nXRú™y8§Íîm;Þ gv>Ÿ€zü7{ Í-1ãÇ€Ù^)%mR|c÷=Ûæ5†²6´†*ˆ ØH[[ –aíÔ{+PœÝ!}—Ç,êÅ6rtßVß8jºo:K©ðjÍÙîvaÆkRU{F>í§6ÌŠ¬¹(J‚Œ¼êÅœW½Sr´_½ë[äW&¹¼])íÉl¬µKPÌ[*Ÿ ÙÆrôc®¦n³à3ºš^º¯]ÐÊkqï™Ho{z‰ã …Åv”½ºS×­‘™޺̥”êäz6bË~LE‘ ìÛ¥¹È‚·r±“àXãÊq^› (Vz<9·Ý>Èä®î…åóTãœìhìAÒ½ XÛsv÷>½Æ…¥µ{è®§½œ¿¹o·öÉÁi5•œJ=:þ YÙbþBwso¶+dˆzv~[×ݦ•8éë¼¹Þ…“¯ÙZ9÷qa¥^å—{¸t™Ä0‘7¯À» nÆM‘\×5¡m”°œõá}tùøÔŽ«–ƒ3¶ÚÈv=ºV÷ˆ³ÏXSÞîŒÀEâÞ;€ä"—ÙaÒƒº3Ö³ìÚѨãR^OuÊî½”k³@½´Èš™!¿QbD¾¼;³¢]|[DzÀ.U‹“)N&²î˜u‚´`+¬~öoG@úÐ/pš) ð¥Bàõ²Õìݲi°U&j;Œjô°3»-îÛ)2Pîjê\š›œæûUžI­î®gNN¬]!ŒºA]À,cC(e.8 SF„ƒ)šžg¨êÙVý`¿U̺æÀ˜±4 ÀtõvåT–œº61¨ß¬]LÛÉÐéÝ$q§qoÊŒ @s·ÉTÄÖÌãµ…¾un롬ßO&_¾8ˆ¼»õäÏÔþäcÚ·YÍ[º4«E,j-¹êÂçc²‡ZZ7q×K0ÀµAðÐH袆ÚêKÉöï ¤ˆã5¤F2ûÂË{ ¢êÖghX锹«PÈr©šX8âåyˆÏO²qÙ ¾ŠT±Þó¼“Þ(çVkÃ{à½ô<"·&{jW”–?$4Ñ¡ÞÞ!D¼açF×Q,}|W¼fm[Ú³Fº|P¥}gU¬|ÓPÚÁgkxVb@óˆ™ÒK¦úvAjð[ÒÈRØ3[=Ó™÷nx×->N¦Lï\ôK¡ž¯¶íM[Ý€gjëRÕɩϕ×5.°¨®ïSu(õz#¡o½[6<¤p·—á§~jµ £Û¦‹»­¹›ñÌJ mÍ13\³G×NY¼*t mþ4«3îR2Ubu–]% î ¨¦Ã´#Ðm¼ÕÏ›Dׇ¢>Ìä— êÇ‚ÁnøŠX+Ü›Ü-õ–nšäØ©÷,¾Ju‘8õ‹®l™ûÏÆ÷qô°Z¦QÖ?q]xÇï-½DʳäwÎ_n°(J=]sk%:R²iÍ8ƒØ®-ǧw4 £Cw±Ò›c0<ãgœgÚª¶ X^»­weÌ oU¾¸%dµN-RòÖ'öΡÊç9k3{$ídÙŠ8¯˜ËâGHF#ˆïv«ˆêö ˼êìÇéZDÙ ÃXcÊÍ|IÑïG›öw]Ö–êÞ(¹Áž)Uﺥžû²ÇºÁ˜_´sÁ]à{'Û”Ð3|Vüp­¨›S,RvÌh.óI'Œf´¦•cëÕéÚ¸ÝsÖ«Vñ` º¼ÎÒPUܲv5å~ef‡62÷]„«6Ê2ösPIMØô|dë–ºy-d°w ±z‚™Óšk{kvÞvý™¶(lÎ+•F)3¦RŠb2ººK|ê Èé8’×ÊwO쵚aYÞ8ü<¥©Ûêë”ìî활B{ÙìTï)Å{½ší™SXÁΕ©RKr1c½ï]ÀuÏ·ŽÑ¨Áºwä¬u1/ŠÂîˆ÷Œ÷Ó'65¾§öõ1‹%#¶C®æã ¶¸Å~µ’áîÞäÀ îÔ={Ð:ů4£äïÕ·˜•;¥UêÁß }žÝ8®.ôðdYò»›¤ý;.Êt­~ÌÇ71ïh{¿»i/¿hðSÅÍz©èYK_½îm<ìêÛ´„y™1íXNí t'œ´hpgÊ­„Tì)Xj|{s|™És‡•v s ‡Çví t7®ïkg¡ôó󋛨­¾tnðepu𬡴žnNÛ«îîÁ@-®¤¥Øù.» w:Sbe®ÔkZ‰J—‚>Öß³±kL$YTÊsö`Sʽ;t¡Îë´5Æô9Z1˨+•öZçVëÙÑÊF™Í½yzm×ެô"Ø+G ìwÐÖ¸ûSѵu?5íÛÈVÝõܘòè5–3^ÌÊæ8žZô·yS©êåÆû4è./%”Häx§„äyî{Òò ~¡xJÛCŽˆùííyµq²Z µ~j:W*æøXv<=B¹äHHWV¥¬©ÙbÿO o›~ü42üé >7*á‡5ÎÜWÚt’j ¾V§±Pà9…«ë³•Öœçik^Ú™ªˆÌ¼–Ì{]BG™C]G¬üÁjƒðk½â…ŽÎXN¿Û~VÇ\½<õ žšöíµÅ[Û[Wr—N„:Ç{ÛI¾*[=£w3¢®4±hÃÖh¦¼¡:ªHLq±FEðʼ0®§ÏAy:´+&»{i´œyÛYÊj£¸5­˜ä®Œ„÷,V „Πé)4|F"2‰¸õ-½'öMϳ#ÏÁÝ.癇 +Ì€¤«:ÄÀwz±¼Úo¼;¡!i§¶¨_¸áEáÖ3+*îÐÚ3’±d?´"òZð–ú¥Bî ò\Ç„I™#Âsz):ýy·MЇiì!3ìÉ¢1Mß´ZÄZ½L60¾ÛåinM]êø©ÇëäÝõÓ9Ö—+ê,íé±13’@Y¸„ bh›ì‡NÝþ”ç«ð‘^~ØO¿b÷n÷,Ã3ÕS‚^©mÌN *oˆâ7FA)°*ÞÓtÌ=IfV>¼®íá{QèÒˆ„@¹Œÿk”¬–foì첩þ±bç-o÷·ïi(l=DÅèN ¿QVTu\È“î¡I`{s6Ù=šä[µ /R»Æ3ËvŒ5åóó›ì»9ÿ«¸|ΉLŒ$ÆÜk¦ûKJçºÅåỵcôÇOÇFÇËÌÓÜѸ_xKž’Þ+ÊŠýi•AM‹)ûk¹VÕÍí Om"¯¤êÔ7ÒQô¥[Ä™¶Ùlܱ~p§CØ s¡®îd_uïo´Ö,G½éæ¶,ý™“ɬZ0«»púס¿¸EŸA³‚^«­m›Ó‡Sâçt”,®{”Œé¯PÝ]J†-Þ›Fä Q¶÷+¶†ñâ¤ÂíÆ{‘2œÏEªpôí³«±-æD{̨{ d„õæ&®Z™Ô|1©=ÙfO«c¦;½«¸b»&šÔŒFèj ;ge±áœÖªë(ÙJ13nÛº¶Ý1UrFTw:_S›9ëÔîøà]™nøØkyóÞr:Ó:úwÃHÞ¹ÜK®(}ÁbËFä‚£™É¹kà!îo…•ˆ®¼/¤(‹ÆÊUcr²Å‘oq3嶸ª;²µqvÓÙk]LäµoÞ¨žS­k ƒ­±&eÇ/__ ;· Þ+'ŒLJlÁ˜Q«v¯ÉmÚ8S Â}·^¹}v«I^ 7)³7s­ÎE} ê ^ó·’ ¾‹Êz §QI×]OïBÐ-ÓöÐ]tßh˜—¤ÊK7Ee˜šŸW¼¦ xeï»i÷Jæ!ÈàUЬ÷&®§#Ó¡D¤”Ë6MÊ‹¦ÞÝ\v,ÝEÜ]Ãîø¢cvgZžmæïâZ†Ÿ{¯žâ™[NÝc-ë¥Zƒ]k/x ÛŠ»j;yU‰5‚HVu]r=†+{+{·£·¿ƒ6«òôög¦ñý|â­T*éBh¢kZáxRë†ÊîÂK™+¯OTêOy —4è 5BXQ.FC¬‡SP.éàB (Cl”¬íò>w[®SÕ–³ÆA3ju÷dÛîû ÞÔ¬F•'ºY«“~ÝqÞ^ÏYxÜÚÎe<™ðN³gVR­áÁòô:·Ô·Ëç¶³ÃWØnp®\ œ‘ÌK³ºìÒ÷'Q÷YYåv)²5^ÍâÞoŒ×ܲóÖe ã»4stãçÈjŒkWœ1¥¡¼ NÞu§é·…L½ë¼hrÊ™a1ÅÛÉc†ôƒå›”Õ+ã=•wQ©Vͼb–©ÖñInþ1¤¸|RÛ9“.^Ö!,.ºÛ¼<¾,žhù¸«­×>öκTßR°;ˆ{B§Y°#X*aûǰç%çÝê±UЏ0›­«|K§äûÊì@ÀÞdÕº¹^HÞ°ò H×`ÑŠvâ8akl¾„ ”9ÓU¾rŒÞ ÀúÄÇK­ÝsÞU3sÉôQ®lî#|Å)êድ\¬uéûŸ-­·Än…´BŽGÄábî)/·RÝ7ŒY÷¸ðÝËã¸ô ¬m÷nÔ8ðÝŸ™ÝÏIIŸ­:¥&ØÂm¸Û 1Œ`Àå Þf·.­ ¶¥8*Yë-ò§ï#»™»Zz¦BõÝêõÒ®{ìÜ[=<®Q×A£aÛ·r®‹´m…¥ˆwB cHà‚RÕ‘/]n¢…ºß/q6k9æÎ÷V®ZÔ£¡“ÐáqìÑ 0Ÿ¹­”Â[å[Þ³“`ç€äÍÅ3vÑíê.'k³ö?gžÆn‡ ‡•æÃÓÁ^54w…#-=¢í §µ;îZô/f8× ¿v¦{¹ËÛŤ¸´W_?ß.ç—Pg(©+¦â8+Õ‹ÝöÞ8{—‡)àùï°\Ô—…ש‹ðy盾[l]ÒŒ}{‰,uÎÇÚõ“Û ¡M`Ü[m†*TÃU˜t®ÅŒšhN˨ØzøÁàÂxÖ@6’öÝÖI:áÜõÀ0É—',dïŽà •ìºN¥}Ô ½â¸¨/ÞÑ“³Þ¹‚Lʲ/^áH!OM§±³¸ÐVùö’àÖ»ڼæ.ÑOŽW~B¨š®;Þîž+œ‚?ZtYün†Å\ÆJo.÷BÍÚ(h-bS9<•}G93œåqÑvhHQîà.PfÌÒ(nà¾öwk¸Úxò‚ËKs¨¸„ι –=Òc»Î|Ñ“¸ŽÁ õ 7[Ð*=3JškË=Í÷qSűˋ£Æ¤B†GÂö¼Rº÷£Y½ƒ'29–¤¬ÜìSƒy ¨ä÷"½aä÷¥"+aW4Æåó°÷ª5€.«÷o >zªyy¯NeØX9 }àÌëR[®ÉíôOA±‘Æ Xèlƾif)˜enâ|Üõå›/Ý×g< ŽÎ×±œõ§”{!†¼ÕÍÁ˜+×¹dÝr%)Úùæ¦Ý•²¥±¹*h¢[*ó Ô)>ùyõûÕf0'h5@Ë€m*Òôúi •/*;ÄÏaêžÏn ã>6 µ•h6ý£Ú.’íê4Õ —ý úžkÝnÙŠíÖøeØ­¹wð£P‡|'ÆuÉ=OEÖ%¸:qÙÛ[ç–}£W¥!î“È,.¢æ¬Wr¿]%%Û]å¶7Ûoi€ž¨¼)œ¼RCÜb¢-¨WH®ÜÊÄþ›íÚJ’x\¼ãY£ÆÌ¿¢¾Ý‰f+²=mÏ@m½Îç‘Ã7<ü÷NìU‡×r.S6t«¸GY|óFkìYøý”?ÍðÔ$gÔ˜Jg6¿`×ss1Õ•%c12м<­îbÐÅ=Á»ÚÅJ·‘,nnŒ†‰,8S=|ý}c…¼bHøpy ŒÌ8mÁ•^Á”0*G&ª¨z‹G¦]Äéõ–pç¸k &O^ߩĿ²¼EªÚÍ1Ʀ¶Õ¥Ò·A|0®x±íš5Ë‚,Û\æÓÀÜILI«®Þ/z\£w6|JšãvÏG¨ÐP„=|æܸYe6,úÆUÖŒÕ%6ˆGØÛuÓ¿wVVUØ„ˆPWå‚W«P‘ lÛöL•½YW,Äî½Õ¼ Úx»gºh«¿vÀ « •WŒÉEüõC½— sø½xhº7„â†í˜ÌHyw»2K¾ÜöDϸkb».:°l{ǹ…aÕdFˆ }YÝ;s5#s¯Wk×G­1+-·ñè]húYÐ[m9é¨å³»ØE¬‰¼Ï ÞbrRäã[›Lé‡9Ð5É2@-aNêµNÂWäVÖ±^¥±¾³ØVì%M¸l¤åÏFzEìÜž½gÎýyìôß*ãµAÞ*‰û&+1í…“›wckÖr×¾ôEûÙ6½Âìªå*,îézŠËÎæ<¤èë‹in¬…³MìmõõõwR¦ò ¦uªíÎx/#Æ ©’Ì·Ñ›f»R Uñ>Û~UØ¡ý£¹»9+Mgí©·àÒ¾ÒfkÕ³'„ 9—ÏÈŽ<ΫY±g,F…¯½çV; ÞÅZÃDvnorÛ€8ÒlôCnp7Û´ðÈ%6 ×5ët¸ó€q<‡o-¾HvÖÌípˆ¢·¡„†¶ Aí-[S¨åMKÛnžH{f=ìÍ\¹š]3¼{®œ«ºÁ²…îƒpV^Q¥Ó+tbz»i”[ÔñVž¨JÌîpÌÕÝVeŠ‚ˆ¦ŽèÒõ±$«¶Ãxš888{Vê›…©èÎÐÆ‡/r× 1ðÕHN¼Õ½£÷³Ùêo8w<9†`¥GÐce$× õÝæOu¡~E™ qmÇ•ª…`X%ŒW¾j·ÏÌfA0¾û´#pë–XiÓË×PõÆbbWjÐÔs´óHÈ4ºyÉJ÷Z¤½îÆ,Ýœu ž‡líøîP—¼vö]ÍQù°Úèš:6+Näæ*²èe§qd%nÊÝ­$Ð7o“Ù;ˆ‚kØâm¬ mvع֜(\l ®·03×”6b÷yŠáfîl2²Z¬õ+¬áŒ©×3®5V¹÷wË®'åq.û—Ç”@;¾{ƒU·Nl¬ëQ|ÑÌöÒêÅXP®®ç;„°Í+­ThZÖ»׊ºÎ^Ñ?#!WFÕÑQQãcšå]í#ÚÊlÑòZ:¼%®õåíKÑŠ\¾u<{LXÒ¼•öaf‡/×Ëä¶ÑÏžè“¶ù}«ç&óî<ˆ]}+MæÝÜHÄ+úÅ7Ò”éwçplÑì½§³œt¨sNfÛOª@—î§ë|$³œéúò¾.vè]¶+‚—z „}ž'´RN\¨£j*Òê廂îîÔ¬Ç7]úù½[h'˜]uwaS5 Þ^T\RõçseÍÞ@M>‡ñßRÚXh`_¸¶/»×¥ÀÃÀ^:µûx9K›öóyŠ!_Ž„VÎ_ϬÁÍÒw?qǰzÔ'z…_s­~ôK‰>„áÑwd{š| vcæùÞe3°Ãέê#…Ö7šK©&¦½í¶2Š¿ Æ®=à¨fZá]ƒ<ö;R¶³2ŽP¾\™ã‘â«·Ïìí–¸)8kÁ¢‰gC­K·NœV3ˆp훗Ђ¤£Ûvº6/qðÓcUâìÊ(òò¾ó4muE¹ÓREZ¨b«ñè.Èr¯€½GÔïg†Ür…A¶6=dÑÖ¬è<4øÇH:òqÛOVÂgÛ›0KÑ̰«„‹­Ì»×}G-!Ñ©Q7¶)ʛ˨Jo³4¹›è–ÈÑò í$¹1~x·[]¬M…q옵Öà×ÏWK«Òçl!…×.Sª¼¦›™“ã¢jMÁÁÅqé>¡RèçËÁ8¥\´Ca½€aE…¦·“ˆ*Ê×.ÜgpÝït,½×].j28qä YÕÀ36q‰›{÷M5f’©™+[Í«ŽN•‘¢ häšP¸ëºžINP›Êã»xín3,ZÒS,ãÂÆUÛ†I :AJèb±Q·pëNÔ¥}Ó²,˜Ûu¨‰•jb(ñt,Ô}ŽœÐ±Iq½/ Õ•\.‡1jû„ËC+kTºG)b¿¥Cd'(0`¥[F†›ûU{´…åU´Çð‚¥m]í[Û‚‰ku¹ökrÔ‚î#+Ø|ý ^ 1¸nÇ™÷FΗ—c£I$i=³:]î´£Ø/µz:µs馡P\Èî U«º}”žGLå%VqÄ1šè€/¦]ö·Íñµ±•Îý¸hæÎ®§tØ}Ã=è*J¬oÒyï ï î‰Òœê_ONû¥¹f ©‚–íøÜ>óÏlÜ阼ֺa]Îm¨çˆ¶¾°âÈøÜ•ÈV+E¸¬ã©Àdà ÞëOÌ9ÓG×ä÷æP[õΙ‰ö¾[²ë¡ ÖOVAÛ¼ÆçÉ>»q¥ ÈB†íñjÅm]µÊ™u%Ixÿj]yno®¿ ßß›„ø<Û·ò­W‘cîÉî:Êî—ºôDV•q´l›ëaÑÍçu¼;,é¼––®èÙu¦nÕ:Z8êued®R£º÷âóÂ[£ÔåX嘙»ÎOʯ˜xóiíÛsB‘+¬0‹®7{¯8¼®è¢õò@îû·†ñ^#ðÂEnß°ÓK-!šúóŒ÷ŠKÁÖô8&K²žð¨.À®{K\dc îÄÌ»p<Ý‚1Þ½'}éªâ²ûä¦K^6¡‡ ¤ç ˜o–L[´—˜mõâCEOS®‚2ÀÌã¦Òyãdœ»ONU¨ÊES¡uÂÞrä×É/Cä{w–yÚ~(Cl¿¿r]]~˜=ºÕvµŠås†Ôãݙڳf¼ÕNNâ˜ÆuWL¬ËïÞž°:;äòo¹· 9Ç.ÇbàZëPâŽG^B+ÎÎAï›î}dÝ/T»ty…—wˆYκ|øz[·¡viAÔë|p WksÏ{”ïuһͥA"U;ÖuìÆqã7W¬ÅKµ² ØD÷4ó07×s‹bR>jCÖ{²óµ|v¥Ðº–¤º&³r¬¬ôÈû‘9MßÌšÚçq©Üðx+öÍO°ê+áj“î½Ö¹fœ=U« ë6ŠÂ>±CD5’ÁÓÊ`ï™Ë‡¯{»Ï§Ü‹o+-]d¢‚HÇk†ÔKelè_&êfͳ•´sÞî™´ê4Z“q–Aî,ÖõétòæQ¾K½óÉ6kv£øe©z¹„Î{šx0-NöJ^Ó-U.j¾ñZ<ÒK§V×U]<‘€–P×]è©ì5¬{Óòz¿Gêgß¿jË~ò"Ÿ¬ûÉWX·ê÷^¿@½iNü‚˜#¸þÆ=iÝz¥c2z×qŽvЇ»é$ãJMÒ ôc¼ãïzƾ٦¤v{»35Ib õwW?Jlvïyn¾ÛÊóÒª`µsOÖçÛ‡y«d!¶«¯l—dØVŒk}éášEðE¼ã Y`~zë4Ten èªü ûζ¥Ïº¿b 6gâÂöí\öjŠSu9fV×#óÇC´F÷—Âã°¬±VõQð¬´ë,‡`”±.ýHw_¬ s«¦o 3*æ…ôÝ|Ñ^ës†‰é–'©ÝxcckZ9ãí™)VÅ;w)·³ÇÑ2>Ì]C®±Š{^¡ÏһРU»ïW]·Œ,áeãm#[pŒXÃ?Þjº´áª"é‰h DË̾EÞk~„öÐkÝî™ €7*¹Ðw„òµ³ÕEX‰ÅöíÑNZ‚¯fb­ÈÏÏ®—áÎ ŒJÁ&ËУ—ÅIøm÷•¼·{Utf)ë!êåÅ'IµM0Õ¦n Ož}'@›4•™«ÕÏA®$] Ý;žÏ‰¶m1à7ÃÛ^+]G;QS‰¬Z™HfrÃÊÅfE¸ªw:5Õx»w·O=Š[Hß»áÃJ°!l¾ì­ëe˺ÀV¼lñ¡êº‚¹'ÞNüÄ»ºÁR3ž„mëÝÖò-|›¢S"áôªœc•¢ýî‹C aïïhžñÝ™½^ÎÌunÐX¥Ž^¾f@fo>z¯-/¼½ƒ‡m¾ÉßJ–[½˜"„“uìù·¼òrJX»ÚØ7Ó:"f!±4z¬ÛåÔx»Äho5K’bï3;]ØÝ_A‰d-ÔQjÀ™öR}yM‹IÆÛm¤hƒ{tÞ$/·9¸÷q'áËZ½î‰Ôv.wz¯î/%½ 9}sT8GmÖªpËöÊdƒXfQö”(s:$Û˜%¥Šé¼¥‚i’µ Üôzw,à ËCZ&óͯ¿¯=ž/–|hká¦õâ˯Sår×agÍ–kH-Ùy‘7YÞYÔ„«ÙË¥¬<ù²zègÏŽîZg§BX¼lŸÃØZ4ý VêFëÏO¸Tc­B.õIÁ: ½¶©¡½S«®ee–ew ž¬\ÃG¸vÖ%öQç/rÇ•XV«}fÚn³–ýÚ¹3>2Ý k|=¥ª‹œ¯‡pŠë›(¸ñÝ×G ¾hP¾ã ™DÛ 8„‰±ôÊ1v:™fÐe›ÖÞÔšÓF:µ·ST5CzÓß™º6 ƒ$VÒœ>Ç}@`ngFÚ-cäà{C{_ ”*cè×cg;œClìõpeG^-ýž5³Ï­·Â³Çt0± ¬®F〮µ¼ÍÕ@Œá Úr¶†K‡Ï#ž€Wš1ªmµ¼H”«-zffó«YÎYDW„t)÷¼ä‚tõè<º`XB ÏPš»³š²»ÝkÇ:Õæ¶§¢ê7ÎåÔãa† *šw†#O¶ôí7Ê Þ‚æÂ#µ¤ÇNkÌí û‹ÙºŸl¬É=áŽøì½ê^{v‰ï3–ÉsV!DfåÚÖ®²+~v½¹xÌÍ%©9¯°‚ö®PW±®À¢5ZÉîÓ”ûŠJãæÒÝ<Øá]KFn[pñ@®ïÛærém'Š{Éø*ÌÓ9 nÇ‹qä0J—Ý•·SuîÜSÍ9[·©MÈ/µ ï b-úcW˜…Ü‘qWîÔû‘ˬãÎrͦW-–žwK³xùW>·*ev0iàº^õØHguÁ€e¦.Í_bÖ;âž°æ7Û¥VÚÙÝ,Ò¿¶­ðÇ<4ÑÇ0•¼,tºo6œU/‘ãw¥¼Ìä²wÅÌÁ½àáçYÄxe×+¸G—r‚ºZÙ‚W>ÝC` º’ì6äɕժ=ë#Gm©ÑÝ7Ñ{wÊ÷ÑÛ—Îcó•¶qJ±uÞ—¨sÏ$åÛ`]Rc´=#†·mJr²Üê=a ufzÖMyÝÜVñïioŒç£,Ö®œç?[3°X©½îÝ¡ÚÇ#½YØÔƒ’îÆ}xG±cÙ´Ž|M§u'Ó7ÎÊÑa•’’«ìNÆK»afc§¦¢8{]¬¨0Ý4ü.öŸVÕ€ýujN¦LJ¹á=ëõè%ž^Ç—w#òî/—]aïH¦Ð£W­—vŠ’ÀV’¹ãG0¼ÍSŒ|M+»Œðà”¨¦þ§`d½ÜÜ)„­DæûÔVÆEÝM;+r×cF*>Ã>éóñ'yׄ)JƒG½ê{ ñ;¤ªv×\ê]O1–»¨»ç‹\Ý´2³±s¦YùåºéhæÁ²³<Áƒmß°¦Œ0¯»—µåsðÇÕ¼§R5};væÀÍG§SözØÜTx0&ŠC®Ê UúA¨­õb€H/%AM«}Ç€;`™ÅG^€ìö¿@ü`Œ$¹f­ø€ÕxÝvß= Ji›IÖG›¥ÎJÑî-æz1òÇÙzCæt$[ÁÕ³ŸucjÛ,%aè6°>¶èoØØ¾+ì=Ú¸÷pÛ®Á\&`Cyö&1µ·•Ø[áöN´hU÷¹J3/7Ük¥øöSÐó+”<#]Ìh{ùv^©Œhò(U`˜wé¶c ÅuÒÌÁ4/kxJ)@úÆöà_¢½Ög«Öb¡^;ßÅ&µœdÄ-‹ŽJýu¬~WA¤Ç–¢nõöºÄŠ!n{¼„^bY|º'Àç9X;)Ä­R˜±¢ñç'•·j Ö›Á"us†|åË|íþë“&;ê+VöÖ©µ¤õ9Þ¡F˜!Ýmœ«x é6ëtŸ°Îr±ÔÅ)‹î©œt6Èá™J]§#ÆÝÄ`j Þ£s¦Dë³\FŠíâºmÁ\ øÎ³ž>×§@:÷×wô’¯Ìùä®bjxEïLãÂÏ põât막Ùßj5#εw[z¥í(\î ̨OXâ Ûå$ñ­ÚÒhnv^†øWeb_`~»µhgåÊ öà–VþÊ1»:ô¤.\—ãµ§iáÝ:µ€Âðç}7!3GCÁÞñSg¨Ï‡€;Õqu§qÜ”7y–…önƒ@Ù®Âéí£°„ÓÍ(o½+Ñy¬¿^«ÚÀ¯mU»•øôãN3fâºQºØ˜¾€¶x±+œ¥+²iëÏl[‹¤F³kuÞ\“om¶rùX[£(.@I:þfQ®å£ÝO™Á[ã£K·6 G¨¨·°Ýé¥ÅÒšžO)››Ò±ö87¸ãVrêñ$ «Äî:ç³ù‘J…¦&Nf·cÍ€‡¸ö»¢WP=p¬d>¦yœ«€}±×`ŠuÔÛ#w—–áŒQß0ÎëìI‹˜+*bíû9ŒnÁŠ,ûfÚnëv¦ÔÊSë=®%¦½Âíç™!öI¡.d¿!POyû'¶Z>4u o-èÛ l¡g,ÔógÑ9¯O˜åÛÖètÃÃe5wfèß*Ë^w`±¬ª"cºÎ&aØ×Û¦7¤U‹/ÁO W×ÕtdkÉÖeÖ“—àÔÀ¶ßGBÔ874*Lé°E¹™›ÀoLãQNr_ı½¾cyôÙÕãyO¸!ƒ…õîꩱq1=äÃô®—¹Ù6 6[Ó.ëW–ÜwŽÈ‡B3Å;¡Ñ6¶ê4KTAÁtî¦é–. ¯AXo’Þ7Vôi‘¦¥*Õ@]¸ž ­#6Ðo¶2íu×vp õ¦4é ;µ^4¡ÊÕ0ù»›]¡Å’ƒ}—Ae V·è:jbɫ۴5Ë  Ëõ £ÕÌ–´³£—îÕCádV©@K,:؆©ÐºÎ©HùJ š·.h-Äö/^Ag>WÞ¤$êGA^ë²^é´#ŽjÑݬ, ´oåÁ‹BÞÐ]ãÖ8yGà)ÁNv®Îs6›7R.ÍC(F$íǧ`}–€U´3m jÕ)oYà`JèËìŠìà噋OT ˆ®\id¼Fn]—éÓxrîÝÔ,Áž¼'“öߦWu;@A›=sŸ+¥V¦VŠéIf Ïq²¯/Þ±Q –çA¿b×`‚sÛ:¶}®ò1à~½9µÆ?.Ï\ -W€‰B¶¶æ«ðÈvÊ—öñÞ«§æ«¥g”amXêd ]»=.‡9V6Xì³6êNê2“‚Pƒƒ$nûw*n:{ÏÉ—ÄùŽìID¨ø:[o"­ì÷­â®»¬A—Jꕚ!äS-Ùc¿s7œû–­ã¹5hJóéjÌ¿X£´ïÔœD„uóÒ8g´öv‰Ôö*ëDz}È…mMκ,+Y ØÎ”2û¹‡½œüó7XrëklØ œ¤»9Öï50Ðk©(<¥=Z6mŶx=å˜%k=QªRÑPá¬C·‹î`BêÏ­uì¼uÐùðîl—vSÌX*s¥«Éu¹moyœ|FÚ–yúo–_‘µÉzó´H´I®\ÆNÔ­D»ÚjkN±S¨` <ÍÍéÆß[ë¹2òY3ZU–[@§xt†éêŠW9ò¯gV MûÓDv‹Êí83[ˆª1ñ”…V0s´ ·Ò·3‘‹…Þí’Ìáˆ,Ç®ÐÜaXÍ+@ñv5O6¯§o¹UhÎØGSÑüÏÌ>§WèQ¦”ÉQùïi¶‚¸H¬Þ4áôÖÀÑ`Ö+Ó.ŠÜ¬00›½óÕ•Ù}Õ¬îl]J£é£¶ïªû·C§}À \pDOl‚ul%JÖ”ެ¤Òê<¢*<t®ï†oe„}¦íùUÖò$y•íG¹/×êvg>‡-`ˆ·)\¾¬ì§Æû ]Y›žA|A2g+ñ²ú›¦,v r¦àŒžx÷/n† Ôƒ¥ë&L¸ûéáZß­ùTâÂü"¨57ÀcaV–¨5Ÿvo¼±ŽBr"‹žµ&8Ú(ê=z2­)䔸î:PH:èŽÒaO*\Öâ佉HÌPÊv~œÑf„)a,…v û1Èò¿' #êÛ΋D6ÙåÈãëÙ4‹¶’ß6 ‡ªîÀ,,ÏKùç ŽË²ô¤ KS9^\.m›ŠÔæý†W{Ps˃gYc«+, pÕÇ‘‰iÏ=|,o³ÕѺt}È'Þ Í0¡Y¯y] ‘ª®“Ü}Rp®&Q.M¥«„ë§›«Zç4ª#Û®á1¼—k²U³Þ™ß 2î¥Ä;Ö ©®Öè53®}˜^%’Öãjˆž;´ŸžUm7¾™Eý‹6]eUïSLÏ;»ÓT®=×s6×ÞάMúNÝQ:Ï®å^Pls³•ÏÙ¨;$FÏr~Ñqoê5Ä+êj_^YßÊ2|5³–»È-c`·uÛSbDªž¥³Î{wt,f|¨ÛgE3žÙ:¶Üå°dß­ÊW‰d¬äÖd8o"¬¥Zs³°AgE…—aßG%rš‹Úa=‘Þuçe7=Ê•ù ¤´ª<|ÐMÁý^=È»Ëw+mÁx¬öj›YªÉwÀïwWDw>“’¹v\¾‡†Š#·]<ÖTÇ´ö<Ñ;«hUd¿—Ø_¼£åIãMqŠ–SŒ=§&ZŽe#èeð=[H•v¯gLœI÷o<’ѤWRn ß>:‘Û’)Ù{Rç*xÞUÌW]Ï‚N0}Ýs`JPÓ™Áã8“xå2ô÷ ³äêÆ;E€·oBË~'vÕDØÈÚæ:÷)Z_[éQÝcË¡îéï §1ågx„ ÞSâ!Um-C ÐÎôÙ¥e²Vé½5~¡¸Àà; Ò€J:\·]é!#<|zE—.>Äwí¢¨â½˜!+K±Ù‘ šgP.ží;7‘n°ŸQzŠrþÅj·ë§.ŠCv†Ë1[;:¼Õ–v¯«gqc6ðÅ]Rû³*+]+¨‘°Üç¡cîÌσÌGÙ‘:m!uº;ZcÞÂ4iâ6A,ó;:]MÛôͧÑî|Ž •~ñ¹ƒ6Üy©{‚ÞêšØ}¦ÌïxŒ×Û)ñ‰%¢U3Ó•H©J zÅÏß&ÎÞYNµÞSBRWO4.¼ÊÇS„Qu°Nx7ºæëÅ¡K…m5ëkO|HÚ-&ó–*ë5ö‹ö+gÄ›Ýï|:E3Sb…ô$õ2$[ S%»ET:¤â^òõá6bÆyØ“¢/~ÐM«ùV5®gªaîg”&‚gÈ]Xîô¯E\âï eî{Úúˆé6S³Ámæ Ûí±bCákµ "ÚÈ|½ííÅÉCãîÕ{h¡­ñÌ’43/Š•ÓŸ–Y¬ùªÃô“ W+ËP>噳{móS&µ&[¯$<‚KUHZ¥ö@ Dz9[k]õç…:æ_Oc(Xqžù[Vî ³pLu¹³y‹]u®’Þ˜-qXÛ~XsÉÛkY‚®¯ØŸ œ£-árÓí×®Üòˆ¥ÒŽUݲ¨ÓoÑK…ÈÖÈTdf¬:hëÞgh°Ò!—|)ú³^JýÒé«„ª_‚|v‰b¢{°m:.Ѻ;&2f$mÞr:ïå°4úÈ ®}²qî õnë:›î>IzêÒ©†Ò¼®ë9¬mËWÖo“iÓå¾÷¶î¼0õ{3Iµå¬:ÍÉ_ Û€Èûž1‘Ú»ÅEuO{´Ë6ÃÃtpO„'sbzùÝØëâÅâàW޼̥6€AÝ7z2¼èíö¡ÅÖvÁËéLäÕ¼‡iâçÅ^½Ù}%ž»-\$0Ћn´ÖíMô b¹f:•j„D‡U”ªw¯‹öCé[á6œßˆÍ«S§m«ŽõÔ}z©Wó¤$Ø2Ë't­9ºÔíݣšg+ÅÜŸfµJ˜ƒ´(>¢Œâò[Ý£V®² Іk¡:Ý­%5¸Îr¬ËÉDZÀø0Ðæ¹lë›@ºXÏ¥‡… £(.}{Ýt„ÍèLël(u°-8°lJv;¤–S:––SÑ^ÚW޼ïڪмFòúé"+Þ@)]ŒsuË(üÇVö6°J'²SÅ“Y#Æåöó¡³àÒÎ Æ›ÙtµB6ž^ù”Ë ±7‘׿œ*çQVà®)ÝìÙ·ÑosË®:Çôº”yçk÷AéÓÆ)\›óêüø3Ñê÷3m¤/k=^„ö]]”òÂædÝ’“C »¤ë±ÑÚâYœÕó¡KU]kœÆX+rºµœS ìm0›Ù‰P0ûÚòax+L#{‘­¿R½ö£Zx Š$†0b:Ÿ¯¨n ǶÎU±,¡IÜ—›Ñë>x ý0"g¥„ôüïIëU)¡÷²#eÝ«Ù/Ï©uöù½â²žw*|î|C‹ì~õÕÂ]§+Gr~\¸˜·Ú}WÄß®ö»ìjQ”ͪæ/š>^£H«ˆYÕižz.½)s0‘ÖÓ¶8ÖWiµ;v„[yCR®Ï£K”{¼¤W˜/[ÍÔu·,¾R”3–.+O]å½C°öpkï\GÂä–6mvµö±ïkÎI®ïÍ 0ÃFA™ÙÐ2À½:ô7CçÂbv¬à3NVì”ë*º·¯`0wx[ê ãNŸãpòÛsÔÇ.ÏP—CJ,nô½ëî݈3“²äN¥ Ù=ÙW„äi- ¥zz¬ºl î;»£vúœØ Tk³òo>*†7æ|Â>”½Yž5¥™¥ß+Ôkdq§u„aÖ8ÛúÅ1¶…댡½Â.âËWN²*½ºMØ·ãž`ûkgMEöôNïTꉺ¼±¸²gLÒ»…9kxnꦌ–L¬$Þœ˜„yš2 ÷˜|»YÃ-«ò‘C»q=É‹¡bËÊ·Üíh·ÛJRv¸éË“”ÓLñÎ6Ô»WÔË0W.~çÞv¼ u¾ÍIkSw=Å^T² ÃÓ‘Y01inÖL«©o– W)…E {3\S÷–W¹ï(…ÒÜUcÞjQÈßµçÀsñï•xÏCS)i`‘Ç&²Ï;T¤ì§³Òý.çÖè Uw›Õ#¾åYImK3¶f]Ò/¸ à{¥åžm2L÷!™ï/‹n³TñÈÝ{ûNuÒ_޾ÿ™a ý»„n äi~ëÙuì[Çc¾Å|{,͝^õj‡¹#hΫI:Àï¶­”MÙÂl§ÏµuaR¿ž¢ù\ž{^y§qûbkË`Ù¹,ÚÆ¶°ná‡{´.3{•F¸¦;ùÏDPzëÔŽñ7ºÊ÷ uΓIF}@¹SÆ¡\™*Å5ˆÊǹ³;ÉÁ£R-鸠fów†Gn¼­MÛ¾Üa ‚ˆµµÜCƒ|žšÆÉlñÆ2ÜTéùM«BBÏÎ[ï)Xžq–Tfò‹Å6º+KÇ•tº¶ ÓnY›_ îHÝöV§&é³·bêaß4=çKw‘õÂ_‡“¾rYB)Ø‘ÙÃ·ŽœÀ÷Tb«.}…rÖuátõÜé®®;ÊYSVçX=[ÜŒý¾¹ZÅž•êöÆ^Šº†e][r¯‚šº×ÙXÎ)™.\½îà­Ñ-»×b¬^L‰?Þâ|þöÖVÐöŸTÜ~µØ¯%uôb>\n]hË!#…v+Ú{Û4jÄ.ís-` ºÈê¶:Øã‘Üí8kÓ\Væî¯½Ö•Ô° Ö²àðÕöUÝé­kãrm8¥²R¦^^w9µ‘X{B·š]+aì¡°æw5z&El'Bî'˜ŒûµŽÃ«©Ä,âÊå··kiç6³°ËÙ’í•Å »œ‚²[Ñ´âÅ™,»º2­÷j‚¬PÆ[iŽUÇ2óm}áèkÙ2émc ñ'zy"Hë nµtè×ÙïaÕ7áÛƒ¼•K¼Ê”Õ‹—\€¯tܺÔ!5ϵ?]xÛ÷2ƒ8ÎNûWÇUwëSS<ÜÑŒ¦B…,@—L׊åi‹‹g‰ 5èVÖ€^«UÞ~èûx[2¦V˜Üåƒ2ÃÞ!•yœcMÜöÜÓeù¤:(Âwgf–~è'„®¢/^¢ äöѵÕtª=Åð¾s' ) .çÓ0ùà{­\œMm7Î]«P™° ¡f @˜0J8—hÝæ÷W-™–ÌJ¶MCºÊSm7!ž¿u—~ɯzŸ= Z®î²Ó‚à8ZÅLKà‰,ábéºÞƒ6â »­}Sa½&±£œ­Ö'½Þðuí›»J1âœ6Î'Š<óÍ~ûl¬ºz~ÍÑ¥o½Îåm²Wˆ£*Ô²®SÄÌM¶ÛŽÍˆn„Y­ÄOuyXµ…zä^Oƒ©ŒZʽ²ã¬ÈÏuŸº*x\ô¤¤l³v^O^Dùèo¼3r تǑX=84d–ëÎψ¶W1²ýá°-Ï•uù26Ú”×ÚÊàR}}k)rxû†;Š=C€Ž–” Šæ Àz•-;ðB­ ÈQe!³:µ€æü6§®»µ]yËHPØèéx¶›–0ÖÓ{½r_ÄXF»¢è¤Ìñô•Þ¡Ë”V÷ro%:”¾Ê5 ídõsÎbÜ“3}%Ÿ>‰÷fÛž^^XwÕ-í›âlêçÏxl:M8ý%”½¯×:ûÆ8@Éì{亡§ƒ®¤¤/ 1íÛ|:ÖnÊÓFˆ!uq;CµRœ¶äÇFŽcd™Zø,¥ƒl5CléHÄ fœ¾a¡°Bjó» ʵ:‹xvÚÉQYbÅ`Û­>T7à!¯)ß5:’VÓ/2Þ®)íãæ=Ë|÷49ç\bÎÕwήo¶ú’ÕVu‚…<½sÝ×cõÖF±ë7½ëS†ÏH_…ÝìêÃDï;>K9 Öê’¦‰x÷¸ò®™, ríÌÕ¸ë¶[÷I7Ž÷gÜ= -[ê32²¢¿šPw¼0dBøÏ¹š|UÕc^άŖWº<›ƒì//"ÃX²ŒòÖzì?4£//¤;Ü/aPN„[:GJ”¾ƒ5|zÒ?^‰9¦ÏJf­ºs¾Ú‡;4:í$—ÛoU]#ÅèÃìî`Ò }r•“»C-^eê‡Bé0lašMVT›u×ÌX×¹pºµÔU³wÌ9ÛÕ‘tÉrk†¶ÓDª­yÇ6e.’? iÎ1îë¡jÓæGC{›G=‰ÛGº‘®2¯¼5ZqJ˜ŽzÌdl©¢¬g…Iy¤þ;’§}ÊoªgpéK¾JQšÝZÉ(«~Û¤I»ºjqäówUóæÓfx€­÷±¬ ./«¸Q²$±Ž¸ÅsÖ¤§6êâÃA Ƈ×9Mu …‚iöÓç;Zç$8ï3&<;G“¡Úï5»/B¾ØñyºóÌ÷—ŒÃOj_ƒÉ+&"CXóÖï.0¬Þ£ ÁbÇ;pÓÆÍöw.÷žíâÛ[]t] å}îöæ3Ôc…ÈÍr*³¥æâím^ð&Mf¢ýGÖŒoze™s[,åðlZ¥¶‹µÙ–€}ª•;Ý8…87§p¢m¨äv|(k°,zч<ûehÐ.ç‡Rj¶k5­z>úLÏ æ 7DcàùòÚìOjìhŠý¾}ˆŽ­ˆ…{£†´U’÷}‡)¶i$ñˆ Ã[¯‘È]I^ô»VÞêP3«P}”K-㶘÷]9ãƒf×U©«—hëé~Ãâ©Uú¯/¨€5yÚÃÐåÛ=nÁ­ ý«R}XfBÝŠö’ú‹Ø*g Omœ1ÔxaTÞ¹ZX¨{hŽàN^rA:$fîªãªs©m›Kotj¤}ˆØ ŽiÊçZlË”©sr âx¼.n+~A%ËDZ2Öe™íó£¶úêù&ªðB9Nʆ´lß_M•â0>`>³R ¶±ð˜Z:¢5¸üQ€LìK&Ä´ò!ÕܱÉÇŒayÍ‚“¸jÉc­=Aéme*ÎÎ]³p°û-º¼V¸ª{møƒËá—r`»ÞI`FU¼ŒµÇ™XöYÊ‘™Z³š#A¦ ¢¼Ù®V½îÓ¸ï¥nœ¥BŸÃ·Êά„—#ëq*²MöƉg»:ñÂzøÊì6Sì°‹K åIu=nSº»¥É>4hN\'MÍêí<™<{SëËyG2×vH\>¸Ž–]2¹´®˜p`²ìáÝv…[•Êå•ÈŠU‡8rtÅVö:–d"m¿…y±™…Ò>®Q=ž]'M««¨nñ¢¨A‘^Ù¾}¶ítäô2NïO/$]:ñίuD©Ž˜|^rÓù—)鵓rÅÛÅ6+°ž¢åÖ" ÝC)b¢Ð:3º3º­Ì›ÒÞØ‰\ˆ`U‚… ¼·Èî¦=Ô—ŽŽS~Ýq{šØ=Lf,ëÂîúˆ§É ]tq f]HšÂ·6¶Ö?>ƒ&o—ýf¢¬…ßHAk§Çj­­N÷Hdz};%éñº(ù‚z²œPzI.*ézR×}ƒ*»~[i]ÎËUÈ>JÅ!{nUÆÒ¤Ùn˜ÈnôÚ.ud:;òwub>à;¾GÚŸ’Ý]I¯½—8ËUå¯ÒÒÙMñ©°K¸cº¼ohU”‘»o;ÆéÊnðΚíB8̲_PÚ‚ëIЫ(™E X{S5¼®ÅPf=ÎÈŒ5{†½|pµ©2· /Ɖlrq«xïho*` Vä¼4×ö˜ï?§³ÊÎàZõg±™Ï{xס•Æ&NêXÜÅšÝèÂmÏE¢¶¯‚è9»™VÎS ±ôèU"á+ï˜VCíq×fØ£ãy%©ÈŠÙ“Mî|C¿cõIAêÕ×zÞÔ‘nÏuÉ;°«#k!™Ø®3)  :ìAAâ9X"“&ÃЩÛKÃ9ðJÂÕ9mXé•ã×à¼ø úSÖ%Êc{gk°ß›,8r%71ÇӗݹœkFyÕzñúüºWJ”œ¤)È£ÙFFå7ë:L $îµõÓºBðš¼ÞºÜЍŒìè¬õ¸ò Í ï¸Ý)nU¸ ã®92”ëˬ³ö§\0*;cuR»ÍÒ´Ô}+ªðl¡+÷T ±¹Ä¥wK4%VäùaE*óÎá]•'•ƒ¡¤•µ[™×ðæŠöfWiïºéÂ-“ã0¼×w[ØÎÎ8Kàa©æò\ít®º»Z»@ A_Nµ¹ÆwcÄ» ‘¬³tï+H(7}õèìXvÎôs8sÍ`BÇT^QÒÂõælã=­¿ÝfîfU޽h ³|¼³Ù¦_žö‡zEõ:ºttÒS¹¤ìZöU–kŸ —á[ç©|ñÓžÂ]ÎQ©@¿ËYýîüȱÜgç)êbÑ~ð½ò©¹]^Ú‰%Y)EvíˆiÆj”ÁŸvŸ…©ÈÑ$a®‘{õ5kŠ!Í*i·.¡w3”íì¾¾Ù'×½-TÀ¨- ·~²ž”yœ}²Ë¢Ï¥)’—Co rÓaWH6³µäd4…¹)M„,{ ALë ˆ‰c™—B£]AAEýѪ—­ÝXðÙÔó&kÙ}%,FVÎ2NKz/{+ʚˇkºŸ¡Åq,é+z¨˜Ÿvmq]—ιEÉÙV'¹›±Î-Üøó«JpøP8åÏ­¡˜©o˜m^ö»öõï†[‹‘"ötéÄæ¢ó/‰.˦íÉÝ@b©¥­h²¡NN„Áë+Eåe"ÜÇ™2ŽçH¬•ªWÇݪz^ùyW‚‹ yb!î÷«z«a§îÛJí NÅJ4¾Õ¬.n·¾•æUžßKÇìTwÑ&²vwVÕåJ¡ `pÔk{Sè½ê4ÚåÈ<âÖç¬T[„–s}¤G¾÷w&¹5g²u¹d<µaê¬é{lÝËÝDÌÊ‘QçkCŠ‰Í¾†“j†»§:¹¢©ÍSrcçC`/€ÜÅ«òX†³ªHfO¥â%Px’‘3•N,ÍSÀ:Ò ×wwÓ~Ÿ?dÏ|%å\Î÷uYg•? ½ÒèU¹жàC§¤íâw°l$JF ZÞÑW•›2ž·Ç̳—á¨úóúBuËDzÁNó„¡xöW”ïÌ_ ‚_1…„PrwªîiÑ¿jº).£íË}Å0z=®mܨ:i+Ûëæ'Â>º oOs63,g‘¹é¥¿T6»ÌeˆÕÜ»³¢¼ñŠlRaÀ-Z¾h—OCLk‡ÊU³ÔÕΖ¢ÔV¥dí'†Sí:DÛ´/Å!’&P¬ÙÖùå'¨áÎ۬WÍÂÉš­²—s¤iÔ—›‰ ®fµ„ñ<"LüK5ÀÍN½}ßRç,ê]‹×ºv‘iO³DÜGs²ÇØ æ®°˜É_ÃÌ~c?Z$´~óˆS¼%SV«—lo YÉùîÇÃa‡ï4uiò¡yWh¶ÉÕ7¼áw:¼êà :R>ûØH9bÞj[Û¨,pW}{‰TÑfÞ$pR3JÒÛ«×+-‚¸ ½bLø7°ûA”|_u¯QXôÞ›Ó¥{Jâš–\v»Û«ƒ¾j á5ƒªöQ š—FøX1Fw?\»òèžß_¬æ6n³+ésâwË× \U>¡¹Y‰Ÿ£S)+2#Þé–wÞOºw…,÷"GÀØ e,”÷^¹»,5—Sw7¹¾®òš=#½éylZ¯e÷¹O;¾°—‘^ÂJ÷p¬6®®øv°2ƒmýÝ™^†‹—«Vl+62‹©­"ÚõêÍBŽÖùyRUëâ«`zégn —Ù\º]ëG¸ïJ὎":« $åÚ“g¢û¸P‘¥á«bœPËq‚Dâš/-xCY ¡èƒÇ«»×)^Zw4×uý7°´úêͳ•9¶9õ.ÀÔ+ñ\Ü'Cºg–=ÕóI»u´èçwfS/¥X,VžC•’1æé¾pÂ]]A=éç@ÓX% ñrq¬5¤úì´ˆññY¼Ñ“v‚ù™Ùn<®]VbO&çÑ9‡w;6…]Ä«Kvlpw#)óÝvéÜÑ{ö‹í|ßf&À•™f‡Îø¼“µwÚÜ}RW“G!çÜ;BO3ãÔ«¦öqîcÁ‚!4f'´#!bœ"1a¬„(ED Ö†Nb¼knõQ­F¶Ž[DáÉHùM—ÍI:ö†ugÂÌݿus–f×Y1ôu¬ ì·£…Þ£*Ã{ìCèG=Ø"p<0L9 ô¥Ðê¿xvØ¿EZBìý§'…êËñÀ ©Êï8ߺ ºKÌœvò½Íb«€ÃkuãFúñ˜îùáTÏ&ùѹÅÈo,9²·¯è„i2ö–àæbòݵÕ|Êkwm®GÚ_?ʦâ›`î»÷=––S³eòãÍsÝ3’3EÀ—½ã•ežƒr]Ú¸†wj©Rá®e‡‰g- ›±‹´Š+Ô{Âö’„fPtĬ¶¥ûm©ÉvP««Õ$ÂtáÜjw¸Kë×›u›©G…E¨žvrg.n³c« Dk:N614<;VõËÂçL4aêxú‘¡\±-˜·<ôsSإߗ›mmk ÄFûLë{Ýt²BŒ,Ý\}ªèRtͽé9²Â²p7XÇ/¤ëœâÑ<ŠÛ‹f)}0»w¬ É®-^»ßzO[×R£<ÈðöÒöïv¹©3qvLmý–$^RûÏrï‹ðwÏÓ V[=6¢û;ÞY¼ßz•Åä¹›ŽTá‡6\bÁÚ¹¿rýÏzdž¼\$ÎAöoÝ|iF°nç'äµ—“”†¶¯ko‚&mÇzB®™v»©ê¡ÎÞØørlîªÓxit¥Ý!¤ßtÔT‰¶á€u+àøŒôI,º›rXL­Þ ó5+q}zn͎ıÓéb³fò[ƒ#§U}`žåwNUbôvð¬%­V+æ›O¶êÙpvóèàú±[+/2–×ið‡x&ØÙ6Âå-Ú×–…•)‰QhöЭ};EAÉZ SÛ“áGAÞ¾:ðmÌ b¬”-iðËÃÛâ*Zy_|¨½Â:{cÞZ+-—ñɸCá[³J»5#oy‰ª__:±<}ÀãI])¼2&ýR ðÓ¿5Ks“vÃÎá8œ´Ýyâ <;]s4¨´y¹WAËLveŽ®Â>ÎSsµÚ¼èWo±ÑX±’Yõ61ÎïJRådš™áÇ¥vºéۥϨ5{¢éV'¤©§©Q­ÐÌ\¸§Dî[f» î«Ú–¹Z†G­Šv.Kx-U×éäÒ~ЬàDõàwÛÃ|oõo– VŽ3J—²×¨VÀÜÍ­W±H×”Êíʸ â·xòJ~ùoáƒv½íê;gÓ¸?mGÚO5MÖ ÍŠº¾CÙÕÔ*õBå$0®=¸{‚´gB¼Ø,ã›Ý ±z3‚;tÚK:‰}@JºÚ‹lî;Úƒz]¬Ëµ­ÕÂæèå;1¢ZXP¦6ïS{;Y +8LïuÞG,i bV¼ì£îër´(òØMf™}Aó:ô^Þ®Ý*ÈåÃ+„7»ÒøçE‘A»ó}º.ŽòëN`0Þ"ÊîTlòy%׬)½Ã‚ Ê^#€¦2Øß *„>ªÛôì—O-zÛ0ße{çŠÝÊTÀK@É ÌòQ™6%.¢§J–{ïeL¤† u{­ø:–xfC}ð´¢Ä3kM\òÃw·=AI**;ðkÞÙ)‹˜]4u•x¯x*œíÝȃ—mg]îK#Ë7Ά0¬ €&‹»'çîØÉ–¿N9l˜îˆi…Õšj*k^R‰ugËÀ§c•ž »ðÕ‡@ž¡­ ѫӭ7NwÊïÄ[í÷.³ÛŠO=‰æ »¼Ú¯{hüc´®æßÊæ`¨íÛÞ¡’sº)kv.ëbî—ßi,´Ñgj6º&àÀ)7s—Õ¹ÉÎÚfLЮXL2àá& šô¢7ŸFûß]¶ÖØB:Í®U‰—îô­õ{0;ÕÈÈEGnazò\¤seáë[Ù‘ë„ãè AÊ¢øî,–¡£¯è’ÎëßA£VKâAvýÊ÷Âà¦×ƒpÓ{ax~ruߣ½sg®ÓÙOð]ãÕØÞÂ~Xíu{% HÑ“/WÊöôýº›£p€)Ñ 6 W:UËWZ³´cÚ±Ò´<äеŠ_XË{|8 Ý}”FiÎ]¹e ÅÊáz݇{dÓÌQû¶ƒáÖC\Šw0 ]õÑÆu罬Éã÷|eɇ²9›Üõ½Õ™oZ§¶zX™Á¡ÔÊÕÛ]bt‹¡ÐTæb‚—=¿˜'‡Dfª<ž:o²S€f¬d²D'V‚¢¼}…_¹ŸKV3z!,ªg¼iGHl;•ÎxÞMB½Å=ÃÑL^O:}q{–P÷³&]ÓIÌ‘ä#`È/ïq ] ¤â¼»¶«©”~Û¬¸áXiRˆ½Ìs±&2‹Xü†éů;ØéNî5á(o¦GiîKïSÕ'£µj¤Ý7\¯¯é»Þõô•´ÉÌÏ?9®³}åä~vTPõ¾îfsÞêHK£¾wÜ—ª¤‹²wWN×B±n½§×:ˆGUÅ*Rù¾YoU a­UosOL#±¸Ù£.Ö-^eG$ŠxìĜƳXª]ÎÙZ¨G¾ÓZÌ÷yâ|îe£s·¸ÊÖøs“ô7d,7s†Ô­wY"™´#j{½]÷w½]¹ÝØÐÉ\y¬I±êjºl ƒ»·||n! ÷£¥ xü³Îv›×Å ïs8+¶u`§ÓM×'9s§t”‹¶ëŒË~¬QÊxi@îêã´­Û;Ë¡(õeêSu^  ‚LÎm¾øÔõ­óפzý‰¿eMU“_oj‘7 EÇ»¯/e ç»[ëåÕ #–UõÖ»é«+Òûcy–Uå“…K6Ä×Q¾4ƒnè{/ OE%ùžŠÓ‰]4hÛ Å ‹ÐÅpë"®V:§Bœ|%¹Éwå) b´¹‘ð¾´jú½íß=*ø.ƒ5·:0âfh¢‘½T…–}Øî¸Î¤+>z=š’ÉÚØñ£1ÐxåëLPúðCà´WZçwêCzœ3+ßd!úä¦{[Ë"eœ‡kÔ5­Î‘ 1jQÞ:D«E¤æ…e‹ãïs³™G‡Y‡aÚ”[Åîà§,S5ÑáKp_ô¬@7ÁÒñR#P­–î¶çé·êÜCµ±tê[­C*uÞù¹xîóÕg“ ­ÝJ}íS'§Ïë$ISc¼\óymѱTH5‰“ wºÆŸ¡[WWê^õÛ—e{Ëzs/:ýW7I;’•'À­s¤]ÉéÒž Óº2{«j+¡:j|GUë—K%ˆ©XˆøªŠy£tsCgšô÷m箺•ôcJ¬Í”›Ò£>šß: ÛÄE^„=YzjlìÇÄ3Ëå]ÁCBwVßNvNÚJM†;öã–{`i3)Èç¬ UÙZJ«ßGö4ÞÍë9ÓåÒó§ã˜çŸ—]ÚÜ-fËIŒIÓº¾aàMûkpe´¢ËèÊC¬k=s_3€»¢^!Nºî%Z‚—i¯Þt×l½õ_RhøÍ—›­+Ì&tä_$ ¡‰Éï£C[U8m“ÕÔ4¬BëgÞ3ôJ¥å>´VÖu?,«zѺDø]¾ƒ¤À„‹KLšwì§±q®—Í;.ÈDàô”o¶´«ŽGš·Î}İãÕ|…о]Xq˜¿]ßëµ3ÙÖ]§žjBUδMåMC±&ÛÅÎææÒʃ§kuÊ!×gмÀÑ¿Í7×~6I§íz$ ƒèÂr–úµ0F7€fú‹cÜfcÕ›»KE—iɉúh~]M Ÿ†à§âïÓ0ã›Ê†ðœ4ªî‘/³ÍfBF­›´ØµZòÔ¹‹c»kiå¼²¯dø½l鯅èeÅFùc•ÑÙºXïo32óx;%9½c¯o)Ÿ eì…õKÙä󙕾ç¾ãÃ…»9Yåï™±1ìÚs±Ãko|owN42×^t«q-¼%5u$ÞîD¦LAÞò÷›*Ö(2ßÌT‡¯pX“y–N0ATe'bÖ *–”é2ÔúèÜ­±Îa gs9`ÑPx÷¢#åeõdšÑÓ&GÅr½Þ“­,±»©*î&·i©´å‚7ðÚV_…dÌdhÌÔºeÞìxyõƒö¤è¿„¨8ú|h‡%å¦â[X à/ ‰®jð‘*9¼DfåÖ©}­uÜ‚¦ºÍÓÆô&«^ó4•ëÌÖ²a½ ¶ÅÚ”f†7[¢ÃÛCp»3ˆæG0E›°ìר9àséPx1N½{×7¡ZVT7¾K SjB…ÎC"cx{»]CW¶é¨FëÕX½:nw«Áq¡^®`¨˜6£¾öÑvN»j'ÏO˾5q2ź±:è_¬xÌùåQ+YkXÜõœL.Ø-@WGÛjzžÄ)uó7Õ¢±áÚ6ÕÞÜÎdÔ®ã/IâRà£(ãÜ©‡eä}G¸kœ\¸¸JM¿^×]Ü/K9&Öóµ÷ˆ÷©Ã «­ä "ì%xçaiÈ«.2á!<™ÁOÍÒ±Ö·Ñm;=dM#"®ÃY©+ÜF¶äzÁÊažºÆ­¾Å`×ó?’×-ÑéÆƒ0xʸüa&KíïŸcS æI¬>¸µ]µuÒŽÛ›¢G%pKÅ×»4dÂÛ6KÚÀ=i½å7÷«4Nßsü µß½ÙMji”­Ög+õÔSNw6çÚëæ®ƒ»š{r (알O)××5LWAÅ}Úð|›W]ͳpvâ¼C~”ý1Ì’ªò´"}äÌ“L A;B^`i®*O.úWEv%ýÆo»xw#Ã×wÛŒ«T}{sÝÔŸ?gM|ç’¬¨3ãRº6zz¸mE)4_:äÃÏ%‹Ï7Û†Q£ÒvJÝ«²\Z¯äéÌž’g‚äTÍ£q£FDg ¯Þ]ï»7¶Ÿ›Ô³²ÅŸSƒ/kSMvR*¬žï+¶s£˜%s³jó--R£¾“.nÃE»Ô©pìæ1‡pð›ˆkØ&í‚Xksª÷ ‘ÍÅžNþ•{àêšW(ÍgU¦·'gRé71œ‰ Zw–8kWs{ Þ“†<éD5ׂ¼µÑ$NΙ„¼)uæ-–ð‡KIj¦)ÐÈA˜n=4«Ö”iDʯW]fï©×–NsX„"’CÇ}¦¯ÏŸJ‘@k¶\ß,æô”¡›ÍàµJ0s´¹ËyK-ܘhÖÝ’ó*˜=¶nÁqj7A1µáo¬º·5½ÈãòܱxD´S8v²¼Ýz˜•‚.Û\³K” A.Ûj é6òËÊëc—³³»Ý7—§cE çéÓ«›žCêÁa»+*zÔ¾¦öÛ3;z–&nuI |¥wÜÚ;Å»k§nny®ëvòÇef«¥;Ý:Ûçy­eÞj̓à¬\mßpй^1ÛÝZæéÔÈ“a?Ž[—¶²÷\ôÝ'Ý­Ü¢/o¦÷£ÓeËPå1À4môec~©cªÜ+•äˆ iõ mmÌ“qÔn‹¡ˆi T©ªV04ÕA/NÚçIÎ¥§¾×Ù°n¼ò¥PÉñ»º3£¿?º÷ÛÊÀÜ(Jâà–uúæ<4yrðÆn¶“Áç†ÂÔ(ȽkÐû]j~[ê}Jâ)<«€{½yÍV‚¬~µ½Âóáµ øqïć{=”æéjz¹M~}×ï(o®{¨Ê³Ìæåœí ˆMø HÝ)~Tˆµ«®ÛÊŠN€]K…¤Ü^¶Ü *Ù3–5ËrŸ²îvPW¶™™]5^¨&lV—Xð©]Y—±o:>[àdioŒ40 UÄæd}°¿ ðì5-bgP)CvÅî!¿Qt­d§cÜýtÆ•ò'!ëéð†w;ÎörîWéÕIî˜áTDzæûsÕÔ¤ÎðN*ñ]PáÔ6õ#„àx¢kÖ«Åá¡Z«ªN³9,Ó'3gdÅ’}`Ò GqÖ3M;×jÚ¾¾/v+ÒÍq/O] \ 7{bÚOî,vŒOrïä>_ÏAóýÝG/^Ü7€LÓÆypù.wtç–—KN†àÌ&jù¤¦ñÓ)_ 8<4ÝÕõKS >‚´Ù=Muk*¤·{:ŽóÚÝsUÌ8rVf:]wÆ‹ˆçØbÜIØwNfsѽÇhtÕRÍF^:LÞºên%o; ºF°îGÖXF¸]Ž’‘@®/“%ršÛ,æ÷j·O˜®èRÒ¥ê²S3% #¸‘¢UËu·NGQõ±«¬VV\ש*Ã{`® »T6w˜´c˜ëFæY¨Jsk)tÑ•¦µ¡<ôtoYÄ;f +º¶ÅZ–÷y+ ]1MµY›IY½çÑ!wÎSæ:*åKI÷[%šì–J¹u¸%‘uËùqñá ©Sqò·­n·¸R®ë´ùpÍMmŽ—MЭ>î.SJ¾®×móË"hÑ‚k2±¬Ï£½Ì•pÛ¦9hÔÚK‚AuòÀl»vr¶·° ÇJ=Ç«‡Eþ§êû»(m؂؀F ÆZ ÈsLúîÁðlA„lÑvªþlûgÊM|øHF«×mK{0@jؘ—½Q!™}-.œ¨¼^ˆµ9žz„ø,êg•<3m2¬»ýWŒgy¡j¶Pîí­¨õÅ:Bu¹ÄôWÌnéäß[5h\°ùw<òìµMbÏ]pµ^Jí=¼ úRý™ö(œÇƒhJÒåù;SÆëÈzùôß!¾Îý7ËðÁÞŸ?„ˆ‰cD|YRŒ …L· TôÝ4¸ì%ôw¤˜yÝMQL»ì3¬,¦÷ÝŠ×É^ÄwLéÜG#¿2¸5flÐ;¦oúKDC2j7F{¡äkcGab½ï¶Æ+Ô7‡Pªú4Ò‡#“”©¨ÅÝ÷y$«Štó.yW®£r¢þòÝ×jáÔ2¯” °.äóA¸ufÏJ–äî˜W:É,ÚWf¡oÓœße$‘¸»Z„+ŽÀÌÄvæùBe –…qÖ¶ŠôÝìkzt¬á²Þ!´Çú\•îmÕÚò¼+Ázâg‘ÜÔu©õÙ¥¥­S³f×zñ[xèÙaĺìõZ隨L³©öTëG®Hì) ‡f¬ÏÇÂxQ÷Šóõ"kªÚz>¹ .L¼Çâ.êåqÀûH¥×Zï+T~]Ååg„ÑOËÚ¯ã%Õ÷¢{\kú ‰“„½×æ×«lŠç,³XY¾Ó).XîúÕî›×<ØTÔõ”@绦VÛÝÓ\¦H¥4@’ÍÜ7•ïWOö]¿_¸¨Y¶Ìíèar®Ü¢Önp¡| V:×^› aÈt£œóBROQ³êlÍyvì_Qè°RoÌ· :¼X#-Êä…žÕB·© c%ÑÁaµËM ÜöÓ­˜zP VTV„ñ9ÒCí·~ÒNía­î£Öu]çQ¥d ¼Þ‹{Êo>Á3Î5O}j©òP WÙ¢.¸6žA€p}]Aý¤efºÃ©ÉÇT‰Ü§³ZÍa`C…a]¼2c”§}ׯ YÙXΗh湉&ƒ%öLS°åU»R5ÏQ¼K’Õm•œq–®¶þºky(të¸èÍ .W[ïM\ÇY½'ÙKÜŽ&ƒ9Pë2ŽX‰ÕÈc³^23s*sIº‰Êœ:Z»ê& ÙFW£EɲÙgj^ÈÞq°Mz,\­­w‹´D¥”x™Ù”î¢b¥è Ð=ç¹®çl zL¥Oz½ó ìó®®]¸ú=Z4g;k¾ýeû(?ai{™´Ãa Êiš×)¥;¶™¹ÀaÂα:²\v†N¬7wO‹éLeIEÑU¡>Qm³›ÛJt“J+®]6 ûÎYÁ¾õxg,V`îckÃvqt¨3tú•âêìš.ò§ÍÏÔnkE×WœÞõ{Zjé`ƒkµ¼¨2ynQ½àvÀjÞÏS|·ô;1]hOd¤êóu-êÏG'o‰È9{éC^~9Q(ÆzðG9)u¦ÞE „$àÚTµE³º'Ü=/§–èGÞÌ#.MÆôšлË+ÖyžápJ„,Jƒ¸÷=bvq×¶ý¹®TG)Í·P!岨›ÉÙÛ!Ý9»õæadë–Ãu¬dBEŸ½ù~ç+îü¬ðuÀ;Ü®é;Zù䣕¹wWnUH–ïÖ¸§Q¬Ó(VV iôQIÞºôÄfší<7Þ,]Šy¸ýœ³®˜.ü‹'c·YÓÙ˜g:±äk:—+µžÛÌóG-½&è#£_”î&®lÙÑï`Fõµ>€ý}}×y¿k%\{÷*“Ë´R@ÁYF®á"ÔPˆV*ñ]W#¢ÖÁ,gr’wjÜe+µÓXÑÕÇU£@åòÚÈç‡]òV}¢j€L -r£¼§)Þ,#ºÂ“"‰5À±¬ÌÖuîHÞ¢>X^*âûâå+k‰Ú6.fïÙQb[ö_YÇAMÐܰ©S¹˜†jƃå×3w'›+ÏUøÞ«ŽäÝš=µÖÝ«paÎI¼VN—7ɬËä°é§Ô8ÝåÝ\“‰U'¡ èî†Ó %Šà©okºÕªr¼ºµÍ)“’+¹Û™Á°]±œna—£´³Snïj/“op<{Û4ÉžtÅ ~J„êÊîÍ/œ¥¹ÛvšÎ´­>§ 87Ú€±ë¼¿–ƒVޏ«|Î2…Î묛kؤx÷“K –ÝêÌFË d­‹`ÕK`_Xœ1,Ó1’%æfÉpжßju»C‚‚×·‘„j­çakA¨µ`œ­¼Ë¼åiª‰¬¹”ÜÚ•|{uº³®r¼zfcqŒ‹søÀ$ðÄN6*ï¾7xh^›*t~Û†#B¼çw«Çô ÷ƒÏW¶€å«ÖîI¤]6½ûqÄ×~ÇÁú Ÿf ½íFõ½VkŸeà›šÑàâ+.èŠ]·On…á«çT¼0Së±;(JwǨ©Ù‘••¥‡6\£1¶;µwƒvÂÃÒ˦Þê]¼‘Ùt `’Ÿq ᣠ-Íö=¢ö‹©#¥Åbâ÷w³:Ss«ožîL/€G>¸mÜ\k¸Q3^¼’cCîôíÙ=n³… ° w’í²’´—Ó¢ Gzh;0òì)Þ®”)×eÝ÷r¤Ďf+©Ä Š+m_}2ç͇Íe£”ë…´õÙ©Û÷z°Tíß){Öö^7Öuà “¬Û¡ÈŽ{*ÕnpDzeNi«e?¶ÚcL4$õ&ߌ·»ì±]i ÅÕ<úíñ££¹& ®¬ëÔØY, :Ód3IÍZŸuµ@ìô~»oÙ'oĽ‡¸Z‹&у)cy‡ «¡Àóžƒ}íö›iæ Ë« º&ž•³>ט}ÜÏex¿lUåÖ›ï9™¹‡ë%gmïYôj"u%·§7NSÝ£,Öcg{Âú¯`U•+X~g!r†5½vi8†ÛwaÙJ;o[¨¸£z&)Õ³CKB9—ÚlìÕXºcæÀ kîE.–å¬Ù{³@/Òc¼wœ0ɳ|p9‚2ôVZ)Ã7vréÌX}Û´G }½C½ÇžòÐ fî\‡[TRGDY˜nðüuÄð^(¹ öY!9™«¶ô{@:†SWiª/oE%­Ùw»×Ým4¯š[ï÷Yc{·¡ÔŸ)¸ò­«ù—V’*Åv`åPýÇÔooÉZv…Ëk¥¯fÉ­ý»•ª{E鬨MlÓÛ h,°Ô t”ÁÆ¡V¨"ñÍ¿-ݘžh½3Êæ6w³3^ÚîÀ•Z"“Ö’1t¹f&>±*+|!Ú¥GÈÚœ;‡ÓO¯¨WZ{Å›“¬±^~lwÊ Ôð=/¥‰kN:tidHná}ÈåöZÓ’·æb/­ š·VÜ´­™F‘®Üshún ïG¢õP4º¢º”©æ. Q½|Œnݪ=­cÐï#Þ§)‡ÕÚÁOÌùex-i˜,o®»zÝ÷dä±kºzªÕÐëtµ÷ŽH›¸Ê‰Ž½è»MÕä¦×*rqÒ/˜²®CYzQb¼IgsŽJdïg_hб“.ç8Iñ”/²ÆeAÐÛìÐ:ßriæò4  ªùsv©#>»`M‘³•œyò@P¤ƒä&GVÃbÞ]ÕíÞ:€37YAR¾Ëó17šY¥gšÇFn ”êÈžkÙ‹—jê:gÉo–ˆž8{]Cº-.Õ…ÌX …AI0T9btÅXÆövî"ÊN÷*ø:™A“½½³»aéi—Õ‚:ºç‚»sÎ×C;A¯/³ÊëZ£^Þ¢-€rÎã)ÌVâŠT oúî†å½Ñ‰o"†ñ=Éõ+Ã`wú:¾ŽC§zÂð^­·Ä·… —ì nÙ6ƒªî;f…`•×éL{Ô+u„ç!yqÊ7Åsêe#Š^ÄvêæoÙ³±:×N¶î»+¸È¥¹›ÑKfÉOºRšâˆS©Ülª›š€Ãg w "å`Eüíòî=ZJ?×+¦ º÷QÔ¤Ùšt\G36Í 2¢­·òSÖˆ`Ñ/«,×mTÁšöºì[§» æfÛ]2»;`™\ä–ľÇÓC‘¢øNfmuZÞêÜÒm ._Âg|p̫ݒÍ×›¬àVà¥}`ùMíõݵÉul‹³¨9=Ê&÷óàz®M‚»ø¿c÷‘ß×ùC¿¬õÉÈš=E7õ‡rg^®´à׳~å/D™Âný»ƒµ‰¬·¼·­ ¹.³˜5ghâ/”E {.…..ûR/k-\q,Í5N“Z™³žêÊÚÓòZ:qÑÐzRõRcë8ü€ZmxzdßNïKóÓ¡Ã/ÏÏz2sÒÉB?ÓòåcG®åy§–>ïWQ~ vkáxU`öŒO4 ´© [Î!ìsÞïw“7\fÐÍóÌ4þ“*h^µåA²zMx'rénVœòhg§s#/{Ž#àuõÝg°´¦D¶Ü¢yu/"ûÀznÚÇB5~u%kGÍòohUê­¤cxDV lBë„6Î@¥jK•—ÉÍèvú–ô·³66å%vn]…¡jð‘æóÇ/ž¡Ó ‰%¬Ãž‰@©âgi_sYH¥U(ïÌíΩvùâ¼”{HX˜NJ;œÎyãì®÷Mƒh¿'ƒ#×= ðs¶Î}7™0eëqho‰T!^Œo푾¾œåÜ´:³¼=ÏoO—¾*¿Èï×|•hIòžNþìŖ΃>åÚ'L«Í;\¦á7Bº5]vÎk©¨¯eEÚrôQqÕöÇñ‰çD£µeVŒŠNÚ]óΉ5o¡[g«A²°euhɃ1Ô¾\‹Íy–MvÛn³’ˇœü*'n•ªë¯v–Y$ŒA"‚mO>œÅÅu©‹óZÓZ'Zó­ ¡j¦"^ŽËXØtêrã]‹Œ¬+‚Fî0Ü«¥o|s5 –}^æ¸0âÁ›Ó- î±ÌeÌH(ð#©Ûy¤{1n= *)§{¸ ‰¶Ø¡›q=jýïKwCV‹÷õ—B~¼ḠûÝÇ —3)~=™ÇW—½]Û&:&o‡±îÍÚDBïi*†·×xýne{Ð7tK#½Øå=Êñ7ŸV{º8»BUÏ+·£¢cÕVXŒ ÎÂ.åvmX¬®šÅ(–ð(î¾l䙆_]ÉB\‰ü%<¥ÍŸ+Í]hðÀÓWRí×:»¹ÛÛj®ËÙ †£›rºñóÍ·Îç%ï^à*pâlt‚øå´JOäåå'TªììíÃ7ëYOeÜËN“ œú7v)‘Õ¸mH{=Zq¨|ÿŸ}ôo†îÒ¬“Ç=WÝcÂΨ…)fK®¼]"¸ÑýåÞ¿k››\¶µš¼G^âÑçP‰ÈùJv•Å2žB(µ[— út†Z{Ï$ê˰åfIÑ"¼Æ£Jõðxž ·[Vð|¨=ÙiuwÈg\ƒh{1¿ ÊÛŽâØàfO¢½³k¿tÌ¬ì­ ôèi§m‰¸{ŒFþžB®ðu,î4y;÷¶éØf¡G:+R#òÄଲÎÛ®]Î. 'f—³-˳¹ºuo{4>pã`iqÑÄtÈ‘:ZõÖc™1äk)`Ý$õ{ž•5úë«6w»Ø ùI+S¬Zç9CHœkZkO§XîÞ¶ê ­2žV¨7'”4vžnÊ/¾¹ÏÚ„k{ÎÙ¹µ˜¼ê7íf»TO®Ì¶U¼šEbËx{²ûKR™,ÛáíB¥ìhõ†zSí«îPÐós oÔ¥n½ê3k{ÜZÌç—Є€=b­¸®¡¤q"–©šr÷®ò.ö£ o½æñT^’[ùµvRë?vÍ7%×]b  xçd¾å@rÞ¬Ä-UÖܨ*Nü/'  ÛòOÛ±3SÍßÚ’e¾½¿rÆwzŸržòÕ`sžWœÔi†‘g…dÕgËU~«èÍz…âÆû¡Š†Ð½v‰¬T[™Ô2ò°ó/jv†zÝ?E7 ø4sL¿¶önÏ!Ô…®3jJ¼Í¬EÖm¯|…Aê÷zÙ ¢U¢XtóÀÓöWNC˜D5¼ÚÎ «ðÝc±îFýçë]¤/RÕ¾ú-A]“ë½Hv@q3—K1×~Ï:ÈeÇkW¯7ç{gfºpöì3=è›§WO)àÙ[ÇîÕ|\zVe‹«®ó’.SyØ€­Wn<ƒ/Ÿ>¤ÖÎ+‰hÓ@%*y÷p5£ÞâN$oú¿Úd_‘ÊÞ)”qÓt¼žKn˜«Y€ · ™¹¼Ïw®LSvùï*åàW)»Vã ìñ«áà­hß ±ìZUa¡F¯hÛ*Í,·½œ¸e,ɧ……l€Í,ìM±ÝI£Øu»Á`î[˜¯haåx9Ž-;–âÞ GÀï*ðë¨,âòêÒóü^a°,|…NkÁüÅ7j… ÔFÄ&š8½X-Θ¶¶ô Ræ [“—SÖ=âÞ4Úó™H[õ5;{8Î-žw†¸q¼š@¹Ó }}d ¶»!Éváð…ÑG/Mº”bAéa[a-…,1h÷ªéÍÌܨ½áZ=Üq¢3tj¿u?v¿Lc`êg¦²|(åìËZůk©§¥ @{k‰ès^gÊÝ[Çá]‚‘ùž”涃O¸I1kFøzû"'P »ífPTÕz¬d0C:,Å£ƒ¼»ÖòaM§²rÊuÅ;òBó9©‘Ù&ý¡ØÀ4G¹¢ÓK¬ív0`^‰Ÿ†¬QX¬ûÛÀ¡Dñ<Ÿ]ûtv(/dyØÊ¸8S}¼ê˜Ä6Þ>óì!!^žkÈü‘Ó˜O3Cn²+­ÍÀš=»‹pâ¦ð®4Ù©ts“•™…+›‡KÝ.qš‘y ˜ýÓïKËòÁåש‰K.ìùöφí¼Ý´ú[´1×-»ŠJÏ<–|ãóȵZƾԽx±˜@Šh²}VUxåt®†T¡ayY¡\ío¤“ZW¹ÎvªR«á ^eq=¼÷Úq™NØ”ÃOœz®‚«7%*í«¥;ëvWHhÅÇyM¬¬½=œ wÓ:º¶b²Ñò¼oYÞ£ÉÑBœ'hÍj³aFЙ~B¦Å¸€ö…&x´èi¼:/ÓÙ^Sx×¥[k{èá²»/¸³HÈn°Zy\QQv+¬vJ®Ð_°bînôKçë~Êe#î½SÁ\ã #]à©Ü²éhTzNc<÷Ûu¦ºÈ»“´sÌw©C«ÖXºA/¸òaá <9U‰ë£d]CŸK–&L]Û††,âq½¹áï †5Gªç]wžÎ‹Â„" Öí¦h¼=;;³=æç–%’­/máb¦¾e­çG8Æcˆ,•åžóšè©ªë9Ï&Ö®Øóvåvù4&Ñ6µárᮉ PéÜÞÆÕcÛÄÇ=ÊѲ´Wù5›ÂcüýiŒŸ©œ~– M¥]Ù‡gà»)ÕÞ ‡Ië›=„¯•ùÕZ´Z-]çóví¨¥\÷àïº~ Åñ©Éª^ųכ4òµ·œpÑ¢pÝê–­ ì°ê!ÕØ5Ѿ7—ŽŒÕ9w?»Ù4Õ¶n`ôÑËŽN[jªf”ÈUï0©õYê]Ruî·„fè ÓÍË.±}tÔR&½™=ïlHønYóêXjà£bîìºÅlgnõsΡÔn1yj‹]°ë)™Ö€§§ã\é.¢ƒß–a‰XÒ*ë âPOy;ç4ënÀvn`œúî¿>÷z{ÞžÚw«‹÷;•s`q±÷Ö¦N[oI 75 ÝÎIí ï±KP'(÷1—7X˨¹s¬:]î-ÛÑÓ8{}0‚È@$Wbóye`RVGæs±’3ËÝ=.Çwvšö_¡1é™¶Í‹Ú<Òt°ýJ»­¹ ÆóÚ[Ä“Í{·!zfr9á¯tdo_²‚%Fß@dñ®ç‘-“›îÛ:mAÂ…ÓÛælú·Ôy T­Ø–×l]œ®Æn–w},½ïdƒjt8ý+Óá»>>÷@¬ŠÃGh.vþw¬PápLt]Ýæ8A‡SÙ|wS±g¶ôÔÆw;ÞÊç5á^]’¡¬½S@›ëƒ9pºcVÃÓp±hƒG%«zÒ¥Ù§t5]¸òÄ–z¯òê•àyŸI×¶ï¯I;…-–€ÛSK¡Hnt–©Ì$ŽÇÜÝ4뫺´"®•µ`sÓ”x«šÝñIªÛŠZ+¬ö«•¦Ã4oûŽ×CÞæ³‡¤ò“®óKŽË¸ÈÏãGzx™#æpáÚõ·ïx.‡aÒ”¬w Þž|·@«¤›}°Bi÷¡íáì }xŽÍôclbÓ€sǘJto}5‘¡P å!GŽ•˜{…g°Þìx¯| GWh¶ÎÐÌê¶Ë\í´²»?dÝv”šß³N`é‚÷¹XÏ.”ëÓÉÚºµFå†O[]««*ùp=ÒG=·™À‘‹pÙ¤·§xJgw/fõãc+ǽ—Þ¦àMnù{fÂyj±µO§ É»úvFãÉÕÎ(ÄÎlê‘«žÚç¦ú÷ƒãîy]áä=o|rZ&äPN»YN…D¯¢Í*Abó·-J9¼«D×@$MòÍxÖ@NÒOa¨t÷øóâ£.¸༩·ëå×õ´«—¾Úƒ¬+s×Ô/Ng·[À±­Ô¤¥NëÄ‚lΖ —?8UÊ¿0¼†šº× q]/sµ˜6ÁÌÔøö±d–5̾Ú{Œ¨¡ƒ¶âiGŽ.—;8¨±bÌ XÕÜÌÉÏu®Î”÷j¼öm>¬½ÖHCVüg–°Š¾ìw0Ôî²ë#´GV:±·6-’–2Ý®)­« ùý±¾¼xÔñ«v:iq@+0P¾DO–7R\KÓ ¬¥¼¨õ[éâ=Ü=ëIÖåÒsX¨K‰ùh^ÅÎFðjÍ‘†;r§½>'øï6²®÷Jòµ‰Ìåš9ÜV¤2â+wceájÔS€š–í]˶¾Vdá‡y›,iô½íÛFÇd£|½9^]V¤ú¤f^P{³_Y€ß:4ÕšÅÑMî¡Àð}yºS½íßK©sŠzÚ,)™¸Ï“©Ù³Åk·Ëm²4øV0%1î¡Ñ33©ã4«(ÈãU‰…y‡µnÛ¬O#t89’uxóVc­ëpK¥n7—¼k³ja±«˜j"»zpȺÝ@ˆ=Ž¥çº¯}‡ ÑY‚ÈØL7~jTË7¢ÜáѭצpùÓX:ùa›èóÛ+ÁmA2¼¦±Ròºo?J]·£hk°o.»U–öËݬ]䨑Ê19î8ªá=Õ]~¬½2ÐX\ˬ2uÂÔÜwW<ä(š¨ÕÖŽÒ’Âæ¡á›+SÁwZñØ …ßÉ’¹tx =¼^^/gÞ¬«Yku]^"ÛJU»TÑÏ{VÒÄžUÑËÕÐê‹5=Û3ªcÇ—D®ØƒÊÞÌ •të®<–]õ®ê¸/3v ʽ³ƒ()ÉbÔAV‚{¦æ-÷M¥óJ–úWCR,·~ïm]+ñ|MÍgs¿”]Äbƒ¦ë£$ ã–õp løƒŸO6jÕX¬(Ž{g–(T-Œ&b±pE¶à¤¬Tåsm`ºW&¶0D÷š`et“ë¥8qÎÙ%fÜHãá;&ñUŠ·#²]80{ßn±ñ¯)‘X²W,Ř²÷W„ÊÎF¶Ð|³yØEºA,ï ‡í!…¼¾#¬§æ´ò†ù6M:›—ŸSÑåØzÅ®¬¿{íiÅåàÈöl¼žçqlîmÇS¸_ƒõéU²¶;v½‘ýË"agµ×ßv1•LÅ•ÜC(S{«Ù/-¬•µä¦‘ªßªÞÝÖPÌM(Å©ÂtòY¾×*Â7Ñ ·¼d» VXe$ÚXÂï;7}}cj;9‘£¬{†`íÖ®•1Ù­.À.é÷'l÷\eº>NÍY5áS4º'Nùòºb÷«÷³M¢Ìó“Bß{­ÒûÇjQ¨9¢§+YÝY¶ìw§0kÞœû&Ò[{ÈéCÞ‡ÜÍÍòî²q›¥$~! sìZ³®À«O«ÇÝ4EË~ß\mDÚÓ³¼>öÅŽ ¾b ÓwÙŸŠd^ÞšP®vží­0¡ò陣5>‹ÞV†õ5MQμ÷€/žÐ=ÚRçWð2˜) Ä<­µ¬f2?©ûÛwŒóüè-Dv/Ý™´§d»ÛÔÁù Š\šÉÀÊF§wå׃׳³Ô}N†èö°uq4÷õ·îé4íèánà\nÖQ†æ‹Jú‡^§ÖzçÅÔé¾}:™íaA‚^ µØ;d·©¶îÎ+{@ZáHÞãÁhä¡e’×s¢U„›×Õ»o”rŠÌ@R‡y­†2÷’ù*<Êö{Ê,1ç¢ktÓ¨Ó”™^´ ±5ά{È{Û&eiuŽÉ:áå:j»r¶ÄÉ+sŠBÕsõnÃKP¦æwÏk§Œy¿, €(hú®ó·;³¹JWW×›Ö/$§‡WÒ²#ß[‰ýªÑí’áÉš‹!ó+™2évÝIptåKŸ§¶P×.VYøæfš—â ¹c·0òéf·ÃéˆìŠq«§¾.ù ÀstYZ©Ð¬”åuH¶îûfÝ+ņ›³,’Æ\¡b÷ƒ5m¾Œì{r Ž-Þð$‹çŽð¯Æî²˜’T/‚éf–^tð!Îw“S¹V«¼ŽÄûÖ®®YH¨ `úa»ÛÙל͔µ²ö‹À+ÖÌÊi›ý®‡Wz† ;®à³¨ý»ãLDx¶á¡E ¦3uwAßn³fݨ«³ŒˆˆšÙiÊšpðþ5Ýš]uk‰#§MíÃÖ{éž^ik}ÑÏ]\™›‚í—ƒ>N#WkIzk†à¸GžÓÃFö»ÕuÞ½xêï^„û¬’ÞU¸ŸX¼NÚâ©mbÖÚ[WÖîk¶q‚kCëRÃD†©ó qµËn g~]Öî¬×°!(tâêà¸Už¸.±ßuÅ/µåÀ±Ø¤SG«L$Œmnô×®]¡ÁT“Ëfa5†ˆW‡»$ iìxàÑ3:ÓµÇe-}ݠϺ§Sެv ­4ö­¹–÷6=8“^vrÛȰt ŽeM¨yú³¯£ã½¤n€[2d2äï†\ÀwÖ½ã¥Sx髵VгANÒEo_F¦Ì¶Þzï…:[OV:7|¼ zÄçêWçMò,h¨š¦y%Ç·ÂUûÓV¥²Þ‚é«DxƒZÈöNê+ÛìáyÑÚðM[çö×”¶àžÍ$¼{ìô´¸Ao`Ä/WZb¯´ëën_P–6)Úé“•g¬{ÄŒÁ^.¥ZÝ:;xë6ÅÓMÀxêÜ™»ï:•Áíµ’•1YšìF)\]ïDNuˆ éöC«Np[×8´} uÍòç{íCÇÙËÛí²ÈÛt.Ž5wÐG’ÝKOh=%›M÷!S¶ÕYÈ% Ûç·i[KÃÊwµÕøîÛumÞmvÆèÕÇJÞ;æS™{qó§…jùq¾Gyê¼ zÑTòÒPÃ\-Ð4»0§¾ÓmZë7÷!KÝË·ñ[í^¶‘¬å¹šç-¸ŽŒ”ò볦R›œ$§Üî[­]漊”¶♉zÛ<Å©5Q^0æ ůµu÷+’épãÈ(]Ýô‹ŸŒîõÝ$ó{žðÁÖï}âmVc®ÆôuØ%qǼnûSÇE\pQeN^÷Šíe…Þï,دJL‘1%S…s—œ0÷aâΑ?bcî£SÞU["Ù¨N¼îdußc `{ÇÇIíÓÛÆ¬¡¡Êÿ~[m¿wÃÚŽ.¯Ê.¢Õ^~KÄä^xÊîÅAR›Ý} ²pLÃËÉðZýÙ›¶É£]zï‡CÂg_ÃC»á…ΛZ©T§ãáéªð÷³Nä¶ìa´tmê¨#mS0µ^‚Å®q¥t$;:ê*íëÛu,†È§¤Ha*+í{—™:éô̳¦=o‹;œ½¨0dT¡uë÷‘1}¾oO0®nY³Í¦žtÞÆlª¢ƒÚr‚y²µ>Í7h«ÍÖíêíWÇkd³˜«Œ.cJž[@åíoÜÜF9r.ƒipmv¼Ø]®š­{¢^:Z_]`æê¥ÈÝ ÝÞ®8ûgCÙ^ ¸aáRH:¢½öɰmèÅrµnâŠüi†ç®Îent™ê}Þ‚!¸8‹¬ß— ìe­÷#wE¥ï]ÀÌ Ýf³u,%‹TÉÛwÖ…¼øj©x©Ð„K^Sããº.®>ÛêÈ(€â8…Å^NëÎà7S|ïZÊU7Q"öÄäw„UÄ%Çuî@4JB¶ïܪT¸>÷†¹pâ…®¡ëaeó%Ѹ{$×É4ÓCCçî¬w«V³šbúBIšÔÚX†D]àtóVÎ )Ï\.BãG©tÜ£½VÑÍtÒ|‰x¯k¿ —1{Ö]uuc/cMý6ÙÒY>ô3©Ëö<ÁÅîM·y¢ô³Ò‹ÉczC7Úw•×<©ýn¦¹ã§ƒ-c «L³¬Ó¯÷L}$ÉP&¶ `T†Á,\Ú™}Œt4ÊÅy^ ]$¼­ât<°ó†JÃérþðó4±½^4Œ ØZI)ǰßVÊæúŒ94%.3ž$™².ºúÎZït^<Ñî~•2àÇBÔѵ¼wÙŠ…;[±Š\Ó5 ™ÕªøãMf˹ݯz÷kµ·¯»X1 ÎÅ*vm‹îô£™Äj¼"»wXy;•øvéaì&€™R¬zúvíéIÍÆØLMW™fÃÚë}ܾÍ,qÍÚ„?³s4.öí{‰¤:ñÁÚx]«ˆ×»ˆäÌœ§R$wÑ>Úݵ°MJ­+Í.Å÷Ü–f0ö”Í$ÂwÑe] üáµÊ—)“ <â¢)í1# ¹ûiitÝ绋ѣ]¬Dg…‚/ÈE.ß,øxSŠ9™VIn¼¶Î€ú{ÚDÕC™:ðÖìÕ>¡4%e{ƒõHöîø ·Æ´›?zRµÝÜþb1³y­`Å©S.Š¡z­q£!|ô³G{‘€-yô̒ó4%4¡Ív ÊF 8s+ŸpëHó«=öur–F´¶Ç4ëV”=V7œK»}!Ï:õâ·Œç°9×n1t+[\Þ Ö]´zJ4kžÇÙ8ÈÕ_pu‘]5·r°u¦—hO_WtVû2׎x݆ay‹y:M ¼WLbVÏUËßîjtËu*÷x' T²÷°•ÛÑ Ã) †˜ÛÝÊ9 \rUž]]ÇŠqvJºW ¶_'ye )ç\zßVÀ>ë°á7BÏ0iàfMcÙ¹X;Ùa>‹C¼=CeˆnÖ¸†?ºå ®f›|àö”ó©Z9Ç ´§aÍ~ÑØNöNô\ȼÂ{Ï…hårœáNð>ÀUó]¾Îù z;ëÁ-ÝèÑY¥ôP°†=çÝ“\i©l‡áËfºÌT3*ÔLk&ñ—Qi ³Ö8•iž‹Ê}¢ÅÏA[¹}‘%çq)‡˜J­-̱*ÂjV˜7™{{Š=¾o=D1·9^?(VðÁ}»2.[ÊVf‹«±P“~¼ÇŽÛÇ+L¡­ôl‚ÄV… )e—•™ïfÏvú†ðÅJÏcE&Ê¿t‘ö£”üMiŒa<ÓÛ—îét/Ð sµægNkË4ÆìFñ[ßTÊFŸ®+jDzѬÙKºº²·|Ýúø¾„{ˇŸ/*:™œL+Sçµ™g.rµtû»¥=#·´D¦´í*¼£›ZgîêV³–:ŒµreìÎU ÷:Ö6îÒÔ’´]¼ƒHÊвj©íô°;–ø??Kt¬#¯²WK2}¶Ý=B£¶;§ñ§Þ Ã8Ÿ ôÉàû¤7jg vwß°ßF´5“¸Aîû¼°:‡½KÉùvÆ­Òæ >㾯3’—µÖó×¶ðP¿´Ð\pxjî8ý›])¿\sÕx–iô{§¯5”‹¿Y¥#È/8ùŸMp;EVO;°5╽¡IuJ]7¶fŒêq6×G×ɬ-RW3¼4·f$oÒ§eÍÀá•R?09ËÖ#'(תÎâ 1 „¸Ðq¬"$-Üâ×A²ks¾æ±q2Úº²um%eG• Ë—ž=×Få±öäÕ+~·ÕšùÞÛéVã©iiδU жpÛÙYîèšë ®+Ó73%­2*He>†O3 ­Ôë¯ \#ò³¤íÊS…ëT½•®„‡:öÖj(‘*lŠÎž?zˆ¬»Ô‰õ:1¯æšW•œwjzùƒê¬©Öq/vúA¿yHJJ¢õ5cFz¶Þ= Ô¤0îz„Í‹¥\ÀGKyI”Y îµÕdæE'¹ü>§ë¼tøõyµV=WD‰úùJ>8Ð6ãK;§!Œ½Ü6{NPÍâïCšêÐDxœ§Á+0ºÚ²e¹\¾E+yúʃ*Ë{ÛÔÀ@ô®¬y sf¯ÓFWÓÕ³§nìÖïBy†U굤ËEÆIj™–1Ç8Vº¹.êNÕ¡Þ,5¢ù'D’ÝglŠÑð(ä$Ûâo}CázCyâÖª‚^žÕvIÓ0¹îs˜Û›ru“Ä8:B†‹ãZÿ#:[EÛ86Fw•]øå!§ÍÔM9¥Ý Ý‹—¼H¯E¼kdÇG$tvÚ5*Ùž[XÑoœ ½B»íê¦Mû½Ø°Ï[Þ¤ü>Yƒ3׬•¥´;uØDnWfžŸÅî0ך7×U³yla–=Ô,R­Ì± ÜçN«¡Ý]Œ²º‚B"geÖ(dúJÜâ1òЧ㦯_ä컫ÄÞ FýºäêÞ÷x¨­ŸPº²j±oi›Ny]•.V\}ØÕv’v<å¯vßX[nJNCDB®rçÏ1tUÐ@æ{հ穽œ—…yÕ¸¾&„¡IVdIp¡R­"àÀ£ÖÎV9£vâo¢9iTʾb„çº&±“0¼O*î>á3/¨«!ëü]ÅË^(ŒƒhÔ% éíÅ{—Õ\ó]Y¶Qâc(äïµUÝ':ârÔƒåb3¼ö'ãˆôo¥j ø{oÛÈr˜$×3í%ý/Gœí)(¸jËMtëœw®cÁ[ÁìƒÓR§¯}§g„¨«¶Ä|w¹ƒr­kZkÉ«KlAÉÔ-^Þy”ØïЛÇ;Äl঎ÑÄg1]`¦·x¶‹¬9¼ƒû—R–œçYy޹åq¾»~凳жš)u'-ô°ØÒÛ¶PÕA™"ê®g"»-¾³¥BTÛH—.£S.“nêxmgÕ¯¦V"ÅKæ³Aø`Ñ»[ Ñ+‡ë"f7}šÝì‡É`òÍÌGèêV%Zø¦U饬á¨/HXÛ6SLk»bdÊfÔišé@¤‹d´n^éO^õÏ^?yuõ{IÛiQeÊf’l‰›$;åô®¥ÝË8Ê·²¤}îûoÀ¼ÀüŠw/UÇ×'Ðê®ä)cÞåáO*G³€€vLû·î•{Æ_î7n–KT9!“]HWÓÓšÇqD¸8šX9 ›NêèAÝÝè®´¡+Wsðw´}‚auE…€a’.K¢á.åØá¶Ä|½•ïkêêk9#ìÚ´/n:¦WL5šØÇa^*¹—ƒŽ^mŸn”Ø¿ ^¬ÂØä&ß®Ÿ”Ð]ÙÞ}X*áåìÄmwn*Ž•¹WZÜú á’²Üî;H-ì;XQÃïg·Íž}Ég»çÊÕY…-ãŽË“Yì(õ+ïu¯z˵h®1šÙP/T;hŒ¶5ÇÄ6».÷*0ˆ®,S<›ÕÀÖk~í_²&?+:v³¦È„,~£|u Ç7qõ¼7±ð¿tØ}ï{rî—Ây×M6]e}°ÚŽÒ^Ú5›´ÍÛ$}³»®G¸Ô¥{›`Æt¦vò²TÙIÞ¢!áØ¸l™Sº°°ø/V_aß{Ï…<áïf zùѱ^"…º$‡Zuâ©î²›Ò"¢Œ}—YÇZ<û6okÖdBv¸Ý‚^•‚“´evk¹—¾3—^ð™uzQ­uq]M96©TL½ §ìÛÊÓbzIÜËß#\ Cd'âEᨑ²ùNj­§ï6zÆÊîYæå^:õtBÚhúým]{ÈÏnèCÄí¬Nº*˺\ðIµp³kŒÞ«PÎÞêÀvºó·5ëN|s[œ'q7’Í¥X˜ÒÆã« šs–á•a:Sr£{C¶Û¤’וµ† §‡p£Ú Vxtp¡vò¢xîbÍâÌ'mòHƒ¥¶8ñ  g8×Ü'D¤Z«¤Ã¸®Š/ $Ý*ì¤0·uìžîf®€N®ã­­‡íò‹g%H·{5ðÁ%Ú¶À¾3Ž‘yÝÊÏTgg)¹ŠöÐ}4(,v=X$_Ä1’o½ì#ÝÃÑFñÑ Ë*²Ú-j‚.Hnñ¹ÊêQyx‚Òùgòò#™lÓnÍîfEà0CÕ°g/"gdÝ’ˆUʬªÀ² Û=¯(ªÜв;[¯7YÞ/ný®¬†Ý÷´—OÔ¨HÆñ:|ì=7;‘Ú rÇkvʶ=‹Ø­lzè|r‘êåŸÖ‰z¯u 1wkt(,ìy\¯¥¬›Æ]§ëîÓ™îò¯HǦKq.uz…ZYÕ”ìp|%k™™ ¤ëŸ á{]fÅHn›ÜDÞÊõ6Ô÷Nð]À1Î×_n‡es"ãp‘ Vµæ)ÚŽ»Íì®Ì¸rS ÏoMêV¦KÁT6C%©‰©`avqñ£LlšJvè×p ÷xÌ~¯8M;·!×>¾Œ¥ð—Q:öMrÈy^€úŽeÝs|„ÆœÉhv*Âq!aYïŸÀöS¼‰‚é®iÌ;n¥Í_^ Ç\µxìÚ·åEï+žÔ]o8fÊÎ盛 öø—FqutùøôȯפyîÒÏKè/D}uÇËAq…VA˜=å—æ–ú‚îǧ/²>a~ÜTº·)ÐÎf‡] 6)ÇéNÔ®…²«VÀ±ößÓ˜Ü:w«pŠp2sÉr²homéÌÏc+ÞïÈéÃÊÕöá…ç1 Äi&ñJÔì ¼j^µë»#¦÷àyõý+ÒãõSãÔóæf×kyœlð#Ý£ËEp„5‰³ëC<Ìë8ž+yŒ¼šî#SUdS IÌYÂ…GÓÖlÕÑJ£wyÏÚ7ƒiM¢åÞª^Ð{®ü9W{íž»oÕÂoæí`ØwSP‚ú×M+×bÐm&sXÞ×x§+Mî Þ××ÔÊ=ÎÐ<Å\ìwÊ^f÷YD˜Á˜Â*Qu“)½å”oYe¥ì´w30öÀ­–ËvÖu8;€vÞgefðø¬‹;®|ÖãÜ.Í;¥c(DNJÞè­øT/Õ¶€^enîjÝû½¨›Â_¤Å ÁÊ¿ŽE«=•Ù§ºÔ€VŒÎdy;È7™OxÍtëmNiÃÖù°V¹óØòR¨:®×ìÍLuL-ÇÖµ§ "C<ÉÃAÎÀ°fš»ÐÁ­Ì7BÚØºµÍ>ô;7¶Ä—ó"¹\0,’p9Öæ‰éXû†é¬Å7—ì^¢üþîR ÍÆ½„×VÍxäÇ,å©à–}æ|ëôrÝ5r¬?ÊòLå¼ÚÞ²¸÷ g·7x…•-m®Ü–m 6ä+iò´I¬Ð×^ÙÕŠiC¬I@šØªâR …÷ˆìΰã77éx ¡±î*¶’îT¨ÓåÙÏÙ¯¯Ó¹à%`!^/&%uë¢ Z×o¢Ã{6l‹7} u1R[AÊ”! œ¿ Ψ#žÝô¹Úsn|§VQÁ­üQ~ÃJož¬ƒ—x©^Øã.Ÿ½ác:|WŠöVõ†7™d L˜Cœ”ºPmÝZ’È‚OW³éæ³++ר´—«Æ˜u‘ñ5}S! DZº#¥UÞbµ×•µ¯`Òì;Öq†®‚UŽó)N…Ì,Hâ m÷mp ÆE­Ê´î<·W‚ï8í2+u_ÃB›Ü ôíêö.0ÝÛ‘¬lÒE[fÞómòôhVøs,Éé•rñÉo¸ÆÆk«¦+Üj·k+_oæEûà»k+·4ß|2o!/fH¦g-egCèð·†Âp±“mDw–ä1[ÎîÕÜõÓ×…x<4ç Óµ©Öy(\‰]a”о„F.³ ”×LÚ‘2EÑâVO©óöõ£ž8zîÄíé.òÛ¹=^·Û•µ¹ÛaZ›}…+AúLÞo>¥[LvVí,¿ y¬­¸Ý—¢LƒÝ™ öùÙc«l4˜XW†nò˜äÒJì1<«‰#ÓBv]«í©¦¯ ¾ÓnŒ­Ríå©V(¹ÜšÛ‚¯"­<ž,ßGîõgŒðu—i[µK+¼Ëã®ðA l“p• « mØÇ—Õ‚ù5ÔÝ=®xžôëYo´ËëƒèdoN‰1«§ ;“lÔúèâ¶e:EŽú_p˜7©í1"mÙõ×µ]¾À¹LÊñ»éYlÐOxÜQí7Ç<Ì›Þឺ;ê‹oT¢-0ç¬Û¤Ac^1Ž•vL¦÷µ-"&ü´nUÅgj) ©ÛÔzæõªÆ*kÑÆVëÁz‰Fì…ôãÖû‘Z…età€Ÿx$.±/?;pøô}®bºåâ%xæô•íÙ]Y‹ ÓâÖ”Bç…“8]{H34ü÷ÝŠ®´îÕ ‰1w¥¡†oR–™Ž·UúÍйy7G½Ç$"VÐA¥X¶Â•9ö̼U¦«_1^™tdîÊ9ÏmZÁyZ»hUÀ«jV–kÑ*׺ ¯S±‹Q¡ÍߪýâÙ0Wutr»±´h1”øsƒÀXÁ¼&³ƒT‡Ë¶®÷Ulfx ^ÞS§­ÏÜЦªŽ fÉ;γ!'#[ì‚T_ÕÇ ä©ß£tƒâ6å^ßa+=KG–w /ª÷Ÿ]¥»²íû¤|e_Q¬¼t.SS¶X½€ôqÈ«ŽªÐEk7m:w²®:à5›‰âðôóîÂ+Þº1;»$WBÞ÷ @JœÚv{g;¹¡Ð³œe¾ØÑNJÞh&…mœ%u_h駣Ε4p©4Öuç©ðô5èËDó/¬w_n.¼¹ÕÊ-âjL·eþ Í]ÔæzŽ ºDûŸêì{&·c%]øÃ»<‹ð¸/4uy.ù÷œIP/¦Ùè6ºÔ’UÊõEƒ .âm(êó*N»…v“Ê»¢µcr#ƒ.&{WT2,™”KÚÓÛs¯Š«lh«ÛWx;eËh×(]Düׯåb<ë¼@ëW¹ÁDý“ŒÇ]φnÕžrLíËz2âã×c—eÖ`7N²âƒF¼<àá§äß@^·o°ß—dÕ ¡–– Ù /¬r5mýº7/"ÊèÑ4G_À_É]`ÁÙiƒC¢Dš´º,ÜÖêÈ!¶ç«MmFRâÎ;1®o«³GFÈÊœ¹Üm|éîàXvoƒ£D>wWn vΈ¹ÃG6ÀK1X¶J'GÝ´(нªÌGVÑ"®åÞã•s½+ ̤,œr§ÃO¹·Ò$„ZG=V¶'Û×ZïÀxj» x‹ìÄýU{b\Æú-l¬÷7©=_Jîiw¼7:ßf§÷es{€Æ0‘²&jÃ7“lZEwaT,Á¥ÂÆ&®>δéx˜#T|zÞ2¸.ßnøï:‚d·§xGçϧ½òžÐåµ}ž’Ûx‰ç1Kqzm'naÚë×KHçÕ.9[Úw)™z¦ëÙ½ÜÁ2šíWf“˜ 1·ƒçtÀz½9_d™¿râªI…SÕ2¦…f5¦ +G/Û`¢'Ù &ÖïÎÒÅV;'w'—LëpÉɃƒ67ÝmÖ ¸(ޤ’Ñp]®Dâ‘v¤^ßµØ1®s&Š®°aÎ墥Ò}$ÙŒüŽæ[ãêдªÐÓ—|ÒýÃYíp 5vùªUÛní)%æ£j¦å½ç^”’çžyÇ…‘B°Mí·Nn¯vgG²µ1Gæ,n›fAVy½ß³A™AóÈo¤É¸Ó”¨u×S]GHuÔªŽÖ+´˜¤«±lˆóœPî…• xÌ—¨4Dß(T-:AWEIl ^F½lM8 iu„ÄZë9¤³zös»ž»¦E÷DîkÙ¾€ !éZ¨™<×°¥HtéçÓ‹ð{è3ÚˆïnKÞº½PèH® BkÆŠÂ*öàë½å®=•uïó˜g2ýy›)¹# \÷Šõз×B±ó×ê>\ŠZPʈї똖ÖZ#_ “1fÎÒ)½Óí’Å¢’Bä¿=KXÌÕ¤Ú9{gRók¦ù+§®¶¬Ž­|Fv‰á3ÈT‘UÕ¢åƒtÎÉîãÛ•êžS®½û/œØÍ`óäáµ³;ìG8Ök''›]€â ˜‡GÚU&½¿ŸUå-µÅC›!Ë9nTGȲV¡ï Ù–«vIiWUó"¼6…ßåJž¦8çS4޾Sœ»§ô#]–`›L ½o,ô\ba†¬E«Mv[·=7ÇËݨPâZs;§”¶Ésò‰æ,®«ÍìíÊylwXoz´=³n´)çöBã±5¢¥óYY3Tº´¹6ÍlZá£tœIX…Mg‘Õ@_vPqöή}wÓ+Ó¡¦ëë;cÏ奵¯×`à<ŽwÀyËz›×v8‡Õ·ð®&®+#îOç¶ -cKÄõÿ÷㎧íNÕ @L}su˜¦´ ÛÈÔÔ<ÖÑyt–%uyOˆ±‰¶’[š`8½Ò‚ ^ù+×2»5çm¥t5bŽ+*^ÐZQûw_±ä¬µ6z4ƒØ{*n?Z•6‘5nÑêÕ»1ð“{k_õy=öû2³(p«Ê=w 溕&Seo(n/žÝ'Fb÷L³Óº×Ÿ³¨îݨë¤Òv“ÊZéë=”¾×ÈÙκ¼M3czI¶1TB]X§ÉÐmîwݹεeš±Ü7œâÞCv%f™ç™]¦ôœ¦ÌRpoÍóµE‹}ná¼¢ÄQ.;¹NfZYj9ONîdÅ–ßd%‡ÝFì¬Â·ÖÚÃaKžò²8Q¾ÉÈ\V©Çv.÷¦†*åÔêF!]·[1ÅCn®H6P)Ô¹yjqºÇ—Ä+r‚; |‹;ÑkÍ]ß^e*OÖ˜ê;õÎ xp(Å)<ìš >JMU6á ¨ˆg œdâ£{¯r}Þ1Ö¸ŒR"yftoTÕÎ/’¼¶,P”ÝݬÁ Ìt’x¦ \±"Íu¥%°…wed2Ñú7k·-ul­Ã.îmðq7•,º‘QeÇ.z[³ß?L>õØ9Ý"Õò½¾¥×Îþ¸ì²h-8©nÊɼ²û8®Ñ§JݾQ*à-ûÉ[BÔ¹êYîv÷·•ö‰t'b¹àª+k^棴\-Ÿ»ïw½ÃsVŸ”ܧ€ºÜ;†ßæ]óàÛ¬ÎGN1ÊWb£Jèvdaå¢5ÌšmíK«»´HGÎ^åï_Nï,K¶r‚ƒsÏ&Tãë岑Ê«¦E^«Š ³îÔ¶µ\Þ×y£®–¨>§\O‡yQ w¼sÇ$»æ|Ùì2JÞkÞÛ³¦¥ ÑtvrDÇÚÃbµÌP¾¨ÉÖ©Þ í™ª°çrH+u ½¶ºWGÛÆuÑì•Ûvi /@ç/²dwj]raóT:êîKÛzÑ3$âÐc‹‡vhz´·v0%…Á\*ÜÙݸÆb¥zy.¨«·ȯ<*úð•SÈFXAšXõÍ]‘Frîû´›ó¹¯†<÷¶ ÔƒÉÈÞgŸq JŽ§× ÏJt¯3Êø¯|·DlŽå³eøœRÙ#«„Fæ>´#PZsg·s{mö­|B›nd¡Îï£/NÑ†Ç ¢xg­)åÈypε0 ìÚÍ?_˜Iv3v¶±ç×·Í9JË´OVgc»ÇÃf<ó”íjº½ËÝG§ð¬î¤Ìc­^h¯jåaÜ ²²»u†;­kºêr¿{îËzÞÛ*vr„Ü>z‹ïH70!bz4Äà¨'u1xcÈ÷îN.;]'i™ÃÊá;+l3Zý„ËÕ,”ŽÒ9ç'[[ ÷!;_bb,Xô×_U5¤Ñ×ÔÀbvÀñX¥«Õu˲ߔ z>viÄ{3ÄÎ`£OÕ×}Õh;µ7 ¤½K‚™ºå° ?_$«Ã6LõнÞÕ/WO%¾Ûf@³Áu rÇrZ§ÐdË, >—ßp,Û>H¶è<¯_³"ðÙϱæßMe/îØ»³ë]g²€òÝÕ²ç°cM÷<¡Ê¡n=¾A_ÓXÖþDѸµv·{O#›ÄQõÙ¹‘ßP¥öÍ(çîQ ©Ö«aÇ‚ËÝÌG­ätÎ:´;¾ÇmUx„Bæ™w®ˆ{»ò¬ˆ/WÅ{Yç£BMÂL"vIzÅé³ã=ûÙC&Yd ?\®ý þâüƵ_ã–êX ¯Æõº(G÷ ­µWÝÛ³°*FÁJô(Sùõ[ñ£XŠd#Z*±f¾F…ŽhºT„äuz…ds Þ,“® ¶JÆŸÒòùLãÖ,ÖžŽ0´(©°8–5ëQ.*Wq.­ÃØRî{Ó&7[lµ†‰¦Îb“ØÛw36†ze<;\W«;©åù£—՛ȑNàµÓ+I²ûSÞø= 8lßoR„- œÎXb»îsŒy©Òà¨m%¹åé/àûËÏ…îº]žcô´þÙ_´ö3ü*À6lßä𽕻bzýlJ}\âÌÁÒSá¥dÙ‘¡Ñ ¤{e­¸N ÅÙ}JEÓSbžËw—ˆ˜m6iM£•¢—+7¨=x´ÓµÀRá×h­öέNíô Dð|ž••2 7s¹Î¸ÜÙVw®d‘ÖÁBÅ?Ÿ]Î]ãzjÙ+E Ú Ë\ìÜëÜQ*ñ®CÃÔ¨WM ³¥§µ”È$«ÎÇ º¾óè(õA7³7ÞÔ³ƒÁÔE –—núžë”¤”®·§ˆ1^çgAh ž,r|á»/ʈDŽ©Žbì¬Jë±÷‘ÄÓu¿ošÇ%³Þ’æEAäÄö(#x¯½Ø;)Õ¿™c §GGnϳn&Κن=u<óS]¹îž¼‚Ÿ9´³·»Pœ4ðàŽ—i ÁÈúd¢€MPt>À6á],¾¾òJQáê|)!SÑ]¾ò˜—Úxó¼ängÇqÁ€ì!K:w„Ó6ƒUPVöK‚3lޏÅu«ˆäº‰¨’Ô²â*eímÞ'œ-eq#«¥¢Zú0Îà®°†+îƒ5^Iè÷d]Ö°CjrHÞ €¹é˜üC8#;/Ky"¤QLjÅa]éæÅÔÊ/‚ÏNõº?]úï»„Š xkvÅ(l&©Uu–_áYíœM½®~æiè3Cm/+»£€å Œ¹Ê%ë Ëßš¾”ŠÛïX“yön` Ñd+Ú8³Èß¼{YØ×„@Ø;HoÜ_zn{n ï\KµÇ#k¬6€Ä–\B•w¨ÝqO^‚GqTo^È^ùé´ÍN=XéŸíw»ìæùH7ØGV èðGÙ!N VªÏ#zð‡•9û¥ ÞV·®¸å,øZ9n‹c²C›ZÕ€»]Ÿ^ªvîÛçIj×;×&Û¬Æ VÝ^bscá½ÎÁí±@õ¨é·yl`¹ÓT|yvλ¾Øn '9“AgP¾ˆg´[+²-ÞñÏ¡º`ä¬ö2[{¢s‰˜BÁ ‚®^É¥câÛ×)%ÜáD·v°y5‰—8*Ü/ë—}wfnµg6Ç´Ù¦Ÿ£»¬ïRñ²·£M½³2ÕíShÆ–^æKÖ5q³nºùК¦M˜2 ìA£³wU¨9¨Y¯^Áp[9tï^áÂ|Oy)ƒËÓ&AsÊ÷Ó)»îóÃ<½‡¼x=€K8&xܯINí3Ókw­*ËL1¶ð³ðK ²í¹¢óй7C‹6Z®¶Â¢e ÔkhiœæÜŠÙÂQvKZE!Zˆvœ×Rj4å†Âän™²¢o˜ _D8ÕŒuï Ñåy`RWŠÉ³=놋 ’¾,ó|7^ØêžÌLóš¦É.EÈ=Óíd¹3 ¼€d†æ[ÃÜ|° ö°za .wDC*ÃYÝAç °ŠåYδ÷#S‡4ûå­ÕÊÎ*L­¿‡ï²}—á{ånëÞçK²ú›W!ë.ôi•¸”ƒ’Þ\(jÊ=z¯VÛ ÄbÙqc”»™ÂbN™UÝ-QOv8úÊõÊx—6¤]ZÅoJ—¡}YÃ7:¢øtåç·ÞDç_ÛåBbÛ¥îë›;± 0„’\¯·ˆ^Hk—C*舯UõÆ( Ïk½ê]:º³*ó’ˆæé¢í;ÚL Z“KhÑcMBÔ„£‚U=¹«Í™²™t‚Ók·}Ù(n>3­^ÕµS=ÖÉ.H‡/Dñ…î_g…ôŽGXpÖWneYUÛ}½9 —kêjë¤å¸OTÐ îvN¨[(oÁYÌúÂâ«`»ÌõïW–‡ÚH;ÕÀ©Ô£±ËGÙw½Âúœfƒê+jì`æ>Ó\2q¸ ¬ôÚÁ&ɼ«7ЄÂÑ¥^‹é‡R]ç^”uÆö,`W¥šþ6ß~Û$2´•}·ºEÚNÅÓŸà;zwpŽÅ{ÃX¡×Ýt \&NW3[’£«…b÷Y­-ù|!»¶ÓñѱTÙT]7©çSTJ¦P½Öo/æ±j‚nmÌçìa?Œm)²»œSžNC/äzjÐ()±¦O¬•ïz—jØ~ÃÞ>Ôž†%éî©S”륳8*-ÐF[8´Sá¹´±æâ©Æ_׆¼S #¯+óê[™êÑØÅbwÕÁƒ*ãhÐTT”¡Î‡:Û®û«^÷ }Õ¤ñjì™ý}åïš‹áz¹DhZ¶æÓÉH’ ¶ÛbyƒÆaX1‹Ù]+¢«T…FSÀOPÓ—Fóé@¼ ƒ¶sTîZß*æRwZV%ƒr“EõeÉ鎭ûWÖ~â¨,‡_p‹ í?ǬÎ=?Aù.Á}’»tùË)V¹ddzÕ"¶5J™–-NËgcÑÑ7×v²åñü¼Ù‹ÙÑäíΦmøÚIâNç‚»#I>ž‚Ýq¯7L7Õd¼iv7×£f ub‘$Q…çSIžbµ½Â9”^ÐáPó¸kQu…×g&É{WÛ¤©ÞôÝ€{µ¿£¥Æ»µÑ€:ÝË–¸NûSÝM:˹µEXtƒ¤¹!&„dŠ9…‚®Ó5Ì©cݹÝ3z_ާ^Ó¶šëÛz-µì|¢×j5 +Qƒ»­-.h§& õ¤nó­nIãx»uï#†1™8õWòÍKÄzö®±,PP=êöÆmÏD=ww§+¸YðÊðé@Ñ eGÛ¥lp™º+[5-ìë(vÇYt7;5mÆ F¢»²º>áܲAtë½éÈbIJ¼À{¹THíf•WzâðƒÃÕš™ xrã·w•kÖ‘+š™0¢îë^T…ÊŠ»3u^[xØÖ´;|‰ßmxÔ¯u^Ä̶Dd:=²¢G´g“=ELÒA¼sz Ëæ/¹÷lêz^¯í£Ï'lÌê—¹í÷ i.—‰?ŠnîT`Uö1£% Þ‹J`YÉe—Ï4!Ý7.©×w7îJñp†¤ oƒ"Ö07´û´"‡…v¸c†{2@Ujv'±©]«k¯n»£(JCCLc´ër'hÛÊßµMë==+(ÞS‡/Ü®(½ð“Û…ØÆîù‹ÁŽíõ×ÞµŽÙÄ.*Ø5ƒ®ÅÐM[ÆÂ\á!æN½£å㉋â›êßg\k8jv·Á©hWC–r÷¸aÃõăs®^›ö5Wóî`êž¿?˜“qíó¤£ÎݶÁÖ5ÌœÎ𿱠óáÝaò«nÓ£YœC4¶RíXmÒî­£Ešé6µ¾‰åf‚W`àj Òh ²ÔD’.¸ìF6[âjÊN®ß:}`í'³p¦{‚n±¾»½ îÀ©©Hovíò·înY•í¶Qô~’ï¥ûs×ÅîHÒ½7µŽLŒWšAUíÐ|–#TjØÊ¸!-m¹¿6poXÅ…uÒB»˜¹9xGïÉêÖ`'¸U¬OÇsAfZ¢ ÊÝÔ¡Éä²ÝÍ­È5p¤ ÓrfaS’g— ãfóûhLÑ,»X2¤ìœú,Ù:ÛŒÁS@°G_h×¶ÚËB³0«æ£ÄÖHEíKÝÝ—Xn@ÃÙÞ‰¶-{Ù&ëò÷a9}–zúrz©â6Ûš9k3z¼eE_ä.Æ­š·t±vëwÚ dp8ýÛï"8QÊ7.aö…1Vf¡Õ‰*¾oÅRòºñŸkÍ [ë»jmDëǰ[„0Þ´ºPò×èëÜ7ÆófÞM!»¹~>Åü‘ÐW—ÔtÐ:›ãÚ‡ë0k‚3Kh» ÊVÚøjRž´*sÃv¡§Âú•n!ÝŽ°Oº³[l›WÍuBÆbÓW)òÓ°¤I†ezùüC¥î(óg}•«jH3MÍĨq©‰eé=Ï+1BR‰î±™Îmõ‰RÇnVüÄîÈÄRì°,íŠÆªåedCöö 9[˜gÊïœÔCÉ–¥ÌîËIà4)z`u0Uþè½~é)^íÙòçÑb[ª÷_§…ü4½® ÊLCì†ýW«£¼¬ê=Âì[; Ý ÊÅ’„d)Ë"§Hu¦Uö T©ê£Ú$û_zzucÛÖ½t4A˜ˆ–íè®Ü¦9óUïoÜOU«a?` 0nŒ”oy X°;·f­37}á¾éá1wxõ8"»+&êÍîílbŒwxªè4¡Aò;Ãu•¡5K;‹hk$Õ¼wÀl’L%¥ À¬âç㉩ÍîçY§`}AW“}¶he+½·Aç(¥¬4Ú̬ӵ¦˜‚ß;£Š«3@ÍRE3uʆ:Ýj® (tËÔ~’âL^®–Æ;‚»WyNZAqÉÃne=H˶Siœì’§¹“ Ò¨REYɺšï°WZÞŸ5‚Á“ ”(†E<¼œÎž^ºÆVçžJÝ:VìâúõmÄ®œ¬ú}5tË£ êÊG«çöo-‡ÇÚÞï Ž{+”o‰În‡K}d¯Û$ûµðhc…ÎKµ…ÖÐ6¥Ç]wnQwRŠâlØ…ðGÕô;ðÌâŒÒìær•ÛhòÃÍa 6)eYPzàÛÈÓãm…{ €¨»c¯7×w8(l/UŒ¾U"­Cp4eå ¤¨"i1LúúŒ5[ä·}К‰,°A5;vàé«|²tÝ€ ¥ä˜—v|}Â'ZFš¹M¬ÍWדÛ²¬@óH#Ž¦ÎˆvXT´õ¬³!@$/ºîݤeó»@à+\63Ë*ò™î¡Å/Y¯.¾c“»*ä1õËabÍ ­¡VªÕq ›W¢¢©/µíÙcðj'NëdYì»=½  ÓµcðB_ˆ®1å¹½N`õÑFàa0.šÀ$º!ؽ aè”ò¢'ZFÔ·A¾­´î–ç½6î@ÎÐ}˜ƒ©¶ò+Êö´ÕŒ¥Åö9ó÷¡ÚÉw¼éÓ5žYT$´¼u=Ú÷ÌEî§Ð™çµ|ªv¼Ë⩯~±œ/–$û²:W!¼Ë¨æÏnw«§¼½wŽ’K½×D‹§Uâd ×yms» ³D„èŸ]ù‘xG]¿KÂÂEÂhoVT’ó­Ý’RÜõóëÔ¹qBÆÖ*cO…íŒ/^²6˜Ê7 œÀöq;;\yضGqs³×í¶cCZ7Ë\>ÞܺDѯx­¸…fTùɰTXîd¦›>Ö댧-JDrS3—B²*F¹Ø³[VÅ<œº–û7³ ‚„µ9Ó;R7b~ÁÖò³½]¤Âœ/1öz‡C›X´OIE3tÙ Ýs†ˆ.½˜÷Œ¡×µÔo“¦ÃÐ<újάí­L‚{–ׯµKÔµr'**ÈyEºúàV&{BW[AÆÉ¯x‹v8Ïv«nÕŽ¤•ÀL‰ËbVu£5óg±ïK§åŒxç$ÐxÓõy<°ÕÙ¬CÛ¹,cÒ¥´§ËºÅÇv2TÎõÓq),-ïwe#”’^çqw‡Ýœ°]¨ºíä­Néãá‹7P:ï¸iFz\À8ïY¥k5õÌä³nÎGuÓƒ¿ª ܯIc«ÎÐû1Vƒ„ Çqt™5“ÛÁ´{ÎÆh÷¥yz mÄ ®12EÙÕÛx«&ºÎî˜~ÝÝíuµÀƬ2djÜT9¹ÑV£Ìmë×cí§ÓLÔ,dííô`FÈԀ׈g:ÏS½NZ§”}`Í2ùѧÇv¢¹fî‰Ø½~¥Gu]ëÏ­å¿»˜ã¤…jÖ‰˜rg ²|5Åhiéö•K½³'óAº½£~ÇÞ¸ë'R¬µ%.ƒ}éáf¬ÞøƒCt%îmÏJ°a{¼º°fg¾5©ŸJ´¼¯­ƒË=lb»¾­rºÀ@î³æÖYMMCPØ£2' Z­óN]Èr–<–9t6‘½RX ¨_)³FžÃrÔµ}S€t‰ærñ¼¬§›~Q¼özn0ýÙ\ÃT#>3g»¬Þó«Y(Äö®ôÕâÁæ ¼Tž‹åÈ#®å[g:Lc„½vûl³a[‹,U—Écì´ßv°‰eXÀµ±k¶qÝèÉRàƒè•é 7Ï.^F¥íÖ‚ºqWÔgfʿ翿b÷á›çàÛi6 Øk2»—j}+Tù.úsî ¦¼uâº÷zƒ¯11½Ý+˜g¤®¼ygÇŠˆ¤?žhuâŠ^”Ù£mMB†ìMÑkRæJæ8UÓÒß»]chÝÝ™³eßNŠÁätÉ€Uã—êJ÷Œ;,Ççï]À$>ór•Ðs¼]ó«7”81btwV¼ŠzÓ©ª‹DîyÝ{Ƹo ÁÖ¾*+–1œk2ƒAôs¶F&é­®¾òÕ=2b&ïÂvwvˆ6ý hÌÝ×äÒB–#aªA”u—ZÚÑy”;tµÓ(¨F[³ªaÚ ûi'Ò_—'Šˆxkh\­—|¯@¯B7ÝãÏâo–U‹º¼4x)ó#œÚä DN¾ÆY©z]J.6Çr×btôí뺟¼d+QE›ó ^UåèTt­ ž°ž¬G¹vÂpÁ‚T›F²éüÎg7ÖÑ£˜PWÄ‘õôvë`åêßrº7¶¦¶9Y4¹aÈþFÛĶ£‰®Ûì{×’·ÞK Œçyîð¦¸7ƒ¡¢Åyʱ~¬§¶ƒ;cžH9<›9mô Î׃uiØlЊs[ŽÜ–®\•†j ¨³N¶Æä9K´÷_|;CB+ÚºîÞ“¨wÚªÄ1ŠløûûppÓÚ»öîc¿zîC÷•j[ÖS‰SëZÔ ñÉô«ˆ_* «”²¤²EMÇÑTʼn=h “7Íf]ªšhï¤ô_úg;w„©“un¶Kë|ÃlÆmòƶ™œ¶»n×pam]¬LÊ]ÑÀÀ¹}FJ˺֬Èso¦všŽóSmÜu/Ž}ÔVj.¥qÇÔ¨½1"2€¶®â*IÚz %U„+,‘ÄE-‚…vKY•uˆRc¤æÐ×ÅݪçC›Åý¶îq~Ú=V¼ Z \›Ü*ûÁêÝO Ü©n« Ã3º[}ަR¸¶¢Ä†_\æ;z”à;+X ÜÍæ`¯OJîÖ(q¥É£:™³—·©¾œðΓ–k”Þënb ú5}¸]¦Éˆhx<ÝsÇUló¾s-ðz%Ú¶JŽ O:ùÖÉDˆh‰c‡a5ZõŠYqaÓßEÙhÂùÔ¹œ]ɼ•Æ;+§ZÒ£,\–††©Ä.ÑÆðc<±³µ¦<Õm$^,s»ý ×{#™TC¥‰koa ܳïí¸_—¥ß3¼Çt9i¿åùƒxdI¦îéëw±$,Rþh ˜·Ï”lT«ïì×_*ãìkµ´®ÆÌ-¬ ­ƒ¿Ä1^ëQmPÛ#uÝÜ<ãAbûòGÑž–égoœ{`¦ù1¯¸¾;ÄØŠa'–²n+Âe-QöÝï¼±™É×·G­tý%Cò;v6[èn”޵ †»lBAwÌã4z †Â¦~tsÑ6-=c›-N­„p--º7HÅ;3ÁR3wªu]ÐTênèó8i¹FùÊ ¨Xó®M{³«ÚêÔºNI%ß´ö6à¶š¢é½‘.Ç}AÛ>Ö냖ë0ÕŸy¿‹æ}’[íÚë9 åö]¾c2^•+&ނýÁG:áåÝ{iê²o{;zòÝH7(»sm—"¨’šêŽx¼•b]Ns·E¾,åa¸º¸³ASÆ1ó—´¶”G¶ —5LÅ£c¬%ˆA[IPhÔ)N8íýÙLj“P¬Zº±k@—±nn Jl¨¦{ÏV{ÇG+•éfPR¯çA ¨E"FlGÛP‡w€ðfµÑ·}œ^ËC¢30R¬¤B÷Lò±ç\.§°:›ž—šQÙ¸ºë—WJóa¡c—˜3"ùa@^‚`¬o†ízÂï¦{æUÑ8GI°Ÿ¯×gšÔ¼p{]Ku˜)•±W°"¬\(ì8÷tÀÔ¤hpَ͡ý‹I)¼§vûÚ%Ä(ñó[DûÐãݤ‹n„W¹¦QÍÁ×H-e1¢¯ÈÙ ^u¦Ø¦¥mNÛæ3 ë×7Ï1‰JuäZ–;²sîÊU(cVî«Ø˜«Ë4E:ÐËÇ;“,åš=fVä]ôZ9ŸxÖàZ{)xzh^è0¨ϲoH*xå¯|æÞ¸¹æ­™Û^·í@ZÌ]Ã2ì!Š ÕyîÏe^/‡TJ!Y­x†g];9ÏÍ· Ï+¶¥vô‘÷2rQ»¶=ö1Do¸¸«©Õ¸ ¿&x¡n SÀÞßJµ:^Ý’jÍÃÈÎcZzH~óCØfÉžKŸÃEÉ¥‡)x¬·sš¦Þý×É`ŶrvR¡–ªwÒ§ØL§Þ-Õúí/(åçzú˜ h×h’*Åz‹Ún9ANÅ–§=ëùN«ÎQ×–pÏ.ËBêzB#.ï]†–)Ó€No6t*Ðy`z´yxz›Q(&W’°½b`Ðy½{ÛÖ8qâðòé[Òó‰¯L4fJÔuÕr‚Ñ)nØô ·inzgªa“o¶š×EâÅ6†–Ô‰«û} ËÓggf£ŠÕ “ŒÆ~ÐúSäãǶæÖU-X /jRÁ¥ô//o{*ßt¥‚ÖV”P{2öբŪn!ÊnïRáÕ”¨§iÎôéí.çrwÞM[j‡±¯Ve$$ð2O+Ƚ´·°ŒyœMg-Õ{K5ïX”öj¶+öõ¬«eo•:D³ få@Å»ºû¤2_Êó†«ucª"ø]ž]o}¹` ñ˜Ì#++Dæ;zbyήìhå´¶f«ÅWÕŠ±”Ͷwòò#¢+…&‰ð·Ð{± Pá¿kuÞi*~*²n¬îÞñëø}‡výÌŠ»Çf'¶²­7ÉŽÅí;{YË¥‘ÝçfPSÝè’}—¢iö»hXoS•YJ3MÓcAw‚hm®±c>^ k8³“¶jɳ––&9@>v©¬ór³A8s+4mÖCs‹¬aafo>-ãWÇ2vèé„£œ"ôÉ‘¼œÁp_+¨,‚’"™Åg${½ ¦L·ÔØÔ÷W%´¿r5(;¬A™[½˜Ez£îu§é𢂰\æC[׺÷×Xv¾ž†,ç©£%l7Ó¾¨‡%êà«0Æ©±Ý)âJeôžj—«U°éVUóœ1\€VW_=ÊHõGç^Ö³j éhQ¼TØ„Už÷^$õËO®­Y>˜Ì»rµŒ Pñý=VÝ¡»²„ábò¿-ým"ÿe4`„·Ù§ùïF¨Ñä¬^W)Ú–r ` Ê)ëÍÃFZ6ï…÷0ej«Ù¸rí§}w,Æâ‡ÞŠhƒ¸^™ÐÈò陂!9m‚¢™S½GÔ²Jjëusp‹ZÞw.‹YÔs*1/©‡ ya ² VšÔSCjDí¬…òðµVHeøLµ AúCG7_)¨¶±Ùë÷գ܎Vˆ2®g¢>»;Æøá“q,ócù½“…ç2¥àOB Z°‚äT[=Œ¶¶È„osla&Æo4o¨Yº'6Ƽ«ð'+X rÓ2¹ÖÖ¦Ø `ò'6ß7Xí§î“‡zç“t¯m28ëhecxæø8ö¡¨oÙžáo¯ÐJÕT´ctáí ¢u GmÑŽáiÒ…­TDzþ±Ä*Íd¥HG'¸Í˜ß|Ö}þ»òüÝqñ¢C³eKŠzêÎá®Þ—”Ásv²Ôèï8]dê™'éÍk@¼x/Jä¡83\ÛʒѾ­s÷—µf£ÖŸ•_²MûG‹«ÞApáPâ‡ÂmùJhõè÷Ùê!*`C«¦T¹yQ"¬)HŠ]Ú š2thzˆ|f‹Ä7Õ¬vÝm<9ô/E~^úýë'Žê˵µžÛ‘Ù¼èÝBÆU¼Û«Á´ïQê×àÈ ä+ çºÛ//³h¨2l@ÑÉ4‚O=síÀ5Öžê#§5œ½X¸Úuk©q!žÜÀïiæÛ§¬fW6ê*œ–cÁË8éí´îЖÏRkËË¥º|loÊj†¥4=‘­»=6êRö¬X@}¾Ó×öžÜäôæLí¦Ê’ä|®­ôÙ†èiwbÉ¡nu™Ž›]Ö¹cQæÞ®5Ø/­‰ßž{s1€»Ê z¥Ô’ðÅõ©SZ¥G,øÈg¾o×­zѺÕÔ…ËðÓr¾Ož9Qí9Ýd<®¦B+µAŽµŽˆ¦13³®kªW»–òãG{mÛ¢ó~Ëhpˆ¢>&oÒµ™ín³>6¹¾f+£s%å¯O3ïÉ8–ÚýÐV~™AZn¼ó¿ZžÜóôg=éð¨mžëXqà}í+»t ÅݵºhµÑhœš’ƒ5•¼9¸ÔØFRKºéwÙ‰1T ì:ÌTM¡ñ¹xû —^oÔ:¬íŽN¹Ù£¹Ú$cØ5¥RÑ$Ñ«Iö—¬>8)iCV°«¨Á¥´U͈Jr†z÷–ëì´Eàïvœ,XÀ/fµNQîK/l:ÝòáÑB®Í_k‰&5½…Öè°„j:È’Žì öõ꺠¯Y‘x ¸é…Üö°[º†^çºð¸9¸6˜{¦Ö›ê×o€j 1 ÚfוÏqé¬Ã•Òb /]÷S.]Íž]w燨ï¶2sÄ/‡ºfÇAàPZ èÍv³@ÜN¾<ðÑ\mÞ¸›Í€ŽÚ©˜_D%·“ {b°Vlí¥¨v;5ÜÍèlŠRŒTeª'…j¬‰¬lºPä2QöxÅíV_½@UíxäOR8(Êðfº—áñW@xO+ÜníV—uË¢fbʱ¶uà 3AÜ7°zçÖÚƒx\.u‰à¦iuzý¹›Ÿ†_«Óç·má¨uo/3w\äh«r³µÁ:öÑÎÀĬ¡WvÌ©N¤¨+˜öOQÐ a°˜e¿é¸Ç´«¼dD^:ìJ²Ê€î{»ØhÐñ(]QÛ]¦³Ø4_¬­Ýß¼ Ñ(tú,_h]¦²ltÝ!Ú(ÖŽË w•šÈsbéźã:´›Z³jºv.–¸0z-S}w¾õ ]%,N×€‹Z œŽ¯*u£c›¸üù_6émaT¥Žíóé"œ<œÄ÷s0^Ú>'{¢,û(¶æ%i§Í°h Ëki¾Á5Û.=p±°)ÜQ˜׳ý·ô?hŨ܆܄@û-W´{ÕÝÄßµ“è·€Û̺ÇBêúÊÍ´;/ºõ.6£‰ÓC„.$ìç Ë-¢Û˜fuÑ ÷ XŠËJW¹ûI–‘ôà‡OAiœ6ºò· j×f½Wg/7i§l)Ý‘³¹×}9ŽG2'SÎZû MÖ™]±ô½å–ëjA{Õ´ìœbÞéÈÜë|b{Ýw֬Ϟ0êrŒu¾|Ù°—nÖ Öë¾á C|§Oe¼C¼<ß+ a‹«µ×—¸ßµ>a ˆ\o›“5Ä`ì˜W®?·FŒI«3Èg>wI Û½[͵ɥW©¼7”cBÎÈiNmäÒ¶îQÕ¡è´è¿õéê•qñ^è´³‰yõÔæâ¾Õ¬JÉà ±yÑá½ý'²•½î¾^fõ£æ·V®z!O¥ðáéÙ¦ÂÌÖJ[”zLöC=Øœ>´¼£iü¨ ¥Z9ßunéØ ¾Þ²#³ß%M•ƒ¥nÔÆ_°Öy:æ}X·‘{®L—•”T«™¡É&5o1lßm¹5ŽÞEKöW<äÄiУAâä´µ¾È¸rˆ#æÍ/I½g¥5:²†Ë33[6v ßšì×RÅìi¡š¼MzXëõv¤´Í¨.P«ÚHm ÔF™Þ¼Îêʯ;¿W‘ÖòÉ&¢·'¸ÂØ^®¦ÝÖÆÐâ÷¹¢Q£È Ùy¾GtNÞâ½áÎÈBÖY¾eævžå • ÄÛw‹¼±Vv÷3ÍP°ØwBÊlIÙEs³’ÎnÑB¦[ЮÉ(åšq%b4*Ó”k·3^Y¸`I-榯H÷-}†º›/“¢`¸øå*¼Zâò¨•¾šª%µÚ%§ò÷¡sÁA¦åm‚2·:¦K+Ϥ{Žò[åïy¼øciJëõ-˜:éåñ'PP½Æ16Bׄ7kvÝ{ˆþ(·ª»ÀÓi‚7ùÞ-™3G´+šf¿‰ši‰­mõrW§éž¾÷=•°,¤c{¹yá¬ì¤«T¿v%çwÙ;ò›X®5;¦Mó;KR*Á ·û_u?rŒªõ\ööUÅ}Û)ÂȰé{(Á¹–¸öªP«²©ŽR7¶l®Ór* •¸f›Qæî€d³~.¹žÁ2w¯9UÛÌh•.…ÕˆÈ.^>«J›؆CW”{‰ÁËîwÈÕñ=J»ZŽ×o ³Ý®ÌCPÉÕ|ë¿o®DûÜÖ^œ1W¬:E¾ÊÞDZß6ÅZÌ;¥Èñ£Œfmªýî×W=Ñü¹!K –lÀªóËŸMNž}—p±žáéf¼0êˆW;é¸Û>Jq×¥¨¯C8ÁR˜òV=SOáÅ‚ÏÙÆ½HìK.¦ý6[²G\:ðoæ|m0®ÑÞƒ—HТÞjHä¥05^Sw*;žÏws³CØD^Êçá}Û”“=ɧ¢¦+§±š'iæ![«[ì«w²jsMXÅÐZIgdâXžBƒ/Årëx6¬u‹-b®ØÊóˆ]·ºÔye Å3ïÄ®•‹­)ùyN•]7o3%÷)=]+^öa]½zö$Ù¶–]œqúh©ÐÉÓà'Â÷•´Q9krÕŠÜòRÑbU*YC—žèdš8vÖds$êBŸ¼ëë³áèýW^õ–=ÒâðÉÛ3!TŸ©–ÆÍŠvñ2ÙyB\@bÀøSàäWÝk¨ãX‡gaT0¾bè½,•¢Z°ùÚ¬ٰךaÚ¼WNóÍØÞÏ0V›öz´øöÝ=Y[•“~˜%a3s…uwvŠ+¤¶¹”&Ù¼kFúº÷&ÝS3+º§FôtÍÁ,¦0¥9Šœå÷פ‡ÙÙµ*:*ºøZ‰U…[Ü,Tœñó™Ü=¯Äºž×ãI׋tï§k®¢£ÞhÄËáK"3Q÷Ùˆ‡ŸvB <¡š¯hÚu•vš(µ¸è*ìЏ}0›çÓ.³(¶Èg`¹MwLç™J†`k–$érœç=â˜+”ƒª²ï,l•¡J°{å=8{2Ö ;×´W°6ߨ“fQXõè_ƒë޳Ü^{äE–÷ (Š—€»™‡qKµØZŠžªÆ¬NÀGÓk,pVÖä«°^×S¼uÁ>6MÎâò„V8·n÷iùÜžžãW¹îƒ ³£ ]ÁV´*Ä];|$‡m1M:B«}"£’Å]pè–½\Å-w“w.Œ{^Ûö1<·¬tš ‹;«)·Š1ë¶3FKñ~gÙžv¸Ô×2·ªTë2J t¹Br©€ sákš8ÉÔ–ß×ÖîS d”«]ä«úùŽw–=åîmu2dÝZâÝ—Sî•wnä¹²»gf[s_N/e*vOœaãØj‚Wypí¿i}Ú,Éìó³Ý2žáö=Ûáí5Þh_­¹l»0™Þƒ» Jì3jÖ. k¥Õ ä/aÉ©6­3ÞuåÃÀoZw}KÉÍÝ'g…ˆØ+¡]Þ6šxóa‹scØúÔÝ JèœÄd‰¹9©“9&o ݨ"*kæ°ç»Zx= ŽÃ\‡s5®6v–å§j_UBO^,©”š$nô¥»­ ²î(EH™{§×µ[ª¶¯Ô®„jí**Y¥Ð®e%í³]¹ë¤=^jºzþœ½k^çXpÊ;së[‚šHakbÑ~¬ÅR> W ^Z•#¥½–=‡nžÓ å¨z¹ Æ…ì¬Å·†‰T…ïˆköZ>Ã|w)=ñì Ðï^¬¬ãW¿!s3U±¦ñÉ÷4ŠF·‹@_Ó[ôï4ãV»0Í ”}•œtP› ç×…)ÛS8æ §Ô;Š(j¦ oT¾ÕªúåýÀý'×Sï¯**wKeí°  ësÍwvoÌÊmô°:øs¶X[ e€ÐîíxŠ]¾}u]^N—áúšm0ئMÿn ‘2®¬ÙWõÁ7—æ ž‘Ø F,Y¶œ§=ºüE{4Tõyë™jý9bº8ÍJ_.«›ÏŬõ9¹ÆÎº„ý’§h¡‚´ÒæÕlëØ9R¹\Å¥ac€pJ[ֶЙ¦š©w…ULsŽ•0ºª&$ÙÛ™¢3›11®ZܫեõóS(åÝa»õ˜óÙ"“½sÓ+½9ÍN¾h×ÜvQ»º»®yÆï[ûtÕ¢r±®ÓèîÛ*Û-„õ¦‹õÔ‰{‰éôC´ëv“`F9fpðþÃ8º@+}ÛKÑ]¬¸CkíºB›ÅDÎWÙÕ%'­jw`æ\Θ`o·PJ#bn«…ÃS|*élîàÔ5ÈJ*ˆYëŽi£¡-ótsƒk1@v&ŠÏUÚÞMŽ©3×ÅLÃWµÇbsÓÛ¸» Ý¦^-å:7oƃw.“•…œwTŽÇs=Ðî`°¹±—u˜‡Øì[ùŠ,J ö’³;Ƨ·˜xYËÙÊ_Éß®‘c+—vQ¶|ØK Z}ÕÃNåÁXÏ'ˆÁ Ñ·´T¹äíÚÇB»¸¼ø¶øóå ÄèÖêî=Ûóð÷utEÑô¥º²zòÃvÀ.ˬ·J+ð©çµå*#zŸ©!Ý“°Wv^¢o†÷Z}3´fô«çÚDEíoVR%ÕzuëkHÍÜà¦ë³ÖövÁ°åtgwžZJ¶Y4ÊÂ{n±Âv}´fqZH»vAw`Y]jÓ¯ÛœùP}p8©éÀÞeÔóa»Xe岯!öຠ¯¸”©¥Â…>á[”V™Ë(¥X9¶l;ÐÁ#q•†¤C;•ÛyøŦ%v›C¢·ÛXk!jÖ’ š ìÖÑm n¬;Á @–éÂ;ã—ZŸw*¾{Ë–óÒ¦+Ík«¹,±³ŽM9ÚTôœ62guö+ØÍ«NnKàáλ´Ì6ÑvXÅAuÃNUš+7ÂÅebÞë²ï1ÀÇ)­Z¨šŽJÃÑ‹©ñÝ[}_Àó7tê'„0h Jë „+b\¬£UÃodD£‘Áz  »ƒ®+×ÜqšÇÙ[tšÂ(±£lÑÊz#cd@ÈhõÓ6ãMǵ|§Ö&‹ðÝ«NMÖf{¥NˆfÍ7t§‡gœEn1ÈU~¨ëÞ"YPßeoWo8=ðnv8m3Ùë¯k Ó.¥šöqŒæÊ]²Yx§s®ÅJÒÞûÚV./Þâ tÝȱŒb³gµøv™§ÞCHj²÷œóˆdÉn„8¨ä«b 4òÎÛiU¿v7y3©—ȤêC‹_3²C–ñkoº²öõ©¶²ËµµÈ­•Û¤ó|/ë’îÊ&ø6Áy“:€±/0®½DÓÜÒŠƒG¼Põx×D¶å2æšN€òøè¼^ãMADlv†9Q™[4ì-­6± y¼¤P;‰Õk;L¨=·Oãˆ=ÝLª+ Ð÷RÅmV¬Ð-Öø<Ä•ëç\8Š’¦A6ÕfñMÚuÔPãœÞ^·tªXøƒpÉu€‚h\ròPÝrÖÂ[•Û)ìë7@òCzYRbô•;¦]k*–ïg‹T‘[å݉mêÈ:Ò´ÇiÕ_V5«L·]ŠVÑtBFnö¸P§BwwZ°–%Ïš"å•ì5¨Z2ÞÅgmz´ì ½VÅýžò¥`¢B>î¬ùbçJ¯z`¯i±6q1YG%Ù;.Ô|Þ]˜*RìWO«Gi£“íS]¢:„Þ9jú÷2›Sæaóœíz˜Û‡E8µ"Ýzü¿·2®]l•[³|ÛÚkØ„ËúñTjÅ+/Z‹zfg躉ã&v÷áÂBFÔ£¹Ýü+òYuÑëîêZë(Ð÷·gDpå£yà%f #0z]pãµ&çGvn¤Š»ëËçJ*¼ZEßR%Z³{ºÆ,¿>Âl ï~êʃÎÞ·K&3Œ¹Ê{†äê-Ü¿?±RÚ—Š.êí å_iÚ/¥AÊ@¡•»Ê³/¶È¾Ú-0÷Þ6ôc+¶ôÆý­Ú9W=¯vÖ•»t„àŽmÕíe5IçÁžJ¦PîûØ:›}eûßWVF­&²¦½ £Ži™—Fíšèß**l”•bÒwšÒ\éËo·»'«Šæt»¢Þ¢/Z§eÐÛ£ã)RW%ûë°´Ó`Ž7æ¦PÈ'¦×“ ¥Çl§òYCêƒxÂÄšK2)c¤î-•+xî³…îîÅAÖª[V÷.–6D¦k¬g¨\CƒÖ‚ˆVl•r3ÝxéÞiZ_XòÈ@}S…•”Ø–6ôÖ>\Ãïòo3»«¡™­‰iX D:ó|éí«b°Á­+*ñH~’ƒåø;â,ײtÊÅÕR½´«t»u=ÝÓBwaz;{H¸öÄw–îìÀxçY¥Ù ëZͧÍ ¤'qÔîfú#ªí5óg²ŠÄs=»¦3ÞAŠñ^¥`f#¦ w“Eóf·_+<¨ót ê¿Yw•OŸ·9— ÍýË(¡It»T¤˜6ÖW²³Y”oßÜ¢sV9Ý:¼UÕæ¤‰¨®ŠC`­ à‚¸`,SÃ5]q|Oa•t+`®Þç6öÝ ¿°Ó6îÕ! +t‹ÏÅ‹›ÚËÞV5uåámŠÚq“yX’Ø‹1ŽV=¼×O.ê?hZh …Må½W´žr10ó:S‚f«–}|(Þ«*7]®-Þ•ˆmޝoXÕ7r¯Hšs¡¡ÓÝ=ê¾ô¯qe«N­•b¯ƒ¹·Nаé ]x)>rž&Mx÷k «É‚ÚH>Ä‘ã}½•<“iTÜ;Á“/d㼑Qh݉Q'muaîåóñ)ŒW$ÚéëÃ6­PW5Ua3Æx`ŒÖi©q÷£$=¹yÛŠ¾}¬ëÂxõãëH#]f–Àzà•Í*VovßY’ÝG¹ÕÍ2±÷fd¢äöQDãA¥ê“ÛÄ— €]ísUÈÒuwVC:ø¥Å £¸ìqÓò#°·´úÅ'¯.pæa!ÊÑ3Ðv‘ 4ÇY°B›Z§qׇ4 »íÀw¦[»~ès)æN¿ƒ¶Æ9®)é¾â+2¶W+3|<ý\7ÄúÉïI[f3öÃeÞm¶ je°ä«cºŽÜ»Šl Ké·‰ªm…Kduœ]¡¯Þì<ÙƒÒÊt¬Vcß ¾¾ciy…ÖY€qÊÆ7÷…ÉVºëÛ-7žnЭ%{°ÁΤjøeƒtiAôî2Ö!³†[]f¸V-Á>;g%aÏm8ÂëEÑÈuÏ{ÃWtj:ly“s‘g,ØíU)bºCÒ„ØP7½KTÛÏ»æýñïØÈþŸ­b½ú³+¸Ölõ½êèÈ vÀ² †õóì¤põžÚÌ|*J±]¶Noe*/dë?/Þ/ŠL0â5·É¹ìÃcÞ[yN}ol)sŽ>ËÇ8ÒÀ šäéq3>ð­s¯†qïrÑ@N[Âíâ‚zäxû¥ éî£-o² 6ŽW«ÞD;4ñ—Œ:C¡Ï‚®q<ïµïu'×k6n×¶šõ\é~Áí­ú[1:Ö\Ýh×E +g@ EH̉ðÅlÍ¥Ä`úÓ;Lù宯S{ŽÝ“Âu)½óÊ0çh¬8ê Ó>àª;žP³Ùzt¸à–B¡jr~4<Å9+˅ݪӮe;9YBÎg˜;Û³0Ûƒ:¤…ÖCW ùn5Qv5ÃkÌùŠO ‰ðx,uG[·ë%nucèñw¸©FÅÝöšÄü;¢!)S½Ýæ|}æöjḫ=†šÐyŠhwÍñÆlßÀveüô²uT™Vt¸è©º~¾C2w°&]S–±—8V2ìeb0à–Þâ=n 7íÚ»g©Q|²µ¥u(o[wÃ7³Q¶,³î¼Z›]žÓßG6S÷:›:eªé½u®ÚÑKBŠôDU,ÑŽ£0Z õq˜gÎ`x‚áâ{&»êE}í2a¢–Þψ«ºå«È¤×[³€i§-Pív©K@ ‡"§U×]~»u{­,ÜV žŒøJëu÷¹jºáêp)š6g]qð­ ¬íÞ7oÔMÐðuPÛÜÒmЋÉV­°4e7\7[J=.ïP»ÃFdíN•©nv7½ŒYï¦îéÈ뻫·(¨^%Ô^Þí¶˜'¦j—éœýìžíôß ¼«Äå`lÛxáw¿½\÷-«7[¯´oµ¡Ið]»‡ÙW]µÛz”½vwä©/·ù^Þ}$×ߎf-ÖyаHC'g.6û9©IØsî©É\·*dºħ¯rV'rœTÒ¡nefÙ†ã6¤( h¬¨Œ¾×jç2®­JZŤ1š¿Ç̰é̯z—ºù´X¢äÑÔ½h¯>^Zêí¾Ü¶ IHíÖÔ£«®vGÌ/F+Éó (G¯(f߬enÀof¬­!Æ2vf7Z¤BÆW…ôkF@o0ɶ,óXÁ-ņ»d} Òä˜Ô{v5¹¯¬ÅN­ƒK—Ù²-Û¡•tùÄI³O0ÇiÜÁó®Ý ª÷*ÕFí¤3 }á¡UÊ9E“K‹¶Ó@õÎØ•Áéa.µ”ä×—K†í§pcælÝêÍ¡JºàÈðÜ¥[¬lÞè¨×I²Z#[œñË—v,•w&`(×_#ÙÉZ$´g=£y2ãvƒ ·Ö-©,ÃÔ·kIKíèÚ.soª.ŸÅ¾³%~_·Y7ûšŸ¶’µ®Øë¥¢Võq)ʤK¸³q¥œöÀ-ž‘`o…[[ŽAÛO𲏵®¦;;vv Ø÷z²;¥Oæ}Ã+Þ{µ6»ÞÌWÉ·Àw%­rK¶DÍ'—].e‹O´“Ú ä¶UÀ ¿‰Û®§·¹nPH¸¨œ; Eª ë)ÑulÁ`ÏfvËaÊY³£Úù`4Ý*ä“¡K!¢Ÿ}YÃt¦mX VVŒQš¤{qÓ·RÇ_=#"ÕN!—1Ù›fQšÒ/­»Xèr­Êw´åwš cy`R‰öW3böúà«™DUû:tûǬ®O¸"in] Îyñ0¼ ú_½:ð{ªvõ«{w’“¾HQCXòæ4Ú¨+jkw“á…Y×ggT{¿lG«hl»‡fÙÛˆc®­ ©MÚËUs¢›)æë;9Ò' 0Ö Ë9z±ÀÁBZË®Êw½´kªû–”(¦¢ºÇeÕn¦%•¹ª¥R蛺«k,ËDÙ°# mep lnªBÁ—ÊBr‰hÝ䳓[dÁ*#|†à¶©q~wš»}^ÌjMònŸBЫ s¨ÙÔ]Š=O5Z ]V+íç&t¼šÔÕÛWˆ[i±`A¨Ö;2¦)ö"â*¢´hÄ$­ÉÙ@£ X¡é·®³Þ묇ò¯a¹ç†f¿ƒÜÐ*r±eü5;kK§—¯#)VÖØóSE×£ÈË®ð.{v\h—‰$U*ú€²P}¼­¨5Èðå›Õ6Ž]»¸©ÇJ² ÓVîl¬‡9­.MsÈ©4ïÙ/k\õo#z=Ï'7UàWÒñ´CyÖñ+´÷lÕŠY½Üyc"æ4åLo£ òŸv;+Ã2"W`ͬ#<ʃM¬ÑîEð–]nÞ^.¬x…*‹zÛÑÔ¥‹Ž®ÎB´vÇœfÆUÛ8¼zu ÎíbÆ·÷VSÓ,c‡Ÿ–ƒ}IW³VxæØÄðT½˜g•”#˜_ÙJÆ¥Ü:ÙÈ/s ^~W¹—•lôÀÖáÞ;Êã}8:Ÿ±žK€]“KX ˜¦ú^`êî5°åu_.Š:kƒ®œsÜP[@M·7³ž†:ÊîëÉ¢…lÇ ”,‹K ¶X²fãÔß ,•=Û© "û3 ovÞ­÷=Õ°1Ý€q[ìg ô÷ŽºO–%ÄÀ¸vœ­btr4Ú6´LÌEé Î} ªá%=Ô9«Mãí‚ùc+´òëá}Åû«¶ç9\µaÊýû-ý£¸ ‡roõm…; 2Ñ׺5.ÎÐ…‡öÅ—ÖRIfP¿M’}/'qÊÞ'ÛÑõ϶“ÒÅa{áÛ"¨0D»æ¶ÝOdwËÒ•ò¸¯Ðâ»kn:Ov©s2ÊÅc·¹šé©íR¸¤n•K0/¯p; ËŽkÅ!Ky|èwYx!·>±“6Y,òº¼|"ÌmVõÔÕo–éBŒø-ûG\ϳÇtªðxUåw²Ê|÷ׇ¤èûáâ.Èí¨u«ƒ3„òAJæ[ë-ŸÜû9NÜÐ ¬§ÑmÙÇišJóÞûX!ž)¥/D]CPÍí¬GdG¬}*m •k‡ÙQ&ox¼3¤}Ö(ù¬Ãî‡uåwŽÚî1¢)…hwqœE™µ"ͩҒk(v¹¹¹m즓í«×–P¥‹Œ.ëØ:À–-¼ìK)ÑØzóVÒÞ€?z¥º¡c¬‹º{0•ò”' }h†{§³îžÆ²­®½]j%«)ñLwÃJÞ•;rË=¹Øuéu)îWP¡Êa–b««ß;໌Dg×)p¤<³…„XÂÔ4tÔ‰ãf 4=í¤FhÛËá­™eîËBºÛ÷¨ŽÒ Cڨ΂ #|ë ÂüÀ¿V©™ÇÀûµØS^z¢^¢â®Ö¼#º¥>8•}(bÊ€AÍ¢ÝÚÜ©^LíM”1§“YÛ\ˆø!ž7jVJô6§Ö­»…žj£àIÖ9‹s@ á8‚JSÂ5ò݆Xmj8ï§v‹QÇ.¯‹Î Dân×ÇËÌŠÛCDËÖŸ™t4zénZ‘f.ÈÙbõâ vè0”¯yVLt«<¡­6s›bæû• ϤwÔs}µ¶~n±5w®È¬¥Á+!jóŠå^¹ÞµÊ2e%ö5OÔì"¯vŽŒVk°¥Üåëנؤä¹4çN âÓÉé«1Ó*"¶ß˜ÛÞõùX稚¹Àì íLÕµ™®¸^ÕøªÆÏŒÅ^Y7`Êzð?y,¿DÖdYÖò]l[kWv¶=µç á{€:ÈÞ•ՇæÇ¾ç‡õãfÝq9Ø÷jëÄÑoÖ‰®ÔÝýÁÐäFƒš æ *ž¼¡ßE+F±ÖæœÉBÖ_Üpô¢ÇGอ­·8\Í£ÒVþâÝyÎ=WïÙúüb«©lü¶Æ$Þo´ï<nº|W,«r­T<‚¼Þfi«FnŸÜ×ÁÞãyä=[(ªÓÕµ¼±¶Æ¬—Ó&&>W#©™ö»Ñr¥{i.›ìîÖïʳ`eÃíE]gEÞ¡¸¢®ÍŸ{ÎráRµ¼¦~xöÊíjÌæs¡\µãÓ¥ý…a†¯8žæ­t×6^*Y»¬mZ Öê†é#ÚºÅÖ[–E+¢1áÚ[€Ž#M¦{ÉÏtÁWõùój1%‹nó0dlû²yvuì†îc£7Ñì/uøx&|˜«äFá äǼ ±®˜^’ J£˜At´ß ¬¬»ž;tFä6¶éíƒÕʤP®6Uæk8öåºb˜—J¹`yºÒ˜tµ¹Úžöpo-ÝYMŠÅR y0Ί^uÊ?]Xð &8>¡{š/H¦&`ƒû¬Âú›šŸQÌȲè'’ç5knxo9€û0è’ÖrZBôN!’òǧyÞ-ÜÕ}‘L³’vÔI¤èjÅOŒì$Î¾à—  ‚4î¦qŒÈ 55ÑêÞšmQÇ+5n\¿€)÷Z¹‚6šÙ]gtÐsˆÚØÕvw*:‡N´…åìæžËväKJ5ˆF©uÚ€àŸsªå(ö7²j1Ôí šîãx~²>á0É›Lv.¥o‚¼ªZl:Ù¿,†@2,íóó` z‹ß‰ È%C¶û®³Å:»6Õel­Ng;=kxî·SRvlb`°6ëU 8æX¹N¬P6 †±¹¡ÖêÖ['E™ÐEyPª™tæVñ–û²Ã.¸™–Åàh Ñ·öÉ€ë2vfJœѯ!eôÅ*ÒÎ: I‡Ù<îºÛ9*ÛÛ×Z µ ñÜç‡_tìö©Y{ ì®Æ}¦cNÀÚ”¸`Í­Î2®]›˜\{ÔjŽ™ëîÜïUñ‚E¯g¢ ÇÚR4Ü8®›cø=‚Õç=ôû§=Lé—‡5!ícêj1”'9Qn忇l{ÃF°T „ä0òÞç±™—757WÎ5™Ö-‚àeí _fì×Põf­ï-D“ìå"¿V„î¯Q£ª"Ìg;,nvö]‘†@AX;s“i"»Æå×-­Èiå F¼©˜+ Ó)ØéŒ¼\ÐnuE—yyW!g•ÝyIJ¬o7™WµÈ.ºÆšJ½4½Œ7¯¤¥j°—bºó˜»fäIW!ÐJ{÷·8ß%êÞUb``Y ]&]¹¨ve/z¹*~ɯ;`a™rxÞN;%¤žlè:æÀT‡«Œ¬Vj¦W¹æø«>ÊÑî4bǹز,Q>îN[Õ3wc:½7ª8{Õäe-] f^ ux%zòø]¯T¥Íw§3=£^·´"¬¯Dnæ¦ár¶^œé ÄËÉJŒ¶xíY겦^©Ê<6”–󩘩¬H%»±mžÕss‹sWÙC¨Å³in† Ö–}‚]íˆJËRå_{†G…í÷ж¹{á¼Î¢SÊìmàA÷]_]cº­µÃAUG1Ó®x©*½¬±\¸ ïq€`¦Ýªžõ©ó‹Aóœú¹*ÍÇI¾ÖÖÃ8æ Ët­g[·fÌKܶKC(-á$î_¸û¼qétu;qP9äøUõwJ›½´IK©Œ‰Þœœ^ß&+K;‘I­9{c5ïÆÍÚÍ'¢fc¦³RÙiväÊT5'Ë6U†¨ñ’°gctžŒ»†!Ø+”½@õý¹å&û:óæÇ+ÕQßÎ|ˆ2îÀ¿µ¸0Cˆ=¿*5vÝÝO¦íâ¼_výušw#òÑWÞ©IJ_ñÔ›oçí0Ø4fî]'=,Ùue瘰Iƒ…6Ù§qFyGpX`.£ ãRŸK¹C±®eNèPÝì×W4+TªÕ ÓŒó£¹Ykzq-Yúœ!h;iË)ÁÉt ‚›Ö;k6ó«)ÔIØÚ9tz3O% cÏz²SºÎ˜zÕëµ±/X'™¾y£Ñã[¾¥ª½ëÅRå²UÐ^]ö¡Ûê(UƽÖ­Y_F“ÕmÚ¥õïhÉã^Zó=1ºM} îe–•æ¶ùj«©-=c#“\ÈèÆéo-vJÚîÂOp¤ÆôÑ9vee+…QtÄUa•¦Á“ºµ<Ø ÎÄ×aî¬l§-+oÛâINXÉ}C¾ÖåÞ¼F÷hYÓ›‘•µî]v©±Ãr%Ô›´Þ5{;”¾gRoMdBèÖéÒ°]3|+ºøõmruÃjË|äÞÄV춉àQz5°öÙõÕWßO“Àêa:1 ÈèRPÐä¹ÐÒØ»[ºèÝcJçÛKntÍÌZJ—\DÙÅ(è^ð͡ԹÞ:Õ™4]h÷pyb¤\jg7®6'|-v‘Vfíâ÷É›L 5>Ó«L»Þ÷«v–¥–·rÚɤ§Í€uõñÝ~½}æ¼s•5Äý~OÞâ‡Ô¾½ýî|+“|}âòAæë*þõf¡ë’­ßÈ  ðvrö×qo›[mÑ"ͼtà¬ë³# <”°”£Wa7NèÉÂVìP¬Þ4Dš†!F=YCU꨺–®¼ÞOr¡”¼{ SÔîövåä…íD9­­°à¡öÊjFû;jSî YÈ{9ìºA Gf Œõ««â¸‹[\a’eÙA î6Îu#k5ͱ»YYÌ6(wP‰qŒS[¦Ÿ`+ß&¦Þê§w¹ÍIÝ[Æ,Å\m•¢ÁÓg%%Ë%ˆÎ­Ó¾j?º 85¼O:Š ÊS¨±ÁShåë„#¿âiæ!#2¹ {xiÍ©µVcÌÝÝ߆ÒM„ ¦eXH¸ËsI°í#£B·š#·O—­³º§K$j©SºÎ3†qaÞè¶k:Æ«dÊréPƒç¬áKD«µºéн•Ha˜Y É•™¹®áÌŽÎÖ!@šEš°Øz/¶,.õÙÑ×Q Å—ŠžA rˆfc»‹C25m‘yjÙÅr ¡I† ×…î“§ŽÆ jKÅ5“JARwTÇÅJœßó½òð×HnL\ñVE™y *·³Rs¥q¬+‚·+åE^Vn§vmaC¶ÔÁÚ7×¢µ…ÂPvš9rûvº¶ÝËêâ§œµ©l”‘k¢)4Tìm,i÷¦o.õ(õ߯ýð“BµÑNùPYÓ<}œ¡˜!ô'6huÒŸF³²tÖ|ìˆçÄÒ¶mösÎyf.éÛÐk²êgg[éU Æ–ÌÕâÖö€vO½*ðð °=4šN° ÛJñšX¬ä¶ $²Fo,íZñáˆÎ°/t‰‰w)é<™­„y¬¹áJ¸úóojòŸeÜù%QÛç1u9Jæ mãÝãÝ#8î<›Jé·mk;«<Ѭêfë¡5<ûÆÁž~øÈÅw¯Djû8wÄ}³v ºhis Ù]Cy‘¸ÌHa•éì©ßmL†¾Ê/–ùôÔ«8+©ywªæåM¾nú¶ºíÔÖ–ù:·¼íÀMç«2¦ýŠëVÇ=W5Z–iØ©ÁË_”b»¯ÏÃ/ucÄé®+ëòÃwlë¾¼LÒÀþ-®Úý<åu]iåÒa˜$ÁD{vsðš_±5ão;tTUœ’·õ]5›V(˜kÝÙ)ë¥1KÎåyÜ6ÓÕkí!èºÝ`ÔwÇh£Gìì=ã»ËÍAÙäL2úVM ÆÞVÝ]â¶ëFm©òî2bÖÑ„qV.@›-ó¬[7:|`Uy ÁØC^·;«i‚9ζÅr ¯5ôä3Íó0t3«ÙcYêöñ³*O%´óº÷”]åÛwÏzq4I—b7ÚÖt=aS¢µ6nœ•´sÜËÙ¤<,¼ÍÚ!TæØs, v¢øçVJ,î2Mê”.ZõÛŠ–šxw4GN§Y¶n_=’ßZ÷<ÚÉ~èñbÜï¸\wÚòï NeMYɘk‡Öo³ntÅ-sU܆sÁÛ*ñfËKêîȵNd¹Kn2 Y[ì¬Æ–xñe·›Þì:ŠÙk±Ž:,ÀÝŠmÚ׫k¥Zè6ÜÔ*[ÛóyNð'îí_Ƚ´·Uⱜ«¢O¥k>Añçõ&ë)!’zeêé4hé/ÝÀÃåÞʃÕîÝ*×V^×Lt´#j btu´ÁlÒ4qs‘Aº/®ÖÐ¥Î^ìÁt`j´–ó«´Àª5}g*ÚÊV«µˆ% UY’"îb“oGA³o»; S¥ÆùUÚ5:!*¶1aìû8¾yW•4¹Ów¸ÎKÃ;Ô¢·P[“ŠLò¸u+ãG)RZ‚§ÌÒZ6’5unb²m¶¹Ø¥–-ì8!àX=Ã:5µ~*§$*÷`¨Ö=·ªÐTØAÉ1<ÛÊ8©Ø£J³w*bj¼õ[Þ«eI‰g 4©Y%ût3#­ø;ulpèϯS«”|´!‰«.†oGØ€‹é½¤é¬èäU 39µý>ÿ«å7ó0g+ô[y?]eKUÇ Ó“:ÃgNÉÊ>+p ‚“á¼â±üï*½ÓÊ›\û—Ç7Q^V½ìcYÙ¯:ƒ2x—–n°÷ªb¡;F—@5¹2g3¸ÀøUΓ ë#æïfE\d´µÜ&Î5€Ó¡¨Mb=®ÇÚ^Ñ»¼‘‘˜è\½l)ª]ðÈ)Ù¢<ÜÁ«ž‹¶ñÒ¥J²ÞöÎGíÓš­õ°Jýïe–ö¤Íóñ­Õv’²ù TJ;n5åÞt}•†¸N4¤G°ß·Ås_z¶öŸðªWXˆu&ÕÒ ·£QZM¬ÍJDkÈë¿ÈuÇ›ÉÉܦJmÑJߢ¯1±­µ¢C/;·¢g—§³ª{•°ùøS*÷kÅ#\m~¢íSÏxÕ½Ô­D©WæwVÒ雋y Õk›óC¬©t>Ý óµÉ¼¾(+D²8Dü¸tùh|7÷Ÿr­”³Ç>  šîU°7#Æž‹q%·Ètê>YÝív¡iqÝÏM¿…Íâ'· ÜxùæX’ÄÞ:ž[ÞÆÂy\ÛK’Ó©W%W×{Y‡ëî®$5¤X::aQrîWn(5Tqf¨«2Umâ5¼-[Ó´¯¯6µi\bR„VÕó ¡•x— E¿ÖÔÞ˜—”ß419ŸGƒA¶Æð™úðú±ThÞx+¢OÓÅÃåO:ê¾k…jòvûUE”ÎÍ7N‰Çw,â×+Ýr^*¾@/ÜØ«‡wˆ©±åMC]¾‰ã)2Nò'£L^€•X²íì}½l¸ ðdµY;«–WJ°K=…1M뛞¼äfuk‚»î°kF­òóòWçRòuÐãóbköCæ§°KžÂ¹—¤ öBm m¨{˜;˜Š,bxË¥‚W¸œ›DW.ÌâqMÌñöB¾ï@½pïpv"º7(ÁÚ”^mn«¬LÛ=´w1H|¯«5dζj| *F§Z ÛT0VëÕöX¹YÐfÁMØG¢óØ+®­Å±W›®ÒU˜èpÞ«Å6‚íf=j.LÍÇ:®‡ RjC«±Û„.ösòÞpÞÜ^Ù]Þ `Ú\ÊÙ.5fÆðG2o9_QJf³E½|ÒX²•qrˆ¢<—j·«¼hvÞØÜß)B‡µ…ç|á~‡f]ðÝÚ6–û¾”Uk\(›§‚Ô}Xo‰OäCv»5£Ô%WÛwhW™©‹ËÚÁÖk ìÖ;/ KÕ Z±BÆ£–©aqÀóË+qû‘÷ ùêæØHæ™yj¸ÍÖ¯ofÚòmVk6³ÉqólKCÊöž*Ãï]ö:uq¹‹+Ì[ Ö½frñöè•Øè[¦°ŸOZܲ™xÿ,ìŒöx”ì;²J²¯!sfejL¡CfÁùbÐzø%ã̆ÑÌG·Õ¾ŒÐ34ñѲÝ7·˜eøaMìÎUÙZ›—™G1´TÝ\ö”ž/ur~EyÞ®X"Œ—p6ûvIm'˜1¦)f]4p¥‡ë°¬Ý^[ ×H5ؘž 5eJî²ëV=ŒmÆ;²ì…ܬæ>í3 kG1äKáau(n–ïdû’’ïZEÊH½fžkJ¸ÖOzuõx·KêôclÖŽ¤DÛkâ[‰d‹é‰gV­hÙXsub®Xú^Η”_[K $îiåÛŠ··%šo+ois“ÆüµÒ§çÅ{ õxk’ïuüõÇhwMlé“v­R±<¤ö4†îdÛÉãŽõ‰ó»‡Ò´TòÍ륽Y„u|‰.…h!ÎáceÛ[ì°°Nè³¥åB5íôÛMZoÜ+"솠w:Uû×[ˆ×1¶÷ÕPî`)TTümSw•pÄ,]bå×,ØâC"×Þ)]q1ÈñÓK%ˆá»WÒ‡fÕÙ>ÝÙxðE˜Æ‚¥x7Û´)XvãêìazfËž©A*|zÊo¡´õÕtÎÞ?^ÞoUŘÄíWGŒµr·|j]K¡¸9MÕ¥m Þ³4­Ôa–·=PŒÐ7™ÙÅòš;/‰5Cu¬<ƒ±=Øâ¥¹µ7šÛ=f!bqçj=yìJpu¹Þ6u «5Ã|Ç*Ié5uŽé¥Äê(.–f&f߈Å8¡¾6Š(¼Ð¸fÄÝm9\žÝ¾\±wL̼šaD:è+”Ú|ЦSUŠl¯Ù¾õñýÐò«³ùžQïÛÞм[´Ê9Ãí¯¥Ðº|2€W0v¥ƒt$’c“,¾©hØÏMP®Z÷ÈÕðòtÖÁVüëo_k"ó¨.b8+VÉGoÈõw?„W¾6±d}íö+xõCÙWïKvjJ:0"å1rE+¹]òßMßg>}äüOQ&‰š÷—må5”àaÎ…= ['fp„ä㺢Ödë[¡«Ë&aRs|éûÙ†=­vT¾¯_M„/µ¥¾§upÌõžËÆgÙfmÖ>ã', a¹{™6ìm/±îŠÉȈPb׬jÙŒ »ÇÅÝ]Ù¹yo!´ÖòPUfÀFÏ^m=µÇæo‰ ç_عTͧ٫• }·G±ÚèLPì±ð}%ÚãÛE÷k™³Tº=¬¥vuÒÛÔ1Ò³ËCì »*ÏW'eж6Ú½VCZQaOvæjÔXjòGA}í©å/é}ɈԀ3Îôp«–¯¤þ3yo»ä«³¹ w9w”3˜,UÚYKµó¤¯-.¬`:èŠóPÎã’.†þÛ Hì×µ4]Þ{1M×=ë@®—–·¯:ål–ëÂM¤S´¢ÖQó´…nt¬[\FÙˆ']ísÑßn÷k+Y4Ë#(S°NÓtx×X×Âò½ædû™[O]7P¾²Ø«â Ê´GÝæ1mÄ÷¹¯v;ž¯ñò×K?XŒïš™zkLÇ5˜‘ËzJ»Š7/«7QÚ/–ƒ–𻼠uA‡0r*Ü„—€œìü…n§›øâ¦Ëñô;iu›“³¶EOW7¯¢ÇÍõN1e8éÇ»Ê*v©¡f/-4íJ½õ–Tûvµe™ï.ëW*ꇺ´\>t:öõ»¸A¼D¨jQ!¯BcºÔþCEëáǨ÷)t…¿Ccg·y_Œ`¸µô¾ÙrwÏ6ë25Àn©JêM«‘íhŸ"U]ÝÚŒhÌà«®½xÜo¶—Q7ÙL¨ô:»º½OïnZ°zëÓ˜š•Q…æ»§4tÌ'ã1½*¶åÐ{é´½®®ä»†+¶ÆH¹v²sÌ¥qw&o9§yShë—ÐRãÄW3¼-Äè-éÚ™™ï~Ìüiþ¹œï]ÞJNêüüÍ]‡Æwg*Ñ¡jVJ*ãÕ›±©¸•u y/"Ù+ºæôìP{R^ÝêÜÖQóÔzÆ8š›¢l^›—Iö«ÞåÁá–JqfìZéI X†Kg+«]hí\ö5YÍF¾uÙI³œ×Ú+r…–/1k=B;›Cá9œ£ƒ‡4ýh罱腻hßfŽT=hÈCç6³2G%I;«íË­IØ›®¬¹ÍÅÐW1)ê¼ZgšÚ¼½7ï–04=òÝw2®yŽW‹^5v´LÛ´kÖ¯Œ–â(i>W¶óØíæx—KggÚ~áCU-­6ÞF¯—SýÕ½ìÇŽÚté®×bã¢ÔG›èàTò³¨*]GÕ $VÍÛ¬¯’æen Š6 ¾ERºA|o¯ùê˜|p$/Ÿš¬\ñ†·S­žËùï[áã[Äôõ’ycÑ-Ål|O½ª W‡×h\öStu?FS¡‹Ø›·—ÍAv A0U…+½+È:Ú ÍõÖWX jÑÜ"îÊÔz–Þ6ö5uk]`:mª>µZF-°¶%ªùÄå¾KÎè/अƒÝã«ì™ûh¬¿¯4zñô_i”ß\UiÝ º“)e@[PښͣMÆ^xßiÚ­Æ çŒ`˾(«¹ÁoqÑALy·­Gg]«l³†ñ:å·¢åpG;í£{Ý<«µ·Ô8“•‹äZ¡Ü °®bH1±`£MHMM5×šŠ­ÎN¢·Ä«ç¸ó6VÔÊØbºÍ+%%—Ãk™Æì}œØÞ fÏ'¬µ xíDk¥r+¤% iÛ@eù 7ƒ XÎtü|·µé^øÅäP`å„ä*x%YEíŽçfg*ícHâ'£Бb"aÊsZ®/U`ÇØÖ»®æ2ûÝd¸‡eqÚ…÷ËÜ ÀYºSÙb•:ýš¢{&ú_Ó¬Ž{…5»ÃÜhww6‡Ñd Ò7ÌTP¡W<áWØéÜì/4S°½å$üŽ#÷gê—§W™¸'Œ.ßI·Ø5¿Ü¸øÊ‘kö÷Ÿ¨,·µÓ°MœÉ¸³»èÛ(Ó­áJ½Ð-=»2Ä|ÌwðG1´WÂhG+ÇSW”7qÐ{ºck%µá]Y×eÒ¿ {DÈ4AC«¢÷e——H¶Y½¬Ž:O¡–fi—í'lc|7iÝJMh{¼øÒŒo„'šuÒ¥ÒÓKl'3¢zÚ®ºÔfïòÞöL« Û ò[k—†ï[¬Œl±>q~¶ú vòzçoi/”ÅÀmâÛ=ËÌV"¾¬QÒ»® ßB ½Ý•ÙǨ!¶7»9x7ôÀš€\í3;o(ås}‹"â ogz­xEBL¾Ñ Vçºâ· ö9ãw1¢i®q­Þ^:}I „ó(iØ3)+KÉ2±xí\Ó.€”¯RÉÉZÜžžî  Hèe•pº†"ÊtéY³Úf½DÆ rÇfR[í´ ŠÞ¹ÛÅÌÄ(,g‚³Ünˆñ€ò·Á>­Øªü©šµâ5 îêÎL_sézþ¥J3Vï$´áÀlmžáò‰÷Âô®Êè°t¿/*èíW·èM ÎêÔÝ«Ðå@¹ÂÌŠÁŽÛ6TwQàyksíÌŠQt$[§f!g%,L¬Z*Ñ£…™¥ùÙ®y6‹ÓYG%9v£ÝÌ·¡*>¯•_VDC~¦´¥‚ÎW•«}‘°ï:o+œv7EÊ:¨œ‚µ¬}Ç·ZÚTU¨„öMWkàYR†ƒeSž+Μ"4Uçóò‘´·Kè<émoÏ*De~]|Iýi÷`°E!”s=’öópc¯XU±±z>P û.…õÏŽNœù:’‡¨,xzõ}fò¦¿{lv@šé+SÆž.j²”岯”}a¼—)оQ´{i¡Æ·º‰”˜3{ƒÅ?){Z½¤ÆÀ¡¹¿«^ï.‘Ýê¯ažÉK®Œ¯o»s–]¦-ÝedMHï‰#¥û‘wé£0뽆³vG–°žxh¬ðkg›ˆ‚RÙ -‹‰­W`¿VÍ‹&Cë¦)Þ%ÙºçfVo®áà~Íš—¹^ÙÕ7Fs%¦n‰UŽÞñ+§³ÀãpnkY :æ`Åp65ì³ÛÄó…®er/š.Že*ã¿v/OÀÊ}pø.ãCxîÇB.MÕÆ¯€x²u*€‰ðë{:)›p§ÞGÞíÕ'/Â’‚÷:é&"¡8}ÝXÓ û › ú‡°E’ W× ·jB˜ë]i²ú-‚¤:õμUg¬ í%¼íÁ,šò@AïzfûÆÑ*çÎ_VgWŽä|›~â‚Ý;…Ú;ÊŽm££*G“— æéFä°MM4«!ÒÕ/3؈èõ]>ìÝ¥wƒ'Û}”×i–}èÅxïƒPì«ïpƒªsZ9Šohõññ›Ó §¨\A÷ŸhfµÖŽ™°è&ó{ˆf÷ E bÕ;õKʵÒÝ^Ns˜*Úâå:ÐU1WµëôÍž™öºèØ¥áån¹€o\òÖ2’ ¥êÉPž¹©­Tr¶jñ¹*‚Ë8ÑÍ+W…>;ÇM[w¨E&4èá|ÅžÂÂ[3I‹ën*Ѹénß;7 ÝÆbžëÓ˜yh××úû­x#'-^)ܺº‘d^Âö[R3t »–ŒîµÄhM!:ŠEÉÌ¡Ï÷e‘·í )¿uÊŒ©ˆú¹å–ÞNÆ-Ë Ý5Ó¶¯[]´­‹ëËœe.2-,¹QÞju–'oQ×ö¾fÖŒ²ÕyÌöõ›cЂÛÇ–—~¿_ur\óÜ«Î]~™‡Öyav~g†ô’{ð|£aqÈwÃ7Ë]`;5ZµÖýE—”ÎÎëLuô¶¶éðZ·-·wÛÜdæ,õeE»Ø¨Ý)7„œ…o~Ö‡fw»¢Õi_ä_=_F¿{qz†Ö;ž•Xz`Aî­£ü¿_£fmG¹%w:°x{)œ»f&@‘Ë6Ç”ô¾é§ÖP·¡dîÈJ÷Jó.5…—¶‚*¯åØh/¦‚0²ë@qålÞD1ŒâÖðþج©»ëZ{WN®v‹ ï-_-—Û®T{jX…öÌ›®AŒbíº§D9n-™SPÏ3š<÷vëŒ"¼^«Áš|+;(T(3ãÕˆÅÑ™ãCšcr²É¡Ù²¼¼s<ûµTèÜ<}[룻|dÅ—¡‘ËÝõÕŽ[ΤìñBv êÞËxH¹Ü’Ê)&(ÛÛc’æhí Vß@Éûe'³H ±R„cYëIS®ëSìÇ6ñ¢žE¼Ïkz- añÜ_2õ_p˜ð‚,ã¤ú¢­c"Ó~<+}íÁwYW’°7åºjÖåÒÏ$x#+sæPͲM¹¶È¢KãwÈH³P=Zl2šxù3Õ0=‡#yݼ}ï…ljîãÐ÷ï ®èëˆVë¼ ÖÜõúïx¸ÎhxÂÇ»r»šì¼K[e«6/¬V,oåÍå‡ï¼Áœ/¥ïÔêV/Ñ Û(úÙYÞ¡;U•«<¶ B5g©+µ/×™8ì°†w|ú3—‚k̃ÛÈ{M {¢« åªéâ/Ïqw FN1czÁBó²«kO>t©M\{(”'kQp'¾­*˰ QUæÕ½á[Ý3têŽmš•¬Õõmñ—$¿6µ…Ñoy°kÚUËÚe¹gÑo¦ûX¥ËVn¼“Ý“pÑvm³¡FkvyÛÆÍD/5^Rqåúè›{6*Ñqjœ/\TŒ÷(Ï õö- v¸_*õõÆÉ(ÍJ˜9ózóŒu”¡[Ú ¦Îû ”n ´ÚJ挅N]ûØIñ™×£L÷±÷_ÝÆ¥d•žZý˜ð[â-÷°“S%q4-¬wT¨'yj~LX©åÓ6(aSl¾‘öÙ”Úç™c©«¾:mÎÝb £T©ów“ëÐÖ§ÑwPmAtöØuÀmß4vÐ5ŒžL=Å ¿]{ï3k¼ãˆø«ëò¥{]›¢æßMÁÊÑÚèœø&]âdrì{[€äwl¼ÀOY”ë–®åÌ9q;Œvš{I]ïuK~MtåCóй6—u¬-TÈOç˜fß%J›DjáT~r¶w{èÀºº}FEIœ4âOp>I•d*±`;‚–B²ó·&3dÙáÓhÜê^Jõ¼U£3©x}·è×»8r…kŠh4ƒ¡½¯°±W^˲A—ØÓÅvÿƒÕs“ñ˜Áó¿% ¨i±ô׫ðG<‰½MjëÒwÞ{LžŒºjä¸"ÖjÀeùn92Š×Ž\¦¬Þا옫Úg^E•¥³ÇÚ¥µÛÜ_daZÙÚ ZœToYãkzh Ø~&–¾›Þ¢B»iÚõmdBœâ2ŽX‰7Ûv„tåo®`µ¼f9­J³ÜöÝ®e\¬Êc'5E îÝ®{]l×t¬•„´—‚×½öÐXnÕD¹Í33œåØ/2Ž`Õd_0ÜÎèµ;Ü{S»RKˆø;~DKáRY=§µ´ †¯ÝÔß|NÕ˜¾áB?3w¬§ÛÁêWÒ&o7Lm< wYØy\73µÀK8·b<+µgu<9žžètœ\ÒEðæHýjû–t‚äªd˜±ÖbÚº^)MÛaÝmlŒåCóàš©› e®ÐÒÙb•÷*îw»[º`C›¸ò½Æ¹¥”)×K؆[æø‰Ó­â²·Ï¢·/IŽöhË©j7+ºù ¹OÞì+2»9Qw«‡Ù×Ú<­ŠŠfç\â½áÏ&k~ÙÎPÄþ¸÷/t—ˆ‹¬l¯Óxí çàg³÷Ue£Ó¯P—tèx'êuéoK6|@\.wšF•; ò¦áÊžíDd½Ï¦îiÝλKG»zÉ®>çŽQ$cÎ#´zû–à"Ю,vBb«µ7u¸ú­‰w%g9æŒml.eUîÚ{¶ŒfGº|õîÊîǤ-«íBˆJˆÃ;>×Ýu«3”Lð£bˆöåô(ny£D²{îµî Í…bi‰/¹Œµkš)ŽÚ_e¦0"pÑ]ŽSÅud­@Î1ó£Lk¨lj»ÇÝåƒf$*KÇâ sžÍdžZhtÄ*äó¼ëÞNºÄÈóßé¡gØ­ÈØ)œ4™i*__LÐÜw‚ÙZH=qéG%ÝÁè{ÃÝ%ÚÈc¢8ûº”¶¥‚=‰)`}Œml‰Ç@¥¯S½Í ½Ôø%Ù¬ìN]±·(ò©Ð¨ ¢¯{ ©%_±ú£—f_™Ã«Ë×7x_I™"ç!7G;“×ëJ™±[P°}OÕn±\&É7 W=ɧ\šu¼«þA\Ë—åYéŸ&,ÚfX¾¦qQÄ*XµÈc˜^-/wqë[QvrÕÍf ´ÎðT­…; ¬¦MG” ¿Ý—âo.Ь1[ÃÔØ¥”|I•tíC„'—Q¸mu)vÜÞÝ-VÐ=®;Æ>Œ¼ÎêfèùCÚnŠÜ"£·ç‘»8Ë ZË¡JcÔÕly¥+è¯vf®K+®ökïêÑ뜗+ÀDBïm+ƒ/LÙòµÁoP ìKjð¢Çb¥Ãk™ëf¹ìÍnÎö&»9Üo“ å7^*ÉNÞm4ù-ƒlª<ò•§ÑîòöpÞv§‡hïpYOÚE]ìÍ÷»Iæê}cª1‰°¨‰]®âl½œºXÂ:]éJî…;÷º‘sT[ØüÖõû³(:C ëmC©Ø Œû¸ß[weêÎÁ}Âj{ìy³éψ°.^j»D^KX92ìiaH®U ³2–º¸ÀE’¡Âzi×Ü:åâ]M„LÊÃ¥ºÊÚ•‹ŸKd©jM¬Rœ)næg0Þ«¨R²®“:ÉìÓKî讥:ìFTr\ÜŸeÚBêÖ?wsû—KÕß]ñs–óÛ¢e%Q™s€éÕÕµ¶i¬+åº)(fJºÞÚë’Qç+Ñ!n™VÀÔ½”ù5g»½s«Ç²(èFïf­)Eo³Mws”Ú~‰”Ú%ô ýËÕì£p]¨Fr'ióÍ[Eªëâè3Û¶šn{-ï´…Én«~Æ=SSÑ÷œOÌ-³(Þ5J›eÉÎÓggQQð¦õ¶/Þ>Ã䢧ê߲ūðÂÞ9‹ñ¿öK·çÉñjɱ÷+o+”Bè¨Ü¤P¼õÖW ¶k‰[µÕ©7{xnu> ] ÂÄ I±nS«îÔ"ÇR·ÊRÛs7Ö£Õ[‡“Õ€¿,F»©Ü¼9„öf*Ä+±m\[¤„qí«?Œ¿Ÿ¼E[ÌénÅÚ]%§Â²7ÞØ3QÃBänˆ^¨›2&ÝÚÃwåam£ÊaóBc`O7'm)õ«éŸk!®©ÌX)l¨vºgt;ɗç.]„²›°ÎñK{iPÛ®Á&; u ­eñì§u)5‡“èª(ÕÅ_`¹l,ݳ՜ƒ6γ•*w=ê% B´Õ_^‡~Û©ãF³Ì‡åÎ<õR×·7(ŠíÐf÷d«¨'G±dVnŒâÓ#Ç0ÍMçyò ¢Yǃ_>‹7yW²€Æ(+pÙÚ ö¯¹xåmžˆúKë¬ò乺šîð†*dÚÚ1xÞîÄK© NR»vNt»EÞ;-hjŠœ2ýþcëm:]#:æ^"*ºª»¶h§šXòù¢åÒù‹¦œ=:ã›y¤¹‚éBúùS&ñtã¼ÞôBþãÍu³¥¼È¸ Ö)ÀÐÉßdd¾«›Öºê-g±‘ÌåjÍ=¶¶l9[Ð< lmõrÁJ mîâ_h§¹I j>9×€"ØÙ›][\3š–Täp·zõÞp¸Š_«Î!³Ö~ÅBiëjÆ®¡qƒ x¶ÍcQ:ºP´²cÅZ{¹>×Gh–®»”ê½Qi¦m±€ÍáÃl=À%Î=ȾÑÓŽ×w'a¼apuã‹»KEJ7Ƀt7º£áÚR¼™VHè ®«pÓ³fRÓMƒ7Rᜂ} Þ¡ä‹Wo§JÊLnnã­‹áÍ»7Š…šÌœò€¬û)ÒœiÇ•Ìè²¹Èz>¹véÎÑ-¼ØT'xö(*ªPØÌn]…\åb÷Y{8¦ûE¾¡Žê[í€W>´9Nãö šËÜë½°Æ·aœ4âÃ1L®šn²Õ¦†&~ r˜sŒÜ{ ‹cØq£†7lÙŒ÷7Æ=…›×Xé6é\_~[g瞦ÓÐB‰ÒŽé‹µrªîõH2 s±6ÒM½C¼ìy§ ÐÓ ¤²í')ÚGÔw›¶Æ[@Xœú¾½Ÿ)ôfê ¼|®ˆ‚©M 9ˆV2F*Ý5f ²Í âpó À´ž)›“E¹8–AéÉf IžìZ¬=ÿ4ûuË oQÁkÍQ:µÛÞ0Äv GuZ›§£Î#= Y–à«NÕ¶RÝÄà z‘{†¼ú_·§yB(Ac…³©o·×9ñ£ý#,c|ųB¸Ê~=·ªÄ¦âf#›1c^Õ½÷Rñy¯‘ÃŒŸ{F^õ­*¯ ¥óí Ë«°«Ñ9êbý=ëªÇK °ÂðòÔH wç¹uu´¢<¼õyú8¬ªÁÝךL”/&<Õ³nÛñ"¦€ŽÞW‘} ú×´nÅEY¦©\`îÖdlD÷ ]Íy¼v\øÒîéÊN²ÊLëë멪 CX¸úç=áòè$z°,U®êh»1öѱù¿{ˆy¼9gº‘åI,àO DBóœÚ–`¨‡JΊÖmYÔ-L‡.è~HÉ×Ë–ŸZ´E%Òös~N­€›%ð[gqe-+jѦ¶Ù¿§w Å@–³Ë˜»¾JhíYGÜ…vá¹KU ʜȰì6$XŒlÛœî³>.»2ëºé‡Ìk·{ êÒ]w0è¦ÞMo:pìƒiÙÃ-¼¹|J3s¡5.×ÌBÁ’æâñ¬œû†.n—\~ã¡Õ,7^V|ò»Ïw|0·. •úÜ—–eOÞñˆ¡vuÄã"£÷fˆ{ö«Tk¼/FÞ1ÚyºÆ t2…‰2s¥I áKÈ›ž·>µÃ<‚š ÛåwÄ\:^Òêq ±{Ú:^[ê»zã&ƒy!¦kž‰n¥sPŶç’¸ÐêptîžÙ±ã|»qØbw¨@ÉÖ™XáÑ—aí^kKfÑ¥Iâ©A5X¢|vúHn^àºûS(¦Lœwížté·çÓ”,²HºÖD§¿nâû9pœÂFÐt¹LáQ =o\áÛÒ·²î´¬ÓwqëØö½EcË Ú&Ü~°¾IÉÒñæÊm #ÞY¤¬”g9O8!¾Lø“6m§*guæonbçtº—&/ãi)ÀÖ ¥Ò¥ šxôåÔ- í-snTé¥Ü„ò„Y[\î1¹ºÇAñs‘éÜ5tí‚á77-‹éGƒÕízæ¦{Ìx[á× b‹é|òóRån^³]S>oëY2õ>Û—f2£«Ö¾të96ðâeÓu‘º Šl–Áì¡A.VÛEs—á½Ï\®~ëV§2±y^f"&Óç³[NbÉ,,™™w¯%uI•}YÂWn ÝS!ž£ÞSIÖä媤u§#^xkjwkÆ^A~ZMËó4ëlbÛÝÑçïoŒŒ猭7eÌošKCî˜è,¦è<Ù×ÛõÞe>׉è™öŠpNù“Nžò®éz°#K¢HdÆïô^Ì`xçë¿J)ÓXk÷ìYôn¤`>4o°GÁŒÙ󵋡ÂCÇ5 ~=V"few :<­eÕÒf÷oXrµuÆÊ¡û=²‰5sawÒ¶£–>ò°*d3s{µŠÜs¥F_5ÏLܼkq ëÇÔ¨×88<”øbi\ÃF³eÄMd௕Ž×tÞ3Ä?xÙ³œíI^"½Å`±u±Í®ºYyìÚŠ•iʵ=ìywÒcP÷!”÷xg¶µºßãF¢ËÁ”Ü<ÀaJÝ%ËB¢²Uɸ¯9[áwM,ûl*èz^úkóó+Âßkºï®Vw&–ß)μQèýGÙ—s>ë%Ó¡àOsZ1™ÉÖtƒÂ·6ga¤öëÛJ*ìÎ)—(ô²ÝŸz»}3¼6ö*eùÍ8Ù¢à—$Á`Þ¸?oä>ÚÜo ä÷Â)ûÔOjÃßߊíÆs#ëÐr÷†°){…fù1¡ð¹‰z_Xá™uek +¬á­žc!  qËqåVQÚׄn!GXñk…!wr"HìÝâã˜ß¯Ûž YN·{¢¹”.êscöG±øhü]ûÀ:_ìU(!ì;²Ò<žo–YqŽû»îʵ‹®çe!ÌKÌ묘 oæ ˆ—°o0ñé=ÀîîÜ+oxÎy­ØW,s[€Ò°1^2©C”ÎË¥ðƒ^§¹ÝJÑá‰è•ç»/4ë¹Æ÷{¦!WÎE™HP¨V2+2 EÂHc:Nm5²€ÎÕe WV{˜ái¡Ž{‰`¸?WD%öùñQ±áXôãá|ƒ£—XV‘µ¶˜r.]§ºž¬ìfdB¯.ÓÉQ( =cúbÚ)²üºß©‡™D+Új,ÕçG8¢SðCB}bÎÌ¿F¾|ÇAÐ=yÛŽ¸TDW½´ÅŒ½{EuÏ9Ò¡5í£åµ vü®¼<œM:õîAÕ¥$ãᆯ%uˆ„Î9çšN‰¬Ý±Hbw`9©ô‹ÝMs”r’ÌÌ}•njT^WB+@Ëå™ ö¾Å ¯yðé¹Õë½ÐV7fJÄ WráðFÙc¹n催aÞl*´9W1XµïS®/¦h08‘Ûë8;Aut¯wgdŒ»W7:-wZ|ŽVoÈft­Ä«@Û;½ ˆ_`õ¹ë…%ª•aŽÐ³CÏ£Á:Yšì]£ÂÍ" Єë4Ñ¿’WÏ4]-ȑЗׯ3\îˆJ ˜ø‚\8‚¯vÖdá‚Îüeé!P‡}¯W‰”fMG=ש¶"ë«)sh\Ú Lá'ƒ‡ZC·K§»Ù¼Uax‘T§­`¿z®=¨ÂƬd@q—&Ù|×mÆÆ¤óšÍe춺lécsJ[eãÞ™Ÿ^}”õžÎ®¼øc ¿@nà¾wžrB›º^Í”øøô¯}rÇ”*ÆJÞN,È¥ Ì*á ½’û‡®7WÚðc~í ¢¬W1Åu› }¹vàÑáá­&{ŽÒ ®²uêºÚÎZÕÀäL'xýk«S™Ç—|ÍÁ­Zíä77¶N9*×aƒ‚­P¬·,Ë^ßpàŠºËhÊxãR½M£ì^²Ž@l·ê_$â9[âóiÀ÷½]…7¬erù[Ú¾‡mÆþí 6l†žÎu¤i®ìÕEÆ#`YPÖ±¹¶®àŸvò¼]PS]Ç Ì‡§G/%4#ÚnÒ¾^Qû×P[œ= Þì· î=X&Ië}º•w¯cåž7˜Í Í Uaͳ¯e›«Ùì¹ØwÙ† »/Ž{k…±½ *¿wc#;®QgÙª0ý£o=9hÁIN¡S*ÎRÔ@dkÛðÛÄ®HÖä²ÞŸ:zÆ.Ó¾ôšäÂû˸Ê9`ZÎùjÍ9ˆ@pÛ]njã µ’@WJìofÚ‹ŒáÌA!×´ED;ý²Ø}8Y’ ´=ræw‡w»kštÕÚa»ë ´TÒœÐÉÕÆàN§;&ÎEïĵÊ]ÃkŸPntDfd³í镤æ1ËœšÅh]5*Íî÷s®¡çá¢Æø ~áDv.iczm‘œd#» ¬±Xó¶,án;ù]ª㾬ÚsÓjû6VN*Ï)¼;o4‰v½tŽõÝx»WêØ©¸ÖëšX1,ívXê½ÛÐÕàé«zW„Þ·Í{}î7Å%šú+¢øÊxjÝsÇ\á,íÕ´==uî„o½±ß¦±ñO4ån°‚GhvSèÕè)£9·€U̸óW Ñ’ªúÒß½ë]½×׋ÔD{«²&4º&º‹{ó&Ë7|Kç|ðÃx¸–3Úì¹µï5S»‚Ížc›Ï‘g…Þunž¯\î@yzvUØŽSÊ[°îTÖs‹G²‹îÞA4H:õ6™˜:éöÌ9ÍëS#¬*.³ =5ÓQÇc3?Žæ˜¥©GZ9¨šé¦ñÉÌÎ# ž1ÓS5Ç| ƒÏr²Ê¿VµÆÀ~·?˜t‡ûZ«÷Sb·ÁsoîáÞT¯óíÔ·nñ™Öƒí<+z”®ÕRø24¥wk¢qÉ‹°wÀ[¯©QíYFñ÷Í åÁ%îqÞxîT½”ôbw9Ià ©µæµ]ÝVñºï(¬Í<$‡7âo©ä?w­ÚÄqßTÙg;®Þtù_…â7ëÀ Ø3ŠÎéD€jÖSv笀®y;Ñ=aVîUÞë¯r食ÓPf+ÑWeÓ·Ïqª—­¼!®¼Š•¡‡.Î -)šãÇhKËub·*EQÙyÛHæVÙrô-„ˆ#©†ñ&¬»MÒ¬ž¢ã5¼ôPœù{  «·:*מPŽô·ž—éêšÏ–N¡¿+U¦A&Ýk|o{æ`WÎzî¡Õï#@hïW_n±Ù%_;žÒ“•åܸa³[§zr2QÄ5ëË»\Ò›ÏçL '“Öè›¶Ò¡”·q#1(£ÂÕ­msã|H§š÷Âû’F뇲 ž¬Ê d N»»»®ûìåE vœÔÐ ¹em·X•`D…Dh:6[=À«[O!àìƒ]Zc[äì¯{›2¸Ì¹(*¨A1ánjÙYt&rເ§Ï¯d¼4úDTyQ<ɛܼ#³žlR*Êõ2CX oN[•—7s9¿g±Þ¦ºß³¨töú°½Ë·ƒÍñ¥5˜xu‚S.ÔsÌäêÙÔ½:òå{»ÞLºÅb]ëÊ*ó·b3‡aAö¹ ß'Ô .ñˆØÍî›]ôYê,³ØôTÚtn︂w»q–<Ýd–3Ù=C·7”]O|AÎíZ,ØäN¶ul<;V-æ(XÑ]ÛãØ;¿z§œKyßj»óJ`Cݼ…Ú—«®ø.ζqºt˾èvM¨L“½<¸1K@~¬ÐóàÁ{I׃б7Âðxü½©ÙÖ;Ú ŠlÑ™z§¢EýÌí¥ŽË ¬Ç&ñ!-X!aƒvà©» I¯·µýv©Ù7€rJî);C%îÖnѬõºíUoº5ÓJ‡¬PRÇTÃ*÷ºë†pÊy÷bGr0¢–{¯@×׉¦—iÞËÚ<÷S©i£Ûw-ò°+¡Á“–žÙ Ö¢‰”³8JoULx¦,ò—¼¾oâ'Ã_u;ÔMÎÑY•™¦Zºø^l.š˜º.7*Ñ„ò‹™_¹£ž ®{ÃAÔÍ"æJ ΈíÇOLÝã«lbh=)żV[—²€t/½Û¸;¢wÏÑööœ2ë^Hã°/³hTIXãOz[þä^™ë ]áêÖUcƒ,lòC3¬vˆ‹°­]ëcOQ<(¹W/9J±Œ%QLlKÁ¹ZhrbŸay/·;f6œÎ¹« "°´³ŒFŸøÁ–¦4¼ÕŠòÒ­Ê:úA Ìje_VUtî¡.J·ÈáàÈêÚ*i†Êc;Ú5–œOtñòÆû×–ë¥RzdÅ»I‹˜ÔÞ —»YªjT7ÈòÚˆê;››\ e׉ðÃÀžùíúûq>Cy=·´¼c»uÏ£;ÈòÁÍòÈ­¸Z{p…uÃŽqBf¡Üpm6û`e]Iè…﻽í®ò£{ שάt¥šc€í3@ì°2ž¹ qÑÔ¨ŽÞì9yj$²Ô·§(½X2ï…ŽËÄ*ˆ§dè én…£Œº5pðÕV«hÀnµ„µxÍZÉXì®’ØMÝpõÙ9eª'Œ—•®¸è´Ÿ[yÁâxgwjò[ÊaÅ“Ä]6e ßk¢Bfì]Ò ¾qæµnѵ[]=FÖôÜZ­g_ÚD,j^ší\v·mà÷©Q(ž¤¨ahýÅâÀ¡Ï„Ú9À[ÚæwX&în¾Î¶ß³¾-Žj?VïÃÑ”‹mW°Crï(t,p òë=Òã›JßV”k܇m¾Ûœ àoÖ«W`¿–ÑFàòBó^ã¾^•¾xjû—…Õîí J.d<ºctºsè9»«¾ aO7s'E~·W寂)(ÞŽjº<Ë.Ê©ô™÷(ψSp0ÒoE+ùϪïë¥XkN½¤€oH7”I‹6»œÎ¨)²–ÍÙLR·§O8óákŽ%{ÜÅO¦Ç ýž>³ÂC¤Q¿¯ÚÅXªzf¿pFlåOk¤³£3m±~O{fe.ç:Q÷î½Í`ôžÜ{~X’µÇ_¦ó"«Ô=BÎe½ò7ÉŒÓÕ™Ã&Ö Þxƒâçû{?.õà/ö~å¿~Á`_ìykpšÁNŠõ`íÙæèo–àGOY]¯Fãx+c9”OBÝܼ»y«o[cXlÇäÅñxmzáÞ×åEÖ¼r5“ݛ͠¡W]Ç»ïµÛî¹yôï_†_Ü´ʱHn*ŒWZ¼É'fêì>]YINV¹ï,t©1·!s¨ ]*ZùÚC¸yl zotÑá]WuÆTï÷m¯tðBl»T°öíß—å4ãWj•ºófÜžOjð‰wm$”:ëTöS o†'—®²3hlÑÁ\ŽP—ˆ]³2Ï4ŠŠ¥!ÊîÌ{ƬõÊÍš™ iý=†É&mª.Žw9e7:èÖ¦ºÏ.µ¤)Rúս˃ʾ–/)æà–¹«n­m͉0¹‘ÛÞ—WÝXÍ ñ4=ÞˆÁ¯Á‚R=ž¥«ÍÚãöCN×°ýÇœÎMƒ¦Þêð¦x èÔvÆÁ¤‚Ðq÷W’<åî]‰ÆÛV_Þ·Â\ÃeâJ”yVp³èsŽNkW^ä{[»W«ì±5îÛÏzÁŠPXÔ¬®8–ïQÈÏv5ÁóàñM' ÀÙ€+½wºÂK—>»àí|U8Wf éÎ4¶;}Qu»èÛ+^ m1 ¾ë=…ÄGÉ7ÚH2œm  mŒ­›Ôò¦£*9²ìõîYÐÐÍõ[ÜÒcGn£­ŸaYM[ûª.Å9 Í£–ïÞÉÛ¸¨ØbÎvº<ª£÷¦5éÜG°-0:æo$v·6gÏ€“Pí–)ŒCx3–_S\-³y[éÜEköðt4ó¬öôE»[Ì ñ»eoRÕ|)³áKÐuo{“×+‰ñ1m½ðgÐ?C+.WeÙÚ!ðö /,Н’\Ÿ¹K½ºöÄ«¶ï#ÜCÝÕvØz;<Ùmœ¤Ó‡õk†[ÊëRÎE„EtK& RôP žòãÇ·Û׆ÐÊšž²á¼ ï3³‰‘Sá] Ûé²çZ¡Ó4÷c§S}箹Ö/z‚¼ç¡5 ÚÇ&õ&QÐ<ãì¸:u®ó$#»Â‘Õç›í›/Ï™‡¼1Ÿ&¥ÞaC3†;uŠ»JyM˜óiøïïo¦{P.²­`´1T"ï@[.Ä5Œ…3aò{ì-ó™šs»yg½”·»¢Éž-ïa*§ƒ“Å/cÎâ*YcÛÝÔ3²û" cì´—½¼¨ôðòé˜óÛkÊMîÓœµwj笜ax ÔœHZ4ýhÞ™­i‘G%“"8ßPFemXÅÒžIÕ{¡z7NÇÙJ‹W‰áÀy/{ ³ãú{˜1TÃkÇè{Âx›(ư=~°¦ì&H¾t_’7)<Ų¸âµxî*èUvFýœ¢³½Yçš5F"‰˜rµ®&ê–Àc\^”&S©¹H×ddnÌxÂ=@ˆgÓ.ÝÇ{)]L½¶cWÚ8¤8ç(->xPɲvtoºÑ p Nû鱃Ýåˆ]çÉÔ ĽD®õîÖäÚeUÞ,º¼€÷Ùšu «OtvÈóµˆ>u£ppÑÎûCЏ!}Pˆíð‹7¤¤ǘ5öDUzï{Ù™| K–Åé + ’4áÊ6Jîw|˜žæB´žÑññkJ‚;&…{è^ÆpU·f¦dªÏBë»}weÖ{ÔgÑà¨P§F£º/Ý*’Ôª Jg«ŸÄQâØ¡½Ã,mñ#ÆRÉuï)îÐæR5¼æ»ÅÔØ.Pœêuáó²Ñ&«íàY™ÃáŽÚ–ptì,å˜7LVWa¨Òï ÐÌL#¹©¹Ôêȵ¯-_“˜…NÞ Vï½Ï0éR¯{y*óÈ_¯èóêõ߇"ç.9¾(0"X7Ââw'zs¦,~ÓϰÞï™P¦ê!Y)…Ò$´ÀŠ£«4Û:Gâ›e¼Úh*¾ºSÖï½¾tMžÝWÖØäW`<’Ï‚êÅlÝÌ”º–úDS}Ns8.²˜ìã³f!}Ö{I­¥ybß+Zç"=aEÔ ¯OJÄ€8ýà«Tîå7·~¼°§¼G,‡=ó}÷Tð~ y¥le 4ð`×®ýwx÷ÍŒ'ÆØ•²¬XÒä—Ñȹsé ÛÞÞ[f™Õö'—}Á'¦´ªu2(÷\<ý¦½I‹Ôe~—xønîÔU6ÑSrÐÁK +pa ›‹§Ç“¸‰r»ÞÞø‰u—TíT“[‰$êÁo}X}Ùm07eEvn&xOHµk `‹¡T6]»æÆvËé€÷ ÚIQ¹&ãæÙ° ´uU’Þdìyª€íÈú¸^Û'S·u-Å|ùB¥M÷¡€ey u¶b¯1èÕ-iP…^Zʰº)Åm.¹mï¯ÈÂzqé2’¼ðï,C¼$7µàåcòvü«|æCHfä¡ë{ w,Ûõ$yå#¨a~w’‹§;¶•GYz%]î>=íßU‡Kl>y^{Ç.èv°Á¯; ð«Îâ7Àé^ÌÊšªÓùKðcLÑÉmü sÄÓs8êÅ ŒºìVÞd“ºÝhtâ¶®í}´!XVʬ²]ÙtLÈúy)¦W!#åê}tÓÙö‹Í”W›•ª±ƒMËí73¥86JZdë}X°«.lÇšNÇ+o«ë¦J·£¢JYt2*/ íJÞ¡¡r¦¯« i’º=/3x¾±Ÿ½©®Ëí謹걷’Ž»ÚÉÒi„&/³bº£‰Þ>œ•‰Ð,¡‰lìl•2íèp®† &°VW6ùÓ òQK~ÃN´.[ÚÍû&¢ÁWI™;«¨I… p^LdÄmåÒ}{‹ï½îpd4µ^+£ ì®—''11“©ÛÝ5Ó”Û"ÄNŸ¦÷]‘Qs\u#|÷¡·9劉/s‘…êï1fèY¾n_0ˆ§­w ´<»ƒéj–ÎâoZÊ’Ý +ÏÄ{oߦT=_†!úü—5:ަÙ,5êʸ³ºÌ Nq¢s5uÎLÑÎÑRjå.‘¬l©Ü·—sŽnÕù–÷¼Ë®»Ó¯Ü‡º–lU`š)÷›£vÕ˜ÀÉ.¡± ÑÓcJÜÚﯷ¹¹ÖƲLÍ„·¸ õ½ì{1%î§Ðˆ`ä«YËÔž{ÂòqÏV£&>Çž6oÅàT„ò|‰®WBk ú%[o/’ÎJ‚êbÍ£$†±¸¼· :¶Ëm­6Vêkj•6·™¦„ñ·¹gI›»Xy‚g]OP­•¨ÞA)R@_ÛÖ:ß ´<ݪ>IX«40{ R¢é~¯[ëF„¨ õOmâk¼‚á^à-“‡ßSc5ƒãé&T9”S(=¹wÑÌÛ–œ‹hYSk ëLÙÊrs‡±VKëåo2kŽWMÃbZ›;+z6âÚ¾r•³ƒÀøËµvxO ËöHA—®ÛÊK”¶O/gŸŸîý^$ÏÏZÝ¢ÿ  x1‰¢‘ý)ñw>¶RiNº0~¬Ý7®³¬úVߥ¶åó²³ ã݆Drº s*М¡äMGw|IBà›SE5X­ØYc«Ÿg ï»Eaºw9‚ARÐKȆªÍÁu’*Öv\¾Œmã)î”ù ×è*úwk­ïº°»«˜(Ønc-×àpÜ‹ËE…e{#Ôî{LÒik íæÒZÛ‰PéHæ5]£ë×[‹.UÕÍÑÓU#w•gº¬àxÒ¨ÒZÜ:ÅnK;ßsãÔ›H L’í僕eku·Ü ’ðB*~>­ééÂsÜ—í§Ò•¡™Pª±k±NÈ8W+ÝÜR>¾¥«g}¹Õ´a³[Z¨ÐOM`UÔåpªá Üî—Rá´úÃã‹9ãbµŠ±EvíŽ|n‰=ß ê<È^XÁ]IoŽÏ•º­_–Of M­æÃÞ¬PO³²Á~cÚ];ÆÆÆÞª é— ÆœOTÌ*|8¨Qn迯PV±hÄÁ[²ïy"4Ö&Ô} Žèó®â4êý‘\H81]ofbîMÑ<ûwÙYÆ‚½+±q lo„²Z5†åg"õ툞¿aWév^汬÷ÚÛ³ÚàbȶnÏ»<˜\®›î¼†½Gåw§_ŠsµÊ¬^ò¢Žµîï‡el†(°•Ûä¹›8«l…8Çœq„5ät§­aÞ[ ’k¦¶’¾¥·{.Æ(¥Öb¢s ¥¥†úßÝA³k"çx;´¾R!®£¾#q­8 î¸è{7Åä—OfÑsµ·Æ›ðèF® Ò=Û:ÌÛõSÃIÊXõ>jï±&ð4öZ—‰ö:")Ã+vÇ=é¹$n96·ÁŠQiX[9Éxñ©oÕÝštç'œ¸=´*_ Þ᪸D¨0§u”9Ú¤6M«ZáÎÙXÜå%X”`EBXQÙ¡ïwÖp{{tõøÛ±Ö»€]jµÕuƶ 9Ó–öÉÐÅ—Ï9‡sHg­DСr"µ¤%0Ç!˜=2e𨵠ú„žË!‘ÔQéÛœøŽµÏá&½½©YÁ`ù ”0-¼;+‰G.°G X”åì°g¾½’'ëÌbw„Ïw£öQ>Ê×ö`ÌÔu97 ½T¨øêéU›À˳fáCðôÞè´©Iá ×ÇQ·®äöé¹îâýOÇ¡îåI΢-èSÔwtõÛ]“ÂúÒ뛬ôÙŒ3” 0xÖïw¯å{îÁãçž×.­½µ®{ÒlšÝ‡Â¶ìá(b¿|¤õk¨)²}vÆiÚ_v¶õîxjLô²»¨ª&áÚŸ¯(;‰+«ƒjò€Þ¥Õ°êþ©½L«@¾'îC¹½2èãºÆ;mU¹ÖŸÝm_Xæ/áÌX:ñ»ø8¹D*ä‹Òhå.Æ€kº¸MwÓvOv?]ª~àâöšÐas í𸥇²ˆ¡ZܹÜ×e;çÁ¼!¡kré—˜¾ úkÚ"TëË77æPí«vŒ¼µ—å6ÅóîÙö¨u¯_»4Lq×JZ„WÚ£²8p|,«¸Ásç3¦PÓ_¤Ü·ÛÓ£>4Dµ[W¹»Vb9ì:­ëÍ”«( %‹·"Á-féÐAozÜŸ_Ý™ÊdÝÝš¸*"+ …M¹ h½ùŒ¼ßYî#Šœª‚î·X¯•&×+Ê ‹Ë‡=®®fæ Uõp}¼>›4ªlv6oªuçgfÒ'¨qµYǾôZœÊÆ»_¸±»¼×=5š5óRÅ”Å=7‰ì}kŠÑvêÁšñì§Ç”jÞeÙ‰õ>×VV³{Ì/:TîëAŒPÕˆµÕ\汸ÄlB22ßt”긼8iìB¦Í–@K%¯]sMJêSD«ÂÅo[²jÌ]ÌMÊ'·H©1¾U+¸uÙ“í!¥on¯°¥¼LV†ù†L¾©ZKØï,xŒÓ;¦¶«®èˆÑêt—Í’ê»yq9ZÃOÜüÚ“…~WÉAð`mRšòYÜ+&Ã9èìðXj÷Ǿ[‡ÚÏ2ö¡À²pÞÕn¡øcÜMË´ HÖ]õ{rhT]±é±“{×4îNÊ*@ΰ´£¦½ãEJ°if'¼‡'74›¥;\Ý\…æŒá®N¥}ì…Ëz•b·Li{JJÍw Ñ–I¶8„"šY- Ï6Üeôyz”C¯0ê¾n¯[á|t®}ºÀÕ•´¶Þ­lW ‡YÛS/+¢ÍyKž‘m%â1«¨•KIÛ†^|Ú¶VJµJЭˇ«óÜÜù´Æ:Èx¯^YP£» ¼š7åÝÛ…üXª;º#cyµsð²ûº;a~¥t”ÚXÒ«ÀnN[8ÃY ]«ãÀ-Þ¡µ ønibFS©Ç‚¡ãä&t//ìˆ×V@»¢ïkzþEœ;°D§Têà7M€ûª2 Z°_oCÞ#ÂÇdÍB]¡KÏI¿{– 5 5âa V»» 7¹öòµà•Ö\ï«È’šíÁ6µ KK]¸Íõt»¹áÚV‘K{<šJ“)æšËû2J×uÖÞn¿‚á¤]*7ZæØALWÂÕð2Éñööaµ=ÓÝÆ’2j"F]a\k†­VuTæ§=é—¨N\ÑZ$íuÛßfÚàÜ¡Àž4ÞU¢ÏÝ›5ü­f‹ò±€3àÊž*+â«*+̵0&r§uw“F`ºHW Ý:·Õ|P†Û¬ÃÊçc:»½Wœ‹î6ü§ÏÌ+c@ˆh«gkÖ‹Æo(]H0å+·e…¢ nº4§AÂVÃØë¡q¥C6VfK¾ŽÙ¥^Zv»„r¸Ÿ Ô˜¾¬¡êY|C]5^{ˆ&gE:Ê }+¦ìÌæêÕßnLT–u7R”m âz»6-{O®Ëgw,â5n¼,j`q>í½ß_½ÜW³N©/Ñt3êR®»ÛêîX ̾Y ˆBæ!S ÌÕºO‘EŒT&žq`!ïuÆJá… ’%º’Ô½3Á,=76q«8÷›O5ÑÝÃŒ©h墬ç}“('Ýk:JX¶M3¿&¨œ×â)¾"…­“Vx¾aÄ'ª? c©Ò“{: Ð9Ç76¦›^uœöÉ{5EHyÒ™‡²§%}&b ÷{í³õÌî5º5g 7QÕ÷XeªÊ e6”ô WX‹ìâJº®ÔÊ|¶w`»´°Iö×/\o‚Áàåù3™‡ÜñZîi½B⾦¦ù%k‰Þîô˜S…^ÑÙ²µ¼ êú\÷°³Ë·ª»&4hÎjäÚ­•€¿,¥ì‰Ë&Ã4¼·^jÁ6<ߎRÊÕË¥ž‚)Õ™§Ízø{ §´7Õy±Q~ßvüת”^í»j‡.®WÉSg®ëXÁzlêM©UƤæê²Ÿ!.óª)Q•#‘G5ëŠÊXãÖ„êpq]egfE5ÞßT¦à¿/T<–ñs¼°3›}Ó»F•[ã÷VJ/'¼ô„c±ä¯za1$¥¡fnwÆÞe?7™Íí ®‘Þ>º4*7•-¥½m=Kw¯ÉFN*…ö+Ìd#¨Øõc¯­Þ,Y×ŠŠ‹*Ýu j‹ÛCµWTYšÞ¢|¶ûªûŽêÛ¡ÏUK‘5çMÍŬÎ5£¢ì¯ +°§,w§« ºjÕÔìe«;6|%Ö`|d ÖN]6®†öG]ÂKñá§\5Ôù0ž1Æœ,L¬Irã˜Nõïd«± •µÃ9¶ÍEÇeÞÖn„†ÈxØbù×v1Ó†>ÈuÏ:²ùT­ÎÜ…FÊ#•ä„×Lœh§“‡­úÍ_-«CgzRs”Á/‹éÄ,5bY”ZŽRtRŸ;-ج(OlÁÄ=5²FÔ¨Ïe1µQtjEænot8¨Ík»fSÂe7V{;Z.cÙw¯«µÝÁPHßqßpU­æ °yõ¿¿J¿~ê6îýß©þ`~«´&uØíÌ÷,¦Å í úóÔ•yb±P«kÙ#}“h7x¦ß:•šNÍûR­¯åVñ”;;n»ñuâkew5²Ÿ¢Dæ2µ UŠÙ™…ÝãòÝWWZU¨F\¯Yç[= íKËÜO×\ȨzÈW2œÜ¼•y&²ëq¬Bâ3/©®ôÚôõª³Ùè2^Ž“. Ê>ÃBš©g'”[KoiÖ\6ìS8ç°JéÙë¢Õkn‡’©ÒÞN¥6p«{L»å:ÇpÊC©¡«5†dÚÁiíáÎÚ+D"Åvm 9Ó®IVªn5ô½®~“èR­7—Ð*nÙ›Sxr¢·&ètû‹ }îöœT^ÑÛu¹¸–”Åø¥9ª³E V7@«„g0)÷³ Z9Rä%bCÛFtÆ#¬ÛŠ1 §ÞÎÞ@¼ìœ ‹FŒ åÖj½ÛûqJîà_^`¨x+oí—«Šox©Þ“°‹èÞ-¡L¹ßM™ß8ñéˆF7‡M9£íã7ÕÎÄ}Wyœí¯f8ív×[ ™kÂÔóu щ{^¥\Êî¤ÜËØ½ˆÔËu ¶)ö!¶Âë¥ðÚÊÁå¨ š}u½<ðB+•Ž ¯é6sãOqãâ5WcÝ—´š!ÉN­eö£Y“ª+ea+¯R®—Léå\{µ.Šò´;O µ +ÜWƒ_Ë•T‰À.Å9[nm½w6 ë—9™­$‹YçžÏ%@#K¨Rë¾ìû¼Ò1ÜÕ˜=wKcwo³–Ô ê+œ;C¥¼–Ï=í•:`X*,ç7ìÚ*+¹§k@—s–å³rKYtÝ*ŧ Ðêõ« öÅ4u_¹­îÎ ƒ‘'Gb÷_ž†ƒ†îËö¾äëÅY†ßYärZÆú…s/å\pÕ­ã%k­Ê]„½ƒSÞÍymØÎ¢©õºÓu4âËä–Õž OF!Qnm h‹ˆï³¢U¾;¤?N¥ë§ÎŽîEä¢{‚i䓆-·ŒÃ+OFÄèvÅF*`³}´FœB á¼®„dY·³z®›¥V¨)‡Û—êigƒ+uÕ•[­‹ÁkµVàO6eZ¶8w!/:»^AýºÿÞØVnüèþ#ðo­9vÆ«;XCÚîæHÕÚÆq|’á‘Õm“bvä°h-¥’Ÿ3M×ÆÇ ]ÉÓãåˆÌÜ»³óÊš-sW¼kUfŠó¥…LŽmýÖàéÐ.¶ßn ëå¦ÞPýétá®õ§W¦4Wi¬¥ y6o¦§1cEQéyðruæF:î¬-7‡U>Š–ƒV7Y2•ÝëlÎ%×tÑ|û»:Tmï'™ûÙ1%:*ñÝxû"Ýd¬íöɯÕc¨X½ý˜Ütùf4ÎR¿$´òê®íC¼¡5]Ûátß^²ûìçYà/ÆíŠÚRözÇ8L¡¼—ÏœôUÛbü¶ýœ-Èd‹–HDZÝtcóUouàÎ=;e15èÖ»è•G\fvZUf†–.uL ~çêæ•k‘•wHm]±­õM½{å9I×I¹ž\ïÑWw–oÂÀ7Iúì´Y>–ݘ°t9Zg©*ä†xm!ì§lnSkmðJêÂ_*±šÆhÆÚÏdîìWmY:DY¿g˲ì´*qÎQŒˆtõm-kNn‹È*žìí4]™z-×5÷SYDVk[¸‡ræÊ®Á )B#K–õ&8:úcéÍîÁ¥ªF2VA—;;jfßWkÆo½ÍT}uço½ŽvË<ó±… Ëm\ã¾¶‡wÍfœçbáè7M]x`«‚bswžêµÛ’ ‰ZW¢ÅÒÊ4·î¾}¼ÚÛ¾XÝ3B¯¯$¤F±¥甽EérÏu®ÍˆxØÚÍ‘T¹»L®­úVÎZk›Ôó–X{΋êsw¾É‚)4,+F°_B»¾J­îqØë•Ú÷ÙˊήõÓ)- óÀpT~2•æÊÛm1sÏvÉÝîèD;X¶X³¤óëÈÔF¶Ãávç5¡ ø%Ë:ް<K\èo9Sz²³Y"fo©Æl׸dë·ÕÞn-ñ›Ã˲°:c|´R+Mî_¼lkxr½Ùfã=g¼ç{w¶®¢”õ‹/n®#YezË :ÛíSF%•Γ¥P̽½tmO>Ï}žš“›ÞÜùËvY7Ò1´o—y=´vϦq*d‹¢OÞ'Âü#¦¬{b¨¶\ŠšÍcÎwc±a˵½! oDŠê8¡Fh„u½X{0ùO÷réêIÁEUÐ I~drÈnvg4[”2AWheÆ2 K¯{3 CbõÒSnÛ;‰JÑt©œ«Ýžï2Ûï?N·6½AÖ¶Åe‡"°Á­ùÄô¬~(ê.oz[È]ásLŠÐ¼¡÷‚téæ_¤ãËlŒçc-&t0ynç:YP•SEºê.ÓœíŸ1Öˆ$•׺BÃX&aBÞ¶ÕØzÔgÜ…ÈçÐOY‘‹¼ÑãIñ‹º¤f­c´öÉíöìÒ¢¯‚£Т§nó|‰Ñdz%<8·ºÝïvBÜ›}Q_ ai]†¦³}|Éy\¾—uWWm,Àœì†Î±ºRÑ´ÊÙš­çæ4õK›¦Û[¢Ùé4šZ”s<çÔæ{½»YQÕõ«#ÜzSH©I^âeÎ Ôuy¨f ð:š9¦SejK•»Ã0 ³¹ôîS‡*9³Âû»6ßCx';‹ˆ4¬k§–"ó*i¥kDt­¥MVÚàLš;î7Ûç\}—Nþn鈰[¼:o]Qãåòg¼ù^–i¥³mÓC£¢¨ºøëï)–:u{4¯W½+e9÷BlaWtúbÞ®gÀè‰=|,”2™Þõ–-O{™éC·P]å ^äw ™]¯3D¼§¹Õð†]kfßœX™W{Ø7¦¶æ)@‚iÕôÝë[5ƒOkd¹–…_’&ÔZo{}> WrœéÐp®Ñ´®Æ{…ÖYÑWlo.h•Æ6•…;ü­oÅ_µ¡XìWß|Òݽ+E47‘w嬿¶¢Ê#œ˜ÿqÎBÖÔ9^ÙzG]úèJó—w%:²eš˜›EÕ£6Ÿ36·M­öò¦»|ß:v.¯vlÊ|ªw\Šz-›éRó.µhwzÄ$É\D m«Ï Ñò1§…'VϾꀛ[¹j‚Á¨þ¡cèæâ@ìù9¼)úýîIŠëÜöï%RzØpÜ÷É9P–xñÛìöú¹€¥¾9=8Ÿ)D•YjƒU¦ß^0ÖÀU$AîÍ èË =צ =îww’ºêÀ3á(gs//·¯ge¾VUE-\m1¶_{Z·ïM ~<({tmEëÌM_PT<°½ÖÊÁ¡“Œ†ÝC›Û±u:Ó}»¯@,]:„Æ‹£žr½«¼W^Éjëá´–ép ïŠçØ{Ãbq\-íÒ÷¢eK£Ë… Ñu½´;¬Ò{HÍ…Ò³‰„Á‹IµÖ en4£Êç~Îõ­º9Zâë÷u ÊTeîQ©*N-ŒI/žè*ÖêЯ”êOpœ×mûUs5ìÛºN•Ì䀧x5KvEJwŒÂú+¾é\ãÛ‹¾[!®ËQ²gÏG§{À:õdÌò©¢À¿pºê¨‹r¡›ÙèW¯8KBj׺²ù ÝiúgUf*í!éú­Ñ¡³Z÷V…\VÁgŒ¤ãŽŒô¼¦&íAÞó¡£ g–°lvçdršñÏi]ât2,u×À]h]zfÎò-ʶ‘Nï`ÝãžµMxp·Wçš}Ö›!³vS®Ê.ɘuHuG!&0•ŠÐTpþòño0ò¯)äß{¨P„ÞIdï‚1êHß[Yu§±vw×¢18ß Û=iÙ·­ãE´vÌ£<ùæ¥o­yš›®›7aHÛÒ§™•wP±Lf²ë·Ùo¥ÜlAåmä)ÔêEá}ÈÚÉ XßcÜg„ößeu †ëºAJ«Ò?_¸êå¹fºÄ[©§¦ù0—/žmñã**¨\ˆ]m¿‘"õ¬WwÔ‹½¥×Ï^ÀkÞÊ˽n¦Ö©œ.•Ö•Ë{Ç7šžsÔ¢ê¡J€nH{-|JÖWp$Éš×EGæ’<‰×x “Se•å¨}w=RZ—mµe¡÷¦(‚­Ë±x/hØgLK³u\¬Îwy½Ì²‰}.Y‚Œ=Ö§D¾©Ä -ÌÕ¹ÏoíVδ¥ëÆÖÖ«U­dÝb€ÀoÜò à{{“V¶—œÃ^wVE³„ðΆ½£º«LŸ¯ñ¼»ýÙÑ•¡c{"J‘ªíõcwxg'Û×K/Ö­iSžjÒ ]ž›Gë˜Ç&iŒÈÜ»®§WÛÉpº·çÑ*™¶RO!Å¥Þ½vÝuëì|rûác/’Á”J9]!Øoiâá ~¹nÕµ~¿pUC&#§°joTf¹êë§áIg\|Σ/Œ¡IaÖüˆ0KÉŠ­^Ýû]ʲ”îAð̺V*NÍ€tÄ«1Uïr%éŽ-« ;¯Á™ Ç.‹_ʡŠo®½YŽ÷ÛK6 ÍÞ=ÙœM®¬[f®<½Pµ‘m6^dÒÖëc˜Rtºƒv×^PPVØ[û:]ó™uÀUذì§áÔzó;Øñ¢Î>sO*uÒ.¹ 4ñKÜ­ÃÙCUc{Z¹ÞЗP‚¨cõ QWf‘µ·Ñ^QbHnËŒÍóô¤EŽÚâ7ÍŒTÙڼ䋛¸R´h]Œ¹kÔ×uu—C¶Q©—Å©QsÙWQN¬ð £µ.aö»"­*3ìgÝ)NYÍ¢÷ª~”íú—…T`ø{Õlfe›ˆ¤k‚åùú¦ÌEg»áî"ë¥Í{Ã\ë›ç³Iô¦ý& ÛΨAc¯YÅÍP˃̦ RÁÛws´óhA›Y¢¾ûï‡YSk£Wš†tW³[Ó2£h ;OÎèbÄ€ÌmM—‚ƒeÁtA…Ž˜Kb÷N[½ucœIšÚÖð×›o ¼f « “›¨-Tàà«<Ã2a¶–ZÌ®LiT¨•µˆK¼—µ£)h‹íëaRú¿Üjö›b’+E5ˉ¼¹R•îÜ•k #Ü>Ûæï*úæ’!0P5¦ «E<¦Eå+ê8µ±6Ý^QÍ! “X;L 4)T¬Í¸3.«¥²³ ”™µ0ðq#œZèÝ®®X‚9;ÅK:ÊÇ´gÏã)Z¦rnÞ¦q` lQhOÞÛ©Ù<ØÎ~§ <º1ïN—Üv¶P¥Ùå+jqlßtˆêöûÎ9”ǺӾ‰ÑDaO‘[yÊ.¿2×ï{4|¶w=ƒ/Ü2´Ö^ŒZ &Ð÷œ·•—0‰ƒvúSrøc—ŒLË5óOº$ûlq V$y'ÌëìÏ-ºÂ!¿¹;ÁKS×Þ¯}ÃÅ"ðK懧ÂK+´ˆ±ŽS¯vvA7ʽ˜•-lžÊ€fãWíº•ѽ/f¢¦ˆÅ Üí3 ç}¬L—zöÙ1™¶¹ÖïE`õ–9vã©¿SXÞ4«]UìÌø±-×l»Ã¹ÑÕëCy^ž«(FÂ=Ò@f^9ß=hV 7 ½±h9„©ç>Ó àºëêÒs2e멲7ÀX‹6»¢Ÿh‰ë¶­tW‚Ѱ^Û\»OZ¬£6ÆER,cêÃ"[ï$ÎÞ“s'»Õ+½‡˜w€qÁÛì&q'š%uo– +t\û]ÁvjÛæ¬Ì·3ç,hBµ=…YÅ¡÷m)|ï¬ÒlDJì»åpcÚÃ.^ œøY•Ø#Ãu@/Ræé[˜|µVˆ³ÈùéD^‘ïD»1ëªÁ’»:\.ÝönrZ¬¢• h5$ +³Ò·_ Q}YغŒS5@Õ®)M·± ®¸G«ÓU¶RÀkuèªÀv,]dãlºÎtÂ1ävØìš(6¬Wès t±LTsÁ ôàyzl/E<ê!Ã)A ¥z‘C‚·TĻɕ3“*sýµßž@Pü7ú¼Uþ¤5 ÙÂI-‘¶‚” ­^áWÇE ¡—Œ£¬µû¢ É/X(óì.•÷d«Ñ¨w3M.Çt/£ZÔZ±8É› U¦ž¥:cA.G%§…r›6W —Ñ“ƒJùK¬ÕS[ˆ^ÆdÓîQ=cÇ ”ùtì\Ü%73[hzœÅg3Š˜»-‹©aæ…%Ò„Òp-J*Í¿%ZçªØñ9€úèœ[ìxß ÊA’·³ÈD¥ÆlžFЬL*`º°V¡¹ž1³Êâ9³r˜Ì]8ðÝáy LîV(3A§±·+²…ŠÉHnÐß)Á£y°9u¶‡]Í Ò–¢õ tÚ­Ç6­Þ>œí?[‚膯§”Â4{ìæ«:CupÓE-¸žn½Ø ж{+ºCÙs°fŸ[%¢2ü°÷Ÿ‡¦ú\+&´PŠ”½úêÙº°«+|Ê‹5ë¥em#G{¨Òð«ÝÝ•pãârÏŒºyMÊ„ÕM‡ä ¯`Ž$îdÞ{aTu}ˆ‚ØÁNÍ<°f!SÆ“RÃ#ª/ `°FÓ­·—Å_máA%yŽ÷Ôƒ”•¤rVê:ÉWnëÙ̧S´æÖ¡ëôÙu# é´^ðˆ;Ón ›œ{–8I\:;¸=`Ú^¬Ò}ž=&#à•I)8“¾ãΈjYµ•y¡Íã·½OÞÜÁ2É ºÛìVú»F ¼ŽZVv¹bsAß!)t-¥¾“*·íÜz„™$±×¯fle~yˆ Ñ¿OÄuÌÚÝ|å©\H9ˆ¿jAžIô#WÃr‹'Òï^òÐ/ÝÞãUž™ì×}GY¶+Ø0=k#Úuí§¼"+ *ëre8}Ò¸ÞÐØW%ÃÇ\®ŠµovÇ`#xäX'srÁTȺ|·8L¡lEs±—œI[^ñ/eOrÅ©IRqc_@ë;µI0ÔÚÛƒ´]Z|VÉgc3R59hSk°ÁoìΙœ//·zvcBs„¨†¨–!˜Wdt”’À‹A–œîuÄ,‹nã:’ä/ZèLÎU Õ›I¦¯¨§|¯]7¨åªoŽ*¿”iÞãº.Ûéb¸È¦ƒhxÀ§» Ø)]*•¼O÷«dU¯õNgÁÖeüÝú`µÛ9P¾±ç&œwfï¯"îx>ÎXµ¢Ì”ÒÑšl úA¾˜=ì»ð¢1«bb¸®{?½=§z¦ê»˜ªG¸êfåíZiMøÅ_cV Æ Ž.F¸ø^'Ö¥{gˆÉ˜ËÙGÔË™×OBêBîŸNÐb®YÃ"Å¢õ:Í©çIm-%­Æý‘Vv•#`ØkÕØ×:]C ñYUð›©Ï@Éw9{\`c•ûYa¹¾÷€¤ì—Á4zÕ4[e›žP¿ÓÆ:ën®è²¬˜¢3Œ‡äŸofÁAëÈ,Ÿ]$ÒÒÚÉæR‚C{Þñöó=/¾Ô}ây«.'ôîx%¸ÓÎ^‡Ýt»"|7Ô ¾Vêì6h‹ëÑyqÝIt"Å@ҦξJ%•¯R¹åÏmê]yákÞ+œcç òº~6ª)ÜÍí>†²OWm"Ñ;C¯´ò·°‰z[ªu  ݺŽsÞp˜Ê1½RÍ¡…²6ÒÈéâêÜ£âcz®'8ÓðÎúøPξtyÈgĹ•ë©ÑdÎÞo€u5Ó@mM4GÞ]rò»nSÝÚ›¬`&•Ñžº³Æg«Þê#ÉÈrSÜÔ9çWçøïu«í¤f-K&~Ê$uÛPìØæ9GN­ß?ÐS¦³Õ{¶jjß#e×’—+Ö¥K>°ª\÷^áû[1HÐÛ*;Oº¼§#Ÿ¢ô¹¼˜…ÖD¤zð[¿o´XÍRló:¾·|³SM׸'ëˆWE”ßÃv½lª3y„«‚¢Î Î1ÙôVÖÏe<£«ÎZX îJ*š¢<<«d/ÅQjgq<ðvã¤wkÔú€V^c'mñaðžö C:ŒY’³¦/SlæhcÛZæ¬%e¥}Œ÷gJ°sŸ8Œ·jòtÊâí·Ýºæ‘wG‹`œ¤R<[½9®õåY«Óܼ“to%mÅàÂ5ÈîC1u1x=³]åt¶…At»:³µföð6(+©0ZÛì㘭Mƒìp —v©¬ê½›ØdÍÛ¥-‡­è›¸â®ùGJoÖ3Àb ÌO’¾1國¨—WLŠÛMµ•Äâv®õêL»M¶1ö¼X½Œóñö`'.®e”ò‰8<´ªÑž›@WB{²¦Å4îcÎ1ºVÛ„šÁÐéÛ“m] ¾‰f…å¼îŒt;{$_±î [~ðË%w¾é ò]ŠZ×f¢w–2#•"Þbp‘2Í;š¯–8å+µ[©ÿYÁž÷+Os‡^1/Êmð¨ºîã ºVÖ ¼I—( <]¬®D0œvbêÎ{z7xW†úž»s;ÐNr¡rèU9€ë²ÈuÜör€Vm ½9¶:œŸKw¥¼¦Ÿvߟ•F7Ì_z¯jÝCWÍÑ»÷ƒìzå‹x!Gò®Ûñ­òuîºZ`׌`¡®¶? n—ËÝÃsB6'o± w—#ÏtÙ>ÈF× ¶ÒÃÌt¤ßÇm]ȲW˜—[4¨œ4ãÂŒ=åô¾­®¥ºê:^ÊÞáǨ>ÃÕ{yRñ¬æ¸I$À¼÷³¯bo{Ñü%·y®uèF9*ckÑÞú»¤§X”6ï¿@øeü9tHŽW7É¡{® §Zøan´<Ÿ^ªÇÚ¥Þö¿…]Áa¨#Vù4¬Û{š=L“׋ÝeTãÝìài>ë7}ª’/¥Äž/†¿¶r޹õq÷¦ˆ­£ì]½MÙS}W«@ÍJ²ì;’ÞIÔP ÎÝ\¶=<¢ãöè€ÃVO»Á¡ÛÀ ®¦ƒ ¡ÙJ*ÃÙ%¥D­Îî&¥©°qʶx]š–5|òF÷TÜ]6+p0 “wÔô‡·çÃ)^.Ÿ,ÙEžâÝa¢4í‹NÅsÙa…ØDì°à,5‘,¥m%™^!²× Ñâhúsä*æ¼áZ^R×™£ ò\Š÷ Öœ|M¬Ý£án`$çÑ ¨h Ø’´ŠÇD0'H¡Üztì`Üí| Іr©J»Žs;s²I¶¥Ýzl¡ídí°Ä-²iëUkÕ¼j€IƒåbUî®o*yô¬´çT:óMÙíNvyp7F¶°ÂæÈÌ6±Žì75io{Y8?ÞvÜK®²=k‡s6#u© ÌeµÇ$¸¥.c·qtºw ÞRÊ»+£"¤wÙw*{Þ¹C½Ëêõ±Þ:Óòôvj'/ű­«¢%fùQ–Aã˜[ËÖÁ͕ٛ4ö‰>íЗ«/‚§WK3«ÔÓÖÑ>bTi>YMM»™©=*tÕ¶Ž'~‡o§¥\m!µé‡/Q%¯LJŽ_°Y®…^j#` ¸LÙZf†.ëcàÐŒ‚N{P |¸^¾}]¶VŽ pÀÂ<‹º™wˆO{çÚ¾±R½Ú UÜ||‰…uÒû›bÈŸ­a¿ Ùr~H=`T>×/YR7"Â_#JÍLÉGäQ^SÜÂùÖçrx¿t|%fЛ\1{šq›—tœ=‡VBó1Jê›Â+KÕRœ,ßNÌz·“vAy•z¥ hž 5‹÷‘œèX»_4›O¬šZkÛSxÊÔ3á:ödrÜ·L±ÃE«¹+{\ã7läå[],4ZÌV’gHþŧjÉñOïb²øÏ¨÷;ÜŒ{[yLƒ‚DtºCv“†¤ Ú]MeÙ·í<®Èöý´÷çyA]–çbIU߸íÒá9ªrö\˜ï­+;|C#ŽÑ´W`÷Tš¢VN¬4{ë@{…tÞµë#Ÿ{Õj¢ñ°×)‡ Ý6êÅ KUÖŠ†MtÞ?8èö¾¹âº’¿ÞhÁt– W·=FöbXjEc+Wë©ö£k•NÑS¢¶7v;°;u;†{·åØë ßCIE¼‰¾¾~€(}·£ž-öºÕ[Ï)síȩלb/ãÆØ b–/6V™¨ÂóÜk1¦àêâŸ<®ãz Ê}nÙ¥v÷•p¹7«©«e¿Õr9žï+dÙDuHiF#è:nÜËhêëógIåYíͼnD­zÙÔŸš”ðEúJõ'¸Ò‰Íw§½:xò&Ü*LÀž6ó_Ð ©D× ¸3º:á¯s„c8D Jà;‹ì¾}:UÆë-Ê.÷;ƒQLו€A€RâV­®®íß”µrY3>'VìBõ!˜7Žnpds$:òh*¤9Vrêr°Ç .»L½ÕEÒaYsFæ„w>¤ÌÌÊ븺qš0PâUì;B›Ì÷<ò·kƒ©Ï8ýLk­øð¾ëÝÜî]);’ªÞÌ­C;®­³YM*¼£Ù{Ù\õ÷vÒ(¥„R;MaV·Y³hi[ÙƒçF+u¹©äStÎ%všYÊœ›f.+»o–0a­5}¶«³r¶øŠ‹:+Y<ÇFÙ­î)Ø+Y`pó´V†+ƒwÍ2NCƒ»’J¶hrè¹Û€Ÿs¼%yãïEÝTêø;»ËÆ\yµ)  4ê)s䮇%jïZ˘º{©aå :è÷Q‡Ø†'«¸‹4OM×IÇ!™Ï‰G’ãÉ;£ÏS{¶7KMÚ|/„ݦ’àe¸é-V¼]ÖæS6Å4­ÌÄhò¯3´Ö^ÍßO$N»S]…<8ð^¬™Êxõ åXY¹E·cÊñP¶‹ìÝN±¥ç^ñÁMçEéuæëoÞ ¥3¤â,¼­¹ŽÏ³·Ÿ^z$sÔc§îé)º {>·}#Ù2±ÅÌdH#ÜÝPÐX½¯hÙjxÜÀ tJ¿xZºØÝ4Q «¯z¹Ûã8hsž¥ÝzI !r‚ڷ𑬞ӭ÷ÒEÖ>ÆiÇÉæïvÃ6iå¼}Ô÷›3*ø*Å;§ÈF]!o{)fÎËãÞõK8ÝÀèt Ÿ@éáÛÍlì§µ—ˆb©) á½’Íù*^ÕÍv²ej£dw¼Û Òe2j·/ZÜÑdSy™Öœ ¸¼(ZÝÅW¨ï!¹¹Y¼ç´¡qZÐ3‰Í¹Òm_ ó\5¹Ø{ì³x©åűÇ9'·Ø %Кbvz€X¢•ʱš'SåaØ:öã8spv‡×¯#É‘C'(¶˜³*åÔS©ÕÔV{†UÍ$UZžO’r1u‘´-ð ½Ãmª·X¹µÖ!˜ áqdÇ!êmïEB•¥º•ÑëÙ«µ«’ëv“‹l}Ñ0{uÂ>¨Ñ ÅOV|ÅÀ ËÞ”Žîû©÷g`Ws‚íõx‘ìkœÁ׆ÛVÏcm­”þ´mݮͺ ~Þ£lž7r±Ù5dšX£„w‘±ƒ«ü9P´«Ijì æoç.‹J·¬ÆV(@g•2øiTµlÐ .uªí mÉ3'¾dÎã¢zº(+w[×-`çÏו}:x{¡É–§¦øzkœXzò­Tƒ#Ç#Çxoå#˜8ðí±+m÷5W«.ßyv¹aöW<Âxy-ÇM‹½W½¼›ŽÜJ\qUÁÞ¹ÌÑo5Ò§Ø€&jy€A :Ô5 ÜÌíÍŠÉÙ™ „'¹ ƒdвu€e,ˆÓè«:­G€î¸nÊ€+e¼é£±Qq »$E`­.t:®*{µ½k™9vòëwuÒpÕñÞ¿Ïœ±GåÈ‹æUŒÇû¿]Dgh¬YöË鬱ã>WÙIåX|¢Àìœ5ÄVTÆÕƒÑ*±.Õ7›Ðm5Q*ƒb$÷3V“6vŸ!yKc?‘¸,_¶J‡Y@¥±·²9äèöd»½/ašõ6Ç:Ϙ2fºV³(K{Xt5sä®Êh;Õì7»çŸ4Žgמ´V§©Œ³*°µî#:ãÜöÓìÍ™FšG¿¥^=Ï6&+XËÔÐæŽöšO¬`¡Zû‚Þ]‡U­ ßDyñ¶éÜCÞŸã½ë-ú êxñålâ²0»ÜCÅ;”½µ|¨­ž+¡ç›Ým™$ßEJÈ®òô[gPÒßM$KÔƒÎõf×NNy[/î G–åq€óœ|óƒ ¬·w¸¬»«Ú°ñxí’á4ÞŒPvÚ›GPÕ‡¾u»JZ(*$à‚®Ç_<9 žô>T=íêž—F¥—ânQ™nQùK°ªW “+TéØ+b¸¹Û×òJþV¡8T½áÎ*àýoQðjãVë¨:s1,ÙâÄ1¬ãS«ÝŦ¥ukß#¦:~Ø/ÛÝî::‡*>8dVì©BÔa•¢Q9Õœ^ÚiÒ{¶.⳪ƒBöƪ¾ÖEuIzE?† Ïn `Fž>Y¥ø¨ÍĪÆêÇÙkENæjQÚNý«ç~7=Gž`í8½,aX¤Ëí|î^cѼaÔ7Žv{P×ìˆR}g圊†Þ TâëK»2ä5Ë9ÝEäè𭳫dZ7Üìª9–Ht†3l¯öôèoqE²ð &ò³tgrX .†¡¢mŒwuàæYs…,Êòu–t`ãͺr¹ØhšãÚ–e.V) ‘È·h“r°JñÞó‚®áÏ"oU ®+׌Ü6beE§ÀVd¬gE1};_fV95=wÓ•áêA²t £|±Ç}cW%&°Êž'Æ®¤«Á±Q¹w—ÆL¤"Bô©Z ¨M…e^ÇK”V¯Q©Qº}Up:Ôs…Ö©I3‹à¡HÜ0êñÀzgììK•B+ÝÙ*íŠK¥÷]ûˆ"!Ç%§Âò$¢we‹ÜÚè¸Ööøsš]ÝHG/ñ¸Ö{·€F»½Õî-ùsˆí›\m¨†îö}C8M¢¯·åCHyêÃ[ŽÎÂðàs¡¹H-h_eÒ‹HcW>uÅй Ëø"úúõ‚ö£j%·ŒG  ™PÔM>µœgˆõºõý"´¨xbö€ÍÔ÷&•nGMŸ 8(k%yn­³œ5VüæžÒÐK"'rc±×¥ûUºã¥Õ·%ðõ"ëðgaTifñWwäÁ”+gM†£¯{Wî¬ÑËX(UsÚá#ÉkËI¶†F­[—ƒ"{1ƒÌî^Ìoéëå¬UÈÕ01à²%¼Î´M¶(•³Èã‚ †ì÷|ð†j½à»0L\>¸íå Ë%‰ÏžvßÖÍÎy{ZEFã¹’ú‚gS8ë©íFYêÓoŸ-£9)®Råëa³½oPì˱÷iÎÀ´òWµoƵªŽy n¶l® BðÎZ+rZíˆË•¹•ÝÔ!Ã/¨¢µÖ‹³º jr®¥V ®Ý–~Lð¯ldàù©•sˆ«ŠÁ'. ccÙ¹QlÚ‡¢]C>¹Â™Ò9²1?¸5~Óîõ’;ÒãTGŽÛu3"­Ý$UF­¯:Ñ%ÐÃv+{Ø(¾,ñÌÃÔa*Ôµ®=RÒë[ž ­ø·¬õøšÜƒw¸ÙiwcÆ, FN¼T»¾˜ò=aa«{Í_¾àø”¶ÀÏ7òØòf%s©+2¶@öãÚëã™IéÎY‹Ÿ(eNát³³K©y—FP¥îÆ{//ã“¥æÚÝ2€$ È´eÝsøïØ=S]"CbvëªðÓ5¸³ÕrZJþ•m uŽ•á®ÀÒÏ<îWQš®öä‰ûwOd«’Á±l"ýÍ-Ö´°k7L…!$©«“¢qÛË®êŽTËûhéL(°Ç”DBê\X®啲·*¶÷Nü“®U¬-ŽáîFñßt€'T¼­û;Uô–‡mÎñÞƒ:Í\5pÊU­÷o;ÜKÞײu‘м£ìárnÊiÛ8AOÏÐò«1ç ÀÜ┡uÇF+U:¿[ôëAÓ„Ñ^c×WÑòuuÚªÎ:кbo\®kïãØ+o >•‹ÓÖÕÑó: Ö$Ø= Ö¼æÄP»Õ½87xÍ)ò‘º‘Ñ€ î®Ðb¢¬»rŒ._rM>áÈïuÝE-8å`ÖѯV¥„+S Th¬ê^ë¡úê!¾’VF€ÄèMï–¶›IWw«W­ò'Ëz§_%›¶¶z‡ZiÊŶ3à­ì4ôIÏ«*¸J€'6Ëh±dÕÉÜŽèI\ö¡\ö¸Í!12ùn«©fçœã\Ù£%`Šf_&m$7Lì–Õ&Ê»rN"®Ž\V8UDzÍac½²Ÿ«µ°<å›­º^p˜NçpøÇGµœèusW^ ˃C¯k;6ÐÃ6v?w½|¶Ç¯rn W?^–Ô7ÛÅS‘MÈn%p±yÕŒ:ksX[§I̧0s"Úpn}·Ô¥„k`¹Oñ3ÒÜc 浯 géîáÔ-­Q†¤>•"ÞÊ& Êz}æýÝ¥g²Žqx½Wa[ç[¾|3`÷S î ¼§[Yá–’ží{~wN*tÅb<‘õ£¨ffuГníζºTÍ› 3NYI x>oEîh¢™L—ºVðà„‘/ R“eÆî‡-ßz¦Í»†æï:ž—ï]%>6)å8vÓ—óõw«¢¤}ž†‡6ýI̳RˬÕ`ž©°3Osd u<Øpvå¸×r›šf`„"Œ­Û7²×+kK]WÚR‚vm™X´¿ƒËa®7t6-î­G(ðU Ä€%_JÃp¶Vî¶,(2è¼E¯º ¶û[©Î{W—)̳v¹"kð®t°±£{ÝÍÔÙ}ˆÜÓ'SÖ»{vòr-xâõTû²¼y`]b.=Dž¸·ŽÉØð¡¹P%—ˆFênßläíMk ÃgºW?år—½àO\ ÁgNÓu.²ë­aU³"ïYÛo«r=y¼Ý[¯°¶’ PwIŽüø¹gˆ‘,{®œóâféL›[÷Êëû«Ç5?T4µo[õoº°ôš#ä3rsÙp­rö˜¦c+;“RöéVï`Õ ±„‚ðü°[I[]Ip­šG¹Îº’êìå´k®8÷Gk17weM°‰Å¡C¦ì&\ºœkq¤ÞŽÊ YÜ£ì°0S%D[d­8´M×y ûQo7mKs«Ç Þгѩ îñﯜ ñÛ×TVt®î_lrdTr…H¨`̤·«qGÍ#}So8iÃudð«jU ÆẀ FÜ^ñœŽx·*‰k•׃ivª¶aõÛ½]Æ[ë­ðwã¨ÛaWô‘;é1ìW]ZHÜÚ.ã5˘ÊÓºÚ¨µŠRïlv⺙}ÃtwdtΚ“³{³´ “§pe×0‰$g2ƒ’ÑÔ˜bTØzUYçË”+ÌŒpÁ½4.qy% ;RâÙÊ[¼–êÏFÐçÝÈÚ–õYÈ«+CML˜Y7šµW…¢Î³8Åé­É”f×V¨ã@¡*Öºõ­R޾™ÀÈÈà ‹ËÀ£˜wîU|6œAÛ"çŽ;p< J“ãêwöYm Û3Ÿ†ÜúwÀÏ•iᩎÃËâ0}¸þLÜç9Ï?ƒåí§ãrÏñ.¢½Ÿ/.ýô©=Ú—zù²S™¶‰·ŠWay² èe –B aD²dÍ(MñÚÝš¨ZϤnf'´kØ©w¶Šg…Bý†K9ÒžýwíÚÕÕÉm¯FâîÊ7I)^Ù¦hz¼3¥µ‰krbê¥Ï—×} ¨!ŸX‹{ÌßÛêX*QuêC8—GE–ï5Ÿ¼º½í鉫¥éî“|r]9q"LÎ}VtëǪW¾ÝÌÚMc&`«ÙoUv\¦š˜÷|Þ(ÙÍO¨POvèÂì­û¸Ø”µ¨¡à³”­ÂnR¡YÑ?·\,V£·0€ù¹Õ¥†’uzÁÏs¼p¡Vü}[gÛR]«‰]£@fÖï u˰à«y!¢q7E{Ë Òý/odÆþWVóXh9Wv¥-ìHÅI•—$ ,H“¢þ/zi¶2§q´OªßlZÅ3lAнÐjò –>Z²Â/auÓî~…@dŸª§-#P€o9C 8˜¢·” ;‰d”òôí`uÉ#‚­U诟&är(ÕÐ ¯ªó°K„£²º²ÝêÆ y¾WÛØµËÛ9îi)bYÒ–ZwêXŸ:S™l÷d\­Q™ÓàJÝŠŽeˇ8å±0YÊÔƒÅÑ¥ÛVØ4O ùܨ{e)½Ïñí¾ÝŠz…am-š;óÇ›3Í‹¬3V(èK¹¾7”«Ư§5ÐaÛ.”6º·K}…ÖwBÿ5”óÜ#·®‰V<Ã*éÜ> á§C¼ë¶N²&ê²9ÊzùçÙ-Ÿ³†îÕÚÆÄyN%ÔLl솲iÝË[ŸoµŒŠ£µµ»sª>¼Y¸žtié7Úò {È#ƪdçÝ£ºGó\åó£Ê)Ž´ñêpܽc½8mòàä4æž|x°‡.¶ÑPc’†Þñ·)a¥:ÕµµµÙ¸#œz†5g²Zac­mê׬Æ7Òw$ lõë*¸2µì¡2u}µ}޹ô[Bå®Ñ6yýÜg—XÍг+õZÜÔ)ñ0[}­èÌɹ{I]’бµ¢òvóâJeÕîEKzðÓˬàvw]‰Ÿ1ZÞ§Ï$ù»bþæ…HmàhGÀõêVëiôÄp»WWÕ¯}uŽ\õKÊõgJ%Œo›G.5ÅWZ%.°îÓãK®P›K²gÌÐØö/ËXòÝç`U‹[¼=¶¦ÖQ 7á1W.]:ÒXî„§ ¬ƒ%ºÅÛn ÐÛ·’¥cyÉÌÝê`-èI²•ƒ<>nl|6;;ËCQgŸ`Ý¥¯FËDeòys-·¡Å`Iô£k¦âWˆvúlÙ{Èå¡I;7]²ºr¼¼êÎq’ÎFJ•À§.Ètj_vm¼£Ù~8®S|=Úý‰‰/íޏ]ÛBÁ¨Ùwk3/³|JºÔ dšuÜ!’¥õoswï­¶vσ(¯Uðß3²ïÈX¿ŒÅjÓ)/¶ «&ü]×Â(Y¥CÃ,w|ýBL×Ô)Uйö£Îï¹Ëˆ»åÁJ¿JÝ»÷W‡žW™òIê7¶ݽÇO´Mǵ4@‡?®wSxG¬t¨kæëÕM_ºáÂÛ|5¤ë± “);*¨Û˽¾—WSÌâC*òÒÙT}Þ°DvqßovVa¼¦©ñ»æµó½g­;έ«V®²ÖPi%ÙÓhÚh^ž´NtƦÛZYYIAЋц•_E¼ï(~…ÉîêÄÝš»%æÆb™¿¶½wb{8“¯P=mJ>ŽßzÛ¼)´OÍ«PICl×qLDÆö¡´ÓËËÕCºNmH!Ë.¶õŽÒiÉDZìµ3;àE•bMç{Õ”ë³{7˜ÜÞ°OÍ™,ð£òG¡ÒìEæñ¥{¼»2¯‡e‰Ï:“à‚uŒò»xýwFÞ¸¢î€˜4í.Ì’ÆâÒ-.Õ»Y8¾}]šV3‘Vö»n·»\Ñê»ëÅf|u´*G^ºÉÌ¡ç«xâ +PÍÀû³q#×m16wû<ëû®zü‹mV ÞVJ|X¾¯šã$ËÕí‡ÝÕÀôÙƒ„÷GÜŽ@52W§%e;¼yÖ+YË‘è¹9ò­¯’§À<]Y:¸OÒ´Âðf=} ™¢‡Ct&¹}}Ñ:–;ì¿b£}—àmx#åíGbÕ¢R§« Ä6æ24’rJ¤Ye…®·£ží·#ØnôÝ^#åèý,rx¬zæxoîiú•_$]”»›•Ó‹1¼ñÁî:{4õ w< ^Ys TÂ_ËyòWg6ï¶Âê³0µƒè1=XhwAVÁN:BeŒSðß0Ï sz¼?;€C]Ò–®¬›§HÎÄWu#®Þ5¨w_vBmÜÚ±Õ¢máàúr&È»x¡Wk]ãI2 ÍpÓ燬´gi²¤xܬ‚ÛtPŽ€àðÜG³¥ÖQø »¨‚Ìꕌ.åQ\¥[·åö³qýäÕxH¼@hÁKl+%Øç:šá•c¶’¼éÚ^f™áâs®öí¼ô¥•~ áÄÍMÆ(öe6öÎX•(<'v¥$‚g¨ôPì]bT¾²ìoqËǵ›LrtIàûÊ6ót e¤(hë¸Vº}+ƒÖÅâ3¸3ä­VæK§àõ8ÜÀ¾<·4ÊƒŽªÖeuÎ1í93wŠyÔØeA¾îMTh£Åç0ªáyö`>âœÆ4h,<ÂöþËIãì«í' ®¾ý%Î8¬·ž}M`­”7¹ð²B£3–ÒˆÓäcFн®´¯³kcîÕ´Ã?›˜ºBÅ¢žb³äPÖäbðô@èæõv"ó—WO=ZFg›<¾CÜ-“6;´ôÑ·Ë!4{Áø5{á«VËt.[u/®™Ã2»ÆŒÜ³å·™Ì?e¤E0)>@&T­YHïwagÈ—K;=ÇçÕËggkx¡ö_¯q¿ Î3«µ$‹-ÖÚY]ãÐù]ÖÂoƒ[¾mIDŠˆ••°A…¡jT;lRMo¼êåöËéŸK"ðw³ipˆ0æÇ9‘ƒ /ޤ*ßl3(,,œÄÖ #•«5À™r7#Ʊº©ˆ„ª«ªQÛïfx;¾9}œÝ‹Ò½HÓ+°°ÖÓBbÕGÛuÇ_% ´ á/Mg¥çYYf†æSï#Êu¦iY9[w<º­Ì¾šKCŠß4¼°x=9!æós•r»Ý´CÒÖh­B7¾¼³¶+æR<É’r2;޶Ÿ½9)V%ÍE1få_] «%°ss·’Ð+¨*ÞeްG1|ׯû.ßA«g bÚ²NøAfEk­³ÚŸ3o^gIÛ“´y!WáÙã¬è8ä”jöÁv߀ΒmV5ÎA²}ý„$=l²FkbÕ÷¸c+¶»ÓÐôrºïÝ&„s=QooÍœÝìC!Ôw*Ì#ãè&ØSÑœíÙ¾šû¶¸´’kÛÝ*ˆsw˜Š,í×0ž~@>{v¨ö`—g×Z-êtom¼i6¤R^ùh!Û«K‹­ŠZæNÐðøžUšK7‰T»Ï4¹åA%ùK׎êìqçO³·b ViåÃnœÞê.ç>îÝÆ4±²T½„µ§IÖ€jT¬¬7&Ò4_L⺻…Øâï­[˜kVå)³XÓ·Ã[[C’슯+#ªÝñ÷o»›†El9^ÛÕIÓ5ë¿e³Ôñ9¹Lðík^ÅäÅ |È4ÔÔ‚X´äß×Íðƒ(‚-Æ|Óšwy;:hîV5Í.á¢/QC7ÃKë^¶ä ¢få[wºáåMèÃhÉ ÍÜùR‡ã–C²ëÞ“;Jž¯"A¨žMÞ´¬ØÑKB›ÔÏ4ìñ¹Jï1èV1’g,SzŒp]î.8b¸0 ¸ØÝ½Ñ=sݺ_¹ùnÓÓ^Á‹¾Ú1sùV×L•…ž;ÎÄëœ:Q¼ùS°ëW¾ÌØó]Ù ¯=Õ[G‰«Ê¹UðB£Îz}Ûž©W^ÐTX¡íÛi­[/ÇS©(ª³uë`Ç ïˆ„^’ÅöŒÝIÉÜyàk¥ñy1N•;ííÊÃÛv'@=y.y> 2SÌûIßX«æS½»u|X§~›Ç^ë·ÝÑès'Ìê.™îîl0àÖ°”wc0«ÍçŒÙµ®¡8ƒ5PfàK.’Y‡è»(B®fÃß —ÜUt\ˆîL«=t”º€ P:ÎÎ¥eÁ…g.¶^Ù›´„'Bf#GAŒ– á²]YÛ¡ÎXë ý$éuÛFÆÁ^jŸaÑsÙçrrhï‹F•›“h8R>€"ôa’ÚEáÞQSºº&ƒG= UîÁc¦árægß#„èk¥ÑûÆ>Ë¢Ïjy2‘C_®Æ¡:´V¾ç+VI®5—[}Ò3…-Ê»—ÝAªQögÖE ÜÄ·¬` 3€%VÈïLhð32tœ»y»8Öº=Ä*»u„ð#> ‘í:†i ×ZFµü\›îq‘2A›†·¶K¼K¦ëhëœ×dõrUjîÈÚYßN}ÚT‹Z³K3R¬4`ºé—kxšKEÞóÁêð½ÃÍU°tÞ$Ë{è9ÆxKÜ8Þ •ôµ¨’ê¯FÀ3/‰ÈûͲÌB•Ʋî¸ï_Ûb#5÷KSo^eŠ%‹UcÝç=~åÊÝ#ÐDRÅÖP9)ôÕÐbùж µyÕ„k»‹—–àðï@7öýlE ѸÆ,²cwàó3®Ã‰7P!Ú:ÈðU»Ü±šYñ§œ}‡­ØÌ—=³]h ­#bÑ9ˆ"âs+Me=ÒSê6!ò&Rìv€G&iU•”ïWuô¤ÊXÃsîz‰É ¢L­˜90Ó•Ö K§Ÿ°ûÆw«½&€áxtõ!ÙÞ½ö@ÔÕfX§qòšÚ's¥ŽQµs#å[Ý(u]—tfŽÏx³¬4E¡ìæÖ´Áàܬ›ÁüC”1ªÍE–M:…„ÅÏ#vá’N%¬°UMrØ ' “½ÓÌ ¦;>ëí;Ø7µiQw5tM­©fšÔö92mÚ;Øß..xõ[¿bËâúsQÞuÄWZ .Ú½x(Êõlᑪ¾Á•}LTßMÌ]]fíÆ@{‰ç…üjßEÃ=Øíö=Пc¡N’[ƒEÓ+±ó.ÝVþêð¼¥)|½CŠ-tßJk•¼’´GcV^©®0A·‰!öN–é6iðWì¦l4‡ÉkW«÷Îaøl¦)›wã Jî=oº¸n¬jع‡[êå‡^þÏPÏ.}›v^”½E‹ËR*G:3˜!±£_)‹7‘ÌÁÏ2_?׿g”‹EÖ.¨Ê™ ð u–pø®HWJå ªwHMûV^b/¦ÛžôÙª¯Û¼×®8å”´ÆL©0÷½”om<;_»€®—ÙÞlx©Yz”Õ<êe¸ßkÅ ëòÁÂI¦È›Î TûZíÉœi•&ÌéC•ÔÕ]6eîvéc\·òÝå€V1½®PäÀ=pâ”g'÷dËZ6åÚÛá†ëË„S}f7 ª`ž#ìÓ¢¯9qTÙzžrÛÅ—6Þ¬Þå> Uö Ìí[XëŠm•¯|¸[ñ¼},Kžx=V¹™Öl^ÁÎç&èJdzÎðìÏ:yn—zêµc "Õ+3‰xA˜Çe“\Šu ¢ž(0tHæ 5°Ö7hÁÕ£–’|òå*³½õ[Vï]‰ÆºÜ”®Ãîì°5LDfÉxF(WVM­jS|Ï$Ä÷!\×gÙIj¡31ßÊÂêâß`éÒ¡C¸p¾yQ[Ñë ¼€„duÐk¹!ÙHê…í` ¯(ºò+ÖÛå{Ýv}.œõ'Ó,ØôÁxÓ­]y(Ô«Ùôë’ë¯f˽ >¸å§-ÒTß·Q®§âëˆP> !]⺞fzS|1{xSÆŸÅ'-ïÉqëºGyï{šD3ínôS`i®9WëÄÝÜ{Žønn9Ž=£oÖë¡í.„ëÙs'6išÕ…è±÷Û²†Ì<¹µ6œ fAÜܼؤH¢T°._Y¨)ã¤Ë»ƒ»á:¹Ñž=dû{O½KÀß—­ýi|ü7¤jîÖT£|}YÄUÏI5Ò6½ðqß»»ÂvNç–y¸’ÔåCNÚéƒzŒ²bU…yQíFá9½F§ &¼< "ûÛ¾"îmÈ¡÷¼Qv®ð:ìp–Õ#*õf®Àž<ÅÝ‘¬øcÞ%ð¹[‡fö Ôx«Á–KYäx9—$À‘I«ëˆR’ý%e=»\õœ{g꯾•ÌM*õf*sºX˜¨Óg3LœªtC;¥Ƭ–°°8Õ3Ô5CÚÃöº‚óÖ´ù[Ã5мk¢£"–‚•bž•4¢ž ¼AöjpŠÖ¬ Ú÷X‡µ,êçµ0ªb­ü GËk½•Öu\È¢‹áLW/…w‚:{Àèé´<À­Dl/OÓÕgÌအvƒ³Æó3jsnÖ0•6ô5[dÓ¼³¦:im •Ò>];+¼:¸cð«$cá­;K \ DñjŒŠÑ˜¯–£n¼­èžUÛ]J Aæùîî¼Wì'çWz`,ïÙ‰íWZÀxÞ1ösc¬íàheßP•7îvÎí•|Í2÷œÞê*ˆfq¥˜µ±®é:ÃÁS„Vƒ‚uRå„õÙBšØÏž‹‰5œu‡Au`’p‚×]—MÇQdúP¢`Ǻ¥ÑÝu9Û-6ɚѦ«cÍÉ̦7´kÇ·!¾[YŠ^cÀØîC7¢ëÖÿPs ãt YÃÅãB¯'_^e ‚v^r˜,‰3¢›ÓWéjä^_3Jôî«ì„­¬¯bW‡7 ¹ÔºP¼“+•˜v s‘’áOl‡ é[‘V«`K~ͧaçt$™Šö­ \â fÒöà¼=6ë˜]²l¢'½ßaôªcÖµVH¬11³8lç×&ó§u#çÈÖ\˜NëB“ç/~9»áYÅ7+(¼_s¯{)žj*éÉWCiô–z;8à—Z§³W°ÎöF+(]Ë<ÖL1~9³ko{kêC´²æ*‚eÛ©í<–cã«ÅØÖ·Ó²€ÉìÕZMHe;$ÓCEÎV+~·Z€ÇsC-®Í8®÷¾»1oÑëæ­e<Ç©Qa6ÂT/¯F@šËŠ\ëÕ[jÍõ›çÜ5ÅNìj$©bï6®eäƒNÚmw'xâyÑ÷°Æ;!j0KDd¯‹{jË}%ç­JÅÆåJzeÂàPµÞ ¯:yü{©phò¾<¦Œáhý­´ïŠa1p' × >¨xºÌ|–¥/ÝÎÊp8ΛY\DQJqå±{C$,ÌH @…ÝONÊXF+Þ82óXšÑ®J¹ÝÌ‚ãX·= õ®WUS*Qj•e@©íôkâNôjé-邺;4@ob“2û ¡Ž‹ÞÓ~¿-ÔœçÈ‚Ž{hc‘Ás¯25*îbù¡Ø~›Y  Úp7vN+'uß‹ \Eðé]j­œ›u_d&;w•«¸öè tJ:´aýu-mö ± ö/`C>ÏtœþõÖeÜî:@ÆòÜž©­!YÉ\³Pãs•¹qp«g6|bÝR@ežÖrN8 èb²Ô‘Y ¸Ž®â 2oI0ºµ+\¥Å»UåìG"`እå2›­ki^q@èÐõC«§.l9ħd£¦÷jÑÊ[S2´Îu)Ýü‘©ÝåE7ÚAÒ6¯¥Ù•1Ð+G®µ#VÕw™JeeçQ~d«˜”š7U{}ÞH#`YRø¬¾ì²å3I ±k•¹ÂÊ;pRohÒÞt¼=ƒ±An‡ŸœîðxMÃê´àóƒcW ð•ŽÁ 'ß].é™rô6£C³U§gcBèP·³–½©rνØG?w³%rÏžÑ<¨§ÀŠÝqÛà†Ô«Ï_»ç"èFJãÝÞ‹l׬7ZúþÆí aGÀ76½.ó‹œ$ÙÌouÙ4{{+ÊÐà0ÛwÝgkrÌr¥•WE醖c¾¼µ,ú Çæ…Ü÷N+ËÝ|ò€Ý~\j†œ6ès2mg¯È!A…ãY¹Œ‹{η[V;ÆPÐ Çúx Á^Ø”W Ü;%$ ±¹­íÚ/ô9¢Ü”ø½®¸RЗÝç¼Çw¶—ìÄíÈD åp2§vÉu.xî?u‡æ ^ xðìËßv5C¯1 áÜßZÙCAßwÍõT_¶/~­ P·¹ùëW£+×9¶uqi¥—Ûñíæãø`_qÂÎGÖû/3^БS<¬-‚ê/Py*E«E;ë%â9µ`fñÒÕ¨+b½Ú«¢'½•ñž0\¯du¦ìOpJ²yfÒí”#zK )Àã[D2Ó¼UdÖëWð s±¥) Úèýzü¶ßo­^=(,÷O #®ÕpÊÞëÇ,¯µØœ=ÒÞî¼Nën=U8uù¼Çk´~Ýž¿0èŽÎ§rló°¨jíjúwÊ^mÞgÞfÇOÎðæo¼»ËSï{B©3)&ÄâqžÜ&°xò…zû½‹µÝ„õ³j†¼NÅyJ“t†üÃlúf1ÌÃ}>k¯ÉkÂmD¯@Ж²³¬ù'X6cñß}töƒs‡èZS‡²k;«ø ¼yG/§òº­vG׃ÑñÉg»›Þì æîfÛ4ŒI§ƒt®®+¨èìÖížõ “²û™wòré4CóÞuÌè9YŽvåµDL«`0u³éïufžºkm¢+eW¶xTïi¡×(žÚÑëDó©Í8ä”jË[ŒÙL|0†o/¥vî¯3Ï2<˜õíºE{ zøFÕ0 ÜŒ}¤ØåÉRØUœ¶ NŽšðõ$Ûõ¼{ï' v¶zÜñBw©î;Øþ”0eÁ~ _^ÔÙݸXË:ŒŽ·€¸äÈõEÉ7#2Nx…w**“Ý7Oî×·¥±ÑIÌ•dõœÔ\å+vÌt!Åvëz *„ÚÆ}ÚU<:dHM¶UkÞ­¼iã¬ïu'¯9)@P;wlnb¡—ÌÍÚ"bì—§”\*æÓNZsjÇN’ÝÉ`»êÛÚm¬ëÌR²u½´o:ãsŒ*P'v¹Õ«‚“ã]1s:°‰hGZpVs·GsYؤf“I*W®e'Ûwz±§Ç™¡ìíÖ¨^»Æ.l Hv£Äg^¬•Ø3š¬µÕÃS˜Íïgٞͽ@\ ýCÒÆå…°ÅjpëÃAQ[îÅ݆¦¥˜Í·Ž®#˜“Ú‚£ÊÞ®í>á\+©›=˜”íÔÈÖâjï=š65wŪ/q•I¾à`«Ø Ö+*“É”hòÌ®Ò=¬7±¯$:°sÏ>JŸgM´+j/fò¡„ï>À†õËœc1¨ª}@˜{D;f2ocZ¯)ÅiŒPºK×*52uÑuáwcÙZm^«õ;«›@«ð¦À4]9–®ÊUíX zšˆ[yåœnN±Pm SGz»Y]¹:º¬=×t=&ßõªV¯*Øü•<{LÐÉÏ®S½ÁtóÉ0´³ÈýêSÞ«½”‡ÀÕïȳåu!S Ø.¸ËÌ£(ŽÎ¼¶¯Ÿ mÄÇÖ© C5mZ î›yCtç³yÎ4J•Õjðó¾ÙcËUÍ'Dãè9Ù›¼ðžO½¨&¢µFãÚv+¦XdáD6–ê=n¯¾úðå°³½ÛÖ6â8]9¨äα[Ä U¿eÞÆ1n±ë]JÚĦÃËz×' «Ì·;€®xð½n®^ÆÕÔ¡J¤¨8Ôwܪó¥Fµk/b¤±Ýp‚êRC•Ûæã¨¨´²È M"'û²ö”›|©eôº}€±N€6RÅxht®¤mó í‹lóÓÌB¦^ÞÌø^Ö¦†5«;¡äc©èÐb Â,%&ÆîúãÑf-¹×¥ Áe­I¡¸âaÁI7£sê²Æc¬¾ºæÒ“F‡ÞkeH×Þ­[»Ú­×zng2¨Ù è+¯]ÐÓ¾Þ¢=ê6 ŠÎë•9Zƹ^@$=&• $Ö›ß{t:×oÂÕà¥}Û±ñêS“©=‹½™põûÔ&Ú ùO´ôsÖ}ÐÑÌÚŠçu:µÄe@!óÍ’ð"ü5÷ÝÔ­+„x™¼bÞãV6îÃÉuDi>³WºU :õΑfpÁ›¹%íÓNl7G:ÖõI±‹B}M(å“^•—+ݬkBÃB´ú£´^Ó˹ ¤Ø©mȾÎÔîf”:—$‚ÓR›gqÛƉ]Q ƒÏäì7;nÎìï%adÖŠÀ…ձΧ:tËâ·´®–Õ•{NAu‹0{ÝVNÔ½ÕÀhïZ0óó¤3Ù®ÎÜ ±tª=ó›$¥ÆR¾â»·¦Ö˜.IH­C n´eðT߀»Ñ¡uq‹ˆPÑçR¥bg]õ⥀ïúè5›ÑY²´MîážÌ:'`÷w°Çâ¼l %¯ãŽY[t®’ËV;Ð/¯ïKw‰æì®6wÐɵºq2Ÿ­»‚汋]à¡i:]•6ÙêS_µw ÷›~Õ~ì†gÎiŸw—)¹@†Å?YF º óŒÓµHáëuWnÅ¥ †ÂµÝÌŸSÜ“{5¸Ñ΀Ž|¥q¶…—ˆ%e­£eàåL²›îÞæÌìœFVRç–Ù¨ÖèHqa«ùÒN°ÞÞR{iTËìÇÆD§–½ oÒû®ÌÜz{[ÍØ–ÇÕa›ÛÍVhf*—W\rè`Øÿ^œ¡ÉÌY¾•вée7µè)¼•h{×Ñ —°Az¸í#\RjãêUÊÇž—(Ç–{®}œ-€³D^êã]ÁV¾kØÚNõir‚·]fó_$à €âܬ›Â{©éXŽSÎëWª£ÍÇJ´÷fšÁœ™£®,=Sv¯-Æïy³Jž9ØêIÕÒ‰ÊxØUN6'.eeùTfé‹à·ÆÝ¹/k€€åª>Ü âŠW¹ɲ}=öVåÔ^}›Ññkij¤nåÍgÞ±¬fÜZY9È…=“ln¾{h°J|Ѝn±ç7 ÷]Ú]îpòÛŸ¿W«ÁÍ~}Áœê, gÊ>G¤zY t>«¾Ñ~§”4ÅÒ$sÓÍJpqêAUÌìöïdZQ¼ó;Ã~ ¦i 9~Y\ðæêîÐd$1{bÌas=Ï{O_=­1j² N¤±¾¥N ˆÔî³*zh›»’×c˜'4ÁÊñzýÃGWzìè#¼»ÊO@q°±]¦ùܨŒ@TAžÅÎö—Ù—šé•¡râÕïTÐqž®ŽæÆê×^};lw4L<}ÓhеaQ¦sº,±n£çWt®øÜÌêæîK°›6­í^ŠéÐèŒ,‰c;)Þu@"Kk6hí;œâ¡Æã‘+càa–iê¯LtﺧÄo°­ë>³hâš¡ «ƒ­J~†*BØî&_½–·2Rák,_ëÆéßïÀhíOæ9ÞJØ×£­ëH3‰–ftö¥Ìd5‘ìÞ iW*†½W/žþ¼›ÖžÃÛí§ÍtÕÊ÷oCJ ¡Ý¸]Oß–ù]z¸.´FS-ÓàF O~µÛ›Õ½ÞÐæ_P(3£g^¶‘‰)·nÁsv¶²¸P½S=ô;Þܲ!t½=‡5«»*Ë…Ä[NPµmN¦6Cí¸¶FtêË€á $¾5jÓ`2…J ÎUb2ª*b2ŨNĤ1îK”ô3×,è ú®ÒÓ@ž%ØÚöÒ¶½¬a=„t.ÉÍÕMzÚÐÍÂ’é™j¹ìJ£Øyð6ÃÓÙæ¼/x/^#µ•nvl;X¶*ïo€u_PyGÚ¶™Ãj¬4ø<ÑÇÚ˜Ž©˜lˆ6èºÀ¦m1t&bsUDžßÉkêÀñ³‹0÷-‡>Æ0uGº«jÀ$Õñ°.“€v²³³ð[Š,jžÕe»Tï{ÆÚ!BâöÂ’×~êŸ ÚæìWÙØél >À6è¾Ë»}©5êé2ý\¸êõ][ŽQ+…ð®j…lîéFmôÌÛÙ¯}À9Yfm+«\'›Û¾uN솳†]4¬¡½CW³\Ÿáçjüûä7øŽí+ýˆ­Ÿ"½fïú]5Ô,:Lg[`½Ôƒ…-ÌB «´ëlª‡5ŒçÖ¢Ege)7Jk›ûÎÅ6ÿuöÙù§Ùä¹° v¶ò´`Ž }5T®dÇ—ºJ{v©³YGÒGîx¯3Ãún]^NÂ’øµËMù·m76][o…̓x{=Ft&Õ')FS«XúåË®1m's 1½Ô7ã©öFö'¹¤ò¶éTK­Êºc»wqyÝÕ¬®4^=5r»Y y‘¸o0ø>ÈÇ·¾Ú=†ôú‘ÚU}^;³ÉQÑ X>rë·´/èÙíx…_}zÌ×b„èÍÜ@Ý#‰!þ¨]yƒ5ï¨â®Á·èõå|Þ|•‹ìƒG+€>ŒŒWã䟪o5•ƒÝ§³&ˆÍ(^,ŽÄ¬ÄuÕ2àæqÈÝB¾–ÜÊÅ›0“yðî·s‘=ѺÞ1H ¢'V3+#ÝÜО¾®ÚyfÖPY×¥Ð\cBë8•4RÚÌæ€#'NÁ¼äð˜VÎï<×>ç•}Aæ!ž¦JÂc¿5)r½[‰ðÖTáZIÔéâ`]Izþ 7N(4Œb¤÷½ÝMxgy¯q½½åÁC0nÞdˆ´l¡£TE+®F±+È¥º9%£¯;;Ch,Xa!]µCé˜Æý¼œÌ›û÷žþÔ€vå¢A²wòx¥F drÚÍC~BŽPŸÃœž-w}X«iï1Fh®dæcÃg:û¶âÖ«O–,®èé&ë4Õê¾`p*ôgg;›¾dkO{‘ÎðûKO¥†ÎÝ‚¶ÖNTdÇ8¼£¸Ä­çOi|9’—/xÇöÃI`í¼çÝ&6plu´•E4A«IWÖé齫“iëix²½‹Ç¬´ËÎ6eÖùÞlIႃ«[En‡7¬Ý…º—öÐŽòeS„×Læ‡[¾mej\qÇɶºžs8kC{¥Pž÷¯1¼4|³°<ž‚‘‡‡qöøƒ äMK‘ ™h¿u¿«®Y‚_hÚ· ­d,]½žì·dßMžÃ]ìo¶]Ì\z¤oÐUÃ7¹K×R§OxyÙ.Ø,àåu(céb¬’1 3µ¶Fá=@Xtà§RÌœøtì^j6ç "NÔjúÅçLuÖ·¬5p½[Û+[À/šJ*Œºw [e>J²hçî-{%ù\[ö¯jêÀy`ÍÇs©-ºrÅÙÝ„ÌCôÚÝ¥½MAS5p,\û{2¦8«»šTì«"ò·;'›s­õìÎ÷½îIÓy¶ÆmÅ|Ý©œî|¯ºÍ{&^M}-S ŒÌ¤¹* 9gÕŽ¬•}1aѸ(Í_:Ô/Øq÷²ëÁöø6xè 8j×»Ô{ybwš=Xdr§ïeYÏmyɦòžì½ºC9JŒ aFUT4Ïž@ö‹]Ðp gË›`‘å¦ñ{ ˜)aX ®ÜܵŒ6%móS¬¥YžñÕS³WyTy¸•Š;B–SÝšZãõÖï_2’²‘…=}ÚוŽ_ªÑñ‰"•îû»…3æ¸Ý7tpVš•x¨¬Rùb™7Îu5ÚϽVºTAžµ^«:eÂîÛ]Õï¢ÐÍŽzº}p]4Ɖ ;Wt¸SßO^™ÞÚÓwé/móÖL§Ø’[+«H‚»W|']É]b$q´×_•&ÔöÞÕÐ1uâÒ­,Ró"ß]Ñ#·¥J™NwÇ:86fní¥)pÈ?‡uÞ3›Hö¶Ó|€uÁW<ã×Å)¡†¬®vmsb—Ÿ²[ްŸëÙ•±nדå¦Yút¯Gë}Ü%vÄ«›Ù–ø*7Y·•»©—…ë>²•1-ؽ¡I*ý»ƒŠ '«ÆóÀânjÎ+–Õå4¨¢6û°NÌç@,櫚Æ('õãVòò¯Î=#|1òäÝÃ^¿ì–Pö­Lß&Ô´”·Rþž ܵ]•¸©cüüµ¾ó49=ÊžŽÏš<ØÞ¬H¤<=Ö$~Eµ*f²öûfýÔ£‰ûà<]önކn•^Mph•@âkQ|˜Þ·L_‡¼™ažÕšïŽSÁÝDÐÁ¤>nƒ:÷ÖÝÎç3Þ#ÖCžD”²ôo.ì›qÏ’j™ÃÏ".éý{ڞ }ÛŽzJ!v7mÁçGa®–ª+À󷻬•jÓêHV^ÔA\é)X%Æ8ÅiÐgT$C‘ïÛæóJ±gÊr£«=Êðüo»0  ãª:±?bž< 5£¥G•ÒZµÕä³ éC¨—s þK #ƒÙêÞ“T´6Ù[Ú;ŒhÌñãYN™€­´îVw'Sº]ºCãìÜíôì¾Öžö+чm]¶5€÷LûE pO^JÌMIh%`gÁ¤°Š—JWvDÓÔ¸zŠb¯W\µ¦­Þr×J°BaBŠLfVî$ŒÂ¥ DY¼sƒØž4ÝÖ9°Š‹kFŠb×Vˆ ì6!MŠ{eõ¤.eÑ÷¥K¿ W ¤Á¾Ý£TŽ[ðú+¶ûvE5•z R×EŒÒšÐ`ÂÅ\sÕ¨[®o ÚëurÔãTPÇ¡¿˜ž,VÔÏRù©tzïÎ1]•o®ö·èŠÌÚ4ìÛ¸kŸíµ¸oè$Á”§Ò¨‹}¯mfÙ§•,eí¿G”ÁìVÞNÀ„”Ó ¨ÉâÇg!æ/YN^©•­BÊtûm«Czs›ê Ô—/`ßmàâ §èÓÝ=€ü€N±À¬«ç3bºðh®i*}G¹õÜLuØà¾Èªµ Œ¨'=N¨ÙµêÆš±Yzm*–УK0ôììÐfxsÅîgp¤wPò BÕÏNsÚæ;VE¯;´«ÝiƒÙW“P1ûٜЋPJ‘ œ÷‹õ¡)ÕÕ}Y…ŒåyÆn:ÖEÔ¦µ-¥5M³Ü³´V’ Û ø¨îò¡¬€N{DtByé3=º”äm"}\õwVæµOqW¦ÑsÊáâ"yºz¶»T‘ùùqÍÒè+„ñ;ŸkwCÙž|Â=H‚±æß¶{ÉSñÝ^VT‰åû">µÕ2œxAœÔ;^|!³$\Ua¼bº‰|:èÍˆÄ CO!šigvVw}™…‹9p5¦·OmµYZ 2ÅsT5ªBÁŽî6ÝíIy¸þõ¯ÑÃ^+gfOj•²õÛç£uÊ;qgÝLü.%â«”w¬kœRWšuƒÓk’Å:ß5¬=uãÍXœ° Ë…\5×ZÂ"%R^7•ÀVd[}f‰Ùëñf]ôy9ÔåW®Q-¢Þì©W^ÞxV#â6üȼI‰Õ}ÖÛµGu¶Z½­BÍÑžŒœ-Bdpí—BÍmj‰›hßޱ/(mGM"kçÑMÜŽvfê«%öhžJxNô†Û5¼˜À±!¨ygH38¾ÁïYt˜«v=åÈ+ÞÕ¯6+2<3¶ß­Í}HàÎ#ny õ §–ÌkÀl¹ô€ë&á¡fêÍ\¾´¸|@ìÐc‡ÁXÕêãø«´¨ßY•¨aºßS~6šêæž¹:¤²x2ë‡G¹æf†l 7×»WJÓyÉtú†îtËçÒ|-µzí¬á¤zžÅqÂý!ÕD}ÅæFŽÃ„6ž]ï3wØÏv"l•V˜믫yn£|{\î½ Ÿ»µ‹õCx=9TÌñî°I´î~×À•ûÙYÂìoU–öåKõ]ÛÓŽñ’ð’ç½rx2f{OZI{Ô¤@ÍךdÊ—¥];¯2̈øQËоYX‚»'/dÚ¸Ä%ÔÈ_ ñB3Bj!Ùèr±—OÖk8bånî4÷Ήö7¥'#¥L+s¤¤†xhãè õnÁ€{ÝÊj¹ ‹Úg*BèùrĘsÓg „'ô[¹F§ ò¯[ƒ˜íµZä¼êñCOuGö¯x}‰ò|èêÛ¥¯^¿ ÈTw½mô}åpBËô¬Ñz$¯e?·jÝÖ,÷Yãiü:¶ûb#Å0(Ç‚áº<©­U¡al¨‹Ã~¤…Žô惪]Öê 0Ü7΋¼¢@·žÌ?g‰qqî´µk¬À ©HÞ4e]õ €çs¢™ÅN°âÅ-SUnœÞòŸó¬Å׎ ¤é¼8x-è­¹˜ºåzØ > ø\s\¼®‡žT +Bò¬æ£Y5ÛTi®³N® ˜§€x{xúo¡<×%KŠÁO®¥cñRØŽôY^1n}ìÃãC»$ĦÝÉ6r°èï:¤‘t´8ËÛU4뵋…ojÈÅGm5™ê$ì½[Ó »dšjlƒÃ:8ðÑ×ܲ¿£|õftÎö~MÌK‹ËÉׯ{/mV½¾4¹…m2L$|€6m–D EiX YÉjÇØ+±Ýs¼OyN™g„kÑw<—¯ÐšŠé^F‚ͼÛB49<:úñð?¯éc)Ù/ŸdÚ½¼]ƒŸtZE°>ðêbŠdvûÒf{k]Š}9Æz²q4i]Úýð¯RF¯ ØXºéj×zî0æîö …ÖJ•ïƒe'+Ýà±çy`5jëlÓ딵…á\éúÇSÊÞh+fþ¾¿™^Øöyì>ξèVX¥®cÍÄ/¨¬õk°lCÜòûh«ìÞ¼~¥ã:¹6“+PhïÚ‘½Þ¬jfTéÝ™0;¬ï°õãæÇ§}§Ýuwl;;RÛÖÑàŠ£xÈ[Ó³wˆ¦^©Âõœ3»ŠT5ãN!dƒ}Qöfh“‰¬ví,À®²ò‡q.íaær¸sFôžµ´†Ìõ篲XÆ®Ö=8(B¹ËGW/€×mdzÛ»Yu“<Áä…»Þ–+—eÖ=xiÓ©B9 ;¥ŽúÄ‚i\Îôœd&Qy,í@@ß1wBš¤÷eËÊ 6±V°oI¿g»±–]wCN®Ù…JFæ;Í=7Exw½·Šës­ŒeS'}¯A ¯až1¼[A1?Eå×úÿ ×®ãïW4×v®|$ñyæC»C‘Ct÷ð£‚órx|¹÷!ÏSâ·–å_ §®Rúe ÖÆ›î `š;S:W]=›>®ˆŸkÕ ë‘RÔ‘Ê*u=Ô´UühûÔêëÛyµ c.?–ir­d„Ÿ®4®”Ç¡caó(•·Ÿg2O­°½ŒõšÞåÔíç‡*í®O|û3‡yÃ} pöjüö²váµÐ„ÒçZfdTî´æZö•§°~ñ±rle€yTT Öv[n ¾ëçÕµëÎwëñ´2L6¯v³Ù˜_*¾Ù: 3J2»z#€g/ XlrÐVw}ž­q§¶Þ rÝ=ò`6†=6t½T ë¥p9ÖjÐZB£*î®®ëf=LÞ>Õè<:”B=öï^V»C¨c¡ WZO£Ê²’ß5®¬ªe`õ)Þ÷r˜ÞÙÏz®¡g†*vjÓåÍœûN¢èØ@/ M¶«%Í®$‡5zªµ–ïŠð¬dÝžåVëUß&÷ØHºÕزDå#´áêγ¼žììß1¶š®•Öç†år¬[½îã^‹’5ä1 …{1L5íØŽ9KŽ=4†¸éÄç?>ÝÛ…ÄÝØ­'Á2ÆZ•iÔÜX¡SBųè¾1og ¦sN˜ôd3-W`‰iwÔgH±‰ZÉiêóv* ÒÑ;|˜òìu3»8¬}¿hPÛov{³±wn`OºA€ p¦v’ G¢©m&åàÞ…³w¸¥GwC‚]©Ï3¶³ò|O,.Ø›¿sט¤"…&±±·†éfl_=µ“B·`C±!‘Ö*³]våyrÏG1MΜM_)xê=° Kžó~ÊQ«ÏvÅóÉwgf·ëcµJyA1\ðæ]½K†pg¥ðÝ…íõ¦tˆWgw[¹RÂ^}Ù<ª›¥Òøîæ}­‰qÁw꛾µKz¦ÊhòËzXC2ù]*o6GìTãÛ[±€8OAfí<Èh­ì”,pÔè/r–kvyiò™é\/¦•ôÁ×e_†Hå{1­‡-ÐÙ¦­ÙÍÖ¡é°*¼I˜S –—Üðve×>«›HZèv®¥ ãÛ/è[­ldÝY¥G¢?;ÇÈ)•Û2öìF"koQøé®õM¿7W®¸nW:>Ãî$µªóòІ“åz4Å_«3­ÁJ€5Û*öàÓ±½kã¶xÖÂÕ#*Të×´«Ò³µ^¤|¬ô”³„&‡Zc« ¯Pk½Íï£E=KB*¹åۺׅxÔ´‡~ cÜ*·-åsAVãºÙôÇÚ%.˜*RH³Õaí$zŠ]‹áeV’ÕZ¦õâëC‘¥2daiÖONòì°÷SwAÓu­t‹ÞɦGxŽ@žE‡×òÛìÍŒJV•7²Õ7éy×wuáìie£å$‘`ÉhŸsêßZ³•Cϵ©¼yxË+Òæ´û’÷8XCµì®E‚§†zS·S¡±m¨}^ Ýv¬oyÄôe]B‘œè¶Î-©ÐÉT Þåpvr¹Qé½kÌ%ßcõK®YuVÓÝÏX+@<ÑYÔ>á2•^™º~®¤)qŠÊoxÞ§6S¾asëW{CžÕÝ÷_Êøw>uØÚ›¨bÙX­†ÁòÌ©ƒh×·±R8 zmìY*Ü R¿r#xw]•—I}½ÌéÎÒÛvèÍzëÄ °_QïXv¥`Úb;:Ç+®Ù¹¼'›‚Œa›ÇcBÐŒ;[½CM×Crtî·ȉY·„w›ë'Évמ¹äÝM¹:Ìsf²>ËÕaè;±±töTÞ–Ø8å“ìÊ–³6‘öñåŒV¡ƒÖË&`‰¬¡OÊúYI-ñ5{¹“É$7Éåƒ2-ç•g§ŸI.ešº]¢Õuƨ%/wäF¶žr³”]]@³iæí}—X0·ÖnèÊF×LÑÏ™€2=bqܾO5 DÔ½xêG+ì³kx|÷ŠËFw—vñÚ“¹Â÷6bLw§©òÌк»¼¬N)f4M‰qÅ]/¼_g ôk^³SɯzJ}¢ùÚ¥Û±sKÏØ½ Yn鶈R‡£Q"Á`˜;‚P³¦ ¸1ÏGá{7Þ,,¥½¦Åš19r,F·k­L8"ÃÍ*µ]]”W7×´Éô+ÞöçÞ\ƒrË6êÁhQw³yÛF8³0LãwYìõ÷(§Ó‹›Ñ5ã·—ÈÇ[6êv‚¯å×uÔå2·Nœi¤òíè '¡3ú^÷—¨¿iMùz•—¶—/mZº÷¨Ý* Ä7%ÔÍ/²“¥¦ê¾Zš¤ŒaÙ£Š­¨òF«¸K,ݾë;ÔIÎ;TÈǹ¸MT’­½P¤,2¨ŠÉ]å;{‰3]ëxè-ò¬bëê²£na‡>œêV°'¶ <9tRÞ•ˆ&3{Š *ÊŠö‘ï ¥ ·jÛ÷« ïuú¯;ß9 ž{O7µr¶ûvlP¹ÞõлC»+1Ëõ½"öW]'%ù}|“ ò™¯.Ì G­÷NHe¾›‡x€îƒ–ÂEè•´z¹6´‘‘Ãê#ÌÔJãÄ$®›tBsϳ¨Õȼ÷o´Œ3ܤä;C”gê›&_»p(S\^ØËîÍ¡ÙÒér’céÓ/ûÏ|BXÍlÉ ;Ð\ž ^ûH‚O½R0¶Ð&ˆH-õ(GRÌ­ î]2\”òE³A–µvm²ž Bµ]û¿ÑvãÑæ©‰…Œ)|wJÌòƒ³kf\•”ºTb²mBDþ`ƒÝ¾v°Zû=&“&k)¹·6ó†óEÃoJû)7,jܬ% ,%²jÐέ*ùôêW[W«‰›« 1´[w‚®ÍÞkCö©ë]Y]”³R¢Âkç^˶˜$l]âÊnŒ)ë+Ú ü`Ê€t{ïjËÃɘñAµÞ‰r;N“Îy^ñõb…âT5ôšol/`0è§6ô@·›êš†ZÚyγ0ÐÝ tëMÓU3ÈB/†¼uÞy+Æf\?c>\2~MrÔ³DðîEFÛX†â­#–]b›)ë}]W.IØÕ³&_– åëv"çF±+á #M|K¼èë·%ÎíÞ¯´]H¬N92À¸êFÒÝ:ꔽãÕCO 'eÍ™B½P/3H59Ïx¼’¯ÄõœÙ³âêÖå-¦×fK¨+jóEw0Š›|íÉá\´ »Ïåw´ÜÌþ@•63´O-¨P¸–•˜M*?³›áø×¶­ô¢{ÚÑ3.o’{Ìtúa3,nm4É™r¬¬Ùh^l­7d|¯€Û­È\°Pw7'Íc™¥áÚ‰–OY Ó1wV˜GXTÏ»v>μ1îõìCUY-HÂ›ØæQA°WePG €-É{åì]^òðc}3“ß©+Ξ¼¾qTÑÚÆþÊ%ì§µx“¥–[Ù»„nB¨Ý׌mzܳzû01÷îyÇ¿vúéeëÅ´‹iâvkU$ !݉æq¶ø`‰c™{ÓOa‚ Sp>¼ÛÊ™¸ŠäZú{¢Fç½Þ†òîÝ—w3aµ~÷”ÉYG«˜€/!V†Á^ºë|uøW ¯R¬F¸PÝNmÍÝJfQKÞ’j½iZUOÃ}—ÛÌåîb·ÑÕÝt¬; °²è13ÝÙ¼zKجI¿š§Õ¦éÙ°üõÝ“ÐC¤Õß—·9æYwrõo‹Óa*6Do®è›ÜwnÒ:"§×¼¯ŸecÝîöÈ:躿s%ÙÞ^JxLÄßk+;»6Yë˜\ITÍK&Jüåí7ëÚôžåÄÜàŽ]1ìR°ZZ“{&?gŸ°Q] {ѹÞo dömßXx¥•.·0_ 6 á JõÄ<÷·¨¿a®ÊÃf@k¹$VÛàd›L¢é>(bnÚ‚¯w%Ö+·½j®¸iÍeë¯g9ZÁ¶y±;¥;Ðë¤/¥¾ç@ðJK^/CËÕáÚ;=Ö½©ZöÔ ø¥Ú»ße“#Å’êXqLõz°cÂdÙëU,)+Èè”ûp;a³á¹^ëÖŽ2Þ¨\êÊäï,- nò£§b•a«¦:àT§]Óî’²Xhñš`*:l»]&áâ(hï ç–«ÜVcëÐ)J}²Ý:³îž×ÙO¶òVÔ(6Ér¶í+w)”Ù» (íÞ¸ ‘‘VÉY u›Ø³(V( ŽÄ·³­UŒU`úVö`¤=© Ó£-ù™¾ó®Ÿc©ÓW9Ï%{½QUÅ¢úu÷+ UÜJ3C'eŽÀ›ï::X¾:Õu';x<©h·tèã°t°Žkìf÷‚Õð„Ê*Ç‘¶7·:-;àæâ²üåûROÙîH¼8—Ÿ…L|%fk—Ï¥:àè`(9ÉV‹5kyD÷HÜ/yê¿©c\{Ñ,¶‹‘t¸²sPj·HèÜÙ$º57çVórÇṯDA#Aöl…d–Ì{Š"ÝŸ¾ûï‡í3²ÐYâýËy)zú°@k·é5fEážgïqÍ”æÈßV.¶¯ÔW_‡eô…ü1‰»©{7kåC^]9í0»Íg¹xxzÐðôßV;T)93§J™Ów•ó“4!`ÆKÕËW÷%6Û“ªp7Œè[´û’î¬ÀóVýRE‡Ê‘mQ7´-µ›6„Í:‡taÚ¹:, ºj‚óDÍL A¤r˜ÌÓMA!w‹j&ªÙމÂ죻Œtv,·Ûc 먲…Üfè®ÑÜúuØ;‰¬òSyv–w§oÅÚíÞ³Þ¤º7ˆŒ~Î1Œr^K¿Lž±ÇÀøNÞî¨ý¥^a/Úû#™ÒåžLîµWìMiÃ-™hÛb9ís+9W<ìÞÑ[Ø­¬'ulçóX~Ä]n%ӸꙗH÷hóÛ=YÕ~—;B”nkWª0ŽYƒ©ü™Û¬T!á³áR.÷z¶OO¶¼Æ¾j­m»R‡¾UëW®úÚ‹ÕV„ŽÑ+·E¯rËW­«½ê fô¥NÙì&1Žxe^©|¶!pq­7‡ä˜qFW»¾ÃvÆ%z1 9qõÞòq§wcê9S‰g€Ýˆ>½âiÏ^=ˆûàŽA7g^÷röÞ¨ŸO%Îu\ãµwVvWc³A¤dK4óo)åÈ×ëe?ŒG§p8òìñPJR¼¬øo‰¶•¿QVнÆÂ—RH"µêl¨²´å.ÛQuî6û‘Û¾S û¦ËõßrAª5CZWåžá›‘òŠØPMêÁ¸™-Zë4Á¸n…Zë¥÷™Q½´ðIO ÃÔ£™®^ë¾ÐV"o>ß•áïUý×êmó¢4<´ÓÞš"êjÑV*S}uˆåÁ[ìÖ‡vTôiì˵ˆKC]l¼Ê¹uœ^ÒÕ]bÅ/­|¸q.œØÞLq‡5Ýc·IÓPІ׆[çÓ¡ :g‡ÐT+;_yÞŠjë3×x"[t+jê•!¡ÔYÔ¸§-Íu*xåcYŠ]„J†p—ÜŽ˜–G³äé‘Þ{5«fMƒ‡Ü‡×8«C1˜\´OAGr˵¡7uWZT¸…¤Š cÎúv.¦Á¼¡ÍW3Ùvô ó 84u‡5ý¼x¬ò:žØõæXÝ÷{:×hž‚N“Ï× ÞñNãx9ïQ“72ÖvÅW-9Ìûjy4ûhõó3½ƒ¸cöººÇZ{w#=ÌYŒµ7®Õ±çÛY¹ç‰Ý"›ÁÛ\ ítm¶©áÙ×`9ÏâË`M.fÊ3¾Êј*0"ÕÏs~|Œ¾„`F· ¬ì®ÃL bÉ?mˆ¬4¼.‰EXyËZ Û°Ž1ŸLëÚ·ÐÊèã×z@æ“Ck¡BíGH…Mäì^›{u9H;d¿d­/¼›b‹÷f ÖUÐÙµoßbÞZÜ­„<Ê@Ó™T&Õ ‘Ž-átO‰á=.ÌÊ‹ R¹®N¾"0ëYMÉÜÄ í+æ Š¦µfû Ö¹m«x œ½eæ?hD|m8õóÃ{fo«ùЛ;ÍÇA²†_œöÚ;Òuø.{ÞŠ®Åy¡4XÉN) àxÈ'C¢Âpœ«µ®és.ÂÚíÇ '0 K"§±Þìµ{:V”U|/…ž49,G`QÒ7)] ¶ðµWÏ‚Ž©»™[À9ÙrÁ¨ð<ó/qlí­ê½ÁÙË9÷>V»˜™÷yÊ~rgs¬óÄž(Ûc`­“ÆÊ\›³s³ ĽØÏ ·´kžµå™b=æ«Ï¯3X’S;M¢w½J§9<ô>F(G¶?sQ]˼´±l@¶’}>‹^në'-å"åä– î·lGÊ9¢¸Ûg77n‰ÚV[}£ÕaK «tÝ0eí]COY€³žtK&ÕÙîçÛÊ™®Þ$ÑSŠmð»çB]×fcêÒ†vøàºcB š'x.ØZŽcÃíx°gwÞâÝ6|a;F¹qq¦"U«_a¡Û%ŽŒªoÙÚâð- ï# *V…]ŽQ[1¤ìZÏyW‰WK\Uá=ÞÂz·h|9ð˜[eƇk«{jldwâ ný=Ï6Q÷V_§¼yijÓ>zEvÜAŽÆ[vËzëf®w>êû‡+Z·'giò§â»|^ú„wLÍ{|Â=+YÎèÌ·ÛQ¨‹]Ìvšíâ]³³2–ê{~u·Ù.}ˆGç~½È¯ÅZÖF6 ÌmížB pý댮»—‘>uíí>ì|nŸI2»f}Ý’­Y«!³Žï:ÆJEóOkp]ÉYÖÝ+0ä0v‡MPÓ«)qJÜcs:g&¨×û²¶u*I¼×,o´D,Hdì²Î(qsrŽ÷&\˜–j+%)è=±S=×:ºëFoصvÈ”æü7;½®2zLÈÑËÉáJLͺ°Õj£uÏ­Þze]]âxaÖæÎKDÇïVZëÞlh{<‚Þ½`‹Ù†ô€N§œv‡V£0ïgIÝÖ¦Ê<ì"F¼Ú>r<~> Ò ¢ôzx«¥ÂËÙ÷ß}ò¹Æq`a¾v]ãXç¬6#ðºÝ#Gëäéݧsµv´°üÕpá5Õ‹H ä›C^+ Me¤@4ÙâîÙ×R…„¶âÚrå!»µØw,nQ«$ T¤:ìYë ¹l`W®$È4osCÏ–ëÞ §¶1ÖT]|$8·€ŠÈB”’ä"ÐÓ*jN|¤Ë¶€ÇCJÓ¤‡)»° ©Ñ–0g[¡å”¡›ÔPAÝe,²J`ÉöÑ*+ÀËz­V ‰:½Àš Ayªí Ű:2£´m±[ZhQ…æpm †dÊѹycíÄÃËÀ–id§bÕàš– ŒÙ.¼N–GT[QN÷{¥C×ËJ>ÞÌ„Ú-3~<î²[¾võÍ«s5á¥K›e%Q:ììë¥ÝY¹>RNW™&’¥vÀÊÁλt‰„,ÇŒ®Ó`57\Š3;ô[¹§d¥·íˆ-÷Sí¢†+sag1>§k«ê¾V8Œx„™ZæŒ6ïT\ÍaÓ¹C:2¹¡SÛ×Z6Ó×Ì`o6­îSC25k+„_ƒ£zfVó”w3 4'¥nM½}¹¾B˨IorÌf®Ü`ã#siç@çZ¹G%ÕÃÕ{ÃNðkçU¢sgàî´z³Û’­º¼—€s{!Ðk]{Ó“žž¡ïlÜö÷L‹€wÛJ¥ÛuÛÑ·Pv ™›X-©}ÔªÂôÁ5N¦1*Ý™`Ö59©}Åž7†ò1‡vœU“Ö4, :u+»GÝyŽý›îš•šròcî¨mÕÖå¹Zö¥û9”–Âûµ á{sÁîÚ»Æ4Š^îĉó•>—žû<µœµÒðož/wÎÍs>å9íðË–•|q:lW+ÔÖ­Mò0FŽ'”’ÂÙÀÓ„ªu®ã}gU'I²®§ÎÒ»)ÞeÓ•˜–áC‡¬Tò¼àn¬ò[KG–XW^õãLÂóÛÜ©‹6YèÏ_s°ûFØžj>t³^LM×¢–]ëXïŽV÷0»¥Ú«)Ü]cL–¯ P.¶)¦Ÿ»~4§Q¬¾æ¾Ë(Åݶ{ÝiQwöiÜ“^èz<µX­ Gm{ŒÉKm«Á•Ûíµeû»ÚNëUaPc'ºC}0Õó¤nn)nÍØVéFh[JdZÝî2‚™íå§<$R| ³Ø«ß­ñ¼AÓ}KYÐÅÎirîÖz.€3;%fKÉÀõiø –×aušUçíjââjÅEË8Òúe[å§aäôŠ,çÙ„ViÞ +sÞó-Ö¾Â:æƒYƒ7Ço53z­œã©…³_Q Qs‰¦ßjå Ù(åF㦴bÙÉr¹“mÁ ô”Í÷³wت5[ÄÒ¨ré7êqC¥ÕïNXÖš»Ë©†­c/(ÞØ½_Í‹Û4W”Ÿ/ÕÚ’On¬ü†娍Ö·1­Šžwí}ï.µSļSží°³yì‹•:£hZ®&SibÅÊ 84bÒ÷`/Ú»sªÏˆµˆç±«×·rt˜òëõ_y.ÕžK^Ä^EÝ(ÎÑ#““èwT— t{8Ô5£-œ†à[B•¡{‰ ¥q#)µÌSø'Ò›ÕŒ•Ü´9`ã¢RžÛ1ôæ#­©µ+ ¬ONʇ^_G ÙhGׯ\ô½<Âì ãä.eNã'z‚Û({½ö¾ô¾ÎÚõªÄ ˜Ô(^Ó†›š-,оìî¥5.¥Ð‰Xˆ-RÛÎ YÊÂn„ùÚ«yòÏcš;9àA нWO^BH´C@të¨,?bDW‡UñˆÖMö½B&®,ý’ÖûOJnÀ§¹ßXÕ\6lÁ}DæŽÍäŒM›Qïo¹’»|“UÛŸó„×1™ CeçWk]϶ЇuK†”Í‚åÚ+líDÐæw ¨j ¦âéÔìõßW_['ˆHX¾²\V®7Ø…>òÞÞ—¬L o ·–ößÜ9õìÑ]3Ù·7¨×0mŽÚ±pà¶Z%ÛÌËwevfÜÙôpN¢/µÐgÎôJë‰M;δ­Õ±{Ë00…!ç/*—O »¯˜)¤=iÒaÖm-ËÍîÊ‚úÏŠÝ xÔá7=áÏžø.Ú½õ/O?oVXIŒÝ8¼Ÿ›«|GFHV{ÖùZÒÆU×§k®XX9w)ý½{“ÀgfË ÅM9ÏêfÚ8Fq5ØG=¤§K‰RÃÕ¶³TcA«GOEŒ*Úí8¤›Éwã—‹°j¯¡­ç ¹w†p­ë™ŒŠ µð‘kÕÐ.qiì¡ Ê ›Úù˜úîZq,¾bšˆ tPN›M[†Ï6’Êå»hMidŠŸ^‡òãùØÊïf_¥GÝJý–î)y`¶t*ЦMÞã^ö]fïŸ;ÑJt¨Š”Ø\Ö$tRó×'²¼–ÔÛçé[R;Þݽ©  Ë«±ÞT8§¼ø“û^‡y Vu,Ÿ:k¦T³mqöàEVÛÕú¥èÂTìúI‘ݾUyy`Ý홪jÖUˆè;…ݰq+5<*ïàÄü/.wy#CÃú“UŸü/aЭ“Hz UöL3I*–Í0Ñ1-ßj,d%lÅLÔKÎqg }uv;»f•€”ÎûXÅ!§/‹c|Œ¯Ôayݳ2ÁÓL$W‘¯G·cqð}—}Ó&t:œ°.RëçNù³œù:ÒÄÂû8H·/GÆÒ­á˜ý^Îðj€õ`´_ÉŠAS>²þ½®NCg/k¤ ½Æó«˜b/ÑaaûpƒîçZÚÞâõ‹=Já|-:®oŒU,d›K«¬³ô”õ·¹ -}aD@åÊ;¯Ä0k£îܽzÅåÇ ¾©uÁaiÔã’†÷Kkv÷`̯ @¾v7ì3Ü›^_A™yxùm¹ÝQà5Ù+¯¸ t žgA¡omî {Åh¬£ÔéIíâÁÕJü«U€ëëfîc3ÙZ‹h…ŠP õÞËLWu¿†÷AƒøÏ½Ô}våAçW°ôÚ…i\òÙy´3ÅÉRáH™£–ÝoÖËYðÓ^å^g¼Ž67ǃÑq)×cÚ®) ]ǯpñ«”n­½fq]SŒùŒg·yªÙºC¿EeÛv÷ƒó•g΋Ӧ^g ˜~[S«”Èí_Æ,•®íÎ}—·iŸ>~æ =Guw5tGîÂo«_£ÉÝzTwk-xܾ¡æ…éNÏJŠRûê7Úóe‰\‚jçÞʳžÄ¥Jƒ;§]5|Ç5ðÊ2 àõµó‹_©Ð˜“ï:ú "ï3d~ÃãV]óÞ >™0 ÙRJb÷×SÅ›Õ${kîNôi›GŸŽžáïl×[ë¿tC®Åx˧ðÉÅçježKvSxL3%‚Y} èi¦U èµc2¥Š·QÃËíǹŒ«ÝE+¬Òª1î¹®œ£véRêÐ2_Ûwìh'éJ­ˆ.[™y³«Â¼ÔñXmH(ovë®L sªàbZ,›{'OíëÀ8pýʪ_7»Ø,€ShírÑ‚Ï[bÞôß\K„Û¯ f¯c­ñyŒLöÌΓ6B@Ì9ò0{ÜÎl/–¡x}·o>zçÆ= žBïXžÊêwì $î·[®ñC.³füåéÝOÝO¬×eîãëÎμd¯3‰CªñÊFÂÇsÚiÅÍVìÃΆச§``¥pP:ÌØiN¶=¬ß¢=ëWK9Ñ7 ¬.ÉxÐÚîqh¸Viw³¯®ø¤v}Kê°ëJ óνRµ•ocœ¯sÔYÙ§€ºb=€Õ í⾜gvcÜx– šêç™n™á\µ–Ðôì¢*$€¨·¦â³>=}Mèæ@–¾Ð’HU±¢\Žâ;§çV˜Lk»°!ÜŠÅͦµÂY»ëµt¼i:ò.oj–÷x×…½…ª(Ô0N–üŽzP«ò .³cMm™I;ØG‹³Ò±½éÆáæMÞ5Ç{ÚÎáƒv{ØË¼Ô¥:Ú¸“4 ÀÔfÂ^m²Q3±§f¬§ nÞl¨ñû§¢”o±{¬Ì×+dÄ5Üô]Œ}ƒ“ã&šÕ\˜Y· ©¢Ê§co{žT‚ó"uÀö‚ÐáÆ˜Ÿ7Ùá|µt”{7—è.Й{Ú¹BÖów‹¾æ'r´£TâT# Ööæé-@èö*8 7ÍT¨¤c/´=xÆ×¤ÚÊžè\ñ2?܀⼘µ‡à¥™´*?SäÉRE’ÔZ®o½S–3¼è’¤'ÝÞ¶ã>žæ¸.Û––ivnòÙH¬X1_ƒê„¾t'`ηü^ºÍ=·½Üêˤ¹)„ÔRtöŸ!-ê­xÌS(Š­ƒ.Ñឤ•»^Zf#bØÝ²|s £*êÛ\³«èóL®žÖ#Gë¯Îÿ?Ü å'ìß;Èê´%žCFfÔ³9õÂJ%…±›.e FE”nºûw*ìŒ;Ʋ¬×Bõ(´(„"ž{˜ gyF¨Øk Þ}µ+.±áÓç©<Åìñç|0²bÞ­ö¼–×[@^§Ú¨ºwjæÖ1ƒ[X+6Å׆»Î¥µsèr‰o€µòw³¨Î†íu÷r©Ü‘3.èRîìV𬭕kã\XÆ 5>y0„ÀpÛ‰ÊqÚ‡d˜\쬦ÏrãXpç¬rS»×žªó/v (œ+Ë/%M§¶~·v8O5ïqå­àÞ¬F±|={º­r1rö, “îån–êF'ÇŸ1ÚêõÔÚ²Ž¦펄­ó¼¡×š¹'èf7ah He,½B/‚wê{Ë`œïjÏUÞXÈ´‹wÕÛ4;ÑpæÏ¸•¬S”ÀÄóV˜>¸U[镚/ì7È“V‚åYL©5•F,#ek0 êwNZ–„ï5ÛÌJ>«f¸ñ+~ÓСBàe›&g¬VæªÃBrÓ7«¹Îµk6»w(ìÊŒìíû-GLuM:ðÇ•{x—Iw„ ‚Œìgø\í§h,w­WXbå+îéªÛ˜^[6š‰Pèn€ZVËÎÖ™ÚC”‰2òÅÎÍ}È^ÑâDÚq7™>/Vo%]cÇ‘»Üx-ÐÈ0%Ý›|ëp^érÇQƒxwNÐÕfçW‘ÓÖ«á:výÚ½®ÕÇÕ<}Â!÷–š—„gRÎ4Vœ½engÕdÒF'[%dc×Rã.w¥MÇ/ˆK[BpGAH±Ë É>oæ‘[/€áÇXƒVa¢2úžÒ3RÈÍeõÀ:<‘Ú¼f{kÓÎ{(W7Ý„k,zÖ÷o_œ*±ŽÇ»µš¹,—Ž#æÆôŒ’&JÚå:°ekÀ¥˜0rêúÂʸ£¹Žø·Ó¨D·Êr/…µÅVÛ¸-àîUÆú’.í#F]VtcGÉíçeôUµGf³T¥ `­+CÛ¾`P_uÞkR|µË³ÒCªXA䜣^*´ÛžÃoÂT#­¥?³ñ¯ÚÜl¬”m¡¾Æ¥w<–rèlÔ…›Scàò »„³zÈs#Õͬ¾3¢N•um¨ 7¸ˆ«‹¨#Pè®ÜçMà·½”Sî!í=VñK×8 k¢]vÝ_d®s)þȺœóÛ–ÔVÑ9OÑÎ*…½7×waSD.áÊjmÕŽ’–%.ï@‘[t¤Míô7¶#D4ÙáSE;µºp3ÎRÐøaç¡,½s–æ‚5÷EÓ½¾^¯<Èû½¨6Eæ„‚¥PE4‡„Èó¶+¾X]eÓnòWòIʽËz]ÖUw¬ûmO4êf¬t–˜î•}±“QQ§·)ÌƒÞÆ#4—~[m°(ïR¢ðnÁzË"ÝÞrŸ´óFbüÓP_ïÞHû£}rõœ'önÕ³ÕÒõâ¼ùT¬¬‚…+­E‡€ Uûçg¼ÌöC’ä{Úo³8D×ó»$ nÒÏ´€E+óy½/A®ò¹Ebô®¿T¨aH⩉TéÝ3)í”'iÆË¾ÉÜínŠöµì}YF·@íØ¼‘‚GÍRÇ9ÕÞv–Øm8=èiŠs²ë~V°ÝxPÃê´|4êø=rJ¹Cféï—\ïÒû0aéê4²)¹‘_E%ªubnDj"ÈUï6ŽT{ºø¯VÔwã‚ÉÍ¿g­:ý=ÛŠ¡¬ôµéSÛÖžŠ€Àý§o$4ïfžü:Œ¹ÙI1åÐ#z@õ#«ëâW}±$ GID7G Ün¯¯*h­ÑšÑŒì·q‘2èRwØO`fòO»ç«SV)X ïY}h“Æ“µÀåkŸrÜ šÍ ™¾<ú™Ž¸Ä¥\ÝÓ\¯ $=”áëDͤÇuÞ ¢9ݬF]ëãÀ½h=«.•MÂÃ=l샳¡Î®T™Ø#}pQÜò²u øL¤*j¿¹¢û3´f¼k„¶¤Z¸|%ñÚÎæ9ܵ'Ól ‘ë¥ÆÌfÏ.´·.› ¶ëf¤êT¦X•…¹Gg W\¾ã™9ÝÜŽŽ-Ì ÒÇ»JZ+~u$§Ë9Y52*½JÞI[Z·aí-˜Ms<â‡F+6ã¡}šzk³Ûºƒ0²q¢êQ¦èö2•ª/J‚çŠË©u÷vªk¤Z°-o"РΛ8õ›™õ¾êÛ=@J›Üš ß]-ˆö( dtÙ¢×påÌŘ.ÀtŠ9Ì'ž)­ÙzäÊܼyivÞ(ÇÓ³Vu‹ŠdË‹…)˃ì´æÊÞí4ÑÐŒ\*dÛÜv51€¼ß)+`®Ÿ(DF=Mz{SŽzôóú¿Ì¯.òfŠnßÇKxt߸ð1bŠóÝÚcz7—½oëç¡Áé ²òéæþ;›šœ7ñáAdTÝÖc®ÿwggôù|ÛßÚ®ŒŒìÉåàVL6åßÍîˆdSa+| ð0Ç&eeÐu)&ÃD˜EÁ»¼«TbQÆ„x‡nz²lÅèãÒz¼G| ¡yv-§Þ››;β@ u„+^zܨTèú²ðÚc3svëyìîÑaˆ}u*!ǘ'­©¡Å¢ðÍV[¬{˜¦¡yi«‰àxÀ4vˆ«gALLÞR¥hVõ¦hcíž—œÉb{¡¥Ú³Œ=Žlèî±:xÉEwpÎmŠçá{1 YÁ»Ú#pîµÜutjÚ²³²€6‰ÀÖÌ=‹¨î½”n.ı]³‹ic­îé‘gbÂêîL¦Œ„UˆÓãN÷Þ™ÉW©ï¥N{tŒq}o<36w¤òÊž6Ol7~Î(¡A¥– WaÎuË݋׳ÂXœj¼_<îç¬Ð"IBä4êÇ ‚Ë!] Ù·¥Ž÷m¶¥OªnŸÔkÀÏ.Ðìo$¹PY§—Á -¬ÃXÍׂÜ×iä¨ÑJ®ã ƒ);gmynûdæÙ1õnk[B¦m2ÍJß5l\{-ÞVgj–ͦ.EîȃKªíëâÛUñ§s9¼WÓ°<µõ­žn?`¼>9mѵmà”‡pr³€êCî7 ««wäGžcè9*ŒCö¡ÊL1”³J o7Ã;r¼¼S·a“yì¿)VyØæ.ë2\ïHµ!·´zêÐûÒ·^Lr-9« ÊuríµJ{kèÏ®P¡Ã~gi¬ÞúŠÖwoUråÜihËsÃØvÏ$E6=¨gIk•^¥}½ÒžOÆÄ ‰¼}òõ½šWˆÜ¸;³ s´ÞÛÉ.:Xh.@%’nÖ¯¶^.úT}7¥`•evc|šìÑ~«ó¾%ËyÑ»ÂMz×›¹ö÷¡kÚ{à,PåÔçkU)Þ­Ëÿؽ{S6ÕùÅéÝù§›'WUîǶíNx¸ôy{ÞíÝ}8fWW}Ã/„.ÈžUã#Ê?™V^õ i`4Ýç·pñ¶ïz÷9*‰¶®WÕє料‚>·Ê¦+¡Šè‹Ortë¦1Àh‹ dÀIŸj8ž €­‚tºx8)¶¦;­y'¾Ö|/‚u¹´ íãbëaŠº»‘Êè¼[;yÀmÉžôÎ{y;•ñSÕ|z ³s\Å>ö>b0mrö"9(zïe½s â2º'GÂ-sØ{‹—Wzž¤ÓØ;;ãSã\/Là° ñlÏ«»Î—ÎÏFC;MÀü¶NwÒzz„Uzéov¶Ïݺ\í-Êj´t[‹Ú­­-U¦:ús2Oú¯/2 ùmg;à×J¡6I²µcY”¯Qê}¼£Ç”pUÀÊ®GŽvÔ¨NÍ—2³µ¡kN«G|cÒ»6?¬¯g©Ö8hÇ…½L Ú{†YøyËíÙ+X¢6&´Ýo³¹_Þ;®™ö¬©|K5±µ^”›.²UÝnËõ.zdh0xŒ©›®¢Ó3¿: Rî'¹Ü¸Ÿeå{¥;&¤ßW¡Ðæ†-Ëçðƒ«qwÃ¶ð’¯æ }×êäoÞ!¾P+ç"¡6+s+µWQí‚»ÜW´×yó¼8~˹)fî9VêÉ zUüºb›¬tp0F½‡¡½ZA‡ÞDKå÷—>ÍœhÍk,±—tsl¨~Vpq¹{ßxÏ?)Ï(GÙ‡='k¡–ÑîD\ÅÍQÅ!}R²›­iMmn-}RmiëîØÙ¢`šsjþvîsàW†‡+è‡Suà¨Jjxº¸¬ß[·§`“iàÆ‡¨W‚öZ×½GI"Ϥd…µÕ3¦íÛíñ£EšQLg–ûÔøÖÅòëþ~ìøéßH{ôšÂÒ3õ€Ó=ûÙF‡—½{î+Å`Ð2áëi)Ô…ò›R  w+%¹HÒú)²qT’;ü­îGzRÆ7:Ž ”^«˜±µ+»X¾¡´7å—ðtññʹCqé7üE#o.*ȯ¬|íõ÷H#íÚtr>¼vr¾=µ°.¹a¬Íæ”Ã…ÑZÝÅ.²Y™B£K°TsW6+¬Å<…À9p3ÅÀÝ3M_iv¼mç:â}÷–t¾b¸ub>Ë’ Õ—/cæg)b ]g‡]뺹6 Ü•ËÊóêÇxVrój¶§ÇBùµW‰²wΡ•ÑÞUàÇGY;Šòæ³›c/©ë?¶ðþ‹÷ï¸AïS©´ÿX„¥|©}Å¡Ló»¼l`-õÑãÙ'²êÏ©fPÉÞF{,ÜMÒd¼wÛ÷Xb»}ž"²èxÞÉ–7e¡E‚õjW]¥¹AñI^^hrÇU‡—D—òØirÙL*ÎÊÎSÛY>ÜÃ:Êöcªo° ]–ö¸Vš :·3ÅyuÌÝä°wÅ`*Öz˳^ ‰¬Ð+ªùêÞŠÅôåÙHô]X¡{‘ìamÒÕšÁ]ŠÉéh*;ZÉsŠ÷ŒÄ„÷¶ ñ ŠW«ºT§×”ÑAÒTÝÜÆ±ånq+°:ºÓ"Ùeƒó“EU®·Ä¾íËJ :(ˆ/Ú¯«måŽÝáî[ZÕiƒkiÕÔ¥Wm‹èY‰üEÍ“2÷­p‹o$,¬ÜG}Úø{OÓ.ç ^V!¾ÅE*«´Ú¯RÄ!ö¸õcÇ6›4êêØèÓ{Ó¬»#yÞTÊ/‚λikC!^¬]•ƶj›×'.¨æäÊì‚÷²•÷AÌÐpG:žß3ŒÅŽ.ç¹£˜‰a)qìöÛÝk‹î‹çMÄýª­¼žŽ³¹' uÙ"ò×p>¬ï¯Öæ¶k¤I®È5 ·x-©„Í\êu85·ù­‰9“ÈÎãØ%ˆ­W³õáÆu$òîä$ Í, =YL½){Ö]*¥Zš”8s°‡Â‚WžÊ³>[ºå_fr ºÙ¥©WNó½ƒ:e'F$tÊ'Ú:ý|¼ý 2ï+ÌÙç–ìÉF¿¥Çi‹®F­â—¼ùÕð6;f-Nš©aZË-›E|{N®c(‰+`âÞb˜º@Ó9l®øº: _áHñ`f÷¥ ZÓgÖÒ½‰êËvÏL€RQ×ÝFˆõmàg<¯/ÕÛŸÃñ<{Ç ñ‹Øì­JW>9¢§mä å`.¡ëBºŠÛw›s$ÞëVÐ|ö^¦îÜu7Ë;90ö œÍ ¹Ÿ·÷$kZ¸W—<6ökêÅ¢&^Þh›N‡J7¾?zŸ ØÚö[ëí`¿°°ªñ[ß_¤Ã+:ö½ã爮²!馡ť¶¼ûcxL5½Í)ë¸>NjדfíÛÓœnôjº½;®–RÍ>’±‘ó[ô²¼âƒðµàH¥©Ö·†ï°Üñ¤ÏMòÆ®¡;¼¹‡ãæz O]‘·‰s²¡Šü¤ç£î5‡–O‘x†Ònò×°A‹#sk§­û×qõß¡zÉŽMDºnhÓ3ÅÚ“ä4Ñ’±ÖÛ«¤f3îQ7³tG[í Š=;¨¦€9ÅoÜÅ]ô·Áºñ»hçÛm6pý⫚l›-Žv{F‹³ÁÉé}o«'¦ñÞ²tµ•äO+ÏOŽeO m¯×à=yyÖ(ª¾¯D¨o»´¿M‡ޱ¿#ݪêB-Ëé^Võò"ýê<Õoe„ÄŽöÊÞæçXKá®r€¨Uå=e+ªåX©UÃqH¤ ½ˆÃNÅ„ Jj¹r»ËwR$Í=î)ý=^<²ŽÊÃìÞ¼£|ÉÙ+ãC¸›ZÄî k]ÕÈ_g*•¯+ZÚr¶Æ¤eÅìÝÚõ•#S^BÒ@ߪ5“0£ãb¤2åvöë7ݱiƒ©dï…¼˜¼µöa^x§›ó¯szq´-ËÛÌ㬦šsì”UåsuÎþ¶óµSÒÞËNø(ö QêÇ|øìµ&™«¤gU›L®¾NVHâ›RêñŠÕ6ç×Î{÷Œ5;–Ôß^ìc'&ì Ì[ѽÔúW ܬ·é{î»›•1UÇTK×’éÙÉÏ]1Ã¥Êæòt髳²±*å;téúen5p]…¿c±k«eÖ{Ò}ué›T­Œí¯Vú ˆ¶ öà·™ÒŽS¦ §Y§¡dnSU«’³oV#N5œÚÄ‚öäî¡ë½pX“.¨¸ìÔ¤6Bý´{ê]]+®s!ÔÂ'¶½àÕÁµ“VíS®æZÀÍux¤f®:þ\´^XîåuÃ)yMªíæ jš])“«oWCݺ2e§Î7gϲÑqEL!¬{YJ†´iO4÷¼"ÂaÏ1˜×!®¦åªÂmFùz”Ñ~°}HX2î³Ë&µB»Wç<·q–žbâ+ƒa˦7 Çu/U¬£[À²Ä6éz2ÅÐvJÅ–ÌÊQ}õ*½²R™Ì{ËÖÛÉ Áq[@šJ÷IXœË.úBǨfÖÇYÝTƒ›ÌèÖ®fºó%_¹wwE÷xŽ~ÈfnM7GÒ+•¿¡Óu2õ¸Ê4…ì'U_b§–ŽÅn«Rä”ñN·²º‡W¯šOίhmøJG®ëu(^80ÐÈÀ…mÆÅláix´)ò’Ûª"§,p¹;:éŠa\­¶øØ¬[ÂÏ3©N¤žè1F]ã­Â¢€m–pYG·¶-¬­ã2Í5Ç!gjöç ¦plu¦,;à£W™oÝh—ÜÅ+꘣Íçaå\žjcº ¹ôêHeðë£ÝËn°Hú¶±,F‡JÁáØABâG$Ác."²E¯½ë7ë«=ÜzãÇ·š{ S–T\€ïj¯6‹ÎÑÂÞø:¶:siâD/vá³xvó¤„Á¶é¤ìùòxf+{»8LÆßç8&õ®Kð§äõå+^³O®i!ø+”^µÔ™•Õ—0ªë5» à·4ÍáÏ“eó)à",»”û¿/a£ú°{÷~)êÔ˜ëõšæi~¯O]x¡M ÕûÀzÓ¿kð鵟‡}°Êë¢ÜìôPP N²£»íoAä یũF)3£ýnW>ܽ» nmEÔùUàÀç$¿6–+÷Íc.¹}(ùób†ò±ƒv«™5ÀÐ;­pòÞ>»”¬×{ÚaÍ¿6a÷Ùµ4á|ÇzƧ$«_+­xG… oT4<Þâ¼ñ.¬ÝY¶=6+xÜòÖ„‡"Y[¢cjê@vÈèo:m{>‚¤ˆT)fÖ¨·öíª5+k«"hh"ù¤2™Õìê™ DM¼àªcÎ f¡}ÒTÜ å@³¶ Ø]w]Òp¼åVhc+“Í ¨9Kýé^9]h›•çÞO%ïnÁÚ¶˜rnÉœ%(ÈkU³™+%ॅÐo[äwŒ¯³µšHýÞl%ißA嘫ÈêŒcÈ”‚o1iTZë»0»è˜×Ûh¯–$±ÒÍã7±WO#ò˜’­¯At °ÓWÉÖ̺tGz½àE`êz®q­œLAë#oTÙ•y™P+ÂÒŽÔì¾ôeYÄëoŸ§ÚPø²<‰žBnÈ4š³»çžkzüýB¶ÙGaA…I%oNdÛÕ‹Í­£PÝÚÃynB[¾–$j»´"¸ïsY–ånë¶\ ÷ƒÓFÑJ€îŽ–Bnú¦x^ºËÉÞ{¦c¿'ìEÍܽò°âî“íw”kxùブího†((Å6õd¼õ46ÐÄÒ>y‚P·Ðê)ÁwµÔWkëCy³lnÞ²ÆL·u©ºDð—E±zvNÔ zɨëë¾QÀ)Ø­#*þÅ|2’;-½_¯œApôµŽ•ûô¬kÕ}Äß"É1“«q™FåŠ~ë§RÃïj©ãvÁšqàó"vReÐÙ»B.¼KZ»5V„J³\áeæÓ[œXÛYëk÷yúC~Ý´¡¼sÝËëz®é\2ÕÞÐöâÁ4ñðÏ B¬´óu͆ >Èzv;¯µ¬mè»FÁNº`çX‰¸¦k®…ít•éë˫Էgdý˜àÖÕ³B•jaXcÚh¸ë.å®îÇJ3tté'ëYx_TÙ vÓ™½Å”ö{¢×´Í6ê…2Ðc%ÁwVœ¤Q)òÁ ÞÙ.—íöwÙ£(¢—µ=ªÙ(FV<õ<¯¡®€vÄêηm¹Ü¢4¨¨]CÑ`ÕZ£ãÝ2–b­-)ƒòÎxOh·Ýån_=Ì ¥•aë½Ë«¿Ó;ÞŒJ Ƽ$ ¬Ø€–PŠï0˜Êy×;Aí#¡¶0ï’®®Ìî;nÝó+€¾èXöžèRÆ® Ž ëq‚åXWu÷IåO˶áqlhàÝcvêüÙnnŠÖeG³Fèõ=Ó=N2Ëì*SÒÖvqìï¬P|oBç¾ 2 ™´I ^Ìf²¯jö íbàhîß ÍºÚhÜO+È6.Œ)]zá¬êÊ ûyº=½/OW´C XXV³å¤ö‚Þ¾2±ñKWhw]à7P°âgª=É®žúÔÄõ laº¡xP‚:Ýó&`5>=ç^b÷F­Ñ2jß$f鬴½–GCxš2éW¡iù¾NĬ‚æÚöŸ.ÄÅæ_4».iq“ÃgØ1Ÿf.w¡—x4ÆK¯†û'^Ýz Ùït Öåê ¼žØ\^@ÑKÅß­··(A!’°Š0(”ç´êúAÙY/…nsÝéí4jÏ Ëá⦌a²÷R•¹•³9*¹qWËEûïFúàÒiíkÔiÝ%Öü3Ø#=fgc-ÍTX³kÕ¸}wDoŸ³·¾æ¾A ÷SNÅdN ´T"#¾¾»çãуéæk¼;z5Šéí—HRT©š[ÝsaÑIö²M‹×ï'fdjr´¼êELY»5h4;ÁUÒËUŽb½ö{{y¤*^õ«WFLVÆfÝ{r';6Ç×Ëœj¬‰EeòÙÓÝ1…ñ}¸»See5´]‹^QMåQ̷˜IÝ¿RHnêñÞŠ¡Î³D‡Ý´4+Rç¯5N‹Ì…ö“ºƒË{€ ît”K•C+Leˆ¶5ô´(žÍ..2÷©"3i“Ôñ¤§×jòaCYÒó먩Hä¥õ¥Œß-ׄØÕÝ %ÚÖ%ãå§&E1Bj""UiPæ°04qbFqšÃ°ºJ(·®åÞRš ©4ªMä8·Ï®´•t*.tzo¯XYf˜V,«ÓްCÍÏTò‘©(pr”ñÁ&¶€lòÙòëÌ~ Øí$­ÖÝ>àkÝPêolzT´(K^lpw˜c‰ÐZ&^ Zn€×Áh2”™ÛN쮚qŠ#ŒÓw•ÅwÉsJ-®ŠõcÏqÊ`Ìùc]®³¯±Ò=©£12¯‘ pµ„°ÃÄÅÉ n’«("%;Znèv ¯Š+˜¦k¾ÛƒÜ»p6/±[Û Ð9 •¾÷z*nY ÜùxÌ]ï:ë¹»ÒR*ú]Æ<ž³áW†è¿ZQéƒnÞƒ^Ê+5ÄõT…ÚƒL{â’nŠ1ˆ)YÁ4ì®CX–°?o¥ €¨nÉ‚Ë'*^vp ¹%á Àà4 Ä7a5ÐåÆPß±ñ¥õè¥&úO…wèbùZ)5\M^d„R¬¡ÖúÌ;]€t“4]ÃHÆðôþ7XBý³{Ýe¥ŒÝ2ªóUys±ÒÝou Á½÷I¦\a£ÆÝZ±Â}ovö"jJÈj~õ Í›#ÐpNý#ß¿n•À6*M¼¾469 úÞY,öãKÎÄ®Á-M›Ù²’H‹Çš ÄYvU³/?Yìê¼t¨‹*ü|ÅA<(°_7Ý]®áœU ³_;Qfõl¤_vvvÍo¢À(grBêqUέºx¢9ÉÿGVw¡@¼ø‹©j,÷Ѽ­~©YÑí&†]¸³³©E}©åÛ´ò ©Ñyy¼Æ¹FíŒÊ+;ºÌ ®Û¢´záF¶¯+:bÆâH Û\§ân»n ã) î§»1ߟѼ6õu…¡è%WVëÜ¥F-óqÖD!§]2Ï$µ_Y”°¡;;¤ƒ¬ÛÑ·ØæÒNÈXü68 uüßqûNWw#¹zWIø”1jd.¦e/ÙEÞÙÏ­´ˆž®™·Ûª• tS®îû †\gooºzý푲—ŽE[¡ã+-y'[›KÓTñ>ŽU¾b.êÍ»]´sduÝmt Øì»«˜EÒìŠÓ×pïw徫âìÖí^vêk‹ìâ7~âè‡cÞ/9išßD<}»Òöžž®‹kîM¾äyæîvBlj¤c»½|ërº£ŽŸyªT§»'‡'tæ}AXxW³a×­"œX([¦'¹¸2Õ,jÎDí^¾†\…Ñà&½£Ú™ˆ»\Ëí§‰ºX½l$:¦+ÛЊéEXÀVZ\ èÓÖÝ6¹ÕÞf¯ µ˜DíAK^P¥Þëž ØØ"02¢‚'aPÇß,ÍÏvv+;^ºÇ°/Cäü•Ø·î{Ë é­aZ.½Ñ‡uØŽŠöß’[VQñ\ïÂ/8õѱÝjNÖÕ^ï„qOo“Ïnø×nb!Ô»³nìêãf:TΞ‰M¾ÀÑyt‰™» ílYÞ–^®µ¾u)¡ò+n ­¥JÔn4oºë=@ÒÒ0«9N®ÞQÞ]Ú{Ú1µˆP®Þñ¤.‹~†n˜k¤ûª‘Ý 8àV…Y`¤å›Ñ}ÖHˆKó’:°‘ ™Õ}÷wŸ›ìƒ÷§ãa)•áEÞ»ÜÒ¸Ó«)aêÞA½«Ê*Í«o‰( p½·Õ|ØóNUª\ñµ–~³¨‚ZÓ”&&Î5ÂR9ye;úò9R‚„‰A"ô‹»åFÙV/ÊO¤Í™©4ewqðVinÍCîC(Å)ö¾™q¹7Fßq‡”]¢xs™äÀ¢‡¥,öéBg…»«º‡e…Öâ§Ç‡6äŽG¾m5ŽÝåHtK¯nç[Õ]¯#D$Rè&Þìö»†h©ÚæjDq¥Wl©«vâ‡/1‘£zSÅÚ‘½Q%ïU«Z¨ƒ>P¢Ü2‡Ž—¤ÑJèªÊÏqßxöäÚ<ÆÛcż:ˆ­¶É×T༠³ï{f+õ;sÌÖ5"w½ bn ÷+G +im$æ{M?²xìT•!6^J±™éžŒÒ¤ÍUgz­¬A(éon÷SàÙ]§d =bN"EÝ]4`_$½lVêD^vïS>ã.ÉÛWiªÌ- ˜Ñ”cºíÝžQŸov®ºòv­­>Ž‚¸­Ðf…_»ÇLSAkƒ«@·ÇR±<z{Í/:n¼±ª¹›«È-z®`]‰6Îäqó°,^rÌ㚣Ю雺%ºÑ§`îìrä!F$éÚ²oÖ²í!kÚ{½s…wu黄Óùf TøwÔT3žKnM•(×û¦×aˆY[œ¹áßžõÜ-ŠÆ¹Ö·o¨)=Ùà÷j¹T¹$ñHG` éêМZ\L›úÞ¡¹7íêêÔ{y,YÖLzªÑ|åîIHÐX_q³Yó/¤.e– ;FcéqD¶nÍÌ89påY—×¥ºŒìݵ˜ù”D+‚¥<²±÷ƒ§€÷»ç½¼*Ǥޓdȉխõ¹§†¤ÁQ%9¥ ñlÈuÍ^Ú1N´ %Ðíλ!{ÔIqdãu>âògg*žÖ/†äXrºW%¾S)õ6Ÿ]ª`äO{±¬¼7&)¡-wCݤ”ÃÒùyµóÞö[æ·—`ëË·LÚµî±á0ús¤ Už´©7·×äÎТMÈüTÏ!ßÏ{¶t»«¤;|ÓÈHÖ+b@g…ä{_ºe>X÷—”Q¡ëwm›‡oW…rm˜^ÔñÐê×V¦(k{0æÜì¥W-a2yYäìhp‡Ï™ÇLì¼È«ÅÚÛÀºrwYÅݼV^:]Ù™–E/¯¸ÎÝŽOŽÈ´§r×– èvõ]mºå('Y Cîê\~^œ²þ;º¿¥¥_zs!Ýåt$}·Â1çB\úœÚò齄HÝ4«]ó[QÂÔ±ÔÓÔùòw·-ËÝv39Òn^û§Œ9†,;¥Géä¡O²Ö yžDÑÜMÜôã]Lh:9zguº—Z©ºŸjV“g»,õµá–’Êz]åuvÏ=Çà¸Í÷6;½×“Ý2m‡97¦ò°Ø™£/1)2{ÍÖÄ£ÝÅQ¾×Z°ŽÉ–茣«( ¶³%!gܶSÏu¨÷ ¾=iàõkë¦ãã·Â1P齯†­Fr ®õõý–7ËÊU–};E4˜’!a!K¢0ZhqTÄÞ(B«)mÅF-iÔ6Å «O‡‹»t­¥Ä«V-Ûœw3Ì:½Ý®šïÙ29ë¸äžìñ¡ÕêíÀ#ÚÑ»ZŒ-˜SUaøé ×ÞšŠ×rá³h^bɩۨï«aîSƒ=¹¿lÕµ¼h¹<ã#-‹ëŠò÷4#Õ}O0EÌWøQËüý'àz^¥K…Ø¡wOi]Á—ùïlë¶1òS¾µÂÛw6gQß‘¸gšóiñ±»®§¼©äî˜úì{®°ש_‡Uœ›ÊåÝé½¼aèÉØõEƒ.Êrâ”ó ä œ’ôD†lÚA³Æc¢Í8ˆ‡ÍéÑ·˜0×ȸ…¢ €¶-s/Klø¯ul°…o`Ψpn|k«¨wb’ã·k SEwYõ ½‡´eÞô-PZ·Í¿:DÂf·I:·Ö†‰„Ev=föqŠŒ/‚¡¶-#Ørì7½}²8]&Qç¬[ÌßfJu=ä=7NÒ–Cê]Š—†ÔÖ»µ¹RÙ3)ÝÞ*E´‡²–u!­tºÓZýµÊ¸`ï0=©ìoMÁé:ò¶§rìœì®E ùšy¤ukU} u9¯–]ž¹Êc™ÙÅo$Vm¢ä=ìt¼«¶7]ÝæýïRº™[÷fö{ÊšíÉÆ(í%ë«åJ^cRm‰éOlZˆ9öo€ó»"™3Pã›}ëSŒe-T¾t.£3QÃt¤éecB½vø×{Ã(‰~®tO2zXRu®ÎhTíê^]š‰ÄÛ”ziÐ4ª‘é½ÕZé9Î<+œ@yÄA¼YÉ vݑݤ㭼­u¢År¥ŠúE爾s‘u+¨Wm$êp× ¼x# »Ç¼×_:”.ïØBáº>³ë– ÇÄΕ3íebÅ×µ0Ò03²÷ Ø_Ó^ªß Òx^Mõû»Jw´ð”ÃPM0e«áh!u·‚ç¿JŽ`BßT²(Aw;+ËWEZ«ëõz¯[tsmå¤³Òø¼]9Ïp«uNˆî8Æ{–]iк¥Z¶E¹ƒ—&$cڃΒ”½td"µtó±õ¹µÁXVŒåí¨`<×±ÍèÖ¿˜®³$wv»¾Ð€äª=†Wt¼¬!=«Š,º5jØ•|[ï/³¸aÂaq¼Ø+ ÜÛëc)§Š/ }Ü/­’ó‚µ-ºìuØi–2¹„è\¤;¹¤›8¯ÝÕs)MDV÷uµÏ Š%Ý‘EbK \J¤Åk³T°¹]gÍT«²¥—η}Ô¡²¥zÒ÷•ÙEûSÛÓ£Þ(yï²Vý5o-*—gtÍiJÚØ»Í³ N~h±Êeí>m’¯P° Gwž¾†t_ zÆõà …VÐø•»)ÝÀ;À Qpõ11XOÚyÉl×Dr¥lÎÊ'­¨fÚ}³Ù3x8÷ÜÒ2§oµÚkž¤‘í°†XÓí¯ -ëêÓ’¥kµoÊ ´úÉm Ø«`ÁN±Ü¬ºì E(ÃÊ›‹¹U½¿¯ªÍ,T*º®ùðÎsàocå!ž",äÚ×|é*ô,†pt}ÂÛõ•Âúz§ I”bñ? y®ìuW£`§_‚ô{µ3Ók¯j`!Y="ítÍØ2œúfuršë]êRž—òêr]žkwÜ3Ï;ÌZ‘²úx®ÚËY(ªs76w ÎÑËå9gÊ8tbq-EŽÅÚÆI‰†ÑtÙšf»“HîZn‹¨ Uç»ØÍºˆX³ÙÆÎ1SˆeóÇ@j=kÒ;çS|ÆpTrbq=’“¹§— ¬N£ÑyÓöâ•í\Ö¬ ….;ã¦Åëõ“uªƒ($Æì¡Õ;û­s‚b°Rõ2èÔõ>ÞÇB§)KK΢´_j¼| œã¬t6×Àjýw›J;l­FÊ~%(4-¼Ì8¡Õ–r8E6ûRKTê57­YÂûh‘L)1¼LÛ-²¸åÛåF¯r> …°qÌ?:æcpdáÝœ®¼X(ùÌbÌYÖ…¡ õ1½ržJñ ¯£½¦Áw$õN³Ã®\Z>F½C—ˆ›£Žu§¤ßUÙ¶QåZXð‚Ú¥˜”Ê82w—¯Ø1÷ ¬£Ýç\Qðìð^„j­81lFµánÃGnŽ%ä¥êxSÞÇóhœý±ÙyîÔÖÌõ(íÓÏÛ”µ¬‰;Ì·>|¡šWÛÅé½±l:Þc³=œ%ä,;áWñ!LÒ²¸Ä#{l®ïG–>]×å]!Ý=wZö”Ñc*@‘ˆ¥çꕃq`ÝÕ(šf½eUÌòåÅoi8[¼‚ßÓ ’†ëœM³S½Ò"éj-Ù•ƒ_w˜æ‡vÍê9&æö_ “¨qGÛšû‡½‚ù ’]̧e{ªsßo”X¼vÆTy™ÞÓÒVdƆìY|–·!, ¬*¶rg+‚éHû«ÌZ¾+ç£y§î×]75ì—„^);„ÊÒDŬ¾³œ€Ò„åÂ]ÍZéö»ìž~[¶¶_ˆŠóR|5ÉÕÅpP†MÛa÷'·›½8¥nY¶!ï3Ý‹Ë}}n§·1ð7§{¸ ™ºæÖªTçÁ{NÚd¥p3"eë6ú¶ržf ïi%z÷[ÑÖm6蛿uݬ’k[/4T:Uî:keÑ•ÉíMwÎT°Ž{,f%@èš°^½¦úÃòRúNàÛÁ9»¸#'R ¯è\éGŸ½Gd«ƒªkŸfûÁ]µÃìAKÚŽ¦&ñë‹F‰#,ì¬é|QT«mo± ã’å^§Ä«ÚÎ1P×Vp)V éÏŒ¾5ÌhmõdiÚ°(2V`¸¬M4]fÍBº—ÂȤ]α”}¦£‹KÀ`Lî`eõl»$éjV<õ´ttÁ]Ϻö]vŸ mÝl°¢þŒ›±Çz,¦ÎÜE¡¹Ø«•!ˆK*D›ï®…5¢Ó¬²3_`DÅ[G@¬­lñcD¢7,ÙšØqñO‘(³µ‹ºVÚÌ}òΔ°'^Ï_Ÿ£ô¶Bˆ‰NLVËV0PÁWw$êÖáÀâ·Û‚ ¼ÔºSQ½¡­àô+pwr"†,>WΩ¤q£¹Hl“"¬]é< ~m”uóWV ÁÔOZºß [àÏ`¤ë™ô‹)Ôƒ”¬¢w¾ JàÛÙ˜&zv ä àëKJl’êNg#‰VÚ犇„íÖ°W”äŽcêŒAØUdã˜mJ0ÍÈår¡vh±ªfôïgq¢@o©žõy¡ö­w—%2Y%÷u 4êó¹,ÔÚʘÖÞxÜåzÓø×Ùt6õ ¿nÚó *í.³=츼Í㯠ó(Å—ß½áEVÝÙ_·Ð3xÓé—h—ƒ.c]˜ºÒ ƒK°\3Ém=Ã2qt8V3k¾g¹öWd˜ ²“¢/~lB cïrj»±wŠw¹·/ÆïWj¨ç)Goá§4n×ß. É[ðúY‡•eÖ˜,ÔÚ¶Æh.ß‘ºòÕZFuÉÃÍ¢ÙW«\N ÜÛTž[{{b¦áä5íÜ‚!ÒgHRm)'éƒÛS“€ëygW=(6"x‹îÅgÎþY4?oUàN?í!Dån.ëÄïs#T÷e)Ýä°0©ãÚËèxš!VøÚðÀ/sÆÒ½ \$,žôòêéÝÛ——2²-ZRO^{-JtR®\UMÊÁv•—ÐS·yBÓ%ÛÚÉ×ïe^s³N°ü·×­;•¦uÖ®£FïiI¬!÷îY–OV¾geu[]µ( £—ëˆõGX3} ‘¯„ÎñYRÕì$Ô Ž²n^NWq²8\—ס»9C3iLºX¸ä o”º}›)b€Bi5Ù6Œ3t_€CÒ‘utpnÃh˜=b]:¾ ì‘—ƒø§&PÒ¥b>_;xÆÜ$妸uÃÙÆ‹èûnj¹¾BÓÃã·¥€ ãåY7=œNÝ7ÜÁ… vVDíhÇ]aáÁ}.ÉK†WjR†žçy2á5°Û9ªã»öÄÌkÔr] ~{b6§½*fNŠŠÑK‹ð‹ñêa\ݥȣ—ÔF•g¥ò*Þ ÖÑÒM™Ü~¼¼7 ÚF±¦;Uœä¹AÑ™{Þ;]ÛvñõòQÞÖŽOƒNRÙ]=ôƒkt¸ØúrÃ~;^¬óÓgJ8‡x,ÛNžhõyHL¥u‚à´ˆ!uó?¯õ¾Oxþ[w¿¿Q:?Ÿ¶éøOòÅ:µÈ9q­š%‡öêëÖÒõ^©tð„ÚjûOÈü7ÑÔa¡†Â®Ûжë{}îöŸŒÚg©{ØW¹ì®‹¬JUxk;rP•óD¥»&ýÈk‡" í5)öºk!ÃÏåÔu_,Ήb+s&Nd§ÛFM§ÆÛy×¢ÀFÒD@(PêD¾ô©—FÛˆT¥Ý~@’(äб%µ·ÔUuÎ õc}í¡X+tP¶|{#ðÞ…Nf\î)á«Heç:Ïg%Š£”:ø6 ­ dKÓÖ³ˆMܨžp)­LöÔ;E&xF Ä™‹%l…°š,»a·Zù²¬Ò ÜÓó™×椗/¨™²ÎÖt®™æ;ðÍÖ$õ¤Êóuv4š•­Y¿py¾2Ïvõ6*ÛÁ6;EÒcذÚéÝÈl-ÅpÌúnlMe÷øïïÁz'‹ëó ýq±Ÿ½ê—á/ÐW…Þ7M÷alàô,S %Üdžé„S»KÄ7Ùº7yë~à$Yµî] Vvå5˜:³*Çø—~ܽ]Ï@·uù[û”èóY´ð,T7*h9ôrÕµƒMÔÕ§„yÚÀ"7·ëf=oÁëÕ=ÛV™wÏç{A1®†P¯Båý)ŠíJG/–Ù}G²´66ŒYÆ‘a½å•Äd¿9G»ÎcY~,f^Ó¶µ:êòKÖRî‰mp{•m¤vûªñÙ¤’ËL— »48°›uóÝÎ¥np¢uÜ´ÁͺÚ|Ô\³ÍNB¥çd™Õ˜—¤fÑî«»Oeckš}‘6zq¾»&0*õm¨ç õÒ’^Cä½a7^­ÄcÚº·G!‡Ø˜=u“&_¬‡{°&¸ðõ £9búxë¶‚€xÝ_+Ö;NʂؖèÐg{Fô“8VôþYÐû¹Èì¿JÇ ,íÇEpÇ|ë¶Vd4ç.‡#EÇ8ÔïÚ%5¹ã1S>»ŽÊÏ÷©v+Ãǹ«¶Ÿs7Ù\œÁ0ïç.нK9ÞHˆ†¹ÞÙOSÂ{$÷µï®{¯5ô©â3žBG*SQlnn¥ŠwÎyª¥½EÓÌWùÊbP~ÅK+0…w§2zÞ|Âýžã!ðÚж쯶…Êa>ÔíÏ¢¦ƒ|cžÞeÞö^fµÅçpT®R pÁ}QáíXæá©·k{eiC¹\g}Z²ŠÞ4$Vw!¾¼ÈUwzD÷)ºjy.“0É/‚ÌÛºû¹Òé`7£½ìëÞ`Îr7‚¡ƒ¥R£:„X¹ ç~S’Ô¦—²¬kïdkPôZ|™¬—éÎ`÷ îÆ¦/p=ŠgF ¨@µÎTÅÃW#ÙQרgTÚu®]“™S¹Ýô;ÚËFå­ÍZbš]9C;^öª{;ròY +–: Ç–ýíœ+”6s¸k¸lö›Ú;™;’‹IÆ=äúÈÎ ï ºÆr?Îl1‚ëÏR»Ä´b^‰;jºa8ViÄô}„¡K*âÃã¹EtÑÕ^ôéŽõrÆÛ;@Êv9ƒÝ¯ƒñЮg±¹¹Ž¼ú!¨D`¶Îço*k¾îbCÓ`ËÇ  ':™©õ§w¦µÖÁ¢ƒ6-Ù}E1|IÊrÚqûÅí÷{hçtÉ]ñ²ì§Ú1x:vKkœÑ¾î5”Œ9JšÌ>ØPTVÎÖT]×z¦,$&»iά¦º“‹0_j`ÓË›f^‡4;[s¡JÕí«3-…Ë7µÈíEbuí»‚+ánú˜Œgr5T[F½oEÛß{¸VfŠð–7k½'Ò‹HYµõé@ßNƒÙ[Bo•àãê}Ù¨£§.£5ü‹UôgXœÞ¥ÉG•™º©yý½»á¡[çj§‰´™þý¯nÐ6Þ»[7ã6º½^KvòøD'Œ½+qeÙ¥u¬§ò­îêš‘éïgƒè:”¯Ï§L…%{GÔ†}vêI#•(ú×Nëw¯^‡@l’]{MÏzåHèaäyŒN.ì ËÝ%»60â¥ç£®ˆ½¹…s:–vs˜,Ɉš¥>S6‹™L½×7R #º€‹meA]®ï21:¦üÒÁÚè­Iœ«RÛwß®·¡½"Ù;&Ú# Ãæ¬©ÈŠƒœ.”¹µ:L3â!ïUèSŸÕ Ò§d¹=­v6ï(p×ÕÉçV²6Wg}±Dç㊲ù¤ÚzY7~‹:‚¸³ Z…Ö\Ñé&ª=&ÖBÝ%`ÖWAWHÊÆÓnæ3ÊÈ}‚øåº¸Î\°–è2€:MNQ_iŽˆ–²³zÑ Ò²ô€·—©z:ùYc1<ê—‚¸Þ )¢ñ_7³(w=äǽt,ÓÅ:º•|_+S´õ%œfÉið”õTOwºëM\WÕÕ™{Ù[åqÚk²ê\m¹Ì¾›šäJ§*M[¤‡b›™bµ«õ4oÞC³} ¡¸P9“3u`îÉ*éá[bÒãô¼/3S‘ÑX1®ÊPò»tíç1Ýï=ÔVãÙê„è+Ûj•àr,ñ^÷RÅÈP@e—Ë ¶o.tC=Ö¶§z›=,ô3ÑhçÏ=º“[í÷3Õ•Ø»zf“‡%"7O.ŒäuçÓVc{lû½sº¸€òìën ' ÎwCXö·.vAeŒÏsÇZ¼zNVù\Æ6„^ƒWSÌ.0}b¹F‚ÞêÊÛ—v2Øu›Ò>ÚU =yIr©=5Ô‡b¶¶ù§dãº.ëf€Þœ“=)ž°ëÇ@Qmžœªßg;¾«ð̃â` óɵbG¡˜r¬za º¼ð±u7\YB›ÏÝl\¯oŸS-¯3Ø]¶¦Ò‡NjäÅWîä³_ƒÊôë÷¼è%½‘{M{')doM‰ ÐBM&FåƒVØê6ò¼ Ù5¥žÓeï”ë©f±¾.‡öã&Fñvg{4Ýr¼­ÏÐA¸{ÕÉ—+ÌãtÄX¾LiΫÅS([˜£¬œ&¹i§—ÝÖ­Þ»]‚*¹žÞÆ+6j­1öå]æƒ놆æ×báB,·ÉÎéVgEªêX3s«O3tõç®O­Xì 7‡x‡‰L\ÎÞdêŸ|%¢oEeÒF Ê ;¡¢Þñ‹EªÌˆ]k»«‡¥‹–æ4¯UuqÉ‘›Í¼šÑïTïK¯B1wªÎ] õ;9yõG©Ã@|Vr$PÓê1bèºpöÓÍpœÊ'ßTÝéUÚ}Çšp.4|evXg·ËrùnŠÀϼCôæW 1¹†´]KƒÙÎyIÇUÝÌCmŒRjt»k`êÈRÅ3_ĉí坨Qs€§“öí”Úër𮚎x½71„…žªöñô¢ØÐà­Žk›;ŽÖwr5aÜ5Ó0{_ÇM³{ÉwÑln¶ÎYìË w3>Šï¤¯7ëãpq Kö§êç{žë†ì¤{M犩˵{ ¥3- =NVb¢Ô*+™aím›"”;¥îèÎR…Ž!æcxÌ<­»òúVµØóÞ¶¡½Ù¡Š ¢€UŒgÛ*éÒì6Ge¿HsUf¯#½IÃ\ý}O­"£Û¶X»«NÇqKÝqÎoKàºm)[)¯€ n@{ì6‡Â‡Fr­Óeè¹]»ÚÀLœ×Y¬­¥Ó$ŒW¶šÑÖÒ³ˆžÌÚ“Öt2úÃǘ¯ì­³°. tbõÉÜ…æ´}'ƒ–$”Y©']Âý-\"üÝ]¥<µãEQcQ½,57ÙkQ“ 4ÖzT÷#ÒAÇL/Zo±ðQKa‰àZ²·sÚ°‡Yi†4‡uzŽßò^?‘—©P¬ìó‚½|Âÿ^såËÔo°©~Ž9Ù]•šHÞRšb ÂÁÎ{–yk®œ†r}SgYË5Ô4[íH\ZáÛê“Ç9ºêém¥•¡ ê …ÛÝ‹¹/MîÂÙ¨e|yìV;´HVuâÀñ[èXv4_MwXª|ñR‹Ï»DqpU§Y;½¨mûme]ÙI–‡nàÝ7ÝòŸ¯¸W´Û^êu¸ãÓªÍuŒ˜Ÿ€ZzrêCIå6ÃÕ2¯0̲û«¦£»‹â)¦¡)Cy¿˜P&ô‚-+JT[ÅëHÕÖú„¨át{Çqøn~Áîç®§¿V¬`›ÞçC=…udùzý²óÏv¤­œÉÄé˲3s«—¯áÖ%ñõF½PÃWlß`óñÈT¾é~>» ez^­¦X •*ùmƒÐoVøhåšáå~¹É;K=ž'&ý[ÝîÏ£Œ­™u¼Üžºî-|‰Ûg(ÙÈY2u ­w;©ßaÌyÔ¹4 €W.Ô()Kœ/mè[Òëç ýzöÖ‹M÷J2¯Ý2·3‰”{VrG´´éö]µßLã[ ^kŒ¦‘–­;HzÓÃT±'5aœ+ "ào&¦^+–vj£ÝÕ¢V¼Wóv’¦àT¬é´ÚeR{­Ì7Q7Ïèò€îÌË8Ž]Wg¼^ÍÊÑwÛZ<Æ…ò¯&Œ‡¨ÛnOyQ£’K(MƧ^ãÞJJ…k/<Ä>¥xÔÞ>¤–Oqfîøç 7@|MêÀlvÔÕ"JB³Z wròn›Û‹Ÿ´ÃSlÓ˯ ]Ú7¸qzºâ¾DYB §ŸcøƒO]¹šÆî2ùr¬®Â¹»¹zÀ¾ÀÉÝb—×hðãyá¼x,Š„}y>ëÇ&lò]K”þNƒ–î=ï´)ÝYJc åjz*mÊ^¦`–a™×Íéz‡ ²ÐÞ0ÝñíFør¡÷Y5öúž§ÙYŠe–º¸ëV«¬[ɽ}Ä›]ŽÙAV¶Y£ðÕV.ºÆZÃéƒS5ƒo{”U0±Îvª µ£ G™4Ÿ/ËËP¼ b`X ã¯{ Òµãz+EtJ÷9Ø¥¬ é°Õy%\<õ§á]R{'Héo4y­!Ý,3«UËò~•z¦îr"¹˶mV¬7lÝ«ªw]Õìg»K!9…›bÂ…ÒÜ{SŒ Œ­AÏ£¾›SÙ)õnæÃ1S²žÎÎJø¼M5O:ôöëwPA§];´QçÛØ«¨”Mª&šÝÝÆ7­¢ëC¥Å¬uφËlFZx%fp!Òù޶ç(éNÃev‰+sz놔ß^c¯Nò]3ǘ§ÝRÓ Bè{=/\÷«ËÒê§-#+ŽZí]p”y@îòŠ×‘^`dl}ÕµÈ8²ó_ žµ²uz¹áÖËÝÌœsM*Z3‡Ìuísv§ E¹S»± Õ‡*j¾F¢PàÎ<Žy;gN¢µ²ð:É¡NÍ•Á}S)û;Àî%ä[qêñNõy7ëÆytè»s7ðaR¡”³TJ¹5ÑBZZs»ËÇŒ,5©è׺8B`‹«5¾%}é^CÛÂnik²¹8·Þ®4pÃP¯ve‚0M¡»3Àbµ¾ TYOj{®ì¡×ëñèxs¥îzÔØF<†¹O—³¼hu›Ç\©pKíû/CfvÝ:m!Ûˆ!ZùÊò¯VLÊǛ륜zåøðß"ûŒu:ï½PàÉ&Ö1·•ŽZ&g–ïv.†UíBÍó,š’†—»W¬°Í¬,ìǽ"yȬâλP à=±Ü7,u󊲦øoœÌéêͧìž[Íë7sͤý\)V2OqÄC¼=’õ*™¨$rÖ[ZsuÒ§ÊÞn¨ï,»ÓT3l1ITeÜÞÊKë £s…×`£©a|ôƒVß^¥íqÔ[£×yJ ã/ÕuwŠgg‚(ɺ÷Œ½ó;§77°2'¿g³ªíz­ÑÐØ8b ?[[B³É†Ú; ŽÆtæU¶ùb;• q.#zu­WÓ·b«p'}½È2¦w Aë³7ƺº¶ÀÀ8Ù5§Ž[ˆÑU”=ò-75?É]rÝÚ€™ƒÅ–Êi‰aÞg¸]§k®kËVCÅN¼ Ò.Úš•æªÝ¬­ôðyºPÔ»G“Ýóó»4•yµ­5`ÝÚ7Pæ¨É¡¾ibôÓ>s!ܶ0VƒñÛs£¾1ß½±K«º–‡¶M§ë5ªPaP«Íj^7Vë…Vi6YõfVà7á‚CAÆ /u»Y×gÝhUÇU“P”Y1Áí•wçêtsƒ N÷…ê©ì¢22¢WTW ~+Lï'E¨AUÛéÙÖ)àã8?3Zù™8߸ŠW—kÇ3}ÕÖUúÄйGa`ž>1!Öüë)ò²µN­¬9Ìõ¼eƒ·‰û#öËZ0qiã½éD.•ÕñÏ`³¼_ á¹mCà)IïxV÷´ð™2Êj±Öש¢´È«<¼Ý#­¼Wg»•A¸I<¹ èÔCEšØ0­æËÝw|zÒ½Æøúƒ5™®’»¯u9¨s|e®‚œ­7Ù®ž\«[ùˆ)°3 x}ö ZUŠ4÷sª{¹f Gx³¼vUœbè ¹c^ÜçCÙ8xá)xX yí\Ñ‹’ÜÁ8êÖQ®4u ×Á÷Rs8^i8P¶m†í$êæeß+›V‰\GÐêµÙ©g&ón·ž†·†x)^$8ÇI ÷­:ÌÏ!(ä?\ô„ â2I„×/Mæ\Ìà²Ú‡J•{Ú1Gœ{@~Púog×¼Ú·Rý0§Ó¶ëõä¹os]Hûj÷\13 Ò­¥G1¬}ÙÝYjñÓ”Á‹rÔ¨N@ªÛO[6¦Òº‚µRíwZˈ\å´Sïx—౤¾ëRÍQ+Ü÷d¼£b!Ü‚-Ÿ_€äžÕîÄã)ê KuvEוòÔÖ]׊Ùåx4´ó¸üÝç’d²ˆ÷"!Ùiŵ6OV½$t|殨é2óH{†\†NôZ¹œnúuBä– •œÆ —]Isu‘Ò›ubæÑêÈney³~™ ÷^\®ž\F;Ìkc‰˜]5XJê´LH½©æÏzǸmÐÃ|ŸXÊIžH V2µá´ãѺRý)G&ÚÚ›%Å  FÐ`,›Õ6Ff›ÜÊ™™:¡öæõ],öV¤å¨åóQгAôKqzžpO]÷KÍ,nö¦hkP¦fäËì´`º]S·‚¤‘ÌÝU¥x­Êx£K]¶A¢¾·O^‡7s ºÜàó‹ULh¬B”œH“X»o9XWTÌÔ.,3U 8ÜÇ”qoïc‹[Uy_7h%ïQR–kë,P{){ öÜà·åV×nñä èw¥ßc{H%s ¼³³» ßsÍt¦žôIÛä*;¬ë(Çt®}I^f;‘ÔѸsC–UÆ#Zàpg¥ÑIèéÙX¼®¸u ¿«/Ÿ[À ÍChà’¨ÀLùûÕÊåG:ÔÄÉCÙHûŒÇ¸IX^ŽLbíù@NÄwÏǺ´L4ò•&²ø•r>£ÊaíÐ,myÝË;é=L¡Xÿ+WHuš·sÝÃÜ]1¢{3=I‡}™aw³Ë½áâ¾±X§Í¹ ނӻ÷®40ÍܧôZk¯`i^eÜs\¼u/nºKÕ9`ƒTUîëç $^ÚR׫‡ÞvqéyXNޝ­ìàçp¦("BdŠxéŠuvˆHÌêÛÊÐiöɹ%jeõ æòŽ.’œ¹D ¥Þos5>éæ3e¬¥7šˆõåqëIO°‚߯Öd›IUŒº9ûļ«v7€æy‘SwsÌ.[´â­µ º™&n¬w–HÚ¾DK÷µ®ºÂiÒü;<ÉÓ¨a®ãÓØ÷)Å5‘OhîxJšîx­hîGî÷xô¹7ÍŸ:ß—W aĹÉ}¡Œù£ÁgLãˬý§´ÔËxxÖÞ—:ÛY<bä;ŽÜùuÖîbîÞ}yCmö,§°GTÈ£5ÚßÕ„¯orÍ^®•O·w#‡gɰ«È­k^yôCƒu Ð»óùוæ3™:*̪Bîâ…nÖ z:”fP‰;6dçÚÙ «zºncÀQëÇ᫵q÷/&(¾Ó^mUï?rê¹oMŽ…le.%¢ 7¯d¦ØOÖkn¸Ã¬Ç#ÁÒó/]nô2 2WMBDæÃë$]Ö'ÝÊäØêgÑw•‡+jó{Zû1| ~ÌY=ˆ&õÓ>¬u¥£–eÃ^Ë–Æ®­LÝ8ÎÁ›Sº¹q‘gDn¥m_>¾ìÙ¦aÜ|ˆ6À¤÷mZÅVVá\±‹„íað0\h4AžÐÑ¢ñÁñØ]7µŒ{NÖ«Íkm÷JÞah¿¸Žn‡MAXæU®Ö ¬‚ôµÛ‘å§²ÎiyJ­u0ïZzŒä«o ˆŽ TØ€}»dœ®(~hÞ–s©'æ@^B=É;~o7™¢fîÁAQ š|€'¤Îã/ªÕe¼•2ËImÔs1jÕ×Ù'%ò΂ºÄîZw0\—] ÷´BÏH`ûD`Tà=³§Q³ãÙˆû²½M:«6`¬T®œÏ¶£®±ˆÞ ãC#Wš²×VËZ°ŽXnÃ.U½Ë˜ÍŠ%¥µÝظ"ub‚\-ߌúÆ‘/Ç[^÷ƒ¸†Þb•yìêQÕ…’è_L{;g^`hË£—¶¶R†ÃúÎÖ×s_.®Júj:xßve‘tw2Cq®x6m$mà!:&bÀjº^.TðÍM ƒrïŸX²˜¹'»Øî³¤µ^Òß_qïgÀJrW”G«SÍúauçܸçP „3_TG «¬–ù’xò×”›… ѧ4«âyM#t÷—UÕ-®÷ã#ê†õ¸àk…•;M‹Áš×uo»¤QA´·©LB–w3º·$µÑn_w{ÝwS•°@A4ÆkÀM0ôü~Ùã’ø“[´Âz)'ÂD 1¨7xl×ì)èÔÊ鮉†îËEC+£ºGrìLhý¹•½õÕùÍä6Á ¼óϧ¹nVà(4ß·ûS¶*µî¼åÔß*ÀN j¦^lï­Ü˜F³d'‹˜uzó\ÒÌ9wËÌeÊM™zÝ­XNª{ƒÎØ4š¦t­ŒJ8Ê£ÖÐÔ.ó!áå'PµèKuhñËŒÌuáØW>|FSyé‘¢ûׂ{ `Þ&“ûtz(ÌÑßufÇ\×7jºÔxW>»|÷®°2÷yÚ§Üî£+o42vÍ:Is¬˾º»Ò0k•´·{MÓ q!2xÓèéœ&u;HœÔï«w»Œ‡™ƒnLº ûjêÈó‡H¿wˆ²}u=Ãkª§Léõ¼îëÞ7º1¯<ü ©Ç‡’OÃÆqGÁ^PŽÝ2ÝŸ<:n¹ \ÔóžTEç·ƹyª*ó.†¦­c¼Ã¨°Ë%úÍIÁý4íáóõeíú¬Ê‚åò†½ÆÚ˜+&ªWns€AY„PÌ»,®Ý*q¡{L\ø‰¼,g*È|«HE¶wœ¹  =–+.Õƒ¦êqhìÛÎÞ–2¡éÌÜÛ»F†K¤-Rš “q¡¥e¹\ZÛ-Æ”úùG:_L»F†ÍÞêº& QëÖÐ9µg:*Cäå“Ýt3nôE/«’—³jF­‹ÌÞÇ„md×i¤ÇsWà^¼Â_*±ÛÀ d§)n»Öƒ÷mªY`ªºnÞv›{h½ÙÒR[K$uîK).w›% @ÓÚ¦gX·Ý¢µÏ€ºDÞÌj=uÝõ'ݼ烢d°ßro+oe×$®ó”¦C‰4rhúj›èqìÁPfLðÇÙ~UÉJ˵ۄêyrÐ߆«@òͬ³:cX h…ªN«·Ó¸ó]Š?M}¸¥½;Œ½öµl-T°ß‹Ì^=`S˯(íé[i„Ý2vly.gmî1–†dµÇž›*9ê‚Ñ×âpwDÖä73bÈAyî¢ðÔóßKÉ\kC.^¸‡_×ËsÔë˜Òe )óÁ¶´)ÝHS©%È7og>»JKÃFòßpÈ>ÝIÑØÛ¬«û[¹×YuÁøã~+bî)¬óVæh€Ÿ\àù5 ôáS46MÎ| 4ˆßa~šõÖjêµCˆ#\¢–Ž*yp·¹²µ½ä…J¢¾»œîf y°žÜ¾•™K4¨Y î–@J°ù<µIw»¯ÐŸ$ïB.6ŒÌâìÒ’NpŒ–ûw¢¥xNæ"ó¤³k9WNI¸•p]X›±nòså-ØÃ¢¸&!òácƒög¼³< 8iV1@BÜ<6Y½tƒóüÙÑË/Šê¢ ähѽRdeDlÇFŠ®”õKf÷g¡¬}}ºŽåt¹žÃÏ”¦õ®ˆøqêsDïA}JoRz©3¹ó#ËçK€]ûµ¼úÆV€)/`R˜Ëix†Ÿ½’òµe*ˆ°RÙ ^ÞÇ< ÊŽü®ä)nÄQ™­&Ó­E{|†æÚ¯z+T8ç»ÆÕ÷«)ï®°^‰·M€yæ]É·’^òB—¬è*eY6¹ÓDξ€äÛg|kÛ ¸ct Ê|Eà¥8ö43rºº!aJUµŽì©*ä—ÃÀ‘¡*ßsuM:}Ie:ö^쬱ÔðÇ.ÿy?Å!=Z¼]\^>²Ïî¹KºæNÑ”ÆÜ(5Y¹Ì‹vú /}Þûk´a‡ã/€\ó¢¨e‰…ê%ׇEK˜q=º¡;.›ê2´W^ù«ÛÓì-û<æ±P‹rü/…QDJ[ÙÏo  o ·Õ£l¦|·Íý~êp¥Õ“ª|© Ò³|y†¶²ÑùÊîÚÝRsY/¤¨õèR÷2ÉIŒ½'4?n>â&;Ôfî^0¬>•a‡½RJk«Ç°Ô *Z¸×kW®µŠÇYd“–÷rW5)#µ}ïj g°Í¼Ó€Hɲ÷+9iœ4Ž#Çn­v„G¬èìÔÃÀ••}È‹æ$´÷„±Žmnª\ºGxyÞ q<è#WŠé¥{O>WßV¾!«º'ºo3'¸ñ·´›³kÇ¡è%èVë@û¾jœºág´BYy‰3.¬ÅØ››óÈ©ÔO,AÏ¥# ;§˜%¾UÇtË´§;7*íçqˆâîl5RÇí“€Ѿ⒒/_¶ºïVu]i Þe_Íu ’ÓÞ»îÝf3@6.îâØy¥0oWNÚ–óCÉç¼nw`žß1CÓ—F.Þ§ä]¸kZx³ ho_îLûka¹ä áÉ3o¼Û6K>v¦ô/)éçå̉Gnï¦j¢-V¥{¤‹bç¢ê|(îxOk‰#iOÍétÊ]ëѸ¹eêvܱ\ šÅ³°Z¬¥¯™^μڸÖgÙÓ†Ñí§Šà®@NŠbíÏîí½[¶qp>É\‡%ÂñªÌ±ÚÝâµ¥…>ÀÕ©ÁC•unXÂ75"‘ÚTrMpfgNìMRù“Zn+°sGÃQ¦õê$RS­d¯\½£†ïw5ždãj˜PíùÁ«IåQ›Å׫st.­ L}qä2õ N¡kG«sfzûÕá`PáO+ئ5¬¯”˜Û<’œQ d5-`³yTT\ÍÛ)×ºŽ±µÖ°½ zÚÇ}SƒA£Îî­Ì•3ª]X‚ЬÁ„]åp¥Ã«Ò\Ñ£ˆd[ «És´é¾®1䍨™gSZŒ¡»²­$8égÓÈUï´lêÙº!ôŃÅç®k7¹ÛkzCGÎÕ;¯+òysŪfŠ]Ö§HË;‘ŠnS9ÙÅÜ!=›,êô{$ô§Z³Q„廾‡¬Ëò>xW2+Qi ÷²é‘q©PÙçHµWZvæñoinAö·{ã܂н[9q÷@„o Ñä(ë®îg“°)Ù¦ö5³Œ¯i÷qÔˆ8Ÿ(;H™ 4Ûß¼N”•†]¬öÎ;EmžSáéôè¤M{­S}´í[CB”ê+ɯ Œã/¨X"`ãŹ¬êØ ]Ù¤ÕÝ‚7©ZˆBê HÇŠ(R¶¶ ÝUI—Å<ÓU·/$Õ„4`9JD åc—iœ£œí¸ÙU`Ëôh¥Tgî2 èA]¸,´3n®‡3PhÐÞ-«¸žo P”^Ü© VºEÚ|+ÞÛ7yö%—À#éG°ŒVžd3–uìÁ Q¬¤Ìê¼ Û¯Hqµ½Ë­Î)æöÃÙÄèåÈcÔöÆ-Û#«@´²igkN ¡'+¯§¼ý´|ó‡B½2š®ìbéîe®qâëFñR‰¬Úé²ío]¸ÌÊÃoÀ½öý¹AwP.À íÈ«/%­a½9¹^͵Dº1Š3®>$ª&LeÇXIMg]F?fgî¾”}â˜/}U×, †^mJÛ ;E‹í™—iÉ¢ Žº»"S—`Þ®ì »Âc—»ìÚh N;öÓt… ëÖ^ ¸šOWµòg·mÊ{rÓ{×QAQÏpK1äÛÓÕ–U#?º™PD*¾óFûjê_DªîΓ8 Þ¡„£ã~Yà]‹6)øÎÒ¹ûŸ[;q¦ñ­ j¦ä¹BojÝ/âņ·˜æyv-²¯Vñ5t÷ƒžéS*û]{دH¬ªiÓYš…UÖVaZ¯{A¤9®S™‘Î9*v`¸p:’3kÆ·{(é-Lã{—óåà½ŠŠºÛåÒøap>öK\¥ùCQð=½)"éÅÃK³Zãdä8…öÞbeDNmµ‘À웼èW,ìñš”}¾™áðŒ,c l!KÀ¿wž›ËwfÌqn`kÐíœÍ+‰•žáêàl½êº=Ñ+¶B÷ܬ5Ñ»zÝÙO¸³e›Zþdç à”¤÷lvÝtPh·N•öÖ«M%1ü]Ò ‹^ân…gG郛gxöËìzQé67Û² ѰZ¬k‡v…åÂÍõ{Õ£hOfbÓ [Vè½=¸j²uÆ|—§«|=—ZOk[¦¹NW1é õ[ÖâÌÔ©òµÝB”\ÜwÚèÛ³isý†e…½ïX*ÆþÂ)êêk‘Çj­Òçs4à†ð~êßiñº±é«’Bs™Mì­ êjð«Ï0hnbÓØÃî¥nI\'hq®*»¡«ÑXä˜f¡æ´n1Ýü·´PÏT§ÛC`wˆÐùÐY±îÕÊé’›jT-ãÁå{نܡ¹ÌÁ·¶Ûß»p—ÕŽHnJ¿_)+ÌðM[ÊV´š;›C:;rä«w'[XÛ×A†ñÞì0q.÷ïÞ­QŽë€I‘VïA 1ê;s0`\€öoºÚ¸œ"újçpÕ¥š¨nßPv„ïç‡îmªz±ôÑ=îNÅkTTÉ'×dÈ/™Ç ³C»p®é|®ŒÁ´ªì½{),SlVšQÅc@ex¸=Âefä{(¨&)½~TÔ}*׺Þî÷«Ý¶=žŒÊQ¹ãÜæ#/kÞ©‡ÞTƒœåFa°ù³©¯JºÑÞT½,î¶à«Ç—×v[æU@¨ *9Ùu.õAwtÚez!ŒeëÕÎÜõ%C¯^J²‚ÊÙhîç_ºÍûäe.é·ž÷f=ï:÷ΉÑ.5Á&Ñ»pn…ÚÊ*¸²øõ‹»Z«²š›•6ò®—Ï¥LœìŽ*¶?[–r±WÌ#™\ûXSXü{o{(}_}[”$­SJ«Wâð‚Iã¾@gì©”ÅÃcÛBîFˆ-rA|ÇÚÌ;ƒ¤jãä27oeÞ}›HÓ—¹yNk·’EMRFoH»y±Øþ}ÝV³°T¡á^>}yƒ9¹ÂU=;ÅJ…[çÎFZzémà|N.ѱz,E¸XœÜâHæ8õKÝW¢fâpìÇ@›$`OƒxUÊx°á­ ˜rø¬—Ç"UdXj k…k¡®†Z¥}ðŠPÂ^ IÞZt2Ý꽑ÄrN´ vƒ‚–{Y­¡œ²¬k|>n·S@6ìÖ[R¶¡ÌF/¶#†ÿcóå^Us;µõR›t¯´í&iÏ‘sзè³Îk›§®³·¥g ÁK9©²Å™JX"×›N»³q.¡×”Å{îíÀ¹X{¦hvM`5JVÓÞñ aE"—^âÌÏ?½æ}iBΈ¥8Ww]ÐÛ†>’er·\óÕì&—¸žÐŽà¿±vã×n‚ºHË„#¿0A£A?ä½<ñÆ,˜3%éU/Ù‡Ú¢Ãh¯-)öžb¾Pºær®3 ©ÙŽÝM”¾·\ª:ÞÜUÊ”H\O³SÐð{~Æ%Ù†)÷Lõ÷· î«r_w¼›Œâ¤Ä„ÔËë÷½ïR°‹+Y{¼,3oú$ï""§«Û¹„¤ ¬É¨vƒ‰3‘×Wb=É~S—|5ûÍÓ­vÅÁ»ˆ-Ô[®zOËC6_›1Ôê¿fùŸ»¡B]\iq‚†L®»JO¨ÅºÚ»Û}+¦ëu¤zß[ìØq_3½Àíì)ã–NHUl(PÕä†t¯V޶¬kÙCvÓ´2Y§‚·Ï=íU+V+ë**ï€Æû«y2V+Þ˜8Ð è-Ú³²°ˆ°7ÝÉ ·µ{a‚Ía8„‰)&7W&zÊùUîñÔ$Y;›æ[fµ_I¶¸MGz»Œ]ƒMo»Û#¥#©ÙÍóÅäQy¦ÓÇ ^_{6‡ÓËŒXe]Ê9Ò·Õ„k¼n€¢B Æùõªá¼)}âpkêU¿7ÒæŽÕ¾Åè—s,”fÎ㼑s¬c¡Ô=´‚Û¯lH[ö7··}xϲ ˆÄf_™Èé«&«K,j|ºtg†vt­ËBŸrÁµ¨õ©3i±C‹¹à—¢£nx+§\Fß:¶à«¬§äþ,÷·3X:›à8_8ŸÌY«Žlé–Gzê}@šf“^[šŸW—erÞSîv.¾ár•]mNè¡(øÜ€íœ^4‡ôy«…&}Â]à¢êÆÜ³Êùü,»qè)"”è¯eòä.m ÅÖÇü}ZøÚ£­Ú AQyˆ£v›ynb¹5eå¼á1åO µqjõôžÐPô>ë‘"LšrÎÏ=ï^÷;¥'j·’SrS8 ¾4·Ü‹êÙ fyW åŒØ`ÔL˜À%˜±½‹Úˆv.7|®"{s®Þ[(u2†©±ëܽ YZž8r0Þærž¢Öãºæçw¦% ã°1©.žÏmYßuû,u!~ÛÍ^V{¿‘æ’ž'Ž~×îÞßÞRÕR'I–¦øY^˜Ñô©§»Tw:“£'¹é‘ì­bï GÍs Ï®Hn…Ñ&à½Yí;s˽SÌîðB‡X>å•/¨6¬\Y²¬Ø¬[¤ŽH6%­ê†Zyƒ]3:%HÛY˜‘g5ê«8xåf<Þ“s;¨Všæ9Ò$ñ´¼¡ëlòÝ Ù›o QÎ&It›êÖìê×^ù”O`®-»©‹&®óYòž Vm¾°•ŒØX/Ò]éz<š¦7íõÜ}fŠ41—†Ãâ)ƒ}3M€7–î=XëY¬¢i#µmãw†.àKÄUíô7F‡[k*ï„›” ’ŽÛÅa‘fJÐ%Hë:k„®íK¸ÍÚÂnzùóõc<»uK&†5 Ü5á³»*D•;n=žÕ*èK÷‚ÕÖò{:m`ïgÞ „.^‡«•è^R ì"iûAÖ°¾˜âÝ6%¾DÍG|Û/.AÓ Q‚,brÕŽ´:©¨A;:"W-rСÝ{ØaVx§ZÏ7»–ŸD5^šc9EÁ)ƒ-öƒ±½\ ¬sŽ©ÝïJ·Ádqj®Xñµ^®ÏUÞi쥋s ¯Y 'Ä soÓ%õºÙ[Ëu˜·-öPÖ“³n³mmÍòn Õ4åWjp¶¬Õo 5½'¬~ƒÁò§~‚}ò½Ê&¹vM[«ÈzÛÝ2ïÚÎ »”*ëÎÙÌ}aÃu‹¤ÑØ1öìú ÚºA§/Ÿa¼ÛoyÁ6}5Ðã½ÖTu™Ëm¡uÒd|¼qZ–2yŽ» µÒ0Ô¦í8š±éÛsÛikHõ[„Á|CºXÆ»Þñª×~ço³·bÐÌÙPÓ lØsLù__u(cEãºñá›Îë¶s¼qMû«,òÞOÁ'OL7ävXPìÜ4LÝᎀìóu$W«eùÉž>Þ¦@S÷½^…¬í9¼1(ö’"a&ÃÆ0-7‚`k¤Uù·Áhiw0+óYÕû_ï_ „‡åÛõÃGDõ¦nÆÂŠC¼¤$—w›%Ù¡XžØM1”ô,êÁ[ÞžrëÑ<¥^T“ßbÙÛÁVhA6“èºý†Ò~W¯Í†J“× ¿®—`Óî\ZÆnšÞNƒº&n=̬N×`o&ð^`DjV©kìrÖâî­ÌLWj‚JMÓÓ¦2º‡gEAk d;[=7^«o'˵Uñ°¬Œ+/Z—:=)íß¼µ½g¤Àq12pA»õг¹êê{mõffxjÅ̳ˆ@d$»ÅVíXÍHéÛm¡m²Õ#—zGgƒÖ¨½ÖgWvƒçë&;ÝÆm-ÇkÑZXbî³ ÑkìѲ^­{¡ÇcŒD«; õ‚Ì¥™nÊéOLéZ²Çoe®Æ_uo7g¹6Së\vØ»àp1Ý(\Sƒ‡dy}fmÊÅmÚSYêU´7î§}r_lvR:þIöWA…qKÚ8/8íj¶J{…Š!¥­+ŽW!Í+»u¢mãŸ8ÚhÍ,WÖxµ#Y•Âì ˜Èž£wu„Pø!ݨ11¤ºöñj“ÌvðV6ðº}‘rÔµ"Oë®] ¹Vlç½¹y;)A:ø½W¹±»Dq>®Õ+ É1ë?Ep·ÝHõŸ£.œ—¯u€ø]ºº ØÝájºž,Ë”ƒ¹·7)ÔÙ¿·`¥Ct#±lSO’_x{VN*öèz5ùó>ïÖúÅ*µ{*ËñŽÞúâíEÔìýth§WµïGѱٸs ‹w ‹5s½:ûëqË“»jÄhÑ\zpóOw‘ö†™²Þv«Ü^[ÛtÛem.ÎNç ìp.wEÌ»ã©ôè3±ZÑ!|»¶#Ú¡¼=–‘W„nry×wÍÕªhjsrà%ω¦ÆìÓ‡sÓ…Êã¨øí¸þzî?d&· ^E÷¬@Õ› X²!WY¡õ¾­õ#—+¢‹„f8z•Ò%y½´Ì|Û¹EÔŒ™ZÙßayÙ3Šaz ¶½»Ë;±%AºM‹ê×XÖ€ÀŒßešÌØ’é·Š‹æa|©x¶74“¿ÃåĺΠ=ô:¼iÝÅ„®èßW¦SßèÚ¸“$¿ ÔEúÖŠ‡ê›Ey:6®¯°w»%êëãYS¢àe^û51½NìX캵Rpµ\Ý…ní™Â…eF;+u¦ë)­‹§Ýq;v%sÛCŒ7ªSÞÆúvÖŒƒgg>ìÛ¾e&ëqe”ë»Ã7£¼º+ºØ»yÛ¥1 ÷hÔ\võá(®­޲¢íç 2ïžëÛ•¨KÞ“whË¡gb¬K­[w1èrÖªWò¤B®§MNºWÁÙˆN£ß<±|øè& 9 e]o"ðÓi^npg¤¬S®îé¤N#rÜyЈXê!æ ¾VûB|¤(h]-mòÈ’ŒO)5Û+2“Ç7ëBЉT§ÏpeQ—ÁmL‚ˆHïDò•_ÌvòRÕÊ4ô`3‚˜ «;nlžœd­(¬/ŠxôD\@ÁX×FíÂHÏ¡A[åb1ôã´é‹ÚËЧymÀ¸X£†½C¼áŽ]Á¦°…¢ü¯¸ïÛžl=sã×eå}ÛÄ |8à×]êZ$¯ëD[n¸ë5Ò·áÁ:{zàÍF’TαÚo€œ²™U¶÷³7]PcûµÖ=Iàå¶_sÎ1¥YƲe’‚IuÃ6×wò•%ëvRå ™0æÿ€Åju—ñ_²– ’¡Æ4\›âkk3ÍX\Y`ˆ¼ÊHn(Sž2>:›Õ]ÀÖKC ó.uŒ²t!+ÂöJzóqu_i^-oÁ ‘gey?=;·Îd…3ØÉöΤG»dö›ÑGN`§K1‹ç”Z%Ð,®“ˆ]¶µmó•9JbîÝ03…®Yœ_Që£4–^XiâÎ}µÎ—tÛX’ÁoimIÕb·aÔ€5 ‘œ¹_øÄ~ß?ÞñgôýφÍ]0vó5­OÙ·Ù9%…%à)Œà‘íRš’¿sYC–?Zã~KR+ .>W'FÖöyõg ÀL½WÞK&TcoÙ¤vêœé<‚êHŠ*Þ·k×mU¾[Þ¤}êÍLíãSÍnE\å’ªR¯‹ìusNÝÛ¯4ZX&½ rrÜ¡bûx^ƒlšÅ"7b±—Pê·9ÝݹϺK,bÞ6«Ó¼ãíÄ`¡^,:q6,»ÒÂÅ[¼Ô=œ(uìí‹Ìûu6x£©¡^ÓØ¢–ÊÛkxöd$Ù =×R´‹ãj½é{‹mAVè´ójê Ø9½^Õâü;{­ß† ³Ž=íܤî\¢ãpÛ>Ïz1¡Öu«¹ç´E-ïnûîd÷P8|¶ À ÊÖK¾-鈜áÔgnÍŠ|°Öà­”è=‚‘câ9Š)x»Î÷v¡~ï?±]F‹©1ï¡ÆÝõå{Å1aûcëè²ghºÍ¸E U‡E¥Í©q´²ûM%ñê©åp]—w(we7!ª"ŠŸuîãY–ŽR•6íòŒmlÇâ-e1ª¶L—Û¼˜£íÓÊL’áÛ]íµÛ›½KUD€ôŸAfë¯ÛÎnAS{VW´«ê¸©àåNZGÚ+`³~¸Â¼Û ÀUßëIŒêÌȩ̂±^ç’‘cï=ÞÇ‚)ܵÎûl¦JR±O;ã<[3ÞFƒ,#Zåº7[._P—=‰ó9ÒlÌ>¡C;›¦Mfä«wkP'Îøjëòb{6Cš…¥xêÛÏ9SÛ·ßr _WH¡NÅéìµDuÇ)ƒÕtÙê rh[[Wª¼Ñ¯rÛÔù‘À¶ø ]*ÂÑ-ƒvsUÝaÄcѪr•ŽNGeøN鹸+Ê0iùL[šý§·fvÛ1(E‰Ë*Pë¯^ý»Þ8½]g¦)žÓ(?—¨?“n/kíé›%Ý)‰*¾£\Ur°Æ¯EÚÂÍ |[”ÙfFJÅÇ -%›ê(½%²LÇQP§‹+¡»”j rÊÖ·aÊ“M—! ëݺKµ­J¸w-1;r‘îl6¥¤Fphîm,1+Ü1§›öÜâªÝBª‹d†æï)aO£¤ßÖŽuÓ<å ¹UÉ—\8ä é¥ËÕ}eîšé¢E}>çÒñºPy=Ê{~«ŽšÓ]cg¼ú†Ñ7HŒÆ˜ÛîºõôcqWmhæ¼õ¿MÍr’—S)ñC 3·VhÛ"ùpDjÆï–øg»C—@ü^²Øõ2i«;TSz·|å.Êñà/]”ÌÙ‘ª¸;Ù¸Þk4ù}rÏ /.ø]I|®øNçZ{¡ÀCòkq÷."§P(Wž¤}CS¦žgŽGg'Çn»Žü­2c6ÃÛpMˆCdÈÕ¾Ñ o;)iûŸ¦¤Î½Ÿ"¶›A޲Õ' ©¬fGÛš¤FÆDö@Eov%J{Üí¸Élý„kulQGÇbÍ)xbûÙ] wujêòÑkÊW"’¬•&é`qîJæ¬=-mkв‚ÅñÚÂx ©¹á¥û°`î¥{r5iŽ?w-iäoae:ë«+etÖ.Y»¾ØWãºFq:êà[^á •Ý5Öé¸8Khj¸o9r^ñî´vËpx¿^¿V_4÷dòî¾³|c±ïSìô#Å ¬¨¬óÜ£uª¤ÇÖyñ]ÕÜo=ä]¾Íg%ßiçÅXÙd¸Ïs® V \ÊL Ç%êâEå¬Ç"Û Æ7Æï¶²[ÔÞšw©ShT®­Ì2ЮA»Ç´²®Q›n`C&ζêÈt†õÕaƒIJ;¾R÷Im,AO°écŸ1zü÷y?dHwYÛŽ5w¸AV­žƒÏÖ•ÚÕ–ç*1J~ qk°µ9CŸ¦{س½‚—³Õ—ë‹ίÜ-Rö‡G½¹:u¸ñt3éŸvV:bň'T³ZõàÝTú5@VlºÉ¢Œ½Z–‹½¬©*;¡ÄjœªÐ!‹†êÍ»´¹õ›z„ë÷¦±Pe c•Ø®EŠ·‹M½3çŠòdu¼»˜åÄõëʘ놅Ðv´4å·MæuÍ •[ 5½¥žÕf·+`[ÊÚsw0AXˆ†¦ÌSiZ3+m÷>»Æž(*'OµÔ`†%qº„Ø x^ˆÚº¾w,ìr3®+ÊTòúæ>’>3‹X+Eíæ÷;ÕiƒpGaÔ`ºûŒ¤f’¨ŠœzsÙ—o™¤ú\~¯Á¤Éôé!Ïep7fù­Ç¸hóÿ»sCke<ôq5o±T¾¢w¬ìÝ6VŒ»èr >³ÂåcºRwbÒH*Ö‰®ðUÓ"S)lnº´ÔÁ7»¸fZÙ- KZ¶\¨¨Mwsó¿vítQãÜwŽx!²×6,K©Œ@Ddui­C0ê¡€ÖÝ:]Ý:g>…ž¾ºtÔ®# mÖÞ‰¼\´ä˶ªùb¥R–=ß|ÝÆ 6àÀý ½eÄŒ9¶Ù[§ Y2•Ÿ,«û]F¯ŠqóïŸ,NæKZú’+@ËÍ•}'yzíR˜_ÃÊLiï®]Mñ°ªað|¦;>-mâ[«1L¬>Õ%ÇBfUëâWÔ6ð,C 2‰ éŽ5È®cMÑ@îƒÇÏÔăÚÖÖUå^õÂé[‹ËE©açcÆÑf†NÎöÝü‡ÝïxhÕ^ßB2m Ê6½ž4ºS\æ8žÅ`ÌË€ªWÕá—p`Žf ¡VóMxûÝg"]ËÔ)TØk*_qÉ÷\62Žw·Él,“àñvféëc²@;·‰ÜpW<I܆>je–_ywJ^uÞLÚÑá«ÚÆÔ[ØëE¥G«QRͺ™)¢Ø^ä°¸¤óÔ/*†Õ¬·©RxîK€ªÞ4ÙÖî`½Ü ;©‡9dœ«tÑâõ5Þé¼q5ܫ󡂶ö§ê wÝÖ0ï¦uÃ[1kùÓÙf^¾JѬÝ«,²÷Cêw½t,œ7ö´$úÛŽ¯±šµ(Y·ÖEðt$”îu_];öç8­u¯kŒõm•‡Ê= Óë<܃1\Û#Ztêjsäï(±Ó:aSµnÛˆqöÒ¤7½ëÜÖÜ¿WiܤДu ïÅz¡l‰WbÍnBˆÂîɸ%ÇœÅq«ùt–A48aS·7Xó™Ñ›+´w7ÈÔ£OffjÚÁ\®KÎ4¶yÒ¢»ƒð‹56ÚUˆb%ØžëZ”“Ž5$•Ãi—˜\«5áÀ¾–xåvs‹ @/V彸ZQ=–Ú¨×}ݪÆÍiO6AY´.ÌñŒQ¾¦‘C“‘|޼ÔKv©>Ì""x² µyA»/V\4èLçk9îŽ}lt¬ê[ñÎ-¡Ø3iw7¯/ä—›´kµŽ”8çjó"óºœÇ<"§rÎá™͉XjE²™ëé4Šèû¶É». C|àò7êšòJv7/˜7šBOô­­îhÊO®ÌNG9Š(æÊƒçÙÅž·š'ºfѰ_zÛçœ5·8nìX» æ;©\ŒP»Ç»Ì™ÓªøÅ¾ïwžÇ4ÃY˜ÍÃëå÷°ñ‡ØýÀkt´ É\¡\<æZ$¾øšÚW½j¼Ètý•  ò|ß´-wƒn@R[EåÁíìÁÑOk› YBß5;»ÚÜÜ&‰E¤kR@öœ[Ô}·ÃÀÓ _X]Éç¦MÌÄóAŠÉ9¾õ†VúRð®ã@=ê}s¤O-s’·*\StS È0wKøÞï@e"Z&=~`*ö\¼½&díšö²yíxUÓ®™´æÖ^Þ£Ü÷G…QÞ=ãS¥¸¨âÜ œÏEu'³µµÕ©æÛÚí˜ÅÁZÝKÝû³|ç¶_W{Rf½N R+K]f{(KoµŽLDK>|"öÀ¹£¹¹9Ìo'io¯iÅ+šé}JRUo~á¥ÌS:Ã=žŽ™ÞÖéRž0-ű3”@»6|òÕ9jèØwÅG×&ʾÓÔùu§wšò묰²¹<;/ŽáY¥&ÁÏm»rL½êÓWE;ÚuQC®¥›÷Iqäv¹×׆¨ýð¹£ÄVåíE¦šQÒÉ—ôF”½ßr@ XŒ&¤«k°8îášA@:pÛ}’Räxv¼npº¼Í*R‹ÖûÙdqá“®®â* Y¦\6™Z–:Y©õmY ±Žçìmõy™ ¦yfï=®¿E‰^T˜êPØf`¥›põ×Nö*Ì_Kªx{~3H¤,IJvάæö…æÍx1_ôn¯®S»ŸÀr>Ù) 46®-¸û)¾È²?+,{|Eº» ÅÇžó¾Þ³½w–Ði j ºCwFֺͧåNµu½u´³;•@ŠK0ûÔ±h«ô'dÖô¿Sïx…ÒY#)½òÚy^Ó€_]l™]wxGIŽC‡Ðë šé½,hO#†`£ƒ2ïw•£à¶»‰@§„§u}ù.pYºò‡«¤1†(Ú[&ö¶ŒÛÇ~UÕÎzb9Ø72ElhBÞ_J¢Ë(0Y¶…^Ôã¸24·'˜m\¥0ð­1õ^4M‹êW,¬5—tŸ9ÊFôj¥a˽ÙGir´t!Ÿ Qæˆ «Ô KÆaW!Åx·+ ò5³ *_8ÆÄ-gK¦zT ì¬^ „ß鮦ʉŽ2Ùk´föüOt›Ýw=¬¼éÙ\El)p"ú­õšë¶-Ǹzû¹¾íÛõOnn)pT5*õ×It¥”DÒ×E¯·ME¬33휡…-¾œ&Ìæn¥ªµƒsÊTWÃ,«ÄÅpfögÊÉ{*w'…àédyÄ›dVncS¯õò5¿7œR=Õ¥¸Ù2_ÑàvÀ¦xC)ìo{Yf»£×uv9eà ­Ýo7X ^§³VTñw~Òü3+‡Œñ©bô©BWwRÙDç”ðD½<®§!ؽT‘mºïZˆØÌÊÀñ¨ýWáKr—Œ•äv÷™­‹Ú$e)ì§7*ûØû9ÛlÚEbua®‰² £¹› 6wÙ‰ï ¬¤Ö‰Bµ¨zl›1ªòÞÕhêÛ»<õž’ºlʸgÍÏâ­­÷x55Ê}ø5ºd˜ßc£”¿f§¨©¦º ‹×·yŽ¥uÍ{_j]¢6·MÁF÷å…OAƒ#®˜”-ó*´õ+ëêùIÁNE¦íîñë¾A{¦ã¾ê~+dsšÊóŠóÁgÎO·’gg;+l‘ºf•¥ÙÐ÷1Rã.¡çs&gš#·ÏÍË¥BChm$;zÌJ8Kï=²ô9çà]µ€ÞÐxí)„dböì¶is‘™†˜éâγoe@’¯pãk±ÖX.Œ¦r°u…ôà‚^Hõfy÷®?.b,,…Wc“ÐqZSŸL©6eóYµjƒ)ØY×Ô%ñÊ“VV» ³%šÃ×ǘۥ. wIŠçh{œ§gdzD̊㱕Ôüôñ¡ë£gÄå•sÞ´©N4:9ÞºÒÁ›}¼ŒoYc0}ÞY·H›sËŒ°ù1[|“3Py´GCƒŒyËGÑ…Ž§ëå`ïy[gð’j‚¾ò`Q"7€µ*p»ZÖ3qcµ+…m¡’bÌëä(b.¸mÍÜÎ{-"Áåí~ôó«yc{îTÁÓAûÝ:q½5hò0P¾ÈèNA>$Ôö êò}cVW¤ÛJðr¾HÑcŸr§ÓŠí؉ZËíN˜¾Ú=ŽÊ±]` ó*éX <®ºodškl8µÏˆ.nOÞç¦ì·¬yŸ=®ºÌ•(]#)f›µJW!fÝ»CšYÃL†]¹zò¤„•Âæ­iç[Þc»¬Ð­ñ/`lÞ•`w„¨lÒ.z&òÙ¢ ‹Æ¢éS´Nȼɘ6»2sfƒK5¦ ‰½·•3î.±,Ý -ó*âô⥾´M)~.]u™n¦'{*Q:EÊd#J²]Šrå¸k4ç'@bU·¡RO8n©ºPpQ­¸„žíèøA€‹‡[ხïlä +lcW|òT׫s¸N§E§·|qS•¢£àÎyv:•õoêYêsŒPV{°ÖÏQ2.AlÓ¢i|ð`¹}\Õy˜U·S™x^¯{¤»£I%•MºÖ3…B@åë®óaªÆsì-Z«Û,tÁ%¹[Q™iÔDõ¸69c岈9•vÑrþh¯E†Žó±·LíAÌ_Åamˆ åëµ[Ep¸Áá@KÏVúš—|U‹~ÈžÐø³÷’M±Ê=ÚcßryI²m»)îe»¥[ÛN¯wF*$4V&Ú@¾U«Ë/ïvº·;·G¼2–èiõço+{68° ‰yÝà“ÔG«1ÞÔöêÑÞå«$B‚¨é¾Éâyõ欭NyÏvçÉÍ"…„7J"pÒ©˜”²ªniÌPõÜ3r:œä®¸>£Š^™†¥rĪj"i%Rfz¦ß-¥4Ìœ·³NÐl%¢¶™gež*,\¢o-cCƒËÒ9-bhÀ bòæ^Ò%ÔfðæÈ» ·Is1b¤ã·rå,T»j!!Ú·µ<¶DvÌ4d5=¬‡åæÌ@^Ûﳆ»Ûí¾ì4Tèôh j±q+WyÔ¬ qæ>æzãªÛÇn"ä–Þvs+yIRÔeë)ÃMnR,_v áënR4LRz¡Eû§9°LÌ(u”‘Çj¥÷tìͶ#ÏbmUš>ÉåûôÀ@±yûcý….¿±eÔ£BÈ£GÓ\y!]Kž=4мJb_w]>y}D»—®µ­¥DÒ}]ѹ š%A:ðœÝ™H—|>qœÍƒ¦ã¹ê™y™{HßyòÚa·µ¾ö¸Êž½wç¸zìU­)½-–·±©|ÚVØ„¥ÜguÛ™ #Cd„ûËO°g‹h4ÃK‘eÏnÏ!t;°õ=ÌÖºÕ_eƒ*PYº7¸­6yvÝe{àMÖÒUîI ·ÝQ:¹—sÀûGy‘µµE/*ݰà^$NG»3¬w?'Ý’9§¢¡BœOU;ß]EÑ’nÅ/mäÈíø\ÆÆ×‚óËÞ•ÔuØtÖ‰ÓK_lÁÙ“#*úÅâ òR¯dT{³7ÞgÝ5NQÝšu·ŽÞ.¹X;î3@Àæ+xô•Öì²cÇ;]uô/v‘žÎºŽÎº—uì¾Ë:ׂ¡NcÆVËà°ìGpÕëq*ìºÂ‘Ö±zµ µ, óÛ´*m6­cb™TÆ(w§h²()¢M8F!u”Q]X3/­`G™¾oå/cyÙ¡ãË2¹Ú0°k‘d¤]^xh×M[W<¶G–ß“•›¬Ÿ=µ °ÆßÊôS׊L—C#8Ëõ*#ÁÀíú‘µ=å/7j¢[eÁ1é­|©Ž•ÙÙ”°‹GBMAŸâöÝØÇV¦Äk%]ð³)ì”óžù¤:kÞ ëŽqT7ÇKÆN»Ë›bÅ*Tù¼9ñéu쥂À=7 uèÑdÚÝI·öàĵãë¾Ö,f U¼hª/–;™VŸ9)»ë Ì Q¾\œébvº=·³(åóØÛ.é‘Ë[O^ªÁ‡ ^å±¢'oÝHåõ©})cì­J(§…öc@ñµòôŒz£¯T>Êf{<³2•–QzðáˤhèÎ.¹ÒUö§•Ùë26ß[‘EÈ8g¿a~"y|o7 Ð_¿P+óI­[ºØK‰]´ï²¹zseÓ./[ŸF¤öìgeú+ï)#É][Ùˆ‹¼¹b~îêoŸ<(›Ã¨Y# Û΋Ÿ3µD>Hï`tÈmá#¶V·Cü3x[®Û«%sŒum˜[áJž¥LKúûMãä‡R*ÃÍtžë¶€Xupµ šM¥#œŽÃ*<@å×Ò‰ÌáÙƒÍå[­‘A¥Ô 4ÕA 2Î첚ð|¶¶›êÀ+» {»"„H¨,Ó'n ¾4•\t©r9xžpJÕ½eZƒÊ¹/ך1` -nýqwÒ8Þ'—ªe@Ý\À†xÕn0+È€^›.¡Ôй$t÷£i5w,`8GVwÕ’u½ÈƺR|þÛ ]¼ÁyÀ¬H_,Ðjc¨R—03%ªSxKÞÅ´›å=çÆXöøÒ®ÂðPêÚ.Ì«6*{‰àž^Òã“rXXîq²½åµìÏ(ï[Ë7/½tt^o˜ D|/=לövù9SCnÉ·¯hÌ¢¨Å~81ä«ÉX ½ƒªkH÷qσq¥†·"mÖªb!··/‚ç©kì»C·.ЦRáB:Ê=c±žÓ†ü—<žZw‚¹îêcs€²';Í ÝxBƒì“r½ä³Nê²ÖD1Y —Ùƒv ¸…Y$ Û ®Œòa›¡¬Ph˜ŽNáK JÝÕæïƒy@W_ íЩ¿I^¯ÎìbÍ;Ø¡W¡…Z¯{ 3Ô&õY™6µ~÷ëÔÔT2åmz°ÔÞsÙ ¬±— •»Ä}‰V "¦óÍuÒÝI>*×Kæ§Vœ¯ƒÎ*Û ßjëBè,¬°«2Z9:Œ=G˜ÙyNšF× ùIù÷¡—OÝ^¤•·¸òŽŠåb}˜¬‘2»›½^×Ú5±½ï1Y•fdGõnóªës«ë-ĺ¸êìÔñ“’µ Ð ]3$16—è«+ñã~ GîŹ_³†Ë1^doòÃ]Á‡èÓ•lÅ ^¡b³5ìߘiÖ¸7 åÔ2ðq*sfTD»¸eáœäž7:×o. † ­¤zÚÞ$µ‹WKæXvŸË‹ØÔº›] lJèiclº× ¼O†V´ÈÛÛ7ÉÊùNêÖ39‹àË'“¶ŽÛÝ5‹®Ó³ nbà´Gnõç8ÕʾȲÁœªÂ u^Ô}©Y3s e6èkîsx"í¶Çc;9^þ®ËPûˆ¥¢œÀ˜gWZß*Û}´%½ØÚÛËß¾ŸLE"‡!dÕ¢RÛ9¢ë Ö¢ôhÚ©†]I@$ºæÎÍêîó+]ÝkîRó¿f.ÞTB¢ÿ2ÅpËü?B{ñVщœÉ¾·z,¯.•ØÀ­¤JçAÚ• ;bX5b†áêpè'NoPSH5"¦pŒ*ý¹”ö‹êûjЊfz“ͲëÔ_¹çUÍv»¶Œ®LGÏ,kðŠµØ7Ñêg'ÒÕÛ v¦¿EGÙé}íZàRÄ»ü@wcë~[pݾ±%Ë ð²ù9ƒ]3{NŒè¬G´·Ã—TλIH(ó»Áݪ¬ëÕEö1Vq­ ;3‘IÍns®Çm¶¹Þç;á»q·”è Ç_\4k~fíw ±q ˜°rÕÕî"šÎ~~ñ8qNøÉC‹}õ»Ëí`º"¶³_ÊŠ±—W•dÜ÷¡2C´^Xêʆ蛄ئ„Ú{ut1ǾØéÌø3I9|׆ߩW¸Í<ªî“»ßV« 5[E†~ÚòשŽy-ªë»XžÔ³¶ë8·EM4Ùõ:µ+½™½AìÏ™9w“MfqÉêB§š¨+SÝm®¹í_^é"j¼t&sÈo%jN@dWM XD• ™›(n@ؽÝWMrZ® ‹ræ™ÒÈt— Ú¸¨#³«tíèhao#udnÜÕλ™jnàLÚô3˜YvåØ}*ï{wtÜŠÚ¦µ¡/ÛÒ”aæ‚6ÃBˆxGwhIœ&Á™ÖòpË7‘V?‡@iÑÑÁ VFûmß/oxdÙ`´=Ò­&¯tVSJ½¡´ï:óNG¯%Ó;‰!ÁФö™×£¦Ú:ÕöàaLgËVåªs­d— `¸mꑵݲçon>Èú>‰Æ]a‹…ëÅ3ÞÀõ „ ¶pnº˜ÚòÚä®Í#³šu†%‰Š5‚rºÁ[Üa•®Pˆ3«”4‚±ÒÚ¦ò·NÔ—Y&”+ „N’áœmò –`ǯÚé^â¯s;_ ×êñ¿ÓÀoÃæÞsÝÃIáûÚ›ë£y#Û&6.8ZÞ°oVî*»p&ÌÎï+~v/o^JžËŠèR†¡¼Ý¨’–¯<¤ê¸Gœ:ྰ+Áðã’TdÑW•¼{¡íV…rD'GÛŽ]?këmv¬MuåI)³ØÎ±Ø­VbÖ¶ù¬Æ߆Ôò‰32®å'•ŽË¤æíÖ£8ïV½Êõfç¸è÷Špfs¤»DQæ˜G7£:bégÏÏ:&+Ú¶óÝÄæ¬ÜnDjHö²¯Ow<2ŸgœƒOx/„ö>pæ9š…ßfÒs}¯¯Å;åà{*hœý"¸l8Þk!çåË xëÈvšôu¾Îu¥¿Xõ.Å…•´U?ÂÃÎQëÝTÆ^¼0¹”àÊÇQéì2NÐ”áÆ 2„pl2ÍJM Ñaë­£§£U›W*B§R®ÁÖ«Ô> ´[†º·:än¸JÞ*öØ’žÐÓ¶O)[ÞË«:m-{¼ØFTëqF zk‘§ƒÝ™sRõГ×'e<´ß9Ô§mu”ñµ»$¯Jâsʽ½ï%ÛX+qŠzàβ|ücŒÖ,‹Æb×à†eY‚]u¸ÿ(¸oš17ë«ØžDÕv#'áû«˜­žj޳ö†ñxøúïcëNt´s¦|¹ªo!+ù¾“.†$Uä2í+rÕÌZI˜»¼¨ož_@šÁ¿‡¾EXì;nu³í&©ËZ¢»v³¸ƒ}vBkŠlše¡¬#Ræ u5š‚Æ8­¬UëâH€{|×O²½KÚǘ}ë÷€s 8döW&úïJYÕ¾¶º—R»zêãbö•ª–ó…ˆf‚J÷¨XjaXçaQ{n§·»–û#ïbn³^¬‚üÔñ8¯º'Gª:±à]Œs=v-Ù¾@y4°®I—zÀ¹ ãkÖË~å;θÒ姆ļF]w%Ýyº™´.¼ õëu‚äçS'EëÁÛYîšÈó–s÷´]=±;ÛÞéG »sಖm¼Áö¨ôLЀ£`¹ ‡,'²ÙãY’oË+A·¡RS¤íI¡ÚôƒK]-j4˜S†k‰Ð¦{ǻ͜a.ýEc1–˜±Ii)Ü kvl˜8¥›ì Ëƒ¥\ŠÇy¨Zˆ¸_O oŊབྷb# ] ›7^¼&û¦ÒžrnV祾½ÃÇQ«ϯo—²ʨ7ñrôÒÏ_«ÙRÔˆï‡6’8‡VËå‘uhÓÀ‡1›7¯¬Øˆ.ÓR)³·]Û$šôŠ»u*å]š¶5ùbŸY x0Ý‹é ʤæ1kTO[ȯnpíT„V2V½YD›Z©A´•2ŠT¯¦ã&+™SÒ–{<6F–äR_n¥Rø½Ñýp%žBp»®u“}šÀP^#Öõºßdˆ^ÖØd***›½úpõEÔüQÎ7é~Lßµ2'¬¼eεޑ/Ÿ7 -Ü•ìåƒbï¡£ÆÁîë¾ U¸û²ÂAa“MŠÏ{ÞT7‚ݱµÏÆËÞ¾UÃzŠ»¹`*{Z¦ýìxýÆVIÝ'¼†3èi#ã,]5|X/Ò¯+¼/XšõãD¬›¨Ý’ 9¨Þk]’ÛËžý¹<ÝñîžÐÕÂVqb€÷žû|É™Jý±ôƒ†nL d¾]Ô såk±_1bÂï²êma¬N^¬©‚¢oJ/5Mž3s[Á8d•ÖR½ê¾Ã\ #¨‡ídórò «ÜµÛÞBÍaÒ¬blæëz4¦ßK‰Páïg¸_g6²ò{t§Ë¹ìÖ¶¤}Ö&õM¬½ÜI+šòcÄCzÖ>Ä$Êtm:½êÔv»õêÝv{¡×\ƒ³Hu¯7’³¼‡\maÞ ÉE?díŽ+w]G}Ù¹Ltí ZõLy²2²…+U¬2³ÁN>cç½¥ï7¹áŒ’—Óz^Îíf˜¢e>2N•>ò½* »~¿gvz{ƒ´Áuæ±S%ï‡kõJ*36#—yœáÝŒÒ]Aõn]§»V(0ˆ¬oO J^ñ«6žSO‹´¯-1&E§XÁ‡fs o}Iõr£Ï{ŒW¥Ù;âSˆ»l¬½D/*ìÕÔ1¡‡›™`¨ÕZÁX”f–õÎìšxÞ©+7 œÀÁ«~ÀÎô L:*…_–“©M[b­´vïÞqß…sîÝÀ6k±­Lõ€°¾¸ûd®­Ð>¢yâïKJ…,ùòÁ ð=·ºÑå\îÆYC'_F­JŒl6®hB>µsGRA@¹ÝEÏ\êt3zÏ©w¼Ê¬pë:—ó sj< ¶ëŒO.˽¡À¤ÔÐ\ŠO&Æ F†Õ‚ªE†U¦"îniM¼™PìÔ—2MYJÅw†_Ü—½î±2žÊtߨÖ̸¸ªÙ+k¯‡й%µW6XnµP}%çv O÷\˧Žê<}Â^bãÍ{_VXæ®zõô€o¥]‘Kx,𨣅–XŒ ·š4»ãà˜g3hlì`jOæ¯/¨ýɃ†ޝ·¥L+ÛU´ È)võùþ/œµøbÊó÷æó,­Ú†›¾jç]CÄ”ëØCyŸ)qÚ•yù"ë[âñ/y4NÞ)û±Pâ§²XÛr͸ϔF9ã´6VkŠK²¶ìÓ—e b²Ù5-Þæ }ˆ+·­t¨R{^àå7å™Å#ð¯oK¶ò½)í󳛡6=Š›¤¾ƒ±h¡bΪì“ZÞÐ[ÃË„6”¿ËkFŒMu*í?xþ;ݻՖÃ4q¢‡‰š|Ö’ßuèçÕ†Û7hC¿Mõ©pÐMy^±¾ZŽ×Aä¯xË„(;F†»ÒNùd;;5ÌáJüÇ?œð:Ï[‘¼HnÇ[^=!Á¤vÊR®œ+Hp1öVÚîð=‚¬u:‡AÖv%ªý[|¾åÔ pimÁ—¾ã¢¸j8%ëŠòÎMõµêÒ}WH…ÒýÒY7h<ú)5ûÀ7O©ÂuD{w{g5»Úäµ9ú Î9ÊÐn³#ô'Z–ÊóíÅØÔÁ)×u¨h·ÃC¹÷( Ø-_w+Y¹-‚sITí)§n1ð>R­¬Ü™B]—0ºéÁ¹˜ù˜ûò8»Ç‡À$·/Ò®Ù°(»ËLW·D.š®‰Þz¹ußy Ñ£Ð™ŠøÝF—Îë–4L›~¸úÅ,µ™}I=qÒÚÞ½ç2£ ÝÒ”÷ !ÛèÊu{Ÿ=fJ·w®'X&KàœêJ¤Ìg”Ìèi1J´°îd²•ÒËÚòÕ{DW°¿GÔƒ­)ÙhBê|Úr°Œ,+VR¬ÓÔ–Ž3©0³ƒû 9]pTõ_o6àØ´k´¨—ÚôNBw§¶cIo´YCŽz™¨ïÖb!ÛŠ5½ØpWpÓ«TÍKÇÇ»o Ü áf¯Óë®ùšaœH æ"y[Ýl`òUØa…“/Gκ‰92툮²¸+Ïâ®Vû¦Ñïnºw-«öww@ïb˜åÆ ný5}øW½é™ØeÒ:«¥=ÅㄟÏwŽî€ç.õ¾‹«ÝE£J®ëÊ)õߪ{±Þ=ï[ç}˜ÎSÈs»Ž¡ËȆùåúzå^a÷[bÀï%|â®…©£CS(É»|œ¡HÚÈ3(ÒO¥ û—Åb™ÝÁB¹î^y±eœiX¨*u•® *qÔÝòêŽp x‹/ʽÃXO0K7mB”¥°•©½}d¡fmàu´åN•éÁÍB¯…%$gjºÃ­Ý9f®œŠ /Œ¹G¶;ç4µ×b+uxÛí`>"·ÆJô §«¹] ÌMeœnåf¦öŸ Õ¢º1–§r¹±C±YÕiÞÛÉ+qfuÜ•2‚ Jq™Ï£+_,JB¾æŽt~ó^Ò© ë ë:(š£#t_»4U¦ØzÄPöå +ªì§K†| ¸åehÄkY·\G`¡lÚ´áÑ®‘šð'C»FõÎÇÓºûí­=)Hs«¾¶º(Ò£Öéô* hå”j|ºÔüSdW,­Ý1UÛKVh¶ ÃÕp*²6¢šå¡[¡®ñÙkY¾ã¶¬%— u{‰ÓUw*¹Ç·ß9¢ð®uÈ/®ëAžs§¶Ÿ”ö3¬uí—Ç ÄÂ8¹Ù(dÞGp¸K‰;»Š”]’Ù³ºZâ¨Í^Á³0«'d#=}km<»ü¢ íÞ:›]ˆmWå :+~£Z§+GÙ¿_I…y@ä¾Èé'ŽÕí ˜•ÀË¥vá¼0T¦‰¹fÞjvý“q»v|èg5ëÉ–ÝxrÇ·J¯Œ>0NÛCæö—`]«òZz˜G©ø2œwÓÙYmkh*Yɾ¥Ôµwwf.‰uÜ`7Þk"á»*#yç¿[s%kñ½Vo­-©†*o/rŽl³(Çk‰ÈŒ¾á4"®Žš¸2婨´s+™¡†ÕMs/‘5ïØbá3ã&€díø %­ Mäh߬QcQU†D­ü6K1ÇíÐ']-!ŽÍ‡Ø»ˆLY…÷$ñëŽz ¡0ñ­=”oÞKÕ£‹‘,<` aÕ7«…#u–:ž;¯^®¨;oººŒmæ$êVûcëÝ®Ôí‹ö6|–+ORÏNž>”j*ñØ(…–ywK͸b=‚w³x«W.Y¥Ê²nhuëÁtÖЋÝÜ\µœ‚çpwq@æâ'³ï dj5a ìçy|Ô'XlRܾO{´3rè¡KseOB—_„ºÙ”­â~æ>µ ·è×m{»!`{v¤Ê›Óc­ñXp꽈c7®÷¶®±Rj;¼E%Ðf¡L½œ4W)\DaÄ-Vä¶ì`e3Õ¼ÙSˆÕn¯årçÒŸd®Rc˜Jº)ƒwig)€p ÉÆ¡-ÌÖ„—VãwÈm;íăѹ-ó‰'殜Uo`÷X†ó FÖ¼·ÝR9lçUïrX(ºz¶i= ‡«Cå§¼ðcÛØ»^y#)଻#ÝYç P‘ð¤s á9m†¦FQé±Ju ¾Åfê4Âêî–¢Þ˸ÿ®ÙÂNð¯PKÈŒë¶FÇùÎß?p^ß÷QÒ ñ,Ì0à55ïÙAÔ› ®c½ÉùT3| ’ö…ùyš–&ô»×@„±œGf_g9e#È&u_*tµýÔ /¯‹œk§ÀØ­µ™‹(xïO.XmhúOOpÝê¾Ñ˜ì’‘[là9y'"žÎ­ž·K ··5#¹Ò×#vþCï`îåžïb )qÆ&‡³ÂZ#áKy_öç<ÔÂæ9.î¶ùòÜÁ²½ÜµxwPDDevNÀŒclŸŽûjû»>¨†5ÊõœÅN”Ò´uª±V‹6ÞL&Ñ©Ðìëà–ÆjÞÓ()ŒP áȇ2´â³É襪˜èp.ÁÓš÷¹óv$±SìÚå`ß°»K!jð 1‹ˆÖÊñí C`ïP½†°6ž<Í=ºò<û=¥ºJ³aËËgƒ[7X®¿:Ñš™ÙÎÐtÔ†Ú©ÑnͰÁš;mß—yæÞöÆ7Ö ³ÜŸtÖT­Ë—ö^´Ç_7Õlzö¹Ê·ãw]IíÔ”Ô«™qžÝ‚K£vÖÛPÞfm÷(+÷E¢¦¶vOBàj¹i¡tB:®ïÇäõxo³y¼³v"Ÿhå=°pŽoËyQíµä´%žÎ­²4›;pd¬o ê}ס×OW :s²Ÿ¬c>{ˆ\k(Ó:ý•ºœ¢Ÿt9Ä®ØÖ‡>ZMÎão%={n°öƒL_·ÓvIfˆÇåQî^Ê&¦A05——d•;„®Ãæ½C½K2’‹…¬ðˆJ*•mü튺ÀHVw->ìÞƒzûj%OYPžx„«½Ê<t Kº‡ NèVÞæKì ïnˆ…x^ûܽ£Þ¾Ñ™–>[K•!Û˜iŠ/7e[ÌåÈñÅ”¨dE ¼¤µlñÊÌTò•½šWî5Kë­º¾4òœ06>Àm>ÜT1Ö¾n¥[Ýâ5g¡wËxL7{œ¥ì¤Þ a é8ÚÍéˆ+`äÅP™BÕÂ0±¨f]Øõn&¹{eΛ÷«2£µµí|±L¹Ç¨IEZÓq_]’#Ô?!ºÇÁš-Y㜈©]®ö÷¦]€£VßœUˆh\Î"0[f´oÚ…¸môæ©âØÔ¼#©ç’Ò®zožsß³ÎLòÙ£â}êf" ï)¡ŠÇ}X¤ápegžnûTÌβlÔ€œÓʱÊ"ò™5pSèÝ…Q§]c;“½™—RàØ5o\ãŠ)Vß¼ï{5CÔ†Ò¦_Ùƒ´fÕêÕ‡ 52Â)ß.ål<¦ÕÎì›G ¡K‰Júˆ6:™#µÛú÷E΃î uÛÉ›ÞìÉXÎùu·áüÀiÚ«ÅÓ?¯ÙvéYKðøsýsÕtMã~¦7/…(ëxŽW´Õ¶º•íG“««‹ÞÆêîÁå÷]Ì–+Mw¨bpÝ„½w,éº(Öòã‹)YÚ¾I;¬ŽTád²ywf‚®˜©Û½9Ý:Ääk@2¶­¹RïåkÉ4ªbìUè¥Içƒ×‚{7Îè_BÁ© Ê^PáXlÝ9]dT]íÙÇÀ^埦;\=O¨„ÅÐ*¬ß7Ï­‡Cq–î¶êÏÙ„Þª´"µH.®g€Ý4d±Çkt>Èåpaø¤VNlk³[²o—˜®HÎä¾VF4Æõ­-F=‡{Ý ÑÞÄÕ=J^—ÐϵÒïR†¦åætȵjÁFïÜémJ]¼ybÈú++95ÔyJwÎɘ4¶n[îc›Eš³×:´s¯ $N<¾ucŒ“ëuuíP£3V@À¨:>á|-¤Œç"0“î={ª¯îÏmiJù±çÝ ù{€UreûÖ«mÑx8ÖÕXÖ¦U™|„Ø¥õ¿PÖ~²n7·„$ü"nÖÔÊSÂ÷ Ʊ̻¯v Fþ+«iL.âÇpϧ ÕÇÌ{JwíåSn§y÷Qøºf`b¬·äoX¸K3×;bï:ËðDç)*03Þß!bèî,­(®˜”#—-ŒÒ–C§‰p¶ˆ!9±®dÎv1|èOqŒQ`5ǶÔüÓˆmàá*ùŽ4³ºkã‡'}k„üsÜ Ë}M,ê8´ ãíÃÙZLŽ^gΊ´DW”ÄÓ3/ÍI®jÛè¢B‡½¾Õt1iÇp1R :ÝïŒð§›îµåºKȇ“ZmË­Iï*xW½xœf×@9âë.±\µ$Ôë*iËì²þ¦3Ct;B#Šä ò«$ÜìSJÖ_ºÇ¥ð¢-¡™Ndb ýŒÜ¸AtˆË -¾yÊS2‘ÔCš©B¤·o©á<—¶Žb8„ç:ðØK;2…‡Ç©òK«dk•r¦o2mO ç#ç^§’4I·ÈdôùV¬‚ª4%íT‚“ ”†^wRUck”Y‹;…*¾ÞË ºS9%Ä9˜{ «y Y)ö¨è·µwubïycÛÊ{ÙÃqõpÀk^™Æ™ÒFÅ],w*¬v7b…ž°;‡yè.”e@7sA®Ç«/rñ±¯ºžaΚ˜ Z42•–2È]#ƒ:rÂma«:´Ý%ÙXçÒŽ¥¥%Ò ºU·d[,ä(‡ŽéÃé.ß·ªíc§b³‡;ëbTÖõú‘,8¬Ñ;¬‹›gzuMq¯·›¬è™Ñ:1ôËñn~oÕúyïÊIJsÕ.$®¶JlÞñÖðüÈ{‡Ýš>“Úûð;ék{f ¶\eÏÃ0 —s(ÂRÐØ(Æ…!§Ü^IiíÉqÝô#U¨¨S™vB:ðíT¥]«kZƒŽíL”ι«åî÷ ÜͨÃ^[Xxö(¶ŸM3†(®Öt¥Îõ ÷5=°È4Kd«xæW¡`~é·R¸E˙嵇Þ|Å«Þ÷‰w‰¡PRQÜ÷MÁ[ÍÏ_œjv `çs)â53‘Û$M‰¢ÐIõb|™)ƒÈqFvWcy¸~Ëâbû¶â’šéåiÔ÷DmöíËê·t61Š=P|jgf•Ùéo씲çŲ:ĬÇÔ"Ý@u_afÇÛX¬6ÐÚƒz´¶–Sä­—ß–mZ·}©¼Õsv%.dzµT”oz³8سÒvÛÈ%ñx7­ DB'¬’Û%ß$³{#7+÷hϬP¬ZÜ/røŠÌ!z‘Òú_½aëu²ü0±=F¤£^­'ÔHVãͣnjÊë}0çÖ> ±° +IÅ#"kˆ–N¦&æZ¢µ²•*h÷,)àðJ*µ¸ÎA¡'Yd±M Ìì‹„ û7oUŽZõÐ<ÌËè1[uÕ‚uêèHYš©#Ò¦Ö›á»Hûaî¼vÌãWRl¼¨Õý¬e**Ópæ²ë<®·)»¯cñè »:>EÞyeëð®;“2æìÝr½BNL¦gMbãÙ:ç]1ç+—c:ÅmBvS¾Ìf¯x‘AÓÁ¿mÓ+\}Cº-.­{¼+¥ìávN_¶W˜¡~u·Î˜ <ÅÊ7ªöŠ·­E©_'3±H±P‹:ýÔ²¼ƒ¯]׳èÌ×$¿r†yÆqÒËܾ7ÈNR’÷„¨LH¦ äýÙ ¼Ã-ëò×=žsviÆ<¯Ë­•^8’¿#Ð:žh¨±oº¬mË0OM1м>¼*C½µŸ ·¼Ò»ÎDSÍo•Ìšo…–ôÝuñwËæ¹Ø™*ÚSŒ—˜c5×/£X¾é.÷‚Kè@Ô÷j ¶GuǬ½î|Ø×È„J̘» KjxÙ&ã`Ò»fÃVËÔ…û+wÚìWtÉš)>©µ01u{UÎEoy½§í¥mñæi ‰ Æy­Ü›¾ ÝGÁ•X³)v±Ê½Z"ù†*îï§"=+.½¼zt)“@û šVÎò0¯{C•”­ø®7xJÊß[õzfݳ¡ªà±pЖ5ÖßJÛÜyW®ˆØé<‰ïC*Ó-9=²fïY 5²Syë¼ñÚ{@Zt0õNhœº±Òî{”­ ¶ëzн~Ïzº±‘EÓ•¶ÔíÑmÅæ%¿±)ìÔžÚÝ}Êͧ|æ_dV®ÜÞgk%öjtˆpâg6î(K}˜óÑ{P­“½ì½ØI9\~°Ú]Ù+ ϶‡2ß=ê­,c©S ´—DI"ÅòFO§ ”™;uÝA<Ái—àë-±…žDÈ1ÖÝe­ETcæu ´ýãÞ­¦°t(Éù~¨|šÍÌÀªW¼býíR?}is®¥:Ì„+aªc)žµ–l÷ÄClEímvË‚²IÙ¹jw¶>¥D¯ÆîFr±{ Î^iv»[hËÝg®ìÐï­Ò¢ñL5Æuź0+€ ®n]/¡çEë@gx÷±}ÃðÏzW·„F§;YÄ!c8…N1USvT4%d´mç»]|€î®ÜŸNeÄ{ªÇ*Pó@]vìyÇÃÚëz¥êÄÜò©/ë» Föõx|ûÜÈžÏXl1õu¹%o]štÞݦVóËû&v–0ËG§6özô÷·¶!ì9:þëuí­ôö¥×äVPT™² /€ámK–¬»…™àI!‡âiÂå-ÆóX;­D=Ú;ZT ;½”ûS¤T˜¯9LW°# Ǽýs6[­ë+«cÕéi× 8ìmí&s0 ¾ß6HjHÝÜëã„֨˼'3ÎŒh³0½_ –^«qù¤9]¸«y¸Þv]â‚™0;’»œúê*¤5í¢ìRë6.{ïMý®¬„¹<º3øÃÖ󩨵%oËHŽh:É+(&Ù:;yFƒ•›=›Œ”*-©Ÿ”x9"O‹å½[² ‡Vç(•¦m‹}¹…®Ù™u¸ÆRȮɜ]‘Ád®Ósž³rqÑÀU<®¥ºê)„oÚøF‡eÙ3_n*¾›&óvmg#з{]¥.“¸º|¤ÃÊ 0`¬‘ZãWŽ›ÅÒåÍqKMhßæë,\Å+w3¦ÚÏQW˜¨TM­‡H‚Ü ÙöÝf>9}˜pIg¢ãÑïŽú´§¬è} »¡iæá;kA'gèIë§ epåÍŠ:7cµzÈ<¹@½»‘‚3VÈâøe«ó4Þ&1ÚW—´Ï—¨žÓeÈ–î?y9ôÍ©t£É—ŽéëZžbtçDÔ¬úÝ_A?%O·âædêÞ×5íÑ} =µÄo]mgW7²“ÕM´U³q] 1õñ{´ˆÀ¨ŠÓ÷‘ :ž÷>:6ÕƒÍu1sW·W©T 2kÝ»[ŠT¨É\ƒT>"ÄZ@ ¯ Â<¬g‘ëÍx5ºb5ÕÜpÓ\"Ó0T w¥ý¦ƒÙ¼².c;yü©2ñšS:7•ËTQµLžYWÕ·Ç$Þ_UêdÄi¾¥HV€khæÒ사à ÄlímÖ6ÎäѺ-vdÌ”q[åÐW¥ÆT:°Qèiïb^W­U³Þ÷R­ÎC/—' ÷MßKí£4™¢Çqïaç \UvÞÏ žÌÁ–òYÄ,œx6mRZX©—ÀjMÒO‘7X±Lµ{nòù¸é2Íl8ßmîµäÈåGpöv:B‘ 5ˆggcJås±©%€+Ásª™ë5(&@›2†G†ô’.{Ju¯]îé MY-Ì:oFØË´´[è.Pr)t®GØ/)ÓÇÜ/¬Ø¼Lã°‘Ç*msŽí¾Ëu+)åZ$ó¨vÍH$`Pé!¦p‰‰ºæRÜf6røuQÓ³7H5±¹A™G‡S"^PÞ.®jv:†q¡§b¶W,¥R¬Züz½=LrºösV§ˆ=®·•#ï†ì,ÙzŠq¥r±Uå×1¾Ù]Ž~ôÞ`bp³Á»!çŠYfÕ¤0oÑ-"D€.˜ô~à*û}£çDÔΊAê&×Ý~ÓÜ׬«ïMôÈ‘s±½47\].Ã˘îÊ»3$ð¢DÚ µ²üsô•]ž«3Ъy}K§[Ó·™Î¤PÊÈÐ;¯>—㊀„]]ØÊ3ˆõømù,Á³Žõ{ÐÞÁÖÆôiAQnÒm8ðk}ÕC^ËKް¶…Ú_W$ºgTºäYß­Ë¥XœæMüãg=+Þ¬©ž1».˜ÊG:vö9®oh¸iö£Ùw~Öç¸â<1v ô­SB‘s¥#­ê/“¡ÛÜ:p]¨Ó¾V8âÎW—Æ^ùCÔ1ˆ• ¾ƒµZRiž[QºÎn®‘’iËê¾·(O¡û âT, îŽOV½çËx”ádUò=Û°#íö'žž¯^´t;ÅìOÈ%bi³rõk€+w[8u:œšV;ì­fòƒ™òË<4ßQlÇîÞÞ­èµ{ õEêÕcŸ5XºW{+°YR¶dÔZ¿Y¤šØ«Ž&òÆß R©xwº´?e=4îѬPuÂCîšœó9è>SÐÚƒFW®´íb«òL+B™tiKôµ·zw~x”ù[꡸4H¹Ã|Ë£A-Û–WW–¡Nª-4…£›m‚^87a>†›êê׃%7†Ýœ–E’‚êÞÆqж5m+ dIz `íTPM¨Ø‘®w[X«‘Vâ—©r+ºKªn±ö/&·k Ýø‡[W˵s|î¯ |”pí]Ø^³«mbOº¶è]/RÛy^aæï†yEW¼X#º³$"}-Ížèè Gw·(ø_Æ8›u¾UP„ã¡€ñ|_võe[]<¬¦u-èÆao^9[z:»ŽmG§²Ö&©£nÄ–õžõŽõº¾cií'áI{e<‹ô©wëcàÖ¾Û ”ž+º½®ÒÞ¡\!wϰû”ÆèuÉÖ»o>Gµm•»[ûª'iž}7Á­ø0a[FŒÉ-åJ- JõmK5ÅQ_·o³¥×˜aÛë]J þÇ÷ß{ýûô»Î:üÿH(7›Ÿ—Å`o/:tͲ7°)Îes²’Þ°Ò}Zö‡òê)ÃG¶2´»ã\r[Ù\ß+T7æ´C«m\ØÅ’Áç¾Ë³bûÄûx=”ûBgí£71„•nà³µÔtö ™„q/µ_ª(s$HK5ÞÍà&DØ>¶Ð“ {Éý!µil£õàNÉöìa ÔÝÈCXyÌËБݣ©ÓÛÊçJX¾†@Žæ]ÄÒ4¾H ƒhsË}cNå’¨wØÅ¶a“åíöÙû ãƒ}xrU^ê—:t´ªáÀ%Ñ›7c½Üaáâ Ê.ómÔdÇת•Ûœî*\Tòô`9Üž{)ƒ™œ}žÃQNÌ•´Å:ßp23+®9”õrï£4ÙÓZæ-íà%+’_QÆ›Ôg|GLV5a<Î]ÕÈØH™ÈÆVÙÝ¥[tš\Þu yöį®uuÒk˜Ö¬ë®Þkomt›ÔÓÁ€½`B–Ž@tè:¨1NÌ‹B"Õ'œÎ|PÛ¦ÍÈÂ=xÊ%h;M±]³tNùnzþN»8{€õàîÞ‘0®JÛjͦqAŒ(*S­Óؤ±QÑ{ácÄŽÀø¤&Öÿlý7CÇZR³|(Ušoô5‡8>ßb®âG]ùÐÒ¶Aÿ)·ºd^ñV ÆôéGxº„¸'té^Õ¬Ï2:gœMc§Ë×v.ËO73 [¢·`](õ1´^@+˜{5Ón_r-íÚÊÅÍnõ:¶µ{ˆ»B =Ź/ÍîØ»7åRb÷:MÁƒ†ªQƹvÞ¥Vƒ"-2nYÕ|G$´Š‡Õ½ôõŒQ·Èº¼öÔö6, í«§:ÊÜÙœû—VÝÇ/“ó&ýÂKÌÙWá-½ßR¸¡ìÙ×b¤¥ïïÖ7Ò墔֨¥0nòׯûC­º#—./*Ýqqéq½­.ŒÕ¶9çFðÍÐ.f€H¥£²VõƳcºN5£9j½Bö,éfm¼ ,<9>…åEW{úvÙ„zŠóS×ͶüÆç&.ʰ'×¥³{{hœ§ÝDb´ŒcXuÊv0(˜‘Ö/RÍ2±5'CƒÙ,å~™ïaÛÌ®Â(xòE™Ù(ô_ÙtMtá.æÓ!„Ž]Ìæ”$F;ªjÒ•zºžœŠ>èUYQò¼×Ù}¯k˜áyÒ´;mhy}ÎxØ ‡¸ëº1„0úó6¶Æçs•ˆ›“VŠ *á··ywÏk±s_(kaÙK€lΔۙ»).®Î¼˜¯(Û{†Ã¿mÍ+³µ9>Äǃ>ËÍÆ}\TÕЙçÀzF‰à9Õá6É&G•˜dæ8hRòîíï´¶¼Èßjwë!{dØøžÒ/…åÓ«‡«uÖáDQ豃@‹—Á¡=*¥Ë¾#YÂ;Y—ÐP<¥MeMã3¢®¼jÞ‘¥ú]BjþÂÎÓ“–ÔwêÛ>ìPµW ­ˆ’ í)5w”ºöU˵8PÊjï­ªdácˆëv=©Ê ;{*Üd0¦çݼ«Ð·%-sxv•™¯ÂÇ“ÅV3®LrÃô¡>ï¬tº´MpË“2«>nU^³|9ÑTx`â²ty`Á”·1=b³–÷k鸎Î(Vm™K®±¯tÿfä¨òvß«ØÓâýX‘µÙ´ š]·R]¶Œä99W,%™ãîë½i›â™~íOŽX‡³o—7ÄÚÛ–ÃR•œÇÔ[êÒJ·Ë™W‚/ÉîS“§Ì¸ Ÿ{­„òK  s1±¨i Îø`9O4ê}Ç˽T}È×[Ž“µÏf7Í |ÜäZ‡–A^Ý«»½Î¬Áï²­êœï9ÓÊPòˆb+ëÆ®Ç5¡œ#”êÑ£Å>»c±ÕvVüÌ9çÄXå ¯Ê#jR bI&íKîðžõå”4ćn»è¤º¾ÆÁ¢ï(9µØÏMu~ >lÂï±z™¬‚÷ !Ÿv9ît.fõuô0_R]™Í^Ü(‹ißj»Ý<,†3¨zýCøxÂ6I…óI)êð4¬¹¬\Ù„žÂ˜f­]ÑRÚ¤uXbðØÙ\Ëçs¸Ëw«mØ:íÁ“\®Ö(í5ÕiSPD+±Y[¦¶Õºhjy1ÚìWé«F¬-b„Ô¢ÇDՆ߼s/*ÕÊF|ä `Ü—•н7u8{ÏF«ŒZÚxÈó ³» ³½RV!eV:³ã^Qäž ‘Á ýoEn¤0)ÍU‰«ÊÌÞE°æ÷SíÍ2+ê{xõ¹tÔ<ië¨{§xiðƇbÕãœÜˆ­êŠÅjg.CÍwˆ¾IæîᓽÒx¢wÈ!ÎòxB²É©xß‚s¹V˜ÜÑY™‹nˆ=Ê"í°{r#CÁ\nÔ[\4ùú¤‹3‡9x~Ë[â£ö”øû$¼YhX3‘œ:_§¾Ü #+ww ‡ÒÇupj|± ]¹¨ÖµËƒwMùøž¾ò¹›úÞ×á}sñÓß nî-Æ<‰@þK|­1ë­êïyñó’C–ïƒK9f,á|o¸•¹f}ÙÉÒÌ‚¢Ø·VîU0³’•8Fvì1X×1bÜlçë­£ÂîÍêêJ£Å¸±Õâ]ÉÈ5 ý|Õ^Ýe~4ÿmyzΉÓNr7g÷+Á3Ë´•˜Þ×Y¥cV*v<9­·Yt޾ÀÞ:Óœ<äò¯xŽö BÛ ý‰`vçw- F™µ®»¶Ҭvš¡³Êö—]àQæf²-¹ÁmmÙ ‘«Ù)/¬.&Ô‚݃V¨ú "`{–7'Ï›²/,W,1 j^J¬oGsNLC•©1c6/;Pk(Q›©”*ÛΠÖаkÔ¾пžÖŽå†Šê ¨šô[2Ÿ”<‰]£oò^â_JÔkdó͵Ât´ƒò×(ö·$šyÞvZö‡2ºÇ»ÉâïH¼K¨‰îº;†€ñʺ8†R ˜Õë5Ú:‘{É·–ótÆúš¶†Ì´°Áæ²xAÙüÜäü¹Ž¥¶(•tMm×îÛ;]¤ìJÑs¨\åS­-‚ó,G;”¬Âå-k¬]|ÅmYÉûKc¬ªB¼®’÷«AÙº®¼ëµ£ÂÞŸvXu'_[<¶Ý W «OVªö¦HUë@zÚ[êïØ\«€XÞ¬[V÷]Štù{´î¨­þí`1<*RÍD‘ûóÊân¥ŸÃËoW«w">júxMÒŃ(ºØŽ=wwÙEcäÐ{ìµµÚçbrëÓÖîíý†‘w°<@2»mö0^xò¯MrÕž¼åê³3¡[{>MÝm§°ª¦ŒÃ}H¥Ù²—]b"UܵAàóêo ·&Œ¨7’¹«%vRîÍ;s,rd2ÐVI7cQ‘Ý÷ð›pMÊ|ÙÌp î¸ðAxa[_}_1ÒÓ˜•î.3jûM]o(ÖS\'*¾(ÓQlºØÅý)©X‚†îÝ ¶«¬_Y0VÍ2PW`$½9)ÂŒýë2ˆÎW«8žÖ«-Ô:í¥ƒM¾j¬ÆóÉ'iÍ3¼±^@êı—¸ QTÊå®SêìËõöú1C·@uaÌÛCFEÕIz³.s]!Õ¢¯H»áNâ`çïsÍÞ³h^ÚÁ¦=ÇvË÷VÝIl>™zu`lû’Böf„fGa>š’¤ƒW´”Ë©UõM·—ÞÙ¸ò¯Ë×Ë(},N+ìVº˜Ð=Jóq„ÚV^ ×îÝ¥ŠQ‹{B°½iä*óGSÆáê›™B@Âu+>o×rìéÜÅõßXس«pµÛ9)ëLm×½ìÄNÈ­UÒ´¬cœ-×nQoR”ΚÍðX/±¢:Ñ™8zº†éöœ-râm+Ýx7±zÕø<ñD=·oçÓìË›Šeª+1ùV²otî,5+r³è‰ У7’fh—М¡+@‡³ Yu„9y8=æ3×íê·Ïʋ‹­<êË)d£¢ý»X.Ž|x)å„EêD<+[/|t]®¸¬E¹ØÈ¤zJY¬Uª8]1Q€¬í.$lÜ* ¶ôÃ*WXš:RuÖ—Q5Æ1:`ò!ò°’ÇzëGŽd_ åÒkW|™ì©¡·x°Îr´ryÝ ïEWÛ½”Ðë+0rŒ{hîTùm‘z,ÂÕ«"!2\Šºz²Š@;ê‰ûqÎCÜó7RØ,ï,Þ/T"´îìê³p×»‹禸O•­«)–Ä(5ŒS—:¸FÖ=¾t[ šUâÔÊÅã™Ëͬëêìî›|Hêi…*åq„…±$6ïo…2’_jV„Sï®rذ6´î' L€êu|M·ÓÑØÞÌkrí˜uÔ§ Æo›ÁwŠì9EYY¸òÝ«AƒŽ½+Ö_ey¡íÛå»Aäá"ÁºD¼î{Wœg%´–‡‹¹ÖRºãµ÷X]I´­:sWNÍ—>ËÞM-«rvxUËìp6ï{»ÆVàz¸q¾²PòZBž¾ { ¡4ϱ۸1ÊÃ(¼Ã–﹉ãÉì¿Vþ[‚~¤ÔŸ¿?Û=‹„àÒƒ®Ï3’ŠÛž{Ï~o^à÷lñ"¥AçQÌ8åå[5:Uˆ+n™–‚î‚ë(@§´«¶gÚÔ0ºéÔ/{®ã·Ös‚UÓä6–"sWÇH í[¸_J¬U¦¹k•ÌÉ‘]M¢Ó«uî0YêÖ7@C&¹Ð»ìb@˼Î(s}7··\b‘Œ ¹6 ”*]»zo—G×Ðnç9´>¹½mÜÊ—•›åÅu÷@ýÎéÞ÷t†IiiõÖ F·v|‡ÒNîN)×êq†e„zJ°¶Ú(ÍÑ€TÖŒ"òôÝÓN¼Y¹3¤öx:yx(YSçj]‰ÝÞ=Neì¬ã\lüÛo(ty£i—a>‚µlTàLÑ„=Á›„#Z펦ÄY®ÊY¾”˜@^Â5ð{ö$`4-1öG‹’ºYÚ­0‰ºOºˆê’TWÜyçGw0–¦7Më·Û”1T®\ƦÐv ’ß}Ëé×ç)NõQW ÑË/¾Wy½.uº<TUvÜC 5‹«i|º`fLÌî.rA½å‹ÓÛz´–ü¨¬ÑïmÙC8ª…Xßaã;\®v-/{v÷ŽpÜXº!Ýå/5#“5nÝë™—ÏZq‹;c–¾›Ï2r}¶O>kš·Ó@ÜFŸRX×WÑk7ëWíÌÈÁã—µ½(¢¢€Þ*y7Ñ9Ó7§C Oze¶Æ* {3½ç¬øok70äa‡š£‰\-èôq £}\˜®ÄÍ]Ñ“‘ ¹87º¡WßKcUʸ«Àì÷†12Ã9ïkš«4dz¹ˆ¤‚óëÇFé÷il¡NíPvËÎÜssF"*ÊQÁ…=£‹oPp #(²Ðr/ž˜Ž/l¨úË«£nQáu×zð›æ¦–ðy â´Ý—ÍNM÷ÖìS²µåãY;))¨·‡˜»AÞòñt…óFë&#Eé=c¿Z0Bë9~µðGÑÊÙwÕ;+%Ò=جrí¥I*}».ê領Î{È2ðt¥Þ¦Øó^*ï,Qc 9Ç ®©ö<·×X\ͽÜaŠdTdb¹¨¦°Á¦“Π¹ºQ¸¼ïkÞ⻣ î[m¡Û.°I³C,±€[èc½ÀYpíF->/¯ ç[ºøŒ AêîÅR–%Ù]FSù/=ÊvDt˜Î>¸}0ˆ<«( O³1]úÚx7*‡yšé„p\Æ<¡jZÖáŒBnæN¥’{,[^‡ø;¢òïM`‹Ø)ÚóH¨ÙR·s«v´¸õ_aÖ= ùöëŒ5ÙkC݉}η=â2½`ãåÌz™ø5‡fíú1v»#©wÌÕ¶à ¬ý¯ª¬fö¯Íý‚æÛzýÕù¹j;ÛêfWXk¯y]cåÑãk&µ¡M1)°x‡Ü¯:Ü×À8Êë"í]Oy3@Ýšmá]gnµÁíåãG©£¨ ·BƒÓ5£½+”ëk8̱ٵ¬î¯MKß½÷ck¼§t6÷Ísm*›ØðÕ’¸Z …]ñ¼î²œ˜t?'HQM¨YÌq¨ži÷];ìëqe—39•Õ»”¹P >ûçu¿ƒån T¼êX2ö‚[ZK̺WR­Ciq³.eÑQBvnRËxJÍóég°çW2 º.U‡Ð;«Ý¤©l»”ðÙÀշ£•²<7krÈYÎEŽ»ÌfŠn‡a_ níbF.£ —fŸÎ<–·}n‚ ^Í:ˆ«ìU½tîÍÀ›ê¦Þö× º‡»˜=÷zè.ɶÅ…Úû#}¹ÙŠ‚C ¬Íf£ ÓWW$–+< ‘=³¢µ«…f=ÕÕØ4Go´’ƒÉ£1Ö£»NX®*Êuy ¾ÔÇ[ÒßM9Å\U_g]uM5šÍz¾Vª¯MüµòV†1¤skµB¸­¶Ûm²(Ò’©Ûl"©$ÿºêîì’#,’]IwaÑU‡Ø.r²iÖ/vs9Lݘáa•e»£{Þª¬x—¶\¶W¸ÚÖªª$’I$’I$’I$’ª©Ól’þIT‘·ÀêbašJNL„Ví¶Ûm¶ÛrÕ\¶&šm¹€§uEı0I0$mÝ$‰D¯ê}T×[w @Ý/’¡úÒ²I¢ I$öwv!îä³çLþ:WþÏÙºÏ;"¯{×ô¿Ä£žv¢èÚòÐI‚QbòŒY)%ŠY*õhˆÚš´’IT@•M‰`†/b¨ZµR§¾$ˆZe•zµ… T…B0i,Š@…F†2 ´­@ *,€THJ”B£¡.¤iUª¡ñüÚè´éóíýŒôõü»þϷDZʿ·£Çn¬Uüçñ\Y„\\zPvIt>LÔÛ™êßÅ–;uôL;f€…)Æ|åžiØÚ?_~ü xO„§÷pQZ¬û´þß1æÚ²!ëߡ¸ÿÙFL3*íß„Mˆ\†ÓÝÚx‡ù ç€í‚:E‘dùÓîú}—DytªH¡Î½7zjçÃŽ¸™¢Ñ7ŒŒI°†ÑzøŸye;˜øËÊßá»/lýkð˳^¾×™õøÞ¦ú®¼¨ýúût»}¦ƒàZUGp0Ñr2¨J!‹oäŸ+óçGO—Ÿ\Ï»—Ázüï{×ïîìÚÄݦñý¿,‰×ºÝ…‰ÀCϳ ü8ó ¹ÆÇ·t^±BAºàï,q)¸u…VÖ6ì52×ߦxÃá•jo'¶õÇï¤>?Mñ„‰ŒeÏŸŽK×Ú¹w{:êxУAº‘¨PMýŸ>ùÐ~›•Ýv¾»½¦…޽sž‡—ž¦ÌX>^†ØNØg8‘„ j[ð<‹ÒÑñƒÚ] -%+éµQõ -Jû"çö|Ï;ãÑð7\]ÆÖÝ7e–?w㻜ק^–úÿ$SëòqývF@E$$FBEN°j$'_›ûô[Ë–2Š~B#ú¢ùƒ"„§ÑMHFZ‘9Oï‡(˜’pœoæï ÿñX:̤©GX¦°W¥ä -Öp¨QgOãÀŒ'ùàe2H§d´C Úÿ*Æ µqȹA“|a&ù<êÌŒ‡oÐ<ÿdõl?ªÖ~ˆ×m{¹‡ÎZ×þV¹Â{}\Õ·ž×ÓníœÔöŸ7Õ{\ O|¢ÒÁ\Ñd9eû­¯"þ5Ьq¶úÅ»pu,½¹–,p"}ó±ë۱˩Ÿ‡ê”±2÷¹!4ˆ;ËùÇë(ÿ¸÷Š*¥*€¥Â, æö³Óêægû'ô?Ȉð ç|B Ï¨¥É8_a<ÿqЅփ«ۡæÞ÷;=™æz_â“æáë7gåw;cçãË3Û¨ØôÿnâhêéÁ?·½ªlmûôæ|+¦‡Æ û¢ >^Øy1D:z+ê‰ï„!ë¹R`†pòƒ#W¢ ˆ{þÿÖwò) €“·âX.ĺ@QEN0P‘FA$Tñ^‚ˆ)"´g \ÌKýÁ4,æ QB&¸5,ÒG1ø;:8ÂÁ¸ÒéB(¢mTmìà¿«ÄáÛ…až6vÌqÅ«Ÿ¿¯«ŽröJ’kõêDŸJ÷è$KqÙ$; Y-ùÕù’/ú~’ê¼Àâ'ªÉÄŒ´Z!#½P$F==ˆ‹[ÒÕþŸ¹+4`IºD²Ò~~oéßcˆCzäžïQI[ˆ‰!2J"ÿ›Aä»ñºõøU~e)²¢ ¨tªÐñ’ùþ¾ÿþýÁ¬Æpûü»­')ø¯E¤ë õ*RÄ«fÑ=±DÖ5! ùSH I!`•*’€ÿìFá"±‰$HDôkfØX€6rIDKÕWÿ7‰rÂd³‰ bŽªÃIÂH¤‚rˆÁ’/ºÕSØÖò/!]´E aQ6€ÔdïH˜\Ò P„&1™xEʵcï/BH‘ø¦áÆ…ã³EXdI_HPZ!$CÜ5ºZ%JH ìö±!JÊ@$K•HNâ?8ÀŸ)¶æ¤(œ±JȽ"î§y>xš2»&ň4\%‚”?ó5D\½ï½&EO÷Y[I}RéDøÌí‚a.ÞáRÍ÷ä„ Ëf¬$ÉP$Sÿž3(ùÁÀF=´eCÿíElHð‹%›Uˆ‹—§²& ÄÕÎRfŸX¥Çë®àÊ2™!9­FeEC—§ÃèŸÑøVy‡å}Q· u‚I$ åQPP¨²/°¦ëjÿVÙEƒê3»¶õ}ÐÌÒ´Óè¼K‡Ñ/IB«x‚‡" PïeF@éô΋é…ÏÈû×@¸ýϬàc¤“1‹ìñ‚Ú ¯Ü µª6û×x–ƒu:}E$ çM¤’2bêÝúŒÀ~ȧÍô•œFÙ˜€@=©ÿGpm¦’FÓ” -RBÉ(‰,%˜›4iUä=ad¹Ë Õ‘Eb- ‚É"HHŒbÿªeÿXm¼ÉÎ/¾)­èú¥G¨lPBÛå¡c4!ºŠ—Íu´j*´gþ4ž¨øBòƃÞ6o=j|Hþ.%FI$좉:”Nv|)‚O9p€{¤†éfQTI´--$F@ƒ$# "FaÐDa#$Ib”Wå(¼+(Èɳy/[y`Ê]‘F È=ãÙV<¤ÎQ§¤Cvw­mU[aTÁ™ñ©ÿ`ú÷ÈOåò,Ÿ=uNô} 6!¡v7cl|þ>=y8«±Â¹}/ùôÿµ»úÃóèï.X¢Ö²UŠ…B%º`£3Ò|ƒ¾X5!B}ÅxÈõu—3ÇJ±ñz~6~­+úô¹Gè‹»j.Ê>°Cø‡\‡¨ðÜõz~½7Ng• £ÝzE„(Þh4ŽqíƒP8e¸ÞJ‡˜qýþmf•è%21É4;ž¶1nÎ=OkÖ^ÖõR•CÀã41DÝPñÒðà÷xäxÄú¹T€x^€c<*•3O*Rª¼¡Ý Šg ò[N ‡yÿ‡Ç·¾käS²í¡¡ã=ÓxAóùJÉí˜ÈоPžB0;ªŒ@\ß £Yöø±“\û½¶Qí;{I–ý¶UêCR½:IÒÝbú@éÍãÒén„éÐܨs¾<ç+pLÌ÷ïwï¾£º)Òý¤…¬5bG¬Ü‹·Êá˜gø~(oøŽL¿S\ôîÊÅ®û“û HÛçXýçô|KQÿg‘þ¯?ÇeÿÿŸÓ1“Óœëw•é³:ãU¶×«ÎPÖEt¶ðZݤ21ŠÞçWVʬ2°}{Ä×F™µÓ•ÛÚáuœ.¶<âV+ƒšêZ.ôÝ\œÖÇ(N<| Û7™¹ÂAT÷…Ú!n–lµ-Ð]w,šÙ} µ¦a[gºe…ÂNÚ"O«ˆJŽ[»¼âåœgq¿¦VE1läiæÑ¨¬ö z T:ñ^éîÎ8¸ÖÚ§¡|àÞ½¢Ofý/(+#ËmôEQ·ºÎ'h¶fPÜÒ(AØÓÕJˆ{½’í[í¥ÐAD¡×ÏJÚ)u-‘ÿ«›\õnq(êUˆ½s¨"õå]yw B×D–ôÎÂÏrY ÑVzgX¤í/Dkw]®š§›½©qÃ[ÌöJr·­[‘×qÝM¨:A4PDDH”OÚÁíYFXbð¦_bKÁ^ax•i®Q³¹Ô1œ5¬{ oög-²ê tÃÛ©7B¯£•Иˆ`»„¬cÆRu.öL±˜Sz²ó‚U·h½{ ÚZ@êÐ×èUïrê‚]Ú¥Üé»YÙ%µyƒMm #3’Ž´QȪÂz®ÁÕ†€·c3ƒ›!(ŒÊ\é\\²sWjîHßfª–/¡°zž'ÑÔM+ê{WÃhªØ- G Í Öè’å+«56kê‘Ï´Sê.Çï…I/¸n•jg$ã;±Ñc}HõñclÛ†£ÊDï7Z3íX ±iÄ7{«"çvéYf.äâ‘™¥V P]Ø.s{ˆX!»nq¶4è«)ÕÖeÊ ®Þ\{ §2²’0H‡ÉAM>p:UÝ]…îT'2îŸ;y˜ÏØÖR#gÑÅ]InkÎqjNŽîó9u,>‡nUÓ«eU«ø}WÛd‰§kŒ}¯ÖÕ-tw¶ò—,ÈlW<±vâî¨(Ia«<×0-6nÏm´`Ã"¼õŒÀ»1V¤û¥Z7‹ÚØxç6!^`5ÙJ•âUrË5tï}½¡ŸrÍ„*3¼Öñt/uÈGN!ŒYË ÛÊ·E\¹ Ø«³n±A]äpæƒÎž¡±ÕñílYÉׯå×jéRÄJ×Ã¥óËáy‡T»ÎA=yÍM——+²‰8Ò¨l$µ6û´%Õ‘o%î¬çwa|È]Ø.Õjaγv-åvŽðìp”Ý_)×››vïDS) uœ»!3¯se,Z&ƒÎj§@•×$ï˜q½¤fÛ5ŽØ<ƆEjë.uâ.!Ó¹S÷{6Že6¶+´ýâŒt2Åk––í—”kY—A§.I¿mâË­´y"±eêé.û¬™V±m²52§n{¥Üž÷†•ȯEîUÕ&¾çÇŸW_}sMÙ͹½Pp ´«Ñ¼ÒÀ«b¦iäºÆ÷¥Öš]”x-]NÅ/n…X‰¬LFæÜk“ÊÆ˜ÍowySÃõ¡£VºäÃ’ðîNΨéÖñ§ôÜì ¸¹Úu1r“ RY×ÕÐíG-õªÓ‰|Ýåte:u*ë& ×Y)àʉ«C¯!Yo+WsÖ(æŽÚ <;Do´tT¡ÌjÄÆ!®…Gº4ï%-QèÞCg£t%‚ÖÀ9té¾®º›*Ê™ƒ—RuwoŠÎM’T§Ø\ƒ‡wVÒqÕÍ^âU)n¶#ì2‡ieRÌÄE((¥™Ó_<iîš•„^ÐCQIÖvFDZ—ÁÜì®ê¼'ÜëW8Ü fHnãS%NV²êmá#E×vZï,çÏKç,px€Å:2‘WÛðΩv䋲'£Š}•9X=Ö«EÉ]m ¹Ê!åçwÅ‹ͦæ—eÑÊg²ÁiÖXŒoÚª‚f¥\ø`ÊãZñ#f½Þ½R±ÊÞÈ•&ë·'Gl!m«Å{w*”!Ž«lã‚£¸3MI«†ÒÍË¥#«-óCîçuÍÉ4–à¢Ð&ÚÒ©Œ²"³¤¡bf×5Êr5pÍ0ÞØ$*²‰@¡·jw…Ö\w£í¬•³®…ÐÞ¼í-©“™r.cÕ¨],ÅWœ—ˆˆ›QÙ]èÈnøëËç,Ø’„ÉÑQÞ.âÑÏê`õ‰“8iV46yiçO€ÛR\—/>p,Èd²n¬ºbî,|uã va·+‹™ k’ bpôRû;®š1cÞ»c-lêy¸}LN>T%ôK!Ü(ݾË}µM1Æ·„- 6ܦf<&:&JMrÍÞM›ØÚ[+£Øò1E‰ÐõÝu‹»7B(²‘K'±YÏEmØ3—ÙIGô?åµ£xT•@°‹DJª •‘*„ Y ÞòF J%D*ªD¢P’¡kЖ ¤ ’É$½Uïd±D„P’Bx†ô"°Pbý'ûƒ•º!úxXåü¿¹WðCSûCô£ä†ÑÜ"æPp‡ uBœ2 j¶äúîª&*ˆäÞ:‚fÔ!D°QL$BH„¨ÕTª©D˜€Õ©¨0j53½ËŽåçZ@ò Iù¨"Ħ$•J€Û¡¡*j¨7íÝí½$p‘’HÛŠG$„!kZÒÖ!$’I$²ì¹É# $„’HÃÛ€x~2ħ¿p KˆAˆ/ 2&$ESp*ROª‡Õ^øªª"ª¾Aw î»ï#œ0ÞÎvŸÓÚeêæòåYM̰•’' Æb¶wcpcØÔ‹á’E„B@ÂîGÉÚå(z"£þRTïúgû[÷¿[•‚ÏælZÂ¥ÎÊ4ôÅqó&ø þÎ4Ùë£H…å^•Ê ýÑãqÊ&¤*Vز ÂH‰%É" RP„PF@$W?AHZ,‹þiü¨¾W¦“ú‡$‘CöÐHµ wøöÉõ—Q¡ïÿï ð è|ÏÞq¹ÿI9$’&a¹ýÄyý§ˆz ÃoVÿA,›ÞÏÞÅ;øâñߙʮÖkqí0Q¼è`ÌgM=¼u×(ÇY53ÄÞû¢nÌ ö[X0`˱ ›¹¾­zIìî;Fl'°nOÙ­çP ´ÓêöÄ"Bcÿܾÿ¤ã"ÑC_&ô«û qþîÈ}d@Þ…A=0[hú[-ªUvRw007«Lø Tuä= †RïåÈÈúßlkÓX¸n„˜]Ô@ûV , "}áÂo@º <@¡¤!‚AK&ŸÒúÍë<ÞÀ8kÌwA=_I(•F,á ²Ôì°­¾«Ò´‘RÒBÄZÅ/™Xn7½jV‘rÉ +‰BØ Õ(DÉJ”щP¨…³ X,Áo€@}g Õ&FBn1hØÌÂTh IP™‰rœB¶v…²—”ÿH39vòP$ŽèEÛJxÀ å(—D(l¦……¶5&f'O÷ˆBÃhƒ ÈäM‘áÙùŒ‡|CHåóAnD ÈAý–^™!W »bQv °o¼¼JiJ®c¢2dŠTƒ;xšæDsTÞÅ_Ñdå7ñCúÏé²xX0 B,A¨ï?iþK¿T?p Ú‡¶!"¼J3êŽÙ\xÁ ˆ  „Œ‰Q>í!êÉ]Œ… á$ ¤ˆv@¨„€H€HÐ(€B2 _SІ‚ú΄É<¸ˆ%/ã`_X2WEÅÙŒŽÉ¡$˜”;¨\²(´Pᦰd"PúߟþŸv«€ÉSˆñÇïøåVðþ£SÄ:Èïq|Ú‘Œ 1¡,-*CÛEÑÊ c”@°Òƒr€…À4 , Ñ‘l\?œDýïæÈúµ¤²DŒù;–€Ü*+ÔÈ¥7@ @Ýû ÑK#Èÿ«NG%È>ÇQJ„‚!ÐÁ‚§Ïð ùñ’Q ´û(²Ú0’ ’HFDc#BÄ* $„ƒ$„’I$)ÇyÔñáA‘ž  •Hд…A FF1<΄+œ H$B4ž]K &ç†h”1ðÁPh^³¸ u•›U"E$$‘‘yBÅÈ2ÉÍ}Ç~î» kÐÑ çA¾a$!$è†EM!£T–X”Ái%Š‘iE‹U†£j-°DÜ»;ƒ`¤Š{49Žö²h‘-Rû²µÕ¶/jª¦$„ ³±Û|ˆZÙ2&”N,Þò  Õ´ÂUXQ”¡VÔ;-áýN?TН•ªtíʦå4q àâL{üLâAÍÑ„¨8@@ü½ÃtFæÊ⯞ÝàóáNÁ¼?Žw[ôZª.E´H|©@ôž‘‹Ä„Ÿ€ž7ï‘¢ +y—ò–•»õÏ×ü?ûÝÖþm(»ưÅÜíM€ýÙõ7Ø Kœ É‹F6· !”Kaµ›0ƒ³Éþ‡'˜ϯ•<¸îÁj7¿hCåñ)Oá÷¾Ûa"‡ˆÀ )´üðmÑB@j †{hwÒ~Ó>]õª†Ð_Ϩ€I †!Œ>>¥.KÄ,?( {,¥ÿËGRhÄ+3ƒÞ­÷2$d’¢•( D1û‡Ê)k¼Çyùw!ÿ–o9«ž@¦ˆfXñ"bï\Ì}4®î½VT±Q¨"+pî¹ „&±@©D ƒ‘)#"I-Q!D E„‚B X¼'°ù?ÃÕR¢1"É"‘€’2, ˆ‚µÛ¼¨PVº+P$&lE ZöJ5 :çÆÀfDË ½K^4Y^<:,N°ì TŒ *ˆ2•,|¥€-%^ÅA-U)J*ô(i ¢@”M@(K”VjôT… VF ÓP”Ê*¨(ˆÂSUÐ^;[´oÊ¡A"ì…ô,s“$ œh8ð8ïÕ(d°ãj*×-(ˆQäp<®_KM­Aj-DRZ€¦# b£ ËQP„–u³VQ;±h7ƒTªÊôXÉ- WlðS 5#Dt( $ UH@T”%Ò#C±ÀaÅ660%Ñê`Zˆå „ˆ“‹4@´±x1…,¨!ŠPQT’¤ÝRõ¶Y!B€ÐJl0 ”mÉhZÅ%íR iU­]ƒNEܤŠPL­E±8^³!„1 ‰%U d*ª0XPZ•m’9À¨h ½ZˆQRÐ6™`Ã`-?ÍY€Ó$Ñ4€H:`ʤn`»e0_Þ72h“°÷Lv'Äöž²ß®ÆþsœèÕÊ:Â`½RÑÖ‚¡r$!UÖ I´†ÍIÉ­ŒÒñ¨#ˆØÎÖ–©;§Bu6STáÓºxLó(ÒŒóÙÆTMûÄ´Ý_ºÝ2 &ê]þ”ߥÃñ€5lí¹KwÊ€`Àz·æòw±ž@Qf¥¨$:l¢ØÿG”KúÆxk¥ÖÙÑhò¬Š÷_y¯3 ×íÛîrwËÞ†GÛQ"ë¾ó-Æš— - çIy¿neÃ-Kœ~qrO8ÎBa(³eEÆôêF‡aß®sv­£U[àYÀÖ…TR”@aýivÜ3.ñµ·€dA°å»éоkG2‘ÝÖZK-Ñ&ª7æ†DËtäfbÜy #O;&–^™ÚÅPš‘Ô U©at9‡”}=(H"Á͈å ðבGVý‚ E7†@VüérÓhÕºm¦?VA½h¬éìe—³@ìàkÊçñ 6Ào5[ÜÌhsa ŒB„ƒÒ¬=p$±Ž5²p¾±KM!:`K Éœ"@‘S<Ê0ZÃyÐÅ ¨¹…ppÑ´pDã¿,³Ë)eÀF6( aIf2 (KÀ£=ÆI°lÁ* D¦WG&kfKEbÉh—-M&„¢¢Ë…n#LTÛ~£#´¢«VÃh‹Ê i6µ^°Ýž@à&ûq帑2±Û\ޤXR¡Z¬øl m”ÖædŽù´BÌA ¾ªj¨ªIy{g (¢í)[íKœ7ɵ„$뺑s±Žg0†3F0n,›’¼`¶,é—–ì¯ÂަX-—=Ël¬@3ëW,d!¥Þ•©h&FqÁ›jÈRbÆÑØÌ.ƃ¦Æ6¶ZXË›\ 奷ÂFÃ¥me6²UPp’HÞ=™N0æÆCZ(fò¨X¡Å%Öù oé{lÅtg˜ªƒS|[)R¢H ‰º:fc&â1Š0*šB5RÖ`ìèGL i1"0 ) ՂږШ%Žx/zÚlD–ÈI+;–¬ñQ„--ŸV‹E¾yqÒ©ûÛNd\Ç  SÃ9΀` Qç;:Àɶ¼w— Ý2ÉeÖ2ζ…àÔß*À$ 9o^gµ÷k»‹£˜çÚv›¬'á°U¿¿4ëmH ‡*cn°¨]™ÉmCjÁhNÍüû7’ï³pg¯Ìàû.[ç¯ÆU}3ÎY&î—ªtçßGi9Á/z¢ v Z–йl]4·Aîé`ì½7>×ܱï(_´ü|×I»|7Ϭ½UøR‡ õÁîLâ’0ˆ±Š&Щ×ã7›}$±¥Ì3¸TŠÈ€îQxÄmá-HÓ",l’BÅ (‘¦F0*$ZbH@‚Âc%RÓ ,•GjÃk&D¥@0­‰¯©piÛ¶ ½hÍü¸ørñQås)h\ª)”¬sA<‘‡(w¼CÛ!?Ù å£üŒÓûÎà/’i„CñþâÁd„`oy¡ù¼ƒ‘íÑÔÃÌâ»À;¹¡ºÕ´XL¼% 3î¾ß„.ë4@· ÚU'»-!ò¹Z‹wû€æCcÐUªÔ¹„!5‰h_XDpÚ%k !¡”ÓRð¼.Bø!Y)÷7´»@Є÷db oP€;ª¦B{ÙH°2ŽîP›ìl.ÀÅ<,¼x(®2‚Â(™œ6·¿×1.™tCrHpèÛ§P¥Æbiv²˜ÊâgŒk/k‘¼¿8S \-`Ë……®”M(³ªFŒfikˆ÷s5ΆÑI0\ÅP(…C84Á•E X±‘)þ¸ÊN½Nˆ¦H¦ÇH=«ÁhPÔö; @²ñôœ—xÞ|ã°nÅoö[Ô{‘à[/„›wœ8Öc\,9‚½½Ç±¦Ðßbœ·l]Þƒ î­é’[8ž»ÔfCi­ȳFò×; žvƒ­ ‚Æñx´…ï zuŽXÖ–(¹j3»™¡ÃU­…ñBøâ›%´Àä6SYf0oË\©ÁæÙØ03Œ˜°‘„°N2í\çÅ^×HêGÂ`Ð’E€À: àb å ÖuÏ/íñrGPØI؇¶2 ÈB Ha¾ Ä’$ Â"a"ÂBI  Â)Å(Iò›Ðˆ€´°OWc¯ÐÊ à §’0|üªüO9ÙW_ ÊŽJU˵Q!²´¡T6ƒ8w„|ŒR‘Áæf=ÅÃxçYÅ€Trµ]kãÃá|'ŒòXvBô>›m–Váz«À¢ÆwÞ^Ð3H]Ûu®AÈÖÁªÊMƒ¶Ø© g;´1M·x‘Ý¿'Mó‘õàÅ›ó@¶YÌÐ[ÚVm—ß•àRBlän½›Ì‰9?’oé.ïÌåÁ ®ã’k …Ž5©U #PdŽd¢ôS#yRõE ’HâÖJÈY‡7B-À6½Ü—ªæ°DΆ–‚¢0¥)CÆÒ´ "óÙúç:æ[?: Fð¨¡"RzàämzBÅyƒŸr6è°;*QIµ'‹3&Ê` ÀcqÍ@9p7d¯#ÝóJ`$=ºÉòÁ¢ÑCpE‘€ý8EMè…"‘  Fˆd™­%¡# pKü…Ø^a(0€ÄC™~^îõýÐy‘D 4Ô‚ÓA(B! ‘‘VA-ñiˆÂ „„!…¢d z(JŠÈ!‰,X°²Å‰aRDKX‘R|Z**[à‹qŠ•M)·"’ ':Á«\, й™b¤…0ˆF ‚glˆX/THÂ&qW+$ªª@•jL ¶ˆÈ Z2F0ƒÈ ±H%A@© È!UB’ A€‹ ” ˆIDŸ¾Ã÷iò°’>ÿT0GõL°žâ³‹ïÞÆƒ§î·gÃÀÈâå½äC¸º qøÈrAÂ÷3ƒPýåb’ÂvðûT°!ñì5Ô„ýÃì w,ü˜ 5w BÑI-¬±q·"#Ib,„ ­ëPCPBà ÿ|ó¬©?êO°ôñK†¼‰D’–#DEÍŠôŸöA½©$841Yƒ#Ý,—Фˆe˜¬ž ò`eþ¨ NªÎÂ0<ô1¿ B.~ª Ô~®JZÚ)LXÀ2D?ª@u€Þ*D*$ˆ™@E €Æ"†FŲЇM(Gï)‰Ò#Æ&ÈDGE…JSË~V­aÜÕ9,’Š@6"åÅ?l¤ }Îh¤wlY !HAèÜCî !ª&FNPâzÈ "mÍ`Ùˆä—"È2"²ØãÜ­›ÿ¼ím-YÿeW–ªÐ«ý{iÚ‹Èè¨GQ›à "‰¨sI©>SBÂos„¦Q !H# "¤‚*n³v?9í @©©dJƒ°ddBJ¤¨B,€FbH1 ÆD‰TPFzÐI $ï#L2DH@‘$’e#ažd}DM}ô-KKD©$ …†B›È¥>@%"Ä…#Ùé¶áæ*î-®qþQþÈiühý4!]&y™ØöÃ8'ßìžøH—›¡í3 Ë!º‚p‘ £ñ'8ÿGC\dפ8â{‰¼‹QS\þ°ò$dŒáŸ]ã°õµo›—àNS„œ(/ã€pÞ)é÷m5CRªS&\LçîôøôÏ|úã¤Üåo;éÈ:Ìpi/ÝŠ’G°{É  ñè§œPÛKT ŒD,¤$‘BÐjZ@Åà ¿dPÉ@—‡{š¤ˆË ùQû\»£¬*¨M=ÚÖ) ·½Ã1cZ’!HJ…Ób²Õ7BŒƒ¯Rf¡‘ò‚,Èï51Í>`wv!hßY7{à†°'yF“8}›Ã뵬´Å—¢Å ¶´û€ }Ä .@9Ú¡!,FJbÉh¶‰²P*£ˆÁ˜˜+ï¾ZIGád¨F’Bê8£T Êb È6Ú‰)`I ¡xÂÊ©TJ•R °©$$@ ˜ÀÔ$R£[Ê ’ ’-ª’ª†ÕAU@ý(` Œ’ ¡1jH4úÉh†ÂðI $‘`ÈD$¾¦¢’H¤BÂ0€ÈHÆE’BQ¥€H! B "„‚H «ŠŠ Š,‚öÅŠýfOM ?ïìüIX5õÞnâÂ?£1Á+ÉvÜPÏŸáÖHÂHI¯»ËãÚ÷–‘XK³‰`‡+¹r& ã]Œ0.œÍ3ÆD†•û`^þ$ÝÙ3…œ~ÛVÿ¾+ž³+pÐÂãá˜2N_¼Ù’Kš¯ÒﶺԆEW¡Ým·"H…á3 ¨l¤¸QB¶Q{-@afáHÀfÕˆb$XÀ@ ‹Hˆ!Q$Ut‰h9—¨HCŒ‘ Lª€ ‚Ér´ÄR¢0H©h!¨-•ÌIŠûOAdX Ôª—Z¢ˆ²)>’•ÜÀMùC ¤üÅqüA¥jñ9Êö/M€ÏP/phÛVàƒ¿zå6µ¤7Ñ…3•Þuê¢$xIf{òPëNSúÛ¹ ,Gu)Æ T‹,$Ä ¸LƒasÎCB¤‘¤¤RS J*˜’KÐT H@·´’Ií…o•¸t¢Ð’´*»è²Ô9@©-Q¨5A½D ".狨o é!IºÚÀ„ n2˜ ÀÄ7A¨°‚f¹'4à…°wÚ£bEÇäáHRëŸüH*I$ B0àùz‘ˆ Ebˆš Ì Ø )•7>mÈ-àú¡díET2³W%ID¥çÆæR €2@‘rªH$’Ry!Œ¡±Þ~zø`Ê¥4G q{BÁM7„‘"ÍÅ-(HðˆÑ ŠH%-¤¸\K1 Áä¼DðVøèyÜ×hq•Ë‘`·ŠQÑœŠ7„¹;@;[ ieÏëvÜz”@¡ŠœgXƒPj Tl†ph! ¨ŸôÒUVÃÁ–L‡@ð"…ˆ B€¥¡õuñ£¤õa-iNMDoAzµív€+ ‚÷a2+}í~ó%½´8I`È Z2cä_ $b¦7´€›½=˜“~»ªÐœK9áÄ É-ï-‘óý¡á§ÿr3#ŽýÛû‡%±‘‚·ñ½‡ffrÐÍÆg¢²4\XµÎÅÁ½Œ¯™…½ó•‘SC©¡é³¿Iéù­™Ž^þ ÊiU ;#À†X8íšÉh–€K[l#:äô˜Üõ‰x–†Ä*ìöâÕg¶·˜É7˜†zq©!÷ÜË=¨ƒ‘Pn2$T"ð5”wi¡¹yG«5÷èçþ"@Lr¬@á~Dˆò_H¼7!òˆDÍBhÈLjaU%öã“è ‘«J—Ëøƒ dÀb­ˆ©WõÚ|‡œ_pHV*H@ 6ƒX(¹¦³U>z¶h|ýL¡;™þ˜¡ð?‰ÁO@¢H wÙsÔl’SȱV@”HA, ¢‰@!!!#h†Š„MÖ2» KkY6Î!ø”Ò - h;!nƒ`Êؼ‚ØuŒ Ù3†Ìt f@ÎVKìÎÂfJbµ²9™æ4•CÒ G-áÌ‹CPíXA¤¢B«bQ){м„ K°d–(¦Å(†ˆˆµ‰0[Ä‘- A$êq‚“§ÒóB9Äd!øA+bº°r°Qx:"X0„À ûh$[ È€ŒŠ@;i`ÆH‹º‰6åD%˜KTbUF–$H{uê_A܉¾)ÈôÒ´àî xì0Êâ"7ü,µljå9MµL5wBΤ¶ Ñ”(I%ê _}’Á$$ùSNg$m  l¡cKáãMÛ“IQL#CR©ÕbÓÁ ¨Œjí0f×…Fô•t‚’Ö-%KA$ @Y"Tg:«ÕDáf@¹33‰XT¼%%i +p.b ¢BK¶.1ØYªÕ‚]†!DZ&,Ñ%ªUÒ î"©Ð€-‹”˜¢ÔV– ôÇ/ž ]bÄ6)r’BÒš\¬(çd¹,B5Reµƒ7© ˆH¥@ÔÊ÷I¢‰‘³#Ú6ÃT°eã“E´.ƒ”¦ Uþê[¼J5ž™Û/&7np&pįݣóaÊiTÂAáAR2 ¨ØŒí«hcŒ-f¹õÓƒs¤ßrœ‰ ìc#EŽÇG& Üe|¸®Aƒ"B¨ªa ZÁ„‰-Df*è9”Œ_Nü*\ÀB1…S"kžPyHŒN$Ä{`tF¨ÔÐaP,D¨T¬Ð,`0R<ƒ" h,I(¯eÆ€¹$R (*JH°ZH•¦1• ´(%Z A , ”B)Î)h‚ªUT vËY X"°Žœ$"/zXÝP¹u£ê¬Y˜R¡!#,Š «´¯© $ ;ÖT˜S|:…ÐÑCTSÎÐFJRÚhSðÈ l«Î¹‚W©k¸?ÜDÎ1Øó‚0 ©½Š¢È¨B(!ÙQ¨‰Ȭ ’)QQ*=‘ìˆÀ€Ä€¤b1d 0"ÅŒ³k š\iˆ‘EI?N¦©c@a_Æø½ÍP)CœBAH…hŸ÷ÃÝ"ÝP+¥°@‰FêKrŒÄoY_&Ôtô¿x_Ì $T„F1d‹Ë‘œ$ z©O°7À)ôÂÄ D>xõžñÿðwàkÐÏó%„iÄôt®¡$9ï ‚–‹Ú ¡LÖ.0@ƒPKª=€–…è TJƒD!HJ ÑPT"”Ô”U B5P¥ª FI$`4JYER AEUT bÈ„°¤ªU5:G+DS FФ´±(€Q„%)AvBÁE$*Ê…2,„€ E•¤ H’F,JY!EDj©¡ŠB$$H2¥—yé4C$W$YöYÊ2w@îµ,ˆÉRBB² ˜‹¼X°‚ E(Å‚Á# $’¡"+Vx÷Ip2Ì8Ä€$úzLD¨¶Šü~jCüÄü? ~BnŠ—2)K,IöÀ¨;A.ÆÖ)°™,ÃF“"áZjÊQ¡Í ¥¢¦ç¡ÈC˜WN4a-V-m[ë]Z"Á>ãõÝ[ŠÜOôÀ!ßùÄ+ûÕ=ZgœJ.¨è‡íCÀÕ Ö‰ð­@@PPR@DE@‘@d$$Å$AdFE@$@„U>È££ô >ènD|°¼û€¥ÿ)úŒÏ|è@~áÀ™ø‰êÜ1?‘T8 ªpÏ©ˆ©hÚ+ 2"Èé‚®;Þ*äŽp$‰ñLD;ˆ< ¤h=Ybv |‚E ä\¦N¬KÀ„F@‰!,OBÜD+nàÔQMY¸†™H@‚IP8ð±`—(bU¡’‰`°0, @„HZÔ°*HBFÐÊ%ÄÆòÍ’ûè ©º%ÂèH°Ò§A¨ÒTK1h„nJ M”¸@‘#®—#R[÷Qh6¦»³—nI Gذ´¹  ØH‘1ŠÒHCHµ|¨ —Æ]l`õ°Ñ£êr.²1œN\`ªg之’zG@ãÕVÊþÎ2…m:' ^…BB :=–KÙ5æ×$BF$AP™DR¢ÓQ H0e BD*\ sÛ„²/%|âÀU€ ¬+až‘L³aX·SØ€'Èzâ/lW<ä yîZõ›÷ÀdRABDŒ!ÂÎo– >’ï@Pêê‡EÚ?À¤nFÂÚS*H­Æèá£p¼oM0‘¡¤RU¨ŒÅ°ÂÉz…4@ª¨ ±e°¥àTd*¨nF£EQ …I1–(ÂM K–µ‚Í‚¡1[PÐ.L,s†h°°!"Ã*„)F– D«[$,­Æ$d-$vð?IJšssAbZÔ ÆD1#Pmk1‘³!"Ȉ'ù…Ÿ^ÿ·Ãò6ÆØ¬¯Šò¸±ñ!ˆ9ïfG4òl'žgë8ûÔä4æ×Ã{9;Ý#·8ÙvÁ2¶C¥šÁGi𠛜îéSZӮݲëxÞ»L½’œÑ^†ÛEd_¬¡ß5ªKçöf䎀~R™¶ Ö Œ× ‡ƒƒ<!ƒu2JX^ù&Fð{¯”¾4Má®â¾04ÖÅàŽGxgˆß1EÇŠɇ% € p·!¸A´jS:ÑIc=5 Ã&eÔ΋Ç[Ð$ç2‹‡NT[­qÑ4¶"ö­%U¢ºÆ/&$ 2«MÀæñKNà“”h-­²!¨hXÊâTýX¬È ×t3/~fÅЪ‘%¦7Sp—ÁbÚÜ–4¶,TLQ5±ºãDt*¤^Á–U1™ÇM ²°öhÑží·º^¬dMpé†ä0]„m -ïNw Z³çz ¹Zémâ”dÇŽ6n—ß&÷}¦|±c,ù”nÝZåáXãgi½ @LÊ*P‰5TB†k5›pÂ@ÈcÆ4©-Ћ”Y0™s/KJÐ`®PºÐEX®ø|~¯´wPPik¤âª”U*Fæ‰b‹é•&1‹”]¢‰bÙBô0àj]Þdg‹åW,Ú$¼nBª¢Y‚Ä…QE.\Þk\íÃWH…Ðf Ýûbpèft/Ž„òÝ€häð€ r9P&/kX 4K†¹ñ±rše ´YCœf®Æ—4 ÂÀFö‘‹5Îð¾1{^#1r­¡jäIW±d,ÑQ´ZflG(#‰/E©(é±W0âåHêž[É-­s—È $T*ƒL¶¾7;Ø3)’$ Íæ<ƒ‡u ôØÜi{1æÆ1 û—!hBD4§¿úº5±Ÿ®ö/vøÞ®U@†¾à/EáµSŸéà ×Ä1*Ö¶ÃtòeÎübK`h°D 2Æ‹½„„IÎœÊ É0ï·e_º¥ ^ÿ…k˜×qÕK™Ñ-u³… ˜ÆX2oâáaô™o3þ¢e¿HÕ¶Úê²¥šÐsæLN¬°èSª,9oï¿”6¾á‘æVÏlCKÑo¯æœ¾Ì4rvKU§¯l†cw Ë¡8iYsaOhuÔÛC6·/ "›Ã™ì=#Ç?1àén+{Žy ‘ïÞr3µí¯cCå®\’³î&›×†yÃ<Y3W¶‰×2ŒJ¦GkQÀtïÆè›÷S vAÚÄ ºoåʪª¤$ÜW/o ¤«i{rC‚!£ŠòW…ÀúÿR éÅXî $‡Î@9_[Ü¥ÐHô¯çѹÛñð™1é.b¥éÂe|d•.bMé%ÌíS:‘†BQ"Ü!hUYFÄÜn‚'iº=ÕÞE¶+lB¤‘#¢DHÒI$HÃe ì!¤kR¬Ez‰”Á‚³©ì*Ø©*MŠ0N‡AߌøäÞwÖ8‚òªlAd“ˆŠC!¤I‚ñDÌ1Hf´•ûÏÖ (h`–‘{P•1dy¢ !0J5L¡äC!Œä²ˆ„,¹!m1!¤h @œDÈ$I¼‹?2>€vÉLÈ’Iæô$A„Ð¥j1eTˆœ7)‚Èö•Ð] ? úNW CsænhÞ»Ž9fG’¹:Ø.ÑF¢B#E›Ù0/e.ÌD¼ÉŸéþêý!šföxG¹œG‹L̯ª”j˜¯½*¨*¥ˆÝŠ 7{4êZ5V‹MD,4P»ÁÏ41¦»·\­J¬…l(ãR$â’) :t©)Ô• Ì Œ‡¦ó<ˆÖ!ÌæZÈÂ!ÊŠ €mÑ !tEøB&1‹®w¤ÕTž¹&€øÒÆPñ‰ãHXÛdJ Z€Ý#•j2UÃý˜,…Í L²µï´,Bø±,Ô.E(K”ÔH4dT¦ÖËŠ°Ü¢Œ±V©‹è#hvÀ©÷E èœ ñ‰÷‘;ÞòßC’˂܀ÔD¯À f]6$(D:tä)2S>¢Y#bÄñ,…¤ž2†,ú£;^ÙèjÓ–_ ptX€ ¢Ç䨓ád| gÑèØ¹šÃ-ãnÇ%ôŠ•ùs9rÛiAOä>þ>2˜Ìà&.`# •X·ÛÜYË´ª“™þ÷Óc^™íD³Ë°*ÅWN:gæIä† !Àè@:*èéæ(½"Mml`Ä++®n*b;]ÚcBùhí{:†ƒ*lX™´^å&c*BI–TYÄü–KÂ|ˆ wºä˜µQ„ ànÉPøç®gÀoãYJÕÈ.‚÷ÄTU@•Rû4qfv±Ú°qng°×†Ž­›œn "œ‹FðY¬q8ePták­¶a ƒXCxc;‰µm{¤'ƒžWl²4T¡Õ¾…Q‹ÞÁII­.Ø+8¸áu³Šqlð_ukbg˜%eP- 7Ò_q–KÀ½ƒcxXÓ.Y% Ú¥…ú¬já[„N;Cm®ë™ÁdŽâ©û%Õá¡nÆo±€Anq؛Ų“!•§öô ØNîÿ k¯¥-`ØêXr09i ôµc,)j”é*Ô• G—w8B3†EÎÎT9@¶Ë¥ƒLÜr¼•U”%ÊVrÒ*;‘ešéYz]ڊۛʎÊÀdÕT‘™lén‰ªþc=0vŽâ*W Êq——'gµËxIÞQJ„ŠI „ @ŒXƒ"!ËžçqƦú¿ :ŒƒÎ…sµ?™ÁÒ R“òøœÀ9Ë4]í^¼àj¸äpã: br'µ !ÃxQËÁ.p!«kÊ-&¦s20‰DŒ ¦FÛn™"Û(^¦P¦È-yp#Q ‹ %!kf¬-ËYhXUB‰B5‘1  @`Bªh¸i ŽÓQœ’shb„zJm±L€îH)`ª» j£Œ*%‹ Yˆz®e±D$1 AÞ‹7—ÓúàŒà‡$"¦(iFÄî@æi’\¾ª+“U£T– ª¦1Ëg’ _áBÁéHÁ‘,ƒebîaÍi¢2×Jð-þÿ§ ƒ·ûÛ„µÂˆ„#,ˆ¶Ôj¨@±M'¯ƒÃ€²(’ x{Æ•mBDI$„ dPd d@ ƒ PÒÔ$A¨•I$Y‰FE$@‹E@„Œ$$ AIdEŒdTF@FB@ d•@dA$F2ª„‘dP¡•$$E $„’ҥР5D¦dÒRÜiý6r`í ¼$S4\b6.°‘.‹¢¶ÖBQ(ƒ±ÚTªÙL òd#0([Ó¨mì©hžZQÀ*ª Öû–IwX¹ybÅÛ1i¤1|eƒuÏLÊ*M2›áMâ^Ò,•,Pµ È@– jIKPršHbJ ± UD‚DbÈÁ‘e4R½Ë X¨@!z¼-*€T‘¨A’—%šÅK7F¢É R¤„H©DBH_Ö‰“ceKY“:Œ$ daE#üæ bòO°]Öù!P8µ¬E "¥ˆ‹I©÷JÐO¥xËPnàB 0X Æ`)’€BIŒ©$`Ø:Áfu¹7=‘C Úá¾ûì  rªªkID@µR…WÓd^Ã’‡Q éaB ˆaˆªà¼y*bæêзÆc>V ìPwȲI3ÅZœÊ…R”W"C;4Z ÔLKDµQº.!–TÖZ² !H/U¡­Z«BÑcˆÖÀ¬â´©r“,è½ÈpÌâH–”DÊ. 7fTQj¬Z—$‚ÁØc’ÎÜqÒzOA¹®U²#:îSr¦ºæôW: Œe‰'9P’$A$J… RVv ,¤`™uƒýR–IbŠÈþ°O÷˜ÿwiÝì?ë¿æÕcãþä̺; y0aü†·€p[îp,¼HvXȰji“‚bC+X0XÏnù̽ƽ(}aÈÿpÕ¢J²°ƒ,œ>B‘B>qx™ å°h€óû û=‡ÖŽ—œâVýÉúvËÜ ƒÓ¿–ù dGÞ¶¼T7ŠSã¿·[ÿx%ŒæêÀ‘ŠÅw ²Iº51TÒ(T ÀR`a!t( ̓€ª(¶‰G²)ù œ?IGçHÖeÛàBA.E.±‘@&ò„ï¯jI ªÈËÄd¡"!1õüt°dzà§ös?Ðk¹HFÛ–õU=j?å0/‚æB©åmT)ÒxRsÖ#Pü~ºFBìR@¶ôz n~h't>ù:Ä,AµJ"´¤.Z¨„¢ªKœŒBLWÍ鑊ȟbS†$`D$U™)oOzüóççjªõ Æ|„Ø•-б^ˆWv|>™™¬ÑÐO›íý:|·ªrh;D9Â%”J€.Y}›þâ«#J£¦R jÔ‹ù5õƒr”ÉOþ4Q@ÎW攸wn,0rÝbÀÊ$‰"ŸXJ"‚H¤ ²#gt„ @Dm°…-§ð#! 1ÊTC/¢ׇÏWZûGÕ¹RZú±¢K¸+è¤D¢JuöI%ýöZ‰ØL{®Ô  2¹Õ)´±EZF%U‡•„J¸R Œ$X D*áelŒ$$ ’@I[¨p‰PÕv›´R¿•¢Ñêˆ@5T¢ vûÁ´F€ªŒ•Œ"æT… Ox^ü@̤u¹¤,&¤ È2!9¤¨4¨SÈÃcÇȇªw“…uÿFÝjî…¹ÁyÅ$JªI ö’]õÌzuؘ{ÈnÓ†¥(GB>Ì4ÒÜC.èRî)è MËà"dW§ëÂá¶t5D!$%/ e!RDÐ4….° I‰Aÿ¦‘Eÿ®T ÁS¼wÃï. b"zH´g@D¨¬‹ ªåû ”Ø]2G° d1 6„ ¢%€ÈÁßÛŠ¬Ê=! Es…¥î±¬­gß ,ÏÄýD?í0(b"VT©hZ!HA`J# „5L)£þŠÕŸòŸßtßÚSûRõU“F u>›™H\™RÒPX³$†Ck¹ü]¼$„š`ªÍ°ÜºRAþ¬ì •&Pck‹ek&‰”KGR#“€¢²¡ÄK2ðmâr%|úéŸ ¯­Û\9ѹ 7DÓ/æhj±ý؇»Ïåç©óï6|¸FÒXîƒbZ¥PZ‹Z†@ÍM6%^‰=Ì(µR·Žz3Ìôzç™Ój5=?UƒBl`Ù%§ ¿Îj÷ÎQ“¤ Z‚Ùsk”Ô =66„ã>Íôa‡ìµY¦Äùè,vÔ;K õr:œêt:§®ÈjÞÂr-ܱr=Ø¹Ž¤ÊÌM9ÈúsöLõ–—¯Òó‚ÛôÖ¶Ò¨~ØHça_ˆ›%ü¢Øe(v¨A‡îøÅ³4µ¹“,k¬±œÄmys+q©ÞÂ@‚È‘RFÞwÄ´=yiU®òWzGÜêsÊ^g¥rªÚ¸F‹ß€¨-m'˜¼ˆŒ@eÄÖ~U>YŠ d†‚‰ü7ÄŠfƒ¡,vpþz8’vV³2FyU‘µØW‰2+ϲ2¶E¥å㤆a§Ý¢pì8)œ~Šû~‰àY/àã9éÈð>ðÆŒY9çÆµ‚ç#}rã†Ò0§Ó³¹À—¨T2½÷”&Ÿ 8fÁ"Ë6lmò†ýƒq—]Ý›_f¡zÌ. ùC.ËØ“KT÷ß™«±DsÌÅgƒs™@ð½®G,ÌY˜%-L²¸X­ñ3ržZ¥gRKª ÿ“WVEHj¶¹“`ã{ÇNuÏ;LêLZµ Ï®ëe 9ps'º&îS’n§ëô‰Rî!óþËY´ E$¶­õ5"[Fƒæ±ñÿWáoÛ }ËÚ¡;÷-Ì®9ÿ˜ ¬“)¬†¬eƒÀ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ±é`:£¼gté Ž^uw ‡ÛÕU÷wݵöŠ.íÄ€n`¢=ƒ% »œ €ÓTÐ]6À }ñÔ¨;{æñ*¾XATmõ Q@1o¸v.Ôc–}ž¹gÓu_õº¯T¬q7z|ù÷ÍØhlPÖø=¯È¢ÏŽˆÒ€ë ;s`ôy¾àØ·Üè@)C@4ÐF€ `@@  9ïfeì9U@:@ÅN‚€ï»”¡¶t ôèBì­J¡A@UÛACEhh@5@ª(f;ãç¾,'ѺîSTnu.g:eµ¶±Ö»|ïE¥l Q«ØÑÑzÐó{ÝooŠáƒJÀ ´4‚5Ð ;ˆ÷º{eê“YÖyì}{é÷>Þáæ¹'€:ÖçXÝY¹gL®»‚Ú@)JÐ Tï§‹í½×¼w³{­íoã¼° 2ÐP8x÷‡ºï.Ð>öào»Þõ^À)÷ÞáÐm;*õ•žžßd•(¨’*Õ44Òî¹Õtn0o\â•ÙêëºUwupK¶:¤™³<¾ÀûÙ ððmï»îlß7}jo¨ãÜrß]Þ|@¥€(SZP ÓIU@ I¾E{ïÝãµé«Õ¶@ÝϾÞ°%¡np]»Ëνἶ#åºç;ÞÇxärø€zíëKZ­b†åvùî¨"S6ë Ô9Ýéà{Û½´ v-ª×¢½o­·}{½†ûp÷Öçƒ=}wÀ£X_Y¯¹ÝËí×c¢@Sc*ƒ®ñ¼«FšÒ¨{Úø}ÞÞzo1ƒç™o;½m7¶qyÜì>Ø6î®G.:æ¶ðJ¼Ài 4¥çÅ$£ï„ƒÜÇvPöºô×='vÜï½r2LåmÛZ’m¦÷¾Moc»Öåw³]ìÕìô¡îÏ{{ez5ãÝíg·ÓÒ5}à¥}Ïq»=êzÏšwÆž™Ïp:ö÷ÀAôwn‚N¯cNšk&MvsúøàÞû»ÚÓ/“yÜ÷|ßgYÝwLïn]îgVÒôÒ‰¬9³@P'½äz;`®µ»œ4=°tP÷`ÊîzÜxtw±È;dØ×MW¶é¯BL½g®pÖ½i¡v• 5¡A£mÕ°4·¯sÀ£ÛSFCÐèt7gk=ñ¾í9÷ž’@O¼ï`>5{§([43ÞðuBp˜Û ÅŒ7KnW7\œîáÛwFUÌU\ƒ›½W¡(®„TS½Üç×§m½ºu× ÝRÛÝÃÚ}˜½çLöx=ã¾°-cÖ·ÙÓ¶ ì2SÀ>{¤è*ß=|{NÙ%íÞ7´÷†®ó7ÒÅy;Í]¶Ï[ï=Ö·Ô¦¾’è"Q»—Ìg^Ó‘Ød2X1Ú)v AuC:öôï4¦Ãt7Ý}úÛè}²'ºç°[®Wws–5‹ïklS®Jú÷^Êí³XÛ5Òë¸uÃäÖ雽â_|øƒ§Ãà1g¦¢¢¯g=Á:bcÉÐ)îâålù½ê¯^÷Î7½Ïº>úz9&ôJ6nñ¦€÷`õ2NÀ †S}Å>»Ó·D’'52ÐAssªÌj´ÄR` £l†«‹³®pvÙæËžYØ2•P ˜Uw½öù«½Ñ|¥ò»­Â€„PÌ1V,¶Ì™Inû×¶x2¹MPM½Ü:mnÓ³ƒuÜ¥!wg»Ç½Þ^Û{¹}ö/A‘ðÚêmiµ”&›Ž+”±kZe4Í=ÛîÏ«él¦Sè¢Ø£¶MbÙˆföîžo<ìRPƒ^½æ<Ì7°Ë@;·¶ÇzŒ’Il27sçËÓç–™+§9”p{{Á’ªgfݶú­Æ4+^÷½í=·y“ºÇm@îI]n5×CƒEÏO^ RQHHíçŸ4+fù÷^%QD‰ÑºÝ2¬ÃâÙ„WÒçs¾Û¶IõËF ÙcogJEz¾mu}2,Úw}öØ=óJúЪõ©û:¹»c°vy{(½WÚ—m÷ž³M»(kèûÏ{ìsÕƒîÁЦµ#=\öíw‚Ù÷€è:6¬ùnÆ PâÐÁî>>%}e:d¯»®°Ç€i@Þð€>€@(|óÞ}·ÙGÖ^÷¼ ö«ÝnN¡ÑïEl3_3} "‚Ù‡Û€€€W¶[ÞÚï ³H«O¦úɰv™õ€=NIè< ÚÍ÷g>Ï^ð}ƒK¬ûUóM˜ÛO63ÁšËLcEk€=ó×Ã"«ãf ,\‘ÑÏž÷ŸxzuÂSD€dšh ‚4˜FƒMdѦ”~¤óTõ2 MQ"šFÉè¤ÓF„FƒÔ@F’R$I1¦Šm§¤m@õ=!“j §¨ÕÐ=@‰ ÐL!¦ŠŸ”ØFšõ?Tô̔ښdhò£&˜Œž 4€ š L™ š50!£QˆÓÒAê=C “I Aš ¡ L¥Aÿôb*Íëþù“þOù}óÁªì’_øÿ»àå/ÊŠ#ìw¿Iÿêoø%ú~¿µÿMühWöÏöoVÏO=•·¯#ùY!I~X¼¬2ÿ»€SóB¥ø¬¨­¤~ÿ ,šV˜Ÿ'&¬LÒ[ã`üp¥g,òÎ\¬x¡<ïLu²°j¤/ü¾;Y>éÉÓ$ñ{¹¥”·LiÖÕäëuПÿŠü^Ý·sñ¿rÞ§­%b½oóV1XgÆÇÝu1ãBì%]ºY”]dŠî¶Û«IÎV¢éŸý^©mZ뎈£µ„î®ø‘ÎŒ‘æ³¢’Pžû’I•sïß¶Ô”>ån™ÏÿÇâ§BçåWô¶ÙY;?Òù?-Þ3ŽÏÔþ£Üó÷ÆÕI™ŒSò}#ÿr‰_ÝLåAØrËžRt_œ2敦za¥Í¢Çÿ‡ºÜ¬Gk“¾W¯?tË4ôãŸ{ÿŽE¨<é†ÿ½§TKÉÿÎîÀ«Yû‘¾¯Ý û¡þSü%{ËчñðñϼØ÷!ëù}z:bQºB^—cªò‡ JË–Ù½Ç=ެ%aÞF¤âþA5rËÑM-tyðêb¹Uÿ™‘äô¿ú}“çÍñ_qþC§ÿ}Œêê—[é}·U©{ÕÚ‚C»9"ØÿdžP{qÙ…Ž4GÿgÃÝJ!¹/þrkó×Ñnòz-ˇ4Xïµd¸IÚï/>û<BÙm¦hÿ*Í«JsMÁ×Ëÿͽ–ÍŠøuå>³ÏͧÛwÝR_i²cðSë–ûdò}&ý3Ò÷œÜ P¥kVŸôCд™X\ eÿÛÄê»ëÙ‘i.Þ¼ú­†Îµïôùùl‰pŒ¿JÿÔcÂI7*’‰Û˘ºÈÞŸNÊÓ,Ë‹ñÝÇöí]ônÝ»¸Ê!'d›r½>qµ7¡éJ#ÿ®7Å¡¶I.µü®ýk_ ŽÿSt°.Â9ðåï%” ~Utí{èÿ«óþw_áÞˆÿ8õ‰ªDÿÐÙ m$×cw»¥ûˆvÿ¨¯´°éÝtw[Ù8¬ƒ¬˜>2ågÿ ï20µvÛNDI“S$äÓ?è‚<Ó»8[gK~m†øšÛòŠàn×»-}sÏ~qO"Éc_ ã5ÚYó/=ž¿¥Ë ·/š4³<¦áÁ&n§1-¾ããË‹µöå¿Ö*5—]™<Öñ÷ß±®ü»{«>mŸ,¨»‘ý<öÙ>{>y›aHµ¼9|{öÖ–­bݦMî` ƒ4Ìk“nrEóÝŒ])ôYJ;se¤ê‡gS (D ¤’Ø”à‰”hðQ”’?âý8muR’³¯\,³‰ú¬–Ö&î]”ì“z Û3Í®¬ˆ>›5•Ê/QLô!Õ(­NÝ=¡5ÿžÌIyõ…Lë%ϞȉšIA÷¼ RƒÈÉãÀ)xEˆ95ɬ+ŒÝç¬2®cŠE»aÓñÓ7¶#(ÊÇj¹;R\åÙeêÂÛp9(Á:OÛ‰R(‰¾¥„æì1ïÅ6F+‰¢æ§#?“sÎk¯Ãk­²ß>HßѷãtÅs¢Nò•ý݅Ûe# tÚôqÄÙ·e¸†øºrÛLõrL¯ÉÌ,dÉ“)Ûq™Í»I~ý½õÍ}ˆØš%é?Jòò ö^¿"c£Éò›aÇùåR˜|2>Îû÷f¿ˆÌçð÷{ãuÚa;4Ó}Gú2í˜m‹¬¿v»K©­Óœ¯ŒôÃr—½2WnºíÙí¸SUwÊ•ôS»\Z–V+ì)*N%œëÿ‘D¥Ô¿wü¸lþzÛ’¼qï2ÎS“i\^c§ßH%óÿÉé7Je]íÛ—FQÍÆòü÷OÿNkçÒ¬¹_¥Ò1çΑ+£{¬ Øl±ê>.±˜òß%²®%{*O}^Ìpá)O ïÁNZÑò¿›†»q²üz-Ö÷³ugÆqÆ“¼œì²ô)^ôá¥'¶Ý“Û[wœ`fë+•Xa€;|ìß;£ûèòÍØ^åSM9ï+ù{&iëøÿ)üú•­±òù\¿×­ŸOÄ#éüÖ™#ñû)öÓ2 ÔZûç- ­ñÝlO Ôx§á cÍ#íZËŸu»c—+þýJ·áýÅðXøöÛLMK÷Zü-Ÿ_ýÿü²ÄÓ¾¯ŒÜ•Îé¦ú^L³¦+ûÓäÛ“`Xt7ö¯öœ4vcþ›6ß3»½¶Sg<ÖW:Þ.gÒÍž0¢7íþ¢•íy yÄϽ=ì˜ôø»BhAgÜZ³Z9íFˆÂxiJ¡<«¥¿éÃ'óËÉCý0æìÌ;Qï4væºÒ]”+c: 'üÕÈ9t, q&Çöó8Í#!æ¡nÚ&Öé„ÝÙ m¯X>tDzMÇaç>CšŠOõÓOHÿä;4Ÿ\{|ùøŸÝÿõÔ ûýe9¸«æþý6ôRÎg\áÞˆÖE]ìÙè˜Xï?>WÝ;U>®fè™?v¦—ø#¾¶‚v¨t”`Æ‚.BKW»±§þII¸& C¬c˜rò› ØžLŠ Aë:¹ÁÌyŠ–1Û¡¥:†Ã«Y‹ˆ‰¨Øîª9!¢§9§jÝiJÞ3”kŽ˜²)ÁöW$3®îDSù‚a?†ÂáÂà·†La?ù¤owýNZ›áß…’¡Ç³9ëÛ…Ø6 Šÿªwúsj%„¹Îå"RC#…ÇòCoìùBÿ»S0óu)æhSSüLª™þ*ÉÆÔ}aƒ³.MŠ" ˆ˜&"""ÐÖyç¤ój[ã‡Z¢¢Š ‚"‘ qê6ÆÆ5â!#õÀw§Ÿï¨ã„£ô?7ï:zPúE;d¡O?mç÷^ Q¹àßþ#ëÿLû…ÉQ‡ö£JIJ G;]‡@rtÈnã9â~¢ âLj»°mLÒ6’?õ=SY9yâ°Ïö:ÿìþ#c|'Á¶0Ä–©¤70pšý–))&?’@ø{H#¶ÑëfM ’ XŸ«^Íu\æþmü…úJ˜)Jd”Ø×Hªª$·y ód&Ö2Ͷc„8¡×óø¹Ì»ÃÒeà †ô%#>’b ¸þ¯»(~ ˜:ÐÆu>&™sõ¥ƒJ]_Eh•TUS}“$§v×]1Ž*÷Á¬ ‰r)åÏm¤àiLÁûLÅþ¾ý?Xµ×Éûù_¤N½×]Ït[…Ȭ®úîœÒn‡Õ2†›@˜U³ ŒTbµ‰™õÎÂ5ígæ‚4§Ò×¼LzOOÍ8·úì¹Þ*§yÿ_3õíOë;½üò1Øyz8K–^Ìܹd~8é±ùég‘5l¼ŽŒÙ‚<_êó÷éxRÙ 'ÏoÒ•²ün¿<ï •!=³˜ê€yÄïJ‰W^ó÷â”ïù~|óçÏ;ß»;^Üҡ߯p©ß°ú?ÕÌ„o÷û}çß™ß~F{м¬ªŒû䜬ôû~ß¾zúÎâéîî½î‡Ò‰ÉÚñm´¥l¶ÅVu3]çÿ!üGËÏ”$I)·4˜–ßu ÎÉ=öÏ]BÛ Ãá}òÒÁHp”!ñü?ül½7`ôÊf#Sðó›#`™Vš“ §)FÚ±Ä ä™Š’p©.–yrI†£œƒö‹¢¬|®v&É`G@á#âªEÓÜKyÆyâ[n8ô©ªã¢|ìlf§ûT3xÞwLØÞUU ôÒïý¤oÒfóN‘ „uÓ$+¤vÊÃ)¼&墮Ç2G!&ÑšDŠ—N£¬ÚXÅ¢-----8ãŒcŽãŽ8ãŽ-¸ãˆ8ãŽ8âŽ8ã‰8ãŽ8“Ž8ãŠ8㎠ãŽ8ã‹8ã‡8ãŽ8ãŒ8áqÇqÇpqÇqÇqÆ3ppçqÇq§ãŽ8ãŽ8ÃŽãŽ8ãŽ,㎠ãŽ8ãŠ8ãŽ$ãŽ8âN8ãŽ(ãŽ8ƒŽ8ãŽ,ãŽãŽ8ãŽ0ã„qÇqÇiÁÇqÇqÇÍÁÇqÇqÆœ#Ž8ãŽ8ã8sŽ8ãŽ8³Ž8ƒŽ8ãŽ(ãŽ8“Ž8ã‰8ãŽ8£Ž8â8ãŽ8³Ž8sŽ8ãŽ8ÃŽÇqÇq§qÇqÇS7q'qÇpŽ8ãŽ8ãŒ8áÎ8ãŽ8âÎ8â8ãŽ8£Ž8âN8ãŽ$ãŽ8âŽ8ãˆ8ãŽ8âÎ8áÎ8ãŽ8ã8GqÇqÆœqÇqÇq,pqÇQÅQEqÇÇqÇYÇ;qÇqÆp˜ãŽ8ãŽ8Ó™¸ãŽ8ãŽ8ãø0ùþ, ýÉ ¹…0'Ž hJ¨óbcNasXm{›<º2sŠ^Ñ5$L†ÖµDêLA9h‚’R»e}2ä?zïèê¾Æjh»$x6 Øv£v²hÚj$¶í”ëv#€Öbbk!å±ý_À‚“8îùúW^˜íÆ8Ÿ/$y±M@c8!`J‰î!SÝù[kNÑ6¬O…9зºUîÁô?˜O@ܧ"BþƵ­k Èè'ÏÒÀÖ{yæÁþÏò£{ÍîOg›®@¥µ9L#É@k"p%À—‚™çòôPû|·¢Á0mW2 °LkT>ê:M!&êE¿e&Ôdšn.nx<ê’+iÂÊ1½TíTý2±9 ;‹zý’:ÑUÿPT«ìFüré Bö)KLº©VXá¶±r ÐXå-ªÄñø\Òöß^SÓíÉ­¨m<@¡€™ËïøG‘TÈVÊÛ÷D]6â/3Y¼Â“ߥØI¥Y”¶šË&,TY ñõÑó÷ü%ŠáÔ톼ýß³9^å|K©ñé~…J3¤qR¹²£a{JóøÌÜH§ñZ¬>²cÚÞÖº,¶Ày°ßo)¿±NY’ÁÃ§ä‡økY6YlôÕÇ÷ö%>ÎÞ  O· IÓˆqhˆ E^ sh¥$¢…©?ÉÎPWÙã¼(Ÿšt}«r"Ñ”¯œ:ÁýI©uý»ºŠh™°@žwD‘aátjàÓ¶DFô3qÆCNì5ºj;sÊúBðbZÃæMîrÖì‹ ´© ô¦Á̰霫kR¼iÏ62é¶åaP‰Mäìæ*ñ ­ü¼küz°×8u®AŠšÈ®vIƒøeuºŒÉ1?V4¡–ÙØŠ«Óçòº]o޶5þT¿N./á*ò–¶”¬ñjÒ×{E~]”}jÉœ¹pzk:Âk¿õwYñ7z"F‡^ËÚiru8Ã&-ì-5$>a?×mç î3eòv “.5“íìÃ΃¬¿th1AãéóÖ‘>E*  Üãªmc”JEëw®_§Gª[ž¥¯}Ä× ¦ï‹§ˆ,Þ'BéM¡…*S¦OE/wåI¶tÜB;è0ÎÅÍ 3y{Úó Ò—¶Q„Xµ¦<]dðϵÛge¢åt+^d6éå9$×½öȉ>9ŠMy7ŸZO[å”;a‹ìM§¦mLåÖ%¿óÖHwå93¯"¤áÄBCsüGùáåÙMúPÃÜùš3mv×c¿3~×+-J²æ²ÙSiKC쵯:p.¾OÚàõø]¬÷´uü™Š¯äa‰Åý¾€‡œ.Õ+úOã©çUù&~¬Žîˆ7Á—sú{ ò—ü‹˜¾Qà‰÷ûºŠxkŽ&Þ©%Ñ‚p¶sI,_¢nÅÖÆºRøåxÚe¤íü~v†þXÝ’—êŸà‡©}pŽ#ÜoâÊšþÝù©§ÏìÑNxÚOåS‹bΓi?ûR¤1òLä»À£ ‰µè³å“âm'ãÅŸbÞÑ9d¦Pn=¬Ã³ql@ÅÓ]ÉÜú´ëQp’šI+é&0²(—vzÕÛ¡ùÓU]~.úÏ—Ó­äjóâŸýß³3ôâ£[+*XOhY Wý³$$©2"Žé7–,‰Zÿç‡K’°º{ܬØv7-îÞ èäI¶!® DÐOËã&´»¯› LÙ£ÉÎ8ã"äÓsv¸[/éBIdøöØhtzÞg*ù¡Ë¯èé&ý_§Ý&¬üø X¹nÇm†*CuŒ€~,šÞÛz8Ú|b:ÕDÇ«…râa¶Ôså)mJí}s$•ÌáéG™JÚ<¬B‡~Ž´Dðª¥yJãaµ„ÿÖœŸLwqQ·ÉKÍùñ³ ©Û* ˜ÓŠ~O¿ªñbšÛ@µÛª] ÍûøT‘3³œvØN™TšD’]–»‚¤·;¿Ôæë #ýß.ˆ$…p¸2ôI×]Íâ¤úäKÓíÂøyaCÆPÙ’–…Ú=’ †½¦ Ooî©è’ôrÙ×khé}š8Ãnò¿«k‰˜B®Þu®]¼¸¸÷öõöê\’f-§ ›¿™n¡MYìÓ2˜_YŽèI˜ÖÁÛ9–ÒÒu¹R¶G&€†|vÉ 0’$<¾#½SNe“êì™l+(Š·•á°9*;75µ€·æîÉHh“²]¹tqD¥Ò§íPØ.Íõ ©­A™QðØ ŒÛ¥5PEÚÅçû×\ I+ÑÍôÞÛ²ÍAµÛí]ÚÛÍn…?‰Û[.ZÅ´ïø]zó@Ÿ½×ê[Пj(-û ØÄTÇ}VnJ¤(Cªssï•u½ÐÖõs›Z‡•ylÛ L¹æG™L¨iÕ²LÔLRò0„~ÌmòýÙiÇ«§Ë† Œ“‚„¼‚`>Ä1\!Ê”K›2—ªÚy.ßý8'öò:åéSH}ìŸ>=^ce_„ té7ý ¤Ik{…<¯-×ryt˜o7{“/™Øï‘¸ŽxÍo›Ì[áîQÐì¦u{=¡2j÷I™‡LÔ@lª á¾*cƒÚHt&òÆÿÒt:ít©Mêb)-]¨ñ"g!ÝYʪx²Ü¤Å•`Æ4µ¸¨¶×`ºù´! %hå%$éêÒú¾¿Ý ­‹žåìÃã)¦I‚ÇÛÑÓòñ÷Æ6шIÝÒ÷'&ǵ’Éw¼ã¬Nï?5;ŸÁPò?»ÀDÜq/¿/I@Ÿü/þ g¢S{d²“·Ì»úðv»~áè§gL("²hSP!s8_G²y šÅ+Ÿr`ÒŽz3¶)IRC§£·Ô€½à›é²˜ìÇv´Û!*[œÜbŠÏÌEúµYÿÁi³_ŸÊìYO“Èìºì«Šyu„l]–"MC0¡• ²©­h9½—Äæ &ãßÕÑܨ¦s²6º:b"ü>­vVeéüLz­_EjÕÇ+ÙHÏsåhø o$B9`SìAцœ¬šµ ðc¤–»µÝ'›”é¶;ª÷[¦LëèÔIü·’…%ÎÊbõżËb†ž÷¯Âr”î‘bϨr¸§•”²s¹¾åøó–À¾šTúþ™Ó—}zu¡šýz»$.Œ°—™XE‹ã&d*®Aã²ãäf“R"Eƒls§ÿøv‘øcLJú*ïÿ|mÌ ÔU sƒIƒ@ÃdTi‚¶™VÈßê² f&ÎÃÜðZ3ù{ðç òd*ÛuÁš¾ngWÇïÛmq¶µù$Ç™‰Ÿß#7éCSжlX^¹´ÓKkúnãîÿ»Õ€¯ $bEbó;gðíyùoÕ_`íÉ¢iššZ 1žqxÃÙÆ!Òid˜ÌM$Ó;¡]Z¡·ð²`€ö¡Ý“2ˆ¢5³áæ°$Å©Š+Ó1r%“µØÏÛLgƤoyi ý]x2M¨ÝÖ-Lmõ¹])ªŽ<.|\¾Äþ®0æÍ—_y»üÖK²—e‘Šß ó~2/“–úò¶únåÑ*VÕ¾ûg„Û$­ÑϳGÃÖ±®XÉï:iÿééL=Ò?e¤ìÉâ8o–é×oaÕSI÷ÿT»7\bmîïèŽ[c–ÇÚº¶bTëZge3‘Š'…ûJ »Ý¸~íg·,µå+ébq"ï¥.²M%®ý‘WŸéºõb/)qÇãßT¥’V¬8ßZ©™WìR„ÞK‡³§3βÝtÛüweftçìÈ¿Zòé4‹Š¯R¾Çøö_QÏÑ”¾ÞíySï«ÙãûoÃæñ»?_w÷g%‡»l6gg¶úÔË[¯×vÝê¥9/>Xõô×}†°ôÝJâIþoUµÆ‚ ýÓÚ·Ïn[•Â?u;6¾“Znîá¾¼5|xîxà 'é—gLâuª"ÂDt\£¡æÕ¯³á:í~ü-¶õ­’Wâžg|ÔAtå'+º§ºE-:n´W­m¬ñÉbVÃ}ü¬…‰¢+iù§My¬òlËóçÆSèÆüf­À““ϟ麜v×–m+qÅxY%Jø?u¯ºêȳm2Œ9ë3ÃÓOŸÑuÅ(ð=ý¹a?M/¬ºeNw¾g ™]<©œ<¬^\ZÆpÔì¶8-×WG$éY“Ê·;¾_= a}’½œ_4 °Ž2{9‰ß¶—«]<ñ…W3¿G±¬Ñ›1÷!®48—Þ@?øD@03Ág§~6ÃËã…Ùãì‰1•Û!þëTÊÛ÷h „Œd'öàĦÄ4$. ‘HÉ„ d°že\s bÀ˜°¹…þÜe{›-²nဓláD@: € €APßüˆ©öè„BД1#E SŒŠ¨¿ì„:T%*hª4РÂIeZQÏòÿwñÔ5'òÂÿw÷áÆìgýšDú!i=ˆAÒCÇèÆA‰2€þ(â_Ù#F•;ÄCREÉ íî.î™*ΗûŒç8;ÁãßG¬z‘ÒG˧§eî ¿‡ë1Hð…ĵàsq’‡ÃÔ«$$µLHÄCL”Qó@_­GëÁÚÀ°}² … DÄ % Àx`0Ë 5¿câŽj¥g‰’ ¢H›$Сq6ñ,V‡$C¢tGŽðºc¹Ó¬SÖ†—³JPAµv:a½ÐûX礆úÔ3-¬Å3káÖų.ùX?Mó£™_‹ÃJb›Ï‘>šÞâ¡Í¾6‚Û’¼”aCºD D PÒ¨"†!T¤At é(TJTU4"*~d B‚¼ >Ù0Â$Á"‰Ü½qÂç=$ļåAἓÚáL7@p„7*j²,2¼l Œ$Ÿ!‘_oÄñ^HÂTŒAA /¤Tu‘ Œ+ˆ„¯€ç£!:ÁAG´àlœwêiA± nŠ(-úƒý»×CÄ>xÿÞžÐl“¾n Á ž©ò}”˜’x8d\i iâI€Ô¿q$Äùèq³ŠþŽf?¯‘¿´ü÷P&ÕqÓô¢~`Š…>›R P¤ÈÔÂ¥UL IE¡tRD40@PЩ˜ÁV, ÄàAD”°ÁDÄ 4Бpˤb$I¤¦b …*™€""I€ˆ¤‰$’†˜c˜\A8 ˆ2AbÔè§K§lU:ry¸­¬:6°èb¨†š *w‡«Øغ½Môê"ït QÕÊðMu ‘05S LA0K$”$­TL$ÒLÀA$)D ©UH4ÓT¡èÆUˆ ª(¢!€BšZ EbŠ"Pj‰Y‚ ‰TZ"ACRÑ@~•<^x0SêP$C@4•t8:¦í“YX¨¦ª§ E% ‚Ú΄ÉKšb(˜(("[d¶ N´éÐÒí“Z]°kI´„¤) š¤‰b’$"b"!"B!‰@¦H”hZ @hq&¨Ž/µ8%¦–’”¤ˆ¤)?NÁHÐy I¡ÐlàÛ;e­Z\š”©"I=bX$«Œj¯¬8/˜åï3ï€t/€‰i¢!0!øAÓazÂmaÜlS1ú,©:²°„ûùÀN‚aˆ„ˆ`¥ª‘"2$çÞhá}_é•7QA0DID(Ä#I!@¬ÀML¡L@2@K0±$0@ÂBÉ ÐP¬¤2ADHÀJÄ@E(Ê,¬,ÂP„ÂJ„ ,€R 0ˆòËÀd:bûþþ‰Þôì]B?>ŒØâ§?ÄPáS!ø "¨,*Ê~2BȦø L‹€ù~×ðt?ܵSB‚!ÙvR X…b@` *p*&B€d¡a¨@™"aZ‰R! B&‚‰FB‘Hd†‰‘$i¦š¥’¨!Všª( $Bª%@ˆ dHˆˆ€…bPˆ¨ˆ¨  ¡¥¤(¤R*((¢""""" ¤DˆB%’(¥ˆTˆ¦•ù@r’H¢&A}0‰3ט= ‡æççყqÁ1=Ê H¥"QS0B¨!€4*‡„½^H#4Šž»NAÆoÈðü=² µ;Ð<¾Èf‰( <ñü,pééÒÒœWÓâ<ò×á<¡Y QDB&E—̃‘'íë%VvGAg¦¿â«…žAŠß CÄiiŽ˜ýȼ̃T[\®ÈÆ¡ê±Êk ›AJéèÎ"³Ò¿3 Ã3q®Çe9L@Ö.LƒˆHJ,ƒK616iŠŒ{q´bp85DCai|lù–mcHf.ë©1« ïB„2zDœ®< |ϯ <áeXGzLÂiØ’ÀÎ6ýk¯”ð ½g7™³0oè¿\g®Ÿ/´×ªñµ§Ba Wë¼=˜Í´³ìÓnÄ÷åÔ/‘Œ¼miÏPbŧß6æî2Ãg¯ÑƸÙ¦eÞã¬í*VG[]Ý+ùðãlV´ÓÎ9¶á3Ã{õön¶Kmæ|yöžzµy[´åÇ©þæ,LPêÚ6â Œ#\íl¡òWVVÙ¦ßCóŠöðÏt°2Ÿ%:Se»cñ/ò‘výþ:¼‚*BzÙÄq:3û‡ø¿µÒ«W à}?îŒxAx9èûC¯_c>Ýýg§¯\Â^b7p$|ìº5vbíÌ×ïú '}њH|òLðøŸ¿€oò`7…—Y˜w“ýšÀè6k²´9Ø{ÇY¾Ã¦Î•Ôn=,5ø‹ý¬±æË,tî´_–ÏËÈmðÜ[µ¼~€nÒ"Ù¬÷r·gšÑ˜`Ÿ=\•U¸÷“åi¹‡ªÉ»þ6pŠA•8ñã—³¹C¦.îñA3ò}W¿i¦’jÆ_!ÈfÊ`1Aƒ)ñQ}é  އÄžã/¹ŸZg£TÎHÐAù½_Ñ¿àm+þ®©ÿ–Å2OÛë)þÃà›`'©ú3Y©*0DD¡^ÝõMÒ=ꬓWl!bs*#gÇŒÛÛ»>«XÞcødݯtgÒ-XHó‡ïß3uuÃCµÉÓ.ϧôõÖ;> ó£3ñµ› 1éF2C b€1ïfùÃö~Ù¿è ­¦ïœÐGW” 3P0Ô šªAxˆñPâx Àe(ä Áx/àoo·Üw ûC¹P?Ñ ûræ?BcD´¦ ¬ÐsM%œìáËì/»L¿><çœ#ˆ¯À—Þ.®ø™ÁÞ-‚Ò‰¨€$[Yóbñ‚¬Ì*½JÖ!›<4m1rŽ'¦%S}“¦ bÛ‡>þ‹ßÝ]w: ouwâ Þ–õÁ€Í£b‰Æ¥t-‚ Œ¤‘Aˆ „ ÌNÅ€„51`vp$[gáG8_?—ÏÏ<Kߘ0°DˆvU¥ÈÿÁjИ€é°®~óú õ‡#‘—‡$ÀaSAÉËR¬x$h)óĘڌPCIØà^òof}XÀØ!‚z evu€?oSÒ !ísÇ;D!Òl„0ß0PPŠ C þDB,Üý+[FÂMëÁ"Þ÷è0zÎÿуR~B郿 ÚzxÝǘÎuá”QR $•“ͱ €ÚVmÔÍs8¶% ଔbסÑfdàq ÜñÃsã¦É»àÜZŽ£–^<á™0Öð(Ð;²p Z C1¶är9LWà€ü>AáéØÌFi–´ió5^ê‚ ·Ú˜XîÁ‰¦g‹íèz:Q¹‡ÐaÂ*¿œ?`d?(m3ž bl<¼¤0Ä È‹zÔåªá!µýÌæ27va—äì£^à ކc4_›€„pàÑ ¶h )@Щ@ú…2œ:¥²t™„¡£¡ŽG1 æç='5ìÈ'ç¾C³aòh`CyíÛ(¢=mµ×.ý;ð(J&Љ0«AÞ¸Ø8êz‹´?÷¼ÀdÉ¡ùú`ìz9“o¬» ‚H tëÈʩϺ%„ Ø;þXaølv bi7DH¡ßDïÛiÂnK ŒB‰d Šx¡º^3!¨HnÈîÂ|M¸?=Œ ¤Á¿A$_ÀH¾Þœ=c¸ß¡!¹’ÎBsÇ&Ì6/|þ‰¤*_Â=2’g“: !„É ½ÊëÐÛúœù‹nÀ€ìÆ;Ý^Ä ý'ÖÌ'ƒžðÃõN,“Ó‰)7ÏéBÏãÇïΧ¥‚ŸI≼ñ=‡û=8)ŠKÐgŒyÓˆe’V@Âà&8mbX–Aƒ…2»´„ŒÕDÆUâ(‘r0L †¹X@£Ôœ4Ü“yÞCØþÿß'Þ-¥;b¯Mªº-¤Ü;m¿qLzi¬‰?¦KÐ| `:V·A$¾ÌºE$pÓ=FëñÀµ/ŒY/ns ˜iùÐ4àL^Ž1ø3¦„Í?2ŸLQæ?OCô²G;<Ñ'²–P¥+ \ÊnÞѰ±8rm¾Æ:‡ò‡ý²øƒK¡b¸ùÊ^êOäí?>Q/:û¤åeI4¡¦½›¸¶ÌÛ³ÛÙÒÇÿWw’ã >ÿO§G;Žã¥´ý_ýíû<¦|±mü583öÓ&>E1C§÷¾vƒ~ÖùÂî „LcÔ~u±7¯–KóгŸÆ¯³³‡Õú/ð}¥ì™™7j=8Ó§túù{›hòeüw<`íŒ3¾ JR(¤‘ÍÂÅ P¡«7Úý¿#pçÚ„Ù@P2«±­ Ü<Ç—K£M»‹XàÝ> È­ûK /¾_ÄHòjOÏM H´·ô_ì¯5ûŸ…ÆLnæèØy/¸¹qà~¾í¾<÷rÊËô¤t· ·65“U@k¬®ÖëÒ·,o¸˜dkÌc¯ùƒÇëÈòcS£÷ú¼ÑãÁäýÝ'ŽÜMLÁ¿Yê÷£÷ùÆ6ì*1ÓÙÔmRï3_¨nøÀô·y/!ÒÿGÑë÷TvoAqõŸ¿w}Sx†+ÉÔ r£PôŸÞÆóaü~eÅwÝòÝ­ü…xˆòøŸxàðaüýþ¥>¿£·§kÈûOÂGŸÑø^BÓ°=»ènö–7hÓi3*‘-<ž×y‹ýýûNäsxÿ-±¤ð2mœ<9p,çC±¹‘Â~¤Ìyˆq2 QGkw{Œµ8Ú7ÈðàÓj3z6 Ê|HùÚò*uvR;%ÊG&ôyø3™Ù¬6íÌy˜cÐ:ÊEZ2ã¬ÛÅõ‚ ,hÇÒÌpá¾î¯G˜cùtFX›útÙζ¥XúK³ÕCF/çöyì-îCjÈcÀötÁ-Ä|¤?›žÞD·£«ám]>néŽÑ=Âï½™èp)Àæí÷±î馷žïHCüæÈëÏF`Žt/¹cêËÛî?7éaŒÌ7§cë9Á†üFoä¨q†:yúî—· Lô2/MÃóÈ  ÇùöwUF.Ùý ß”¾b˜ÅŸ ÀÈ—ÐÃ{0æþ‰•_É¢%{C4æ)“Ñ!¥µÓ£%û°³…½ ­«\Ö˜½ç¡W(¥ž%e„Sš[­tض?ÂÌáÙ ›î©êÃfMF°Ünj-asÐˈÇ+GýÛ›÷·{¶0Í[xáy˜·sý1Æóùl´ºpÉË>”i³c20Ï}£ÝvÅÇ+dW!ܧ.{Ø|Ö4¬™˜V÷²"œòÂ3qæ![N´©±ñ–êÆÖ®üÂ}Bã{µX}ÌHi"·_=ø»RT±·òg oâÔ5„Â\ ÝŸø¿†ú54:üoæ7¶ÌN>÷í¶9”}‰² °ŸËðÛÎ:N2œ¡¹j]&­gSIÑ»_©ZÍHP%k4„‚‚MPͺ‘K¤Kk„¢ ^x,É»©¯z̯nh©½í¸Šß–1q­40Ø)˜Ðv'¡cÐÒÉ'$ehÍuœKëÅÕHüi'¦U:ðs›¦DÕ㉠%6åƒ0É¢²†×ø{5}?Ÿ>l8ç®\ûó–ŠÄ4jcˆÌ#­6w9\†‹dÒö;>oîdÝ!}»Y¼&Y ç´´â¹Üš»žæ½‹£¢`®:˜êbK§›=â¥À¨ë±ÂÑ 'Œ­z_Ï–¡nMƒM¤í‘- ÷oH–Ee±¯¼h?ò~» 'æôjÜØŒsg-9›ú”9&(²gmÙ1Žd|7fâVEÇ[ÜÅjÛ»ñm¶ ò(á€X]µÞÆQuˆÝ·õL•îij‹oµŽÐÇš« 7Ò-æåæ‚ ¥[Š1ÃC<öj&éßêMÝ#ˆÍª ús¥¼îÏɌɮ6ì6 ÜÜÊ] ß´‡l£Ó?íäjè½_“ON^ä4ÛCÖ„`ÏÀ©Ú`òEöIë•’ ¦;\UÊo­ê[‰œ'qF¶¶¦f%~è¿ £*/«&çïqùÊí*Úa™î¥eQŠ7osË@¡µÓ°ëá£i1gg’Ogëfá N–åÐYg^ë‚—¸_˜ÞÅ9Pø é³½i¸×dO˜Æl3 Í}g&kŒ¯ ëÁŽÌe,)''àÀÖiÕ]~l•˜r&ÝQrdÈõ¿×RËÚ6ŒoŽÁú¨â[î>>Æm&l-± ‰ä5âh m»JQPwÌ&>)¨=#‚º£€PÓk`øi–2v™ß¾¼1…UUU_ì›m6Åk‰Œa ZØ"$ÎÒm±®ºÉ]UpM¶Û"&›dDDLM¶U5`f¬¦¦Ù] ³¦¤\´¦¹UU\DL+‚m±6Úm´Û"%¶Ûj%-´£Á>!7ç ä6ôñ¹èFMÌaÔó'SBî/wÇLÁÛ »^ àñ¿â']½$ŸžucãzûÓÜoMþ¾·@îÜyyûøgLgk³¾‚†Š (h(i)ç9Á ¡¡)(h(h*‘¡ÎsšZ q˜¯SOÇËÙÁßÌö®¯¥‹ŒëglïÙ&Àì-á¶–—ëͰ[öm4=7)•»û‰´ü".ò?,. ­‹Ž•áiK2´%Å5 Lp´9~?Ÿ„¬ÝÙá¡pâoÙå8_+Zs{ol°Ì¸¬·E…ŽpvÖ ¢Á¯ØVæ<¬ixj ñM¥)Lò³®¥‰Løys§qÕ\¼Ê’Ó9Ð[5<=§õ[ÍÎe€Ä€é¾›“Ké§n‹ˆí^i»#dDCCBܵ4)ÍãoÏFîìm ’Bßò¡å\ÝŽDµéÚÏ´ïÚ¨uœÅÅ›ÞZ¶L6Îúà×´PPKçŠx׬È!²'af¯c3D‹­c¨‡”䘺ÎÃ4Û"w2¾ë¸£4ÑÜ&a'îÆÖíÔjÝÝþÄ1pßÔo¿Ü8éþSÐ36ÌQ LÆ;˜E6…t©¤¨†n’ï6&Ö¸Ìh Ž2}~kšTéø_͆V$k…jL˜6Ðçæ퇲ƒ7®pt8¿ú-›&ù~…}ê˜òZ 6ˆ5ñÙŠh ó8tW|ÊÙN\óéÓˆ{ø¨]#/#§ ¼$T瀇‰rk@,>D,™4„ßò 3žÞÛd×xo×»mæ{Y$ö{ù!mþKí8”ÐÙTä [ÿK'é1ñuPúßj(ð)ÏÈzI:¿ÈÊŸèpþ¼LW—Œ{‘äHÏã&I‰\äýñàé%»ìKf:™Ê`„Hs!òÿ7¨üëë¢!î[Oç(mxR7úœìA½G!Ù‡AÔ±¹á7õ¬•[±‡FîWÙC‚6,Ð ¹åæÜlž`-Xq´%ÌLþ¸r”f)1©¬†vU‘øÔAd%}kUe å¾qÕÕd“E"E³Í¿„ãÛuÑDËGƒ'MrÓ‘‘Üòv]+ 𔊮„|/‰3I>ZÃ’Hm˜¼˜‹Ç †3bV‘­ óõ¢C 3L%qŸòèÂxîÖ;ž0˜žö¼AΜÀ,þ”öÉðlâ­|«‰(•öÅOWᤤšÌ¢ÑnQ9>²2?g]á!&¿÷9Å6Ûµ‹ñsݾ´ö-qWD“³@ “ g,05uþòš!©ß …pTHQƒ¡™6,hkÃ5!“„jÒÜ›i-­µ#Õá´#›ƒ£ûªÐšä]u_ °Ï>kí]l!¹¿¶Í¾BÚ×iba¾„ça%’7/Ê#ñÿ´¶¶%‹‚ºXì¤úº˜Ðú5賺䯮ìÂX…Ž4ÛvÇ„‚V.C´9dÔE0ï©ó|ý›>(ÂX =€qG CSÁélæ’ÚóJ“~o×ÏMùÒdšò%­y¦*¤&‰dI4¶y¡¹ö;{ö?tÙðO ¿BøÁe›ìß%G'ç—–xe*HÍÐ{âì Ââ±'E÷̇¶pÑ[ù5ßnÖçÁÙÚ›þœ‹Íðö»T”’®Ù Y»JiÆn®)MÃÕ–Ý–Ý˳ú©R‹5Ì< LX÷\übf(Â⃙Ü-Õ܇T Edæ¤×¬ÊM4%EÑú,¯Ðô•6JÄ$Ó›­;#¨Mç€v‘»až¬vȤí!—ÊÙËÇ1ž˜?l†(¸)UÓ#æFÜäÇ…Ðn£Ý´éÙ³·¶Ø÷y·í ‡Öç•óñã¦ff£vüß®eǯÞmúr—ÓKiÙÁ‚£ó£KF:,fÆn¯/6vÅ.óªÍFêr9¥ÌúlÇ 7áø[+µã·gÜüüß~ë:ƒáŸ7¹ƒºÐÏ/¿3X«±ï÷i‹l„ŒwK/ëpó.Õ³[?AôûçÝåÎW6 Žv‡õ~Ýs­¼íɽ™Èðæpéöúá»ÇHl¬¿N[ §móêõôæhÒ†;cžÎ?¢¼6öô–›¸]fá®·‚‘²ÇXɼËK>\Þ;pý¦#z5w޹A)1Á!ÔN²~&%èÊåÙ{ljäíºçX›¾ @®ÄánEò›éc~•ÃðxíÁéú ŸlðòãÖ5™ª7ÖÏÖgî<÷jYéqü>¾Ž’Yxɉ®þbêTµšQ=nšaä‹gÓ¼¼žv 6ø[O6:~P>¤ T‚ŽèMGYE‡'½6~GpÅ!]ašþäÇêFYåãì¦6kbRwÓ»Õ8´š«liuKyîˆäŠp B¯Êsâ#ï“M„‹…·o““~5ÉSt#¨÷ò†ú— 3²!7í»zZô0`}ÁBiÚâˆõù}’o°`Téñþ^fɵÓòüŸŒ5€}1˜Ïüºh|cÞÆLaÌCßY û½pÐÍîvväìí©÷~ͦÍ;¡ %üÔ4“³ÉæÊYfßWÿßöóy:²‡úÏu5dÃ,¿ã¯³{´Øç2d?†LùÙ@ö²óeÍ/ßš†ëƆ€/vp0pf-DZ ÇÁv®ÆP»Sü}´m(wž¤N$éÏw1"Å~u¢‰¿š1]%…Jû[ mqè®»Pé¥;ðëÕ¥fvûá<ý—Èüü>º·÷˜WÓ­¿Dê%!ö*ÑÉ“qÚPq¤oýS —mþ$^4×Ìn%"õ{Ÿ»ð¦‰~œ§ÊÙ4¥s|ãáÏ6º•¤÷53­çì;Y8_D‘_ŽÍòíwñ?¼†ôçÞZ•ÿ”æëÓ—;ýµig·“”h¿g}ŸÃ¾Ðä3} ¹®¾h¨º7GÕüík~h†ŽCý}æxœo Á×ÛxIhׯ‹wÙåúÇ)?·ìó¶ClÒ¿RIv°†ÂA›鉢8Lç• ¼zÖÃQ&s3¨È°Ümé†è†l‹ƒ_®MÔÆ„u»Z˜üâÙèãß+*]2ne×Ëã;&£Œª“dí–dÊ}x ¤a):(b>JZSï3mjL¥ “¬(Ó* ¢Y@Ö)ìÉ È}þý£Ë‰!Ä΋§’U‰–` ¤ýSs*R”ˆŠ„”š^'öâ…'^JvSõ½&!ݺ—¾å¾ÏGïƒzíÛÞ=Þ)ã 5ܰ¶ù6¶á'&>iß»¾±à§»‚eá Zii§‰ÄÑMð»h§§m‰b6 ±¨V fØÓ‡tË,áer%uÌ×}N²ÆsƒâžÀ ž«©ÝJÔs&„`ÞB„­Ñ±gíµ»b[¿uÍf¬®ø÷þ‚LˆC&&μa‹³°Þ.Î7­ÙÆùœûÜpkLx.~óNAVùÙàØ7âìøïX¦ ™{5`K¨­„em`wÚšÉ; ± :eÏ«÷wðÊgâGyŒ3.’ 0R‡­5Pº¦‰¬E³vímų¸Ùk·‚*¹"x?½4 ¸¬"B† ^Àrb­é«ÀµqÙû¬3Œ©*0ÔLzd8&S™£x Ôü¯gÜ—Ðjö»zXh„ϕ֥~)+ñ`©û¬ ’l†ÁE5¿÷d $šhËåtT„ÌÍG¹:xíÏ ­¤“ `d"T÷C©!V‡Ãꕦ—yJw¼ØCè–"«Ô†„ÌæNÌ|ØŒìuˆT1[®oð­=ipv}8ÃôÄatç Ï¿”Å'‡ Þ ¯LÚ¢øóÙ&ú/攄ü·¯YM2}ºWý’½[òjƒêÙÀ‚÷gmŽÃ‰šÎ¾¼}~š{;x7D¿(hñqÿ;³óõ7N;uJðœùNT>Q¶N£¸ôœ×áú-£äZʼnp$$¨îqx.êÙ›ÁVµ¡g‘Ûog²ëlnì/+ý‰Ð);sy¸rlºl¤š^Wgê”4|`†‰Á×&—ÆD”šU‚8_"M. D4cÑ8hhóÄ4a6bwÄ4A u§s³x Ži™¢Êµyè-Ö0nûÜs¹w®éuHŽ~òC@W­˜ÕÓѳР‹ZÕó}5?"kA4‘aë½’?`É£ b®×hl…xMo–®›͘éN{}“%§»'†’غSÍÍë(”zuØ~³tÚƒ!¬œV?¦¹˜åqgu3<£§8Nâ|]Ô9m^$ƒ‹;æâ…’c‘ÝÃ}Þ4E…°¯ÐËÈ’“ƒ{÷ZÝñ´ÙÃ쟪M$ĨQmMI¸ÔLÒI1–ÑÚªNòF<Òq1ç2Ú¶ äCïÄGµh,ë~nö A¥ŒÂ‰$ÊîºSoš¸7o1zoͨ“& ‰­dñ~‘bƒ—t¾Ï¥Î`Ù]ô÷Òœno‰¿µöÉÛ’à" .„…“Ó½ÛÛÕ…åîi…øÒS¶Ïuá¤X"Ç¢„üº< ½7nçˆ3YqMöõކ‡igóU¨‡0¸éãîËÄÞK»ÆþiЙšIœ±™«¥ŽêF‰yžÙK‚µøQ˜µ4¨àáÝcŽ%y«Ñ1%‹±¹2MÒ˜*" zÍxæ¢Ã+m ù„á;5—}ˆögF0Ú!ŒWÝ·Ä·ç" i‰GÔi_—oGoTíXU[™i/«{qØ|ˆ7éѰ–r}üÞMOUW¹ôTFA_ž{u|Bõöàõp:Ð~ÿZýÐK (ž8ɣȻjkSZ†e[g—…ò/¨—ú¼Î‘éáÁ¿›¡‰ó¨1RpH§= XìcY=ö¢=Ϲ·ov{Ë&f:MŽí’ß蛿=„¼l¾ JGÑÖ•®+—g68a²[İ ýôH2 ƒ H ˜LÂ]¾nìx ¹²xÓØsåºÚ§Þ¯•÷àrØXZG.‰xØYi{Lèºúµ~wgô;?ǧd7 0zó4K´îãΧC´’ÙwYF½Sø÷ÙJáÛ|¾¾¶<ý]Ö—y [om$Â}_¶a"É>C²Lô`ÌÜ[åk[×é/$Ò~ o/¸%æðÝø‡£¿fô†,èòCpÕµ„4C³ÐšÓd¶ùá“íâ&C­ì7½f#VI©=¸l XIb¢ÉZÖYhJµÍ¢"}IœØ±ª6lµMžZµd]ïF³iÝÓ „Y}í_¶WûKvÜZ·9±ß´µ”ÓÙÅØ¼‘金 àn½$¥-K^ÒÃ>§å6§âÙÄ3Î23¸ÕWzö·{³ûÝŸ™ÙüŽ?µÙäìøt±éúÃ'ØÑ‹;\„s2;ö³•ê Ç«kF·¶–y@÷Ò»Ÿ¿· ئw‹)ØhKVǬ›s¨êy]9Nè{\ïl äÁDëV‡Úw}“bB¤Ý/R1D'hIµ?ÜB •ÊQLÅ…Q¡¤_”œH¶%)MÞ$úÚUÄ=Òqè¶ýÒkéÑÌÜÿ'gðv{tÞÞÎ× ¡å‚Üšeºm”5 úÆí“E}A O´ÅÚ[]žþã:\(˜ËM:ié¤sñº²,½Þ…aá{u7YTN®¡²ê;ˆz–SªY¦ÇF› åLZ—ôN(Á­œÍ6 Òn„Û¼f°g?<öÊ,"¥j6m=Ìû1¯?¯Ô÷ÜØãœå[˜ÇoU˜S–Ñã9œ ‚L‚ùmÈ':Ž'æ!ÈCATáüÉMÞÑJLû\¬7‡Ðãyuq6ã» “ÂwS•­ÞàÜ—|8èt—&o§²Ñëœ4xûá£Þìý®:`ô¡ö0cÐgHMN˜nA-ófc×*{Î 6…÷ÈoI+t?'¿Õ§o¡&´êrë%¤½@äÙofØÃÈ9씃Õ1hä2ÆÑgÎoò3 IC›‘Á± XŽbDMnw¢o-ŽIš‚o$Ÿ5âMžþJŽD‘w0iLì¨$JoF—VÛ7UFÓÎöVRv?³b¯ÔW#¾PkÆ{Éí&>ç¨ÞÔÛ ôaqd¼‘»™¸åž\Òº$7´™½Úº÷Y_è–ßlš`™5£¸\Oœ»—Q©Òï/&òâûÔäíª7ÂÉC4š¨rµ‘;\ÜñYÿLàÎú?"X,´½°S·ô†Ñ[1ä«Ëü¢;îlfÐM´q´Ï]d^}hn&ZYL­iQÇ&åªåWûKg e"áß¶é˜X^¦õJΌݙÛu°b…ŠØ™Ûgâ5K÷Œø'õfÛ†Zsp>ÝÂŽtdúõwe9î˜í¿#Ç[Ü~»u‘”⦼ÑÚUIàCÛEblÐìÕa™µ‹«•¾SXày^ÖH«Þ½›gC³‡{³±ívs;Sí¶ùcïé©44³ç%1üĆT¥¶Ã¿ÀînӘž91F‘aÆ'êòé¸-)êµ k°Ù®µñœkIlã·vÃrÄ7z$Ò·u†P?}gVãs‹'£,q†³ŸÌŽhÕw¥¹BÆE¼oqóïÕÑÖ‡Ü;=Ã|"ÔmâÙ0C¤™Ø™:–ÎbùQ©Ôìô`Ñ6êÙˆU«¬Èhgpº(%&—¢LUMæÓî˜AL†ÊZXiµÎí3ªe&•Ò(Òii¼o’fI¥ê¨VM-áѽºú[´èoY—WB6Ò%#±L‘æf5L»Uç{IšÿHÒa³ða-í¾ÍÆáÍÈȧVoà*2ðñTöü§m=Ÿn7_íx)m˜“™ú§)e‘*ÔS^µ÷üã?Ðùëô£ê\èU‡Œ¤'%€”’žÇæ§£‚!ÅÁe:6—”›©Ö~?*gs×8ºïà°èô¤=>$“%ÙÝau­éŽõyêÈÜÍv3CD=Í“äæ—ék7#8„¼‰¶É†Á`Ìi"Y·É$ý¤_ïùD®çß&/‰Ž–g–äšî@Y?§Ús&ÿ÷Ï^B¥ùNÜdn‚\Ðñ‡ÁóÊeè-Mg±­b‹n=®Ã5¦6±“š_!/y[ÉZ§6kóFöºVLé—‰ÚßlÚØ]'ß"ÊyšìÙYæíz¶œ";¥Z;=íd‘%tÞN]ÂÉ&ÉÂk7„aæ™[Än´sº>ðýW{^2¶Ú,º˜ÆHéÑÝpöO‹K©¥Eз*RRw6Žj‚ÆM%ÉË'ÝÌ}t 9éð–»jwìïŒò£?×™ ".MÜk¡(þ‰–ëdxIö0ïÞÔ¡~ù¥ÃO¦2m,f¯ìÞ`[=·=”Õ±kcµMÂzI¨¥iG‡¥8™_nUkj9d²,ôáœD,±™-gí¶q‚òÃ9³ÀÛv4e~´‘ª-HÈU5Æ`£IË=Ï{Ȧw*%… Hè…l…ËÃ3aRó¿vÛ‹x)ßEUV‘`|—=Ÿ*žYÙÅ瞘=ÿO2+\ú*4•8cYÑŽ0{”]µÅÕ®ëY±Ês³é øsß(ƒÓZŠI­QäkŠÑÉ·FQ“ªÄ•µçœøOÈ[3ùi6Áªì›‡ R£Æµ5 ú)!5®8+“ÚîÐåý6«Tö ³‡×¡¢ ¬`fIC¸6Êú½¤ìË­â÷‘²[¼&ÙÚkxî×?PHÝdËÎ"KgC÷:Þ®—»x˜¹=“w}äµ²U’qiaœÚFén¬¦É±cpó‘|S]µ”¶k* XVÝ/¸©Ìø=²±9¸¤Eƒ‡è»HÖ§”¾E¦.c@NÄ!‘o)<¾ tëCY³‰w­êåTM5ù©w&œù…‰Á¤Ñç,yŠª¨í² b欚é~oÊA~Ç##ˆ¨ø ¯%ýB ‰Í[É+LvïI®f.±ÕBŽÐ&vЂâ+ø/k}ŸŒÐå×;Ù|¾ÞüÎo&Ç'å’g,ÒÖC>\Ÿ¿6é%îÊÄF‘±ÜÅ¿ê1òæŸËµËü¶æc®Ÿ&ýOe]CXKXbÿXÄϳ»¤:âœ@fÓ ãV `ém‡~»¬|`Ós9ú#6'g•¦RÁ\'d„iG“¹©CzPÒv3ÑÏ “nX•¤ýmÕqö÷‰¡®çóWäÏ]Z-:8=>®Í›mœ„[Ë7JºäÁìñzo“ë¾;·“ŸAœ6ßkÚ·²­8y‡á34ß=£”ÜõDœC¬ìIç38.q‘*þˆyð$9BÆèóJ_‰ô}7™Zˆsùr‘Á5DOÅ9÷a’a‡ýñMªÃù`ú`Ö¶ðËb_«™¼ŽíôÖ”@eòeZ×vxðYØÆ?¯uÌf}Þb;eu¶éêì·85-_W®ýi6ò"ï/ì”­ä›ü1k>üÉYÕM:iPÏVv<Ü Á`Ž8>ŒXr¦¿*˜Ü7áBëøÏ¿•Ù—~Ûÿ@Õìv³³}Û¬Õ©Í f;?¦a6f]+‚xC/§Ísðæ Ž|¦[îüÙ|ç_ß#oSaǃ•¨Ü7…4×ãå“Þ|¸(ØaÞµÃÛg_g>¼¸°s÷óØÁÿɷ¿.ÌϼžTÓß(ý[Hþ¤`b½šs°9š j',ÜUÿƒw ÑtOL½ûKx´t®˜éŽéÓ—s·uµÜ‹ÄƒKÍΔv½>Û\Ù¶i’ ±«™ˆæû½iQË+Üíï:þ@‹3Èt¾Û”®žßM§x¹ûôný.7qó55ÔÛå;Gôšì5åÎ[·nŸ˜¶§Âëúpm¦ûr€k„´ße6r'i±Í={[u¦4Ü[ÈÕ;û¯w–ÍÞl Â}Mçò‹2¬qaWa=ŸLå»}½°º¨0^N §Ûw Y™&»Ñóf4}V›NËG@…ì¾Í÷‘÷º9º7nýòsÇë¬Õ ›÷z}ºalîq÷Ë®]ZS®úÓºqåòÙôe#»9ÐÝï=y—λ¸,ñõú'E—\ŽèøëÞ’gkI±†Û²û W–°Ò†ÒÂf]<°¸§‘6šK}ùñód¬$b‹=ê ƒ¯í·Žó“îj­þl´––l•¶~Ü›ïýÎÏüŸäìÿK³þ.ÏÏWgö8ûòÈ‘ÍõjâãÚã™±s?è·õѸǢX¹¿eÛ6]Þæ2=Ä;Rë°]ãÒŽRotÏxj„åvƒ<ûfö.=Ù5hÃ:f6å„m®éã;EïÖóÝn¦TŒ«‰÷å³Ï?üýïÞ÷äýÖIxàé!·OgãÒìÿ˜®=0M¦&þ žœdÐÙmß)Íï(Ÿá¾ »Ži5·ƒà¡ ya6°_ÒTVþ!K)ì·^‰dM­÷àYpIÍY¶DQœš1Úl?y:•Ý ÛD“[Ôé¥Iº†ü_ƒ}e#*¤…R’ýáˆHa8dÑ[¥)$1p£’ €c|´ÖÅ)§œ²ËyE9õE–{nˆ7\Mìrä6äÇ•ˆÜÝO=·Á¶ dÖ0ئ´ ú<"äH~Ʊ±²ôhÐÅÚ‚d¬h™“4Ä)ûÚÌ›.‰–_JiYzä“×s´dc¡h°™LñçÙc_M‹Ïþ|e˜Œ/åÛÙ‹cº!£ÎÛ 1l!ÇF¢9C›»§fŸÁÇLš”®ÿ¥‡HÂO›+÷„„‘*†ÿ勃õ7ù©PüoÏ_d6†®„¾Ÿ®ðÊ–X¤;@fÓ.ÍÉø%"cœÛ L¤ÓbA«NPa@†H$ÌŠ”öÚÜô§¼×®-”b3ŽŒÛVV4¬ûÈ,SÝ õú+VßQú0L!ÚÔì²ó(|ç˜J7N…±It&k¦Bx=QÜ®è¢i‹ŒT.´:6'ëœ(fiKûÌM]B°•Êä¸vTNY™C?SﶡͰ°Gá-Eƒ>Ͼá2c&,@¹ ¹™}?®ìäç‰{ZÈŒ#‹^æ='4eÜ%‹ËŸÆæó º†VÄãÚ¹û£e‘mD¹;¤Ø >{$xØÆÏtšY=XÑ]£ÂfšG‰¤7Ãh:9~+e…ɵv~µô¸=“ßÙ÷•Žl‰ø`öRÉF2¾ì®³µ«f^çÀã†j@ix­8³V¿e­Ñë”4}ñ²M+6†|ØØÖ@MpêSgîà0+44[4"›K/’‘ð;IêË]uñ«w02W­Ã07W;Q,Ðq4„׳‡N­Æ_G CÈìçÆD41——4­ûêI¤ìL&6î°VÇÕ7›ÏF6ÊÑRÒ3½ên{"J]3m&ß¾·Í‹ˆ°ˆIëwœ­!sÑ®ò;<`gpÖ¨bNÞdÌûÜ%¡E2^é8Y')¯•÷I`RlFË á ›ÀØ ™jY"v_C‘yî±›ðêÊêPKš*Ðܸ7#d²iÁ¥žsi´ÂV¡Â¸Üe°û•¦M/Ñ‘áÀÔ~Ž›o=^ž›­ªÆ_Z~2>ˆyI– Ñ$%zçí ̆îÜ^¥<{ö1}ê>øž|¥AGŒlËH«– ¼McXM€¤ZìèíYlknßܬ…Á˜Ü€ÈL6ˆš i!Ìq:ëÍ‹6MÌ`P,è®Ú=’x¯S?$,yÛGœÚ¥–¨±þŠ„Õ},²QΙžm)É«‚Øûã­f¬†"ß8D5ÏR‘+¶SÞŠ”³lEŽ©ñ†¡ÏЬ¤: Ðä'Ñ|£"gCÉè ÅÝ^ÔiCMÚa€Ï)áÃBk ëþœ 6$Ú2D£ I<‡Æ†I@R'U,z¬+6t:4ŠÍÄ[ÇbKêzøç“qlCõŽç°é&Ÿ÷¢ÎFÿÇ!8.uwäñóßF“Â_÷Ž<<êþþ‰Áø£pΦEI¢Ÿ[ÂLÓÁBÉî‘9¤f< o3ê](yTV44¤ŠÕÈ¢w¨™nÆYµÏF¾mбRecûEÖŸm¡ p“ÿ.â,Kþä¼¹ó >™þ=A6}I<¬N‘C#þ_ϳYŸ® òO†;Dý©ˆNNV‡ø¢žvJ;œøØuˆ*¨¢†$ qÓŸ/Ó§»FÛQÐÙ^[|§ûýŽ4“µ¿k8‡q”í Ýš³õËÐál`Ü.šD“„ä(¿‹ÊS¬®ž¥®4«9NU8P©B\i Eª”kb¹ÊjSòíŠ7<$Vì§)N>h$³…•™1à euÕh‰4/ö.I3·1È<úä*Gûçñël3ZB ¨CÂ#÷ “/Þ€Á|ùµ'~‰¹ÙBQsÀ2L±ˆg¶V'¤ƒ¡åØS2ÍüT/[þ r?è×CðìÑÑ"!»à’špyAHRʉiáVœ“mqÀæ@óý6DC8)%È™S0D7/ËNíý|èî› $¦øÍ®oÞì×VʸoA„ÚªnjìJ÷kçc@†Ü‚”{‚e!¢ol¨á÷&2¹JŨÕZ‚íb’ $õ‚ÿwá:§jŽãjöÊSæîÓk]ðŠK}^¤ØLÓ×(ü½C„*×80 ‡OfXÒ.VWL'E×N¨y¹9Ç Ã0˜›"=öóå@Ú­÷;íyñcu´l"w[¢Æ&KÈä‰_œŠËo»°[F !&I ÓǪvjV‘‘•±ñŸõX\†ƒÍoÌQÞáµîS¶¯ Ju«iní²$ùÚÖ†ìV¢Nù[ôÝo®ü‹XLã˜ù¬g¿&×,ë¸eV­m".ýR»8Ä5×;o­øÎÙ5÷’°’²<»šµS×ÛICJ¾TŸk œÆÆ‘ò>pÛký¯åY‡ÇÍšÊÝ‹}—=,Œ¸,Ô r5êhœTß&xbÕsÝ&«¬0é¿@èL ›ÓYñÝ{gw´·‰ê÷‡Îy÷¶ÍæR4¾Rì²ÝÝÇÛPÉã§TvÏlÏI2¹Ž\3ï?C;&³5Æ·‘ûí“^Ì]Ê ÿ7yßK·`ÝÜìfM_×4uŽ/å⻊œåëµ0ö@ìOHMVÀp± L99D¤øI®9€²æî °jÖÒ@®Y1(! S@„4&=H siRUÎùR0r,DNÀ{{”]xMña “þÞm®0híéά¹¢³NܹԔ‹OÀËi•-*pn!ð—4¯€lWréLÑu׋ޖFM-½M{ˆŒ•%éB¢.3Ôɳ‘8«Øî–(º¤ G?Svq¸½XÝ7`w·ŒöW\ñöDˆeóÆç¶óÀüù5f\;°œ7bV“%á’èͲáJ½•#‹è¤s˜2×YäÝ—CAÒîÜï>dTê?>Ö“mã)4qˆ#n9[¶ûÙ·=±œN¡ÎSlç’ZYªŒKëÝqÖØ ¥¼r6݉FR¤š[#žƒ¢ú5ò§5¦;mÙ¬N©·¸t¢ÛþÕgç£S<ìIéÀŒ¡Ç™&gr!ÐDBK DWÛE"¶T€,ÀviIîÖ ê4“f‚‚Ø"¸Xz½ô8dÁnë¶›{žNr#²ùŸ“fÕáú;â]æd gàç ¤l%üDÞ›æ&Zm¼}w+ñÚh-²}lÈ}·¡ÿB̾ëèžÝËß“YÕ&ÕÅaDùŠÕ'Ô¬[·ÎEù&[œ‘¶ %Y?B&54àžïmHéV5j7ŠÇérøº)'œ{8¶Ârc“È`јÁÅ–(ª‹yT¢I9ÉFÝ¡1Q7 EN018ä&|®‘eV<›š.ÀÒ,±è’Òd®Žx iv|_+:·›Óè{F±Mo›ÂLðkFPëúU)—Õô›ýåÊkã·éPÜ_¶©Å¸íLÍoI%$çü¹ìïÁàyê¯çÒT;‡ÀqªnAÐß]{CÂ"Ä ¤œŒ ã=@³›ï›}%màJŠV‘É<ŸÏd1õ ®£?ÓR£<å çãË(Lìæ°Î™„Ês˜õþ†Ó-­ÌŠ7eÄͶ®Ö»æ×ßÄÛÙ¡t=Ž3pÂ/“Ô=›£ ò¥÷‘¤ÍLÔEWc¤Üão£^/£?‡¹êžëÍÔjÎqaM©¯£Õú¯k§üY+ÒdA ¸ç‘$’PîüL£sRXU°ÚìôÞѹ(ujlyÛa)Ãc’*£IÁ'DIì&ã)>0bÝMóÜ•äǹÙ^9 Eά¯uçîÜàBI¡úöš^Ç,†ÜÝ @¾‰ë"Ÿ»­ÓZ:K¿'ù¾kÉ€û„+“Í®bˆ Zr@bF’Ä®žmOJ&>tŠDì¹ë7nd?“K­môçò¾YQªH\¸‚Õ8&dW]ÅI‰µHwgÄWS8™:{/hËÄÉšˆ6ÈpïAܼi޵ìüÖn($OCÁ»AñTí/<ñŹKý7ñôÅZ²ÎÕ´«zþ¥\mÌÖìíF.›sâ[ZUUeñÛâ1aŽNÃÑ͈‹>;̹Ž%¬òð”ÔßÉwÁ5ûÓ¸¾Íûc´ ›‡#3g¢à–Íʼn™¥£0Ì#EÖÂ8^gŠk¼ü¼Éã×Í”¡ Ëe…ƒhÖŸŒ¦€ã–¡5š¡§J[®Z.`Ã#‹gÊNú.¡gW½—¸Pï!˜`Î'IzíŹMÚöŃ6JÃ]­.´Öχ&ÛF sÊRiZè:ߢº®)ˆ8Áã+Â_„?³Ày›ñyí{t9ä´àñþã4—·Ê_¡y>Ûôƒj*|9Q¹lùô“hó½ýmxÞ•öµQ ʼnšÆlL儨™&EY ÖÞ a¶vsµ¬ÐÕ7V‚.ì;m 3+«äÚüÒi®ô&ðšWsô‹OZ±UðÖŠXªÚÛãg]°Ä!!œ;Þÿj/˜~ÂS„W–ÄX1ù±Ž3EŽ›K&§7m+æËÖzÊþyÆÊàÝÈÏlšK–ýL–Ãspö’FÔÃnSçågÁå`ÂéëqèÞhibÖ} Xn±Œkh‹i‹6ÙüîÕdß[qËRFDˆ“8ò‚¹2­Fˆ¡Õr ì|lS©†ªj£²m¿Îä«ìý?×£uy†|g3ßÙ¯t·¨:²v܈w‡‹kgb] {Ó çC}Zßg´ê¢ï4ÄÇ· JlþˆóÐpµùåê2l¶[hkF¤1‚϶,Fˆ­öÃ_c›ò4?\;òf¶Ïákm‡mîç>ë)ËI4¦UÊßc6ug:W4›wGD7"]¨GT±Ä¬>VéŠÙ ŽàÑê­B}‚¿è›ÝÐ_B¼Wìý6ÅŸ_O£wÏRò¸BtˆÏBÌ!º\úZ¬Tk¶Ï›–öͧ,‘È™Ü'±:ÌçWÌìñ3ÜH“&îUoòT7†í7.ŽÒÊ{T^›Ç†þÇïÄ.à埉 ¢ñEì0À¹‚L [âÙ{JL›ú[§lªËX[F›Öàr4)wR`ó—=—}-¬‰‘”©‰ZYbˆ:qllÕ!ÏT™î%f;ÞQÒñ¼˜_‰$õyU‡Z7~ÔM‚‹#Ä–uÿ•ÔûÁL‹¾µ2!—G®w‡w 4ëF$>Ñ“g±ýtcꆗ½ÛŠnôÒ¦XâÙÎ3]ŽÝ0Öî³Àz1cSGE;9an>b ½™H×¢ÛwTõq li§ ïMŒ¿…šqffÅ3ªš“¶Ò–=;/jšÙ§ ìžÏײz&wq IƒËBxᮓfª{e‘KZ£IËðra0üû^Ez>ï's;>qèlf¢[8iGÒ¼¼6·K6NÎÇ_h;Ý»]œ¾îfcFqÛ`ðˆæs{æˆ.¹®ÉÙï·ý–[zǦ‹>‰jš@ÒØtwLÖ…¢Þ]wâ[ü¾ïÏ|.oŸCëísÚE)ß¶gøa#˜ccÍZ7 ppäJg;ÁÔ€˜\Ÿ¿ìµ»gRÆè,nŸL?T–¿è߉|‹3læe†gnQéèÂr¸½5äšG9G t%”ÿ–><<´ÀÂÌÊØö”cΊ–1{õGçSö¼¹]d1µŒúKZûN…rËÓB›7Å1Å¡FåÇïzL5qúnšft'bî~ܜΟ¯}µjÈ™ÛÏ6›nqÛ‹³ü]œÅÙÚ©«,㟚z?`â3 åƒ ç.‰o$ 3ïˆfû˜=cÚØö^VÀÇ¡ð³/:çuy®UI¯-8’ˆÂ?ï¥ÕùöéˆÐ)WHš£0øcù˘­Ìľ}eÇD4u;vGL3úŸeÜèM想–:k’c ¸(}ðíõqÛáÆ4w×Ë“×Ã9sæË—>YËŸ:˜t稽0a}k“´†ºü–[Ô1з–³¤Ç±ìL@ÍÙ笿³«@ÈQ¤ƒ µšÙå ñ8ÜÔó;<ÝŸk³önñÆm>ggö;?ív~l{ZM,ÛhÛ-éŽ~nò W÷ZÖõ»?c³èìúR5醎NωÃvf†»Ð&“÷<œªþ‰ÖíJ´­•~âQÐ?b!”ÛªUóÞT‚ìËZ+ì{ìÖšM­¸Fn‡k P›.¯9¶er°«kk´gW“,”¬)á3/æSLü䟺â¼ú¶'ŸÛ´:YrZPG±Ÿ¯.Vwü]Tå»–ûù¤¸°¨IBJâ‘U9§T¿ˆñ‘\.µªŒ–ÊDÔªR'äÙðÖv·×twû^?ÇýÈqÉ»˜_$èßøeO<=7ÈtßÍlÉi„¿”ŽxFU²¦u ÝÛ㙘ËöüÊåµ 6¼ãl’‘#12|ƒý¢ïèïºÐ"Ì\öé^˜t’"5ÃýP“* £JDUO}þ¤M˜©;°lÉ …k{£®4ôï·¬å̵ŠMßN/&_Œ¥{ÆjØ›?¦¡ã}¥‰%+xÿGhþƒ¦æü½š#â1?ÁÚÏÇc¡ÏóÉ“)»¶ 03>=K‡‡hÄN‘|ã¶L%—×ršnÉØÞ¨e5ëôÏ®×a±²OŽÒ(Êl@l첊‰Ç¥êì©9\¶S˜Û'®tmSQ±¤ðyéy+E õôPx¸_)ü0‘‘ªÎ [+”M:Œ²Ë)QÚCÃC”vgbô³¥¤É ùð¸-ǹïÆ/潎¯:J|^\±&™¿‹•ƶ(à ¥ž­œ h“9+ZÜn( ªX™x×,¸òÈòÿB‘é*¡¼V½ÍY[9’,™1åÆMÄYÕö2.+žybæsy³×5¯ '#ª2ºÝ X‡£6˜N&õÃz'èEÅrÖ³ Ó¢Rrq5K›~ëË &b7Å"†%õ$êoÊØ'3}ÖÁª[W#ñv¾ë‰ºuƒ¼#p&†_ÑbfêýÛyo»w~iû¸þd?ßô9,V"æ¿6£qzZï!^š±YRRi¬ùɦ¥)nµTs)ýH¢ªÎVÝ*&%\pB 2¾ª©g¶"ç´‚1gºlóf‘ 58¬ÔìfItã4ÄUi¹®+MÕŒbøbWÃÖBì·uÖÐL›aù_|šÐF,néQCehöph&ŬµR Ö2á©„ènÇjËw_|1J”yã}òµ8ª-eñqäi•­`Œe#E>F„1Jc©&ÑÍÇ{×uIš4šÜ€·ã-\å`çLÖWnŸ?u¶É9æ²ç#¬Y"ÕÃ)®žR”f UëBw‚«“C \žDm(³A3–T}é\Ñx„ôœ±².`I‰Ò?r„({›ù°ÆÊLÁt—BšVZ²‰Æ‚ŽícÝ"Ê;“½`‚McE$Î¥¯)áǘÝFà Ê÷vAF-ÌbþWö¶vÏ<˜ñ~é®CàôW#¾}·o˜í¼JÄ6m­…ueœØùšÝy5U‘ 9ì.I;‹3$?"CâæŸ·+Ú‡¯aéÃçä˜|dÍŽOcõ“RÒ†î}%S÷”4²ìËmxšècfâlÕ (p6Èškyõ­âM;÷ŽÍ&Áå­‹=Hjµ'W— ¢A-Ü6¤Àµ*Ò³›Ñ5!!.xɵjεvŠF|±¿¢R$Ö¡sÃi)W9‘|œ&Ö94 LÕÁCcªí–26˜ÁzñÇJ˜RÈ1ÎÉ„"úV Qvbw¼n— ‚N˜g„Êê…í5S;¡d|—®¯Æ=/Siì;¹_Í6Ûš;[Õ8~o²VN6ÛpÖ‘ Õ3½Ô9WHœéZD)ˆ”ØñW0‡ >B4×xO Œ„³>A³Ÿö½‰S8ŒoÇ*Åõ§ýŸ'†©5ØÝ2®“bäâNE‰¤üÎó“àñ|çÔ”ŒsiÁ†˜ÖC˜=uQ"çŽCáD{QxºÑÙG;ÐlÍŸ's7pì±ìûßo}ÖÉ„›°V¦j8U>Ý}»–BÐr×:ÂØvwI+åkrʳ [p+Fzö9in·5ðË·›»¿§Mt°ÞK©’¾«Ùk>YêÆ:¾Ûóðâ_ú"»ùùë[Ì{gâ5~¢.J oŸ?0.³¬Ës¶m2¶REÓ±`äÍúñ;}; 4É’eyŽ»Te\ÚûumkbXgVsɵ҅”–·Vj—DYÖ)3Q:HK…äõ%gUhB³‰ßŽ&4ªf´bÊ[rœîœž²=ŽbÓͨêïÙ¬‹î>Ø™:yœèÎôäOõêl›/n³5ÿ¨ùÌ™aQ@†T|¥$FvÊwÅ I…Ú|^8O$¡öùbj€Â(žë®Ul¦INùÃE6‹fí__× ;,‰)â™É’ƒ2»l" =ªhïm‚WÉÉfÌßbéf¨ê”Ï—k¯;|ý:£«·8Ê-+]ÊQ; lÛò(Cͪlv¼Ô±þ芽‚SR¼¯Âüx–±ß'äÞO™û†™‘.Ý.×ú.¼ß<>œÞÝý°ÐÑát¤Òß–}ÒkôœÍךö7§yn㘒1ò:Ñ3ÇRrÞ?S/N†ÛêS¿‡Ó‹9ºÅ]5Å)’h’Ân<ýYeÃJ»éaÇ«@Ò­ÏÖdhº2âµ mj ©¢ÓhHBnt!uÓ(cz ÷l3©Ûãlj¿Ûϼ60d;yç\ìVLÊnÌ—Š„ÌŽ¤U6GÕ“gõo¤šTðž dçÆ6Ì",`cµ1—„Útv}J ÊÙw›øÛÛ6°Õ½•Ħ¸[ÔE `®åÏtò–¥\¿²ºY6¢VèÖ»4Ø›á8%ÔšÔ@€˜ ð›oŠz:uËè¹4S{ñv5òeña!o*ö¤ú­IÆÚ;ÛÑ6žŠzµƒj¦nçšvbäñʨ:p™`šý[]ûhÅ`Þ[œþšwP¢<È4¿ú»$IÏŠ¯kµÝ{[o55¡ÖÍhÛ…÷YÒì Å£¯“Ê'èñ‘£§;Xpó—ˆä(ù}Ùr¹#ñiƒz®®è±¢†CZ½èsa›ùì•û8mbkä§=ó tyó–NXÛ$X¬“%F…ç«æºCŒâ-LýÞ™FÌ5!Yk_qbSv²˜¿ÖÒ‹CÉnYy›F0ÎvæäØç~zɦ€vo3tIŒÙ+µ¶\•,±uÜ$Òb—!b#³§cL%”HPÓŒ¤¥:æ™ìG®RP‡r6<4¿&ŒáóDË CªÌyLwoeÜ)6ß“¦Ì±ÙÎÎé’{ülf'¦æÜP &XæF·ù(”…I BG'†©{ öÔ2jØæÇô&QlPPýt» ´jQ}ù²BáºtFv‰,ãøü¶¦ÆW·%åÞ›|;rë ²b ,aÄ8îЙÁñºCâ’lÏ.¹ØÈŸN}È`®ÉïB·pýí¾˜WN×Ö¥uæÏ^ [2by;pЦ‚œ#öž—6±ì4?EÒ죓Òo”YjÆkÏAÐd>ŒšwðnÞƒñkü’„šÖüú¿Mº^ÏÓwÍìÂÝÜ) U0Ï©‰ØSš“oswøoó[2Û—¤o×Ýu½öydýXE0Î]ÙCçús–yN…¤ÐmÀí“Ë{WËÑÐpõD4 ÷&{Cßã&— èܺöiùÂuà:ëqöz»¥`&òõts÷ףȔ½N6ÄlAs!¾~÷n¿¶ƒNNû70ˆŒ½ÔôÐЛñ^TÆúô-É®SDíznTÚûǶæáV ÷6.¯™ôUÕoòÙ·…ö4š¯ýÕ[¿ Ý’¹Þq®°/Fê_)ågÒú#Ò5ÀÙןµºÈnzªçÞZg,ZNäº íBkм‡56µ4¡öá ‘·®¬u"|çdO·låáÂÍÞÁØÓÒupúefœw«Cm»=®?=罡 rï)¸ûÎÖ“f4ÒgL¦¿BC#ÕÂ<²éÃ?£­ócëváª1.Ä\;ãñ>r%d#ºüpém¦|øç¼5º„Cšº|±˜3˜8Üé€$N¾sRØ8F|Êwòº¤pMªÜÕ€þÇ&Æì¬’º4ùêiN\KZX]m®«ÖóÀ¸7λ½l}°ªîí¶XSu÷ÆÇ'ê¬ÿEïÍ¹Ùæ>èé—'áLÞ¶•~j‡¦t‰—iÍ)n­c$×áe,»f¶úY$ŒÌô;a¥ƒƒ@*¤™³YÍÞ¾¶°b˜ÆŒJés×Ó³Ð^¥óž²í—ú Ž’-£}ö·Ã\Ïp}HüÏÆÌÜ»ídÂû}éÝ/Hn,áÇ«&ñUå¾Ý0¤ì£µXÛµ·2@“ýv³™í˜lC ÜÂJzÿ„±°‹´-„ £1Ï †LCÄbšŒë–”+˜£+Ãvmöq¡šúI¢b5øXmãÛ4“–‹.uK8“i2Bbˆ“'I"Ç4jûkµöOnßkÚËܶC ¿Ô·ï›â£î³°Ý®wYBÅZ̶±Æ 71ÅÞ÷ .¾©ðcápV„¹Eé\ÂqÎÀ¦½ûZ|Z—ÉÉ—ê7ìN‰ôòq {·¡ ‰bÆÂjS~áy\I7ž—¶tQ”zO²òï¹Xb­ˤ·&ˆÄíDÄA[«¸®¶§q¸AkïJEcÍä»[—““u1)ýÌÌω Õ v-êó=ZÓ;³‹‘§æDAÚ[»>ôvïkxäî»$3Hf¸ó|†BßÇ@âð p¾k¿î(é:0ì“¡ð~É §ìúàýÞ‰¡&5ÌçC>ÝE6ÌãƒE™HÅ8l)EÚÓÁÚÆ,¸*¸˜œk„Ú]q7×ÒnØ–Ô\°°D—¨WŒœk\p#.&”’ìîÍ. sõCý•M€HÖƒÄq‡‹ÚÁ²^#°ñcn‰m…ùècYã»§ƒÕ¶³Ž;Å=;¯°[mèÚ3œÇ”z;å>l—zy’ ²A6K38Øœé#4E²ÅF¢&‰()ˆ h_1éñzaù>/ û›>"c£™š¼¸þ7 aú›¢<Ù[ß!¿ö]~¬÷öÊ{Ïó¦'ÿòCè—ìþèðÛ&Ÿ™yÿ¶déµ›ðð¯É{=Ý+ÚÁ"Ðd†ÍÂIƒ›vÎgLœôjÞÃû£×OGzNŸº„fÏçú[-»yëávêþ½ÝÏÂËïÇy›o^¿Lrdzoëâ_!Ä/¯‡ÕñÐ`,ðvû?Õâm=íc»O>hž€óGæ ŸÃ=pë78ëøs£l©½NÚs“Œâu‡ðy¼|ØÓhCí~ÓχüõRøÿFtØ ˆMtÏ÷(zBq„ÿiþý9)×§í2Ñ7z1~?¢Eûòÿw¹Hh„>™ÐÑšà4ƒpÞ ®ý—Œ_ú½Å*ØóäÈcš ÿ„Î(vè9šuúc=„@Á $üþŒUGÿÿçþ|úP¾pŽeÈàCZl @‘?˜À@ü¤M"ñ‡€t u¡ÒäŸ>¹W£eê¤.%BTå#²æÒ¢!Ø6!]c”‡æüÿ˜Çý*Êþ« ~M?YæÂjpLJö?.?þÄþ¢Âø=žÞ›æoz?aô/ìþ¿uâÿ2cw8¿ÓŸ¿+m·ýßÓéa˜fiüÅ7G÷ü®Ù{m¸ßùr—FÅl®áÈ´ ¥‰/ŸîŠŠ›¿.­÷S= G“‰„kÎ];ôºéïµúLïÞßíòqþÝwS veˆkù¢\7Ç”é›xg..>Š{ïióñì«uîo¿lÔïÖÃÝ zgKc[­ºÓ¦ZÛ(™XØ*ΰìº^ߣà°Í^±—`ÕcÃuá†í¿Ý¶ÖkŠ=Ý~\zföjþÞi·/O F0+76׳Ìpˆ9¡*~j¿æ$þYuÓ JÁ%$JçSŠ’¨¨ˆ€åØžížßž?Õ';÷C²kL‹<ªîæ 3ÑË&2â(ý¡äKý5é¯ôWÏkÕgï6Hßsˆ(ÎfÐk 5ø…‡þ=§ØaO{…óSÃÁMÙÜèmÓ?bêɪ clÚ;%ðЙGq*$¤Iß¹†v®”"Äy‚§•ƨÀ! 3æ?ÿÌœŸd9s‰iõD9Ï í+%w|Nµæóÿ)†2+¸ƒœy8äÇç}箆Pÿ8Jfà<ÉðïŽ|ÇÙTÓ%~Û ™š ¬¦@ – ˆÌ2ÜÊèà°›ÝtLTh?ýs6É… !¦ D¿šx1Å5œ—ÿ¤J@ßâgÀó›º<,fÜÜŽ®%ñ ­!4¶”¯üÃÌz|«è–"ÿ!+Rårž­I€‡ùèDƒ@6,éyµÑ'B“ð¼pt#ýºþ?<ÛçƒÄ“´„‰hcFE¨ùü‡± i3#ýžœÿÖUޱ¡×ï<6>ÿïx(è%$ÄÁ¸ô>vkƒ$ÛǸ7±6bdæã¾@;*ïÄÀ™Žâ›úšÎ1&."—I‘k^' ±˜ãXX&kÇ8ÈYàÌÍxÍ\¦ÁK†0 *1Èb/Crl@18M·[™ þØCqCaDN0.ýç§Ëư<|!ËÕ‡† )bɼCá êJ}§Öp<ÚaÉî  ±Ï‘£Óca`°}ï\¯ho´óâMÝ…œ%;Ì›fƒ1£×\œA›Iý²©Á¼Âa’ ßÛø_o³/O9íËȆ™r´¿çÎðÖÊ›ÛÂr}y¨ˆ¤?ªÊ£µtÒ==·Üdù±Úèàw4…D;A‘xP¦ú·0Âmµ~û»&ÜÍø55„ Êl‚d4؆|:à±H 5)¦¢ËÆp^Þ= ªÔ5¨&ÍÚÁM‡dÂëûb¥­mÓ]IŸ»íƶZ€g˜§ˆ‰M~zÂhBÃhFaðû½yÔž1íöq‡á—qêLœ3-B7 §P”•úÿÈqÆÖ ô sçå~Ç$œE \h¬à¹1ÍV”Ô˜…)¹dçA40Õ<ªï ›L|‡d¸ÏËUφïŽ5<;=‰sʺ™_¥z$MÅ!µoT§ÇÖ*ùzŒ†§ŸlÇA<·ŠñL3ÍÈpúNrY‘K"Ä;€ÏAØvÁFžqMD`w—’p4S—$_GX='@èÅ“n¨›hžsšµÇ#nÛ¤xvɤr$Pi3dYŒ$Çi4­›3ÁPFëÄ[+h6ÀËp™’°MPÕâa馬]PÜ“:$~Ê6às8<÷tœC©É͆¦jœJ#:‰Ed¬M!Øt"öü~q ’äy¾D”›¾aÓþ„Æ.Rs~¼‚ý¹Œ” þºDz }$?T vÃÇ.ÙCd%d%$%d#òn,!”$ªfãCå û½‹b5N>;ø÷©1Κ›‡éµš]í­€ä5dPãÿ5Ðó¿ ýÿ`mËÉnì©q—–³Ñ½„s”Ø>œWˆe&èë‡z†í\£˜a—o%V²âÁ$L†¡ñÈÒi1°ÜÞ Ä2†ÌšåÑ¡©=Pþ9™éÖ6˜Èg„ÿ¦šÇÕ-bëGftRXßž›•ÑOâð5ò0c½7o<Ž‹Á0'Ù)Ñ‚ R®2 ã,šB»ü«Éˆ¥ÌÌ𗉾³ðp:·€eü¸rP¤’×O ÖIìð­y¡.÷¿žšàØPÐz)Ný  XÅ¡‹ô™¶h$(—KXp4wCs»3[Qc ˆkÀæ ˆ%™ H›M ’&Ì_†=áp™˜Ïùç?…øO ßÒ{C`gÅ'¼ ‚ûNå.RèÖ8ÍÍÊÌ‹FcŽV·6.6€ X-‰L½Äå$K ¨åY›s>öòw=u{ä¬YGçAÓë2ys9¶ÙÉuTñ'" Ž4|ö´´*д3/7F%îçûý¯ÖÏ—‰NýŽÙ6:ø™¢3·<Ìw±mØ9d\Pz¼ãõѼlÏ‹Ón ÷‚+ç~l íù\“•Í®»÷T%ÿM0¦l`a„î’.i <¿¹E-3§é‰º‰må=Ö)Íÿa€‚Zcý‹^–‹ cJ}º§<àR$ßNÆï6½¹ -ÂTÇ¿R Cö)èßBpÜmµ»êsȰ³³lMoI‹Ië{”>ÁW‰®I„#ÿ=6[i`ï\2RéK„íÓ3Ûm²³î²çM ¤…$Óy`öô[}—_Ì町¹¶Ø7e'61.0™§ÅíQ'ÇŽø>â›3VEèô~ŒOEƒ½¸Hgÿ¦Çv3l‹fH"2Õ“7~ 4}ÁB…íB{æÆ%¬º°ƒ«aÍ? ´…„Ižõd=÷¸›£ßYô¬?ü¿È sjÞ‘çňt½» Tü߆œÙ2š]a4Z}àNgiÚkùgí—cCa&67dþÏÓm ƒt&Þ™ƒiïn~—2.þÓ;QoþÆÎÏþ{Üoç¼»ü>‚Ï’Û¨w&Á®«Œè(%‡ßcŸûüxº„ê'>{j­9eb £’í)Ú˜W´ïܯž”ùAU¢¹›wÄ‘çoÀÀk ÞªÊÓ˜ëÑÈ¿Û¸Ó ópÛ"Ò!DÖJ+Åé­;f̦ֈ%¬t”þÛaÎ7¶ëÎ?êM`Õ;q&%Ìì7 ¯ —›±m´kÜ+{[kнƤ µÁáÿì†Í7%$Û|ä²_¹·\ÒµŸfrôû~CÛ§[¯Ã"÷ÆOŽóX³‹[Э©´Œm&Íy© m`:î¢úí hãpNÖ ´©Üú¨¡É;:2}ÙþÕIu ¾ï}M»óàÏY aˆ“ž©qàõ²£§[“Nd“Õs4‹Ë¤:„S³aF&æ…ч›º"ë+j›aŒ„r£… ¥cýyãºGªß*9•…ÅͳU ¤%„”µŒ ýK‘MiÜê ‡âàq< Q–.é´TußoÚ–Ìb.·Ô·íóà^S³›áóUv+ËÍ?ôQŠDù¢K2ì½Âl Lš¶Ü4j·h;£;\˜ÿ›ZÍ.qK»Ÿ£9Ì`,a›Yƒ°KN”I0š]H#1ϵ©e¶O"ÈC–T†ÆÌ³é•¨œ”aˆºéJÊSp‹l‡¬Ð%à{l/­ùŒPó”Ÿ)$〰ÓÂÜùËÇ·õñNÚÞqÿÿ­—&´ЇÉeè‘ýëme¥£óîôƒÓÕôÒ¹V /\ZÌ”#ê85ß“lÆv‰¯LÉz rGxæBbÑ30IôÔB ò’ê“ÉÂùŸ‰§Î…³Í‹Rt›mùÍNcŽD|‹ÿ³îp¸Ù±¬$ãÂ[‰3L3½*ÃÝdL‰ÎoF°ªLÎÃè£sfOKY…¼áÅ.m“$×}5Î#…"'¤æñäó—I¨›57xa|Ï^‰\{A?.ý½þ7Åø|ö,=Wðè³Ì+Ö»7rJ šê~¯'ÊÞU§—-°F³ªÏý“†¬¡™¦ÄdÉ#ëþ¶u±fUĆ« Ú²6÷¥Ã”Qó¬yÀZû,óþùXØY€×Ãü§HÁ^8þFm~Õ˜½\ðn$4÷s8<Ãl©í ñÙC¨ÜùcÒZßHf#È<æäf ØØ™‚AM Èêi£z;|Vãú"*«g Žáa >IÅàŠñ6EÉÃâùx’.MBkÄ" ã ÁQÿË¥øM¬8L™O×õ*\1r7Œ/¬FÈoú&ÿ›¥ÿ95…¨Û ŽÉ¼ö»?V|ÖB¨Z ƒ¢W7áê 9‚Á^­mÚÓ!YNé<ïïà?I^ ÃÓÒU¥çÎ%¨¢o÷þié÷Ò ývKýŠq—üÊW«·§út޹ËÉßþÌÏVôàæÃ²ÿÙîYâPËO ûuùÿve—OuÑ6–¿Ý|põüÿ—Q<úz~ÿí™”Ûg¶þÎ O¯]l4°.u7#°–óð[éi®¼³ú“?i:›ÒŸ›Qý‰um¶0¢ßþ¢çµñ™CùÛ™l¡Šwlài´ †ÿ‚åÿZVh! 䯶ÛÙ ›Yþÿ]Ù®ãé¸ÿ©Àö–ô`$2CH‡h2o{e†ㄈ‡`ÚGŽ®ÓwOþ֦ê.ý•Œ›æõï7lá…žþn2á7—Ø`üÛ®;»,ªÛ+MåM„úѰ‘D­ýT¤÷r븅Óôï]MˆáÍÃ£ßØZøžÍp‰õOøÝüÿÌ?‹ÿƒîÎìpú{u¥6l®•¶ß££ÏcvôˆÚ_Ãus–¶Óss7v• ³lÛÁs–¢kQ†W~øŸŠ¿Oã.Šçb~«šðy =e«¿ÓÐBÉìÿ²XDÿÎñX†I®ÏWg8rè£6”‰Z¬U“&¨Fô3zù'2/fl“S'â`iÆuNÉÜ.;ÑÛžÞ&ÎmÇ’‡%þ_õ³¸ÁàÚö"R9;ñ8•XˆêMNµ%LrÉ?÷ëãó݇àü~»ŽEÏK7]쯗u#HÛ·è߆ûm{l²Ë,”¥)Jã[Y2‹qkÊvtÿeׂ㹟ÚâïàG“དྷòønù—çá™ËÔ|Å?žU糟çáéáŽCòó˜*«~Zs‹ùþG·âs÷}ÆfÕìÆ‡éuËèÕüçO»Góù‘RÕËZvóÌÇü°âßeÙaµzŒ¼¶ÞÇG•¹õìî7øXÅý– #ìÇ«ò¾Þ¢ßUÆ0ñðºü÷ÙåÑ-Ãmø~¹U’H«³²ws,"³üoGgZ9»ï4©§¬³<ðiâgf[B®tYºE»=Ï;®à79íãu‹Ée…œv}<ÚC-¾œæPé0áôéè\|7±ÏÇ.’ýýýÛº«ÍÒl͸?£©ŽŽPt7X§i«´y“ZzsüŽœ[ Ëíá¹ìÿÓQ¿;&ßoO¯ë5=¹j«ÊÞžûüÇg1Ëwúòö›%|Bo—bvmn£}eèJ´p½„4™ÂQfؤM_)<}3˜sÝoê“ç‘êœçâ+IÍ [g3©ìÎÖð“©aÓü%o‰Ùó[.^Þãõ+nEù¤~8Í3Ðöôë:J6%yƒ¾½ÙtˆËéù=Zû=Cä¯Í»ìôðw‡Ôy`4"'Š„†9á M$ð?Ïþ®½|p“˜‚Ó±°gÉ8'£N1&“Aˆ Á̃¥qã2 IBZÜDÎ8‡âlü<´jIgý·ª$ÊÉ*ðƒü]òà‚Í$ó‘+" ƒ‘ɔà 6Ãmµ°”ß[4AÁþÓ°F*yùMªªªžn~]ÖGò/õÎÒV' ¡BˆÅ™S.eõÕÖ¼xõôã…‰Ö<Ï1“3;“37335¹h±’L&HQ%Œ`íëØo¬€EÚ*(™Axµ(Ò¬´FŒ±­×2лÀ±“Œßâfƒ}MÆ%¥X¨„/íkQQ04‹—·JÄDPÃ7Í2è¸òÕ›~;F$AöGœ'Øðo`_/çC€³ƒýúÀw ‰µÄ†ÌгÐC0¦Î–iÝ–X±4SåΦ¦òÿ6áCKªZ—èç?C |rvÿ_XïJ ¡(†¦áJnra‡ÔhÃGàÆ<"~B'„OÀˆþ )L%0¥:)NŠS¢”è¥:)NŠ^JS´†‡ÂK‚Ž0ÒI4Â0¸®*¡#%­Ùª¡ú;lªª©(I‰rž¦f`ä‘Ý wBˆˆ­ÍÓ·ròù /³3³.îï®fvꪲb+üê£üÌ-¤Dz¼2š$AWmáF9„aQdûMFZnn3i‘="(´MÝTAÇQ&<?A¹4F2qÍ(ƒ,G`±hCaxU3éÎÑCQTÛe.º-Ë$É¥­0¦Ë³tX8„H@ŒvqÉ*Ÿ¶è‘Ñ{»êtú³ÅÓÒ¢$‚Iš)ÙÄð_[K_eÝKo¢"R”¥³ùÏæä:;…eM­š[Îؤѡ3ëçøáKÍ+æ&ØÇhiq˜‚þ!˜"jŠb,Âìyï¹­lb ¢˜–-Ikü™Ù9Ñcõ%×|; £ 5h!Ø: ¸“°•0MÄÁ&„КBMš)M© º)zñ­ˆr ЍÍRÒm¹£EZc%Â!˜ßlÿ?äf‰È_NuNòÉ8ödC^Èž~²mîü Ëün3Gƒ›·üsl1˜3Ž#~ª[ÍÒÄä*X"µ&äP‘$Xad¡Þÿ°? vä&ZT†b’ ¦þìÍý(Át^%¸U×v´¥ÊƒYÃóîîßLH•`“"¤&fžõ|‰‹ÙÇ#© ¿!Ù¶ o©Î…!‡·Óðø5ù·6šõ7SQ· ¬ÝçFyJth&}^ð:»n ©¹ý]ºÑ÷ðýG8ÇK&I›A,/§1é¥MŠ]m_‡îú¹‚ÚÖ[¶·÷Ѻó¾;²³k``nÀ¸,¥óž¹mûQåé9ŒÅÌ’‘CO bDK¦ƒ³6:Ù÷¿h5%± ûê¢ßŒ\¨˜¨¨/í“åâŒû8@ÄŠŽ”+Õ‡Ò›ãŽ#BWÑ‘›Îûšñ!ðÆF†òPm¨ìÑWN$,F²÷a »Ï<'Óc˜¤òÑœluÛh zšÃðëa¿zb˜–9™r¡|¿»nfû°‡÷zûÄ9í:âQx ;¹¼:èìkàˆ"†u°ÚH$—‘;{}4hí±¥ ¤™ßÙËVÎ_#Ýß"….ºèVˆ˜‹‡"×”—ê;Ë©iu…Å…¤ÜNT%”‰„ÎSˆä2"÷—ÏÍDËk»Z+Å[DÉ{£énæ£ )”(¸ånÉu—°¿„²‰ˆBÄš Œ ýódZR™>XÎs”ð(ä§D’÷=1—Ð?7¿áŸ«øtâ7e’޼]†f´·ÎÝÛý:9¾fân–‡£”ºMæ ¶EWy»êÒRö? áiì?T·ˆîmvT]^$™Ûj¨ÔI„$Èv xHt!Ðí°‘ º|þ4Ü#±º|ü¯¿ÑÏÝ#ê›¶éñ\½¾‚.³å4ðßßåždãv>¥™m&Y¬µË¦—ãé«ó`W,ÏÏâpŠžE/v[/¢þŠKoöõ9÷!眥ãëÙž3M*S¿, ê¶hÞzÛæõ÷\ý:ê$$Ÿô;þ‰<1îéw§Ç Ï-¸||å}ÁùýË…û¥¿T™2Fo¢z’W®è[ôöí?¹—xçü>\x‹éß“n¦î÷¯[ô‹9Ô2ûO©Ï_’f>n®©}QÕÔ>GÂw_õyn÷_‡¶]v}]yþίf¾ƒfxÖ¼¹­öØzmãg~ó³?šÛ«ÃÜß7¥"ìóúþVù5¿£r—'Èû7.ˆöí=XX°úèùöì‰PŠùœý>fîð°¬P»ÜKO/›g5üÿ\vuSgôrÏ›[;IÙÒé9×·Äí׆)c,ºÿ 6-öA.Þ^=··o-5ˆwS†Þj{ÊD{¼;>n~úwYŰÝ5Ò/Ðòö}Äþ¬4×öÒ‚-ºn½J~-i°ãN« ºqž\þLë³Ó‰¬{dÝ%2ɺٿZ ½®ÑwØP×¶ßKn87ßŒÖ /÷<¸`Íèá,í]¦óì ¾ÙÊÏ+-¿&<¢ë$’M42t><þ×-Iz y¶3Ë~nx=Ù¦on¼ÐÄ,õtš.rI.„}TsÆ¥% u®}Jß/ÃÃӻꕧ×ÛvÁ LÉ[Ìñ\½_í¾)õ<>Ÿ lÉËzçñ-ì<òéìökáQ糟ËgÂô­;:5ß_7Ñz]^åØtpƒÈß íí#Ñi1 ‚K¿žŠ=…×GÆŠßyÑF]³åtn»–~ONÜJô\Ú˜67µ“(Ó•»ƒ­O Ylù£‡:Zè4:lÐð†°~Öô}×ún-H½èvÝÚY2Ý·Ó+χ1€;0&êvÙƒ³WÙͬôÛOcYÍÝÖ ú–(›7Ðçw_;fßS§pǃ|«k³ÃÄO·#³/§ ¼‡¾ÜÎlÑ«ü!‰–—ÒgÁN†xá‡5Åþv³ên;Xñ8ÙûLMåûxg»¸wW=û÷eUC<æs3¢¸úžÁÜygÛÍÐßN¡Ó~Âï›§«Ÿc]+ïž<ßÕÎxË1|®.f ¶ýÒº\¯· v™üÆÙðìòúqÃ3,dkvÔ¦ëÛèÚ{§‡NþÏ“t³ùsëwø^ím›6îûCϲ†îNéò²r¬‰e×Zy'…“)Ôn‡^ŽÃF5~(ìnó²ÃÏÁÆ“}_ebï'Ñä”y¾‹ŠÏ&ŒXì!0wý6SÍø+[Ð|¹†{}óÒooE–3tO/;žÁüïG—ÝH·¼3”ú˜â+¾¾§ë¦ýYÙä‚¿‡ÏÙ#)—rè:ˆû¥(ãÌ9êû–àvbBdÞ~ÏiëR˹Ϋ09ü2åYèúXæýÚÌï—¢=¨×a®£›Ì)‹ù6øsÙ§@N¥œµ_?·»§Õ䥫žéÑÑÎmî™rIÿ-¼Ï/=jgÜ76>kúîîè˜Ré ˜HÚÞ¯¿× c%×âHááí/3Mã ú[²×Z Á4ú¨Üò-z»1=oÕ2]ÿ 曥ôz8ОÝÙ)÷ñ¶[æÛöš{‘ýeöåú|7ËÍøß['Ç•œ˜ÐzOóú·³—¿g^†9;0ì o«æN>Œö%“¼*‡‘B¿¤õ4ޱ’eg¸™ónüÆ´iOÕ:?Ñûî××ØÌ¸ç¼Ñ­eµ¦émî6ØÆ´Û•–:ÞW±¹[gö½½|¯cr²Óýœ==o•ö måm‡¹ômò¾îç»§mÊÛŽ’”c ´:l:ÿOâZ; ¸™®9¼³™„Ÿê¢LÅ_öÍäúõe55vy9äâhÝåˆsN ¦m®83Mÿ‹®ÿeS½’1‰ô[aÈg9É•rŸO§ìƒ‰$“g‡î†ˆ‚Ðxx`R…˜¦Ÿ‚÷C‹vžŽãŽ0㎠‚…ÖsÓù…WÌl1dŸ…’§ ›š‰iAúS¤¡ƒDì”Ýóœ6d±á“bÓhÌrpL˜–åãšc¡ùò°ûÙÖـŶCoÑÝåÞQ*%¤8…())V †ZP2J¦)ÖaX¡…$"’€JAj†b– †b ˆ *J¤e‰JZÄdýïÃÓ?êQU‚”DA‚=¡! J¢”†K¦@¦…2(PD,AËAAÉòüòï6ëã­'õýÿÝ”—òáÚPòôQ{²¤%êʆË÷8!ÌZ§aþóª0ÇL, Ø àÕ®@ÒüÞHêñxÓöž Q5Îã¸0xœ‡ˆûó–F$ÒA˜ “Ç8–5)ÃŽŒÉQ2œ&¾óüo Iýá¿q¯F ?b*Ú~†„Õ9 K™:@$ŸíCþ¿göø*îC3bÄésÌÞÉýéÈÐPCõcŽ,FíAáÜd2¨«¨…ä‡d÷¸ÐAÖT4dGðÜgÐðqÿs¯ÉÔÍ“ýk>¶ã7cÅF¥° ò¦×ñî$š‡¼(›ý¥+cùОhH,8;Îtˆ©BdÈ=çÖuŸQÚ¼áááDAááááá—¼¡ú{¸ú(ÀÓDšuë4´9)`šÇ?O:ÕÀ9M]îE=ÝòuƒC21""󈨋Üó“[Y}?OŽk öB†0þr  Y÷w6OÁ”ü8“”¢C©6 ² Ä3RÝ  ‹Ø§î§êü½ýºµQ>Øûr'%úòí= ÿI¢·Y¾œÌHR¨ðÐ*»RRˆIêQ6±:ãbƒRï6­\Ãj^‡?Qê~ÖB˜@)QH€n A¼¡{{ïDú(¹Q„#íË–’ÝÞà3J;ûékÐ`isœÏè'oLR£ÖÊJ—R‰šÊ8êµîr£ý”Ù b<ç˜saézîÛäeÿ¼íþæ§, 77¡=Щ$~ï¨7†´êž"‰‚7¶ÕöÙö3¶û¯ÀNÓÙÐìðžÈRë¾]ÒE6·:»î“Ž´âå™Ê{MW3dY‰?Æ¢sÿ~™œ›s÷óêzÈÑÇv:B`Š(¦„zÆ¥`±d £ —Bx×n.ûw0á<­¡Å/§„b‚óO‚a LÁBÍùæœ|mdO^a¶ºåÞõâÍZÔJ%8>Gúø? ëÂvliJÂÌýrÕÁ¨/B¶ƒŽªˆ’žOäñþnñe)–UÆìc³™‚Ñä²R6OiÂ2,&78 Ëù`ÿà˜’q·¿ä‘Y…Ð%üò/í•÷C†ƒû“ƒævâ—ï}«%'‰š›¨Ô8šÄ—èýWQAö?’òËôŒp~²üäÅ=lì²Ïï¦ÂpqÅ?ãù sïúTÜã”?Üן´ëX…£8ï’!Z_6ŒLT7‡îñ±off¢f)‘¼†Õ¥–kÓ)ŠO-!C€„z’h&í­­S¨l‰=\òñáJŒZb\Âáî6}© ÇAŸ\ëP‡înüžèö•!ÞN·îÏÉmm°k·Œ˜bèîra]‘#ÌZC@Ö9²5>ÃèMrš$?6N[aFx£Ý"/‘±¤ß,ÜMæu¼.‘MWPúgÝÑÒtÄ£(½ûo›mÝ6LL¡†K#c¾\Ñ›ÓBËDá>wõ.|zê4â›Yp†/‹mæxOORµéÈdÔøÌRE³Æ‰ÆLñ±n®O›¾&¼;óñǶn7ã.¡ÅÖÚ¢*]ã 1özqÐK;,ÒŒö_†ñOYJðãÙÆ/¦ YÓçÍŠu…eŒ§¨iO”/½=Þ)iM†ìM‹Š|*j â´¶S(™1ëÂN–Q§¨‰§}Ýñ{ão‹LlñeÜ‹ë–,"¡åÇgvq ‘ˆš—X‡xÃïÜaÅöî©Æ^ØÅ(›ã¾Ü|'¾#G\m©DõˆcÜ‹/ÊûVÊ%8âñE|µÆÉGÚbãØøS;Mà N¥‚P©¯u=v1Ñ7„øo—œ|áÃñ=égL"jyǸLQcœmøMy’ü(ÚSáp`Nö[¢ÑŸ1õÏÂûjâ…˜`ÇÖÇÑ+xÖœ‡3ÃÓc¦MÊ^JwÌiëë7“ÅîðÑ<ÙŒx¢Tòí=Nß<{¼!}†”°h¬º'&÷¾tO‰óç祅¤Ã.1¯Dùw©ç#LkDpc`qB–">óòŸ‡ËŒPÞí¤VŽøáqÇÃÃQ~{¦¯ùgQ{w qŠ!Ö݈ىðS©ÆJ=¼|ïyÞ0ç fK¢ ¿Oœc©á™2Ñ1¦ [±m/Ã0S~lølwLÅ ¥/Ð"S™M¹¾Ÿªðü>V B¿ VôëM7ö8÷[}ðÇÎxv>`ø^î-ºÖk‘8Ͻ¥7Ž7ubñužãY„÷kb›{é>zbý}ú/SU¨?ÃwÊwøü§4§Œ_Vq¾‹4bx¾:ñn5¦˜ÈÓ ©ƒ­¦MîÖaG±Î£ÍiØÁ¥)ðÝN°ðœ@ŠE’„ôX2zÖu}ØçÍDئ3ae0º‰»]*6ViŠš5­a('Ü{nhÓ8ÑRÐe•70£µ.ß-Ín»S¡M~xÇÒRžòuuD±(¨#KŒf RÂ…ÜßÞˆïN \7iÒRÄ9 ‰‘s1™,2dŒà­–àKOKÚ‘Éoy‘œìò?_xzAÙ °9³Ï!aì‰ãÜÇ ß­ÂOÕ<8X–D‰44¹ñ3¸äˆ¦Û$,¢¿8v¤gãB—[Š|¦ qb¯qÁ»ا ÇÙ²Ò[ÍoÕÇSçÃp±ø§¥ö{›Røxéã7Åñ…|l|)âøäìœß/ÀéD¾ö78C\íø“ÇvÆ||A:ûîcwÁ˜1Øëó<'Ó=Ldãðíà´Òúÿ&8(”`îË9ÞGבå@H?„1 .‰$rd²ˆYMi… Dd„0ŒZ"R”óÅÌ¡Å"q½|q|*Rüx¾ãÅ>±ëepz=„î¦%•&„”þ²dÇ ÂG%<<¹Wv˜éÔ§ ²ëï‚zÍÉî8Îa|3wMR¥O|fç²[bZ—M> · JܨNQD(AuBDŠG‚‰ ()‹Ç;]K/6á|2Æ2…ê¢qLcÊ^1Å‹Št¿ ŠqíNä‰f*¿ˆ>4™è´¹¤™ÊyCpaR–ØZ/B”ri”‰£^®M&d¨Š¥ÊÌá¹S v)Ñî8³fQ(…Úäãt–ñÃ}a½T§¼wçÆº±¿­›{á×Ç÷m73ñgº—›ŠSÞÚ7±}L|0Ë´MÑM,ÅÜj÷ÑN;¼âû4ñáÇo¯®¼ÊzÄÇ#Ò‰$y2©ËÃ&ò$ÍýÛfØt±×§'&ú6î», RϬ`¹(_{L]ð÷Ï{Û~ihË ]¢dSÇÃYyøa<|MKic}K„ß8éÂ¥I"Ú{¦Ä‘‘‚DÁ3‘3ȱ Éô üª¢vÇØñsfñ½BÞJ õÜcƒ cá¡L[˜Æ,ðÚ'™YaÁLýð<Œ0eŠpã¦a1 B3.î÷ýr=&0Ĉ ŠçŒPLP‹hÕ~öÿÁøƒ´-oA‰¼Ý ŵIÆÕr“· ÎRCÄ B&‡—4›®ùõëàÎWåMÞ¹æä–tìçØÉDßÿFÚâkÌõRº)9©ØìðÉLªå*Ù,E•ÐÌ ,…kå"Ä:Ò>;ßOÙ),šš¤HdE·óü4|[o-–Ü×lÚ?[†²¡œÇ’ÁÙ‡`«ž9ûb¿"©ãå!>dÌÄ14‡¦XéX“ÛRþ[ÎÍFˆl¾n³8ßá«ã¾ììšl†3˜”¯9¨º%ÃaÊæƒŒ#J&äž&¦šjî˜>cÌ‚qØTö½–¡®%®³f)“©r>/ZþY¹ÃÃx›Á¿oë5|¢„“&Mh°GrÐ7ÀCC£7†ŒARJOcÉЛR•HBœŠ¸ã&ÎÏ›âÝ6õ7ÓL¶å=ûÍ0APÌAAÉõt¸é¡Üíœ?òs¯£ùŠWÿñßÊØÚB,ž·-Ÿ¦N+,³‚%ÿí?ßÿ@›µÙC¤ ëÍ!÷ ‚ÅÖ÷ÿïÖ“7@²„òïM'¿FO¨î@¡+Ñõéw+]ÞtíííºÉŠeƒ¼[@ý%‚b$Ä@D=Œ@D„A‚1o÷Løág=&°×pë·ƒ`Êg’Ü{"ˆÒˆÓLˆ,ÚðP;wYDU¡Ê±Î+¿ s­·›1i¤g—ÔTv# ‚´ì ²‰—Hsó^Éä&È(QÂ=ƒh‘Ì<î +‹ õz6žy† kS3 =i–Øi‚¦¡èªN2ŽŸÆ|ΉßºŠ˜™¦*¨)Kî„C†môuù(þ6ëýkZÞOáÖÃÛòĻՇÝåÇO¿BéãéÙ_§ê6l¹†åòÀy³Ñæ¸Ý|ç»nË¿ÏL7ÞpÃwÓ!¶×e÷l?ª»Uy§5 Q”ÝÅ„î·Õ•>þ›†xßI½þ½÷2ÎU]ëõvùJÅrŒK/'̃Ó†Ó´ýަš‡d7Aºú˜ØT?,€ú0Òp8ëGî61Ší"’hœ$’f>ºôéáìÙÇ쬠æ£óóz¾«ºº+ϳ…þo²˜ÊÎlå»»õY;Î|keÕ#zÒsA9‰Bpö¯.RVÿ›ý{¤<®ÆçŒ0=vÌÇñè·†w•ËoªühtõD­Q|=Ïy—ªÏèýºÎÌ´YÁl^ñ•qºq¶ó¦û‹•ûײ´µ«nNDK·û§;wÅbÍ· ÝKì.ÔÆÎ…6,§ÐûŸ+ïÆ®Y.⽟Þöî¸ò]̱ÄÏÆ{oÎŽ“¶7`óÃߎÕ;:z±Òëò–M&Þõ•¨©£Õ+ÕºÚ(—]—¼¸g>u³>ß×iNµi]–ï=7Ùgmb|§K¤·Â«Ê|0‘LiþŽWß[-+O—’Ün»znã¾vfóŒt×[筺ܩ%YõeYOÓ¥bvuô߉¥:ºÙô㊿•±—V“¹ã™hô]DdïrÇ?-ÔéT³,ía†ò—W++_&çèéÛvs{áRùC¤NøõLòòÜOÈ´‹ñǯKüöú.Í M7ÒIî{0Už³¤œ‰à"vRËS+ES¶]TŽö-÷•ÏfP]ŒVoe¶ž›²Ã¢.èó<üš{l£íš5Ñî[û¼yIñïö戽ðŠÙ|ùøwK¾^×Â×w~VÇ øóoº»0…3Â+t¥Ù(ygÊÎ6wÊ.—=–é¥ÒÒë%X1Ón2¶×Æåé°­7Ù\ñh‹Œ²g´ÒÒ%*¸¢*XéÝÑ+в÷ËÍé³gCæÆ}}·ìË;C.a·Ñ¾ÝöÙÁm—;Î2ŸtëerÂ1¹ò.J0ë³ Ü­l—“SgNÅ*>CÞéóäõÅ®•›fôá”Vn–TáuÝþ«3‘ªÇLíëž–l™¼”ÊËlýV“ ±6*<‰¦¿4®º|ÎÑ 2ùvyµ¥…qrÑâ(r8NÈrúí†ãÑ:ׯË©bw=rº–šÙæ‚ ŠøCZ¢"'=½XcÙЃxyû1ñây-Ã\ à£Ã ¥WÛFCœfÝÏaöèë"èÝéõrÙam¶ÛÙè×q¨Q¶Ú‰yoéXQÉÑJ~YØLꌔn! ‘juºWîÞdÿg–½Éf¬Ÿæ“§—Ñ)F½tUµëÙ]þ—çTV¥x®Yá¾Gv=‹w_Žá‚ׇ%²Í—·cé¶Jr†›õk¯.sÓL”â¼Æ–çóÊ‘Ž%eôb¥>NýH±lm°:k“Jºø¿l¢·céký‰ß/ºòŸ O¡ˆÅ¯çóôŽçä†=]|núI®î?…öð³Ó‚Ñ1Ì@hXvï·¿ÅÚñÆGù5ƒû3ö~o¯<®Àà#,»Øôn̓A5í³@î·Á‹:<¥ ù½ÎÝ?XË«ëË·×›ìÔ³—{-9ðn÷-ÜÓã@1N—o7æuXqèêÂÞÙÙo=o‚º³1ù½þÿžù1óΟŒý’v¥³›NR¬«*E (í9Ò´¥eZγœÚ´­(f§*Q«X£W¯¤øì쎞<ÆÞŸüIm8óz0ŸmÀãK=—ÀÓL{®»§«ß\Œ s¹Ö×ö†ÐÆâЖ·ÎZ—Xmƒ+ÇÂ%°‰Ê¶Çª¼+FðE銲øo$rG¸ûO¿ÕhÕ¥Ä EÏêéçÆZ¡p®R:}¼Žný:ÏŸg#ØdÐͤn:ôüâ00;ü»€vÜlàO#«ù¼J#ìñÕi·ã¼È=G7÷øtñÏyÌïÑÍizÝÂúaéÎÍÂTÖeÔ½Þúí,Úu© E)7ü&@zI•—)´™5¬†”8©CÒâË–«šf™)6ÿÓB–6¿öÛáÐÉÄQ˜;0ØÌfã‡Ô¤&Ìç\NNpõxy#”ã“ÙÓãC ¯óK]UÓªlWÂSSï•lëøVxøc^îãÄÚ‰e™|)œ²¥’%øVÈËglgZ‘}|„½E'óžþ—tRRPBômÙ6`G½Á£‚×M ·ýü󮹞ã‘.óaE¸ÌL¼­æÀðQæ^ ç ôJIY´­I•lMœÿ»w“|ûZÇœêòru=öËÌk´ùy:íï:MC‚,~çCºôøøöQ71ôxáåÓ³ÀóÎíŠâm–<}–×/¢Úãé©Bƨ›÷·½×îÏÉaºy-[yVøfØûo¿U%¹ü™ïç%³]­Í÷q^oÄ̭ݵû-9÷òÅ]’‡…¹YO'‹BR&hüW¨òã~8ótµ0MqCp³îñ³ÉW ~É•×òRîãâ{ΣïÃŽ÷l޹t#"tƒ¸ß߯S¸E¦Ûɼ·Lã˯·Ù¥nÍ]„ÿ=Òæš«·'ëž>¿ûÍ:¾—÷}_ÕŸ®}r lBýÅ/iàg_ Æ_o·çÏS²÷~¥¾>‡Ð<‡!5¿»9I†ƒ5ŠÀUŒdntÛüM…Øý™¡?zyÝ@ÅÛ Ô|ÄÁ¿MÓ·ù{\žTQJÄDŸ5y{—âKê )ÍË÷°w9•óèYðøt|©|ìO½‰…GÉq½äã,G訛sž¬Ï.éú«æyvOŠO< ãÉÎ*Œî»lîæî#þ"?¹aèC5ýÖ*bc¹à¡”íNCiY463Š=s…9²¨ÂUÅ\·ôŸúž`iJChSù!ÝÃezÂÒkÝ;‡ÓhÉaA2ûãß_ƒ Ðâ²ÕPe_¦òàhjO”Ñí!Äí!¥4±„IED;vÛ´Ÿ"4ÉFϬŽÕ˜3ëd(¬ûy¹¿|> Ʃץ›°"j*ösõ»ß£t‰™J÷œ” !E;aåmÃM¶Û³ªf*¨&JfªC¿Np=CˆB*¥ˆ(¡"@¥¤&¨’І€‰¥˜hªb)€‰‚ J"!¢‚(ˆ)(( R" „ˆj‘a‰  ’ˆH”¤bb*”‚¤†¨/V˜(J„Š©%˜¨¥"i)JŠ˜ÑêMãÈa" †‚Ц&š b*šH "„¢ b‰ŠR*ˆ&j†b* ”¢¨$¤ª¦ˆaH Ha€¯Ó°ÐÐ!TÅDÅAÁÀ@Ì3ÐS3 P‘RD”C$ÄA3QDI%D3,ÊÌQU4TD5 S!ÄÌTLÔ̰ILLÁvhÏüÃFfö`†ú¦Dð]ÿá>s5ëçøíßá;px-'¹°ptk[8’$cJlÇì(¶Ç1°²Š÷ÿÒqÒ0õ†!;ièqÓÀ¥¶ÕŸÛ·šïËá~ïWé»aŽ›âô„2}6.(˜ˆîa?Ö‹ÓPX¨Ä¥/1ƒÌ–Ç2é¿VpQ T4% RÁ3ME$TÍEÍADCDMD”ÔCMD¤BRDD2E%0ÉL3ERC DQCDÒS3ÔJS4ÐDPÄËAIC>lEFÈÏb( ¢"j!‰¢je¥(–’$*!¡¢f©ˆˆ!І †¦¦JB""!¦šb¦Y‰„)ˆŠ’!˜"æÍÎödaˆãhÍ#þÃÛðâûý&p¿Âyû\ÑãPË7'8é˜é¢ùô‘CEIý±×t©ÏºÈWaó.%6¨ù»CSÌ¿Ûe Ñb8¶Çsp$Yv”&;DÒúØ‚íëY˜ò#Å"$ eu’c6A P–-Þßzž§a]ßÚF?;èkRŸŽd‹¼Â^Ê?$ês3€s®I˜ê@f)¡³bk8Ož÷WáKéJ|{Ù­^ý•FwKjX“_]1P™[D¦DìPŒ>C†xÛÛÂÆµYsÂå‚ ËSñvm‰©&d™$&B ¶Ëú´µç{j]‘¶ñÐØ €³¤ C÷G““V·–ÇF¨|ÿ ¾­áôÜæe•»Ú#TÂ[ÙÎ hK5ѵÕg¥ÌÜqGY·în®³äŸ”Ü•ZŽ8îÍ% Ó){³ßf5ý9yóàc&xhÂ%!âNV`ŒDNxÎLsþ½ºßu¶3+.Óu Tq©f-¯“S%¹Ö¦ê‰£Y®©÷rSC®IE¦¤)¶dèD«ºÊ$·›,A;-$]uÒ†ÿpN³ÑÉî:¨ÍÚ×nÇÞzLº<éµ·Ûr’1 µ‘û—««·Í9ùìô"í[ÜÂöu<4{‘Rß)~Àú»~£q=Ás3{Y„Ä›ç=Aù»Ì¹6ÍÁ@ü‡³§ãä¸î%/’ýÄßîí¤ÿ¥·Áîé÷.ù|® >Æ›¨¼ÜÇc|?ˆ éÈ)ß²ÆÚÿ÷‘þèyëL13Çvº§éO ¢eD¨àƒê!]„ÓAG› ¢r’œI§7œ3ŪÜ|[ï9¾–4<Êça&ô’h@Þ ‹wS/…ÑyçêÚl‚æëúVÒ>öÝ;/-¾Þ¯ŽÛÀú7e5PÁÁH`ŠU¥©)zeÈâ+%B+D…‹`ª«ƒùϧÍœøo]]Ó$›ÚõÁpLÚŒƒ½1ÐGž:_Ú'똉/áèÏÀÈ9Àà›…è÷–)“мÆlë¯Úß«o«Þ›¸” %Ów(f’‡p½1¹a÷ÓÉÁ˜¸fjaŸ§8eävð½»WeþZäv¢Ò:ˆÆüï‡×ßìš<˜CÝÆ"BÅ„|Þ³Àö=.ך¬á¤Æã§hÕôn#¡üøB24ƒmm{5“ë9¡KÍ¥9ûqgͦ6sÓ¯_Fÿ)÷ê!ÈÛ~Î{H=¼¹‹ŸÍ¯°á~=}…ŽLÉ·.ËsN9jœôÉq°HFsØ-¦õõlv²P•Çb;lǤ™ìñ-á“lžÅfÉ3x3wòVð9nk¶˜÷/±´=µ:“&êùK5ѼHªßÂíö|Å$ߘ x^„7m îáúØ»¿»äéí%^Pãí¹f9‹ + ÐÕ¼Ðuw1™ÀHáóŠ<͉¨CM6~UËzÜuÁ‘ŠA9C%ùK9ŸNúšÌÔ?Wå Ï:• e† ,ÆBkI®ßuÑäî~ã0Þq>Î8߬ô*¬.”Ã…&¥Ä62fš¤¾xϼág^G.±{Dò‚ír½:ööqw‘ÐÆ>cBb !˜ä×3„UÏ0"¦NÆêÅØM™€gšvgšD Y"Ö\jó“ŒØÑ´æj…&À\påH¡)AùdC\?¢ãË"kmüˆJñgÓ'sÿˆ ù?jªaT? 3ƒïü¹r¢ðX”¡ )‰b (b= €dâÿœ7=ôP…r‡Õ?‡õêcaP×ÿ]Ké,Öã:zUÿä?QÓÐszªfú&_G{ǺÀòXE?®E§tK῟‰ßáe{pŽ ú(oQõ–{^·G P¥$ü·;©{&3X3Ô ’€õóàõ:z:þ|˜u0ª*u\#Æ ¢lŠ$ŽF¡H™0 Žÿƒª¡Ã‘(¤/þðÄ©Á!’KB´!ADH”52,ÂÉ*D”ŒB¤HŒ@ E APÅ MD1)•Må$hïe„("ˆ þÎóýsGõvc«&+ßòr?ó‰IOþ¤_'81Å1[¡ªMNÁÁ¾éÎ$š?âu_þÀĶÌ2Å®lCáõ;\ È£}MwꔋÞö{³9ß²<¶ÓXVO^giìzf~Mïi2¢h‰…òå0¡µ9!“ Þ‰"À™v8üÒ×Z3Å©–!pcæ2{H>—3ç(@"ƒ¹õMæ_ý_Òý·Þc Bö nwç´~õ›…òŠ#8ÄaKÚu¿}Í…Qh”Wkga8v5/~˜ïZ8\ÙF.¡÷üåÐ×1‘lî8lé¡È‚ž““ì|zST^/iÔ¤<"Á 2ß’Üi,éôD¹$ŽC‚HJèŠÙ šˆ:ôx* ?ÞèØÁ´¥‚^; + z,ì(z&X†j¨wú3¾É¸kÄ3ƒ¡cð'qJR‡N1“‹ÎFDãó(î”ûú~¼'Å&¸ø&¥{}Ò‚_1êÜÂÄ`Q/$2ï G"d:œc­ëxÃø(Þó¦—ÇÁ×Tú;Öu1Æ0ƒÀÊ7ñøãî_Ÿ ?2dØD¥.oÁØñJûŒqŠ[CnÉœî™ “Љ[^<{vüød÷¨ý¦(ŠT ¼’ ‘ŠqE©ŠgçuhuÔÇS¾Ê©œRÎ;UM ”¢%Ï!©¤E¾9'šÎ@‘§é¼‰ÝÆ€–ð¡ØKâ ¡™DÕÈªï¾ææÓg7!˺»¢88¼L…‚j¢I¢àwjDÁL0ìf¶·–›ÒŒ¦ÉŠa ¼N¶Ð¢Wq.Hä:ëŠ4ÎhžDHê †¸ˆMDxPêŒELA‚£t(æ'Œiy(u0Ñ`þ)¦ãëçúº|‰Ÿ]Á]¸ØªÏ³ä„"Èßa!Y0,3–î§ãOÕ^ 9Ÿ‚€ç¡ÛË¿I3Õá!ýÙú¿M ú¸É1“æYg¹–#ÍÛ”ÈRlú)ÔMQ¸%çI3D9&©iÔÎ!ÔÇùÑ'ú p ^ŸfeQüö¢¤MTÔÎl)iݲ‹m…ª8ã²,µN÷v­)ï¼PáœzÒýèêS¥G÷‡)3Ô9‘$*(rËFGL±œóvB '×ÌPß%‰ßV~>^/¼"-g½Ý«|!A1ó>m–…cô@„:ïÛsiª4R¦Y´•)bTNóm"€L¿Ð"‘rÏ’›t‚$r$Pã‰Þ„š%‘Ÿ( Ë1Å[Í'LjgXD(%ú|µD[!“¥TA§…)-d˜¶ïÇÎiãŽöåáxáÒ)zT‘rЖ¿újÙØÖ×,Êæ% LÒÍcÝ.rú¨dšÁžLÄø»3¦eƒ;<‡ÍŸvŽI$3K ÂìkGfq¨…ºIâù‹tB)X‘$æ3E7Øš²B*(ƒ –¤ÌåþöhAõí…QÏ’ˆtK´»²8•”5»(ˆdIƒÏŰã#ëGî˜b ²ZC\Ä×lT©M"$ èòžQBÈ2_Á¨rcO†=à„C“,ì<LÕR2‰,²¯s&G¢Ì%(d'E‘]Èîðš2 ×kN9¤ŽhŒ§mÛ²Y •ó òvÓkàÏ ¥5;ÔãÔê{èA$Ž$"‹rŸùn@ÊÂdžCÝÌЪƒI$±r"Ç· s‚HC+fžd¬«¡B ´Ù•ŸaZRP²ïúð2W……„¶w6›wïyú÷å|ÐÑJž@ó€x¼Câù>ÄÍË,ÀݸªkË܋އ@æU¬E»i¾±luê—Ècì=ÇÙcÌÈóiÅ8ݸLWÂ%%Œ×S¦ ËÔØÇb²´… ȧECæ{Kæw§Šv2‚)Žg“I¨9%ĉŽJ‘Ð’â¾Ôô92‰E–n&“ 0A2ar2ž¨SÕ©µë|F"JbaŽç¨- î<¦r¤HÊ:õ±¼yàG±ÅlÝDGðn÷m_Éæ Â1JQ){ãv=†™Ž/R‰KÂh©^ûN´§Q¢ ¢{ñÇXwŘ£Âœ#~~4×ã~Oªiœ=8zÒ'׎Dgáû÷RkÆ)C_–2F®»ÇytS¬Ò"óí:ìoåÕP/`‰BöäªaÇ!Ê$™'膪(‡‰F}"c1ÆÛc8e‡•=«L[‹Ý¶,õÕ6 7£Æ¶ÙlíõõÝéãêýxöDôDKF˜²–ˆ—Q´r”]©tqÅ3ghoEàÍ‹)Ó¼tMï”iϱ☳Lk)矩û¾Ž öÌœM-²ÓR–`X…‰Û¶Ûï6ÜXqiÇî#¸D/ã>|ú7Âü¬lú© ãèf²ö®[DgâöcxfPD(æi4ºÉ<ÌÿÖ’d'yu¹Àö.°×Yl3·n›Cb»ÔBå–RæßŸáðÑ<|íz¡S·s8iØ0Ö8>|Mß ‘>gèû=§Ï‚%6‡mðJjÉ@8áDü—¤MXšdPCBÂZUÍ @šgˆ’¦¢DÝÒA†'Ù–Ôæ˜ë\GfÄD6³c N¦ÔwMq÷î)xúù7K0ÒŸiã?—„æ0k)ß1‹¨ô½NƒÅñÈ‚Zqá„IÉÅ•6œ‡‹‚ W(Hyr„w9lÑ9©V»žD()“[’¹íÞÿÊ2ÐÙ&?Åàyÿôø•ü¸zÿËÔ~šš÷YÅt{×öV¸Ê°¿ˆí©àEþá·™†Óûíýp×´3ðÐÈÇ1ÆsÓó`5¨ý×µŸŰj±ààæÃø3°uíça7¡¼f¿¬k‹—îã¨ó=åãlG¡¹ÚãžGËåú‘Å‚¶h:A;-œÞÄÍë=ææÿú=¼=}íšíË {sÛÒ.âpªºÆPã£Ù°ð+HõûÈÒþ,æH¥ß¾æ>Û}‡+°¼fáQÛ4røÏùnùi)õsù³¥ø ×ñ/8("*ð*L… ¨8àÈL‡ÓïRÓžÏc?LsŸì'ØËÉi ÖÊôjÅÃE¥Ø6^ÅùæÇ—¤T›ö0¶Õ™ŒwŽìÃ}ËNœ9šËå^ÏÇrÒÈ`&&m2?¤{„l<õ~vÊ èG@ èc…he?(tú/]ª0û¼¥ÌÔÖü¿õÿ\еZÓoa©q¶rLIÈq¹y–]c‰ïùÞRïþ¶¤ÏÊ…•”äÆjÏ+þËë¯A‡¤ßÝAx~nn8ó±ÂØp„Q Œ&!HIœ®‹ö‡ý]öãoà~œáÕD:ueh bêzÝ{þ_÷¶Ǩûñuè…ë‹ZÐJÅ[¬(ÇÛÇž²i—°›õcŒårnC¡1²c«n!8ð"†·'"ãPiRX=$ß·í»>®{wƒ# |ÂÊ/2Ï&,¼œ“œ™ƒµK‘ØÞ(?júz¾ÚGŸÉNéb¤ïçò˶¾Ü@k6Ñž:xªn»TfþÜž›q÷up6Çîì¯ïÍF»'wÑ¿ \À~Þ_dZ°–¿ç—2»û‹6«<ô§MÝÐjÌòÊY?)anÌTxëV÷Yæùs—#ûü0†ÂcÑJ®øHäò™·‰–ã¡%¥®¾ ÿó¿6S˜šþ3<Ød’í§#Ëlð;¿U:Q×VÎë¼XfÆçlˆµ“[æøÐ—OòݾνÏà %ïŽËá»ß¦Û0]اJÓzYÝŒI"Vxû°™æFçùf÷d:?ÅâXÃbëö“í¤õþºÉ¬\¬Ð²ï‘Q%-CG>u{[àԂ´"Ž‹BuÃÐù!œ£’©º„~$8#ÈÎÃWÉ[eÿ|»kˆ ƒƒˆ‡û¾wŠÿè,’2ˆ/ð‘q.  ¤(fD)‰Ô ‘DßÓ¢ Œ'ùÞËe{Ó|þ—‚è€0(”ÿÌWþú³–b(¢‚×Éx"4€À!˜7’.@¾˜àšê!€z G‡eZ)C¢•¤N S‡atF:šT8£¸©@]<%€© p, ¡a¾A9¸N­çB2dÈï?çéþ§üvöbƒcÇ#±Q*GöÄr‚’&ïï·îŸÿ ùÏ5Ÿ©ÈÛÛS«^aÔ/ѹ35.îéÕ[m¶»½é>ÞòC¼ï$»UÛh"߈Ìnf=öÖÈVŠÙzž/àÖ¦€©’øñ ÆÝ^Ãã ã®ï{Çú’Níñ0ßh÷æû8ùñÚßåÆs3 >0ß*oW½‹ªóÙÃF½õ˜ô Ÿ,ƒÅìú{Wî€ÎÞ êc›Ð&¼ô®÷Ú÷Lôæf=gDùÎý¾,'”ùe“4¤«‹-íR¦ÒÐÌÀ˜l=˜Ã|Ù5“ó­{Ys÷[j‡¯”åtIÇ ï^yÊ¥æ”L̃ôrï•õ‹M7ô\<ƒ½F,cNãÈ ¾ðø¤‡å!¤)ØB ² P‹@ˆùoîCÕßš&F¨‚‚_Ùƒpü¿0àÂh\),+J1H A@Ñÿ–~øÿñÐßê“_ñà4Õ0Ioñðä©J±‘PôïõÿÃÿ‚ÒžýD1ÿßßH.wgÿEŸï‘}ç⟴C¦0®/l‚´…:²Ù5„ž¿‹ÿ?´†¿·ÿ?iÅûßçÆdÄÈÉcÚ)«ÿýC4[tÉ]œÿÏÿ?ö‘·›~ãp‘:dÁÒWJRà%]4£æ_úSœ^a…xOúd !–p’®‹â!…oԇɗÔlþùþ3¿áþ3ýÓûÇ n R‰`Œ)”Çø›ÿÖa‚È&I?ñD¬áÍ©#ÿ«¾+k§N1´·–¶ÊÞ4¾Œ7-*m2­ G£J$rE$D²ÑÆ<"I@„Å=’c%–fFê¦Q/ÅöÏ \C–Nô^qpSé^‚"^²w…!VZdrÆSÖ4ÓhŠŽ>qf(œTO¹ßE>ñÔâ…²õo%Î1eh¨‡‘ò„qfÔšt\ãÁ˜;ÙH}8s®Él6:HÉÍ{(DY7¥Å½s\”å6t9ÆÁvŠd>ði·«œM±w‚.DOý%´#N¼o°¹4·x<ï%é9w\#1ܦQ¦tÆ›"‰²Ëw »É‘YÞø8KK}î× µÅ0Ñ*W9 ‘ œg]ô䄵ñEÒÙ²)D̦Ö–§¸³ZFgf ³Þ-¥†Wãõ–kŒaO|Åñ¬`qÐA&n;&6œ# †ÐÂ[‹×5ˆBœË.­°8öQ‘2;$A1!F;>™…À8¨Ñ;ˆ‚S  ZL¨ÂĮ(ª‰™rm¦‰hn,M’YD•XN8¬t+¨Æ1&˜¹2àØvÂÉC»¡D!"z˜{8wGVaxÏ/&©Ž>®;¯‘ù÷!ôpã“P·eL‘.BÇP8íÕMI¸&Í0WXaY1·3u»¹“ȧ# ' V´OHÞ5é–ST¨+G4»²øÓ‚ £¶ü¯n.HPóni…ÑB.Î.~§í3My‚*ˆJÄ%;€òfa%ƒÁçˆâYáÐ942ˆ|ÎRnbW“'4ÖBr%èáôâ £w4”QÇ)¶0AšIÇ»Krs âwbŽ„äŠ q$ÏŽšIv ;NªÂÎÅHÔa¦ mÍÙ£aº 2…CŠdqB;’äÉLžEY|ѸQÐ"É)]Y­ŽMœÇâ¦j P§(’(‚š £z|û>aúû,¡J…/SnGT^d8ä@¦G9"YPûd£Iˆžã¬š²E ¬àžË%g[YeD¢ÃG›ß"op}3Æ-߉Ý% 0Ì!ƒ‹ÆLî„ÎÿôÇËtÑ\ž‰wð{¾¹œÇ$¶ÇMr\a…d„F!É’ñ0 1 ðLÊ9bÇòNw+G4‚®¬ ƒ\ì6m:ȺD9¦5YtUoÖ8åÐCN#©ôƒ4|6¸HÒ•¦<މv‡I"]‡tA$[=YRu‹'t˜!\is’Qô‹‘' ÞÂðÂîWZ,ÙÇ.œ§‡¹Ö’1SeêK”Y,åÿ;ÿOõÿƒ0OXKDµO×ò&Ó9ŽÑÙÙ ´>Aä’¾ad}‚ ~£i7N³äïªwàÓÒ¦5úã]{¡mh‰ÐÆ)$Ä!èµPQW4[ÄÌ6%Å\Í [)¯•šo`¡T¤Àã˜Û ]ä vJ=T§eâuMnµ˜uÖ‡0Qç”Qª ™#î=B¢Kky²‚ Š$¿ru¿GÎóN8~Ú&”7q‰AßOä”\ZsšK,£jË-õahÓªL¤Fh‹ â Êh”@ò%"i ’’!EšmÓ”b/e9†Q°AõQ2>i“E¾ÄÌ4¸ø^ÅÅ™+c ã®öhܶ‘w­=ü%§ÑmÓ¸ã­çVS1åìpŒ½“Žá/×ïúí9öÇY,úcôÉJˆJ÷Ñý+Ó<ò‹5ÎB Ë1ðâ¢ç¬²°ÚqÒxÒ 5ö¨¸ Û‡97[ÁÓèS¸ø!DSœ]qÛ߯Þ8Ç6hDw3öd=¨:pz+4sœä÷¸ÓÃö’â—˜Nš<6×|N2l%­S¬XJ&Ê’èS&QDÈ®I¨.h¥p=<ŽèQêd‡,ÂÇ„”×D½ÉÓÔE•ÖaÜQ´u´¶od’Q•”Hæ¦(’ž‹œDÜêã¬í}Û#)ÒD´È‰”ðL¹#’“œpK´hই$.\Òð·(›²Ü²+ Ü¢pÑ¢3®Ç2ˆ'5Á=ãY„ŠøÐã„D¹­‘‚½õhhƒ¦C” ÈP"htˆzaÅW,dG·w[ê.Vu$Î`Qy¦â" Ò )츑ȇ'0~5Cç‹Ë;fnhŠ!±à‡.`RJLçV9¥\£ˆl½:G,„D“ Y¶åé¤nBìÜ5´ã›ŠD^<îÑÎUãÅ;T,¸PÈw"Ç‚œ2ŒÛ‹Ü;Šœ%‘¢w?ÕÃŽÂ8‰P!A%–tF4áTæá…¼'#JpVY…†n‰M%.äIx¶°ÈmÑ{¦#¥£0ì4—&‘¸<€ŒÒè¢$±ü[Ò‡wprkK5³º±Œ){îÎâÉÒ]VAqTaóåÀŒT@"`ºnÉœƒ@•:#IH‡7‡“N5¸±Ì²ˆ1ì¨qè¡)®ãu$p®ô‘Ê¡7Ó¯šæ¹h±DÄâgw,ƒ‰v˜JPÏ#´ÀHû&Ioy†È¡=M÷Q‡LÑ–Q°q•ÍFF«h’xïÁ÷ö} ÁøGãìrcS›99`—"Ôî&g!á< ³tžØÑø“Ly$ê"ê*ÐÌ„Ò È“Hr?™»N¥ŒÑ–‹$P7ˆ‘lÙ à‡iIÇwy½'Œ^<ÇfÉšiÔ8Sá'b;»›¤µ9U×ej'Ž >ö Î!÷š] ÚíòA;Í¢t°Æ¼qÉðùp}MOOˆþ6~DðãÙQ(‡Ë2‹‚„å郻º0$˜PL8¦Wqjƒ†ÖCíóÎê{2È9¢Î·¡ùËg{4——èHøåQEÖ #*¡PîáDäuÔ5™Mf-s¶ Ò‚ñ±eñ2Ÿ¨ÅwË¢ZžbÊÒ £M 8]é$qÈÜ—7 !ÅLj‡j{ÓºGšççÙ~ðIZ@ÐEV–> ,É×ày#&Œ3 ‡'r…o{MmEï5 ‚œLï! –VšÞNÒÚV½zIÓQ19`ì!û |äõÃÚ]“›sÅ8µÓ˜;ºô;êxïºy1øÄ ÓtÏÏm^œdgÂÉF½‘CÚCÅåœå*g0´AqNmjÚ…d$Ð' #ˆqÓÀ´D·\ƒN[–$ZAtÚ>#%Na8ðã‘°ð;›v öõ˜´8éaØéÏ~>º}˜êsÇ Jmär‚Ig<àO™Q:WãÜô¯ÖY¾v78©i´ëÅ­´¥C͈™g5bs‘l‹«'JN9ìÓ l^µvÝ&9z_*ÂŒ~ QkÁXu)S¦)ȼ)Ö&â¼uxÃ6(a2ZXýñ®>~IÑÞ¨~ا’‹¢n)¡Œ£¯dè'i0v~¢t± §#e‡y&w%(††Eáu»Çpå†a0›°×Â'Zñ¸sN˜+žQ­ÃÅ–GCA I¢ ‰$CŽI‘&?K&‘ÄáZ9rHòM¡Ý©URé¤[ʼnSŽT“qm‚.ÝD‘8Œvh¦œλœQÅèóFs:K²ô‰0ámÑÅ8Œ8‹s‰¨Ì‚[H‘ζ£›Z‡V‹},§M$\J™™ r% ’DȘ dB~Ú4 JÎàŒ:Fêç#Œ·ã‚Š,æÓ ˆ‡,±ÜÎe‘B£^ÎZÜw9Æ'™0¢iUAi9Ú"s³ë ŒP7ñû>£üéÛòÿ‘ù¹†Ñ2I0$LKê¿_üƒýÿ®’ðv ׈ûoèOô÷mýç7ƒüAÀÊÎÓùØþΛPþžÇ ¿øvóÓÏÈ1à™‹‘p4CÉ3õ¡­V¬E ‚éyøCL?\÷k^Ÿ²ÂÊë†ÜP:Œ&¶ôþéÿG5 ÖLd.Ò†»7†$»XƬ‡â Ù ŽH€h‡ÂO³‹àGžçüÐ |þcç£XýšûY³UÏÅ%íçë_rõÑÉ{â,ëœ0¦²†3”(Ê*³û3e¤0ÇóÃ8€œNYvÜŠŸßñOkÍ…þ÷¾'Î>8saŠD»7â }×lš2}½C£‡f³Ž?ë£Óþ¹Æœ#Ž8ãŽ8ã8sŽ8ãŽ8³Ž8ƒŽ8ãŽ(¢Š(ðÃŽçtÑâßK"ÛýÙ%ÕŠê› ÿ|˜5 ˜…îb5->ý†_ÒrÞ9*¢OJ?ô —"4‰ý2;ï7ïò0D¸Ó¯ÿl¦Sukd‡‡(¨Å3ÂU‘ªd™&eþP—¡8‹¢–M™¬LøNŒa„£Š‡Í”îG”{L k$SWC­8M¦ïkPÚC@²Ñ月Àþ:‡FoðÖ 2ôtaKE(ÿÝNSv"‰| ÀæíÌO—۵”·y½6œ ÈA½ûKë“ÚG÷È| R/"UÌdÂÏBåb9+S4ÿPœë[ oÏh"/Þ'ê¦@"Å0´¯˜ö`ôi´»ßÒÐâ¶©~Ó&3 oä“N­mS-D¿>õëí?Í·4¢sÄP¤BÄ@°@Ä(yÊ"fˆ¤¿ý3“2ÀRã”hÄHÿ®i¡¡ÿ†@àOž^æØÁFûxy[´Ôâû\†òagêNi|;H(tü“[íX$KpÂc&‚ŠF(’˜‚F@‚ I‚ h¢”ÁC©ËÑìãëÛ®1®¼4Ú×&á\zûVÑ2Ý%1•$“!sÆ·@ˆh!V)ø–p:¤)hQ쨔¤ˆû¥C\‡U”‚‘OÊHRu•¡ˆ¥¨œlÄ&c¾N‡ 50‹BÇs@é62ÓHÐ äœ#Œñ4¡J… ÀŸ'Àƒ²ú¯³ß’”$CÀóš[¸#„4œØ˜m‘J{“–66! 4 R­/’hˆ! ˜{!È”¤Ü#¡„‰F$ixûÄÉÖ8›ïCX8þ½jp%… †r?°ÿ‡ÏïžùÐÓià…c™P?\HñµÀ&ƒr†«Ð) ‚)h›¸ìÉ‹`ßš‡n†‹þa½ØÁƒ{áù;:çL`ÙŸý›ñq›ÔqsG+› ¯ ¸¶Œõ{ Ò,°A <¹„¾Umi2æSdEP¹6ÅYn#M•“Ý’#6(.ðÛ/lŠä[‚%°äJ4+GÁÇ#Z`—„HšH{0‚Q‡[\LKÌGlŽñHy' Ü29aÃñ8]I0]“Hr\i.kšÄ@¬ZQpÒvëÀ¬Ý$”çr$éáF™È¡wŽFñm(EHéa}E„êÔY‘Åó„4§ÇIȈ3K¢"’M³; ‰‚Qng%)¶ªî'\ɾDàøx܇£m 7Cþ!B'D<~}S÷ÿt R\C!DÎÓD9Õé°áPø9ívt$yß,qßKk\ƒ†”˜À„&=E'Z!$ X ‡;h«ãøq,É4¥#’ ±- LΚ–ŽÚ›I8€¦LÀ7iiƒƒ†¤Ûc­‹ ²(¨4s"¢ˆCb…MÿaÍÇ*ÕÁåLLy7³qÁ¡Ñµ“H¡Ø¦ÍM ƒŠÈ)»²ÜiÅ5Jlf龑7M•b0›°ä¦ã·'cp´å+$pµ(*˜ètšœˆLš'‡v :ÜiML’ÔÏ©Ç,ë)Œ­ÛSˆÂˆ#4“: uc¡Üè Õ6átQ³dŽIn>ŽB¤aÆ3 ˆm6 Dʲ b¡“’0ÌE8Œ‚±J‚ (¦” ‰0£‰áJ´9Oqa¾)ßfÀÅ‚0Ö}QäûCzušØë£ZNDàdØeCGÌ¿„% CµÙÍ_Ÿ¡o`[8eišC³E"o£3"d±~ÊØ˜~ý|?÷¦äv0­/fÌL̀Ɯ8_g»7Hhx{õÑ2òŠ0„;qéÃQ¶ÞŠhDDŸ &mÇ‹>™?!ìMùS2ŒhN\p²ojZHW$Raf’Û˜mäÖ•RL;ctd”\¼qª‚gOiN„Àã¡ë‚¨Í˜²‰äT‹5É8í¡æ7 ¹"hÒãGŒ…uHs@æÑÃ$êÖž u =i$iU¶Ê•锎da¤Û‚ÅšY9ÓDØã—dÝŽDÁ%–iÒÎeSº6£ ±ê,©‰æ²5-‡4ÃK-Ì—/^(²¬ƒ•G,°¹eA6f%ádP ®3 u¢{Ð’H0²‘",Ç„!Yf…˜E ¥ä•k'î1É,‚ÌÖ·È(ÍÐPãÑÿ²1œxŒTÓÔxvxnË[=ñfŸïÁÇ“S§œuù`ù0s1eñ¢‹‡ âDÙ6aÓ&½k.k¶¨e$Eo­æÓé»%x\x[hä£Íg ½§‚I2‘¼\@¦Ž:#\¡¬4(ã4}"[¶ëNvŽ‹„Fšj‡EèNt•¸²Í5Ú¥²QFa5F5–SK$ÑC˜a ®<õ£@츋N#Hê,¬}$²ŒÃš 0ç'ï1iÛUwˆgVgã OæˆtJ¤¥ß¥ÛåQ:KñÜWÛ}ÿuêOágºïòþ2犘êÿ‡¼ÊɈØo÷ /‡µ*œCÙSk±…÷ýG¡¸†çVAÅUEUL® SQQóQNÜé«uÔBIB’)•š$†á îá½ðØtM¬†Ì½7ºËïkéÛ1~»¨¼²;uJ zb*‰ß•Þ°ï²´¿¤¯(RÉ‘…ï…M£fÕbl™žù2Ú&m¦G##S#˜È½šââุðððððã8GqÇqÆpçqiii2dÉ“?öÇýù»e¸Lè ›6ÃnMÄB´XX?I´¬=µ×’ÚXßÚï3êòƒÓ·è×{DEz‘CüsÖÿ‘ìÓ¡“@>Ä” aD€F•sÃÃÐ~’Aø §ÁCpB|FPuìL¢êÂ$JRÌ>)èÿGû¿Ýþ¡†Ó?Ùûã±´ô»þaÍú<nÂ<,·×ë¸$JQŸ¤Ã_ÂçxŸøhÔ‡qãiŸ¤7'–‡Z¶Xño7§þ¿·?mYÁûº.mýSŒš•=íñlIhä¡§Ô"Kº°Aïmš—•;ZŒÈC 1õ}š‡OìÂäôáÓÕöñ>™UiLjüÖG¼ëÛë=ðѧÝ1ÿ;Q„.Œ¼õÆû[jZÊ{™©«„m¡÷¡bA?ëϷ΃‘ÊpgÞö5³;ýSi£I¸®+v}ûh$Ó md&UŠ' ûBWœ†ƒ,h÷e)D ¤š›Î¹É“9[&L©¹…")5Œß¡È’ÇW¹HWq {!O‚Œ¡EÌN°cÅ$^À%õà3è3áá€L{?[à'DÜB¸k³½üÂh˜Û'gfÙá€å”y ?…„ð†„bjÚ>ƒÉîlô0³“§I.tóAè]ÝúNß7«Ùvžkpõ8ŒÒÎéÚþFž’aÒ]vü)¦qµœeÌV:ɘ‚¼²þ¶N\t)úÏfëò0d”)|ÆKX"dB!rg+@ÐÒ™3ôàzŸ;×ð´=bÉóóûžÁ}¡wm¸‚Ný]œàÀ1žF?Gè9˜†ƒKÍ Š[ÚŒ5 ™5&Ý\g&± ^AÒÃ(Y¨û;k?b–R…´>@3ýôø:_¨½/M-ñ¹cl…¿Ã÷¨U&4ÆAðüߌË[¼¡Qµ¦ÕD,Ÿd;¦B )ÿ»Aè§µ$vL0nþ^£ øÓî›IŒîè‰Xlš$ŸÚÌ’’d PŽ“ÇÑøYmŸßiZ×ÔŸïÝúŸáñ>¿Çƒ¶QÔ'U;ý˜¥‰g <¡õûpèMa¡ &H‘~déï;ÓÈJ<š ,ËA­D­ÜŽ‚jäiìð8vP¡i<‡2†6(€ $‚^>d?Ï+íƒ{R‡a=3Âs}—ÄÙ’Oî²í öG!_¹’:<:„{Ò%)@Ö Øû+õN]{M²fhñoT1f©ñm&’cÌ[Y´GŸö>g£zƒï~Ñ:¢ž%ˆÄàÆ3±ÄÇ9ˆ¬Db0XÄ’E,K ‰xžzôö6Ö'Aˆ¥”n¢»Ôõdbª"_Ù*¯›Îr$Ù ƒFˆŠ "ˆ "&* &"¢™ š¢f ¢˜¨¿Gç;bàù„b˜ô›“ØJ ¼ÓRhˆ "`®ÉÎp'¯ç˜$è¶,NŒÊ‹.Å„üµàNê$¤˜"H¦™"f j"b¨* Š(¨ƒÈŠ C$/d¥ m¤·=˜ÝD•TAÃ|c1Dıülì'JðŒ™š ‰ˆ#EF"(ˆÆjÑG×®CF‰¢Ü«ÊÞäЦ)¢ª&b(" R(+é³1è>¯ßÃ嵐~w>s1QDÅDÌD@DD’ÅDQ±öç1$ÉTRQN† ¤Ô€NÈ|öuÌM0U^àÄD•QîÍ‹lé ØÑSøó‰™ôDžÈ{ŽìÉá$DAQ{ƒ³II4D2QÉŒq*ª(†ÇèÏk`@†L@ÌÙè5ªÍ–nHL]„dl.¿KK 16 è$×"Š”2rbªUÛŠ•%Kžk”ûn€œYOY s±žMŠè«³[#®crÍúºX4ÙºÈ,c3ik bfi¦8žûΣ¬¾†9 Î)ƒðå{8põl¿g3«$üï9ôì  ¥­~.JP´¶‹A b# U 4(¯óÝ„JD(R‰-D± ª(%oî)”ˆh‰€‚á¨ðyÃ…:(ª=@ùá ž¬&¢k¼µ)‚ˆ‰i ªˆ’""`&("Ñaô’f@A‹b©*!ˆˆ=â#LÁ%$ç£ó™IúàÑ/³Óá0S0DD‘QAÄBC3DD“Q HIû(É “]òR„=Î/”èø…ƒØ{X†‚"b$½—‰ÉáÌœ9ðb‰ÈÔÊ·ò0ð‚¢ ˆ ‚ ˜!Š’ˆ„€¢š"H˜(¢ ¤Ä_p^€t¨|B9è“E@QATD”3M%7œ0DUt\Jûðü‡_ $‚b"¢ ‚V‰J$šƒÑŒC U·B8:î52ÃHDQA0@ÐC4‡£8+cF#A^‰]Ò;n-ˆf¢¢iš"(™‚Jˆ÷*ˆŠ(ˆŠ´^P¯B|S‰åØu7|ÊŸi§‘š÷0KDÁIDMŽ°È·Åƒ†ÇšICÖìîjm…DE4´QgI‰ TE8»aWÛÓÎIÖÓ±Á{›DE=‹'ݓɒ‹µK/*äŒD1¢&5QQA14@íx޵yÅ€[÷J»¼›óBƶöÉlCgc0"÷)Õ,{´ÀëÙŸV§/ wðÐôôTBê–ÆˆŒJR•"'t}FzÔÅ”L”@L¤M!Gäɉ‚ÎíMl¤6øüµ©D2^'zÉ ¦((˜ ˆhf™ˆ ˜)‰‰*šw’`  S$¾WhˆD< Ünw13Æ DËoíÉ–‚f8?#Ø<%zA¡KÙp)‚!šŠ("H¦pbd¢(ŒCêK”£ÂR•”§ÖÐc³™‘À7ÌÇd– Š&`Š HùeTé,xjcDâCB@î%àï°nŠ"ˆÅDTQˆACCÄœê î@9#Ãu ª"ZŠ "/²ÕTDïÞà;œ ‚àÁØ{°Î‡pU‘FÅ íB±b£i¶þ={mÉÍöï 2 Dlh£}t±ú|<<”óœ!NæÆˆŒdʈ'jÌœÓÇ¿å÷{ÔޞÁÂ÷=Ë1=Ù·|ÁÃ>8nrï˜& νôkÉQìQ;3¹Â ;XA1 Š£@ÉÞââ"wSnzmÚgnŒ › ÊÊ×,` L0qvÃÒaÉêÀ›Èvöê»p|ŽÈÞ`‰ØÕ¢Å9iZ‹HdÙÆ dhˆQF*@R‰eŠK;hˆbgÐðÑÀ±†m?áöctÌXÄb5¢¡‚>«}°»Ž˜ b†ß¦°4,æÝƒyí­Ç}¢ˆìTM“ÜûŽ 6Gr‰E% s7úå*nln2"®ì(‚ÄY±SƒFl;ˆŒWøåÉJxã[‰°‚±ŽÃTb}G)ÖæÆÑAùõ‘œ‰ÉMÌ;°Ãb°ì”ŠEW7.°Ì¾/ë³JQ- ¬°T}ŽÇמ ný6ýÁ: ¾Û3¤¥0~‰Ã 0Q Ý+aª\l"/½*" F{XÓܸdÂÞøTHÍ´—Ìç­l14ÂÏD£ »PÀJý¸QCà4á¤7SÁ†L^±Èdñ Blùº9gÍCi©q‘f'¡¯bÉ ïyž„SU<ü1Ô(Y´µ•”èø]Æh&J†hšo$шÎ3n—HF(šh'† °Q gÉÏ¿ÐĨ)© "jKÄŠ2F†™˜–(óJ´-cxÌ?‡ÉÛcnbY-gqbbvbÖ”­‹vjhfÅΙDõ0;'}ç3 ΂1ÞÎ÷&Ø¢[Qa‹Kg«F<[¢ÞžL¨ƒ±hÇÜeØúf ÊTX#±Na¤ðЦs|_¸h–ê#'(bd^Z„ÛÆcìï:õ¤‡lúÍ–ËJJ–Áˆ,P¢KHÕ¢ÒQ£Ñ"4¢Æ­z™oÆÆÛ +¡©°›cR¦³PÏ`ö ‚bÉn+¬ê,€®æÑóch„ùóL;A|qµ¥YˆLJ’ãqYTE, †,DŠäXL¼´ìât!‰rÓ fŒmÊ·Ý“=¬Ø¡Sù£ñ*LŠÈv¶¢á®²9°Äïñéû»ÐRs‘ BÃa¬¨1Èf8— Ž$œL‹KKUcR*!EY[-SŠØŒÄ›$c9´DưAT´¿–iL,±Œ*"ŒV}‰¾‰š"m)ê{YïuÀñÀ”e›ŽÙ“’†Õ¶Iæ99‰qAƒ-J‚ºw# *ŨòAÏýr¥š}’‡0Ãîr;êNÔÚ|Èmèx'4©g’Ê“Ù(†å(±70ÜtO#7ÏS$öE=‡QcôacÍãzDvâδ–Vt!z¤ª|Ò¢‰€œ÷ÖÓ¹Nµ.& ØísR€šR롤ÉÇ*\XÐ[¦{‹G0-/"cx³ä)äÎòŽ&(‚ÁŒÍ‹`Q,µ`  [[eàð]>ÔÐÞðs[úúÖg&ÂÄ4´£Â¡‚¼™bI¦¬T’UË”Q‹ðN9tzKj ÏéÄh±¿²ÙTcÿL¡<1:袽ÑÑ<ŸØaGÓáûD#Â<‚éÉ—Hü¼DZBF| ‡4¸-4¸Ä!É[d$Ö %¬¦¥É=¿[éí„§<‡ ?º•-ãŽ$‘èH˜Üc ¡2ã‡r ö°ÄÑŽþ„5øpÅø÷è1¨v&-ƒOnpØ¢ÚZ–D¢(ÒQJ*U • h˜ÅŠ˜ŒmjŒF1šÓ‚6šÊR˜³”…©°r$N‚Ý7&è¶ÀòJz†?ª?Œ õ`®Û![ø¬äVbCÀ#øBAÙa3z%Fâ#H=`aãßšqà÷Ÿ8×ËØôà˪c3VYèXXò{9P¢2uB§Bœ%ˆLfÚ sI_Gd7Ô*¦ôúë¡aܲŠ"‰Ó{ŒQ¥(‡m©‚VS—&ADi¦¸º0¥ü‚WÔöŸûz¿ÏôÞÜÕî?5H>Åfý—K "˜|T(A"O'Ä£›fÊAújÁU è¶Æ*E9é"NÔ(½ug¸æù[RÌ6 òBùþ<¿ppò¹b ÍŸ¼4¡órùæô]¼ÆŸšÄ`/N1œáQ"ÐÞ‚07…Ṳ́Aó°³çùù÷káøö{ò‰Ù„ná(Ĉ‡Ýõ`YªŠbг& ¶å»SUR&F(âIlm>‰”8¡ŒY’] Â+ÓòûÆ”øp˜?‡FtéÝð!ýÞ†¤;ÍMƒî4¤ˆ[wõ“´ŠTD[^×îXæe6š#‹2µeÊ8€r¦\´æ®Qp>ÙNQÀ´WšS@ø°Y& ×"yf—‹t‘QÛ4ã†L¿&Ïw$’É9¡±¼—øª ,Ä]r4qÔc”(M²qøv™:øz;Ê8Œj › ±aÚ) *DˆqËMÙ¤ á"´}ṟ[]äÖ‘ƒÁŠÎúZ…`¸É7Š×)j+™ìãzÌžæ³éÒ ž½!Î(qn»ôJF „ôW5:"t‹±:xÒyQ+G•…N¦žk vÞ6¤©óÊi„=îvL‘7F‹KË£2v9©ÔÐÉ¥WjââœPòØùZ‹Š$²énÞáëh0â‰X¤žÜ7«¹HäqšB*ÈF^¬EðžG9gA!òÂN2„ù¦¸ùnT]ßD7A7"¤Úk.,¦ŸG(…8"á܃1Y…Kñ4>IL›A椡ñIièê–¡Ñ*K¼¨qèÖ¸2tT"̶µŒ¦Ë{~F˜YŽø9Ö<éu¦p«Eí¥J32Í]©¢<(˜†C»yᓞ5Ì´’\ëE–VH±@¹4Û.{žÀy“&¨Ý4«¼Œ(ƒ;D!É ¹"îK†”jëO¢¢L”.6œs®žª„j’ ÊÜ,£t¢bH6Jôw2HvNlÁ…c9¯5¤Y%5˜cKa$M¹ ã¬kgæªÝUÐiYzHSŽÒn‘„³¶‹’‹‚Ü©‚œÒYÇ3/e)yíSÇev´vÞ ‡ì99„päºDÙÒ܇)3¼i‚´I$Ò(àŽÍ¾+sJî7:h¬(âMCÍPý™%p&$³‘byˆ‚K0É‚N(ª ¥l§Ud;“¼ê‰HM´æôhrK âºMåbí´k®†~Ýd9ÏÚ÷´$f´ÓSX»-SÔl.ƒ9ÌŒ™%°Ñ^ºzßOSW0ÿ ™¹¤Àœé!Ù2LuggË‹ôaEºM^ÙÝ(ýh¯ÏóOº„ µÛlɶJ‚»ÝT4Ѭܖ¯‡¾ÔJky¨õñ$P D É„ RL¬DJ;vwr朣@®Ïìò¼5šYosfÒ»é]ïg P㦳¥ì>ŠÙ# È‹|9ReMlÂ1ËÜkh$mÁÃj%Èv$›¬©Ð&ÈÄÐí4;MKK BÒÒÒÒÒÒÓVk‹‹‹‚âãÃÃÃÃŽ8Ó„qÇqÅQE‡Ÿ³ú@îéSh,Îw6þx!tøo딄’­!¦X?Bõ|¿w›òsùMä4vwiÐä+áÚáh B!)~ì!Emksþ¼?a“‚~kÈï< ЏtᮟJÀ«*°’?@óÑO›{¨SHÂî}=Ã~?ëüŸ þÁ†}ûí=ÞÇ›g¬ÛÝø0V~ŸU¡Y4¥ÿB`M™§$ñ[û³/Ôg}¾°Ãûvù¸Zî¼á˜ýt©ˆgS¯ç»è²ë,&< MÖÝÄ À5=Ew w/öŸsï³ÌNÌùÉÁ=$ÀC/¿ ÒE3±ÃAÑÇdî#æ”™{l+cÍ‘ûS’ì‚nUy…ŠQõëŒ&ó¼ËfUrô~\‚ ¡ÎE%‰ƒ¤åTõï>YŒcòÏ}$!ëa__~@>öCÜ­(D{ H1$…èÁˆ(s“' ùûc$=)ïIì2¯‚Q7’‡Žƒ'8«fCQ9™0u…:@E¼Æî°J1½kú›ƒ)7ùósŸØlÍXfì%ånï»oôs|—ODâôøúðÎþÏnp"Zå/\äLãI5µSbT=›Ÿ’óX¤vÝ?T ³ûÕûüD?)+£„tÓ„HC*lzåñJ5b†¿ÔþÓqBÜíó:A!¾ýýG[[Xû°?IGR"Y”ƒ‡äwªÉ÷ÌØÐƒN? žu8E V eÃ0,gAµãxæƒxzÓ£YLúî†ÏÛ÷·­þÀÍ `,ÖÄ^ÂO¥ú"ì"Çgb¢7›Îƒ:¾1÷ÉÏ>6ûØÔ°¤ðŒå{Ìý"˜ý¦3qÜnÈý?; ÈP,oÇê¼/‹!’^ý›8¡@ÆO” üOüÿ-äÛR¢†ÐÌ͉ðƒ`‡‰¨ÉDmmØÆA´X‚bhˆ+BPºBŽð1ÂHƒc%1'– Ö'XjS6A "RÑ(Qb#–æÁs’(ÝçIéA‰éÍÓ¬ID¦!ÐÒEDANÆIÖ\cA, Q°´h4Õ)”-PÅ:‚RZtAzé¸É«"@m¦H—g Ë‘ÃcLÁLHG :˜Ã2&Î)¬= Û øz=r^ÉêÆdÖ#„ðÍ'ŒÐDÃܘ¢Z8ÌFšt¦o<{âqú}Þý´¾‰Ûc6 E2QQë‰ÀåC4DNÇb†÷œv-FÐoL)õãÈSǨZqŒlfb]b ¡1ˆ "Q¨(¢;8A¦j ÌaÒápµDPSY¸`i.À¦Ñ1˜ ZZ#´­hQ[±±)d¥Õ(¢[BÒøÃº­ªŠÔ•F‚”EKciDFÒ×1˜˭iˆ14G.r,Ä ‰¼¸$Æò8%P\ŒídÂÆ5 g7#`Àz¬Äe ¹ÛñˆJÁƒ8ÿ¯\&d` †( VhüFBÉf $É™$€7H~]çÄô[©ê{K)J–3ÞqˆÓþ*,Pȸ9ÏEöØùB•ÿêsÓ)za¥Q^¿’ é½›Bgœ‡==.®ÉÓ׫/G<™t¤ð†©ž¸W®èHÃ"«ßúIƒø¬»NG¯ÞíBóàIóÃÈã|YÇÙG£´\´ž‘œ9§$÷žiáÏÄ#ËÒ²;œ#Ûd!;’JîceÉ#ÜûØq¦,~$~F œ6 d ˜lÁ+ŠW±¦½ž=÷‚C•¸©*Òëkó· Ååš4-.&m,c¸ Ÿ¤¡èxíó«P×§™»¤KDm²Î0`ÄᙥµŠÄãlHŒSÁ mœói…ðŸIâoáÓ±í7<á¹¾OõÎuŽ™>sPÑ“Ã87 %íƒvâŠ!ñfm‹ 3iìLa^±‡‡xDP/馇öAw­úôÂKeo!ÎøÄŽÄ/·,Ûë`ÐÓÅ´ÊÒÉks´ŒÑ+3DL™[iy_Äßê~e)@ï}QBqÞz`’ Ç|œJWï‡Ún¶’ ÿ=,ü4¦?·»}?jCß®oagÀ¥ 1c‘9¸dÁ`ÚKdÆl† £ÁQ ‚(6ci)µ4l‘áÀå~,‚œz!ÜŸçë 4üYPšˆÔ!6ŸÃ“ûâ‰L¡o2Ù²ÂÈnýé®aº$^Y£¦‡l.D7$ÖÖQsAu¯S¿ŸˆˆÍzFDE䵂‚>R¢³Ïc r‰ÅFsJefãF¡¿ÖÑI¡ä²†“ØNžD4oJ2(,tY^„hndô záÁL6>Pù<§Æ©Ôø((£-¬)eQ 6QQQ`Ê%Š–·ð#Ãøð—Â{õqE,â“ÈöáßüÇ(&¬ ³¦î;lT΄ä‚!PÇ1É“àMõ‘JX¬­Q’*¶°³´Fe$ã¦ó× ±æ†æŠšhÇ Née¥ù Òbc ”ÜëZŽa‰(ÀL‡IH3¼]c„ïs+r¶Mq¥ w1êÞ |ÈàåùþjYüË(ŠQ ÑZ%bƒÄÎ6Ñ¢#‚ˆœY­ƒDS¬›gbvƬÌhˆµT²”£[gƒÚŸIisFÆÃ¼ifãL΄˜¢¬‚$)7ì!ªnÖ*x]ˆÛŽ$ðœ;Ÿ<8͸BQ$QýžöŒ (ÔAEÀì>5o,î«5*dT”ÕÕª)òÑÙÅ‹8“X–Áz-z= 1À®÷ n¶)¯Fa£M“òLjÓ»!Á7&g’ “I$Ësx‚ѦÔ*ŠâK¹}ØdæÑŒDAÊv’fæÄ\”lϾà2҉ȟÍ>;͜ꡙ´Ð¸æ1G cDdÁá‹á} \F¬Pe´‰AQ±°hÒŠ"6Å"£TlÑÁ’h9¥NÂ.Âféekäl”Ф&A*M(fQ¨ÂzÈLvÛ|Ä=Ü ‘ä°r—c·ãi0ÁªÔ,Ã2Â¥Ö½åæá‡g²ß§ ƒ>`¿Ålú Õ‹øný‘Ž~‘ËýÁ÷t|,XÈIKœJæò\õñ’× ?&Σ ,ú~£#‡Ñ:7¦ ŽÅPŒ¦·ÌD2ƒ%½™„5a ĶŋƒDhÆÑ˜,f ³”±r FœX±‚6"„" £75£G,”³GFúaØÃpØ¢‚þd½–ßÇíIS_Á'N‰rglÓÔp¿¯€kEO[[YüzúagÄÝ…‹LL­‹¼#r ×|Î#! ‘ŠjÊv¤¡¸ÓEmfŸQÆ%8(b Y¸•t–`݃/"aE. ¨‚é+=ËpaCQ9ìaOcsØùÆäƒðh%ªÒ¥+FŠÖ…J2‚•(•“’™žÖÏ\¥;îoë´×„Ô@h~‚ûœNXübaÛT-mƒôÐczîÚ;¡ØïÛÞɈ¢K“¤4ÕeÛ&,N;á…Ù^ÿ ü~*p~ŽßEFÖWäôæ 4‹"ÿŽB rÑjÄIN Ba%XSØåÔãÀì}YåV\:êð:›çpw)Ûpø9 *ˆˆAŠEbŠ2<™ ;&³±Û²nSé§ïã¿eÙCI~I'˜äÉLLºNâG®¤vb²I4ãúrÉjSx‰§zœÓ_¬rL êùü5Æ€ø!¥1¢üéƒêfü1Ú|±‚*ݦΠÔU½LJ†ÝV¹á-b“Çaä&>Àx~zü0íÜ6óµ˜˜Š– ™"ðÁ€èÖ!醦…5ä¾75=Óq8_sƒZ“f¶¬áœ‡,@µ‚ æ’­Ê$Ax¤™GÉ×G…Gôù÷N‚°‚B?ˆŸ ¯è-¡!5Ó } §‘S2BvÒŒó2‚)kš‡sSó#áVã¦ò›ÄÚƒ p‘(ÐÝ›–ÆNÃy±Øø{䪂”© $¦b™ ˆ 7t,JN§£à岫éǘÉ‚qÙÔVOï¿O¬aðôþ=9%ùƒg…ž0¿®’}Áߨù/Bh†¨óð²ì)ªˆ$Üx4³ñ°8߇ӥŸüVµo©fâNB‰Dω­ðFq/2ùå}7¡—ƒ&æŒíˆ-YP#¶Ïljf+þßû€o ì~Á¸tó|ÏŸ^þžiõó¯\­í'&#H”%pýˇ LxF}¢µ/–®z1éá<ÖVbifaöÈv÷zÍ}ù7gb|9|¥û ±ÎU¤chD™Ž<; ÜßÔ!J¢*"ª.Ÿ·îwp÷ïs¦ö{þÝÇLdA½‰ƒzc0Ü9ÝÔέ¦<þ¿O§×?ÆåÑëvITŠ“æÉ ™ñóì9KLùf@õUEg4¬G^Ýõ´MéJȤ…b(ΘTNßÉðª9‘ú3AoÓìö ý_Éú~ÕiZÑ¥¢6Ð>³tÿ¦ÄGÀûX ì@>ÀC%ð zò^¸œ±Ö},Â~T÷•‚ˆ*¢@¤ˆbZ"šRšB$†˜†š"/Á´ÐPE¶¨ˆŠ)¦ˆ˜„¤& † ÖƒcDIHPÐRD‘m‰™¥ b¦!‚)hh(Hˆ†ˆ–¢(")$‚&b¦fhh š( ±Z Ähc9 qŒ‘$CC’Š(Š ‚1ÄÆƒ4ÂTÑVÎ'aÁ” L@ÄS ÄÎ0h0Nm¢²`œÛÖ,T›bf61hŒ˜ÆÆÄÛб‰l0cöqqÍ‚Á1‚5ŠB4÷xñናmš,˜œm©Z/õ£h]KA³ûçïž8òÑ”â#F P`­£8¬f1‰'8“8¨sE1EˆRªŠ)E‚ a[-ÚØPH-‹b‹iÖtØœÆ"M¡BJ ÚX ¡FQOôv0…•®ÃFÍ­äÍno²…‡ fQL8Ÿ¬w=ÿª|3a4o9å,TR ŒTHR@kcfR 8¢‚$¦¨*¢‰h( Ä¦1ˆ $¢‚H¡Ö’ g%DI,D¥$4TLÓT4SDhc8Æ1ˆœ™ª3±‰ÆÉNÚ­%¬ÅƒA1¦ÆÌA°ŒKKFÄF¢2ˆŒJ,ŠZŽ1T`ÑÄç,Á¢tãÑÆÔ˜-3¢"ŒFqiÚ†cw¦gcB›wØÝÿB¢2Ú!L14EÎ÷µ­ÈÌLI‹RiÔhk0ÀZ1 lر‚b (u2VQh0Ó%F-FÉ¡­"± ‹˜6v“Ëc-$ØØÆÅ$ %œX6 Zcf3‰‹ˆˆ‚šmˆÆ"y'„͆…JMf–Ú\°Š$(Z\ŠÜ6¢b¡¥«Y‰Šeªƒ‘,ì²±šªMÖbˆ¬BÓ­ŒD…£—‘–$±“E‚ε3&'AAJQÄ„T&"-—‘ˆ¥Ô@RÄ3 DILKgtiƒF#F6­Á ØhpF‚!bˆ Õ%bæLp˜Ø ¶*xp8pˆ&"‚Ð&IbÄÔÂ[(ˆ”ch’ÔJ†Î"q«N¶uDã-“¢3[A¢%± ”XÖÚˆ4Di™Šd¡žÈ83A §E¶iÓˆ,aÅ0a.pÏ#Dj ˆ±ƒQD3›3µ´hÓŠ˜Ö Œ˜‚«Q X‰˜“XØÑ8ÚF#V“F1ƒNžO)ŽpŽM±8ŒTš¶)‹FbââˆËu(R…¸©›(èí‹t ˜¸ØhfbÃJ!Lb—0®â´6´JR”)†€¢‰¶—XYµ™1•D¢K1b¦1‹,ÆÒá)£5¢4š!‹26f–j8ÆÅÆÇ×ke&cŠ\•q‡L#’Ó6ºSZ&42ˆŠÈ‘'vNì;ޝ&]¦½,ã‡=¥ãŸIÚȆ¶QXéµÓi¿q¼Æbàjl”*•'„¢UUiìŠI?>Üžáþ»ê >%Ë(ü'÷ÒG¥–QÛçèÂö•ýýM—áᣎs ôrÏOÃã·‘ø‹Olq†YdÓˆ‰ß15õMk—É™Çu…ÂËc=njÜ+‹ ²Àƒ6ÏË(±ß4ðÂÇ!YõIéã$CÖFS™iWžþ<ˆ^oÍPjtþdÿÖüoÎÞÄõaf†–FDÌf‡(Ð,g£‰ŒÞv[Y³•ß’e´Íð-W¹`^CŹ0‘‰Ð¬œŒˆ¼ö¹ãÒŒ_/ÃzŒ'Û Fõü0ƒ(ô“Îú}^š´ÍÊ~B’>ôª³½Õ³-è{:îúxááã>¾²^ ûǼÞúç›Õ¬ò"\ÞøÂ=¢Ðïp9=-ATx8êχ_ÓÉ6I#ÃÜ=Ÿ ð>!&oìc±'m¦b&X dÆ&Üôwó£[œ”À´O¦ý½¼óòœ³¨K0õYžgžá…ð ðcš¤÷Ø;Ï$’MÐIè(4ò›PÃ&—vxTú\˜¥¬7Òׄ†Äzº›ÓÒÝ•Q)‹WdXa…"4üÖï¾42Ÿç>ÉÆpŽ8ãŽ8ã88ã‹KKMŒ×ÅÅÅÅŤɓ&L¹¶6_«)3ltáš%£Tsnr­²Ã¼àÀ™)€ÅŒG’#ŸªE.ƒšäô£Ä… ‡X‚lwÂ` åú{þoËúòo³ãí£É™Ÿ«ì;n&µSÚÍpMbÛ&÷`4›²î…›Ìf©Ê9®tf=‹¢ëã×p=ˆùé >!ÆSX.ENôx>¯¢ëÚhë¯áÉ×úL‡ºš t›öÙ4ɲ}Y>G~}Šå¯6þIÓÁ[w†`u©£rÔBb !ÅÌìÖvÔ¯ä%}ʈ#»RH«Îh¡„?dlDI2FM«ŒzÇ÷ìdU<îd`˜ƒýa}eÏNôRnú,åŸ`› Ä–dþ]ƒ6Ñ6lÙf ®cîìwfŠD*B6!´>ïxã‚ÉéÂr2… m£©Šb‚¡¨œÁµpžRñƘøï‚t¦4Á´£dZ,]5ÌÐÔA ”[h"(”(Ëei¥Pn¨Vˆ4E¢$¢´¥†,˜ÂLU$VµbLG$Ç3£`²èƒ›’qˆ‚׳Ä}žy>ê Q< ÆØ’3¢$£L”¡Š{w…†ôÌ7¡©éÙ)C ¡†aEÙ(㊔£ºJ†AÊa¬ìš›l&[ ¨ÌÇ,DEÈØ[% ý”g*0´F­ÇÚ<‰-…°cl‘Ø1…)hÔP´”S6ØÄM±°záÓ™‚#I§Zc¦Ã$Dœ‡Ìb9»<Π‹Ã;†t¶Á¡T*Z%£„mF ”ˆ†Â¤¢k1f±,ÌUÇ'ÌLâ“ÑóØ>’f¢f‘=Â’h÷ÕÔxÖ° ØJ iš%ÀÃëŽ>™¨añÒ¶ˆ”l@øm¹¾2X¶f䌨†ZE:6ÚìÁ#¿·ÙëÀè'Ç]Ñež­Á42FÎx'zÙQÚG³QÁö‹k¾RÙ[±·áÉÈy´P?NÍ3\g Ö‹w£ªƒ]¸–á&S~3ã!+´âû΋«ÐÆ$º4ÂOŸ`y8÷ús1äq ‚§†HØDKF%T3 ȣŴ0Bà”¤£% Pi«qQ07 RéÔU@MTdˆ%bRÁ˜Òˆc V¸…E(Y¢* ¶6™#4cm§"³ ×åCå=g»] …Ÿâôã„xcQ>³ŸDº1ƒ,DÕ4­2Tñ±iO sm–á ”ðx;XzÏdÌKa‘• š› ™¢¤"(f£‡‡c˜ºGHÁÎyä¼á&’1bM(Š~×쳋<úcä­2¢=Hm(PÈtFÂ…±)Šj7JJ ÅKŽLh*%i˃šh%°ê"ždŒŠ"µcŒÛƒh×]’j–RS6â• ÐD¥  ÛœÅÃbŠnÏ":uç s;š4:Ä”˜ŽZy 0ÖÖ¨"^&ïÐDïix 8™`†Çzyý;½¯I%p‰„ ŽæþñŽ™ ¯ÂÑÇ<‡dQÚX±¤Vu-Ò+$œÁË¢ü­8Ò7eÔ[˜Põ4Wø™L># ³Ã±i&_¶LxKÁãÉÀa¶‹XSIƒã”@ø[ÏEë“ááéŠÑí¹h¡ G²H¢q¡s=ãÍ8Ší}É"Q·#–Gywég–x¨sÉ¥DÝ—²Aè½qåÑ/^#‹! Dn]ׄ óàÇú žý>z"5½‡ÝŽ]­åógJ‹,ŠHâxHMGÒOMæç…g„;/‚rÔÓ‡„ò_g†¢ºozË*â ·SE„Íñwmµãîñãä•{ëfd—áàîÈÔ{4ÔZ<²Šy,ZyÝ…—qŽ=œ9+¤¡8ãœÎK@™Ì$††Vê䲩°ß`éºÚ2_²Ig™2`ä’8è»(“Ù,¥¨ó\qr;“ɳƳÜòjÂÞ‹¸C ðé/ ’JšY¯#¿emg†¸[ðãñ°cQ˜ê(£º(¯4¶§œR½h:œ–-ý**™CI醩<F[-ƒÒݶܻgÊ&¸{™wO™÷EððsÈi»&F«9C–x ª“M3r´sO 8ƒ ±H§Ž’„)¼¢D+g<ókS.<£"o¨Ó áEÉè™Åé~Ìâ0Ìã&TIPzMžžíœ ƒGvDcyþ²‹?“ágx{öÇ¡ t;b(ŠXï0Lt?‡éð¦lÇ1@J!Xç¬Ÿ¥ȪB È!¿‡£Ã7L-oÏG¶«j‚¶„ƨ‡i.FÖ|ZÂÈM8¦f÷Íž[èñDoÊ–#Üb?=ÒìÓÇ<,EGù:††ãÀ3à|voáÝf$ ¦Šb† †H†Hˆˆ‰ˆ¢D&I"Å0î ÁüóðüÓ[M ý·ïÌ)¿ñn4ÙDÇó_ .‘ãQ'¡ŸJÄQ –¬ùé¸IG‡Û³‘†K3¤$;OˆÝ˨¨T©˜ÆÖfiÛŒ6†ÖÉ LCh˜¶N±øæÔ®Á=’ñ³&ù6„Ò6µÅ6LÜ¢ˆû:«aíí‡ÌNOcGƒå‹úüû…âb`Š& ‚!‚"$!PÚÛ¸(†`pòÆü-cY€Û}âiH‚…w”i_Ínÿ0¬™Êèè0¢Ù–ýiˆ(ÓÂHö k$ÚC…ŠÌÏZ…L¥É7¦ËtȵÊ]<Û3^ ¾ˆµ3!ó¡žX”jd!àdšÄIU'ï-¼gz “&hÅ1YYëïÇa<8>îl|9"¢ÃjPF$ÄÔ5AO£‘ð'¼<#v¯¡ô¢ÕŸ­• òf(¾i?ßÌ£+ïÙúª|4õ75Ñ&&Ì=,¢ÕŽ4Wìöàñbž84rwÚ‡„(oB°§›*x\kŸŠÉ¨fÁ8°qÁ+9Êy ÓqW â¬`RÒe  @ÆUß] L†ª¨ˆˆ’jHŠ Äë·g]ŽCÓ¬Ø#Šú®dòW´$HšŸ ýRh’•´xi¿ç6ŠÃ‡†Ãâ5Ör,FžŸ ¿Ìkë%;wbR.ºtšŠ,Ô³\Ã"¤žhù,¨0·&L@Ú°@圙\À’$** ¨í"d‹á¤LÄÈÕÓkJº4 „IQÑLÐTDEàá?œ|¢n`úòJ¤Ÿ…hùö$cÌJèt_²aW‘Øz×D±-õØ\'´Y1n×%8Biƒ,^ƒØ¼®'ÔͲ]qåž~zk~Ó}˜øLŸÓ 70+>ý=ÃÃ/SÚ‚G—„Ýc†íŽ;ÎS®5#ÔÜv=0C4TÍI1HDĵDD11'ÚŸÔŽëéME mµ?…Ÿƒz}ÑÎ,1Ÿ‚v‘4x4³ûEµ2€»Æ˜Å›†Æ 'ä‡ÎBO*avÿ%ÖµŽM ¯Ó¾ò©Ùd½þvÔ7ïôë#†œv!ž«–}»”“42f`¥;ì@zH;ét3»ZÂyý¿†žÎÿ.Í>«¦AÕP¨=™'Ø?‚OSjQžyç­Ò )õˆ" ¹GH)*!âûeúЂ?ˆø§ ò ¦šˆ¦(ˆ"H¥¢™’b(*’`¡‰ªJ˜ðÆ (©&1dˆ¤) ¤"$„˜‚& ™‰¦š Š8šK†ÛNÆ#maµ–q£1N b‹`ÃÆ'E‡³’“.&ÐbÙ,[‰‰±´Ú)É™ ¬b#Æ6b¨Ó˜ÒhÙ'Fv!Šž”³ -”­iJü½¹ÜÏM¸€©J!l¬£j™·½8çéôßdíôøâjäŸßÂË«›¡UzÁôGÑ Ù îã HDl(­›`ÑBœDË‹• ˆ *"%”lj•FXËš,Ø£ ’'%Fsˆ±‰TcV&-¨J%-¥•%ˆYßP¢#‰¸u¿~»çqtY\}þÖ}È=èm¢ 4)vÑ[)4WsšÎˆHÜH“(ûôþüÇDü3|àæSÈœuE|=|oŽˆ œ?'1´ýPätG'ßç~û×fè<Š¡Ñ믅I+{´ê#ãáã&’÷àöKÒÈ =‰¿ÈùüVÝ} `f1(o´Yå8~‡ü>Žôç”üçŒ×ŽÂü4K®¼Ã8‚ï~k2d|~øÞ 8EÕ¼<õ$ys:zé¥ÄÜAR¢¡yÐÉJ >S_N÷8çh¼íö}ô!£Q±w]垘[|_‘DÒŸi8€‰…gîÛñh’H¢”¢H–hšˆb– –ª(&bŠ ªˆ¢Qˆ¢ƒDwhúö;“Ï“ÇG©ƒ×áPòÐ ¦ÒÄxÞ²B!!É%yáE¡0…úÑ£GðáQ"©«Ë$r{~"ÒD‹ `P¤‹ÇÑKk—ÁF˜g ÔÎ" &"H šŠˆ*‰ %˜& ` ‚)Љ˜"Jš&¥¨b` ¹œQ ¶ „~|÷ðôÞ8üi™?_u7]9]Œ2qàñPcw:áì\½ŒÚn ˆ‚´ÄÄA1Q1“M3ÑQ#PKÑLQ4LKE4ÑE5‰0A%89ï9ßAIÁœµÄš »ø«2F‘}lpÚyLÂAá»·—žÃÆú•å2J)B>•6Xs6íÆWˆáÃtá‹Df5”ÀXn!CIASŽÝ÷NžÞ'u™3< vÜq“`xœ(N(äâÑqMEQeÆ"IîâHͼ¤pêštŽkE?ùÊ*}—ò+‰ðððyÃÍ$”Zðvr<<;‹BÏJ•Þ8þL{#û+ 2¤£{ׄ]zÔ#ÄF=ž¿W†ÁÎdž¯þ_< ñæAH=—µ–Y>zÖQÈ“á…9|dCH¤ç²IN9 ¹Ä=Ý9#¡é¡¶0ëõ\ ð‘_Õ>y¢(¡1Ft5 ìÂ1äܬ‹¢qÉ*ŠñH,  Ácôì6ù{ë{é>úl Ï£×óÑÅLJ’f9Aa´âé1¸ƒMʘ±Ü÷”#^¬òEçg„ááFI~Â’|=<‚ìA&YÁÑàîx<Äð&åãåûrxD`Á£b¢ˆ(ôs±Û¹JvØí¯•äA–DÕXäŽY28’Iºsð²ˆlW˜ÂH”d§‚Р£óóýɰ”`æ’xIÄb!‘áäW矗ùþ’ëHÄÖ~ˆÓÞÄ=”M4 ¼øY&% Ö9ˆ=óÒ9IŽ?¤Ö¿ $Óð³øuØê2I PA5LIAA! “&BE7Ê 8·ªÇøY GÏ-ޤý‚0Bmw ÌqI,èMÇ´\”LŠÂŽCÑ¥Á8™¢Ú‰¢¿ã‡!²-.½:™ƒI1’Á1a'д{Vu¨æqÃîÎPÛ·`ã"†™8Ñx)ga!Á½"0‘ËM¶í¨/¦èñ6²Ðân´qçË:ŽGiÈî{Ѫ&j( ¢ 0!8OÕÙ44ý$™ñü“š„Ä~ %ªõîG–ûgՔ彡TÞŸ¬šcpOœiØaÇ’Iò˜o 3Íý’~ÇûÞT#ꥑøˆBÇ£ì"ÞãҤظùIHìÂnâiÎ,­×mˆƒïû²Þ~?mû½ñÝ×(vÑ 30Q,RÄI,ÄDÔÍLENó»Ìã‰Äɵ”ÂNîÏuGê¿jnÚÛÅõœNî‰äÈ&ÜÈΠöê±zce—¸c„­ q"Òu¹SP¦U !6bkDÆhfrä†,¤8èM" ñc<Ãô{`\&’$™®°zJpZ™ƒZS)³”045i”ªÈS4ÅA0LQø-èð> ï\}²g#ýn"Ñg¤÷êˆoÑA­xxמ¦vôÓÌ3Ükn£ËkýÁ„‡hÿ­?;áBFQ¤´‡ÏG’ІdA‡ÓáßE¢h×?q8·á©¨e£½µ²âr½æšû‹Ä&c±4UÇçhT!Ð8*ôr„x9B:p·l§ñß!올¨§Á\Ž{ë·]ž˜qø=~Y Ï¢‚-7±D@Ö¼¦†c–^9<&hɱ(T‚Y§Áí7Äp‚Pt˜Ñ5íÈ$A¶?‰Že¬×D´éxÒÞPìr ‰Ï4’Ë2u;LuÉ&™¢ ¢&&M Á–™Ü+hž·rEòC"š‡k)¬ ™¶…H7idÙ12fxßJc â¨ä“2!É‘mJ¢¥œ¤–4‰ Slµ5ÀC^&¢ ¨#Ö‰? ,F\Ùv\s‘ôˆkÇ º&t‰&OÂ"ð+óJ<>—ü‹ôK7|JŠ š¤&¦! Bb$¿u‡¢Ú‹N&ôõ5jj·=‚!°ªƒôa”‡väÐq·†f¢ä}*¬–›‚ŸÃòKoG,#‡<£á…Ï}û`¾Ç¬èñWdð3„E²S¬2(r”ß´Þ[µ¿0ahî~\Ò¦)3¾bj†8Cy.Ö/vÑÜjù—q¼Üt;Mvì ˜(©¢f ¢<5=(ªœCI$ãÒ‰£ñÚŠψD9…~påäDxšÏYVm$¸&Gnée„"ÁÉŠ'oô½¢"„žý‹éè_ M¨“éû:XüSCÊ0R t#ð™% H¿ (^E0k—ãͦÂ-É ²N&ÇCò÷›ÕÜ=äø‘‚fNùÀC0TLQ-UM4Ro8àæsÎNfoÞ˜QýõÀþ9ìéþˆ<æ=8íqYÀL¯YÉ$Ö?”AŽÝŠˆ)ÝÒE DìE. ìAyažãi#+É0Î,$ 61!ÚÜ„7Ø{Fpz*CpáFX¬ÁÌHzsfÃ&é ' 3­æÍ1ÜuQŸÊ`ÁçfF¬Þþ¾ƒw }‡‡(]×k Ò¹µyrµ¹®öùùºü÷½Ý9ãŸJë`kPnÈäû¾>ßwN»{è…t´0béb4ã¶›2mLA:àPúÇéX=¾>_•óû4ú|þjm Æ¨³TLm¦&"b ¢6 b51§9Ú*#ccŒæØ ̓`‹Vv [U8'¢ŒF,hÌæÑD)*Pie³× (à…këóá·yÞüit,Å:Ôð´©z ÁÒ‡d%uÆâ%¾ÞqÁNÁµŠ L)A0ØÅKK,Ñ-ººè˜L•m³mC"ˆ%ãEc ,ÂS ›:aÔÅ-4º1(]TsL\!ŒŒ´Âˆ˜¥Õ˜È+Q¢c&1.-˜ÛLÆŽKi±”¥ "Š:Ù¡‹kcC2𖳕hãí< "  ˆ‹o.©øcŽÖôd~“m®÷Ò=2Ïò~f‘üINðÓFÙ/&Ïws¯ |æãÂÙÄa•¤ÀðA"ï*ôdÈ.§ëy±ô[®iÊæÍ¶Ã_¹õ"÷¬”q–íÒ|ÿ‡¼/ž¸þž Ê~dAŸK¯>x|E‰éOi;¶œ9žqžzÕ7¹ÎXÃ[Yå úóÉäo…û>3XqáÅWÌ'ã£U9äóñ¢›­ ßhßž}¿¤éM~Df¸G…Fž\•­²v‹ ð&rN¨HÛ‡˜¡C_¶_ôûxpþúþ‘·¢ñÍŠù·Ük§úxqÅ"¡â«Â4Z>Z ó‡Ub³D•¾*cNðTsirÄ&ù—å¸òP"»(¹“Ð9uáŽtyÓWÎUW€‰>ü³™›äŽ0 7Ö4ÖÄiñ…ý>Ÿh’ F“X;}'|û7{¾{Îé9AâÜB)ªª¤8r‘˜9yÞGø|÷¨ðt&(ôB0Eyã˜@"Ê—& $÷ãMše¢ ºê÷QR;ùh: ºÔwqT¨2ÃõǧŸFZßJǧÀøÞWað¶a^ô ßgŽ©Ï[„-ôмy’²ŸÄf"êÒˆ(ã¨Zœ©“££s\ÃVÒTˆ1CéœÒ‘ö‘¶0$DDÍ,2US1žœ9…Î8ã‡EgÂ´ÝøÕ´h—ÖÃ_¼/$A&ZÓÎ Û<'´ÁÜõ¬²! ñÛâBa#äzR4Ôæž‹á3ðvtŽ8¢ëdãJoP„ÂYKdTФ! È:D6ð6í”–Áée¬“EœÞ‘ ƒ2dÂf›3Ùi[*m£Ý®ó~%-/Û†Ú_XÁð±åȹa./-6—7—™˜“---- ãŽ8ã‹8ã‡8ãŽ8ãŒ8áqÅ¥¥ ŒP¡B„‹Ò.½àF!žÝ“òŒ$våúáN†L-P©«xqúøŽ J§‡>@áñœh‚"$܆xâÿN×4×äüöÖ2Ú]hùk¦Û»FÚÚ×LÎoeßìÓÞ[I˜DÁêúÌLò··Ýĉ¿”„ôB£‘À÷(á€1ŒE²aibÀ7‘:i 6EÔL0‡nM6=ÿg4Òº…‰«Áß4kðÊI$䨱)R³E H1D„VÁ“‘2K¹Ò=¸ÅÇŸŸdâíçÝ„ð·ìóÄìO¯ó5/ñ˜ñ”4fŒ™Jhs#34ÄÇX•­Li’Î8í¨Ãëbø=f²Ë4…CÂS‘)ØãŠ•8Â=tѬlna7ø„åœò#ÚØÈë¿ìõã£a°¥ KAí÷ØOÏÛÕ9á>‡ÙìnÉYöÆ}üüæ ´Ñá²kÖÞÇ)ÆŠGaƒ°—‘4ô›TÏm$¨ìd™à(„™AH…!!Љ¡LníHƒE¬nfƒo9Ž7Ž&%‘xš(?¡1t-SøŸGë4ø|ã47·FEÈPæ?-¶ÛV8lÕ›¡ƒ³¡ŒÂÑl¶“fhGcSáÙ=¾á b4DJŒA$J•CPÛ0ÜrâPÐZE6’¡ºÒÒvL‘c•6Å·;Y{vsŒu{€ë¨·ã|K‹!ÜáÑWDµŠÇ“r$ÁQC«4õ…‰œrÐŽßl£¹òo‰G¯Ä¾ x<#É:¨¹’I<ܬَ$öJóÁQ,Ï|(ƒw4×.JDy±.ôq”O­ÅàãúÞž 8Á„‡»%ž—=^W§®òÒ¼&0«ž"ú½˜EošVù“c•×J6§K4ÀôGž7¥ÞŽtá$¢EéáôQBw’}ÝFIÚkDƒš‡©lê qËôN27bÕóµ:ò•9}²xâè@ƒº(˜0AiKLm²#Ã^Äu³ßODAîûjÎñF¾Þ”zˆðqøÒ½–a8/cćôk;Óˆí¥Aïi¢m{iº;‘Äœ¨³‡/…â=÷O1£Ò•rš¼mPxµÏ(¼ÉwöœÞ,’ÌÅ8ÖC>7–J³Œég=«0õKqÔKzxJ(¬™ ðÁaY©Åáãq‡­é…¿š2+ ™5C;@”äòy5ò7b>˜z`ˆ£DÅLDÇð>Û“žÆ#só·—î³ö~!~¿zYio„wym…{äžž– XÎ&B˜v ­l ´K9Ö Ý þ4w^‰Ž?p”ßG`¸ÓGsÂÒ-"~žJãRšÍ!52”"3”¡UMb$È P÷B Me» ãØ|†#ñ7¨m‘Ù¤Î"Ñ º•dH¸ÔÖZÒ¸ÕÌ„È0NÂDF,бž7¹­&Tîtq†œD<ŽõÒ,D.!ž%×<¯Æz8ÕIZ1:6G;kÛ­`…š-ÂD‚(Ù¯5QŒ%Y{d"jC¼AEŽa.B2´qÎk/eÍ 0»ÉŸ!Ÿ9Ç4s ”åé–DÎéeœqOG‘ÈÒ5ŸÊ{vÁàð·(ÁÇq/ Ì“ls1Þ`Ò,ËÇÃŒ+¬ÜáúÌ<2Üð² µ×®°ñ¸x8¨B3Mÿ&cýËð£Ü6}§/áCÊFs7yrÃæ¹[²"¦')¥³ƒ /„Pÿ£dèVï«GÄY\dä‚mÐò‹¹4Ç6šuåé ^\9ç„c"4èݹ<Ös4Ý)Ï7„#H<%KDÏ" šò,Ýs ‹/Â;˞؅ě/¸'šYcžQv,ñZ<^Us´>#ÌÁQ/{åtq¤›B3Âp𻽜Ý7 Ÿ"ޥͳ¡8£ <¿‰ ~;5;³-ÙïHÍ8²Uׄxm¤xYGúAç ;Èg:’yx¥âìðr 6%tÒ„Jä鱜Y-áUrySE4;iÈ}&‡ð¾ïZÂ˳L$|£L<.eA闽̙ +E3&äáŠö ªY$§Ÿ}Ó7Ì/=ý÷©³ÂÞÜ·ôžßIÕsé^›å”ÒP±ê ÑÌJ˾ˆù§ŽYáânžFyËË(ó‘&éäËø¦IE³>e7MŽL5I°KÅ=9ç÷=N™îçÄ9G®yUé¤ ¦Ô9GƘŽ,ÄCy–Öcç £èyþº³ß0GÆò‘¾cf9ñqŸ /Ëlk‡7 òÍ3üÖ䥜x8yFÏiI‘[ RG•ƒœ·iAPÖ ÝßÁd“!Ç—ª²× ¶k9—nlwN[6–ì¶wIâ·:±ê#aRâ¦âfŸ‡IÇqÄœqÇQÇqqÇYÇ9ÇQGéŠ(¢üü*ôtÖøðOD‘4”+HnakÄó*™8) IB´JpáøÚl_†½²ãX߆lDÒ¦|0Áa¶®jÔØïÉùÀ='³ÝèaæB¥(cÄ`Ä„CSþSÙHÉè2žÓÎó9˜G³#Å€‘ŒHÎ~ÉÈM_×£2aÍ š¿ž·U5°*ãðø;}Íßò½MQ³g?1wÁŒ&Ú6(Wöú›ÇrŒZZ”FϳGÜÀ>áÐüŸÆC¹Ô~~×í:/²ü ˜¹‘[Ü!Ù Á·ÉÁøFðt!ÄŽ‡Î£3BÞ@¹LˆBØ9©"„Ž%n£pUÈMkÉž¶mpîáküI8ß\G–›*G€ÊóÃ`ðLŸÊò´¼çÞ‹r}ž$›ÃÎì¿ " ,‚4ÈrÜêt9o J=6 Í<<ÑçŽÜ¶%¬=áBò¨ô³(¡·ÔtÛ<Ô¸I™¹E¤âeûlÆÆð‹$sœè®¢ŽÆyy!Í¢ ”,"Ðùï æ*²Q D9§žùÒ™ë¬vÞ£ ¥FIE˜^Lñb秈ñÌv]5ˆª"áœE\£ÂZ‘ˆÃƒ‡C‡žÄœlJ:Îðï)AzG j¸íGGžPŒ¶Á]IjÇNYu7½<ަíý"(ˆh¢"„~~9ÄðCŸna¥ø¿Éj(üxÂãÀ¢©š…Äj^X¨E”ˆñ½!¤ˆUGŠ"[JR`¼’Y¿åïÁÝ¿0é©.Ó® qÛÌXi3C–kǾI5©ÙDÍÝ/-Òiá'ìêu ™i¥’b ’F‚"b" ª"¦i*I錮›t8œ§ 13·“_dcÀço@|Ò›-“qîÓK4»@‚ô<öËÓgiŸgHüüär~;|L}ç §Šˆ<bkGöFï®7…¡ë‚N^D ugi«''E !ÂCg™‚š“´dàp6:œº°ÑöcTÄOA÷§óâ’c”q#ËX˜ú„"Ä.Š—‰Ä5¦JQ^éHâ×aíÉ} ÔH›ÅÅœ+R8õhÿjÒŠ=8ý“Ÿ B ‚ˆe’fH¢Ð‹íǦغq¸-´Aø›Ä}8¡ôYˆM²í sŽ‹ŠÑÊÁ7*ô-·­`4l•æS†1•GHÅ'ŒVÈ=¢`¯rÐßœ<¦iGßñ7îcc#‘Äí8k¾8â‚jHˆ‰f™‰o˜Çî"X¯òÄ{òâOÍ’>J>êv”GJED"Ss<ÀÁ&ÈE¢1½ÄœV¨r°SÏ|*Ca‰±¹˜†Ÿ#4&‘7¦‡B]äť̜NÂËÐê4EQED±%PÍIJtâ\±¸ø&½È¢H—ШÂ<©HÆ<p¥œBøìÃÉŸ,­¢ÎqPpé:ü÷ñ¨Ç¤ÇÊ=‚¥^¸VÈâÃþƒþ ´ˆ§0F'Açî*ÂZPÔóÅÒDSŠ^^†M<'ÆŽSÌõ;("1*]‡8Ýû–YîW4…õ{ ¡Í‰E ©I8ìç¯ü×ëí9‡ÜiöÂŽ| £otÈ“b?BMâ>?¾OëÁìD ±ÙÓQÏ'IŽk\|ÖãÂÏÂï×ü!”D4EQSU1310̃DŒ:q9Û<¨mÀ‚®þu‡¿èƒ=Ï8Ô;QÐ{<BMàF5Ô"Ú(‰þ«©ü4ݳšÁ9ûrßía#ÊlA?}!‚ ýÉûQ  E ‰¸oJ<#:làƒÏ&C¦4qÍ)áì\Ù CJj¯©½ ðý“Aø bi†Jˆ"j¦)ƒídåŽ;B'å|r2SòâNÉ,ÄYõ¥ ò‡ËmÇ.ÿ+? )?§àCŽB=ù$·â`Œ?9Î_Ì9ë|ýèô&\ØaÇá'‡âL™ ¢’¢"‚("¥¨¡xNQôÃØñÏ…£i@èæ·h'jêo¤ÐXÿ4’çš,^SãEîɸÏŸùöÙø‡a®Ø¼?\o‚B#­ü&aCJÎv1‡m97Ô4ögñÌòëÞe&™¾j¹ÚZ ØÖ©lÇe5¦¶» -R¤šÍ`i‚£"Ïbo×'À猻`í¦^žk¾9[/Fˆk>/å˜Â|>˜â>!Îvô Œ³ ¢=®=>³?…˜{g¾ù3[}%zYÕä䢦MF7´9~¹5ÄÜH/O ôíº| ó3ˆ<ì1ÉÑô®¼›8çÜ ¡Û°W„î—O™CЊ®ékw'+mM8‰ð+Ê4ƒ‰£•efžVøeïqáý ¿g­'ÃHŸJ4¬+ç(¡ÌÒx³é¼C•Fɳ&ïMig'ôÎñÉ6È%üDu²¢0‘ò'ϰވ›¹<Š"¸êð¯8² ×’T‘mÄ>g töH)õÓró á^¢ÕmQ„аÎ<ÃYxhšÑÒ^^”iÆ7g…ÑÅäÑÇ›q²yŦáD‹ü½ñ^øã–M@{\ñǸ_“¤úxÏ%(€VIOg­Ò"qÓÁìDI Çï$î(ðóÁ|9¶Ž#1ÎÕ%xj¤N‡¼I×#ŠÅ§´Î~»¬ |k)Ï,|FÌøX‘È¿‚k³ä>éîæmQ„D¹ÅÁ”9'&´˜´¹,äøXë(óÃÁ@Il^TSù>žb6Ï'Ò‹$„]iw…yôP‘%V™ãRYgN¢‰<ãÜ“ÒO7´«ÃÃL‚öm|¢Ê_"Ûm©QRv{FDøã s}ܶ™³ ìÀ/Òų'–¼7a[®­¶L¡CqBâ¦Ò…†ÒÒ8ãŽ8£Ž8âN8ãŽ$ãŽ8âŽ--- ´´™2f¬L™ˆC6Ë/üÉw ÓfèL1DLI¹áØ{òT5Ô)…$’ 0&þ]vŸ¥Û>T£Ž€´_DSâ˜í½›ëÒõ³Á®p¥1ŒdsS¬c/F?œ8ů{DÝÚà¡„b" ¢3!E#Ò÷k¥iœ`Éï8[ý{O›ÚY}£ G}Òl:á Î6ö …8qèˆ|d»3²ð“v†¯C´@íTQ3 –@×ì44Ï«‡8 í Z.rýâ{J'w‚Dš»ç#™§7 é⚸&D9áÔqÔOLYï+ò|9ù:Ë'm4GŠ”â©û©CzW„¾ç®8ðjôãÎ%» ¢ÂÊO*o¼ã<÷Y½*Δ(¯(¡Ié¸uxLÁ#™êl^{DQàôadµá•5C»q®SyvTQ2ŸÓQ›â5«vºé÷{2È0+BNÞ Ÿ)ô”?÷tx>2ÞwããtsÊÈH<õ²¦n‚jãtƒÃ $ò‹D¢G.ziûÒŠðƒl­8”Aã÷Œþôœ[8œ‹½f¢‡6\¤`ðáEĉû…åž¶FÊM’(ôÓ êÃtpFÉàŒ+Ù,àæYR,7b`YŒöË ;¼+›Ò áÊé G ¸Ï .>úYé{¾ˆô@þ乞ŽïéáF“D›[cÓy¾I´z½„ãÍ&™‚ Gž/bL‡r‚#: QS0Z—qøw§py„D Š•!ÜäùÝ$ûƒÖ÷¤T7­QºQçxoÂ;táÇ«sÕì- ³ß¬âX¼ÁëHôðsZÉ÷&HÒ}=Yëá§~éô#Šˆ*‚"œ¦Ç<ÃGZiؽ.’„ÔþïÛ™¸L)>¬.ËÉÙ4kÓHr#ê;ûñ9áþ¢~DJ¤Þ‹éŒä&úkއ$ˆ-h•‹,Ž)ç"¾cn8†šöu(‰d")šŠZ(bª¢‰Šˆ"f"j ¤F~°´ÿ‚ ü‘Ï5µ›“"&´”ŸOðóÇŸÊŒ#½óÓÖêko×§¯†8NçE9k„} Ñd¹&äÈÝÛT%²ÉØ@Øf†Eçj`ÍÝR²Nž·ñ´äìlzšÛш,D"<“+”w[R„âEœ<ü(i±ðAߦ‘ÆT2Ñ3ÆD¢ü lpƒËAäÊ1 ìsìÐŒƒ‘^YbBô¶FàÏ(ôï¤ý4Ž>âE9hAkPTFÊœrî°q}!É4éd “‡:øŽ:¨DiGà¾õ& ˆ˜ bªjJ!h˜XÆ(ƒ½¾àó Öü›ÜŽœHò|4ŸªMÓQ§öùF¬Ø°Ä“#hE7”P}Â%–Aóê¼ Lå‘úý7ø˜á1b‰Ób¬˜Ãdïàhp… <¦‡špIiw³”¢pÂr0ï­öÐɸàlo:°LÄÅ1 o)[cSŽQüIô¼¿_àå1ô²¸Ñ"é·Â’?LåÌ=ãÔ^,òã7 !¡¢yØ#„j!Ò&Á_°<¿ë‹ù? ƒßÓ|qÐÁM(Q<°ßVOjYàv[™r Ñ%ê¨pö|‚Ï׿¶’qDÿ~"¤‰˜ˆ i¡‚™&¾ÎãCÍ¿ÄÈrL{>Îz} ؉OĵdïšSØèJ¡’‰/9t$Áub?TzNz³»à@õt&mCÂd픚<Œ<ó`“à ãÄZ­›ïzÿëñ¾~Ï+yõŠˆ""*Xˆzu¬<ðjzk‡ô·)IBBþ;LÈFXyö#Ü(?Fñp¦jå,$\H©¢ƒÌ™ˆ³‚”Êtkœ,×WX ôä=. ô³Ñ M“Éë,àz.ó„~ý/VGiƒIÞ jxAááüúoÆ ˜ (ˆ!$˜† Å‡š?ÅAgÆ·`¢^kISG£¹ïÚ‚OŸ¨0ÒܲD!.sBJŽ>–}£Ûþ¿§îg”Yâ;°Äy.L(ì…;Y$M)›ÄÌ+vmŠ‚„Áˆ MB‡$ÂÑçDë1E$Ñ»äðÓKc¡`Ëü„#è¦Pç¡* „ÎAóõ³Y°òYíªl?»“DŸ¯Íðù8Ú|ë5¬À·0t&KþŸÏüo£ü£áD§Ì3UYMƒØ¥®„Aˆ‘5ˆ_aUâÑlÓ”L|Mé¥Áþ¢­ÄvÁU% Õ‘UÍÑADAQ1LúæûÇØ+ïçágÊQó ÙÏŽç;&Ò¢$! ìµ–ÊâeõQÓtXå~ÿLBÚc•ya§Ók1&Ž©†=>‚röïIÈöà°ØA{&“‘4…0flXòPØI‚a—ŽÞ"Ȳ A`ƒÅb-7Á£ÜûñëÕo·=êhä”mæ9>Ê¥²qvº[³=j¤ã¦&"d„2d1J\Žãg§‰“q¿‚D‡á"ÃDˆ(ÍðÓ‰¶î#G7ª^∇k.‡#ù"jÎ#|¾ö2Kñö8Ä{ÛUcŽwi'˜'΃ǩ2äÒ'M’Œó[ÀqíD9ãÁ¤ç=;gtX‘³EžS<w8ñ…Q¢iÙ ÁÉr8½’Ú¦˜,©i³<4Ž$ðÆ™rÈx§Á<ÉÂ’Í2èÃ!ç âÜÓÊ1³q¤óÂs¢NâKŸ-/ƾç_‡(4ò´vשÈñËQdvå$ž9fŽÜ`çqcøM†ù‡dVˆ³Ê‡6êxxÌ ;<è9ã›’Hæ—›I±.öOo!ÈætÈÃÓÑýE±c‰҈WïaêIÚŠ7Â2°âÿ¹¬Ûå[ sÉe—éåA1Z#,òúÐ:Ì&‡ÑÜëïO4‹ðÒ!ž‡ÞŽÃÎswÁäÑÌò|¼·ðŸ ¼.l¬ ²”WA‚±Û b\zÂcHÃO„ÙF¿ˆƒÐ÷L+§ÂJô*Š‚G(>2£!# 0™¹çÓ¬ÔõËšã1q•EÓëÅgdü.P R”¥ `ˆÁ‰(’ŠýÀdO»å΃ss A"F"E<@üçK­€}QgÞ:˜ÁÅuàT˜è:ل١¯Ý]œxÄDåžÝ½ Çœxc‚ÝDÚ³ßaŘaa¸È¦d¿Oøû’§`ÁWóü¹ ^;á#ž]ᥕF•¡1Ú–IwþgÑÕ5x™àk’ì—r ñ÷Ì‹$³£Î5¸Ga¸xNO‘ØÐ`ë#$˜ĽWAëß‘å {¾X”÷£¸þy2TÔYTO§¸ûǂ‰(ÖÞñÉqÇU“%ÔÐXîìÓÎJÕ¤ “é%fEzÞKˆ—^ŒN&hè¨öJ~¸—‡iuªðÄéÜöRÛ¾Óµó ðð}ûžETM›ŒyBÉ5F=@ä1ééÅ’zŽi!Ú •d¡¼ÍÏ7Nò޳r8¡É*mSQdŸ†9G,ðÁ`€‹î”bœhóãÆg›3£€æxL;Oµè —¯SK"d«švøÖPsYâ‘ä@LÆm{ZѲñÊLéµ^'ò(@ÈÊ!Š´ßdòí¸ž"Ñõ#ˆ/ÃQ2pþpî9‚7†›àêu`"‰™¨¦ ¤˜L&HGßžïÏ8ô˜úp‡ÈyñÍ’÷ñYfßppH6¡ˆ  õ3ŠsG†œvkh™+BÓ!PãN}¦ÂÌ:šju R"hŠˆ)¦ ‚hH¬Eb(ÁO9ÑÇy¿ÅëÓ¢¼g.¾ã$T`ÿ†3¨Öl j ñ0B½Zðhèà\Θ'^¾}g^,•†{R¤=4_)°˜0NN ^Âi5ªO+Ü¡X:hMmóaµªhzM×£!˜´}Ü ´M;8˜1;q¤~¤ðãÓC=¥4Q@DÔÄTLG8´D}5ãê>ž> ³ê$Ù¨ú—SzIf`æ"Û„\#Ô瞟¨i/Ôíì9¿+‹?_¦>,¿1ΣŸéøŠC¯VæÓ’Sžö*¡ÜF㱇;f5㓚&“êl0£ôcMx@u¨$˜ ¨ˆŠ˜©LŽwA·ó˜L&ÁyŸY*8Ïl@$ÞÙµí1ÛWZr®;ÙðFCt²ÛõßóóÁYCø™´G¥½ARÁb(woSbˆÑ  çÒ¤ÁÑÆÄ–áêsÀÞ%¼-é1²ìx&ù-…~A„&L”X ÄDXÝû̇nû™6+ÖÛmº"=Ei‘ù&fô•ÞMü_các]ç3¿ëò°õÃ/Ç’Üò ©ž‚=¾"—¨âÃqƒÂ><9c³Ðå¢Ä7!üj‹<; ³ªKQDM%%,”P1F¢‚sïGA·&ó·¦KÝÑú“ÓíqæAï±¢”zmF2$³ÿCú]l5•¨‰„žýu0‘H˜›÷C_“Ú&`É 18‹A¨%0|ÅÏäÜ-G"Ñ&š¨¬ÝíŸC@¤Ž!j8ê׬ô{4ׯo}ɤPÕÍkŒY?ÃSàv;Ó^5t’||±Ï†2|»É,º8ðãp%Á–sIá̆ ì”xPíÆˆQ´yÇÅwIÆÈãø7â ;’y4sÂ\þ—åÈLç³\¡u·²oºôttãr‰ˆð³L#¦GžšæÅO„%a·o ¼âô]¦îhç·ì£IË=õµ WÕËÃøó˯2½‚H>|‚Jùè+æ”IÓ›óÓRœoE$N”Töxi‡žwžyûÇ“g¯ê;Õ´Òí’LniÏ"%BôÒ³ p@w¨•æX‹%ÌB )A¸YÞiƒœ¦]ú$ô¡ÙdŽa‚Ó½kðã'Kˆ]b¢*ã!pTqóû^…:/Iš‡ľ’•ÙÝèü°Ž’„oRy8¸£Œ^o“³Ž,,-öOyáÈ÷d±ã “ˆœîžsŠðv ›£úHæQ}ØÒCñv8?aŒütˆWͦÛCñ~U¨&‡ hL…‡ŽQ§Éë|@†E‚,ˆe× ±¡ì!±ãFDà¢+Ø“ ¼z¦¤¶¶å|]#Bê oëþ›ÿDœú˜|üû^}ýi;hŽÍƒO(ƒ7´Êlû‡§´bgò ôÅ%9¶CÛY¥Ÿ£fó×Õö™ ˆ.lRDÄK4IQª¢DYà¹ÁØàßa:K®Óm³‚ØØÈ%èÆÀHˆ[};b ƒ¸€nüû!­®Ì…8àg£NægŠÙ…Á˜y7Þ=A£ŽÙ£éã°âÔp‹¶ÂfãShŠLHî|ˆ´{[øï¾´x~4߀ ¢bj˜˜& M±_8§¥æ$¨úAL—IŽIVâ n9L8ª®Š©»è!QÓÏÀUÃ#6O’Þ@™ÛêhA$A ŠVÉίÖpYožçcsÐÏIèȂڑdXŠ/°•TEóÞÌ,²›õ«©1ߨ, h°YˆP=`¼ßÁ,8ÀÏÌꑟëO­žKS+åN¸ý|¯‡èhA_\ú"hÜ|ô‘Ë<ˆ· AºTD1H„`ã\9bh쀹(úaú>·ã~‰ÁL5,C4›`Û¦íù3®®ÚÏÆürK,ÈGK?Bkšê²›®Þ‹!ä„4¾h›ålË7&'V~Q¯ÐUÍBø‚Ð$|wo¨…rÿdsËvÖE¹¶°â*ÇA¥8G ‚máâ„|¬dq'èy¯© ¨ H˜"JH™ˆ‚b!Nöp¡½¨˜³ðEˆ’Fûe?¾ÌªmG~]×Ï™ìÑ›Oò‹ƒ ,¡+ ÷õú…âüC˜á÷èç 1#D ¡”}‡Eà:B­Nrä?ÑÀÅÐíKp$ñ©Ñ£±êké¹êŒEÃŕOò™O´x¾9}„#í.æ¿òœœ„‘çÈâö Þ®£ÄÚyA è¢ ~ÿAg@B4ÁØîÅ »Þz`MÄ4‡#ByN N9Ê›å̧y±¼ì4åÙuX(b"""ÀTQS¥àÄðúáמښ\I ¥|kü$/góZk}‹(’O”Š1éI2Ž59™dIúýB‹z3Z”=”SÓ³e¸}CIü@ø9¸B C¯¶Qç“<ú”ѹäÛZ(yˆÆDQˆˆ( ‚Æ#!Ý; wË8yæyyÂÁ"øˆ=a}D‰.×Ä|;üÿ¯×Á1Ç8s/¢o©¢E9ö™Ëgè#õÆ¢Ìà›bš%p¤Ryd0“ŒÄáÌ~ûË[ij÷r å›>8ã-—é}³bBbO“&&‚ÖOê$ãlÛ4r¶ÊS‘Ì”mpy&¸YN`: 3S›ŠðÓ‰Eá#–s=ÎOA|eçt¤lMÀèâø†Ù$Ëd™ê)í {0 $­ ÐÍ„Mõ‘ZgïgÛðöEÚCèŒÍ(}*Ù Ÿ0Ét‹£*£ã›(·4‚¨räO‡!ñÍm-¬Ü½4’Î)ztÁwÇ“´’‡7-¬G†"âÒó·¨M|äÆOi\w’ux@ì™Íy(‚¸§,ÜÁÌø¹ãyEå=_ôù>æ&šzLŸ`…eç”!ZˆøFXú!gÏ ’6Ê£ŽRâG‡S8QEØFžsæÐŽÜðñòiYÁdç›ç…’l–èãe7Aà ‚¯Ç Ú‘ØIRá[±,oÑ9áŽ,vË)El×Kõ”Ó%n\†SŽ,ðT«ÁØs°¶ð‚.주<§sfrJŠœ—WM Öc¹S äjLl©–gƒÄ²Ã…~iJÖñMá‹dr´”çn¹fq{ÎxqÓá#ñFáÎa¤wuŠb2`NA%qqáàùͼ²Â8è¡CëS熘ÕÐŒ! O¶(ãG$½Û ÓPåI²cÉ;¢JÎ'|EF¹*Mó ڱs8ª —ñ‹"èÜ™žgÂÆéé<$ÖÓá$5þQM9m¦·q"—өȕš@æÂñº¬B’"iÇé×cHè%rQ†ÖÙ%Æ›˜FCž×àŽk&ɯ(y¤ÐØûá/'ŠˆnÅ]‰Âˆê 0…¸F“â¯<ðEIˆ±ÚI‘âÇ¢^³ª<è ¼²l;Âfã ð!¨ÎEÕáËÌßl—8º~"‰”Qä4ÿ?÷ñÝ’m€Ã7Ãû= ÇW¯Ø½ÿ‹ÇGáíî>¢_’ªp@½Ÿñæd0¨ öŠ»÷¨ý¡0)®ƒ†UG¢qÏĘÿïÿéÿ=Qì"‘ý¼7„ýÊ`¿^ÞíW©9Aº¡¿a$ã¢WÅ÷Fµ×I’cü<°YÔ§ìÞùÿć$x½¯Vž ,{åér’ü‹Jµ‰•ÄÊv1¡k|ûÏAuÝé8g'üŒïÓN~¬yß<‘TÌÑ,²D„ D!E$ÅDTSL1SDQ4ÄÑDP_îáwŽ£‹žÏd‰NLIdƘӣC £{`øso;¸ùðß穲Ï¿¬‘ÿO˜?’&ºXMÛØ#ìï‡wøxßÝ‚r[4sðæí‘4y:ªvgÇCŸ$÷~ÜrLØHC'+í¶ûîå[ñÙUUoâß4wvßx6åw÷ç÷§½åUU_m•]iÎ÷vÛ+öM·ôzwr­ñ¸âs¹UµUUZÕUµUUUUU7‚s×ýÄ1à]IÑÝÝÞÓB‡ìÖË,w{"ÝÝÝßV”¥%UUUUUµVµUWõ›oÝên½èM²¿¶Ûm¾m¶ÙU]·Øzw[ØÛ*ªºfå] ²ªª®6ʪªªí²»lªÚªªªª®;N¼ª¿ùd6ʶª¯ûŸñŸ[ÞÆÙUUm]'×wWØÛ*ªµÐªJ¿=ymVÕUxqk´x85ʪªªâm•Ç×t0/i¶U\8»ü`î¯+ýéÛhO¾îU_M²¶m®û‹«U[Wƒm½.ä òª«üÝܪªü’m°Öî›eµÛeUWe]úØëË}Î’^Uô6Ûlªªí·òçžÛ¯÷?Ð'ÏŸUUUWÁ¶WìÛ.…z¼Ü;*ª­ªªª«¶Ûlªª«¶Êªª¼I¶à6ʪªªªªªªªªªª¿¼èMcO¯¿Òiik_é˜æM¥–ƒùtüzߪ«ól®Ûm²­«ùH‹•ïç§w+ýÝÊ«õÿd wrªª¯¶ºª­«öe{m÷ÇJ_CÀ¾LÎòwz°Ëõ_ãF61§4òïÈ™›h b8¡¨ïÁHô$¥!Ó˜o‘lÞDJg10ÊzÍdþ™Ì Ê=ÏóSÇÛÓ|“ñ¾µ/i}`BI[Rþ‹ÜVqðÆ&„bBjP¬·”ìîIF5 Tj]çÏÃxxô ^@‘#r0Q§ Å rT¦!‚…SF—i 0’Rht”4£@j-±)(CZS”°TJ§E0ÌÈÅDÃ*K0±%ÂD÷Á(ZNå¬,‹A¥3,@Ó¤pµZ ÉtÈ8ap˜—’!ÀEÐñ5=‡×%7Ém±!wÖÜ^‹¹lû)ªú¤á4ÒÒoSœJ[‰¹aj•mQÿ;y‘|‹<<’û-ŠKu3·Y’xÂÖ•“-¬?GþÓ­#ZßàÿvWe_nÝ¢KÁ´E…·3H4 5 eaч#ÒÊê0s_ò\†¡ç6ãrÞGöÌüQÛýñaò»ë¯ÔV·.KICå¿ëø]ù¦Xƒ…ùký{¥Ý=Œ¹H‹6_°"ý^M×òÙvüïËA(6ÿ|«"I²³wªFÃem\žýµÙ±±óe9ÜÄ:ýÒ·àa用ȕ÷ôO¯,²Ëë;xÓmyØÖl¶¥¼ž†º:Ó¢ì'k½Æ0x­Î²¥ô•º•íÖE4‡±ìæ‘Iaq‰$]ËêÕcX¿¯7nWq‡³tdJùÅ?©çu+iI,ß5Öï4eGmÏ­ìâ=·\nºí’ï¹ók„³á”xeKæ_l™TTYîã6Úºv_s_Õ÷O¿^n³U–©å9Û§ËaIYŸ|EêyÑdÈ£ò§u,š’Gl-yMJšt7EýPë·‰¼£ß‹å¥øyi,SK;™ÓÖ5­Íý7òzi–$^\ï™O¶³i¥EÛYë[*GÕ:Y§¿ËÜbß•ø-Ƥô’Ფ¼ž›½§9ÖÃ0ÌÐtTéÈS.¬²ÎßoÄb8oëÏè9½ÊÞ;>}è!¾–Ì]èíD"pls¯±|ÂéCzPTõ¸Àè5_N @Þ¥C¥Ó(ŽÁ)1TtÝÍ$Èf(€½f ça¡¼‡@߃·ç€¥vܶOD-wFÊÞCt89kÊZ]é÷g·ÍÙíþmm«ixæÃˆ‡þ›MÍaÖ_Á†ÀeØQŸ!¨ç­Ï}¡³Þ¦bís_Q“'å|äÒv÷›o”ß²¬)QNBxû5 >Ó‰“1þ_ü5 DäìdÿŽ»êÿFDþjxqˆSëñ –~Œ~ÁZMúwÍ ,ÚìÞªN& ±ÇE Ÿõ 1CQ„Ò@u‰ †(öÛµwPܸ ¤¥¬‚Hª­ììÍzß.ÎÍxJÆ£ÕÄ”Ñ~’û:êÌ6âç`4€}Ä?t ùc°/í€1nãKùd G”k;Äš?Gâ0ÂM%‰d>ÝË:Ë$Ç-„¬šÁ³Öé wB¦Äâå~ýKO›-,–wß{`ºÒÙ[çra —ÉGø'/ÞéŒÍläÁ[¯ 9¦¢ˆYNßH:¤è+ IçEtú}?DË«`Ö™6Ú<ÕÙU.»öÊý0j—í׌˜’˜¤BòZK3ää%çO'Á@™“Ñþ¹wá†{2•/úôJä“n³p£.XD‡7¨Œ(æ<[… s eš<úÄÁ³û‹ßÊI¶ÚæÌܬWlkRާ.ß$ÝÛŒÃßmkëﲜàM¨û‘ÉßbÉïÍ2r¼2ÙRd6™•“¡ííå.» ‘|d.ng&øRÚ‹F"79Bö¬áw§òõrÝm/ÎíÒ,—.:í¸–_akíÂ< ÔåüØD¤Ü‘¾ÑR;¼Ú³C6TÍ­ݲÂeú”fbú,ˆfbˆ­ÆjMyJ©æÒo¬˜„Ì“! ¸L’EÛTìçJ_œË*pλ'†¬3ÆnÞ¥!«»&ªÀM °g‹$Ó†Û¤DåA¼Óq¦gH ˆhh@nçz°ÇO.ý6emz7ÝxPå X?M]ÖÄ@eŽØÉ6ê["Oà€¤¦ÏÜä3Ò þr §¦—LÑÈë¤Lá|”…²âc„ij=zÎùýÇŸÏo3!$/jIù=¸;ný@"²~jšCIÇaût~y®RŠhxþltŸ™PÒÌîÏ^?6º×F Pq’.óðãìz+¼pÏ’¸Ðê"d~j“ø~Íón$…èMÃ;[ñÑH7ØY*í­FÒDõ“-a Ò :ržäÓ×ȶë+ vo‹LüŽEnÆ6átNƒ˜˜³°rðçSÓkh¶\óJ©ù;³{“Uµô½6‰‰+uï|0±pY î½ÙÝíò2Iÿ}5X­D×°‚©–d1ÂCbˆó; Á0Öy³‚å^K¾~Ih î„~2?L)ì„>%ÊS§y'ï[“V¸ÇÓwÑ? k˳Ö]å½±*ÀÇU®ÚHõ.}PìÚëΠw’s*̽>~߬½·^ùm0½º:×Qî ;K¬j¡ÿm·‡­¤Ãh|ºÜw†ŸÜæ¨Ùkñu¦8ÎÙ3LÜrq†´ÆpÀu#Pd c)µƒõ×+ÃÓèý–a-|¾¯×_¯MtÁ7‚‡ÛUáç !]þ·n™8y=qO/'/Ì€áR‚0úOOÆø˜±¡Ü5æ#yŸÍ߇³Zñ=æ˜ü€_¥Øhâff¾=(sÊ|<üù³Ôô~36AÃÛæo,yø؆Mxsþ&ž˜þÌ7ú† @YÑ`SìU?üà¬À?\' Uü0(k ÿ„¹‘í…͈üМEchÀJÂ@”Ÿtþ*$²BßÓè1|¹Ù¨8Ê©/û‰ŒŸ³ï˜pN,ʃüSîÀ»ä9¼Œ*=ò ñ”@Ö#ïõú×L[¾•O|¥˜3ûÕ?‘ÿ¾u«ÁØky´fü;¦Íñ“ƒbc·Òƒ¤îoÇõô³}çÌX0.|θ$]—®’cÅ4ªàÜF0à;°.„’ÓÕ3¥€ŽH´ó1ªŽÌOÑóë]” t:ìrÙåfâÉ›ª' 6œ:\~mú"Òw$šÔÄ“$Û€}Ï[õ«,ú)ö·ÆÎc–â˜ø´0ÍÐ&£žNM÷‘óeNÓ+™º·?æ5Ðên§›oùÏ´ý¾ràáRBÚðÃrûÃ'Ç#Ì!ÿ ²×¤°©Òz¼ÐÝýŸÚŽ„Ks7?¤;=\幓?i¯IórmÕoà†Ç>¾£vUú ³àm½0µ+=1‹“1¡³›öûäZÞµŠdr5'Âv…}QƒQ›!oÙì¶¾ò'çÜÒ°NRT“ DɃÝ÷µæôéÈ4b¿ïƒ C à!Ð…’”)©P¥R„L $CB4ÌБ+´QE TC34QR´1%  ÿŒQ@ÿˆÿ ÀœÄy÷ßÞ ¬ (jH `ftà 7WîüoÍŸ<ÆâĽÿ_ßð˜}×SÃ?“ßñùtq>{«oÙêÜ“SžÜ½MãÜ{}žsÉï£ÿ­Æo⛥0u3|‡÷_üb^'ä¶qebù}]íà2nÃÁÇû« ÄAØ™»ã"»ö sõŸ›œi ³l†-¹‹@)æföy(Æ¿výÝ!øéö#Ëê§Ûdm9sÙ볚×oP­µü?}ØÞÍA&:›Ùùü¦ÿg¾æñ÷Ùß»íËoGÃÏt×/WYú¶–œ,[®¾Và`p“Ìj|æÖ&1ۅ⻵¹5~oA§Y¸M ߌ…{p>$ÛyŽ Éu‰Ðt-—åO—“ú/GãÔáÈìïýNª»ÿ`hZ8ȇ¥=u&x(à` ¥6ÀÜdqQ˜ CÂj.àü¡µ€7&, <2Æ9eLü}æõ9jsäCËÇŸ5Û`JUÐ {¥t ‘Ýå„_â~û í”v 9Àó…}Ò!Ñ„q¡Ÿ—Ÿñ‘ûJ¢€ aXS ,Ê)ÆòJªÿ\¦a Pf!Q‰‚EþrT@ã)ß(ÿÀ„]ð¨'÷H¸fQV€€T}ìn„°ÙEP7äÉêTˆ„ ß kæÄ£‰ZT¤U: þ7z‡çñÂQŽg³c÷"îG«½«Øö}Ôsí¾öýg·šÄÖÌoäˆ û¹CqÃWÝûÏOcvæ.ˆh8\º¿kˆTòþbͺ7õÐtÞ»\´¤“Öü?ƒ fæ9ßTΑ'!@³ƒ¡Ëø_‚íøíôBÿ£|l^ØN¬Ÿ†TùàŠKøe 4SDÏá°mš+óô^ñìÞ±%„•)©Ïîfý§NôÍ1Gù¶“Ôþ ðw4™Ï[µÛ3v¬¤ÅI ˜?Þ@ûd0OWf~¨hf>ߨ»éwDˆÐk[õ°ÑˆØ’hLÅmûä&oÏÿb:1á„hÈ×;_û[._á`ÿæg‚Á¦Ð9ž!‘8ÑÞP«¹b°íêõ!”söa ¢•+ûIåfo‘§ñ³÷IHzL¤;ÉCqýÉû9«Áµûƺûw 5÷—õôÍ)©jîñ»G,Å”ùÂÁžx^Ó÷åôŸå¨Q×÷|¹D?³®c— žÏž“Àvin±ìCñ.gA‚-`¤Ê à&â@™hí &iªß0;‚ã°fæbF½N!×{ïÛ&À}åÇÆ²à1†o†øF`8RÇùГø#±€ ý „Õ(\ŸÉ²ÍÑ-m _ò?ÇñÐò°“ht >.“w‹éP•ÿ‘"ž„(hËÀàçÈPÁçÎ~ b#ëOrˆŒWþÂ"ÃAÄÞ)cÄC hô”¡oÞYèqÿHø$Ûþ3y¼½å Áî42·œd„ùMú¼žÂMÒdɳ<É>â àò„hÔgÜ’€/ì!ªªJÖ²æETR;’"ª¢ï$=d  ‘JKòdÛ&–†‚O“ƒó,ŸÄ²úF¡1º1$v`5BsŸ{»šÍDCPüW³GŒ-èÙR00DÁ…{Éí°ksKa[[J×R~_!dî– ‰Ãƒ× ¡£=˜7왎Á1^bÇk$Q3ˆnuçv­ü“ò|j¾¯KØ~¿xîÔ¯NÃp P¤ˆškRÊq$D‹±¡ÀˆÁ©Ž$ÛLà´ †àCJ´Ÿÿߤ}'Ç·g?ÁúSîW˳»vÀYܾ ݬTåq0TJ{~rª*(,†™B> î÷{×¢Õ£`Û&á>ßí³¨ƒ¹/Ü}:Y”2ÛD KƒmÅ­$m6Šø>¯àv þ(>Qá“sÞH‡¿¾ª‰!Pn+ò=!í#îõ|¸Ÿq4ŠLû„¤Â`™3<@´þ‚ÏÔkŒÜ´ùsþÈô·[;µ¶—ho:ˆFcZdìVÅkÒ¬s½ºƒ;“ôBPA˜†r¸øï»yõæ›<àl ÷ª­Þf²ÞF^‘Â@nŸß‰pfä›aÎÂÕ¶ A®a¾\™ÇüüWØ}gYüOä~£s÷€â{«Lô.?XŸ Ø]Ò[ïp3` ú“í@ÏÞÑÊ_ˆe¶WÕÕÔàèÅÆ¤ü²C’c€ÎÎgQÊ&µ1á Œ¬úŽÿÅl&1DMúvCN€Àåî}hHíû>î’HB&¯¦ƒœ^6­¶Ûtξ?Iþ´Db’8W1rÑ´G_Á‹f4UƒŸÒ£•ΈŸgPp7ò²wðÀ'Ù0x+z¤2ßø>µÔšl:X©vÛ1Ísù?~©‹Æ6é€ ½û²º]A?{¸^šýqÀ:㿆>xp!®:uÐ4uljÀØF‹B^%…j|°ïPïŸe4yÀSânóüAb ?@àïIBŽïp7ì´_ÖVJÀkàÍ/¤[?Ûùcq£À&Ã|× N3í&× rL7q€BB7Áo¸íÄC¤E²Áû˜*¨Š=Äágî÷àÉUAùÇíå4ÿ kx>ˆšŠ(\h}'`}(dü`Iù{Pÿ_þ"J‰ˆ¢¢"® ¦ýâ6?,¼‚y{õÉŒ`;çëÌ[yº(dÔ#b5ôYR`îÉHm„¤¬´ÁÏcºßì>ŒþûÜÀÏ©´^j §™Oéd‘ýH_”|GèPËØ>.ìsxÒïÞëæï˜«æMí@:²{Âl˜*]°Â&8ÎnÇMí?´Q£³úã¹~n›8ÇôBoðÿ3ž"aÂQF*+޳ oÁÇ]vÕß|ß7µ)’¦ï¼z(û د‡ö:LY?ì0›ºØØÂQĶ™}Ž™Ÿ‚'÷õæÑ×·C·¸êwÂD/ø‹uûÈüuÒQ$˜“Ù'ák Oo¡>b.ÆöŸåÚœ|=T¶Rj[J%ëÖo¼Š·þׂ¿VÔÊ>©²¨†dFC}ðÖææø&ŸV4ü7ú²o-*©7¶ÝòÕ lGåÁn< CX”˜š^õ,X¤ Ç4Œ™Ç¥ 3âl„æS(Ÿ}ØËØY$ä œû¾œkZ†´þG tæRm?áæbH’Ùz/Ôš‡»¨™Ç™Ô3ÉBf§MÚþ¯(XßæLx÷=¨d˜m(ó&„Æ"$ùCe–&O”>­_ðp5I-õ¥lØ"-°£&± ÎÂKÄ,²Ë5¨Ø·‘dßpÆóp5"ϳPôxÀ퀃sÂ@àYКeÔM ÿK=ÀCõj†p çõŠA&a°$¼€åa Äañ>09UÓ® >´À¾*IèûmÔÖ9™H¿sT—×¢Có&T%N_¦»c¡¶ý`{™§éE„ì!‰3ZÌ#Ñ÷½’d1¼G›¯ÔDTU⿽;­~ÁþéLË:}~£Ø:{H´ú×e —¿Ô÷i]„EÞR‰?P’°P4Àû·›‰Ç,µ›lr$BÈÉLÝÝ7fZ š›o¹30´…E°PZšß}Ùɲ0"¼…È$gÌêü~`úcöã6òHž=ŽžÕ}æ®Ìg Ÿ&Y7 ŽËzÃÖ׿úC$FG‰]J1O°0A3C.¨¨ÿ/Èb QMºgÏ…ýK§ØEUXÖ†’ö;ñ'ø–Ä÷dýS"t ; ó·¨}Z¹aþPÿx®„¤éÝÝé7–³Lñ'”UX~¿×ê~ÏGZÖj\5E·Xf]i·WMÕÓ­ÒM€½à<°þe#þ‚±‹†SeŽq\‘•Ey&qRáâ +òò×XÃ>ÉWðmT[ù\ºµÎ»3;ÚÑî¥w³máö¤íCŠ€˜Ot5ú`ïå…_¨ey!ñ£²rWûžñ_H£ÏUg⺸úµpGñ,×:ÉÇ»K9¸lpcSçÅj‡BB!‚BÓ®ükâÝ >£òqÉ?¯ñ) X„¹MŒŸ“ŒÎ>LÕ/c£?ÆGŽÉ¼È‚Ò(VŸÉ'Ë™¤¹Xëôàýæ®ðÚ” œ˜ësèIàgž%§šî$Ý€T\ ýüOôN¸…*XHúÍŸ@ócïsça‹Ñqri F™*ý™M‡i÷&˘ì瀞˜=¯b=0ïGÑCõõ°û1µUT´í\2äþ0ï€eeÂî48‰`!uຮ†CSÐ ódN (H‹ñ™Þ +;Š¥TRÇ¥œ@ÚFûE­ë‚dIѯ ÓU5BÆTMc_c}"aÄTÚïÎ8Û1Øã¬šJgòVe;þÖ ŒCPÄ$CPÁ1 °ÄL2Ã10ÍC,1 °ÄGðáË ÄÃ,1 ²DL4”Çña0CKˆŒÁ¹¸< HdÈ1g×a‡¡Ú&ßoíÛ¢J£( MR^[¶):Wb:ë9F(kc¡̱<Ìs Ø$éßZ‡Ö:˜Âý¯ê÷Š-öTUÑíû¾_7HÔà¥ýÔ•… ¤·a?:äü¢ œQ Îÿ×ôvåÉ“%b¶ÖäàI@¥'ï«”’°çüGß<›#þ\‚J0É/Ô8ôŠm ä.`cîÑàíW¿œ†_Óñ*"¢ý€púõ+?µ~EÎd,6€0öÓ:éP˜¢??èxú2èMrcÀàì\Ç™¼êwNÎîøŽV#8Á¹ïX/”}PgÁOL»B¹´»`ç¦%ãöJk^°éÈsp°,`v›þÿyÚvíB•/3™Ç<[[嬾XçuâI›ÎK˜ó`Ï}²j!Œ*[‹âÔ Zˆöl2¦ò£ø?=ZÏk}V„ÎölY«•ªV9ÌÛ1ÆLŒª7ÔÓź]N!3›Ž' Øýhè'C9݃à.юǰh3³·â?±Êi¥/özc÷çî!é]Ï'…W6“Lý[ ±¢…¶[Nòéˆßüˆ{ÏÔ% ˆ) *¨Ìjˆþì†ÚÂI@G-§DPKM$45K@Ôp‹:£ïŒH߈Œ¡IRDÄÐy’ŒCób«zqVrr]‹@?jxþäGa>Wz\Iug&º9§ù­Ù¶øÈ5&û˜˜1ŠNÉ0âf¤tL÷ø]þ 7ǯ’¦ð#óÊc Jle60›MŒ&„1ðäÅýãè«üYCT$2…ý_ÔñùãÄýY;ÇèÙðqv³ùrIê_¬M QÔVq|0bó*x«¾låRTòÀhdÂ2`êÁï>¥!„Ä©îI«ñ†=Îì! G0õ37´LAùJÛôiöx8ãÂJ# ¸7002æ;íù6ˆþ_¶€|æÖ1Ø@KOýE¾ŸõbÙ>`%" ðþƈª€+¿@M:áÆH ¿8™W©Oã³ý¦¥ B„Ó¿Ùfï‰ÔCî?Øh(ÍCUbœø×À5±‚&XÄM¦Gé°À‘íA™!œŸŒöá=…6& 3Ú ‡·yM#¸n¡þŒú”ذº(Y…œJa2Cù¿‡À)ð0ž‡H±(þ´Úg·´;þØ! ' b(LñÆbbbgIœg8 ‚bbbcd31ˆˆˆˆã‰’"61lhbI‰§›4â]SM%11T›e¥ Žc0% nï;‡ÿp&(¡rgjƒUÏÖØ¿&$1솵˜…¹Ø~÷=Ö4Ro›ôu1ç=¡?w;+_‘ÛÊ WÔ£å/.ÿè§$™„3A’†âÔoÐßöÿäÿ¿þÜÝGøÿoøc=ßè ¤¬¶þ‡ög¿?õuHqühø%Óªk è½a‚´ˆQ°C¬M`Å#–ZK-‡íÐh6ùðl‡â)ÁÆ5• ºº0L¿)ý²eCžuNû;¦RuÿÈ?Q»L†t¶ùuƒývnÿ)ßèõÒÓ÷’‘wÓëˆ \€øð9Êß^%‹ú¸å;X¤`ÄfüÛ02 œ;9ßFwÆ6Ãu–ó.n- ´SY¿¹™ dXŒÑVj#_#õÝóAñX˜š 3~Ô1Ò˜wåa‘q„ õ­œP—¦MR‡@¬\^mo¯¶Ò­@´£ú¿¶S©Pà d·=g¬võV‚ÃY¯Ó·çüŸŸñBIhjŸÞù?AŠ V+Uxñû~½|õë„èNsça¢”>íÍKs$‰·¤œO莨i´:UÛJk§QÂ1²³:3¨ùϧÌ!—]æÂ¦ç¼OæònfaƒÌÀ˜+/ 5תoÁüÌ’Ã78ípÂN—”ÛÂôÁåMÏH.½†È—•ß}ó©Ö{gºq'º zˉù:î~nßó<³³âbõEWéýÿ£¢>ˆVõÆž1YÆ*ªI$–Ziå^&üŒÓ4ÆØ$î!@ãžX–Ç/íjF Œº›©M¡.ت4HÀg K'»¶Ì+Š£:|ÀéM²ÍJš±oC ·³®;8½ÿëÇ í\·¼·p:â;¦¬á÷ãÙÀëBX™vý]Å~MGòûUUUUWŽƒàT·„üpùˆ*°ÌÝ„cÙMÒ ­è¼nÉÍØ#³I@7gcŒ¦ôéìbéÙ„ùMÞjªª Ç•vØï´>öOÇ2)Ñ'n¨Gz Õ%“®â-»‡f2J[®6 ’Æ3\bC)ÆI§&>pø·’%îgê‰þ?GËÊCÿšú o qÙ’aonG) )’èù¼Žòþ¾g1A‰ÌRÂß0«5ùÄsÏy¢r-ö ¦Š(’N«×§ÃUš$æ‰ó×ÐÌ× dz††f®b-î+`†úè{FÛé Á±¬ä6åú1ØóþŸÈ†N9ši3è(DN ¶ô~,Üì#lbZ¢lq?Fˆ~¯½Ã!¤U1¸9Ž!Áà>gÁþoeú§j|¿_ç ÜñÿOü?ÝêüЈ ëþñ¶¶}rb¨²ÇüIT‹¤pýŸÐÏÿ£ÿc[e’ù½0¦´ŸFy<ºÄÌÜîÌ/X0ßÙ¸cp¿Ë¾Ë7Ûô›ƒLiÞÀ}  ;ÿ°d hßX~56=û Ìã8ý/öžmvÒƒŒ ûHÜt~rÀÜÝ Wù7Á6ùŒ§|¼Ë3ã§×üæ¹Ð;5¥@𠙚wF‹§¹ì³ôùòf+Ü}\9»pÜÖ3n¹ñYþ‘bÛ îñßâóà£IǬº`åhu-ö¶43‹kÛäþŠúAdý+׎þ¿÷roÈ/ãÙËÎKߎLàÛ†:½»´¦þh¼ÚŸ¢?él£…ºæSáñ£|ü9ï—o)C\Æþ†½¿³\ø–>í¿‡Díj:tM²išÔ±nØÓ ® ‹K;zn±Û}ÿñȺLˆ¿=ùÔ~î;k„äûi2c´ÂƳ7[þêsL%ˆ§Þ1ذÀé9ÛíòŸæ¾[Št(ê>3/”ß0Œf]7¼/—‰Äg³îF–…±¿ÁÍ.«mÖ9Gò¥ÿFÈ´®µmí&éQ¡f°Ò1·^S6*ŠŽ*Â~öð$­ _eæòânê-ÉõðË•œ+fK[ñ H›íPµwO=ë¸|ü~㦲÷/Y½òkïÚ“C·á¼úŒ<¢÷g"<å û®ªµùêþNûQ¿¯ßßù¿G:­¨ó¦ÿKÛI“Tã&ý«Ù‹«Ùè;›êæßV¬àlè(tç??$Ó8•ˆÂýƒ,C™,`\Ÿ©àí¯–g¦ÇyâíÇdqh^ÉŠJ:IÀ¿§ªPª&&$îÏÖ­í1ˆÌèÒ­hÙs]­ÌÌ`0ɨb:5oR4éΓ™èóx[ÝÝÝÝÙÜýË»»—wowvõwwNñÏŽw<§ž˜éîñû`Îî~Ü펕ÙÝ×ÝÝ=ÝÝ­º·vh‡IЪ¢6§ªìa3;4XÝwB añ>;>S–;ÚîCÀõ ná ™Éz€½¨(Ç%Ë) ®§uÝKd+˜$$ç‚qˆa4´FævõïnÌK\A±ékÄ*¸âg¦.·.­A¸¹´SqÓÌ=!Ñ)$ó5{ÝÝÝÝÝÝÝÜá óºww6E§aA¦UÎ_fl5!FTJ©§/7¯xçOUk¾ïãØÞð^³ éǧˆÊqŒ{¸íÇp‚4¼î°eõOVÒÊJ ‰ È’ØPED¢ ’£×"NyÍÁ°ù€q‹ŠˆšÑÝØ¦H¦‰:pãú‹qï—C¡8ݾ¦iÍÜÛŽ×Ó‚q8o.3MÏÝûIüõʼxð¡T;Ä$cù“ù²cÐÉ|4áöpUÕÛ{Àý·>ŸŽN#vÌ¢bŽYUQQY–—ƺÓvÛ\çÇ¿Ã~¹ë¡lB©DÊÄù8kÒ¡˜¤ ZËTq4ówÍW6ú_U½1±Ûç+¼©@P˜©eùk—d(Yh¾Åý:7u°&d!¹ûÂQ¥Ã‹I#¢ˆs<âeæÉ·zQÓ 3‘—ì“N Æv–pv€¼ª¤ì‡wa1\xõ~ª¼«ÒS¡Ó’Å=$BØ@å·N»±B< ðâÌ8“t8qÎ8£Œ,À㊎,9ß2úßs7³»;ZC0ìžÈ~¥Âmµ×ÛÝÉ«:u8ê‡@¬`Q(í-ˆ†ó¾ð¯¬¥ ̈ãÚ ŠŽÂ©êš Þv‰|Xð³O6™Lᆵ,“!éǹ*„.g{•ÈŒ$ªÊ9Oh 0ö'ÛWñfœJêëGšws(¸8^q¶AÓ$ÕNɲfš¦æIBH´ÂòËšèoZ¯&™E’‰¸ì'a›ª† óHiMô‡ ó·„déN³Yl±AA„×3Y1>ŸW™ï;Ï2NváÃT>®®¾Ïä/Ñ¢»+ú=IÎ`¬ ‰™p’Œ$ HJ’ÊD,¤HPÇ®u‡ñG’xöÎP‰¥":`Òrn7XÁÚ; Çd É .÷–ßÙþûkoÀÌÚ[4‰ÐyÒ11ÀÓJÒbÑaðböí­Œ²¥\:IÍŒ0KfÊ<¬2"Hh€85µòº{ž¬ ¹n^ $)?è,‡;ðû°|`w ”EïÉϙŠ¡r¥·?;†’Ü0Åá£!aNÇXáÇòï¶Å>Ê‚½O£¶K±$úk2´ñ(;Þ `…ذœH}ñÄâ]âc†9qŒtå…~ÕgÛû{õØ… ã‹f{Ý8“'$Ž`A‚!LÎKn¡§. Žþ>SFˆ{Î)î ñã±ß‹=aÕ¤R«Û°aÄo߇Qy÷÷ïj‡k¹‡B"¼}yTæ…æ½gø&E9Ëö]á“Ú'¾v#'·µ™nìH 8žÅ‡l(h €¼@HõAœÙÐÎ5Yµ0IžÂµÞïXßl@~\ ;x‰±¢.ncs$Ò’þ¹ >ðoX…!=)ÊN)r0ØÂÑ% †ÅÂMæ²ñg0¡¤x„8æ=s"½LÌL³ øwï´$â>dSq7 ç‡9³ «TÞ¶«Ûõø£¦m Ó6³ ó™‚ÞFf»‘ç†m &Ÿœ“„I7)ÈGìέ­ž P†µ”ÓDy@öëcûš ¿r}ˆÅ‹ZÆÙOëîôxoܾ£ö†€¾]ßZÒo~DAð̽‘ýC—X5Xcø‰ÆôŸêónÁ€ÀÕ¡Ã÷úiþú²$OøÀëíÆ)Ž, ”?ñÙÜ)hˆ F›¦J@4X4d1!©Úxe^c‡ Ç…ÞG©'ÉýëÊð¢ 5’Ã…‚ZÄ9ÚqBÆ I˜Ä,£+@”ˆü=ËÞ¿ ß©õõÿËÓù4óà°TXSŠØv˶øÍ0Dð(z_¬)ûˆ;‡?rü8œG€4®7‘1U~0æb€I˜cRÓž/þÔxÄ ¥ú‹XAÀðŠ¨ˆúú s»µ¥•-J[mµ´nÐ>ô‡òSÀúvùû¸#…. 3)n[†c8ÉœòGðˆe^D8 ü]Ü/bÅWEsÔÐBà(ø9PÚÌÅFß^Æö£\ÃTLNØŠØø×Ë<+AZ_úüýVgÕ†}ãÏb/ócñßóçƒåWÎ}y÷ñUåßYÊç»)’„Yv14]}·ß+ïÎÒUÍe,°%šµ+ô|Xï¿=šJêi¯å¢Ë ë=`Tº"ôg†®÷S[ ÏÛyN†uÔ}Ÿ·áx¿Œ?Ÿ^„y{4ÀôË_Y©µòK õ4Ë®÷È=Mî~ ø úÖ’úçª<üÊñÛ„s}Ùµ~I~.=b½ù‘ðÇMɆ˜zñIå„X¢bø¿0ÇöZ+OW”ô쌰vÒ“÷ËÌ!¯îù¬}‹ãç»ú{ä"~íQõþŸ,x¬síxþ}=Í3®¯+IèÆ ÅÎAë7ÏÊa›œêk^ú±7²ç Î×,bìqŒþÐÅ™ÆÐvoìNÈûS)  ì»/7´Nðí^¨s‰¨ªµÁÐÒ#¨.ð¾loDß"h£Ìr!qý~åønñ89>oáùKñ{„ØùÏá·38hÞ¾?ËdöovƲ‘$Ô‡÷ —Ø:M?aú°íOÝÃù€S÷z~{ßð¾ÎïŸÚj’*—ø€¦ÃGëŸï󢦱©@(RBZP¥Q¤iT¡ @¨ƒó…À!™"¥C4@­ Û|gü¸ýís9«§æøg³óå7Áå B ”ìî“3LÄzˆŸùsß6ËËA# ôsj‰ Øÿè³èòšâ¾ØuH¤ä¥1šQPíŸnC»×ôóÏOô;¤¾ßl'(¾EÂ;åse Yç…ÌŸf1$ôîf„.ÆôsHÁ!å†3ë´ÔB+\dÄôŽZ–$ñn$› 4PH”ŠD…”"²Dû$ñ„Ó‘é uéÐr¼ùl:ç8Á£¾")¦‘B€÷@.°.`™Þm \53 öÛä@ï€ûcnm!íÆx®âß±G× öíÚà[afzëõ—·ŠÞK„ÂiUa67œ¿Ò9çz¼ÞuÌ™>¤) 3FmUu!ê$€;Ï,Y<6UHs$Œ˜H!˜fþ<Ó:†¼ßÏÙ^&žßy?â>ÕK?½=Àç£Pÿ&p€fצPL –Ršö0‘è¯uBû3 ”rÂÌOQ¡¡ëLÐÃRŸÕ9Zªï ÆÛãeúí¤é:R”•'IÓ6GDÕF¸´rR/³ý–u2I¤2UH©zÜl”\Tk3z²>CÞTÄ‘°ä,˜H©öo®¼lÉ5Ç¢ò#8”˜ë3úÙvͼ ;ÃHcy1„Çи_ÆLA¤"#>Oßõ´ßrƒônì8˜‡9”³|SZ†êZj`þÙï‹‘£tÝ'×S 7U»QÀå&H&Jª‰(‰Y|O#)þžÇÖ±ë×on¾¯_v˜´ÃºÎ˜ncÑsÍ‚MFŸÓÝ®ÅVíb€ûXÀGó€ÍàÈS$ˆÀ€ŸK è4Çpîüý R ŽñËN°c%r:[VffîH ™ËqýïÉëöüãÁs혵ŒåÂÚ‡·œf VßœJ—(´Û! ]¿/Õ:A˜6ƒIs³…@å¼äýŸ|²žˆ5CËõÇû±ýÏ%’Oî¿€ÿ¢ÑµÁ.¾9„ˆ’‡‰H6 b8UÈxáÁ5§˜h®pÔZÛQËŠä1¡Š¤j€É `d¢ª’¤?‡“/ëhà+Þý‡(‰½äqõ/Õ÷Aã#€ŽBR¼M€ z“ÐÉ ý§ý¢HK@ž<»]ÈÈgý&¡HHÈ%Th4þN¦äNÅïðO‰“à]²êTÑ$p·~|‰ƒQVYÒ=†P8„б¹Ê92b 5Û*þ¤S`>CÎn5çÐu 8@y£ð—|}°k"æVa 7Â/yìû}§13/K~¦"¹ÆHPV82’xH|Â2ú_ê={ K|‹Ñ=¤}O2‚ÞóÿoÀç^õÀbòC áÜQûü9x†ðë)¼°<…c—0ò5ûp²Àÿ*«Sÿ³îΉÃ>æT2gÂTÄ &žÏÖîÈÖjÞªÒVddAýOñÌZ·Ñôo´ºÉCÍQÿD‰”ó.AJ„ƒý%Y8!Ä)rQ]õ¶¬k®3DÐìýøk{¦c ¦›Œêš¼ìòñMG B/A6'.Lö  11ï…L ˜eeíLÀ þ¹hqŽ(„RNO†üŽö8ÒB™I"D32Åù˜U A%² bAz},º1±ZÞ½Hëæ´Zó†Ÿjšpò,EÚ”2Î$’B)E¶Äp߉L\²_Aßh\º(*«.ZòSM< >à^O ,žÑ½+N²çWÈbÈî8›Ò0eÒKcv–yOX }‡Ù¥NÝ-§Îù¡i>Å»²Fs€ÜÀ šçgBª¤¦& t €”8à'«%… ¤Â™2KJïβÐ<|ÑÔÔÓî`qWŽ_‘³è ·ƒ¾æì0‰ƒbÆP©Ó4¥$àZLŠ$Ó@;EÐÓ…ÀÌÍ2ä¦B.¯ ˆÇ•+éL(‚—“—O:ö/<ÇÊm4Qñ#¥ªy¬òN„ý—Bnwì&IV@èè@º^?HßPgƒÄ` Ÿ(óå·Ìó‡‡hø¹àD4Þƒ!é‰jŠ T:P„x¥ ê¼×(m”p;À” –ˆªi(¡ª@¯HyŒã'ˆÿ•IÄxˆ®^Õº~]Ï€kì½dÑ™ Jã4Á„ʼnK¼ ÐqLx'1CRÅ‘?hÉÕ‚ë¡>«Ewu‡’TšHwëí ­ux»»»m»§[ Òˆ“Í Dç(H‚ ïQÿ“R—•Û‹¹AT®*$h4Ù·?AÖ†’ aà†°ÑÝ"Ã0è/Víß õÕÉ:¹2Їüø>,ðæ@AM難QJd®€f%I‡Q였é&%ÐNKƒFÙÿœ 5ØP{ˆSè0})}¿˜4 Ðóœü¢Aò)MR^ŒŽHà‘ ‹…”̾‹‘@>ßÇ垇×Ç>)÷ÿŠèÐüé £!;Ïë}Oqk1nh¯:3mö7¸’Ë÷ß°˜vçY¾:IõP$º¢#1Òé$ ;òê¿åŸ^Ê‘ µØ)Èï 2å5%w ì@‘5?„u&´or˜dh(³''Ðòb¾áZWŠð,¡•d @‹H˜w]à §Ò?"¼çß¿Ìw= àlÀŸ·öØ!NP Õ Œ‰rJL+ð”ÿl©¡+IJR`l4…Œß=g²4#¤pœ•4ü 1'ðÝ“=Aªè|§i‡({Þa»$IM ÔФ$ à‡Èš(x€'™!'¥Sˆä†¡)b™  Aèã–ˆ  ,»HÞ{ãt¼„츧ÒÆ(ýß ^&žá1â¸ñS´=<Ÿw‰Ò£‘  —Az ˆðìóx†b*_ßf|uŽZ„oâÌa¡›S@C!ÛŒQDÄZoßøv>³í|Œ.‹šö‚óžöÜ C(§¸ÚFT‹åNÐoÍwЧóp9ð8w趃“ñ‘´‰øÓPá\}Ž®ò;Ð=N¾¯kup ìõ|óiG£ƒtËÎ1A J£8d+&° Ÿc6“½e§GÒ¼[in,iÅ?Ó°ïRû¶å{°Ô1®µ…Wëþ³À’mÀÜkÃŽ­=ÙÂ&‹#Í_Ð Ú¢>“¦„€É2ý“çßvž³ïoô9BÒBG_ÀIƒªQEë ¸„\ñN¿%~¢Cω9Œ1"ô$2ÂRƒY Èpÿ®Ù<ŸA*t @ç« ¬'Bo¨¤48HcþûBa#Ûàt_.¡OÖ¡¡Or§ç€Â!ôê~cOFDñ˜id겞ô_eOAI¢i!þâ׈ñ;ÌbYTX´ü_øým~wB€«E€[øÄ¶†“(þ=Cü·4ðŠk3 ‹R¥ÞX)ý`§ˆz?Ž]ãïÜp´nÕH€Ö8ÆI *d!¤"B—`ÊC- Œ#2“JL¤”¤Cw'ƒ’ÒÒD IµM4Ö&Ùćdí ¥|g"§Ó¦@ú£_êæGZxLZC3£ý‚ìv?°«ährâí¯§¿Ê÷z0S¥HNµì¬’–ämp£ ZÖªÑðDÍÂ4ü?¡Â{ ØAÙd(¥Áu×ßô{çäÎ/¶@Y)J‡Ò%‡TÜ0³`¦è}N0u,˜õïàñ}x„§ÑG £‡w$ ‰&¡Õová>Løùºå4’&… [ã|20D;Ûõ'² 2ÞC 뜸±çòì·¼a©ñÆì‡#‘“TABÚ+úgÒ¾ž£ŽÀ:ÀeœÉ‘ˆ­½Üçñè!ˆ>梼ÛU3ò;†("‡cÕ a2*È|ýL:öœF‚‚&bI¥X?4†d`6·")éØ550¦@”ï‰áÖ#Öã‘ ¤6¬ÅÌOà&Í3ᒙ X¸ŸP|äòÍÀ¦ÏQ¢(&(!l•ÓâYšÔjËPËÐ…#îᣌjaÒ`–#»!•çp‘1½qÀ~윑1Ù2alP vpúè`n™0Õsœ>=Uˆ¦Ï£`q{œÓ½fŒ5îK©yÓgåø_]\¾Àù‹áuó?+à«Øxæy.dx–4°$7·’^=â”hphç“°!œÕfPÃlÃ{Ã:‰àh0C3ÕQ,ÙBöç\kž´I öxž€È $´É&â…@žÈøC}w½²yC`óÿRŽ­$ñÉ"hP㈖š_Å—¤•Ä$tLøÐ2–þ)¹¨¯pÚ|Ä̉HÓkE0ðÎÎu‰I,vH`J`tn*JIr4(ë%úk”˜x* iL)¤Ä /3u/§`ò±‰i*Øh:l’]Ÿze¨´¶ á®iž¡)ª‚TÄÃ(v™ZïªÐ¥Ã…jÞ±ÊC3Yó°€ÒwÀø…Nº6®vê|/2)Ú“§RkúˆkÀ·äKÑ1Ì•Æ8.ººf±Ä¸dè“ϯ±£nBâb Å5‘p`yãJá9ãõ õ æ€?@§¯^ÐCÍ€h)VLW-ðnb=И¡¥X B¢¥†DOì ˜¦„\#+P†ì@\8{ÛÛT ’õ5(›q„d%z·Ò¼u;}à$Àó|Ï1ÙuòÀâGã?דä¥ÿ¯‘_  {¯Á`M5ƒ¼ß D(úã$Ÿ|;¯UêÎ !“dœ¤eóœp¦d ýpTcêŽ3àÇgöG`‹Ç!–Cô>~ŸhN΃ !‡ˆæ}ÝOæ¾¢ÙŠ0«~s¢¸³ûp Gü>÷ö¿ìb}qÈ)ûNà{d<m›êÈpÌNÀoÎi9†Šƒ÷¡ A HAWÜOÓ¼;·CÀC Gé£ 1¾ÏÖO ÚAdU3n4LGsóÓë€à~}ÜÐ9Hawgw›Dr0õ’’b(?Úæù"GÅÓ~þí݆W“ 9fQÑ0X4…ŸÅÛÛrÔ&Z@f8Ȇ„`š[…A—ùë²¥–5à&<_P†7Þ¡r*0:ãÿSš†Áþ(K÷Ý÷ Í$ƒò‚X](I%'â‡0d‘®@õÚ‹Øjt Pü°kØÊºˆ‡„•‰öŸº ÈkL`”Ú2&Ã’¥ú®¡ñ†°sH%ý6ß7ܣŴ9³èüÃ'áúmƒêKs&–„)h)¡¥¡ )( “l›hhž¡I22ÙŸ™•÷)¢ÓXB‘Õ xî9 öê‚}‡3_õÁ€ž„ Ûr‰="1û´ñ·nÃ^ÁGØ(àÌ´(½Þ‘ypmMb +ãŒhEÊ9AWÄè&¦Ä+„1Ü9âúM}øÜ¦Ây²j²§.DZè&3Û½ë-,LÐIL >bœæFžA™R ‚˜ØÇˆ"‚„¡h™˜H æ3@sC`` q‘2®a,¬.]Û ñŽR}‰¹ë…°á\94€È›?½ÐÐ^QGŽp¤2tÆ5róòˆ†\qåÑܧX©<ÿˆÚšÂOé¤qÐi+'êt Ýb¦Ü9*ÿ`Ž"‡}CÆ$ש骚ÀÓ^ÂöA€ˆˆµ]` ÖÊÕ- BDž’ST?~é¢Þˆl¦<ÁM|ª¤uîGR4‰WÆQÕ4M&š¤¦$&?D¨)Š™¾(ˆ’†‚‘<$Ä44 IDE%$CÄKK1#L@Ô$M0P@DÛœÈC‰#8çD›c–C€Ç}Ô¦,Éý³ÅØÕ/©@"O!Òûæˆä~3aª*ª«ø-y#¥ý$âV”çËâ%ï:n[V"9Iñ±E^`3!A@ ù&bÞæçèÎ?J¼W{–å”Oê•û¾—'þÙ‰h’†ŠÔÄ!LÒþÀ·2ýtÁñü]tAäæÂc‚„) B“ÝpÈùZ½ëà˜áÈrJçY(×0÷žxN b² éê¦*""Ü÷-UDDÕUEEUTÎÿWÄÕ iù=؆"—¾|*1“4Œ@`×<81LT~ìaÄ¡œ¹àûjÒcVpÍ Él3vš[G xÐìPn¢;ŒP8‹@ lá`¬;©×2ζ®Ýˆhˆ¤"xX¦Ž„’' @Ð#=±H‘8”J<Í´HÄ­T˜‡…DDHÔ’%UL¸˜†.M0ÞôH Ù5õà§œa ÕG®P~^xÀ4­(DÐG"5˜&C‡"âCÏža5ÊgÒ¤™ƒÌœu~ö6KÌÉ£æ„ÞI6ñ›Ú¶¿T;äÍ¢8 Žfx@OGHKóy(Ä85aåéãU(ÉÑ 'çÆƒ•ñ~‹ –ĽOîÙÔùç5‡ÍÚs m®÷¹»üzÑ«¾ÉÆ»fgÖgç×¶¶êmµ¼fM‰öØS†J=¬ ‰Ö³ÁÉ>ÍôI{äåàß¹8énî1£dJAâH{“Ð\>Ì.“àñðâ ‘žOKÙ1›G“<2…8„ß,¦"j•Ð×7E ™­ÍÍìå„”a‡àÓE/´?-B…*4Œžã±Lëï÷Äqò'S¤(#!Äh u¾s¢êÚ5âØä Ž&$ ˆkêØ „·xœM"zÀjøa1ËÙ0}³»ŠØ8ñÀnX¨¢d hL€¤%É!¦úË®œO76…=;fn’,6€ÙhQË|V’Á­_õL @¢BÍŒ…ˆ¨Ú˜Ú@ðÈ׊KN:Îî¼]Üβ[Ì€ª$" „L SÁáôït™!ÉP‘_ ðÆ-…™Œ„²(“GÜšZY°4líÞd%+°h¡"$°M ¤ùÈv¹ø‘'gÉO"PðÙöBüˆ~$êHQÄA>ÜE‚ð'¹9‘‰99oWÇOõl21Œðɧ ÚÑ"LÃú÷Írqß½ÅÍYž¾‚L5û!7Œ|V&Ö¶dãgCOü>H*QSŽúú1Ú8”•rAªÜ!«ù¨ž(}ÔÑÈ©ÐP±£v@~ aÛXkë|Ú£2V\[d‚mv7ñhÚ€—mø-aÑp™ÐŒùëþ˲]LZªý¬¯ãe]åÒšº¨mdFÊÅ•/U´b£tÍÇOm¾LŽî3x"͉²¢5¡»øúã~5É œ–¶ðoìa!<‚þD7ݓēdPxBß&·Ø¨gYc È\k“¯Ð,?G†8)üÿïØ?'`/w|Ò== 4EÖJrkÍÛ4ç“x¿ª©Ú½.®î­ã0”5 þˆo?ùÐÎOùàônØÏ5äo\ Ép'c HsÖj¢ªñyöÂðüé„_`{_`t“aµB+¨™â¼@€Õ·Sèõ|ØÔU–@€â.hhjƒŸ8¹ñ3ËÑGív=„î Ò«Å”»ß¸kgwú1½^: ùÿ¼1œg8%LµP11]DÅ6 ,]­K®q°‡5Ž(cêJP;zíú_*@‚^5 éKÙ.Bg2Õ4l‘–( š‘Ö鄬hÊf’‡§G€(`ଠè%0˜0Ž4¤”  p†”V """Q B!‰ñ½i߇‘ì3”qöa0IDŸv4Èãp†‚U3 ‹ ”43÷ aïëÃí;æû;fM 0ß×b¦¸ƒ @ɬ¹ÀÃxÂC3æ!¤@~6ÍÊB€BÊûb,<ˆT‡ñ²JÀÊÙ4cY‚ öHŸH½™‚…¶z„œâ“C³¨$#øà4e>·åoÔa0Nülep7·D;ÑBÚF€|‡Â„šD)c}Í2ûä•:G‰ÞàÜJQgô |ÙD×ðýìîÏÜã¢[>V«>³DèØ5`¨rÍÞ§ÈÙâÖÙQTBÙ>±1'(ÈšLAE%N(–a(K®ùa·†“`¼Õ’¢E5`")&GüLtÆÀƤ˜ 7 ì ô>G§Wûpz¸‡¯õýœüî¥>­‡»Sj›òíä½üWÖtÄ{ÄÄmAÐh?7»fiJ¯$,QàÑu¾¬p| C²D›©Š%ˆ RýRHq¼è…DîqõkC´(ˆ»ò‡õS‹%†md³ÖÒ|ĸm&ÏM§h0$‡€`Œ9ùòaJ(I`¢&a‰þ˜@Çu@# —’uÒ&ˆªD’¬ý¾Ô´ýØ}IÙÇi …J_܆ڒOÛp¥‚f ™^Ï?˜ÑÙ€˜(0À~íJh)çàÏI;±òO‡_‡n¿E×{®6ìnÝÌùm>Y³EÚÝ·ÌÚî×+jÚ°˜2 Gãä¡‘ìAê˜ô©ûüAí㿨îW\ŧ9CëHó¦ãjª0D±¸Wð¼ð“Á!õ±ú¿Eû&2Ï,b˜Y… B ¦QJI%@‰ˆNä5Gy'êƒôì{Œ>[‡i£RLæ¿-Œ.4×ÖÝ;mfÈQ!³ÜwaÞÊ0ͬó,òua‰¿ju'E8† © 8Ú‡Ô~.Ô«‡ðó\qýí÷è=!ø§ÏÏ€ìÈq ûk—Hô0 ~ǯ"zL‚|†? C„íÔ&H©H¢HïŒ (€É³¦@‘T4TE4:™õ…™+_,'3¬„UHAv”‡md¹YvU‰”ÐPÄv‡`î’}œmÍ %QbÁý<O³p鿨ZQÅSÜ‚ÛIQ"W%9ÿY \— ÿ« zQBw-á×­cÉãÍ©1 2™öHð;[ý~ý=¶´æýx®šóçÍ3å|hÞ!êÞ~7’#ä»Yÿ<4/Ó½tÉ )é—“öf´O3Ç娠Ӈž,Ñ®]äbŸñ"›'ìý†¯­çøFÑñµânéÙñÃ訧ÄV« ·-+€T, í®8ç¤`ï©&/™Be¶Ñ}ƒÆI1•r $Ä)–ª¦Ä×!)5ši5¯›ì9¢fíØÔS"Ó´|Q÷ÕðQÞÿ ~Ôß« ýWóú¹³o#ñ{ì‘_ÅöÑÿeö”/ÜÎû÷×ñüœÃ>C½_Ùƒ²,ò_Ãû•ÌŠ&~P”/©6:Y”ž÷EÈK:•š¾ò¦L½î žPZ²{陸éó8]Dùu㉹§P¿bfùì„äÔN\0 ;| s• ðŽ·~Œ“jC8är¸x:襗©s¢Ñ箽 âvkªõ/Ód¢ü­h6_ ä×HfvÍ(`{Ï™.„ K‘!Œ30©¡ÊSÒ“–C³=™ÃÔߎuŒÑ·”wdî›CÁ!ÝìƒCóOá1 ƒÁ3 g'úÙ~!ª€ü‹ iá¡‚á3¦ãÎh²šœÚšíBJ ô, Wr’o.ñ]N»w7çß 4‹Ù˜‹zÏcÄŒ_¹ùõªØùÈY±ŒÓån4ìCÜôä”ú?0Çé?üò¿|HŽjf  ¾¢Ð HŸÅñãm“0ÌÕ›^í]rÌÍÕËc«]¦ÙæZH©}e•(á·Ô3Œš0²¾óà“ÊvNKå “Ûj5-–ËaÃiV”ecOnMx̤KRݪL“B/|u¸›Ð3š¹—)h†uÆyjHÉýþ/Vßmyô-£v7ð ‘ïeÍ÷5Üõ`{óNó² fH³ˆu¢Baëdàñ4GS'Ž~Y6”Úç*qž…¤œ …0*0;úNÎûì¥DïðÐcp, ¨xLĦóëiã3~Ï›,Å‚j‰)Ëddwï2Ýà®îZ+Æ ¤X.÷0˜á=ጔÛßW=t@ÂxgUž1øü¸(Ð=bYÁ HõzXŹúž5Ùºâ0dÍ«Rd&nVDìÄŸ†W^‘ÖtVޡ׸Ñç«Â\óp7„5@~‘¾dC1‰€õÿO\Éu#`ï¶*<²eë~&¶µ­!¾Ó2TÛµ á”á$òfæ9/²nì'‘&Špüm¼ÂwÂy{'Žç}´0Óe‹b1Db Ðáe©RQ Áç–Úšö›ñ+i.1¼æDš7 ƒ`pJ$$$”3”Ö»æ =Mû8D¬Ù¬&ÐîOoí8ÐU5$ÒNÆäÝÁƲŽ&:áJÏn¦zñ^“Ù°½üqp]ã€u.¸:öãÕº² b²Dšô÷¦ÖÞ:۳虽í‰@V[#)s™VuÍ8ÄUàÙu¢ S£.‡Á'YÀ"HúêV|ú;húRÄèçÅ,cÙ¯z8o{'ÅÐjsÆDC|,aÇ;RC ×ç”Úö é´Nn+…‚›YFÀBú䦯ˆÁ ¸LÜùQW“Õ?V ©Ï¡A×&ÖCH@Êì¤&M+5w²W3LÙ‰7ˆd7lã…›¤& ”HÂs‡FSH ñä£[¸îÉ9L½Àî®éà 冚øŒLÕ¨o½“ËâfvYܼm.èJZñnל¼%d4’ümŸ÷$;çZ‰¯,3È÷ÎÑ177ÔÀ;ø¡E´å;fkÖ›úp?Y25ׯÜi_L6ï°Cz€ü£Žú&rœ³°„Ýa;É|æ°Ä ˜›û ߯é”ÿÁ{ét©åÉëx’°é›ÉÙ–hs8B¡Ò w³:LM£¥c¡6Éêa¦î‚À¡˜{\nÀ8Ewcè]Õ‡†œMõg—@N·).ò9‚ uFO9dÚó½†Ô»Ž<ˆQ…;Mûì ÁêÍ@Ø;µÏBEé Æ7¡…*èà]dÄóÀvÈxGÉè ‹¯v » æzÕ1L0#»Ž“‰`ØŽ–è3Úìq©ri’m”DÚö=&&£`lòw÷ã\ÍnYÀ♞û›ˆ 96…áØÜô¡©#^0õæûž”ÐOs¨wõ'k }šŒ<³¯ è2f˜`§vÉ1<¤Ý§ŒžRIߺ:»Sma˵ٿoY[õ\µ?×tK$×$´ÉˆºjÕ¸"—“ýb!&Ä5gnÙ5ŠÆQ›HlȰQf©ñípœ‚CË ËˆŒ¾nÎßÎCßEdóÞ‹ Í!Á„% ÄÇ “ƒ³¤÷æ ½ M¶{Û!áßËø©œäÁ× Ì‚³Ët¿m_6·ÏÖÈ`·@v¾òÜçLV 5†SR‡f´f«U~Ûî«´ÒmÁ»(jåß°dõ¾é“ä0˜¢&mjJЂЩ#ê åë¶¶aøäÄC ¹VŠ`•*Û(RŒQOó5‹Å©6ØÃ_€ñ·xYÁpVas(£‘(؈@Øïè燅N=c‘\IÖX­#ïÞ$A¯„'› ‰ä˜Â°Ä’vÚ„4$yøvö0Í鯮øðn9m²ÿ#|Ãë÷Œ=ã߃¤`|·ŒDÐ,Ývø† ¶–Z:ó› ¤Íþc;c;Ôn}¿Iãueý<«I¾áùƒ²sì#$cßɘÄGËü66½Œã!Ï«çÚFf#éò΀»â,q§ã¡þC5úå›ç„Î3\ëιDñ¾£ß7Ÿ•žl(³Ï}Rvå¾pÇ‘óØúw‘鎧g<‡ ¬ºÙòï³9LÍNïþ›\=íFn¨ËK²YGy,0Êù>|â‚ÀÛ†Däó:½–WFÏD_GÕñ_qòƼ)8“˜°ç¹8ÕÉ®dà”‰ª_4 ‰Àl2(ô”é&Ðjˆ€Jƒ']ÀnÙÁŒkl„ÄaƒorƒÄX1GvJr5%cÆÊ† BŒˆ•c4º"4šC@šp„èh ™ÆJFF@4†“@P˜%` 3ŠYtTÆ–”Õ#AE,Bºš[&Ml›eÒPÿ^ùë$Î?ïÑÞ‡ÞÓè7 cy±„Óé¯Ëˉè¶<ùû•æûy*>x''äCÉæÏÙ³×Æm`^ßáV‡‚å³Ñ™¦Ù¿‡ÿôÇ,Ü)íz†îûŠ”ª¯®µ°[[‰^k €l‰:š ¶ÄË…Ù7£É`ÓxaÊš/`W"qy3bÆ·V»)5¤ÙÚV„Œ€²~áHãÙ¨êáŠj"fÕ¹D÷û2‡ˆ¡¹|V\€tQííNÔØæà(t󾹺M‚Žþ0>”$‚o´ ô!L|­Ä¤Z ¤b?Ø€ €„)"Bd%„dˆf ¡¢!J!?bša€'¤¡UDU@¼„é¹2BR§REF@õza$MOîG*x{÷…ßa*dÃ…ö@?º¦|?Œ~(÷¼¶ •{Íxú "¡@`’‚Âa0àè`Ÿ¡5ñ à«Äüxép¦á'Ò šù¸å t‰‘8xd>Cº2B½üIxˆ «_7›!ˆt !9à§¡’ñzCìdô}Žëëˆõ¢¸…6y³%dt€¡YGþ† 1ëR„ˆ˜Z)(i èhñÿp2€š fMÐê[ìh£÷Ÿ{.9ÏC‹Ä.ÖŸëXy¬&91öC˦¯a”FD4¼o¡Â%‰Zº ÄS8’æ{ûÚ–6í;¤7ìb†^;qOIÐÿ¿ã«~ï§1â-‚Ю ›Ks޶™²6žPï¢ÈôPväσdNµ˜|->,)ð²žy¡Æžô®éš6ðpá Ûâ˜-…îx³B¤â‘¦û8Õ<[Õ•î‰äÎXs@õÑ ›hŸn{8Œáøu2C9§ßoêÑ“ 5ß,lã®JÞÕí_ÛzcÅ.GYHPéƒâL¿Iñ«cÊt¤¨|'úÖݽ.~¿pٌ釳†Ë¤7^O-MÚ§w ÍH^8âé [ƒë»PÞÀªY—Ó±¨©ÚÏnÅü®ýù£Qõ6Òd'@H'¡ƒï0ïã¾<]ļ½e¨åÃÇa»‹…nD2ú݉è½ÏPÞÿGã×ó²´¶‡dð:üü†ùcªç|Æš^håN‚^züyC˜‚³¢ïSh^I”P€Ñ-Ë,á0&‡ w.¼øC !êÇþ>×ðï° ;x³Ø<Þ„¡dë/ÜoP Ê*'7à –×T‰ ØHAr¦&’X"ãEGøCé'¼ðÂÿÇ‚ ·C»ÔyÎ)ÑláI‹>s•¹ùàI ‰Uñókó B’±iÌúy4rnA áÄœˆSÖØQ^©¸ÚR‘JP :$¾eÀœMA:hwj ÊG°Q×phhŠ:Ïö™;ATìSyè4Aé⤆@õ‰*,‹0PRîèŠ ]2”3K5Ð!¤WˆðÄÿ¹ÒAý y¾n÷¤DI¥%´ ßba¹^XâÝh „Ü]øw»Ì`ú¸®Dsœ­ A4ªrÞE,"ãÓ*¾>n@y¼D, ) ÉOt å $Ÿ“$Á)¿Paî¶–¡cç.ÈDAÝF8<âv^’ Œ†"•”é-ɺÇKsµEµ—H‚q“û„À¦Á»°ý]Á¶v=ªØZrÀGÖÎ ¨‰!OþpÞ†œäÀƨÖ!†ƒ=<®?¨5¤ôuò>µ!HrÿD¦¢¶Äzr¼Rš˜wCG™}±9·l;R'™Ø&DøRQ¤¡×–”U”R”š3‰V\ðøO :Ei²ƒì_ç¾÷ß¾?çyÝæ×œçâÛÍó¼ó}óØø1§ã·!„Ô™Ûä¹0åõ&ŸÒO ëÜøpNc‹;UÓm†ºíÙJs‚² VhkËiÓJgŽQ• æ®Áå­Ãf¥‚I!b1&g¨d]€â‡å¯>)T%Tµ ÈlÂ!ê ]Xˆ¾¤â G (® ªLnxB þˆè„4`q0BM&Wëà‚¹ù Eû˪RÜúj¸ù{)çÏ&?gx<‘Ñ8’E00Á$“óp‚RB¢¥’)‚VeÈŽ@À?Â<Níy¼ÛDÁ¿ñ>Ÿ[‰ÔLDzÎï žßêØâI@'oø>ÉëæjÉê›e›&q¬0ïû'}¬:÷¦à›<¾ÔÞyÕ»ô†ç-? ß&ÿÄ—àœ6œñË“À$ò¡]S€ÐOÊŒÿXªÅ幆Q;êEG(¯Î"LÈßCI^@‘TfÈ@À0úiûñû9¦yËDÿG;'ý0Þ~SS|¯•÷å´…6f¼5#!üEÕ¦§ §Ÿ³Žï G¬}¶‡ý}“èW|Êç¿àa?NÇÒªŠâ okœ³ñ‘µzð™‘ðb[ã|¬1;@W¾¼7FJû6c×QFRkû3Î~0›u‹&oÄbmåðø)¤ìî`†oDÔ¿z;J}&Ι¤÷îÏÁÙ“(y? y=‡Ã•7{—Œl(’rÂðR¦þDZêuÑðâ#ë¹®óß“^þ~5•í¾«Må_‘‡µ(»ãu¼L’ÏnZ}† eü (!ƒúŒzHÑÔhÁ¼0ç‘ÛZ#ï£9ÄxKFT¼M4Ô—G峋ÙyõêjœØrEâ¬g˜Z/ûA?»í;üÔ-÷©¡;û1ö&cÊœq˜?@™6r:jˆþÈAñØÛ‘i¡œÎÎå^1 ØƒøT›ú@?ÏmȈUàp WÑŽLbZQâ(ï!—AA64G*å m±2ìvš8HHPÞ°>?  Xk¦PòfIB‹ÑÀHa`òå=Íh‘çåο~9~{M›‘´-ÛF€ØÓ>?a£tŠ( !MÜ7èsCÈÌé:áO­ç + hð É•—tSËÒvå}ÄQðë>.E“ƒø\ÓM#¿8C9d»L¸TF(Èlnýh˜èD`"b|wŽ”TÄĈxWLvhÐr†|Æêóœ÷†b4cdó/v_:ˆe$fJ=(¡ëC`¡)p€e¹ëQxÍ€Á1'|B`SU‡¼C÷¨šstQr¨zp$æUTE€#ã¶ MæNóyè.‚©@V™fZHfIg+ÍCD4N^…ȉ*Šá2I§GÐ3Ïr˜„$P¤2)=¨wú>y#È›.8;ð98ùKÄ@¤ˆaT€Æ;r‡4­Á#2D÷ÒœEÙL,¨rô:A£ \|âtä— )ŒX™C°‡B‚$Ç ÎrMÌ’˜!`ÉC‚s*8 %ccgkb2X„ñ?)'÷¤>©4@P~‘dñƒòØÊ ŒIFüƒâ¼Ÿ‰jŽÆMOÈ2®Žž Ü °EâÆ@à.aÒÏS>"÷SÞ +¾òo ¨æ†© ¤»Øo#½Èbl˜°`8cõf/­Ùú¾]ï€ú¾íhéh¥¬‚0mÿd†ÿRG$À¥*äûëþFx%%þ(õI‘Óaà‡ßÌ¡ÀöÞHU&Iˆ+_2äpƒLPLE 3ÍŽ&)„fyO0aŽ–$¶CXJch`KεȎ^{.1‹i¥Z˜O!ŒŒ pŠ<`^c- ]«ƒÂãLáÐ}]ÏHпïǾ¸/žEò=J¾¥hä®$¤$jP½ç1Ì´©¿†ÊöbCíóCÂqøF>>Yè~Ùä²Ô3é:1BD#ˆM Ï`OE½$ð$èžMg3¤’©˨‘Éd—˜‚½ÃÂ^BØ ïõKü41 §’D{’ ÇÙõa8Bi‚E'¼2pÕ+M"4%)@1…4ÜÀi‰Á°¥ 4"Á´°NÉ‚(Ji„hc0a˜Mb”tiÐæ¢R”4çpt¥ÉÒdh°oªõu»³“Öj†#yýuæ·BßüëÃ¥²LšÉ"ÉQCLG`X™‡^ K“/òœ¢Ÿêˆ¨¥¢‘&õ°ÏoŸ¾[FÌ7å“Þ”gV(¢ÈFR óÙß}È?g~üùb•)R/k·'Ë`Ræ$ùèÖYI)%±}Grúûhó7´(WjCÔ9ÖDBiù$¢I?»…9 ÚÃÍ|Øìºò®Žœ4ŸÖ¿E7‰„8áSÌÅTE IAܳ±‘Ýý˜ä&i¹m‚¿Å³€‹ª~Èe¶b¤§ä jš|¢j ÂaMg¸Œl63…Ða>ò?ˆCÛ®›[àÃ߃$†8€úzG—g£Dð;ÖRw’8Â@°qx~ßOB°øÎsÄ~þ6䘉”]Px¦_ÛñjœW"XSY¦*>¯ŽSäcÀr âÁéŒÑõ^»Á“”/˜‡Ú¶æJY’/؇ó!Îýß‚ÐàR˜˜L‚“뀋zTô©ÄGWP°¡AÆAÁÞ0AýO0S’’m^¸ ¸‚1„‹G–Ê}FØCšñqQ8[ü„Î"6ñ<  î”ûÕŸRÈR–„4:D)þxB73¡••¢…‚oˆöÛ$4÷)ù‰+4® JÂÉ»Z2{!1 ús¢jSVã31’c ÁCþæUBé¢X°`ãQ‡t³d'¾ÐµG Îý{û÷¢ÿ`z° »X;Šñ°]º`Ð…D d ‚I€ýÃDLìQD‘`‡ž¢‡$\ þÆu4Lh3¡ŒQ4à8ƒæC橬ˆž«§7èÜžî!Ð0=~à5ì†%j² õÓN",‰% »<À:B¦ù_D©¥÷F!ZÒß¶ç êF“‚ŸÁ€Ç¯ sù¿.©¢¼ÙÄ‚o„û ÉîL9¸B% /BU3XNQ¬Šnãb̦ö8é½ÉE};a'˜sZw+€‘CŸiñ™™FÚ2­öCÆzçË=™ï©O4Ó†YÖ$Âg]ÈhòÏ ò–ØåÄ›dH16Dõ¤Àd Æ­ŸœþhYûÄçve4•ùÄ‘× uBPÐ44ú€ãÌ%É$“ PPÑ S4•IFeÊÁ2aCt.8ÆXÈ<‰Fª*˜E¡¤ØAøì%7ïü_9}ƒæŒQLDE˜1$•4]7õB8Tæ3õÃä—¬þŒˆ;FØp„M @PÈÑ $ÐÐPʧ‰"P B˜ "b‰fJÕi"bÙ±'–ˆfƒœÂŠnp1Œ˜©N’Úw „ÐB_Ÿ‡#™ñÚ¹‘Á ÏБЕ¦v’‚”¤¶ …ƒƒ=cŒ­zŽpLLyû'q@Ýñ4XÄÿˆÏ`SRöp½ÌÁ XóLÐ m ÍN•YŽïYlïÆ°,›ñ!CA¸Ó.çdƒ†®$>k”ˆt 9õs˨;臓#ÝÈG”)ÅaUTD«¼ISq¸€%ƒ&8œ@ƒ›˜a9`ú@ØWëÞÊZœy~äæd! wg`ùÙóÆ]¤Hb"¢¥?¨L›n0k¨Jȳ"’ Që¥%*îèPýòƒõÂ…EªúáV¤<1Ãßã°&ø‰V©UhJ"Ua‘BŠ*”)… :Z¥B$ &R• $ªEbP)hZ h¥fR`B (‰P¥¤ i@¢€ ¥ˆ(Z¦Bh„¥JibE‰¨‚‘h€X–‰¦R% JAˆ¡…)¡Jˆ¡ (B”Z„"•) (Jdj†„(F%@¤ D)&J©Je¦B!"@)(@‚R€ ”…( Z `¦a\ÀÊ>öÅ*4­ AV}¢§_%æÜ†ãUGr‰ÐÀ”ò2鈉BœCH›e¦ËØìë¬$E-H„Škú JCKKÑò /8;¸d î8`àfüÉqާ—£Ão€U$@!@\ _L‰ÁÔ–È÷N@8$ࡼHm¦€žYäXÙ “û ½Ê$&y:¬1€eß~¨(Š!!š)–’ˆ¨ ˆf"%© ßa¢ !¦ÙçNèÞ¯©Ü ç`RhI=^Éš""µÐ@èQÏ…ƒ›á™»}˜@ù‚DCz{Íèà@à”)€ò–„‚ã wø‰4BË Y{¦Ñ ¤=)3ñÛŠqB‚`ØœA‚ DàÑÛ÷ʤ¤·® MFÉÒS„9˜ Šc ©méx:*=ñ$“ É!$Ø :·¹/Îö¥§Í YçáøNA:<0v éþï†,Ä€­´&KGŒL*6cÛÎÂd†ºöKú]Êßï6)—»;½‚Œ!„Ô` ‹§`i6íRqÃn¬jvÃÔ—hùÂ~ß´ó‡ß³Ú‰Zj¡†vä«ì}¯Î‡ænšöZk»s¼ ãn© £{k¹NöRe²_gFlƒâÚ[cb¾ l#Cšó©÷29ÎgÇ2~ž¥µ(ª£P±EÁÓ23a‚¨vZ‚µ¬ÓMZgšã‰ q #°ƒÌaÉš¹§'Ô|ïpžtõ+ ¦ïÄ›ñïâtÐÞuî¤Dø9LÔ¿ÉÔ?}ô"¤*”=Æ=’8‰¸@á™ GÈ·!&Nh¢”¡I`•ë€;Ä;Äqä*М€49MJ2hq œºˆü§ãݸ~c(öÉ?™'ј$eKâœs#*z425ÉMqª É ª½ÒŸÏ|¥³¬<âð¹ƒ<Ÿï{EÿA€¯¹=[È«%E§„Âo=dßXm©¾Û[ºáuwY26@üÙ@œ ºèà0™ƒ(·°{Ç@îŒJzé!g)aiÀûãǤ<|újgZW¸³='aOGrèO¸‘O‘׆R1¤ !“9œá:4]O?Úo9‚R×àÈ?Ì$ aô(h’@CyF’Ù5%MHtºq(ŒÄr÷¡¨sDb»¢hÒ÷/aìî]ê›$7ÈzMÉw-»UÿPç(ß Úiâ´vh± t‚xwww­&µ§1@þz¹€Ù"ýNŒ‚lÉ€Mü‡è”Çׄ‰`Ïóg2“}T‘‰ML¡‚%”úÌ` ˆˆ‰ó Ââò–‰ (iÊGV¡Cúà?¯±ø÷ˆ1ee ì±õØ4¾åØèE¶ Û X…¤Ö1^-û»ß”ÇϰºÞH›¹>/Rà R‡rþ>ðÁWÉb=°à²ŸÈùñ”Tù"übþ{žæ€â`fÁT›ÀÀ£oŽuôyC(ÑÓ– ‰Ù0£œ„2ëID‰¸ò6†ÃF’&‰$Cõn†·xНÒ^d9QOèÀüæ0ŸªÆØIOØF€(J‚‘)"hh92Pɱ€4EDJ˜‘ KB?æG‚ N½qžÎüùM27=yøÏ_À2ÄDÿ>gk )`˜6Ø0aL áî8AìRÓ@4ó½?X}@ñŸÂ1¢ l+úBä<:'@>¸T)iAôH®â% Œ]öèrG—'Ò=Whvà2¬/tú_³¶CXÅD„’“ǽÂ%Óân#£«U!HPU‚"¯iiû¹ŽiòÀéõ=p~ã*„Y…É1æïy~42'OCèÐ{Ϧ^F÷W?Üçk JÄKÄ0üç—°øB\ãb87ÀâCŠ'b" ¨ àœ €”D¡2 hšØvžòݪœׂÉÉ=ñˆ4Œ¦N§y¦î+S%1r ]ü¸Å?,ëõ†¡™ÔF³ü r”ôÀ¿3)ð{dß,Bÿ}ä9çeMzaɲuœoÆ–·¦SR`E y?ÏÌr])F¾ØOC)Â¥ Z )°iB—Z ñ£¬$Ëa½î?äaàé=ç$Õ}ß]n’°ÝËs,ž^ïżS=€ë‰Ï]ºöÀíц‰ó˜r¦RÔæ„1kïTܾ–C´ïÂò#·ó®žr÷÷ÃB|°ó0‡¥äpž0q‘€´CÀ0;(=Ç”ÅU>[yÁÜ mñ²´‡¨—õÒ4°ÙŸ=‚€dC-+5²{dì’„b ˆiJP„q‰>É÷ößfNóŠsK™´$û•}í:ú b((³'¯©Û^×é¬ê˜¦5†ØMØâŠ;kÑäèL¬ª $=ð'¬1ðù‚O}VCxd‰X·$ž.”%䈷Oëà?S²ðÀ„ðžHž Êp–+¸aÉU½®-ùœxÑ áî||þâ†=ôÿ„ÐäËåðpr’ÿO}É›ö7ÑÃ)¬ÈŒÊ®Aˆ‰±­°©3¼Û|St´ÁXìgàÒôÌÉ ½q5aåPÚ†Ä_ûØ-š¤[›@ºÎ Ä2Dzµ-ì¼Ù©?‘ãfA¿e‘®¥Î1§ÔÔăˆ.ëéj (ú$Q=~ܽáZ¢TéKÑÆ˜•J–iªÀ¾ølU÷¸Œ®œÈ–Ú:•(M‘YæED¹ ¼yû®ÞÙ…´¥ãÚK|Aƒ#²À™¥á°¼ÁÆù³ЀÍíÊ@HñNØg îžAëc»v…šŸ²{Ëy„4¤3}?N’ej>ô2$'vµo¢ymÓv;Ù²kúE5H]æ˜{ìLܤ›¹Ú0̽s@î{Y6Øâ~É£è‘#·6>0~ ÃÉÀRsÑ?X|4Ë QR"Ju8{p ûpJÁ A‹ J1@C-€íLŠ­òÔD{Éb ±¾´«üÙý±ë–gPÆÌlA»æâgÎuñè8…%©Ð{$p]èh«”ÓÑÐ…¡‰ UO÷G¯'w8‡&'7æ‹r2r1$sDC÷Ÿš!Óò…ëù>=õr°Áí ÛÈ ƒƒÁ-Z¶Rʈ28tñàIqIйÒQa3Ó8×úüéádüë ”±±åÃÀ鍯Ãï«ë¦<xÕ$AÇüÁÔôu‰WÉT¥FŠ¥¤?LòTÌD´ H˜•Ì)ûžÄC|ÏTlØ1f‘4!ÅDÒTN¦Àˆdÿ#°Á%pÃJTb$2’È "2üC#LÒJ—­)0RN †ê!Å“NAF&\Že’³Ì@³¯Àû¾Ïi¼´ŽØibJ 8@éÚ4}&ðóú°â-#ERĤE-.Ù "&¢¨R‰bª@ˆ¥Ã€( ¦JHe B’H<—@R±(ÄJÁ IT| q JR´°Q51ÈQ"A$ÀDH¬‘A¤Ð!$ÌL’Ä •P53HÁØÒ¡LIIB¤„­LEd™ˆ¥h‰ˆ"€ZšV!)J ¨)>SPÜB¬?Že“êv&—ˆÁë÷~Ûš"ˆñšŒ‡Ø…†IƒØò¤½|£Ÿq‘}~dtdvp$(„ÃÑ>Ç»>Á€»ŸxóèN}¦øN,‚½w Á¾C šc$ì¦2…êB§˜÷<ÿD+ùá_$xo¶Ç9ÌŠòC¬ªh1 öf ‡ C¤é B!ŒXÎÓ©ÛŠ”ƒÄÁgHdÈCO/sÕÛ©„h\$–Áï× ¸Gˆ{gWL…‰âÃF£uüé1 uì`ã>»çìðɯXŽÌ®„"†“{dXTý€Î8¡5ú³Î'åIºn0ßl UF&®ã0èBw {C©ðyØÚdÃV¤6aPcž˜'$Þ&Àx.‘K1ºDH‘ˆ , S PÅ—© £¡!¥ r)}H€tO»Ц#Á0y‘“`7ò_QË™¶LF2ʼn00ó>nA@ ˆ×s.B¹l¨åÖ\‰£Ng3±J` …™†`‰dÔ} kçsÙߦ 1¦œÝA4‰^ÙÚ?LšÒaåÔ]’èíÒBzvMaqq)ˆ…VF‰i™ˆ¡µÔÈÃXA Ì çí'“«ë€"Rš3ê0†cŒže ÇIå#ëd;ÈhG·Ù€G ð”q¬€}ÑÓAöþ@\¯""%£¨bxYD<*†„{Îc¡ Sg¨)˜Èš(H!ˆ€˜ R ‚™ª¢*Š"‰VJ"‘)(H’Š@4æ$”ˆ'tˆ') bQ0¾!0§?«—44‚(e)š€  ††‚”¨fbE'ô‰ŒA24RjĬ (k$¥€†Ì¸&Ì:XE™Âçˆà"ÞÏØ{z0¤/roÔ…:’°IñÞï ±ý·ò î õ%$Xw’­Á|êòö|l nxoÇg `›t ñìfÉzxñ¶ùû•¢ *ÂDò¦PÎtÞÈø¾±ßúÌêœã;Kd3«Y[Ï»"GLetÁš‰Æ¥|3|ß­Y6´±¤Ì¹'nQß…ýZ´¬B“ÕÐÃη5®üÙ‡k$/8&bP64CIù]°*þL–nÃu¡@¨yó<Ó¯ØÔÚN°¼~„àì‡f¥eIìÉÿ†åó–t† JXQäOÅ ¾Ä³ºnO'»°g^(møÿqj¯'¬äí“°Á«²fw÷;ªôêéw™×‡b!„ögðÁ¡Æ!ˆ ¤¦$:&à K §Ÿ¿»/âñ^üÍó™0@è –Ì÷øØn»E˜Aˆ“ô¡ŽÎØÔUÜwzŽˆ¢owŠIû¡. ̹9Ès´Cë´=O¬ŽÙŸä6ƒàø!$fˆJ’\4C¢këƒ{®Åõpx $ƒøâsy߇#}søa7#?žT"1.‡’[.¨(~®÷sÔv¥4xÄ ¨›”Úo¢ü÷)þLA=p ‡ a¿±jAÐ(à ‘d>F}ƒ%bvb#?ÄZqŠ lø$^œÆ™‰”adMQQÙÔÃõ; ÜiçÉÜ‚ ‚<1 bD¤äè¨$ )ôžXõ ž¤ò‚¢½tÂp’€s:Ä:yâÿfÁa}Å)Â;S S7e9 P”-@³J… 0ƒrõÄLJÄPS  ÈD‡’ñäHQä𢢅d<—^‚2?›r}N}&ös§„QÔÏdìÒPš*žÂ§ Fó`á¤AÊ/ßÅ3›ÎÆøDÛ’àbÇwf<[l ë2ÌMaf”IPÜÜK¡½(!‚Ctð!ñé——-ô!nçÆøŒ’\ϸ=Ï8êíwãó¨Ïé÷ïÙ!.9VV  zæÈR/²¢»$ž‚;,¢<]h%ÊRëÏÂGö" È2¼Ù€äÉ)KàG ÿÇ’PJ§ÂÂ'‰”BB ` ºìÔ–#«ç΃ômfŸË`¢Ÿã—  £ª_Õ$î~²OÐ"B Š *1¶PIÚÍbÆ0ãe }}•BÕf(4É„Îü€wPÃOz‰E¤SîrŸ¬üçÔ‡¬/*Èh<È8 ¨`:+ÖAë!¶ f@-ôïÝ‚uAÛRÀgäPþ™„•JDi yzúo$ùJÞ| ˜)7fÍ'±ÜâWÔ€hˆlïòbŒ2©Ç&ÄHÞiùð‚K¼NrµIB“ Ñ|ïܰb‚ ¬Ÿ0 òì]ÔCX@4n0ñlQ+¼E2’Ñ' ™NHôaÑúðèN¦‰ãçùëÀÒé—àŠ_Õžöáø.?(r[ócÇZö×™|c»öø¾y”ô%'»¹wy ÙÐ4ç´~xÖò`ðaA«ðí¥ð,~½ .¿aÞû»¥­¢‹p53‹„1M©M¸ ¤åÍY7`õw¨®÷¡§' RÒULäØ)åÂ^ÿ€{ÈŽÍuõÓâÇŠûD@!A]˜Ù\lηïQ:žk·áƒ0ÞœŒ?ÑØ‚ñER=n˜øvÁ»Aõz¼LX3‘^öÌ:æBwÃA púÄ;8)ÌÖ‰(ª(I¥(B!1ÈÜ\ƒ€{dS•OG  Ä‘ƒ YgØÁjX= ÷ÌxÔÀÍ¥™†zÍVÆúÃgÖ¨c¨È]aÂfJZ;–N½ËN þ.òd=6:)K)A™ý"•Ä$B†L¨¾ÿh=¦¾òYWã-HJÄ- B4…S4—6;ŽúÀhœ™þDû€¢±öd("¿†Â‰Šgõ°Šè$z>Á'¸ G‚eÓ ’y¬HtÉŠ<´wîDÔ]Gœ|ÇàtXÿ$€>ä2Àrs­J¶þAŸ^ ¯WÌ&¾Ä4È” M·œ%YŽ^_§!BåK PQç“HÒ' Ž6bð.¥ŠBhBZH;Œ$ÔP2DU(CL…¤©Ä­R4I2³ A0ÆH 0DQø¾­ x¥IiÆ®f°šPpqˆ"š2áô¸ÄUHȬ7ù²¹3_lsXNpœ%7zõµOi¢ïsD5I!ÌKâ@€ø–ÞüÇ£‘ÙÌY F$4LÑE\œƒSp 8"Ö6Æ•{·âB³§7:ÈqäL‡Q—«òU„;œ`¡Ã |eâ€Ä€ðK¼‚Я#Ny”è1@¾‡Ä D¸àLcÚòö„û6pg>°_Ù.‚Ýwœ©–gíö*r§!¤|RÁ¢1'qoîr—–ðNå¾ Áwà9óQ6Mpz¸S2)Ÿ‘_-û†ä&Cåà7XÜl³½Îd’³Ô7¬!éE|ú8O'³ä©y|á:ZkXÁåÉ9C’»‘š¶‚:Þy”NÇ_q´x þxPβPdъx`óž`äè€y¨n; ’H©¢šzº‚8FþŒöBdœmlç­¦•ž¶c6ÖsöÿÉŽÌe?ˆ&?´“ºàªªÈWwú¥ª¢ØSt'ño§}\ù–S _ÆI´HHe@BTᘠ|°g¼—Z‰]ç¦C”0%¡Ú6@›É'ç£ÊžßSóã~wÕ|m/~_“»å›S3IôÂêä ÆôaÒD4Þ¾Ðï½á•8o‹¸PÒD>G¢Æºªð¤’’Bg·IC‹2ŸwmiÚhxþì.¦Æ¢!ÍfÛd…"&`[”Ô¡â\þ•êUF!ÔÓ™è+üÀãìVÓÌ”›ŠgML%*wþçpa±­íîàà …•Úíö9éŒzš°ÇÜ¡Å,°£žwk±›ûÁ,ƒùÜ™3T²fñŸüiæÒ?ϵ§nØ´:.nˆì˜›o"„„“3TÓqí‰v˜ihXh Z0¥ý׌4I=ó…¸`öØ÷hñÌÅü²á8ÒPîà„ 07‰œÍom´µ*ñ¸£»rs¶×dvÀ) ž“\DÛCaÍgý2ñ'îß"¹äw™‡aM%÷”*hgvï)$*)\ä˜ ¨xz—>SDþ»è~Gú’ S¤"Û]÷¦ø‹’b$ò¸†²é>g‘Ñä ›¿ÚBIÿj)œˆVŒvË‘P¥{ûS%A‚6Di)î-Èydؘù^‘:-##áVŠC\¯ÚL›] SCþà?‰nʰÂ$]t2vBï0,aQ&Ð>+ÏŽŸ¯ëUE~¤ƒZ»þ‰ã-\fAtP^Ãä¯b÷Hz, Úc›X\#¾°jð"„‰¤ûàˆŸ e ÒŒ·'ÞŽ*Î3l 9‡EâEȦ«ªÂô€ýd½›º:ïo'7AÞÁ®¤1,A¢÷ß ¿\(»öO`á¿ãØç®dlXûª`ifn„JD9œžÏªe€! %’…”€ŠEd|Â`~"ž¢††ÆßŽ…ìIý<]"à àeÅ_–OèÇX„‚v–ò|¥-ü9ôNÇ»„P?ÝabX¥ Écy,Iœó×I ý‡¾pß0Á…`–\¹ ÄC¨JÉCŠ@HQ#)%Tš°E!ÜÀ)ÊD´Ô5L“G0b„”%‚‚@¨’€?£ðz¡@«çàâOš.º îâãóq/½uÞAùq;°aÚû‘1ÜÀD ’$DQDƒ AËÿœGÅvÎ uÎfØ®Õ-–’_d­ÜÎ?ÑÂqÔDƒ‚çlTAŒóÅÀÆ– šK¤·R‘4KS±¶JGl»giI *¡*F „èˆï{ÈÊ=D…ù(OÜ') 5Øü‹ Á*Y ºî“v4ù DGŸÜ£ä4𹓠$„Á ÖÇíÀ¬’}DEèN™'n¡@ðƒŸƒÎõ)öLH>äÕ/ à#Øœú“úGâMÄ;{> (ЉU(ŒDAC¼ØÞv+!BÓÚ5pæ3&qþóy±5f^Èlª;´AÖ" óz©8“Fóö ÷ø}ÀŸZl€#ã"›ÐÊðâAXY AaÄÑ£Q ¤U†àa¯ÔPØ'diá×çæ5L`r°{ ¼õôC&îgÃõ‰-:Ç£·%íD>|w@‰‚J$7ÐñEÇê‡PùÁô?§ûÙúP†¡ö¦|âGZÃúû•Ç2¶÷CøÏÊ=ùq/(g$Ò”$¹ †C£¢aS]p¸~œ&vœÉGß$0“¼@7¶"¼ñM^ÔÙÜ ’š°Jýoæpœ&÷? ˆk£ëÿíÐó=|ðb!"5P>AУ%"Ð ®q%ù åS+9 Mü‚xgj#“]mÅzÍ@LŠ vÀ#Õ ýмecF·c2ã,ÌsˆîmÙ^v Ê1 .ùçI\""¨#‘Ї®áú€Ì& ý I5Øõ9ÐÑm´´ph9ß_’õÁÎLis–üíý'Ÿžá䔑8!1/è5EH}I?³æž+}öòWcØF{ûu Ó†/^0HiŒ6íMû¬êCêß©ŠÊ%‚,lauÂ`KKLmµîíÒ¶ÝMqB}’†?Âú_¶Ø—åf/Ÿ8ÏT¾{~ïš…CúØcÚÒi1988µ­G–@Ì52MA pK'm8Ïc_vÚå8ʹINFJÄ`c7˜þô>ÍhE6wÁ%-¨7]4Ã) a0ࢠŒµ¸œ"®I‰#¡ÃÎ]4ÒÉ€†ÇqÀB4ái6ÃL+(WøwœF6^™4/Éç $Ó[ÎD ŸŠ”©:t”Kµ (œá3¹' ›;db.ÉÑx$vqðlj@¦|/7½è¤”rB¥âä˜Mõò<5¾¢dFáºÜ+㭜ȃd§4=ѧýF%7Œ²Öº D7èS@8¤@ÅÒJ&cI‚¹!E¹;¡‹û~¾‡R—Y»Î§bF؆-•¸|3«egdËÏÁâ¦æ=ô<bb!þûïõË5 ›2ˆƒ"¸ç0/*\¥)3eðé $d3ý¶ÁüÛ·NõÆÿSíÁɱ*zì¶N¬ºB 0Dþ÷'.F€ˆVd …`ÙöX­­«lC34“3ź‡Éß}˜õ™†³ßFÙ´dÂÅ"íi¿A®ÝÔÁ&S÷¬žýL0Þò9¼uG¨hi{Hît5õ}F¶ÚJ$Ú™i‹&!]N¿•§h$ÈÝÛS=ZM¶FÓ,…¹@ë­³çÏnèÉîÜõ¶†<ç‰G·Ý=í!HtÒR–Å¥ J²}º¿\wác[¤ü¶÷ó'¦*QEùv€¿”šè¿aÝ£ ¶ùºXtÐ<$’¤Ëd:xMõ¶µ)cyÌDUýå Gö˜À†òLJ7x§Ûǧå‡<>„> ˜ ÐËi¬nÊÂhd¹ö™¸‰NØ9ôúk/žÄ56öÔßäí{ÑÙFÉ­´Ï·S!´fp§:j˜§9_fKF~Óîa„‚® `hÖü7òçQµU¶Y¬¸u(£@§VªkVb¥psVÑdXP•=¹øí£éY.U;c*T&B¥Pçôr£þXm)ƒ£Î=P>¸ ï!Ä›1= Y»t‡²Cˆæðf !æú¥C¦ö)±‚$»ûB1-„F 8«°sÃÙÏ»Ø±Ž ¼ùa9ˆÒ,–L320P1½ eì×ÝSæ3¼ù¿PeLòäð“’ûWr&€C¸ Ò>„ÂBC«è ƒ•üIÁŠì€FìŒÌÃCE»°PôŒ^GwÃ:öêa:éù@f¨ ˆ¦ˆ¨¦ª‚¥$êL(á­lZ°ÕX¥•¤© H@ïë8ò_Môûp»¼ b`à/ÄØÞôxsu”Gt K&è3„J 4,Ö¨?¡Çô¯µ>ì%óÚä 0 ˆ["ØüõaÀ¦‰“h>™‘syà€<Øå5› c#€5Ú: èî`2x©ö¿O ‹9"fƲf¢%Ðpq cÊz<Ø;cÿ6Ù^Œªì«p4^'xáɈì†?Äoä7LvjbÐÙ 0Ÿ\§¯2¦$iR,"YNúpÝó_t !K5K%="è p<—Èi åÈ8ì•ä ÉSÔ8H¡O;†PPiC’0Çi¶*ËÉ„ê0>Cäã§Ä8Üf•Ò§dOb€xÑçyÕ„%À0ðŒL’™\sž¥ƒ¤¹Cã®:åùœd ŒLT›Ñ÷›‚¯ >j?1ˆ )&)P“‰£)!ÅÐÔÑL§òÉ÷•Γ¬é!'/iÈî\æ\Mœ9‚K©1X‡ùûǨ)YýÈ7ÛIúã/3Âásb"e0AU íŠŒÑ ˜#8¤Š‡S †Æ l±¶ƉÄjŠÈQ±”ÑCˆB ×®¿Œõ@`O+€&ó¡«xXLH“]0¦$&–$xJP¼gÂäŒÍ2àrG =ÂR‚ëæOè¦\Åç±$I§bV“™Àäˆày 'ÍO/ï± ¹÷—û½12JZ_D½õ÷’HÈgf ±µ‹i1ŒLzâ+é?8çüâ°°#ýЄ¿ÌIèQzþ%†‰vþ&‚Ùhp3¸‘ö‡hö­ÖGºÒP¤Ä*àÆÒ&ÒŠ¼„ä ‡ Ì…¦” ¡ A¡b’‰É0Íš ¸²ºR@m/1Ž$‘SÄ̦†d1(iüÇ: pN„%$ÀA#J îð’•| á_…xÖ|—Þ§j3Dc`>rPQU*TÅDE <—pHoCC$l`GAòØ T t9wЏ• Ä⇙ã½Ñ5¾Ô·†ø¤XžPü¸‚Ã’²† ÑxãËQâ@x2‡ûüâa|D_¼'ýÇ?‘ (V(b(’ˆX ‘(¨ B˜)`Fª ˆ„)d!Dˆ*‰’–†€(9GP2!¹yÂr€¦‚„¦‚´È‘⯴C"H¡ûXRO×½=ʹPº(^ÊRèN@è )8NóùAé u{/8ˆà ¶Í4—±´~ hÄË[ð8}2c9 zªR  â:&¦ì. `wN«ó>6H B ïð°ožÏÅ—“Ò)ˆ~¯YóÒq›ÑÅ‹Žäçärä'Gƒ˜äwY"Iä¼–“È<ÙÖóNÅÅ£ÐlJM\0ÃØá£*wlÄúqê9³yÞv¶u®EÒW"-'ˆ³ê#ÍO>¼@==SëäqTó¼r¦ä*P4Ð!I,CÀŽçâ¼È¤vè) ’(ÇQ…N{ÚÓ ­;U‚œÁ¦h5`2‹dîáʵ&Ò˜…”65JijV°2´8ˆ0XÑH)m¡˜Ø3Ám™¦`­ƒÑ$lé˜RØ ±;l$&±j%¨©ÖÕ¬%( °˜æ38Lè¤ÄP‘0àÐËL ˜'#ÀÓГ‡(ÐCA†ƒEÐÄÃ),í­Ž®k;XÑ`¢›aÐ’÷›‹ìæX8’ždÇI«.—ùûé:(?YæPôÎ(ó ‡¹UmûïÀ)„'׬/$ "e>·ÃßOXÊè0˜ ºaN „0©Â ¦PCPéZ™uMÙTC Ðv5™$ÍVØ¢ª†'YMœLkÒÄBSTÐ0I:Å)2S0ÌS³‚!b"*Û1ccl“Í%LLQh̸Ž+’H¦dÂ;÷ϼr Í/ϘžÅ•øÛlD€ŒøCÅÃBPˆÑLU(PÀ½' Ô!û^‰’¸4x˜YˆÜªùûC¾²àI"`!}¦|g"lŸÌ “¯¥1þƒŒ.·t 'àû½¼1ªaX€6ÁƒËÝ” 2bOƒ.œ Œ=j›£Þ—ÍdÆÖÂdƒýöß Ÿ)yÌúƒ$žaľ@×Ò3ˆrÈ¡ÁÁ,†DÄÅø?÷ćQâ’…w-&2x->yü-þ\C†& ÈÂ_«|77õ C¸øãû4<3|h³]Jjõhk&³ã çáÀÉiß>œO)dÉP÷D÷äû$}Œj ¨™n¬Û%Q¡#V {*Û2¥jõQˆƒõºùþèÉQcÀ!ÌäÍ44±›l‚¼›~áôíž–ýÞþÎÍÀkäx¡Ø:É G@>NÄUÈùw˜À!ÕÑüú •1Uôú†$i€¥È¾>ýꆆOŒ† ž›÷°° T2j!  )þbÿŸ£’›¬IÛ±wüñXmá‚w‡ñÊè–P)’’QÞò¯Ms`!aüÃõpKÏçêä ý¾c{*)ªEª_b"”Dã9êC•~: ™«Ô6ê Â@Ò Ä«J2!0 ˜m‘DPMQSØþ—càFÐ…óyÜ¡˜:ˆ½ŠL²÷ù@% ¨ž¸)Z•¥(h@&hõH¢é R„JP t‡xM)TªD"< ¥WJ Ÿç€]ºDt %'ûСˆRšQ )T¢‘¡¤€FÃøS‹Ò¹9ÀÀ>ûÉ÷Æ%a/nñ2æŸbšèóÇ$]0;‡û~´”ÔÄ!Ãä|!»Ð0Ò³(ˆ$’¦ŠdQ˜€©"a"j%’x›Å ÀoÊÅJÛa×ûßvD !GP~ϵ‹õŸÍŸ+žþ«Ää#Ü òÇDC³Ìz_b¦«ÇÐ3H<Ï(Lƒ½ìéQLTŠ¡BÄT”¡$Tµ@QUI3DS% LK²P Ä¢D5J BÁ" C@(PL+H)J % ‰%$ÅK俣 ÷á\„X‡AKˆ‚#L…²‚®MœÅ*g|êLÙ)}[”¢ˆ¸×IÌé:õrâÃä¬ LŸHyáòj6@ÒâÔ;7Iòhp@àä‰ ¥EaÞ0uEש¨?ï_ºJîè`¨`Q>ñ=ˆqw)º(•(( eIb•)Z€¤Š”ˆJ¡H¢J)¢)2½?XòMƒF$³‡+²ky)ót‹ŠLÊà'd˜$‡\íBÁ æ²n!&„†Íg&&;°ä™i@ˆ~‚†WlL»¡LmêÊ]Ñ®Ž ÐfLÄD0Òï„Ðq$ðú ‡…ERRw…¢¬dÃvÞù„y >J‰JCèHFxÓð8¦N{(èL¡õHÌJ©ì½ÄI]¹Þ°`z›7*v4É4pd ŒÞ8CB’ËOSÙêBl¬‡Á3M—zÐC¥üƒ@H¸ÒÂÄz½vç9#È÷n(ÎÊe!(ÂÊË…}ž)ÎHR4«@12Ê´‚h°}HyÕÂ}P,²ƒða@ÂÈÁߦÎú§ƒRýÆÄ´~-J‰‘Ú¢ —g8Ÿ¦Ç(ŽÂù#ëÖìtò*jŠ£I–!ÈÃÆí8(9!6¡Ty÷žóŽ3%‚Ù7‡¢ÄwÎ@ÖŽ‰< !ñHËÉ7ì ߈ ™`!„8÷HR4Ø)Ò†DúlJެ«©~MØO¾tÇ& Ô ‚D¢Ò§ÅYL¡ó—ƒç.˜ãL?(÷–±ô0 BP*˜?z¾c`:,’§DZ8&þ?„€i¢`ˆ‚Hðp ˜*DdaBTÖãÄs^=ãè4Ö©1™¬ ê_¹rzäØDtñrëå©Ç¸æ™ËôXÄ|õœ )*4¥ìÄTÜø#éÿ›ÚoÐ0ÍîK ¾¿‚n>fâé=Aˆà^2I°0陀î 19J—Œ0ˆ¨5Ƶ¼SDá ¦Á´&}®dä¨ê`ì2Mž]!ŽÑ8[&­NÖ¤±ž™¹3riª”¨aß! *MwË÷ï/Î@ÿ_èÛ‰“ìA²…~¼èJtÒÇ,8‡I~–õ¨rÝ{oV–¹þÙ¡…(¤ÚHÍ0¤ÃR‚ú°›@^ºP”ó6P£xytëÛ–‹¿Ÿ|R§¨W£DíìÁÂ>—ŒøSB—C ˜›åY¤f’¾1@NëôçF!6Ú$@¿€IHCžŽÂüˆ ý‡É…7™Ê2‡I>ˆ¦ÊFçĹ5ùà|ˆRJŒ…ÆE9U=!¥zŸ%ã.<°`rX pç9õqGIü>íÉmÅÝ;¿yžÁDÔŒž¾Ì÷:ý!€¸àû  5úòB ‡Œ8¨q 1+Œ\du­iÓ¸†yp!NVN€%^(åp YÁ^`!EÒ@’m‡à}÷OÔx*!Ø ¦„«²ÊrðÐÖÒg-  8(¶Œêýû É`6ÐpS§;Ò¡~ÁgœNü¤•ŸZb&(bïù3–µ;|ê`–¤Cæ< ŽÌcªVO i¡H÷íþ¨ýç ~¬. u² 8 "* xt°H&`\'ã÷µpžÒÀ¾m#Ûűç^ n9pœ3Ò'êÈgçR `L@4Ò¤ ú0Bp'VsÁ‚|¶±­©Ã Lb¨4Ìf)W-ÁÞH}‰ ê€wk¾@D¡¢”H€ =Á¿ë°7¬}rk{ãø®uÐ!ÕSî» í$@¬€ž9…@4N¤ù3ÿ¦Z • ¡‘wçðäMƒ |Ðþä&)¿±ð>˜bp˜ûæ›rNeŒ È&•„€Ä-¸²{¦²¯Ó×}âX a>`Ïi!í߃‹Óæ÷„-'Êaìî.ޱH,6½Xõp{ƒ(fPo«»C±z?ëždc'rÔ¼')!ì0…@òa,==!ýgÙý_¿û×\^¨ùD€žv‹àóŽß°½è¼"(@¥çX¥èqWçêæ‚6NãØÄ$9™Sf÷°´·ùÿÛ÷ˆm­€˜ØxñßõZ®”×¥÷Åï¬÷—Ѐl€¦!×òM Ð&Éú¶'äu^_Ȱïä&Z›ýFÅ•\±|pw\!1¸õ?òc‰Ð˜¯ØŒù„A[?*a&f¾ QÊÚH’$<Öæ”Iu|%nП¦ÿÝ?_<ÁëéDC‹>8McöÊÓ}¸—ë£Ûµ†s•'HˆyÍçåZÚ‰¶jÛ#P Ù‰†ÎNBNIÎå‹’6+¶¥ß Üö¡âˆ~€é̾·ˆq»KpÌ?’"Þ)æçŽÎqor'˜(Öx¸s TR5™IД‚RÁh(†€ @æÄ MÈm˜š¡ b]‚ÈMµÎøß¿L‰¦ŽÀ¿,Ø‘ÈG€q/ƒ~ñábîɘµ. ¦‚“AèxW°ærþlz½ø| ƒ®yÕO P:€l¡áT¾‡A}H>F‡€NØL> r‘ªüg݇ ¥wÝ«~DøÂ|0y#ä…- ±#°Hfìào £³°¹$wê±$NSïÄÐK2ÁQ ,UHK2!"v»³ˆÀ½Œ„nÛfÙC&C2œ6O}MfZã4Dìm–üF`6yBSÁßÖX T‚`‘çÀ¯-}Ú:ƒ€Ó&›=ãì4Æ )眵¤œ€i°ÃÂæ<§D÷å1†žâ‹E]ØãÄjýÐ26„Ê!œAI@—ß!È®I£T"LþAúuÇÛ‘ †=Mj¶þˆËA2AI’|€^Î@zH@RD´ JŠ»Nt W± ¡‘_´˜ôÔCóâhÃ~ùž½¨'µž ›n3O Æ Œ$C“$@Øä ¼1¿ï½µäœ6—Ž¢ü²)NèL‘3JŸq èMQt’¤‘I‰?Õ±õ 7ÅÀÝÐZú³óGßyf™I½ M3ÇŸúî»;Ø nò€Ÿõ°Ä‚Ù$ú ê¤ 0˜XÊqÕja'¡…ˆ&Ë–ì&Nq¹òà÷ô%="÷‡¤…tÌ0ÔA/¿Xÿ¯6ŠOy»…SŠ*žZ“M-w‰ÒNÒ ®—ó!Žn´a$ãÄ8’MŽ5÷ÍI¯°l FâÐfÆb¿°`Ð`€“ öHˆ=Biû9•-²®æç#–Ô8i” ’öí†=Ží}0©¡%"”ÆÂ|Jñ‘iŠ”¤¥á i(&h–šZ) ˜* ‰öŠ)åÞI¤“5Ì`ž°‚02eÅ×Ò¥µ ;ñ±E3 ( s†x:ü²gž/ˆ)úBo¦záõ ”Õ‰"ƒºX`Äëá—ŒZ/«P«P?ö¥pœ€«¾x½ñëíí‚5ÇžþÂÕ!y±–ñÓ¼È?¶:¯·Çs Ö hiˆ†ƒk$‰.¿[<à6]Ø“zcR5]²â  ~ãn;`6È}Õýs˜àŸ¼³çé€C0HÄÐL«M ^É)?j~Lýê8&¨c1ô#,ïCçbzýy€\0°ZJ•ˆF€ )šŒvÎY €ÝvC˜j•þáɈ@Á2€9IÙŒ€µûùÞÉòäUŠe¿FŒy.d€~¿«^¡¨/‘"0ìL)­qùü¬8=ƒ,ÖÑøêà«MOò±üÉÞj:p´#ÃC&I `a –Lú` Ò@1ßÃ,ºÛAÇaðfæ¿¥w†ñæ0DT,´4_šOJˆcš q™;²òb ®žïuŽìøìøPa}Søíy§Œi äH²YrBûB<¤ŸMû.y›t“ÿS­Xþà?9î˜/4!0tî,.KÁGêœì‚z•óè@F¤Ò\+º ìõk“é _ºÊ‡³2+ˆX†’‘@¬¶Öå"¿Á>ß{¬:… K5… d(£»òçX#fßö5N5QK†R¶˜DÔ«lJþGiÖpÃzXâçdBk­€ÁŠÆ*U®¨²‹g žlÐìwJ»À áŒ)¤45œ,»XÆû ,¤œp¿LOÐÇnôÐGq˜’&©™b"d¾ 5T”Õ=JMp—@Æ#' (=é&!éÆ) B‘ým&‰ A& j%™‚_dÁ´0z²Ø£ežRŠvZ}V”·ñÝ$£²šž›’QÈ *R‚v%0Aƒ[CdøØJˆ8èˆËmß09üy3$ÞìE, ñÔÒÌ …Q…¼ÊÉh>!á!ÄqtÐR×;ÎCæ Q$5B€ÅGhˆ"Z)&%…”}Zf‹»y²úÖJˆ*Á9›nô{9sƒdžÈ‘ ¥Þ±™F™–"µ²Ÿ ‰Œ´LUžâj‹ßV./‚d¢RB¨¢ ––*† Š˜b‰*¨h1©8Üj3R•D“UG¹1ÕDìÔš¤1DH ¨"÷Jíc”§ ðá*`"&]!³ÌCÔškz‡-†6Àxá™z‘!Á&äì”NkJ0P)Ä8„&ˆy@Ô(”ÉPƒÙ9DNIÝÛvÚë4g³GÇŠöú'Ê{Èù.Ãtìð&bŠëÚ¸ÏfdqÐ3Ú®©\t+q©mcl”ZjaQ´ÝK  ÄR’#~_CÀé=ûŽñv–Œ`€äàÉCOÀO ›¥êßÞS3\zu¿ ëbÅ'¤ˆ¢H#ewøq¹¯ÎñžU·Ÿ“÷=sìLÂO¤æpR…IC3@‚¤È/‡`~¦†ºE¦™Ž{êJŒ¨Ù'éªê¡oö¸Go¾r\96´ö ¼š#çõCS=*Â>œV °¥/ñîšvFYiZK"ߨþ™Ýö[¼On§M‡E®î*hiÊE Ï,*áÌ3î-nx"9ë€GÌ‚aQ6Ë)é ×¹7Ñ –ñª ¯8&þòœGJû\¯€a÷$«êâP ”Þ!…Ü”C&jb"nø¥þ€9)Ó¹8?„=>@à>RO@BCNfµ¦éÕsOuwrScI%›’ã ¶-±´· èmó_a…ßlûõJëˆ(&À”œ¡Üç’v«B'C·Wvï’q ÉÓŸLr^'"PBB„H‰ ä>,Þ ‡ó”)Ì9óíæHh/| ÖÃÄ“‡Õ—€F(£¸'oRê( ‡'< 2üáØá~ä4½:œÓ²R!ì‚¶dQ>ú¹÷…‰=z+Ѓ?D ÿL#µ”›®cæx R(vÀñT|ij Aû;Ut…i®ÒDt2yÁÇó}ãô+¬ŠdÙ™ƒÐÌä Æ¡Ý ¾DdÚq ÔÞ©ô-QUUJ¼É?§Gd8®óƒ8 2`4H)Ü6ú€Ÿƒ†‘ZìÁª]y|„Å”)ÿ,‘XbÀs¤²,°„ 2¤…Dxûò)”(žÉTì2RàqÍ Éeil:šËo#Nmö–ÃÛÝžeÑÔ'S©&ˆˆÍ‚ ˜ƒ~);„&$™Ù ÂáŒDMv™$ bhWpṬe9 É8)p1¡šÿ biF€Ê l„¤™šLÍÒ8\”ÌD2áI™~“ PT‚08Æ%á£HC9<äŒÃ½|a1nÛg7n<ÊÏ÷x3$ƒ~?6` B~ü[JJ¬YJ@hƒE˜1†#i“ „)‘²žXÙ3SH‡wNî‰2>ãÊ~xÓæSŽ^¡»™ö¬Áô#¢º“IqCͦ€Nãå_@yÄÈ8‘صß@çº5‚x‹‰×i×;¨t×߉"—ë´¯ J³'¯N^ö#ð} ^N"¨ã$RzIá–Q„|Üg>¡˜©±ÁzäQ¢“]7åS”¢@S- &PïN3éa7ÂAÒ Ê ½€ Ýä!§^d`>Õ—|´+àK‰ÛšAÇzh°·¿ýÃóèi# }/SîM袺à¤à½v|LJKRP²À,£÷}†ÁluN&ºgp2 ½È§±¥‘HHܸè•OºB($]BMUÓH[ràƒ!†ðÊ™T|Ûþ¸ú×°ß¿Jiqy Å’áˆQ'2™ËA‚‘ ÁhOd4¦ä9¿€Ò'à/ˆ‡”0¡§4e%S«“™-XN–LÄÆñF"º„† “±ó?Õòœ)²fУŠ‘¡ƒŒ„ÃÐN â@Ê-±D0¤PîÙÆûL?Äwp`>ï¯v¤ïQR×HV0>©õÚs¸,sÑÙE9&”tP i$ðáÅjCÌß„÷ÃÑ 4tµ&çoèNû$K¹’ ›­Ž•i­tR¾8lfõd+ATlS—˜\²~½Oº{WlURUŒ÷ÕTŠ ²Šh‚öwƒñq¹ÜÎû„é0nP×Ì&ƒÁWuÁ*ÎWòä_€Ì{ô˜&tXGBücIJÀ 9]9üáúÀVýž)˜4´è”˜Úì¥(M/ NŒJà¶,`Ðã`ÄXrÆ‚²†YÀ˜C™ÔEÑ-ÂPÓ€52e³Àƒ™3> ‘¤F!‚P•Âì ú˜„ùà^„£êpê)2.L/ˆù!!î7ª‚N‚ŠÈ¡DD IEMD´­! óÊèRî‚P¯•Ø( [{•C@MSC*`QµTà°+à/¢Ü¡æ>¤Ûxsö’$†ÄG„ B`>¨ÆGI6 ˜/%}êå@Î@2Cæ9 À J¥ ÀBLMH”UET¨†äÀ ìvõ.Ž!<ÁÈÎj­¬+c0žëTº(…D8 'LéQpðÊ×E÷ §òÂ#ƒíž[‚$¦_%‘TÝR&Z„¢¢A¡$NPMDÀš€eE4Î_Bü2µ–»9è"7ï°M0¯c·”¾ã¡ãÎv‘”¹Ó¶ÒTÌ™;šlaá*)¦ êÒh1xîcmÅÉ£œ‚ÿ¥tަœo –´D9$i$Lž( ç¯ÜÀ²c²¤JV2§i_WÎ<»Z`‹y_+ûA7-øËü Ÿ¥½iù6JËT¦KîÿWò|ñÌuÊ'®%SøK§Á:J(‰Øf9,s›L8+RYÔl/+\žmŠ-b˜¬o+SépµÜ^'^õÆògUüåáŽé‰Ó8Öugrh–Þiq[Ièu®$6‡Sÿs¸øu´ùÏëuýe€À`¸fØ6‰Ö[Gf‚‹^¥BȪ%·múl$E.°ácÈ›*CÅèÂŽ5 Êmqd`Œ’Û¢íSJ%7÷LÐ 2b›¦óÌ;e"C`ÈïòíF€(4ö‰½ä‡ìÝ¼Ž·*pv-·SX¡O`{¤Ô54¡¬ßÕ†|íK}²· 4ƒ:pvXCMÞ1Y¯³8ÝÔ›èY^Û§‡h°8g®Q» 5¢E'vM˜d1ržúúö~'¦× BÊŒSìÃ3:ÕçBhtÓoT“U•ÚíŸkèš8Ä0 Îl›)6¢$6cè÷À¼f\£éyOqäÚMØO_4áÝåÐ@ç¬\3i(ØcU ù ª²YÓ3;êdôg¶©¶yÀÄöxÜ=saH¢†±ó+‡¤¿[ìˆ,¤ƒ¡c4‰µ (w’Øä=Këua׉¹€6±Ú»Ÿ­“ õËæjçš3$ç 'Ù°"ÆÔP*Œfxj‚öÛcAÍ,^Sépk@å!p~«l!JqÆì1O"ñ„+ˆ–ÓüŸ^xØÇ†÷Û¨ž¸lëvi‡}SuŸ2ÃsÚ¹ŠÆË:9Î'«|÷¼AÖ(^{hÔÝM;ƒë}'ßÏË\)CŒ-¸Vò‹oÏãë”Êýÿùàâ=òÅÈH>¡ÉgiWü{Ћúâ•c—ûzMe§ %ЃЌ‘§{ÆÔ™¹‘Âð´Ø‰ˆ±øl<†Ù6>Cé¾»@.ï}-F]7Vˆº \fO43Ú„¢‚ž¸&\²$LÂUë»ÖèÿKÏí¹ý'ÔìÒï÷/ü+1ÆsÍö*ë¢G"Ó?¨sâAW`…’ ÊÚ&ioš3˜½Iß_>wBËõ/ÒlW±ÉÉ2ð¦6^9).>²ºÒT˜5ÏLÀý=°mC ¥¸Ã¡Üe254B6Þ$H<‡Æ¦L`ÄQu ‹¦c~ÐŒG ˜nà™ z¬ ¤SˆÒgj‰8f)£"æ'v‘l3‡°l'}púC®¸6«Pì–vÚvî]^.GméUmt'Y0]¸Rkv¤ÐÕ„#Ñõã»ÀXwZö!û7çcÐÝS©’cncaOœøbÂjx I–#ï~üͽ~rc´ýÏÔBªþA_¯LôÎCÛgºænb'ú ;k·dæÃƒ ÎÍ’'=“¶öyöì\Òòs0¥¥1'SÓXx6ÛzyØÐ(ÝPC4µ!©ÇÏÕz€ª-Ü!”‹ò'ùij‡Xš’Éòß0"uà3qÐ;áÜ·aƒ™àˆ×B ­²4aOÓ'ÓVRù~÷oy¡ç; ëY×YyJpv˜?—‡~6(YS4³&èiƒpÀ´ E1|]º”º®Íî2¯ ~x]´REcëÝ©AtåˆØ†Ö²Õ:f1Š:´¡O3Œ5¡zóδ¬UˆŒ5Mœö°Ùš‰;6È«"q2ŽCK´ÃŽ}m<¶õ¿¢“pùê5z»Ç×rýÒ{f ­ éšè×¥Þ¢’´î‰´?èwX¿T×öl³Ï,Rò¼kþ•í±m÷÷·9{ »ŒÄ¸ó“Žáè‡s^oÏi2­)N}«³ûD`×6“7Nîš&yЍ S íõê>½'«E AGï>D4š&g“÷˜=5¡’i5»ZÃç;+o๛u-V) Þo²Ça‘G¬òßô}ŸÎ9"Jmmçûï)[‹NCÄ¥–Î or˜›ÛdAY’Ü$@á Ù!Æ,kj  ™<<&Âö߉÷œñÏãå•Q¿~°9:¤»È¿;ÄTí£9"oÊD–V¾Võá&¹“u+®«Vý=yûvj®j•ÖÞÙŽZ÷ö+gã+OËËÖÚÕøë‘ÂÂcA"âãüaêße9Ÿ’LÒgLÁýGVg“—ñã´´’j„‡Pw‘"Ñãº3H…åI%n:'TgDQçIM‘¬Iþ¢ÊŸa©wÎ>)–_Þˆ¶–Ûþ(øþÿm¥Tøæþ‡gñ95h¢É’‰'apÂ…ò,+Z$¤u×Y̳[®+À7¶–‘JÕªIO²LÜ·ªŠ7PhÖ‡ Ï_mŒÔ5Í=‹$µO œtR‚%dÛÓĦîHÃf@Hˆy!;ç±_z(³"?Ü2`tïç’£r-‰ÑɨEê¶rÂ'g^#@<(vvDÙ5ÓT #£ ¹PÕ 5uÀrx‰Ë—¨›×ÄÓ“1©Ä—®>DAè$ÍÊáþŽr¤ú/°¸ºâR beÒ- ÿg%Bd™È~ñµÅý…(4%!Éù²>‘-<²„Ö¦Av«øS®4"Ÿaò™·vVL õácÅK4ÏÞé‰J”0l¶Ö9õîè'©pƒ!Ä_cÐCÅC±¦ž&ª"eëUYEÄEUK(±;ƒºr(òRM8N¡Hx$î§P ®­§KoÛ½€¿³°P”açäú{y§ØBRR~\`Õ9pÉÜ #¬¡éì{YÕz j˜ÂôÈ›¢úêÂ|°v,.-Ô÷.œ’¡!€ó³‘þp×_„•ØÁî;ã’ï¯OMÔñKhv…BH%†ãÞ8©Oùû{ÈO S;8Ü›ˆ% ÑÉú]iùÃã矮†‚vÁ/>.µFl-¤ÄWL3˜ãÀmT×PAžˆÞ)BÐÁ1VíŒj–æ¦]îÁó†“@û¸–@!§É¦ðq&I©8;ž¯Ä–’j@÷´–†#v `…ä<§a ÷KYfû)ôä™ Ëte”i¿ÎúF8@ù|˜SRt ˆé•sPÍ©‹Uw©ò%€éŒÞ| JrÊx¾÷+VؤQt“+™sb¶³x8Ò F6š'm[bÛÎÕ­´@¦¹%EÓæ!@¿Å@… D8— C¨‹ÁÂë©fã3'Ëã™?Ÿìõ†Œ4“®´è-ÖijŒüY ›1‚—³:Ô3Ÿ| ”˜a‚1#Ø‰ï žø]ÌpøšÒ2O® ë9Œ&â¥åÌ2ðÅ$%Q|0›ÉÈ¥|‰Ó8‡…‡ç„ ÌQ[ÝòBOŸˆ>¤ïr° ” ‡ a“w£n›±Ës½L€ì ¤NkÀ?Ô—‡êôˆéhz,yÌ­ã¢N*«*)ÍåX“áãñ×UY(}Hîg†šèlBr­P5HH@FìÏ8k÷ ©Þ*½þ~ðJ$?)[ü4‰qûdLJJ@ô\?.Ùh÷qùaòQ=.ÚÀ§˜:¤¹Å‰ý_ñcô÷z…=`p$_$T)×`Ü£Å}·¤„ä½x¡dÓøXNžxú§ÃwÉÉý á$…¢¢>ÏŒroy6s$Ÿ~ÁónцCÆm€ÒRR„¡›iÊžÐ1D…ÃPìÖä‚.·èœp—g¢?‡6$TÑ(ÔâÄ<³—‘ñèê& óŽOžN„ˆuŸœ²TÞ[ÔõÙÛ´‚^°‡ SÞÁô´ RøTzã½Kìaà&Û)Às;€M•šÂ¦RL –ùþ½¯ÞýOÔøå ¥ý/¬ ÝÏv=lY?-€scM;årzƒ·¸z a˜›`|¶ 'î!llnŒü™eµØÒ ¹Žj¯öOûðz¯«¼å—“_"P”d Ja&]´‡Gl’’‡Êÿ™~Õò§ÍüØÈ÷vv¾w\Ç‘}W¹°øÒ¦\‡—bÇvq ä¯$ñ¢Û…½=Æ'7S“•÷ýÚoõ·ôN{þœ`´¼:3LHÂÓÞÝßÌt4ö¼œ³pwêð‘ô"í󸃸2¤IÂßVúîGl¯#°DD,J6Ÿ!J'¬0¤¿‰pbÓ7&ÈI‘4‡£ñ}Ř´p›†øBXBÁD<*žŠ¤°Âââ2èD5!ý„ÔÛýÿ‹Ûg¥©"Gò+Z]”½Ñ#¾?Ù²¥˜°`ˆJ‚•¡PDlapc·Í¶oû?°Þœ=9Èôù#þÞ%É+¿¦³oåâTÙ(VS² ×§=.aÅ5Ó:¤ªE?1f’ßCc{à9AV‰Qä8 Âk¡¦.¦&B«_edœg¾Þª‡Y÷FÙu¸ó+ôí äÍ¢R§RðÄÕg䌦Ëâ›OPê[ûëÝÜ6éð`n Á óRSú–)rgÚÝI½Eõÿœ=Û!£¼ég›†õòõØŽpÅ dæ•kX÷áõIåµ§‡¿íï)¯†¼¾ûù»‚)Ãúw¤LT¦Š’ @]pM×ëÝ瓹¥{qê=dïG¨‰Kó—!¨,!4ølØBïÅÛ‹87=e겓HÞý¨o?fÐxÿÏ%32Ñ_©Àªãmqˆ‹–œZ; Ý>]LJ$ÚVù>ó;`„kJaÆá2ã`Cn “Anö$‹<úy“È ÕÆCÔ›Ùƒ´ËŠ]P!ÀŽ´@@!¤CÕÉ:³´W³:Í®ù5)Ä2l¥5ÚÖD[A !Ž!Ù18Ô=&ð(ùF„ pŘ•ó!fUtÒdY‰ ¯IÛë“&ç´0Á‰‡¥ ‚ÈZËÛs|š:ãʶ±Ÿ™Ý;3¤8ë²I¹})N•OR/Ôz6Í|íoÞ±¸m?‚¨£ãÊú1†D¡1lã²CÀ8…@É!5锊"ÅR¢r¥ÞÉ «,zjü_’II$¹Ï¥é4!Èo%ÚÔ´,ò²Ù³ h ¦²†rð ï2ð“Yj”à(wÜX©ã‚N@æâ}ÃF†ëíÔfØ3F‚ F€hG{—G» ‚’ çÀ¨ˆªª¨Š«ª'd9'ÂÈx)Í ¯‚Œ  Øƒ[–d8ázkJ\ÆfUïD¢›Côù§ÞåÚê e~´Ø5é IŸÑìp¹Yù]‰Ç†>³\2MæñC¸ð0¸ïD=^aÈ:sõý/µœbh L$?¥(Ä ¥–#e ;ýqìPíçüö3‹×ׯæ“‹Ý€ ˆpqÔ\ÈHÉH±þi-aü{û²Æ˜Â@C¶ì–"ˆ¤ÝÒ’kް›tmƒQACß0ѨÜÎtM¢ c]‹&ÆI Âϯä`@V$#û&Üxã(/Õ 4 Ê’OpšÃÄ<øÌ†@‡KÆ€)Ó뿎$T0 ¡¿$¨¢!’¸†ŽÚ‚¡GµülÁW0š&”6c\2¡¬)Æ»iŠ;œÒpÛ]ÐìVQ c©BÎñ:ºÈÅËeL«ù}ð•N}ï5KÀרõr¼ G±íãOn ’*a¤¯¾4ó}nF8†@–"X …¤I’j†‚–m,BQ>W“rÏfòˆ23ô`Àƒ‡iêTÓ®¿OZ °bÙ°RR™¢ÏÙÛ"-ª¦páE ÌÞ0aê«×}’D‘,þ¬8’$ˆ=€^90~Ò*/ÐJ*º—" H0T’J“׃¦Àz¯ÈrÒÏeṎ²8†3…R•Ä¢…xSù¥ø’LE~è5 Ïž0ŽÁÂ_=¸<ž…ò?äç‚Bú’B$R`@Ä8 ŸóŽï”Þߨb"бŒIó»e×_V{B7ÂÎÚ8A_Râ@§¦1H%”>ùA2 HR¤2HšA4´ BRDˆP+BPPH½—CHÑ‚Ò%;˜Eä…(P¥ ÐÄ©B!I "…#H”‰2‹Uü²‹¦•(Z)U¥†¾¹1-U HÐ %P¥+JÕ"D…#@ЉH PB4 !ÿ,†  _P‰“@Q J ¢‰"J” Jh™@¦Z†X„‘(Z‚H&†ª‘¡i)‚´¾ åBE@P4ÒR£E LÒ\r©Éº]*ЂQB´(”ÿ‰ØÆÇîý™yv*¿ö’™–†€€>yn§„öýè|QØ0ɱW*&ai•.R¦`MÊoŠH‚´Ð_åPÒ™f-LÿÙë;xl'YïlRFl`6~WBÔ Û î„+ÌEvÂæV”âœDIì6 P%wCúç0ú<b!7œV'jBêBàU•’•sªçÁà§Oâ`ý ¬%˜ B„Æ á&æ£ 6À~¹ù*§òÀÁORŸ$?Ñø—© Ù‚0j • ÖV²…á×pP>&§¶¼zõÚî\3¡•è ÚãT&Z—é|@ÚÈŽáÿ¤Rc"º—ìþ6Cúod¦5âz)Y”ÖØf¦S‡FäÞ”á»Ñ23Ù˜å¡ÄcyÖ³¯œÓ„$`Ž×˜Øà9{´e·”ž]&!¨˜"0¬‹b¾pvˆ6OÎè0Í%)]#Od h¬tŽq ¤Ü¬F†øÌw´ÞŒÖ”ß[qeC¦¨ñ‚ òÇœÈ`(²žA‹Öÿ*—˜ÚÇ‹#„×Ö¶ÝÂ~¸×,4x%ñ¸N–R[ ¨ (ª Žôïv‚($¨b‚—NÛÉíG\h|Aæò´Éä‰àÈ9|îæ"8X¨ä\a ëXP@ i#&,£õŠ JRqu9·‹æØ°êâ«oVÅK’­°ê% i½tº7Î&åÃs…Â¥˜äöÄpa3f<-=—¤QËDG„i9w¶{´º³õ Ÿa…ö§ÑPÐü”w‡ÁbÀNÍ0ge³Q@e,4a"6D`%,¸Z)\9œH@WÍMJ\¿B}| @ßž.\Ì™0pÂ#nƒ×àI8=™öáø“ÉSJˆæL@vG-ùvb ¥ _¾Ò…/ 4)¥ZWC þßíÉɶŠ4´¦„ #ˆ@шOPy«PDPR H‹ñ ¯I{ÞK¨n„¥ ¡4 >¸Cè’B@;r `Üë!¾O:ˆäÇz|'Üà0Ò ÁJE5 JOÚäÒ|íRÐr;ŽØ4€ Q¶†!¤˜ ’!((ª(<>ìp>Á0§d ÞLK¨¾©sãÌÏ1öš‰“q„xFüš'uÌ“!vOjG”LlÉêc*eXå?‚K±IIým¦ Ë ÆÎ=ÚÀWƒÑPüBJä>=ÈgÃåE!5;—LȨú)Gð¤hŠX”û6NÓÌ;æ½Ê/ˆ£ ƒ²@a@ÐBFb@‚iF{ä‚'ñH$IƒC!D6m’‰óá…Ñ0|¢âP2õèë•”‚“93e,F&L‡BDı˜-L"‚2BÖ¼0Bd6 ‹¨Ã%÷I³óüJLqÌ–.íIû- ™¦K7›Ð×Omõ¨ ÆM@©  ‚ÜYÑþ‘¡®Ý¨þêqQw¤ÓŒ'îÞpMì 0{Q{ÒüáŒ"‹vgn èËeØ)$ƒ¬úŸWBf*m?òìôúz4BÔߟ%çñÌD ÀX>ˆ% P¡¨Ê##ùfb<úÀL'ºêÜùÓ=C@½HvNÅ ©1ã@IJt‡*~­s4êP1‡—S‹`††l°ž¦æÛA§ròk:ëiùé÷{…¬±…JÀé€rèDÃw\Y\N÷8´ ±C?0ñô|â¤@÷¯kú‡6 ³Ë|ÂýXë:~"9U;V°qLqÚ)ª›õ? ù»×x=çËßÕx†ƒI$QI0âJŠƒÇäÖX"aNh€‡ùÈTËUÐ49 ‡ã…0ˆxÊç¯Üö‘Ðæ_PÄΗé=˜å¨(ä%!ÄÞ0 1†°üË„›Í 3„* é& ¤Ë“q¦ÁÈAtIb/^Àz'wʬOO¤ÌPu€]þä3|./ |ÁŒ™èÖnò7÷‡ÉÇwGÚB;ÿ†¥®×‹©ÚZTçi²]vÁµ`˜1Ž—„¸¼nœwhUãÉ©‘ Ž0¶ºsÜR”Ç^9ÝÅ‹±«)+]þµ; hœ0}ÇqŠ%á5ÏÄÃY”îL,2a3,¥á㻊<”¶—¢zÎÃNö=ìSÌôõÃ6¶³Jl%4§tÝÒãQ1†ˆn1˜ëª'S°ônL[ª¢6S ­Å/gËãƒ|3Á¹á…ïÚm<µî˜†!Å)‚[pè\SaQŒ¥‚â”Å"Ö¤.p:[½8FLÁERlcÖ1f®Ìb(cF"'lãR¦Ã°¤0¨›8&S#fÅÌ "‹<4Ä¡¡M7l%§"[„hÚY[ê!„¨ƒ*;…,0Œï¿à·ÓÈ`¤·ì&´Ñ8£lŒ¦-1J¦±(ZËS©´êš ¸)A– (ÓVP¶Pù“¯Ìã)ce¢S$LXŒRAV†3¨’ ½6¡nKC¢‚%G“~ž÷YÞ¥DFÎ9‡s§LbqI‡jbƒLhÄÔk-aB‰PĺââĦVéo͉Ü,£w>1Å4¥9üÊbšD°N6úáÇߌ&ƒÅA>êaå–Í3cc¸â‡vöK²«Ý4Ò‰ÑIáç—w¦5¸Bìô!8ì›W¹ŽQš{ùTQñ óÎl°øfQé”dÐäIÛÎ@†k/ã~Gz#V‚"QYS„ÓÇ(˜¸m[cTbщ‰°RaL•_—¸¥J4¥)vh‰ß‰»Áj3"5ÇD¥”ûûî-câ¢Ö–!«ýäêXSŠ_«ÆõCäÚâÃ3´¤@ï"L¼Ùƒ‹ÄþG7ÐþY¿‰IïÂÌ<Ÿ '`s‡2O„ûðòLIF }¶Òª%RÁþxzwž&kmñéé•§Í$×Ã4‚ŽöàÙ¢³‰ô©r=ñ×%|zéGW¿ ó 4øÐPöˆ•"â¹€èmœïüÆ Ï.Ô3µ¶ß¼KÉýêAÿª¤ßÚdPIÂJ‡€Ë–ó) 0‡ÖG•\ÿÅÿ㊯ð Éáf4–ŠiH‘«wãúÿû×DüD²“©æþ´>`?ÄÔÚ d&;ÔHüo§ìíÿ¬4ƒ*QA*tãŽýÐ ¤´þÈç>!õá3S鹄07±fK:äÝéý<8¦õuò8>£¸ÑMUç!ßÔМ> §·¼o¿ì3äãÛÀ:{ H*‚hŠ£§ ÐþÏÆ>°‘41%5ÅÒ”Mú*¥Ì´i T”es+¼È4.%Ä¡‰ïè*/ŒˆúüÐÀÔ <o)I ÿ><û_÷³N_]‘¦ƒ½Hx›SDÆáŒ!*Üx€8BW $‹îñÑ?f¦?Ìõg8Çœ38ºái "ŽDhé nÌ^1±„ØqÜX K ¯€Äêcý¢léúäÁ üÁñ0ŸD.‘M|0¹ÿþÝz¬Àù€?k'ØkÐÞ(ÁlýPBÊ<¬aö8§1Æq ìÒ>"Î @‡·p{RCÒb˜“8 (wˆQJd-ƒBR„E)¯£ø‡V©®˜ù`X!ÒpÜÈ[*„yô¨ =”ß;J>¼Ÿë—ï J$B”#C)$DBE%þÅÔÇwÄþªu­O½±U%1ðe)“/òÁØ,4ŒUC`˜ÆB°=9”3#Pç5.´ g(ÄSòI Ë!ˆ9  JÒ D`*…‰O/ä‚e %V$Ô‘èü™@>?CWᣄ¤DŨ•´‚‡”^lб(ìb–í§â¥ß/°•Klh#J1•œi¥ÆîÅ)†qDÍÔ-‡ÄKצÅ1˜Ð¥ßæxÅ:ÄBÒ0´Ò“ë±Çä{cð{ÈÊbà´šMµ­M¢þ cAhVQ8D£-dCDŽ&Jq9çŸg ¯û…Uz|Dš#ßÂ(öàrwÊô’Is¼² “>GËø+4~i# • ;}$ñ„wPƒ|÷þ_äßà i¸t°ìb°ã„ñéòš{ú>tú|>úÞ/»]\Së Ü|ÂXhãlxØ¡DLpŒâ”x¶ƘØä8¥”îq_Œt0³ÜÝlä-³qoæf„’2 ³¿äCÿe÷+ÄãÞ#R$î#õ;JPÞž£B”²ñA¤ªRÆS18fU¾/íóÓå=užá‰D~SÞ;Ôpž(%°¡¥{Âv£‡u7Q=§‡Å4î.Ë­6|fË[y¼»ºô´á8ºJÔ§ LÂÊf0qG¥Ù.®c¸Ý¦5ÃŽ+‹)i‡š‡tN®iòw±ð¦ŽzÔÆ™LRìÌX–Ô¦´˜ï Ø^>`ã!ñ+6GZj;©Ó¸î)S„a@¸£h[\Î8©®…¤©PâäÉ…-)E8£;‹·»O‰Ø†1(›h˜¢üùØ-æ¥í±kYOJ ñîâÏwÃÇž4¦;q܆,á‰Úê[eÆ*eÛð¸1S±Í8-[y¦øxKéÔ–dCS[/ÄÝKi½Ûb˜qn Ð¥Ï3¸J ÐiAëš”.¥¦§Ž‰mâûlvº&)zŒ™)Ñ0úÍa†ÒÖÌ{ާŸ,|ú{½0¤L‡ÒÈ>DQ"De;­ú8ÎNdg]ª0âf~‡Ô|_HB0­–—‰ÁÒÃ0ÌÛ†ä˜ÙÑý*qÒ¿2 s³ÙÇ¡¡„Ý<ìÒB’¨ ÇãÙÂvÀ+ûµ˜i5t®ûyÔÆ0rCÝ…:?Í!¼ÿ&CŽ¿›cHˆÎÆgòêgü5pØè`dÄÞÚ2û„éìa­XAa“å†djhE0³!A˜B–˜‚"©qp{0‡doF>Eëð?Í8ë'U>èO¢?f[hË™a‚ ¯„¦ë2M$Pÿ7§I‹ Y¥ÅÒ’UD¦3ÛLÇ(óÃ<™+à `bSÃ)Þaš6̉@@‰§Fš¸–l'_Y.¡`Á£HlcVŒOè¡æNÍÇPrC‹ÀìöŸÝ>TŸŽD +Ù4u€áA1*f ³™68oÞðã®AbW(‹öËU Tþú€(@qHRza¨pÅd‘d¤21”±Ka;ý¢‡”P»SØ+F¼\Ÿ"Ø9 €Ÿ+ # Ìa…Õ(U&ñÛͽ]²•õ:AaÍ!m“×"Ë CÕÈbÏ!OB!¤…âò!ÙŽ1“d丌@l­ CK Q8wúgŽ„åÍj'Þ ±pøûbvȸk …dæ7›Â³ÓcYÝwý^e$Ÿã|[([øé¾¢‡l[ƒœäXÆ"5ª&•Äò(|Îzš‡ûg˜ÈæSj‡}²n-4V›³¿¹ëø7fÚÞ$ã8@Ž p¡‚a;'w>‹ßGuD•p^ž€‡t$øLlÁ}ÙÀÖݸq =„2<_£ö<Ã|&?™Iþmˆ¢Jªhª¥ˆ=Ûö7JàÏc…—öàXB†„)r.3þõ†LÉJØF¡*ŽéC¶Ï3‚¾2­1vH:£T7¼m[—ÖNùÿGȤŸò8dBd‰ŠÓ:ù@šGF¤¤€Š¿ÖÉáØs<á•MÌuDóPô‡€g‚¼'ŒýL¢ÉÁ€C2RĉÊQ1 §ü"%¾ô æ@() D *Š(üº(šMI§¿_6@ÖÖ&Ã5É¢‘?”C×°”LßÍ“2T± +M(mî2½ÀœIN(°@v¼¢‚ ÷>Ð '“×ù²ì‹Èuƒl<Ò™&s’ßÛdÆo Yý†SÝ?Ã?åů÷%G”Ò±›\:wQ¸ýß\˜ÓªÚ´† >ˆo˜¢ÿbHlPòI~úHlxÚç6sœã)"ü©¿8xO ƒñ@9=`ÆÿÓÏÃ}‡¾½Ñ8údÕEGs™ "¡‰e!4SÏ®£œäô¦Æ©–Ý ­ãÃ9uŒ0}˜C ¿Þ'˜$:DO”ZïBÂ}¿dëï'p?&ÿWàW fk0ÃpÚ¤ÔaP ³IûOôɶâ@o¶^pçl߉97IH¤bòˆpÊßãÂcMÄèÔ ÐLW‰ ›°‰£@‘˜ŽÇ(á²l)J!$ŒK†dÆ[‰r B 5­Af•U """2͸œ98à)¸ðQŽ’‰­.q¼ãY£eUß"áA0fM& Ðàf¢*æÌÁ¦Z`‰hÑ¥‹p÷×µN/¾w0DDLLÀªPBŠŽÀTEDT&+3,8Êhu\&¥¾|D?ñ/,= }žÛ½ç>Íí?œÄ<3SÞ}>™Úv²Šü^õ¯‡çzf œÂ.ã°9d˜bþŸ%ͺu"wõëwІ€lžAò$DÒÙ;¡?AŠë­¬Ò8±°Ÿ²;`„êI˜ßÛ]$}zš£zf¶­úîn@ô`ý‚Øý9¼€nw¾æbë¾É”ÏÓ?ÕÌM4ÖZK΀ò±º¡¹¶.-m[¾ð_2™ò D~=ä'›ÑÅÐsð?b’%i$ÜÐDœd“Êè¼R$&Tò¿‘¤_ÆfÔÙ}—rV\â+!×ñ]ÃÓœ ‚Zh~_›á¢}41 »ÛážMŸ¯¯S!Gi¨zþŽú§ÛÅ5^Ù NÀåËñÔöápŸx0§ÈsßÜ_Qjê@”¥(âòtÜPQ˜ÛZ=–PøYzØ÷BäîâÇ]Îr,‚›aéÅÝD˜QnŠ4rI·›+‡E½V‹RDn#s¨M›²9ErõgYȶˆwjB{(¦¡4E"ƽDˆ»¾‚3Ó[“Í]S¿ac»d`æ¾!w…ãÜLR´(sc+"ˆ«4’pé8ÝÑðv–Ý)¸áè¹#ܹX ãN)¤°\L³’Ó2Zäé6e{Í&2c}ˆpiè[|ö6:arÎs*›Le"íL ¹“i©¦ƒ²2+tE^‰ÉR¨2L6Ñ"W!9q‡ù$ëÖÒ(¼ÑȸŒš’ÇEœd>mYÜ‹,~b˹U&Ô–¶µHâ„<õ¦±Ê3I¢Š3?w¼æY§Ž9¥3¬Ž2ÃJj¶wE-Š6DRðSBÖ'e¤{ {ár‡ÁÞ”N¾üDÛC”;‘t=Q0OÊ,¢ßÓƒà‡&¤ƒ,–¡R…ØçàÜuÕF³ÍSÌ}?=ßwöÇŠ+ðü³>»–YQù‡ÒIª ›ÑÇ‘n£ *,ÔArÍ/ϧ8³°ƒuͬl¶8òTYE9’sÕM–ã§iâZDS–.Œr‰ÚæÉD9,‰·y'5æà‚Ë×äÒk‘ÎÔC—'^"D9$5·Æ‘© ßÏžMõü7t0ãäïT/4‰>I°ESÑòÚ‡v¾K‰<šcËc–U.Š&8¼0±id]IvδDÁ†D¼dXEÉ9×KM/ 8û²EaÍ+o( wn­' ‚Š*éË(ÝÓÃ"ˆã¼%¢Ëä+ñaŽ# ûXIƒ•¦ûØ&¦ðT›0iÜa‡ï&我Ãñä¬Âà÷Ùj$Ò3½äA2@ðÔEEÍmþ;‚Óœe¨,‹&7\ì~h"ǃ·¥œä¼J’Ê'2ÅÆÑÚqEd2¾¶;Ù$Áò¨‚GáçI‚Ÿ®¤FFIf™iºôAPIäÜäI›†ÙÄ!5gSV@‰Ø3s¯$¡Q}„ÙÒ Áè¨Þ: â ÜÃñ¾~!<¢Ó°Ü!4Äòß³d±M@¸%]qÁfæ¥/µ‹DÜ[büeeégmÍYÛe–Hp?<ïÅ:-œB !hÎ3652046èmÚÖjÒ6À‰Q¥”=\]^æуÉÄWN¢Î>î§m8êM*N41Áå´®‹î£ .„:,”Xõ{2uq¢xÍÒ,£IÓGF äªÛy&ÄCA™fò`©ºÂ$íÙ8ý$ŒÝh)YEDÉ ²¢I& sT–r70ªâÏ¿?¯ßäßχ„ÿoìícP¶ˆ¡7K,C6×c©bj-Gt¤YFƒ¾ý™í<ÒbB^È>žÑ™éY/³Ü=ígÚZ¥ûigçÖØOXÄ”K>›C’QQWŽû楱hz°‡4.Éý$vw0tyÜ…`ÔÞiŒäyGgøåB,ð<ã›0š+ 0yX¦ˆ"¹…x¬˜$´XíeÙ³›¢ŠlȤP¦šY&B² §H¦IÒJQæA„OÁëß»ø{¾cœ±öϵ" ?˜ùxpŽ>ìEÔqgäU÷æ]äÞi—Pò8äÞ;ÈPHè_9^3”äÁÂQ¢(‰¡å ýç¿L$ž sÓ¥J»Eq…>šfn@þº¸«0O9ÚM݈Ù#G·i:Ü~ߌ§ :£ŒÔa4håa¥qCÏO£”„st.³Q-&Ô9E˜Î ö«jà…&d|õ¿ûCùã‡ ó ……vÛ†-|™‡ -kòØJòÙKn,ÉŠ×ð}7ùñ~¤ò(þ’m\ˆÒ§hÎÑÉVl‘´W±j«4yÚ–;gv,~XöaÉܹ Ò$ˆ¶J‡×{‚šz¥]*rÇŤDšaû#EA1Wég³ü~N|—?5÷ÁñÏöa X™=ÞK˜ bI+À±tm8‰–S×­JÙ'²Õm»6 `ök®¦c6c,¸Ñ`˜Õ­¶Ì+uÎðï4;;_ýØ] ²rÚd¤Ôk0Û=·;;ÝŠÊn)ÇXt +™3‰.ÞÈ=¹1Ýg‘̼«†ÛvŽ&bǼȡä÷¿¶<ÃÇwÎkzIŠ0ÙrzCæë&dsòvù xþ,›Èü5ðñ t‘Ï«Ã'McbgüÚå1>|›†+‡žö`¦ ¯MKåîSÐäÕ¨²«ÍÑ?hwõ’9Õ‚à!! ™)E÷ñˆl§ iH¯30Ï:iV7ü—Þ*!r¼þˆ H&‰–!AZ€w×9À´ 8r'2„ýVäø€áSƒœž÷nP! Ò¿ˆßÂn/ÀïuEÄ™ID¡„•úö‡‡x „Ɖ‰„Â`@ z¼8ú£š'Îê)Iÿý²XãŽ/÷_GiÌ:¤É®*4˜Ôk?u:™¾ˆ9AºåLòdáÒa–]äÀˆˆ +¶íˮ݆ã›w 0„M5¸ã¨âˆÂê BjSå–YØM9†¹¬üYÓ6pô£Ï\aƒŽœxsfŽ‚gp£8åœåömàð8ðÎIY—˜tD¹ÓºJ ª†[Ò\›36s¾—'â$¢QÐW?ö„ùÅ´ŽÔ5é[Ídd˜<+ݨÕ4‘ØÐrKÁ—‰m“¤àŒ:JµÓ¢{¼‘TGd“#—tŠ+²+m(LêÏSà2GXpಹßȲÀ3“Co&{"°Äç9®p›jå{“Ø;E]·Îr{ûNÊì¿výöPÀ…²DÙRu’)y; ‘"\…ŠÓ{+XŽ¢Ì6&4–Ù¶ŒÃ#hƒî(ƒ ºr4˜ŒCŽ:Ž:Ý­ŠBØ:4r¨†~rˆ5ÄpžñÇ#¬»*"åQmØ9B»ès " xgÑKM©¬‡O$R4L›/žŠtҩĨÚâ°šÂʦnå8ð^vu#,èggã~9ÝQò+CóF½‘+]¦x³`¬i!¢i˪’Í(²‘ͤKНh²$œ6.´£M{ûBŸã£tŠ Qu.9§ÅÙQÅNV—CŠaÚ_´áC.µ’È„L8ñ…JŠ(²-m¶Ñ¥?A½t+¥£ÍIVÝØ\YÚ©Š.Ç‘à£nG“-Eôþ¿KwhŒ³x¡e’V9b& ‚ªiݼ™"l’ ŸâsÂü¶ªÓ°©!<œä˜"«rè«&_÷ÔÊÑ®µ:Üßd˜!zW´äÉ"ÜË$Ò £jñA®ô“`ŠNè‘Ê$Ò‡.ŒZÒãƒì¢Uœ³ .wKâ\îâîénÔôºæh|, PtõÕœdœSJ²f’–9­Å¹#ñLèDœXéÈsváADJ44H¼&¤Ž+²/‘­ÒÛMF-/^‡µ¶[.‰çw(¼/œ[qcÎé;Ò]t3³rh©‘ó ¦Tð×B— £Ž"³9®ÊzÜ£]È7‘M†r5ð“…ïô@S‡`¯d=÷ßdýè4f†ÙðùíŸd‚Ãô¿É–ü!פ¦ô¢"ãÀ¡KRÃÝwXIeÖi9d˜'ùd†U"„òth÷F“.püFA*$ÆÜWzKEY@œÂøÊ$ÜÉkÎŽƒH›/(ØÊ² Ö¡,H­b®¶h‚E5$ñÅLåìÑcáeÇ;Xœé(ÑùÇÔPæ6FŎ+²KzÊÓV¿p÷ﯟBDô÷ìy'Ëð¤ŽQŽ@ä9{º9-E=VAò&ZùÉ#´×qT±Å¶i¥-Æ(¢Œ§J,tå§3. Û[D9+ ,$š;xâd¸,±AÎ:‹V9ªÄWÓ$ó—|<Xø!îG©&Ñœü#K·ƒLfˆ›3`rº#‚º5¡¢ìáæE:K=”aÆÓ<'£Hã?ì!­´á³3“]x©l«„ËÇ2”årx0©sŽ=nDé³,ƒˆdhñ„n’J±‘¢Ó\'¶ƒ2v 9ÍA †Q·-Zv“#¡ó‹H}$Ù4Æ¢Œ6«uÅ4ûBœ³gË’uËŠÁZ5œŒ“‹BЍFOŒ(³±ŠØyÕ¦¹LR8Y£½Ôa%ŠKÇ(ê$ãLtò9ÅZ¬"E-„´ÃÙ†é¼a‘úòd³ŸÍVª$tè&¬G‰‡9œ^AaÂs5¦Šé[•£—Â’H,n–NQ&É9Ç;Ê*‹çÓnBDRyä5k‘D Â=˜JÝÛ×7dŽ0¾5âÉäœP‡ëÇ3 Ì~VqcâÓLÃÏ8Ü4ÉÑÍ-ª4ÒÏI¢GCÎë¶êùë|ý0n.{õiNšÏŽ)¿¦1Õ³´ã¼S•NlE4eYEX¤™„‰’L>œB¢Ky;& ˆÖTj8DP鄚HDKA(¼â,¢„ÛºZj¹·QA£ñ%A¹ »$qûjޱÖ¸áÊæ#¸­£ºÌ ´!Â$ƒ^ˆU"6oxrã–A°Q-›vÁIµmNi†däû:¢É£Grd’H&Û‘Ü‚o(ršI*vÔç)Ä9>Hš ©"Mu–nŽ\æYIߥƒòâ—ý›ç$Ä&fqšLµŸñ›:¢6.VYw"i¥g/ÊC}^³é±›ÞÇ­‡k[®ÔûÀ„É&t¡ÚäNPE>¬w‡¡ß?}J”®Ôë}‡Ogq)Qyaé&Ä—>ØbRšläN?\Â[fÎ3Ñ ªB±Š€¹áÏìK¹­ÿg gä,ì””åBDZ ¾0ò—`þû¾îŽiœ ©¯f͘_0{úbÏ¥@S²O·%̸ZC?¶ž eãnP ÒŽ1zÉþpƒÎi‚±(±Ô&`‚ç9&!2nûelÚeµxcíþY—KŽþþ¸v‡c¿D¥ ¾Pȉì=;›–kRkñl#XN.#]ÇêúÇS8< Í„Vns³>« RyCDPºâz‰ØÛÕØär À³$Ô PЩ ÄÆ”aDkVÕ$íµã€8ãm¤­Ñhê?3':>%oN6‘τПŽÁr «&íTùè¾ÀßbíçAÀÆ35êÍhtBzSZ¿ oÀ&“IÍ(Ế[-ï‘e¯É7ƒ0*ÆB¡3hÐËyÎa†A$ãØ¶c‹+ãCI3¯Pâ^*þòÍE9ñ¥½bX?( àö4 ̤êÙRûRj*H¢ ØYa‹Åžä)o"f¾fú}Múlo‚øKqØÃP*%Ié öm$‡¦ÜþDrŽ@3ÔØy2’ìà•²R ó*˜›ÚfRòÃL6ÃÏ<’°=.; 15”ózbɘ1}­n´¤™éN+$q 9ô Ðk¤ »¯Íc1në,=þ½×˜ ’m…®m…¸2õ¸ÓšT4ôwþGÍ¥er ’šPÃÔ1Ýò'^}8ïN›ð]”ãßòjXܤá¬Òb’ä’Í vo‰Œ–³*CvÜÑ\tAÃgÈù`Þíßlû£P|aÃ!ˆpÌ´bJ\Jõû%œðÉ™¡9Ï«'ë5HˆˆŸ¯½ÞaO«Xd›¥ Ð¡ŒÛ”ch†8²½ƒÎlÚl‚€XŽád™nïke#FS·A}ì<³Áµ ã5Às†86¡?¥ÛÇpûŒ”ÅȦ }ºÉÓ¶Á¬‡x™ †’œÄÄÐsµL,áÀ]9·€QËÄa•X½Ók¡0w,-LÈBLŒ…·?LN~v”Ë>-si·SAi4‡5lh\ó(J·Î—Qؤ„Å!(pYa²T4qü¶y¼u?±®ï0™‚Sùáâ¤Î2¥Pí›êõhC_&h†H´¢pEaˆ¡F)N&Ìú»áõœžÂtðxêË<Èhò ¡¦%¼·yhb5'åŒA{(Ãf}ÂOƒ±&tX} t‚†Ã$Ä&ÆŠ")Î,†ì4<Ò†u¹x ‘AŽ^ž[&Ñb(ƒ°Lç—‡qNšJެ-âÉ4׫dY€¹øÜ¬ÜsI¬“Ç8Ž#Ê$Ñxa$ždM˜SùÄY5fÖ#'Í’J:IÒ7 svžäx8u&8mPª4ÄØ†‘@£m8Y Ä&  † @´ü©©u/3ÈÌ;‘˜Ø!È8ð­3 -Ý¢¯ ZI§ybÚ/|ÊFñfùe"7â”`TÒqof,ap°Š¡¤œáŸ|çHh=Æ”—ÙeôÈö8@¢E˜$¢tÈSµ)«É– p“IÇ’Í¢¼]FæNŽG_((Š$Ï ï†óëÝ‹ÌGsš-ÆÔAåµÁ¥·±f×`øûzÉ;£<¥@+ ‚ áž9ÖÛìxg Ûje¡ƒLIÝ `"‰áíñ=_õ(sdí¤õÜOÕ±ŽˆqN7ž;c?iôYéîšaáðîyÎÕO2Ý…ž@óâ¼·‹¿!ÇŽpˆ%ÊðÒJ|rÜeѤ9®Óçƒxxçvó“Zx‹r‘á.q£µäQP_põs”-ÚÑ')ÚF¿„–(³Å&äÕk‘g®ZiBrd àßdEBƒ?zF66$A‡ŽäàïWpC›^êôç¾CŽL¸R(=c„bhÃCb&k‹®† ÐLã&pUd$‹ÊQÒÃK9:å”#|" $rR‚HÈØðÆ^Vxç5æI%:y·« 7Mb ArqžWƒ¸ôœ]ÄxyÏÝæyÆΈµ‚ðB-ÐÔ™ÐÅ¢H é€ùžyæ J¨“݈_QwÍë³’ã‰<,¿ 3›Äac’ÊàçrhBó¨²Ê ;Ë}½*žÆÓK63tƒ&cJ?MΧ'¦Û a¡‘yaD]ûq¥DC‹| vøv™Û¸S³dê{þl)lãg¿†®êjGX;%4íµ"Ø;ã Û¶1—Uf†, "ñly-÷(²öVg·þ¢«¿¶›08ÓZòðƒ(Î[rQƒÔ-Ê3Í„=²$£ ÖÝÆ‚è£ð³ÃG‘yq­ÉÅ’a§åwž4âðÑqmuµÏº+¢Ë&D\„[á±¶ä™Ód¹áÄx4‰±)ƦI&äÃ6¦5*1 ãÄQ0Q±³åÌá–;PïFSÉàìy=4&CñÕs%QDjnuXY†ÛùƒùDžM¹¬È@ˆAXé€äf,ñËrbÐÞx#à :|ò(Áú 2uQ0qá>Žë“õðü[„Ý4;·qûhÒé7¤A]"¡t&9–þYÓçÎBäÉ2"ÇðDNrówÁ|*—ÜƓÃEsvGl¢›»O76»JÏ,ð¬‘ïÂ[ ðx$ëk¿ HFMJÃŒ8¿_9¦SžL“6‡E5U“?h––^Qs)Ðë)¬“Á÷ŒâSq–|ßvA½L"* ðAÉÐx&lVþ4~} t±ŠM‹áÃpy×)1$ÁŠl²)™uf~‡+߇®‡ý³†×H_'8Ê"]¼9ü<#"©Vö£‡$ÑõÏp]"­ˆ¨0“¨}"I±n#"Í+Ï<ÁË4ÝÝ¿<: «–’ z‘Þξ!Ï(ÒˇÎg´QÇÙ‚”·Ä8‘~Ysâs«ÂNÒFÉç`æ½Hÿ´å îPç- ¦õè…ß®o==Áô‡FÏÂ$ÊøQŽjmù‘ß-f4/bI~­D~u þÜÖq÷{ÊšðÏ]x¼o‡ë”^µ´¾‹Ä~/ߎsdÜ ç=›Î~‘â\Ó!;0â›ú!™Ä ¼³‚7Q0ØÐܿ܀äÈ!ù½+u MìõZåÿ·ãì?9 ฃÞ:!„ø®#zÞäÌI ?eO_á0Iò_L~sEÏ0¼ÊñË,£è °bÂ:œ.µ… LalT)KY “( cßæ|«îtšŽÐADxï:züÞ…ûAÇ«.r÷ú³ùµOR!‘;ÔÊ"ä† Ì`âÍ©`âqy ùÿLÍ¡—4L34R‚TŸÒ¼OT;€öH}ÿ|…3`€›ä§( ‰0ˆ`I’ˆIøº{}¦ú¤Qø?0Íú°~ˆ6É‹TQ¯ç“QüÄ…=æG“”žcI¿¹Î<$s¢\Àê²czæ_Á 1'å¾á4!¨ÄcÛ›&˜i(„+ùÓùÆNÌå&ÁÆrd—eØåYáçU·nxXæY™~XžŽÉ1œ³¢ˆÂävÂjü“‡$Ù¤zÞŠ/ÃnÒrÎGqDçW)@ܲł2btÆñ ‘i3r0ñ7„xÝEtVळ •çIYé%R”œ†ƒA°u6CC ¨rÍŒ, $¼lÎÉÐÃq†É9f)Š¤Ð…8ÑÉ£},z&" òÄá%÷šiØ;_’9¸¡•éà Ž"(Ñyf™GxÜaµÇ ÍÁy³·ÍoÝ÷%ò>$“zDǘ³” „µ1:*TàøïB,2‚ÊÊÔ%øæ!YìäÎ(…;¢ju,& ›ë&2c ˜²j`Û?9§àA,“”ŸËR˜²4©iOjk©¦âÏ‹ `¤_4ÌM=ór¼$Ì&üFNKögå.!ƒ1Ù’a­@„¸ËÓàtÔ–+ !Ìè³ '6(’E¾xi²xõ2Iâhë£ÇÒÌ:Ù°<e–IBz8³DUå'<$%yG· ÝâÎ0ð©æŸ3ÃNÅ=SlȼÎÛÈóÃÊ‘|£Þ(ði—! c„Å!©0â"Ó‰’B`´äŽ2]àæ9æ¥y>9•áÄ“tf«ÞðÌ5Ë]™áó–ß0ï<ðÒªl’I,ôÖr$Y?Öf“<‡Ò‡Ï6ˆ‹p³©1²$ò8ç†ØYwç‘p<¹'ž"Þ qÊÑwÜ;Íã7`@äaÑN9ä—µá…mx´±ÃÆy—„ÆœñáF\xIŽÐåI£¼—Œ-ë`ÙT刄xK­œŽ3O6ä”ða„’\ð~”/á0y ÎÖ&0S§G…a4\ÉPÆÀ¬¨¨Š#)µ†Õ4> ”Né݈5a‰i¨Ä†²be¦:ªs 䕆)99ÕX?Dr3‡ ™Í²Ì‹m,³šæBI›&%åŸ>ŒXþ9Æ]„xa僡Ëß1Û‘E ²Äxj$¾N–ÝKa4#XIG6Y0^4H¼ZÍ’8É![ÂRLÑdå!Ø¥„0b!Íš2a†¶ß“³Ù]q”v4çˆ3^Úêï ›ÁÈÚÚÁÈÓ8¸$Ù Ûî6Š/a«Š$å¿H"r£&ïL4†™e¨”HùóÏd&V»+DAƒ’|ËPn•“²NRL°ÂóIa!p Ä%14ef9—Öƒbp7…à‰·5‘ã”íÄ^pýÚguLlG"6ÓÚåk‹Ã€Ùý7Ó£Xû[r’x;D?²r&h¸[(1ƒ=÷Ôøüzç‚ߎ&çßÜ…b^Ug]¿ŸñÚ}G¶ö=ÿ;P7 8(À@i@öùf?ÇüýôuÀYÏÂ@Ì4v\£ÕpBd·®&¢U¨ i˜µ;ˆD Û@òHÁhútߌ>ìbÙKù|ôÝê)Z]h_YiÊüÜSK¾ôãqJš¦Wì[ƒ†ŒQÃtö0Ù ”þî€!„‹.©YÆ+Ù~Mê£óù,ºË‹¤Õ!ôJÖ”™àÿ6Á0f?n&Ç[|ÞdÅ)‰“30L±”-D|YƒD4âm¼Ö³Ë,òáúà}/MìR–`M7㻄£zˆ¡“Óù/t¿Œž†Ôµ²…јÁGSRµÅÅŠ¡hc–%gJ+ ÙQ+áÖÙE%¤±2‡‘Ã1äÞn\˸"8DR§M%¥)eß1€ÅFV•im«à»vMJßN¦ÄKe ¶›°ÃQ+F©nͺ¦pP³)bZQЫhˆÆˆ‰¬Å SÖÒbùx9'/íß6‰i¦µ˜(¢#0¨P«÷bd”¢ƒDŸ£¦,ª%¨XÚ%žXY~ÛƒŠˆÔ¢Ð¥<‹†EÒŒ­B‚Ûee¾{vï6 º¤ý0,9²š-DÄ.¢  cøc6J(¢aˆ;-ŒAp¹ÌÔÕr4Á‹}‘“©ŒÄ(UŒ¡ae´§ë™1cÛ"(1ˆƒ˜ÌÈb`¨o¢áRŸµ’¢DÂŒ–V*Ñ<àa–(š(QQQFrua€&l\Eã QpÕK^mëÂsEáŒÃ9ÔoÃçx§"žŒ•8Ï…ãŽH‡l^¦Èò},CáM¾YfzR=!ä³ôŒé' ;Î=ï'I§ð¡Ïc”&É2OgJÊ<ãnèƒÌ0â´KÁkº=¨Û:r^ý¾ÖÆÇ=!ÊóÛ¥¼3¨ÙG¢B€Lþ/ <ò 0ƒ0P{â,¡Ç%ýœÇ£±Ür µ[eˆŠ ŒDc ‰ÁeF¶Ý9ÂifL!DxX¼ØïÄ{ïIá‡E³Q9´HÆ l¢Q…!ÁNŽ oØí®O|òwäŠy·I®²#×8õñ‡* ÷Ã$’bmxñ" æGšQÞDçaÐ&õÉÜãyb,Pà¥`9ÉrJÅ:ئ#°fcÂ1EˆÉDIwÎ R…'EQpfˆ¤ùì‘“Ób–#š£‹h³z¦M .©L,*ªï:tÄF1‰ˆŸRø@Ç3(¯kKBÆ'6Šš¥á¢"'E* BQì³^½pôGK=6H™á¢4°l÷‰ˆ$¾Å?;§"2d;Š †áx[;Ç¢¿<“DjãTìŽxy~éX›ÃÉH^–,=s<§+ÓŽŸ:ÓØ ÃÂlrðP@½«qÿ? @„|¸†RÄ=¬0ƒˆÄÕ,eHQ—2`âgµš&©YÒTÂØ‹g¦RïöƒQ,t4Š‚¢3x61ÎeŠˆ)„ˆ†ŽÈå¥l¶’³¦kU´¬T_Qž\EH‹è0Áí3ˆ¢¯çäs‚óÛgt˜BaX¢ €ËIEb—2‰Ð…EZŒdY±w=ø®Ãæì¨žR‰Nl,éí¢ìÐå¤pjœ4I œL‡ÅÌz‰ðUøVN_¥Ö9#ÊýiÚÙžšc8ø-7òÏLÏrôô÷ß³Þ8ôñ¼ÜId—µ‚*=˜¸òp“Oùd—ÇéíG†ÃòöÓÙ<Ðö#ÑÎ:÷üW¹ZišMžy'éh‰ó•ih‚p‰Ò>g‰Åì}w6…Å×Bo(¦ò 4ƒLö9 É.~|ôËl=ûï§5ÙMóß„ù[üÓ©ºÈ·ùF|›<½%9ôè²GGóí~ÕäÃ3ùQðªåÿû™ +‡ìþ²ÿ­aÑI$Ò•ª [sttZÁgwšËLRj!ò2Hu3ë¹3”%Œ‘ò|~o•¦€s«·ð9%ÿ ®‹Ó WT„Æmø²)ø¼t }ŸDÊÙÐÏŽï„͉Úœ‘À.÷° ôúGר@û<ívtÕ¦£ýS¬¨Œ¢(r`´î  Z”ßàqÃpŠ›7-¢PEDBpap9âgGY§-2 ®ð£Ò·ÜèôGY÷„xk•éG¹ ù”9çžù6G8V9áÄ?„SãMQå­›áeGxÓ£ C#O]4^û‚I§Œf 1œÅB–Ò(I³€¬ÜØÃz-‹… §Dpmd[Ó‚`0Þ’‰…N“ºLËØ4ã5ü=4¢äÞÎöÌ6È=è$¢ 6ËÛØ$ÓGˆm©ˆ$ñøð³"t‚5dÐqç•Iéê4ßa¼Dû1ÐOž£ Â!Q-ï©úß©¬Â¸½ÂmœÒy&q4t³£H#Ôç„c–c½I¤Ê€¼ò;Žæ³NŽ `» Qƒ)hõ )ƒÞìpªÅ’b6vÁƒ§b ¹‡M1$Ä6Éš˜¸[‘§ŽL˜Ç'ÜôŠ*Af4NùdÛE{¹…©(3Wp“h8w§’* 'OGqåÖ¥NRŽ2ÒRÄa{܃”¢ÞŠ`,p´±*óeSPYAÝ¢~XÌ|N*ðŒI0ic€âù@$! ˆ2p©|›*ü,.Ó‹W¥Šë ’Ÿ¥É²$ÓÏ Ù<Ñuî“áø9åEZê8÷С³ŒS§ÇCÙêòŽ2Aƒ1¶§KJ$Ô>ú9x°¥£Û¸JtÔqTKR¢«AJuLj— ´9æ"6&bرNcXØØÚ6œÄYÚ¬F,Dl´dŠ“âmEÕ¦+FQO¬ÙñiN²¥AE(¥*;ÁãÅ*•Õ±*+i„{wN ƒRÑSNœîÚ "$Ö˜b"ˆ<Æ!’`‰i ¹Óœ*)q‹ÙÄ®1q‘ÌÑA2‘2•‚%k–Š"‰0߉:(P9M´fÜ%›# )°ãüºRòsiZ(¥K,-(‰*v)R9j 11:¥1…AEv”Ëb15s%zpa…¥Ã%Â¥3›‚›jpD¥£@E0âvï-­Ó·Ë ø{„ðï‘VžP-vÏvî̺0¢C•8H¤Ò{TAT{éæÇ¸D–Êa`ä‰-E¡s^­ê_‡ð7ú°ÿ\ˆØéî÷!.h%å>ªC² !ö33&*»Ä‰Ï`p}ÃtíÓÌ£Ú!H'¿¿ñÔ}-…\Y¬:‰aô R…‹ßw{ç¼ )]O®Ï;(íÛ×{&t÷d^×7»ÝÖï{¾û‘ñ§©/«ÛM¼«Iî.4ÛÎî[#Îûqç×wÙ™[_wy‡^ó·¼ô¯3Þ}yØwzQõÑvo¶Ò|í÷sŠ«ÛMò»Þc×½ê÷ßW¾÷µA½ƒÛt÷sëkžúùÝRŒòföÝ›íÕöÎÛåéóÚ{{vÎV®°¶hËsÞ¾'Ÿ]÷ÙõÖûlﰣܾß6{޻ púîìò¶÷ÞÞá¾×“µ{Ål |ìät4¾>Y Ãi·Ûpª È\r½÷Ô=5÷×wÚlw6ûÞº‹·…>o|ûÝÝ·€(§½óšjµfèï„7Ûç¾°µë³å;Øt¦€o½U}Û˜ÃV÷Æûãï½Í)-´AEävÈwž§¥õZùç×ìÞZµï†‡€"‚„GÞð=£Ã½åïT AÝë¸{ØЇ wjß}Ò< ÞÛï]Òv°2óß6zº¬·\лœ Öv»€ ¶Øyæ÷Ï9½í¾ç·³ëwšñ÷|}¶ÞíV½P@Ðèz=P€8êxõ÷ÏW¯}·oo9¹_>úÞ…ð=@ººñ»žìwß_væ¼Z@}€ åçX[<צ¸:€Ö¸Þ÷‚®øO¦¼ Ö½70ÑöõÀ·yáC¾û€è.Á×—@ ÷}ñ@(B”€1÷¾°îâä 6Ôºçzù·}ׯ§}å·}éàwM¾@yP2 ód{@"tTô=+ª†ùê÷…=܃ã½hõÓ׫Øôúïaè};uÍÚåWw彌ºJîàºÙ°_}ïIWÖ<Þpôºe@0¨zÓ·{^u íÜ.·/5ÝÒå½S ZÀP{Þî÷:íØ»§e ”>™€bì8|÷Ž <ᆱ¹Ñʳ]óUF­´Ý}uóß#ï{}ÙÜ×}îz¡¨à>ãjªMíÓºô¥îw¾ós1jû9Ý|óЊ¥Çge“çÝóÛæêãuœ×¼jWžˆ¶úoYåÍfPû¼ñå€>¾@úko=9çª}ëÝ›ÞRóî¾Ãw³†°w»žª*^ÝN•ï\ûÞÛÙ‡Pó€6ø 4ûnšc®îçÖ›·ÎûçßuVÂ̦l‰}n¬Ñ§ }¯  ÕBõgžÑ{ÆØ{¬évÂ)sŒé:§YÚ“Þ@¼kCÌÝ>ûÐT}ï¥__8eäs5×¾¾•+Îûò#mu×"vÛw6¨Tzbu²ÝÝ^nJNº9ô¥tã×Mm÷d{ïs¨¼U–l¾Õ§@h廫Û/MZšz[Q“C}€ÖCžñÞ÷i¹Ë6îÀê÷8õ€îÓ—E»¾Ý]êî»Îí;¸8kë­ÎxÞm…Ý®e«h¾QîêÏfc¯®fkËiíΫ·®xƒ'žçSé¾IöbÎ:=\ÉÈ3jéÖØ ê»M®ûǽ=¢ 0ìïeï“êëÓ@ÌlÀq°hÖš¡Ò>¼EÜyé­4žÌ»—»y^ûëï·»ì_Gu¨²ÙËíî5S³[5r3s*”!+K+Ø5® Ö8n.ÜíÒzÔ)=iƒy–î‚ØÃFEÎÙÁ»f6%@Ù-Ûtb±dݰ>½ƒÇ|tZSDn]ÆwÞçƒ^åл¶›SfÞk>úv¹÷yEIFÜï o°aßa·Ý]Æí§pnoo{Ñ÷èzevÐí 5v`*m—o·=·ß {Ã}šPåÉË.M[tnãG¯;¡»ÙY^Îãï³¼Õ_oWÞ÷ËÜ÷‰íËàm÷™¦ÞÇ6tâwÓc[Ÿ6½vk/˜/XJ´À(DÐM š€ ÈhИdÂh`F&&2`˜2ž˜ #ÈÉ B!@šM0#&€(õ6¦ 4h5?EOHÀ˜ÔÀOQ€d !£i dÐ Ó!¦&šÓ‚M"D‚4ÈM4É6I©äÔôõ4eSÞ©<§âSl“Òž(~”ÚŒŒÔÓAúOJhÐm5z €4@Ð4 B’ €š4h ‚b40˜? ý&)½)êOÉGµ&Ôñ3PÊzš{Q©¡êiˆÚšbÑ F€4Ð4 444Ð"Hˆš2¦#@4 ¦™ 4 &ši“ML§ƒ<M”õ< žž“ÓM2SôSj~š)ú›Tý2SÔQ½'¨žSÓI¶¡HˆM2 ¦Œ™4ÐÕ?EOSòM£T?S2£Ôéò€ÓÔѧ©“Ê4z€õ¦€4z††€4h=@ vÿoÜw÷íýÎsï÷;½ßxî0ÿBŸø<(DD¸Æ'‘,bªÔÅ`DðhR?ÊwÓ¿Þ¾ú©ø¡s–ïéZè²Ì ¨VyLI-™UµCPª‹IÿÒ< ˆË.„sE0õ¬Ý}þAÜ¡èóý§«õ]Cèr÷Æ/xbìcãÿ‹ó¿gï<¯Öý?cN¯.³*2*Aª¡@‘:ò`ã ‰p¸[–"I-Ë’F ð¿Ïðî ôbþ<ö¢ýÑêˆ?öOÔëþ½ØêŠ?x}ήŸÜø¾‡ÂÎ!ùPûx*ïI4~Ì»÷^sþü_\Ýö6˜{óz:èªóqå^iiÎW5ŒàÒi«þ&i–ÿòÇÈ¥ÆEMy¡qWdWlŠ¿ÎÅÝt¼ë$¦¥ú Ýé›–êk}™obQ1;\ÌËWŸ3HOI?Õ0 @¢V³_5zZg¥yŽš-`§d·•§E©•Š¥«ˆh«þò¨"")Ú‡úõsŒ©‡EYÓl»é’Ýt¬““`Vûk³µÿõïü^§ú›`ýñcü‹ù·öûá‰Ú_’ ˜&?¿Ì•zµüŽ‹‚…YçU*²SR§´!Sªä>Oµwî~{ÓÄËU_#Äžoبw7çý'M§ô!ìCËûùWâv+ÿè3ùXú½ (|芠xä+ûÐ(zAC¾þ,ýi=ùEjˆ‚0X(²³±üÞoƒþóæÿ‹?ÿoþËý|ä¾·Wÿ¹ÏÃÞ$ù?–úÿó›ÈÃÈÜ„ ¸$€`AE ö©C׋ýÿøó–Q¡þŸgö÷MSG|QûX ¹ò;®£[ømcì¿ïoþ=ßmä8÷så9?ÎéüއŸ·Øcú?ýŒ­?Ç1 BDOßÿîJïü1‹ó¨ñ䔉.>óù~7¯ó^3#O§ßêëö½?¨ÿSUêÈaø¿¶øÙ¹?8”4ÄQ{°¬D$A˜i¥JU Dü9? þ,ÎËê1}ÎÓ—þ*G~Y¿Ëøo³~TB"ƒ´!'Ø:S,„ôd õéü4¹¾Cá8]¯ñ˜yOù:Ÿ®ÏOë}-ÔåÈÿÒ€De”9‰òHpB øéþ§ŸÔÿ“WêÿÎ>&¯ÚgýΉßßáòÀ2Ò:Ý?bXG^P ìšç{Ÿ…•Àì:¯%¸ô}Îó ôþ²¸ÅÎüÿƒÊ¸îª|½úý¨"`ûªµu¤”ýdÇ­ñWSEÏqyßéTàaó=·æêÓ´;ôOT\¤³Ê¯ýe“vÃþ½‡Ú¡Ýÿm @4¢Š2›ÿ¯ÿò.¿ä€ô‰ó úÁz@ ä~ ¿Q{ãöý–ž¸Û{_§ðá9Rù!Êýƒ_¼üâ ç5|£%úg%ƒÁujp¯ÆW²Æé}»¦ÙEНjµv›_µké‚à•ÁYÔ½ÈÀåŠíÌî ²RUV°QˆPß- ÔÐÊ_ì»âY‹¡î›©cXÄJ"„±Š"P.&¹–WKç„0ȶJ¤˜ª=Dñ;K«ù³ä»ä¼Hã=}½ÆüPiÿwö([Ñh¨òœÌ<ƒGÔzGÉæò_ ëö;fRUæÕ./FXHxGHäño*ŒÎ#RAÀ ÊÉt¾§v!/˜»‰){u¸x×™5a« s¬¶¥9·+þnŠ^cÍ @ëfð¢›:48`k`]0ðÞñ€q¨)A¢š qg€ D@>ž¼ÐÍ2Í·hbívT‚¨Vm}OžS¶ŠîB¹Æ>Übòý·š“w$öÎó·l;XKL¿ ÁÕÒÌ}­§ÏCidšJTWDYK ùi.Ío†Më¸VŒ~e¼xÈ &K¶CrmÍý¢Üªž¦Á$ŠAÿñ·jX<Íò¢hÞ¬!€€Y›¡WI“›jö[Ì·ób±¾ŠòFƒ #<3[×g¿ òì1EâqØ@RŠªV‰)¨S>ð¿Õì¡õòõºóRŠ•ò>”p_‰§Êœ0¶rº ô·!PÝŽQ‚óEb¸}-I@”yQPÔ8sÙE±hÓ3ÈAh‹‚Hl5 e»måáÁjI[d§—cÔÖÐó6¤2™õJøòXÄs”u6ªimJãîzºÿt¹@|îýCèU”i¥ BH)}q0\H‰ €‚j¯ÏÃ" …½c)ŠH’&ý&ÍÄç©ÓJ:¬×gŸÌþÛìê½B’ñø«–§À@ë|ü$²äj©˜‡šV!%ð½ÄÕÝ|³jø]òœCh˜ø¼ë‹©+÷۸Iq…tQt_Æf&XJƒKñ¡õtg3 ©¬Ç2áÁ…&Q9Ä(ì™à¡»g"ôò±§ 6C­¼Úp< fiÙMìó‡à/…²uFn[}ý¸ Ì ³#{+¸£ú¿D)‡³Ò<íÇV†`¨RÔ¦4T*¤9^|=Ýê»Üîrrns¼ß}ñnûï\ç38&óœ{ã•y:\Xw󙬛Cš€¯nìÌ÷f%S&$F¾ƒ4EnÚ@ 4 @³ ÂtÃ#dÒAÁÄ€°°ÀЭ4ÑÍ5¢!ÝCV™ÍÖžfòðè048aæA¡¡¡¡¡¡¡¡¡EáÍNìp¶ÒÙJS£­4Gw33Ö3&¡?´õÎzéš88“[$5, I 0¹ÙÈF?×”'± 4,)3š{÷Î*óœþÀãüÐ*ÈûŽ1ÈM½F£^¬µ›Õ›NkX«r‰$X£æÈÛ0ZF ˆƒ%,†O‚ &NÔ EGo“Z`¡¦šc£=^^­ÁìÖ$½NgNc:0!r4q VAVÛƒãì°?6|oÏÈìöÊ4Fý&x„ó èÐì݃Þ‡°¢ Q¹Báa‚Îz²8út°0Ç“ÖqzsìË¡‘rɺ Ϩ„¤É€<±] ¹­Gê”éÙ¿¤c’kªïá×i¼ÿôŸíîÌÃË,XOÃKG=5îþ3=6o.xÓꎵ›Á§\ÚÍú¹ÌÛ7'· ­1ÂÎi$Ñ=`ÌùrîÓ‚ÞvÃÚ§´r¸T„9„ðëåè¹×òjÜu»Òµ¯;ýªÑÓ¯À•N•êÌ».N½½²çdkí²«Våpq±ë_oä@Nˆ€tVíÆýÊÑ,d™4U_'«x¿iËäxËŒœE+´´\#6ž[C…õA¸PÌU(îödÏþXtƒ Ȧ0M, 4‹˜w‚¹Ã×Â*C1ŒwJû\3nÌ/\ưÆÈpg­©zYºnÒ}åùÿKCˆÿ јy\ë~ôÜÌrùIÏÚŽœ›SQ¡FJo˜Ç9´ÏcŠ^XÝl6’Ù¢BåÕŒ’Ì$ºLœ†ÀF(—À …¨Ïôˆ'0=•rLÊ( (è&Jµ‹Í³‚~+IjíD-y[þ_%Ž8»YN:ùž÷'l™LÄ•‘I—O±ígG8÷vòðœ{NN<¶Dáò½wQDÖØéÊ4ääöçàÖbÎ“Ö‰ÉØç˜}Ȉ|ŸGLc˜ bq¬ÉuDæØVIíŠo`A!ë— Ö;›û§×Ð7á¶xðz"î‡Ë%¯jÐûnŸ¹Utq¬íò¥&³!T’6Bqp~e•W,°°9A&Ø8l}»£Ÿ±¤çT<Óæ÷·­Ç4çžLv“Ýì•mýóM­ 8 Eò"fÍA'Ÿ!–á|Ý#‡÷cÇTÁóÍûbà\{žRµ W=¬.\q cW»:Ò€$ºåc_"…‹p»$yƒ„^Ð`6C0…ÍË€/ ¬¸hÄí’ ™‘øbíÖÒ}YõiŠ‚-É’ ýÏ‚l¯ f•òq³öÈ™šãÏáÛu%’Ä…ºó¤DÆZ>BŒ°É¥ê`Ñü÷¾˜g™«âã\©"eX°00ļ«2¦2ÀM¬¨h†{ùf鈙'Ø¢¤0ïövø‰€âŽB;ü àkï«‘ã©x‰è ˆfzÏi@ú»SŒ×t?,ÑB¹rŽíØd€ŽBЬAžõA;Ôg1PdäˆÅ²†DÍœcõ…/­¨°ÑÈÛÑB ê—õT6”°Lƒ²“?ªogÙßÛáõo}tg7h7Rùò{/¤œ²Áò¨AîʀɉËKËÏBžQ”ÕÅ3Qò þÜÌ·^^ćfY±RIUAÐy/O¼/™Èy˜2ÂB$/€a}F½’‡Æ@ëL8€òC”7àíŽpÖ áÔqñË›Õn A[Ö˜m*ö|£R-•zB;ÅÇɯ ~燀ò>=ü¼ó÷t›ñ¶xýÿÛKÔ;DÛdé}/‡^Y:,r»¯=s( ’:?D ×=4êC¯ýh°ˆœ÷(jrJªª!ç/¸S×.˜ÈQÍó®=—B{B/½/â‹KÜ‚ú :ª¾DϾ¤Õr¶‹éÂ.ôlÛóô“pª„„‰7lbÆH™’„\.‰õ! Eû‘ MÍü²i‡q!É’º•@_b‡DÏs6]¹×ÞØÁ†Ø¡Öb)ÒˆuB8ŠpÀÈIDI2,Xª¯¿ñX|¼U¸a~H@;2oó‡Òy‘DqCÄ á„¡"ˆB†‚F•v·ŽîMÚ¿~<ݘ”WÈ vÃ×¶äMP7yxø¾ˆ=/Û“{Ф!&åH• L§O(v+Â`]~híJ™N^ÇEc ä‘$dEæ¨:9 ¢ázDN¡ a8ðÙêkâ¿n;[ÑÝРudâÀLÄT„ÄT‘Q#ê¬ `±ZK ÅhR­ÜÕ[Jª kUƨ¸Æ×-2ÜJ(¥)EˆÌA´QÂÕŽ S&µŠŒÆ±c’Õ­Ks&²Ñcr¶ŒEcU$¢°+NbcqPÀ€"—‰µÑ¦ºxbñӟϹÕ/Íò5ìp¦vlìšÇoIƒ˜†ÉB^q“¡ZŠ}ÝçõF}O·Áã y==Så’«‹q¬ØÛºP±“˜dݣέÝ[Èô±UZìïnæîÅ,¥î—W¯K.ÂÁMìÛm¼š«’דŽ«¦­³róŽË±[1o‘šlð±1Z6¬Cä»S5µnì¸a˃•uµMǾfë)º3iy;k7­›—‘ãÖnš×“º.Á”ê´¯ ­y°SíëÂÜÎÃ3+˜k.A‘RØÓ¸ðÕs³xñN¢´ê´åÙDmc»ÜËëŠÑ°®ïKkºDÊÞn3eÄ3½TeÄqÛrøLX£¯žV"]ßj¥–Ö2bæqîã'”Ó³‘»o.fë• ®ÊÚ¯£ÂC°ÂÂÔË.«E,Õº› I6R½^³Eíi]n¯xLC&2ôÖ£dZ¼ÔKì½lSmºÃ±˜Ìò“Õ3pøû­«QFìn×4Íì¯RûºBޱ³UO.n¼lCMè·“y8SÕ«Q«w9m‘ŒÓmQ ú·+sœ½©d§V{†™VÙǾ^ljÚ«lëÎèÏ›{Uµ ¶^¬Ô.ä–¹.´Ù‹6¹Âê¶\5RË ¸«orKS;ã.ŠkZ¾í¬fkÖ¾ÝTåã¬Fn­KÝc^Ííº©0Ë­Pù­*¸ï [»DDÖÒ¶cäM¬L¶ÂíLÎ66ÞV…Œë—2ÍM¹Y1uÎîYy‘Œ¬º¯0¯Uk‘…Ón9ƒf4k¬±ÍNó±k³W9 ¹Š9¹7µ8ε±3nKc ÍŽÛ-•¯TÒ®ï.ñ¯15+¯‘—›£6ÑÙz1„STä²êÆÒ\¬&S¬‹;7 ú\¡Œï0Ó’º×šØKxÕËe­:µã—/‹nû·KbËÌÔ«Óà Ëy­“»Bëñ¢ÙL‰——–ãlª»m½ÆfÎ3äÔéKjÓ¯ìͰÙKk—ºðSCÁ™2¶Ú¦¸í2û;¦Ôî]ZÅî®dÌ¶ÆÆIšå.6Ë3\=ŽÜU%µMFcâ©EÎåm-@Û$›W7T4fÛkÐ.æÜ;e>¾µÁs DcnnZÜ¥{8føK’SAµ*ͶØ÷m0«2U®nåíFC³±—9¦¬´4=B¬ÄÛå=Ó²ÂÔÎVa«2å[2ÒÓì‘yŽëP×/­z븴E^ÛâÖÌ^k>¼ÍN˜°n™›ví¢åí^µ´×TÕQº¨¦ÕåÞLγ<­¬ÔC]â¼²NåmLüzø=³  ‚ðuËeõÏ“K'`d!bØ÷V#ö}n¤€"»,BvxîÉÈ Öõí”kbP‚ñ¨Ñ†Eš±½vL€aR‹úoÜ6˜-™dîCaÚ.šê±Áö껳92åÌ¿C­‘,¿…ƒ66QbΪ‚K07 C^s«Õnʈ輺Ì598'» vÝ“K&Åê5åÙzÖô¥Ò‚&s9þMV®— ß1ä9·„ìµDC°0¥è„´{MF:5ÉkÖh„•­Œ*ÛQ-ö¼ "LÅ\U½ùªòú„ë~ZÃ…“N2mçõ—r³nð9¥æëj— 'N3.[)1û°^Ae&%ô;¿_û74þÏ/Áο±ùn‡!"´ñÃ<™ þd~’ä„ð­üÿ7ýûïÑÞøÏçÿw<'¬ç1âz]ìýËì¸?ß̨ó¤æˆÇ¾úF  œBhË”§ªPƒê~.ûðýd?ǧý[ãÏä8ÿÅö9Iž‰àÂ&޼ ê»… ýÅ@=ÇÆï˜ñ=ë¶ý>3Áö7…à çWÞyß7Ï[NТz# åêJ|2>ÑDO6BoÈÚÏÆ/ûü/?Ûm¾"àAé¥ôÖ'÷ìu˜Ÿ(;ÉDD÷~“gä:iüÆËÂxocÚ]7@Bï–ó–¼Yö¤4G0± !DNH€ƒŽ(:¾Sµ÷nçþú|µ¥ßõý|þ¤_ëÀOþ6¿Ô¥ÄSz ÿßOÞE·Ìÿ®¢þûŸð¾{EùCT"‚ƒÎxtúZͤ—!¹D:‚{ûܧöéü^žïóßA®@÷>#­öö ÿyPj‘jÿ ÀDPÏ~~7êxMíÆu§WÓÝÄ€€ŽOÌÿ§KsÇyž•Ðí^ˆ<™@>¦º¡ MÑD?¹ñø?Ù±ÄïçÁÇÃúþÂï(É Ã(-iWh"'+Ì(äŠ@;Çý{ÿMƒÛyÿ—ÅâõU´.Ïøn}¸-€ô"XU‹üè,ÿƒø_Àðþב˜õfÛ»þÏÄÕ«Ðþý>ÌþèESï`«ÿ4T£ú=ïÇÿ'gGoøyÛÞƒëüú‡H}·ÓÞs8´ùòt¾+Ïä""w¢ˆ7Å @„Dð¥tD"9þºnƒ½íº}gudëøÿ+Ædwèó~³S=7G8 ú> û•gúœìÁ;ñÿ˜¿³n"¿º€Ÿ¯­¹(€rüÿ¾êµ¿g·îü§Wö=¸D¿?‡eÜû¾ŽÚÂ( iGû‘TÁöß[ûšþüŒŸÿg—¹‹ýgâÇ÷9ÁZŠ˜ ƒ¡øú߉îþ÷ù5üßç~f•DùáD DG›(UÃ4ÇýêÅ |˜F@«ØSö?ؤîAr±PCøÐG¿?w@òàˆˆÿÂaQSòJ¨Ÿ‹·µt •àˆŠÌðW{m–HjSÚŠbJˆh؈#úÁüây³?áCaø×cSÌ¿ì6޸׋"Qk{8w.auC Kžë¹úŸrZŠv4"˜)pÉ`'tQGgœ=…l" ša |<.¼À© –ºÖ°‰)S)ç„Æ9ŠZXÅ?¢‹œµ= Ì-ª³X\WİPÜb–^á{î&äT…O]uªÀºcK³¨P9, ‹ÎÁ^HŠŠÛPŒ;êNç‚ÊÁÅ(Ùbd HY°é€/L øˆö“¿ÊNåpò -@n@³Ý™h„”F è) X8Œ‰ŸHa$†z³}p„THŠ X!Ðbl( ‡]M!IJQJÒ¥#@¢”ˆÐ" HH£Ø@øÙP¨”ˆ†Ë² DTÙE eðm€¡¤ŠL²CÖÏ&_†ƒ-ÃZiQK“ÈUPÕOýµ!Š•GdVˆH•wYEÐŽIH0K¨È ÙDÆB.œÔÁŠ0B¥¡e·€ç(*¢ ¥! ‚  ¤)K@bÆ0ÿ(npW}æDJUE ’ !ˆŠh– D64êR…btЉ¬CR&€PÒ`¡€íÊäUt ËlTA¤PBøý¨Z€Ñÿ¯U…@A^B‘D`W `òå’ˆ¦¢V‚ЉR%B©ZñÀdD‰@ÔÁ˜¤Q T´TäàC™Œ¹ ä-0AH”ÖK’)FHd)´SAMDR6°e0ÐÙ1QDBÄ@LATCJPdŽN “´³QDDF4€#€ŒA$E5TEADd…%2IT„KQYdµ„ÉQ )R!Œ LHD 5w±€Z±„ƒ\bšXÉÆÀ° BÀÌ(¥D‰B”FƒVP´=þ¡àx@]Á €’@  ‚ÞÀ€ ‚pV5€d$ A‚‚“ÜŠ0Ø‹ªch0 ’’šh`š‚JL̤* "ª(¢Ì œ‘1š‰) ¥²…‰2F“ŒºY„J’S Æ(AŠÂdN@íƒqSy“V"á„$KMƧžL*i`« Lì3N‚”ݬh!‹M«>YÊ"*$€ËhEô¾¨c±„2T(]=5b´Òh²œäâ8†ëÓíu&ÈN$ø(Š(¦¢¦¢*&‚Šš‚j"¨Š"¦¢¤‚J*‚ –©ˆ!ªj$ ™"&˜’š@<ÛhQ=èâE TÅP³$BA´ˆPÐH4´%*RRP50*AÁ  „IB‘5JÉ"„Ò#Ð1 %A KBÄ ‘Ð$H¬HPH”APÁ@"ÒLMR± UT5QJÌ¡•¹±eÄŒDà.ɳµ%U\u!Lj7† !€€€ (` @€  €”R ‚`‚ €‚ ‚  I‘]ЕSP P6á•LMQ: )C06ÚQ2 R„ ‚JP‚ B•©‚d"Hˆi’jZb‚€hZA¢`"–”Xh€(fˆ ¡“÷^ðØ4€ º2›È&¤w¹J…(&B¦bl„HR¨C ¼YE8$Ž˜I‡D>4R¨U|b©„5c¨@ËW6Ó¥R!¨B"¢B%Ä£¹éGµ6)L…ÎÈ„Sù¦úd$„„ù?u4°ú¤°D$<|‹ €Y…`sÓ¢dÏöFL"h`.KQBªŽÿEBw§$=Å3Ëú%†°çÞzu†=8ɹý§&ü(ä3RA³HsÊŸÓÜó/™ |J£nF|%˜ñtvIòÿGÎÜ÷¿+ :£Àzí‘Lp×8d Øí¥I!³ý>…Ì+ÛnÇbæß.¼0€®;xæÃ«×·'óú™ÃtãçÙÔN°Xñ;Ö죸qîu÷²æÃ ð¿÷¶ö𙉅³d1ˆœ3Ëó~Ís&ª“$ GªKêfßµý2³(yÊeK½.–qGŽváøö`3Lo3-mqlåŒßUBPŒ–I˜7iŠdåhF…¸ªÖçO*ãà†ýy^X=ì:¸Û7O›­ãó~Á«6AÉ ÒäU6Bˆýð# X€ AДàéìÝ#AÜŠÃ ; 4bWØ!öØ1lvúmšÌBËp ŽÌòÛBÁù,Zfã÷ºÚ½îGð¾Ø9þŽÿc£³àI¤(¦ª`¢¨ j%š©(ˆ¢–¨hh¢ª¢’‚©¦aŠ’¨ˆ‰ªbJªB‘¨¡ $W.ïc··æëk2hžU«‰Øò'‘òC&äæ!J” l€*(̧ÈÌÈe³L² ÎÏãË耦Y HTýŠ€ê ³.îäÃû_~ý¿™Òáê<'¯TžÔ!CT1C=2ª2‡|Šï;uï=)«ê[×Î:ú7w1àrYC¥¨5ü<Iïa±ëð_7 §Íƒ-Xë$Ó<Ń•ÂMÖ•"¡àÜóÆÕPÃåòܾºöXHqM&bq†Xz°Ì;PO* êÍBšrü3‡] tÎÍsªl§frÐumÉ¿ÿÄ6}3wµ<>–kzš‡±æuzG?FÊì jRÁI’ iATF,†£aÕkáðµúÀb·³??Vn,P R”hÉÇÀm¨c ¯´CƒA‡Hã RxbŸ.Ñäni¢RuãÄÎLó{—ÆUà Ã9·ÇqÖÄ$°\üº:@kêïÑ›íV©uD# „ ÷zë(¨mPà-z>6+¨|gá»ÓBÔžü[ð#ƒ²ñ÷ñ×·æ§N‚œq E,¯8µrÕP£½— Z É`—õB3PE„9ëûnfŠdÞ3™m½ƒd„Y9õã¼oXu‡eåçæ¹¼€†DÑ”!K¾¯îòÀv='r+lQÖ'*ŠV˜,ÈaŠä =])¼šXžyjÚfCÑó!Ø”Ñðg€všßøiŠ =‘æ;/'…\¿ø1‘ÑýDSÕH§x€ä/çÔÅûºž^}WíéàOCêÅä£Ütë3!ÞÕZ€{p ÔÔÙ­¸ë ôãÔjtuæj^°*/ŒÃÿ¾iÉÁ'ëíÓó&¨¥éÛŒïâ±â›r¢[hþçÐîݪ3æ×5h4r‚ää‚`îi“ e•C@¾ˆÓPòêz;cm†ð$”ƒ@jQ´`†K¨Ì0)g0R `DB”˜ l(20©RA “÷¢áw,»».êª^h(É?/ý×§>'C€°¤Q‡›Ïpí‡J´ø,6jÚá„—¾P¦¦@Û¦Éb¨ Ž‹¶·‡&ÛglÖ⫹ãúkæû7ä7ºwÛ±¬`•Ò(¸ûðˆc0W_'*†ÎõEUEUEU¢ÉR»nàóŒ³s—…‰piSF»´UÈ]CºãZ‘ë§Ó]3?›•2ý/ÒÛa„{Yõ¿MQ•Ž•±bÉ0_QAª E,½Çºi|±§ÓDs^ƒc²ð‹úzM¾Û'zÏ̵ÀkXÉz˜Ó”c¹`åf3 ´gʰt‹ì÷7+*ýû÷ïÑn•Ðk¡mºÛ•ªæZ-‚Å–­:Uïßm{Èe^ÚZ³&&Û!Õ]¡®îbVîb:ës^bæV·\³ëÐ$?¾'õ˜¨«!¨"¯µ+… õè%òZ×›“Ù@4* [§5Ò2â´ŠˆÀÃÆ‘A±÷ÃU.}2ˆt܉èÕö¡kJ;úX?ªâ)WÇe¦^¦ eM,Äj!ã׬ӯ^ 3Þûs× ¦/¢{cÒ!H"œE4¦]R)íƒòb‰ ƒŸ¸w,yZƒÔðü¨m<€¯"æÜÄß<|瞃t?3aõDFá°w¢¯Á~¿.T~Xì´ÀÄ$×T0›¥P‘.¥Ð0>|ˆ2m4X0tp šFÊþI˵G7(Áñh˜R’y–¢Ðhtá€3Vvãç¥6vrO»¿ÒfŒÍ Ú2ÓÌñDóƒä^3u¼õv X¦Ð½Mè …ºã¢Dh!‚À¢x9pÏH¡¶%zžŒ\TèõJoJY¡E’gñ‚åàÏ݌إ¼WÜÒ9>#(–Ý“V›[·y„-ÈÎÖÛ»^ }rc–!ˆÔ-,¶Æ­(©h #@j.]ìð }ó1}þ^ñ£•ÙLtÝ3;Ö·¶mí¾<^_ZK[›TÓ¤²ÝÙ²Õפ…§l¡„åN3h)œ¥£DXÔv,L½‚¨å8 1&¤ÏÛ^Û Œµ“vKyÛ‘’8é¹AbÔ`œ¬<Ô•{¢£åïxÛFËÎe>$ógÈÓ«pà·ª 7nVÃhÍãŸ"2©Œ¡ç 0ð¥SÐ0<Ñ}È‘ÏZ§ DиnÌD8V„)HmZÂnÒI/hhé‚tºR…‚>ÈB*ŒáCVyUTà\%/q9P± i-¸†þŽkÄ@tQRd£ññdÁ¦—%^þ¯‡ß¯QL®›´\Þèa'$áV1X.ŒeG£Ñ¢$œ‰­\Kx—´Æ•ª)“n»ú×Úþ$숧¤6ß_¯—OE:iho¨w·¼g2³H¥ýσÍë~9ÅÓÍ€fT¨RÐgñТk¡±ê Î#¬?zsåuŽýïcm=H§¨E")ñÀE3ùójODÒµ‘\øsñFÆÈlogçøžGª¢*ª¯àUUWºtaV+öÆ¿œòþ΂(¶ù/-Uü?3|ÿ¿™5x¢–UÀE"°‚Ž._0Ö®Ï/mÔ[›¿Öªªó"ðôô—¹Ý×£®+»Mz”IÎ+Ó¥_-EŒ’wÓmëé¡­<;`“Y7ß«éêkîôç×üÒIÑäÅñovªŠªæµ|íùyg¿mÿH)‹÷ÎŒþ–¯åà_Óçw$ðäøôëÙÓVI,õ]ïãw4¢£&1¦1íÏ˃Ñúùѯ`}Ÿ›ÕjôûÎiœoFª«é >§ášª€¯šUZåþ3Òý”ë'®ý~Ïg¤'~š_‡Ç¼àªþK¿rt<¥íÂo:€âµYv®Üœå±A›6Rð1–ç`UØŸF]‘Ònš»™CÛ‡¿l:.¦˜XiÛ3lïÖÿ2Åï×zWÇØvI4Õ½…ÏÚd$+éöæ(uçí|¹b¢«UUE¥¼ê§ÿ'IÒ#ìÇ!ïÒËÌäÐ7˜/QÄ$•º ãÇŠ)žxÆUz봚犞ßMu¯VÛI$’R9¨úV¦ÛHÄœüù"g€çK>œe˜]K·@YrÛs½~À;›é^nT9C]/½ùþ”õ|=ð8N‡yÿYëÓÕ$÷UýÚÇA}9ç;’æ,yˆGSZõý]ÏÓäθ#Wœ/W}¿Úª:ç**¯&±ë¸µ·£¡Ùø¹ðçÇ^¾}`jü¶q§·ÖOIãÑèÝ«xk&•D-têŸt®sÝJønö-kïy¼@‘Y$ãæÁçÕw×>aO†}OϾ— ÌEN„îI73h£i=,ÅG Vz¡ðÊ ^¬©çð$œ!ô>Ejª¶¢­±':÷Ë׿¢ªº3ÏkÉïØ§O²‚)½k8Î,²I§+V‡‚°èéñCc!±ÝÊ› ˆÜ”¢…¨b¯¾ÖýЇ»x<û½Ï@}ZNÀaDÙ5ZÒI&eëj7rmdâÙ¯'8©hCâ8éœ=Ðß·ÿO~ïo ózªŽ Î‡²ªª¢Ö‘N¥äo½ESUÙ†^öx½8mçá­ERB÷­èëü¾¸ÂŒïÇÀ´©UyÈHÅQU“*©$‘ C&pgp-.¶TÞQp"\…M€\–G^ÇPÎf&Íói4ð$ ]œt"H!ÃÁ}|F¹Óm‰ešû*šîwÍT„â¹Iþ:ÇÁj¨Ÿ^‹H!_ØhªaRC˜ °æPðñ-B‰ˆ»†Ç™ƒIT•U¶Ûm¶ÛÉ×ȧ^ï¶ç°=A‚p§Õí?Lt'àf6øwî¾´tå)t5”Ø?ç‚'’Šl;MŸmAóÔ sZe"B$e|½g3ÉÀÕQZ2ðÞŸú7ªó´z„·{y¡2Ò ¶ÔªÃžk™Ø©A;Ê÷ûÏ„=UUTJ†Sn%õöÎ3µã­˜ê.ªŸ0»)ܰ½ž!ý.FG¦¹Ÿ)ÞŽ™•b_±Lù%è_¢Õ¡/Ã>®*ªÅý)SÒT% Ÿ/Y8„(#Ní¹ Ït©[I&Õ!Œ&ôÃL]¥°A¤Rà1’` ¸.0 2±‰$®è‚÷t«Ñ¿f@}}:׫ÜʾϕOÃMf¥ßÀþÊjNpìɆë†×؆ò¯ÝíEs§ äÄ«€{u¯—pëæ5«n‡_ËHa‰ØE0\o$٪њ­«s{› ׂû:ï†kĸ»so»w’²”P«²l„%T„œ¦Ç>z&ï6Ç>¡v\Ṛr†'mEQì*Šùb8®&Jëk.œ‡›øÆ^€ Œ$%ŽÒDItÊú@AÁ§Œ½ïyFÇeÏ«HcUÄ9Å{œåú)´Þ©}žc«†2l*ÞŽ÷uNˆ£µ>9,-âäp`6ò4:SITPUSP¯‹ßßìÊ™ç7%è1JýßZü‡omôóÚÐÞ1JÝK”V!sn¼WîÄù²kj&ÐKÛÂÄJ‚J¥ÄCÛ0Äôuþ+¸á¹;÷Éæxžä›5ïÍâ:Í$‘ïj¹»µ:ü·»°C›Ul údDãæ=ƒÚ yi,X^b âöªU°xˆÂ±£“Lëïl_¿ÑúÝ>ÕœD éVT¤ C|[p¦¼5îmâ¾_ðêã÷('joÝT÷}vÀ¶«ÆDÅ¥í›EOÔ]ü0ª«P^·jSŸæõ܇å™>%X_ž‚ïÃßP²U";òõDÛ·¼†,9¸þS`ÜeêÁûåOö¨ï´íé+Ã!4:(UT/ò”|ÈÝ Ê2ºéMéHWUTõLzs¨ž]ø#D]tšé‚È’î£TfA-BªÀ(úT8}| ð%7|ååûSë<ŽZʪ«NŽìÊ̪¡ApªÜØ6¡s!$ȊγF`I š‚"o0…Wè>¾w~ZŽznkÚférŸŸÁõ÷H¿ Ux©Ç’JtUý~¡bÂK;S*(²ÏåPÐÆ Âößv¼%fñÊ'²‹@š™ïÛY¬By_Œ.( $ññœý×$ ¡~ÿbü"ªªª¯{å•>(¢¬J]?pˆ ëù˜ùœÞ½üöZߣÃ<“î¾>_?&ó‡Ï°£1ú/éÃößpˆ2uo¼úm6Rù«•s­»l´‡uŸŒÂǽmÊ ¸wÑ¤ŽŽ Áäžî«ïìOW¸c«Ît]ɉÂÀ|¨ïš“xô¥žž¥ß zç:Ü[2i9/+³ ¹ŸBXLº­›Ua‡†V«[Kˆvœîq0¬/H(}i(‚eM"cUdÂj™A§Y2Õm¤ 4L†¾Ý¸&ÕÆvñ¨ì0Ñ@¡€ÇL !tøËeÀ°^‚FyŸ6çr%–æ}ümf™–ª*ª{vO‘Žmú{ûáÎ*¯Ð P¢]RÑ8Õ¹vY$Û¹F\ÌDÇ©²¡PAJokˆ“`káå›L¿wuŒ«}ölåŒ[eè˶Û< †Š€òq·ŽÇ>áßg-)l:§ÓÑ¿vÞlíUQUUUUUUUUUUU[h T(l2¢Æèã"w4&|Z5€4¬ûE`€¸F®«Eù¡FúÔ“»u$sª ŒPâWšÓÂþ\À'U`®f°<03â´º°$V!&8[$¡¹¢Yi’ùM­P©#´çðþØ'ÂênéÄ c1ãŸÇßVå…¨+Ïé»ãÁϧ÷ùôü6ºDëâ—›‘ÛôÕwj¼.r_¿§«Îï¿”šüs÷‰ AG­ß>pÛ~^ÚLh2X§0ÒÛ,ÏÕ4ÉŸ#Mçó½gö¾ñwžy‘Crƒ¡ìÊÍã |æÈ~Ž–èé£a¤Kqˆ™•ù¿{P ñõCFª¬@d‚Lì@°% *¬’*Óœá~ü‚/œH&—±œ5Zó\™â´–…{¢"I$’I ”%ùhÆI'*I$ШÈP š­Dl³æt A[ØÚ39E^G=¯¯ŠƒÏŸË<"/ï{·5ª¢ˆ…U&›˜ˆ=äЛ ™-kTXrrÙ! W0k—Hj¨1ÜÈ D¯ÅUL(»bAe’ 5Ξ®8åí·£9èxGìvh‘ôQønG>bµ‡¦žîB"J›Ÿ_äÌ·sô~Æf´øÛñ@³1U㢕Ov©;µA’j·¿Û Ùˆ§`nwá\ö¬„ø_ƒ’ªI.írãB/l掎Þ5B;Ú¶Úz®Í ^¨7›ã2,íÉÖíT’I$š`‰]äªïØÎ¹é­D=„Œ `®ŸXVÌ„q ª*.ýiLSåjˆŠªÆ"ŒUDTE¡jdòâÞ¡õ_iÆy­Bc:vÁ‰$Û o„†´ío…L¹ÚI$$’C›@Ï£6×”Em‚Dó“˜ÒÖI*©“fâ~ŠQ‡_?ŽsŠä$=”Ñö{?;;*ÿ-*&ÚüFª«|óæêžsÐLÎZvûO`DÙlåaW–ZMàq‰A Ø3ŸÊá9P*Èš.}n¡…¹Vµ£€FÑ©F@ Ò¾íŒa5Õ•‘X¹(I'h` €qåˆ dl”Psål«¬zgöw=þÒþÕ;¿îµNTºµµð‚¿ÇÇñóÃEÌÌῸŸÝºÊÃ:ÏÚIE‰Þ—šÓìgj~Ÿ‡îÓxKo­uàèß³:hW{ãâ£Pö9ï+ã)ÌeÒ·mU^Ýâ]¶ókÚÑk¯O¢ÃÀ÷ž,=*AÊâ} OâèyþG?giÒŸ–¯ÕÛ ÞÍÿRƒ’PÌ©–/3 füÈÙ„öŠ›Ò‡3ip;P ·ÎåæâMsMM¦’TEŒ!˜ËcÔpc3ìÈä©fâï#µÙh;,ë`–]7½Úª$’Ij…±jÈVªª„LÆ{þÓ—ØqWŠ«ðËåòô‡`/|Û‡ïeõêõøÜÅTÇÚM—ýë…EpjÒP~]âyÊ|¢«©Ô9¬Üo…‚¶nM»SžåIë_E›“4ŸgÀ9φ}nR–Být+±§ó´êñ7Ú¬£‹J¿9°B®@¡úQÔuuQï×ø H€@(P’sëz¨¨œ¦Ú–ª Rd( c+”¯zzp^ú®ŒQ޵^Œu~)ꄞ?/Îs/8Æmb&~Qa•þ^¿Ñk¼s£ùl½Üª©võvÙÌäöý¨ÔÇVÓ×\^wÑ=Çô{ö°Âª¨*”ƒ Z*ívy 5ê¢$ÉEÅL\¤; FŽv\é80°l…ÚX¨VC¨Ée—t1œoÕ šÜhy ]zÆ’/«­à›!Ó~£} $œofÒl5^ÛT(Ó ISÆÖŽºâcÃjÆßWÏVcÝô"y„Ê¥¹×7¢è‹¦DDÃT‚[ª—\k & ¯Ãw¿¦ìûP©°ºÕ’NO›[Á;êôÖ½¨÷ð“þvjÔ×Iµ\eUU_Ü!We-yc)÷…Ê®9ê¸ïÂ.G^ X­¶2)¥ï$’I&)…[)¾˜.™•Tujú;ó^þ‘‘N˜ˆ]ÄI™5Þðúy¿­3žBîä’pHÐÖ¹ƒ6q‹„.—%›éeU©¡oD6zкªž]ÓÁÍUûYErÖ7Êu»òÞüyž]øç¥_oÑ3·Çgª¢ª½Rò=˜UýĬ|!I$‚ $ƒj,d*@ÆUuŒzñ+ܺDpRk&5…p¨àÜ˹b4HÕ&¢ªI2•‘xª1ç88™EMëò%è³HšÛ+ ¬%$JJÇÝHtAìbÀ•U´ÂHçÆz½šhНÎÓ><ïØa/R¾>¶9HLŸ]qÆv&GÒn¼fk¯—H?-±·ƒ¯·[EUTU+èyÓO9O­3¤oÏ1=Ì’c>û¹R¯¦n Ê)›óñÞÂÿG¯ˆ?¹ $éDþß±j¯Ýd} IÐÇ÷!•ï?d;Fue_Åo’Öi…ê4q[p€Ã-ÔÊDBìÍpÓkïé(OJéXèíµDM¡‚¿zŸe¿áHB¡`²3©ø¿Û_mS–}]–KŽ*Šª®Ÿ·»{?ªˆVpT˜ç†Ð )$›v¶T©‘Òª>`¢Å'÷÷×LÌÌÌÍ Þ3*ïÌ”Gðéw×áÍ)Zs@@õ] ,?;vŠ(‘ÇŽSf¹é­}n¦ÎÉ$˜Ó«6¡Û—Ç9f=ݵFÍ7ÇèuÃú6góÛúYq¾–üÓðe’|ý|90fM¾SJ¶ÜCéýšCO9·¯“]88š€U÷§øòzaÄ*N.ý„¯O×ëf¬LùpQ:æK…I0puöpêynQ%³îÈ% œ<–&’`!u Y\.%AQv]b  w”ÍN‚î¾L¾\6T6QoJ¤å1L/†»e4ñ3' ,1JZ¨ËãY EС°¿ 3.Ë­j*¬YÅ/AQ&…{Ôõéîßù1baloªô§}Ÿß”¡Ux3K *ýà Ú¤ˆˆš‘ÕÈÔQÖà Àšef&ïœÒI @ðh4ö õ'ù·¬Ê3=>­7Ê{l¥j€hºB>qu‹XRdž– Ý”$Vª¶LF†JÉxJ!²lÁ©,ä…zîš$ c´§Ëvs¼àº‚ÑÈŸ{¸G0f‚qªß¨K:×XŒI€…è! jáó¤á_«ßâÌ7êÿ^sÂßÌÌb"ábˆ¢£ççüÓäž]ùg!áJ¦ï×è>Èä¯áçÍ«FÛKVùåÁ»ç›¶Òóãåâß¶r•EŠz€¨ $”Þ «}›¶Ú“Ø&.ÍPÂ7Úo, *¡’[ž™üf‡×œ:þ=:˜+ùð³ö _d˜¥q— ºU¦ëȃbþ4†OÀT`Ä׃„Ìð$(Šš%šó~ý<$“ò¡Äl›§ÊÞçï0O¢±»}ʨªÙ©ø<çCå×[¿+Uð}¹_e<²QT|è0÷Óg_¹ÉûŸ€¢¿5pL.@’I$MAh$Õ Ý´D!ÌžÑÒ¥ªEUW®WÒóñCŒÐ{Rrã·GqÌôîy±ôZØ¢¢!>_5‹™kîõÃUTU´«òë1WΩ$ÈÒj7÷ŠUí&¼éìæ}œ P”Û Ê}0ûŠÆ=M挭îò~@…¿s'qÓ™«…Ö÷Ù<˜Åm3,µ ¬âiw¶±\Ë×vÀn«÷7ÑÓן6™CéÉœ$ˆ].¿½È¦a82…SŒ ef¨Ë³f=A†® ´ò†þå`gÕŠ{Ô‡ñÃC>Ȭ¹W&奿£UoŒ×ÁfËVeI Ñ2Né)ba¼t+¸jZºæF¬ïÚ ÉmšÅØñQ,jnîÝÉ¡‚Ô²ýÊÙ>nh×1ü;z7õú|Ý<OµÇç{5ôç )³8MUWÖœ*ªªú³…Û8_fpøqÂ*úþm:+£ëštEo8UU_vpªº§ 71ÑDUsœ*‹œáWTáUtÎDáR¯ð²Šñ”UUUUUUUœ[UUUU‡od€<\8UWDdoèóüÌ”Ž? ƒÞÖ3}HºJx,ÌŸ•úéÄbE¹ÕZ‰jªª¨¨ñáûg?x^ï·Ã`çξ1Ã&h¨ªŽüƼ±ëë¾£ËäìÎ}¿V^ãæ³†$Š($’fÙQlP`Š04ã„ÐÒIªª©5¤ƒy”8Š…åÖ"Ed+DRHQŽÓeQš5 c!µédä=+ðàÝ’N3o„°gÏTW*¶7ˆ¾?-&sK[rHiÚ6˘g4šv÷JlNÌh¸Ñ;1£ûŒ£íô3Îʪz§Ç í’[Ï‘ºi‡i7pZMÁ;§Q+õÌÒèV>ýj(«,6àoúýÿèó÷ Cà¥~à‘‡X™uWx߸2€°B@Iù½U÷Ž•Í{Y‚$Ô”l›&Wõ†cUSݳ iŸgòàB|GÛãÂ÷C‰ë‡·>¼4iÞöª¿¶•?—wMUËü;ä,ÈUfü«Z­j4µóámLÆC*:Z¢Ðpi$VS®w*Þ`ÙE:7šÚT0¡9¦i‰Pø d0È©…ö€`™eÆÖk6v ,¶ÃRÆëPDI¸þ¯—'¤ ÀËÓ–•OÉLÒR¯³!ð†ên*Ñ CVT…Ó +âTŒæ^rª¡>p”¢¬UUUUEE^\qE Ô6µ9%´¬7AcR›Àœ%Û’H²ÄÜ]d“#}ww¯ ¿‡ù¿²pïµU÷Zªª«éLÊ UUUUUUUUU^ç—ŸO­ã=› ãÂ2°, Ô‚"Q8 ÊAKbæ›ÞLФÁÓ½ÕUß· UõþúÏÊÍW×ò'@g¿Ë¬UTÓÂXLÎ&ʘ¤ b¬7H³6[rŒ W™ŸvJK Ûuªí2XÛ3K)$¸Sä•dmÆ`¯ )Aa \Ÿ|^¯·Õ£²©®ðù}K£jŽÌ2ªª©¶!wßóªkó°ä›ìSdûq¢B>=Õ€¯GÏ߯ŸŽ7ÚüɈKâîO½¹<¨(¯1Yع‘耳ÕÊèèãÏɱ·Ñœbb"ªª¢*N=Ô\:N¤O«>yÎ>]ÝÉ÷cDðÑÖ±š% úå•Så|0ñ{©ø4þ¡—µEUR•Ÿ‹’Mæ«OeäŽüàÊâä'5š,NQ(®+´Œ’H9u a@BO†ã/9i~zH íˆß¹ni‰½0c ‹CÐÐ7!ï$‰ARZñ»Œµéͦ٧œ)ú‰àõóìùüiø/Çú›¦Š[.¢¶—ñûÍ ¥)ó|ö~ߌìúb)áQë3ìúá¿Zuǽøz'«ìòðxßÜùnª¨¨ªª¯`c•UUUeízÖ%#çQXœÏk%ËÔ³rÌ¥”nK0|d³òafä‹ãèõž¢ƒÂIè³Mpš‘óÎÖ:‘½¾€/RNh„РëƒVPjýLz¦$ `ðo¾˜{!Öÿ }±Sz`ºéñÅg·ù•††™oâõ[ÒWøaòrï–œ!‡9Îκ§1¦Yí/aY ;—´O ÕjÊsQžwóÖ˜zYO µìŠúØ_?,£6n>þ´ááÏMëCs0z>ÉquQTR݆• ‘Ôâ‘ý™;Ð&Ýaj“ ʱø®˜bŽ’4&„9n®ûä¹ýÕâ‹S„‰æ»öÍÒÅ/‰t Âa˜†‡^…è?v»ÓïðØMN“v<ÈC©]q [î>jÒa믃x›íFNº~éŠpš P¸ºÏ ªÄûú9c02·TuþaáeŒË Þ9;_ß¶LAR¿²Áü#GþÇô7Zr˜ÄpZÌþ-„D„S‡Èï ݳɃ‚ûý>W©£ûüs¯D©BŠÎÍ‹$ŸŽ?©³{%ÅUö¨Âˆ «²;Ô¦ó7:µŽ$ö¸I®Îð2ûw?wÇF=Ï8ªÐÅ([~MFßÒ{*"¥X“žÄ‚Üé"‡´ׂ+ˆÆþê´Š§F†èwô´·?v0šÏMúÿkûV‚|(?ª¸Å¯ìžþfÙ¹ë?Ýã²OSü8/óãC¼8±â}(a`Ó,%¨• ýKÁ …e&¢ymËä7…âñcœÝÑ«žJóÏ~¾GuVÈ ý¿¥47ûºqe-•äþÚ¥Ë ýKéØÎüpÙ• ^9ñÚÏì…»>>Å3‚Q5™«tÂsÖ»¶rеW\¥!0lªXçÈ&žlêBZ$ƒ2…€¸E{ÑשAhVE«bº·@ _×ÐÀd~Ò¡íéÉkaäxµ $D¼Š±qdu™iÆ3š¼Ìù¯DÃfþ¾¾È"„ÿIO”Tó¿¾ûúëÖ ¤)‰lÒ7§þ¡H_à¦|‚÷Ñø ¬øâ€Mo‚À~f¾{¦$#Í&“¾Éç•­b UŸ1õÆÄ J!(A j‘ÂÀ‚yüI&e-sÆü©V^÷Ýj¨¼ø™1UUR§ŸaåçEÚõpø[ááêy̧Áð(ªª¾H㪪Øc¾Ë:µóãW}€ãœ·u_TQ·Ïà $Ï¡ß[ ÐÈ|‚ÿ@º¥å…¨¨(ª±à§Ã‰$̨‡ª(U–jöì$’nî2‚ª  i8,_dÁF"£Šˆ’Úyñßu5’O]œò]irú™="м¶x8uyÄð¤Àá÷' ªºûwâïÓÀ¾Ç­cœqWsÌÕ1bQ g–­YÏ™S×8-© Ù‚•"`Ë«møC&üíQ“ßeÑO#óiåø/—vŽfr—º%bÙÃÅü<,Có2õ Qý PI(C$c$®¦4誔šÒ„"A}el Z_³º\ý)(µ#Úª‚• $”Zx3 k‰$Þ*MwØÈO +~v+ËBÃÌÌÊ»*ïŽöç?¸Ûû/ázYÞºZy%Tæ<Ý·QÖr¸ýSZcOUÅæðˆu¾¤˜þr©ÍMDÔ¬0‚oícV„ÐD ªÞ™ŒB€Ôæ3îÆ1u°ÛXìM"q mË4XXi,–¶DT ¨*’Aó´~y˜ãUUõÓaì§]t¯°¦´§@[†®†þï0=[Î|)ØŠ#ãòtý^ÏgËÝ ×èf›Ò*±H–¯ éêˆs¿¯·ÅhV±‹ñV;Q§GNä²"8[ðL@•Æü-ˆbˆeTÔñi—_d¶‹Lu**¯µñ"ýóNÅUUU]9ÇY{b™žcÂþ*›Ù;}Ã.þ|—ÜV*D~¿¯Ànÿl¡#©Ì{”¹Ž ^>û@I” sf A$“¤BM¨--Zì¢07 ¨ áUÏU$saT¡˜Û·8³ã‰Lô±v¤Ñ›t¾8(¡Ï[õvÑ޲¾Ò¬ã "5%}Š1lI—Êÿ¹sL eÒÇ̪KH$ÍMwgJ 6Y“Ê[ç ¶)ç=oÇÓFO#¯_UQ $ŒŒ…‡–Ó~¾œ`ïFhçsd*ü\4<(¹!’±åÇ_Î?£`».5YÉVÈá$³µt˜¤’$’ uë@ˆ…ßqâh ”œ‡LcEUE^™É­fUUUQ$A6PŒa3KºÍµ§AÈY›| Éç,p $¤‚†XiÀc$[`Lɬ(ã^E‰'4 sØáJªêÿ½½ƒþ•üWG"¾£U]™UU‹®~Ï¥ÝÞä;ß%*ñù«zÒ§N‚LàªiÂút©Îrßo3ÇYˆ–Þ³ÏÜOU9¡ò@Í2AEA¢’\Tv+‹dHÉÌ]Ýü|*"Çè<³òib~´½”£Ô¿ÕTUóJ¼-^[×»Ÿ?løøà˜°ŸŽíîj¥ô¶øŽùë6ÏêqªÅ_"%?Ì&"\N·«v,Ë)˜³ìï\u¼p=/Êð@â­£µ´[6>Y–˜÷êRÙ)œ”îËk¾>D½áÝ|Ñò»ÖàÁ̂Ո^®¢ü”<êÕ’=[”r£gOkÖÌþÃ)”uS<>‘{VUa•§ÞýÿÔiø«Ï]~~~ÑZÕ:Åz@D Ÿ_·K‰bǪðo{^wÏ×#ã¯Úù½Öb¬{E¶*’OõBg¨Yäâ•RÛk[ëÅDAR[Žrœ¥—fžóÒÊŠŠ °ÝŸ§ª€)š—ùܯåþ^~àÚ?Ž· ÖÄýÒú özøl³öú~ÁÿæÖ‡B"Z)?YƯ(õöž$ Ýpÿ,ï›'ØãDwGQ5Ãé6"U™ ÿ?üFQ–ûí¿Äß׬é.q$›Uz¨ô«eKú÷d‡o“sÏ9ÞªÏFqªÅTEE_o³1>r&*¯íúÊ`¢ªŠyÐ8íÒ8ê·ì>>¤&|SúyÖrHUÒ>\qàJž=k¯%…™<ûq*¸ë´d“Ruj‰¼êŸ“}oß~žpØg²Ù v(¤”BPÞî3¨f w!–+euÈ$¡É%s^Z“Š^òMæç²PA–Jۤ衄œjô½3©53X9óA`Ü!;@Q<@àÙÌaœG;ÑB¼.´W©žPÚdÅï$’I×àóé“;^÷¸Šµ/»æö»\qaú!#£3FkNZfÇ"bDP¶ •£‘ˆ“Ù)¡p™A43$ÀD!bZÅ!A- Ð Ê”%Z(Ð¥”Yƒ(0ƒZ ¤ Ê‚T Z,([(´ T(%° ãAA±EM2ð}°)7ûrîÞ;åxÏÞzÎs¸ÓÞ·®Èǧ£¹ÃŒ Œ;-MN§¿÷ª±T²üáD3¡çž .'ûx¢Ÿýn#Á>oèý×öÿáïþóå~gLåAOA@Š/ó?ìäõ¾‡×E7kæ‡Âņ"¿Š£çŸÍ*2UUHI ]dS¬x*XÏG¯>PáDAÑò²HÎ#–;Q¬œÈÛ†XAýåZöªIÀBE{n«‘€’AE¨U{Ë)Úž˜ß/é¦`&“;'~û^¾”R"—ûß-œyú9›í.8/O+ãåÔua'2·©óö`¾"É\ïµú³Zõ:½ÙÆ·_«EC&üÈ^µ;o­tDBµ=0};Åýô_\ϯ{$æm8¹Û¶×¯ €§¯öqãåÌßYqÁlw­žù9ÁGª"¨ñ½pŠÉ;à@vN=UUUUUUUUURªªªªªªªªªªªªÌè¥"›ˆ§/ÄßèÊh ‡K¹zèÉ”Âåe˜Âù2–›¢:tüŽ ŽŒx±›çHÈn §  vøŸÆ†³Q“›CϸM@R¹lŒY3™1ƒ’¢Û)E ™2Òl>ª"›@§¹Ó2ç™ðUQŸ×Ô?u?¼zpiZQiક6ø=þ. ÖE9QN )㢟Kø>2)ÔE:h¢þYË' Ÿmî9q=|˜¦†|‚}:7 x¡eê[f¿\Yƒªò¾6yœ…øê¸Ç«÷s¤Rƒü/Å/ǪÛô‚!þB A^â)þ¹Æ–JPï÷ü~ǽï}]=­ÖËx1n8 j£bÂEÜ_pŒ Ÿ†­Ó 3ñÛµŽö'ß¿çe¾FÍíÍ“Rõ Mä;Q¹wD®¶æÒJÆ\îd«NU⽽üÞoø?záýÈ Ì*PÑH*Q$ªû@§tá: Ë:œ–v+&ObOb)$AšAÊAf PÄŽ@¤˜PA`°h¦ŽPãv" § ’Æ,áÁhS 8 QId–0`ÆPãã’(¦–)E’0ð8i¤7(àQ)ƒCÜèd72‡vt`IÙ#Œ(æ’8ã %$()‚ŸÄA›xÍÕ¢ СGÿV¶Wò*•ï}^ÿ'ìü0‰h „Ï}8o?Ìy¾3‰"rgÈàØ ëÏz\ˆ<” M¨ÄSù¥áÜý?ÝÿÑú_ø¿¾æþOýÿ£ñõ}L?þºü‡4ø¿T¯ƒJô:žÇÛ{ʦS¢ „$dªjþOñ5¨¨D>¼ ŸÈÜçûÀ¡îÈx?•ý“÷ù ¾šûWùý²‡b˜î;rˆ+ð|…ëS^–¡•jeв[ù† àíöËŽðîg¹Þ³1MæuoÉœ«~x<ßÚô\gò>|f QÓ)ß8â BíUI@ËÇ£‰tšHîXyi§oû9¶æý¯']ÝûͯÅËç>W§ï5ð†ÐÅ‹`ì%äräƒåþÇÉ›Šsû¨DG¢§ëÚ?ïþ' 0.ÌqͯMéa+ã”5¨Ò®€œ¸€ê¡cP¸:™þ÷†H/L Œ# L2Š(ªn?·Ý „Sf ‡TÊ tIÏ@¯ñ’CËþ=Ô4 M2ÒRÓ97û<ÿËyCÑ›ƒ=ö Ü·œL˜Ò4@žTäM‘¸_ÿLNPúi@ ¼š¤ã¶õ>«Õ×çã”ûa"b4g^µµ™½®µ8Iöµ'78Yn@¼ƒÇT l'²€DDÐw‡áƒa:eK9É šC>`hiN`(e”–~ùIìóx»)ëäw»ãý[}Öù[y˜¬’I6WÄóˆoóó+{=_ŸÇÕt4HXß(ƒZá¯&ûüò9 ›ßìfÅncØ-Š{„#ó‚›zÖ:Ó—CNL41’͵ó™LYt¸A ˆ'Ì<¼vEUUWè·$ô=|¬ ¾˜ŸG{éñ4,,Þ-§‘±[á ß&Ø@1ð ì¶6sÁ˜Yä‚•ŠúqWÙ³ UU^` GΆùøÃ­Ê%’´°óáaþÌ6ù–¾ uûTŸºÁ¶:ÿ®Á[óìW] /×UÞ/g)¢yÜÁŽ‹E¯µ0QGQÒB°gM¸fØUÏ£=ì‡=ÚKÌšçàëìñrëÉž²…ÙÏæÙ}§Mî÷²žÐíi~yB :’¼Ý¬Svƒ‡ ¾5\íhÑ)Fss‰®B9Šº&LÀÉ[ÂU}·‹Ù6L»xõÉûó›+æçÖ¶À›†})V|…óaáìRv¶§·øùÔŽ*3±SûQà¾roNÄÃîÉünN3£|5Dx„šoË8 1ßå2ñ&$Ó‡!2i®žz€Üà€â’Ë—(e „‰jìȪB*k›4Û.“¸ßT\×™¦ÄÕ1xƒp¹ {›×/Í£.Ø`a©]GÉ=?©fÖµ›UqÃý@@Ûü\ÎÅž-ý£½yfç–ÐchÓp̳ =--¡¥–WU^»¿-cÑç¯]ÌKªÔåµ<;žKÍ,ÜËûUËnfo%­}zÌDúVëÒ÷›ñé¥j§×­o{îþŠÞâs‹ÊŽõšCŽïÚøÄü%Õ¥UtµÅ^êô^­MŽl?|]W£ß¾¯5u{¿'ÓdjÁ¶wñ^Qb¨óÙ^ùZø¯Ö⧉OÛzò!¼ˆ^ºóΫ®¯"oÈñ*¥9®·gM­Úµž{Ì=GKéÏ”ó)Q¹ë×<¬YΟÛûÛxè¿Y+â§§õëÛ÷Ý\(ç#¾ØÇ±n1†h½n§Ü7¯Uuž£ãן´ÏŽº†¤í™NŸŠª¥ûY+§ãúÌž™}._(¡^š}z¯6=1Yu×®ºê룔±ùVü׬oVRà¸ë~oµ÷½ä¯h¼nuÄî…QÊwœ…Çö½k¿}pãìÏKñœ,®©Žr—·Sã·Âevñ~9^£ÛºÖðã /#?:äó¶õ½ÍzSÍèò¼è¥o:–SÌð~‡Ù[ÞG^DG¨ôó~²‚±x™Þ4Uñ¢3»Ùæx­Gm5àËÓÙkÍy”³L|/ªI»’=¶w8ËÞž[Du{™UïgÃd÷ê®<÷^ß×\ê'3ÍëÒúÜ«Ÿ~÷ß—^ne»úZño¹¨glP¾»Ž5ª÷Ï^_—oÓã,W–ïMÝôýdKº°Bv«¸úÞ;FFé{‘˜¾ª+Ï–Õûë”cvOŒôVñü¬•éï<÷ü§õ¹g‡•¬®yU=W®µ^½©sÖ•1EíûƒtnÛ5¨÷åõ’Íj¦{¶ŒÓÏ!á¥r_WÊz1»ÅíN·Þ&Ë>Žªû,gbÓö^õÓJ²ÇV.s®JÖvÌ/[Ó;—7ý î<u3Ò¾ë¾ÒûåËê*/v-üôy\œ[éy²¤|;<^µW­óžzg;÷c¾ßku5¾¦{ž ôWOßÞy;9µ:¯Ùç½îËíp¶f¾Û¦µ†¨«Ôkí¼nüõ©Ò"Ú(‡¾¦ºâ¥z—ìïÎîègy9+]ë2÷†2Œo8ù >/E®è¯ÆµP¦lºýÓz®Èõ}­ðUê–gʼn¥í÷¥éU=KJͬi×/x»Ûl^§µôÇœlÞåö7=w“^éߨíQ¯¼ÅŸVjß‚î¯7¸ó¯Ÿ¯;îãÎβÙ}rûcÇîÎÞ÷^[Òá=·z—°­Ës×—¥ó9Öaî}-{:löÞqlÖë}Ï]®øwC)èôzŽcõâ\ëø[÷îg¸ôLyÌ‹õÞj†wçgJ[ؽö¾¹ê==W[Õß­Ÿ=wß~¡QUûô´¯¤Fl/Õ‘„[wætqMíÔï;çy\×eï—0RúŸ]_7T†¢'×<覼¦*¶ýßbÒÝWQÉ÷0«ç{8:ñ¯žŽ³Á¯» ÷ä£o¼ªõ6Þ…‰çUï©QJ™ÕCÚø4=wß•âåÛw/9ά8 ݯjž^u^¬`oFÜíY)z½~£W˜ì¾›>·éûöý;ôÉ~üã–ë*o~ýo=êÇS¾Ùêû’àòôL¾M?­XÏ]“E÷~,Á‡Õº}ZWbÝëÜMÒûíïÛîæ{nÇ«%y<÷šuÁŽAg;<‚¬{è~Ñ^£2xýðäóߪ'ÙÏÏ9 Än©9YX´[œ^§I÷&øîºÞG‘Òïjv®§‹s®ý³±ÒåSráqîýzòV7;îo¿K²óÖuãåo©ÔŸñ¶9¹Çó§ç¦í¶ùê-I^wn³Â•-T]ù_z|zfE<;(„øuW:§wø‡¤í%Õ{W[\»ñ–qSf÷2ãÜKvS׺&°vUk9k¬½6<)ÌîtP±Ó é™fqf'«ëµè‹WT—ôòë¬X¶q³/¥Þeeã®ïÖuç¬ê×{XÞø§oã*Wjr ¦+Å1G¶a»Æ™™cÃÆîZ–^úêN[½ä?¬ÉV×°\n3Ê¥f«(»O04ªÎ(ÝoUU4+º¯ZIŠ[Âx,b²R¶¯¼ð¥EE_K}Ÿ½!ñU{UeÞ´<²‰2ïÇenxw¢á›ðsá=ßœÐ)ì HFBIe¡ã~+ƒžšpuËF˜¶8øÿPñŸ«¨òôoX›c¥·wVØÚ;óXZ‘xà¸b±€›W¦½Ù!¡U|ªªxˆD­È·BäVú¹w0xdã÷znªtG€HËêÉÌ”²îo`âÞN–îªæ¡ñ-Ï[\[ÞL±_ våN›†}]›²6¡ +fOÚ;›¿“æl`«£Gb©š*-ªªJ%¼/5Íg1 v¯îž$yÝîDº£{ž!ù¿6¼S#\læK4ðŒhÔD$ÁáŒV#Zܶ©Ù:•n™™…·m±K¦­¶î™¶ÕŸ]¼8¼¶í–í¶)tնݶíµI³Wm»wmÝËrÚ¹©ýbèÈg l033 † &R%Oëfõ™˜(S†Æ+GùßÓ8uÑÈTêÌ.Q¹¹7¥B‚¡5òÛ Ì¸¬Ã#Ø—NŠfsm»n¦¹“FíɨN¬š|Úm¥´¶[gS30Ã.W:¶©0×P Åcm¾hsw0Ã"rîåµKšª+mºaˆ&RÜÛl¶ƒ…`hÒ¯-¼ÜÌå´S70ÅÜ Ë‰—Ûh)tÑÔ«™™q–ݶ¬0Ûþîþ•t™(å²w¢îË%"j?cžú’ËüÃíx/aƒžÿnxÈÄR ­14ˆ”¤Ä±J’ä`Èa"ŸÅ€25 ¨NƒïUþ'òWøÈþÇ©Ä&Ea…((D"Qi¡ÿõ*ä4%"”% Á*¥!T¨”ƒJLP…5H­)CJ$JÊ*’‘¤ZQh)(JA…V¢…D¡TbDJ‰P)Pp! EI¡(PhAC%ˆQ @ U)Eû.jô$"Ò«3JÈ$"©ãöˆr B*G+YÁö¾ÉúÝ õCÄø鮟~“z¿cÎ>1î¦àwU šV&*?zÄd•OÿͤÜ•J(iT€·,Õ󧛹˅­míß›ôøsf™ÈpáÂGs‡8]fªŠí¯Ä‰”d”t—õ`§9Í4JÀròòã]4×–^ya¤Á*M9 /TÙŽJŒym 1óó¼>NsÏ –ou”Àoµ;ÕVsÇìó¿Óÿc ¬è2øÿ—Û¾âtñ­0zºzäØÍœá±Œ0ÞÎKÔ¯IË¥ž‰xQ{æë&¯7h§³:Ýê ¸Øt‡9Âh鹯 8†˜s_cXº–¸õ˜²ïQÎ_³©ú~¿ÌIÿŸL±£Q9åÃ?Ü äxOxŸaó·äŸfîu½nõ±6Ý—3;†:rë Ç–S(V•Ë,»\¸f“åö{ú7²nD6!D '§id7âö„õºË=Öâk.à+æešé…AdÓKíþÇ xG´Ìð ȱC#SB‚c‚ÇBgùÙß¾o±òŸûÞšìf@JnŠÜlWDNÎÖ/^Šœ€&Pìx¾Øü Î ·ÒC˜rAÉj( 4뱮εh8Y¡Ì35柣Ôca¥>@vÐÐu?ŽC`àlA°$Ñ0§þɾÎ[°§F˜)ÏàBôhŸ#HáˆF482ptÓ±š¹ÒèaÍCÈý"ôàä«N®æÏ;Vh’CÉÊ2GÛíæÉØ`ô*)££¡ ç4°ðÌ s¶xY@+Ÿ°=G«¾ÁNÒB…ó¡CJL!Az2¼ bËqI0YZ'à֢ơWä— E0ƒ„`HI§$qH^9ò‡ø½!öòècÚh*ƒšý<|ê í‡b¢¼2Œ)ì õôPàU)ð:0¢˜,Ðzm)ý†!fö)% v  ö2tèã²@È©…gÕiL4/ÕÍ×$ -ÓÏwHéžíž:¶d:…”=¥ó)ÙLh[ˆptÓÁ…ÓD÷˜xC üŸEvãë(䘡AÙ 9 &%HqHZ:ÂRÂä’ã)ThÄ  Ä ˜vYE–|(1n8Q9¦žGIé“!$ÂÎÏTtLÈž˜:Îì:(‘xhä‚„’0B¨¬(µƒ`XP@Œ(ÄŒ¾†ÙØþ{†t3X¡’0¼=Ë«IŒ|±#– :=¡ìqè£Ð©e’@£0iÐÅ#˜Ä”+ €­g±H,²JV†TMF ”ÄP¡‹köXX¤ü-A!–JG0hö!Øuó€Q¢éD’PÇJhåœ>H0r”L0‘øâÒ¨Ô1.0AG`†l; ‰‰ 'c48x(pìÐ(‹žù÷ƒúsn—öÝï!6`ßtø€"` ‡ =a zÃÐÛi$#³m´Ó6vvvvuÓ0ª¨¡J(qcüÄ/*¯í0ULÓò›_2z èàõb­Û3¹/”4æU®o¨’©÷üÌhQP!Ñwc4 Š7ýì»~ â½ ¾!¡ póÄñ²IŽMû-\É’‰‚-AíÈ—i7nÌïËì¤>iÈÀ1†ºøqzªO ÚšFÆveÉza® Ýc ‡µ¸oSlYE ¢Å£¤&L5ò2D[çêâ)ÃAd… —ùañ¾‡Îä@IiþŸQ|¿AÅ»ó׫ë·O"P)"Œ Aìàú5‹%$µ´`Eåa€Ð'ŽGðôð;Ü@ëºW³ ®‡ù:qûºûeŸ'4o†È¸ˆH’'ýúzdH@ܨ‡B,=^Õö¾¯ù0o¯<¹Ì›–º4Ld 3?k¶ +¨¶p7[§÷ËÔà}RÌ,¬Ú¸ÂÅfg“óqŸ*ÛmV¿G|ë®·¨‘€‡bU´*ªH¨loñó° EJ "RÌfïïëvý‹6®`¬ÚžóT›Ã-S”ˆÄ_i.J¨ÌÕ â¥$¥õ¶’ª" Zz¸Ù˜ÎþÀö»kœ‹l´¤ä ·u„â5œ~?FœüTµ.79м¤œë~K»åçËœò'Ýêåª.1åË9[ÆõÎLxa—3gGƒÕu]ðwê_܇ —§ ô9\»!¤0[Ò˜¾ÛèAU³)|R¼¨ÂÙZ]_VZõñ1 G¯Y)éRÓë¹;çû/ŽÖýÊSµ-aÇšàØ/Ï×ɨ‚ aÙ#‹õI5}6lÝžªùÝ{‹ø[ïã»~|‘¾uõÒr|ˆ¹î:ômŸ<Ë¥ñeETçÇNÔ–ž¹_>2½z¦>½º¿ÇM½?!;V­¤4rBR$ E¶É•åBÝ’¨¦å³%À¯Ÿ µôI*ÒªxS¬3Á®Dó߯9^7\XÀœüE‹+´ñ¿wduLSŽŠU¾Ý{â·Â—Ždá¯eí?<0¨C›ð8w5lnûŸ{£šÀÈœÐ^XåûÖ7dLjÍT‘ëd,KHbf'7.w#·Øƒó#šË¹¸'wävÓY0AXA¤]PÀ—4PšÀaõÓ‡‚Q'YL|%H"=œ4ûJA¡ÜwßAÐ qUñõ÷Úa‚H€óT0®lejX Y%±…îgm×4… BRp ÛlG$Ÿ=»-pqÎyW5ÇážÖ@Ö‘ …le´…c}ÈUYé¹€§,ð˜¦Àd`T¸¸˜Ž,C)#,‚liu¤ÌÀÖ`É>HƒC‹ š¡}8¹hÉÄ$ê?QAôñòó³$ÐA ’A Ð)3š¸tñãŠd›2³¾KÉtƒIöÓãÓÏžXïf RsíÝÈìæ™`lºó îŠiŒ¯w2øl:óux â‚bUÑÂ7Õµ:¸!Ü1ïxƒ‹jCÅðw~’c ýŠå K¬€fÒ +ôƼÔ?s«j°á; „ºLÙ é<`cpݦ¨‰²£hÕs(¤ðøM‘=i~ I˜< ~•Ém@'Nü é.'k>|Ëú"{nÞ1Feªl8†Ì"›‰~.^FÅû¦Á2ÕöÁÝ©è:Ôg²1¸$ ³µžP‚é2* Í×]Ål¯·¡0n63.ÏžÜhg;éóFÖ.MìE·ºg†³"YVXÑ$2pk 6×ÅDNûSáÄ6 ‰n n¨ )]‘‚ÎKqÌÄ>HœÔWM €¼EŽp̃bJµ\–ݦC+ZiÀˉ¿lC@nPÜZU‚fä°èˆå-KŽÜØXSd+Ó²ÞXÌ€¡7%¥Ò,RyÑ<÷ÏÅÅ1 ÜÀäÅ£¦Rc ¨ A(7–¨$™Û®2G#Ɔ8‡+Ј®Rö;Vi¶µk™X…í3D¡,W[®F¾å‚Bݺ‰T®ÖÏÔ ŠLÜy—Ä jVcÚ#Â[µ&QÙ±¬±¨[zÓ™ŠÜâ`•àhL%8")tÐc’gÞ~¦ûVfçãƒ~Š)Å SÀË{¸ÜBPæçÒÁŽW™ƒ™HmÛ+娼6©skzßk&K«Ã4óÏ-f–Ú±nfáÚˆÇvÛN ÛÛÖ®þœŒ%$hÁZ%¢æºfûYWâáb[ÎÑÐÁUT’ƒ¨Ü6ŒDX‰˜²5×MpÀCÌ¡îœ6¥W=C—šM$d± š7ö5ƙƚy`V‡˜ÔÙ.5caX–ÆkísqµúÂe’Ù±®d–Öyî2V-É©d£ûVÄ3H¬Û|8£‚ºç:Ûg£hਸ਼ÈQd„ÞÆ&Ã@ ›j\çØÁ+C¯<»}#Ñ4¢8y›6Méå÷7KÅBá‡Z·ñÚ²™FùÍz¼ƒUá^È俩ʃ"±`P’Æ•§Ô@Az𠊈¿ ¼mÝ*’±‹›pÍÉ‹GxäØŽ}¦¢ )õ'Õ…$vQ`³¦LÂÿ1¥>HµûRa•ú G£ð``Ç”¦ÒÌA’Ã0°¶‘HÌS¼(2 ƒ"òù–ÀÎùüÞ9×=K²Eó­é¨,w7sFw‚¯ðiØ*Å~ ÍÐ¥ ÿäJÚ<Ÿ½ðŽ™…“{ß¿äx{ù®gãìÙ xÈp˜K“¿…—‰Ì¨2(Ö 9‰ŸËï7ÏOÛû¾·.|܈3£ÉNÛ´j hÜщÛå&•àE0é– ¬T>MàéõÝ—ÈÒž…)JR‰M  (“„ÓМ&ìa01”‰EA¥¦6mÓ]s Àƒ"('tô2ÄMJ“l”Z”@-(ªˆ>„˜É€9—-9…I+Q£|ÂØ°\Ì(èÌ@¦$iES¡ ŠkÆA")ŽR c’DM4C#D(ÄYÙ`S«ª8 ˆ†ÒY;ê¢=…9Ç~©»Ö—C9º%N!¹ÂI‘Ã^ åʧ«ëd£4­FÚ4P_ úÚ~¿k}¿¨ü«¸0g'2êê0¸u–‰mAfa˜I·FžÆ6 ¥`†”$ (©$Icë`pÒš‡S© €ƒ÷…”-€Ë tŠ3èÉ þ·‹Öûüɇã§{°i¶šè%˜ëžQ’oE*ÀUdHˆ5¿hÝúñÄ:¶½i¿žîµð—{0Á(Òµd˜…SY1“d½^f±¥,¥‰â莆7Ç|2t^ff|ò”a¿;½ò^wâý'³ž;‹b-K‹…‰LÊ Ýñ³Y‹+(– b' …ñGÜaé¥_]o„M¶0Ç.e³§ÉÁ£WNOggF];Ø=w˜»ut8ðå·wÕÓÝ|uÌö0+&YÖñcñÝtÕj¸ßëy8C‡rÑ­Æmó5ìÂó±¥ÌñǾ ºÃ3xƒÁñü>¨óççkÔ Ðth5D±çžŽN?Y-Ñ—oÌé¼(½¸HŒŠF eÖàpéxÆ`Õ—lÛH R Ø_"’RªÑûsyµ¿Q“ªSV4P9ÚÀ]ˆ´X#‡òP;-dä(sÉ}ðÔ’³bÉ0ðÅ#*T¿wn4H¬LrÂ'cÈ¿zþ!Nmä|GQ–` ‰¿r°Â,ë¤bF2P€mªðó¿ÎD&ü>aw[¿s±ì¦f8*2’ ˆK†š;Ý5F^ b©Þ¬n¢¸¨¬QZPyoÝøùŸ5Éèq¿íyMÿÑñH½"3Š!!:kOŸxå~ÔŸÚ÷â)ÌCˆˆ þŠªJh(ªªª¥Ai¤@IW¶Ü@Cýñl4Š}|i®Á¿9´ègüÐÃ{“NÜØ'F-iétŒ[ ÀŠP€Qˆ(ÑRR*:y gÇïм=– ’Y ˜d‰¦ˆ$JZ  ( ¤RI’B   W¨aŠb‘ bå`ͽëcaSõÑJM /ø jÔªP JŪP(fbà Th(aþßa!ú'yø>Ñù¹??‚›Ç6k -&Idϯ´”˜ñ°ƒðjëíµ<L Ü×XD>°eωHžvЉhŒ=*JˆÆNF™2„MÊWÑ qñ`›y€6ôsƒú‚Ê2~©fB õª/B£6}“?œ~’ÎRŸV`YÆõ ¢Œ2Æì t›Q…1­NÔN‡R§D½±ªZ ˆß³ó× 9bœ#Iÿ`E¤˜LRYDì[{ûSg—kÇB‡&NZ² lÕ)ŠMÙûà”8|;”`Yr|ôQ¤;”òEÐþ“à ~ÓâHžÏfÙÁ¢Ex5ÀŽ#{³¸e›Ó1bPç8P³dƒÉpY>Ê*ZÈ{Ϥ~®|ϑÇÔS!]¯à_Â"$…‹†CÂ#¹B³Ú‡àf¨sö¡ƒ»¸`)øv&†–f~IJu5BÅ7A’¤%M’•IœÃì1Š£ŒX§Ú‘%ÙA’ý(Ÿr*+ËÇÇÐ#ÏN2;Ï:NH7^GS¨y0zxúÌùÑ÷ö~ ó¢ÆaM‘™¸Áò§¬è£~·èäA¦*g´| éÏZpÝճßSÙóc³†;¾­}±|ÛÁËç‘ øQ$=‡_b„£H×ÇÇÑ$ŽIA‡³°ä–§…¢yùý>"‹ÏO$e†7pMM3(\Ðùi¡ÑÔÏî3«AACýt’P{0ÔPôQ H¤ŸQHqJ'àÖ£éjðÓñëNhÝœ0Îèsô7>ç£×fÑÙÚWHÂ*:2q=BŸ§f…–1è7Ü ZH²HÇ‚ŽB–(îpqÁB… ,«Èù4s cì(ÅŽ“íÈw'ƒèá쪄=(vB:"¯EŒäv¡"¨äX¬`zpW PYŠ8Xåb(ÇDeð±ýŽ{H#¡ENÔ;ˆ|”ãÃ×É’øoC`‰‘Üùý (SôDçþ7¿öqú ä’@4I$›µR×A9C¡,‡ ÖDxhQÍô¼Á  êÛ&ˆXû›Y ûø[¥¼÷xww½üï¼{Á—3! ÿYƒ° pñ`ÏB†›úzš»-u7€dèÏ N«7G—Fû´PGïçsvï鲡¯Û¸ñ“6<£ÑÙ·ÌÅìu#©H‰²Ä»Þ|3 Ùk–mg”  P?]e„ºªCY–Öòr§¿mM÷U³iΕ1ãO‹é°‚Š4@€ŽfÌ€MqÞ,£WKœºÐ0Ó­tT-´ ÁÝ`éO8}%8pŽJy#Éâ7Þªª‘þÿÞ ƒ°5íw~Èq¸çaíu%UK s¦+ë§œ?4ˆ/AÀ4$àLhn`ÄÚISFÓÝ3ŒP±Š ôGt´e.a=,²_® w Æ›ñ8÷Œœ¦Cs„ 3¾èÔ:ßf¾ž@É2|úÜ 78w*¸¨Ôó£FyýcóÈÖÀ'¯S^6Õ°ÒãÃfÚýývÕ—䚺·¯?©XŸoGmë$²&Û†2°z¤èJÙØÜuf~7š`-Ñøœœ&„ªÇÂ#Úà‰(z#¬Zö‡_×¶úÞïõð7»°Èå@œ÷º¨ w{¾þqöK|àÚÊæ603šÏè3›VÀŠwƒ" ‡^X 92M®‘»YhäXùZ°5 žu`w¯˜B±ÉFK¬{C\ÆÄ·’¦=»Re`³‡8n"’CÒ…¢£ Õ¢I“;®ÄV{dÌ8ª@€Š Ù]¾ª‘ßz­Ì‘s-!šÆä/PMÅ.až¶˜ÃÞÞ(4¢â|D]eÂÏ»9·«.Œ–jHÉåÒšéµí×8ß7åOR¼ý0Ùg¦žrd‡ã˜~‘eQ;¨¹‘áYI•Èöíû-®ÛÒµ6¯ÂÆü¦CTdãü¨{þyÏG8ZXZ^ʼnMnEËìåäw«3å˜OGÀ¢pÑMKìtø èi¥‹0GiTc™äÊùó£Ç3”â»Í£ûÉߥfC‚`³™¦æ ~*¦BD“¤6\î#vîbõKÀŠwŸ^MHrßÃîg¸÷z8MŽKJF•|åï)#…ùŸN¤€‚Ûî´ÈÍýç:.Ÿœu£QÁà""iÒ‘ÏW=¡ó(tR½k9í•”\·K,Q­~™‚èwö‰tmÛÖ‰ÅÌŠ" 0R_ONÑ,gHþ¯ïP‡úb f ãïÒMÍÞÖÇO ³dضMïvž³ö,pºimòŸ?ƒo|Úln4ÆŠ<Œ¨Ë«þ"–O«]]öߎ¿qÖrìS]!2ïl!lN'Á¥š£Z«ÉÏX6,èéÚjR [–ÊŸe¡ND‹i‚ƒZ2y¢÷óoWœÙLÒͲ~Å=òÓ¶TèVéa‰ë£ÇÆJ—Fxçë¹¹ËLk}în´°khÚÊ–£¹Ë¦•¦/n+ÁŒÄXŒ-Ð…,¸ê2Ô8L´d=…«!VN,•¶ŸNŽl•`sÙE*æS¬› y‹£èyýÃ’+[‹tZÕ.nA·£ÜGJ$Ãç—çäª ÂÂ\š\ÙBË™Ìv]PYjÛíåZ²Û šì»§5ô«•÷XâZÍ‚^µ Žuƒ`€æÈ”ˆÔF¹ên¼ÖÚŒ-Ëy³J TÃBÕýétû@é¤Kw;;5ö~yhËÚÉr9:Ëp=¥¸o1šØDnÅÇ)‹&Öý¦C)”¥W Ô/gcuAÁç)fu¦I³Ÿ*[R@Z2ÖÅM}}|¼™ƒífY‚kt½Æó Ë Ư™û}á½ÕÃ$^§YC%•Žm’µ–eE¬-)¶±³:92i.cšpt»ÛùN¿6^TkÐÙQe«“‰dxcÞÈ-±HUD[ª„šà bIi9gɯ}-v?"¦1·^ŒŠ­—T(û‹ŠèI\™W”ÅÒ´áZÑ4­‚ÕKÕ-sÃä¶ðÇ5\ÊŠ˜‘h‰Û˜ÚŠlˆOÍPZb8%¢ Ê";¶¥Ý ihn=+ü%]¢Àý·\7V/C}Ãå`å#e=õ¹¥%c£¨m#Ù¼! 2;Ôc¾æDܽ—nõnÁ¼ª×°·¿åS'ŠœÈV‘N^¹ÐyšoŒIÅ9@øßëû{B²9×Ã!-ÕÖ‚‘4 ¦È£‚ 2¤æ‚›ˆ)ˆ)î"—2w"НsÁ]þýÏ ãž>l\éö€O|Íq`(gñÌ2H) ×%LS00™ŠÌ%„KIm¢‹i*0@„Fög÷0ÿÐÿ‘¼é mÿ›ÿµ¡¬6w b¦-±|³ Ï(iÑxÆ”¦–¡Ùa½P²š¿‹tßö—˜0² {ˆ3?­ dS þj)ö‹¶(ÑcöÖP]ï+É(<â4чÙ)§ñˆñQ7øŠtïS×ý.ΉJQ¢è{”Òxíð3 Žèvt æ‰âyeèOlñ""YÁ‚i¡ßñ½h†ˆpYDyJ&Rõ9²hZ ¢†ÊQjÀ¡‚­˜QƒŽ"’^ƒ mݺ91U²J0ÀÁE[’šD*a v;–Y"Š0ÌŒp,³†Š(æ‰& `(¡@ ³XHÌÌ(ÏË)±ABÙ0™ xq”$´r¤„Q‚‘°rH¨+!Yö@ð3–%#)£³(ÍÑ2I ;K¶(ÊÅH¶tƒ `0¤ƒ ,¦˜hš02ŠvGƒ8ü$8(WHqv£X„†ÂÇ8P¡¬(8 îž úêz¿ ÅGï €<~Ùë|dÉ&"(£öÚ鈧ìo‡'¥áÆbU7K™ÐS³í÷¼±^ ®ÁñbŸv|Gúx2ïCït¼\¿ãRQÖÙ Ž[Ωº¹"I‰Õ6÷ÑKßôrìQq fùøYP¹Ü¤SÁú:ôCh¢C9¬Öˆ¼çlW#úZ»Ÿôÿ'eíöû:ÍZñð§v°îQj0QW(‡ûïϲzïëg«1›ÎeJ†f˜D0I,# §€hN¬0 ‚_ÄíÈýee+ìòÔêP|¼yþÜzë¬ð(F´ÅDjw;x9À*ôZña8Á«ìl?“¢‡‰å"{=ßÁñ¾J´ù{æ;|tWõðïºóx'²îœSï{—qWÇjÕ—–ÉXÝÎ>kBjç0nKÓÒ´³C[²ËÒãÔ=Óbñ”e­•ª˜YV­ÒL›×¬‰7r7af/%ˆf­•µºU‚Kf,‰š­*"µr›K*J[Ø–cf¹ØŸýüÿž£ãˆèp §NCJ±E0”PÄESÀ1bB'††ÔV fâ&§Éúw§9AŠŸé@1 R@(d¡°gÃJÂîûïó±¬x(1·¯”ᜫ„õ Ô §ù¡¥?%QUä×Û^Ü"1Îg»mƒ'Rß&ÞQ¡©A†oðÿ©5½*ª¸§gÖ•w•H9tJõ%ÌÉ<ךw>¾;döª-×/žLDD®bõ¹à~ú(s޼s3D4ÓS‰U¤:‘ëå›—PÄ0JÓ¿™6Aåׄ¡m憙QÈÉô„ДD€„¥^0b$¡ó¡1)=Y€dËø7ËŠí¹wiþl®ðݦîBIŒÀAÌ0ˆ …‰ F%„ˆB`!ˆ„!”C?³1@ºÄ 5QÛ!°’:'d"HgFÊD/dc¾F± ÍfˆLž“X J<ïÀw‡•çÕ†çƒ6ÑÍЯK¬˜‰ij&”ܰR2$ò¶öR¾^ž¹ÐRÉVÓŒ¼º–’D¨’’JJR¤ à0ä°¡·Ÿ ƒxã DŸ*@ H$œ½±ên½rlrÒù:õB"¡ÆI»Gj®Å{aº48ÙMÂÂJô&¸Ÿ:è`j@%0NÚ’ôÊQ^cPÀµˆt¢²ˆf’æ D …PäåA¸HäÈKƒ^hð*3Šk“fÀYº¤…ÎÅ6åÙ.¢S2°IF™Jűš+.»¬šQT-PìAޤÏ!ŽeÈÃ’EbTºµŠRH¤dI䫘¢DءТ`( åà§!‡E͵$›+…¢«¾ cC,‹24ÃSqÖI¢,º’pã¼\Àpfrb‚¦ïl³$1DB¯)ö3*ã ¬ä³î"¢¢Šj`Õ¬ÚTè Ò((çA¥rG àÅ3.ðœ”àLèæ.&X”暥Trø5#œá„^Ë*‰F2e$Àç4½$ÁG4°š!”©Ø…ÃÓau(+iµM3²˦ ±•1áErņ¬Ã.ÙÞYl‚È$·Ç&¯Kp*ˆh,¦0/(| ÈbHj¨ ‘Ç1´gÕ!2ÁÊ4ÂG§DÊ$Â5 Á4¶ƒ2ÒA60,¼cNHh5ì°Q ° X–taT’Itr¨ J5¬¾v,S“jí2ŽÂ…–A6ªöÄ#M]ÂÜÒ •1»dKeh1…C\]8Pn¨·PT’U¬la„»618J˜Y©¤ @åQ…¤ÀZ‚è£i¹Fž’˜¹º–2´•O{)df/%#\0’¨Âð¶Á—©l«!ö,F4…Ê Ê2æ^Ë!+([[²ÉJ02¬’šË1a÷)HZ£!²GŠ £ Ë&Š2‘AT b†Ö…H3n™j!Û7vÙâ^Ês HgYJ+U€sÒ 5҅“Q‚%%2.‰•½Ê3N†ä¬¢Ž>΃FËÛƒ>X¼6a$åß‘TgÓ‚›‡Ëf&ë9+6@0]…NHúéb°]BZÞBÚ.M˜…¢Ô©ºHdµ™tFR²ŒPøh$†’HòCÅU“¤¦½ìŠ™B+9¦1À±†àÄ/,æ A£áŽúâÉMåm½3>k3Ö»;ù«i0édŽ <ÍÑî˜é„± ¦¤¬È£¥”S0¢E”Š)M—”>\’P`££&ÔPà D£ÀÓcJŠ¥XðIA+ä&ÿM¹fu3/’5 P9$È(²¥©CL0VL}0\¡p)Œi%V´”e™‘.…&ÀÇw i)6‡†.’¨«°Ç$£T ”Ú0ÍmÃ@c\$6#2R Md¬baF Ê#( ¡M †TD¹§)ªÚfwj¦©qnÔÁ Q&ÂfE$¡‰nÅ“„ÝV©B2%–Ú¥*©œá‚˜*Y£"$-ÀÁÂdáHLŽiœ.NWi â>1@°Œ5Ô™[˜aXá3•§7!mAX .ÍQŽX58d@4IÂRTR.ïÓ ›œK Á‹5+¤ƒNT ÈØ3Q&¤6<Îì¼7T´(vÅØq“ ÁŽ R’I2bÌ@ô1“/X8 œ-Æ ]Œ/’+G -@QðxvK‘蜱¨™ãΚe)!©DŽA. C:ÖÙlÌmíÜM¶é#ƒ(û­QI0©ªXicä˜LšiõqîhºAieÓA BÛÈÙÉØáÍÃF (™1Ìt¦ÍÂa­`Áh |‘Ô¼ ½:§ÐâŠaƒ¥â_ t¬ F–‰+(¢¡A¥Œ9 XÕŒô[˜ªÉ¹R¾ìbF¼‘BYY54|Vh´Â'TÓ !"L›¡ªm¢Yª†ILr•eŠTZ´Y –0 z‡¤äétºXô‡˜1Ø%óRSAÑ 2±¶ˆÑJYdêš™ úÇÃY$Bô¿ '°ü}¾‡§?§ãØÔ@Áø$‚[ .Ý<Q'¨î}¤ÉŠZ«2ûØËëòÑ… 0 ¥‡`à£8‚C•O"“Y ˆÌ¨qœRÐM”ˆd°§Tᔂizet”‰hd`h”y6†‰Á*(Éî3»“ˆea<ÆJ1DL;48ruÅ Âk‡F‰À÷³ÁNƒºdÙ˜[“K)…J+ 2YM9bPÔ)×K:ÛœÿÇldwu(ÅXBa©0áå;¿[³ç1}¿ùâdqü»1yM¦ ÷”à€ *Çm€ÍkØÛ6¡ûþu÷&šH’*¨¤?ç³~a.ë¼`q8ÇC2‰ˆpý¦™2(µñLæo³¨°wFÝ0$ t'äœÀ7d:wçMŽ-è×Ï–èÙh±Jz$íšœf19¸ZC”Ù¹Öë2ÿy×9âÒ`C‰‡íÐ5òÚb ngn~Ž©»ú "$#ãv´ÎÎ:…ŸŽcó±?Ù¯Ì<ÔÓ~˜|ÌdÄZÜæ™y¯ZáŒÏ±­+·6¹”•ù:³{M+Z:Ľ]ÖŽäå:MÝÅ»1˜ÏVÛ…ÉBÌ@ÛMP£ªÂî6îÆ¼¼êÚ½å®O867aï‘Ç´…±¡ò&¶Zåâ Å÷é}ú§ö©ò¿+QÄ·÷`¥0`ð”t!D"ZÊ "ŠضË"$¥([r§ –ˆ†æ‚'ô„¢¿ H¤°I)™ŠK OÌáõŽãŸWãÏõ‡íÈ4TÓ55QÙèõ…\Ù6–$ ’ªˆ¢Ñ†'Ïf"$ŒÃƒ‚€ ¡‘Ü£0~Ü>GøÇ±‡âþO£põ;Þ÷¥çm)¾ôÑIûŽ`]F^ÙpñøD4 Äe0)ÆÀ©¤‰Q–?k>>Æeó7àpߌí{ ê Y¦ªz|Y9 ¦qïxÞ6`Rúµ_UUõ×råq¹F470·*³œ³ððkÔEû†×Ñã¡Ì.=!yz3qbãÖëmד™ÃN™KìösÞØÕêrœ³¢¤".kÏ=3´ÓM3¬ìMÉðÌÚs¢M@|qóè€p„ C{ªMîPUÊE+l®¦£­×¿14Ióó~ßs˪ÙÑ®÷´9‡n2<¤© ˆaˆI X fJF MµzOîpY° qÞB7ÊTèú=c[ÒØ*a¡iÆjè”Iz„ ¡C•TF ?{35Âd²¶JV)Q‰_f)£cSÄL’üܰô £+hÆa Ȉ“°ÂÄÑ>6  ܱXÊþx|“mµúMz‡Ê}9×ã2Y¡ÛÇè²ä‚ B!Jˆ`<™’š„ïóì®Ò&æyõ¦/^T–©"Ï üYN–Z?T´{%ò2D%Зâ[<§ƒ áXNä`dˆjVÜRÜ2€öR BŠ3éMî $*H4­²,žþ@ç™щÅÈ(”;H˜w³œØøM²aÖɈ02Ѭ8ŸÝÂW¶œoaJYG$Ú@0Ó†eLÙM÷5:Uû²<ïˆXE„m`ÜndÀLdŠ…ôÒ̼¦§mÊt•1ŒeÁ”b*RþÐâ]›Œ_ ›b†H2ËðËù{û§Ñß7¸t;A¸yšHÈ%ÄR;=o'±Gdý ??„´àÅŽH˜8ÄÿXuþN)¶„¨G Gr;REéð¯ØY$øt.&týiþƒK£ççNɈƒ÷vpàv1ÑÁÅ:DêË:ÓBƒR…=P"mÙYÐ1À§JÿÞ;Îò F:¤éÂ6;£Pèa(áÅH4ÏFC"8’·vN×¥A¾©{¢ŠûØdÝÓ§^ÜÛ%æì­¬rV]Ì™´iD5‹°Œ=óVLæ“`¼œU|@ÄaÑÇ27W†‡ü€áÙØÞ7· ÙNÀÌ@ ÑÔÎmÂâaˆ`¤~ˆPº@ñBUÙ…ð³T¶:ÁÀÁIí~í8â±ûKÙÙØU¨êRBÜ}’¦aö7?ß=v|¾:qÔîãÙ^îæ€_j‹©}Ë+ÇO¾ðíƒsäïÕpONwÎ{ìs€ªY†Y»+yÕMŽx/Døm z"¯¥øö¾üîô´HV¹á­×=Ðï<þXð£áÅl~¿QÌé|ÓÎÔ¯G…û/ßÁá‹qŽŒõkæbÎUÁç²=Ï»$SÑ$²g‡iÃÐR†#"¾×ž‹ÓØöö$žÊ;^É8A•âafÒW %Ænì=zξ@;ëtÀõ}‰â…x7b×’ú4„LJ³‡gB aÞäYÀ)ŒrhÏäúø¯ƒå>CMb{T44P” Ñl/U”È'YLÂQ„ÒõtÈ|~¢›C˜Ôl1žè{“ØÔ ÆE·)ÒG  79anÖ‘€ml]]Hš+$Ñ%Ä¢3:|ˆíŠDzŒlÝÐë3lFàp† B±l4aD™3쑾‘ òåcªh©‘~Ôï„ûTIþdöyîïùÓGq`ðg>ŽÝ…càsÔc{»ôp(<øßŸ’†WìïÚPFŒpáQèQºâX‡®üà¢üf3sá½*öuz¦<÷Ðs`r hf*2)ß¾†Ò9>ŸÜ6+Aw/ôH7×g¯]ê÷å…R ‚Š¢FÚÍõ¬#Ø¢y ·Î*ôR-Ù¨›øœ=°°ôjØ:|Èá¼+ Á±[»Œ§ñ{OO¯:æJÒbtzb©0nhó“¤ßå>5>@-Élúoׇ 6¢rÌÀÜÙ—^ÓaÞÙ±µª`q?£öX¢þkù¹ì³Ñ_ª"2Àä)ßD~J/õý·ê¿tôĹøãçmGIò‚8¨V¯} ÁÁäYvö8¤ãäIáfÐymò`%PjûTi-ñsá·÷ùO›B¾ºt >™¿}º'ƒ¸Ÿô|'ÌíõÇçÛÑ~‚À¢1Œ>¹Êš$_Õ߇³£ß ×ôã©Aüçù—§móëϺ/*Eäóé¾wñù>Áß®æýÇ£ãÜL©ðPí÷¼|É?[;ˆ?©=ŸD~|ôlŸ%wëá£ã×Ìt6ÃDb?ÁÔrýQ©‹ì !Ó }=QûÄDH¿G‰ÐC²A»1íO èTù8{Ÿƒ”aô|xÙa¾v“Á~4õ‚±Ã›â(@¢¨ª¹|=ÊH©ÈÅà8 ñ²o—©8uÕ9Xi¢h§Øõß³–thïÙOƒT7¤pe öjì rT˜™w3j/ãÝáz‰Êkw gPHX†ñ ²Ä ¢²€´„eÁ›M7k/-Bô”ÂúÞÚu“´¶*°9`é5ßLÔ©·=¹Ø|…}gæÔ0xžÍB:ùäSMÅû¾ƒ±àY xždñÉ ùôt¿G¼Û‚ÿkÉ÷÷¬¬‡ï®†líÚÌì‹^œ¯ ¸]óóyà9ßí<£þ C‘‡X½ôH%ž§}@|Qͣφcáø§±ÒãßRŠBœÈ=xgOðC{!¹gožá~IÕû<³À"NŸÉz®¤®v»AOg¬!…g“½7«£ÐÜÚ¸•:n½9ÛÈtÚu"áàÝôÜÛUíÿZ$¯gÀwÑØ¬)> _ƒ`³%‘Ne{¦ô¨}ײ0ô¾ÙÛàÄ_Žå’p²e[Ö tßÈÍVR »øí¦Uˆ,ÄŸeº!eÆ1«RʬƒXçà|ÂpS5ÄÐGR˜¯Öç¤P»ÞaÐL&°d /qVC]tÈEWZ æ‰XÎða?ž ü;?C¹<þ „‡ MÛ5ð‡‡Ty½@ËñéÈí{K+R c²†ñ¼R¼á‰c®ß|/¾8¤Ñ£NП vyÜp•¥Cxç;wK8°á¤ ˆ£èÁÄQO]íF°wþ*Duçv{>ÓÙž|iʶQìa‚‰-jû貜Å0gÂü'Š¿|ögcæúøåÅÝ|ÀÜ`^ '© PÁh›‹=‚æô£ ýŽVÞ’tƒ(¨'ÈþüîKï‡JA×”¢âYHgŽ ˜2"¦b¶¯ÕzŠCÜ s ͽ•zo½üƒÀñ §ãvíɱà©Ì>3Ë„ˆCÑHtÏ8±ÆÂ€á½§y›ÆÖ¬Cd0ßœåiËGïþKå„ïö`¦i(ÇéûÀ“Ò~ò9>Þ²Ñ}> LØ1Ûüh]êx9O†[wðŸƒÏd"7X à0§ÀzõB—„g >j‰ñuÆw“ÑÐü÷yiägEØêq‚j×ã™ßÉü§¦ìô2?O×Ð?¥:cèø¿q¦Žß>Ì/ ùÁÁ»^Ia#›õ [2XdG¡¼¨…˜8z¬¸,¿NèPݨ/ Gx1/×U'É:uüDE´iÖú=œ“¶EñýÁ‹B—vÁ}/‹rM\5ºé¡|è2CYºVSº—Ãëéð™»;'èbŽëëÊOIöI=ºc·ÊtZ:oAßsž1ßÉ)¼‰èóƒO¯c8u‡”{¥.žÌç^ßöŸàþgLëö¡ yRª£‰ò2P© ,´Ôþ?ùúíý0ûv}/mþÖež'? z~vApþZ½<*'ò›üD8 {GÜnoé SÐÚCá 7A(!ÓèH=}*ŠQù0àæûXüÿ¼_:ü‘ž©ªøœ›dCNÏD°à¦’«&Wþzdr˜cE~Åógаà/ÂxBÀ×NŠþ¤¼ÆOÁˆçeÄ9¸lLd9f3 ßÍ“äñFšxBt{ÔŒqk‰Æ/² Ãù=°§]_~uÆèNÿžF9†6°Üäú*nÏ,ƒêlƒE|:-ϓߞ"öp) ’‘ÂH#~E®oÙ%üáê õiiòk½ûp^P¾‰õìvÓVË<ß$ ô>Ÿ*ôëáFf[f‹×G^Žð0±“ªIÂVÑ‚Í+\m Œb Ø;¯Ú@â"ë©ÆÌE’ä¡Ç¡U`†a‡Uy}uö> Ô·Îó¢#ØX£ª H~=Oœ:JUî4u€,ôcjãY£VžÞe7 weN;| vY,âö÷„À½µ}‹ùìáE öêëžÕs×Àù6>9öÂ:¹Èezv³ÐÖÒÿ&ͧÛä§-´àBžvåvŽürâ:õðC|zEÉ›óòvXMünÏ0EðóÃá2yñÛÒÚð¢HU>Š+0:*=ØÒ;x–É+HÏôØx7ÙŠ^ß…6|ùpv7aÇ,•ÁÓGI‹^ÂÃÂ;H:ù_VJ6-A‰Š/Âé^u‡‘×Ыï­ìSûÐPРýߢ Ûëã×ÇÄôÏñú˜j£ ¸L>áÁO²o¤bHò-³]\”&¡Ìq÷F½gŒxw‰D7ï??–ð;àIû ® _Uc&n;ð‡ó{#×¢KŒ£‡G¾/{,& hQGÑÆ™¹ç$b{`‡¡ÚMÝ~áàB‘°£±áÝš}úž¾i¹lÜÑzSÕˆ­íƆ ¦!Ž ì¯(1:Û® 6Ç¥p5>R•EžBööçÁèÉQl U yu-Œ#N¡Ž¦TÓÑO Ò1‚Ø)%Œ§ã€ÝsãÄ©®Ä áß9ïÐ=, ÞŸàqסzZ-;={÷ìï9jÄ$ ÞŽ/ƒ•öŽÖ °gú€n7Ðß'ϧîiÈb^ŠŒƒŒåø´Æ”/¡>…#²þ0§ø"}‘º=û0áGj?0žÞ ùýhvaïõ©Yç·'ï¶ž6L릷“Žáïtõž‚§¼öàOd;ë]ž ¹éöˆ 0_jà!ÄÏ„ì ¶KÎI•CCnw<'ášÎF¿‡C$G:Ö7¸£OM)]l÷]ðëNÏd?chNxžácAÑ|Ø4\Ç\0h+²`0€=# ‰oøùìï߅ƳJbتQg•…DŠz)‡#ÁM»;/Ÿ 8Aã(ÅôpNKWb^nM#ƒw@VP×I~ûìƒX®wÈõë~OLaY¬qG=‹',Ú pºû÷¼ÃÑZÛ é†:;kÚì?týð´E !SàÑ@çfGž cžÎ=o:=1îF»õÐŽ¼!!.ìõš¤ÜÝÚ"#‡a”³ÑþL“Ÿ`ìøïäa±gT"FAÈÒ…wôû}Æãp7Æsæj\É›)K‚fküÆ‚oÇŸA‡@‚ƒçm¥râÖ‡õù ÀQ‚"ˆ1Ÿ2ÿ#7Jóóuü·Ò„ÉÜ*pãëù[ù¸<ÿ“»‡7°qéÚªÖŠyj1‘FAD“lÿ³ú¿cî¿úÿ½ãÉñ;6,ڹαß<¸•!sZ5Fäop¼ á(cb‡\5CD£o>XÓ}¢0žêÈ#ú÷v‡A’©„@8‘è¹ööï°ˆp…& À$q©E<Ÿý¯ø\ùââ!"Hˆ!€ø”§¨†˜<ÒŸÒ( @áºfo8èpG…¨‰DÄCB”¡ÿ—þ—â;Âj% ÆBK·^¤?¸ˆ‰¿_€oÛ­²ÐmþÏ;†öÿ‹üùý— «áâѽ’W(—0"e‹2N6 wÞdsY›‡ Áä¦îÁâÑÁüñNÝ܈`… ”Òþ€òw.ɬÒGå |ž-ÜfÍ» °ñ®:*ÖZ‚g¯öÖ —©n& ) â½Ö€¨ùñèôý]3«;\úÐU¬KÛ]Ó«]ápñmW šÈ²Ïµ£íº³Û2ëS­£SB²2ÑU˜µ†U+B¬LN´`ÂbÖ«›H؇1삵å¥ÄÕ€Y`ï_‹)“€‚àäa’áªÊ(b˜Jtt!Â&öåÈhJ¦‘&€B!íüþ€ú“îNq7ÍŸƒa QÀh„ ‹   › ½¨Öf:-ßÒ‡ô›w\™ð7%ÏX8ψ%çaâäîãQÇÍ_Á\søÒÝêcßñQ|Б:gÒ=–â¿”Ngׯ˜âìû—“òÞÆBŒYe”l?—³¡¡œ»}Ÿ¿ât?0˜‘ž›sÏh\.¤­ íbc=®e‹{3Úƒ—SÖ‡†_ªÒó–ä˜?{ÓŸÜHy¢@ÛZãmøÓM0à o¶BqíXïtå<]êß‚¦a ÆPghj-<ð‡ §GÖˆ–e »Á_›ù‡™Ôý`5†´Z0'=èdNlÔzzh_$…‹5ž!czåœØi²zžÆl”>Ù‘ù½aòs¦€‚B'ŠX©Ì(eìnaˆlc2!Ùù‚†¡…'²ÐÅÔ0—mÕ ,¦ž?=ó|ÚøsägÓ¥e»(´“n4üYçûµÙö¾‚!ךR\‚RƒWDHWT÷üfkæ`kÝzéÓMØ3㊬ R ™Ç«L €»+è8µô/˜ ÝÊ-¿A²G³ ±MáäS‘³Ç›ÅeÉ»‰¹é0y„ ÷ªbÏ40hOê´)êE8ŒÔ>Æã‚ä¨Êù˜‘9"ÂH!Å*·”xü°1ïjaÏljú˜Äìß¡´ˆPŸ¹»¢=ó!jíw{½Ì÷ Q!…/ÖfBŒ3D•žŒÄ­%ÁÑ»4E$LJ:Ñè½2K°`áK å©g™CM?!˜jVL©U;B‚ž àÒ‘»I•c’‡ Zˆ)p±¤z¸ùž‡§ãÍù‡¼òìÛÜ-çLœ'žx2ߟc&¯UãÊPö"äX^^#Rª…«RUSܵmW{»éúâ1t¥Båß$ÈØ¤B ж8mŨíÏòÆÙÁÅvn‹ƒ%”NÌ?t;(Í&‹,áÃC†ˆ¤ H 43ÝP1"Œ8j¥#T’ÉÖ5†Ðî”ÐC·?Áò”Á΋…(LzƒPÿ´B’¼¿Qߺgò^NÉ´úþt•!“IÐ`!årì\¯\v]IÆZ¡˜ìòÜ_¸ÀÌzóýá$sØé§ÿ+ï¡ø#;üHÑÓsñ>èxñ. ˆ¡¶<žÅI¯ÞˆóÚ»Wž ;ÿ,¿;nþ;ôhz  ñÎÊQþçÕ$Ÿ?']A 8æyª÷Çs¼;é¾N‡{ЩקBÎ: ¡áB‡£'âø×atD£s¨ô…“èxÇBÙTœ“°ð×!Øáًŧö/‡c)cx²Læû%Jãçf®‘ãݶz3O ìöy=æ2< t¨‰ï<ö•û<Ä›­hY¶J:=(H¡Ÿ[°dá¤@¢Ñå]fç®Ë¶×i;NuÀ„ñO#×Ê7²t®¾ù_˜¼øðÒáæŽ\+dŒâ@î)ðÙò7ùÐÕÔð–RÏžç¥ v¿%Ù†óÁK¦:ppèVb$Ÿ‘Exóå<'MÝ!Åø„k éÞK‰õíÇé%ÈÆMCzŒ"K¯"O‚”¶$aCÛ÷ü½šv**xzky=ŸGØ0L&çìWÃhIc_ìùÎu†´::žÎQåÞOœ³ s?eÆ^ï×ÝFgÕ¼ ÂÊÄ™'Ôj³$Ö9ˆ½ßWevSò‹Q¼)›÷#F20Cí¹=|…‰ßŒ‡Év¯£²øvgc)ÐÍm&ëØ)è ‹,ÞÒ%ªoŸ8=šo¦nÙVoÓž‘|s_Ê“ýçàƒÑ)ðd“g‡¥Qލ‡Å …í<>û\0öy,Šýpˆñd2:(P†AëäÀ‹Tpiô'ËÁ 8Y¾†<=i^ª1ÂtbH°]MÃ0Ãh{;Áê†dB!§šìãÜÝ’—~ŸÃÚ tBW‚a¡ˆñövö¯dŸ§Á®²¸ð££;lö-eÝrŒž嫤èèüž‚|Ÿ ˆÊiÂý „2ýŽãàeö{¹ü›Áz>ß`¢¶‹?·1NqG@û¯êWÃ>7ÏËBÁ,£ˆ •áaA‚©>ÐÀü Øü§¢tóÖ$t27_ApŸböÍ>Ôe„ÓÙ aȧ¦)çZ߯ƒ™¡âζ£·ùc€Ãêºë;´³1èÀ˜ƒ¬î)“Ñ«ÏgG©Ž‘ÏI•¡ð‚}kalÆ ²¦ü”Wr¾ zNÅç¥Ëèw“¥`‘/Ó¿êñ#º/¢lÀö`y'¹;±{E¨ö:¯ŒqÇŽ–NTrÝÁ¸®þºBIi:)> íIÁ•óŸø 2{6ÄíÏu<âåGgH‹»¹‹*kdšsq†3–q_(¡øQ´pð8^ìûìtëÔ^Ì:9$óHínÐö)yt³å‹]H7Vag7ôáb-ö¬ûåG‹ç}³p‡\¾Q“÷é'ˆ¢º 0¿’}øn£T&Hx„NBû $4Ü|·èœ[œ(x]v¢>ç Sžý7cŸ”pÃÁ½/!#1}{=˜Y–ˆnœ,: Ý7Ù¼ÏgzOêóÑ^w¸tsÁƒgË™:¤~‚p9¾äéZTf¡Ì4R âÛ›ƒøPÅ;ÝÔÈëéO@ÅXáe›èS{ÓÃg³È<4dSÀ拪eáÝ|–ÝøûCxÈÈÌtð²/ŸqA9=yã©›Øç¥ñöpèæq½áÂHëH(XˆzŸÓñ}Ÿ‰={²˜†Ñ{LàþžGô§«ù(á&+·¾†ûõòF熚w2I'‰á>89ËÇßbÈ"úÊèÕpõKÞ¶kŠ2ñq[c2T§4\:'£ôÑÂÌ0íÙØ9 ý4vz?^ºÚ=FÛÃê»Íeewòmˆìo N„7ÌtŽÞ£VÍɾpHQ«ëë?IF$m³óð>—ãx"£¬·aD´ž†Ba¤ÜšÃõŸG@ÀÃ)VdНà£ô…é!G(Ì:alT†‚“‚ШÇm½®Œ@âÁÃh’ rº48e"rC‡ˆs½ëÒ=ž^ýž³‹Štzˆ=_^Íïsuà+ȧué…ë·x ì “¿{߀¸ÅÄ@u'#ä±ÙMP‡å„é4 ¬ks€p°Q÷u6~‰;0¨è‚;ýCSÓ±*zfëSEáÁ½BnM@X¯äõ„ ­YØq8{:-UuG4ªåuÙè‘Oà{ÃÙY †§”Ò¿³ÑâSŠ/õÉyžŸ<ù‹z&Þšâô3Ÿ8w} Ò ÌJ•ë>±¾º›¶íÈz+wÌ­Ê!à«í¨ƒìš Ü>PG;8xÙäɹsàQá¤)aš)ñ$ð|£OȨH¬­ƒ0´cÁî,V}I„¹|Ð3ÑÎ¥U°É†‡õ·“른*‹ᦺ:ˆ=ýÁÉQ(ðèyêµpÑË7§;,|qÝÉMà©ÁàzmaìãÒ¶ÅæšýŒ¨R ¾ÏÚä­SôÔGglÔWtÐÍïѧE W9ë¦Sƒº«É‘«‚©̉S„,Úß÷æ½*óÎJ³¹Ûö¼ø‚páIÀ4óEó,SÕØ¶Jøv.1tB¬ög˦•þ:•+ñßîÔ?™#2•/KYèngc³‚ŸHüšœ#NƒGG>ÁL–çèžþˆ>åçÜ%¹Ýö(áÂQ‰¬¢¡¥ø;r¶ÌUû¯ØàuñWpoÀÑè_Ž Ñð+ÇÀ*úø„øEH>|hÞŽz$<©Ÿc<”¢ûåud¼ÅñTÆÙ·a¸þ0ÕÛqI$œQVæ˜B‰ó ¦èÞûE¥(ӫް†u"Çâµç…§}cãL2jsbK*V¬ó«Œ¯cÁMÞszÇ8Ìp(˜lè`TfçK¢ƒi×@¡¶û_C–³áíHp¾¨ï‡“è²"Îè“„ç­çœ7¥€[Ãõ³&­»(PlW e%uÀYÃ5™/‚NMûsé€Sƒáéüo=+zhwùonÍÍp¢¯Å‘oÄý =}·äõúh$¥uÒÌA·7fYRãÁàör[„ø>=kÅN?e“¤20ÑOø‰>Âñ:VíÛ“£m”íÙeÆà´v59ÇN$Ê•?‹j)˜]S·F¹-f± Ibåy†¹Ñcƒòx)±ª4ÊwY¤_jÓë|t쌶,ôY'A*s 9¶%‹,¦üTæIgž·<·èo0sŒ4œË!4:~¥»(=2HžÐ/^‡êÄSnbzV -;>E´¯£lŒ³N¢)…Sì?vŽvê6 tÐtx„ŽwÑ„œÊìÈ’»¡×µ0áx1K ½“ÞÁ3„m#}û– '+©;z9|ËVh<$¸Êû|èzúÓ²OI߇ƒ £MéXv|—o¬P̨߷£Gªû0ð*Ô(ÂNˆ’Æ¥: Jέ uµ•r½ƒ‘鿱ƒ‹ô…EÆgÖx¶Ù)ãŽ(L¸:0q™¢ˆ)Ï‚Jxû­¹µd¼vã’ácáM';(1ýž§¾÷ž¯äM˜'r-Ÿ2ªúˆ`ÿcârò|ns¡èöÜp¯9«X/5{ÁHJöè2”‚T‚ ÈåÄ‚çõ„úÞ(?Soµ§ðŒÛß¼Ó%óß:p8ØÉ ®K¤E؆H‰7¬¾L5Š!ñ·èÖy»Ç™—“Îå¨%fUß^ÞaœfˆÞÔó=Ñþc«Ï¶.㉭oŽüÎ<ìãDÜás’‹—5:k¶Ê³ì\åÒÅâÜl^¬È»¯SRX´ã,6„-î6UÔÊ›yâþû¼óRñXA!–Óñ”öwx‘:$í87w¹Ð±a1Óá.dh„ÊÒà/ÅõÃæ{\á"ˆ‘P0X¡´5¥£Zõoh³~’€8ScÇ”ÊVvÒÇŒ ÐÐ1†b!`®vvy$â*R 4 máׇ»4,êj|‡…Ã&Š‚¥åžšÖªm*â–GO¶+¿çßÏØK뜙xãnšð ñS<®Î•6Mü<ˆô@[œœ³^ÇFtQ賿õ0ï…N™]˰„¡^§‹Îˆ’e NØp=² º0­ä|F ÄX$ wÒ:çt±bƒ0J'¬QD=F80Á=@p3IÁ8èPðY(¡À°³ê2†èYˆD£ó-‚™g€Ã±Èy…‡‹°ðŒŒdsFO¿„zJM+«Œ1»Cà@nµÀ€Ê—"Y צ~IÀÁÉ?X¢”ÀÀ §£»¶Šg%wê|:qí7ó\+¾¡Þ|ÇÍö1ŸV™)-3Üù˜k÷0¾;Ãä:~£Ê…¦'¡ÑòÍÉÅKf;SÕ™àkªLäKÇGݪßïdæÏ»›Á„ùýgga÷Åù (uC Ì(")FÆEN»&›<2ˆtØ >þ¦œÚhR'ãAgp:0 (DC¢”¯FÑžšÃ¿:ÖE™ûßâþ_ƒÏÚÑÝ›5k)Qd *}!ƒkÖçKƒsÀ`Ùå þðæ9iigõë7ñtâì¹C ek ‚ÿ¨9Ã÷i Âšòt9ÂÌ8(J;9e ¦†Ê“"–œÔ§4~v @(Pæ(’D›‡ 0&³¢ÑG„cN }Ûî{EØK¢ŽP1#ûÇOÇçšµÔZóR ááþþ£ù4°?$ÉUO›°ÖR¥W€À·yûò ‚‚ É¢u'‡ÚÒöÅ( qÀâ…ÜYÙsX£ƒ¬;Ø9ú¥b^*/Ôú”õ"žËŒå–Ç^‚])§^é=AJݵN0: \²Ð“¤c¾œ;3¶ ìqˆ—.ÇÓÀå¢u¶P¬v§Š\•Ñ×WDPáºó:"Æ üßßÇ ÛÇU†'²$’¸ÉFsÚ¢ ŠiaJ*o±‹îcÆr $üÌ–1ùPqI ~ºU8)ÅéÜ8‡²žƒl8’q 7àÛ@.× rç—Z2ÓIEIIþL‰ÉÀ5ø?ÑIêØ]`‘G¦Tºá`¢}7PpsLÉU!ÀõÜYãJ2>»\T’§¶è%O¢7™JR?ªrÅÂîû<¶ñ8·=mÒÇfÓ{. ×ÇÈAJöZj>ém>à Ž‹Çvó¿AõYìbR8¡ eúá– rŸÎžO[ÑÎb_M‘/aúi"‡ö(ˆâý­?ñ¿'EƒŠAí!cŸ ×ÂÝÌH³.ê}“öAE%þ@ýŸƒ˜Ÿ‚ϼ@®·ÇÉÑù¯‚hSóô÷@1o_Grèì·pg§h-L ëEÞ«NnµqßtTôëÀ~ß#-Ì¡ÆöÞˆaïÚõÈóã½Ó½}ôvr‰=9ž½C¤ŒÃK˜wÖ²#ËÿIÐá©Ø-«]ž‡sIM€m<ïxãŠ)ÂÛ´X/’Êãµ[ïêQðèìt¿G<íbŽØ¶0â~h´DD¦ƒ¥~.B³“³vªyÍü'â-Oh‡ƒõÇ‚v}•}1¾ýÇÚO>|8}þôF‹<3Œ~ ûøs¸:èIÆ{©aéàÛèì'œ?vÚóŽ{4c£Ó·DHÓÔØy`wË£œ¾ yLc7|7Eí¡ã4ºáßéçdj:s®éåìö7’C£1®9ß< ©.‚¹Æs¨âB›``ä™}§GDÈ ÜGv‹p\é&â ³ªmJÊt°êµL¢Î­œ’ƒX®h¯´(•UÎÃL’ÃuǦөçPbpÑÍ$Ó4Qã#–õMn–o* ã+á¦ÀmçÓ+´àüü÷¸O^Eô×*±M]1ã=¾DåþOÌŽ@«ù'߀ ãõáŸcàa€î‰öå%MßÑ–vsÐ}—DZصÈ7ê i2F‘©¼Ã:àáªo•ÂC–hri•ÆI#(ìw,£ àol±†ó‡œT‰8D1×áM0ì›ôD‹ž¥»b8ùÜL Îæ¾¹b¢ÉCœ£¡Ë¨Bì1Š¢Ì‡‡—£²·³Ðƒoq=ëO‚§l3»`ç…XùT&®é+å_J+ajôKâzl¡§ª!¡nú;«ÁuˆŒrg“Žqñ#ïØqCSÆΞeCvv~{Ãjj•X˜ÊÃð~4Ϻ~Ûó²€Ç哇£TüƒO䡃×ÚY¿}Ý¢ì; r™äk1º,ìQ² pRH6½7ÍŽp)œ}V#4Œî™À|»w°³‰0UåÇï}+×–ÈüöõëÓ c†Ó7žˆ”c}¸é\¼'ˆ‰!*¯o¢‘–xvY|¦‘ :Ò'„Bð¡¶\.Žñp¦Xƒ¸.’ÆŽWŽÊqéÝÊ+Gýsœ¿> 8u/…674n¦ž•e¨]9GqƒŒ{ìlTêÛ²UÜîyõÎQŠÄŠË£Š!ÙNÑfÞ“rDouѹ6¹û<è÷FଧëìÃØ0ÁöpàÀ§÷òù+õðÎÏäüËÅ1ír¼~©úöýª¨~§Ðq=§f'Gè_DÄüûÁÑŠÎÇG" ѾH\$9$¹B ŒæÕ*Áà zÁºÒõþÊüÜ^)Ö³áÃïµáM•„ëzõë®QC[@í”D‡++±ú,ìPì’NÊëæV.ÄwYR}FÐ-Z‚·iŒÊ¤»êø°+š¤ÏRHÜßP1ÑÌΔs¢‡D}ŽŠ“©!ÊEz¢ÂžÙÞã³ ž» 'éø‹ÔšâšdÂ9Ø4Çg6 ¡ ÈâMôé9ΚCÒ?HéíA‹:R3R^º<êO;·+Ž0¬Ôaû :4‚ÏÏ}\;»t-BÏ^^<.õr¹'äüðü¤þOÅ™øå ; kÂB}‹3cÈ]Ê~9wö:(uƒ`îÁ}QÂúÁ|(Þ ðYÓtL[lðpž1e„öpèè†(S¸#†¹Â(âÈ×&Ž amfw»,k%ç]É ·vlÏË⚣ Æžs´Áøù4‹ç£×¢¸Ù¨œ)xýÔÊÍ#Á™.k¾ aá†+Ëf‚‘ £¿€·!bÁ‘×eFóò>trλ†ÞɯÇN‘Œ3¦q1Eãp¤¡ÂÜh«* h¨<ì#'ã²£¥i¶žu}Dß"ñwk¬zÖUü¼üéùDü≿“¯TY—E'ÑÄ5¢½`|¢Ñx>™Id>Ûþ ioÏeË £I}ŒèÃì³JÌ ×ÓÁÌ ±ËÉaØ ×áEé%9ç1L”Ì3çç‡@¸Ì~F8O1øöu/KBа/bºë ÇdjŠo޾ ´[1‹Öƒ¯QW¼ç~Æž¸6£ðQû:QûÖ€Ãp,ea¸°;kRR ]š,)*ê,ûj¤T~Àð|3±,‹Y4fœ{NÈ'ŒÊbà/R‰f ·n†Ê(yÁ‘Á{±µáœ•Rlr [1ú„°}–¢†±\{Ý#æ€E½-_A™½ÔŸX—2Àðs±¸KÊÏܵŽ÷óýÍ^_Ææy"2OŽŠn¿©ÞþÕ›¬ý16 ÔÍÑÔU±ÍÔ 4 $A(Œ¢Id96,˜ãÞèêvÕN*:v¦ j™õëÑt@("¬@<¿¤ôwNñ˜C@.€6ƒ Âñp)ÒBøŸC0|3ÌÐȃÃK€a†KL‰L>­)P0áÎpáÃLLä¦% æì€ÒŸÞùúþkóÜ•Áû æa¿¯Ýå€Ù¨†šÀ}(`ºhŠUŒƒØ¢è"p :©¯›±™²õ‹Èÿ—UÖwþ»šÃxaPªÒ§7T°Åÿ»þþ"CÌîX'¤ù¨z„¡65@¡ E`@³ã³Ý kìõzÄÐn[{…uù3¿çûž~~Óý¯Mk1KOÅe_Ö \m*Ý•áð™ÉÍè‹\ÉŠK]YË[Ë\ɲræbe`ˆÆ£1b_q©a¦*kE©¢cgõ²!±³'Uª•aÖÖ#M·ÊI#*dl˜m£W/)vš¶!fñÛvQöVã …¦¨Ê­ÖW³¯ùê÷ïéUEDB&Mµõyþ?i§µÄ£í²è²‰@üí\“’ F[«u€´[VÃWf>Q¢8Œ-1pâ\NáÁÂAH$qAØÂÈk†¨iÿ?Á‹2ÕóUÙC!દ‰jdj*’aUHéG‹”{˜–—Yv˜UU•ÒX¥%¸ãUŸfsc¹™ˆ–ý›E*jÑN{…v:&˜Šc]ëBfç ›Ÿ(`záôŽ!Õô§F—M4š!ý<³!,ìî˜hRD㱡ðñN€™ˆ© $ÉeŒ›'—”^_ouùÚ‡Ë ¡SÞ¬ ŠÒZŒà\`¼CÔÀ­Ì|Û¬ÖqìѪjOHNº®£ˆ#õ{^¿ ypœR;K “– ǺB†¸ÎN·…”ÐpD¤Ù…0N ¤ÚDDDˆt&˜OŸË2†G9åý; šyˆJë0´&ïL»´tÚ7¦pœš4Óïñ:_œìñ„¼k¡ša¤$$£ l1'ð?˜R9ŠZ %e@@öL†un"©¢‘h¤Ã‚äÍ ¹(ƒIÕp$ãqI‘ÁÇ‚˜p š*fºT@N•ŠíµÖI6ì¾n3BÁX×ëý/H'ò¸ïOëTÓã¿=ªAð9DŒàÄ=¿¾O >D¯ô¾±Ÿ®ìçX+¯ï´ð{wúÿI¸ÂÑV9Êèc aNèÅ\ÒBÔ*Kdx:65¡QÌ¡ÂÉb†5]mçFY¸´‚smöÖéQIK&Kc…$œ tqc“ôt1 MÞŒGŠáGG àqž`X4ÍíUIm y«à©ŽrÊ4Ó¡è4iEÑhè”Û„¢ pe:èQÉ:$Xø5»\QÅ‘SÝæü'* ê /Éó—ðV¤¡“GººâdŠ9¥)ª8óSêÊóRë¸Þ{^|ô&‹Vþ¨™;HÛåøèÝZUhÖA¾#Q‡ÂÍzØ< NiüÊQ쎓Ñòe–)t0tZ**I]iåó¹W‹”÷·\ü~#ø>æAÃðv1Ñ2C@0àÂû!üôAGÛãrˆû­…3gŽS…XAÕhÍî0Ú쬓¾k÷ѽÎ(¶\c®hY™·¶È3À}Õï3%›¶û˜¢ûÜ÷™¢éa+©x>JÐì`ÕŽçÊ•x/‡Ví¤ønpï7¡”auÙF^*’Õ-Úêõ[¨›Ðê1‹"ÁN˜A2ÁpNrÒÜw•mš$£+î•2:­p›kn°ÇÒ0QEPÐv §v9ÛµôM1á4YÃ#‹ãðQa9>6PÜôp”C‹a“ð¡Ò ‰=.Toom·R$X¹Îk$kÞöÈû¼Œ¦[×’^-à-Ï@½\ºMa)X¢ƒéÑU…£Ùl=[‘m½ܘü•ùEìm 2ß0}1Ìä÷'} i€Ê›±ƒ=Ï:#ñEX Ð‹Ã‹ð<¼tšýpRHb5ƒ.LÅ»è±ÛFaÇt³ Þ3Áâ4yàgŠwÖßÍAÙÆ“laŽY<0A{=:«‹ÃY¯ŒýhÞXÃ?Pæw·ÑS90Í^³‚éQ®ÎiÓ”‹e6;ñvû:„…á£caÈHVý†'C&¯b‹ÑÛú;›?>ÃÚÿûå:†V£µ‡™µVÊŒ 9¿y¢èð¶jŠ)(…ВІ¤¢–3”£ªŸyˆ²IìÙcû´IrúXä«6Ó#i6)BD8ˆ‰„~’$Ï®”}Ž3x)t~S$æ Ü<¼,~µ'³1¤‘ÑôàÙŽv)Ý)þªú3:è‘ÿ#Pæ°Èã«9ØÖvØ­F“}VTw’@¤+ÐÆ© ã*ÈÍЂ¿¢S+vÉAj+Ȫ,ŒÑbô¥w@“uF½¬¥ÍÉ:*ŽýÁа;Kd3hÔ–Ú{4y™Vâ…ì{E£¢lí!Q:g®‡øñÒÚØá fA%3Áâô)D21„Š$ÄŽJ~Š¥©ãØ©û7(ÙëW¯[›/Q+Y«ú~š–'è~‡0ôÌsÓ‹qéÈÎ*-,‹ï¶" !GM´‘Å‹÷*ªsàNöઌ׃i#1§kîHâ‡Wgrª²~D±NˆÎiGu…TuhhAÑ}«—|Þè=ŒAÞA²J”;QôMÌ)ÒÁû ûžV IÓqºŒðqÖV¸)ñSwú§:=-sØØçiNidW~,7ƒ5”ò8£ ]%ufÃj)§\Б¶yŒŒ …"™€áÍ®ìàØÅšz 3¦o­ÏXHþ”ó;÷¾'mëª2N´èÛ”sµÉ{!Øì´Ùwôq4ñ¾QO×£¡Í<>%‘ˆ (–˜2j™%+Pã[e–X? C à±×hŽÅBB6vƒG‹Ðhöx›»‡Ci¸sÝŽóП–l¹Eè³cJ‰ )B“Œ°2NIgvYa#œ{>ÅÈ_F“uq¡Ã¾x1Y;‡®‡ë³³lÄò.ÏÎ$›¤ Z„2ˆˆÙᥖC#+záT ÝÙhs×L#¤¢EIè埰¯õ¯šX‡?D:ŒQŠ<ñQ sà}¾ý©Ò‘žCz0覣¦¾ó£š ;Y ŒQst‘o8k”ÏlÀÜJ1Eër:Y£ÁÁÌ~“W^¾áÒŸœÑp $a QÝØaºnÝ$YV‰uU–êÛ¸S–f#«®ž-ëóùýOÑ-Wô?Öpö‘øõ‰±”r Ž!÷êl0[rzœÛŸ¹v’ÁÍwÒGµÓè±³£zîò±#äöPÝôŒiCÉÒ>> íbxB2®/kxjAªÔ18¿(1× í‘Î9ÁK‚Î@ÈöNX°e–=… —ÏÛ\“‡²’:.¾ï«¸U,ôts:O6$ÅsTvaÎw EãS“…©Ã±QÖøVwMÅ^…Qæ×êA`øº2Ö\£%ÒAÓµw7¡Ðø/ †g²ìâ 4 L뺜ñlÒÏÇDÏî]·",ü~?~èøëà½v#Áö>âȧQÌ-?B‡(ùRlQ§‚˜;©ö†;ú4‚ 2.y8t?Z[†±½’eÂd ³[ç²h³UÎ •gMÁE”ÑÔ•%`m‚ðiìý9{Šs‚ŽnÄ?yˆ[ÎòÂXµqÇj›‚œáÁ»ádŽÃ¢®ÉáØç@¨×ä¢éa‹ ©L .%¡…sC«N§ s»p?…#ÝǙࣗÒuŽüU(v8ž¸>–Ò{1Í å°Aác“C-àÃöF±Ê‚±g¼‹êû4$u`‚ èq¡ÚA9ÃtŠ/Ì—°s³ÂäÊêäÁœaœ¡GŒGèô8æÝy<âËÖEô®umGèr1’œÎ 1Ó”3h¼¡¨‚"Y>‹Á£AÞ;:#¾\wë³¢#Ÿ¤‰Àá£ãuðAÑEm[q‚Æë•J½ßå÷óˆ‡uùETD?&¿÷öAÀúEHÛ±E?ßÇ>(ãò"Z,ôÊZ5+í¨³Ó2!Ñ+î°fY-xÇÌ,ï^N×…G¦æžŠ*•é FW§‡umÕ‚ GQ‰ˆ¥¡FtŸ°¥sÝŒ@ýt¬;iƒ±T=…ô&†Ëu×·<=—YÆLíü¢èì™.½·£‰ ijNP´ +"û*:a¸B6”¦uÞ¯‰.‹QS­nw£á Û¢·¥èWàØ9ÒñÛ $ rš¸hîc6u³ÂNd ƒp*u8z3QÆÕ-†ƒF•;beÔiuåé]bhbÖ!3·3fɉFÆìuÅ„AênN§RÜ=ŠÏµ«oMû[!Ü9³v6zw Kãm[È{/BD'ê{œ|æö÷_½Ì‡èHß©üÚgó7íOËÍÓY‡ ð Óùûi¾*‡3x‰¶Ýzã0Uøµ¡B 5ý@°Áàp}cc%–`ñ¡©’Ê TOlÄöz 4ðS¨èSJ0aƒ² 0²ÁBÈ((ŠÅ ˆœ QKž1Ä1$j~d`“G°rpÐè”t: 2ˆ,À“ýŸö¿˜ï[} q¹kZ怭oÓÑ¡6{‰L¸%´ºnìîk  ÞB˜:P@Þ"–ÏYÚý¡^¯ê:KVg1X¬, #,Ueí×ÿÛÁ–òì|]|+±€;ô‘É&¨Ð0"0nŽD¸–C2•sT2§LˆQ¯•™ºÙOë´çL§2Ó[÷¨¦mU×Z¸W"éZ¦ò–ضÛ|Vˆ›¸Ù•¥še»\Ù×vœe•!v3%®Ë6\œ}¥†l•m†'`ŠW{VV‡‹iÝ—Ú}¦‹h¨™Øy*àjXWiv{ͽ¦ÝÉݲ÷*§5ÅÖ«\ªé­j´¤$/{›'è½ú¼ƒ@׺D!-`רE7C{Ë'Pbálr|܉½²æÝJë!{jÏÞUr‰‘ü’Ç0¢Éý ÂÑâ"Òâ-ú©WâÛÅeYwPU:Xršur í§3máLL¦f\ݯŸŠg}õ»»ãœ®Z¯‡y$ ý»ïDc$7caç ä–!A`­€¡Æ½L/)´èʆS$bF‚R–BŽt¢ ~vúÄùWÆë¦ §yŠGwqâY»úN|xåî‚`;ü7—ÞgÐ$í)p|…ˆ˜„K)G¶Ž”³¢”Ùt´28g{s3¯ã÷ùy²íÐT-EPÕZ­$ÝôßSä1>)? Ô:§ü'>¶÷¼E$¡E‡è‡ïŒ¤vsN°+GNm)Bi†ë…’:~u+L:(èc bP`˜èBÎ5–,8`¦†‚Ê'­ PáÎ=ŠÁe– v2@(`9ØH($„&evý3êô®Ý¿q5rgMM÷ëúH)øúž*|G»p7zõu¨Þ0×}Gô´8ïð3“lFk‹¿M%ƒó„Å@6 C' Œ)Ê)P­]“F|V‰Â)Êb8g"?â“”½Œ1*ÅŽb¸=JP¿a{I^ûâwý¤ té ,~iЋ tê¥óLBX3™ˆûÙA÷?£‡xݯ\#‘ áCÝ:BP¨=”= ¯[Ì;®®×ăÉ:¯^ ßdzb…/ý¤Ô9èfÛK.GÁxÁ\X?Žœø"“To ØôÖãk,¸µ=pˆZ[ø©£ôüÂ~Sò^"‘àÛ®ÈãõGd¸LM}†¸¶¾°ÃجaÅ5 T†0:û\Êçöß9Œ}„]]±Œ:¾ÅZ>ÓÌW«. Mü1aF­ù'SÜ·]I|BKRoJ9\õž¦4‚ò'³ŒôúµÁAŠLaØÇ†êO:®…(bLÂ\¢‰DÛŽ‹F& 1I,‚ŸgM{V¸z4ëzË8ÆŽ(£!/xéÑÙGg£°¨ðC®‡Eyïνƒw}xO ¬;ð×-AF[€N0pOG Âô ÂèÈóåÓ[/ö%ºnì¶«ýŸUOÁóáШ§¥:ô+„v|Õ'Û AÏCû b,’FR¹&'Û:/1Y/~N2>GØ8=,’žˆBøæw Žô{rtÉ (TiJ2Îó‡0wM³\R`Z”r¦‚ΘÅ< +†ŠYÎŒ [ œ2·Füáå®{:ÅÎŒéú±è£ƒ#…pÜa€’åŒ&D iá ýØvœ2NÏ\ %a…ó~Xì$ÎzìNކÁðL’7€’¶µÅZÄh(dð8(#Qt#"ᄚ¹eœ4¶$bHâ? «üHâ¦ìRó)v9M³1ÂÛfªü~,ü!ª'àúýwÚzƒä=§ QX>/µö}Å>\û)á£`RS§ƒ:‰$w *–)BÖC (aÜÇÂ'·’¨m5€îIªB‰Á¶^úå? E8>Š(¬J•F¥ Ê7ÎDà×΂©zQ‘äfB…üt\ïF ÖHå¡'Añ.ç„IUñ×+®)‡²|UãÏ]šxØÆ9 ¡Ù äÛwç Ç=¹Ñ'žÃÁæ… y&á§ú½%*¥ÏÑšz;ƒÄÑg‚áù_ÍgWêÖfúuÓ-ÖšôRpRp_§×ö£vvþŠ<4 QŽÓäk£* ÎÆ, ¤¶‹*ˆ a¬èÙK‡EÒ/Ol“ òt†ƒ=AQn*Ú»•lŸ Â`ˆˆ·2¥aÖ:bvxÀ˜þ2JÙ>\  Ç'"õ V 9{SgU×… kÁI샨’ d îc©S‡}Ž|§ ²,ä7g×^×¹:tyÛ5‡g¨§×­ñÃÅÃÎS¢J¦ç;†[0Õ“¿c?3ÖkÙèrðA} w téØvÿ…‘¾ÞœÅìh•í•®ž¥š9û>ì~ˆ‰ø&Žñ<ºp2|R—‰lHéݼMõeSܰ\ù;Ž9‰b‡L?£'¤ &J$êÎû:5{4ötuØ)à„²¶×èQT¶v·=I!P䇵W%…†¡‘J•|%ËY«àx”rŽpC¢§‡£O³’§ß‚"#nŽ_.$n%ÏWU÷êOº!÷;þ8içb‚‰àÁÜC–( ~$sÓPåÃ8TŸE/—#“c—Zrnx4Ù”1÷Ø>å_D8 Òº6ŒÔtT \—£¢I0’tQ¥‹g`Ÿ¸í,IÁDžOkøÉèdÑ›Y8I^rXS‚i3†/:Øo*Jê8~8µðÁ|ãYÈ‹UÃz<ç;îö £D:ríÖÓI6ƒ,¥wd¿G èÀ‚L(²¢7œ 0”Uá =u ªIe˜}ä|;òá€(à07ÀÀJ@0…‚"7MÛ3W6ó¶—ÖÈÙU[Èjªïó'ä5WóûŸÍO<ÑNÎÍO &ÏPÁ¸· ª;`§Edý˜åJôF|ÑS뢒Ð}TÑÃ3òt0ô5σØÐ½ÅŠC8×UêŠØRÊhaÌ-ÈÀ”Uëwp]“£îPõŽ`ýÏ}åŠt!*Icžs±R»c¾›ÆuN ]wÝ PέJHõmrƒÐ:(ÀgGGD&–<ð(±çMZ¦½oªC`uø”½Ø;=žADx[ŒÈþá]™ŸíÓb˜hYbû%úëòÃÅ< ìç7eQàýýóñ]s;)r9º›ìëÒ§ÜuCð~–pô1àuèQÝ>Ô„PdØ\Ú{‹=’*XÅBó¥)€·*ry©îl ôHG/³&ÅÑ»U…qQÂ’ŒÄµÕ qÕxŽ+žf¦4_8¸B’ð/4áÄÔi® *hö¼¬p(S²Qr D7…/‘&ŽAæ~Äc4£º•4LÛ’GàÊ…(ã)¥¡Ðª4º< qÌaFä2A6Y0LòYø™~-½_mÕהФsHš³ñ¦Š¿t¸»Ý&‡ èVè‰pü39'—ó½u7¬D±z@¦…Y8DÄZÍí¸­¤°ßaާ^m6 äŸ`šR ~›ÂݨËc²Éè¡Í°¦€Ù m´¨.Ç$ê ²ø.’[HÛg\áj¡IÍ¥ ,ÈŒä8åœÒS+…‹â7 8š°QÙ*[¤DæÍ•Äá„â6›|ãLA"œÇ&`Hdä\=ÐÔ0¼'çøÿŽwòéñûÙ$ë3Ãm°>²@?öÿopçà1lß/¸BBûüt~ %(ýFtÑFˆÑ·ŸoÜ~ÀüŠ‚o)óÆ €N>Èë’¨_l¢< ÚË\ÓìßÚ\µÔ²Ã,L ì>ŸCŒA2&‚s£©Ñs®ºÑ»š2Ü4ÑéNº4£F­œ£­0ßÉ‚Ss•º"Ž¥ÍÚx·šðÇr¦›uÔÝÉ”¤˜*îÍüPóA§Ñç\ˆ}ž·!ÀT šwXòöþ‡´ößû§™‡Ô,AP£Z\2–›Ë$ìyãAžS 0ÁòD®o+1c@dž6Çô¬ ð3/üñü¿-W5õu+w•?h\‡ÁíQªaó$ººm]¸›X{ÅØ+-hÕ˜]]˜Åj·ɕկ³-åÔÝ›¬\™ÚÜÉ‘õgZhµ™ØÉ¢†zWÌ­•‡·jjÙ—¹ÌeVRÞV¶ZîéòÞ•¥•Y×Yæ˜Ö&WnR_&g¯úôýiÝ@Ç †F¡ âйåÃEÅJ5Ô’­6/¢1òõìh_‹¥ƒäú(sØä–A¤QdSä…ÿmÞ6”Óðt @ÑõJxÜ‘`—\E☈fW¢L”SŒï%* PÉ7„w•GŒ§MàPB/Ú—¢AJ í˜¢…¾*”ªMúpP7‚  Q)C%z£ w‚«½Ò‹kv–U* ffª³…EÌ@dØå7×µÎsœç•,yY(ä ªDðñÒᦺaF–,Ó (æš³ ¥T¨»1¥ Œk¹¨ñc_/0a`Tƒ‚â±# í£tíXƺÝ;3HNèâªpÃF¶{*­FZ‘²$à1=$™(¼UÚ_’uÛ‰&–WGëFñÐ×JÊ4ú#®é°Rò¥ G$aGàu2]ô»:û2µ®ãZ–è¦ÇÊ—ð#Q§8z>PaÈ SØ\¿¦ ÷è—ã×ÁÀ—ð#£hh_ ($‰bÖÑÅ;xæIR¸|ŽIv0ð)WYKep8q#žšS1l2Y#·‚§¦þ¡Ü|î,“£Ès£ÊéíÆFvÖ ï•eÎ¤Žƒd¡… Aáì~é%8d3I£Ó¸ÂŒ ãȼ)N"·K$%ZÖXã@♦h>c³Œn"NÀËe>ƒQì^üëÓ®4ïdXgbž¢t ‚ Ød…g\•ÈŽºî_2mFóí„Ï›è©ãø/'QÁ.ΧCÀ0`ò!ßÐ é"Á%à:|©) D~0ÔaŽÍ¯d…i0^QqBŒ} rdÚ8'dŒACY$ÈýgAôÈ!ËqhBº}½ÎÊ)k â¡cµ’3¾Î”xs…"ˆ`ÅÄNΜê±Ð\c}âÌ”±å7`¡8È,TpI2„DH•ÙTìY÷w~lƆÐÂJ‚ŒgU.xAc”rH S0e2 1Ç`aŒ 1x\º•²Ó¸QžÄöD좘¤™ÐÜáG ©ö ^ W¡ò7Õözìo»87F\™ì:4öH@‡Õ_Éá!¦±á#Ôª÷#¯¾ª{g¯OK‹Ÿ¨‚!øoÇÏÊüžs´;ðõáf|…‚ÀN}hßa† áòX9<‡ÞŒIr(1á€t¸ALƒ£5%€É” ¢G>Äà)‰‡QÐÅš•(úʋÖ¸¼7”ózø>š1¾ŠåÉ%UÆÎá‘N¦ ðë¼ÁFE”¡Hr ëµIô¢›^ƒG“F‡€ÅÈ’éÔp (”/+­Ôòù×c‡©ë0š'˜Š¯qªx*_ (fà„«œìáVÄa (áƒúî½zi%t¨³¬ÄVêhŠ<õ)x(­{¶òHžݪR¦ÜßQ}ÎLÜfTò\œùùÂÇùJ_¿|íIô/®qüONj{d”Š«V³£aû­È²«]îØ8ÚZQ°ÁΉe~‡0³L+¯uc€½p-$jÕ8‡Èn>åæ?>Žð áÍ$Ôr˜ýs:8g‘…Ôñûp”¶jÓ¬èTÁÑÜF鈌igg¡j»¬è¦ÓKês8Z”z<‡îº{NÖIv¡¼í/¼ÃQv^à‰M‚(Å6z<0êoYL£—ª¡+×V)" $¯0|$asIru(¥!ŒC…Pr7n+u¡cÝ¢IÇúù¯Ý‰%Œ_ g¨W›;L!!Ũ$h1ѽdá€Ð0¦Ã&å /Äw°ÑpQBl ›cLƒ«0˜)]´áò(IzQ¢Ûë'œ¦³)°W—§…¥¥±±ÁºeuIÃèFëMšÂ"àôñÕÜÊ‘ÁAÎOÙ9¨uÙC_Pwİs­R2dKè±ÔXzî\Ä»‹ñ”§ŸŠ¨¡^4F™’PZ ±™ÎPÆ9"’¤UXIIg”ÚYöšhã‚ãÊ;V ±ƒeÜ‹¡MMOC ppb@àtÔï·/Ô]K³ÉUuÆ|ni³ó÷£î‚i¦©Ø¾‘H^ ôÅÜÑéA†é… ¦¦šòN˜7. 0 Ë¯¡Ç¸Š5Ð4IÌÞ¬±¯‰#°ÚT¨›ÊûsN¨t³~‚‰Í†å´¦uGŠ¡‚££ƒQiƒ¬é~+;Ñžß°¨$VÁ†~ra7¡ƒQ&q4i´¾pJá&š7-ˆâ›aÌØ&°ž ªaç¤aɼ: :é…‰l#¡x Ç,sgœcM¢ù' „hæÍ–‹VäˆA1ã–..ʰdÃs,°Ë¹@‹ßÿ7É¡'6ï*‚ý¢Š>áô~9KƒÁLpÕfK"sŒ0Á0UüÉá< ^4½zÐ @€=8ô‚`؇&… 08 ~ÒàÅRaö\4½ÎP )JO˃Œ2ˆåht>p°þ!Cc¡Ã„Ÿ,, „%Œ@Y* „”< ‡&‡]ßÍ=ªù÷qÔ$á›™>Ô6`£ƒ““ì(Dû~/ ö½ŸÊû;, Î½wsiÊ v‰€ @@!³cwt³uLmòÓS«xca[óÛA¡ò60U¥Ëxª­‡™‡—rš—Ejx†«½ªW%e·!î¯5ò.V¢!Jl-±Åf¸†¶,…–¶¶—h§ÕQ˜»–G•,µg•VØ×–lÙÛÜQçnóZœY|©/Um ™v%›Vëb”‡&u–cMåæV¹ß;÷|ˆø"¡ÜYðžþþy:麕Wþ…]‚ÆøúùŸ®K}$š}9bŽ–kŽ÷oÁ¦í‘šñÇQHeXgòªwSUášÙ­ÙÊ?Æÿæ.*fgæ¯Ó¦'ЇʱÙì…«`Ërác­b»$mræE j§,íÞLéÛÚE¾ó¾p]UM4ô‡§ËíphÒc¸p>'ˆádL0>Nš:t4¿øŸûïçû>Ó̓óµ}õc<;Øw|ÝÁ‚ÏAy¯gÓc“Ѹ(à 榒1"Ée„Š E;ÿŠ@ç * 0ý¥& œÂË:R Pý€uS£<, @ª)¡ga€¥AA‚¸Â@Žwf%£kšXç rêÍ8é‡.` ÆÞ ªAlç tÐ`™‚I: ÕbÊ0$a1H‚xÏÆ®;bÚ“ƒãÆþ8ÿªõI‰‡O®ø“akGoÞäÃÐÁ§S"çøþÎË¥$aÇ@gêÈqRrËØ¢ûG@ˆ!vñv m Å'¨±å1MH›ÅŽaPW-²³†æA SU ê¤×Ú!Žºêœ¯,¡e6h e(ä*’rÆDšHs\ bN¨áÛÕ¥ëb@1¶T8¥JfávË,é¬âbråïä“l³ ³·UN“C I.]ðS5E R‘8 Udñ&Ö&›m¡tæêœz>j`~Å`õpÀb%žû·ì»YENš‡ee(µ'B+m JÇV‰( Â Bƒ!ú·w“›Œ·«Ö³àòÙ3XÙóí ↌:`©ÀùJµ9Õæ)¡ñG·ç¸H¢Olžý/„\æHç a(ŸVJD–aC=ʃÚ(R\Ùr2ñ0Ù¤uQ¤«0y SE«”SV†X 5H0,rc²Æ¦:jJQRüÅŽ¾Œ.Nç××~Ê#׸³ÒËÂô(ƒÜW5e+³×¸ê¸0¼ª0¶-z0r2=kG_cÛ'E_¡:2„‰<:¢¤ ¦€Žã´óŠ?uÑÄb‰B“ÔœÌôÆ jpcÙì°u ”$Va…8w ‰\áãA*ÐÍoÖò(¿H1"ÙVW†%p¡ÜU”`ã¨å)­Ñä¹@XÅ1Ô4tm–²²/­NÞåÎÈãMØu4YÂ>9Æå¼åŽ©X2rÂG:x”†Í¥ áÈ»)˜—‡m,¡‹¤àVÄi}–n*|ÐÕi} …’ýœ“³Þž¾fíFÑJ/Ñ×`Öp÷&ž†,êL:c†cVâÂ\óÊ12Š9•cM¾.e×eMŒ™i,ÈÜR‡<(î4Et(xŒQÉKJÄuRÏuÕi®­S5{õ*«ë_ÑÔ'ÒGd¢Àê:‰Ã³>à=5šÞPÓ3êIé¨ 5XÁ§›Œ<”(¤p‹«½±GÄdúºúåXÇŠq¸k7†#:§ §Å¢»—!äTõÌ Ófø’¦#–Ù,qj H98ðüR LÃU¥iÇ—"Æð‹8åº9\[]›Ô…åÝ&#áeÝh:,íž’8C4IÕâ‹q'LãÌ9„ó©0Þ¾¬±Íª7ÕIµVQ­2üçXû±‚Ÿ I*20A` ü /„ωÑìÏAçb’o{ÆœŽÊ*¿¼µG Œ©E]s£ É‘‡!KéŒ=ÂNQÜÕ-)ôfOEG`p³”¤–Iì€æ[í1‡:‚:îÍÂØãŽüF*È ág$Â,Iaú·F>{©Õ®²c|ª(V;ÖÒ„³IìàȱmÙðäuççBuƒ9вhÑÈNxpF Í>Æ@a×{׿:£©×ô+äáÒu¶ãM¯ÇÁÒ‹J‰Ð{(.ävˆÛ»SÚ/¸=š žá 뮂ήG2Ë#„­ÑfÔ½jÅüñÉÖÃŽÜ'yÅv¤u©(®mƒÈᣌ @ÈÊ Î¼×v”o9"…‚t{®)=¯žº! >Kì2ó‡XiÉn’2]pQs4•9g]ú ìöz£ßGÜê’˜K •Ðï׎SO ˜áC b§nWE±lÜ8Ú/$tÚš/`„ªJf j³+ìpífô°8— Ê1bó¡{‚xXa¼— â*Ü3uzEOZt>¹EŽ{N¥HE²“½4çuÉÙž „Ž+1g£€¢—ÒÞxäØÁPtÂà±ß¬$HËóAÂPÐf§!Mi!ûå‘mÈœºx‘þß_ÍüÏ'†™àÈv‹Ï¹‘~¾8†œ®úå û÷£ |äÊXÐ%Pv P-ÞsìKúÀûéK·aåG¡<·Y¥Ÿ;,°¹÷liÏ0»ÉAɈePåÊ‹MÁG1Å)Ìvc¦è9eµ·|°S×Zcº;ÀQ”ÁNÑ¢CÕÛwl²ÐA É‹K»„é³ óßa7]ïΊ èɊ艂 ÁÖ$íHY/fÛV!›œ‰uÑ©.Q~pÉäAÒto,S£'L#hž¡5Å<¢³t 8l±2Rqù©êÀ¢ ¦Ò:k+ŒR'M˜9gÆaÙf¸¸Á'C„<Œ„6SqáÖìàaVud:WT·$¡ ã°3Õ<¼kð3‰â¥Ä†„UÉ呯Ž_àù,#®àþV2¤u<êÜè¾Ì(£Þ*ùá4qQïáȹ¯9(¢Q¥©gX£‡\¤TÔ¾e’:7%䜾JÛ¬ÑµŠ®Æ ¿$pÁgÖi£Š}ÇÒ| !´ ÝŽ.œ¢Ç’ 2þRÎ"ëš{s…  Bp›/ŠIæ@=nˆ/yc'_ !îÌQLPÉ`9ØuÖ(ëôyä‹ÌÓ² íRÓ£¶ÂK¡‡º'­É $UX˜4¬² bZG¡I4eù’é¤~ºÓ€ÞÀ`-ì:>NUo×Á&”i.tz¬QîÊèR_ÉçF vi¼áÑv =EPèqÎïå;:;½0MÄèf˜_‘ƒ²HE)¡‹®6gYeOúÂõb›¹ÓiR7!š®–æ%  ¢«öÜ–æ-È>†$’ÏÔ$qSñ_­a¿Óý€ÅÖçN–ŠÀ‚ïÓì‡07 80Pƒô({é!' tSÁ’€04 (³°d $<0ŸÐ™ÐQ4F¢|)·oNp4Ã…ÂX…8ϼÀ¢pG!?¸ÿþÏ«ã¯G„Þ$‚"ˆ‚]Í?& Pçåô^ó•ìçßú_™í¾oNÞÅ;  @@!€Ç]ß=Cµ37z¹¥´ rgÆ `ÅV³UÌ•¯ƒVC tZlj!Ö¦‰¬¸ªjÖ¨Õk¸˜Æ¶5MËÈœ|»Šwl—œŠ©«ilªÂ_-±›^͖؈]·[Z]m˜-Jɬ¢•qrÞÕvêY¶¬[¸¦··šVe‰m‰•*Z3eõ¡j6¦.Þa÷X‰V‡(Œ’1ÑW—Jù#"Èÿ}?Òù¿³Ç¿h 뻹¼¡í)®Æ/P;¨Ë‰ýÀŸgü²þ<¥Üü0i!c˜z,ƒK4&› »Ëï•%˜eqR1â „¥ QÝ’±ÞbˆAæZ8¹D=¨éxÏQˉUÝëwüé™™ç[ÒŸî"ýãü£ûâ1‰N©‡ï ±0æ|>ÿ¼ù“—áóøy’Œ†äá…ÉŒÛ?·”ÙF!¯`›W,;·v;¾Ídc!çÓOYè8-Ô£¹è(² j{2뀣4ô‹ùc $ƒ…x?¾MŽADŠ8Üt‡B—ðƒÞ¬¥Š1‡ÚNƒ8•´¡Â͈ $‚‹éõæ5U^a£—T·] ½ñSK Žã”>·ùùàýïmÚò®™Ž–Ž ªC ·a¨?îL,8)À¡ò %$bÓdÊËòNÍ)û@²ðïYZËÂäáÊq\Ìž‰!a ¾1òöÚ¹M.SÉlåÇCð’9x> ~xcƒŠ0T¹V¿è„‡DŠuóÑËoáOÂNɶ9 2ñÜ»> b`®m…Y{SäIe²Œ1°L’¨å) Øx¨âÕ &œ)ÁÕ8ýˆv%œTÈ)FT–~eéå–ëØwb”°ŽÐÞaÈ ì±ƒ´dèÁ€ðb:RްTÂÉE?î~¹kc+vï2ïÚÄMÿ¬[=&ûS‹ÑìT¢NÇ“yo&IƃNRÂã?Ç¢†1øh© Nid©»fžÉŒÁP8*íÑ…Ì%<’T_…!o@a)9¥9z‹n4ÌÆ ð8åRXœML,Ü•š²E5È¢K(â5$Ca`µahò:†-—·¥˜9'À>M8ðYe˜ulrG•œ‚ i —IúsÈ\_Zê––ha,9áX§l]™#SÁ ÌmóK¼<Ó±Du8s.O@Œ¾›‹ÌÎÝׯåK]tÑæ<¹Ä¡õ‚#T°¡X«(V½g™†šã˜ª5‹ck9‘²z¼ 3hÉÑÉ…^Ø%§ RÆb08j&…1r9MC:=ú;‡F8ì6«™°*Ì’Ýñ ¼hÑtâŒÃ\·gJá vL(UšòÄ(Èõ2\òG"G’˜±äÐ4ÅçgQÓ©n0罃v 8´]Ñ,9…F?PBO)qÞPðå(¸àžN,˜g$Àéú•¨êÙu® ™ØZnì)Q›÷3¦ôaÃSŒèªHÑ׺0\á…\¬ ¦ò³šN©(s$¢‚ÌcÙŧÑðˆ‘D—ú¤i«z4¢ð}^†äè ¡*1‘et\ œ衧ÒD‹ƒŽ__ÁÍ‚ð5ÝŽØe "hC ‡胭2ZÕJ Æç0‘‘7—l Æ Y±œbŒ\S…id„Y!{-¢‰V¹*p²˜Á‘ûÔ(²MàÙ‡Cn3|ZRœI>OV0á ”€Ç^v9ht¤rßZ±Ösµ[YÓÒóå~L„ÔFÏ‚ìçDÇpÇØA[lŠ€u62(’#AÂG½87 ¼ƒ N¯aq\©÷³X^EÀÇźìfšræfÈæZJ£ŽBÀ:¥b¨1•Уƒ$®ü$=Z¹Fƒ F¯ ²ˆŽA„Ìò`‚A:] ·d½o\na=CšüáYÚ<šhúãˆÅ*ÑNc«*ƒ)N(KPÄ!¤öc FÒY]œrRÌ9ÊGE!:) x²ad¡hÚn…[’QNîºjÖ°Àè=ŽŒ“g&©]s¬k¨»W—¹WÊ[H$¯¹¨å„âD{4>ˆ>C»27Ù'£áBÏ›–MÇl¼[(QJFõ›† ï”:˜ÃM šâµ|–9@Êr³Šež2pG Å°µ)ÇI#œãÉbqEœ&BE‰a99È8Κp£^ßÐõWè`ÄX¶Þ—ÍÞË)?è„H›·¯2t]^A'´}WS¹PH#>slï:äâ7¶è­:-N‹‚⃎›œ‚¡Cz5‰åï9…4Þ«B½>˜@;Þ#¢ðÞpØä¨Ã‹%Ò¼´ŸZaÅ9ÆÕ)‹S;Ÿ–¥ü‡qaæD´GG[s“CÉÀv4Ô‰)G r©—̺5ÙNÈÊ’FêKKN«áòIÝ‹Ù.Ð¥äZB(7|/¥¢‡7dÀêp©8áš.̱"¡Vì¦éAd*r»àH‡Y„„\tP¥øTt;Ù˜µz1'^É8qNº´ayÂI³ì¾-®¼,£Š”9dvC dc J5ÔX è²ê¸=.¥Hn¥b c/ß2@Àç˜lñN²NÅ÷áÔ6+°KÆ)=¼ƒÊe…JÑGLÐTå‹Å‚n‹Û¼a6ì„f#¶Ô\$3±°…“éÇ¡Fz…î6Î䃦ÁŒ Öå¦Qn€Î†]å¬äãÉ¡!aÅ“‰ Ç(i³€¯H8¤=P¬î©Ê¿†(¾[¢–jIÂCRKdpƒÐš*" ›2b¤clÛ=lü˜{9F#q4Wë€Ö¯L:1d옙XôHÞ]M©m4ÁFŠåz‡æÜiÌùÌÓ¡—³¡Âº+”A²-–Ñç ln ¶(µ ´8ä¯1õ…†b‰!aÍ]Fô±ÞMm+EZ;Ï “¬mJtûïDDö¦œ%Î:ïhÎ<Ú“N_T <øm|# iÑѱÁI„x{ÒæÃœ=žÁI®.啕+  -`r‹ðaTÁÈP`ˆŸ'ƒÖ\3óg^ænÆ k#lÝ$IG5’˘q¤´¶'g²±×J<Ó(àÇ éáèS¬îp%ÏÑO: <ÞùÂelmFÀ’\tè—É­RÇq$£JËÙ Ûô·RzíJ:÷Ô8¾Ôç¡}e¨´ é Áヌ/ƒå‹.K ¤“Ï\;¼‚ìÌ4ÛS1º,l¦§’§&\XG#… Q5ƒÏ`¹d 1Š X¡#7søà7˜1@J-‰P[ ŸcKÇûHÿ¦’fŽGúœ¬ŒTAAN¿×|0“±ÁÀsXaÆ áûHE: ý¡Vu„„¥žˆ0±ÁJ°¢(QAË$'ý»÷9BŸµu"Í)B í  ¡$³EPÀ¡ƒ È0’Ì8Iþn¢”I•- ˆÁúù‚Fÿ'#¦óƒõ|Ä>g¯ÿÍð]äO啹 o.wÒDâí[êeäÐscÔÆ­U*Õ§ž¦%7õ5=ÝU“+U{9‰k *ÓFC°ò¹8Ñ«£ÄMÎXôÍ.ÛÐЯqv+Í-@òÌLÓ¾ÙbîÃCä+L­,³Ä­[7èûuoÁåaqZ VØØš §å¢ìJVcÌÕj¼^°°N[m˜°Nê¨ØèµwŸøÿÿì"{|ÓçèDax­Úòi sv°†3 ~¦K¯ (E;„| (ÓK $RÆ,„Œv™v©Ù–Zkѯæs1¦oŸ9†Å´¯]soT8Ο>H[Öæ÷9{ÜJ^=ZõÝ©ÞîîÛxýÈŠŠ¿íLÌÏ9Þáé?Â~EPQë±q|lIÚ®:uì:ò5…5œÏŒ4 hí=ý:qo—úŽ éôãÑAá?‘JF0ÉÊÂ,cònŸb¨’†bÃQBLqÕSxc«3XRsh’‚nl˜QC$jÈã&lPǨ Ø›BH•4{t³¢(kÇx0±C à–Œš0Êd89Ã]0:9Õ—¼`®–QÞ¡v&)²aäþ}¯ÂíúþùËÒ¹xLx(ç-® yð8UYÛ}ӭоBAÙÙ0„SQgL™)C.`.ÈCŠM@Õ$ï.Òj`‰«¥-(‡+…`Ä`ññ)¦Ï¡èsѽ9e…n¨ä›Ý˜(ãÉ$g&ašÑL%q+Œ6HUùJv!D]ŠFOvuzIK;Ž4šËÂŒ";[o 2CÊF atSzŠêE<ÉþàÂ9[Òiàr©ªü:££·K £5|bSƒ-‹I"sx&xhÖ“Îi7ªDÑ9°Wdô>úU‹#r•ß¶m^±QõI¿W×êuðY'œè÷§ÉëØçÐv1£Ï¾F'ƒ–%EuÎÜi,Äp£³ê4ÀÛ4’ y¦&¸¤h¡œåâÕpbÍÔ _EunJ–Æm~…4y( ƒ½H™ižˆ=9g(VVó.}öuJvB)‹">s‰½uÕËÓ¢Šk Z:àïè«E©3 Üß‹ŽÈsMJU`ua»%s0Þ-œ(¥[%äÅQûÌÃc§á­êŒKs·ì E®ë{®´¡F/þ2Ç~;fvgc/+Œ÷jäÓÛÌ}@û'®U›}u!'lã‹—ôyï…_Ðu#cAÙ³´ÒR –”$ÓA=,w <BOÈx1¥-Ë Úzä°(½Iчš)b‹à§L§ í‰Ðê;]“O ¿@ço~)êMÒ»‹CÇ4€RíÝvŽ—AL 6¨ªX¸«¡‚§ˆþ iÚ¯èÓ¿íX _ ³zo‹—›…ômÑ qrݱÆ0±ºÎƒK¾u…R÷†¤q cŽ4Ù£„ Žý;ä£çWWo¼{ŠV¼³àSà„èô9ÂAƒ0Ï>º•ìÝf±×>(¡o}YÒOgmÁDî{ᥠÅ7¥ oRbòÉ•öÅéÖÆá+͘wì/“Ó—IÉ"_Šh²öã*Á¨bmîÆ¹}‚e$«QìƒÂ‡"‰ÌÉ·±‰VC©F¶Á…‚Õ‹„C Ñ–RÙ6´Ä(Ù„s©g–¾I Á… Ɔ]G$¢$I Œ{¥;’ÃdäŒwT¼.ìirgºÏþ’‘Žë;*Ùä´²òqm+ቈ ¿CДŽhÉphøŽBN°6 IoB¬¸£eðÁXQRŸ½µç…Újˆ åI*-,…,eº#jêÇY¶G¾™˜’FÓ¦0‘‰$~3I#ªg QÊb‚…«s…hI¼G4®EK'¬Á·,¡­Jå_HÂqè&:ˆ(ÀTѪâ†s¬’åytÙ;FšÉ"1³ˆù€I‡5MÿŒI3ªë§–Wºâ×Të yÁASθ]®ªœR±ÍšŠÂ˜¹á¡w49&‹‹ŠŠ‹¸™Ú¢$*ðax3Pæ o .¥™p‚áŒ.CmIJ…ä €4-ÁÔ‡x娸×|rE'I’ˆ²Ñ˜Âˆ[4·Ùd–¤¡e7J$±Å{/Ÿ%G6 ™ßƒ«ƒ²µZ ñÇßgiG’š‹cGW×Dniy6)§E£>â+ŽXåŠI$rHá!C³ ¦9<ÂðûüL­*œãoYéz·Å,·ûk%êçjIÅö ?_å˜ JÙÆOŽà&Ë,y8h Ù'Å*&ŽY§(~Bاd¿¢v“ˆîÆéC,éGðÇà`*oYM5ßN«ƒ–bQc7ZJc±#,tû×¢@ÂŽ¯°i6î¡R“§ ×$ꔜ¡˜µí™Åb¯À8ŠÇd˜c@9wDŽIнQËg0ni/t&h½)×BéÀ… TìS¼AŽøO}$(èáE#Þ]ÿªèaGCŒ@((®" º*­v‘É+*UÊp…ûÌȈŸ“x'³S„d|üÙ^ñx6O‰Æ 6Q­©B£+¾a·ÂMµ8§ UF±Zpb8(¤äO *ÏµŠ²¤ ‡Oâ£b·e%Hq™­öG0Q!RøKP²:ˆ²Zspì 1[•£ŒPÄîÑÍår!’ qób)ËÌ’Çï劤lð5ùFôy¹Gv.qŽ£¢:·¶èããy1¤§ÿ=@=B³t¯Úž`õ]l;·+(;³øÿ'ݼé8u×~bÉ,°h³ÓÉŠþ¾TôpŒ3QÇJße %,„Â|å„aƒ¸ü™4á<ä˜Xk 9%ýø/ ÔÔ£§§ë00$c‡Fˆ18=ØYË¢ˆQß ƒ”8‡±HÁôÔR ¥à˜Ñ-cœ;0±ø:s•ªÉluŠF1í¼!|¼»Z~Þ ú;œ4ƒ8)~ʃºPêûϕ߻¢Ž¤ŠAŠÄYÁ\ÁT„œQ« s—šö?tzŽÝ›¨EàÌ󃩓¡Èkû‚Ë’3'Å(¡CÓ꺬kôä£ çÓn(¢ËGy|œ[W‰Ñ†Gzظ¢#g‡ÂPé©¢„Ð×N Ì@’©ÁC²¯ôE@Ý«â”p4í ’ð~éÈF—4Õv7ŽDV^æ’®«„iFI`¬•Œb]|EzÒêß,ZyW»ÈJ"ÈÙ¥ Îaœ qÆPw*Þœ²ÊUaA•$¨4©«"£šôˆÆa! Ô4‚–RàéÇ!T,¶9Š}ŽRÑþæƒc[ø–‡ü?õ%žþXoÈÄû>Õì©ÎØ£à±Ï¢Ï“ “Ÿå’§uTC¾øCŒ Š)ô³}…$8z”èêñ PѾ­0pDMš!†ï`øàšL:”5 b ó}‚"!`ÔPäÚ„ Þ×3—ì=o/ú6º`yàÌ3øežÿ|GØØÀåçñó—?Ü 4 ‚òÆÄ „‘  R‚š ±^^áÿ1Ä 4›[8$Ä郗)ø±$!+ÅXŸ ÷}¿kô0) ±M_rQyŒa$ƒ+ÓÛv?krøž\t‚ÃQ\Ÿú¯i(S)U 4zcv™ž2¢@‰ 1%œƒmhy™^¹ ƒ•áÌCe¹z/¶lwKfM¨´ŽÂFˆ¼N;7Šw:Êz†HŽ …Ÿ<‹–èê]•%uQ×UÕ™Ž;KÆoó/÷~žu¢öÌâg‡¨x°.VYCñ\kŒ¾ÖRöO‚,a¿U˳¶ä(1(<­  UQñ¿ß_èmÞÅG&W®ï`µ?U Ïát‘Ïw1ùêE´Ç‡AÇjw1Ûá[Æ¢–Ç•¥¥®ì ˆ‚È„|‚a|êã>Xû?¤ïZ‰{Mâªû·äBÖð¼-Å”ø~ùø‘íz˜ù=GrOWS¯M÷¶üÂp–Ÿ×ܘ¾/b¥«Çsß¶¯~ÅíÈ¥g_ıÞ:23²‚êž»íåmoíí¾¥½ypñ[¼Ôoú>º|Þœ&ôöbOw…F©Þvüã:¼_ÁSÑÓ@¡7O$“.è«Dc„}:`çm>æ>«Îš/ÈdƒbÉ[fV]NÆUXé·ô^çò4Áî·ï_kòqÉãïãûsׄé{ß„) BŒŸãûSŠ«ëŸÝ¢;ôÔtß Bïö#⨖Ù?1÷s“©ЦÔögÏù¿S ß:%´88¦ýÏH§ÌRÌd°¿iîK˜(‰e `"¢-J ×,‘%ÉX&¯.8 _Ù}¬{ƒŸi>ßx·\ø^ãåjÂ_ÉšbGï××—Î:Iâ•øj=úV?f>dð'úy.ÐkíÓŸ6+º¶«L- ¬‹lÚZ¸ý ¨È ŠÜ PCif€‰È ê>Ê*üÜ\}—ª¶×ôí°.i9ÜŠ¥(4ý9ò§çÝ÷׎sïýü’sÕ¸™âõÈ í»#3ê€-àkl¯Úƒì¢Zo2z Éß t¶î2.¹K#MÖ9ÚíÀQˆ¿ iÚÊú@¥ò©E¢Û«…Ú¿hx#)l¬Òš2‹ÇÉ]Z¯ÏX7PC.6Z­wõb½&3d¡ôA “ô7 Ä—¦àÊ$¹TÃi5T:/"§IuË+ñP­sÐ`Ú ({¡u“Kj"}WŒÊßšøÝ*b\<–[oÕ^,‹W*XíM"ÓÚû® &æ8]zl9uÆ.ÇUÌ÷°¶á’Ö8†É)Yè´Ûn––•È7‹r^ÚÌV2Âg-0|µÚ¾HT³ÒØZžŒkhŠ‹4p½´…ÑdôÛdç EÚLž5¿Ró2fÖŠØe°ʆǪ̀1Ân:z‚— É€,ëái³§X³ç¿v›,wr,·"º™~3‹Ë»Ó™±²ÈÖ*YÖ†‰¡Ž{n°Qr“8[³:v†Í2‚Xm]÷Ñ¢ð¥N£( sžÆfFÔ.,Œ‚»?bÆÎ„˽·ÊÁ,-Z–—o-iÝÑÄ!‚«³nö2i¸µ±°–2czãº3"ÐÀÂÜù+cbrï+„ëVî.‹ðÊ­ \kb¸FuGÑÚmVص`jžm¨<×1Íó<ÖÉðãcMÛp¬…¡®ÖÜ6ßm-É.²ŠE1ãXÒJ5˜è}M”BlphÏkë†S5ç²]Öêq ëbq›ëZúœpk³VÒÚTžÉ©‡Ó1”® ±ÑØÛ<6A†jòóó¦DËvêürmñìK2­Z®fSó¾çS£³ÜTw=(@D@ç¾SJ)#ãaÞžv[æBÒó£™F(ÅKââ&XÀ0žu;§l0Ö;0S\Sk1«äñ  ¤J|Ò“`€j£ÁNrÕFZbPs¥5?=ˆtºèmG$à!¬÷¸+©'+”'åõq8p,#r‰x#ögAÀIäÃÙÑy¢”Ÿ!?O•=Ì£±~b ]q±<É<ÐñŽ¿s–Öòõ¢“¿Q§™"žPq±äßR dò‚Q5¿Ø½ Œ]¦Ý-È9b·,¶—Àl­`žAõ‰3Šã©Jq23«EIˆCÓƒ±GF6Cð@tAHå¢Í¢¦äõ½­Z¨Ð@ÒFÑ Õ&àHà@ù[ÖÚŠ¢º4eóZƒâÁ…M×Ö‚ònG2AåÈÅ9f6Ú_Zª^ry$N$žIÔ¼ÑÄ¢äÈíËL§¯·ô¥0šIr è.0¸’±yâpaȆ§DOw-¥¶[IèaÁ ˜Å"f-ÀÑ€Æ=bÄԹФüèŽw¡rCfqë¦Øi¥*z ðN`åm-¶Ð4s,ð: ò êÈhÈV¶hèd‡ð u9â–Ùm’Û;¢âHnRÛìÒðhü°ŸƒNò…´-¥¶Ûm-¡mö0Ì¥´¶À¶–ÑKm¶[b«imÐC2ùwq&Ú[|„GD7nõŒ‡¤É 0É $#¯ éf»ÒèM˜…Åø~ rNGÌOAñâËhe–Ù-°œ>VC¥a³Ûg}Ø[{fY-¥´¶ÛBÚ[BÚKh[Ki-¡m–ж–Ø[e´’yFH)4lI»`y ²”›´¶–ÒÚ[dà„œˆMaïg¹›z½›,о ªü0àÜ$yrÌÌë#PG)m-²Ù'"fRÚt9”‘BÚV6É:tíÁ̶ÒÚ[Kim-¥´¶Ì„#™øòNÇw3¡Ý¥´¶Ãþ´v'<-0pNãD“·F÷z¬Ãp$:aÜí1|çx@yjD}Ðz “Ü‚õÍé^1;Ô› .Ä×[°í b”Ò]ÓUC"Ù ºVÆ=Œå DH D<íë ½åÌO4Í“ÍG •bûRa£Ëi’³B;IRK’“ˆÎ[»¡0ò <©A¾b†ìäéÈ‚g4冤ܲ3R d^Øi€ˆ{ §ªlohiܨ¢’Ú)C SÅ~.¿oBp$æQ"t]$±fAoªŠª €— F!§V«mGUÜ ÏÑO”i–!®ø6³lvµ¾¾o:4P\ˆ!!ÒOÆÀ®@aú ˜‡2ÛhÙ,) ,¢Êe\%,…L—Mʆo6®UHˆ†à‘€¢‰hZÑÑ`tö´Ý`LmâÌñLhqæ.®¸[¼—^ÇÕZ¼f;Þxªtªu|#»Œ=6=^ï"~§:èóÏÚ4OcE´{¥uôB‹ñ/Íýˆyó»ÝÌÎþx©Ã4¶Û€âxJÃ9Ò§õ+ª¨½Ý9ü\¡ä"ŒC ér0·!zQÒ…ƒ ]ÒŽš ‚¦ ’Ed×]tÓÖ6õûâ©é·×n’BŽxsüò…Ÿpð¨~®P cÛž¤CY“ƒ9À0O´[(L!!>†¾¹óܺXdà ö'éw)·ß~gö¾WèýOÿ/ü}½?÷÷¾Gî¾èÿ“oÉIJ‰bš†%‘¡¡‚iZiî@0 ¾MÈ“ü¥†âý)C$ùµ¸H|ûöð.úßÓ °L¿¥Ša#+¢Pˆ}XO˜Hœà% Úl@ì”$}<´dÌ { §ž ‚xR*£ï§º;¬©D~r Bm¤ýÁ$Ö©4E.”@"ŠDµ@I´ÄR‚Rˆm]4ÈH¦º|IdRÎE'tE11ä# ¿£ÈM˜ ‰¤¢Hf€‰F…*ZAK(¤v=ãÏÛßÕF¿eŸ}ïáÕSH JAr{VéäJÓcOrôeŸ—ÅéÜäÎ8môõhNpÁ]è6Rº6ééEB±‡§ÑWtáB zâÔTuˤ"báÜŧ““g¸ø¼ ǘiÎË·²ˆ¨÷ÒQ(ä„9XŠŽ Ç Cà )!&–b‚@™T–& ¤°ûêmü4`XPʼn€• ‚a ‰ZÙbY,¥ÊQW0UÇ bhŒPÈ J¡%¤ Yp RHŒfC$IZÄ\•iV‘h±‚U0@…X3)É 0À" "ƒ !*Z"I—€qpb„2\‚ÆÄH‘(ÌÀ¬Ìd‹¢aWd´’,BÒ‘‚6ШÐU,`¥aj$d£`[F6Â4¥¬YjV£+T¶Ø¶À¤@ƒlˆJ¹ƒ‹Ž3$LQ€‚KBà²àŒ°¬ƒ"àBJ8`(ኘ¡$¡0Ó@T¥DRй…I0Ù’D´´ M%X‰Ž#"b.8‘‚¹¦+‘„¦2A–ˆ| ñÝDðøúø²yÌ»¸ÛëQßö|@ñÕí÷™ªÛÐs­ùQÑÙLb½#äÒ ÆÆ Smâ6NSºxØ -xÐU3FÜŒ ¡<\óî€ÊÉï»÷(ËÌHx°3_XMØ÷Ù?–÷ž.3'3}Ú`ªù½zwî·÷wz·o^"åœn¼’¦ˆÄ&=Mý7ísö7Py9kž±f+xJ(ñ^L´'$U3Å=‹®êíÐõ¹¿«ø¿o·÷ç÷öO\N€Sº}4R E‚¤R@u@©ûqÇñ"˜‹ÉGàeóÑLè¥<ÚL2ÁT‘KŠŸ`áƒAJyç*‹#øãu¢›ûבÌU )õ‘M¤6ÔP [ xÂ`’-40”­4…Ä AM S$BPø»N{¼B:* á´R³V¥Uã•gL¦ª¶À]ÑLE=tS˜¯J)¥@ R"ªªª"ªªªªªªªªªªªª¦jªªªªªfªªªªªª¡UUUUUUUUUUU"ªªªªªªªªªªE R""ªªª¢*ªªJ*UUUUUUUUUUUUZªªª©IIFQŠ0>ª)•ȤB‘MÌ–©KsŒŠcg9ç“F£ž|S}UZè,BŸŸý~ÖQA6"¨†RrÌ T:ôb Â)Øœ‡ç¢›àºŠ'ÀÊ *‰èôb7œÖ‚$3Ð8Îø9Û+A N5&)‘¢x÷ÁP)D,(ä o*¥EA¸€)¨xkJX· .4û1¡öf­WV–¡¡VÚ\m(¹-lH±jiÄpÅ0øa0 ¹b»èáÃetñ#‡ÄÆŠrÎ}ÇEUJ±TÿŠL¯e0P§@ô¼ š :·ôj¤)døî˜æL™ð: G!Λ¼MÛX´j­b¤´¢~×¶…ÆÿÂÙq„VU§ö[³»˜F¸á™Dæe¬¼Æ*ŒÈŒ**¡ªÂŽÍ/NF¬9‹Y¹wL¶µÖ˜ô÷Îûë¡{¥B²¦yfNŽfK Z†Œˆz×xThkªº‡·¦VštA­+%k+ ˆKÚœàŽr2Éø~¿»=9½œïÏçÏ=s¾YêDŠ%¨½=¢O)ÄE85UTTÁS4Ä”UPÕ£(À)5UTTÁS4Ä”UPÕ"#>Dq=ÀÜE4E>$S¦Po"­jURÈİdPG‘”D1),›n§D8`à³+ €C0°pÒ0DR#ˆŠ}úk3"™ÑLˆ§§°’ûm<–¡®a’Ðÿžo]^}¡ …ðU€k¦„2fÕ2ÃQ¬UÅ¡•Ä¥RK Ã#‚Ë!m@BÛÒ"!v߸JuÂgØVÖß…¦5µmHÒ#J5KT*1-…•,cRÙï·¡Ü Y·ÂâÀe´²­ÉŠ˜QÆ¡’Æ,b*+äeÅÐ`ÒÙCifKØHmXdÙŒc*ªÂƒ>÷ý^ïòw\®Oâòƒcl¿KGt7Åêg¾@;¥ñÔ*H@âe†òù[¿Ðòžwáxï¡ûû¬¼WÙïs„N_÷÷¯¯Ï DÛ D ?uÄo;íw¾P†Ê¡H<ÚÊ0 D»O{ô'ˆöŸÝí8?íxEý¯Îïüh/îÿõngú¹þ—â嵟;1>@GËE Â)!"’))×#·ùy¡R†‹H"¾ßV”;é?ZšP…HÑm Z8/+ÚÅa M´S‘wo*„ñ ý2½áRîüðXÖAùg€%Óé óžüz²ˆ˜Š~S@§ÎH¨ùl“ÿvrÀ~\ ØýH}EÕ‡àÑ.Î?ƒSÃaAÁEQˆ* A ïžè˜Üó2Š‚ékÅ¡Úü„O˜ï ŽyùÇüÿ<{Gzœ9>ºëF.ÙÛ¥ÜÁ}ÿ'"ÌöZù’éþ|PuÂ)Þ‚œ)M‰Ö><$=†%}‡¸c‹±où¿Kü8¬$÷–!¦Ãœ±ý ÑUbÇŸ °ÂE2nüCÊYŽ^æ'ãL~¾,TöxúmÝqÏ0ô–NÜ7\–‘/6.'¼­ÏÎô%}ð>»—RiÀ1=úD@R#%;w~,þüw~ü»îg­¹þ=§É·Òp(ÈôÎ ƒ‹ŸoMb3ìW›fW­,¢}oêq‡¢y¡¥QPdSÀ…B’ õ+S•Ô+©iöG}¥oÐ(à·ËsZ§‰%¼N&œoÇs¤æßìà©ênþþ×ñ~iâ|ÑÚõDöó–qõÑOŠ,=ž'Ôóý*ªÖù:a÷Ã`þTý€àýî<«ZÆmh¦À)J ¯Ãøã“dÊ6Þ¡µï©¼Ù9!þø°E?£Ø1$QD0ÀA!‚Ÿmg²}OBè\ö(ÜqØŸ¼¸µÙªm ° $•$ª”V¾Ù½ìã¬V8úêfÒ?ÙÏ7yÂëŽDAww%Y²/ú¥ÿV¿Ê‹þ‚¡þö¨æ`óDê½s þÅi raäE ¤œ‘íd<¡<΢‘6 œÏ ²%,æÝ}Ní¤ d”Ê#mF+YôO¸ ev?BoQÙp8œþ³äÿÖ㢹ØÐƒŸÖº'ÍÀ“Ћ¯Ã똷‚QFü?säÀ¿ÑÁ@¥.Ò)n.çdʲ|x‘TŒÊm„¨Ã¹Om·áÃç|J=³Ï'U¾\,[â…9ê«ËÀøpºb,Âcçñ—XÂ{»‹6&S2Ç¡Gùº?åSú¯^œJÔØ™—?Ö'çJ•,4ÅÏ¿å-‚§ÄÌãÂÐçÈßþn¨ç Í0vw­²z‹›ä’O|2eüM˜¼{ò&h%ZÙ]á;Û±7=2ì¹Ã+“Î9å¬ìú#ËI= k°±íOrfŽÿ®àbz¢ŸÙX/ãÇΞ©³òþL?¹âÆQŠ«Á£5ÍÑÅIè¹y.­vj¯¹ÛìÒˆþÆf›‚îf›‚ŸWï%¼çX\êИ^SURVDSÝE;ûÖ5LLtõÔSÏAOU)âîPøÜ¶ß‚O¾¥ï à mqŸ¼Š~vÂãòèî<Ÿ|Öµš:·=éÖü2ĸõ`ÈoÍË›Îý¯èß3ÿ§Ê¯¶’8%5Eº’(ª3©åp!~ðAøŽû0õ哚`Uª:-bäh?Bšµ?öÙ‡}¯eí‚’ 2"#ùØH<÷­èM®¶¬ú}QLùȧ‘NÕÄ`$`WÝlöÎöCÖµc$Ó[¤žà—/m €t(航ª û¡UU_M9Á hT›Šæ¯>žq@¦ Š#¹áö2„ÇY,_®šЊm¨È‚ŸW¨ií„Nä¨ùû¹÷ž…Ãøög›\s÷KõØ}·{6=y)6£ïÇÐÀ‘:‡œÊ´˜jí{’YôaãŠ'ßþÍz’Ö¤Qòp‚|YRKù‡‘¸äµŒ¯Ék«ð3-Äô÷dµT(ܯ]ìr_ÏÅö·äØiYELÆ÷œxÛÐaÝÅÑ‹";üéL‰82–=â *Å*ÈÊåUšJ‰…ÔÎ(múz¥acAßÁ2B–¥T*F‹cŽ6ý‘˜ßOólº½®çZÇI ¯ø¹¾Tý0‡BFžy$Ø( ‘»ÙœŽ¯ìÊЈýZÿ~z?f'üŸó·ý/¶ÃGã¨;H§ÞUþ5hqQT!("„ráÙ†êŸ_»€×cõ‹¶—Ø. ]ÁPŸjN:^Äé\í¡ÒúU妾G¥ ŠDD¤SúFE8`ˆb XÂ."”€DR(®AÅßòå>kðm–~ñb¨Ì6~kуêˆ)àòd&µ ‚Ëôùh§Íò·ÐÉa?òù›G xUA[RnÝÞú¹ÄYäìr  «y1Š}õg?+Ù}û=dâ—×ùTvçÌ~"?HØ‚Tø·sÚÄËùTÇþ©ðYW«ÑGÅ}e=ns|õÙåî<.áñd„„’$ÙÓð‚o©O˜ÏE»¤'½ÃŽ'õ #îÔæ:×8¡‡Ðx-º„χÍÙI¶ÍÈ-TP^,'£ BŒþ“M‚@GšÚñü3fRí‡ÆgÏ·ð˜?o"rµýÌ쾯½V·(åö  CØr‹¹×<ê5Uê‘-ê™6j~"#€älü=GÅ÷ÕDÁû°DüðDçШ‚–Ì`o)÷#¸ùÿu…ÌñT;™¬)Ç??Û¤ü“ìsQUõÑó0>öŽE  ƒeÑßÃ8 Í[¾{”sœç>ù™8U(¢ª¢¢?Ùø ¦ ¢ˆÈÉ4‘™G3Åâ19B9ŠélÝð8>ûUÅ÷Ž‹ü_"y[¼g½ËØæ¾žòpÿðÿîúØtñz–zp‡¤>{HÑ$@¥Ö8ý§ LIÀœŒ~€Ÿò€l¯÷n³ª Šh$¥——¹ô|Ý~ÕíµÑÐ=§ žyçžIäœ%” äë‰j O‹1Š$4-‹Ûvÿ ûSÿ éèÿéýÿî|ÕãQþåÒ;¢öÚ€ù ê  ¾¼\ ÍMnP}ÇðlÂóÿº¼à€uo¥8|ÀÈŠhQ¦ 'ÍŽýd{†ë†éÕûE,Ì_cÔ».Aˆ˜{!µ¡ iÛ‹ ’Õàéƒ9®91»PŒikG w6wqÞO(H—%¯ýa¸ëºÚZî½ï E?ª×¾1Æç9×C÷OÿOÉÛ¡žpu|Š ãEÝ5*å)®”v9£ùð¹¬P?£Ž1‹«ôÍÞ׭ǹþ‡i!„~d+ÆAJkå ¥ îÊõ¤ˆH=üÔ`Ã\?\ö*sìÉ`ùzÂI>ÕŽc'Ú°~<1RâV—Ë£:}:4½ú¼Øðßvrs™&œISï‰Ó±÷øÑ¨w8·õ[«%ï{Ú¨µóçÓ«`ì&f^ý·H X…ɖЩ¿Q¦GP=ò;}ôù’ñŸÊöñÍQÒöÞS¦úµ{¨'‰þWÿ‡èlàèÉ>”C“Ó ·âÇêviÆ8É=+ó`ýHÛú'°ó‹†cÃOˆýÕãÃE}ªÛŠ.¨$‚ ; ö" ý ¥a@Þ‘Yw› íúß3õqÿMtÓç¼ßíâpüu®L›TsÅ O&{@tóÓéCŽ$ÒAÚ½Tëe?{j"£¹€úaÐE'›ƒ^8BH§<£pEœÅЪ ¬œpzBžOÛðu‚&“ÿS~Gcƒ–Ïúü?¡ñ?ÃþþßÏSö–Æ÷ûH¥—Ôü S êÌqüj2]^—ýaO„Dý¨gö2ÜÂvl’†ÚÊÞ[ò>ÛÚõ53ê}ν¿“›'çèÔDØ l Ø Y…1ÔŸ—}–Yeae–Y,:ùª¨¸ ‚z€AäÊ j Â4 Ì~ù1E,ªÊ7¾_â(DhÖŠYQHŠz=Q9ŽÕ=¤û$þp U3@ ô¾~BÎÂ…¿Ô½&´Sl]*‚Ù’w¸ztØÀ?4A@!òUª VgS* DT‘}ë³Aðs÷¼ŽT6ªn„º¹td}.à|®Sßx7÷´—Úñ{ù’Ž8PVa™™eE·q–åÌ.4?Ã!þd‡íÿªíP¶¨­¶ÚÅkZѶjÛVÒ­ä…zí¹ô…Ú4@ýqÊáöðûxÛ;YfîýDMN@­$7º“›A€jš&‰ø‚X Ù6Æv}gðqÉ7ÔŸ¸‡Ë†èþÛpâ°©ßE8+‹“'Úø+Þ÷½šµ^øòñ~ÕFWÊJª,zà]4;ÈqÂCi…sƒ¤óÎ#š¦eG§†Oñ´‰Ï#|+ª7öcS˜âû/…ÅÈÁüt[ã<7e²¤L>oûn®½ÕñRú ?¥ìxø.ú Èü*…0Fò+Áb¢ÏÒÕ¡üšìC ‰õ<¸W³ 쟫þ‹ešÑù0L^O\«Cá¼Jþä‹`NПD{éñVAõ¯ßev]³œDtVȼÜ^ú NöGúl?øý]°SZóÿ¦øäŠujz: &Ì„yƒy¯Y“?J&kŸ:¼^m½^ýÄRXÂ_ ¼ß?Åô$'6(—¤g:øµV)ƒ}‹ß ðM$¯‹aŠ5¬il®ð«êTz"ƒ›åº yÞVØcK[ß‚°¾U“cfÕµ´6ŠÓåQö!ixtÇÝãKô?ñqòAúÿwö'²ýnÜ>ŠÊÇPí⪪­á湇7Kòÿ†wûwÊo¦û8ŸãÙªé¸'rhÎ~+d|ö,]Ÿƒà%Í_g°UvgyÄ‚ã“Å„™UUIQm‰mù òʸ,ÚtÆ0„J¸,a21'ÕÂ. RA+¦–Zh:“-0#¡KC&¤ TÎ^õ ¿OMÿ_ 7SÎ6€s¡Ê†Æ"¥·QKª.SB‹‰=T»‘þÞ:tƒ¡ºœ¶RïÓ¯Òöùú7ø}ÅbO•ñÄSÛékÉHÑjeƒD±ó žn—g«ÙÍž{_²‹Z›U£F4{Ù~§ÆATëÙ?cÁB"™Ï &–Šø1r•_5²ÚÜ"﫨¸EÓ.éz½Í}ë¶µ­g«EÛËõË¡U5"JDНøçämg÷’lQ€ñ~ÄÃÖa”\ç¯@‰º€,DP•ßÜé%Åsý‹?•ízÞ÷½ëbæõ«ÔbuBpŒ_o‚‹^³ó$Ÿ5V»ßÿw¬h×%5T=æÙviìç$Ô H€”€Õ(Е@ )@” Ð*´ 4Š€¥U (Ы@…"D 4¨U4Ò5IM554•TUDR5JU%RÐP´PPÒ©AICUTÒST”ÑMPQH@UT*P4¢(R•T%U5ER¬UUUTÒÕUHP*Ò””¥” IH©LB…4ªR*D4$$=5Ù= •ïSðCøž×=‹G<<ƒS„“>O:ÖkGãðµTDD\Tn2VK\ø¤ŠýÊ!Bîôtíïôö¿óÜMئ§Àó;(ß» Ü“‚ćΆûד…Ämn¿D„Íl6ùk^=n—7ó>Gõ¿{ýή^ÀGóžOuF‚¿£ò€¤S @º y§Æúj}çÁëY‚{.`S³ÝÚÐÈñd“¢¨+lÇYp¾oåh6½³Ù@˜eE=|Ày^?Ű÷G´e;b)‰½áÓŽïñ‘N(§êúœ7cÜcV~‘@~9´±ªž!€ û2IõÇ’fÃUjár]Ùuðо^öç–^j=uÝ+ƒœG®ô_'Çú¿/ôþuW6?—«ä÷ÜèÄýÖÄ›p&qÈt(ãÞâ€PKÔE83\ÃኣêÐj›Ý•Š–µ€ÞÓ¾¼‚‚3‡±gF®ö»:õë׳™=!H„ôP¸)™P ¡reôì{¨z© Ð»KðO&hpÿ£ôEæêyO'GK¦þû&LAqÀ£ìp¿ }ˆH¿/ñ+í¬bvß¡ô¾gÛâu§Ý =†LÚÃÛ? Á…­k}\‡×Qº…| ‚NV>½Î!V'emS~zr›4º¢OÖÀ©öÔíòÙž V—™°Be­`UT—‰ »\æ«Õ©Ì=ú?wóøþ/²ø5Ô×ë­øñDèþ÷÷‡ü•uªÚ7êÃ2ª¨¥4Xa‘T QAE"Fbæ¸(âªSòáþ1äAùzüÿºfZ •l6v·6·2ÍÊî-œDežëOsŽžƒ)óê«`e­Òoæw½OL¯ÉV«]Xu>û`ßuýô±9„)T'ù”mÅJ£(ÚÎ~Î@EúÔÔ>|;sèÚhѧߪ¡4hÀÂø}ÝËÜ×Ïk¶ÐÖ—W²öYMÇZ ë@·?µÖëû¹¾'j;?½ëÿ+ýÿÜárã‡ÝÑx€òW4˜›Ã³â*‚ß³; ÞT9ÎvbP¡ÝOî€ä{ÑQEUlrßÃ#Ú>L Æië1RÃêK`²ÿ·®ú<¶ðþ˜Dê<Ÿ€ E"?ÂÇ÷QOÝUÛQ"Dø°Åƒ×½Ÿz +%’†&m®ŽÔåû™²p ý¬?W–ü¹eË€×öKˆ'R£A´"ö¡Ø*”*ƒ 0)+² ÕÛ/5öLä÷A* ®EÇmÑã« >þÛ"þQû¹D긊wNJ o­Ä&‡ëèF:|¦©ü¿–‹ !îãKõfùsY™…‹©ÃéY¬ÐÖµ­• I‰|á [Y½EI8Sx @ÍŸÛÇ€AÙÚÚ½Á/FÜ>\>lsÀŠIé€X3G$iŸ65 ÷&›qñ›A¢mÜÈ£‹šŽGFeaè9‰È½ÉóÌ‘*šMKPTõ™û¬ëçöÛPÝÝ»¹Àh¹œÖ„Pòµ³Âúöe—p7Lömk£‰Í}œ:œ¯§è‚'i§ƒç4v(œ¢ï·8ºDŒ7£‡«Eÿ6ŸR újì¨T0Âr%ˆ#ïØsÇüßûý¿¿^e‰ÿ6 çÇÿ^èot¿Ÿû1Mïh"ZùAìö õ½! “¶Óôp?(óûoæRÕPmm!m’ÛÚ´-°-²J–Ò¡m l…¶@¶…´-²[a-¡m’ÛÛ%´…´•*m’ÚBÚ–ÂH)RT–Ò¶Ð%´-U [`[d iµ„¶Â[HUR~'’R¨Qó €nÄ‘!õ¼4¥£ögj  ù ŸE-Œ7Èhh·½(• žx»j |óä·x–ÝspÐkX¨›ƒ”õ”HOdlˆhÑ]è³Ô£îçȇDŽз¶Z—Þn¥5å†0pWÌR^%‘ õƒÌÉEZ‰UtRØ|׿f@¹\c^èçµ°€ð÷‡½Ï=^ç Vrñüƒ Eçx¥ªªª¶·;J}^·Ö¤§ú¸‡ò|zÊ~ÝSòH+óÍ¢Š(¢Š(¢Š(‘EQEQEQEQEQEQEQEhÂ(Õíâ¿ÖÆ?±†A¨:y˜qŽ»#Á cÎí±Ýl`GŽÒGá;áà~+øtã’²³ô÷Ï›÷]-ÜwÎ¡Õ PÓFG¨§Ï’2ßéù¿Ö§¦v‚ ¨‰¾nPO쾇?Qê2?âz7aß›¬Õ !ѾÅ9 äª{É7ÓìØçpöìø ¸†œ§ßx¯¨™:΀$áå¨KKZ’ÕV•0ßO†ÝLÌnoàüLÙ¬ö™2¾3sá!k°!I$ PwøˆÌëž¿ ÓU?²nïL»¾ëÜM:ÙwdjÆV'цœLZ +ÕxG»ÏC¥#(¥ˆ“¢Œ¢ÞÊF e Š[寇¶ò>{ìt»Ÿ«8vØO‡iö>¨ö¾ôú*ˆ)Ý÷C÷…C¨Qî"Ïl°†Pÿ:¨ñéñË)ÓöN+…ß\à $>®×k¡¸ lb‡ÆÚ¿°×káÆ@úÓ½TT%QoÉ“s~a†à ¸?G8R-Rûmµ·úö#à|üzz~ñ¼÷ø†å­JÖÕ­¥ã‰ŒbË«Çåö;ßÿ!MC ”Ýåˆ":b€'ÈÌ ›š?—Üå¼>·»ë;žƒñhqçü·zw !B4éýÁñQI|ÙOçCìd£DC1Cêv;ÚÄ‘­•ªÜ¸åhµÀý‡øŸjïÖŸüŸ›öÖ«_Š?‹ÙÖæ{›BQU¶Û*ûóOäxvó²w4wؤcÆ1’"Ž­€0,XÉ,@äv_^À3NÀŽ)MÔR¤e°9Pˆ¾sØ2(õùÝÛ>·?Ñým“½¦.Ï`§åð@±;þ7“ï{^wë‚–±ÿÙù+øÓ·ôB#Ñž®‘\®A2ÝÏ{þ{Ý~¿çêÿ Ÿü° D.ìQGUZCò7.@£s ,Yi äûØÏÁÊ SøÈ¥ÅÇöß©tKòóoØö¨Íé~7ÌÿýÊ›ÿd0 CáŒsi¦Àlm•bÅ‹`X”¥Ä #Á-(ˆˆÚTˆ…aF,¶Å”d¨(ŠÅi)‰ˆš¤ÌÅ¥  B›i´O½_G+—¾n—Wä¤."1‹cDä ÷r½<ÈŽÚ›t'õÆ`iðOmÖ=é;èð#ªNd¤ÉæÒÛÉnFé裩Ú¿„ý—½ÁÙpt9Jü“k€PAu›Ÿ5ºh>6û·pÝ_f¨ˆAià;Êïêä/éü¡ŸyZqø|þ£Ù¿åp Ê´A H/ÿÚ¯é»^„äÕ…¥L‘/ÙÉß½ùND2 êHNÏ.OÓÌm^в¦0SÊ™bËÌ\0ñOòÎþ@~ÿÎåx—ò¡ƒóÓ!„ À½©=BG’ƒŽ‰¶?yü:7ðýß>ˆÌ†_Ëz9gO[&îÖl í½ɉ>ÞØ~nKtÊ©"M„"1@4eæêcoîÑÅi@cÔÉC³.8L.u`(Ædé’‹Fó¢¨o6á»ÔêXÀ†$êCœ‘ËcK- ‘3Ob 6wX6HNZÍ›–]„ÌÑo•êiH’H¡UÌã¹SKߣãr-L–Õ'®]”‰[€;îÞÄÝ:ü,¤*vk‡Î¤;)‚­°ã€dz%©DãyÒ ¹A@åëÉ—­zëâÙ9Ro@…13F¾  åÍ\Õ’9S€¢ªR-½’ɳ¥‘s’ `tµå&]’°1&ÙÊ'œüýíF ÒH„tä\®í(s¼``˜r×,^“j·÷ ;‘!<;ø›Bl;Û¶w$w fṸÓkh àuQ£3ÞÕmD`+†“N4é0Ú&.ß_kVÉöø…ED÷ìƒÙñÍÌS“º=^-P>?™GAÍ£ËZ…¶‹-U3zLš:Z`T WAÕÆh¨úúŸˆÍ½ØPuCÇ  AÂÃÂÃABAƒAAC )…ÆÇü_\àýž5å "Bu"îÈ@€XM„BÎcBŸqêûáìûù-â’ B©?(²¶||¿Ðwä86á@n93]ÄP7J(ØŠ, éú=dÃrM^êÝ<åÀOÐxO½ÊþTdfòÕCâ¼€v 3P~rÃHº‘Sô»í'I¾,Bÿ|b™c8Ì$ˆ’„4IŒ‘!01D±‡ø;漈)ƒä;ÏàŽØ|îe¸âùèpFCDfe˜ºg$UpaöO¤ÔæEBBYíâà†/¾?;æ¦Ûè;‘Ñ~ˆÓ™¾¾|+Îx.q*î¬+Óö<]Ý´$„ô<¿‘— úS‡a_íÃL;fè,ûanç„DýÍI&ú ¤|½[YdÙÜ:vg±»‘î6nÏ9U–úÝ—eÙ|ˆ)²ç† Nc6TÆ·‹ÝˆIPš&›ÆÉ49©ZOe¨Ó+œçÒ´·" ªg׿Aë‹W™Åß^ðÙâùmz*·©·õеߓñÚ«½ü|çtð±éôJvQ‚°—ïEÑÎ{4îCȉÃÔ ¤ˆo4¾3S“$;— vr|7pú)>EëûåžÌOÀÇgàÅ0ÿP|žšpkgrŽóŽxظNÏŠp½†;ž­z_C=<©Ëð£Ð§Ñg0ù'àïèQÅ;,ü9¿“ßlQ¹ƒÀÐ+†¥‘ì&ªRô9ÀòHþê% SîWÉÃäù> ³ („LRJ> (­>ÇÐLJÀ©Õ¯‡d$§ä¡ ?·ìø0QP6»p™]çêþ»áó²c>*üqbUûƒêmÃ]ù!MbúÏ~C& ’$– 6&ªáÝ5UáùëO}³l{¡¸ÏŸ¯_ÇãÎwß©¼šˆžæw~þ›ÏsQ;l”^ÁUpŠ©025²<«Lnšo¶!€¤%H‹=ôS¬P‰Fi™Ü¾ú6êryãºãÖ¿×Ú~T¿´ïë3³Ósó/ç]­g|ùòëÎßãÏ:rÐÈVø—Úz–‰Í2…¶ÖËC#o,áòàmª™8°›´|u¤¿c”´’É žwõú/Ÿ?ð¿¬o¤îcŸoÅyqúÁú|öÇÖÍå~²bJR=§ÜJ@dù ã ÌÈÕRy7äzcßPQù›˨÷ý÷{²î®îIVö;§6gmzç«ÀÜKÈw´W€†X‡©ìë$%º6üÚ=´òžXÖʬç5yœ9ñôQêè³ÒPî=-ø\¹Ì$9©ªJŽG.ïS²ðØo¼ U !UUU-T^ƒ×Å×çÌÌÌÌÌLjËÌÍÞȪJ|Œ9z÷AJÞ\*‰DAKAM_®ºÅ² ]ºàH+Ší‰™Ê·×åþÏûïÿÏÄö?ÿG½ý¸¿WåSü_«½í}Ýáñ`-œàÆK}ÿꊚ?Âõoóö70ü½P`I„A%€/©ÚHtbP åx×2Û’Cìÿæ¿àÎïú¾K)CïüºK >àÓ=KñGÍfl}bÅämöp|ïœ0¡Oø~ttYÐ M£pÈÕ?²Â…^‡–aIþüø+Š‹_Ýs($8: ÿgœ@á8YP‰°uÎ 0„;nYd˜&¾E3³’žJÒ³‚rši£ Ó cÒi˜hx0ÓxM=ýæîm„Þ:¯{ïÐ@Ðhf“YrÅÍ‚Œ dZ$ûQèY+ d“üª«$¢‡/î¡Ã¢vŽ˜¸\Î & & 02*Ó6–'ƒ(àÑ; fa:ꆌ¾"ÇbŒ0Q0QØ-0¡F0¤$ZBM šhh$4)úÞÿ&á·ÌòÀo”_I7§ø|Ù¤[ DÃÓ,i‰ôi@é‹ÕI Ȳ3Dò[að†¡@p‡L((…Î"ŽBÆ! €çð0‚FR†€“H bFÀ‚Ç,¢ 4c (RŠ,4ဘaü…„4)‚PaD ‚… ÷Ã÷©^¥;ÙÊ xm$`uÁ˜þ…<‚•F9()Ö @(ÂH@¬8£¸ã‚‚œ=È3„upRHR q]ˆ"0 ¶’‚Þ0ÑPÑ:.‰Ð<(u0Ñ4LÓ #ÞÎÁ¹ØÔ£BÂÆ‚̘ Ðv)(pÐÃ… ûÃÛÏ>ü¡CCIí°ˆp)í7vOˆÑ˜%ì™4Ofš'F”ìèÄ4²œŒïž¹¦O‰À¡†è]÷ -<ÀÓJâšb)c%Š}xt KAÁ£ÂއF™œ©¦Zº{06ˆhÀöQ@¹ A† 3ÈÎ)ð1¢¢Ça”yL`Ð+ ã°§|þVÂI)±A‡eú8Q%)#Œ¡ƒ Œ;ëÃ9#Ñ¿]Tè˜Û¢<²Ý·8ÑrJ™¿x‚›M‹ú:tÜKÐR‚SÓìtºOKgcˆ±AÁ·¾j8´özXZ¸ñº‚˜¢»vGp¢ªªJ¨Ð|ÁÅ‚*ý™Á€&޶‰¹¢»6µ¢‡`.—Eþ‹£[“–в JFTZÜ¢× 2"‘F ¤¶°ñ|ò¿—=û3ûþ<_ô,?ëÇ7¨‚œNÄúŸ$ís×Ûæ XT¾… Äû8…ücü™Ä!= ˜ËŽ,0ByRë!AÒ‰‰*ÌR’bÝÄ×a›fši ‡ù’‚z(ÎF³0Vî–Ðrà ”®ŸáPŽKRTß †fìGf?óú%±áMhñ Øîî†âBDˆìŠa÷9{ÑÚ%L½§+À‡òâ’$ÚÛìÉ–WÚ>C!Ëüý¬Œè9õÕ5T&Ž#E[†îÞä7ISòÌÙòtDÑ´}Ç­&Ðü[wöxN¯:v[AòCŒW-§îý滥üeµÈ] 9I®Xuаm b§hx“¨í¥ÿÞŽ`zÏPpçgAD@œ …H‚„x–q.4á"K–y¦aÎ3›Î]æL Ûsœ¹ûPýÀA‚¢ˆ°PÄ2“0CS+B$¤òÉ'VÝ]ðj“Qô§Sâ—¹jlOïCDûž:S9°G#ªŠaÑßïùVS6Bù2c’õɉ´6péÕt:pôg6Àg¡˜èoÑ:d_V§©ÃU—£¢5Ø!rá¸oðyN~/ly;JuûO©í6Æc²Î3Š•8[-#"*"}"Z•-žp—Œv±¶ùÇ©Øè Œ0`Ab¨È‚ñßaåö_!}9›†áSFUãö˰÷ÖúÙO5“r¢»'Ò‰©íDÄ©X¦‚¿lÛëÎ?}|J@Þ6ư¾¹9dè` %RMDÒòÑK;éîk$×ÃùÒlÊÈ¡ñv` ´¹ÓƒÓå¬ì¬-µÆXáž1…reM:iõbð?§'Ô’êà†3ž;ÙÔö€Í©Sщ:{g.çí=¨«£`Œ !Õ¢¾|y=tá±Ö{w¡W'-1ç3)åíð"˜w`RlêÀ(  ½øyÄ=DNÑND竦àÂ$Þâ/Õ  ¤Ô PS°£?ËE!26…=y‘Ôo 8ˆä+Ða7(~¨*¯ÕhE¹©xˆlœ:C k-#鿣|yžð‹²3lìô·€ÜŠ(cÍ’qÓDÍE/—CD‰$MóÜEón&(;LèTõ"¤Ê€NaSSæ{WtÉOÍ™6 ý£s¾é…¦=ìâîDO"MA–Pe„888;fMa€96 o‚&^ÚÝãÞŠZŽ!ŒÀ®‹6ײB¬U=¨¨/zL•$ÓR@“ úªÁ–”˜“÷˜1 §ç­…G«¸s/>Š.Ì|2mªl€ÌŒ:Aë‚r»˜öótróª» N=N¢OÃ#ƒ£e³)‡  ÁÊá§,Ž; ùZè»›C ™”‘˜éàèT5Õ ^QE%3C U,…LU ]Ũ°Š©ƒÌË –<ÙÇÙ*mm¯¯¦‘ Z••E@E>«açÙèÞ³Vn qÊÑ×¥â&¸0ÏIb—oXãV?&9À0^˜b‚šK 76Âð™SÆ£v@9+@¨zèž™B…ÄÑ,„TCQugyÊéU›Œä í4β)ÖE1ÎUÄ>CqBâ4ÂFg£oâ„wh`°ø8§¯røc_µ“ÝÎQ¥¦æ ÆáY"¡ ¼sÄj,T/‚Q;bÁÍúUU>V.Õ€Æf ”(ªYn4*¨‹TxÖ ©‘šõÚh¦¥ø×'ý[ç¯p-;ëŽé¨â°¿N±ÿ1#{úò«Ñ¬ÖŽÒkëUSSé9èëÏY¹ëâÇ|µ©XD“û"Ÿ‘µ¶Ý­ ø±D§ðƒL˜ZQô´¬¹J9iV› 8#M>‚%4½ºõœQ/2Ôbà8Z1.&d}?çüðB€R¬Mhû¢éßK1+µé }áR“hÔ¨!UŒu`Ô"‘’ H1 *»ÎÜW~PëØÍ±m1m„w€ÎrÄ=€ˆõó•äB¼*¯±†2TJ+R:JaNÓ\Bw|œŒhhY¸•®7mL*›Ûл´U¶(RI@ê0+›´Å",1ÉɈbÉñ=î;$æŸ3€llIRËE)B «T TDAQPK@õÇ­‹b‚ E‚Q«^ô©J¦žÅËÝÅDAµhŠÓ>¢#Xœ“ÂYEÝ?ˆøé*¢ y‰RR]¡6fy~^7rL©Áœ!–Úòi}:ÉÔb‰Ba2‘™c‰“…“†QèÉ1‘ü•gB*0ÿVj;j¸ZS/¯ìS‘©®ªÍG«W”Ë×Tãy:Œ°u<Äxj¤’I9BK‡/)Òw¥¸šLAß#ÒðtŒ Zê $ßÉ×@çYÜüZ•SU€¡Ð`â (a(¶’”`[a¡izÓ`¤Œ’.[v€;“‚ðŠIu€²56'áhO{©à:d7·!Ž\orØšc¥çš SáùÏzP% @a’‚XzÙ@>p(†ÿCoKÑò!úÝ2]é']éÎL—EUQÉ0>ƒ—¾FÄ$§7VywxVœ¥Ì©Ó¸KårM6 2I›ÐšöáNðŗǃŒŒ“Æu™´/mæg84æýši©å…z°°Þò÷yÊ;Q­¡dKÐûÜw™$äf„1ú˜AypaÓ' –Ž¥DxÌ å+#Š ¾\Æs†x°Þ©  Äâ2€bFu×Fq´3pΕ‘ax^“¶Ó¾`mÝöÃéäj#Çs`Ç$PËC ÊsLš{?tMÃ÷ˆo±¼6a¼)ë@Ž`GbdÅ–Š  F "Œt¥c»‚“RPxÈÚÖøfùÈQÍú µ¿–œDUÁæN õ™HÜÙVÏR„0¬ò§Håëc¿‡ºŽ§Ýô¼Ç_ØŽCñ{>?¶ÿ÷'ùç@åè1Œvƒ¯xPXÀøl b1>µî|­ ?§THôØÊ«: ¥AÐzëÝC· &›$©ÒÊ –Á”)AiA?©…!T£Ìñïʧ˜v*ÌôÌ:œΔ´hȃ#iD¢‘L0õ0¥³fg@'«dLA½Q܃ªTSׯøÜsÑp2pk“ô~û|v¿ Ú(Ü€P5+0ÿ4û Òp§± &S~«4ƒl ”>žžv‰Á²Ê³ºfþÃWÊœ8%‚ô]|©zN“«©fÙÎÍ4ëë¸pM|#êºμŒ œ ¼Èá¨m¯¼ð£ÂÓÔM4›e“Ìa¢æ%‚ `'ù¡äj–-ÊÙ'L t=‡AˆÊ8ÉŠ8ã¹P0Ô@‚ Z†‹üE…< 豃íè{CNÙíÂQ"™†è$ñâa¢ê†„¦èäÇb×QØîz÷0›Ý¢ D EÜèX[Ê3¹¡É…Û4놥AD´  Â4£ ƒ*#ö0iV®pTÒ-Éì%‘¬´qÁE]Cs†œ::}ÀšN† 3®BÏDQIêu“A'‘à¡Ø!ß Œ"Ž)Þ®vŒPžƒ @ÇagD7'ŠzPø8tI¡”9°Œð’”E4§{f s6>¥2…ó0Ñ€gcgJqQF(H=à‘‚ˆÂ”`¢°©#¦1]ð öAàż Ø?ƒ ÂûT;+®2¨p[vaÇ>(‚z0gAÈ=fªÈa"Ab”â°¡D0ˆÁØŒÀŒ>äNøSǘ\ ¾è‚>Øš¢½Úk{ê*¾ÿÇŠ¿‚*ë aù_Ö·c*ž¾cŸüÚÜÖÓ€Çtß9¬Q N§ˆxEwÄ7Åëàh3“QC\×9‹—„`hÄa¦ ïS‹„Y„Ó…*DÒƒŸŽžýºJ~Á„ñ”M?_¡€”§ä (‚!‚tè“Ñ: R%Æ$ cùÎÎÍÓÁ˜¨-Ýa†{ òI‚²Àåp‘ `Œõ/©äS˜d‰4 xö™00:gÇà)E Ü7,(œ@Ã…/ç|î‹ì4þµZQžå¯/)ëܳ¢Ð=ˆ¯ÂŠH\Ó5Œ¿>3ÁW\$ú˜îö.^7…îoj¹ˆbððë…€;AqÊ€m^…L  ãF­Þ þð‰Áúí PÏöMÁ=t†ÛÒûï³ö¼oz:PQåú—(°]7Ýü¼>Jpyñã:ô…DÊüÊíCz• EíŸZ_ó¾¶÷Âãû™˜÷QNË×ôÁëÂA|?UÊ¡÷PâN§Ö,rCàŽÌ6¡‘ú´gƒÅÏ"ç…¬g7¾Ä#ŽœK4_nILôöå€ ÈÀh&*w(â½ÊrÃʉ§Š‚ÏwÓ¥[pmÑcHttÅCʼnƒOÌë;¡hœÌŠ T€™¥b‡ÖÇ´á †0ÐÒŽRŠ–wÚn•vœ}P!ŒÄrwlðF¡ thÎÁtÁ.c´Ó:tW[±-hwÉÖ9j¡:ÕL"÷*¨Òõê¡+»b §t]ÎQ¿b&ž½P‡vrºiÐh;Ê óÞÓr~;Ì9ËÁ¤¸Š£J±®ÜÙ›œ§Œ›Î›%h<í˯—À|<Þ!Š|ªðª jØA‚)c…¶¶ldDXŠH‡oðûûkÓÁ66èÎ"ù4ùiª„_.?Ù‚£Q\¨¨»ŒM·šñŠCçI©EóÆÐ!©C¢û†±>—ãgüÿëý¯ôÿ³Æ¾É¨ÐÑ;aŸ Gȵ6]Ì‘inU`Ïìm…¸¡R2€¨´„«3K¡Îøm é…š4‹”ƒ á­8Dwé  ðô…þ0ÍéþËÞ¡Øzp=:;ÁLJžbf~Vhº”þ£ßèÃÛ`Ht qŒ¬jK0D°2°9€òóÊ'3Ìó`ˆñü…ž}Y8ºpxi «p¿ØZSÝ?²p/Æyü¾[¡îLÍÊ›¿Zh¼Þa§Öý~x3ÄÄ„O›Wg†06oÿT0,ŽE,Rèˆdp¶™Áù^¼!³ÐuiƒÝ±ÜØ1[`ÄÐH%R¥Bƒüßü¿˜–Ý7Ã9á¾a(Àù–À±Ì8±«êbuÙÛdÄH¨I f `€ cÁïÇ7üÈ{0öâx6¸QÌqB1¡È–Lz« Sø üØÈÜý,:⡬ª3§e?¥!.!ØÓ)$Räd\@sÈ«®2Ž˜ß1Ô:E®BÄK8æaˆ[üRŠOä01Áˆù°²–Å.¬RaXƒJÎÿ!²XíË“Dðaч)àBÂG\%•:+XÑK N 0Ž`ÜÀj–l’„£K(¹dd4gàì¯ïRͱvÄØ4%ÃÞ «Ø…ËmYD=óÕ9ñÈ{DožQCdx˜A”+Š`ÝPäQ¤PtXÊ8Ã1@Ö3’bӀצ`ÉadÔÖW_!_Â+UB½®*÷ƒûèü]þB ­ÌœÀû!‰¨ÌÀ0R—ì@É $¡F(Ê([–У²e¹,‘–®U…˜80 2²%Q$K+¢ •™km GS&dÉk“ìk¶í¥b—2f`fMj2ÉeÑ8ȬéÁ@ÀÁ68PTæSâ RÆÇµÑUc¢8^ôž¼ëä¢Dö_Þ½¥ð‡½æO GkÕŠp!a¿g×ôYÄ* ¡€’¿]•b*(©•tQÄ­ ŽI„>³÷É>‰K${ìï¡¶BÃD+‰Ž9>ÏÝa<ƒçè<¼ž¿’bàu¥TTe¶x´†ÒÈÝ7.C-¼ƒ€´~ ¯Æ+’–‘LttzÓÍôaø£Ho…z÷–݊壄f³„›&6·,M•_$ ¼6œq'—FH&0Æt¢ý(MGôøsΡ¬íŽQG;œ…H/Å?~{¹xß:»îp\÷Aέ-hæÈ¤[D™Al´ ,Ó¦œOK¦…ÃTµÅI×!rrC¶rQð¡’B0çÓ’2vN¡×ÈóÉŠ] Ú– #x*ÏÆ TtéjM œ Ê4[ÅüufH"Õµ=±:ˆbsøå°l„7£üä4§‚CߟZ  öåu<ŽoðÿZ´'²¨oè®%ž*ªªŠ«\Èßêž¡ƒÊJ%-ûða ¨D¢ØŠ Z†å‰Õ†´º`š­HÀ‹S¶g3þ{ÉË?Í™Ìn·:̪1Ç6gqŒ¢†I†Î9 $’ ìku·L&CXYv ±E/ ²¼Â˜:rÌÌ2mµTi™y›¸é»³’Ë4”˜NºÄÖIA+TÁ” %,„Z h;•jamÚ,Œ$i –‡ƒdÄ5#¢¥(É™Ĝa2̳0Â’B¦ˆ†‚(blœ&” BÌ…¦‚Æ"’€¥‰­£‹ÖqûÈ*Ïï'Xü+åÓœ)zü¾»» ùHk$ D&täÍŽÏÝcs€?Ëè^çÐT'­È¡öãÁ»óÈäìb¨` ­/hij[ðÞÌ;õ{LQ—X£(”óãøaØ!¦biF—çtÉtZß>ìýS/zu…âÑð”‰þ&g, ,WÀ Öÿ£ô·2q®¹ä / ´¥Ô…E À£%ÜÈB²DI rhhƨ ;6æáÈt”ö&2¸•IP \µrE#b™ˆX± eL¾ŒÄí”aË÷”“É,X14B¢¢œ‰\ªXíÕEº˜àsÎŒœH„ZŒdUM|f³Ù ï]’NfÈÓ–ø€ä³.ÐâÄÔÏ,PÁ4Œâ¶³¢ fA$ Ð±0l`ö¥J$:„…b '¬ŒA餛yq̧ŒIW¿N'ÚüŸÓ¼uÐ⎠¸’E€>UÑIóÀ¥‰OÀF' ðG"˜ž 9áÀ^Ä!j8BÀg?0¸q€À£Êå­ýݱyT1K—Í7Ų̅Q}Ë|Æ:J[¯“eТà'ÌO_`{é?öƒê>ÖC>#L´7¢œ~å\µÜ§5ù=0®iÖ|ܻ޷ZõÎwoeêªÃµVêš·dÞÔØ‡í¢Ú”~C+«®\I¦‘N“xÝÜW}G]¨ã´ÁoôÓêôö[‚l# 7CÑË÷;ú'Ò3€›#8×ù‰?°Tì søzWÁ夘fzC-A§Í&šC*‰Ô³söì­fîC&Xt~ö>à0%ª@êöíÊ*£/'(Œ†‡=C¦X"«ËX°ž 4Hë”ô®-\ñEZ–<[­µWòÄCNÙ&“­¤þµâÆ5,/S‹D+—±Yýp" ÄPNP3Dj9U>DŸ&NvÓ®½v;ePŸäIàÒ<´å ê {޵rEgè³êþæ£`tÑkŧQˆ!Im8h02™Ë£Øé»Mº´ eÈä°âÃ\JZá’H<÷ ÊqQËØ7÷ÿ.„_«â+ŸîA²>%xš˜2/…aX@¼½ëaŠ5‹gÜÿÐú›ç9:a8x)nBçS~àBŠ»@øÇ I?n€˜0Ggf» ÇÀΫúhÕï¨4Ÿo±[~Ö[=FÞl¸Éw±:QCƒí{ƒã*\ê'd'Îcá¼ÓÈßó¼ÀhÐàG;L8¼áÂ(‰Eª{»¤†ˆ $ùàd'ó3®U{ÎC{ùY¤ÃVW梗B_m¾w3Ú×tzò|L òyïLxc؃¼‹ë|Fõµ+±/-‘Wi‡mwí@à°O\õI+ˆái\Hß C¹§Ç‡Š.Mh†—E¤ŠQ’ØmBƒ‚ƒnQ @ƒyô{²‰ ·“à·>N=Y„Ì™E‚Ñ ˜¡RY‰”(Pª¤ÓrVõT Îo³gjIî6Úµ­µØÔž\x`nÎØ’x¶$†1‰A‚ÑÉjPêᘠ´ …"¡«x~QѵòÏ‚uz#pÞ:‡köjRš ¶ ñ.¹"²1¼ mOÂ…€'ƒµù®)àÞ_W)äC&‹û½ÆîÆ$ ÀI€NóŸEŽÏ+:Äý8gn‹#¶Xªl$=âaï§XžãÌ™4TGnm˜«ˆÓNzÈèÑÈæ€ è`åÓbJµ]”tøãÉÔkŇh§T+  LSsBM0"|ÿ/xm¶Öqx¾¾©•[.êA=– „„›[Aüçrxq=œ•ªH«ßçñÉRâ¬RÕÂybÌE£«­»J5Pá‘xcáÃ0Ã.:GÁ"¡Š¥áI{ƒIØöµéúŸQG ÿöÓ7”³#HrfÃ~éDˆl@À6o‚ªªÀ£8FB×"½ý~†êȈŒë¢ùY !ߟx!–_ò×Xq&x½áxȸÀeuÍ~ßàÚΧryVHZ\ÿZßÏE¬J´ôœß'ÄÏlÔÊô¡¦ù°ß\ܶ­«7¯ô5½üswûõ½ÑTQó|;ŸÕöçØ¢W©óàØù¡:ú#ò_j«9ò,D44cpÍÀìE,8¨` Æ=)`ƒ”¤ãAÒò½ Ú +³9øehôÞeïo¹os—¥´¶Ûm/ª¢z†ûTóx#‚‰ ñì³gM¼æˆnazƒ åéCq5‹Ó®qãE7¬-¬ÝMWX»pNW_<m9Ññ!Õc†1ˆ™‡ ©xúV#džµgF TTNÐ+ÛÌe¦Û¹å'‰Æm»ëjÃòÒXX  ‡Bª W¸‘9ÐzR>ÝoM ¯Ù‚.ñ˜­ŒN³pÛÇ6…,í\Ä›˜í%Rë×y$…©¼$îMMoR©íå¥ÈcJdéiH:„ÁÑ®bZGrAÎô˜bð@Ä2 ÃÆ‹ÉLPd9+XÜcIÁM€éÿ.ˆ—L¤;„ú¹>cæz@D˜)úkv«jN ¢ƒ>9Cf é+Ô²FŒ³C¬‹È}ÜšG·D nt&ñEYù$£ª»VrÂÎzJ“®6µŠr¸#æ“3¢n¡»Þ“~hï @©¾ ´‘WI—gòa#Z–)Æ»«!:ÖAëº76ÐDs*N*šps–j rInøŠ‹ê»Vx™ô±;Eßœ×@§èqºu+j©ˆ…ó´Èç ;R¦õç“Ùà½ò_5—1“»í ë¾çbÚ+Y QDjˆšíŠBö­íÛxµ+)„Á«¨g;nûð®g¦+Òzt.>Öõo–fÅuQ !Åë}dSö°j³(HÅ»}é–-àùI¿‡÷Åö"$2žübLXm;ÐHtâƒChùY¸hR×Z#Qâz„a×áµÐ¯N¼h!e]þ²¾&×dÜí e8ÎŒeïÓ÷ÕÙݽܠˆu&¢*ã{m_mËTfz‰ç? 2_µ<Á>N˜QENïš}R¬;¶¨oOˆrñãËa4¡— Þº"É< ŠráÉæþ&i”„"H)j €”B“@S"¨‡óy“‚öäöÒœ‰@óء줮üóŠIÅ{ƒ9ÅfT²f¾.™ÒoÁ }¨a2Srt5ILLoÂ^„>6þb›ëžWa ß]Ð0÷R¢1:BË + k½»—ÌÒnœŸ^ŒJ¨ˆž:O+f2×ϯ ä‡mó¡×|`z›«‚²_i’CÝÙ°Håà-ȸ$–êf?š‚DQlÊx>:ïàïÞ··N½ïξÀtßIƒF…`…}>Î…z…fù3–êÊ«žý» ªªùÇëå„…\-jù^£ú-Ç^Ö&1Nüœ^uŒößM1X½m‘òÐéÒ§jw9H0(Š'L'Ý xh;¼:7 3™†c»ߨ҆ö×VÉÌ÷ ¨„ßÌkL¹òPÌVØ_—„(hÜ{ˆb&©¨§˜ ›`UäÿÇýüŽ;½rˆs‘‰d–©Â€3 L%•z¡ ‘N¹Æ¾úáéè£tG\Ðy™}’ŒB†1‰Ú‚`ð„û#„4±ƒèpeA|ÁŒd“—L4"šx=QÐáH[€~/ÇÈÒ€ö!’SÂrpç‰A›ºhÅô"ÐtSöŸ QÄ‚”ª——«r8ÁÕÌñ²,-JýÌë}¶M3Øg5…àhÁ#6ò XcìEiE…-¨Ûý_~`í¤öˆ'` Pðõ@´Q4EULM%szêJÜÜÎÍ´vq2:æcmÃWé‘ùù0Ô‚¿O›h¹7Ôë1-o7ÍÐQÅŒQPû¬.D0ÀÌ)QQL G ‘O(øƒ þxb¸#ä’€{&ÿCÓ觸«Òõ-‡W¢àcl·«E'äAS:Pãʳn¹vC*j­†˜fdf /…˜‚Ÿ¯Z©fÊÉ3Ãél©ò ¾›»¬S>WW ¤á_'G• IÚ£bCàDéD:!„òáÞƒç[Á`ÑÌž·öª¨•Ì']ëÈ>8¹“f"Ý•·„Žñõ~œ›¹2Ö=9¥]‘ÙÜy’…*3™D ºú‹\Ÿ=­s£TÉ^?3ïo×A¬Éi>.­÷ ˆ}0óà\Š—ÝåDß> }³1wµS³ÀßA<Ê­¹…ƒ(:v;HhÎ%¯õ§c3cðÓm9=#Ì:¾Ê¦ÄdU(û˜® v·?1ëÆKA,SnùŸÈí4SR–SkÛÜ¢àr$Õ3d¤ÛtÉðS§0hB!1d$)†%¶Â¬ˆäË'¿tÉk"%Æ]¾‚à†2lSÚóŸPg%O‚_ÞÓ&1\Ð3—3h]›^ÚÖxçn§gù®ÉLtvÅßÇà£tž 9$^…~ ן+vãÌ¥’¨©!!´Ò…‹úGËCj䕹—[$`ÎJh&Æ ´S‹èz_m÷qßÌ~!Ÿ£ºs(—üÑ’$ÉPK$’ƒ €@¡/®!‹ÈË9ÎrIže_dÊÐxÚôG8§j HHc=S›l¸AV{Ÿ´þw¶öQ#K ¡0õ|Ù$"f†ˆó>'§§·ÛÊøu–±I¯“®`I›‡:— êˆÍ3 >›TA!BC¿ {úCŒ¢†ª7ÌŠòÊ©½áã|À¥G(uv<,¡yŒ©®C¶äŽA+"T[¸˜»ç=П€Â ˜˜`ˆ“Ðô5 9áJ“ƒÝÁ×™ÈrB402AL T²n¡ÄèàTô`b†…¶ª¸ç™B’ëDAYë…á‹v†W¶n”ó»ìÛNðŽEã ¦xXJô`zp¿nQ"Çk@òø~9{ µ36U|p”ÕPPm˜Wm7ƒLI<¨rÂÐqÑN´¸Òt𪿱â{S!3sÓÀ$äÈ>ë"rÝô¹V)³Ê7í=ÁE½BwÛ¾Þ>/,ã°y`óc¼¼\ŠnÀ$IJÇ<ó¦Xô£·=")—j.Þ¾þ~—ÍN¡v«ç?Ú3÷owË®; êçùÝ‹~ …®*’¡°Ñ×å+$±Ð/Š»Ò«æÔpö¡@ð:vÎa´yÙÐW:sJf¥¦ãõw1ƒ¿=ŠuóBE´ºÁ ˆ8‚ÙG–"±l‡J‡J…'=‰`á×m.#Rv¿½0·fó£‡_meëQÕTUD® —5͆0CÁ}Wм©–ee¯ ´=ŒŠ-*» ( Å¹duU¨¬{^ ìÎÓ§ªÆ÷Ld@î,©¬‰é} "*xÚH”*3¶×=aܰ¡«ß¯"–¸]$3­6\]ƒßóptùsçÔíì^'Ê…ûO(ïÒ·®{:ïË6bÖ)¾ÎOKÝ5敪OÎÌíÞt½E|¯Ê÷ïßÄl?ªô ¿2<0|wïå™KðÜë6®»¤z=Ý &@ìÉò=ºH¾'J¯GQá,òžß%]ƒ8N¦â®MMØ;b j&={¼ÃУH;œ½·C7ÃFÆ ŠAjŽÊ3(ÌA¡RÎÍC‘ø ;äš§§Ò(áWüèîìñÞé4…ýƒ©Ô#CÙòJÌ!QRt'0xšD`§((ŒAUm¨±`¡Sh(^b‰$qWô~—[î!]WV8 )„î”` »î š9ùÑLrÒJzé°LQ1BFÂu#¾zôÐDÂ0DOsǵÒ$’ÕÒwÝ„7l5Míò“‡¬¢uíC·Ä1v‘NŠÝ2é½åËÃÙ\½u¯Fî{¹§eƒTYq–?•îs@ú!!ã‡hȤß…Ã/Yq.8†ÜÑ®&ž ¡Š$/ª¥†Rî!³¨4èhãlÚ§15‡ÁÂáQ£#  Ä1ÄCÑ€@žW6í‚,æ>»h5Èê‡íŸt)†v¼ŒÈ²W!ÊÛSÂFZŸ?.–kZº‚Ð,‚9¸""T)ç‡âÄ„¨gHÏædluþ—/ü‹y\\`‡ãç~—­â€zß#är'Keeç2ž =§2²ªª¡å¤¿À&ÂIâòŸäs©÷Þ†î·jìÈŒ2 :`ŽŸŸë` '®pßsòG{Böð¯–ÿ%|*ጠêÍÂ~R£Ý ØŠìHTõ 0/u@©þ˜“‰ã #tâŽxé‰ ½ äôWÌž®ãׯ—#Ûz˜¸dßj½ãœ¹s–Èž–¥¶¡È}â­[É¿eŸ{ψ¤øöÞu”Ù÷UUŽuÑdÒªÕU,qUN£*˜€¬c¥›¯«éÖ—åž]wáí¥¹wuÕuöã·Q0ó²ün{=´€)Ûy§舂,-âô3*Jïm:ß§Õ8Rš¬ºï¾Êa}'F*‘­Jm3ü´óæë­¶•ëÈú¸¥˜k¾”orÎ_›ò°ª÷òáð°²µu‹–QÈ©z£.yß©Ô0Öô®m¹AÓ¯ $„¦Ø…˜i˜†éÔ(žW¥žÜx&½ÚÄ&À“Ñl°¤¤ E%ŠXª¤Nl§ˆWãµs2ÉKøfÉœ‡mZΗe;ÝÝèO­ ¼Züúx¿¶®¿%«¾K¯­íÀxm8Õ“!3#&ï[º)_Í{©H†»„Ì*Ô0A&©I`k-65+/\µ–X@%Õtqµé66ÁY$à×Ö[xçhÞ'o=c¼“LÍ:Ÿ1øk]ù=b´ï lÁ‰ÚXL¶~¦%ß-xæÐ¯@ñÏ׸ó…s)–øfjuÕÎ^âI#fª¨$…–‰‚"***¤`˜¯Hûçñ®¨M‡áTã‰;7lÕw'ªO -ç*„«7xüÏX'!¢‰& Nfš!‚ ¿ÂœwQs›VŒÆœ‚À(_N²Ñ<²oQršôU_s×ÌFŸ·ÐöOÎaÈ×F@ú*I))B‚D–PØsâ˜ÈM‰« `eÜžñ`!€¨þìùæXö;´zñÉ8zÒ”7Qy`ñޏ>O†/ áCgž¸Xš`†&´“Aå}sdt°0Á=PÐײßi´j )t‚‘AQTJ%Ïa˜`ÚÀ ³l™tÌ1]Ìd$0 ÂV1‰0Ó hÜž¡þAÛñè¨\ú­afQ†5HúÌ®,{-()F¨à¶!’áDP²weß=Xl+øpÍðÝË›B-~L©Í=hœ&àÁó"ZÊÒ&Á3¯]¬Êê{„@æÃžyuÒãá?Z¸÷ÅTf;>I*AÓ¼M€Ù¢¶µŒ€³á,Q3Ð"½OÝ'!&eÔ ºBF¼™í —bå·$!0²R9ý ÙnˆaTYÙö|ß=K˜o»!U/yÔseÅ%Q¾úŽÑ”‚8?\´ë)ñ—H8¼ÅèS¾¸IÔnÜy»<í­§”&­ñÞEjƒ‘Å[émckzúãßu¾qû¯0˜§Ê·pQ²ã0y ýýö£ñ„LÁßx`)çŠ8„%›• I@âí?‘ówÙ·c #$ã>” /ÐL(€I‰,#l%@ J²ÐpÌ1¨V¥¢’ÔcASôO§Äßb†š2$® ’t4Œ½˜`!áŒÊ’rS-‰¡bV¾I¿ ÌË"bzB‰!¡§XMQ& *Á4IAH"êHVD¯G IÄ“X#,‘„i¥ ,"D lV°YDã1$©D+DBápQŠî3êžgL:Øì&G%ñº¶0gÐŵÃíU/Và†Ýãäí#' ±PH ªÔ α,€Õ~°×SÖ¨ñ}ÀÖ¶ßÂyy1ñó‡Ž{ùÙ!¤•+$Ö¼ïÏ-N(£G¥‡ÏZ6Ëšhú”"—2Cöˆ|~¢™Ë£=‡iÌ{û‚>÷Ô óTÿßÓ²ð’v'òBüÞÙnvClìhUþQÒ'œ³¤÷áð¡t}º-(jBUä_ǂԪzD\9HþL #–4Gš'· ¹sK‡gØ]Wº|^êlXù× ¬}éÞŽÄ~|v—_$‹ô0—‘6f%™Y¸èæy–OI4%xIšxBÄ¢i>\ÆÏD›P¡:@†‹2äƒêh-fµ¨ÑØ Gi=иI¿²0æ}‘4ç+#2‚B£â×äà×uNÃÄNRÁÕb/U€õ"¤‚H×ÁB‘¦Stê}k8y^AòeG¯FÄm€~ÖÀ+2ðE,“zq,=Âð‰ÎØ EòrpPŸ~b ÎUUAûnb:Úèìôp5åŠú3øãxýØôÏôñ±V<õ#étàzþ˜‚ Y0”d<×>ñ]d|ßg³"úì’!õB~ýëeþËü[äò¦Z«¢¸.ý00¡9{ôw‚û¦ê¬ˆÞH&$d6cJ¥gNPd”)k0DÀçãuÅo»ƒJ Éìdz¢’K”Þ%¬¶$âæ85¶˜<’B%è Š¹íºB–Q­¸ÊáÊJ›nZ>ùÏ€HÙáªrÐð}å7&¹„ì ÕO„?žŠ@¢uGË 7(Q±˜‹ÇÞ<Ê}¨ôÖ¨„<šqž`f=KQºôÃS+‹Ø8èI‚4:!Y Åb EX2 O×üËN¤1†Ûûñ[ïéêCzôD;GpºîC¥Oj$€«dRDm“ÇnØ–ó};ÂÝÄGˆâÞÕ·Ç!@âî×­ÍÑ-…‰£èz;Ÿsý^‹ÿó÷ûT=")·$O¾dH°vÕH¿ãIä×j®7‚—ѳd°‚’bJí&œNì(»@”µ$Š»È)´ª?×w‰À(J"„’¦nœ,00Å1–HZ%XJ@dÿ¨ïÊ ž“AQV"‚£`e<Ó¼§ª¶“4½{nïx÷J¬1¨bLnµ†Òü@ÇŠ@< _^DrË * «ý‹ì<‚§:ÆXí‹þ>[WmÈÃY=©=¬;B^®3Øœ@¹WÚãÖô{t¨lÄøhTÖôÖ<ªÏö¿§’§œ$:î… êJj·S¤BÑ„?­Ä7t«!r[°Í ¨œ˜®[*DJ%ˆŒ+Z5Y!ª¨”:°M˜(:»Ø~-¿EÔÓvhœ'Õ<¼ÌŒŒ¾üíÇÄ2{³„!„ÓG4]_Õ•ƒæÑê>•MÀLÆÁFä²HÉÙ&À°»VFR¹Hƒ‰Tk[J "RµZÖÒ@–R}¨i?e?V_ià  À@Ö¬TÑ*Œvq)Þ†ô5( Sˇà }z-<à¤Ò>vÊ% 7$x õ@úØ}ØØ¬æ£’We/cwéy÷¨Na+㊸Ð'Ìxy¸Né#©q—-M:a¡¨'+?t!5ìmEDAQ`©qï`âYðú4wGÞÉiüØ8¬“Q§„ü;>iãóG¯ÄóâVŸZ8Cåê â6ƒq‡d•R‹úø*P»p8?«ñˆzaFJ ÛšŸdÉAh.ªqexÈǺ µ˜ð@Ôu»wâãÅ홂„’ À†0ñÝ–é \x"ð"Ÿº~åOùóÙ6=Àç sìü¿¾ë`wo{Ü.Ž]Ú–s–£­­Fd³Á©8ãù‰-•lU…à…¼Áx–¤;Aw¤Õƒ>½ý[û[[—9Û9)çHñõ©,‘Õjê všß|»Õ¹èÏ2<Ð8 ïoÂý,vn=‰'Q„Pào—FÆ&¬RÐê`'´[Èfú¨Zž¨9:ƒÅ!¤Š A~<]UÜG«7Ç̪„ ¸…¹Èß öulÓ×…ŽÝµ/¾ ¨g¬¦'É47,ÔɃgÉÌ,ã,Œ©ˆ9g›?qˆ¡0–¡p±äMœ”pKŽ$ ¯WNB'NœäÂN©ÔïgÙð{Ü·:ãö™nÅð¸ŸòÙŸu„ÿsTÁ2ÓñV¼ÜÓ6̃3)Š\Â~­‡.CœòÐúÒu98ΡÈ<“ãÖ>;5‚NÐpŽå«#”r;ûô㜧Ót/d9-ED4£Ï9 ˜Š@)éü¸ˆfa%9?Ô{ø{à Ð JUiE‚@ @ Š*ª¤h /XO¿Å4ý¡*¦g„ÑYeAQ‹ú¾¾z§ªŸÓ<6 Æc_[ƒ ZKT …§ÇyÇãµz_ûöýOGû~‡ü~NPbÔå‰Ð(þ/ù;_çýþLC$ËVPˆÚ)¸QÈ"›S“0ÑЫ3E5«á \@ Æ"ÚXŠ‚@ ‰˜ °p‰JZ_”ÿ9Õ èó§P‰áÑ,þy`ˆ¢nu—ýK¹78Ø@Ÿò)Ò}èˆg4Óv??×iᬛ²£.VxÉdÅ D¢ÍÅf\àE1`Ž£:ž @äÿ·Ñ¦Ò<ê-+Çî“æFÎ H„UÈùq²‡cÚušœªª«´aŒïÅ+PÈwòoÑ äÌ D4JxÛø¢­¨R¡™d’e§zïÒ€i]œ­•|?±áס=ïB[Ï¢÷a=j8Á=ȉ`ü(~ÔG©Î>÷C–0Ÿ¿ R‰@*˜DE )$M4ŒÃK”R‘1P!©A@,CBDÐ!C(ЈSBP"ÄEAMP$1D€ÒËU¥¡A@44!*Ó@R * HR%˜‡ôþæ>p ”<ÒBAĉÖë`e`‡Y^ÐhĨ'ð~—Øw«šu‰!ä&fdðA|îÎçyÁá QC †¥€i"¦˜¹•"„õ~ÿ§ŸjðþbBâ @<°+/Ñ⿜FÓëODáÛp é>Ì$äiQ'¥}D„º?:@áø=žüwσá'óàå(~¬žÄóðà㘘¸]Ö1PBT‡¾ˆh˜¨–* Ñ@ÀÆß82l¨¡Õ¸‹ˆ"Ÿ|ó6 ˆâ·“c`£z©—8êÐÞ;=ÿ‚øLžTðÕ@«Líâ/<`{§é͵±ïÞYøoÉWÂð|ø15>ù™þ¢r ÖÃhúWŽ=ÁÍG;'ìgïi8y2\²»Ð>(ʣ撦 Fý0²Ø% ÈX`~l· iBंÀ.Œ™ƒÄE;þm ~üãG?Že;äCçÄü-Îó.wÑBˆ€†ÐÅA𠨿TE6J ùÿÝÿ§_¥çuÿäü_çýÿø¿“ò|Gaþ<7«ú|]Ï'Òñ|ÖVâo/ôþ?üNñO_ÄÿKœæ‡¹ý[ÿz_sß~—Ÿèÿ‡sâ;~®­~?Êo>9ç §¢z*ñ~n ǬŸ:â·.8¯¬eâø¶_{Ùb~I²hñˆËká@„~MQî硃î;ËYÝþ•áÏ«OÃþÿ£É\ï~†ÝÄè@t¤uPP0‚;ð‚:´ç3û¥ÒÆœÜïû8»[X©öaAà.ÜÉ '·§Oì™ÒÅd aÁ-ƒmÓëɳ ˆ#åÇ\"£ÂGƒ`æòëQÔ—® ãqS!°€ä9bWƒC¼¨&23Oõ¸sÖ±xXÊ H$÷xâV‘÷÷ƒÃüÒ‚‘®Ó~ݹÇ:éu®óc6Ã2ä-±?Úâ 6߇6ë¨2‘PÏ»‰­üÖðƒìùšG \ÂØ8Ç|ÔQAjµ­NfkÈ ’v²3ýŠ3(&·F‘SæH/½_æ,²ªƒ0ÌÛÉKI¨è$ ,È.FI‘‰CEQƒ‰ŒÄR«r”B0#R±$ƒ É ­N£E1ät,éÀ$I W'ö©¾6Boƒ¤:ø î0®@ª™(âŒ@uH9(¬€Q’g×ïÄOÇ–Ò©RËo£$í!(©€ câ"È’ƒQRDŽül¹n¬»Îgƒ ®ŽMSPd„Ä¡<‘À8Y½LIÓ“­7ÂJe’ò¦Ð0ْ줫ÕLS2¹R$N8ÈAî!Žî †{.-æHÙBD+C‘…ó©A¨ÒXÀ¡@°0…˜sfï¡‚y€‚È"/O^V%Sr2@)JAC”‘,AeE0Ô%ÉDÿ\«ñ/3.N½ïùê·Þi/e~Øc@ gHl4ïwSpp c©1U VÒ=꿯0^ÎX€Xn‹ÃüІ9áq>_P¼\ÌGßw3W^©ï?¾Â…¸ß'ô~©¿¬3ÂsýJ*>üÌk­Ëñ¤s,2À—'@Ë•#dg049?ÛGðäþT&^p8Œâhj¼èð#â}z Ì!í{lEsÆ`$(h*žì_çÃð<:ðןƒœ,ƒŽ8ïUðr×WïãÛ&pŠÝ€þt¼r¹19‰#'+Ò:¥Ü©îÁÅ =.áЦVuǰ¿ù¼âRH&S7k>M]œÖñÐöæÁã©îÁ~<ñ@ÇÖÈ)‘ë>¼xÂq€Ê‘*¯¥†E§ ™°Xœ‰äœV5²ü Œ VÁV Åe0þþvÍÊÌK(5Y­˜:9n¡’‘QJ)"‚'!1ˆ$©3 V¶[Túi!DC ¨/Ôý‚TÓ 0L>—Ì›GÐ/Í‡àƒ¢O¸;7¹† r-¡t½Œ/Š ‹,~^:v¼‘#=ðpÆþJ d¹!PÁÙÚ4ÌÙMÓì$Dû‘™2…d¢¥ïÝ‹U`¢øÊI\Fæ 3Äe’hŠE*Yivç³ëUèôf&@Ø—JgUærЀÔR­C‚)9d“3@Á ¤€™&*› 7cÝÑ×-Dúj,êTéE·0•º%Ÿ‡ÆYWSëæÌ„]Àp³‰P‡òMnÖË»J€sÜ>oJޱ",’$`ª Ѝ¨¨!HŠ‘—ÛDÁ„} (J ›®uÂÙ7­>£ŸXêÃð¢½ÂVR•AGž ŸÞŸ~~ú] ¡ HšF껾@nníˆÆ#¶D‘Zy'ŒãÃÁÜ~œçYž¸ZÂ22}ˆÕ.„¢²#"œCµÅ†CCQD£R²µ–~Â*,UUg¾YUØXT§ØÀÏIÙQ›* ôà™E¢r ªªª¤bbj¢*¬ú|›{G‘EEDDLÌÃÖ'h!”DÓ"DF¥ j;c þoúØOzž¼ø‚˜àö¸ü^R+æøGƒ¿á¼Ý/ ¬{þ-!µAJÌ?\Üû‘ÅQà^Ô¨»Çǹceb¾ÔxI`¼ê'6ÍάN™´F¢H®'Å£™!¡í\„VÔuJäýÎ8¿,¯ ä/N)Õ o9÷8ÔRÐm8öNjuÊA¹×ZÊ Ãêð|\»ïϧNa‰PçžyãmeS¹üØž>#ô[¶¯ÅgôÝ\fíÓ¸éþFå_”M3]êO¬40p“C"”ñ"ú ÔXØÐ‡La²ïº´ÎnbR‚Ç$3!ïPðéOUQNa{OØšTÒqÂ"j"Ñ÷UömÁôw ‚áÂ2‘:'O1*™‘´jbGÏŠb|Ô*¤ˆ¢!˜a™SgKá†E,Ã!™a‰º_–=INÏx¸èþQ”;d^¯%¬yÃ6Î}NŽŸ/~éê\0ím™™f.ë]¹¿bVbJÀ ïò¥ˆÍˆH;™©”+&DÒÆ7ŸUâÐãBØš¦©™Í02é;Kêù8m”ó:Ò÷¡ˆ‰",¬û(ßBOeéÕ8LÅûà 5w2Ѝ¢œ÷ O(Ãô,|O^ PÂé ?zçaY‡]9¥ _c’a g>Ä7›^[Æ«m §áLŠeÁ5Ò[¸Kv;޸ʮ±¢@‰¡Gkðò×L'‰æ}]´ó+:óÀéÚJ0çv@͵ç ‹„çÛÒj4J”KIHTU—¬¸‚€û­CÚôag}{ QáVºùiCWÆd‡w¬":+(4”£ã­¥bë®-x˜q]9•cn`nž‹å½8jNºä&€êGFÍËV”kÝymÔD„<X #,sÇRG¼§…˜ æ;Õ RŽ˜¹$LE”d+CÉèT@å 0 ¤2¨3”Ñ-"D4Æ$˜øg©€–ƒâÝzaOft[•ÁÃêyLy‚{L£²û@ÒT&ŸÌƒér8ÆÊDÌ%‰ìB~à~QæÃÙ‡fyóá¨ÚkHâl\ïîâPaÉŒ><ˆò0 ÚÛÈ!íŸ?êûA@SϘöuýB4=55€ùÈNÅt“u{²°yX{¾¥cøpÉb: †¨DHnOJ}!îþ}z ËÙ§áì«:Q{á×fÔÑhÖ_Ïkù—47¯ú’s¹& mý”ë§Ði¬"VB&_vF“E8Ÿê1ú‘Ä€Ú¨Þ5®èt‹&‡Å:C¯¢ šûSðÛ±Äè"Šó¢žödžëíHuJ]ØçÀ~œ Ë‘†FHy ü„‡Íê?PtÜ  Q‹ú¬x£hæ‚¢ïG½žÅ9t”æ‚/R€ÿïÚñ¤2*¡;µ²Ü¦C+!0Q5 UE P\†ˆŠnRdE30™2eÜH!ŠZ¬bê%™•Én!ºMmN'˜Ÿîóþëû¯×t/Ñ÷]ë›ò~·[°§ÖUœ§%/´þ—¸vHa$¤•%Ó ÿ‚åƒÛ£oÖ¡ût à]¼PñCÖ2h÷>oµˆuÎŒ>?ð{Ô Έˆ-æÌ›34ãY¬jâ¹>”6ûPdóïçCvÑÐÌ™AóìzðøÜ? E?’¾$ ýmßt5»é>?øÿŸêò­—O2ðCЪ¨¢Œ¢Ii>òÃQö_î8ÞYg» ˧é6rÙ¿¸[šÁH,){ÙË>|ôàpO½;ðg¥æ-•q†°0ÞBxC/`xýj¬Pú±_¶.á̺$£˜qÓ&ñZ%*âs”špóœ Hl&²P¸4?⣬0ê¾²(&á±ý¦§êÅʀϿE/ØÌ\ß>uŠïJëÕfrÚŸ1rˆ{t ˆ  _|$µÝÎý÷?3œ(¼–¬ 56J,ñòcp¹Y3ji)±ËŸ/O–¤Ê&Ùîú: à€”|$I2ÃÃçò߆ðÂ?`WÂW%lä¡Ù誶)ub|¢:3ðr+‰n Ù£©èÑ›|R¹(qgsˆm†W ½ËÌ©²ÌŒ"‹1™ÅÜNþ_\òvО@®Ï¯ë9³BMGŸœ.±Fj³I”´I~ßðÿÇÿ/ú:ÿîûÑÜééC\‚hE”%KMèßë½òÆžÊx€n"›]ÔSjš…S,!ú‘H–ŠA,ˆJ²„â“TRÐÉ"BÒô†CVb£¬ÀÓY é å¶4£0LJ‘PD s%LòÀÆ 7ŒV(ä†JVbä$RU2bDx…–›”b"©RK å8‘J#KNÈÚœ’Î`ÚªZ&˜ ¤‚k'mó½€MÝÝ$…$‹WýÇ~Fx´^@@/Ç脵êàãEÌ·E ^Œ P˜¤4T <¨W´¶¯‚Ðݳ³‹ kFÆT'’m¡á‹»JËÄž£Ì²½8¹A^nJÅ«´1.WßÇ‘a†¥¦ÉÉ¡IW†Ÿ†¾ÚiYP@QìÁ¢2 >çÝ¢OAÍgN¼uÇpÒñ¶Ätßn§ýÍiä8' "…åU)4†´R¤Œ¶»ý:@Á4.·SæÙþc3Ï¥`p—ŠÅ Sìø_î5J%üû »rñ>ÖZÐìdRìı(`zŒ”LjbT+R8Ò1ÚoÌT_q¿õ„S^—‡­AéÇ3¡ÿZj·4WñB qfŠUPä•Âuñ6Ä}tëØõ¡dïf8KÉù´ìŵQc@… ÒÁVZ’ª«<;õûÝ£°É² ^ÀѼz«Ã8Ü(E–zK+&‘#5¬‹—FW™LHÉÏM–~³é“YKÑçI A€}V×Êb["–‚'Ìà'}6PÁcÞÀïAnPº&—AÅì÷6Û Â,»s‡dQKà“ªdˆ)"†„"Z‰¤¤ª…`ª`Bf” Fb*J_ŸáÀþ`tDñ¢Àa’xôXF"¤‚„2"J™˜«€ûóTTUTDUUTDEDDUDETUTEUEEUTEUEEUUEUDTUEDEDDUDUDEDTUUUDvÑQUUUQQUQÖ’Ô%,еH¹ù>NÄü¹½ëÅ2‚!´õ€ ÁtD­´wŒD0È+ M²“½ã]¤áÊ«e‡Z¨\Pû4w!’õCZY:o.¾Û±îÒªm$ ×R‘Z|ºDÞ9ÌßÞžéð‘ìü` ‚ÑŸ_…™"B 8~zß‹ N‘¼Y¨Ýˆ†d*\U¡cwÕ^ Y•-kˆ˜s‘¼d6aô£Ô™¢.W¾[8 ¤èÇ8Œ¤#¹Cç²ã³RTA/öF˜Ö£ $÷%}É.ZQT´¡Œ$xa³× aAD¿•¬×øÙ]ì¥-’‰ç6yçlóÏ*PAÖQ,æYc$ðk CÛy`d#"|6äÐ0@Ä€H¿FôÎʰH[¸9퓎Œ"cû™dXjX @à^CyIvpÈc¼¤ÎsX rå¶7öäÃU€¤È¶"[@RRAÀM|ˆ~®PˬRAŒ´¸[çÔp­ƒlå¤7T7â ·¾R——ÙÕ•ÓÍÛ€@$¯ßïÏBu:¥ŒŠ˜iƒôjS!äFÑ9…'ˆ;z‘ò?*‹u£ QµÉ]~w/Óö~ tÓA/2¢DîPŽt¿Ÿ §´‘ v­hÙpÅGê«ìŒŸu"&9(c¬!ê§Y:‘W5ŒÜHhlø°óÈŸ‘ƒùlC#Oh.f 8ž% …*ò†RŽx›üÖ Hå+­nÌj¨bCM¨·RŠ(¼/ˆzÑÄ´$z=ü²òh×ÖÈ#§«ðò:€œ¥¥¥WuPx34[¼MÖKâÖbã KhïÄÐÃR0_É"†Œï©AÕ,­M©f¾Î`©$$)`)*—ûÐé"#ñ4`c(«ÿì N  È„ 6ÍèîÑÖ  …_~H¦Ž²€9¢ÈcÇZ1‡DÙˆ‹‚ RE&¡ñÔÙçðúö«µÃ%ð‹‡«Ö ;°´@,D‡–[‘œèºï.Í&s$°ÝÌÝÉ Œ£ÙÇm&2Iꆪ(H¡%gšB£°hÒlDÃ@€H€.°ãaú]+rt¿ÂœÆµ RrˆØy`,íæÿ9áՇǼɹ/h¤5‹ ¬,U¨=¯íþÿ/âú\ŸäÿO›ö8ÑM¡Wû¼Ï ª‘ݳ0Ù³äŸì¿cñõàOõØLÌÎÇÄXqóß³3-¶¬’I;~ÉŸÙ£XdÇ”§CT&˜—­ ¦×½_#2dÃÊÕfbÈ š'\˜Ë”Eæ2mÜ6 9ÔÜMæHê/I §Œàwfc&¸“Lîxˆ§û¸€ÿbé§lXmUÃ?ÉV–5Óñj ðñ~rÓí&òˆT¨Âº9à”!¹6œMÌþ0FÄ;Ax†š±:¿ù½t'_$ökL"0¶wåžÎráˆåÖÔþ¯–&aÙd¥Ÿë’\X·&•¨˜ý-gp³,$DÆY‰‡"Ú.k\˜Î/JüEQñ{¹ÜbOwÇEUô#ãÉì|yîm¬mgc^^YJ©˜ZªTn1•"“WD £B»Ê«2±Ö13ÒÊTù#Ë öÑRëM3åó 3-Ý…fc%ã{Š]žtˆsž:“ÒtB{8\£™Ç›:(,WŽiž¶p1Z’Ú®[pF4̱zÈHS–·Мõ6^ÑE –i±Ðž~kñÜz˜Ü£ýÆo`ÜeQE8(°ë‚QdG6æmÄɨÜÜÄÿ'¡OâNNçÆx$ò`ñôxîêîÛKÓø? žò<¡ )ªõØ!芙Vd¯{GGýœ­ŒMÑ_`…IPéÕp^…Ä‚¢ú]\Osäѫأå3û‰þ~¤ïié<袇ñ¿á0m¨6\kZÖ£¶cêŠ)Ž5QE­E¢Ž‡ÈžÈ1DÉ#-#!” 00$ @ÊÀ2vUùl( CÑëwRe¿:Q q䤸Ð˹(–ÒXÔ‡Ä<8#ƒ÷ãr{ÑΆˆ×Z¶§éaò¬%åﺔu!zTž‡‡îÓ¬»iôÄ øæ·ÇÔO×…¨>Óð¨c@2A%%#åx+ Œ:Gµðñøyû[»Õ'1¥¢TÖ³W]u¸Vúë¿8'LŽŒ"&ÕP11°E@?Z·°;´PÐ80ÑÊ z䨇Ö$÷é’¶ÐfF¾\уUµdM¹¬8:ùºCITKÊP?T‘ÏÁ³k^ók’ˆ1n|ü³‘)–Ye•Ûª”*¨ÄRbSLT%¢6 ˆØ"Š)eTÔC1 ÍΓSGE±A©©©²©¢¦ä,ðù}>\ z2Ã}<á½î’9àòÆK@úŒ|<ò'nÒ=( §¡Àr)°ÁôE$¦ðQ4Õ.&2ü‚n¸…Þ‡u:Lñ":|­FÎHhªÎ؈Vq…^Žs.V )[ˆR¨áI%3XÊ`ç6á·S0’UͦͦåÐ ÑcF3%4š%À«Ýú†IlòÇéñ÷*ÒneNƒ«ÝÇÕ¤1Õ”²iéÄS R‘H4ƒËe¨Ø&–ÄÇó§n÷Y€È²@r$ßuÛJ˜äUDv¼ø¾@pQ|fè«,©ððàr ‹'C[ÙdYTÑš¡KBÅ]3ƒ’Š `ÙÈT,â^Œîëà†u0E<ÐÉBG“ú죥Њ+ ÒÄ)´H1©)êà^÷,A\õ·½+±±0 øsW,÷§àµ>äx#[àm^ÐK¹>€ƒìcŽXíÚ“Ã ©Ì†^E¨ ‘8ãª1Þ€çvɰÎÓçû¶Sæ>3¯GÉ}ˆîdoW”Â;mP›‚õ_ "´ï‘Á —üBÿƒÉþf¯WcÌñjå«ËýBäuŠ®ÕZ1Å PÃÀ,7Ýù‚#IÀ?¼|~•·.¨¾CÞöe@$ £Gy¬Á–DÀ¬h¡ã<=ÜOn4æ @Ô‡Lþ‘çP˜«<£^»b匆xi ݳ"X¹Uz UKÅØƒØ4y¾Ÿ§ƒêTÑ v)ñäKh@©½mж€SYRÿ¯§£ë§¢»ICý:})15ž†S¯ŸŒ‚¶Ûù¹÷\ãÜÊó þg´¾¶C{¡;ˆ5¢=¹çg˜!·AÌÍ3Ž>{Ì®maãqzÝ~{sútz¯h C±ñd[•@ÞòŠ~ÙÖéqv°Mp×ÜKkxé8ödJS<ݹ\ÐâŽb+y8¯bÏ!"HûÔÇJ‚«î¡®X’u§gúÃðeÄO«Øðž!.~|h…¥¥¤m‚õõæfS?P_Û”Ù(0p))  µø À´³b£HÆJo@£È¦*\‰ËÑa{µ³±*dÒLC`>šY«”p¼/"™ôášÑäQ³¿Ý£·I ðbC IÍ—Vf9¼Y‰ìûš)WŽ ùôk´É´ú@û?Ôê<’8¤)Ž\íkZã‰D„h¥ª:†ðÖ‚¥C^¡þl>/F?b÷$ú¬IV¬°a’J/UŸ†L€÷gëðˆ2©Aù À ê“$ô TÀ¨•\ø¿qAôw`‹Ð@ŽEôqøH©‘ïñÇ<¸fÝZ-ËÏÍχGiZn0‚щÕ"Ú=µ->h¯ökÍ;¶tß´zƒA Lþak\¨–ªeZ…X¥*FIª^µÕG™JŸÇö’G²*–~÷Çÿçø¯èz~nÖ}HlB‹Z*RÁ°¶«ïå¥ǵ0žlž§÷¨9:ù} yù¨µm#º¯¸iD…R·Äóëõ5Ƥ&[;! úúÓ Ë9IJZ´°¾€bfBCl¦P,1¾æšØV;aDûD•í9àdk—²ïFûy%&§[iÓÏñ™½7eq„)nIFD?‰§RdÚ¶o@gcàÔ’[Ê„`ðwB‘FîH,îš•f¢{°Ã¿ ègÁ:20¡«ÛX* ÏÃʃá2¥§9»–’!$ÛL·™)*¹ ËtÍú&0/B†SªBVF@¨bfþ*@ô§<ΑÍØ™Y¨ra™W0¶¬ [[I¨c9}ü$×)d(û*O†Ãp¢v‚À¬öI1¥Œ¢Vß$¦×LË rr6l0ÈÓs€êo©Þ`òÂ5Npé>N(øÊ Š9–I!Ä®Ûnäͧø=~ï'<@¬€ @:Z…¡|1B¸2ÌÛd =ÿ­b#à«ô'‚¥¼‡¯ŒÍéÙE‘•TeM\™Ÿ<Þ3QŽŒ5bq&+b.×Uó]›ÑÐÛ±’μnàœªC šPR zZ)˜¥$HŒPøµíTI™˜(Tr•Àf&!{¸‡hi—äÕpzø÷wŠ#¹OwT |nÓÝÓ 8ò* Ç(KE.‰,11¼®žzY]± PØ€¼´"0 lP:aMqÚñ|l =+V‹K6iîb‡©Ù;êQòЧ©‰H¼Á̸@ ¥âÇ àÑ£÷UA(±ÓÊ}p°•´“½¬ëÃÙ%J†Âp‰ÖF“íÑÝÓxhÐ4±:" …(-ŽM •PPRùúxtë ÉrôŸ®CtùHÒÎaªB$ª˜Nç\rÚ¼|^gåÃØœqAšB™ˆ`!cÆŸtšHÃ1Ubª»Ì¼+ÄSÅšJ4hÉqv nM©¾ '-Àg—¨ÏÃW’®2Ô"9*÷s 4ž[=½àb½B2ˆxR‚(OË¿±M­Wɨ'ò?å€ú'ì'Aª%ùÒöN¥ø%SlíéÊ MŒj=0:`&Ø¥æYŒå¦‰õ² boYF%Ù$84@E°Š –uªD M"*kL@ÍS¨$´1׿q80;¸P•ÓÀy!n*DÕ4U4SUSÅI²)$ H)±+¥Ãr‰( ªCƒdç)!ITÊÌ­€4›H)€nB&Ò Ñ °RÀÑ;`bµd*1£#¢…¡(!™“$’° Ș¸H¸@–4©ZL²2¬±(@‚ªP‚hŠĪåXÌÉ•)p§- ”Ô©e°$D´mYX*RÍJˆæ ¶¨T±($¡ DEQUI¥"ËÜÉd0¢ŠiŒW, Ø´Œ75C¤Lˆ§Ú G”b‡) "T„’„Ѹ&$´†˜dÃT0ˆŠªˆ©IŠ¢¦J¤`  ™j±¤Õˆp4Ï]„9å( Z©*E4µiÍ *D Ð"I!îëÌl*l'Öv2.DUNEPAã8QH¥“ ¤¶`a I@¤H¶ÊVÐk%%¹‹A(Ú–¡k-+A"Ë;ýBnëh,ªbEí ä\ÁŒfÞÔfe´.åW-ö$&Cìñîgø©ò '$¹Õ¥èŒòCNt¸ÃÁéq׈ã#«¥Ó‡¦=ùíš:ì C•ÐOÛ#†þ÷ÔÀvÐæèy_‡¥O3èÆƒ% š‚ ’¢„eªi¨¦*¨àx£ ”=&n¡%0LR3b”²®™ÒhjŠ) ˆ –¥Àþ¶ÿ!ºKËN™ýRÓâÉÖZ)À)2D)”ÅÊEèeTֱᙩáæÿ¢ù§ÔýïéÐï€äœ$¦žÂà˜V [DZÀ ti8E-5€ÀzGÓ3ŠWAšqWŠ„ “ï|WUÖm¾—‡swëû”ùq„®ä?ý5zèõ>¶í¯¥öpè¥à¤…§ËÈhtºôí´9È1ü` ~>ë­¯ÈÅפ`Ý$ÖD­Ý Ÿö",`ÈÂÏî„RÀ)þ” råÁÒ'å«@}ø}¼kÝ ¸ÊÊÇò›mÐRçãæu{¾‡³Û¹ çÀùØ 9úNËîÝåöø$z d\¤ðNŸx›#à“®ŠK»ÊÊ`®'„*‘ªA"8BJf= u’QETSKBµMTQJJBÔC J«$ÊBBB*,ÕPÂ!PPRÔÍËc—àm늺õî£1—i©¡2ÃãŽY„„ˆ|©&¸öÞuÓo[ÍÜ NnÐdèw79Í»×:ÝÅÃ͉&ÆlÙBl„ɼKilús¹ñ“çE:P®ÆðVïø¾xÈkÙG^ÔöW¤‘®¶ãÒl»iNºU% n Ç¥ hÓ&ÁT´¤'.šª™Ѝ¨ŠŠ " "†U¥Zi¦dFI‚nÄë:×X§u /X‡AÈ™a ‚’d˜*”!¡¢¨‚`b"„)”´“”DEHH¥RTDÉIAFÚã¸FÅÄ¢ØÌß>šdƒP)× &Jza!·Œ$S£3Ž.2DQ0t.нËýí[Ý äªg UCE¦Ä"‚=Ù P‰«hh@i{~ —SB'Ã/9™DWܪ'hùÞ¶_sEÈ FÚÄTÚWŒ/ T´D:“&–jãÃŽlÜe|rŽž(D&<ÜRd1d1€<# Éx…UT•ߥ‚ pXÆ­(Qçiq÷t†HÉW`„"d_…>v“'" ('žaŠ“-JMQI~†ŒêbnDL±DQ ¯y®°û¹£úù!§©îÖèGª%L6ô¦#ûó—a|\TòÈW†ËPɪ*ŠšVêè>ž€õ"ÄR*Ü@Ì* &J&BšPf#ƒ‹Ž"Cq!6a”@"àÎI-1 ©Ñ&¥RgÚW\ÕÅNutÀydé…Ø4ÄLjÖ_~²‚„Ëlÿ½ÙWX/Ð:ŸôF˜‡À €4HC+ÓG·Ð½½D˜(¤† ¤â F4à– AX@!C'Íá÷ã•r ¿>ôs#s0m •–ÉMëߤ÷à]ã q¸`‡§&ÀW˜:d ="»Tøåºú‚Î{Ÿk6æ6=ë¥äÕýªÉÓÆY`½ÖËH•‚‹ ¨È°À6`’"ŸD†ÿ]ì*³«Èô¹NçŸì4ügîÝè<¼PÞÖ‡y06èH#XËÖObI8!Š‚l[ÆS©ÎxçÛüÝá7» ŒYïKÂIÔeµeœz:nGÕ±9xÐÍwÊ<äQå±;E:xïró”ò,X(wÒTÇ“òó;z;¨`2͉¨-XȲ>´*sqñrq Ì!M(©*þ­´³v„ùÑNô«d÷&<ò¸±QD‚±8Ê¡çí¡‰Ko\ÃDUa$d„(¢¬dE‰–ˆs”ÄWyç¾@†õÏìR›lR†Ò2BÛ³f‘;ïúé œ B0ã( ƒ–2ú.“9ù„XÒ‡ƒÓrý»Çí|kÀÁÎD蜇˜‚”%È)çÃz(H 3 âD÷ÑH»äd kÙÙ¾ÛÕ‡™¢ Ll×BïÃÏ é蟸@‚³¨çsE¾€(iÌ¿æßH „ùH:•|<ˆ|Or3MBHPÁw3ÃcLBªãq0‰Ø(0UZš‡•Áš( #„)ETÅj1‹^vTØ$ˆ€Å¢ø]y8Hö×qp܈wA¹€ĬBàG|¹(PY ÃéàÆ5g?—¤£ù¸å±K˜LÀÆgç8ü^Sd4L áÉîÞZ¥+?W•Ði4Èf4ؼ»v±6#b-‰’Ô†kÖþæ(>!ìžg•áÃÂñ'pµEá|è1tË ¼»Y“¯ºk•ÎSÖ§åSI ãíP†n: çl :¼e ? Wh>#5;ëºN¤( /.áBXg ‰EüëÐHpv(8aœÐHg&ŒVõ€àyŠ ÄÄG× %µËÍáŒ@ö7FT~I’tìqP|úçgµ”íZHP‡!`]±6Lš±ÏŽÜÎd ¼<ßåBꘈjA…$$@])Î#ÏìÙêÅ6B¨àfm!…QEQD’ËPÍ Œ[ #ñ@‡“…ìŸ0ø(b!%ðp¤½½ýñ8Ñ Ð)èôâèçH…¤" Lϯh)<óËù–w ·ŒŒ¾®¶ÜJcBÅÐS–0’9Wñz(ýÎÊïÒ¸4(> }öžÀ}±ü$«i¯„sDs “!„=çJÁ_0"˜ŠÀg¨öex>ÇŽR]§€©9d d&"Pmd‡È€è`…P[r‰‰qsôß™Ût"ATᑈ0j÷~Käê}m¿†§r@ÊBÆáôB΢!Œ´Z½þWõ¿w‰ˆze<áùÑØOó’) L#"- çk)…X}+ƒïAÿ œsFä1çèmx òq ÇK.¨%Õ(k¡“_‡é¼k_Ù'K^Ç}žM½U$$)zÿaC­ýâ4Ȧ¤¢(8‰ yÇ}Ì@>²0 ‚`Ø¢ `Š,Š,¡Id ˆXªX|Ïl ¡C¤—a™ëÈ¿2ÙÝZÙÿGþµ)Ç– ˆ*–AKöðKvÃú{¿Áéêx †Ã#0ĵ÷/kg]øw–˜pWàÔÛqS¯ª¼¿jcëá²×L~œoÑI¿Ñ†èÕV›oÓ—Ù‰,å¬JɈiØ„Å*õ"-€þž¥xƒ:4 †‚¯ÇJá$wQ$z_jí¶øó ìÿ¾ØrìS6©üŽãëuiHGð8~9×c¸LPòaëaÒê¬C©à¯£õ®c髹 y¸>ûÅ”¬@PÄ ÉØ«ù`ýØý?ψ}<Ç"uBZ+Ìñ¦äRBCV¾0S ÷6þ…¡¥€ЧBQ:…#£# é]Ó7xPjà³ø:ý8Æ–$G_Ü¡6ˆÿ¹‹6›K;|<¸<‘º)ÕÕ?™è“õ Pšêg4|Ò!´Ø¯ïVT²±Wûvv†ÙKôÀýƒm´†*ø¸E´=Të‘ûtºÒõ‚±Þ®O¾§ $AêÀ( õ˜Q•B‘b F¤ŠY ¢Uu PÐõK:i‘ˆŠõ¢ƒ×¹®ÚáHhëŒ ÿ3!ªhyªÛÐÖyªÃ”#dÉ$YtÉ4齫’Ù®ßå±¼wq·tj_äQfA„ðbRHgÈqî"!ç‚›X KöˆZ(?¶Q‰‡rÐÞ ¾OW¼õeˆS.Áo#gYU°À·g;…úØD&±&lötŠ–yH4€ŽÅÔJ§¦ ´NŠz!M:à‡Tд%m¯råé¼—ÍŽÛù²c<áfÈ:‡C4\ß Ky!8ÇS¨…púô̯eµÖ[ož„¾{öcº:èÛI¿ß£¸J2!íQÍ Mfä/!‰ÑL…p¶-,t¡i`’}x}XZûN®Ä¬#ÂLo"m ¥ÏS–ÌÝô@vKó¥“)B#´Qùìøc°óÛ¿S½õûêéá§?»Î^¹9c`ê «T•¨løÇw?¢þ† pÅ^h½áa°Nꮑa§ ήž»jôqÍ$E;¨»°x"¶ƒ%kË™Y´Ã[„›ÆHÓìæ/B‡,€ñ{ȆP¡(cuÏÉf7FnŽ‹á«¥ÒÉiÒoÑ…¬­ŒXA‰zóýÓʼã¥ÿ#”å[4Ì—/Ꟈ³ü¹å<ȧ)ÌÂÁ>6ÞØØ{0SI“寤jjØc*—€ÀÆ.ЂG§|EB˜BæòÔÛR¿²>k=d ¥›5H`Òà¥5½Réf9Α÷êx‘H qÜ:Ð'éñœ€yÈu1­ O~r±ÕÁ”o‘«Ö5(OÐ熪„|³¯‡ç–7§ž,ä¡)D ž àS™êÖôd 5IÎøÕÞž|ýÉÚÚÚv©|°}ìOq^lóNGͲ{-Ná*î‘#­ÞÝ—å†ëš‹@ç—I„.A4u°$Üpx=—íºI„„h€À£,²rC!¡ Å&— >¹÷¬ø7¿WÀŒ÷&§ëø|mÊÖzølý¯*]³9 Óv’)ÙŽÜÛìyõVLN´QÝæ ÆcÙö0¡Ëä5w* Qᎆ_/h=4¸ìDz®qµ÷ä0“nnúp ã|zñÉn=ãÃ6$¦·¥!+d²½'‚ãŽ@!¡ö½ ü߯¾¹›xé߈7'aAM"·ÞhPÁ ƒ“8(PУE‘Z“‚ž€`|+6 ò<V¡ÎmÑS§…êNÄ<%ûFz}½ø@vǨŸ’|£ê¦b ª‚ ›êªS].– Æá^k‡^\8v¡” m¸GÙh@ç¢ò¬M#uÙíLsü¹ŠÃ² ÑÁ¿œÅSD ™£Út›~¶§˜ý·—–¥|Vçÿ8ÝøÉ'1x¤ »Eäo(ï] HSø”|[dÌqÚÙŒ¶~e¨xÞeTòãö ±ž ló8’™ß†[ªdÔmƒ˜•ú—xª4J–VÛÒ²Ú[j5…Db…O…¸#ðñLE×5Ù…)RRŠ4¯­8î¸îSbÜ®¹º¸…V–Û~ Ͳ…ƒüìÕC+Xˆ¯sÒ5ŽœÒijÁK S"f 9ÆÛªM@Ã;4ÀÔ_ôQCÈÃ@VFÄ c ¢ä‚\PIXuŠ8drAH`ú¹2 á#ó¶—¢Á0)#eþ¿sxˆëwiM!¤8$~ºM°âØ`K[h8p8|ÿcGC*HÐÄ2ýÑìZá0¡½Ë $&F96¦èŠˆª¢5Z³=uŸè MÎDú|ï{”¹™¶ÌÛhœ.$ÀN0-°žƒªõzÂõÖN´S^¹Â¸ªÎ¹Î¸ ðªhs‡œJRrÖ&‰7²Cv‡A¤CL„ž¡ëöšu k³&QPµ•Él2 öØy›eƒ[tz $ ™ X}þ¬J2>”îp!¤( … % %”$¤‰’H…‰)i!EŒ\†}Oƒ¹Âž?€aÒ-©+ŽÀNÇ Œà(bVJÛfdÈi"M™XA*PÕb`bH¼ ZÃ/Ž •BŽFÊ ûèM5žŸ‘ô,y1«Æ¾•©e«ìaúÜ0ôFGêÆˆôÏ»Öòw!íi!ñ‘Y _,ùa4øk‰Œbîêïܱ‚£Á~Á”•H±G Oâzá ‚<¼Î£ >¾¸s1ài¼ø‰÷ÉÀ6võ2;ĉ­ÒØ™qÂÚÕ©ûûÄ7ªª)¢ ªªˆªJ‚ ¨€b’˜h ¡¦¦&¨¨’ª**¢ªªŠ*ªŠáÂÃT"ŠR(Hñ“#³àë<Âc2|ÇC鳸u‡z{Ù˜?9 Ñ+hh<¾R,:¤(E=Nâ®b™ –ßB ’ út¶q›LÖLÊ A88̶åQ:”š(¨UfD¢„™Q"‰l” TšÓAÒg=9éf˜»5£ j†‚âᆵ€0e¶\¸¡ €‰2!˜6×çåIcê@ã™GŸJÈ!ìÀ{1Onƽ©Øìlö&~Æs"h…×¥ïEÝ„€/¶oÄŠ‡© ©ú²¸‡Zåõšáá–æñèRÊÀ0‰¸Ä+¬IŠb´´\a{£¤YÁ4«ãirPIŒWTyèW™ë*«º)W3»* B S-&d°fU$‚…ˆ•nd¸VÒѶ”GæaVi&H0?vHS ][2ãŸgsÒŠvrw{ ÞÖhºüönEE(¥E­òapkü¬Çú¨™;}bd¦Ñ„À¤±eŒÚ£pÆ )î~\ÿëÕôˆ• 5gVã˜.Ê[[l1PËáŒ{‘…³Ü)Ï¡P²c•8–´¹gÔ•°€ÛªÊ­ÂSŠWöÛ:_íŸüèhVPY%×ôˆÓiê³í¿ÙÃH(­íe[i©[ŽðÞ•/Ü÷R(G N}Î^ˆ·*83;ê§»þAÒaxœÄ|íÛãå¹P‘‹A<2ŠbÕX÷'ÔÀ°0¬§µGâç½ Uíz库¬ÌÍU[±Û™Îf9q=ºg&ã¸\ÆÜ.5¶Ûm¶Ú_nä$?t>ùóïúzóŸºûý@ÌÓн!<¹:Èñ9”˜ä›†à°Ûófì¦ÙEËÀk}Ù*¬;ç @ŠÅ ”Ÿ+T>'žpNÞyhÆñFã«().}¾µØ\+òêµtÊŠ¼ga³Õü·:`MtvÅ"™¼EÚã9µÓXËõaTô —|¶øöaêÊA _;©D|¤n¾Yꘖ£ïD+ŠB‰Td?´$|‡eùD5S5„<ˆ³ˆEAsŸ˜•HpxÕ†ÛÐS‰ZUK¤¾Á˜ŒÇ‰I}v±9ÁÉ$'ÇmvÓ¦ôtÕIÆ/1t®f Sõ’¬MĺK·ÓÀaS3­yÄ©"å=w=šs,³¯“»»Ã Š_61Lù¢Ÿøó˜8ŠŸ*‚/JB Y*m1ò¬… Ôà ð·Œh¶§J:º©tè˜(:vµm³ŽË0Ö¤,Ë‚ŒîC2LË…K,¬HW¨ TYR‰h…w`†èxþñlæ«#¬«”ÆxÒ‚!Ìøj–BÒܼ^’&ÜòÁ¿ÓÄ¥QSИäþç×Ü`£E ã7áPôO©Öã ¤•¹Á)îLÕryÓ™k0N­7ÑNsg¯vvïW Zojò|a!ºhâý¾[ÓöòøðS3™¼|c³ž{`)ây}2^xガ¬{"&.·æÊÒ§@¬C9ôØ8¯K®”:`°SGâXg!J–ŠÓ ¡ŠÛÜ”2>O·ÐK7Bù¡=-ð­P2+R~é›áûÂFô -響ÚÏûå—Þ?/Úë—°ßOÅïÎëƒãM+`®Æ·$Ú/UPú﵆ò…%TZàtó®S¦Þ’Úf¾s-z30½§Õƒ¯ŸÁe]Øéè±~Êý6kE3;þø)éø·Òðd5<8ø;ÿtãQ9íesÁ9¹]#q¼f‰,‘þ7Ë¿¬}Â"\ce½n;1½´ŠH!‡Ï?Šn÷- ß`ÝXR+¹ÕÙkЋĥþ$/¦à¦©Wl½:Uµ(rŽæ‹Õ(í êÂç:ÓÁΜðô'n¹‡~ZhuF3ѳ"ùåÁQëÏ.O +—pôå’í - V•­´ ÖeüG:Š!kÌAàñ "޵ÛªŽ£3 ‘ßÃ?L´×ëZ•a…aòžV½÷˜ÃBãî<2©¿ÈW¨bÓÛ&kTò.Tx||¼´gñc In•ÿt§ÄuæÏLÂiñnçu—É"|ÛÔy–JzÓ­¯wwTª‚¨RqUMøÇƒø3ªôÑ ].g„«Ðº:€ÍÍ_šê?ÉT¤Ylqm“!>~xo§–øè{Ù'}Œ^©¨vÐg«êÖñ°Ý³våµ,† ²I™¿.ãáOšµÛ„ucdE_ª2ÊõÊõ™²t†{=âûY¨£}ïïR¿®ÃÚÇt8îÈèÝLdŒq´rÝ•AL¥WÎãç–Ÿwˆ¾¿Å™Ï.ëO'¯N}=÷·¡b‘\K‚[ feÔËvÑÿE:frTTµ~Eº‹u–çu{lý±W}7jÓnOËÅŠW%¶š/ãgȲ®íJÑ'íº¨Ç"ÿvRÔÏS|f•Ëe³Ô_Ϻtâcv¯}/Ã÷ë'y:?Œ\6 Á’íb¾&Ô­¸ë2çã¼døãB«4ä< ú«®·<ž_3.¡ f[T¾™Í2RÜ‚àÈ`ÅŠ¬’Ý2¶–Ûb 2„¡¿…Tâ_cÕÓßž“mr‚—¶ð $‰ zÇ)Ëõ|2)ôÝŽ®ŸŠx”¥÷†OÁxn^]¦D$¤1Œ”®”ÀLV²e„C„âˆÔAž¤viÃÈú›‚ÄMW€ö=×ì¯Ú}ë°a˹æËK ;CÅì8G»¡ƒÄÿZ¼»º6äzŒÀø[ËNïVĶthNW³cËf(lÌ àH.©ÙØ Rhwv©$F?§ø6-y¡ÉGg«Ùà:÷3DWh44èu´¡œä'z¯",öšžÓÀõ&æÇâRñ*\+Ž9Îs–¦* ±‘»¼¹âƒ§ë© ÀŸH¢~¿›´ÙÅÄiÔ1îàyP·Q]£s<1‡«… êH :švxI¶ž¦C]Š=ŠÌ6!Û3åt¾Ç˜ñqüŠ«¨ßŽq™û6ܸ¹ˆÜ ÈŸëÛáÜ2§9€ñ\¡P²QòÎ0ñæ¾l –ÄB«¤n¬1„¸X0#fm|Óàòxxk…@:œ9ÉË,Ò50P¦a»3ƒ59ÍÓ€©êá˜×b9JÝp2ËtÚ×báJÒêró`+˜™œ0ŒÂjèáNX ñ:àðdžO°~K 0Ï…ú˜ñº H•>X=s¶\ÀõLIÅDù¸qâÉ $lj_ _næDܵ#"2 l€aK ;ÄçˆužÕHâëäž!ÇJ*¼537TaóGxyAE>dzм$$;¼3†Àûö ;ÔrÃaÒ•¦ˆ„~ì!b@ U>½u,V!“pê! œF®MK©D™pUÉ_Lñ\¾Á変ýÏí ˜'#¡Kä‚XìPÖ‚bk!kl¨},‘(JZZ€ ¤)Š ‘  ¥ (J•¢”¥ (iJZ ‘R”¤ ‰(„ ˆh)(JV’…¤¢’† ( EMÇêUiUYAH\t h)òÒŠt<Áï7ðDC™a"08+Q·•:¯atÀ¸°0ƒ ]ƒbfábÌÈJØdµm-ˆâbR •PRãTÊfD%"Jb†F@…(–Y&F‡Á `6°]zy ሺѴ)K 2wA싟ëëÖµoé§%X†˜(ùŸû¤„m&?[¥G™™Ü•'‡ËÂ^O9êiÛçHüp…' œ(éø¨9c³ÑS:÷W¨lªžü^ÙѨ¶q€7PÖËÀû^EqðH`0ÔªDU P°AèR€‰Ø£Vÿúw诬󱿀÷§ö~?C@†¨L襉çžZ#)”®iBzêJ(üEUÖ#¬1/øaiŽzõí¬·…‡2ÈX,ù^éHHU4µJÕU5À¦·ø¬÷¤óžs¿m—ä×rÀqñQhæÒé["€s픯@Ò¨&@Å* ‰ÖˆsÀ­ºps §•cT9çŠ;Û´xcï…¥6…`‚|<¿uõuzß !’d ió°½Ü<Ž~§6¸ohß6„â…¡z7ö} O§…ƒ!ÇFhòC«o­BÊÅ]jìñññìðímã ëq1ì—gºC¶µ¼Nkâ‘v‡§î\²_ŠÃãù°Šlñ<$D™‘*¾Tµ·ˆ;w5ÂHi‘%–l² ÉggâØÐüö“ ®C³„ÀÛ¶Â Å`ÛnY+#È€ÙY€Áþ J„…“sµÿugê‚åŠJ©ûˆ­çwaPÈZG3ŒÌ üšZH鉦ÔÊ7‘ŠC´/YÖÀ˜ÞnY?âUëhrôbô;€‰Ú¡5 É´y[…ñ†?CªôÕEz¹Ê~^§ ÇqÉ’¢tܽáŒÎštÕO4¢=ÙˆäêHD¶š‚™¤Žæî ùŽýÕ~Š2ªæ¡O¥9aÒ b®Ø«IÛ ã^icÚû:Ý5øg6œ®¿êùx:Æp  ’2Š–ÈÂM³Í;X­9þ/൲I%Vdðªàª.åØwÔ¹ÚV S{(‘ÖMë¿ÁŸÅ;k´6ñ‚.Ã-JDŒH• óƒ­ƒW9ÚIsNfbê@@Ë c'D õ·t…ˆvȰ‡lG%ÆDDížRßéïëÔ»¡OP ƒÍôœê‘‹µTD\p$‹\¸ë›“^UYçJQõèÉÖ“¨¦wqÃ-ÊUY݈d·+mVºêÓŽ8ìÎÈʬï$ç4MÊ–¡TµA`A^EvLÁÅ!ÅJÆöÖQû—ëv¿£mR†“‘îä=uíëNwKâ®Û|æ•ÃÌÝ›ÏÉÔ£¬ß,5Ü6ñ…² Ó»õæ±”PPçO|¼ÝáåÖ(ª Í½±ÊxËÇ®dôõ}¾\ýªsÏg³ÓÏÊ!´ ª‚÷[r•n`_l8*#cH¯c W;ÕÄšqB3Gwdfy‡‹—µß9Ô|f\~15KåÖ”  Þ®z<Ǟ…!瓊3jŒ´¬7žšDá"ˆâ\zá ot¶Gb2*wz ãFÄHÞ–áD§6ÔDBë˜óדxª¨"‘™“xªâ ˆu" ªÌ1W ù §þïçyòæPBä Ú~_ÆdäWWð‰¬ð{°ï Aõ¡P©=‰¬YïdÇ’š<]MŒâ &H'Äw‚`>aZ$ý?)ûadLûž24¸jNœaW(«"^ý+3~›2~.öÛ¥wFR|ØÐËâ~œ2©j†Õ—d†É÷ÙqMa¬Ùºû“ òåM0×·Mþ•ãáš}»ºÊú,üÏPãê¥-°¹õöšãñÖ¥ßÔ÷$)Ö_}kÓÝ+SJÙ–L·YÜj˜ñwß½×¼Õs­žºžv¬O]ÃÜÉ… UŸ_(eó[:µ%jë‚ÃXŠK¯NOS¼æÂ”ÙNëŒÝJã8²ÏµU™oÈHéŠ@š~3õÊe_z&onüçcË]êñSýx°¾–Y˜QÍ”AÏ^ˆ)H)õ ¤4“^:Ìc»©³È\I8®B¢ò¬M«íÏ( ( JÂâ¼¼‡‘@!A ww5J£/¥×Xb%í©æÞÞwßËÆr1Ö~ñܳ×q¹5,Ê2ÆInܾâñŽ9å:ZíkÖn,uëg®×Þ,5Á2£Ý÷÷î¤ñ›Í×ÞŒZ[ê²½wÕ î'œ²)NuPðÚÒý°½+8²Ïέ©e9o°‘ß.¢Üë·–å7:"&úÔ¾¼fq4òCc¢ k˜ÿK=预h ¢ª4 /¥«´¡«ÉE=$¿0¦¥Ñ™È«¸~KMñûW‘H‘¥@àñsÈBØÊö;(wT¢ZO$6PìJh•i¥°óþõõø<\L&›_—a2dS„cŠI×Çï¿W˽kî ¡‰óD8Ñ÷Ë(¨¬€1Õih¸I²E0hÁp>Çâæ€†ÉØôÒz6!- 8hZ*©Œh­‡I%c¡âûˆìæ‡ôȤ¦@Ò±,Ñ”%Ñ”͈§ E;¸žì6a³ €¹™œ¦°‡:ÒP £ }¡í¢*Ãßóüe¿:9¡‰2DrZa€˜Ã2d[ Ș ‘¸lp¨,š«„¥K%¥2%ƒ °12‚FA…¢à+(T³ws6fVÖÑJÓ7\a´&cœfK ã LÄ lh[pˆF+§æÔ!£©®¾¯†ñÏPä»›DGx‡xÝÑsIó@Bc¢)gŠ3-²˜m†§ŸŒï£…A\Fï¨'”ã½4"‚Rtƒ…T·¤uÃB X"S3«.Ŷƒ«ü¯Üøß(¦Ê# ºLÛÂ]XâÝL‰áøÕQ蜶ò3Ä@;ÃÊéèé"ƒm¼s×®s‡ eÀŸ-(, ‰h0Ù$°ב› ÂêL8@ Gçá®Hn¾€êW6T‚Q8 ™Õ/jãOL®"Ø™‚å‘Vsé*B:`aå5)h ºñ¡Í(à‘ªrJDÕP©Ÿµkc Þù±=”:Pôa€&Ý|4f‰ ÑTôQOHð"–îÃT*ö%lîhêU3­Ú¹åå±Óm·i:¯LLL¾­=˜Ö’‘Ú¤äJ;ë"Ÿ€føeéæ`CaˆŸh?ð@<%ŽQTVý;Mg?w2²~ kÂk®š˜»ˆ)¥˜`?²Œœ`<‚¾ÔŠEOŠF¨]Jd"ä€ü„’@P!“B‡ª Õ‰….Ä¡’Bí a IBmŠm¶#HŸ’‘§Qjæì°Ô(³ªLI8È k È4d¡©u#¨­°hhDÚ5êÔê8o…R…  "A¤Hi3ð癑 bsû´¶`ÁE©q÷1L$ÀMõd X¦æÃÅ4~B:Ŧzc È(µÕ¨»!ð¨¹2¡êèàƒ$„—-”VáºBû˜êð*íÔ ’U?UC3A*=¬r(h… cik[¿¸¾=RÂÐí ±¦+Jmqtl/@ ‡DI$³Hvúž® ˈI²!Ø òÚbˆª«¤zaB‚…(R%8¡¿_$ÒÍÈRC§Ñ×Öõ‘Ó”|:=Ø{?bËÓE—ÊëÏ ÷{+?Ÿ˜ÈúzíRvCåa]ÊÓÓÁXÊäÚ;JM\°¦g@„¯U·ÇJvž„Fcä8© ÐàáDRÎäNä<¯~!꾡Ls˜d­t6ÍMUt¨²[‰€¤™LÆ2 `êVk¤©­®¥ÆI6 ¤’–c6”Ž"Ra})9l& Šm…à%JÈÒ#˜å;w!I]æn0«; „†S%6èærI¥…ÂPeÚm-¶à£Š–¹–”·2¡©lT)¹…ÈYvâb–ä Zëv…Œ” ¸ªˆí´ˆQ\¸S3+·.Lw%Ë ]w.Â…h$©J´w ˜6æµ¹¼åç8ƒ“c23 „E3΀4ŒӤъi²\¶1c2†Dá€p6éC¶æEQDTpVTH,QEQ*fo)ºrÈ”¹.8è[¦ÅêÀÝßHHaRl`ÍE˜&SÏä2f ¦2‰‰q¢X¬EPlÁ f)- vÖA@‹!*U•Ô˜ƒ­X ×© ÃP‚ÍdܰC&æeÉFÈ¡Œ¥b›jŠ(¢ª¨¢¬QEˆµ –nSL.æG[PÜ4PI™¹·sÙ$ Êð«¸ÖÉ—JÒ¨$ Zª¢…ªU%F¶YDTœ©Â" `‡pe3,"ˆ'!‹K×ßÚ~#¿’g>O×Åz#CmEˆ(–‹&oGí¾wSw—Ô÷<¼»fƒL @€šÃï¾ïòUûs~ P9'µd„Ktâ"e ÜKƒ’;¡ 7Cˆ• |ÀëgæÒsÚÖüFáê §M»ígìñ˜5±¾QèûTb뎷+@l x­\h;D2»>š îAN/Æ(Ž“ ƒÏU4´AL(Q30TSIQE1R^‰2JE ¦¨š©ƒ!À™Îì†#©Ü~ü}Â(ÓÕœFxÌ$M0ÑDP§\Yf.ñŸwF ˆ˜ª¢'£3‚›~ÕrêñD |èA:ÒæK€äȉftÑOY¡=1#‘Çš;S¾É¸@v"L¢íÊöünÚ gËåÏpš`^B¡¶i%šJ ÈD(¨ìQˆh°Û¢æñÉEOðCdž1¼ìÃ܇~0ãá#OŽ~4p«XB‚…bÄ ˜š—¹Ì3< ©«X˜üaÁN‰‚†Di*…NLèv§OfhZ?4"Z&Ù^ͲM+v4m¼rqE7`¸t î@<ßO]½˜‡Jw‰4…SÍFŸ’ õ~=Õ}¥Nù!98ÆHÊGYͲõþ#öhO.þ, ‚k<¶èÌ(“Î=4|Ø}´:zï¹&qš•Þ®§¡½g„‚T P*q‡@ˆTBï®mwÚ‹Ò͵r@`Ü$8ÆöºÌÄÒvÍ‘òóê½ùÞŠ‡I[wñnm“É%MC¤+eÑsj×V€¥HWÀˆa;u>æBefükp¾1iÒ Î¹Íé:F£Ë¯}Ë¥=Û€§$F$¥–62™H‰šÓ¤”Ä(´ô•ÈQpAóaÖ=ްfý.MŒéŠ9ë$[!’ÂkÅ*Ìp•`©©ðHð^Ø €èàÜyЂM-ñû\Ó½èPÝtß½'JôðÁ(‰"÷§ˆÉ‰R†±(ÕiX£mUEˆ2³1šm¬'ZÓ‰ROø–P6ÑH¿¯ä×K­Õ°aÜ:þJ|+ŠDÙÕ…5(ëˆLÀˆ˜ÀÅn‹ +3¥†› $s¶bS „BÿÒ»—qŽœî‡8£¨äd, ®MúÒÔc›G%8Ý8©(ïç…D¥ñбž7É锯^×uš qú·{7µaÖNAR;3*œà=”ÄÓ.®¶NZóŽ]òû\^‘ÙôVÍz%ŽW »óþƒâymO›û:¬Ó¡_Oà,V¦ ¸]y“ÆcpÙøÃ¸°BE$îÚøy‰ÐØa!éM~¸÷³Q±Ø?$W²«·?iå$Žºu¨XŠ‚ˆ¢0ÅíÍNjÍYTÚq4 a% 4°DEE(Â)AK(°RÂ$ ¶#…,A!DV¥X»~ý~À4 ™ Ÿ!&úÃy&¤ãpqç äš'Ø@ %…ˆ&@(h$Šò‰ F@O%}€EˆAƒŒôÀØtÀl¥l!(‹ÎoC’¦ì䨣ÁfÚ@ø=ÏoŸÏÃs°o9eˆ¢hF€ió*à~|8ŸÆXýÀ:êCãæ>]Ù¿ö¤÷Pù·)#{ÐüXH|,ú6†ÉÂ1d+l ±'å½i„‘$ Š®Î '¥•@>ÌzT­²„r)š¶äóAKi ¥ÌQøXÛ¯®%ù/ki4! ZÈH—©@þüa§ ïâü£îg¥@u!Á-| MUaûqðͲI 4HYy·SPÊï0É´±wp ‰%‰ ŸµÌ‚µ‘LTà?/«ÙÝî<Î{`ø¡Ÿ)ò/bà<CÐðô}²¢‘> á æ%9 '¶ê®ßÔiÙ)×B&fgÞ½mèöýòýÐ8Ô~¤ê«ù%ùæØ¨Q¸B™3©¿CÚ"?B:vÓí³ؽ]à^rù"¯ÒßÏÅOY.øós,:ýöž‰ñùó¡‰ÌjRp1*OÝõÄ´md@©±A8¼äDßÒ:dï {3k±‡@ÌeezŒî2!‡M&š¢Ÿš!©ª&#µD ¥@¤R"&(Y¬TÍÍÑÐCPhpƾï¡a:©€ê*ŽþnOûý?•äíÿŸÉüì¿Wôù|.‡f"HûAMÎçB!=ä%mÓD ‚–`Ѩ"çj=HÖÐñÀä&¥ã|XT¢w‘@¬™¿ ýǪo#9n5åÀtmD!þ¯÷n.”üp‡óƒä‰5ß 8úK&a‘ JwGî ¼òÊ| L‡5ˆ¤ˆ$ÜFî‹A":¢¨zÂÆø§mg=¼8ò‚C›.\™sYû¯²X¯gðïsé;ZuÂB!$oîF,'Ùj30Þ€|ÖGã—ø‘Õ'Aê„AÊ^aD›ítà}â|sýÖß#LÝëžÎŽºë®²ÿ^ªŠý½ŸA ŒaaÉ£1@Vƒ%F"3;ê‡ð¤0 , AŠe²V£I@J`WÉa0@?ke ¶û®DÊQÔh•ÀJîReŒ[M¹)Q+V­­`X†Ë „HLˆ I$rJ–ƒéN¢kÅÌÃSÃh¸j¿5ŸÂ‡Ê†7 ç†H–ŽFFL+Š4±È~´89ô{…â¡â”Òž©B $d’€ÀmñÂfr>ks8§w‰ ã÷üŽfÇpîgtaÌàùs2N» Ud½ƒÇ+` ¿2¬Ooi$Ús§°ë4®ÁßpŸäAD{ Áå†)¶n!m©j7o¼:å©¥ €”5!b¢µ„,Æ™Ô_±øŸkðþ·GádØ'ägjZðÏvÌÑ3ŠîÆÒÛæ¢ #i6Ü(ÈÈ o„9áÝûó^WTò&¢ÔÁP’Þ½zõí+ïˆãš¢‰?šÊw]õy¿#‡¾u[ív¯àµ€a?h4ºH`§ `šjJ ‚bF4ãgžt’ —\,]äPÒ4‡gè~ÍCzWRØz¨u'~éÁÖ—!J*˜QEO¡ì} _ÔÂa|©†Q†a¾„L"˸Œ %% ªe•ij!KKBÊ5¼ëruÑ’<Ã.‡Ø„ˆŠI—>J>óÆÌn:¤Mˆžt*<¸ŒBÏZT9-îCއ£7´yÞuÝãÂ?hŸ}’3Ýýöª‰¶ûèž=±AP²Èò©÷Õq „ò’K ®Éò@¤N¤ >ïâÏÏ“Ïdr„·±Wñމ G&µ~BØ!"œ«˜rb1Ué#:q2ÉW C*äHrþ!è<ØÇZ¦¥üŒŠ\Ê·¾Cë*ï[šù!«™“$(yLbc¥sü"ù ¾ ¾FAÊ|úÿ·÷_µúý÷5v™èŸ–ÏÜOK¬êXà5EÅîä1à¹ã³þ?×/eðdоM“6þ¯4›ÃŽbQ9”Kú,ûve¦ä†\ †fLŽXÙa£P€ŠÚ@ˆ2þ!¾‘HIŸ‰éáÚ™ï¹r³á-zêno ™”¹ë ÈdFF¾ ,Ó¨Ó7!ŒT ©¬'K4ÕqoõuOQD$¯?^ö}|qeŸ|qÒˆÔ¡"úyô>·^§;lâu2Êô{8t3³dq(" Ãÿš¬ŒrOóõáí1;¶nÝÒQçì³ïJYëSìæ¶±–D:¢í4o´WJXƒ–á´Põ ‹PJjhžeˆk- c’2³Œ¶†€ 1MKªd’Ï–„S‰b `ÑÇ—Íïìûý:je5jÔiØ 0HÙÀgí]»ÿûhL7`”!Ƈkú]™$ÖfÝ·,Ú “)þWöŸCü¶ý NëÜŒh¶ÂÞã ý ¢T ‰€>µùx›êª@Ÿâèàê”â$Ak!Üdd<Ä út~t€p‡O÷<´«‰HDU,D¤¨IE<•‘@§?“™ÕPQ+ É@ÅüÅsù úGêuùƒƒ¹RS§lÍãKïÊ ³m]æë‡hcrœçg6nCgí Ÿ_(l;˜4nèæïª_½*æ¸bú)M%¦M'Ð}ŸT­H¿NOÛLÖ…HŸ?²… ùeúÝš®æáƒ—Ê¿Xݸ੉_»»g}✅N‘2ü!õ¥ð•bŠLò±Zƒ&YBsmlu·éˆsÆY~Òt ú‰—,q†cÂújÔZphß¾ùw:Ãå7±Âk$¾åýf{Êð(³&f~Æ#ˆËÙ¶tQC1ðŒ%„'ñ–„9Çd;0c¼­Í+¿BÚÞÚ”é CV8øï¿×$kã°t;wルT[Dvþ§-\c‚›?iø>ýÜ6Úµûs? —Z}ù÷\2Z[k»…1Ǧ¥Rµ;wlBf(3¸Â£û9U“ ü£á„ˆAµANC.Ä™€¡‰;§+ãþ…1:H+ÄJVQAOœDÛ"@SàÓ½ö|5±M†ôXž 0닦N9zê{]”Øü]ïrÙšs´TÓ¸l²Yšë¼[΃¬+AÓèeÙ×/P™¸Bás.?Ëú·Ü96s™M *d¾ëÓíäè–L1Ò[öÿ"ôç<éøºmÃÐ':Ø¡¤ bêQm2¤ZŠ+ΰÃ( –„'®ò>-ˆ]zà@*kšù$Ó!®ÇÛChÉö(=ø?&OËÐÕªUÐSÇ‹ðE0ëG¯}u»»ýÌãaPü)ÈgM70iýmÿÚ1GÆ×Ó³a_9ÊPîOå–æ} :…  üz_WÉè5/‚r÷j€"Âùê1mxí¡= z™P €FžÙQ:,¼¡r—’êu¿ÿÏ×É×Úb¡€¾+C“æ³¹?ÅÓÈ9Ê~—ëÓȾðèzÇ’X£GY“«^ö&÷ÁM‹Þõfõ{î$Ê¢ÀÃÞI> èîÆÁ±4³XÚÑåJ(‚“aËÄ4ļM*К)gýÏ:eÿa[Æï“¾P<ˆæøIÌ+>—¾›}Ïr4ɯ‡ûž'ú÷¿-ã='W$þwZß?æã?ÙxЈœuÅGó[_Íöz ¶Ë³üô=óøî&¯EÒôºMÜïv¨ÇA‚Vt^ `9ÌríÖ–±jcX\Æ+˜¾ƒNËt»Ù¡Å³Ñ‘U V0½ –»H®°ÝxÇÁã¸î IáäÈË,²ÁæÕ4Û³%‚{ F;8»Š lèw?‰Ø°S$“˜4IË­šÊÕ”´5«ÊÖ¿ûxtºÿ·ù·Û3_ül=Ë/éÈT=L° êžçË«ô[Õ)×òÜö~?Žkêøœ}<é2ØÓb‹l~e¸ÿSsþ¤>Ê'ºjRQ¢õ‡bV{ÝÚµ:èP®d¯–fŠ!ÆIF”fèî Lª&a·%)W‘©S9õÍ«Áä»:©°c¦õ»2‰³"¹ƒ ¦¡Ç1ZëÕ}äŠ­É {vßdQ’=mÎÖ¼0¬IÞ3 Yl\-%ª Ô²5Ïkd¹i–¨ „×€žyTš’±­`€3Qâ=«Y72nÈöa·ëšÊ–,}¦ÚmÆUO¤c"‹*ÚzÖL÷5¦BQ­Â™ÌnÖ\:R"ÃLalöÄÕË¢Y”HÚ‚ÄO˜ÊL¶ºPêž$† (iô*°$¸­¤F­‘ØÏM£1¹MQL&ŒCa²5Ð×gJf©çA¬‰][‰&b‰Q²„êÖ™‰•R8É5ô½©k£tÈîéW#=¶Û$1PÌ%Û¹u”ÞÄÇf«§Ž½õssd­î`mÅ‘ŒuÆø…êœ&CÛù§Šž¡½?¨ýaVìïVµYÌþ˜•ƒ~«ìo¯îêdÿmQ³®†*ÊÁÕ¿TÁRiYVÝýv†éäå0I³Q- 2ëÖñ nÂôç«fEo^¨ûFßJê’—9ØœÖQEæ¬U׬‘k¾.ÊÖËOèR}ü¶ÔÓþùýýcø««JÌrÌÑc±:ZÉÖ’hÏ`y.žI2a”ɧ Õ¶nÍÃ^ìe÷ÎGÚkä?¢_ð¼Ö/ìs÷ëŽð×û?Míy>¯€öŒ¶žɇ¬kYÊþ Î}^½Nv6뙫J´Õ0®¢¿[ñ ²ß.9ŠÉ¿ÝýuˆMQOIÐ2õÓòYY# [¿þµÃ †y±ß6,µFYGï”5LåA„c ˜êv®kŸJÆx Øäy± .sZÁ\Fiº£ŠÝ«q½,ÓVÊXÒ’7I¡æ{¸³ÃCDŽFËaÃ1”aPÛø˜ÇBQ™cgŒˆDD¯Ye]´t[%M/žì‹m©z~Yªü;"ñ†KðªLpmÌl·4´ê$Øàì –­-3 ”ܹLnêfí°@F1áV!PG©nÛÕ²û®´fPLNc…˜ŠOa#'’g f™Òˆ±Bº+¶…k$ºµ˜¹²Ì[xc/d¹FX¸(ÔÔ–`õÄ"%-p39YY6Î+‹uÎ11Ï|´\ŽSQ¸[\–%KYb1\ö˜ÆzT®þ”Üê¨o‰úÿkk¶ÆcFuñ™<þuÓÜëмÈÐ``¨2Ö' L¥­b«ØùmFjôX¿Š›&#orãAVMR‹E…íP¢¹Y˜r4ç‰$rÚU–BÉ–Øjµ‹ØV5¦Ü´êAš†2Îæ ,ºÑ¥PyeûÒJá›n[Rm´§’JT]fÃ$»·˜µò_&iŒL CÞå‚ ­Ó+¨ªœ(•‡ƒ\–ߦü\ê_¢'ñæã/ˆÊ+çô¿[âuUWö]ü7øo·–׋çOß’”OlI./ù¼wVPïÜo~¾»þ¿‰ëªÃ®{ø‹¿–®G† qˆ°I eñ‹Ц«qe{wrkM\cz«KDô¾…ÃJ"]iqº¬žÇ4’K-t¼\ÑÒγS%ðqLJýÏŸ¯ççÔœîÌC}#‚3TDN“À‹¯· 7_=éÛc[eŒ4šL¡àˆkÉCÅánf¸·e9¼w Ó~ã>åvY”$¦«Œh•aèíE‡ì}Ï{;ŸúÝ~oÙú=ˆûžïs>§Ûœ?…Ͽ͟cžµø>'Ììýÿ†üMôÀ'òáxß™ïz<=ïð}?/Ë{_½é:ÏÛÇÞöžÿo‡Î|?sìüàý»õ‡cÄþnw°³{ÔŸ«þ]Ξ®³Óï}?±¡ë?祹ûB$–æüš'êò_C‡“ü:…íøËý._iø¥ñ;_¯nÿîå·ßS–oŒõ{?/ô¼ÿéü[ž½r¿-{I¹žïéÇ¿r½Ä,=ãû«èÿ·kß-Éè{Ôÿo+±é»_õó>7Ðt'ÀÙÔ|>'äÿo}ê·šGÖo´~7Ÿô›šº›Ù|îÿÔ}O‹ôt?ˆíüß÷^~÷þz?ûÞö_§[È/ºøü¤û‰ÒÿK\í>³Ç÷œ¿Ïì²|/ôÿ8Dòß-þ¯ôyŸm'²ˆOSå>ÿžf§¾î÷Æþ{óýGÜó½'ºçùŸSì¼'ôO~ŸsÍþ]çUä·¸ä>_ÑÃð:Þ·sÚÉÅå}–÷ëNëeÜOaózcæ¹¾W™Áð>Ûñ»Þö¯Âô=¿ ¿ý½é»sçàÛ}ÿ×FïÊÕõ>'UøþgÔö½·ôÓê›Óóÿ~ïŠì¯a›Ýî>ÇÑû7®è»>ó¸àzΫvï.ƒÒlzN£öïýƒùœ——Ðn²¿FGÎúóØr~¿¹ê÷¾oðüï)þ~ËâþNÓêú>/èµßò}¿}é|ֹ⺯5­ó?³Çmæ'ÿ¸_kòûÍŸÕyOsOƒý¿ß¤ÿÏÁ¸½´Åäy΃×ßúOãíö>ÛØù¯Ýv¹ß«ìwÛñŸk…ê¼¶½>Ö•—3wÞþ§ëì<¯ˆè·~Ïö·Êø³WiÝCý~HDòÿ)~_Øõßuw÷ÇÅùÎóý='Óå|Œ|wGÈw|ßšêòu7ãõ~þÒyjdäÏKœì<Ÿôþª¹ o'ï™óº^kÎv_GÔÿ_=»þ?7àù->“‰ÂÍÎõþ»gì¹ò>ƒÁrWýÿÚêè”s£îú^©çt:Οƒíý¬Û®¯+¹ù«égõ^K©ë·Îõ‹®ýüg†ü¾WÙ}¯=é|±ó:^ˤì›Ýn6ÞÏÚþîç[ü{ßµ¼/5êynO´û}OH8×t}jø¯ü4»†s¯ñ<ßÕ¿ä‚'ûx‰þýûW¼x>‹³þÜ? Éõ?_ñvÒí>ß¿óžsáìùíç“í‚%ÝoMî½í®«/FÎãbÎ×Ê/=øúü_S«þT¾Óævß ³Þþÿåâ<ß¿ÜÍáÿϳ—ëþßU—þÞÓúú_ÿïñ=ßmÎmþ7˜æuüvwöäø½Ï™ÈýܦñFô~š0þŽ—kþ?ÛÄñ?½ÿHPž þÎ[Ÿ‹iÉs{×sƒ“ÿOãXìOÅòãòüœ{,ÿÙ™úû1ë¾ß ú¼ÿÎý–ïöëï7ëmxOWá1yßøë9>§èsš×'Ýx_¥«´ëü§¼ýW½×‰ûž#øûÏñòÿ¯Ýåwt½óªõ§Gþ>ϧý6¾L"~»ß»÷iïÂ%ÿøé}ïÇå¬<·«øÿ¿Ïs߀œpý¯ÉuüwÊ}Îsøõ£Äó>ÿùë{=“<§¬ÿ,¯üûÝÿmóÂ'Úü/árnÚxÏ Ôý>Ñö\?Ç~=ñÏì¸?#ãWþ_¿ózŸÑú:~óá>gõÿ׎ïðd}ÞW'àuïëÒwÌÿî~¿Óð>«Îã¹íûi»ÇuõuÆû?ÓÝüÏÄËó~Ïïiý/ò¶|ßçÍñ^‹ý{mÇŠéùÿ‘Ùv|?QÌI½þÛº÷¾·Ö?;mÕl÷\ŸãýyõùþKý}ÏzÚý^_žù?«Æ„OñWEÀñž±áä OößzŽ÷ì¶ÞO¼ý-8ù®¯Ñr_®oê·ûú/°ï!ßýóø»½ç=é¾Ç¹í:ï;•k¹þ]ïåúŸ=Êó??˜ù4{>£¨Ãã~ÿ·ûÞ;Éø¯— .Ge¶Úm_Éðrþ¿€í~W¥ýïÖÿ^ýÈOƒâ»ŽÓªõÓ¢ÿSòxÍÿ¾ñžíÑû~g³æ2½—¶æWèý]}ïQÙûÎKÙõÞüö›«ÎóÜoß!{˜î{½/ýSÉQãvž»ÖÿïÚø¼^£Œ£¬áäK_KÈöº^Û½CÍy÷Ôæ=SÂ&WÍŸ/Å7¹æ}ìò÷þ/™^ßçë|‘á÷Ö¼çÉñÝÏÿ²õ~çãhùÿkÏhûÎ'Cïr¿yÎó7:?/Ûèÿo2ý_úmùŽ{òËúŸ·÷yzøÎKí÷ý»ò|k? =|ž§þ&ó»¾CÏí|7øù¾Óóìþç±þþ#pýï¨ouî;Í?WÚ~=ÿ‘äþ7|ý¾ßØó^£¨ôž÷nÎãþ­~»¹î?ë§ôþ³åw|ŸÂáóטú‘Üð:ÞÓúï›?«ï׿·ƒã¿6SÏûoÁþZ>w…¿æþŸ‚Íû?§3ÁÓ“õ¿ÂœM§þ›¿ ú~_Ü~Ÿ‡ù}çiåÝõÚ=‡¥ù^còg~î¶Øî½çÊÈù_Ç øÿ¡Ú—eÐïü¯üý]'ö¿÷žˆˆ:¢ÿÉó=N]ÁÉöšO¯¿øŸ;ÁgsÚúNûÍø%ÑIÞûM ÷íàp7z²äv¾‘ã}¿Eó;¿Ÿü‡á®Ó¢Ìñ~#¶ßû?qØøÞùíûŸª8¿ÂŸ·Îð;oµí¼“æ¹ÏùÿW‹ç¶|—¶ì>ÖoAá}¯Uñ?ÓóCêkï:Ï/÷-èwÆš|ëÔ{ÏKüÇù‡37â÷¯[üü÷÷ãýï%÷=OŽòÛÛQç>ÿâõšÿGÎìóµ¶[¯ùð½§åå6>OüZùw>/cýþ/)ån|>.çW§û¾7ðègâœ-ûÎÍâëúßïo®ô?óÐì±~ÿÝð÷W>½ÙϬ³ésßÚÙÎýïúû\·ÄÜyœ>·Sâx.ÃÞGðpëŸ7»î¹ïqCüwÕìzOyÑzïÑsÏ êïÙä¶_Ïçû^›³øþKs¶w¢ïÞ×Ã~ë'þ[mןÐõÕ~Ûþ¾s/uùüòý¯óþ'+׎÷öúîþ_ì?¦Ïîäö½¿uÆ]ï_—îgqÞ'åmþ‡“Ú~¯³à·žÓî×ì›mì>&ûÆsý׌ӿù>×›î}½g?ã>ÿúüî§òýïÌòï?ݧþÿ>—­ü9˜ýïTÍîûØò~+’ÛýÚC‹Ùóüÿ?+÷lÜòóÚ~ÿgÎù/O'£÷›ï«ä·|ÇIâýÏ/á|ǨÒÝæy_QÈý¯~€yLýe·ü×÷lð<¤þÀþŸùó}o±Þ{Ë}ëÅp;ÀDô}wu§õº,z]ÇÌð^câêr¾ß+ú¾ŠNÖnÇkã}ßt½ž§'íäýßqÜuèÑ5môZõ~;~³Èù¹±ô¿“gôù¯)¹ô—»ÿ¯ô¾ã÷çm¼ú{ÐòtÑé>^Ç—ú»ßþÿïá÷ý½^»+¼þ­?wëõ3ÿóÇððKö¦þýwÍÜúkÝññ¿sSþ·ÛmÌŸYÿ¬r>Ãö}o™Ýó=Ÿ;NmÏ7êöÿýÈ{G¨øÈ|ݯ5ïþ·÷ð=‡¬ßxß¹ôx>#öº_)í?Ïoçºm®–Wãý¯‡Þó=Æÿà>geÓ~Ï ø¹1¶ïŸóèåÿoþ_ãgúÌ®?Àù®;ì ºßÿ}ŽŸqù7ÿ;êuÜŸ9û®üϱûøºyñæ~_ãûýæ÷ÞcÆ}¿Eó>ßüýó×·÷óžOÁúŽ7Ã~ŸÙoÎõ|ò«£û¿÷é½7ô?×Ý}.Ï÷?þë~'!OMò¾ïþåyïTí·í¾¦GÑò¹ãÒúê~÷ò¾ãÍúýŒ\Åù47Ǻë9-×Àý¾¿L¿9½çªéþÿÊ\ïø|gzÒìgMí'µÔ}Ƈ¸Ã?†öGÅúß²Ñäó{kÞÿ½ÿo1»þy}gmó<ÏôîøÏ/ຟå§ómüÁêgýœÖÏžû•›2?™ ýÛÿùŠ É2šËµ-çŸÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ›p{˜0Áçnc•ÎhÀW”#L% 5$ mN<îéöx‰lÒ%–çpÖ»·´‚OV…:¡ P UP@$9¯Z>>=¬7wtˆšÄ²k¦§w]³#®ÝÜ)[NÛ–`ŽR«Öh«±Õm`: $9ìP2 tk ÷Á Ÿuàh»…Ëɨ(Ö/€—4ï^÷É„Ÿ¾à[/£9¨ }ñgÄð4sÊúû–ÃçÕÌ{³|O|·ÝÍ÷]«·HÐ tP^ûãa7­ö|½Õ'UNÀ P<Ýsuðqï»ŽØ Ùòåçß$`½lú·u’÷ØÜù‹êò€ݦ¥ÕÇ ÞëÞÞÀ §Š¾ís"î½­$÷—ø^ïo§IïuX|MÂ…ê }×J)Jj·§ÆcÕCîï½ÊO‹Õí°¶Ð÷idi)ŸMpø}W6ªÞÌâ1ŸŒ Å®Qjè1ÔƒŽÜFŠÄd`†¢‹ÖDî¡«„Ô©…¨LLU‹T,PšBL0ÞÖÜ=¨kÓxl B"@ ·O•ôðø°' ©óëv¼/wÎ^ëÑö;'O(‹}ë/€<ãÐ ôu¶*ÚÖ±LD™ÇÇÍ{êçgGį|,zÄ÷:m×&ÍPo|Nt·Û¦¼Ì;Ë­6Ó*{á|£èSÐÒ€wÜv;=Þ›:T¹[»vpëw)À§t«ßß¾èß>™›Ûe6Ýåç´õrÖÍiç•_\—ŸovEÛ4e…€äqÙ¢…[’m«íöJAuÔN/<ã“îa”Íï|^åªúëkmm-1áÞ‡ >žöÌÛ­,•M±©#¾eê”%vŒ­VÛª:Ô×ÇÛè>æÊºûMÙ,|>VÃ;ЫëÄå/b™µj6Ç®ºY=ñ|»$’IE ¯¬S‡FØQŠ5m…êï` )ºî離^¤–Êk7¸m«Éð>pt{IknðŒóÖï $èn[¯¤“ë°òó­ßßßµØï8ɼíÌM¶±BåÑÀEE PJ(U"@ €D@ PPPU@(  GTð˜&$D@†€` “ÄÀ!“ 4Âh‰ÓF†™ †™€ 4h4M¡¦€P @€€4M42dÈÔÍLbd›AˆÓIä¤òži‘¤zdLÐ4Òx4Oi€™<#IèL“jdÍSÉ©¦4šÅ3ZêêHˆ("@uIF®ô°Ï/ïªéÀ óKqM‰â„Å"ìyz3Û1K†¯#R…§a0¨¾e¡—¿!SÍbÈÌC/ ΰ3H: |¤rÇFûò@DÝ=R'SÜL 'V‡ž”áàÍFvó˜ÂXÀ¶$áízý‹C3ÿÉ'A(à\— aÿŒ™ "²ÕkÿõÒ¬øíõmöŒÞX†OÃUo⵫Y™‚bµµ©G£-!hÌBŽÔ&‘¥%Ť£R£KRGkT…u6ÜåsŒ2o|^fq¾3Š–ó…3‡y¼3Ç÷À€W-ìíæÕ¯àD’ j2w„Q0cÀ˜Óžìa×ã¤`ïž]0ó3açýåpF籆«]L¡ûvå 3šÕ᥸žÏ¡RIòéÛyoKhXEòÐ6JˆnJˆlÕÜŠ“r)(Y_p¸f«.fµšº´©»TݾµÎ>O:ãŠo/ç1š5¾ kœµáDuœïF6ït˜ÝëY.±· 9½ozɽ{$¬ºÑkx­L:Åæê¬¯ZTZ±JÑàKÅlâŽÖª;JÕÞ&ÅfV^­/QȨµu¢§6^8ß3Y«¶ñÏ<îó¥8Ýœ¹’Bïþ¥>cñ o{§ º¸—DAó±u'H©½¿YAƒ"‘ 1ˆ Gé Ò}Ò¬PrI;ß×gQK"~}¶õûØ{ê¢EóUŸúà/IDJ{ŒZ ”ˆ€U›@ttC áÐù-Ãy™Ò6a.<ÄBÁ“‰…?5)2ØO‹M/ßýغ¾ƒ™0z9ÿW°TØÐ¤úþÕwèß‚ÿì{…žJ–¨†W©óU² ›8ŽjðÁîîãnެv´üë÷ÿ—_è¯òy›ÛÌÊdoõmÔ±òÍÒûÄÿYÖÐ)úkD)_‹OEô¡iï!C¬¥#â³áñ½]Ã!á7ʦ £³ßüËkµÿŠ¥Û4ÞïáιtU m»BÊHSÝÿ?¥]•ͦ߾­¡7Z4ŒÙóÿ »ÆÞ.ÑQ­?U)ê¶ÁßMx«Ýâ̵¥ì*ÆÈ,F˜™!‹DÈ®H$gn‚²AÒpLÉË“ÿ«Ó©3]qˤ¨w³ÈÒϹâ{ôÉÌc°†’Žå¤nH΃¢r­ÿ}øwƒ“[ôJU<¡êøª©]¸¦®á¨CþFw‰IÛi:Sj¾—DqóÕ(|M ´°HaÎÙS#¿Ÿhêæµ'T »ç¬«? ÐÉfLýFþ“z˜U0¼^«'ÌöÁòvÚ._«Ÿñ+ùR¬ÌÉ.òcN™ÙißÂÅ æNFóÊ€mêÎøQaPz/4t´Z@¼bnOíÜ£)@‘Þ¾ö‚P›š,"Ì_cƒƒIÄ%A5sž;‚Kº[æ¥$|ø®¯A¦žUì¡%FÕ1ÿÊŸ„MFÿ¬S$[ù#óYò'3ïÑ?ß#& mX9pq~5êñ§iH9Û*¸mH*Pc|LœÃø—1•ü$D.§7°Hˆ0ZXÖužéÓ&6ô6 ¬e³jã“nò¶­-JŠc'¿š^|èÆeâ„§2ƒUšO¦‘ #z|g¤YW{Ocâ?99û0'Õž«æ$ O'9_•Ž[K½:‹u †ÕX•ùåqFÄ™¬q]FžX䀮3º|gj½žæ’¥9Ö6ˆø Æ8Îp;h7E"Îþùå©guLó…U»ñŽH&AÁ¼iÑIœÊ£Â«a2TâÇš{ŠWŠõ++3Qš— ø‰m¤UX\„l0:²þŽQ<ÖÉžç쳸¸ä¿÷‚~Ç6×kȽâäsüæ Ç {RÛ’Óä9Z·'i2Ì5ïÌ—É%œÅ¢ô5K1¶Wà®éÆ>c¡.¢>:Q3*ó3!*XC±ôŸz§ü}Ê–ú½P2N#Mrª¼¤ß Àƒ *×3 M†ÿˆQ˜Û!—‘ F ŒXU̽–æÑûŒæèçƒó*ïwª :ésH%%åÂì“ °Ì™ŽWè‚,%‚dggæx¹iì-ô˜y…¯>—?6ººŠ·¾g¡!•~•p¥Ki]䉤//Ê Í5•ôç\J„€\w¡)õ!ÀÓðå{†¤Â1dˆ€’»Ì²(€Ã¤âcó?5^÷6Óéø%Ç™&¦Z§B‘‡_³j¢à¬ì8½¹Õ®¬À–«Íü†n èÉ ]Ã?Á£2ÖêëÕÖ:à7Ú2O!ˆ -E]âíZ„ñ¸•¯P=ØÔÙÇ:;*`ºE›˜ù#Y†zˆ€¹ xþnÍ#à`ù÷7£ì*k‹àÆŽ”¸0À—¹#¥+–ÔFX¥Dl5:`Œ¿Ù‡ÏR3¡#\mpaSâ×ð&:Ìj˜C†–67 î-ƒœ€í ÏQKBÀ`Ä¨Ë VÏr€8S÷„E%=×Լʕ–qÏ ‚2&W‹í²‡ãê3YvÞèzsêfÇ݇û™g]gÚívò yôÝÏ…LÓS?”Ú¹dò¸•Ϋbäíåm‘t¦Y\þMŽ-Õ¦‡­reøü¸ 3ö€ æ¨RÃrÃÿgßRÊÉ2í5Ëß§(¸DATÄDSœ MRŠM>u ©ÞóU©!îöX;N_˜û}S°Ã»ÀKsíù ÿ²gú,Óª ºD|žªä}%á3Öæä¤÷u¯ÈùüV…ŽUš^ÇBqó7i}Íîó&o &¿kT±<˜à X=¿*ŠU#+;4–¶Ç“˾_¹¨£üuR•À‚w4œ ?o ë°S!äŽljé RÖ׿ìç½½†è.,b>ûëCÒ×uýnN=œi «”w1qÛ“ÐÑk´½ÎíþöÓÓLe]VD+ý‚~ )A±ÅÏ,r &šÚÀ›M»tb¯Å òšNS|–Óoõ9ï@²w]Oé÷V¶ž+*»K)ö¿?ãÚ€œ¼KޤåïIn½–z¦îsgˆ}&$r±PO.^Y²žêYïAIaì7©?W*ý"L¤HE÷'0(ëȇþÿ§êoa^ç|.©%ZdïÌz¿ü¶в°¤KÌ—#uŠrÕx²cm¿] 7gPǾ_óüÁ ‰÷‹æU*«Å6+ÀÑ› u;’¿¹+tåDþ«Ž±‰C¼ë Au5Ì·o›tKŒ•BZªvˆ¨øä§~¢º†Ñ¿+œ…ÂØ›#m Üуƒ‘T~(¾·ÊE²ÍuŒ=·˜ö“`À%*tFG¹ji¤¯”dÀ¯¨R)`.™?xO ìÁó¬ò:¹1ªEŽ ¾¯FºƒiSFN5ÂzI"MêÆ– `ô^6EüŸëb 0埢Þ¿,™¿Â£©mõ–õ©ïà'¹õª¡Õ^l€’€¿ §ÚíNæ81†Y(9Œ‘$QDàæL(–-Óœh…ÝÝ×A`ø¦÷wáså¦IðóÂNóÞ4'@P0aˆ®‡M¾dtÇç?0›ï9 9!y~x8ÊÍ„øÙsstk[Z”%=~ J=ïæâ—ÿ* @b}I HéìP'p4¦¼¿l7ñeSË~êLJkòFGŸ™Ó囤ÙÚï– yµÈß3S£ä¢Ó”·öÛ3ƒÕ\Ø£g1nKÃÙŠ÷6ö\wóD¨3·WwvC«5³z¹iZªðzU©µ äÕ¥£¤J’ F.Ì~xQ ÿeÙ `nY Í‹ì òTt²V¸Oü›VcŸ;¤EØ5ùÂ÷í|ËÀŒt”ˆo¡ß;=ÑM«¢y{ÙpŒ|PÈèr®Y² bš!FAÜoÆ4€’í¯Ù7а†“B]‚`¸»™×3PãÀ}†%UR«Z¸¹3p¾²ØÞ0â½ßßÜvÆœEìà0z˜ÈÅ|Qìp}p\ Ž5¥€ˆC¸2=߃2’,ŽÎ”{-LA&U<%õžæ¯þÎIgˆi+/ç%U‰ål:ÎvnÁ«Nõhê%DLET 9\·e$£{¢}; ŠŸAX[°Ó‚ Óè˜l Ÿܨ_2Žþ~£Ë”x•7ÿµÅe€¢”OY3z€´nŒR¬öj°¾MY™!ì ×<ÆÌêe=øáGiU§~P¿RN©Óà/æTV`ñâ]€?…iÏó¬YC\ÞÓ?ÿ®¿» »‹VD«;ű饻`cÃ=Óô9$?W‚k Y‡ÿàqÛWXûìî÷Ùj€v›9+W6™("âCbÇ38Šæ™(ÜZ¬;må„KoeˆtEþx,í×ô×¾­®8n‚+¡ÌÜ$ ñ›ªùhVˆ‡cs1SÒ^”Îb$G¾ËpácâE»@÷íù—&{ƒmÛ#vî<hõ=r0qóÔ-au3Ö1À†ø¢ÿ£‡Vê sÀjÚÊ?†¯âöû2mÚSgNfÐWìÍ))½÷à±Í?Ã±ÂÆÊ-À3潋­¤c ÏÃnˆnÅjÐ_ ¹JÂØ·u‡ÉD؉0}i´!cr7 À³úÌQS DœožÂ¤NüË›|2³Ï¸^s­j+ŠºÅC­]‹qª‘Ç„ƒýÓ°êGÆÐ77Û]Gôo±“oz\WET¦ ĈdÜ0m£T4oùlq\"·«‘Ó[c²Wµ‚ÄÜ´ X›åàü`A;/a•ÍVØëˆl¤¦ž€WmÕ*D\^®]ÜU'£McÎþB33+rÐ7ÏxhÓê {ö™'Á·é_ía ²sR!!Ó™JèHé/G>ÝB˜!¸Rl¡l˃i"ó¬§sª%²Ý€þ9ÏÐÂý­ŒÒ;l“‡É¦ø¬'Qå>¼1%cÈäi.ý™ü#JáëZf"KIµ/­R‘ÓqGÕmV—V£B9ü‚fûÔì«d°äA÷ x;ºsLÛª]ªÈâ)¸ýnXBÀ¿šopá6–²~ûìr1Û´ÛóC ¢yØÁ.Z‹Ã³&F`qÊ“`…M”†'µ~£€ŠHú{fr7áìŠ`v¥¢]OïÃ41éf‰nF*Kñí³Ì9ζü¤Öde‡W¸¹§./ÛB¿Ë²°Ü´H5Q.n>ÊIÐQ'Ü 2—óP/„ PLóÑ”\QØÀW)E›÷çUÌ)ëXÕ]a}1HLyH’?bD¸u¯œ§Ô6L‡0žA· ,”XB››E%×pWHà½üCÖWˆ›¡¬´Bp‘÷èÃùô€È8É¥´¼ðÔq4 Ð3švÚª*ÔÐûÛÈS¯î_%2Æ–tÞj^kçâ´~zP‰öÐØÌ*îrà¯krȱøËŽ”ŸTpárø;  è öü—ò¨N qgadõûh˜)»ZRÚ îgmÃ%ÓÅ…Æ1dËCQ ‚òd6`èNR†µ‚qÖÒêP7.X•zóÂ\ì€qù0>ñYÞœœy)‰wࣚüMMõ2©õx[dg·ÞJ:]Ué]®m?3}QÑ}t(ˆ¶Ø‹£DÛÞŸ3á•Z“¢pA÷ ;½Å{îX»ÎýcÙ]Pæ¾Ð)ŽþT¡WÃìAÅùZe­:ÚÞ'ó™ Ks—ÍëÜ&{ª\Ñk.¸Ø7Ý‹Úu´ ^ö —%Ë…gDèˆ}þ¢˜K½³÷ l^¿´ê!ÜU™åèx¸‰6«Ü×ÕU*p„æš7IÅ©ši3S ÙÍDˆŸ€R·ÑÆ0¦$."~äm“a‰ r_‡Õ埸´Â2l¨òÁYs´ö ·šÞ„×E-ÆJp¨†Ü£ØP‚} ¸¦\ÓAöBÔÆÀ·yØ! ©y`銲ãFà)±à‚Ùä"[žà0>Ø× l¤>†ôn I±MR`“‚vY¨0é à4èÚp[bo2a¿³ _¿8½tXÕ6Ñ—Â[B͸ ¸A5À Xý+C]¶«IÙ(°5ö’2P5â;‡¡GczÖ#ñ†v¦„ætö±Î²ÕQûiƒ0Ý:R AdŽ’ ùçp(¼WUÛÈ¥Ô×––G?s¦ëon~cûM·© §ž÷øæ¥‡ ùZÒICm*{Žš¼ƒ#!âÕóë°òiò³.ë&óA\«×DØâM8]d@"ý²šo½6ë||ôÔXuŒ9#z+ù›:4è@y8‹éÞ[Š£gûfÛ²7}¬ïýòœœÍU¿}[N¸ÁÜ{°áyî(˜u~ÄÔŠ%R(sP®‰ÛÏy‹Š4ÅÌÄdÐ5ØÙoê¼èð©LÓUàð /$µ§©`*ÖPpT)ˆ¥½ÂÓOTÖá  {Ô Ð"tã |ríF礹ñíQC"lÃ{“érê-B¸Û[Y7ÑE`Íg˜_(!ÃA ›z$Ä»EjLä{´Ýxo¯8û³ñíUïœÇ“›¥ž,xm_7Å´÷Š@öš{ ÄŠ5ÉwÆ%¡´Ìfuîóº¬^¬ŒU÷kŽˆð•}f׊¹+ÌD¼ö/éôÉžãü—/>T°~¼Ö ïû®ÛWÛr_w}ÿOŸâôGåð…_øÒPÃþTéàp0Dˆ'¨7eÓ™·ÝÝ„uì¥üd&I¿Ks˜ˆ«×¯P-9A2yðHß9ÿøˆ€±îrÛ¯õóþçßiµ³>½‘§ÿT¦ÑQaQK´Ž ?ýwšÏÜÍÕ)OmRõÖŽè¾ëÁ³Bãû^Ï×úqíãŸñ™vÛçT8;ú]ËL§Ý,*$2Š7º\3ÊY·ã>‹}:¾Ùø7éÜ·FTÞ¢¯ôÕ0»[þ×rǾÕ×p¾åÿ ùéý‰ wº©¯ùôn¾,–m‡í§ÿŸ÷„žÇŒ>PIû\ò÷§H±DPRUŠ*­¤©™Q·Ûø’løÁ I>üˆª•€ysÏDò-®JW› R,þþo™Æ¦þU"Ê—àª@ˆ†3:9”†fïBÙï´ÔÎÞ[±¹¤Ëàó?çœÿ8`zM—Öò–®T2ûR†é<÷Äý^}ìO2Ù(z‰aˆ_úúÙ+Äpì`ÅU Àà.R÷5€¹rÖFÚ”ÞˆbYpÚaÁÈu¿óÑÿ®ptT3ý<#å{ŽëËû¾ÇŒÖgqúÎ7pAFš.áb »€(ÀÞìÁ¸RÙ»WQJ‹mµ,²Œ$N~ß·Þãl6W¿,Ù!ûÕ¡ê_ òtõ<Ï=Î BT’d€sË㸊‚öÚ ò>$ ÷y/‰çú¶Ç|2|­çQ…:”ª¸&jh¨—]—çkzYÝj ‘Ëm:¤ÂˆT°>Lxð†¨KE)*MDž÷ˤ¶çJ3ì©^,¾šbe½öň/rËÜw–«¯z\`„„BB( /H®uSŠÞÄ‘yAW|çÛFU­šªxTò÷o®¿_ÝöýšáÜ=½?žc–Šuø¼á4*‘b,Š*Å ‚!k-÷Pö¦kÍê¾ç«xjŽ¡‘>ƒò^ÿíòÝ1Ê,­×ª¹O“³L­ª´]Ão¾°ûêpÁ9ê]è¾<£–”»³]oHnû58N™µ§{[G™¦ÍÕûÚRû©–ûFMfkÒ¤I¨½ñ Ê[1„0IË> È@dd‡Äuí]xSßÞŒ$VÀ $'ÅVAdX°UË*À­ÿ/µ=ƒËì¬ÝŸrsn÷¾±bÝ~³bµq˜çÔqúþ¯~+xç 7vcŸÊMÊ•U*¦lÆáh¨©UJPÚ¼O þóºx §EýÚ²`mÊ0«Jd¨È€"}3S_6‡¸T›±>Ç×åMçnÖ­E^^О¹=Bytyóœ4jv¿»-®zBº¿©B%Ìe™w!võ[Bc ­ [raÉ.€…ƒrî[0ÛÁªpÉõ•Ç|½göEOCù[~±±Ôëc›·Õþÿq›¡× ât˜2ºÞ÷‡/{åŒbÖÂa0_Ã×R¶›¢b°î=m‹]‹Ù˜K‰"+K»3<ÉB”d©gw›YÄ*%¨“JÖâZÖ´`!%(•K%Ò÷.\¹vˆh‡uHU VyˆPȤL$¥ÒS „Âa2K¥Òétº].—K¥mŒ“ÚÓÂцÌÎ"!Ýßa2ò1¼@ , `Ül0Ã` ¥79¸’ Ë—’,1BçÍU¾‚ Ó£.þfˆ{l1T¢Š(¢Š(¤cTñå¬?ø¶Û©;Šâ¦üÛvýÕÊèp™}¯¨ãŸoçþsë‡5áÅ+JV­¥úù¿ˆ¬!áO*>w8åÔsé))ØÍîaÔËÍ=’"tónSÞª'G;ΣÚN¯/ò9¼÷ÍîçªÆ[g:q»J‹^ÿivÒèNb„zÞÒÙô¤ûÿ/uñÉTò¯ô=殸´x8ð†¯/#Ms[õh€N¼¢oùô HâÊ""T½2äÆ" ßY€ù'×>:ïsÞ 4̑ǫ]UòvdÛØþ„!íiÝaÖúWäQ³›Òñ?–‹´ý »‡ñ3ŒêG¡r±’3­’|y^މÁì8cÈyÍšR„HB r¾ÕU”K…ŸÒ—óß²··°æ^^Öõ¾Rxî$Ã)iió¢åJlSȪ"0‹˜264;‡yr≒zž—mûKS¸¤*pìug¢l½wòäï „¢(‰¾§Â"=nYm/RžËHt‘AŽ•u9áåópI,4½ÔÓ+V»Yw‚ eooÕìIÛ8)t±øŠª+ 1ƒ¬Ua†*ªªªªªª©‚¨TÅUUVûí¢VØÌ˜ìÆó:OW×z{[^È‘J‘h¥)ÐïN&烆8FÎs\÷oÎó›¶Dªh¥©ŠŒ)Nv){ZKñbö¥¥² öãŸó¸|ËH|ƒ{Ïo·¢y‚ªøü`¡Û¼ü›€½Þ=Üõ'½îTèÅúãkpOtªÝôó|´V¯w=ù9w%½|ù­ú2ËeQTñ+»32­dë€z¢‘ðg >¸|—¼t ëíee½É”e›Lë@ em8|N„í¿Îô^âµ:ŠîE¼¯«ß%Êݧ vŸÁÿLWåÅOÜõúZÌýÜÇd·å×ü¹þ¢ÉàpÏ>ƒö•øüï·Åçîs0cHBí#—{]¸Wzèü^%˜:œÀÙbâ’丒÷ò8·—ìîÙ·¡g’”а®ë™ü1AFÞ~÷?g%8<°ß¸›æ}µÒŠÆû†S„¸3ÙÈU÷÷ßÍ2Uu¯2ó­+×M;‚ʇ³*‰Ä b1€$xÝT¥É,”¥$ßkRT¤9þï;#Kw?a~ùÆðþ<­í‘ƒ5rp¶bp˜®'US@ÞÑD°Ìb`i8H”æj»>¯… ¸ d:Fëâ¸ùiýrûoÓå{qÓ€lk_‡ê&‡·ò1Œzú·NÔú:æÇ¡Ëê|G©'?ÄbçwiÝúNºÇ¶·’ýc{Ut¥ï1îÆÑOáÙV;ëe<‹æ­TïõÙÖìy¾V8o`éw}W€“Ÿ³¢g~‘Ø”«|÷è?GC©v§žã;|n wPDp´7S¡P2TU:?wù\¡-3#%éP1DìýK"&0aÍ“~ëS¿ê·¡dܡ׺s†»w=ÕŸ¾²¡ñn7¯Ã/Ôðèý'®÷÷Ãew/óy³§™z?µ›¼î¥¦d‘ÞîW§‡Д KÐ!ƒÁÕÕÞ¤z {EÓ¡¼]îwT=AŽï²·ŸïýÞüçèäÙ\Uô}OŸé·]«ä„V.{ ?5÷-^o7.×åtgTí¨f /icMZU][Øiñ|óˆO­ÞsÖ_YFC㺜ÛÉ÷¸5<©Ÿêwh‰ö]mN[Ý?WÓ=¼L±Næâ@qÛõ ¨{Õó”éуiîÌ›l5‘ÒIǪ̀[&Ÿ„ɱLH›”,0ÓS5ú¾CœËþ®†8C•Ç~Ë”žfÿÖx"÷F%Oí×íö¿mKó6õ/¶Zz:½ç‰êª¾8“ÐɪÔËNý>ócKnÞm÷?º¥O¡ÚµòpÉ×Ùþ[áByïߟ´øÞ„Ìò•>?r¨¨jˆ¸:¨±Ô³#÷õ!­­þu÷ÊŸ9“ѽ¸°¡y¤"<$Fc\ø‹Z¸þ…½Õû•áñLð<-¾Ü¢¼ÒG&^ʧÑǨ˜ÁL†'Î^þ½Ïѯ•‘¹'llWcté0¾p†¬Â‹;>“RG 'Žk†5$º:ŽÒ)5NI¸å(;NàŒLŒŠåIqÈÛ+ýÙʲùss}-é"i{í@KÒ°¿2¯ ½Åhc6ãdÕç $4¦"C”£;Þbk‰Ï~€·¸¢ÌCŠŠyÃü²ìr`™£üš»Yžã„¡ýU>®¼E0Ba}Qz¬ö¹ÈŒ±Îòê5X‹©¨ô•v!(&šX!ö™fôhìM#=ª+ôÍ,~n:Õi’Ž9"ÚÞåÛ"€Ì¨_ Da>µ±ç@/°u½¬:‚jÎ6ÍiË_â@ó¼ÿÇõ@ì(ä²MÝ)úÑ|Lª||z=áb,Q8,·“h†¹žŸ)355‹XíÓykÍÒ{ Ó@¸ÅËój¨ÊWä~›Í5ˆä:ã·_ÚWc`:ìã>o £ÑÝ@ zP‹¤æ€7/KtѱWÓæûÇÃj­¨«ñãM+ÕÔÈûlÓ*ÏÙžÉæ4ï¿eª$à c÷±0Ó£ËÃdB5eæ¦};v :¾4æ¶é˜u"ðŒ'çnZŸÃåY7ãpóÞ©F¾Bª›ðw’´}´+MÆOŽŸÓ*ÀâÁ}Ýß!¸ y‹ÅèÞF‚ø8-bOÑ(ßÕWDç{1`#Ø~XÅÑ-¸-„\ì–sÑ  ‹ƒ*ñüAnñŽ’P\ 9ÔŠ-0#M}þª¸)šN;Ñtw\F®à"›CN:"ÊÀׄ!îÔsQ—'Íü¹‹Í—ï“;z^w ×ä£Þ£"Ÿ¬¤¼pó*Rc>Q·~‹èŠC(ïAô(±‚éRÀZßUÙDRjñúÖÁÄû½²ûCFA׉U^òÞ<^ uL%°5Å­˜òÙÐin©HÊù,ªƒƒ#¬¢3_°8/cŒòá³ì»æŽrvZ`M_&CŸîÛsÍ/Ú 0yö%#NÆýYût’G¸Jx{Kukì ¶Ó”Ñ¾Š§(À¶b é»ã/µ÷DßpÑŽ¿l­:Ö¥ž—S;Š€UbÎvJžö„ÙlµÁÇûaGÍa•èòœuîžæb"ß+¸Å´ç¤ ° 1ôqf8>¨½åÿ˜ÔèbòÕÙáQ—˜[Ù%™S?à:ûOÏ¿O|ø,¶‰™ãÃ97jþÑÈæ€–á¶Þéñ‡~§aƒÖÕ‚0ÞbQAÅd¦ z¿œüÛ¼[|³$S6¸ú¸PÊb#'M-š›é­ aåpó­±sáãB—Ä,‚a’„írÂì–¿Õ¯ÞƒYû¢ûã±X÷U$÷A×aЦÌ{ö´j7ƒ'ÑsƒÜÆãŽGs™µ\ª’•6Ùéøb<Ç  ½(g¢ð†ð_ûß½PüQ+”ΗùœŽö®d„,¬3?¶"7à„6é€@2ŒèE(À¹8w(tt<¿ ¯ôÓ„°±I–:r%v>!R}×àm w2·)¨…ÃÑE¿owÄ,§fh˜nеŽ%I‡Ï Hì$XÃíÖÊ´ƒ+}¿'³Â ‹ ÿÔ•Ö[¥¶`!¹ÝθªzGˆð’Ö-;ð<Œ¤ü0ÔðåÎpöÑØ9ßøË;Òzýh˜(5 ó¸Ûôp]L ÃM¡Ä`30Êà"fÀô˜Èà³³áüX=®Éµÿ-îÿyúˆ¨2ÍÑqgõžè’0QaѳØŠñ¾Ê”#A³BQ¤¿-8e/C\¦3  ­ 1‚Ž©ÇU0{‘€¬“ñ;˜ jßÑçâs<°:ÁÕ¼Â\DŸiK’•Ö9Ûåã`H CÓ&Ã[{K¡>&¾e¿w±ÀKö„¼çÁÅ!{.Tàü Øx±NGÙõýIGÄSÝ‘_õ-™}Ò“éu‰9KÝQV· ®FÈ\ûeÅÎþë6€0Ô›)pDø}îº`ŸÆ2[°]6)Ûª<îVãøÅ´½,NLOµ6Ë ‘ÞHÓ?àbü—Ð|—§ä›Ã*¯úfSKûøvX-Ýú]Do²e)P©@N‹ˆ° »nÁiª¨Ø€o­¶ñP*kUÏÕž,e_ãÏáBÏiÝÆ'a6;çÂ*<¥/º‰Ê5éF¶´‹åKBN"P©„…ý6-aUL š jI((nùmÞž2¤['R‰[Zµý‚ÚÂÞÈ}<“Ûk•†LAZAª×h½°s‡!.Ïcú‚ËþGFÂÍôo §ìlv…D·,„zäʃjö ÍÚt°xœ#4ï-éEpqí+ýžªŸJ¬î/…ȺÍõ­·¥#N‡®‡Dõ?ÉXaþ3êŽ>-ÄmžÂ¡${Œá?´“¼MHO¹“}’6à®(;ÃyåAÛ¦+GTÙÄB‰a±h²Ž^¢iô}ß.>A[æýÝBq Z˜>ÌHdo-¬³Z/l>š@ŒÀ£™™j2#þ¶ yÞ'Cš…£• Îã7ÜÌDÊ*Kà-¹Š½»¤ß•‚3šÑ!ã–›w¯'?»z+2¦ÂД”¿‚Y郕Ð:’_¢º*…Ø3 (<¢ rN ¤•£n]`Tû(ÔKl\ ÂÌ‘¿_hˆ†³6? KÆÆü-¤(s™—ð$¯‹ƒÕY ÖiW>•f“,G;j®jŽ&˜A¬Üy´R¨D˜°4ã]ŠçA.ª ÚþÔ H¶CÀ À¹X[v=`;†ïGŸ11ëÜWlœ1‚¥ICÝV÷ZÞd×=ˆ•U–)~$•'ý;ýX)<±z¦½ˆÀ>XDxjÝNþBr êôîT4ü­Ü U IÕY’–ëç_ ¢#RÈ(Ðyÿ‡b¨WÇh Zè¨iø—‘¢v@Ì^ÿƒNŸÅEMw®)E{+Õíä¢bÙ¹ƒeËÙtèâ}úôƒ€î7Dñoï{…Êú=HóàK£¥ÂíÛƒ‰]SÎcÏ•FÛ­öZ5݃ÎP†/‡5ò€)Í?[eì¹ˇõ†+|dM;[y Ujgkg·<|×Ô¸šÅï=÷HDÕL,>9,®G|'?Ñ`¡„öCaá/¦€“ž›Äße1ɱ¢aj¦¶oлÒÜ·*€S4â)êK-‚@<ñ«¥à q ­8#› 7§b=81 =¤CŠ>\rž‹ˆ_Íx}P""ÎÇkú%ö Mr¶¼¤¼3ç[sH™¾æ^/8ä‡oT “«FAq»»“.¼\>÷(ö g N4@"¤ô½=ÄÝ”2= /Ó[RQ°Ý,XÖ»¬Á,ïìO8Í1ÆöCóŒÐÉ}ï0^Á«³s~Ì%UÑŽËéA*€xtG.!’"k”ZÀ@cˆ~hiËÑïÛЃd„U¯û+Åü°ú â ;µ¢2Ñz.–%Ñ‚ó¸{áÝñºa¢jü‘\âVq«>°[ÞíçžYÛá› xÞ3õÕ|Oƒ·V‰/<™µ`F'àÌÅ`÷f"5·=h«ôvþòâuÁâ8F)Wi×=ÆTƒ–ò6©&Qa÷ä‚|/}ô¼z¾»Õ­¦IÇd¹uÂÜ×z¨ælÁ7„–I²2¦lûU—“»{øû’¢§¯ Áà W›¹+tZă.çH*ÊÜ7軩Wê"QŠçï‡ßËÀäAŸ%Ô´è¹8šd4²ÊÑ{îI+¶^ R¢÷íãÖ"ä«¿ž­ý÷?mâg¥…U‡'ß»U~Ñ\J X9[]™äc]´¨å»ë'ÞúVé[…7k¦š€ÝCe<¤‰i´4‡äh1°!‡H’É8r?@ŸœK9ÉžÔµu{T¨ûð¾ –pO´³QB8ÖSó»‘bF$^0ûE´¯ª= 5#År`Ò*P<©@"e-†êNèípºÞÝ"õ‘fýZ·×¦Ò4¯ôxè¾±ó@‹’ 9qT)ù-h“S/ú®üÁF€öÖdÎvd±Ø7ì´þf1XøX}Ä~ÐôüFÜ1wÌ–ÓÐ?owKš">&ßfÉ÷”˜Ìùt†B.¶c9BÎÔN°-ÄÅÀ£ô<ËLšUX#”#K̆oT´ ø¨­9Ø{öèŠ]2-æâ©ñº9»Ž-`J»žÈ‚½;?= ˜u ‚VQ¯§]H…€¢½ðjy}þÛñ°ö’Ý—5œ%1A§NZù<åPݨ; >±„G±=++Ì5Lÿ¹ìat –Ð)Ë!¶¨ ¯˜/éE¯˜:bi°úD‚}‡3~Сr#!±Þë© Í& º†½5½€@ z]|-›£OÙÃß[%;Ü8Fù¯^*ßYwÈÛÞüHRÌÚ€rŠ‚Z9fXŸLAzK.xøÐ‰Hä‚§¸Ûböz$²Ç»Ó-‡ÂÊ[éÒ ä1]ywmè2x•fä|“Z«.müˆ#hi‹î…›Y¦…Þ7H› \7ŽQj^ü·o9ú^5sÿugÖ­¤ùe»ÿ¯Ä÷LyÄV$nSØÏT÷º¿‚6D ÌÄ¥lóW)¥ ;hÎz(ºK/ÒB]Ö¸:ç'”äÅþJnpò£IWs'÷rd.@f¥n‰è4áÝÑ¿2àÑ”ˆ܇)W¢¤ŽgÎr³ì€åõ RãCIbûzr=ùå¶Q©ÂaêÕ­¿Èh’$¾ (ÝI±r›èÓ>/:³® A*š¬&Ç©¥bµ_÷1–ôŠHª÷¨­“sgK¸9ƒíÇ!D³ ¢ 5s2&ãÆ=D™½Ë „¨ó路ùêD’3fç;öµv…VãM¬KûÓ;x‰ß,…ºvJãóÊ*Ê¿ãÎ –äÒ%‡de·Å\ê‹ – æÂ`i+¥¤VÛèð1ž&Æè6ÎÓ]À£†‘޶Ïb­ö?ÝáWån*[³Žë¾ƒT†o™œ°ªË©t‡+z~… ¨$« +uÊeÀÅnÙù„™{Ï´ÛF Á’Ã7(¾„$6)l¡^å¬t¡Ð›'úbÿmèDƒX»ÔXÞuG<•žR,qšðié#üµu¶·¿†ÚÉ<ݺIó/‘?FÛÍ5SÚm©¸æ/ÝÒ¢þåèÓðÛhæG~ƒbR Äz*‡÷ß-Áö.S×MHÐöâç’Š.«hÉÊ1Ô&TžØ—ÙO­D`‰fà»–G‘„øY¹óÒç4MKTPÕ¡£¸È¢;NOümzúµ1ÝO÷xCz¡^Y^L§—K1ä€dw|ÓdVœ…¾C´‘ØÌ›Ž‘½øáý)íXSoâ¬ÀÀpøÐJt„øª·ž+wüH`ÈÔÉ\žo iÞ(©ò7Á¡)5MMJobû6CÔØt*CÀŒóøUo½F×—7 ±{3)Þ^Ýa‚R¼FD’!ºðhÃËÁ€ ¬õŠ@‡ß‰}A‚Yî+éÆô·Ñ½:½™„ôcøu',Žˆœy¨”r»jC–5ÏŽ[o` ª<ŽÉFúì¤*q¤÷Öðžb© „J<¹-˜M17åÌTXVÛœ©?gP¦o>µ˳l®š>šAXéx4ÐíÙ¹cy׌¶Óà08¸JÖ{ì'.^v/.uy%¨M®WmûªJÉÏYÈw~D‚F##ÌI,å,õ4ê*ͧ‡gC—Œˆ˜è •EBd’ãwøÿ.·;Ž‚¸P†÷UBmyʼR5óÁ7 â‚vÖä¡ÈÚ“ë#Œ+z«ÉrGDö®¹(9.çl„â]Ú¥ø ÃôxR÷ªŽ¨•Œ5´˜ð¶‡Á_o+H ›‹)ß=pR:í¨Ù^r3I»$·zðöª nFéxcól“|Ý´ ;#c¼û;¾üŠÆPŒFÝ·yÄ0#»Él(B`,OÝåezWƒ‘rGù —ë(p•p1¡b4¤cЬgA»AˆwŸ‡W›Æ8N45$—Eútˆ$Ÿ4± L4õ‰Òƒš„&Ë‘¸«ž'6kq-Bï‘kü)ª»ëu R«œ×5Í ö‚?} sÅÖ.7(Ù¬¹WÓj=äï<åúÓZ]‘ÆVR5óš«íðodDtAËZ‹xàs»›•R–‹¿vžYpôVxMã‰ë_^%ê7÷ËÕfQô$z&ó&dÃ(ÄÆWzKj‡ÄcŠ-,sMÂDŠ*˜kn¿¹ýÖÈ}~41PÐ™ÂØø>n_¬¸¯Ã{Œ5(vÈ‹LŽª3OQf¦ñ·­ÜÜÂyÅ%ÉÄp7¤70¦©¸Û‘#…&Ô%‰=Ñô8ª^õM—#¦ ^éãáUÄ$-‰¼ 6[oIPCÄ7%Ó¯èCÌý_‘Å´D‹Åø.¶§D¦­»\ÃÌPH¶Ÿ Ä ãœˆéÏØœ‘ž)†ÿµ€ÂÈC=—r†ñ|ó=ŠÛ¼v dë'ÇËöFô.lìhÝÑrŽM`¢ïà)xÃÜn¥Ï$ûIVdªêÈsD«F9Fˆ$ÛšÇÊD=˜êtž O*‚ÐQ-¾™jê<›Xã)¯.§DaƒïòÂîî¬|.Q¶PíéÌvG¸tö•(£FþRÿ}ÉSÁt‘ëŠÚu—Nj}0í¡UNn͆²$?®²£éÑØP!5½xsM_Ì÷Bë¯>`á 0U‚¨vü<L4så³ÔQ8½‘HPÆ! Ý“L!V`³[¤2|ÅÿbV ºÆÚÍÓgɉÊÏs›¨zµO“³[‹nvÕP!µIíç[»Y<á)í~j¢ GÉ²Æ ®ÑKÁBÞhƒ”2 šfÓf”¾7«³;ºW]0[AÀ(³bòP`"¦VBÂ# U 4w&®jC´â$;µ;Y>Ób7ÈUɈ®â§s:»ÔЗûCq5(˺Y˜Ú€—°ìÜ5hœ@bÉXŠ¥|«ÏÖöR¶ FȾ ´ªqèºÎ_6'1’Äm‰-¾=lD¼£ÜöœüH@„§¦iN®uŠY4ó§ C4J­þˆ„z@¹>JrÒ»|n0`à–ÆK7G?ŠÀÃN,Üßaãû»ž)NŸ×¹~ïö2EÏϹQ@f†ÛTbZØ.–°òkel¯©ÊÓ×­Å&tò$ Ú3`€0¨«b…ޙ܂P·óݧëæV²W†TDfˆ4$ÄÓ£Þ*úaö‰xzHë ¿ .@@•aPTãXî X×¶ù©·0ôà­¡Ìò_Ðf6-ò¢Ož•à¢+9=fzÿÍà©ð{±‹Mã[®Öâú'ébPÙÖ€Ùæ^/¹u„lI¤Éž‡göwÀ±+ì Ú€ÿðÕ0/Þ% ãÃñOyMË Úà‹=β&.:™lD«Ìl쟷¦ø%`±^Þ„%—û—‰/§kw«,* yËQåÒûl$µg–ªnº)´möIr³÷8Ïáwä;èjàÕŸ/8M\ñÑT ÿÁaçNü4¨ΉØ=cÊ­TYÒœD¦TºÍ«ÁQB<ù%ICþÔë_ì›+õÇÌÅ¢zLbŒÓzô…ª­ýÀaù97eôaÔÉg‚×vå>A­UL#:Ot,hb,Þ®öp²H©Ì‘GnËd-n–UÍbè`3n®pŃX¬’‹j)T ëYk˜AÔÌ-ÃÊ+fó[WY¢3Ðæ¦Sƒ¯ÓÑ@'Ï’4íÀ:jœÅ^„Y1‰Œf¯ÇFV‚}îž& ¥T¥1BtóBEލ }˜-뜒% í•ø×}'T_qÒ‹&é´´¶Á IP¯t³R¡ ï »#òŠ-6,3%Ì_2"à´KBU´1™n0]Mc¶e6$ÇSßdËéPs«¨ò¶…:ÎëìF’hB´oȰDÑ”,&Î5Ö}IXƒ¿XÀ™&—òþªIt¦ó$GÕ¸Ô@ü[‚ ×ÅÝŠÏjÊh€ðÄÃLÐ~}óÅØ½Œœƒäà1òS†Çø–s±`3ÍÏÛ1¯—[Èš734‰ýr.Eb]ÜIaýž÷xFiz›â½Ä#?JxÂèŒ ¯¿¹M5ð~´žgÐÂö©‰Iâ‹~¶Û„2ìèim[ý?3á•”‡äp 1êxGZíÇiÞit‘V ‚NÔä0p¾R~zU³cONQ©F‘©‡„-Ñ@VµxF‚¢›5û¾È8.X²ž]îVÖÍáÉha©ëFȈ‰%’h» ”ÔÐpì敤¹* - g˜í ¼·žÛmW þÀÄý¥DP ¯+÷ÿµ€ž ‰êgWÆzÏ1pÿXŸûtÞΈïÑOc}\D0ÁwéHcÃÖÎÕc ±»—¤¸4€€ B ÃH5ßšñ¦0á.a¶:)þ‰Lh[¸’wûσxû×h‰ìxuC­¯Î"¡kRZZ‰·¡ˆ™*‚KøTå[ÕÊé±rHyÌ7.ñ_gÙþ;\ȼV·½µDПӑÎáýº.·£ž´ŠlѺ9dˆ²Ú[DZÁ%'Èïk\Ú \UјGæÐ’²SÏIñ`®ˆœj¢T7qŒdddFD‘R0fTQs­H¤*¢¼°æ‚`m?ÃÈØ²Þ9ýÜd²›áY$h<3« Œ‡] ;ú}`dšåë„æÙ0êL&d¦·»×Àå'Î)õýòõÆ’¸ño þ¿úúÔG†Û íW9à Äy˜‡ÓeHˆUÁÍ”eVTÞøÆHØ2à\a7—.p $t EK¥Q B2 D0YÊkýRŽP°9%Ï£¸*§páï¶$DŽêí¦³ìj –E%¾ýBÒ,H¼²Cê¸H™¡Åœé§kŒ·A0 ðÙ£J$‰3ÊÌ ¼ý(Úåü_;«¸aº+§ÑÀ‘“š&¬!`'º:6„ÔBV #b£$PQQ’’©"<¨’#Eb¬ Édˆˆ(ˆ¢²(¨ 1&2ƲB¤#,X1FH±ŒX±Q¤ …XÁAF"©c¨IAˆª$Y$E²€QDD± Ť,Æ1#5*¨« ,b E‰•’‚Š¢E!P±ÀD"Å„QH* bJŠDØÙ"%–Š,ŠÁ,¥±«,´/wIÁçôúO_Gãÿ—yóz¦»¢ Œ¨F1#1T€„#Æ;3¤YIe•,™ßF!©Ie„ŒQŒÀc¸ ª V˜”àX  ¢¨Á",bÈ ƒŒ˜Ö0FATQ`VÅB È*ÈøÒPX$ €‚¨ÄT­à$õ .=YQŒAVE(œåNÊœVw¦öÈKHº@ä“NT”¢ … éJ£‰…$˜……Îì dDÏŠš­·…ÆùÜâê&I”-²:IRS/jiê pDˆzé"°hK-KàQbMª$ÝVª¥¥[E”ªHÄFc!"„"€ÄX²)$X¨( EDR,¢¨–Ä’©jVıH*Y«¢¬‹ÒÊŠ²J²@©Q) •«%¨FDƒŒ" E Æ#A"£d‹ÌH$’žnd¡çO;ìz´ô;g°ûÀõH *ˆ {U/z嫤mc¹,ˆ©HT¢,B¥BTQ-J¢À±,²±ŒcÆ0cÆ0c! Q¹Q’KQl”¶ضªX²$PQ‹ADP@ÀñzrHŒH± HÆ2B*0¢Šª±d" UŠ¥¥ µ%¬?1„“„,CT‡ 9×Z§U¶HŽ1P9H&û¤!) Ø¢·€ÉS†³×樲_Š[„´âCYI*†ŒÀ¨ £^ãM•ŸLò°Ì˜¸:¬ I6óö‚ŒÌ/žN…:&nˆ{IYÚ•+'ÓZŸH’hx²Rt°°ãôÛÍ{¬ ø¼hÄu0ší¥Bˆ¤í™Ë“± &Û²…$}çÔN£&†Lã75 EA.8C”äâ›´¸B«IK+)…Z¸>–ÖŸz ?"†ŠxLŽ~„3*G6—ÚU)"Þ†Ò%oPŸ!‡—‹†æ!·ZùybÃÙsוõ¾/_eoËã4†€yz.žb»o+é¸l½ßzÑ,Øêî;†©ÿ½ßv„•=TUU@óåéG’Î+³_Ûz|íõ[?îq;¼¯d©ãDYó?WÚðI¯¯¨omâÚ­»Ìf?Cšgú®âôŽ›´ô#ƒ 57Ѝ¥w´S«–WA ÉwA )Üîû\êV Ž¥û*PûÎ:,Nð‡à»t‘Ì{-ÿŒòzñÕÉŠׇËçÎz™rñßÙ®kú-‹¥EñóCw~—ªüU5Ãu^‘ØŒ¥ª-)UWññ€Œæ2½ÙÞÈð£â€ˆ'©ŠÉÛ`IyëâÊ{ßnW–¢éåç)ËwÎTêu´·k ª2¤ÖåÛ¯¥Ï~„DK¨ª€«Ó¶î™ks}_v7A}•ø_Ï"Ýi@ê>ELûdžtÈ‹çä[?ïp°"tnzM6—Xš¯«Áø[îænÊ”¾¡Ž‰èáÿÝn^í»eéfá‹`c‰ØOGÔ¿œn+G’™{nÝj§ˆ ‚ €{T\Û?”³æëtAây{Â* tèª&‡fñ`~л¹™Ö!Æ%Ò‹–èÚΩšïòªª¸7)­Î âìPŒäÁÚH”“«ÙÙÛ¿wÊoŒ%ãäß4æ*¢ ;žL4šæ {»d°&lB™6u¡X£æ©Hd²÷tªwø)(é=øÙÄUˆ°0—Ë™à¿4ã¹1‚ÇXå¥qé€/ª]´[ª\Rè qÀiðÀÉ0˜L1Œ±[ÚÒ©ìÓ¨êÿ߀€îUóhŪÑE*Œ± !Z2´h’­D*ZN”ìÌðÐ!ô?•$ t—‚×~3ý g†ƒF‚¦ÎÀÐ D[õ%½ª¶ë“fŸS‰ ,¾*¿Öù{t[kh2‘hÂcŒ`$A‘{Õ•#"°R ‚Š VU‚Œ‘+‘dVŠä L#(‘–ÆJS Da”˜•g»'å÷Ô“s`ä fY k±uðç¥P ¤åß$à+«±ÍàÈ U :N•‘:M-µe„#VO.§Mãcæ’Üg_sóñ²ðî%Ü7+@J¤V$X’%K÷ ë@îBøW&P–€Ri¡DÎÏ«òˆ' 8¨v/Õ9wNsüÖ.£Ú¥|„”Pƒßö#NÈã¨þQ‡¨0ÊmŒÇ"u*A i(hDR‡=I4¾žßÐÿO|ú?C›nÜ.l]Œ‘ÅtÜÀˆ‡g÷8Çjž$ª!å;êÁêv‘‚Œ:ÃÕ“ë5ݸéÏŸ g}˜²Œ„#£ìojaH‰iFt`S5:Â(š)ãØn¿u‘tßF ©]ÆáOÉðhýçZ¡ÉN†8æS«›N¤„GñˆÜ¹ )åÑVy'ÀúˆnyØ“â¡ôݺ&ô=S裮jp /ý~= è`¢(VxâÏc>¢3~{tü_²á•Á2\ja¹£<Öù“´·,Ì…òÍ}?›Y© …ßp×'Dœ³8‡ÿT˜m9FÜZ»pEn£¶=µÂü Àµ OY6d›ù€¸^¨VÀ¸sÞ’¡’æ´)!CEª±²ø—ê I5d‹c)!„’ÄZ—1h³âñi†ºf™†e¶šØÁO¬>\âá¸`"#?ë7±9îÁÑn9vku“3‘Øíõ–ÖÛÚ+Mßfÿ=èêê)†÷¹N’6•= 7#ªgqò_]R‹’·Ñ¶YCû︶ùáí?û¿aùÿ;¯6¸ÆøÓ>enTamîø4eEË5ç3¬1nÞ·2¸t\G!vÀQÒ†šdXÆ)$DDHˆ‘’2È¢ÅEE‚‚ }_^ÎÿEz~å}wÈñýf³_2&)ÙÞ-6lØN.;õ(ì úð­öBëô+é¨%ï¹Ñ“6{§L6úK¾üžõÑ[§xtл² s[~“(E3´&^-oPW¸ûžÐÓS2³uc>†ËWÏO³aÑ×àç#vü8YV·¶$ PMät; n5qÓ d“ mÐÀˆ&Ùñãm©Í9«ÖéN[¥×–w*–mҷ¶½ypÑ®k¹È´_<Õ ×’"'áüã žó oÞí΂|?fc#>_qÐs–§‘µìý'OgØò{ëôÿ%IvyÞ(@¢¢‡]ûçü³î i§§Âîa¼®û[Õ^ï¦]œ‘qJÉà}^_\W9Éʼn٘•µ$~JÈÅy^‚~Wb[ʰ!JÃ`lNíŸÉ¼ó u|™|–O'YÝæçú'éÍþrÆþë¯kW[¬Èâœþ§ ó.Û›~noN¥±ŽÒŠs߳ñÞò÷c_FŒWÉ>É|'—Îîöôž_ 2ý7„Ê9³´Ù…ç§ -â³>ªf?ˆüÞ³”R`oó˹°4«¡ Ù*ª»ò†@0)†-€Rs[ï§³“'Ë×þ˜í‰Ã[¡e ¦µïßÍÉ*ÁD½ÎN²úbî] ñsÌw ”[¢Öª¾òmTàCl¨ o/ µQ!•´Á—•1w>wDd„™)ƒ;/ÅDbÙeLŠ?Éz}jzÿ!Úì|šê_’IónÝ<9Qºpܸ;ž5Ý4 ‹¤TGZaFæ{p6A;îR9´è:,ÇÒsˆžOövùƒyոܷ¦=Ç#]Cg\ðQÏTF Q†ôÖrq$»ÂAùNî.ú:ôx oTâ±r0£¢•†Þø(ßTF –kAGÀ@DÁ]ÚéŒ»ÂØ¤Ž|¥ú•{G7ûÃx‰ÞQ,UN.˜nÏÕó¤qR̳«·ƒ˜†½ðˆ7DAnaŽ¥4XT] (csóûnjh(J"Í*ˆ ˜lzŸ¿ý¿^ü·)Ž}뢨nVMŠB ì ‘ÎpÊ‚5ñ¾–ÏÛ˜2PM<‡®èˆ‚7ë°Ÿ#“*©ÔÁáWË ð¨¼îà¼7Çžrììlˆ›N9|ô&r)³•¹i]éÝg(¾hˆ ¸/”zÿærÚž‹µ6(¢âú_ÅÝŠ •nÐ wÀèï/Æ–ÝǯÚ`€DJ'(·iºi«ÏÒÂ}¥þä4­Ï¢íïãÝémúIC(mêÑìÚòËÁË£¹|ûÏ7Ú7Јg‘Ö/øtÀž`" «»Ç?u32|^Ö"$‚I!˜óûzº„=nèn|Þ<𛻃»/âwxüäxÔ,}òžêí?É_‹Lп³Ûæì4Y˜âˆˆjîa„5árÖç;ø}ÆôަI#ºoõÊâ_Ó¾y÷¾Åyž³ú—½ò”ðxð»ÉÐû2½æç°såðs1Œ€¬& ñ§Š0f|ó]VÐ7áëDOìû^üùÙù§ý2~‚=_C¥å+î½%§{Ý7]<ò¾îÍÏiák’¢­GgÚôƹEß¿z]n‹.°ìÈÉic:äæÛ†&ÜÌ ÉçCèØT/=’ŠlSvËóZîMVÆÝwœžeo‹xq­*µÑ‰àÉ™MuFà ”×rÅ*üZÔQèÂt.¤^.–“ƒÚ-jf®‰j,Qtç”G–2ÁIÞ¦«ÿxz ó=,nû¶qhÆýÝ B]S‡*ð×w¬«‘¶±˜Á ÎIÄ)L˜…sl¡|“(«¦%b˜<ȨN~>¦^ŠÜ¸½|³tBP¨Ã(o†*»”=‘”Z6kïùŸ?=£µÇ;‹±eæ!ä»ËåM´¥Zø¡U{U2ìMæÒ«¿¥©Áb™å)²×vŽh²¦«ÝWvÖùç ¦ËVc¹xª®Â÷ò¨Yx¯k'QÿOUé“ÍTäœ9ø|é±’çõ&Ùw„¹O¡ìé~™òå£$0RþXËù¹zøÏ,¹Ä~ýæö>£[Ìå–Gááðm\÷ Ïd;Ú7}j¼õkiQÑDß«öüòª·Äx|N‹¦ÿÓÆ“â)¥d~4r¼üª~‹È]X!¶‡›ï>›<“åúùп™F®ã³ÌG?gs¹Â™x™–ï¾–&tSUæ‚ÖÆÚü¯rù–»wW„k”JÉO~U‡Mņ×Ó;½JãÖ—îóW58†ü×v€ˆ&vß—…wËkS¤ã;÷õå!f@ìÓ™ªÔV°oä•RW©BË¢ªÛƒg¾yj2£3"9ˆðiŠ(¨Ê‚¢œì9VùmÍJª;TÛy•÷3ƒ;:y÷xã5vk¦gu³ðQCUºGz(Ñ$ITÔ7¬æÞ¯"qœçå³2ÛÒ½šçxDxÇ_‹­ïP£³ñÞ¹wDjÏ¿W<7NeãnßRk‹—Ða%L©ç÷A;~{òàEM4v-úºø! 0¨Të$„ðú¯78^© ÎU+ÓÕM`p•4Ë­äÂ2µøàôëÕÙT@á¹Ùá’hPDANØGhåNRvÔa¥ýø¾àS{µvTÚñÞó½ÂwÌ«QyË™ ­ë,/öK‘ÿ è°ÌvÜî9ÓÇ©Õ{ýð …Þ9æyç‘Í!uNGìüÎú·­Íà¬n ëÓ8F$dÜ"1Ë.þ•·@ @oáæAk.u©ÿ~ZzÞ¿~o:qhöœ>Z;÷v+µdÎmoõ:šïÞ×bÌ·Ö°ðw;°ž\¤Ûuon~wx|ÊðxåvB§˜Ûržmñæƒx¶qÅu÷K7Û ‚ø Áâp°½‡Ów ¥žJ:¥ùTz[vrg’ŠzLz˜µÙ¸˪Ïk­Ò¡~I‡ïu<]}­’y­á;^‹sõMEÜÉûJtBœÊ˜sf¬9GÛÙ¯wªW´ZÂÝ”06Ìsž¥×tªü…é»_KçŸ5£¶¡çÏ5{…¢lëÎ[ŽÞ×£+_· «è+æÖ_ìô{º–w\ep:UÕïëRˆnAë]MfÀšM†F"þô½¥Ôç™·,Ò™štÐHÆ’MòÑhIÚSÂ9Óà—¹QAWy`òª¨wºEJâ¢rQT÷:r™S’㚦æŽÍWAê"t º’£Š£÷êl‚¿-5tñ¨¶J ìÕƒvu¨Ï!ÀÇŠÇul™*&mËÂë­:§Ø±í1Ãvý;“wêìíªuOg¿k!¢KØC69·'#¸ú5ÌÙ¤Åf¦uçVDÝ}œeæ»ONã ¼|[]‹OŸgÌéÛ *éA\àrÕU‘n¦ÈpÙ¶º°¿B*WÕŽŽ36I^Ö]&äDè‚‘åm÷º§O£j8Ýïa~·,­?Ï|ým™´l»¦¬\œˆQ{NÕ/^)ªpžÌ.Á·=º=“ij?™×¿|!Ùªü×}ÔõyÐÚšÔäå³c÷d¾zç­rèã2e Ø¼sÞehÈlY³òó’©•)½Mlå~³fqz²ÆEÖù&¼Ð8W5EgÉz­B:šñ‘™ÞœæîÔj®Å¸®U:Ú¬ ª×Š« ¸«nS ™sýŸíÿ‡¡‘»m‚â§c‡‚¼Ío%éÁسl1ߺ-úG*¢X­|ùf:Ù˜ú;ãAŸ’×>ò_É¿Dºñt”Y…¶<ªoq©X´Àö%CE6Q,¦yèýôïÓÒfaV9×™l ™—9Ÿ¡N¤}ÉN*ŠŽ]ïú¢#ò­zVŠÓýs–©Ò¹ßšäZYvWZÈñÞæèóýBûºñ£ñL™Óz·[â¯hà÷É«è±ê/lÐPæRðùuk "”O5NÊë»°Ý^C&øpÖ.‡­‘®˜Ét1êïÓ(2:ZO±ÞËßu}1|Õpwâ󨹻^¥ÓÙ[ :Yy¤%;‰¹ö×,éÈSÛõ§mÞnøÙGOdéæïÛMë‡âí×Þ™A'¯š‡èw†D“™n ²&gnp´Øï­óíŒ÷: ë––éÝ-4TmÉ[ÙžwGù 1ãð2R§»RТ§kƒnçJ%˜å¢ö—æêß[–ŽÏNÍÏÏÖ,­•OÔüŸ‡Ç?(Þ;åèøµø¡Ø‘Öš£qºüP,z„­³S³ÕÁVÔlPðâ6ì¯[n1x¦<ǘK †÷qQÜzWKt0ãý_CàùŸn½“Ȩ,PöÕœèënÁÙîªTÌ©åê¹Ù¢rÔÉŠ¨Âw;%-¬–Ù{nOBPõi²” ÆØ_a»¬¿°~öüÐgàœÙ¶ßÏN>±~8Rµ1xhOÍËÌQ¹êÕWßÝxÓ×+yñ¿¡ô‘w/ Ýo–“.ÜwóÍ#3ŽIÍXÃúÜï„æ³úôÑÆ«¯™G7n¢Ãªãr{ƒ{Z œÚíçæËÍèï·Víß,-‹îw«+ pêi ýmæ|Ë“éïízù´ò×£··„íÛ—. UR©TªUJ¥)JR”©JR”J¥RضÔÏŽEK|&†²a©“*ƒQº+Äq©“­á•_=CMg:=(¶MÞî2µÍ^Åš`pêè«”Ùk ᳫäq¤jüÖ-–Cå5›…+u*%ZÆë=Œ†CU1ÔнýS{:kkŸñn÷u‹Æ=âEôæìSc3è:3*y—íçÌkCÏYõšÈqùÇò+ãz½‰TcßùÂp>RÚ›*z±I¦tuÃg×N:ÔΫOxþwú¶€{œóOfKd¼>Sc­ÃØTsqOàïwEt?´Û½éÐRSÛ°®¬/fý~–E&ÉÊÙoتB߼·WU÷sñên)¿]‘:¹ÌþE"F½›3žÕU„wƒ¥u'Zô1kZ•}‡±±O»ó<ÙceÌs‡}šÊÊu+*'–]G;=²:rÆœèvi¯n\YÔ=’¡’†Ûtsé­Ó/‘ÂeÛçX®˜ó}PSý‰ò¡¢¹óïÎÜ?î×—Ùcª™è T왢%ÅpÑD+®šÇ’…•4¿NâÝO3TeU8æh˜±Kj¥²;*öRÌêÛÚ¯–HçQÐ5¾p;7g…HRøLû¼Š¦¬Öc£ tê\á`Yݸjɲœe¡y¹-× qB)]ÕZö_žŸ ”\Á`%Ä™öyÚ§CŒôå“]s6‘½( –Jhb§¶•Ü­À-qb¯.u4b©«sMÍ^®ùAÉITDO ·Ÿt•T!UMÙ<*wU”ÈÁ·T— Ä¨2?upSdyX\åˆÌÇ›ÙiÖj×eºµèâD *Ô€h✢’SÕ3¨¶‚…¶×{ã™j˜¿,E~¶ÔuVÝD׫i)®bAeRؽa•Œ#¡kA7…ôòÖß.É:#c=éDµªLÒÂBª“D¦§ ¡K)sÐîÄ!ªçF»8oÉÈ,•˜57ºö™YÝ,¾%çz²ºðZp„–¸Ðh´áé-¨F;"•I|m»n²œù®ùçy×¥â-çÃ&p·ÝxÑåÏÕ}ƒ@¦|ÍÄ3ÃrÔäÃ: <Ñ’+‘”Um]Ñ"ìàˆ%)õXˆùüŒ(¸È¤B®¶|Éf«Einê´ËkNë½c‚ÎJRætÿÃZør-ÞhU^_CáèN[»y/SpÉM˜ž-¿rçFº<^71PÄÕ×™s>HQ(êvŠp_C:Ùj)YÛv1C±å-3˜±3<›™wKKa;ç~5¥Tî ÕË ê°3­hä+—Ï <`muA-Ç—Z©KNíŠÙuA­¤å¥4ËÁ¤ªûO¼}³êìö1¿y+ ñçðì÷+^=ˆÈË{@Þòè`ÝÏH^¹°¼)Ò…6Y ÊÕ»§#‚öuN˜/’K ª¢®mÚMÜtMx²ê›÷:Q‚¼| ¤E(›*tòÜ8KC+SšÝ¬ «nÏŒ-†'s*h®³HƒU*«³Ca}Ÿs±–çÜTUIXµ(C#2sFÐn~‚åªSžl­LéFÁ ¤Ô1N÷o»Ãy)sÙªzÊvW—-«© h©Ö¨zJ]Q-rÝ/Ì’c69Ť¥¬ŠW®…T§'éÜhŠ\tJ¥®¬¼lS¯§u_6“R]Tªsõ¡«\|âƒö3îŸ,vŽ}ÔBSžäímZ!¥ž‡{r0™ ÓÍIéú÷µOaPî{,»ýÊ.ðÙy· ½Ìráî+øÝã \ÕQW¯Î§‘ýÓËñβ{%–/ׂ\cLÄE…ˆtõý;ƒ™@Þ¨ dº£ZË`í7?:ÔëRª”¡ÚmYQŽÀQ×3w‹¨á)MMuA:™7v-ç"&x˜f5ÛOƒ|ÇÒ;èÇ^ýx*ôœvU”DÝæuw¹’ËÆµâ£v¶¬'Ìy{ 'í×09)&L ÜÈUw ã‰+Öuye×9Ñ)è*u(ÁØC.gΘŒxÓÝvÂ-L2)¿<Ö¼–ÊÕ(…ØãAº˜ëXc»…SÒÕ;ye–þfß–w<øW%B”75ÓvMJ Ý]<Õ&–æ±;wðä-Ò—Ò"@@cp—ç2HU•³Õ…©ª–TŽéÏ¡uEMÜï*ÔàsÖKñ„ãS ›þ‹÷½w- eÊW0ÅÉÓw+ ¿ƒL² \æÚ.,üDËÊ ¤sedÏFDõì7dì]øüŸnœ‚‹µï•"ûò¶òK0ª\;{ž™Û'RQ³æ¹ÚD•9•í7ë–4Kçã;o5¾\LPè‰LóÑ}_ ©ÅðÁ9ù©cR¹¬±Ó±~à°Èr+Øìa2S’¦¼Ùu5<²Ž ¾ž™NváR|¬Q üǰÙß+åMr×âp–ôèyÙvúWQGÅÁT÷ôøÞ ï[ªy«ËBå:Ž•ê{ò)uEUæ¸Ïܶ›­¼H«z­ôèU" ¯èS« Я’ x,މj¸åÆ52xâ§9ászÓÀËâïÉA36krØd»÷©DÜjw°µßð…²l¼¹¸ò"{¨&7.'ø9sœüU ýj†Áª1wÑÃÜ)çªñ¥só¨š÷8øúoÞV{}LsåzÅ·æÔ´F©êrÎÕҦśeä´ÐÍÕxŠ—¤ •x´t*oö¡µrÎ…å±,™)Gˆ×Ñ‹-UAjÛ Æ!9;mŸG–… +Vº6¢” ¹û,½+Òƒ]òŠ;º]]nÕ|6¡å¬B*ã,ßXl k@ÌõŒÞ‡f‘^T¨:‚¥šõXYEH4YŠsÓZ"Q{ ¦^4Ǭɟ¥+nUkr컄ÈM5)qxY•ÚêLe¶6£¾THèÆ·f’W²¬µoÂ-iÅfwcAʼëu…WÅM›eEy£Vl¨°-šHdXÜ̼‡œ…d_tíŒ*)¡Âö^|ÝhÖç\÷4©­«ÁÛŸ]÷²SŽ5Ž<ÜíÑ{rX7á.ºÒmg… ijŒfÌg³ö7eKç‹ôUĺ°Úq«¥ó®"4Ã#©“dý¬µË%'#8í>2»Æp›†0¢ ‚4¯<0,ôc8êøENœäÇ2äÙ)FVÔg8ðo<¡@åØò>uXQUð\Aš9:âÓj­¢|—’«›ÑúXÝš·*¾·̦Y•RWeZ3Ñ_ x·Äè<ªyW³Œ«Ü`3~ß&N€FìrhR†e9÷¹âñ±ç¯§æún*¡¦kßÐ×{̨”RÊšRÞ‰oQª÷lйó9–¹Þ´LúÆ`˹94R¨«ßwEQ‚;]új#JˆÝ/»!›o½öŸËææK_ËÑîc§§žÂì.(üÈoìG7%Fâ¯^tCÏÚý¤u_ÎjÇ“yÀ„·v2Ê,#*¢£å“ÍI~/Žý¥óú=Îǧ©ÓŸsÊw]Õ™”¨§5EK+p$îÜ}ý}O½]y;^+_ožw=~}岨‡ì!ëç¬Î»œ£ÎôY¿wDt_±¦B"ö¦2­^Æokà„š0»ºËÒ2Š”ŒŒsFnЂuUÝyÉgh·D•¢—q¸½±×"ùÝëüæQCð7rÛÒø\xïì)Ëmù7C&é3;˜ÝÙdŒ¢±v5t–'Vð¾Í},¨êŽÉÇa•L¼õÅÃ8RKl¸q[M#³s:Eñ“'!JOdA3ßÊM¾oFzŽc¦Ì&[eÕÑì e›kqÃÙßCX¯‡6Z7ºåk$k󽓱°Þèã%rÞýžíƒDTLj¦§¹ó|ªþ>;j[ÏU2”\³é@gÖ†ðy«æûñ®:ê`œØŠ ‚ûé%T†ÿ71 ­ÿ¦Þi Âs‰Çœx Wôž}ðƇ;xoß*´~Cù¨P)5bRE@è†&GPõN>‘S-ÝÃþrÎZ°~+*3󼞤"m›«'åÿÖ¡ÝMDÞ©Ä©sõÐsAïQD†0Ïq,Ill,XÁ‰P,Kb ŠJ ei¤¥)JFF2–5±‚D¬,eBÄ©Ih¡e²’Ö’•–%¤`ƶ,iÀÆ0Þ¬IÈuò›ñ|u«¹Üòy (4”=ú4/¾7}ý§S¤,TnY& Fã*`Î> ;“A¬ðP! ™ò’Ñ ½.,çýö& û bc°‹Á«ËZš›BÌ@¿àðóPVö%%h|3fÏf kh†Ò.‘*ý@0‘ßv°P¦Ñ£|êòAHNsF不jÆÁÚˆýVuj'à#¥‚àÝ€ä«ö¬Þ5˜Ú.²c$´>õ‡~³±E¿Ðß—áã(\n“hIá“ð™Ú»§Æ–Ëd3€òYàÞÇÂÁÆì ˜Ì=K“SÐ œÆŠLÕ†–dB oÖ¢Gs03ÊÑâ¸Ã4aXÙ™bÆsÐHÕ¿SmktÊ‚) Ódvž«ÍFÝ¿GÅò_·î¦F)_4 ‘›3ånæ_/Ñ1ÀŸ,1*¨‚œÞ/™™¬pž(Ù\–.ã–ªåîSöX‡.vi³D òŠ+&7+¿ÛØjî”;P&°DZþÛ½ f3Rg·L«'ÎüÕ’ã´ãÛ“ñ–²ë?@@¼öâ›O_ ~p‘ƒQŒ$_”  pDP ºîÄDJÊ¢ˆ±ÁL LZŒ]Rˆú¡ý]M+Þƒâ2.Gmôj?ª(‘çc…|ª÷âѧɘ¯ô­ÅãŠÍ]§çi÷oľw?Çêöi¥(U¸+ÿ/„ã¿äßhlÞ¼Ìq×Ôþ>¯PÂåù»ºx/`¶˜ ª‚vãºf×¶•²%­­{+£ ^¬pÇn½¡%5aTOï=¹ÿõËåÝ/vEý6§ ;,_¹ÖÕ£›•"–<æ*Ä©6ͯÅA!A'–}ˆïkÁ^·Ëóäóñv«¿^?¤ášÝþ~_·ô <)%oN¼uÛU{ph¶ÆUÚÜ^9˜¬ÕÚz©Íæq/ί3¦šR…[‚¿™Âqæuï´6o^f8ëØòjõ .^fîž Ú-¦ê" …);qºédH®´ì<®Œz±Âþe{BI¢°Š*%¼ÎrqÛ<ÇLa‘|ÆmŒ0õ_1\ì59˜}Þ©±à—1V%I¶m~@ˆ$ œÝšéýxMÞró#ÌÏ›µ¿qó8cƾgŸ‡o,yœyú;Ý.´nCuùœõr»íºrì/Í‚óHR!ôtbÛï×ĺª–Ê–Ë $ZA¡ºõ¸Žv|’EUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUY$’IŠ 4QïP¿„Öd›#À–­ ó­DK%£ÙTQAèžK©H³Ý«ge†š½Zê^Ñ V–µèöbkF§0EØè7}®¿InÏOÅËåt`(ó}/F˜Ü-ý_‰ç:žàÎËùþÇ£à½=’®Õ»OWÁóQäsaëjSÁ¹½*ƒ% ¯›|3Ý£úWPê®sª«­mÀÖstLòÆ.6%‰C1¢Å’œd¸Î‰F Àªâ°'`xúÕP@Nﬢ"úøˆüx9QĈ‚þÿ;GÓçPý3¸ÓSæO¥£6f§U¨ Nfºj j!ÌeyN¤üàX߯­do´Ô »‹çÓç¼XáÖ•ô•±&ßÔàå¼çŒ8wQåG•9•ÞN Dç:7qàsü«úð7a¾}¹³½>_øG±Çè÷}¶žæ=7îö´îjÞ”{W¹ùÝ)âõò/Álÿ‰iB|—ÚkžžÞóŠ_ÄÅܳVô¥;R8¯3ðyãLJ §>- ±ÏÑÓϯ-Lbü%§Lù+q‹RV:¸4gE0ÙtÓ=«¤º×AùìW Ô jóËZÝ}Ц×8ûí œED@dy=`UQ /Ì뫱ñ÷æ¾í•æe.^欳ÑéÍí:¾™£™úþßäüþÏ~{þß§äNjη›~gLJ?£Ž^%éo/I•ÕiÇ8çgó=:ÕÌéº7çÉtŠ‹h/šð<Þ*˜ÇÒeo2Gñâø—œ¼žO‹ÇÍ/¾JÆu›Í¬õ‰°Øˆ­d±Š‹j]êYKE-V»,ZöE³ºÕëHµš—†‡+eu¡ZÅ«Z5(‘x¥©¥YáUÙï.VKM™Þ×…áçBO†<‚DðHT-HK%UYRIE•",ˆ‰jÔ´«$-E¥¢H?LH²DN tTBÙ:-:Û4ìu+JÇîÃRMŠŽ)rÂU ©b…Š”aI(H\É(1râ•©{ \QŠ,)I,9É ‚Ä¡RƒA‹P.AaH$‚ $©$… ¨Y,ªŠ4š7nÇ=›*¹¦›±Á§'R´è$±R¤P‘J 9BÃ+R(8Ä*AR¤`qÈ R‚Š(’9cHtR HABâ” RäŠP¹$@)b¤,AQJŒAb„ bâŽAbyU€a‡*A`P€©[* P£ŽÓ€änæè@w䈲DN£¨é]I6:šu3ky§™Ws7Pà0t8´7nÙÅŒ qhÝ\\\MÍÎ.)UÐ1Í9)¦ÆïD‘º—½«Ëefur×›Þ÷U½ï{Þ"#5dW½Éóe¥i4R÷µ2šŽ`BElÙS&µ­@ÉkF™(\½e½âŠ=Ù­\Q+5­/Y‹%К­RÏtebL8ä5p³*ò´©…(b.ذø¥Û–]é?ã€ßó¸n_¡áBrÔFã÷hª{þ&ŠŠ?_ª»\I{”:ÏÕþŽ&è(ÝgÈ '˜©DQÒôœ|ıU^O…÷¹Ú+AÿL'‹ª¨ˆN‡Àî­éwÿ?Î^Ñ`_±Qû›**Š…°G•ÙìõGè´ÅèqÞ©ñ½î‡êë¯ê¿˜ÙX‚¶bÐ¥myú¶¬…´&õ67­´² !üeQ‰FzÍ®}l?])ºÃkÍò¾kåˬI9ô²ØKw{~m-ëËݲå¨*3²•¤b^ªW“ý›oÏ»^¸ :?´ç¤"×ãudh§UÊ¿gü½´”±³óÿy¨þN³ƒBƒñ…ŸQÅÛÆ%ȱF…™•R@$“Z1Äq2}Ÿú}Ú†F só’&I1¤m0ÁF=ÕËçÕsÌk¼GjÝÓ{§s§`Ÿ{ž,y¶íMRWÍÆ¢þ¶5TÅÔ`/³q:z{’ÝËgrN•3YU®—•6ìk<f†)€uÔд; ¸½'L—¬w=nÞFäX¹SêØŽß‡GÁ¼š9Š@÷Ò~{€¼¨÷d÷;ÙÜô*.nìl5~m`\Ô|èȦ•½×Ø:ø¥¼º}@í7’(qyüVಮžnšÙacå¸)ÌŸ€ÖúÈß}]¹o/ʾZ{#• ”‚C:4²ïø) iîÁ ¼–0´Z¡æ°é“:ë¨oÜ“Í,ç'ž~;¥@_=}AmX. `-VáË™ã1fö ©7VÐÛÊhW®ÍËë\ç§z{ãïåVh{ùÎkò«&Çÿb½¯žŒýfËUµŠ¤À†ãsàÖßúÖ0Î &éV¿†çÑœÔÎðd,ëIìα•~]BÛhgª±¾ê¯ˆ'3zkÄÈ ©H©!€ÊèÂm0uŠÄ³ëm`\ÎÔm .ߺjý¤SXãÿÿ€ Dõ«ÀlóžxßúÃY>ÊÌ@âŽßQí>z)w!GçÄ *OÑž¡šfè¯<ýüXiV_%¸d9VXÈsŠ»|ëlÊW¡î>Y~¬Ú]&7f]²Àž‰†N/Ùf·¨§T-:þ!ÎÇ3ƒzi$Js¹4½Jzl¸DÅ(‘ ‘ÿcV=6Áß^T”õy⌵ŽÛ’µBž¬ïu¡Wm0ëmAƒ±.KŸÚHÈ@Þ¸œ¡O˜"¬¯.ŒlF™Y¨ä]UÄ8Y}Uô¼d azœ†W›Ð½oRi@dNðXô Q õØzZ¾íáƒkú‘¿é?Ðì÷ØéŽÓ–Œ/æ8G.s›ÎÓ…d¦A)ŽŸÖGÔÀàᨓ‚|IîJ§ËÞvâ=t†ë½RÁUÕ‹8Xâ+ÐȬËL ?Ñóùùôóÿ´öû‰ôãíð1GX%:\õðë”÷ëüû{Ö»>õÖ»éêÖ7]~:ßæ÷žØþÆÌ:þG¸Ë›=3¼—è3EãKSÿl¶Žœ×ò“¨J|"ù™®Ç{eµÊCþØíZÑ7+?ÇxINõûƒeU_ëVmˆ¯²½¯ÞÕËá/ çú¸(Ä/.ï¾Þv¼ bü wCTØ%±[Í"D‰Œc+˜ó :Îö7d@æ›M<¶¡‹u€LDÂïÅú^¬¨º³|H·½®÷\°K&¹vðx¯ž&Hs| nÄì>n^Eù<‚[…~-S¶›á~Gï·Í£2o÷í1ÆHs…½\"®b/›wìï/Â$RcÆ,IÍöc8lãptR‰Òø,qÚ·Š£*q\ïáÑbÆÏ¢K…ÏBÙD^û´§„õ®,I±}Mo+ÚØªF1Œ ay|ä"ˆúk‹Â) csÏ„ÛéÖå^©½éœ@À@k·Xp@ AuaVÉ%>ÅæÖ¼xsN ×~«aÁohïþØ%àó¾\] |½â-¡Ð ñbʵQÃ[.桵I?¡ÿ^Êó’ ÿös-Ý#ÏÞ`%Ñ.È}WÞ]A\Õ÷£¦I^‡Õ.|…:ó+ûž–ö„Ápò{ƒýª:íÑî"œw àn+&ŒKJ nàØÔ]åSç“`Kû=¸)Æ­¢’=W¶L@Ÿ7@¶þòyìCP:é if£²Ó¿È„:N)ÏOµm(x6žlCk+áªä«YÛ©½º|z oj†Š*#íMé§X]km¼6혲كÌZ¼x‚N…+,fâ !ÄJƒvd'M³ ÉoXÎOHT•Œ .УDWŠ/ qk‹È"@HØ"g"H×ã õˆ6«À•ñé¸Fïícé&7fytÝ/5çŸMy»FQ‚#d›4²4¼]|÷m)°ŠðQ^s±èÌ"°¹ bö"ˆã)pÎ~ß?F*³s !2EÌ—™>‚OKðíaÖ-€C5†]Æ kJ¾x¹›#¯ÛÁ¨ˆ^ïµ¶â¨^ ¼:½~ëyt¼ßêƒSñ74ZÊz¾{A>žè^úw áù¹ÝÖ*Ü…ì(-oIv»r„ù9OÆßÛš'PÛu7göÄl ÃLRš+‘µ‹ ³T Ìl:ÉcŠ&#,®¹9$Fq4Ó‰IÍ—\=®9Õ^ð°«éãYéø+í ½WaZ»$YýªI¤©9}€Ì»¤4"N¥G#Têw®QŽ:•'Žp˜Ý-q bKJf?ó²eNòà¡6iPbÖ\ÿLq‹õZ.ž/Í¿u/é`(ÌÙÊvPdüüÖr”iÿrç‹ük3öÙóE]MF7£À¥¿"ªÆz2*¶Òÿƒ‚-+c­Œ¸Ö«o%#ôΜ6ß¾f“ŽÆƒ!¬Æïõj_aÇZ%qš0Û ÿ"¡ G×{–ÕsÈòmbçë÷7a:¿É¬åçÓú?Éóò(gýÿØGòÝõ­¨lNîHÞ“çRžÚЮ^Ÿ[Q½#ºÐeN+ÖPl@& Þ" ï~MŒë¹Ÿµûx_CÓÍwÝþÛ¿ºãw=úôzÖèÏ0 öÏ%sÒ`Vn~w= c:¹å%a·ôß u>ÕãééÕ?ýx>™‹F@ 1Œ˜‚uÏú!î$Úle!‹ ªnmÇ3&âÁ#Ý_É7¢–Ú‰ Mµa–±LË™ÿ^º£Ð[{½¨ùl#ùÓñ€Ï=èQªð Ag·ò:Ù äÓÌðä[Ã,?[ñ¹R£dõýFzõÜÏĦ %‰ÍòžL¶ Â8TÀ8~AøGìKñÔÚ¯–ОuÉÃ@Àó P—" žÛ12»N4ÛÃ?%>¶º³{&ÃÎÇC4I[àŽ ü•iÂÏ~ÒP¦^½?dÑÔGd Ǫ̀¤  ,x4(q;À3]sfŸÏ{=Y `˜az+_Ûö0–Çó¢ôÙ+ƒì*’,6ÄA´]ž;r¶ëÜ.Î:à°ú-–Ô)›?OÑØV"*%z›-rÝÁ@ª¶‰@ßx´RºX‰ü?É;°~CG¶™½o}j—¡«>¨ÕØ‘ªD†g‰·@uð›Ô ™: uùR£•èÂCJÅšÙEìÀŰdYMYDœ"?#å°Mú¶ü±VVr>†š"1oºü†5Šs*‡òÚÔÆ4ñæ†òÕœ½§Ô醃þY;~ÜÚ†(ˆÈŠ>Ø(gÁº´EBï²,Ø!³Y=‘"…%S~Ðý' šv‚1¼44ÿ¨~Ü\cªÖíYæ1e™l! "Ü÷"/q wwÉíÐ÷¨–›q=°îÈijÊz#ôÃu&Ï1ôv\ìšz±QM¥Â÷´Ãa;Ñ´”XÝê|9õqíl§’¦uŽS—^åóÚä[ö~/‰Ó|áj¡ßT(˜x6Wb ã œ‘ÁØ]‹¹*òiµhðú(&¡W¿WŒë­šLàh@HÀ¿§²ç:U­ –þŸqï5‡¹)ø¼¦w“˜`3ANø€tI!÷¾zbÉ4YXœ–‹ýÓë¬ 8ˆ„!ãñw¼ây$PTI'yË]›8YKQç¿+l¯ãZûÉÓ³cỚʱ÷=ýl>ÝŒ($Š‚$=>ßr)–IùUÏ-7pk ,KHN‚PÅU²IÚ± ¨rãƒGS}#®ŸÒgNºye¿0¼´‰e%w\âØÈ†»'ˆmR"Á:]x=Nšƒ2 ¢pQ-$ßL°&4€…¸(Ooý3²¾¬KêÏ.gÁ†,í¼>JóšZŒï s3/9\ÿþ¡ø«LÁ,ŠÁELŒ‰Õm‰4¤ðÞ½Ìׯá<ÛGwkd‘Æ’Z*ÕèÇ:;® T¥*JGDo¾Í–KRÈ7£E’’z}oZ÷qêã86Î;et)d ,„ÑË…ß|€×V!UüÌãÒ”RŒâÞ‚¸2š`DÌTPÉßg®ùL¢wh!Ùyæ--bÓ Y×¾ƒwW-~&Îõl™1(ÄÅ¥÷o (~óÈãåʆe¿Æý@ÐTa7)ÆP(* ÇTvYÎv€Â(Ѝ”ÿ ÅŠ[yþ“ÀÈPt¿_Äü_7ù¿±þ~g×(—ôž†À2«Aßøªî…ån¡H=î¦'åî´ZKÚÌzŸ/FúJu¢Â´§rú¾‹ç·}÷±¶WSà´ýOkÜ·„U*ÞÁz»ñÊKðz±üϲô;Öö<ßÒ¸®îîôMüÜ_`ç”î©Æ³9×I?õãÖe.]Mø:€ïü¨8–ÐvÂ[ß‚Øñ†‰íűƒ¹»áÿå…§ÏtúÛq{eÀ4ü]wõòè°{JÐþÏW/mô™ïí0SŸá› ôê°•Mج¼Ôs#®RbÁŸë#^DךæN–Vù%¯Gÿ áýw¾ÿµK—1ÿŽ7îüN³JÝå‰R·,v5”‰ì2Û¯¢hXû¦9™xƒ@1 YP À`Ny á± Ÿ-åáœq¯=™VæÊ7 ýŠYv_¨^†›U]_-‰ˆ;­¦u[À|Õ)ðÓ“õ‡Ý™/ƒ–ÓÔ?Þ>·òÿþa°ó=\„RçQÓÖûwÝî®bü?jüôµí…¾ó$ÓÉñ¾i¸ú{öù[Jý3 ½mDÝ%ãìÏS‰3f$9?˜ETY²‰¤ù®÷0|ï@-°Î¢Ô®\XÔó<À÷R\ú ƒ®¾Ç>è>¨[¨ç-þ˜N>°§~–rE@@æ háCvñ› Ún×/ió8ˆâiMgŒê ¦û ilÁ›&ånlUt"¢¨d¯db…Ñ·÷nþqfüe¢†K–>`xSÛ©ÿ”?Ô÷ö5K²^ r>îš}DSq8#"JËÅK;i—.ƒP‰êdAa‘ƒ|K +<¾¶Ç„þïnæ±ESùÊ ¦‡ò³ä;\ejYœ§¹I¹ùë[|ß-:ÏS›ŒŸ¦Ý[¶ÿl=T ïÐÏxX €4{l³*<µ|v9aˆ…~ljŽÇF·¬’<¡ã¾qÓ6‚ð‰l/°&©"¢ÕQ£Žv ÿó›.ûܵ)x°ºØ¤ùw×h”y–¨²Ìc´ù8ëÿéqÖô«úÛÚ ¾RrÆŸH¹Î`ÖìŸ?¤ŒD[wÔoJ©ï¤ö^nÕ \-1ÖF‹Â8uÏÐÛÐ*ˆƒ$eXR–äêd's§Ô"‚és#„¿Üûƒ²ö¸5>Vc¦Ý8ÌÌð4 ž 4…X4¨c c/Ëvþöþ熜J©UUcv4)ŸÒvSfï,þá_ ‡ýÿ/‡.[nv>¿Ãš<“Âðᥠ¤"¬"C Ë~Mœ…"°©¥ªV„CDA9œ¢¹g÷Ç£´Ìètõ›ÙçádÁ¼(_¯u»Ý¿y¬ðIàódV/Ìškï÷©12÷¦°[uŒ[ä2ºl ±± ]üÊßÔö·O>øóEñöyi@Ð=6jø´öþ×}/ªzž‚²â=M—Ý×îÙnѾA³†_å Í™ûºtg+¿÷é¿/ÜÛÚö+ýMÍíý¯»¯)ëy^×—òƒßsé^¾Ý¯¹Z¢oê®ÿ‘)ص³Ý§^+ç—'®Ãµ Š?–œ<ô7ÏžQøS3­—â(w©Œl­¿vßC-óöhhuìþTúôI&bªª°)Üc™¡6(•)Sb¶Ð’`Ëoé¿g¯LãÅ|°š Óªª¥,¶44”6S PQ†ƒÒ7C¹?Bœë»ÆØV_•–õ{g›í¡·­ƒ%VEHT‰Õ8v&7d¨¼8¹?¢cÖ2€²òŠÜ¤¦¢¥'va%ågå/ç^e^ôâø¾›g}sdot…=È"¤ñÀê‰ rºí UáÒ”"Ï®¥ÇÊzg”ÜÅ—³É7ù«¿‰ÐmÿGGæ)ïúÎÒõsw úy~¡XO‡ïùs¬lÖ¼?4Þ W£EÖSç—v¸ÊÄl»û·¯,[#¨åñéÊÞÓ£ÜÇ E?UÝçp-€>ºKË^–gY'kžhzv2¹ÎŸ—Õ"+ÒîO”)$§1Ç9ÁÎq¤›=Ê kMµàŸð"¨ßš~aõf4maZ]ÝU™•}™Þ?¢Vô;DѾº(ˆ¹m‚SÙ¥ -¶¡Â³æÅ&wgbÛ×Ðc`â9 \MÛ0ë`ÎÊp¿k|‚ÛJ;ÞÕUZÀë&„Âa0”OtL&“¾L&Ä)6&í›ÉD¤ØšL4M ¤(Ô“dŠJ˜MÍ ØMÉZ&‰Œh”š&‰‚˜”bUT¦)JU¢ŠR0à ŤȚ6 Fƒ BZ*Ðÿ¹Ÿ"ñ¾ ©ðù©>Fÿ¢¼>ÂoR)”˜N’R))4M4¤ÓHŒ4hš$Á4Mš ¢a4M ¢i%Ri¤4hÄ’¹ã Ã!*•F±‰¬š!¤RS©‰…Rª1¼Cscb¡E hJ0¥ ’°¦I¸”Ú›ÛQ­²IlÆÃF‘Š˜Æ&”hÍ&403Q&¦m €‡:Þî:5@) O•0xJ $8N¯Õ 2UõþŸUV{?çsÌH⥽BÂ0s—î»D†Ï{ìt×±|kÖ+&õdûÃlKs1KŽ|àFßJC#]·Låy¡9ã‘¥ú¢øuV ÍM‡uÈ’ôGN˜SΉh£šcòuÄ8ÏnÃü3ÝýŸlãrÅífmøNÑüC7þ£Îøétêê¬+“B¤±ZÞf^­jÕøÐYmøþۛݒʳaîöŒ•ä›Â¥t’1ÃIU­hç–Zy~»û°üy‡AEE¹ +nz*>æµ79rÑ%Y,¬RÞïy]†fxXߘ¸I`‹W®J‘'f|ó—ž5xÉò†ng™–wÃsg‡säòµùpçuNÒQFƒ †ßW¯:xL®³M¨å扈m&ã²âv+¿ü?C\ÔÂå‡!5mWÍ +®6µ7íé[+ X@@®·—ugWÉèí‰lå•]ÞHHã‡!vYô°ö(Ìök×(ÙÈÔôfDM‘œtzäÐýÚB¯ý^@?À{«ý×gí¸Ôë9Å„òMÜwè,nþš ßÑá&Åe y™h>~^“Pmʈ“ÖÆƒ’ow{`¨‘áìø`^´ïŸŒu¶¿¤­[ œAƒÞ¸£È™P5?;áwç¨]Q=¦â×ã¿yä¥×ÓT±hûÿGÞ訹ŒÊ¹þ/ý·Ÿ¶L»ïe”´]´½×S©‡ŒÅÞ+9DmŸVʸަžÛS[}ã]êë%TÀÄ‘RÑxRªâV)dL¨È‘ IŸ•B}N¾_Ïæp:á?D½²ËÇKÏOÏÐ:5×Ï/g<EC|ÔH‰¡(„D2Å57®·ÎJ_”Ö¼¸tÐþUìÿvª€`0:€ª˜Èco¾g¿׺kÕ ×Š:RwÓ/['†¾nð –ø~e"õÿ/ÕàòõNËi”/i–h&éû98\‡×Þ›0«q]"wÏæùØãâÓ%sî3QÄarWÜoþæ²ãÃYŒñ¡=™zNüVt .ÞøÑ)Œ;µBÚ%ûãN€V<\=Ž=“Ê]ý…ÑñH# PqxõôXŸÁë-EåÞŽ3§qMŸfÛ.±=FBl³Âgh̵¤ ´ „(Óßúkôtþ6L}D/S^s#î$7 aÙVÅEùÇý%îp*^Åøp ç÷| ûC~Ë'ÚmÊß·þ•²¾”É ¬u µsŸËü2|[ÞÿáÙnºQá8RJ:KD º@.m1"  ¤,d}úßõ©ïð7l št|K ÈÀB äHu€ 7ø< T#Ât`Q€,m·ï»~÷çq8ïç;ûCƒyaÛMå uHR‡½þW¯­t×L;¥c½2w]›]Hɽ­¦ŠÌ#ˆÊ‰jɈBÈø§ÓRLCA‘Šö¿ºsÞÙÔrè‚ ãó>â>ÿ>šOM£‚ ‚z^f¬@cÕèHz'äíÛŽ½ÿiÚÑÿPw Xìý³qŸ¯í_¹9/Ô}4¹ôÚØ=¡;G9Úö‹âCÏ 'o¹ßùµ:"ÞuÔÕ%á’”dë/AËHómò¸·#-Ýß&»×+]iÍ›“|ò´0¾*9ÏV0ËŽý‚~Ó:p¦àðóÑ8v¼¾îÜ6Ç¡›ã™yÎâ¡è'»ä#¹3dG Æøè:‰Ü¿^9êsÓ›Ñ:6çóC–òRݶn¿>ÝzñoKä_×bо[ƒÛ^§¥Ó‚öøkèV MÍZÐç{³ù^c,¼9côzo®4hU-nc›®‚Å_€Ç6¯*‹ŠS^n å½| ¶™}Æl[½Åt¬jÍÃx®ÔQË÷&*‹MïéÕÖ|Û¥‘­nÜù » Ãú^爯»äÚØëÖ!„µ#õ/m”PëQRèéë—,RìÝ.ÑÜößÃ4-!‰‰LT˜öJ>Ïq&ËWe±&i—³Ü~_æ³ñâýŽ'Êäš6€6åÔJJF³]J'K$bZ)!e¥‘Ƕ9ÏñÈô§Çþ®K€ú˜uû‰g€„òËg·u~túïªú‡Ñy:ž±Ùñôé¦b½½0Ö¿÷=O›¿–tÑÞŸ¡çÿÎr.Òv­çZŠ"®¨Rl¶}…KnS|ßrïˆÜ°_û~¬+X22ögÈOX½¾O´¦j MÇÓ™–u… ˆ…-!Hª(ÈÆé™"'–ÙÁeö,«" ªŸ:ë `[H1 ˆŒ* (!ÙlðI.÷†2rç^Á¥é.vorÓ4ŸuÓ5ãÊŽO9£œï‰ö*Â"ÆA@Y@•Œßºt{JPùCÛ7Ì…y1”:?è}Ãy)ì·ÒÉF»»Œ;xÜ L(ªÿÞý,Æõ³²_7~¾?ûóbŠŒ ²£»"2§¶wrÌ×cwTGØs÷ë µýú/Lí\©ßfœ·Þèk\g†|L5ö¯Ý'ðúíQŒ+ Âa•dO¬\ÿ¤\`yc¸5†¡gÎUr{07}(dfˆŠXDœÊá†Å¯‚ DöPÆ B]„@áC¸™mÆ"DÛ r›yR/ïrK‚Ù1bá€V6¤ÕûÕJ§œçŸ79uî4¯ì­«‹IÜK{®ck€ç²o”ᙞ BæXy Õ–m•Q8ƒÊe›¥B<+H . · SzÕ•¨¿.hoddÆïþíÞG,CÉÇÐä÷´¸Añ±AOÅü²‹¦<ÐÕÏ#­îµÁÓ¥nœÃMònÚÌ[¦:ÙtS>‘P%Ã\~Ð@²—7c.Åܼq®f[ó’u ím.é"Rcš. 'úЙÁ.<“õ¥^ƒ4ø>­4j…e@"ÂG'€¿b•; ’ö ^Ž1¶†Ã—Üp«Â¡¡Öˆ0¢ 0Á§3­œ%@ç-˜|úÔw±OÊì“ìu{XB^·%R²˜J‡Ýý˜ê…B-Æýée…ë,|x9üÿŸë~ìÃ#2Š÷“:#pé!¢¶Ç =³ÚÆòšnæA6Áã§ì*¾sD#Ô·8¶”î³Á,K(æ\øï*øñÆèònšÄÍB—ßÿ^$íXÜ·ôÊHšpƒÔì°{&î/Œ o¢ô€ÈA$1ðÂ!„×ߨS-hó„:Çt#?8D¸˜Á?Ló6ï€-Ü·ﯠY^õÊBœpñ{kñÎok¯08¨ ÂaÃÇUúùÆŠìëø,dL²óiAÿðƒxg¿žzàíúï•Ëökhšˆ ¾'“ç>}ˆx?T?ûÁÔó6_Ãöz ¶Îèëå?7sü¸‹¦ö+¤™DT$YT((ªªª°„‚Å€@’H‚ŸHèµU ùll•À•ZˆRÊQ°R±ü6ŠX ŠÆ¿Çoûæ?KBòÂ>'?¸ûOÕ. ó 4.}PQ´!·Š2HÆd’I± ðKÆÂ# ?‘`Æ „X*ÉbÀŒD²ZZ\Ånaªˆb!õT@ ~FŒS8h D©è0*.ãº.×òt€£¾sÀ£ö¹üa8ÿ9C4©Ã”|‰„_¾K…H¯›#â8 £ZLöˆæÖéÑXâÀŠå e-Ë‚ØY*³>dzõÿGø<¿Úé?·¹áÇ“¢3}Êþ·ËGµ¯I¤:ÐT¯ÙÏ8 ¡½‹Õ‘mq°¿Z .KÍÞnø¢ªI3‹ÿ*H¯c6µwçÆ2Ïqü]ôà“áÍôã²²'`à ¬À'0ˆ› €O¦¬­r9û‡×&egjôKœ—škx‘b"¯Ú£ŽìÃöÍ»–¬b°Àêó]HTñ´ñlI—ª˜\d<LûCÔ€Ûk‰s#8«vaóÿÃI«ôœáQöb£øûÎÀáF¬V/WÌøØ!ä†|($Ç•Z"“=XÝôÏì÷J«ÄÔŽs#Ï'¬ÑN&p? ¶*iâw¤¾-Œ­ÊÔ¥"jÊj¼û†–Û}çÐÝg}Ë ÎïuÕ’œâx%¶9ï:´fz®bGe°"!`,h²¨o%o ÷¯/œÆÑÆÃ6;%*\1ßtkyaŽLS€D X"FP ¨7æ®Î^´X†U½–jàK¯›E.åwaµvþëúzðµŸÜe3fÑ›í_>eiã•fp¿¿„­2âßIîѱzå-Ï×v¶YYþ?Ìñ UáÑüg¶|´Ýu'~OÔ¯~s÷¨íÓhèåôf_ÊÖóúÝ¿}Þ÷Y2›Íßw©^)ÚÝêã“É~ÜkõÔq*-1“¤[@èÆU\:M ó% PLµBäåÕþp>Tû¼F«ev‚É`6ÚÞ¶¿WÒ×ô³Wp|NMÈ>“c雼Fq0T$îЪˆ$Ò ¡ôê ‹Ÿçþ½Òûé¸hgãïOÓg‹×Ý-vÇ’Ü6ù ÇÁ÷þÓ8àtñz.ËE÷+ùþâã¬çÕÐî_§˜ž+­UUJ8Ð+ðÅU˜­]NúLnþkfI‘™ÝKEÐ^zŒ¡¦LSEãzцó ’±…¨Ú©?e-B(ò4Ô½×ìTäÕ¿oû½™Î:5ŠËRÎÒ _ʈJMi•ò¨…R¯öADBˆñ7¢DBƒË¢EŒè€êˆ’!/B@‡³ ;Ö°íÿÅ¢"…†DBlØUÍU]ówl·X#ä–Ú¥j±ÜéP£!þU}õ@×-å Fde]V´RÅymQPQ»_9›«.*€ÇµªfÍ×UYÑ|뮬Êßñÿ»ëüµMAx0‰ž[cGÓ]ïb_"‘™ãî$“¤×5%8ì•*ˆHu6*Ùi»Z]Gè\¹~B]eÇJÖ®" †b‚ Ô&wÚÕn¢ ¨8*PËø[óL³+[Jáðï'Öý_söºÿü~/yìlÞécÕù9JÛÝû»G±e¬•ç[³ƒ®%ÙÊŽ i[¶VæŸþ5z¯Š÷Þƒiå÷¡ÈŸÚÆ¡TÂÔì#à¢@O’ýàÀ&Ô"A­¼±‘ #ÔÄw2élÝÜü "õÇ=÷|ƒ¸¼…¾(käw2²AE#‚á‘¿ÎôV ÌCåN‡ËTF£ˆ¨ñ-H J€£Ð*#h¨QÎ0ã—æ>käÙ[â·½…ùƒã9òñ«J«üÓDYáæô[Í‹Mk¤5an­6V½ZÔ¥akH™Õbïi‡´Re«¤Ì•Þ÷ÞU›Vµï³&‡Í:®|¬ÃÛºe)f†L¥µÅ"¥S›æ©!UÏ-ôÌŒÌì{g©’YÒoS,óÌ'=Œ¢427A°@µW¡móBcwÏõÛÇPDø=]îÇu•NäB«G{¸ì>OÞu­!›½7­­[Õ!¢. ꈭz٦ʔ½‚IU´£ÂÖ&Œ¯k‹-KVä ¬t&…V°Õ­å^Ì<–ß—ªWŠâ¦‹Zzîõ;‚†ƒØé‡DyOÓö~—  #  ìrÒß/4û»ð.^â9-:Ö:f>Å,ãíïוà{ðWVK~FÆ£—ÎI3Œs÷#šçX÷Dîfù3žÍKe¿°Xê\˜ ŠˆtžøX–vìþ[÷Ó–‚ˆÁ)岃ØïP³#gãùüš¾]bxqú‡" ^©pDCضÅ{yà[Yøó¥UÅ¡¥á~ƒïgÕHÖ¸øT@ÊÄ^žÙôi€Ò1HÀSóD ß6'°ý'¥÷£÷;oE¸ï¹tG‹ë²½ý=ßÒ;ý·ß÷\f‹o£eBU ÃVIHÄ„_¿ß¶" ‚2 ±?[ýËôÿê}îp£ÓÂà"(ˆ",ÿvÕRÎÆ?Ó¹»D' Qˆ ×²…Büiâ¨1Á =‡ƒKÀH xQ¡íFÚpå%HP~Ï_¬ÝúîÖ½Ô+;šKkI;š?á8å+ZÀÍÅhÿ³I*+ WVuo¶vx(X´EÙQï,Ô¥­Vf¥Z,ö-jïZÊ®¯‹UÉ{Ý™U_¶QÆ\^kxõ=¬¿¡edUvl:¹g#î_ •Ÿ6{SEúJ…ª)2ÅböF{¶YZŠ=Ø´Hê`«ÕH¥°ö¥(ë £¨™Ã–"«XqÇb!ÝYhc Ê´µ-¦Ú¤Ù¼©œï•åÙNuÆù6ï3¡¾z¨Þ9·“/ ²ŽÖºÒ®ÎªìÖ‡Êi5k.KÚ)ˆ+X’£U¢ge¡FUUF‰QÝéfj»«½‹ÑKÕl×z¼ÜVe•yñýn+b]ñ”Le%˜Â,Í*ìë›<3Ä:ƒ#DD)f…†™íJ-¬¤[Y\¦bæ®ÕfV·ã­"‹0«At³’²™a¿™Øí!ü]ãñ_‡‹øH„ƒíuãÒ@Å„„¿µÂ G¾ (ÕDk¡™Uøñ{18.Úÿ¥º"#ÁyÇÊÐÈå>]áA÷‚qœ]@">ùÙÕO% 3»99J¼Ÿ»B¬ã> ` L!ËJô¼—Œ!õõ Ú%bY™´í™ù¯ÊTk¬z EÖ/þì;*ü[pZ² ‚ùÃkØh”£õÓïû½Ž³¬5úHˆ‡ …ñZú ˆ[ºãù0ì©ZL$ê¯8\?½–~Û-wÛ£ %ÌÖòå¡Öì{L»/íÆï,ìµÓܰîQâÓB–X9ä꨿¯|gƶ~ME7ãگΣ(è”®Í ~ŠN­}#y;˜®£j˜6ñ?eQÍøàæåsHCÞa𳵝 6ü¹›m*ߦu ›ïj­Ôãí4­.:NðD@€Áe{û›úóõø6Ó÷u@²ƒò9㕺¸a«Ï;ûtÙ!Ãeü.’Ì–§º²Êê,álö‘ÖB\—$Œ’]]àÃŒH˜Sß>2Lvl0àMIÕ" ä !y¨sb’yõ»/êíK£¾yV][½ßo‹“Ýñ¹÷åt·_¡ßûýûgÜMߘë¼V½×ÃÒ[ÁVÂGNírmÄ 6– ‰lPÛÜ$m¼ CmÒÜj–FžP¬ îm¸ÏwCWp½HV¤ª ªö~ëãQý+ŒED/†#'´f—µ¿3éš*ªÁåm»Ü¿åùÉöÌVyuB""éæÞ»:{Kk'}Íó³Âeøõ“‚tÓp¹¸\/NFz*›Øôò&ª›ZíëJnr›zý,þhÛr˜YµŒ‡ ´ßú¬8°LXYTT6Te=¢·ê!…]jL-e^)jiE´<Ì­¨qj]¥æœZ‰qÆ…Fb«ëäô¿·ÞþfÞß—ÇîüŽ¿ž„"÷b·¦ò¹åµ ­11A¨„0XeŹfôï8¹³ó&æe§?ØX¬»Ìskí‘ ûAduº@8É88 ¹WÔ—(·æþ ¼¡±mRÔ r­`RM>€_ÝÙéq?r€Å™$4©Û`2PG³I Þ 774ÅBgéÐ\+ç±â«(i>ÌPI”Øà*ÍöˆØf˜ÿy;açýÿvرӠƒ˜þ¬õ¼žÄ|>wËûBEùÒnh?”ŸÂh~>m鮺yÍcÍ™ÛÄèwLmLm§ ¿ç<ž%>¢‹eÕfM”¼eó¯4ªÆ@àç1À1Ár82 (H„J‚˜[7+ìÄ[ŒÜ«M\ÞF¹Ö^‘ʶ‘˜ÀQD‹þs?Ãëkþ7ïnûp¡ù £âSO¡îÇ&Ê-UškxÉe‚Êœ˜öÛ8£‰8ªUUUURªpý…0‡FDDðí[Å!0a¿¾„δ7IY)’& æ:2&N‚s},C¬·ÎËobeÇ*ÿvÑgäê÷ße_¿Â5úíxj?–¯Íî0×4Ѳ]E@(DD¶*;ô„QJk1%²q³îlq|O½ÖG)‹j¾ŒHÆà+…/è„´(lŒþŸeø‡gþWÞÞï˜IDïgÙ„{§D< ®þ«ff‚§ÞpZ”¡r¥Z´É—#~X}_ˆàBª¯êÀ Pãð8¼5¨" Yû™¥‡÷K¿èra† RáRF(YÁ\šqi[´âÓtÅ6Ù£Ü# <=¬êÔY #Þ…Ëîö3âx?_ùŸ‹íŽýÿõû“§óáú)øœé ù‡‰ù)Y­Q ŒÆDB6Cb©I ¶¤IºÉ¤¤£È°ø©9!1$¼ ŸߦÇGG9¶Ÿ 9i²MD,±Y-”Dà „Th AA’^çŠÏ[t’i…´Â[ý^†uÇö7dØÅñûúÐ"EDA­›\8åKÞi™e ©ð,³…t’ ÉBŒÄ™ƒEƒâÉ‚`–³« êÂÍYó)†2æ‡Áü ù[ÅFpœÜbS{àÍ/ÁÃe=A†Éz3ß&Gû+¿ŠJ}Þ㉚Óym×ôÁÕ”Pn»:\Aéfž‡a¯è«rôkÚ‰¥$ z%F ’èÄ¢¹RãXrƒ Pª=.Z cGŒQ¯fÂj_­;œNN£^ºp¾"ÿ뙌‹(Y œ“™lf’¼£ôufœöáÚ“š·Öò^µÐÏ V9˜7gÑ)P´ØšÀš$&¹Y’äÈ—Ú—Þ¯–wʶqnXÍ6Ò–ÒK*Ji» Æ`ÊײFêºDìéžtµŽa/r-¶Aj¦É9–«j¨‰ž7^–Ñ ÙsÙ‹RÅ3K -EMxé—þÇð¼Á7&·òÔ?J¿´çèëD!;†„°¡ÏÐ)¼àu‚Š‹„;7í=Ó³jö6;ü¡KÓ“Çøû1¾`NÁ9°3y8(XzßYO‘Tíç8vî”°…48–ÍÒØ#88téÏŽ[9¡žy=2FÞÙãŸsšZ·\#ÀšLU•ûûû¬%tÅyig´ï¹n # 2‚Ž-”mì“Ã›× c–»Usì¡hÍ:ý½ŽÛ]»çJ!’'ê?¿;Nµy“ÃÕæñ;{[>?”ž"P¥=ƒØóc­9Nm ʬ>ƒ =oËu‹–êŽÖìÛ.ž%‘;u2í2ã‰+q‚8ÐR†caÀÀ7T¸A `@…D],æµ+8aŒÚÖÂõ©:í–Zîš—¨ÊÌ)¡{v8dæòÉÖ1£âƒ)†7ªFäñ" zIS¡ÞÐÉÅ"x)»MúT..Ê™9ŒÛ-’ka²ËDsTš%òž1!Vu+[Ú¼÷~Ú Æb®Wíþôž"R樆?Z!TéVK ¢§:5/®ó32ƒËoNe {òeÖ¹ªsä½k¦ýŠŠ#s­ _8‰Á¸JF2„ÆJŒq¥õ¾ÐÕ´³ .µ¹US[Ži‰o«ÝÒ1+¯B5•ÜEQC<`F0†×³‰‹##¶ÂuY93“¯i栅 kª1a%µ¾V¡šš²&*^jùç7n\,í’2g¸NœYXä4Î ÝÙꇠôy §7Ànyä9‚Tâ"íBã2 N\Ș²¥ øLòæ×>Boš%Š–Öœ8 µ¨eÈÄaLÄÀ쌕ë±L6[T½•’YXÕS|ß{ÒMÓ­—Q1Ž·kVŒ2QÍ22HSUMIPèÃdµ]³±ˆ•£²Te²ÕDV3GA÷ÎR… q’7t°¨NéAœR(Ñzšd¹ L P‹m«ìfWm¬¿ÑéKê«»§œý¦7³ô" ©Ürá¿èŸ° ˜/¿ØBÖÃÜ+ÍdE¶ÐØè:jùŠ›¸Úl:ô¢¸ŒŠ*a¯ –ãÍÕÕ–šXÚÉeEµ"rFS !us“:¥5³šª:¢8º $>Be®T(*2…”HR™ÑžÛ¶ˆ‚¯ÃqBÉJZâ¶Ήn ÖÏ ‡L²³;|7:»ÕôÌ ‹ge<¨Û:~+…7^¼â5S©ðJ ‚2zÝ –LŽa†d:ÂÈ‚¥çA%Q‡´n.×èFTæç“¬“•(œögL™LDÕYcáeAÊue¯s±–k„Á‰¾”i ô‡¦u¾nW‘RÐÂʶԉaŽaó©Ž d °¥Ë¹²ãJ¡©†Y2c62t5­òÛPMHjNæ:~ß²™iMŸt˜mÿ; šuúVN{ ƒw;ENqyUFà‰É~¹øðÓ†,tØNœïˆ¸ïÏ …Jª6XtÉK/5Ѷzi–ˆ;×:Ó]M"z°L®ÛŒi’F¹d–8­gkЪ*-Ô‘FPÜÚíy*Sg|21¹K*ª_6eeh]Èâ+Ö¦eÕP¨©¤ÕÍU)Œ8Ňd­«Ò•ÜÞéè@„=&‘zS<Å8Œ1 â:(”9PÑQЇ<¼O&Cmªp°½ªµS§>|±Î•z¸º¬Ê…˜*¤çàÖÁ¬×F’è-Šë­Ršbõ‹ :R3°ú¬)ußQhÚô%¥Žoõ72ŠqDÆFS~Çá¯4—§!•ù\ERÊŸ®{ß<¢ùg 1Xç49:4­ ÅÑ[&Æ/Kn~bì¬É±eÌQ³z^‘‡Œ±A4yÕÒõÉ ƒMÂ:WkÓwJ´rÃYyö_"»¸ïzç‘ây+öõñ‡bÏF¡¸å·-·ó·úèñô¶öíó Ð@´Üè®õ’ÿ ßìþ¤Z-ø¸ »¤V¤”ˆ$¤DD.l½,m‡.qÅ¡çI:ŠœO;ÈÙ±x·ú]s|&J™3Àš1ÁïÐã*9¨L)C»aKŽ•IA¬iå6Ü —iáCmÇøÕÓš¤/ùP³’6gŒ8íw+9 š®«Šã1)8)C… '#¬h ¸"ÛB0$¤Y$T‘ªÜ:Ï—¼ªcù¼¿2gÆ[ sÊp´+)K{Ûm’T£ð|."õû— úü'–§"ñ¨UÄ`W¶û‡éÆBöª„¿…ßÞäÊíö¢-ùË¡ž ž Š|À` ¬âœl‘·‡Ì6 —üJ"Æ@6÷=M§ÄzJµ–«Bã|¶…¹µ È{«»RìIr27~+@³‚#¯v70!öšU2Í=ú¿Þª®ùé3Íæ7sS Z–$02¸´‘ÒK»‹¶®Cñ‹„ˆ·¬@Ho$#í¦v·G¢PÕ*í1 L‹Y1®àâCnq2µuW´ï.ÅRÚqê²\·G Ž<)s›Ø«e+X‘œ³¿)ÄW\Õ$©ï«ÌoüÞ[_Ÿ—‘©Ÿç\0•VÕŸ^ë„o‘»ØoÛ!'`'+¢ð-ƒN4&Õ†ÔL‚(ƒ‚ °h”¦É“%8À$Îߤþ—Çœ†CMß°;3ÌåÛ\üÚרümÄg@x~è~ÿ°-aÅ£t¸yÔ8^¨ÕÜJ``Ãp*ètEu%7µ[škõlÇo]wµ³õ]É;JóuG%¬ýT2ò‹K¬î^¸Õ÷¶Ù~Y²êÿ—§ó[<ÿIØyŽoÂã1ê>£‡HÈœ·6Õ¿TgUJI‰¡KàóLjöÐ =‚n(RŒ @É4’°P‘"ŸŸül‡Ç|Ô>9·Ú[BÍá©~Ͳ¥æXYRè•nO ÊRq}ž+½âbàÂ4æY¾Ùi8ø4Œž2âÀüý/ßå¯ðõów}šöÃ>6Û·ë~ÚrÎBs«hëfVsæÆF*9’XR Prã, ‹Vå.]¹iRí a-ö=> Ž3DSâùÅÇ̼ïíöIƒÖMGÄŠ Ëð(Ë*ûsobw³d’2¢ðÆÅH†’Wwì÷CÿI ±>´™ð?é;wÕ~W9𽫙ÜÚ>äËN4ˆabÊÁ EˆRx½uìˆÆ1bÇÉ%׳¿W Nd¤¤Þ¦Ä“ ±4šla„Ñ4.YÏ'4u°š 9„;ð,ñÌ'Ëù‡Øž',ò:ð~‹ÛÆRèô“ïUéðRè?#%켦;é_^ aÊ«Ô ºMVî="XŠÕ)ñb`š§0gk$'`vØ!†À2–¦øÞJ:7oÖçávÖÂÆ‚.\Æfz1«ss¬ˆ™äéÑïyçχ _ÇJk¼ñh6;Q‹¤*dVeqÆ&ÎZ|ì²\>ø!¸á¿‡Z)ëÛÎ÷ñ8ÃJÊñœúÇN“Š›èLõ­H•¨íâæuÌ=mü¡êžP Âv Ù€e(,jä™F§&S&#‘B€H„™üµ½·Ûîvíõǧêf:XõBRIKRB¨Œ‘Z¢•‚R¤ ‚ I€ ]G*TJ¦•u­ham)=Ü«v¼¸£á^RŠÄÊ3Ö–Z:± K5T—m¬ÕZª3µ~Ç@Â!c¾‰¹½ØŸB$º’¸šŒj”í!u-¾¥ÊŠ1srèð¯†@ï¨&„¼T 12‰%ém냎ëeƒDAå²í“6#›?ì¾›¶—»5x{Õ¢¥³àgvÕ÷¿£ Æt7 ŒŠ¹–™¸‰Z Å7ª;ˆ©¬íž(h¦—d­–.›ä¤Ö@ÓW(Q[s6!MkûÉÔ…¨£]–cüÍ÷ÿ[÷_ίò?±¾w9#˜!¨öë elÓ9n†±Ð®ªÝ1”b¹ÕÑÜÕÝS,‘ß»4 Ô'+Qaeã۔ʅ‡QÜK²Ô„B!@¢vÕBЩXª bÃŽŒ’…»Ø{î0×ÓÁ”aS7A4ÐÆçÊ#E( bM+F7îJ¸TÆû>3É]#+_7dšÎÚ\Q0ô2h¸¥äK>K4†‘²P‘—UEQ Üô>±÷&›3/åî5ØDfåa=ƒBMùô"[ŽE@jí‚pú6O(œsÝШøÓŸ8hTÓ )®Ó À›è"0¹:B â¢×61‹Tžj1 ©xb:Й-›#sÎÙW¥õ[ŠCf®¤Š.âÕ722E›r½Ø“A]¬©]/iÜ¿ºÒŠ)Q‡"ÝB)‘40ü ñß&OÁøqƒá“µ›:w'—˳g4å˜pÊZæë¼ÁÕ'U`+GR4šl臹™a%H­¹fn] , J°$¹2Ê”Ê1C*ëgZÜɨÇIÏ::¡Å³SŸEìfgSéϳ<žHy¦ÈlZ9·ˆÍÒ…wm¼ÝL.þ ž ÄT±IÜR”N##ddß³T%> ’ªŠªMt×£..Sq ˆ !äÞ¹åk"#dÎÓh½XËA”uD}5HS%”A1gH2Z›ìyó@¢ f©²¡…Ƭ†º"i,fi›81m¡Õm j³ÿsûš¡‘…ææähI#qWÚôqrJ qª¼G<¯1Æ{´§DºËãYŽqè*ižþ:g׌mÛö]Uë¸Ðß,¨‚ ºo†73$®mj=…¿Ðl5L&jŽ ïÒ"f90ì"ç)®1¥5Ò~¯z£ˆœƒCgnœ(>|5¸¶£B—ßQt[ŠoËÍíkÆt³V¶žJ«]!8*"‡‰uÅf¥ì÷·d͸³»&MLôu§ žVÂQt2/g€ùm_QPž5,Ö¥ Š¥ÜM¶®kÂ]ÕbÛšÏgà¹d[‹ÍÞ™UíJóï”̺Ñs¤T¨ÑÁ‚ñ¢¿î$–˜®š˜½ò+lffbÕKB¢Ú rLÓ8îR¤—. © éDڴҢĩ´„>Ãî÷Z°[0ÍJeHÊ´¦KEˆb «JÑТÎ!Ú!²}f 2f›²¨&œÚÙ™ãjÒ_LïS,Ú÷ݦôD½…0*3wL÷´fÍ:dékÒÓ-}¯CµV¦ÒYò¦s4Éô¥ã&k jL¥á“˜D\æ è Á5‘hµ£^)q¥¼›ˆÂNš3.[>®ÿ±ít¦xO~Ã+ûÏqî>g}ë!~©ÒYl¥o;Y1š¯åü—óþ«Ìù_ˆrð¦-´‹¼:f½^æ&öýÜÅi¹ù8‡üÇYñÓWÿ%‘xÆr˜:ñ ËŠŒ®³'­Æö{¹}Ýö×9ÉqñÌ,è¸C†ÓÜÛÒ¥‹UŸ—å;ºDżûúú~„~ìd!.¬;Ó’Z Oç±ëñ¸ ¶<†VT\¨! Ò%&ÄÏÓV¤ñ´â9‚5ÉèÀ•ëióµø_Ó»Ùý·äëÆ'rQð¥E¦ÑE6dM·1eɘÜ2ÿ>ЈDW|{àÊ)F2eqÏ©Oç~»Õ…áÇ åºMhç_än²’5ë¶ï- —.ÑÓ/+w¡Èï4´¿ÿ`(ù(!ãøì_ïªÿ<ÃÚùÌóý¤È ͇í•K:6|áYH´B+°c cƒJ!N3Ö7΋u…ùBFü7GÏ_ ò&—H—öÿ’¾ nççJC„©åž @ly§‚µ~b“àë­W S¸±W´ ÍÜâÇŽ KgÄxÙ±‰EQIÞ¯Ï+w.×Һƒ0KÍ¥™ø\ú }›£¹Úì)Æyf—ÿ-}eÑŸ¦¯Ÿáo%‹â] WÆ_$9G³K’Ösª®V"Å˾’3L’$Èm`3Ÿß”Qzk®eE†ŽK$6S3¸Q3|¦[ƒ(ñmÖ||–ŠC2N¤ùäר HA€Á@ÀÀLÊFR“‰­‚Á.[rž¾Ë·+[ìkvç±ñ>ÇÐØ[ì:Úéÿ\_;Çl©»òo-òKB—}_¢ùN›JcŒ ¥ š2øÙê‰4ÁK˜;#×}ŠZlYÍP˽Â\©•ë6˜,Ìú³¾LuCw¿9M›¨°fFûŸžëFÓ¥ìHF®6³\[Ðæ?Fààqt X-Ú„‚Âr¶µ,)B7ºî‡’ß¯Û Q(7éKÇÏë·²ýj•}œ»×ׄüsÓøç¿ª|•œu8›£mvRÖgv åG.|åĹBâŠI#ŒIRF ± JMnÏ!!+WŠGî8y?]÷¯Æãõ?5ýß²ð²½íôüöBÒ{âˆ{ZYò k $>í' |#föýoÁîo7ña–Ôõé9©# <§yÔݳ)r8]E¼H!€¢J^¨ˆ‚0køïÁ> yË—¦xÔþTyî#c~â•%ÆfK‹‡‡UžÌl–¶mœ#PÿMcIDDÓM—%ØõºfÜZTäˆ •¸œ­Ò‰aBñ­JýÎLÄA3-¿¯þÔ}OÌìž:wÖÕËcжkÉž®küÄ­%.BæQ#¢Lš¡—. %Ðfk,!¢©sþôf=~>¿}½›‹ìuRyÎÔ-%F…ÊP˜&–Q,JƒJŒÕ*ZÿAù¶(þ<ôÏ[w¨ÚF½ú%²™Úrr"ï›42ÿÀé•ï83[^¶…Zdõ"êá’ï Tš¨Â¯ƒ]ñ¹©¾Œv š Qv¼ØhA®[§Îů½ðªe\Xk^™YÂè´ÑJ”ŠÒ¦yZÃÛßNKM%’¦™×6ÃÊ‘ŠêÊÚ?§÷šŽ†ë«q9è€>àÌb¨àÌÅ ð'ƒi¬¯µØUÒ!EpÝ›Õwâ‰\PDKªYDA („•áKE²©i,ú==ìYÏê5YšjÅ«{ZDÏ*®O‡ª6ƒ\ò¾KÜ|ò´.ØjÂ(Ã]¬¡ ¯–Âæs†–ý´)ñ]ˆœÜÑ¡¨£&*/ lúV&7ð\¤ÈRÓr¢*ª¢¢®3ÞJëÅ~Ÿ›-Üû°_-Ð%y«*a Ð¶- ¹¬´«ÚaƵ³F›gCW½në‹VÏ]1ºJ× Fx¾‰Ü¼$¥¢õ‘ÖmQ[3±%Eÿßc!`F!c2ßs·ÅpÚ÷xaÊ]K¡8xß“Éö2B<:Ùš¯«<ÅKom&œoh7_ ¬ó'ö¬H¯ãИÀ`¶ªË–:ÍŒéy\ì=j›±•2ÃâÙ)skaÑZ™c»x acFÐ^JhùT„3]nfÑà QJ+" ÚE[ÄÎÙdRçõ~BÖ¢Øà_2æk0ê0æD»oIAwKÚŠÅ!¹ÜÓ®”|´ÚÙ|l_%œêœ8É®ËÙyóh¢¢nRª–P­ç=Ìœh„®ä’Å¥²ÙÿÑI6Õ÷ kp—ܦUMÅÙ™?ôGPZ[|â¦B+zjj?66}Üž!ו†±Àdßp·3&–d…9•˜8Ë%lTXºK—¥\ÊØ|èYÍLŠV&oK^1vj^‚:®Z®EVêM–\ŽÄÒÞÔIÔñ{ꩌƒf[¾ÆMC”¼ì‘ìïTÞãŠäµå‹­™xPùÉâ¸8òz[+\ß±ø½½ ól_Ûçn_/¿¥*p8'X¶2Mt6$ŽU,k]Æü²ÁfÅ­jdµNläšseaòÊïh%mÑeŒÜª$eGLµ`¼Ð¦éGÙŒÕ;J÷Ès8ŒÌ›Id»‰JÂR޹Yn¶¾Å Í£*^”Qƨ£;ŒÖVQM¢Ú,’¦Tr¦HÈwŒ:>tÌšIañ?»jõîøj%-•v…‡þ·Éÿ—·ìÅ5ÊÑæÉí&™Åõg9#xÈEÐ_‡ó‡m‰ˆ´ÆõªáĶ¡¡ÿЋï<œ?›Åõí·Œº'ÿúoõ $dã‹Äé<Á£ß/DÉ€|Š8€D@œ$d)ATdSªô;¢¡Ô|-†2Ž?pÅ\¨D@ý¯õ<çÐõ©ùÛÐS.Ÿ¡–‘OÖ˜ScÆCojW° Q <ßõ?‚›wÿ'eÜÒùâîܼa{6ò›þ7Þ«ÏÛm|èƒ-Å d’Ò¡ødæø¿x8‚\$âŸ!ÔÃ.Ë|ÁÖfû3­m¸;…b'AjŒô‰LÅÈØ£^qábP_B ë:¬O ˜±±¿ìAâ õ»@¥:ld$éòÚ=(12#}›AaU1ï<äŠ*Sè÷éÄP •´vJ£<â€Bª¡]‚\9^îŠÎý¼¤Ôc$}½_ÍM¥ñf»Ìè+[± (Ê 1³Hä‘Ȉ)B@ŠÆ¶T¥hBœe²ÃÎÙK+Ço´Þ¿/iäû?Áû¸ÿÍ÷¹_5þ9Út‡WZïÕg[ F Lâɯ’€uiR€J$*‰%hLdFƒŠØºãMn«´òŠvÿß‹™µÇo˜§™Œ9À×÷ÎtõÛDNÐéö¸¥ Ÿžc¶ýÕ³‹‚Ž#O·õv_]¿†ÒÒ{<FÙòõÓÕј]jÏ{ ±?iûÎ;#:‡\)n~ÿæ?ïýê©úõž‹ƒX_¹Àüy;ü´_5¦­Žy·šÑª`ùÌz¿ìœv{”eÖáŒT¡²°êŽ÷[$Fì8™Š• ½pé)¥H‘_k1U†ú')KMb€¹]©¡ìõf®·£‚ªa`|ÒÝIɉ‘MîRb…Ã"÷mÚ9MÉõw®/ÌÑ¥¦>~s›OЮ ¡z¼¬<0íj¶HžWß/?|ɸ*ß©W1Ö xW‰Ôp- tCç‚vØ_œ ÐeÖTQ”#4œkeNŠq]ïÊ·*#ƒQ·X¤Q7…˜àoê.P?ÞÞë6‘ÙÅu9£ÔSéú¹·è|em¼†ÁX‚³X P—àf姆ã›p0ç ¶ N¢KD¯€f§=–_$Úk×k'¶ÞRo£sxã±a?Õ×\/ ƒp³©ºäêtŸô¢±b.ØÌé%6–¹<†ô ´ˆØ­kݕȰÒ[ª‚'íKR¡œY<BâS×JÒ|ìÂg•Ut`é á wÉûoØzIØÿGî~«à ¿iöC:§¶dÿ Z ÒÏgˆx—g;Ÿ·ïSÇd„=ÏU•èŽË $hBé“)èèuÏ¿{ Zu9o:˜›kí*ûgÃáaÎËdÔÇzTv÷šžvîÃ4ul>Jמ¾àÎÎŽ;ºÛ+­¦ßÐw (Þ/ÜÚ©7ÂK–-¶d0Ï3QýÄd«¡þ3AŸtžÖ毳ƪխ“J’H–r¦ ’ÃX‚ ,HåBK 7ËåRè_”i,¼ZVÐê=7Êç?W²ìÿýÉf¡¡ Ð ô™9íVJPÉ­d=G¦Ô>Çì4' ‰DÞ¥ $¶P?þÀ­Ì5qâP:}–ã[ýÇ’vòQ•;[׳“Ô^²«ªª4¥XˆˆªÁjÛh÷=»¯Zkç‘=ã&Ïyî½æœSMçg6F(T[¢¤¤ 0ˆ T©)P.T¢+V¶­ï`k;ÌWÔ±~{;CeW{Û=q[‹Å­´Åó{«`És¥q”>1&JÎp^¹<A10¤š™!šXóµXÚOür%AÉÆQ"6—Ê—ŸÝ)%cù¤ï"†tåj9#¢òbÛâl¥¯¡$ÛËg¨Š•¶š*ÖMqŸõÿm^jka‹¢&!7š£ë~Ü\+¾g3È6áȾÉj¦nq‹å™œ% WÞg|õ+XUÒ¥¦—¥ I†¥rj¥Mo\&±¯ c†-]g:kWK¼Ûsƒ’PÀÄ…Ê0³9׌l)’Ú¬8ctâ!nQû<­åfNjiˆ,¢è*DnÚ+:[ê°I¼w¤â¤ ×*°_Z´J¦¹%Ò C0›RÓ“æù êÕÁ½TŠyJ™“Ó;%‹XiÆu´!ÁÒù,^—»BV >ºÃ;Ó3HK²Á˜[Ú²ûõ¡Ij•r¹nÓRDœËÝdJ.nùè÷²Eµ5Ðz’¢®E(º[=xežY*eh[è¹iΛš¸¨šŠd^‰¦“BÍŠeB¨ˆe]u´bŨԹ¬Õ e YDªT\î“bdP`ºâ•†kVêš-5ÝzᦄÞõΪØÍK™fï-OÿRZMÙkf 3Í*j|ê(ZÈÈ^ÎòŠ…­KNzT¦Õ3\^›àmd¸©…tËvDd"›êSu–öªçœÄÑ›Suf×ý=€D *ÚçR¦ek*]@RÑ2,B¢­´É¥™k0)| ÓMoYÔlò¹KN+ºkŠHh!¼ÎRëm ÉÒfqRòV®KÅuREª6ªB…PüÑ@ˆ¢Ä®QRäd­MJ³ 9ºí67ܿĵ¨Ü8Òö~½žõÒÁŠé%«J¤e×fw’mŽcKU´×^‰Èؾ!5|F™®e²]h¢ƒˆ–2‹X¥0„\ÚKm&NRîÍ|Z –TÍÒ©¹ŠPr_ñÝè­’„Л¢g%èÛ –®Ÿàü?Þ}/c;—200Äjï8㈌Åf›n}©;ˆ¦/VùuÝç+Õí/†–(MjÍ^³jÖ™"Н]—1¡é“Ö–®_¶_£„М³ÉÞ¬¹Ö*õòtz}_Üý_âÿ¾?Çÿ»æ¿£ß=£«mVc{C.b °-.(¹ú‘Dv!„íPPWPbŸN±)‹aI%1‚njpzl, ñoáþþH¡Õÿ?üoÀûXœùç=ýýß›3yjïÂܺäs5ùÃÿí¾xà¨ó˜ë.[m­ÕÓšË[™­Pd`±)„¡)Ð:S9‘œçÓ½Ï9m²ª©ouÒâûüstaÓâ9Z/βòóÎ!@·Uic ôìQaA^pÌ@Έ¼ðÙ¾»Ž%‚PñãÝŸ˜˜?Ò.‰3„²Ð’F†’Tïk¿ð]0ÞÏ·—Ó¤N!gÆ‘$š*ïÓ_ÏífBñ±—*vZ¤ÿyp,šâx†\Tò t”ns¹ÝQ¡;þÁØ\°3ùðCŒ[¾\5a"÷0€F¤½–2…¶(z,¸'+/÷ºß–,}à+ài^Õc^Jë'÷ ðL©Ô0V+i:¢À-»Ð›î7µué0žš%‹ö£ú9ài ·w»4]AŽs c Åˆí­¥„ì)rœMÛkZ—.Yõ>×}ø;Lkž7ƒê¹sÐõ¾xÊ2å Œ"1BÄpp7àá$¦M{v‘ƒÕ‹›‚^ñ;ï:wcÐs®>N(Òë³¥3úÝ:•ëCMDQZ]Т:øÖ»”ÅàíÇv•v­Ë—aÊ’9% —()@‘$¡qK 0ÅJ$¡AÁÈ ²LÞ–¬Íkuý_§§ï9 —Ù~óînÀû-$ ŠšO|ÓÙÐ.ØQ!ÛhôôÛW5]\÷Ô§ÕëDA„a?Ëæýv¹eftä,Â|Òy´:ßx|žð©âò3È9‰)J¥ ­ )‘Gr ¤w,1H¤Ö…Š \(U…I±5H¥•G2g¬2È˳9†g£Í] ’»J„N¬ÝïšÿõkfÄ–,Í+ˆ£¢f.sVíÓþ‚X2iuή¢²ý%2ÝC;ÙËP˜‰Ñlø_r¨j­I{Î/y¹p¤S¿I½uÏ,ñ,¦y˜¹˜ÏN*Fmu&ÙÏ´l)A†’¸xÎŽ>Z´1dU»4•­oJ&v†Ä ëhض(ƒVù]­T¥åN û˜…ìše›­è»Ä&_JAûªwɾ"õ±cx¦éuGJ&h3˲‰F­íJ ’=­XgQÐZ2ê—šT­JjÜ3„ãŒg< ̾šÛÏ£^$qˆ£ªŽ<¶¦3–Ò*оy,–UåG¬Ê(°ÆÂÚîó‹R´ Sfj¶…2|UJdE®wÓ1Uý¶¡vJ *é¦ÐަÌ>j窈‚1f[W ãv9ïd\÷<ÚïK£6ZØÊöµ‰3"@vYGË(e!œ¬Ö/ư=žò¦6½×(»kr¹Ùè·±; "£fªhÃnÒ™¼Sl¶|µ”­ìP]ŇÏ7Ã)]–Õ³nÛ\è¼›;|s~•¦Í•¬QŠíà®Õ•w)z6Û©{ÍñžKöòÝV/Åu¹< ·kJÌ÷Ýs!õÍaî‘Kè¨1œ\µ¸ {6XÁ^RböšÃV.QV"™N2{ÒÍ{Püßmþ˜¼ògÁW÷»Í(¤ˆ:èñ´cUš2Ä „µ^$°²¦Ûº0Íle•Øgá9©º³½&ð[;K^GT¼Ý¯U£`… Qî;¹ > I§3•KÕ•J^-“¤ÞXŠäΔš-¢u¶¯0Ä‘“M²A®DRÂç-UÊ«W‹-­sý­.«z)õ­ÄbAâÆJºMñ¶½–"Ã}Ê)Š«W™ÇÍf¹&©K•Ũ–›¬R)FŠÃÒ¯»ŸâŠcìoñ½]Ò*W;1–šhÿëÇ¡§Ô§ù»¿'ûþ—Åk+j¨ÂØÚÍ¿ëp+8‚é 6úd»Õ'6\l1Öb]‹¹]óî„⦤6d”aÇ=qÎìtÜ&E ð¬0‡†0ɸ’ž:ÊOŒ8e ê °b1Þüê¥Î ¬3üœC²ÿàðšïŠB•iUÞ¿·“…â—_Ožõ³|PŠ” Êˆ¢ª‰!ŽŠABª57^²_ý dÊeþ‰;ú,{žÿ1Ýÿißi P˜Ëo Õ ƒp<&uÅP©aæñ¿?ýÉ´º»â·Mùž:M»§ª¼…’áò:ÆêêÏžFÚ`¦¯2¢í4¬Vå¿ÕÛÔš°NYjä¶š$¹úº3;ø¨³›æjZ’õ<‹|W]o²u@"Çšä4öz±îc-Ïa›^±êTÝu2GÄ{Û^ýüÌÓÀUŸ5ÿr*òi*LöÖo!Þ|¯š,;Ëø\±NYFÎŽãÏ~¾M…^‹@ÖrÛ¸òjöË#'<衘²©¯jðåçŒÇ³°àQù À…„ªã j2M³+ ÒF94àiÐV‘"$æ A­*@s˜Ï2d©O»‰âPÌ÷%ó8vJß墲Ïõ>ׯÏçO{ª4§«-ÒΙ#-S´*I OÃü=&ÃÃóZŽÏig¦Äã|j5Û¨~_­ÃsÕß_¸_-ÅçF­eÎÿNº>¸?¨‡–ë‹cøu" ÜÃnÎŒö=–ö{fÍK¡¡G²‰F² @Œ•„ ¨ãˆ9@{„г’DKQ‚ôgWìw²…¢~—,gqÖ•…°±e¡j­ ŒÔ¥!©9fÙÍ.ÙR¯iŠÝáç(qª|kP Ž¾ Çâ»ùñó†Î^îÕQá–ã!Ä©+HœlµHv/ |~TVñJ»¶)DÐΑ‡¢Öf±ew 3*6dÌÅU[ø‹9yí™›`ÌU|‚QŒè’i'ÊÎ{å%ö3L•Ç­íh’ÕËW+-v®"V-7¬ Rã­lg\h© VÑZÚ“ý¨‰LÌĤ!šBß‘¬éâѼY³èÆQ6‘ÍcD£˜ÎÕkÅšE~oßE/v¶†–hÆC®ÕÎ2Ïi9ºÜ³«-r¯=¢áÐaL†FU‰»A£=8…ék¨ÍM]Ô"3rîôØÞåçlëF×<³Âä£hf²™Y\èúd«l§_3þ»b—¹c9QLÄ)›ôÒjh¸ ‘Æm¥hì¶É§G[E3³jK= «Yt†ÅóÊ#**¦ ’U i¤ey©J°^±Y Àô…Å*EæÂш‰Ü/gzňJ´–jÒ1ÂÆ„Åxb)m´`Ë=0¢˜¦y>Uµ[3d¸Pa׋¢$Þ0·VVQÍ@£NTÄd(ª_—/W•ÂÞÙ9¬*²NѯœhÙ–’X±RÏZ6o4x¥ŒÙ÷I7U­{QžMBofO3÷z=¥­’\¸¬Ê†ƒ Pr†È“·rsv¯q–U¡9Ý¢ùç”—{¼³q¦Ö,=T°Ï¡’3‘•òS+¶rÊж¢Ò¶ED{üªP¥äò¾=b(«Üà—þGCã,ëp× xK÷‡¿Ê©½"mÍôžª—òÓäu#/0ï¿÷1Qéîè¿ ˆÛ»áIAŒ`F6úûO´ƒÅ4÷•¡ÕðQk½-kÒR&IæC«ê~/ì{4§jCŽ–i¯¯ŽxonU›gò½Ÿkï~ˆt_ô%\Û&¡²ÿñ­ëE^•5Óù=i[}–Ü}ÜUþìC~æ€DmT&VQh ?à ¹MKoW¬òN{p2—YB ö¾Xc’K‰ó•>3Â;#“¼*i°D^âíK„QÒb|ŽV çÓ /­3ÎvÅ­£Úoé{ ”»’éôP—ü#Œ¡ÊÈ3±ÜÛ¶vä÷ÆIÎß„6& ‡ú-°Ï/mŠE`¨µJÎk06$âŸò±[d±FÀUôÎltqx}»'Ágâ)jÉo"éñ3jÿá«ð25íK6àŒ` F"$P²1À880C”Ô¸ø×»©ëØl}S›DÓÊ1XÍéÝ?»¨a]ñÂÄjÿ³,Á¤ûò%5¤§ëž’Êòæµ[ )×MÆÊû¿\|Ví³¼Áyì9$ P, 0¥ˆ¡% û²…KT'BD©Î$Q@éäñnk{|\/b#}Œ¯ÊQüZ{`LAáñZÑ6ß©§ågÀw&¶"¼ >AH{Ýþå÷}çáß…Ã^ ¤¹T¹àbéRJEA±A– 0IqÄH(…Éd©{"X*—!º@ï-0ˆä%dhëJv£ºêP™³Dà·àÍ•¨ïVk˜*dÔÃFÝ”™Ê£Å /àØŠåzÛ2(eûÀŒêÖ)k“FBÁ\¯ê‰ÖZmu®H¹ $9aöÚ©ô[¦Ø±¶4Æ3Òõ¦™b¶Îéž³;¯î?­¶C™™K(ºä9X$£ÓSY§Jex¦Jõ}iS:PÍÞø©J—¢˜¼fõ¡xÙ¡ò²Þmk½⣵K+4hóßöI\·%W™ó0IƒsD;“:Œ×v¶×f¤QVÅáæ­F³_m×Ë “Û-kŽ”cH˜²VÙ‚Üä?Æ3AžsšÿÓý_ºÊµÏU6ŒÝ”œä¢™nÚŒÉMÏŒZhEi‚qrìZ—V¨£½ÅXRÕ±y—jR­I(o˜ŠoQª¹çûy®¡A‚ãXˆ)+‘š¢Kç{dJYŠšRøšš^®ÍAï\Ф.n©–%¢¥í“Zõ§]2ÊíW\´¼¿]‘ò¾W²ªÑ°-ù†²|ÆÕ$qŒAË•qݲÈÖ‰K¥AumÛ±K£çLiž–s,â\²E+ž¤ˆÿ_¢ˆ¾/|m’]¨6å)­·Cé‡_Ÿ©®BÕÊ–*¶.1C1â3%ëHÂm“k ŠÍn=²Xúã¥Ö Ö•¾üA\2Ö YXõš) Uä—¾‘UÍðŒ8ã³ä=‹îù± •H+uîY ˆfKW7œ5"¶´d‘/-ÌYÔf&¤]m6‚´±Rs+4Á!TGj´Òª°¯05ç…«‹^ ®ù¥§LMš6¡/ƒët®yg}v3¾w¼.5ˆUýö³¶Æ†¦ÁqS5ª`±­`xkÒ„ÞºV.÷½K- ÚÊÐ]^ÛŒc³«L+›œ} ¤ dÉâ Šº·´*ª"¬™]!–ô¶ÎB WiéW ð^*V¡°9î%'éØßúç¼ã×½Äù¸• ðR9l4Õƒ÷aããŸÖ¼Çm*ßßR78 6ü`ÌF01‰oÝîö¾Â©eVËÜ¥ýßà{‹Q©hg‡Ú?aý}1bô½ÕïÑШ¡:D¥E*Ló?«cG)׬a8ú|"ßw¹Â ëëàñ—¼gÆA´'# 87+ß«±ãÊ!ËËÀù=·æ» ×» âÐ ¤•¾¯:›y`E3Fæ¹\ÒË,tFø¼)˜» TûäGAðÌf˜úr„ÇÄálÉÕ5!fO)5k|qúŒÜmnùª¤"9GSÕº‚wfŠÐ„$¦Z9s½k|þÇáj?+Ó ä3â$æÜFÊ ^.¢ø¦eWY»‰ ųÉÇ`¾äÍœû%¼ì6t +¹Õeä Áè éæêÁUžy" cžŒ\–Ô!®ùÒ x¯¦ný¯r¯Îæõùºi9ŒvÐܼæ‘W¼œÏߌú覤iÌÐŒˆÀˆ%€€C?s‡æ­o’Üн!m‚á§Lg±t(™ƒÞþÛ °ã-KÞ2PÀnRÖAñECž9ùäòîGy=™ëPÕô.IAr#L¸kΫ§Ú¢e„¨„ÿ'Ÿ-rÎQ8¹0ª®N.j® 1\Úp­Ê„ ±P‚¡# Bä4;€Ð$RQ§¸{»³HoåÓWÉ2NhÆ‘¢\7Í—CçeºÆ ž¦ío’ê±òºÝu^Š0ÝÇîô“¾2*U<TsÁ)qX¸ÈÔb„Ú‚+W*AbAJTïÖ^1‡Yÿ.üèÍ•:Ùª·¥3ÉýÖW¦Wo<Éæ®Oœ,•îL×+_FüúW,ÿ£ ™p©ÿJåBYW,Ú_$0Z—±–2–kÅ.Ñ «Ìj¹#UêÐ"™Âéxh3je/3U¢RË4¦œ®=þoú¾{MÅ‹˜4 2b&8»gZúÛöÏz¶ Õ˜«M踉7oµÚáKKbú`Ë6m¯AUH8“4/ŠÒ·W‰8Ë——J‹§æÛÂù(ù%wÞAðc}"‹÷UÜû<^8ch¡¿-Æ û.5v½rÓѨ–5ÓBl]s–¾Ï‚™Íó{˜R@üþ_[çœhPR¥‡T7æùÅi±­uæ R`f³]J«ÈêÕ*ô‹q¼®J gª‹·g¬ä;ÆNó«wqó–[˜ ‘%a‰¹|©–yd•«º–¼ÀÕŠ ¬døV(ꬵ£;äe[3^-Œ:K`’øV²ÁI$*ItZ5ˆñ zDLVóƒ¥JQi%”jQ˵â‹[Þ´š­¢ùÖ“µçVã¡Áb’QlCâêõz«\p£6,²R—kJTªÐ—YG&œ)DXÊ·*ðÉKBÅèëzIÄÍV5þÆ3ĈŠ °ÆÙ66ÍÄË*KÜ™š\z°L=ézaÅš&1$IAq„›ËF5W4¥3¤˜¬3¼ãûJ¨Á"ˆ™Œé‘R‚î[š52ÎØ¤sS5µ+¶q=clRµ—FTª­lQa»é|ahZ/RëZgWs({™Mê½Ï¯øuÞh¢Xk @lhNleA4{BZl¼5­kx£Ë¦(>*Ô­ñKh­Ö-‘xue&˜Š^±I€-!ï©Ð`à€°VU"¤ Ò:ê¶»Pò)Qè@º uã4v÷’±§!ª“Ö9N :Rˆ»dCQ¸,…ß$YædØÖ)Ÿ¨F¼±Ô=¹·îŸL‘ôƒ@À` ñh e»ñ:!)€1¤×úʽ‹ E€®(ëÖ–À rÓ$Š vU8@v”œ&Dó':cƒ˜Æ[bæPXûi0l»¦>÷þÍ=¥a\\hA°²& d–ñià<¨D‡•b(¤÷Ê8ß\z—[ ñ´ŽéF\7e$˜Túð-JÚxGl`‹`2 ¯Òä*{U©fè¹W蛃Kóm”˜ë*éOÆmžÃûëç=DyÓ%P%Ö6ÅeŠkIê}XØIOÛvÙ˜ƒ¨†‡0¯$ÅB„xißc:Ai§¨T:Ìb*¯ ·²”jMt¼$¦´?îAz&{åËí`”É};t‚R€@­MUQƒÚ[ –uìIï':þ4B¬At:3ú>¾Ï뻹¤å ©f7èï»]bV±IÒxþ÷§ýWìÿÁý/¸ý7ï;Ÿqö?áÙ¤AUdž9R!ã¤'‡gäþëÏìÒÅPOñþäÏuß+8r9† ß;×K™Ç?™úïþùí1$o“Üöøõ¿G¨PÀrü…“À’9OU¦tσÓbª«’‰©¦B21‰0¤™XV*«ŽÙŒvÊÝ7†g¯â35žÿ¢Y! àpz‚j|“Àâ˜dˆÀJŠ[KRÕÔôh…˜SöÉDMÛm’Y‘5äh2&c$!)„óٽš ˆË4™Å¶¢jaI£bDøt›Î½Úv£Ž-i¼å³j¶I"}Öøà”$„#Âð|½Ë­[rSŽ!å=_1ì¦íØ.aTÈ×þ/¼$Â’T`ª0àÈÃŽ¢³J–&J`å-™)JDÂ`Ìa†ž·¹¬]Äe Yü³Ò&9«‘'Ëâ5Ÿs¹£J؉=ïF?PPèOwÜè6l¼%Y£LN½44b¶c*¦1BX”0ó˜aãò¸d8œbÌ!“Õ˜zÚÁ‰±?5²š‰´³ ˜PrV ÊS dÀbjÊh41)ðÓ&±4Y[lššlÉÞýü“vÍÌ0Þa£&•\àunn›âÌc{l¦ª­&0¬De00ɤì2hÃu~Í543Ü$(‚Y³E˜aˆäµpÀÂQXZ¹(RÄ¡’ƒûXdM=½ÙMŽêàoRŒMPf‚ž¦L0ôÓ †Á0ˆ&Lű‡w—Ù÷û|þ¯'IÔ¥ˆÊvR !AÉb8EX"\&Õ’óJó).¸ÀÉ,­z­ì9Àz½ó7ò" ëö}Qø8<>+%×ðNÎ*͹Òöw,~„ ߎóËï¸õwÖh³ò£{‡„­k÷l8´¤Ï«-k=å®÷½žÒ´%ËjÕš³zµ*Ö î^¥Ñžƒ-‡˜[=ËZjÒål’ý·ïY·T_å»›¶¬ØOɨå37©N‹ddo7éWíC­På‡8ÙDÿE 8Ô Ä£„ R‹ Ì01‘Œ(ŒXT £![¢ fŒ«Sc"Db"9ü𩎊ª¸„@eQp÷iš×ø¿û8Û#H‹’²ϧ*ˆ¾ëÇ¿[–§Ùüô]Öí„ÊÇF·e|D¾þcÂgñ3)ž®i (~$ÁþŒàéY ú*2®¿ã ^˜×Á€Ç0ñ)I݋ߣçR™+tïÙj“]ÅÅí#°ŒnqóR irÙGRبãΗ0“±æ Ó੸X‡¬¾+PE?©ºqvç ½wE”+ÌQªá×´:¬‰í£¤šJM+KðöP>aa•WˆŸ ²ccÞå}Kí#“+÷NÊÏçX³‰ÇyŸÐÓÁª„äu~k1ÚØ™Ée¥$éͲE•Ž_*fú=î`G£Ûƒ‹Yæúp˜Œ¸‡5DWžÊ: ×[Ÿ–‰£,ÜÓ"úëslBsÕ¤ >*Üû-hÖª¼¶kU‘QWÿ¬´{Æê‘aüçu?8sÇúÍ4„4r3Ä©ýŒ¬ËÞâ Ÿ‘oï>{p_&u3/Q»;üº8üåG ã=<8ØHp:Z€YËÿ ¾:œv_¹åWáqœìtqdGâïEC™A‹7#®><£ØtÓ…<»yͱ²»íó:>Ý“;1ÙR‚Ê‹½“O‚ÁåTí äPî/F\tã<80˜Q¡€ê;~có(WöO×swGé]O1¨**åøZv».Z)Ì® ükêeOk'¦úÞâ¾W’‡éˆ‹ Ê©j;µ•Ráoœ~§Î™Q/c•Òï †~M]”’ Ó·T Tç~WhQy3+fCÇÝ+dõIÞ†½ž”ù þóË~hËÝz'&Pʽ¾þ´ì>"Nçi¦G–ãHuç®ùC±ò?ÿnÏÜsË:ÂPð`›•̽¨çþÓïp,¯ ’턆Îd%÷òl˜…ÿW+1óù'j óg$7*SÅK7Îmy´Þ!p½BY´à©fºn»`Tþ5ˆÔ³’©ë(f¾ËåyO<>C…~Å@®{þOiÀ¿ÃTMCp(â gv–Ð(C-”2Ž2¥CŠÒ{ªº/7øsn›vo•.â`Z¨žÖRã§lQTO¯Ë;Tœ˜ä·ûjZdQ¡¢&`6u¶Drs•L­W9kï¿Î‹ö~{OuôþÅ@1ÝEÙz0¶Ñ€ãÅà*Ïýéï9Ïh™–¢ÚT´òÆq:B @dHïæs'9°¶¾ÔåUvªGýí®È\-qùØþ:­¥ß(Æ–¿‘¦=cš,®OÛODr)A:_sËk›&ß1›‹e ¥¿™¥4ÕtêÍ~jÊòÊ”óøäK`œÄÇÜ·›ž>KN²¸®!tÖ©•)¹lù¤”KîI‹Ì¶,³»Xy‡(¹]hð¢ô¢‹Ôq†Ùu±8#ÇŽ<Ø4p¤*í°íλ}…C.j?À1lùéO$^Äw:ø&ú’!¡»³ÜúJ& @`~G!áHBÜ•Uôë·‘ÿì„=¼@âŸ:€ˆ'åOÚÓøßÒë{" š¤þ<·ãKó+2ÞÊÏOź´?ÝüÞ{òúŸÇü/Ÿ†Þ÷„n\·2¥!‡\-¿‹ÃJ6ËÐ" &ô2Ý—?ÚVn2ô.\WæýMZʱÂñ'‚Í!W›ôÚssºê”£óäA)úoÈé?Lœ<õUìiÇ0áfпÌm\1Ä{ëîµårÇ"/æR¤y®÷]e}ެÆJ¨‡ì™‹t_Owû>Ë_>_Ydÿ_=5à»v:÷÷þ/¥ÆüÚ!ÍêuëÊCD^–#ŸÍn R¥0ý×ñùf`òò>tòTA©Ìýí“ûË>Szö¿e»}nvtÛ¾½çãkyý"ü§ ½k×»Úz9^ž½θªÙ^$¥+“æšxX"½“Ñ<UUDP€ExE€(ã⎠j‘Š ÆÃú\Éí´AõáóŠÃˆŠ&¢"6¨ £(ŒQ"ÅQTŠª±b£ŠªÅUˆÅŠŒX±`ªª,QUAHª±EQATX«TQ`ªˆ°UUQV,BŠªªV "©,AAH«  ¤R*‚ÁbÁbÈ@‘„`,UHª«*0Xª ŒPUXŒX¨Å‹ ª¢ÅTŠ«UEаEE ¨‹UQEbÁI! ˆªª¡`²*‘bÁVȤU‚Š ŠEPX,X,X ýk꽕Î÷Wa|dmn¹7÷¸iuEúܽ^məܓ–çí| ¹¹›ÁÊôö~oÎï=?³Ýí;Ã\Ǧýó3äÞÖÍ[Òjïéü])âõë^/‚Ùþtm¥ õ/´×=?yÅ/é1wrÎ<øpáêH‰ë‹$J ’'¦XÈ „dˆ` :…Šú¾Aü5žÿ½õÞõúßÞ}ŸÉ$NÈZ*¢ÒØ”«Ih²)H( "("‚‘TZ‹(Z-HªZ‹J¥¥«R¨²¢Z-KR-E¥R((¢ŠAbF"¢•$¥AJ…©jZK*ªË$ATµj©eZ¥,Rª•KKQh–ÈZ‹J°–É‹"‘HˆH)R$––’ÒÔJ«RDNò!-DZ[$ÿ£HË%Oð=Ïo¶ÆcŠÔvÒ*FÚzi­ë —×àõóÓó;H@ÆH '{R±1X‚„öÙ11˜1Ç0hduheª±£B0Q%Ò´…¶Ä­µ•‹+R#Xþw VbQ%¢‚ ¢À*,£VRÊ…V°’òpjªEQPN°}po"“a`ÄDAƒ"ŒHƒ:´kQŒTdFD¶UÉ“þÏñ~ÿèo2$€%ÐQõyž€¨¢æ(ïürxå‚Ih­D`e¶T©‚ÅP`Å,E’* *¬EY´E¢Z’&<ŒºLEKè¹m*ª"ˆ!ú¯±éþGïÉ>´9„Ž6¤ m±bÄ‘<˜H˜)$"Ѝ*Œ²EY!€$¢1A` PSÂå¼ÞqAâÙÆ™£å7ù¡Í5-17òÿ ˆ+×C'[èë(igYdeÊ4çLDˆßä¶øcã<«µxѱ¨ 8TæïZ.sãnÜG÷ôË ÏÓ/PF(ƒÕÜ÷î'ôøX8Q×ÿfý—™×w~×çþýôL¶Ôª:‹ƒ\¿ZU}ËØ<Ô´Ò¼SŸË•s°ÈH °)‰âSºkw#%°pí¯¥@€’-8Ŭ÷mùºYk¡¯ò·ýÄjrû[URÞÌFq-°ˆ]$$)`:Kräà ò&2 C©ßd3DÀ\åù¸‚ ºuÍ+oî&jèaír °è¥½½'a ËÇîÞì÷kÍ?+›sË£Õ¿õì¸û˯ó½v³Ó Ë@>àÇÇdÐq"fç¹1w’ÇdBcˆ0—4}§ÒHþÏ”ã¥6nñˆ÷+¹Ç¿Jk*`£"üªP6P¨÷çpPå`‰=ÔK½åO@x‚zˆ”‚ °dw¯?€n‚ŽTAºŒ"@úDìDÜŠ¨•$µ$² "Å‘>€ 0¤æÚTFïÎ’F 0¬’"YÄ‘.‰h`"QQE_™§ˆ­€(ËEBŠ¢4ŠˆÈwu¯~DAl8¡ Œ˜ 0ûù"&I$LBNAˆa$eĨ’©T’Ø--ZZ--%Qh²­"Ê‹bU’ª"¢©-UU‘m°J± •$¤©VB• l’YTUYH°„F@‚Å€ª»uDjÀQ‹ßh}4Ì5&?ÐëñýéèûM½ŽªNU=e¾DÏù!qÅéX›Ë`ª |PŠhgÊÓ=“éÃŽ—ƒò5k…¡MeM>›cj¢;€ÄD ¨Ž¿Á¿§}L«™ån ‚`ýQç!s*ŸFÿ²Ó¹ÜmkJóâÇ#^ÀD9­ ¶Ã’õ)âïaƳå'õY[x¬r š ÖI¨D%0"Œ“0Oõ´jÈY$ùQQb HŒ‹$b1D‚ÈIÌS‚DQETØÚˆŠ®¿Îè†k Øó~Œ8n¼0‰™ÈK;u¢nV í© =º½’ÝW£å²Åu]¿,Øß‡-”_>Î|'k/±µŒ ©×꿸W(‘Y›€|N àp$¡¯WŸ„ýê“r÷Z(n›§ãöV‰éù‚€kŽ‚gei Ë8º¼N/²¡Àœààäs U&ÂX+±D_Iõu¢áÇo],rÆA¬788±¡}€äÆÏ±8~ø° lFaaU_ kW›cM5YôÕ]Æ”+ª pfq[Û›¸A.›XªšÞtפÖo¯¾-]ù‚¨ì ¨ç)eh²BÄöÔCÙDG‡ç}Þõ€â;ϵÒv¾éñ;OkÈOA‰ÿ^^õ2©¸1Ž¡ýO¦*‘BÿwCÔ î¤ ‡[šöÈ©NN7öfƤýg'ºKî8BŽ Õô—±`-ØSÐÑþ0dÊÃè°^Ã'ÏÞÈ:wo€¢ý“8Œÿ¸‰ldƒÄÒ‚;zNµˬžka#Bûg ‚Ob:PïtN÷~ »ø\†éíQ„R’<Êôž÷:nMžçÏYó¹=ß¹<YÓãîÿç®ÍŽê 4x RReDŠP²Dq$J ~ K„äŒDzÀQ¼ >pK“s…Úž»"TæX7±±"lHœé÷ÏâÉúê…H±D@QdEEmöQ0¡¤úÀ£ˆSª1D}˜(êDJHè@«dëå•÷qüy!¬V "O9h*ÈPPeJ„,X"¢ÅU¡aQ(¨¨ÁPˆ `°YE!ã[`½D̆RDêꪲ¤’Å… £Uˆä·h­Ô°‹hŒ/–PŠÃQe§4 Ô4Ñe¤ºJ•c3.椃  üY8tBR!5 ˆ ª¨Šªªªª‚ ªªªªªªªªªªªª¨Šªªªˆªªª¬bªªªªªªª¢*ªªªªªªªª±Šªªªªªªªªªªªªªª¨Šªªªªªª¨Šªˆªªª¨Šª¨ ªªªªª¨ ªªªªª‚ ªªªªªªªªªªªˆªª©FBUUU‘‘‘‘UUUUUUU‘‘UUUUUUUQUUUUUUUUTQb1UUUUUUUUQUbŠªª¢*ª""ªª"ªªªª"ª¢*ªªªÛmU¶Ù)"Y)"X `,H¶$M¤‚I¢D É9N:W_C4­)dƒ:aÕã$MÛS$9Æ"D’„DçUEŸe=Í‘§#תSò[£ÇÂîð:` Hí¢Šš¸ª£§‚R) „Ê™Œ‡¦Äd‘ZƒÑ´zø¦oí(Y^üh*Ò)6–X \Š© ’Ì"Gg(Ä!¦jD*Üs.µÖâd$†üXµ7¨Ë9*AI1cÊ-[¥cov±³*¬„©H*‰Ï˜Fõ¶ÚÖ®”‚©$DêY:fUQ&IdëL‰öiM4&Ò§R±(ꎱh…i»f÷6Í(P¥Ó–ÊÈd0 &F(Á5 ¹!DH§anÓi+$·pÀÀl&©a:e3vK l¦stZÃz¦ÂBetÆÕÇ#…ÖÖR2¢¤ÿÓô[ð¨>“ècÄ#édð4ÿã‹{§Wn.1–̬¢‰%3Ôeaã·ÆRÅDý3¦¡¢#'¨¨LŒ€™Ò—¥¬AëÅ~/¯¨uù7ìôVâct8^ƒäñÝתµ5Z5ºk4A–cˆ™ôóv@4€£@FÄ.¢È, ñwÑŠç ØHBqD(«Qˆ*ˆÅcPX("*ª""¢ ‘ ª H‰ŪµJ–­¶[H¨ŠÄDbбˆ(,UQHƒUP’H(Œ'¦I#‚y¤i"DLœ¹£…–@â«o9Ó˜3‹nZ–µIÄ’C™$’I910©j¡l’Ù%DØÝƒLH\¬‰Q ’’Ȩp Š‘@Š#NŽò¢?D8T 8Šy@t³Ã›æ×#, e(Â5âúúþ“Dè^+ŠzÀ‚„ —C" „<ö¤mêëŒè z²‰Ü÷Ô8Éðy{…LT¼qñ s¿±òí¹7-¿/Vý@ÏÕÚÞ ­ªq#û¿dH‰›pC$ã-µbâ%$a+TaJäÖݰ4WNGálsl¹tø”×ÔûÝ.£Òçry©Ïí_Ÿ’ú,{ÇÊ )ÿïì?QÙ³Ž~]Ì¢ü?­ã&ÎÎúh4 o*°XÁ„\)Mf“ ¡·N‘3uL…¶}äSz-µ‰»G,ÈÌ·§ì)uÑŸxš (XhQ•_üX^XRhC)…¤QËr•‚ŸãÛýŸ¶þOQÿûúùÚ=zöµ ¯¾ë<ßÓÍibÊFƒeã*85Ì r”*± OŒ™0h6•KÓé8ÐoCw32)æÃZ•XàϱMý‡ö³64¥µe‹mD(V¦-¨ÛXZÙl¶ÙN¹GX) Ëc¬® kk!0042 )©Uoú_òóÿîïèò½Ç÷(‚)Í› Іªs­eߎ m>Ö>WUÿaéû3*€’ý¼œ=CeéËŒ3Š#ÖÀûbÃÄ´0ê(“KiÁ­%A9 -pOÅ,é,SƒãsÅüÍwWdùünm Êfxö¥Þç)±yE_â@Ÿ"*dý“QÜÂ>(N:^ÝÞuÁsï…ÈŸr8ú€)D¡›æ‹¤ Ñ+×&€z´ ݦÃ9Ÿ)ì&~ß5­¿J£ÜEÀàˆÂAé:´(ÍÛáœ]oÇií˜ô‰C³Ýœ7þŸßù÷1¼k¾ôaØòñ«”î^Ÿ÷óx©ˆÙ°@¥~Тó¿ÔqŸsÈ"g$ð‹:ýOÿ^r0Ugãs¬¯jGêjÅG UúìL÷GÂ9†¯n‰E\¯ÕwÙ€ öž•ÿ/”>Fá×ÞèïK0N8ç"âay Ë c\ýn®´ÜTʹGò¼)D#Gk+W÷iH#úêúYvwV§HŽDד+X,Na\½S6×È\øË–‘áþ±vÿÙ‡ÀT**ºêýàhè<_tÞ/ÓÒÊÁÂÕÂwFX¬viþ¾ÂíòÉÔ U‰’œn;Âး®×åI¯áØLe~ëYLÞjÑ Öm…¥¥ÑËŸÐfiyô>Zhqù°'˜AZ3nñ  ~7—“¸eï¤I×ȉì§Ú®BÊʼ¢“ïßǽÉÊ€¼ËvßuÂÍ™Þú¹Kß‘€»=B]{¸Þ6j]߆!Ê& ¼9Q!e*·†3kÈ]Ëhª2ŠÅ÷ý~þ¯˜Œ¾½h0üŒJ팅?Šâý·" 5¿Ý®£WG6œO&b4Ôû?a¤þrîJðL5‘«Kn‚VÃÂ’)f 7Σ}ƒÃì©t•³VÐ>d¶·Ý·V 7Õ07'þZžˆ){$›9$V¦1ÁŒc1¤)RˆRèÖz‰NàyNÛIÔ`×{«ï[÷:§sëãprÿ/ 2'Z‚ŒF×rçú/]fg C*~(RFcpÖìxÔ°*àxáöÀ^} “úK@Û› ‹QcêÕxÉaØ?¸ƒcÛ%¢ ƒK¿uJÃ,ÈìSí!¦Ö5·RÚD@h+7n½ÇŒ'Mže[É!CÕð¾;1l›ŸÞ“ž«ÍÓÎBé¬Ð¦6—«|‚Ø>‘‹É“Ž+ôÅB*|] [ñˆYõž}`/”Ž-´Äi9íâtïK;þ½¿N|§¯É×õÃçq]·˜gƒ«DÇ*C;oS½åØÿìÑícYzü,IŒNÙÜÌô&' ŠVXìCÁ D¡)H)éÚJáô?€W´«ó½æW¯°2# §ûˆ¯Ì„@güðäqûlórÎÄÆãj¤Ù;÷hì³DÜ9ÊÖ:l„‹¼Í-ÇSSxù8ŸÅ} ïäF¾ƒýÄAW‘ ¤R¤RD² H”£…q[™U”‚q²N9ë”H;4›vÞ½[6 b*ëY½,îóÞNƲ€Åµ/¾hü€6ø¢DGhðWl[ý¥8@À y„ºÃr˜-ŸFì¹™ÐýÇÄö‡OµìãÂßò,á¡þš­¡QÝ5Š :*£¿ÀQù]ß“º]ñ=ªzB QöࣇÖó(Õ@‚ã'€ÛÞô¿sæûKí t ž¨"㢬U•h7ðB¢‚ B¡ÜTçE¹)½iGåaÁ—±µ+Ä ú+Öt]¦ð …({U°ë6»Áíî§øq¹!í¼Qþßæ‡Cí.üßÐv*ˆç*#¢ò6j=Ÿ·îù­ßW·÷×ÇͧŽGQD1àÆi ~)vÏpn’f^Ìàiq‚%&23‚œÈc34Oú[l>»y§à\4]ù%_œCR¼"­Z¼½ö± …+0¢Ñç­A˜5]ÒʧD‚‹PÜa©Ö!‡£0fa#Äå°RÃ` ÒjÛ°æΛ2ÿ¥ sAi”÷ðN+½+‚ýìQÎ Þ‹úˬç!Ò |û­ñÃRå¶GÊ®¢[õHÅ!¥Ô~¬]ÍÐ>ú¦`‡èÁ$žÂs bVJ“âƒrôçÁ¯g´Òê)÷9 mn™¹B«b„-4¿u¾D AL`¥P8Ò êÜÉÉ>7)ÖSÏ+NÀãç~,( Î1cä7ºôKZsålïÊ—uC'ÒØ½æwîWî·öb¤ExÅ€ 4*Ù'Ç Špws5ô)!oú‚s¼ôn«Ío&SÌî`*¦þ :P4 oÙ¯.zc¼z.—{¸Ö²T¥)ÂÌ £ˆ 7ô ¦ÓzÅ ü/ð":ϲÙà¿ÓïØ§ÊÞæm|÷òù]¾&ÕPíðŠDú …**E-«JTªŠE‹j¨ª’ÕTªJ¨U’)Jª©RªRªEy;«aÿ=þœÿŠT•¥ Ö•¨&}–Š/ú|Ž3µºø×K¼hyï§àb8z³ÉvÉyáÝu.+ŒpÊaÂ©Ò &¤¼7o>Ÿó}Ûršl–~:³¢âRFßyYàPBas: srè³Cè¹=Ñjaã$gÕþç’[›AŒg-TlàÀ…’:èQî:رåD2“ÐÀ¹ÔÞt›¹€›âøq&ˆ‹ªIOf^oŠ)¢nׄ'úãÕ«ÀpŸhÅRÆ ‡Ýsž¿Óƒ“q{ÈOy©|A ТPéÄØ Î *vËäÐnªG¥òÓ»Oµ·A9‡ØÛ„E;xd â_ãOøÑ]h:[ŒØ"éc7ÞY•÷˜Ì3}Àh2^r7›F<”Ó/–ž·CЍj[¬ö´`æªÏG•ðdç¾Â€D q1 ?!Èk„->*›5oƺ ºnžKRË¡ö]n§s@/$=ÈÀÀŒF3!ÀYë»ÎŸÙÂö48¾ŽÍ‹ØðvKè*¨ìuô?$61I¨¢£Nï¨!é|­^&´Æ3÷êïÔØ~}¿…èmQù¹Ý ¡gÚ÷‚äclùžSÍ'Ú*vawÛîÜW;írïùæ3Ï'”8ê • (ã€]“´ò*'r‚EŠ0B+l”,•lK"”‘¸&Ê’ Ÿ9ç>c„sŒ@QœÜ¾oØíüWŽÑô=¾Q¥4>Þ:( ·õ·¸M×´âþ¶ tâiZÊ{sÇ·´,rA‹¹K=‚hÇT)õúWíx]ö;¬Ýš——n¹“dC“é>õ=¹ñ½WåóŸ²Ù˜Þ¥ót©'E­ª,²€I À‡EÁôß öúyÀûÿãîüëóú’ü»‡cëAIíºßÇî‰á!Iô‘‚)D"(|ÛÙµœ¯7ç~ß*¨w†·¨Ë ŸØqÙJ—Ä9C•éÙer×îìC'Ë:‰.¨d‡Téë¹ÿ5ð<Çm¡ßþb* Ï}ï<à(ø—¯T>¶ØtÿÇÛd‚¢rÙ£­^+½u¼_êÿexPÌÙ Ÿ$rÐÁX™ ?¬\…ÓÎ~ÿ*™8!?õeåéR Pææ a¹2ŠtÄ2ç­ngvœU>Îó—„ÞP˜‰Å˜a7;fåCœÄc‘’€ ¬oŸÔÿi”ÕBã6½¥pAŒè¬Èx¸n ¡£•Õ ™Ò Qâ 7Ÿw‹ ]ü@£Eá¤Ò—Låy‹íJÝŠ4‡=×ö•K1Ý12 !¦ÌÔ¨@@¼!Ôn;†¹­ÎmÞž4ãí´MXLྫý™7ÓØdGb˜ˆ€Þqnü >ï—V÷‡ÆÊýhª*›¯MövxEúÖ‚;Lÿ™fȶWÉÞÆcôŸ9êz‹iÏ;Ôs{. – Í(Ê^¿)ˆUF†SlÝ éɈ;"ßÁì.¡7¹ÏD³;оXp{VaUûˆ#~ „`-Ñ·Wh+Û¤‡t?q¸òAÉ‚k@Ñ­ ˆ%Že&\Š.i›‡LäèägüŠà32æä”NiÏ6e›˜Ñüq²ŒÖ¢m5¯<> êˆç¯Ñû÷{]Wg|Ó{žŒ×à0E©"¹ç™&ɦPÿI~›­kb ^+Zˆ ¯°÷|–·ßY|6úg.ÜXo$û? 楌«L a—# •à5ô»N7}§xüÃ9Í!”Ó÷{¯Ûè{p70Q¨ ƒAÀ >¼bˆÙ$K$D®¤¥P’0PŒ 4ÝÀ (騂/Qõ~³S¢Fà,`_ ûÔoªŠ)Ò\Þ{b( ¿=Ÿ½òþž×àpÚÄUÇTGÒó~wØ~œàýÜ.é–*{ï[Çqž÷(üðQçýb¡»; TUÅ÷&­ã½÷Îü\g‰âú¿i¿›L¢m…¤Ü«”c†pOU¢¢.ù­úè*ƒ»¿É¾Ð-ó,c§f¸á̸èàH¥Œ_’æü™•3l[[Õ;RTÃbç©É´ÞmýV«»Ñ¾¯KÑxYÁoð²‰J; *a³€´ø´ÌNx¯aÓÀ·ÖªÔ|áÕ¸K|¢" F"&ƒõÓ—Éÿ—j-¯5:l†noƒ)/#–ÇЖ$ˆ”nØÃ‚Oùïy¢'ôÒÒÞĤ„âˆjy ýHÀÙ¼O‘LAåc›fŽÂTÃ&Õç>M=™åJ5Z-óÿQ3£³b"ÿ ¿vIÃ5¡ÑÎp3ì–›ÛýKÌ@ù½)µù}œ™[i}x^}ÆlG#°g[4A‡Ô‹RÜÕ*³…¯ ûò“M/—¾go;HŠs,[ÚJ5 §ðÒ5€;ãSש_¥TeX rûÆ_ÿø •Æ;FþC‡6Æ·y´Ê+G3û éwªaB™ŠßM§óª X Okín½¤voO‹ªÄHæuo8ŸjØîù/z›Ôëc@\ãèøÄˆ‰±‹jÓ+[“¶í³r«í8–" Zí‘òïth±ªï…NROO BDà‘žl9ë)æv¥VÐ Mùu¯ëÅrb#—È÷á\Vý*ˆ’1 Ä÷Ô,—xP†4í`D 8åÏ´Y^zYvÞô—€ æÆnlä’ŸµsêXµ±+æ%>û-cØòä{(òUT•VU©J•*UU*•UÅR©*QTµ¬ERU)R•DXA3Ïw4ï§èÁ|íÆ”=§ãÄýÇùü]ïññ]N@¹½é¼‘zoBŒGïwŠjËqâ=°?©¨:E<<4I¦z ¸µº‰zÌWª…&TÙÕj 0»`‚U£˜•íh$”ºº•cIÛCM‚e–Üìƒýðý¯3rpÏîçÓ/;x²i¸P m/eH^§ˆõ—£ø©™®ì%°êeó."b[7 uéÓÌ!¶b:’VEó}A’•Úñ<1ëÒoñ·T†$qo|AW%ûWš ‰é„‚ä¸#(5»ç>…È‘% k°Uûú^-§®2[:š^‹–Îføó9¿t«Ý€ŠÿÉínsÓ$DrçІ²ÇÕ+ü–dèBrœ[¹yãé·´üŽ.¹¼Æ0j"€"+±Ú†Èã‹ÚçÕ‹1­SÐ’6WëIíë.™` ˜Ie¸¿DSÅ_+üÍ{“Æ 5‡WÊfu>Û‰Ì}þñÅì-â÷ïÓµ¿îøqSæå%Q>´+Ä®½eQ6ä°ánrÊôˆ–-f‘5Ý# ©ˆšÌß9#kÐm`PCN©²vDa~¾u@ˆíÌôœå´·8<·±_$-§“ó AØK/V7}Ê¥ù;.^Cµ< ³·†ýB}DÂü7`çÕë5ù,91ÚôYzƒrúÜ&g­<ç¢áOÍŠˆè¢†q! Ø}6A£$F`÷ÒÏÖppõ™yv¼²åÝ‹ÙÙ:K;¶7ôžæå<“éͬ„öÄ=ÄôÛ­„Q™.;Xžç’á¬Z®¥=ÎFœ~µjnÈuA€ ]ì@@ =§ @k2;lÏ!rZC¸ßÓÏßrÙ¹¨ $hˆ¨üWúO¥¿G¶õŸo™ï• nê÷QÜG$tŸsæë=¦ãÄd|ޱw½®gÒÞ²ÔFâ*ú7~Ðó<ç±ë@Vè(è„  F«ê¦=%¯„ô}ö¦¦Áê/\½Âg~"íÑýNæPoVòti ì¡ì%I-Šë†w9øÑhRÆ"|VôµxúæQj‰Ý¾òg¥¤'2«+ƒ­)…Óêï=º÷ê6W§ÿ„û½Û!ú¼¿Á$b OÇY Ï#V±¢=_AdÀ-åPVƒß¯ ñO_‹*‘mÕŒ.ÕnjEÝïXÿ# 4Äž+ð¾rÖqZšeôƒAt=ƒ ÔöÔò%Œ¾/P_OÓfn !$£ïÚ†½u)Ƥ‰†\»–¬Oj½†)Îó‹ìZxsÎ5ÓPð4‘hÆ.^~«Zj?´­ƒ`ö¡ÇžÇÃeqvcfR® dD˜¸\œÌNÉ”¡‘(¾í}6¾öÃ<Þüí÷»¢¾ÖK`,û[É:]rèpZž€PˆÁýxéï‘û®K 0;˜øæŠš,ðq°Íä"ªÁ´Â<·D4_<ο-y£…7¯vݧA7ß<-õÛD£Ñšõ*cîQN l®qÆ7#~p ôcg@·€ÃdèUl,.3.Êé^ºMy LîÉ µ˜ppÇÕC¾%½iÀÃ@ŸåoL¨®˜£Pu‚1–þÞÎCšOsÌu†ÝsÛYÀúq8ÝŽÓ;å¼öiõ–Óf ÙìÍ4ˆ¦É*Ve›i`(š1ÓPèYÑ\Ó :v"ݼ°NÜdž›+yŽ’¥ôè0p[¼Ñ±×ªmø?wI=)P»˜3ŒKa• b-4Ï]oÀµGc˜õ$Þ5¸*¼Yúfp=>ùéØ[4"¥‰Û3å¨~8›ÑðÛ3à®ÁWXì2C§¥6§‹ZÏ¢¸¸ß´*K›S+“ŸÒö3ñ›6\ÎX{à7œDb×µ—Ã…Þß""»Nìm_éÓPÆ?®èä.UK  þôé'Õ÷ªr—;ÿM¥W7I€æ9œP_r&ßÔ2>£ÛÍ¿‰·i‘ñéÃuÓŽŽÕh%«·ºõ:ˆf0§ìŸÝÖ]Smõßüb9t›ªzh žŽóªûa;lÚ^\y-usòÂü­Ò±Æe›yž3E@MêVì2<O^ YcIª÷žêÐ÷>,ÞÁñPÞÛX¬Z­)Ü£Û—4«Å5;îˆß{Ü‚ÕѯÝ]ø 0ÊÀ¿Ôéû•Óþ½ò!òáÚ"öfà QÙß>e î#(€ØDʈÅuîê?·»üžË„¯³ïTZ¬ öÊÄÐüA¥úmSë³úÜçfßdºÉÒKín„QAíË­ 0¶mx[Ÿ½‹S‘û¬2º]vÛV)F‚ƒÛé/pôèô‰¶Ðí¬ü€1wTbÃ=…Ð+ç% =mÒG‘‘ä>ƒI®Ò:€ìËfÑ­ìþýzÛ¬nDMìÚ©:S×ï(£A\ÞT8z°îO䉗¹”@nY3Å6‡XYtU°ª$h‹tDl`{(-[¬ë~®¶Ðö €f ã׬Úí{¾gáyÜÀ—ãGàmT+—µè³[TA?ꀨª‡÷ÜÏS?¥šÀâ7ÛÑõŸ®Ð³ õœXl±% Ð)³ ÙdŸ1¶Ô†˜çbþ»'0Sx” þcª%# Ô½«¶Ýi*+É1KàÌ@À7E“¹ù>“•ÞëŽîúºèAáè¼@(é“ÕN§[šú¯ºË+Èn¦œ°×ȋϕQgrô×:o»x¬õMʹ›…ûþwü7Z¥&¿?šžò{óf‰ì!¯5C¡')ZºådO-—aŒcwÐ}-5Á0ÕáÃM’ #ïxàÙTAya0Zµ­ÇŸºSVSDJ§f>OÔëêm£%øþ4:EŠŽÉ8”ÓùM@Js«äC«IŒ„_pèÒö»¼LLÚ5/ã.àq‰T}ñhsêšB%„°è ó-cOùc\È‹ø¢:‹®ÀyD"àÆ²$HèOŸ¸V‚¸ºüƒ°°Ùu.!¡g:hcTT‰X 5*vŠrÑëî²<{Á;B!Ýèd°‰apPÜ-Wo©ÀÈ@j¢­»µžÖÝ™ãå}Àõì±®tMŠæ—¯žÚò" ~fmöW¿=*Ô¦•ô¹]Ip¶¼jä@¯Žñp’÷0Q¨B$_­Æì÷\w˜.Ýñÿ®µÇæ+\åß§»CÔÒ†gB Š'}Õq5(ê½ñ;•‘gù^³m÷î/ø÷p À %‚`@O-ðÑù9ýʺßKËlø.‡8EP €S²är”@ñ;ë#ê긧w‰* ’¨wÚ4@Oøs¾PãŠYlà €Æ>÷fòˆ.lwj_æ;*ïÉîëH7{?æÃÊ·UË}ʹGÃÿ?áwâ|ß#ø ³½ðvêGÅŠÜODÓr€ [*T¸eÕ­¬¦º‹ìð¢Qp/˜mè†vµ}¯–È]ÒTá@î0G Öfœ¢Ãݾ¥× Ãô¡&®&8½+о{lÎ&µË‡°ó€.÷®ÄæñyðÆ7w—:¬G!¨å:V±}™¯¥‘¶ H®3}ö?°ùYDJaÍ=‘Æ Sãl1¢Ðw…ä½x·DÆ™i6Ù”!0ñW›™]Ã9 X‚Ô†(t”-‚Ÿ#]-­ÎuX$5½£ÄñÅhÕ§š`÷$åÙD"÷Ó·óÆTéAj“ÙûCSmüËš¥0sН–@s.—ÿY –˜¸гFÜÑ| œJÏF±&6“dÀzëPn3'sq âî_>j<óô>!Ýöô&„yëÚ7ãã#Sn«»ŽWÒfOãJ‘ˆ»&/+§ 1òü+·ëã¾{ÆÿÉŸNÂÌ_cJÉ ü_+ù9Ô‰LFðl¹ª%㟗$±_ò¤âè3ÑŒÌ;­?å8e¼5¯û¶Yeið8ËøE»k9/ç†ø ƒªÝ>Ž7ÇüŸT 7Ãôdªµï¤6Øç‡¦ØU¿×ré¼¾z¡„¸`¢Žër?GÖó÷?ù3´¹{Û¦ñÜ߈鸫ž¾ÝÕŸ£QX €EAR5átßújµ]¿{ÿï±ÂQ¼î¶wß>å%MsÙ¼©á‡{³œ»ðš+5¸ûE/f70È ‚YÂCkYç<Úè|oò¥mså¹¼²ÁYÕPøÛ¯)½ÇàBº}ÇÛ‘?aSÛmK®ºšOõôdœ`n©ê~îD´e‹D¸h]'Ê\ qQ÷ubq²øRŠ·±2}µ4"pWÁ×»Vkø'åÛ;1ΞDJ H[çÈaÊ!%Ýl,OàÅŽRåHšˆ´ò> ¿*Ö½"ˆ.œêLC?>˜xÝs@Q'-ÚÒ yݳÜv'¢Ü+eîÿËAô~U­wÒÃX‹[—©Àmì8îG˜Ö=òÚW±¡M‡·åÈ'_¨|J®<ƒ:p©ÁÎ-¸B>ñµº ï±L—§ÀËEOĺKÚ0aï›–¾ƒ ãácn¨OQ]z­g„mv3]Ò eÔª'mµÚ«ëß6ÍŒêÖ#IdžåÝ ÜFèÖ:¥J`)ú¡~ÉêʧVmB^ëú¼HHœGGȷ׫Í[ÇM"ÿçå±”ReñÅñŠ|}¬b|nJ¹€ÇN8¼õ‰3$ª óg×M‚øð#åûd‰«)°„'ÇŒÜH[cj“ .…ÊÓâãt\eÝCŒÃëÆÂW€¿ï·¢|ÌçX\3†BHÚ\ù@•( ¦“x=_Õö>áù^»ÎÇ{Á}›ŒË¸?ê’ó´›9rÔ´¬»N½íÀ€ äÜî׫9ö—]R«íf¶Qs¢wc´ijA“ÂLBxIЧM2©‡a±ìõê ž<mP ¢½ÁøÙanéYà$YjUÂÿ\%.úHþŽ‚1_ßNÄE¦»ŠP@~ƒ»-šö»yÊܽÍm"Hˆ ¸6fÐ×§Û³pÄ êMËæ (" M›Tî/-¿&êèV‡Vÿƒö ¿4èº(#ˆÝк{À!âÈbRìS…Lª°‚¨ìQÆK‘xdÞWs¢~’!’pÒ;qHç1Œ1¥)ç{NÞo>×ä€üA0ª"WåÿŸ‹râ‰K¿œñ[ã¶4›ìðlè+vV˜|ïÖ^[j©~"bð%ïò¾Ûe,¨Aã ZšºMDXpÒˆ Ä5LӃÚ”QàÐ`2½b9vïgïxúÖ«ì]ÀMFÂÙÆ;ñ¶"f<º57FR?z {Bz,ŸÆà‘z‚è*2à‹bxÅV3²¨pлð ²ô€ã·¿¯I?À5¶zœ¤â~H»Þ/F•Í®_vÞ–‚Í"2°ThjâØ{r¤#Áhh ¡tCæÓ5IÈêæºˆÎù6rÏʶžÇtžÃÓn¬f®0¸œå2(Ʊ¤¹Â §df–æ-X÷]­|S;°ìû¬£ý™¨ú}“{Âè&p¥!3híx×:âäÚ,7Ãçž²øU±ïe…0ò2¸,jsdì ƒM—4Ó¿ê”ôYõÒÈù9Ü€ÒÂHx™´×sGDÀ×!¡ñ“îÄøå2›î¶d•œØ‚"¸ðr¨½’„ìq5¸ÙLúÈîþ²·gª(ÉRèŸGñÄÀ ÀSL2¶+fèx\üܯ5_ñÀIÆËÈ`¬w@ø6^{šÝû5ŠL­ñÈ*µìÙå§•;Äĉ™nx0ì„/ïkÉFÛ´5¶C[ ÊoG‘q¶ÿHGoF²àhæ -À×òÄRUåy 3í°­žÉ#v0‹P­-°*O¥Ë¦#-àç‘ wNš™Ð´¡S[Ù¦âÛqêôXB­lä:€ƒ|î| ŸŽD±KC©†µkÆc¨v§›; Úr!IJžÎMtÕqÏÁS²#2….,¡Á$úk±2Hž¤¹Õ§¥ÿ€1ðëùÏ0BîD¶ôm¨hŸ·}ûbFm*¾ƒ^ó߯q¨¶^ ýßa1ÂÇÚ0þ:͸ÖÄrö ˆˆ KÞÑ÷é3Yûò­å{3sÅÔclX›p{ýûï=—Éó>›r½Òäò.æj¦-Õˆ‹\c`¼ú%ì•PBĨÅïnw›§Õí$°'Ÿý½N1ø0örµ÷ÖÔ6y.çüÀÆ.3|šã‘ ›ßÞ¶±X4&"ã•ÎÕ~¢¡ îÇ"`Iã1€Üªú1úx/\M…Œ,âÃ1…tïL=‚t{rꢠÑŠˆÅñH»ðª0* °?]FŠÅ"œ„D†á¦ì“ˆ¶ùò ó®èާíl3ûO’¢ ö4â(ˆq†“(Òl(qˆ«<éˆDXj8݇/ÑzßQïÿ—i™ûsoO¶{fçÄŰ b"æµ'€@¢À"§}ÚæØ%»¨~ Y@íîÛÙwNãW&Å-Tõš}ìu-Î$óƒ?¥Fþa _ÐS¢Ì¥‘Ù]-sPô§Èºq lp)ØÚ %Ê`þ¼œmÜÛÚºÜ48o·d”XÒÀa¹¬ã»L¯—sÃ!!'!ƒÿ÷Úü®¶¤P9­nh:På%ν‡Ç5ÛêéÁòûÞÙðVópp–ò~3ã0ŒÕô0‘z$Ù¶\5Ø”½ T•`'‡@º$‹æG$´òUZ·ÈåùŒ®Ç«'ÂÂBSt¹S‚°\ÃêÉõÜ&ë‰äZÃ7ÞÈ ÏZÿœGwg;Kʼ¾H>ʸ‚¿ôyÆ—cè£AŸN—nWËGËPn|a©`X&ÁÔ”LæÌOñžÄ Çsp-—+U ZX{›c{ Iè°' =+Ïky¨üñ³»Nw[×ÅGïò§ªÄw¶*/^5‰Ë—jXßHYQ6Ó®w­Õ/š¨²"¦‹ú¦^ó®Ìª®)°``+Û¯WO—£ƒÄ“YVU¾4Ù-×­,Vjg/{®Îç¬ÂÜ*+©Œ@sÌ@ÁæÙçP™=hƒôG²cR¶n^9?ž"Ù]࿾¦pÄceä-ë’&2 MÁ1÷ÚsÞ®rH¨Öš·q•ÿ¿^îtÀ•G5TLFЈ]òÞ6¥²@5犨Nwã}Nîܳ˜Ññÿ»Ï8ÿÚó$õðɇåþç»àÿæCóˆZªÚÉm$¶…¶Kl-° h[BÚKi i%¶Kl l…´-²[H[BÚBÛ m h[d©m…BV°•-¥d¶„¶¶–Ð h[BÚÙ%¶´-²…Ki%´-°- [d–Ò )m*…´…´¬©-¡-°+P…´-¡m h´-¡RÚT-¤…´-¡m l–Ù-²[IR V²Kl’B[B¡Y [BÚØV [@¶Ém$–Ò[I-° hÒÙ%´…ªª´!m’[BÚÛ²6€[d h[@–Ò¥d–Ò£lP J JI$’IDŸÐ|=7+Ùb©¢á((¡óú¿ãÃ} ç¿ßÄ=0†ûøŸ·°üAUO£ë²@ûÓ:jÑôØšÜttNDç¼ϼÿ=Çl/¶ý^—‹÷œ‡Ô Šï±€L¦ ÃìOÙáhP I˜á‚”ˆÐœsƒ‘WäiåRØ <ÐÅõ~f¦­'Qåu-G 2"¨¾CEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE ø?‹þWþÏ÷·>P!Û°!ÿ<¯«±pÍæµû·û/RáÒ.Y÷-! ë,›,Tš5`ŠÀ °0Ÿ¶äaÍËÚip9œZIŽ¿Jõ•b¸èý Ý¡ú±¾`-O£¥-Ž³ç’¶»—ÐÍKÖ`\•ç£èYüt~Cÿ®E¨®À~/câTF!}L¸}¡½¦ßMì9þЊéÅ(ãncŽ5®a´‘àÞkjdZÌ rŒ¹'×¶{eèÛÐAq Y+GjcªÜœbã-µþ‰`¦ïµb4ýúh¦Ñ¿XÊë"= :¯¨Q©·êDûë+áË¡\æ«û;%ØÑ~8T˜ ŽÜ­° ÎÓìŠsÐ×€ÁP#È*­]7s½h;÷SE³Í9™•@v@1§;D@•g²Ã¬T¼§Š–v7ýÿAß~÷¼íέU$PAZy¯¯¥áîôÏ÷Ãú½Ïóö[ßUØ/æÆ1Œéàj‚¬µ¶/`³BƒÍ] ùUÄU fÉ{5ô¼Jj}×\îuno³è—èÝð«-„B€j.¿$´Ö“G™h´ DF @|Á"TA‚?˜lÿóD‰Ð}hUTª¢'¨Ÿ÷Äñ=wGå9TÉ(‚},‚sü/Ôý^ÒB%DH€ˆ@®Ã~Øx~ƒÛwj ¥ùÚuCït4õ›0(u[ó¶oïÈd/ bç1¼Þà @Øûmž~«µÕo qÊd55,µY;RgÝ)äzsIUΞs¹TçE´·ð¥þLî>ü¢Ú¼åÅ–;e¤çÝqÕPIïs²¯âs1× @4rÚ:«U,Zà¹ðú\ÆQgyØŠ%˜H $—¿uæïígàóWÜ…WŠÛ„j–](0l«Ÿ˜s”œË5±A³Eâ!ö" ´-®îœë@fÂ'{&°}–={Ã^UWÔ7å)fdµ÷ tŠ—÷K•Òù°™‡a ó}Ù¿‡sÚ .Ã…tû‹Û5ÜÕ’›L Œ)…%rQ‹#gâ@.¨—Þ}`ìrý"¥!S¬8ìÃ\..U×}¯Š=M wª ô‹ŸÆ¡C‰ÊÕC ¯åj™‹1¿“‰ñÝ-LƒÉY9i§ #kp°¡[dfÜ”“Gj=BS=©µÌ8k~œÅ-ÉUtV_ÌVá-?£KôÍ[Z,,Éôƒ}~–PDþ‚mf¸,¸ C§}ý=‹~ú“Iyð‚ëåÄòBDÜ`½³)1¦PªF›éêCøÐ‡Çü›Ðko¦K„—9Y}¡gVű¥„ïSg³k½d­^.9~–[á݆Rº"'wηÊbrü…›†è½Ž¾N’ž.uYÒ³ÈYvÌù™³šê—ní]õi²C¾¿!hÿâ1Ž `$P¬ä"a„80¨6_³<{&æyªB®Ù²ì4=µÚùïIí/üuâàÊ.VÇeüÐùwPy—·7uÉç·µkrío†ƒ†µ{ÁÌäxuOýijB:,ç$-S).=~T6 Ÿp£ ÄUiíY§ £á2th€#8².ŰýmeaöN‰²ÝJ—Ó×ùÆgúõ§Knî±_ÓÝ"[˜ÃGÈ?š_Ðê2Š”p£ ÚÝ ö€™ÊáÇ•–$8àö¶§;~JØ*ï¿  ÑPŽù‡¾D´îDéÉûþZ‹Ïöý;Èøտ¿ìœQ¤Ðç7ÕþJF®+7†ú-»n5'ëdµ½qn¾°€!w¿|Q“0líbéњ˜'ô;¼Ö>dKý·,ý,3ãÝÿ V¯˜ßnzáéòï|Õ°eå-Èß8ê?÷YõdÊç°žqdŽçr Z!¬èa!¿ß¼61¦Yµ² Ôë†{zG±,îŸái(ê”êðasñ›QëÆ[@æ\ ½`è[%c8‚ç»ŽÂØÆ¥xOÓšõG4JøÔ§D³âMÕ~TýEÄØVÏwù8Ä-تÔ%?CÀ1`._-ñålr+ªìz€.g»öþOÈˈ F›ªùsZ"^‹©ã]4=t Ðëz¿ £<*¾z™=¬9¼ß&%"Ç8Q˜®K'eÁƒëH ‹ÀðûÄ,¢Eªéo–Š ¡ÙèŠPŸ~Ó ]Æd„€áCE«E«M¯p˜ˆ£°J‘ßB¾úËvòDY8ž§½—€4ñ6v–G v.? g<0×BJ»yëƒsNÍ-bªªAZÁ ¥0ö u`“m‚Xß—]ŒûÆ)@ìSÞþ\Ë#®ËÅÇñ#Ø´Á+…ªLû]¯0l7'ë°ÑxõT*d¤s^<ÄâhÉg²C©ôdi¸D c……ú=Πœ¯M]¸*>’_sÏ?;)“ÏMTfݦ¼Vÿ½v#Sáxxiöú/*p;GlÑ;›yÞœžü]¥4¯Åùa¦ÉEܵý“>:NM/Ë(ÿ*P5‚¢„ÂõAèGX³«ÔUC¯çsü©e‰qD””a†Ä˜×'b…^0ÝÙÓ=¸›É%b†2‰"FŸY ÛFÑÚ9;b¢‡˜9HàH„úLZâ<ãUÌ&45ƒ ò÷"z¹Ÿa½®NºIL Ó… 4Ù¿´¾r†ÀÒ|[ûL¶3½¼Ú† ß¹&›ÉQtz# ¾©ý>M¢®ë=£”¡{%J»*§ÅKÙÐw}0NóÌÚ$AØR™+.R±“KY£è7푉V;*eŠd_y«‘;õg’õèÿ-TÄëñ±m^ÃboìKçSîÂä5AÀ4ôŸ•ÇÖŒõ$-B Ùm¦Î€Àà—ñ¶Vœ½Á¹\´•ý‡|×Q9¥Â0f-z^;·ñèsÁ"5Š;÷QZç •®oçê´MƒÎ/øŸWÚátµ¯œ æ Àn FvaèÌNÃc€'XhlÈá;‚ɘØòÓ¦»fsgHdªNuQÄ@û‰Ùc&–‰KBØ“ ÒùMHA·ú;ý6hübIïá…ò,«„È|ºŒœ7X¾(<,TŽ8]5p!]kƒ™éŸCÀ;$ÉÌ«ü:»»¯M”O•Gtå¼f:qL[2¸NDØXë!œ+¨1ÞCi¥«ÿk&ÁJ=XpÞ{â«tæ õX _ÍKö*´baB ¡=ë ¨d N˜”1áÞLŽ_NR¶ÑÆTj úÍ(‚¸K<޳•ÉÞ,]jëùG¼ùs®{Ï[u¶vCÞR9†¥7tÝwtcÅ5:n†vïCëMAö7ÞßÀaðþ¿ª<£&¶P‡yšSåÊÔ­kRµ­kKm¶Ûm¶¹ßëŸ÷}7ýnŸÆÏíýÁünÿzz¿•û~± ÝÒ˜ ªœ¨˶™*¡”EË÷¿¦F]$e´´‰¾Å3H‚"Hª8Öí*"}¿>¦f¼h®2ŒMp½B›Tké1M?¥?¹×­MðÆá¾Rz@D:@9P‰8¦Ü:ÙLÙ…‰qs¢)!H Y ÅΊh š"6ÌÁÂEÇ2uH4Ò‡?5‰My"r9FFÌ%8Bf¢ª»!ߨïÔ2Á–Öw•–;ö~çO2íá{›p éósó1¹åšJ²+n6!5ý®-t—Rª£]ÇT¸´?Õl"Ê•K2XWß÷w´ÙhZδ½bµ P2@s¢ˆA‡¨ü´O89Á²Y¦¯ßIø'è?•ÉÌÎcXœïÓNèã=[xä‡ßx«–ßÖ¶W3µtÑþd´ŠÚ›5‡Ý®Ý™)’œ„‚*a Sbå X‰S+^ÚyŒû£ì¡ê+qïKòÆ 7†œ;|÷ …~fmƒAέ/7ƒ1‰ù#"Pæ `Ì&Nps†4jED Ç–AâºíŒ[vó‚§2î— Ìàñ¨Ið!|Ôg‘Þ¤‚R×®u×ñ~í»šHÔ›TõwFˆ›WÎÇá€Mª"”„5@·ºG&7|"“ÖNãÐY»«ÀTà¡qèmxÙk°¡êZd!Ë‚0Ñ"Æ• …Ú” ¤:zE˜šq> ¡Ì àâG·¸KßäN ûu8Ž!®£Vô¦É䢯GÍñø‡]c»¡»¦gúËöÕ£Ã4o+ ½Ä ˆq@*c }xŸqã_ýá_ßt÷«û:®J~Ìcs}“¯ù u–µA)ñE¥µ[Кþ%Ãþ° Œíú•ÆQ©JtÕkZ¤dÑþÞ_}o[äà)µ11¥•®ûÖ¦ûgeÅŒ·¼¶Lë …´iwZåg«£F3‡£=½€¬LÕ~öx}Òîs*¦:‡¶ÁO T‚5wvTAô5†09+Ð\e|·k¥¦ÄÌÖ_{8®¥|w3lÀ ½×rn›&b„WÄm7Ëx)S+ÒÒqÅŸU[‰™~¼õ^ZuXÇDL´ ìæÔmü¾µVJDçA43cÉÏÍñ!ñš…QtkÁ¬ûmÞëIÇ„½„:˳BQ xß.Ñ9³{(®«Õ'w;{‡ïæ4<òs¼™»þþË—>NÆ!ŒyO˜TÑæÈ¡ãòÑÏ!äο3þ^gÂ`DÊÁÀ&p¥xOu‘Û÷rüao˜Õp#ôh³…°¶4mK|È•ñë¶on[>®Ç,JÎí¬ýpÇAP ‚'k›¶«+ãé~ܼÅîBhÍ`Þ Ì4àÌä)@á œTÕÉþÀ’|}£«3UÌH…ŒôG¾yõ "|{,uÊy L!sBe1áGá‚ù.J}ÿ§°Nfû{ Ïš}ŒÕi¼ûËúŠ“@ rEÆ.™æËÜ©ÝÏ&ç~ÍöŸê§{F ìiIÿm¿9&<Úœy}ÂóÜË6Óm…¸(f»Å¯Ø¤ÛyÎ!j?/ÙYéå‚’“"F)€àQ`5$A?è`ÔN85»ï/g¹ŠmÍÿsùĹ|õß+ÐjöpzTŒ¶¤'v‚-_¤È"cß ÍËïÒ&UáY¼?…å§}&®+~ÍØqUc—ý$È-—éê]d¦2S+¥:@s£´“¼`×K±²@Œå†}îìœe?¾UÀ¸cQ±2µ$²ø=¸­ÿWê{%aUNno½øæ~gL}]Ž›||iàó$gFg‘ËõÖª©åSÍ»^Ækxé½-ü=? >ÃõÔü£±Û©tûOýo“Ëï ô3Úôö÷œö.¦´˜Ž­Ôt›7½:]Ûi–Uö)S†BX@ØLÂÂl%.ˆ†aJi4‰¬‰I‘1™Œi©¦±nY‚ªÄƒùzûZžÇÅß:º°ÊÔßþCÿªßö|=îÛµÏy‡Ž,}¾ö[6ŽÕ@XeVfgid!ÀhTÿf­)Jâø«^fmkÜuq˜ºªÞ Ê´QâªÎ°ÐŽ¥(Õ½-KÖÔ¸œsœ^«ÖïjôÖfœ5uD¥D±0Ã# 0Èà 0ÂáL*S ŒcY4a†i¢«J•3 Š´a“XЍ•Œb±RÉÃFV%pÑ£F (P ÂfçSlºp™/4åÊ9ùyˆ!" ˆ)$MŽvRؤŒIJC 5HwthVtUQTašîñY”€á™¡!ÈŒd†2MugCô’åݾø¶š Ï‹Yoõ–æ97.m»oX%çÛ.Ûýïqî}= bf-3ážôžý>Ÿ¦Ùˆ±b ‚s«Cek”Ê×hÆV…>5×5UÙ`¢¤éï5ÛfN“äÝ7Ò¹³\Ñ|©LÛO¸õª£g—ë3°71ÔGë¬]R|´YüqhWO“önºÓ@eĹÔ/Î^ªì)¼`Y–fëÐâÕ2ÖÈò³³Š²p,ì^+°Å{6ô_1ÆÎ¦ÇmHØ$;ºÖIqF-½ Ä¡Óq¡Í¾•^Ó–¿|>H$¬úc|^LK¸¤:YPT XèÙŒ¡SÙ“¦Qçü6Ê6¦°";Ôe­ê¼…× ÀEÁWWÔìZJ>vÓrßÌtå_Á:o—äך2œ÷rèÄúêÂD7 ÆÞŽ O¨Óe{¢Ûx¾ZÍMÙ“©‹| ¦!ôÇœA|ÄCǾMª$‘™#ÉPgÚæô°p“û‰X40‡öÞ}¿’‡ã2u>ú ŸòVåE&%iäèÊÈ 7O!‹SÄ—ü £• H¢^½vák@•í¸Øçò«øòïף两²Cn˜¤¨¤=Ï~1æ/8—o/Ó¾ÀJRcOUád‘ÎþÈ hߣëy“u)tqaéû¯ûœHžºŽ@AýUæÿ_æ¾ù®aH†MìÑØ«ôJ&$<’‹ýœ < ?–ó…½ù?-á}¼O}ýÿÇ•5Fªä’>2ºªˆ¤GÅ«ÆVØ´#®é·`Q]­¶ˆ±A oïõðŸ#Pð<"´9ਠöÉ Å…¸PÝúý6ŒÑ¸‰°åÞ~Ÿ¹×O OdYÖy—g~¼G¿¸FfŠàŒ5öZÿ“ØhöçøE«ø&®öu9àøÎP^ÑÇ÷Rú©þo»ÕÌê·:‚ðöíÙМA}f•i{À†¬×1Á–k°p4¨/>V5løØÔâÂíoÚ§M¾¸7Œ¤å¢ÜmÙ³¬S‘ð´ {ÈÅ8–2ÙOõà}·¯>x}ŸåÛ5–öà˜R¼ý¾{aí¦¬µ¶K’’…*'6[õ®Ëð/^,‹dU¾imTuUQ¿ûÜúá«iÞ«kÜŸPýœNú.B„‚!*IB‹lYEÁ,©*T%D¥K „d#$`ª"D,­ 0-*É…•ÁXŠ‚£ˆˆ¬Uc‡õ½Ÿ‹$OtŸ„^àDóÿò÷E¢¥Ú­ ¾··š*ÂLK”+ûˆj¾F±Q­—¾î<-#R-h8¤Å-TG¡r D1ÊÇ!#ÚÝQ½•s®¬¾EϑÕÖààäthÏS4­¾úÕHÒÇFüÂ3¦ ™ñ†Õˆ?6/–²)vÀÆZå–,Κ¬+gÁî)•%«Gg{5 lÍú6ÛÞVÙ®»i¦)–š™2ßÂk]ï°°®9Â7ìë™6c·cMk%ÙÞ®5kšçº°×•][ .Vø*óºm‰¡UsfÑwÕªµá”™izÎü¯»,RîºÓ5áKÖÖ±ÿnÆzzHR8NŸNÚH¸ø€€0Äô·0mÃ&£¼F|’CÁù0N§±¹‚J7°$òf9‹iT³p‘>G®ÙjϾóó·ÎRDM•Šˆî'qEDm*{Ž'³Æsõ†”5šV’HI B0!$ †,ê¿¿±û>÷ì:n¯ÌüîŠï¤E6 ¶Ú+—nZ%Ê·ÇE…6©nW­HØÖ¿ÍÄ}÷qô¬=ˆ/€6³óv°%jÑüÿ.¾AìüI ,é9|äáë/µhÃcô”#²eÇË#Ýd_^ Qú‚–åÔvøPZ“¿ˆ‚kü2Ìá4ëÞ‚14ލÒÁþ7t1šÞò èèÁÛÍ0ôŸ'C6aQ#Ë׸÷¼Û»ŸUVËìÁÅÀäA†,ÖU>Z÷žokUŸé*2½P‹Îѧ`ŽWIΡaÚê—¿ÈU5P÷_A+¹Ï,C…)/VÓOÉâ`°u}]ãqǼ¨8Ë9~;άªu’€üX¤È­Í4ø—2-¦'¬è îá†ã0Ö`Ðg¢ì¬ l~΄o0äÔäÎÑ|µ»Za| †ÍµÄŒæ…’ áæŽ_ùE‚a €4¹”¦¯¸Ír’jz~3÷S‰¸W^“oÄ~t úÚÅ.øi){/iHˆo ͉ïó;{Èd£˜¨`Hˆ¸›OÅÆéV÷°Ë@=ó­¼ÍÕ˜E1æóGo#ö˜Æ748:¼mG»´ŒbW„¸°8(Õ3ëÓÙÞ• Ha=…jTA‡:;º58 %ùΞ=ô{éÁ.0öxVf¯›’ ›‡~?÷üðÔFO 5Ïô)TwÁlþcˆ*,g8²E#®óŠãÇU,ŽÇO´!8õü€0ùB=@y¶;c" V¸˜4bo}¿DÏ’ó¦ôCgŸ3YŒ+3S›÷€üìöû)”¸m ¼Mc®‡{ºu°ØQ(Cý£tƒèc"Ÿ—ž.~ç–ƒr¯V²uIÀ[4èä²~ÎHBq¹4tœ¼"e‚ÙUÎÇ-bN¾K£{B§×\…C–E„Ò3[ÀWrX‘”¡ˆTëýõ‹ñ"pñ&ôRô•ê¼CæpñÓ{øŸkéÿM¦1£½DÑdxpµ9ˆhK—)½HpÖû£ðªûÏrqç#Z×I+ÑYYý¨âv~gÖof·‡]ð?âÃŽÁ«Ïm˜çg\!UÙ”_ýiH0Ìì?Ι‘»OãžtïnMÌŒ ¬§Ö/GÏi©ÃW~\£¾pèüĨŠÇÿßñ¸)=ý4—75OfçúÖ ý¤„ŒÚŽÙã\$§=”O¿œ›GÝG,²7̯€ju“ÑÍXcN¶!ñ/â¨ku7Fåm¬Ëõëg÷’jãGk²uÙn¯Q¸öÐü™úüˆ‚±Œ³¬Äfop]ß¿%ÇÉ}Çk·©QîôØ&^§Ñå¦LBe£ŒÞ`°4FD@Òc&gNÛÖÀ×ëÏÿ±ü§úÛ+½ÆÙU³§þ°nÜv˜KOŠ_êÂë=Á0Æ›A¾ í8m}¶=Éx©ÂBŸuÜõÕ Ö~ˆq~uíP_¯îw BmUJ”A `eT?kÕ,_¸‘œfé,ƒ9Î`sœçVÏ]3ó©·Ý;¿À?–ŸäÞ~‡Ÿžâ·Ë×ú4äIˆ(‚¦,ÔÐeA]ZK&_ù$ýGö:Ê'/'Ñ|¯Fî nÇC·~¶Ì#äÏ=Öæ×x)r߸yë³j'cç×qzîvQu†[:¬3$>Ž…U5£J•WWVÝv}Ê’©³1¾FÍšÝsÅ÷UЍôk#(¢ŠJÕB™aªÖ³çbmÁq“$.jfÏ‹­ÿöÿu³ÉF–»ê©døY­bq­*›,2­´»R:ß§üùÛ_Ïÿw>£¬ÚgÔD7Ù¬…7ê°P°+ Ô)‰ }úíþ³ùÊç×À›&ñWN›F§!½ÅÙÖd—©²û¿rš,‹E–ÇÅýl~beze_ŽìCÎ gÃ`vØ"j~ÔnDKÓІ1Ìu³ s‹/ç°Ä4ëãÙUE‡;óo;:3žh¢òê´.I[´j[mÍ%²7f®ç*"Ž÷”%Wާ“ Ê´ÒAß èNRH¬H-&š#à°³T+æüyù¡{ÿ,YÝúÅIh•t^%‘z¾ÓôÖ!_ôˆ†DC]Ë­¶gþ:\ “D>ÈhZ]µANzœoZúaÐË’Œ‘$==."C]|™Fü>M,ªÃÕÓ삎°û.ºö`]1V}|éuþHæÝéxðãy¯ÝÉ6ý{ÞF]‰îô$ï©:\ꥋm&”ÂËipe̶ۉ",‚RC HÇÆ H.LC¾j÷~äÿu:¼9 ‰´Îû (éS.Ô=˜Ñ×¢tb.£Úâ·œùGDH’Á‡§³5gv¦ÿ“aÛ D®Åøª¨Žœ;+…ì 0 QEë|Ž×Zˆ¦TD:0ˆsóÓêÞU+kGÅ“}ûÏ2°{˜49IŸŒÞUËŸÕZ}«èÒ FWEÌ_ár(¡Ô­ÔhAA9‡Ÿ°H…1>sj™Æ!‡Y‘Üš++¡B¾´¶Hðd„©ïÌ JƘæÂï/*wÕë-½1 ÈbnUÒo@‹ê'°X`©8,0°´$Âúy!·®=óa!4R‡=Ïz§6•iÞÁÍ\à2Yÿ&ã:“Õ (AEÞtY½ õ¥B˜ÕyŸSW^?V·o §¸4ætÜY+%¼/kB±ë©æ?×K³ÔqŸ[c²¥¶‰BÒåiHsRŒƒt –Ö…kJÉ1¬­j$•ݼ¿­é¶vÞd| ”ÙúÛKŸ_Qnû„ØóýÎR¦ÛÙÊ ð³oYm d̉ê êé o­ËúPÎŒ|—yÓîö?[ð}¸˜CwmüÇçºëš–·…¯_‡öÛ¯0(æɰÆpp\÷À²;ŽR¢9AìºÜ<扙›•‹å=”½ÝélDŽ‚ ¨ƒ* 7ˆœÌ¡!‚“œ˜â?»„üï9˜o¯sb½Ú”`Ð;†˜c‚wÂ" ºi& -- Ò›cf¬CŸÀ‰Ôf”µƒg¿6Ïœ¦†Üþ>ùt…¶‚-Æž™|€¹GÜïí¸üŸï\„2›°Ä½þeîT"/`ájÁÇÆS$ÄFT¸B:ù€†(vY$:¾e}l£æ-.wœyªxêqÙ|„¥“®38ÿ3ö¢1#"H¹æ€ÑF¤jF%O"ÉåÖ-y\'œhÝcI¼Ö2g»ñµ>3ïÓv伞ËÉ–ÏY¤ «ÝK)kVäÊM8ºRÊSæÄü…ÆØûö?¦ïŸßsçÇ6Y~;›«•rnÉê¼dŽgrzÃÓ6 W•’ºHðìôõfHú|Ôõ¾f}-v•ˆ¨ªÊÖX‚æeµeÞÂB}Ž´À±–6FBÍFˆ·s1¬÷É~íÈyC“(8ÒáAù!!=ïâùM'’Ò¥YT¶Ïô€ðeLÓßížC¡ü¿GrŸß^³€€Öƒ"´‚ dñ˜·ÔQááY¬8‚+ˆW¡½òJ„CdÌ!¡¤¤Š[ÀNQt AЉw:䪊¥±»2:މÒlm"¿>êße"CM˜0” ¤ýC‘º¸¥xžQcÒ T[i;€ç´÷¬.¦ ˆýßéúi€ ½Úe¥ŒÄÀÁ€HK##1 HØ%8ž>÷}¯¸ ’Š9ùô$MÊI d¼ÀΉC~›á㦊ᤈfÇ]*¬¤RŽ Ì0’SÃùá‘ܶÛã{½¶¶ÙÝcݰýÉéÁd¶VÀe`ÏC î‚P@ÆJ£*“Ñ{0–ØM!–•t% À‰½ŽB¢9Cn¢ã…6P"k&*võÊw°¯Äd=õ@í‰ãCq"¶Á,Š`’)¹¡ÆÕ}”Ì_½Óa¾ö[B–©Ù$’$žÑê=ÏfÏ€c1*ZE´†Œ, —.nJYf„Ì5¢IŒgknª—.V9jØer8,…ˆF1.R, ¦©¨Dšd‚3L‹+ PaJ”&T-üMýKÑ鉸ŒŸwמu<­g•¬’ˆI€ qm™‡çïØÂœ”‚Z•Õ"Ô”‹oJÈ·#ïðãô;cZ„­Ð[™V/HÝ‘êU"•‹t|N¦®;IU0Eú*H@Óì†Eø$ŠÀ9†•©kñzú» ¿5Êìæ‚» ?Ý¢üo)«Ýˆsù¡é  ‘Z˜‘ýeä-’"8䪱½-u¹»·Òãï Ð ìÈ^ˆ@Ãað‡œäbVJu]O¼³‹(äK}¤u¼F¦WÍo{|¾†»cµ›ïíSÞ윥!/7Ah犻NÅdU–äX0¸¬h¼š8Rƒq­’Bvä®dé*Ì!Ì`Œ3'Ÿ¼ÜSd15ãùç•EÜlÕ8N:-âëuGç¿+ïÿ±éãÝ=aŸiËKð°ý³·xˆV{˜Y0e¤ofHj[mÁ.0 §Þs PÔÛ,í¶N£ym°;r ª’9Å0*NG±€t`lÉ);:^z+7’bÍ1 ƒÙÖ⑚a͸G™ªÚ^š ˆÆ " WYœêd$"í Q!Ã*‚„X°Z°è2gkö®Ãw«Ý`xYá`x³’+*¬ ½ý‡õÿ!í¿³í¿;úuìî+·¶Ñµˆò0Ÿ¬»®—ï;nœ|âuUõ®i–¶8ÐÆÓîÞsÇãOöÿ}×&I¼ÐÕNÚÎÛ›ßK„¸G$+ö<˜è–÷ŽÄóô¼Í2s7ýª‡¿RÖÞù{*1…@_ž<¾,¢Á¾-»V^Ï'=ßYÿ¹üóòß÷>z¼}ÅS:î^•ì–L¿éoä¬u·üOï©Ý!ûº¬Ö"ÎÃ;£©«Þ«QþrÎ@¯ü÷ïTÛ{ nZ9 ¬¹‡­Ÿ³³¹ñxèÿ·ÏÕj÷k„‡ƒ (¡"‚D'ËûØzsé­•Toy•çy‘WtþCRmìïû,¾ÁÏàd„)ƒ BpÏ*Å”0” u(œò[Çugq{Êúu5OÚ5°Y͸ k(0YhäIÈ1!ÂÍÑ+(%löŸáÂý\UÇΧ JGFGÈ¢çéÞøË93 ß€zí0éµpÑR”$”’Pà B²·ÔÑ› Ýé~‡šû/#¥‰ËJ@Òhoç(Kt÷ežËÒhœƒtEÊK/ÈUï¬+.«*>­—5ݰ*½Ý›š—2Å‹žJ»¬·¡zµñ6‰i± êñ­-e–µlê<Ùer°Ô›åm+žš<Îc£èab±›Åí›Úº]ŸÛ|¦»rù>tèþº2Šª¨"’üAh_¬¿ÿŸú‰´>‡ºq`X1Tš=åi¼]&±‘|­·,ˆ~n¤Š!beIm’U*É-‹L›d“Û?ýÇo‰ò¹=KI¿­0&˜e ($·”Bz˜œJÅ›”I1dÁ3²T#Œˆ?V¾i`V œ }«l“3–ˆô,O¬ÛnåUGyا^]Nwi4žˆÉ¬8ùœ*ƒ<ˆ' « =)$œö<ã4pÁVê‡P‰$ðémn€€„7¿ebÜ%®îtÆ8¹œY¡n˜f¡ÝN«<;Y&wòm˺ܑʛqŒ\Otú>Èîôí,,”·ŠJàQβ£Þ>~¸,6$Nž˜æ^Cw/Ô°ÞÄáÕÚ+QkÇ‹fËŒf¥™‡AÈÁOùþ{D?AöX˜É‚þ‘þ~˜üýEòá¤TX¨ðQ‚åÀÁj­!½ÕdìÕ³(;á€A… É ðQU /7fÒN¿YV JKQTI1®~LÞ{TºaÑߺo1“Yt¡ª…5¶R’­VÎxØ‘)ÛÎäoÂû¥‰~éÝÃqcù[œQÏq"~íÒ&â[QиՒHñ³DT’ŒLHóB­.Y€›Z|Œ' áH+€éq­¶-X­×iX_\°%Añ#iö%WRZL,#EzIàêO‰jþn¡+ J1ðãÆ2 a¿ê9ü›wDÀ S¥X ø´Õ›œÁê(Í>gô£¾y×s•c¿ ¿}-·ÓíW‰ãA´z†RÑj`y½FlŽEϹ$K‘rrZpiˆþGn¦œÚ~Òº˜Otz8W™g${ëßéúþ ù'°£€WÝ€iéR,JÇèâó#ìÞ"½‘žp|­P4‹{$t’NgGävS°gæQ²óµ¿ïlý–Q)«3w:[i•ÿ¹˜…^ OÒýâÜãsK¾SØê šöÈÅíŸ;•-o§í‘gúu×­Ù¯"²ªÝVï`ûü²®Y.–Á”#*ÙÜÎ/œ¤¢ ©öj„(¥õlÊö™•J$n'‚é÷d]ÀöžzÊ™GÇqåƒùçîuv"å qÂêÚ´Qü. _“=b«æO¸a5CO;Ëõ^燥OE¨S$hôÝò±6‰i.wOÛ˜©¤ú¥r¥ã\±êäT®€è­L›ŒÌ¤d쥱‘WÿŒ¥!‚Uk¥,$Œ#*qƒ5–a%Šk‚ž>Ạ2ÅRq{õ£ÆjÃI®”¨,éc,¨1]È쳜$*®“«ÅŽóKÑÝU–YaADU ë¨!WŒM-‡Ó{×áLËš®ª“(µþÛ8LÙ.ÊŒ®e’*ÚÍ7\…4Á#‚–Ñ"/“!æ !U@uMÊe¹eNaÌé„êÎŽ“¸gÃY$Á‹;AbO jjÍ’‰²Œ³Ud «‡³²=¨¨:*¦T±”Jâ3V¤VIALŒY褌Ä@ÊöW)¼}¡QCªR:iÃ0œwÝך;3}›0ê®r¬föƒ™•&YIVÑÜLÂQD¢å£³@á[ŒˆQU¼Óvf¹þíRÉ“îh(&È`T25T%Û5pÂæ3UwÛ,‹¤í‘žDK(B ’QÊ;›QHEC…×}), ]E:³Y<̶KMY ×hkÿÛK©[ïQå1ó¸ÈzºÍ‹aÆÒ›×Âè<ª]ÆáÜ0T®ŽZ-5’͇ãø v…¦uýdÀ.‹ßî1…¿ÛþÍøŠ}ÁÐöÿÉðGJÈZ)F­Rµ ÉZÖÇò‹ÞåÒÅR“$ÑmZ•’µJ—­¬Y+Z„ÈJLÈL†íö4t¾ÇowÃîalËk+7 ;>“ã¶N¯ûõ¿KÛ~<|d0¯oÃPc åˆÌ–‚P j€œ2JÊ„²~:¨ˆª© ¤mÖ‘‹ønhœ<+¥µHÇËQ©ïr8O#ö€J"݈˜êù0'yâõH!RY#¿ &±”ös÷ ™ÝXH”±-˜â™$Èš—Y#LP{ ™vâì´çèÑg†ri»Ûã'2æ-¨rò@q²Ã,M‚eßtÙôi‰¤)ÄUtdü?-Õ-d$Ežó—åËáPª ”ã±ì÷²:ëÝ|û„³‹¨ÚC<#m6jp % ¢m?6—Vë‚Þ—“ƒŒÛÐs_ .U™mw ãæÓˇjHÞŸ: dè0äŠw¹AC„¤‡ÎÓ¸®Ö ðyW¹gl³Ö·fOMCECÜñ‘¶Þ]yã«ß›‚±U”gõ“œ´´²R0ÌKT†˜„"§‚"ATBÌ…&€ò3LQÕK-o@DI*‚ˆˆÂ÷@"¶F`UJdQ2‹ M3‡Î]†Tp¸ùÅGyb‡O{xfcÆ´•+®Ã¸ãB†ÒÆX^íN… 0)v# /)™w½r¶xÀ¶¥¸ £”œ&é76æäè›ÇM r°å•9ÔÈ•†„hȪ1"–Ù|@ÛÀ÷׋Ú,W:ýÝÎÎÈ$ò’qÀTE` €"ÅŒ ÒI" ‘„6ýC$ +tJéFŠ”\„qS†Ýã•-ÑÚÐõç´Ã]Bsêž&Ù¯­Y笺™f¯„$&WÎF2BOüÒ2k¸@Á=,Ï+&ÇKV!‡²æÊ(‹^<‘@ëSHØ«Åç§‚{†ÔI•Uî#a´lÒXÐRh­–3ŠT±]Ï\´¯`l¢ÔÛƒoS1jÙU7Ž·«­kT‡ ¹Ä‹…abcp…7Mj·t®²Ö™²ØÎX á2ÝqtJî¥)MÔQ,¢¨ª*ª(Ê»ÙÖªƒ\Ô[qÅ4 ¨,²nÔÑw9 ÐÐ@q‰ÁÚ¼á­[˪däÐÀq‰Bªµí&€­êTΖZ›•—“<ÙéZ¶…²²¸ÒâQB ÂC´¼ìÊÍH‘1ôsF¤D’x£šL9¾ŠË¼ÚHä±$;R¤ê®…sÍ3±3zpÈ’cæg‡6KDé7òìÀÕ„ý/›l¯ëÒP€‘{ªt(f*kbŠD+²$ªzk*’YÆ>V{‘jy#¯³cÕ9ºÒt.7ËÎ ½3Ë9\+&MƒÐðbIÉÍVÍ'{Úág {z“Å}ÃDl“vÉ'”‚’ÙÅ’@‹Š ×k”|;¹¡¾èè߯GÇ3Óz¸ÎmýåXT“%Ãñ¼ZÚ9¸öÝóÿKí7t­¾üUÍh‚³)˜BA„FS|Ž¥‰H%Š© þ‚‹™vÓˆH–½Ú´¶7>GÔ¯ç7oÓ]:F'ñD±­†‡¿~Ž… P.pýWT™©ìÏÁœº€fÂ`N ÄÎÝ`ù+qp½)güc-%’¬ùl.ðü’`'MÉÙ¹]yžUQËrMhÆ{IÓâDÖÃ-²µwi{ú7ÕÐÔƒ ¥RÚº×äá €D}ÝROÒŸ!G£H­ë G ¼£œ£v„YホzEXºÙ7·¥–³7¶ð»ÊãŒ¨Ž§ŠtÿÞšïO1=n3| ŒB4qóŠ5øÍ?¶Eàª6¥C†¯ÞÛ›SÔÙºryYÜÿ³ËÓ޹ª–ˆY±¬€•XëgÃX"S /ÈÅGÓÕXÜlÄOªo†/Y¢?£å¾!ÎÝè¢fߟòÛ÷=ríÜ·5ÀtqtAUl‰H‹l ÓúóÊhóYö•>›“7Õ¦/tÏÓ+ªWœ l¬MŠí}‡f0C&d@qAFµ« Š 1@r$²…¼&Û<‡ÓÍÀB Aˆ(£·(¡BÓªí¹Í}¸»Q é§ , AA–¬²ˆ)´1{ Cë'ÓnVծϴiIÏ'‚ñÆàk¶†·a¯ãç4¼,þƒ£›&«ÌÕ«¤ìØÐ—zUÈž?º"H·À7…ƒ–¿†}å×ßÔÒF°ÖA–ìÝùK¸®ö5ÒKc?Á0„î’ýìòVªÒ‹Ã=tæÙô5ú.®­~OëEºÕãWU—øæõ.@`¡#ƒëˆ _7œ“ ž÷üxþ‡²ò˜~´mvÄy2”ÕçÏ'øªÒn&pÜo9/{oe+®´Áü$Wì%37b"Ù´ëeâvq¹Ë—Ÿ"q]ìˆ0Y‹99€+Ì+½¶•o Ëæ?}¨(Žº´ô³mãë÷mãîdÃÅ/ædˆ†ø^$”‰HÒP‚¨j¢€û8Ÿ(„€ÙR±r'k:Z¨­øžz‰F F5ƒlüÏ¿þÙjôl9ù4tQ?¯~±ð=%Í]m ÿ<ÇÆõÿÒâ4$é&ïÚ[Q}³ µ  4{RýBâèjÒÚY!·ñµNgœã;þ?â÷—ECƒW9«²0 ¶ M& Ý5 …È VÞÕú]7{Ž¥ÙZÆæ2’¥g,ӔŤS-7:MI¨:̽»ô.ïÙƒçu³VÝݵsÚÙŠ/pô„ý'查“ê[VŠZ´¶©U!!?ü~ñðõþãòþ_ÖýqH|4’Œˆzý@ôÏ$Ç¥£iA$#ËÓÀ†JˆX9¤|r 'O)¿²&¶_vN?|H–ZZ6¶† ÏN|àtž8|ù!®áó íŒH*‹À”"ÈÈ”Ç Tm/r” Põ¿Ë”Ë·©ÉúM'PúîD< ?v_ "IïÂD‚‰#»ew¡¨xCªž6Ó /;#C¢¥ŒñwÛ.´K²{~L-œÚôG“J–Óuíó/ìÉ€*""€Št1b âµ XéÈRoíª©jLËØU{‡?C“ãÆnxyïÅs§¥‹#¨Êü;CGº´µâŽçY›˜|âm~Fa)vþvÿqÌòɯø•)`z ¥ænNQ%§†èÃ&ÉçïÎÎñ\'Mßyí+‚“)ónÁB׋jiü§ÁÖ) 9Wr=bëDM«¢~=keÐíúãÓ´ÀçÆíÙäþM a˜ûƒÞM4 øÀÖª4ؼ¾Oµ¯I—’ò»’ÿÍKfØ ]õ}„kG 2\3‚1Ͱ0 ‰l8ª),ǰ_SÙY_ªa›Û8ÿ¾¹xHƒþÍýïÏ* =ëÕ›Ö° à/*·'æ™ÕÂÍÌ ]eò[ &?Ù$¡œ®†f1¡!¬– tV;iûw­^£#_]m×O/õ”Ä ÔÞqìl?_™Ü=z Ž=ðÔD®>õà”³ µ¡H°ùœ†j{À ³ ôÏó(Ëš®ã­­¢uà0æ~J ¬ô óÁUf«é°ÚXaûðZH9zj^¤ÞnÎ5xlOk Å•ˆh³¨’¸éºX'Œ¾ÂÕĹ¹|ÜXvl&%|qyØ8ÿýëyà]à÷òßCi½/o ¡Í®ØvȱWè5„Eƒ%,Gï™ Ž /ÚêÒÀ€°„"Å ¢¥±‰$2Ãë©yK OÕÕTŒd¨m_íßE8^6áxa‹Ûá¥jÀÄ,Ñ,^þl:¸†Î!ó˜q‚T½©$¡¾¯^‡%”Sæ²´«¶ô$Ÿêþ•Â_¾¥Û³á0ãþø 6`°iwÜøíƒÆä†%ramö™5ÊsoÚøËºEE—.Ñ·²«^W]ŒéS é!$ðg¬‹™D€Ï¼²¡‹ aŽH>BÕHV&vð}¹®ì¨(ϼé5hXçAûG±Š×”ìÎþôõogøf$°.>½MÆð;¨ 6ym×38d Œ‘Ö0Ô‡«×ó%zÂs-«Qejdep’˜¤á¬ŠT‚"(1AWˆˆ;{ÝŽhš8i㦈RVI%"RŒ`ª"€-›é†ù¸ƒ•™”ÖU²”j»wɲG¡lßsÄÕrŽ=ùÙXˆŒ Š0©b£uS$%ôÝq~Þü_½½¢éÅñPLÀ±vÙIÌ_ÚA‰¸¥ Tm!hÔ©Ÿu ÄC $i7°ÁtÑnúUÄ}CÃâÎdØy=ôXžÖ-1ƒãÔ¸& 2Ì™&OlD=öÔ¾ZZË>nƒ¡ƒH°‘Z]!r¿¡QDJ’!ô¾S¦,j§¿®ÙÚÉÃàÇz™G¾Z—áÈúÆ•R©Táìä7¥¬² ¢–Él´ÊÕH¶5R-‘¯'(ñ·íɳåcÖ:¢Dõ¤‚ÂiÇÉ© VÛ‰·s]™Æ*a¸7Dq…jyYïqâîe…h§€…Ê&"<^]í+ƒ˜!dÆ“¤=aHúèOQÊd=cÉéH¡9ê`|<¤Äú¦M¡û«ñ°Û¯n‘dž €0¼ 'Ÿ¥‘Ñ¿+_k.:;}K¤ï]È_”Aá4ßu tÑz^† 9õy ¨õ˜Y6Çšo-èk~åéÏG¡Ïw4SÅÉk "¯³ /ŠœOnë/AÌkº# ˆ™Fn u†$P ºFë±Z8ì¨1C†Ñ¢äê×iax5–±xTº¤ï¨òSDËìôjzñ<6æ§™˜RÊRakTKH•-aî@Æ̘†Õ»`uÂ;â=8™ –pB„@Ò–HD®±ÛÝì·Þq¤ë§5[U¶°¿ (¨‘-$K%[V”ÐñözùÏEµ%±^ÓXÞ=>Œš½©Üð nø÷)\@±!!ˆ.n#SIeµDÒ–´~¥ð÷iÇE]:ÊO†e1žÎ\¡K6ŠŠýT¡×ƒX.ìä¿?e6tçÐã8¶j8GÔTnu’&nQÂÉ2õf ˆ)P‡M9 `·’p‚0 mÚQQƒ¶öXŠZæV¶"Îëy‰=ˆ=ݾ©X̘2–Ë©ùÚ{“÷ ÙIÜ=RÒ­R©l‹h’ È ŠÈÄÁbŠ( Š ÅFA€‰$c((,ˆ ÁÈ‹`¨2EF)dX=¤–K  " T¥«,«%–|DÆUdX°dDP$ˆ‘jÛPV‘ñ… %°§g‡›ß‚+¶›€VB$]N“ÞγL–Ænä"¸—­ÕÂS^Ñ52"¡¶‹RH²)"¨kp³^ì 93HL<š¥K̈ÏúOw·$Ì”Ku^ÎxóSŒ[×9ä¶É%“Y¤—SÔ1Â0ÍÉÜÚ˜ŒÃl_Ê °QòÖ.¢ÆÜ ÔɆ!B†L¦e¤b • ÅðF ž"Ûë_³HNùÖ“·¯¿ÉÝ;x 5 ô¼›R®Ø–x¡dþ?_jÃ|L}W¥?-“¾N|íPú´ƒ†ŽÆ¯~[DP¹ 1è ôŒW PˆŠŒAŒT‚E$@€„×½úž’{)öâ¢n¤Ñ´ j.=œgeõò ’í$’T ÈÆr,DPå×ןá¿jÃÖ“W·§¢÷Mî ¯GˆµSÁˆ°ò´ròè]å ;‰øÜ8•Œæ‹m” ~ݧö-åj &DEûuv}ŸWoJ¤‡gùÐÒ×¹Švà¿תPÅ»ç?E,™NãKÏïLß»pØÿ¶Wœó؆HÜè|É›œÎºÿ»õF4%æº3WÙ;2½m¦_A¸3ÈèÆòþòdº%1\8Ѩó¾Y£`Ñòà`îe•{½="µb<,ÀÁú‡4¤á|u`„Ûhwÿe¿Ø’±¸sª=šj0ÂÎ×µù!o’&í\ý€“¨r!"GPoÇ›ïåÐáÞ²èVÂãÌÏa`® p‚&]0ÛÓŒøÅI"rª9¿:Øÿ7aa_a¬Ô,‚VHVJÖõý’á¸Eé’fµc»àÀ^çµþ]¤¡ÙÚGøÄÄ\”Dò9ðÚ’ê>½n-«ïÄtÉÛË…kµcªÅ~J8|DH…¶½  ƒpbêïàÚîöYç9×—[ÐÃ] !#³†É¾òüÞ_20`Y‘@ç 1z¾$ø€«‰ºÙ²_»õL#K™ŽdÓ-J ˜Ä0ð5k؆Bº.•¨Ð€u!}./òxK§VO²I—þbAàbÔd ýµ9ç7›‡f êýÌ¸Ê Ý‹üFÍî$ŒØd:²d°èB‰ÚNžâ>-F:ñÝ l?rløÚ" ­…P"¬hé-x êäE½®|Œg¥aSÿ&—G­„ÈÎ+B%.-¬ì‡À%ŸÈh¾;í¶€@æìO·…ò$xùLŽÂç€uÿ?¤¾Yœ€— D[$AÌn‘@$H”¯ŠÏã^4Í–N"Oèë¤Ä¬©âÝ0KlëûoÌçó?ÄûoëE4ëeX§lïÁdÐZ6ò(¡üZÌÏñS4&8AUP‘¡H+˜" N[Yìÿ?w†žCšø/F¨|L“$GrØú9õ>o¨ÇvrÒ ù9nL7J‚j>i¼òPØîìŽãלõäWÈ®Ø-½öàªå¹~pŒá·Î|Eyˆi6[`=w¤ò;îwðQì0‹“ò»ÇÜpßènEÌMÜ’C‚€†5Èb4•«ð7Ñ¡ŸiÂBÈÐn6¥Ôn‚þçX†7Üëñ 1pb®œyá~B¨mþR ç×ç¤øyÙ$^`7Ý ×¤sñ¹_"%·­£à9ÁÁñC‡œIxËMªöš7_™ßTñ¯`b000UÆUhÚïÒ9ÌJ§‡J±²af¦ÔýÞ'o´É§¯“©Õà*æ9¿Þ¹ÿ¼ €r“€ÍùUøÒ ¸þý“‡œ° QŒ¿Æž©Z¢ˆø»[ÙVã§6²±zñêÞ•y1’#R´HúÃ×9pôµSW³ÉvsóñOû ì˜dõŠ€ë ®WàÈÃÀ¨§/&h•wHÂãæi"Ü øÜ6Ú¯¬ÔÐiNTâ¯uFv^x¸è¡Íœxˆüëºý.MÏÒÝ=Ê¿Að>¬ð:¥Ù=N’ǹ«ü§ÕܽͤŒ@ÆR‘1‹öù=Zpk%Ÿ©$LÁIȆҢ/ÊÈâH—IUÂç·S-TVID"’pÁaY$’ñ@Ä‘E!hÀ£YX«?ÌJÅ„ cÆdR“BBÄVJÀ€ ¹ 2Á‚+7nš$ÓWÔç!!5û¢…v»ÞBkfÌŠŽÛZïeýg±ëߺÑÐEÎtjC¦ôô·Ô× „}Í€§eij¯$ ôú Bp˜¢ßp§“{×eÄýgåÙ!>Úh‰ã¸:‚Žvùí¹¯µÅl³£Ÿý÷hh¡‰õÿoÐïþoƒæùìŽc¢8! £"H¬ˆ/MŸgÅšø^º-UJ‚”×ÓTûûjðsïkÇÓþÔ…`kg³g1ñ9Js‘ë=žX$ëàì+¶ºÏòr,ù‰–~ƒóNØé=é°¾<ƒ¬)ÓƒÁ £ííì“ nAe~ÐìEXÜB'&-õPÈ*9à•5eA* µ_½xU2.žk6ñ*a’F↷ {µ àDFY¼Qý|£ŸÒ˜Ð*Z³f$úbMol”E ö=ÇCÿ¿ØzúÄYÐÝk´£2)‰¡D±«‚ HL´Þc˜Éδ`fé7§ š5ôVè5GRv‚¸ÙKÓ,¹˜T’Œ²DfµšÖœ>ÄÝy$‹~KvÓÖêY;8ÿs[ž_õVuÅ‹²=`ê¢Dߨqs¶ÅK!ÆrxØTo$DïŽ3mŽW$32"©™‰AK @=¯ªéÂÌH²É}¹D•¨H¨V-Š© KÚKpÂ(?„`‰ÂY!(þ/ú¿_ô8üñáŽõ‘ ˆ… ¸ÉfH…±‰Øë$G­è:gšC¿ÞÒ]¨\5äÓÔuÏDÈO5“­Iç÷£5qí.ZMìvºV6¶XwÚ=še …€Â°°g‘,†"€ù-,& Ä•'ÎèZt¦ Ñ“ž‚ø³Dåo€wºÙ“m}ÿú_‰¢Gy\!f.I"ÅQT÷©Hå*ÜV3úÚÂ` ‡‹PãY0¬š@ Ûhš 2MQAø?ï«Ì ú[Àsøt1f¿N¶f…QQAÒÀä&œš<Ðr*Ö_5cÖ‚}6ÿdL݈dÕ×ìhm,ŸÀàG«Õ-XäÔ‘¹i’–¯P b”üòæC ÿߟêþ_qÑÞÑûZ)™°¥F’$dãWÚEÇKP5‘Cë½µÝF^±Pøˆ£/#}Z-,ˆ‚A/©©"é 8ƒª Š(?ž(–6Ÿ¹ûå°LXß”m¡e±ÇA§ÕqQ 0WÖ! ¼%WX†aìþ=C8ã§å»àÐÍ$P¯a§wœ“Æ ¤F @“˜c•Ë‚\¼wñ•¹þ1õìM×׳ø|7hÿN wã¨^¦–?ÃwÞ®Ô²ÿM¢rŠVÚrj8 =É‹MT†g‡>H2g5®IB¨€O›Œ ³"Þ6&xŠ€˜ ,­†•d¯,­¥¸i³§ühÓ~EN›¤ié¨c­SLàY8oÃŒ9±w…ï:&Ë™¥Ý™ÖäõÃ4;LŸv*à‚DA2öÅíø|§ì­0ßÓÞΟ e TŸ¶7þ 8@²„D ޳3^ Za>]AÀ¸3`îó7ýsÓ=*ºKûyÒÉÔw}|'ÄÝ9ÌΟCp÷_®=w`”§±ÔЮ®¥TbÔÕܤ+ã¨zÖí×ÌÞ%1LÎNg/]á—%Ñ¡œqqunËrܹuÙ†ÒÚe»> `§RÍHÕ!ËÁè»!Ê»êåc¤+£¨õÿ5´ïì^')ÕFÄÈmbÐ&˜÷lÔU‚AHZZµA^sáê1söŸS)1÷–æn$ZÌ…a”ÜCsßpT¬IÂ~ÝKÆŒ*}U°4 P X6Ö™éÈ´ oÝtù݆ïÂÿ^|ˆNFÉü°‚2«kÁ[ÉC†Ùe¶¢MHw§íÚ­.²o˜øüÃ6[³‘À€ó3u(“™L³>bª@°„¨V!1ijnBà6^ˆF¤«+힥æ-^ÍIY¶DFƒ‹tÜI àÍ úéö­ß[ôЬH)ù ¥¼¨‹ ~WHJo©^[Ž‚ã*†ä1üq]ev+öä %8Üï^ŸÌœn¡HÀ5éÑu_idþmh¡Í »RkNÇâÅïaæC-hX‰(–ùÙÍ —ò ýÖÂ0\_Âýî!ø;,DštT¦ ÅLHŒ~®–†®‚®j+µúÛõàTÝü=–¿Ýµ…rèèv#ïSÚÀóUÚ« ÚÚi*kQhS(5‡Îþ=ЊM2° 8>ÚéšÕ®RË $%úAͬ…´7—$!#!S ¬Q€¿ªdR&Ïä‚voSh(ÖÌèiÏó’™Éœ ÔkL”™««`e-€ZgD 5“R¦d.ÍØm l7m8Ì\ÖÎë±,†Ä™\ü[ S‚²¢¦¾#sEç œÏóó@ö;älpÈ*ÀX ˜\o2^ãPÌfT˜˜aƒ„›3ZÃ*JË- ŒUŠW2 0¢(‹ºB³Ifì®™¡º5Âæjfks teþ_ûWŽPÃ)ˆcB#×õ{W6¦ÖÕÍÎŒBIZÿ*už’у[”Ú|Q5i‡KÒ@TgsTDzšk V7HËFªˆÝ•åâÊuØ…Û¦O¯¦—ïõ¯ÌÅo1IóArTÌýJý/¥øºÛ2³å(CZV¤²’ ‹¥2¸.7ÂøŸÜ$ :ŸÓªNçGFœ†þ²@ƒæ½ª‚ï,Oí¨»ê#BP ZW£6¶½7/Ã?R{}Wñ”~o‡Ë~ÚÃã/%õðrÚ¾kžµc(ÒQ£R•+ ›fC¨ã>q8ËÇÑÂ(„Eî ˆµ,!P“©†4ãS‡KG“½üûÆŠ–?QƤ•?¼ÙöÔ4$ï‡e!“«µÍ` Ü?OËÝÿÛÀœ,™„¡1\u©ƒG!e”ÈÛQM mùªôµàÞc—c—>—½$“¤âܳ—¹ÈŽ R¹aì%ŠnH‰ Éú|Ã6GLr2$ 4“H dd4„®ZNí[P¡ue­â0Õ½q) £mWœh8€"¢1"É,o¹w©i¬Ž'’,ƒ[¼­-œJЗœ³ÿc6³ïĦÊJ‰¿Ó¥E"Æ""+4 ‡ír¬<‰'é8!f€ k›ík}å!à ¬¤¥l’Ó*îªÖuGn܉Ȥ‰iG8½×IÓPtTM¤- ¦ZØ~B=6|yŒ®§j?¬ùPEbv¿QPª˜Ð_ü‚Ò* lPˆ¤€¦XBxi8 %Ú¬›Ýì+Wh(HJ@Õ HBVb¥¶0 )fÊšlÑ•)úZ›*$ØÚdD‚Õ«,„OÊQ$˜QÀüî~7$$„Ñâ:zuᣘ§vB½ƒ©Á%4i£!!zstLÿ|Ëo0Fÿôi‹Æ Ôþ\´ Ì“½Ün€£ñJ[ H¨†™= 1›fCHhHŠ‘R$`-Ti…A`žÐ{©­€ß¹GŽ×P7Â)½@,\‡=+#$½@DzRÚT©‚V,6!õlÁ!î2LdàT¤Æ\d¡ŽT íþ÷©û9Šž¯Þü[øpîF*I Üô1C/›3A 0±©Ÿ‘IM`hPE˜¤9B FM3-Pm,„ž}oÌVƤ&°RDÕœ¾6íTQ¶Ð"5ñ²òXVû¸¶U„Œ€°XêØ¨$å¯UBG"BA`¨@-%P1KJ¨@(ŒTªU²ƒc"0P[&Ù1$LÉ•ád’&AT¥F&„”)%ˆÅI©%–KŸæ{ Í%#rCX•jË$“}’h’5VB¡ldV!RP…’bd˜â h1,±Akµ(Ÿ a!1 Œ‰k-ª°‘-2í„Gðü[È’HÔtO=ˆ…¨yÞ» Y½™‘ßzbÈÅ ))UimôpdJÚäJ}gÿ\~Ze"T2y{ä‘XEÀˆÞ-Ï]sA þwï°Py(õXXK˜¸¹Nó©\a³ðm|ÄÚå¡¶ð¼"Ñ_t\€IµEl8û#à.•ˆöÙJõK§–ÅŸNßmœ¼äÛFöóŒ:Sš¢oP­ÃFÔ8‘WlXKo?Òsæá:˜_7­÷h@Š}wÀ¨p>T¢–ªü—ƒÆ‰ŠÆi)šñ !£ Mÿ™CŽïKŸ޾>kg—}¡cK²üfêªJ÷*GÝo9Ë^ø þj]óúªÄš.ÈÆ )´·ëz ÉD`^d·N]ÍDdƒ¾Ã/¡¬Ãßí»Í¦­ì 9˜–ÉC,¦Ë+;†Ø[ÖµÞs(畱.´[–§†í¦„•àm~ÒWˆFÇ·æãyL-±ShŽÿ>'ÈgL°¨,“cVײÃN?&çlxß7\›«´”ã{Í};.ùI®›ÁÑL ¶hW¡ Ny¤VTR}FéÊtË‘—(\WMÖùϳÞqûƒI#c^sý­22Jm¯Rw¹ÅÀÈöÙuU¤A ÍÌ(C»R†ñ ¶? õe–yVXŒ»ÒÃF{É ŸbÁÄh\ç*¸Kƒµ[°Ç®“íâ(*py.ËÀ3¸% ]YçØ07Û§—òAˆL@® ß‚ãÑžÔ°o "¾zIÌÌ•H—¦ 7jH“>¥6H“pd@œÜa%Û91!|bä8æú!dYÿîR¤ÑH²rJŽÉžQi FB„h%¬Áõnc‹š¼‰7LEAN2 ’"‹"‚0€#Hµû«#([j,–XDÚ}›¶b¢9 õù’šìâðÈ{Lò„-„%4A‚ÄÍ…©óªg#à__tàKÀô”á@õr²I$ûŸ¶à'ÿ¡ˆºS¤¡PH›¤Æt‚ºh‡TE;äßyE Ⱥd\Ê$1x€…%¨åÂÈ¥R­,±l–Å¡lZ‘e-"”ƒÓ$C¹î•Á!$_L/Á+4Ó¶:b8¸fãØÙsVDìŽTï©«&’ÂÛD³©û($”kŒ ÕâåîÖwSFiÅ›fR2š–LÇ©œæ± wwÛ³k-0ÝGn÷’4^!»ë&~©ãtFÂÔb7šfSkd³(fS•"¨1‰NÞîš×®ÕîàÉÑT€­[’aQ’H_§{ ´D܆µä¤õĉdwõˆŒ²Ø´–Æ=cк 6èabIƒ„ ]u'阘©yJàĨ†sõHžN¸ý¼Ç¬–R¸­ƒˆ!®#F,Æ2SY¾¹úJHÅD<Æa8OLœ·†x.;ü^÷>Б)Ðò-ZêþÒ{µÓè:1,mdF±©4w«M®!eŸ¼ªð8±å‘’`3bYAL€Øz´òxÉã ±<œœ­²Ù!]L˜xç*\x¥µOCÁPÈÅ1‚êAH–Ÿ3Zäh«ÿn#’yÕ+³%¿‘ŒLoHsðú*Ë"ކ<A0ŒÂKâ(Ò*#v*#–âÄ0˘•±Ä#™„n!©/S ëÂ̼¼l—ϧԆ%-RM¾Ï¥´¬”lŒ’,##(6Áa7å…Ò,,>Oþe © Èð˹—4·°ÁE@§ÇyÙâ#`9U ¾¦R@×þ#ÇóÁ_X¾ö™«„ñ(—WýsÝ~ÞyßGÄÆ¿Ô0½”TXÿj¦)/iaaòœH‡+•Ä»~õ„à‹k1º?ˆ ®¿]Iˆ@Ôæ y¹M%a{÷º¼R Å`oÄ‹¯=ð'×Hµ®¯¬Àu Kf¥æ œ¤½ákª¸~sçK çxÐæLŽc(",a"‘ÏçMØó/0ö¸íLZ4Ãß/ƒàØÛ|hþºð9Îçé}ÎÂßÍÏ}žC˜øZó\š'Áëöw"I²´Œ€B¡÷Ñÿ4’J£ Éü'”EUEKÉö~gåÒ¡oà]áB"ʾÔÝe22$¥²î:¢_ú¾7EÖq=Nnv‹cì²Óµr FB[tËÒ£œmn½”ƾ{Ïkehwž?Ôô9—ÿ.ï’˜¡%˜II‡Žêë«1òÚÁ2땬Œ7íUŠˆëº¨Ž9¡êtÛ-–)¸à{y{ã¿?«ö¿÷ã‚£'úª|Ɔ ]7ÈO–ZûgtN è~|£º¯!"k36°Ô±¯oðýâ ýúßÝB5bHy\È·S'\[1³Ã†Î#XuQ\Pˆ\½æ(]±i}?)pÈéu)T6“É=š™ý„éšëÂg{²÷Ôp}‡6Ô¹Vуš«;(Ä’ ¤Š©c2|›­˜A‡@ª¾”î@@¸bÖT•%ŸOªUCØøëá¹@»Œ Ft óq'–Ü =ŸGÕïs~ÊŸ AQélAAHtéÒÚ Â+!óGòål©Ð’å­j$‰•\™”-›:†$ÖQa»E"ÈÀ1ö =0;§¥öFBYœ!I:ç·’+í–œ€ÿÔ)HÚáü÷W*Ϭ©§P$4ðXõÊãgм«@M MkEÂO<‹pÁî°À-k5–[Ú‹´Ï?ßQULÇÉ”NSUMðŠg;ñ8眛 )èä@©È¿±öÖ,K þvm0„ÄÒ½é©*˜jzdö'Øã:»³gªŽh/@nýM«Ï•…¸ù'%½Mp|Ö׸7ȸ§|ÏÃÝ+»«æ@Çi³»ã´ÖƒãB¬0(¿cÅã]…0Yú/$æ2ÙÕ¯5ú•‚áŒPÌ›¨t‚ŒÂ`tÙIÜEJtÆf¸ß™ÇÂf8ÖiþÚš:¶9¯jGG;ÙxÕFþŽÀaŸàzYD±@˕љÜ)8rž–‰¡UÈ«!‡å½K?‘L>‚¼ Ø¹qåt*nº-QFBZ%_dÞ2Bº ¢y@a,`ºeŸ 9l§•Ѩõò8*ü”Ž=bP˜ÂJÜ`Õùî¤îd'h^•õ•Ró°yÆ.Zk7g˜ÏÑ*´pzÕÇ`²ÉJºP';Øö!/)â ¾þ\ñò´Ag)›¨«„焪y9¹êF€²#¬¥ÞT4Œé­wú>(\\û®êüê÷2èãÖá‘§ý5˜¥+‡´mµw‹’…Ì7U@~¥"¢ZSÓE¶=·,|ìú¹r ºÒð1)=Ú>®)ù5z <¹|·Ï%|v;ðƒK³n¾J߉ÝÏ­ü0¨Ø7:XBu#t¸*æâ+YëÛæü›=¾*•$sg9•mÑTR¡U]Ïhp|‰ï,å üü=íÏ{‡Oo'·…YÛ6ݳ?ò®ù«uzüoë·ŸÛÆZc’èD@ƒãý÷~˜A Â¡H¤VdYJ­ ¸ß ®Rü}hàƒ2æI­¤JÄc©$@^SX#™ÂF+‘H( ¡·XQ‹RQéÃ*ÈÂBR¶…dÞDµˆH œµF@`:£BÕ¶¼`^- ´fÒ¢Fj”T¹™0¢¢"¦­TESI¤S c*‰uaŽR£üoáw±³å m>m%BÛL f?}nXˆ2Òƒ«ïý¯äÿcü“¡ú»ë§ÿ]—Ì—‡ [û4ïL0ˆHF"(fRœ„:Jö»n×úñ7pFBC§›ä%q0¢ÇÄ×yý«ßï}—ˆä Ò´ú?±Ñ3PNí¬(©Š5Nîå ˜” ¡ý¼Œ±´žçåÿkóߢ¿ÞÛÓîÿ 3ó~©¸t+/躂Á†C·W ¬=™•B””a7~·´òvá¸á¤ŸPrBÑi££­gRýMíš _ Ã@r±DÝ)¹éˆçÊ…½D¥v©6,—ê.{Âb%æ²³žÉ²j<:ë4Fg¶°DXeB(”'2 ¿³!·"Ø*ú~Ó|k÷Žæ¾È@î'"1_îC9sü¤N ³ãt *’”%h•­$+?Ï[»ðÿL1€ŠcWØ%Rå^{ª_xz¢€Ä’_b3ÕYÔÿg5‰ží±¿àNì–†‰ ¤,žpï 2D:ôŸ‡ômó½Û†!Œ_¸òÊhÇÍ…õ°Õgd0`*8Î2¥ ¨H(¤“ÏåóO,BI<íIØÊRÎj#‰Xj~¥ lQb(*ªÁd ŸÛäÃD6„õ>AEÛm\Q¢õõ¤„‚R?}Œ„‘-*OÁ±"‹-*HNzZW+ÿ3M#/4Û«K`:,21’@…£ŠÆÑ€‘@V´aæ ­M Œjc‰ê>°Å6Û½×FwœP&Ìy¿cçÔzfد+Ç,‰ì8dÞb‘ÉRæPRö­$="$#ùÆì§–x>^ß&¹(šC.Êw½$žê0ÅK ‘ïõu_žå.4É}Ñ’¦a Å” E-Z‚¹4.»KʈÐÈ&FQkÿ=ö‘RN÷fN]Ù9Žâ X‚Ô‚ÕµßD‰‰qœ“t‹|ÏÃÖ›'¦¥d¨kKz|wCMVÍ@sŸRzg|Â3Rñd˜iuGüÒÉ㌂ÉîÛ€[h(Þ¶¢Iˆ-óD`l^„Š—‰| b}†¹éûÍ`᳤Y)ôŽzäy‘á&£+DB'Êg‚tf¥ 0ºBĪ¢+=̵FÐN¼‡²‹$IÀ¥RXVpRs!î„„øÓ:ƒERÄE;#´H›(‘8‰#Êu"G Âz¥P{Š©ëuªº¨eTÂÞ‹k©ÔÊ‹[Sägâ“txƒ9¶ðdZ~b¨-z‚0_©ÛÊ3´4ñ Žü|É–žÑR g:pÿmq‘-cŸDå‚Úø+ð»‡Î·fc ŽZ쀕ò1 8ÔØ·ò:dÓ.5ýÚúRyëG‹Ñg{³ȸŒ&°øßÌè°juôK2ãéí>yæ½½IŸƒöüÿ•ª¶#ûÏsòÞÓÃûÿ7rý²§ß+¯ŒÿÇK–û‘íK^Íø Dix˜ˆñÍT£âWÿ äT‰_ø_5z,ÂíÇY~É,…©¨zFv™ÙÐ\°÷ ë9 ÀÀ÷îpjÞÙ­—:ÞiwRßžÁöéu©ȉ°2ÕÓñ³äŸÑòO¥8Äú_Åɇë©ó÷FEFE~OƒÓ%?f ?N­EamQHF×HÆLUl=5„‚ò¢ª±/ä‚d…•~×û/qOZÖâÚÓ&]§<8ß4Ùæ-3±¿·ÊBÛ*²,(x³yÉ—z±›ÌÀF—ž·;¬Ÿ• åM¯Ïщµ;û§ÅY«,ŒVŠÝ|ÿ•ÿ?óûÁüî¾mx1äQùræ")´LHÓÉΦhåwuˆ«Ý¬;*ŠÕ¤ÍJ2¿Š¤E™…Žjåü‰ Ñúÿ~¯’ç¡ù;ÜÔ]É›ª·‰y»qU ºÑ_" Â×ŨÅíí¼H²*Í8ÚT•Àæ`°ãƒ……AG àíí,¹ÌóÞröŒóÿk¤à-Ú§YvµNÁ†æ~‘ÙkâÊÖþ's¯µÔ?¯ÚHë€~óA!D` Âˆòb¸ÒÄ^Y$DȦ̋¹Ÿs#í ·«÷˯~®:£ZÕFÎéâRË[Kݲ³Û~Ûúœ|ð½SéþÛ £úpxô¹è¶?·Æsn/.7 ž×6±²ƒ‰þ.Ùy£€1t\ÝÉÅ ÓÌQ=¥á9«ÊW½én&NÞ…ÐÄÁBXRð–Ag”«Êð‡æ×þ¯ôúz= öŸAêki²îcÁ‡ˆØå‚S í—P7<áÆn&<†iƒc—EÖ¥Ž9©hÉ/Ž®‡󬼯®ÈtP:!x<ÒI‚ÄEE“=çâœ÷òNx˧ÈVâS vÉi"bNhLzMtÞã%´@¯G¾o±b¾Þ‹<¤ò¡vK<`¬GîoìòTzS¶,Pùþ#'ÙówôK)ì­¡móÓóDÑæ}@Ì+™/Á2!#“Nbªó†ºý ‰–i@½§Fγó;kçLÕªSà³ÒXö_ñûºôµ”š!™ëêAAdX(AAAH±dPX,"ÅA@R ,AA`(°YY °‘d‹dPPˆÈ¤‘AdP ¢’)„PQH ²,€ °Q`)  °YÀR)Y$„XPPPX¢Å‚‘H ‰R)"Â" $R H² (¡‚‚YbŠE‘@U"+dY ² °DE ¤ZµiU-%°Hœžši©"'!!;uóuòKél”b FË”µ[l¸å˜·Ë-+ ËÜë ¨K$¥dLJvÉà ¤P€fÝ!F-¥KÎŽDÒæb›k‡oŒ}ÎûDdæ`pG´•ÊÝs‚Ö¹v·º&e׈‰›œ<ÔBî;ôš_™ ©û)¨N÷ãv;Ôi5Q0FBPjCFØ¡LÁ=†@EfT "zϪæŠ*“G4ZI$5M)AYF·:Jм 9šÚ^Õ@·ïàil, àÒPÄFo°Ä‰pNŸY\ ²Æ¡Ao<=CW š¢0¶õ(Qc0ÁÍìçáM¤i©ûu›=Ï7•Ú³ŒÅ€‚E(ãF àQˆÈs—TÊËüæ¡ÏObt5Ù㤅ÔÐó#£- ·”^­C# x´ÞŒ+ÒBg$ÞFæSlÁvš2@YÀÖEá_à·£ À$Jf՜ҭ˜O«©D0jY<¶œ‰âϽÉ2{` à~Å š,íÅh8Ê´½d„qe £¤°j¦ý†FÉ"pŽ‹up®Þì6ª¦ÖÛcå=…n´ ¨5—#؆KÏŒª¸¨bd U[¸)cKë²B«‘vƒÀoJÄ0*õvUÞn% ¦½D°…h.ó‘¦PXéÿ‡’¯GøùÞ;YišfÐ.8ìB– BNQNh¬ª{6^¹Z™êo\¾JÀ ‹§¯0¯*3­…“Ä[ж){ Þïb®úÊïá†{mÞ–€ ˜áàGרWocáDï–4ë‚£ Ú°:û9Õ«TdÔSu«ôô…lõa̵uPáÜhÜÈî|¹]á ð–Â@Mÿ@N‹ï–(Ý;1aÎü&rùNÁ`›\HÓV¯iZršMÞˆ} ÐÙï㢨4&í*ž,&¢Í{ Ãô´0Üßë8gø£vc6ÄÍ6ÿ—ÀGïF†Es»T’œÏøýÏ£ÅÓäv?‹˜üœÎ`ö3ÕO0Mm’Ú”„<Ý aYÏzò, ŸiW|¿„ÐEŠ/ÛL1 Ö!Ûí¾Óíþ¡»ø¿[­¿ý¿ÚÆ×kåyÞIéÿv{ & $÷RÎ.:HÔï°,•ÌFVVg=uÝ«û5½2{Çroµìõg"\dkÞ™6#E ®}97Ýo˜²¬!¨^;7)×]TÛy×óµ®—lìË2 9Cµ6.ªš—5\ÿSj,C5 ¬ÈÃkGT]\bkú¸ª$T'SZ[a^&•6UÒ´–zê¤:³ ªãë9nf¥ö/r)xd‡€ucE4¤@¬Ô¦wkkU°ëK©{j£í[-$Y%åR%‹ Ž(÷\+ÌK6”„–ÑXY€€WÅAts Öƒ°pëd‡"Œñ C}”ÕÓlá)YAYêdƒº ´Žçßèï®b®°f¡&h*MaÃ%`‚1ž‚Y…Œ¨ÏŒRÙLÞˆ—R™Ò·¥+QYÊB"#à­u*´Øi­MwI+¨ —Y‹¹³a¢Jè n”A•-fJ&mvgA,¥¬Ék5-f¸Ì‚b”­­LV­3Zf³jÚÔ«»ÙÝJbnˆ‚ ÿ7É+÷¾+§ÑfugžÔ7)A…$FGûêª>î†8Lª8ô ô3³B“ËÁܳGÚÉÃ'oNãÏ=NÎ…ÊÅàTO½ ³›†ûœé9/–Ë÷*”í®yQ©þÉü¾éó6×5âý ¯D+"QW^« 5‚¥xyä>]Ëyßqß«ô©Ó\8z:ĉè&„‡ŸTF04{¼çu2¿{ãîÛßÐÉÈÂâS!Zª#¤¡ä–ÙæüÒiÉŸ]™!ªyªLZ²‹„GcF  z}^œó®ÓSqéìæ—»PºŒïM)JÖ­ðÐùßšüÞƒ—÷vDÈA<ÿ›Ýç)¸ù~£·sûy+˜@QÄÊBãx½¬é»ß›ŒöZ~?C†›ðã¿Ç†ýYh_$£&D@W ]çàcÜId( iËÿ{÷u Sü˦ƒs««rQÆ[Úô»ÞmÎ {8a‚S!62I+pøýÇóínoù÷JQ`R! 0e)JBƒº÷܇‹PùQ{änOÊ6xþ»’%R8pŸ!4±¤Ñ>I#$ Ñqbб V$6º+Ì`±e¥²:nU„Z†òN3d7ýïÑxEÒÀ¿Cþò3î4ôJhÖHFÚò^.µ b±¶ KŠž( ¡åK‚â†ð(¼‰PÜ÷ü¹,ðøZÐÕ¹š)YkXú@h!Zi© ÀË4êA«jZÙF¡YS—××Ö^±Êîr”j|»^ÌîìM& m;©‰’¼òd’Hè»Ñêôm-C޳N’šÄ ä™gdÓ«ªGDDœozšñöñ¶ Fý§mÍ{ͲtTv+‡ƒ}Nn¸Ö†F 'ib@à„ï0æ°‹<:’‡E˜˜œñwÆm™ Jbµµ•k.Žòêöõ>¿„lHž"DàH™à£[¤„MbR±9-~AˆZó>n§ ö:yØi!äÝ×­tÌa;Ù' ÑÝÈm“-"sMÈÈÄ$ž¼u½~@ 5D¦MÉ"ŽdF‘P)I+F H°•ERVB,&0…BEb $P‚’E€)!”–‡³bQ-E²-‘á!#ÄíôÖõs>ê†C)¬³89C&ˆ\ŒLÉ#t-÷öØ»™X -ø‚]EºŽ 0‚ÙkAÅ󕢇žÕ×_H4%!¼èõ!–e0z•µix“‹ºì½F¤3‚(¨è$¡a ‹ÒœÚ§í±÷1ábäCÏi ›T¢¦µÆ\g!â¼ñqÞ’s%@yµ¼Ãœ"“¹Ç½•0.´j¨¬Ò ©˜"iŠ.EUµeMA ˜5 ÀCL¬4hl4bfK«ŒXQtk1ujÝ„¡!0™iˆ ”.¬Ä5 ©€L- ` @Ò1$#wš0TQˆ›fÜ$DÕ†ƒ,iœ„Â)`Á]QÝÞ]!PšÕ„œsÏ‹s"…I+(%Œµ`P_°ý¶œµ ·öèzí¤a#¿ðôPÙ}l‚[#Rå$ñÙ6+ÍcS–Ú쨎Yi¯~7¦sÏiª¦B2ú¢>Ó;›eY%[ [!ij’%ª “ÒD*DDˆ¤G0ñ~‡¶*f4ÅÔ^ ½¸(ä ;î¥Âú¸®‡œH>7aÇÔŽ£­‘^ˆ”ßXŒ³9D‰²‡Gbk÷sMyLrÀɃ‹cBowG (¢¶+Äî÷°Dó:–ø4‚h‰Mó~òyX·c•9½¶yË%±«jØÅÈBÃÔY;¤ôÊ>"‘ÙQå$OVCV#Õ¶}=èÿ€2ˆA±¬FÆ£€! Z©o#¤ù3P |8a3Z_Ü[ú¦úÐÊSøÜöþ)FCS…LŸEÑžçØä²(O<ÿˆz£'¨ãòûó/òàD¢]ÛXÄFÁá÷s†(BS QÉŒš1„–O–´ðh²Kn‡+ñçÁ+«ò@c|°$—z×!—3{ 4㊇גÍ2 ËYc~þs=W—Ê®±·Øk%érŒ´€ý«Q´ënÿ¦ÖLÅþ‡³üǼ/ÄùòªØé%­Op–Ò7–SEÈŒ3É G@ä@>‚ F`>ûæZ›1UYAâ墘Ä\0i0"E"Â"¯´ï B½ž3Näå+[F÷K2mŽ…› [Bûp3"ÜËö™9 › (Ä3H <À¾-OæB†)ñ¼^fû¢òGÒ—ÀT >=)V­J:–(¥Î*ž;¾ãa‹UÊ2LXÌ©ò¬0û*4ùq¡Ñ…E/WI dj   ŨؘJ<ϯÇ?ÒÖ>ûÍÒ¨mHFXÅŒYBf ªÐÒ§ ÆÑ«ªQ¸xéû€$l=ŠþšÏªÉ¤Üê[FX­Hû¹"%ÔšcÆMM4Ø_‡ø;|îêsíü™íÀ€Ù!#Ú³ßW¹â±² ´rÊÄfR£$`0Y™—è¯Ån‰|©ú‡M ²AH,´‚òg¯mÂ?ÈGRÔÞ¢¶ïê]Ï&\T2¾&TÍ@÷_¥d©,¢=¥(ÌK§¬Ã°ÕE‘üJˆcÞ¿‚eàŒ‰!­„ ˤYjBB[ý"™$!{l‘$ä³¢‘Bp˜µÂ¦¨µ•‘Lx¬ (ü±ª·DlF‰'""D,ùæ±-DD—Z¹°êH+h(9íÞî›!¿ŸBàâ©éöõõ¨âÁ¯,:d¶˜œ¼‰+ÆÂŹ¥Qó¬0ðhyö2óÛÏ\ý&øÈ@øW5-ãÖã>ìÝf»#RXê „m¡0AöyH›œ†~ã´‹ð‹Ã »É÷¯sñË¥.^"Ø<ž0½FgÖЕZ0~)÷Ó'ëÃņ`c¡_ôJͪÈÀøç[°P©ûR¯ší@è_ôtfötÚ+[ÕÜûþ‰ßäyµ»?Ké«çaà ©/ùÄgVÐ0ùG‰CK‘¦Ð±…èœIh@=ÔçIp>™A³ßX»wŸ•Ç+¹ŽãÕ}èV›1ËÞÏ8%J ÁÞ'jlÞøSŠó­b¹¤¼]y[ fåsiÉDñq¿6¸æ™Z½Û=®Ãý¬û)òôãÞ­ç¡ÿÒ?Úr b¬¸Âǽ ¸°ö€øõ@r @Á¬DÕZX!ñb•DÜ p1h@;ß_FV–ª˜”C½" `2Äó<c`qþ-ïÌëáÇÒµ\ùVI¬¤©4e.ba tªª*± U[#’yÀ!Ôæ¶¸p’ùæŠ÷/3âÆÛI‰ÄúêuSȂ֯A*D¬ƒRR…²*H,TìÃøŸZü !Ö„„”'¿¦vmí}ÏeäN¯h¸Î= ©” J¡ Â…F‰¥&Œ)¥0¥4CF͸é§6!Ük ‚a(–’’‰i0˜HjèœwnFÓƒXÆÜÃ84€a0DD-2s+U©„“ Q&‰Fš4ª¥*0””™Æ2(ˆˆ#¾8 °56'òf¶ÑMŠh*cEB±©…0¨Ñ-M“¦†@Z¡BPˆ†2IN5‘EtRHDÂa)3”Âs´ØMgvtÐ^#‚ ˆ%*ªVæŽB“a²’¥±ˆªU*•X`¥UT‘E)@DÜtŽÆÂ]tÉ£†Ãl³Þ¯H€a§†ÿ“ÿd;$ëÊÄa„QEâ•Õ BüÏþÏE„ŸÞf¤ûmø_5kmëÓ̘’KâÐõÿ«žd?K¹píi¬\òúÚ·Âл“a ¾•ƒŒ&­Œ‰>vV}—=¸ª¦¨¨¨¨¨æãaöèùT§ù¦gDaDYa‘AP±Z͵¾ hc–R©\eX**‚¨**¹Eó‚û}º‘½±½ãlï´Ö`kQòl”iÂâò_,Dað¸'òµ,gRÜZ±V˜Ý¡qknsÂy² dD˜ åÿ(¥Xí¤Á9¨vmÉÈÅ'ÍÅKbþ±Õ[… ٬ױ¤*.‚ø@Ö¹ÂíÜýsÞv]×S?„–x÷,O -`=Ñâ?'÷~ä®ùšžç·ísh͇T3SåÑÎÐÞ½'_a·+ óõ’¼ôUf¿"þ;M·•ib«¨õRØ[ÀÒ•kžÐŸ:HŠBÇ›±þJ_dBÉwz;nÁÆvýFGðøN¹l¨u$ ~Ûî°lý­L±¢J²*7Òþõú<äý¦°;¯_è^Nïè~nœ xbØðš2nSŠ…B02Es Äà I‚°û§[4õ€”•™åÈX@èÕr°V‡ÔÕ¬I¬XÇZÝ!5“ЬªÛ·|ˆãßšÁ£'ë [›­ªª.zµÖ¿=ÖaØH8cŽ! *$+üP—R‡òvâO©o¸{Pl¸·£aÃo²ƒÿWRÁ îúùu¿¨ðš*Ò ÉÈZ @!¥?'P5î=ÏÝ~wáãÐH`ûóWÚDͨž.iå„ߨÊ(œkž¿­×TPHŒNÔÁCøðª#_Áèù¾ßÜSGCùŠ`-ÂFÍÛÂÍ2ä8ùŒ¿ìÿ¸ý¦¦aÂîw7÷&›&;N=…ëàa$äa»z˜û˜û?.:íéÎ'í~‡kÐú†áÃJPÂÒŒ2?ÔX×oÛoþZU±/~ ,NÚí]——%#[Qsš3-örKû}oÑðü·¶!}á"_AnÓÑT÷¥$E´Ç]8DÄf‚L6K' ­Ï¼àUH”—#ÛQt`ÞÞ.…w…ƒÉ)!2¿xv¼ÂßÚ±°ls*ïLK‹ëmÁœžNh‡“>€ˆ$€Ä`c€ªcõpÛŠl[†‰†0X?ƒ¹>x(Õ9¾XýäO¥Ëš}æ‚ráŒûÜŒuû¨únT™óû|3®gþßþ—ÈË Þ/‰šáÔE |zÿ5ÉKâ—„ T©yC[áá И =#$-`´‹ š';Éy›y>æ.½`ÆT>Û™¦>WÄÙ›Œƒñ¯6 ó䞪…+`á0‘tŸ-x×òhGs#õÛK”ùXßQ(¥ÅJgï˜à¡¢âÂ;‹·\#>øÐÑ5P]—ÎÅ&r¡ÕÿTÀ8¹_ƒ·×”±b0ƒ Ú(ã íu s…²¥@¥ÒNâÊ:S¡íå~u¸þô)îk°÷}†‹OP÷½þù¨ÇJÄÆH3ö9Ž´ñ#-þ¡ÝÊ€èY§á`*–²ÿSMáéîùs„#A“Ý@¹ðpau$ñSµÚ¸ìuÍ¢$É9žÑT8ZœÓ‡‘XÜu[§cã½~Ÿ4øNP²ÀB¥h¿×ø÷<†Ð¹.x0w#½´äYDGw¢³Ñh«€_"èIû \—óç͸Á=‡%» ŠSE#ŸÇó<@À®àŤß晟¼RS½uÛýëíßk0   œààÆ°#^Éí_c"œr”ʯ;9Ë‹í;^·Ç1Êw)/àç %§ñ·ìí¯9]2L¼<¾qC þýD‹@L‘Ågc1ñúi1^¾ž)‰ Ç&-¹Àwü캫 «½þÂv/Cùú@ýO¥ß.Ïu)··õNßû“ètßaYÃPôÐÓ­DA  `JG‚¥¾ËÍäbN‹dÄ`öZEýõç·‘õÿ¼« -"ºŠúÃ"’5ŽýFl÷ØîJ°ž|ÄK¤,¼ZKÖ)•?Øöƒ{u±;wº€¡†ªÈÖ'x«Ð1ÅéÛ-ý ´UŠ$å>8S4ªÅãY™Å˜:ro:€Ô#šï¡Ãõ ˆhÂf)±Øñs!**ŽHÃ^Må·?xf½\Ûã-]‚lk?yãHL)öµ²1¸\¢ÞIaMEÈ|'Uáña +Q¢"‘ïV)ÇWÞyƒá„b2ltAE`¹P L+…e ¯“#XM¼o™È‰>ï-1ŽŒ,шx·Å®_‰’`«+‰²‚O•ð\i†“e49'µëAÓÞÛää6X;zJg#½9V°ÿm¥¥dýKB"Žb·¼¡m÷B_èîùk»¬Ôâ<Û;Ášä€Ò0ÈåþC$áqÀŽ+5Žá¹èR@½ 4Héê$Kyî¥q¢«`ݬÝëY]¯+ë9YIï hÎ<ï›,D@`´Ú/eîì·êØVqR7%Îx—™q»·YégFéÞl3Ä!U ,d[ZÕùÏÔêMÑü£b>ˆ¸v¶}±.©²_­ïäny é̤ ÚçЫK±`Çk¥¨©N§‘ u—-ýxZûË©wµhÑFì;Ë@5ñõ)Ï”ÎÎ Ýp| Wáøê é^+¬õð—.3¨ÔÇêŸ%øV¦8¦‚J´i®œßTú­ s < 3ÍðÌ´Ë_z·íã¦Ù æžÝ —=cÿ6¹ªQ°ïjv,n—Ûñ6ÇKʉŠ_ï'’AhÙ„8Ëi±RÙ€D¥C´Ê/¹æZ6bP‚awü¥ “q.2ft½ã…v°ÓÔ$ãÂüUÿˆ.ZZY}!ŠÊ]h¹x¤‰Œ3×óÓ¥ƒ‚|©šnŽ``U™R>éh4{°úaµ“GòåõáCá·EZ@ M®qã9³od0!”,x£†.Ⱥ|£õñ­ÎÀ6Œ–×{¹µˆd ˜<׈þ¤»§n ë ½C'$—'®àpcï߀±ŸÄØt-I@sf+/&S *Ö.æE³žÝmù~!Ng<¢¾ÒŒOùÛLYýK’JI8 Žù·M·ÜUuÀ®sZЯ¸ŠV”—Riu'Šºn÷`6Ž û*Ô–%QLÕ¾±ÍµY^´IÁñã Mám„|†éÅ„çhò  èÊNšý籤D]×=ÃÆ5Ò!ÑÇêi£1¹M©‡÷ˬ‰¹áÞU®Õ7Œ³ôÜ»·-¶Ï8À=¸÷Áq3œëœQŒ ÓDå—±KÈ ÈÍ[8³Ž€œRNQ¤f;éW³Qix!»£Öad»d~[¢0•QDy"Ð=¿¦n© D :â;©cJNÒ©e 3rŠíѦ0Av^e‹ë›Ï¢:˜TW¬ø7ˆÂk­t‹}MÅü("]4ü…çBúò8 µ#¦ÉHLÌ£Åò*ʳ®gåÖñú׋‡C—E+újæ‘ Ö|¦è\ø_fý±³c¹ %°û,2¥zÓ«:¢¹¢§%„°:Z;:Û€J®Çäì2VÊy|½é¹LPbÄD™§îýõ˜Kt¸!D¨YÎuY‰×ºÁðj[ØúËRžýÛ‰UG–ie§.Á*<ÉȘúœã”é3ײ¥vÑVD È1šèOê£s¸ í…ã91Éà•ÉF NH§v…¿=h á’ÚQ«€!°î<^¼)`ìöÆæ¼ìÔÂÊ‘b[&/¯øåÀÂ:v78Ÿ:Iä&(Ë”Âþ¶„4–H",/÷UC Ö;³ A>rJ\•NÑÇDC†¼ÎÕõ7<*;æ¿3¥éøÝÛ¡›sÆ ‹^±xOäf­?ÍûŒ¿–Ø70¥Í‰-ˆ³Ö¾«ˆƒ÷â ÍÕ@Çkñ%¤2—‡­Ú‘±½}7 °-H‹û™; Íë‰û³AÚý§#+sÍõ·H{¯·‘ç'Ø êLCP&8Ž›g·ÍÇí ·ô·pK–’{ù¸ÿ310ÈûaFy)ÉÖ ¡<Œ¹º“i¹Ãäœl“yß¶t±( Ý"ëhjy›ŽÿÊe9qÿŒ7šˆ¼åŽW¥‚õrB}Jü9;³ŠƒCoäðÄ»›gÿ† ´ù@*@`GÏÒ.˜1Ð*˜5÷ÊSÇŒ¡ø *+/ÈŸ|fKK²ìô# .ª-÷7šù‚Š%ã¨ØvÍ£ CFñŽô]jF”)‹®‚7¬'Žqv½ª‘s¯ÓP‡:åÛa{Z6ŽÆé‹ûCæ6Hþv–Ms+Ó0éŒü[×̳0õ\˜š(—0¼1’µ©…K²PKé×’ŽôƆj¹P&ÌRî}=µQ¥[[vgJÏÊVéŽ~8ۖÈOÑíã6DÒ×)QÌrUÞ|÷Hû.X8yHFÐ ÄSzÐ ± oë-é2Ôh˜’¿“j_£.E§pr6ëõûÝ'<ïp@7g ßÖ ŽrP+¡\l#©®`ÍnÎ^Aúçtм‡ç³Ìª>»[¼v™c^m_Ûè”ZzùheBÓ?@üçÇŽ¬Ž …„2°htk™Œž‹EäÓŽý(ab0žE\HìeQc(!Œr?÷÷5(ô#@°D”K!ß”ÙÁ2·#5b0'SF+h3] x‘«‰á ùçGHBo+R£f,!Ÿ{ J1Âþ!d¾#ÇéuË—`Â=⢠Å+9Qê(H83g˜ jU7(`)ï ä³)ÚõD?XýÂ??¥À”uñ¦Z}¾*ïÏG¼§Éixx5±ÉIO¶åçØ­T@f–Öâr€4¸pZ€šL[eî]LŒÆvâŸb¦÷ó"¤·«€ükߎ×Ú8l€pè㛓B„ëò\dwëi]úKÌÝÞKô½™S½ÍÞýCš$SÃ$g‡‰Ôý•­J ‡¬àh¿Ø§¡Yr &Ì0ÁÓ”íGÅ'VšÞhˆa ùngˆšï’c£“ÔK²²|§N“Úê$î©ýà!ð=!WXDì$œÌûocŒ „ dêqa…JáÚtPÛÀ·†C°âà«DIˆ“6±ÓS€Ix„…ÅóXäe‰±?¼?·m¬8õ‚gâzòÇŠž™{ÚI‘ÍÅ•ˆÞ«,³z=®„lZ@ù5–™ß’&½¨éiX¼Y4(Ä]ÉWVDhsã·®ÅQ«:§gŸ#Imt×àÄ:žj+³h²TÅ$h=cŒY¼Ë;)ÇMˆŽÂël¤dg8¾V¢Hý­k´$-r •W*.º‹ö…ê¬>àj¾ÈÄ×tÌß2FçÏÞC«ûxÉvË÷üi…½³Yõ~Ákù½= úèõ£ˆÕ›§õo€Ðæ{š¥{n¤¬…>~SÓÕµ•,þó"&¬-Â:ªwÐ1Á²Òˆž…ñyÎ-n+ëP¸ŒŒƒ‚1@=š+/Õ-•CT%Fš Á÷_  ˜£/·cÇH¸X’ Ö#€$(¯™§•tæÂjçîZž¯æ­öÄ6ÚøÎ‚—ÆZv2Yç1:ÅõT>'^»Pg‘ 03Â]ü*ˆÌÀDÈîöÉ ‚¹±! ›þLwU[Vt1XiHšÍZÜMF÷+úLžË,@£#ÊpT_p'àÊ£lÕE:øût´íáEf¯ß+ÜùÙ{oE¾禿þ-ô¸[Ab1™à2,Äñù%’Vb÷t0PL‰Û!¦Z~ß.4{ã”W£0¦r¤:PXdc|4€q*H—‹‚;ü$+ë’7d":›3§ˆIŒYä<6˦‰nþ³¹o¢Ž¡â½7ÒÞ‰/·­iÄ9!ÉA™p‹"½Æ¼/År´ãüôo…Ïìƒþb#AA^UÂn¹ç*p°W0Á¬Ñr²¯€0 ”_dO³Õ´¡a`pþéøWd>VM €Î ½‚:ä`ó±K!Mt1Æä P‹Š¿®_‚z²+»a‰^fÆÄøëà<…Ù¤Æw›'è.@ú«Þ©˜©ð¯ÈùHN{‰.uÁh)ÿ°j‰£Ée×P)P…Ÿ#t9A˜]JÔ—ßÝ0UPW ź›ÀÛ|j¤G(dÆÜ·2æ_7ÊíZºçHB2‹Š±p eýr ªtگ巌'ûž­«sž Ìzª _Âo© ¦ø³”˜†IΔ9P“Þ:b†g:2”4¹pŒü§Õ(îÐ78T±ÓžºrœŠÃîYþèZpþÍOp H V>‹Ÿ ‚í­ÜlÁ´„ÅaË׈³ÏKÎ÷ ñ¹ó_,+¥Ûô‘% a OqƒÝ]dTD¶cà)8K¯—™òЊ™ÏR†9+Šé'w›•¦ j€Gõ£UȺÉJÛÃb€aX‡ÛÒ¶j_ñuZÙó=›4˜£$÷q£6Ù†H6µƒp&H^¸,‹²l€ ÍT/Ä„EN9öR¬1`ð@llfD<ò:lIÀÖ£õ\_Ê ‚^)([M|ç\Yüíç•Ù#<›ë×µk!¢ˆ ÍÇ)º;j€e"¹ä*³Yíqx×Qc œ¥(°.¨×u^Êkˆ‘• ;?•ت¡ÂøBÌ8ÎŽãW* Â]Þ+üÂË:&¸bKèÍE‹™¹ûØŒ6{>B¾ä·È@ߨ"’æNuž¼Èç„Z1õ©:ïÇ3IøA_¹­cù0ýxÚUCºëÕiæï²®6+™®ßö…êÝð·¬Ù^b£ºBý~Å2 íí¼ÚØú2zäúä7 áìº#ós–ÝE}érµí|Ó© …G3+9CM+_¸È&˜³ÚâU­s~øª vwxòD@^½«½8ø¿îy¿ðöÿÈѲ¥‡üÉC©TÄÜÊZå÷ÛÖ­õ(ÀÐP} g@»@‡Šù—[{ÞÀx…3kÿ"‚âz½^jï¯fÃþNø‘“d»®kA:—Ô{óz`„5¦Ñ›ârýÔt¾…«×œÉÏXï=LeÕhظV>ö¬î%…ÖÚ†?T1Õ·EQÀ±™ÇÀH.é_q¸¬…U’y…›•3¿óg¸2ÅŽZnóKiÌ" <û—[<é=ÌPŠz•háOCIêžÇ 2‡lsç~Ÿ¡ñ»]þ·&õFáÚLZ$ææé•®Ä“Œ”&XÓÅÑL\ŸÖôì'mçVYÞ3WFP®] Í~ÄÈ4þ)fLþê÷ÁøÍ‹&TŽ¥‹S_Zb t6ª(Vö ÿ±ôY¾ò–st0P l·Ì=X…ÔÆÍ½÷?M»ËLäN£UÎüxx>œÚÃ3§Ë BÕ˽GÛñv""*«€Ý9êå‘§¶½*ñW$æíÖÒùMœö‡VКÚã@åÀÕÝÇs“÷ÅŠàbÉÍÜib¡,òÀ#‡z&â˃è)ÃÞ©ÉÁ%Š"3§Ú·­ZhþA‚#tÆH@\Q³ëã±\»ófD ˨:3òŸl{Ì”Çu~ñfQ:AÙÐö$ òÉÿºý¯öá)¹4\á¡Ñ²é9i„ÃÇð†€¨ÈIˆä¿ÛG`õ(&ò–€^ÌÈjõ KXΧ+èźÚVë¯,!­ZjØÍQoPmêx`™6·Zûs_Zi(7…ýÂ7]6n'ÂV\²Ü¸Ú±LmÎþaýQR9ÕM%*‘€ÏÈ×*q,Jõª7“Ìà«Ðf¡Ñ(‡8"ùõN& ez#–¸Öü œå÷ET—'%I1©ì¡Õà«Áx˾%e–Y…¤ räè·;V$¬;ÕÑß͸‘"¢öß⇞ë¶Ni)öŒÔX1ùÁ泓È÷¯çÅÄB&§1j¼¢‚2yÃUÂ{ÙΆ7ôœ@åÙ¥–4;^›0*%Õž9ò²ï®Êæ´¡žº÷ô÷&Ïê@ÎQØïP¸îXÃpa^+#ÏAÑ™þš‚¹m¥NkþK§®"Ñ/ ]ß³´GDv»¥ÃãMP•*@½9‡¼R(²OGÑ…8V„ÑÍøïìñR…¾Ô…~Üñ#t3šú±$Ès-òÁ@[2°¬B²LqñüôêÎéé99Ó^®tÇìÁek¶ ~Ò àç:FL¬ƒ+F—ž¬8ö¸~Ï‹Th(‘9ÝÚÜBÃÍz¼ ²ÿ|R|øØ†GŠ*м¯ü/ŠÂŒ$€ï×B"ŽWz1j\×™½WòZ3µ2êÚª?Dv]¦1vŽƒµ±»¦ÕÀ /ÝYa)næå‰·Ò#²†ã4•[[„kùú|p3… )€báa†º|d£Ó„˜Ó3Ñ)µ©J:nªÅ0·^#±ßJèššõG /?‡¸ncÀLOáï{âª)ª†3 eü ”î§4§>]þ N”Hï)¤7¸@gø®‹;»/Ô>"U­weˆÛ…T(—V˜àBõÌ,M+>Ø2&'Œ|k7ç"]¸; ž&¸å$"‹0^F²OÑä¯:yñ Ý/ÞW–á“Y¥`h‹e,a xz®á-@ôiÊk®;ÊgWO¶}älJµ.ƒç°sÜŒ—•Z_‹ßâòάÓsd7ú‚¼Õƒ|éS†Åê½ñ2zæÑõÙäò°¤ûaëŠÉöâÑZM-ÐÆMIwè KÈž1ö=-aÈÖRW©ÊÚé¼uÞ'¸J`¨$çSjÔ~Ç?[¬Pâ]&á M gö'†`4bgµ¸®:Ì3ÛE˨àÅknÈô!ˆœ•¶_'³R©Ñ¹èò(òs×Òv°%ƒ4‚¬Ìãß¿„\uFCý>F•§|ÏB[½OÆ%Å«'ií ÕsœóâÐDÝç.:J¦‡¾Ü…V“m@Qâñ†ñËÝJ@iò0.ùzaOÆ ð†D¦Þ®îÛbøð§Q0¼ÑÄÍ'H‘€Æ¾Ú°"V%l¹`!¤»JÃyÊYÆÝ qÁEâÊMÖ’}€ ÿúßê«g¾ZزҘ.‹?Z ¦%¾³C&x:UÛ†e°|èž®-zHz*“éVàœƒw„y½?Óý-©÷ZЫÙrrqo–;ÇOI8Kç÷ËÛƒ¡ž5ÊÔO:`Îo|  d ©Q÷goåLyv(6ûd—ãâqH3'½õ›Y¯ÄÕ{bfSçÕúÂ`’5­ë–ü2©_l+ »óœº¢W7¢Fi‰RóS¯]PBdµ E¿Ôúcš“©OsùÂDÒdÍÉâ³ÞóêâœÞlJ„×µÓ@³§ïr÷>ÐÑÁtDF-§xå÷H‰Å›¿ÒÚš miÛ¶Û ô¢N¸ÁâÝ ØdfÀ.¨=êƒ] ZóÝ”Qjǧˆºõ¿ Âèͦ RªHü1öŒ¾ªÕ K,%,Cllñ¶ÀÞvÕ³`ÿQVæ$)NÀõ÷£âQÎŽq» VÓgç2åg/ù ùòS¼p)2šWéÃ+ô,ÏtTÀÜç;‘×.hR§Ú×/jå\À¤€aÙ¹ÐW06 üXÀ{ún(78²YÑ•µYë¨(²<ÉÒ £åçø·ÎI-Pl«vV?äâºÛgÔBÄŠãÄ)ä,¸hÙâð~Ÿ:‘-c”)PO±ë¶Ñ  „ìNŽ«‚‹,ÔÍGTß”ìWÏ.W  Ô¬ÙÌ[)$e•ÀêÄ Wz‘EþBÏ œ±ŽÖ#Ø, žJm2f+´²5̘L*ÙTùž»ÞáI]­™+§iGå9a¨&Uïj…Ã/eoƒl˜S­·i„ÜPá–€Õo£AµxëÚ«ÒXC ¦F¥$ôE‹År'“2 "oÀ+"c- "Yé|èõ'¦þc‚åh©º²/„;íàÞlF!½-ÙÇ»açô—¦¢¦¤ƒ©ô9& Ö…æSÇšCù ßDÂo¹‰éˆÂïŒòŠó/]‡ûž"ËD'Û'’%qi Ô&ÎÅ-Øùž››ÊÀ ‚{ŠÒd\òŸ“%§÷§EfÄã~Ü‚ÝâŒÔ*xÒ" RcÒCV0Nù’õCŽ%‡¸@>…Q¿‹/Ó" •«XpôÄz["Óƒ0ë»4I~(LwGƲ)¸Ã;c}i^iàÛN£j”6¼W÷wI&Z_c°‹þp¥uxGŸƒ€3q#.€¾ô¤0ܧŒ’˜ÔÅG5ÁS(…£È'Ó'W}BzbùÉ~˜´ˆRR}Zá+l Û Q{D¤^C¸ûa\,;JXpªaZ~öÑÒ¦ßZˆ-#ƒ&›ÈEI}*”lôÔC”†Dg™Ýâ¥u‹È;ã i²ßê€äã\Äþw‹¡âr©+H#ö<>öŒ‰vyùK)— Üv·!Aà4þ6x?ÄZNŲT€)h(M!ʧòý3#aç ñ!m˲­RË…G¹³EØÐÊ©`DêefÂ¥TÝOÈeæ[í %sÅ?mé9wÆÚ&l}û ŸiúÛàUeúÆ(µìÿÅjꊾ“S$§/”hê¼o†Ç‡9æ¥Rj\e“°¥ù)Nð¡ä ë ”3Ùt[{¨ °EX’׶Ľm~(ÜA¦üö„ÿÖlÈ–Iøº=†o>Žë5\Ü›Øø~<ˆFsò&sÜÍÒ…~Ü×H®²‘’ÈP7«€Ó1Ô†B˜l¡úÔ‚,dL“B€BSø¢N‚{XD{ L-­5t€ÔˆA:¡] †7ÜŽËžTká¾»9aûew6°=K3ÛE”¶z,(1·¹¨&TÖ6ÏòtôUÌæ¯‘@ö…¥Gð|zVÖ:FO§‡OÅ· ÎôÕŒ1'ž{D›¥¤Îá~)eh]< V­ÑX]O€e ŒöH3Äðœ7UBóMs¾( ÅË ¾Ô€Œ¥Àì›j›Êˆ%’†¤Œ¡M«-×V†”ß"Õšä_s»Òvºåªƒ$“~cE-u¶±¿¼Íâ!ªŠÆÉ{øß] –l ŠƒF f¸•dç:k¬KÒ‰) ï¨óñ>ýIZ`“èµjÇk/7'>ÀÈÞE^( h9Ê_$["ÃCR™–¥2Ø8 ì¿¢vI%NÉ…,ž;·X¯[s O–g‚'˜äú íuž?œÑ.Ll$¥xv”^„X7b¥Eìbã( ÌÄç5ˆ½ÇŽZ?g”÷Æ¿ŠuÐ)àEàmÿS!˸*z]BèÚ³c㬑ˌÕwn:ù«„µ4uqSLP{ CŠìØ9‘ÜOB E)jj˜4Žˆ[>ŠàeÎÆi0!ö\´®0 §mˆƒU9rêI-0!€Zó•0Í{†4åaÆ* £MEÄ—à\wQÊfɲÛ itÓ Þ(°~_!á7Ù$,äq¨ã‚k³jB–?ƒe2å\€Õ» •I¹­bËç„“¸1m-&{“jÌzçêôõ7 FŠR{J–ŒCÇÇä¦=c úrï3#yû VAéü¦æb‹“9/R¥99ðÊ0ˆ‘¤­ `Û†ë™Cå"Ö¤XDù~úT‹Îˆ¤hš%2BÛuÚüŠÆ=ÖáIP¾Iñ5e Åxîár8§I ªÒ“KÒLMůÄV Ýs<§—înQ‚¸GMjÍ}©eçM¿n-¡¤#lY¿²“ÎW›«Ñ²,±‚îÈÔ±²OÓGsë.© ‡…¦¸»áð$ÿ¸ÉYf¨J);$lyŽòA¢ã¨]LQ }@¸æt½HM†±²ä¨xbxÛÜ[KMN?€Ð <>I® ngXàˉÜRQû¡?蛫eÅÇ•Îbx‹kãrØÈ€z’íâH{Ëx`­T¼Xû¹ÎƪãqˆùÆ?¬Ã#‘±á""‘)fò¯g§Ca³ ,MK¤ÓOuÞPc/=8F­G5ww¦öRBn9mi‹›×j¬îlÚ_t;O†¦h”‘ÙMU{ÆìžÛœj®¤KU¬,ya6?q‹x%5Jíò'}¿ÅÚ#ªÌ{ÅD‘CI¼”m¶†m 3$-Ù0 .ÔrL1%oVŸ…ô½ßi˜*‚£ @árŠiøÐÚy„Ð.%™á›Úü¡v]³ÁFat¤gxñªv6#1(oi|žô x1@ÐeB‘3ü2M{LãÚ;Ø¥>•w Çõ0›3À$l +¶lf’F‰Î?³&zÒ*‚¯½ý¢mʰrÅt²Ÿ azüÙ6rð{‰KS¼X/‡T@¹ ,¤‚Šô\”nƒOërn62N ó µV¤1¤!só*Xo;Sb*¼Aàëó‰"_SI€šX¼!eS,è€Ð*Äã£ÞàÕWh’d]3–¹gxœGÛ:Ù¼TD¦óàïHp‚›`ÁÇ‚Z»¹eË8 <Ø\VpxÚþLq&¬²r9m’€É$t»$ã#‡Gëm¡ëM§Ø§¯Ð«ÞUùö×ÌÍè”ÎÙPP"Í aúìfØôU¤rÎE€aÊÀá™° íuüD˜›ÞíÏ!lÛ3P¼ÆqØ‚Ë`è)`Wc¥¬»Ì‰M²ÿŽê° |hŠâ¬œØ ÄäÌÒ, ,ç¼@{6€W¦ô™QðzHµµ­c–d1t ©Ú2÷L 4„± ç{ƒŠç´nÀÿ,¨†¢Wø&5Μ’!š‹F*‡÷Š^5¤é¤bs#Ĺ[5•¥øI#¤:6ân\>LÑÔça&;AÄÜ|0äõÿÕ*”Ô„mµˆÔÔ-ÇQ|§óÀ‘ƒÿÀ½ÎÈ€.œ~+´— · ÒYŠ]˹LûןiˆY†ãÛ6hûŒ7,–±/Šc(“‚héÄæc5ÿ¥õ÷Óº-ô×ÄtÙØeï;~„ 22аUñœÕp·æ|vADˆUð¹t±‰ ¾H.¸p“+wó Œôâ…e” 5ˆpõS™K˴ɽýK>mÚá+Üg,b%©;íœpm­ü—\»zà0%ÿÙD\y54‘œºjja–Ò{È:s´h¦¦ÜE-ÿ£ož&w$Ëì%½Dq · ˆÛ>jk*^¶a›ÛY!Ëi¸~eY#yÛér‘i2ˆ:9¡î¯ß„ÿ€Ü°XèùÁãÄË[©5íœ<ı¹eù0àq©ƒIÀ»ãÉàðï•ÐÆ~“+oGì$È‘’â7nèÌ8a­Æª˜Õù~âB߀Ƙ^©;¦a=ßnîÉI„5°H%¼_™ºå¯Ì9s‚Êïákõ ¡}ëêÞ ŸèKϸÔÁ꣬rW§íž­©öA&OÙ5Ü{rü>„ÎŒšuizÝÔ Åg‹}!ƒ¹å iâÏÀh‰l8mØ¡Ûø7,x&™¾Uð Œ_TäY}%y´Nöœ•Öû^]©›PÈ2u&»L(Ë€iו¼+㊅CÜx¶æ¡#‚y˦ÖÎîï~ÖØ=[™D—Áºî®àÙ8¯01lðꉂ;‰ñoº÷©¢Ûû²9ótËŒ¬¾ì4T‚5`Ë¢XsÉ’kN¡œjŒ¸Éœ;/2ý\ÈÚQnœB.òÂJBdKbÙŠ¡‡ Í—Ìwo¡my›…ÁüÄô°/È«a}¦FzÂ9wØ3ð^à©Ç‡Ôr°ƒXäð<²½úŒéNA@RÝú8ïNO’xÜnY;€s±‘‹#BNh¼ßJb—^ºB"¨žÕ Qwc<:s²bzš$="ÄÀΡøäÚ¼Ëx¹¢‚ÈÕ©Šeæ–Ræù¹§µ'UªÖëxaøE‡ZAtEålýJí8Q•î+æâMÒfk»(ÄÛ“ÅN¥]_ÞДaef¦¤ úa.ÇÁG`<ôªëVÃ'mòï w<ÔŰÕÛÍw?ׂ½`Ú©et ÞAq ²Ž¬Ãû@`K;ÖÇ©†_Þ›º&ŠÞ4xíïÔ'‘Tž^M[ƇÒLÚ±à.’’#Æð,éYQX·Ânj%²uŽÿ˜v3 › ¹>ªÿÞ¹ûK»ÜWfñ?ʈ­|¨ÉŽ >Õ<g w‘œ8Ó”pÆ*îfüÁ*l©×d”V<úç×>Oeŧ"',ïU’e‚â’¢j_ŸüdT­GÉ®·á¥[+·gcèÌc>Cc>ªìc‚¼ ܘ¢ÑŠàGž{µe”^g¸<rˆ3€”Î5f•íIaÜsÁ³ê³ÐÏ"‘%¶¤O¸š‡ôÍcz­‹t–˜÷¯CÏûn01úO/2Å úÇ&žž^œ•z‰qŸ»öŒÊ?éÑÛQÞÛÁx> Äà´+„©¦-Ó‰‰Zb\Ç5CŒ«‰a¯0AäÆÅÖà,ñõ@*´Y£Šu9VóªÌ0G»ñ4<5ïKšÜBwiyäa ˆNT«ÎÙUÐo¿¯›ZA0\yq|ûhá?è°6![0ÑØÁ“ ª™i®E.GáéId3ý;ib…È ïò>,Ëý Öñº`„d®¾™™[NÐV˜é›üOîF’ñ—ŠãRKš Ìöx‡°@îÈŒé´c ŸOyÉÅMƒ‹ó×ÊÚ†ªÇ£Q…Z¾ã÷‘3yÞÚÁ«Â‰<ÌzWå +VøÍFƒˆÙ¶¬`0d¨5(û¸àí+dvÀv ºî:O‚tÍmB·±ê)ÔñZz‹AxP#直6¸à)ë\SäväàŠæ =©”/8¦m-í:ãe‚†HZ~1¾ÄEQ Àu/¾–YL Åq• $Ëyq;-b¬êʳ®NÜ©Õ,æÑpŒušt߇Ê;:'h,ÏÅ…æ¸Såêž6|¯ÄÒ9a10ëYþHb"vï5ž ‘µŒ4 “mÁÚÜ12ý0Ý0ïAE—€6º¶H‰×ðÊÏz XUŽ*€ò K°»˜²ö=é°ôJ’á»%|ñ¨<'œ†s‡‰\ÕòÌÿy©+C­GÖ°Y¹úZÂ6-ÞRßSÓ7éŸkIÜê*%Á Ç7 ¼qª,‡-0íVy Œ%ÚGŒ…ÛuùO½ÓP¸„UÉçð¾â~k¹'8Vüµ?ꔟÄ{+ûr迎ªQïÛ2‚ã™'¦ùáº%΂éœ@3ò!(§‹T”ö޳ƒÉÎc$´·[ o*õ_'²Øoî ˜].>Î| OÀ`ÖEi®M pÈÀýéÖÖ«iE†zçOÙìsaAov–µÚÁ†[ÿvÕ–ióÀÃÿvšt\ëšr°€3s­–,HÜš/½Ð^åà lüó΢™S 2 ½2XÜ.ëΈÐJq*•¿ÕEÙ—?…?|Ò£džšEt£{zÅ…‹yß’†øko@mÑ´€õW;µÓ.Å…S`2¬ì0í‚’‡Ðt`ÈÃøR¥ªG&­‡ ŸJHÎ…¼‹gbf5ù órœd‘™V¼@MªÄs¡XøÝîÿ!Ãw+NŹ¡U¢Á5_ð MD[ÆËù3‡Ä}5[›ûÌ. _ÕBÿAžÕkÞTëû{H&d„DGe¢¨ÚHðÐ~K}ž­üà[®Vñor'ó_ßw` õlËFB[ºVq P’sôœI˜ï^`PQJ‰hjSúûkÜ/#f­Æ® "[H>3*™ ž¸‹玑d/‰2t\¨‘õHñ×áj_¤œó‚U/ñ#óOMËNbL[@‘áåó`òj³+%8S? ,wòúûšN!Ü ’óüË+éÁº‹¦-aé麂€ )CÅF–à¼vºÙmhBA¢œqî«þ弌ÐeuÖ#·¼8d||È5"ê'nƒ.\™3j¥JTÉ×¾Sû Km{'4[_ˆj3 Yò»íã¯6,,ϾxP‹àëgAÑÀE”E‹?8z ³GØ".QÉãß‘‘dZ$˜.ÎpwÒ ›Dk£„–U¾-¤=‚5+J‘Ò™;" «W¶êDº¾Çl)³×©ËÌýlŒÇü×s" !•?f\c÷M%¾ë3hʸÿ…᧬Ú`bdsèI]Ÿé”šb,»«?‘F^f(I{ÜN€?’ÃnºöZ‘8*]•T“•íÄi˜Uk0Ød%[ý„/E»—H†/Ðé;JÔ^¤"+àÂ.¬ý(R ;Ý}@9ÉŠ°Àr xÔÙ—iP Ò;’œÙQkìT”5± žo¾Iw/ïlf ®˜åz¶É%ð48´rÃ0ÀåõÙ)jÔàw[§IÈòpi“øIƒLÔ¹³œNfÌ í^šdWãöVLŒ^‚ö'A“»8oéÍ@“‹Òâ>Hª¹îvuXú¡EúÓVÎNzwI\œ£\0+/9£ñá4±IãPÌ=(¦Ñq)?hò0z8ºˆ…jt'höµ<ö7˜6Êf]¾íÐæ0f²¦,R5ÀÖöCI| E¶® €n€ómሂÑE<áøM.9 ß°ò‰Àå Ȱ1ÑP„õ±}²Õ1QB<ø/8nÒµœFi:Ÿæ†•ÎýkÒö熂ê iZ¡KBò´›nç„€¼‚³_{úLO,åÉy. Ð JFi:XSQ­X¯ÏDæƒ3Øî$­`â¸(©ÜÂ@² 8úe<éBO ×°5Ècñ°÷þÿ8QàÊÿ€/ÜLXdª+l£(‡èÐU1”KËŸLÿ\#®ù,6÷Ý-ìXì——Þ˽C($õ:ŠáK~©_ü諹O•z“¾ï:|¿tN×" WWïzÅCÓÑçöi•å²~£¥,âQ&ŸHIºu‡Låk63ëÙgiùV{Ût}-ôéµÇFŸ ·VkG|Àgg휣¹s6;îL 99Qì<Ýs-Ö^Þʼ7y²ùÏ«Vòì8Vø`ßÛÓ½S&Ä  ¤j¦¡¦Q±ÏVKõÂ×ùâ!ÄYÄE£v¬ûâ3M<µM>ƒ¿Ÿ¬,vU2V˜Íb˜dÿª€g†0Ÿ¢e,ÎÞ4¨âOd4‚rñRò[ø±G2„wdKëášG)Ê„ïÝc†QUGœ`°ÚAñ ­Q#°eg‹å+Ø{yJðs¹!Ÿrú$ù›Äƒ@…Ý¥c‘ƒ”P.ÀÝËTÏö^E1þÁ¢vœ¡íI9!ÂÖ€‰Ð'ÎIÊ+O_™“çMÛrðíYüžF°Yü%%@«!9.?pà¶¿J+Þ‚1lü/„+½1gÅ7B&yŽ® ëuÙBª^÷ÿ\¤èY¶ÞgoœC!^‚;¼Å8Z8ŠñKÇY⸠9ìÉe¨5aàâùLÍ(µ£ÈɃ»$h\†:²Øc$bA°Á jÎA•IÓ*d~²ÎåÑ2ñ?™Çíb§¿æe±|3t'qEu¤]¿wHìÃÒå®3ŒàЉ‚*¡#%ì½0ºlȜܺí¯ÔÖ›åá OHú;7@6®/¿ËKϼ4ü€DMòŒÆ–yrÞ`¶vù88f°Õæuo Ð"~ÎŮР§l/TRošÕ®3 5ÁM,ÜJÓGeb{„Ó«„ǤêÝ;Qêpÿ!q€ðû†mǺ´AK Äàƒppû2°6¤'Ž 2¼ ]R<°–³wÍ×øà¨òß~`_Ö³¿§àÞ/ ŠA8»"N{Ÿäþëå:ëõ| †yó¾Š x®8-ìºwO­‰@Wÿç IG~xú©<)ÞR鑜Qzð¸v+]ôÁˆ ¶¸ÐV¿¬æ3œÁ!’)hx¿ŽVUüí[ö:–‰†ªû]ˆó+o0È  µã éns¡²p\˜…€TÛNŠë¥m$¡‹ÿ^B‹ó,ùr>$s%ûõ~S i‚OSÁ²&¦~5îÖœF"ù!_# ̲gn¨7ÿã[…ÄÝz)/tï]»™?åÝe¹if|ޤ6f¹é41b/L”¦ôÆYXÜ”8‹Å¡Eºó0n€œð+ jçÖöIl[!] íÉ(Þ ’ý_qt£› Rß ®v G<Ë£W(´Ý¬ªòV!‘úĘo̼=Le=߉ŅéôZÓa&ïT3œ5DTe†«‚‡`”™™âFèYQ¼ª¯”ÍßÉèI›eSÉ<5Å ýÏjúÝÏ9;$ì“/$ô²|Vgk×ýp-Så)ïÊÅî«eÁ{§S ð7°[„öN€éiÇàFÏšžE Ÿ¢É-+/¶& ü d˜…G`A\RÇŸôÞìF?"[<ñË^ ª,ËXuÉKùõ¥âb¢·ª–ÔB4³ú IùgÓAIy‰¡‚ÿÜ„ì ¿šA4¼ìµý'©ä‰ñ­síO#›´èú>×#Ðï83ù_7j´ˆ?úNkiŠdoQßë*çÉÒ†cš‰äæÐ°Õ?B«'^ø¤OŸ€J@‹­ª?E Ð € ÊyH‹#Ù8ï·õ5®PÝb_W;wa2ƒ`¸ž~¬ÿêËÁ´~•Zž¸-_¸Ìö« 0y‘õíVT_D½’œ;‹=¦Ø«Â‘~ d²ÕáaW ÀQ×]« ²”!DÄPŽ`€æSv2ûtk“ŽîD€T{FU7ÅI¤WåÍ%­&0p©A=•W 2¡µÅ,Öv1uêÇÊįÉeŠR̯Ö9µúˆ:¥yÉÍ„\[˜„#•fa<`qaT®ék#$þwô Æ/î°v͵b-´Î ÏߘØÊE¬ û$-÷á(©ý ‹Säöç¡h`]=މã9 õ I8˜IKÇ Ìr‚¬@Þsä&êÆá®Â¾Cã›@œº¨#²Ò6ÔØRõ`ûžLdÁ€÷ž±Kˆ6:BÏNrh6žéÚKåÜ6›z4ÕÜaÁ2ÆJÓ´õɰɧ´Ê33·Ûžá<@î‘ ®ŽñÔ€XþL¢²^¤<‡K9«¸K¡ŒÁÜ4Ú™ŸVJvø›ÜW¥ö–§áLóµb× øÐ…<êòàV“'¦Jª†ïZM#šÑUö*ʆº™+ù¾÷yåÖZ­³z·Y49‹…òK/Ñ܈³Ý,äÕåEK·n`–3ާÕï tMí“!¸mö®CYôDîW߯˜)å)$@pŒà]hãå嬥}™ÄÐñìd`ýr¯ëh_áK¸H³¥˜b*32Ì™`;ÔõÞRr×hQUZjÊBšºLTXØ[Í1ÄŒ#$?ªuçâóšf¬§7‰ü¸iÁΆ«åœ &ýKðsù~¶¬ dX,ªú,—«pÏÞ31DX«…把 ž˜W‹õàŠb–Qó£G“楾 ¡c² 3‹H«ÔWV„¾ë¹ê´öÃmG`ìêÃWcV(¨ÜXµb5Urd´‚½DÀRgÉÄÄ‚/àöQË8ÒÙÂh¾ÒZÀ¢n©õüÐaR)ˆ ¾Ý¥­š2]Fh}{òãæ¸áô)éxiîµdh&ìLØÿ‚˜@]TULÓ%w‡™ÿó_4y¬á|¦ 09!Ž– +&Ár¿°$!¾/ÚåÙ Áó9#´»Xöš;†uæÅ)u|Yöí†6”[¹” (аT•Pñ駇¢Y]&CûàÖ¸¼Â¢¼ðoù•<ë3cØ Ôjž“¹ p&¢ }auá8µŸp9?oCÿm¦ÐðSaÍ ‰Õ1pÂ¥s²Å¨ýú7Í%Nì%‚ñƒ+V9‘vëeèÕÚ>É9dù8‹~ÀÝ »–t‘‡àýÁ4-Uñ}E2'Úq+]ḛ̂êÞ1”¤”$ʈÎTÕHŽº@§ÌÐzî«]í¾ygE!8Œ˜âc]àÁÙ³ü‚ÙçÂOn“ýb8Æ‘vÁ¹àÁ;–3ôx©ÌEë|äƒX-×hÖ5JÁäñ‰Å&8\§|îgñLý1Ï«êˆéÿú€øœØ‡²Ê=†¦‰`-ŽCìŸ0ÀM59µæÔù‚ÿ볕”20#e¶_óôrθ v­·Ö±œÛ¼Ù‰Q%!Qdç˜|Ö·+ÂÔnh°–íëß ¼S[ÙrX"v9?Gì×Z¼…b]ïÐCFš˜šßƶìÃqNÄptÂ\#-͘gM)å¨*,q&þ•4[÷…øÕÈìKã‘ÿkmfŠOYËðQ’*ѸeÕ`nX )Ó»ŒŸ§¼¸Ëšƒ:ˆñYä *ÛP週 ~Y» ¨{À´W*cí›FˆÞ6nFSvNéÒ»øF‘¤úfVXOntÕ"P3_åç]=W(0 •ì¢|{*ŸûäÄlNÜ/ÌuãÓB½Æ§…;oSÈÇjP]f:õ˜ê; 5ž½\F2 =“´`™æKytKÓo¿ð´µú¨)ìlCWl|e,øé"¨ÚâUIÑåD’¨‹ªðc­ÿãõ ŒÎ%“Øœj3–:—(‘c¤úÌÓ¾öaʬepf’ r~Ì,HfКvÛÚ[©©_ëû ŒàÜ7÷íêkÈØE³\è:À/•öaÌpy€CuÃ.žB* -qˉ€Ì²y™^sá>g¸.×+øöÞ£¦Ì`4èLÞbÒØâŠOÍÚÕ/'i’ó¦˱º"ØÄOJ£Xëˆ+Ïp~D]F(×ÖOÅTïAª 85àÕIÎuË~ƒÔÁü€qK°cLÅa+‡}œõƒ ¢¡ÝÒÄ‘?B—Ânë¦Ý«0tÝÁct“-€íÅŸXj"ÕîÒL÷ô½ÈY²û$ªÝ;¬®»©?û›YÛŸ£zÕ±ÌYàÇš~¡o$ë0<ÓhÁÀb@w ßÉKY¦Ü·:¢¶ÇF!g"I@C¼DÁ ÔÛreÁ慠QÜ>·UøXå**Är0ï1;qþ¤ÏCÎ΀®^Ô2Åå¼ /idæóúž8© gî˜h±¤Í`¶¯jœ‹Zžþ£\é°áñÅè}«3·Î†ŽÎáz¹4Bi^`ÑÝyU©Ø`trnZÎÄ"«8±u†¿TÛ|r Ÿ^õWâÙ1 }ûY_+#ð”"$KNïV‘¢-ÇhGL©*Ç…W·PÖg23Ò;VA’^ê@=7rÚIÃpëŸÞ×wÚÅAQÑõxÖþqSªî½yZ€ÿJÕùå®gƒ¥uÔ}8=ö ìs#b“éæžp ‡>í ¤˜F©¿#×#FZ)CÙwæ+ÐÌõÁ1#° Ó$©pË}=àͨ¯¬wx§4nÉ: ü5@ZT„^tI—E uµý(ë¿…£j…i3† §˜·>L¯)åû܈'Fš†SPQE ÛBkPc™²[-‚™¡ˆ¹zºís€¬‡/•?¦€xÔ쉯¤ ‚ТŽß4ÛìW_2G¢‘m;™>h µ$!‚!¦:È;p–‡HörFž_æ“û»8zE󂪡’©ªxšÉÖìx3 hm¬=¶‰ DûûÖþP± š59†Âý·µó¢»klú¢·1˜µ«à›?íE28³HfMªòñRGÏNØêDáœùžDP;Ö8Þ O”Ÿ‹VVQòº†ê±: ÄƒÚ«$‡Ó²å·¬,'¥(5ÚH&²}<˜‡A×^•å!~¤R3nÌÈ…V F ¹–=fEKoȪgè 2I>çÀ *_í¹4|ùwˆ\'-‹Í] óPØîî*÷®î›äüi—hk»+{YùÏUÐÂNºNyÀx¥S¶”bªf‘8ëqx6ÀY!ZEÙ<bðT3ÅMß,E+^âÿq¡lpÌÓ°ÒÕ…"‹$¯ªúáAÊ6Š´YOùÖø»¼0ýæ¯ÏÇL1®¤X…‰è²ì`ž½O}ßóZïð*q’Ü ~^©´2LRúò+œ+Ì.šlް»©üFVô!°ÏáEâ`Elž¯«Õ±ø+R L‡U@9Ðpu j› ÊJ0ËÛcp½ÏÓ8dyjîfh¾©1p$ˆ¦',œ4A¾þëj3ö×£Òµ=¹RCHxFã%ŒÿSûuy‹%ßLƒ…ëÜòOS>£æJ[ºŹSïrîlˆld“É[:û}dˆA©õnŒ!zë*ß»…I­7#T~C=K¨í|5æ ù$sãÚy³Çµ˜=Ó¬ˆ§ÓãÞVV€ˆ›ãÄíú,úã<6ÁLeA;WnE}Ä2;Èâbè¸ÑZˆH‰Ó v‰HÃ:9Dcg+ WGóh*0²f–ØØQ§°ÙF†u~?kuŒ¾&68<Ía7? c¥ש aÆË¨ús&í0¡]YÆÿ'm¾÷sG5„G9ù+ б±ƒ#ÖpÞηäkýBÝÞÓ©VÓÀ?&öð$ëÀ{’±–¦Ž##j†kiOû[÷]dÕ²¾ªêKdCÅ|J4ŠqÑ49ýHSÉ@:aÀr B|Ï4ÚÛÿI¾i|›7ÓmWýQ‹—¤œô³1š(W®i×­S3°½L>µé’•Úª$ÆAìwÈp9í\ŸØaûnÔ.™ZÆøövoZ/Î|KJ$ÆågÊ®,[«4¥µ¼1×ÏK6 7y Ÿñ/›5f ¿õyâ YŸ{³èw,ô?±­ë˜†7#}ãg¬ _ 3\KsÕ—‘çG">ÈÃT‘ï"¸Nî``+6øÅmrßýÙL BU‹¯$<ÔÀ"y>”(~-¨úŒqFŸpäËa¶FfžDÃ^“?·Kz;¦æ'Ô9ssìM¾•T®¤ŠS–f´?4n?C¹T¯Ôeè{h;w.Í«ªK÷ö+“é3J#R‘+Wô˜/ÚWiŸ¢Sô^2jÐÖ6ü ¥ÍÑX'O~{ºWñºç ËË`»„ß40,ÄÞAg 9{-·á§Àc`öèú {*ª«0ÖR+Ø.¯#JaÀh×ÚÎæiœü|-&~‡øð…÷w:`V±è7ÇyƒÊ²å šºæêp~p$£¥cî9ñþ¬ª†—~“›öÞf Å’Í\¥ÖŒŸ6HEV<ÞŵYé§ÚÕîºXçrYu<ÙP¤)3œœ9AæŽJÛ¯³ä$iÿô³]ÍùŸ Ùý ük¼k¿¡#Ö&†“«VÞ6Á—¥´š¥;ïÒ4Õ‚.´hÊ>|ÚhÐrl³îÖ`¦PT¶, ¾iwÒ4]Sÿc³]Õ™¤–—ïkîMÏuwð<5IÜ“ð©óÓ·ZIÓ;/l|Vö+t¶U¯Hð—tÄ`F!VJ¡]ÆüWV•|¡×7/í7Óc£ä»é˜øuª þÎæz‚WùMoV5KÓG½·Ö]®x˜ð3žOy©J«è?Šr%ái–¶s ×ÇŒ'ýy‰(´(fÌ*ùt¤øæ‰¶çqï ^c8ŸnÜós—òlÝi§¹q-%äO¢à˜Yèw/u¢ˆ9Bˆ &á5Æ×u·,Ë kçd®wõb'ö °¨È8¥aËOò·XOÖ%Ü,4‹nà. YÒt¨S~6¢vóVñÆLŠG‡ÄtaPþ³ú²ôÔvZð‰YZ¯d¹âãÈÜ Î¦ ì·õ;ß=³Û Ìx-åt´)”E+Ï µìMI÷Ôí¼´ÔÀ¿ý׺åSLÊ6wOpcq£yx &7Z#@²—:_â\sŽqO/¨£²·Lʼnº# ÆÐ6"ÉF%ptgŸ¢¼ 0Ðt>ê/MŠ´ï‚dؼA»õW%âþ‘ÑŒ}7ä³\G”W…Š÷<œý™dXc Å`ÈkP]Ž´EøR2'WÎ+îw6Œt¡ƒÉ÷MöNÝk"WÉ/%À5¹ÞÜ$S£ëÂT#.ÚÓ}_5Ä=ñ”[ÜKi%6Æl,Á—h6ÜZ €œÆ~¿ó×£Žu¹×ÚÙ&¹b¬3 )lvWºéê^ µ'ÝAƒmBÓã½EK(é¢äu|«öçR)ËGÓég•ÔyšK“XV7) "ì'¤YŠqQÍ_òÔ5oè WõöñÚ^ÔøÂŠV´ÝqG:É¿7coRÎ9”Y¾Ž£{ÛËAèzŸZíí×%)¹òÛVçž×Ÿ1Õ" 6Œ;áú5H•8ÅÖ9 cÌÈ$E¾x*TëØPµòäƒPb—²•ã»tïñ.yñ­ô;û®ŠY_ ÔŠóäÓuÃ/)rÄOê=n5¿î}€ˆ€hüÕ‚ >Ø®KMñþëÔ» P—ñ Re¨ô[$M§î—û‘zV îŽÙ̃Í^àäÊívß@)‰»IûQZñ?Ë{:ÄŒîß:I Ùaé·&ÆÞGEèÀð\âS³Ç½¢w˜†ÃdJ¶K¨4™.H*Š\MA]¯bª=U—8BÍü\­Í熜A©ëŸïåc;£'p¶bž[—°„ñië…r>‡–ßÝ®µÚvÛ…$ÂþI7ôå÷¯‚΃ÒÓ0†º¢ÉÁ?Ò K˜ucð¡Ãuä©<ÉHÆmÞ³;Ýu­)yë0£&ý±7MjõýåIªÅk€ If©4¥CŠ2b¯Š²yÛh£ˆäátÞfðÖ˜»{´Ù™'_nF›¸ú}ÂøÛ*t"!.À>ÑÒ;›ÚAïð“½`5aÞNP©Œ/Ž"–û”¼æä’¬/ºnÁ¸©GKË’‚áL³Ü‡8¾¹qÍœf]Yü[ä¡h/àÒÉNéf¡L¦C< (Ô 6£1*°¾h)‚I³â˘i­‘{>±¢¥EîŸJïG}*°h…,‰’‡¶)‰¯ÔPÈŠZ|‡ "ÒÄ–˜â{X¥`¼÷Èå2'9.ÜËç}ñSn=--ˆg£àµJò¿ÀhsçÅ­ù ` ‰ˆƒªágÐw'¢ê]µ®xÄN«ºßYJkÔZ¹v<©®q Cí¾Ph;·1%ùˆâ]ÉÖ¯; ˆÍšÀûò¦^NÚã<ßvm½þVÅ4Qà= צ ˆŒ8H"lI[œ5cZž©–«©Š·È``ÄÈUÖæ¦¹ùB(ÌÇ ßø­ëå•jÔÃŽ wVô0Ù€óÏŠO .éObó”K~ÕqO[c — i‡qw`æøNCáCÝåpŒ”@“ÎiÚê)«óì§Î.s€±å@ð°Iùq”I*B§ Ÿ˜ßŒÂièz=«n¸÷–.3zý¢l4ºÖì.¸19P—gÄ ÝAccïï ÃxïQœYÖµ´¼àe£S—6Š ¸HåÒ­>Výœ#±HÁÕõ–~,üp}ö;émÑEâߢɥ¨&0.Ô×nŽñVpÔ1Ž5Ív›„^`B©1: GMØ<¢©óÚ’ÝÓ"4MÓÊÍÓY}«í˜µ½µ*:¯ÉlhØ­½œþæ´Ñ ´ŽÀˆZ·ŸSÒçÏ@¹UžÇC":•<ÔYÓV%ÊZm‡:\1²míöaøÇ.÷¡>ïÈììIƒ†Kºƒ½ã+¯8Q€rX!üs]ö5P÷Ë…ð8.Q‡‘Â(YT’$ hšÑµ<±¹€GäaOä s{xˆa×BçS»Õó•™ô…T5Aï¹1ŽÈígãœpY í‡‚ù!7³|gs$}~ÆULzˆµp@¸›ŸAõiZåoÒ£M[ìrcÚ®r |BR, ¤Ð|\¾£ð“8ähqZÙ+Fw=˜ëó×ÉWA’àÔÿ3zb Db+Wi¸é…â ¡9AÝÔˆÀ~wÔåã0ö ½Ûµ­¤|g@=΄^ˆ+å`Ð Jý໓deëX¤eî½ÒÍËV‡õÁ¨(‡?$´Þ"ÚVá×~ßÕ]Ë2 €£LÐ÷)móí|çk]ÐL€¬äÆSóÈ×?G¦D H†­nok¸ {”WžºŒ¼rc¼åÞ¸06sD$Ehp~qúB>gÕŒ™/Ÿ£òŸ6’ÀÛ{Q‘•ÐÜàn2vâã>4÷€{¾b{ø6'4'1oK­ ߆.IŽÊ$ÐoY'Shë%ã×Wû ñûš¸ÀfQF•€R3/é°-îÈ? =CY?€O¹ð5H% Ó^u#OjtÏqDÆí Ì» ›ÁÞîªôÓZ£×þð¬¼L%¿¼'Ù¼Jr> càòg²Ÿ€à&…¸ñ:L“bU¢›t±U}O_g8b ?ˆùÕÊ…ÚÒôÇÔ*˜ñéj¤Š€î7™‰TüþïÓÉn†,ÌN_¾¶:ójšÇØö[çx®o¹å2ž>ž'@Œ»s,ó<‚ìoÆál’N`8žX iQ2²W¯ dê9ï¢M.dnœø#vµbñ777µ ]{Eóê‚«a¯‹)õû4CJ:ç«øE0lI”Aú$8_,ÌÀÃÝÕ‚>7µ )Ïš¦óÚ¤Q‡ƒ‡.=2 ”û;FƒÑÌí/NUžøÐ®8N%‡p¨•7-šú«^•ƒ‰gÌÁÝŸ¶>ýóZ'¸9<•9³ÆŽ8ê·:­5òó¹— Û@sM1PؼÿvOTÄ{|pà6Ž’6ýÌÀ¾;!¯¬Pëx¦HúøÈ¹ëðJoÊÑ´|øñÉ{Ç_v gnU“q^_›ãa®µsípÝÆÏÊŸ1IF Cß%,6îí]‚ A »¯›" ™Tgš=)š˜¼$³ÚãB¸ôà,À·ÙrÂîLÙ‹ Û¬mXÑ_™ßsflî\^Bòæ-È#·êƒO½ö¦øüŽl1¹C]A·ËK{ˆXã^J EYW´!•vïÒj*@°ÕmC€h.î «6 ‚FŽ‚Sw»ï«Êg2XAuêtñÀ¶Óúcó«S³œ†¹½Q€XÀìδҚ?}D@–‘^Ï ÃVîúø-_01AFÜþ1hØØßv߬žø®.>›ñ‚cáÌÁÕ-=³™®P»:œ3U,î¡vÕÙ¶^©iÛåîj¦G.¦Û£Ñp©JÚgjú Zo0*‘A¶ÛÖËÍ'®D¹gÿ l"ZæôŠ:`ôá›hp'•ªFèD\üÒhÝ“Ú,EC2<>Y6[PoàœÉɰÕ$y!«–Èg@Huaw¡såØ#ÔæU‹¢g¡«2ld]Ä<6ÿb&DÁª¬XÀA®½ÑÚÇŸ¬| M'EÒÚUȺÐ_MÍÂ@±‹£`UÞÎõO[º»·¦¨ÂôÐ¥ÖÇöù¶®Å±i~<ê@SDŸÈ×§ž±<ü™(ô®˜+[}áøµo¥°Iúº¿GX„Áí¿0cˆBìI7ðSdÓxiEB^mÿ&ÆVu±‡!ÆÌšºe+Ë»•UA(l6Qòž°}1zÐL^§†è~úS…æRÝæ>{mzeyö‹üÎÅñ7•{Æ×7Ì‹ ’+ð|¸dØ”m˜r¼1’¼˜Åj¤}mGçPÓ'µàƒŒ˜óÎõÖ™ð0(bn°ŒfÔ]¡¯¡£ëF·ù$bc›5zbØÆ™¢»bÈM¤ÜʱÆgoëä¡Ã €5•nô#¼\iÉëþ«~YêE%…ÌrÀ0õ'Gŵk1 ÚNAÆ¡‚Ûc£ ·E*7wPyË‹0÷vßÊøˆR×4Ûs/;ÈU¤ñïôkžÔ^µ.ä 2g8èb;"Aö¦vëJHäk_²F3õyPX»Ç‚ 1˜¬6½*ò‹ <úÂÿÆ ÷Æu¸,æ<šßûÿ‹iSøðï÷üÿö±‡j+|`œ—Óo‹. læí=ø°""8ÒUÕ©»±B®¬fîEI´lm©4®Â„IQÏ£#¡Ë°ïr‹nÕÚëÚ.ì*u¹ÈÃd¿ì# DøÝ ÜrB"”Õ ¹­Ìûâ}›ÿ}Ç¥ÐÐ6þ+©;žþü2u— û ¸„?‚E€JóÉ<¨B/B(b3HBÃ:Š(DP /pPf¹WÐ ž^… ©)º9ÞÁÁ™ïÅ”ðVý6àýõÙ3›`geâ5 cm„£§Y!â/íJ¬Âƒc¯•–çµåQߨ#ƒæ¹¬©¨‘!EºÕa蔓€ßt‘'¸KÈÅ–Eâ™1œ{4СêedæÇqLêêÜ&7dîSä¨ß'}Bå!Îpõ•™;ðd›f°Í’¶%ÀYèøw–Z9ÈŽOõÁGÝZÞ>ÏLm‚ÿ±ºi¢÷)Ø~I@aRv÷w ݦf—ÁËôZ^OQ#íµ4•8iÜlƒB‚Û8:`ß©•ÇȘ<¶?¾ZWR‚ÈÒ/HñM`:ð-P³èCRK‰û Ž™ ޾´ËP.øók$¥˜xÒèăˆŒü;êãÎïKE`”eû#}‡w­ñè‘:BÆë¼¯Å¼û*%?¨öáñî¹W*!j•%rhãݰº\ùò;hv]³;4*QUœBA£Ô`Kå@ˆŠ>¬à œú)æBÈsEúŠca™ÔËÁGÇ|ÎÙR"Û²v±«r/8Ì×YãŨÖI¥"y~‘·xÿ§€|AnˆúÓ³ï¯1µcq#„¯’ñTWLº˜zxl%&Að-….¹Ý?ŒŒá¥4rÌ¢>t»2þH:àk2|ðý[ßdB\€­úÂÎS±wLÝb‘gGÝìÿDñÑ}œB¾ƒùìæ7ÎÇù-?ykÉúœ0ï>šÎôÐÚ/÷ý¡¬úˆ /ØsÖìejU7{NÂîA‚¯óÏMªèxÃ^nzÙí[V>œ,ðHÑFPòIûjÐfÌyàéöc˜Fî *µ"D€éyŠÏI[¡”ër›ÃŒ±¥FV-xŠf®öÓ%§Ýjs¤.GºÚ-ªuQ§@ÀÕ­“1ÛÇbž.LiBo %‹CX0†/'³ðüuZx©ÅµñlÂ&âU bR¸ú«!^ýç‡fY¢(й>¼µ`’éïI„µÓ`A0öxá pc¥]}E—&'s¼o„0ýlÒÑëÁ߃HKÌ<Ì‚¾Íº•ß(`Ʈ̨êL¸ïN/‡^¸íæ®lŸè¸´TÕYvͱ„P$9ŸvS4Uâã7“¤7$HÇx_TAÄ3àÝUðaت;7ß:~U5?˜ë¯Yªõê˯kt½‚¼p¬§ù£×æ¡°¶ܪÇ#Àýzû‚‡¨f@|¥T_¼,[ø ÆòS‹¦øƒ©Òr1⥭¡,AÚöšW|Ðø„ë R\ ñŽGðTpÎ*Í[NEÝfTÎÎÇé^ü¼2ùŸŒ³Ž@’ò³Úrl6 XFuÊògù:4…Á%±•ý ^: ؈¡XCÆwUœ[¬(¥Àó§0ñþx<¢ôY, Y8åÇÜX8 <$„(ñVO¯ž÷µ *ãÒ’´ÎvW—jÁد’+<Éh‰¹‹Ñ£W¡±4†Î)*ç¤o=õTš¸uíõé^c¤6sœÈŒ`»…VƒÜ.ÁQýóÿa—hxÃÁ0T¯‹F ƒµ;ª ±‰é¶ ;ÑÉ”íÑ…ã÷“šÀW¯Ãî ¦¤¡”  êÆE³! ü 2uÐEB «Á>?ˆ¯,æ‰| Ddú)*ÃÓ™xCo­á?ðTIJ«¯“_#2Û±ðÛºÝïÝí¢Í|ÙÒM^Å`E?”ÇÛ(ÊI ²] îúC˜¸ùPEÕ+J•êÕ -ëム ÄB®reÜ2 œ&pÒp×_smç5F†ÜÑTdõÈÿx’¢¥õ¤ŒCº½'Ý”9ÔÕôÀ¬Ý®ðHr‹ÍŠˆ­øŒNŒbNvœ}]íA@Á¦»"ð“˜7옾j´Cfxo¤J{oŸÙ5ª%r<Ëé ðòF½,#lå˜ö\'øû:ŸdUgn©;üî]ìâ¸o¬å[˜Óu†0³`=È/m wRõ‡‘ÀÅ|jÒHŽ Ïmq|ünà“x°ñ%Äïã¼È¶dŠr±ηâ«Ñ‡çÇ&qH—¹Ù™‰F6ÍÏ5¸Ý†ã´Q353_þdMOÅñD²™”¯!›¤ £D5”$‰þF¹¡ón£o…ÁËØøZ‹Ôªü™9€í’öÏx »<Ïë¯3w‚'Ö*æÿZŸ‘ø“uáSõ‘敪pÍð$ÿHŽÑ aÆÕõ®|MDOóøaÒ$¯?å·È™H;©':´5ÄŒGž!¯=zý`tŒ%ÕUñ8ï×—¸fŸðE예þ+8ó€„thbåv7[US6G²UD ‚@|„ ¶@ùß%Æ›(£ø„f[òø„Vm}‘¸wêÛ¸…&†V.¤Axt í&7>§ jäy˜ ¬êÓãaB%B±øžyH¤q&GßW½ÚÆ—Q×£_}Ýç—/#HpyÛ5rqà,eyÃ,â°ê87ò=ô3üá œù°ŸŸ‰¶z´œÁK2òÁ[Q¥vÆ \€,“ügØ‹VjW‚`H}çzzh«ÌÝü&· / RwýCdºØkÊ2 Û‘7q2>×…â k¤àÉ\?Ýv ¡õjáû:Ží&r'ð+Ò@3±úìv,PýÐ}3ìB±©°x¬ T4-2~ ô›M³U(Ö¦Y%míÎøÂ©onÙþ†%ê%È/ÒŽålTÜ'U(q’ ÒX•û™éŠE½ñªE¡¶å<óœZ_Ê#ìS G §Ò0Ñ#Ž ¿·Ž øq“˜öL ŠïXP³RFl€MðIeߢ—Ö¹†(K@Īºþ À¦8òP“¯>tåï¾ ð#<¦X÷„ÙЪ;HuxK²c(àèÄe§…Â^!PwÞà•ÄŒ¬íåu,ïÅÝnm‹{ó¦uGùC£cbÏž-uÆïÉu“™·m Ø^TwSϬŒ†Ÿ€øÉžÍª¿y.S‰ò/Ô#Zõ "Gè—_ú'J¦ ' ÂðJ£í¡™/Œ$”¢8—ûµ¶<×î(K¾ ;‚,B0(Ú¯ž2cuÌ.yXƒ§ C_™Œ¸ÙŸÕÆšÀ¦ÌÑ«Øsz±êÓ:Û¶ wvÖ$ ˆ\±¢#iñ\£t\0(!#蘋¬ãüO½#Åè=ýÄnMgÙ 7ú‘eCzÙULCãØ€¡â1ïQù…/w–§µÈó¥Þ_I_›2‡Û «9,bi¬m70!¢ƒÇÛVvq{ȲWSÎÝ©R“À!5ƒÞ×ýs˜épRH¬êË¢­B&’¬K«#×êÖf d?$üíù.Ž`+áõ™ß× Gß©_Nea±,a:¿/à €,BZ³‡·‡Ãðw£Ð?þךö«º¹[T‘@‰«CƒD`÷Ìq×…¹©¸±dÕÀ/\'¸¿üXQ ª^FÙà©R4é.ÔêŠÏ†LTeô@zÞÝ©ÂÌç[}úÛÝ”½ÔXƒh”rƒ ˆÑ…\Žo>²ž)`ý‚jØm(ûÅm>¿æl¨Ksmô\œ<—ÁZ$‰:@ö‡ƒáŠî­ˆ“UHâ| e= Ú¶yã˜Ì»¹Ú­HÞ}ßì;î’Y•.Sµå{Û~=ž‡?ÈkUçà6«¹ŒSü ¶x%pè¡"#+ø»õ˜ŸåÍ]>Â"!‹: #Pð@b.v^§ Y3|­™ œTB4!O¡‰‰¶¡Ø ¨ýa .š™íV½Ø/ e÷ð»m¿â/3†€Hp ècG]O˜£‚YÀÚ´aU¤m\Úõã´ùÛ\&{¨âdÇ•1ºÎ8Ý-ÙTí°Fоå©ÊÕ! ?(Ì'q;åƒø%¸s~êö¹æ &5wEʉ¥¼ßFø:âK‚qD4.Dx–”ñì†UšQºe€ö:œ9ê7kÞ¦dÖWÁYc ìw^äB?ÒL‘*…öøÞQ"ƒÀ÷:ªá;ÅajvN-†0‘O~X†ËZ®‘Ÿ½æTûL<åÓ.¡è±0NLß,“?Úm¤¥}¨ú#Sö0ËIg`l=kD±4‹Î¨¯YöÛn5ôÛÛJX5bk!U¸ê §Ö0cÓVcÊD29sñ+ÕHä bàš¤¡ˆŠš*P\8µ!þ6—jì~œžxu7,{s= ßÀ ’.ä?¼MZlƒ ÄÍo+ã(’ðæ0ŸÌÝ Mp˜Íª¹PÛø“»ÃFbG“‡N#s–"ÓDI¡fæä A$Áiå½k2p³Åpgµ„Í]î-49¶Dâ‡wÏ“aFré•9?1!SÒ•NFÑ‚|W^ÕÖ¶7ñÔ{‚ƒ _ì@ ÿŒ ¬?DôøË¨nUýÿÁÇcˆ¤[†x”ÒüÅj¡ ú±[ûјžR'¥5 õ¥&ºòå×éÁCÝ@hÃD̜Ĭy4ƒ©YÂp‹‚LXÑŽÞŽô´Iféž[­å£ë±âŸÛ|ãÜÓ X(LX¿ R2Åmïo9ô1+?Ȓȵà ݸ’Bßçßî%˜ùk9> ÐGÿ÷ˆiCÛF3׊ïšúîâM=³ô¨i­9sM³…Î"­\`pZ(p Ĩ¤Ú”Tãý‡lí,ã±÷®YÓFÊ`6…bßíï¢1e Ûÿû*lŠn “£õ•#¯é¡Y©Ö›gSC™òRcS-¶„`«N\(D&¦4…¯ö¥<%#Í#ª`}þNÎ…² –KLô£¢½,„ðŸ‚b™Ë0÷†A+ 'œ,‹b£²•0J¦qe±*J÷“¼ýÿ6ݱE@¦1²ËÊ¡ñ›g¶¼çÕ™&¤Øõë2N½\èNû}cKtæ‚8|Ò@æB¿MSAjVýkR ØÊ’ETJéœNÅh3ËUîôy{ ÑöröÃæíÙÔk8lÞ¸›µw“œütªæ®ú<çÜà_MC8¿ðŠ“³²pí8_y¬ØÌÝRà’ƒ*\õŠœ˜Â;ÂG±¡þ؇Ñ÷ ÷MQ"‹K' k‚ýÚbDÀÍÝyËÕ<ÌZ¾P¾aA{ÓD`˜{Wiʪ“L^;ÿ9‹®³Ù¦äb4¬ó{ìýD¿]Òï£èÄÇÝHˆÄŒJdðÌ*úK‰@¢|’[5ˆW4Ÿêu{ð´6¨"ÔŒ«Y²†tÊéjö¤0H!Öî ŸA¢CI±ãâjÄQK†%SH8m‡m¨ò߈D±ä›!Öéê6w¨)ÿ@ýƒ• 7£™•>,éž ’'.=ȸзÐì<Ò†˜1*âWΖ 02kÊã~ƒ¡%Øn°È Ø®ÛóŠI¶Ô}e´FȳsÆ %cÏó%ëÒ(D!ŸQP•Ý<D~_;ƒr!뾆ÏÃl[ D@!%4Ñè2[p Þºf±0ªK9Ó=Ú%Jrå6œæÄ¥É‰ n^µx-·ô¬áÛA,Í_¥†’Ý¢E¡öóáï-â÷5€KަøKäÂôUšÓÍŒÖÆ™£ŸfVÁh_¡ìL#/Ž*Üßåz‘¡“‚T/gê•aÇñ>’{á/Uµ"l*í¼;ß É †@8Vèöô¬1º ülf-u]2“i.4é;Oìuõ´lD‡j$Í=¢kn°ÕŽÛ‡*€²Š“y#ä¾ ¤´')ç £CÒlÞÖpQÑ¥ÜP¹4?ö¶­¹wxø‚¿‚Ÿ«3¤ÒýÎÔ·šÚLã0È—±¼6JèÏß®‚êÂs¨¼V·å}ÒhÝ·ï<–^‹u€Å’S5 ‘Á@iò#Yó¹þúÙä+EjX;8¶g~—ÅçñÅ·Äñ*Àø mCÑ‘òL#ÉåÆ2DDª —Üéc0-ú[ ¶Ùƒ!Y.B½5QtSŽ‘¬¦Óχä¥.êY‰J¸À YÂky–W³5x÷¤Ýõc©ùxݺQ>MiGé×GÝ+Íó#Ý“–öÅœÈ$š…7 œ~8{9'™Ò%±µ±pè:=ý…¤ù ÁX­Wõ0û±„à îTTáÈÇ{míËg<Ôæ‚J*d¾«'VÐ)Y«ÖC’¹Á¬V«tI" i^?ñ3r¹N6€uØ-ÕŸz£ b\a’s„ž«ªÖ$¦Ýfɰ¬¤ª:ºUõÕ Ø>§sãêÛ̓;°ØÃ¢d™îF9;€„»$Ï=ø¸;b3Žk|óÚÐ'’Øö³éÖdÈÎ èTê —±.ª†^ú‘ÞC[.‘?§ú p„¹žÔ‡Ô<—P~ïþýx<'Æ]„.'Õ*éF2«`s#’þ,ÝÌy;²‹éøÏO„!u< Ï÷U-«ýÎXWIÿ€ŸÅå=º|õ㣕Û7a•ˆ†‹ÙãÍ=.sÚÜ´÷¯fùzŸîï—¹¿ê]£Ü½ å1kÍr¬¢$_óY\šRƒ¬¿€ëÑS‹¼«ù%MJO¹`ÊhY‡ X[þ˜¶MC^Y|D ÕeK5¢° nñX$mâ è6CuÅ÷¢@bò´Ò²=ß^Å<£\c?·ís >hd9Ý,"ˆ"À­úyÍnuÝ_Lé7 ž¥U+}¦]$c’ÓâS –-doúóQAyþê Isö[A¹Gc˜u)j)f«³åã7§ófÎîÞÔf­‘øW™Mï {Æ£†xìˆfÍݪqÏ÷-\%§Dz 1$‰1[Þh˜E‚ÚûƒÞ«  wrc QäzлΧ/تMN tEOÀË8ÈqUL8kdNÂçx‘!”.;@3"‘“¢Å™Aœusᮣ&ü-àß¿Çù Ÿx0¼0†ƒN´·¨-zµFˆ ëiþaZQ“ž†Q“ƒRþC&½wR*7L™äÇ`_5O¼z÷bÙ’C†?›@ã 8't­¤4J)ÒåËU<Àþd”±SÕýçz¨¾-VÇØÍBœpå$§¶“›p#!„@ïæU»'>ª¹ƒ8=’CQ`¶K`vPÈò`iŠuÈÿ‡ÂÜ#qeUâ§\úœvÓÎýžMÿäûtGœÝï‚ØzoGÙÂmþé!LMl€CôE©mÒã)ÖzµüÁÁÀSÌ”N´ÿ|ØÏ)8aV·© a¦»OÚâúP7]N¦þpeD¶éÿU2]äHpx Yåú8ø{›¦Yìnw]žO§¨«Z™ÇTc¦«þî—ô#ÈEyuUî"u1€újßbÿé-Ü•¶7ãYféŒ=á0YåYtø¦èô÷XóWœIiì¥öů™«¢„Uã|an4$ ä{ú•cw"<äU xËÚŽO$ °¸#\^ê¹@+)g ›”^Z:ÿ ŠIÆææL"á }©°Qíj\ƒ–„ÕèVBÕÀã®Êðà‰r¨¤÷ßÓ³RÜFŸý/CÖ &ZÆ„L´ÄcÔJEnKeGF™h Ó.#Äöë–;´QÚ›ïÛp{:­òN+Â+µé{9¾Sœ[Ý'd‰äB¯úå¸@÷G2:BÚM šÞÓ½‡ˆçÜ¡aÍ=dêI$Ð )‹sÙ !YRýTàÅCÁ˜ê$˜³FÃ+}žŠ©$A36 ‰»T*è}\’™æ&›øyLL>ߟêM¹t?úkÖÖŠÚÚ$[1‹2è@æìz– ü°ew£È6ü“¨aY¤ ìFÎú„¥›ú? ºXŒMBªÚ¿Ìkˆð2g* Têˆ#]ÅÃUô¬éŒ.Rø(q öNoý8¦ ¼ žƒ{"8d\Ÿx  Ó~¤) m¡—]¾rm,Íëbû<Á×p’.~/%—´¾É¡˜ó·n--žãªžÄ^î4Úró-KÇõ‡=”„Xvøif<ÉŒöñó´põ>.¹8>UýŽ.Ex×ú,™Ýç›j¯[‘Ù&NH£d=ž ªé4N³vÛ_ù N𶦬õ/O¿}Þw™¹$ž–vË_T`‹Üogtí½Ê^A»cXµ4"mJ˜ )¬ ýÑ-z¥é¥Xª:²€n5ÔÉ(_i%·Ëñ¯fšþ3‚;¸Ï®Ãñbÿç·ëìZ\ ¨¸Ý5L¤Dm[³IµÆS.öw›9NÚ îßÊñH&á~vuß=A# zõÉ^Ô{“_Ö‰tÖg”®4ý¡ÌÈløõdUƒÆ‘_¹ß5›vo1a{ Qޝê9 E³õ}¶~XQ¿yÎ U9]~].¶‹¼b=ú‰ð“`‚Ïk†ñHJ$ÖÂ$Za`#\™ •|¨<ÎÅ8Riš.?8(5ßÁöô¡8iÖȶ„@•mú_˜,r™Ÿ%!–Õ”ZC°Ý}•+0ΊzYCq™¨¹`ÜíŠâæ?à")Q(º­}æ¿8A)#Ö¯è]ý%µ•`™+ã¡×JÏ®(šÐÌÙž~ÊnEÒgŠ ²‡J•Ñ“H¿ŒR–…Vï°' Œöã1FN)üàÞ+<¦SÙdf¾cÜ1ªu]BV,"ÏC/uíÕn$ðº¸ú/é00§¸˜øÏ㯫¶ Æ&’iÏël¿UEU•úõuùÓà2¼èªƒZÚfî#àCÂFl„øýÍ+YMŸ×.t†é26¤º­X Ø‘Ä}—_r¡¬7¢Èi®»¾zm9J ms÷Ù¨$í¨{­2T Ç"n¥ þæ#“&n'1 …-±PQ»)Ú†j^¨ŸÄiâŸc"ÔÕ#½ªË’ó©‹šn>0<ÈU“ iN¯?–ß©´D#ågóO¬rÛÁXÿÝ8Ȥp2»öž±drNUm?îþÙ‰û¯××c¯LÚ¹Ôªš ÉÛÖ*Àfá3ÿd®äU_yyñðìï]mÈI›*,E¨)Xˆ¢Sèܾ1OLd=¼2À\i¦©üœ$Jr,¨i&æ„OîÜa×ôцò~;ù¶*“•à‘Š#vË ‰Dí2;¼ZjÎ?òä¾Þï6>×"ÚözÙЭ’Íúm“gB³®µZšnm¸ó$Þ&„R®ÝªÔ:>c˜°.=[I;;<$|”ªÅÞ$_å ²[)©H W{Q1%ÕoÝ$ICÙ̃h»¡p”òåª;ß5¤%åš*Hµ;Ö\¼ëù5°?R=±ÖŒT¤±Çm³49i1ÉXqküìAð`Q y°tEÓ=>j7IºþÛ´–™÷áßã:åæ{œµ >/õ&§ë Bðƒ¿A~i[婇Ãèœâo$zJÍ3½pyª&ûj MsæºoP“w"P:•›oƒæ¢všnÉÙ“ÖP”³ÙlÆôÉL–ÅÔr¶(L2§C¾×'Ädqg@„1PïÜ Ða¨SõÐBÍ£ö¹Þ1ú¡¤Èev7`v—Åœ©¿â‘)ßšTq ïI ŽÆãàˆ [qzÓnžb ë\IüÊbWCÑsýÓ?ë©ÿNd¿,P&Ä+ qæB®¤ä€Ñ0",D?¹²ô´øÃý6¦¾ ÄâcØiŠÁÔ©®¶œ3§™²ŒfÔ&×-KpÁÑiyví‚èp‘8¦1¹ŸtÚíXmÄt5L6¢°å’ñ“zhoïXî±>¨ædUn®çHƞȼ5Ôo`BiºßuúÉíq(ÑËíçÞ{@½èAPP6M¿©b¦–Ëg½£‡-J¶~Á¾Tæ¤ðg‹*¨ƒ»î!6¹ÉUỏÈ› µ¶WU·¶m°MB9IáÐS†*€]†‹‰ÐîK–?K$Á€ŒH£AÂ=-ì°þ`ÂWM>‚»§hÞßgo»øÌ0qƒ6•‹’áÐÿ£¶he': I0%ª•{¡ø *¡+_®Iv¼R ŽÏvïr-FÉÛÂ;ëQúÕ˜]BBÄ8ò†ëÑzc¢a‹ˆv€ãÑÆÑP?l­´0Èécœdªì(zTAyÔùÑ÷QÕK0ó=9€áŠ&ÿéÇé]QIÚæµíEr¬&$Áo¿M¡pØ´ÓпËe³kŠÏ¾€E3–C!—ò5øáKÄð³…´Ä^šåØî”`ŽRµ5hÞDÈרúQ‘¯Ãrq‡ò£l¥ýü Ïà%3ôÑ<Ù¯«ÃDPÑú»#Ï£Œ¾îôwfàf¤ò1b€^0ìǸ÷±2 Mµ¡o Fø*îéT,”c˺¨‡øH)…¨ËìË;lrm˜û}43Dº(26Õ HÑïlC ²´2­~ƒ·!K»± 9å7ÑýïLÐF´´w`;r ™UmÿÍ>,A¥4ÎÀ*[ÝpÉLïU6ÝÓQÑ`Ù[òŸíj†…èU fwyÍû2˜O¥~`‹ ¤(Uá°Òru¥42ÀØÊB€¨­M:R ëP_†ÂGPý;j€Õ;šÀ^»C q÷ÖýÛŒý yg¿ä Àþ¼>èB×?-YÊ|-…¬) Ä»5+ê‚'Ç~IR@iÄZ&ªåNmáÏSk hø†Ãc™ì ‚ƒ©*–”—€ðzkqÎÕ©I€³eüÇŽHvst½YAÅ9ê±>jHáuU8úÞj€­Íq¤œš ‡¦è¶Ñ\yÉ ê#ô’«k\Õ¸hƒ±󛥅XËå|$çKÇêÊ•ÓsmI¡N û£Vû¨©Œ"á]€Ne!gØöÆïO“T¤ CL´H06è‹M§\Øð ‰(žÞ³ â:dPßìnï‚åöç¢=O!‚ׄÎIßzïd©O1í…ùZM_ô‹Çu`}¨ædé Ø°Ÿg©¯œª'nÐÑ¿Tôðç[ñjï9SÁMíOá›J葺:ûÓ5¸Ñõ8Gzùk!ÇK. Ax¼‹ ¨™vä8Ù•6pA†¦QËr ùüFÜnB¬e†µ ¨X ßòÒ»î`œ.˜³MC Àâ;/‹'—L(ìŽÿo·ß[×Áõqñ¯ßº„(?б²×@fÿ*S:µ¯'1ØlDMÒšÛ„ùÖ¹êN`*ßÛDH;,ìû¢˜ f0a> Vc½okr·9áÅ Q™|Èö,Æÿ)š××øõ?]biac/b\ކ"vtacL"+½`˜?j¦/Cö †¢þqn “Ì@fæZ‰ì¹yÜGÊ«Xi:ø†Bý´‹»—“ÖZ„zÁ‹¼ø±T¡h‘?¦† æù¢•I冾J“9„p¬ÔÝ2«°"к=ƒå¨Õ$ÄTsÈŒÙRü;'œi+l²L ñƒcawJæ3TÃü'U1©¾Ìô< Å$iÕ4ùºl—Ûot$ë§Iìû7F9 ;°[J{Øàñ`Â3'o;ÈÞ-ˆT9ž›ªcz€f%Ÿ¹Âr‡èyžŒ¦6Ž’” vÎ¥üÔ„hÒÃqYÜSÖ¹ÝÀÐ)ʼn*òj®áÅ8GânI{ÃÁ|0ŸB=o¯ÊÑš.ýÅ?˜õ]Aß°uM`¤d¤ NR™O¶,H=n? ¨6’Ôøm!’èˆ-¸ÂȬí'*ê>Êç´'ÀÙ•qÁC2gQ W4çfKAÚÂÌÙ„ŸQÚʵ`+;ÿ´T ©ÛPÝ~ˆ¨? §Î0ÞFöá×Jô6Âà\H#A’hüäu=¦ñoËëoÁ[Ö×¶s?“çn° fÖ¦n(a_Ä ‡>e°{V‰Öz¥Î;îåìôü¶×Êø6mœó@‰a¡ì€ Þ´Ö ü·Ç\ºÏåÌ£$"A€€ÿoÁ8Ÿ§U–1;ÆBõÊËú—Y¢Ý&™«ÞÑ ¡Lw. ¢ªÈF ……ÎÚä˜ÃðGeÁ0ÁÒRսⰼA¥ø’YÓø—¹ÒÂZÂ7ƒ|ä &~IP”Ò°FÝ” À Ã3Ε.ù!¸çøpy™…ƒYßß/—3ºx‹$Ò«§Œ€£@×\ØÒb¿ïþQ¶Ò/\8 n¡Oµ• (ÝD³8:¥tIzO‚ɼÚ/”@Ôµt4°ÓšÄ]Ât›³¥ q:è54‘¢‡™¦¡„H}±ÏïPxý9tL›°ëçbÜùW眂ð4vOyÞWB ê¿Í]¯BŠvP²¶ùgÒ.±Pþ‘ý @ýOÐöˆ®ñuaçæºÉßö!ˆA‹µa§I7?:€¹LW¢Ï7›¾pA\`šdØY„ÒÇqvM k¹t5¿&d¸'÷D ¥ë))!˜D,IJ2U?bñGr'4²˜›è}~û¸ƒctBêÕFÌÜ©ö¦™ µ5zQžæß¯ ‚@CŠ9|Å=úu X3jN†7°êv—JÇÞ' Ä åD™‹pëŽê¼yÈ2’;“¹`$@# Pp² ze5Aj€²h¯fAzhêæ•bÞU|}žã¤ÓHBùÕ©¹oýô6žF=a7³qð~ˆg"4Ä.L‚vº°-ìfzÜýO'¼âå<ÜÉÌSô³}ÇCáÅ7WÁºGÛ£ž¥ÄxhòHˆ '–‹Âà=“Åz Éà¡X.Ü£Úñ ¸ Z«\ï‡35²¯)'&zј+(*ž#R#ÜïK¶›1ÿ„P‡^áaÄ×i?‘ÕG”S|±‡¼áº:«õ^*ÐùvY-»dÚôWÈn…F¢dj_-:QTr!â&ÆâÚãÑtå‡,`õúMÂ~/ÉQ×Õ¦™ç´Ö‹5‚‚Ðé|ÓÍXÐáîvlhïÛd%ú*ê­.Û¾2€wñdmsǸGË–´déQ¤ñ”Á6Ü}Ç”;Th7>ðo‡%&—˜²' CóyÍ‚`|(í<+m”4´³@‡ÚO›Jƒ7c6üP­#­‚PTf-‰„‚klÓ(ÉW¦=Avb„@„/•Ò4{í©çÞ“Bë«ÍŒ! ÕwiáØBJX,«ÑÖŸI=,9€ÒIÈöÁš]£•š.VúØg„\üTçghlÀcG¯Å«äY•cuöút*%Ò»'í–lΑU»0{‘”ÏyF°±ð·ãs ë)qBi"Eƒnˆ0È+÷¬È&Ø‘ƒbfÑkEÚ6»W3¾¡@þ°Ñ‹2m¸Áï«„: k¬v­?µ—7~IÐ}˜¸qÑq±Ó 4H$9Lüü¬w{PWÏpÑØ]aû ²…!‰6v=Ij¦pâÂŒ/õT&y»ÙK {äô¡Á/CõµÑ³m[z³ýt½x l3´Ü¿ÓO*k‰ þªºÞ–ÎÜ«m²yþìdÊ#ÿ<êÐÎúA™ÃgÎ ``Î0¯ ¶'ûŒ|0frŠï§yÉXþ®Çár®aب0“ÍÍHcö °Y¦QG^Ä)hb šÃ44N B°è‡ö ÓívÈ©±‡ø@Ѿþ.'›|/uâ´­ þ>×£ÎúæGX•k¤«!DaV·JjqŽõi¾¬ÐUÌ\–BݶVçsJá Œ Þ‚(@]ZmO½|>•Ï"q$Š_z‚Pç¸7“ü­­yò©5€²þ¡kS½ˆIIuK«¨ú¹¶ a9=?q™]yÎÖÞœp—\Ép$#L¬#<¼ül›«…-Š?.`R£w¡ÅÆ8ë,YÊ·kl—> ðS~–Npñ-2K —)‹½‹wF¹%]^jë¡ûoé´äÈ 0Ð|;ÓDS7W×TûÝ[~¼ž aÅàÚÙœ#£<'Æêí»Ùý0&>ãï£ï=Œ—K)ªçIø‘sV™¦/8,Däiætö«¯¦Ãí"ß°`Ê1qAÊàäÈ£æ]1›á·žn«Èq>[ñ¯Â¦˜×Ò"€SÌÊÔòÙ;“+ÕZ÷åNÖµY¯iRaê— 8ÄÂ|NàvÞh¿¼Û”j5£ÊøA]x!¡ #£¦Ð4•Û!’›â+Áªûû2¿ˆœÁèË)h lȳD®¶’GFeÛyC–óÿ\‰QcçZ4O¡p»7NÒà£Ð+ “ƒži÷áÀ6Æ#]: gŒÿ˜_ìòº“=½u°Æ…H»ô€’ý+>#@Óç ±;oDŸÁQê …Êòsaî| ü*NÂýŸ9k‘ܯ“PC#|›£—#/7ó±·Ï¼l’ ¬¢MöjôEJp)¯œãZr8©“¼V¥¸×¾ CÎî4ǃ7CX€g ¯Œ@DÀZ`x…/ø²?ë«3¸’Q—ø£ö -Dù L„L?x­œ Ã×@É5Œi‹ ºÓŽÙI ln7 $sÌsþë 1§…í%Ù6àÆ©É~c\“Ëb$ã2q³¿ jVQ¥gO‰Aé3†^ ø¢Ëq_îK9*„œ Î>ü𓧨íó9Ÿ ¸ƒ^ÍyÿŸHïËWEÎñ¤e`í+?Wˤõ$X±âxNDÛiãZÆõˆÈðГ@ƒùëîüÿ Úe+S“Ñ,N‰ñ»"z·Ö†QB‹A hIw1T”Süä ’¾VHu—‘OTž==@ãÛ)Bm²5±7ùò螄שÜv=]j³[ƔƖïãRk­ó$~ªçc°/%y GÇ÷$Lþ#UB‚‚"] êdsJút¾Ò±‡ï&Ù>¡0ƒtXìÿÛª6·Lîu²Ž‘¦ñBCò{„k: dºYé»úÞ•ã=&J»‚þâGÞJ¶è +*uãåÞŸUtÆЦB—°‰r2^âEgî h'9azIíÁðD’hoFËš#ÙÃR;6Òâ,U îî]ƒS‰®sëv7$à8r…ícgÉ:+ÃáMΟ¶2ª=AŒeQÑÙ!-oV÷‘®rÊ¥œRß®Rµ7ò%uêœ?z28<˯<ª™‹ÉªW𫙘rSjF§ÚÛ?™DgâõleÞ‘¢P½lIÉceq¼q&>. GQÍ$g… t6 )Ûi)<ž#¨, ^àœB2Aô¯,²O™Ø*¯*1œ§ãðUFƒÊr0Ú%®‚§š€’‚2VÌ­ú7ÄÁ ÀŽA:D¥°øUWLH×µu]ØìÀÄs߸i ½maÌOÃwÄÈŽ'l~¬Ä7-åhpù¬s_j·¥ JUK úr ÞëÌ}¶ë­ù¦Û°)û(h €³'#PÔ…ÿÚç / ‘Ú%¿1êÒz3¹’œ³þyIÕòß÷Öa&cÝg‘ÓY ;湺ðq©b¹-aÃuzLŠÜŸ;êcVJ›—™¶ˆE¹`¯_ت0„`'ÉÒèß(¦ªàGÜÃ[ª/¡ˆ»-0ó×p’`é‡ä Ù¡¦ûF÷Œ˜?ÆAp-—L´1-¶%ÞоøPwÁ]u´~Û¯Êu¾ùpÑr’àÒYùQ1Ëà>&9ñEßÊ[·õœÝ«Š Ì}Ί‚ ÂßBî(”àba«|2n~€´¹ŸÍÝ­ö?™àÁP²V»²Ø:N&¬nü´Ð¢i­Tp`F~mÅÀÀB@hÜrÇ–è8‡È, ÊXþsí»_4íÅÝÃ1‘Çè«ÈÙÁŽñÅîi(Vv­uΘIyÂ’C å7 ªÀÕ5Úâz„¶šŒXáKËG™8)ÔõJ?íA5ÑnþlE[5‹ Ðó2*º[#ä=.mȈˆM×¼ ™y#\;%€²®vb&.»bŒÚr‹þ›íïg Õû©ÔÉu£úaÿžýyü•}9²&ŸÛdË´‡WöUN^C¸uî$¨ávV å5MDð9góR½)»PæláÜB;oТÅÊë‹'Sέ÷gIYM¼á…•RÃ/¦ĮƒŠo &z,·2KÝ´8<ýÄÜY;*tµÏ‘NóíT³5[E7¤«F¡ëÒÛJ2ŠÅr¼T­³bÓNJpV»~ÕÙ+»ÿ:;å;7‹B¨:.ª°Ð¸ H^(æp~…­WÑŸ ڳѺ¬`ÓEF @}~èqJP+x³èZzõÁ¶Å7ä›@nNªÁ m8Ì“S”X°‹Ã)“¤‘à nܹTŒà ßå¶³„JôËš¨õõô’XÃ5EjˆT…Ìì…HráÔGHI Ï^»3eÀp-(ÇÆ·>’~o›I¶•hÐXC&¸¢üJ©47¯åÚ|™JÆ¡7ÿqI„qCúÍÿ¦LŒ®ùÀM‡h Å‚n¬€3æ¯LÙ£‰µl°ÂæÉŠé³Î0%¦cäùëÑ5^¯Ï¡øÅ‘ |‡BG”V ¹`r[“ƒ·û‡ï2Á¾n¤,báF"ÕŠ¬’»U0þõíqt;¼»ðí”Ì»–‹6/á`]·®n‹+'‹$¦rÛ¦xe¦—ÿÀ¡›ÍÛjSÄðt9ø0è7ÊèÄ …t^½} ¹ãrµñY"¨KÌ")xºâ^zT¤áÛ6Øâs4ŒÝv§ö­H´BE\m:%7Ëßï(.̬P|(/ªb’R}\-¨¸ŠâÁã´ð×™kpÝ/Ew8Òf™æ#G4‡UÂÖ¾(I êuÔͲ?ꇀÜ:â`¦‹b¤Ä¹ä¼S˜¿üq³Å²§.ŸŽ o÷ê1»±]-UlÇ'Ü] NX[«šl!-Aa£ª>_ŽÕOqZŠ`R÷k³Aç·¯µÓfÔUF „ñ´™l™X¬èEÑSAÍTÒ Ž¡¿åY±Ex7òçÊýVˆE–Á¼¯Ÿ€E{Ç edïÅþj—•Òìl.¤°ñ釯ïÍ’šË 1¬…€åO¹a…J]}ÞN8j§G*Ïêú'ë¡L¶dM›!ž´÷ÔoYBˆaóÍé\Q‚-8‰7ÑT/oÊ'•(jë „Ò·ôÙ3ÄÇ$',Uá5§«û®Ù A_;OƒgaNà§a6KN†¤¦Ì¹n÷¡qAw [ýknW8Mþ‹Q8ÌË쌽rüþgH[ääJ rØï”› «SJ³— Wì@ÙÀ뻩nkE±ô&Èúr;¢7»‰}®y9kï±ïÒ<Ý6A³~¢:ž´g³ìc5Þ;§ìÃR#º*³U­_ ‹oÌbéó+OpUš· íÈvüþ37DÖÞ¼d´P!?.m ¬¦ïFB¼»³ö²¿Y+ô´L×°`ŒRÑ4„k|9ÑÁ§cxÄ¢¡ÂJ~Fà*«ØN¥±ªGÄÛ#›žøI•¹åäUPù¾èÎcÄõÏŸÀfIg#Wáû¾ÌPã7=ÇêÙ)ò-sõÜê^šæ~4vUŸ«ž(æÀ}ŒÉxDew/Ƹ,õ½÷ô<%™WCÊhû¨Ò**¬OŠVÍÖ“™ŠÈ®Ð½REãܵUäi”›@õI@µ°~(¬îõ…Æ”óODˆ5óÊÿ?N,Ù$ÈnëÕ º§ ™çC]Œ‰~"ÎBi÷žT×[³¦ca £¦m½ÿ=÷ë  é$@õ–æÜOyÅÖñÖt¿s…i¶êˆø3o†žPå> „EH%¹‰Zuøòö¨E °ÀÈ»¥„h?‘ó® ÂE •̀…/p~þËù4‹¡Y‰8ßrçøïƒº) O×É¡»TT¢… ½Ã£áC šRÑš¥ªr¶öÌû Žô~…þÙ½|ã4ºáWìM…Ä7Âö1#ü8î…;GST -<—ÙGú«ÒÓãÿC É)t!d«£ Ï»ŽV @ h~ÍØ=Ërç1+Vÿ‡W´¢* ÿEzé[\c÷ý“™Ên¶Ý&£ŠÑØUÕÀÇ$@O ž 7ÛÁDhÞºv Ÿ•>äRûA¿p–‡ãSoÛp÷q rí&tºpqOɳ¶)2zI±Öe+ÔÀ§,eq>ÛáÕ<ª+yH{éèÕI­0ÎÆ^C-O«Ó„½ó1±*_˜Úß+…™óCs']Æg—`TÆ{òk[˜ \ O: .4¤úò;d¿.hA]«äÅÕŒUZXùâ "=C _Àé¶-Ðî¬Ad8•Ç“¹•u>ûòœ ûÎ2²5 ÇŠ­JZ#{Ž Á¸=um¶Ê-Ñ7eXCò3Ì#¸ņ „?¦å?mvÎGX‡ˆA¨WV´ÙÖÁÂD«ç\lS&½ zzY8VvkV<:Ñ$:ôIfVÑCÌ󨚥iÿ¤ÔnÊI`«hO­ÂÜ™v–R_‰a_4k–óóoÿyÇóÍéRWZ!O& ù PkT|üLÿÓÓ0?yg—³ ÙHÛkæ@Ù£Ó¨†JÁ¿¸‹"Ò“P°+´ÂÿšÐhôÕ¬÷€-žÕ:C@ªGy~* dÊox‚§ÃAì'¨Át_|·ôáDHÕi<]¾§ŠÉPƒM¶¡a_«R´ÓFüo¡A`ÏumÄ—ñ)’‰€ØÁ¹õž$³†Ç÷D[°4²Ð—Ê¡¨©lžV»^ھ肢ôA½ºF ÞB]Å›­€ôæ6,l¾…;‰€³ëÞôD&x3‹.ä$ë¢ók»Íž1ˆý†)èÒ¼‚»Ã›ÑÀrøÉüÔ­taº©:ðGÉøŽãÓXIâ;Í$b,Üéþ B[@Í¡M0ç“(ú«7ÎÑV/71b½Ó;õÿ"Mà¬îAæør´Må%Î4eßbH Ã?mßG±®Ô«º•Ú2ƒJ]Y7‚ÔÅžsÌ„Œ³9mõåÓ+"N,ûq˜ŒJÂë¤_!±ÛºÜz|~ÉL¦ OÉ9Ï m^.0ÊíR,´«Øò0´âç/Ooò»ôt`Éò q éãÚ"›d•pššã³•ÝH`E¨|òôJ@é’£‘c¥°¥j;:Ü¢+lvØrIˆêÌ^š0½ÙÏ/ÌÊ®μ7¤i4Þò »ü¥Œ 73QÜC ƒÇí³ ©xüw·ß…Á@½Ô»Æ xøAc÷ £GÁn4€ýlÂ^¯ÞìÂêîģ±aŒôËqw^iàÝü9˜Žt5½_aqSa‰r*i+=5ù͉%ÉžÀëa]´Êâï ¡­£~M|Ï"'Àw¦»24ÆÔjï¥jdᵃB`S{ /Q¬Šéy'n(‚õþ2‘\öbýªœ¯f£IÓ[¸„×ê€kåà€À×d…ĬS¾B67¯‹„žhº˜[°xy{òXibæ¥%vY#ŽH…C‰Cú½Íµ—zŠ¢• ²cH×¢`Ön`ž äO¤êE9`8Å‚µZ8  Ò7-?x¬`ú$¸„RõÎDb§»öÑbrÈ÷òÁ9Y Ñôm^`]äCñ½?,Ɖø±„ÂìýâÞKQ9D¹Z0ÑÅ3õ³C¿-2CYrá4ÌÜ#,µ5…î g°YZ‘裣?’œ0lëK0ŽàGgØ_[× ¦âPߢ›àŽÇµ×"\„–ÆE—µ° ñf÷§­Ð,Ô±0_…xÛ3-û\€vvFØIîð¯ÀtŠtUZÐy^ÆD¨¡¬%¿½qłϠ¬´¯‘p$9D.‰Ë»(ÆbìÑæ†1GO¥ˆY+,½S.SiŒþÈ×5#+V¬VÚ(/ÑÐÇv†6¿Õ/æB²DêŸðô¡ëÐ:Ö[5|•_ÇO†’™]ôoš9åßÉ+e<-ÌrµÐW1é~Sé±­ÆOÖòaS{¨~ûüW‰¶ƒÜ·äýÚ4clZó½—ïªýýÁ‡]"jÌý`c’F9hô»ïß—¨¢ÛuB[Éçò-ÀSK—|¸¯Ãtqª‡=[aB™\j$3ëøœ†;æ#ú=œDí–çé ¬ÁÕö¹<±i×P¥ï‘‘ûyÎÆð;0Àq½ïÂëD¦Á\Ü+d„y6¡÷uÙ+»ór3[BðfÚ6pBt…“—Œdž %‹«vß |H¾ª§G1ž^òJì” ¼‰cô„fcþ"E:d"¨å]n»Ç÷SÝÝ¡ ¢4xª/é#²í™îZá„5‹ÝÆÓóW•Û" ü¾|£²¶*u-æxì_w£ÑÃ^ мQE©ô4XKŒ¨4Á³;Ƶ­«­“àßÚÿ£›”šÕ“ªÜÍbƒGC¼cÆÿÙ†«3c&ÉŸxæñ£Òç{¦ñƒ‚y„ÎRʲ8Ul¶2\æ |çFJ…÷â€p¢ úÔsj'® {2:iqRÔ)dµ·tÅfTH?”Ú¡‚æv›þ3«„¥1Rp™¼_ßïG±oÕê`¹cÉ2ßYðÝ!À+í# ˆIÔHë'kø ‰^|+®}·ó/z¨œ=ò €-ãØJìd‡@!ïÍ:˜0Š ÎºqÃMÿú¹Eò ÉÔ¾f„Ø$—LCÏ”nÖý°A€í< ¨£RñÙ(IÚÆtkÁùž˜;©÷»HœB×ïW1&e«=ªdïÀ6¯n:ZÆ{ë—=8ìY²Žoe7îÕâ¬w¾óÍ"üi8Ðh6Ni˜W®ãBpîaƒn›ê˜"RT#³øN~¶c?»é8Ãß>m]ú7êè.›^¶/:Ät®ú®Ú"TÐÐ8wH0ð/~Ķ»öÅmL!2ý‹œgâ:â~u /´×,+Gh×¢5WùtˆFÖL®Ãš«ø-*U|ý5£‹ìâ?xo]µˆƒøS0Ë\Ù ŠëÃL"LéÐ}Öˆú¯T-ªó¼ƒé–;’áÄß™–7'WzL×É:i*:Š-f8Ѝµ¥Lˆ!&Óû/” šý¨¡*|Œ:¾ë›}æ­Ú„p×”:Îè¨w)û¦QVq g¯Õp†°YjÜö«Ö( Z·"·=þÁ ê-«kÅŠë!…´Q—]ɉ3W±ŠXúSYh·”ž+щ÷Ô“²¦µgéÏŸî¢/‡OŽWÇþÒ­¨¢aÂÆOM±‘ó¥´DÖøÎñ‚càÏ„‘â‚%ÿŠC¨%=»L_€í¡2@Ïå(^ɵö¸”!Úã¶Mwš(0—ƒCã›@8ÄØª‰Ç Ôþ:ø‡KyDÖu.äò"@ŒýíŸÝåi﨧+)wÿp¹Y­üâPG.õ·! ƒ¥Aψ¯¿?R‘õHPS1'+×/û×4¡§Ë³ Sh—CÇM»|€aºÖ£’ïßw1< ï$½E=_ Äò¤ÅÕæ/ñJq‚vœ-ó¢!Ë Té>6wÞbl熆Üàð“ÓNõê'þµ¤Ð¢4Œs{Ô?þñc{WW=cqhw\ïq9ê'äÿ!4À¦àâ°Ó—}”‚Dèæ„øf½jå”â¦é]ÿD_ò½¥€(þ7ZaL4»µxÞn68N5<(¯5 É…´W Ü´?ùŠ É2šÍ’û N[ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿŒoxã±Æõ¾Ç.ð%’}‡¹väðy^¼zwwVÁ í±µ1ɯ,¨àz (:Ðzß`Ù Ól.°}°øã€"Þ.ø;€ ç…ð$À muß0ñ=åv›Ýéë¯woy²o`qì» UãÛEƒ ŒÈpkâ¡@ @ÈÀˆ}•±˜HP|s |<£ÝxO©è^GfJ)E)%/wÉôqëà(Z÷·'`^MЦë¸uÀ8Ýp7N§ÆÙ€6` îñõmÃà(ND>j‡§8å€Y` @60œîfÌ’'Ï«ÖÎ>¾‡1;@Ü r$‰"H’$’o}›»ì|ùÀrI$‘"I$Þ}w×À(|÷€ôw€r$’I$’ÙÑ}×ÏŸ ÏŽä’EQ¦M7¾¾ûÏ€pXœ”ÓJ4Ò—ÈÀPûϸžJi“F”Ó{æpæéF”¦ŠiKÏ  çÜ÷¾ºx­ÔÁÐèÕhÝ€Óà™>œI"¦€Z­°p /XVɨÀ   Œ(d¥ÁÚÏ;¸×.=ÍЪ¡ëܬ†ÔÀ¡Ì`ÍàÚCÜ žÀ´À/föŒ>áë·Ð>ïnVaá<Á=u>° ¶V#dm}ÖÇP‚n¸s@[™¾™¯l;³³z['ik»®MÎzåÌv µÑÍÚ\ZÞ™Ò Uò¹Â½î‹zjr*Á­:ÁÓXjÔòsÞíÝÛ6Rw]ªÐ+˜ÚíCèyØÒZ·¹ëECµÛÀº¯#ÈwM‹Aw;´ÎÕÝ9ÆhíÔçY•ŽÝz›³‚9=Ù®…¶]Z¸âE{Ü‘]ë–Û›¬ìÚ²Ù½·jö *4†5ÜâìÆlËvÞ½yzêÍ@¬±Y³»ƒ`ÚæîS¸ïOÖ7»MÍÖ¬³^wotä€h),ÕZÀaÜûeݧ4Åçp   ¤Í‹Oî¶ävÖ6%½ÝïEr½[„9r{¹ÀMm¹ÙÊÀêWnÊv ëäлW­[K^;Ý]}}À}i¹°÷3´/ll Ô·,àj"ša0Lš4ɦM4 €41†¦†@h4ÓMA¦†šhÐÓC@&ƒPýT¢Hˆ)éTõ ^Ö*§ÁÚµ—tåRæ¾ÚONÙ—&…‹÷­(m0¦¡ëÐ?¶á‘–6¥FÆ7%B sÖû¤÷ ŠH¡sAžrõ„ÓW&ð®l†ææ‚%xç·ÿŸýº×ÿ×óŽþ?_°å|§0R”  ÃeÌ! !IG@s Üšœ“ÃË)ä1¶)jû£Ýã†s“‘Ü7wÕÃÞ/§‹½¯$Òã;û2‡Kd2¢„Ì´×UÓ¿=cøjpâU©v?Ñ-÷–qþ$‹+Z”ü[œÒ˜BI¦šR”à )b B `€+"6Ðÿ¹þ§KqþêE·$0=ê¼ñÖþ'uãÝ^£ÃºèL^xë“ÎÖÖåµx×wk®îF%VžMvÚ–¿·{í|žÉ’aEü(üçºúTûȇ*(úØÍïà±: ÿx*‡Ãˆø0Gû?.©é8vFî϶ö¿—o¿>4þ‚‡6ØŸÝÒ"У?&ý‰=‚>“ìÿúwü¯ìu3TÍkéßø]q·3VÜb_=ää¼ß'yÝsœœ˜æûŽó—ÖõœLóZî9®å—Zá]kõ¹­f)ªC[”âîq©¹xÊÞÂØÞ_|»²öøýJ©ø×|¸;‰?#¾Õï¿køð?w¯§_–÷3&BÇ&xX Ø ŒéÝç.·loZ®d}¡hg[­Xñ˜ã™Y’[–qK§67©8‘³‡8z®ëN\•®S$vÚÙ–æX1MQ /¿ì€ã¶>.až^3¬{YçmÜãzæw©ŽóSró}˜Ö5|fk²üœßyÞï]ÎûÍß=¾·ÜêwvÆó¹®ë·Æ³9ÎiÛ›´88Î8¯SÇ¢j/[@ g_b ò,d±zyê(ŸyMÈ}õ{[êMoãÇ€|X^yH…Tí请wú¬ý\þ‡ý×"Bgúœï™p}XªöDø0?Sôëàg)êbR ‘Aå•ëÑb$ü @CÆ,s!ëgY:x| ÅÈçÚˆþ¤Û…•ÍUßÄöÓÓÇö'Ë›_N–Ð<¸?îvV´ÿ´? æÃÿ ~ß½ý[>ÇøkùÈvÝ媇­Ž̓úFôùð½ó«ÒDý¨‚i÷¾&Ïßoû+¾”<¿ì£ÖÏð}*~?É®dè:êüIëæ÷ïÑçg¹Æ‡¹Ÿù‰æDPþ2‡Gàd†ÎGo£z!.Ÿ9–ÜoÊù7º—Îß¼mŸÔò Ò’˜¤&ü¤ FRN”ƒµý2åøÄ‡ŒÂ°Ñ¡½n@ùä¸û Ucãø¢eÁGI¢} ÂP_-$mJ¦`ðÑ4™0ÐÑ1Õª{9ðׯÔ#uãDRÊÙuWP@ÜèuRÉŸìïTqùî¯èqP½rÿV,Íê\ª¿[8 ;¼ÎGæÎ\Ý$2±S}e]çÁ; „cr0‚< PP ´ F†g;`nSîüš…´ò1Âp0šóÞ8-לç0ýo‘( ûÅ0r·ñÿp¾Q§í—¶™®‚~ÏÙ‡µ™“äZsy® GØÙ-“S©ä=1ÔMͽ©fç–Ï®Ïwãª% ByJR”¤!J@PP5:´¢ÅG=p×?¼ïS™æl~oêzF.ÓüîšØRvŠš)A R”µEt &ï1v¡›§”žãp¬Ñ¤­·á.c¤‚z<æ„ ÅåŒq 0¬æÞgØÙä'ª>+Øvåõã)xt˜{m~±×/÷ÀPÃùýk^)sŒ­9¨L>{Ín‹Wqåʬò=9qr}žc·g1‡†0†”¦ÂÔsTÕÔðwÝow«#“â¶Î¯y”ž i $J×^4l¶çõD¢ŽWÍú‰8õ]OG.“+ßòýx?‹¾²ÿÏüR‹ëh”ë¢j±žÙÌåd¶Yz‰³§Ù»:44ýÏjýŒ»ÍyuY„kõ]º”[³Ù@ôõzr8æ~N­’Õ*ÓúÑçE%cú½U®ð.¥²WucLÚ%³©u¸KϽ+ÑÚ¿‰Æ[kuøüðcàÁâ"cñ0.:öÝŽ™D‡J@¿_.i.Ê-§ü:³„6íšJÆ/®R»ÁGøxËÉ&©¥-søaôyôÂŽ¦ã¹PÃí³¸RÓ¨o·v–Ù¯øògÙ[½s|ÉñöTÁüN_ÙO6xýþsÖß#αڦ]Sê98ˆk_¦áª7M8Òä7!ߨÙ<ýŽzs†VRÆj2×ßǺd®SBÒiøì÷DìN¯KØ¡‘Áøê‘÷ôÊ͈ÉìÁóå(Ér3Qæ@íAãºyxtPn”‘´ Ó¬;€“`”u€Àc8 #$~ÌŸÅúõ"½ M/ïD ›†l7gOÀ²õùq|mS‹öò§«²Ç?5D½úîUù?ƒ>Ù*¬ò‘ï }"%‰¬,uƒ‚Oµõ?ðÕÂsœ£¨†I¹°kzp\È87s¸ükw¬x B‚& MM®÷n|6N˜x½.¾ôÿïD:¯Eý£ðQ߇dßOÅG›Òd¼°} ¼€ÜF} ÿ1—ÐcûØÒXÔ2LÜn^š¶mk&\¹‡P7Rà!é›`‰CØ~+”bb®_6Žt¡,¤NÌ%š†ÚžpÀ| ‡ÄŸÍñwØa~ÄoÔ­}k]òx@£ó¸™p›45 U $/”‰i! ®8¸µüï?¯Ùiø8‹ â{ž{ úüŽMü¬x;¡ÿ½æ§¼™ü)¼¼]­›TÓù©· ïÃøPoâ ³=½QoöîyG¥7Á®„éG_XylÕ!å1je¢£³E¨Cv;’ WѸ±ñ.UAÝAb"$áH<ÍI¯²ìHäGÛ—¹=Ÿ*VÞ®ýßÃuûmƒ:rv¯ð¡ðëÇ„ˆÝ¶Û–6q•&¶Bê[ )ÿâÂ)a½ø€Ãr†‡#”< Ùqh±.…Ô€ Œ[ Éçú`¡y¨ª0U ¨j-QKRS.Å´UÊ5vŒÚÖm­oÌÀ3ŒBÕ_ÓrþÜÛ`±`‚Ñ RÏšþçùõ&ËÎ\K=&wø^Sß•›ÄE¾‡Ûñ¢`Ë·Ï겟3-Zœw°pŽÊñÙ¶.Ö,-{ã•–¥–[&PŒaÛ_vÍžšZ]›Æ×œXa™ŒÒ!dÔÛ8=!F2ÑãQ?„=ûÒ>Óm®¸ELp­Ú0"„þøˆTb€®´ÂTµª@ €*<)gK©'ÿ ["°•ë:Ó•½ß•¯Ú·Ùx¨Obo÷bé`¾SìÞW¹5^ÝŽÑBHL„Ì RÙÙÓ+hý“•)Xÿ*ÐÛ?öíÒ\;xÁ¯ÕâÝžÛ¥>{„æú§[>{›l߃Æ_ªÞø<¿‡oHî뜣Sý­˜Æw¶šÙ Dí§¢–uÝJK«à‹:Bß¾ÚCXÓ,åÛðU¬‘Ñ“öŒ$ )ë<¡“žÂ¨5*áÏ0€‚ˆô1I@ˆ(¨´k4jª¯ºû©Ûï>P÷àÿÃðzå‡*¹š°ÀÿYÀ%S”=¬‡Ò~ÞP‘÷š]D”c\؉Ɉ¾ãÈÏ·¢3ÜèÙ› 5’s¢Ñ›±š4ÓºÓçfcÁÇ“­§W3'Á~™™"@…ŠNó)Í!2LNCˆq2P X\bˆa‘m‘¤‘#i`1 Ô–æZ<0L`&–ÄØîf¤ölùb!î¯ñ>Þ4Í%á¦þ¼œéœ¸æ5Ö ùíÆÔ¢Çà0ƒé ÂL{m¤~‚º=bø•W­æ3>]ëÐC4 _¹^]¬oÙ7•Û¡¯õ•åÐÆ÷fù¹t„dùuNÖ¸p¸BHSL&HI6 ñC«“Õõîvøe«±ï&€™†^ Êe†&£Áxø¯]Šï®-Ô“*›HA2s!˜pÈfW_(1îCb6º§B:&h;¸nËcVÚݳõšÌÉðt4’ÕJ +èËû¾üãÙòê Oó¬Â*æ`ýVq›z-é㬬¹Ã?HZCrƒ"N~wü}!ïMøÃèÆÏ?Ü@‚Çq|;û=ãfë#¹î»|`Öuú ÍÎXüÖ²põ#çä_—²GÌ%VLvêbD({»S ìG¼úÑýÌá¹4VŽrä9²'ÆCÂÝÇPm<›™`TùFÌq¿… QÁ´ÃMl=É@Ó'b¨Uf]í­3•°Ú?Zr€KoIâI5\HJhïF)´F|¬ùÓ+3Άµg«í¼ÛdÍCý7Û¤°¿d»ÑDpLÞµTO§MöÉÒw± ·`úQŒ¥gÚ]©¤z M %Fü øKåYtWCð=ÍÔ†=I˜s';W#/9ÆßíÜî^…¹jä —“cçæœ[>ðúŠù`ä#¢q™^ãV÷gN™›æ"æCN·–wrÝkN©­AÙooªCkÀ‡£çJ¾o§c‘XctöHá®\é·ºS;uŽVÂèýH4¾÷äËab—×Íï{dãwo¾Ül2ªÓ^.ª Š#{¶ül±ÇÛxÏZ³:oóµ[T ×çNÁÇñÍ[Ì ífqޤ—z¡ƒc7í¸vèUh=xÜg+»à1÷ý´ÁzäZ¬(D¡®|¾Ø¥þy)Ú竦eZ(*w ÎïÑÊSºÜ3Þ¾Ëu¯o:Ô0¸y„{Û׎Å1õË»²8ßáYö\Ò>ŸL”þ"øt'Z,÷v9ìqïlž¶w4¥ÛPKˆàKƒHú‹ßð_Çë5péܧõ2“ g·±Æb× º¸Cit¢”¤V’õsÚî‰ì`ó÷ú™ž/ãÌÝÌJžœÍ´ÜÜÑzs¤+ÒÙ ñ«|ÏÝœùš;áéâüºØÖ$yé$/ ‹/qóÀF¦°¶Ðè\äåVr)7®Ë©›¸Ý—ʯ"p“áÅÿ±2¶«iÌŸÔ~ß3—³7…ïTÃã01=^²?¦–Ïùãøò>}S£gî%­ÄF_ûK¢×8´Åuà]=CÝUY¼#÷üì–Óš¸ƒ­Èhe‡Ã+ïõ~“^eж¥ÝšŸ}ãú*?5=Ößyû•®VñPU:pµK ÜgÍúrϦ¦˜£»÷Ýy¸0ˆa“q½4õùhå?²yÊ& îÓƒÂö°½”_ù¶Â×-ŠÃ¡"FGúŠßØã¢åþ©šºŽ[ß9’œ}¤KR§> 3¿ç„O`Òm-Ußaåóq°µ~[5,ާŸÖ7yåG¬o©¿!7‹ýÿU9l˨°*x{ʹS}­í´XÍßåÿäbÖ­‘–oÉ—åFiDfË9–ü·Ô:"ÿ›XÜ»Zl×%SÕ+£…SK}VùÊX8m_®/2¼ÕÅtÝÒœ§áb;[N ßhŽOÅè†|B8ï­|V*ˆ ÆÙ½‚zÕØde×üõÚWØé%]¯úI×ïb¼™U”Kt˜LËj¢8ªhØ£CÚ¦%›ÁŠr˜RìžÞr0ÊOòÉÖ¶¢]® ÚËü\âWÉM¡wcvÓbËù=³ª~ØæyÜöeÿÊ’]ýW`sãY&窘œj§jo7¬—–f €pì Îèç&;ÉR}XÔ ”™º­^cy-ys*ó“ˆkM„‚ªp‹Z‚¤øp¬'Üù]®¯8ï»Öý ÑàÌãõÔшg4pøÖo>MÁçó¬­¿Áxý³{½£Û&†Â†oáΪºg?'¡'ö[,úú>ï¿¿üw§@Ì»á¤ês˜Q^NPªô ³XÇñû2*÷–.4_Š!.U6›þèÅ/Áöª§ª ïåàI¼éêÛ—*“´yÚƒÕ6Í27˜m¥þ&±Ëã'Çd½‰êýÔS¼˜t¡ÜÓ*£Ìj™tïÛd޶n[íjU­=)_¢ëD/G·E ì“}4…‹Ú!äxT¨š&M ¿3½€®xGëYíøÐÖ¼ügdY«ñºßöÆB Žë0‹ÛúÄA0òoèÓàt3–8Sù IÑß. Ù.—óϬÐýÕQGL=“#ÃŒm\ª—÷j:¦Hrs?LGÎ’_#KAäýcx<Í"úè±-Ï tðãG Á§Ó¬Õèè2ßì¾Iñ—ºtNÀ©ü¥]XÞü}žÞϯÞÌòÂèÌՠβ,׿á)÷'º!à{ïožhd7æÊùÇ7ÆùDo}„Ï®“£óðiþ1ÔM$%auO<×îA*Î}ÓD¥iª“kn¹CõË™ÌÐÙ§Ñ2Õ/e¾cã³_'«éù‡¥ô72:ú:mWÙ';}?ò»|­¾SÞg9rUnÖ)Ï»¤REƒ¶~zåoù ̽Úó ìoŒ2Ù¥ãU«ðÿ,ò6ÕºöìcOÇ©SrËňåxYHÜR Ç¥ö@·¥@f3Y¦²ƒv£Òêø‡]vÞ·üôé”x…~Oz½´€„ÃåÁ»?n(Ÿ¨$CëT!<¯¼÷]oßÕç`7!ç„´fZ!NRU“-¹ïÓ ‹¨(8u(Òt 6|üƒVâÍ]û4€SÓѺ0òH ü(DEWx¨vmóÌ?n^Öò«­‘™Gì÷OЇšÂÏó¥Á#Wkq8ߪ½—|>úC¤Œƒ$ͯóš pxˆ¢hl…Þ¢ä‚hmãP f°*Àu1 (Iò‘i´ÍŒ€´QVÝöÿBË(Ó>ñ|"8ÈfHBBB"9þÜQjÑhÕr|?B˜”~bŠ7!$B‘ÃücX|˜šüELCCõ¤‘°ÿ—åoRZ$°J¿Èõó×ü.«ú‚¾4–¡´8o´¹¨ÄÙÏdFè¤"¥ha¿¿†™¦ÿâÊ5/ëÀaŸAE=bDþZŽˆÓJDz¦Aøøiiᦤ—Î46| ƒqç ÖJuˆI²vc›š¦jDq±xÿ¯‰YÖÇ1§Z:ÂÂùám·ù<$¿œ?›áïµ4ü”Í.ŠÚ%ðqa|sÀ·„Õ€ìvñ©èÙÿîµgâÿ¯§#èG«²3ç.¬‰3a· 71Ã"Ùãg°qãÃÕ—G‹Âa.í¤÷”Ù| E>V´¿#WVùÓÙ·:åäº+–õý1Œ[úÍä‰Þ½Ïn\xçÏ?…Õêå¼ãRÛK¡³öu#޼sÙœ{çÿØÊþDprÛáfž%ÙN½H{?ðn¾ôYMï\κÏEžˆ/×ûOÅ•Ö#é`¼Ø|ÖçØç½~þ}ÌÌoøZŸwG…iŽ7©ÙLÀ–£1DÌ2ŒÐâÕu“#mið÷R?ÛÓšºß;ìéÌ{NK~EÇÊQøK¿Òcàîëׇd£œ<=Ÿ/Ü·³ÿgguþ¦³_c )ü$¶bðíÇ“^yP S¿ÓïŸbÏßÙºßìôëLÞ8{Æà¬Çø¯ðüCçxô2î†ùØ_èéóVR!í‡Ãð¼·¯~ƤHú{Óþgò$ÌÁò!˜>öªñÊ$7r»®uÛ®×)vBHàØä;‚¯ lßáþÉ.6űö¸Ñ=ûo“ÏtpïZYu·11 €B0’[oŠ[Ÿ]ÚÞY«$’[i))-µ¹kn•’ÉmTZŠÝ}/³æöÛ||m·êõàQ´Q¤ÚbX( O—°ÝçPn_,>n¸ØiÓ? øU¦b†ÉÀÉ¢•Tã­ ÿ2!²…$çb¼>ú¬É¶Ò˜×hOÑwóÕ`±LLÖ 8 ªf”]›œ߃™ÌÂßÚYl,f–/—.YJà0&Êúh²aÌ ”8¹œÌ+øé8—Xht³9øÙd/n Óe QÉdƾ¦Î†la>Üë0áuªCK'F$¾f_„5€Gꀖ¯É†-d¶ú˯·d/Fº¥¬h¨ˆ:bЇÕ-“5Op¤¾fÏ$éÇžb¼ÇLâ»n~¡ª4Oe(ó@v¯Ëïú5ÝѶ*ûÒDÙÛw¿¯v_'iU 1†sŒ<ÝzMkã–ŸãÑãôo…›`OÙ³Üs+'g¦–àü¦½¤aºÏyI3 d“ ¥‰ˆÙ¦²)dÑLb%JJQ%üûƾ¿Oן³ç.Ùn(<“ù¡¦ lÇk7bf‚ vV Xýð÷¹3»8Ü,sž$ÓsÆs‘X¼À 6ëÀF¨iFêu@Gý4n“\ÔûÎ×9*OÙý„OúÔƒ 'Gí'Šrod8z/ã üŸ/eZS޲÷ Ѩ '1"ÒXHF´æLÀoK_ ÕTPJa‚Éäô÷$¦óÇ•M© Ë´ !¤'£á|¡ `:‰"‰N«˜²¶ª…‘IhK&L¢êÊk šRVè›<Ýž.mÍl‹OÈëµÈ¢«_ßõŽ˜Ëux·é’37ªÔºú:‰Ä+­ÜâñïáßµÔßðíõ÷)D@¢("Тœã°,¢€`Ôí öoüû“”¢ZÀ0ßrp—¿ÓÚŸ:8Ž7]dkö~ΘRŠÎ¦m‹÷¸޼›ˆ ‹Ú-Àå»~Œ-6­ÄÉõÃ~º™€Ãq÷p¾´ºòóºpÜ7q øM ç¥ã‡}xÃpa 7ÕȆ»ÏùìÌÌP$^ogìó{9«Üžã>«~M×× cqøû{ÆÎxw>–öƒ¨I~ß2?U«¾¦¸¥Fa†¶c <{ß/F[<€a—)ÏWžóÃŽ½ýú‘o]Â*pa™ª{ ã¶èYå£íï#ëoÆÛ<ºáßÊRê‡.Xé£W†^åš©Ç|/Îȉ”Žú¯ å—žûÞ\'¾ºí& I´ÚJ”}†Î>ŸOd½;±!Šqg øqç@gÓÏÓú2ᦒðe×–Ü«ž:_ôÎØ¹‡ò¾µ÷z`3 WÃ6Õ>Å.p‚1™‰°–íÓ±:æpø¥ íÒºÅ÷¦+´æÛwl×ß;C¦'ŸlRîäJhuçì1ú  ;0¢0`A¤*A6©eŒ’l†ÉIR“If™$¤6I2RH €µ(Iª´’m²IBÉ%J A)PÔ†LšÓ4ˆÐa¥ÛH„’Ri$L¤,•’J”Û!´’Qµ“!¶4£6I)$Ó&¤ØJD’Dbhc,@ÚF"ˆ‚ce)& Y2i%ŒMdÒHm̈kd’Ô™K!IRH¦’ÉJ))$¤£RJ¤ª‚’ÊRM’ID´²²[IHÉ0š’XÊII$Ö¤ÒdÕ¬ˆŠ4¥Ù)4‰²T†’K&´–©2‚Š1¬(Á ´¢V“%dÚY´²JÒT¢T’l’kBmII“%©QI$ÖI2IRk$•¤M’Òm)&¶I,¶Õ™Z*´–±k6[EY4lÑ ”Ñ$ŒDf¤E2&ˆÉ$•’Ŷ(Ò¤’Œ”di23dDDcDDQk+&’Y% ‘¤‰&M%“i4‰&KIZ“fTÚhAm$I*Dj”2e “"H5›Yf²II2Щ¥Kb-’L³Y2H™-lš™"#6ɲUJ IDÖDÔ’²@šÚQbljÉ,ÖÉHÉ-ÒIVV¬7´„ºøo·y/G‚"g»®ý';§ûßí‹¿rGTˆG´¥Õ ñG±k¦ÉÄIŠõµàI¡m·ÛÂg´HÑØt>Óîja!†8ž{ê*­ Æ™=´ÌQ3-†éÕˆ7—ÿ>GËf€Äf`>`Ì3tn&Ì3´ïð8üE±‰#‰yÚrÝ”ZOåï‚èriÉŽ éjÔò6“¡E©[üblËìqúq<+ÈÁTJ<\>0}.À½ÙÓ Îóçå^ŸO÷žÈ³ ÇGgýîuWuÊ;WÂ:Oñú^ÌÆ·ÏlèÍë)»Ce÷Y§î. §ˆFOKbŽÉZ«ó+ ~ÇàÖ¹O°ŒKò O ±Fnò(G÷!zcL^­½Ó´Ws´™ߨïÒÃL.ùÙWR“ƒ*aøºJ¿^.ç^‘Ç´õù{á_ýsm\Ê›!=k䭲ݛý~®Ež6:¦JØk.s°î{6o)ÁíÄ€E9[ £|­€WÐä¡d¸†Ë®:3½"q9ÓŒ‹®™Ë³á…Q*Ø6[=ጳVC‡EY„’îu8i¦4¥èÓ©Û5äh}¸žûõwPÅZ­PßÛè3žY_îǧÜïߌâN•mþ³oËÛ™.ø2b”jäû3²Í_ì&ÆÉå6w„˜2·…^ò~]óµIz/·Ù§"›Òµô»7ÆéƪfÜ!ùN&,à:ICÂIôàzŃ`gц÷[&™šŽå˜FÍ]âÅÓBŒcIÒO‚¼‰/±ã |eœ8‹L5„¾ ÷ 2„$É“0]LçXò²:0KƧJû—d Xø¢7ÛåÕÙ¥úe• m²_fþAY}e…ÚS/WW‹OUh³°Ì[\ØÃ™0B†K‡(BÑg·ð!É»7JJ Ö"]D]÷5é $AK„—ª48¹ÌÛYñÏÚ^íL1$á83rîÇRœž»\Ë™û%Ç€“ñ‡¼þíLIþOuðÊy±¤Â_=b/ÏK»;Ýïv/LÎ[I™¼*·DKt9Foá (YW;]ÚÈñ­,¤ç8vyBWvz80eÏÜÙÞSnË¿h!öY@:3tnK³9O<·Áò.1/;ü‡-ÃÉÈß„·”&%¡É€8ABeš%òŠÖGÛÀUá¾bVíÚþöï>Ÿ:ëŽó°Ò13Œ!d]ýVż…I"'dl9YŠãÊ$ÇWHHìÜÜú"géQß›éN߯Ä>W¿Ãø¾·i:gÛ, K°á»fÎÉÙǦØ5eš2–Ÿ2IgOY=ý^‹ÚÃvãçÝv=[Ý¿¿‰agxÞ('gŒ °q’nqƼáqdNÚ,»^—aÕÌ©¾\µûÉ7£ßô>WËÊÛý¢„›ÑßÝžî‡NîWræò..WÌKøøãHªSÞ®jŒ¼:·_•·šé¶‘Â9Ø6ˆ¹äMŠbãÅñ¸[9˜sjôwKýmŠ1íêÝÌ»Áhn5}giì\Œ=ÚC”›>E_ìù–ñW]qKÓ™™£nçÛÑÎVÕïÀ"µP½»ÔbwÒ¬’“ç=‘Ú£F/†ß*ݹm¶ð3Ølë+J‹†['[—nÞÌ!è<7&MíM½Éi½q¹ëUª'-²$ui­x׫Åü£O>ðéãío‹²ãÇ?¯ože¼Íwð”û·d÷ϧHË›·oaÝp^ZÖ÷ãŠf˜v¿áÇ¿iY®é_ºXPJ^W®çWpî…5Öâ1áv<`ÒA °‹³L²Æ†ë._ƒèôbŸDØatlu· c 5³A4tËYŒ½èÆ1•6Ÿ/Ævé(Ïæ¯TíœiG®7™@UåduìS¾7@õu≠±ö󾚢Ǵ¼ë†‚[ÝÏ’ ©[7¾ØS²çÛKË¥¶òzÀòÅ5ëwc—2Í|÷Z½\íÃ}ï¸sõ–1ò³B¦TÝñð}Ó2çeë;+CçÛ©¬ ÓbÇ ‹Ãòr xE»c†û¤c×Ëlz[Ï &¼öõßg{Kà„(£ Š‰ESÜzükmu…%}Ñ$tíÛâkc\&¡o ½¿‹èÈí´O«¬Ù%)#f= :^‰Ô”¬°q?4陥8À#ë•buúm,ÇyÅ7µŸ»¢ãÂ;8ßL¼¬ÞxlÊî ÂAֆȮ‘SÇ ÌŒbFmÜø Å´’ ˆîÂìøÆ•¬|Ýg˜†×“uóOÝhÝlIù7UwˇTúºFÀJ˜ì;—u” m‘ºÙ XU$^ã¸ôÊ]}n7WªÛÀa£ë#†À”»(@€kÚªG¦/lX£¶KÞôׇïÔ_€Ík/|Ñ»Ÿ‰#?1žô‡K¨kÛuå‚l Ü~oŒ$ï³­Ûv/¿ŸP—RÅ ø¹Ý\«Y1¤{kCÔ uíƒ0æÓ¾eÖÝ7ëZXn±Ä›­ý‰H§Ò|¦Y9×-Ÿyo䇭#]Tˆ èüUcÚ¡qÐ;x¯®ü¶úÑ\îÝÆ›­ þa6™&§ ¿†·W‘tå¹sßnU€ç“½¸«§ˆÛXb­ÂÛ,î´]wdÅS\“/ vAeuÆ9íÃT.”'”fôð[üùpÓ;ÜJíß)n6¤«®–l»^¾JÎÿؾÿøÓŸI˜î‚¼+žYÙ¸Š!v·B”¥\Y·‘Ù¥õ7ƒ½°ÙXxoyÉ­ †Í$JÀGoà€Ã~iÇ-ON=¸ßÓµÇ,ôÛ%:tÉ7Ò:¦hLŒ‚m ±­=m}÷¹ì{a $ÇŠF÷}¥}0­Á¡Üm=±Å;·,Kã|ÚÓ¸»€Lâ½Ú·tÚ37Yïì.´è_Q6<ì×ï‚#8ïÎ6íÒkËZlË<äk5p|͆ߟ²’ÏÆ¤Nv…¶Ìü-†¾RèRîN­×~b¨§ Š]tTèú©Ð»ÕB˜›…ã·¡‡K'‰´ƒÃÓ—†Ë2í Vå’í±~åxÈø•l©ÉΑê'.ÞxN}Ó„=?b ºP6¡;²XoôÂQsTÙ ¾´äSI¨FÁIlº6!UÔ†(‚Ù'¢»ÿÉPñº0ùÏ}’—¹Ú#×¼éêôãfÌ=Ïvó‡—œ§8ÀÙ,<âÞpø7’éë×cè;‘>IìüŸnûj¦'¥s;—Êå¼B!!zeyî>ÿ‡;{QÖþêê<~Ï3¡ÚŽ^¾wù­kŸ ×>ŽR‘å±õÝʲõÔÃ#Ço–(Üt–ß{²¾kN5°JÄrÉšK'¬®-½º¡+ºô¯g£ª9ÃÇç.í‘lm×<ñÏΤËô]üNîíè@ÛÈÓ‡uŽË°GVc–Nm,ìu®QhóÇl­ÑßX.röçÆ19uº=¾žu¬zÚÏ­[ìÏ/›ŽZ\YóþoºæQþ*¯¨Lçô--au|UÊ¿ƒ²ºçwù‰ æoê÷ç±g… ¹Ë}úq>-\­³,éŒÜ0Ù\Œúc¾ï†çC r¿o ç•78FøèM8bz— @¨X…8÷WE•‘ŠV8è€À…DÓ§Ó€`c]{>ªÓÒE~'¨v¡ŒûÏZrÌ÷|:ö 5OºíÕ¿ûû=>÷ÃñüD„ù’Á¶~V¿/Zýk7ð×?—sòÞÎòõxÎý®ŽµÈ{IÌÖûì}ÊwµkÞòò÷Ö7Ï·ùÉ{îoïÍÿJ¾_{ígµ+ @¶ëH k¸û xHËü"o¸ù;#¾y|ï_lÍ!‚Ö쥷{ÖaÐØ&F|„Û¶öñà’JÓ¯›‰B2îáËE—lŸj9KžÝÖKu[Úå#Äk‹ØÅ-»O ;ðng}½•Ï-æE”—ˆWX[žsÌûÔ×…ýô–Áº²Ò#wk±Õi}åÆÎqŒ^T)מ—õ- -ÓÀüžÌèWBƒø]/%_k×»Ð/Dãò3~3<>C:ïß8áµ¢Ý ^Õ­ø›ÞßD--0êóéÙn«?2&F¾ªy¦c¿¼¡ƒr þG‰[>u8ÄèZ˜ÏÃHL˜á¹»œbëOÄ÷cÕ+¡Öi|%.]^dþµœÛÊ[vûÞ¸_ßÈ}ùâúò#}³Ý&¾2ÇsnUkýYÞqÙà4ý…½ñÇ5–¼}8Ù–±’öŸ<.ÔJÄa\¹òóѵ¼M$X,Àa¾­{¡p 3šuGÄy!2yzõ[¢~½Ã.7e¾R\3ÇÕ=pùÞ9èO­û%ÇŸo¢Íq¶£Á{6\lÚöçî{„M>:Tël/¿*tï£Æ/vͲ¶]^ôðGož}^ìÎýv•¯>ýì0ãZâæÝÎ%\{7ðrG Õq"\KW½ø­ënîŒ4³’e‘¤/»m<óÊ{¶ñ2šâ^VáÎ×ÎÛ íá+Þ Héá¤Ï¯ÖwÔíhvãìJèÛǯ¯Ïæ³;xó·².zä+ùžºqÊî÷X„·]²MÍŠÓ¢]d³¦ÍÙtP—ÂwÎ7ªÃ…á¶*ÌEÀìÚà ùD yK3M»²ëÇ[ÞÉu}ïŸÙ~=þäzûxy®9Ôù]½[›Õq¾B…6õtêìó==!éÓ½Rrá‘ øÛá3ŵ c-%§êdmFÄWŽüÉv½9!r÷-.Ç<ÒßÒÉÊìËm³.|¯­óÆËHL•÷`f¼²ñÎzÿ\wäÏ.|;“Ǽ‡–O5ÐÂs ý½óàâò-ä×>LJÖ»¯¼•žös»ç>ó}Çö7/‰ÉÛÎg•{³ùûÏkXÎ=j—•]Þï«îúßs7Ü[×WÞuO;ÓÐùzçZJÖtôý°]}­£ {{3{¾Ÿ›ËÚöd­¬+Ìç:3GCYÄúl嘵J^f!ØýÀðk8ÌûŸ=ï® vq‹£PúûóóÕàeêÂ2’q­žýwâJ`£Â™éÃ>¶ߺ‰V_nŸN*xøzrll{ŸnØ$[ª¢$¸ô­l°yëÆ¦Ä&ì=^[sæÇYë=! õÌ´F½}! G(ú~4 ³wû†ß‡”¥-ø¢5{O‡&O>ö^7knŒX;¯p|qìÊ3àèhõŽzU›œ¥–R råukÚ ÖÛL±ºú Uˆê\þà@å$Œ0ðüš­’;¾ ýeº|>¸ë|uºå]Þ’gvž«Ã׿ogu;¹ÙÕëñ»½å_ wzñ•eÜÅÌ©‡ r}¦SÊÝV<¶Bî§–ê¼¾<½9˜ìÙ}*ýVž]¹_†=ÞDòð—#¾æÞ4Wjé²Äò:û_]º×W”°¤x•­yÕYaÑ‚34q%âæ‡)Ž×Ùzü{ˆçÓsóîÄ2èKlõ˜‘;‰/†,Ž®¢I£Ðx26ad:¼¯þÖ’ºƒ÷Áð°´ãÓSœ6e·•Ü>^Ød–Ýë— ×¸ƒêK]~{t/[¸«ð ûwÆýqÝ„î/:l4ÓÑbýšvN^\pìZkv7iŽ;8ïá„¡c×27¹Ô;ÛGöpÓjŒËt¾”œ& G„‘ßqZÄB¾¬xÆÎ{^{ó¤6µSmØí¤ó¾Òr-nd] !&P\à“zãÂ%û»ŒÝ.=!éê%(’‰2å“Ðù ˜ºƒ¡»»è×—¸W×ʯ¹º¼t¹á…÷õÆ }ÕÝÕó{û;1…·a~àkÄØŠè¬Û WEWôÔë¾>0…·lòã"Æ<¶½›€âŽéÈþœ¼w÷yEÜk{;ˆ1 ‡n§> ³¶[{g»«Ò{°R‘ÍÌ,³Jb0<6ÜKÂat{´–›r¶{ÿ#nÿX´·¸%nfçž¼$›{…³Î”—]§låRvÂ<§Cw…NÒÞJ0w•류ä=×]ì´‰R{_JHžêšúØû:ô…ÅÏ–í¥ÂY¿R¿(õ_E¢.¸ö—y—Ûv¼´Ò¥¯Ùe!²èéÙ§w{³›58îólš”(_ÞiÇ(òÏ“h‚”ä>Ò7³o.«—öy¨Q ˆƒ‰OKŒi³YHI½Çg=vxðÙ®ûŒQj‘[#r×¾GŠ2íB¦áŽs"Œy't—@éÕ¦¨é¾{&ç6بAdgÛ{é±Û•x¹—T4žÜ .1JÞÈoñð…´l -0ã…"e›ôO\úÎÂ1¾[vŒÖCK)„ öúàÏl;úºþ²e–éíÇK÷å¿­û®Ð¡Â—oÂvÛÓ—+br/Ffûw;ô>÷ÄM|}ÉŽòºèt4 D»O›éãºe‡›œnA ÌÊÉM¬³Ë;ƒJò¶þîÛíVG,÷sõžë6׿³ŒJqsg1Ü`ĶN^anp\wYǤ5Ý·+qm¿ÎvÒ˜e´”wzr³.= ¨z†ìÓµÄcæ€ m#ܫâ§ ×ÝìGÝGWû‡¸õ‰Ê/áÞ Êþ{tör൑¿—†|¹G¼KsF²Î™ÆlqÁVùö]umÖÄô*l 7‡WÛÆÆ·RG©Í<•·5Ë€ü¼vnLJì·nòLJ*‰n¤zý~å¾Ò]XÓz1àg®»½]UjÍPíÙ½.ü]så.yï’Ü Ç|çKxfj¾ŒqCm–åð(ÛðZÐ"„'|à=ní~iý}°…“=’”º­”(„gJ(ÕhÏYÝ˲Ù/àC__ž(·Ç~ùÛ¯.سPãë}¾ÛõÒ˜ª¡¨„*|rtEf:F†Na84g”Ã8Oìfjÿ—Õbß©+’÷Õo’_ý¥ý÷ó»ù^•ëï]ýûSë^Q”,NPÒs‹£$ñ—”OZšh(=.¡f'Ä_…£Üi¤jÂÆ“%gdnJBÇ]"ÙÒÈ«×6¿‹Ï>V«LÈ=Ùëšây?,z¼ðb÷Ýí¾çš—þ?šÔçg븿íÉ…oUÎæÿ·+½ûzŸ´Þ1¼†Ûãµâ”JÜb{äb®Œ j5pyFËeçmm̳pl‰+®qÈ>˜m”vÛXGÂÉÁ?¶pk,Þ§£ÍA< ByÛ(ºåéÀ²:ëãÏIL¾¦26ÃDÑLëŒÉ-!ëù“ ÇÂèl»vèì†1Üì 6)L½êôÖr&çûú‘¹7L¡èòêj=œ1:Îé;ˆôãêѸãg»×Ù„_ 7%Sè·Ë,Øö¼kX]EÓÖäg(h9ëÎa;YÇðÂjæ—òöe†2…—ôšƒ†”Ëåõѱ2·U]+{ÝblO{ßçÛ-Ýö¾&†/º·[<?Iûþ›ï®+±wísšÝ#"ùÀI‰|%Dù&êªl(Ac¯F8:¹dFý%aÇ·ºû t{;TÔÏ_ ¾¿V<(z0ÇÌòmn…¶÷LtA6¦†8ãÝö¨/´dË}»žî†%Ø\\vÜŒö[ÙRF˜0„/t‹Ö(€„ÂEÚ¶dÅŒfCeý||λºì6{QHIÕv…¸:•Æï¦0`k‚.å Àñ.ùM–e²cͷ߃¿;ão ŸkG}üîÛ*|1†4»F^qH3'‘œE …•BFóˆJT9ƒç¤~¡ yáâl7’ôë{”‰Í¦ríœæW 0ѧJr6ˆìí—™Þm æ’„:º±É[ßøºcïÒVh``hn3)n‚·Ã»Äì»oC]˴lj«ŽÐ\Öêduwn%ÜvÎdÍ›:ͽŒ¥Am‘ç1Ið„!èD!´»˜Žê#å€0Ðçë°/žîý³Úø/-ÿkm\/ÌžÂú*Ïwn¼¾t¿ÆR.rý™_¡cùHh4u7Ý6Žýpãæ!qí¿ð˜ô>Ùˇ¬4=áù£é‡=Ìp‰oA>áìuð@ç'ˆ€O 'W§Ã8mçWy|p©%òÈ›v ”±Á$ë#ßoíìÏ„ŸOÞù飇¯”F5˜(*aµÈÉ©ßwÎ…&5-}\Cξ›ß‰k¿ ¸¢>²€DBýOY ™t^¿jËQ žxQj§½÷éGëet;>ÃMßPXô6Ë•ËsÝ~i‰ß/úçûߌQÖ鯓Aç„ÐDƒÅjíèè‡Ûú!é^r%GƒÀ~âªýœ<ŠÜ<_£Ó+-‚ïÕkq:­Q–¾Õ)º×ú"6œÕÜcîÂ)– $ï(€É€'ABº¬Â€’€@=ºŠ‡‘ÌA“ª=fžÒÈÏT§öŠl€éØáŒá°gAˆŒ%M)Ó¹ Aµ>™š>a™£†£:xD„ßße·¿”¿cÂêG‚€ñYB7ö;ö;V޹óVH²S.é¾ Ì ÑÞh?Súlae-l?õæÃFÛ¿fÊ–Ó« 3M Þ×Sá¹Ûj¯î–ò–.7íKÝ;8Òjˆu‚ŠÛzˆv+ûéq`aªÀÃVvôÂÓÆË!0Û®Wyo»_>ëk·µœ°Ã¾Œ½3v’ÇÃi)á:Kü( Š ¦oâ¦^}¾xo§~éæû‹çήl:Kµ :bé2Œ5/ºPÂCÞí²ÌöJ[üá½P¹øÑß“›|ùL‡+!ç–Þ®RóØðº†à Ï±½Ð9Îsœ-½Ö´s€ ;ÂûÍUTåïÚ½ÐÝï½ïhsœç9ĸLç9 ç9€^äcµ{ëZLàÈ  h µ­º ªs—¿'9Œcœ¶¦¦´^\Fsœ†s{ç#SSZÐÆ1{½ï{Ù{…îÓ82^á3œä/pç9Îq Ü¦è ¼ Y9½ó:`PÖµ ½À:`@Øh9Îp;ÞôÆ0½À:`@Øh5­i{€w½ï{Þ—¸L Þ·»ãqÞ÷ïz¸LàÈi·1~s{Šªªª½ê€é€kZÖž¿½ï{׿½ìcªª¯zª¤UUUQ{ÕV1Šª¦µ­hîÕUUUòò¤©R¥J•9Íï’¦påïÎs“ƒ¦1€Îsžsœç8/pkZÖ†1{àÆ0 kZиÆ0 j÷Ö´!Ò`3œäkW¾¦´÷½ïo~ô˜ÎsœçDÖµ¨ˆˆDDDDBà ªªª«Üªªªª3–´Þ÷½ìD½ïu€‰ÉÎsœâ÷ïo~÷½ïN˜ªª¨ï{Þô½Ð9Îsœ¼^èRkVÔÕîÕUUU"T©R¥J € ‹Ü½ï{ÞõA™œä‹Ü ï{ÞËË¢". ¥UTª¡"ö¼èe’o{½÷½Õ˜Á‘Œ`c——ˆ‰‰‰ˆˆˆšÖµ  ÜŒcÖ¯}MMœç9Î Ücµ­j{—¸Þ÷½ŽT©«Vê5fÎxÓ|í¾N9÷ûŸ9ÌÓïå圓¶ë0o‹ãX×ÍWÏs½^ÚŒj±åµîI¹ÉÜÔ½¦í{jøïyQ=¾_«Íî5';Î^¾O¶˜¿'Êæû‰­N^^gx§ðÏÙU¦o~Ô­û}´Ì래ƹÛç¶–vÖ»Qã[ëfvµhŠ˜Ù—G¬ëŽX×1Šß;Œ]l¹¼Íçž›Ï-YçwÅgߦ'goÞÞ±Þó []æËß¾ö;Úíûîï–î´Ý¿Õÿ‡ÿ-k§¸Ÿ "¢Ú§_@*¯E; #$dü*öýï?ôÅÀfvQšIÝüI|{|c/ñŸ=íç¹)©Ÿ•ÃjÖR­oUÞº™iÖvþ‘]V·å_*o-k¾sVÚÏ;_9jµx²(.òÿUí{|û‰üUÚZÖÎíòžQB wŒª’_„…ùªÔ{OȯÜ:9vZïœ%ú“GbðÐï+èvUnãÙ9ûØ<Þ7¡õkM(1£öYí4a@nÎEVÄé@@M €€šBç‹‘„—ÇmðíùÍ,Ý„·ö.Wöó™9£;à¾ÓßPÎ-îB«æ§OÏÜsßÙz ž§AöÊþµb­±öÄkS­ž°¢}u­¬þÙÕAVÒó>±˜º²}ÁaÜÙé¡f3ø¦é+NvÿÞ³í€áçì©V=@;ÑtÄ»”NÓ ]K¶¯¯+êH‘÷ïü·ƒÔ&OneØmèùÔU®½LSðÅòž„KûÖorû×è=¢“p’ë$yʹ·‹/WzP6H¢Ä“R  o\‹hÚ¾Pý¿•dñyX{R›Aœnyú>*pÒ[5Áô©gÁÐJ²€Ó€¨L0§Mh8Ø|ùàYmÚ0‰ßzO">q)(ðk^“̸æéi];ê‰céY]*L%S œb«tñÆ€ÊKNÕšB L‘BqBÊÒîá-83I‚L]Õ„ÙÂJ¬8g(¡¶k1[m×ë!€°³Ii”‰½ÐUï.îåT.#O ¿ëOpæµ3–“g¡VƒTYr‘ r!‡Š nÈü9â&=yMŠm*àïlpuþYGgÒ¾3 ¸œMø¯‹ÿBk¹åa‡Ôd2ü·yÒtø†ƒ¡ª4|B¡þ?I„Óý™dJìn>»ÂŒâ"2Øuà7ø¨o7ôHoqǽ¶cŒµãœâä•x$„$”¡¿¿Ó[%[ˆ/ïc&»cu¿s½¿*Ð7&?±üüuYL{!$f‡^¼‘Þ‰¶a+:Í3K„ÖX4  ,Ì h5{ˆÕVqŸë¸4xÛzi²>§x›íóþ ¨Èöé9§WSËýiK»õ=û›\¨]õq#õ§Ç‡uÍom­ k³cþî¿÷ùý~ºy$ÓgÂíOº°²ü•SÆw­eEü÷î1Ê-<`ܦÜ9¬zè8øÛ·Â0y˜<ñ—þöŸçhÅ„ÿq$ºü~ŸÜ}@÷Ü4^nk0ð9î÷ÛÈJI„Ñ ›£)µ§‡íÜ~tåžTÚ2—T5HœÎ1ðuu/Y#r,à7ð M[î~sñ³ÊÿÊð·G•ªäaBͰ¤Í¼AÿÊ»8]’ð#kB=ù~ïÏúÌêÄ<ðfœ˜w¿ÊÙìÒ“TPÉý´bÔÇŠ ip€¶Ï«õp³‘Êe{“$Æóà:zÿ[Õ/þK:š—d(ú|à`Sþå4†›ð”'Y¶ò“IÈu²2*BffgØ>Š$6¥`‚_á ªS…! hzŸöþ· ë½ØµÌ9qñóâøñ†¾èøÏÏŸ£ÕuÄäs¯ùj7l€ýQ‡ôý÷p‰¾÷Ûÿ ó¾è$/çkºW?ÝÑ­DziMt© †0dcÕ„äiI‘”Åé6$áfa@À˜…, §–›u?*>ý³ô>Ê~NxëžÿNÜ)èÚ÷a…Ñõݽ}Ív ~XìíþþU½Yëú#5ÕÚòww/­Þô^Iw•½Ñê—uLÊyãŠòd‘ßcAØb4YÓ¡ÄÝÙœ²‘h¦±_é?)Ý>>{^ÿ»­ìú5Äâñn·ôkƒ³£®9Ðñ«ïS2ü¬C{ɽwæÍw[ÏeñŠÞ{Ë»~ß3;Îïr³ŒVtÜ®MÝÍòú×szåë»ç*ªT÷½^ÍÆïÝmó«5¬•ÑÙŸÉ낤ùw˲\¾m:lôÿ†OטBÌì9G¾W€ý~î¼.ÕSwÁ ¢çüycï“Ä_ñ}S?ƒÏœ~Š>‚“,^p2JyìPÊ[÷#µéœ¥8øXí}j@EîéˆØHîý_‡¡ê¯Ì§å³sóï°LR1Páã âCŠ à#|>Ò;“ÅF¤Dð‰Ñ¥],ë‰WT <Ø x7)".­µµ-YužsÚ´9tÄmî‹À‰¨§à¸" %X@X¼|3 T H§&³d‚#¨Óƒ™D ê`H”‘!Q(9¸/¡KJX5Ñu(òÎ9ÑÍ}PôÚ0æÓËwoVÌ<í‰Úˆùzae•´»Ýé×îwrÙÒÞØe¿—Øï¸Ö^ï¯^?oºE\§ßÇÞœëÏÇߺ'¹—¸öYòS+!7ÒþÞÃy²µEÐÆAêßC¾¹|,U¹Ëˆ@:´HÉÎ쨑–Ì<¶’±6 ÎÔéîš(àa"Ñ5!.Íw_â0’Ö5÷y.ƒ6:ì7¢ÓCÒ£ m²a…Å 9ƒàöÿŸèÀÒþõ9qÑY³Új‡ÚÓc™ú95ýÿèÿÂþ÷AÑà`5ò;æt¾ø$¹aª3!dNOÜóT¡¡7úÚO AÏÅ|¸}Ö_º¦O³( ÓR“Ô3LoªÖ´–e¯Ç‰~[ï«üß«ó<iñ~'ÛúŽÐnëÀ'¯=çÆ"`Bíú7ënŒCÑÝÆh9¹I˜øÄDÅàDkFGzÁ4¿;†"4d’Æg%ôkì›9Þ&æËQ„¯ÙS&FQ„ÄÂ%œÀ`> ˆæÑÅùÙ, nm%õ®Ts:lt<“ÄNãÞXîC욆Wq›úlYH#€o>ÖV°ÐC@j!„m4à 0ÆÓ¤ÓâÐ$1>îuÑÕEîHû)ï00Ôê±µOkín-tš¼×£|mDöÀ&M¾{„ Ÿ!Œ#6ÇHÚ"&8éÅ7ÃŽÐpj>Ó¨{»ñ£ SÈMuk~ÿc™žŸÆý¦>gsœŸ%ío“ÚÔù†ñ+ÓÓ3½ñ&'0“zåRÖ'éx³Õ‡cj2ž!ûö´ß;Nåe<ÌíIÜgðvx*aÑÀÏ?LFrÿUÁþË4œQ÷œ=›Œ9òmKÈä}‚‘ÀVÓˆCVÁ *¡®´}c‡Ÿ­éAËÓfŠ’†ó©‡V#_VNv¿Ý›~äØ|~G_üçôðcûK#?7 {°x{6ÁB DË\kí¿ãEÛ¨ÜB¾hwÓX´õÌ2\ŒüQ„ËYqri¬r_mh_Ž´0»6K±üÏüÏ'Ø~GÑýþ€—á.:yÝY2šæ”Ö N³éŸ°+3SaJäTeª{zg!â‚2µ`{žßßËÝD’¿ ÚgðôvüOŸû›÷[C½E¿²KÝÛnÌ(êªÇÚ]ö†Ò&Dƒ&4R3Ê%QmÜsaÖÛ êÿáõŸÝs’½Ýg^·¼ÜÎ3ý§1Žgy­æ«¹Ï+~¾qo;åñ¾a¾ãžÎ‰¾s½Ï=ÊÞó¿w²ýÖwNÍszÖ/|vóX«ßz™öyÙ©z¶3¹Ÿ_µéÎ:Yå9G3e®L4Ì0“ É04pì•?´Wó®Ã¤‰CÿŽãú;oM¬»‘ Ò¹h³y´©Ïé%X×Õgï¦ ú>­T¶Öí·êÿ®µ¶µÌFg y7÷Ó"»×ßâÝó€ìõßRÑøí&Ž”UB7ûÝÖÏo¼à oºÛãßí¹J,ÜDmÖ2í»SLL A7 *—Ž¡ÖÃCxòF‘b;°rÁÆ2! ’“0É0Ö.)Û#ÂøIH&wq±CcƱ\†!°£Á" &¹\Ó-–>~ˆÊÔF7ÛN  êÁwâ%ÖNÈ@¼ #Ù¬‘HD°³†VlÛ*ƒ†¦ÛfˆW$u hò­Ç¸†¡Bè‘=,Õ‰×PÀÏ‹¢ù7Çñ8píåcóhmž¯·Ã×[²Ä­<«fŸ+|1[l§Ë´'ê·u—þŸ »¬Ã‰vZËlÏã{Ø™[‡:öÞ;%¿|“ëçù½ÿv|¾7¯íñḕÒ.ËóÍBVXSYü´ß_/eþºá¤Öð—KŒ+[S=Ýj…ºO•Òvôí 2¿~?ÏÃ-g2ë¸íì!.ú”ÏÊfå|î!A¹çSÝH郘ã8V–,¦`D÷åo,¥¾=}Vü§ÃÇ”xçœôŒ0®»:øHÓ‰ o6Ö߆5>‰è™Š<€ø¢à{cÎëªQ»Už·—|™¾í¬xý¯•ðç†0o%~™kÕ²""¯?û{ø«ä¿CáOÈ–¼œáóᕳîæfÛù˜¹a²<C±'?ÙÓX}!i•¡±S{³ónŒ#Ö/)õÈB„ ŒPbаÊ7ÈÝ(å%6#Å”B0YÆù+¥ò·]dÕEI¾Æ«–bÅTš²U¢-EDmˆ¶J¶©’£b*ÑdÕ¥&-õêå±$c&ÉmY5,¶Ë ³D¥!3,ibj6ÐL# ™!Šd¤˜™$ƒ%!iDÒI%¦ ÔŸ¯úó\ì+ö‹†ŠÇŠ-ÓÕ·'ã÷>æ|xñÙá(¿½od%“'2È=ÔÌ@HLÂdÃL„ `HRc1„°’Po…ÔÂDDˆš&FNú»/.Þw|—f11³&FR1a%,„2BTê>~]v.»¤÷ÿGÇ“†ÃPƒa$íÛwæ[ûìùz3Qô¥nÙ5Ê ›ÚãŒ}9x(DAÝ «+ºðìã•™\÷w´V9F ¡õ>ÏŸÑÖ½Ý ¡Œ~¹Þ%jƒÜR$×\#8³¡ç·.c\Þþ>ØNûïwƒ+XÔñ„´WÍùçÖ.¹‹ƒ(ʱŽõ÷Žì ™ëìÉ·n¢ƒû¨û( ˆÀ¤ ¨œÏ} 06ázÚÕ2ÊñsëÈQ‚¢0%±ýì9ê?í(rþlóKÈí—¢ÏN>ò»ªï´¬ ôè-¸M ÿo³åz~·Ë°èÁõ÷¾xh82.úi€·è3Of·Ý…ÿàì÷,¢ƒ\8&`!ir·˜P0ò¨Ã*»4NšP€ÀyGÄL‘Ÿ‹“‹³G‹A`Ý9êü<Å7"ã-$÷]|/M#31€{=ž»võ¼ ù5Sîe–X‘þ)t‡Ç%7@>g¾+â=CÌ’¡ïË“í@FAF»ÿ©²\~‘-¥€#ûÀ› #T ™UÓìcM@êGÂùqÖŸ4;@ìž+‰¸nktý}]PÄñ0ï°Ëø²ä ›ú${»»;îÌõ™½/Ãñ´8Ò¬L¢sÝÂxFfa·Ÿá~¶%x›>·èF·í¸…ý’35$Vp–w­Ì¸&š–Í>\~É»NÛ ¿¥í»hP³pAàY1W‰I3ý#êŸ5‚ € FïÕh¤9ñº›_Fi3šý–«.Öõ)]SJŸø÷™FóÖ´ðE§=ð,ñQí=¡u|‘6ÐÝÌ:t®æÃq¯'±“ÊØýhÎßêìy‰¥Aí©ntJ[ß?·wdï©;~µß±eØK?"Ï·+¢Ùmï8nÂÃuJ0Ľ3fÊvÛÂùì$ó:§ìÆùX°ç(å2ù¨¤#¥Ç,é9ÿWöÞ²¯VFäË)~ œ,Í00ßsnøJ|%õe·æþ7ó>ÔpË/•ËdO,Ì õá±¼¾ßìÁ»¿-úÑö²Ö$ÿ¢ùüý.ZómÊéôêþš|Tgõ c¿—õ£øÓOµçüÝd+ÍÂø¼û»¥¿§Á(Ô~ݶ[º=6‰ˆkD9íJ h·`D/ˆ¶h6hºë¢–‡•ö~iÍ?Áòÿ+«—5îÄ =ΪÙàÍè‡ÎöTú(>ô;UJLÁ-†©JQÒ¥zÿJ}± 6ˆB9ÐËTtÝAÒ·A¦?žWø¦ƒWî¬z¨Ä'ã Ä¢|8ÌXÂKGÝÇ*¡xà šF––°T !xV= ÊIšåpbÆ´öù›6s–œ‘¼97£l8/Y £èç€ãZ4(a¥†¿›ÀYý¯€ž;v7Ö©|S¾3sD‘y³ÍNW| G:°øm­)#åJ‰§njøÈRKi7q²®JMìÑYcO(iè×*c‘|ßGo/›·n÷›¾yÛתQ[¬&ó~cã•»÷7Íæk9Ä­Û¼ßoÞ[:¾³Î÷œÍc?ë~®/ZöVNÞöÎ$™ü™ùËÚø±z­{<õfþçnQ,fSB‘\ÀW2 Å™"A F8á$½gc ӎܾ³¶÷ÂÎ!$$ƒ‘Ž5$$ƒ‘8Dçjkžq­Rë:Î{alÆ666Øò^z$Ã›Õæaˆ àæ™Î¾&’388Î0ã‚%ÇÌÔ¦Þ!heÉ­-¼ÁǧDqÚÖ¹Îý³UMVqÐ^³—¾;õ[59{ß:›ÛÍW1Úõ¹x\3},ìu¾ID˜‡T¹0ÁGXœ‰šG=µ«YƵbq¾.û¹†º:ÖùœÎ'/Î{»Ï3›ßI]Æ9ÞÕõ«vZ[ɧeñ{ݶØÛm±×—  c—Ì—" ,‰Œg rp²œk‹sW§½qÛx^:[šís|åâôn5Ʀk­8híÕ}TÂÛ ™0É™`Ài–ÜÄ×9Œnò³îk\Ýû:®÷Vתü›®÷¸–ͬ>9;rÄ1¥“01"¼ÌB #˜DˆëM¶ÆÎ¸3!ɪÎ'Æv˜÷8Íΰšä»âöåµ³“†–§'d0+®‚,m¶ØÛo@·îG»q¬ç&>:ìk­³77ÁÅÃ9 ‚]¸9Ó©² #q„q¤„Üj4ÚlM¦I%±Ûj¬ Iã@£q€äáœ>Ö™1«ÙC‹h˜>݇ÌÑÀøë97@¶;jm¶Úäí%FsÛW‡§Öfpvã˜>¾ÜcbÝç9$\V9N®S‡yëé99kGf¯i‹Ì^×½¤¾¹/uð¿1žÕs›Mfos|µ·kI?i1¯Oµ]×+²üÄ÷ÜsºüÔÇ/"¶yÌ}·ÑΩèœy»æÎÅ\öÙÖô'†­»š|ÞcSxÎ/kþܾù\åVï5Y˜ÞurNî)­6Ã9Ý×Ö9]ŒÎUMæóÖ¹UÎk¼îñm]zß;mÎöTÖks—Í_¹º/ˆ¬óiŒÌDý¦­$÷×>Ûß­bÚüüüûû}·Þvìþ·&sçuž|¯|Ì™®ö)5ÓZÙæë=©Õ/&ûÁÎÚ£2IŠG(¼ÖõɹosXÖu{ç2ÿŸ3®Ïvcç¿9öˆN¸O &“B‰$$˜X1}ñ•ö‘ºùÚ¥lªø_…d’Iа×Ö¸4mÃ,­¥—ß(¦d^÷½í7¿¶|«ëÚùᆵºÅïy%|ÜÅW»ö³Ÿ|ù½Yó¿3¯Ÿ7êßÏŸ5«Þ÷¼ùé_;Zù¹ò¾{æd´ìöýMû=•ìZK_žOF1_™öq=|wÓzÜÕíiûnÐà×i³´Îd{‡Y"Ø’ÀJêq85Î^f+8’ñ/˜qxÉ‚C€øâ^ ½ã£à=<ÒÊõäMX÷©·½7‘=<¤É§Qjjê“M‰Æ3ZÖj3ÑS}ÏMo¶Î½l®Ø[im¥¶’ÚKim¤²Ùohv3L—µØõÑØ¸óe•7çr8!wÓéñ=½ó¾+„#coxMä u†ôA±¶6ŒÞʱêÍïWz33y7©­ÝÜ­-èÝÑ\Þö¹yxˆñÇ™+`ë®´Ë-ˆnËcMŽ86É#l„ƒppmÃÁ½øÍy><°íδãNÜC;×:~Zò…¾a×&sâQéöäìÎM7¾rµ/3Z©ÉWÞ¯U3¯Õ÷ÉÞ»/œëvªÛÞ«Æ©©3 9p†ôno™Ã)Ôo•ÁÎÎ yœ Ÿ+ߎýÛ:œ÷ä­ó#rAˆ%›Ö{7+Í^r§e­-7ZÎê­ÌÕ듵ٙXß ç“b/Ùw¾4 Þ‰™fädÌóÍië¼÷›îÂAˆƒ½¯yŒkµ|g?¯v|ö&ûz§ÊæåíßbUë©î7ÜrjÎfnû¾wž/œ›åñ/;yúÎïÆ{ÎîV5×;Ú¬g®ã}•Ük¼ï{¤¾–¿9uk•3-wÖðpI¼òÆ‹Hdá1.6q¼áo†dI`IÓCDY‹.F‘3\ŒÌÁ—©%!ŽRÄ*BY«íøÑH`åòòy¾Ëë÷nyÛÎúgŸŸ>w¹—‰ŽwäÞóZòý×%ÿ;®vrgÅ~g|¬çÆy9ËÊÍvøÅ]žÉ~wsKL[=“—ÇŒïàðrmªyÞ°N@CdhlŒDhhÓh{Îo:88çLçM¶Û¡Ï7 ãmð\H7¾ qÃßÇh×0#%Ê‘–Ó3!r 0rwi ¶¸³›ï}˜ö2Åb|{“œššÌϳ>æk˜Ögzá‹ÓZÍñ†õ¬siÌë\Vy«âs•*j^ÛÕõzÚ`xž:é¾yO±vÐèci ´6 ŒÀKŽrë—Ç<æi°$dÜÎ/Í TãŠ<ã{z!¹Mî‚ mD`hCit#Rƒ“Ÿv¢Íf‹m) Úm°cl{Ã.nÝàÀ$Öo7uw…5¼¯[ÒÞ¶÷½ÍÃÛ5½4€ÕnÝ ±“0²WØEã]ðÜÌ4ù““•¾MpC;ñ¼‰£aaMpøï35{Öu£YoV^6bäpÕi)­í¼qUƒ04îaª…†¬Ö-fbÍ4jk aIJUa€ÀÁ\%,·/•\]Å! >¥œKœhh0:¦¦•×?s¿ç=ßwÚŽÉÚAÔ… Š‡wªEÚ^ãw°Ð€Œ*:WD€+ æ@FðG® 8üšÏ÷Çõ-ýÇ?Àoû©ýŠ;ÛÞýÃWç1¾_fk¹Íjœ»Xc´ÿÌÍ{Õ9íâ{ºÞsW™ÎõÚÖ1y­úün¦0.Q‹Fæ¶ÎÆC­˜uÉÉ3&ò­UÞ÷¾K…"Å€@,X˜Á6Ô‰"$Õ‘qW$HX:\AeKÚÀ,êÌ àÊņÃR?Å~­0,ÂÁ!Òö,X)!""$$DHˆˆK€tÁ,Xpd †¨ ÈÑ‘n,`K€R !bXµÖkuˆˆ‰Á›,$ÚÉ IÛXsCGtºÉÈRÖ,€ ]d…‹Y€²Ç!a I l7 Û–,Å€t¼°-±`eÀ:b‘"N2ÃPMkkBŹÄY0‘-Òáh…‹$Ë$Z,K‚BËN¢`HXœÛDˆšˆƒBÆÂÙ‚Zp`K¬H Z@²DRà0,àȰjĈ‰¤DDÜDDÆ@çLX.Yb’@ÖHZBÔ½¡`; ‡@ØhàZùŠI€.,Yb@X*Ë€tÀ°q"ÌØ …´–«E‹BÛ ›Á‹ép ²@X°@H¸0…£6KE–ƒa [AfË,jààÄ êËÙ`HYpÚÁ–$Ù A l+L$NA€/hI°ZÀ«Yp˜X°pd †«vzÆ@çŒXK…¬…‹dX—êËa Û X±f°îŒ‹Kp³ Òö,YV@ ¥À:`áfE†ÃK»9¡£ƒ:\Y%#""%­i-ÄJI©‹,’÷äç-9nrZ-ص–…‚ E€)p-kE¤³©#bÐ@±d‹,Ë-âÆHBÛ,[@Ð-°™ƒ:\R®˜„±±a‚"À){€Ye–Y"E–êËbËE­,,-bÁ,²E¡e‹:³À°`YbÅ€@ ’ƈ²-kM¬±`Y- ‰ -‚ÂË;bZ×° …¬" ±ab@¥ÂÒV‘€,ZÀabËa ‚͆I ,·$Òëe € ²âЖ…¢Ý0…™k–jDDDÒ",Ød ép @Z,ƒéMZöbÀ0Ø0 6 Ì Ö Áaaaaaayx^5……`XXX5@ iŠüMß'î_¯­K¯z[çÐãÎë]ú}©bŸ.òòO ! {ž1µ›ÉWº:(aaݺ˥6YK+%1j²’¡~wNW\B¨Ps:hÙR›56´.r-{l6K3<ÿ™–óËM,†û›îKÚxöuŽ vºíŒ¼<&ôOá@x¿gb¬é¯ù)˜¶q ¤R "%hù„8P@B·}÷Øì×Ñ9IS¼oqñvø)öŽz¾óGFì× ‘ÞTLÔ帑õJAâ^w¯2¾|I”„!)HBvpËÍ«ïÿ×çìö®ÂU ôÈD#DB2DòÃõ,Tƒçý¥=\»wúl#q>þŠžŠ&€bª“‹H*¹€Çùôù'ž<ÜÚ€9~§{ë.TQ숪 È€ £€÷o`UízW;ºôVËñwŒåœ¾ÒãÖ—bg+ÌÃÓKý¶F7{€¶ÂÕöX@õæ ”ˆ"'SJq†¥-%+{zA3ÛyÉžê0Ñ|0`V^žò•Ûµ¢Yà29 4ÃS t9Ý•_~cWݱ¸ö±ï ¥Î÷ÐÆáì?v­ÛáÂX àxgy@kÿëX8À)·èÝóþ×úøß+…ÄÖø»{©²õ¥æÆå†ÀØ6ànHÖëæf°#n6LV4„úÍÍo±4¾là“v¦ýšŽÕE6+kÄó=¤’i£ h6÷,…yãÅ\0¼)£Ðð…üƒÏóo|ZÒÒÖ´“õ÷õúù÷ó~üý™ƒ:\¶ƒ@ —é€a h Á€i€à¤ ç9 Ó©UUUT  @Ødª­ÕUzIinw½ÛÞÎsžvsÕá®s„sœää¶÷½ì_¤ÕS{Ö•o´íUW;Ò‡Îî÷cYÞ³œÍND•1999=9oKrvffLKnTää¼·g"^LJ˜•ÍR©Rªªªªª¨ Ò•T£§7Îïœâ½Í£—®óº­g]¬g9®Ñ5Œéµï€é8¦F10¦/y€ c£ZÌÖ©k„=u×[ÓyÊèÖ´ZÌ«žÌøkØž+cm±û}Õ­¯:wÍ;FQ½ô“C¿²±ˆF¢Ñãã÷µ—Ä’³B²ùwY¯;²òìxÁþmôÌúœýn[y%™bcýê£4Q0l{yøúù{ñ¸¥’JRÙ5JmdÚ’ÒZ•¶l²KRËY .z…E¦f€QÑ>öø&ÎïZÅbÏÚ·mëm¾Ä{•Íh˜"2×Ñî^/U£Z·F¢±ª+_[5Ë+áUº&Õ)ªÛe²ÛhÚØ¶7ªÕʈÁ¾=¼¼©5Q ¨²Z¢é¹[Þ¯~UÚ÷o¦­¶¼W,j£]KáçÊ-£$ÒBMÎ\â `pS¶+l ¿8±ÃP¿ëO_ÈVÖ¯ïžýV$ÕŠ’ª2jKþ^ÒVÿÓþžÿ|ksÓývýþy­[›“úªI« l±Hœ‰‰e —$T¥À:Œ,Í‹%¦íAf°É‹²Àt¹i`)"ÂÉ«júÖ‚ËR n,!¬ nÂÍ@hÌŦ1{ÿ«½Õ­-i$ÿ{½¤´©ZçZ¯Ÿ Œc †”–)R^jnffDÅî9Ýk:×LMrTªÆ3™1ª®Ñn—bצ)ii%¤bI{Þ÷³úrÕjÿþÕYDÉŠ%$J,FQ4Ó%%-4·?Á«^{ªÕö|þ²c%Fñ¸›ó:BI&¤©A/°ç¾Qý¼¾ógF™pè4lÝ¿ç×íüßÏæÆ1†ÃJÇ"/vFµj©©Ê«b­Wj‹N—[¸5;W½ï{É~ß§ò__=)ùµµ]{ço)\2m«µdC(gøß·Ï˜Ä×¾oçÏ­ cT)ÌÚbv^D^ùØÖ³­vS¹•lUbª»Ge‹±{S?¡ÈMóq(HR—½ïy{Þò÷¼¼Ç¯õæóÎóÛ÷ c®ÉU]¬^ø—ä«Uî͆µiMNU­W¾+®Õ/f. NÕ¯{]|Z÷———¼½ëµï#'Õɦ3!HM õ¾¿ÃùnÛæk½ß½æ†1€Wj¹Uyiy{ZT¢Ã{Þ·º¥íÉUŠ“\µQÙ ]‹ƒS²®”ÆP€’÷¼¼½ï/v5ÿ#RsÝ´æ=­û~y¡Œ`Ú®U_SS“’J”Ô×9½ï[ÝS{´çsºÎµln¹*Ž—³§j÷—åñkÞ^^^ò÷c½âäâBBF}øþ_Êóâß½Þ{oÆ ¨é­LÄÞë{Ö÷TƱyÚª“ª’¨ì.ļ€Ô«Þ!!!0€ŸG¼½ï%íŽÛÆ«š›æ·ÊÝQ¡Œ`àÊŽ™ÄÔ@ßu½ë{ªï¿½Íãj‡.Åþ¿_¯×ëí¾C"ƒêädŒ¡°“Ïè{{ö}Ÿ/³ìøûhc82/mÍÎND5¾s[Þ·º¦§mUXš®Ê¥.ĸ5*¥åñŒKËÞñPcDF„Á ^ò÷———½ùÿ½™“œlóCÁÁ˜9ó!Îq­ï[ÝT KÈ`•®}yõúý~¿_wÓé4% †@˜M6Æ›i¶ÛM¶ØÁï™Ïì?‰wööï;>³-ØãÊåÚÙy—¹©.´)OTíy™e׺ÞËët™s¢£ÿÞß‹6¢ø!ÝLôªèB'…@¦D­úq-ª–-‚‚‚£*åÆUæ"ê r‹‰7É]K e S(XˆTpròm-ìi%z;„I…X êÔÌ~^O>¡~àð˜8%ÆŽÏ¥ÙôžGià_ì|½ƒ˜u]å‰Ëºê¸ª¥Ô]–Õ|¾ëï¾ëŠ·R_þOGôz3¯fˆ¼èÂt½¥[ÑJØg²wSpÓ$Cˆ!2dÉ$#Ð"3L‚§Ð¤©&wl•—TÈKóË$Ôzÿî`Þ_¿ 5lyòKëåkÏÓò½Ï¾À׉°ŒXŒj,‹!#"Âp µØ ‘?Ûf¶ñ8·ðù/¾Ö‰1Žþ ~i†œ óìel9ʈYìàñ‘¥¸›Ý‡D ¶Æ~ôtC5á¹ÿ^ãûùœ?{#]Ù’Á{O+ƒm³ÜÈü]Ãíê»Ãqu¥òëî»§£ÂqT$1ªcÕ#:÷ÁSÈ‹[^ëCùÿ½íßù¿¾œÏíùü*µ_°Ød ép Ò€ \¦pd † l2t¸Ös JåUUP€l4 `ÕUVªª¿¼þãù$––ü÷¿??4Öµ½ËýûùøF¹Î 󜜛æ÷½Œc*šÖ´¡[ªJ®Õo)J¾³{Ó[¼Ò† ÙцŽBŒ§%6 Â0‹³^bfD•*c­ò•;UUT®ÕQQ• è*ß;®sŠv÷6vŽ^»ÎÖqÚÆóšª&µ7W¾Ž)‘‰‰Š¦%æ(QR®Ä¥+:ÌÖ©kÞŠTÇYÇ+³«¹£“|tqÏY·95Y¿ô¿Á÷î>¿òÏß%ô{â# Ûå¹Í×ï®ÑþimüÆmñ}çáÒç]ÊF%r ÛG /‡Zú®j>!ýSäÄâ?6úWÇ<ðÈM“÷ï I;„8„‡’BBHZÏ›Òt_g’fª’.-Iƒ}m‹W¡åãËÖÌ,AÚ7'À‚íØž‚†ëS+ˆŒ(È«\¶Š6“C¼Þ^6ÅlV'uåçr×À¼WóîëE£ ´…îV!*Õdb]H3žjÏß„á½ÆPS•iÍ… ‰˜7ÁFG/Kñ¿?×åßî˜Ð?ùÉöûÚN¹p=wÖ'ËÓ àën"fq3&º­ÚÜ]ÝtÑ£&¤®m\.kswv¨ç-¹ÂÕΕ®pªîãwrEÓšÂX¹º«ºérå.XŠ(ÛsnP`ÜìÛn[”ŽnÔÕrÝ6uÛW1ͯ•ZÅZÊÞfñm:Ý™„ÉÐ5=ñ^總ÚÁ‰“ì^ìå”ëè°´•–"ÕšªªÝZŒÈ±l·K¬”°H"è•"Rà°é€°Í‚ÐØh@Ød`X;bâDÝ­«ÛZÔ‘h, †ÖÑe–Y`,H°„ÁilÀ6ÌÌœ¬ÏåGƒ›Sh8ûÉ!á¼½²P60 ‚fc¦4ïí¿áü?ƒCÁÁ•§gfg'b9Ím­î2•jY"²® ÚlÞçñÿÁjÍj~’f`0ÎðÇXë øì+³hÅ´¶ÛYÝžÛ,²È±u–{âv½ÔÉÞ"""&M|||{:½ç’’c5î!Œc51Œg{ÑÖ¥¼ºID¯Üë“߇Ä<ïuÊ1¢%$™íøøø—½_""4O§\‰úß*ù|§|ø¹F4DDDø÷ßg^õåȈ‰ø„ccLjëS ”÷Ø6>aØØöDO—ËåìëÛ¼¹L·ëuÖf4QgÇÇǹܯ|¼Ý™1ŒcBBn­ÖoÖØ\Ë„Þ{x`pÛZ03:”¿£•üÛþoèùí cÍïwÞ÷5è÷«ÞÄžžõj¬,iªÇ–LÚŒùŒÃ6*øcŽ ƒ,í¥¶µ¯'nÉu×XúëØ„kĤÓCù¡ØØÜD¯uññìõÚæ4DDDO=÷Û®^î¼¹""'¾ûìÜ{nòäDÉ|uÙ¾>>=éÞ\ˆ¢ˆ™$Éï¾û:÷uåʈ‰’JII“ß}òuîçǵԗuÔ’JL’I/¿åòù|N¾;˯áõÈŠ1§uÈŸÍ×½åȈÑ-íï¾Ë¯{ˤȈˆˆ§~Gèý?¦êýø"Û‹ãËn^ÍýuÔfcTÌÆƒçg xp—Y,±ÝìþËÝ÷½½z=ê÷·~ÏOa³[Þ·¾Ôsû9j¿ðŸÍ%Ä#3rrõ `Ve”,r5ÏKhvíÚEnݺë$ïÖ{†¡âR1±±±ü°ŒllMëZ£†JPŒ~BAD€–€RÀPŒl{Þñ9] 0¡ H$E6J ab>ZV6666Ž8Ï7)©T\ÁBEM¦ÐäQ‰´Ú~œozjÕ6¢6œŠ4ØØØØúÞ÷¡ÃR“p’B1ÂŽBHF=kX8d¤ (F66“ø EªK|þ?ŸÄëã¼¹2I¿W®Ogõyr"&É$‰%ï¾û;»½êòé$’I¢"d5\¶rÀmµÈÃKàŘ P ©;©fíÓÝ}²ËðûÞÖ½õO{³ÓØ ozÞûJî?¥-ýßÑi›dÀÌ\"Ë0ÂJü 6åm-µ­wv¶ÛmbÈ‘»®½Gñ @c_!Ç!ƒ˜HˆÆÇ­kÈR1±è„Ÿ5+U aØÖ÷¼ø{Mæˆq¤#0Œp„cŒ|›ÞJMn–Â1±´9 !!ǽï¤cÔÓ`?R1¡ŒLiŒ5ëÄãCšÝÀœÅ9UÔX„‚ ¢AAB&:B{àž8ÁÃ%S€QH% DRŠNVÅ$Q£>_/—³¯{Ë‘>:¹Ÿ.·(™)§Ëåòöwú¿×ï—¿ì²Lˆ™åÞûÎù+ãyî¹2dQ2"Zð©Ï-újÛ.2m™ŒÁ’`a¾tÇ|÷Ûd,²Ç|{ô{Õïb_“ÓÌo;Þún4·öVŸ¨ÙdÌÌÖ`°®$øc¶Ö¥¶ÚîÎÖÚ[m±ìíµÓîXB#¡`㻽ÇBBBBBÏÂÈטçO‹„cccca:„°’‰½Ç8zWn H`Øœ„cc'¹­G7* jcRB1±ÂÓw{Œ‰½"RnB1ÈF6>aØþc·9Ï1Ãr“Ÿ-„ ¦ÐØØùwËåίyåã®î»))‘=-]7'xhÌ#MŽBnzóàê÷¼¹$iï¾zuï<‰“%%$”ˆŸwò¯ÛúŸ:“õ¹éoÕ¯$·ËÚÖ¾ÿ“Ÿ½'òsù<ÈÆ0pýý}z=êžö=< o;ÞèœçóË~¿žÓÖþ¬Ÿ¼Ÿ¼’ZÖŸg·?^ù'ë6ççêWígòv{ÞÆ1oz{ÒÓÚ“ãøzîå'ÂB1±±°m6†Æ_Þ±¨\¯Žòï—\×%Hˆ‰ññçÃNç¾yroŽºLˆ‰»®šo‹ãÏ„ëÞòäI2d¤’D}ß?•ò÷äί—y\ÌÑMÞÞûã;{Þ\ˆšùõÈ™.ë²[ôêqÁƸn#jR1ñcc„""4³fšø¾<ø;{ÞnßnDDäO‹ãχ\Þ÷—%‘4Í$’#SÛß=w7½åÔ’dI“$ÂB…Üvr ñ°,vìX1±†@5êK~±ßÞžþOÛŸÉñ‘Œ`tö}õ{Û˜œšžžk†·ïdoÍ-ùk--%¿{~­ii?9©øüüÍ¿>þJ9ü}ïc·½=ï=’ÿ·ËâböŸm1™‹ËÞF4É¿7]L””ŸÇ|½ÝæºdÄDQ2'žÏ=;^îòäF)‘ÒÉ7·¾zw©Þ\£>;\Ñ>/>Þîór(Ì’R'·¾zv½ï.DDF‰(²ó¼:ý+ÚóÝß.܉’š1¢3ñ|yðwà¾<öäO—\ˆˆŠ{Þ¼ï+–1ŒcÎðïÁ{æÞÜ™I2"HHH§î´ h ®Ëa›:WB9RµÙ=›-ÈÆ0:{>{ÕéíãÓÆÍo;Þê™ÇóKDþy/?Vµ§É÷çß¹÷­ö}ü´pþ>Îq'½ïZyû/|[ìï.O;k˜Ñ7×Ï=:÷¼ºü:êI$’I$’÷½:ò»Êé’É$‘ãß=gsÝç—#ˆ”Š4ó¼uËÍÞ\ˆˆˆ‰’¼ïËÍÞ]‘2""yw޹y»Ë“õºäM“{ÕÓ4ÒMÝé®<×yr%H™$ÒI“ÎðN¼ï.DE±Œgyç;Í߇nÌbd™&I’d™N왆¢`Tž3ƘãLr¶Yc»ŽžÏžõ{ݘœ—’ÞžÓf·ïuKÛŸÆ[øÛòÒÒ}ù>ýïÜý÷Ùô·ë9Ìž÷½oeú^øžÆg""""'ã9ú½ïžÜÑÎñ:ó¼»"(Ó4DEW»²„ªRfq 32’ 2 è®¶ÇE£K¡.¢¡|$jz5¬úî°¤‹”øxÌÙ«a¯²|›¯D|W r‰aSüIix©ÚgƦßêO/7•6˜Æÿ…ïÇár9æÊV£I¦²dÇŠáfn–B6ÝÕEéþ›¿¾§í/&ççß¿u÷î~¿a°Ð4 †@àÀ—µ#@¥À:`@Ú«5UUª †@àÀs›Þöà\2œƒ l4Us\æ8ï;ß{Úïw½îpðvo½7¼oq7¾o{Æ' kZ×B´s½ïx辫{γZšèg :´S £ Éɩ٩¹ÉS2Û™’¥µyÝw¼ro›åuUÚídЮ³­å¾©Ýc ¦ÕÞv³œö±œfª‰­gMÕñ…NQ˜^^;LÌÌeAÞÞ±9*UJ™Ö¦´Zõ‚ tuÕÙ¼.nða'u×uÅñý¿ýïÒúŸÄ=çð‡ßÄ~«š×òkI´þÃjìÆ{Ü#Ema®_›eK$ŽÕÛ?ÇM².‰»5ÊÅï}Ÿ‰Ú¿abIˆ!˜±ôrK.Ù’˜‰×H‡…ŸzŠR$Ç¢Á>¼€Ø¾ûìœ npIÚJN îˆ /õçÇÁÜóÍ7K³É›ą̀av]â3î t°ß*qi•L1`ÄkDI—ûG‹FãU;² Îq21|žgZ;¡2Exí×Õ¨Öܸ&vh úÐ-vn×N©øøþgq(AP+’*˜ Dz‚bIœ]ÊLÄPÑh©ù3LÏ{Z ÐDy9ýâ9É‹‰;NìÐ"Ï’ ²ˆEØø½¯ÚüŸÆü+÷ú£ºäÑ«÷J».\$–ZÕyÕѼ•t¹]±Ú‚´AŠÈ‘´[l’9$ÎçuÝÝ×wuçyåÜ@<ó¬q¶Ûlh¶º ºX…m²I!A&6„済Œl•r¹ „‘ÊÝ“UÊæ&¥¥±€)&k¿”ý¯ß\þO÷=ï”÷ùçËøe ±#@¶¸–àŀޒàX¤‰rA$Rà±€,äƒ"Y †…fÕUUº£!bN`‰kZKnÓz¶5 [£ü§½=;ëzÞ¶}kzÀ €³ƒ+,LX ­™›vQ„;¿ÍD¥ìÔ^ž ÄS2”±ý;ìË*e…°¶Ö1ÓÙóÞ¯zÛšžžÃnkyÞ÷Úmko?žßÑ%ÿi-óŸgçäšüÏçßÉSôâűoåÎmï{Þ¾¿®äíF hgb84§¥#åýªV{¤3–œø¹†“T¾ÙFƾ F„ jÝÑ2|ûæ<ò"dȈŠ#ÇŒÜ<ÞDDQ)<ï Ï;»¼¹2I‘>ÿ<õ—s½ÞDDDDFžw…ÓÏ""}r""oËñçÁÓß"Æ4m6"'ã®O<ˆˆˆˆŠyÞ;“Ï" !C†âË×µyüÏ©Ã%ƒ1´ÐÂò×Î}þýþoçïö_ÑìûÞÆ0:{>{Õïnü˜žžkF·ï}§1¹üòßÑ?–[õ--ooäû•µöÚ÷Ù÷ñ²ÇfÞЃ[m¶ÛfV§ Ø d!¼ë‘/¯žzÓ½ò"M$EüÞ÷©Üïo(ˆˆˆ‰¤×›]âw;Ï&Lˆˆˆ‰æÕÞ.¹s¼ò""ˆ‰ï\žê»ÔîwžO:äDüÝr"'•_kÏ…;ï‘6ò·Éç§O|ˆˆˆŒYçxtóÈÄF"12^w‡O<ɳqЫu'{X;0ØdÌ^×Îk|óõß×íï{ØÆO—ØÒ­ZÆ2„Ûm¶Ö|‹F ®IØMs@HHI£F1<­Þ:àóo"""""u¼Û^E/5Ó%ÝvNë‘«]ãuÏÞDDDDDó^/9gO7‘6G:yäDDDÉ&O;çžDEšI‘Îðéç‘<ïžy&D¤ó¼t»§žDDEÑ¿'×_e婸ª~¤‘y/¿×ëµ÷õÏׯF1Ó ÑÓkóU9/3&á®í­ç{›#“½­ûÚ}–´{æ;óå´ù>}[c¶so{Þó÷õñ|cö½±óR÷—¼½åï/¼ë‘7qãuÊyä¼ë²&DDDîðí<ò"*"""~|ôëÇ{ìÖQ2I‘Oo|ôì÷Ìhˆˆ‰’M÷{箹ž÷—&I2""'wŽäóyE¢""'—xë™ç‘$™O;óÏ""(ƈ¢yÞžy BBd! £mo4¬LÆ0EÆy´“·—×ÏQùû~Wïì{ÞÆ1ï:{Ú{Õïcº—“SÓ“²byÍoºÞw¹µD½ng?Â[ö“õ'êZ}«|ûïºõ¾Ï¶ülbß¾siï{Þ»öõï‹_Ù—þßY™µåÓºå±;®QŽzvyå2"""}ýr{Þ³³ÍäÉ)˜Ñ÷·4O{ÔìóȈˆ‰ç\ˆçŒ×HóȈˆˆ£o;óËÉII"""I}¾ùéÓß$’[jͫLJO<µ¼xtÛÏ*I)I“&Jó¼:yåI%4ÌÑ+Y-]óþÿößuïßßù-ü%¤Íåë÷ûÚýþ~~õü={ØÆ=ït÷´÷«ÞΧfæf$¼õ¼Ó¹ÔƵÊ3Åoáû[õ-7koóò¿=¯¿Ÿ†Æ?†m›Z[Þ÷·_²÷Ä»2òòòòòñ%ç]%%’K»Ã§žJ󮤒’¤²®xtòòÞ5G‡KWÎÃ7”<3›B·&›ƒÕ ëpjÐ+Ýn6ì%ÿâÄ‘€+]“ºx05Ûtg3šaNÌ¥–YcL3¶Ûk»Ûm´óÞÓÞ¯{VÔܼòþ{α­vžÌþŸmióß=óåkß>ý³Ÿ{ÞÕWä’ø^LcÂöÎ¥¯á»LX˜œ¶ÁŒpw×âë[Ó[ˆºH›nÏønáư’ް%J¼ìÊ NY  e¨Ã¦•Ât¦zÓ_׳ï^þ÷½ê÷½—½^ö÷¼ÌOOS»Î±w´þY?–Óòß~I÷ß~ý¶¾KO¿MŒc÷Ͻo{U_©|UñŒc#ƒ¨’ŽÉG{[ƒƒÉ(8ÉG§]³48P”pvJ8:f¸ð#l_ßc¼ß>ýûùßÇæ}ëßÞ÷¼÷§²÷«Þš››šžž”çs¬g]ª‹òüï¿Vü–r|ûÜ}÷»®ýúnAŒ~¯nÝ»óä8>d©Èå’ŽÉGT”såÈ•’`âj©(âj„”r¹J9\ʶ1™|Zù“Ÿ–´Õä¾¾|ùó¿?;øÇßz÷÷½ï<ö^õ{Ý““2ósÓÎíc:çi+›ÏêO³>cß kÖùð܃üϽo{5_’øµë̾-|âQÄì”q;%NÉFA´ì”dqÐPuID'+R)*p®D_­¾{Íôj2"4¼ö6‰Ôå_*‹a†2”Åw³MDaÓÌ ‹¼lѡǦ´ Ø&Ê®xÔO²GÎ5²m.¿¦®¨PòDÅ£Bªlä)`ßJY$Ìò³Î1R2¬ï<ÿp ÔÄ$´^†B,Š¡ &sh«–øØòGâ;lUT\–@Ÿ>ÓBÓ’¨ÈSÈžaÓPa n€ò9xr¶NŸ½ù0/¿Wfßò3ebæu–•c‡2É&¾iü/òw_Á|Áv—I¼Pý‰!Ç€rkˆœxd‚–‰«„j] d*šd–ƒÕðý×;ñ7›>­F¨Ç·ž~]þÛã$²Ê öm—][c¸^ƒÑñO à &˜ÊR¤!HÇä~¥"'ŠS‚ýŸ?Yõ?!ÏvïlÈÄö|Oíñ•‡Õ1†U{“=ý§Ï>-`~Û[bãˆÐü¿æiýq˜}ýü}—\_§.iöF˜Ä›4ÿ}´këvãh#E°°€Ó<·NaCy ÛÜ!§rÍ=¼úñ(Þ7’Ÿ{"oéqú¬4ÛL~ܼºÚ[¯ö=hú.ë¹»«®Ní"»aÙäÔ1ë^,y³e*bgqöíÚñÙ…| °Ð4 †@àÀ—¤K€tÀ °Ð4 †G9Íïp€bªª©Ðd4`J®s|¿îÿ;ÍûÚÏu¯nW^¡Ý÷©Þó¹S{ß7±Œcb…SZÖ»IJÉÎ÷½ã ‰|îcÆ&oš‰™ˆ3G$0äÙ¬6hÙ†ÈC€ÃAÁ³©¾c}uɾo•Ôªív޳] ªZ»Î뜠Ö0qѾóœîsžöc8ÏBgZÓu|aJªrŒÂòñÚffc*vV'*ª³­jh’ôÊ¢Žsš¶ê_³·C9Åjõz…[êz%Þîé!&d̤¦‡t'e®±;SwlÁ¨ï­ŠH:—u¦,Á„`šÉ– I„‹m7C ë×j<¤w×Z2aö㠃Ɩӕ3f£‘dp~žwµîôm¹>8àñ s¦„ $rúëäå¦Ö~8äW=cOÑyá9?|¦™Ô&I¢’:(%g/Ö#:ò&šgdëGiÄ?‰wçßɆ̈́Á®Qù×N×/×wwww2Eã¶$WlUÛm¶ÚYl„$¬U¦Ä9h6ŒY65%Šé­Ð§™ÛÇ6¹Í¹ÝÁk”d±£F,jææJ<»«ÎÚ6º6"F#åÌ„”DIˆƒ+šåŽÛº·6åŠææÎÓ‰0:aìÎpwlºöÌìÂþ·+|T0°,åˆÈ @hfX8²Ì-‡K–"R\@P¥®‹vÆrÐd †‹jËÃ.ÎÎs›ÉÛtà ¥®IþCÞ÷½ï{Þµ­ €é‚À´)%ÂÐÛ$ ¥Ó°´µ®|ó±»Ò—c1±ìûöº¶Ûm¶Ï=—½SÞï/œMÄô»›gXιT—ïí?Rwß7ŒÛçÏš|øn–c÷Ͻï[ýÜýZKáy1‹S9Ôp(¥ïn!(â®:B8ÂY)#C¤RŽ9d àé%N \â>}ý­ÿãúÝïy×Ïái>Þß×ÇÍ|ª¯ßøwñ‚÷£¦÷3*^Tš›´M·¾çXΣ´Æÿö3î[ÚóÆàÆ?|ûÞõWï%ñ‰Œ^­|_2øÍñlsn S§šÔRŽ©(äa, Ga(àì”r9|­ÁÀy¿^Óååÿi'ok÷Ýß>ýýwôÀÆ0bŽ—Õr&)­çX΢¥3*pÍY¾JØhcsëzÝ»Ow]yŽ'׸÷´»hÖÇ?Ã58„ÀpvJš#²»ÁÙ(9ª)Pàí¶!ÁÙ]€ärÉGzòóë¢fýRäiÎ=8ß§§¯`c 1GKÊ›‰Š7c:Цu•-¢Ý·v,Æ>çÞ÷ª¿%ñ/ij˜¶3/lGa(È:ã£Pjý¤ pq·’R¦¬%gNâB»pvÛ|Kç8‹zÒKHŸÏú´•y~mßµ÷õßÓßg8÷½çžËÞ¯O'¥ègXΣ²¤gY¯{M{’·'½!¡ŒcóÞ“ÞÝWÙ{Ëâ^¯‹æ^Ø—Î$¤#’’1Ùîw§‘J9–J9ìÑ3vèr1E’QÆÓ²Pq ^݆³¯·ý­kÞùüs¿ŸŸ®ùƒî1ï{Þyì½êôò§'¦Zo:Æu§1D˜µl“» c}÷½Ç/º„cÜ®Â2A«”„m»‰G â±!J8“¤H:wÈ”£€ì”pv)GHJ@ŒãžÞÒ°ò ñ×ÝóïßÏ”¹ùŒ{Þ÷½ç°÷«Þîânza·3¬gJ/ÕÝ»H41lbÏÏ{ܪù/1/{÷RŒƒn‘%(àéRA·b©ÂU,ZwÈJ8!(ât’—ů™Œf_Æmz«Þöë콯Ík|÷¾ý¥Ï¸Ç½ï{Þ{z½íb^vzy–ó¬gQTº¬èØhc}·½ê¯’ø—æ1™|KæšÖåñ/mÂR¶î[„ÍŨ¦;»ppIGÕ%¬$’ƒluoÉÇ—}ûüùùùKŸq{Þ÷¼öõ{ÚÅäÄôõαER¡Ž†ÂM c¾÷ª¾Lbò׿&310ÁÙ(à:IGd£PvJ2©ÇF§“™&c™& $É0s÷?ßù‹n^s~÷ïß×ê—?Xǽï{ÔóÞ¯OjØ–¼¼¶&dôõc:{Ê1'Cv c ?=Û²çžä#OrQÀuIG+P!%RRY)#mØJB0jÉG#—‹pOŠy;ÄN([´ÛÆYcvQQ{T”_ϳŹ·oˆâòX¸šv´* E €ßÞca‹d'[‰lUR ©ñÀ6-ôlÜDI@§ ‘$ x= »è{?oîw¹1Ý8œýjD°V)¡¾r?ßÿwÞå¹³e$ëgÏ,3øüQŒVæh¢)„›x‰ÁÛˆ‡²P§ ǽÐÃa(ã–¦LæÄÎÍÐ-ÏzâºÑr4qsÔNí½?1Ød›üïV€ü4Cl9]ŒüÙd# EI3Óz¸žþÏf¶þçç~>‡á6Vl¿ñú»»ßü~ŸÏ©±¢“R(lÁº,"Hiç\«Õß埛Í|MáL\¨é>:™ eäø°²(5¬­ÙòYA¸4Þ?Óh­äýã×#Õcš@飇d&ä¼!,c¬ŒN²0ƒ@†Št2¿ÌþÏÏüÅïùùù_?/ùùû¦pd † l2š¸ ý¯½ïyëûÞLàÈ hÛœç7µÁ¡Mƒ ª®ç½ïN¸È)ܽïg{Þû½ïy=îfµ¯nW|¡Ý÷¦÷½ÍkZÖê ç9Ъv²Ë´¦óGjv¹ÎéËÕv2—!ÁÑÉÁ£‚BŽL0ÎŒ!ÎMI™ÉkLÛRòÚ“2¦%åNÍó®ÚUÚíUÚí ¶AT‚ª–®óºç(5¬ät;Îs¹ÍóÞÌkèLçZÒ÷)Ú§;Læ—Ž™™™Êƒ²ªsµU73½înJ²S*Ї oy¾÷¾U¹]œÅó›æfýÝw]«_þmþ'ûA£Ñò¹21ÂO½ï)¯ºO®Æ§¡A¥%M¯ÚýoÛfV´>ÿr¨}ƒ ¬Þ¦!øÛçF„8ñôhìÍ@$2=ô t!oD‹.î¼ú¥@a²ip¤+D¤ÇåðlS2C&BL•kwkÎê2_”^yÝÐëœÒäÒççמ\5s¦À[ºé,°Xó¸,Å 6ñ¹nÌöêóÍÄÛÝ×wEÑdZ( ½ÃW5£]D]ÚÝ ˜l«ÆéͽžwLñ·Ûr’ŠåË–äD‘k“º ‚Ý.réåÝÚæÑ$õr'v@øçÖæ:úéE•¤'ºNµ ì²Êج uÁkf$¶ÃIMÉdZ"ÎXbD€‰Ò×´ZËÉ)\$$*ÁV\HØÀ,e`l±m]å¹ÍïK`%e¡e :aþçï{Ö÷½=é=iX Xbb[¹bU¤–“m9{ÎsÝï½ïRçõ±{Þ÷©ç½^öµ51==Fó¬gS¨Wõf=íW½ïoÃCÅŸž÷·Uö_¾;yþëœj_íYÆm¼Lf_Õ Pä²7Gd£AI,”rRX:9²Q©,”d}ï×ñâ³ÖÓÿ!‰Þýï_¯ß÷¥ËÜ QÓ9ÔEαN¬nQŠmfÃCÁùïZZõ_©{b5©(àì”ô”x¿FÝ”q©ÙÜ)ÝÜŠ§AÊäBK/‰|Û翌žßù„•{Ê÷Îwõïß÷¥Æ1€RŽ›š›—ˆ;ÜëÔêÆsY3Ò«v 뮢‘.ºòíÛž|ÈF5¥ H£$ލ¥´ÕRRA§Sƒ£ Ù*!(àêB’AÑÇFAÙ£R9d¤ {_=·{öÓ——œ÷»ÞûïÚ\cîsï{ÞëÏz½é¬÷ÓÆ¹™¬kPÎ3Yæ S|íp[#uã·`×<÷#$á*„q©g(2‰ä”p„£ƒ¤%’ާŠQÁÙ(àëëš¿ÌòE[η߿^^\ôÆ?3Ÿ{Þ÷^{ÕïvnjbLOKyÞf±­BÆs©ÊŸÔoØ×9êï¹iã#Å‹HýzU}—ƒÅ G å„£ƒ©IG+’Ž©(9½}9šòssnèj9-Áx9|ËÛöͱ=iëãõ%íºû¾>þ¿T¸Æ0 UŽ•—ª3¬kQR™œï]¾N[휽uÔ“®ºïؼrü=H¤R§#T%PŽ8U%PŒŽP„©ÈÂTb¸¡s$ªG*Ÿ#¸¡Å%NG %WÆ/‰›vtõ÷Õ»{ÌýÖþWß×ê—üÎ}ï{ÝyïW½oOUÖ5¥S3ŸÇ¼Ïž·µ'+¾çŒŒIÐ.ºóìrsá8¦JI*r8UϦf“‘Á$ RTäN²ÐI²QÀ¹.#”j&ÕrŽÊ5 ÆûöïßÌ9GYÆ÷Ï.Ý Æ0 QÒnfDVŒëÐfr¦ms¹gR92YŒ`|ôªû/15Œ_2öЧ(á\£…rŽ’y49¦Z5 å+”p®TätãÈ*×~{÷ã¿——]uÖ1€RŽ›¼Ehα­*™œ˜RÕ¸ì-Á•¬cƒç¥WÙ|M_’_6¾3kâfËÁ—VààÌ’A…’Ž6ʤ£‘‘U%+ŠIT#L*¼þûÈ6·ß]ûöùùøAŒ`£¦mii-©©¹™¨ŠÚ³¬k]S8S©²­ÅŒ–[Å‹Hüõ«/Ÿ pÓ”r TíNAªíˆe’Ž6ÉF1ÄÑd£cˆj¸èÔ’‚q A 0ê œƒŒË”)UX~g_R¯oaêüêI§X ½ÿççöFŸ7Ææsú§ˆ¼—ÃÀÀ„«WJʱ]çªû>_Êþ^—wÛö]O¥å{¬m$“P5 HñÓ@¢Mê¾ÞR¬s B«Ýä]F«sÆùKjþ¸é.rÊ+c9›žÍ]R8S†0ÓL!{G@åÜìK w`L&K®£ìq³ó§5¹î¨ïpûï™ñµÏgèö€G¸>ñ½AF’L`v’²"CÞÃäbÂİj-ë{ë·®?GŒxËã/£¯ÑÝ|/Û ûÜK:»Â&|àÈÝdÈã#mêfÙÄ™ÌÎf7ŒKßX¶/鉉yé‹{Þ÷=ï_Þ¦pd † l2t¸l€)p˜Á6mÎsšûß{Ø÷½î{ÊÐ ª®ë½é°€ \É]×{;ÞÚKK{œæ÷NgÚ×·*¼÷½7½ÛsZÖ´àÖs §k,’”Öê©UÎq;AJsX–©Ù¹yÉÉÁR¦ÎF80Øh†…Ñ£TÜÜÔÓ[å©U+²»*ª(  )Ú¤çyÝw½+À¥ ªí^ýÅVf³š¢&&u­/píS¦r^^:ffg*Ê©ÎÕVó½ïu™TQÀÇw;[¶5©½p²b‚œÊRÊY9U鿎?Aª‘WBwg"¸0¡ðÏ•+‡ÌŒDÍÎæ½Pª´Çwj†’ʸ"6S&W§µŸiç2„‘ 2H¤!*f3—Ý7ŠM.î}Þù-ÖŽm͹¬Z`<[ Îáλ¼ž@ CÇyÝyÝÝÂ4njì¬ËI´›^nÁ´mÙ”JI*Ù š !%Ýr“^»»“Îd»œF™™\l`9œ‚€œ‰6Ý„ `ž÷0Z"åÀ€€Ú0A+«* ÍqHJ, ”!0oÓrÛœ#¾*³-›è­+e‡áÛh[m–«ZÛ|XìFp²ed‚Í‹4 Y`Ù!”!,ÀÒë¤  *Ë„ÚÁl…Ø4vNÚsœÙÛuKØ -i` ,`.°–…Dòòv=§ñ½÷o|ü´ï÷òIikÌê¿???=øB÷”tÆ¬Š¦õ¬kAüüž·¼öýï[ž±‘lc~ÖôåWô á¨Oܹƒ†BŽÑÂÂ:8X£ áaâÌ!;Ù„ŒÈ(:B2ÉìãRø¶±/O“ï#ö“®ëžü}ñ Ü T:j¦§ff&$MbœÖ±­g6jœáÁ’É1ŒYcç§*¾ÚøÅ÷™/Œ^ù—ÄÎ$ü³ „ìæ1ä7f1QÑÆ; 0pÌ—?vôîÊ8]w^hŬ­ýû÷õú!{…v»*¹U1]˜cMëX΃»ï ·ÎÅ·Ï[¸¬}’ø™ààcÁÜY…¯0%Á¨fàÓ$y0³‘0S ã`ÔpiIî_íµ'{óçϾ!{…v»*¹UÌÊŒk&µŒè97{Z,Éf1‰µ¡óÛ7Ï€f°%i:ÂA˜¦a#YŠ\$k0& ¬pk1WG@Ì[í¯'9ÝûÞûô…î*3ÈŒQ­c:åSе%¹':³¦1‹Aóܵ}—†YFŠè>°Š<Å.:@ ÑsDX‹^0— €¤tuÊH2¼f^Ò֒ؽ푽÷ìę˽ï¾ý!¸÷½ï{¯'½^öç'§±“ZÆtªkHÃ[˜uÔ“¥×]xç¸ÈrJ:ÚªQÖÇ(’78xyM7¹ƒ*ï(§FÙñµS¥Åï-™ü?ÛdÌ´–“ïí1'¯¿ý~ߢ¸Wk²«•[+&µŒéRSQbJ[kØÂÆ$].ºëËŸ3¥®•B¸:B6WFGF Â'êèÕhkß(Ôh¢SDÕ³|ËÉ™/iŸvÒÒ×û?´äü×ç?·ìB÷ ívUwµ¸VMkÓ¦¦÷šsˆt®ºëÇù yúõ4˜7 ÉG[pda2¹ÙÓ¦tPì„‘·" bža†e[ÿ˜÷½ç)Pªr{Ø¡½çZßlo{X›o–0±1kZbaaù_ʘ™³Ö/ymcg\Ïf»75ÙÖ›žMÙïrZ×̼“7Ïü÷êfÜ¿~ýû÷ïëõH^àTT*œ¼Ü•ú¦ÛÞu­öä®÷·&ùÎIØufŤ¶1`ûªýZ^Ó7Ľ±|KÉ‹â^aÓs¥Î•ÎDåÒ¹ÒçÓÿé0ú4£MFC,+¯(­.ƒ¨ARež"€VNf¦kY“ @ƒñR=aß±JHRéäñ3þ>çÆ=µMŽt%ü׉H¶Ø´¤ arà¨o°3w©¶ðÚu\ÆËýg±©øü<>_ήž´Ðh0¢ë\tHX$ëªZì/-yàu]?qɬz`slKì#¦ïAã}· ô¶»”MÛÚµ)v¥Z$clR8FÛSËÍex(ÓøŽÓäbý³3‰Ïí³1GÚ(1j¶Û¬4È2÷™Ös3¬gX¶'¦-‰y/B<—é€a h Á€.2  € \¦pd½¹Îg†ëüSÞÝýï{ÞØÍUUV꤮sœäã¾ç9ÍûÓÞ­ï{ÞåUx;ÞôÞ÷¹­kZ:gYÎ…uTÖr¢›ÕCµÚæøáÒúó¶ÔÌ›œ˜››“²Õ2§&f¦åNÌÌLMÉyÍ÷uÎjüÇ9ÇhPPj“œïuÞôíñJéU]©ÌUc:Öª•Ö´ÅÇâ™Ò¯pÌų•R\¡¼ïsn+$¨!ɳ88Õ¼ê¢ÜäçVyþKÿ÷ûŸŸô~Uàý!´ÛæÐñWÕá) /Ç>Ÿiô‰œ.î„éÓ¤˜`l 2 éà!ˆOzõÔ¾•â0üN°’@é!^ÝÁ I m±^.:îêãh-²[źWÝçZ>îéÑW¾yç^7+•ºîÕtÚ6½ä–—ù?£¿ÒþÓÓ¿?iœÆñ_Ó¶v ÷½oIèõýï¤Â@‘gȰ‘¢[D$l2äƒ @:^ÂÀ¥ ´DZË€²Ý-€È5ÙÛs–ç;'PE‹X°YešXFÂÀ ì. É~å˜ù1lß;{Þz½À¥B©™ÉÙde¤æ÷ks¦s9»å~à“2o|éÛCc:»óõÆG'=\Lc2ÜãTlf¤&4 ¦¦-\L1Ì ¢Õ—†8š˜Æ//yy1ï?1mߟ>>|üü¤/p)Pªg²òñ“ZÆy¾˜äæ7ÜÚÏ6éÛ,Ç]t@!]uãk\ù Y’Œ*N K(ÊU(ÊYFRÊ þ‘˜`LÚ²0 Þ׾%æ6¬cYüž^·ÏùùùH^à §51"5¬g»é©™¡%7Þ±ƒ¡$ Bu×K®û\ø~Œ¸6ò©Aùɘ‰S1åÂÀcaj”epd¢”i8^Ò÷Åï|Iy1oŸŸ­[7çççççãõH_î=ï{Þ>ñîI¹éæ[Öµ–úrjß©^ö'¹ÏzÞ÷L¸‹?9ýûò×ý¯¼î}Öeååæµ&3/lÚóåò5[q0n¦Ýñ—ÃÖãÇS1Œ^Öµæ7þÿßVÅû_¯×ëõû~© þcÞ÷½îÏ{ÓÞ=ËnLÉykLOOÞµ¬·G¹Ù«ÛóçÏ“›÷Ï’-o±…—¼°Yý{I-%}—·Õ_:—“YÆF‹’ŒUÁ¯KÓcXw@ ˜5x”h® Ž ˆ3¿š,Uïž·ãÇŸŸ=tþãÞ÷½ï’KKWÏŸ>|÷¾ròóå¾ ëSYo¦':ªûŸnož·ezÞé‚÷,HïÉyóØÌ¼Íñ“½¦ ¿vQ¢ö”j¸0Ž [f½óïêw—ö»Îþ~¿T…þãÞ÷½îûÞ÷‰é™‰™É‰=<9­k5¸&/›Îvæþ¯)oÛóñ?>WmøüT‹¬¼¼YaßÔ¿ð¼ûy™y›æ_2×¼¾+§Mw×¼˜¼ü;É.˜çK˜—¶+}ü3ùwæûùùúõ!{€ ¦sœÍD+MkYntƵËÿ Õý÷æ§ËU[²>Z|õ.]t 뮸òÝÁú:::ëìðepdpdpdT”u·‘8˜IÎøóß¿~;ñÏ——(^àª3&&bMkY©µ5~sZ¾·§;îÚyïRååà;ö^òöùk^b^Ó7:››»”ŽtÜés¥Î—˜û{÷½ï¿z]¸÷½ï{¾÷½â{3SÓÊÓZÖy7ÓR_<Ô}õµ=-ÏvÕë{Ôµíböºë®ºëŽã;¸0Ž GG2)D©%¦Q e+o6Œó.Œû¼í¾wÿ߸é²tÝGuÂá€CíàŠZP«†˜EßK¦W×®UDPª /àºüdnVrñ^#{Ï•úÜPCñ=_êÿ_‡îþߥٮŽÚ¡jêîºÅª¤°?2*_öF0¥!HAå¯áñþÊߥá>ïsö)”X`kð>€$ÑûûŸ“Ï9¹c^)wWä̉äToÖF]Zr¸ô×ì¹üÝy²6nAêÚGh¢½¡‰¥csJåˆiu×]j¸•톂)p˜Á6°ÈÒæº@¸Lu­VØà UU]çLŒép B¹Îsœ»»Þ”wYÖ»9Ðoœàç9É­kZε ë¹i¥õ*ª®oŽÍrüšæ/Íjr^njT©RZÉÉÉ™ÙS˜•&fœîùÎ_|ç+µÒ€ªJP)Jç9Þw½9{àê»]¬ß¹íc:Ϊ‰|dܾ(âœ+˜—¶ ®v†÷©½¸¬ª tV5/jk[ÖØìÇj·›÷ÿîÏïo{Þ^òÿ1óõù'òMÿsݪB>»:q9ñ5Y¢ö<þ½ßbE¸×_±—Ó½¸33!kÞyWäo$U­x¯%kÈ£E¹¹Š)ZÖéWˆˆ‰dÚLˆˆ‰.hÕ¸3sZ¹\×YÍUÕ誢ՌTX«¨­£ba&H&f€š¼7;í7‰Ì-áHÆKûè‘b!û?½ïzÞ³×÷„°·LgÊÈ$lEµ- ÐFÅ£0X`-K€RX@.AaÓ×mÞsœ;nØ@‹a` i»´€2‡ À^[?Ï&ý÷˜ù›ùñóçK±þ'÷½ïwÞ÷¼{:ôžVšÖ³®t~Þ®êOÕµòoçÎÏŸ>[Ô¹{g¿d„û|ï%âéµÎ›—JçK?ˆñä¼Åñ/1|KÉVq?XùóßÏŸ??:]‹€ TDÜäÌÌVšÖ³©ÉÓ¤ùŸ=î×½êéõÓCétuÔãÀ×vA¢8šŽ Ij85Ÿ·”j¸5‡üµã'öñãË·.ÅÀP¼º©­k:tÇ÷z÷ߟ=óç_$Ÿ=R.Z÷%í>Kâ^L^b^[ø—¶9”j¸282nPeq2HÁ“¿¾³Ë?=ÏʯϞév.*›ˆ——Æi­k:tï_}¯oÞ÷½ê²åîH3êü—˜c6µï7:]øîòo.t×:\é\êö˜ïø¯Ÿ­Öq÷ßkïëõÒì^ªªªª»Ú×'d©{c=­kYÓ§*ϸ÷·ï{Ö÷ªË–½ÁßÉyòøŒƒƒ'œ©·\=IF^‰A—´©–KÉy1¬fKÚfkÛŸ¯Î~sççççéÒì^ª¹Îs{ç;ÉÙYšÖ«ZÖ´é©Êþ÷~û¯Ÿ-ÚùñóÕeËß®ºë®<†Ü<áS£#ƒ Ì£/2—™¾%æ/‰y‹â^bÿ5ïÖu÷X®}û÷ñÒì}À×{ÞóÌ䨼ÇkzÖ¦µî•Þ­÷V·µ¿{Þ´÷ªË——;ò^|’ø—˜æ&eæm|KÌZø—Ãft®¥Ó\é·.šçJï¯Ìþø¾óq÷Õ÷ïã¥ØüÀ×{Þóä†;U­kZ÷N¿Ž±»ûõÏ[å¾|§Ïy,^ö ïÙyòø—˜¾%ÐOiF^ÒŒ+ƒQÁŠ85Gbߟ¯ÍsóŸŸŸŸŸ§K±pï{ÞóíåáŠ5­kNœY÷ÞÜž÷½o{È^å–;ù/>_ó1FWGÁž®¦Q¢82ºèÔx—¶/ùùÏÌ~~~~~~:]‹ÕW9ÎMï’jrUc5zÖ³­:s·çœ÷{ß{Þò—°Ywì½¾\ƒ<š®MJ3:5Ž AÁ¨Ì!…0† Bˆá¦”hBq(+¨ËÂB;-×(¿€ü*Æx¦¼}­ÄzùSM0Ö=¿–€õÞýÞã¹1_‹ôÙw5eälû[ŸtÝðÎúò‹Kf)ö¥â»>/Í?dÒgìdcwó­DrÄA´Ó%•6WZ£.Jݵ~ÓPÓ+ƒý›?7páýÆŽ¸=ìU±êH25 öeM”âÖØ¹²©ý¯~|ùóÛ¯ž¿Ð†¸LàÈ @Ød évµ € \;­kT¿ pè»L@àÀ—WyÍóŒw{™ÕUuj§@×9Â÷sœäÖµ­ 㮕¬i 7P®ÕW{Óªs¹Ï/Îɹ©0gD9:FŽŽlgF4AQ!‹Ìæµ¾ö¹Þ÷½S´"‡i)Ú S¼ç{Îw§ovESŽÕw5½c»íc:ιD¾2n_qN •ŒL ^^ø(:µÎÑ­gZ”ŠÊ¢è¬jc“–ÅLvñ‰ÈÏþtÑç32FIõ¸G\dEÙûÒ¡D*oÆã©ïcŸ”Æ£æ»-1ŒUs‰[9ºÔnkšÆ9mÝÛCˆfHdô}]g±IHsêÑ›M鱬,²Ë)bàY‰ï=ïO{Òy=éZ# lF–h ¬°pabćK„Iµ– —@¶û-9ÎrÖ´E[¶Ar $¢ KYÁ±`…ÀÈĵ¤Ä¼ŒüÖ3ïg¾÷¼àÆ?¸Ènª«½¯o—‰æÍkSZïaÏîýïÏŸ9oŸ>|ùï!{–ZÇ~ËÏ’ý.t¹Ô¹ÒçK¾]äû¼—:]|KÌuùÍü×Ì»óç×1£=ìïyÉßMNÌÎLÉïoMëZÖ»Øg½¾{CïyÏvO{Þò}.ºë®;Œï’ƒM•Á‘ÄÛˆpäb$`ÜÁ‘ ‰Á“~;ç~ýîûöùõÁŒcï½ïjªª»Úî÷=íSšÖµ®v±÷Ï[Ý÷½ï!{Àw伟%ñ/1|KÌ_òbðiAa‰ã¼ïßWçÏŸ>¸1Œ}ï{Þs¶©©Ù8íoZÖµîÃ6^]o¶óÞí½ï{Éa1laaß–½ïò×ļçK.t×:\ê]óï%ã¥Î’L[ïÌüùÜüùóç×1£=ï{Îv¯¹©Ù¨¾5U­kZìô¦;+·—cîµk{Ý´÷½é|÷’E‰‰1‹,;ò^|¾%æ/‰y‹â^bø–dpdqLqÄÉ#Cn8›sÇ{ß¿{ßçÏŸ\Æ>Œ÷½ï9Ú‹×jµ5kžGwžw‡Úß*wÏ{È-‹cw伟/‰y‹â^bø;ÿ¶òò×^WËóóóãƒÇàjª«½¦¢b»WÞ¦µ­sÈÆç9‘ùÉÞ÷Þ÷½éű„µ‡~Kϗů{áÒçK.t¹ÒçK.t»ìû¯ŸŸ>gçÏŸ>¸1Œ}÷½íUUW{ZMɉìÅ7©¬ë]ìFó7X¦q-÷Ó½ï½ï{ÐI‰11a×Á‡Âö¸™’1&G€Ú$y„£jS¥0*S”À©L ͬhÔš—hÑ«Ç‡ý§Ó°`‹[ÙSdåxŠ€+¯:kQÊŸŠ¿‡Ç…Ø¿ö«åï»™øé~†2Cm)ÊÓ±9e¡Þž#ªœªîóVŒ¯ / ¥"“5Å 0Âé´ ãL¤EoP#=š$Ê¿C¿?|TóóøË2þ{Ÿ­q¦ñÁ„dâ)·Œ+s$ìnfÒoúŸý˜×ÏŸ>oÜùóît¸7pØK€tÀ °Ð4 †@àÀšÀ8RÖµª_€uzªªª¥. a80sšç9Íïyª©–µ®Î3ÎqÎs“ZÖ´/1€WUZoZu)UR«|éA¹«íë›× GAJBŒ…6.@Ã3-y‰73Ûš—•35&#›×xìç{Þ÷ªªÉJUR…9¾wœç:v÷4v›êýçuZÏwÚÆµv‰|e—ÀtàÈÆ&Ååï…¨Á(ÔÖfµIqQP¬L¦³5œg1Þ×-‰ß³ºä¾·‰Üoâ=þÓ.2ëx>/À¼ø^ûÝY ©Tu¯eó¯î7ÙøÀlg×·5&&3»[’¥¢F,-ù¿èüýùÿDDþ~ë[®æ¤ôX[ „N¥—,¨…„€G÷~÷½ï{ÏK¬Y"èńYdebÃa«E†ìÓ rÃH·K€R,“²nÛÞ÷i,²vE 0Ydée… ÊÒÍÛ‘‰‰y$Üí¶ç?ù¿·üηö³_}÷ëƒÃûß{Ùªª®ö½15mÎMy–õ5jºŽóøcÞ¶?iòsç¤ùóå½ïK¸;öן/#‰‘ÀdpdÉFWL”e²Œ™¾//{cççÝ}û÷î¾ýûæÆ1‡ß{ÞÐ*Œ^yF¦³­tLg¤Å¾úzÕnúË{Þô/{-×]uÇq¤wpdpdG¥ñ/-‹â^ؾ%äÇÍ}û¿¿~ý×߯61Œ>ûÞÍUT®ÕOKÉy{ZþQ©¬ë]„5}ËÿeŒ÷^÷çÉ»v|µ|ùïzBKÞ ïÙyòø—˜¾//yŒárä\é»gÃÉâé˧.ŸŸs÷ïߺùóï›Æ}ïfªª»^nKãÑNjk:×H¬bF_}=é·½ïz Œ[iß‘ö®œºré˧.œºré˧^b_ÏÏ¿u÷ïߺû÷Þlc}÷½šªªíVåç¥í4jk:×I”}=ÙÞ÷½èYŒ`7ÏíŸjé˧.œºÎ]M˧.˜¼Ä¾/1/‹ýùŸ>|×ÏŸ>¶1Œ>ûÞÍUUv¦·7&mÉy3*O{}ßu5k¤Þ÷U_yÎQé=îÇ]t‰'].ºýÚçÀü& ãM¦Â2í{^×—µíy‰|^ÏϹû¯¿u÷ï߯Æ1‡ß{ÞÐ)½jnb"÷ó}榳­U&5U_[‰õ½iïBËc ÷ä¼ùy‰|^LKâöľ/1/†A¨È8È8È8È8øëÇ|½õß;öïã­uÓÃï½ïhÆå­/-©‰‹"÷ô9Ýk:ÕR^k´¼Ãï¹ê÷½ïz [,wååï>Iy„~uàæäréÌfRf}W>ŸÙþ¯ù¯Îþw_ŸŸŸ¦Æ1‡ç½ìÕUWk3sRòÖ•ozîµj©;¾VkóVÚ[Ö÷ –˜¶0XöÖ¾lûXÆŒk–+˜Çô·“ůÏ׿?šüüüý61Œ?=ïfªª»[×%IïeÎkS:×a9–#þú&=mgõóçÏ|ùéiïzìZ\>¾Ú¾uö>÷â*éÍ1tåºc B”¥Ž¥#@” DbQP+•G à Ï+âXlvÎzØ’g²k*U€ª›š{U~ò¸ èQ˜ÄÌÈÓíZt9K¶O¼<í‘Vµj|Øý²Þù¶/ò)Ke8ÕÅpõçewÓë*ž&{pŸ Uܼ‚&Q·moËz|÷ê>­í4¾÷îp6€ê:~ç¡¶YÜjk¾¸€¬wO~6Δž-.¬{ªÈ\€Œ2ŒˆÂ)ò0ˆ@Œ]fЦŽ²’)'cB†•8dTjvú@Bà°Òf…¢Š‡øÈ-ÖঠƒH¢úÍJÞ ƒcè¤:@!iCA½Á†P§eÛþOð>Á°ìr¿Æö0fôÒ‘3T"„4ÚP1¨ UA¦Q¨5 ‰"¥"5 V7J¦1PkúØ`™€½Þ]»)¼º’—–'D¯7S”!Os‡Ó­7DÅŠFâƒTLL¬t²Se)U(ÅDãt8g—ÙÚцÆA•C»(0¢£AA10f ©˜â„ Z5Ô E©@gì£Ýwú¼Û|¨ÚÃKAÖU4# ©kl 2«[âaE1¸ @‰Ÿ€aV m´1ŒÃåëKFh¨©4"ª F4UA¦FßU@ia¸´`Èœn,Ø»VÃ`œ .’δl!ÿOßýUA¹y~'#íßןíÿØþ¾¿¾Ö?¹Ç÷9þ•_uîëkUœbV·½N9fý9ª¬F÷´¬»ŠÛbù¾·Íâ©\¬÷ºäªÿrÞ=w¤ã¹™¸œ<ÀqŒ„ sÿ@„‚)EÄ(¦6fSõ†ã`ÓrF!½µcF“m#Œúb­16ä „-@àˆ iuÍົ»* »²ZÕûûP¸ƒ¯ »†¯ëvß³ÁT'ÖsrÜn“0(C}åh(C†ämaj™énbâËHêÓþÎà‘fÿkrS­šØœ-Kàsxlsp:öncƒIÞõW˜óº¼¹³=Ç2ëvõ½Ö™óài’dêÛ¢ésGÙÛÚêæžñö‡öœ}ïÑþ6Šósú7í¯ÏU±¿¹¡5÷òkawQ¨eÞ»-¬š:höq £éuзíB_ׯ d Ô…F¦Ö¤ ˆ2b:±7^]}§íæX·ÜvrÔ/ïí}«qp˜Q&p|óæÛ)"ˆºÈ·l·æž,\«´CÞVÅzüߌ¿ø^ãm‘‚Û“}ËqhIuöjlŽ öÙoº&S¾¢Œ„lêXÍN„êºeû]¥{¬Òzá²õ´{î}“´÷ŒÜõRÍý–ÃJBøE@ä¶çm#]¬%ÂyC‚i-ˆ¤ÞǨzΙ¢™!ÓLì]so–™m^v—~G§ÿ«È 92ãGGYyWtD5癯ü›w&BG+rÖz%Úõó>`Îò£mAµ6#¸Çp¡£ì‹Â¾î'€ðlìèÀ?âu'«ùK¼Àá¯%ê–½ÙÌÛ7fæîèŠÔbíÛðÆ)CóO†™·Ú7=˜_£«,| Û?v,4öBùSÛ ‰!„Œÿo¿ª„åKoÍ’» ýÙ“iR_WòfY‹µÌq&­vlnîâèÁEX‚~ŸWØN¯”á±_þª—.ØÃ[h· ÏK¶;ÃÕ½‡;ã,Úûzšß©`«NœeZ¯{÷ÁVeÅJHð”J{“Ô²¸{öOÖí5îäYM¹GÒªâV×]þ¸]Vc?‹ü5›•ôÊëܾ(í0µÞ³bóv–»çli2 N¡ ‹ÈAãCœy«$÷)®Q÷­‰”oW`]áD­åJQP¶å» ¯]äô iˆö÷½›µr™žä:5°yÝi{Ým‰.÷’Bowt Æl)”¸+…Ñ"SßämƒŽ;Rºê½³»Æú†ÕiµóýO¹®ŸW²k¶Žmå œ4ÏJÙ;]¼a’-×qŸ·®¤¨]½ÈîQºÙ&DˆÓXV/ÞïÙ¬ŸHè­ÿÝé#~ÙgNT¤³å ¾³¶;“e“ß°ÅÖ†<ç˜û<»=ùR…a^ùs’ÈèÙFÉo†Ø—“ÂTãJô*VêÇÑe¶ÊÂpt?GÂq’ö!Õ+犤–ó©B;0“‹ã´äN*¢ÂJ1w† n\µz›e%a5g~wñž4ѱqȨB鯢×çöͺ®ËsXýµþúî9~±¿ÌbÝŸsžëõýŸöÙ0!Ÿ 5lxÆóœå¥¸ù1‰4zÿ7ž§Ã^í±…ÈׂŒ‚ š‹—œvBTê³7y؉œ5! Ê,¶[Êyz^—[dò„)ð½/£˜ÇÏgç ËsAé!1&ê&ÞØÛf5—=϶ï¯N.›ò˾»©Çn/»m]õè£Éúåd°ê²ØYt#k¸Q1‹±9BÔÉ)':ÆVpF22 9È,ü)ø\ÇØçÓ9¯Çº”ŒénÉß“–²Ç*Ú¥†7×Ya†)K<í•íJ½(ãæBø×~WçöÎ}ï*Íw¿ËŽ{^Çædíç/S™Ÿµ÷7ÞÁàïŽuòœ¶Ï;±­4ò|nkñžÊDØUK:Il¿HDZÖÛ3ÆzÖµì¾à±"¨ñùŒ:Šh¨ 7 ÈŽ"2%Ðám›rÛ”cH"Èù:U".*ÏUq¡´r ý—-Ê?|þqÏ.ËU›“–<þ×VIÞ™ÏËÑŰ–Êĺ9xw>\F P‚“Ê·wŽòD²Å‡€û&³ik‘ùߥù?©ú|ùU/w{,²rY_‡V"P|'®{æmÛ %çÒ\xuYeô„:ï³èß :ß21²!o· "1‚§>êâë8BruÂÛPI",:+¶(û`ÐÉA‚d˜"¢mƒÆç»{ç{à›…PÃâå«íO29 Ä‘7be¯±$¾.Ôw"á¢/GèÕaìôÓ}>ö,Ü[‘°ÇÃ8Þ™3GB•y«ßÙž;"1vAzÙ}ãÁ-²rL1î3 ~W¢p™º$P¢£F`Ä_¥¿Ü곃ÔÙŒ¯V5‡-ðƒX%È…×Oi4®Š™ åZFìxÖ«vsòÒÍ ÌÃVü_*òŽ™ç¤c¢‰W:%OI±ïàó­M¶óŒ¡ë¤{^HßaKå›ÏŽåðÒZ_cU,}±ŸÐ×Ó)ºXêžGd±¾³· Æ:(–N±½14>!º#åZ 0Fô¢{õ­xK}v—K4U:qÂ[Ì"do•¶â¤Ö\é«EK)%c´÷îÆãiu󻧉 áÜ&t ³ež×Þ¹Úõë·äeêžÖ«d°\.ËjNY´“ e’‚6§-Pò㻵™¾  5oŽV£H:P ¦|Œ:ëÝQZ Z‚àw"™ÿ‡ÈžŽ'ÇÓ§]@%ìó³Fá[ýpÑ_$ßÃëããY®³É£"ŽÖ b Áœ„$òyͳñþõúÓÚ‹®}Êý·mVØPƒ$‘UNôÚ_Àâ;`#N:1îDDnA7µk5­šµ–Õ¨Z¶"0`ˆƒ"£%€ŒBQA4šMƒ& ‚(  ƒV±‹ŠÀ“0Æ4Q© A°Æ(£&ÑVÖjÖ[Z+b#ˆ1‚ Š2PÄ%“I¤Ø2b"Š Ð*Ö1b±XfØÆŠ6MA°AE0ŠHH" À†nlæðøšûô›g§êsT•1Õvšº[MLûEWF̼®Š×Õfj›ºŽ›FN᯹•Sm‰Fa01/³üŽü7ç<»gäýÿ¡éÝcn§Îí~Nz>¯vG§/Š˜mÃ)ÊWÙHšáHî®¶ßê©^þèËêí£söïõÛº÷Ï%M­}­2Øèëû̆ÖÍeèPâ£DX¨ŒU€÷§Fy§îÖ}±×§Vu‡Z}É×aÑŸ€|±8gFœQ‡€ö$@GÜeÃðo‚@6pöCè“áÈ: 1â|ñÜñOî8yÃÊ?œþSŸêá" ‚tI¢#Ë@ ¥ù›Eô^°¶+DZe‹-QE‹6”QDX£X±TV)#lš±­¦DI©1´šÅ¢ÑjJ¦VбE¦Zcj-‰¥RZÉlU)Z6­Wµ¶’¤¥­ºR–,VJIK6YH’¢+&ÖKE!µ¤ÛL«)VÍ*6É´[IªŠ¢±bÚµºmª´ḇmF£coÿHEíûb•D@¼ˆ ÄÏÒö:|k®¢`"¹¢)’ƒ /{nÒ€µðÑ0‚H—4Û•ÉÜvT»¢ëuÜsµ†ËtÝ1Kn5s[ókm›DBE@¨‘BÁëÀFÀ#@#iJ ‹BPÀèËD\V#SA˜T”hÉÅ)5µ¨ŠÆÛej-Xµ†D`‡ªçŽ–@n  ,µµ–4ÕRŒÚµ–¶Ò¬0bˆ"ÁX  ½OÇþ¯óèÎŽ"£›Á”€Gw‘õ,È%`€… t§Üê5QŠsÝ“94RÚ* MoM¼p•5qÃñ~÷ÿ®×A–!$„—úo;ÔòÿÍã™ó:¤8ÑF¡#q0B¢ÑëcÖÅIn ¡êâxÏnx #Ü¢ˆ¦``à#qà´UAÁˆÜ5B"„U€Œï‘|0¥°1U ˆ$¤A–'UШ‚-(‹pÀ;A'‡,0¤†øT•GdR*g ¢ •EG¡FƒÔ“¾&PÌ 4îœ1ØØ¡í¢]Þa¯ë½kô2ÁÔTJº‚'šjáêÃ?[75»»W{“ÕÝqt.cO ©á(7® 4;·Ha±Ûº8ýn¶€4OÃÛrÞ &ô¡šÇ нÓ -¹À·.é£à8;4&·æ}[_£hãDé¼)T=Kq!Ã>(!ôË©¨ÝÎW†`¥V˜hS¢€ ¶XÀD‘LWŸÜy6Úôö^—”s ¿«éIJúu|¥=¤ñàs D@8 ê®Mò \uXÀ6 Ó‚R˜UKE‡H¾‘L„DÔ»ÜØöÆWT_Üe»ÇwÁZ÷”ú½ž=ý…è_Îs‡Š_Î$SI  Ì`¤™&f(˜ŠQ)Ûùüà¿ai~ʘ4N X2/Ï~nRÎçqÅä={–8Å@7€>Hùôø@#ŠƒYû Š€@ˆ½Hà>OÛ‚Ž\2`ù #@#ÕLEfå $D‘ŒµXYñ€-”shÌùÅQºÈƒÒÈ#G]T/oŠÅ¬jˆÕE±Z0Tb1hÁj ŠŒÑ´i`·Çk Òk%Ji5¤¬‘%‹E¦dÛ2ÔZ)6Åf%#)"É%“Zk(ÖKdÙ*Kfj5I’¬šI‰I“@Ì›BR‚Õ$“+%‰5&E6)0Z˜%Œ™”–Ò¢Ó)4–’´–%%-©#I‹B2Él‘©™±$Á5‘4ÌZf¢¤²L©J’Ù1i-Y#S-“Ù6ÄÍ’MX´3&ÔʱhÖSlZÐIZJ²Y,¥jI2m¬’H”Œ©6´‘£f²I%™¦kZ-µ›d´‘2dÉ‘$’Û!2ÉY+A¶’ªLÍl•IfФɴ›&¬Ò’‹&ÊmfjI+3R"³,`‰5ä AC ¬DŒ‚¨Ö6™Z5£IбFɱfhdj0le•²h³&ŠQ£Iƒ¨­Ñ-²¥ˆ :¨°(â2€\\`cq! ’0@0ÀGTvr¨d»VÚ•k55$ @$$ 3 0 P jÍjÀ3$ ¦ÐÚm 6›B@$̈ŒÂ3 ÌÀC2@”$$$@5k*ÖjÖU¬­²¶ÊÛû Ì"Øb‚PÄ$pŠ äRE‘€†¤ Êa3› #qÝYt¢o~|9Á‚.’(# ²VµøšÖººÕ­ß_H0,ÆÔ Üw©!_(0F­ Òf’F4†Æ1³`F½÷ïü·ËÛÙ3- SeŠüësmZ5jËëC>K«ºòÞv3yÕ±¦DÅb4È1J+hÅÝÅ„mdƒh®%"bj¸Çbø€…J}ãÒ—Ñ1šÊ)çÌÉ<ˆfÆaþ_šQ³M‰QiŇÌÒCŒ>%õÄL·µç–Å ( ª2 ñ^e27ØToA‚(ŽpЍƒp<1×âD™ÀmöjÖþ"­ož¤BF4‘Œ˜Œš!2Qa”&É hÛ[`Ûj¥m›mY©‘$DDc&#&ˆL”Xe ²Bš5­°ˆ U´¥tÀFDY 2  „‰™’` $$€ –R™€€¥& ­¦ªÞ¦ p>ˆßª&*•vÔTÃZªþÍJ’¤«RI­I,­dM”ËX¦ÚMZM$’’•ˆ¬²©,¥IT•%–KKJYYRVÊIIZ“[k)%JhCkÉjÝij–•-²ÖJÉl–”ÚÒ[JIVJ²Y)$’ÉblÚËe’ÛZÞï®W×ïÏ­«M÷:nš!®­Ì{«c¶’Ìb 0!BA´3êü¶ÑVùõ«ª*Ò–ÔÚ”jB(Dˆâ¨YE  @Q€‘ ¬•N £€öÂpU6”΀Ñ“‹Ö€ä@ Ó¢ïÄÑœQ™@ &¼ ‘KòÕ>ì/6Û÷ú¸ÚMÂ9æZ_¨ïn{ÞøðÞÏ#ñƒ_¬ÐN³îRãg§ûw›i,¤N?Rùÿe“Oø2„‰Þ¯qÞ;ªÖ·hWòߟYí‹gø<Ÿ$ÿGØý߯?ÿÏíž~ŸNª ‡Ç*%iV²U¬¶•k6²­eWøáèd$üú7;Ϲ0Ûqÿ=6´ùyºOò—üÑ Æò™IÎÖ¶•_Çvúãþ³Tšd¯Ï¯½Ìx¨*?kSw™T *OÀ{†GéüÐ@Oô€ŒUO”ŒPÎó}~K"ªƒúj(DPE‚¢ Tò_íÒ€P€wú@GÝEM€Ÿ‚‰’~×§øÇÁïçÔôv?î²<Ôl€&Þ“Í“ÏÏýå`‰ö5Çä{ûf/ ìh¨ŸS;DáþI¢›>W]mÛÊš1ÏØt¸"© 0%ž>;•!Ó¤™c"ÙU-d­6{5ÌAdŸ]NÏâ_Júkc¸Ü¾j–ïÉ÷d?}.訚äI–¡÷QI´n[ G# ›ž®qÚ”§û7û!Õ8Öo=çjA˜Ê…\[B üy¿[ú-§¾Ø:ÎÏ­ÚÜÇÆ­ô±¬g÷;Yà…øí‚Šž0ý;€ìö¿u£F~åü]|—ç#H s, ˆ'c°@;?sÎÈZ! {ÀÛoêÊm ´©’É,›1©T’•)2©*M­)$ „3Bâ‘aÆŠ6jßoéxîŽÛÌ™`s?!Òfi2n®©5bßµ­ðlÑ® PA…×Wëàö/”Ò¦¶!4‘rœ 8Ú/>ê)&Úìoµy“s¹O•î&ñ“X€>Š ×”ö–!óaÛ]Ûf§*» Zz+a€½þ>ÒI6c€À,QQF""" (Æ ` €Æ b1ŒP0 c Qbˆˆˆˆˆ±ŒP1€  bÀc ‚ ˆˆˆ€ bŒŠ Æ0,X¢€ 0 Æ0 ` €  cÀDŒc`€1E € €1ŒÆ1AD@0€1ŒPŠ4b Æ‚ 1‚DD@`0hÆ b€( PcÀ1DD(€1£Q Ø1ÀT1£ ` Æ `Æ F1£ 1Æ01‹F00PÆ0`0€ ,b€€€€ (¢ 4ÀÀl1€ÀŒ` ŒÀ1€0Œ`Æ0` `1ƒÁŒ`€01€(0c0Æ( ""-µcFÔ±ˆØÑŒ`6Ñ«* Œc@Œb(64‚ Á€0ϸ" D` c€ 1F @Œc¢Œ`Æ1£k€0lcF1ŒQ Æ oàÝÆ0€Æ0`À`4Q¶ŒcÀcE¨£1€Æ bØÀÀD@c b€Ô€" Á°Æÿ™Ü€ cE`À€ £0`Æ5ŒQD`F‘’OUû^¯šÌçËóˆ ‹¯ÿ_Ú+¼„ü«û¿'~?J ª„úÒÛŸ³ú]ˆiC (Žü!Ù­óv>{½åx"(HH£ ˆ©"#"(H«AàPPÉ ÛÕiUM #ßõØžß(ˆ ùžf}Y€D'*ráÇá:*¹ïÛw|¾kÏ| øL¦Yu\s;j¶ˆ/3¼®ÖùFF%µjÏ’¼/Üv47¥ÃNšO ]ªV¤jv3¿¾›ùÝêŸíz߯2ÚzÒ¿Òõù»aš !~xS¢\Ôb Žº4 h j0u ¿(y*Š# #9O@¥  ÇG?zâö†v‘~ÆççýtÕªfåèò³™Éeow#Éÿ(:gç¶œIÅã,Ø’RÕ€ ñ€€ êOÇÿŸéOUÎ Oq“Ïý'§¸;ED´cZ5‹[¬kZ5¨Ñµmb´mQV‹bÕµkbª5¶-hÛF¶bÑQ«cXÆ£V6‹j-cTZ±j¨µ£¨´jÑhѶÅmXÖѵˆ¬Eµ-7ñþÓú§òÎÏ€GÇ”QP ô J)Š"P€ª0CÌD<›þêöÈ ™T0Wψ¢•oê É *S¿ôB©`Etëϯª>Z!ö~·2¦PÖ{=psñ™85UR3Yݳú@zú<7ÈñlÚÃΕµx|cŽ}Z K'®/®~5$uát»ÐîÛ4òõey]ýyÿ1®­›Ï{¯{ƒ.='¢Ã[lk`qÇ˰]«#ö§u²¹©/‹Õ„à„ßìåð8>‰dL:ú¢¹X¡tBÐK¨%AZ`TQËþÐýO¯ø^ÏÚgèQ÷þ÷£þÛôcä]þŸýÿ›_íô_Ø~Wáþ÷ÕíÞ9µUÚ¢r@G¢±ö£ì[ÔPê(’ŽÜÊP("ÿºë>{¢Ðfþ.î¬\Fò¬uÂH/Ôúvð?<ävUËwÞѰ4˜€ŽdU@bªž×h|R Œ#< bŠ4ŒJ‚Œ0:ÆQñõèDžƒìïóÈ ¢EUAþÎÛ±ÎuÙ·Àª‡¹<¸`l?§‹ˆ}/À»´ÑÛõãxÓžù÷)ç|.‹?ž¿$Ñ—Ä,øy+ÎØNm£ÕÛ=ÏäÀÝDNM ÏÏ,u<¬š-°L\JzHÁáì}´§>…¤€€TÜÆ+þ çóY Ìá£õZEâ»f„I3_Ã\û¯iüàÿwOö~flüŸÅµ¬ƒ°ÝÐV¼+1Ý ‚ˆ^þ_¾ü<½µõû²ÿnª§|ª§êéUMê~þö×…™vÉk·Ïvwu¸Ù§_Øó³ÝoDzAæeÈdÂÙ¬ú ÿÇöNø÷¶Ç²I®ã´2dP"÷ÌÙ €ÄId’T¥)µ!³«1²²Ë2Ô›Z I&Fgû78§Ç‹A­“9ÉÍ`ÿŽºáúŸº{òkªö-ŒYi‡3œ¥yeO’ÍÅsxžYä@@8¾u\úက…Õã'|~O °Rçü?[Ópíͽ3‚¥ç]`ª„Œd'[kº;³ú¯Wyê­zˆ oÿ?Ñú|øõ{Tš²d5Õ6ÊÿÒÎø4öp›”v`#ç57eÛÐÝì´Xuû?oö–ù÷¾´-˜hdÍD%€(¤$ à R„ò˜Så*'N~?™áÉJt¥)xÜ{hŠäµ+ ¦lÎYÍÔ¹;Ó)g+5™fæ±Ó°k[Yh°£Y³û¥ÇW“‡dpP=YU9†rP“üR‚6¤AüšAi€ÐmþŸäw:¼λ“xOÑøÿ¡äxÈ„×pÙ?‡Îï[»àtØ~‡+ô³ŽDQ ¿‹å–@¼nöG_ü¿Åÿ”5`omX– M“'ßÊõ÷=L.Xû¯.»É3zó/Ô þ&=¥µÁ(£^Ì®ç÷Oœi “ðÊ‘ÅÙ¼^b´œ;‡ó’ _ÇDÕàÙ^/îz³ÇéÜu^zi§‰C.•2Ú¶9rx„ÿ§W~d q€ê8ÅHRR†ÃS !¿Öãq™›{=ŠƒÚ«®\òMsn‡Þ¯÷@ó)KþÇwîý/ÿ¯Îë+—úÝ/Û~në¥d« z¯^{)Ú·É"Çþ{lâdñ !M°ø€E¤(H’TcÒ¢~#psï£9J ‚䢇胣E_ëÚÄ37€Ž €TN¥ÚÕ«Ü[•×Gúrª_—åÿøýCÃõçcæ]`ëó{’ì/õ±]­ÖÍF9.ÕlMïÖøÛ×°‡} ©$*0ðÒ«ûR† ½9›õ88˜ãå # _Ö d´²p¡V™õóä?s-Ñ# BbšjâKïD>_ë¸h„ ëøý¨@…ÄÕƒ”{e”A1<©"²¬pP¦ %Zà~úÄ$çfa°moè(1¿“ð^ý‡Qj Ǩß6½V¼™%¬ ¥æ´ PÚ|ÃL"“Jp¼cL&}M„áÇfÀ``Éúë·oŽŒ¤D JðB‹ØÞМtÔ\M"Š#†” Ù³^“Ö9­ ‘ô­³ÌÏk?ÜVÙ*}”óÇå£v=Oz•u{çAQ•0þ³öÈÁ@Ò%U³Š ¹Fl Œ¶O( $룘z³ '“¥ ÇEé)ñ` !ÏÁÁ0œkŽ€.c̈ÖõããÏv“ȵV8M~")sSÌ=OSÎéì1Û„ÔP°Þ*‚ºïÃOI›õ9 / EðÕRvp~oeÇ!:ÿ¯kIÑœÌGøi6½¶û¿¹üÎÑ•çk›sf[_Ùý®Oã:š¿xμÑGõUh˜Â@!‘ ›¢>Û­@FõOŸÁõ—ÅDʈ &ÔPN˜l¨#GÁUÇ0æùbl*æ‚Ð!v”A ôšhGÏ‚ª^¸îÍÓlCÅ &ü2¢ ¸(c—E’Ä&Wòõk]±{Ãú5á²ûgØù7¢ªÝ€dPEï5WWÊ;ÐEv>©á(ìóÀ*?ísÊ©Êòv×±È 9g 93¼ï¼ðàïñ¬¢€qPÉs¼ZrÉ y@ûÇ·ó±òvŸôcâ %øË6ÿÓic¹‹àª 5H\r2…2˜P¾RI)”ª Ð"­NHö&Hñ¶Šˆ•€#xÝ÷Ä‹5ÕIÄ¿»UçK¥UZÑBéL×c\ÜyEkɧ™ÊR”¥Hbt™ˆ’&' {#h€ŸŸ“?cÊ«ôá Ll®×!eJÕ´dè=ñÑᗵРWaÛf9ëät(~³Ë€ü #Ìq‡ÃÖ߀÷IÅù?Üèü>“±ìz“’‚ o:ý(ª€æ9Ù°ø^0äÛD7žÄ3FØnf«Rž !x9ÀFˆø ˆŒTÝø\,„¹­¹þdC÷+"ªš  T {›}ßø?c-ÁÙvÛÖ <>×>Çå¯u2ç…)ÏL[íùíç Z@ä—ljžµsîDòI„2w•@¤· [9qŸ,L"‘D RYà–žjVY+Ag µ¾×ÈïÆ.²˜tsN_K×_Ä/Êóµ›ÃÐÍj·Y¦ÿ·ï;¾¢vçwùºÄõ½à¨³%Á¼¯Z*‚‡ÇøÀ#戢#Èö¼§a½u\*©@ `²õpÊ€‚È’Xoì{ýžÓšzÙ×Ú°ö8ó?(sŽïu“(Cšê´U¸&„PÓe‚Iˆ1"ªnä|Ð)8+J°Ø¼Ÿ¥A[¿²¯eøksî7ç(wOK«p>µ*µ/“ lZûøÿömðÜXM‘Ýó7r€ú¥z€aAA#ÌíÇߨæƒeÑUCóôê’ŸÄÀÑ¡QS)ßD’1ã‚õpŠŸÙª¦@ ð;¼”p½@ÝÇàÿG?®jþKù¿³“ÿž:!èÅÒÑxðŸ¯üßÐí¦Œô,¦ÞUœóÛþMH|¾Ö­ƒÃàÃÝO‰ï$OJ2âþ›õìãÌó¶é7ÛEQ­­’ÒmkZ ™úOo 2[^êÑöÀýH?Þl5nÖºøª7ýûòË&ÆËž‚-a);¯…˜5Q#üC4/{QÔ§qåyPP:€@K|=™ôÍ¿KçòÛOTy®,Xo¾2W8n§éScš»ÐÌw7œj>?ïdÁÄârí?Š Dù°` Ç`Zf÷ÀèPc€¿ÓÞâÒ:¯©Öå3dØ ù}L)aцÚ=ï%P‡aÊ Nÿvç¾/Ü[uïAæL…Ö¾Ý7Ã2_—Øïÿ_¸òÿ¸ˆëz¾ÏÛjˆtÐ:0÷à*A×|ÚˆD˜<Ê?"^þgŒ ؾY<¯‰ó¯_u=L 2Ýgñ}ç³çz[Ó ­«ÖݾºêR·r"Šãƒ›0ñÝøª1Dª¨ARŽèR” HÿSÆE_K PAD3íæö†º!ît";~ ëŽ;³=»ëþ&ûî´Ê2ÿàs}oKí±·gQ*O]Si•á·Ä¿Üf¿‰›õŽ/MÃÔÄÓpò&1C)yìp’Öºñq—8ŸJÖáø¾ä“I±tº„BH8‡¿ÝW¿ò¾§¸ÎÙìE®Øf:[iû“²ýã5¶}ôÀaPž(š@zD±ôÝæm?Q£ðš{ˆvÛAä\ìge8|4z7aþrœ€€uòAT¯9{ìåŒ{Ôˆp–a°ªï,wïQÚäó}Íw30é=¯S—ÚiéÏÀŠ")¶ŒT ꩵJ‰ã *WÙ€€ïÆDïÅ (­à#P¤QP"€±Uöà8€€ðæD6011¦û&€FÀ#Üþ?àÞŽ² ‡B .;ŸñÿÎÎp@½ (%月ð6¿úhzÜ7ôo—x~ŸÚ#ù¹2'"‚<9Þ÷üÄð<«]b¤“½ÉàÞŒ|YD¶k¼Co˜]›˜¾5Ä*†BDªY$*ª”ˆîæé×8š%Ë»ùß_ɼû>×Ùµ¥ãÆG«T #­¬Ý!¨rå¿Î}o…†±H))¥¨! S7F|€Zš„„5ÒœÈÍ÷¤¶:]¬×ÉŸ¹ÌõY¿C‡ùßãž«¬ûæøÜì÷GDtDé/ð‚ €¬‹9H…An箲[ó¿óÂùü§ª>“¬?ú;Äú”D„ @@€˜B0’$` ‘  € €€ ™A0€$I‘4ª§yÝo”ÿ;™î¼÷Lˆq~Fá±÷ýò²ëp“‡¶Ë½L fUvÅÑØ°a.@Bk0€Â€ˆ„!ÀÄR”¥.we‘òtáa¨úwû¶ª Íü5t™C­fæI™µ ^5Z@€ kYÀBú•¥e äÍ[ëŸ nù(‚#çþG¹ñx†öøqÖë©þ.uÞnáV!2“cÌì¯û{3#Ç¿²uüOéÿªÁ†x´ýÝ4Øûwÿ•Ê|›9yòc ‘SÛf¯«úóÝý×*ÿýœ’ÇéôX LDד÷'Išu~‚àþèäíFD@Ni£ èkaJ Fˆ#¥ÓõI÷Ô¨‚ã3ÒûùÎÏÛùEfvRµHL™ú«ƒ³ì%‹qV’­nhQfþâ£î“®¼-V#ÞD¨~ìF?˜^@ ˜H(P5,ÃÃ%ƒ€ûCÇš+‹ŸËvgòœ>3žó“ZÃÇãi(ùXó’ð]’à @ôÌQA+ÁA&ƒ[ö¦yÙ”~>æ¥]Ä+dw ¤¬[Í}¾ß*ý 3!š)«”WÖy|s-ˆ$›©F'#5Ï·RÊl]:¨ÓïÚ7znSa¸{íÊÞAÀ3Ü õe «:áøn9I©G&– &Ðc’æ 'š›Ñ*§X¯šiÚùš*«l|¼\sҔדϠÇ[ö/ôÿÕ¿ƒ1Þç;äµ2¬Ì§X\ñÓ 0ÉðWã³'Ð6BÆ¢»Î>‘"BgécŽÓµ‡„Ž+h‰•!e Lq$V™À]Y/E-MP ÂX©iK¶™0‚ãëÕU ˜Ã+ôÔê ›N›nLòò,fj¹ö“o½Íl`ÞŸ¼½›TÇgÎÊ6KGö[:NEô¤seõ;›>¿ø—P£U ÛxÞÜnt·Œ›ˆß»‡ÎๆH7,wFSàì 0ÜÅ0QiþÍÍýJÿ‘T:y?°ñߣ6+tYƒ“rg »_„\mÚ»:cuþ½Û5P«'–wLi£`ÁÙe|Ñ0ÐC¿¾ô[VŽá{I*óù¿?­öõy_?nw¼¿µ¬Û9À³\æÓÅ9Ùh$èÅ RÝ0m‘ª®&}h-°éVDq½D F§tÍ(\ˆ0¡ß©öí¶œ?÷kø¸{LP_zõLEä,»¦½fÞãtÎ@H æb´ ®ƒjf³mOäñ>/Éø(î7]¨;ê!lk®TŠëJc±ú×ôZé•ÏŽ¶/ßp¥¿Ÿ»º¤ñ‹kŸÅtkµþÛFÁüiSn+yL:Àù t‘å !Ïw§¿šø1pûG éå…¿ÕÿKÙ$ýsþ•3mÉŸ©AšöHv§ Ðô¹Š´¦$.V5=J\æ8ª8±~iõ´¨T„ÿÆðÌÎ|ù(B=±¿¤—ï)Ù™IŸå/÷Ô'…ØÀŒ$Ð`PwJ6D@cmq¶‰Å-ùoûOÁèë­}|×yÞy׎Œ$ó¸ç]ÜË!L333.6Ù“ÒÆÿw#~ÇùÕø‡÷\ùíFÅÃi·lïmbîS DDTÌWË5½›®4š‹eµꢎ⊠A””ƒ óæ]Ö·Á—BJA”Ô5 õ¤Öõp{‘ JЋ¤Šç]o~½ºë\‰ÂI±É"v šÊ3}o7aÄ9Å£‚lh„J#ihÕ ILj[ø>ŸÈý.§ºöÿS–}Ìè7tj'ÉžIÄéÐë$ú£H4ƒTé%>Õÿ‹„ŽÐÏS¾m;ü³þæ[y²ûúHîM¯“«æöã>(¤°ÌÏ›¿f¸þ²±qŒýÍD޾“FÒ•Ûwgη˸.´£À§ûÓ«pé­hôPbB0„¤ü£¸vFÖ lhÃò“æàu¹LÃ’é³¼›:@õLÔ)ÿÁ‡mEÑÕ*fÛÐQ¤KKuß/¨ygÈðó˜—¡-!¡Õ¾Z‹ƒ,<.cø]½.ŸÐuÆÎ@ÎT¼,a@‹O±È|ûÔ­€Ð¥‰¿îñMiU,¯o}Ž ‡¼2&rdôýÖ=n åø¶nZS|ü%þ­|л_§Î÷ÄŽxऑ#m !ð*  „ùå ‚…@QC<@Uü˜¢לšç # ÝMFCöÚøßñ(±ÍŸJƨC»!ýöúªœÔ(ç‚Ê‚Ò:!ñ~‹^MUPZIQ¦T%dªî¸Ü]×]uÌt^W›¹æÞd¦u·tìçÊW[¢én¤ë®XMÎÍÇ]Iº]-HPFÑ×r"½:âù¹PÖï¼­Q¶©²FýŠ.ÁíÛ]Iqx¤Â_æz£¸É ÀÏzû܇÷}‰Xe2Íco¹¶[¯„ŒdD”D1i ­ÖVH`Í€aªyÿJîç^ËBªŸÃ±€a¬µ¡nlB+ÖyÊ0/ôÕÀÌÀӚο»Ž?‹ôílo¤° t6à t#•ëîšm³ ʰ1ÁËɶ-aVÜbl­.{´¶Äjìôh3´‡*÷Û%|Šå‰³ óÃ9V•½ñÒXÂí˜ã¤ÖilÒÖ»!\v=×Ù}C Ùí'²:V’n{³•ëc³Ñ ÎÒÐrÜ䮑]š”…Ô}j‚„¥*cRèÞ•Ïm¶B·aŒŸXS ÕO|ÝD½ghúF6á éùP·“·„ve ÍüÜ3ºÂPµåf¦ÒvŠ®ëÁa· ÓÍp˜µò¹È³9áHùÄá¥îkf­”ã}4Ø÷ÊP²ÌÔë»ã¹VÑ^‘Û,¡ ¥IÕNOtbf_²Õ/–Z-kcì¶ÖØkI†É"o²ÈZ©mf"¹JpHŸ ‰Î¯ƒÖÆÃgA‹¦Ãj£I­vmbÀ37]°1¡›~ã‹„!†-½óÜhp+œ?C8e ”³)ŸŸB&°…±f«Q ñL¸®m çÍ!^«—eû8L¸h±¢d¼5ÕÑb#dq4ªµË§)&§ ùQþ xqsq2Ýfv;ýÚTd©²YÄ\Ïg-4®ëøVî_ëZMË_Jµ©©´„ ÚCn:Cõˆüo\*îÌ$xŒºÞw8²ƒé—ÃÅh²ÉTÌWY]sA༼'Y|ót·éh׫.—tèæ4xü Dæ]Û/P€€fÊ©xÃW …´j°÷'jqT¶Êä'òÍF§ãÌÇ\/›0ÑËÂþ§2éU{/Œž¿º³Ž®w¿Ô¬NÃOw;ßX{(1íÐàI± Þ!¦—ºaĦ }=±ð‡âÝ`É o{G—sE·º³‡Z_eºV Ψ衘:ìlÝ€#þŒ,K¥'AD\".ý¶]˜’á¤ipÍ4hí l‰f_+­k[¶®ŒŸ#öC÷ò‹†¯¨\Û°tÿAácD4£ÀPÛHÎÂöZtñôx$†ú¤w@€ýbÜz#o›£QúYW…Óð¾ö]ùµ¾µH§`Öß“oÐ}ÖøÕw’ÈeÞœ6ø€34‰ŸÐNv6ˆëd·.*1ý\#úSfãš öÇxæýûn8îÓµÌÇ;ìîKãëD[¥Õ‚Ìd*Ú;ZFì.†î Ïå%B‹êÐüDDeGã ‰D`¢|-+Ú #›WhçãÍé+ÞH'ÆézW:Fqþ7áíRd%-6HUU’Š2®K|Æö×¡Ó aÚ;M€|Ðhsj¹Ž¼-!raq$4~2×CI¸w4Ë¢ŽÃ? :¹RM¨&d„! ‘¸5â$̶¹ßl0ƨÃ~þùD0C>Úa¶B³‰I‰"•6õ±o}ážî²àû¾¾â¸ Üä0߀7dŒ°cšøÃއÊC¤Ãà8Í"÷•9gûÄ‹O°Ä>Œ,ßÀbØP$(²,, ¥À#—?-n£ùI! Âàÿþ»!0XØò&ImÀk£ƒÛÚ™¸¡²1jÁŸ“¬KèM 40áœW dB¤§xñfþÞx;ãt6¶ù#{…¤tm!˜”Ùhi>8"î÷ιŇ3‡ØÌ„ šœ4àÚ„‘Às ·^–ð=Âß \èåðœ1>y+ml‰!pÁ[B¤9 HѦÞ÷É]˜–`G’6uå3 ԶʶôŠ›²f¶hƒË½ëF<Ï·uMÂײ®;i®¯X²ylçœàèÁ„Š4Q¦š¦S$?“!庸yÿä®áÅ+ܹsSiI+­ŽÍõ¥™$ä˜ÿJ1 <š×ðF3"ÐU; ƒ{^¿‘ I‡A‰§ýfÆ·AªD A€ CvÖaº­£0Òm‰‡@¤ÏP-8U×`ÕÉ-KºïDŒBî覈&1Iƒ~‰&¢}l…ÏÈgŽA®à`„ŒJœ¢Eéç\d_f/B´ÛM°ÆìJË„&!W p‚ ǵ8iGU’sÆ‹ªòïšd ØÂBH:ô uÕFÄF¢Ê Lèv‘ò4sNTÁ]?Ôô`(êXšÒЉÁ‚ìÛQxîz ‡I N÷ì!8F,ÊŸ¶&Ö.Åm‡3†r1µ›\ ýPjNHp˜Îu¥‹6;Z7`Ìd¤‚Ä3lµ¾õ|5ã½ë%™¯ãÕ¬®÷­½fE´¨‹„,æág)ýž8v»””ÚB*¾v~¶×óßÑ«_¹CŒ®3B#LÌz*oÁ¦\&I«8³oj€#°Âä,¶„Œ"oÍ1OXCT¹Ôt©ºPÇV!É#³òiLÌ5PGeEB ç­Dg/Gpãž‘j¤$Q5 ‰?¶¥tîA/OA"?zGz0AãG›'6›ÎPš¨mîÁ:(¢€o§”ÈGóÄF Ö]6Ѝ 6$Ú¿­b(˜$,@ýK…–íšù µ–óLÃ,ŽÍoT-Qµ²@Ñ*Y˜a†(h3t¨`-A7Àn!1p6É@d(½«žSËÜu]ͤËR ¥U * £pÏYÜávE81ÚƒQ¨9 7a|¶T±Ä¸Î}& :â»@$UMÕ`´BF:›7â ZCn5Z ~xôà#ÏÀ:]Tna¥ÝÑ×V«Ô«{Œb`\HHBHײ6ȇÉ#+J ”˜}ø”¯Øü€Â#Eµ˜—^æex3@ösa”R`”û»2¾Éš%¥¿&õâ¾²KðïœñAÍvdÁIª¨,ø­ðëÖ¸0ËK%‹ ¢ˆHuÅU$L±QáA³M2†lš2%…n`BBjô"íeÖˆsTíÀRÀH=6[:Ö¢èU ƒÅ‚ Ñu´»êÂãµá8Ф$[¥IEbv‰²FâŒ{,ea"LjCæù5m¤ª°l+Eóâé³Pû{Â"ceæÆŠ\Øîˆ»°¡Í¸ã·ÎU,zæÄ¹Í©žøã…½qÍCßCIpÉÆ¹5ÊÔOz$N¨¤j!©¹ÚKdCDR‹JDäE¦B4dÁT颓“}}>®,ÑÑŽj‘TfZ´Ï.Œ„ŠÈ&¾ƒ´j ÚŠI™(Ö~[åïî}»ÊúþÕÛMh¤š&ÆDÛé{~&ý‘I1V¸Ý‹<w†Ó±˜n'«1‹˜n¤1ÚÛDÆ-i–8ÎVý›]ÿ!Æ Lé€ÚÑJ4%Œ8²vĽNFÑ*×I§ÙÏòíÿZÇŦKaíÁ…¬‡þíã½~ F=âƒX€¿› ý ò º€Î¨0„ Ez …@B´ÆJ ‚5àßdÀí,^pì]W=Äêº#ÎËü|¶´»Ì'žÜ» øÂÙ»5µX‡åßkÀ1øw¡ô‹‰˜å¡µ3"õyù8I¨‹)F²_ïF(­“ýZ_‡ÓÉñŠ~–ò„  Ã3¦b½Àó(ów=p¯©*ÃÆÞÔ2dðþ·î>¿ÁɰcÝ_Çuö6ž/èÿ±î"ö}çnz~‹–t5›•ȼµœ›o>o@`h ÚînäÄôÓéØðË©ª‘!}ô3`gOÔð^£ñ|8y»pÍ4öHÈfÉ0êPß*¾» ïn\¬± œ¥Õ@µŠ F6iB¥>˜v<Íeè!§æf3iÎÄLÜ@Hã»BÊäPap° „{ˆ CqVfÛ(ÕWý“~gÐIT 2 !!’I!2 %` J˜`ͯ`52FGêÊàf3bÙ† fž Q–T´uÂÔtÀÍÀ!—j’B18 ÜPT3ù}Q«‘À …âd©t6Ɖ´fDUl Dl\êjш‚dœ/ÞåÙUqŠ2Hª¼ójŒ*&Cõ¹5٠˳Wú©×¡¿ÈÐfÅ#®Ïe7ø¿¾xD¦ÈB1“ƒ^bùÏ¿Ua£>ÜŠGU`VªÒi¥$·]%ÈWãÿ{ðoÂHýÆášÄíú"¤Ðhè{r5_në²íœ¯œ(»ÆÑ!ÔL¦ kš4@¦°O…F¶=®åŒÀÃA$#ë\AìW6RûrÑ¿³éüKö>nu%=i†ýf¬7Ü…RȆòÉ ßÔSi´{{AaŒÂ¶}™¾ú»—ë˜âŸñèL«Ê7±û9Å‘o_5Ló€ú;7‘‹A›¥´§b”ÏšâÌÌÕHÌ/Šaàbã‘/#UQ!.°:ÈÓƒE* ™\àÁ/0As4æ(m©‰ô½^Å`8&q¹À¶N"fyfPZMµìÖÆ‚´n<1|ÌD`A4mvc‚lA˜o\ГÐ× +ë`­üÐ1BB@7kQ#&µŠ&H›1ØBBI$I¦ÑfMøuïDÔèŸÒìÎê4ÛlT²&¿tµª6ö·vÁ¡ä‘\ÈŒR©•![ᑎaXŸƒ€ì®°Ö¤ª ¦Uæ¨(†Û•çn²5/+Ï‹¶¢×uí»Ï¨îº“L¦ÙR)I áR0±(„™T4šÙH3¤ÚŽû?,äC‚P>ÿQÉ b`Cûý÷ó»þº+F¹wE™¤¸¾ÿSX·è íãÖм²cA‡ aJ («±4êñê„dµ¬Ñ%ºí¯ó·Ý¯û|ŒÀjÉF¹-4kS© ë7•‹Äʆ&Ú’4•õ…m¶'±–ïq±˜²·ø“i¾PCc ˆ, âTE(m$ ꇺøò·i¥Eµ™7vÞÏ_FáÛusÚîÜñÞn©šÚɦŸ9/³£7¶÷CcÒ(È 6Øš{‘;Ä)Æ*V42A ıB¤Ø†Ô|Ø7·¶V—‹œý›ŸjqÓÞ³nnkoáÉyÓ|½öy5šfkçÌ3OËŽ?WÛõ-»Û~)>[ÇW¨ÌÊ= 5¾Ä˜Wýí?~©¡ùˆÑ­µ 6¢kào€÷§tl|N§¤Õu®£`$ šÕD]Ý:¬oDÉþæFÅŽ;£Pr;¾UXn&bß7-¦Ùtúm;ëDj( ‘PQ;ëÓ'M>Ûí¸¹ÕÅ­ó±ë3euîÍ)½ÛÆË£xs¾8Ý_S9æç7#ÑÆ>¦iZ·nërÇ+éPÚ„µ¿¨ó^Q½¤þŸ‡sh»]η5©›?bb Á²#ø,XzƒÐÅ =f>³ÛÊ×Nn×+½kæÎ=>4é+*2LÖ=–<‘$¦4ßô¸uD·´¶ê³4óô„w¥w$©ãXä=ÿõj9á·¶-UØ„6JHQ XE,ßWî* #€Á-ἪAm8áN±6ADœ©@ æ¬Äľ”™&I™£Â>€ÿý#‘BpWgd?!;&{Ä!Nî°âF  ¬… $Gf¶iØx€x £ 0Ñf´±U†I RX‚#í¸ðÛ”À¶+ˆ P­R†T…0â@ #Pá3¡Çöáç?}„;×(k-,_7ŒùØñrlk|~Çùý·GÕtý5º>`–ºéÖº¹²umï4 ±l™oÉÅœâùÛ·m Ôº³G6]KVŠ/—Tºêhº™ÚÂÄ>§¦û®Ïõ¿þGÏù™ 0b†å”žÅCcÓY¶m‰5 •ÊÄîîìâ”îå ·Ó ÚW¦±j|+…ñ‰H& 5Ø0ìÒƒEÔÉÕ]Õ…B¿?¡°_qÉ‚ûI•¶øÉð”¡Q¢ÂL˜0¤Ëq@ÙFX©+ì ѳéJÐz›OE;ÉР$ÀñM‹^Zá"×åvuÙ^Xrw‡£6i¢ xwÇn0ç¿ÂøwSm-±LcgJ0={\`¿ÝC®1zñ¦³±2“{,íKp—=tRk‡‹Ÿ@ƒÑm¯F“ís!Âk;ª-óæ˜½_}Îñ«o{înjÚƒ0Ûm?´Ã;¯`µ&[°‰r’/¼JhUÙ0Ç+‹Š@¤oº”Ëò»z„Wgkã_„Ùç1ï¥a,+HKìèñ¢úm~·¿˜Í­ÛéœÍËÌ}Ö¯[«ßS~ù¯³—ûÏ_íóùï¾Ö}ó=ûÇÏ~sóÏy¯‘œ lÑå=rnožp}q¾ùs±Ï™Î[×{žUNÎû·ß¾c•–/œ~·‹¯º¼äܵ…¶|°C:—H‰¡ !¾ÆS…böû“þ7õx1xRPÆÛq¾™ÄÈ‘Ii£èíÆž½Qá+ÐêœÇeA¼„¸sYÄáöþêÛþÅ·5­  ¢5Ø8ì\RŽÃe—Ô¾Ù ŽæÍ¯CJÜ©pˆ`ÖD(Ñõ a;1k¡jV hÿä`5É™¡¥…GflÓ$2Êê1mÙ1ƒÏÝ?_ý˜k†O™”|þF¢Cq=Kà Ԍ·­l%í½ ÅÇUÕðíÉS҆^Î îÔ(†˜•Tæ”°„eu6ýMVÆÔmµójåT¾LVÃVˆXX`h z¿µ,—-`“ @ñâ‚3|ŠØƒ˜_¢m.ˆ Š|Vä#Ê ¡VNÞ‚ò½´~œÖ20a°‹4ÅCQ ¥× ©’jžæhA*HKÓûlõ‹•ãÓ¸µ4¥©¨ƒMžAĽa±v¾šÃ2Æd8i!¡¿k!È!ahdئÀmKÈ\é*ª£ŸB@î¼à[nê&Žðë£B·ßl ÷8Öç¿yž8©\òâclȉÌ µÞ9*€ÛòîicH,k]Lç_°ÍšOÊxÜïßpîkCÎT) @B°5ê9äfŒâoDß<ìæÒB,VŒU_ÂÈYQ1žˆÑ “NÆH£ µ^3BÒ³³×D|¡ùCÓ9ã;œ íË6ÄÀlføµfÐ)p{ˆ`>p`Ù՘φ™!",’.À‚f²ÁD‚¤j)UJBoôV£ÿ± l ºuÂV°Ìì6¨à´X…u|7@$‰‰Pd‘¹› j°â²þ6B„LšØŠH94™aaÙ‰}ÆÈÙ÷z‚ŠH* €ºÙ‚ëßÍ÷èƒlAm=q)Ù¶Ô…õRDÕ8³FØ®„%ä¨C4@„!I&jµè3þùëaãŒs¹ƒx3rÑ¥á/µ©ÂKÑÕNÓ€>ð¿!¿Ú åäëƒu`ôq¨$† Œ‰ÆqÒû¯ÝëÚ¿>¼íÎOÇ-[òD†HÂlqÑ Wm t“€ÝpoïMÈ&Xð¢ÆPq9ø„»™X€ÅaÕÔ’L^3)7Rhz}–YÜ 3%³Kê f6ˆÔ¦ŠÕ Py„†7–TD†a1+ö;.²ŒÖÁ0! $$ÍHž6’I„É2L‰5Øãè/./Wø£Ÿ¡äÍ—$wlwN¶ ¾.4äÀÈáI-XDõ&¦k /f¿ ^^zWŸ°êÑ ¼oÿ«VPÜÁV† /@Ιú Γ%x`vÔð`ºöŸ e¢Bõ(> 0Õ"ÃìB„ŒŠ F€wv±ÇoŠ!º&îæ¶ÓŠÈ@„ o´pi l`×ÁxŸ9±{HA­&9'L¥šŠ±y,÷Óãt¥ÑX5D!6b›JÎò‘†!b4Êq7땦tÅΉ…i1¦Ö%/·`ùF˜ØÛý|$1ÎwJU1H¡$$ŽEác›D%Hß$¶ ¡®¢óB&VD3Éà „¹25?èþ¾®²8‚!¾¾S:9¶$4¦ ªÈ‹?Zþ€¸ J1‘7c½3E…Ví³,ÆÓ¥F)pœRq¹TÈoÞÉ£iy¦ø§õ§Žû6-r®F…²›ÆØòï¼”¼j²÷eî§Öã`ÂÁ|/°b è¾0‹+U·Òµš  -ü¶¶,×½$ûœg8µ¦3‹0çç%Ns¶Ÿlæ¿~ÕÓó×—å³/yû]N[æ·¿î³ïžî»Þç½îzïåóœêt¥#m`AÊ‹™ï¥òþ¥D2cFûëq(Sî/ºBHßcÝҾ̹Yu±&‹l+¢Y¡…›Ý’åYÎk:BmïÛ(ŸŸŸ+2oîýõÊÞÃO®QäÛÇ­ÅŒ¾®ØxbºÖúKÍ‹ò5û ­¾ÃWÂÖ7Þ¼ ZÜëÂSJ–¬Ùbò àë8]§ò-ÁàYæ^è‡OÇâðÎi ›£2C‚áÌÙd$V)£J6MHfªü{jü—_Aчáqã/ZÄrƒ”÷@ÈŠ/ š1€^ņ긄$‚Üex/ˆ &2È Z#¦ݰÕ< ‡{3—€ÃwQ/ ôßÑ•¿PŸ7kÇŒÐgÄH‰ B;°‹î2!.æokqm“9AP’š¥b9 e¶´ŽkCF8&¢±Í–·ÓÁíòIÏÃÁçÚã]9w¶t”23'K_6ŒÌrœkJ¹±!ÃÔ€#* £y* F­»»^WÉ ™§ð¥¯·Þ‹ç¨, 0!UKÇ()LaDbKPš! h`Äǧ&Ë«@cI¤þù ¦…Ž4k¤$‹,¬mQ¶—[ÍÛá¶vu¯%ä¬æÛ¨îÚº\ IIµMbM²D{;ÉÖ³?ÛUZ¯ºu^/æóügæGÐÛÏð¢ß·±©‡Ikã’þ”Õò‚ýv=|ƒº1ÇH¨–…ú±~GœõïÌm±¬þ…¢éµWÑ5,8å grjÇ~ûãÀËçúKjCNN·ýîÞÓ¬c0u‘ÌöS©ÜíLŒ#ˆÏu[ømÂà9Pîã#Ä<ý0ÒºC„–}(“´­&*:1@G¼ú[°ïá¢Tc#2'í_MÅ3ÁÆ!Q«¡ñéL§pq?>î‡PØ¿;eX—ØVž )¯Þç$„fõ¡ þº×ÊA·ñ[W5ß·Ý~$Pã^„§1ÂfŒcH£}·ûø½‘þ·û8ܹSiöiK‡PHáßJ€’"†äwX÷’I»àÎ߆ÈW$$'ˆ‚ÆL,í@q6©%©ÒX¥†Šm=÷P¼ù︵~lÇ4±ªjWË–¾£Š¡”&´/›ÅQ¶æ!d”J2 Κ 1‚ ôÐ4嵋²üüi:!^;Ðà@ r½&Âwt©ã,À½Š¹ÓÇ»¬8YÞääî¯t{OkRBõoÁÿ1€4äENãü>gʸycË¥ QÕå,(悲 P$^†%dQ©Ü[AÂ<ˆ'K¥D¨È Æ Œ.3 p’'W!¾+ER²²C§q‡M •Aä×ïú5¦h^l/ìͦ!óa©é)Z îµ´Õpd†ÞØ4†ñ l1ÖI2AŠ 6Ë&3À›A7z>U±P.Æ F9Ȉ(QEbËå%@© T$*‰C*JJ‚ha­1ˆ(õÿ­È̓Üw–[kjèv>¿Ä Dz B2%jýê´|ò ›@|Ã@ƒ’BU4~Tm@.|qL`Ž’ƒ&mú6:hhœ0ŽÅP†HpÈ×gG6}™kF •µ¸ïÐPùô{ÃCQ¡“úÆQ|t0 6ƒÜ½—¢ÌEÈA{ãÌ6®Ó´€„8¸B# B*ŠØ;÷’(kjb@оDyÉ‹UßQ‚@b>U\Dî°7ÈYLàF Bö…º.›he&4`jS“tP$m}Éñ„sx¦L2L-‰wIÃ;öÄPé› `TtÐj@7åf…_ÐÖñ»O²‚½ýßmæØÈî”ÐkCtcXÒ:`%ùÀ_êy’€ #"$Š£" Œ)J@@|DV¦ƒ¥*hS.¯\êĵ3ªäðç!hnö’o}í×?:ÈâsG1Êëfåz~Ü«äùýýϨôŸàÃ‚Ž®©-µ­i $©ŸÊîå–6ešM©• B-Ò}jèçÚÿG—ÒgÅöP÷žOKo“°SÕUÂŒi ªFŒ!ð¯*Ó}ÒÿÒÅÒæ¾4,¡–ƒU–„e?ÂBÏÄ®ïNŒO >f._7 WóÝ5Zºñ¬&ÉUßÄû~ô° ›®Nî ›*!Hr±|HÜ ð`,&%›XÒr·lÚ-&SQb«FMTm%hØ­X´llZ¨-cX²kIkcd´”cTUQk°Dt›ÐÚõÍ¥_Èa{ú¾ð‚‘Ï”+.Åî‹Ââ0‚h‚AÀŸ`Ó±C ‡pwÀ»$ÄÒ‰!bE±‚èN¿ÃÜÆð¢‚×6É”å>M2†´LqÊÖQ¦HÛ-€Ö ‹!x¡KÀy±)…ÛN}© vjÌ–xóz°‚#b#’â~*:_pÑc֙Ĉƒzb0ô,G”í\‹¥Œ^ø{#áê ­@ÜYÀA³órë@WÇAAP€‡À2Sá×WÃ鹚ŽúñéÒ›|콿f÷ÿ®k(»½ß¢5Ê–¾jú’?'¥ˆëàÏ.ï\­­°Ï©è~ù®‘m.ÄýZÄÄVzØÉ+ÍÅeÌ? •ííó.~µŒÂ»dScŽ¿7¥Ûân¸ûø£´_z:¾·W[·ãû~’‡¦¸Ë\rÔöWA'ia“Û°óå÷¬Iý¢Ä› ª„€ŠDË+R…RfI–ÌfhÏ'*EÄäûÑÞ/Öífu‘ÓÂ×¹{äø“¼R6Ux\­®iJk‡:Å‚·¦`E9;OžS^üö¦}¥©­¬Í™À˜L&çTr€ :UZ „„ ‡€sC.iÐ@iRÁ–Ùo&éy­t…Þt?Ÿÿg¥Ç¡†N¥CL@Óòs8~q›ðþ9¤¡´…¯wÞ陆@KðeÍ|ƒÄí³¹'æêS{ÂÕô³éð52VÆ‚êÑi{SFä»üÏï¿Z&f?¥ßSr»þzÜ/O-§ïºq:ØÝ€"ÅåTŸñôåÂ÷D¯š!h%*/6tUR‰(›¸ÇôÍôVÜ”ÕvQ_ òóÕ#“'ušTóª5Ó]Ýc~µy­F¤GËŠŽ©û&@Í rŠZ(Œ€«#&QQföî‹8„KBªQÃ<A€CןCžÒõ=s­Á®¥Íï¥Drl¯[¥x¹vq'FÍÈÓfDME®L?xµ(ôy­é‘©H•q†ÌíÏ(а€FH)$ÊQ±"_ÓDgÚ,â& ‘WS·^‰|>¬ÂC¦”¾¹‰ä#¤ÓræÜù°5ç"0Ãs nß&%WÓ,T»#äcRQ U¤óõ©“=°Œ^ƒªZíݳ-Ö2nöáÁŸæüË] ^†@„Ì"ûº·f_w½©åtZw\ÒW„!&rÄ{°äCjz8mMEb …%¸êjÂg.LPÆlÙ0e Z‰ ˜k´Žï {ÈŒÇGBE$¾ £°.á€Lb˜Æ’~¿mÞ6Ëö_<ôlEæµ*ùyÄýåç•x[—FDÈQhˆŸ.÷Î (YR´ÅÚÚRç\á@NP3z‹A-E •³ +ïÑæÌØ&ý‚ ô?B —ŠHåSIDrÄq•2J¢š.”·@Ho÷¿¡Òên:Mú±Š Å¨T ² ƒbÜP ÇB.u ýºÛë¿¿Úá¡LÈšätA|¿öJM*B@dr5J`$‘ŠsÑgBldzà7•I1½¸_PPè_{1zÂl7c|c‰"0`är¤#ŒÈA¡5*òxoØg\\¹ß¾_²,»ð¿ ú;oÖ^ão…ëm¾¿Õ·ÎÒ e4#¢Â0`OÅGNJ8Òô±ùw&fÇtå\Yí&cÔ˜t/~н(æWØüŠ-¯ß«ó¦^®&ß76ß®µ¢š"z‰Á€Hfwp"Ü äu[3nÝëA•¥»SEñ” Âå©57´‚ànoÕA±‚’9YL "Xbë”v´›¤ÖÒ+QÈU‚\€L¨£Ò•½W†ÎN” ]6$a±+‡$Á°bc Ѱñí$…`•jü܇› ò¥\u‹H=¼¶6Ñ0o>—Ìø` {äá„kGûª'A&ÀqîTØí!¯†k­F3hvvö@‚ˆ÷ŽG²Ù ¤ØêA­µç ‘«çæ³±³»½¸uÚÙÄ.F6ÆŸÒôÌâfŠc¤šþ5 HlI<©[7ñ¼öë…pÔ8.óŒ×‰Ä}^—³_æZU³»™o¯®¼ú‹ÙýÐ$„òÆ7J*ÒgiAˆ# !ÃXœŠÑ£;çéíx¼³œˆò5Í ÕÅ HÚ}ÜaFŒM ¶)#ÜJñ˜˜ygà°;O`„ _:î®s¡ÍÇ9-ÒÕ¬ÛñTRfT‹– L¨‚ŽÚš­…IF’×›óþ=ôÕû©OÖ·ìÙPó·6Êù?gçíENÌT )ïa3¢I¢€ ›“y$˜Q;»jÊ DDÁ’̈­¶ˆfFH,@Èû]…é-b®ýi¹ËßàkZÓ7fG# ÷y‘ѱƒ³*0v éŠ0û8x í½ü²¶ŽÌ iæ1tЯ‘´:ÓoáõôÕö+^Þ|&™¶%÷#µÝ|ç7¯­ço…}Ù} Qª|¦½F’¹bÈAw!! 'uf*˜äȹ<ûèÑë_ÈÊýýE÷~œ¨ –µ”´ “R…EPÀšŠ„Ø°ýìåJlÊ,ThÕ[2I5+·6J”LP•V6±“RФض’ÂZÛ/ÚªÖë‘I¨‚"¶1‚¢­Qklb""#ˆŒE¨ÁEQcZý÷º¨ý ²óÚq@Ç’-;ˆÃ „Öäî€Þ›2jmÁÞŽ¸¶*oמ’,’0!Êà "¾Î»w]Ëo½µ\¶ñÊ1®¥@ˆ&P€ ¢"Q§›HÛµ›ŽEÎxÛɶ¯ú« ÃM¶/Á v³Ã• ˜…Éõ0‘CHmr0 ÅF +‚a"DQÀ\²ˆd™¤² ÷1fż7CV<ù aÆ2"Ù¢ãP ‰3_xÎ8]ëåˆÇEtÐ($„‹1&µŠ eåo*“CpkJÃFÔV Å›ãdÙ\½ýï1Ý·¡Ô4¡F6vÁ*Ì‘¯#/ɆéôàráQlÒèçÐÒöGª\mꪊ';H¥¦&ƒ=îÒiÌæÂ#–&’Ñ 6Ú©F`J3‘ lÆUH†€’8­_QÖ'H5Œmî6²ÁØ@ª†­#™Ä$!ŰëV…ßÊ·85æ§[ÆW8§½ßrŠ‚'Gh‰0¤òœ©rg‚gƒ»ÄP-íþ³#é=znx =š4¾’‚bA1M @ÓªÍAÆXˆ*×ì-¹FÚ6¿;k–ŠüÛ+Ú§ 1b#¢!ôÌ@¤PF#à}‚"B¦¥jËPA¦Áx5 (…©*ÔS$IE-sþn×Ûýßk¯ÔëüO¥æ|¿ñ5ûº5ºý/A–͇ý>¯*­_ÒˆË5©îŒÊ6›§lxBô¶ËGE@SH1ÿ/wÛü>çßo½õú}!I¤ ´ænÀ„ƒEITÕXÐiÀCçš@xDA€áÌ Ñ'Í&P@!Öxö›d”l¯/ˆPq‹¨æz.¥}V¿®¶žùë¶ÉìÜé3¸àtŒæ2Y†˜ 4A 8 61ÿk ! ø_öøü D÷ö¾î}âY0}Þ„’Aè'¤>Ÿ¡D2 êèo®ž46³}×ÕD–d kHF³=ý¾gÿ;iÜË“^´ÕÓ•t8úù'Ò¸=>Xhªl ä]Œx-Ùž¶±–]èw1q#[ºÅ†èXt_‘-ì@G¯°õ>Y~‘ˇ¹íó ‹êù¨‡®T¼[Ä&C†l-nAy=Þþè¹(A0‡°b`Êæg¿€éÁº¾Ùâuÿ(É|Ы:¿œL•ŠÌZH5FAG­ ¥ ¥0•¸¤þ_EÍæýMŽFXÄ$ Éœ{âæûápÄRX£¤¥ÀH—D´X«Å·,”ÆÖ·ïp£mê¿U¹ã[œ¶(ÈI—]WÓ¹dkÅ­¡-“‘M¬í]v×iª5ójÖá¨×*Öኵ»„㾞üW¾è+ãup×ü¦õUÌ*µüœÛ¤€fð„ɧ‘>%€GS³TÀµè‹¨Àˆ Bvô¤CžÿºÍýà çƒ  þÖ¶y¾¸m4íQD#Ik2c¦~OFâ>[¼1±ciYªKÃ/ÈìŒÓär?isÉ!d®XŠh'.?6¯Þ1¦(VG×AËÒ¨½,Ñ-ñõ) £þ¼¤5È]Iz4ÔNÀ˜‘( b‚ óž—ëXíóö—eFµ 3h/¹Ë=v ~7w¾wç×íj¿ËÕk~˜Ð[³µŸ»—,fÊ( gˆ´ÃeºûTD²vö¥ù&XÐjˆ2–JR-œv&2„ÂL™4ÊbÕ Ñ|ÑN¼¦nþ# €:ú‘€\™&žqëó¶'éA5„2o\âþìÍM´ ¥žgØkÀã§hÓçGàÐÕÑXɹº2¤v­× [‘ˆ„B«–:ª†R­¸ÇwEtÚèÆâEmkÌå»ZÓ®ºð½ÓßxºÄ–“tQiV• ä/»!`°…+±¬p5 áŒU‰¨Žì. sJY W ‘E6…AÀ‚ ë^Œ:´$h”1ZÅ¿0l‌¹5Ém–ß%êú¯žu±r¼oÍ e»“Å$ebŒLÆ— ˽¡Æ6oZšŒ‰ÜÑ@\X*'³Ód¸àY3Ïþ³WÌA²E¤±ˆÉŠ”ÕZM!A_÷¾ûû…_—ð«”(Å€<€Š‚ÔŠ§PXc’6· KA˜4ÁšP$0^÷¨éØà™f ¨³ÝÏóû+ÙÃz` 4^ÐGƒÃ¦d¤j"¢½Šk>èoLÅJ@d"!»f3³Çj2¥Þyn˜Ø¯!;Ï9·ÐÖu·.ùÙûk78ÆàZ0Îfb «ªMgí5Âó»êÊéF®™+[¦ê¡°Pi–»Büسx1eC0C °c$" åˆ+(`šAЯ" ªs@ÆÙƒGÄG')^†"2k¨¸¡"žžE¹7ÈvHpÍ-U¬¶`lM}a) ¼0MŽZ5"à³àô7á¡É´ÆĸeíÑAðx4:ðèˆ@¼àYÁn-¼cƒÙœ}†ÈûÏæhòa„”U¤6‘F( #}âUÇ2 D‚ê“%pCV"¨D¦ ' È­.0T.@ˆR8o¨ÌÒ(a0…×7Àôº_ƒr9£Emš·)ć 9˜_,ܪPC æµÖ¦AÛÏ,±Y‹*›häH+’c9XÐ&r+sB ¤î?b‡I·Òù2(h·OÜ ~º,äœoÓ„Õ°Æ®„!J@H –`æ ÿïÿ³Ýåæ~«g¼¤¦¨¼já%êƒ;ü ž-d$cP6¹âð]½!ý—<ƒm®#mó |óã ÅÓÛ sÅ‚KNð®Ø²;$ržà`f #&i#“o#“?¼^øý>ÌÚsœ•órœòºùÕÒA#ÿoéÿ©Rñ·¸üÝ×ÝOÃÂe>g˜šw¿‡«tF‹$níæÙƒW]¹­”¦pcî©n¸øÄíºq&¨äÓÉ,®,Ï]kÃ6†EÍ û¹¥éâLb¨^“ËñnƒPš¤B¤Dê% JZ!n1i”äM m mË¿kqffp¿CöÐ kÛƒú/åx=¼Zw~ “ðäbÂ:uò‰Pר°I|äØóo¿çšjED™,T›m~šßËÅDà€#²¡ª!çK# Î"ŽXm¨¿X@o¼™œD’oÆ=<"d#D­q­O{‰3Äfmø„lò& žŸV4íþ{Û2ß»&c;&ˆ¡…®u ¨AU R†EƒÛ_•~]Ó®a™%r×êOéß2þ;"ÓM¼qÉuÓ¯^“rS€ãTpÄ^µÁ™’F~5jjÑ„‘8œl–tòHÁ$J!U¸‘¾ß[ôúQó‚Y Ó©ÐÕ`ÇF6®Å•Ç„±×€,ÇV[Ã2º; "G$B§[þmbü¥Ê`5Árd¸»¡bñᥭµ&ê]ËôJýÛå|uD‰<ÓW4ê9ôÁj˜4ÓrôÉ.’3¿H4øk‰FP®&¶pýþè‘¡ t;tŒ=‘ã¾rBÌ9€$¶˜sI\¬mk.mý#8DR!•3 ‰æ[%’ä™ ˜…bÍ4AÔ­!$`ao|GbŒ ì \Ë®PoÎýCý€â Ì RúúÍÈŠ®F«ð›=Š6D ¿ÃfQbJš[9Nl\m.rÃÅûŽ£lº@©JÇ)Mz8d„J$Û¨Ã׈}V½àÅóZ*CÍàÇ’|n–Éùf0pØ™ó¡G<¥Éb!L1غÚ'ÞÅÂ¥®Áz µƒ²LM·Þq¬µ˜xG®¯¨›.ªœŒy„$ÜJ7ü¸ÄBd0¨1³Ž s$ˆ"—œ; Z¢²À†ØÓ1 Q‰V>#X~EäÌäÞ5±B±THC&@é¸Íze¸ = €]<âÐUÙdCŠ7!¹¦8;6i.…ÓYÑ’‹[1`k”OÕ»có þ¨+Ñ$}âÿ¡Úb“<æùÅ4¹ÇæLM¿3³…ë¢a $)aÊC CY€ÀR˜c'ñûß#Ÿ`™ Ly¯h˜’axY)ÆQL 4&í¤ÀOc(q.—ÇJDeQL@l ÒRÊ›øfa ã ÛÇmAwDFÚ) „òÅ?BV—ÜhÆ^FVÙjŒr¡ÙŒÇÃÀ¦˜ØŠFØãÂ?F¿%¬büFl|"3ŠWë™p>Ã4“\1fŽÌ†±Ö2°jCs±— MÙûlDó‚ÌÂØ­ ¶ÈÁ³¿46š1ŠÝQëÓË•i£AF)‘0aêó"Àa2 ±?sC2_Ïï²*Ò¢6R)HV “öÄ> kpÖ «yx½ ›&ºT y¨Ri‘6mŠ÷…!uÌìˆ(TƳ>Oäü¾]3ûžÛ†¹†d†Ça§ž¯½$"{à_>ëá¿}}«Ê÷aNê¾KÓd’§ÓÓÉ q¼ùîŒiáÆ ²}¦0  \äJuÁÐèhÐÏøü_m•c‡ú®Ùs]ªàœ_“ßÏm蚦 xk€²oþf€Ëó;ì/ÉüŠ\%á lÔ!ïbËi`ß–!~r†¨—†þ“<.MPÈ"„Ĭ€ 1©»öbÖÜ*é(ÕœöŠÂâõ8$^ÍïÄж‚:bÑ‚jes>j"«1Ä„ãEÇY/ -o€1€[³ËSf¬>ïùŸƒ{øIÙd t…ûOm'Æ»´ÑÇc-VdiÇôPƒLA8š0È ¥Ž´‰# à†”i(Ûš€jÅZ5H¬zËbŠVclŒn&¾ÿtûÃÃ|EÇœF<ÑÀ͛ Pli"vQU¦´B°”Ó‡ûÖPô$!1‚(É ŠÁ¼ØÍk ²ðωÁšÊ¤ …£H¥© …IŠ#$‹$"ŠþtÂÔºŽx © ˆ4hx­û7h‚ R¢BI$azT/#˜,€ŒFŒˆƒ_‹çH£`ÖuQ¾JžÚµ_L1Æ’Ss·À»0ýè6)G(áÝwr×gÎÊ5 E‰p>çBÂ(`@Ù‚:¸Usm¼š¶¿:×㔚£V«˜Ô´¶ø×[jÖ« jønjM­¬Õ®ûûÚ^šé½w7žhÜÛ–·ºu+kT¥µZm Ð .gr ! å¨Á—€pš##=X–š ®JÃÓj|±³"diæØ4G/=ù@àŽM0¢T1 ’Iʪ@+öâáL&Ý+¶izS±üìBd=O´J~¹û—ÑÓÅ6+GîM.Cm¦Ù©·z$¾ÒŠ•ûu_:ý tci~§UÒ%¦ÁÕÜ;®]nØP¤c¦º%—!¢‰•{ÀQ²YÎ9J§f“N5h6¢WÀµÜ* ‚Æ,°‘s‡"15nk m#(: ¿¢òô6"ðâ˜å ½ýɵ_£M¶³ÔÅ.«s^+µ€¡0ÚdÂ4N†0ƒI"Å]˜5 ‰ Ü 8Ý – þE+ÂÑÁ„R‚€F…j6òÚfúoCä÷{âµÚó]¤ˆ©|.–ìÕÙ24ΖºÍF’Yr5×iÎëmµvªévÀÓtDBHPÆDƳ+-²ƒ’cˆccm¦¬# Ò+V2…”1Àl1Q¹SqÁK$BAp‹E)îÖÛW›\·ŠÇUÒ‚I¬cnjóõ¯*ñ±å*ëm® ¨ qô@àÀïÆ4¸j0"$#ìÔl®¨I!!HDPrÕ­ÚëuÇ:ìÕksFêêH°””Èo¥ÂHà}¶"¥‚ýô8˜Ëƒ³3øîì×ÅÙ!!}×·—~dmüžoǺm%3(›M“2P’HÏ_˜½6KðbŠIE$‡›.rþÁò @ED(²\›ÞÆÿçaSxs«êÑ´òÐSø³Óy?Œ÷¡Ø ´t´PÚÛÎdqž®£—D}T;©ç·û…º+ë4G*DºÔFg/lUþsFÚÆdˆ›2Y8µ÷ Å™ÊSµ‹ŽŒ󷄉PÓšiïþ Ýî5ìÊÖoåÜ3V8ÃL¢â4>¾d4)ÓÂöÌ—³Yë[C?óÿVˆ´oÃwèìÜ4þWdþ=™k Ç‹Ò[ON€Wõl…ÈOe;Ð’%\ÑC_e«[é^oºåÓfÙ”¦¦P„pØD †ððÕôd¾.APþÀ¢éŸ_ïŸü²¯"DÆPÈ|« H!úÉá”­ÚΛBšË#÷Ð…T5E+}äiêŠ Ð6ÀÇ€Òø®ð6f·­P™R&‹- [­ÝÕµñµòj- ¢½ßñþ·äS)Б$¸Ð ©ÞEu ‰P¶6Ñm_ÇkslTh·òÍ«üœ G ªcc?>ádp;Âo}Åë¿"À×Ý«Å%&ˆP ßÜ©¸,ïÛv=ö\Nˆa>zeâszFBªT$$*„¥"E%”Ìa¸?¡ºô__)6Š÷&7X¶R“5`“sƒãœmx1"ΠcÃÔ|ÞÏ£WrEêGÂÀ]/¤•Š›$Õ$NÞ—qׄ@0€0š€)¨Gi(ÆÐÈ6’Û“X€$BE’ !ƒÏ !ŽcƒµCE FÄ€cc¬hjµ'—›& §f±bÅG™ˆ,µ§>Gð6›$ï'âw`æ@EË ä\œæŸæ"h B!€@¨0¶oÇ÷[˜Ù6ÑLü}?Fß}ôúI”’ÐQl9¸ÉhØÑK5c4·k÷5o×–‘*#$EÂc}E  $xr±µòh4mZÁÞ¬[ù-ùFÎÀN†Ú¨&„%ÛŽª2‰DŠ×†MØi“PQ¶§B"n&0€UÔ“PÊd—[‡J_VfLó#’”ûõkw]Ú÷ü.ù&mˆ)R¿7Q{[[òöüáкVßmVµ¶BB=FËÓefN:Î!Âqx]ûtê¬^ðló’@ÓbCGd^RÐL[à)  ÒÌF@” Æ5X"¨DåR-"ö¼}§[s`ê·ï]uWÍÐèhf#¯BQ$BF0ƒ ¸Å€¡i ©hZDh‹´›lÖÂO*&7±h[qjÄ÷—u¤$b"»Y}ô`h|6‘è^9 8chXÿëvh1¡›€O¦ñŠ k 6Ãò¬*piAÆø"5…¥ô´1r@¡dœ4QŒÅé¨&9ñ’DQ7E€ÏªY5À„zpk³lƒ`›°UšÈ² £¯ˆˆTÈ\üt›`›£ êHgÈÍÿd/Ñöð‹«¯ÛɯÇ@FÌÌrLX¦¬lŒažFG~¨q$ÛvxçÉ4>„Drë‚B$vF`ƒÖN·ðHý¾æŸ‹Í]7“Íá“#²âj¼ËŠZKF~6¯fÉ$ùÄÄ«5MYŽæˆÔL2Ô0lÑì˜Æl±±½·Á©Ž3ò¿6/ÎÈ^bH8–ßSPÐDþ ]ƒ¡+¨4­T°Ð£#H\Y[|XÚ“+¸t½â—óûÝ>ŸI:p€ k¯Ê“ò iÔp¸ö „ÚúcDtÐXŠqù7 ö"6{Èœ¢›z¸êÀ R nqú7°œLqSá ÂŽÇ}[²™bO-vòó©<¼H+ Jý÷åöÕ¿B`a±±&ß(;ñ 0`oL 10 4\CÕî9ؘÂnÚ1èZˆ;ú Ýì¦ %õþûYò]P<Ù9°†¾+Çg`DŽHѼÀ×ÕúÉ3.Bý0QÏûù)»¼êWmÊNgóÜêq»Øh³^$ñ[¿£ñÈPÊc"4Ož½¦®åáÓº)—ÍO»iöñ@ÑCc#ügZ`Õ8û£COõðšÜ Q‡G§'çf8é Þ³¼N\zJ(õWx?¦VI!ƒzmÐÝ;Ö±Üd»Å/þ¼ÞÊÚ5{1#´€Ž쪃¤;òÉŸ´É›ó¦¥ç¸ÖÃmÔ4{)ï0T5F!F*¡á .;c£W¶°—AHBUQTL¢Š†º™™™˜ƒõLMoí Ù)eîÒF*R„*p%ùWíÅÖ€îy^ô¹—µÛEÏV¼¡°@ñÈ"õ{®“C¥°ýEñÝa(¤Ö¦±õþKâË÷ê´0Hƒe™ôôz²ËЋùp^Z‘C?%6a¿1ãÕ×”q1ä¤uLËÒKy(ìt—£7‡ ¸™I·Ä¾ž9q@_¯\r/. ¦ Ĭ1G'ÜHLöõ‘Ï Î~2Êšp÷²´«œL§Éð>ºí{âù¯ßøÚ? ¸ÈR­cmÈH&7cQ’¶Ùp¨M ˜££ ] ¼ ÞÎÿ :Àu × Þ½aàþK6û¢!š _,OòäÌEŽgÂçˆÎ8Àº!ƒ°j鮃¯t¬$!°]i·Ä/ Ìã7µbµ«ë–¿–ì¶ò¼ÛÚú An¶¬ŠFù.ÕÅ»YP»4Ngž®1bÌt8q8²ò<[‹„Š2 QÄ„“@Lý² &뤛¹Þ K•»|ã-6Î !¥…ºòw÷{Þ>“}à^½i ù`ÙKñ¨ÍS0Ö¦ÐÁk ˆ\™Coq-òüùÔ†5UF5ø0M˜¦™±…´Ù]å32ä†<Ðpü„$ÌJ!$ž"Æ2cý‹Î[T°S€1D(Ù8¹±A²ÈÂ%ûíÜN›I¼ÇîûgŠžArÁ{“÷̹6—g¾VµÄá¡ë‡D؉'³ª‹ª×’7%±-™"J6U†è†n2UFÒ ¬BdÌ僋Ga‚ $ÂFAŠ;UÉŠz™šwܵÏjäUäðÊ–'üû6Åå®ogšû_FŒ5„UŒ9‚‚A!À€šr°ÀmPcj˜BLšCŽ™À@@nܨ¡Ê`!AHëP1\×#Þ-îOçÑLÒÒeó.Ã2“ïľ}á¥z>n14xÍý,w·ñï6Œ`5‡¹ã°©*x€Ý Ø¿šÄRÏFòèÊ>ï¹^þXïbgÝ·Y‘ðHvÓC6jÈÿFàÓh‰¡~„˜¾G@1Œ —¦€a@Ò–¥¼vâÐÍ<»8( гþÓ¥›wUݹHoŽÝyçV¿±ÛÛ©=Þ÷šó®¥¥\ÑÔÄA ÷?ÈØ²@ƒdŠ6DQ m¥¢9qóEm °i5‘M½k@ß]…Ÿµån²lHEG]råÏŽMÞ;;¹®îÎîh‘zBÈÊÈÛn´ãƒ]ÂU˜ ›Éi6Ð!YɺV(ÿc£½J½bÈ Bˆ#ù75ü-~éädšüÄBÆ@:iˆá¯ØÖÍ?þŸ¡Ê8Z~|JØð;æQ†Ý,d6FÜpþ4¥žL¯ýÛÆÇW„È¡cB¡&ÔæRÅcc•6 YB{ž‡ƒ±JØ;Zl޲–Ú6­T.¡K#?«ï™Ë&+ÕåPçÊP̵29—Q{EBÆpˆÃûÌÆÌÇ@½]àH°O[¸yà¨PÓýÂL0þv£Ã'qf,Ê¢SêžW1ÓwáèÅ¢Ä-žë?w•¶Û[>s¯Aãò„7 ¶ÔýŸ—–µ¸M¦Ülh¿}éi‚m1˜Åû’g6co†J\ç¾[¼»¤ŒuÇ?q­3çò$ 1…É‚`4ØÚh\ôiNTä2ŒˆHDDâ‘‘ %HAƒK¸½ÄáÙ]S.X組9µœ¥¸Z‹±2»d§WcfÚèo¤‚ŽâA‹±ª¨7ƒéc„ÚøCõ ͸$&Wq° ŸÓA,@"€ZÛW{»ìû>ßÍü¹ŸOâÿJÔäA±h:f¨–t… 9¥¢ê@ÊÊÛVeFå×p¶øíº×‘XE‘R¢W(¤‘É2Sxg”2æ¢ÇXB?ò1˜$REc²14ÓvW~À:µšm•4È1V&0n2µÃ1ûÞwŸ+G@$Œ‘¤P¤@þ¬/ï,nä]7c©1Ð:qLB1ìxC^ãö¬™(œ/’ùSMŸTöåžp‘äøCÄŸRšvֺɾʈqˆ¾Þ7@ö¾.Köò'#‘J{è…b$Ÿ€aJ£Ne©Mµ¿ŸçˆzBùpÍ›Í;¤ I ýþÇ‚Æ,jòs›03²d‰x?µ zn¾×#Ý`­ÍÙ$„^Ã8×7rY;d+¶2© %…æÃS “ ÅV-¯ï£œûlµ[ÛpZ›ŽRepÍŠf‡ŠþŸñ 4ÐÍIAuDq d€a¢À„†Õ† uуÎc5TQTÃ$5©$½ßi"èÍ¿ck†èHMëæâB†£æ‰ Ñ€ ëY¨n0D[  üE$$FX4D,¯ "ް¨¢PRpIK<=¯2Ê$¦£¥F,èiÖ_"Hºê ÅçÃ})°¨9´€Žn—®ñb$d­ mWÝ:ÆØÖûòÞX½<_92,±yºÊ|©„=DÕ311Š"±’ “*Ìb¤E|à‹£´öјÒ›V‘¦šú޹ä™"êm¶ÓƱ”8R´×5[t÷HF›(¾†³’rõ’ÂЉ±±ö×ÛÖ›û"mô_ûÊÚ‚Ôòr÷„¡c(ÉÙÑACQ°˜Àòe¡ Íéõ,äHT¤2D+!-˜ßÄI2ܘ)yÃý×ó.(àÑ7•0…ô)ï˘‚4ÄÊ ¸ÜU-¡é/›ƒR €„³*#G>[]s".'˶¿IV·‰O7[v[snÉ“ TfM`@HQ$–B1$.zÈcr¡yl7NAe ÒõÿWûh²®ÖÖe®Mª›h‹Q*QCg“nkòK§ð*øš6É4Q^VBD„d$ ©h(ÜNœ€q 1 f!°ÔcâG4M3Jôzʤ$Ìòäb̉pм!¡±¤ÆÄÆØ7ißÇ?Žð9˜&âZ)°¦qc Hm*9Ê™ráô¬AùL =‹‘<’!¬Bk·äA KçX«‡J „ƒBƒdÆØ¯’rÖ³:wxêï-×Ñy æñ8éËvîí›IkKWZ󯟽‚#sFô…^‹MÈÁø™fÜø‹ÛöõÞix»³º\»®iݤç]]¢ë·l®íwu]¬’¢7j3*Pà”"{ø˜T0 †Êäh¦y¤%ðeYϺ¯ÀÙ—g„ 4rD>3å³€ Hæô€@vÔ#KOxÛy sîòð¼«X6ws×<쀦šBòbQmŽeç,ÚØ~}÷:'OS„›§~V*– èéMf“>¦ÐÞÚ¶ŒÆ"¿ +!§Z˜C8|4˜ aNjQN:+­ŠÕ-v{7Þ˜ãlo—ŸNl6¼Ï¥ãÿqËÔh¶³«¢æÏ~W¯D–ÚI¦ÙÇÀûiœÎe¼0f&dðX±?Ý{·§­{²¯Ùe !O7åØçÃ+ÀÄ1”Ùƒg7Cn‚ÆcòkM³P‹å{ž¡¢Æ–]¶òŽ1u)ËnþÅ»z4OTv¥@…ÒH‡Vm·_¾¸[ 2´7$r»ßfÿ+ £Q³˜FNMÕwªFµY³'“ÑóÍöö æqŨ BÞ”3NÉÎ)ëó×~(ÀÓ3™Y¦maexaèÅM(›aÏÔß¶v|~ׯ+z…k³ÛaëC ñ¥9×wk¶1 ¶HÙl„›ys‹ßÄÊ®Õ࢔øuf@ÓFªái4ñàøX[<ä4ï—L…۸τñÞætç8Üv¹ÀÕ®Hh¦AU™J~-3YS¬šÉ±¬ï¢{õ™‡ -cÔ£ÒîÐF6G0 ËÖåvc^Ù ÎFÝ;N÷ãHjsѬ‘ÁÇ#€üB61cKÐkCF.Ú¨ìunN9ì0šŠuÎ\]Ÿ³×KGrF„{‹5é;ãí¯QRÈ×2ƒ‡¬Ä†5Äi¸±øyo­Y‘‰r)ò°WÊ$wððÜô¶¶Îð‘7O»Ë{Õ™'"Ø+Þ$wîðœïvc]úÒ>ÿ)­kZ ä™Ï7š…ï;\!oȆ˜ßwßøßÒibk]Á3#Û)KØûœHµ6GðàLXõGôkI–ÞÏ ©T ã­øO…e¹LE£ø}r •K.ë¯Ý{°/+T¬ƒ»öQ‚Ì:EÔØ°äƳê'3ZeÄÈO”& …Ï8¢êÔã\ç$îí €a°!O.œ~IölÂÊKh_†ƒ[m>>M»°kšçn½€a M®m7È8Þ¿•ýFW~Ï]Îs¡Œo×<dm±²ßgžwéà£>\u‹S^0ç¸jvgqܶ&Á%|¨×¿÷DÞ"{œt º, ì÷Ú[ÓóÎ/E‹¶qË™¿BT‰„ˆZ ‘@%†Á„5²fÓ|؈¬R‚0oäÚÒj Í1xÐǤXÐ’(%«„ª"¤Üø,ƒ4™›óÑQkEj‹XÖ±´Z6űEV5¬m´U´UXڢѪ-¨ÛTh«EFÛZ+h´V-hÛZ5cjÅÑj£V-ª5¨±¶‹«jÔ[E¨±¶±ªÆ¨ÕÚ66Ú‹XÛmÖ6Š´kTVѵlm±VŠÔ›mlm‹kÙµ[–ŵ¬m¢£%¨ÆÅhÛXÖÑV5k¨Ö+ckcmˆ´Z5hƬlhÔ[cEATmX¨¬Z-cmFÅlhÕDEF±Q«Ú,[b±EQlj[FÛc[$%ócG l~sªélã„ÁÒÀúqô7‹µ›Y[ªª°v„UHã ÈÓÊ6ÈŠ¤£AÃËK¥]YÝkyWݯ…l[_y†º¶²Édâg£!“"ðÖîm×!Ãþrq‰Ÿž-¡MÐõrÁ›‡ðØA#Ff¯£§9¯oYÉ`ÃVØ&" ÂG1©iî²q˜€›è?¾£›|EíïÆ.悉c!³L²Ö¦‰CÐW‹ÅP´`±`aB À… ÐMòdDUp¼rCb%±F‘±’—ÑÆ Î1ûŒ(×BIãis˵0å ôúˆ]ÃP“4ÇðÐrë=€ 4ÈÛkx @™2àÈ'UcDPcÕsPŠ]\“$ içvl@åTÉ••båxHaÆL‹ÅÁ—Aòþ{"Müï¡£†€m¹B“"Û¬ÈCRhEeek‰4ò•Êôæžœq‚ÓøçÂ¥›Á±:&53®5¢î!›†DT¡,ؘ¶„œ iÓ.Ĥ5Ãr›,¶j(Hi!+•««å>dëv‚5sÏql+ÖRÛc 'nˆÔ°ø„”pjÚíp5€bø„Ëä+š£ŒÍ$Ñpjïb$·¦«ƒv,Q²ÍI*(åËBbã”bí_qµˆ']±@ZʪLÚñsf%$ b…­ Ã{ðfôÀ3Lal5ß c¬;XfIžØ7 „‹ bà#Ç´61Gü6i¤“/ÅßäÐpB3%Åœ8Ð ( p0À¢@”8êhöënŠõìÎU–¼Ìþ7Ç€ãÀ}îqÓö=/˜Î=6áR©bÚ¸u]=—“šN˜™8ö©–POþ¿…`é‡oC×å"ˆl<¦—Z°šÏ´euÄ´ÉÊ7#%šphcå„Ò7ã·+^Z÷îcä{ìû^Z{¼·ÝÚIimüÌíùÌÙy‰±yÙ[›÷8ì¾Fk‹é­÷à?»áyloy¼ÑÜÖó6”J1œd…2Pœt†cèì[ÌË€a¨´²ÓE$ð”¯%«æž¬ ~ùf]rþ•Y!&µ@“Ú&~Z­ü˜” 5îT½ Ÿ±ú ItŒ‚Åñ-Bð}¼T’&|o "¸W ¸0’Lê _ˆˆ+$}uºô÷ØN0øþ¸rý•£9ÂEqa‚ˆî-@@åÄ¢8RM½µI?T+I…@ˈDš~F(Së,º›±¤f„­f&˜f¸o~^$‚qN4 HY ›ædتY½ß§²\|Dä"Šdzl7ú=(f?504“ÚàFÛ¤Ìbô˜ ñ/m—¦-d xµ#"‚02Ò‚4OMAZ$’*û‘6„ÀLTh`ÅÅt(QŠŽ³@4 y†”òå2¡’.#/ŠßAЇ”ÈüpÀž]*r‡.k VI4Z{5Tx•zÑSζJ­âSØÛ*pfÏkø½÷ñy¼Ã,°€tòÓ’PwŸÝ±| c*Í­1»H‡‹]6%\·ÆÌ!ÿŸfYî œüí£õ<'9õ|mìr_ $9BNÂ7ó¡A}lX;WÈk ¶îU¶7ÐÈÇ?8þ£èôAü@gæ®w/ÈÍc´ÇS!–Å5îŒ"I%ÁàŒÈ“¼maňìDØ€Y!!1 ¤,Þ˜H7Ä4Í›­višHQ”!™’uç!Ç­BF 4JsnÄñ{æ7÷¼ìñ€aÁ·Ú¦°\xÒ‰³YNÆû¶:6(Ì·™“£a9ç±»c”1Qf,…ˆiÙ®jiÛöçõyCZžþù1ýo±¾Ö¥ïüŸÖ“Ù÷sÜOq뜮Ì8‰Ç[ìémöÏg³š6Ä4›Ù¿yÝaàdí×Zª;²ï¡ ;¹d¼dåówXAÕ>ž®ÌN1,Ê{QFc ï?;Îç\Îl Ãr.»–1çw_Ã?µq{%zºA¿ç"N:Hp7p³súê™~%­;it²ùÚO ¾uü^;¬»Üú|eHm,_.¤Ì,À§ÌB¬ù¨ŽoÙôF2O.RtP ‚‰RCæ{ê2_Pò!VŸ.Œ)$“—ƒB‚07H>:BËϧu^_?EñsA„dVBs@¨îÛö,ª2æ¢Ä $ Ü:bknÊœ³{{ Üwðþ˜sÏúLérÉýC_s9¥|ä97¿ž)Á¥>Œ·a¼_娾†ì7}}_ üŽmuRÝ8ÍÍN*¬M¤v0ÈR”…¡9w|õ1…¢rHLiÂwFNû¥ô #‰Ðrõ Ÿ™ªyg P¡“¼«O4ãý{Co5Oâ´jjmæø·õû›˜ÙºfL*#/Œ2¤¢i(Ñ«1 i2–©(•‰Ëu.btà°Ñü{¥ø_zÓž*\€„ÑkcS–•›2TQ÷°ðãY®œ U „Þfñ»!%®IGÜÂ'´Ðc­)³Çé¿ æR9!4äo]ƒÄgÍå€V härÛM/à^ü8tÒ±…¹Ùøfu®½¿ªªp•zgë;Ëlk˜Í”A·2êvæˆAï–Nÿ‰c˜ì×OdËcAؤx4³)Gu vµ–"Õhá¡ÍmN;ô,ª5†klH1yÂSØœlvïänk¤B|…b%'¦Uëd,Œ[•¼gY&À¼Þö´„«Pài¥Ž6ùÏ $%÷xÛ…q¹%Rê9f ’™”H,Lµa¸l€pa ‹à^mZ[ —Ÿ=Ðèñ/ŒôGhÀ”d>Õâ„lÛÓ#B¼L”üLÑeÿÈÄÖ1³UÎGȆ½»ZÞój…e÷w[ý.K츖ûß_fï“AWæJè*²}óÁÝäHλ‰qèD62Ô5|À]š<Ôiƒˆœ”Ps}½pÖôÀ#`<\¨oΜ¾8SW/1ʳ‹äæLŽÊ"ä[y<(  ZÐd`H›Œ/¼E¢á ÁKiÊ|ªx1`$FÇ RÚ$ߨuYh‡¤Ídκ$"‘ŠI"!õ2b੬pŒÚÀ#õöv¿»ÒãÄ ]g‹VèËÌ:8]ÏA*'G:ŽÊç=œç~ÿà{nëÿoÖìÓÈ´@Óþ¶Ý~ãsg¶ñ|üp;u“?‡™¤~h{)Z f4‚)À <9J›{¿ÍŽV5ü·ur\Jäéa‹…ÑÉà’ø†Ä¾FúÇæô#ðÃó>.Þ2|“ǃfŽœ ˜Ͻ)K便;¾‡åþmº³UÊ ƒ-2cY,hSñvÃî7Âê"š6¹nÆžƒµ#”k 5­Ó\¹q£¿ŠºÃ¾¶i˜=eìf“þgÝçúÌóôæk>¾½$¯Ä¡~L>¬üGp™ (†zs@Úq:äáÞw­„ {]»"žíˆw²ÿÂÀ”e¯ ÐaH„ÀF²75d€è<¨ªF¨o\ùHéTxüù´œ¾ûïE¯´ßP+,ꦴu2Ø×4tÆXA1aÏKÎ’Jw GL©—¸½< tþrÛöJbõ,ÛEU¾—•èZžƒÄ@Î"Z^üå:C=|¤Ö7m±Ð)žØí¦ûïÇ’ ÝâèïÅö¬Öùµåöûý/mï8ñ¿/g6# É;MÀz+h߬‚BðÕ?4£xî_øà¡º*<úg-nêƒW×e“Ét³ÖMîOmP¿Xh~®7§Ñ=pj~H¾®‚Ÿ£(=+ á2ïaœO§JŒ‡RžÆúõÿ㿌çw']ÂL­Û¼äuT"„Ú”ê ó´YÏcšÏ΋MÇëQ¹nÓ­T ¢/æ'7Q³saý便}÷ºcʕĵÚsýPÊ©Úe˜;m¿ók¹.½“éáÒ›­Á1vu¶î‡JÙkȾ„ù„úkÛYˆ{œ >hg7w¹•||•²‰“¢ÕgóÊ®M|9^ Ë®a§rì@@. ´põÞºÚ^úÆ>®¿»kâq¹¿}ã¼RttÝê˜:ÕeõûuµŸ#i åckÔ{=Ý0! «ÕV>H7·Òi%ú±¹TÌDŠ•U²ošWIµŠùx hé—íe]}¯5%ë—ݯw”<µÂ¿Á¾mÀôqx.¿ŽŽ sVçÚ}™Dm8š/¿WϰãTlol&Qü+XT}ª)ªjKM/¹s–…)2€€4ࢭãUçö~É­ççÏùÄÖMã%áíØSä!Mßbf¾< iÍyûî\ÿ„E¿?x1d ‰Q·%_ð¤øÀâ™; ›5ÝÃÆeíým‰+áÀVÆî~7p¼ê+Q,WY ºó‚E_TûØÞÙÁ]ÏþšVØ,š›ÓçÙëâ© C2¥Wç›aìÚ%âñ—(?ù7w…7õýø—s¹Ýþ»Ó)*m–έßÇ»k¡]ÙÂnïPýº™·ž÷éÍaîž…&c¸úœÿ3®Öp¾ »+¶<~Ç3ÞÙ|2ߌé™Ê ü}¢ü6šE?àr¡ª}PÇ=æ¨LUV ËjÐ~5ŒM¾^t÷yxÓ‡íg9îQµq•süVñ-w×mg?Åé;ÞÈp2jžìŸ”ö¥a†+ß]"–BÓò‹OO}l¹§ãW£Ï®}Ù•NØV”¬ÐEa,8žsZ†ÖÕ[¹bsj³ª¹;G?õ‚]]!^íÒjW¶M:_î^ªO2„+‚d/i¸À×*)7JÑoXpÜžîû•âít']Y¡û¯ö|ÒóðëÈj°˜œ»(l7ÃoÕ¯ð+Pÿ¥¹ñ6+Úo”!@í“Í?f'C)ÛUÆa›[Åôšo¥ÝRп•¿ûöë}jÈû´ó~梶ÑùåŒoà gòÍ]r–4ol"[r§·“Y¥¿/¥‡eìüþ»]«Òæ¦!kÕ›p@¾§+²á¯#–©!Kò’L>4Q?Ï®Âì®ó~8‡ŽÇJgÅŸµ÷é¶~[–?ƒ–—?»ÞîqgÖ÷–/ZÍw·ž ˜ë·¨îåùù ”F®Pòj˜ š} äÛq6òµ}S¥‡*­¬{bQoÚ·ïn³» ïn;SáêoÓ¸Vw;,Χ8·ø—ƾư®Í\2™žðymò Û”ÿ$bíÖ×k?çßd~‘™×™ŠÈõÞê¼’žíÍEÃRÉÜãý8ó‘Ÿn¦Â²?£Šæ±Øïz¿¨M×û§%kI+ÒffݧÐa®õ‹sž'hÍÿãKÑ_ôtó|ϼ#ý»Ž›­”ß3EpºW3²#õÂðõ79ÌýqÏ.k·“²œÒdáiººˆYÏò‘Öéûƒ.k‡ÔT?l<Œ?Hø_Å%#öaAN§¦‚«a¨Ãe·9e–Ò2ë$íÞäâ'™{Ò縘äXɳ@  '߶Ö›ÌC¨ôvAlï4Ý=ëÚîec0ëë{M<”¬²†¨ÃÎ< žB û£®…šrâÄç#-ÅâãjÛØ`˜qßòe’wH_ˆ_òô4êõ mQú›*ÜŽÌç…?ôÉy­³ñkë½…^ý Ž_Vż’ç0ÃÒ\v [{ש\MlݯÝQ#âñ/q%%X•ñNþžLÇ9Y¬î~x­prº¯Ö…Ûš¥"î¿fÁ±­°ðïx½­ïC­ÒܶÖiW3¹ÿŠ´oçE›fÊ!éÞå\x'³þÕÇ=Ïë_ªÑ8ì~IY& öꇪ± =Sòaâè9<çjÎûÛõÄ>·¢ŠQH&4Œl®Ã®q†ç¨üòûõK5Žl/üãõË–‘¾ÚyǽçX¹É:Šû|^Cç3º@@6t̺…¦¥´ÆŒ.>¶;Ä®•jÍE9O*p?¥h§æ¦môYne¾?©ð¾Ùλ]Áø02]þµ— ãäJª>{åçÝsÖj@ Zèî›ÚûL>œº.›dîýǵÐÍóOxÖÝY¯_¿:Ä›­ä*Ä='o/]ˆÌW8ç“eüO“݆‡ånݳó?©±ËA¨ÀÂÇøÖlh¯f¢9‹I÷i§Í¦€õ¶Þ–’ÒúÁn OÍìý©îë2<‚Åbb¹óöô«nÞ%Ú¸†þ¥-Îß±À÷'óRS*ëY!ýúC{׋Q¯‰®üÉ—AJ­ÞÜ~ÿ{=Ì<Ï™íYÝCŠËâÚAÛh´›IERkéÛÐn&ñ?ò¾û5çÖéé"ºœ‚èýý=êr ¿ÃeµpïcaC´4Fˆ½þg’™çÇïu” ƒÝÆö3_w®`íÖz›Uþíè›´G_©2Š”§CªDÛÅÞdõçC&Ã6›—féQêyÙ‡ú%XLýLº¯ÏÕûnÊî÷s~æL›ÝL^S‰S5_ÚÇ ÷ú.]òv~':Ô‹MylÖöPîÕ_ÆÁ}Üú1sÝ͇J#³‘öüáÚ»ý†H΄Ì-÷»ÛwÓ×2«o¥#$1½¾£AGbP¦ûñ9Kò¿C±r,ÒmWÓõÝ$-í ªôžÃ{÷N^—bÙ§®ÁÉý*­q÷ÍV> í–¡o+óEÔg9äß3£Rù¦Ì¯ÆøTè,n»ôê]¬†9÷…àÎt>¬XöÿÖÎz7rјÿ“¯Êß©L†™ÿÇCW³ä_×moc®_¢ •§ úÜ (üÞÒ£€€t{½µéä®×.Ú¡œó2ÇîC÷9ÃéÜ7xBÎ3]å}´Ÿ+½ÓçlfA¦¶D¯ŒªöêJ#ÊÑÎLüi°Ù6j'* /º »q Ü|Üš·]€¿,³cØûíÞ÷U!#®`íjý™¬ý--s€€kbÔ¹+³Ì ØùI‡¯/ޝÝÒ9›}¦ƒÎÁ'CK8â?Ý7~«Ûbý¼XWe„Œ,oN†ž®ºZ£É#ÓÃ袚·ìrS“×ãI^3™Ãm0©½Mñ·Npž'¯L—ö%žC‘xíJ﫺þÊ'ø^˜Ž{´?4©i…JÊw³u²¼ÈèŽ8âjª-Fn[ôýî܄ȚÉô½%VäËAü§²]î7’›ë“ŒfãáÓê[ñb%cïòÜ},.ª³ÅÀ©²ƒ–ÌÛ´üGï/Oct³d{à1®Þï¨`7›¶Øfâ$Uk² 9:[Ô.kA_Çvô™- Õ¦_MëWì+4G•çþ­;6ÿÉODªËˆcN‰óÓIU®vºŽêÞU‹ŸàǸ¶È2ÁL½ie>²ówͧpѦæd÷rÅ9üŽÃ|«côtÖû¿ Šßûü‡£›xÍò25”jÂg8¯-¸šú |Í«ª,t¢Zð¨¹>ikßÂüb:ìd/ U³¨ ÍÆûlÍÑÆÚwÕ?*Íj9¼µâÚæ2Ú7$×áñá³(zR eY¯;¦rIr¥ŽÖ™yÚÍöM«a„p7þ ´”?¨¶ ÙmTg R¡2ÓÒw¿`œÎÿô¢èb]|8Z.ž¦½cõä4ͪ߷}ÍÂêí7ü¬Ä-n zzó~ÇgÛSšæí=›m_‡Õt[Nj ü_SJí£GÂS>q6S”ÓIw·ƒéõË4·å͘”úr±©Ÿ9–zžegÛ¿±¿»Œxéh¯° 8FKºekœXëháªéWpûh嶦_g9‚±öœÖ+aO"wÈåêxz˜Oo‡½íõBÓÆv1ð¾®K®®SÝcÜ´—Ì:'íÁ-]ëI˜ôîÿ騙èh+wEÛÌqøŸ÷›ä¿ðEýåü6+‡õ¡ (¾ÌІ)öjœC~»éÞáx’°ºˆ ¿·okS )þUÃHØ$í@ ÎÈÀÔüó*Ä—•Çü0ÇA ­æl¦ÙMæ¿s/1—f*ŸÌ¶™“p‰à0,dáX\Z8«Ïi“ÛôóU£Œ †“•^É=†ßÛÚ~kÕ´Ij£?¶Ç´Þ·w¦×¹\„ü.^†‚fº%»ÊáÅ¥ŒÑl·­JŸŠ}^ÎwÐÉôËÙ¢c>°}M^Ö·îßI™ìa?GÒ¨o¤Úœþ]HpÙR¹7È2rfïj¿iÒhøâøÝ?îqo£–Sûrnä.—9}VùþÕÇ ©– CõRzòe¸y¨åؾû^Ͻž—·p¾ÅÅàHFÅž‰Å>ÒeÕ âû6%ÎËÇ?•éî#çô.³~]|û¦#«LÏÂKÎæõÿõ‘fEÀˆËpþó>û{-æIµ2k¡ßÒg—¸ —¡âSQÐYèÖûã|ÿ=ƒºÿ±wì½bˆÐlj^‹a/]õCÉ¿áç0iÒvgúÚ»súL<Æ")'&WñÖŸÈ]Üm^‘Œ⯬ôő˵m©ž’ú| ß/D“3Ðçï3œsÝÔEÿ:«]ˆ}F3ÅœÞß N²f̾Ä3zxÌírÑLÛ×ËIk÷m»× EÐïJs$]¸\+KV,ru&ù¥WŽ¢½Œ†–we°C6ïs£ïâèþ+½êºÕ„2Ž)ŸÁƒ—™2אּ{ˆ»A»ƒOœÞ«þ:4žû\ž‡ý¨ñsþW//';ÜŠ|š~Þ®Gš•ÛÔbÒi6 ~½û¾OˆŸ(ҜؤÈ&p“| ù<âž«qÓÔ¬³i›ðüŸçÍsÀëöÐÁdÍòæuE€˜ôZÒÿÊ÷ƒ-ô•‰²òúGJ‹Caƒ6ìÁËòî(TåV¿þu*ù/s§=WªœéõR{Â=ÕÖ=ýœ±°}ŸŒ…já`î2”Ÿ‰dÝ‹¦%ESæáëÉ÷;m·t‰Fí}6PíV¹¢³A±ß øpv®× ¹ûþêiý¦©³ùB€RPÂ!ÌÆšœÑœð©s3Ï”ZÏfã½¹zÍçSˆ½¹ÇÌ<ÿÖ{ôø°Á‘ Gô¿é#ä/÷ëmÞ]î}çcäÿKKæ Æ…Ëçªß¬yy¹_S4çÏî“iäómŸ¿¿?42–ÒNG7äÞBTI!ƒ”\¢.µ5ò·i¦ÄÐd=ë· µýéû¯ùe¦>•På|ò}uWŸºël}?±æ¨¦Æ/ô1µn!¯ÞÕ’<Øç›p¹Æì½Ê)AYx¯—ð ñžÊ\­_—ñ¸Ä{[:Ó0y›Ëunwf|»ÈxÑ»g±¨6³š\Ç 9ÒêW$´hªÜ³ù}ú_œö©Ãý§kÈ/²¢ýmÜÛöòOù•[òZ¨Äœ†ÃuK\éúîä? ËE³Êî3p—KÛæG7‡ kÿøÏÞ~yK‡ÙWvÝY[5™KÃç}ÿ_!Ï¥<^;U6Ç×HóLÑ^‡ÉþoY>‚YwÙùowrË®îüØ\XZ¼kr)­:% Ö·|ÜøØ·æJLïhã%XºÚ,Ö™+›ýÈÓ³Ç/ê+9,͹o„¯…~ Fš¿øçŸó9=îµ»zyÉN×į©Ê¿¬Ö¥ÃéÕnºž&½|·œÖ6¹Mıނ0ÇÕÇs»Ð–[ø8 çK›sŸÝÍù—±¾"JeGzs?åúî¯k8•*56µN'žPl.jÿ ¹Êáïò 4®¢ý\¾Ç;Þô[æ} Þ§U ÔVëßëð#]–»\³‡Ø³ve“t.îNïÍy€ÍÿÔ«æý”ý<ÇfÜÊŸâ‹f ŸÍÜ’; ¸ åJr:žÌC'´8§ƒÒ÷¾:åÚ÷г\êÞ¾˜€€|¼ŽY<ïßF×;™ße–ñ×Ó{Næ–óqÐÊ(ººÒ{RLÛ8Sú|} xߥ¶ùÿ–ü;R£¤[Ûîüt. vÐx»¹Èhi</rO;ßáÍùü4¾¥%xb_Û<‡£ö›{O_òÓ¶,0C¾m´¹M#ÿ}ö¿\à úÿ0ýmâÐOÜwñZKoœg£š«ÓÞÔn}x˜8¨Ï¾¦‹¹€}ªbÑB3y†J‹›¤ÒÙÉ#ìs`š•Ü}VwEiI¾Ø7Àð´³Mzôó«¿Š¸Ï­ÿ±c¡³pûCP·¯Nx¼·üÎG{e5¢ÖNÕDhXR»:>ºÕÞe±G Úª }­âÞ1ÓÏ÷}½Øxõ 9ÿn³r|}}1.û + }>[ú±Ò‹öQð>’­Vßözý;· ¼“èVVü)­Xß³o_%ìòu_øÌ ÞºÑÍýg\ែÚÓv4PšÞí¶úVÛ¹øìßÿZ±OwTúí4Rg+§ÁÃîòl‹\ß gŒÛüþ£åºLÝ@h+¥ržFªÉo‚szëQ©gF«]°¨¼`wäó¯§EӞǾðFfÓ´½³–?¾¾pÍ·\íš4°Ðñe¥¡ÇM'jc½Ð¦ëàôù¯›ÎW»†÷5I!Xõ¬-õ«ípÕ|÷DÍ ìì/«×~‡rPtËòw}rÒ„Ònß$rmE×9Üÿqý5[·Æšö÷ mIÏÑšsyÀ‹Òû¾üM„Êö£Xâãª36ßæôâ¿):û›TJ{ ¯d)öÿýOŸvñYú·s§¥Èƺ¸nyîZ·({Ûô·ß‡ÙÛý ÔêÆ÷ñ©l˜™­‚¾1ï7÷ƒÛî8³”ŸŒ¾‹_'ÏìLR^[dVtOÍ©(/¦cô>—êËfç[) õøcKˆWoú¬„é;ø£cüo?¦|þZÑ©-ëGÝ™Ôt³Ùœï· ¼é/ëTvwlÌÙùÎ[DôýW—!Õ½ˆ¹ùa@> œ ’=Š”]…»›º™;2¬‡Kóÿ+MDë–·ùeÈöþ^ckéåÑÎ<°ë¬º ¾ wWLö‡ÈÃ÷¯l‹¶ÐõõŠ\ü¼GRúã›’sÚÞfÝ<¶pÊSnï¶âÅu©¡48ª.{+6%Ë—*ú­SPŠ*ó§>·Ý_ª­¨¶–ªÎ@c+yüîEcnºý^k¾ç+MßÝÿÙ5”¼nϪq|àupý­NÖµMU.CeÑ/a³´Åë¡§þ»Ö}ü(Ò§å9®lno¹±Nÿ™U÷˜¬÷Càóø~Öòr Ð\˜gd¶™rö¾…Æ*‚jÙŸþ¯fRMµºà Žé=ªöÖ{:*òY€Ìu#;Áï P€š¥§‡,‚££ó®o+kìAû[\î%àå7Ún)Uêï3ºëäó¿äò¿–ÝBbG® Æ÷t±™ŒNïbÜ㻕 >ØÚ ÿ²é—…½ù±¤à/½ÍNâ*Ÿz¼½õÆ%¡µreó÷а±]1a(v£ÿ}¬RçË‹=ŸÑ¸¿:}¬ÝÈó=|îF*K7âK ÙÅá°ÒÜF3Ú™I—x6Ì6imHÃÔTö÷þ½&¬ðÞz;‘ñ*œ¼}î3 ×:냴úÏç¯iþ ìߦú8F-ncÉf§à(¨7oŸìЧö1Ûe~On Ù˜¤½?³U)޹ÿÜ¡[gï;E…骜Àì©LêÝÒwXøUïbâ·¼|üòÎjƒàÅæâÂâ­š:ø.fŸžW ËnÙYPÑÂáãÓ/uwZoÓ¸Áö¥ÝƒoG{×Çìµ7lã¶J’ò罋r×ñ7«}ªÊ˜ÞK…rÃÖ¡s¤³š;óÈå»^%öI&Λ¹ÍìÕwR¶ <vÙâÅÛ%’üé´š-[®{mÑöJíýf›Müòyi¬¦ò0šo:¿çâËÄíÀ÷.–º¼ÞöŠËpÖïXn²»êksÖÿ#:{gx=M¦Â7Ósßhu3ßE&‡¡ösûhù{=C—»˜ùüÓìtŒØuÇ»ùbì2 ³?Jó0Ü—mV¯?¡¤Ùrì®.N Ëÿ%Ôh,»òì—\ÅNÓõÏ„äkÅþG˜Ñˆ–IÏ¡“Ïy¸(²ºîR í"½_bJ_S«ÜUjyžýG¦Ò3 ˦ËV×y»òs‘/öŒÇ9¿ ëŽÍ‹†¿hï—wŸûgw?ªVþ…kÿ¢1¿ó{|íi q™Ìý`œk#íM`f_‚t‘ûœÉn/x)˜]Iù-h±É¯d­û¸žÖ!³ ¥sÁ`ì°}²J_w¹?²q—€üÕ¡ÿ¦õ¹MŸïÇ`bÌEZÕß^HfÙ¾þÙÜÁÝr_§[ÌÄ»<<ÁOÚs³·›ttÚή ±›’öIGI¿Vøû°%WHãoÒûNópL]&§…¥äœÕ95êÍdº.ߺ·» Õ£zôòµZœ%ü Γ¬ŸôX^à³ó(©üêB‚k×—‘ÔE×þ$¥¾ÙqÜþâ­¼·–‡Ÿýݳˆ¥YÇoù°ºÎß%n‚ëEgó÷µÆµFŸ|Å:xlÊÐü:Ó:妸ŸûY¥Ž§8ºµiž„\ Z+k KN8EÁʹ¦ÍÅaüð7n³<ðçEá´œQÛ~[бžU©ãÙ0¹,tY?ó’e5”dŒ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÀïBÆ %ûƒÒ òúÍ™çjCf…Õ·Öö0-²$|ãNõ>ÁÑ<†óЕtq=^ÀòÌÔ¥{nKn²—¢€sgŠ€P€@:¯c@@: Hk  > ï³ / »ß*>oq÷›€Ñ÷O‡!zœ÷ÜÔ Z÷Þ¾ð9ìSÞŸ|ûÏlÎî(ÊzjÏ=ßCß}ðxúÍm}ë÷ÓšQŸX%æ“ß|ø€¢¼}÷€ãXöéÐ÷Õ}ôßnÒ¶e‹çØíжÔÖoc’ë(»;ÇÕŽ¼¾¸¡W ¸ÑÓ–Nîí´ï|û·gßÇÛqtK›€ï—Þß|3ºáÝ€·kï¾ûá¾ç÷}á÷Ì{ëpûXÐ “{¸ú)C›¡¢Š}ç+Û>†ûΣ㷘­k=0 ½@sGxO@ ¥4<ŠäkÍì;»» jF¬š‘¢€°Ö|²xô€$dÛ„hÇqÖ…9iJt t,€ˆè7bޤ1:T¥ð}·ž%‡¾ÛF{Þûîò{Ö%‡ßJ[ÞÇÁ»ž¾ó{VØÖÞ³FÙ‹›4Õ ;£1ßBÝÂÙ.¸{ͶÆ©*îw@>­v¸Ò¡-iox{ßbØ®›˜éÑ}ãÓ&!îô×tzÄ(¦æˆç`ïKdñæ×ÝÀ:û޹­§§tÖÄÐX‹X+m™Át#·Ü݉–…iœ¶u^Ø a¨ª¦×ÒÎàí¸«[Q[UˆBÛ{½÷½¾ÉÚR³¦Øûíè=@RTU-j6 [×{ßxÞ™["²•°,²¦‰¯¬ŽQ _\ì'œ:€Íî´©µ4Ö a©H÷ß]½˜ Ù6Ë,tì2UФ$"ÓbûçÀ}ìß\÷rë[T.•—m§° TIH'XûšW2e©¦n»«®¾øû{²õì»ïyÏ¥]¾µr{Õ}|öåQ€&#2i¡€F`š 2FFM €Ñ¦£@ƒ@#@@˜A¦„€ €Lš14iOASfJ~§©Sô£òeô …?RzžjzˆöŠzG’h~’m=M ¤Ú‡”ñM2=!êiê‚=4Œi44zF‚S@$B@¦DžšhÌ yG©“bhÊz˜M¨ÄÐ4di ¡ 4Ð4 Ð ÐšI&€šFF“F¥?i¦%?iOMªž™0Õ6Ôž5MåCõ&Ôö¦Õ‰µ¹ŠuýD̢ŸâñSTlY48Ìæ»KÕzžrÉMeøItÛ nªm=…?8ûžf;m½0ÔÌñL)<èŒ4~VÜ[ׄ”&:z©žÕË'¡%½O=6k¶ö³‹ÒɯwYfZê^w™7ÓÛá9`50†)>á bª«‰OЍÛnnd d."¸PýKQ Hah:-´©Ž03. E1 3"e¶Õ.YAÄ13 *äC(²ƒs0LJ‘q¬ A`¶KˆcEGñ¿Ö\– ñâ(z˜€¯3û`'±€ÐÅ$-ÛÄzxGÎÒy¿Bñ qê 'êÄ}o– ©³ß@,îà"g~çY?ãë}[sü͇²y¿x0 W˜ƒþ°y’<ï¾§ølæ<íl¦ßÒÒ§i=_Tþ'ÁòšsªÞÛ"æÝãÒª´óú ·©…j¢r–cÆe̽9nTÝF;æ*‰*s2)ÞVY—URæQwjR§¼©©SÒ‡‡ˆd—j®…j’È.bnÃyt» ®Ã-j»‘w°Å†Ÿ-û&}pý¥&tèbîÀ‹Ë;ÉaŒ}@ÕSXÒÖ…GÂ…Uoô2êæTÌ¥ž¢q9DÚÈbU.fŠç ®ÚG3…Í*Ò–,QÞËÀo ÌÕ hǾ;5Á™ppÕ· ”HN˜`ÿsõ_ò0:Μñß\ª…o‰]“p,Äî¦1%6Ó "f±C¨QJo&îáVN@«*&ÑO/yŠfËÈW‰Ñ9——‘FVFM–EÛ©{¬äìËPéEkRõ¾µ–ÒD¸”´…)_>ÝÅ0#âÇÜ~=>ye?‚ÀÂü¹è.=W]‹^7ˤ$?²í^šÈŠ]<çîÿ•ºßƒÚÿËÜõø?7V€ÌDúóù儤HõÿXùÛVéGÛyšÛÁOîý<7Âà'¿’w³ç]Pïýµ†ßÁÿõž~åõÿK¼‹®Š*Ä€±’@zŸäÚX>t=¤<÷Þ¯×êüfˆb¤9„@V‚‡âR18¾hºóIŠ..®W«{š×‹‰£C1` =dNª<Åî,zX‡åm¾¦+“歷;iµ†N7 ÛX;¨ÓŠÕ×yº7Sôáì:Zò pÝʃ>ÑýéÊDûeb€t¤ ~Ž÷¹pïa }Ekm³ý—“^{Í;‚÷~´J×HµÄ é@¹–0„Aφ°à'Ï1½èœÜÅ9&™;„Ñ)ŽÑMýn“I=…Y½KèÇš@@HT3÷/´ì‡×µZíÇן&¼ý>‹_“ƒ™ÌFlòæÌkkŇÖÓ™¤fñf¯“r7&Ud!|ÜfŒ‚>^…}-ØÊ;»¼e’ô³¾TæMQ#uºxO úP|´iíèNÁAž’’GØù¡Šô™?/ßó ¥^†€÷!B2&Ó!_Ì"Êrÿ²æØ"eéù^m@ä³4ÇŸšs“?úƒ˜è}Ù•3Î{¨L•Á¾Õ‡k¯‚ʦ)·Ó\;ïD%ñ@! Pu¥;,ÓUÕ§÷[pè¯}RÕ2-‡åç¬mr5OûÖhC Aˆm>Tü ÓD8 ¢ðÂé0Í»M÷ÄâÞoMÇ¢&d¤ ‚/î\Ú¦‚²½„ý²AƒÓé—úv3v=‹¾ÿóýòN~”ã×Otu´yHýË^ƒåoÊ®±¶Ãð~°h]H½Ýauñß2Òj- äÒÝ#»ïEûÞ«eÝmuºOîëäfÎmüŸ#o/¦«ZÒÒæØ-ÎÌ2ð¦äR¥Êe"Õôß®4B´iþ¼×†šÃ‘Î”Š–)Ö3QAÒ`¼BoÊB€8Jö-5ÍuEg[˜’B~x:~ˆõîÙc8ûg,‘~Û%¨ð’á¦7þ¡h’°ü}m=¢î-œþÑOq+õ‹S­¬ùhU‘MPðÞ4ú÷÷e¨èeŸ”çhç!¾Òº¯[Lþ£ècõmv¼„F\üŠóHá¡Àé¬lœXþ?®×~&{CÛ^Ôd}·zÿ}›#KCµúÿy|.®iE߳À«È',ã=Ó¿¢ÊO¡—HÉe"»Sx¥¬Ìrbº‰·&öJ §¥xı>£RsL‚©$©ìšùgúSÉŒj„½D-íilÚ}ÅšA °`Cm‚¯ÃÍ2ø¡.›Puó¦þž/©7–õ žxÕÚäê)ËVj$›.ò¢*ü™­È¾MÙŸT/?±î¯@ŸG,˜Ý{1WSÒF׎ Zÿ~÷®ÓÞÝh×Ú“;w2§Û˜O¿«ƒfïÁUX–JèJ‚këùÿ% yª“âý âÌ]œaÅ´CD6Â7îðšÃÞ~S (lݽÜ?Qè¹[äÝr±îcþ}#¸t„&Îì÷³a¾<@BœòƒÊTÕ®{9Cç1zþõmZ.'©Þ ÷ä_($sllÞH&%hNé`í›Aù¿/®A^“ÝÙ`ºóA+pÒÙÂGúÙÆlúiT—Û»ÜÙÚ¦3;û¸ÝÜã[6§Ùk´ïúá`ù³Ú=KVÕ!=ÙOyÄÈ¿@­ùüj> Î÷ÇB@B”ä¯Þãf|€IU‘ÿ~° D»ú;.\Øý­ßð >·Ñ38>òŠ¿ë¦¢­è«ž"®§ÉħÁ"†¤É þïù”þiØ/ŠíT*o¹¡Õ€#Ø÷+ãCú°ü^qù0Wþ;Ž+ñT<ÑÁpÍÍT ¦0ûE'Ú¿µß·šè‡õ{«XÅY‹T˵îv×y¥MÀ 9Pç•. (²*#QŠ"#ãßA>ŽÚ†‘ˆQT•t3Þ€®d.ÚàÐÍî4W)æ»ÊÞ k/ýoÓï@ˆ‰zìõÙQ‰3U; €ó‘>„<ò'ÉþŸüܸ”™¶ÕÔÿÿ58$èjÝ ¹õ¶®¥Î/—À©ÏÃÈsð79÷ßcÓêD d+þF³¬'¤Ž8t[yÿFÀ «Ó¿krÝFEdVAY‘¡UÜÅoë+§¯²66vÙÍy­þêúÿ¶õ±Íî­à¿½lYáíYãçŒéZÌ·i™6°e2Ï8Ea|è§{ÇÍdYbhÑ=¦â'}ký ב:ñãñsù=(«ìE[š)ïŠI$øh¨¡pP'áÎí¶â"d‚ƒœÁ,B @„*JÑT…@*îPŒÊ DB€8Ž¡±ßSûKüÃ~»{¯æZ¿Ì×oèó¯eÞÉc?ì°ñaƒ3®Æ‡a×¾Í'ƪgмcòXÔÍb6 ¾ýÉx°´äT°’HXrÅÜÌ þŸÐ·†l®êƶFF6ž £^è²ÜüøKe«m·¦ìáá™ä! èF*‚‡¡YFy!¾šcÀ¾öwÓÆCt2  @°HKÎú{®MXO¨TP‘H!"{ȉYcl7ÌvÍ¿kQ$Ä*HÑÁVÈ«ˆ1+db,#>†ndÚkm_÷öÖCè²ÛW]pêÁb“VgþûÆÆäþu`ö•žh<ÞX¦Þcc&ò1#ŠŒADUV¤D!–®ì€Ufú ™Ë\—÷xtçÝ—U¯†èü ÄAõ¶iâ†d”‘š[AOzvJÊþ—U¯ÁR[Ô½å4QË„íA» ¸­y o¸ŸfRÊùrlŒäÀ.8Â…à!sަé+ª*ZEYÁP«–ÕìaŽ©^lÎ9^ðÀÞÓøÊw?û8óôñ3eQX§Æ+ƒAªX D€ÅTF  ,€,"бH°€IS‘S˜ÚUCûhs<ŽTÚA9¸ƒŠ ü¥(ð®š5¹=ÐÀÜèHÕYIâ2Uô(ßRµ4ôœPm À¼ÙO-C¹¢jðìÄþO0âÀÙ"|ƒ’N ‹a†€ÓØq¡Žµzì‡QØó@ŸL~Dú,òŸ;ÝëCRTHŸ&Dt ˆÀMÐ\P ê"áðÐù Ž×ZKÁÒX¢‚ë㺠ì¨ÙƒBÖcvågXÉfcÍh\·‚ŠPjô¨b‰ÕkމƒÏw ã7ÌmzkÉÈJAóägXUG)¸‡,«Jtòè¥M5‰õ|ð 3Š`€8ZŽÑ,„S¥”‰ñPÁôè¦ý>ø>«U\¿×m£G‹™cMgNeðL$Ûâ·§“RðŒ^ç¾3Ñ@ðïnZŠ‚Ê%a‹þ³Ë„<ùfD{~¬é!¬|!¼µî¼xvŸKyTF2I'¹ˆ Ž4±S‹GøÐ’O×à}cÑÝÚ|‡.Á¼1j͵'ðÿµ/¯ûŸ$üðÌYÚ£f«Ö]žÿ{Hüž[^±ì4Ùm“¥ÝÍîÛËupKFS¹6!D„êÚaåf7yNŸ~0! cõ:^aí2' §x!69ymdÖ‡^ª ¼´â£ubº–Wvç·šŒ—ýunBÄ­ÀÚœž s…NõaÓ¢()Ÿ1÷¯sÄL§€:HYô”TA‰×‚¾¸0²;XYp+!v×-Òò'½G9ØëzoLntT9²’J‚†j)¿Ñ å» ™}ΚÙoÊ/t_»uû­¨¨ùxàm â2Z—{Ù6šE@ 1°æh@ Z¢¯cD„‰ ›¾ÙH ]WÏçðÀ·»HÐa.n“¶ˆäxÈÛ­z1#‰™ÉäΪ²A–Éš/ ’\õ…ED¼’„ ¥Šˆ;,YÂÖµàäë°r²!Üwì.‡²þ+F lŸÁÓ]=|θyŸå'©ð=ËÍ…d= “áú>Îy˜ °˜þ19sÇÜÑß¶ºOu°³S _Å–ø#ó*\G¬ósŒºuBŒ©¿eìŸz½[¶òZ$6¡¿y2£‡mD\ª·êªã|ŒEõ¼N¯XÛYLŒG—"öK;-Ôºb·¾ lÿ‚-¯Í†3¬¯TÜa‡Í@T'7õ±‹ü\9.}]ﮡ 7Ç&•·ä“…Tĸù±Ä}óå}ȧiòÆóÏ|ž†R‡½ÀbÖD9kó(1™M4œQñ•³Õœl’sÜeUïã–á}›cÎ<Ù•=§Nž„0ð™m··MÏû… &OD^3ƒ‘«ÖPZ½RG£VÎ-D?OR¶ê;…üÀrçmb÷º6LÕ?š¯n§„”‘ðÖ_g²Lµ¥1X¸Šæ¬qÉæ§¼-‰dé4=šTd­Tص®Ä¦¦ów*Ò®Äß!¹¥Û&ìå Àý°ÖÚNû‰¦'6ì5Sû'ø«k9Œ¤~©–òŽÿVŸëû·•+Þ¹>ŒºÖä€;½R7XÏjg¬¡2UWé.Øšcê|î©Îw°ø§…ï¶›@Y ‚º÷a‡ éÒXÖjuþ{ý³{ä¯QkóÔœ¯mxf8I.eeä_*»Û°»êf5<þªž96A>±~yZW*@çñ¡†«cÊ®7c¦9Á熣™½Ü®Z`ûxWÇä¯_ÍÎb’â§R0°©¤¾MÝÃ[«'¦^%™sé(?ê6ï\3ÝV¹A¢›Ëÿt²pٌěZŸƒó-ùú{ü¹Ü©å .^VišóḢæÂ\÷t N½Åö,[ܯH߃#‚/¥†C'§Ðúýû=YÎW$É„õÏ>~g‰z­¤OÌ Œ‰ÏÃ=I"ãß0/ZÌ»ù¸„IšìoõY‹¥kαeëýx×ÑÚzù/$Éno™íÇ}U²ÂIéfzÝÝJvv+ÛÚÉ_ÖPš¯åß&Ê;ä±ç€å#þ¹²JB+Šyª­Y9¤¯Œ>»Å³õÈ{ýêO¼§/î#Ê}'4†ÍB—5„cœ’£ÕçJÔýäZÈÔZiûm,ˆÆ6«o3u­ÐR1šø‘$¶#¿z9ôçž±ÅÈGø¤5©Ù¹Ñi_-Ô¿Çýq¸­ÇŠ:jC_¢?`ÄíR JâGáh‡.†aÆÉ m¹=^†2S£ëûþ ö®uå²E¨ÕŪõòÍ*åß+ùñ€.3·iáânå$Y»O:ìÓ‚vœ~ª¢w]ÿ'U§Õ_ ɥĘr»¹ò98‚w…¼ål¸üÜjÒ&½Ú‡`ª~çd‚ŽÙÙ—)gmîi¥@ êׯœÎ¿|“š3Š+ÜĬյ—ƒÙämØ^¹/p»‰{ÌWçN»«olãIZz˜ð[’©cÞ×ç4{æj~š$€ê baÏÀ?ÏÝÎÓ{· ‰± ÎNÒÍoÔù' _Çb§"ŸÚl5êÝ+;¶m„4¥š·«$Ü‹ûûñ¢Ÿß‘9-9¤v´hYª~N«J¶»j®ZJµÃiæ’ È(æé• Èù裼æ vN-}ûÿ·§ÀÆëW¿y6äxsÍÛü8übFÏÚÏvÂ#R´“Ô÷ g¥P†½QÄ©^·‡Tw)þì%Ö‚:[\®ë¶Iê׺ÅѤx¬+3I•øæIËZ~În­?ñgŒ‚ª«1%tôÚ„“êÙ|›Va°yžÔp¹š/<î²Ï*õUò§]«B§<Ñ1Æmìb?)‡X¹$µi~$Ï–(ñ©ÿeìnSG™§€=E¾¡’ãÐÙ\E7-û©úi±kŸV{z2 às:¥ÐݱLö-öZ>ÎK‰ÈµÅ%Šþƒ´ lÜqª2m99Ål§ÇI!û@}ÏŠüêǦnƒ¯ºKvìžLžú¦k‘¡z²`¢JÔ¦d”õbšWÉòW§ïèœÊ”©ªSĶâ¯r8K· ‘ëÙ ‹-‹Eû7(Ûu ØÆÿ¡GÃE}ì”Á¦ÅÜXžñüÖ˜vrŠ‹Ñ:ì,çÊÞŽwªÇsÐJe¯±Q„k1ó‹_ìâ:Sî6œ„$ EÛæ7i­V ôá8f ›pe9R‰½^Ÿ" gŽm×mGþ]/{|YºŽ<]t¦Er¤ìÒÊñ7þ_Í(7Pt=p‚z«dY ¿?ãÙv©qƒ"†®ÆÅKE0ó ókwtƒV¢ñŽ¿¦”瑞ÄMØQ镊ÛY-x€<±Ý×·ïuKÛ;§ðõïþ‡=Æàzzx>?Qì}7Èù+yÍ €ø0[à/’çiEW²¥ßÏÀ‚‡Õçû‹*ªl¡ºÁßÿGç…¿Þ¿{ ß.ï/†®Ävà(ÿÛœùßsäüÞ¸ö¿¯»ÐÌ'Hgañ½4μÁªÁ¾ç6‘‡öZÏìGfÖ.<9UÊv€Pó‘þ‡þõÿÎÿõö£ŠOí¢}ÔX<HЍD ,†´QJÔÑ°Ž¦Ê]åBóeÖ‰t¡K[06Æ©!ñ!:‡þI@ëxÌ 2¸Â€ –-Lþzö6éòéÄÇ$L—N8»æ÷f}m°†¬„’u)1$„‰î ÚÏwЫSÞD¡ÑQRÅP'èÜíü¿þ_Ô˜0:œü޵ENÕE¦7­ q[s6¶PÏAùvcØšúÍ™âK1˜˜îî­J»‰t‚p°ã ‚ êXÇÓ§ä$îT‹==§Oc›s´é0­Z¦Zñ¢Âp$ŒH.‹Y ¨`1C½€ULõ”Ä;ØNäØ~ûè„’}37¶l\ö.´!ͯf§÷©'ŠR³°’£rÑ3ÔUÛ"®®®?Ó…ÿØŠ½åµ®ÆSu¬Pæ¥5N›qM„ÐGjIgõ©ØÉ“<ïºÍjÉáï{ô#$¸&÷:ئ»Ú õ´Y¹àìÌM",§Wúäû$C`Ë«¥û(«Ûå/èÕ6-I©Æ0,@Ð!P]·þìYa+ ZŽDÇîçy9gqª!¬DÔÚx¿pœÊ‚²çŽõÖ;RB )LVªàþ ¿œ[Áf`@ DDÐÞ<·mððÿ6v‹F²ÜÝîÔ„JÈBØÆ¡­¨É;¶LCÁmókVçß¾%¯ù“zÿ©;½ìsÅï4ßë™ÿwz*îçH ©TU+khV6Åb…dRÕ…0’ªISÄJCík/ÙG¶[MPº{úY~ßwÁá¾ÅcöÙô8C”ࣕ*©B¢Ð’AÉ fÒˆ:çO«ÇÍâ›÷CæªQàÑD$[Ê–lU³»;sµa4›hrmf¿vÊCÊë×eÍñy @(M …ñZ,˜Â"EÝšÎÏ|H3xoŒ8Œë +VÿîÏHm² <‡qÙ¼Sý9è×ã‰Û±l´@i•é§edn¬øB!£l‹{âáŸ0jIî}tH(1 b0EV1+F+$c b"¬"‚Š‚ÅdQ‹X°@$„%éÏót¸BÍuÛÁzJ9ò‚'ØFlobl·f9œÉ®*}Ã4ª@(•eJ¶ÁîæÌñ3}j>8ºNN>…×t,"SN}MLè!$Y]‰Õû ĦFxž C2Ujà¿Ïbf9ò a™›‡ÊýþùõäÏw{fJÅ ì_·öçÀÓtÒ¹|yò‚«U0"¯Uû€'Ôð/¹ŒóÈ]áëúºèÍÿbîá||b3¥r‹ÈPò¬Ë}<Ý6h¾#c/SC—^ÈìäXÿ»ÕÓ.¯'Ï.+õòãç脼ïËÇÑÑéßà+Í»¯Uü™/øýùòO«ýÅÒžþÝúý±8ôtç,£ëã»VŒGñÙãqâˆéòx_¼Ž/Â'øù';õ]ÓáØ)!ø›>ƒâö¾/é篧¦åu7ù˜GiïõúZ±“swxyö€;Ê&ÿ‘}Qü¿í KYOàO“ùQ¶üØ|¿/’4UåùfDÜu‘N·Ó0øá!ÏfÜÕ°v"¼$8‚*Òˆ¼¡ Uy°Ç©¹Ò:eD¨ „CO_cKLR!²ÔF<œ%dZCÅ$˜À­A;Üm³bÌqE_¯Çn{I ô;Dýu@?E]3˜f¨ûÑð¹~0ý}Gz*ó¯ÐèDi‰ÀÏ5 Z¹l[±°f¸Ï |ü.2j[K]uÔUˆ«Ö °¢¯>†mÖ»º*â@T2jŽ#KÐi”zÐí#¥Â†!ÊtÞI@:_§‰÷`‰ÿ[c³‹o¸Õàp=dUä0¢*ä0ÎÄëÑWàTS¿“”ß¶Â}¬QAûSô^sá• ‹@,ÏÑ6“¹@â×2ä™xoÄi˜Ö¹a×àÚ;îMr›}÷vžÞFg^ÛêφøÏì ä³Q»‰¬{ŽÁn1@–÷šc݆“¸×^q:'‚ie] äTwf3qwº¸˜DÞƒD·¤«Ý·‡ là´l¯Ã fã ÇþUî÷Oýqàœ‚"uMS-}{´v0ásL%¬;>6{B÷;'7#9~4ˆbLH„^3ÄÄ&å3Óײú¾Nñð‹á”Ëû­î“ÊÔó Ê÷XVŸ!gއžû¬ÒuL°Ï×6,l¶6Rëœ)»Ù3³2™ÙDNÄØ¶N¼ÎÉ…¨xù±ù®]»RN0ú®•ý RÁ¬® ‹i’CÆΣ† i‘þR*óN÷X8x|~í¼¸Ý°ƒVmtÍ‘MAùÈTëžÕ@ˆ‰·¡,Ð2Í'¦l‰# ˆr¾¨4ŠðÔÆ@äžñ²sDƒÑщÏKf£ Ua«I(¶Í÷µe¾Ó†T•·‰‰å;„Ä@%êÛ³W¢)Q!²"7ˆƒÂÒï PÓyqìëŽxß&@0ž2¨Äˆ•*¶ògÎ>¦'páƒX,(-)—!’DIß•ÙøeÙº"CÊ2)¤|à}Wåûøü}š2Î{»üÉ‘lŸz0Qî*ùD¼"R ÛÆú³àB@„Ið¤6YPðÏÃßÅl#ÆPŸ]Û ,Rƒ•@9 9â“—ûPf<ø÷dЪï´4ø«bøõW–ŸZ ¿tUp N< &Ë>‹vüvÆÈ0߀ÞÛ<°(¦ö‘{ÐÅ)^-@,²6ie—ŽÈ[ö"6ò‰†üÒ߯>qç!È$’{¾3]|¾âî|¾Ã2f¨î¾‰M•¶úˆˆÂÏ<‘äˆìÞè '† *ã‚2ŒF–X1ù$UÿΞ¤æ=ÞÐÂt*€¨o•Q¢W<ÐÉ §2nøûêÂt\ä2mĘ6K­‡Óe¦£JôÂÖ³Â9ÇÅL;Òœî>ˆÆ*ç\F\?eäóönœƒŠÐ@ã·•«mj "iMž®Ï…½)Íq€3¦Ï7Úþd6ÁÍœwtíµb ªÈÔY3U¶ Š«;•e„á2înX¨¸|óܽò.;÷ùÎÌ{ÇhÄðì•w -RLL ¦$¨R¶Þë[¯^ãaà?Ê5|¦æÛGT²býœEÅQã⦬³eØì•FP¡ Æ’|ém–v[ëÈ]ÇMTÊ ÌCh¡Dƒ LFèà?¨1ÉnAæn‚7ªTÀ‰Šv¾¯¢±SºÞþaSçÂ``à´š’ y“šÆŠá7 QÆïi>µ±s};bìúî)*¦­ãµ]™8%DwAQ;îçGÑÆ¦xæmv{¶2˜;3kZnžÝ%0ÃÒ ˜*¤ q:‚mSØ×aWðÁ®5Ž÷aá2PòÂâ,iàãÄFD$ç&ñ€¾Û$0Co >”RcG )(yDLƒ|¯ÃDU‡“ŸumÛ:|ðãÚ¼7FÁ>¥bü¢“KÏm“°Ÿ,Z=½hv…xjZ"W]ï__)c$iš˜«bUéø!¶{V £©2¼8°Wñƒ°F]M!Ci‡‚²?ÝÈUÅÅ}þŸ±§‡‡.etÀZBz)>Œ?(žØQñaE@·órÛ\S P†ð0` ÈȈO.¼WÔפuCž<r‡¸íÖ$#Êáâ›1P(.ˆ¢ ä-´xˆ ©tvÅ~¯‡-P+ ° –†ˆ´vß„ò²¿`„-Ü^q¶Š‚BU^šØzˆ6ÙµÄÁ¬ê ‚Àî ï¾»E' ÃmÎ|] º®˜ð¹1üZ ÊÇ|œ+mºí¡˜ÈóôYR„9àp´0«Þ¸èeŠB&¡àÃ^ø‹ÍÆËG6Ç¥-®ËÐO-¹oǧíŒìqÇ5ôÂuŽ‚bð£Qà:TjB…Œ†^p°Ê–pÌÀhE‘Ü Waã»Çp fD NÝ…Ù‘·23D^®9<üÃFºܳ׊Ï^{œ3ñÝ«Y@Ïd ,Ñf’"‹ÜuÈVx°`WhqR Zm}ú¸ö@4[v³¦¨fÄ¢›T ¯%ÂáV€NÒ(ðm|º†åWß…£X¼-ÖÁpMÑ:mÐc% ¶+hq@'í0®®ÆÙ°w×âæMC¨ë¡¿,*Tj9ŠA) !šEÜnUw±Ç“[/n‰Ð„,aî(‘ ?)ä‡, 0Σ; ´€ãt‚S>¨ÙY_A¦»«”êU†X^MA6éŠW§†úåðvíݯ 7'ž8©D@Ó>ô¶I@˜=Ž-¶tîºv§?Fýê«jï:wQ÷6­B‚k}6Ç£K#w ÆÛÄӇÞÛo¥Žù÷º` 4w™Qå’ ƒ«½“z](*-æÚôy"Fð¢…r^FS­Bä¿6çnË0ì:( Ür0èÏzÑ[8äÚ¦»9`†³Ôð†‡™íŠ,º…óxœŸkܾ'ÏŠ.hO‘†¦tÌ…3 ®è-ÅD8AUX*ŒÃB¡ÓÊd“­ŠY+óhšKƒ 0øU@ÊÁ {)ôâÃa‘  •ƒM3TåœØZ@‹oéÓX¼¬†c˜"ìbOlBy#%ååyÛÇÍmB\R[¹n¹´˜AˆáHv ÉyÄokØœ* i¦¸#Ðlz©w)Î'#O+ý-½:<]~[nÝX‘s\°‘dºK90 Õ(ï•…‚ *µaežœþÜ„Ò85Âè5çÕšoz‹Æí´¾¹‘‚¿ÃÛŽôÓúâ)h–éq€€‚¡ Ô²¾%/½v {Wl°2Þògð£ ÁjD;òá)}kÆÙåÆäi¸nÂÆfPG7Wåþ¥ÚJ ïÚà@Ðn@öÈ ±gᥓӖÛý”Ó«e±Yæyúsk}þÿCïÛ†Þ{£Üùè×êÙFÈTÇ?³5ã·ÜOÓõßÁvÂ1ycž>nK»*5ð²¤=¬Ànƒ8€óù‡)@¤z½µOQ*žµç«Ü¨ïúÞ©çÃÜ Ê½¸ý+mŒ§×:/©[wÀ: à ¯á‚à–ŠñÚÃî]b„±G?K&ÁDƒ ýŒt†¶ÉˆäÊØ• ×¢¬†´Éf!òQ†ë¯îK@öDCH¢h[ºˆ ÅRW½,9‘c›E@óíÍ“^!Rn'»Ã®Ïj€2 b'5w¨‘m±¶ 'À™*À®H¶Œ›Àƒé\ŒpL,wSL- ua(ÂznÛHÅb¯¦ÈÓˆå{î“¡ J_ K=xª…TàY•kÏísŸ\õÇ‘Äû j$…<¹ ùKÒ'Ê6†å¨ôµïg©ÅF—ÐQª<˜h, ä"ý1ÿS–îu]/ ðŒàD®`F»Ç¶SM…8uf*5Å"&ÀÞŠfñ ßˆsVÙ²kpóÝÂvyÈ%<@¦ÛƳ—‚˜í‘^`à)¶ ¢z÷EÞ<*Î|{«…r•ùŠ·†Ä¤Ö´sM‘Ò›~Ñãñgp­Øö¶¶÷®¸B¢³œ™©Ë.ê Ž¢mƒc@p›ˆdkå*^1ËÅêw\Š3ÀnÕéèéfÐ.©®³pb±œj2بح„º9°ù@p1™‰õô òCÜ!ПAMa•R#ňëŽî‚(i¬Æ€¹%ß³0úÐPA¦áÓ|؉©Ívs<91{•sËIeÚ»ÑeT/$Õ#°€,»Ÿw}ǯ_¿„6ðÚ:bk‰Û¯›UÐÀA‡_FÔ°$œCX€˜ÇHòÉ  €6 ('+ù¸¨c¸ìž¸TkDÚA,A[™ìÃ,‰¼L=ƒÁŽóz‘–çÁ "4Ã`μ²žU탢ÆñžqÄ%bݱӨ ïXã/è8†v€eàƒÚ«¨u…åc¶¼¡A( &²†Õµa®sò࣠J σh&°a]œ©ŠÆ¸º`R ‹Þˆ6î¸x'¶C±¤E¹ßnÍþòº‚ìZñ4ë×mÒãB)bâ ÄÓÃÛXsÂŽR=•‘JÌ¡ qj—¥üežvèÒH„ˆ‘vTR]¶Š"ºEdjº÷b_½ñËšÐa!(3Bl±¦"ȳ+pƉ›™×!“(ê;ùDL»$¸¯·uâ»Çtÿ\'¦ÁîÙþò§ºÌŒ§ëËD¾E¢öᾂ–¥'Åuê½æKþ%ù«íÇòþÞ9’³ÆëVC¢Ÿ#Š¥&v‚\ñ•OVïøµå³b”†n®>[Äý¯Ž«hž ƵÁ¾ úCé‚4ú\“®ª1&ñ“)`ù/»{É¥8»Š½Q^øÙIÿQl?ÔGÅFÞO²—Ö†Ù3ÆgÊL~cVW I2¹hRÄŒDø8*\AÔóbDöÂ.AO„±lY­ù,¬L9•H9<úÏ¡ÖÜB¨÷½ëgŸ;I§ ,Ô©ñ¯V¾ts^†¥œÅ)»6•Õ rté!{¬ä>CrØë&U"ÕEV T4E‚ß±{ûSAe‰FfbC¶Ì»ÙP€ÖÝ&6÷ùE–ÛÔ/òÀ -ø1˜cñ·^|Úúǹ³.ôZ+Óùs´¡‚žØêkVAò\Ð9‚à|âÔî:çt”íW„2x?WdFp†¢¦E¼vs6Ù¨sl¨Q  DLýS¬ÆÝƒ6Ì——”3ðïùtäˆØwÊv*¸áe2P_÷ÛHèÖŒÍûÍzíÈ—gºÑŽ£Xe¢N ëe“|H³3i— k_tX[N Ð!"UÒÅ,ÇL’Û2r©ò"öÚy¥LW( O$\á£a1œÅ”²¾="óÍÍÏstÔˆé$9ˆ×‚ïz“àºú u³]Z¯r!ŒÑܬZˆ(0«®D—á†pq*ÎÃtV5[½kªÙ5/¶q¡Š)ÑÕsh‡6³4UÍnƒ_÷’“_í¼vT)Ší½ë»Û=ºªÏKÕ5÷9׿¼›É—é*ú=ö·ß‘ùIp•ʹõ‚QžqïÞ[–¢¬^ûæM¡é*ú2 ü½p´Þx“Ä, º7I .®Txà±ßÚ5øØêZ)¹H@ˆ‰rˆ—]‡cbÒœ¤1„Þüe<òªÛ+%àðS]Û²¥Š¹¿.°¥&QP« DD`ÂGŠ*³ž]í¸ˆÂl%™6Ù!÷ÞaH+QjÝí!ÄBln†ßǤ°N&vûr‡†d± Å³,Çjï §m–Úl þL!¨<-¹2D•µN vû\³„§Ïéa=‡„•Æ™‹!jtÔ{GHqÚ(CHQóôÀ†Ã§Ú½½ËhÕu°pŠ*À”o?L„ý<°Õ±Ež ÔU}lÞxÇɬLr‡A Q0!$4Lý{ƒÚ;ÊÜ¡UP¨PhæÑw1žß¼¥;< Pùõ‘qØÂ`Ç´Ì,׃'®bÊ(O„z•€ šêyʧ'?—^Ȳ§>jíföcà€a´BpÒþE\´¿èËŽ¾ëÞø&OÁß×ë *áÓ¿‘²)$W&Çt]OŽ•ßf ¼HjÈ¡QWy6£}x}^ÏI æÛk¶XyG®”‡CÚO€÷ÑÓ„»Åsb—¦û‚¶û¨†/ Ž+dˆ•Ä‹v…ˆNe–#æÓÑ ‡ƒgôôÐê;‡LNØâi)ä‚Z4t÷²úîài/EŽÞ=—ΊïƒÁÂõE¼¾"TŠ¡è€mŽ9¢Û®b.¹¶%½>6N¥ì5ªáãF)˜˜‡7Ä¡£ÛW¶s…Ô"6N7H""póG…[6õ^à¤{cì·€×=3ëއ)XzJs¹]ë{Í©È玔$ž(3ËiAâ}£:l?w¦îL]ì;V|¶Ñ+`Q–FL>þxlŸÀyº!ä÷cÉAàKÜ6Í)¨\ÄgØ=îŸ ÷.³ ì‡·Ç²‘â.Vï†cÛÏ–ßa7ûM>ãNsÚòëZ9f•l©U‰:†RJèQÕÖ9"ãîóå¦,£?‡˜14Ð…"¤ï ¡‹„0ˆ"®*ôÔöΧw·´ŒœP¬`K†éh“€Ã¥1ßëõªW«“—VØŽßì( ¥()†d„äAðI¤ØÔÎuu²¨D/Ë{r#ác›nd€?¡­¨8¥š]êæ›´ h1 ækçqøÄ·[µ¡Î ›ÔÆ]X1eè€ÿ¢Âc¨ÄÖ‰]¥+ò€ø'Ý4U¸ÆÅfÍp!"Ô¡à#¡F7MªB@Bœ-ûDRò¨:%'Rܳ;Èia[=‚¢ÅýÉÕWfNëÃþ\4>œ´§ù#²ò¾íÔ‹×ÅJh©Ó”†ÆŽ›~¢¯g¿xØyÇòxè«Àð®ê»_8 a~ *½Pײr%®#%×QK´( ]µ¬X ËÇ%°åÜ÷4ᯀ óöåÛXÖ›´wéOèãÛø×hAµÆ|”öw'µ¿¤á[5l,­»""A"'Gô-Çծ윿žÏýæSd«®¶µ-ªÓ¦áÔÛ­»/ÝÝ«(MúW«A´DÞ°´j®2ã5ŒØg[ßÇms°’M¹ô•—¶ðe@Ò³ÝB¤›]óZêžô}®–*N •›³Ž^(„ªê¬&ra¿¯qzÙ&Ç_ÈËeôyÑM–¶¨Â[§<·-ŒRVÙ'W%2¹ðÒ„³’C^n4VožŠ M(^ië:NÆJÚ©inµâ:ÎðfÈ …(!L°á¹Å1ÔÁ¶âËd™KȽ•IuêË­‘ˆ„™µ—°Y%qœWÚ­Š¶VÝè ÚuÛË.¾¾ºß¾ræêƒõéÓ¥6VZá«kRÚ­8Ü:·=×e×¾ü¡,ºWª/Æ& }£†»%”bÒ`µ\e¯á„šH; t‚'Æý %A ’ˆ?, q{þ® ùA@ÀŠ»r’I$’*ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª½!$–G¢*ÿaþÜÝëÞ}6‹¿Óö4p+®C]KgS žn&7ÜEüiÙ¹æ[em‘³YÊäæß5râ ¯™ÛÇm±Ó‡´¾j|<ØpƒÙ‡88zàôA^p+Àš€ è`<  °@Õp@@oô@¶B3 jÀ‚J´ €‹¢=à{ÐíÈû‡»ê”Uãp¼—1Êrj‰ìøšÆ$‚#½ïE–)ÜùMˆGÏ´ÇÄ¥@ºœRQ0GÑF£ê !LÝ*ìêvý¾,µ‚üWe;U¹giH€ú¨ýól;ªƒÜw\närÁ7Lu¹£^ÏMVv}¦ß_[®Óä‚Ü®UåQWµE^**ô(rètˆ‰Ð¥"'—:û›¸Vsî§–²ÈyËHy|ëò›ðÃæ¾Ë>~å–8ëû¨eL»‘3½T¾<»õÊŽu7µÅQ{ÅÈÎ=4A ¨ë—×z–LQ9o|ɼ€ˆÙËæffs—<æaŸŸ§ël³8§ª×s¬ª™˜æjæóœç9œãóœç&fg[DUj™ë¬]U%ea-'p+œÌ¼Û4wË9Eg)ÍDm[±Šñsj¹Î“3w<-’9Ë,³M8ffffZŒ—QÎUóœÎqùÎsœåóœŽsŽïÎqõDO ç9Âù¼\çßœç9U3<ç9:³}ÂçÁç®±âPç)Õ}»Þ;¼FÎnQËFi™,õÛÏZ«ªçË—»G{Ñvˆï\Zý)±Ü]O·v%ŠˆÇâÿSêéû*¤I(?«ÕüºbÚ0ªÿqoú ß[Uû?÷/Öt‚Ÿ¦`0¥Û˜a9H K~Pp¢$¦äÃ)e¯†/†÷¶Ù·÷^¬«¢%“«`*(ÊÐáØýÊI4$ï\~‰«ŒPà);658dS|Æáâ0ôÇ14j0 -‘ù}µm“Ò•ê²u²Í²m^ ‚v=¨º‰7+L3@ð×E×òY Êž¥  ÊØœÀÕ¥ÈeÊiÅi´BmÒlQ”Ü®ªäñAÒ„”ã[”§©š'»,wÀ2¹ÿ«£ŽËi|¦C‹¡kžwZuG}àkU£×¢¬DT(UsÅV úŸ³Óý×Ôáé1×Á.}'ÑØÉ<ñêuìCOw1åÙ_$3l2þVG ÞɳHñ,—÷Óü™ün!&÷'3Zp:šê`p{<|§Ð¾¨‘ÉUï§È‘<'$Ì%%ž„NÜò=h›«ÐC{í|9*"?²å"°ts²Ýsb @ƒª`BRcÊ@³ÒŽ… t°‰<_fžÿ~ó0ë7àüP@gyKL0P Þë¹—ç°®é:kMœìLcsÃ_n Ëê“Û´½//,òâÍoƒ »jFrõ‡¥»Œc¼.0IPÏó¿½ÇæåâÿÈûX«·o$6ë›bƸ'ݲŸkïÿÇÇÜÊcªpì¸f¤Ã€ÃRˆ¬æ™Îß!c$ÂBHG^ý(Nl/{Åë¦<êG“p Å ­À5¢áW)jª#bŠSk= u×E88£v¼NÄ8À‰©aDÒŠŽÃ@YË×Ó„ëÙaåó<±äs7U.#-q-ØÂŸëHPdUBE­XuÏ ]ÁM“ à &bD‰‡€9 ÌÂÀ›È˜NÕÓ\™èHRÔmx;ÌnØ»l¿ü.ñØwØ•{qåœd†(¡bró¹b`ÃGØäâÔA„Ù¾ÇX]ÙæÔ@*BZÁRÆ£.?´½ƒ<Ê*6ôu(-óíÎï.»¹UŽÑM@?Kü1ÇDäë ÌkÁì螘JVðˆý~Ïéêº2U<%gOη'øå6@j°ï^sÐ-âgýì°»åX!¿jÝpÝÒ2f@l ÿ–?nˆ€?ô•€ÃRÀ¹ ˆ* Oú:i¦©°`ʢȥÖ8tÖ¬©èhÎ"ú\i\$f£ G(—øRÔÑ¿Ð<¿]¤UÄaJö òB*Thg%S'ƒ~øÿíq1t_ïÆÁ¨—E4YÂŽ§v9í˜úŸ^G^¿x±x`úÃÎ'×&/x¼cù|ªpàÎÙ ç&'Cz‹ÈEÕgøTëŠ.¹¬¨ B§º¬ Pf#ËÐ4p#Zc6×Hè],Çbõµ +¤¹ ç1>a¿Ù  Š`%…Ì"7K çl2ý·#¯kØøS½D¬œÆ£ß˜A´ìj)Hü$£ªÖ=ûƒ4$¬ôîq{‘  ]ThÇ^ÍAÓbj“!`üêÞ±GohôtÊú‘@ °Î2Ws<Æc ÐúÊ΀®ÞgnSp[Õõr¾.®r€·ŸŸbVË(+óÕí{$¼¢„¤‚â ÿÔ=[P×OF oû‡ïq’½~ìtøÌ&“êï@ùd3èî€ÊÅ_oô¡"%°ö‚îá±sØ…Å wü ÈA í$à—†¹Ëiæ¥Ä’'²èÃå0¬‘ÇOƒ€éàá€?7xN"VøCsÀ'=ò·n¹SnôýÀPÚüù?ÝŽ®½ßw?3È÷¿_®µüËÃE^ËOûƒlaÁðî±!†w”|Ì>O©Î†¿”"#Ï/–;78ÔèlsHVVO$¹,@¿@,??@šDâ%ºS`Hú¡õDˆˆŠ$ú/ô¿Cï*щµ‹Â‡(»ý˜…¼oºòçÕŸÝuÆ×»ë8Á­…ß“³ÿÏ‹ñ¼`ê@ÒÞN.¥àïD°ÍV"“Õ¶©8?3ªÀ9ºÝ?e‰?ÂM^/ ¢ª{0Ë^OµãÂ^>_=PyÈçŸZíÏ~þ¼¯KeÆto×½Ç×ÃÂ;?"Pò¸ð|i|oóK¿ð»1§álóh‘ý“íâ_ÜìÍúêuPtü7~RétqÏÐÁBÀ‚{B±È” Jü€ 2È‚Ë|¸3£;}n#öóñŽÓòŒ9´÷‡«nâ:®ìõ3{•ñe%VÍâÅ«•‚y¿gÕ¿Ï+çYÊ=_Ëèû²åËyþ~ŠyŠD¢¥)iD±-XÖVVVdˆ‘_{Õ£ ºönƒ`Ö¾¶ÊMôoÓm¶ý ‚¬£måF–ÑôÓ/Ç…Í—[$•Ï"gÑMDXˆˆ¦"”­Œ(‚#ºB³·Ø×“»ÎqúƒÞi×ÞõÞâ;€È=–îjh¨©Å-ët¢W}û—µcp »¥ø…Zd”Nɧ`Í£Ñp¤§ÉˆPleÝÔÁ£ xt ªIÐIJ”mÞò?AHÍzr!IU{™ˆ³Iü?.Æq³«8Äö/n³ûüpù&•ªvF4¨1-ú½œàp^öHvû9\ D Ïu|rÓô{¬;°BDzú½ïóü³õP6툼‘îáâVºQÜIøúß=©ù>ý!B,Nvo–É)jÃVý^ÒìúŸ?·Ý¼éûüê?fžá×ôOÔÐt®¬}î|OA¯äñSä· _°ô51‚ü<>Íþ ¾~þ}ý]ž»2Õ«VK§ü_·–Ü>íáh†öôI)ÍíX ¼×’|×Âgá>©¾žˆóù禽^C†ÃwN«¹uË.Ìn»W›³“•ßËÍàêß{Éý¶îË!–vÓAâ>{¹lØ8{|½ÃÅÃtyak*… ¢÷«lƒÂRéÝEí„É%Á§už]ðÙ‚·XßBvaóo—Ó„y­³˜ZäÊw70qGPy—³Ú´m@rã×Ï·érˆx&xk§EšwϺg¯õŽþÐ@‹ààÊ!ËI{û<ÙtÕÖ>¨Cà€¨x¦ï6ßáà”¼_Poõðœk³´Ž ”}ŸÂÅÿæýå2blúì%Ô6ýOÇHu?Z*èŒO›… Œ7-D©DX±v»d+«T4òÍb2Ú O¯f15Æò{Ïñ?®ŒÜ!´+"R•,"á'zŸäsX7“Ã3Å®2ò}ú½ ú®Ia® p:áͶ¦®a|ª»À„ ›„¥78é2ÀÈ a…`ÀêL«-§‡—*‚ bU2Ázª(ç0oÁ¼Ùª˜øxî;ý/ T?ëfû„xöºJôf ŠEš"leˆ¬”‚ ˆ‘)aQ|ÓÂy¯ÜئãPTÕÖgá—dÛUp͵oOáëÓg˜ßšpfàþ_•®Åº«I:ÞÚ¼ö=lŽèã› „Ø¡4 #êÒ ¢†4S ]Ä”Qø»]¡óØ}‡êNhÛb–-–…«kºûÌúÞQˆ¨ù?ºbåàöæl¿ètNTMÉšxüÜ©É1_çŸØt*VäÃçP;µüûs€•ƒ€í÷98_(+jS/›öЉ5RªYîG=ø§HE¦?\É_ÇUp¬Ž)ðü¦vŒt‡u‘Ô¼A?/® Ý·nüÊNpxD/ý7UÕ8Á¾Åñc§:xp!!¦K!xzZl·)_+sõ¼iÒp—'ípú™nÔEócp±Âe†êök¹€…+9G‰N, :-K[;SiLâÿ\U‰jk‡ Áài)‚°¼[€«ÄÇ—Óó‡)wê.oI+ñG¦sB.\1¶ œ­_Áý|ît´(PP+´ÂüUÙ( ÝŒ×{%k“.©”ÊÉIT‚Ó›÷ëéUÆðx#åܱsÛ_]wQÞü¿HŽ¸Ý˜âðýíÇkls·ämcðelÅܤ҆/—ÐSQZ$rcögLj§’E ªª­zE@RÂJÜ5B|"\ƒ@ß ÁBÆ}Çbò G™ùŸ¢’d`²<Üð¼döjÉöòËÃp”EÅ»œ>ÿ$ÍçMÑyô^M¼‰‘ýjjÄ ¨b®¦P«².|‘pîJS§AÓAÃXD›ïF‡¿Õ¾8ݰ‚‚YÁNç_K[%—dqE¡gÛí=­9éö¹NDä'+h2$ƒ Urôïy§+úÚù¼ÌÃo¾ÁËg8þóà÷«ø—_ü±ãúžªe›v¿é‰Ž76Š Ü(Å£ §q‡²~èÁ5 7x6q¯Ôü²Uw-ß[?Ëù³ L¡`¿vå­þ#'é‘ÀÙ]ÓGªæqe۴;üï%ñ±héçÀ$Õ"(HIRнҺî[ð¹/nÉÐ ºÛ·ôuÜQ@·»qÙ -ÿÃåqA5]]µîèˆb «º¡{Ù”®‡»U«ù±1*Õ€üQo e¨cvÑN­ØDDHÃ<æ:ò"-Ø®›ê"%¸s·8 P2…½QX@ïÖ;¼y1¬@\:A 5ýç×þÿT0ëêLZºj['·hüñÞiÛ¯ ix¿§Âí†0ǪPë=Ø ¶¦ë ØE³žV ×®}@UEâ«ÕFôku“£ö&«c\ · í²r.Íâ@¨bqÓÛËJŒ÷ ðÃ’wº ûM‰Æí”ö×}3hpÙãmÑ»c2?«ÁXX›IeB“Ë>kBî‡W>lˆÄ]«Kò`Ã'Ãäœõ‚* ®¹%£È©xÛeÜïìjíæ’qNþ¦à7ã€6scþ@GDûLrÄøríº;ú–˜h{mjY[À{ƒ³“Ù<:÷Î_»lk†vwJÎ|­h–°­šöKà àÞ|8vo¯ë¼´ÓQ¿]²Æb3ÐuÒ?ô'ˆµsž7‹·,²²úÿÝñg­Ú•íVÛ9Û U˜¡Á‚“‡ Øò[7«‰qjÒûÆüÈô¼‹ÛÛŸ›€Õâ•ãÉ 7u6h—ox"ªkçßíµÑ›Ø‘/êø}ÌG”JDd„Ò¾Ó‡6pê¿g@›ÈÕÆ­ÊpÃ6Ę0 sÍ8.­dT÷kB°Æ²VVÚW®YPA‹)?Gèû;ž}èûŽTFDx·Øº­Hý~ÎÆ: MçÊ@f]^oÛaÏ$‰ÊÁ_¬ñËÁF0X£1 ¤8™L@Îw~+R ¨¯º%ß}òhV ¨"°:¥D)Ûˆ -ÔôQgÐØøYÁ-=Ûô+ºî1ëZÛgv`i-½Ý£ÇÇ>ànpxÔ¢ÚX©+Q+ÛÏAŠ%te)i–|z}MçW<9kˆ°d-’A×9È91f±œ‚A™WIºèî¿Îÿ—¯ùÞ8W. dÁdù(ûývßÃ}Í0”âp!=Éla$ß)¨®0²Š£o+~Ù;}¤Ö4òç‚Õ;½9P<ÔMR>ЍT&‡)ÞÕ¼ü~céÈøù<çyá§_z&ŸÏ=ýMiNë¹L¤ lÆ” ¬ Ë@,'Q ¦ÊâÔ±­*-ƒ$C`©a ZtIs­åU…ö5Uí»>€ô¤£ì(”€lF|9¶©pCáLÆ Ú¶šxøŽ€rðÐÛ„¡(†¿wö9ÜìÜ—5¯ŠjêqÜ×QTnyþ: ì(ŠRäù›S}-µ°'µ±0Ë×Ë2 `3ö8L‘@$oT•¿â_ë~O£Ûñ™>áÛ¸éômÞ|¡Ž~Ý›’ÿå7|ó‚§ ì xQxá¸cÞ¾éç±ø%ÊÎosù5ú¸HzÆþª—$ýï£ô>Ýa—àøCvücÑô~q§LÏÕçëÛ‡ë¼ù+ðÂøí·ô¬x] ÷íîñÄi¿ø_é{¾N2ø¬ïçñ¿º<‘#VÀI6òퟂé? ½»«¤;ýþ,(D¹MÃ`‘#ñêTIöÇÕ#cnf.(J…ŒÁ +µÃÜ&Ü-dëroÏÛ2á¸ç3îð8$Š»à FÏþp:þ|Æì.å 0.ä^Ó|Ó»Àéíµ¼Ùî5ú¤µ9»Ì{n:mmRy|ž TﻜÀ 7ÿ>ÝHüB} yqj© D9îyp_šGþÀöü5v9/pEŒ3…UvÝå,ãËå6ëŠôÖ´ñýš cx<ý¾¿Pýþ´÷¬ûl£ßï_‚IbÀUy¢¯K{zßàøW¿ÅˆMé”}³Ï†.øJðÕ'ötŠ{ ðòúm²1´4çðÁà£$J¤Í˜TU,ǘŠwMò¼b£¸N8>Zy"R-ø—PݽûÏj¢RN½EM¤Ñ ?‡³f D;ÂÒu€ñB[ Úfü—à}t¢zÇW÷;”EäMšäͨ{™cgènbþ‘H/·Œ LTúþEñûQºïŠŠù—¿Ò¾îE%ŠòX¢€Âѳf;õ(ñÊctÊÒ6¬±-iÎI ·+ @@ÔMŠÆÏmŠ7éeÃB׳ =Z;aîÖ”Ù~¯³ú|Äþ-MtlRbà ä﹓{"Öj鵟~{ev%"%Nì¦k7Ëä´à8’Vý7kÑ2|O±Ò,pÿõ|ƒ QÛÔ°¹{õÛqКî KvÝd ûÎ .Øêëäô9sÆ?ZÑÌÖÛµµ]¤Ìs÷ÁÇ_ߤ¯ùW÷VvÙ˜—ÞÙ?ù‡Lƨ(²2‡â¬e9þ…ç¾¾n|ƒ}‹™ÊNÇ^áÜ!@…‰Ë–!†âÒJÉ*Æžl2r§ï|\%úUª{¾øTï°º;EŸ9äL8óM`j7„ ÚÕ>’OÌ@EF."ÇÓLm[µ¹À¤¸|òT—qûÜ—¦@±V #kFY°<Ü—6x¤½¼·}ÙzvèïûJ0B/GrÃ37ézê'§ß´‚¥ÎPK§>ϲ^´x,ÏwmRù;×ñ‚"TLÊvd”uÃ5¶Æc*¤´hV m¹rÔhF×.^“ú¯š¯³u“£X(KšDTÖdÅ HŠN˜mw2˜¾ã…ï 3ŽÒØq˜hRú"mõ–QYh-Èu #Þ5áMRNe…*;äJ×ÒÂ5!hÄb °Y-¢‰¼ØwŒÞÕ[±on*íÛ(ª‘ÝÁ‘eÈB²,¢FýOÞéÝgoã²^¤÷]™ÝÉ‘|.–¼ð²N¿WÞo<¤Ì3ôìwž®-GÕ›cÂ鎸ÕY%”p0á§¶îîîï9ÌnpÐÓM4ÓM4Ʊù¦¶Ó9­„4N”5–Y#ae; "M8IFPQ¤ŽYÀ$±¨0Ðh4ÒBN,¶4Û[LáeC †pƒ ,³ 0à ²M-šØ³8sùeC!©™œj$’C $Â[I ƒNPÐipÑËÌh8YÃÂK °áDEÌ͇ ±¤Ó(jÞd7&«[#1°Æã‹.Ë-­¨ÖáÆçæí•Q˜ÒLg)±;cp²‹“M†0¶Ú‡$á<,Û Îƒ–p²Ç9D–p“œ8Y<ãpä,QÍÖ4j4ÂñŒnƒJ%ÁE˜SMSsyÃB‚³ s (f’I04 Œpjl$Â0ヒPÆ‹L9ÀÀá8ÖÀÐÓJ(ÓO# Ò~ $êrÝ7:ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ˜x4ágƒÁ§ƒNpÓ†ˆG „#†œ4á¢ÃD#†œ4ᢄpÑ$¬Ð‰±¡óÎÐïYù5ë'A¦½Ë!Õu‡ç²o½~PÜ â¢ÇA•ˆÒúåãV ÃîUè–-ñWllûÚÛZ š½yo…írZÔä«gÛyÒë–œm¾K¹ÛCzåý ¾çg¿=Òw†Yt€Ä$Å•Á2U+Œ°È‰ ¢3Ìcàúgì4ˆ¼ròróòóó»C¢+.–”ÔÊ@»¼¦Ô¤£)äm¼ËæÔp½Ù JöHriÑ¢#[‡åKZeN\›“Éâ+, V¨¥5¥ó3{uåí8§À}ô¤Uònw¾gtgôÐ×ò½dC¤!@!:9̈õ|³B^fþk“jª…Bó%Ñ=3ð?‘T3*D眅® è/]]ôO§Ü¢*ò÷Î^\¨yÿuy”mSFÿ4,BG«‚¥å!L‘ˆF(ˆ,óì+?’ÑgäžõÆ$y Goó°áý››¦ÌàŸµqÕ=8X¨?»¶"‘PbþmÃ’QÙ…DÚ–Öˆ=ûûXH»DU¿Ñ"­Î‚¹;ʜǬU_òó}§I·„’L¿¹è.„øQ0@ãËŽÎëðΧ§„?÷è<ÖÕ9ío»½îDAýÈŠ+¬Š»n>‘VÊŠ‡\«wßðŸW[‹ó¶‡Šd~ׯ AÐÛÒˆ¯án¨äUî@²Š¶€(Ï+Ên£J¦¹îï»—3nmØwGCvç¹òÚÀ?éi£ÉàÕ@O1Q-‹” U¦"0e¥U¯ûþ÷ü®ËSél¹>Òÿ+æãúÿ; ò~؇õ>÷£ëüÆ2ûY™™†ÚÀ6Öfßžå6—J€fêhüØ( ž¿íú¿/£Ð²Ik6ÓÁ񢐻 sÇZ]*ªX\6¿ ©XŸÕàÅt/Ç_;çèõSS€Ï›;-v˜´<µžª)£0m­×—Bd6å÷Ku¬üß~íæÇtÕ}ü1ý©Äèg6’Mçä^¢¯r¨ &h"®1áçÜŠ»¬2Ï?Œta¯x¹ëœKƒ’Qà (Ö£B 0,¢8IcQaÃ(§žcî`JÎU\ñ÷ É»©‰¸6ÕÛç(BÓ‘Š/_‰iy#¤ÌagEX5{ÿçh,ûÿÅìÿå.¿ìNn‡“pœó¯|¯ ¹m?¸£Xü›‡"T…R”©XA ª "€,: D?‚–#×…óhö¢p½× æöËÁ›¡ü“”ZQQbÁƒX‡US =˜W#€¤b1"/yw2ËK£†øm¾ôDRoªc`Õ7f88Ø,GqDeB¥E¢KáqòžÏnð›ìÛÈL´Zâ~t$“O$?RÃ,ëæöóÛ‰t‡_/D|Ò‚‡ Š hsh ni#œ++‹4²èãA l(C°Ôi,Öbf™ßpŒ-šÎ@.5/¡ BåVØÖùüÈ*}8 ÿ+õ¿…¸ã]p;<º…'˜ñÞ‰(‡ô~{f:Ðáïìÿ~È¢+XU`ŠÁXˆ±¨‹iXÁQbµ¢×çf ¡‰X€ «4¦(Äf¤' ^¯Rg| [æþ¦Çòâ1¢® ïçò‘µWÍSÔÓdŸ9ï0¾i ¨”|™„”B¯MÈ*²"¬„S[TÖÖºn֪饲K'•Cc#i’f%3L.¬M4Æ—g8 ²J“J ¨ 2µ™“óÜ£†Á´ÅxR «¤¢ þ-(¨º?Þô× ¸%­L"*c‘dÚLF˜„„„‡N2BI I22^ùÌ0j΢H‘Sd´ërpXXðQFA¡F „€BI“A0÷µEȈ$þ1ß%ÛtM‡¶¦“ 8 ôÐ@ɆÔé!’L&HL­Ça&ˆR²úær]Y‚ ¢ï‘ 9å’iE—T˳‡¦L‚ÄV–¬À2Ä2ò¦pØ™°`qrje#‰­Ç`¶v²Y ›$PHQ„‚ˆ;º¤¥QZذ„igPZ÷(ìBèÍyçJpß<‘Α) 拵DBË¢ l_™:ul€€*%ÐýsNZºÇ¸àH° ö'Äþ¿Í×ÕÿøÛ¿ùúóÂ,;G/ ïqÚ§1ˆ]H€{O3(ë£mª­Lutˆ_ŒYŒû7~8ËkÚÔ°õÝÀZ:’Æyq7þGÏý_ô??ýþýWf¿³»üß7‡,¨XÊG©Y `Ôtðb±°IÕ•}ßOü>™âtOuÑþ?YpXµÅÝvòó0uØ.8ý|x»%ˆ0nnMÐü¸ÒW¼Ò-Ý$͈t·û?Ðö?7™þ,¦q ‹X2‰¨…Ìýí:jÓ¾cŒúWçúwŸÉä ÃÖ“”¸ë¸&4UÖÒ“ª<º_‡—«M>_>üü9øísQèyŽpDY…ˆ“NƒNY%†’a Æ D9…± 49Vø«ˆ|QY‰†ÝsqÞ2ù‚Û…Î>q¶„`Q“¹kŒ‡¦áCMr¯‡Òoõ½{N}?îÚÀÆ#$ý/9›2Ýz¶Ñ4(,–¥‡³…‹!‘T¨à`TŽ`=¦œzû;;oÙ[Š~ZþîZ5ÀÈE¼2‚–Ô4\ÈÀ*‚¬‚òî„þÔþ0¨#î?ÆþÛbz÷:ñ9¥Pª¿Gð´Î¡¢þzb^êÀûCôççˆ`%d1†]΂÷ ^3*B:’—‘6 JæÓÃB9¢ájS©†l“[r ….çíŽìOÛDIú‹·ËD¹O±  …81f$A@p…‰R¦>)'WRÞà u |~‰z»×› Õ2´?«xV@ƒ\‚u`(OèõuI%d+R°b1"ÄUUA`ª*Š*¬$ˆsûxkTSr"¤„ ÛèÞ äSÏM!¨D@͇ŒzC ˆ Î7,ãŒá®;;AA:[m6VtIÆáa|4rá…„‡ (РE]œl89 a%"Û†´5†­±Û]JÀ g% 9Á€ s ȹP§ )IO`2ß©>¤Wú£¯@ëáD?ÅîÓŒínÜgwëhu3÷Í j@·žá;úBÊf{“³Û(öïÇNþÀyEñð–;¢ÈRëpÃh½EáG˜­üÅîXÔ:¤ÑyÒ“Êš7,F:¢J—œ»éà ‘a‘Åfm,âF¢S‚Æ"€ Éd‘aFf‡P(‘ÙÕLÈ ¨âˆbá‚ä DoœQ & A ×,Üχ^c¿p tµú€oS¦³!!` º1Ù]ZÆà0½ÈŒEãbb„·ààÒøÆÞPÍŠÅ|M.o0qÁ¦ ‘Ä%hpÈ\²ˆikPJ>8m6`ìPÛºm¡ÊSQ¥TMŸÀ@ÐmÈH³áÁ@.ÙÇH¢³3¦VZ¤ÚGÖàh&.üˆên{ô¾sËŽ_AŽ¿ÖY³òÈR&ÝÀV ̹4'«&Šœ m,bg¨àˆfi6†ÅѰ“!¸‡‰¶¸^–3‚;ÃFI¤7Ѷ(Á‚R©Ë·…%Õ;ù×.''¸`í67—9ÔÞÚ·ß «¿¿xšÇ#¸{¨:íÓCÝÂAX”ÂÈ`˜’Çfб !D˜‘g-÷7Ѷꡭ’c"6%Š(êª0.GÂ%˜Âaº¶´`'¯~§”éÐ4°" és>šß4LÐê€ÒqUÖâ°×;îàÞM¡¼ÒÝχ€2.ÕMÀ€’ãCœÌŒ²‘##AF"Š(¦­b" †= AX,$"h(M<|wxóæ§yØéÜpðîóL3”7—‰£·‘䈈£=QF W ‡0V1Bd A(¦˜JÈ’‚RбF+ PJŒ"i !{pæðÁƒ^6÷¶qËßÐ,,|7<¡&LÇ¡Æ0D †öÈ`“¢ŒAj†IÔÀ0™X‚Mk$˜@dº0¥ÍÑ=ðâÌö,±Á¯ì¿gÈW§Ç3K˜H˜B MX»%°p/Ãù§M y¸˜æy­÷¢È¾! *ºÀ«ý|¿g¿ââÓä8½/MvÜ6¯*ÊFÑ ÌCmKæ•Q‚Qè JˆÝ#®‚éEïø-ÕþnãÇñ´ús€]Š`!À”¤0U S(†€ƒH:²7-xwï+—¥ÝŒôº@ug¾ŸÑÊgr½Öôû_ÌþÞ«­…ün2n¢U÷–¾¹<ª`·U†aÁuÐñ‡Ï”Ó «gG¼íâ›$M(‚K+I‚èñà o8{ðm\Ø#áüÏó2ט¢ƒjlo}x8$WçTþf  ƒö l«{E«¬ßâ—Ëôþþ2ˆ?) Š_´¼1Gd^BpßxÁÄy%<ÿ"ÏÅõ ÚA?uøÕwç(Æw§¦" å÷ÙIeQbƒO™Ý_‹zm»]»éŽßú DŸO~Ý~õU’÷¦ë}cаg²shÉ`³“zÓJK!ÁFQÙ‚P‚G$ÃM ‘‘&˜8ádŠ&§.Q›Q˜ÙÉ™Q³Wzm¶l‘3„¦4uY´V1hÁãäñ×÷Ñ9ŠfQÞ±Î(ùîeõ\s¥bóH©¡gç‚%ôßBÖ¹éŠ âJ•NNžž}“¶dÍ™…åû}ÔÂðd?P›¬Ù‡‡öô“Ô‚Ðz=0—[ßZ†qœ¼s©¹¦)˜6<ìÜoQ¾ï,`1æÌ,E‰ü¼Tà¤òÿ&ŠdªL‚& N$¬æ”¬€È¸ÃN”à:SJ`¤‰z¦Pˆ’ÈÅã—ë~?”|^;¡V÷=^>y˜z„‚†Gø€0_LÆöå¸íÕ¶ÙdÝÿWæáÿºRÛ?Äí¾oHSιö?i=^£ÛÎäÓIÊ¢¹« °¨\GÓ»§,px§H#ïÊ%¢~v~¯L\ÄHWô¡òqèüÜD4²È$ÒfŽ@‚ $²C#áf„šQ"(0 €Âg%æ)e Žú×edÙ¹Xq‹ƒ)qÛ'›YsVžè¬5êL’aãëü0ÞÂcé·ÎØ#ù”!éBa°hîѨȺ<›f†eÌ™ MÈ Ì¼wZEo‡ÙáÒ÷~ÝÒ^Am*£\K‹Z tªNÄ^‚qoªP^„H› >RÓ0‡M f‹,/ù3h ¤7»˜ˆ˜ÃX¦Ñ}Ä/1Y G¼ E pÌ·^0©àB”^½bö»`Ê¥[±{y^¬JóB&ìÝs:žzÁÀàa x°§û:-‹,©%bB ˆTAЀª¡B*¢¯CÃ.®ºÃs:ö?e 0\D*Fo&ž0Ð’ãIp9\ãAS’rŠjÉ’‡5Ç4C"É4ÑK'›³‡ƒ±¸9†š Ôa$ó;kèLgÓ=—Ö?ׯgÝr^ LÓíÚƒ"åä³7À 1š ÑÇë­J²^µ –@íbŒ|ö̰N?£û^ižž€¦Ýˆ@ÝfmÚéQ³PšZ*ÒÎ3«0 `ˆ2pà‚R, Ô޶Û³ëÙš`b* —¨ˆˆ"ä²ÑG&d^$/`¶x­ÌÐBRT¦ÉcÓ•Ó™Õ;¹öÝè6¶¸r°½ÁÐ84qïSŸvSfkÎÍë­¸îßÂI!K€e]ryæ3EGµÕ I0x$­p¦ƒªw>~T;4QN\ Œ˜—Å”\XŒÒóœˆwÝXR÷Ó7a¦^ÝqÑg]CÃt9n YháB0‹z»·•ÓUöôÞîü”#ѧABh;L'‚ÒÄÇFíç·†ÀŒê 1 é(d3 Ì3ì‡^ôäÉuØ›‰ý·ÄÏr?ÈBOÒ¯¤c—¿‘[˜ ³M(€¢,pÂÌ 08H‰88æ8Öf!‡,‚F‘;G/ж¬æéSºó™ ÉülttúÄr. éc?'©GjN”¥"Ê1ïÀ#‘‰=›N|™Q¾"¤ý%I[Ô>±Ç9í1yʼn¸â¿ZaRxn,Ù —÷%ã%¦¤žs—£»Ù®™ˆ«êÛ§Ô®V¹”džxGò¡ea i0a‚dªä @/z‰"_×Ó±ë¯^&Þ­ 0–t´9èwŽÆ•Î5;[mŽÀål1£\¦¢­“`Ù\h*á Ö@aD”Ç,DQ#a¹m­R4Î^a,ßzt[ÙÇMÑ%2æ¾Äç/Ÿã|}q¼3 ý~S®Óz=ÄûCPt<ÔÅ®»–Êâ-Âaƒ @ÈXùäLH.eeÛ ƒ –=Ù›S0È9þuþWRk—\ÄæHä8Gº§ß¥wëN›H:ˆò8èw5Üo‰AI‰C‰äs[µ6‹(;xñdMÏ2q´’I à8JG†Ñ4•ñzåÓ c ²_®½œI}¤@z¨ŽU=ׯf’ÏaiÞPíÐ1ééëÍ•‘T즿EÂëç¹FPáèq‰8È¿>,¶)œyG$–sÐ;ùõÙÍ$<89-îx § Šg<»@(ÛüG𻟗¸ôÝ5íÏc„ÉÈóî‰ì.ð‡k8aa£y"ýv)& ƒ%ˆE&¡ ,˜¹öšˆDY ?Pç_ží»ïÙ¼óN‡GdŽ rwov+™ž3ôă߭g¡v0 6H$`q™·2QŽL9"` 0fP¶×{‰ÙV¼ÊëàõÌWF˜^>ÑÎM†Ç±"X ÆB…NT7¥b”ò4nô0™B‡k^þ‡Csc'9Ï8³¤Î”q,<ð»Ä,S $ãE4‡!¢&Pþþs¿ ÌÎ9æè©ó-$¨ófy9çiÀ㸤©EEÑUß·ØüÍÜf òdÖk¹ÙêÈu` ›¿³ºêœ,P‘ÑMåcÎ9=¹ý;ßuÍ÷öÇ‚°cJJXIW›ß°ä 1PÛ]ÎU04•¤©e4¬g F! ¥(ÑŒA,YY`®ê¼û žø>Ⱦì¥M"'µ#ëÞL7­¨vva­gd̈́Ĵ(ñh dz/Ã34nÛ}®Uýµ«o·zé䈈æÅ„pC–8ãa$’ÎAe„”i¥Ð å‚$ Cqr92ÚQ†cåò«/ÅÎL_4j~qª-•ÝËéÎs6j‹Q•8ƒ˜9Fý¿»Ì@²îŒÝˆY`KÄù¶3¶þ†ný¸FiŒ_,ÅçoðµÞkÏÇpI¨@ð¹"ÑÀLA¶’êÊš°Ë0Æ TEQV ŠÑ·•íóoÃæ—øDO˜Ym­š)Šcpú-C™Ã¢‡GÓ¶Q$ÍœhÆ‚‰ 1 ƒkÃ@á$ðsn±†”sFÓ`( q„ÆŽp 6â0éø_ ëãò9YÚö:ûa™›¹ï1Äv *«Í™™‹¸Fz´Q|3‚ûÇöÇd~9È rÆÕIGn@PTÌ"AÍï·îüû‡$±Ùª+Ì´Ï‚ä¶áaÂ2(ÃÂGq¹†#Äq^¤4B/Åx]øNþ¡zÏÙ¹Ÿ”…n”)ED%3°8fk7åD•†66m4yøØŒ¾G¯ ®ÅÐ\í©(q;êûIjý ’æëmfÞÏͽ×î~·è|>sÑþ—m“ƒÂêjiÜfò\çõ-«?ž l5IH«bûkÜ]í3,éDE8é1óñ|÷;~¶!ÞìÖîr;Ë@ã–88a 8i†ˆ @Š:,Áº ÂcÔÃÊ[6B/§Ì1æy¯<\š1pÞ*nËQ–Ðôi®¥£ÂTkᄹ§ ,áâ ÓH†5¬ÑÓfs`ˆ†Óƒš9cQL#…ÛHÅlcQ®Ùfa…¦$D¡`œ84fÅÒ›DÕµõ×QÓ¥ððmˆÇçSúL«`Yᡆã@Í‘üS…Ǫ¸·L"æÿtß¼öÂÙ=â-ªýTU{äx (Ò‚L<²Æv!¡¡¡Üg€Ý¡„< mN˜tvX(œîœÚ½ÉÙ†ÒÀ*èÑB&lçÙÿ¾Èƒr ±Œ&A”oØÏSàÓ>L´Í}/«9è²Ï (²ÎIî4`€í“ K×ëtÂ^„ÎK—t&ËßoßXMN˜8 ÷4©_7ŽnMÎ[Á¦Ç03Æ3…)Å e)­61KHm}t&ây¢®„E^ý ¯3´ü8v[iä“8f”äÁó 7ðz;í{öÛÆžÂÒ|‚9Rp 8îÌ™¿ÇØ|¦eÛÇ|òvPîº.®üûÕ§ŸCcYf tÀ” „"oª$§•Ñrܲ‰0å‡B+Y‘î@é„$™nþ¹ú¯ºy,õéú$í¼³rÏZd“†ŽÓ‰®çœáfeKeˆ±ë–Ûe±HB7—ÛeµÖ¨wš…®ä8š:Oôð¾×™÷ÿo’W4>n~ßq»ƒoŒÿ"   §Ã`5TöͰ­x#¸˜mê^Ä M§ 5ÁýLµ‡‡äyÏg§ö{ÆÓ‰\)D·­(”©Äû«¯¿1/ÿ·¶ñÿäóÜ_×ÿ3äûà’M“òýðÁð!ÇZÃ>Φ95á =©š•~ «È§øc‚¯Ž¹vî|\…phæ’pÒÎXÐhä‚8pÄIÅ”óp÷H‚ÑŽ¨ÚNôSäò6y%åÜÙ`ù®åfî]DÖ â5ï/’÷§-;Ðþ>Êx@‘$ûV(Qí\â¯íewÜž§5¡Z}R Ƶï5Ì$ ­“!’”e$ÁŠˆ2 PƒMC-g,›`súVÑœN‚q°E!$#vÐÝ3ãoPm𢭤áº`h晄˜pF¶·0›hG ‰,m,¸no9œC˜Χªß—£Ç‡çÀä S‰êdyØÆò›Çð2t@ºõ0ý‰¼ù¢|]Žj(Ä DJ(¶ýSý/Éüü^oáýPDèè6÷G óã½ù@Ÿeðr,]"h²ß/b‚iä˜Ík¡îVúÂϺ†“†óÀFY¨Gêþ'Îûˆ©öYô9àkUY`õöúûðÛÍö¿¸ûlÇʬ4²Í ’K’‡(C~8qË r áƒ@ÔQy”qÔÚjÞkΚ÷X¢âUÄ=ícméu<6faj¸‡­¾'Üý÷õÞ}×Í÷EþïwÊý!ϯ…»ëº·Û=÷ï ÑMô7(²Š(Ðå³þì8k;i£‰m.ùlA‰ i,j$ :[´æ·D8I£iaÁ°˜ ;ÈQB+œ—»mÌT\œÙ &©šÃò"`ˆ %¨–0I¾º~>ÝzœÎ)N”aØüñFh»ð3 BL“#ð—Å:+ôßyãÙAg]ǨÉôþÛbŸk(ÂäÝttÇ—Iœpq;/™Ý à/<ý6p’YtŸÄòŠ–ˆ#ׯ'i¹7:Ñb‚‚xR—©0Ì¥À«msºiÏÃTó’YáÙØ<7‹ l,ጸtJLvÔ9ª]@ žHÀ~¹ô ŸDÛ[‰è¡vh¯A°û ˜áêê%/>w²I;ëÍ“f^eúÓv ,b´ÏÎÁ_7mïë:è³ÄvxblHì@“22@Óïn¸ˆ}vÜ€èhv†fèLÏ\ñÔa&’_~ƒšMµÏžÃІÖ&ßgÞjAã§’N§0ÝKiX˜þ–R Rb ?9åqËÜÜÁ÷rt“mvì0ˆ =µVy7JN øH®Ì¢‘ñ.,vk÷i›F¶µæçFãZ 7uYˆ5¥´¨$·ÐX1CïÚx=¢d§Ûµd <¯áï¶kïþ<¸ÆÇœ•O»€ffrDagȲÄhç ((²ÒH4¢L8IaÃG"Ç2Ç}ä—¯Zƒ-’®k8Æj8b*à €¢š(¡„D„Ý"­ÅƒQ4`!U⠆ВOVÍÆy0)0s/PIjFM£’"Á˜5•‘…Z0ßÑÀX¸ÀBÄΞ/Aå¾V{„Å’FŠ,ÿõû]îæˆ›áNÔ¥Ma0à ˆa`&””³1ªLY’”Â!dW"R‘(a"xêQ‰¢ÊhLFªÚ[@Ꚙh0Â`„@¢DÁ2a,ìÃÒÛm©€Ê3ˆ3óiff 0˜ž¯ˆv8ìSiI¹ˆîš™VÍ Jcm©¤ÔÃJÂÄÂÄe (Ä¥% "a0¤CõÿêÓa6‰B…Jm+($L¤ÀÀ²”–a’±œSù€`ÄbhDÚt.X¸]õ`”Ü*0kw µ¡‚îÐÚUȘa“aMS&ˆ{34¸j{’`˜hL DÃÂQ˜$ʈÄfÔ,¦‰J†ŠJRÌ)eÅN8kK!„¡…¥EùSG^œOo”Üà'!³bÄ!$‰LúæÅ=ÈcÅÔd:=Ð@ äDDM Aÿ;Ñî}ŸÀûL£û·5¶³– ¥£E§!œnJ&ô\˜­3–÷ÆåD9Y·ÎNe½»ÍåïvÉ«¨{/6ǼÞ-…w+xÿb¿ý!€ô=~È„ù’&|¹ ËüìÃgâÕ©¦Hkd蛸% õ(¹wN96öïWaQaóHW¢"ÆF 6,(±HбYRˆT¡mT+(ªÄ#9[Œžû Ý…$#É¿d_ƒÉi«`O>˜Ë–uHt_ò¹€sÑ⃠|æ}4Z€‡OÏi +™VÂ댦H«Ýæ<ž¤$Wþx£caÖ¸ðÎÒëR#WH.†=‹Íi"ˆ¢Èhƒ1môä óAò‚ÀÁç2#Oá‡ÙJÀs.PLŒè"_•_Ê0òþ™¼IÊÝó·Y†Jº .þ¼¼,ûiÞ†š‡ÜßlöÌøÕÙV‡ziµÃ?&¶v\ èÀ ²ucKãU%@:¨õdMôRÜu¬ÔÝ‘ º³E~ŒýÃé•õ»ŠÚWmŽà;Â, Y†¬ÝWÿEŽ/#i%J'~œÌ=BÕàj€/_2¢óñê¼öܾ-¢|HM ÈOÞš6{Tdñ±í#³Ä°ð¸PGáÒµ´c_%+ðí›yíòRP,uÙ&jª#:Ž·ÃS·‘Uo—Î)d¿·»kabD‹¾¦^ܶkž%íY÷ 5H#=Öú)¹:$Nê‹'|0(ô¡†®‡ÊÍ$‘)aóhÂ<ÔkUHäf ˜bã(^ nsDn},|T9r®%GõY)ÒlHŸ•ìæ[¾Ô)¬U.ÚŠyCéiò|¼ý¹ãm¬}rNKÇë—ðþTÀ!®zx¹ü€.Ó>îD¼H*·gYõ0_i7A{–ÀoáÇñr›©m„,ÚVûn¯\²œ¦G°¸üO¿çÞBìe$û8ΚKr$”Â’ ¢˜®MÆ4ŸêÆ\—˜àÜËÀ2t³®Š?“RtmÔ}GìuËøÞÇÔóÞ« üÆðE^ídHϧÜâp‘Ezž"®×77ä­Ó½GMv »£¬L §)uBý]dê^}2zHýÔeuâëEÞö #ƒÔ~ä« ÃºTiÚJƒ}sYEÇmô1?¯úÒÊõ[?×¾š–ÁƒÏö쯬®ä"øž’‚€sSñÇ*‘ Æ„²Ì[3.—Œ žHE®ž¾\.Ä^Zõ™kÙTN!CÌèÂI½hE•YýËëfÎIðû±²ñlíû\¯÷åŤ,“Äæ¾3ÕößVÛe³av:à›%lxc_Å€Sy.8`·7D²7å«,y†WCeòß¶”:Ö)]M¹q„0ç͇ÛÑf«,'ÌÑ€‰'_ öRu— ™´"Ò‘,ˉÊ—E`Ió˜Y&%&p"[Z‘^eºJôZÓ«Œsã†Û·XEÂ'þvH('=Nþ“hÞMF¼{"-½FZ¢i·›{ IŽŒ‰±¨ÚïJåEŒvŽºˆ£1®ëêq„m·§Èõe§ y¶µÏr¯6+F]Ê5ºHY :ÚsÁoò-4<ýz5œyuc¯TgÌ=ö:HÄŽ¢±PX`‚kûæÅž@JBø%›G]”€‘ }å—0M’P%vÊ<Ü÷¼òI|»-]×fÍ Õ¶•ü>a¢šÕAo¿æ‹xþ%뎥n?Ñ{C `ë¶ n EË,îiç†ÃC G˃½I$à¼/¾1ÊŲ ,–´£ªù}Y–=Hnù°¦¶¶KðŠÀéúZ,j«?[ƺ쨜#NÞàNÁüA$ߨ¤šf0ªØœÑ?›hÌ4cá5w„@s×Þ|ƒý×G»„?蛹8t‡­g§}¶&osÿSëÙ.Câ?Ʀ5¬óW#'E}ò£˜Ìé†Al³vB'¾Ydû©šÇ—Ðöù—üKŤŽ}¾ {ýc]'ñúY®µw­´]¤õÚ¼¶í¿s¾¿i“thðùT96B ÏÕ(¤H‚¯,p&€°Š»‘WTUÒÆ‚UB5T °‡ñmŠ«PF"ˆ“çÀú(AEº*Ý`ˆb"B,E(ª,AQPU*‹QEŠ(«U*¬UPUQV,‹b¬Šªª±V*¨ ¬`¨ÈŠŠ°Xª±Ta$Š(‚Å"Å"ªÈ"¤QEYŠ  ,R((¢¬PXª,€0’DE(ª,AQPU*‹QEŠ(«U*¬UPUQV,‹b¬Šªª±V*ª‚±‚£"**ÁbªÅPU„’( " ‹PŠ«HŠ‘EdPR*‚€±H ¢Š±@% $8ž8çHeÒ;|ž’ðº©ZáA‚BÕåŠ;øþ¨&kÔåB¡°˜l"-xxð‚^ Õ̶øÍ^f¾Jع/ÎLj{‡ñ\ÙUBª"" C›šÑŽzÖ°N~{é\ZË!°´†»×öÆü0è¾Ë>ȲÇË ©—G7Wï ’ ða®ÇÀŠã®!¬ ‚Αѫ_’Í•¾ƒu¸jà ŽÕrÎZîÓö±²þÕ»%2">@ˆ‰¹" DQ‚«UéÈzCðÐ.‚0´ÃØ} Ø8†¡—87Á“!ìbD€¡(Ãpkƒ!Ãt‚T‡‰¡ìbD‚âz$U F„aF„aF„aF„aF„aF„aF„aF„aF„aF„aF„aF„aF„bÐ päj $““¥Qh"§"€^ˆ¯AøŸïz*ØE@$#Q‚FD ˆ ‚R",Xˆ’)Q@FP`( ¤P‚ŠH¡"ÉP"PIFH @DHH¤"ˆ€‰‰"D #D`°X²ˆI¤Q"@A@AHÀ " ˆ"H D ’QŒ`ƒ(  ªAˆ1dX H¡ $P€¤$P„ (E ¡I"@FH(  I)#Š! # (¢­*‰"$ "|©f!޹j¢·û?sxmÆÂŠŒI¥"#?c?¦)‚±! +#©%i¯×J‚â ˆˆÛX°¨ ‚€¤¬m""ÖÛUŠJÕD…µX°+ 2,De³ !ÑUS’ˆ«@«U,†Š¹ $²I&AŠ0bŠ ‚¬V1„ ¡ÔÁnEX€¨pá|YEŠ¢##)Š `1Š ±D`Æ,QQc,T@E‘T€A@’ #H‚°DQŠ ƒ( ±‘Al¹²©hIR"„+ìihHF,‘‚)H’*«"*ÁU€  E€¨tßñ›‘È¢®T{O1J*ÙQR ÕiVI  È«@æýŸ×õ?ûþÉð|n?òÿÑUGo"ÛNµÓmÂKiYÖã¼÷ 0t»ÞV(‘ŒDJ@R‚‚8rÉÒEªD˜E „ŠÒ›*¦$I0‹jó–.‡ w±ëà¸|(¿WŠJ¢t7w“*ñ€TÀQV *€Š¼ê¦$!"! D !# xj* œ¶ÊW_ÚŠÒŠ± hEXŸÑ슶U´QV!Uº еAD'hмµpŠ·(¢ R"¬‚*ÜSHr§j ”,бxÉ‘V>/lŠ´ªŠ´ B l ¬B”PMŠ0"«  H ¨T¨ 5j c"È#$#` EDD‚È"I"$€° ²1#a$`AB‚„U=жxDLH«Œwôa ëÞ‡Ñx»Réz{Í~{ÈßÛ²å¨Úž“jL%ÁÏÏA® ´(š=¥3ò}¢[ÔÏÐð1ݵd`=(><š–oc÷F—QVã`OCƒsêêáEY†prrº Ä5 ùyu½‚Û›¾FŸܰÞ‚ 7©À/îh  GlÞîr ‹¾å’3ów4ˆì¸F÷Èru U¢Á‚ åÛ¿ÛÂD’ÿŸ@üíûj(¾4˜b ùuè/”,lÚ¦BlÉ4²ÊåBûYÐKµ1ƒAÄ\|m´ÃËcù„rp//·Ìž/7æ,F“ù? ô{DÁ;:œp˜¡°f, †f“®¿cû0NAÇ•¼"åìîýã'%ÿöûÒžC‹cgWÔGø–CÜÏ®{Å‹ØÕ>ßÃgž>Ozßo†Ë»·¥•~+[¡þ X@DO:Å·Ûâ^" S/U¶Új‚ob8y*ј&â:Q$IøõP¶.²Ú0'Ý¢ÓÙøÿ³×©Ï%ˆ›Fѹ>ŒS倿&±êP@Ø(6(›2Ú5Ùçßb½Î/‡²XÑCb eçi !Eà#ÈB@V„S·EX#F$R¤ :È«=jdU D⢮U£ÍÎQæQÆŠ¸‘V ܧI ÄV,DD‘`° xþ%5‘´! Š·¡„<мú ¯ã¢¯DU‚«Õ. À4~ðÓÀÑ( £YŠFAI"¬E„DÀDƒD‹DE‚È,DdQbÆ(ˆÄH‘€ ")°D#ˆsG¼ŒR"®`Q$ ¹l*° då‚# „’epm‚¡H^n€!&¥èR aEZE]Àªä2 d$“RBH0’FUUUUUQUUXÅUUV1UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUŒcQUQUR$UUUUUUDUUDUUUEXÅUUUTEUU`ÁUUUUUXÅUDUUTEUV1UUP’D$‘UUXÅcUUUUUUŒUUUUUDUUUUUDUUTEQTXŒDUUUDUUUUUUUUUUUUUUUTEDDUTDEUUDUUUUUUUUUUUUUUTEUUUUUTEd’I$‘b*ÄUˆ«$DH€Žùr¢ ‘V­ ¬QP„5L´Fa% ¦AÍ—]rc%Jñd¾!pÒ÷Ÿ²ý÷ûþÏ"¨sŠÎ PDŒPdûP‰"Q QVÅK#F¼ pŠŠ·QK!p`ª§¢$ð¾§BÆP`’Ó=‰  7¡çÉÁ2pÉ%Ö,‹$((*ÜŒH$ª°€Ô¢’ ‚ã$ÀŠI))“‡FAÌÃ4XPQ\0¹ˆ]V[­k¦¼®²êaŒ\Á²›&¥¡Ž05-&.¡Ñ¤Mb\Ìu˜‰JSWC \ut©–mXX°Sx‰ì: ó¥@Þ@"Òªë Þrônœ4ë¤ðlÒD“`Ѷj†ÖP•‹aÀ¡iûðÈM! a QWP¼-*HH5M´l¢p¡°3<®9fÄ“öi ÀVª ‹£dD ‘V(ª-„õ›)é€H‚PnE]QWïI´`Œb bª"ÅDQV(ª±EQTQ*ÅRˆ‰""(Ä01EXF@„dUˆ‰Uˆ+ccQ*"бEUŠ(¢Š¢ˆ‘V*DDH‘bŒ ˆˆÆI$aT %ˆ€†X‚‚À0¥Š¨ÄUUˆª"**ª¢ˆª¨ÄDDDbªªªªˆ«Æ*¢*"ªª¢"+ŠªŠª¨ª¨Æ*ªªªªªª¨Šª¨Šªªªªªªªª¢*ª¨Šªªª"ª°`ªªªªªªªª¨ˆˆªªŠªªª"ªªªª"¨Šª"ªªªªªªª©UAUUUDUUUQ" `Šªˆˆˆªˆˆ«ªª"ªƒUUUVH*°P0DU ”UîCXp¢²QäýB„F@P`ˆ„ˆ$ˆˆ‰‚Hˆ€"Š ‰"""$dFAˆ‘ˆÈ"ˆ"$Hª*(¢Š*E!"$DŒŒD`#F ‘DD’ ˆ€‰@H‘"""$ˆ""ˆQ"2$‘D@ADDˆ‘$“ˆ(ÀQ„‚I* ˆŠ   "0‘V ‘‚$DDHˆ@Dˆˆ€‰ˆ"$‚0\Ž\@‘éaIV+m”º‚®AàY-Q„ !$V"£t7K4%°Š$‚)‰€‰È%…V¬ *‘ECR¢@QÄE^7`«Ì€T6áz‡ó)9„ Èâ<Á;LNåh†áüí²`]œM¢bå(C@šÄ–`hÖ¡!02eBÊ4=0oP”$É|ŒóÖ‡ÐLá@ÌÅòŽ€»£á>h%­ÊØaœoÑH]S  €s@e CAz £D¬ƒvt™Ì(«^h«|[@lm¨Qþ¶ƒ2CkµD­Öm ÈC!@‰ƒ\ ú4ÖŒ£áÀЂ„Km‰’6¬–‰á™‡ SAæIf0jÔ¥´)Èd0ÌÁÊ+3-H (3‘DBãr…µ*ÒˆÕV1ŸÄÍ8& •-»91ieµ)AV‰bi¢e)KŽ(ŸóiA5¶V`ÛiJRÛDe_æYLªmz³P´,tša˜%”³H]^Ƽ® Jˆƒ‚«áÿèàf¶–XY­ µ™,+Z”j-¬£Z"T«mŒ¢+-*TD•$€Ä•„RJã ÆE´`Y`æT¼º¤«¦Š[Vñ0±Q@¨%©iZŸÁ²ªƒ…©¶S.[#¶–feh"¸b£n©˜[r\‹ 4Õ¥J°¢"¿Rá& ‚0P* hI"LÛQÊ6‘!ĨBÆEÛ¾aeuef"‚…½àa@’›ŽRŸªû7A§ÞWãújmB¯öäÄ@0Ï»cÜÑuîë7ãÊvº¹J¶iÍ~S‚g½ÃÁÜÞêþ‹Òñ¸í¯º¥ª‚"3Gaõ‹©í{$gqý@êäôØ»¾õ1g6\Çôþ>\¿~<·/¤ðã3ä! *šhðÑWúwÿ>åö^'aY,bÔôv,ЏUôÇÌÉúÐÂÝáôb³“áoòó›øÊ}üT½0Úó‘ëÇ÷U}èheÕøJ½t½t=|ù§Ñg{Tñ٫ĦRR‚ô<ºCÒªËÍNëâìÊBQ xH«Tˆ«"*À"¬ˆ«. û$¢ªTO;?ª~¯õø¥Äýa‹#!ø<Ùcò®¡–°J5~ï×þƒ€Çö¨ÜÇ]AÑ"¨£ÿ8z_"í¢ îý;áù«܈«U=;ûXô6&;‚«ðUP€€EA€… 0B“Õ|ÊT¶ü µmµÑ‘ªŠ¾óoJšÈmq¸ò3U÷ &˜B¥»éOý("®üE]˜Š¹¬NéáA²hWó`´ØøcÝ®¥øš±àD&‘mÕš{˜S€BvÊÒšA±ñô?Ïá¾ér&—íÓçc.s¿Ãö;‹wÿ¤¼zŽ–“1s´Pý‰'g¸§þ)°?Ó€„ “ÖÆN8 v ^[Üû½ïªÀté×™©ÈUUŸ½u§ <ïó?Û{¡š³bʸ‚^ЏÖýßi¬îûô÷QW™ìÊC_å–c =q 3Ê'WW½5_‰q¢­ ˆ‰äÅbmpÐó1O¡¯ŒN4U/óÝÒ?gjùŸ«õþÚ€E\ˆ"h£ ÁDˆŒHˆ" DX±DˆˆB)!T„)AëI­om×Õß6!B'f×–ilzÎ)øFÅHm0Îl€˜@–£y¨ÄœbØØ¡mÕÝâÕ½t ð¯éš˜Ï_§|´=¤I¡ÒÖÈB 0( (à€Ï]ŠèÏCàá‘Tõð$(è cvVqШáµJ pJ“ÈE[»•D¾¢jV¢`¸æØbR …Ù¡¶ÊŠ'Äìΰ/U:;o•ëœ `Ú„E_† ˆM'Ñ”ñ4«„¡Ö)$`¤R$Pdƒ$@Y ’(¬ˆ4(*{/ðmÕæ@\È«Í_—Í $fçfh€:ðýÞ>>ÊeOI qvðœ¶ÛÚuEç¯É‰™¿û£Æ9glnºñ±‚ʪÄ-j#$ ªÄry¤û%’äUÔEXНE^"*гZwÕ6ýå"¯óøœOÚq2ßÓA'vº-2Î+ƒ†2¸÷ëLŸd6Ç]–Ëy Ï]QëÆ\,hÞB` {œv?:ñEC|.#ÑüšêäçáøµAl™fiI 1D"$PQ0`ȱ’"(‚°XÅ‚ d‹"ÁdEH°Y"(„PŒH Š#,‹Add|ÿ—øÿñ¸z7 Äh:dUÓ@"¯ R…V)« )Æ@n80óT€#ˆSˆ(†û©:ÑQ9A7¦`LHuhDù´ ¶QÎ3s«åИp¢®p9„UÑ rµRWº”É7m\ÁÔïd48§;$|\7³~QüÄ|œ„,c†ò`:t§Y¶êŽ—¥=@u'.òn¾Ï ’|b_¸Ï›ú?Úטü`ª«»Ì8b^D(Ö «PÈ¡E¥¬úüïÐøþ÷’ÜýËùŸù3H%¼¾£ ÛÛŠeÀœmkxÕ«>î±J:Ó¤UôÐØÕJv»o €Ì!ì‘V†•PÜœ ó%Y顺ë”A@ùÿŸÐt~Þ<Æc¢}7Ãü~7Õù¿;´Ò“ÑLÜm–µJ4Sæ"¯xÁ}®1ròˆ#J*À ! ¨…J¡b*ÅPÔEZC¤Ï@C·`Û ˆƒr Š·€pŠ©¹E^}{T*¡r ¢¢"LôC?§æ9 }Yyë'sîøãÒó\Xí²[|wŸ8îgYˆ¤ïŒuŒ·l"@HÒJ aC¨`sOˆö7fQ±kˆ"×caUå2 Ñ 4Ui¹½G£Í‰^|oë—¬xA‰,ðÛž/ÀrAìDA±ál½ábÞâ «ÅAWú¾ÎeA~pô ”3·VÚ™ãã<ŸŒz E_ÇÀ?ÒPóÚ\Ó*UU& ¤×d>àé²—B20!QE`ˆ€ˆˆ‚"@YT"" "DDF@D‚‘DH‰M`<&ÎÃÈPPïîvÒµ{ìþßzœãóµÕ¤(y¶˜Àl ޾¸ÕÌü  yêwÇ<•ÊfÍï>ûÏØ±ÈÕÁ%rzד• **g@QwÔòçlס¡g> ¨'–E\óÈÅ…áÌåOŸ^ó®øZû{Ôýסcß Èc÷ ¯…b¼ÈHBÐÈë@o‚•ò㉀»õ;Oeû\Îóàz¯ÿ|oçO±Ýó\ËylçL×0­Ÿ±ÄyTA«ÇÀB°)AÀÀ^û©œ¶ 1&¸ßØ@°($R)ÉtF^T5ô@Gãñˆ«‘n-!ÝÜ È" ú?04ЏQVäUýMŸâÞzïŸàXý N¢Ï{ÏiX/Üæü˜?{iðú4é'D]”cæÀ°R”‰mß,¼BhRÜñ’/Hå¼iU+Ý«êæ…ƒ2v—y¯‰énËßÓòÿ=Çóö°ý]Ëö_íñ¿o*ðzOweç!£C‰I¤Ž÷¿ëÃsÙÞb5ä•<Þuà™o0\/òñ?Îòøð¦ ±+¥ÓÔÕ¿Ÿ3м&‘DUã«ó¬=„B„:.þv’[8Hhiú¶ ½O7g?ݦÓ'á~¹¿„ÜQ(fÍÖ`zªY7nþ³ózï©ÿïOâ(‚ˆvÀÚ<)© ƒ,sˆ„{ðæPOÂ@}’ˆu<×äx|@Q7\Ê*áŠ*Þ<òâ÷ŒÛË¿Ûx"*ãÎȨ©ÒétžŽª‹G§ÁÙøËÀàSúßðSúóý}¾sÅ% ¶­ˆ£oé™uúüÌ7]Kl2Q!$œUQd|qÊ‹Ó)^?ãïeˆœ è#ÅA$ÃO­" G”^ 0©Æj§Ù ö›n6§ÚKŠH«M[Ó}(÷òñvú²Áô¿õ{ÑÑ>¯óìññãÈ?>6j¤6Ým¾•÷Â[ ‰.MÑhóÜÿž|šÍœ?ÌüÍ ò£ôùÎÞ€}¯ÉÉõ. ~SsßýéÞ;ó­³·¨×½CZÿƒ‹¥HzÏ÷StÿÔ+4Y[ß Ñ4G0 ÓÅÇ%»”sât|Ù½«Úÿ‡ æoïQWêÛº°'ÝÏTÒ!ÁE_RÃÑÍh}@™ÑÓ RÍm=÷³þÍ…Îüþüs?ß”U¯zo§?xï°‚‰œlÌ`QÒÕ¬’l !D–DâUBxÝ/=*ÁmS;„ pF’µ©£ßÑ?+«§@™}?šõ5Zy:d1™šB*á}ýÙD€ÕRøÙE\*iÿðï-„õ‚ì¢ !‰ÓE["z9Õ~ a1n@4•Z ­±"® ‚ª AO\"ªAÿ½ÀšÏ«5@U=† × TIËÛjÖsAŸAÿÕŠmz¢Å­_¯·>¹€ã+¹àyBWN™Þ¥¶1ásè‘uô Lìó} pãÌføifÈ«¸E[xåµ½!t„*qÒW% O»S)Ålܤ>§Ø³@6c‰¹@«ý©`½åÏX/¯|{ä3 å‹·›øóÀtTÉÓ}šºN|W§ þÒo9¸C`œ[P}úEšf /eÀþ•«‘‡ááIø/û›Ãè@^uP܈!ŒÙ(‚ˆ{ïí¼ï6оWül6è œñ¦·o°jÚmªˆ@„ ûË‹:gOÅ:’]:/Ä»àΟª­Ò*âÅì¨êÆyÂ\L+Ëõ e´93=Þàø¸:%×úo’@ß>o¿Ùí|¾ëþ9N»¤ ä7Šò*òGPж-né¡{üÞâÍPª“øù<•ÙòTUã¶ñD½\'ÿ!D@ÄrÞˆÇá"¯çë ?Ιq:&fyÔ¬QW"*ÀÉ(±SW{¢m \ñ×fþ­Í_&$«2 ºh „bô;cõ5q}â!:˜ÈG‚ây­"ÁX¯°}ÅÉŸóóñŸ´Ùõ Ò@B”¥)ŠéMŸ-“‘Ã̾j¥` ß“œQ@‘‚OâÓñ|È©A…wYiïþê*ÓuÕÙÿ_šÕÊþÿ§Ó¿ˆˆF¦Œ€óÞ£¨Ï~E_“§ßòîøý“ðÊl;íÃi—¨e¬™Oþ£îNCoi諲9!!!k'·{°(yPÆd—¤gex@/JKÈ¡¬à+÷ð$ZsÍ•ýuÍf¤ÂC@†º~Æ‹=Êõ¨¹[Çra¢4ºÈ¯ŽëÉ¡ü{á4‘V‡ÐL§%>ßföç4ZÈynpø2¾KLÿ{< à€¥3Ï¿•4?:˜€)4~ú=¨ O)‘•Ë$‡ò¾Ö4zÿ®Ø 6åF,ÊEŒþsq’äÑ«fÈ&%Uë¥ÕZÀkÉž>!É@ÕCª^ùU6— H'4‡ôó|ÙÍóXyC†Oæ<*/nƒ#ÈB8½Xu»Ë>4>–‘åýFÈ50Pk ˆ¡d –(«hxªy¤@ ±|„)U@€ÊSâxÀ¢eUˆ:&-.%Zj´Ïæt /ÊE_üëêb ŒØ>±ÉíLÁüä4m‹ƒ¿|ðÛgGÛ0a§æKŽ÷ÏqŒû÷fJ0¥H»ÝcwVdÎ1BÀâ¾'®™±Ž˜èyLþïúcù¿cü¼ÏÈóß?<Ÿ™ïyÕ¡PAëmÞX@*’d¶Sb-()À]  Ù—?‘œu5ãK÷¹Ó³á iF(¡Oê¾9ðñ?CûÓ õ~½Û!m!m i-¡*)Q`[d- ÛÚ¶…´–ØKi-¡m’Û!m’[@¶’[@–´ƒi-¥HV¶€ØÐR¡Y%dH²´’Ú´-²m„¶À¶„-²[B²°­IÛ%IRJ¨JÔ%jH[I- ´ m„–ب[`*ÒKh[`Kh[BÚBÚЩRЖЕÒ[E%JÂBÚ´*T!+X[@­@ –Ò¡m%´-²J•[BÚBÚJ•’[JƒhZP–ØBm’¥¶Vjm m$–ЖØÙ%B²@¶…¶¶À-¥dFªÙ-£hT¥° „ –Ò²j´+ Ò„–Ð…´Y*UP5RQU@€¿ÌŠ©Ìp„= ‡)PðQ3tØQp ¢úÿliìb:È÷ƒþ?z”6`Ê ‹"OÝÉ%‘Ví¯?m_Úš5´†Õ’@ Žh¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š4Y[ $Iý²Oèá>‘«½‡9:u±N^8Žh`¯fL?¿`ˆ\¥‡²ÁêùÉî=vë½÷ÿsà'½ÎößóÍwôþ_ ?#?÷gñ/Í샎AWðŒ<â*ÜAA¨ yžôæ¨ÁnúŽe㽞 ‹xÅvDq‰ö*‰°ÀQæ"¬U "¯z€¹å¯JªƒD<.ýPßúbàŠ®V"¨dQ"ªŒDPOMDUÿ*ž` „¢–"­"®¬E^³AQS1^qE{?qU2  ¬UP3õ  ‚‹ZZB³˜ÖE\=êᣦª„„„Š*ñkšNœd’BBBsuû…QÅ+ü~'æm9™?@ÿú±ç® h}Á˜1-Ô¨Ø[DVµ¶ÂÏVÿ¶Í1‚E«J%Z¢¿½ÿÍ>C¯IÖ¿Ç~=y`P"­­ðÔ&iß%éw)yÁ‡¢bAÙ|ÓûíÏ¥ð~W©Þmzû_Û…îüum ׄԥ§Î{'ÿ‡×ÝM•®ÿcÙké¢uO޾v’K:Ä<)§E!xGÉåÃÕ¢¯‡ÕõR§VŠ¿¦ Ëÿë³ëÿæ}ÿ#Õ†¡±äkÝþŽÓó»ØëÏÑE^µkj81š`0Õxü÷ïïlÈrr)Å(g|Ñ­R)ùÞ”G ƒm¥´±ö}¶—ɹïwXÃÿæ‚ ï¿Ã—þÿò Ì… Òˆ3'&AÄúµ³! ,ZaQmµµ5Ï“˜=‡ã°WsùÖ„Â)år>$¸ùv\ŠÉJë:dÎ’Ç„!q%p¢°¶hs@ºúyÖ7þ¬ó¹¸ŠrÃXvðãy¦´ÊC€¥¤”Ìs)ãëæ¥œ×Y!â„+÷wáN­Ùÿ6Œ˜.|ÛŽ7ɾ5õCt©aŠýGØÔÁÈwØW:ÏmiŸ@OÇGy:T‚DÃLê)éÑHGR€àÅqsø}[±è|ç±õ¼‡Sኹôœw@=!®CÒMó3  á À AA³¨}Ú\’‡7Ô§j>Ùl ¸Ÿ»ê,~S­¥Óu§ig:=Ãgmj …?#]²¿ŽúaQæ—úÊÜõ÷â„{pÎhón»'ÈB–Ü@B—Å R†oû–Û{èuï÷¡6*Íðís3nŒ~oO" ƒ3RX^Ó‹å<ŽÐwå϶ÙùËøþO´TTï¿‹_¿ÑéO«ê´ÌŠÀQ§"XÒæ9J‘‹[-.úS‡iÃÄzó°¾,¥å VÏih½M,ÁõùFð+ÛÙO ݇ÅÂQº–±¢Hmß!ò «R&¬ÒaD(¯ÔgUF8¾DÐ…ZŒaòaçoª©Ñešü~'9~2CŸŸ‚Ìùu´È+Ñzáö¸íÇf´ Ÿõk­ kæ+NxñùßG m7Å ‚o€z ^'ËÇ·q^'«Žó¶Ôîë6ªp˜ÓZyoŒèˆ^e`NÞH7,‚"r¢'(Y31Š Ô®$Zs)«ŠÄp TĹÚBq±Ýób'/5}:~A¨`ÁÿA†ìé´Î@Æd2Ç*b4+؇ø 5TtŽ¢:ŽHQ›ô©-,=eG0‡þϤéy7ýŸ›|ßø›‰ÿ#êÃ_lös òåøù¨ÿlkYvH†ç‰¸a(uu±ßQÒ"?3—Ãü®Hü}é[WTë>pI ‰ÚcÞÌí`Fè,(Üy««ºÙVð㤈NÜ—! ù$=–@hUEv”)Q¶ÔhR‰J¹‚±_ÝxÚìÖŒ‘0eCu1ºñøck’d±.¯Îü<–˜%Ê™ž¼|’²”°`.Ï Î|3¹²‘Р„)†)V Jë8Üà ÿ†Ñ‘N˜Äâ„îÌÕµÀý=J»õÏíp¼vÍ©•'ã$Ìß3m¶Ÿ’þT½è$1l—/hš>ÔðÅ*ÓíýüwÃç]êùý{¡ºÀÑýî]Jjw›Ú¢T»ÿrÖÇw’d±$¾ÔຉuåKWNŸ+Ïø^ëú}‡ÉóݳÌëmþ_c¡cööæÁtX –Š F@Æ,”à[ @ººæ“¡ ¥+D%Fs fmâ7 æ@x$`kzÌ›O/ûØá~sIïN2Œ APJ }VÂv¤Ó@oñ JÇ“éMJµªß¥Å˜¹böøÉ0UQYp˜°ä Æc>hX/3‰Ê Ÿv  α·¶HLÅSMµ­Ÿ­s?XüòéxBõEy--#½AÞÜ._dI™‹,µWŽbð,(ˆ¦‚µ„$8и.p¨5WÈÜŠ"iƒÔ‡õP>dEXZPŠ´Œ ü¨˜‡<|R‚ZÜ‘  –èY$$ŒEŸ­ m*Z1*ŸÏ.Q(b¢ ³0¸¦ s*‚˜ [DVàMruHc:f]¯º=êM¡›€ÓÐ@(vjºÞo¯»[i\lK^®a]çï2ÙÊW±_/ËOËôK }”ÆóËBæn\Á ³ÌÏüÜ"rWSN¾aæÛ‡‡˜ÎC C}ä’/E_©»æzqßÇ3Zasgd- ˆƒ/½Ñ(`þË!VÆ·˜3) ,YBëòÕæë9žâž®¢8ñ£Éƒ‹¥u½,~®,#¥±£›àÖÖëëäbrøÝmlÕL¡ƒÚ¯”á+ÞP¶ú‡Æu«¸veŠ®̓[3Bs­ ˆ+.y´qãG“JëzY5?ɇ…SK3»#<ï»f:JXØ1–€ —ÚØŒðˆv€`¬ ¦4…†yFc`9Yd`lˆXYЬt•Ó[ªÍr¥‰ B‹†ø/ЖȾnŠà“å’•„¯„®îÅ1ܾÇus]³(¶ÚçkÛ§m»ð^í…{Ù«º$&OW—Òy׺@„;'‰ÏÍÙ…ÁºØ/ËPdttˆZ¿$ìƒà)CVsóó³ÈT›ø *åMKõ>¹óÀ„<“Ä;á_ç6ö|RZ×Ǩä&—øŽb*ô8l"­„Uî"„UÑÖHH2{§¨ItƒCýÁ:3Þµ+ü÷ç°fvssÊêògrv[nÏ·(îµaäøafËøtÕ&  mÅ0€2âÀ” ðOI'4ø5Æ„ q*j­û”yø#ñ eâÑÅ¥÷fÏg~è·¹¦ÄÈ$ℹ¥£±G|<”û¥+›RÌAŽKBL@ª×N« »l²¨Î@%w_Y9Ñn•Þ·n‘ëáswò Ä:ÝòJ‚–51C¡X<¡™zuU•r½þeð·HÚÓâö\—- ï™Ë‘Rªa£uí'_RáŠÊqŸse48n4ˈ]ðïúŸðîÿ[ªãŽÜz|ò sû:jÕ#õ¦k®²ù„ûßäÿs­3Åö’ƒ£9e&ã:0~©]0PâˆEZ­3Y´(À¼á£xêBò<ï¡ø¦ µ¡] ©ˆð80ß NƒF?²6EŸ*ÈûèúÇÅæRÊЬ~ŽŽ#L‘Γýƒdþ5ד~ÝÚ›øßq’\¤)EÏë¥Íü±¾bÂëT@ o˜~nv”»ú‹B˜Sv‰Y÷ùÌý’!´]Œ89~.—ÕQW o–Æ9÷ͳy—èo9Ü» @ý‚*ÀËè‰ePøý¸ðñOO\õß„’÷˜·ðÿ´|O¡þÈEXkdOf’J¤‹ä`LøýÊ5hM½+•–”@”xÂ*è™â'd;Y¢&$Œ¥›Ç/&†B•S0f ™‡ï¿: ÇåD­_.@ϲhˆ«æÄU¤ Û!¸"—DU– !ÿ,?á„ Ä49ížd‰xž‹<ú?¬b$ˆ* É Û·ÒžóyÝÀ½0d„‹Òƒ Ve*˜Æ‘ª’ m¢íïSŸeŽJ˶WbðÍå|+øò›bIŸ ÆÅÀ‰E…ºR0Kìχ¼ÊXù ^ÅZq> îæ¥ó®"S #M)h)ˆÚ%w ÍffUVÀŠš’guƒ…'…Ä‘¬=?Í­" ÂbµEXÐfôM2Q‰"J™ÅîBX#C xjœ¢0M%¯ wɛԛ U5Λ.˜…Bëe†r‘Úë KLèN’j†‡ ¦)ó²ÊL %˜wvH¡-°’EÔ$‘˜aj6¥z$(†aYB‡áÆÂC6`µ8$Ä‚š´Ýò›é1¼çºË“A®’N4 uTTÎÖuk{6¦K^°Âùˊ܇dÈ`Œ–Ö‘Á`ícÎ)r­Ž]7ZºPbÖCA„ã_±ÐSBoÎ"–O•ß‘ÒÒ‰! Dÿˆ§Ïf@<ð9$T+|W ðé(¡¸½1@4iz´|@Üfä¤aC±éï0`âMU,*µ óï«>Aι‘4®r÷8š Aç °A‚¬…j(¤ˆÁH¢ÅâÜh«ÌD`FAç,gáŠíí´Î$IÃ3TDŽâ4Å^è#L(´fJ Óv¯ñU¹w³Ö«Ì¨üþ‹+ç-NPpÆB<€Lå’,'&'¥ mªsa^Yx .cÀÜ—ü7ÔBI0Cˆ“ͩ枆™Ý9N,dXᄉ•‡ÊÂÐyÄ/´R ÈWìQV“¡3½b÷DBñØjdøû!íxˆqåy¯§/LИì€%ÒD"`}Ia±‚o€øüu­î‹¤^OMU„‡„ ˆ)ºŸ§Ð~1·p@Šª–Ñç =“›4âžÒB L}«ƺŸÍŽ|‡M »¢&@ÒE]T$DU‘QRpAV¶B«] ¢$!ÆH•ø)׈Ÿ èÛ•U“Æ$'²ûOxuSÐn:²ÔÂÊ,Œ<ù%1#ðÜ×òõ­^öÉ{Þô¸ÀX>ŒQVáb4йýêháG1Êm $¯ ĉ76,v@R(&@)q`Œð¡4FhöÍü…jØ(·Wt‚öƒ™fT Evƈãâú÷-ßâ‰ÈŠºU‚„E¢sУÛSr ¹< >ª*üÈ«·ÕèöüŸO®ç¶‹Q¶§ÌzL ó²ï¾Ì­rPØOy0‡—βTQ{­ˆNÑ@xØÌ÷ÃÒh—·˜ |§Åio—⹌-ˆß?*À2Hdd‰ "ªü}yî³õêNGÓ1R}=Ê.ž.!2tЙ>=B\Y"$H!¼ìCþ?²zÓ­+-”´,Dü j,ª*LNBaá¸L’bYg¤ùDìBPF2;žR¢ŠTÂ?ð­ºN&ao¨¨²lL&ÞÏìû9ŠQ]5-¼Ú¬XJЩ-,J"ˆÃ.LÖÐÝ{»-Ì£0jBãc'«õÒÅH¬‰}0=>w¸ëÜ74š$Ú¸yýÎA¡PæãFËeެ‰{Yøol H—a‹†fnA)ÔËÙ:UWœÍ²ÒÕxÇæ‘G˜°Š5ßh,ï“ô®°‹¢hˆ,±ÊTíä§E?%Ä­ 0þÆ6);LhèZj%!5¹%Ì2:w`Nõ-"LñÆ„ÈÔBs* §¶ˆ²Ú¸oªŽ¨ Z"3‰Ë»hC“20Ü8Ð1 Ú…L ²ü'ºz>n8ª¢¤Q8ˆ`‡XÈA¥áE¹ñ°×cÊ@õmO‡ö]Kî^P÷@öx§³¼«WóP w÷‡JŠx H®5¯aE S8‰*Ôʯ9@ C{LŸGÓþçµÏð}ÇÏõWÍ„O‘ª›Ä’šÃ»£À»Øx€bGÕ…çò¾qÕ´<¦ÇDÀqà "JjŸ=p¨ôP G¢Ž ‰oþóõ¾÷<×±ÆC¥˜òý§çzÍ@2κkbìÿ ñä-„5 88`b9ú£‰yI i8ù,§/’¼:;S‡ c€`$‚ €’¥'W±ÍÑ3„ì¼Ö§ß‚¾d@5‹˜gh&lÿM®ÇÑVµÅ¨ zàtš5ÓÇ—@)€DäÎ>ä5 Š½Ô¦,¶xà’ÚhQ'ÀÄOw)>”_ÐY Ù‡ç!ùÿQYÌÛJ W/&Wð´ÐÐåµ ÐM ‚’2I"ï$H†¨„mžˆ\ªÙE¬¡°Ë…ð5àô«´Ï Ç•ËÎqM31–ô³€5ÒÁƒ h8Å2‚ š/Åßá¹Ì’*v„X KD²Ä% "C#D,ÑgÑýªŒ2ž¸q’R@ô›W„e©Ê|‰ÛAÿa²( ŽÏ:ŸÅQVm•;rJ1਩²l.WLÒþîp4ÄM‚ C «Hú¦zõÉ7åŠ`"-#èTK)b,VÀQ ™E^`E ÖËÉX«èvÖACŽ‹| "!$„À×ÎñÓø¹ç¸26{[K¹ÿBZ-]´ßôǤÉvºP—M!!ðyÿìÙí=ÿ=´úß»_áã~nv‰ÝÏ%`M6Åb‰bB–Á0J2ˆ~Å,ŒQÓ#d¢Kýó~O›1ÙºÖc¥0üs\¿;õ²¤ý–Å?Óe h[am=ûID M0bÅØ­îGrÄѲMÄɨÐà8kE‰ ÇÉHó­g½Ù×ö˜?A»üô9øóI€t|V^9ûRÊSaV¡Žé|³*Ó šäÒ¿°Ë£‡ÍU·ËÒçcž÷GGBŠ$ª®—V¢¬>]ÃÓŒ†Sc«vêÏß/C€ƒŸ=óÂI ÙóŸ6‹ECI£ãý_ìHrð¨©a‘’!È ÜYåå‡ëG‘@d Å6ô×È‘AÕ›)¤Šë@±¡<¡Fä›îÕ7Ñq¯`^w"òŠ(¨KF¯&ŠÛ`8ÔÜÃ3$­- ‡¹bY¼/-KV$P@ï+ëé’œZ!Øš¦îÁF`~¢*ÝIžÃ%gØjÒŠsí;C´eˆo¹ÂŸÔQ¥f•­ ‹B3²ëû˜I'8wvý\…H¡ˆ—…/ãd4)¤+vOl «ÈzcQ ëÏ_=üÛÐà†³«@å7O—ÁãÝé"Zìð›­à‡õÍg%&ŽûÕ{;…ñ]ÒX10aÛlÆŒ€b%d¾‹Ð ÃYY€ZwÀÏ̇rpÿ$ ð@W`NP'‘6E “ÑÎÀÜE µX¯p&‚$öP|[ûDvJ*‚¼˜šªaDãD˜)3Ó“2+(³qÝdUnTqX˜àÌYˆP&™ý^ÆË“ *ÚQJŠ ed90&3  *+$ÞhÕ2¨©ßqòÔ(]‰ôÓ§K`‘Ôx†S„!Í(YMH8°aӍޡcù?æÞ~É[G)jÓ1=œx~}ûžWÀóÜîë8ú© ¼¤ä·vAÉù~h¶&’öóýo㦱ùŸ âif >C>ÈiWUÐtç5 ¸`H<-|°¶@I´r¥©&ÄÚÊ ±Db0s‹ÞèHMœ„.EX*Ð…I$ŒÚ”S” SIW,A'«ÃIf2$:7`¡°È#»[¼ÈMÅD•¨Œc½ Á"¼™¾]5‘$‘ØMÜ †¦Ò…³†ôÐìÒÕ„ëMNÆÇ„¸¢…©½…†£"’IˆÉ¦Ía€( "0šKGY1†D‹‰ô“sŽ‹´Ì.6ñêjjÒÛ]4ÿkôæûÒII Áˆ8[•Å&ÏcŸÓ,y>•¿7òÓ|­ 2”}´©ÚËÓ¯cÿ—N|!È3\´‘V´—É`¥È“†J0…_gûçø´r5W_Ѻa°ÂšVh†åîêCЂ%@PMâmýWå`õñÓ¶Ò½~©}Ëj·:¥À«­„( ”¿É)9ñ 2IG抵en¾Æ ýßø½Ï7øL¶4а0ǰºŒ%eÁE޽Øåçÿ|înècfS)•$ˆl›ÑünçèÏCÑèeÆŽeÎÍtDÙÀpLZ%vÄÚáA9Sˆ˜“(,βˆ}ä©U5$’#$$…ÖX•¨2‚ÂAU&í~e’7ÃÐåGó½=ªŽ`˜éI›ÕŠyÕeÔ ÏÉ"ÀQH(0úlwÞäDæÉ&˜c0*‘†Í`f¬œøêM“Ÿ¥4] TÉ$w‘˜Om8Ÿ1ÐÒ»ß&KÒ—»M‹,`ÌŠ6´¬EVX(B@FX„„œs½xÐX‹ÜÕ € 'ÀgÍÒ_©síÞþn’™§‰ÛŠÐ—ꃙþ¢¡Q'y¡lLUÿy@ÉÚ&„NÒ–g/]8SÀñ¸[¿VÛ(6P©tåêd:ü°³H?½i;¡$L¾ÔØa³U‡Ô8Ñ‘ ÌHg4Î)Ór…%Ç •( e9–4piˆep¢¬]xssÖ¡R e_`~‚/2+wÌ@OlD­V¯À a‘ˆ < Ù·ü?$½ôÝßá `O [LµÑVŠ«¼Poη¹¢[¿ÃñáòÓÀ9~uÑVã/ŠK’È«má`/d,0Œƒ¿³@ˆ0 ¾Äª?aÎZ/¨ÕÏð'à< ùkÎÍíA2™Juéäx éNÚÓ´9‰ä¦ñ x&7Fk]ƒÒ@›uõò–·•Àìqª,[m Ñ u.3 XL&³y…D ßá“7äÛI[þvѪµPÞ0 ‡#šîâ~Ã;aê¾ÁÙÝ—¾¦×Fg¹¬Q®ô€ÂI2¦aÙ¡t勪S‚g·tð€÷ḟT9n¼KE0’#M lìeÉìkt&jð?7és{·å§µ¾-v~<×ëÛ/¸|ÑV·ÍÕÎ}$#µ±H«ý…ý÷¤VQ AHA ‡Ú=Ïwf‹mJóð}‰Ð! ȱ’![õ|sPÇÒpdòךgVoéK ¢×óÜͶ)!Ò¸»T.ܪU_]©j©d©¡HQ…nâãS‘„K°¶ãú€$;yÛ¸ïÔ6–w¹²ûb>è'#i´¡:$©Dk*[Žv½!$”¶IphŠ´bò’Â*Ĺ“÷|¹˜’tVdOHy ¼O-û%$¢'zrJ;—Ó›!0ºË¿ÅÎKŒŽèÕñ‚Yq´œ 2öŒ˜zBH!½ñöÎý• ÇÅ%‘°™U0HÀ/•}rõÍÉsÈ5ýHϳÓ!¤ÖJ*«7ÕnâLß¡¦qa~xc¨-`xR}cÑÇ»n'úÁöu6 ;;'Gϲàêû^޻ə&{Ìý­ÍÒqÙÜ.u?%¥½è=ðçêÓŠ8-^MW±2H!ß51HªÞ²n²ÞPiRÄ9¹±ÃGNv‹Å"‰:qÈù=Ó @Ùó2z~B‡–ƒ¾H ’I$# ¤Ow‡ÀUDÂ|°ÇÆèÉé0Ä¢ P»éM϶;%•È>0/ ìòØÙ! …h8;vá1›[á;Ó í<+AB¢A œ…3Þ”¦Å¼ýä ðSS±„=Ô¡ä5òÜ´œ.hYžwûó-) “Ý2‚Ïû/WSU"ÑH«бh¤ˆ"¦c t±4¹Š¸bÛOÇЖ¸³0Uk&Et6Ha‰G4c¤¥_$$. ovËð•ŀƉ*@ÜRÙÌÍŠ='Œcé}}(q[¢¯ÿ¯ñ<«t€®,;xÂÄSì]>™øœÃsÉi É\Î=¤¾ ?.¤Ur1¡0†œBt”N¿õy~{òoÂá&ý·-u7Bƒ 2%Å4Dòb2Kd µg쪫C-¬˜“Š­c’ ìØV``c&1¢Qbâ€~Éõ5¬›1d¢Ca“‚îÈ,”b¨Æÿzà2èd£&2xãViŽŒ¼í4k}f“@0Àe£©–r2’i:µ¬MÒLC‘E"€¤*Æ‚ŠD´$ª’7eþ³©¥¨ªÀ –"~ûÇ»ø;¼9¶7mû|ç~%~µ]a ¨}~»‹ÎÕ† K´#Û“` °Ên‚’Lqx×´¹âb*ò¨oîÖ;€X¬'+¿‡5ù2U¢×  Ð¥¿^æØÔO'×<žïô¹Ÿ1{±Œ­Ô€çX¾Ë;–"paŸº,Áè” ‰Æ/$PAÉ‚|ñØÂ‚a¢fhK" |hO°~ËM|GÉ^¢m$à3õwÞãqëŠA*ô(bXH(vÀ‡ðÐÆª |NC/ˆâ¡ŠŠ1ÎÒPÃ%á,âŽ&´ž/´ôeŽ~]ä⊻m:ô¶€]^ã`N_lA‹†¤$æd UdEV *³y½BØ1›]ƒ’K9ÑÔ„#‹×߉dðbHú¶ãcˆPH éº¨Ÿí[èÐóõ÷™öü6¢ðB„( (RdþOȰt­‰ÑGyéÊÅxQ.ŠD8=0Bê¥A**=¤&ÈnÉP©8q³FVŽ2áJÁX ˆkõ­`ÒòUåí¤°I†^ ´SôÅŸX~XI"T^ˆ-bÒl?ð¹ŸW]ðíÿoÂCêj“€Ã¹„mö)˜Î­ú«]Àг„€áàV~S–,( ¦ iå,9Í4ÙA´¶-J£`”@Uw8úeŽŸÈÇF¹«’ÄøJ Äk5º;IuÇo‹\†½é­e´bÅD]4P¤1aÇfˆêExE¤ª‚ß ’Õm$&|N|ÆPB$µ;n±dU€W8Ò>¢p1Š$¸F¥+4TN sSÄûà ^Çzp'} ˜$Šð€æäŠK¢®œ'4î·ÅÕMF†ÌÓR™­4Ö¡¤¡R]ðS‘æ@ÆWï{źMž%‡„ TSùpýI¢¿h)=S¯TU£‚v§ÅÅ6!l^Äà*¨~4Ñ‹:„Cà?ÇãÖî“hI¸¢†(Š7;ÕÖ|]D¨ G@4µ‰/¢‡hèý0,œÑbÄŒH“-+(ÆI$Ä&Â*À\±üet-E@FBr«-™ –·ÌóŸ¡Ïó\_Ëé?kë|ÿ#ÿœo±ö[Ûÿ¯¶ÿo‘æø|=þÿmÇ^`†¤uæJDº‰2)ñ²‚ÄaXÄc)Œ‚1b¨ ²¶`,ÕºqEOÞm+÷ûïÛËíüÜ×7³°æSrœ~k&‹ÏV–Ÿ¨¶“UÎ1¢­‘æl½Š—&{úܪìÂPÚýV€)÷³eV ._chqÁ.5„ZC6=¡AaE„A²$"À€Æ °‚‘dXÅX ¤ ŠÀI²bÂAÀ‹$UTVHY X «$RD!»$Ÿ¥Â#4œÀ´"­•@oÃD€fx*Э`G‡kÓmجŒÝ@@e* –*ÛÒQ]„‚Z/P˜F㋦ÖÇ6¿+TÈ„"®S>jQvl) Qm– YIÔd’HÄTXˆ‘ ÔDýSK(dV’ºqÁ>åÈ9Vû¾é¾Éêå»mØ%4#d8‘8½*îŠäK ­œ&:åâÜ¥Ê*ɇ½ˆE€PE¤E[ÑW?än¾Ç¦ë~GmÃûßÁâu¤ùWöÔ×ýîµCÓoå§Og„¥$áôsÜhõÉy~gæƒxþßã¸×kbû‰>ˆR†÷sFùöëǬK˜×Œóð®|²O ›ýÇÆJúƒÏ¹<Ù±¸®•|}Æ£™ø¹°'§pá°êû–Ryj\vqõ¢Æ‡ŠÕa¼C$¦ý¯qÆçá}y¯•tòUý#Ï¡Q݆•>˜ÖÞüd¦Æ+ Ë ˆŠ×Wëmu¿÷®;UXB, °@B™ËìÉ+kÄá­€ø@Á 0ª˜€@-h÷š& ÎʓŌVÛéôòßÊö~Û4›ÄÒ|VÙ Þæ'¿7”dã¨Þ@´Ï=Õ{˜ïwÔÉz1Ø3GûºÜpÃÇ8¹xŸÑ¿Í2„G¿Š ù’¤· þïõ¿€k3ôM_y©‹ÐgÞ_<ÔÓ‡3Ëžª82 ªàvqíîŠâ´Ò™$%Å0Û–úŠ¿·²%î=jô:ÆËqpÔלC=!iŽlß­¨‡‰8¤0¸£ ÔxËÐàÌ\nI¶ÛÆè¶‹«³–Ýf¾mÉ¿æ.ú Þ `ìë£/ÐüòzÐS(ñÊ0*62Š‹U"à ª¢Û 0UD 󦀟õÐ" I¤Ú’ŠŠª¥‚ Cã1 °ŒQM3áp9H8WѰ1 ®]í×J³ Sä8¦á‰FC„ËöPK6Ѳ –ŸBf]×mPÔ7¿uíˆwä.Ƕò6Bh‰£—7¢$YÛ¹¥É€Ž^w †x¦é¡ þØ„¢­†Á÷þ4ÒâWÉíõa43ù³Ø qKîÀùù½žìœ_wŒ;:P¡Ø5EšhÁAD+(Ô*êæQ¢Ä~³ …ˆ©ð¦e,Oðnñ†¡ƒ ÐàÔ8Zw¸½5 <Š.ÄqœxÏ"Æ›Su9ä$õ(«o¯íÜz€ô ÷êãÑ”U¢U‚#=4…05±ù¾Ìàn3d/¿aD1”Zµˆ+QTE‚# ¤;ˆ ó>œZ¬U™hXZ-Ñ bZ p@A4L]¿°GnKP#(¡=¼w@Æ6h¯áô;¨ÓèR*±Š V qÞÄU Bf™q o s™Éü_çÂJ9Ø6|‘”‚fÓ{ º `KE/I¡ 0ðt)Á•ŸT5Œû}FǘSÌéÅɆ鿇a„ €#J––BÇê6 4dRÂÊÖ­K=pJ? 'Nóçõóö£³xˆIÀŽäN@«!ëQWˆâÁ€­ÛO1ùt „Z2ìò™?L€wCÕ Æäæ{¨}± Œ\BD ÀuŠTÞ€Ù€¡Y fY+ Y'§çz{ó3ŸŸ}í"øÛW¦à§ÑÐ x$ƒ\WÁZÚXÙÒ¶ˆgÖ×wæ33©§Àµ!¦èm”¸ÒŽcdÑ€÷GQr¨P+ÝM¨Ø–Ú6‰iÒA`Ê©è«9Á(€²n9O7±b|”1 |‰Ú{÷ÐÌå@Ù*{K¾ÛëÓhTÝÙÙýÐîšÃHX;›ö©¦ƒÌΛ‰¦ÖT°ÿ¿L¾ÍMR|+V¾ÊvPÒL9>^Aî¡›n ú©ÊjF°³Ì”©Òë -œ)CdYž“–Ü$lcÍ2 ‡¸Õ›ðÀÛzP¯+ÇM“@h–âÜN4ÍHìêAE¦ 8ºJ“q€k©mcSai=AŠ(ï‡/{nèlAÒé×Y-(5zDað™öwj¢¦iäfûŠ]lîê ŒÙ¥-î`D Ð9!Sw¢ÓÀ¢Œ²e”ÖÖåËZÒã–JoñZ¶ vÁh¢Š ] YF*Ú¥RÕ!$ˆXh”*Hp÷…L1` ¤EY$ ’Û+èô "$VI RÂŒ>“zŒ)=ïvhÝg ©!º•2…æàÂ0° ¬9ëà'´ºhQHèzé¨v‰í*bÒ«[31ÏÓ77†ŽPùùMöJ5'ß01 :Ë_›.¥–†ˆˆ˜=a$žjClÅY9<“gÙNŒ_3¸Ãq„íM¸‡@C³AËhU`–I»@ýòrÁ  8¬â*ˆã6C€¬ ™v³êªG²êðOP3ºIꨫh>ó‰rXhfaHäg˜ ,Db0D`ÀQG¼kAFA ¢+bPb¨Š,UV*¢+¢ ,F#`¢Š(¢ÈI""(bŒUR „ŠDdX,‹X E’(EY`„’0¢AAVXÅRBŠ)Yd‹T‘~–¡ï'Å!è~S%’"{‰’ß UZ=“Üz曟-¦t˜·ÀÓv!­5¤šìÞìÑä’+x’,вËJ‹XHr´‡$ Œ*†¢ÉPHI#R–c!EV$A j(¬’)` ‘Ã2 .RYD@P†˜IÉ‘Ã0Ÿ"Mj¿²‘ñ#8XuÔ§÷ôÓÊ7,”„ƒ‚:vòé2| b!4†9é݈¢-ý:,ÆFC°‰ñq=D.*põŒ} ½d6ˆ€yž–·*éÝjÌE\ܹ:رõÎ:õ¤îaQ=>u‹%RiÄ%ÞCi'qÌÐm–ÅS¥™† ‹|¸C bQôÃAÀIIH}tø’ÙR$ à= ²zXÜòYavìU²Ù°¢­­&w]#4n˜åÇã4”z!˜Úоð—K°–¬¥=Mš;%"{Äë!éxSomf—O#â§â˜r9^Ðï„ §X,~ÉB&NÕ‰#Ž%yP‡8H‘’_™ÒœÝ±&䀩"Œ û¦ÿ+·´“@ŒH /|m‰IF#DBB¤%F‘’ëÜbø½O'áý^c?¨ýoËö·ÿÙÐÙq~ó!¬ëhâJWÃ@! ùçSB€ÔÀ„€tŽ@9_P7½&¾®&eÆ1þ>GŽò×wpæã¦:ñ}vÌ»$ýôÑ€p@‚ìÇÚ±ÐÇNÐÖ ‡œfI?3µ/9ú_[Åþ_·£°ž”Íö÷ýÎ%K²¾$…ƒl\iß‘¸@€ 4Ò‡`ħ1‡ øm;0Î6‘™lS8˜bh–_vÃ}MÓþî÷bÚjÛcOºaphÔär¿8ýŸ Â<¾Só¿t€îDUâC«°lkÒ9½U­‚ÕyœþUÿ7ü¾g9s‚szÍg™ÆÏí¼â*ã9˜l¶¦ÌÂlãb°j–²ñ¨ m ‚ÉdðeE[ÔuÜKñJd’$s©Çàó‚qP8UW+¹C 6RsõHk€ôÐÎ?“¤É­¶²Τ)*2 SjiM®mb홇ü_±ñx^çDþãêÏyðì§Ö`”/#•Üòz\FpÊ@R.•̤!A@ÕÔgÿOÑà!! o—ꈫ- .â}U—XаlÁ>þaEXZ ¾Ãk2s+AXHˆ@,€È¥a¤ ’bC• «8²i¨E‰ ·…1’C6¡ ‰Rî,Õ¡ºHPIc ‰0¸–EVnÉDD'rCãwåd æX†ëHiM'4H|oì°Áz|Ád•JÀ#Ûhhe$üVŽˆ…øÚ b=Ìòòø„E^(ª¬¡„RyAUî"TMu$¶ŸÝÞÊ¢e€¬‚ƒ 2! ‡sg2UÓ^Á‘ÞŦôU¡é4.ˆJv jy¢­õE\!qq~$[ "å ÀÒðºè· »º槬õõ±±` ‚#R)R‹¤V¶áOr"­áF¤OÖ"Tõ¡œ‡¶åtZ€*³ÜްÉpB¨2œX’&IJÓñ|wšŒ@U’r.›˜uÛ#[@ø­ÞùÕMÇ«b ŒF'e4 `Rw€Ô 2yÚkñ¸Š­5†`™æ6Ö€E hS[mM@y4‘ذÃl¸(“5L4B¢*ËA•˜U†“3}o{™¡1’KX¹—^þff£¢‰¦©L¤ddeAÞ¢£JV „ŠÂô)A’<ý4u§‚øìXßÑ^èJ‰H£]á‡À_‘E^ÄWÇѪ¦Ã¸ é7ùo`VUÊCÂi þ'œW2¬T ÍN\¿È\ÔX±%þDRL"SúÔg¬×‚h.$ÌQ’/Ù B2F","""’( 1"’Š$xw/R°*«Rh1E „UQQQDUQ Èô(£·5Se¨6²wºh"¨VÿŽ£= Ôhà÷41Ÿ©¡EFþºWpp¤< š‘l p@õiÉ™!Úl’%ˆEî´r«JX¤.¨÷æ0gT©°ïùt»6m÷÷„g¯„ô;(ÀÒÞÀ‚&H¾¤¬€ì×)VF ˆÃ2”ž}+lÓ†ÄEm°#Ea{E 6F*\ƒÔ/Ù ÑÕ÷Uýýƒ—éj^ðB›!ÅîƒhÔ®€{„ˆzD:¨VëD(Ý¥`K@òZˆwbÄ=ûÕâ#i â¹Øu "˜Ô¨x;qß Œ›A“V›Úª¤Fñ¨A6 ¦"#½bê@nEWb Ì"Èõ’I“P÷ðìo¹äÂi,”èl6 ™×7ÞX+ btéØ\1Oê¥ö&†n÷TŒ„ƒ‰#tBAIRÀyÿö}ozãÌz~ü`H¾ãö óÉÞyï¾§X‰l€„!€„TøIA‘se\1Œ¥n9ýï’Ñú?ÑýŸ€ ˆðÆVÚÍä´…0öƒè °)…O9ð­N¼T‘"`f1“–‚M<¹P;Û½&!D@ÂŽCãø¯»|äþ&>ÍÞ,ÝU¶÷“˜û7y›½õ“ɉ™äñs—ŸI†Ø»éLÔL ?ÈTºY[9DAŒK@œ‹/uSET;½)ö›’œøþ.¦¼{]·ðΧn¨±V!ý ² r•ßM„!Êù~?(¹×ëÍWƒ˜ÐšRZvq@Niê ;3„$ †£-aQ¯r¦²$?“:ŸƒøXÜøF­ÌÔýÖñý>¡^³÷ÇSÆž{‘8¨©ˆé£«­WìÒOÀΙÓ̘Ôhͨîf8%Ù챎ÂÀ‹Š©µ¶Â*ô¹ía~Ž¢“ZÄ$¶ëXýÌpêùÉošŒµÌŽß”]»z@:ðNQt‹°ú SˆÌ¨ï;yÐòÛ¨nÙ¶©˜‘‘N**j‚Æb!&X€7ªNJ ,`¢1üÅ?³ÜyO¤;v¢ýä‡ó|f¥Ã—‘i³4ªÇaiš; ×Û¡Õ™·1—‰Ž!Çv;»k'È"¿`=&¤þ'Ñ=¹¼eTœS’^7ÞÉuX•ÚÖ±²“ I²jjB%‹N€ËÍÕ÷6?ó |½³ ‚æH’!$‹5myàS 1šä= 4›@ˆlÈQC`,R ‹ðNfñÀa©¶Š …ÈdÜ~ÂJŽÓÚjeHº˜.»ˆ²6!´¸á³¼«LdíS!‰}é¾ ,™ŒxZ-¦üŸ³Owv€ íÅÀ«±¦AÅTºÀÒ p:ºÒ9³=c ÜuM*nÁ¬’†œ¬½¿NR 8›Úbb"D"O£ÓW[Ä=ÔXm††â º)GŽÔº§Hm“‰7@6±G9|(ÚRBqð·†ãâ%“•¼…@dE62[:?Ýš|r«ÖäÊtò•%J¢FQ5âK#j‚ïØ­æ„ $V<ü¨àIŒ¡ðÒE9œá oØh@žØ¡Û#žÿ&iwÚP锘 b_£só¥‰ò4ñàrË]z Ó£·Ç›0Íaþ·DÔÔ 1›mï•+Üj‚’A!t D_aPG7z•f¨ÊÛ<#æu=ÂO“.ÈÐ,š`8PÍúŸ!67Î,hRÎè"!œ¸þûýw‰k9Ÿl]P:‡îóÛxš„ÜÓŽZßn¨i+(ÞÁ|"믚V³hâUXÕF)Å¢‘“é7BQîÊAÇCq§Wttk)º.ŒàÀ•˜VH˜‰ Í€™Šõu›ea¤®‡F0aDÆÉVkF,5tÐ& »aÃZz~Çh·•‘U(]»é4ŽêÖÕV³dî„’d¡$’¼g%ý«ÿ2ÕUÞTHªi-T½ÑD(Žé‘„'uY{뚃±Ï숪×"*ÿþÎnÖýíU¿íh^÷ ‹CŠ…?9»¦5¯vL°„j'° ¤¦†’D¸ÿ+pÚj ‰ƒ“ÊT5b*ÁU A@"±«†bf'ã|D£Õ  Ž¯ºnûÂ/zPÚ/¡ YÇôª€‰½¤“îÙ/á îž7^\Ï»ÐÌ%JYH¢f‰Q))‹ž¦ƒW¼ÖZä·ó°õ5\yM!¢ÕgM„„&Šè3r«‚î„&‡9²DMí@W$Sµ11 ö˜Í–ëP’D˜Â)Z‚T”Q˜Æ¤ùè Þ…°J‚«¶‹ZÁID&9mÂæd»è¬&3,´@JÙÛ¡U5s¡Â €…˜À‰b,V 0D¤Y 5I…XÄ}we.%¡E"­4„4±À¥`ƒõÈŠ2#ˆF@ahµÓ’÷—â`ÂV×|H²Ádʨè =ñb+ÂíÊ ±b*ØŠ8 btÚ(9!Ê"™SmÐuÖfí Àˆ¿¼žUR ª¨¿¥êû CÓÈ#@2‚ä‚© «" äj,‚ AED `$“ª‚-ÛXEK1„W©)P» ¦­€1yš €@'·òûh*«e”²¡¤@êACµ·XÁû9I „|ŠnKo›0¨Ï c“D¨FA$‘R9#›¨tã²xxUÚÅ .8áÇ! 9!ÄwìíVÊ_XÄAb€,Qƒ ȈòP±…’,X‘Š2*FÑ%F¾C`Ù‡© ½l–uþô uSgò'0nÞM©‡¼Ö¥UUQUGò~ó†.ÛSt©jêX¥D´P¤íAˆ É~@ÓôAŽ®*"¦ÆÒ'©H±×z³€×Ù»èBãˆuú–@_Hë$’qÅÂiò»åà WdD² Ò Oç4ˆ¥`-amd¬;mXU¦páSe(@I! ¤U¥H¢­¢Äl09l «ldH^©òÌ\([5 V²[Pm #*,FÐXQb…(±•%‹°¬$‘–ÕI#-ª0’F«RHQ’²…¢Ê̆B@Ì€ŽD©(ƒ,ž²áFxæúK $d ú¡ T A cH«‘ $5!QS€ˆqº6žI€lƒ4 (˜G ’,‘¦í2ðm¥”¨¬­¥ˆÚJ3‹Pr«Z[d’EY$‘UBI%¬dlÑ $–Û-HÙ[yò„X¯º÷xݯç«\jÑ©=µQm X¶ŸUY1|(¢"º:ƒ„ ‘EaÿÏÌH`¿E$XàH°‰"Û÷0z¬ñ0àü_Cö¿OKÌN;ù"x”+'¾G±Â~Êuºü\³J¸W³H-{T¥îËð¦;C˜ìÂ¥7OŸ;kéU{ (¿Å;bá%óV`¡®0¥¥×ܳHíGjuI÷™Éž_œ¦H…?®œäK&V¢î(B¸ÉÎj"Ñta!Çù2c;Éðød¹¡’çþÆ×lã·ã‡`–‹Öñð¥MOöúÿ«Pˆ'dÚ5Ó[e«`×UýX® æqþ0ù9†µÏT¯Ÿí¶¦a ¨¦šöA‘Œ"­€@¤,îBj)Æ‚ÈPÜmyf‘¸\§Æ$ ”EYP˜Ð‰…@÷‡Ô Ñ ¸jÀ*O®KÐS qhªæU¹LL³˜ÉtRºû¬ I×…È ŠÚZ ´iBŽ jÒh!Ä ‘`B2$A)AÀx„XBL¢~|41ƒûD¯“€yHH°ˆ *’±TJ€½

+Ìþ¯âíëB ñ^ëèzú£¿‚û’‡ôÞÙ/òñBkÁÚ¢«±VŠ„Œ„ŠK—E]Þy!M3N‹M‘Mh<®"*çPlÆH"òE^%Ä6âÈ}*=HC€ÂÕ£óñÈcƒiLD¤r…¶XŠ „0Œˆ ,‡¶L.1Ð}Èz€Ó²)ð¶b„#䢬 Î=á£à] Scнõ5„„ Ãç-t=õh7‹jáÑ.Øt :ç¹±ƒùgÑ ÿŸpD<ˆÈæ7”ºBCY‘‘Âe µ´ŸÓÚ·A@„Œ‡bÁ•ÿm®¤œ )ACÃôFè*ºià†`99K\”µAÙª”L·‹Ôs¸='_îó¿ü{éa¥VL4S•p VR))‚=C˜{3¥ÒQ A¥LjÓM]9¥Ä>SÜ9¢tP(}6þÖ&m†Î+=<½àßV+ZÅS,à¤C÷ï¼öjf“{ÙÇaËq»G¶H­îø~žÁñž^‡#› Áè?vjö>?c9SKe¿Þ}¯÷ýC—>š.,RIí­EªCW @‘Ù«®"­„UÂj7©5Aúû®KÑãüC**Ä"*Ávj«ûz[ Ñ„Z‚Hò‘¨H»š©¹ê0#V¨”*·¼[YU_ð¨íÈÓË¥ª­ö·—ɾy@©¥rצ™%Ö¡4ÄUƒ~¢àÅzb"—Óþüߥ57Z9 ß( úÅý%€zÁD2Vžô§Sä×Ôæ(ØÍOÐ!ôêl'C9ÇÄœ%lkðØ’Í”´¿႞?^‹â‰”çEPðQV6OÉotޏ{ÛÃâøC (ŒówÙ‡X.1zR¡0-‚÷×ÈîüZ‹ùuõãÝÖž˜¤«˜:`°Þ[•ÿ,õbE ‰ÑöŒ¨&ÄÝɼ?ÑïtÄa'ÛÔh“:+Ñƒë„ °€«‚•¾$iBуdâÝÍÏWM]/š\Û@CaÑO ªq©ÁfYž°GñÙ¶ÚÈ6À¬cúá®Ü^õÜKäꈟ¨‡÷r‘©ª©ó37„,'³ :„Üc<´ó4ë´áɆѪàEÖG,O\E‘hu² ªó½Ü FœºµQÕ7€–°›¶³ 7¾ÒIJ’HÈBT;Ô\>Qt5’‹+!Õ8CQ9¡ð§èyŸAQ‹È (©*JŠ,ÄÔáðèÃ[Èy¾-lh !mP¼¡1“ŠNˆ]šî¿1‘a:ûÓê_7ÔÌ0÷p°ü>éãr®O¹)eQ¢0ƒˆ‘"’.%…qpÆPãÒž¸+ÑáìÉ”a„   ±((o‘ð––¢Î#ðQ©9=ô‹¡ X–¾ý­eïÁsÌE®Œ§á „"0`®ñèè…‹ï˜ãH G*7±"¥zx1ò%­l-Ú™Ž®ƒÿ>&¿ý^—c9u"H™ú_þ?w¥ã4Ž‹`ª®Òó¯é›‡_ðâAƒRa‰€z{•µB–\BI¯©4½Oøó>¿¹ì½îMö<ßëæõþ‡ég1Çÿÿ;Gý9¾÷ÜÿŸô?ßnv†Z¨HHH’JœÑëªèIÝC·w1bþ§ïÿqåÖà‡A …Š£-ɘDBÄëËîè —‚wP¾Ò#ÖÆ°¨”Þ1YÜ ‚(È¢«¬Eíº˜H@hÖÆÒÕQU’1B–Æ"1²ÐV*#l‡0Ë2ÑD1ˆË$’5•{hV±R )+"ŠHÄ’"›$ÅÆ‘„ÖfEš™…,‘‹Mµ£P‚ˆ¢0V ¢205-UÝ pUöϳÎí ì3ÍäÛWZ ŒÁsEÈI#n]kNÖµŽh¶k^×gèÿSÓü#ø\ÿC¥›I"-lçmÒLꦵü SiE?º²å # $O•U?ô‰øŽ¿@¶ðÀá-š·• Ë5ûѯÑÞBI,0ø©£=Ñßnú§è9½©š/0’M:}—ïÜþžð!–OÕg1ï buà8ŠÎŽdÌ2æJbåÀ„$±*ƒuZUYsA‰Š×ºŠ¸PŒ1ÈÊ ˆ€gÂ!L ‘… ƒí±&"^\RPô¤- +ÁÅ8^ÀñªN7äϦ;tÍÑ׿ €„ÚK’Jiè‚\M l;àw¥M ²E š)üƒ$òàoæàò2k©÷pùÇ€$‰"T¢1ˆ‘d:ôØèHâË,H;¬¹-¦>0R9àÈ«9ZQ 6K$.»I‡É/‘|˜lsðÃubŠHÈHB2*¡"¼íîÃeL~RŠ»ÑV¦ {à Æ¡@*°B0‚ÈIø#$£ $ÖÑn5´ÄÛ+‹xßáÑ\±› ¥Ç)p´*Ó¥:ÄÒM“-£poΆpÛh¢Ç5…¹”©V&qQ,y4 ï'£â¾ IHi™ö0`+6·RË@¡ â*À¶†³k'oKmÁnê0U¡#8%“аù(s(™Ü{JYT@‰P d…H PžVÊ*ú̧‘è8<Û¢F͈+ ñª/z¥×¾e„c@„7‚«;øˆ¢(ðé"Œí¢%gÀ'.ßX"8&>>”L ×íb½‘VSÖ,ƒ¾Ð ¬…/Ê…Àîò?CÅâ1¯$ƒpßpSwé|ÑLÄÔÐòØ a⡤ ˆ2I%Ödµ«lƒU‚¢,F( «”BˆŠRÕ$’"!Œ *¢6ư(„ª,RXIJ@ #6$54U¢ˆQ""Ç• dl­–%Ü0£ –‰™9#î¾–Q·‰@w[±¸ØÉÁ¢,7‹®ˆ«H`ã¹5EZ¢*%ãA*2Q)‰ˆ¹k $Ê€ڂ´À` *ø€ëAU’ ¡(g=FÒÏsy½‡tœæÎ½°ÚîËõûõ€ òÌ~/ñ¿êý.‰_c¸oà}g/âY°êbÞh:«µÕBåK[Ë&„tž û¥×G"¢×ûÄÐ~@Èÿœ÷PVUÔ‡‡ö¼«øÿ´÷¿q1® ·. Q½þ|¦Úáåvý·Ž³— fnm 0D%ôiÇ•3•!TÈÉBsªf;ª¤ ïߟ?k׃˜nªfŒcìazé§7õ Ѓ1Çk:§Ûu®yvo¿JÍ"†²Å›Z^ÍdÙ Ùávö¬ÞnÒ.öÔàçµÊã®8ð¾~/Ä €š-áSâX(jRÔÇjŠÛ}˜_‰0yzÂr$P¸qü(ž¿%ë¹iŽM´ªLM¥J#§gš#ñ¤;1 m^ð¦$‘åÝ”T 33y‡¥Ä1™Âš&(åwD£}ÏÄG$×–ÍO2&ç*ü*_+ÔJ…yæ+¯++¥«_‡Êù~ë:š‡öSÊ> 'NInùÜEûüè¾UíUŸ %êáB|òYRÔ<]ðÝœ¹s£y³†Sƒ¤Œ£TI3¦…žkeËðäG´DrKŠGÐ[ˆ”ª Q;˜j¦']ý—d:Á&Ä¥:BRð›=%ÉLJyuo=]–Ô&‹w’@˜­¤xxôÁ{J¾Í;DPãÓ2âZ½£Ä3yÃ_×%¹Ýuꙟ¶ŸSšä¡~AÎÐÀîUG#Ö<Ž—*2 *+¹Õ‘iІ«E®µjîš3I•5’§ƒ×Ë£jæî±®]‚^Xff÷Ëw60èº==§U‰†Ì¾¡è%(8™ŒEûþfäðÏ];JþYát±“9i‹ÀÚY« $¡5”ÎŽ³Ój»Rœ9¯­ßG…¨œ-1±y›K5a$”#²†©vª©& J¢²0ZÞíeÒÉJÄEæâ-ob¥°xðòþ"±EBoH£©ffúݼ¤ý­òÆW5v+€1‚ïH#©)@@uEÐIq ³iÊ0:(۠ל#ý‰´b¿MÞWMeŒá©i’àÔ…`Â.¿ìuÔàvÞÝ,žV-G„:¶0æ*>9Tʤ,FdË´f ª)h¬åØõˆi3£¾² :(Ðkh˜0Á…Ø\E*ít*!~s4ˆ™R‘˜P!3?™H.n»ÈÑTß÷1Æö½·C…`Á‹9¢®Ž¸3÷î}/7g卸y\ÏÚ+¹Ûĵ xÀ¢Šð< Š»|Ÿ °BrÑý,¦Ä9âîõ7¦û-(ÅH6™«­¼oáÍG¸¦䦯§ÏÔSÜg»§ˆBOMo=C¯2ÅÊ@·_ß%Fví8ŽöW‡Èywó,ß`¬ï°Æàµ‡ Câ°ƒ+2Ѧ¢èðh¤ÖV '/MØáÉ5Í\ìè—( U—EZþ7NŒÑ¤%ŒÂ kçØµüÿìœN@dߢ4ž·JÙ˜!U”Óè¿)Ý’€çÛu(ÜØùÊ|ÇS³Ê_H¦+M«vÕº5¶×3*#±EËOAæ]î6~õ:ù+Ô½M€§Ôø rÁÐØ»ôâµøú&rÇè~W ßjêÕÙpü$2×÷C`¤wïÔµthôô)ÄU<`uE‡”4c¯ÈiÅï’2u§ œÑZxjÜÏ „ac#îŒ ¡ ¤5îQg4 YÜ–w2è;;K4yv8ˆbª/ç~òáΊ›£ÿå÷Œ>¹JXq^äz–9C|${gž{i 貉”©8·ê^ýUbÉÑ8ügvNŒ™n餦ö2kŒQî\Ƕ´ Ü¿ZFÅyY(ffg×q\èkß9)á¾MެßÇÒaóÝ ªªª‹$ìš"®!I¹[4"„È$"2góBürˆ7(d.)¹êänœâ„ª©‚†[ƶlàíÜoÈ›ÛÄNÍRrTbcéòYÁ¾ö¸šÇ5eöî3ŠïLÅцñŽo¹¢ÇØß0—Yâ7 *¢†“VÄNäÚk&Í[¨[Æœ[oV~3î )ÂШ’«¶ÖH¤#Sä¾7ßtýôpÒñ¶ÑU\ÆÄFi×µ¨ºŠ¿ã`ÏÔÎÓ-¥Ñî4S$3 ÝQ§ Å%¦†’ªÝyøGÉ߫܆êý]à+ÚH˜ #THÎÜòð/r; z¹K`È»Ó1¦UÂú$º RŒ*á$'Ð0þOÁz À4àÏ~I°SQ¬ ¤Y(5 !X0ˬXt9šN~îó Kª¿7ü¤“¥úÑÌ@Ô ®ÔìrªY%°FfN‡–×.ÏèyÃðø³–ËÊ•FÇ“‰9º´@™ÿ©­ÿ¼|Ò÷ßǽô¯`ïK~dU”\QØK¢2E °’DÅb+(H5£Æû#‚ ¬éP‘‹]v¸h芧p‚«ÏùK€º®dšÄW•,$ôµÑH,FIÛß¾øÈi'p¤´Ž§xdxÇ'ZoFYlh‘}&JatM$;õ¸süÃû©$™l¢‘‰áˆS@Þ‚¬SH…2+툀lE׾߄s¦Òaø³…™p€á€°m#bLÄH$Y ˆH³Ðß 9ù¶Æì oÅPÀ2ªÔd$¯€s^ŠŠ «‹àý°AK:M^IåBŸ×Œ Â1„‘ 4w‘V.† ^¤UWM/:ˆ†¿Q‡lÑþ$ŒÁeäꙿ*§o ¨Î«,E;†ùõX%Ûî>kg³Ò ‰I$¨Šx%dæ{²UP’#d¶‹‡ Ãß´¬û2ä$‘„ðƒÌ,œBþSM™`T•·I""|ñ?3ò7?|Îj^Íß5D É<èiR—WWY&µIX%†³UïCHìhµZ”vÅ ¹*)­RcÑ(A Ä$i{tЬ k÷·'RتaA´³-Ô>.´Ç¤P¼Yq\*jËšŒLÙ4«ª­$„#¡E~,Éù ?Ÿ¾I`5Ý-‡ìáxÄ.å0XŠ®™±Jµ˜ˆjÀó8!„‚žg]Ón>.äø¥¡E´ó/c¸é:NÞ¹óÀÁUWoçͤ Iù|&E¬G-‘e€–p³ÇJBƒèp”Á‡•¢*J•”¬`QTçyï½Î]z’I£ç±Ú]b®ª»Ò÷U,1y¯“Â俳*i™1ª§Â1X£–ù‚“›9ê/þïárwÜAEZ9ª¤çZ­œ¨"9Æ"•Î…ÈNó¦«A0’EM¤j2(oqÒ‚âýÈ0bFú˜@4‹ wD b¬$€H$Š˜çHk\«Œ_ êWD³_eÔààý^”œ˜I#p˜%BÐHCtýÝhG uÓ訞¶¾ÓU^2B„@Ø:ãݨ0ªèrÈOËì0[¾©×:½>Fd¸ªƒ ÐŽšmI_-¼ðÃæ}n_âàù8‡£ÍœÁ}ÑÁ‰}Å)ê§¡˜nd´ñÏÇÍH¡Ì+IUýÈ…“íÙº÷—UY$Y<ñÏZv­ƒ%ÆÆ2m8™un¦…÷ðÎÈŸ¾H&ä¼Ç™…Jâ8•EL¢¥™ rÅ U@#UB‚j™£C1ÐæÓ í³u`¤|G¢o4$#%ØÒË+j%ÓU‡Æc4 V+ºlX¥ËúAÀZXÙ`àj@x¨b&©J3#åÔÈøËÈž{ó¸…íMØ ’ qD1˸uÓ‰¬ù>'Çî.Å ˆèŽ ãÆ*‘gðôRùU¼þ_ù_õèv•¦¿¾xÅfEr¼BÔ{,xøJ\nq/b­?MywÉêU# … ¹³£¢*ˆgdY.É·úØÏj Ñ]ý »Ò#ïW;Ç^÷œ6­ª„¢Ï?(Ët`ÚA äN1¶‚AŸp@€Ôˆ2¸ôKJðšµ+L¶mZYi÷pëó¤ô™ò»¨0ýªt†!ûY¾ŒGƒêø§:’K,îOܤm²wÛ?šÏèø'cƒ@ÊŠ²ÚVÇ ‰£ÜüÀbEº"±cg[´Ãxd†gvg´Á³€Ý7Ü=Œû²Ù¨|Ð`Ô$•;çc‚â üžOU_ÏÓ2†Ö-û¨¾¼YìÌ‘ë·`–tíå$¥)`)¹¯ÏÏkËM swâNwuçÂÓvå8I˜I$ h¤qãHŸv¾~)75†fl§dµ“õÊ¢qBwx–w’W¼©÷’^'YZæ_{c÷¹òq8[W‡ +ëëå*aˆ‡ÏU—÷ ¸.9(D9DYBLˆ(r‡q0ØfÓ-ØÃ!tM­4‹m„yOËåhU·M:v€©Î¡߇P…Åx`$QÎ$1<øèŸððL§4U „ ëµ.*=¼}gÖ/±l2¼¸öÃXŒ¾óm(üŠmc~–kæ6]ß@ùSÆKR‰L0BmdÇéýú~Áñ‹ºÕvyA†(/Ï¥P”ú°/TX«‚œãÂ[)ÊúêØ×9Pµßò¶}¿<|³ÝØx]'wà‡2XZÀ4ž?…{M*"’[àËŸh–Ç쬥f.oAÒSŸ?1ð’O4<±õÑŠ«/?@õ»›q*Æ*2´[}º\t~Ìuš=íþ›íëâ}þP—âôP,1àqü((ˆ?Ììà:AÜNìû·…r¡ÒŒ»³áä`ݰj8y7c‡Ì Mãi˜ ?æi~:*Ý¢oõƒ, °yœµà•3³Ã:"£Åî‚Àd‰WS|Ófô؃ìŽí‰?ùþ9ÍFÛ…Õé9 àuâŽ|ì/Õ“q± T$´ÃƒNĺ„~³óÉÓó·ÎŒQ©ÿ5ù’Q&ŽGŽ…fàv‚çÂq:~7³y íùèmò6󞤚Û4ªÕM1, ÷2ƒ¨š…¥ ~)@mü0Ò¦C 0ÕU¥GŽ£ÑŽØ¿êï;«uúíŽ{gà”óé¶>»ÕöÐ,<|ÃF;\¼„ ˆZ@Ç >Ƚ‘VŽ` !„òÈs( ÷ào8<=\gž âãßÃJàb øl½ÉÏšÖ^:zjæÞâéi¢eêx};¥+r•ŸiíVA¾—áÅÏÖHò:ɬ⭨ wà:®ÅJóðvQõšunÖg¼jM*}‹ Ú è襈ǛŽ)ØüßßׂŒÿ—Öœý¦Û bÉ H„4¢â8tòZt²)RŒQ]C2=7…RWqö-ø~¢{3(f?ºó ZœyEÀ Îäš”„!Óž¤BHN TR @Þæ·«?ŸÃÍz[§Ðy~î;›/U¬D “kǽ´TËH <µé¼ÚD8O _$=LBî%çè¯)èÀ°kÖÉ$Oe÷âù-ºÆGÝX{ÿÜ´žŸBÕ3Ò-E÷2ú-•ùû-ÚâwèçYª \¶8žþ›Ó/å¢OŽR–åVªõFh“\^2ÐÍÝ]¶Fc{5ºåüZóÏìûÕ $"ÂŽs=¨Ó$´· £¢åx7îQù9÷¤…ɶ÷Ílƒ#w\É~@Uùó³; ®ó7YÇv§˜ÂœaˆªÒÅ<·þRt‘ :®¿åKÍAÖå°ù¾| fÄ1~j{š‰¥˜e®¬‰ñ,¢ŽÐ%Áb-¢ÜhàG܉²7XÖ:¿iøÖ·×ZQSzÞñw}^Q§Ä'ŽKQtõc›–E—M¥ué@èZSØŒÍgŽ$ÿ~±¶œžëé¡}I¹Ã}Ðcíà×ZSé[~û§ãÅŸ R]Eü¶t¦K_<>ßÖGÍê*jx«ÿw–BIq îÚy”Ž2¢Ã-Æo«ý¥ºÁŠc½*Û ê~A™jßò‚Ä~3÷Œ7»Ì-9ï_°Ç<Ô·Ød ;(ºNGSÔ6qä°¼ù¹û%W?Kf'ß;ÇJ\^^1þuž¸MÖÇã"^^f·žÏ´¶)OÛð\Ð%óV—<~ mä¿¥w–ƱÀ}0kLx)~NÀäL ½FQÿ‡áÙ;ò¹®ùý+>ÏæsC”4÷&Öqa“áÀ˜|>#{F|¥y­’c높•o·€Ô(²3<¼ºµyΡ±? 1æ?ɧ°ô÷:uÝ_]|Œ]ŒZ/‚Ÿ7ÑÜó9:ëµvNþƒU•trØvOÇÙb¦ÂÊßç?âÏö.º,p¼¥¥ÍÜvsi¯å©æÒ¢_´ñ•Ùo?'ªÏ]p—3Ân“¥•Èž¹ãfáÕ~çªc›c6êë·(°¨a*B‘ÿ³à²çݪÇk”ñNãÎ{ÒÀ©š~ œIÝ—»Æòõœ[¦»çÿ4·rwLx¸F˻Ħ«™½ï*(b\¶™,}W…¿žá´â|—úüË$礵/^¥!˼¨~þz#KØ®Óç-”%Ÿ_ú¿;‰‘‡^Î;÷Â<ÿg†¹ÁRKÎë©•t—|dV”„)gT2N „ óPHë$"Ný«›Ò#—Ò3]õ½³Õàœ|vŽ7¾ÑÆLË{/Ó*;õ¼òˆ¬W!IÎÞ¬´$YŸ°e^­ü¯HèÜbüýšü7kY IœµLég]j_ýŽ;êŽKÝBh&w˲€áäáã:ꥰҮþ%û±}åÌÞ*VšA¿!Ðí|.1”¶>ç¼òŶ³.­ŠK¨OçjÐ;µþù3fÝVv®³^}ÔS6Äöêë•·Õê²;ë§ûó–”k®ý4;8Ü”ÒâÛ:Ct‹ÛÃFë£áaÞel´97{6¦”½>I…WuP’ìš¼È9;£ù±v‘¸ê:ûTú8rÝVšcà—yg48vHÚ›}~‹Á»kzw¾ËRÅc³w=ÿ޲™öâjO„¸ñaÆÑ©¹YëTLÝr9“‘û©´:?ù+|äÝÞØô‚Ðò­%ªšO¶›µ‘;Ff]gÞå÷ ›x-ªœÏ2§·xÛÛäl·ñ#.Ži§ÞÛEþÞN['jp¨’-MZÏ"”;Z“¹ýÎÑéß~‹vÊ_TT–U"«A®Ÿ€ÔoRýÌï…©^Šoß$cNÔõVýq÷Õéѱü¼šßö=ÿ™ eÔªàåBÝÎVª¹z=ª©§£»¹Òý¨Û¨´ ,ð/ˆRÁ’;ÏÈ»¤ö·°Ädáb¾ÓS0é8¦ ú˜tyýÔóÆ*gûIaµºªt_cǼ¹GìUß±lìümm³xþ½“­ËE»Ý;·á(â“ÎSÆê)7ÑE ›:Ü ç¤v;kÖË÷mšK>ÏÊ`îœSMÔQR!¤µmÒAÒ%k}¼T“Ÿma»9JõG"G¨º~Ÿ‚ªÞÞþ»{£»óùaů›¯ rÅž= mgbYØõõ²éÂJ7ÉÆUÂÁØdU³j®?¾Zg+è\|ILÞÅÏODÇF›Âv©ÌkÕf¤æ<íšÍõÖ7ihäÃÊp:ývtØö-¾‡A¼ ÞÎ=Ær;;ÿfÿUÑàÝc=oÿ —¿[ê©ôí Ž Ìí’AímVáÕòìv#k¿´ôÝ¿[u·²žyÃÜ|Ê,~-?Ãuî‡Øpå':ùʙ옇Þ[ëT`kü-xø¬;Sªv±¦Ó~`5{Î/Cå¯B/3ÒýºYßZË'Í{§Æ÷Ë[ ŽF!Â-ev(.ç¹ývÈ®ÃíÓæ*t™‰%gÚöø²h–Ë'2ÃffŽTíô3¨-VkÐaÔg´Õy{g™jŸŒ*Ï ·õæèÈã{PÕw©ÐÝ->Oú×Q°7›ØüÁ{;yöÌÌV/ðÃÛì÷ÖÛ“÷Ë?.0öOø¬³ e®©«QàªZb|§ñËýß¡V1Õ1lýŽVO5ìw¦‰²ásÒóŸËa ]OJ£Ýçõ3hÁêeáížëæ}+1 û¼âÇõˆÍfÒã7;UlõÔäfñMïú»é¦OØD6¿Ÿeó&çÿo¨1Ÿ+µ\enëÀ¨‘êR½\”|;Ž©½qnóC¹‘âMôÛv=4¥8Î!Kœ«óæ5v]çÃù¼Êq3´æv^{>,N÷sªV´§¦4%ûk£ôŒ›fÝ6Ç{ºxdí&6ç¢à¶hõªþ(rê˜{«ŒYŸ7ÉÊ‚ÑBy^I>Cº™úÂûPVüæfqðès¨;VÚX‹ÈT,|§˜ofƒ•§x‚àä¿É¹|W÷{’=µ ðt9ÿ?¯‘mNÚ‡jýÑLÄ¢íz5o.þM/R)qƒÃ+'ŒÔ¬Ù¯ñ³…ÈjtlIä{… nñO!ÚéëÎ$ù[5ðÞOҢ݂9º$Û¡‡¹L®UÙÕÎÅÀKjù´\Íäuu ­|×¼þ_íúãï.¹ûWË*«éßYdéRNÞ ib:BƒÐà ¥€±9Áë?V”„!äŒ_r£ß?óùª^azy×Ü+ü×$³®ú¼ÎuúN…ý#BS’L}~íSyâ i@Ø×û²üîšçûé=áv‰ÁÌo´Õm|*þ·ö™ayåaó˜uÛ³¥“ñn»j¨îBì’»úfGk>+9W°£2#B@8‰>⌻=Ië3#iÛ>¬“Õï5²]‹A7åH‡ù Fd}‘Æeù,»ë¯_×Và\F»·upwÍ XË)Çq+›´ŠéÁ¤AžxCîJõþ6x~Ó¾Y¥~—¢ƒhûÇž†¬Ž¡ø(¡hŸÚeØ…ØÉk+Mv.¯xµ}þëw²sHÙ¦-¹vYÖþVHÜ”"É+_ù™|·²/!¯Óv~Þ®Îᥠ½ßÎ¥‡%ưrã1î7[5'9†7eYä”­–þnè°%¯:ºC8?þÊç-ÌÜ;eÕ>‚ '¹î–hÒ„äþZñð'€ bc&ñãe¼Hר߯Ã>™>o®¶E*þ»> pÊ`øví ¼m7Ç‘£d±š‘>ɧ¹ëoßó9ó4pµOš•Wƒjב¦ý6¯]íê«ÝÑaUªˆî ˆÐh˜U=¬w»…˜Ùy2*¾ô*úó‡BÿB±¥õ^pwéOÙ^®U­Ò½™Až™ÙÍ‚gŽÿ“"†AÃZŸÊ`‚ˆ—ûmV8¾îîÞðbo†,ùê|Â&,WNqq®ÖpT|¯]æ iu[{N,;µTºÇ·;¶][ÐÇþ<^­9˜<]QÔSÙS/‘E¦oB¥ø¬ºÌ}'^Ã`j7s·;Ç|y³ë5qª7÷Ý¥ÎOSûâжéZÒݼµéý-ÅCi½ lwß öÃS/Á™îÚT.ß­¦D•Þ÷>³{LxòôûVºµÕäç•AHå¹ij:BƒØW¸j\9~jMoùcœ‘^ƒÙ­óvmùô—=µMáï2wÓdz<n{¦F†+NŠR  Œûèv)n†êÇð¿Œõ™ßJ'ÅLçWjfËׂÀs/+g¦eV8†Åš‚*y'/ŽéyxKõJQ\ju›§ì%¬ ‰.~ÛðË ¤Óîs£xø£ÿ}õœMö·Ÿ¶»ñ^Û:V.ò<Í[%»¯ræ‘YQ ?—üëÛÉ7Õ:Ýßæ˜iw Î*LÛßÍ/äï†ÿ£Ìnût´ÍÛÈÆÝ¿(¾öÄ‚ù÷ÉÕ÷–m’KÖW"’͆Lr¶T¡ê-”Û ÇPÿöf>‘YQ¬­Îí—½ßÍZok²å%Åí%úë«R²Häò“2鎜Ï?¢ë×…]ëÎbÝ*MÔÕç©©ã,[sïXÑ@´ÏÙ×þíhU¥=œž•ƒ˜¡ ¦Ø¡¡^Å3ÏTß7u¨\SཛÅ&šË½ w÷Ý›ÓÆ{,ѧWßæ”û9ž'yÌyýÐÿë€ìà-¸ÈͶÙ)1Ùq˜X1™GÆ‘úúËËÚi8ɳKœ¿qÆ…/”vRuþˆïuùf{üi!ÿX-ж”ÚÙ—ÙÙT©U6/J·rPþ>~µ7¦vÂÿo-{Ñ\Ù[ñ=U13˜­½=žvIN†‡ó¡¢ú¦f¹©¶JVšžc?ù:™Àês C‡Æi31¸¥ÔvÕ2¼YE|Ó‰Å]îþ_°N‰>œ^ÏmZŸ x¿’Sñ&æãÕ6Ö*#‘ŠSÙÜ!pÕxÙëº.i|Y‰~Å]Ìï¾/îÃ}í)s:ËOÜ—*&¦¯íŠõ¸^…n$¤M­ÿ/”ÕòñÃçÓ¿l{I¶¦±>«±ˆƒÈ¬(Åãz[ù8GîÖnc·Öw¦›²Öz(¶–Γɘ€„!.>ÙŒIÀÏ=Mq›?½•/ñ˜b¡á.rêBñ ßJüNÀ-Böìþ™z;¬6ÈN‡–òcÃ[±lVùíÛZ·V×YŒZø,VqE9!6»Š¡Nã¦ëI¼*õuwZ"ðtÒVš,tõe›·3!yoš¶´;Ÿûµt3”(æL™ÝÚ‘‹±uûU<»Ìöã¥R—IÉØ±ºq%x\Œ£=ÂV‘šé(Y—õ’ÙRÝ?}ëWäoÛûŽœÝ´ªvâW¾á´Õ%_Gæ]2~jK L?ΊNžÿæçÆ{V9š'‡÷ýƒ6·åcÁ½ï:bÑ_[üF›xÁ½—§]Oȯ$Þìx=$Kñ9¯QûìÒŠÇcRß¾T;‹Kásû™L›ªz{(ùÔõg¾)_W¥tåºN6ÓW÷í¤kI[ï§Íô“`«<·lXwQÙg÷O+RÓà¦Ór½ýœžØo !‘(IôT–X#ÿ ¿æø¼u«¶²ß_Q³5Ò6^]B¬›¬Ó¿å3Vë°ÖºVMÅ“Ú~kkôÍ;Û.´)f¶çzU+§®óvKk•ÛÏ7 /·ÐlÇþ9(Ox&~ûTÅìÞ»?Eú¼‘hAáEÜNðJ0ïppºTŠ|;<Ü>êûKÍè$+¿qùJV U<+…ýÍ·Kp¾wþ›×ÖgfqiÜŸ-"ïu H¤j|ów=ÙLð,¾|éýM ùlZ Srrƒú¦'!š´Ú$.NËÞ+hÝ¿¹Œ¢ûù×Ýw”™¥‘øE=TMæ&³ãÀÆv3–œ–Ø`+MV0úcá¬Wó‘>ªçï¤Û#MG+{Àì,˜ÌÜþ;Ƹy-ô¿ý=£"ÒåOƒŸÁœ|åvê.Uê¶^\FG¦jïÙ©zßA¸—ˆÆCòŸ&_  ³«ôí7güy®+’žÚÂOr·÷̼Äêàè2îúyÎ&õ;®ö~1?;¦=[þoþ$É·PÇS]b~M—*Ï¿ófÑ´þñ3YŸ8˜›j¤¤8,™eY=<ÆjÅ…ÔÌô(NDEãüo•c¹CôþUdéýê»mŸývÃÁçõÿš¥;¬—^c¦ä=O{0ÝïˆfKëlÞõuÝ%/x!§þ.ðÜÎ:ׯ…ÕáòtѬOœ§nNQ+Þ±Wè{˜'ufÞË0uè¬OS»Æ»—ÝÙrxýbE&Ç”ýŒ:w—Oïöýœ›_º;§ ­–Cáy¡‚õidP£ZŸ~þ0zÞ—9®h†õÝD­]cÆgwèóå¡—ßMLÒw·[ÏvGîq&ûeê†;Š*wɸdm8;™q ×S’}¥ý¿Gç²ë:ã<ž7yŠ O¸·eãuÐdº‰•ýCÆ‹\í²ä™&ÙfÇ\Í(«J×Èÿ‘%ôÙ6Ìy†ßî-‹›T¨Ò¼šUA»L {…¨1%ÐÎu"ÿ^„Ão[ŠæÆ®¾¤©ê[~yîu#~+«½hÒ%ø¡š4éù76–¤îûý%wZqáíIa±¯¦–¿–vä=óÙ{©µ_½çýìÀßçýŒ76’ ÌYÄp~nÇe}™ö$02¿$±›èZœœUäo±²p<—Zû; Ô@@9"ª ÷ï_O裨ßж²"‚ÈJc'#zì¡cVý¬ÉØe¤•Ó­›––1؇I¼=÷Moo3˜ šÆ’urU–Å ö§¼·eŒý\›8×ðà^¡µ‚fOSÙ¼¬zè2^]Žu!Ó£¢ÛÜ<<}âµ5gÆ.`ü».ŠÊã"³oÕXÛ¡»Æú.6´¥þoé*»©}WO6úéMNƒ0}ÕÆ*v{ZÛJæòÒLòrÒ^Y‡â¬?— ɋۤöüãÕÞG¤Ô‹D{ T7ãÀ‹i¼L91<ùŽƒùØ'»[G± ŒLi‚Ïã”Sábúц@sØúµk› L}½¿¬Ú'>ÖÍ÷£›ï_ü,ÈZ»å$þ/]>Ÿ¾ý9§×|´º¤ùŒñ}ýkQ0zô^©(Û º’†çY,÷×£çi:Ó©9V®hýrJß3g5HõçöØÄ úR%’KÇ)´Åì/—m¾°º—üo<+{5Õ³gOn¿dÍ».ÖçÜ·îÛ$}¸Vm(â®fzÓÝ×ÜòOÕ/1oM;Áš<“ömäKn>>ݯgê¶³¿õ%Á‡ù‰º¿„bq:Â×[°zÔãóØìþn‚¦·½ÉÎ(OKç5á::³sòÇÆ£ìúe%®¦öŽþ…Ärƒ õÍRyŠ¥f‚;äðbœå—­Ô34t©¡]3ÓT«ÎAâÐìÒ:Õ‘õù»£³Ög½ù†ºµ¹¦îöŽËEï0å\¢ ŽZL+ ቞ͷ´¿ÛŸÔ¨O“æÃê%o½“k 3y“V¦g éàüXÿìûà úc;‚(G4ìÒ_;畟è&_fþíú¯Z³] Ï“f­ø´¼ß]É»ZÅY¥wf\ ?©ý-†;9‹òz¸{-ÍggG{Ú–´Ÿ«\ˆbOÆáhêºy^gFi¶³ËÊþ:xñ³©Ì>äþzŠÙÁòpOݾ:WÉ­[ÍQþZuÝŒç?=4»àÕù$ã×õºcô·ó>0z*¥¢Ö¤¿8:f|fè>ëxNKÔvŸG¹º96Fý$½Xצf¯®5G×£<×XÅ9cDõGCúa¹ö4GÈçw3“>›¥ .g.ÃAYI‰dÓ}l2Ujý¶OÚÆM^*ñ†¡ßËØ8ÄÑö¼×qĦÓn{¾ƒš³¬î‹Ý+°¤WuÉêS|çÞ»­LjŽß .É»]|ÂͱoÒØ#÷\D½ M]*ß8æoe#J*zêúLÏÝ“Ë_÷èÈ­*«ÐÊòÕ“;Uk‰ˆ×ScT·/LïîÉ»¢ÇüÅd™Mgx\Ä“ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ†·Þ|öôáŸl2ν@4ô—ÜÜw]¾Þè{\öñç˜R€>|žßÜê7o²}ÀùçÓì¯cÆÄ¾˜}öÕ6ÄWXÒ€‰€ŠPN@ô:‘”¦€ 4zxñ…:|z8(p}ðEàh¢Rg½KâH©>}öÓ¬£Ç­v—0µÖ{Ƨ`Ô÷rù½÷¸zÍØbÄՃݵÐcíép»»µ]kÁV&÷r Í«M *âîÒ7›p´Û ßmÆkâàöÔ‚ûçÌkSN½Ú£ßnT€ ÛKÖmm¶ìÊÖW>3­>Bƒ«ç»Õ¾ì}ð6ìzð±€ß]'Âxµ†€GAÒã=´žÂTڗݰàn€(›mH¹IE_ÚHâhô5Âh´e¢‚‹1ë…lô£ vç» (³ÏA@÷8Pû³éT€¼•îo³»p:gb×£ååÏ€Cą́ $ð}kµgWbmÝ“»‹º[¥ ¨ô)•RµÓ½kšVPîîÌs»×x}‡/÷`.ÃGÛŸ=³XM©šÉGFÐÇ9$[ªßfª5§6 ÙÞ¥žóhñêutÒÚ½ö÷{b9-ÙÔ†µÝÜR©ÞÙ9`Ãmë¼G¦ñMÝœÐf`úÞxwMÀ˜fT-]ñ9èUâÒ™c2Öê´7w ²m÷w Yzâ;“îËvÎÛœµÎê';r™aÛ¬ãÛžÖÚ ½ÍÛ Ô— ÊëJ¯¼ûï>ºJ<˜5Ü|ëÝö¨±ìË[IÉpÔrTÛ`íD•ÕnÍÊ÷ξ$P¡}ö‹—£M@Jä ˆd»ïŸ*€‰|ûïyÏ^ÚØöÙ Úašêäî´äuÌ7}Ovèhºo}Þùm{áë÷^o»¯Uß|ø‰Ðzç³€4@&! h“¦LLL†Œƒ FM @44 hh Sô €˜š ¡€€ÐšbÓI´FMCJy=SÚ£ÓmM¬ã¾ÖroIµ¼uÔ¦‚dð@0Öúxùžßì[×m­‘ʶF™†ôg†Ïÿsµéµ3ËÑ@à-^(vrç¡‚_ÁØ>±³‡Hwþ¾+ËU ›ø¬äq®¨$¹L0xpöÌÅâáÖ~àf'ûûž}SüÞNÑVÖ«>ÄÊåöa÷5{ž'«}£ùÉþq×X˾'1öÃÙÎ|[=öæópmç뵘ºV“³øZíŽ÷Õ=L@tÄ_o:'¤„AÕÇhÖGÛË ³{*®%µÓ¸ŽÇ»IOäRHy"“r9, ä@EwQHÃs‘bês)v9õygA 9òñe´+3üýïÈðr}OméÿpQ~ ²ÎÏÜ~uê ¡¢>Ñøø€·ë7_TÔ€­ßöø]droûífvoŸûgA] úÞ·q³ú `:1ÖF2Ú7¦5T§‰ê>ïoa½±?቟j‚÷çÔôiIshË `ÿ[#\XW:]5ú¢·câÎô~T ×Ö·j¢Ï8ä«'ùÇ´y¿GÚøÕŠ@ϲ¶›øµØÞ.3u#0?7ü‚ óÿ°jë\€¯Šè”´æZ>ææöÈHȬ­È+ÇÇ<7Ü+þײH¯kuí\Ø<Ñ=/í¤Î„YëÀ{-oïOM"4;Ϲ°ñó]…3ÀnÕ†FšÌî\x ‰É®îH|=;®æ]XE;¨‡^ …2Ä÷êöø>ë8çÏ ðøh8„P8¯u»Øx¤Ô±m±V*_Ó»d¢¤®Q¹­ssf‘Œ‘ˆ+ ÇûXX/Ìi2ièÖμ †N¶í@ò£B‚ sþçµNW¦g©‘uô÷tÖ±þ›jý Zd}©}ü(PÊ" ÿ⋾úlš—9ª®oge€œˆ¬ä>¬ÝÕãWÃÎgW­\„ÞŸsMwU¢r‹d„„"’+˜›õ+s4¡¾)Ч`º¨SUQie–ªKjÛ}Ú¼X’/¢§õ7ûm‘µò¥T®þï³wéª`Òbˆ¥û¡\ö“¯2eÞ›±´j­uÕÒœ1¸Ÿ)J‘õú¨ÿ†ã}\&k&„l=Š:ã‹IöHšþyølï‹ç÷üÐXŒ¦š–DÐ4¨(Ý…ý]}o-R­èówõ±’³€ *k9ˆ¯v¸±Of*2²„é§Á€íú^þÎ^Ö^ÚÊô,PX޶¥?:Zâ!¹…ßkÿŠò ^­i6ð[B~Ã\©Çä¶…ÄÍx¶=+ØÕP—%D¨wmNåïÒ @Š)ïü<ËqSm·à¶¤Ø£Q%Z#$¬Œ€È‚ŠdÞÞ ¼Þ®ÃÍíï-w*„ Ò;€„-> äØøÕÉǺQI$†×rl°OêÀÑ>ר&Å·r 0`x²p!ôe¹ómKøNUAëdOYA`$“RIK®®.œµËEþSñwkÕéø}o{š»Ó£œ.jI›ìTÑ¦Ä¡Û ŽÐq„ÙÜS)|©qw71nMIâoß—^~^·WNL,@3m› 3®˜ô°qÖV€k`¨2ûpòá–ÕC¬Òt1LlÔE™bïŒE é™sŸýOÁ?ÈD0@}>eKRè™'ÕÈãj­ =ê0¤ ¾g©©Èf¤ª`›ÏoxU_d#\( *àÈä¾$vOÃÏ}þQÖh áã2ø!J\/nï™êKÇ$D‘˜LbÚÜ(>ÏÃÙËÁ`¿¤~¿øØ×ïüTEÀ 'šûÆ=DóùFPA ¾lCÍÎí¿8‰T§'@bÇûÓ ¡j̯-(!Uæ÷•l„¼µUQLª*_¦ßÈ™ÿ+ao]öÿ³Ÿäðϰ•{—çÇïŸÈ›'—ú“Ê¢²~ÊãJjžczFx|ØO»çKaïRóõŠ#ÎI©P6OY{æB·¶¸sºà k¨7(ÔÓàP6*CSÐÈ;HßQ¨Æv”ŒÄ’8éÞ<ønËu·âÞ¬‡!Å·¨®4Tu]PDí§ N'Ÿ‚7n8ç÷éAÀû¤r(ñùz”I|¤i~ó~_YdÛÕ×ñÈÎ(ÆîŸŽÁ>wûm˜û.Y<µ²² òÊò/§Í诨ú3òdRÂå>÷zöÙR‡.5O[ŽÙ1Îõ•ÙB J¯ÀÏhdg·sê@æ~×£ÜlØ1ÅBwØ@~g—±ÚÃÚªÃÁ"åBéåzÏ"içùe£ªý>VµŸ«/§ÑzN¬v:ì  ÓMᆬwôyµ¢žÂ;Ê+7VJu†b?FBRE†U’£¬ ¤q=ý¢ /¸(o’ð·4Û|7ã~_D‘(‰‰C³¢îDÞ+h<­ûù`odž&Ii]¼»’oN~ NC¥@W£6éî.ûòn·]ôçëqÆØs˜ò›ñÞ4­w¦AƒUôÄøn³Íg8­Ë,àr¬ü E%ùÅÚBüOÅÆ3 HdŠH±Zl¢%F ÔHaæyr×<â-´pýÁócg·jòÌx+ŸšõÔCKö®c´!5ÿ­zù=Û»ÔFïç¶óá]&˜}÷=ÇGlɶ€qm[]àñ!öŠuè±×¹¡¢ÿê¸ð4ýëþS&Ñ\ÐÁÐìd¥? RÞ1‹ôS•ÿOt;+vÝŽwÅÕ„õØì$[5î*ê&¯­z,ëJ©ÆïÓ†®‚6ã¢hÒN¦«Kä&×ö} kÜFÊ–Ô ·¯]~¶Ih¸Lö1Ù6¹.'¤ï÷_ÚµÓGüŸ´Ì2ý<÷uÙ‡ÿb¬plßÝî­Ëà¶‹íÊåà§²“:×gSô&n3&Å¡ŸR¢E Zªý-úfþÿÝe#­/”ÜvñÔm{fÛЊº¹X»¦ã±Q”G‚ôéO¤´ÅlëzÜ3·\|ïQKoyéÉõcêáÔľ#ˆoÞÜñ¡è\)Y•Úòkûoå&I·,µ®àï'´Ãu,~\7-d–ýÁ¿l+^ËÃóás[š€¹aa-þ¥¾æÈ_>ý×)+fÈ· Wuz¢R"=é’íJlì¼îÝV)ÉÚ5 ̼FÍ2>÷+J—Å›ìe0ÈÑí³ðxKGî=ôry«5¸žÒðÍtÚ¦ÀBr¿›_ï¦XøuÚ묋ëvLýâfÅÞ-›Žn3\v¦ë¾ë7t¯bͧe´—EŸßµ›p‰œ‰KxslÙø)xé«h|ì4Xø4ákf#W>÷Uù… +óDƒ“=ªâÿÕ?aŸÊåª}>ÇEÓ\*m$yFô#Fñçx‘/¼s{¼[<=4¯öøóoÿoÎ6n›~k$ÂÉÅ´O¸&õԥʟ«sªvZÂèĈ€b{bÜò´Èòé|9uصjdðFw~ók .Q¸>7sc„àÞ£õп=<ùS‰úøm2Y[mÝnŠ‚íY[jìÌm§—ís<Þ½ËÔfz§ý™ïæÎ°êÏ6o9®O.w12Ý2hÔóèjÓ$Gÿ»>|¤r´Y(å³f“f™zÄM ÝÅøó`hiuM»%³qÍZ¯bÆ$Ús'ük&~Ã4™*æïb‡eƒŒUA5©ðlô۪ϮƒU¾`¤Éœýc(±EЏk¼ùóüÑHYÆÅç..¶yëmãð­£™zGFÍÑËõeªwiq3ø„[Ý»€Ì¦ÙL×K¥&yl^å„^àí±Ö2˜ˆU8M6ÞÚÿ®ö22¦ÇÎ>PÐñ)ïO“š¢Ví–€—Æ@#ùƒaõ@ÕÔçýÖ¾G}†Î-µç²1tÕÍ`¸”:Ôö ª?q Ppý¿º´·­„ Ñ°^5>{–Éú<.ÿÊz“7|7ëŸ7σöñ±Õy+%ÎÒÏ"i‰ß_÷×xÙÛ®Þ:[&¿Õ¾·þðè|—b—ÚÂ[žc¥[f©H•³µ9ÇW.‚¸Ûæã~2$"wÑ_´þ¸ ~ü?×û”ª)–þ´Pzþ¢ycýÞÏø¶ÙüXFÈÂþ΄×ñ šÌå¤ ‰•0paAÏô”¢¥ŠQüš?¥í!øý}7N¿vÐÑB(ŠºäA«ö% $,QüÍ”½´äpD#EPŸÈ³»–Ÿ´]~oý º«Ö–µ^`B†&€IR”OàþÁóg§3ç*ªßÎ뽋ÈG0ø``‘\×qt€fë¸!²E!Œ ŸDŸôîl@‹¹û „;%‡3FCÿÖƒ‰E†Ãµ’âÇñ~mc!88ñŸìøßüûÜG:AI`obËd‹`?Jë!Í3ø.lH‡ Æ11†Ó‰´H{ýôQÐçÉu ÿe_,¥¦Êl¨…BVbZƒmíu]›¾nï¿ûOw­½€Í&d%Õzeû•Sm¨L²T_GvîºÐïç9Ã-ö[xµþŠ­}×¾—ÍÛ‰GýX@WDÛx†1_Ê ¯íŠñª1* ž0(ým.…LP_IM‘ý™úc3BÝÿC"`†u¡¡÷èxÚ%ž]žþU5ǯ²Šbúݨð?¿j"˜6²õ*ÒmŠ84-“‚ž]w–.0 D‡ßõ4€ˆfÿy}f>èå;¢~‘/@¤jxâÆàô{ ÌWÄ„¡±ZàH@?­ãÝç\…}}˜züÞ^QÖsä³aaF¢íEýš9œ¿Á‡D©&çlÝÐôI£¡g¹…åÚxÁ:@‚¸ŒA]ýÝÓ'wÁ¯T¸åµ[O?_3Žýwp¨ ˜¯_õTûøeê\éç_îG£ 9O]è6<ÊIAŸÅØ[^ngm‚uÏÙÞ3ߊè<À`V¾|óÓÿ5ûŽíÂå‘úBÞÜu¼}±-¼ Àc”÷‹·ËÆsË¢±[ÍAêm_]1ôG™à_û|yóüÖºˆš×<‚< .”€bŽRUŽŒÔn5uTäù¨‘„©÷´=,?œùçVÄD(‰Ž-†½ÙAå<Æ@²½9:OûŸåÉ?¨SnqÀ;¹B½%O ‘1îð#\dLó?‚99@D,> ´ ?«Ýp Îð§;˜7M9~e(\y¯¹;,LÅ–?¾{ÀûBóĽcÅn…£AÌA_(šsx°;8¼o‰kHI»*SU)jH“µAF#qbÝÓÕ—kæ5›cºù ÏHçœÓ¨d3˜Åj(¢-4Ñ(…4U„©)¨§¦B!Øðƒ¯vþdÊ…ã— w—%Þå!àâjÑ× Ø)§!e•“Fsµ6ds¬Ýu˜s\غëªwRwy›¶ÞtNMÜâm&Á±¹#˜*/]Œ½”QòUJú”SI…Œd•Jª(š0)èÕsç•?ù'=+hŽ´ùÕCÔ?Pç=¸÷'?$úèYuå vIuM³?OC¤lÏl)Ó `Ùn¡IÛÕûƬײQ=ÄPÿn$5@€®ÿ/€QÈÌ}Bˆ6‹P’½oµ|;ùôw„êUFnÊ£8ßÇM~ö·»À„TX¨³Íľù[òxbôf·öuîàíÀñu “=Ó‡‚Ž$<òVþ FG2‚ˆ(f[ ‰Ññ ®è_#ͧM.¡÷§.8å0{ [ü.êµE›X+FìÐg¬×”øz/µ÷ì¸xÇ\ÙÖ£Õ»±½ÄÈtö·ðFƒfo’TªpÊÿ~{h&ØŒp;=ËZÂ÷=— x÷î>LüpÀpËWm BÁßžÔè‘¶V_ɺ¿à¸½s åêl7`­}=𘠉áï H,¤¦ÆcdÊ# ”¦Ó6Í•X¢ÁD“I’Sï>õôÛâøoÑý×yíö8K¿ä8¶Ï’HSÅ’ØBâBT4UMrª%pš@#{÷S ¥4›Ê,+(T$‡¸ VƒqL ݇}Ýç˜d˜P2®^ø÷#l-\´l¤ b„ÞKìBd„C¨ ªÒê%“‡lïp7­K ÔH ˤÒiÇ5úðçç7úÚo3mØEk|DS0‚»ÆÁßA]÷;­œÍàUüÌ;ßø;zø2šoðð³uB¡éç×eò… ;u±ü]_q¿òr³ýàݶݣôtŒ=¸öÿñ¿«¨îõ¯‡[[@0Àø€Ã`3k£" Õ$Øûl„`n\9 ÍäîÜà™*:Ý>Žr9'IDý’u5ŽÎŒ•²«ôb6ë`ÀgËö/˜ù WÛwE¯ïåMïý´<ãª}éëä>>mçøEÐX|«Ú^÷ÀÃ@Qܱ‹–ò„ËñujKv¯*M^¡^øAX¢ /P@¡Ooñ‘KÔš]&׌åÑB éÇ9¯or=År^K[Vn,¼ V4œ9|*Ñ£.CwËÊèpÃ5¦ +¾Š"’"ú¼DÍ«>¸g b+†žŽ£ºØj¿?.œtïîðŽŸÈÌZÇ÷2l6ð7ÐW}X‚¾jÒ¼à;õ¹ÕÃÉÒãÜäõ•fO(%[˜ìÚêXÝèÊözòëè·aÅö8+l Ç;P\™ßÍA_7(y9¸:²¼$7î£wb(™P”Kb>0&Ÿ– ÈAÑø2€ôîÀs‚¨R=<«Òãm^\Zþ?´Ç¿©6™é¸ÞžMåt/nŸq»€ŸCÕ@Ómùqò‚2ÖÉÚVg°ÃŸÃÖ5¨ëúooN½9nc—M·€M=Ð(Š" ¤ -­6Ò6§VéÉéíÍ1#ñ€U ˆ¤23˸ ˜A~)× ÇvÆ€òU(†ô…mÅA öËŽa«»Ø3Â^ÀÍÖG˜‚¼j7÷5§Wrl£A !¯<f\†c.vs¼ êEe]C&Ìä3(*–á§L¯»GÓÄ/›G·ßsÒ ·ä=IAÝÎKAƵˆ{`^t„Žáßãͳ!§ÒÇ5Eß@2K°¾6ÔWØÜûŠ£äÃ\oÊb‹Òµ#†}éï ¶´¦Zœ0db?ó ‰­>>A0èªS\Bnq†Pý7æýªHê¸q—WŽ€"& ©r=ô:Xˆº_tvã£Ln«°Þ‰!¬Nó2ui™8sÀk½sùàœû¸.ÞmëÜ÷Ó*Š„ô÷àzÖûøu ð^Ì2î\);•ΞLíß¶ë÷TfÞp ÑòzÆDìãÌÞ ébñ㳋k“€äåäØÔeæñÈíÂñïS¾ªG-úG†ûqŸ ‡~C@ÅWì“TîÇj6ôxûŽ]ÓÒêf»Ÿ¨Ò‚³+Ä¥ÓaqZmÅk‰·™#ìuÓLø@>Nëê„úú®š9!˜È±:øhœ@ ¥=$?›Õt˜d5”ϸ'Ÿ› DÖt3œt¿W—¯}_Fœë^òòIòÍ[ŸTQª¶ýP;H¦|ù÷Í£§“oVN»mñw -”¯þ‡8™W‰0á‘ïòÓ!“LzE wYð;ÅF˜ÐS±Ã†ëî¾iæò/nÃ율ãb¦ÛìDÕÓ$“‹¥+àµ!ÕP’@0Tž‚銧/}Q ‹—T¼èæ;àì ®ýŒ`ñu2œW95ölI«µŸvâGIdÞ8L WWëzøÔïÐîÀú|\Yu›]>_‹kožl©ÿ%Žº)Ì/ä3ZNîO vöŒ£¿Ó»åö Ü(> w Äøtûèwüü+GÞX‰(ˆ¼‘EÞÔÅnä¾Úa·WuÎ^aÄ=[ÞÀzÀ€w0?îGµ@°Ïãa¢û‚;òv¼:ù?C%`Ÿ³)I$RArg>Ü|ÎÜ‹çêøjýýŒɾlkÛ†J(9&]ɛȰ ·[q Ñ ŸŒÒËQ(£å³¾uàÔŒe° È,S{&N#ÊÖ%”›2¾û'Wìòª6U™£n§ë=+pk:í»é‡¡²\;òÊ'š)o¬»±œ|ÅÉ?¦òðÌ9(ÐdΤù{gמcÇXK Â‘¼ƒžQ["ïçè5«AÆùm@&ºŽñîöÇÀÏOEæz{5F!ÈYD04|uL'æYÑ'®{ÝnXð(¥><¼ÖÙ:+ ½…H•¹îÆô9•¡À×|µî‘Y=:‚H#Ž–4P,<;]C¨©|ÒVͰ5;n¿Òãq°é«1Ý«°Eü‡ zB«>Š-æÅ¨@‚¢‡dlO÷¯FÞ©fVüeãÇ û¦sŽ·ëÈRôJœñ·:°#{ݵù»:=áÛ-ðÜ.]» ƒ)Óè»jíxF}—ž£m&½0œ7;&WX^{Ýã².´Ûñ<ñË{g`Ëñâ·Oœë’¢€m÷¬MsìÂôßõ ²´~ô"«Èy6öiÙ}ù–®ž—Ï®»ý>”À4Šl;"×üOÄzÍ•qðí`:øö6„{3÷8ç7Ë  Á›¬Øýú¨ámšèGÊSQ¦HdÀ«UG©[ß…ùîÝ+Ù“´¯–kåøµÀG€#Ŷeonï‡îéýI€À\L{ÿª5¥=¢ãâ~Nš6†"œ6®#u.0« M¢Û«¡[³°`O¿õ¼Ô÷e™Q»¥<ä)øòË,ëg.YôòQŠ`ZgÍ_~VµZ†³ûD^”=8+ëN"{|ˆ2@î<´l£é•Éšñ袺€°¡ütŸ˜}Æ}‘ Ó>®¢ç"éŸG]ƒóvgj* £ÖJm¯Ž‚²Ç ¨þíËq‹ìí¿¨{‰æÑr]~·÷˜k_F˜äº7L¢C¢©"™õJ Bëy’òÆVd:¡Š,+ŽXm^õÐÔ|ýI¥7Så„M.èoÅññqîôZF·{ ÀV;øãTWä»»¸Öœmdð³Â[WV“oiqNggœVW!WgW¿¶ðr•‰à]g4^G1 `d‡D‰k´ÓµÏ‹Î‡ã¢€H¢c)7”²A@Ù²ð…½ý: ë•n=C^þT®`M¾hðÉÔñ`ÿš}GZ˜•ÉÙÅô.0Qq=¼CïT¦ Mð³pV´ßñÑ/G˜zwë…² 6¦-˜N‘¸iÊ´¤hwšî¥»3eœ•2³Ýà Q ˜RIFüÇ;M£xç„jxn¢ ‡’Äï\€éRG ³¶t2gGvv÷œ3mPÄu¶²ª||waÈ’7øß´£õ.ž)“Š”Í)ÐÇå‰$‘u ‹Õ5"à¨Õ„â F'Žü‚0 vš¼W“9hçW¯¥ë‡å6+4aã»ô9WÑœ;¨=#r²cÀ!`¸CÙÎ]ê8‚¸críR€nq†ÜTi˜Œr®ýr”AðB†esåÒ„ó}pŒ™GÅœ›T¢7˜}=õSÜ:>?z+^”wå´¸1—÷÷wUT[u6[P{ ±â>5âØÅyÖÝXÅÏpì»Ñ…ëá•„M…Aˆç’"pÑ-³…QÊëØ¤p®{@Û‘™×²ÖÃ&øónݧœ Úê4VtÅ0Y0rie|ê:c÷æž•òņ›Õ…67¤èòRÕϳE“Ë-ã}4¯Á>DòëØòxâFÅ·Ì Úø>úÒ©Êê~'‚Ÿ>襟ÞÓè"Ù<•4¢ÄzýήÐ,6-͈äẔN¢yŽã1¼z£å‹oã~L2÷\NÁ;'/Xä.á—_éà±äÚŠ®åzµÄ9r"s!0»Œ€>ÇGÛª&r‚0熱±@Jì©Ã ¯Ç”gäàþÿ¿Ž¼ˆ®›nn¡¨Òêϯš ¹»ÁgƒKju$#‘R;[»MÕ@p÷È>@;Ô0áËíßðè‡ Ƹîw'‚ÀÀ *,Ø`|éÃ2·u‡‘ )Ý€¼å_Á=zù£ÉˆÓ\¨c¶ˆ}[òjÜ~º“ÃØG°aŽsI}x/Ç+ Þ†è—¿§ˆn° ¢~FàGV´óAÒ u w§`a®ˆCŽ –3è~IQßxpNñMá‚(·ª¼Sˆ¯B;ñÀRFèãÊÊ xÙ‡N›·+¸T‡ f<ÞíÃC×ù.¥»¹t`;vn¹=ø <ïˆç*ƒ~ýâ¼…7÷yz4¿V:õhÉJ¡Ý^žczaGz¯x!íÊ\´Äu<9¹Ü Ô8°~*œ¹(©K2—P•ƒ÷øiÐãÏÏZl ‚:ãßÑiÉ.½Œ=ß*>:XÒp°NÎ݇D=xßv|ê0ˆâ̹lÛ‡MÅ;œ‡Óß×¹E|ÿB}ô¬‘åÇ+\ íU9µlÛ)A*ôU½:6ØÆ†Ûl…‘ˆ]î$ËOPò–Ï (]Ì=¡Ð—vù"[ï À‘.âΨ£/]!Ó9bÿSf¬TPÄ2;!¯F#¾Ýª›Ë”ª´ühÒÝîØ7ßBí'J5µÂU„/ w¯q2i*yÆ¡· ƒ(,/b:pn焌ì/=-ö%ô<@œui@¦@¾>ï‘Ò#¥ J‚\ ¶ää SÌN í3K¶Eä("|}êä¼õÞÙSQ¿5û$n8ò wåÝÖ,S\ÀO CqPÊÕÉv_s±¥°ùhøËͬ¨Âáã⣷«E}â2k2ƒ¦ìëy^ŒY(oÎ p”&-3KÑÖúâ:aß.»eB´q]ɱÖÞÏ·ãÊKM¶TÐc&ØÖ¸ 䪸}µ1aPP±AÛ˜~ïrNNp狸á« ÁU1 êÐwóQ»ÉI€›ú3QÀâc¤é OŒ¼5c›ˆïæq•ÐäâE±¨_É‹XI=ÆÝƒ« ê¥1 Ô7H‰\]ñ5§U°ÄŽÀzŽ}û…GrwY6 Ôþý8m¾írۜ۳_o_wœï -ÇšoÕpܪ$pÎÄ`¢·å=%EhvO­á…êèÞ8ù@:²+voôa¬mÔõgënÿÆý£Ž;zð}6ˆõJ²jvÂÆäƒØå‡› „ǸmÙŸËðï`ª5cV£&ƒjgæM°Ñ¸@éçss6«©3ŠAðŒHÜÕÙxãåÌye0S¥­qæO•¬Ü¦¼ÕDH§f©L+jo‹íQ…}ÆJZEö_·!rQÖS«qÐdè&çp=j:|à[×Âvž¢½¦õ¨`دÆÁA-¸Xçõ±ÎƒÐ8BJ0ü>íöûŸ Ø[¨ßW¦yL½; ­€é\1[)ÐøPb:ïM-("sޏíÒ¡éâ–î_ ý­AµÏO8ÎbÝc±|ÅxSÑ]…?¯ÝGùz´‡N6éWo-7õ®ß7/¬=]zv©ÆYóêyŒ M’9ùû|‡È(5;(QÁ·ö{J1àeÂMÛ{ˆã ŒÃæv¿JÚf8ôÓz'J©ëêÅmå£ó"¦%0eÙcÆr”r,û´p¬­&-^Z儎_™ï½oÏ5´±léfeu°|þŽ£†êWpµE×sл¥GNòú}>¯s·Ä{}æƒN]óÏÄÈQç±ÔKUøºûSÒ=ÊЧ0 T0dníÂ˲۶Bª† kü Øc?$=ø(Š‚H_,© ’F<Çk­D‚H((oµõ¼¾_0+A_úÝÛÁ4òˆ.=½û {:&l°ì³¹ç<±´†Ã‡kà2ø\Ô¯¯j…Êèž­”ÎgmxP5)C¥%~Ú*»¼û÷ÐðqõŠ·1:ˆ7Wðòw&­ÎáÈŠè‚R%4gfi·DDA3†<û9Û äÄf±Û¯L•u fj6Šk¿ö¦¦låe/bÕ¦|{ ñ‘HŠiõ±è}² üî»'²ËŒ‡ªQR€¨‡¬,BÑÕ,2Å ½º ü?8ñ½’[½Þ˜{kÄàc~A*Þ ±HŠ]Wb{ZÆÕò°ÅQ‹¿Õý.~¤SûÇÃè}ëž\þâ;ºï1ü¶ì ²TZ.û…AzªXœï›Ö°X±þ?"¨¼ê.y ÅPDÛûår0?Þ›éžIX(ýFÜwUxUn G‘•¬Ž#,{[£š¡¨á8B¨€ò£J1…ØY&-V¨h2ã·Ÿ?G…u ¯ÒügJ·ùv‰})KQt²§éïéåüsÊÜ—ù.¸ìN> ©â‹z¶ä¾\å[t­DÒp$ôRP0=„#K*Ž›¥BžÞØSKLÝ]zÉLmÚԫ꤂\Á­Õ–,9-ÙvÁOQ{>e§übž/‡'Ü»ðzçäæîë¸Ç'¶ì ²TZ.û…AzªXœï›Ö°X²¯/-ÑyÔ*\óAŠ ‰·Š¹>%r5ÑñŒ8 L§µ·Ö^@›ƒâʉÖG—ŽMÑÍPÔpœ! ¨€ò£J1G£ 4P •s#i݆="f€"'›=ü¼[°øìtzZ4Ñ—Žþž^SÊÜ—Å÷dåpðeHÁü^(÷ѬþJ ¸<;nªýð;H ˆtQê€ÈHÐ, »çøÀH“VÚW…yÁ¸Ã×ùVúþÉ_el//"\UíÚ/¼íq(‚}vþ½íÿd?|>ýÀÿÎ>Ì{¡û!ùcñÇëÇìÇåÐúñòGØ ?p=±ûÁír>üñû‘óGÛÞ–=àùCôÉ¢>Ì~è}!üóGÙâ¢?Ȧ?<<~üþ1ø#íÇéDôðNðë½Ê©ô^\š°]ĹY˜ÈËD©ÆW)*Ќў‚ˆ%!.%2èÖ K:U³3‹'==þÛ}¤Ñ‡/©·" í ¬úm¨)΀(f=VYAíâií·‹X$[§w*Z›‘¿ÓÏ<}¢ õWÚ ¯Ž‚¾ ð ¯" ŸkÍäìì†]Öù·o„åèåúýT¦¸áJ¶¾Œh0¼ñÃô}Êà¶g›ûŠñ›ƒ’ú©F‚Öí¦YI-zÌ®w½Ùò3"··=#×mÚôþ•Õä5ñ+»5¥ ¸mZ6fןF\LW\÷âðGöfÖV”QCÀ麜$nÎ÷nŒðjqÄcy Cùç…i&üÓŸCß^&ìõÂã>==]h"}´‚*!íWp)YìUqí½Çµé{om†]îöãÄ Ã¤»VÑ1jZk¤ÄZÏ"•µkPìÓAHŠ&dW«Å­kZÖdµ­k@ˆ†/KTÙfmZÖµ¬Òe©X ¸PˆÑW¶G¡-¤PVÖP°U˜LQå…&i¡¥+ZÙšÖµ©kV¯[Y$LRZÐÔëãçèîòxŽƒªg³ðvS»Õæ÷r[꾈Çm â3ò²Ä,œúé.®µechý’ë‹ÑÛÐIà j•e<›ÈkQ]ûÚMÌ5qƘkáÙÝÛß০”vï nˆˆ›UšÕ—j/×"MÊÞ÷¬Që&hD­.ÒÑFcreÚÔ¡¢4Úb!eýªÆ-e…šÖ^«[p1xzÙ]©p³&æŽ/h¥š”вO  D<ÿ›ÓèA¨&ú½À¨A a ƒ(µJ–Ù"KZZTQET[lÓVÙI%d’I+JÛV-j+Ebe¶‹TMRIiE¢eQI,’+h­*DVÖÛÕ~µ«mõäârŠ ©‚¼Ê;Žòy ˜X3ã6Yñ‡,À³C4Q ÂÃâ0† š4h¢>3EŒ³C,ÂÎŽß²Œ²Î hÂÎp²Š,:(è6QÃc0ÑgBØË4YÃD(,8pà 4tY ,Ø`Z:h{QÃF:0ô …8páÜZ:0Áš;(£ýIÇbÁžÇc 'FŽÄ8hÑ£ (¡˜aC(¡ˆY°²Î‹0Ç Tß áE”lÀàp¢ „!ãc::!Ãd8Pt0£F:#fŒ8lцC:FÚG 0Ù °Ð(ÉØÜɹÈ” ¯alÀh!°è³@•˜t.Ä8;”(G‚€ÃE ®a£agQ ‡`††#m£ è„aÄ@èÂÌ™>X 'rºÞœ ‚má¬xLm¯\rf•8Þ(kX‡ ×P´°µ¢Ö–›=i¬ÁYSJVÖ­­6 ,,5KRÖ°k^Öµ¢ÖµžÖKa`ȶ*iîCQÙžUZÌE«U™´Í«g" qU¬8 ‘i"f¶K ¤Ã­kW3F[UëE´ÉI›VÐŽÍjØÒÖ­­kM«ZŠŠÖµ"ÕªH†‘H­E ¨Q ÊŠ½-+5µ¥ÃUG”ëTõÈJ»Þ·•Íu7(îεÛUth‘z{Ö·­Å$­ˆ!Û º³‘pã "ö U¨ª¬Ù‹4„ÀLÕै¥JØÕ–¡of!Äš•…‹=®"“"–³ZÖ´¶0od‹Ý ´ºÞ‹ Ö)›a;š×~Ìlº³k7..«2i54aZL•Q!¬ZjÆ–£A)Xsf&öµÑÒÎõ—¥k *Ö›#Þ^Á¼B­éd¼@Ik Ò’¤?W[³•škx;£‹J¾çŽ9fº­g9˜¹æ@îW¸uTä)s§rÇ}^®9U‘ôïW*DÖ婬fêuŸ[wff« ÑY‹ØVJ¥¦¡Þé4˜¹£´À¬O…Áôv"Ê ee×F¢†-vnõ«®óEbé«:3o¹NQt…Õ¸s+œçn¥êJÅ%Tµ‡`íÔZ“eˆU‡ áMhò´´­•´‹T™±¥&†–˜¤‡zÚŸGÍóª|áDOõäVà*⢘ˆ+Å)CÒ(Š ¢È ˆ…Ad˜¯S·3콇ëÞ€ó$#*REƒFSâskljÛ)kmúJ»Ó¢i2éV‰!*°<ªUU¬Ÿe¶ÛÆÖ­wW^vç“‘"kÚÝÍ%3ÓkmÄõ»¼S»VTFK@•kgõå7T+æ~—êxùßõÿÛÙò¾ç]€ú_ŸZçæX R$Q¹:¯ÖÓ «óKF"Fâ Ý{̱MÒÇg#Áî”myàDŒ2›ÿI¢­mg5¢¯4-m6§ÿQJ‚¸2†( ±®a‚&heÆÑ8+¢tàÊÒ#ðd€×'$ˆ0‘‰G.c%Ø]›r±Ü¨ƒïmú^Vçdåñ¾7¨p4dâ€s/hî/J! $“ßK÷°ò÷¯ÄŒ‰I'Øs?ÙåáÜi&žÕ¶j#¸œß­N.¯IÉpYÉ ì¿‚LÛ™í¨··" Kº£Î÷,•°*NyÅjŸÕ_kp,-ÿGø²ð±_Tºm`¿ô‹ )‡"`ÃujŠ#^@ÉA ”0dõZjøQóñÍïŸÉd¿ dͯ‡éÜ} Ùým[!µ¤ÒØ×ìq³j*ji E6d¤~Ê?}ô óîö| ؈}8ˆ •b€¡dA6‘Šcì®–Ãè£ÎüÞ;U¯¹ŽW·µº~¼*›_%¸Z$4oÉWâÞœÒ `GWogÞé»­ä?#ãü-º*F[ü/EÀ_^Ÿáÿ×vóÃÆ€¿X°ÁÙù£goDÁˆ Ì#N9˜Æ Ø Hc¿=©ÊYűnÏŸ]Ï;ôÇÇíã_d1Ü·ëx<â2 Ñ<ŸªæªNtÉЈyœŒŒª‰xeç¨Þ‡êzÊË_¯ÛíOhv¬ï•->æâ†æ_O„dÜ{<ÙßcµÔ8YÞúdïáGG>}.]mÆY|îm‡(L¾R6´4ÛwÞ;_̤QMøç~º×òÎ ²ò|5¥€ß¿(µàIÈ´pGkDeUÀOø–Úˆ ZI ìÊÐ"'_ëßÃte Úüíèt¹€ÌÓ±~èá9q³‰HCC,‹>Ùß3<{ÔÒíò{ð4¼ P⢔ur–"š'aßüÏþ,6ÈõÐC±PŽÜ#| ¥ h‚&3ÊåÒsY.„êöø¿v‡‡ÃÉaÄ 5¦1>íƒ^ítÿ¥ø¥‰šª@ÖzêÆ¿éè»ÔöµgˆV·Ð†æñ/„[àÂ"Ö‡@<Åú>áù{ž\uò:ŸÛ»~5?¦þ‹Áúi–^#»ô a§ÁUsû¶kþ?«ü2†âÞÉ«oã(“N¡—¤÷–Ý Ãý¢Á‰½3Q¶0t_æ­©ZtpŽO™æ¾²}jê9þèÌî)÷ÇÓíkPš•DÏ‚½RÐq­úð?‹¿ø?U½Û ?çòQÅ÷Áw À^š†´êVé•wG ØÖSÉŒmÌšpˆ0Ò‰¯É·|¨øý€nø¾ ¨ÿd|Ìi¡ïÅø"fÞ‡ÁáÊäMáX.s3Š}?®cêP?›Ø»‚¾!ãÔSßÞsÛ½78òK Qéz_0Pò(ÍõW™|øWï† æo©œ6-7@q÷Fš8×å,g€)Q™®ƒÝQDȾÿ“eª)Už=… Îðˆö«‰!Øoî}Â7Ÿïï§@)™7nÅÔha9Æ¢Œ5¸ œCÝ»E:ÃÖø¥{}½;ôïÅ!¼#kH{šáUö¹ÕâPYº ’$áJ'åqsí„™{6rðò6xµS{É j *áG2¼¹ÀÝÀ”b~gÙñ1ø†ó“e¿d¹6¶ë‡¸å¶l$/ƒ¬±xápxgÌ7TËŠeäHÂã0p3ÃÁÁ³zà¡B =˜oà÷éX ÿ©8ùE'3’>E¬´Æ1D³ÉÍNiÉ‚·eh&; ¶:+·cpă‹€2WŸG»÷åû7×R š”aØÈ8S*†Ê#0<‘ÚÆ’D«oi14Fª fE@;ÈÖkiYϲ>„ÄC{óVözîÀ8@‰ÒûmùÏܱæã5š”Ë™„Ïí¯q¬C˜ÝÖ ÿ9˜*J®•\!…µ7—§D `ùuX|ºFÖWAT¹+:®(ùñðËÓËÛ;wfr©^¿Ò¡õ§×[0ù=k1‚>ßëwO}ÁymÒ´óÆÝÕÏäsoïw]#¦_çÔâˆû±ðõØG)§xßçrîØî;—ü}¯á˜õ~v¸?4n]šS éL€u¹û™ùUŽàÜÐö®gÑ"ÿUU:Ÿßæ:· µBí¶¯x]+§ï.m! ¡‡hÇÈÚYƒhs8ªÐ&Á„(ü‹°k±G»#¯–-/“ÚëO<ÔÛ_ªôÏÏÚ!Ö¥6ØØPF£?FAéÂO¡ƒ”½Ure\X:—Íú‡§¸ùǻζÄlº§Ì¾Ÿ/‡ {:õûŸ7ÞçüÏ‹m½¹‡Bþ÷»mtÙKt|îþ|‘†0^Ï­JýééÓpúýÝõ>|Ã×dÑ“0ˆÄ’UM ¶TXX È0î iª°6±'Çt7©š1abØß±ØŽë|Treh¬êZÖ/MýÅNq÷çÖø|ëãŸlÐÝóÆ:F]bÛwA{GCþÿà}:nú:³¶ï'Öð…»O‰LÁB}&QÜ`Æ AÕæqù†Xy7ÙlÞÚøûŠÖË¢¼Ü§›Î½MËÍ¿®‘ó=º5:W÷útù*¼¾2ƒ¶8öGÛ: ’{ ¾ž}¼>¿Ek?üž É×<þ?¤±ýçJÓ»…8y~A;Ç…2ín»Å5§Þ{z}ßVGãìò|£ìu¥÷~3×ßÜ—.OÚótTtø}.£Ýïñ¸ÄïéoÂ:|ÕÎp¯ƒÿNêóýq‡Á\UEq#Iñë>?³áú0ñ6vWv! è,"È„„ן†LoÛŠí?‡O…¾žðèã.îÿɨOsDÞ=Ï£x¶^QJ{¤ý¼ÿéÿgõ²drMη_”רÛq"™*kª–ðeÁÁuh Ì5_œa1[ígØrŒmÛµF†©±$ „©*T„DTÓ<%· ß'‹Ç?¹ÿ®"6ƒ›!wcæî§1Ün<ÙY®G‘àÀ‰ü °M“—ÆÀßl:§Ù๺2]ÉûÇØ#ÿ¿˜ ‡Úù>7`—gÿϹ>D¬Kõ>-~è'Lyî’dåT;Žz¹Pˆ·Mʪ¨8Ï}÷¼ñÿOûËÿaü%ó¸þ»öߢ8J'žùeI’2éíNŸ{ƒíô¬Ã0%xýI+qÇÚ§âŸärk ýJ÷kÕùãöç0À8޵v¨Ë5ø—·±Ö5\ËrÇZJ¶£E5-³RBÍhô½)Z0SZ<ÃrkLÍìÎÊ*ËT­Úi÷A@ÞÌk)bm;ê»"®pžnØÑRbr6Cüj$ý`D0)ä‡zi|T\HgwK¬bê…r([ƒÑ‘0¦Æ61¶ÆŸÃ!áÕÉbeÊaIü¥.•ˆø ¨¡¯Òþ×ñ+óÿKþÿõßsÿ'ëOç—ßtýO/ñ|ž>I¿#ÔTæx4k‚C192ä"H …>7ù¾øp/™ù±_ݪ~x•÷D7®º¸ô®Ä¾±w´E&s*³ ¯¹˜î† 95,âX@mFšb(Nm)ž Hêeš°SŠ­E±“G:{?}Æ¿HQ§¿kÒí´™VÉ~<5‡Òög6|“E¨Ÿßÿôü6ÿªÿ÷§Q¢gÏ$Ì'.”u÷yäëÿE§íÓ¸~Fž_·cÙ—’b÷{òîT¦c%ýj)šoUËý»\oíCO®rRØÁo17ÃÆŸÂúëDG…‚†­ÊªÜeFÐ=xjÊßÂ1µÐÄË”Á®™«Ž@o@dlmE—­2òò'Àeâk$«x7–mœý 1–Q\f" ^MŽ U–¢gfy]ô7B=Ræ‚c6$Dä¡E*±‡l‡g"\CÖûŸMoö×çÏ$:GWÜ7áêõ©ºŠ€(z`5‰õÊPIB¾ó{¾×lªø½è=&oÃßþ‡ñv îéøø¶÷Ü(ü2(%›Ü)ÏQÇÝù7_Ç6gÍ~j ýoý×òy/ÝAË’AUÖ¯:®¥¼¥¶¼j¹UÓj+•™©ÎJ"f§N(ÑE($–íÌŸ® K®Ÿ[X€§°Ù(L;¥3ë” ^âÇóÁ(ÛM£Õ¢ÓTé•NÀ»­u¢Â>¢4æB2’¢“®áþ=<µÛp–!mÞž&uEâêrwóbg–ÇÄÃ~ßd­¼û¸*)^"|ª©žõ-‚0Ǧ•;•&GòWƒÆŽ†¸~ퟬ¯^RÅË®PMƒNìÞ¨Û4¥ûhŸ¹ð8¶Ös¥h•U\ëWôú€ î=}οÛeóñÃÈœ¨8âáfMð€+·¡Ë¿/âiKæp ¡Gþ§%HÓÑzõûU)#Áx‘K}üÅßxôÎñ¸WŽR3!4ýfŽŽÛJôóÐa«þéFòb@óø|F'—JÁ%íM³Úå»h?gHËǬi?ÊáAŽmá¤ë™ZÆÃÕæ¦ÛíÁG¼?—†¸¶Þ¨åaú±uÈë¹Aâ¢G·Ç—Öý6Àta¦uKÒz‡@ó~&Né#·áïÊšq~ƒã·fꜗÇÙÛߺ“…YpÎ ŽÌME—f…Û£'É9:Øtƒ¸PïŠö•êKú§ÑDÐe -¶Œ‡fýÌ<|þ÷O2f‚ÙŽžZ‡:dö{Ҭ߮\P«'žk}h:€ßëä{DÑ ÀÛß2Ùo™ÃmÝ_=áóºbÏ—®oNš( ‚OƸ „"€ SäiôÛð ­lÖµ­kZM«ZÖ´­V¶6µ­òZÖ­­kZñkY”$¥•J9"Á­kE¥kJÕkXzÖ¯j½¥­cjV¶¥­k=­6²(`Æ1†ÉïëàŸ7Ÿ–Y÷ZÊj)Ì%AO¥ý5íÉ"IŒ`ûB2¤m£}åäXÐ6b¸FVyj¶S…[¦; ÍJ¤Òè¸ìÝÛ½ÿcÖõ]ÝK6ÉFŠ÷¯»¯W:ŠÑO;V噵%m‹GÔ\’>ÿ+Â’’‡·JåzÊ.P:Ngf@ø*(#Þ!|ŸÈÇáòû¡~*z<šu÷ðw‚=16ؘÄÚuŠ„ÊeþE`HÏŸ'ZÚ“Î(iëzH  (L¨Ç¶vÅ“Ntæ:Õ¬½ê™’I°=¾eëÖ¼yø½ ìá{ý²{4Q-“ævWs!á¼;u†5 _åô" ø>EtŽõ äì]‡Áî~HØòÜbQñ:6R×ßN­Ü’ן3ÄØŸ“Æê†çMNaIÕš$’™Ž5¥$:Ä@H@tÜO q‡œù‹ ƒ ó.n Ü €…0ó%3pop…tmPæÎ;)Aê%!!™Tc1*V™È&H Dh»«ÿïú=¼í$YŽ_,§#~Y(žR Æ@@ $Q…3Ý­4ì§>ƒõ!áÙ‚@ÔÆÑJ!Ñ‘3:´€ˆµÍdÚ‰rp¹r{tJQõ•íSó@¿7ûgqŽX86ý°¿ÀßæÜž´ Bw×òãÝÝÖg`ùX7»3?8hød4 0žQaç¦Ú‚a%_%AùF’9U£ ¾kLḮ¡Û¿ÆÕóµ§›.Í"^ŽÍ DB’æ"NcÌ8â<1¢Ygæ>ï¿ée®ªñoújyø~†Õ&Ãíÿ÷ó¿{ýÐøÐþ2V¾‡Á° O¶,‚²©Hÿ‘Q*?y_¥_h”èü“ü1Ãè;m.3‘ƵD -Áü¤ŠDP%çßÁ¯.ª{¹R„÷ËéX)š©¥h•SÖûÓç Ùņ¢ 4Uëìe){ôý_ŒüšÀ¢Š9–¤ÕÅ‘~Ýô|?aí¼ƒÉÞ3ÓjÔªÓ9¹æhK|bÓ:UbîÙ$úÑúäêxoãá²%é÷ט>PO«hšë—MŒÅ‰p6ëZÅ Rgêvñ©âŸ®ãàœuóµx2qé¾"%t³Tݵk”Ü ª£ð»vJÿª!\TÞ~ñÒN•²’NšÂ¢š¢ DÓA®£1±&ÞëÜ%C¹½6ìÞ5zu–ß~Ö½?k±aòµ]æ\—]”ÑdÍ6DÝÜùÍÒý®Qèªhz¯W^­‚³hâà– 'H2ñ5‚BTÛ0¶¨ö²‹+›8vož þ_ÑùÚ¾®î‘CðÞë˜÷rÜ`¾æo˜0Š©o°é8¯­÷õb3‘ã3– ƒå@‘„BEò~Aö÷yòÌD‡Dsù‡¹9ô`SE´QC•œÞig)IÄóƒò›(©RÃ_hIB›¤ißç¯×$Ÿp³ïÔQl=P*ñrËK]æ„Sµ"dVnE”¬¸4[’‹½Í1&5’bM¤ÚԈɎ±‰Kº¦š¸q ÌÊÉŽ]RF5ÕY¤V´£Ù+‡â’— fAT [¥‘p…›…£Í™¨.“g}›“*v¾gEuz6k‚mU:ÍkftÉ´ŸNr;4Ù›†ÕH­¡æ"·[m¤ØØÞôÔÊì ›Pí4]öšeY‚¦²ê(Ò/6Ÿ,ßGš£v(ƒ¸s«érääqœˆã…—2]És6íÄ À‡ Pm$TÖâ*1 #öÅc·˜ÓKŠÝ`5‹{ˆ"±t AJ ¬=¨… ˆ™æW‰ÕsÅ…SÝvíÝ_M(NÍŠ:‚‡r"(àÈB)‰ITyFë´vR£Õ>¹—E˜éÑÑxióŒ³]çd°»¥öú®µ ¨S¨ª©¾ÚU{í¬µ[‚trQ·{ð“b¨ªAEU$‚T©?ÙÀ`‘ sxÍpŒÈ›UÝM_7éºîuº½ŒlvÈ|¹Q‘L) PîÓcEc+E÷¾œðÍeæÊ*ñÊn»5Sv+ ´S5)ÕBœ’ê©(Jmª¿:{:ô®jû>Ë0ªº™‰Ð3ÈoÅi™ÝcEBè•ÊP»ý|–f®$T‘‰°S5ØÕó\ÎÍñ–a®‘(M¦À˜‰ÞpH<ïV÷%C·k›×cµY¶˜Óq“ƒìQTScLc\»<8.³Y*-i Q%ÅU ó2ùþêð ïøïȲ&O1’ç<·ÓN sr5Hdûs"ü@ U®¡Gcé»ñÿ‡‹Ù†tÕæ›Ö,ZQ$U[EOF!î´sâ' yB ùh çVÀˆ\**–@WŒA[Ái_JˆŸÝüŸÉð¯¥Ý¾,þXùå,Ô«Í ¬ÔÊÖ]ž•ÄBÄQmgxІuVjXZm2Ñ6™áeìÏ3jÒ‘jRÑj=˜ZÖ2U¦•¥‚†X8͉Z„¸ ZTUéz!€›-k[Ñ!Yš±‹Rµ «báTZ‹ ÍQékZÖµ…75Õ¶ŒÉ“cccó¶»í¶ÎÎÁ°jåÜ,èáÅfŠ,Ƭ½:K ÃFT¬¥…*Z –pÑÑ|\,°ÃF,8bº+K‡@RÂÕK%­kZÖµ­kZÕIIµkZ£„W@€©SctɃ¡”Îî›;m¾á»»»¡fÊmi±²mŒ4l›ºä×rˆlldØØÆ³«{ìó„0²Ë‡GGGGFÍlÙ*Ñ£…lË£GEÑÑÁYDŠ—+¥½ís®bÅhÅЬèVtpà¹|Tp(¥fÖÍ›+KA¢Y²Ô†Ë 8]š8h†  Ò8Q£FŽÚCC,0ÚØÌ6i3f°ÅÖºæ´hÐÔSAG ,0ÑG gF•ëKG ØhK¡ˆfÊ8pÙ…–hÂŽŒƒR]m‘£g,¥j¸p³ŽÂ:èé‡扦L˜Ã°å ]4Úlì›»»¾öµ­aakd² !È,–Ad°°µl-kZÖµºë¤u´°¢Î!Ñ d[ :8XY¢%… Q¡‘‚(£ 0è¢ ¢pgFŠ4tlKAE$¨ £fÍ–+4ÑAѳ„8X‹,]((££¡#‰"ÌFóD! ÑÐk{6­š::Z­Q³c5gECFlà3¢$pÙ­u¬2‹¢”65a‡B¢Š8YµÐpèÙÑÑŽ‹,£œ6]–l†ö5!ª;:ë®ælØ55›˜Ss!±{jn:Ñe…¢†Í,Ätf“kZÖµ­kZÉk%­kZÖµ­d€"€0,ÂÑeœ6p††P¶hÒ G6µ­ó¥×K®º:64ƒ³ Â àtlàÍd³`ÝrdÎpnlQ°ç`Ðæ ¯Æ »å¶Õ^WÉ)))))))))))))))))0fs áÜ;Ç€áÐpè8t3 àÁŒÐpè8t3 àÁƒ‡AÁƒ3 àÆÛÐXÁ˜0d@„@„@…ý€ÎwêuïzU¹‡qS¨Á‹7@ånÜ{Gäâ—ã~:÷M¶¶8‡M“˦aJ÷ì^7ÑK#¶Eq­qÌo`&“¤Öø–Í¢®»†×r2œëQ: ÈUP&Ï ±j“ l›¢û†á­áµü¶l@áèA¼$æ€"&áÕϧ¯½»;;ƒ»w‡žõ6´ÄV“ @\ ƒj¨¬€È¶(æ‹aY¸É…õ~°üè¯DâäïnQ]Þ3¡n~G©ŸÔzŠF"Á8ÔêýìÆ:§ýM¦Ûã2Z屢£ŒÍüCœUד{(+îG¿A_áôT:Ï™€x7í2Á ´A¥w~AæÆBôåÐe‘*FP‰7îîHR¾÷îüósra Uƒh‚¾R Ø´&ú ý³l¿¥p ÆÈ] ÕåT¸éÖå×`çSÇÆãnƒ“Àä]³üŸæ@V‡ÜÒ¡DPX‚¿…êil|/uB Øô(Íœ“Ê=_^½/Ú1LðÌÅQ^®CÝú|ç®0@QƵõ¶A_ÌüËÐÎûì æúÿ=hož£GfÝǤ3o1¶­ïÆpìï_ñ±ACœ`V " ‚À -;¤S(@¥ùòX ·‚s{ŽÕM2ÎëõŒþªo<¼÷žNíWsU-UãKªëªê<‚P¹S‚Ç›E]Ö–¨zšÔBAÿ‹²úßÔHÃ÷ÏùçMyˆDr)úôRž¬ó·FM¦ŸÌøUñýèª"ÂV)˜`‚¤ÀÀõ_~þ6•N©Ï‰ßì´Oà53uôhÀúˆ¿œA1uù18mÙ©¦•\+MyÕͶ×+êFõ«Ã…˜lÑEQÑ£C,Ùe”t*8B:nµ®®ß WU¾Q¶ú]s|5ºYÕˆ£I2ìjÑêL˳©–0ÓZ­‰iZÊ‹–1/ø¿ƒ¯A€ªA?ÂÅðtp!¾ Î!þÝ-y´_4ÕT0–=ÜÍ… Ì’E‰"QT´&n¨Ø²¤ŸEæóI,mcceMI…£IlU–FÅ­ò7&’×ÇÚãdÅ‹œfMŒ4 aýT;Ⱦu¨.ßG²ëuÙöc/…0|Ô’#"HÂI@¸=ÞîŽÜ/¿0ÂÛÇZæÕñªgT»6îÒåtëånø]¶Þža­ESJelkcP´ÀÞ;ÙÃsrù[x¼Þ³·äxäDxN1Œjæƒ.(êœùþôs­æøÎsVyÌaã œ«S\Ã×úÁ—Œ´ÓŽnH²$+OaߎDzõ+Â9å¨x2lP©èT¸FC…â¡l‚…_ 8X—ÃfΓàgFË,ÐiX±-†Î 7†ÎŠ :ZΑ°¤o8te3 0/­r¹?g\*댴!$NÝ#z‡b!ÚuÓ¬æ×KP¾ˆtPÎê’Uï÷%î}Å[jüÆûæ³£_«÷I± )LšoÀq‰i‡Üîí£hwïÞÛ⥵±µ_59 ”PˆHýz*ÄBÛ4þïÿ_ø~ŽæOÆ%ßå¿-x=QÜ“Õ^ÛFÊ,XLFÐ âžÂ(B0AQdA†ºÊߘY…”¨¼á¦D(`Zà¶oå£fÃ"†¶rè-kc,adPÐ-3wqL8iPRÙF›E±qÒtȘÅÛ›Õïd·¸É¸‚¡ftlØ[42ÜÆÓi–êæ° ËÑDÉ]tq^‹E¡tpÍ7§†6>š[ÿØÎleNWn 0º"¡hèaF fAjÈ ¾Ò×î7¬$!{¢ˆ¬àÅÛFê ÐÓÆÛcA>n uzŒ}·ƒ | …†Á˜‘C`2ò¯­C±Ñ£|åré¼·K-4E$g—Ø{ݺîëÍñU\sA¦”ñuAƒ/íHg ¾Œš„:?“ú[?ð†ØõòõRj•7ëIÖzÉ&Oñnä!2öýŸy™(HÐdÆ 'içR爎ÿŒþ%©Ñîîõþä3+•Ã4ÉÑÈͼu¿4,óÝß°Ó¿ý比Mó §‚‹«´P¤ÀrUKZò®ö¿?ÔøO,îI¦>št<zo¦‹ñvd/ ¥--õ…H2ýŸìõÁ³Èt†¿Ì/àÏáj\¿ÔXlØÕ­Zˆ À¨Í+¾Q Ø{g´{Ññ|6‚¢®{íkgëÂñ@ùÀÄ¡BI)‘ C@Œ úƒ¸йþ^`ýÕ%ÀÉDOó¡møríõòw…üD=påªÈ:½ë¨y£ ,PáØÙÑÀ²Œ8p¢È1˜pØ@Ù`Ë ,,VhàtLÜꬾU¦‚Ï[U©HJÊ­dHšA£¬Í¢Ê¬*0Ø+s. Øß3RQŠwv×M%mµÃOÎ?õ:࢈Ælõf²YTÅH@>§ª’2Im «m^$ÕŸ3ùùšú˜Š³øV¯7e(D\ÐoÌ}™Ø Á™Ôí')¿M¦¯/˜ gã›i­Ô*T¯¢Ëà*„Qp¢#‚l‰‘³Ýb/쟎¾Ÿl;óÉàî£xÛîº š¥DÍkZêþd€Á0P¨ KŽãd’ ú}tZLŠŒl¥")„z¤zM»·^ÕtÖMU?È¿QÓ®.€Î$ (£E›Þ­ç!uôЇ¬ô_PÖkÈ{ý'7ãûL÷f7Ï}Ï-µö<§Kmp¼:M±àçÎHŠv·Ý5E¹t»®ØÕʂ۳[  ‚³M¨4Å/çó§s…W?¬s£.ožùœ0áñ,-Ûmœ™L¸M‹lÐÜ÷ÝÍÃ&a‡JŽàQ†…Ò¼fãG…‚á°â-œ0ÙÒäè޹®+ !@°ì">[´ k²‡re™‚ŠTa#Ѹ c®‡W}m¦ÌÒ"«Û/^ßÅþ[u…Ú±¢®aàƒ†:5Ð"l7ÜP…ß]2î1Àìèè…)8DQ]Ä |+µ«F UPJÀî |‚"ÔZ;D@×ôg5±š4.ëµ ð2ˆ‡Cd0 n×vÛ·œ¿¥Ø9u§ëæªk±Ãž|ûº ™ÛpÛÇ'N'ÃÇy¾‘»ÓÖéßåÌ]¶/šŠ¸zŸØ—©êÒ3¼šÁPNðùl%ƒc pTƒñ²]¬d Œ^øQâÀ÷1ãê£:#I{a± mèùGí×ÑÌ5ǤèäSDçNŒg°8 éÉ_JGgV×ãËvÈ â9 Æ"Ù éËÊpÜêÇÎFBƨ5œ–0!F,Bˆ e1ñ†‚aSKƒlÛ-RÓ¤È@禯&‹°ØÆH££ÔvîÈI$Pb¦":‘OœAN”0ÞÃJÕ†HÝ]Æb^ïwµíMzéMfhÊbJ?®ºèôA(|Ûúh4]=r9«×†ûxxïåÅ`³¾”™ˆi¥xR!úy (0€0]CÀ驼ç)—YäqòÔ0¹4Ž•f”i1­"64Ê¢0‘ ÕÆòÌ¥lm°£© ìoX´Á%ƒZ0¦©!ã2¦DP `ØŠTD*iSDuæ/n†46Šñà (‘B6ïσ!©«Bøù=Çc@NÏ”ôsBn@˜c5ãaˆpN,Šäi/˧Ó8ŒG¨w0Zïï÷è(|D;23{ÃA„„»;DÃAJó‡N°hÐèvàÖ¬ÆÂà=·ÂX¨†Ý‡šðØlÉêÕò¬ß>há5 xù¹xyêDG©¿)á‚nö½YásÀ>Œ< Æ8ák‚bp¨€y ó´½CÞ~‘c3]{ kß½ÒÛ2B¢u²Ë[òÃaÅŒ%UFo çmœÀ<ÑOH*ù¶Û;ØãDˆšñ3n`œvãzàÓX.¤H¹É¶tÑ¢1NgŸ!îõuÛ^måEƒqžú7¸wìL¤„¾ê»Òk†…EóË: g·‘ËÆp‘Ó\ï ówÙ?#áÊôEòDBHØÅŒ…¸†q¨ï£¿G(]4>#U¯]˜o ІôË)—¿f˜ÓË¢…«Dæ Æ4÷ !î&!$&¨B”‡nžqäì×Ñ˹NMÙW£œ%F`¨†RØ?@l¢H5Á<ñN¶°GÍ|GI–Àc! ´PÁ3ÖöPX™pÕQ2\(¡164Á… ø0²Åc;ÅLö‘bxBÎ5Ï{Ö9*Ï«„Wðùu>EÞ`NXÔŽCaˆÝѬ³¯ 6Å &#6¶¤ ®B¹d“}‹HÆbÈI^óÂÉ˜Âæ(J0`PRÕ…ƒ¡…ÛÎò”Ô¯%ÒÉ ¹n—xº´;èÆJ0KjÉÄ|ûú âëÛºj鹕ºz+§@L ¯(¡CŒ „ ÄBê7ÂX“Lb*ŠEìºAcL+%VªS5jÊÆÛ`ÆUª‡TE ¦Õ@E *ˆ-åa^\7AQQ€(È7Û~:ðÈõ{š×JqÝÇ¡Uø åêöÛßç¹r[/Œ·Z] {¹Ýtd¬ØgßoU«»íÌo'¨Ê³b*wÿÊÑ\¥ÛœÞ(„€j–‚ŒF.ìD*oðX²©l;ÙßFI&÷Cãuv²Nêv $L-<Ìv«Ÿ™ûï?Öæè]“æ`Ó-+ÚŽ‚8ó cŽ#€!ƒT ÁÞ†>9˜þ_•ü‡ò{>£ë?mÙÇ™”{ßÎô¸µO¸‹øÊ¥*¹õ Ðô{Jæ0Àô‘( , ØýãörÓÿŸÜÿõþ%óÃÇsë¹pÖ¬·†[x¼#. ðz¹zÞWädI'>ÉwÜúÆ€)C?S0÷:×Òù¿×Ð_L‰°eÅì( ·b„ò#ÈW!WÜ íaîWê†\Z-U¶V•“sjÞ´­A$àŠŠŠ€À‹ ( À„‘E…EjÔ/kJÕÅi4¥‘ëX¸xiuxw—›K µ¥–Œ²Ô ´­\FKeµ]uÙrÝóôô9^kå óƒ¶Qq8-As×”ž—fŽ(!qæÐTÍ(òKÂùY¥wTs%Ù ~ÕÍylk»¥c©/$éß®tõæÃX*mÄ mÀmÂ@âPrѹ€Þ ¯‘<æü90¥p#È@.£Éq`Âûö•fõU¹óÕ• òQÇlŽ1¦È1tÄñ?½_ЍiSêåß5¿é¾¶µ¯lç'8¿ßü-õ{£’¤leĉk±åz:3DƳ#>3pµ('zý™ÜqQѪ×#q‘C‡ÇE±MŽKÓíôh; "#xL¶üð7SŲA ž^©vD¸)¾‚Ì¿o ¾y¡Í=^ûë9ù ʇWnüA,Šû ñà Ê€¤ ¬ò…ÕÄ+– Õè…¿ ì¨êêîñð÷)·Eva·E^J ¦G$Cc¡"2Ú16­„M¶‡LQŒhñ?;?·ñO±p«ûµ?Q(¿²\F±ttW :ØÈ°¢Î,(£a³¢Ž) Vƒ«\æÓ6tŽ’†Íœ °4pí³FÊ9¥‚£GnehÄae𣃘 6 CÞö/áëùœºªm¹Ÿw¿¼G #£+.n÷ØHèÕ³Ä"Úá.ƒppC€â÷üLßÄ}Æ|lmîf8­]š›lhäAX@ÕÔ(l¸Gïá‹9bcVØACB¦­5l…ƒUAF{®¹ *¨ZªG‡/ø4Våïw×>t ;ƒíCÏËš­¹“äà‹àt{…¼ETsô»cÀÂ&ØÆÉ0tê¸` ÄRRÇ(A”Ç!I Š ø4¨AWòJ,Zgä¸ÓcjÓ Œmº-Ð\e` n©¡¨PMŒ´žžT§š+Ç>^Ÿµ-¼^;ËðššÜå3åÏÏæä<5†æQ„;Ã&>:$Ê–A´ „¡±iiÑL2qÚ½Òê¼ê^\–“LSá/+Ñ Cݪ_XÞ™AVEî{÷FðÝ‘rwA V›±Ó; a°)q˜"¡…ËOS¸Ê«)%J©ŽÊÿ˜`¾þ]#§JâÕŠÐî‰ ާ¶½mÌùòÙ ™ÖÈYzðg gwæ‚6¸£ ‰ TVçCGOOvt! –5eƒÖDñDŠTY„+$EƒìPÑë—%†°Rà­ºÐ) ´ˆÐ„!Ýy`^0€À¯g‡ÍîçTíÈì®]<-½…Â%ÇQFåVjƒÝ’upè1jà2 ÈG˜kâ¾;Ï©ðz÷ܯ$L’‹2¯TP•ŒJ 11 ‰y²‹,.êÏ£*áÁ@–†a5† ð²Õ(pR¦O—ϧ+' È/]µP6@̦ˆ‹MÉE€Í3ÒÜ;"z醇Gl)¤!æqœË‚‚@ßFDa FcDº”Vkh†E’E.Ç¡òÛCm£á#¢~¿?zGaôÈ?4 dÎHQs |¡í…ÔPa Úâ°H%ï[†k|“Ý*JJùšóy\/…Ï0 MC@k/Ñ®y@  ½ÀV@NùCmTã(;µg­’“I  dN°ÁTg\F{³ÝÈîŸ'¾ ³úº»£ì}3O§ÙåÊòÞßµÓ#‡ªÅHÍW»Ryj}gðb?KÔ¯äxþtÄdíY·2ƒˆ„Œ$cNµÿù°ñI$ØôqëxáÓÛ÷<¶#oÑê톦iòG¤¿k©àoøÜÚáÈÕïÍç.}#A¾oœÝïãå[¹8¯8<ƒdïj‹®'ü@nŒPÒHÆHZT'ôCëþ'àfõŸS÷}Ÿì~§ýµö|žõ?î…ù?´×ãï_”ìbHP@EDü%à‡W#ðBÇ᣻´K±ú_Ñù8xÞ9HëoQäuµìö¯_d÷˜õç—t‹šb9=.Ý›µh?ÈöüÙ¸ Ãó~RŽ£ 7g`ˆ±áPÙV"ÝæªEj>%SOäúÄÛ_Môå~û1<“·kÝV¨¬æfßÔ©ÈPã£D!ÃE˜lá¢Í°Ñ£e£EŒë54Í´´³E !jõˆ²‚’æP½\4xPó+ ZliSX[%CH–´ 6j#KH«Ö^*´5lCU´jŠ’BjÍe>/2–×á×A“m¨Ž»·òæ!ø›™éµjp?9{á÷ÖÚýŒ;Eýé~ñ•ô×­c¨ Z¸ Óa÷é‚"H È5n\¹µ_(Ã}ªÿ]…¨©ÀÎm_ðh=9 ‚¡)û‚0)ÈÎ;c>À:FâB©÷ªGHp‚˜¤"bb!P¬ºMƒ`Rhr¤©ó|¿,úÓ_?|gÌÑ…2öe šT¢ü‚†ü‹:6hÍgD(á£Yˆàk­š4hÀ„(å–^làthá£T,¾²é@ (À²€ ZÙ@š…N_µ"ÖAIÉ3ûldæ14ɰEj^›)w>±‡Ò4taõ¿f鋦 OYKNXÈS ýÖ8Gkâ÷—êr;ŒœLãbÏ-7ðö÷_2:‡JÄûã ¨s*è(8CŽbùòÙoxä+Ê+\j®aÆ|¹î=Û}×^ê_'Ë…(ýÒ¨E[§p„e§ÂH ’AB3ˆÛl.AÞíî($XXC3@r8죾–y6ó‹gÁ‘”Ï•›È ²&Â1›æ¬„dšÃ[“ð#dáË'[7Cºî{Üka£¢ŽzÃL«Â=U’› hmË,¦z’4Üc`1‡¾ÔõhøªÇRSv”ΚH±M¥ÐU*wÖ6H¨sa ¢LöÀ´ƒl.¡cQ„.d jµ@¨ðu¿Ów~¤ô¨2ÆweBÊÝ×ãñ,ìQÜt·æ#}@(bj AƦ1§p»xˆöÂvÝWˆC„¬;3§€ÃA¨¸¨# }¢˜ªb‹TÈ"P5ìQ[ÙN½Ž™K¼D$%ÚTI\=<ó¸°;ˆÙ5níy =ǸÊ8pñæÃ¨x)iD¡ªÙE•ÉÆ63\îW0ëw°¸ÌT8 38¥ j(Ô˜TëEˆ0À†™å®¤=;ÂËdÃÛ $.¬¢.3\¶Ó¶b™žïÇî߯ßòÒ‹Öío̿瞰ýÝ ¯Óÿ³ôÿ»Ùû¾±Ìàì²¥/TÛŠv`„ˆF%ó¡NTß ­c¥ü_›}«³ú],¼ÞãEyo äê0’«û¿‰ìý¯°ÿÃô¾7ù¾&ß?'Òç÷÷ò‡еª¥¡)‹I*²²òùéÓïéüÿ×õ¨½Ãëé‹|Ã?(P)TôŠb¸ÿ7Z' ðߟIÊÕú•«k%ÃëQlxQ°Ì‘«³Ù^Ç÷hX!»PÍWßnçÉ:Ô¼ÃèÔ‘UÚk5v„°°p¡„0¨°£ì…6XÆaÑgchgŠ:,Ù±td !ؠΨíw ôõ$f®ò¹»³D¨Usí…)w³¥’·y*Ê׫–´Eµ¡ÃÔ—Iª[ø>®€¨§~ð¡ÏÂúúäDè$PHpû`ì€jýòhÐQ.²rV5Ä—Ë-Ü·36˜ëðpåyÒ‡‡L肵ÞN„/ÍÝÔ5‡«ÇÅΨ+ãÎÞ©xÑÚ^-âðFÛ››^8³^qr‹»Es畹^šç½¹¨èâ+ÀDôyÍDr  X@°{$ï±¹¦êgbÍF Š65`‰“W&+È,ÑÑTk]-á£F†lÞ’9FŒ4há®Ýˆb í¦3 Gf“;À(UqöÙlmñ‚Ii4%gyÖï¿Ðp²ìzEw>_(ðy'Ňugi‚=°tdA}êÓU1R¿óóù;³¿^§¦pègc±Ð¬«z—4™è0³ý?6!효ÏB®éYû±l£ (šŠU°¤Rg§~27ßÐì³Í˜h•Û —…öE3É¢-îA”B<{îŠ;UªR‘X_oìzî6rôÍ‹Æ8ê3Eˆ´«¡WR*ð7 žEÑëí¥WæÍH,*ˆpjÆIeݱ¢síëÕשϹ6(Ü£A°Àqç!©cÅJ‚ׯ¦f³c(ïш'cБ a'¯EŒÛÂ… îeBÜ<}]•á?o³Ð7~Í Ž‹Az”©É¢ï¨j"ÎæËø¡/>qÇ ²ê‚ÂSÐ$ƒYzôª”v8¨r€§(†ê+ý¶Kž91ÁQw •ÒC2ªXòV$¤ ¬!€]ܸ8USt#`ˆÛëA¼3¢0=´f͈¡ÎxCŸN®á:u£„p-]¹"jæ†ô³Jª Øg¤Ê PCt ÒŠT[~.Á°.@8Äe Åcƒçoì³Îü±ZìhìPPÔí2ñBS²‡äî’öø©ßΟ0›;œ0ÀÙµQÚÁ„•à²Ù@ØÜ‚Ê€BQÒ²MrÃ&‹­³û½cŒ|¹Þr[xvÿM¹²O®ys9¼Ç—ãÁæÅBýÉÙLG5Vh/*a¿8õøH§üŸß~§ú¯ñü?o®#ìê€WÂðTFKÊ)j%(¯oTa È@ì ñ8û~Ú¤ )96ç™ø3+2²õ¬­v*·²Uoä깜[ 8h£…  ÃfÊ0Æ‹,賂4@ØAE:ÌÈtµDÖ"Æj*,!YÚfˆLÌB¬=„W4¤Ú•“DqYZR¯Ai­aâ"’%„ ؼ¼Ò2V=_! ä5BØÐx=íZ&ï…º7ŒžNºï\0±*@Ŷ£Æ7ðZn}"Ϻs(êÑÅ@Ù4‰@æ…>¥åzëÊÞ¹ÜqÕÍ‹7®×j‰(¼î6áâ¸[Źuyp†ÎnõÕä¼tŒWqÝwmÉ+é·T °Œ‘9å ôŃމ!“k¥Ê:<‹#Ó…¬Ì1QFÚÞhѤFvС#f,0Ýt‹Øu¢C£aeš8Z[†ÊËào¤.Ì`}{kßÍTÑß¾WîP *Ó4v7[¨v0Ñ w^Ij¡óÂP } Ý*»P2 aO6ʯ·«–gº{5 4¤×`² õî‹dšÂΖ+¢¨HÈyJH¤ñ¾¼¶uzºñíäó4†R6Yãàú±²Bˆr¼úš<ŒIY¾F¹¥M‰øƒ¢ ˆÈE)(µ]¶a\:®ÙmÂŒ63ÀÕ²k=(ihtp †NS Ó 9÷uë”™!n¸Ý‡<€.PðD´c1°,9(ÒænTLwºh`êMÎNaÅz2\]ºê¼(ã&„Uk×,±O’eM …×6áÒx ®b ôÕ³§jºÚñ®—´5j¹6 ê[ðêJCÔ ‰óf¼WL]çj®ýoņ-+³«4õÝÉäTÆM¸ ò§n¤f¨´ÒVWÏéC+©¦ÎÁ´èèá®QÙv4›î×£%Å_·lS'©RêÈ™îQ'=–è§~yâÏ%‡(L<i‡nÖ¬ú\]zä3˜µ¥Ök. ÅÆ(^kÖt˜YØäô§êRˆ¦¸Ê¦÷ÇÛpùô|ÏÇ1“ËײðET¹¬ ‚£––èt#Ó&JÉœ;"qêoNŽ6ü1µž8ûÿÈþg£Ç†ðÇÏæ,]¡ÜB«:À1©ô(£ ÿ}üÿÖàû/ù”’¯¾Úw*‰ g›gäDW—iÀ gGBƒEÌhªç/g+4…çÞVZÐíã,á„,£‚‡ (èè0Ù %D@‰CZ³RÊ-ZšÙ˜†£M¨ik*ÑÖ^(°Ð–°‰ŠÅ­I.Á–“J¸P-è³i†+^ @,=¸?‡¹¦!>c/— Ÿ<•u³›æš ›Ö½9ý§qyûO^D$Aª¦NûIKlnàE׉4ë¹¶Ýmx*4bŠ (ˆÌ-¿ƒ®ì×C¦âÑZ‰5hÅCÐ@U4¬­^~ ]Žv7J»5Kjè‡\[KgÂf–qá¢Ë(³péqpÃtºèá¡‚J¤‘`• ¨°€%³ŠäÛê°6‘Øgs;G)øª«£É-6Z05õÃNä–IŸˆ‡ÞÔÝ[_œTTÚgZŠË†™¤Íóš–JJ**8°„$ÇgPM¢¨$ÞH.w:Þüáà¬0®÷g^!ëz‰hém)m†>áƒrÝ¡½j¨¨o7­è£ ™–h”ùÖe0ßX4u†ÙØ(ôÏ4Ȭï¥÷ßDó–ÇçžL#ƶÊêw‡Gƒ 0¡Ÿ>yé:Û§¥£ÛÏ‚ìa­J– ¿>{yìïžãGFÄpô¾p˳žÏO+:£e0æ‘ Ñ·æì`2ÈEÑå£èdç[ôìHí‘ ã¼K Sñ W[}$—ðá~½çæŸ9]+$‹}­ÑÖֽѵíÉ"ÁÁ‹šá9ƒYÅùuEÅw-6F¾7öm)Wöº_x5Þ™»“=²óÆiã£JÅ"- ì¶@TTH°P• aчC!¡šQÐ]îsEQZ9Ècß]C9Âä:›½éÝ+®eMš³' \.Ã{i˜QE—i<=@ û~¬ãø;óÛm™¾osSÔ4@œB@Þ%@<·Ç— ç•çË] 4«q€E''(¡D£Š†XºK øE…R¢kP.– °° Úd³W°²‚¡4Š;,ÑE.—Ep\4p³A„0£AÆAik`3£›ëaEœàp€#a£`©4g\Öº¾º,ud(¯‹ÛO®lÑ…œCˆðÓLø‘ À1„2õ¯¾ìÑ!¦Fex;&QÄuø‡¾çj-ªºd* Ä*”mÆÀ¢7¬»´>ß•ü½_–™À†ˆ7~*óÈ3Ø4y=:<šªhàGÛB…Χ‰Ü¡²¯už5^¾1hÀìPh!â‘kðù»X>þ‘Pœ/®½ âÈa³Ð–º¯úUëɬMŽáâQEa$  ƒÍ›ï¥j„f@ªÕ§9Æ©œYÆ!XW–Pa GìÊ$$xÏ›ËÞLÖ ç^†ÑG¥˜Y<çK°ÁXÛ‚¬ÃÓwZç’6ÕG&BD „¾ BA(øM¨¡ÓvoxVšläÔgs#ƒÅ»a$`G<;hÂΞջ:É­1áÂVºZŠ”qF‘Ä( ‹Ï©+Y¶6X|A~ïë?ûŸå\™wâxãýWý®¶Á±ÝCC½Ç^š‚‰ŸýÉ/Ï&Ãùîݦ}ÇEƒU‰ïÀ4®z‹‚8Œ ¼0{Yø~ìUyjšüÈU†R?üX­Âxæøò®“û}÷ZækŒåáI l³G 6@³£f ÂŒ:0 QÑaG †Ê(£GC8h¡‘ k5¹\(ÕÖ³YÅ“9ѳ:åCy¸YŽõ»:Ðú}s©U…´ºç9B¥ÌÖ§#ù_²¿OÍíA‰¡£—lnÎîÿµ¦À€ 3–´VÔ:éC!õ¥CµEEC0a DQ`,,û6h3–uú=aˆá¢Åe ;Ž’Â‘Òì 7¤²p6D‘ÑÂÍ­Y ª¥fCd Œ€8f˜íé®ýûÎÁ±öª=8hàyÙк7e¦2y…#à ;6¡C76ûèšÕu>-CÁ0áè8m%Ë‚¡£Â ïvß_ç»VÆvQ•áø&Ÿ<2ʰÑÜáåúp¯² aÊ®¼v,ð6o†1Ã]kY;Mò†S(t"qƒˆ¶dýgì¦üøê‚øñJt2C‚aq'0!ˆÀ„‚qv± L†ö®`¸¸Ý5eú¿eþ<®C9CGíúxÁ£áèCJ"fŃ(dL÷²Àe¨Aƒ"Á4ÅE~[Tݶñ0¤x(§”o.¼•ÕæL¼D¼B.’Jó¦[®ÞÍåyv]JíÓL…‚¡R)¸ Ó˜ÖP+ VB*aAAIµ·ø&&* ××!CPj‰@b„¡¢‹£Ÿí i`AŒŠ7œ°¡bf1¨5 ’»7‚W[Ên¿¾²íëÖó»v]ÇIƒTPEE˺>}-AE ¡±’ˆP‘ÑÕ"cP²(]„m²“,¦:LjŠ¡² T¨£é(RvI Y¨j ¨@c"øðü‰ú¿«zoKaEDiÐÈRBî(B” (…&QÆZ²0`Ñ$1ru ? /ŒrF)„hZ‡‚ ¶éQ E* ÆB—ꉞÅó¿Õ£ßüQEÖÈ(nëÓäütø~·—ÝV™Þyïlâ(ßmK—¥"¢¬®´ˆ™j½eM©f…-j´Z€Úµ¢ÐE³g¢­-`M-ô†jÖ^¶‘0µä€¢ï j Ôª¢Jáz·BFûX®)j¨œÇE±5•B̪·w12RŒ¶+¼Û©zë–*‹—fÜÜ®uˆˆ9ˆMi•Qu@ÚmUÕ!§N™Ï.&5µ~:^­J×çÊ·ØR ÎüæÜ~¥ /ö»íÆõRÈOúho ëÁ¹¨j¢¶xßý¿ 3"»xáD„!Ž^Of qŽ8@b#û;¿6§>ÿÞûñůÁÞ,q©Ûî! ù°,þ©ÏZTÂ\[ϯ"{ÉákÇEÇ{*wö*ø½ß‰EÅòe*!t[Aèàw[¹rô.Ï¢ÜÉ"TAà‚¶‚m„O`?DÖï^â ;¸Bú•®&¬Ô ·Cï-ûowä~-´Ñ*xD;¼\pf>¨™;ô°Ÿ%OûÂЀÔÍ»óH^k­Õ,Eñî\®Ñ~_ˆC&e/AR„‹xêÙZ¹}•‹? Vñ¸?µÜaÁER˃WBß-ÿP6ëûx¾¤{3ÇÊú £C”phûoÔ_E«ð;ÝaèQr(Ù‹q¸ 3"'Ò£†K‘Ò¯½ÔjkGªŽv鳨Jès/¹ç®™åå¶1Ï6áP„A ˆrP¨éËNõþ»Ó™Âõ-uSè_Š %»qÍ 6|¾~\QQ “†Ù“‹¯Ác_‡[ßõácA$¤ˆIPbXŠÚB_Ùœ)S}¾íi—Ûì] Û^Yú´”k†P›_hׯë÷É&.<9ʰsaREé²íÝûwÉ0“Ô>ß“ãe0ˆ$D¾K7_Ã/’ùͪÙI‘KÆ( iŠŸÿ2P'ôãûüy²>uþaíþ• øsöàÅu[6¹·ÀÛÏ{ë+äjßlTV[¤ëe©²<IŸfÌùàða!R¨½±ë"w°E¿ëúo²ß)ô÷– ²§ÙbD(4ôxÌùŸîÎ_¸Åi.p(´_‡%ÂL¶‡ó7`4ûU°ãm7ù˜OÝ»`-¢îÀË‘†¼¢C eªð³–RŠ ðð¶xþjåÍD!cM>ê¼Ò¨ þIÒ‹§ÑÇhú¸Ë_n' šš,Kbtô¼}ù ûteQÑ»þ^~Çú3íž³>0Â)ÜìÀÑuoáZÑoÇ\%y4…œ^L†.£EP®ÍÆ/è­â23vúÌhÔ¦{7ª²ò¥kCGð®îôn®ÕZ~Ìà±Go…7~mã; (ª»Wˆ›ÓvSJôp¶cç—l™[óŠ”éò¯DíDt¯í7am®ÖòÝGìò]­(ÄŸÏädg¦^æÎXÉê\Tö5¿æâ­eIרªR€ªåFMèú¢ï]p|p­ájzÕ|Ö[åWraÕ®1h)•2Œ¸Ökdb,Eí“¥5bþ~ÇÌ8¡ ðØtf+¯‡£©µ˜p¯² °y=Œ¬ êNî -¯£ÓCq2£ËÏ0â€n2\võ+OÂÔ®†‚P„y/÷X8*È,C‚í@µpổk‰Zw¯Œ­Luz±Mb:ƒÕªÓp€à<–õxÖdâªr¹ÄrÙ >uÚBúå…ø(¸Ÿ Ž®'Ô4°°€ ¢,FÇph·Š†Æ™2 N SMå߃%ã…àä«ÖªV‹)0»z¢áq0§0´7Ìl0 )vv×WÃÆp¨ß«Mª™p:f€ef°óFZt2Û¼Œ „%>Ð]ÑmŽ`»ó?_¸É€ô² ¿¹¸ã¿Ÿ—/ö=úøW~»d¿Xåùû°ßL¼8W§§˜Ä3°¥@T$xömºÉ )—®–tO08‘ÊÕþ_çaûŸœT`úy«!T µ–ðÎtÑ}87†üfÝTìæé“ ‚9k³(Ë'të«ö¬wWnö¸9téÉ¿ËÒ¶™õW÷öRò“å;IJÜ ®+¾‚º ;¶#JŠXb‡]@}`ШıH¨*f¢Ô•­F¶™IX´ml†,!c$QV5RkXªJ-´Ue ÒÊH´TjJ”´U¤¬U‹i"Ô–ÑERšÖ+ImT©dQ™¬j(ÆÁF4cF4b¢¬Íj-¢±lUµ®«l•%[%%e•-e[%´”²Új«¥´”Ȭ¥’"ªR‹IE2R¤Ú$µ¢ÕFÖf¤ª²VÅZ6¬Z¤Ö6ÑTTZŠ“mˆ¬M**¤’"ڶݵk1EVAT?.eÁœ ù£  ¸p@²"¥åBUWM#T>Œ.2 ÔpXGäú0/îÜ”¡bi"¤'uºåJêáozæ¯vm×$Nt´¥Ë›¾NÛo뉩M¸rÜ·,TrᩦVk†»ÖÖªämcVÛLßv…b*AKóWeÈ+d×yE•5ôDÌÊõUV©Í¶š¶ËUµ}—”£2¤µEh™¢¢f Éš‘”h™$ †CHßnj´Q«XÕEE´j¨Û(ÊÉ™£D·Ûí¾Ö<ÚÛÑmSTm¬••š¶5¶×¾í[nÕ-­± ¤¥µM- ÁH‚°`P"ˆcdl" ósÒ¶QŠ…äAXª=§åÓî¿ Áî¿¿õ?ÕÆTCzt›–D™Öƒ·ŒÁØ€0 <§0¢J @3a>>˜:ÐO]-èaª àÁ—^d—*{¸ ðê@}üRò/— =õ._R8ø:)ï=Ö‚ ;H ÄTC¾WÐGd „¾€¬JWÍV +‰‡‚ Õd@V‰˜V@}ilAYdUA¤DRÖS¿ô€@¤P V¤`R ÇÒQXxþý[ €X€ˆ‚ET)AP‚"ÊÕ·RÛ[•Usm2ÕFÕe’I4’5µˆ¨Õ¶ÊDLŠŠÕjýU¶ò·å>, ÖP@Hð÷xŽç<âßæ]ïýIµõ¿?âô6°~²;H© Ð;ÍKàC©>è u1ܭχ·»Ì‰¹2½wÌ!0I$U\SÎýS"³»Ep@"`ž( €®úmà žÂ­Áñv÷pÛÓÑɷʹuÜec¹ñ·ôœ˜L+lÉθ³Ôî‰Üv+ÁþŒsÎ>¿ %O½Gr=é_Yiê„EláÇÑÄDP6ÑlxZâBe¡P@¥ÚZmË[/0¯moÏEA`aXDü¬b@—3‡77ôS¾~@8†÷||“»ÚîûŽ]mÚ»Ì:\®s ­òÞçÅ‹å®áú_§»ÕåòÏ.tòÿÐß4Ïxî¸ôÝ|¿GOÚÇÕ鯧Éh§š]ÌŠ›\öÏFöyngZ À(°#<„€¢4€Xê ®(+qÐ^¸ %Wù;v­·_…÷s}ò.bÁF,5¢ÈÈJ:P‡ŽÉ"Gb æSÝ ¬2"@EÛA]+WiDE08ÄшAîd°iƒA+%%”¨ÔÖÑF“"¢ÄšŠ"ÑXJfÒIb¥1©¦ÂhØÛIša¶aRcY-"ÉàLGÁ¶jJ‰ŒŠ!Wª áh`&ÅEÐLÝæ4ó¹=]®¶ìƒ!ƒd A\ ¯p ø;€‡ˆ£VÙ¬Ö€€ $$)@@ P&(f˜i¦€š¶¶m­€ih–€ih€€HH’H f­³VÙ«lÕ¶ZÔµ©a ©A\èd€¨P ÁQÄìÎlâPäž+xã8Ìâ° JªÄ³§ï¿Ï÷¾Û~×åþÊ®Ú@7"¨>,T¥C¥”\‘_=ø@Wº;Ãw™ Bªi÷è+„µÀ*"$ˆ»ÐN25D‡$-ÃBQ-Ôº6ÿ åzh.ù ÖE#Ä•4(¢*"ÓµñªõJƲ éJÌbReƒB@’lLÌH Ÿ7r•U« Wx\õ…µX*1^KŽÓ`Ý!f®›öê*h4ÐɽÑ‘1f ›!ÃÜÃz °zé ˆbc#‰ƒêB˜B¬nBn‚²ñ+5+8‰ ñ}¡ )A²¤ÙOy@hL0CØâˆp!C… :™nƪ†&b„€9‚É•²dhÁ¢ Ñ£`,.BC¨k á¢†ëX˜$ØÁLb‘T¬Ž¨¡IB –(!² ÁTE²´T­@œöT§" äA_VĽ²¤Á¤ˆÉ„£%”  ÆL)FJR™LÐ[jŒ¶Ôµ©jÛ5i0i"2a(ÉDe(1“ Q™JS)š+(2H ¡BØ­"/"lV´Z­æºì$)‰@ ’I !˜fB@2I‘32LÉ2Lˆ $ €@€ÊBLÈ$b@@$$&Ë56˜4Ð@2’fI™0ÒšY Ö­6­¯¾Íki¿|>@©¨î =@G è*ø4JK,©2’ÒÊY[5„*ˆÊ•²ReR™M%%’JYRRM²Ée$–%µ,©l›’[$•’¦IEJM,”¶JMDVJÊYl¤’Ë%$¤“YRÒÊKe¤²KIJ¤¥¥¤¥”ÚRJI«%**KI¶c&15„!DR“jee”´¥%e$¤’ZKIi)RÖYT¤’Um¼¥ºR’’Һ붶U&ÉdV’Ê©K)KJ²ZkKE’¤•%RZd’“JJY,ÕJV²--)”V+’¤­”´¥d³"Y-,ÖM™--)%–²V­·Ã^×Âîw^öéU$€Fs(ª‹$¢ ¤„RŠ3¨DTˆ* tÈ’ ȤˆE’‘C±ÁR$UÆ*²jÒÊ´Ú”–µ5¥šÔ@ ‰h‚D P ¨ŽdŒi¤È b¾ÄySƒÑ@x¨¬`ñP†n@ê5âœd ²GÁPÀ˜(ËcM³ *"¢XØ=2?þå|t ¢† ©í.Å:åŽÅVí˜åŠÂabùRT[Üìêâh3Äë«ÑCÍP48<4àÁ¨Ê5Ï*XÒ±€ha6(,JXª0Á0°[š¤!h_Ñ1nÂÀÆ,eêÁBîÐWdÑFô—X„ba*‚Fb›älÌ0€.ÔÎF“¶06f!#6é ˜k3 ÜIB bÿ´Ä*OR8Ai”¨Q¡´6éWž~Ê×-æ]-Ý]Ü—w]ž•Ã%Y¼Üšî®®“wR0+½ÕÇ FÆ7ÔÆ:h@rwkr-ræ;¹JW{;ÄçmÜç\ë¸¥Òæ%Þ<ð®YÞÁ¤©4Ø›Šr˲%sXF“aM8ÂMR¦Š™(e ´Øìªc*FÆâX¶ä¦Æ*à\®›4Bw†@A¢œi© T¢*B”ÝPÁ…66›•EB8Fä#n6⪠¦â% “*È¿ö;wrî¯]‘v¹»+)M1ç^Tƒ&¡L^$¡Ô`ÒÂ@rµã•Ík•¼îæÑmÑ/x÷œp0â˜ã*U-ïôøÅ©¶àüóˆÜ_Ǭo%0øŠz= -@G“[ ß{‡ïªM¿J7 –šÍ³l"]3üÚõí¶µ×FýëgÏÏSk{µ„í¶ãÓ¢sœ„¼sdgöþ,Ο;PÚ""óD’ƨÚDI&]07 Ûþ2Ÿëô.–d3 £R¯¼%ûý¿ñüriúÚû»[&Q¼A_ø¾¯úÿa¸~mwÿùSi>‹¥‰ëذF=ÆOC~‡fnÏw"TÉÐsñ3>Å?iª:˜wÙî]g€°nÚ9Û{Ï£÷½ŸÿGYý[¾YòÿËzŸÍQGíV*ƒ‚1b¬AX äø2IµHOˆ>còÏ÷®|/$dzE£ÝvüÃñsé$‰å“³æf?Õ÷Ÿk€™>ÀYÓáUD|p÷ê*œäŠ ó„‚"Ÿu>æ€]ôÊ¢ þr¢UЍ0à@EüúPý8‚¹>?ÚXS–:7Õ}ÚŽLÔfŽç¯ñsmòçOØCî!ouüúW® ¯hAZ?柤Sú„<¸uF4žI£ómôÉÍü« X‘4”Y? cùùªC÷±¨ÇˆÄ"Ó>á}‘×1|©ºù~2xO5ÒÕG”ïöÓYMçíßã{í|¬‹ÕÊ'Aîõ4®¶0wD»"‘)Ç=™øC‚E =(G†ðŠuç÷­ß៻‡§Ïžyõû5¢­p þfTò\û|žV  A»Ï窢?ä ¯EÝ oT4‚¶A]€"sU°¼fîüJÖ¯r1 %´ªJT²k%Il¤¥R²Û%IZJÒT”˜l JUn¿1yõí'Ÿ¿Â¼ª¦æZŠ·¼-iöW›"Î)ÄáFâöG˜äBíPÙ &-qsЪ5jhþ?î¿È¸d3µË­OïiÂßï˜ú·IåÄZ·ïÊf²ˆŽ%àL ¦!¡0ý4ÿŸá‚Ô‚ˆx0D»9$ȇÂEé*ÞfDÀE ¿Q“= ¥V^÷ÐG.u{/ÞQM¯˜ˆ*}× ùè+è€QQ ê ›;Ýís4Ó°@MêÉ“ÑΊˆk Ëï£ÆžŽÝÿ&`ì âŤúþ¯9¸º,)b/Ü¥qøß‹káo^›+m ¾¯’Z]çÏ)- ©’žiKž ÄL*QDžÇò?õ½wãõ?Áèõ_Íh«¦ït¸Ñ+þŒÀ¡AÚÔcƒÁ瘲¡´žõ1à<ÿWß…ªG¥*ãÀ¶»äQñâ  ¯ú±?òöG{o;zG»àèéo =œ0”3ý>Á¼—„ðåi à£0"ÂJRYif Y%i*“R +)JU¤’Ù` !á¯>á ,½L\có?xßèÈ{ê´ZËM¿ΉÈÂÉ"GÒ ã(@0r0†±Zç§£ñRëÇ ¾mËùZEQÐUExhÒì¾”’I&ã"Ÿ”î” ‚[=z è§×Lˆ;;û ‰‡\EmRMʺËDØ`@?¿‚C& ^/-»LgƒWØ¥É>]h3³ÕN³ ßþGÄþgÛ]zóhí¥úžó©çàWÇòÏÜö^Ì"ÀŠP?“HHˆuölŠvÕûŸ£ß€PW* êE1ïiÏÅÏá%O þ§¼r€x ª?䢔‚ºVä÷iÿÿp=Äd;©ÉãŸ&Þ<ÞñÏqg4SžÍÿº±áŽz?õ?Ý“F_À È`aV !àúÖúfcýR3–Ù*Š´­ÞŽî۬Ȼjú1á;—ÜÇð3¯ýsµ‚vHw1ù”:@;#DE~@‚& ‰äKœDÐÀú ç XªÜ¼5¯5ÝÉy°ë˜lŸY(,¸Y ª$ÝÁ5ƒüÈN†Ì8çx$C@#a (–d€%çl¡3ûd¦ˆQ(?Êm~½ÿÖA_“[ÓÕå pÓ1ߤS‚"Ì«ô[+D“áFøýàüïOb„^ç“""‹ùPúã?}ý%œK›$ùÿ°q7>“¦¿yâ å’Cøî9ãnyå{ÒÍ_£¦øo^½›ÃõÙ€A[½LRqÂ2SQEúÐÎûŒPW(?Ø×§á»ûª›€ _d´X‚½ê*½àöîðM±,D ÃÁŒ ¹wÁ@Jn¢ “äm‘ëž""”EO 5AC¸Ü!£¥»ìæ†QÓm9}ՃǛÏ0ˆIðIQ¸8Ÿè~p3Mp ›ñø€tž§¯0¼Ä¡–†aˆ+ÍAY†¯39oizfËF¸ŸZmdÈHÞî¦Qÿ{ Ø_#ÿp=ÿT&RO7l|\ÈS@6êp§…"/(l«Ö‡œšðúÙPçä/ tþÀØ%ÑÚ·çŸë­ÉõPÄžûqÓ¦ ÈeþÇ©, ãyñ8Z|ÿ ØŠ"‰ö^‡=WÒQü¼Ê ˜äÔ$ð!Éàx6ð«Ã’‰þÃ4vÿ;kºd)0F+e äm©ÕßZA$óòº[0@íHa‘v?û½@ñðÑÑçhený÷ 6Âì66»#sÄ€ˆó¼oûøíϺ„ð§À_·PPJy¯u*—Ý_ÿ—(wqÏ4EÌÿ§ñ½Ö{ÁïÌO‡ïö2 ÜVólg¢‚b°;ê÷ò}=nd£Å¬«õ~â=£Š'´ dº¿Y£ 4²º÷ ™KÁ0ýW¹µ ’ÁÏv~wsth¢~w𠻤2ÁôoDÀ Õ.qß·¶?:.³Y´¶ú¿ãå! ¿™Gc·­Òïýh†çâЕTU)U@¤‰B4' "H‚5M‚’ Idab$ "RD¤‚޹jܹªîê®îÕsr®rµÂ0’ "H‰ ¤‰&ÈÄÚH’ ’%$$JH€’ 1ȉ)"A$$‰IRDDIRAR@ŒQ‚$‚IFFB1È6¤‚Q‘$É!Kwu¹«–¹®knnj¹¹µrÔ`‰ ¤$@FFIŒRD¤‚D I$Q‘ˆI(ÈÄ%$$ĈÒ`F‰"ŒR@’ Æ$ˆ’ 9adi)"Dq‚Ž4’’‘%$IH#1I$ˆ‘"H-UÔ ˆ•T5*ªŸ»Æ ¨%ú>ÔÎQTáÖ_^,‘D›«*ª-꨾§‡Òx”'á¶®/EɃXíù «÷¼õ«mù¯[Ûèü‘~KùIÞß½Jõ½OåCßîö×Ámª¾‹Ò""""""""""""""""""""""""""""""""""""")"""""""""""""""""""""'mý=²¯›¬0«¬Ö+ï¬ýnS¤ØÇüÔØÈm úûC´Sº@ÈM›ÁèäÐW-|Ò']6¸»4zEÎ×fLG KCÅ÷Þ7Ú}/åôzéøqì½Ïœg8Qøû4TÉùÞ"wž'­û=YÛ´W7ÈÁ¯w9GÆE-€¨#°‚±Š"Ÿ§ÉH+è¨.Û@©æ( ÓÑEDÿ†<ÅŠ‘¢®ÆÕp/*L°¶$cB‹P%ˆ€ Å«H=¦fÒ‡¥@kZõý½UáþW¥×7|ý?ÆoÀ”ÿ5Œ•¬mÍPÇ9‚mAÈÎ'böbc¥K6¤ý‚†ëÍM2Ž'Fáx´ÌÀc1‰>-fÈ‚%& Du"™¤È´@„‰Ñ¿.D¬=³îKõý Ñ’sna6ãó ­òÓî%Ä}‘xÄ…vö~· ò†"Ï©¤($<|ÃXïáÁ;LÇ´C®”ißÇ}-‘vàgØu*Å…Y£ñ=n;»Ûö¡Íp&þý®CoÀ£~;ÑwfäÞD¯´ë{‡ç|ðâ¸ÃƒbmÌ»ÀÝœ¡ø=gt$›¼§jÝ ôf°á¦ƒnf¾uÉbé¢ÉVª¯âçýÙ|øòI$’Iïl¾¬ »’Kÿþ¹ŽÏÏŸ@Gpÿ“að ÓàþtB@ÿ=°Ray<óÔ“çEë29&ŠÀm±ã®ôxLÖ ÅìzTPÈÐBBÀæNç0”ˆÜ|dÄp¤êX$AH¥ öÒ€Oà¼64>ÂüýÿºËúû?áü¯—äy¾»¹ÐƒÉ( â„à1%è1¢0 aý„ QdŽ0ý¨ AÜÊqZSØL: F£¯Ø9—]c«Œ›È.¹Gw_K— ‘Uœ½=dV¨©«”¥¦D$ÑaOÞ¥In<Êe·R¤-ZØ¥ðÄÔ­cÀóÎ1Àã\Oû߱ΕGÅBW!¿fh,ߨü]ÿ &?ÒçK?7;sç Ý¢ƒ_ŵÓÙS·è:ÎlÔÊ7jª¤!%¥«úžÀúÿeõ=uÞÝÉ5$iÔÒ¦VJÕ°Çœ¸¤ÄêæžK았Êtu{6ø¯é‚•§,1)ú}»1L ÓÇAöþÞ¯Pû•4oòl,cIyf²Mk\цÍÜÃ+{EËEË«ÖõˆÃ2*©m§)Ã,ýŽ,׺¯tükò¨?0ù¾çÇB­wi}òÚõ¿cö\Ô#ƒ`6 pMèh#mÜ-ÝI©uP߯U «$˜G+G.óDéÐ*iÎJcJ‡¿}<Þ¿~ù­ÄJÑ)Mb¯µ"“VPJ…ÕK²£ /H‹-½j e URRw† ¦6:i¡ƒŠENÿùþOëÿûÿï½ðdä$… uR¼öÄdà1N#ˆó{aÊŒ‚(¢àÐÙÄý¬(¾|¾ÕnŲO*Ã1Iæ©âã>Ø\ަk/$ YpŠrr‘´,D…‚18ÀÆ%01€gà,ö¯“}þ×I.jìˆbõé= 9¬ B$G]Ÿó·Íhc£µ/ Y}‡0e«½R»?¶îÍàCG?¬Ã¡–d=8™_-V0ðøÏñDÞ³½EuûßwTo΃v\q={в建“J‚}œ îG×ßwËõ>pÎù{¯ônƒÂFe`ðû|kI‡1Œa¶IÇNu _¾%ÛaYÀŽ’”Ô±‚ƒ` ¤`éªþh?Bt^øð;¯gt¸ðˈ÷—õyIú" µœLLb*€†`Š©ÄC½ãž?r ­‡©„ƒ_~>ßú¥Ê¿€?JÀý|„G¦{Dî“= :@"¡Ò<Ôî QRˆIT¥jlì]º\Õùw.ÞtÞuÚí¸Æaç^yM^eµÒ‰]ºmŠ„## \òàï+ç‰Ïx×FÔ©$´ÆØã‘zˆ´…óˆýøÑ*¶mŸUÛXÉ#éÇ “!õÛ1›6Me™ª±TÉ8áoÐÁÎÜgii: ü êÝd4ÉyG´“¥Ûèí»!#‘h7ÞJ$e‰ÅämÝÉÙùÜgg¹?rtã® ¬×j®ëà2ÿœ keTÛæ¶ØärÃñÆÍœeQ,äx¶ì3 »z8a0f™P@u+t{²¹ü<'3JQ‡„èÌûhÙÛFÏri}¨£&Ñ­Áò}ùføázÀxÎka‰inº¸†¤éEÓ ¢y#Ù•Ï ¥4å…s‹Ò( …ZV¯|5¾ø¼ oµ±Ê,5páqaq¶DœÞ1<„WZ6xo—ߎ894¼¶tÕ#v¸J™«ÈÓ10Bá@F¤5s;žíÎŒEQw©‡ .Ã~/ØÒf³E]ƒ.òÃ<£s$D€7Q3ÞWÉAadƒèÙ!ËŸp‡yÎBG‰âI!#’Ûªhõ;”à1dMEÜœw$캺˜`ÁÜÞ6W ÌAZW÷” ­¢RÆ `@ÍþõI–ä±ðò_žk”tf™§E`›tð6Y|7²Õe@6Ï•p.»wkìd#ögJƒºß¼ ’èv"™C\À€Â0‚å‹Ô´Ù—D]*}éN:†-~p_¨A^9>Œö¤ãéøÐ“»r¨º$‚GI‰kŒð4Ù£èsºwöbpç“¥bÞÞªIe3ÐYP A,‚º_à+ÓÌ 0yÎŒ‹’€Œ˜C“Ýò¼‘ƒú`®«ì8kê]ú…l,ʃ`4à=ºäQƒ¬ÕTvÐÒAŒ½»ÕK¡ïXŸˆW¡d%<%è³R¨ÞmIšM½ÍF®Ð*V+n¢ùe®4´e•¨ÆÀ8•—¨5£ 39E=šœ†eêÉ4'í 8tÛ4æ³£Lf®–ËÙVg+/hVêæš“»¹mI’ÈÐ$µ8ÆãR)mfÚª4ž86µ¢´£]îíÓ%EÏž—ˆ½ýƨ+­&û¨ŠPfæþ¥Öxu*k¦44V÷NÓ M=ÚjË ÓB£C¢é‹¢:bªUQV”:-—·Y…Ý¿_Zs`È÷é^íØ©Û°RHÎͨ%’üm[É$DaC÷M­:gü0IŒ h6·D‚ÍBŽ70Cuè˜Ø[l¹4Ú§#•ò[*”-Ÿ:Eòw×­Ü$é •ËAQ%Qø'˜Àš€a×ß Â:¡8誗ƒÊ|²ÐëÒT…W'½®ßËÕîU³ošø6ú«,¢>&ã @ŒHøHEÈw@ÅfÇ=L!uo¹M ¶åo×$Bá CÚ¥1÷ Ù € ì¤É x÷wx9pÇ_®l`J‰ß ˆ–ž–z&bµ ŠT§½—6†’ìeÙ¶a$åÌœ6>‘!0 ­hQŽ¡Ís©x„ˆñ’D¨ÈÈ›ÑB¢Z §ïVU©MPQ¨(‘uîxÉq‹ŽÀÈ1½,bD0؉á!†ñ$@B%Ž‘»1Êv3äXœ4lWs¡µÝš v5¥ÆMPAU/³ÜP2@Ÿ4…ã²’¨b+¶Œ‚€H+Ȩ¸[ŠƒŠQ^gX¿Aæb˜’!¥ØlE7·8Žp=èh5IšŽ¬hŠrOÃÓÀ­æ[ù9¡º „ÝŠ+¨¾á3cmöˆ+î*ž•­·žW@‚«áý†b±K®`‚+FJi¬³ƒ`1„ƒ– ~m Zm ,DÓ£ÃγXwùÚı”bj¸¶(yE0nRý4—T‰w@åQ^g†JtUÔ‡²/e_,‚€§é9ŠïÄ,¡Ø;ÝÍeÐtŠo;d8W‘x=è^æ›Z€i4¥ÜΜÞ,ô·OžÆ¬Ï7ŽX½4Tc›šöî­ïã¬kÒŠæ&ã-‘”Ñpˆ¹4ÁS\¨%?܆ډ|‰9GÌBHÅ —Eh{HQ´%ä 0‘÷E†>ã__­D<¦±…QwJ.>¸HûU#“#‚pöxv^Pí\* ü†6íO¢å:ïË!NÆŠ+ƒbøÌÍsÍ·0e ‰¦ª@ FA Ï¯­v÷}¬­ÖÞä[ER³J…ñ„Ði‡TEª(P[k–Á%Ù£†ª»½븽Òu“.<‡P9–œ´X‹!ë®$lI·;º¹7v {å½17#Pˆf@óõ,(e9q t5õO¶È£<þ³ÒüýVܪœj6K• 9D8H~V·Ã)F %Lð¤ .U‘i•ô»uÛ¼.éo¹TS—RRíiZGÍèƒÚ=@¦AJ.±;þ%©b “V/,u§rt^Eɱߜ8‚GC&“|m5«©Ë%„©h‰ ;¨[ÓZ›<ƒ«*CeÌÝFØ PÞŠ*½Í%¶ãPÉ¢ÍïBÍjT¼«Ž„„ÍCLKr ï„{v,,IBn¯5æËV01†[j,#­ ¨Šv HŒ„ˆ„H©¤“Â݈>¦@/å¼p ®Ãz§“—xPú«´hQ]2@ÞŽüOœŽÃj‰v@ÛØ@Š;ÁHiÉkZ#hV2˜Hx²èƒw:‚“}ðxÏ,ÿ·ß~oµò¶•Õù½÷vGü¿Y3|±@em8õ÷:×äi @–&NF( Rû‚€ƒ"ýqG±CÝžÈÈzú*óÐ;†?VþÙµ~Iüœÿ(Ñ‘ø~ë&wêî™ »¿0ï8ƒQ‹’kªjª/ºÓêÿVÓ›t›ð$G,D@¨ AÒË@vF¨¯€"ž°@‹b¯r0Ú¯n Ô¤6HŇ0Fd à ÌĹ¾øØì%ré ɳٜظ¹«Xw`ý¼j)¸À‘ â# 'b D bB)!ÜéÒð]å(TÖ(H…ûí\NLDqÅsMœå&¢/Þ4Þ)ør€âàå3ÈúŸ{휪˹¸5™ƒ"È»Q{=ٻͱ¶ _!{ùô<þ`É *ì¹jŠÒBzÊ*Z4R* ¡ šT¶ÛÿX C¤ešê;‚—ž!:À'訆ÜlÆÑ‰!¾•L~j·<›M“âj‚ˆ¤Cbprã]±Û MeU±šøHcŸ°æŠ ‘ aÞqÈ(b*»ñ8b\"¿ç¥3ÀD b0 à "³ÖÖJ¢RVzæùWÙ›OÁ<7źŽýLH7@­{ÿìãî°ãˆt+,›nj$V2AµUSD` ¢âPü5*Iûm‘?P8ÐR?hv(-¤ùýŽCǼÄ2B“|ª&Z;Ò0ú½-~92w»0¬Ò‚´Æ»3s™îCËvÎ4qÀö0Žt0Çh-‘§¦ÑCF$“öÇíØñ{Å7.¿Æü_–úõ_‘í|ÉmÆVD„#ÿ v|£Ð\¡CÝ DÑpÀ%UÑ'(ŽüèLŽS̶ãÍyЇ€\ýKAûRe5OVAøµ¹ú npá‚áTHÈé0Š(Á¦ÆØÔèeQÜWdl¨Z•@TÕ¹MÑ%3Žt¼ò„¼ë93Ôì±æ I:ñ<8ú„‡ ¦ÜùO ^A‘7‰Z[m§q'D[ iÇq¦"Š…“ðW3§„§‚Ì”Và YqŒl|‚Œr ½+ÂðvèØhMµ˜``õÈrÓ“Xôyôïûç {¹©½³f²+É ß~àÄêwk¤-'l)ÅXåˆ%°ôñ±å¤-!w%4ÊuS‰ŠD²B+À-\À5Ô SQQØØ ‡åB¸@¢œºã;¡GñšHu²F‡¤@‡Aïv‹FBG¤6/–é.ð®]À|Á£îH¡±GRy]hׯ›«âWªdÕ¹^e˜TZ‹E$Ša©_®W¸þĈ¸úDˆ(aèÕ/TIsêxn{†Ð“£¨ä‚Csb†#Ø’¾ŒNç yè`˜ÿD °QDdC@­¨Ö l †ÚlÐt"@÷Ÿ>6H `‘M1©È‚5I4Ø–™e3øeÝn(­ (ûUaVÚ K³›C`í¥…UÈ÷]%Ô²®š´›dÉ–zðÛFóK´¶2V‹LÍI‹.ª¤’B—-úZÇÊ\ñQØ85›D9(„“äßKˆ2ðc.§D†eG6 e#ð]=ÔÑ·©ö³×]qíK™Á‰ÔóÀ<ÀàˆÓ­ #! ¿B¾?“ñq1ßÀ®æ©èƒyj†k†Üëï¹ýiç«Î0æÍÓ6À`Sø¡°3ýýDc´m¤¬¨XÚ "š¨ØŠÁ#˨¢°Ù@e]Q‹j ê¡Üˆê" {h P‚s[©TDY'ÂS»^{ýÝm•ª½.žN»ÊuU^`Æc^þ·yÕìõ¯Wi¥î³nÍ “kmâÖáªa½ív(ÛâíÛ=¢‡P¨ @„(!Ái•ìýÕy+0³!¥Í6è㢧gÕŽv=\©ÎŸÞÿm­ò.Ì ÓQ Wdµ‹;ÑTÌË׿û?OÇ«ïç̤©:È«›þ²Õ°ÌZñéG—m%m‡}jÂEü/³ÃïyOÍ>àF§…ØZ‘²2ÇÙ_¹”g¼„!zà¢MZ ­Gò^OW?ûo+àþ÷~GŠ€¯Eû«(áæN˜ îóâmœçZϪc\ɫѩîä»qUIIš}:³Ö¿¡ BAóþßîôkLlnh,k!x(Âå—OÞæ`&ÑrRQØô8¶¶É@ÜLM¼²0„ÐU–_Μ{Xùþ~v`jôGR ñ …Æú} œ$(hˆe•pPAݪ ?²ÓCi²Ã÷`¯^™Øj¼Òª !Vq†!V¢)ŒŸˆžäBAÕH–Òmh¦­Am¸ùÔ0N&¬Ã´iHA¥É2Ê$ê+@@I°œyõõUÉqNußt]<Èd.3q"ô7ŠbGàHÙE ¤’6b°HBSîÀ|=WI±Ýj›II0Äâo‹Hô>Œù»p^dL€P»“¤wí°ÍJh£[R¢"°ª$E*!"_ÝÙn+»¬ ÐVš|ðùÛÂޘﺎ@ª¡Cì;ÓÀóàûÓ\E6JKGÄóžn±oI5PbBáÆXÅ1¢‰ªÆ–OhŽÇmÆ`ÆÆ…ÌebcUÜ$‰7ñµ±ãQï…Ì ¬ÑêÈo /ç¢{\ÍPíŒÊW ÉE0©CU@ãfƒ¸Q`‚¹AX‡à˜U®~p:X‘TŒÜš%å(hxøGE Ùˆ”Ÿ‹~¸k';Ph±”%0ŒdçÍ2K³£t”ê‚´ð…|{d0cÏb+®©‹É9;†1‰jØèLÙE_“—j@ ê™T¥HRèN£J"D&D€@‰È„H‘<6H.çẞ™jÜ]$„t1ãɹÒÇ‹º<¿‡ò¿w‡°sèÛ´vo(Ùìú¡u`–ªÆüÖžüïkâf•Ì­Dì??ðk}ËsWrÕv‡†xÖVùºû‡ º¡:ï;WO?õ뷪ĀòÀ>ÛÞÙ*˜TJêj€¾UQbèÚª6/‰ Fj@µ‹Ù¾ÕšH¥pÀµ°º­Ke 8  ”Ë‹A[õÜÔáKY«N°Õñ‹PÚ ŠÚå:A§—ØjšßJ!»Ã¶8aÒ5”4°Ê¢6¬87†`p™kØ¢”бºo*ÜÁ‘8Ý…Å3ÏQQ¶°7NCüõ`È'{2íS•÷ö»¹¹yFúü1ßAáŽ#¶ø,éèl.xmý*Ʋ‚ê©B)•É…³¦ØÞ­e't ¡° ´g‹ôTÍ'ÄsžfƒTCwf·àkfµèð30ómŠžIl8»›¤wÈ´]¶Õvws¦ŽîñA{Ý4#Œ»>«=êU°2 •Æ‚Q‰A€&–®q#7µˆÒäC8•Fn(Í¡ÅÚªÓGŘˆ ì!ðÞj@”(ù°Ýrž1¾ |1Úúq(:T£~üµ¸YDW3xsÚzl€ØG;ÒXŒh¦#Ï ÝºxüÈ&æ)œŠ6¹Iáš”v £Â:MHíéÈj¼ß×Gpi„Š1qÓF¢iŠ/î ŒlŒ|æMs¯ZË$¢W##3ƽ=+g¡iVÍß1€²YÜÛ =E­žX–°hB” lp!Cæ…u”£ ŒµÑ+gu¾ZìøºogYÊzÓ›£¶µ–wJ„Ô ¤:Mžúd6Q\ʉȲ f è©‘g•|5 RA ’ÆYÓ(鱤cRãre[Cí.Çr,g£ £*÷9\¡¤ð»BÜuÔÓ^þ¬TŒ£l€š ¨À3Ô‡lC#µVšb° ÝldÖk/•ŠÍü*/Ÿ^5Nê–®¬w•8Rï… £˜yXÝoÆ1ÑYp©skÞ"«C0kŠÌbÙNÁ²ʬT0r$cšc fk"☫(–JMÀ½ëzØJ©­jA´ @rß~Š"‘C"@`€‘P"„lýÇr@ý;³c©£ÈhNgBQ°ýퟬ's ÁÕyA›tЀUík&w>us,>gã{¬½›¯R»bB$ñ  ˜lgkïûn§gxšQ@RNò”A!!¢ ô¨P&Šé–v'ßUŹ!JUPªüž€¾"^AFÊpBè‰Ä-‚‚ ßé®í¹‡˜N˦A ¼Êz¹P6 u`؇[ … ˆ qNaø™"b$ÁÅÇB\Ãx‰ÒN‡fðöŠB.Îè¿Ac)‹ÊÜ¿‰õ·@tú­ô÷·ÕÅ¢<åÈr ÿÆ^­Â´s„ÐÑ{ÂiéPÓä#2 Õl×B» Ç}àõQ¿ÚÁ¶2›bú¬$€ÄÜ ‰!¯áiÔû:¤äÉ›]‘Tñ²„MPˆôß­³’ª.ì·vxÏožl4ýŽ€"%¬j\%BÜoq¶Ïo­0­žil´W¯ŽºÎv ‡^'oX£ëPmºâ(TF)×/5ëTð–š• í¢­¾øBº~<ìorfµSÚu)8e ¹ˆg‰ºZgå7M£2^cÍpî·Žf!ÛÐ=ƒ˜vù¡–ÝjÓQZËu*—;Z@íÚ~'¦­5˜È ¼Wjf™ÿ™ÀÃxIj øº¸ö¬ÀõAÜÞúÜÝP\C’Õ!¼Gux9ìDV@E`á²3}P²u§bBN-îUî‚j`†ñ /3+Ÿgw“¦hѪhwBÈüA ™d K„ˆÊ9æ7:‘xý`_kˆUIjZnËVŬô‹©oÈàh…4Ø!9Ð$ €6÷ Ü@×ÈDèâ ~>\’I$’L($sIúuæ?Vîhíó_Eö3>‡º½àŒ¹=âl°N?Ê!"ð uJ2«Àc›(íäàÈ‚kÓºÙ‹v '‹&¦r*©æÇ°¹½ì$Œ„9e$ Ô•$9 Ò¨Œ‡£¨™CQ÷†šȤ״tòæÚ-#PæÂÐÚ’Èc^×Nø@#$¡mSÕl©tªòF8È¥ÈKHâB‰f¹&.IØpga2YÓ§153Êw%W´.Ƹª¡Ð.-Ç3)Ó›¾"_¬âA^š+!­,B(an¸¹ÚA_Áç^iŽ>ä¸ä8•é!A$BE" ÄCð˜dÙÂöNÞ@Ú1ÞiÉuí;âZ !$ŠÃÀaO27=ü#yu…ÔQÐ㺂-Û>—Ž4:12.^~½ÌQ]b È‚»d @WB`&(~U— Ä’$ K>âtªöqÜu„Ú{°6·»0$ s82"$â}ÇÎ¥Á¦XeIW–f:¨Q´„k& bë×¶é”S®ó+uî£6Á ,> pb_Ag“±Ø‡ FÝÎH’Bu€ kApPÂTdŠ+%彨‚ý©²è!NàŒè”Ç èÒóœtX»èò¶¾Â×}*ÅòwY’m"@¢ÙíÚ&Q¡i6ÕyUú[¦¸:‘ ›œ‰h]x ¬FÀäã’7ØÚC}W²@1(=ÇÜ’I&¨+~†ô”Þï?E—YÏŒÒR ǶÙ&v0¡@¢ ¯ä FƒìPùN†A<¦ÄG¶¨eè`„„#nÐKô×$èç Xˆ{BÃláÚ­ÖÚR^¯>G w“°‚(I¬(¨›…Qd†UE(öq±qƒ8v.KÃ0–‹U£§S©MU†”Z£t21λ³4µadʱ›f$c =5G@!yQÈ$6Áb”¼c+T’Ê3‘¿7ÕXîv/ÔõÑ—y]öjôš¦)G(ã]1¼Ö ܹ^‡>¯_6—ƒÍLg¸ºQÄ«À†"ã%ÝFÆÆâUb‹Œ–ôÜ—Dö¿Ìž<‘V¡×jõ¹¨FôÍgMTÃKÍij³¢Ž'8ˆ) %£)ƒµUñ&–1¬øä†²iP(GlYh¡phÞ°EÊQªGPõdâ`0bƒ@#Å Ü@%5#h'yC©°ÔGLdÉ¢˜Ji:UY”¾k—"N–; 2 µWˆx›ÆùâœOq’B&“°AY°`®mtæ:tX©mû‚¿Óv€žaÕŒ}|Ë«A`ßÏÆ—‰Èn 60ÎËÞzj ‹ªm§M € .^I1ÔÐÀ~I¿ ¥ë²„p =±ìQå˜È?eÛ–¯— +‡aãP"˜¦”J7¸$Ü26´’I ¨ÔÀCuKŒxy¦@²7Þpÿ$"h'hø°Ä`M}šóæû2Q‰DÌW!vé’C²@UÆXSß/P.ENò6-$HIˆ`tÈ+x!zöÀÕb,®ä¼ÑXãtÆÈ6ßç!(Ĥ¢*ÒH©&íZ±;t Ï[-%䋱 Œ^œ¾¯_mÁðè" gE éòLxð|:x.·ÙØ»9yã÷|©Ë=—ìþµíÝPúÚ-- ðjG ÅîB C?p ¬åÂÀ\i*ª¤J [^+%ÒS3~tÖúKzÍĶ÷0ŠÝþe ÅͨM0ÓGûæ­Ûƒ m†°*,Qt¦„Ÿ>Ì1"¼Ô tü)jñ-互·¶msÎ2÷ø›ÆÓ*f ´%DX­£WØ'w5Š£j»»\Õu5½C-¨ªÀˆªD“RPQøuæ‰ïkÔ›ÌÖGîÌ×Nš¿¿é“äc½"JªŸÕUmðóåÔåË¿º‹£|áZÒkñ ðýßÕX`ü‰ O»›swá­ÞØ‘ rDÀ¾DÑ̤<àõÇ uË‘ž+¾xcspqù ÒØP‚µ­›§Õ;ô„3EˆäæÌ êÈmEŒFÚƒæA>hSÛŽHô]DóbïŸæ7Ì}ÜÐX4$hæ;îÓÆÞ&˜‡æHI’v¯ËkßÈ„‡k?˜ú½¾¥ôò­wʆϸ×Ù¢3ÆèlÐ0GòâãØ¾¸±Êî¶ÉÈg­|½Rà §˜`~ÕÏî8¥âcVè€ •9š0±ÐMiKòmAï>j”S’€rBI]­bW‡½¦µU$’3"××úïžÛ(Í$(w*½ò Ðeæ¨+kÆB"$‚æŠôF“ÎÙO•VÏ–ì!‚F(¬Š ô~Ǹ—\Ø´5ÜÑ¿Ä6v ¥xc$ˆgUÂ{Ëþ+oÓdýßGñÿoƒÐÿ£üV.Ü@Vð‚<¬Tø?7ê};—l 8D9b2%E [E6¢Ã º{#σQŒ²Aj‚Æê5‹é1±mþä`:ûpC=b $÷h+”,¤¢‚mÐzÍe´éÒgä㈊c\sp7A[Áb!ٲЎˌ֩ø0Q@b‰# P¨›•ÝŽvø«Êª¯}ó‰ô¾_“‡7Üb Cå¯ÀÜR1ƒLié¶ÿ%–~Tß¿^ˆN 7AT’HÂIŠ!F°Óp!†ÿsö$×)íÕ*Qs»©^2fúÛ!!dŠÈH6í´ßèÈO) ¿5;ñ-y^@m;¿C@ÇnèY­Ú[‚Ü<ÐKpH„ÆYWmέiã̰~Vø*,ˆ\}gø³‡—ÓEB›ÔWi؉·`zÃP<1Dß’ªÙøÔm…› !ù:/ÊÚ‰ ò) S°±Fò‰±¯ƒŒ™%Žž(p‘;l ¼ ¥ ‰AnüÊãyìHÄžF¨Ñšš´R˜90¤dr“-+¦ À*rgì‚¥%á6ªµõÛl•ª¦›&i‹Õˆ€ ‰U·*þëó¡§`&«Ô½w›léP¼t>Ѐ¶jÛ¡6žÅ¨}¿¿Öǃ¾ >Ê]è`Rõ*®…J0’Dbç7wMMI¬‘½uÊÍoenQQMíù=ï^¼óËô1rí_—›ûw¡”71Ó³èõ–m9{½¬–Ô5Ät ¬$‡[!h@²Ÿ ­èüLSËàÎË\4 H@ÉúfŽ'm aÄd¨ ‡…7‘d´wãÔ ` 1dtŠB!Ch¼X=²¨îBAª¤‘F•nc1¶‰ b TXÚMc[EE´m ´±´–™ªÆ¬–´j#h¨Ú#PbŒi6ÃL–ÆÖ5F´Q[±§p•a@œH‰hY9<{ÓÌð~)b é³U# RlIÎSü]ÒB ™ð"Cgt‰îÁ‘LnRÓ3U¬¤’!.8<Õ§@`0b‚`:.…†é¼819ÑÁÀðœÒwä¸¼Èø‘ÐE#WÏuô²5­°CÆäÖû·BÄtŠèOÝzxÈe{rrÁª²Â¾£‰}˜|‹êkÍJϘ7菉#÷Ñ_oG C*‚„:W{H€Fd,±lLRÐxžX@W À8ª;2£ŸÜ¼‚"mv¢ "{) ˆìZ’©ÿÿt·ð^*œ‡‰ê]†è¼ò©èq9Z¦,¦Ñ<ïgRçB—ã…¿j¸ö–¿õŒÕÀ–&üç[(!xŸÿo,ÉŠÝ@½ò_9–Ãò_ÇS??aŠ©Å*FÑÄE¯ç‘sÒ¿{qNö§“IòØ3£ˆó}nÕúE]§yçL}Vê÷à„Ê¿²}mŒòÌž´º¼$:$ãÞèMn·Ó…¥] õJc"¦8ã·A QÁáIeHDÆ‘M<žÃ+·Çŵ¦ÍÚݺù`ÂðuáGiúGçã÷ÍÏ u¾}áø7ú¿—ôJ,]Ëïsüˆhe0?³oå!1¿Cž-JÍ('<¦!$ÚCôÀ‡Mv<8Táá½.Üá¼VæÊ¢´÷CˆÌ#2Ï^ ÓŽA[h1Ò|üyÒfÿŠØaEuÖ\æïô2¾DÙ°ÿˆÇÑt/¼$&×>AýÐ[G”ü—i]qº©íD•A%RUÊŽk4ÅuÖè»-vˆ‹ «, Ü-@6gƆ$1)3fÝD¼†üAˆ *ÔQ£Oä$p¢Q%F5FtŒ‰" Àc Šàþ£·6'qïP-´BÉS]Y…@Å€D 0±D•o^?/çéšv°¶[±â.„ujÆÖÙ æ¦66ÆÆ™‚ƒØý-XÑ 5“e_®Ù7èD !OSÖŽgë˜@(ö‚®@W‘œµÏ·î<~[‹¯LÁ»>/H¢Ù–sCê#Ìsìêw!Ò¥ñH…¡S~-t ”Ý,Ëb F=ÐkßC&òºuˆQ¤¢Ds ±€Ø)üà¡Xœ Tv„‡ˆMV‹R— nŠ·v’à¸6ºÿËød@VH—§KŒæº*‰U͈~¬BÊ ¯/,Œ 6;åתAö*†›f©ÉCAÇFÜÁ@wp²eótbH@Q5{Ï"@ðhHAjªT¦6‘GM œqb’A¡UTA×~ÎPÀªýÈ4{Æ6+cµ=¤cèº,I$%'ëï‡/<ÈäÞ[Þ™šÒ7È’PȤŒ@VƒèF‘U‚ÅÀ€‹ß$$Ü@Q‰Àwá{†ã%ý+ƒºyý“ ؈*GxÜ:çÌÜÀÖP¨Vò$Œ€¼ý´ èÀøcLæÐ34@’»X™¶·;§0†r,‰.þAç<0í‰×£Lx9*ƒŠ˜J”H2&R†Á—ÈIWÐCµ¬ Õ17XŒ„‹Š`$HF)HÙ#ëÌíÜX@ä—¨ÏÑè&7ÝýXRT ѳq¾lî—6õõÇr!Ĉµ Œ¸t%Ån'–‹Qòªþ=D(À16•v›ª¯iî¼eߎÓvdšÖ…óK¥‡G¾z¤$™ò³¿ÂFm‰ƒ †0#Úw—~L¯2tÐÙšÁ¨!ù²ñzªª¼¥—èh£“jÜçhÁ½æQFÝem$}#û¼t°¨ÚŠÈI¹ÂâPeÄØâ'Ñ`óóyÔz?°+Ï~Ê·01t·;4Ác5~eeJ@ Fÿ2êçæ×^Ø7¢¦¸Q—î~ëߣ–`ýÝüoÄê’\b¶tŌƺ{¼tjÕé" [¶ÏX^êVEr˜~c¡d^”©ŸXöÒ3“ràî?ZSÖ¶ÌL x%޹J @««!hÐ\ zéJD0Ùf·†è“3šè¾éU6̇Ÿ±³¼·ìd’8É-ÒpÚ Šòƒ’2!ßH.rHʦ/(—¥ï&¤“0ÕÍ]«ãõ¯kVÕ[Õ5{˜6ë-[fÒUwµÅ¬ „@è"ªBE ¨¤D0³§x¹ãß HÅ ×Eã ™F6Ðd¥è ŒäLÛÙù½8@3h„PßC œ'8Œx¯ÛrD².dÜk láÚ¶_ºàrñÆÛ»¤UÙUl¡þ$T?ÒÕ~TÛ¶öçnÃú#jÑÈ+±`XÔGœNEm ˜ƒºaëqF¥Á6´ *ËLP › ÈÝÂʦ6’m.è4Ä"0N¢—Á!¦ŸDeöõ”/0™Bóe–û¾öߎÛó†˜j6¦­³J±©)©BňIš“fÌ4”ÙcEm÷]Ú¤Êi;»»©4Å65&¤Ö¶Æ¢-bŒd­«E´Z,XÙk-f•%&Ô[mŠûÏ¿µm»kx£lQXŠª‹Q’-FHÑŠ‚¶"+¢ÄF7ÚÚ÷AB=(}…aCá!¾}øåR hûýœ‘Þ¶T6V\äÏàÂS³PäwˆÎ*y•[ÍSP aÀõ"¤D.7w‚…räÒ¤×uüçš×ƪ=5¯]ÔUÔß[Å–­²¼e'n×nó¦šË®YLÏ;my±°¼Ä©¦©çX¶™·iEø -õ(=CT#!‹=È›jTÔ u†a"S5ÔR鬧HHݕԶÒbyt'©ôÐ|qx^<9-Ľh­Ôuhsh˜Ôá¡NX ÝÞ‚’!P± wöäMÔá5Ì8YÆîI ðª<ÃàÒmÍøÖ0M9ñ,GPt¹h-ÁFœ»ûâC*pC^ß3'OTòˆkT„\Ì{ö668Á@îMÄJìÒ݉ܔT=Pó¡pîÐ…D‚D4†›êëÐ1ãݲ*ó>g¤âòNNA1+ b6‘e†…3èò=n‡[qâPsàT$,»Žú,¯‚Ö¾²ÆKr ‘¯›»nÓnñiFˆ •a‹@aôÕ# zrï/´mbß -EmÍ·Jæ²X˜.ÀÂAF¤‚Qâ_€hªÓŽ6éPÁŽ1yȘÆä+f¶¾^w'|Ï[‰œïÂ,ôþ¹Õ³ ™X…¸è Ýþòg@3Ìû®å¶¥")‹y”ÂÓ€ˆˆ82€ jãF"8{b‰ùksEÃý Ûm=‹ýy¶Hç¨3€#ƒ1Žg7Üù'ïù?m L”Ç¢1±€êÛýZªªª„•D/î••Z?çä©Ñ?h»âÈ.ì!þ÷7¯®ëŽß¡ír!š*‚Gv eUŒ½:Ë<Œ¿Õ×”ÚM_×ÛÃ5êÛ{¤ò8.CfË&˜Â&h€îö8Õì˜ØôŠç„nÔ2ìàïü êËw õ& bk"aqí¥1=?¸;Q:¼p=¸¨®uoIõNßuš—jÔÙÑ8!–µ›3"HKÉI PÍ´qï®ôtüÏ…ºÿáýï™É÷¾Ëö=¯Dx$KCÎö/£ð#h0€?Ìüÿzó$÷T5‚ª# à&(—o¸‚°Â Ú™Q¡Œ@( TKÐV¶¨›¾µuÍŪ©1 Â –C÷"˜ˆ²M%­·Õj悼îŬW µËÏwm¯)·Õ!a-%{•ŽåÛâ[UÊM£Æå¢ç²2"]$\B™1Š1ŠR)ÅU¸EU¨âAúŸ [‹3Er« ëŠ}/Ÿ-j±N‰ÆQôK)Rã"ÎèÕÒ™ ÐéŒÂAã“î¢ ïî Šâ_t*„WS" ™:Z*ðó>â‘ ‘Ï‘ BAYÌIØÖLÔŒ>&£%ASV¬‡EËoHÒÚ3As$d´ hø+†(+óòa†C9AK`ÒÐlÃü{›’4z/çžíÚ»'Èʦȵøþ^’>OS)ÉRI ‘ÖQÂQ÷" ÃêÉ—~€1A8¢‚¶ w¹K*f¹|è¡ræ>òta: xöý¶'3O$v*H»oÀ†ÈoË]Ø AÃP? ·àËPauí&ºI;XѺâŠuð2¡J&ÊLª"Gµ‰}ª.›c«€K34Å€^˜%F5)·ÿ«qv©ûu“d-ôÔq‘¶£ vÔ$)„T0¨b"©´0Š—EXÊD¹íÊ ¢¤DLH`H”!G¯²qP šÀ>ÖìíŽü´CâÞt ðˆ‚n‡]^dPW™ÉÛ|¸mfx<«„Øñ !$Àw#Q†´ŠnѶØFÐÅô¸Uʦ¥4 }nÍœö…rMcê–)J"z(¤'ßc+åèÝ9®+½@N7uœtÝP ? `bRA‹Tm£T–­£jI!I ²gÁhÍ-å#¾wˆ`2¶¥lÝ:¶¨$€$‚!jÀàŠ›ÐSKÀîŽÈôˆ2vÏ5,¥Ô!Ê}9Q|Œ¢å‹Ç%š]py›,ŽÈvH²ÓŠm™ ͇KÉL¨J¢‰Ü’¡„³ $j IÁD#‹>ÓäÑc³i9e‚5 ¡#7tÆô3E¿ŒÁ$²D!&µ¿,­÷£}—E’Þº}Ÿ-¼9lW¦Ø1ÔAMS0b°ƒ]VÔ¨’!iP»G>-ET„±Ô(zd!¼x嵐1¤¾äƒÈšƒjg”OŠ’$E]Âè…ôaJ¾ÂÍÐëÄêΜ‰r†ê‰ÏwZN";ªHuÂÂ[™.î§m$ì†D,põ19Ì ©ö© Û)•žŠV^Ð*ÚÛaP„^ë óÇÁ8qn}—•Ë*-IHQ Æ›Gqñã÷·EŠBÀ{Pä$bð*%-F ãQˆ¶béŠÌ@ʸ RøôRXW,<Œlû1¿Å)"Gª¯°Ãž7öš0i!™JO(ƒäS©`ÒÕãåõ½+ÝÙšåÅ´È)SL˜fpšŒˆ’ š‘Es‘üîÏú¾ïyñ}ö¿µò½×GÞ~+°÷Æ©7!ün\Û©B¤º…;ŸÐŒŽEˆ`¾Û…´n놚Ê}Þ4Ý€‚3z,o˪4ÖµδY!J4»–?·äª§Î£%ÕáUNòH;É—.2UöBH@–ÒÕ#Ÿˆôíê/g‡øW¿áÇ?Ã[¦Aê0Å* àŠ!$¡º‹~Ûè·Ö]?f3¸­vYþ£ûOSæýÞÒYíö|ˆ¿‰º–eÉ] Û•JCMÑw_^l˜ù¶”¤„-s!X¾|PŸ~›û¥HÉ$HF  ïuª:HDØLhÛ]0·¦“ÿ”] 0WÔÂê@ç5$t@¨Ùäœeùð'%  †X²-‰žê$œÇ¹EÚ Á8aq×ã8¸À©Ä4Æ·"&B`캆’ Œˆ©GíBBRà 0šm bwí’_–«btù¢~8]öÜ'®¼bûqT„$n7.äâï1ƒrz¡ßåŸ'r'² «&®KZ ¯ÉÄ+àî€y¢ŸÌû´üßôÿ¯M¾‡ù~ÿþïîxþ볯 ߥ7¸G§}µBUZaýÏãQû?s&Á³³Í1hp€f7š^!e…S^¸ TηWN¶š†±¢BnÉCdI T¡ÕQTS¢˜9~]–Þc‘ƒŽ}Ý0¸\anÆëR©„`HÓŒŒÊ)ЕU ‚Œ@ý:ª…÷4‹¶Ì£-H u$ª¢(H0m¢™ÍUヰ­UZ³Hl.:c¢ ÔIV”JÕ°>¸Â°æ­±64Ö˜[¡¬¢Šy hIÁYhm§S ÝÌ at F7PЭDÝî•6ÍÍ‘ÇQÛ¦£?Í1}Ü!ӌ۸* ¨Ë›è§¨\ÑS„àTx8ÔiI”Æ’©Œ *! '’0c$#eH¨’ßü—tð@Æ!5*‰LƒÐäU ªöù<»Íþãlðº7Iá ×¥ÞÅØhs{²mFö+±‰Ø¶ÀUî‰È!¿4ÊZ‚µ¾‡‘Æ74uRóZ­{›ÓÙ\åÓÅj+˜€‘ø¸PáíXK@„õw÷böïÃ(‚¿üÂëׇþ|&,ÅçÆbù| È9urËÁÁƒ°@`ëᦤV#šc!É8–P!ÿ›?…›0ˆ‡„bg|}5#ÝòZš¶ÍµòÒå m¶vêÂîûÒìû7Ú§Oë·ë%K#Q×jƦ7ñÕj€ÉèMgš¬Å¯¤S1ÚÍú­«m-îðÞ»CÛ|÷žCáz”@õÕÔÖêE¯=O«·Ç×–™Ë£ÞÌ™2kvFh¦4JÜpd˜Ð„L"áñª”ÞE2FñŒÁi9zosvo]Ú‚¥6õ–ÕAIF›I# ÕQ$VÑi³)TÊrIz!hÀÁ‰uÔ+66ÆhúöX#\Æd)ËAŠ ¤‹F3p \Ð0€\L }cÑG§TÒ-¦’ I5¢ h*˜¨m·±Ÿ‹.š=ò4»Jý·ÎM»®ÒILÍåÕjÓÕWøöF„Øo.nÖÆ€Ð— ~Qî¤Y¢&h z݉[Î)«T’ôÄH‚³‘1Gi=ÍpeFHÀŠ&à¨t0޲ªU 7önSl~=«îg²>ýØ>{«¾=ñÙåô=rè˜z‘NŽÿ gš ›À9ÁU„«”j6­£[W5«Ö¶–ù•¤ÝIëM÷Ñ£“ÿ:Ö."¶»eLôF†‡]æ•* ñõ”Õçãq®ô¿CÇþlþW×õŸ_ì$ì0+ºÝ²tƒÑ€«|-—¥Ü²EÁ¨Šk¡¤’\ ÔB¦¤Œ¥ ùe=]QŸ¡²ëUØtÛò§ @òAÓl¡¨ör,i Ç7Ëíø,4ÍÜ€¤‡e¶5}êŒ~Ákʇ+|(à`ß P–ÎŒJÓ?ðÿ{Ý4GlÓ₸#¼!ôÂnQúB ØAδ4ÍO¦‚BAùVàmÞÀ‚»•,Â$ƒ&ÅWͨ¢ýŒ¢à½­muî‘¥õ½/¬®áÐI盲Ër–æg=Þ¡.’CU&ã›î\G6®Øà4íê¶ùzª*6´kM¨Õ"È„b‡äãV eÜÔ!Åïþ{’öB)´cÑX$"3P€w‘@BEKãZ¹mÖß‘Z6­r¬VŠ´ )Þ3´” ­:™Ã´p¤%Ðt’ 2H3IóoGCx—ˆm)6ÍÈ\GÆõ<Sy“«ögŒP~ƒŽ’ :çéU‡-h¾@0ið3鄈BpP Ž;Û‘³½¥ùÑKs@ç™ÄÀÎ1‘>†í#­Ã>Ö¯ª±Tšµ5Ml›A I2nh*Fá#5PÂMm\ªïcÎÞØò|~¥èPxž[† IJ¦&Ókç>€€}Ú0œ±Tæ;È„Š²€ò8óðyœ7IšìQlmM*Ø´óÄ”…È$GŸ·EE8F¢P È$á o¨®ÕÝb…EÌ. «ÅÙµÒ^õ][ß/KtÉrÝ5­²RRbµãkÝùÎŤ”쀬K1‘±`ˆ&TõSxó€nA\•²\,aJ¡@ÔÚ&Àˆ;œ1…pa)1x$r>XÀù³­”, xÐh ¥‡¾âM‹>æÔ9 «Å\Zh@åáà@@³pàލèókÈŠe†öA7Š;¤Yå^ˆ+A" Ç`]ýƒF+HLïNÉdH 4Mó¡Aê0Q¥48©ÅØÒÄ‘5´@D€Áz=Òo Âì[VÖ„qe I !"µÜƒæ† pû¼puÁœïýórõØKˆÒØ„)ˆ•'<%´!ÁªXƪ I@7pŽO¸ÅèÂ:ù°( ‘J.ß CŒªŠDP\NÓd¡Žõ[«7u\Õñl0(t3èY0®U&6S8ÆÑm´Ý8ì©Uè‚°Ú\0M#d`L¤6Òš J£ÆjX‘S8i³‰zGÛòÃÄ~“± [Vrº‰Ò=2'"°1Š¢TôѨ xP*¨¤1C?z‚´]rrçuSÖÉG<—õ…W^äKð!šG΂¹9ö ‰ÁI­üøIH¼rIùDª+¦Ùdë®dkÉ]•·“WM¬‘QIÆYPäwß̇$Â40N 7ÈÔ‡´»-†ü‘wÔ𢪢{u$ü·Àg ì#ð£’Ú¡˜ó C7$ßì݇hàMfš@8bÁ0ÕÒ„gG¡Xú›ŒÑøhØÀÉ$ˆ 3’1yN•Å"­FthjÎ\âÖsk'T¤Š'&½ÐúÒ`ˆçÂ$DCmâg(ÎÉb0·  R†韜‚¼óŸÈ ˜t3DéWLá¹n´778½˜ÜIemÅ@¡pÐ`p\GCN¥@žÃ¦RœL›‰ÈŸ„SÑ®ØD!*­n‘]¯—Úû7·ªé?äpŠB®÷Þݵï,Ñeä!…õ0µY)¦Ðœ›ecÒþçô»ßÙ{oø>‘Øõ|É ×ƒpc&pGÙõž=OÚEž{S.à´<xtb"´$H@´1/qú 1ƒµ5¼!WM?ØÉV°•nuØX«E½ÍÕÔ¹oúy ÝbI$—Å×ó49âGÚ>ÚüwOÔÈ\RÈéBÑîücö8:ñpÄVÜã½ñœCXØœÝμòu#ó÷(]lXh ¬WrC_@úͺ°¯èWÕCAÂQâëï7pð9œ<ÑÝ"ƒ¼‚±‚°O=P}ñS/ƒåï¯yèkÌèîÜ*¹±7B¤*M€œÜÆ•VÁŒ$)(·ìvnÍže*Â8 †Y»yYM­H±-ÌÃwV}²´–þNÝ÷Éñêui)Ÿ»ôx5dx‡ú“F„’Ç÷ýŸrî}ŽëÏÐôP8@ßrò-9KÀ~NoS&U2³/ž§ŒLqtðö¶í,[ŠŠªg¦0„ÑÔ)¬ëž( àÄl þÒL oŸ $h4!P ÷M‡Èë(R0Œ D‘R$V+¶™W´ìÕ nHT #Ü sn ×é"H)Èî$9 O!7ÉD` "Ù[¡Æ€ü¯(‘¿oB#õGÞ{c¥Ÿ0Û-”†]Hà`Æ"@‘!⣲nEv*4•ÞD%B’Û6eõDǬ@*´®]È¡GØxVz¢{ýç3^vð:aÓÖR:h)§VÖ0‰¢^ÖûÀ’S:*PÀ d׿´ð휳™´-ú|F…Ø,0|[Áj»A°:BE¸§hˆzÎ"æH ù1-«,üð_CÀÖ¤FhÌ\jv)˪€Ä†Öܤۡ®O ã ¸¢&n2«ëhozÅ6‰ ÙË’›Xû-úÛÞùÇ"چɌËÞ; d¿5ÃKSR#*šh:8ÑG Èd‹Ïª+ƒˆºâÖ©%ªD¼ƒ|tÀÂàV|ÞêUüÆ•H0uCˆ>éÁ€êQƒ F‚ •¨½ƒ%&‰9i$‘è»È:âßÅä,GR¥j94ˆ@¨=€‚{Ó—ˆ`=–”tTÔÌcÖ¸H‚°-B!˜”$X3BÕ8^t'Ím}éÈë’»Â)áò¨3.ˆRƒÞ;Œ$d "› ¥h Rœ@ˆøx`g]æÓe°º;Øà¢|oíÖ«, ËqÆÈõ¾ïµµog7p·ÓwïU<à´»ñ²!±yž)­h-rÑñ® Aœg"Aå0$;б^8ý `lSã„–‚Ɉ#ÀÈ%0Ra¯Ôîý^ã0µÖS–½;½ò²eϧHÚÐ.¬Ÿ† •Ñ'ô.ÙGú¯ÒþnH>nÛSjäÆL îØà˜3E‚FEüÉ®rÍ8¸±Àr—i½¶ÖÚ›¨Í;®¥³»(ÚoÞ]ÚCh;‘ šªTÉ ¼óÓÌ /^ë«È%@¼qCdr2IM7«Š©¢Ø„”WJöÝt¡5Låͯgòo^n“K4#—îí$yn·cQŒÑ%Í)éuåq™n]ÔM’ Iv“´RK_—8èF Ôné ŠÜ2O˜_æ®·‡Óã]"fŒ$›ÔªáEB~“PúýLäÕAZJ“no d³„ —ó‰sÝ/\‡æUÊŠêÈÂùñ¾¯ËC™U ¢§Õ{£j¬cz^hÈÀµO {¶´¦Ýzª²ÿ3UÖ°pqÚm¿à8ݹn©ª¨R%Õ*#!#ºt÷#W{” Inf¤+)­GÊ“^=€F1t?ÝÊPn!¬ Ä„B&H-øsýâÜÉÿ,úvp-GaŠ$‡KVDŠº!õÔ,EAÚuE.åÉù(NÀ±J0(‹ã—wyäàe†¨5}LÞ~±XÐS%JÝ[¶‡p¦Ü¡—E´ñŠ0dÍÝãí¼âf¢EhˆÈ Ó¼ ¹!·ˆ.»ž?çí  ¨´NÀs¶mÉù”®]ÝÍ$ÚBZB*²ì¡¢H@ÀX)¬è<?”ÐèµX©É2 N© ­ ëAX‚m4¢RÉ­6ˆª½YÀ˜aµí©}W74‰}­jµçUou{ý^z¸`&˜0D`$‘„ —8ÂàÑ·g`@ã†Ù–mÌ짪€¯êѱo‡rà–Š]T‡ Y=yÃm­³õZNYLUU½›^Tv¡ *þ¾%3™E1Õ°r¨åÓè> e°ƒ—*(©N©Ê¨GJ†2.TÔ˜ÈÅ”Ù#I7òŠªï B0Ž–ØØ1×ÚºGa„dâI$P£½BÕªqW1cc7÷Ê÷(+«@ã$fµGöZ>¯óö÷¿h¹tZ%lJès=è  ÖC!Ø+dKÔšEè$da—TŒ`Â@’sý1d@7.Ý„ ú&DÜÔѱÚq¶¨ì#ÕX¸®RŒ°R¸÷»›“$(Jø@’F樬*d·£rHd“•ÉwÈ{É·êÄߺ7÷ Ô dª#ÝÜšÍVSŠ k‚ÞG¸T.TóH;[CŒ² ÑÔ»- T¢¾)ÄEG1¼ç³àÐí8Ýkå÷WÊ9€k$J— „'s£%›ˆ;üÍÄ.×t‘5’B$V/Mª¸àÛH¤vžßOá6ÚDvko³ø eº4¾$]CR–€)¥ŠÿlˆWö>f%îßCǪ¦UH(6 uI±% A Žù|PÞ@Wv ¥v_gϼv!BAìNœñ Û~$l_7Ìè bú,e݉ãŽéT¨tšcÊAE‘ºJŠ=õù\ºcy6Æ6À‰mÝF3Ä"ªp LŽ&F›ÝzÝ•$>–¦¹Ä+`´1wj“Œ¶67ÔÕcjî€ì:¨ÈÚl7wUTËö©ËæW¹í5등Ýú%×M7u ‹\!ƒK ‘ùäÊšMGÛB2lÈ|Û߯=¶íÂÌÑ;«»­Î›®!gh ±Š2Ó‚WL¯`@=Ï/ ôpÝC±)îSA}ß‘aZæ’‚ u;$2’ãDºHݵ¶ôµ¶í~Ƚ¼Å¦˜I6#êªÛtÚÇÂíhê‘L½ÕÔ°cت´j ÐA‹¶Uøþv2{ñ^ðDð€@VJ ˜Ù«×Óñ-x×P2(di\HÁ!Â!ë¢$Go¹Ç&7)Žì3ŽMÄF;“¢–¨Ê¥êk tó=ÆA{¢¦‰‡L¡iOTàäO!s Òn*9‹X1ˆkb@Ã"¨¤D¸© PŠb·uR­JA^1ÈòÊì\¥Þ¼ï:ÎÝD’¦ª}·M¶ë Iœ76Îù÷ÖauÚ”Õ%@ BQB(‰qŠÌhl¢i†$DäUj #¯!/%Ìs«›7UÛ·c(í|UåÁ#8"P¸ /´¢%¿O}Aâ±Àõ.WHd‡WB|‚^9Î(+@cÅ& ·PV›jå{Mwu_#Hx9Ç›£mmb–µ‰¥„Š<õC1›Þy_§ë7ÿOùžVOÚï9½JVˆ þÜ[6 )™S3†cAœZÑ=Ù |0Ž=(=J`rx÷+ÊÊQl±“8L¨*–\MP‡…ÑPÓí.#çò³V’ä?±¬aÅñU• Z'ñÿµûßòÜ&Û§1釂g_K™$„’”×yzµæïeô¼rÊ‚ª ë!*éR8¶¿ÃT œ¦Ìå°t0çÇž/¤Uv²Ùj§–ñÔ-¢ÜaÙö;wªa¢@åÎ<85ª\d¨ŒÂé¾<1žº–‡þ† ð:wãµw픇MÌ£4>D[0Y› ”dÖ ^œ”]× „T16W› «Ó< „Ï©Níox±ãe nV#fVž€QtÜ z•¢4ÛI¯mGìÜñ{m [ïÊMêùf¬º0¢µ ø¡›ÕÑ™Ìó¨Aû\ñÊx„lø CÔô%v’>Žó*/‹¾ýlÕtü5Ʋª’*UUË5&Ý•r9 ¾Ê\"Û‰½§#Šùu«æªûóHPôÙ­‡~A5Áêƒ(}g@ä ¸#är|]ØŠê0mCTÒ¶v‚Øg‚zõ ð뮞Q}E·¡ ’²6ãžšô{µ•&ªŠI J„®8#]uI“[£w¹tÓl¶F£Œ×#aN9Öº{µ•&ªŠI J„®8#]uI“[¢^UÚè"6wþ`¥IšG ³‚0Q…š(B’+PT ƒ$‡|¬öŠ6ýoë]: XŒ¾ÿ«÷}*ß7ã«<358U>×_&E…úÊ d¨x!GÑÒJSüÐjí×~ êVýBKã^Š~·ô.݇ ›þ&ðhì)½-úÙ ¶J® ’5Ó¿q¥$B’ó¹üÅÀ ·ò¨Àµév[Åd^i½uÆ3U•+cc|×Î\Uìâįó|t¢Â™…Òša²œ¥Fžv |&nCPBIõD}µU·Ê¦f¶Ui³Ÿ,¼êïŠ ûôü¯tôÏé+Þ·Õxú¿aŸ{mw&±ì9³gF ?°·˜€¬¾ŒµêÄñw£™ê•A£„,y”ütaà NfIAÖ¨ÏÒ bÿàfU»c xZS²“d*6Ф³˜,6>yß €¾•­×µÜ“b¨£4ÖsB,SÒâ* Y“5¼­cnõ¸lØbD FlåtJ#Z9…•´-u+ ~ú¨e 3(¹ª(Àlˆe2<¹dßM!àü[–Ê€0st­²MwnoäµÄ2Q³!\;Q×¾ 7 ®zþ÷ç÷c€Ÿï?ñ"ü‚i¹T¿›&S“Á³èdÀ÷^ ëóiS Ö÷(];ö€à×'qÝö3 ñ@o×$,“p´±%§† +üëm+Òî&…¨57ÛîP—Kp_ÁëÖ†©œ·dÏOÑ¿ÔçOƒµ†©·×題šŠ«G×¾üÓâÊ*Èô{‡E78 ª}âZÀuj3”T›Ö4ëYZy*7DCŸSMÚ¥C%ì-ð´~þ ŠôüÙDHqÝ4‚n¾*î²î¯{_=m‰5"ÅN‡Ëvú0Ç(p×z™Ážª ápøÎ䨂³%©¬>Î!ÐËÌéÆñ´ eYº¨—#%à2£&ÏÀø âÏjøD³Ë7óÙñT¦Z¯Dé¡¶ÆØÛ.-No™Í¸S¦:àüAº{Ê)yN¯¾ÁÌ…(¼"BS‰¼I,'-ãÌo"|Ïh ű±“m£}¾ò¾•í¾?¶¥¨uÖ&žÑx öõÛc{ñ $(¶ŠÅª,[bÚ,jMŠŠÛbØ­Æ*ÅŠ¬Z‹ÔV‹j+ÑF£Dm¢ÆŠ6б¨Ö£E¬Qj(‹Xµ‹EŠ6ض4hµ±‹-Eª4V‹TkEkcj#lQ±mŠÅŠ"ª-m·âÒÛmÍjTZÝ+Zæª(ÖØ¶*(±¢Š4dÚ-hÚ-Ù6Ѭ[ÑU‹F±²V5‹lmRb‹XÕ‹Z6I«±¬ZÆÑ¶*6ØÖ±cZ-Â’«ºКV¤&DÁSBÐࢿMÂrЧùÞV [D,!$nL·—¥ÓgW7.bílÔÕ%R§@ðˆ–8óH+Õµt–Û$ÓÕ¦ÑÛÓ]I‡~S³­¥¹Ô5N÷þ@ÊÇMW”\ Û}>ÆÛH©Ñ‘tI '<tóÙ€EzMX%dXFi±eïÔÆ±šŽ2ÐwÇQ™¸,êZpQÿ?²EM˜CD`msjwªK‰ Ü|Öat†ê7G¸h)ª¶s†ºul»Jõ$7AæÏ|H ú²r*$„ HnòGP`‡¸~|j’,¹wâ ³´°jéè¢Ä”&Àá¡Ofü; +u;N™M6`Õ]JN$œEq$®°ËîÛhÞQN%Ÿ£d¦4ˆ²ŒT0êLläD–RŠÎwÑbnÆCdñɼ0½6¡FÕ+ŽÎùV&F¨†]õ¨îܼŽmV¸â¤3æ¼:÷kvm…¬¦Úx"޳®^í”Pß’0Úˆ9KŠ^¡ðß*«ç;ÎwGž]6@õÉŠ‹Šø($à"¼»d=•@xöŦ¿qJhEò&n“ËèR€s‚uΞx ÄA7,¦ñc³²ƒD'-)uÅ *ô¦âꈰq]¼TËnµR½;ŰÄЇΎ³¶J<*rØ(ð#ìßn×=/ñ¾g#mŸÝÓ²WØô〔YMî3¼Ë^ nNصrMÊÆw½q¼™P19žG>´•Ý݉éþ ®7¢ã$^¼åXåúÿä¼80/1d”BA`K¬üöF±ñÔÖÁèÙ™‡dB\iE&Újï( Þ¨/7T.[n7[‹Üx2ÆÂ,ÜýëÙ}°ÙV`ÓrçtóÁªõbŽPP€¨ Èwyk&s&悎XÈ#Îï|ÐlÞÃÞÉ¢Ûc‹~=uHñæw¡0Ã1"ÙUg€ÂF8«‡G&¹Ò‚ˆ )-|ÔZÓ¡ë¿e¦ñƺnEC…; <œ~9B nKdu"‘FŽÜÊï’ò·åá6u‚í^5.ê÷e÷¼æŽ]»!hÕ4´ÂžaT¢”Ô¥T³Žva­žG»“Œ¬zNö¹Uت*2‚ƒŒÄQÒGFjîóMEQS51ôî§inû³|_j‚•½sµ¡¾ôæ«M µÜðú®Ù+tfÊR™h"¦ˆ"`W| €0œÁ’kR5  =A&ß+ÝåôÒ——›»15&²Uq¼k…t•Ó¸ ”W´‚¸ ¯ Ùì]8é¶+¡a²> Oè=,’HC¹ ¨"2 PXD\#¤a³ '”—˜©t 䋘àokã‚îDÚ-¨Û_;Væ­ˆÖÉXÖ®›msm®krµÒÛ›QcUÍ&®h¹E®¹´jåk•£PUã^eµã[rÛ–Ñ8ŠªANÓ~›…%J ò…Õ5ˆ8U ¾ Ðe°AE{Ž@.nÁÌO<¸¸Ä9›¬òµbQQ"Ïa‡â œüBŽè…„‚R›Y”ŽÀ{Xt^§¯Š›ð´ˆÈi&§(ARË9ñy;† ÚÓS¼À@‹;åM=sV7­• öèÊdÜÊãÆn×Ó‚^uÙ°gtãÔLìú'nÂ41J¡…;‰Êj1¶†X1S(mÇ ”éÆ0 ÈÅ—Õ·lwM½&r拹²îR Ú ÕBФˆÈÑU b£B@ŠM¡¶ÆåJĈ1 ¨­Ò¹j¡u@© â Ôn =]ÝžyåyklMº¼“"Š0µš¼››ÒÝë¾=[g‰´Œ¢“L6˜ØÑ~aFQJǧl©‘Ëj llÂ66­yH<·OˆfQª e@¤‚”¤•XY O9b_ˈ… 뤩Röª"‹å‘$y?óÓfŠª§bÑ3D*U$ 1ˆô‚ / *`¨ ¢ 6 –{ƒ¼{Û+ÑVoaŽ3p7‹ŽS-ÊÇœCy0£0‚»b¡s›f2OLPÔ Qˆ´¶Û1F’oUßó}o;W™30BǾӷ¯›çÛ`bn%€;…2€AhNšf vrÈ­§…zH ón€tMë[fQËÔ¥9à0Þ8Þv’ærSh†úä\Ä ³íËPƒ ÆÈ¢E°ü]K–DM[h/:Û_D"]Ï­cêZLÔÆÚ=Äq°òÕ8í›Ì›°Û#ƒ"i´Ì˜õé5]²’]T‘[.€¨ˆ®"® n€J½6Á4ª¦‘ÚêD‘x)£bØ`ôÁXÈð7EÅ—UÈâ‚מ㞯"É¢HÊDÁ.‰Üþã)­GAw*]¸†þbâ0‚„ "•ñ•Õκµ|-j×µ}ìuˆ"9P0G.ˆ­êl²»™½cIÂèéþ»è‰/¿×&ÔÛûˆØõùy:‰jùå= ýïFŸ6ý§éá¾wÇ“d¾ó²C5Š 4BÖ´K¼;«Óöíݘ¿\ï]ÃAw…÷û¾›j‚øVÈŽ" " ×®H„R#J‹ ÷T\ñ˜ø0ù܈*²Ëb ‚h9€ü‡Ã¸‚taʼn D4 N”Á¦PT_óððË›£EBCÓÊ£HÚß33kgXFŠËÎëÅÞL áÁ!S¾,wÃt’XtD…“˜ZËv~¢F_0eýå¸Û<œ¯ €BÊ+ÂÜ[±`PéA¶hUJ!j’­l(A œžrddW×áÚC>pW:(b‹":ÄË ØÏèIH}ü$„CÖ—µ³‡©puïÞ«'§&»ä „n‡VëË÷ó=Ì„$±<('{L E.Ž`ĉ¤¯Çó 4:‚~”O†Ç ›Ãíªq lªªpn ÀBJD!Z ‚°b>+¼D‚½·-‘ ¥0`E¨H— qA^i Ú6ÀÄS" Äf},ªïî=W¬ÎÖtj$€ñiMpáïiô:˜4Ö[£“ ¨×Ü^Fu!5˜“á”´˜Çr¯èþsµä2‘õ'èOƒ!hÀ"d.³ýHHÌ–U9`à«h>Ìî›K~‡Í5Ê€£Éµþ8´(iއø[ˆ’çüçëgÜ_%+à0‹(¯ÊwcÚ¾*R”êöWá®oµž(Þæ½1Z¼îå¼Ó‰Çº­ô·š½"«÷+ï«Ë½m]±¶7cg¶ý48"8˜‰ ‚T§LT×L«ƒ¨6†œ…Óƒc$q€È È©¯Tå¶Õb–…É’xÐTí£Q;£Çˆx.¯¨%×’«xÆŸ.¼¼›^*K¥¹ùÔ]é#ŒÚ–$’d¹‡¦Ý’E²m¶g”%ì÷Aâ>.Г„ùÿ´ÀŒ×¸‚ÖçoNêyÕÅàX öÐßâìÕÇÍõ‘ÀÐ b”om2r Ó FÍþ›Âú®ý xun§¸òÑ÷i\ëd›ár8HsïŒh<Ó B¤¦SÜÑk/ØËÝͤ0:>w¸™«Ž4õíbw¾»)Å—;êD‰²!@«§ ëåo¥ÛÅŽÖ¾Æ}©yþOÔõÙ<8^`äµð~€PnKä’Ià¾Ü‰EÓÛ¾mÊ‚¼wc–3Ä¡s„µúüN¼ƒ,¾6®17ÁâðóÜ0ˆà0|€¬‹• f½€Z#ør¡ X¹’5x ¯ú…"n¡Í¹0;Å] «öG¬CêŽõÄhÐü^ˆ+‘¹ëÞFÂd5ú¹n’I9œ¨4JÍ\IÆj]˜”Ê;’(^~§þâ¾ÿЀp"Ž¡Jã.¹áh/ð969¶ /ÍTžšs¯uŒk8ƒ9Ä>+tGÜþ¿ò÷0;Œ4­4Òêi¨ž.T–Mí-]#~W~CÏ2ÖÙ–•û¿¬N~OÚ^<Ï®Þ0c# ÀÀ ´M=g~0öØÿ+æ‚¢24ÃLŽîª« ,¨B¢»nʪéUŽÈí¶Û©*§CG(è?ÆŒíE³Š‰í:£çë»~þˆ—?‚Pišï1qÚk;-QÅŸ»?¹eÞßúg[E{•®‹Ú…Ùƒâ‰W¬ÓUpFû²³ö~/Çú(Pƒ*’€H„‚’2%å:á«<Úºãðÿ?øn@ž ¥tã€Í •$&1(£¼ ¼°ÏÍw‡²þ¿ØõŸTçAPè: E©|œÇ"àD0 ”tÕ„ô¸aWX8š6§ •Š.^„!†ó4.ÝD9Ê5q‚~zî•7×Ųûšç©Ù·u¯Ë¸mèú—ìÂN‚Žn6âdo$ 6˜}eD+þŸ¿ú_§Î}cÙãàÑRƒÏ¥Lº£¯Z)'P @,êøƒ!œ:¤q¶;WRKßô½My_ŒÔ­´¶¬¢WÚTDÛ2a`æyÐŒ_Ó¤ºç4d¥¡5¶ÅD«V•,!AŠE" „+¸'Øojêô8{‡¿dbÒ ³ï1‹KûZÁÀŠ‚³à˜ÆÁd猨谻yáOƒa’…Únîkjåp ³)›Ö´p‰As{}È¢1N8 ñ!‰?[ùQDù¥˜ËFmL„÷OUD@‰ùRŠÁyøP5qºeüÝ”ž›}wxúo*¤ˆm°2œS~1wÆù}C„É´scÝÐâI^ŽòX¢•O¿M®ºœ•¿€è¬¥Ê¸e¦(<¬í Nú½TPDƒö˜R*ØQ äGáWM­/‚«:µH©2ìÍGL™wŸ*ùl'‰_áó"zô Èt™! FðøŒ®]9-c_Úæ2Ìxè´%¥Z!Ý(¼!q —‘…È]¨³ÊSת'_h”É軺ɋq\éÄjoEtæ• Œª„ƒÌ>Ùi`õrž| ŽØ‡Ÿ59ÂÄ0T¼D¾>^Îþ$Ù\Å[ŤoQÁ*s爀øPˆB>!@¶&uCA‘ cœÏ,{Î;k1ãË´‚¸÷lÚÎ󎜻C]ÔNŽ4_žKZÝb‰à1)§Z_‹e­´ó$=€ÖèõÓÝöÞ¬ÜkA›šàÓ*Hâgêb8¹ÒÉ: ôð-W&'Hñ|lÄšî×ÝR\Q ‹p­uEû,€wz”}V‘›Ý>åeÍ‚ç¹'ÄôFû™l·V<Å*ùÄ J­žb(-g5CЩ­7š:Öðþ,afHx_Ù|¿¤$xFIƒ˜)âvZ>GŠ1 O¯ÓkÔ Ó“:FÊ!U|иê{í&b–Äp%6OLž0g À$Ôì:¸W„C÷‰­‡‚™—qµg;8nG¨áް¸?öÞKSÈ-YêxpVoAô9:E a|0›ðD†º¬òÌ™ßûÛ–¿ç 8 Q¬&ß.ö\¤@®™ý Ž&I;çÊ~W;hv€–«îø2ØvH ßk8Ç“µøã,îæ ñF @W…t ºžœtT8âõî*iœ>4†Ê\r¯uÛØìbðyWÝbþÆqÔõ|æËRæ Ï÷¼×‡ãy>?Ì'Ò¯ØçŽîw9YZ*¥RWM›qíÄߨ›*Ež·Ÿìœñîxû¹-îëiãèÆü½¿¡¶r--è°ö ú´4qÐ ,ïDDX®mçÇÊia…Öv®ß< 01¬¼k=oËO1¡g;ûÓ¨Ât\ÒîéÓÛݹéò[&l^ž: €(‡È"ÎÜz[wÞÆóã­Ønñ°úv…æ“§… ²_F$º ÿáVžÏM-¹×ªá©ÿUm4<×;³%Ûu¾ï1f%¿YîG’Ö®oÝ:Åï|Íóa9Ú ?_¿3×žàø±³¯øõ¹Ö[l—Ï\Æ»wMA­x´)þd½]~.3Uy¬åo”ÑÎÒo¯ =m»»žN.ôc5ÓŠ¯'tzg“sû=d{ÕçÔÄËoý¶Þ,C_ÑIØÅw7×5βAÖù*<¸-S¢vnfáâS¦½¾÷ß¿ž×΄õ»Ì]²åsšþíÓkþé8•¹åoøõ ÇhvËaOTj&»»u¼MþÃXÞøË«Ÿ¥€ëþWÍ­9á7ÆùÇÞÀ›ÁRu÷÷µO…lqyŒ¤â½«ö|o~çt’Y_ç=·1’Y¢‹Âhwl:M ³èÐ0É·R¯ìÚöJ~s8hí».ƒ`ÃÚ{sÈä=¸˜„î–Œ×ù‡ñG4õ$új¹±Þ6»¯5߸{E?¿'ò?=¿qúÛ˜•ÄcnùôŒûF \­OY¶Ü9\’\ó ë2ýƒŠ§ÇeŠÂ¼}ožç¾v çÎã~÷ÔÄsþ”úè£ÌïàW¢&> ˆŸî¿ÅÛÀDKQiÎòWಎ7a@ áe…Ž‹%èQÊâgEÿnßµƒ¿Üi²¾ú–O.&mÆo—ÂKÎkiÑèßt·Æ›‹Ì•˜³±oYµfÃÑ}é¯ósÔX-ÔÖ¿Ы¯{Úé\¯uIn¹¸O ?èunËO#ÿœüý•Û‹5!~`÷ÅÄM!¤²Ê_X®{ÛŚݻó…×^´pŽ9ùÝ„zV°C>Ñû‰°^ùòç~Zÿ^ù«®“ñÌ$豟 4úžwzÁ.gý©½)Õñ䡘,5IÎÝÆÃ3tÔOj+²nC?·æ}ãõ‘™šaÒ³Zäsñ˜CALÁÈe’U•ë¯{Þý6.<åiê™-ø»t-ˆÞÀ8ºÐÅénn:Ö Ì8ÞîÎråKÜš5Ëå KÐ4½Û×n`ǺZ<£[ˆû=í78ÒbXŽ·‘6 A²8ˆŠ¢Ï‚¹Âocò‚áf”ï¿«›îìžídœf+§”L¦› «µÄݽ0‚"œjöÉó+î[F¶ZÉXæûwfí–¶®·ØÈ'ÅÀÚl¯ Ö3;ýu“¾öKΙ·“[i¦ ¼u3ÿÈ í>/=Û3Öú,…Vß՜é…’‰¼Òç57ß½²fç  †•ŠpdÂú”í‘æ[¹=§íþ+hùzÌÃgYº[ÕË¥Aí°uÖ<Ëk7lØž/~KM´ºo®>/•RMJǼ6ûÚ0z5óvžÖ¢³;)Åœ˜»)v‘ÙC]i=.Üo¦¶ý¯íoî÷ç6 ù÷KEË÷«á´¾à½.øý˃nÑE¼a–Yà/òö¹ÿôgC}ýk·Àe޽¿ûGCZÍöbº…eÑG°Û}RN:'FŠ%šc Y‹‡Ã:dqkjvo}¤œ=»W3ï׫ÀêX$~‡"dÇÇD‘nðIrœbñ4OÎM2^"ôLÞÜö–ðñ¿í‡>“üë‹ַΤöß°y,Ë„Ð"-Βݱñæ!Û)äÏÊSCx)>\Oþ¶ÁZ²Œª2jî– Vžc̽¢.ý–aK8fzåXßÚÓÓz<­kÆÙcvÑFßËp¿9þuÐy¾çÙ‡ÿ_°‡Ú[µÞ<Ý;¨ÔT9È÷ïÛ>+o¿ýÓÙ¾’Ú(ôWb-ú^õ7ââȶžÍ_ËE(ݳ±mUì¶ã9~P¾ùkYtj÷Àl>VÉ,}õ™].*Õ¦Ktãe; û~v>.Ǧü•]-G¶ÙsÜ´ëäà}yFª§7=…N³{¿qjåäþÔ›O¯‰È3þá.:švt×'®o’ç?¤´N'Óþð8OÝ…kwþôó7MÙןìöwl‡ÊÇ3üø½Ã£ÕÇÁë8–úGOkrô\êVv÷±Óžn‰C§­ñ^k1Ý?Ÿ¡B{æˆüf¯!6ÿLÛY™K×(—/ïAb‰>Î3ËÁŒ·xbê ÿIÝì97¾#Qºõ~öÿ¢†ñž»ezýŽÑ-éI·Èô˜œò÷æ{ìþ>ß‹¡á~ÂNCóÖõ±ò—¨K¥¬ |¿Eèb:™i;•³«[‚òrøà%¸‡Š9‰å”õ_š?cÖ¶iRsé?nùLÜò”ë>»â»C¯ìmSÞ¦eVíõiŸÕ¤›¾ë¥÷rÅ]ÌCÇ7çýiÔv©]†Sy•¼Îòåf.VK²i·VíëËÛ¶îŠÓ±™§½ëq_,Øu¾/w–A98sü¾‰÷yq_ ¯”»ùÍë[z¥ð×ZŸrúØ×œÞ;¥+”»x{2ö}]Ö*Ÿý÷Oc\)£ž»×Í5çG÷äŸ ÏKyÔuêdzʯ°2ih$Ǧ«ÁTÙ®ê4â°UXl“T?ïqY]PÂ¥r¼#uú«Aeñ¬lŠˆ®‹þ½Š¿™ŽgI¹½W~Zü”Ù[v =ºŸm^íu=@@Ž01®3¾L=~f]ᙚÉRM{lV‘ËΚ?w%ÏÂð0ôñøídô5ò ½Áµ G3âÑišoüÉùœç†¯ñ!4éøöµß4é%›lü2iM+¢ˆŒïÜ–è[ ê2W B¿W=SÛWç~ʾ/¶èZ_c8Ô£:fÚ胫þw¥¨íz.I·×í_Ö 'j\:âòr¦lý­±šÙ:>ã®áå£`Gi°cìc¹Q4Îë Ý/ÙQKœKÿ•qÝ\# Õ«yl…S +|–bƒ1xoòr¹4{ή/­¾Ãçp¿«}þÎãeОÁ^¾YL}Ú>Jßݵ¤L×SfÏMð¶óøÛ…OLQW …Z¬VóX§ ×sßDeù}º¿ñHÌ)[Ÿ¶à¥""êbZª4ø?ZQÜëŸÑAJP?(øÚ=N ‘¥ý!ê3.LŸ3Âã?æ”Ï sl¤Fõ%›®CëÀL(ý-ÍÚ÷œܳ,]ws¢}S×ã´¡^ÁW°ÛÞ½¶ùN‹)¸›ou;=¶ÚžÃ~ý•¹=×ó|™LŠ3ø¯Ë/}Ñ¿?‰xØ.œõÈ{<®÷S)_ôbgëþõÜH­®•}5ý§³SfÊ- yÓ[=çJ׫‘XªÃáö³-V3þKrÇ~*»×xœG¿ï_È9‰«¥ØÄ1ß©2wé;ÞÿŠ­ÖÜÔÇk|ûM·ó='òÇWZîÕ_…±k/V?ÉnŠh?ÁµO·éZ­Ù§M?Mãg…„Ëc¡«ÓÚª`èï)·3ü™†Ý»†adF†¥+Þ1Û)dmU믉wzÏ€êÇéõŽ&Ú¯Ã)|þa/RÔXm{>S턺æ3vö›Ý±ÓgËaÃðâµCràîË\®ß Ç¡9ºÌ¦w•ãçP0eØï¹MÉ•tdúÑ1õ¯X¿ñ®ÙZ×OõÙ­ƒÅõóJ’¼¥-¼8¥V‹§váqÇ™·ï—o‰­ã3xg><݆ËÕ.†­‰óPÉàÏQmÝl28?Ä–«Í÷ëM¯ùз׼u–{¿Z.›½MñòAK#€«¿ iDN~ªóÊñÃ;ʵ/ »Þï¦u›]ÐxŒê&ÀuûQZ8¥ü[æF[»cˆcÔnç5×KßV¹pðSL7,‹eö§Uäš bõßý—ÇÛ²oÜÎÎ7 À–¾…ác¥+ö-|T3Qï*â\5Ý^ÕužF¶ÑùÀWbÖqß8Û«–3ÍvºÞxÌ:nŒ{WûñØx±Ê%#lp™ÿ,¼c~é²~TùßÜÌâpš:ûö‚ë¾Øî&+^q=6F|Çü–5n6Ûà—¬ÿo/™·-Ý®ÿXí«•föc™ûz>œž½¾ÿ‡æý»Œ› Ÿ# Ç—äi®l—­wÇMšé¶Ï¯Ù|^ò­]F)^?øÌ³‰Ç`•¦ùxavÞwi«_ýt€ÞXë¿Õºnk.ÓØ´<^úþ+¾«×O?ªÁ_è®W3³8ˆYÚZ‰«Õ£ñÀo½MÑ«)컼Ç|&Õ{O—VÕÌÏðíØ¿=Õ­JqCõ°þë°’^½× ? {ÅvZõ>6IÝ#q¬Á¢Žöü ¶süÝåÿPøÔ£ Ã˜~mIxìg½¾‹]Î,!¦þ¶gîÉyò¼0wâUr?QÝí‰ß˜úíW{½aõÒt$®‹/7vÔ¡,u ÚnŠíÀ€ûôìØÕ‹Œ¶öõî[—ÑÚ¼–éÙŽqÓ²-{^ cÝk•_²#ÁÕ³ü¶_n˜|…AÙF .r»£ñÞ°r;’›‹gZ[;¬ ý™ý#•»Tª¥ý÷‘hüi1pûG½•ØåmïüO^‘û†ù,¯Ïas,eå.]× •&õ ‚;U‚›·?SbýjŃã#ŸfØÓä~ÎÓIü·?ÞCÃf…‡3Tó/³Ìî(8޶~Ý.FyÙEÄ_w»gXK¶Ÿ4ÿphHîm|´ùÔ3É4N–«£÷BïüÉryù©.×ãI“}Me mÑdtq¢Õ;ÉBü{ZZL÷íË9¸è}ͬw—w´É@<½ð½;Ä@WÀé§ðãøóþd‹fY3fµY÷¶ö܃÷ösÔ^ÜO»Ð¿Kn¾jºúúü¯é6Ú–¶¶ ïÈáßÜrzV̡–§ó…Eß–d™Ä«þ@€+åuì7Êõ=žÀmiù²ÏÿŠ;–¶w@ÏÃËÈhõÛ¹–—›aÇüø:¬Ý’žv¡‹ù½× îûº³‹tµf»œDQÅÛâí~D}¥öõ!ù—`±Úv?Éÿ›¹×³ÞzqÊèâ9°·*Y+ýUNCHÇüÒë›4> vÙÕÞ íý"¸?ê÷îÓ½™C^Ù4@ ²Êù®È„sŠey¿e¼¾‚ž»/‡Õýc}ÐKNû÷ø¶îŽ«Ŧëqï8–ïîÈ!"—jå¤öÏ4ÿ×==âùp¶¾]zýýþ1þÑWßHÕ÷EŠöÍK;.¿…I³ß1c›AœåØV&U¡ÂXbÞ{’Ѻ}ÌT.l~T?kq Qóx;_’üNMö­ÂþŒê%ÂÒé´®ŸNµ®¥ÿ•ñüÐŽìî-ÿLn¯’¢Ñ>a25™{Žýˆµž‡îû“n{õyÔn|¬:ËÛ%åE–ǽ±«ì;ÜÑ{onS×._ é©ÜÇÖ¦üâdYý¸®Û'—1s쮩~ÎÞsY©lüÛ3‘üUêšó¸í{þÜ;·3ÅÎtc™áÛ¿]o‡ƒv%ªóþ¬pmGatîé]¼»Fœçzã) g˜Ã‚ÂAy³wø¯†1ç3 ì»õø¨Õ:þåFè½ó8Òõ[wвÔpè+ ÷¼m­ß°uñ÷6U3Ø ²CM¾p|y¤0·˜ŠÎ”à@*ð_üÅd™Mf®fGÔK‹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ†Æ;èûŒ0ø½‡¤}}z}¶ç‹KQÍî÷=‡/¼ßx¾Ï€ÔwÖËbÏ™ã^žÁ\^Ù÷>ƒŒRR«g­Ô9(ófµ´A¯\€£q€ô#Р§£^»YI:Ð;µQ¥ kÛ=|1÷mîùn·¼0Û(>ï·ÀÕ w¤ø>ãûì÷¼û›7¯¯¥WÝö€âw\˜*–{ßbø>ƒ=òaÝÁ½ê¼w× 8ñ÷Ø2 *‘SG5îP @èœùÇÜ>Ƕ;GÓát˜€}(ûß_x8EަC×fʶ‹Caµ­4¶ËM "¢·µhÓ¼}ðµå§ÙÐhvî×l9t"fI"VÛïŸ;}ﯷÐU¸pTEQQ*÷—à{À©I$’R‚ªœÏ=à;î*D’H$©÷wۻо÷¤’UPë$¤R=绸:)%%QEJ®ï®<Ø AJ%R ;¢’P*ª«¼ûáyоX¾Ÿ^÷×¼Séï½ ãv_ûÌ׉à 4m¨Fº§%W¡êykP¾ Èˆl44‚‚øCM–ÎuœÝ hâЭkE2¥4ƒ{œ(¯c÷nà@Z#“¤¥(ï¼so/··•§w»g]óà>o·Ç}‡¼%í³mÇ*Ù¬ª©\Æ­±ZQŽÃ/›9LîïkÝuÅ{½÷Üû{Þ=Ÿ|<šë tP'c¾·B‚دZè9Bæ¡•]°%B÷»×¸6©llÈMéÎÒ©Eî÷¾»ìÖ¨6[m“o™`£¶MfFJû¸«fmO}ó©ìuÍc6ëmØw>õ¼ì4²h.³Ó{>ùèúÓϹï^^ZoVÔ(T33¦•Ã_y®JšÚ´gs ×½¥3ǽïº÷JöúçÕzMmnO_;žû¹Ði! L&˜F˜™F#F&A¦@4@C@ 444M¨44 @@i 4À˜ˆÀŠlÒO)ú§åOÕ4òO)µ6)êz‡¨ = ý)æ©¡£Å@• õP4=OQÄ@JhˆD1LjdÑOÉÊf™G©¦ f£jSjhiµ=OSÔê4¡êyAêi“Ê4414РhÐhÐÓOQ¦ƒL¦š h$ÒHA€˜Œ†¦M£@§ª~Tój§ä§µOÔõOÕ<Í)?BSÓjž£ÔzM¦SÒhhý)ê{J=!ˆm@ôCõOPÐoTh4 ¡ýP4È $ˆh40 2 h‰¦M2iO&ÔÁ3@M  ¦#Äщ¦šhÄ™÷IFû²z ÈǼÏ='V–®ÒÑ㱸úF\þÖ ‰9z?Ÿ%~9\9y]Ç6•×ÕÏ$G¨w"B¥v§c£Þ°wê´œ7cmÔêMÍÌ.†M æ1ô›Ä@‹¿E¢ˆò8ǘC¼b ËY]ZRóþÑìanXVi[–þŒ¬©¥e\hÅ"‚ÌZ«Q P!QqÌ ãA`å C2•„ æ `B¡Uå ¨ŸU¤êàˆ'š‚ ûxzß©BxçÄ4Dþ¾eÿÐÓùp<Äê|µʉþH ¦¼.€£ŸÏ=±ö?±ô£ØD>‡gäìû“èЩý1¸Å_ñ©û¿‚†§n+ö4o7%Ÿ6绢@?¶LßÜ!›ÿ’?Úþ×Ýÿ’ñü%úŸÛU5/èÌ{ˆ¸PôVVâOtÓ.–\)’ÕåXèªx)Õ¼¡Þñåa6U™3æ+Q÷!‚¥Šë)”Eâ.º¦ Ä?üÞ`Ÿµw{þzMNÝýÁè¹ô_öÒ–EÎ ‡A9(!¿œ®|¤µJo]3¬b¤™ç•ë ˆN,%à{P’!Óãܹt)y‰V¥&¤BxÌE<Ó¼©N‘HzªNJ&bä:wuLq¸3røqs³3uqdE”EBˆ›t?.o1“ÓÞdS§ˆ·ˆËz‚î©ñåT™$B{H”¤‰‘ê2¥b²žr*…4æN(‡ˆƒOß&~¿‰ýÉ#ô¿Ÿ–•P,FËÁGƒ{O¾÷y÷¶ï¾€˜¨L_Wòl5ÞNßu _ÛG¤ˆªtñþØ~×Å õó,|”ÿZŽâ’”‡¦×è,XŽÌ|Õª|ÊCËXë­ÜØ|ü=¼=eâ ÖújO9–Eº‘øðÊÙîÆð„£®8&,käòã²Cy¡Ù7ü†¬1 ÏÎ÷¡qíbbˆwçí-ççïO­ßQí'à@Q÷Ðð=—²ùGÇÒÁóáè£æ'ùuî¿*—ù?¢»nÛ÷m«çé(göÓöaÚ@ìØ*Bª q…xeêx]]a5ÝÜŽ‹9_LªÝ®VDùñ÷+¾K‰)꺲h+ˆÄêN*b1N(]…‚—¨ÇÜðv;¶ºŒN[Ç!‘€¨ºÃÿg_¡(”$Zc?T\K—ûp÷!†Å7©arÑ‘îÚR"÷š”ü¡¯‹ gÿ{Ép¨6ß\ÐÛìYk{Ðo+;è šïy;Šýù˜þ3¼Äßë:n¬˜»Çi>5Ú} Á¼zûßâ¥?FÌlwðœíFiSíy«i/¤ ܈øàp#Ä9ësV•òH¤×ê8:½çë°@ˆÑ)éN$­Ê.´xâ¼,Õž­œŽjÊããŽÙ³c–b>Ahº<—ÝûƒŽ­+Qa–Ìã1ˆƒŽ0Ÿ¿£OŠ»ý_.²7ÕyÒôÃÝÕ*sl^x+®zQ)ùÃ×§DS†î Œ`c01Í<.¦Œ1«|cÆk铯dc¼ýéC·UHEû1A)Ž0›L¯ ÚH15Q œ¹£ËßÚ]šr45v|æÌߟ–úÂééÏ?P!ª°[NµÉjÙ[$Móߺ4ÿϑܛðQÏñ«fÌc²¦>òqØó‚,™ÇÙ£Ï2@Ї̽ï/tјÿ'ïvÓÈq›‡¸4ýJ˜±Ç8ˆ#ÏÈå¸P¨™ò3:þÓŸN–£x’ºê.G6=nŸ¹GÃÈ¥äì2\,õ?‹X×mÑLG¹v0MS×ÔÖ÷ñ ¸El«+’€Še¾Á]g3_Hl‘Ga‘“»Zovy螃Î÷£VÍØü7ÝOµÇ7:»’æY]¡1¸ ¦OVàdÍršP“¨K¼jE-·O¨ Dt2^ÿ—zÖî¶·Qx˳fkRùø¢íÞµÊ;ÎtŠ’Óf_e’L=æÖ˜‰eP5ë0ÒË:¤°&Jµq©‘ü#Cw-±±‚R})mèî܇¿g¶ó¦tWÜùh®©v”1uL jË߯¿Õß æ¤ßãhå0ÙÀ}¡¾Ú§h`àÃuÜ`[Eû6—ÅZÛ±rÆu`•÷6—ªàš½M@™i]—•¬ó¢wäu«òŸû¿‹4“¦5Íð3±zÔûN‰3†[Æé›’ÆÅpx–_‡wú¦ò»îUœí:â°ÜþNÎ'÷íü\`9 ÛÜcþ²ƒ³Ìót_×OYç»® ÝŸ—ºÖûr¬Ðt€ˆç.œ€-'nñ\äˆ@°‰¿?®yãLvK/ÝùzQn—}¦0L»¥¨6gDÞ˜žgRÑC‹¨ÌT8Øëè0“ùö½ª<5·aóÝ… pÊgˆ7/Îdùñ&$ÖmÑ'—‘â»Ò½ÓM}“E\µào<èþòÅ‹b£œe£=UÌÖ´Ö°õ76M4W ð»€gÝ4j°óê ˆT" ZÖ!½×o×}\€ŠœS³ŸµaT˜ #í÷±û*‡ºöç)ŸÂŠ <ïé÷⃙{ö€¨`ÿÉü¶Æz¯¡ô²ýŸ™&ã4;ã¶³N?¤¦T†,Ÿ¯æ!|}…úöƒ :?þtÎÊX/ý߯Íz· 3âkÆŠ[¸É|ë´ç¿´P, €zíÔ +äM*¤’1*IBF0DlmV+oð5u)WÝGЀŽ5ÉæöO_ì}—çhŠÕ×ã<¦çxjmߌߊÿd¾€9ô8ذ¾ÇÛsï…ô}›ü9?È ûärÖAž? Gµ`¯“­kÕ$BG§¡ÙÉww_Ññ÷@ èªUF ]š*0„€H¤"È JƒÕ~½“Óiðü«÷úf—ËÏõa²õ°¬¾ßcÝÿ!M^…]ÿ&MEOç㊗Ûî!­èþ²|Ç~.?´ß¯êϤfÙÕ²?"œ‚qHBn*R’!„APôÅ@Ì  Ëh6ª¿É®®B‰A "D„ ÀTTX VI$P@8J…VE‘cF•HB2"‚h(v÷¶åí»ÿ„tö¿cK ïŠàޫƨ<ñC-‹}ÓéÂüµKï¥1_gV ÖG£DŸˆöò÷Þ9pø07"ÁîIYùšR‹òƒìÏâ¾®\x ¿BUlíµ:« 2=óÖÃqÄÚ4‹Vꋚ.„¨‚‡œŠ…DRF „"Á÷mAŠÕˆ¡ aÓ u†b¸R¥±*6DAb‹94b–© PT•ØäOÎCî%ïç”·;g±¹÷¿Q©mçëá…´pò56¹7¦›,BBE‘‹«n}1XÙ‘çÙ}/ƒ»°ë‰ä-½G)Í…uä¤å!ùÏ=­kZ½|ŸûŽMM<¼±l—tÛŽ{^¸\Qí¹ƒƒsmc:(fèWc¯ŽÛÛüèþWª›²Š “ÕUÒ™nÜl:~ºn20hd`‚5„*/‚ F ¨LœkYˆ2“UG‡‘  VD‘AU¨ƒ ²4ŸÄÆÿN³…¸|V­T8FÿvöÑ¿½¯Òý¤Šo¢dQÊÊ9ª•ÐÝT>è` q¡z\|šµ›ö1YÓ8Ìkª°×R">»ÄóÕ=킌Ÿ«Ö|˜z;)fíCC…à1­ùiÂí¥gY(yNgÇv¸2íÇ»:CÊy­\è¾aðöW›¿yÙÕPÿ;¡®f;W±Ü'½.„y:wàuú»aÝè[”­¨Øyp8Äv2ÕâPT6`Y0ý\¶™•LX ’ëk Ç)š×7["ÄG†«%K®{“JÁTYmWÔ!îvèe3׋P\Yá¶z³Þ÷ùgöÖ寻o+Ï:tóÓ½PÝø;[èÛàxíœú¹ðöÜsÜØ6›ŸïñÑ®zF¡ápµHePˆˆf3/˜ÆQ½sp“ÄöYÝŠæÊÞ€ß1úZ‚5ÿígqBFCˆ­;Ã¥háí»uîΧ"ëÍÙáàmëԥWÄÙA÷@ir<óàÀÌÛÓÉÌÚäÝÆ¶Æ¤Ë I4Y‚Á©lU[Lôæ$² MÔF‚?ÇÂéb‡:ÃÿNbƒYþñ/`ÐÞó÷±ƒøPÙn½ æ?=Ç>Ômµ¾f&™E›e*Ë<ÏOwŽ8Ù¶ÄE*)`ÑoôBÿ ”4¿µ³úäOÜæv~+üÔ;´Bçaþ£ó~.q¯¹ôý>~·>¦›ßE»ß î«¡‚ŸØ>âŠÚÍ÷Ïñfß`óÍ;¿“½Iv‹>ãà5㾿Þâž]N§Øä9ªvQ }“"ÌÅÏuÑ m±åŽ‹Ñb‚½Mɬežªíò˜è×yiI¿$+=su6·[Ç$c8 "ŸAm†ótJý·©î2T†ÀÿÃåI¼L‹ç01¨Ûw=¸=:»‘ŒyÃdàu„†{yT¶0Å6Œq¢gº…ö̳ßÿ¬:¶ÔR qÖê*2>õŒ¨?èê=üEW3?ÿàyiA引´MÆT2ë2“!DIèÜ¢séÂ%_Fr9ä9óþþÔ”@¿‡.¶Ë†ìÚÛÏ£wħß<ÇŒsøº}Fæ S/1^îkÛøðšy¬}K×uýÛ‡_æ~ÄÏ/{ôöM°óâ¾^'z|÷>_ahôzhèD3Mq#­V,ˆéÃÈÒÚż &Õ·Éf} ìcÀÈõü|Ðüynáë¥)ž[Ízø¦»z×ÁäŸ!¥zÌo‚cͰ¨kº‡£­×ÚÞ“€\”JxQ=Âê0 ¶y‘ dGlP=LÆ Hïî7Ïo-6ÁÕ›WãMÝÔÆùâqÓpû E«]kw:–}ì¼ãÄä0ótìùo§µ7·ëMűCnþ4=ÝÌ…6‘k!Oëcû\vçOî)Ò<]CjŽcv}þ¥£Û;~à]=a17{Ãwa¶7~¼páèŸÝ¤Ÿ¶¹Áíš×¤2š>·gñxúÏÀy(¸x?ÞïÕeð8 ¡–gûoª&õ¬l¬Ôÿ¥¼jÃÚç—!®×£gÔØ2êG¨ÐãE¸ûù"—¦¥?ÛC-áIfri•&›xÌýÉ•„Õ{=°›¶w Å´eS×jHˆ^:7§~Q³éI“ŠZ‰i* ×µtˆ€uã»Ç¿t:ÕpšüåÃB1S\Õ]¬ô7'H°¿Îœº£f¾óymÞ›ëKÝÎãË¿Ö×VÊÓïW²âoöìyK†6µ5*Õþ÷ý-xl‡¾fºÚúîNšj—“s_Òj™ÙkZ{Òqh›\NÏ ÇAëò©bÚå~ò9¡MÁ7†éÜ_e‘J=^×¥=è‘[þñžUñ/ÝójÁåü¼ô‘å)lUù9 U}—?ßà¾Ò÷±V k¾ŒüU¤ÿâÜ‚L 'žÖ§iEQïÝÝký”,¿ÚKŽ—ÃYfò\ŽRÏÕWÓŸilUÉe<²ŽÒ?õ?I­~nGìÿS_±?¼Å„ñ½•¿÷<ÁCR»¥Sd}×µjšw\2Ê–÷ɃbÇôúžÉ-° Ϧ2¹ÊÚob“1i˜‚g5¦® IO=Uõäø´ó“KŒW6)EÛ)eðÏëØ5Ìzhô• j‚³sYK[²°È¸ÿc£O—7‹Ft\¶ÍG³sÚ‹ð%±ÔÞfö1<Ÿ:çIšBÁî`Oe¥8´FÑ,|Z28+÷×K|Îîjœ÷Î>¬/ó·ç^È4ÃßbXÂc¾Ê·³¤‰®ãÌår4ø…äíSGÎþ¼ÿžä)„ ‡.SÆŠßgŸío}½6o·˜IÝcFÇ寿~îëD‹†{^ô^%6h=Fçn”®´‰w¿–Þ7®ÅtËÁ¹žþ¤óèx[œ¼©(¼ëˆ'>ZJÅ¡B—€Ê²û]¢\SYb:5=|š/¼¾ù|9±ªžÄg8]ÎÓmòë]Ú:|<û»Îý$»muÒL+o°^M¦x*~6-Ö™EW£:‡ˆÆ*ù>Ú.c9]¡¬ÒjZ0iºþöWdW:*w¸]à«Õ¼îë|,Ë>Œœ•ç÷œØt—õe1§hï¿víÕl“N¨œ‚¾©ê‡êÅ:ã“ä{pT ÷Ìv%´ý5Õ§.‹bÜïèzéìðMú•3—•™_ÔÙÜ-uU>ìB’ôÌû§ôl œ!$OÝaÿ8 ÞÉÿ+b,ÇÜüO*®b¡K-q ËÕ»;4¿Åõ¨nT0žt¾Ìž/ºö2-H_°[ý» ,aó5/«×ÏÙí3Óþ=“ ys5Ó«pŸ+{ý[ü*IÈþ,WVý{W}ð|ÞŸþ™]Ç#çÖ²Ûõ(_l{Ï:?«ÓÛ,RP°þq]AÉ|~÷ß›6Y¿ZüTVg‹¶Ì6[ö¡i¬Ÿ,†ÊåºiwͤCá´dÁôa}â™/×'Œ”¼âýo¾hØüœ/ 5…Ú6Ý<â76V€ö* }ôõºÔª?ËÀ¡ '²ÿï·¼/âúÁ"­ýØM D«ß†X1ð–á"þ#ߎª‚QLj€÷kþIþ¼ õ¼¤?Û—ÿ›©Ÿ ²_X¥RzŒ8/±ÝÝsûßUþ¯¡§·ÝYþÓ¾åt_yù8ðÂï¯ *©ì‚*®¡5à(B §¥Öà'± ¹‚fßì¬ÿq¢©§!Pl–Θ'‚<€o£†¶4å$,˜€U½‚û—DdÁ‚…a ^ØX]p´,á-í)KGæá£ ĉ´–ËRŠ ú옒e8…îñÀÚh ȇHn­¬“ÿ~¨€’q–C @¡ù/J 6ï  rqJ‹ýQÇÓØv2ˆf·‡$Pp(<ºnòOÐô+ÿÇ$ ü}N¬³V´8=Œ›:¥Q3]uçéÁ1 ©óà¥Ö°ÛP  ðÁNi‘‘B¥v,µ,Ä'uÂ_°PþóiÁ1pÎÏO£—âlð²f`ÿkö\AUò;þ` ùΞ+Ö¡‘ÝÀš4µŽÞEr6Ô,7›uƒ3õ¹¦ÞÈ~dUÚ±í48ÖÒËv¦ TlhH(:WaÓ;Ê~¶Mr©ÐPøô -Lwø²÷‹!˜™NÅ b¦3ZøŸh²è¯‘wU åK›9¨Y8—­Ÿ¸Tuoò“¤GõÓ¿ÄŽYMÿsBn„ƒÐ}n|úÿ¨öyëdzݦ½¼ŒS}³±Ã0;[Ï#îø;F<5‹ØÌ7h‡¾›ÝÉ’|>:Lñu¥B¡ƒ§Ìj{í“ë$Ó·–ǡԯZ(1€|Ûwâ)–ü Š9e-‚×=[hüos³”„Ÿ~¨ó(¯”L1VÐZ©R¥- ¤¬Ogž˜iBuþ!¤ûSò=üS0´¾Gé>ŠçäünÅý÷é’ÏiNàöäªM­ŒÈÕŽ„ˆØª²¨6+âÆß.„àWýÊ.ý|e›í,ÙÝ¢‚£ Ai–`"᜴iQÆÉ¦UUTÅ`оS HFûoø8y6ÒàÃ0gÌaÆØz:šèJ‹ül”ŠÝü°)_¸‚ºã[ÓL*5 YC”ùåÜ1@b€Á,ÓE@ÛbŽ\Kùl9°ßÅîö´ã¹¢³Ûá%Ê ½|6}ý ÎâAú0~x Ø72.í5,ß»Áz‚Dm8ZóÃçÖøå‚29ZʰȇîëGLR9üÍ;W µùkðÓêÈíàTv27ʪïƒnyúÒÝžê¾›|­OŸ3Æ™öÃlm”sno§ƒÙ)d õëÌF¸ê?çú6=ÚŠE__ôþT×çßIúðŸë¯¿É^3~Miñz6fâ½Mþ¿×õ‚‚ O¡>ïôÂÙmQJÚÔµJ-–¢,Q–ÑFH’ÔAK%”´”>‰†jATcY*T²VQA´ˆQ¥ÄvÕ‡ÐM¤ïþ/ãÉJú=Ýf(t2GA¯5bCؼ«êÔ÷Ò~)U4'^€S ÕŒ‘êŽO×îùñçÚl1›¤ iËûÈ÷õ^e°Gb|ò úúñj!ÇÈøÈЂS¦uì­B<#>ˆ ï‘$ê…FÓïC3PÌ ¾üûÛÖ…Õ¹cVAЙreƒ1ºº ¨zB¢ÞØV@‘†Psèë ÆØM.FlÙ´8{X£ˆí1Ü`LJ‘Àèû’b.\ÿð7ÊØ¡é3¡&çåxú|Ÿâ»•¿ö?A;þòIþ÷Z{5tü_±Óïïý`þO{ÏÙÙçÎÆ_ƒ;›îg©V× qþÚ¾<³æé/ÁîçïVKå§aùú+ËÀÇ«¿“ùOúý:^+æóXK r‚4J Ý\š¨37( ÔâÈ<XlT’»²<U ÄÆg´èF ùW4íMÆPÇ~ŒÁ\Lµ/xy½EìW„ ª©¶QhEô„ìPÈEëå¿l'Ë÷À ù2{:»úþ;Ô%¿aÛ¿»\mÅM)x( é˜AAÑ-©Þií ŸÂVY›MtêóXÔ쉫‡¨ ê¢ƒ ºˆ ò×t+ÉKÅUw:&¨ioÈwÊ­Ã/}Ê(6Ölnx"ƒ×pv3ìèè7mnó7=Ί+‹&>?ø÷šæøÂq- 6ZãæùZ$Á~ã~_ÔÕh™y·.ˆïŸÍ‹ì utûP0>ÁéÉ6·!®iCw>ºl f_7¦šU÷…‚ªwŸ¥qúÒCȺRu?O=ÃÐ9Þ>ó5œ¶EÑÙÞž=}œnÅ”ÓÞ sÒTì8{ÇÌçYâÛlhO¶ËNÏ6Êìì×Ù‡gÙ¹[œ^ã¨à|„ö|ÆGYηq[—Å>½ú| #ô•Ïmµ§œmÊv)(ÌÛÌ3W ÌÇ×½ª‹KÅÁžÞ‚0†œSÙ¹”s!zåVVz w|ªLLr£Ÿ4é~}÷8 —7l?ößÑ”òÑ7†ÏU6Ý·KLô ¼/ëÿuNÁ±ß\±ïoŠfýBÝ»û¯ú_EÌ7GVøÈïß»ã®Û·Ÿ‚ù[¬äúò&c°P.ÿb8ò- fFG‡Ÿ¼ç~ÞËõm4ÝÞ6l=Þ͆_­ööŒút¸÷·y´"7˜åAïò¢àVyvŸÞ‚oX1¨çn<³pŠ à @\cũ˳>a†û»DËÎ\î‚uǦ2›|PPnz§¦=~®®}ž«3 ¦ãcò]H²4Q¡×È5¹Œ5œ̃}ʗ˵e@úåiëŸ3ëêþC™<†òƒÂ]:ù±XdÖ‡Pˆ¼öéáBà¦X§ÚBä#+(éAZÓ¨˜.ªåR€X¨=ª"‚õà#›S_S½)ô©´õ¹‚Žu(¯™N< <  bˆLBþií»¶‡—=¯wÍï{¼3E¿Ëǧ øåÌ4Áyù9ô}ô@¢ÿQÙMvå¡&>Úg@¾“—<²_›ï×µ·Ÿ+ ÌÆN}.û]<Øö|§žÔkÕÃÛ×R @P9‚(7‡ânŒvà€Ž]Ûu‡çÃ}¯^_ÇéèÒ–ý:ÓÜØ²ï©hÞ8ûÙf{À"§µŽ3òí¸]Ž`u§\Qc”9pàþ!Fäpñ&¹±u"¤ËÿÕ:ºùqß[ çŒáíáàX!'¡' ÈÌÚpâ”0ϸÑP>wYˆª—‹{ Ä#ª¢ ð¬ÜR†¢î¸V“ÞoÞ‚‡BÔ!ÿ¨öA?™K¢1Àö1»îå€'L*Ðһز61ù­}Xfe AÍr³˜£íüë«ä5ߎaK6#^¾)Õ~ë„­öŽcºs·¯"Õ»µ Ø;WMõ ',Gáoà/ªŠ¿RîÛ¸jD4Ë/yu·ÃÈ«Ÿ²W-Ð7¹ww ´›\Ôê¼³f]åj»R¼ôQÑ3â?“«PŸŽNˆ3ƒ&¡[ù†ò¿ ÇH5ÝÐ-ü¿çº§].O>;³äøÒ¬¢½Á’˜8à„hx2OÓÉ•<ýY+Ó‚!FNqÓ­zή÷ÙËr%.Ù0ä²…7 ‹ôâÇìy2ú%9×*§ §5æÙ|ºïº§Öâ_<zL­Âh—ÛáAó—pF¿¥óûl7wzÿ~ÂÀòÁ7Ù>Î,6 ì¢þ;û¹Œî:rpÞzª®ÀH2ò“N Qä•yâ ˆÐÁÎÏõtûîºbºK]iž­ø6éûyRˆ<£+Ë(×¹;6ä¯M:mЗ’®tôÃÞz2Š{J¼Œ~wÙ…Ñ5¿å/Æ´·§:Ÿ‚ZG]4aË~ö,…C'#u -)H¡öPÆÆÕþ¾þ§¬9FôáŠ9uA«½­ZšÚöMüÚµoæ;ýŽ.G­(”ÒYÇG.¬JÈEVÌ4´^“3|Ë«Ô5VI5Kòäq¨"¤ª¹kÖ}.ƒ]ïÀ(ùa»çÚÓÒ\³t>9ǘÐèN¾M¸“†)Ñ!;-œ’å¶îà" ¿Æºg,;Ë®5ó;²›=º+Ÿ{L3•*å±öÛ¡Žm…sÄŒ4Hkô·Ê“×ÇžÒ:¸óÖëÌKÛWëÔöæõgËOe>OæS«¿{¤d“†ô­ôü0ÎéÝd¿*=œ9 }ý'Hy¥§®{:ÐßókIÕI{ ‹ï{ÙŒSbÛo H© ˆºøí‡–<}¬­# ð"øóÕŒã};úåë­=½“#-á}Ê1²Q÷ëÑIçVÆNaúà#Bù˜”ÌÄÔ!Ì„64s3ðÏ™´Ë\£Øwwcå£p!íÊûžé6:'>}ÀÔÚûùp,¸=8¨ÝðPm»êOÎ7 ÌÂæ~mç§@é??r/œ÷[a¿J ­ÈzöñêFÁßwxÆz˜ߤ/`8Hà3PÃôTpÐg>Ųƣ=e™*×àûÄ{#Â! {¯²ÇÌ yOïþ2/äzØA ]à ŠUŒ jÕ<òYùùéÑïï¸×s«­~ùͽÆÊó}éÛ¥úÇá•ç;Î6](ípa:—¨,Ñ”!‘Ex°ÏÑB˜áØÃÛ3&컜LÚÌ„Eæ=Q”£´òÈsàzÈFz/”W…ì`yG¯Ûõ{o‰¨Ü]J üœ'ŸG¦LП'sT^âážíû© Ç¶ƒ¸ ·”(ó„39fã®ð¢ ¶Üyn ôÓ™ßR±â1nŽÔy£OÁÕ–Õîÿñ·†-ª/‚ðAXƒÏÙÞá9_¼wy†,`ú»»÷uqžþiÏ^ÏNvááÓ@váÉÌoPf‘‚‰¨Ãñò¯-·7WTøÀëß`1Û©\q2ÇvÁz8X¸ŽµM´¯Žo½yLñC`ÚSœjÔÆymÏ´“«…ŽFÝ{²-°:è4A̼c™(5{¨N=À ëËæý ËØôÑåïÒÓ¦<÷ø1À{ƒ~öÁ)î<ûmŸ‚/@êÉ™˜ü†2ÇX¶ï'Ž~‘C4>ªš¡Ÿ}tã•ôûÄÜ‚Z8£ 0•\ϨÆ~ßî†Ûì8õ!TZÃ=uÁz<”T1¯3´Á{‹¯—ðÒ³(¼4`ÌÌrØœÀ߈5<xwú¾,½Ï¦ü°ž&°¼x{^Ûs éñN±dôt¡õƒÄ­"HôðFS/\>Û’~§RúLÄØì=R—9ϰ{’x?/ìù–LÁ ¾¼ƒheÕ Îæ’Ý&Kl!_Èp‰[Œx<bá$fç8&‘¨^S‹zmàÚdáp³Ø“O—˜Öáêî7ûa;líãˆcó¶ÜzËmÃ|\{ARæ )páyí)Æ‹@’C¿^n¸GB̶•lµùvíý¿Áç=Í{‹[¾¨ž{nióÏD&v1ÃìxU`ðmž¡ÄH9y:ú²°Üˆ¥#û"-+—‹z˜"»z;ݨ¦üÐ1==W£Ë„” M ¼¾Rß6x²>ž¤P0o5`'òÀà¾üè¢ ¨"~ws·uÓ‘¤ôv·`$!K!Óp½€Zd°¨ð åØ\ý#£­ãq€@ ™’”ݳAõeç̰<©¹xéÁM>&Æ^Á@€ZÜ` Ÿ7fž‘»«ÓÈ7hÏ/&~â ¹¶ãúÍE`~èMx…lè? §¸ºdCŸ ê°E´ñÝçaÝÜ'Vö(QSA)ÄȌч ¹îçð`âŒk²sê8fwCÐú)hËO®‡¿‚0¹ué¿Dâ½;½iÊÂí§:8¿_YhÃÊ)G᜗ÙÛkõ`/¥)У§€í‚Œ½õª…¸ÆKNŒ#û8+˜à)"¦Yã û{ú;û˜GMÿ;ÃUÓ¶ôxD\½ñÜY8Ýb@Ÿ³à›²¾Ml²eÔC.¸Nªî‹c^ìyç7¦@ýq/Ú–?E–, ú7ºD»|ãÙ ŒxƒÏç_݈¬P›ívðμËÇŠ¦BhÔHjùýg¥(¶‡htíõH)øG˜?æ˜üÍ;¶©a펳 @{ìÀìÃÖšé™xîj4ûþƨ®ÿ7Á,:s~—×k¥ä=Ö5¦´ho‘›cèùy—JE›.OÈ'yõ¨ì·aa$}ë}+:˜åd•IŸ}ëòôþ]|Æ#jE¾#‹ý°ƒ2Ó¾~’ g¢#©Ÿ>®3³ÃPTÀyŽç£Ó)áà–¯ÒŸþŠN½^øÐe>½w¨ Æ£¢ëPe¦ºú€`îtÚë¾LŒÁüÙ ì8W}Ëo6Ѱ·¶ 0”}}~Úø\šf–m@`…*j¡>õ)¯™äöj›¦u±O$˜Ug3ï½?}›ô÷ü§¼5Òœ˜!sB Z_»žo«èȾÀÌ|À²¸ðdÍ\í3чÈC³É›¿Ò Ò7(/7¿%}·eÍ|¾š ÚVwÓëÃ[å õ½— |¼²ù3rêÝÖðùÎß/*ûŸb~Iî' ”ñ¯ GW (òãŸdVŸŠÜ\oiÜ-¶úkæ¾pš§F;gÖ:·Ó/ÄÔ>˜û^õ§¿á§ØÛ†>™ü÷.Ü;!òo+SÁõòž¼vtpÊñDÂÞOs‚8uM$.‰èt^Ϋóï¦{þjS”½™»û÷G£ïyŸŽ¶Æ£ïÇ£~«ŸE¹k•B¦#prõ"|œ/D5¦ï¦Úä¡Äƒ [™Fxõ19}Fz÷™0Úî6s¿êíÝݱneQ†·[˜Z_I—‹Ñݼ¿k­5ðåÿ‘Ç{"³‡ ,'³·¹….Œ0Ãê™÷ýÛéý“ó®¾ïšê~={š¹Àú4†F > aAãOPqöiáäðàA—Ø1 ú´Ö0þ×/Œ0|5“òj«¼ô!ÏÛññÊ7ø¦ÇÚÀýF½:û:4ÈÛƒ­ö<ø>wqlÆÝž=Ôƒß@`ó&ÇQW~yôi@àª/”ÛF¢{·w>‘¸tuô»Ÿ`Ɇá²ÙtÇ™_& u4ʽ)l‡ah5oa«¿PÇXôQ]¢j­—¡8gäÈ2a8÷ØÈðÙtåèåÌÏ´Þ¾KXd=ÚT£¾xqC¯‰UG¤ÌòðÝ¢üÀÐ)zx©Gxì_±ÅÏ3çõÏG°²;’SŸ'¢ÜKÙWÅ#±Ž™]˜îçÚÆ}í¹0·ó驎£ðçÔô×r¶6áÐ'íSwP_3ž‹O†áäKŠ(¦Ì`#}3ñ VôÏÊ…Ô~'&†6 žÕÓFüœÑµ"ª‡“ì9‰äéAÔQ5=&Êç&Ó:´$ï]×-23:ë‘Á¸³ê`!ì™Ñ‡‡ XЦ­¯“vâòù ò(¾P{Œò3Ì>6ž]b¡Ç²ÞM´Ì¾zfg|½(‹¢¡üF:L•zH½\ü±:œÈÎ>>¶¾È³Ñ÷èGÞxû‡„z›ä€­‡wêfgDÎÍaç³\còåÙ)É—~m|37„.Â(øÆ&… öä¿)¾puàá_¯¯ÊŽ…‡#õ¿„æ{`Z6º¼ÕãTʃûVSdCé]êÆkª;:N¨òhËe ÐY,URB:±µÍU!Ž-hC14"é¥ÌÚbí箟ª«C»:Lk[)[Ä›‡üo+^Ìì²(=äj×άL~£–/Ź.ö[µø4>þ¥ö1¾ŽKš SC#3UEOÛ;÷àäŠn1BÝŽ”öþbˆk3ïÉ™ñ󺬗æu\ÇÔùŸŠ:냎¼&g^aýèß –’ïš íý³B´A*Ñ,}šü¸z}_kL{|ñèÀ›µxH~IÑZÐéDº„Ëz;|å0¥‰B.ÓèžyÀí}eÈBNíßr ñüçzµÖ1Óf¶òG^Y("ó¡ýD_; ›m”\¹ 4ûf}¦ü»:Û¿[¿«hH’ÄmÒ¬¼}ŠÌ„®¬K›ˆø¹Šebß>ÇTËOE·nâ(>âpâO õî)ftqÀ°Õñôïz[ãìúos¦BT!¨6-ÇíšÔÁ¢ö‹Šùá>l‘ò™o‡”¸'Œüc$P9x³œßº›©Ñ‹Žöì.¬”i6céAxðã£ØÁ­Š±ê¨!K–`Ãߥöéƒ}[ɾòô›Áá#AÌÀÌ´‘åIAA‚¶7S#¡7ίCs аsT|2ªj9/BºÙ93Xh\»Iê˜pù »6!¹‹ªí2‡®Ê] / ¶‰¼TZ£Î‚6¨£ÕDü©ÛƒªÆiØ8öúØIÕ«A§VìrùX‹å2¹Ž”fFÂNèsì2c=ü-Êwj§ø{Æï`a{ñQaÕ’yl£¸k›°é·“±>·PIµÆ.`Ïdžj7šê ãéÎ= ØsMËéÓ 6b›$]½ÍlOèÙÐÖ¹ÚŠ8w—ímoöL‘om–¸’¶4Së4.8AÔaŠR€óþHÀ<í™dÿtÈ~„*Ž€Ö ¿ÜªjŠc;{Š}TÞ8éèêc!õÔ{gVÕò`rÅüß)¼‚G$YÌòéè*œG&71Bä± ôBš¯ óÈo[tª¨Í0ª7·FŽºnÂà&JÇÅÇÇèNn( ÂÓàAÄú6NñP–_Çp€Ç#ÈñÒ‚îd°1fQ ]Ë€5¼WÁ¹ò¨<ÈB{3¿ "u¦}(g==h8˜îµ÷Ÿ„Ž„ .îBš ‘õôç[Öµè¨Á ?Ëíf;"f Œ‹–^Ì/J?Ù«ÚŒ²ú6^ÌDZ@ Â#$1Á,¯Ø7æ–áp†vÅû<ƒ#!ÔGjÝûnCMàߟ“K¾K0C r;GaøØxßpÔŽØfÁo?fmæúz†h?~rõQsœ”øþŽõ÷1˜of¹=ªKµ|23?Gn·–maìJë×b\Vf„4Baá9ðáã¡oܸÖúŸ´{8ؼ¨…»N€R•ÈoÇMyôaPFêÀ‘ê-|Þ xjUÌOàåW_±ù˜Jû ðaþh¯#“Aò>Ñõ >˜ìÆ} Æ,ž¡?Š€ë‰Y½îËnéêÁn8ߪ6@²›c¬ÿ_äŸUSöuÊÜž9 ê”4lÓpÖI] 4Ó²9:¥²‚>¯®ðù„™íòs(åSÀóo:{æºG‚ìÐù7Ðí§›¨r>Šyý ­¼CÐ]=7mc¸Á„íê6qóyô˜9üŸdêÛS¿¦;øt1;E¿³®”­ú7çà»Ð¹20À@ý)ò(Á‚Õ¹#í3AÐ’»šN˜J@•I†£+áMí‹,ƒ:Ì"½Ô<­|`V´¨B;Â{ÖwÉ* œÓ šÕó0ȱ|üM+équ¢‡GOê&Tǧ! ö:\:v®œûˆò¾÷+Š/§ ŸÕ§˜òΨ·Cf‘S („‰xB¡°ï -X‡˜á »p¶“¿|æ¥zbz«½¯ñÖ+!¨dD¡ßÓÚ ë“Êèƒo."¯‹ÚnôÀPÜÂU“MÏ^b_M–ÆfjÚÈ»±e`­g ­‰Pu ‹dh“MgG;ª»UÌÄÞ*“aYÔ-3>Ùr¶Xv|S'|™„“¢è¸P51£;ÜgUc/Zƒ;›dœü™Œø ­.àçqçP¬ÇT—rÉQ «-•q:ç­öV | Q+½à-^wN‡ˆÉcèņ¼‘vÚme2ÔØ›S嶃FZ ¸Ú+@a3qA“$J4çHª=PÃlªjŒ·²ëÏl X#Káù ÔÕP¨£¦ò4Yk2º °Õ­ÌÜÈÂ»Ø ©@aÒÃL˜%EWÒ›, ycI±å~ªgSêÛ.¾Èü{÷x`´×r#çÐ>†?Op­k¼èUáb"œ«E¿î­Î¢¶3žg×¥™Ãª(…E4#òã°UËÇâ®,ÎÐa,×pÏÞR4‚쩘ÖÔð1SÐOÙ!ÏŸ«™ðýÊWÞX±²ñL½þmG²1~ü}ç -¨!ßíxRÞNKŽ.&§1æãÔ¼wù )KŠ®¾Ó˜Z ¦ÃÍç½½ f¦@S”£^'ê*¨L×nl(½w¾¶{÷¹! w–~÷7xBQÖ—-¾½÷·g»ÇÈŒâÇ^=‹›gaÍ=‘:JœûH½<;° å`ò.£Bƒ¶³šx©Yȵì¡Gº –oò_¤p¾ºcëïßÙsÓÍŸ9róéôAG18s›#¶¨œSFMÏ£¤ éÈyW‡™‡£$-Û=ß’îB0?[l7ºPrD¤þìÅa ;'U@»ÁcE² Ý(Ì‹Ç_A½ãn÷šTljJ2èÓ­5ãÒ²(kÄÔàr1îö£—\׎¡F­»ÉpÈtwõ¦ð=<|lþÏoaî¿R}$ù7ãÏ.}wä}ΫÄ/J°žz¯“Ùä–; Ý g(:Œ~¤€Iƒ"å'&¥¼É_¯Ÿ5ìÜ«fâÃCƒ¤Ç)ŸÊ@ˆõ<ú×c×[E»S µJYLÁ‚„o9½NÜÒÒ¶‹e-&{bw ˜QÅ'Æx ´­œQ›µy‡h® eÑœp;l.%B…oQ­‡EÌXj—r”#Ó*vù"ŸÂ>¹ºú׸zEÏÖ¬/‚5Zì–”%31»‚÷këßP7™|ûÆû{ óq&Ff††'ò¨ï©¹ï$MY· QúÍ–Ž”§PFí¬e˜¸Cwÿ 2^ŒæþrWGñ¾ÏõyÔ¥ŽµÂ¿›žu§òŒAå¥Þÿ³ D>œ–X!P:Œ×ÊiQ«íwT{[‘Ú|'`Üû½]#KcNÖј±u­%µ-Ké˜C!ݾð©™Ê cêÑ9,#ô£éþ+ž©yÕ5›äµÇ,~¶Ý½¢ƒAéø]-æù6Þ<ÜŸŒ>ÿþ÷O¶ë%¸(¯÷_Lé}<™v~ù™ñÇú.݉}<ùúõÝòTòãžßnÐ1€¢&0½Ô**ÖžÉ.ÎÏD¬"&“jzµæ¼gS—¯8Õ帬Ï:8êáé¥å.u®Hvß–u§ˆ#\´»ßºˆ}9[[”æBhp·g*:ý¿n=ÅËíûv/·ÕÃŽþGl± ÎTBQñ‡_LÂùí÷€­LÎTx[Vˆ‰Îé ÔÞ¾ÝܼêšÍò:ã–=»vöªn?NîÏNwƒšrÊ8Ñ÷øŸ§_½¬–ࢾoIÒÞLj;=-‹õú*ûš<<Ó¢Ô»<^Z{ ¸H`‘‚ „Dø~{•Šè5óÓtà! IÈ$ áÕUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU| R@žR@Ÿëz“ }/­cÚ ìMvš¿Rû3Wm²[6N@ž OÅõ„㜞å>>2üí°“ñ:ã®ë{þ®>d¨v> ÃÚXÁäðxýî 3 ¶ÉØ:bƒ¬(0Š((| Z@é@U|¶ ùðç‡7 ž‰ÃËE;áAÛä6…¨uà¯L(=à îEkoÉÍþþêì{vLç=Í_¡SF¶søvÚ>Þ¬~UûgîC»M÷Æz^ÿPÓ¡6 •üý³ýîw¥G×ÉVó·Ôµ¨•Öv¯»§_—v»ï”ºÿ–Ã:=.‹Õ16ϑۧ^Ãá±îJp´nãÍ3ßÏL§UNóñìžF6~†´ôœª ¦•Fßmo|xk~½+dÏÍæìÆ<ùz½>®îÕ° úª¾ ðöË"ƒJ¯áø|o ¯ºjÕþþ+~Õ´ 3™ËÑÍžñ÷j%Òo¬îÓJRÔ8ÛÉä;õ9™#5¡¯›ype¾º0o¸˜:ªÖ6ï7nÅ#=Ü^syÎsœç8e‰ VI—­aæjŠ’¤ÔÁ´ÒHRµšÉÌÌÌÌÒe&fff&efff\L̰™’!„‰&^feDÌÌ̉"¢¡EEDÌÌLÈQ"D‰$žD‰LÌÈi™™y™•™™™3)3334™9™$¤H‘Q%"D‰$L̇ Õ­¨ˆ ’Ô™™0«X¤€•VšÄÑb!i3YÞ]ÝEÅRÛŠM8ð79›Ìªøü¾P‚Å šÖzÒŒµ¢D§‡Ÿ§×Ì›wWdGÇ“Ö~דɽ°©|’OÑäö’W+wfÞÓz_!HðH_ÌKé®Ü­¢Ñ$£r¶ž¤ÍNޱ=ÑÚõ.~=ýþo'›ËyJ­j‰«¬CÖë°ÓY9uzV"e*o“5ª+³0J¤¥AÍ^´yjBRi 5¤á+YC´Q"ÒÖhj£Õ23Ó‰‚i§y¦É©¨ ©©«¼ÔÔ4Àˆ€5 4Ìþþé#" *ò€ê‘A¼B˜BH2Š H @ daaD"A"A"#DAˆˆÁˆˆAŒ$A@!AxŠ·!1xGâ2ÇÑEpü„Ž8p¢Á'…YD’Y%:(‘à ‹ À‚‹I”#†˜@ˆ$rË0Á"„aaAcˆ³G0€áf8ã1¥9®“šp,($£…p³Ë ÌÈÒ±Žv#‡Gb4²É;;$ÒÉ,è‚Yd”p“…ŽA¤À,±˜`tpèÀ²Ã¢Íˆ‚Ì,qÈ4sM¢‹,Т‡ c1gB4£‚8pk 44,¡‘¡©¨\Èܪ¾ò(<ÑAÚx,èqƒ‡g`3ˆ 0l AàÁÂDž…–Xhãx%™I æ˜prÎHãH"J‚F0@~—ñA™€=Øfñ:uã®—OW³ÃxðŠ ‚‚Œm9»³µ6sZîÞ·_qùÀËÙãÝðà 3LÓœæíœÅ¹\‹·W˜=Ú·ËQh'9<½¬Ç¥&iJDM))0ëX­&DkR°°p®$THRWˆ»2jŒgY“éîŠ"xd,Žlí>a >dÔR²ôJR”I4—ª fešC=b‹JI-§w"öo¡ˆ¸›ŒÞSŠ÷_6ïŽí¤—¦¥Îpç$™’yÎ9·¢Jï•PÔ¦g"+r/• ªˆ ¢ŠÝœæÑFeÌÕ\Ì›³µy1;Än™|i–¶­Û²ÝŸ)g*¯nóKØØÞ0ALÌ1RMh)P‘.‰Eg¨Yi¬Ò”¥ïœÝ˜šZ[Ï&o6¤š¤œšá§“Ç•&œ#à<æ<(\ÈDÅìÓô"6«»›Jzx}åeìåÖÇ/K kýêõ¾qׯí&ì‚Ù»0p)A}A¯ É}ªr™ç2.V˜d:Þ³vÝë£bîSó‘uÁ"²/2aÔQY4Ì&ÖY´Ú‚mX¬;«ET#U‚ÚŠÎó3333330!Ö€Qjá(ŒŠÎŒu›О“dV§O¶÷8"ëf÷ªµ¨Fe–ü{Q‡7]á× 3y£í³¾År‘Ob­îთOU¹ÄÙ1Äšk$ؘò»žsyÅÞW6#»­‚ͼV´ !iY¬Öb" Öµ¨hF˜HXVŸeTÞ`üêº3«"1ø±G,ªØyTç"!ÌÌ‹E^iKaK½rŒl‹×Á÷œ»}·Þ*yÜmã¢3sxCÖTÎZyÈi˜™Çåñ £™‘ *sÊ glÒ6ËÞ\–R²G…$Mò"2*¹G8²ò̇)¢%=(Ú맆ã%z¬žÉ å]l\±Ôq”ÎåÇfTc„w°D+O5*3ª¹äíómË›½ÞFUÌŽn¾——ÊÚ›\Ë|r™·»ÍÜâ/5+»åƒÚ©ÌÚ1•å¤2ÏÎò÷Ó?•éPGí /截 TUúðADÎBÑ@}JPû¦O`’šŒF*ˆÄE‚Æ =AMLES Ã¥…G¹7ueAŒd1T£ H'©ŠƒPEÁŠÄA^%ã3 mN"õö¢É/Ó¤ÜÀ„ D’ZËRœ`p0  ’p1çôÂËÝ®ks_”>Ý’ÿ%•Φ'‰ï£]ÊïÔ4¿t>fËï0Ì$¨3ƒ"’ð3µ@É-[8Pµ×vÔiL¤¢¦xDn7Š5™sc¼_æÖY¢ôïÝXzÊÚÏ”]öα£ÖÙ¢æ_&£òQÂѤ4Ò3ø€Àá‚cˆ©DŸ±©[œ:Æ– WVêÆNrÍQêªø&(TËh‚ TA’ • 9m‰Éìt_öæF#±×+ú&’½m'ü…¿nš;ækKV:öðþNŽä“ûª§íþïoh§7×àG×÷Suqˆ„ˆn!ú›ÿmeàyÜø®>§G\¨—òÿÓV’H¼X›‰hI$H’I$€IÂI$’_£ÿ>wØù·üÇý¿àðÍ2>{;>ÇŽû=Óÿ*þ¿æo. ŸéˆŽÕÏ?¸slƒËñYl\Ùà2ÿeË4ÿ.^_3žŽØZÉr5Ð-cGÞ|kMÖ‡©‹¬±Rœk"Üã6J±Æn"nÖÌÆ<›*[:dÃd1Wé¡ownÞÁô¨((’ŠC2¢ Chˆ²ÇÁ‡Ió¼?^hÀT…€AÌŠ`ºß¶aKE$ùƒšržÉž>>¶Šü?ŸGïNáɃ­aU¸ËðµJ ¼¨c<¹•§Ý£Âô>L:¸„<ƒ !‡›GØóQâ…ñCuc½Õsµ^’¶Df«MÆ¥Ésç1l Ðx\2æxFHY‰÷éªóÿ-v=T?g<¿•â‡;p€xw¨óá†Bh×õéuœvf0u>m$Dñ‚ôb?nˆÆn02~½Åî,ó]Á‹dÊxªMëGïû¿à-<©€ÿ$šžgжræ£½Ç ©QD,ÕñÖ°óí äý÷=mݰȖŽ:zúúÊÇ>]WæâÑ §eª2,&öò‰Ñ—oø–O½;wc°5Ì †ÂÀV*¬jV•wXüÏØÿëî}‡ÖǰTË__ë\8›òÏ~Àà†mœmÌp™B£®ø0ÁI¶ílÄÝu6€¦p_ s 0pýj‚?Gê?Üóü¿§ù)E½z¢.Ž£ü/¾ìò+UüÔ'g>W×ë>—ëßÊZɈ #ô»˜óÏÉ#ø?G’¯¿íy%z´ö«¶uëÿ±!f“Tÿ³þïú* 3þñˆº>¦(¿Š!ÏxáPïf­ÅlÕÂ5?nÕ'#gŒzsèîÝ{‡ yˆ;Ìr¹šŠÑê)7F ›:0úF¥M·åM#î°}¨NyOð<þ 1ó)ÏGP‰oéa€¥ˆIÁÇ¡:nZ(¯–¨Ê9èŽx‚0:*;ÑÃx’åVÿq‡í²º}n›`ãÜ= (Ш‡Â¨¥»—rTe²þ=“wGyªlÊ'¿3ÍLòaÜÀFDËÂÞÍ~gâ–-®§^ãŽÃ-¯×çÙ™û¹=y"†Qþäú<ú2~še/üC}î ¦x˜ÝXbíú=›nM-‚ÎÔ íg¥—IH°‚!ëÀÖ[nµùæ}4ÝÚœO=4r)D¢ÿô£¡RQD4’Æ©`蟹üU×þÏ‚—øçªð4ô¬ìBƾ›¸XŸŒSiœkñxÔ}mšJöXNš DD¬6i‡ºwxLš‰¿WÙ{Ûíz®Ã¼æx“w©¾® Ëºë;KjçI«Å¢û4ª¤¸¦µM+èQ‚ꪛ&Óš»¬Z½q³Ø}=¡úŸ«ÿ‹xûZ{ãSÁóCO~Õ~9\”RЕ¥QBq(i!zh`‘2±’(0¡qHâÞ½zUlâîu57}Bµøº›3ãmfßÍKë¥Ô˼Ýaéðåã×­é²M$òÑ'³¸¾dõÆb*C<ã…¨`26ëC„ÛãËNmíÕlËj'4Ú‰Á¼ÆÓÅë¹[ýL7i”N3æ–ã¼ë!ÔluoÒë-"–ÏtqZÔXV LÁ ~X  "‹eøîg?u¾Ý¶j$Àôý?™ö{æÜ»½ÚcÓ§ *·òǽîúºû¿·½ÇÛž'Mþ3T#30d(üû(4¥±I;Ÿ¡Ûê¢O£çóõ&Iðÿr 1OëÜ}AÿPǬÜsÈúRü¤yo¯²­zþ9ßÐ|Œq¢XÛ°NáôÇ| ø ¬ D1ÛŸ¯¯«¯ÉÏáõÒ“òz;«O7–€|b.ö>[ëLº(Ö¦#€@_w_êþóû3Ìëõz²Ü<Þ¬ý~¿Þ>fþ˜<¨ß ^ï#J„?~ÛéÓ[ç¦^çw?'_ËÖÿ[Ñö4᥺éÛ ržžæìú ù¯4|fv~u}ûÏégšr²_â×äC}ÛüÅðu¿ÅSë¢ùú~˜×ÉÑæN¦ùÛ—ž±ÊO/{o©Ñã4ïý[oºoß}9¬ômºo9¡é—-{R9ž»e¯«‚J7³ÕS>î‡ ÃÖýü";·»2šçŽzÞ×àN#s~ÿÝ_3sï*GX×÷1oržÍá¿s—òƒöîÉ7q>ó÷)êëåãä÷W`@|_V„"/†ÞlºwkX˜ú]›òA5-ÓdÛÏØÛšeø”œ¯ÀÒ÷YئwY×%ÁÊÇ3˜Æ3›È3,*¤g—€r‡8 J‚UÄG"L£9"DrÌm ŽÅ_¾§ˆ^S.Õ.BªÖÙ/Žöâð;œÚKM¥p¥O3g|ëJè†O¹ÑUŸ¶‚õCwªMrz=Ö§S¬dˆ¥·'κÿ#Ô#†ñ§åaHä´C=-èZ˜BKWSE®ÕWeSv9Ü¡Øp½úk"G43™Úú™Æ²•M›hŒ# ÍeLÙD¢s½UDä]†-1¶È1ŒÓ*¹å$-Xx„¼Tfa]í×&o~i)‹«‚C¯uâN“~Pê}å›åû7=ÇÉQ &¨ØT9Îðn—Ô;§-PT~½ë¶Qk"Dw¯»úªMñƒÙ,ã|y‡ý!ýjþÿúßü¿Ïý'3¿øÛ÷+¿-8òßöÙù1áѰ𛇚L…?½üñ¾’5<üº)äh~ˆh©ˆ0êð—/D…ª!­DÔ¼ŠàÊXo‰éÒ@…Â…Žo'‘GÍháŒ@LJ“Iʇ¢Fæa€á\¤©ãã¸>£¶Ì£¿V<ˆÞ¥37¶·ùé¥4@SxðÆðx7¨7vә؈(è„xH×7‘@0Q2ƒz‘ÈpoŸ¨ý”Ò_jn*ËóÙÏZ¿ýÖ_®þÎ1ÌÚÿ?ÌÑ&ƧC&®i³éö9ˆ¦x,‚’wXt2äП½ÜßÃk¤ì;ëüŸÊ·eAáCèr¡D$‘‰›A6\­T‘³–ãŠ`[áýݶÙ?¯ï9h†ÆÕ©iïažç#o&ºSò¾¶UNQ%QNô­aØë÷ÝØniS¶á“»)­VjÑÑ$'®¾®%Û¨Ì~ÒÛI™ÐÈÔ½­:ÔgYËr õ $6qÙ~8ÐÚõÜnïÜ}]û0¸óôzúý¢~î~ ý:§G~® }wÛ™=—õÕì·RìØ¿áx Ißôkà§ù»Öƒ®v×6Ìs!;¿EÍYoÆØXý–Zå¸/Ÿ´<³Žýr]4­3†.vÓ¤v‹\ÌÆ’™"·Òèiæ|×v9ý1lrËkØ¢ÀÊÿ¹FÊÿµKqÇUóÚ8ß³·ïQ¦§]êøGöU‹&©þsk¸‡^Þ!øPÞÇ>Šk8¸ëõ{Næ7gPš7H„1 Õp´£Ž¾ûZ}I £Ï4nâ“…¼Ïq>áÖÃAÈSÃþÀö¿6yi9Ûú2‘åá7>à~7PÖªc½ñ¡éŸSÓ?ÞzGpÏQì|–œÓÉ_â·ñø‚̰E÷©|Îé1€Nä®ì…þ®’º»T}·DW (ŠúxÃ6®Õõ}çáhéÆÙ¼ÏæÌOéóŸ[_ûWf@…ý¿ñ;'¤:?ÞT~OÙ–ÄxU{giË$Äü{`ãE¶Åˆ5!TMŸ.5äÍkZ5*€ª¢ NTå—Îqƒ–Ó¶!ü¾ÿíû´pœéÆr}ß§vtËk ʢ߇¾‡û}]½<·»q¨QƒnÔuì¾çvü sN¾jÃë÷ç-nòâ¬%mR<¿ #ߥuY2d(½<êZ— –Ô#ß³*Ð'I’h¤j§ÖÃÁvŒ%rwDSD¹º TÆèn±êèï­n8½>®Ÿi§Æºsmµ/Ýìsv ÓÜæ•=žJìkr;2óÚÀjmgkLÁ¬€¤¤í&´“0¤Sf'7°jØLoØò£NDp´yM•šÒ" \ÕF– ؉äÊhqÓváv}4éôhäcßt8282H:³›- D3v8ª‹Wm×n$èº3¤‡>>¦Ý~Ö…³òùüýé ‡K:Wf;Pé öìböe¼½/¶2ü‚æHߘöhdÐ>ŸÍÀ|Üx)JùGNr3¯QÄ;uÁ}£qrƒG¦9HØÌ+“ý14þ—£x`Ò'w_Õ?þ½“ÂÅ·„ÜÉ€ÛråÎ:À„ƒ0'¡?,"©Ä€cÇ‚pEpȼ¬Xe™­Xù_;CÍ™‡(E"ƒ<>~5&˜m™NI¤Àsrp Ô‚‘*EE˜¨‡ãòÎ32ôÐ!/‘¶Ùn™R³'Ëb¼ëûZÞfK?ô|- ¸cP¢0D¨ZÁbÒ†$´j2?{þ%/´—fâð=!ͼ>  ÇBƒ"Dê8·/¯ ³L±~”Žˆ Ò@ƒc¬„™T‚ƒ§Çy"£„õ®M=ÿM§5çÐÉÁÉY…~p{=“EÉ"¨"ù;°Î<ÉQQ{ׯØÛïàÛó~Ÿ“øßê£Uc¿èr8S¥HBnWQ?½OÛþáu",ÖÁ™&y¢²Óø&kwéÅè‚Û¿"Ö.ƒo1‘!ùDí}N0é¡ì³¿OïØç¶MO¬­Ý›ÄO‰«kZ)–öø«^ašŸŠÊÉÃoñuÀê „@¡s­õ5CD ³rTVR3v=Ê›N”}Y&Œì735—ôáB™¢$*p@,5¿ç´/JTò´Ó7`#*"fÐöÏNšÒ:Fè~ñ¤»fU–¨øDw:d°ÈG§‡Ù}Nºå{¿q™üM"gø_hü4Ìßภ3âÿ9"ÔÒL’–lÄ´¢ˆj豑?6©„ĺkƒÀPj½‰há8´Ä•¨ÕxV÷?F›ƒÂÃÀý¡Àü×–Ö¢þíÅ»­  ñŠ»h`ðAP [AåùÜFaÌ ¿/%1…tû¼©ÂàÜñÏ/ÌÐÉœxüc§ÑÑE“¢ú>0xØTÍ †|Æ#?‰@])úÀªOñG‚̆vv? ®ž¯žÂ‘BLðüö¾g£¼>óºÖ=;.ŽšŠž=z;Ý=^uן?Ië3ÊqøÇ–Ç»äú”8ù±¾3pãmÌ’@}¢`fBí©Ž¡Ëÿ$IŒ FL¤Ê ‚ö WYnѵúCn6꘻e.\­ŸB÷I<ªá=ùòèì`F0zn@!…D€$FAÐ"=4IŽgFò‚‹ÕV†,Odš"Pþ²¡ÿ1+08% ,µ@‰Dþ1®]~Îí?ç0«'ϲ©žp†o”3k7Üãò0ø(«cP¶Ûh¿Û~§.@€|!wmžæ\ÇÛéÒ¿Ç¢áê›éUΩ` ñö(;µNOóÏw€DxÆüGáõ{ŸïÒ`ºŒ¨–~qå:âòaõÝÕZƒlÒÔ5Œ–cRúS*5{Ôuä-SƒÛ{ö/òþŽ>O¿–:û—š7 ?‹®»¿1Tñ>‘Ç‚¡÷h¹š%ÍlѼº¶ý¿TdðsSûÇqÚN`H0@µ[WÜXŒ7¦ ÔºÅò9ÛÓœ=™±Öüþ >AÝäÅè}é¿ ^êó9¥#%  ‹pÅ$ì.#­.­£=¸)´G»•ÔÃFí¨ÑàVÇ&Y°xÑ1áíG¾{`dŒ˜ƒ ¼AM#Ñ_¹ýA2‰à_8ÏÓµ[þk³‡'+ƒå4%iÎ:HåF™ÌÍ “ pàÑ0ÍhW–Ô1’)ñÒó%,ÙfÕ¤ A"-®1dcEZ)SZ¥ ª­­ dgM¤¬n‡™«š§é±SÖ¹‚ †vÁ›Vàª6 ÜxæÆNÓ]‚hxàðð¥ÚÌóâ`6Óê>bD5+d›]Àfjf£ ·Ü¤QLåͰïÆj«ÐLî<,ÆbaÈ£NÒ ñØ1ÍUƒ W‰‹¿.X;ñ¬»C‘$Ù„XEUбËt€#‘&nôÉM‡Wcˆ`‰åÛÅÅÀ›ŽÊö^E‚dÖž ²âAêmº‹¿\°2qv]åß(À¨z+ ¡Îµo5÷†{g9ÑÙÃÇ'†uRÄż¨Ž…àä¸Gl¨*ô¸ !œV-e™e5WuTp¢²˜Ýæ×Ÿ\È/:9ªíN ²QtÛ’LƒŠ\ˆJ!ÇÙ%>Ý\áŽjfÚw&2ãÄ^î>³ŒóVá“ÑP$§rîç]ò 'É$âðD\3dâS¤Ì'xw$½^3‚&ÉYW¦Æ´ J5öÓœ¶ª¥!Êwè•1Q²‹¥x:¾TDC„—# ,QJʙӎ679è›Î4³zÑbªv¥m3ܱÌÒ“DÚª9=áw»N†¨—`¢¦Úb*bEpèL$2npÒ¢Š4¢Š<zœKý‚\ÖhæMWcyØo\ÜÁ½Cˆc¢È±°6é¬ÓÁ‚1°Úá5¬ÇHÒ‰ÏhªC BóGkñ&“Fôá ì¢&³©«·vʾ_'–†(«Eó(¨?0ˆz²:¥&¦² h!Š3œ°±ÎyÊ$ˆS{ËyΩæ,Çc_™±6O—"3"žI˜ûÇq˜î’˜—ÂÀXÄÀˆa ¼8}E]­´ÖÇ–¾·¸ÿgTQÝ39Mâé*zÐ8-Íû_v€×ÚòX‡šJDDK‘ ˆÄ£$`~Ò\;Ÿˆ"`Ñl/ôŒ2`Ÿ±j"*/Øi?jÔF1TPHŸÍHWt£û7÷ý먉½¢‘`BÜýð öBƒyëEþ¼œ+ŠËÑû¥évd’¿ ~½Ñ;¯ÎŽÏφ¸»ê‡¡óóñoì]'BŠýЦ™U9MÓDoŽóÇœ‚â•U®£­Ò }•Çxž‹èˆ~”‰š×ùÛÚ>Ïy¤×!ò¥wÓïr]øOE¡Nt¡[™Òo¬”ê!Ê‘áË*èžÁ]NB—S(xg5ñASÑ[4Šƒ‘e®ÓŠû¾UßJ ÜÈÔˆ­KRÅDApE˼Ìåt%W¼3"yn®ÔÅÆU©î-—šw›œ\ceCñcs.²ð‘ærï90œÙP—JfáašBˆáÖ®±k½³¢|wMð먵̃ny7PÊJ]ë¼ئ%´'•¼‹SC»×3â(ŒÝJ ì](1B}þUu §¸E7MÔ4¶,ëO§Ù#óöÆK Ø(4 Ç÷Ÿñ^⟑ô¨}/ºªòW*§ùø”ŠƒÞ@@P$ }]]mo¾ÂŠýÍ@¨;=Öï¯8ýkªÛÁî-ÒVöþ÷¼Îh”|Û^CM|P,j‘D Ji ÖþŒ> D´¨ÎãxŽŸºH~c׳âGЄW’iÂfq®p-ã×ë*|W©ñˆ!…%üe‹eo­—&TÕì{jÐÁ=ìçG%Ôûg¶íp†—pcdÀ ¤"[Waµ_bÓâݼÁ–ƒ{lþÓ¹ærýßƒØæ’I—WT3És©Â‹~Á$ý“l¦Ä*`«m·Tw—»èè`¿µövÑ×íEÞüªý?o³r¤Ý ŸùßK Àþ­A ´È¸ ÍÚoœs¬ô8â×sÁ¦éÒîŠ(ªÍ8Ù.ï¥ÎÏ9cÚª…f!àAšpƒ (’‹áF’aÀÓ„–8X›†J1FSQ{œ›¾(r‡ãNµÖ¬‰+0’&“2‰V)š*=)C¤V 0õ2äSæÕ¬É-B¼zÎ[æÜ등b¼e«ÐžýÿýØùü¿ß]½Ýqâ/Úš_Ñü.,‹ ^̈¸‡Nôüwþ?§‰ÊRØF ±@Gܳ܈ÂYcˆ"@ÓH2´KÜSƒ,rÆ‘"‘Xˆ°FUŽÇ. ªÄDŠ" A‘V( \ùu¯42’nì%-7 2%y°x;ˆÄ$¸©»’gR‚¢ у ˆedDú×owÆ~R×Õ É 3R-šIqÌ-šò";Q!”I…œ$kk¡°¤Á´PšS!1È8ChÂÐi-¬Ðç¸ÜÆæñ¹Îs‡˜[^£ŒØp²Ê(¢ 3”4@ÙÄŠ$‚¹Æ)ßüz¥WDTMÞ)f?f´¡n’IEŽE5‘:©¹Ôf%z‰þFÇ 1°Ð’ÆÛ3ªÔDÄ»Ø †Ø ‡îò£#ûZ¡@DU‚?²ÐQQV(ŠŠÔ±•mQ’-I¨þòBNÆ0Þz='ìõîz÷É%_¸âénÄg.RÅr9›"½”i\àÓ/Í›L¢¡áøNÎ3" ¸ºü¸¼ãÃÂI}/"%%/LB?»ü¦¼Ÿô~°Ì Ï(íÕúb‡gŸiWPOÕ)èÝèøp¶*(±ºëÞ8CÍDõ5 .ú DÛsƒÓp|†­øêÄ]¹œ6/´áoYck’ ÐEÊ[2’ûvÑ­ÓL§IÈLžb—kŽÌèœî$íçC”X@nT C8"ËlNjx°¶Ù²U$º`g9C¼8„Órži1&Jnš³"ñÓÚIØ/«~‡¬¾@*·)¸œK]q¤äÔÉYý ·LN¢Ì4á"1Ê\M½[òxÇðHsAÍ4ãY#eÆëGÒâØÅÎqòè}Éʘ´‰i¹%!y“WLš1?À‡dד£ÝG ƒdÌ‘o\·æ•osÕW•QdS!$\3¼Ù°Q&6… ù/¬‰B×2 +©WEQ2ž1òžMÙÍ#yœ¼6†ófeÚo6›uFâžnÙ"Î5ò'9˜Ón:{ÇzËoü\‹üâ€èÂI0ÝÔñ/EÛt9‚Ž5’b¢NÇfÕbEbyžC\ñ²cJæaÆäL³@˜[È$ÒTæE´÷#‰WkŸÍ è\éB·wޤçŠVó2N, ‚“p0phÖ°C«RSÓPN‘ç6†Ž§Š„ åÆÁÔQ/ ës$¢§ue–scJ7[Î[ç9:šp‡Åȃ†š ºIâ ÂÍ,² 5– ^‚çU%-3˜î±îrU_$†Â&"‘÷übPoTRJÙ¢fÈðÐDÏ*â(ÕU@í$Ht 6ÜtÜw–¼Ìr%(³ŠlEhä  i»ÀƒÄÔTëË[c÷;=s˜Úr©àÇ’‰n¥ç]âz“w®.6î ï+ ¶Òu0üL@‰RB[ÌU[ &qvHA¦3±Œ¸™á¨McYdhZk(èq«.Tlrr"%·›uAVD5ãá¼ ÝPfO,T;'u>Ö+dr;ˆ¦ë_¦ç2P캊€‰–$‰E¶-²Þ& û_€Ð¾vŒ'ü/î­€ˆ/é"žÎ›ˆÄ((WÕ•ðeó—ÏW__DÈ9É,–ÁlÍ2 S b:HLt™Ñ÷©á }‹&UÒ‰]••ÊY1UK,ÿ Ör®/DL<¡+ˆÓ×ö_/ñ?êƒãûîßïÄ+<šÃjLÇUroÃT¥gÚÒù±X¾¹È)¹ø–)ô~Åï*“ꔞ¿wÂ!c¿_?Æü_ª¾~f?ZBTÎ0Aq?s"mæݯß~M~oëÈý¿õÿ‹?£ýK•¼«‡û#õQûȆÿ!}6æ9Ýúî÷‘ÄGHè.”~^T!?˜ì~?eÿñóýŸ÷Ÿ_ýoòýy>Ñ1Ÿc=yýŠ\Vöžc«ÀŠƒA†¼WHPk…`ÿ ?ï¾ItÊ29,sÜ1c쇲^‡¿ ‰ÌårìoòýφÊ3ªT^–¹`~Y{0ñ!Y†FVn^{ß3c¼¸Óá¯!‹WBŒºx¦=Ó~8=§04¹~nDç$lF6€,%,‚ÛUb"b©„X‚Ä‘ ",%°.)kP´T)Unëk^ýßëÛü>’ÃXhŠý.¸øÄµSÁ#±­PDp $v‘a#IÆ5°ÄY¤>a&a$AD’eSY¤Î9C±-DV‹T¬RV¥¬Vd q L”Ô@€†0Â[ bÌ(‚n9ƒpAñÒµ0ÓüæwéĶà)‘Øgчd}†mmž*íh¾ìSU™Qx¨]²Í‰*Ô 4<=¸QTSœRª—³Öd¶ ÜnVÈ% !F]Í,hÝi*[W[ji×¶ óÛQ÷&¤0ÁªóÆ PÓÞA¸hÒV7< 'è·ìõ„Ê4ÑÇ+_&ÐezQ‹Ôb:F\l@9f£]\8v}”,Z€ÓrŠœŠ¦ØÂ‰Áƒ lª–w|œ@,ߎ¼ª2*Yè£\9ƒ1¡–Y¡-#;뺂(–0Y±&ÛÌX†ÑqâЕáIh—Æt[ c8(é7C¦öT:Nü®0P æy L IƪELà(Ë,²È@ëZ ðã{û|¶§L{³È†öìB0HAð¯<§g‡íxuàòìÒÿè<›žœ«Ïéôûj `Ž%vNþÞý¤.w“ùrÕÃpÝ\-Á7ä&†óa³²(€åÇ’Òý{±SC¥ªÀºÈ2“ (e‹ ]B`ñçåÃÍ3ˆnïI"G§±åà—çÌæ·ÕŒ]ÀÇ‘Iá¯)¨û}xž×iÅd !&(b*PE¢^!ƒ1#+öŒ\ ÚÓ;öetgK‚f?[ÏoŸµŸ$rº:P RPÌÊ÷ª[† ŒoQ­Þ'¼Ž›µôï ý“‰ìz '°Ýê‰àõkÔc]¶G¿¤áàIöãlê ¶¶ŒepŠAL%H1#À ƒñwä¥ã$È®ÖC‰òÎ*ò ‚¾MØÀÁ7»„<ê%š>>èîƒá|KÛÌØç»ŽG7ußM%µx\=*;‘Î8„Ûd¼n ¾´Pçn0çCƒ’ìÜ@ß p^0;–×”tç–Ï4š÷m7yš£ƒ´ôõ;ÕóôÊà˜‘¨Ô@`ut5@2ìíìP3À"a¼ fçÙ¤õXj\À¡ú̺ÌÌJ!–‰!®/«–":‘h· Œ…w䛜…Ï3²Tt¨,» —0t ïŒb£Œî;‹Œ ÝžŽ0®ÒN;CŽã‰…Õû©‘ÁЬ޹$’ FýÚnÛI EÊ.P¢`“‚cçòñŠwsÁX 7²‘5ûó{ø*çºû9Ö -ÐÒgYf ôÞ£sÚ½.á,š…c€¹=„KŽ!icìüÛlÁÚô [xZÖ¢¯àù¸PlA:µt3zÚ§y‚âük7à7¤@ƒâA=ÁÈùÿpBìçÇÇGÕòÎRg5ÇåÝtŽˆE·—“©ë$ÞeûdÇ®v5‹\˜ê¹6¥¥Ý½@€ÂÖ`æ¹ìÂÏ¥Ü7ÚÅíä„ZeÂ-…i§ådû|¶îX„Ôí§¿¾XÚ™4óΨ´yÑÏZ{Ä4þ Ú¨b/¬†28²” ¡ïWR ÏLΉºÁn³7Ç’Õ?¨b ݨ@INJÕP Œ=‚‘\سã¿I¹FVŽÔ ¦tP¸ÒâŽC3*¶\T^)•ô¨¤ƒ($W€öI“èoj=½úƒB_W}Ø‹UDììgM,_† #X‚ß]jQ š«–ÛEàã{\ ™@c°ùÈ7I»%Ù©n€þ˜§5†BföGvçs‡¾5Àä3Là* ¨÷×êL:t¨`…’PãFw8Hi "cLȶ`ëæçŸ££}ªtG‚,·~®ó^jma“_OÔ f‘àøÓ1àvÍ8z<s|Bù ôùøy×›øè¾,:bØ¿woysd(¼Ôë© A^ £žðs±ÇäpB“Øä‡”Htà9®´´ªƒ0e[w1¹èe4h®w±¢dë@û;¹Ûƒœvq"ª"²6¬1¼£¸‘ºLÚ|\%¬ñ´8ãöövŽ"8›Qµç)t‘ÑÐ܈ƒ,S!w@¢ã a†»Uּɺ¸`ÜÜÃàwG~çhÔ@„À„!‘]t{„yÑ+§)t«p,j=¼+ŒÛ-÷ZÉ™ÚNðL wØL @Ñ9!·u7©Ø’`á ’=YPÞ^ˆbé½QæÚM’ÈvB!ªX# ¥ˆÄi¬2"ˆiÙ!_M‡ÒÝPÂïƒ@ÎŽÌ+wéä¥_6kAØM÷]uÖ¼õº=VŽ•ðÿ"i* MÿÅý¯Ðü<\øu݇vp ÷Q¸àíðòtjZ#"¡|A7ñ @hŠ’PE[­ˆÈð\±Ž÷ˆV[½Èãä•VMwe'¬,PDÁ¸9…n;ƒê«ûi²¤”“’÷•úýêzlܳ‰Ññ‹Qh ƺ»‚Õƒ­0tr¥oûÝ?8“Év\jÏÒ_mæ+ŒÏ!à‡Œb q:¬}±Ÿ@ï0Ì¿Ÿån-SF¨Ê[ã[nWðh}ÿÜ{¿·Èbviç<—v ¯I$øÄ¼ ‘æ¦÷Ì‘&|‡ÑÂ~Yµ6DÉ’ýÈÔÿ¦ÿp»z‹‡Ÿ•HH†á>?ÉÚyRo~Ê%o‚ð¾N 7ç Ê(º*³Áß]åç.¨mÙç\+˜¸\ºòýYÑ¥ˆpá$ŽQæœS™È[Â<æ™°ÍÍx®ñoÇä’]ò,RÔÓ« æÇ*öØ~eÿAOv„ö´¢‘Ç6HY™G œi¢7iã£#fâb¾ƒùÿÙléCƒ ^ÿ¸ß°j™ú­=;Sꂦ™ò09—ý¿º; ½Î‡\ü®¯\ìw¥!d觃¡¹ ÁЯ‡ZZíwP°f¸¤Ðú„ M­õÕDUúêýmù:Û†—ƒãÊ/:×37ÕÇ9²ZáKàÝoVoN–‘.rŸ©àâc¥õÐèDAé©“"½»½Óíëo¡M ˆ«j²n§÷ž±·~]?.«¶IC†fVLÉSsL¿v†_ Žl?R'*Ï#ƒCNn6ò~·¼¿¡®ò¾C‡GAšú²k}ÀÕýonÇ«Ü}£R‡šËîòÛZEç¾L\j±ÇÔù'q('8“Ž.9üm[ÀûÏòß?½Q÷³ê‡Š !P¨ª,*ž&¹i‘iBÚ‚†[aDH‹c$®)Äm!ÇÇâsùv¯ÇÌ>,èº\ÉÁ“‘ó*ÅŒåÛN3YTQÑú¡É5©¨ÓÃ…”Ä,,‚Û,D.„–-›NÎ1"dTHPRT‚% ¦fd”±†QGŽ3šB`Á¸4 ¥ xæLNþ™joíïo¡+¶[”ï^bk»…¨ÄÒïüLØ“y³Âàý|Ô}ãìÏ'ÐÜ;!›³³ƒS[vÙ†¾ÀûÝ >áôäÛFù ÒæÏ¥Qàl<ýI,o(7rëA@oiÆlö;9›¨iƒw™D̶;ÇH˜3ÔpBzõÜL¾ˆ<8þ\s61nl¦ºd‚ ñœYá+¢ºöƒDÔ·\@ĈŠpô¤C! Ïé, ðsõc¹Ò E´8ZïÚd5%NIxê†T‘DÚ~ú4hï@ä¦Ëç N(ÒnÅKèœv¨vv'2‡–¦|¬Õ¢îÒôx¹A‚ +6#ØâÃ#~â+\…+KqWžHP„&d?Í9=œj|æÛ-iA‚·¡¼-BêÞÁ²Ý:¾U22vÜ`Ôã™ìm‘´AFÁ¨ó5¢rº<ݼûŒAÚ–DIÖ”ÓtÕS8>& A×ï×Z¸oŽèšd>“3P&>yë›ÆžÕš22™9Ò%0’ÚíCÞð½ƒÂ<žn£äß#Òð?^Žr=M½ÅThÍzm0ƒ¤ôSìÓq˜ŒpØ$&ô‡#ߨˆ6ùŒÒìˆÌiñŠL,À“; qïëE23·xa;ì¢D`ŒMÎ) †ÏNzF°P&.¹ Ør“Ý"vÎÔŸg)¹ÜáÆëÛ²¤´úÎ9IÊq ½ˆ%0IîŠ+`€öM]n{f…{„àŽ1ÆOÍ›¾F7C&èôÑÙ™‰Ì#Ù‰PÅÔû€‰ÞÃiœbZ:ÑHǺ ª¼]Ö~ôÇ“¡Y·¢ïÅ^¸(=<QÒI œ”Ôy›|’Wh7çµùS3B`û0?±ô!œ¦,Gžñ…@Ý»;˜€Íö°Ú5éûM†Ód04 ¡Pµáxm†ÝÔ®ft÷RpïÄİ0 §~¨ä78þ:lC|Ú›wÞˆnÃÚ2gÛ»š»»ß¢lÑÛ„gž1!LYìÎÝœ8×ɾ„º~ºeÁ¼ < -Ò€Û½½Û€›à3¹a^üP!{›ó]ý[«’¢dB˜åÁ­û(Î5¿/'"²âcyÉØ ""w; Èg4 t€¥s/ŠÁ_JƒVÃ`@´È¢€(P`È<œin¼ã®GºM\´}¾>ÌÀ|~¡|¥ñ¾'–’Iì p¢²ŽÏ€ý1x‡ø…M«øöa·0ø÷ÙN9qÔó“eñLó³¶HFd‚©‰BØÁ@-Ö]kQ[µL[:šn:Ý,#%{]@uŒdj”KeI!4²ø<{9 Š I#Í{|ZÐqºØ˜:÷(õ'woDµr§I`,,$^Š8]㺄¼—ŸÕа­–kœ°àb*i8KS)™,©¹#)}É•œ  ÑiÒÊ ÀrzålÇ  è£MÖ: …%Ü›žˆuà=găFs„{ú盢¢KÑÏ$ûK[g³`:ºb»VÔr,¿myÔâ5§t£·î¶øÜyÇ lËâV¬IE²¯œÅoFÅIp†©›°­R0[°ïšJ&–À\ W5ÒkEÉÉßq2ÜDB2¦Ë¸Pn¸:C$3l‰Ó¿³1àƒ `ã]ÈIÖ7zù¿q˜Ï|Á±yÖÑ)wBµåt"r8Ý"î, P¢Õ¸…„„Œ2tµµZ•LpÖW×7Lš›‚ëó?®ü¸—Ï~¿ß×Ü,?¢)Ô ô6™X†nL‘ñhw¶K™¥Äò)Â’ØÉ]ã$¾Œ’( Ð$÷„˜Zb‰ð¿_à T!¥L/º&ÄAóqÙ.?U,DË¡týx(¦0 ›Þ÷Ð#ѯEB5¢Ö„%-U.<;ÌŽ6¼ÌÃ'3aN¾!ÄaÂpáY"8Xáaû|/ÅÂgriå«®=ávDÏBÙm·Ÿ…B†©É\*DÒ&1˜¹ÚŒ)Ç”ãÇ#T’´Ù¦µOFLúp!erÇ|m‚#??Áüçæù ê%óû$3 ó@Üÿ”ÜV‡ø(CÊ [ûzÓÔ¾ªþ‚ØßˆíÜÛØ‚h Ô'ºÿ›÷g©fä9½8u´Ñ}ü©ø8ºõ l65ø· !Ûíï¨í!“)€\{³* *­ÖçCéüœ:wøÿ¯î|7îóúѱcç-2ú®éÖE³=<¿OžŽî{dìÉ>^©EEߎ.[’¶h˜É†8! U„+!H °XTjZÊ+"E¨”G~×qÎ=õµ“Ö*¦ll4läQDþ[=áÒIDa#ÚŶi†psºiL$’Îx"$ÚÚÜno8Çœ8ÜáÍ8Ž? ´†E–=œ,ãtHÐ[ èf ”¹³Í(Š“!3üîÒ尘NJnm0‡ †Á÷]J ]Z­’#¡¡<"ÛÎ)Xc8Éh¤¸®ðX;T7² ªÙ×R´)ì:2³ÀªNBJ ÂÙAÅèèñ)vMÚ^ÖQÆ,w$ÀR¥hðGrÓ€˜ÉÊÃ\«æÆyG \`Æ µIQÚBì~üTták«ðº›VÖ¶ïü󛯧¯š|šŠ”0c+ã Jè"µB­bÔªMs³6h~ížÄ&ŸéÑû¶¾ŠúÛ媡ƒn0÷ØðÒ'–φ±…¹¹ŽŸç\éß­•ÒZ_[ñía†!ÓgxÌÇH8™˜c££•Æxèíw¼òôl¦¡Ì0¬1­jƒ´ŠœÜA¾VQ¾ƒIº«]°Ç:‹Y,)ž/šæK äß&`è :Ùõê:t¤±\h‡¼ç’ÆE•% 2£ …“÷kÁ¢‚"í¤ôåt®ÏÅ såärŸâÜÄ?Ì_ª‡"ÇilÎDh¼6¾5‡SÀÁ Xðý[eàã¹&¯ÅêCañ{OÔwÖÁli\¨ÓléSq]"òøªTV^šc¦h5Á–‚ïÅÙøQË@·¢‡;æ X^ýœÉŒºçOzU3E Q]¨T}…ÈeAMÊBW Ð¬Vv%VøäE‰!\âGÙ…Yü}sðÆ-åNG,3 ÁŠÆFbŒLò7ž´m©&O’YÉ ýwáòÎc§Å^EQŸÚ“00?¹ëäÇ&AïÛ±ïÃߢ$ÐåNCN}Z>™'݂ΈogbØ(®þaDïÄôBWôwíáyìÒ’m5²Ï*ÔkT1RœìðÀ@‚5Ð;iÀ‰E¤–YÕ­šëŸM©s@š ¸¿Í/¦0Æ0H.¡*À#Rp–lêg2Z<Ò«-2¾¹%ˆØÔqÒù,ð]öPdž¯0ˆ2rvÁÐM/>»“^Æ>™ìÐÎ/.73Êc¡¹Mæ‹L†<ÂÃ/Ìríví‰f¢“cJ Ë*€ÂaltÜZ&hfbqµÚîó:Z‘KÖ‚©HcʯŠRizЩ¥,©ƒlÌÿ“"æB» ŽÙå h*6o 6:´*BEé^î7´ƒ"Ì\P0kî(z ª(2AH[St’'Û‹ÖO‚š ˆâ©‘ñ¶“g^B}Rº˜H1äb((Wª‹d5­©IÅ…jV»@Ï *’µÊ€¡ó Q¤±ƒ D…Q½/BA!ˆ‘š¹ Å“kŒõÚù ’ žybôÆi%¼Ã eAFÏ)ÁœŒ®‰r­–‡h1AŒ%'9» X\îTŠÞÚÐ h¤µ¥Ewâµ$”jâ à©Ö±ø7³?£ß¿‡À÷c88çAò{±YMîTtÖêSÙ7zÃ×ö†J÷ #áàñËÃ'¾—Joq ZÖ L^‰[Í(€dv[ AÜ-Þ¼:jÂbŽ´ñ¦a‚ÙžHœï"DÈ3ÖùÚj"ªNtÁï7 »¢ÿÇOŸÆ´é+~gè~o™UUOøKô¨ñ€VD`Rœ°D(5ÕëØÛþ´LΨËj|lGú‡¾‹¨€ÉŒåBU‰&MÈN_HùŒ›<0£¤èüýœ¶i£§,Õ5…Á †jw±ï3‡¶¨Œ•R!lMd¤ý¹›WM5ðútæ‘'I½õÜßKô9?¼|½‰È’v¤%Q\Z92Ý=5.©¤/Bů¾ÕuüŒ ç™Ý} Y9œN>â¯ówòn®ë`::­éyç»Þ?Òû:=pmÇyšÿ_Knô«ÚBÄZÞ¼/½½›ûÅ&ïçÆ³kø‘Øæm1~Õ®åÛiu.–`¾‰#¬ÓÍaî›·%LìóVÏ#×mò}¹¢HNÿ/¨ßvêèÕ0KOxŠ~žþŽdTÂV Ö£ eb”ZYP…dZ“ DUX䥢,2ÆÒ8…J…ãfŒ¡Vk%1)F(þ×Om:ÓºÜÏÜÜÀ`àÚ ßˆš„¤R‚)(bi9%1¦46ae–AÂ[ 9 Î8ÖY…„Œ!ÙÃI%ƒNY#†–i…[a¦ëi¦”A¦”Bjii ã†ëqŽ ÎsÆæ Gáøv8Í#–@Yb:::,€èiF ·ÞQQÍÒÒt¹DIsöUQBRõQÎTÖï×yΪ^ìÑ%´åZy©íP733r=¤7<Ø„(Î<SÌŸMxy8k ç>Ú’Öõ°ç]yŽý„»ÞÆLv˜oÕK4úï”[„°3=/=¯=Np¹¡ªeÊ``ÊÆ)®g¥ CV¶|+QXÎ.fyÐŒPP­Z€à9Rk7Öeõ¥âoަ´7µkJø³ýÞýƒO€ðÓ=v÷tM²ûÜë0“ÁFD [ /C6Ô ‚)ªÒ”¦$£,XÄE@å³ÕmuØóOšé ×ÏxnÛkOµ¤ã2F86 •PÂáÅofT µdäÅ"(“i™ HlÕ¢@ÈYlC ;É÷‹ÐTaHÈ´™Û|{Qã­¦µ•m¥”lúÐõÇ•ªñ/|’ jFVpè÷Mô©ç"@QW£…TeŒ$b• [Þ—š%wzÝÅéžVÆíÕµï‹=Ã:×Ï»±ú«¨—›w¿=ûPŒ2M(²íšÏs“3W\›~™ÄuD9u1Ëú7Ç2ÐÀÁí†zk±ÔÌb‰CŠ ÂÙoJÖR¹lÉ’81[U3 ´í”@¬NÉ]`ÞŠ4”È™* [$ÌͲ1uj™\¼üƒäɘ‰ÏD®ÂG# é¨¼ÆÊz¸:„Ȳ i%­´¡›ØòÝuÄr£ÏG] ™ŒÅ(o*›¡"b÷rcÄ"e¸ÍR»¤=p.•¡ \Z&ù£«A‡a©Ðœ5Cf03lS;X”¯mêüºÂÁ#žuLïkŸŒ?fíOÄ¿…±9žR‚æ~ŒÁaÙi'ÀJ­=£@¸3D· V¢+Š’ärR(“GKŒZ€™MÒ”Øè„y«™àQë»L®.E\ì$(  Õ4:7HÅbUàÇœ_.œâǾÍwÛÉ“½·x£@¾MV «Òù-­ŠÁ¡ŠZ×G;ËŒ‘ŠM-¨aù_—Šg¥Â¬C# Îè{D!凒Á±‘\:ß#~D`¿kŒš Þäp !s¤MÐPŠdvo5 ‚Þ˜]) ®üp žœsØq“Ü9£…‰ (piùÝ ÇyÒ+¿c‚ïKÝL|õz/áåœô!»¯IDož.Ϙx={uéœáÑb><‚‹¨iªù&ÐD˜hN¿C3½<|Œq½ *£ß^#Ùx±¼°ð6ùÈøA¹žá_Ë%,3¼ß<Ó4Î’©¥båf¸5µjTzPų‹[K×6Ü(7=ke;ŒŸEXwzˆ"¸ a ¨ ¤Ì•Jæª4HÒ\1=´¥YÝ(Š w渢#ˆ¡¾gƒe'êT3Jåx¨Plí£Å°°lS`±@bE5‰Í»‚MІ àMÕ׈ê7&{zˆUð“ᕃœ¶áOÕ]µ§,˜b cgñânxÛyuÑÖL±ñ5̳0.¼f> 8bÑ“m]Ü=%n¥KƒƒLçL9ÌñJ\(Ì3q|÷M¤J`æïK+nÐp-ÏjW:1°d0ªjô“”xè¢ZD[7Äôr™Ê«5örf>’÷ï'™mÑÙ(“ X00wpÍaكױÛê·÷4K:ÝQ(•¹Š cu)¾…w¼PE²a’ßC± lÂfl7žð±kk…ƒðÂg‚Þ´Ï-2ÔÒcIÆÆÆbv~ ׇã J4÷VAG¿Â¤ñéw°ºoGNÂgù"æ½Ü3˜îˆÁ‰ÁܶÄ9ˆ¦zP#K›kªcB"¡®£m\8  Qk½ðnÑ’ Š„½ÉW$HEy£f¦Ê£O!¾xjÒ vÈŽtª/«$í3õFEO¯‰'s¯¤fa>|Á“ãBk—'Àê[Sž(êI~Wv74]x~/\wrE ÿ$4ƒ×ß>ýQgCz< Tôñ8AÚ>1Ž7*#=<'ø`h¿•Ôœt¸ »ÜßYóÊPµ1:RÖtÑB¬o1œiëpr‚ªU¾Ëd‘;ÞÎÏ¢ #Ë·¢¥ ÈÀ@âB”9¾w£œ!‰áÔ̦cÞ«ª Ç}äÓÂ÷>o;ž4$Þ‹*L¶iP<§ëÚÉß@Ù~lvÐ! $jÜYÚ†30¢\®3V¯B¥jŽÌ90Åz´_}qû jï…3½Ùã ",ú]dT¢Šµwº]\ÄÍRÑAdx¥é4¦(fÙ!™Ý#ÕxÅMÜV°´ºíãôÝ#äü’qx¿¿Þpýv‡û4sjkQZÚ¶ÜbóõßjÁ àŸKŽ-º—ñèøuÙÅÛ)¿mººØnhÇ.kW5Ž[‹[ZÈžÑ*ª¦RHS)A ]ÓH¦øƃüMè0…Cæ ¦ €5œ¯#ÜuO»yðšŽT‚8OⲚßÒVÐ/'Ãð ò5® @ÂCä×Ït]mµÝØs»ú'?‹³Éö…ÍÜ>Ìò-nÜ瀙ÉÉ‹ž!ðGÂþ¬ä|Ü?CtqŸó}Dx©ñ.w’U9KÄÏÑJ‘+I¢Vô£Ë°f ÑJXHIºº—Èy"¶÷›ÁÉ ± ‡$’È8`YÚmr_›¼w˜ˆ +â6^NDs*§gãUÓó#\Þ¤}­åU_N¾ó1Nsš<9oXâDïÖ™ÇÉ5òÚ (j 7øžïݸ>:} ú¦ñÇþ?Îñ§Û>ÖüfB…"ìéßÃÕj=Ý3Ô©oþ¸ý¯Y ™Ä‘ª¶« ‰—1ag·Ðw9^óÖš ›ì1Q…öQkݯ¼¶{L@QEÑtq˜(þlº èc8Ic¢‰RK9ÑDÙ'XÑ´4£J(’ 8ÆkPpÖœ$Öv(á&• ËÝnsÇáÍ7@ÒË)›ŒÀ9†”AFšI$…’P86„ÅÇAŽk³Ú[…<™¤ÎÙQ••º%„4cÃGÉh™ŠÁø4¤ÛOÖÃÙïï³`x°Ü,Óà#tüÇì‡Ï ÇP„éíÎg{nó޹D*w5ÊíR ¤ä˜N-j€ÈßZRayµZÖQGÙ뽋æ+–_°Ù<Рÿ%tÄð¦üCé·¨0èsÑå…1>9Ñ:uѼ§µ¤ÉFSQ‹O€¢©Ê PïãFC6õ¼Ý ø)XÄU‰n"âÇx‘Q¾é;Ràð æ“ZV#Â…É’ò­¨~D›F ¬ì `*‹° Ä(õà’‹,²ÂÌ8ÀÀÎú{H0Ç9QÉÉ„Ç~«®²Éʉ€ê‡ë«8‡þvBÉÚ$’«ÒÏABÁîÙA‘€Ûžâ²°tT’Î@÷~ò9' ­;£.ÉòòQáQìp}{Y-gG¤ VÇ£9Ûu#!­èBÊJã!D–ªÜ.ºñY˜F{CùAÈ­¥“gc燬¦ÓÞ}€ …œ²ÌÌȳÔWv·\h4¸Ô Y@kjÓëNæÇÑ÷ü>:tQMàc°ðXYbCAäË6`ü6f`=x Êã÷×kH¯~Bí}Py­å{ûóÃwLv! Ý#¤ÅÙ^J‘‚+´L9>|Æ¢‚'g¢ý|Ïz‰,žëz©¯ 7\±”¼ÿ2¶ö* ì(PyÛM¼ºr¾ß9¹9y]éDzèÓ¬ÒÇG²>uH¤Bn ùZñ%•Rwbí/•Ÿ¸,5ík ÙDä‚¶i À¢ñEÊÄÄÜ"&áÚlTiȸé}ù5Çæß„†å7¸Q…†”cZ°(@¸tpùDóÇÒå÷ßoTQãÂŽš65|àÍà™éA{à†½<ÖØÅÎgF´ÄºÖU­4XµP*EbµJW/µû}üŸ”gëþçêçþçúÛÇFî ¸nc\äø üDE&Eé Ã’^öeCF§z¶P°f )°é nów£'5«¶lˆZU|˜ÐúËñGGèÿ©ü~ÏYJ÷6¾/3ø¿ÇÊí?—ggÒë ÖçuV\].ºàµÔZÄdד>†iß}î¶÷®o¯±ûœ·ú³òmqø$}‰X«1 2§hÃÕ½½onŠ<3ä>.ü<›—~·¬0ˆ¿òjÆ7¾ÑÆðOŽ»Å\œ‘î·„ÑÈxÃd™i'3†ò8àôðð”=pÈ{ áGIcX c•&A%–a@äˆ ‰/rìxzwÚ#–û'ó‘$•Ê—ç6ˆæãî]Ì"4®lÅÄ)z2vï9ž$¼„Vp˜Â+eÕaŽ*Q¬ñZ øÏSW£›ÎZDp~Z㨩Ñé1ïŠï°ùý¿¬‹­ŒXÌ”Á†Ô-UuÎu5 ƒÕÁ/ƒBDHî!Q±A ܰ¡Qa"ȰŠ )‰ƒ¿ñUÙóú3â¾’ Ç{¾>†4A2Íe1&2ˆVXÖI±†· Ó 0ÌѨ¸s 4ÃHQ%Ã\µ·-·Cœç9ÎvAÃŒIIc’0`ET6–ô¹j©K~'YÂÈ_ˆiRUe­ÁÞîåîºíðñ){ ³ Ñ,vL¾ev´dHù‚ˆZaŽª¶§g׈N;p‰–°@#¢Éïìç´æ£¤bBv:–y¤×êJ^4•ç=wIÜLCôºíê^-ùÃ[ w“ŸÉÍõÿ;¬ò·}M¦#Lg˜xȶMœPU•aœæ(è}•P)MÂŒÄéOÐpDÐcgt}~ƒÖú7ÆI…ç£ÐãùÆÃ ¢8“¼˜øûë:³s|Úoª˜ìB¢.²0á¸ß!•J•:7¨QD&1k´çz,ï•Ö•¶$ZÝÄâŽÒôZŒ‰œ+…/4º­ì˜Ðàûð÷‹rß´æ.M*áÎü]Ýé׊<ôFV¸H(VA^5Êi-ò¸¡¨‡ÞÝ&êa÷¨½“7œ6TÐd Ew.¦ÚjØ¥ÈCì{ìß«nNµÜ8å·E4°öB%Ô¨-ãøÿ1( fÍï·(¦*·ãÌ¡²ÍÜ »&uÒÂ’8@Ö¼-Alï“2¡TjaEÑrÀ†" p£‹Ó\ïÃ’dÔÆ‚¯‹®Bªï1΀„’&™ SÇéÛžÅÞ£Ú2 :¾›¼ÇùšÚ-7 QVÝV jàhÊN[õ°5X[=CÂs”x”bù-ç=»ŠwTppèá$Žà]:ºE‘ÇJ ŒïhŒ …E7€©-0v\H‰8‘‹¨ƒN°ÒϹì0––É¢j3 ¤YëŒÑŒ¯ŒØ\¬"÷ZÕ믘  L0ŒQšY^››4{ƒxfálQE´³tÚÓ¸I(JZ„âÖ‡[Á@³ñᇀb‡{ ²€ä6ƒ5 02I2LÜ(r«\%z4"Ó X6‹Jç7¤oqq<Ñ WH@û·X—¦4•ºuh¬-`Þ*m,4¸ßÛêý×¾YudIþUGÇáÀ¥è8ä2xqŒµQ[E4GS[åQ%ZÔ5ÎìÆ^«Ñ$Ñ:yÞ¾<ÂåÍÞÉóé÷ºrŠcƒ´µÍ-Æ¡š¼”í6rÍ\É{w•¤ReP85Ï/‰cˆªÆ‹¤C‹¢Lõûçgͼ_y39=·bi" (l¶®¦è@õ2¥¦óWgÐ+»ͨ!p£@v¸¡ qA½v¦DŒ”¥z~Y~'|ˆõè¹7£+Ç]Ò:Ëql† ºâSžq-ÍÉ›}×õòõÿdzÐϱYfµ]¦NbÄð¿¹ãåózú yXsbû¬õ³d µ—•weÕ9mH^\r%ã k­öЇ{ØÑú`p½ö„´‡84¶ö&&¡á3zçµËËãQ€n‚ ióˆz3ï~o¡­Ÿ”CÏó^€›=3ŒªMÔ½0ì˜GãŽ?g|ê:瀞;ÉIùÎ$É3»Ã*&RÊÜ×WÇwžI¦ÑÈ0sJ,³‡ 4Dœ8"Hå ·ÛÍOÔ¬ÐÚeLH™p¤µi9jT9½K+5eYªˆ²!PØÚ+Q2ëEF¥$Òhw?¹ÒžîKôéëú§×éËî·àEü›ÐëÐìÜAA `²„ËÜøß/û †ùQ tŠ l:8@p£…„œl²[–“¹¤Ž@¤sZÉ,£„ÍeœKM40EÉX;†8Èa·Z¥Š9ɸÜçœãpå³YPXÂ4†ll8i%–pk$`f Á¸ ÕxEÀªˆÕË‹¢sõÕHšê Óñ;ªyû?•§­àçƒÁÙê¼ço"ñ;úèÂYÊkº±X¾ ý·Ó!ZDŸE‡©¬S!¶aÅh3PÌ‹&yå¿¿P¾'θ™×È>J¼Ù§‚Æ‚ƒB¨S¶@=Žüi;ªu+ ùÂÅd-F¼$5i)J `ÕY2F­ó» ó÷9ÙýW4C£ÔC]i•FTëV …¾lÖ7}F·ÔD $ÖZ.ŸÛh ÅIä0©¢Xó³àl" ,7U2ÌÅ#Ã0è‰Ðd \®„NõÉ%Èœ­wi&ÉLÀŠQH,mKE˜ÔÕE ›žbXVŽ¥¼k˜µ$GCùø;ÝÊìŠÐQÙæ’±ŒDÏ9ì¼;‡MS¥- Ç`zLå‹e|0‘•­“®é¶#; VÔJ^0t@TÌ‚—¦4Ý[ç9Ù A Zµ× “)ž›×1ÌB´*0G †T…Nm™=)4c´Âei ج\dÌAâ*ä¡ý»øAH¡0ƒÇÀ^ ÄØ`g8b( Ø¿QY ³ôÆ/ú‰ý<NÒ”;ôçû8fb‚ë±ß‘ÕCÔòÞ”÷fò´Ù&IÞ6ìKÎâžnaɼäG-s˜¢É s†ˆqÈÓK ,ÑX‚4’Ç 4²†’É1¦Uj2¬£‘ÉŒ6°Òw–lÎeÔa-4u‚&jJ¤4,ÙB+:­bf®&©F¥+™Æ²fr-ȪÞY+.Šh²®®ÙYcœO{*?½ÿßø¿/dz>„$Øý?°øZ¿ÆX›èS§L"ªØa¿O I¤%eVQ&ã婉³ÓæHÒIáÆ40ÖÒ ÃŒ Ò‡8 ƒMŽÃM q”p5°áwEÙ˜5†6Û˜Ù|çœnp9Æä¹¡¢Î MàPÇÆàÑ8¦5â7ãŠú×ÎW7z:ž¥ß_ñŽu2¡ù‡F|ª³ÆóÂN¼Ÿ™äª?0è ô”_rLN®¿0’ =,ãjX[û¦ëÓÚ0da¢ä.N-W`Qx„JÅZÝ0CãVÚ×°G™W'g¥>þþ· éYÁ Â<x & Œ¦^¹yK†y¢=Ú á$ Œø)fÚI¹ßT®²{» ]L\õ]Mc+ƒ ðÒPÖ¤R˜½êªÑ9æ´¢1ƒ–òGo×Ãë\;pЀµ‡ Þã‚""I¦ ƒ³ßKºÁ=ï Ti€H®ômf*+[“ºjbS’ÔV|/ô°ÁλáÚç°p)Ê]@š£µÂŲ8¾[qÝ¥';(¸0˜ÃEj²à•ÿ(û°ö>I¬O ±˜g¿‡ Ï % .ÓÂwç37j³:Ô\-ë@t{JUÃ8ÎÉÝm¶H$ðò Žá5çs˜uµw*:ŽÝV êru{d6úã«øâyûm˜ØÓ<ÏCÛ¢=@‡TC}„H«ã1•Ö¼´{7­:þcãû?Ì ÿ÷çî7ÿïÆÿ;yÐåò>vÛ{rÖö¬ê†uSÚ»MˆÃpööþŠºÝúC4Ôø@… Ú$AÈZýOñ[R'ó‡°‚€x¶N²ÝeÆ~^>V ZªçÉÂÝÿÍò¸îÀwYÍ r«çEXUÚØçaR,¸ì"œl£µ¸%ÂÇçË·.ÄS&a©B(D©£Ç£}MñgnÚŸÍfƒn ,&1ű)e)e9bá0öìSF¥6Å”à&Á†ÚPÀ,ìØ&MÝÀá2ZX‡PL:,Dp]±ºš0ÑAË)5çd,–4YrKAÿ iX8!‘ý/N4‡n=¥9$ˆÁ‘Ü–ˆ€ú¿ûh¶±Äy°€B?æù÷&€Þ‘ ƒXL0U`…(‰Êš"š«‚%aK0¡fU²˜‹…´©IL‰1TÃ"b6sìØ2h˜)¾YB¶£Ô(˜) p‰eJ!e«,£…˜2’†¹êllYF#)±…0ˆÌ«j¦D)f FSïï¤ÃpØJ&ÛÊh³E,îf†xna“cqÅC"` 8a(2Œ¥0Jo¢`ÍÁ„ÐÊSE ˜a…)L˜f*)DYƒ;áMLˆRÊ ¥–hbpY@¸dò±£Q#ÑEÐÓÆwÊo¿'òDAD|_iÙw3Àîº"ë»ëÙÕ=JËêz~Ꟊæ±DŠÑγ2D™£¬R•¥LD ¬«Å!•^Zf(Ï+ÕGvTVª­P"U+rM‘Ô6B_7Ÿ³ÖVk%SãóÞÄ=ÏEùó¶Ãõ(Ï…íþÜÛŸgÛgÎd,ƒ ¨SdXYÛˆxs£žÄÞìÙÅ—`À]—{žÖÿv_Âÿ‡×Ê €j&Hy]Ý‹q«GZš»»ÐÝr+ÿ®?&q¬Ü.›TUWo&„2ðé5L¯ :…u9ÏHhìkuXC¨†en+‘ÃÒ«Á¯ÃO—Aù]øðËâÝyaëµÄ×ÑîíÆPÇ* ßñØß¸ó :6Ú¡$ñª+T¢"ƒj üþУj8$¥Ám\ö/Eõ Þ/¤'ÊŸWÉxyÓ¶0P1Y/ú³×ž?5Šûv,Óæç?xîj­¶a €åb=|yŸ×Í5N‚Šî+@")Qé”þÏ•Ò*žs–R öÕZ}OWuÈ£Îõ}yìc|$/*t¶¾øõŽÃ `Þ4$ñüï~bû¾Ê7Ç«.L<®Ïæadfqõ’ä¨u4–ÌÑžWªBýÊ'Ö¢Óìh? K¶Á˜K•Œ>Žu–6îé•ñö¿uz˜ÛÖ‚ ;ž¯‚‘ÙªmΪY´_AJÔ œ¯BÙêyé‹Þ±{;=~÷ÇE¿;]ŠD˜Û4ËD½iý[>•„Q„•½¢Ú&n4ß­ZÈ$û?¾ÒßÁÚ+MFó[|~ª@n}QÕŒòž’çuþÏCa\R¤cüÊ'òPåƒešÒ ’ʨ.2ÉI0uNÝ{sßÒÕØÿò-2}9¢[´r®³» ½öß@‘ÐoýÏv6Ϭe<ÿú[OÌm³ÓÍQ®ôCmÚièx†ÎÑ2s2$Ò‰ÔŠá΋r®Þ9´V«Ç:cÍe p—T–aÛTÍv§Ý ç\²vÆf&§ŸRvzÙÔ*È4¿ÖKtV¹p®†àÌlh@¦Ó'ÂÛôô©n›©ÝÙŽ¢/Kõ­X& ôߌâÉÃWÎú²ðDÔ yéç‹ÃÕj;· ½Û™»Î­êfªŽa©×¿ÇžYmâÉï‚ çÔݼ¥èóisÍuiW jY”v`6¼™¶tØŒÊ(wà‘Í #4‘«=a%hЧKøçÑ}ÇÄ~ûòÿ[ü»~ÿQÛòŠ$Êp޾}\uæÆ‡·Z÷Ju"XË…@@Ò«Ò}GZ£k™õ¶Ðƒ:¡l``Óžš­L‰¼ù© ŽšYrµÌÌ_EÐü/žŸõ¿gîwÔ_mæÿCû?õ¯ÓÀTÁë»l½üýÂÈÆöì0qpf˜ŽYWE@æ2zjŠ*’yûåG¯NPA„§¯Ü©ÜÛ{ í<ÅvX@«¶>Úe^­)àšÉ'òÌË3ƒ#ØãIþí· ÕW# |QPÍ-ÇÂŒWÕ4álw¯ž‡Kó¸õð#\U•S¡ô³R=þ}6'RÓÜ^g¿‡¯}Æ¡l·=rP7F†“7þj²ß‡ìÙ+“è?~¶´|uâÈ1Ë{NšeÑ<:Xü6À¸µìÚUØ&û"¨à ákcÊé„Îvè×øïgN¸}ŸÕç‰q#G|Ûéhì¦m]‚dF~v¤s‚Ss "7ˆËÝJ@Íbûò ã a’t2©Þè8RzÏØøp3øq@Ûn¢Š· ®êŠk”WÍ®ÕÝÿ{Eºí–­8¥(Ù'Óþ'þoé}®Ÿ{àøyþÒ{Ãâø_¡ÇíÏo–÷˜`ú@â~N~}([7i¯ªÿ}úÝzˆ'é´†õ`Ê…š 8‰²jð=ÏškI±ÒLÁQTn…?2ŸÈ’>—ÓúSêëÑ7Dø> *ZÖ‡;ŽÈkáááãÝÙ^=½‰Û×Dë –Yt{¸ðáy2€fO}7ˆq–H Ôñúni¼ÍRµÛ“ò×wÁçó™GGÔ0Ý:è…ÉzzS™mÎNS+!ñ³j§7QFŠ[â¿]ˆý=•±¾w¦ÍŒdg®š¶ (bu hצ_5_Š’ÛdÔ§©"ÍdÉH9Ô:CÒŠ€Ï=jØz* ø[:FÝél®(Â~Å ‰¼ê¯|¥ò¶…+Ÿ¢\e|"«gŽ¿8aùj»aAü.³rz¯mzqq+ÔÄR•ÓЭ,ŽÎ ¬6À¨ï`òëøÓÁv‡Ñêççjøþ.Lš›œEþN-ÜbBi¸á 9ÐòY¸8Sn0Ïè𥷿þÞÅ=7+›yëï•î"d¸=÷|& 2¾$ˆÄbžés/qˆÈ ˆÈb! @zè©S“ˆ'ÀòÂwߊt 9A€”Ê^¡ ЬŒ"A|ê(2‰$ˆ¸o[ƒß"ÄPqRÒ(4aJ‚„@"ƒ ‚ƒ Š¢¾ Ò Ø`UT¡QC_ÁDP[†£",€ØP`ºJ ÃÐ"ƒHÒ"áAŠ«Jˆ¦p!$EI@D ÅYj„ŠŠÈ*H¢DAdAIdR$@‹F"Á„ƒI"ÄbÆDb""(È‚ DЉ„ˆª¾:(6 á@(ò·‰Œô£Q–·¢«¥ŸSN ¨~têò¨¥D&xIO×üÞîßÎCuEU7¥×ßýB@š†Òà<ýôtw ïì_é Þ›‘{‹½ò-¢žÀ+Î\bâvþG®õÛ[¥A 0†\ûÜÛ½}½¬\ §Ä‡«ê±aÖ¬ÁÀä Òt°-¾Ñ·›ŽçÌV=Ÿ_àuÏ¥@ê…^‹“"#žƒÈ‡<-z_Ú]<ß´¯ @ƒÛªö‰UÀ?+gRƒ Ê[†u„æ\:P×ë©J€òNFr7ׇ‰ËÑÛM—qÓü\ ƒš4ǹ“ë˜P[ ò KXbiœ±UUå|%nƒFºƒVE‰Ye’RÄǧǶÅâœC6°m¨¦i~G‡ËÆbEŽ`"ô˜ïKœy>o±Nœbd㪠Àû<Óg˜Úµ /eˆ`‚r`ðb;&ÀrHÕù§±áû¾?šûÇï{Íþ®—Çø¿ö_‹ï>nû¿ñþ/Ýÿ”(=³×Š ìÅ"¿x(1RH‚É$ 1Uð‹ö‹ð…+ ÄD:¡AÐPoo›–_˜@% …Å‘G˜¯6‚jÁ¨"WMZ¢4U6âÆ!z´Bƒ’ì÷ƒ±¹ƒ4P—<Â%ìd~,›êN¥ÐbÁF0ˆ°ATX„ˆª€«!#‘"! ¤’ ȼך6ϬZF Á’(F0‚,&ʃ â7A±XrÚS–Ɇg$4‘Qq,AGhÅÉPhPy*©˜ lˆH "Dˆ ªªªªˆªªªªª¨Šªª ªªªªªªªªªªªªªªªªªªªªªˆªªªªªªªªªªªªªˆªªˆ¨Šª¨Šªªª¨ ªªªªªÆ*ªªªª ‚ªªªªªª"ªªª"ªªªªªª"¢*ªª"« UUUXÅUUVAVUUUUUUUUUUUUU UUUDUUUUUUUUUTEDUUDDTEUUDUUUUUUUUUUUUUUUUUcUUUUQT‚ƒ T*ÅV*°PM¡AÈ(‚ØP` ´¨0Q‰zá¥è‰L¼ mwX ÛQb&v 8áæ)Á(y…dÿýû¡á™ ªšÂC|So×]¼<1ËŠ  –Pœ¹î¡åkÏJBœZ‹ä)ûÞ9ùºpI3y§£ÑÛ(ÊÂÉ:3ãk"mÚaÇ¼ÄØL},Y­D§¬’D!9§yˆ‚v:pDPTØÇh`JºK£23I]P ž°ãmæ„“R&Gt¬‡F¶´)fпŸÄ»M¢Ã/É3bì2è%1‘£DfƒKx$ Ù1¦À×ùrýBa eùƪ¡/`µ„JSj(?PyGéïºi¦‚_ºÊ…Ї}VDT @d% 0†`„2‚C¹£B"IÇ8(f *ª‚ŠE˜“[¤4í$ t,x¶´’,Ò‰S)ˆãÈq-•hÅ„]i/q/ªßX [J ²éP‹‹Å«ŠPW` ÄAº÷‚»ó¨D"lTæ¤'bŠ#Q*Š«TUTbŠ ¢¢ Šƒ1P@DXª¡!#Td ED'ÉR1EЍˆ‚¨ª±UEUF( ª*  ˆ¨0cEŠ« ƒ!@ ÈŠÝ (”*©º `ÄEXÁB@YEBRÅAEUTU‚F ˆŠªªªª¢*ª°`ˆˆˆªªŠ¬b(Šˆªªˆªªˆ¢*ª*ªŒTEUUUUUUUUUUQUQUDUUV(ªª¢"*ªª±ŠÄUF*ª¢(бEUQˆ±ŠÄQŠªªªªªªª¨Šª±UUUUUTEUUTEUUUUUUUˆ"ªª¨Š"ªªª¨@Bªªªªªªªª¨Š«ªª¨ŠÁ‚ªªªªªªªªªªªªªªª¢1Œb*ª¨ˆˆŠ¢"""Š(ªªªªª£UUQUUUUUUUUUXŠ*ªªª±Šª‚ˆÄ¢*ªª¢*ŠŠªª¢*ªªªªªªªªªªªªª¨Šªªˆªª¢*ªªªª©` U*ªªªªª¤`¢ª**ªªªªª«ÁˆªÄUU`‘UUUb¨Šˆˆªªªªªªªªªªªªªªªªªªª«ˆªª±ŠÁ‚*ªªªªªªªª¨ŒbÆ*ˆ‰DF(Šªªª°HŠ« ªŠ¨ƒRI$’HŠ ðâ¢;BUTpŠ „ïMGbõ(ŽœÎIöâ $DE‰F‰ ˆˆ €  0`"ˆƒATˆ‚¨ """D€ A"$ ˆˆŒ""AAD‚"$Db Œˆ’"D"$"(0A‘ˆ€‚@$A"DTQUUQD‘"" ""ÉDAˆ ˆ‘""$$DADH’ d"2"¡ŒÂ°ˆ‰Ф#‘‚$& DADIH„ "1QEQEEEQR*(¢Š( ¢±QEDd‚¨‚ª,X¢Š(¢Š(ÄQ‹€ a‚0@EEEEa"(,‰D Ä" E €ˆˆŠ Œˆ1‘Q"Dˆ€@b1„‚ ŒA$H„D‚ ‘€*,’""DD!D@E!„‚B ìAÉã´6#'`PQX¨ˆˆ™ ¦¤$7$ÕQŠ$ˆH²(#R ¤ì‡Ñ@"1 ²A@‚Æ .`Ý‹Š +P`‘))@TA"(?)<ê)±7€Ðô‰Ú: ¥.BXªŠ¡?m}渖¤³ÔT¢SRÉ„5MQ•¶7Ñ ²©rˆ\K©Ù| %«¦y |ÇP¸“*éŠDRÁ–Ê©$èšv¿Þh'XKÞJE@ÈÜi‰cvByî£BC „„,­ ô€\LA1­Ó( ÉËîsÙ3 ° çNwV3×v•fŦÿ¥RGb $-6W·Â00BR‹É]ôÜÑI«im˜Òˆå’¦ZaP¢i(*8ËTÒb¬˜’¤XT’Ù@#ª†µu­7%²¼ð–`b0ЉR, €µ&+ HQUdPžZK A¶ÒÊ»ÔIpÌ(.#²`nRÓ5­$£j©L)XbÛp‚f)[F…B V… *‹ + `âAbÁˆ¤¨IP‹Kv†k ¦Í44k0^Ç_ákm6w2”Rm˜ i[eDÔU-h0£,âkXÄ-›S$3 ÛZc<&µ¬˜›01˜¨DkEJ¨’ ¡5Œ]m­bjUزçñzKùþæç×úÁ÷ðìU0°›Ë5ÜÎ~÷}uLû³î§ð7=l]ÈÛN3Uì`*TÞQÓˆ¥÷åO‰ýÙT¬jÔ?”L_Oλ™—†®wÚò}KQµHá|½¹6-­—JÉnÿ{Äç;?î·Wå8å–ÉæÎð½ 1œÜ Úž…6Ct¬®Â§«Vìf•TéŸd =¸PDb"§ù4ii‚ P ,‚ì\LRõ:ZÇÙÚwèó·Æ^'º7€Dæ›RŸH݇ôÝwè*un]]£ÇñÎD3ñÑ^­%Uë`r/„D:.qz9ûëû»&©»_ŸÜ'ž‘ø펭»~›ö¤1" P€b0Pd«"AA‚¯iDù´3ƒþÛ8š8m½*£$ú$(5`QY^'Öúxs`Ç» Æ&½}aA ×Úå5€Olû<芇¶64Ÿ­×‚ƒJ @Ï’?íþ‹›&P|A ¢ÀUT€‚=’Ø)PÐDõ™E9Ó— M%£ÁQÈ"b jìð¦ú>†ƒÂEDs¡å‚õßî=Éo·ü~aâ—lH=cý q-æë34oó‚K…|¨Òåaÿœ6pIbz±µp[,ÝÚÏÜ‹ÑO'ú²ùu±Qzü‹î"£É‘_R€Ç8Ó—,z.ë`þÏӻޡ>tÀçæþ]Uùÿjc®þ½.ø< öyÎ3k€ Ÿ Pq.%ö]¹þë ƒ‘Qµ’âݺË\ž†¡è?qP¼Ér‰1I„B"AŠ¢ŠŒ"D"Aƒ*B !DžÜlm~©±ÏÁÛKP~UPWçýÇKÝbý¨¨=´þ¸y!‰£”š´h ‘pð¶~ªÏ•÷›ûçÿxó>ç.W-EúÖ‘? Që«Âq/Œ„Yá6ój¦%´»Aûc”ñøÕUÚ‰-Õ’rÌy‰â†M¿al^‹Ò¶ Éä…ÀÆ ª¨€ßãLz”T¬oªòAüp¿ûüþ½ð&DQC ¹¶/òýü ¦‡`C¾ï”T;Æ *AH,V`@A *xj"šŠOq®`þË(ªnw.÷õú“ˆ|jíä7¤2§ŸÛ—·—àxÔ‰c&™J& N1IŒ>±'Þ”™IFbƒõgc["ƒâŠÉE8J8Àˆ‚SP0@µ¾˜§‰1”#O´OKy‡Ðs*©7n[­ªþÏÔö]æ·î»N÷áìëi÷V}¸(¨euQ, <³t%Н9›ð-ÙœØ`”~ÇÝclq‘±B0‹ 1UR (,R@X¤ ¤R, AB,U‚Å‹"Ád‹A`°‚€,$X)Â,€ ,PR,QdÁö?»ñoçNÏ©¬R ˆPh¸PtÔ@‚ƒéÊFE@"@ˆg ‚"{¿ìÿÏ„¨bÉÜ*dPP¸EQ^àTï…@ÀcøÊx™T6´=ʾM`"@D¼EQ\wIÈЇëƒEA ˆúâ‚(9®Ç®eL¤›úJìΞ¬HÈCPÄën†…þAÕTü–û²—cí“3Þ »ûj'úùVÛ±ƒþ€°íE÷еmç·‰«øéÞX8½.@ ¤H˜iCÑcd" Ä(¬â÷ÏÏÙE?û34‰I©²{XfçG`§¼°_‹ˆ'ý•zμx ci$’±(-<"=» Ï…çruw_u÷^~×B¶‰  ê"Án¨?a'B "ƒIUT‚‰K$Eihi@‚ƒǪ —;ÆòJùÛD!Ë…”U Û€ ˆ â"Šg_HçÑÕh d(=¢¡¨*«ªð¥@”’öØ"uŠªÛ8[›çuðê>²“È“Ö×hu£Òí—.¼S™b KI9DL#€í¸ükàÖ‹pˆtÈìвI› .Ýž 0L»›/Ûý0|³S”CùKî\øjåìÛW]â²÷‹…ªtpëÄ„ûš.Ö ©ú¶£ôëtº¤Î*( W‡övÃÁÛ~hyä{qråEDàȲOÌÀ¶^iÕÞ„ {!¹‡»Â[žQ]s÷A“9ËQúUUê@³:Énq$’uƒdH""Š‘"‚!„@AD Ѝ@DA @>°Ÿ—ú¾F,Rf+¼…I!‡cÁôõ2õß½¹fÜgÇxZÆÍÔâ{}m÷„ÙËO4ñ:æxˆ"g {ˆgèêNÀNWôü‘b22È|=,÷_$öf4ÔKUæל8¿Î˜4ùºÀ VIö}  óL½H^ÏD?áç¿ë­þÿ‹ˆ6ÖÙ†}Ä”(5EÅé0ÐhìѵÔÅy`Áˆ˜ŒP )…‡ 1àÅw>}«î2™‰þ#Ú¬î}w­_jþÑgÈÐÐyX ýT §ËÈ´ø¸æe„„lÄèâBúA€% P¤DˆH'OÚò*«G’$§\ßæðæÖÒ<ß•ùJ†MAAÔ@#Ùu¾_œ^ˆêŠ@b æÄ(7 »üKïø•úiµ`¾uÖ˜'Ø¥<Ìì±õÔ€@mðx‡ŽÅ » ï_ÜQÖeÙŸf‡ùúRu~[¬¿Îm4 IÖÕ.É·÷ï~ár0½ä ±L„–™ÿï@Nãc;aºJÀZøç×4#µ-ª«úžçêæïÁG¸Ñ Ö Q‚ƒÏÅj €*þ| $‚¶—owôµ{çüIyljY®ï²ÇS|~øŽÓÞ9¾óÿ¨*Šü@ÐPõÐ BV1B(«$X  1URH~Pãeà'ûà€ ‡Õð3Þ|åò‘PWºŽœP|1Šå«ÍE Kž¸û‹ÃGùòx€ Ü-±€ˆb:ÙO©_hù¿"¼çÆ·gó«¬×y:6*­–ZV‡ë¸É€Š—sзY""2,AùÁéY Œî÷–·\¸î.ˆŸ ê¥sjš+*€=ÈP À iÑt\'¿g—øÿ%¼=5Œ2jù/¶ ¼h\ÍÇ`~òÔº/³'…—›Ý©n£ê£"ž%( Íž0&º_qÀ|ÅR±òœË`ØÓOqúôð‘‹c÷¾'´ê±ƒ– HÈ-@à0CÛ4_îYޱñã?ãSúçð‹YÚªF,üÖ S¬þ/ÊgÁ ÿÏ ðdAú\šá «ø'#Â<ø ûž˜ñOè¸\†¬42×4Z¿«þøºâã*ïcΞ|P§ò1ëÁž–¥ü•é¿>ñú´xß¶¯îɇU°Í§ã*æ^T|?I¿>vïáºE…;ÏÂîö-–ò‡Z)<5SÐ"–Ž92}Ø"@ã@±î¨À&N*ý+= ¹Ï—Ù|Ÿ X¸¨o?VßЦó6ßíýÆ`À_ab¯öTé}·¼“NÛ$6è zaý?íˆ ê¦`KJ!eýÏ„˜Eð¯{ê¾­*¨bTVí#Þ È0Py«Ï &€~ÀQ A@´Ä(5|á‚€üô ?‚Š(b60‹ùƺ‚…A \("€iª´Û.ØZÙè¸>ŽÙø==×ü#ßüï׆¯ÅçŸ/çôðGŽç2‰ž‰]ÐÃá=Çéë‡o8F †h<1A›xw»bä²K¦ ^ ã ÀáN?pe©ðµ8¹¼ÓÌI¤ö\hŽŒT/ÆE{Ç ŒÌ¸þ;x•.{žõ¸¢Ì OÐè"÷]€•±`í{i ßäÿû’Íó‘c¢âr0]éh¢N—O­ÎÉvIT'Ù¶-è÷¿0.0wýàˆ¹UÀŠ‚ºb"¨¯fk(´ïÅB ƒß÷¤.Éù»àDÏÚ H½þ™Inþ»3Ž(5;³”@%Á+Qž¿¶.K¦’ʉúGÉ„ÄëJª‹•ùúÒÿ~Gqš.Ù=žæþÚÒq&u‚oõóý¨Õsú/¥öv—î€2¡ç "˜ €ê È“…}ëP"ºn™ÚžäFÃM1ÕÃîdœºï¸4÷Ͷý¯W_êkg§=PD¯ÀHW@„€ p"›Ý/%Oäéÿ79Uú_Û„éÄñ„ÈV œøðDêLï/’iª9÷øû…Cdbƒz¨¤ïðH\=‘ï›9…U`)þ,Gëîù½‹“k¿ø| ÑqÂd$„H<ü`àYéc|²Ð§X›ó8öñ±„À@àãàÊ` ȉÃuι‹çæ+PÃq#Æ%ÙwM}^ñžÁ9‰óÿGwê=µðz>׸ø>ߪô¯ä‡Óî¹p•ð…DTô€ õ‡ûø^Œ·Šú$X—Š¢žõ@…UjÀª©† ¢(Î_WÛ‹r-âƒÜjëyáÄGkþÞœPrŠåfü’`CÏ/¡ø&¸ù©è’^W¢½X¬-4÷uþËÒšStÒ‹kT‹·‡þõî»î, Ó¬ãùKnU^«6 ªã‰yx Ýu ùŸt}÷ìy|N\Ç3uú?õäšœñçÍMTÍÊk/®@U둌Û}Њ† "o(WÉ|l{€éáA´Çøp  ¥`QÆ=]€`X®ýw¼K [ÉzöxÔS[‘Aà~¹VìÙrvòBãÅ÷GÚéü Ï“í²üËÍ çÛàJ%U~Ýj™—#'ŸË%Óð O°ñyæ:LÀôr#(@AH<,„!È’’2"+¶%ç·©Ÿg°WmVf;TföyFµvJØ 1¤©¾s2_ì]ûæÐ T’½î‡ÝZn+c)á`ÍÀ‚ìô£Š4ª¿–÷ãAWJ–ǽ@WLLÉÞ_rõäÅ4èl¾Vµ’8œe|t« ·sÛêdûµCùý7òý¿¹ýmçðù®”ö§‡JÔêã*¶ A×Ö#„ó†¸Ï¡ò>}Ž¿ÙÁÈx5ålÇ O+î4lf‰Ÿt")¡Ö €@ ,\£…Aí4,}}ò‚ŒV(ª¬EH¨;ZT¤PˆŽâŸXŠ‚¾·IQ XU3™=./ø|­ECº.E?í—ÔŠ¶Ö ˆÇ…仆=l!îËľd8Àk‚Ï&tøFÉ– Zr:sþL”í-$×Á TìöŸ\Û—h‚ª£,€ƒõ…ŒÃpò‰ú”0^}_º ÇË×Ĩyè¢ä{±Ü÷šÅF?‡â‹¹kUÉji|Ëß'd¾! v“Á¿œH È!˜d:LÙ¡ë³Ê¿74Áï4~g’ß§ôÖ´=N€p±‰PX((¢Šÿër<þ/óÐ'ß§ð’[@¶„ hKh¶¶HT¬–ÒBÛ$ hJ•!m%¶¬© ÉR•!*V¶„ lP+ [a m[B´ R°…J€[HЕ•$–Ù!-¤ l!m!-¡V²¬„¶ÂT+*[JÉm!* ¢…´*T–ÒBV[JÈ[a-¡%´*T • •€JÖ¨T$*VBµ$%@¬!m’Û$*–ÒKhKhZª­’HJ’²BVV@*¬*BÛ!-¤ l¬-¤¶ZÈVÛ m¶„¶–Ù mJ°RKl-¤*[@mZ°j¶…j´€[BÚI-²JÖ•©¶É h+Y*Zª­UT1‹¸À!Ö žüT÷ (íȨ+ÙÕꢗªŠwgÒ„$!#0èõ›í½íâXÝ~¾çvyíÓUmù ÷”Y9Ø©adX(7ÝðuMZîyòâ˜üM¸‚a ¢Š( ¢Š"(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(æDªìµ$ ‡ÿnøzþÙIÐØ<|ZÏ Ö ¬ê~ÿÕãL¨§!Ž…î¼›bwE—\ì@àA@V!L)‚™0Í-)l£¥ ßqåhx]>÷¾Ñ=FDöþ§ô½OIÖnÞ/ ôü)¾ë¹(üïòì„° à"¨‚ZÔˆ ºGyØ«” F/UéxÈèé“¡ˆ ¬] ²ú@‚()¦  ‚…ÐP{ DÒJNùPB“ƒ×Šªöàˆ$€€%âƒAE²‚(P  @ˆ€ O¨.h€ߦÕCˆ‰&`#šY îºP ØP~“Ð ŠÑxª©Ø` **DPǨfÞ ¢ž.ši¢ð¸§ÿÚ²(>‰o¿pG4ÜVy$ë©Ƕ{$çÂnªI žkˆ½ç˜r?¶‡1ç5ˆ#ÝQ**5”£U"%A¬}W E"ÆŒ*Ö¢Q¨e¢âLGe`£¸(.€oAä AÏkªªg'Ë€#ÚºE|%j´ÏJ„@óÃH± £ÆöØ´¨†¿a/h¥Ñlåi`¯r«^GŸ÷c®È°‡ò0 `¼2,ß§¸à wÆö¢ƒí{/äìDêDáa׊_‘z4C,Øæºß<óÃcïδÚÚ˜p<ç,óz+¬° DA•ZŠ6Be )n»Ÿ¼´ôÇk>ª÷¥œjÛl·w€Å.f¹´ÑÅ.Á²{UÕ”'H·,ǘЀÆÀ‘ ŽMq8>ƒFáâ‰2¯ðáUG[ý_ž~>Ÿ§Æh‡Rm” À,;M˜Çtâ@Iª€ÜE"J ØáiÂ]̶>²ûMßž#ÙyJáè„PïcÉð¿°ð_¥º;ï¥:¿‰ÃåÀÂÌé蕨!¥ÙŸ8€x¢}·‹w®€#‡¨Ð·ýÌGÖi‘ꪤ•+/Wê¬càæVHÇz4HÑp<=w"²¼.½û»Út4¿X lTµådƨ¾kà_0©2–é’2+¢ ‹÷ù8'"J /¦#ŒŸ{RÞ ” b‚+ÒO§…$ÒÃÄþŸÍv~—îgX…òr6f0  _ÞÇ+r "EŠôz󮽊áj×2@:íà˜øÍçoG×õ¹ä~—oÜ„ïô>=Âh­g1™ÍGg•sûx™hºÒ÷õ¸"®Ð¨¹ÒþÍÚ’4ÉÃå]ê.±;‚ C¢º¦µˆ1k1ŽW™Á(x¨ØVºÒµ|´oŸS¾í'«ÓñóŸ·Q®  x8ÀÄ-©›3)0f2L!O ˆF(=ΰ”‰Ù@ï­uF²1êB¬\ÐÒùÝ.ïã7p“I¬Õ580wý\Ì’Ž™éz°åÓào.„AφÇ¿"4ª¾F˜÷µÜf¡yåPH¹W\7U…úÆ;yË®-TÁÕDýW.µ²þ÷ààŸ$ºÁ«‚'⋼Ko2èlVãî º†¦¿Ô±àb ðgáá(påBþËoPÈ…z ýïúµÌ¼ºÙ»`HÀ© }ú?ÐŬé‡o,Ü'r§‚'€> }¾áNEC¿Ã¾ÞJ(:ÉᶯÕKßÝ7NÙèòŸ&_ѦӘû=D|‹ä i¡ß :¶–î‰]ïì+¾«g} b2'šæ;;Îí;gohö½£Úí¼z§\ìêhdx}çgáÀwÎuÆvnç[th¢Ä‘ר¼ e¥$ÃC¸:oG”?œÞ¸£-2²œo% –Lœâ@ƶí&ÆDy(9!ÆãަUÔTŽEäs›hÉ(1¯R™åÐ'ÅCO†}Aôiãý]”•¸spßë>ƒ»{ÂËôÆÅ•«ôŠ éôÃ.d<Ô;B#”uþüÙê¡•ö+s­'ð]ÿpè˜l–áØA3»|äð™-HI¼>zÓ9µÐ]è&àÏ#8ƒ„3ª¥ ¨˜Q벸üU”t§×ˆ}x´Ây^Íu5·úŸ’Õßë¿´ýçöÜáÍ0-軤kúÌÅýè"*XvX fØfrb}1ŒcÆ1Œc<¨@å@Ö8¸¾Ü^á¹<˜J;nQX?0Ñ,@…ÇHR_© BŠ!0ÃÊz£Ó}Óîxž7´þùw,ªû¼Þè¯,¯ÿ¨tšXùÿgJ)šM¡9íñH®ç£Ì¯óx>+ÛhƒS9@(…®¿wJ÷þ(šGÛõL×ÏΦ‹±äÕÇõ¶Ïåuÿ]«¼ŽØN÷>2øzûNúµØÃm\ÆJ­-Zö±#ƒª3aÞøþ}±úÉj€cöN¹t«fÙ€À)„Ú´8§gé­g®4ÍC4ÓV—MÃ[ëC³¶12æXÄ}̼¼L+Ä ‚M\Ò3öûgd“ ISòÁÈ%‰ºJÅ*w4öå`Ù±—£”¹Eo½qÂêÜÍðÕßÛùƒ–›ÃÄñ‘D)RІUè—¹ª)¢+Ö‚¡1*™'ñ{3¼¶J]Ù•3PƒDZkZB/•OĤ8“sò—R<µ/”¸‚Nâ¦Ht&rPI,èM¨™#¾¤¥4»¬ÙQW"žž!ðaÁV1&%Ò­‚¾šñý/,øÿg6ÆŒÈe¤Íc=6‘–M%MeLML0Æ!߃lD5áý]ð÷?¸ÿ£õ?2 ©Êû²“ç6¡þc•÷ÕæçY=Úµ˜]bŽeC1ùá¸i'}1@ƒò²§Ð¬Ïýg៟H¨ÁGá»e”ßð×â~$jÙŸ¿è8„qÎ~†¹¤Ñ±oD;f–»YSVÍOíîÚ¸hâÀƒîNi#}ŠÖ|NÌù#– 8䉌å"|ßü9|ÿ·gè´õPðÁ#2ùg”/òËäAØ0C²b !œ ”é¾)½O™êK=7ž0úé„Ä?0¼ÔO2E >ÂàT¸ñ|½„D:ß‹J"H*ê Ñ"üÐO6Š­  H Àv>5 Ó1ÿïålØH·Ò&ÒK,ÜÀL1LhÀNŽ ¸‡§>5!cb*2þ­ ˆdj""¬Ä°PE2!Ub¢š'@ÔEöƒ°MI [mKÃtNˆÓ0­Ûz•¸°~Pųd£9ÇÈuJˆÔÔ»ÇéúrJf?~Ã099åí{ÎþrË ù$œdÚïEàjžÙí‡à_9õñ:͇€nA¶ÝýÝ_›z@æPà þ'O 7a}0å)Í“*„5'²ÚýaÚh*3– T(I d«Î‹VÅiKë«fÚ%ó; K Nï]S]N¸®LúÝ«.²øÙÕ`(3„5цÂÛ °]’¯:-[Z¶‡pïiu3Äó: Z€àÿ.9cä°m¬ö—àÛôÏ:4nׂZœ7ÑYVœ-F qšÐBæŠÆ8æm (u¡¢8ÒF¸x˜$ë«›Q6 ›'i®H˜20s“0€˜Á!žøLù5EøQ1‰3`.zfjçÁ*ŒË g Œ4¬‰š¹¼êÊvs¥Örµ¦S]"ÕÊÍl(Á¶Û»i£]Âw8ÇC‘]ˆ_žiß >ÎL\1 *«»y üæfçê\„އGAÉs(ùKº!ñ`›èÚU Ÿ\·œ²e¿yØj÷„“ðúûÿ´Èª½ü`6¢ƒÒ䈠Ò(;MJEeüÇê:Í&¹Î_lu(h#EøuÒËp~ù™ kyåUw³ßiûÛ^RŸ‘bs# b¯mÁRJ¦Uì75ù±ø÷B&Ì1¨ ýwS""¿#ÙÜÁK£ÊJ‚ ±ÕHßæYó´qÑjû†Åb"$z(R xcˆ‘»¾«6Þsg‚€kýK²‘KØ9ïêùoÏ5%ËK©{ú0Uœ­:)J7ÊáÐâ+6:j`š/w}ív×ÉÅœÞñ|Û¬£7kD˜CƒhÃÉǃŒ&˜êò~»vK\_¥LªÈÄœÁ9„¡­ðBPG×Aô}ýuuBÝò-$ïAÓTÇ»0¡œFBC2ÂH¿€¡44Ák ~T† pÉÉä&’`‡˜î­U_‘ymoøXýLªb.-c¼‚B~W…Éðì)ÅýKÁ)Ý:ýºˆm¯ìj•!îf)f³ýXœÄ;L(!Ir]¢\|x—7Ïðþ*üHþœî¾²R$8þ::î#×<ÓÉUéVM¨œâ§”91 ³Le‚ØÈ¬Ê÷µÛO' ÒU쾟¤U_Ã;îè+ü˃ ?kàøG[¾þ5š?ût¨ìçcòºìæÏ¢Œ‘ŸÌÔ)¨QŠ•˜žÄ˜2TBwEÉöHúõS?b>)Œ¸O¦~3.èrÔË»Ž(P¡æ;ñÚðýü&OpåîIr‰…9$e‘ð/¿®ü ˜^a9 J’CÿqQH§¨È’PkÂéÓcÉȺo[ül:a¬.'ÒïúoǯoŇ¹3ßh”9ÁÈ¿^Š ÞC>Ž¥è·;[YvfÁÉAÍPx†„’B”P-VEACüÆÝŽ&¡™÷ºÛÎrñ†°ÔLûdP`ú¶Œ@î  œ7‘÷(»áQÍEýMþ%³œìê=Ô(Y(øJ4Á“*² ÁCõ ZSF™ ~±˜ìÉ÷ü¸QöÔl‚ƒö  ÐaÉ3†Bñ¡Áš^BýèO}@8=ýÔ,ŠNéH~ |ÖfK¦z´ƒ‰8’EPQC}!ý›//ŠãU.ø3Ð[W褈…ÒŒ w€b­D) ¾N³%ãiF¯2<¸ÀñƒpPn}2Éoa @øíL톰32¦)&´^8<øý¿àÿ”}9ä ýI¡mÅBP È Ý&Ñ®¾ú 1é\Ïô{ˆî7ÂE/\,¶Û”P‹"Š@Æ}d¨-BÑlA€§°ST€—Fè 0 -E‘¾QmV|5CXø™ži„!hóH§Í~q´Œ€BÈ),d„_‘Û’ûg;‡r=»³Ð=Ÿ-é°(tŠŠÇ ðòÉ m>4±ˆÏ.·øtmA½ò@ž5u¨Cß,(3öt ´Ên ðà)ÐCBëÍý5ŽEº„îêÒÀ§Å¶H@AŒYþ]f.ff²£i™¬%5E !=H²ˆˆ‰ MÈìe˺W1ÌïG°$œ]ÜØK7 ( ‚°b#07! $ŒBòd:ÿ•ðòSYOX* /¦—4è‹#ê,Щ°Ø\?‹$'Yœ ÓZ†'‘ï¸6ÕChk„q)µ"(w  üÑA¾?¯;áØu'CÖ{²Ï'£ð`å*.@Ù6Ø…ee3)ˆYð”@{d4Cœ“ÈÁ‚=-´3ÞI`‘ )A/[m¦5, òÒ}^z›š›ˆ½¨!ØHzôµ‰N8]ËР2€Ï)*šT'ûNÝ„‡±ì¶wRb(™CŒHÚæË§ñ ­òv•Šå5–Qf¯‘K6ÕÅ&˜Œ„-¤¬)›à`Â)"²0*‡úÌì)êdÇ(N:±b—€ä¸±w4¸:RIAámª5Åá:RŠE%J‚(ûSµµFXÁ‚”}ŠYôúx+l±ž™ï‚Æðñ{Tô¼ƒ™ îÓäÃ`ì3œÌäÓK> À© ’еF÷ŽêezÜνñ zN`R †°V졊–ŠPšý:mî‘ «BÎEë†×‹«bÒ-ÞÕ‰‡h¹˜ sÛj3/Z¸lÂHg-X7Œꬭ qxÉ3F7•Ö•X73ݶ»IB*Y²Âæhu¼ÃÄ#ÒéY£íôúAèuÙ"ÎVÛTI$ñÄ!,<£@´2ìЛAçàƒ™îîuO¸RžpùGÑxZ;¹ó (Šó …U)ÅQ‰>‡{„Zyò’ Vtr‚þÉk€È'Ç-hÑ!™Ãî¯4Ó¿+'9¶Šz†t Jœôí¾ª2}Üœ#Ž#?LÌC9™>qÏI}•Õ±ÙOö ü­ZS œŒ!Ï#Ÿ €:Œð€€‰85Tƒ‚ØÀÒƒ‰÷Úܳ›UfÚË~þ~Ÿ«Ùëmª[VÚŠ{x9ÿúÔgéòèôR´G›c]ÞXvÿCî¾.}v•ù­ÄÒ`†¼{c(PðS2˜‚¡æž5þþí]%q3)ÙÌ^ÈÄý5íÞI×/ªþ—ðæ§Âý߬OÓuögÝ×ßš ú¢y ²oJ´ iYZCÓ Cù¡D8 e¨d…ꨫ¬”ð'šEBT­ ä€Z"²Cå’!2b)?°ïŸKÜ:«ñ%ËK~ Ó¯ŠÊêÛJÓî)béÅ®d>)öéñÚ ¬ý-$غ3>üfAÔÆ EÚ|ÁÃ/ô+ O0Ô‘¥>Ò2}&}4ž_½±Q ½÷P1äjȥ܌Ï7Ema¼‘Y6à°ã¾˜X"†×f,‰ÌZq”H‚P~Ìð›]‚ ƒ÷£ž[£Þ?/æâAGÍa]IÚþ`48‹ f@‹Ä ¨H Œ…•U¶E ¶’”I0°¨{c?R.㥓U>œXŒÏjð7%—ÔƒïQA¤üÜbœˆ„ÖcC­²kÙ=[ë:ïµD"nü°p^¬M…΀d Ç5AÉbÐÐ!Ac9Ÿ™”q“g€6²Àb(6Ìת€Ü«GªÔÕFn òDQº ðJ„‚ŠžkÜvݧÞ÷Y±oó8~†©vM÷éäïÚyŸ¯v6ì,,FY3ÑAa* ”à ”  Îdì)>sfJ ÀEQŠô)aþ%9œÏÐï?;)Ydþ_L3[K¸ÿ´‚ÌÂÀƒãüЭ§è~à’¢ƒ€Ýhp¬F©Ø‰o҉ʽ?_ û³ØmöÐ02Ò¡o'“2Ïd²óó,Š ÿý*AËý QÒš´Ÿ€mØ-©þñÑ–ßÿŸUp(Ó—°ózÿ{žÏm¯iÚ)’(ƒ€ŒŠl½VD²—uÑK‰!C·@JŽü?\RS4B×û¿cOc‘Óñk”sèΖÓÙÈ«Þ6´Òsa¹Ž,½9E[µ jþ'†üà7¦>müßè[?Íá…Û-ͩؑqìתÂ.±D't`u®J0Φn^gçy¡þT!å1< * ?²¢èHUE–˜â6Q†³2™Š,ŠŽ‰!XÁdc©et1’ X(‰¸ØEtB\Ú0{κ“ß  älFU-”z‡Bn!ÊP¨nïx›ùÚ9Š}Ø÷˾Lf„õef˜½há´¦L¾üý–á—^#fŽJa~ÞtŒ‡Ðžä^c㊜²R¾ì.»¶yŽÌ²„8yäbÔƒÜÛz yÉün¦¢'hö©‘B –@I9Fu)1K¢D£$!!¤³ñP—Yr€w «âÊ~•;L{,Ôærþ_iÔ“xMyŠ•ñ ËdŸÙÈÉ=ÑžLPD“ÍêUþÍÅM½—0!äð§˜õ)çêÖχ¸’ËÀ2Êô~ƒP²ÀÉ SjÐIß”9nB•$ä Ω1‚˜Û “°’ü4Pi2>¢.IøIʱP«‰º((u}†ì‡cšh`v퀲 ì!P ÁPQ]>ê‘Ù™UO™'ïÿ1õ¤; ¤‚R AH) ¤‚R AH)  AB H’¡$R ùœBwÓeE—ÞBI˜d¨o‘‘O’ÝøZ-2èÂÒÕa¢¨¨Ê†6AK«ªD#0²À&VŽ× -YGWEу©-¿&¶»A¦¦É’Cše¶T™˜Ø3k §#" Œ‘d‰@[¦j(àLHŠ}F†™JåªtÀÀ‰ËH(€¤b#¿>äLc….°p&µU&æüät+Æ+cQëù3 Y^£4ßåÿ‹áî÷Ò$„ü)GVoÖí¯„áºv™ $ë=óýχø91C’‡¬z™,?¥- ·çlÚÖj,,Q‹‚Â)ö-ÙŸc#h%v¹1ÆÔ2‹a/) f7æ0b P[U„$Ú€ò%É96DrÕ™K«fÃD95cAŠ™b×FÖbÂ&É8Õ7²±”üÃ2Mâ H8JÞFŽ12ýÞn@“T´%z%ŒÎ(y×[$ PP‘AŒ’±V+ ’IZ4æ™›‰+18Ø\0Ì¡ÜýZšy!àý³õå³–aŒ­ÇüFw£ âæ;]IÕsÎÐվЛtkÏ)wå{=cS_FÃf@+ZÚ¬Úá•çììT/øýìÜ÷çºy çI¿ŸÜ_óè?=”2šþ‡3³)´½\ÝÃ2tŸÐ¢YšO`-z{ޱB øô÷J£VµõE[k^WwéϬ:û?Sp?6©ê)éC‘Õ{¨žQµ‹Ž–¶^s/v®ˆ¡ôü¿·Ô5!©By?¥ÐûþA™!û/{@9/=§LÊŠjd}ÅË ¨r ±‘d=žç]3Óêö=yêo"mÚH@äF‚1Ò5㕚x<#„LX¥Ø½qûz˜Ë¡C ò¡µ_?µø^cßéö/…¹ðFVk’v‹_+wZœ¸CÎ|¹§Yªæ{:2„Ýlß7§¬~¯¯ÑÄåxœ­ržoaX¨ëH´.ó;ýŸœŽûVÅ‚‹áÁµU¦¸ZÓ‹l³=ºØ1þËx3/ÍhMäÉ€3N†aûïr¯D*z[Ú‡¥w’a²E2Ü H 7ìUb6ÈÀ }‘Y"‘H ¢ÅDdú2kb*ÅSå g•®òJbØY!UUŸxÕ‰má¡Q{;Ì0‰ôÁP Ó”7œí»UïO(©T.»„'KQ£õšÔ‚0ÆN¬* sT ªŽ­UfÇûΪšnÖçc­ˆPøúY&„S³¥ÁŠ(¢ ±Á‡äáXú'q; wàôù"]"Ž›éHŠB°„ÔêP|1QI%èP& ºq ²M0a Dàq¨[TY<"T9%tÓèÚñ°( iA…!¼ˆO½dü\ô’HfZèФ9¸èü×^ÎPÖ´ÝËŠ¯q6ŸÌŒ3O!óŽ-¸™:¨¦´ÞñÍså¶.a3J2é¥ÉËT†æü*rqŸ€ÑÊVÓJ¨6öAÅUg“W~Ô¶lÌ < \‰æÃ÷Æ’i+l¥¦'¡óxavn޼©†Í…šH ?ºäùXo58=â餒Iš‘ „@’kƒc ‚ÀPp(1C!mß”ó ª²UU‘UÆanº¸²{-ë2ö)LA!|¦ƒª~?hsõ“@2 =¢ùoá  ‹4q0NÂopnªÜ„Î{ò; ŸÀÕdïvg®ÕW¸cÔI,@lºñ9„ —Í[Ü£cCþ3·†™cæžÂðãCÕ`-wçÅ]£÷‡íy‰cyöQ("d°ÔæÕ׌âÄDÒ6#F{¹Í§¾œq’É1 ve3^ä« éô„ºYH©7÷Ø¿‡ò¡óu1¥£ÑpBcÚü ð·»í$î/Kº¨z%Gçÿ÷Î÷¾~z˜`8€ðøªö_D×¹_Cˆ÷_.Y›0ëöDvÅZÈßS‹Ã<¤eú hü±‡°‚0 ’Ê sÑ'6cÍÒÅ>>ú…91e–ȇt'1¡‘DG„Ô;B9Û{P1‚Ȣμ»Ì߯:½G–PÝ?˜d–Ê1Z! ä;&aUj¯à¡˜$² 9LïöÌ,gOî.´ACJâ-ªœ¢ R™³³°Ä$_‚]µ`[êH4G\÷ö˜kfwöoþâÍtë¥áƒætf6tç¦N†8™ÐÚC£7¶KÙ‡qé&ÅSa††I°Œþ3 oµŒñ½^áÛa”^ÙªX쨘c¯x …¢o Àî;¬“±1pð j_ŠzÞ‹5P)šP–ŠÎe¦6'#ƒåq7Ÿ…@ú8ZS¦¾—•ºÜ]âkC³jft:ò!ùËyùz¿_ ä¯^ÏßÇ™뾃«Ô‰èsÑjcâ˜<¦-;&êvóÇQkÊJüç_ô—­3Ûž“b3atádÉ5¦´Ìþ")\ABG6{^PjnÙ3:Þ—Òž=ÅÒåæ=¡ìp²|L³qÝ…á2-£¾; •zõßwâh¦¹bEz]#¼GcíC»²}»ª(ëÉ|ÇDw—@ýùgLzy!íá 7C0y:®´pðàá8¤îÆ#Òm]àü§µ“V;±z÷pAÏe¬›¹ÓPã ­m߯VG SËiìI}y&è!‹—¯ˆ82nÌeˇ>3hÇ­: ¬)4Ó„ý* Cµë.8|}ß¹¸ ã·çºx> S?§ôOVïáØAì_³ÌUžJ¤Ÿƺ„íî®LoŒÜËå‹Åò¥h(µ6C¦Ùé —ØÎOKì÷éCÂÀ~JŸ.Iñ>^ƒU|3ʨ˜N¾IŠ^Éœ¦ìÝ«¡ˆˆtÆJ1Q y]3ÙºS$eªŒÕ(øcDUD³‘ÌÔeªŒÕ(æ48Ì 2sÍ7êdd'«¦2pˆçZïR Ì×û„È1RØ n1P·¨È̆’ P©šÑÐ ²h–ÀÌ\Ëà*'*Ž_/æýŠ=µEµØgÑE«ÑBn…Î7)0¼»%ÕSЉ?äW•ˆ¤UÏ4Å472Ý1¥U¾ÔœuʶdØÈN\_¥1ÌU°ÛÂ¥ª=i†«Ïc‹Ú~ûü@:°N³6½[1¸Ê=©Èà7_#1­˜XÚ…4«’+ŒŽ•—³ †2"ʱšq¨aˆ´è jÂZŒ›H°ÚÊgÓdúÞ9~øîe¸Y/|ï®uHŒ´µÒ †Iâ¬í›×ëêkfßGW™ÙNKø~k금,ÓÌ€2Z<°¶&¦*x똴 %[¥³3˜¶.™ß¨J]+@43:d‚Ð-7•p'™Ú¹ÖË6Zb'„¥¢íZ=(+DiÛ+G+A>àkÔ2Pæ.B‘` ‘P $a?Ìóþã"ü]Ƈ3´t$…Ž&^UEb0¡0ä˜"Ø”uä|; ‰Öi¶&Yl†ÕˆÃÃÌÐÕs¶fŸÊê E[¼p‡`ƒ©üã¡ìàRaãO_›n]Ñ´¶Ø­HÈr3EWf €Ó÷'Õ!üa½êÞz£9@ß¡¥ÍEdF1!*AIÓUÔ<É ìÀL¸¨Š‹»=nlîMéç€ÎðRÁ 7X²;Ó™ì\DÄ!ƒ &¤B6DãiH1š %P:Zb@:JP|]yt‡2Mƒ³šS7b£ä‚óã›ÇIý0` “"f «gLÜýÛ1¯×cþ4¹æ=@J&T}(ñöõgLú\ëG ®ûˆO£êJ7¨µ¡00ÞS<i׈“À›m™ãx—&IæõòÌõÔ:­äY>²¡]µý&L¡Ì¾¢F`jQú¨=—%`;_¨0ò‘ŸUÇ:GÃãßh—eÃÔ.„ö×ÅüÙRiP™&E¦ïÜÃŒºî3)5kÎ6U8/X(±²)g™\ü¦íº¦½0}؈£ÞpbØ¥F¤H¤Œ!L’R¤¤‚H‚¼"¯txî!;lHòÝ/ƒ Œ‰dPkçÒlYvA¶ŠL³ â(Žò;Œ¡CÒa¸v ‡ð{EP`Aèº9FD„(¢@w­ltq@„I#Bh´^ê é$G1N0çù:pwó>߉¥ƒÙð2Éò `tb5‰ zó,[pjÑhÁŒù¬&•Í4Ú“P UN ˜ƒ“«6€l £\ÇU–iíþÜs¼1âv𘷄í á ð.'“­Py 6/¨‚"úÔî+ ¦HÖÐó 6è_ˆý5Á÷j“•iä!QÙÉ‚–2}°âIˆb5 ž'4mÑ:ílM‡ËÞ/ÑzýŽW<]]/fÜé7à1zF…õÀ¦ShX홫X4º4]ÌEï$›M#­¶’½ü­ÜRï°\µDðÜX¬éJÓ zƒïŠ]ÈN ñz,I  ý¥ßŒ_IÍ_aH ªÈbŽo3i›ÚyëÊ{p;µu;3qÞnC#„‡™„’;$5t¡*|ƒ2IY¦—bÀç¶¶Ñ]®"™ „$ ©.B@–½© Ø.b´ %ÄE[ê½¶Œ×€‰!¦à$àÛ«8Å)ˆT­ëqÊÑ«O͈R(1¢€íFæo8ýØc¿t*qEA:IØ&äƒoš¡Îˆ%ŽÉ@z’ æGÍþ}§ËÙ°‘²s7y‡"6äY›µèÌq-`šÎîM.‹\ºÎͪþÞtÛ«Ž|A÷„µA¤èiøKÂ6ÕKà>Œ ¦œ9Ýë¤?NGpÑ=eã7*"dq˜çñÕ«dŸ±j>uL“3%"ñÓG úèî±]åqE»wO¯>ÐèðCÕ ñ‰,çÔóÒä°-k9“ ¥ÏD\œ2a8}—®`FG³¹ËiYð¬CgÌÖÑl¶9Ç€m.b]c`ÈDPÔ< A]˜Ð°(ÈoQ!¹ü‘ !_máØl êpk;öv ¦þXO½Å(²*‚„D ! ‰ :Pf&íšåí÷¡r70~AA‹tÏ´æ¨{ý+árAÕèn+䇰RPS¼P|•;‰f‡9E ˜À D!H_:¡ /´hÆ$g¢£¹âBe‚ƈ;ÔïólÏà/óÍ‘tJD½–ë¢dvk˜S31ˆ›{.ÐúÛ\a ®œò‹¹ÜÑϱ³±!khá¢\Ùj¹&H:Æ€e‚P¥« mÚÀØ’/F,5Ñ%¬2pzÁµØ·Ë4ØõÌ S&ª ¯ŒŒ¢Îkö¬¶+ ÷¡Μ4bR…„W3íåVB1) B‡Ò+wsâ|Åwe6µ|-þ~(?Û•0¡xQ.þ‡c{%ÐÓÝ]'~&Pˆ :‹ÊA¼ì’aªbû É[ÖÆÖ¶U€1íF|»“‡ÃÖBÖP]T¥gkw$¿\wË"s’ hÄUæÁzKFBy ›Œær=T”©¤ ƒ™'±= úÓT‡ÖÛ·²k©ç$ ËmÐ`gÓƒðYºWÐ~ßpSe`¼0¿|46‚xfÒêùµ™¢æÍßabCÈMÀò{Ð¥ÝìŠeÁ[¤æ(…žø%é¼DÌ l)ì;^[Fa" ¨v$”žÁ‡™ÏNÂŒV®*%;Ä#"ÝÞu@ûš u §£.ãäõj]÷5 lÙŠ©e‘ƒÒÉ)òá7j'Ç’£KÙHBB\*4µÐÀ¼áõñƒT¢L‘R¾FIAñÉ“YÜE$ö*]ÎgWŸÄq 8u2"Rgh6ÁdiTAÂ0k“`;±ö¡ó”ü%Ÿ0 IÃq*ŒÃ’ B³ËÙàLv=œ†øß¢ƒ7ʾï/!¨¶þj:èr`ˆˆ»=‰÷ª£ü{CfsõÿÃÿ‘ý¦êŒ~>T‘‡OɱÜ{ P`¨8HZ!TsU!j¦$ŽC2¨€ŒP¬)B¤ÒK†&†[ù)"M·3vo½‡Þ!¤8!8T ø°ÐM¶2²;ó‹?^™¿'2AaxBÂÔ´H")Z4Â<ˆlÀGLX PäàÈ(AË!K`b6ÙH(I¤‰¸’`¡q‰“ööí8-)°ˆ—›håOa:*Nzê†î§G¸›V<÷>2»âú¼z,Ç Ÿ‹:û²ÛbZÝ}×6µZ‰F™ÛëYo_ÝS¯ù“ô¸þ?úài™išG°ÐÓ$‡`aÞIíöµ0›†{§ýQ·UUUüõERbª«Îk'o¬¸ÎËkQÂÖe*ý¶¹ü å×,ì<âaÂA¼IoG@1ŒBfƒü>ÔPÁöny§r† Q#œ„Š((¿N|º—žHdû,†d¨0Ÿ©ÁŠÐ=³# mýâlç8d ±L0M iE‡çÏЬ4ÃR±dUbª©Í±-ªE™kÜ`’L“O•±rôÀ¶Š`z¿@¹þks1‚­ weÒ¼ï´øÀ5!±Â{ À$¨,"“àaXT*RO(óé :lØŽDgr”ÙœÏ+6´©Økd‚®ÝL˜DG¤µó è™Ë®bc4æâ³$ ÎSHˆ¨ìÈn  bøíµRM@„#‚‚(* 3j_s _ÍLÃI9†ßË7¢’(^N”WþÙj)ŒEh±²G›V ¼ý X*&7>ç§ùàåXø–†i–""úËJþáH@ˆäa8Qª”»Sáý¿ÃáøØ@¢'I x>oCy%‘@üÍaC†,/¥L˜->x#D‘+–Jo¸>! xÄÜ.t^Úb( =”GGEx¡aNBí­À´è9Ä5× ìOŽMNœôŠø|%86ë’¤õÛ¢”Œ†dÞªŠ:„….X ¸u K^ôÕUÅYRæ]ö´«†M ¤nB&éúpŽz@°Ä“pULþÁÁeʆРÅOéªÒ…ÚU8@ŒT XÈ!€00ˆ‚¡Ã]Í鎧%™ðmw,Ùj,N©‚j—”ãsÀëJÿ°ùÍŽs×î¸÷3Ë{ï+ú?ÎèâÄC¬‰¡j“*'YUcOµeDˆÁPXÂ…¯Ãņ)Rk$ª ,„X²[%<ÿ×`êý÷¦êo1—˜{ ¾|?‡ÿ)ßüìø±ÐUÖ‚'~xAS :„f(tȈ ÌD¤„ÕCk"Ð ™ òÍ=`[.;î$/²y†m=¢”´Ûº¶ÂVdÜcY>V´!ÔEB(AQE‹" Xª Œð-»âëý¦ Õ&t€u„u—pÒ²®®|ùßFCËFü“î4 ›ƒñ^Š 0𷆉·ñì©èàw™ÕwUú4©…„â²0Àdw[XÏv˪U‚0Ud)|hQ_òCÂ{mT¨TCyA¸P \Aøñ\úZãÀh* \o |€yÐGyÇ)ˆrẋîzç˃Èö Ô­õ(™ ##$$"ˆù6lÛF)Î\7+ªûéìU/PÆ=?&×´c’ô€ö‚íª]î,À¼×\dÓ§VL ºÉ‰u†÷™ÌpY ÷aèŸy#ßê°_8ªÕ”I­R(,Œ¢°ÛçXO‰UE§ðô’ !æV‚ˆ1½úB¤ÒDO¦Št4à[ÌÚܘ ŽšÃ‹fךdd“Oc<½4xÀ±îÒØFÑÎUQ¾ý³a7Å2˜‹xblŠÔS¤1$ 8É<¶ëÝŒ½9Z­V´'R žG18]/;Øé×dÆe2ÀlÐ9`îÅDcMä ¬a’p÷Îë*‚0 Žù 8P&Pç!ÉPÜ›ÝZaêN<((mØ/… òúbÄQ&=V8wGáŽ.e`KPVš;™˜Dõä¢áÚ>šº Šû(—üð8ä0ý}é]g¢-M}0ì:ï PÌzLù|ç ©­ðçYùbŸS`È>GCÕ§ØNÚòHíÄ07²¢­©½e+ÊÄN?Pì¼{uŸ ²º8txN‹ùÅS”Ð; ¿yÖµ­BÔ¥)B°i¬Xs@ñ§t6ZYiãähpÝ䢧~f—²"%Ó‰%ê]qr”²™‚ Y2…,*–Õ ²–{B… ºMâ4 rF hiJº·ÏÊ(€EaFH‰#"0ƒáœ{F ¾¹ëŠŠŠ†¡ÔÀ;Œ –7äsÆÈfÐÆQ‘æì@„ÜâÄwRàO»çÞªYä:Ï=xXÁ£ bѤ¤ª¹«¬2ÒŸÉM’@øvYœ>ucÔ\°dhÀ„ë.8a²pÂÒzÁd†0g{¸@)Sh’ÃvXÉ4Ý_¿×#OPgiÍ„8ɰ¢Db[,Výó 5ÎÏgËÞtõÅQEƒãÍÅ›’O')-¾2N¤z1$„DPƒ‚)"Š «°‰Qb,Q‘TEŠ DE‘ ¬Š*+„ÀX‹"ȃAB(²"Â"2€ÁФD@„FC°$PŠ¢ŠP@ˆÆ$$Ab,P¾f'?I RëÈÞ;´lŠ4ž'7|#[!ŽÀ:;!⻑ÈóH| (!°t]è ,¬2e+ PQFH²‰‰Z)F²È@©B²~Ý¢ iºIc µ‡Ã%’!çÚXÚz6¥b‹1 +1”ÊÆpA’C4YD!¡|É)E|@ç‰%B÷ŠVy-—#G=&Óº3Y’Ú6R@ŽJTï0>C»ŽÀóš¦À®˜oH²(:`ð‰!’„è´¨Âý¥.Bä\Ÿ0m ½Ç¦úüÖp÷ñ4àHÖæ*tˆ ]…a ª˜ jdÁ¢IÚ‚EbÁV*‰$65 '• CÄA _6LÉjŠ¢#:Çœ˜ŒDdg `«æ“óvÛg: Éíö÷Žï•´zqí±ñ²SâW=çßSLüòqA£Gë-3èÑÈ`K<£…@1ÀÁ8´:Û¾WkyÕ`ÎUX<¨í9˜p·OeèþÓü0'u›óac‡©\Öò¡© î0ÙPS¬vEct†[“ZrOCuçÓ¢ˆ½ cȃ#QŒƒ“Smñé¿øÇý˜?S!T¨Íà5Wš/…ó[g”4Wÿ_ëÿ·ýçèýMŸGï¾^.?“ÜcA.èN‚T3˜ïm¶ƒÃ?_š¯Ú9|'ÍãÌÿcy'Ñ (O÷þùâ"ƒÌÙúIÈÌQ½7…Áä5H&u[`Ôã$l‘ì6Ï[æ¹çG¢”nH'¾OL/n’Š€ ¢©LÑ[€\,5ünVß›^tÚËý scå7/•Q•ò1Ì‹œò<»C_U½¨Þ ™² æµ©š*ÁHh`Íc©©‰–®˜MLÉHR¦ˆ{v†$Xƒ&E((l¬„ "& ¨§A*Ÿìi°` ‘³¾çe%¥zv¿­¢2y1bÙé5%=bõפí^`‡"/Ðë¥ä‡YÀwÄì˜ ‹AŽ({ƒÜ^'茅AØòjh@Ô,ÔÕ›0̳<]"Ý:0ÓÕ ËXJ“'½†•é¾ûè¶µ3NŸçÖHÈ?Ï¢F˜#š3=Tˆ—+dß;È%m GDm¾à qg<…Co{HíøY¸n͆3×e˜¿UÛ˜LS¹öǵø/"ޱÕ8PZiZ†˜[®DS@À1 8±µè说SP;‡­LŽï¡oü³_@¸‚{ûþ§y7ܾßÊbw‘»|oꊛuôZW-.xNÓAÚ±ìëMq@Ì©“޵œêx¦fêêF"TÄÔlá¶.î ¶¿ï+:ñ3{;ñ€£4LmëL¢Jo9øÃàhæÝŸ¹{Cngb]‘L¿©Aþÿ¿êÿúºg’[†|‘¡ýA1TKÁ5ôÌÕ:^ñ­3· Y4\Þ‘4DS²ˆy³—µ¿ÁúOö7º?çÁ!ü\ý·ÑA^DI¢¶N@Xý*¿ók> œ&hHÓÙk--Î_iW)¹å'Ùæ~ó½ °Iȼ?óHˆŒÓþPX°c*¬UUü‹QPUb¢Š¢ªªªªªªª9$êMÄdˆ*H’‹,$(m Þ‘E; Ø(:BcΨ–‰˜.@G,ìáRI$î™W=¶ú6ÜÌVƒPU7C$‡Ná’ Óf=¸ú(Ó4¯éüÂàb`‚„®€»;Â(lvÀdr˺ƒŒO+â]’ўܕƒÅE(À¨¢«1ÙBþ1gðš¿scñ|<»}n‰©ùŸ²wztÑ´ð•O ¶Š¯ˆµè%N]ËQd’BH»ÃTÛQ#dB 7»§eÏ}Ø:¤¨ ÆÏsžŒul1†1XÌÈ[E°«"’ÉjQ9’L,AÊXÁ “Aݯғs|¦¶¢‹Ð8$SÈZÔƒYh[ HÑ´K'†JŒsW2 f@ì7‡»@{›=ÔߎÚ'¦\ÂË&þQà &Å(ÜÁÈ¢`Q½ãòØêdˆ†‰ÂÆÍñ,—gJ'çæ"ªªª«Ð ¢ò“4¢ÅWPìØÖ˜FQÿ--T1¶ßSWfìBÌ–Y¨Ô?ý·î˜@=â €åC¸‚sæJ U²]~®Ý•"wÚ¡˜”µ‹X²-€Õ¤“ Šá=8`,p¦8«ÂÓ7)¥"°Døíò[æCJ«ðݕň®‹ ¦‹ÊÒìFã1)`ÈâEaÔ“®òÐ3.ž}'Å ³úÀõd| V$^”ÞÇ –ÊÅN©`¢‚8{61r‡½Yd•ÜbÇÙ×xw–ttŽjäˆÀob#NYYlE*Òo¢„…uA¦Œì0ÛxiÁ!$„’^ŒçÚ†˜aiñÒJpr‚‡6³ÈZ§êM{rÝŒìàÃ?Bʨ±GêZŠ"ªªªª«G’Qb‘ï*…ˆBKÊ+ ”޹‚QZ€{“÷~‡–ÿß™ÌYÙõ|²:÷ŒF)ûð°Ú´!átv2ƒ‚†##"8ã€Â*ÞÿF Éb—Ôª6p”Â6 ¤p0&ÅØZ[ZÛ$,¥02`Wꤡ¿6àý°+C3M Ø‚h’aÃõ‰DS“m÷³:²K©Bzk]iñwíÆæÎf—,0`™d³5«au˜Kw´3uT"–±`Åfñœ7ÌEʶ£+† Òˆ`««˜„Á!3s$§jC¡•0‡"LÜž$•M¾É1'Ö¶» "cF²pÍ“rNHq¿‹í¦c˜œ—• —fÓu¸êǶé^e(åëýK3ÞÔÝ ÐÝ&˜Hš"ÆTQ:º|^/:[û¼”ð_÷œÐge)CðmÌÑôî¶[,¶>~&.厺xCW$<Á$ñßÐL.¢óÖºv@G,¨î QAºÖE Š7ø~,Ù6’ !@<ºi*ZPï`~ZTšašÌ*nÔ›$FJÀ7vrÐ u b,‘²¦ÄHKþFÀ àËcº(,ÃPSžß§ô!ìàq6)Õ=‡ªz<ÿÁà†éä½­¹qL`a>ЇÔUXXJ Òg * Hvª¿‚•+jï 3åCž˜SíÈ&LK²|Š[ŒO¦o“»°ëô>@(f¸ä¥›ÉI¦eƒ%wå--³¿¿¡HŠ¡JTdE FDRI ™¢¢Ab*€!# Œ@sZjH ÈÈ ©Ùu¦èA0VÿÕãx 7W6z];w”Ç$)IÙ D±jBø-­Èé/<·Ì ’À û±.E Ñâ?*'\¨sòMwžYÕN‚}‰ÔÃxl´(È€V„d‚«E,‰l–Ê 0TUS$àœÝÑxÄþôø³,»d!­KñûW¥‰iÇB΢àoÔ×o$•"ñPWLcjaÿk÷?—øÿ±Á_®ÐÚ@ÆÚí†>ŽÀ0§Ù@ÿN*ØHó']ºõ‹Wub×VjÝê^§•Ö|ýo#DÊ~V»ó54A²×ÀÜ8õuaq¦ À‹K`íNh6 Wü¬åE0±JFdol¿03 AoÏ0¿p‚‡DLw“olxHU0IúEÈBÁ…°Ð&I!D 2LUgì²²ÚÐÈ?º€ÙÞÉ æ¦Ô¤n d`@0a@"¬€P´  *Aäp$Væ‚|¢"JÚƒö°_Š‹ ó¤dŠ€T*‚È~[$ $Ò~m+: $ŸØ×:òJ"ùš aʺACåÍA±_þI46:nmÉLDLɼL¦+"QUIQÞ¸,k9MÐK(jK:Àæé/,D‹˜þc©H@â'É5ŠH‘‚ H‰2F*D´ †‘;˜I<žýcEʽ¸_œÄd k†Üc`QåÊd,…ýeêBPêÕ6x™+ÞEdv;à0‚FtLà6á €Š‚RˆH‰@ò9%ñ у7ñÁ€”Y;S¢E?ÄCÄf˜ò€CªbnGL°&2VZ   ˆÉ H;9R#"äAc‘í°H:MQA™ H ÀÊl"* ¹ÀäPV%HBÉ $ÍPÔ@fö"<¸'ïÐ:C”=)9¥…,ӈȈ­^ˆPòN!$ÉŽ ‹D'—ìïèRŒ«ˆã)•D˜[5 ¦iA`8ÀXBIÆA\Eé…*Æ!r ­„FK„-t@² ¡+ÜÖüapHˆ8œÑâŸc©BT ÷4xû¬’(@ÏBAEÊE‘A¢”QF0IÎä Z†wÚOÕ;þ/¤§©‘Ÿ3[Cå@¹,©Y!>Ï_~G£aê­ˆô2ŸRøl#iØÕÙ´ÔÖƒ[mè7òîPÑK»H§Êâbix¥DD«˜ÐÛ°"*”èቂĽdH±Ü«7ÀáÒ(]âÀ„Ezø fÉÆ®âUcçkzë35L¹q ¦:Õ˜•tAP Nåòœ‹HG: °J$°j§ŒÄK!D “Ü’„‡9² z}$Qù“Òz #[=ËõPdEw¹Ù`P|š¿ÉÚ¦Ð<9‹©ÁÀXu´÷™YÑ*‹ûðU!¡ ÅÂluœÌ€L«óp2G3­ðê¯|gÐÈsèO ç?uÒ•p±úéDxží&ÈMö°Æ-š“™Y¢ƒdÖ‚‘´yIö“;µÐ‡¹0EI"H((°G™N½@„TåŒKí ƒž¶êlYu4µ|£ Ø!³RðþÖå¯?Hê"À›8BTMø;5KC¤RNÖ $ãGKÝzQدb ßA!‚’HH¢˜ÝBû–¡-qÊ0ìÌN!Œ‚ö‡Ðø  dþÉÄ’ñ¥;­ã¤{ZºÄq¢ˆ « §Útz<ž¸jÎ=»§—«™3C·lŸšœj–*–d2vM¼‡ÑÐ`2"Q3A2WHƒŒ]“B#ðjÄ-'`ýBöËUXûVn†£µªwÄã[íì§¢#äëgé.˜c4K&!Aì J3]×õ¤ dˆ¡‘â¤ÌìÐïå ¥Á4¸Yida:‚ެŽP8_HkaÎ6µ&“VB\Á÷,8Ji–KÅ 'WIÖpBŒRÿ¤×Û›]‹5—=øórj™ý’dîé.è¦î2P¢H$b›ê‡™¶¼"ó"˜æUŒ7,sÝÝÄÚX±C©$-[]‹¯•ΠÆHÁA‚qB"a"‡qlm¼ÉÒwwx°;­úB|P*¬­H@€…2E‡Ë×÷:–ð7mu…,· ã5!~ÏÏ??±"æym6u‘=E£Pw©À] Î$cdP#ÛÌ?xJŠ8>: ?\&©ãDsa§£ô6tÿÿ›¬õ¾³J糇i¶]ÜÑ" Ž)F(½€±C³;H…±aç69º!û‡ÃÿÉÿM EãóKîжü;ø¨c//ÁÇ´c<ò^`¹Å¥”’%âˆÙZQppX°X2@œ¦ª:„?Bd ŽÒinÈE)–-,EÙ+ÈvCÚXJ %Ó†"20t•DlÆ‚ €³bþ{†ö¢Hu´PµH¢ÅQ,d"‰mì1ÁtÀ¢é¨jÛle‰DQŠ*ÅEQP`°DKBŒ`Ã{XQûìÄÁj#™‰‚Ô¤-•Z”Säà ­R¦4b?ÐÂ@™ú¶ýëõ¯ÏN>·]້8ÍÚfê„Xìµ»¸#ž*÷GFRÙ¢æÕ.(8±C—ʆAøÿü>[M†|¦%¼}e|·]¡¬~å7ÑWTµØ‹0¬\k”¢U»f}[ÆÚÍà b#EâÓFffUÆUHoäúy „Ù›½2"DÇm {Ÿ4š #Ž\DàG}Œ¢é·Üh·.ØLŠB„·û—áfð?Gdý¬%'îÿ„¬®h'¢S˜õsCjMhº¥Ó–Ûa ßv@’w$DE)%›ðpBô¢ùƒhxCÁC@ ×U÷•X¯/ˆQ^$¼n‘©ø´fuhÚ²ärŠƒ6¦1‘Í2ˆ‚ÄU`Õc`B2%aå1€&@A  Ä]e0@  A’Q40”dPrˆ£m–5•¥¥¶­ˆT‹++m–1ˆ% Ñ¡@4²ZA’bZÒ¤íO…é+ë- p Œº›¡&¨– C½À* ~'S‘ N»d ”Vl•2 -k+Ja済!+" ŒÒYeZ­Ç Ä r€ &wø”S7[Ý'jgéŸËxó¸ÊNÛ`ø"PØÙ*E0€ü‡áï_z=¿7”3}3 Õû?wÞù®´j$ ¾i ãîÄ×´Ò]~•ÿ쫚þ‚[÷KãøõÔŽ…Ù~‚´IO|þ·ý 3_Á­‡ôçÊSL CGÏó~D{úÇ7jREVDÇ[%câÛw`Öò&ãž]õ¿Œíâ¶¡ïÓóÎfSNŒÀÞ”Ÿézø¬íêúÿ|ö õ³«wi*[«†GaY‘X¨^ËŽ4ì³&YêxNÕÛ}JvÓ†eÛ™j[–­œ/¾sXÔ£dèÛ§X–¼êÅ ñž%¾ë2<4¹ë_2½¼÷­)‰Á6º†'³!ˆZ±†”ÌÌ ÄÅÉ’-êZ~0ÓsãÕ6ì8—ˆõÃqM®ú–t&¨€E]ÛUTd¡Ú,ꆈƒ¤ÅøÜ¯‹kd-‘H•03D³õÞvNÑߟr¾O„S—>«äŠô÷å`ƒ6zÜÆØQtæ$`™Ì ¹ìG}í•ÒSnWa4‚–ø÷Áz;0â©Sršò—Axw¢« Aó 24Â!ÞŠ¢Ø¦µ #JðÍUß~O†=9rJyiŒèôJÁa¶æbâ,/tÓiÝÙþ;zǤÆ"”7ÁÛ|ä5¢Ä7Dy†Îè¥^ŒGÅY(Êu/.>DˆIÝÑJjHAŠaÓZxw5“{‹fH‹Ú¥ÐGœÍH'8¶w¹¬îÍIÕ ‰@ݸ¾Œq”f Šs[Ýñx†ƒ­) ]† NOf×Zñf9ӌɋ4Y¯j£6E&ýw}Ô®ÞĘI!,—»z›ˆQܦ€`dnR›fØÈâŽÝ»qy¶¸ Û®5/=E²åLÂ!ØÝ]x™”îÃ07¢¾ËtžäW/ô¡‡ã@ƒîßöèÏòÉ7zÇ`ìƒ!£™Ê“úõà(9lÇj’¯LÓóŠë ²åþÚ€,ƒÛípäòÿ·¿ÓdO]åyæÍÂñÞœIf v![$öMV9Ô nÙD…ûûîi–xÔOg½¤=tÌ׉ÐMð,4Èf3²´¨f¬sF3@5Ié(¶Ñª£ß·:û^*w¢&¥éçF`o“ŸÔ#ÓŸWøTßÙçÕ×VGD†§È–6E¢(8“” ~I¡ÎÔ{>N@ïÓ8eyÓ¦,3Zb ˆÅ¦?MÛ’[¨¥Y1Iâ;7Š Qé ˆa»¸~Z©w™žDMúº*^ÞmÄK¯£%©Üaç¨?iÀëm/hhltàý¨Cc/æ/ϹmåÈ ˆì‡HyáYMö³Þv3K¡zjÆlSZlì´‰GZ®…zSq{§R;HK^y­Žn-M Ëßm´2™å{}O{ÈkÉ=¸¢–ÿ_AAýwÙyÛÁŠ!³R’á<)áSˆ 8¤â5y­“‡´“¤áñùʆ i¦õx¦TÎÏ'ÅèÌ÷òêèÍfÃàêÛ¶æ#»3 kIRƶa4ϸån‹û3[Dó( 4C‚!­ÚàX)ëŸìCæñ¯}êLÁì¸m°]Al~ÿÚÁðMõ¾’x&d¾Háî:‚Ð'‚ ¦§ $;w‹6ß ¹aËO ¨…)ÕãŽð@™2¤ÒjÔcòÔ’a©FZ;5+ )Ûïoç¾½FÐrDö·!¬{7n7³Ixë¡ !!ºT²Oc=¶Y”£=¸,òA†aH@„㪼…{ìeלN†A¡²ÙíD— rss‚r‰Æ;%™óºþ 1$d‘™‘ÚÚ‡¢6VÔâCT ÂiD‰·m&f‚ñ —Üum.–r ZÀêÆ¬œ´§b³¿ÈN±;Ü0CÆCî °,$ŠH)!RE€)XÈÂB`E ²BE,  E’(H(¤RE$RAd„""È, (°’AH(¢‚€¤"X°ŠH ) AH ¤RB,!d$¢Å$R(€,„ü‚+Q$D$†*QT‘DdEdAIA‘$FFAAX( ¡‹ ²H¡„PŠR(E$I"‚ŠPFB()’,aRAB,$QAH (,,$X,„Š@ˆ„P  (, ‘`HMhU,°&Š>.›&dKa¨´ú"ƒÔQ2’}“yCrvÀ$"wU2‚ã–©e±0ai•­,®`Â!!BºÁŽ€P ÀÀj<^‹_1.ѱqy ë•Êõq‚xQÞº·Þ Z_}_Í #©ÜêUj×Þš‚]ä`«o~Rl¨§0îKdü•´dÜ' ·!愘yùGWc¤A,~ó÷EZIyðµ5I¯š›ð¢D™àtŸ/²öÏb¨Š*@„„3´“*hDlq y‰  ãV9¢ƒ@y! ,º O`\æ´ìÓBÎ"O¬E‹VÙꉵ¤tâ>€,B)K$bìbØÁ.d†M›ŠÜ! ˜R@ÅP×Kßžtå*íìÌD 3XhI\Ë*@¨ñIýsÃ|Q* ê6Xªv˜ˆh™—wrFqBÁIég{¾-´7s#EãV×X¼hr¡x£qÃjdiN)`7ˆ!`Ö,!ÕÕL’2)ø†­ŠxŽÕâÇï¡2.ÎúÊh¡7¬ÂIƒ¡‹22*{C vt|áW!ج€] aAîBžã¸o“cëü•Då [j𮕙«-H£ª¥žèž& éIŒ˜$å!•Or¥°Šd³,†œp(5:JP.€#˜ÏOkÕ$°ùD ¬ûÕ¹à]¢;y]±ù_cÛc(±6B1;"bÏb^åíõXuËü¦*Ê}×þ]Œ ޳)1Z%æ"ÞG’VlÁ—°ôyiR]n÷#Äï•ÖÎCõÇ«–G´±(.죒~Rµ…Ÿ4KLo Wi5ø©jòÏl8íQ~Géþ= ÀÝtâæDúƒÕ/^·S¡ìC06Ë&'`Ú[»©Ñ‘‡Àa˜rF`h™—¨‡tîϦ*'^1õ†`l»úŸöÙßï¶;I§ëŸ?Íño¶Å<\#yC`¢&=¨lº°à«+†öº&™éˆN ¿Û±ü?çŸýw°|à†!.ÜýÜþãêY(›LJ9ì¾»ŠGƒÌ;/¯óùI|;<ü«ÂßV†§"ŸH*Á:ùéÓk•q®=<–3Ö¯–võ–붬¸Í‘ÝàŠäPlŠÖ¢ƒš¤žôûI”°ÿoÇ;’vµ‹¶˜7×à…¿÷˜ï x_¶…›øþ§¿ë¹6q* ôéE" ¨År澩L5•÷6Û4cèNïs–ÄÁa ¡Yju š¬µ{‘{k{ùdæk5C8„TpßóÉËëÆx&££ª§t7ToÔÜ<ö`$©jÌY MmNì’§blÞ™Q"¨’–UJü‹õs*Eka»7ìó4b¨9¹c‘몜7 Ȭö¼¶¸7ÈlZícúÅC‰Ò ¦hdfÙ°Ö!n’.9}@ëw—ï öÚ#<=7ù9{i瓈ÅçÄlwén,%è4av–rŽÄŠmª(¤¨4ãÉ8‰á 5ÑAË„ÊT¬X¨.¨>äEºy*HrÑ ÖrÕºý!€/u¦1}E*H@òí’CÖC‰´X Š£#'fǺœþÚQw7ß³²•FEW{!pfë¥I&`g1$G@Þ\ïy\ažH$Œ‰ Ð먌ÝÒI%ÁÎjÃÒB"¬U]ç#„x¼áa„XI{¼¯yøqh1-²ÚVëkY5Òea(fÍ5†(‰w$q¤ ÂïÀº)‹±ï`*´|38¾4„&2l ¥hÚ°!;_¤Mšuo¦¥ûK«q°†`±Òa2H/g"B×ÐDvÀæi¶( Ã2N[ˆ ƒ”7ö äE0€d 縔í‡3ÉFf€¾‰TçÇh­„È»=;Z J)3yD2NÍ©›¶`‚h‘2V„+fømt?²H_¢ÃŽº³âÞ]È: ×™óš! Ô©mßT3í÷äX:·èw €y.N9“«Ô\-[¬µ¤¨Qš¥Ë`ëYtݳFXš¢3I¤ïÊLI²LfUM³V˜`Õ3T¶š$ IhpXd•¸¶il¢¨I1Ö5‹ta޵M:PM35trÒÜÈc™ LÈY•«(53&bHÂ\76Ô˜%»`YÙ3K\)C‘ LÒ-£ Ûb¬Ûlb[Fm­‘E"QE‘od„àÉÎÀÉ£}¡D*‚%)W5Ã„ÂæÜ¤'´!×J†°CGL ™:ÝW(H ÷À$Ij$ŠÔ*"XsBS@ð‘AÊ]’I.qzo™”‘9ùÙΞKÀþ>Û‘Aóˆ"˜j_#œÎ!P„X°z¡AkZÓ!´æ¢¶¨²1P–µs =îªÄËŠˆëÑæ6£éQPˆû6Sbl„ßeƒ•΄ó¢ƒê¬á=µÎ´6éתªª¢¬{äÈHNÔä´ª±l#üòåÇg Á¶ñ~ˆ0¯–Z¬ôâ\Eˆµ-í8L$5¯=*3P›Á‡³ÎñíÑžõ{á bî†Û 6aÆô¬HüµKëT ÅãƒÚãŽê‡r”@œb•']"Ò­yZ³%@Ì kÞ%C3J˜s‰"%ÄQ±$‘+ÓeÆzZȈâ&»(d–¹N _$6ðáëÍ\‘GxlQ€Æ)ŽfõºÛ«üßÏý&†¡Ï^\ÕÈ2#x¤$€˜6  ŒÐ¶h¦p9³iÈØôò$Ù' á=M`³JÈ¥J£–Èt@#£æ‰©#Ù‚ƒjIC1Œó"drTÚÕ¿õî]Íé²êâAˆ“Ïavþ>#8q^Îòˆˆº'û6é÷peþO}Ë·iYÄ¡»*·o²ÝÜ{á<¿ÿŸ‘‹þBuyc1ú¦äûñè!ÛÔÜVÕ  ÚvôK (Ȩ2©ABÈÔ rêRåÌÑ š=ë ´Ü ˆÐX‘DPQTPa` #!ý’}¡ˆ„R,A‚?‘û°õ÷jÎÔ‚ð/w#.€uô¡çæ˜\…I¦!’ ÷qц™ó °ÐyײŒ$c/²ÿª?·ÑÂôA«…!Q$ HEQ„‘ ·œn@M­bx¡Œî=*€0Ñ'‡E#à`ÿyŠ(³)$@ È2HBS GGö¸h¾Û’¦ í]š÷“-ÒMˆ @‘G¥„Š ¡1ÅÂ1íÓ‚Æ@1çh å&ŒŠ1‚B0€I$Xk* ·êw`(9×¾>{áù”>’TûoÙêD^Â/¼@y0ÊXb…“q±*Õä²¢ƒKåHÎY®ºò@Ðø>ÖFã*Ü÷‚7–ƒíLS0f5“ãR!vvC§¶† 5ÑW-ˆžE¥20,y?5¨{¬ƒÎ‡|05”wÞÛ°|™˜k8Ô.6™Ì‚2#š:¶£Ú‡~ÀÞE’ãü;ý ‚ÿz@â<#¿öÏOŒTëlµ¡Z…Tj J5¶Â@”a OWÎ*„*²èh‚nØOSTܲ^Á@Þ2 7ŠÃFàhAÊ C(&BR™ b`ÐöOGOB 47y˜L”•Áùìoï79 û¿b¦ó‘·¤e—bõç•lh³· 5íZ9£û?§™Èà‡.XçNU!3Ö>³—-Íí&ã.;àf±ýtùý͉„åþƒÆÉªu¦s#cÜuYô9]†#‘£•AiI=hªEYüW'ËÄþzû­So­îí›9Âyv«ö¶ÝÓMöï8 Áe’z}š  2)”¨¥L*œP¤±-Ê>½mýÒê•x¯O*~%Í "Z‰_[+‰–ª´Ë`ƒ¢iŽSZ$DNò܇ŒI¾·a…O) Û)6I Ì‘H!æà²àäe”$‘ Œ Â5uˆ§¾*†p÷süØó(ðݶùª‹‘ÛÀM‡ èΡªB♾¼pÌŠRŸÖ_ù¬õ\lç¢ßÙp||7m' MÌ«€ †Ž°úüå*R1™œã€8ŒDF2Ä„>w[ó’D˜==ÁV(<ºXm!ÔØPq¸pQŸ¸{¶ ì¡¡½$ÈM•³e?/`|.¿y_>|v´–±¼9¡æÂàTFrÍóp¡e†œ ™Öê£ÔÍHf¯±ô-)Š„ƒ‚#Q ŠÔ¸ˆ æÀ-qMð@0Ì ‡”€5´A*æW¿¶Œ4§s2 _A¥ RtLdç>Ž ™‚Lb¡ˆÝÈʤŽã Ë$ X‹ïý窵µ?3Ûäê=‡…ÂÚûý4ÿ'»}Íɲ¤DÇL·œ:ˆh?‘ÑÿIKŽŽ—sÇ—o;¹üÅcÿ& úÜåÆH^Ö¥³a»×<äèMôÓ—_Øå`!l6*ÐK2Q†W)ycõÊâò|OÓë^ˆß£ýÈDˆ€0@æf4̽w…ÑC¹Æ)1Î’[—]4Q–o^ÒLåá„:QÄw’GÖןã²q©º¸¤ P÷µ–[¤þÝ)ÃBqþGûÄþÞÅoä_#TÊHIô$ž_M½8û¿‹Ë'$´¥lµ–‰mµê»žû¿ÈþLfx.AÀpÅø¶. ˆ>ËKOr^y£ÚõŸ(g—àÊö'Œít&^ Î̦ùöR§2ÉùàÂ02IC|•W‘Ia7€º§&" Ü±yIÂbü M ƒ?BÀ`’ Ac¢VH, <ÝŠhÂ*y$ˆÂ.W®ñqê÷ž˜£"ùÊ¢ÅZÕS£âÛƒ<ˆÖ9…É‘£#£yÉÞlÑðÿ‡ÅàûÙÿOím¹³—IÜ\b)ãÎ÷ôúpùÙžªÝNn C ãÇûBgùÒrÉ™Ëp°ƒÉÇ€„å—ÝnQ0‡]}F^}Êï|ϸ¿§êñ¾¤aq’[C©ÑÁuöÀ Ò@d*O&]s»5üÝ·çi­œjþ>Šf©ÿI7¹›]mMg¤ÂV"CUúú+¢ZШ™µ ö‰²N¢âH¯ò“gòžÖG„¹Ã© L« j­ÆÃNz—5‡c$¤ÌÀÉ ­ËMéê% ì‹1ëø´Øìõ¥¾›¾«už£‡Ã×Cñjémpj©iR_°Y.Dû¶`ÍLöZë‘ý„í‹S¾u9t5ù¡Ê®-»fhu–¤VÉ{ŸÊ¿35Ÿ•n]gfÏE×g{ߌ€Lç§µ6M8×?.¶…˜5yÃ| ÄÅp†ùž&ÂëúWŸ0áɇÌ:åGó±Ëk'IΊäU¬pß÷-¹[“„$GÉŒDfxoŒœX?¸þ…W«ñ¬»×ŸêÿûÃŽó]ÖÓµ˜á–Wû¾-õ…èÄêHy$;µ×Þ®·GÔ?w}g½ðoº³sWfî®òjè¡%uI;ÇÞ;4Çãüàþ»ˆÂ{ vDæY>ÇB“úhnóž¾ÃȹZ} ªbmì;d):FHAå׺}è ×G³æÎS¢ö›†e6ë䯦4ô->Ìó‰œóII…0  êÌ¢/f¸À{±ˆEb‹JE)‡@_Œ0ëÖ ¾—~f@žO‘:“ˆ ü¿˜yL§ÉÚNªó|¬m÷©È…Ê9G™‘ Àgùq|Œÿ[õ©š]«¢½e¡/ͨ¢²îkj`Bƒ™0&$XÎy¶Ø|~Ÿ”NE·EMKÜúèMáe]»í{|ŒÌ—&â•/WÊ‹t"*š´KÿŒÉõ:½'ç{­OKÿM«­ UE¿ ¶;¢|·nùÌ<“[ ½¬ÛEuÐåKo*•ûSßPÊ@¥ÓtÔ4-ê<çzÚí•!Œ ÒÓÊ,V\OÈü¢ÓX ¤D¹Ð0Ê›t®?úÿhóèó½ÖГí€~ÜÑ×é€è,@ ˆ$ãçõÇý¥Á\  Á^€ (´^j0_öѳ†ÞÞÿæ®bNåîgSº‚þëÞ»Éßð§BƒA\°æ05È…Û§F¾z›-5Ûùþõâ)6—îvŽj…6ó4ýKÐdÖl}Ò6 önÂv–á«ÝØq©|mql_àý®]û&äýp¨“f´®ê?¬ÞKñÄ}OIþZc¿(G¸s*¡ì­:*Oœø>Eµ?¨”•µÑÆ„çl?™Oó¾»ЮõZl\õpâûê,‘&wœK9ßäîRÜÚ =b¯Îâj[÷ߪUíq#A rt×ëFÇ-+¦c?» *u£]æ+ÉÑ‚½Jõ’ê8±)íY¸ŠŒUýí²®g½••™‚_‡Icµè/¾ŽÉ™|ôʇh³šì¬ü oýÒúø3šŒZÌÇj«§p— ¹üÚð•ØÄäWZ×ñ¸¶þèyµ[E…Æ×1†‚ŸK–îé¡.™²yAÝMΚ3ÙíËöPÕÂݶ «ÎÊ+ÓZ?6ëwA£ý)§ßÌ~÷ó³¤D‹ï ­·œÎ.\{žq¹T)ãÏìOãùfªÜœÏ‹õ1?ÔVk]œVé%Oôû‡P ×aÎn ~Æzyúfmö¿¦û«ïùp”zÉŠ:n#cuÿ<ýa¡ÍÇÇl3è\¾*VbQ5l(ÂÔ·ÏþzÃ# uÁ[oçõ¶Ie½¯›™{™¿:]Öä{.·"ûÃ[Ôv¸ù›¯c±í—ϹéÓãsÜÍÿá[¸Üúáb3·§æ\×ÍÙnga²øEÌ^6‡S÷©ý+™ þÎ÷îéÿK8±.uŠÞʶžÞ¾ùyÌïy¼ ýS>g82«]–»<“‡:BûîjqQãÚW#íåyÛo ¦Ê#Iu׺^Á ,^ƇÙÔ~ò;#}±;¤õ#.ä‹™ vw±¢ŒD©˜˜’BÑûÕ*‡ æ5âóÓãpNZÇrmFÆ{76±àí]Ø;¸Ÿ›D°wµúRº%©ø\u`k=˜ìnýS€HöíÚÖàÇ•ã&œÐv¸™ö›h εkUŠn&s%¨vÎǃÏÿA&»ýmØ$à0²8MîkWŒºd§„^Á>ÄM÷àÙ«§3–¯·L9Û?AóiW yÅ|={6ç{l¤.mŒé)›3›&t¾J=æÅr3Ît|Ö›m‡êsî°]e~¶dˆ€h˜õg«ç¿»ú¹•XÏF;Ùæ®^y€Þ.ì¤×?<êˆf2[¶pnÝ6p· V71œ?dßÓÆWkµøèM$†k¡BÌÓ2ݳç¬x#¹-"ÇESVÀæâÜ{#2+–©_㡸Æ*1éþÕ˜ÛjKïcTóu^ŒÖç$ñw/¬fÝ+È"2¢Çç­Çò[ü3ÆÿŽó¯ƒÖð÷#ØÕ˜ÔPÃCàÝúØcÖb¬²¬ÓбüX¾"³©ºõqá–÷¾ëцoæçA1€Â—ï¢À­ðù´>ªÓË7u÷‘ŸËtýßlËã®=g$©É°ÒM&È@‹Ø%-Ô†kyàÿ˜.-G£©-áÎõ·4˜+ë‚éê±5œö;Ÿƒ¨£ÚêuSϘ‡{6¥.EƒVz»`°ïzy^ŸâéÐz«­Î\=Æâ·MõSÖæ|(ñªï^û«EúSÛ+ÍøNŠß³} ¯«_øs\%?ºïŅ޾lÙ¹$“'ºjÕx>.ÞM~¯×Z™dVÒ:¯n¼ÍvfRýØÛõøÉ9©ÂVïÛ²Fú?¬8VÛ¾~5Œ*þŸ/}Eþêáþýk²pO¿óJuɇ“ºN»Â×^Û:¼ûš÷÷Û7¿Z«áÈ®{ÛRñÛµœ »ß¦£EŽÿ¤$½óNê17ø;Ùíu“øárŽÜ_¶nÏ®MñQ·\cÓëë·œÎ;ÍlÓ˜I][»}®Vv¿1{9Y™î6§HŸ¹¢¼QÝõœ‹ã×=ףΒÇßàº;ï“^›Ü‹E«ÉJÈïWpÞì^~¿Y­Äqë¨ph¯{YÖNw63ó&üÏÈÁfú·ªKEÍý]/ QƒãyÆñ&Õ'ù¡<Ѱ\+­OwAÁÐÃQ¬à›Têõ¦ŽBPƒ°?|ñ$þýÌÖ²7V¿ax&úÌQBqYÛ[°8)ÃÉ·½œ½³Æpï2‹|þ§c÷ÔãCÈðÿŒVí‡c×â7vJέÛo–£‰pš[’çéžïWg1Êmì0*í!¾È®ô zŽ¥ë&ëÜaàY[Ãdøµ;Åe%>þ3:™ÖûFai¼FD%;_@ ¢Úq;å)9¾ ¿‡ÿj¿%ÜÞ­'ÓØlïµVÿŸê¶·w¾’ˆiYÙ¥¬wÖÁßÅÒz46ï%·ÍöÇû4î´ :PðõÚ Ë.Þì½ÞYµpt½ËŒ»f¡­Á«VÑ„ÔfqÍZ|óE >^-B…º·ÁJùÒíF9þ©~?[´Þ_?oÎÞe·Iüôò¾ç_c»MnÙן/ûüq˜I®ž¯†Ÿ4³žêVu5¾M¼6ü’ ÛÎЮtj5ºv¿§§ ˜ ¾orÛKǦ÷Y{¨ñW9îœúßï‹£¤Òñ½û7‰Ýþi²ŠÂ»)¿{éÔ¸2¥7*vñàí@Üã(uK¼®G] %ÂKÇ‚ç·ÞÃrxY¤ûßUÇa]ƒ]3øô)w2Ýy-„çá{›®èÂ[Îü™7mv„ÇŸýwÿTè>”1cÃÌþ{=ï|t?Ž¥Ã¥T…Ä'™ÎÇÊH¸ªl”¿³ ÁÅ"cú›¬Û5þ¢éD^±ßEÞžÓt¨ô£wNçžxæév”4˜Õ ì"¦#åùøÂôä¼oËù¢»ÀhTöRžìÇר¹‹Õ⪦[ú|‰Ž5R|3qÜÖîµÝέ^¡›¡§Î)ªÔ[>‚ $<²\ÞmJ±?-ŒŠQ,~eÃU_k¦ÓÑpô|¯Ÿ!§™L’/äƒñW{%ÃÞæŽÊ†’¿û„e³Rˆµ¨¿Ó˜4Ð]?äínoQGØÆ2{½›oTO©ÿ/ÐDÍM ÿl•¦œthïÙ³å_£„Á<0öW)è4pG{;‹_<&m}ºg‡æÇn\áµ×ÆTÙjë™Õ߯ÙÏOþjPÂHamq~z5ØŠ¶Œüô5´Ž{ߣÏ\Êr{\îÖK¥1Ñz뮨´ü4÷wÜ|£¤Žwe“ÉÞùrH;­kjaÒVñ”Óa4+ÓÑ¢öm÷ï_ÂWn«|J黫\'¹‡ÛùJóAžÜdß´¸þ„õ“?“+MmÉí?]y¶Ÿ‡¡¦ýº€}=Ú†Š½‡fÉΛÙéz±l¹·u±!‹Eäâ<;þbÁ&‚ÒÏÄ`¡Ü¶Ö†??øºé’²à0+çh›ÜµSm¢Éâ.ÿawø¤PõÜGß>™ôÓñõxÏ¥RùbŽˆ/ØñÓ&qæªÚÁðnÊý,è45šä‹ƒ9~•’°Ošé¬ ÖÉæ÷Ø›o€—¢èPûXµ>ì­îó|aXÒôÑô°·ÿ\>…|ÐÑ155ð^k¾”Ï“Y¿±ÝÔ_V0ß©ç“ÌFÉñ×ñNã™F§Ý·ÎQts=œE:N¿_…Ÿw“¡iD+M]®þó(šÎqæÈfs¿ªS.W­=u÷-eëÅðaš}¹gø6×V¶¸‹l7k…Ì4óê÷Þ½?õ>°lh\•}2 ¯ø––ŸïÕM£òíöêô~\v…b‡ç]Ì=ÎCbÄ|Vz"s¡íÒüe8Ø«k9­EÃ÷åÙc$&5Š_šÊ ½ž¤T¢ÂÙb–¿…,‹$dg9ϲtnÌb¶•–þּܼƒ-¼þóÍõÑO³lL—ìÞCëÑFkÕêeuŠ3°ëð§Oþb¬÷ï:K|W§}á˜Y™iz®kŠ|Äb{þºK«ã÷£?¨z³h•_³øph£¹»^—5½&ŸòšE”Ûþú‹•RÑ+ÓG(à5¸Ù]kdÁѦïòøº»Ò™=6s ««\`Äìú9æã£ÑÌwWªîüM3¯¨Ç=Q£µÌ<ãôK¹k®~ü½hµÉžûÌûB¨ÐR(c#/1ØGåž{äÜÌÁ×;Ÿ•ÿgôsØ¥·;=µM–ÿÑüýr3ŠЫñÓ3°OÖ÷ÿ#1;ìͤҘ"ÈJcN¸0ßÏ£•ò™‚Í,®ä×ä?´®½)±ñÒØäé³HÜ×Aú¦®çW’±VÓ)¹aV¹ÿä{n󧜜T[àpÛäΓ¾á•=ßv3¦"ÇתéÃá›±:È/´Ü›*ÍÉXÞ=w&)û>¼¾IwM€”zOxÑâddôÙ¬þN:2;oA¢«SŸßpþ2}ÏÆòzc-Ó´Ù«6èÔí2êMS¹dQ}¦5jOÑß|¦zE$þâq²Þá2]KíÛ[§šË¹¯Ei£í8*E¾LK[g¹íÂÇ«ÅçppK]æzùçF—ïÙs|…Í-VúöNú­‚x¤ÛdÁ÷Uÿ7xH¥úþ&—­uêc™®üVêh¤?»h\“ÛÆ3Ϭ÷=úòŸLó‹öÎ÷凯øœìÞ}¸>KËÆ¾]àÕµù|:úkÞk÷.¥åˆ»®D[üUµNº›­R›ÁÞšßñ~ åлJ~cûÚ:¼ŸÊ3¥Æç¿Œý·¯‡ãÅÖrëçÝyJ¼ Ì6'Ï͹R” áJß½LÓk¬7æ&b÷¿ntëOtk÷÷vjYg?àQì°5MrúØ[‡Gûèvgm½†‰||жœ£ç5a”ͪtÕs­˜´úýÛìÿzJÃ'0®H>"=ù¤â ¥ÙÞÖ%°trÉZªÕ!¢CÞ·ü÷ɘÏÑ]™¾\Ejßí;*{ÌÏ5ãþí‘ z нVsßR’¿øÌ¦ÈƉÝâf“eŠ·î{qw™Ö^«sUõk*$ùž8[^Åå'x›í’0aû‘{%ŸÎ ­N»]5–jùãÖw7mÓf‰„që\«¹ýCýº_/óïH«ân‘Þý2 ªž= lý˜ä«k/–·B»MõXáÞ9بŸ÷r;ÍÙÜZ[ôÝ89Œ]Ý&’Enf—›kðµ3±È!yD.3•鱞ÂÙ™+]«ð0TÈk3ÿHžd¶ÿYä°ñu¼ëŒ°ö¨WÝš6ÿÎ#V¼íCŠÝ.’îT¾É9¹d×Ý Ñý <µWÂÏË…ÁauŽŽ×þ.Â]Öÿ¡zíû=6ŠÞÖÎë÷‡‹äî§|Ói1 pù öÿªÇ#¿îÛ]KOoì}ׯÉË´'°fØ“(©)ÑaÓ'«ò¼(FAÎÞÝoî´¹ÇÐèà|½|ôüŸo1ÝÆß?°>­žû@óeKáêç9pÏu­}$ÛX—½ÕzaóQGø=/^Î<ŽaCmKýs¦ðuºÚϤãVï“}là:Iÿ¨v~—ÛÅf’á³¾íâúscü¼&ýòáã;L~Òq±Mö™ÌéëRˆ*}ÖM_µ9Çô4cQ¦ï@Âþq½+ã§ß‰šqóüº°ê M·½±ßùá]*¸ŠŸ†WÕvòçô- ›¨•7.ì§Y§5¯ìcª;ÌŽ =ZÙ¼M§6/áÄE¼´éU –/G;½Jë0òçæÓï[Ù/‘™W—y")ËXøçÿç ß¾&UÁ8Îç¶”+ ºÞ÷7K¡ÀúüÑ:il›ŽM#Sœ¢5*O»~FÉÌBæv';-*N¿{:”1o÷dÓ›vîÜââ£lõ0Ì;îïÝ3e­:Þ{Á{¡¤¡òB,DX¸é\îc[Kqü±qëe£8ZÜ¥ÏæGàÌhxw®½á]þP÷ãö¸yyË­ú\¤KßÉ5½½Z{U)äp*¿“Ü´W,º‚“Ǧ;æ^<>©·ÉþÍöe°Q·¯^rA—î§§]ö³Ïû1~µž?BWÉ´˜ä:ä¤þSM ’9*¾ F©ímAÌËÔEâ2’ÝÖ‡ëÖË_<ÜIwkIØnд~á;L¿£ï±›Ê•ñU…WSœñˆc깪Ì[.#©ßLµçï¶OäÛz» «w=[Å$ k]†›ùÔsüJÆ™Q·»]"ÿ_”)>ß~ÑI%ö“±¯KöE}nöAgÙ9“zìe–ø‘ºîB–èÊõMâãóQ1w¼9|¯QëÚ©VÄXËyÍ[w¿OñØ32ó=|J‹4ŸÉcÞ ¶ŠºÞ'W¯ê\^4ÚFïœÞÏçqBéi6ÓrÆ2³µª¸…êÒUüMgž1/K]ÅhÑ(Ròðíy‰ì¦Ñ?MËä{6OsöII>/u‹žÖêtè÷«÷ŸÆ¯¬æŸ³';ÇkÑf–òSê9n‹Æö·¯|æe:ÞrwFõ5}£åoYs=-…šzŒ Øûv¹xxŽ“²ôï$˯" +(e†Xp© \Vš{üz|å^éŸ]SI´YÒ·:cm܆Ŭöt[ΞÃÓ¡«ó÷±ðœ*”(•ÛÍv½_¸ßÏÖÛ@ÿýÂðh[ìSêY«0}{F^vÕù“û ¬÷ãv»'ßFiQñ°óð*cuh+ëYPÉŠzýE½Jó>ùLŠ4Þþ•MùÞíÝ÷?ðß2±JÍ‹ðÜýÕgswNÙ¶RÑÜÝIŸÌÔàkî4­ÝÊæ“§ëÅÍ`_ë"=¾šEm´d«ù¼¿;ÝNÓ õGEKyU¸ºã.Øp°ªîw¼4Ú¯õú¯>®ï'£Œæ³–:Qç#¹ê¿ÍÅ&“À\ÒYý÷ÈßÇœDÙu')úèî°Š¬•|,®GcÇ\ÚÊí"àf<_ÜS<ÛBªî_¿ÀüNä/)¬-Û–Xš—ÞÏ'ëÜ.­oé÷øä†¾×ŸcéЧòð詺SùÎVº[«ÿ‚ëâ®°~l+«þ‹óg©÷äávµiÙ_ž÷»2šqß ª³L¡½øx³pý†_÷ÎB_Þ3Z>¢l“œãÂ_!s’…ÅF£ÍwyŸÚ!+Üâíº:—µæ¯Uóû»¹^¶Àß0QSß§¿QæÇRÛ¶K´glq)~’º#¼åǹ²¶)O£èS¯¶|¦u‹®÷¼ØäÙŸvõé‹ùÓøT*³í·ª<çá~Fƒ¥Ð­ÒZɾìo®÷C³î¾§1K>ª¥Õ¹ÜÜ[4ð"÷hf¼8?[g?ð§ñhtßÄ1^Rw¯ìô?‹ijÛäÙñOñlýß_³ëã{Ô·¹çŽäˆåe;ŽÍÍ"½úÅ ³¯ú~"ÙïI‹®÷¼÷©5ÍѬíÕ²íïcxKQ7„ŽäåWmc$q5“r'¦ïO“}~_²½8|1r׺÷7_{ãeR¸èÆé›ÌN[—&‹Q4ãöá1èŽÞ×=$ÙFž³–ùWoê¶vQŒN®È©Óycý'©ã‡j™7Cp¹†Xªšwv»¯b-óÔήœ[7n'¾©“Êè—½¹\ƤÛÿ¦Ÿ%ùкø9ó[Þ¥9e‰õÿ[˜õólÚ%ê³Åæˆâû×b`qغùŒ»Wšízi]õ½áv»þML3Õ§†ûB¥+ªömuü•dŠÉòŠü>÷«WÂÁÞ(:cšÛxåÔUIÕÏ]-À2Q-ì©zևήªvhî8Gsu T%}î}Mîn6ï¤Àô4›LŽ?ß[…½@JSµw2¼ç||~ÛV9‹ˆ Š»]û–£Í/_çö¬Ù>6ÍÕ™6ºÿŸøÑçQ±ÜïnúÈ~ô\É›ñú‹Ÿ7MP9ÿ·?¥,Ë;烗˜Ë »¤žCŸ˜–ÏRå%kWj­Yâ+Þ¦^Ã÷aÛ³ÃQüna´œ¬¥ž¯ü°Ú7Y))aü ô{,k"\{+—w'Þ ëäæ3UÚŒ'Ó J=Æ?¥Ïº 8tI“FÛIÏyàg2{¼/.K]ÿQö+ÔqXm5&z^w):Å‚Ör=ûžªþŽøÚ¤À7èxzÌ?E߆Ñ5ÓlÒÚGõìú­(ˆ\§9fã÷$ÏÜ‚ÐlyU•l–7ÜüÏC ]yÊÜÐÖwÝ–|ߎ£&Ž›‡£‰ÌÆç|yo '²›0™ßͻѠ÷äæ¡åxý¨0&±««Å4",2óœœoOå…UøßÎaÀ'Uí~¼¼IÖÿ6•uO Ô‚éðX6æïÿXœìÏÓïü\| ·¢jc¿ÝC¨`xXŽOö]âÏ¡Åók{ ±Rôÿu>e§™²WÖî5øv ›SmxÍVc<3Ù*îë—/MºîX¹m;÷û}¢‡kŒÊŸÏÏß¼yÙ’+-òŽYa}4ï³b±é^N›Û~Æ1n8ÖP -øå;4\—;†Kœô÷¿÷kÐÔró&6ž†·tµˆWµÞú*g.oò´_=ÖI£‘ ³-K7¼v»*f—5ªúPK|½ùoµgš"‹bó Å$ôZÄ3h%{´óú,—SW;ù¸îÿTÛ1Ø…ý¥õM;ë$8ÿ¹ky,/)ëßQë'‘øÖEþýð’óKEàQ‡ë_U&©d´hØÛwº…v}J?‰ç"ßÌŽ”¾KäTý¸fo¦–Nóàñ]œpõ=,œºµÏ_w|ãø¬ÿåå?ö_ß§Éo4—yþ- é{ͶæbÙ½±ü,på'ýz¾“oV•£X‰gîÑׄè8çÌÕ‡Ÿ†í¸HÒEžÕµCÔôÛvh¡gñUÊ\Ýåê®’M¼4²ä™ø?ïêÎ}Š×k̆gÈ×Ivz´Ttšpûîa@†Cý¾|å}*^uY ÇG!/_’ôýò‘:œ=øt¦'rLvQ…ëóB ÛþòþºÚÀZ¨ÊíüúN#¿CY÷ç>·Æg)!8]Åêİìpºµôó»^àxël&¾8ÿTã{«ðhYtVý\Ê´ãöÞuŸ.¨²µ¯rD‹ðèv?-Îì\ØZ¼YÇ,b1Ÿsª³û­ö!ïòdìþÚëí¾;ˆúw>jÖÆ+»WÆ_Yª¥êøÐfׯJô}Ì´¢¦>šþ3á²Ï5ëV¾ÅMƒÏ´Æ¾§¶`uC;øaûݪ¸‰j;«&]"6czÏÎ`bLy¯ÿæ(+$Êk<j€bÉ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü7 ï ˜`x±ŒRëÛës»·¨ãÛ¸ôt Èt]àÁäﺜ—îǼë nîóØ´Ê€ J^ž¤h*ƒ t» *¸ÒÀР’ øs”£a|ljð17Ÿgt¡*™Öú¨û`ß}åÓPRóì)è^¼yï/ÐÑ6òÀ©Ðít§Fºçø vt\ë…QBƒ¼ùï©;àØŠéÇ®=î9ÊÃc¶°Ä×^{Þg9Ü‚^3e¾ûÛº®¾ÀëeßG»ÕîM ë·OsºÈÞâ„«ï½¶oeän@Õ[kl¦Üôïêîͻ5A7¾^óè|pXW³/cTåç²ÞÐ:V›ï¾xîn ëI:ÎàsgÒ€^fl B›ß>m  ÷Þãß}×¶\ú|àÐòè€Ý@š{äöI°P؈IzëÖÅP©´0&š$@£i›[ëHº£ #DËŠŽQ»(î„‹°®º„dúètÖ©îδҹ¸ã'.˜L ïxuOœ©!NÏû{£Øö%7½yîûÒóe÷ÅRî_÷YD”Vo³m«;jÚÝ9Ô,1¡ t§¼wXÖÖ]Ît2Mf&ì;×·Ý^ªW‡n}ß=¬{û2‡Ž¸áÏvÑ+=x»yÛV,ÎÜ»ÜîKÞwœÛm{Åí­åW¨Ô|ìŸ\Š+Ó˦m³KNÆuXZŠàì;m}ÍöÔKÚc,k-¯5ƒ»i$Hk;»¤û-÷½®öÀô²TÃi›3*P›Zßo}ÃÔyò‹i“%«dfæ©©­°Ù-´¶2h-÷úô„®Æe¶[,lÔB^ÝzmõΰÚ=ØH³îÄ€ ‘sÝÓ©²Ì µ;c@éºÅ©j¯|ï¶fØ($Qì\é×\ºEóÚí¶6Ó­;hÛ Nx=çwƒÞªžm‡n‘Ö ÷¸zÃ3µó™WZ¶¦Îû:ñlÏ^ã{·Æû“¬§Û¾ÏUV}Ý0÷i0 $@Ѐ˜˜&M2 L˜™FA 241 44h@£@4˜ ÐJ 4ÐL š2hЙM0 “AÐG©=)ú§è&šž˜OQêf§´£j§©êz›&§¨Úž¦jl£Aå™CAê€4%4Ô"!!O*~Õ&ÚJyOSÉêDÚŸ¥M'¤bzP4Á2iê 4hÍ&F†4 @Ȇ™i‰ &’"Md!¦M&ÔÉè&4ÒaSôz™MOÓÔz£õOÒOP=CõOÑO„™ ”ÉåQ zŒ€Ó ›P’"€€i  ‰©äi 4LCÉ4Â2`&M&Ò6ƒ$Ñš&˜SÍMªzz54Æ„i£&S40ˆðƒTõ=‘¡£TöIâ4P*(€ˆÐ TÛOIÕ#ÔÔý#ÊO4hFJyCA£@Ó!£C#&™¡“A„hõ 24Ј2hÐÄŒ€4hÐD×€èPµÕU¶ÌŸ%QɃ•K“ǰû]¯>Âg¶Ç¦þüfkŠÞÏý¯õ“£˜þ.Ó‡þŸ÷þ_úv=žjsöD™¿ó²k½ª'T¢ÈÛï,WÚÓmªÔºl1¹ ¿çˆü³,’0€f°ÇXŽ3‡ôä ×ëÙDÑZ­¬¡RµÄ"!ㄨ©K[mZ–"ÅŠ,šaYRTO½“ñþׇº;ΫÕd½ô?ßÛø¿­AQ÷0S f¨Aø>®¿·ÞÍÕ$¾=}ñˆ HaUú§¿õ¾÷Ñù<ï§ùüÁ:wÆŠOÃýýc±‡ Â*(õ)%ªžÕÞ®¿Z”ÅM€9Uý„ày;òï ¯^ƒ5ú±èûe󣛿ÿ¤¨:4ôÞ®ïß{±µúì8¬l€Í&#šÊ]ÆÏÔÈ@ÇÛ0 T k!Z’™¬ZÍk­3õÜ2i¬ªÛB«m†2¦2B¶­@Ä¢*Öb`„‘Ïèä™–Æ?C0Cëë&µ ŒñIýû ðçÍ‚ˆþ„Oe3OêcÙÄEü˜€/øb‡þ y„Dð#÷±>ªäź ¡êù¯ÔÁþ¬3ŸD|Ë>·wʳï Zr}´¡ïÎ}}Æ'½Pê!üøW¼0~=Ru×ñáè ^~”{9ñ|¢œžÖ¾ÂŽŒþY£vŒ“í©ÿ$ÿüf 1?Ëíè<â”ý·í¨âIÌ>Š!³Ó¥]اÝ}ßÉ=ÿKà\ˆ§þ^!åâ?Æe«‚k*î^ª§.âñÝ<½E^=™.®È¹ÌÊÉwTIPD<,‰¥–+œ&.܇ɩDÂË… *®ûMý/é¿ìSçÿü9þUv™ù­äna÷묱eîð±d6Ô@΢Ü„ù“ʽLx]‹\¥Ö´šõï05`å‹Î®­Ó]në[7ëܹ͵.¹¹§[ѹ†·Z75m3]ÜÍiÍ]ïMÜë$@™\Ç‡ŠØ!Ýê"U+H„^\“1‘ªÊ¸ª u“`U:…w Ô4Ý»ÎCÕ¥•ªP=ÍE,—Q#ÜÔ]CálÃó}hÉ&¸ÔÈ¢!çï¿ïòò†b´ÕDîo]¿ÝO‡¢î{¢}ÂÞö ¹ë;ÏýþÖÆš2zᲉûÓú>Ĉ°AúIùrÏN—ô¦Â¬›E*‘;ŸÝ´ø5ë°¢(:è­OýgãËgj…ûIG_JµéJN}ŸùO• }á2ÏùfW˜ ›É×&阄L ËÆôÀGšá]Ë–ƒ× ù?øbºP踈ðã‰ýiø0~wÒÒv$?Û9„ý™ú¾ÚŸñÅP=¤äAéùϽ°Í î¼~–ðNt|üÖCòà vÆ’H’“Ì=Ì£ÒaîÿÛY^ö¶Hî»I/·úbÁxC›(ìÎ’”†fÞYÁH—2ÉK0¢eõÍÝ?2:foô¡ÅYáZðyé…©€øÍ¸"u¤  8Jd5ê¹ß ·µ½=‡ä}í¿úéd $\4]šéy‡uPÿOŒ º;Ú0q ÇC‰ŽÞž+So£nûp{­Q uÚö4MoúβÅÚ]?Ã\´­÷óF¥w£ÂÚ¢(Áøywþ¡08ycÖ’. 󃣡LùãÙÕŽ.?Ú¾jé£þkbÕy¦" @À¢ÎÀÄK*¢éßÅ´¤EŽfaᘎñ³´Ø-ü¾UÞuu€D.‘‹Iß@1H8¹^8ŒÞßW¦qDzxœ1R¯"‹xk¤úC5cŽ J~êsŒ¨lp¸è¬RD‚¡0#ÁâE~6Éáú&<ÕèNO› TPƒpÚ«‹>‹‘Gœ+…“­R5,`AìÀN“²… ‡Þ@ϼñþ_—æ±äebßzÞ͹’>¡Ï:£­€™dneÌì¸nú:ç”ÛâñFM¤ñ9¯0òÎ{ŒS&XÜ‘¼%=:iþ§êc‹ÙO©UùÖ¬/{T.SU Óàåõš­Í‡ƒ«k·Õþ½óùù¿Éý³£õåÖvïêöµZ›GÁƒ"ÈȵÃ.?Ïœï³ßkÀc¾'""ª•u¨,'–O‘§v§Ë´Ui¦Ù=Ù~FcÏÔrm‡ë]=¬ôt=Ø ©‚fÈž_±§Ä(.Î „&˜úˆ2´X¯Ò ñëPâ`¸07±`ðUÊŽXLZ”/Û^ÕßÑ?ƒÕn6xXº¶¶5À·y™¼Î)®q‘ÚœémÇãYNçÚÚÁ¸|kW Ë‘¼ž‹ôèP©Z„-ˆ»”Î,̨}üTïê%:×Å?H¾…c½Ã;ß,¥>!_ ûRšögS‹éÀ—3).L}éûùûÝ%ûª°zÔ‡™­Ë1©Gë­ìÔ#ºªÍF]]f_®.˜¤Ë§å¼ôÛÍmr»Ä¦Å‘u‹MñøÄlQ†&SØßeÏB‚PôFá7Õ¶ãM»C§Ì-ü<Øœ¡³¶Ë8ÉLÌŸåAPd ¾Š U‰á -¼ãpRàbô‘V ½úª7LÕ]·á](löcP윸r·]üRZ]$çó¸ÏÀÄÃ#UÄõömê–#À'øŒ¯búŒ@ ÜäØdö48LjH>íüáìÜq¿|§©±#ÖÚ*:~á.³Ô©Ù[Òö—ßýÈj_ïð-§˜E¯ÀuŸ$ü~;IÎÈnîmÕkéÌc|HÆØ7ÜwÕ|€ÃyÝo’kõо7y?Z=o¥©]57NÓs Kü”dÕÓæÝÝÚš$hE4³ÍŸD ?– {_ÐéøÓ  €s¢©üI÷0þ·ó?±1>Ï÷T¬þ¢òëþ‚€úA@{ >{©µt‚©øZ¯æ½¿õ}ŸmŸé›Z›˜ø’­Þ]º´nºý®&ìÏþú~Ú.Y¼ôjÿƒVöÌçZçî}^ÍŸ¥ÚÓ¯G³Çó”æH­„ÈxªŠ¢"ˆ¨‚ÎÖ)RêO¨ý/qÊpÍ föïCÑá!½È¼ÉÐôVýønUÿOéþ xn`õÁ,`®z¡Œú9ðü÷€s+)̯gnN©ÐgÔg‹ŒÞTGGχBZ((û?‰ÕÆ­vôúkÌ!7©!<ä&œuºilЍ1 (Ä CAxw§›ë^Òß>ý;ú­ólÖöªÕH¨:³¨õø¨ö¯ûòòR×Áe ¿¥mÅŠ+ìÖÆ_ÞÆß­Ÿ.— ‰¯Fâ€î‚ æÂÉûd^ªü-8áQ\D2@TåÛ›®¦À¿ U!*¡%*B7‘„ZµjÔ¤UH¤l Á`ƒ"Ä #€áÿcž®o_ô¸s~-†1–ÖAgà /ì5ôe_ï\LGÖ£ùçµË3 ß2z:nÎŽrK°•ßto"©½$ILéUtK…Š„ #%.5=Ò˜ÍF“6¨ßÈ/ã{¼¬¿pïŽÀÌ1ð&A Æ ¾|ÞÊ™ã²O"QQd©QNd˜É9/MHØH‚ZªC¤$TJ UH'ñæ6Ð9um³Ã*_ tâÈÄ`(†žßN›õ4¼Ùy»XÛöcµ7$˜~Íí#ió{M¿ÃDŽܟE¿\5›sb¬“><;WÑD\’FB!$Ux²à\æótné¶EU—ƒF»d'3=ùÚ²))ªÝ)ákò½ ©µu6·U,\Tºá¥uÙ^Åõ©Šçj©&E¼Ð¶¹þ›çvFInL‡•pSto÷]ª˜ôvO?[Ã9Zj¹–í/ÑÔŒ‰sß(ËVþ\¹ºqþÍhXYÐØ¯ºIlªç®sm«@ù±,H‡Í÷viƲ ‹BH J#"Hƒ#‹,R,R@„†^P£WJï‹tòl ?©ÞrùÿHë‡BžÖòS¥!½ ¹ûnz}[Û3ám"¿èwž÷áøõ‹ëdUr/Y]ø:#jEæW¹s"'œTO¸Q×åC%D D‹ë¬wqÝßÞÝ,aµYÊžÃá Þd!/¿‡"¡èv‚`yV1þCøÌä?O¶›Rõe-Ó½0Aæ)µÃ¯‘ —`E wr·³u/ðG h‹ö ïª}âîº+mëó÷w<{}Õ¥êŸ&ÃéLõû˹Åá΋ݸ¨¾Ž³À]NåNy=õÄÙíhFEŒê so| òÃqR‡LŒ’ ÉAºÇ ÍvQlâÛ£Ÿþ”uÜü¿Ëeür2äÉÚìh²íTàᵺz}_¶¸É¦B·1«¯#]mµ„Óú\ã£,:qa:øé‰lü)Ð%î—!„bý¿×îⰔذë=qüWS“YÞP¤äMLN~¢÷Šíã‚¥ª¨2µK‹UŠ L9ðén÷URMQTD·)Î}ø†K¨×ç\)d×Ü´ú–­2\—ѱ!+î”ö²M[*&Kó(ƒ¡WƒTâ *‘@ªÍQ¯Q‹ÓnÒÖaUÕBÑò¢1 ïÆ~žHžAÚ*ciBzÄä‰â‰q«ŒýÂÉñÏn|]Ì&ƒ…A}åi{½pŒˆLû…Jzç¹òsgÃàø1±;‘Pцó-®Êª±Tø¼5Œš×j†Š€G³æ_8ªqn«Ø…ÊÜ&ØAÏG·HÊ]¬NpŸ·äþÅÔû¬)2Ø*ŒÌ‹þnß$úsòU,)d¦À€!kðŽR¬jâ*E;]Àà„ùâXí1B¿w»Ãz1›LmeZ? 9tâ‡Ê …Cøÿ“.ZTþ^ãé_Íyε\:6M꟒…ð«JjŠ*Ñ9*^›#ßäŸ5·ò^%hz• Ô‚§‹.…tùûoÙ‰_F×ÍwªGtDÿµÊýª*¥ØÖ«f¼&‰ÍÔÉ˳w<ò*0¬µT²ÛÞíÖYª&Îͧ <.{’é,›êFŸF3Ú©ÉÓ¦×IÎþ€˜^ò%ÕÞÜëžЃïy)ãà0aÏܯ1PÍL”ÈöW†6a©N^xec!7B›æÑ&ÈjP:éS%êç¿*íú¸_;ì5Óg÷¹?fn㯪²ê…¦˜è¤.ó©t1MíéɱÅLrðÂÓ, -·\'·[8®³½RúY2˜*ý>P¬m¹à19ÑO,¥:GâúuúžaŸDõó? ]¦ õ“-hHµµCR¡ÛLÜmZp¶7dîY£u)ÄPã“a”G-øê5-y"’Y¬/» 5òû$]JÙëxp©¾D•'ï*!ÉtRQdDÕdíPMÑn:?ЃØÄ\䨋cvZ0ëØ²S1MÜ"^¡p¨ë5;ðérïF/¡-Öß±›êÜý—î^Šs>êXÖJ–L‚º¯±Ìº¬C¥H™y>Óo-²Ã&ók‡~Vu3›M,,“/(K=Õݶ‹¾ã¡}ÿèôÿ»ûßÚwM®3i+Þ¥å%ù¦ßg›­‚R)1gí1‹³xô"òfe¼{›fŽ«—P†u ÓQ¼/ƒª¿mJ,ž…ËàzÒ¥¡"121¢@3³ŒGä0¶œ?¹y¬2õQ*DÌ¢¥C®T߸4(@“tç\8M3¿¤ú×9*â:ö3ÞçÓ{xO¾2?k¸íbœY¹ÀÀ6Źv0)$§+ãϽ8!¯¯?’:™`Ó†iÒy^3Iešt„@ ÍøS|­àåÕºk sî;·Ç@ –gü€qúŸ¹Š.—5QöéÈø­´ŠZ5fä—·ã™ÛÞ5‰«îöè€ 0c‚Á£L8Ñn]{¢ƒ…¸È5iÆ%ä€?|ÇêljíÕÜíâ¾î’§gcP§+›ô4°&ÁnÙXétS;ô¼ìEüûk:ÍkúWW©›T_£áC°¯ˆ¶ø +ØTu3¸[vñ'ëê¬àšý9çÞq¶kËV™ÌXŠ;Pè¨rhɧ®KÿtúìBêŒ[4¼¿tðHôì0Øýå~ª>ª?¤¡£ˆ†¾ý›tn¾0ò\ªέpþ˜ºMëÓµÎ\¿°Pa—8ÑÎak(¶¡%Ïsf Ò©ýðCrÒpý»†¶ÕÏ%‹ã>éqÅ–Öâ= ãúy•Ç—M¥Gáàµ/Ýï WM;¯ÂÉ¿ðY#Š6K ΫW=¿é®û4”ib÷ª:t7zXÎÍ%"ªã mý*ÞGç ø~Ñak.î”ÓCÁtg?;évtžYá8Ï«S;áæóúZ£Õ/Û:¾u‘°ÝÆøšl;/šï‘‡ÁƒÇ5_…m±ÕÆýÞ[÷;Š\˃s¢ 'ï/³ÇR©‘ƒœµ¾½ÝéÍjðÖñt˜LÏ‚Î:²Áaæ:Œ8|wfGub·Dêî.¼£¬˜/ЫŸ^Z^Âæ÷UО÷Øë­û²@ˆ. *H·¬5KþÄÑst–å$äö¡x‘7Œo&Bý+8•ñã~Óó@DWÓ;Óžûª&ß*îñwÍûËÛɬSÊ2úþylC› ‰Ò«Éˆ½puì˜= ËóçFqV#ÑþßnÓ<ÚLMs"Uð(t4òŠõ}nª÷³-"à Äh¡´t!PnW]rÿ…–^Ž—£´»“¼€æRÎm¤®(~Ыu†¦ÊÅ'°ÎÔH Ì&¯£Šð_ÚŽkOûõ ½Þa1¥ý¬Ù’ê¼Ì¸uõ[Næ¹e]F¢ðÖmsß8‰- Ã@qç4Du7v߯äŒÊŸ†ù ÁL¹½ÇäQ]/˜×º wÁNùaÒaU–R‰Ó‡ÿP47Ç;g  TŠ¥³>ëw;¼ê›[jãû§tiCMØÄÄçãxè)4Ýå–ÛK] sËÐmçš³GÖ¡‡ƒ’TÛ&··u»A®|QÝŒïØé1©¨Ýí³­@Reñ²W°eõwÏ^­7Ùl8MG+~¥ò¾Ío/ &õ-M æÞ«=ȹ?h‰ÑÕrC?[°…–Ì,フ-JÐ5oV@Ø-ç è5¾ŽGõÏÁà¦cê•"é÷Ö¿ ØÉéÞ’_r9µE‰•lqÌÑXŒ÷—Ì·†¾êT]³þ=‹Ÿ¥ž[Ýoœrz>÷ž“[{o«åÉຶ[¶{à DnQõ0B²Ö^‡NíÌËài²Ã¾äkë:´¹Íå·ri.ÃÛÃ=7sWqKžåbé|¿_¸ê“°d LDˆöóÙGùb ‡œþ1É‹ÿˆ;àŠ0÷Ãí¿&ÈüãùJ鞪"yúhð üoº+$XíNÖ~&ô÷5û_ìô¶ÂCüUHþˆM®ßVÕÁJ Åàb—žv–ƒn¡ý-Ë…à^&~Üá‘€ft]ƒqK‰þÍÇ“•‚{¹ïüñTbt¶|UŒbŒDGÏÉ¿?pyW /4³!™ç¸ò7¦É·F'Äÿ&øÙ;ïÁ³¶!Gú´f±²A¶z žÖ·ÅƒšbAq€c®† £ñ`ŽFro”°oï4ÑœQG4bUá7¼¼ÃyÈ3bˆ!™Ý¼Ö>¯Þ6lj©²¦lUm7c#)û@Ït4Á ‚ ±`²OÀþŸä¶qØòté3({¦©2dŒdþ~҇ƓÂ*VMœµì£Y¸1š}Å>•9ÊTüôùrI i"© ‡)üŠß›@2<øœíb€ÀAËÏžz¸më¡lO×Pî òª¸ bÎ2bÛ«à¶À+=¶{k$ POO›Z"F©%RÛË$û[/&ˆtVNaϪ†µs'¸²åòøZÁU¿«³‹ˆêltM³¬  ®YI ³nPTŒ‘„”p Å8¬H'D¿Ñ²VçË«ÃÍ>àýð¢yË)åobÞ\sè@GA+=]”-go.6ót^Pj‹ >ÝÔÇ*âé̃öG¡7_UòZv¯Jã™eF2î´ý¦GÛÊ÷3í¼±0ðÅGõDªÓ½OûgîÒN£óù³Þ“9±ÂÔ¥Õ”gxÞ¶aùÙqj¯’éVëXé½|¯ûì¶šïÀ•EZŒs³’"]É" îµ/ŸÍdL¿ëC|ÓpRyÞWxjÓbõVVjmhS­=[ógWJçãÝ €žkèƒÒŠË­‹åÓD\]jõ¤UgÓ©K,œçDã'î°MIô-OéàœýÒ;ƒÖtTS_1ö¸{ñaTãYpÚÜÿ‰¹Òâ͆¯L[ÇñsvdhkOöW ½¬§}økjxNo=s©g/ÑñþÒ?çm”(94tÁ´G¹ë£µÐ£)yD:9\ $·DµZTãëC˜aÕãÚÇ.JÊÈnZ¸ïÏë\ã®ü¬‚‹ÚÁq%@R ,-¥D–”dhF¥0çúe72a2õ¶6"VîäÕsØn ’²ÖîS|X'–ì!‚™˜–b5=kK.:q•–MY´UEQEQHƒ¸è+27…etÁh§•84— ¹Ãñó:I›]þl\ŸÀ<þ,ÇS†_=¥Ì÷y¾_b°6lZFK·ÛåºÊŠM™b¢ç^L‰4TTAU×[QaUdRj"Fº;½q•¥Ü–úXÕ„!O“W¹œ ’0Û¦D‰4…Ï6t¦þ;ªÚ$]6)>%€qpnYÖorvl_FåmZMG^l[¨Ê9$UH€**Nmf©ìˆMeÌ.’7)M…ûT€m=EÂl7sÆ;µ«¾wnÛÖc-Fu±ÖÁ1mš“‰"¦Z `«f €ŸØ?ªâG ¯ª×]»-ÝNÝi®ž£Ø-4(ƒe·7™µd›m›ž‚Ò™fÉ©ez·ûÝŒùlÄÅqÔE ¢‹4A”üdÈS&ŽzOHUêR:¶›Pi„GÊúÐé;{Ršd›~î@ºIWÚÛÀ"‘`osÕ»òü˜ÿ9TT]}?4'hE¼\¼ž8wüÞ¨W›V—yüú±²˜x¯yò´{ŸGtl]uó­Ë…×ÝíÊX¯b_ìÚ_³žÌóóÆÄ'ÍûK)jÕª¯µÃ¶Ò™"# DE¼ŠÁjRÔdX@Œ`IA,gG´Ï¦QÁ;ì¹rbuy \GSªL³V¹½ÞïwB@Qc»‹èT"¨ªÛ—Ó·`íνxQÇNÕ0ΔCÄB¤l½ã±‰¹OçæCLŽqf‡¸¤©K(cŸ•˜p`šÄ'©¢ì9!)ý"õy½Æ•ò›;~ŸèóåwV‹áƒ©«*û«!PUËØbõµ)s½¼üÚkñØK—Õ²~î=Ñõ}šëu…ö—Óu‘Ò}GÁôßÞ™a¿/ñõ’êÔ¹OŸÝû û˜sê¢ví6Üög_íZZ¼Æ¯6~ŒÏÇÚwñêÕç+‡7GÿVžáhæÎƒŠÇLþ¤üÿ8Ÿ’HÞÒõó?›Œ¾ªy¦w¬‘õí¬<ªE «ç·xÃ2çq–ÜÏI²²IO}_uÙoäé/Èû‘3:"š­·Ýdõ;»“€ÛÛÝ_fTú”9"½Àuùr²ÝÏvd( AS€" Ð*LôRȪ+ˆfÈ Õî ƒ¾véËϬ¡4ã$áBq$>ª1â¿’×<¶ý“oâˆ&Þr@“íd‘=Ä‚tב ÐsÅ€1Mß;\µ””@M¤=—”š6–º€ ô “&›æâïÃÜ NÅí³Rÿ•µzÚpàˆpb€öñŠÔ)Ý"%ônðØAW“¹ëö¹!.ìQráÑÜ<*,†– Hi<€Ä=¸§»wÕÕê³/„òÎÓ\¿aÝöxM7h""5¹d5W ©Æ¸ú-Δ8a½Åß_WBÑѵ0°Ôu§ÚäúßY8츰²¯aðtú˜WêöA¿·b«y•8ëNPˆ;õsøÕ¢@Þ–seðë¿Ù©Ït>‚£fº.™ò“ïè¦^)ÞhÆ>]ˆ¦ãWmÇ=‚­yóÜH¿CUoƒC,õ®,—É×W°é‚^s¾²Ïœ¤‡i}¡6°_¤,…èÇ .ð:5[óE"鑜2,ö™˜D¶ûíõÄB~ð‚ Ð #õw›LŸå †FæL×¹Q+×Õ2) L³V½\uQFPÿöZnž>¶96„Z¢¤==aÈãÊå7¡µ59ó Œl /V@ÚÝí5™eÍåªvÚo»Ù#ªÅÞ{æ:׆”Ma¢"" Kƒ(&~›p啨ü²;:›ÍÉVÍHÖ.:Œ¢~B ðŽ(B{Ã!жK£…U:W™Fˆ­Ëy|uG®‚à¥xÆ$£Äp@IVG ÕNz8Ü] †Éæ à—Ae×jQè(/¹ìÈ+«l>2ê/–ù¢·J—{˜ÝdMÅèúÝ$[žwβ²øÐ@DAßHY–6 a6¿]ÍäŽbù5›o¨ ‡¯Úì!~“Ö@íp{.ö’1\Æë›9Äæ÷X2¹m3³(^žCC‰X›h 7ÜýÃaaì›Ï)¾p"f=2;Ë„íE…=¢¦—%ƒ.ÁRÒã] ‹Rìƒ"[*uäŒÌÀˆ š¹ù»õW×e+ ÒëH³a! ª¥½\»°—8˜b¡eÇ;rÄÞÒÒí„Õ50ÖSPN®l,qëÂ-}Zo{ð޾Ž;DÆ ÅHqââ­ ²á}ÜŽƒ_!‰^í0 ¤ ^OÄrì¡,ïïkHT¸Ï¦l¤ §ª|Y$Š“Oã Šž2€öbŠ£ßŠuiÉÊÔÛj´<­³ÏÇ$;‰sÚÝa"'!A¾ÙìeVÙÜÇ7=T,(0´²Ð&½XÚñ3¹VûÌ#á~½D@½Í”1ëLxˆ»bI)“ŒÆßF d‰\7UTÂ&¾à@HflÛw© ´¿0Æèas^ð@G)äãͱ¬ÏÅX¨*Šõ(Û u;[tmè׫ÅÜ"‘«ŠØ»’å'Æqm jÇ»ÏÄé MD=|J&žæìxû¼ÿ'¶ìø<ŽâAÈDê÷p°kR. 1NsÌuìÜNº @K‹ÿ¦}¿ÆM…úʪ¯Õ[QÊ)Nóú¾\ú$d€¡Ò@dÙáúžï?7ön³ÁÑy¥Í %ši-lr³½ë…·.Ÿcu ¨-wŽ®¥ŸGÇ”±TÈ™l1ÖÀEe'¨Tô¾^8¥[¶MÒb?_í+ÞŸ2Í}d Ȧ~˜ì¥ïŠ(êPS ø±(ŽìÒXÂeÍùà¯h™ý«S–žÇ°B0¶gÆAû†Œòö—ܰ)éR„’ì<Ó§zñ°šæ¾æü&²ìÂOå†ÛóA&·Yìk¾v›íêî¹0IØ·a£ËÞÍ´W¥cÏ4œ6ÐA<˜ïïÕnå²Üí¾êÍ).<¾äl.B'—Êx*/ŠÞŽÍ¶<¸_M,Â9ùoZË…>¼¯¾î"©5H)Ì¢¿²÷Ê×èI»_«tý~yc—66óɺ»Ý;t÷_K»Ÿã7@T[Ô68ïªGÒuöù~^ôN Ÿ8óÊ>8Œ1ç“=³çʱæØþEn·aTçS¡Èø»}/ÝÐJ‡öÑÛH·¾ãªºd¾L¼‰ÝV ë]ªMß6[Kî“U£§t䱎– 7Ǻ¿î×õ‡æ&ý>" €˜ÆÛý,ðòϧ¶í.5&LÚÆ1Œ=<ÑI¡–£ÔÏí^·[jèEo_rȉț ¥-êU €³)0ÍçÛìÖ~(Õhû¾qð[Îú•Ý+Ÿþu§„E»Î5žèÎ ÇSN£H\f[~#&o‰[u!L:¡åïÅÊÞtj‡¹`“(r ªuž¦BñCë¨:y&iŸ¯Ê9sÀ÷J/ˆö.]‚ž¹õÂÿ%—©½S›vøÁ+»×î#ߺþp@Klá~ÿT~!ˆÁaì“õ¬ªVÚßå:;¯Óžœ'Ï×YÈ©àÀÖY÷÷çÉ÷ßJy"£ "„™´ï´:'–Pô6A;d¥Ä9­+@“Û‰°ÅH–+(ëb¯7ɪ±õ¯I݉îcçjb«—©YËU7:lT¼ØÉäIìm·å!á¬F8¬y 4…K¬%W0›y<%0h)dlÒ«RÒÅ£¾lÂ6)«.µ¤tí…µ±Ãàƒ­Hû[F)«T/ Ù‹>4Á9Ôe6³/I×Á)dî{…[Û}BæBc»ÂÆ#R„‹6XÛAŒÊÌÎ÷KÛ¬}¦fãÎ⋜¬ VAŸ“ –‚¿©ÐD‡°ñïÛaO¥]ä¢Êíe|o}fWÞ Üzzt´9k_Àç[%ß\Ëç„7X°e6ÜÉ}³ô&[÷k9qžp™í!Ãv¼qÍPÝF¢ÄWéataà›Tµ«IvÅÅWžïÔ\æÁïË*µ+K+*Ú¨Å`?EÈ_dã$'”&o!À³Á{¤IM{FJ?™ÒÏ?<3Ã'â¦ߕ¯=Ø^¯œžyà ½R¸x‘¹Í©‘Ç«ÇÖåZRñ焯%ÞÇxÁìVXúÍdµu²¾ý¦é’ÒKúcH9Ø2îØwµ)j&«© —jÚš‹nÑÊ5$+Æû”x,—|ÐhGj­€jˆˆuÙò}ù–¤¢èð]­ï±/åãS`¨›Ã œ0Û&ºT~Ù£Ëf=²íÙäÈêJ´‹‰êCóú?9¼O“npô‰qiš¼3ÖË4à Œ„”&â|WÂÒz®ÍÇD¬ÙiQz’¢‹y-nm¿ Uu=˽b=4•h‹æ×¨Æí„ÊÙ\¢:3ǵºoσ0B¢«Õjöbг|¡ßr‰oSUíjù4µBó^i¢ñÔO2”Ù~PšÊÐù¼Sí(¸MàŒ©»mðî÷§Í¾XóÚ–j‘T/¯¦:Ö¥Ê!”7qÏÐRj·õ3ŠoàÚ_ql˜“ã7ºã ƒªÐK·l*ÏHíÔÖÆßjÂ3‰{²Û3í]¢gÏŸ¬”eòí.è9­®Äzáë쇎ù]ôùòÝeW–ì­ÑU®ŠÖ›ŸvŸCŸ¨á\¥– ä¿MŽëavÿVÊ1=sZîàþÕºœcdi ñ}ÚãÝÔÊ-Õ÷};æ‘Uj17_©„0ÙƒR3éªq³šÞ˜ßuì[wTåmüíbêè´ÝîEò‡j%:)B§¯--â­]Ûk呞ÿ¡üî¨õá‡n v# ºlÊ&ú÷(ù_ËÞ.ôò2zê8¢{ …}"×aa‹òX*¦¡hÇÙŒF›ó]”B¦ëZÖø9ï…ê2¾ÌLK¶Õ¹U}õ8‹µƒ×"•4]ªYš½ë²…U ÏrËašÌ!¬{öV/N ôHÝZ]n2dŠ)y9ïÔ{ꆨ¡Fµ:éwØËÅU9ØQÜé9VuÎ84T(ªLûZ]ØÄëkC‘T¡yÏDÏÆpò@_Uóè)ß~º)ÛáÏßj67-[¢°eÊJÀ8 ÎÇzä§Büå”Á³3j…Ä &V3…MVÏg1éÁ(TTeÂÙ”=ËãmðyvŒGT\áÖ–§ƒ`VÊÜ»¨ÐíhëTË?²Ç9¬Àñ`0ÌÌ|ÎŽ£á”õݘ #¹|w”±Z& Ú@ïa‰ØfdPùîG2ÒÉ|“æŽxR,PŽ­[¢\ÕÕeg^º,Öœ›ÄóÂÍs`öÞkæ¦ã~ï2C£fk÷ž/nžÒ¼US$%¨„ejlVn’šõóÄ9”à.Ø¢-Œ2®åƒó ³ßáŠÅnºî#Ôs·¨êØxJbB]kšêÀçá­ôºPŠ5…2ê‚mÌO–Û¹—Ó‰ Lª«)Ó·«ÅXmÈÕ¾(Ê¢–Š›à\tÆRÝb4“nçÕ;4‰’ªÊ<ý‘Nnî¯ÓÖ _Ó£³«ò‰²{‹Ñ®‹S{GmÚÚç|Þ~(Þl-?šŒAnÅ…Ra´j‡s†ìã k3XÝ2åUÐ99|%ÁåA#8â$6ÝÏGvkšDÉH-ì‘”#éŒÍ[0¡µÃ9™®Ê–ÝG=«L’9ú)–A´Vt9ÅM¨ÞˆdšûU¢æÚ9&ˆðƒ$Ô:ûIrít’ vsm=!é…ðѳ«;;.Tø|R–œ.!k2ؤ&(¶Å"o`˜R ¢Áê§‚ve@Öò*öÛ•è{u­‰À^L±¼õ‰žvÕƒ—-–Y6h´(ÊÓŽèE`¤- Ë3§ Âu[gœ4QB<ˆh]ÁÜ ôU+õév_ÅL1}¦õ T 7-ÿ òOÒ‡×EœM Ä~Ý4PÎþ¡ï×Lø›!ªÔ¢Éaëô~Ë÷(½Éø’Ó¼¸ qtß5×>W´èï|í0öŽ}¥MÍ·0kr¾Û´IL¿'䎈Îó,Ÿ´ÚD-2aNNÀå«=©!º—ü"º¿×¿k–‘G™J]‘#Áž}ãºî·_|žÜ³§ eÔ˜]hìvûÝêûð9H>¦†*î;´I¯Å§;Ë¢ÐF‹ó´V¦6G¼…É¡mYjEµQ‡½{¥Wb¸uæéœæ…ê+.È@qjahäX“݈§@eàYé5%¯¸’Ð8úÞñóˆ"’[õú<$aŠüTFU%<¤z¯\—bêÕÜKºžK°-†-á¯_4'{#77ϬᕷE NÔíéŒ †Wuä‹Îcè"È·©åòÀ1…ö/[EÙWJ¹Œ¢‹Èe€áq":Ë„ë&Ò*2.Z_Ï©<ˆÏvMñ'¨Žf¶*S‘JŸ,[ÊAÝQÌe”,–W\*´AQÕ‘Ø=ií•$ÒœNâ\Òoh&÷ÀºÌî–R ÂË,uñTò"Š+ÒIÒ/”‰æ:$®‘Ä™æ;“ßå¥ÇQ¥ÇX g£™75u´V»{؉¨™NøötL„K4*Y‘avÀ›9̽X–c·t­Ëœø ãœÖ$1˜`k: ¦F¤}:  m0-cÄl66U‚²‚‘NÝSC†•/ÈQJfŽ(­Ú«¡K;#á&°&<$nú<ŸâË·q̆9¸/Pb:Î2òFƨp( ‰C³ÅÌvóõÜ`@ñF2’á6‚„gL^‘T±˜š¢ªÅ–*­‘«×º¾©Æ¢¥Á˜s¦¶ºÎ“QÖ†Ò¼K£n½z&Îy¶5q±29·˜ÖrM†­62ãUåSÉG;̃¡6ß¼‘™¸Ôo–9Pç2ú6†¬ ›Íd6¶:-&dXXj8›G˜Ä‡*H‰À<}¼uoÏ>ÇŽ¾yó¬gŒÍ¦£w‚Ü„ˆ¢„Mn(·ôø ª›‰&’Róz­ ËGNÃñ²×™€É2ƒo¾k­BõAV,ŠÃ* Ít E`o82’˜ê+†xF[ˆ\Ë÷ûVóF±§³ÍÖªÃuô.ÐVW‚2Š)˜¤HÂÈ!"+©š”é»v›Í]Qàûyo2æîáè²õ9©ï¬åÕì[Eâk5éÌ¥:¨tË‘w^ƪ’7’Û )Àµ!¾ç2Æ×ç]ðÈp¼³{Á8iÞp@ïo7qj­ÚŸ¡·£‡„ÎuH›3ðƒQ~ŠVU|»=ŠÆÝþ^ˆó¯?näGÅqÖò/\56f/;·^ËÛqàOWsFç[‡dtImx¡ÞYŠØÍ‚’ÒæñgdnJMä°|p}СSŒ»³åOevÞ–ðÒdŒAìf«Û¦"‡P™¤3 ’.Ú·säøxÕŒyì –è(—¢† ³•´ÊçæaÓ™6¥Õ·mwóêÍ©¼Üóë¥Ø"z`Ü0ëG±›EKµ]W½;”CH sÙtzö –Ckè*qš­b^®ð§[˜^sê¼Ø²g[i“byÇV®z7 —+wx¥­6¨mÕ¶r–»v¤>®Æ~£Ë8ûûãÝÓÆVö5nÍõéÃÐÕØÜÇ:^–‚0“<ÖÃäÉMåñ£O+±Ø.Yréh¦E…³Mx-p²ƒœÕÑÞ¯^S+6œ“܇G RšqZý=ŒY~½«Ò O{™ø"x»œï2d²¼K0v3@ƒi¼˜n³‡S] ²5Â<¢ú ‹ÉïßzÐ`Ý:ô…¹ÙD"ù»°t؉֨@;ó€ €‚6«Z¯«T[pýÔž¶øúmïÕñݯݷo:×$—£[jµXÜŽÛÖˆñ+ZL“…:3PQQ!Ó]Ó!hÊzs o)ë±³S» xë9x†£$0:QÄÃÜÖ!ŽØDÙ¶'f9ÇÉx(¡DDi¸V"_c>F'h¦€€› ‰Q³Q…;3^ÕQc‡,¥e³V™x4%Œ ÕU`°‡bç‚ì¢å$–Få¶ç¦ªÊÚµº5ôW=.¥ÎÑomþC¥ Þ\ôo=˜Qiœó¾O§xkk½¨=ªËbŒÅhVV|Í8Æ„®ªà°•–ÎkÓ#=k³|e*Ý8%·ÝªûbKŒ]tUGJÆënÕJ_QG½i;,¤çUB–ßdåd¥œ3[ò¤ˆh¶E¶¡f/,´åÆúE©£Á¡êkRÅÄ%¸YG §JE!X¨ñ• æŠÔwy(ÔmJBÌcŠ¥ 4‡uíb„xÛ a¤Õq£üžÿ¶AJŸ"Üö¤Hõô™)RWêI)z“ôTñ–áq½~Iƒªñ7Ýž§5«œ÷U§˜ØÙ½6Ä•Å÷YZ²â*QWV«g¤ée•U„òxR8Ê5‘r£ŒÅ×WUYMpä4¬E"kƒ»\øªa.â¯æöî Õõó2W±RSo;Çñ>¹ÄH8zûŸ$w&ˆçªê~åô½:ìsáòjxÉeíÏ—SóÕaÇ\èBˆøTò9˜Ë¥(Ç“Ôï™|¥d)rßµ²1¥¶˜:Ý„'+&:¬Ø¤m„Üù, 1k.„ —0òÍÊA¡£%(°1–ËÚÝ­<µSU/¶äeH­ÚQñQoÀ•å(TÁíÑo„ó)vôåȤAgžë{Ê,Ã:««`ñ”óU”J&tƒ…¢Åzc“›˜{F¹— LºO²æsV¹VDcz _4w®¼¬›f€ $=üä)÷üZ6j~¥¥¶lT”VúHó¬WªL¯Âî§u…¬Ö·ŠÙ\RùïV²'¯Â.Ö1g‹œUð¹Öµ-eLÚ1ùÕÂŒFJ/2²”XàÒé”`2Áy[]Ä•I&ºoÕtN«.\•%ÛG (/^¡ÏƒÑؘAKÊÜ5k™ Mæu至£mãƒÚ´K¶Îÿ4¡˜±…œ×ÉaX5èG¼…×Ïâó\†6 ¤Œ+ ê½IžI·Ü÷|±,Âþ¸n¼ƒ’644L,U”Q_WìWÛ{njmóÂŽ#²%]FPRp—Ghðùꌠª–š8æL‡‰†ÝO¢KFfÒo²ýK4ç}i~žHdëäšÕ u0o  €Ï€Æ§½É­;ûc°¦vN¥ŽÒyy(QÁYER üÌ~WmAemËšÅAň7ä?¢nªX®÷L</{ÓyI E¿fåh29б!•ý¸YTƒû%=L*§’ÔÇ£ ¡æ>b0Õ™i–qöãÅ÷hÝÒÅ„šã hO’0"w@†KدV¡•ø0ï®v2QSãð!ן¼ª"Þ­±« .|°©5UšŒ½-ô3XÒ´‚Ç©q­În6?ˆ>4=ç ³ö¹\! Šåïb¥êÚ¢ÍðwZ´Ÿª ëácÒ‚Z´±Zí”rî…œM¯êW•Ì:ó•–ÆÁ‰éôV[gCÚ]–[Ó” °ÂúªÞÛ£e‹×ÖzÞyØRlóbí™{žÙ_NXø{²KÉëñAB*›Ù„õøQCQ) Œ]u†(ã¢eQÅD»:*ßôX™ïrãTïdàVú,0*¨bµWc%ÂÄd”2|L.kö3)dÏÌ»ž uª*)Ëœdæão½¦½í[…¸ö”½r¹„ÚªPäÈÐ<)r\3+ý%îóÐîk™8 'ûM[ï:ßÇÃùGy–èØw'X?Ê(4§ádº¯~gZ;~ï·AÉÀPãE…—‰ý~mÉ@ùÐ÷§9:þ63MJ“ùÀOÇ"ˆ:äuà“È’[í¥ym–=æ -¯7WÀð{öûÁÜKèù»¶fØðwï¾H ³ox]"úl89ßqì4ùÐ~³×GÞ ¢¿E}®b$'·PwÜ{™ooªÇ·×M¦äʰ¹ñPvÈ(_fÔyÊÍ“«­üi¶‡ò·KüÅÒÝ)ûk›ü»›ß•—IJZÝÌJ®›q}g Wû¿Â²1£Ìýšâ?î,g¤É ßœø ""ÊÊICë)ÉŽp\ÔëX/HJ#nH,•]òÊ(>üÀ9”ß¡WÛüÍ—N÷¡G3¯f®º7¾ÉSÕ–W¼ôÞï7õÿ;¢ú­?x¼ÒæÊVß±—^ÝñóupÕÓƒuÖ<8FY˜]ÇHFË(+ qtìψ $ ˜XËËž/¹“„:¥(rÌÕ•y±E:¹½b΢3ø˜Áë/e*k¡âÛ/çn4ƒõ\Û.n©Y|K%©Ûz©UÓo5õœ5_Ç¦ÈÆ3¡qÅc=&Hfñ>ˆ‰•©Â2kéraì|Éó:~2}—Þšx_-kËpmø€s)¾ B¯·Å ±ŒQ]ܱk…¯båMŽÈËy­®Ïµ…§?}|QææŽP¢µÛññuíß/W Pm87]cÂ<%†eÜtyÖÊ 1uË;Åì"½Š*Šõ¿X$$~¢¨ØP³ÅUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUu‚ (¥éSÒé-L¬¼sú];VÀ¨;=F|úuÇuûñýXÿ˜~ä}ðü0ý(þœ~D}ýüúùúü`ý8ý(ûQöƒè”}˜ü˜úáúQù¡ú‘óÇØµ¦h>ð}ô‡öõcîÇàÕìO¦?~ ~¨~ü~\~¬~þÌ~¬ê>¢A>lùgb>ëõ½@pŽ‘º9] e cB‰5[è$Bü¼xr¾*ÞÔ‰Xˆ¬0Y4rªEàˆN‹  „P*( ä|õÈÂÂï¦þrÑŒ3µÿQwÎýNÒ²6²å¾Üܹ^UÙ#úã¬ãk<ïÖš{:ó0ZnŒ©8Û£Xº·½Ñmr¶Øp\ñmšetl1"ñƒk6´`±×¿d¬]–q[8§iÁæ¦?q»§§§¯«³²R”‹‡{ý9zæs™YËQ×ϼ©ÈY4²ª áy•©æ"*­ñ=Ôf=c×ÛŽí]W9ʜغ…J]l%«öË{u@ª©è¤ôeÁU°QÌ椉3%UX¡R¡Q(–ª¨«V*E(‰*IUUP!EP(ÄŠ$H¢ˆƒU„õƒÊoF²ÔUP¢šMÃ`£lÚ6ÍÐ!FStá" sƒ’@â ÒË8`ŽÂ^f 4páÃuh¥S†håÆíš0‚Ì8`Œ0‡8IE–YDI†p³I€Ó„p¢C€Q%Ž‹±–MÜ&æîÔ’MÙnÙÑ–rnêiÀáÙ#iEY…Q„aÐAC’p±Ì89˜YÁ@I˜"Ê (²J IÄ”8ˆ8pÒŽ@iÂŒÂÄRQ @Ò¦¦¥p®©$ž”‚x$£waØì8t²Ý#V­U¹ÕÕª¹v#'@€á%ˆ$²É(pà8‰$AfÕw4päÕ„§ ˜MÔD‰Þ ]aã¥]ˆDÆe\xxhc(#ëÎp²Îet¡!ܼv|(½2ùrdÒ i%ž“V´‘veE] $b„"šÎhi¥QME»»þ'M4Ó:©4á$åcˆë9Öîn¾îîîÞîÆ›»»Îr"vßxfΑQ§5;Ýå_.¹wq»9ÈW«9q“Èå‘Θ9ÊЮ]߉–d»¾6îìpRÒAÃÉ4$“M4ÐÞhœÚ(¨Ü$ÓC$yB0Ó*±±A™ºnn¾›»Dnë‡30¬Ë,²Ç­Ð°²ìæs†ÑX"ª¶Y¤–½ß3É›Œ~QÅg9ÜæØÖ]³[[6e–pˆÓ1Fä”P=–Q8‹žThäœ0È#I8a†aÃMÑ:s˜h‚òêÖòù¼! ¢,¢Îë‘—»©ºædMÅpœ¾žow/•k­¿¨w'NP‹: ÂN@ÉÞÇ‚ŽËÜåÒ\$Ó„"LrN8pÓM4ÓNi¤œ$,‚Ì! ÒŽY9q}4V^Ò“½íߎm4˜0öì3vÚ>¡4ÃÉÚv©£õ})Ž«c‡sUÁFF,ãÄ#¥Ô¯«‰ãœ9·1Ô¥ºý,G*¹“™*ß—ÍSÖVÈóTï¸MßÌÔU_w¼ë¸ë‘×x]œQãˆqxöwÒXiÐ"Ì:i0Ñ„Q†4ÁчRa¥iƒ’8ÒÈ(‘˜pÃI4¢‚ DQS41s2"Œ¡éiDŽ`,‘Ç á¤pᆜ (êØ“ ÀÐèÂQ#”"4 0rÌ ³E[ˆ³tQÓtå˜tºá $0$ á"4²(è³££HŽa¦E‚ ( 1¶ÄiÔ°ä«8ÐYeQà GD>µÛtIÂK1­ÜÂH‘Ê(’g†”Q' "ðáFMÊ,sxªï&Tß •wj"ñVãóuß^ç_ˆ·æs2.ytóÓ»]Ó›‚åô¯y¼~tŽ¡\ÙsΪ:®?Nti4k³ÞôVc×4±éræy³ÅÖåå×])<ô«.€žÝpÉÛË8PùYiAÓ·1ú˜wæ•b¼Ö(&ÖTèéÝ7®XÚ–¾¿«zMNíiµ73ýÛà|  wñ±+ÒÐ"ˆ- ª"Z"QTlÉ! üÜg…ÒYj©)úË‹Q E!3XåX‹Kjÿ² Š"UDä²þ=! þ©$ ^~îLŸúyìÈiYÂÛ\EœÊÅiL>»ðqš´„¢ÒÉD‘“ó2Y³$IRÌÿóÒüüôºWü_Q×ÙEâm–Ÿm_øêòl/#nŽÄýZQþOéú/_o‰õ¼ÿaâ>¾áZšê«W êüTz¢•ù8B 0Iƒ]‡îÃÍÁ½¤JpHÚs*T¹q¾¼5áë3~÷Yî¼ ö@[üXSüßÁîìÝŒ’Å×U˜Hϼ…ôöʈ Ôæç5’I-j¯9¼„ZÕ3בS ±Ïo!c•l5ŸR‹³÷g¶Õõ¥ê¶>ê­ i×·j«%v¾Dv¨ÑPY9ouö^/ωjŦ¾ ¡ÉõyyÓß©ÅóhÎÓ⋨àîPè9++]|íV;×HšL×l£ÑÅ H,Wïa6ÿM’šÛçš#ÿ£®±Þ'!gëD †/hì?š}>DÈÔ7æ¿ènXGú€ƒUsŠ´Äˆ4rÙr¯@ˆžñwzµ>׃3î|Ѹ|S£þ/…xÎ÷|wß÷F§Då]‹ dœN^Ù.ÉØüÃöePmÔÐ<ž’–s‘¶-hx»0šìªÔ¨ ³Ô‹Á´Ï~ù !0×2š§Æp(}<‘àY;z`4¸°QQ­R¢kÔ€¨Oþ“lüã<”N½uz¥U´txçú¬äOÁ¢z‘)F-sß|öö|4Œx•—{p| dÇ1IJªXºsÞ‰èPGä´6Èü…JA³R kY|µ~WÐOTÊ*íqîÞe½ÞcâGÆe©xœ4†bl÷ë Ò «¶´{7K:¤åy¼ ž“¿ŽÞ¹ùÛ×,T;ŸWñDŠíæ¾_WâýÞö9±5ï Ÿ•fÕGÂ'Îñ,‡åEø_˃ž)îâϦ°No0ãærÎ+À´ÄX³á(lã 3dÞþ>8Ýúi¦s²â–ÝjnéS^]ꇭ¢!»[lSj¢Y×LµâÛgBúÝ褈+£èÞ lCýžæ½kfÕ=Åö~Ö½gŒøž„œî,g»¼°ÀsØoÙèêçc>[fsHÂ$v¦»aÆl™,#×a’Cx¦Øìê9›•/ùr# ׫hÚâ͈îÄ8å­Î:º&¸ŽØ€š hØÛ,=KGžHîaøýGÖåëyLK;!þÇDYd±>³[žq¬q)u"t+&QÇý½ŸÑ#O´¡Ozöì5]£,Ò³¬úÏSý¹ÓÚ;äM}»¿é&0K• ÐtݽuX†ý­%ŒwâœV6±cÁ -"‡Ûüµ—"7[øU§üžÁŽjMW™›%båö§â^ŽþæØNèƒþîÝâ§ì³‹Üö²w„TÉóGN"¸ãÑ ¯zó-$Øè‘“Ùß$-±¿©äì‚ ªZÊ5ªŽ§û·ì¿.ƒ>óI¿%g£Pi©lHeµÏ‹‘v¥×•\0üø…4·ÅÐ)HÐ…Š™ž¡ä˜(ÙÿZ¥fÇ‚™D­$Aî‹ÊZ]óë"z’>âòT€¶]µlÿûô­)sw³=Z%±¹W¤ƒFù*A9”†óC5>Á¡:l¡»ðØDA4…M£šö{¡Ÿ-¹\lq™_ìéÞVñÏqeÈ€îl}з,½S6õÙÅ´R …ÕEUSİÈÝrú èJ¾±Þ‡$Ñbx,w5ÃQ—¼u•Ÿ ¹3ë½`_5A–ð›/¨NÄ:î‚“!@âB„%2…5åÈ…ç¿ØeÓb­a´»Í¿FLé_ö ^Ðç/¢°€ÕÊâ°W¹ymv),;¹€@Tˆ‡xz5Õ-Öêl“||Su¾þ>ý·ÒÏ­\}ŸgÎÍ?R–ÈÖ4[GÃÐü[Ë%…!þtè–E•rGà´RT²ù¬Xuße÷”Ðû«ßUû·}‡ólwçÏb~úÏÜý¯Æ”úœéq—·²½?YËò pŸwáußãë\ß/šôj÷]‡äÝß¼•üù}ï;/»ÃgNÝP³+—'UŠ÷‘ÝÝ(Y¾´ ë¬Ðñô”×ßån>ÿ÷¼øz ŸðÃÅ´7Þ.»°é{[bcŒ©*¥ŒOAÕzž_pvH<Ž„4B™®ýWhqëòy»^:¯±Ñ÷žßá6á˃ò{ÇØªëìM¨„•h5¯žÑ†ÿo³u,R¨ÌEFéa•qbî)a½“j³ÊçšÖe÷A-mS£±â’š@¾šŠ›wª©ˆò*n2Ó³â!œÜwfUfmu¤”’Ä£ª/6u>Ygël‡ž©:óÖ€ÞæŽr×Ǿ¼jN_•ë/àÙÓ¦Á ÖÅåÑ‘Óí`pÊ]üúÒ2U=ud]ƒ¡†UOÊò_gãòyjS'Éß?æT—ľ,µëë/"]—4þl½Ý-™­5*²-9ÚLTUO/š~|e}4¶¬Ê+Qß—]üeÏ«í§®ÅþîQ¿Ÿù+Ï:KÏ짘¬0éßÓ¬iIVV»Ý<•·ø6ùôŠgÌB«ìœ‹ÈYm{òù¼ÛÌtlU»'˾žçªþ DñïcéE“©ZäëõsB^ïA¥Ü!ó£Ñ~wÏ×ßôW§—>xÃIu‘Vˆ÷áÙÅæò/³—¥p¾9ôpôŸGÐ2<Ü kIïÇšáͧŸ°ùk‡ðþîï§µS鞟6¿åz½Mñ,´*µfÕëvÂŽKjU´½·Œ×Ðû8fÆÖñok/?{íý×ÿ·ãÈúž]›¶`ªúh±Xhj‘[¨²"B± T£ÒJ^óœç Þs/5®ø³ Ìãš\Îf™œ4™ÛÛºO/:O©ÝélC¶õ7°æõ[Î_2Ö>œœKœ8.c_nˆçœÆã‰rxúVç5!õ:}XíÇÞc¼?¤à¯Ž´Ù|‰™UGuÉ~º…ºýBRÏÕËWªµWóE#Î@d(ÉQhPH‚F|"¦+,ê9œLíYÿ“ÑôZA¸AZmæ)³ž%z;¹ Óü‘ó~.$+«d&^ug3ú [M€Í˜ÀÆ!0„'É¿æw}½¸ð[[«¶Å6L!Õš“`8Åæ|ÏŒy"~¯ÙuYÌžÐì/¦7|> ýø@S×akRJ„àµA¹ò÷²Y›‚²bZíã†ÐÔ¹jÑüïÔßñ­/OòJÙ@>ä™õmdz?«ßLz‹4JjÑZçÉH-ìƒ2ªž¦üDQ~®Œ¿|ÒÑUO·ÃJ[ŶQ¬6ÂoNšzï;]À娪Æp…j=J¡m1— mH@@&«{†}åLuMs; mÝŸ÷ý:6]k¬ö^8Çnøöüõ?{HÃB*¤"™úè&K–# @Oã,TJè„PtdTØ8E†}Qj˜ßR‘SÕü_ÙàÔ×!wxþ«}´ßœ¥TÈ"Ÿs¨`dcedfeÌæà€ÌÀ‰|æíïïnë2r,°šàÏüCût3òúBwR)äXŸŒŸŒ?ÑBØÊ J(¢‡®6Qö+Y-#]‹Xê‹ÛR*(qÖ_mo¡šéh5ƒ*”¶³ =kb¶T—ëbÙR_“t϶8ÔF— 0{#8ÂXÚXµ,ÂË?_¿òE»^6Å*ª-ƒBeåGÇ£æó—Ù޽žðóRÃë–oÛÍ4ã•ÁUBØUÒ/£!‹F-#lk@Ñ®©áqiôD0ú?ðx™ÚŽ–þ÷þ÷n˜ýÖ¿sÿ÷?›ôŸÂÚÜîóü×é„'¤ìƒÞñ[Ru§Z~.î©A{v §Õ\pDê]ã]B"ƒÁòeh¤_™9ÏÒŽ Sˆ#\pè'¡Àu}XêÄ®­«Äí>b;ó±óóŽgH•êØÁø[–@:ßKe·¥šûî~~ ë’öÎ×a£/ ’göcØ÷9ÿßøîôª Þ+7¢Ï½U>O~Š„à2àCôZW1m¿ É,ÞiìzZêÒŽNÎ]5mÜŸê ‡›í5DIIO®û-žŽ ï÷x²xÙrÖ¼-ëoérúo½ÏÈ!¯¥‚îùY‰ÎÀ WŽ¥™‡U\Ôf|ë‚JX©¨¸K/ë¦Ì• ëwïß(\®¢Š(¨Êes…ù³ì¾ò?CèZ„‘²²JB¶¿ÑèÖC Ý’""Åönà"ïchìØŸF=2jm^ GêËàý½–~é¯Ûaáe¾[¦¶[ÄaÎfúšy®·ø[û¬Ç¿­ûîó¦;öFZ¾Ê¯(tc¦3¿ÅæË_†s诀 ¸O”Àè^ì¬á”\ÊÔ.!Tؤ‘C·Èíø»÷œL={M¤ušX·ö­ü£ª“ïÍWj!…e[~Гí—ï×’ÁùÚ¡§µÓNnY(¼Ü¶ã}5l6Àµ4‡AMQ·AÔ«N_¬½pž2£ðœn—A„°——X“¼¾ÿÐcVS‘|6YuiBL•†Žh÷Çóõ:‹FÙUõW÷YAÖúå…q]ßÀÑ,5P™Cü¥*ÐìþÅ3›úp‡*çrÇl?fŠ›®ä@T/GõîwêðǦ[W–7–2o»»®&פì9~Îyë@sdúm}Qlr¬rªøŒ»ãkÉ­œ^K rÒôÅØnfqŽNZ¹¥}ñ³5¿“\åF{Ô<8áqéË£ýUË_E¿—v —/˜ÌÈâjÞDÂFÿSœÜóUß%aÅS±gÑ“Ç^¤=êóŽ»Q´(¤ž”Ä;ãÙ»4‘UøóyÀŠ‚" ª ~øçL{þM‚" Íì°èöÿ?<¹ópÍ¥ürþï*jƒQŠŠx~.CˆÅ""£ˆú››;óì{>ûñÍXŒÆ·çfŒtö©üv8lD»¯l}®®W'Vã¤&vó®ˆÒíõÙÒL¤Xù§Ø­ðeð|-´dtëtªiƒªÆ”w¢Y“&»Í‘ HÄHèAàѯ̛)¼r$ðÖóÍo’Î÷ÿ¯ÖU5Óñ¨§ÙIyÓ`Sócû~¶ôQo>GßÁúè§ø9 õ$ÙPø5ü- ¢¨ÒI”>á­%EšPKüø©étû=œ;Vým»æäêˆh>Äj¢;ʰÀJ ¸ÏFÒVJŠ(‰×â–dCËÆã•¾OLsK`<ÀwA‘¥¿8Öª‘Lm¢'°¹¼4LÉþ¾×Øø¾Æ‡'0Ä÷n@E÷O“äû?»ƒÅìqQP±/…kÊ®‹6òÞÓY_öÖ2…ŸMäí\“ñ4Þ€ˆvœÑ·í2]úoÃM³u$Åu¡“ÙâGñ¾ýä6:ºÂTaT¥§Ô¼¹ Ó xÜÜWž3nÌ2]f­NÛ%»fù=5ăJǬ%€U§w\w-ì°ÒÈžd A@·ñŸu0ü—á0ú³ËõOµð=y÷÷$ýœ¹~s!ä5bd\¿vpáÞœ[¿³¬ñ§o§Ê'7â\dþ4ù|“è¸àŠdœÓÑï@"`aÐòŸ¤ÜÃI•U2ã8? ²`›„<®fîn~è :·8ðõÑAÔ:ømÞxüÌŸŸ;f|,sÝïÕÒ„ÛS7¹ív{~×Í嶺«Kùí•–Ûu—Yt’YÒË«d’£X´…bÅÝ1Ñù!ÎNýž·@å†Á,â&ÉʲIØ ÛΑùè³ë?1»ü…soÁíû:ö^5=áßm½Aí¬«Á‡vFXÊ~üiB¥*‹éK&ð‘KŸZGùöÿ?û¿ò¼ÜÊx_ttB9¹è|f%µ²(±§]'Bî}Ý’‰‘$Bz)àëOLÖE÷=Ê—=—=}‰[ªÊ¶?äWË[þþ¯«NW:=o&­›=ÊÖY¨zj›*Šö{µ=å–ÆúÔæòⳌþW®÷­”‹Ñ5E€KÂ[W85ÌïZ‹?ZÓ‡K·ÉÁëý«dC‚Àýg^™¬z¯F_ ›‡ ¬Î•öãÄ_Ű²‰z‘T ¢·µ³ŽX¯ÉÕ(÷2 e!eLžØµíG940‰îÉŸüßâz)y‡,«õ¡ãŽ~J™kÚúÎ|>Ëòá}:”Ã=þ;b³ü¯Ë…'>Í!yÚ¯¢ÜJÊÈ×¶Pü|ˆgou}âx}Öñ&3çqµx½Ýo†¶Û ß×é#Ëjm¡;.óòÎ27ßRØ`ÈEA]WÊÛUQ5Æ+¹è¤Ró%è¾8KÛçÀíÿµÿmyqß|¿ù¾@‚kû¡Ù·®d=,çCÈŒˆÈ/'¨<º§”Ry¬ÄŸÒ79€cò?7õ?J”IøþE{çÌ`ræ¿ý3Ha/äá¥hþVš¥Úþ±8aÖXH‰oÞd~œÐÐ›Š¤•ý'd6c•7ñeþÖ²C1 ›ŽçÒµ'¯Cˆ8 ádc†”“eÐêé²–2”ç÷ÚŽ4¸ãÈu2’&ÒÒ…G°ÉÜtÑ ÀáKJT¶Š2±I£©“FŠ"6+8Ù$’#•ÉÒhw¡)(w%!羨¶¢ájJèõž0™„ ™‡ë€ÍeÑ]Ibá’S÷5LÅ~‡„î!ñ˜­î«IëG)ê±цhf2uÊöJ *Ž¥§’-`غPû2tÂM‚Tí@tPpθºÀl:à pšpç~5l¦yé›”“G<ÀÂÈ*ô²&"ŠÅbJ²1PçxÚ:&Ý(¢wnMZ8Œ/šA¤ž8öÐa“]£Îé¨á…˜ÔÎK/¬É<-ƒ¼<¤œpq£"S3LX ÔÖI¦IYf‘`!­uõÄC¸’wßççÊ£#ˆˆÓ¶òÙªˆ÷\2‡ç¶AÂŽ['м = ÎL&a¾É¿ÌYoM5@£ÞI @îN³0 §c†;q_~[’–p®r ‘7W¶ýÌd³m[N:È0Ö¹ÂØ1a²ˆ²D,†,Mi†E“ eµ2iv LACÁ,82@é6Â2Äýiwd„‚S¤Üä݌ð³Jðd‰› –h…E«G—.×ÇÚ² ‰$‰é°’I!ºd‡Q#»·Üèö“´çwS×p'÷´;~ö½·«‘WWBø¨Ð‘Ui¸ œïh ó+‹&ÌòHÂ`€(” æ>ÐPx¬Z¢Gær…Þå<Çºä‰›ÂØñÝ$D‚e$“Q ’ID2M"€à B€ó”ÏëºÞº» ß®¬qëoÈ÷9ü7¨z»Žï&J,ŸŽÏƒæŠj¯Me±˜ŠxH>‚üÞü¢¡ì­¨EòBªFêSŽs¯®oÞõÄì?'¦ý2ïhÁ‘F"0F ¢ÎÒN¯Óa ¬Î(mƒ³N»Ÿbc†Ú÷§©\¸é5\:¤U7ðÁ™Y_]ËÍÓKOàLŽ~0ºüf@áÂ\áfi|b€ç G4 qƒAɦL59pàâL7LCˆäÄÚF&fâBI¢Œlç8ŽpK¡¤ 2ÁÊ4c àI †…‚ x_ó[ÆèLÀÌYÑàèæ <þ€¸©TÜè°äÉšNM˜ÓHíΟY!ÿ&öGô)+- ¤PUQU‚ (¢Š'ÅjÁˆÀµ"…âíkÈàÈ&¸+mWÒC^Í‹.Sïƒz’N¥=)6z:öÍ²Ü ™?÷ï#ù,Üó°`n¼ðGN9ùÃÈ<Ó¶í‹ –8Á%» >2@ä4&$C “QH~æIòh‡»Ò$s‡‚ 0+ÎD92ñ!GŽÖ›eЙI(”{ ¦ÆA&Ù#Ö“ïXÇ·"†O7.0_MN>!Á¤ÙDç9ÂÌÀÃE×&÷ÔÕq,š(nšp™À™Ó¢ö¤š€†‡È‚ !‚lÈ$@‰Å{Óª.K$YÌ0ƒ„9dã™%ËWMV£é Ð=†btJ‚p”Pë¬2 ͦºëRgv˜² ,0±A I‰0rèÎ1(騣„’ØØÐqp4Ž:*˜’38‚S3“—<¾‡y$ÎRÖXâ¹¼0„CA¿æ»#Oà?¡&QÆ¢Âk M"f' C ÞSuÛ¶>ATc»ŒÓ$˜v»‚Ë2(wh4ã\\ <g¹Œª¬Ü–d´âaL r2·G GÈ(G²ÝЋ$˜ÿ:¨L•!Á7PNŒÌ¶dÝ9˜ÓZcY‘²Ç\# °ŒU¿Ó«¤…ÖN–´.j®=HU{cwftò}¢K8‰†XmËìfEDüYì¹ÿvXì»?ü‹?Ÿ¬õK¦ º0zŽä(Ý…ÅMºMw)¥TAgÖ=¹YÏ»UôSíqͨÁì>YH¤ÜzgD Ægh ̆ HH™yæ9¨"9ë¢*§Ûj*øå~Ñ£~4¢kõäÃÇrq–o‰2Unf¾2¦‚hܽg”{9Z4Ø„4ÿ[íõ¿?/wT‰'è(€‰·Îþ¸6q£•U}V¤’BG²a ‡·÷>ã<ÞðJÌq‚€ÄâÎ <`ƒ÷?ÛLYè2ó û}Ëiqjƒ}­’Œ-!ôMu­N'cÑ,Þ³’‰DKN†)D¥ˆÈÑlœ!¬˜™3} ãÑÌ   'î‘“ìK>3W{9òBÏ(±$B¬§¼ÙèÒ‹\”i‡ÐèGYe`ä’!¬ps ”Ž# àñš·‘‹+K ³–LÐ^I@Q@YiÀÒaѺIgfH¶î:éÞˆ»žšt°qÊ8PtPPƒF²9%¶ÄìV(/ ¹ƒf9½…gïÇ_¿oã>5øþ–F¤°61¡ 'tADGPLq½K¯2›ªÓý.<¹ÉÇzŸZ±Ñú¥ÏëQj­ AŒbî ¢Ó#5MšÌa³|RÔ–Ó„ç;î,é"K‚=ïÔtÐ…>¶²ÐrZ é‹ƒÞ©Ûµ•¨†Ô vy¥:=‘¶½_ôž]xåg!òçCB•–Òµ±b¢Í.k]5gÏÍà´-ç7¬3›ùÒ380“SJ´N©°ÖY­ØÔ>Ñý¥-]‡Þ&Ä…·h׬8òén§™å_)åN;@Ú¡Uª jý`€Œ¡™a+RФ”J–”Gµ„¥(,1¬"’,S1‘a‚ ˜R„¢b¦ © Ù‚éŸvÝ!ÔÖÏ’Lð4s¿˜Aeœ8`ÔΘLߘMúY€tiESRsœ¦[±pi0ÉÁËujr­ÂÍ#N´›™ D˜XàIÑÑ‚Ì:€¨Ó®˜ÑÆ0 n7,±¬ $FBaA(9*Þ~mm”žØqU•z•´Ô8”‚—åýûfó÷`éé È|.ÁA©¬¸Õ¨sqdö¬„Ç-ûíWU¹˜Ô.c2êÕÕ•}ìD4뙉7)ã]´6Ü t Ï•¯lu;AI¿8¢B98HP`œ¢^$T$›Ñ• Ú•Ûƒ¯vô°Ê/·gN’ðåM£QU0ê³fQ¢ª›Ó~S =¡¿ 8÷Œðb«Ãf™iˤèe˜  "$ðg¡&ouë…SpAú·Æfë‡L†ø ÷À>ê Jc @TtTpItOÀå­UE6äeÉõþGÿ(¦Iµ©ÀÖ"‰‹·š&c› ‚ŒGš4 Œ^+ABEHK§}ÑS§8 +æ1p qõ;Ûkª08{þ.éÚðt¦ˆêYK)VfnÌÙ©¬dª§¯ >˜7ØÄl=9Cc6 : DÃâBq*hÚŽ>DÈáÏ„C{[e‡3”3U@R!j nR9V³²§Ûês×u¦²s^z˜¦Í¶äÜe‰¹ÆLà'+!,oy"â&‰²4ëê8QÕ3Nt5“Ö¶\8çúƒ “åzjÞê5ª¦Ýx»\{B™xa¢Î4]6¶Q¾ÆÅN)"ƒªäX0ÛȘ¥Øè…Ġ܉ L| à…˜9…[:d~!3£~9„‡çQÞ3YcD’IÐH¢2wa¡Qß¾³"i)éÃ¥”ñíööoÏ!Òbhájƒ[ÈèÖA'nÉì0D4Q9Œ3® s8äÊŠi{Fe! N_¢º…Ÿ. w~Û $`ó¸Ðè×¶/¡<Ë*ÃËÑã·ƒ”›¤Ýíô45Õ¥=ºloݸɡÇv˜®5ÊÉÅ-k±ÎRmCŽ{65Y¨Í3G$Í]ՉƧ"¬ª,[VW§ Öã;Ö%…Ršè4šxöÛ}·w¶fˆ$C<èU0dÑMZaA¤ðh)òf“RþÅáÀÄ•K Áp^#ë2$™³€:h8xå¤Y Ð¯%`ªo¯g†©³e3r—°Éfö¢uäßsvOq ;X°áÝ… Q0´âè{÷†Ri8Œ×ƒ,M”©‚!A…˜¨( T[#çžíDB*’žjh8ÄK±¡íÂä×p?}àtT¸¼5 L1"¢¥ÊÚžQçÁ‰ÎUWŽõôÃE*•N) ž½îÃDK$DDî¦ Á£(Ü;ðß]dàx7B"×dCÒo‹†õ¬Ý‰6Ra[Sâ±™™ß‘^äö´3§ °•ÉmŒ—¾9ô÷v/xÂÕFQÁK]Ù>|F¼f«/fµb)40 D/CgàÕ~´5°¦*8 ÖÂ:Þ¿“Õ HS¹R6"çuÔˆÁÂõ@Åc-FˆÅ%eA$¨ùa-ÖsŽÝÜ:8’¨Èó”ÈÆÞÐ!®€Ùù'¸»ßÏrŸ¤Œí/´ª0Äü»ÆeX±² |¿4¥8LŒ™Ùe G÷þq¾;&ZÿyÐßa0§ƒÎñ¦Su!˜ì‰<[66™È--?wpÏÓÑöš­”-ÒˆYìÅݰ±ÕoñGüVýrÊw0(¦£íMæ”׈v%‰ Ê ÷Çö<ÜüŒ>GœÃÏV˜H$Ð#Pwñ4{qçòÆ!D¢Š<\Œ²ýž% ¿ H‘aD(‚)µ¥¨XÈį51´=oÀ‰`y³ú¹27úEw=bjÛX•$(ph ÒÇ (,d9ÁA!!GE…8ßä“`ä#ÄÎ~¯@´á-$ÅZXrF¶¸Â&Ë’G’•ò 7VCùÉåìh¶ i‚ Í –r$‚ 戒K% ®6ò¸W9˽tŠÖ0À£•ÅŸšQ¶ž#P:Q:Q‘Ѿ4t›cÓéØMÊ ëMÑ4TuêXÅwjÓjí„æ»"2derªý­ý]OÓ°çœÏ°ñ}i?*a*o~6AVK¢b¢¨pM5uuqH@¼‰Á8•8ÑÖlDCåÿé¦{ÅúïÔõe@€lx;DrÎÙˆJ0}ûšhRJî3M™PÝ\)|uCvŒœÏä;©VOä·4 j’0‘Av°8ìŒ Áü‹5›5Íb»D†±‰ç²Q9ëaïèÁ],盌F‹;ñ‰ešmNwIô²“IÃvN4ÀÉeYˆš;+C¾e )c-.Y•eY'‘Lû{2hE¨Ú{]’¯„Ô ešˆØghÅE D•r”£ÁAˆwÒ‰¸ÜË·§D€P²ÂãÌó44šøó©õÕ½sâÁiÏ“3%*©¦ UN>øëW­(©SцªFhsPïí×}«ªL**“JLC4Úa{u DªHZˆÒuædL‹(„äoujH( öG$5Ä'±RŽØ¡V\nõŠArç1²¦– f1Å”¢H‰a$ÙGdÄ×±~,BÚë zl ¹Œ ‘„ƒ6DÇ=¶Ags¢Íl—˜Úܲ¤æ[*Y›ÄAHëÓÄj©"À'Ù+¬áVŠ%ì‘FIþ†ÔËÙµxã4ÈÈA“ˆ‘#a ºA&¡*ÍçŒí–Â#pp`Pq@d¬Ö¾Ì!av(“Z”·é– FWXT“‰RbŠMà½0M‰¯_N)5ÑÃÒ9„1@’a3 šMÂDÓÀ~i†£¡@D–$“ÓÉÄ=2jo»ž¬ËÇl<øfŸÀk>|ø‚.a†}$Ц¬`&›úpMÍÊ2‘ò‹/ãy>ׯR_7„"È}ú_.d¢x”Ÿ­KWU­è×u*”FpLœäŸÇ½Þó"¯êË!]B€LH˜Û]«Òû€ ²be8†\³&¨k3> ëi4&Ä“b`DÐ…(RŒ–ÂÔm Ú`´¬Çß¿lÏ€èSª½0@‰g\!t™$¤)G¤àõ­b4 4ÂÈ4FšHÒ89Á eŽ4š)?¿,i¡ƒg+©«2zÇå ‰: 8m‘Nœ 0Ûª¤h’ïdáU…iÃI8!çm7Dlndëíä”XpáÂ0¶³‚ q`Új0á†9bg4¢Ì¼ç3¶¸üÊÉçí=Ÿô£ý·~ìá¯ùCõØöÕ/=/µ°àBËóg£ÏÇÙO8ÙëlÆ #,ÄÓW‹”ÚsœçšsR¡¢Z:ðO‘Sä¤1Qpe¹>ø&<'A]„}$…Н õz¹ùçÌÒ pTã2‰Õ5˜ÍvH©†œ/Ž¡®,©è]è%¤$&v9¦N õ›h½ám&¼¥¯Fº-¯Fœ¼”Œ„0SMDõY–!¢ëˆ«I(’‰¢˜86Ê,*)và ³Y’a‚Á”¤D-(ZB•hÈa½úuß·GUÛ½®ƒ”Å$(°ŽðP&AšË €¶¡|4(ƶ½84Гƒ`Q%hYa¤š8ae„ð$0$²ZN7s2ZG„…‚ÀÖ,rL¦,glÒ¾s€Ø7ƒI @ÒƇê£[=ZàB˱þâ6>Œ‹ 0-(ë'‰R¾3N:Ç5pÒì3’˜ƒ#¸…ú>DLtþËž~¸z:ØnzD•ˆ¿²úœî¶[ftïðã‰$¿ðGx³YHËýÏöÿ½áý ’õÑ+øÈ®74‡Á2'†åõùµràJ…BÒð¼$Kx`2¼YÁЇ’‚¨‚"ðœs¶5á·ŒAíà À‰A@ÔµpRº02(*=ù»Ò?“þÖš•ŽªÍ.º”=Î *©-ûóÔX`2ZlKªZ § Ó[‚–GF«¢h-EQN¾K°q$˜3W¬àBíkì‘vqv½Qç×{<‡I»qθH‚¸¾¿ OsÑ€²˜Ä’LB‡ˆÞ‹tã¹ï°- ‹³-ÈÀ¨( ßOùÔáHvqw‡/©û™†[™×s&]ª5&é¸ Ñe¾Ì40ÁRÄAZlLß+â\*ÎÒs¬ fJdšçÖc¯,퀖— 1`Z.µ WÎ:œÁIAž÷aPRÖu  Ê zÜ좩pW½‚vaH”“ýõÈø.²Ú°n=¹QurxQxòßa$?UŸN7F‡ ùÑh2U)=|žáµ‰0ðã¢Ñ"”Ìq3j¡02H:S… ¯§Å’ö@^}»ØÞ•¯·ÔöG³‡Óà †°žÙSî ¯ÃM·M"M@ฑªÚ¤Uujp(À:$5:O!éÔ±g †˜bÇ™q Âò^T‚©v€^#¿º¢ƒëÜ„B$E™6³"e6€ÄI[¼ÜmÛbI´˜Š-'aÔÛžI ‘!ó÷D©Ô¡‹x€·Î9ö>}Û· š¢- Þæ™‡NÙÁ\^=¥Ö.e„J¤ÖçLàT ÀÖt@Á2i€ƒà•òä$)’ BLä¼&£â¦†£ÜÕPQQ𘕆y´›-Œb‘ÝÆ5î­–Z…K‹G¤ Kž®Eã*kóç¡Ìpá‚ {:lòÂÐê7ʪ̘a4U‘,yEí51µ=æ̘˞zl;^` FF¥4ØœõçZÛtøx{’ÂÕš©†/ 1ö©O1³SëóOmvÁ«íþ-‡¯eÏ @ìD€ý§øAòø~'Æî3ñpÚ ê”Þ’åBQ"-Iíû>³‡åÊœìɹùßÉÄØê{+g¹”(õ©È‘ 9yœ>ºƒg»Üo¢šu=ZÛË#È3@_@cŒc 08ˆ@¹LŒG²(±Ýbd¾8Ë{OýóÖr9Uz2©(;ªë6þó³Øï}Ž_Åïý)ßl½Y¬ófˆlæaiîn=¥(CÚ$4&(SÐR‰rÎ<…9ëþ¬IËGèIÏÛ„yw$aU5àÄ–b‚eùyÎEæ¼89b ჈°ƒH,,Ž"Ì,‘¤rÄídœä «Ù­ÎlÄμY–'æéFàQ˜CAã‘˃\£KÆ9̺§*r'ÃÆ]–!Ë6¬B0á%"]¤“ ãµí¾;d›[¹Âë×õ<‹ýÛ Aò™½ü!ÈNš±VôŒŒbFErln Lœ­IbŠd‘L¾ÎÎwØÍ]µïʘÈ÷HåUAê˜uNÖÎxòO¯ ÿ¥_·O—c@ÑfµmY·'ÄÙ„ÏÓXETV IC‘¸hˆˆ‚L¥Á ‚‚ª‚c Hj B‚‚™¨4…ˆŠ(£((²–Â) Þ©$Ä%h“<þ÷o'oŸî«=tQNMçs 9Ä}ͺp,¦+Úi¤Æ”ph(,°Ñš (4ˆ(‚ 0S;Daae‚83 *NYE¶°û¥nNVKsÌäètno&­M޲8iCÞZà ßyWÖo]6 ¯ ¯‡ØÝBp9`â`ëDD{]tUЈ}ʨaÆÜ~;d6¥é†¹¾¹f4Y†!U] ˆ¤Ï4Uiw×FJÓ¿Õ–•Go[ú)B_*;¿£@ç +ÒÌŸ £CHÄê†@cy$QJª*}{Þ!_ZAá凧9ãÓF;íµ <–½.7ù¹‘ÑòtöŒQEC„O·;úqüN’}d8IG…ŸPí¬jôk“X-‡,'ÉSµwWü€ï…Ar$8¤7æj’u}ùuZ'¾2©XžÝÐ'/ðþ{ìZ÷:Þúÿy(Ëübú­åÆ|QÐv|’|ŸŠ5˜`&‚7'ÅÃåæª”aÝá>½8\L3M  Ø'”QÓÐç™ø„1äS9dO)åɾµ¾‡Ðð m f£¿AÐß?8c'ráîjD z7 }E™9וíÎÍœ–”íµ É‰Ðè†vP³F¡‡w]ò&™+ w)Þa“" ú÷æÉF•B¢à²‹+á—Å9cÐ`vq‹Éü< cÔ6ÜžÄiCd‚.¢0™úï¹`¢†Â( o! €v18w54ó×Å}fÁ™˜¢Ú+¾7»»ó ²ÌǯȽqÝÁÄp=±Ãn½ß¹JJy!¼w#é?8QDA“1$L: Ï$kD0Ç_I¸@QYÏá„%•]–ÜïËìí%Ö?œD?ÉþÞªí»wˆM­45Ñ *!#P: ñ®T™ÿåø÷ àá•Ëóf‰Ÿ10=˜_HyÄ¥\£Œ–‰A™û©ž´nÿÉXno5U‹ÞðøafÙr7Í,…¨Ž"#91¡@¢AšÅ`ÚS4`„`9øÄ, ì7¿?å|¦¡Ðèkš:ƒ¬ž »ÉKKQú. õhè@Àù°¢lB€Œ”J•BTäøºfªœüÆPãɦœáøÁ”"¶ š,¼#Ödrš©@Ð@àäkf­¹pÁ•4Ý8ha40ÜÂÙ¤’Ú"ÎU]]Ѹõµ&µœå›ÉÒŠ4áÆ,ã7£I(ç8aÂ9ÉÞi‚BMlÖ™§—»Ñgi‚ÁdIAEØH+ $£ 0át+Óõúë\¤êó„ɬÈWYEý/ {éï¨gŸÃ|ðP¿+òÇHÈ2[ë—Øx.—Ø•²ì :`”’`•#Pùþ¾Y»²†$£4õ±ôh*¹1'ŸÆ mÖR6ëÔØDß彤=芲 5²—óä€g¾æGr’ÁX db#4ZŠ+‚¶(Uk}W"46hHV!FÈ& (2-U(Ò”ŠÑ)EE"o_VôÜûñi3}qÞðŽ9"¢D-ÂÈû£57 kkb´E3p,( €àYad4҃ 6 »kv%Ç(°³‡X‚ä$’j €v°ã†[ a­£Y˜9C‚ëy_Xæ«Û²K¬°jMÈ1¼U¶69xÓ …H‚Ÿc’¹ë£q› ð“ ûˆå îD¢ˆ”ÁŒ¼ú6~{›ŽHšÌÛ°ƒ­‚)|H(Ð "ÄR# ÑÕçІbÙ›Yräì¤ÖŽó‹C•6%¬jŒ’¨X™<25 ×…¸ú ‚GqªÇ%¥Æ?\ÓœbÁ¡ÝB2§ŠiT”JqÈâÊ*re®ùHBÂ-,E€`Z:$A³,$ˆThë»±8;héZ˜¦²dôéӉ¤H-‡a¥§*š¥„8‚ì$hiŽÖ¢Ž¤8‹§$B"ß¼m×¹õbÊ’°÷ß®aìáÂŽj$n˜¶oSì|êÛlKï+Dû•¬/Í‚3¸f¿8‚Â+P¬Qæ ÉéΡ‡%¬Cè—§+ç/¶ðü­¹¯à˜ú 0@馩<ÉâQÇ*†©&˜æ¬ÜC¦mçÏðVaã0ÀcÑë‰ìðböèí®ÀåS~;.ƒS<ç€ÌÌNý§ÒûQðYœMrC•Xr… Ú¨(YKé`H XJË)L¨QH¢äºÚ®«*-(……éiÒ¼ªô4W¥õ;¶a€®m¿üw,ø¡ÝÈhq|žü*ÄÝ4sƒúcÜ1>I§(y‚`¸hâÈvG^Þé×áH§ #¢ ão›æwGvˆ g8r½B<¬]-6Í¢ÙŽñçìã÷÷i œ§Ç'‹É$n/¹:m³Ï—ßàuD”AТ~G8q%Aa™ô”gЋ&ÁœãQ.ÍŸ^ýùDçåì+·±»¾ºŸ­¥ažC@!0€LÍN‡_ù)Ï *©À~¨²G0§ú7Ð,ÉÓÁ¨n1è0Tè_c…ŒàÔ® ²`–J÷§–Æ{žù¹ÛÒnʇ“ê‡÷û?èa¯=µƒãolW™ruQ†TQ—Ñý¿Ö7Ì<›<Þ’’ú%,’A Zedñr¦a£$( ‚OYf˜®P¶Zœ 7Áô?jjqÇ’Ë)ܽÌ2®Ø³ñ3Ž\;Ý,Nï8Qè‘ ³¡0Òˆ , :,èF–es 9˜UUÝ*ãàslsk_\6óÍEµšãá™ÅÂb EÒaF”I‡,šu¸ÈÙ›·s†ãa%œDQ' 8[G 9uO‘ÊEeþçÊê?b×ücŽ#½^½HÕëõ‚NÒg~´¹=JêŽÛWxÊRYð±Æ*­Írú?Dp£d³ ô½ ß=.3ð¢qùÞ[½ºïvê¸g‡g¼$f›$D´¢*'¡£Íc<å†ÒÚJÈŒ‡ZlÛÓ8k'x$g$y‚¨Iˆ²CÁˆ¥Q&†„&¼ i Û )› $nr887e¹”ÊrÄšènq2eË$Ö×’p0ÁÄ@h6YMACpÞÄ„†šIºûC ÂÄ fnÆï“˜9#”Aˇx®cS–IC•V\^AbcØvE™ŒaCD«‘Qü_ä*GÜœÎVºí»¡7ók¬áœq ¨À¢‡"޾‰6,h‰4Ö“‡¡£%èØný"@¸ “ƒRähœÓ±í´š8& éõŽU»ÈõؔɂŽÈ…öÅÏ C±ÅxY-Fø‘Ðd ÌÅô8ÃÄ·c£·`€‚è–i¿P컎¹R†›qºS ¡Cü]røA„œ\Éa õJK ,ß‘¥9àä :9àã€Þ¢Çpï4’h¸†à—ÝÂun3Cp<ö²üñáw×H’‹8Ase9µe¶û»øÔ;¶aÌa«)¹¬|HƒÕ‰}\µª›žé©—¶a€_!ùOåBõnÂߟlÌaïç‡^”÷¦eg9ëå§:àÔ44…–:ªÏG±iÄ9_»ßÝPo®t¾ób[/¾ÄiÇ ^B[BWÈ´”±´S”§yq"ÒãHÑ!ÄÐGŒ5&Ú"ð¨Ïã]©‹ö;ZíÇŽá¸VtPãó¢Hmö÷ ѽ˜ÁËAä…¨1q¹J8ÅôbŒâRDžÛ,„mÐÄÐå•sö ў؞I+>B$èpôØs˵¡ºžîmÓfƒ§w{%£8¨„„Ï!3Dáž(ö½®‰Ç9cXyèñ½ÙÈc‚FL˜i* "¨ˆë"TœÝÒÛ¾”ak*îïçöK 1§nvõ—Ú #(u‘Ï_A„·}& ò•Ʀ)”`7é»H8×Jæ 9ío‘Þ2‰>)m©AŽ\5l×:òJFÜÜ-yvØËºöÝÿGÎò;h\;kÖŒÙÏ•‘Y ?hÒÂ!e±JšD0¥DLk&L‡–­ò°}ý)ÐßÖŽ:KdÕ![EÞW!\FQ G ³† DˆEDý‰cE\”0ä;ÌÅÆlÀg5¨ ¶Ý͉f¢K5.^™DŽAV­ÜÍÙÛãÖ&‘3šALazi…–àúQDQ$U(xײïƒO ™Þ,nÿR× ÿ_û”µauFdŸßbn(ô!ÆÏ õô³cSúé9B)3ˆwq}è’ÔòI-Çb\~–w¯ì=4êIÝZ–G‚“ ƒ­O'051;ºf¦7Qܱ0ã;¸%¬f1â°€8MBQ Ó·‚¥×¬Övÿ_øÿà?«vº65ˆx#ÌTÖU—€a3jÀµ=€ôÂ!ˆŸŒ ÁÖ³ÚÃÞðÒ:f+Þuá…Óc–èhß®À‚her Ùt3Z§äAãYˆ@ÇÀqÀ<óŠak?sOÀLê…£*‡ìOÙÄpå“m$ÉqAPÎYwü=g䲕cÛ^ˆÃ!Ç$УPPa4#K¨³˜]ÉÃNAPDW$Y¸"LâÍ‹²é9;®Hòû$¾ rŽhª³”Eóaè±]Sñ³›ÁÄIÂKÒåÈ(ÑÄYg 0ÁÇÂK Ó…9Í’Ji/˜×ssµý÷é}?Ù_g·†[†œãD˜LŠÆ6$V•°…! (ü»âŠžºƒ¿eƒ§Ï¿g»+i‘Jüø»C{ÿ-Õª!ì‹"0à­ª€‰ÕêλÓçÏWäprcsïü$àuGÃŽ8t`À— 45°#8`A w¡Ót ƒIga Ц­¦Nއ',7#DÊg;5æpã[šÐÆî8æ”HÐchià`aMAÂÎ@ͧ6í’` €ƒW$ŽMÕÁ²hdeÓLù¾“¶u'È:*®êO¡T@„7…˜ÎcA}·®Wê4=~(`=&ýtÚ ÞŸ¶9Ü78W—B4BàAI'Ã{ ¤¡ Àé?;! w‡×’@N‰A¹‚¨jRÜ’«©(6Ï7ƒñ°ì;Þøpª·ÏAžƒ ~;ôõ(§!Cê R-QC¿7/æìá±÷U<‘Iež½C6¡zᇠ‹n Ñì9¡ D7Ù…5hŠï»Z©—’áý;'va®IÉô½¸Žß ,€Î…EÈcQ${hžÎq‰0(U0/¸T±@ÂÁ„­\¥…Õ¤J΀9ys Ür†@ ´~¼þrØÖ{(ö5¢¡" i¤p–¯€OaavØÜ (  £Co(^G²YÙ…I½‚Ë™)* ï÷¬%çÄçš©QCùêN‚È 9H$½MÑDœ39íŠüŸN‚v;<  ‘ÁÆè:_jŸ™áBµ  M|øjAÊ–âiäùÙæƒüuÙáèx$¢È:›&G0Ÿ‰Rç,šñ¼4.LCA,uïÙÒ§#žÜT µS³e‚ ~¯ü",ô:çp!z. ¢ý´[7°2ÓPÚÐ"G ¸{ ÑžœÐGÝ0Eä½…Ptõ>º“ (’žÛÇ$Òàqb½ g‘Ðp)Š($“çŽÁd¢”:à`‰‚ 3·»WA~ð)¯râŒwÇfq£¨“¬ê½<† ’, Ã¥zsuAŽd7¤yn«ŠW̾|Ií`àcX¤Ë«¤^£Ša^3dXxbBoÅCB-¼Ùˆº1¿Ns±œë¾Û1rٲDz²ÙWJºŽÍ÷ÃæÄBq_'×ü©ù?gäüWœ]ß»ý—ålCì'äJÊÊó’Ÿx%45%ˆÐ?q£´ü$¦ö[Má‘Ü„ÅÅÓÿ9.ÿ=°ÌÌi…ˆÐ¢Ç4@pqÊ,¢G¦A&aæ'(ÆÌÃïeª*%Ùï˜üZfn™–……)qA²]Ô˜aEñr1mª/-îæ+$“…Žp .p˜á·;‰­Ü ô©$"ôø¬…>oW¿(ªü+q1’Ûñ¾—g†%й¶¿`Y—ã„á äî¦ ¨-ùÍ)Hïù5:mEET H,DgŸÏ®ß6µk°hîaÙ‡ 6ÉÎÔXÈ$*´4°Û»÷Du‡Agpà9$œ0އlQmeÛYMÆ Â6¶ÓPQ¦–4(8rÚ04£ Bd8] lq™ØÌÆ—aaEˆ E û¯ø~è«i;S’HÕoƒ^I õÆŠ½^H6úŽIÔéçâ×àPµ1Ò ²;Gì]@àãžQoDQ‘~¼iäÑ ã…ø 2#³¨Ö4 »˜`ÓÛµ¹þ# ¬ ]%0q å©ª@rÙŠ1^½C@h.ƒ}ôð3º9"Š ÜrÈN7Õ„Âú®¿°ÃôhxHtЈ$‘ÇôÝXÅ™ŽÅ #uºÄoÄAPvþ %ØåÃ…q‚ž»’ гчVL!!Ⱦ7á%ÝG(Àì;$ï 1žœo1Âùè:ߥ„‡c€åEÈÓÔOøìó|<ï!Äp@z an‰‘eÉQn íØÝ„C${ ½.74{å+UÚ3òÎ^üJZ¶|¼ìs$kˆ¼y¢iO]ú-6:L“2lÌË.Ó©¹Õ§c&øaº‚SH.ù· ·…ó…„Š ~ºi~´$ ÝŸ¾SØ©îÂïÆI [±GA!2ÄØkdds^os®^{O8¸ÔÚntiÀŽ$ûË`«/•Ùý¹Ñ¡‘¤ÑÈ蕵vçgMMP´Û‚]ÁL©®ú~³È=”ONr£èò:NÝ›ê[Áë°rÜ>÷pá%”¼³°jSùÌjåÿ_öÖÿgú_cI²Šzqé%ýmœš‚ wa5¹yXù;@QüÖõ^Nw/ÄÀûlXqÀËðrúµÔ“!A ’åç@Q±Xâw½Á ÙpÃûReö—X=¯mÒë»~ï¹é÷2aŘÖw¸MPÙÖªùj¬Ub«àîôxøP/.k(}W ³tþf£@uf£T60= ’8[N´>ÑÙ6lM10Ù‘)ÜoymM ¹ ÀD6˜n›œ4Y…%%,©g+6úÍ[š' Óƒ}ž§—CdpBy¶rk‹y¬ÎŒL§†ÌÊhÄÁÁˆª6q¼‹›* ;]W>­ð³¾Rð˹F‡A³ ªaN50f±)¢dÀ¥”¸µY˜<ªõV…j00ÖV-ª¦F ZUr`Ê1(…&©f‰@AD³Aˆ6wÐÁ2Q”(‚ e“X¹./zhÔ¦0 dÂ!0b1>a©×É¡‰Æ„¦"2’–R–PÌ2`rwS¸ÔØ‘6­š)e)* ¦"˜dÂRΟõd‘ )²ˆ›™‹bm)4SEG%Ã$ƒF„’™)€†6h0=º&bꛥjRRZ;sDfÁ“E0¬Ì•+²´f|Ý«_ïùËåÞr³…œ±›{Ü1]ÄIJ g‡‚däÚ?Îè~Ä‘ˆ&ÓïöðèOý?êB^^u§™aæœ<¯“¬a(“¼ý^H’Å+œ®•o”œÌ|WJ^¡;Ýpˆe±zÆK[6L×˼ªœCÊ)<|þd°íò¯L5rÐ4±?cy—§{ÖJéÞU›fÓ¦´Ûi¡–q5 PUE1 …E–%`‘ÆTƒ`´-Iab¥†+ÛV–’¥øFxúþo[4Ìîùn$óò´{ÚHˆˆx_:ôψH-€@ˆ˜™ÙòõŸŽ*ë5‚ãépþÿÝ}ö´_íö—¶ɯÂLéµ]Â2ðýÌ|?´Ñõ{Þ˜zDŒ:7Ãò 1ž)Pñvôq3»þ[Ši7Á¬;Sn8±d{RxžŠ#(²"ÞÈzbŸFì±€ ˜(øpþ¹›ÑÉ3uñ4xv+û~—è,ß©"mÃ\u&FñÃË<~…ž>Ÿ/Y¯AÉH²x¥gÚf'ÎP€ ¹Œlø•¹G?‚¹L§ÖÔ%£ e£;+#ê¤ïˆŸ¢©Ö*”œÿ÷™Cý £b•qâ&ðçÄÃo¨’ÔíÃGC!ØSL$|0â.&ب4†~‡ü)«›û±3 p"*lh—B9ïꪣ\˜ú'³ÑqÛÐ @NïšÓ}í…Ì! “öLUö­i§âïÁÚ¶ù®ÕÍ 0º/7–íÒöÉvQñˆ¾’x|ü1¼‘ ¯on Ø| |Jê«øÕϲfNÓ˜úRàV/:ûqw­»-Yq•/ü¿£ôgoÝÏõ×öWÜXçXþ[ETžgçʈ²Üˆ"""$±ˆ®>òÈ_-nZ¢­vÚ^E½jäÙ&HÀ­íH” *d§˜Ãêee~Ême‚Ÿ¨/‹ ~¸ÄQs®\©õ´¥…òn…*PS˜à^~¶¾tûO÷‹$SõS"\(¥šŸÇ­«yY+°Ä†q’¢£ }0•ݲÆí^n%bŽ(ªÎda‚à¼X?Ö©¢ª…R)!J F¦mIU™¢;Ÿ¤Q!qGMp•—8Ôa“´¶â˜¸a,4(jº.Íoßš A(2îiÕc"„ “1Mu*Nã <߬kèÉÜ0Åý tCò Jõ9²þaØ0› ¬iø5r9Ô’)ƒ‡{DÕ‚¸:W“a†äo»2×]8éÁo}?Q4¶u©sŽAÊ=Ë~;§X¨«ú‹YÔ»™£{Å`«\ýfê^4Ð¹Ž NÍ¥kýf9‘©„o‚q… ¦YF.7S£ÙüÈÃ?áT‰}Ѷ&(µRâü(XTˆÅ pMî¡«øWY+é*B+KrÏ“â°ÃOckîùÇ£í}#®°èœzî[þAÉ8’)8HãŽS@Ž4Ìк–ä£)uÅï`÷m/½l¢Ùm  jÀQÙ¸pQLÖš‰@rû¦uêÖ8Å¥§|ÑôQÌÞDS'Œ9#`ÁR…‘YUKSB†'HçY´´¥¨Æ2¥^ ªi*%Æp(@þ…Ma@‰‘tYæD¼ìôÄÇ_ŸÑ ’k²ÈÄ6ézæEiЦvó. xsÐ)_*ÈÛÛ  ….0.+›·™ÈÈ•ýÓrDMƒ :ƒˆ˜bu?”z~…îæàœòP´JwŸ`Ð{hs¸‰¬R^K‡¡1M£…¦ƒ‚ØÌd¤Mð88´#+è AÐPp‰–„(gŒÆuYDQiQ…|ž9 ¥žƒ|òó¤‹ ˜¢”¤™oô³(c¹% ‘ES™<Ýp6R¦”=µÒ^8…TJ˜Œ$ Š£Y€èIV9CØŒ 0ìÔ'sçÎW»¼˜)*A*^p‰2§YxùU‡QèT¶Ta_œb~’ ƒ‹ˆÅô-&k=b¿·. Ì©å2-Õ+.ˆYIÒ5ôÝŠTQçX$ E2&Lc¥æáFd(bQ,fM‚°¤Ic–—Ì¿B8TbbœåÅMa’Îe˜˜…¥¢œÄŒQÌD.»u¿~Å¥WbzÓòÒÞYÖÙ­ü}k2ºÚñÜü¢\´› ©xÝ\د#'¥Ù[[uìƒâÖ +¢•¦Ûä³4Ê´‘Ý ŒùÚæð¾¯tláÞå‹ì"Ä î!#ÒƒÃô#h¥Ê”ÈIÝ•ö÷Æ0}¢½žÎo„}¿'p€•TDí.‰aѧƒ:ñÖÖÿ 0ÏŒûýlèôë×ü×°©œñÅÌ’Ô²ì è›±²˜côKMXl¤å¡üïõ_ÃmßnŒå§,ä²>íÀûØö>#â>#à=œóžcÌyO!âxž'yÞ}àûáó?,EùØ‘U:ÔTô@R ôÿ€ÂàƒJ*ÂŒÅ"Á Š«b[!%UPZ ¨‹I%¡l‘È´[jHZ‹AjE¤Z…²BØZRKI d[$*ˆ–…–,²Ù-­«V•Hª‚ÒITª% U V–­ZIjÕ±ÄK(Kd ²H¶[%© `‚”•RªHR¡R•J¢Š’IU©TRŠ ©#E[mR¤*´Z ‘@ˆ’E  E ² @X¢Ä‰$Š`ŠE©%¢*­Yd‘l-’H´Z‘iЪ"UZЍ…P¢4¤XÈ!ñ¢¨Û!'c;HP™”ìÒlx6éX ¼%\kú;&Ž$ ˜0ù¸Ä0„@fU…J2V ÃŒ†-¡QdF"ˆˆÁIl­–E–¥kBŒ%A` ¤b/î®9F2–‚BRŸŽ6 P¢¨ü ¨‚È`@Œ@,UU„E‚ EDUbŠ‚"*,A(‚É((,’ Œ’+ ’"ˆŒbˆÄX¬b ™üç·ÝÛT‰µ ´H•QQETŠŠ ÆI"€B#"€Å‚Š£ˆ¨¨zÛ `UáñóXP‚ˆhý;"§+þX[<„ØÄAö;‹ÙxŸ'æêúï´Ëï?Så“Û{ Ï6’çCÇŠÛÀëúÏd2E*{8’$"œØb@7¢§&!ê žkÕPŸØŽH|sÅ}Ï îAQ]ˆäÝ jí=ˆ 1TWÍŠæÜ$X„I‡˜( }lr]PÃáa@m]äàKR `…H%Ì@‚Œ¥ˆ3Ú @¨Ð¨å@ˆ+BÄAiÒH–’ÒHÞÄYB"Ô‘¤¥¤[$-’-BØÉ al‘j`Z‰idEPC׊aÅ@r(ÐO€f½²©*mi¬ˆ)6"‚mƒ1æu2¯Ëص½¶{‰'YòûkWÐäÁĵñr…@o¹iÉ/·®!÷8~½âÑ×ôp}«ùg@€ªßù‚¡ëÝCºöìjµ©³Ã§d|Ö~” +x+°ð‘DÅÁA?_Ne=_»6çÀü_tuÙ€î?†ž»ÚÚѲpJ§u<¾Od.=5«”K¤«õÞqð¾u.î—»¡OW“óÿ7Óø5éù>Å̭˳Lì=ŸkžÛq­Pg÷:¸óžârÙ4â¡ý9b½šKM%Cr{¸>ò ŒUˆ’˜Æ" A€'ƒ#pò•vC¼µªoáã2–ÅÉ…¸ÓÁøàƒçµE~¡@bR´²OnA,HpBTCà!6 ïöÀŠ9¦)ïêt„!*ª„Y‘`0OË…b1Ÿ+°9‘ú0A†qD`ªy*° 2A<" t’ÑjmFSe"AˆÅŒ‚Èd±ŒEB*‚(Œˆ"(ÀYQ‹Ád‹  °EH"OÚ<*X±2 `„ïMLHÂrL’@'8kEã2$Ñ4d†eª±@ÒA5O–A<§$$j 2AUUUUUUUUUQUUUUUUUUUUUUUUUUUUUUUUUQUUUUUUUUQUUXÅUUUUV1UUUUUUUUQUQUUUŒUUUUUTEUUUUTDEUUTD’A$UUUUUcQUQUUUUUUUUQUUŒUUTUAUUUUTUUUUUUTEDUUUDDUUUUDUUUUUUUUUUUUUUUUUUDUd‘@b€ÅŠXªÅV( ã¨uFÊ@¥€Ä Y4ï:e²` Ó§[|¤&˜§qª\ ¨ÂÒì<]ÀÔEP;j,PIJ@ÅDÅ-“›”‚e™nÉÁ½¿D„¨Ì,…ˆÅI +$ž–ƒ=e”@Q§¬¢ä̶k¥¢8€TE‘ŒZj"d‘`**£/¤R( x§a*^æ\¶¡¬29¶ùj® ¤Â…´¤4ã ƒb½išÐ°I…—vè5˜¢ùõ15ÑHLçZÓ8ŒD“é½vÐü­ L¤ƒèD‘ÆxÔjÇ^’&´‚“QTUµÎVȶ&Í–cQA ®‹*‰jËxüf6ã÷\4œÒØA5±¨â$Ë’&dDœ•L“½Ñ'¨°S‚‰úMâ"бˆ«AEEF*Š"Ec1Q1Š$$‘PXE@ªÅ@b0’1ˆ«AEEF*Š"Ec1Q1Š"*É *É`2TÁ:X’D¶%°„‘ `%–#EUX‚"*"¬AEUDUTDEŠ"""ª¨ 1UAEUTDDDDEUDUUADDDDUTEUADET ˆÆ"ª¢*"ªª$@HŠ‚DŒŒÄTDEDFDb"¢""*""""""$`±ˆˆˆŠ¨ŠˆˆˆˆˆˆŒDETEc‚,Eˆ¨Šˆªªªªˆˆˆ¨Šˆˆˆˆˆˆˆˆˆˆˆˆª¨Š¨ˆˆ ªªªªª1QUUUUQUQUUUUQŒb*ˆ£`€‚"¢*¢*¢*"Á""" ˆˆˆˆŒb""""#ˆˆˆ‚ cŠ¢*"ªªªˆŒb"*ª" ˆ¢Š¢Š(¢ˆªªªªªªªªªªªªˆªª""ªªªˆ¨ŠˆªˆªªŒEUQQF""""ªª"ªª¢ DUUUUPAU@DDDDDDDDDDDEDUDUUUUU„IUQUŒQˆŒb""""*ªªªªªª"""ª¢*"0b ‚ ˆˆ""22""ˆª"Æ(ÄAUUUF""*È!b UUUQQAAŒTETDDDDDDDDEUDTA@A*ªª”¶¤‚À¿•i‚òÏ Ä'1$y"¸lIñ ¥)PTªª•jеJ ”•*-ZUI(AU‘V  «@ˆ$ˆˆ‘"EYP@HŠUE©lª%Y*¢¬Š²•QUR•J©*ª•EUUUQTªU)J°J²T¢¥T©(¤’¨©T¥J‰RªªªEB©UE"©J*’ªŠJµ,T¥*¬”±EJP¥J¥QT¥HR’UETŠ¢ªE*JPUUˆ«R©EEQRJHˆŠ F"Š2DA"*¨”¥J©d¥”¤¥U%T¥’FX0R¢•*¦F 0U*QI)DAE!J*ªª¢‚ª•AU!RŠ¥UTUJ©%• T¥ZµJ’Z±URªBDŒQŠŒREŠ*(¬"²RªEJRŠUP©UE)*ª”¢ª¥IT¥J)E)J‘Nd×»¬sbŽ–ˆF¨€²LS *"ê¢Hª¬X()QÁÐ8$dTÈÐÐ ¡ $ªÀr+aP  Tb(¨Ì”¦ I¹'¤è $t;bHëG¼(ëG÷‹C§ä»§p@yé`B’U” µÔ¦¥U@QRàQk1j¶n(ÝD"Ã÷-ÂÆ$è`ô&÷¾¶©Èhcaq§”h4£b8ÛYÑ pY‚{ )â­ˆì°,"œB)‚ŠPšÔ´†ÒÂjŠA®£:Ö¦´É7Ú’DX;\„5xK|ä&7µÜfmMîIª,˜·†SQRIGãèÆ¦ ÷ôtJ6ÒÖ«D "Âiqd¥VtÌrZŽaP·Ã”VÛT`ÁU€‰A ®d±X³ ["6PA‚Ó·0U\IiBN¨†(ÛmØXR6¡fÌÍJº,+Y(hŠãp+j6jRø²ïY‚¥¢* iE6ñƱ4ª-ƒq\Ad1" JÉ%¡IiABIQdT‰ "B²@¬"„•!(’d3 Eša ²&" €k3+"I¬")¦€¦ ‚X0FÖƒ 6 ­P­DŒA‘âe‹—Yx¦‡ö.œ«n‚ÌÝ5lyq4ÑM8`UÁ#ÀàF8à¸Ì¿elî§·ëÅÞÅÝ ‡3®É?¬70 ˆ¼*Ç 6w€¤ä‹ êW°ó¹Ûå=:_œ¦WõñÐ쳯8'ÏÀuß9by„Í ÖÚÁÈÈ}Ý%0³G\aöƒ,åuiØÆ)=¤óåm­2ä@6@&”0?Q@@Çoõc”Í¥#@$€*MYpÕðÖíb/ºì½]n>3^ÖÅ®zï‘!vk.W«HŸC+Ó[æBt¾?(M4Ãk“zCÂþ§ÊùþOÎ>ÃËúíО~.­ðùŠ‚(é@b)BTŠBXŠBY“WÒÆ$Ű©Îö@yï97ugñ(Õò3äøÛWÒ’ ’!#ð«×̘S¬<ï×忥ËýÝàSí¾!ýpˆŠº€å¤DÜ÷ê€Ò†ÿÂøKˆ( ?0Eb ÄTD€‚“#ô@»÷PE]»Pr¾J ©¥éÅ?¬X ;.Ïïî#ó ‡Jo|E€`î¾^[™w2§CÝR ;¢€ÙPç¨>íî Sæ}}z˜„<÷ÒYsq†rc§.@õøìwóüQrzPõ(fUÊ’®èrANöÄÑK1×iaÆ Ye´ˆbúžÇïîEÞë“ìÒMBë+”jü“<.6ãGC`@1{Ë)÷3Ðt?ÏÝ ŽI2§ïöpì°ÂzMgFyù(µ¯ ÓüJ¿åQ±Û5Q[3^p3å;•JŸ¸Ð½§ÇOAæòm|ò~ˆ?XŠzAô ÷îøa—𠨚 x ¡$ÇXú¿{!û½4ý4ƒêâKlUJª)B©U ¥(”[l¤T¢•"ª*¥UUTK÷æˆõ^÷µhV£ág÷ö<è@Á–xʃð| Þ6ž}¿ŸòM'U 5ì×S?Ò¥°¶F½VMWsïe«ZŸpB_œ$áH' ˜Žy²X° {VU#,ÈñÖ4‰œZ&$©9¿K·'\ùb¦§þºábâÞ*Ôß_®âŽû³7 ©å–0|ÝLÂB@J•Ôà $`ü—1ºþÛó³ê³üîV°f>›i_¢Õž~¦î’B‚Ád"‚0FHªAa" "ÉH°"X  ‚„EB ‰ ŠÈ @HªÔ‘h¶$µ±--KE°AB,YH°Q@R±l‹bÒ/×Ö•ÿ†Ø¿?¼ÜYÐâA<$„üÊIEDP²I$BĈ|’ë‡y ´  ‹Ú‚ ðQs¿—-4éA¶é¥="]_þøBS Ö#R¼‰ù žX:yH‡Ü'äXô3Äðß6ȶ½WÂÆ> ª(á ~e±2²^ ¼<ÿÂó†ÇÚà°¹ l¨h^h[ê4¤„‘h©$©ú¹Ïõáí>ÞîöŠìó÷Ÿ÷åöTi'_}°˜ÁHRÒ° †ip‚b_òu»¼-N¶&üöDzÖ_9Jÿ.1¶yY¦\Uÿöê5Þ…Ý'S¢ŸËÜ÷è*ˆ ÁU㫹,¢ª–€ªÙüý_QØä¾aR¿lÿ1V-†ƒîH ¦u@|ëçTB•…,!Q d#@Ò*P°bˆ?Kçê‡Ú "ƒ§G´°¡bÇîñ€ gáôüŸèÒ)Ðß÷ÜáTCé<ñÁÐ(o «I¸nü"€K[×zlp'%AWþZÃ‡ÇØÿ_ž5ž ¢¤ë(2üJo@‡’tÉpíf=áïZ,hé¯2˜8vHRRˆIžœñµkí2¹'Q+àÑ¿-»Öïy?;ÄâÿOÿZ+m;yY? 1ÜïÌEºyJ¸Ë|û®æó5ög"y1€oÜ¡Bc;àu­¼º0«÷y«à˜u y(ËóOí}¡ö^'Ò¢©â¢©›8 9³–4ƒÙbs/Nö¿iÜx^Є Éáø$I"äò@ðˆ÷ãôIÿË]¯ÄûSƒßÒÛy<˜sôÏדáô{[n¾³Fõ¼%­žÏ8`=¤’Nâ *ÅJ¡m²ªªQBªUBŠ’Šˆ¨¨¥J¥R¨•B@Bâ  LdÆ £á*u-ÿ„ Í÷Ü ®ë_õA…@ý¿·Çè=G§à 2Š*9{€0?zypär2W[TÄ´$I·~‰†‚eÀ (‚¦MqGv)ëçE…DP ½‡ŸP‡`B|9Ôå~Fº:P_QÒÐR€Òz)iw߃íc|£i°R}´Fb D”㈑ŒH@8·æMœ¶dÞÒüÎÌ&²°šl°´äcî9ð À¹|ŸÜ°ë™ø~`<Üõµ…À¯$쀙¿ÝÚ¼˜<òL2¶° ©E¥)ûî¬ §¸íT TAÊ)ÞöÞ˜- ï1€ m´R0€Üaçç^p628|®Òˆ±ô`ËfÄŒ@ÀÆí°DR"D! ª BO/Ï©ZÁ˜éù9VµY÷ ’¨0Ó+PmyÕÚ|7KjŒHHÑ»‘j€â †S6œéŒ P8åÂ2øqî>$ûþ™Jÿˆüœ×$Ú`é´úÚ¶²ªtegù‰ûÙ±ì½á¦Ë‰²~Ïl ²„4ÀAñ<;‡ ,‡ií<çü66zzûß´ùß÷ÿÏÿßB%…jæß¨'õÙ+'‹"=# †y˜€+@D)Aæ"#Š@F@bÆ0EH°b²*È,€ŠÂ,d!攄ž˜ö'°}€§\*"€¡@é¦ßo™O:³äö   íï˜{žÔ²€çDP‚€àtŒÙïûü2™3b €Ê!—[þÑï+Øø2ª±åö_Þä²ÒŒ+)*5SÚõ¤è'ÄÏ޸ē#=‹åÍ!ýø‡–X° 5TŽd‚TaE³q[©§åO¸ƒ/½æaäWx’V ?5ÖtÛÈoâk3yÛnAþŠ¿ôñÚuóL<-wÚM¡ì{ÞÛ³|Ý-Þè³ NÎUž¨W×ÀÊŠ^(Ûá2„6 {H{w³„'}öYìýG¹ú³½GÎ(ò@šŸêŽ ¼q´Ã°x%¬Ò‡°¶d&2@‚/ÝêGÁ ûàjÖ"¸Z½Dl…n¶Ó¨b»J°¥v1ÿÈ2“ÈOhh6¸€ ³D*×uŽ^€ÇB *ä˜{¨Fäã˜"X ¾a¨ô Mn÷Cïk…"0u°ÒºjÎãyo½+ KX/Ø?M®~âã¦úOLÂP ý+Ôú^‡og_ÓažAt|ïÔ„r“Õz»^\ªbCÿï?¨¶ÎÙ¬Ô¦¶@Ày[€îb÷1 ª¡#ǾÅ@n#ýée¹éþ„Ý-6J@ø(’$üù ‰"ŸL æ²þVHòq-nBw¼é"$ ·£@f*ˆLwPD?›ÂJDPáSUÌ pAÑláQ5væä Œ›„íŸ8èÅ«œü§üæfUOÎÔõ$!EÿÙ\8! WB ôTlЬ¾¢õtæ³ó1ü-_¯ÇÑýðö¶¯ßNåË §,ƒù}Dzí¿SyõÓõ¾ “¾Â&(ø1ÂA樱¯¢§èâ²~¤ª(²÷`~Ïõu]6“é}Mîˆ*x ¸‚€/ƒæEõ ¢óàƒå@yœ„DË·±¨äÇÈÝ¡+Á+Çñïã«eMÀŸSf:úðqøW=0¹º;VeÓø>y|aÀòµ•õþ‡†Á¢aɉ£p4”Ö&ÉPƒ‰¹Nk¹(õ…_ϪÞ!–&C6CUÍykû¶P/%~‹âï0©NÌqcqòó±@ßöèƒñt‚òX´Ë¤@BàAé&¯ ùxܼ+þÚÁ¼ø¿ÜëÖöòбû wc;<²01’>SR§×Óo8‡d =ÖúÈYO`tŽf€COv mÀ„é ”HL"¨•ÕõÛ?_˜tU4ˆ*ÅQ&Ëýs÷rsüµ»ïÏOÆpà'ÿ§2·°8å'~Ìn`w|Š2À9nHI5h‰yÂE d킨À…„¾ÙδN'oÉØö‹lh~»J‹n”ɇvGÇ—Ÿ€‘ãKö–ÆÁx iÝÁ¯d‚=–A~—DOÂú„=æð*àªÿßçúýÜõ@Dð@y‚*AWß\U4ö-t€Ÿ'µ÷h=›È'öÞfêý÷Üÿ¨<_h8‚3¼„•ôÞø¹¨øÿXXË:ØóB|ÀD( AÁ1&8a‘€qóK{¿‹ËX‹ã=ÄÈdW»È‡ô`}ÍžbH‰ñÙ9Uéyî0mš-ê?ª4ë‰kʱ»•Ëœèír†Wj[&4×ñþ;?ßú¼¶mË{¼ÖPÂÙ4HË&Ûä„çñÓgDŽÓZµ@Ф~#ŽMwÞÝ»c©’VaØÔž‰ìÒׇÓôƒë£õp=õ°5O‰…íU_õÞí³’22§œî»™ßxi«Ì÷_¡@UP‹PR H[Iւ¤Y%j–ÙÛKhI-¤–жÂ@¶•’ ²I-¡+*k$¨JȲ°Ú-¤…¶Û!P¬…¶-¤ h[`ÙØ´T¨Kl¨Jȶ …@¨T„¶À hT*JÈ ²ÚT¶„©YÚHJÊ*V@+Y!Z’Û[BÚÐ…IP•••€Vk[H[B+%¶H[I-°’ÚÚBIm¶ÈBµ*’Û!m$©Y-°¶mm¤+¶À l…¶JX°¬…¶I!m [@…¶[BT¨Im ªT?µŸLø"ûQx8ˆ¡%‘áúí‰L]¢Ú O¨!ò ·¯‚Ÿ‰à"!â›!vBA$Ii_‹oF}€`?˜CÈ9·ŸÓg¿Dñì©å™!!!EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQîÉ?¦¢~˜g ƒ¶ž>IÙKOßž†®´ú©_T^Ê dµ"*0k5£$30¤Oçs6ÀÁà„ˆR¼¹¢¸ô}+¹7§XNWñž¼ì`•œËž^QØÙ’H Ê9O/»ÅÕuû'‹;7±›P’ÿ±^.´ÃÍó>ªèö'Xšöb‘DQ7@A‚„ô‰¸‚žá‚žPUðÐT±îÄ‘ãÏâ¼y€€Îˆ¨„PPM‘ÏµÞØçŠÞÙ̓²÷Ð^ÏÜQ¿ÂÍ…íú&ÿ_$ß0‚}̦~mç 1‰¤§Þ~÷=a쟨Ÿpê! øÌÝõ–‹A¹å,QƒDFª •’ˆ))°lRƸqŽgíìkM3 Ð×_JA=„‘*@K@KB$@€% œ-€¡qme;ûêVËÞv;ë{¹eG³”Ö—Ø äРó! `ML§²24ÇŒ!½˜Pìÿ£Àð‰;‘¢¿~ 9€|%ÏÃû¾0­<ïk¼þ#×¶-Ý ÛŒU¬±ôlTîwè¿íð¿3øúÃç)£øçµìÞxÄ`PxÎÄe…"èÀЇ€>™ÕàáÖ]¿4!4úÂ0÷P  #€ÍMñ}éý1Gg*N•—.²) `aûï '~(‘!*ÆâegÅÛñ¬º²?z*T<.®MEŸŸ9­ÈÜD7 &õ0Å MücÓj‹íaÄj5úl àeÿ™û¤>>å䎧¸ñ^ÈÁ:â)þ+uõUV-kzËdéÉÚäÉŠ¸<ÕõN8\ý6Aõ<_æêþû3¶¹|øÄ®ÐØ}ïW y´Å-5UýÂóÈê… îg3 ÀÁ 6·œÖñ;к½¾¢½†>T€ÊnÖÓ5û4˜˜Áhío³^Ù¿Ø=Òpwz×ɺ›;ß+ÉÏïwOô#·&–3øD'"á¤`ŽØqÇl/@à€T€#ÀS¯t€$ds©åËEZ/Œ¾íÁëÓ5'#©³„œWë¢WÅk|žMÿÉÏ?Kýº¬ ûxwÓÔ0¡!Aoèÿ‹#íùG¸±EYX€p‚Â0:6šÆÕð…XìyÃq7LPòÁº8í#§›'ìpÙ}×ú<%¦Ð}kZ´g9´f?“v=¸Ã4bͺu@N'FETED?WûÓƒ?7òó3333.eUVb~ð9Ø­pçâU±?FZ¬ÚÀ3¨ö¢,v´œ‰öÐÈD݆Î~M)mÊgôý‹ä=–ÕÞ‘„s‹ØOº'"\¨_½5šÓt!“»†°•Rˆ!"FD…fàÁdQK!à2ÑN.´«RpÞ¢BàÞ¤³ÜèûôxoIoØDÚ(†ñw›ØK-UÙÃ÷Aá«çrˆݤ&õøîÙ”ÊÕv®eWŒW']Ùà ¥µìpœ2EÞ›÷* m]„1ÞÑœŽÁe­µ¡<LñtÇ—6äýƒ^-ÁcR´tªÙFU ¯9¼–vî÷j³wsyËÎeWUUü‡îFoê}¡ù¤qÝÄ¿š_Ò ÕüÿªÛ¥+oe7"CáawŸÑê60ÈuOYïùwü)mƒ×ŸÄ78G¢V?gžüG.{ù\xE.µÂÿ6Š Y«ò,uï›¶)&=ÑCánÿ?±mÿÝþYÖÊÿÀñû?²xvpƒ/÷?/ýþt®»o­ÖÆÙ«`¸BR‚³3¡=Ùnì¤Z˜)Ç.ž¾ÂÙ¤Ž…^Z`j}Žçrp+àƒ Þ Çƒ¤‹lô9ØŸ—E1&ˆ°†y0+£È$@ƒEC~Æt]Ž[×pþµTËmnÏX¸LÜçÓÉóhYhÍNϤ!c9[Oq3y Q¤1ÇÞÎ='ïís-W+3 ÏäçûéÒxÕ)ûfH*«ŠÙ7ä/Ôüš<ëUz¾Ï˜­õîûšcùÿúò…ÊìØ6~+£UÇŸŒÿ7WÝ~‡ ó§ÜRü3Çöb¡êÏŸrèB›m_§·«¦§M¿Òº˯Pä7[‡dwWA¾ù]Ń ê®ÊètéÞ?¼×Ûûÿô†îîîîîî밢̡œÔµŒ-¤¬b ˆ,‚J¨ÑµhÖ¡uŸÇuk«R»ø´>s÷ú÷É÷*¯b~O;®ÉܯÙ˜ººÅ•µ¿Dðï.ê óòñ9÷ž}7y±»3»FînÓîí“7U¹i’Wª8>@EY¤…ƒ–…•KÙ‡MveÙÆtÕÓF»Ë,¥¹±Xés­Q&?–íÇÖÀ€‡:¹4 iù`åÌË]wv‘D;~°![opr5 •T,ƒŽ‡Õ+£™ˆb&HÜ”b~k ±kÉéÖwfÞm²ÞÈm÷Ÿý¿å?µý§çþƒàQ=ÚÊÑóhæ‰öo¶T!e^±õg[nÉÅ+|YA}YXNç@ýåd(~î‡à}ŠA?’d^¸ú$úÍ#ð™„û ®¡ú®~£# XÿZÂrz AìZP*0©€†øûRH‰ý *ÒÉY[dA$A„K(Q‘„D‚1©Q Œ*¦Dô¨¬0öÒ ïÎãç½Øoå;fÙ á2¹»àŽiÞ[_ì}owöaí¡•4’´Í©RMjPlÅhLÐ(ñàÁØGÐjNƒY6ùWåãžåŽ ßê}KÌ!ó;ÌGB†~Øäm2¦H 1¬cQö³”(LZÅ7]nýáš°ç2j(/ì ü4Yäê>¹Wóáëâ#ÖŸ90Rä;ꉘÔOÇb¤§¾î7µÃ›Èð›_*{Òß*•|‚ùŒ |‚]GÎVÌiцÜŒ"ìÒg·°œWJßË £Üö½Ë¢ÆPÿ^sÇ3W}pôùë…g=I‰%¶j¬zê÷ßÑàë I\ƒRÂÒBŒ~P9sA™µ:]~çV»S5}ŽðíÊGÂ, üEqÉA´ßIøË"úìDYïÃÔÙ-õìÂBOœ<,ø9t2:[Ù¤^hh<")=)nMðRy4Ç2 gq,ù²ë­ê+ˆ Ncx.Q@íë“X‚«Ì IéiUUU9_ÊÞÃËè"˜ÿÇUæãÛ˜uv»] e“F“nÚ§BA4M6óŽ À°n¹Ü B€Ð =NP D#Á ÄDŠô¤‹0 ¬¸§G°^ª…jÈÆã3Û—žY8Ž4de»RÙwùMZ óð„Às²‰49„Qñ`,ž@·£¹í¤çì0 ŸD`— î|ˆÀ.ý|^aw‘@:šxÛ4ŽzßkÒס”ÂUËI¬NÆ'û‰—ñ-0pä{½È†‚æýì&ï¸ã§tœººg…@³³“MvgsÏ£’ͬ˜ŒDÖ`F#µQkv{Nˆ"Nœ'‹ÞÈ·Òlr‹H¸‘äÛ!o|Â߸½·µ4òcPñ `‡_ÎÌ!´’îÿœ ax„¿ÄÍÍ 8²‰Å’fømÎ kÎÙͬ…då&âîÔ)8ä”< ð÷¶´‡»•  üZ«öx'½Í¹ÉÂÏÍ«U¾F 6Õ²æò¶µå¢Ú›Ä2èÄjotü›dÐæÓ¾Š­YÎg>»ämÇ·‰×ÞthËRš-{¿$}Gðlüò·K Í?gÿwæîyz¹À(w“Ž¼ØŠ¢¿Óìϱç8óZ|ÜØó¥ý>^=ꛓD$'Ä«:ÅŽ´ö˜Õ¢Tzˆ( )"®_+Jà õ™þ¡æ«Gß 7ãq¢Þ’?ýbà îNHtCožM›Æ­û ¢iPü6÷HŸÓŒŸVsàßÑ€ƒÄºh³ˆip¶”:äM@` l$dfü­çâ}c€Á"@UˆÀD <`üPÚ7QýUÝUU%&Ñ”?]×JñÇ‘Š®‚ Ï'>H†e™É„¤•$B¢98ŽÞ¯hvµ˜¹ W]?_ÑH7t!ˆgÓ7Z ËØt ïÒa­3dЃcp¢•½˜2qAÆ5øšó"%˜ÆH‚ xU)LCa 쨃°Me²{‹ zžD%“{8šª7iˆÍJà¥5èÓ'Ü3ŽÃy§­ J•8ÝqLjv„ǘqÜ–ÁjEÌh¬V!Ê|~48ÜJbè-Xä§$D`s©Óv1Ή¤¸»’¬‚mI…L`æ@#É‹m¹†`¢K6ñ¡XŽ" 51R™‰0ˆlLÑGàÏ C¬Úç+œ¶!5N  ›]³qçÓ²D;%9,PéÙú({M§h³…lÄ4¶FŒL 2rý³–\–ðÉÑ®S0¶”Ì,aa©"MBu›=ÿÀPöð÷#ö'r„¬©ôA‹'c+”9D )ÔÁg k`Ý Àtë·ºÛ4Z›VL“U¬ú½Ø‡ly;hxvP? .PŠv®^‡G~¡Ä„LÂG~äó¶ kl÷׆'ƒúÞp*i¾qÌ—„çP¬Õª¬Aˆ‚†å¼wmF†›74)Á „E:–ŸYúw¼µRÛ%,_½`ø¬ TâH(@éuIk+›±ø¥ÍF¸^Å€ û–\dœ¾ÌÍÛ  ŒÖèT!Gt7É#Óû¬t/'¶:¯ÇS¹’C$!¶HêiØMçR,A‘TbIy“½˜©!üÀbÂT$ KdZZbûl¿ ¼{R `ž‰Q6!5Y ª²ª=´ô÷þE»›#18dð]UFB)"Pà˜.:~Ìá-”Ô,­ûƈ„ð=6|8ÉÓÛí‘ÎÞÙÓ½ÊN1Ør‰.íΦ<0mƒS†ô%€œÒH£bì"AIFEPÆUJÖys½,vyÊþ® Ùs2EÑg ÚÚå@HŽ|“†öªç; [é’.ú*uiü6}ÿoÉ" “&i -ˆÆùÍÃìÕ)iV$~E2³Ð,˜ûè-K†$H“ }v‘lKZ*`šÂ(¥ K"Ê¥…Z¥R[;—ëg–ÂÆ¾|J’ ʳ ðq¦o÷o–­D¨¨¹%ê‹”™œÌ»Kºn'z–I¢$¯,‹ó0ý®ýðPé贯ן<„Ö7ù't}ˆš¨OOŸ¼¡ëù„Â& †[Š«2Ù¤%jÕ~ÈÝ=ÿH¬‰Óí°±Œ ¢ÊàR‡t,¤`ÃÐ[4 åõØ€Hº8Tœ’Rå”Û’ªš®­À'•ï¡íqÒzÓß⊠"‡ÓÂÄÊ(  VDm)Z¨ "+ïòtO´›Àõ|ó´ ‘´jÒ%¥‰?ŠNCIªˆTŸy¼ÇËž‚šdƒ€!çä#$šãBEƒD+PðET™Ò€l5å@²æš°-DêÎÈv-ÍXmzÑ#Ùiˆ3ª(T%=v‹… 2ú*©´5Ÿb‚³³'yìŸ!󲢈‹'²׸<¦iød³;îýÕPç9¢ü†ÀâSŽzSpöÚ‹¤' —2:P8&M´/nS` ÝĹÎ`›:ëBÅì‚T|Ã#HF]u3 ëJýG‡h¡6Õj¥E=¤Ëgò›Ø£2Ö U‡-™œ¦˜ˆ°IÃʘq(5Ý=Ós|kÅä³1´ga!!‹Rb)iJ†jÈtØCÐ’n$Æí°#Í;›©q»ºŽw†³4ŽémÓÐw©N5±@4 Ud¦ªaWãÔ å6"YÛL>O‡ßø}ì:œ³£(´*²˜—±HàÀž¾I'¥‹D((2&NN~D”«VM&ÇÉó»'‹à#—¦:ÎboÈü@ÒûrY‚Së3ÇT9€ƒ)ëO:4h¯Ç’Dú¥ õ4bðä:ø§SçXPÖÕ‰šhdÿx;Ž]|‡ã®¸‚m8 aÀ‚€Á€11ð1£RÇñV¶ÎlžO‘ n¸NÞ«uxg«àô^«hû¬;,´Œˆ« ¸€N–öŒpö+ä‚(ÀUH6žÉ8«ÌÖæ©ñ4£Á>Çò°=ØBt©r|ì£Õý¢ç ÌfÀðB,X/¹‹$*IØxç? ü&ÚWøµínÚ ±<,-!jbŒYjSº cŒiP;Ñ8Ðñ¬ƒÏsÅMIÈÊqË4Zæß§Ý¹±ÂKQyJŸiñ oª2›9ÌÃj¥ÎQFP‰„šÊz¤#Âõˆ‰êqçATg|Km B1$¡(j"Œ UhAXÞ­TÃÑâßwÚð#MûJ>ªÕwž 2µçà +Dó¡Fh§úâ@"²Iè³äEŠ­ö«Àþ¨ˆ…mû”y@ãkˆ§–I€ Ü¾`ó—h^+šÊ<ÔP¤/a@bQ•AÜŽhå‚güÑ¿ßð*µ’ZZqF´ó=èÀ„ÿ£ÿïÙÿ™mGý”è7qœU>z®"®–82C‚íW‡2… žHâ"6#n>šÏõ/â=Ï 4Á@` ÌaÄì.·a$uC2Ò£ ìýÝšÝ-qwölæG¦vžô¹ f]Y$s½Ìá°QÙ›!„0\?Ë}“ºŠ€â2kÆëꪃ-¼Y%îêÀ®åùm¿œnÕ•Wv¾ Ùùë“cñòdÜ”™‘Ý14Ü2 ‹M0~šÀR\=/ž¸;?Ø»¨„ƒuããI'£ '®¢ïÉâ.#™‚1‰2(ûÝ{˜jÀi !³='DÄ-²AàŠ[#–TC|_4…Ì<7œõ çÎF~>ç Ô9ì)W¬¡˜Sè2Œ¢Tc…¤XIJ6kXæbˆ7/æa7š-b a‚Öi[F¯^¤=ÆC}Ê=s0ˬq>›øA·.S«Vz&[Y/hPÑEl”þ¿ªàPæwîÇ= J3Ú°Ä¢‰ƒEBeYE2‡ù_·^Çøn!;ŽMw“Æ>ž î 'B¬O*C‘Wó ëC[Ÿ'O= ÃI}‡oN’÷7+üö òéŠuPÚœÓC¦ªÊ.onÒè9Ó7*¦­ ²â€SÍ¥º³SbØ1Æ*ÂС ”0'ï‹ ®›É`QÇèJ„@?Á8 ’T{"ËsÑ”žV{{¡«H®”¿ìàŒãÞ5sÅ«ãcwÃI‡„©Ýd´Œ©‹ðÉÍ3+³AßWN’}ÆIË'0äBY (VH{² ÄQXª­¬TkEË Œ< Ÿ¨HøOw8èCèwSQHh7I‘ùåh~|"8À1×NÌÒ±gž\b':H!ÊŽ!©š\áØD‰ó&=Û;éÍžUy.ûÂþÈ Ò„UE¢ÒAÀk¦'FjŽsF¬¼ : î† ââÐÇNiËPXµ–§{ù4§Èºt!®5± À!.ÉÊRÐDp  ’Ø! ÓA H«Gw-,1šÖ–`Q–2aL5†)¶FÑaiS’-4)`Å4vhˆ¨ª”X ˆˆŒ’EVH$£P©FRÂ^àøÉÜ=9'¢ì&SðÚb#×o“É•­Š)8#\èìˆ9™ ™ñÛÛ¯¿új=x,'ÑM>&Ûå ˜×—LcÎ §´03¡BH ´}Àï%Eø’§õÞöÿºþïþǯ{+Ý;õš_ÌÁ“i½Ý07º :Œ{ꂞRkfˆ¢"ÓkU3p @ÞŠêQ]Á0 D$#0$cÌ$‚iƒ3œÁ\çY¦:,ž9Ñ Q›Q•ˆ„# ³2JâpJ¢V¦ÞRi‘\…³{é•ALjts„Xˆ(ÆCWH9.·.CP+:8eDIŒ ¼ ‚T¢+‰b¢([.˜QQdc¬°Æ=”ÒLH*T¬8BUDEDŠº‰@xÂÚ{ÉROËÎa–õ%̨Ç-мš2eðh'›ÍÇÍìC¦è>©—¡k3ªËåôˆI2§o¡\sç?ÑcbÅcÕ¡!—Åó>€£ÅÕ‰èÏ`>ßôŽý§QfŽÀMk4ëçmßu…ÔÞöRUzr .®hÒMòäe)YNI°ICØ6ÚúͲtDÞ_—ƒú˜~/îáúJé„6Ãd…“—uÙPúÊÛ9+ÝQœ±6r–*ààó„B)þ»üBHo©RBâ!@hˆxß8ð¼GúÍÖŒÿ@PYºXð¨* ¦¶çª ÉHdcújÜôl`:Ÿ^ @#yƒhP(‡šê5Vå)E¦0‹D±ˆ Å„|üû¶aú$¡(En£è663™w*×ä¥W(`±Þ²b¸d°”žüØAÍÝdž!†O½Š©-…¨EÆm SÑh,ÛÐCó Y¿#â0ò°¡ñê„'l‚uÌ|‰ðÌ$:0ÚpÀÖÌ1;&霣ÚX²¢!Wb‰±DY)„&Å*.&¸8a  fÆõ-¶)åʪ ~‘ϤÁ7ÁqÍýŒRÞUÛÈb`[÷HñÛtžw,ÈÞ' äžaöj­²³ÑL0»!HÞ ågÊH.àE7AVwgÑd ðyÁ;,¯Æ4ˆ›BÁaA§YĤ³ü^ã×/^³‰âxŒLÇ‹˜0KÂÔõ;s›C^ÍÙu<²I’ É N\I~þ{Yá<´ uŸÜîî“SÔø”’I¨á> {oÀ¨jLJM2ZKamT—èTÄ1c‰%4¬Å”ÖÒv,ñç ¥]oôî´|5BÀìx3hµ(`0Á¸eO'@x{^ÇNVjŒ"ÅXŒ4D¶b•Öpb‚&Ç‚s+—žÅ»ø«óyf- Á%ûŸ©åų@Iòߨú$š‡‹WÎî3Ý›.„èÌöY¤‘fñ(~;Ðø%e^oóÔ¢ûë–c¤$#ž˜|‰ñ˜µ¾³á{ûå"Çiµ¤j”ß´íÛÕ'oªbaûéœôó»1êoÄb#£W"ÅòñòÕEþÉÁ¡„!§¯‰âS¡á¾Üï¤ð韼޶è.º‚ÍV5 ©«²Uc‡&˜öÃúc»ßºc´35/^|I,ºžHsÂéáϧ‡dÌFxƒV £ë¹HcÉÎ¥šù}åTz­âGÄucסAóOÓ°!­ËG3öù–gCXö‡ëÒÐ!4ös!½!7z¼Ø£%þ¾å¡ã}Xf^ˆ§4®Ï *cÕ“ƒÆÈoÍaÞÃnY–(KPìA1Ø¡ÃgVSN‰ž×jµ›¾ú¾;xøÙÚ(ßwÞ—˜Æéöœ¥E]7yVbœ¼ä¹Ì§f¾hä5Àö±N@Z” šÓiŸ¦k@í(ñ$53yï<^¬Ó¡h‰P{y;sHqi;ï— IÕé .™É=¯QÄ™þjõKÅ"3áSµÕUÛ·§mwÚ‹V¦^ÎÖú^pš@ñ;i¾¹¤›;©!Tg}¦Á µVeÇ0Ì'¢ižgOã˜fq;`’g±G©bj¾}a+ÚÈ0Œ3R¨_='_TýÊÑÎx`›Ÿ]Wõ¬;Ï7sÓÊ^ØñE†Ñv›†©Œ|¬¯ˆÉš«¸cDßcS7h-è†öšéþºÝHé….C»ë¿£ÛùïãÜç¼ç‘¸«—œy}»ÉÎg69‹—õëèFö;ï5N¿2®ú@Ã0Ô~ú›þö]XGBe+wØ©/¢$Äb‚ܸQüKðÑåø_cúoûžã¿Æ.ÑgcºlÀÝÓ”g·h5& †ÈÁÙ˜¬Ø”6¬ ­µ&M´Ûtz&ôh.ô?±wájý9·~ñá©þt¥àÄUòöæp`Ú £m]ÏÁ jWÛ²¾ÿ.×mnØßt¨öœuûµ–^¡†7”w%÷¥%µXþTºtKJ ’/~ƒVÿ¬Ä.lUTxK2_; ˜ÊƈŠÉUc—#— dXQ™”3 )*ÛcDLj°T´ZÌt 5HÞ¥bîž^o¥yׇÑo>'µ4”ŽIÑlψƒ3¹’º6QÓ·£+Î_CÂ38Ò+)A¥ÙwáÂÏàóEb ;t;·l|•é˜Ìõ%ˆ‘]­=˜z›—nç\‚¹œË'º1ú¢9~ö’^Ô®>Ü„‘;IÚÄ‘D…ˆ*E‘¥;ÉË™üÃc«¬qßúžN®íÎøÜf&uÆÒ\£IÖ¤ÌÂà]£)Äàe¢^¯<ÃBŠ!âC¿x"ˆ÷H…"êõNŽÏÜnxwt½²pî;E‹“cnè^Ýè.¬ AÄ`@"BÍÁU±•±r>·¾{V½1õhðnéW e’­Q²Gm1Ql”¤¶Ñ%°ÕŒ-%©,ÊÕ‰ 4ˆO"uð;Í0p sÐSš„¯å󢩸Šä›fˆÚ U°ÒPP û¶TG¡Ó¬µ²HhÔX¯,“ÎWUL„ljRj̘©"éÝ@°XFäÓr}þyiQ $b(2…0¥(X“öÂÈ`kÁrmžŒ³ A‰ÎHŒ‡ô’N“ ¢¢mpJf€ÌV®oÉÈâÌ¥¦‚¬!¾ÑÊ2dóµø{zäî°ÌÃ;/ºj M»f~ÙøÐâñí@ÞþÞË ÷Ñx¼D=ǵ Äóï¸`‡qÑž ¤~d±ÚˆÂ^|º¼ÃæXÄ0IÙ®{wŸ¥OÚƒâdo_{œåß½ûs9¹?_ú¯+ÓFbzöíòŠÁíd}]ÓÛýdù‹Š]-LzLo.#Ço§ÄOgJñè⦫Çò]²(¢ï· @}YÆ;!ËdÂ5ä,å9×Ι(èäcs ‰ÇDØd  h, ÁV²…JITì“H± 3€˜Í“b!rŒ6¥®°Á\­JAÛ¢BÀPÄá Pådº™Id³f\bAÄìðå•W3 CÑ(Äó˜G¢HCî H'e¯–ÛyͱT`ˆ7 ã¼'Cpññ§šHy"0€!sá…ªÅP{`Ñϧ釢ù…àÄlR;½/RyìXlÌ@&ŒìβPx)8ZÇåÆÚb#Š’ˆÉ¸%ß0šX‹óÒÏ ‰`hàóTÚ·`Œ‘ŸeÖ†:–$“ SSEм%T8t& âx™€,ÑTŒ¤Û ÌÉ”Ã$ƒL™1E’bÈ!l¨"E R ,¬‘¥+°Y-¤XMR˜¢@¬+m!±²Ä™#s³×î/ÚúîºAÉ ˆhe´Sr%½ÿ×ïf¹¾Çïò¾œ³ée˜É³¿FKõ/€Úß‹oZbv¼$Å›€%¾ç¿ô\Õ»;½ï«‰"µPøöDêPæÙš¦Ëè”Ì»yE=mÃÀ…ËÇÄL)9ÒA>êÍhrGvŠd•b±„ —óeÕž‚ÃÔ •ÊE4è´±¤a±”Ðâ*7_‚¡–H‡P–bg«wcLý¿™ÖZ*’Aiîá„@bA@k• %ömÃ#ÎU/DŒ b ¨{1ÁtÉA<.jó-ÔÁ[뻟gWKøV2 rà(\ÝŸÿ¥ü›Éä´@ïaÏ"gxH‚´E;(q\ˆé*QÆJ5›`¦|Üäã‚ÎPQam‹¡ú¨crµ½Y€~B‘‡V3‚:#Pd †hä=E ó3#ÞN®.©O·ÁeŠQŽ˜f—§×æWb`fi A¬ ãfÄà;®æåÿGúî|̾£PÜL4ÂF T¨ªÜèÈÎ" .éܼï‚—O: ,¥?pv‡RP}Oo½f ¤TY(ÁFD’*RƲYi£á‘:¸GL?öØ*–QóâÚ’^ y>„2%jÐ%k_D ¡X’¥´ŒL,¦ ¬Á'¡ Ÿ‰ 5NÉ.ñÛÚhͽO¶c•ÕóÖ´O$ˆ=©¢ˆî¬b $ú*‘÷úÉâõŸ"[Ö»F)eM0‚›Dؘ»* ÷8Œž^HXÑÛžÂâyõþGw¿Ã¥5¨ÅEí¸‹]mµh:U\éqßÕR›…œÓ`™IK­xÉË‚¾o_xdÕ tgï“hx|K‚™†”ÄœbPº¥Ñ,®Ø ÀÀ‚àÌE«ôAXx.Р«°r*_àas؆úÁˆEżVõ½Øob|z¿R(€Ó 3'K-ï¨IdLæ#ŒF6þ]?»w>ƒÖ{¢Oè°> ª«e¤HˆÁ‚,úµk2T¨b’¤•µ£R?•hˆÅ€¬ØB ꄆXý¼åi>ÃËÇ-úÞ»>bÔéÙ’î;†¯±…³ž¥Òå–†xڅ܇pC°Ò÷ÓÜc/!]9×§Y2»0MžML„"d 1Ä»ô1äÎW½ œ{Q3#VN²£èHƒ·9BÉa,ÌDŒF¼0>Uò(ØM¨<£ßçþÎÞPû¾U9Å÷P@%`T‚¨Œ‚ŒA E„FB*É‹#H,„U,„XÅ$‹,€±HªB,Š0"„FXȤP‰RA@ˆˆ¬Y Œ"„YY!‚Á@"$P[$œæ'e®šW²0e¯·ãÖÕ±ø¤€ˆ <ɸÂ.ZjlÑ£Q‹d;Ð&ÐÒÅ“tÞJZÌ«¶m"K4­ƒi®ZSö>äC[v D TFFD$ ÁÄ™KìÃcåH}*gÚÇií:ŒN‹û%²A-[Ò0ƒ2„Œ‰¦âãåóúí‡"gŠÈ =¹`mAIÌ\9…t ¦˜Ñ¯²㻹NåS!•Šgœ]v£ 5KS3îæ¦š¢žåÞ6c2A7ŽØr“Œ1Ý3®X"+Ä (!ÑT@*µ™©ÎqGa­C·‘^qÇÞ—>½É.læ~ÝæóA=­úòq¾Þ¾ûoš'oéKvц;*ç32ƒ§ñÏžºˆj‘ÀÂÑÏóz‡Cú\‡ÕÊÔýS;`ôtZ.Š~©Ýd±§c.šq€c´a$ShöGÆ(Ë Ÿ;&l¸þ6ƒ¼4€ é±F@66)6³PîM“äÁöKsiÑ"–€TÐÓØª€þ¾>hÎC!ŒÉ„ í¸±yñÿÎx‰Ã$øõÉ.@OE´<×ξSÔ¸¤ÆšH¤ÛÿŸŒŸƒÞL[$c ¢ƒ¥@Dd@¬£¨hЏ_ðÞ+)DTEÅOóØ#5"-H’Ù!%òEUâ°Â—>I A¾_Kxj>Õ¾c±Òý@PÍœr¯½ ,Ö­+/¨Új°¤@ ’Ãôçn_…Pí2o&òh¸$Br–lÛ§]Ï`ÚM@ÿN†0‘1¢J*2T¼Ms*Åpä.]gh~ˆˆe”­PÔò¤›Ä¨þO$¦‘#*+¦GN½/!ůσzŸ’CžNÑÜÃÌgS5ÂBDîxͲ¼ÍãÓÚ5˜S°†Ò3OUA`QŠ##UEB !sÆ4aT5tÈÑõsŽÞ9È­1®ÎqY2FD ·‘¤Ü—‘Áº¡ˆ@ <ð¹Íaæ¥ þŒú)]˜b£ˆ èå‰$däÒRÁH<²Q¥ÐŸBxˆÄå oÔa”°¸Ó„…ŠÆ*"é…j©‹©ëb9&Ú·wN.$y$%¨/»›¥4²FVI¬’@71Üùb<¿ÆÂ©òL>v «OIÛ ‘À°/ª?nµÇI8^'¥~B¥2-0K¨²"KTDö¤Ž×W`$ ¹œ£—/!L~1ùÖ æ`E/‘nµvú$ŒI±åºQæTRN¯kí˜# # <»Ø&P„h=~ç;^Áœv .N ÉðzúY±p¢~tž´ö¼¬Ûj_PÒs IML˜hvˆ"G ¢Ò$÷F1#?®¦ÚQäA¨[­šÀVBÂŽ]‰EUXb2,UNª~… ˜TEbD½¢a}sÕÃCn±m˜w] 9r[¡ó,mSãPY=l'¨gö’2bcÖÔ6‚§Îý)sdYJ©½zi› ªsaÔÅI´áwL©—>B€Èq¡Ø—°—Â1 ÑØÏ½v„Gæ6Aà‚cìC¤p¥fw´œDËÎàÑAW< åÄ›¤Ê‚&£1Ëxwx%Æ,xÆ•~­í4E;š"Å"/Ië”Ùäã›~K¶v¼Ú7`’ÔìÞ·Ú• †é^ŽÊI'ÐØåw„ 59-Ñ©—*é¹h”ñ¢(ýŠŽ~\ÙÄÌBoÇ“²t‰Ž›%§¸·Ñˆ LÕ=´+wa4*%ôÕ0Š4öWCôa£³éÞ­ 2LÇBg¼ §…?q€xsöSuAò>ÅMt8ìí«;o´ÄgQ U“µ|¯™Ý2æ6™rµ-ËrTª‹,ª’)%_;6¸5TJ4^JçÊégAÀXŒ”Jc %yÌ 9!$E(Z²Õe‹@"C´Ë *­.šåå'ÀH ªXP`ˆ„E¬¡bêT{ä'%I—ì{oÒˆDî…R†â3Wáð'£>Ú|j/kV8²zêÖ³¶''¸£4p‡—½†¾­Óê>kŸ£M‚͵ú{ÍÍ[…MáSA€Ã{:s~‰›åŠÍðÀµ5uÂa'i ‰¥ÑqCÙG[%¨tRjr*CnšêÃl[E¶R˜g:ý’ÄàpT0°×»ÒÄWð|a†“£> <;=õ¶ÛmhÖÙì›"žt:x”g™ìú 3H,ݰõƒ7—û¯èÄ‘b€,°!„VDB"/z‚„DŠ 2A@F,`J…H ±dUI Dd`QPQdd‰"¬•j¤UUUJ°•j’X¡-Z•K,BÑl"}p D+$X,ƒH¤X(( (AdP$ŠbŠE„P‹„F)‚À‚È"E‚„·/•BÚ}Ê÷'ë ¶T>lÃá’DÃëO“Èøùé}EØûɉúÞ÷™6ìY(DÔŠõm¶ Ôa>¨{쀰÷$7MD¿ÊЇÑtD" ’+˜\X*D‰ÆÒrš$I@c@J²(ZW AI+1„gHh3å²³¸5†Ù?ÊР¢Ãë3ÇyãÝ{ƒb¹ÁÄ''‘žËAÉ3 ©*À  9 䎤‘:qA9„¨‡WÄ„F WjPGÎeᦅ匦LºN·h¥6xÊ5Þ•Â %!PªÏ·C50ŠÏ]4là˜(ü*¦r7rÌÚö4i)e072S¢èõ»…¢È€ûP ¸ãæÝ-Ȇ–È»=f°ƒZ`ˆ!„¡87¾`‹¡Ó ® Ï€c¨<= ô“^»bfµ€bx¼ýòuÓ¶÷Xsœ4ôç3j5«a’‘ÊǤ4òvÍ“&sˆ1LNM<œ…Ö´å)½ÛˆQ$X"{aAL¨"ÕßÒ"X©WŽ´`DÔ@HÈ’#1FĘd€MP*+"îOoö§ù¸ý´ª‹Rqh–Ê"Ž¢Šˆ‘F°ÕÅ0‚ ‰ãyæ8È8iœÆ£òUjtîì›!›÷ ¼3a¹qÏ,ˆCdÀK“ôñë$ ¨†bÏå1m'xfé\õ¿Yë±CÑÿއÔyT‘²ÿom¹ŒNß`W2\:ذeÃ'zTd$á’P–Kœ&·|ç‹?“ßpÿŸ?²l}]á‹Kå @DDN\Gq[ñoã> Ã[ç8…ŒÌØ€ñMç.˜`—þgû¨Mbtáí{%Ä¿¹O3ö>á(Š"Ÿ7Ý ‚~½# †0˜3L™ŒËdi×§Ÿ¨pæp×àV…âÎ!æáñ{p¸yûº˜È;A”ŒÓýß<‘P[Ž•‡¨ùû»øK¦1<ÇÑ:bO< {Dàâls€«vˆíšÍ4AÖ\ °0Œ Öß³õOOyA%ÀΡj»þ[ï¼ì¶¢Á¾ÅÌ]g˜Ü¨1-þy™ V'‹ _IðÄIüÚº%Ø?Ë>ûæøÙ0`@™%TI•P%•rJ‰õ˜#+!(&‚qcü¢ ϽÊi¿)‰!"Edœ¥Va%EˆVŒ'âýþòÄ6É&H±ˆ¼ ¦LB !YÀÈb³†T‘d׆$"ƒ0@ØqC@ªC„²î™¨·†nÙBL3s‘*BUE\ÏñÙ°tP6(€ÆÒˆTI9d.®™(Âá O14¹Tû?ôpBv–Éþ¯×Ñ Ò‘dE23ûšZf¶Š€Üµ6µÚb‰D!MÊ £ÚLàƒfäv²'rû‚bœ•Я·©³ºÉ¬"9?{ù¯ÎäjJú[ùžÒ j[Z¡ßþ‡ãa„ µËá­ÿ+B„­H eøg¹‘Ú’Ä’'¤&èÖL(²*ØwëðMhFV¶e“TnY€Ü ¢|2=®±1"8(í+‘ƒãFN·W ˆÓPšþl››!œ>¿,^ÈÕXÀ]å1""°´¦0¬Æ‘•)™]lÌÓvHQ˜âb¢?ÃeA4Ú…Yà^Žj”âˆÂËnÍrbtj! 2H[k F&ûbH–0€‰e$ *»IzC¡u›ôô·c¼éf·¾ýV½ŠUy‰ üy šÏU"pE­¹•ß_§¦v¤Èq€ó2tÕj´P¬ÒŽ+1†#ŠÑªYvÌÁÑ[ 7H¥ ü^MC¨ ¡“}@²šPRi¹Îä:ÒLÖIÜþ‘òYÄQBªØ²É"-¥ŽãüCo…ü¾„U• ¢Wº¸ˆ’*ˆª ˆ‚*¢"*ŠˆˆÄQˆ±TbŒQ„ C²*›Q“¾Àݮ汣¢8÷Z®ºU1¢áP ÝþŽÒý\7"ìЄÅrRøN´}ÞPί©°QšïL ÉT/°]Ѷ©ç˜W ÞUM9 Ѝ,Le„¨ ”Eø˜ŸO• rs÷f5‰¥®R"|íð§¯ùlj{lh.\¹|\I‹°Q8ŒªH¢ÜƒY!õ™ {…~’,³âMå(“ä´›Ku…LRU‘1®‚ÙOïxœ ×ĆŒ†a‰KI $ Š1€Ábþæ…4IÈm“^ü [}é6êBìnwvʰÁ¥Þ "M@@æÓ³˰…% Hô=ð[€Çtòžc~Ô3‰b{ªOzeVàuœˆNâóòÍì ¶Che„~A±B–[àÊCgµ7¶¤™QüÜ‘+iƒJ/Ù}œUº$Bà›']dy$†åî2OWÇßõ×m¯fþÝ!ïsIÛÉÜôëg\xãd&$rê³®Cs]‰l™·u‘D Æž{FËô+„ö…uÚoVÄkf¶g0X-à¤Ê€PqÀ€ J—}¬}§Þñ´ô?>:È*‘i$ŽbY:—›sóHþWøzy©Ì´šT·•Ä?Ü•õ”BªME¢¼bñHh«$´öôÛQLC§5kÉÇn'ÑÈS¹”g.†"’ t¸NAj ˜Q¢ ˆ50— È©‚¾Œ00Oá=ô×þÁ›•ˆS …äƒ.ÿ}ú¶‰§ôƒôàøºñß]åÂÒåÈ}¯Ûì7Ó†t/@ïÙ¢N`ÉRèv‚ $ ¢(§‚®bfð¿Õÿ]Œt‚'Çñ‹þBLn`Q2Y(Pê`=‡’?º‚ˆ^ž{´Þ¸°ÂܶåZ–ãGˆ•£m&;¾Ü#HEZYBÉGgϱ9UV$±>ʋی–fá¶ë(¤µVHH ;¢©\­àa†* `'uDtø…D*f3»v;‰q¨r¬TwàœY÷IöþFgD’z;Îe…¡U6§“o²*îf1g’Ñ]ͪ ˆ|Kš7c4 bPÚì)ç6îRÀƒaˆàcÇp— ³dÎ0cʱ¢(X6ç ±"Õ-#áò;Œ:žâ 2¶¶ÆÕk6ZYm-‚%‘µ9)c¡u*1Y“h´!¨`01¹ƒÎbß&<ƒ\¥Å? aY@¨ÄI‡ 1%«‚VJÄE7uçR'îÒŠ.HæI-«jͲçM SŽîˆÑ²£ çZ®œh]î"K\*¤„Þ1 ª‰ÃE,¤½˜(ØRTÜœ@YâBœ¼RMÉØòÈ¢Õõ^LöúË8ƒAÉKé°¬ƒTPþèˆH%ãk¶• ? 9ÃV‘hêhG@Ø(íöرVðª5¬[<™>›4 bIÄíãS¾lΗ·ü»3ŠÙÒø^¬šk¡Z(R(qvqÄ›”™"/°ñÙI8Z-Ÿ"Ïsð˜l?ÚGµ ò”³V;dE'X)[‰Q1Bô” ¢šÛÌa=j˜‘!ò‘©ãÛm碥šàÇ6•ƒí³´ÿ ž=ÈÅ]O„CÖwÙEßcDÊðĤ´ Î]‚VJ!´Ÿr§Ü£ó>{ÜþKýÿCòü¼š¸7iæSLªY QRÕhÛrö45ôøš4¼³fXñ…ÊÈs†dÖî£ „ ðæjØJý OÖÿ_¾6…Ýã庚ÌÉ$‚¸Ã³D¶†0ÒM¶²[mÚ77r‡_ëxÄ5«›Ô10•\)$„®IÌuô®Œ½ãˆ–£N2Lr<· ƒl®™/ MXb@svŠ¡‹1EdšOÁtE&Ø,0àà¡t¢V nŽY¡•›7¬ÖR|l$•€Mi)…N3SF°26–¦8ƒØ™Én¶Ã—1A -Ê–ŸÚቑ,˜Êã åO¨feÂ]µÑO´ÝP±÷ùì*mºrX‰|^ê2w1“:ó³Dã!«e2ÌÌ¡rk¾y2ËÙM¸j˪i!hJâðoß~wPé ´wL¸ ¨~)Íý.ãëÿ¥j~¨N0Ðìéã»y¼ö¦R!4H“Àã |ßì^Ø $ ƒ;È—ÆHsuŒ†Z%˜ƒ Šª]Y„Guu4õHì’HÄÞ'- Óš-YVñ§/’?Ùº‰ATŽÉRHXk?±À±€à 2ÆlÊ%ÅRäb‘XÆHÆEbÅ"›<#™avÞÿlò9yù‰ÚJÄ―Ü"•$$ ØF-±j[$-lRÔ–Ä––Áh’Ø[-ŸF*BÑ©#€L"B…ÉnÈÍö’X¤PT‹$_1‰ ª6Šè)H 1²´(,N)$‰µMÕï6¸‚Ù •3c%„ÑDÑRT´lK ,Žá£jÛ*¥V ˆŽ©wqg%‡žÅ‘ŸK¶Ú åKÅv&ƒ:;ÅG‡vƒ^6Í(ÚŸ)„;€=©ÞfÞ<}ŠÌ)ŠøÒ€‡CãÖÙÌèòhé;TKg,ÌnÔ¢ZtŽ’xR„%"° ­L,Å“B…²-“2˜®ÇÀ`‡ZÑ…éd5X*A«tѨœôš1Š-+˸L©¼O¬,KjÁ7ô|šç2ÖPDÆH& Á€H¸k&.D´Z]Óx„/Jñ@[„½Õpor2Hyöv_Ρø(N…ˆ„ˆÄ¶õU‡`>Ru5ëÜcNëÍÌ´4çÄ& š4}ã3Pݳ-˜]dá‡W~Ú.G‡Xrd Ïœfñœœ ÞÆÖŒ¦a¡0Òè«dVv]8ŽÆÜÐæµçK» é˜Í0tDc (´Øœ¶"%lBU¿™IŠ‹Ø2Àµ{‚ëEÚn3±ÅacÄ4J:R¦Z,‰ä%k4fµ4UyCQ,)²I€{®|Ç“â¤HÓÂöН> ³*ºpüGã4þ6¶{Œ0¯›N—e}O…™÷wÀ¹¤sQôúa¥4UEˆªñ‡q rÑñø@7 TßÜâ§XbUg5€¸åà;b±êÁè'ÂBw¦žO”‘G„úÚq,õ­dˆQaRaP¥¢‹‚˜T²1,¬$‘Y …Pð‘iäR­òî껢lA„4²*|Q„ŒCžþVá‰Õs|–'ÔµÀHH2)ØóµdØ<^Ž8\S”r& )‰.¶Dg3äÜÑGlÛm! çaóiݰ`ê{LÞ)'¹c -“Ãö3£¹» ‘Ý$Àhâ*’8`é#ÃÑ!'®’\ÄPÐh8ÝÆ5Œ$¨¼” m¦‹»?‡Û¡˜,fA¬ä9° îVtŒÁe0”S–)Ê_—Ù‘sòÎ.RhoPQ©ß×TPˆ5Õ”Š@YçÏØ›‡ “nš+ÜŒá¸ù*yìîb]5IÁDïí¼ÜöM`Ó4µ0÷ÌÉJ÷0´µ)HØÈ1F9¾*C1Œ/£E <ïÊäüÏåþ§ýÏÀìóÿƒK”Õ^­çä²sÙ6‰† Èôg³Ù @Æ"01D±ynFŽdœ9„ê¡»Ù_–×H}‹M™§³îO¹GÙó²ö7N¹ìÈu`÷•ÙM³.é†ìçÕ³sAaÚÎxÑŒ&/¤tckÅ–œ¬ÝNÇGÕºíô±ŽÅà¹EˆËT,wêXÉöÌ’§©Ò†$ÒŠ ¿•t´‰6SŒùV:w~0ž)Ù Éû1õiÇ–<¿”’È%‘d‘¨y€çŸâ§˜DÔüF)"‚1A± ©’€"¼ÛÉGÐÔ>tŒC!J{ ­ àXÐ_r9$ük`óñ_ –¢L(¿­“Š‹†®A±@¶·‡O´Áñ«Ÿ‘Ô?>øŸND„ÛáOR¥Tõî5ï|¯_ƒPÌyÖU+£ñÒm´š¦¯5¿ã’ûÈÙéVâ%”üôÁ‰í¥DDDDD<ÚòDÐ&‡ 0“D7B‘"D]²‹"qJp`= «fÄœ>}ó†fÍjQ (ȃïdJv}Çô“ƒ‰÷1¨Ây–2/¦ÈV $ `±àÜ6…Ü"B¼¬Ax%Á¡ÜÌ÷¬Ó³'É×ê—¨•a·NÈ®õR•UÔ¬*±‹Ôûÿßzû ýÍŸ/µƒ£¡YIö]d“F‡Vg~,lyWÛ»˜º0-Ð1æf‘æ-ôX"¬ ¢¡‰ uÐΔ˜É‘°âpvˆˆˆ‡9Ea˜L‰À¹Â‚ÑGóðèn…ÈH|¬øSb[DH¤ø~¦“Gv¦ôF#KÂ~…«RøZhNRŒÈ±”D²ô^¹œ”‡Í׳°Ò¢7ò#¦ùqweYsC½@;pd-y`hUEYfc'„ë¬eUJ@Dd;ذ‹°F¡D“x²‚’hDô×ÒÆ1'¤-=[88œ>a\NB‡Nþ¹‰8<½BáƒÂööÓDJ«<+JIܶ{¸—Q˜÷Òa´v¯ØÃÍEÕš)ò†p²­”DDELJ""""z»óÀh¥²Ê•*±H§£ {ŽÄÈxÁ6|(ˆˆ¬ˆˆˆˆˆŠªªªªª«*aUUUUUUTªR•R}ª˜UUU3«%0J0D˜”S¬úeÍŠ"‚ÀJŒˆŒ"[e%€Q‚'¼5",HÆCB‚Œ'ÃBN´¢CÔ’‰Õ(ûCÓz ƒb180<`T2#=oœðN#‚t Y*¨î¨©6Úùqíî¢_K–×Ö`8ÑÊ\X–P¥V&+÷ÿýWe9(ðÞ~–¿ƒ£f ư®À€¿°Ê‹2Ÿ¹Â«ˆ$UÆ€‚ÅòÌ‘ƒò4$Tb9h[:²bà2¶ÉX¢1¿épÅŠŒdx¦¹ÔÈ1xÖbV¨2Àl Kl-“¦Šé,X¬ˆÈ,É1•*¤sZ±HŒF1Ž÷•6êJ¥ b #"0mhTD-+Xc1\«-j…­e­Pµ°(0U ZÄp¡Ÿî2VDA$ÀµAAáï,Õ³¦ÅÛ@$‘ÏõYõ\S5+弇kÔ:ø'&‰²@#8L²Ñ—ïÖb«ÓºKTÑré¥0Á¦Íp´ÏQPg«ÙµYLç·ô‹RcFÎÝ:™G%Îì3„`Чë¡}]óõÍ ¥µÕ£cR±(Ò ŽèQ†´ÐˆÜ&Ò\‰D¶«B}— ‚Hè‚NÈæ°Êˆ0" á×tnÒ‘b7X´Âi7ö~«cFÉû‹2›m»;äú ¦OÀ­bªÉ“¤ÙŠgümfM ¤¦cÉalOwïý ýèÒ̶ š¨tó,ÓN$QQF\#‚;32ä>‡¢Ad@0" 5%"agGÐä1îÍdA8¬–ÀóÝÚsžx€H ¤_šÏU]n0P`²'=Ðþ̽]„aäÊžRD5Ž]*(Ï9…ð"bêT*‘ïxÌ“àý#°ø;Ï Q`ýJW¹ˆÛì• ˆJUUE¶û}2¬ETc[£¾u!,HM“Ë*–áùžÐMio6F,‘ãÓ1½c¦’fÅ9h«\fØÜ002‚(ÓD$€‡ Èø5xØ£ŠÄEVEEDTDEEUd„ ›“)s Ì!–n¹ÓÉ0„"/“¤­3ÂÝ€ ï3R鉫°îóm‘ü㙂*™”!*¥u¬"›0[‚D3dE11èÄ:ö-ÖÅÁr˜Á˜¨¼ÜÉBÂ¥çvb +5†R†@Á[ŽÖd­Š0‰]±Ó1Ò%5xmŠL'mYÂ<É|κF’riV|d¾°ø‚†¦.v&(¢‚¢T¬TTrß{è@þÅ$ø$v`jÞ"eâÍW Åi- Íͺ*&1± cAÈÊù•žqÖ³md´š×óô4DW¢A¥Q*£~.„ó} †ü/ ûXÌfÒöÕñy'®i­¶Õ[¨„µ’E}<šøC{ô…“àq_~xäÅNLšDfå !ÃP 48Î~“ˆ¦Š3gÆH "H¸}Œ°SŽH·äáY:›Úør˜!µ÷ÃG»>búÞ”'S/&t} èHK¡™¾KˆÄ_tj(™ù’cUõ¶µ„Uƒ Ä_ò4Rìµ(T¦“ BY¤¥ÝˆZ+¼síÉÄyýþMí´Œ±ûéëÏ‚ïü†7H‘9u¶Y `i Æ'ºZóld97·¸ž¦C¬@QDŒ×e°Fô…®4Õ“&_[W܃ßÇÂai”‘,ñ!=ªk¶,SB,>_£$ âlßFµ¨ÖÁÒ´ƒZÑl„êÎôÌH|QE_Ïa ´„'Ãô¾PíõûQFDH# TM)Û !±z4ø§ )áqq=˜f¹Ÿ9­b'ŸËZá9ã%À å´æh†¶ÝEÛ2R꺨#èu¢ÞÄ\ ¡Qom™  ¦R«9T–"ïRÛf¢’ ×(`Ȱæ»ÔË­&¸ótχ]& Á蕎ª÷w-¥26™Ñ×.[xM8é¡ñ= 5•wG_¢cy ~¥ÌÇû‰™${ÓÊïËŒ¶°q rÿ;µÃ*ñ,æ$ËiiC(P­ 1ƒ¥Ùèa ç# xhØ£À.9 Á¦À†ÛÑä¸Íñ fàŽH1Ÿ^̤%ĉ¨œï3––C‘¥X$&ÙbAy×C ¥l1‘±b©E_Á«`@šÜ2C“o{N¢l) K رbÅ~jPÀrÙ$ŠÐÙ‚†Ó€ÀM¸©0 E,¥Qe)**–&S«2–& #R¢P×0Ö­”²j1"0uóD‘ób‰¿#½;`<¡Øã§_&/ aU®!HÆ4e#3.IpÖuÞ.†L”¨Ib1UnCÅ€N¨uFôaó)Õ™öÞÝWZJƒy@ÖS,Ží £p!щ“(åÞ.7ôÄ 1ÀÕI@)TcÚV" T@FÐ%ª B+,>»ÚÚphДJ'aJ&Ã5>¶È`Cdɵ:fBNI’&5,Òû³#ìh)Ñ,™WBÂÒÊÊ+Z…”¬`¢4m…¦’t˜…“&K6ŠÌJÁ³cFØR㱘‡W]HoŸbsÚvÃ]ëàB$v$[®M%É…V 81Šöï¥Òl‡ q´µ* (Q-l8ÌÌ¥´´VI!!L KBÁjoÏW/Ûy~{ý'ö¿kó=—7£ìýï½æzu @ *ô“íÿÛžC ¯f<Ë.Gȉ ìÆDŠ÷”'!XŒv‘ ìA`ã»-…hASÖX +}Ô,­xK|M5×Q©Чæ b¶ë2g¦P𫏹.?}ýÌH""M‹‹ :yïLß}ºä9ߨ¦ö‘B"Œ$X?y~«äŸ›O¤IZt?O@6„÷ñôÅt¬¤ˆjp@F…ëõOâýoŽ&Ò×÷òwR"â®jYýOƒ#Nº')¯E†e¤¥Fm“ÎàŠ¦«b"/ªx¡°dO£>ΧãëX,÷¯¹ëðä§Ç¯"Âü„¹%ÔJyqC»_·—ˆöK õ ¤02=aû}úÐ;&A®¹ê{„úYGL«$#ˆÑË 1l0œâ…UeG¯5®D‹'ƒ//'‡0º8wÙM__§FÒ'¥Ö< uŸ”þ:¬+#Ô67˹OiÙ$ë:PLó(Ø!|ÃD‰kŒôæ"RcóÖäD¥”wª—á]oÞŸ:LE[óÕ¤òâtã§ŸÉÔø«=ÇcŸeï'îÌ ­‡-ÞH_ð¦g% ™Ñ ÏÄššÔ‘vÿLðÿo ™)„’ Їž•Aˆ" yl«ã:sËït¯§©Òm»µøS9\G·Œ—xrç¤7*2úÞ²jŽÆDHðãîĤ•q OfUCƒ©Q.æÐÙWóªb6~¶ÔÍß ‰Ç-ú>oÝøvþI¹ŦäKàý¯‹aՉį*‡eÕF#v\†¿Îy¥ö¾¨óC'ò:¡Ñ¨6¹ñ¦Åѧ;žÖµj6­:Î-wš¹CÌÞíu» qbK)å”ÊPF²]¹ž):—…ÜdNò§«ªét¸ü~‘ä:羉hꣷJ~„G”x¡wCd¸7ÜdG)üèõמB½›AÚYÜ3 …ªºÉ¨Ë{ÜxÇáæà9ßZP´èždðàÆd’B–Á;™˜;»ž)A ºøºäòN…Œ#¤ZÖº!4330ã»âhÝÜéJM½]ry(¥öO¼Z\%äÁã»ÕTŽªaûî‰S½Áï癀qþþ?ë†é—tÛûÒðCÏI ˆTM™h­™%Ê€°ø4ÿ˜‹-³mEPŠ}¤á1UšB«`å«»&“í¦XªCc +þ%q'öˆVHH™bÖ¹¿ÅÏ¢âL1qå’qá!¸µ9²–°q5¬ƒC ú)&D˜’!™àŽNN1Ÿ‡£>ˆ¾6°þÏòsîs®¡Iø®sgŽOÚ¹V5¤7AÊÓi i1û ¥kÃÅ?Lˆò.·ÄÿX:xµ~Ýá6}â™yÎŽ…y¦%¤îsŸ8e†˜Åcæg×wVe5€À€Žìðv6¬vã:O q£©üçd! ò…=Î"Vîžm^7/ÑΦÓzô˜ ç9="Ÿó¼ŽçkAÓ‘©¡/à²=w*–—6‹åÝÙdâ I3[¡Þ$a|ÿ7‡ 5QÁ!t§V¾–9²êœrTÓnI‘itÒA"¾8¢Ècxö “(ÌiÌ5«á~X?H€ìçÂÄOHKŠðr q2PÐ~Àøá‚þOãtÔC&ìé`šäb¨øWB<;¢›éôãèŠ †Ai/Gž0ÁŸ7ðPý8çHH%÷¹ì‘Π¬)©AGï”&±ÙB/Û䦟£üÅ}1Bf°Äfœ…š©åqz›ê^Äñ 0ô¸ä]zÄ“ªÒS¬3²ßé"H‡ü7Ø‚(ø1{ +“ö(ƒÅ0)ö—Xœ R5¿˜¢@RðPĵ2»Bû³ì°÷]GQ!*l>††u§÷;}¿5~G*vyÍ>@¶Oo§ézï”ÕÐûúÍk6Ý;nËsFe»Ý ZZÄ…¬—%­Eæ8XÍ»Ÿ`45÷UÚ!Ìøâ¬Ö#](dNnÂ44;xVÖ‹>›N@Î( hžŒEù Ëò4u ¯*]M¹ÛMtÝÙˆhNrçnË1…oF6ÜÌ-Òh ÔUyÔ ^œcÆ £™¹{¡›${(;z¨`M£+šŠRRT1bx‚ifì t=þÿϺu˜F:tÖAªXcë·¶ËeN¸ÎÔsÞìÆ’6ÉÌpO—©ÛȦÊÖZTT“ÈæÁ|ý Œ2ÁBÏ ¡ÀS&wPå‹4!¨¡þµ­¶TÿŽðb«àPm!žcÌJÂ$h ÏC³ÜÜ1økð| ŸãQßâœÃÌÉóC>z“™”ÞÁÅ@æTšýæ¾’¨(nP7',쫈D_¦ ÌNËU=o}<•uÀÛ?Û·‰¾u”I$„Y! ¢Â I%¨´¶$-"Ø’[’Ù‘jjE²KH––¤-[l…²Kd‚Ò--’-¶-’ZµÉ l IjE¢‘I"‚ÀRb„°‚‹d‘-‘ [jZZ‚Ô‰l‘i-!l-дA{Ò¥EYZ ˆTD €@•„X@"€¤X° F¤ d… µl%²%¨µ%¡d‘@A‘„E‘$RD"ÈEb `DB) $X,aŠA@UŠR€°‹! I"‘`KE †­M\o5H&“H'Â}°Øß‹„I rS¸eÚ࢚ŒFNKŠ£32\S •ÌÄÁ@A#U)$@Њ–uªÀA€KÈ%állSçÝTš[_I¤4*9 E•Nð7Œ¦Ÿ‚0RÀò ´µ‚~Nï:!¶œ þ¸ôˆXI ð™~Yp†u.žÀR• ° Šˆ1áŠ$”<ÿ³€‡ÄÅ’ ‘FÃ¿ŠŠåEK—ÀP_¨ \%¯ðIÉà ¥Š€`œow/J–A3?Èê«b^m}ou+-? ÷¬ÊZ’HX ²{}f Üy·ˆàvøªð2ªÐà‡YoЭ…ª“À¶ÑÅ.?‹zLØZQ_Àò³˜ ±.ólºÔÆ—Z´¶Åå"Æcv•Ÿ°È"hÊÀ2Æ9òã&¤‚`ÂF£4Ë3Ú¾¸ñð—BE2ŒH¥Ö¢iÃTd¼\—§Å<‘Ñâpõ”eF¸*•D{ƒ]Äúh"0EH¢a )w¦8;fmíÐà,B%Ëb(9ѧj.Ôr ·µÚAÐÎY’ƒ:F€¼ 3¦xY2¹JsÑIVµTvu¥!˜‰æ-+"TTê-=ù(™oŒÛÃ*!M@‹œàW~Ñ[ÖÑE€Ø¹³DMJS¿’ûÕšÍ!&Ðw¿ÚòSºÉé¶²z>£ßäëüïÕËúÿÐç‡øú³˜Ü¦×c+çÕUš´¦ÀïÀùðéj Фœ„!{\åý?ÿ|=ª¸¢¢—­Å̹¶*ø_õó5â×*ózñý/±9ã¯.RË;ÎèÙ‘‰ÙaU#¾û aÒèË»0L¾|°pïqý笅˜ŸÇÖF*gCǼl)Þˆg^tVr›§ã1ˆt™ÙÄ×î[ 01ùD,ð.Ï!Ù;·4AÂÒÿµp¶wH,OÒ¨O¾£Ëì:ÐuñÔÎ`¼îêã–jkÔÕŽÈS7­Õ1+Ô·ÅõǸ×w„zž¥ýÓ>¸©9s•Q„2O丹- B'ÄQ;®ók×Ååi„eÂ!¶žý®à''¤ÊÜíï)¥:!0$$0•.O#8óY|k†äÐ~Ìàã/I‡¼Ò0ø‚‚`UÏvK‰Þ”\ߌERJf´ÌÔ]½ºã©v¿‡"9$ª) wPÌÀ5¢Ëä§^ã¸S¿Â3$ÆšófÖ‰H˜Šv”Q½?ª;‡´êž0LÜ¢¼³ÎÈ‘˜Nsœ*ìç˜f¡Ø`j÷}çwCÕ]œ’ktfl«ô0paÇ^\¡¼?¹Ôäž—iÉÀ¨Gc€m…>ƒ•9=±Eä‰!"2DVD`ŠÀE‚‘@ÛÙïZ¯ ’™Ú]ƨFÄt¬P‘J…xÖ‘â!\‘B!d¢Õ˜wV¯MÆØïô(ìw,“M:(tÎ[œ<,cýnÎGOV¸nOG†X8Š$§%»N«¢(†±5ö9ã’¦ õ9$.‡çE­OÕÀŠ:ŠõY×w~•p$f—m`ò)˜bi2šQú —Vól#°Ôo#3 Á¬Œ¦L[MÂ$!)êU‹Ú¨ò&qÉ!!wèÙÖiÖF郋WÖdã^”¹dÿ¿~½{™ó½W'„4šñÐD,TÙdh•*Ã|- ‡‚ªO*-R›ÛKS ‰gë6òsy抇ŒTï…·}œÊºëv •R%©lF’{±‰EWqº<ã›'âìÇ5ãJà Ê|ºO|M!½¶võ¯ÚP•%½s 6bø2‡D& 1UA#¯¬HB§!d< Âç ³•ßEHè’*HÉ"Š›èƒ‰#¦ÏH‡ˆ…I$©$œ´uNÜËž ¸èÌT GZÖ:-…RÔ*µQc•F‚ËsP"‚Å&’4©¡Ä‹™ 4i ‘‚Y‡PÎÿK ÚðÆÓ‹B䫤®cÒ~;ß…=sâdgtSïµX[’µkoHËJ¬d7ðs¨4X¡C–è¶ÛÒ 5ŽÂr‡<Ü7¶–äD;]Galì¾9Ç‘WKˆy.twë¦ei¶ÞCCŸè°Ã,ÔU›ÖNõ”o‹™)à U ƒdCA™M!#RñÏ-\`Ðâ Êw6ÒRpUÝ!‚ ÔàƒÀ6*ÀŠ8{t¶l­Yž·£P>a‡4,á1`nÙ À4ÓeŽUjTb1UAŠˆ‹#¤•¥X€ˆdè&ÍhÐ"‚ ÀU‚Åï¹¢—•ÖhZ©aQ(P¢¨µ¢ ”¨j8ÉçÆKÙ$éÙÐÜŸ $©…ô¡q’ÂÊ…FÄ‘¤¤QˆôúÓ!¿.’ÙÏL±ß‡vPiF`¢y¹;3á"IʸRךȒäÁ&… ,šS¨•¢iÇhlj=¸]x <%oirâ9âš>~bzxšnxâÛÕ žØ€ð#ßß<ó¢ÇÙeƒQ‚ª‰QTd+DDDŒ Œ¨1 Á'gµ ÉiUƒTE`±L¼L'Ä´»ˆb¹@àDAê@á2º£8k¢] Xæ –Ž]DÊRs,TÃK£²à(<`o)H”ÙÉI…Њ1 ²Ú:Ö}› hI„ĘÁ×Y¹<·­ *^¦ÂOYÒ»%D t›OŒ`TѪGz+•¡µ¶–)<Ÿxqš]¶CCÍØà#&níÑC2r‰FœÑÁ~GÅg'Œ‚y ‘0ž`bašs0 E%Ì¦ËæÕÁ8NÆBìÕ£ e0E IL°±Ä4Í‚÷ODÉLJ¯ªé$ÆõQµRX†c žö&³ñ=Ìž»Íwù”N¨©·´ˆeº3)8¯j™#2RPE¦AªZ#–Vب‚ŒZ!'@8#̈:A/ô;nõx[>“ÆüŸºü<ÏŽ}Í—F·IåºMȳ>ë¹½ { !œÏ'CÁÀÆ#t¸Z7 êñŒÎ dqLëwU0#ÀŒîž3+’!9]À;$¼—f¢LCZ9Yè2ÌñÊ 0†š1'âêk$‘y‚…^Ÿ‹Šú[Ï"$&¡c¢E˜°9(YzÈ!ŒŠE‰àðaN¢£“­«„¡‘ů›.?e“áƒíÈØ+Â~É‚åé’Èx4ìVSî‡ÚŒ#¤uåñW’4¢€H¢£p¥óÖgºñ&Ð*é+OÚ_râK¡‡aå"%‘( ¾-¶P(¬!J“ ]ôŒ{ïÈvhËfMOtH÷Mm¶¢!Eº˜Å¹A‚ó€Ô]LÇØx°RG ¥Xª'žHù« SOVÊë£Ã〠ïdOm Bxås¨ {Yl®Ûï])¯höÝB’,I!2[¡4 äo$ÍŠZé ŸŒâÁ,„“ÈE]€„ŸG“ $¤£4çÈh°‹ ´ÆO‰¤&K%¤iîlô|:þr‰¾œHH#ÏP6î Ì9´©ÚAŒ„Œ‘W&Ým3=z¦ä¤ì¢hå[i––}³M+/? &ðwSKnh3s¨}ˆS^\äèžËðd¨²pÖI£VTTq bÀ… @”ŒÄb$Rèï`‡EX†˜=ÒJ‘¬±©W(…ZÁui´S€&AëD¤0ŽX#'Sr¢z2/"oú%* ^“„׫î©ÜÿLÿ:듼¦ä!kÌÆõ†Àyy¶M ]­Z>s(ݛٽöeñú`ç„XÿÚ)4Xª¿pˆCëÊ_^ÇO!OóaýÌÃåë̆Ö'Ш9±Éü^UŸ­úl§ºÏµiÕô¹‡Ôܹàðƒ’8·­™µ”ŸTKÂåBèúË_˜~pÛíý›Éöíܶx›m,Y)Ulùò $¯F"Âꃭl¥ÀL`¿àd»í¾ž†½¾®|ér€ä)lB²*ЌȄ¨d(Tó"­F#¥ü©p[Ji0LŽ8èCÍHû}5&’TmiH[#›-4SÑ!ámY0Ž©O=F‹•& 0–-Öá¹1"*÷Ï´ ‡»´ž§ˆh‰÷JJùŠ?·ìó므*Èvó 2,VtªM(Ñ© c)Z²5 kÈûü/¨Ä3 L A$É®#ž÷ 3¦s5Åø=.~ò€H'm»Íð³—à;šèNº¤,?>D,p5›?C–Uhì»0 €1™¢Šd"ÂW]kNÜ¡¿©R$§ôø¡€ÃÂ]ädò{-ô>ÏR-{‚ŒÏ_mû‘ËO°Q}¸–,۹ǥ† ‰š}cqeÞ÷6ñ²ÚàMhÑh§°˜VÉP«duÅîàTz ëpµ:I𠄨îÂÉ„€«`³É ù)<*A;§óàkBÓ»Õ[΂ÈÒõ³–PoR}µ²E²Kdybr÷á'÷Õ}1 ‡cˆjØÃ›8¤ÐÕ@5@ÔÙO‡åõQð•Gõ?éÄ—Ýßé¾Óì¯×ög+”ù€š¾Kkª0^9‹èàÌcˆÌF ,‚Îø±Â@×ôæ9ÙB Â9õ2=¥þ`Uú­&í Ìiï¾ðPþy¿ëÒ͸OQ¡,Ø®îÕ¿bQ?­Gí?qý0æ&à—†Pî›SÅ»ãÁ¨\Ò[¨wÅqŒTO&¸šÅwÎ-+‰Ž)§ U.šQÀﻤ3œnå×ÝÕ·á„YPî3ofÊ0¦&f[s6ò~}&âŸéÅ„tú¿Å—ÿØí™HÞµ½T¿1–øžö±‡Vm%bᆌö…7¢ÇØY´R­Bü¡gý¼Ú&fÙmÞŒ0¨øuˆŠbâéÇm´Ö‚Z9áW1Ûv[š4·çYI¬c¶°vKÖcß+&ŸÆþj†h7È^[‘|ãxW¢ª°²ßhBÓOö¦I‚qqÌå8`áë¸\r¾Þ2¢ŽÓIò?ûFc}üïýhxˆF±cW‰"Ëçk2oֆ⿪¡=Œ%ïX5¨›T¦Ž@ ¼à+ê°à*ÿQËL…©¢Ô×?-Ÿèr‡þ e9Á½‘L¾D§ CgÚÛñ.ó€õü;¼Ã–΢nðg\"ðÁ¢ÐŒ7´\"0”«¦!x¢×‡É5¸>Š!B( B0ƒAM!Œ±?'ÖÑËóô ƒ‡:cžgˆÂ0µQ*£¥ ÿª“6"D²ÒÈ–‚ˆ ((¶ÿkw6Ñ¢±ä pƒm’î'ڸȘ¤ õEû$¿já½Ûã©…+õeø~ϸÎ;¼zvꨄÛè¤ÇRC  â¢Þ4µ†¡§Ž9->›nµ¶q‡!8 t88ðÚ¼ ¦DûÖ;ÅØâP§ØÚ“"¤•UÒêDx÷J°·Ô(^¢ºþ‘’ß.ÿò6þß«ùÚ_Š¡s2"ߘ¦‘$\cý#Ò!S]rLÕ'¡ CxR…OßdýøŸ·Åoíó™z.|gUÿ-£b»)¿f®½FFŽ ™¿;l§“pýË3BfY â3¸ƒ.X™“301®¹×gpMƾÎFC?PÁÓ †5[Ž$²šxºÖEã+²@šA@ïâ‹£ö© HL‰º"/ÍŒHCƒì»ÝiR:jiû¦]÷&D®uÉàY³¨{½(ªÏIûœúæöÌ—s3FdÃFDÖj\.cg ¹l#΃¹;­ìuú_›­qº?›Ú¢ÍøÓzÚ!Ö¢eÜOÞ¿ù”Äu2Pü'§Aâ’º²Œ¢|LÁF`UQ~âuåCÔ%šÆ#>QÊ/D`ˆˆ†¿¤§k°EY]M¢Á®µ¢Z(a²ø’ˆ€gŒh™(­®­HXN•Ïz¸ŒªŠËgÊ|™o,n™K(¬¦ß€Ûš_›œt3Õ9Õy-åþTÚÖÁÝ-\É­bHZX*®_=ÝhU~UnÛ« ãôã¨eJÅñêWÎvyé|-¯Œ¥èíÎ.¦¡õÏþ‹ÑM§F™9uÀš ¿ÄÕòì<',"H"{ìœÎgï#6hcb)ª;ÀeÃ!n 5˜ëæLùùä4"¤ÿ†HäSñj£0¡æ`˜tM—;—‚™¨r{ëWæâA„Õ‡vs`&«í¸ú@‡t@ó_––ÚÖÅ,þÌóŸ  '¬ÜÏwÖb‘ßû®€e±:Ï*µlQ•Ê£G¿Õ °Ø± ¼)€ªY¸¥Må?½”CßEb<] óLŠgÛY9¡G ÀAæ«ëDW[ïÃýØçÐõ4Slñ 4 cЀˆˆr¢…l·…U‰½ï¤¶ÀÃÝBh$W‡žÎêCÀ³öÿºäuCÃÉêT ç_µÔ³l_Çû–„À˜Î ™¹©D»¡¥‰PSNgbTqjÓ¡±yÜøWÉ-æ¯æc†‹¹W~§Ã(±KˆG9 ¾„YÌÔu¢ˆÚiû±Ylµ_3¯Ë„ÿÌÉdèÍ C^º¿Ó›£Óê´ šüîUý;=œÿ³õøüêµÑ£S·mJƒ²;g†@°Xá„"½ÙßQîcï`QE 1;°K‡ñf¶£…O]Ùÿð`³Ô:g:äy…¯{ëû¤TEä ®¯¥žfik –ލmÓ£˜}àÒ/7ƒÞëç*vµþöÑ•E¸•ãøã¦j4T̶lüµàÆ…_ž@M@{ÛÏß`üÔèÐÆÃ”øÒq_lx°•jc7sRà²ö¢ qõ‚Xfáps+ `‚,ÀF¡¦D‰ B¥N—‹¬T ¿—pǺֱˆùÄ Ô“ËŸ‡ˆoBÍ}†¿e.­ÈïÛ¸ð\Ų^¶R3½ÜqjfíïH jä¯KØÉÈ×DÍli£½žl‹Uϱ➹›i´¿ùÒàor×׆©ÎO+ÀÃd´ÂçÍ¥ñÅùÕܘ»t߬ì'"ÝÇwÉ=l-U·1ÃqƒA@ñô“ÓÍZ|Ö¯W®dö›uúðxþ‘wÆèf[âúD@w; -Ë¢âï°çÎWIQÔˆß%L ‡+Übœ|ÑÌ›ÄÚZÊét;Ý·Úû“Ò"»á•áEÿƒ­²¬¸†i»dúH¸i·ÓèaŸ­'/뾄ÞH–Ì¿ïŽØÈ¦áÓÓ8µå ;vÚ¿ööåQj×¹ |=Fǵ¿Í*Ô~¡âuhósW|®1 s € ’g7li`¨žyp´¶›Š?ìg+Ád®óëÈåþ^—ñˆ¢ÿ¡´¿.ÇóV×ú$@MEv[†› #1<²[ÿpµÕýõm÷Ìêo -/7ÍŠZº"eÉê5Žâ]‹‡ksÀú9Ýþ1Ý+ì|"¢oj®âƒr»ÊÌpo 5JX,|ŸvþΔu°S[æ$|^+­]/‚ õ¹ÇivÜª×æGG ånÏ;U´He-Ûõnqàÿ™íìiû«ÏçVoâïø÷¾ÌÍÕWþÆãšëm?ÞŠ_€ZÄz`r#áî‘”Œ¡õú׸ϧéá]zRÑWŒg2­ºi´þuÅv¼áÛ¯Ve!³v®´re„FM°Ú7IèZíoi»_¹ôûx<Ïá9U[t¤iϬD̹âô]¡=:#B»òûöÚÅIw/v„®'©R¹ß~Éwf=ò×}¬Wã¯ræÏä"ÎѵýÑhêU“Jc,éðŽÏ90ĪYŒÛw åk|ªØó5|ºöm*ù³øÈM?Hÿ[–åØ0sãø‡·4("zÿµöP=Z†¸¯(æóêýê}õ‡b’4¼üÿxÀ_ŸzEÍ㜬æéS‘·Èû8VÔK¬È æbQ“qyhâfšÅ…î—Ô€þþ|ŸggÕ¬‚i·JùÊñôóÖ½ý—Ö쨺Á¯Ô~<¼²ó0.m&€ôeç³ € mΓ?YÚTÉÅËØ«¡¢ŠOñ;FnÛ¢÷éB ˜;kÍ:«”Ž 0Ïf*½^õô³«ÇÑð~Qy-=½ÒÏ~Ø]T*Õn¾«YÐCïMIý™þç-Sõ¶Oßò¡MêýÈ4Þ,ƒ<(Ö%Ó'ñ½;ñ²žäLÝL ïñcÕ\¼F7s™#¶÷ç×ï$uŽ“¯<ÎÁ^óåï=ʶn¸M{WŒë‹³·zÅ€úJ˜îk_«‡˜|ÑÓo;hY­U•f;sóZ.Ó ´æÍ|½Z™=¦—Õæ„‹j±cŠgû×ómwkêàô½ Ã+!  Öñ67q:»³òDæ'ùÉ6Û‹´ )Ùhïš+Nɇ´!G³Y™åª2ÅM×Gh-Þi§uš/Ý]Ûdç©ËºApÁȳyÖ¯íáö¡t´’W'»Æª«¡~påéö4M}Öww?ÌKÓXÌdò‹~Ûÿ˯쎲}2ó·g·T§:<Ê5bヺÈÝ"Z­|ž<ëljò·M¶÷_ïÎê:ß_Ëc`á…«ø<}õXÈè§ï,+,»g_ᑊnáWVj´Žk˜¿lý&–>£3ô}ËÖÁö±Î“(±Ð{Ï…!¸ ”èÊóñ¶NUgÄŸóÛÅ\5*n Þqò+µ~«pˆ5.;'Štq—gc3›YÌú.>´"\k>M?z¹¼åKW8íªÍêbš«?~>LöS¤›®ŽÉàÕ¹º?øˆõÃï©€Ç7à2Êíó/ý€Krs~ýÝSû³èó3Q›8;ç¡ý…ÿ]7àÛôtߪ »–ËŸ|­t*š5o~.6‘¦ŠÛµôCMà4VÜ?u;> Å£‘[}èsë¥ú“Ò½ÅÚ¾å¿z]MÅV0ÉÖ·—<­›Ê®Õgc_WÁÑÁÄ¥~ÓCíkWëzÓëhSR½$ŽÔ Óè5ƒªv²Ã…·§ÌÍf!5&\\%" ¶€ŸGètE¶ò³û“„„¾áÚäÕb–b5ͽüwŽ.íðúØ;’ÝÒº¡±ÅÌÄE"¯NVYæÚø·ØeÔØ©›YÊcñ•±¾~ë#‰àßo ã+ôC^Cñe–øQæV9ŽXN›vÆÁíÿÝŠÏF›ƒppð:y±~èë“L¶S=ð»¸o-ah°Ýý–y£Šóý•[´Žú ޼•?¿ñ“·¦œØæ2ZÐÛ׊šmóÍá»FÝ›œiãx•¼ìPt*ˆrËôûg«*P@ ±°ˆAOšðF¡ƒþv–e:pïÒ¾¬?óbÈ2‘Þ9ü¥‹î1Kj‘¾~æš®¥nÜÍϬ{ÎDYüai…b»åo.=éÛÏ–ÏÚrõ¼v}dÝ+U/e ×ÞÊQˆóØ8“ß)lçãaŸIyµy¬Eû¡iuB¾sFWÝW²Æh!#,U?C©¸‚ÔsH±µÂ¼a´0>6<–]G‘S»‘Éø%|yžRNuú{¿Öå¸Nó7ª²·ë:Èñât«œ·*†}ÌÚDîii;¼¶i}u`Ý{túy*Z2øþ#2~&««ö¿T4âmpsœ…=™Ý kFo•Å3¿¦&e'‘ÁˆÝƒ¦Z‹s‹Êzö}¸ç çÏcÉè,qòWþþÅÙ@þ¨ OVŠãžÊæXü·¾gûv«!³àr©ìWwùœ¾I]Öç›áiæS 5WÞÎש´ˆæèª}k÷+øùîœõ‰vx½–ÇûkvËðRî_ç‚G,‘–(¿)õÏzÌdÚ.:kÇ \% lì†"GOî]ç]ÔøGsÍÃØV4ͬvùÊ5í[íû8. Ê>ÕWÁ=s2þÿ+¿ÍXs´ öѰpj8xßÓçÎc ôE•±£Æp»ë«fÏ0 ¬É•I'>Ü¹Ö Á$°?¨Ë8‡3ø¦ÎôÝÕ rJöš–, fÅ÷3«Û(E†ë$Âb$ú’`!~Íùÿ{kÖ¸Õ_k–%V(s°ø‹7ÝO†JFu]ï ™nXÔ˜vcôø›öÏ+]åîü²ÓWÇ;kN%[ßkBëÎðo¤õòrK}VQvÄ@ Å×Ù³dýz̸!VëhîoŸ¦žÓï«êù¶`Œ³î†M2º68åµ²0\ˆÉOÖÍaÃ+D؇wÖI½ú¥®îèä•27]n›cW;úV®nä÷—“ìY\yâ~¯|,ÍEÿ-a·ðW¿øm9éÇ[üj–ß³#õ“ßO%ög<ú¬íëmzÇhunüÇŠ¥ìk‹2—Ÿ[Ñü ùŒv@c;xßÔ„#ÿR¿Ï¾ãrk+ßYx¼ÿ=\¦†ªÿÂÆÓ ÅŸ“ÿ.dw¹å¦?“ç²MÎ_³_¤`BqæÁmÏÐÄLi'ížsü›ÍÓ]üî¯I_§¼<~[3cgèÆPá²"‡3OçÞÂgÅè–Tfy%É«Çý!`³8!9™J骺œcn´ºÀ¥íï⿜žÜ63*Á ̸åQFø33³|lÜÓjé®åü\€á˜àf– ÎR±©×åífħÃLhýt¥È€ïo¶¦ô„ˆš^ü‚"8Ã(— QËwÓõvløw¼Þᙿ|ã˜d}p©d‡˜àjT§§báü'|}]vO ªñm âïUœ‹žòçÉûëòô˜Ê‹þjoM°ùÞpdØšèxZ‰J×ñ3Ä‘—Ëô0‡ßz¬Ï.Gñ<9ß››¦§¡p(]£cþYÇ _*šš*ôŸMÿVZ›rÅ­ÞË/&j@î°(*(ÿC!›šT¥ª/(SÌ7®fÞO·÷ŸÍ8çיže¦f·k)˜×VÏ|¼É2Š™þvv÷³Ï_²î ·7æ<¿Ÿ ,ÿ6»Y´ªÌpxOœßN%i²ELS2=—tgsˆúå)„^Øòšýðú.ÐåZÛ¼®Ê±ñ&L•èþ]ð¦Æ5SœÝƒŸ/PÙA©éÍ¿mýZGº^—¯¸óy™=Æ¢»bî5ÒnUnã—Öwš„We®Øó¡ýøKjtXL­?¢CsU÷²Ô[:ÕüüÒÕ(û1þ2\ÿ¥o¿åÄÑü:|?dÖ›Œ9Ù·ìÝ ê©¿~¿z~^ïÙ'nc\$‚\8¬Âw;ª©šÐÙOãfrZYFÍSΖ‚F‹×¹îG®‘MDD”¹xÎåÑ'Îê]Y÷ûf.J†kOkŸ;×èTU©Ûl¡‘®Þ¯O­Þ ñ›ÿžêëmáãHµÏÊSÿÊt³toZå\¯ÏÁçÑßÓ èmã) ð~~(¨Óýbªp™‡Mç—áÉ6W0òÒ®ùX‹°Ë÷ÝY>š•.»¨mñá”Tÿ1¼¾^©¯©©×ߨãëo0ÿ]Œ}EàþmNQà)zÀÈää6|Î_çüŽ}’I.xä·ÈuX€ÆçÜøíÚe}Ñ¿ÜjÚ([¹ÕgF•}uÛ\ÞôO¢Æ?ý–=]ôÂSƒà³aCðv¦ØfÑ!¤ñ\Ór÷Ùî,÷3#0"xt¶n×yë ¾~£‹Á¸°Àç¾”°«+Òlr`:†ëÖqYW(ÉÉö¹1/Í6­}‡VéZ4Cw;ÀQ+ï7 \§£é#g§NeU¬—{šZ,7B êû8o7Šëöþ¨éj$×üÀ„KËRß…Oã ˆvàz¬^æä4±òÐo?nBâû%ѯñóÑy& ›‡ª±Ê¡æy¸}…oµƒ¹gœû6*S⎓×Ó«#öo¡xM»©†ËÈ»x«<Û/{ÍãØøöURÊø~U‚Ë¥ÝjÀÕ¼ó:Ò¨ðÔ≫áèSZ#w~³%¾À,êž–‚ÝJp·º½ïfüöq×M%pQ_m×C䃴ÞmúÜ Õ‡õ®9ûßjñn‰'‹1Œ›éþ~›íJÏKY£ìJÿ&&«´×±F=¦ú šÊïËÜ‹NÐU/LÔYOï´Bze»ß¾®ÅïÖÑ3jð ÙL¿€o”r+{œNŸuŠ™k妙ãmYß­²eo³G_…»ð¹m¸¥üÞ¤•¬÷»ë|Dg+¯Ölá>T7ûßîÇ{î=vCljM`“‘ée°Îeny:~ïEç÷ƒ÷Z\ÿUµoœ~UêW4—Öu±S¬ëU㘽þ ìC¤Ëô·:ßöñ>õ…~èèþÍÙýÞ ã+¾y`:FÃ}ÀÜàc|ú\f l¯0ø›ýªšL¢Rú¿Ú¿ª±÷mz¶xÚ¸41˜6}'—–käTëQ¯ì»ˆZ»».žÚ‰2<Úý[lÔª)è—=ÝŸ´¸ÿ„¾Û'­º{1®3Î9ì/rÙ™Á+Rõå›[¢]Á²)Ù¿m¹¹Ç©Ž‰Ë¼ëÆ; ‡—ɱ‹†äyüUš¼ƒ '×[­×T[õýú-2‹I<± O¼ÐäW>«o91¯Ý¶lÃ$gõþi«ÌTû²4{­¨ÐiÜg>ÉÚ<:ÀÏs×w;˜Ÿ‚<2O7·O/©êFjãJ›õyôQ¼ySþοrÕ‘w$@«E¼LÚahvhc€©Óf­þ®¢»d#q{¨ÚñŒ5[(?ôZ®$•Õ.‹“ý¡¼3»!XÔ°¶?åî0ëfJ|o¯ÒD û·sü«/V«sꢠÒÔuÜûœ‘2Õš™†šZ†½ð÷¿­nnó…Âìíè#ZD?±ðr×¾÷9Öù¹¸gæg½Ñ×W;ÒÔÝásC¯”›õмÚÄÚ Ì>š"Õ—«Õªtú5m”ŸÛá:‡ÊOkù²<]¨Azêd~7Ö¯øó*k`ë;5žmg¹j÷ „RŸ©›âáá8g—qñGcmÓÔñîî¾X·Ý‘½o‰ýz ý†)ô7›á :§Ø³®àõtÏ_ïÌn>2ï™ëÅ|<=î‡ãõ°ïÞF?›yÝÒdq¼êŽ_k‹E«"æ—úvzk ˆí9ºE8¿VÞ–9^2ËõÀÜö¿—ûõW©‡í„³ë»Åøu3ÿŒß6s-3–äÏ›“¿Âžþ»xOÅÍoNXI0ųƒÚD/_QŒ§q9þÉÖÉ>Õë?‹›äæãîýz“Ê`ð]?ìëê¯hkn¼:&mWÒ·)äxŒÒ2"ít°N<î^7o»Æ÷{NYK– /+z|MÒ:òž ^üd°ªkŸðó.è6ø5m3/…¯g`x²ºÞ”¥Èî黇¦½áÐk°\Ztë.Ø8¾¢-±·]?‰hª¿¶¥û?œ æ$ýœëOÕQ{Ü•8ÜK8a?xÿÂÏgű¹maÔ®ç­Ð\Î.Âo^¤Ósà"®ûŽ<,F& uV÷¯:c3‘f°¨º"Ñ?±3¸Ø9à™€Sm''4J“€;_ê»WŸÇ—ó©^æ*+$òºn-üBËCÇzéwô¾þmæ+9Èì[k1EKjsY Ó“ÌH‡S{6°2‰£3ÌÜý”µìGÿ6WÌ—ç×Ä‘ Ã†TOÞ:hªîEÙË—KŸ½?J5øk2 S _‡Áïg¹u“žÔpêÆºµ5­dæC C‰ÌIO3Àæñmý£µœûŒ~VMEP’Ôæâ*ÊÜe¦lÍßÕ9+'=fC:¾¥á¬pë¼J½tM¾&»°æ¹H©‡î®²õzˆ ܬ}¾;÷ânë«üý}Ö<³q:ÙxË2Îñ÷‹|’JåíyyƒF GŸjÊ÷©ó%I|8䯆åóÝ]b:ú^ŽýƽF­"Òàtù·+÷×ëtƒ5²KèM®d`•Íý?š‰/ç³ôv¯Üï6óÜÐF«ç,™³Ûé_ÐÉ¡GøJ¿©æ¿0ÔîÜe?YûX}M\zþN3ºà· >þw¸‡@£_´×´ãSü4yÔu4ÙOE­›Ý˜æÇÌ5ë3ÿªIy9Üÿ‚-l'/ÓkYŠÜÇüWÞ8l ÿ¿¯ùé²yúúüúBH*±6­M¸²±ïŒ¾Ak‘[…¸Àf×¹¿“"Ü+Áÿ¢}¶ïQéjÞ÷üY^ëôðw8<_ŸÏ…Åû3óoÞý†µf·ïÆHËüƒ¤g„Qc;§’ïÁ-b·ÐÍu'øÎ™ÿ®¢ ,RîòúÂÀ§çoœ½/ºDÌz³³¿¬šÎ׿ÓN´¡ÿŽfÙBôÿ[HùîŸG!× Šé/÷“V3Ùÿ:‡?¿˜=< WNö÷vœ¾Ó Ñ©¢ˆh²¤}~Km¦Y·fé ÿ¶}š5×íô3'µíœ°o–]}—©‘ë¸û4©-· î¯W ôc{cv¯×Ò¤ô»hßpÞ{;¸D®š“7«‰“³€lºiÜt²´zŸ÷é«ÛYFsuº½ €lÝþ/mMU_y©Ý12<á¿ä}{îY³BÇýn„Á2ä© Äúü¯ öó‚lë-£Ö„èå™ý²¬s6m²ì½ËONNïˆàbôkܦŽ!ޱü×7AðsÃ(ômá…žë¶m«Ñ3SÙ2õÞ.÷Ž ;zÌs¦=¨cÃH¹ ƒ$Æ}®þç'˜‡×ÅÅ¥a»h9>6'H§+æ2­yvÁ•lôp.ÚÙ@ ƒïp àl3@î52bJdâÅëÐ× ž7 F;ÎFÞÀr1€ˆ"ÐçnZÎ9à;ÆžsÐ:½ÝâTA!C›WÝ÷IB!ñxtqzmôð–wÀcÏ€Gݾ>ÎÜç¼£Nã$*Š ª )"ïŸ7×Û íèøú‰é£yâJë*Bx3@ó{¸Úìhмx|ôèÛÕYpçμzÖ»<9¯BØ%·GéÝ 4u¥o—ÝàV=î¼È7''½•Þw®ôÎWn»xQ.öLHÓIhùÊ0Š 1uªvùª>m5ç‹×¤KŒ*5£L)7—¹,^•!®Øç^ow€ÝÛ,¯¡¢²Ú¨  —Î÷|wÂTr¦Úª@@Ù¥Qo–à2b öÎÆ›Ãï1Ø^µ»»¢)A¥i¨ $ŠzÀ>>úìSÛUwc»œo®wš”ë@¨XTÇßsQo+îðÛ\õ·w½»V•S`©;5ÌewÎá÷¾ª£(;‡Ç·Õ*•îúwËÚtÄ÷Ëêû€ñ€ òïMÝÛ èxÛ‚‚ùï¼ô:ç+xñ•Š €L˜L&˜& ‰&˜™™0Œš% #@4Àbb`ŒŒ˜ ¦&˜A£FSÐ 4É‘‚i4É€#L0`M4ÐÊzA) "!MÓM4L§¦Dô¦ôLFF©ùSÚeO'©å õ<ý ~…=¦ˆOIê{SLh5=OI=Mêšz›B~”õ©ê@¡ODõ š(hÐCÔ=OQê4À“IL˜€i£&ŠlÕ<'¥OÓM¢“OM©µOHÛL™ ¨÷ªi©§ähÒAúQúSi䉸Tý~Q¦§¨öJzŸ¥ÓA½‡Šd=AêiAêhÚLêD¤‚4˜d2hÈÐÓM †“Ldhj`ÐÑ¡0$ð§„jl&Ldi£‘¦ ™= ÈÄ("H@#@¥= M¦L4Ä4ÉšŒÑ¥6L£i“F†šžDòž£òžG¤i¤ô4Úš™2mi¦DÑ“Ñ16““F›Hm&ÔÈ4 >^0ƒÃ8l9sÁhÚxJÞ|¢éøÓEúQ÷.w·¬Ýdü¤æûÏ>‰6†_õŸ²Ÿ"xe+vPͪB©Õ ‰S°Œ…TF:s%1¦faü=ƒ?Åü‰ IˆfÝ1¢>ü§!>î!†sÙ]”·Jâ®*‰JZV¶µkUADUbRó31-¶­­IRjÐED,ªÖ ¤Ø~gõ½kôØüd¬ÿއÿg˜O “¨H~'ÛýµÒ¢Æ@ݪ|ˆjEuµÆhXÈå&Q"00zFž@ƒUYAG¸…z6á¶² ?Õ. \B€ `¡åy9i¿“’óŠƒPSäM)ðäýP_$O¤²¤úéÅQDøý™/:: ”q>U¿ ß|7ðDb+”VÆúW.7ÊÂBå•©!B VéËS)“õÔCLPÍ\ÊE®1Kr˜*ÅÄ•¡r•™[ 0X*À$-¡m)[)[+F¿Þ}=â ³``ˆÿ·}– T"ëÈ‚ãN>~ô¢éù“CRºX#ÑþJ+ÅÃEöp0GþÄM†ƒ­¢˜™«‰Ëa´Õ-¬u‚vP1DÓv][ì50>lOn(»å©Ôʽ¸áa¾G1Oû>M×îÕÊLŒ|èk³WúñZ?ÛK>ày5­f®ƒÙl´ùÞ^ºb‰[¼[{ý»JÑÌçý¿¹^¿aðR®bŸFÍ>(n’òYÌÐÍjéÉ~/³Ãe+‚‰õ8|j2ãcêÊÞ~Êû±Q–ˆp°Ú’µdWàißÑߪ•Pªþ7þI?•.ô¿’³'åÝU‰eÃÔcâu—‘oQrØê¦ ™IAhN®¡Ü{‡²&¤˜ˆ2 H„eë$NfeÕ¾,Ⱥœt¯Ð4vÙ”|]‚³ñ/¢qäUë÷vlœ¬ŸéÄ5Šâ‡M½øN?¾H-o+é>T·]øýÕþ9R}Î-¯/AÙµNä2!ì˜óç½f´kNGÙͺTÓìåYÆS[ÒlÕÌm¹™¼ÅÈÝW•5¤ÍSVUäÝ4yrº¸Ýê70µuš7­£6ã«­)^a(SC»‰M$pÃÀ&L¨Þnl[PÒöQöžòo ˜šHXJyÉYyöMÁ÷UV¡¦]æ^f®ª$ÞdV¥$iÍ Çê+D0¯Ýãgt.[ñ±Pè9„d8 û#^óñÊ7¶ç1tsÿVïÞÿáþ é¸@D$ûý›l¤1Êzýá±*¹;UûÛÿøtEýr yµì•C¨úTê¡i$Aÿª…B@dµÌjj1Þ·Sfgaiöðj>ÇKJòÌr’’¢ÞÕQPekôµ•…oÚª¤ã§ˆ‰J"~º·ºú_ãiüè~ÏjñiøøÞv^ޭʲˆ‘úŸÃ[ºAŽÅ›9½×¯ í£#×°dãÕ" "7ÄsužY—N’oÖ}®‹¯p%zPÈsUNšŸjsP·´ÄO“d®žÄzMµ2rëê}9}‡µyËÃ×;à{7îüïÞé$‚/H½Ï¬š›+†‘;oñoÕk¶vûÃRàœ?NÆ~YÁÃUg·©¡/å5Gúð6Ùö7ƒ¨Óí>-ÁrùÓ`›wRÞûâ1"§%ùyg½EúJ2ïžÇx¦õ`£ÿyµ=£¸wŸâ4#É*|åתx<Þ¹çä_gøáñ¿|${*§³“ü.7MÑÌï>¿â¤þ“íéè@:ŸâÂ!Æþ™W«`þk÷ý¯*èú¶5Êïvÿiø~WÕ§Y}Ÿ÷7Á]Œ;9¯uçî|æÕ+üo ûRÀîÖ$íñ}繇óS‹ƒ2¯yͺ·k Ò­ ª´ú£Ýúõqö(˜ú úRRšŠ·ÉëÖóט±"°äóøû.¯êu³J¤¬p|ú5Љ෵gÿv§ÿ~¿µó£"åú4"îõÈL(Hh0 ,<´!#g2" œ óЀk³qdXõõ ¸çø¯åÊì¼ou¹v6ÀƒåE<ˆ£ÔÅP´"‚gáHDÍ]_Ô*ÜHb‘(q­Ÿ1«y·ö"†EPks …ßBÜ'K”ÿ­Úæþçû2¹2€1ìñÓÿF‘ÞjÞÇ‘„˜ÿØ@Sî6þ[ KFT*Eâô8@1ROë»'Ï{…Ù™g=ËŸ¯ÊìiãJóY ÓE'5$ÚÞʪ mmÉbí¢¨ÿ‘‡®Q,9¤ÂJN"AÊ&Ý,S0BKñ²"ð#M„£RªÔw>i,AG0€Q¤¨ßFƒp*,Á£šE´‡VŒ1Îr±.š®B‚ä8˜'¨<÷‡P•ý(„B¢Á®z¶êwäÂ"a_OÛ—qxM¸Gãý÷¨ 9YwMQB3±¬â`Ã<£g«äøKÎV™„±D0K+ûäâåW£ÆbTkd?ìuÙðDªh¯¢ß«0L#j#ÿNˆ¢bézR'Nµ„SPÇiVm±š=τɋý+Nbš÷QPæ°PÓ¾ÝÕ¡¸SN~ù¾¯yD)ƒÌÀôVáËËŠ9ÃóV„ Ä7Õ{èÝÕ$¶ÙRØ2Ä$b{šx\ñ16ÕB“@JÔDEQ7uÙ¼rÐm߇Ñw @êÌ0@?%1¾›Foªï9ý“fàövx›&¯-™üßçû_¯ºîoÃûì Pð0@@Ée½û¨Š Ж¦…†×Ï¢e¹CàsÀuVŒñÅq¯ê=&)ã_æ3P¸ö‹»îEg"b¶y»+û£óÞý[ ú±ÚvÏ~2‚Ãc‰®Ã,éW)N ùm¢Yp¦íGåÐ0œˆ¯ö]TŸÅz¿æ©ªT¦ÍÅŒ`ºW,ÏŸòý#©ºÃ‹„Óí3‹ÿŸ°œó=ÝAQTiBµU%Rv´OvÅjŠçåæ2y™Åás= ã=jR±¥Ãúí„AÛrR±¥`>H<þ-_”¿³(nª$€B”E\±ºÚãW¶´f°—ìåÒà—M €À % ¨`€B„¥Wùq)‰ôú _|ž˜÷°/Ø–âE§RX=¥×?¾Á!º´·tÆ}ec†®Fá± Lšue$„ñ¾_vèì6"òA4ÞáÜÖ씡KæI(ˆ21?ìµþìÄÚ“o±ýL xÒ‹ Å©\SF"Ÿ¾(Mׯâ¥xO­"Tž]³x&^¦ÿ9tt”‡®«E{×ú4ê“ÄREùJŸîÇR3ØÏø(ÑÙ?J_–%ö ´=Î"Q£TTX-‰ý²œý^ šëžG­¢ ýÑÊÿ6Šg«0ƒ~“¯ÙI`åÇäEB Ôh|„rh+°RJÒQ9¨§<«öâuòå;Ö^çáê)~—p77#úñ>…tRÝŒ£1 ©"¨ ïß•øÑߟá‰xe†­*Ü‹G7o}_¹•IHËoÑSÝ>¹2­ô²F\èÍ\ªlO½p#FäΔÝ'DS³xž½ÜâÆ’x¢²âª0ý$Ig&«\VCÙå–¼‹9»¥­Í&ãµLµnÒòdòÌwÇ8„ž}úpNŸN™xG$Ë ÂP …2 Àð¦^‘­Úõ’q±YϯÔgƒÑÓA<-ÑÝ¢5ÕŸ´yF@:«D¬¤¹JO¯Ìb 6¼ p‰¬ŒÍ˜Òz>ý_ÎP¢—ïß6|î¶F@>?›ï8$u«¶/ø©†+N&ÖLäó6Ìê²t†ο݂.7hݯ6:ÄþbeÑ=O¸4@=kö_6]þŠ´žÃ¿8¯Ô­4Ã5ØËu›à(ûè‡üáìlÏ‚“ý^²žÖ¶œ_DZõ3 öLÙ/B§_ÒažµŠ‘f*$ðá̱kÔÕÈD@›k胯ôlà-å¬ãmeJÚ3º2·Aù0¬ÉQ )Ý'õE4WX‹þ¨†NÍôËw›Ý¨Ò`}kr¸ó2dÉ<©›…„›¶U\d††0Ä1—ž™¿´˜ØD_*‘Ÿèø­aV*À×+b¬,ÿ[2I-òyô„ñc+¾7Å5›oG¦Dµƒþ¡Ê¤o3ËÇàtËõv»pžT@|rsx¥ý2j_MzC¥rN :憾÷¶¼?tˆÊئM¦³ÙÛ¡_u·öboQžôªÙ ÇWTÊroùß²ƒÌ¯Ù)Í›@ŸŽÄ¼H|Ýü`WgY5”Ý÷&$†Ãѳ´%§™¹TlÒcrc h@j©‡¾¹°w­Œ”ve¹d‹ŒBób¹õ³5êz\_¦Ûxœ¯-¶öš¾îéA}_‹äÿ_þÿÞOÙì: ¤çš*ÌðŸ{ßÕ|˜ÓÇÁnsR0K,HštTn„Ï®8ÿ QqÂJ tÑLYIX“RÐA!wèC°¿âÔ„£)B4È]îWJÏù !›ôú…o7ݾߢn¬>Èû ~˜³%ÿ1hø&)>”l£¶r}ì<ŒwŒ¢Ð»¼’µN¥]p³ÄDÑ}0å»ñZ¼’_Ñ‘ã!× µë©ŠƒR:q‰0Þ¯óÿ-Y¾¶}/Ða×ß?‘™_Ú±dOAQ êi1E"‹ØpàSà…áÓ“Iÿ³#Ã@¼ô}¸¾¦'ŽMsiTôlÎPBwõ´Bì‰â[ª†FžÕ/óš•Ì‹ŽßÛr0Âg<ä§W t–a¥5UU*uTä#بxb4L¦´<—¡•„YM(2ë2•º6·b|÷·•ämÌoöntYRℎ]÷Çσ¨pÐZÔ$4¼6Àb<9þüËôá—©ëÒD7ºÄ  ÖG$SÄEOK4a:í¤u¢q*áÀï2Ûutäp ‡Î§@¶ð/ûìN3ºç¼íŸðnߊ y×|_H¨.îÕ‡;˜ÿµª¬~¥¶ØkEï"ÙÇÚpÕ}âо©óÍÕ}µPj†jÓ1éf‘ª·úMNgˆáÊ-1Jˆ=Kê•Bˈ:¾†ì¥To~n¾ ¸_Oª^†Ÿ¨¼ÒzYm–úîÅ(È’(°E"J‘H¤F( °¢ ª¬M¦h8€"•!ù=šÝÊ'áÃgÁúÝö+J þµÃêþã5®á8\?НÃJ²øÛ_‹ÓƘûÕͼ§”ÊSÏp¿­˜Øl_­ôÐDÖ* ¬lŸ.Bh¯Ñ$­èõ B¦¥|•ƒnÊ=Ÿ~–VC\¨¼ÜûŸ²…FHBÅ /‘Çi*Êò¸MuP\žWªÚ»i^UˆÄäììù dQb‚Äò=V”²ÁbȬ€B*H"ª#"'‹¡g+?3=EVißGL]Œ'·ŽrxZU³›éQS£-/1ÑbŽ!ÑR;Yç{Ù¨²ÎÇ»\0L÷H­}÷(…‚“|øì*aÜXÕØ½ª 7x·Ñx$=XB#`L`€¨Ô÷]گЀLH ‰Qb©‡V-b…d© •¬XB´DBFægJwxfë±Ñ÷’½YM ¿ÄyQc[‚––N&ÍŠµ¶nÉ›z¸¿~íý¥ô~ùþÎHfvCÀb’ @ <¬Šª™ „"ˆr:›H4#»—æöÜÊ;õ쮜—Ó·íoo[£!‡6ÄUNÅ„:Àšûk|L$ƒ –`&v¡P‰‚…ç™ BO`}&JÃÊÃBð–¯K&Øh^´¯ŸÁÃY©0ó+b‘$`D[ÀÆŒBÍÖ´®©5ÿ¾!ñ•w–pîÞ0“²aÝ}¶>îxp{¹xñçÛg¨ù™®ÊdbÆ"Å‹ $ëð÷õê»xÙîqÇ’_k²•«©Õ6+ DIUbí.ÚÌh­PÇ7=-×]«–’y´¤›ú,×ýþ>Ü3]Eé`ö,:‚ô‘¼Q-¨ÈìÌ òf“)ŸNJìNÑ™I–ÓPéÌ/lú&,æY–÷ ]«S-uW†{•‹·Š^ÁÎÅ‚Hù¡EQ+ÍΜoƒáµXD1€¢¢ùÑI ‘‘R¢\æ‰öëÝ”¥`غÄΕCrv¦Ü•Ò÷Ì–Õ17Œuîð!¥‘ßê A E lC¿^ \›ÛͰJÔ ˆEöU¦+¥™ ¼ ¥2æŸ^í¢Ò°’5Ë ØN®Ñ»ˆCaOLh…j—&!çÌ: Ú|–67aiU‘|èi °Œ`©­FõåõéV3#’Ì—%ŽL C6YfƒÐ!€ú|=e88Ìšˆ3Ö»Õ ½€[«9»¹f€ÃH.M(]³•›à´SXÅÛä@’<êá³VÛ‡A÷ÁÃíbÇ1œ·„™‘2’fÙûG"Þª¨¢ª±ÇXœ™5{©­*!¡¢‘4=WeuÊžÃü/PjUDScMAù^컋1äñváî9x-ˆmö´ “~:B ùfÖ§~I‘ím’»E¦‡”´N¦õ¢K¶ëepåÄ›³â^–h×A?AI=e¿õr±@'»”wkÙ¾íL/Ù~Œi<³nn7 À ñ*EAm+(*ÅŠZƒáç¶Üb¬­¡ ¹ß‚!¿VâÙ—;ç1¶à²›eNeùz©GP*ÿžd¦ïùøwe&-H\N¶1hà}ßêþwÕqÁð9È^λý+ûŒâ9Ÿañx\=¸üŸ•¡ˆÈäU/€òq3¬q‘†4PHHÐ7ÚíjvÜ*ÙÔtà÷ÝÚï}ü9Òîò@¥’eyz’9Œ&J•…á"ˆ`«Ž{O,4%2IrBgRÆ^¤yÚd^NA«j G4âÁÈV÷qP+ŠršëàäD~Â7ßei½Ðüß™üØñàÁ~òã÷ÙïTu¾>[?æ#B¤’ìrá‰1£šû,ï±d³zïnÆËeaÙ—,¸?Tìª m"ç ˆõ›1Î8Å,*qœ>Ë7ãk¶k!`±tÏÆ(c÷Š ®Å…˜rû>’Òx¨ë½G¨Ë-\™õyÞëÓåÖê5«Ç«k²èÚ 8fIf^eU2x|¢l1R™Ê­•KJ+·ÆRyE±±„¾Ef­Ë®‡(±s\;zûô¹Ýøœ:ˆ~dñž>÷ž kf´Õ WÚÉŸî)Ôø;÷€µoUóËn:©­O´­eÏ‚ƒ÷¿¿û‘xã~õ ™})qwM„$¥ZaxyØ Ôæ·,{FceËz‰‹äŒ`S›¸vmåk«M&E»—Q~K26JXŵ‚ˆ™Ê]TÐTß]%º©Xý };ârïÞsjhïç|•úÙ¬´Ðs éðHwL7q!ŽLºérꥨŠÉC•m¥6ífËYqá}~ÿ•ÇÞRêPé}=v™¡5­ö£·¾æíõÚÆï„f¡•´0=ܵ¦ÃENÓ‘êSéîxœòþË´/SvϹã:þ†àýª)³#O“õ8¡šÌÜoº'ú_—« ñ9øóW@Ž{ðÊTyF¹L' øk«’r. ¿ëÙòÕÃëüRÞô”Ìúº‡^<ÏÙSŒ¶òö€ÙãlôdDä»|H0ÃKP¿{1R/ôGÜ”‡Ë鵓÷ÁßAëÊc,£‹bÍ1ÿJ–’ß§þiOÄFæœýVîRì°Ó7Uù©Ér޲i»/_%WÑÂáìLðÿ¨ð|fS>ÿ:&œ‘»8È&•1»÷šÞº@Îa'åéÃcD^½<«öl™G^Üç¢ó43ØB$OÀýмX£¨ÅÊGRMxŽœÐ„ƒàG¶bÖÊ.Ù#è;#6“†³âŽós¥ô3%h®Êʾò~Å¢‰gÏúìÄl½ö‡Áú|“˜ýuÕ˜„¿©ÂEü9ÆÝ‚I öµ& õ&°ØS‚ÖyT»Ì’¤œ¬<=[^×CGb²¯0YPÎWI‰X—CeAYr~¤¨°á6Oè–Y"pø<zL„=1pŞо™Z "ù8Ûm/Ï vxs…´QÉX¥yÆÃÉÑš˜PòaÆá³hb} kHÒ²î¦>–å‰ï½‰æbñŸ4ùt˜jGI˜.¾Ó߇»àÜ9¹Ò'Œ#KŽ-ÜIµµ7"§àD$¥h¿öyB%•s¶Ð""Ε€Ÿ‹Š˜(ß^X㙀?(±FO»%g/ ÁdÓè­†&ìgñg†(—†myäA<ªœ?ì*Gì»oœž2‹ÛëæýŒÇtã’ CÔ9Í&ÿ¿èdïÙ䥇ÆÉõ¿ßø:Æ!÷äj{ï'rnˆŸA6E½.¦CÙNyÜŽk“¾ˆÃ«5ú§@±W°xFœ¸øw^ö«{굂6=’ib0ÙíB_»¨ÈîÕGi¯¼ÙTñ©Œ® íH—‚.,›ÂIÕ’zh…èÕ,^¸mŸžšíâÏÒÙ ké§­v}ö4˜7¦ˆÓÍ~âðW¹ùë*Ñ—X2G†}Dù{g³oW1+Q¯Ý|UîÒ‘àƒ1y…=Š ²³SÎÔVšÂñ‰è¿³R‡-g9߃ÊqÄÚñÆØ€â¼ìâ¯âPN[õdýÓúDêÈѳêÊÒ«± Þrl¿¼3û^]³éq—wÓ‘Ê8§maT!‹ˆÎ-³ZZ­JIÂàñšýç ãMÀŸfD)>‚$P“ð´ÏÏÝŸ\ᔌµc/­–æÐÐÁêM™$[’(÷Rê½ÂyÜ‘*ÊÁ©ý¨m¾UÕyøkÌÏ[éÆÇ߬³ÒÖ©$='òe¦q•C6 ÕÑ"¹ú&(Ú4¯»vÏ2?{¿åÁ6?ì¼¢Ëîªá¦6ü¿•Ï^zèGÉXˆù^icOT©÷gY}75 —0>„6M·¸aáüz!¨¾ñ\/±{«•Wz@ùh€ýxÚƒHŽ¢Pp">~üm'+¡„6i@÷ñM$OÌT¶Ö#Ø'ØËúZí[5‡zg–ލml°k‰g!‹ÒÏ ©>å #ãã. ºé¶°vL‚¢=Òc3z³ÂzgµLY`µI-[­rˆ%`î?q¹73çÐuZ!¡çÈD3 ňÍ~Ÿ2vXìßž Ö•GPß½,‘\Äɳäb&ÑØbž¬Ÿê¤ò<-©´þe³ø«þ¥.¨_rÐòÈÆ#©}£ Jm?´:'¡Õåw×FéÚVÇÂqTË'Ošâ‘iÂoy{ƒ4îšÌå5ü‰µÛÌ8sö(/°û]ü ~/îÿ´b¹{«_ùPq)ézš9˜£¿k±\Äý.½@2øtPýŸ¿káYO·ãˆÄ{Žäx ]/Ïü".Ô¼¸ ø×/±ì¾Éî×Ánf·¿txÈøD¯m'×oGÿ‚ ´6x fØÆ¤)^ÑV Ç!bÑáÑÂ-D5tÞ¼`Í{"Û—å%@rÙâL‘_ð³ßL_‰Q 7¸8Ð4¾øÃ{êiœÀ÷ÊG6¾ê'ØêÏ^ûÙBÞ¡‰ ÑãryÚ, ¼•}–´på«Þe°¼ÿJ¿ª}P©åÿÝh;<£õ¹ºÁj[²R·ÝÏ÷î½Ð4«‰EUdF}VVM¡ÚAÀðÕ¾ð¡ñœ¥ (˜êX=YåÎáD€<·»áåM¯ë|ÚãH^¸…b•¡`ånêÊ åñjõz’ôé¦BT_\¹] W}å…ßFê-øg4”¶=ˆ>‚ ß’ŒùåÕÄ1Vï°õ‰SйYÒÏoרrc'ßšn›S}ÜVóNÕÞ¹!RêGo$•’'Ù‹MWiÎëðµ¼'Ðè“;«†Oúý‘Œâ»¢•”uÃÇq…Uù0?ÿš{–0‘Õˆ3tÆá¨„VŠC}KSíˆXiÓÅ“$Z¢ ¼¹v|È‘™¥v‘Ä[Å’ícWÞ ðKl¿”v 8ü3ÁeŸAG6—Ô‚ÕñÓ•¿öT ýýŸr¡%’¾½`GV®µÏlG³wšÐûº‡†ý…íŠOëRž3 t=˜œi¡Hw'‡ª—wOÔ8IyÒô©|Ûyk˱¨'H†Ô¯,§Kö³É™ò(¼£p/ â½9FH”}ÄnLZ6G‹hRGf%˜ôOåÖ4Ö˜°@² è· Ñnj¥ÿ×óÙ“ ºLÏ0­oCŠ 8aÛ5ʺ:d÷_çD†¿0Xå]ïJW7€‘‹pö åã è¨(688·‰dæù¾Œʯ¿7S¬âÖÒGUŸ‚l:¾0ðŠPdõHC´9bâÁé¸úÕ’±]¢ K¤"ùÖs€—µõ´ž÷T76kL$…‰¡@Aï«"Mßñ™G¯È(ä6+-NÆD€Ó‹Ô´„ku”|©E3ÇÏrôòËj;X²½UÉ)+zá!ä·Y¢›R¡C}±yëšïRšŸCNæ»!¦ÇLßúˇŠ:¿s/œïtjœ™žÛáü<]®Ã´®âÌëB\},ö•þ5f$ïéùÕ½ÿ¿|FñêL(£âGÅoö†ÎËu¿2ƒ[꣮¤,$L»2»j§#Ê^¶öhùÑ”sIð^ðÙS^ëq xæ?÷ªÀTuþê1:•˜#Gl”îqÊgývÃ;·ÍÚXØó(sAf?åÅJÒçšõ¶Ç⊳èýÇ]s a„]t&tùUÉÉ‘=øq5èƒÒ4Y†Seˆëf_P_™HÞÀÿ+h’+jï6Z<M8@(½¤ZIhŸòk¦•›sÈ5¶²µ4œå¯Ãad|ç»HتÑðß/ñ¬¸›á4KåãqŒE|/¤÷×¢k9LÃ{òøeËP8vÔfš_&†Oó [6 ?ƒAsóàdý2‹·=K÷w)Š$Íý¾×ËÊŽ¼ê(€jð2€(q£»^ìz©†Pèi(FIá Ž¼¼]¸É<úbÍEC¾«2{P¨"ÖµÒvH§È×iu &šÁÜÐäô¹ ²m§1;ôMv­‹¸ívÙƒe†YŸ><ùü,Ãåð¥•$Cö×ú®*#-‡UšÄ¾´\÷¶“äMomLà¥vâî6³’OH~#‡/²†ºHvL’nqjÂÁ³ñ„¨sœ·CÖÔÀ×S[D­‚S¿,, á6›.ó3Kìá¡ZËHà âÅ9"„.0"w§´Ÿ G †ýfRv2ܬ’2ÀD¤ú¤û—&ÙZãVw•(˜^m¥t…ám¿F¸Ý'BuèÓ€ºDüáô+…å  ×1Òoز/›ç –vKørÄ»çƒ[vuIZqGl¨¡fœfKž3ɺU™¥"»ø´þfír$]1øðäîbÇé¯ô¹‚+AbçŒüô1ÇLþͦïáM#D‰n…ÆÜ•¯«Aó\tJ"r£(süO:R/ 4¾âN¿Å‚Lr¬-ßM¾Ë!‘“É0óZja¥Cs¢€Š)áŒåÙÆïý5Ç$®ßdFÇ|t"‡³ØøÛrÚ|2,}&‡>8LÎ ¦ÙZ¹—‘l4väÄõ3Šè½=¶v««–Ë€|;†”5ÔG¨¼-Ñ;¬£(;_ŠŸÚ9?ÓÔ4<.–Û;h³ÖFÏÖ1r­ù»7ï²íƒ Ôv­©·pÈ:E©šWÆŸ×*•:³ŒÄU›è¥FÈa’¹;tеJÜ ÿ/ªÊVظkAlu–îönŒžW9Ê[9_ ¼aíÎA~kûjM4ƒ'°·q-JÃ$S!&ž ®å¿šÄRúʽ*;¬“XûMÁÐÊ+ Ì ”ê+IAg­K”ÚÖ ó¢Ç*•-a"A ƒñV|{(¡_÷µ=  NÀ'ÏÒ“tè5ñ9¨±ÃøÕj¬(Ý “Ö\¾™ú”Ï€òC¼ÞZZH»×@ûuïru…ÝZƒ4Ó`”ÒkÖºöåF¿°.³_ rW“ø•+ŽÕŸfzúnˆñî ¤~q&^c²KÍrF7?o¡ú·ù¯5²+Z<µ×ÌÇU5îeô[ N×ñÝ÷žV—;úKDJUË(xBÏä{ ´ìVFźmÚj“~̺šÅ{° Ö…?]¢$€¨ôîn¢Z…è«h|bN‰¢ð4š²<(ó]4ÀÆþìzƒ/—¯:51¡ëÇÕØbaGro!aü¥¬´¿…­j8¢}”oXÞÞ—×ÕL¦~EM")Ó¾ÊäÖ'“Å-$uÜäÎÿ2~aµý^(D’”|á'ÇE)`ºƒË“vaLû<…ilEÏj𘬛q³éó*Åö>TËçiß!2òA?ó²ü¼™vìDǧá²SçR”Ec¬ÒÉŠ.3ÍþÿTEùü„9¦ÇUÚÐÊNû—‰îwnÙ 7#ó¨j§1›4C^½™ZŸÃáßÙz5•ì«*åFÉÝŠ.ihpKÐ\‚Ú€ó8›4'É‘påŒoý‰c:r5yûª,š“´¬Gí9ÿˆ$žN%’Ó›ÐT-Zß™ݪçÌR Þ3£i…zÐfòÃsÖÔ}TQ|8Uýí¿®]ØA„ÆéhWeP²±vË.@QZ¿í lÉ}®µ‚ÇqˆDŸb!’ƒÙŒ3Ä'%Ý•ÁMòØ(Júåa•æ•ú¾ý“lqÎ8ýóìµä%¸A>6,‚¬U“ïãÒ”Ê×t…Qà4‹r‰ þ%‘üí*ˆè*zYZçêñ.g;õY\ûw‘ì3é 6t=ʉª^½‚Ç\aÔüò{ôãÂ~€2¡ïœ¤+•’`q;6ÅÍú½ÅXã¨FºÂž²]ч«ß fä¶ñ5tì„ìÆ…b¨½>ÍGûyü j0Á¯blHÀ)WäG¢Ú-‚„ôaasËuí‘I/*o‡½M@û}@Šý Û¤¼™pÐ7nþÛk ©°b¹iœ©÷G¥Ä°°²øHrp[zÍJá¹!r½?@?¿†-h0—Ï]¹éämŒäO]×:öwìÙ)¯÷âôÖ^CÔ€8ÿ´¾®c“• Õ_wò¶„ô–¤]Çlb>ý[¨±[ÓãÿO—[°¯¶ëÜ–ÿ³ð\¿u§÷xϯóý™ŸÓ§' æ¹G‰ˆ"šiS\ôwÔ¼ìÙ£)J§ï™¬Ûk^Y‰ø”bD¶£¤‹RD‚pJ›zÂïÛGÚ½¶@ø§«„(k²ÇÛµ÷¸ýÿh¸îtÚ¦µ8Ê\»¾G!¶ë9ãU¢¾Š‘qñ{èÚ‰û»'rܪfK'’I3P¸Þ)Ùô´â;›eE¥ƒ'¶ã4(0MyØJ€î?‚ˆÐBÇcY* Ú °íÿÁØ:Ïâ‚.À󃂈/g«ÒÞ¡ÊlÂg °XAô }UÛ¯—:FBØÃ«Å€'>'ÙiDšæabÄQ‚“áÙ(ÕíÉÄL7\{n0TÀa¹œ­½ {j ÛÒ×.R_P8±ƒ&t¥íbÂ{Ö¹bq_âùÓ&”ÂÿØÒ}h˜‘Uã/!ýº8µ»j6?OM6ýÒXË×n]¤O÷µ™-^Ë}Ÿ»Ü~ùÔòkÏÄBɇ45….V8ÕïVž žÛÅ·Ôài¾ÅÏÓw‚€¼Š ²ö SRÔ!Èn))ý$m=¾Â€¯Q’ÜwYÖ'ù l¸–Ql&#¤uÅ»š• l?òѾ¡á½¬ªé]èÚµFÑ)0Yµ,tÜ´lË-ù‡XOÏÜíTþ÷)Jñ çôþ±ÿ×ÿ­ó鎙š¡/í~¡›âº‰_gĤЦñ§–Òj·5Z€”‘RÚÓÈ;¸Îî eÌU"„Ø­xÃZjÊÍi£ÅŸ+{íôúY(À'^:Þ|\LôqÏ;ÚõªU™uey3åûüµeÛÊßV›nûŽ;´ÂN³‘KJKºD¡ubÛK†üBßM<{©Sö›Ce +„v‡W"]€Aͤåyñ¶J:ˆÀ´Ë·ÔÀÛÅÿ~[F-|WÛÿ‹æ4gßù¯…ÚÛæÐ^sç»Å8:@þ@?bôg‚v¦½Ôwͳ¡!+ÇŠq0€¾Â{U€µÏÌæ†z03<”e /B‚Ô@{9ÎVM37Y VÎ €-ZM¡p´TöÔ¤èL%µÝu®Ýt?Û‚a‡aô?È¢;ÖAé)E¬ ÙDEKJVÈUX1Šù¿“ðPDÀ^Ì}—P62>/œõ³G=i—t‡‡3 y==þÏfýó±!ÔÙ $m“Ý(SPHB3³\¬0‹[tUn·«¯$wã™'—Ï“!Æ1ß›¼ÝA,PRáT/ÉÑá­A" ‹0©Pí|$&M×âZ·áá5¹éñ¼kÿ;ðÊB7Gæ/éÛtO?Žûf+Šan†âá5nã:å÷›€j¼¦L4¿K‚0 ›ñï>¡ÐøùÒ‰Èú÷4iržµœ KÐ"Š’_ë lüý¤–1ÎͶ[’i“äCEÊûŠÊøLØ!…˜rî½µ(.?– ¶™–¥Y–­0?«ôÔ¶‰·ðc4ð$)–ÿÞÉ‘~·XBUþâÙš NS½ë×Y·l”MSWèhû/WއɇÉem•¿Qö¿PÃf€É>ÂBÕ¨zÓx}‘€˜ñ݈øM¤9œÂ¢£ ªŠŠ*«Î/[³ýÍ©¬Ã´É¬i«Ùè,‹E÷èì$ÊŒ²+«IS­ívÎŒœNâ—Z‰Ç¿ˆvdØL«·Ä‘³jºsT:ËJêe}/ãqW}ôÿG¾U˜ÝÈötªJè{ÌðÕŽœžnf¿Xž‰¹Aaî $$1`E@Tc#€‚ŒEFŠ #T±V*ÄX1 H gêôežÖÛëa¨ÒöÆy_Úqƒ#ð}ÚŸÂ8©­iÂ9F|Ô&—øôµåeÓ¾9S—‘‰‡ÇÇã’‹çZ¥ ãÍ}rwHêÓH‘¸ßµˆ£î %XÐÜèvg*[‰«˜f* wnfc­´ÏÔ±àãÇ<#®‹†J*¥¬%€‰Ì­cç/r–ò[$’ÃMŸai©ªŽÛg¡ÔkIJ‚×A~¢(.‚‚ä ºµLó«Ð˜KrI²BñÉf-‚Þlƒ¥cCe$6| (*¬Xauw \‹¯6SÁ'›^:Õr¤ÓfÞzU®žß&ÚdjÄ>^²ÿc\Ž'°®–ÅÈ}ck=ÕkËá=èá w›‹™§3xËÏÿ-³íA›epA”ÑŽòF0®f<ª?}Š51Üβj´¬jƒ?X‹r»XIfr¶³[¼¿J“l°ì ØæðpjËúâL½¼åº&ŽVfºØ>Ù³™Ÿ[çfïëÅ•”¶e2.jÍU×\SJ¶¡‡ _|ÚP¤Xä( žR¶;üó»BþÛŒ›Ks>&E¸1z3ÕhyI}U4QPb¾™†o«8nþÞ3GÈÏÁÞc^5økP¢šgl0|q\ÙüÜÕEg S]ªI$Ëzˆ!ñœEá˜sšùô‘0IPõ¦AÅ «ÏF>xÝ=nÝŽ¾|‘òzô¸=圇ÆÃü±Aj0Ù oaº:ˆ´rLdDIó6D Eæn³>œ(]‘mKjpÐå²^xJ\Ê™²\¢þ<–¨AG‰¤— ‘A ¢”zóå«m·´ÌÌÌÌek S9!—330ÌËVÛmD[o­ …‡«ßÖ‚Á(/]šÂ‚ψ_ñ‘ª™²í#pÜ3_Õs²Ì!uH)I–‡áhåÊL9…\Ä1Ô«}ä„`´q•åBAtª€¹Ê0³£¸«ãÆŠ¿P_˜U@åý-u¼ÃÄc­é}Ùþ=ð»=­^6ꈑп;ÉÅ f›RàµRï}Wùxf{¿-9'óúü†ÕAfθIÃ:-iMÙðYå="r ‡°ÊükN¯aÙ½íß[ž‹²WB=Apµþ+{ûωÍÕÄö¶µŽCog?µP]½nF]¢€yÀª¡òñâöy)ç·âîÎA2‚ÃI¬§¼âû ½Êf­U 5®»h»k};W£¯¿3søî¬§«]B®Ø«î^k‘Éå׋3ï½þÍ>^ ½-a…¾uoCal”S 2=-c¨ÓŒvãšñÊΫÂpÛœ¥áxae¤D4,õ&×YÁpš9¶“YÓÏînÕö\da>Òì~}>Cë‹€_š>·|Kþ('|ädE­%Æ™ÔGZНÀ¢nëò;ºê1¹pê±#Çn#5e®?s?ãøÒ¿¯Cø4¼÷ŸpcÇG}^[Ç“§ªUåÆpåO¬ó%¦>¹À{Ò§áàHZ€…ÍAÎß±ú)¸†të²./®ä¾>ªtmôên¥ôu¢ šwBÁ`ÇUª_¡!5B…‘n­E–9À°Gç]‘lìì}NïÌ(;Óþ>AãGƒþæÕ‘»¼ªêÊä„£N&›¯Zï’:™™V{,¡Í“_ÓÄ{9epúõ_«W‚ðš§¥çój3³&ý¼ºBžäâæQ$^9g}jU6¥Ê"¸ \ËÂŽY7OàïbˆL@]…¦4ñbîÞ5o 8)”Z#KäšWQÐà{ÉkªKÃK˪ý÷íªºúȶ>ðt? ÙºðÕOÓ‘N3)¢DXÃÍÆ3(„¥DèË ôq †l¿Nn" œß-(6ñÎSÃ|5Þ*Øß…¨ú??}ºØÆÄ:ÈnÒ†úÒ'Ûl’=ÍGzJeòWåxƒõëò#m8â”5vlVPÅ¥QpæÂÙD¸°W\ƒM%ÈܦR\û±®8®_G½^¾îwƒâ\Mu‰Û–Ãú£Ë0">aùM) ’£õTœ²ì‚Û0ýµê‹‰ylß[XH´Sä§ÆS;0ÜO¾‘¼¯]b1Þ°ŸM!2xä Üw•àüˆ÷=aíQõ@d½BjhqB•öÞUÔ_Er:ŽSvý{äNÙ”Ý=À ³r ñæø¦û˪q1“2 NóMÒÎ¥›ÒoœÄ÷´—*OoÉ®íõ(.#’ì`ÔNŒ0‚‹Ñô–Ç0¬Œ]"<òÈöI\©ÍFil;¥HB$!%±¦½k¨-gü]c»ÏôÜ,ëpX“k1µ4W²^Ää*xarAhÂΆÐe1†Ã_»ÏzU4‰U.EÙŠÅ6Y:Ìo hg¤)4«q²[NÒ¹#lÝŽü’5øÂHÆ>ºÂa] Ui‹P¼ &5N‚dzþ Ѧ¬ ÍGÝUtÄ/ËoeÇch Õ’R²(EUpß±¼5í°îï¿užCïI÷¿(àœ®È˜ø1TSjµ 7ú¿„Ý~>¹Ÿ½££èxïÛÜŸîUÇn§?¢ÐAñ=üqæ)QÛ¶û”ÏÙÝÓÚ;ë’©üڇ؇Ÿ]?ñ|üW\â8ð@™@wuåäBו¬ZÆYŒ~ò|¢Ò¸{6ÿ\6êwA a PÓºÍÂ(à¹a‰_)éSeÛ¯—`ñ³ç¨ù™`DÚo«Œ#Èï'öPÐ@FrØÙßÙ¹®¸XIK2âu…®¶Gp!|ADADüs¯¨yz½Þ{Ø:ÉãO3<ÚR¯qçç™™™ sZUg"à]^eb¹ Åë’¾Äu§ê¯mlQ vçU{0^B%§^9áÏE@VËÃËÅ ÆD²X]¯]O± õ{ùò³“¶ì¸÷æ5ï'ǧò@«çÐrm2å&¤¬k°u©b€é-²› m$¶mÛ¸ýn·_0–jD@DN¼°=½Öã¯Z·‚¢µ K‚¤²áŽ‘”’Ñ)V)‚ŠtñÞ ëJ*6‰UëMÁÈgK®±rlwed¸bšåsnØÀã[;Ü©#Ç;ÔjC5S…®E†U8{iV{Ñ0+nÌNçÂÕñeróX4씊R£Ë¡æ¸™1Ňfûýs=Ú¤æˆ:¢ôD4 ïê{xƒM7³†u~õ9õD._$˜¤~¿ºÇ¹Ç?#<lj X¹Ù‚f}‹ˆå½³§AÍÅþ¿àxOw~?7Ԍ˴²ÌŠ9&U-³-¨†÷L† J&7˜š;ærÍÚÆ.)TÛý‚ú‘´â!ç¹›Vÿ±¦+N6~uºfHm¦æ‰å/´Mçî_:—¦^qÕ´ã éâµ½èöø¨.W„==vßÍ6žÓÙÚÖ™ÞsôóÇÀêÿQß–Ù©ãšZ¼ä¨ÑNt#èßIEi|.b æ?ŽîYù|ÛœŒkÖø_ñ€ÕœíÌ ôw ƒrˆg·lÎJã‘ì¹ó·e xø)¥ñÛ6”«©/A‘e±!~î±Ôlñ–˜µ9“Þ•ãaqጷ`ü ª¦1`«Šö²þ5+[&qAlÛ*dQ í‚ükºÑkbÞ@•nšå˜£‚êCÑsªt”‰„’™®XF\GiÔx_vϧÝrš©ú€€“ÉÃó ;Á=VC/>ܔķ`Vk8,8Xp™/ê F=ù‘×S^+™°pðÕÐê¬q”\ÈR¸7Tã}Ê‚øC¿ 2·T ìûWk{-~I.ª;0RÊè^YÛ Ïx«¤ gŠ´hfIÂUz¾„ìç!vyM2¢‹`UB©¬üŒßn×=ìàü§nñXÍj,r¿¬þ‹(”ÁÙ}4dUÕŒç Ún{î—U5D Ũ-ÌÛ ³…ˆQe.,Ë—¦ÆF-TdrBKî¡Ïˆ¾iHÑ$¸xªcžUi[*Vt.:Æ{ä™<Î~š}¸Í#àøŒÖ“²î9/Öé®,—hŸà=Ê3O:0ʪõ¼·-@®«1/&~~ïm$,\QÎ'K i¾/ zÛíJúÐÛVƒãw[aîúÔ=î5er’¸ñ¹Ëkûr>³íx¥[Çä•ñ2ñ5¦M©%æ[”þÎW¾ãÌî$Úµ ·‹~.x^cöúbV¼£¦ ©^¾aÞmH8Ø4‚mWr¦ÄXÍU›Krv‹#9øeqæÖ$ªJ.ÕS‚ËÊ|—$}FsèvQ%µ@U…cK·q„T)€Êcdk¤jœ<,å²5›5Y…ƒ5Ò=ˆÝ~ u^T‹¦}•¶& Óg[lˆ‰‘Qô˜…ÊŒŒ)‚J$BíÝ á¤÷HÏFvd…Å–Ñ=ISµVa]Ö*,Mˆmªá—7hüÙæÈ/91^³e=ÇlëhÁ£U §%= …Zæ¥ [·& uó¨[Ÿ ¨á /¤$’ædÅP-9, ŽI3sÚƒž§3’˜×i_Ö®ëBLûÛW:š1aw%¶¿=1—.[Ú9*yj¹LyÅ+;$Ó­l™7y²C“”¥ù'mí‹yÓ×›:L0­5ší°MoÌS$¹TÑ`Õ­êì.l#:±iÚ·²ÎWÆÑ.¶gí){@”3E¬sq6X†zÇìLô[9£)µdn°.鸌ŒºQ~ÖÝ»{žšöˆ*,†¿¯&Õ•R“Zí«ž©ç§e\&1*"ªø¶©5 ì—%vÙdÛïdxž×”õן¸¢é•f|§5 Ç>ekå…)Qni]šk^Ⱦï‘J%´T®À¦òN¿<<üîdM‡—‘Éâjí¬/L¨n%‘UUNrÍæÑœÛR騠Ы8®}ÌòŲ¦œ‚Þêˆ XùŽ5/ž-便•ÊG‘:¹§U–ÆkG,_’èÓ®c,%‰¸xõ1M‚æÓ$dºÈÓÅ‹¦†7’ žÌ¥wÞ=âN½’›µ¨·Î™k.¶ÑÈÒÜ`qjRࢅ3>U.%§Zežá²ÖçÚ¥› ëˆÊ´-´B» ÅÆY`c]bÏ~Í›#­Äª èPø9R6Öð[.(ÊŠŒÃ*9ÔQ—b‚òâoÇUƒ7“ãSA0¶¯.ßšß§±Í©­YK4ᘟ &tŽÅâ,)mIE’ž5Öå4¢ˆƒ],…– ŒPŠ2Õ$Á†%Ì|$lÎÃØÁjúJÐÒˆà¡åÝ è•Ž ‡]rfLWÁ=ØÊ6Df‰BÝž6Åøóù_rIöv%qÕyÕþèn5uíØ÷ïNû“ÛéPxt¢FUq¶­‰ç€Åܶsò1ŽB‹–s*GªkdÅ FÙ³ÝÎ¸Š¨«!6n'T£¨5I]‹Óá""ußN~?ŸLW?ØÛ€ùùˆŸ(ß'ž/  t$ºí.Ù'&uR¦ǃÌ~þ§ŽüÆIf2«AU BF¦Qs®²J^4öÚÕÛ3½´mßyíÈÇèSIÏt7žÃ$ÒLHã|I‚tš]÷»åÉÕìiµâÏ2 NðØ’ò šÐŸÅ¹JE{eÑ{éMIi^ªŒ‘y&ÂÄ,¦%Ó»bZ~j+__×öÍøÜ~ûÚzz´!¹_”<öÕUä9—z>籑ï5Öœžó6ñP\2®—"sÕ[iUA+>û^Jc×ÊüÔ[ß.϶sÇQ ¸â§=• 7ÇQlO#~4{(”È»T\: ÙÏœ?‡dO#ÜjAdlR8/¯{ÓÄ…¥/DK|ã T–·ghÁÓÕ*^zëÞ‰ìçã\·Ž!.êüjÄÞVM¾©j ‹c¤6 êյ޼ŰE PWIÇGc=ÖäÄÊõþ`Ñ¢¢\âè!Œ_ö}°ãK¿Kº•ÅŠYã̺éæcD÷‰òïSê Z¸×G9/·ÒfkÈÝ'×àz_ªüE³6¢hãö7ì-,xêkú²Û Toñõ£¹É «Ì•ÆóûÒÿˆ~|f»udI0WNÕÍüµõý9I!Ík¾­â ökaÜøæ9õz@b·8iS:è!œnm±æµÃp¥óêI%×Omt±E^±BNg‚¢Ú«SÕR¼Œ „g³.RÉ£dŠ”%D¹PEÒdh.¾Ãã3°Xsi‹Ègc–x«Mö2ì, ½’•U˜í¶~´+ëžqäGÍÏ¢bñ¼ÁÔ>ßÁGŸµxb¶Àâ¶Z×Mp²Ùeœ0B  J䏿Áa‹Xk%å÷ÓÓ¶àÌg_\}¾í á“Çã_G¨8áµòÉoPá>;‹ªIUONÒÞË/?(ÖfÛ&¼6Éò`f§)æÅs§¿£Z´«Lñ5+-ËkÆèa•PC0³«ÐÎ6"6žž²kgHcd,öf8ãl™¶—Ì–²šl¦«(UšR4éfh.ø˜$ñ™T– çÛžu}Í Ji0Ó:® 6ÊoHÆ®Ë$à'DºáEW9ÃÙ“¤'ÒÁ!v8t¥Íß"hêWT4 âô­cÖ(¦Qk-ú›»qY ön8U•)Ę/Û±“+IݽúƒgWÞØ„’>XÇtÂrgNôK&é 9DÒž>Ö‹QYHY½SäÍÊ¥ÓæŒfë.O²ƒK¡¯©«j2ï–ƒB4[¹• 2QVVT´¦ ï?%C8q7…UÇžU"ÄË!z¸Õ.mX¥.ÚLü…ãbáó`૎f{³/ƒ’-‘¶®~ÂG¤Ã…°º¸ ýs6)ïgçH ¢©`¦;¨ÂÕ ég*2£dˆeÎ? t­è‰¦HEƒ6ƒB“ÁZ(RBóó%ª„Kó «=2ÌLù”ÆEÖâÄ)˜Ìûô‹i« b[øa1@ò›†*)#ÅÓ~™;G+à×Þúê¼£pòÂùeÔa[µÍ¡fÁ4X.ÁV¶çpz-šÈ\äH©1jÂaT•†|ý:¶_ðøÜ³6B¢TÜÆ'~ÿkŸT? ù¯5öûZ*ú€Äµëê{©]î#;ü£f2{zm32ãÖ­ŒÜž¹Fž]ž~/ XQsÁGqÇ!‡bk9F’)ÊY׉0&³$d´d|$mGˆ«L´Ô±w\ìëöàè˜T&s‹‚2‚VVàM[µI ‰r(ªŽb•в™k‡am졉ôÖ…³¡º«gbɰÃVÖîÃRœE1!nÈ+…VÈb@Í´Ú 4æb¤ÕÖl.xâ[ 2ݲS»—£¼(ñgk]0.Kì Äªä©†,¬4.>ª+³’XÀ„® ¦M:u•U¡'㔩G]N,ïPúÕDÈr ÍÉäÑ>ö_ë}ZìS{/¦O3á…®¤PÄ ÍÄU£Æèñ›ü¿hÕ;ÂHGða¡&®³¢¾i»w¾{uÚßxv½"hÜÂUNkß[ï¬Á?1‘¸;¦·ÎšNêkzW~ŒÎµ¦‹ê \ÅÔI|¾§“Á“­`—ÑÌuZÕ~–âºùn5ú9–jÚëÊ}Uv›~Òø:ú“4#& ©÷ψ¬<ÈdEQÂ÷G¹îóƒõ·kŠ#JéÜ«Ž`|IØòÊô'Ÿsí¸ĺŽ8>­ñã¢]Û}×y¿Í‡ºí$ý½þä’vLtés©ù?-aµú3ò§ã7ßžù”ü|djHŽž1|‡ñÒ@_Ò|gVg~¹âN]ÇZS³åëž=gL¹J¶”ƒî&¾ìt·Öˆ|ÛêHï1ôMy&Í/]øÎÛŸÅÓúI¼UG)ñÞ|o’¹wÝ{q§ªÜiû‡èka¦fk¸¯<{ê9´Îy£…í—Ÿt/ÇËo'žyÛÁ­ã}ø!¿/¦…[03z¯¿Á(·¿Mû¶–3œÃÙÇJ©¸P‘(ÿió(®Ñpl}L‘Š`~~©>¼Vç{0.háSzT\Ä;Cg3$­-uC<¼¹‘‡¹‹;Tã‰Fiu– ÂÂ[DG”Ö£óYÑ4´dº×\Òײw1³£²â·-¹²þãñNty}#bû|Ÿ‹·_9DðÃrŒÅ¤Þ£‚ƒÛÎŽy÷Â8 ähµ.ÚTÕÏ]«¦Jg¼-/P—/`ˆJú¨¼öjà1j/6g--$ÖwB[;açÍYú½PÖoÏyÂUßîY ×èkxž+7_›ÑüZއWóûÞ£Ymó}­“Ómæé¿ÉÙñµËa&©SøúK|hc‡½F¬°,‡-…‘£ OºÐ¢/³8J &°|™¦y\%È(2!íϧЛéX-3Œ¯¨ü ¢Ç·ë0mˆâÅ(ò¡d_lM_nÃÛgšŒñŽ£Z_Iæ9éÓtãš_Ìÿ®[ßFà~± »ƒðü2ÎZX®­Ü𺠴€ 7iqù÷os .ARï2bTq++=d_í2¨ Øœ:ãs¡=ãá?¥±¢P”§§bËú$L¿ [†ÑÃ/MÑïKÞ»ãÁôãëf¶ÙäBŽÒi —R‡;÷‹e%â1±EÑ<£‘ü’¿æðçïz™¥ÓìAØí¦¾åQ¹y«§ìOLqÉL×YïÏ‹ûu5P]P€ÁúÞ}®Û²s¼®O´ü[>«š»Û0A~à~–œƒî;hf ûó÷ÅQD¤”Eʲ(,FU/7&(®?¢“íÊgsŸ,ŸJ“~ œè‚uà¨=¥w…+ A¤ù_ ˆäšgUñt§+ÎsœíÕÝt<8ÑNGEÒÒ›1÷ÕÔNÄÏúnù0òÛu –¸í;…uÆLâ}Á¿âQ†o©Ý¾úûzö}M3qO5¨hììß\¹Ë2Lq¤§Sôð[<ýK‘’|ûŽLÈžzG•]c/û.¸±3|Õi½1eÈõÌø\¥6€‚"‚—h&ù×gvNj4W äЃì3W‘Ó¿ÃÕÍ&–[½»×Ä<ýïËöüë5¸óâfºÃªÏ«LÀÌã|\D Ï=1öò†Ÿ]•U#—ŲÍ2k·2,Gš“<;BIÓ2ƾâÌžÚqÊ|íáËú·¸ë͙˹Îsn‹¸a¥)¾èº™•-6‹óÕÔNÄÏËv”|¶ã”Þ¸í‰󸩴ƒ_ŠˆøÀ3}ní÷Ùì»vTÍżV¡£³³}rç,É0Æ’˜úoÁmŽ— é'½¤äÒ‰¥#Ê®±—¥uʼn›5Zd/LYr=Es>)M$@DT@Dœ»6•ÙÝ“JJ+„òhAö«Èéߣ¥4™M¥n¸]shæÈXÞpÒÉ,Ö_að‰U“" ó<’EEað„¢l²Q$Põä’€„žªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª¬’I6¨-(.°EñøüD}ÍÍGÒ¾nM[…‹„¥¶³ZÊЫš‹µWQ˜™FÍMï)Ùñ‘d•ÒFFIa¤i/€w8>FvSµ½ô´{þ:‚'Ñ;S†8Ó=ðì@ÿÃ{8:gÌá—=“Î:³c±g«§¥ñvT5-QbK7¬ÕµÊhš5 £v¬Û”^šœ?_È>Ü•o×ì·Adɉ÷á Œb}÷^µ-ñϼպô•V$¿‚—Úiœú¦…PÊŽ+`ú±B,æT¯gHúá\BõsK«²„t™(/–îIJáB™œÚÀ‚%àE€ ! "ýt6T•KÁñôsø§äý)Ò¬ûú÷ˆˆ5­ffîfu«pë[Þ÷­ìÞ÷¹m›·»—ÕÔîwZÍoy™ÜèÍcjžî¦”šwHùդū·‡Éô5ºY²ËÍA³ØlÍs¨~³NiíYõÂ} êOÎßâSàoÀ'Ú­O%sÍõšnTäÇãFkâ?,µõ0Ò­RÎUŸjšeQË*Ó›>|×g+hçâ{,’:êéÍZˆiJ¦ãòÝ̾åFܸu½¹›ÍoßS¿:Íê”ñ.qo»+/n©ç«D)\}¬¿o™aPô;Õò(¢S @"" 1$ ¢QDI‘H „DFD‚""#!’@Q@P QoôJ Ö¨.Ý` ƒ€½cѹîǸh¡È=ÍžæÎ Ñ&‹,‚M ¡Éƒ a¢ (Ñd˜A‚ šF’ƒ B B°‚È4XA ¡hqÍY¢DhÃfY²‡A³f ÂAÙ²ŒCPÛ0-°°F‚É;³0›,³ 9{FŽ É…hr àC$˜P‡6"f‚ 4YfÈ0Ñ&ÍŽ9&‡0“B0ÙE #dŽQ„XI£dh³ŠÑBFÈ£fš‚ Y±‘ ¤ Á‰ hË ,€h£–fú30/An ¬J5–6, ¬Ö™CtaEŒà€Ù#@ØY.YD`åŽ`P8Ò°°¤ ‚ —,bbCТ(†'ÀQÞ¨.—¿mv®\ç;Y’£’§wÛ\[\a-8a–eµ4ãä¤j¨ª˜¸•{ºÖ÷¼Þß{Þ÷½Þ÷¸Þ÷½î·½îw½ïs½ï{Þ÷ºˆÝI÷{‚¨[Ì}Ä¢_ {ѻª§R[—³f6µl¥¥žÚSIU·{ÍY»¹ÍV÷ªSG;ú—k5Æ·©¦æ$ÜläŒÞ¤[B7Ä÷¹ÄoF‹I®ÿþ9–ë]Zc"Üç”[—Í_ {çvÞú[¢~÷«¢n»Äï\k¼sÛÏ àÜš4&ÔB§*+Lawåå­9u'Ä"4;(N?öŒã„Uß *oƒ‡Õ]Úˆ¼U‘Óë{wÛÜíô‹}f³"çWO)4é[Ù8¶f­ókd(¢£7QºÇÛ›6CéV¶MÛ•šk–®gQ‹zºÜ­­óµWpѳŽ4dîòÍ5•–”pæ±ø’Â#zÝZÞl ›S™{Õ½¾¸ÕÉ[Q£vLêS蘲å˜\Ko‡ô?Óý¨3 ߺ Ã@rºj ‹ñîYÚ‘î÷åJ"yµQ[<_¯W§÷ùê…ÈÂÉ/©@Eô£øåFùN׫[¤®*PXs¼>K„³ËYO#'œ.ƒÕýwò¹j*#ßýK˜Ãî“ý?Ǧª*Æól„„<üµö ¬?ȸ *ÏØZ Gì©kYüëZ ¢éऒÓLh BOíÛ§‡ÞÐÄ0PŽéX³±A(¿ý:†`¶ØBEQU´  ’H’ÛéH /·áÓ!’ë’˜~O…Çmlì; pú¿€Õñ QÜ‘„áÈ‹óOÈçàÕcÜõ´Þµ«é†ËÍí·¡ôé41ªû~…<à Fêç®;]†níp2íµdBfçqcÿx¡õÐö`èÀ²Âklž ‰U4€Úå¡Á¥]Ò3çÙ±wr¶:ÒvüQ• Ebb èÄ…éOÛ¯GÀ,%‡·œó»þe|ŠÏIhu¡E=.Ñ>*™8Mòåà`¾@€XPWyB„¹¬Á£Ýoí„)Œëõ²÷8øÌÁ«arSkÕø¿[fú›¦³{Àï{~[ºz¡õ6óñxþ%ïôá>>‹zÌÝ(€ èá6еäÐ2!mCêS¶)ú|pŽ7ÒÑHÏp–‘º=Tg7¥ñ | Äâö}áP8\»óÄ U6±ÿ mMW ÓÏ›Éï‰pG_™nåáDòvÀ­;ÊX©k&ð±”ãSñ{UìTe_Q—U]TbãE©qî;(ùÉ|’ÿä:-Õ¿ ´LJZ’ú>%òî™.ôø ÔÇú¡*ØA?¶.ÛA¤<¡G q  ¶P²9 üÜ·îŽûr§©s­;èY´O²82€Q(óbUµœi£;J¨HM‰RfŸ0,Ä7x?ÒY¿©2­ ']ï 1” ž|ËŒç QÉðB$  _ Û»‹Â(3?D¢qbu@þï€ ŽÕ ø]ÐôKa ¹¦xFE#·o¦–ë· ?¤´„"¦:Âu-y ÿH£á®2ÿ!–{ÉŒº) a0Ó ip@®p>á,JžòÙý¹ÿ[¯šúRKyÏAŠs²p£s€ë‘™ivAˆŠ+wuXìÆÆ>Ì & õºw]^ÓŽïœ2…ÉÖ¯Q ¨{|au¬Œåw7Áþ¶—…•¼F-WÒ.ÆŸðTÃÑÝ™3ÒIý.ÙXүςЀ¨’v­qWÞž¯ÙLú~(ÖÃþÔBŽŽø>¼‹ÙLN/yuÊd¡ÑC CpÕÿ£ýq€‚U<ºÓOñHðŠ­VN¨whùX­/'³Ñr¦ŸûçyTDo¹ï¼‡Èçÿ\¡‘Oå}Ìrëñà¤ÄÑÛýÜÇËLO<ÍgêÕtz]}áÂíÚõ³ŠŠ_öœ5dFþKê7µ¯±VC„”š_á@QºPX€Vˆ‹¨Äþ­§ûIO‰ýn@mØÝc² ªë[77Þá½Ñy.é$dpÙƒ¬ÏÇÕúÃVÙ\ 5‚iÊ)í`NI²–~úðe@‡„WRØ• pG v†æOƒÈ­cõró°™#ojÏ‹.áåxh ü”#u½¸a‡™¿•{lñ]e›Þê¿ 5ÂømñbrË‘üý@-`…ØnQý—Ú÷χ··™ÙžÓˆ›¼Ã±íY?oó~_,KmêœZqîù~O ˜3†§>ÌßÁ§ô6A½å…ø¤EWsØcÇÚ¿„~Yò¿ižd¢0㻿°íD‹EU¦áüÇÀ@©G¼b.¹¼÷ãˆ>½å˜Ï±ñ^ž^-Â>Α#'Ñ> ­¾^\«£ºÒ+£~¸s°î¥DDDEQL¿Ùû> ´ T¦ºªy^ *é4C Ž˶[*Š)ÓËË¿Ðo¿½DT|G­ <(Ñ:³| àÉLjÅ8áxš\™2Ê£^æìD{ ˆ<ú„’Ž}Oɽ¶p›Âî¿'kƒ±'vöÜ…ÎÜ;{$ý§A ‹@›³—C’F'QÅ9?·pãR¸œN' í $–’X*˜›{4°\ÐÐ̹’gCöNKF©‰IGŒ0à Dõìb]Én• ¨'(e8Í‹–B1EÑüM ª*}WÛt>r›Ú‚œ\[~ª¹\¥Û–Ùâøq–DÚªD™™G_ V”…~ Û¯w2K{ÓSã—¢)§eÁ|d¥ƒ´ >¸ éÝ®s$­¤Bɱ–E­¦î¦ž*µnQŒŸï¾¦G.Å“žúZÒWÏy•ÇÁHdz ÈJ“2Q´a‰“-®®ãøã>­"@%ÍDFH éjG´(§A[&܈~´ÓïÂÝ3uà*c±â7‡å/ɾx}èƒÉ=Yxª¾þ¼Ï7yœ•×ßÙ‘…y·`k‡(Ø•$×B©râÔò»9¤Ð¨¹ð›j,ª"œ¢¨¡]TzAÕÛk—"wßTSLŠ}æF¨Ka8iÏj8y¹s`%RàWA2d`ÙȦ1)œ—ϴ䢕d4­ÒȲdåyiAQÕjà'W·"F6@&\àÁj9÷úibxÉX=~š¾ŸŸy´Í.$AðF”LììÉ ´€@-ÁÖ –Ú€©øÏ›&t¬{²9ÐÐ>Ïœ;Œ{e&e¥²6á½Í¸«Ç|5™ðâ”lÂp© ÇÕ¸TÑ8²­õ@jÞDRéóÞaŠ5­ÃbšºöEåw)—Ímç˞χZ!ö‹·eW¿W#gnÛù¢×»u‰!+×*ê^·[è’Š FMt^QÝL\gìx]\»•¥QKìç2©·\BŽà›9Q‘c1c‡9Ž¿ â2,!‰Eq 4'Ï76a¯6\µÖe\ÌÌÌË(âŒ3Ú³Ý~p–MZ›Ñ²»2¤ÇEùÂáßçËbvJ±-Ãu¢+ýFt&-p˜UòcÔ±I¸3‰õ–íÞ²<“[³3£íùqvΘÕ4T¢ªtôì§‘#ÛÇŸó&÷Ôƒ²6òý'ä.¡iÒmŒý7W!ù-ÝQÎU]r”)…›Õ)î#™1DgPÉ#°ê¯ØÒj¦]GQ—M*-‘SN©ç¥Q¬;Kåw¥UenÏO ÷Càœhˆê–N ùFkÆø+ÅS0ü–4óÌX:y˜âT»·±¨M@̧€ôÛ]mŽÎéŸ×q›O¹ÿw¾ò\ÖœbÔüÞ1ø"Ñ‚–˜cšv“·µPOÝÖ(ÖÆ?>.á»»ºuÉ8uÕÙž­ÄÙð¸ÒLþ’‰p-ù)sxÐòѯ6­ƒèÙʇ›²MfË3öùÝóŸ•–î–Úº‡Þßδ=’ÄÛ7ŽÌÊÏÞ¿>y±YôX‡çX×OnŒµ0PÙWtšÇIW)[izÞ{õyÖ-h.™qÑÚ»Œ[Ixi´,4úõUmþƒ÷OÇ$°“O%ûÔ©v¼…ù7…/gBŠ-Bñ±sòé’ÉŒÅ&(X5Xäm­ž-n„Ëk Û+i^i"dTÙ>ÞKøZwÕ˯´i©ã8½¶·N» ®å]ÈŽ¿ŽÛ…Z6l<²^Ï<Íù¶VÔàe\.>•ÅÃcÖ\ÄhØ^[ŸgWV‚,#i4õp¶„f½ª*èU—°ËÛë¤È™›˜Ò+ìç^«ç…×JÉ·«»Í©‚n”½¿ŽLÚ¡]òÔäWtj§ËW 93ò|eŠkÃ`q©Ç°7æØËµ=¼ß5ð¸OÎ÷ýÏ¡›ÊûÞâ¿ÛûŸÚÿ?‹´Óó» ¾ÇNÆ–¨œ»¥¯~Ù#'L2±Ä Ì3* ®«¯Ø–U3¦ø0¥5a›O·ab ö€qÆæ.3Nw{¶ù>'þü}>K’ê¦ç}_?ÐýŸÖcßgMÌdÇ‘Eߦšà¬Ú.7m)Žcuç¸âhéDÄ”á>~î¨3[HŽæ1aÛ!à‰/”=Ê“þûñRqÑ·{Ž$µ?T×—máÅã ûKgñü%·,ì0†#f¸ JžË"qïoD~t6´¥ãGcݳ&á¢ëG#rWÝ\À5‚‚>~•÷³:†—‚AQÜ}Ú¢äÏSéï›Ç&\_X+BC®‘R'¯áì—¨½ŽC›Õò´4 ".ŸG=ìä…@ĺ|­SõôêS½B/„ø¡9ÈÐ`O¿ÔÓdnú¡akK@a;Q IŠdı@RalgØt“€G,G¦†(þ¢#îö!wÛìjýtzëݪúµ,ødFì0=ÿî•ÄDQǪ°áH{>Ûí¿VÖÌ›OÏæ/†‡Mà˜:'ÖH輋ˆ¾aDz÷•}Ü9_ý|9ßO\ÉTZ,¨2ªœ‹Ý†šÔ ÜÖ`ŽeÒFë[<ßÒãú É„ ô.‡TÑUF(qä¿ôäÿo_Öï=÷éþ^r~ÛÉí®Ýõ"ÂqÆŠPÈN´~©'µ,«ŽÁiÖM)”¥Ë pÆ$>cÅkxöj¤B9ºI ÷r¤é6­Ù&þÐrd8{áëtÁ˜zN:|W%<òxÓ]&v¯:ã}NŒÿÑÝìKM]—Q˜º¢‚§º“{S<{b‚Œë¸QVlBfíx4¡»Äl›GÉ›•95KÑ ÌÅð]òhã¿»qжôºNªRˆž·íÅ{øó’éöîË¢9þ¦Ï¾vÝF_ìßbyE@9Âï¾uÕýç5Òqå~’HK )èÜPµ#àe]V—¦p%ÿ¿È#j”9vd•NådHÿTQ“k#UQ¨rH—)Dª†‚îj2:rC§y¬™ní›Þ9ÑÄ×3ìÍ—‡×š5‰zQ Ýé%1 ‰”ˆ8N($¨….ÿô !ê$t¡Ðâèˆêw6[“n—;â0¨Žú à0Ì!†¸§ð»© Àä> b‹-yÏŸ/xÔÊYR)PU&«QªbDé¢ ‹ª ·Î§Z2¤’Nª.&#\×¥åÜÇhûÿð¿è:mcõØ™¤ñèõ7vJIÊaÊ\ÃùªW)ìv¶I‹zMï(NêSìªõ’ÀW¦‡ÊßÐ9-ˆÐý[ƒ®z EI\9z‚ÕB.žæÞjî%dAÄ]U--Ã>ž–âà5[ìÒôœp­ùåã€wAÄ»e)STO2òMÌ%rE¾n¶]¬z¦’%<ÌDðõ8¹w‹ÞâMÅ<\I?In”,Y {ÔªèFÓ;ÄI\äq¡"<ö \Úup™ñÓ©Ü%IRNÓ10)u'8˜”ž^”Ìq5… «+ZâØ<ŠÇV(ü² Ç©ø£üÌm’ â²²±ÊÀ41éÒC €X ˆ ^0Tª_cû„y 1U8?‡ky4Úù]*¿Ûß„B½Îú[S‚Nã çÔOƒ:#ž|³Åðÿ+û9Lù¼N’z¥ …&ûöK×ö=‹ÝÑø­_¯Ï²ú¹Ê&‹v'!Ë·üÍðî•Ëþ¥Ý̈£÷Òúž*‹#r¡¦­ün˜4«4rrS9=¤EAc$¯`YªbGx½Ÿ‡Øý¿Ÿï­û·ðú…Ús!tøÙ¯]S+çí¹°¼á5ÆM4 fψÚ?ƒàÀ¸õC"#ø–XÔ©‚{W3Þ˜µ7õ_×õˆA{¤zIýÓÑc??W«ßÐã:1/På“l{è/B¶„:4ì+ÚæôÏÞñ5ß3Øû¿!Æí~µ§ù3¥Nè³ÓûÙTé˜t¯•ºU"ø´ý?çŸÌ>ª´8÷Ÿ?²´X,*tŠå@UE-«tÝ;®·Nõ½¿ãü|zª$ÄÈÓ—¹¯=(^Ê™$Qsñã1Ïó9Éó0ÎKß`˜ú¾º÷Ç÷=eýïæaá4´´‹Å´ûÚ.$Gç»Be]Ûâ“ÏœM ÖUW3c3Ÿ,€¢ƒÔ34A3¤ª]P¨Úq“7j´+hugªëÏà%yÓäô¥6*ÀïK5Ýã3³³–rŠ¢V6Š“¢SÇk¢ŸÃs·žx—â;9œ‡÷32 ¦ûg¶y¿škÒf›cŸ>ÞßFB/ÝïêA’ÄÐAІU`}™«Á\µ÷3‰²’ì–L„Ù= » ¢SÄ¡³Í µ†i =&Ù³¨Ú[v8POùß<]NÊtnªÙ¿—!m’5X¦U…®ÂXI0ÃOM¢éä%*–WWöBúÄ–¡ÓtÞŠ„±mgÆë+¡<îII¨*ÖZHòúÌ©e½ríiRN‹­Q§Wf¡«r؈åW¡‡ oì+–ʬ"ŽÖ5RæI™«y“>þdëK‹:q3=ŸyvÇ–Ó•Ñ·Méáy\¥%©X²Tûl—`BIÞÇNIeª4N´¯lõ£iÏéTá(bÊR×o £‡GJßm›ZU%»¸¥Ž ÞõAð¹mE]d5óðnîf•f Æpü¼õv_].v¸›i ›³ÍšÖ[³…åk¡>¹Rk¡–S<'š™5P}XBU°ÒÇfâ{Îб±ØB²f›ºÄqªNí¤Œùkbõܹîʹw¬Ñ@Ð[ôަîm¼P”‰Ï™ÊºŒ‚¨ªmƒ/Eƒ^Á¬Týλ²êû[å~ «ŠßÁ¢—VÔe¯B5QK Ê”¿Uõÿ¸ùþÇ.¨ÚÆÒDEMë¸ ¯zºvq²zd”“ù5r Ê"2(îË•ª"¬]ÓÍ{÷ã}mú÷b(§;SÊÕ/©>dzPÙÃðÙƒ¢”ÕR«7«‹‚ (È"¨ÈrÖ²iTB9t˜3}O.ÂMˆ–×uh•NLOK4b\Ò:Í(hù¼ waÄ-!À­äd'zV“ÅE*I3ú“-ÏìôÿRÔú¦ÈwZ •È ²ÁtʃZ|íï{°ïâTQÎY^-Õª?1 çÆã[vÚÇÄÒ–a®Ü¯7µÄ9á¾ äÉäðGŸnË# çí¬þ×Ác’“Çä‚§Hr¡¡õòÕï?iýNîGßÌ×…¼ÿ‡"5<<~“Dý΋øféU>Ç©ÎÄ&¼ëú­áÄXÖy‰ÁÙSóìÙƒáîµ’Ÿ¯_±Xè ªÊ2’(:%CÌ®<$Š:³”Óà*/(’®³3¸UÏW¡[á•$Nx”ÕéåD´.$q7èþ³þùoGœ‰äV…¬Ðv(ÆÕqžoÜÆùÿ}Ë]Ë™ý‹xÂ݃_~LO³Þã&k\/2­jH™H$PBÚ°¨KºÙôX9xmÈ;s­g%ùIK©„NC‘[œÇ+ºçäCwÓNŽ]hÇ Ùz~#Va¡¾0^¾G6ŸµdÄÍ”eæ"nôµYsÑf@ÓQ}?1%zY׸±º¸5wÿk§…ëüÔ‡ïáoMÈgܯ½ðë,oô”ºÎ+òK…ŸÉtJÁE›áýü$,KAW&ˆaÓ[ýSÑ–å³fJ”ê‰ý[œô¼I·²;x©£Ñ5±E*Øå?ƒ®ê¨t*•k•©Hô‰Cµ´¤|“– $–Ig}o-6‘ »8Ì4¤7¦y_¹¼›ð™˜´(JŒ¶™%'©ÇÙmüv_ëw?Çœ†<½ÖóËø¾àÔöû~O×å”-#sfÝoÕQì©G²_xŽÖU 3Ñí4ˆCíø±fL6]·ª{=:¿ò¶gÿtžº#@Ã[NMÔ%ËLA»W&VçCèŒÏßRXþOJð“ïTyþYŸLû/áÌ­üfV7¤Nïªs„[øUùNv¯{>þüÜ×#Á«èÀbÄ0=èAJ> 9 þum‚ Zl¿®¢óݧ³u³x?¦¸ÓÕPû¡Æ© XE”=- ¾º!^ä) –µ"!¨ÎpÌ0¨:÷øEH½Ìï>íàu‘OÏ)ámXÏã]R¸§äPZT† h”.…†â–ç Ûí{,h«?á$b2FbQ‚ÄÀé1* @ˆlˆ¼º‚ë½Z‚à{žÞ·§ø*Ó“…ºÉÌ„.”íÏØØÍw§5¨×FÐÙƒWKGá£çs|½Ôû<ÌËAÖa‰Ÿ¡­iÊâ?œü/Îéœ'›yÎÎ"mÝ0ðîï.O¦5jñá"®ÇOðó$¤Js‰xJ^“ÌE½nRv—*]®¯òõ6–cêM 1óSÅÔ—bD!—ÝÚÒXõö]^˜è"ñË-ÜB%I'¹P™©%‹‘ÅsürSÌŽèÈ(€]ªt"•ÆÈ‹EÆ`‹NŠ[â¥)JµÍv2— |¦QÏàa*nNÁ¿ÝPöå©1Ç”¦˜ŠJ$ðLsÞU’ýº-ßlay‘Ïi$P¤—gt¾b¦úƒìì“…‡gÄÍ?(S\Q^3ZÖCŒG¨kZÖel7[â˜8Ñïr: =PðW"_ -Äî»áÒÍìƒzåÑ­éaQ”™Ê&r¢ä@#ÁKýxµà¥ðÃt,¾~ÌjìRÒuÜ~«{È÷ûÓ*/²Dï0æ.·¥xï“W“TàûˆƒOšu>Ì|}œØ0 «ñYõê M8LñÇvPê! ãØXåôÝW‡roº´ˆ»OPâö˜¸ù>M¤Ÿ>+C;Lo Dcî^eAdL-ðµeðÿ S »à;¡ŽçÖ&g¾wŽ—ª¾;¼.ø,øÜïF¦¥Rî·<=é#—݇y7.&Qð²ëhY‘>BCA!Àrrw;ó˜Îë•Òr8N™)˜ý9ïi»¼#”äŽÑ ´4˹.V<Ñix£¿Ú|Ðk[ÚÓï¶2ÑJÂ9OrÔ xÇ’7JS$!$´ï pÉáß2),íŽò;”¬X½`Þ^žÌL¦e [öêë9O¤#„ü8äKÄ;‘#‘râH§IýîdòŒ…Ö­QOLúqKü¬D1Nöˆ¨²´³IâŽFh½ÌÊÒ<Ø›Çé·Æê…J9Ðe± KÀZÒˆôO v`È©Àh<‡R!¢ŒÎXÌÞTw³A­ü=ZlÁv¨¦Ž ¼éÇ¡&®,’MìH±8ðRŒø6É%´ñ3s³*v¥'šŠrÑ$Kdáj¢ž|¤í…!¡—* ºxݹýçá​ŽóÝlMÁ;¿ÇGQ7£7(8ùËî¸w(Imú@ÎKé!ÂÀíþ§Éå,Q*½ß›J‚ýGZ‚Ï[ÊáÝé–7Ä7Ñì­—›Ç…ÝÜ“ ÿ žÇú:}ŸŒäqÿÍÓØƒ­‘ÿe W, £Ð<¼¦Q ù °nY& …Xeê=Ï•Öö¿OÒúíõÿgóý”3’˜4…—Ss(àÈj^?ËÝÒŒõ:7<=–ß*Õ±¿fÓh€XÊ¿ &V8m¼5çÐâZÅVp|uq‰Ñ‡óÞ½Êe†=$n”qÛ­hÁZÕA Œ €`ŒëâÜ'¤ LÀÍþf:ÇþÁø\ñœEÂDŒ“¿;™¼Æ*t$XVÒæœå‹âª¥[Þ¢”|O›ÒùN£ÉôrRAp:Ççõ׿ÏÛ0¬þÕLœ |ÿ·Ãý´ìš¿«Ž±£êÔÓ,öìs¹¿Ÿòe†‰f#û/ÐÍoGÞ]þ4¡yë­B÷÷ÊÀXß­öÝMî=Ũ…Ôƒ“Ly(Q$*v²ðAZàÎ4pËW;EÎ*YŸ#I†ÝXIz<ÉíÞI6ßÏ}ú<~WÈý>“S´ÖY.ç]¹÷™³ÞÙ×L‰*éˆXV¡h›NÌ)&Õ²gX¢ü™ âÞd+¡§ãþ©·c¥^ÒÔo­Õ±-‡Y¨iMóMŒ£Ú3[ŒÚ¹¿˜×«_›®¸æ|Éë¶m/Iwä±xZZ ÕÌEyd„\JÎ:ßÉÊw¦À:ãWÙ~¦µl«†êýß|€‡î”/ˇ¦¬JP@×½*¨‘9å( W\rÝ `¬ñ¨¿w—Ï~°x°b–²Qh´LÌ*rXYe»;¥äûí~g˜tty _‰ô¸ y-”bl'¡@Ä=÷Å̽õ¶Æò¸¯¦C˜ƒ˜·DÛv¥8§@JLâ’—N“ ú—«F”Y©âÓëxk2še%¦@¨3XˆÕº`Á Å2™Ü6YB!AhÑ–…¶m;±«´“Ä÷½ïO£ñ0äáh”"Ñ’H„U vf;±ä™1S¶~t'}ÅqUSOTÝV5£™CêÅÙ[DöìR`¾b0ákJ%w)ä—…«!4Ãò&#*w8†Z1’§Ðñ !î5ŒP—&YjF¨½z§ëwø| NG0ãœ@ç4Þåó$~ÁnÈUHt½8וáUáÁEVKl>¹ ÀR#ÍŽŒw¢*Të;™ÝóõË»“ÙÛ¼õPÒÖYFg kK¸3»³2xÈ‚S¤#²Žï¶ Mñã†ð›Y¼9Ù=Ÿ½¶‚É5‰–ó13ž±M0*E†™ Næ)޹ðê^Äd¡Ä1ˆ’Ix„¨§R£¾ñqÆšdg>]‡)®¤lP‹bNC†BÖ;«È¦w#‡¡Ü‰,hKùjxÜfhç‚ gÓÁ5R%‰dÐ~Ÿ??³:[ßÇ-XÕ“ÑlÕŠÞfÓÁô^o†Ñ¨.ëþ,PèÎ(ì(%¸Ðj?’d¯±‡^ôMvˆò-|5… r "BÐ2(8ˆl‘Ak¡$AD´åñbõS‚ Èͯh6†ÜÎ×Ïð7—»ÁÀÅAh¨-ú µÕ²1P6TAp¥Aj.o+ÛpöÃðöá#ŒRÆ.X© ö•ò*±„ d.¢mî |™Ì ¹½îíù…»Nõ9&–ó7r§Wf£S 5;Òwf`fƒá‹ÜñÃ$GWª­‘·Üì·Ùo©C@ìY§(‚vÐ[A D›p–d4’9¹›$Æ1§l`ØhÁØýsEš(MdÄpúÝí¨D˜Â(á‘Ûi‘­š,vCÄC›m¶6fI†›(¦g6lmšl,và ›mìp‰cnØm´Ô`Îb±‡bXrÆ,EÁ†Šca°BcPȱ ŽÖØPá³C±Ú4 &Ç(¢ZL Á °Ù³¬²Íš£EI½Û ,ѲÆÓcY&Ìj Ù³ Ø6„a¢„lrÍ’# 6h)±®ïZÓom½ïm³C±’Ò9ŒÆËØL¶´HI³FƒL]´˜KI†›vQFacYeVn ‚î«Oƒ"1³3[K{Þ÷½†÷½ï{Þ÷»7½Ào{mí¶ÛÞ÷½ïm½¶÷½ï{á·¶6hÓp9² ® 0ޏ,³ 6# 1€Á(  ÙfÂB ³D°ÑL039!%š Œ`m¡¥¨£FÆppsfÍÐÍFåæóYrñ†9£D˜HÙFtøT–“E–hÑ£M£fÃm³f͛ɒ 餒ÛTÌÎÔØNÛdšÕ†¥Ê,Þô‚Ê( Ù#l(ÀÓ6͆͌N‡6;6oWEÙƒFCYd´–ÈÞÚËÈa¤£ I±™@ã³ad h±Al$Ù… B h’˜Ð8hÓKQ$Ésc¢K4Qe„…´š ,r‡;³0/çUÚ€®¡C33a¡¡¡¬ØCC@˜&&&`$º÷¼ÇP ¢àžÿÔÃq¬r‚«Œþ,kú¾àÿu„¿Š±n_jy ûß‹äÑpçwËâˆóäáVüaÌ?‰êqG^evç©åçðÍ÷íÃg·]¼náù]O–ñ®s¿n³ŽÝÆëÛ~Àº¢Ëí³{oÇ!íTÞÅp"+ª'Π/¡ü½µ”ñŠ"'ÔÐÎÍ4©cE_›££#@ÅŸzÛ½¾µ½Tjg¶æQ;;å>V§Ä£L´U›¨6ž7¬-ë7u–ˆZ”nǨÒ’R,é¡,±”€ë!ËååŽO…‘opÝdäð®DÇÔ¢uÚ¿©§Í¦Ùý¹>{ƒøpýß±ÜeÍ{úø»vnü½úD÷ÁáM\;;êgðÒ¥ÌÕPÐ]Çoü¾îc—§¼Õ³—}šS<¿ó>¨¸Š‘U•ƒ&Ã÷ùŽ0Òo¿– ÜL¾›ùcÿβϿòlþ?I\N ˆ€l…Ò‚é¼'éL G§×üÚ¾érR P€  Ÿ‹¸Ucb#‰ûAc «*(§øé`Š(1ÿwô3 ~ñ§[,I¶…C!@¨Û–”“R ³†P[eBL8qþ_ìð¦ Á󢢪¾üãð®¹7ùð/í•ÞäWñkFõFÄî––¢ÝïS¹£u¼ÞfïôfÉzãzáoZ}k&Iw®!9.×1&âõ¼lÚ«”í§©Õ{z¼¬Q*²Pï7¼Ý“³6žoqªÔƒÉºÙVl¨!a¸Ôn §$¶Ó¸«S„›O[š}jÔÞ´ïOŠ§Ñº}ë!Þ–õ*-¤·pµ–êaN:ÿ‘üÑÿ7¯…Æç|öí£QoSU¤•_mÅê#RI›†˜ÕÅÝ¥»‹™X«{¬/'ü¿èpWÂvÿôvh\ñË™S=§º‘sÍ=aB¼¡Ae-DIá¡â\wx‡„ù‘©JzZ¬S¸W«Uf©ðV‚&_ržžl/X÷—m{ÝÔè±,ú“Q7¹“YÂ*ðwwy«Š{En/Zuƒâtb¾2¡öiÝ-<íîÙN{ÞQºÉ”Nõ)¡ /Dky Ukw¨#kQtæß{r¶÷&Ÿ[ŠhS•µ–å³åY‘Z˜¥¿÷•ªÞçË©O*0áù¨¾jèX÷s/œÆF¢¥+Ô̵8-Fok3 BÛÄ«%)µƒÉ–oXµ‚Þ¡’Ö¥¢]Þ§-ÓåEÔdfÞ¯Q–úš6–dmòÝõ“ºÄïo#éÕ=NÓ;kZQb*r”=CïjnßU1Z½æ¢öµ±Ó®fcUéxOÁù€‚€t^Ø+‹÷¨´_™@¢‚ÀTvHŠ‰Ù°P^Rë6s&³Oç­Uoù³`©UDS¾»£½ÑA~Ÿ˜æ°™ÞRÕP\àÀQІ¨,[¼±¯sœecQ6ølú]‹¼¯–örÛ±¿"\ãë<ãy¸K"”‘9 ”…b -ÓÔXåÉ\@šÔøºß;(Æ¿ó0žvï5ß“ü±Ÿýý™øm„|»ÕZ¤W}z¦Æ ”CŒ}Þ›Öx:©‰.ÈJt©_çʾÁX¢UûÏàþ^ïDZóãÔÄ£_— ø‘Øó0@ â!ðHAÁá… \DJ×0«VÃbUE_üÿœˆ ºÈ.ëÿ9ÖîW>çÇðßþ®Ò‹Éæ¨:ˆôÉ áPy·pFg«Oç|ë’ ¢È°V–W$¸ü/ÓzŸc_°üÍÿ÷Úù•Ü;”/ŸRBHä °®á¡ƒ†i"rµLÍ`*0Úß½f±[Å?ktÿ£í¶j¸¶ZB‘õñÏ#ð´ùJ‚þà@x„CQö·×6|,±“ E¿¯ª·Øµ´+-Z¥®èËÂG6AøÕHHš$°‘Ì¡È $“@å ÇEkU™fª%då&¶ÈЬÜÙtjªÈy¢µeæÉŸóý¿×ö>çµé{_Ùÿ:wvWÆõæ¨é/¼QUkLÈ@Z{豋’,¥Ÿù{¨mÙ¹yù¦K ðÿ'6ÎÑÛ2Ê…{€Ÿã:q“£{¯¿~³Û³huAF1DQEdDd³‡ä¦=T“ÒI&± ²(,FCŽÓ0hQ´4˜l¼,›g;TP1ÌÌÓõ…¼Õ4s0Ò³(¢4©ñº(Zÿ7¼ÉÉËÛí"$M ø(€‰@:Ì v›Umã9µš¶5J÷)ñÕ HÈÁ|â‚å’0pXA KN*fáùršµZÌÙ²@’M”9¢ VÀ€ÕŒÔ9±¨,sXI*ó*+ÿõâ Äqª5ªˆ¾8[²_o[ÝÕm:ª|»ˆQŽA³/¡Õ|UE—ˆŽZÂæ°±q¡‘ªÔV†fà‚$"Ÿsýáú¯^† F$„EQV,UPXª,kb¢"¥KH¶•)iR}Gúb§ô™!P×Ùþ × B‡mŒÒl‰á㡊íÄ0^|„¿Kú‘~’XŽãD 5VAžžïý̹3Œ$ÚCû¿ÿ6dèÐäħ•-WýÞ‚¢ìÁØ‚`Á"F”&a'ráäÇ6‚P™“! ³OmòØLñý:4¸Ç°ädL¡8Eœá¡Sf¬Ð²Á­¥´÷9«‚¦õâ5”¶î™àB…—Š®˜„±»©‘î""µ§“`ì;l±i&Éqª‚‘vÆŸRl¡ÒÒÐbsè7§Úÿc‹†L¶i$×G=¾¸˜`”PІ**¢DhÑEd¶AH¼ˆ‡fpDÔ@&VLH˜Œ‚&l3ñnͧÔ5s@ŒRô¨Ù‚kÛš‘6„6‰F‚w¦6©›jµyºÓÖõ¤µ5›#{3hzÞIµ ýYÜJzZÂfŠ88(âšF™¤ÿ¢‡ v¸cæ;ž²f‰1±‡ã)D¦tb8MÊa×þÊ}Øá¶£b'x4ŽqLq TT;@&L¯P½ÝYVða"4ãëý~0$¤iÞ´á ;[Fä“dŒÒC-3Å˵¸rVLL5C&ï,Ç0æL!Àñ¦† ¼pƒW,Dìù¼fÍ(›rêUAíÁªµŒÏ3ºÞ'_à~ Àñîû-ŸûsP¯Þü–«†Ôïª÷;9»Ìío¤÷ÓþýKæÕg3¸¤ÓËÒM\€šåF Æt쀹¬ mÝþ/ŸÇç|/Ÿ?±Ìæøž‹ß}ÃÁeìÀ]+Uø’È ²F@q+„%ÝÌ,Ï;ÓàFçj$% š xwB6Çß©¤ïL–1d=R¿ý.7_ä#ýMv‡Tºã§ÿµ›ïYË"{×nkŒ©‡V£Z0}/Ý@Nµf¢ª5c¬8µKڼÛd̉œIëp¶KŽÎ㡜”#"+Q»Œ½Ãê"¨ƒ!ʈoówþÏüçÿã;ùÙá‡x”JÔFÄå4¬ê¶["‹‰¾-u"'2äu¿_¢š!Ǫé×*4kÍ­%ntK8Ä3KÞÔó|xtþz¸óËXñ”„¯T@ <1;¨}Ué”Ã3;j³¡Ao߸VÅÁÏû½lž·‡þ¾ëÌmµ]×É»Ÿî:oƒ—á`êh¥xæo$Î<›ÙÊ=›É]‚»ñ¼FU=ŸÔ¸—¯ tòRH„©JlªÚ}s0ï)‚w w Œ ;W%ÓužÏ?Úu–¢ ·(;‚ÆäVÁòÛó>§ÇÆüÙùö…M§/K¦cH5lœjƒ‘™•c6£w± º9gÜ lÊQËÆŸ9<ŽtCízŸöJy~wI"BFÈ,ƒFʲYC’XáC`H d†y2³Tõ.c9†i<>Ó˜'­Ù6·—½¨+O \k9fo‘ï'ð¿Cõÿ¶ÿküOK÷kövÚZ´¥µhØÆÕ±¢Xþè}2¬É‰SاÅCÕSExè;É›o(ÄøA p0´Ã}Âñ-úÎ&_⎳[®ÔìÊnèÓ5f¬ŠìöâëìáÈÔÄ„ôKÔ(ñ™U·F…l4`VÚh¢&²½)³«'—{)S–¸gR’,5×½×Z)µ"•l1®ØdКJéÒb"jÒõ¹ª(¦±?Ò‚:kyKœŽ[¹£á!·9@ýù“›[½‘²æÜ"Ý“¶h¸b˜vxNÇþF‚å@H  X4L3g®Eœ˜ÛZ†,üa%àKˆN'º}L´#mbÅ€‘X 8’"}´]6Ùä•ϳm¤Š.=dYÓ192J1²‚„XÎa #h³†­ˆíµ¼ Ðl¹ƒ 1·°œc Ùd"CU¥xiǯß[õÏZ;W=¢>µyOUy´ž«eÊë}t’®õÞbb»JÔi%߬váöoX´©²5}ëŽøæ]VŠíÛI‹q®Ï*Nmû(æôë]¶)Φ;sÅ©}ˆOçóýÁ¿œ9†ÁË;?žºðþ‹" ‡'„å#nuÀzဗ9½>O§Ky ù¤ô uð-ÈQ tëàÝ œÕACh×rßPélÇä)>Ço‰–lLáÅ«d’kqZ!ãpài2/F8Cyylëm†‘3è©Ø‹LÎC±´™4±-ƒTEó ݬ<ÕŒ„˜--gŽêͳ76A¾Sì;ŽÞ`:à1lv©-»¡2e+`[Be¾aç9:º< Ä]s-ð8òjyå«Pfmã`¶éÕ+ÏÏûKÝŽ¦kë‘áÚu‡ì¢QÜtÎÎ{t†À YMû ²ïFçoQ¿ª¥1• ,ö-Ÿ ªžXwø ¦0ij¯µÚ„Éñƒ³S–·«Mz¹LIoƒ;ÀÑ¥Š*•0ÒI¶A“}“2Ó³kÊnDk{ÁûZ9œ-œŠlX«Û)¬í‰ºi×6¢ŠG²Mq ÙÑë› .ÑÜ‘áÏÚÕ&†3ïW`„‘ì𥇗tâgI…Ö†¥W« ¢BHHsU@Ä6N8x¼"ýŸRE2È rU\iŸ_rÝ9ÛnY‡²â8óg£Ôk(Ì«÷†ãa¼b†nfyœ®µî16é25å$ê6ë¾yiZë~¬ÌRHõš­6ƒÛT„ñ˜³~hc¬sÍÄ[•H†…öÙûiØ y,„Iœ³qñ–q´’B9g¸‘$™Ý§aíÅ…­Y¡iÐÑãckXq¡³PÊt8š³A‰ŒÔ²ðG’ ÛäÀÃP¸*ž' B§Ãĺòïß±­¸äp‹'¦ÝÁ&¶4PZlybL_§Ø3wžàyì•.Yÿ…ü@Ž~a %fóKçïè·1ûÏpô†ù—ïë[6w èpEÖI#ö‡c±,f›ÎÊ(¦Í‹:z6Ü𤑢¶V ×ÀèaFSÔÙªg'i­w9ä®i^œCI«KOiê C‚RM.`‡rÛ#§ÄÅã¶AFw¸Q¦tf„â<_=ŽF“i0©â.ôíŒÔ‹d1'glC0”•J0Æ6n(`uÈg¼¡­!D$Pšeæ6a–¡©s9>üüdˆB„s­-X¡4ÉmÄ$)‡LœÐäâ¥Á短˜ý„aõ¡! 2G/ô ë_Jf‘|“ÙlÉÈú¾ŸF¤ÇÀ3êðƒGD]?Ôfþ~hc¹f›B cè!¸¿|æ0ù<ý>„Œ„L8JëÛX¶wІ,|v‡>—ºÖƒZyû®A-¶mvq½Ó]»7ƒãš“{vÇq—RgŒ®úûj§gL¥‡óÛ®)ìn´nßh9‰¶¹NhbŠ(¡‡„ì{´’§mVÑ,Vþº ‘¬Miˆw†;½*$ÅSEK_f}jbÜíÙÃ#»®»m*ªö Ï=µ-úIcx”€ñ¼ƒc0­Ttˆ€˜gÇn'gD’‚+×Ça'L¾²'ê~'qõL[‘ÛmLJQ¤Ïª‰f;&,—cyb†3ããúÚ.ÄtoŽ?.°ÆbS}®gUô†½š„­þû z“Á³î^^<ǽèN6“C=9޵|”<ã iÁT@uYõ^‚gǵkífÀ7ó£·r#d°dvyÚ*6ôÒÀ9ûú1(Ô\®ÐÍs¬Ã††…÷j$7óø%Îsv&Mú‹Ág]|½ºÙ×GÒ6йp¹'¢ˆjƒ–ìz¶–;ïÉïºMŽ6„k— ;8T ão XaF†ì›íEÈ;i5Ÿ“,ÕãçF$•C¡Æk¹¤¤!Ù‘ìIö\µ¦¶ïö_ͽË­yuõî€Z©5ij$„Ý/6ªSž³¨tô£çn‰¬-›RÅŠ‘ߪ;! K¬>KÜù3rŠ çÆ|+»rkŠöôsF+/´¡<´lŽÁØzíe˜w†¸›hiƒ%ÌmÀéÅ•Ô<8¼B½i)–÷dü  á»CzÂ皉÷\΂ÝO¯'t…­;‘Zrß u7I #’Éz,•ÑdUÕ¶eT1TNyæ `cɛѻÁ®&Áv‹qOE§âlS….–_§éEy}]Œ”3F-ìPL`’x¼.—T;ä)à/Ø®¼|ÆÎ;Ï—öù”ššœvFíàGàD€iñÎâæ8O¿—ÈG¥ò_gê»:•ú·r“ŽSB¦öwS›>gYÔòïòl›¦éx[mD6*ùApGÍø2¶šŒvC®íuÜ—ÐÞ¾¿ ÖûÙ.£¶ÝúmÜݽ›×q{Ã\°S^×æÇ "™" ©‘hm“"E†DA„¨B´@8™@i)Œ3±NÿK²Wì÷?‚¤-á“¶£½|4_G §âß9‰¯ñhw?¦ÒYâEŰ[¶ØÍšøçñ!Ý,bçM6È Œ‘‹¸R§Šâ¸ÊŒã/n±÷q\¸üW<ó¼×ªÖdJg‚-­Ug­cÔéî ÔÞ\V‹~3U—zŸÔþnù)òõÏìOˆó³POo·Þ;À롃ßÁüÛúõëqYDShÃÕ-Zb!^JŠR%"ˆRÿhª®šüC½Ø¹Íܰ[@»ÚºZ®ü‰öý©¯V–ÿguÌåÝÄ_§GMa!f„Aa"0  ƒ ,E=jš3+vôØï×d¹x›o¨|²­µª™„̪”!¤WÀö®1½é~ÛþÇ;êòüwÝMïWÄQ™™™ŠµjŒe¶¶6Z‰ðƒÂzéúÓÝO±a>ýÞf? ´ˆÙëR–´> '"”ý<øÙa¡>,õ­®¿nà*Öé œ"cG³æõ~‹ Yï§¡ \^ˆ¯ißËßÎ[}B9Dµ`[‡wp Bµ/¯§æ¦µM¡ËªÒÃÏ/Ñκ־%_S3?a5]Qs8ƹ†õ\*5¢¦õfoxm—-Ë Æ÷­&À¦ÜF–1tvdw~ßNÒé=¼,’᪥Þ!Ç•2Ç}oAÛ ¬Kb@í¸É™‡'µÆÚÑßWÔÁÓ›ƒƒ”L-;.h 5<àùws@@LDª§ ”"§wMÕ¹pháUXѶë!Š©œ[¹tæeLm^5s€]ïüxz·f[v¤”³ äPfs™uör‹–¡*ZßxFINýÎØÝ‚˜h:‡9M³Ÿ/Yòäív“h¿peÕ§t5±0Ö†B¥r¢¨ÊâVA¤m+Ù ß]% d.ßVì 7£áÓ7²¨¯3Ù¹•Õ¼µž-\kW‡.a2™¢îÝe5ì†÷šÅ\\FæéUvS\íšÓBœ·­Í¦ís•P£ŒEÊsšžHô9 ˆß復Ó*"!-KÊ”°5º–jt“™T¥ý8VØÖó §d'3%¥Â^´<¡èÒ’ºÔT3쀩%±BCR¦™›5†Š£šÖsjí¼\ÝžØCf+Þ2ªº…ÌPèît)±@!PK=*3Tª ß3ƒËÕy, ñ’Œ–ë)„f`\¥„bÈ1DŒF2}m~OÅò^.Ìùòš­'Ö›5ó§Hš (†(²®„Q&ÖÛ-§xØ6ªµZm‚ 6Ì5ŽHDŽøQ˜lÐae1£{„lÀÁ<Í»ÀI$ëüÏú¸}þ­øßVóÇ9åjzÔ>¢õ›\:ãkq­"¯DƲ3qSFío‹Ý¿õÚb7#2ÇøðÝ"wo~ƒóuWxœŽÓ$3›-ì÷"*ø›û¾B¥ðí}Y4z¡åɦA G Æ†™w³ œ4`£R“¶ífÓåt²½´³!ÈÑN;«…-ú@˜0Ó» 0’dÞ>—‚n=TaH)1 j‰hª ;³7&|ÿ9‡×/Qæ$óUÌÁ7_¥ÔûDw\afLÊrPO…ªÿOö¿î`4܉ž«õ&¯¼z9a¡DYT×v!} W'Èäñžßk޽Òq:=ÑÇÐ&¹j“I);•¡ÈLü$Ò+Mö&çÛò”ÇP¡6Nbe…¦NÈá„ìd£]îO¡A’3ríæ; ÁNÜ•¬‘ð¡ zñ߃ e:Xìæ;:G®ýkL+8V(‚ÎoieÁçÇ&ÜvEWË£Ðæ³¿ÔâL„Ÿìq ‡ýŽƒÀÅ{G©ú‚½§éoØ¡Kù1‚¾Ê läò@¾ÓIÛô¼Øg˜Â,X«œ^÷Øznå’‡(ˆÆ=9á˜Z¦Ã€§Ž©–çœ/uŒj²WÄa XÈdÃ:o³ë{R¶Ëž7â@àMb4˜!ZB¡$…¤ACކúzÌ„ìÙqù©:u‹'•&0î;ŸGS»•Ó¿gðˆô‡÷^ä ÇÉ¡2æµÑ̹"é|õ–`hDaèÑô Óº!2L“[5Ë…QhÃÙ©Î;z8Ñ¿Ÿ Õ.Åœ‘±ÐqD¦§l†lF÷XK>‡hLA2ÊøAP’ìñ{w÷ÑïBI™Õó2{„´°¦;Ïä÷ _W¶†èw#ßätàë@U±ÉÑà÷õbNv‹p ÷ù&µ¤w#ÛÌh„Q .ãD"aÜ D “rܹºá&àã®c† fšáaÇ3`lrX“@8\u­êÊÑ¡ŠD€ÄPuœÝ|vížÐb#5ã»xšÍ­;oïûÃgǃFhÊD4»qñ§ð1€ÃA>íåÆIðH˜D¥(ˆ’Í8‚Z1"!îáÇàÅŒæÀÆ;ðvµt#Ðê%HîÌ7/GeµCA0Öe^\*4ù4*êbj†n ­üvƒBBa$ H”âþgE hóéˆ^¼øUG’16 otQ¶ƒÉçÏî…äc‡iÞµ_%{ öúú»kúSЩ$Ò‰Là v%î9¯»7g5¾f ½(‘wmLzžÜü? ψOâãÆêfÿ·îXŽSm{±±|qýhGclèw+¡3QG-S5‡Ÿ)OU.nœGÓ¼b¼ÞûvçIOÉ­|œ®.)T4!T*8ŽUÚ\¾¢iZ¼‘ÉjïLüëŸ?ÜønÀÌYêNNãŽx®ºO ÇçRQ6h*ØíE÷= ¾»s)àÍ9ðã<{ÔG\<}Ç}Ï(ù3ºÛÔ3ìÉ% y·h;z_Ý-·¬Úíðº^c}·Èqÿí|| ^‘ÜÎÎxn¡@ µ‰IèM‚óäB_ ¥·hQ«ú“+vb‘?c¨ E#w­M(öN·z’ÝÍg ņ¸ÑM@Ê€@ð3 5þ6ýœ˜ù7•é!:£Ôª¶ ½Ÿ¶ Ub†/9õTX’6öï¸ÔÙšxwš¨l"9œÐ~÷¹ÜÏAêù3ð·¶÷~9ÝÏ_9nŸÇ"øÕ×jsÛ.8‹eäX;°h>gnÿ_“ õQÙÊ(`Üg­Ã‚ö )ç%-@kZIeOd º«ä«7iÑÚúÜoà³h ÙÐ Ä$* ­E*D)’@Êüÿ™ï·~ƒï÷  P>ͰJ59üêO:‘8H€‚s(2H‡¥V, |t¸UŒC••‰çO¥ô0ÏìçÂÿ¯áœu¬Õõ¼ž.O!±f‰fÁ)¶ZUÁª ¦‚‚ðþîÎ<¶¯jé´;²š~ 8®Gs9/tÀ†Ž±A ==>vsœî–;EHÂ|žŠZÇü÷§“þ´~°ùþf/½l€ ¬bi–(BšÃXB¡ý9›óüœ÷›ò½Ÿ•§—‚:87g&¸Í ‹$²²¢Z¬ýJ Õ5Ûìr D3{mí‰68Úl(‚šƒFYeè•w…ÁÁqWaW­Y#ˆÕ ±4kO¿›s9æräœ;eѰʈØrÀã‡.ÿ&¸ ñe65»¸ 6a0¥¡G9•Mr–d'.¤Ùjê©Iz iD2+h©sæãÝþƒ UÐXŠá>-ý]4ïîuA! »¡ïÏÕÔËÒošc”ôçÿåvEŒ0ú¿ }Õ¾ãžÆŠ!‡"Z‚6Cy;ydÈ÷±Ð}GÐ áÇf˜%¨˜†ÏwþO@Yßì˜}÷Çðy²ÅU“Pدåÿ±«9òý|ØB~Éš_ñþO néo¡@ž$ €ñ°ñá5³QELú)ÊÚÏ[€’ŸåÈûÓ´ €úÐJf‘ ¶àÆÝÀgôO27)§|£˜íÖ¢“[¸‹Èa¾œï·4ì:~Ó}³DÉ G£ê'4t9 yÛšsÁã=•Ï(nÚÝË3NiÛF“{;4!‰ê¡¹À0@C7«ö¶Ž»OÙ.qMs|A :/¶áý‰Õ×ò;ž±Ê<§ô¾ ã­!Èø÷Ðã_˾‹$=7`Æß`ðÉœ¡ÆÛ"S‹ŽÒ¥·Fsd±|›áa£{íÛÞÚÎïÖ®e¨C»v"5ü¿b8}¥í3¹Ôü%÷¥á{7wnÍ'’=J½¨âK­»2¥%8;&D?~Ý7ÊX¢9ÏLW~ÔQMÌÙH’džÝqŒ#®q½‹×Íyq/okŸnçbNÌÃÔ9ÇfèÐäIÙ‘Þ§¹á—®ÚXpïÛ}zøá¹%pû}ë¿ögÊÜ·U­î[ÛËÎU÷ì¹õ=Þûïät;Ïá M‹Cä{ùLÆcÕË29¦fl2€‘ˆ,+  ä2Yñ, /ä€1€p3h|¿©²ëçk :ГÊ0’@†Å)$ŒŒçü:}ÍÂ÷‹Ò&ÕüyL?ØìpØ›@1um qß.¦•©PiåWȪ©´‚UCÝo#í£Eî› )‚=ëE^æ ëÞ¨³ø×d»37h—øsáRy¨–x™ˆSu7ï…üM4½Ã¨PúW.î‡yU(šˆÞLXæ'1ób‚Ê;¨O² -‹Ý³W‘•UEUJÊV£‰ dÒ:%4Š__o¿óoä (¿hy ,y´„ÈhÄ  ä…Ì}Ó #˜³E•QM-¶‚ 6e´šh ÐÐcQ±¬²Œ6`ˆiî9÷náYy¯»\*}$Ÿï_VÒû\½FcÙ sœÆÝVfùâos\Ô½à•kzŠ6&fqÃ÷þe^2:n*!F›b94vŽ¢{ϼ™Úš§ÌËþ»@Ysë®ü´ƒfÀ#<ó»“ô¹FçºÛŽKZZ:ÎÔÇîj<Ö#Êü`èÞÉ—’ÑÁ¿~ Ø€¶Nik=ŽG'Èþ<²"sPo’Z³íýíoaêóz bœ6v^jâÏG ÷«³ŽYŸ·å/ %U© UQZ}çà]1|jmj?p2I¿Ù»'êP;ºžÛãƒg )yzqRÆ%u1K‚½sXvyçŸÎíÛÖß7°ñ¾!y‹ã˜üÉÝönóÃï\?PTCÏ]ê]v³y{¸ˆÎâÿ£ß-íÊ„Wt^ñw³«[Ô^¸¾»ñÞJ‡GA}·`pÐ>ù×j ¦éMÞŸ\£ÈbfHL™v™®H¬ë$QUI!5F"Šª÷t|íü¾¯¶ùýïio±ÿŸ¹Ëÿíá#k¦áÀðyAðuFŠÌ]÷»…VDd⎃‚gvéŽ{N€ú§ØróûšNeÄ4uLÞ~¿æIsâ`ñJÜÿv4]Jm¶7½½®]T(—Ã…P¡@(P¡RV­)^ªõåm¶RSê~/Cné¹5âl5½ÍO?ÏàrA–Ý¿5/‘øTK +ÅDºœf}ÿ÷ÿïÏÌåúï=Êq|ªN…}Šœ“‚ÉÛ—į́/Œ1éö6òg_å–-^H×–W³ / ”»@ÿÆp%_û\_üÛì 3hq­›mÍ›¸ÈÕ—P¢là `‡$Eˆr†F‹ 0£EAFÍÀ‚‡@P`T5BÉÖó7·D ž!Ÿfà5„+.4‘»ÄíH"ËI‚Åñw?ê>ódIÅSkCËâ² ªÃDWÆdÖ?+²<·–7CÜÛpÍG–x¶³ZKP’›ö݈öù¿T"~Ç¥„þÊ?cî¤KûÄH¶½/; Ï^`ñßjˆ¿XÓ¬|¹þ÷èuõ=Wéâd 0mZ–æ*$XRã•*3!,)AD?Ÿ}¿|ú9ç«¿IáÙ=ÓCpe"q*SŠe9 ¨‹,ÑXhÃF5«›¡ÞXÍÝ ™›ñ8Yìpp¶4Õ¸!ŠÅ§rªÍä¥÷>ö¹›.øåîny斸ί[‡³3qU{•GÑÆ“ÖðÄ¡æîßW|s4ÕZÖlÞ¯yZáâ·œ íÿ¶¾;þˆ 3k…9ã’`îÌì!ŽÇq6°þP"w1,‹áßÇx E6ÏÛ@C¹'å^ÖH.ó!ÌöD »®ÐKXÄ ¹ê»÷  ¿Û·]uãÕëÌŽlä£RêÈÑçvHBI†B4"{ót.,¬¡Ë¡Ý!ÆC@‰!ŽÚùDcC·év‚k&æy…Ojª¾ÜëÓ=KŽ&^âÔ¬ï^¤µõŸ‡n@¬°ìxDׯ'™ò#‚ÄA×gi”“¨§ge‰ãžüw‹Ï^ÃÓý…÷óÁ¢Ã€ànÆqE×7{¢™Éi³;wî™2a£çÍI¦‡Wü­Æêw…o·’B{în öíÇäkAÝ{ u™0p¼âê€\8Ð C¯Ü Úõ¨æŸàÌÑ·xÌñôQuðÖ²½¶¾ô,¶¦q~LæÙ‘5¾Ÿw3;)ÀiJr'+j"mÐ!c †Œ`Ui1¹ok‰ÖÞc_Í[gû_ÏîñœN_Käíz Ñ&, a”2(ž2D—çІ›ßÄ¥4ƒ$̇.œH,”sÂí*:þ«ý¦Ä–ÇCæ¡¿{MÄÓë¼zí^‹¿ÐÏoõzão:©å\î!üï:ma캊?Cù¸ç­¥µÖâã*é_‹£TýõâfVáµÆ®mó…üÈž-qšKˆ*¸åùù"«Ôoš„òèÊ~»o\Ô½rÔUi –R¹eWLÔ5ªZÂYU΋Ê9Nñꆟýsý~³°ê:©Ö39k/dÑ…ÓVý ¤^q£€‘æß²­¢=tzFC=úúv×=Çâ©_„á{‹Qð÷ù 0ÛøO¾o¼ Oô1’¡=1ùåS]uàSþ¹2®²xŒ˜«eï°1ç1Z°+¿‡ƒÌ}n[?Œ·ÓR»·t Ó€¨+™â¿£ŠA ÐqR+Ü:GÈ®Ìþ‡Eþg—ë½ßÖlw¸‹>c¬óèíµ/ÉYû:J=Guäúšo“ÌYÁýŸ…W÷ðu]§•Ãx]!ôuü©šª¡”“V½1²½y$wÝ£ô§÷óÿ¢ »Ïâ¨Bß'ø],ÜkK|~ÅøÚrõ iè¢ÎJ84pQ$šÄš,ØÈ’F¡ $Ñ0öøEo5NŸjÓãÝšyÑÈ‘ƒ>X4®tŽ4ƒˆÍõ<ï7¹ò»NÛÜ…RùÛí-<ü»Žÿqâî€Üž±ã‚0R¸ÛôµÙ@>n7𻄸‡5»f2{àßËÆB¸Û”8ÚÿYNÿ9åñÊ¢4I"ËùEpÅp÷p÷}ÿ§éLÞmÜ÷ßjjhäoC¦üÁ‡%ÉQÁZ ,UvŒ4"ƒ­&vXi¢ š4Û6a³ š$m¢ý䃵&ð…¢Ñ èŒçoÂŽ1Etwd!$»•mŽòî3ê| Üj"8ñ2sÌ43MOÅïø_“ÓkNsìíµ=øÿWñxï8,0`ÁC Š|Xóƒ˜8 ˆQø'ÄŒ@’wWPzuF‹Œv{¢ã¶Ÿ=—.®¿ó)ëd³zæj¿õ DŒ2q) J@×bƒšT³ÏÅ0*ˆGbÁîùë;P¡OséýͱüAÍýïðó~ãòù^€dá³-ào×DÁBˆsúŠû2ªRÌ÷co Opžš‰NÚ5I\×ý>?äÿÙö¯Á‹~µ;óŸ²ÍwyóQ9yÇ'^eÎÜV·ÖÐ.`–Ôß­=îŸj2;Íx-û®w¬ñ$h¾9N3 €\v»¶ç˜Ö]"P0¸apÂ`ͺ !åM@@=£Ìú¡Û!éŸ" üV^ªkW-žñ¥*–x´°ÁyR€ Êmbã¬AaÌCX«JðÕ£—[ÒGå@Ó‡Óô»/Þ¶S uþþßþû»©ÿïwêÿýsÉÉlù=×,ñX䜌õñÐhŠÂ¨€«ʪ±{œöåÎUhìùï—Í<è}!BüœÎû×Ýêz¼Þo×ßzì÷k5‡4€¼&ë…ê I«T)JªiB¢„#T¤ð:þÏòí­Oåaü?ÅÅÄ>ydÇ¿îGD™¡É7×»†÷ËcŒˆ3{š'@åC]N×w¶®;àéG\q½F«êÕÌ\± 0®M{Ã6Íò 4uìx0ò'‡%›s…u 9íõS6† öïòÇ²Ã¹Û †áÏükψOÞæª¯¾ÎAÎÎMI¾ýr=lÁqèî! $$J9ãÄ5vè ȹ4—Ù H-t¢ß¸ôœnèunr a],džk æÙ{•Øs»ÇŸEß³Íx¶OùûÏCé~•¯Ùö=V]¦Óìæyý¯‡³ûû7] F$‰‰¥Ç҅擇÷»[|€ô¸D3­."œô šx‡ý²ìAú1ÿ/¼y{&Ñ·7›…Ã6éw¡»7ÀèwÑŠhï¦xæ~d”~éø¬Þ®~øš’3´Û¤qÙUlRú讀¬*¦òUiïqs6²‰½G !ï#R—’ÝÄÅ%5¤ñ£.kÿºõ8d¼ZG{Þë=¡óq©èãXÏÖMß#Öv‰–ÓñdðïÆâá Ïgt%|`éâ̰ž2KB‡º+ NÜÙ{­.¯3ö{ogÑO´OÓÖ>©÷É•2=H|ópÆú3Ï‚Cné/ÜEtïâ$Âx_ päP:V?4uRí•/d¯ÙŸÖa‹!9[{t¹&A7èf¾]ÀÚr]g°bšx¦ÃËÿÅwgË@9Þq_Ëœú_Gôáè;u^+5ÎèÜñìÈÌ(2 Iç"‰ƨP|DSËGö2¥Wä|Ïì³WÑ£tHã’"B9£ ŽafË6hb )ѽEŠ ŠO¬Ö±àÜÙ™¹4ӛƻ›¹­?÷Ÿý¿s÷ÿÚv?ÉP§§Ö|uµë¤ÇL^Á”y:ÆI™…¼ÀcÅ‹([¸ç„î‘âå+ˆƒ†‚'E%H¤0ÃLID›4Òl²eµXfÛA­ãH‡6mƒjX² ˆ-›YTPå3PÚ,٢͖Aƒ08‚éè˜szÅKû¼×Õ®¦D<ÛÖÞ爇¤ø›3YÌNï‡Þr#aêùhNfŒž-­MÏòHj“›ž¹Ä%Gø Šæz—;d´õûÏì$èñâg· Á?Sp_mmÝrµÞ›&ß·zþ5huêóYñü¿›÷kùK£AÀ.î!O½ äŸfôŠfº¯˜Ò&¯o‘nsÃÇ%ç1dú éÃïØ»ÙØØƒ KÈp(’Or³ƒ³ ³5âœ×JŽ7¯“öQɆÑ2çEBI~ûߺ{ëØNMK;Ç’/¨‡ÿ^I®K=¤% µ¾ç„ÂWª&›ÔTvwÕ‘}½1MÔ_š ôåqÏäI¸Ó“qÒÿ¿‰889öx5TEPù2Á¢Æé¦É-¨ñÝžGë{ñÔëhWïZ§”/K–·lê÷®ÝaLJ*¿{寅àh°yëùóóQà†€ìrOAÑ{±¬×‚±›ÐWsÜLÅ ŒQÆXrµî:_ì3 q µ½76ð¢G_÷þ[‹DŽw x©U¹‹¹î¨¹·`îÄOo)z!¤5.sGBN^éÈM¾5®Úê&2_É*æûY$túø‰úãÃF˜Ù) #ŽA_"‚{n7ËðþKá´Ï®Q[<óΧ!ú‘¤J9âõ£Éû¸š£X&‘ÉîhOØ,óÄ)ßcF´k·4Phvg ¾ùv7;ÁQ8ĺㄳ³ÍE'ë»wKOª}E<9¢ ˆ†„îÜÏ']»öd’HL‘ :ß‚¸‰V-oº¦´ûg÷l°$•ÌçÉ#‡,®¦†±¥’x®¯Ôºìü›¼Lþ3ïüÍwùzž“…uݯGò;>Ècç•'EbÕ«²‡LBš¹@y„@PMÞ䫨œiI¢<^@€9x u–r¬ÑÆJ ÏŸ0€B±¡ D‹ü-J—æU—[fO’Ñ •Ÿð¹&°+øuÏüüðù]»ñΪûþË4úñ²b”¿zվ淸²d¸w•zyãQ¸ÖøÜi÷ÆßOImñÿÖüÿöÞ5K·ñÒGï—nò¼kAÅ\A€ë€?¥,|õÏ:½æ­Np·›×m¨Ç}ožxªæ"é(¿é¯ÇŸú?ô?Kýô>ó0FSN 2‚)ž¡ÝôÚ<Že7®š^DT{ßž³ZÜÓ€æ»ö/÷pbE£oŒõƒ}•µhÄK—‘±ñÿ] %M~s]H¬r+…‚'FŠÀ–ZL}Bö5/“÷ú”?›Œ(Qƒx/ {f”Ý6T‹¾€ôãíÚ4”úAÝÀ3!ŒŠc$&D´µ[–q ⸜&{ªã}ãÄÿœ?ùΙ­†ZNNÞ£—aZ%D{ ^9ËÿwŸî9VâˆOýäò÷JÙ€f¢BÄI÷¢(ÐYF,ѲÉE›XØHYCŒXˆÔí¯y– áí´a¬, 3¦!Ë2¤XbQÒÍBûÞ‹ŠåzÇÅ×®áá rœýÌàôùS¸í ŸŽ~YVpŠ ¢ˆª,32Ý•c#¸{ûªÞôî=ÇÞMÚÔIfˆ6X‹' ÞŠkˆÕ°f÷›£Fˆlfr Ñ£Z)´nGv ,AC!‚'fVáb ÔUÿ#ùÍG<4ñQzx®Ó£)—ÅϽèä}ë76«”ee»¿uDäukSz+Ž'g|UÖ>:8—\jÖ÷­Ñ®f·;…½^ê·«»¾n7:ã·þÿhA—wý«ÔÛ8è³³?]›ºkxà yh%9Ôu«"ÅÌê ãàívœ'µÉ}TFÞʦnÿçø9\j»ö¦©~ØìRÿGú~üò„ 5ÿÓKE×ï'^½„šoØ¿\g'ã;s.½Qëm“ãÿ£G[rEÝ .=ö›ººÀ×s´iQMEøãòîm«†áëµcޏl;:Ü ¿9[ ©1®™=wã<çŠÏë!•³eÊìnzo"<„[´G&ý(—ç|n´mW9°W~[ŽëU0ŽFµ#" 3%ž-Â'»Qgc"äŽýÐ’Hp.2ÙßS<Qƒ•ÕºÙ9IØë§žN(5¥€þ5®Ø ¢$:~¡Iµ%ÐgpÚ jè»ë·Ö™ÆÀÄ›‚GñsH}Ž8©0öí߸eùm êœåþé6!*ÁT¿wsg©e‚%ö;!‚N­XQfp§R0Iª¶`dFa•и¨j$IA'>M˜½~U’ï®ãO{ãØ9ÍÛþ;]W3HðÄ?ÕCm&#l‘Þoò°åôùÌÊ\TÏ1d냌?ø‰ö±ýqÈ‚h|Ÿ8wk×əӼ£\9áÊÐ\8óÓ݈¹Á¶Ê s²DžÇÀ¶Ù¬;MRAÈYéX>wÁíú„¶CT¡4àýI”‚®A™µ@=80éÀ®S“Ê!az'vW-v'DFï90 &3õm%yCÕY"™$jµ»ªfîë«[ /ëá\ZÂèØÕº¤¼Ì‰yµÌ5”½Ö³á, úŠõëxJðUE F«ÎÃ,¿Â©¥Á=ÚØÃ5nM활•A¡ž×nÑ3>UJ\ŠOpên½öUÉ£ V¬âÇ*_’²¬:ý5º7)y[ê]å:8HþýHR M_N/ß«þWåqq~ÖDzB©^¥ €Œªpç"ˆ¤Φ¶Uì4þ·ÓðºO­±è'¸í±ö?g‘ê¿·õcA2°ös¬›æpb`ÔR;mû:+Ì2záâð8.p:#îò¥üÄ<ÖzÑ ÑÖc§²°^†­ûô ¡ƒ(.mGìt¦ß¹…eÉ­³¯Š»R¸%ßn¯È¶½}"n¯ÑA&‹Ruäz<µVàXƒn”ÓÉÄrz¢Ex«qe?ÊÙ‚GæŒN}æÞiƶ3÷d«_‰äl×o@|»¨*ú½¦wñz¾Å•GžÂ•K¦™¾ÈãÿáðôIÕ}` Ê¡®h9‹ 0¨ ˆÕX²¾å3y¯dœ´@„0QHy¸¦.í;ð°‡óþ« €°€¡Bs°6¸P õ/]ºT4h]9]W7q…ÌùD éYœ3ÊΆÒG]ÓhœŠÆÁK¥€í_®†lû*gETèùë¥ýhMm˜/¯£"È©¨5PÎuŒs„¡Îi®ƒÍ2`>Dƒüž›"Xæ·ÞÓˆm;£û瑱ËT¸^ãó*ÐY0#Rƒfÿó–ü”‡ ˆßëT¬y¸÷R©}ÿƒ‹ï6OÕÞ}þ‚‚îQ¡ #D’Gq¥EäÍÏzÃãz­óítù-7Ct =”WqŠ Àòeý+òS•®²Šñ¨ÝkÜ8ð;÷ñô¢ ¿ô?ßQT¯‡•a…}x&Ü{Xœ£šð{z•öþ·¢Òªj;‹6Ñ—Ïݳ‚­j¤¸íSALÏt¾÷¹ðŠÝBÉAësÉ/¡=©]Yȉp»u­[‘É"^ŸÍ*׊—ì&þ>Ë•­mWÚõÒs_‚ú­¾f*@éöüÕIbÝÕ3¯{;‡}áÍxV»ÛÜåÙåï ¸sŸó·ÕeÉ|xê £…÷øÖkñaÿçòë;u ×gö¦ý¤|§šî¿J"ü>û;åCJmÂ~;všæÝý•Tâã—¸ÿÜý¿³•Ägüi{/“ˆ:™NfIg•…Ÿ.ì¯ÅŽ¢›t¸–ûæäŒ»­-†˜,(*™EÍÚo¡C‡×?wèþ…g¥ªeŸ_Ëþ}F¹DF'GiϸçVwCï pGÛ÷kµÜbäî#Ž$¤™}ã\cÂߌ¹Ý^æW©Ôg·Þfhêøx¼ãï{Ï‚˜ÎâHLLÉI[EµN@q|¬ß÷¯·?³f˜ œÒU†,Û¬‚wÓA®¬Ëâ;øˆ2n>Ïò¯Yòÿ¼ö>½ð½ÏŽñ-û×(UÐ(/&Zâ“iex»ákVA1q L³æ|Üçlß Ÿt™Å£Ê30löY·T.62©èþä¶ÐÞH%UuûRÕ¹ÛcË­Ôx~ü`®¸®]F»tüœñ€£5óò4”±þ„Ðù5¸êä¢(moåß3èÖÌQ5…F¯9ÏÏÁ³¼P©&s¤ücƒŒµlˆ<À4M,åTt›-þ«ÜH!qpæ™Ï°˜0g>ü®Ç•Ÿ¦Ð£J險©€Z1“eæYÈ'* xùYÝÝ–¯÷Jú,ÓL#=Ÿ‹æÜÄñÔÍÙ‰°P„R"æl šžÄZTb‚ëPZL”„d$ëÁ* ‹*b{>ÕPS~ºPL€«$B@R@HIAT*0PUQEUUQb1V «Š(¨€±Hª¨Å"(¢‹EQA*Š(°UEbÅE "ÁVHª ¨ŠAT"ŃR «"¨)( ªE‘b¨*‘b‚„ "‘$UPX¨ÁAUEQTQTPQEˆÅX*¬F(¢¢Å"ª£Xˆ¢Š,UEHª(°UEbÅEHH°U’*¨*"UH±`Ä‚ªÈª EŠª‘dXª dd E9§%iü|ð¾qõ»hþÿ龎¿ãžÛNÕÏ÷Ë`½—BN:¾RY‚"#‘ÖMÊEe []wRIxA3€TDÇê/’Õj1ß½Ð5·µ¨Jý{´Ÿ®±z]„“›T©. ÝNÓÊ5»¶·.c›izãëz¸Ú_×iÕCFÕ$±|Í[\¦‰£PÛ‹µh\¢ôÔáàøGÛ’®¢"ãЀˆQ""å(¨.ŒÍžÉìhé Áˆßœ)ùŠNXÝ#äIhög{Óvqgp§ {£Š8£˜83ljŽ@ò¦ôáN$éN,ޙɛó‰8“Š9ðœ©õD÷ç:dT ˆ`#! Å¡2È‹¥((¿ŸÆç¶ïÃíbqÛèÛ+y÷$Ó]Š-B "HA‚€¢ ¤HŠAB(Q‘"€¢ÀYH¡ŠH°"„QH ")" €¤ŠHÄ‚ŠA"À„Y"€ E,„F((ˆÈE)@‰‰ "¬€  ª‡ƒ„ "E ¡F( ÄPE (°Q ˆˆŠ(¢‚ ˆ A)²€ Æ ¤P Ä ‰"€$@A‰I P"ÂAA’–I ("2*€>âÔˆ‡/·¢°÷žï ÅE¨oD[ ,´Êpµ„¯B5àZȲùÏ¢‚2ïPûPÉ?cB¨ ˆÃv©l ,"Á‰¶T­„Z°D¨´(Ã"ˆ‘–Ð-•ˆ ²[dV"‹ ÆE¬¢E¶¶ŒJ†I `%ÄD¬Ajóú\Ö\äÃâ¨.#ì𜽺‚ØD[)ê#Nô¨Ä-*ˆ²ÅPX‰éµB1,* ±ãú‹Jò*Â…€‡à¤äÈ) ,‹"È‘R" ªŒb°PQŠªŒXаE`‰éRŠ„’((d HŠ*,F"ŠÅTŒ}ÏsÖÚ]ÁD €H0""¹Ð"Ð H°b0QEXŠ’Dbˆ±@±AbªPQŠ€‹×érXÊÇárÙ2òïæ]ª ív7¢£WÒÇìŸÓ‡ösú›UA|‹eÌÁA|/Zº"òԧ@$  P€@8–‘óô_¥ú(yGmGn—& uøæ;x¾2£;ó–˜5ÈBïÆœò¦ZÅ ið¨È™'nhoØõ|½kÏZ{0ìô nW'ÏR˜„ºÖ·v²wP";@c7|gSŸ°)L¬¯¬’ùÕ8®q.ŽˆC%êœýž#ªÙ÷¥ŠQ¥Å.ýoÌoe¹‘##f²«ß±ÊìãŠýówçx¯»ãÝ^at¹ïý¬r+ÎBé Œ‰óà•ࡃ(A‰0‘úØ$O$CîoH%¢H‰¿ÁZE6£EM‰AnTFéPX iEíU®°$ ¤€ #D:Õ‚—K* h* T¥AqZ¤E–TTAD ÷ ‹V¡Ae@ª)(ˆ¢U¦Ô* ul °Öþ®×Xˆ°ûåAiZD@b"€&P,‚©@‚2E¡’Id( RD! ‚- DXÅT‘"À‚ÂH"ŒdH„QRAdYd ÆUùPZ„ÑÙZZ‚ŒM®Á®â‹‚x9¾›få1ÉbÜD`hà™hD#ßm]“Èô]màW]Ý£VÌ9¸ÂJä¬Äk/üä(D@D—H \pˆ€‰©/1Ɇ+ü?C°,~¶q‚<`_¹AwS¡õx_ÕZ@~ÂŒ9ýÀój g¤Ù sd;`›:ºžcX2l8²ë¿n}Ib “ €BQPvD€@ƒ•$JòT"¨0m܆ÂÙ# ªÿ{Q„îÚýv{9¡9s?‘;Þã¼ü8NÍzxzß¿ëùŽ·ÚñÚî¸Ëõ¥õCߪ&Rž>ðl<§Œ8‘O_ÿ½Fo²ÇŽ]ï#d˜ £ÉÜ('¡Ãjö©«^81q'+¹3ÉÏÞmÛÒø5ÛÌ lcy(XXx1$w\ƒŽêkÀ\#kåLü¨+þŸªwÊåeîy³ãp–ì•9øedÑ·@ÒâùÈî%ÖU¥„-²ªŽ+~¸æî>Ý©’Š—ûÈÊÝ~ªêã[4 ‚Q<3å§ QNßA•Ðí€V”Sáâù¯á\V® olBÖ6‘SÑ€¼Pø¥’^húÞ;Ý×­8¡‡þÉBY("Ú€«ìôð§e…¥mðË2îD2œQП#^Ë÷î“Hªí&÷¦mìΫ*…*Hº¶ Sƒç9ä¤ÕSî3cÁÊü2‹4ùê‹2ð3ŵtÈ RÄH]uº!x«‹ïr»5ÿð==³ëÿnÁ}×è¿wÙ×±¾ŸAyþzÌ҂ΑA`u€‹` I Œ@ 60E‚ˆ• ‘A`©—â”ÑAk ¨Ú(-•Š ª"pË¿Gs¥¤ÈV¤R(,ZDcÿ-d‚à™¯2‚Í  Äý"ìX ·‚¢‰f¹+°kÇ« 2iëX¥%ùD¤|SO1Š,QŒ‹‚Ád‚Äa"ÀXAbÁb*E"‰ DQV)b©ŒHÄ©bÄATb‚ Œb«"ª1D7CI ¥R„‰"$]À#¬€à ¶PXšDÊ)QL’ð0E–bàª-(À¥!b ˆ™„ â¶_ŸP\´E  ‹pTH¡# ªªªªªªªªªªªªªª¬bªªªªªªªªªªªªªªªªªªªªª"ªªªª«ªªªˆªªªªªªªªª¬b«ª¨ ªªªªªªªªˆªª¨ŠªªªªªªˆªªªÆ*ªª±Šªªªª¬ˆ*ªªªªªªª ‚*ªª¢*ªª ‚@‘€Hª¨ŠªªÁ‚¢0`ªªªªªªªªªªÁ‚"ªª"*ªªªªªª«ªªªÆ*ªªª±ˆŒbªªª±ˆŠª¨Šªˆ¨Š¨Šªˆˆˆªªªˆªªª¨Šªªªªªªªªª¨Šªª¨ŠÉ "Å€‹PQO0r@ ,QJPXª¬‡&5¬­ºãrÑØ¢èaΠ¸bX]3°ƒÔW1#‡½…cúÕù:mú½OïúßÏÊzMÇÓ½DÄP˜v´ HP€†•€”§9žÈZ© £õê H¡…†à‚6$óùU X¶ió°äÙ¤8J’ÊŸ©ËAÊH¤$ƵÂm„P@õR€†XP¾å a}Ògì^Ȉµhi3Ã&¦Xo| ¶$†ö”9kc,T4dñeš°°Ð&+Š”^‘$n¬Æ04uÞ€Õi6È*ÿ‚é(Vè¨(F$Kº²áu«È0¸ÞZÄ;l1ࡱ ÷Ъï 5Ñïr®Ø;»‹àm$5[D!€lþµ)áiêsC‘¢)D£"°v®£"Ί‚Ê1RQ` Z©Z¤z/ìòp3ÄS¥¬kNgük*¯\ݺ<ïƒ^»uÚQÄQ@´€'3ÕY1òô  GüYP(ÁzT( -ÐÅA'86‚z*D&õÐ~Î.UEUŠÆ*ªŠª¢ª¢*±ˆ‹H°A¢£ÀUT) U‹ @@‘"ª(¢¬V1UTUUUUŒDXªE‚(¨ˆÅƪ €+D" Z-<ÑdQÅQ Šª¨ˆŠª*¢ªªªªªª¨Šªˆª¢ª*"#Qˆªªªª¢*ªªªªª¢*ªªªˆªªªªŒb*£QUUTTEDUDV(ªªªˆª"ª"ªªªªÄQUX UUUUDUUAUTEUUUUUUTTDUUUF"¨£UUŒUU#öiê‚ýéç ŽB‹ "ùb‹¸ÅIù!@IHˆˆ‰" ‘" ‰ Š€" ŒQPPAdQˆˆˆ ˆ"$H" AD‘ˆ$DDˆD É`€‰"ª¬F $EŒT@ °FˆŠÈA" „’DÂÑAF" ÈŠ„Dˆˆ’D’ ‚@Q"ˆ" ‚1$$DDD  $Q‚ H ‰A"$D@"D! 5Ðe{yÀêÈð*ÚÔÝû -©DVZ6´¨±¥¢ Öñ ÈËF`¢ˆÂ)"‘H29`8&Íù ÂX IJ%"„ A€dX`¢AE€„UWQ%Q(æEAx‡¸D°@„2Õ¹u¢/ªB苉©±ƒ·ò°CmÆ;[d\½¯Î£Jj? åÿ9ò‰€3>¨f`f¡Íc8XÅ¡qAž„t¥]´Hzˆò\¬{…cdHª¡JÖæýâfŸöÅ¥ï:y`C UUàÄÒ@d­|“béd´ „‘ :O±n4J JĨ Ÿó{[)V/×^åóš…M" Ÿ‰‡w*Ê è¨-Œv{ì ÍzÉ„Œ†) ¤¥玃„ ñ`ÃDæzÕ¿ˆÂÍ áÚl8â-5!^¾# .*ØÊU-R)ôßniÜëÉthGLlZ¦k?G[ ´cbZ¨£bÁQ†©Ž(U‚ ”j~r±ÖZÖ”û/éèÃM-¶Ó•Æ1 –Á )eJË-QµB±5Meõ®“F†T¬ÂÞËçw©¥ŠYD­ýƒY0W”Ã^SxLkJH”´³óòà X(2Û´©BÚÆêތՖÖ%)Z‚±–5²Ô¼9šJÿ/UÁ´m…j%©hŒakÝÃÓÎÈb†™ ˆHƬ‚Ũ)‰"Šb¢ÁIR,¬,á%@íˆiR Œ6ÃN2–ÛLʹKZÛH4j,cZ–QecN8…ö¤ 0 ’ Ub©66dYJU)øsž¬x? ðyõlIE •zéå»ÎÈî?Ö7úã[G'ÿ?sûKIÝêçz–Ô7®wyäsM÷b[J–YWfÈ,#åÖ e®PÿF÷Þ½= »TÛuNÃHÔåçù¼„¬¹q+¾Á_ÙÑ€¬ÀéRŠÖ¿hyðºÂcÒƒf<x¡…¸o7.›|Q Øö™ñÕ›¼âÓ½Î!"D…§¿ü`qµ¿8CtþÿèêêªÕ¤mF«’êÜ属^íз¿N•.mUQ©üËzos¶µ0yÕ?&k5nFÛB´É’y™‡‰cŒþ½<]BéjQx¾ỂVqÚ¢ß]³:œñú"É€iú½ko£à-Øwwí±×$Ó㎳{ŽâÑ(è¨æ@±f¥€ šœþõ¼f:¼ŸrìÖôªèÏX(È@?ÖEk&4äüD“g¡lÝ«GÙE'öQÕt¦ˆÀìÔ¦[(Ÿe)÷ËÒ1Q²ø°"6´=¹LªGìd]ñ‹5«ûÔRàV{‚`M‰‹ßì¥ÑLs@:Î:ä{ñ/›Q4¸òTïùÁ¤¯JSî¨/ šÝv.ãŠ÷,ôQA|AJSãsTˆ+ºUr›%²)øçö?WÄã¢y Í?Ѷ;îkdkìýœ]_‰ãžÚ¾ø»ùå¢ßnÒ`~†¿çÿ¯“á;À /€Cë^‘GR…ã#ôÍÅ5»ÃåFŠi({|X?sfqãZñö}ϼ:D²3«ž­­Ò#;f"2ø_ Â&Éj9x Õ«æ¯# âPµ‹;Í"Eº¶ÍÎ…µß(Ù¶%ijd_pU5þ±NÀ 5=WIXÁq#¬ÈÔÿ-±ôhÕh ‘ö»…™DU9Ìðsp¦"@VX!àPóXŠ„PXEˆ1A`¬PX©ËTNx) 5·rêÿ¼æÿ'¯ã|\9vHR2Öç"›íWÊÈ^ÖGN»לÿ_·áý,ù0œže„pœÚ€ÝUÉdTš€§4±A}NiPZ(¢yšw§ç_ÓÐ~» Pu€@Q@ *ŠAðÚ“ÍΕ”Eõ•㾯R¶éú}F®!†Kh–bÒ!mD¼12†£I¤½Ü'‘~`‰ú÷Ž×û×ò»¯‡úúµÕÛ•Ǫ O«ãómoyÌ]Gyÿ½oÅ[Áµ IW¹%±P¬|<xÃí?gö­¶^’“Û‰‚}‡÷XA@ D Ä 8c'Žx½dÚ"&Ø+ïkQöd´æÙ˜¨Â,åÂàï©Î5­8k÷‰Ók€Òîß©Ï þS”W´r'Ò'¾”q`Õ¾„eŒ' úµópVPÎ錾0ü¤¼Tóq‹…A¸9ÀÁE¹“@¸ýbxõºé–ß•ƒNéØ_¤’ºvËßɬ.?LÖ ¹NN@© W¥á3„„>¦ÇòÖü9ËÖ¢qŒí§KÁ”Úøò!P™c"ÉÏó\­b@@ ü¿)&`¾»ÀÍÆˆ#Ýa%›Ô®~TZ‚à‚_ö²áP"ÖP[ÀAT9  5a5û¯Ëùö½óMö-ÌQ7žâ*tTÄ" ""ˆ‚ˆ""$‰"$H‰#"#B (À;Â$&åù+š²%ˆ(¹¢uû¶^ü~_!uãõ.ÁêÝgÿž¿âØl}Øj>vsô¶lBMºÔá3ZgÁ éq„Zu”aH¶’I׬gcü@rÊ(v±²ýÄÒÓû½žàœœÓly¯Üà«/pó*åŒ|Øý#Øø'%”«é–¨1G=ý$à‹’&·ÛX±6Þo}‰"ÃDøTºù „ÒHŸOw¯’¸FDé;Ô0ÑŸÓã#2% !@Ž“§Ð9Ëèþ¦§!øõ\oÞ^'$Ä)'Yá_\®þîÍ®v‘æ¦OþîãLª¢yDAÙp}Z…Tâ"ŠázÝ‚¤[TÿE¼?ûþõõ¡ã|Ä4õ¾ÒŠ:'úýýw±ÙüÛQUŽM?÷¾ZçY¶¾·l )íÏ*`±šDÌhÝéûPHEB2 HU$I²¢‰Èe·]šáAnþe{‹^#2ʪ%>m߸Øé n;%ÙñÝ9 !Y ÎÉQH  &ÕíSŠüOà|+™{Ý».›_.‰DH’Qåî¦ä3I‡ÖIþ9R„¡ ò”î¨/Ó¢ »ª ¶ê‚Ñ[RÒ€tUQAwû¢ë P.c_hõ¿Í_Jwÿ_rüùžcCÎÛüíãâ¶3x²Dz¦cóù;(,/[øc‚½ö–™PÅp# í~Ž7'5óúêªH’‹†XÚ>éGHv.cüŠêzËšºðB•Åïî"±}ÑsÁ²Eê#d/lQ·\³«ÅL 2׌Íê:o–æÿaÅûÜgµ™ÎpUÂÁ@%2Bª¹ÚçDÊôú“ÕúsS¦âµd-–÷ï+‡;ç e¯Ãƹº8˜2 AƒUT`Y¡A`ª +"Äbƒ` Á °‹AF1V*¢1ŒBFG‘ì­ý ÝŽ×SâÔa b- ÿ:¹QT"‚ìí#E‚ÄR "z›8)žîÌæ—ês0Š ÂŠ%¨‚¢Æ_‰sÀ‚¨`|ß'Æëœ­¾pÃ(¢]§›o³Ñ} ê ]Al(* kŠ ±ùKû"(6Tà@Ì[T*ü¸`EÍEæîddÀh=_¡ªõ=«n›‹±ºÚ kÆøpûÿñÖþÏ+˵z®¬bº®TŽ=;j/þ]J÷].6”¡H•£Ö¡»^·õ¤‘’KÓªÏm8Œžïašµ¹>žü;ÆÿiøvË÷»ŒžcG†Úû̵›GË*QêPûk±SÇŸ"õBÄŸ”ã±.Q¦C oÃI”/9X_eú%);ˆ ¢]àNKµ‹£†Êà¥üþL.âÿbzÖ§ÿަO+zyxS:ú{Wa0ÑÞ_ ²7p œÁ›ë7ãÛLðaê¼÷1YÃW¬´à²ž>õ„¹Ù«R@A„Ú¶ãFj« 7^f+ž†ªC>4[u.pe5Ò‹@D“…ö”½ÙŸâÆõ ¯nE_¢xI~t¨ ¢‹¬Î éýŸmJ-„¾Y3èMEA @'dÌžÎ.½(r)6­Ê(Ïv«V.ñXÁ”¡oàe%"ÛbI\¦1iÂýàœ¥™qÂ|÷lA2i[ô³Ô¸×’´&¦Ì œê¦qØÂap-Áþ«Â\»MiÖ8ÅÔhmñaß|Qô<‹©(aD(9#üZt@€Ì® µó±<ïç„@@D%“Ó{iîx.×óèËò,G‰Ûq¼™ÛGŸØ¯çó8Ëß÷Ýz*=x*>¾c¨/öÞüûÃóòzékºt˜„îvQ èTÕárÇÑÎ[ÛõZ@ó3_Wcàá{47µ@<Š ˆ„b±‚ET‚AD"!‘‹$DŠ©$ˆÝÿcí¢s£¸š€kÔBuJSÜx\e_ÄÎöݯ‹üáò;j¿àÖw›ÜïOõxlqæ†cOÓ þð²G¤H;ócæê/^·¼žŸ]?„Òq›Pc"wpy {¾¢ÌšËpO§’‹_¤#6¥~)©Öâ?ÿPæ¿ýk«QÀQž–d<–Ï'È~¸ÈÒ…Žv¢ýÀX<»àøœšZÅ·1´˜@!,ˆÑ‡@¶¶›}ëàûbÄ¥ÓêÑ÷7»7ï9g ª€Ðvæ«î÷7~mþëÓáû· v?%·e®}=ÏÕØãôŽ˜Á­Ý΋ºÌˆ(>‰‰(ˆ)æÄÇ|°å8qõ±×û O}‰´ET-2ÙðEê„ß.s½½ò·àfejਠP¥à]ŒýÏý®…4¨`G¡Mí©Ãr¹Ã ÌŠrëo½x¼/éçµ}Ÿ)ý ì“'ééºÏ¯ÇÇ~Šï7Èyöï5€€Ì,ÿ†òPý‰›æW>®ÿØö4êNy‡)ó×Ñá9Ê·£´˜RkÅ=­O½÷µ¥/g±$†7Øóÿ‚øó Œi1 æªÂ%Úr¡ììbŽyN6Õ‰ú=Û¿²«A6àñ…«±øê*ô¾h6Ó¿«ƒF"ÞãBI]iZO3è‘ñB1±à€üJé:Ú<‡Ïïúmë×óþÆo¿Ý;žGŠÓ`/C™—“ àIÂA5r¨ÒuøïïËò²}”Ço·g ó9~+I›³×e<[íŸkó(X•¤ˆ4O¯È{µšÑÿéùcö¹ºûèp|ïúÑiŸÐÛ7_™øÈ€‰Éîåe8î_¢»Áã9Ïoù¢‡_¾ü“ó¶¥Á|~üV½ù0Ûã‡æ‚ÊMÃ{ÛG$¡ $a)ÕNdZ£-N{iœð²¦ ÛÇVÜZî6;¢£•nŽ\îzò‚i0ë~»(Úù±/Åù’³Ê¥PûHþ›u÷¿hˆÍýW¿GQ¨+DS ž‡5“M;hÓB oéin:3œ6íÌ‘,r®ÚTC¥Ÿ_Ûãk¶þÏÑßÌ_1¶þškËFQÊ:W|®{gÑú¿WøíãüIz÷èý­ö}ÙÞè¤é¦"&˜O½ö­ ¶¡bAed ,òèý—ð¹„À‡ÕÚ¸=³¯ï¯¼ AK¡DÕAh‹(šAEAycvoX9ÕB ”‚I-T3‰T+‚‰÷ †,UD­ÀYØÝæüÇãTQ; o1m$sdØ%õÛh )‘l–K4®(‡Î,û•‹ÀF@+azºÜïÄÙ`ýZ¼1„¡"]Ë4}Nk+ƒ”¸$/¢–â[—¬a*.MAsI{3{÷q±oö…Þœµj»^C+ÂûÚÝN·vçñ±£5LEk>ŸæÁbÏo¿ÝÄm&>ûùYwùý2íæùJ)¥æÛ½>–Ó”µ7ϳìöF7è]q\Õå±@)ÔP kzJš¤9Ãpùþ¹`„-Ÿ :íØòËèõM:—j…ŚÄٟÆÔ¯Ïp Rj¤‡‰ßjèÏ8š³þ‘|Ïu='Ñýð¨=N†‹®Ð"I€’L­t=/¡!‹fë”fB¢BCð}ýв©x$UÓ¹ 5 0T »ßç{–ÖóaæéUM UUyµd=ËE@å´=Ë’ò.x/?56ÌA¢Â"¨(iØ_mßF€Šãö§ËÏæ·Ô!“@¹PSGñ7:ñ5ñ¿ênå¦Ë– "Ý,E¸Tb›dç¯{ÿÃØÓ<¦2ÆZ[¥2œßp ]…ât4EG€@T.ÝLßsÃÝÑïxxÿªƒÒDÙ’,Àå­ìqz6º™È¬Ú/¸?S¼õîÍÓZõÝ!CæÅºÖ¸B€ BH}M³ €–‚ ”¹!û Q˜šç ûÿýƸXÞGíuÝ\‡/Ä“üŽÑ)4Ñ+÷úÇ1 <›¨*>Ûý£â ü'çXþ¯nQGnÇàIÂçüí”þgÆmÕ¥ë-¬hgh0NDƒøñÜ Ö»q JÕ†`}ÐÏéñ“û—]Œ»& Éõm6Í"ƒ"œNLm·Å«Œ¸¨\eù¯“î~w¥Ç–¼ž£¾³‘òþvø…P\OöA^ÉP_c·çö퀜rZ9€¼EÍØ¢£‡ÍF¸!¹hü{PUévì‹m0Pôö%: ÀÂÈ"ò:ßýz›—7É|GG?æÿŽk]ôÿ†÷û”ÙAs³¦²}/J­!ô8!µí'þ-=mÓ.Ú}ßcM¦¶ëz}s=¡Ôq§Ø…”—’ï—ºîÞ5$¸Ï)r廽MrßgDzΓoÆðïúUè \¬¤h¦QÉÃW+œ¼_M‹jå œ7ÑÔ÷Àv䢰Åì§wkW>5Snßt£¬ÍÚp€>$9dàùÇUÛ:â¤_}äZÛ¼ÍKFïz´ÞW»YÚ‰?p¤HüÑ#]Þ±µ+3Òà?  äµ !Užª”¦«–%EtE•¨ª¥WužÚÚßÐpýíËO%ä!­D?NÇàÂNÕþ§«ôW¹i¸Ç§]{|½³î;„d’NÙÙ{¼ßd )ýíEƦ÷áP_V±·þÏÉ­ì¿+Ó<¡?^Ã7°+*$TH ¹¶Š4EŠ/è¢S©ùý¢SȈ*‡ãÿ“n´A5ò›ïÏV·‡V%Î_Á÷¬ÞZíu%Ç‘Jðªæ¶_7炜FQQÇfÁÓúÿîЀ„®ý®-ŸGI¹å¦ñsuŸïµåzžö¿^»â+ v­óO ZáJÜ/¬×z3³i-øóÈ9¶µrBN‘B *ª 8HtËÉ!$I&o X"I>Ø|/Sâ~pÉÊH}Èh›XK—N¢çm½\þ}XƒŒ’Üÿƒï^´ 6PªP°7a§?«53w_<Ômýqe^×¶wj~7‡Ü©ÿÚ\òÍîmÕùÉÔÃp¤Œ‹ñPÛTï†t¢¬êw‚¶âM<~XnÂáÑ‘‡ƒgØ¢¥!SˆÊ®ö…pŸ¥Úv>Ö8œqÜC •) ¸ü\`DDýµíö‘†»yö¼mfb Ô+nÄAMž6Ñ¢ø©Ñï§ùÞ3'¥þRÎte,#—É/Œ‹ÅðÔ+­ü¾sòÿ—c†»žÛõ÷¤ŒxaC0SÌ/öü¯¿«ì1E;0òËô¶V5ˆ/Dü_^À¶¶€Kl–ØЕƒh,…´!m+´YRT%JÀ–Ò[@-²ØJÂ[d¶…´’[d-¤–ÒÚ@¶À¶’Û!m Ym+$¶À¶-¤¶ÂÚIm •¶É l i*Kl¨´€[B[ImÚ•­d-¡%j©%KiP¨TmÛ$¶À­HP’¤*IZ€V°•¬–ØØ[I h[BÚKl–Ð…´…´!m l¬…d!%´’ÚIm„¶À+RB[BÚmY hµ„mVIR¤%¶¬ [`JÔZÉ*[am+ - [`´-¡m [BÛ!m$- V¤%´…¶¶*VImª‚ª‘NMB(Ÿ!ù |²5AOQ?%„.k¨¨ØQQû9^ZÅcÐï/ñù=Ï÷ÙhþÍŽ Yõº<–Ñšø¬x¸D>¿âèÿåd×Á„ȉ $À ”ª°oŽ¿pµ¯X†¼yªØ‚ æKxHHH(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š( ˆ¢žád ,>·ñûÿOýõŽ›ÓÒ&Ó~¢ÓIaKÖóµ%àà©èUXVaY·‹Ýsw LæÚ='½èZœÆ&&[(à¥N§æ¹ß7Q÷³ø®ÁÑðd[½-‹ÈîRÃ|MSûzÊ]L=oý¨¬kÙËw€ÞÁ*%2õYnŽÃ§’+¤œ#HzD¡oãôj‰sæsÔö5Dï¾ … [ È1"ß=h)|ýbU®ú¼Ã£“4}À´d M Ní“xEGÌzsµT®w/ˆx›pqt±¶'*„ù¾Gú×øîÙÞxL~~Û€½Íîù¬qX¹v[‡…Žç1©Ý @D °EDŠ(šªÊ ¢P\}GV(ƒH°C¢ØÔ""ä>çÕÖQ² °K¢¨@AHˆ ;> ÝAS!ÿÍø)½ü¸ÁB๚©>-‡§* Ê ]Av*‚íüŸÙÆ ¢c;€xE>~?kø|Ì}Ø*¨^("ŒE¶M`¢¢§ÆÌs»†Ëd ô=lþߔˎ—¦Ø¢&ëÐÁ N¯À·ð»ìܜٱ-‹clh¨.­ö°¼GOÞé‹%¬7¨ö¨Uªª¢” k¨í‘ŸþCˆgÏï?ç_ý˜e”5Œ0ÌÊªÌ ƒ+=Éf6­l·ë>¿&"œØo m”BÃøwÚ’¥IMoóèëú?ôwñ>̱#Ü…”éT犂áƒUè{?Gt´P^Æá)¬ã¼ŸÅ~çi¥ø&’¾ÜË,ÏÄ¡BXìÖ…i0éÛû}H¨˜…­¹–ä¿÷®œÇ®!à_8t¿myö`’šÞ¢^®Wvmè–W«Š}Њ=Ž#d¬„Š‘ÚªJyÕ®ß#Š/D¿ knKôÔ¨}0I_ÿ®?P~êœäžíÉ-p<™þ5y<kùNS¸°&Ì~¨õa€†.íAÐ4ð{ ¦÷¶}ü÷¢ïñü‰º ßïZðŸ¢v Çï[Owåâµ—“ûó[~Õ×SèS<ô΄hž†çÍò`‹“Øðàö«W·vø½YfêWm­ÉáfÎÈ€)c &"gStÂ(ù/Þë 2?,ÐÍ`J9€` õœÙ/u—ùú$nÛ² ¿·%èû¿el"!¹PY*¾€Þ»€Цöþ"ŸóàÊ8õ§|)'%y!ZŒ=nìó›ˆd ’ΤwÀEªØ@Õ b«ðÍIÈÜx»’&ÞäV9½óÊ­ga3÷U?Ç þ.;’FêéFAúØšAâé( &†qp³pÌ“’Ù‘KûªA_‡œçm˜›ƒ¸E`ùy2eÔ–#Ï,_½«5ÃÕ'*ávVrëQ"ÈAHˆÃŒGºy.ò»ßR ¡Ùæ5¯Kä䯻_c÷n?ûò)¤‚ë =twxž#¥¢/¼€DѲdasM²¡°Xªʯï³o}K!ª\ŽbJzòV gr7¯p¥÷Ûˆ£Û„ ÀDOº:g…CŠ ¤#c£ ¼" pJù]4¬Dm!›DØ{7¨Yxl#TwÍX+ll”rìóûPJÛ°³;T¾u͉úUÈ΢å~‚sIÈ€¤:¦N8ObâÔ©k»Üø€?“®QŽ7C1j ™wLUË= †÷‚>5; ÂÎgFªlHü¼96Ú@y=Æ*,ùŸ«t?¾6¦@x…+²Éx—L”Ÿ&¦¡~óVo±“ºkC<;øòöYú?['òr3Sòíþ4nÁÑñr'¥úìa>ÿæâmø­°÷W`šüTÖ&·EX»ï¢ú›w éf{¯ï¡éùmðÞ§3üÿ®¿¥Ç(/dMx˜$ÒUW°‹'8M30Äž %'Ô¦9”¯ÞCl¸ä¢(ƒ¶düAÉl‘ït ý߇ýs [mÐ˃’·ƒ³Ò]ÈB_­bËFïéÕ7R×7ÙSbücGÁMw§_úI`ÄÙŸ™F*Åa[M* >‰?„Ϫ¶«-Õ…¸ò8õʧ«¡\_LŠ«]3óýNÊG™w$i†ú°~=_Zu¯kʘ¥N¦Lk0A Ñ  ¡q€Óa$ct1(QŸ}Gòi”ûGÅÁŸ<âKO¼ÓÞ‡» D×ûýÃñãÆ¾÷ëv^×ó¸N"ÑXýYTe\ñ·ýˆ¤néM¾TGº$î4¯ e¢ £ñ^å”pgxI¿fÝ0<_æÅm9ï6¬³òdÃë a’­Zq_㦶h»_À]gŒ«º?l¬Fùi(TýÏy#µ~-j®s^çÚ1£¹ÝŸLr›!af„2Ò§öÿ'Û]œÝû]Kµ2|úvŸEî JœÉ4.W]­î•/5lK² G‚^4.Õ:¡»,Å`‰ ¸ž ¡ÍÈÀ0Oî}ßùYûÏá0¶¢¯öçç^sü¿cí¾ãèìýcˉ–Òg ׳™]•’°¬•…B°¨V Ô))’‘$L'Ò(œê°ô¹„®‚;ú¡Æ5¬üW#ã !ø»’бÄúºQï&poÍY@æˆcþ²‰ ÿóì«zãÈdž`ò"só×D3À2ç9Þ^wƒ†Ã’ñ+œYŒ[ŠŽRÕæD)aþ„úº!¶ø1ÿ7sŸ+ÑâøÿF¬Ü^ÊÚËâe¢Ú€;׿·qR»J´ì‚vNÙÓšÚp®•¤Ëȯ2ÕCÞùK´P.ص„BåÁ‡/tÇ^ã¿ÿhåHåq†cË1‰†¾3ïã/í­-)J+áßÖ¨JÐ;¾Æ±“ß«íêKî[%]à½î׸ìw¸Á?Qèiy Dò¯[à,"H*v19Šö…\¢,Àh€„°*’haêÀáB‰ËËÆÿ÷ßÏú¯?½`eG âÓït<§·ðù‚ÕôsÛïþ·7êµ#8ñÉo¥«#é1ø.5"ǺSçáï¶üBò¦*zWäªÆL$ðG$¿¶ø„â29ø¡¼"É7w<¸+4ÿ£?’fdç¯ÉøeÅ%I0²öC…N4™¬ AA`ÞÎËN9 ç§êz×$yɼm4N’JŠ’y:š¸:k—Á€÷2“¨Œl,QGtðs•x¤äúCSšFQC[¼ÞÉEøiüÜ·¶ö[Ž0ú¼ÄÒs,ÓékÇÍä @Õ²™Ñ峷ߤ9rL),xŠÄÕ<ãNFÎøü]°¿<7QìÔIŽø÷WÖ½œB sf!åVNb‘^Ñ¡È8üÊäô}<ýº¦Kb“3ŠÆ$‘V#£Úu:˜É8íט®rƒ•%KˆA‘ž7J!íR¥Tð¢á<å꥕;'JåÞXÄäå\åäCµbËã[Ýïq.è#nCB ©3»l Ô³éžß"QšC‘§)VòP¡ ‰ Á¿¦¯3/í›ÎAy,\ïŠ ¢Ëß­t¢ð«É2'+( R j"De¢BKœq½4·.LÛNL̹?_¼õŸÜÿx™àéÌn(§yx½=Û³Š2»¶“‹êet‰YjC1ÔêÓmÅåºÙ|9I¥,¨Ú þé3Ë-|#2ÓN|©*‚¡b¸ E4÷ìÎñ ² ¾ÕpB K{áÕ?E“:¦ïžÜ4!€z”|„²+ä5Ð è4®&¨3"Ûzã‹G•TL?—™•£\5dñíQ÷\ÿT‰Ú¨%]«œ€«Û.ÿIž«ÂæÆá"8**Í4$tt„W·p(ˆ÷«ÿéã•Ë„¡Ó|f˜þ9 Ú~·òS<„\Ó*9&¡Â|Õˆ)†ø¬øúÿ}Ô%¯ü¾ÿØòyÿ“Âßóz˜ÎM©-éÂ.°£9h2@Ì’àrÓÞF4ýX=ý†‡É‚ ž€ÃØ¡Äl€Àî;óÐÅv;¦ŸE¡Ðl ð Bñ® ¹ìíûÿÐo;guýú ˆõ¢H8‹lZü ¡zÌ›Ój3Ø]^hô®Á ÄTÌ2úȦў0v·X²õ—¯Ù ¸²‚É\Â?!îÿŽ[ë«|þe#rMҙغ±;Æsöé™"e_Õª;&4šRS­x>†w¶ñ:ýŽã‘ø=ø\èÏB(©èvlw=Û†âw‰Ch§`HCŸÝÎŒ¨£È:B°ôí(Ñ+ÁQÈ'UðÂÊ(älÀ/uEÉ€(÷`Šz»ŽŸ>‡ýÚ(t¡íи¨/0P„(¨,0„7¨¬íÃÚquöÊŸ¼~qí_¥@ÅÂ~…?¬Ÿç'£æH~æÙa-¡m Ú  TKD*@¶²XÆ•‹¡c+$¶YJ[±- ú4•0´‘ DPX ËjÑJ"ÊPJE%)Ü×ûÏÐ-¡îùyA{g{[õ2ð1=d˜\U§ÎV½‚Y+•µúë¦Ãߎ¾h-«Ûõ¸m†µqïTÁ˜×Nô<[½¹&ìþÜèíT€zfÆÖö³5õD¢ô\¹«ã10]¹ã÷¤:c¼¬Ñûް]\Öko< /Z)Ïq-Ã:X¥ñˤôÊLn©dM~ÕùÈúáàn»ÁÀ¼ùo&µG~ݺã—õâyn“¦Êî"f+¯ÓøÜyõñ•ß›ãÛáï¼noÛßS”kzó ¿W˜ûñ0{øà­¿•ï•ß¶¯›ÞûWÂêø†s^}k­?}Ï–á»Ú>=‡YŠëâæ¹áßÃäfuÕ÷®ÙË·Åöë·½ŸÑ‘™å{N¡yí¾äqÔAÒçzŒÎõu˜Ýõßâ×]¾vߪ׶x;Þ¶‡éq¿hOžÞxcî£^5ÝûI=q·ùy™¸ÊëCKM¶µŒ.EIÒÞڎ᥮þï~†¤ýáÈ`h †™ @tá¼|šTÞo¡ú¡u"*‘R[½xP£ø„€ql$ )+›Ühj<¸ˆˆ¡çóðþBoSë–d¼0öò-ØP‚`ÐzÈ ±Æ¹Ó·[Jbpèàú‚Þƒ™\BQJ¨°~Á›ssa¨ÔîÇNãá.Tp·ÙÃikŒ˜[æê!Ô,Œâ›,çœù}i‘û¿é´7ÚM í<9ÍwROpS¹Û¸w~8ÍE9À#dTi 3 í;:ÕÌÍ\ANúÉ|Ÿ5m½ËÅÖ¼xMÖöë­í?ÝqÍTÙÆÞ|NTøSbj,BYë•Òiž®üò¼½Ÿ¥™÷V64Ö¡sa3ùÝÍP\W¿‘6.w`Íe4ß«æÙCÎæñøšÝ¿?¦À¬šæ*âóA‡ÛÁ‘ÄåñÙ¼ÎÁš¯T5úr›iãv‹>~-Ù'þê T à ¶Š“"äÞåé8Oë°E’I# n*lAåC˜À2I´qöO9k‚Ä9Öª.ˆ"xÝŽ÷ŸwvÁÐ-­ "¥on€x ©ò¶ è‹ÅXDOÌ -bôuÐYAe¶ýíÔÉòjè‡4_¢ôõæÂEŠøÂ¾¯•‡£Ö—I @ôAX#ðyý)±(Aæ‹„<úp"¶Y".`ÕKE,'zæ!‡Hntœ·$X 7Í" $2Dº‰5æzV ®çœTœf RAšRvÄ#ÐLÓ\0àdª-#rœTòØôN*Dd‘"Nq¨9«x‡GY? A}²‚áðS”ÏxÏæ‹Ìtµpåµ$ªB8uQiQÿaü04hœ}!X#ÛVê˜óD=rÒFã—)[áDóºÁCºWª²B Uˆ—ÀÃÁpï@XØ"b¹I ;AÿÒüS¢)G‚C¢QêˆÔ/ –L>»ÉíÇ×l’“ì„ÅO8“H1RH1„ùÚ¡ÓŸÆ"%,fâ/oŸF.½°©¸¸¨,£i‹ÙnpâÅ$HEI$H²2’´Pª±žFÉŠï ,åb…ôç¸F#WëãÛsÚ÷KòâöءƱ¶‹cJÁ’- ÁBe`E–d¨YÄÀÏ0ÆÅb¸Ž€k‚‚• e î ª%<=ÉF`tØç&}›OVæ]–òÕF%vÅÄÄY‘¯Dîã7o,·•›™w«0$&ÑP†ŠÇ` n=c£Æ4z2PÓ‚£Xµ¦Lu€:‘eA{f¿ †*øÕï)I(?cƒ¤QZªïŠI‰G:QÙ‘‹å‘Éöš€Ø=ˆUÑA{!ø1íW%[ô›·öùF±ø{À`Dˆ*é°Ô¨¤È'Ù¤ªÅ_ ý1kOÚuÚï•“‹Ôÿë¢e…Ó‰c‚ë~Ͷû‘z½~6Éæ'µY€²@E «ÜÚb„ðºfG›×å¼*"ŸÉh Ø€Ž :Y~ï)Ïœm`ì$ºúyŠë{(ã§4þbv„üx›/Ø×ÁLZâ í®˜9£tí°pµF;ˆ4¯^µM ZN—KmÈþO³Àrý‡Ç…õ>ŸWêbïÂërb%hr¾WÍW@Nb",‚‹¨Ÿn {ÎÊ~3Ìš(¿‹´þÀÓ[²²=Ý' þŸk¼Öëö ©®u+ÞAáwü8‚ZÄ<†4¨¢ê‹$,Jžü€0­Þö2M0mÓ„“Q96¸îëÔÅ Šèâ"u‰_̉r¢†Ã'ˆ(T1²> ? Ê NCdB£m på¡{¢äÉ-øk†o˜ì¼Ëžå _ÕÔ»eR7­†»*tVjªããOè>•À¥j£Rò™;ºàá)e7ˆùý`oÆÉÖœÒ-gÑΑª¸[‚Op9†©i¤põ2C‹ŽAi¤ÇÓ¸ê Kô>ü¤åõzéß_sºžÓóã³Ê&=/#Ëñ<ß­Î4ˆÇh¬ ö»ÕR¾'ÕÍêM¼&yP®_nOy©|\3 è4 w<ÏÔ{ä©fmþÿÆXУ?<QQØhtu¯Ò¯šÄN‡âìE{pQ‚ÄÀ4½Ý×ÖûV‰8zuAH_6; ]%ÑÀ^û]¯‡Ÿññ/Á2 *2o` H…B\‚žæõ¤TɺEhбÄ4ËÕ°úPÕC1š(r ‹já‚S¶ˆ²#'z@ƒ}[eþN"¿nÛoI ò½wéÔà„ £v2âôegPƒïÈñ¨é|€‹ÎšÛ®¿ÝíË þz¿Øæç! ³WÚi\TÚo'^×kÓ@gÌ9 f¼¡oÞ£ z4ì[ïAþD’DÖéx,@$Œde€´+ ‘@"ŠÃÖ‰{îÿ`(yÛÑÆ*·–P[·ßßòU¿bAòßÝ"(œS÷Ê•ïNÿ¸B‘Ó™ië±7±ä(ʰ5§8†äD@‡ÍBê‚õŸeêUQ Eâ7ò²PK¸€…'=:í/¯ø;!Oiâôd(®-%|QµÕµëúrÀÕ­Ñ1F˜O#Þ+]APÔÑùò;Ý|Ŷ­€÷Cšå,E'å1J1jÁñüÝa…Ÿ9ÆÀdšZ:)þt‘¿–ÊBQOºƒ¾žN&ý€Ê®ÓQ­ñ{ŸÍ }]13[½cñöláÝä¨2£Ùúi::½„ ¾©#í²7…û¾7âÈüóñ¶^ñ„¦¯öö|çc¹ñ™Ü^2 n°ç¡P@$I’•©Z”@¨‰ƒ÷¼nW³ÅÙtÅ[|é꬈ÛEUpø- Ã+0C+Àgñ='˜Ùw½Ñ=k#{ G&opY³#Ú8*‚þN[€¶,›—MQŒð«”Á IÄsœÞ£ïk÷ß»¸ÂÏç¡ÄËÀ!Ùª LW+ëPåw?C¾ä«œöbÏØå¬.›„ ód¸j˜?ÒP*’·ó©€Ž@qËÚ!¯ë ñ%ÐuLúT À ã¦ô·—‰JB’‡<{Qý• ïÎá,Ú·ïmB‚ÌóòIzjÄ FHÅ€‘rð‘ïÆ=ÎÑL ÍžA‘K2ÐMpi`4Þ'çöl7GSÈ{Îi ¿ãH|@"Œ!ïCÌòïI¿bø…Õ{‘Kî(j2PZ!Ym(Y(ÒÈ* ÓIcRÇPÂ9š$§A éKD•€F’‚ÄyÎ*‹÷†_1¡Ý¢Ì·’ùJ °ËaU²“H\¤Îp)»òŽÛÿ‡ä·Ÿ/¹ò¡ð8îÓnöËhÂlªI'Á½"P4@чëN†ÁåÁ({Ïá0ýÇuï è² R8›2)ð{ó>²Ê…@c7zc{³J´€ ½9Û…r. À²bô³È D\î]R³^ ª²a‚ÓZØàh>,ëBKlјª"Ç’A* Š`"µA'òw%…LÁþQÓŒ|bñiu*ý*.îô XÖàE96¼§¿YËÈYÃéiš‚Î' k(²©ì$Ä/v`|êtr•“†O"B½ÐÖ`ªÂ#ADœ¤€»ÕÐÄS8)ƒi‚D‹á @9¡;6öd¼Çho¬²d¼5á%á"¹ŠŒT¼9üäü0Â27‡w_Öø7mvˆN°¸P<=aã}rÚ4)ÐÊ‹T²êÐRkFƒ JhFbц¬—UE`Ëe£L˜S0Ôš$’M$5 ’ ¬) PHE’(€1D‚Y‰ ”2HÝz ^gjjDõCš†”=±¶%)b1O*€ã~Iå xhD+" Q–Vÿ° L»-7‰—€`|â“ô\nØRh—#¥V#r kí1iJ/Åܹ§¹\:2=(h¶8AÆ`Cyû:3£³áä ×ɇ?áÛ„á”dÐÏØ“¥þ.¼¦VãŸ8¢yõB¥u)¹âl]ÞçZBââ=?ýãü4FûäZv;ëXš‰ýÐ~0˜8?Fñ®ØO¤l k,i“Ú|)A•ÞæaÈš|# WIð´SGá ZBIe$,ŸOfè‹P´Z(ôPëI×÷Ðë†"Áá D¨¬QÆY Ô²AHD—°C‡Fû/DÖ†É 7j,mãžÉ»ª•÷ûà!&ÎŒ¬NT•AÇ–òišÌYj\ÂQ›eÕ¨BE$1Ò`È)sJ„Q`«è’çf\Žo35\Šç¼tʬÏ{CÕí~×å—ÛY§ëú™Â€‘˜AVª«sÕA”UïÁ}µçAÞŠÞwÒz3ú¥÷ýös)K…mZ£‹ìµ?ÃÝ~Ÿ#¿Oƒ˜¡Õ$ qm X¨u‡SrHdw"¾·§î~¢`âmå_»+×ÅÿOµÓþl÷ýçnÀá}<;‘„Ÿ“ñóù¿U‡‘öÖµìì¥ÞÜÍßQ×oœƒ_ ÇgAD9§S!ÐÃG\ó[Z%…$§ÜجûþöQâ[á9>Àø1BQH,¢w¼e¬ü¾æÝnó»¼ÐD2ïƒuº )m.PU[¬J¯û—âîÛr››E½¸‰t“?@ Þã}ÿ ÈáõˇÛä‚ðLD„ uî`L 5’YôþtópŒô¬¬2BIçp %jȉˆ¤„!!")!(H´6"@SÔ£äÁGó"¡ÝeK˜d‡»äw œ¿ŸCÕDzÙÑÙµ¯xTPâ gý3ÄPàöOt†ö;›z$¢ IüàêQÚßI¸y5œÄ½íô2n’Ñl,A% E€NÔ©ÙÕ(q£ƒ„QÞȈ?‰ F4•_iUP%lœ¬ "WkÁ´ôìïžærn×–Õuîñäþ„9¹«Â§9´lQz `8âR)‰ö`ÿfþ¡êÙ4ÔëÖè=r¿NîrûºîÉOj†bV<epà 6BñGGñˆì‡¦Càù,õ‚‚íÕ$&±3ƈKúô¿…ûýr hÞ𷥨OçDZTz‚ÀxF| `âhÜ!²‘P aò¦ 7Í ¸eT*'ÿÔ&â>\HµTµ„FA$$$ƒÌmþÿòþ§Æuttsì¤Â¨Š q Ý/»Ê)Ao”$0-¾e C¡È ‡Wû?‹¯ààêµ* t8 ê’Š*eÄ@Ú²¢×1{եǺSùä»?µm‘,bùZÂáÓñ±>‘®P˜ÒÔúÒM!‹‹'é·Ï­?Þ(Az\ïØ$$„Â試:xB}RªèN)Ht`â¿"qŽ8KM‘Æ ûOÙ²ÉÿÄSC2·OÍa7øÁ~f9”½‰ÞŒ¸ØTSðž¼zÙñ,ðpºÂQ?n5öN‹{¶fóçüÍ^¨ÌÿFCAfì/  ŽÏ)ã¹8´öK×uˆ‡Õí¥ü°=!çM3Þ²,‚¬ŒÍÚOÛÅë;0ÒyWÁ˜¡Ð{.tò¨tçž â¦;©\ƒäièbE>;ÜâËœ®dT­VG¸xö_NÔmm:Ú•Û„Yædœ¯mñx?A‡òy?µÌt¸5›~+Êî;^_þ8Ü´@DÁíÒäLÌ·’«ò5¸|yâè%Dü.B˜Ü:—oÞ~ Fê8‰/†Ž¹wŠëˆ–ž{qøH 51 òÉÌsŽ]„;’7÷À–õãóNz0Ï % ² åS5Ê,Ô3—°o™—”ŽðníŒMp‚!Ø„C)—`Rk•y]Q̘jê\[ÜE-¹,†Ä$¥Çt<¹ÃÅ0xäáî¸iÕyíÁÛh%¥»ážôîìͶG;0†ì­,鼞†ŠqÙ1Ì7/¶ò…;uØpKÇ÷¤ '{®ò$;  CÁÇæè–;o¼7a ´43yHÛAÌ Ó¹@²Pu­‚¤šS B D Ð:¦Ÿ¼;l,†Å\¼±}!žÙV§jv¦^Â8–’¾Oy,„ •í{ËÕß3k*yw<»¨_à$o(gâxœî–G…F¯—_nÑŒ†L†Ê%Лœˆ·}ó=¬„Â=—+oG QÛÆIÝôî‹]°‹¨«va»«LЛÁ5µí““heE&’˜î¢Ò!à ØdW"z*“ÄtíVNñN‰vôÜN±! 7ÃËêNuŒöç– áF“÷¶²8¼ÈGYÖ‘§åßWÏZãü¯IÏ& çÎàÂÑÓ6 s©vËsÖùƒŽ“sd¹{ZwiN tU·×—;&ºw=8Á±4œ¤t:cˆŽzˆ1´™"Ÿ‰12åû&áØ 8TpÎÆ©e eM94ÍI@Ú ¬†¹¤ä†½t“?[á»Û,{±Œì8„ɸ‡§vkGÝ*U·Ò´‘Ý:ºÓ‡&ÑYíȱDo‡‹Ù}åÒ83~3vã¬ë»3Âi`õà¥ÛÛMè:áwAáÀ˜ˆ=Ÿ»",LÅ1·—NÑìþÞú£ÁÞ8?çúþ¿¯ëïß·®;ôw~h˜yR-V||óW9Æ?³OÅ*EºÍñš¹É“ÏU¡-ãd/Nñp‹‘é+@Œ²I4AKX?V]®ÓÃüŸÇYºgk›*í´¨^øÑ^ÿDC4&Dãý¤†%ßI„š÷ržMˆW$ÄHŽ_(¾Z\CäË%®N_ÈòÚAò7§Pº¥'»G¿Ç±þß6aþ_ïf§ ê’µòOgZ™1ùÛü­õòæTº““¢% k® õ‘Ò=êø³FÛò¡77Óba¦6lM7–atu÷.L-™AûV‚‚âèvϾáßñüõ+ì› ÓÇó˜–Ç &2%«L®ÝqCäÐpÆ$ѓָSBái6‘¡(<ÚòÐCyü˜>]œ€z¡ãù„ï×®³×1ÐÌNŒ2‰™™@m²‚-h…`ܳÒÌ2¦8*¦V µ‹P¢ Y5r9.á :¡ Q6ÄA`ÅÚVeÏÆ­~WØ>}‹òmÝûiøÝ)üëü6«¿ÑZæô”äZɨsçŸq[ìûàÞºèuÛ„M# IßÍðÍ Åš„ÔeTPîˆ%¤„ ,X) ÇÖNB7…‘1 ¢(ÞÊ}‡WÀ†£-€lÃ1°Œ8¢õï_ ç˨:꺳íæÝÂá±Vµ Š¢ÈÚõœümfÐý7Èþ?õrÄÖê<ÒaøÇˆ–ŠQQð¤?%ß¿¨Ÿß%ÚáïF œ7­‡ÿ«¿—˶cÿ.ðöñS!5Åà$Láé `•$$Tä 5Þš•²ã9¾R¾î$‹l‚4=‡˜'«üîÖâ@ßÎòåã$šæÕȹ`au¤é=JåàÆ #È€¬‹åžÄžx qý˜e›„>bG L Az¯ÌmÙËÖÁ´„‰ÁÜ×üÿÛ¶ú»Ízi˪¨Îë©e}“l=Hop}©Á†$¢¤¦¦É‰;ø_Z¯[dnÄ[¶EÊŒÿ«ÃêLÛ›+âÍ~0¤hè‘íý~¡çzˆÛ¿LRGâOcõH<ä¬![ôéY€í&œv¾«môxµAmx¥>ÄPØ|ß'´ÞŸãÓÏØ°/jF.¼¼ÊTÝFJFRƒBšO_ƒ³{²†š£úgèÔ7K„»[¨& 20¢Ô‡•P[êéˆý<ÏÃËÅ®DjŠäYPå-üMÿ×ðyeÿÑJMhk{"ÅÑQPÌ»ulôQP”R˜’”%¤Å¬'•°ìwø‹°6˜ó±ýu ¬µà~Î9S€ì'ý¯ìE*vª$¨±dP‰¤µË@ýøóöìXÅ]JÑé.èB%ô4* ªqlß/\‚%ÆÃ’H¢;‰QCuÈÞê †quGSM­®X ž‡6{±EÇ¢­ ò;<½Ý{e1D['/!tX.úH¼`©É‘CÈŽË/ "Ëd¶ÊäúKª XGi4ÄäÉNšT΢ȉ´Ì ˾ÈÙR«±Îb˜EZ‚\¢ñâè`}¸Þ!8G]UHEÊ?´I©?}èPXôDlBÊd¨?¢"X?½¤0 A >®1)åð—yï·ÃXU¶û_£î|N‹ç~>?ñûN7Öy?nüê‰IìyÁ§ósù´žGU¹Êç –Ùˆàð}³Ù*Ê¥·Ù†‹ê±R¨‘Η­fúÇíÇöBŸ(ÛµÄ47‚Fs;tÜï–i 7ú ˆ¥ YrêØ3Ù«ËApa¼4YÚŸùý¿ßÜåþý~·pð·ToH¥'’I$ É BE‘ˆ²$Q‹£_{­*8͵ÆAI!$ŒY "E…yÁ}ªùZŽ¢ÖiyÈP,™B8Ȫh¢ÿ–lE‰æ×£ùkÙu"’üurQ‡ \BmmhÍå°>ž'Ãþ¿ôqôNDÓ’÷#tø£d|]uÎý/Õãh…-vSê3ÕÄDI¦X¢#=ù¿«Î·¸`ëøÆý;ß5½xtOsØw= pf1TH’M°›ž&JhµDH0†B b4ˆ@=ÛŠF&Æ»{âꢢZ <’¡ù…‚NBÀ…9[H È‘X‚(ª  âœÅŠ–À(/P Aß²øÛ¤±–(w‚{^œ/£üar=`~Õ&úõ¸¼a!Yª.ˆNP%­Ê@l˜QŸaËp.-€?°d¶eîL)e{ìr¨Á2b ¬ @ AIûK^(òðé—ok /Ôµ" «ÜüKã|êõ;Ú=ÕöÌXtÈäqí¬].;ËðúwuÛŒò,V­7*çrÇœoÉ[[£°úŠèþ¯YÄ¥9_Vñ,0P»2ŒÑ—Z=è´üŽú2qïÜ êÐf‡ç¥~Áõ-.hšžMŠŽª8BÙcÃÞˆ«-ªÑ[Ÿ³àîœ*7îGÀWúwþ’€ÁVilùâD¿ÍZªC CQÊNp)J-I@Ô}ÇBjšòÒÒT’.¥z8 ÅôøÑ$lçP=»SôMEmR¾††J±Âüm2r©Ø·Ý…_QpRSWãá0¡>'úiT€!Ã¥14D± 3$¦ ñÜÞÎ5-¥&Yõ(oVhfc‹1'-PGU°ÐȘôïºH¾ÒoŽî¼c< zöE˜ô“&—y“4$ °º¼!©3nΘñtÝ·5¢ƒ%mR·ÁÄ4!X¸†²-”¡Ó³ˆ{×QâÝ•²C” PÀl±µeRÆH0<ÑÒa"Ä ÇÄŠbHB(¢DE’B0ƒcõõ+ã'wi$‰$„Z¬H ‰Uxˆ²w&†hi§)Ôà Ž8®DÅB#Éš–ð‘òâ_M\!=H-Œ´)KÈeç¼›5a¤Ï1˜žó ‚nÒ´±-Ú-)Y_¬‘ƒ ² `Ä’t4ïámL™³2›Õ¡xó@3€eƒ#<Íê sff‹oŠŠ’YŒŠk)_M4“ïnòœÐÀ½îŽè x¨2k¨cÁ«>®ÖÖÖŸ?Fp2Û­ÂÀ…U`œX@jˆ ‡óÀEP"åö·ß÷iÆš%I è¨]¤›ºUþÕBüºgFEíì_¡Ѫ­ÿ F^snçí#-½2ïe±"0ÚX—èpïÂŽ×àˆï:ko´¾¥“O3h[]@¥Þ§—2àLˆõUšäºÅØT‡˜\Õó×m,è$—  T¨…£æ{Ÿ¹¶Ãç|/ÍH"t¾á{~ÓÌdC¿ãž9E\Ðsœç32°¿ëùºSG½•%IRnÉÑåêUø…¦‹zäX»âäièN UçÇ¡¯ÎÏ&ÖyÊ'+n ‰Š×…¼ú6€‡ ÐÁ€ `Úá„‚;{´l¾j?wCø.˜Åæ%÷gìÔñØý²`GV#`}|_'eç)ëê`Ý@2™H<’‚СöÇa3!HŠ#™#È.$°V¬m%b²‚÷7Öêã¬)÷ =daHÃðF×Ó Zmê';Þ™°rvÒήZ„±Jâˆo9Ëâ'—ϯ‰Y|®DŸ[¢õ@D;ë„Ãgìy·—[üÆÕùU°°b_«ÔŽ4ÓeN¬;˜†`æšN¢¢È’™ã“rÂq®D gn¥'Y%rY7ü:rüí@­AÞh1[œª]/#š¤#Zbä½·MþÆ.™§°íÙoÍc¡ú_ÊçŒ÷7ÿÍôt<»³oµ_r/Ã[+r#¾„_Ž@<̻дɨ"(!Ø(hÞ²1É3¯˜¾P6&ݪóß+Ѱ€jPB„ / »Cç,VV«©PXP[4£ä€ØlQ’‚ÐDýVTY´ ŠD"ûÖÂt¹ Ád ,“z²bËP²ª¤*¬U Œê[dY¹# €¢1F1Oê}͇BI‡ù(Æ­É%ïEà"üé ûKD[k”…~'BùÈ0®VE@¢ ˆ‚Q=|'B ÆÅN¿‰HéHg3™Õ›\úêoMpÊÊ j@Eð*¯^„JR’½dPú5ÿ^áýêÒ§ôøjÈ?ÌÙIÕ…­!P*ØØ¼v¨.aWéúÊÇõn'äÜð(.(/ÊêÁ€eÕ)uÊÔr™-æÙím-e•滣Ÿƒnõ47ú‡3ÔÜ)^Ö§{q¬‡­dà*4µ«¹¥$‹°¯?É%¨2R’$Œ¥)Bƒ$<_rmëäÍ÷•-2¢‚Ú lõžUÍ 2.®Ö"ˆkH"‹Ø*[åå€lªäÄ[!l§è„eSÒbI¯›„ âdl4µ®ÂFFä^Ûùu—Ãl YH¼7´¶ 2ÖyBj¢ N“J¡ÿŽÔã3 rÜ‹rŽRL«óó3çˆ]Õ¨i(¥”U’Œº&?™”&¶ì¹œ(ͨX’õBát«Ü ’×Oj¶T,"1‹ ¤‡Èð @†°zò¹È èxs=ˆ\¥‹ÞkÌC_Ó@ÖP5@ÄjH9<ç^*„Ç£‚ÁNƒ˜Â¥Ì!O,4½Ù9¢»,PÔlÄFχa0ðå0‡´‚‚1`‰"¢°"‚ˆ$ ƒ«Õˆk´ùðî V$H@;ઈª¨¨¨ˆ’(„ p¨›DdÀ1ä/@;ƒt0… ç,=Kc„Üd>ü€+ß··Â QÜÎ Âõ¶&¦š  ~E´à5ãC-rûº.çŒ,/uAh¢'Š™ã+èàyÿúè…‚Ùòˆá6€nqu’zÞûóÎÈŒ92£hÚ*«É’…,<#Ì—Mÿ Þ9Wô(””núد`ECE;Û@£»è‚@iØ|ÿÚþ^rÙzQjÛ{¾®š{Y˜¼Xc»~«»Nµ»xF€{¼f¸gãß넆’RÅj’Ø §m-  ·¡äð·7ÆéÞô<Ï7ó2]ïÉÀ>¬[]Ùù­.C—ëõÁ·§vÛa6cÏu¥aû>n5½Ž+B* BÎ)òyühT/2šš/áW¨SÉ`ô­K²_&DøÎÝdÿ®ât˺~ÃÒ–æÑÄÚrW6:ÜúÙxò+7E?‡WàæõV8ûºÜ”ˆAÔïúªŽ<âŽL‰òpÿ³éaµ=Wù´|~²žÓN¹Å»~m0]‚=‡¨9_*«9Q#m\šY!®%ys4S äc8â9“7i"P ¿Sÿw\?wp¹qIm3{s×’$†¿Ò‘@ºlôÌA™õøŸ·ÚN’ ûâ¨Oñ«÷X%¦§4±‘T² ÷ØUk‡Ýà~¿»öñÕà ý=>“ÐÆámKk”ÆS_ãøøÛW=ÎÕUyy·ÁÓµéŽs>ûï:tƒ &ÏCær™ß&ü¿ÑZ nÃ?CÀÀoû:þa¯Þý_Éñ,@ÜÁ“Uòwž¥åòYIŒ`lwØPŸ>ÁCb¸tÁº–щX¢ÌHHŠ„4yA #ˆ‚ËJ&6C¶,B Í_8P]¢°P]Í]"…>%9ÈsáDŸäÐ!P¬{HuJ…t[Dšàé’o±³†qÀ|R ~ab"nÚÎATL@1Ý XF¡JAýQì`daý˜?U!…Ÿf¼¬äøþ¶öç#Vi8¦Âƒêˆ}sí{AN!iN+ȽÏÉõ>ǵÌj&V·Ý]´°QDA‚ „Cœ„ Œ0¤½dLp;æ ­ùvHŸË¥aQV4jBB ƒaqÈÂzÌ*"CLÔ‰8aÈ„Ä %b›CQ€$ž`ëœâ‘RPl–U·‰_ȸÿŽÛ¶[ ïŠFÙ.nÜUžŽÝœ¼¸Mûû—ÙÀÚsLEáž´dC@¡§#ÌÁ0…e”¢Q\ñÈnº›÷= ˆ!ÙT‚ ©¤ò0ù@$nÔoa#F0MeJ…âžWÝ=g—©»µ»ÊüO6`,=r{ —t°=d1ݰ9<XP; Ûù“°ÅøS²l‹:÷0Äè‚Ɉ¤üX&¯±†•ÀjTù× Ÿææ±‚gA8+©x¾( b`Y²¥)õJå Êïµb\©¸BåÉ…4Ôî)¶OL.©P…îvíCÈÿG0Ó®Ïúåʉ8ð  G¶tDÎ!Bn¦6  x&Û?b ŒËüzœÐÌ<¿«@_ø¢ÿ÷ƒ*DȤáØ:ï àÁ4ÄÌVÀ“ºgÏAbĬ]†dyj³çFõ«Ÿdkeá_§4:}³D1ðí•ÜÕCö³ùßéðþ>o)±ÕvŸ…ØúøöeAyfe—$€÷†ÙYQ`Ê:”ýy݇Ù?‰†ÚtÝÌúx6­ÝöîPª_‘Š!Uz*,‹R ´\ùº¯v(/V!p˜ÕS(¥‰»)=4”?v$Ó´®­ÝÔ¹­ RÕÀq!`)ÆËï³Ôs¯£õ-Ô»· À$„ýÚìÐÆØ°Òc$¢Úªˆu‡ L!® cö»”þg¾ý¿¹ä°(.‚áµ9Œåà] ÔD/CÇu=Í»Ž²åÔö~‡Å…Ï–Tµ'ò_-`JÆTjZª]ÖÉQQàkosØŒˆëÎÍô¸Ly²2Ã’Í)BÖ*HŸ‹÷ü¾—! ª  ËšMH2 PRF^ý¨! ¡öcúOëÍçê|ÝÌfSQòè Œ>ôH“ üÀÚ°'¬/Áü«s¿~ˆˆ‡6“Z´ŸäQäÃEdw/”è0‡©m¶)ÄÌ®èTR=Ÿ­óf<`g`¶hEô¬ã #X1¹h“$ JÒ—†B@9\˜¤ È ,«™øÁ©†™ü|¹²ðRã@±$³X ší`Œ+BˆŸI÷èÈ‚ÁR*‹@2LhH.PD4 kE²Œ&a1•¶T¥±c$úJ—$¶1PkQ[hÅ‚„b ˆ!$–ÚÑ •~MÄ“ 6¾n¼ÅÞ0¨H²c¨H6($C¨}< ;±P\V(,Mt¤3‰íC=È}2Q.¢²ÑI” $9 -ÿãd:®üsµNÈõÄ”uØq¦ÒÓ”+=)Ç ZõŠõÁßìÁH à¢ÈˆB"")BéŠ ‰¼ˆÜ"¢ª#*-d `$ˆ6ÅADBB$îçòÒÈ‚,² Ê’NQò‰çôZ©Á&$×)%¦4óÉëŒ4jØ $0¢2^ëíÜW°®”¶D´ƒkz•ÕEÇÖF½H"Y(ú>ŸF!óÑíÜ9Ðø`±,"C:aH€Å[ $(V €´eFÏ Drt ;{”HaŠ>&šÅ|1÷‡åvQ'YÄÎ'­~DqH‰È»:ë`B>"+'õ½_õä\ ¡ç@Ì6À¨ í`à[I©CO£A °ÑºQÁƒ¼™¦a¬”§pqÂ"¨ƒaAÀ)!ÇþÞà6 ‚€ÈtdŸ³©%ûÓãßi¦W2¦ÚC×ñwÍ~”àœÈö+=-µ×+øE´í`À|äX6Vœáêêçg§tËP³»úÍSÅMhþ…ÀJ0xÿÁÏm]tqþ—Õãî·=3N&¿øypQk@8V€ÞÄK1f ÇþÑ6¡ÇM ¤eJ„ƒ/éàٙá?¡¯ûZælÂAACo6Cš£”ê~¼z¡9ªxþ^Ä·y'³Øo¥x·>nãý¼M>¦jËÁ‚Ò–Àâᨾ[êˆ1~Ž¥ºÌ¶sHz®q(a«ù‰§ªôó‰ƒâñ_èéÿwÉvÞW,|÷ž3S”«!i†Ãö‚‚Ô*´j -Ã1ÛØnÕΘjLK¯ÈøÞg½s4iEñ‰dÃÍ„ƒ!Àf¤°=¨f®ËyNP.¦Ìv°÷?€j uEÄÂ@AØØPÀÄaÇQ‚;céÂ0vþx!¨‚H 2*²„€,Šˆ’Œˆ,‚œàÂÐùÃR ¶97Äbá[^Š7pì-ô¶âøg‹øÞ–¦v!iNíˆÁŒa ŠÄHI·ü]y"çÌÐí½¢´wý½‹üI)¸k:¾·‚Ž€…½ vn"ûd¦Ä5äPA7„Cb ,bŒ´`HChœ„EcUb0"ˆ1UH $P#(ª¡#È"fsùuÑ$HE—Æét UY\¯ØRa¦› ˜llìð;M‚PbŽÖ9‚Ž@fW‹ä´U¹ DHAb0†Ã\€&®QK¸ ŠH,"$$‚H¡,€H²&×·¨aâB,"!ƒ‘D^Ä'k‹  §€ƒQ]ÐW€ÚÅD`2Â"ÄHu¥! HkðD`…噢 °¡p"YPX*³²†@)£$As %CÊ(©¬d¦¬: Äc Æ\Û¡mжþ¦ADÁ(œ„lÎKŠ80INr¿Äwp[å’:*eß=9Q°Ôhâ!ÁˆÅŠ­DÖ °A €F2 ¸ H¶‹ß±P°¨,Š‚Àó¡´£·+“Á¼=Ê.Û\ÓA:÷‡¦D@=×»ý ~‹Íª¢-¸ 6òɘ¹‹’ ´c,(Qz3 רÚñøüžQ;$ÛDøÉÔД’)°¶P?Ý}ï©èÙWß%Xø…=‹0ʲ”+ü¼›f_ÊÀÑ¢Á6 ƒe+HÊ­KZ<%`æ¬f6©Îyzr6ó´¡rèë:ÿöôÓ£Ÿ=uWs,/Bù8®üÙi-keò½ßy4¬ ò­`(¿Wæþëøß—Ùñ8†Ob&³Zœÿ:âÛ°qoõ1h“ b¤ÿÆUë’™^ذÒH¸ùñÕ³»PiuAb ´¨-œ$™Â¤!ï­ø¿àl+ôÕIùz?ÄQ5‚,H ±QOhˆ¿ø¾SH ÎÇ,ÂD‘I$YÓÜS‘TÚ¨'«JTÕD‡´Ÿ:* @fó4bCP4‰S’гèl9Éä“㟎* ÁU,H(ÀOT(J€Æ(„$Ab"Ń'k TV) çåÈ?ˆ29Sp8Ñ2• g"'ÝÅa —[³—Ü–wàRxsÀ. @p>—ßGö\Dt÷4'^ý¤¸¥|ᇺûBoG ë—xWCŸjÆ3¡QÊ£ëÈ‚õ@<l[RiSÀ]¸äb›µœ‘,QÖ Añy/Õ ¬ÈùÆIª¨¨û¡‡À2ÒYXu ¬÷'µà dXªÅAX§']ýܵ­kF …•¢]l(\S£îôaÝÖ´xÞĆnˆf±À?l`…»©h€Â¥0L¢–‰QÁ“"€ò§c!Y;dÏ0¢¢2>b™žÂØP‚ØrÌvÁœÐ>1\H@½ÄÓQc:å‹Cr•Ïy£ `*W4ëÔ~Çq0ªc"¦dQ汤žÍZ¨CK6 $dY "u¶ƒKÒ’Åþ„ϧ…äÄ…EIì¤+r•:²×İá1ñ p²~Ïáôõ\ëWT޶ó¬ñfÊ«R(- `‰Ló5 o}ÞèC„ñúd$‰ ÉBBÈ_í…q¸š­“îy©(vI¤S³ð<>Sœ̙»ÿMÒB ¿ãóDp¿·mcÖXæ½\³Š*®½›ø?ùûÖÅ~‡éû:Ò¢¨ª"0_«þ!Ï´$-Â'ÛŸÄdvo¶ÀµX  _¬ÈF•ˆ*;¿Dä‡ò ú†/­Ö˜aýì”ÉÕ6й„‘ߘ¢yU‘§ø4$¦¯3 vdöhqŽ.±þ|NqVšñ 4þeÞמxÞŠ»–a\©ìì`r=ì÷¡ %ï²òs²K³©Ô‘ñ¢ù‘²Øg(¬72C’³)ñßÏì;{¸XP²P+ ÉmçÃÖô3Í쵟7yñ?_S{ó9½WÌãn¹00¦¤•RŒipOÎѤÈbÏFk I+ýŽRBïV#?tñ‰,D ±í¿á¡ŒYl¢È¬°¡R¯RÖ,…D¨¥ÛªVs#¢È70Ì •Â,"š‚Ì ÎÊF+R”(¶5ˆ"ˆ,•*‹B¶ÄД4…QÊf’h??ýmfÕKC²ÿÖsJ£Y«­BŒ£Þ+œŒŽsœÏÞ[Úî÷¨úy¿ùýýgç°Y°–Tðœ#Òd ü»üí Oþ{ÏL~Ëý.[CÙàÌKee¨[¨í(°L+úEŸÌz˜þ&4{ØR ³Wë¦v*5ñi¿#E¡î™™ˆ’š9‡)©§rAQ ¶£&÷ŠùžÓÓæmfþÊÓ )aa‰³Ud -’­_c1ËmZæJ‚”M[,"Z•¥["ê‚ÑBOjcû,ÿé‚‹"¢ÿ_ßÜíüÅ­©ÆRìˆV‰—ù}p¯~7÷³m¬V»X„ä¾áÞbQÉ­ˆŸ:ÇÐèžD‘5SòðìÜfÊlûîÔH±\¦"ܪÊ#iêÜ„ªªôüb8e% ßôô —ôÁìì¢zù'Û’ A ›UU¦F‘ “ÅÙ:Ât¦íú“0;Èjˆ*¢½¤ ¢YΪ«ù ÔUŵU^!9¾V+sR PX€¿&,I&µÖ'4ÈIý 6ÍWÜH„«œ^ ' #¨cw)ŦˆÌŒAŠ ‚È(¢ª&ì %d ¾v4—àšQ­5†¸~P]ÕÐ.'ÙÛ×lŒ%Jz* DÅP‘#BKý"Ÿ©÷7¯^-µsÔ5 ÀÖLžœÃ  ¤µL€Õ"D+…Ħ °Åk ‰î…¨iupEL_×ôõB)ž¬‰^}é ÜÛ ÐÁ°)ª‚Ò±@BÖd°£Aj‹!çj*0QVy®& t—þIú­–@‘;¤aÛã³’áÜž ³®fJ¦&C‡õL5äH˜Nw¾Àñ8›-=»YÔ¥¼¡3âªMs-yü}H{bdžæ]EBÂRã8£žº§ˆßkLÕüŠ’H™QIÈ_»þ8ªï~“QãùäøP³I£Ø·dèu!­$°o®Ë—€Ã9zþ¶M1z”ÈHu„d5*‹,áŽRFDÒT‚‚à˜œ½‡í w?&€S¯±,üHǾ iõaù¿T×Sº¾Ÿêˆ·—¼×J4î%á€õ˜* ‚ŠE%µÒ*ÃfARH9J':PQwÎõ ˆV *²! &Êr¹ ¶Ö_YÊ©Ó Dd lÊŠ ®äýØ&š{L“ì(±;P‚‹®2 Æ’¹ÐDh·” ¶Å $¨>Œ5"ü †¾UAhè–Œ’I!R¬¨.¤EóGN„TBV{*«ñ1·óéNVTˆv4Ú&Z\ÁAáaêeÉCxM@• E ŒÑ’ÓeÍŒDÆ9t’ƶ +ÙagBÍ*¹NN„£•bJÁ2ˆûŒÚê³›Ês娸RTÚ2ÞâàŒ ²Þ~­ÍZQh†ÍC9oTÐë(Ù¢£S»ŒÒ£¼k HÜ]HåL$&^<Èll¯yý˜8qI A‚]AoJàâ§›š@‹!5âØ’I >‹ IÀ?>ɤQ",y¬µ+Çr­ZI(!8…,ÞÿöaàbÁƒV*P‘åá!, †%P,Ýâb>5‚H„`ÁŒM…!DO`¹`ЗRêP v /Æ؆|0;»˜ü¸µÅQ¦2‚1à ZÒzvQ¹¹ã5¯†­YXá’ Iá.Û(áåÔß™Sb¥žaF]÷¯\L¹1Ò‘¨=CÖ"¨[À·‰SÆ!tåL) ˜…(/Ðܨ¢Ìââ,èÀÓ)¦`£F•¬TQ`¢­†Âžî’˜ÄÊHÙDuk8a.Bl˜a8ð¼pƒ()U%Ih´,ŒJDB¸„ÞìÈNŒÚ™xô¤‡$ìÜÎkÐr‘„óèOUÞe+”*<@“`Òõôä 24•ˆë, W(Üa(¦¬JZ¤b±h„À@{ÀV)B•È)êÁzé>á]R¸‡ßc…™´Ù‡ÁÞˆìM- ªuÂÒ»!íÌh­þ(V¥Fj‰,Z` ˜Ð–Š<¾¤NO£Å/éØÞžœy]ª×ó—o¤æÄ¿õj[ aµeÔeB9¬ 8\ýì'ÚB Šƒ­”mJ_6æætç·Kä]廊ro\Ñ•G8Yuè§çë!qIV@Xr÷ª)SG#®2 I§}¤„ì®Ðü;~=•;åŽö÷gÉõ=¯+ªë0ñxø?ÎôœïmÝqø“Xó;>9q†I%{=}ò]H« «+ŒVTjNZsî®Õ2™‰ª 4(‡¯¿qSe¼º¨0ü%T¸PøC03~èü]‡º+þ–µý÷‡Òw?jÙö“îåöä'™ám‘¸ÜD¼Ãâ)4é”M%´£ÛôÙ˜Œ¾—t­¾výéÄ¡ Æø6$¼±åà¹a†gpdͶL™2â½R^™=×1¨˜å;¼Ó6¢¸`bbcüÊË%¶PÆ&eå ª©9¶Ñ¨ååä{¶Îa’°!% A½5 ÆiÀïìõÚì½9§AÔ¾/µ‚ñ®ëx:·{rbP®%»SÔ­AÄúŠ6IÈ'HÚ¤¨v¼ Šwyˆ!Ú^a»r¹ý·®ÛÜ;·…£^Žûßã [Idzk0z´Qî{.ó·›³»ŽÔYHõU4i%¦ˆP“´CbvºŽÒϵj0Œ’X@§UìCé,¯»Â™Þ·}Ƨ ‘ÄKí%‘0É&E"Q;½Ï…|¢£LøÏ½.øV"U줊}øõ—ZzLâB ƒÒ7Ö˜4.5²™±ÙÛ~\YnÇŒFvÎ °8·¨‹noMLÖ¨f­tÝuçš:n‡'–]àœ× 0+nÓx[ϯš5ÝÕ°;V¬”Û! Ù\87aʽAk³±Òá25£Z§!l„Añþó¨:\0‡v9Þú˜¿ãrãZ ¥HÖk¦jM-#Ë‹‚_>\㊌Â@$ëS\Ì^eÌ‚AHv`‘¬:Üì3Rhéi\\övS¯[½H~?¶”'DÃoiâ9‰Ôõo§Uw55 E»ñŒO%NŠªË+0*"%Ò¾û¹í5ZÔï¯fôýÆX¶% ¼¬žË;­´·ö?Þ®®fŒÕCµëØa…Ã#,«'"‰†Åó ~¯ñÆÒÞ©øÇnòâ··åê[ñî¿àŸ{wåg´ ºå5ÙŠ)¿YßÄì‘{ÓºÚUHì›H–üÓÔ3ø<×RcøßâŸcWE'ã™ß˜¹5s 7A–æHQ·;ééåž&¯:l|xÆDKàÈ{»·U¤¢ ¢ú»=ºï}³}Î&Iõóú{6—Äyhx’töÀîÖ¨.K¼õlƒö.:ÜâMÑȇÝéÛj5Û:°^IßJë‚-&r?.$eJbš†hW¬š»c3RÒ"ÓŽîÇ'¨fs_ý™ª=vŸ©äß/ ¹@ps«–êÓÄ.\¤êmU=ú_µûü3LÃŒ0Úõÿiý—L€‰-Õál"W¢îeó1D‡Ëêÿé5òœâŽ>¯10â¶ â`VþºÕùQd²ØJŸ¯SÑãZ#woÒælär÷¥GÕùÛðòÒsµÛN3Þo5ç{t±!²-7Ì®góû{®{õ+:‚ügÜšÍAc‡GVg@¦Có±ÃùDGWrv·IÌ Øâ‡Ï0Ô_µëàÕ/@ HØdŒ#"P]åè3 ê+;W˜ Ȉ¡sT›–Á"H¦`FÞBšÖ\³™mn¡šÔÃçˆï©T§l×½F(¸ Âq-/%RRŠ‹Ã¶Bϼ.h:”¯“H‹„U ,# à^Vº÷ª“½æí$6!Ä5Æ(¶ÌÊßôèl×ŠÉÆ¥‚͈@Ó&Üf!§|[À•an:8ÑŒÝL4Ã’(Œ OÁ×↜l˜IDiÍj9 ‰u¡š]H"XçªxAæ…¸¯«IíìçWêa—׫ÈÊW[÷OŽÂyå ¥9‚Ñ1_(£ Æñ'…±®¹¸æ¹æÚá‚ü"Õç``Z…:&¥€) `Y,¿§ùkÏ\À ziÕ©ìÒ œ)i€H(¼€p9y 7Ä2‡Z³9æßŒ¨Yd>$÷*áq×ÒxÆÿƒ?X|õ™C±Š=Kë$Ì¢÷Œ!ý*“ÙE!?ê„AžPÁ ¦O$¢(Pád›Ô–—¥£ÄD~h~à ±qæùÒx„ïаBE;±7q袚wlLÂüàîó\úd/p–íNü˜îßÀÎd“‡àòüÂì·ïV2RPp¹~šÕ _Wõ²­â7 4[øT!"ù­}Ê€#µ\ôi >š×rÜɬrö&P6p¡€(Ý;§Oý¦¿®‚“V¹þ.Æ-0U‰oQ¿¹‡1åÙ\¯stlt;{½Î~.C¼âý-e×Xz1¶ ç!UVQŽ™C—’Ç^\¼ì³ü.3‹¼&e°7'>„E¸‡VPY"‰Ç̆hQ˜jÎóg5¢êOñ³B4’Eq¿îžœµ<7÷mí‡åAÆ´¯–M†O/MPŠC}¤wÁÓ$“%h«s‹õnÅ#¡&yI$†xÛÆ œä‚hžÖiÖy€3¿˜£G&³¡EÔÔP/î¹xOÛÆåé<äváÙíŸ9¢4œ1@¥™ÝÝmÈ 9¨¾ûæ5³}»ñÅÒ5’Òm0ô S¡<ø.œÄh@Ü tÂBÓ™ŒÕ =yæÈ_ÀqôúI¶üómétvÔ[¬:éÚ'\¦ðT›¤2wNÊë"x"¦XÇr[/f>Î1Ý2B“9ô⊧oŠt8›aZìk1ã\ILÞnu¨))¨yyâ«z’J[ófºóJx•ÓRdä:N9wÛÅ\;ÊDßX0Í ã¾Rví[â`´±ÊÔ°Ã4;¹5©NÚ¬ÓÊ´±ÊÔÀ#ö^ÝÔ&ú´”è®eº°º:\Û×}’ "Q®ü1¶¯•‹{—£„¢ë:ë× Ça:$D–ÈÈåÙD$ª!½œ®Ë#9râçt¢0ΖˆØ¦†@„Ïû{´ÕÈX6ë2%ïà 9ô»my/_Ýk\‚Ôuþ*¨µ*Ô\{ ̘•-Z…¸ÚõœžÐÍa¨Öp5ß±†s†íÒãF`"è¨.*‚ìJ‚Ù N‡KZÿÐ øyýÔjz# ‹ýÕVª¹/+œªZd.…\Ö®³·?çžÜOò5õ¯c81p‡gÐùó!Ð?*¯kY·Q¦%ŠR’Oh›PP  pì©X”Â,oçÕ~扈!À€à@4ÎÙ2Èù]?lfØf”8ôä  ˆéëøsÀè çá!Èlmð<³>”еTî8` Ó Øüªoüý@€à|88L‡!œ’ïô¨D¦˜•.Y<:Í ©çØÀvø“ƒ¾Øº²ÑÍŨü*zH4ÊRJÈ<‚4»?¸ TâKJJÝL»ñȨZc/(±efŒ¥;ÀÁ]&ü®ÀÖ‡b™q˸ø[ ôÕ›£A¦Etõ„AO(óë>ÜóüÞlâÈŠ²*ЍƒE"1PüõÁ&6~gÝû"\ȦüTòYQrñ70òÎSÃío–σ»ÆÔÕ׬<8©·ûϬùÂÎÏÖç'iþÍT*7H[anèm”l¿‹ôõµõû²0ŸãíT \`P„ ³SÊAS¤ eÚÇiÖ ôLÉXPUÈR„»G¢O ‘AØWÜtßK/‡¹~ÞÃa±3t ±”Êä¿îÕžÛiF7›Qt Û®˜œqYdJ@º!Û‹‚œþ_.^¹ ký¯ž {c8pAàÂaC| ‰wÛì½öF ‚‹d^¯Z¯Ú-¨Îšú` ØgG6=2IDûÿœ¿ë)Ъ ‘põÓ:ȼ® ºŠ .!àë¯0–½D¥ Z)gkH"}ëO”0§OËÉf3ÜEHí+!¦ .¯Ë홀á° <]ݵÝ߯Òð#ÎkKü8«Ë܈´Ñ Ä„$e"/p¢Â"/ºžIìШb  ÷=ÓÑ;ŽØe™LLˆÈd”d6ËEdÜo£› TȪ Îo犬ˆ‚ ‘„Iäd¢ «²Ee@‹XÛ%¬Š¢ +, ‰%a1‘`$*E!Œ$U TP‚(°•"ÔBµŠHQ –‘Œ ã&$ !ð,Ò²hNÞ‡wcQ°¶óí¡š*ŒS2Ñ âÄ,®D]6µÁ4séT[å‚caæ†A­Sø}¢Ç¯ý<+’ÝEì)ËÖ„ú¸”gYK&HR ¥ª³âÅ !6iF¦Ø*êĈ˜d_$rE°ª%p3O°Ù€eá£Ý—0¤ìÒ.y‰¶´E’œ0Œà° ¾ÛC†RQ1:æDtêƒÇmÞ¤ÛŒ ã£5b¦“-J5±—, od˜ Æfi†šÍ&"ÝH’¬œ÷LÔ9Üx¦³™qÜ&HkN¥¥®0£4K­©52•2a ã†ar†Z—rLs4Ñ ÀÐÂÀDJPÔ3Q‚‹A²ŒÖhÉ "¬DUŠ1Šˆ‹†`L"+4+8$³0`+ Rb!mŠ,›@P¨Š‹¬¦:¥‹¡C¤'Nf· ˆ„çJTT‚@±D²ÑKU+…²°ƒÜzgó¿K¡ß§:#þŸÁ €B´iTòÜf$B0‹COC+ « I<Œ1…`ÕéAy¹dæÄ×T§q3€o04Ì >]TÄ7 ¦ }˜ê^ |I­T!#DF‚"#U“ħ3Y†ÌTPX£ ´ˆÒ比Ëmm›ÄJ6„cÅ$¨¾–È›€¦6=ѨùŠ‚çEÏoT2‡[Å[$Rˆ¡@Ï/Ä`|÷Ð}œØìQÉ êP¢²E%Ðt~'WÀ…e…Ù}ÒÚqÝ÷_|^Añÿ%j¦j …@ž * IçŽán÷D}nÚÌýX~¬sÁ4ÎÈÂRÒ™Ñf(b%Dñ×<[YhM6–*ÅíP IçÙG¸‚_ ðŠ$ŒdRÀØX·* ÷ OÈ|vŸ¾²¢ÁDXF0`ˆ‰$$"8 µ—£”Å€Ûk§@EÑX’Рu!JOhQìL=ÀՑܤ$ `…dÍk¿v[Ô%À°LQYº®SLl(ÂÅwÐdk¹"ÊB áOLVc (%I˜ÓQªB‹"Äòì #"=çywÍÉÉgPߎ• Z-¾¸Ó× H¤‘’,‚+³´Æéƒ#ƒƒàmpôÊ Œ‹Q~†=±Tq}9ߨ ‰Ù)”I@‘„¨5QPZ¨,$ßX T~¬¶tŒ„‚DêiÀ‹"&µþ(}¡˜];&®™À$”#Ô$%$>"ÈsšÞ‹ÉùËt·3Ÿä™žÐî Ì3fiun6˜†#ÆøpÞøRÜÒéÖ1ÊÜKºoUÙOÛ:f÷34âjëWƒeÖZ¾WN= FZÏW¥æ9>w™È$­U) Â+ñí?Ù¦âãnUUs6ï/p'EŠyx¢&RJ^"I•5O2”=—ôž”CDJåEg ~"l{N××NÏËÎòwFÛÖÐo•ý*~×ÿØW·Ålߣ«xÖÙœ áÀ~;üä‹íª‚?ƒwíh‹Ü}º`OÍ•rh®F¢er㩃†»2õá²T!Qd0!;‰L ¡è—‰ã9„å ô?¯ý.£ßo”Ã9!`ê–Ks%VLj1 e–,5jÔ 2ƒ%Ž‹ˆ¾VÛ£-Ð2X`SÄòˆïò«ÉßÔ´ Õ£®‡b‡#bè!ö̰dûótDm9›Ù¶«&$šÊMQ‚G¶å Ufé›¶rvcU²R9¿CþŸòvˆYZ§b‘ET'(¤¨*à‡{K|¯Ëö(a@ €( …‰ë¢Úª;ŠÞ(…`vÂýhÊf K3OŒ}²«oDûž¦ Ä ÿ/ËN¾Âݲ¾W\ÑO ˆŠÜꎯ–¼ÞóEÎiD±9@­,ÛqF ÏcQ.sy*7?VÜ]ØùfìbG×}¿wêù>Y ÿ3“¡- £3 !å:õ¹>óðuÑw}þ”Þ{¼V2½ÒÎ#^ùjÛ±Ar»Çåòìäy*d®©X—r¿J‡‡(§à<ÀH ù¥ùy )¦ò†šöÆ-E•ò°‚¤ôv¶š¹…°¹&ƒ>Î~Ég8K5&‡›jr½¯¡_•’!÷b¨-¨tðKh8([%~<ÿ?%ä…v6¨k6‘$$Tø1ç‚›!xŸêþµ* È1BN(pƒ+_VTm"É €–Ô?·ôïN‚n3llÀ‹›ÇZÁ°[©R¼S¾¬ª{J&Þ L€ DXt°ö4hF¾³µúlÛIÖªºökŒ¥×}q˜Úé©é•_‡Å"ùˆ~å*ø’~å–4àU{ÁÑéWSM:ˆ¬¦©þ4ïϹP¡döA[5ù`+ €0wÐ !ˆpÁƒ?ªþÙýõÇc°FßÔZBãáf<”(ÄÌw¹ø¤Ã|Ê\q-j÷QKø@bœTfXÂXj!>´ÉUBŒnR4c,QÚvª\­\^þì%õ¯Ô´éÛߘ0ù<ø©ûœ#é–ç÷Ó¥Õ9<8]ŒúCV‰€C‰6"дI+bÌ„ã8´ìhÑF>š›BS°–…DS&2‡wÌ)˼ž·Ð¸w Ñ ÿO01ÃY2½YYRäU¥R'Ÿê˜î|·[ísrQ]endÂÐñïù4+$…!3ËW7’Äô9h¥HC￘V®;¥rU˜ÉBü/möãÖ¡ñ­é7É"‡öû—¾ë[3â‰áÝvñ]ÿŘG’{÷ìeÝ=;àðÚ¹¬,ÈÅdiL¿xjÈn¼»ÑÞøÚ\gü»æObxìý—DÜéûnî´u0§SÁÏ€æ§ ³k—Óxîß[®]sSܦy®Ú—U«´ü%Ï;\Þ>òw¼~'6ûÍêôxíÍó|ñÓõ–.uÕ¨©Ôa·Õ»ãª\ë®Üq®9Çk9ëdÜòÊß]ŽŸnúßzÛŽ*óëŸ^yyY;z½¡!ô· #Ƶ{|/®*³:rLšQ|Ûùì¤íU9†çŽW5•O™¢¦0|sÍN¶ióQ½-öæ;:<ùÂ7ß§‡&h¾,­b è’ýðA5™ ³&¥ýD˜çtÜèæXý‚"o8Hl3»-d¿ßý[_‡u¾æzþ:ÑÞd›Wk_­]5V¾Ë£¶!¥¿ÓÕj…„ Â 5º°Ô!Þú2Ù0—Q [zazФ„ah]ûAÑþ­y,¤ˆ1dA€°žoAD7«s©¨‚«âmXà4Q컯ã×µ›Mƒµ‚ö((†ãÖðÄëë-rHÈ2F_Ôþ—›úoúŸùïqúŸºŒ´ñú1#Ú©L“o‘“Q-Ý÷{‹Ro6´ñ—ûŸâºÿWö_¤^F‚zŠ~ƒ’êd»Ü=wíßS LÊuÅdù¥µI_“¥Ãë^j1eéÞnõ²®6RÝ̪z’"+‡­ñ™+ ¾ÅÜ©¬5¯UÍnu³ óQÁz&\‡8]‡H®Zpiág;êÇ/ÓÞµ©!#ŠL$ú[Ù™{wºÝBÞÿ'`ß;Öµ|=ç<'×/îfqgá߇ª¸ãvürV×8H¸Œä=’DÞ-†Ók/|øðdTw%§(Q®{ͧ꠾äw*êTF•ÄTÅQPmk]ïQ³¼µ®nin¸}-Rþ®]Sõˆ—}šÜÝÅÞsq­\?ïZÛàâ-ŒÂ³¥›µÔDý;i¡Ø÷—²Éýß»/úûý§¾ùß_³íµôù/õòôk[r€cø<‰æ˜1ÄþÒ&³ ¾:oe4;[DavªJF™§ˆǘà·ö)ò‘ÉðE¤ñªŠW÷ÖªF'uT¡ˆ™d»¾^±Õb‘*å&;ÿ'e·MÀ¢T >÷LT„®¤oŠ”ŒµwÛt=7)úÉ—¥és^|&~š.óûNn$XY‘fó¤Ë\]×qŸÏõvÛÆáÇt;·ØÈcü^*¬eî‚ÌF+­Ëb*«€²ªdTGÕáÍ)ü[¶‘ÏyÕ/ñ© X8ϪOj ÿ#W„º| ÓñÚkxd‘é–°èìéN¼NøÔ9®‹³$6ؘ\Ì©„#÷l ««¡M:_­qm‰)Xïn™™Á¥ …5Mga’ï•ÞuÞ²@’ò¦"È, Ìœ³0Ñ—2~œõË+,üß¶Ì<ém“yöý“½`üvî†òÞ¶½ˆ’cá0äJ„Bôðl‹dŒ£i<À—WÓIC¥ö=fGXB¢g9Ä©JxK¹"¢ùî‡wçÍj¬Z8¿«L?Bq2FúõÔ<¸¾>â¯h‹`½iðG]hËjr‡!éIü—wÔ¸bm=!oÐH,r1 ®µU­UrÛ"û…8~¶ª¨V¨F§²˜GÙâijAì¾×ÿ¸…&™‡fŒåú‡líðªë\!ÿlÂàCÄŒUûì¼EzYåY[q_­* ÒŽ$,y|·ãŽ –öCk[Tc§!íA¤ó–·¹‚¬8ÊK»vÔu\®7jDÜ_=Šê®-G tî¦5ÚS­m`lŽk‹•a¼ÞžM"²i±Î^—hãªwã …Ì7++]-çXœX·H°Yœ?öû̼ïÍóT%~{GHí‡F‘ö{3§]˜½zç¾ö ;òC±ãž9ÿ'ZëG(=•PzñƒŠüP«£Î!!Ý.aÍkˆ XüV¢o™‹Â@žýnjr×MI”y1S¶~¾&³`F¶¥•Iz®¤Ÿwæ9‰P?gxìõ3¤å;û»Bö‡q{®ªÊ Zº’GÔ…\[È\*OO ¥1» ÂnvæL]QZ™m/sUeÝ…ÔL†o[>ŒÝWo ŽÜ÷áþ¦dt—uĉBM<ÇO®×ÞHM••”˪^±®çru8·ÄBJVà¥pÓAeW¢ÏY ¯±žÉP †ÓÄåÇrœÿƒ»ÿÉ;ó»„¥-A/|/Ëûm8Æ|Í0ü=ß)ÿ¶0Y¡¼Mõ…÷£Þ%¿ÁekêMzl¦ŸðCˆ×Zyx7YCKNŸú˜.]±ôE€£àmP‹L+aÀ$ÂZ¾"DPLè“ ¥3âó³ZõñŠ„$Ìy8™ì긽7àÂÚ„w}¬¹€B*aëK¬=°ÇüÔþ7ô¿kÏß7ÚûÎËuq×9®6ÓNó0.†«˜¤òårÝAÛŸÒï’Yc¢¿ÒÔÍC£ù\ðÝû¸é¡[~h‹·¡üÄ$äÌÂD¬Š£•nu!˜'uó?¾Yo¤ôYÁಠ[#žÍg½”zÂ.*”¤“»§Ñá<îÞV¼„9r9§á›r®¢æ%”¥¤Õó®¿™‡lÏìx„¿²WIÝ9+´Ä¤vr"”B·ì꣤k(ÞjŒ×§ I°ß3)“?¤·;Ûh´ñNê­é-$$¯îKôü‘ŽÒQ"Úˆˆ"Õ ij.\wæ ­ÊDȼyi+|¼n·>7RU*:tü73‡N8öñéÍ[Ì;\n<(…ÒÆÛƒ÷ªÎu½èÛ$¢imT»ŽùÑ3 „%âwT»vÂ]´Žú~;¾.“Âr6üpP‘Ëôüt»ÇXØ•(–¹ eGÆae ‘?_¨ýÄ–íUÒû%+g™Su 8Ñ åu惾òî÷þ³îí~©Ø)Õkÿâïkòm"tWÌ¿2ü ¤ÆÉpèì;X rÑÀ×P0b‚.k\ lA¹¢dî¿KÐÓ­¸øùî²)–Æ ær¹·.º·²²¹Ã†V[·–™‹Mî× &±ÒäĦ?/Z4|ÌÍÝ_›tëæ\æÝéÓê·µ»½mzŒWYÈrê%pðoŽV!2¾oUI“k{¥Ë¯œ^]à (’!\ñÒL[ªÈÄmR)ó2 4éDÍ%Ò¯=ªf,pcÅ‚ñ£yËŠq¼E$‡y‰˜J“A(IÝIsÅde¼á¸x—,ªÓ3–UGÈÃ!h”¾U).´0¹aWÌ|•¸³&äÞYՂ¤³Ü± úrqÊÛKEz¦Õë¡›k›Ì|ã°/û &×Îä2^†€ÿ©ÚÆÝ¡l ”e<@ Ypsdî&ºÉ6,>—ÁOà‡EŒ¢"üXéÈ~ô×wŸ{€Û÷PÂ9~KÚæõ¹¬ÏSqÄ|msé}þsèã½/-Ðå­ÏÝ{43yó’²D‰†étß@Öì¨h¶Z„ýP+>L/½ºñ™²?cX·VpÈ 1 ä¶‚—4Ћ&·¬ïጾÚ<ãåz5–Ìèï]Mmœ-¾•Âé§e¦ç _=3pr'9¯rl#ÍÁ™qjÉœaÚ#Z¹¡_›U/%$£I6ÊuYóô´gƒÂМpzˆ¡àq©¼ ë*1h9j©Å8‚š2á47À9ùz]}qà]žûí^ýJ·Ó}¯Q,uUö×{7]ÜŸ“¦””y…±Oׄ÷š{¸Ü?À}kïñf[Í UN»P?…‡‹@w•Áäô—”ÌñWåÿ%?¼Ê¢ºâ¤8‰JKè5¬U翜&ÞÛ3ììZå6UAèb(u£?ùU|jë|\h’çU)OõŸŒmª§8yw–z(kgï01C67LSš–¹ø²¥ [²8„ÀXÍÄöänÄB Š€:1Š(»u%qÚãû>7åú>h=¹o©. ñê ¡zMóýîQ÷²(ãËŠ8Gœ}ó»û[U¤+< ÐK¨Ê F-͇µ$%€Hr³ØœKCŒ‚I"€@¡@ö>8+JŽak)/Ä^éùâi&ì&‡¦=—H5FåBßâd~Ì>#cá|ÿ—ú;M†Ñý¡â³þï3üô68S~oÙqÊ"PPëê€9Cµt'T›MKÞR[ƒ‰†€z2I®›­^¯‹zƒÉš*=H<ãpòÄN>à|Ó¯Ú£X® Ð#…f7"ޱ _¼Q$¹X(çÚˆþ%+åíf]†ÿ­2 ’ñ5™áEô§c—¾Žãkh¤œÄ×A¹ãDHA~{Èý—Y,ªC*uVÑwXß#%&4ŒTç(k ú¡þ­pè¢ßîl•ŠÆ„· ¢¿àãÛO¾_É‘újÝû/¢gS>áÅÿݾÝÁÇØúù¼ö™oQØ‘¶œve×—ÄÉ¥1OAØYÇ ÷Aï ã‚3ÞM^{™º¬×àMÃzþ‘óùa§¸¾R&«cµÅ– pK“¤êØæKý…¿içgyoC”ë¸ù®èÙ‘¤0Û ¥BVÃîFÑaqe5òªÒÏíÛf L3÷G붦øÑ“ò÷7ƒ6#µ²8ýÉV0Hp€îJ¬&¾t"ñ=…joÃØ9'UïFÂܵk}Çì•n›£?-ÜÍ~å^¹<Ówãp¦¬›§§û.ºŒúË6ÔÍjZwm(—„’®µ7»3àWî¸ëæ0Z ³EbëŒ(Ѳ+ X`€ûŠÌ‘,m-uîTä7µûÎrÌ5¦tbò ˜¢ÑÙ?å—Š6rT)X¶©µØ‡qBLÝö VÑðšÕ¨Ø8‘W‡4º? 6Ž®¯ÕÀ[${µaãá6Waß½ÿ‹Ê,—ÜD˜Wh H©lÕ9»nò}ooPÖ%|M¶ì£ú•[KÞ}ÄQ0ºÅ1·Æ“c®4­]­<Ó‘@€¡{gB–T!×íü7ÿkšÛiĨƒØ \wZëÿÎÍ}üA¾S^ªdϬZóR±š=å¾!«aÃözÚÂA(€w¢Ú·9Y†n.3´ Ú玈¨X,˜œ\”ô[ ä6ä@ÿvƒÏ•þ_Ú/>\ ˆC¨Î¼Œ® »‚Á0ý„lêÀ>f öaJ7#ŠœJÔn#a†}¢-’,øÖ#ÿ]ÙÑ03 žÐJn¥\n¬ðì–ÇážúwÇÌA9<5žváOádP(,0=õóûµ0õ¶JŒŠ<ÒdÜa¹cÏóÊŒ’ŠöªÌqò’Ö-ÕU‡Kš K‘Eþn~š ‰gËrgŒä\Qƒèó0 JY‚Ø%:óA\S¸>±ã+‡CgýpÔ…O ×Ê#ÆŽDZ0ƒQ$Ú%ùB‰=pX?Š`ÚÆ%op,LŽÁ;ù"[%é¡ëá<’B=YŒ=s}*Ö‡"~&1!À%¡5<Ôõ×ÍФ•6[ýµ˜IxQΜˆ¾ @€=õÉŠsJ$*IÆ &ê€s ‘q žÕç&éJ‡ö^'t3|JN.ôи¬ugÛ,ú2âuÃÔêµíg™bˆª¶cOJ…Ÿ‘ew­\K Ü'ÕÂÅgˆ,Ú2|cì˜N?|râçš; ðÙÖ{¼&èÛïðŸDæ/ý”Ò´¬( ¥”x¢ pd~ªÉ‡dg¹û?¿q¬^Çù/L¤Ê°Yà|Y²[˜Ÿþus¢Ž’Ýg¬Y«€@•ȥݺò ø[¿Z–UvpD‹KC¿ë#úãNx'Óÿè”0"ØiQk¬.k”FÞ‚Š8¨ï¿áPVÂ<Á&…¸~W5øËð¤]óߨç8¶©7ÉSR Ù£h›ã€q3‘а ü`IeÃ,–eJh½JDZê•B÷í ™ÃV‘éâúwöúçIì…Šë—( Øit$.E?­ž»)ÏìÄÂ[ ÔŸe]Æ,Ä# iÄô4" ÜÉ­Ü“±—Ì2ž3„Õ7ÆÈdt…jDÙþ2%áêÊPßÝG`è­6g§dß+éHfÜ?;v| œÄ“uõ¯ô4þ÷'q¥Ô§¨ãÏ·-“oºz5ÐÐoFÉhd›c¡»ù¤iéa˜­KNÕM¼Dê' ™ow}V’6ÏÒæRÇõúdzx , „ѯΛ5Éæêç­û ÇSå!úQmõÑŸî’¡«éhhÔ÷Ý{g½*­÷²Ö#’ÉáèŹëÊ£õý!Õôc =[$Ɉ¥¥jú~è~)Þ›¤;…eå¼ãÿuÕÊò¦C8Ì+Á]JÇÔ]ébiESŠÒAûBÇ1€zcJõ ¤5[;ʼnበ–B‚p9Vå .Êê¸ðýÉ#¦\•qûÀŸv1“ž„­$oÎ5Û†?N䬔Ì‚wyŽ:x 3W £/¸¶cúZGW^¦FѽŠ÷²ÐÿSdïggIû L2õþg•Ö`‡QB×½b… ~ëg¯ƒ{K<]_Ó!"w5âs™möß{½˜ X¼p•q–Ff{]åìØôÁóðW ]ëµéWÖ­×µí§™&É’¿'Š\4ŠDÕ)±Jû抶ºµÌ}Ⱥ,ù”بëJ¡Co"ä1d˜\àØl}-‚ÐÐÊŽg5#§…Ÿxiåê4GaÝ9v~q/œgƒ/âICÈüd—\¡²Û:òD‹Ý´ 7#QåÒ¯Ù3 L)ÖÏéüÞzVxÐٙɫJ¢JMˆB0ä¶ëXÝïmC Dñ_ÚÓßI¾Å»<Ûí,îÕÎHß¼'–ñ+N¯ÛúgýÚ`#›N.Yv"é>bÆ!4aë¡‚ÐkÔkPÎ !­wžmÉ ´?•ð |ÜUݶg°»T!-Áœ–uª^©¥p¸ÖlI56h³ÄF_8.SÂû§…?ÆÕ{ kAHÑ+Ñcóy¼‹çJnŸÑF÷ýÞSbNboIwûUC½# /n@^àõ}!}¹>Z¯ðyYåóK’Í2ýPMu3 ™Maù[!¬JVé¼iÙÆR-ôI©?zÚ‡í©Y‚Ø\ãÙ¨ çm¼¯éƒä¸…ô›ÉÏëpEß­av4mÊÙù¸OŒ~%¨(ƽ”Z„€’0À5Ú¨Q.‰ÂЩG–x0“=F^ÞöÆŽCŒ[ü±üz~kɼ+GíÛŽ\¸7¸”jÄCe¥ÁÕ^&%?@4ªÇ\} _¢‰w: Nçºve&£žhD)Ò1úN·£êëNõ;~„ ³÷äCïz¿ÏHb .ÌO„m†gäÚÄJPF_:Äïnâd‚„wÏàs3öåË5¶6]âwÞ:«ŒâÓˆ¢ê#1²¤ÙàŽ«Á_sçÚ‰³)|lvÐf?ñÂik>Yªi_z Ä‘eÇÐÓ+Åœ ¥Ý‹DOdžÝ„NØ”HL9²á<†<§2­¥Aàc‡8IÐ<äŒËòI ú/CËÒÄ윪æ3~?œ0 @3Û#BÈ,ßgÀ»>új3ÒKP\À²~‘Å‚žçþÚ;ùjx1~d˜ƒÀò’ÇàB6§Ì,.Ê?Xľjö쩘p½ýÞ+·;§¾¿o~-G{݈V8†ßRÏÉU¨ëÚ¤0H)X»ì\dêI[ ôÂDòƒ³8é–z)©}›ù¯…õÐË$ˆ>¤9¬‹å­b¡x_öbºy›]»¢Iu?ßc›ûܹ”­hùÊýU¤-FÕ¤^¿5"1Y6òfvïÛÂìÎÈ¢\q/»K2ˆTC[ßN·-ñÿ%Ë^"%‘ü&açDΓ2­Œ¤“©?áDXÿ4ª[ ÿ†:øåô‘Zè³lgóõ>Q$ð¶cö)øZMúèDêŒÄ\ÖÚÚ¨¿ÖOQ™VZfšÅ‡Iá)qá<Æ<ïÏr»Ò$Î’^ª%¡èýòyQ•©*ª 0†«ßnØ2ÇÅ¥AKÉã59Ã~<—åùzè‘ IL~¨ˆIÍdÛ–•FÜŸYôWE»¦¹òlë >V!®‘K—4Ÿ÷ ‘~ "?¹±\t’â r”,á¹ØéU@ÿ„SqÛÈW&^I±YÖ.=í ¨æ¦ç6«šûdñâçƒ ö]4À@€Šeþc|‰j&*ah£™glÕÿÑO#Tïód~íÞ=Ò€ @=w±™ûöˆ TõE9'ÅeXÙ†:¢ˆ¨lò–÷IêúÄxWú.ÿ~pŠÕéñbzß;’q>:t7é·ÉÃEUã¸:%G †¾á©äyRŽÉé„ô¥³àéHtü^Ô“:•§ÅÚ0 %«y¨‚`aÅ®Gd·á®ñIð{NA܇]ÿG½bØmêF£ÙÍÁð x•š|@õ‘ê´ª¨¼“ÿ¤§Ý5Ú“›ÑFÒÈ ¢±–ù+ <Kì•ëUMË…¨Ýÿ¿©ûßá¾™¾24Ô¿±=Vo! ˆ@÷“¢UQÒìÞHí¬WÛ‹¤Æy£k(ŽÓÂ<«Õ4Íü˜gçÉy‚‹Ñʼzž\·ÆÆ­ÛHÒè<àFm&˜m({Y©µi¸„êX3/¦{ú|‹(ï!òÐ:Eý3‹|Fúˆ¬YAý¢=B>APEÇN6.G~Ñy{Œ©[Âg Ã¥Z¼Ã–±Æþœ~ 6!ñÍ[+Ó€1ן3ïh§“ãã„@.î¸8¢û™ûëÛVM'õhã{•• )VÊ…®ÏWörÝÀ,w¦9¨)•$ˆ¬Ý;jd¦_eQ0õ__ŸSQëüó´`‚†1q°Àë\ä=«Blr}ö²3NÐðÿý½mÕ/<è­ˆVš$pZ•ãׇB•jÃ(»à¸QKšx”£Œ0\#,S& â±g–µµ/„6À—X°Ÿ9¿‹Kji|:7³Òg.§Åò€(VϦs]S*ã†óªæ&1«‡q@ÿ¨]l ÚœÍe%íõGǦ{—Ÿ¿æòEËÃóª]Ð ˜Â£Õ !ô .0U êÐãØÙ¡ßÒ7;¹¶j p™ &ÑÚ':Ím“YG{á =³Á§ƒæåŠš¬%O´Ë×=ûÌé†CaÝ……þ+mÖâ(@ê!Ð$ҽϥ.Ö“ïÿk·4 tñ׿wUU™¡p ›èê® Ûïôhhu¶Ÿëú»¸ñ½Ã¾‰zzÙ»&¾„݇ÉóÂÒ£Xƒq=W·¾á¨Ï5)ŠèûSˆE½çìfÿƒLž„ßÝž~þ²!ߣ “P,§÷3бS‰³âŒo:7”±î¹Áœ5‡¬]`–²¬&Wò<Ø«`N~òúØ+ÝpÃ÷4ðukdžŸAªŽ´úóËÚµSGÖûA³Þš jÈaUÏd™z‹àÖÚlê/gƒì±NÚvþØVß(xfnæn‹¨–3z4Ö X è[qÿÿœûÅ&e —rC‹‡¢ g©º=ðO~DV÷>˜rJ‚+ϳû 9GŸO~$l§že5Ä ?§ÙÒ$oôûôÌzÅ<@õh-úcÖw?±æv§ðvB(õQjã÷Rÿz‘< õ9;”U«Áê5â{½îж®×?瘯~=KE¹LÁ±1Q{±ÒtŠBýÆØâ!D8cò6£5¯¹5þÄr@ìÑ—’— w¯¶øýe=”yaÛ†dµIx_§¦PlJÕtñá_Ãä´rÀ—XßÙkk¼CJÈgÌFŸmÜ)L /Ì*åɬ™þÓ?ªVU-Ø(ˆrû:n¬b¶‚N¾À¼Ëµ±52?"´Á üü@ã«¿]…Ö Ï*À£Ìh®dkE3¬½ÅâéƒóÁÒUNù•ë\FÈš·kþZJ~ ©/[9[hÇ~ÐcÞ¥Ê i¾\aá4¿.Yö?Ûcµ {-ÿí2®°(mž°ÆòÖ~A `ú$¤ÍµH/ª‘+…h»ûWtÖzñ²}W#¾f"® Kž4'‚‡èoóO2dŠ˜CÇ…Býñ€ œDæe*¦Å›H0¾‘”Œ¦?(Á#hC4ÓpMþý?š¶Æ<æ¿,Ë'-ëcCõiÖäÕ(àZEŒáß/ÃÀ^À ½W¿z÷ÌÏjU”ÄEÇ%]"Ùw¸íuûÞóô#=dÒÕ‰Hü¾éAP_ôi=óÚò§åK1Æü—›îðíÜ “ÿmÿúÛ1B*`ÝX@­Â4ò»D Ê¢a“x¹Ð<¬;ùUçüù£Ý ¿3Ý8á‘ô˜kþ ŒªÚ޼„â³%Œ=e%Ô Û˜¶½Sôaž&m»ªÀÖñÈ™é!»³!µÛoZ¥Õ¨§+ô”l£fkŽÏ£§ÿ¤Ý1.T³ÿçú„{õ)Ü”C ¾1ðg ÂÓ…Ž;RøùÒÌ¿Tú­ë_©öŒ|œ—ŒN;r \NÝ:ÏzáÅ}QäÓ ‰x"ñNCD<ŽD®nl–ÍWˆÛ¹j¯à\`eü+lHËnŒ'^u[¤”äXgÌí/Ç\ê¨8ºãµ$Ѱ=‡95µ‰ÍÂH.áä™Úcá‹L«§í·æ.;Ò.·>œ³Q”uÿz(—™àÔ´ÌT1™™9ånT+å»YÁÒâäçÞW« 9¿yJÿ¯ÍªÞæªv¥‰ªÝãM*™TÕ÷™•Ýe>wÀ})õ-`EZ¥Ûþ¦8ȳ4¾ßÝßR;¶=ž©Ç_Î"/Þ¯Íu<¶k÷8‹•©kõâ÷vÙÉødW|έ7ÇbˆÈÞÃÿ}q·¿‘öŽ‘èÍ6Y“ÿ³ú O¸cûç”ÿûM¤>ùÔx``¸#¤.¬e|ÂÚõÜ8:Å>U¡êoèbb²Yë={ç[½ïO¯[dBB½ç´©°Þ3¾»Å¶Hߤ-¢J÷¡½¹o =ΩGwØÈÖ@îC´©4j–CjúU±c\;Г«T&·êw·X–;Š•äGé‡mv-§™x[Üí]Ï%ŒF§¤UÕòÕñ ÊMÌeÝß u S;î´í¯…äœ`ùÐtÜÍò¢Í—›ÅŠñÝnúæýñ«|)ˆbzQÒhô=óÙIN©Z2 ^×Xˆö€ÉçÆÔ±+ºS_)^p^·>ýÇ·ª|º­G|C%Í“‚®T3ÿi¨Ç·­J2æ¯r{ž“5—îT%|JݸF ·õÖí£ç ±iéÏ×ÇF±—ÌdéÁÄ›(kJkôþOAFÝ`äú¿T’Õ{ Qrsªˆ#ùü„ÒvrZiß_r—’í ëE=È¢Ô |7éH3åÌ>¢&BüeÂ^ý=“øâc8'\˜¤™Œ c«8YúMÉ%ïrâÞe·Ÿ+Ö2±ò›•˜òÏÊdü*Y-ëkÿ‹<Õ ³Dȧöä5û­þŒ]4 ;\¯C™B÷u ŸS4(”ÿá#‡áÑ—Ub–OŒôèÑ•(¡K̵OÚÿ¦v/xÞrÌM±¡S×KæSègˆSÖy¹zû¼âY/2>Ž5=:©h4Á¶ûoŸ$§ùèðªøÍ`ˆê›·ÒŠˆ`i…ãV‹ºšRÛ×.”þ\â?¼Bß5“ÍS±JÿÇ‹gó¯kä‹–ÏDt²ÐI!›Á}‹Ë3O²¡+zj°×<öø•¢ÃsÇ“Y„ @-ˤEï¸9O7ÿí2•XSöƳ…¶M®“/©ö;›ɨ‡ÿ_XTf_QÁ[¡”«˜½aÙ.m[.ÀCÈêo‚XrìfQ˜ûˆP®Dü…¿uhxÁÓúÞm3Å–k¼p¥þIXŒË­ž¹×îmÏé{‘Aí¬43sôO`†Ê€Bÿt·þ”ýÍi3aw‚RÉ6"¼‘ g9Ee¬ß "÷ÕxÞªdÁp™'$ßüûÉÚ7cìÆ,«q¤šŒô}ζ”ôÖG¢|ð¤Í¯ü3ÁTVÜ”Åïvnmzå‰dó)ªxLü$ôzÓoU 1R˜]¾p¬ìͤ[]ʼn¶¿ÏòRjÚ#aØx×Ò8+4CóÊ Ãð·)ÌËUèƒúDãù™ÅªËþ }¯NÕ.{¬Xï¿»˜H¶i»˜èAêôËÓ[eøZW…Méœ?4£rÒc8ô|˜€qdœøü²Õµ–GïËá5WZz„N‡q5^ÒÄHÑ%¬2öû¸¢Êˆ£Ï1¤.¤;¦‡°ÈHÖ`èÁ`ñ“$Ây|7ô ETnÃA›agWÞg¼§ÞKÒ#'Ⱥ!»!>È®=ûwÉ壎ÊÞbÑÉS§‡<‹ó0bϽUïm•Y:hS”üW¿£}µ=¯r -Ï{ù¥y½^‹Ï®_ÒàbûîÙœì;\_•Êø£×^ã-s€ãÊ‘ :‡äþuEöÑo–¢ñöèÜýV,½®©:gÛ‰KI¢‹[±º°ÇªÊ$Ïß]›l¼·èÇ Êg]­AÊ‚­ìÿN*¦*k×VJßlòÙªƒ:åJ£þÌau2güÖ%[îË“+åÊŽô­S¯¹³;ƒÉîaÇöòŸn×E³ózw ¾35¸RÖ5½ØšOD¦5çÝÈ»³´0þ1kÁK í=üÏ·¢N„ýúbfr¬Ÿ©¾ Äÿ–sEý[ýË_Óï:QïÌ Œ­^"ŸRνútå'è¦öHÏâ×èæßD[TàÜü Ì'ÊH$õâ—Ôd ÚqÌJ RÜ+•ªÝ[¶íj;¡´Ò±Ž|Ô‚•ÏPS«BŠo«G=`@jz N€Ïë7Ö¦¨íX¶«{fÔBÃ@û›× %ÏrUùü¤ ¹¬_\ê’߯¡BC±|Í”,`[ŸR]´[Cã~§í£šþ5 ”¶°Å]Ë?')Hú÷× ±Ëš>i«EöÄü•ã$q\D{ø²â“ŒO-Ò#:T¾âÞuçDC7˜£3ÓÑRä—SsýµJå™{¾ÐkÌPJO”²»Î”äÏxàX†°„±ó‡(dö câ÷¹w Ž5C&Zð ¶÷8h²83´¦.c …”ÇT}Ryôûq§ÍÿK†·LrFÝî(áU“cç$hÍ(l®”ר÷Ñ·ñ­aëx«OÈÙ!$ŒŽë‘Ë$¡LöOD^œý®ë×òOò€2YKk<¨12ø°©{l$ê>zÃS\˜ìŠ‚}³¾&A9D"?QˆÍŸù›+žÑ!BIÈ!æ>ó”¸>í*L¢éÙë%oãˆÚéºãa³¢Qí!fMAbõ“õì Ý®Ú9µÛt[Ü}V©¢@@€&³”ýYº§Mâò@í—ü òÑõKèá1êÔÑîË»KÐ/M:ì)¾Rœúh\p< ë£ÜÔ{.n,©i¶Vum¾p«:Nn ó½ÑÂ`,ˆÈÂA[ '¿:ø f5|˜ÈÐÝÀÙ$­è‰IÞrŸ¿Oï± uQð-EVG€¯2sõŽlø&§g·¥VÚ+®¥³¤’U²¨@zÕ„Ñ+Þ<]™º|™áE±D#–¾Û8ÍF‘ @€9ùÜ_Ô»y pú÷T™Q)¡ë0¬dÿWŽ‘J¢à¿g ld”å?N¾ Æî"xæ°–©wrPgŽ&-Z‡6ºfœ‚;ÉR±ý9ºÀu@0øn_Vz0™ Q]:¯KäÜÚÈ­>ªŽ-ˆý– -‘U]¯|$'+NFõ©—¿dµ³¦BÉ?®àvósŠx(s‡{É…pª|^ƒ¸®&QÂMáÁ!Ôþq–æŸÞùÝoqI`äsaºP€³´ýw[j·˜žá'µ  ÃqàöÒÿÄÿæýÏÖøVŒî­—¾ `Úhg%‘ìºR m{%˜‡½ÂëbF¦½,5‚¿ucˆcë:@2yÖäm£D|Ã×ðl«†z4­@HÒóÑ¥Êfû”ÅÄî¼(ZäùVÊþëûÛìdܧäþ®’VfGr±%b&Üþž=“<Ö‚*0ðí>·Ë¾üú–Á§Ú5º 0']«yT 9 y9-ÀŽz·¥;¬ý8Ö>+ÈøÛLªàøø¡¥i®Pö{4nñ!牡¨šè~q“‹™X‰œ BQÜI•2Ì×g(.3w eƒwŽ’7åۯᬠ0•Ü‘°½Ãû9So|ŒJpý"¿àÕU‡wÑìq„_¬|TÉ{à5CódñéW£DÝ1Jz0¼ôÿ;aבrÕÖP‰,T\÷Öó×(Ÿ»ËÅÛgHåwƒM´Á¬Iø2^ÁÌœùn°ç}Ôu:¦çÂ0"â'‰º‚uŽq°‡Ì1ù˜»ß ì²&‹¿Ùl_ÛÔƒð$#÷¨OVµÞ«XQag>ÞHÌR»Ó™KÓ(ñAåžõÆ'µåNÆý#™î}> vÓî¨\ÅÑ5eHŒË—b4=a·qåz³“–­4ÿJÑùÖ·ê7-Þ¬s•yRô·#+6û·‰´B"zÝf4@‹"±õ?Ž›¸7éÞj-çëk°·èâç ]Å¢ªJä‰jf0ó ?®D§fXê[B³ãòfòbêó§N‡´]M-®Ù˜œ0bQ-Ð+’n÷Ó¹>G¨ö”*’•ýú ]E Î%Ëñ¡i®ˆ¿gP/dö2«YŒõ M\‹c¿Œª‘ÈvòˆS šoŽ¥3Ú×¶÷ìÉ"&’dgÅAæDrt7ÓtÊ5ß`=m*$øtøÃ¢ÈxwlÝ@aÃ)ÖΧL³ûºÎ‹Å£î«R=‚ù•Sê­AUzD?˜f8¯O+¤‹0¢tK³âzˆ56ý„©.+úý¬’/µ,“èÛþݪ¨}¥|— Ëz T¬¼ŠÏAF…—~ö í%Ø·¶ÒE2ÐL>#xÎ…¯[ݯ6*ôIåæÊÃ;¾ù*“W@¢N›D’÷Sïú‹ôKÓ5Äÿj{&‡Ôì^¸nlæþ›/&|ëR]‹ŠõáÐ[T”yÅa«ˆ'þ~áÏkñ•‚·õñTBL – ¶"Ë7 ' l¦/ðM©jhUõ†?ØNxÉÆH$¿¸ÏP?eV¸Ç %¿¦‘¦yGesA’as ‘ «á¸ÿ¦ïXc†*¹"• „f!Áä†R98E6Ž˜óP)ãWÍñ‰Y¤—ûû‹|`Ê}ö¿ãZp’ìJö×ãjRï‹PÝEM¢BÚŸ×/ž¤oãÆM1Ó!ú8úØ ¦Yà[Š¡&1pÕŒ6Í¡}IGÛçÎ ³Ël/ì"OGc󨬘 4yK–Pñ)}ʈ]ãnsš›çøÑ#¸Ym¼Iø7"FZY¸ñ<Új7Mê:g¥2§vVr;ýÊvQg‰Ù¡Èº…¨!…4 ï~îxv&q>¨y'À]0o4†À+|(ŒŠjvIËœp ÏÙ wâ¬ýS—±RqíHúxGÞY~WoSý³¾pƒœè³1üa–Ï" þ[÷&©³¥6òÒ%~ü~û!‰ã–,wiCÕ³u)ÿ…Ã$Õ\`O+ŒTv[W«"Cmká¢ß—³’v²÷£2yj­ì¶£elæÄu~‡âMúÃô´¹‘L”f”h{9—8Ò´z-ïÔ¾Ú“ëC÷;|–¬îÞgðô” 'g6RÓM…¶K +³±2¦©¾ôˆí‡šk0ëp%LÿW§ó"q<Õó³qÎŽsl·|ÔÜŸê Ôõ·½Í²â‡f¥«$Š¿4Àj‹1Gƒûëúf<?}V¾§‘Mñ1÷y³7©•Ë¡U·ò(½+ Ž;üT¨‰ãÙèÀ[µ3>›ÕˈÍ4a 1¨×R¨³ËÂI_Ócùß)óhœk€Ç¯Ë® 1ŸyZiÑk>Œ*iÆ[iböþ¾·øëí ŸøD+žÜëïyŒüÇIe{œHÜ™ü¦8ÏŒb*³ë@”Ú¯ ±÷·¯vVJÇ’háÁI5G¯zεŽ0cëJQuÓsA¸:ýŠèaè2Ÿæ~»¢{K§ïqýoïÛ·@€Nz;AWw5’?´n+°bØ¿ÿX±Ç •Çœœˆ¹ö¯½ÿ™àzaë1 ~$1ß;¬x‡¸¾XfÿàVϼYWm&•y.Jé¹xäyñÒƒjÉÃòJm׼¹Ý 5Ûò*ô_7kõÃG4ÎVÛÜvñÍx·Âz…p:yVD†;æ_Ãh+ñæZŠö0Eˆ¥>;'Å£ 8œÕæ‹„\7@‹ˆÇ­=6e9ò{OC^¬rv'ŒÓJ!ßWv[·Ó­6ãê…sî¬EêÙØOî;Œ3@CL¨o?ÝN­l…‚îŒ]7ýŽÝŽ~CuÔ,(Ì ª¼@·Q²;eM¶—ÞòÆ•TýL¡zxÜÍÚwJ«4úà'ú¸o,ãj•¯_¿Úï&¾ñ_Si!Â*³óE"¥|þÂó°Õ(ÿ3ƒßjuk[ËSFg¿'ƒíŽù®¸0qŸSd=Ô¹™K¯±kõÝ5vý´Yɹvô]·¥öy‘êùºDžN”>«uÌ·ÿoÐrm”Hfë^!cÄä2|v@Û¬Vkñ˜õÃÜ›—Ÿòø?j¹®ý,»ªê“´C#íÀ|fºéÛ§YˆÈ.Ðx˜câПy2G¿"+æ8ÒŠx‘&®0rý9£(éìjöö=HÓ¿b}_AÊ‹ˆ¯àþ°K!¾Ž&9rVaB±í=Ýçɘxs¬î2!ž!Κè®4,¶$}ó¼ßÖ>jkÛö·!J=£ûjÌfsJ>’Óœ~€g’·1ì1®ê±shŠ-U{/kÚæ[¹ɪè¸ú§Þ…Á-ëÞ°ƒô?Ìùú‡Èhÿ|Œ™µÈÇ8p÷´T¸*óÿÎfZ¨U,E¾_mŒû‘ü1‚´é2$&‘6 ц‚Ѝ:/÷kL왩ÜÂvÂì˜ð¾ôßRo÷둸€€-fÎ;€=S·†×:vË«bu@n;óm+º©îͶPÇbg³g/»¿×o÷ñ³’ý’ãMŸ ¹»Ï–h¤ÆÎI·alûy”=‘¾ßm%æ¹P+OFÑ Ÿ¢wœ {?¬&9µØDÿ0Ý÷©–ÿÃŽ¸ÆrÒíö¶!=®„±±÷s`€¤l ÄyЪ6³#Xë5§÷\‚ø¾YùX,_WX{!€äöñ ô¯ž ÒcvÔ|ÇS*:LVõ\&‡œ¿è­+{¨Â Ì––s˜Oƒ3Ÿ™R˜¥îíÁqM6J.Iq¸œÚßkOW©BγºXrŒÂ» eq#Ýþ%ŠûÁ¨î`@W‘ ÚOl<)ûA_ pðšh³KåŽ~M'(¶›È5k¨L¹x’\œ4V¸Ú(÷óÉMÞÐsÅG°’ÿ‹# :u{n}¥Wú-©¿|Û*³LCWY©j^ÏB¶1ÐòÞéRi0ˆ‘6F‡!O1ˆÐmt{ã?7\ŸÙÍÏ`e¥_ë¼ñ·¥ ˆŠ6Þ¡ñ ‹òÁÛè²Úîø+pKÚ–Z꣫E¥ÕE2b+~ÚHýT÷çç?žaOóæèî×Y¾M¹¡¦j‚õ$éHäö­¦áj@·)•Y[ôe˜£mÏ ¡›@ëJCŽ¥²½úY­HÊL¹ê¨•7ñV”_,e™Bz$à„zïÏ£ ë^ ))Ò!9ÿ¸x¨øñò6%tB.:¢“V·œåO™;$Ýf»‚¯Ôö¢=SòØM\½ôi*%ÂæÎ 5v‚Úºû‡z:Ù°S|AýƼ>†óÆÓ¥ƒÐx”Â3qQZ&Õ[,OUxÝ븪¢¯?ùe³l(Âöº² yRˆú DIŠ=I+uí&Óžj>&Á–Æ2Çõ6T‰þ¼›©†ÃY3±T÷’ÞÜrRÎ(÷šÃHÉ`¹ &CôúX×°I÷0Ÿ´ ÿÇäw©Ì)Õ¶?¾NÂ%ÚÿÜ{±¥<”áŒV!t–;;.ñˆ(½I’eNŸîÂü<($*p×oÉ?Úv÷0¬8Ú9ÚBÈs–®ÿ8\Ðuq|j+D™¤-Lе{úåöÍå´ÌÓµ†è·TÌl#µ¼Áÿ«OµPq\îdXu.ˆTxâ6‡P€ù6Ò¨1s"&2z;=Øö©KI7ÿ<+†ÒÊx³Þ¾Û?-Ëç‡ôž#•Y÷E‹¨òÌí€ÞÐáç¹ÊÀÊA™°Få{ÛLª3­~ckñíE6ì/”—Yà_³V\âãa0%`dû·$hlܯ‹ë‹¤ÒQ•öwzñtÞÍÑ>k…š·Ù;¼„ˆsGÜð=i-Ö±Qž 1 >ÒÚ_zR¥c YÜ”ê,â„‚Õ#AK~³ú‡è#ch¢Y¢‚†íìBy!`’ýOH"ä/QV»–¥Gì¾$›—ÜAf(É¢Çý=E݇e•XñËh6 ¨½º AÕ׈¦›Ty|ûhøXœ­oTÞ±’ÚÜIÊ­úîÅ®3V¿È;’‚›Bþß8U äƒã¿'ÅŠŸX‘ÍQ;|¥r‰8öp1T_ǹ!7 EÚŽ`Š~Tr×Î ú“½ºoOô cƒj¿!sêú•ÎÁ`Y¡ŠÜÉ%>áÅ_6ׯ*ÆcóÂÒëÄ]®ýÈ“&£Î×t2auç¿U…ª†Á£§yü´ÛqÏ /‰*Þ›•w Þá츥#™çÚ¥žV,=÷4ÉßQyœï2ï—X¸÷»HÅ[Eì_{å1ƒ/›Ù›|ÿ=K¸æˈ³?µUÃ'Ú +ÒÑÕ7f4²‘cöXñ\÷ˆê™‰çz§¼£§SZßKÔ!ôã¦wQ^ÑÙr…!QðÃ,Á;áY¨#jšÐõŸœ"Õ<ò‰™kgˆ”ñ®¬}Ä+IAFàöo_}¨b6fS.'¸%Î*€T•“ö¶|sAdVºTìù÷¥²øÅÃ1—FY׃¡ +Û@€hP®SnDù6@¥Ìã¼ ^¸™œ50uÿilï©.9ºÚýìÅj£¿“×ZO) ,t9° ¼ èR£à:ú‹ýã•>ØdÐs4aPe3ÂK²¥8Þ­#Ê×f £Ë•ÒM»;î¢rns ´o1ß/ÙŽÑ.Ö+ÖhüN†]Ž2)I)gödÒ[>½¢¦$VMäYVÿ-’½Ë«_:%/a"TéZ[ºá…Á'äžÅÄÑpþÈŽµžÞõ‹ùL¯Éú]õ©’¦Mz-š¡‘ùÞCL™ú&p‚î$Óžv¯ _ ûg»ü0œ[Sewð‹w%öBœ³ÏÒSV—KGo0Ä/D•랬–(³»9ûP7; Y†Ò{œÓj:Œ½æ7¢ö›º…É$T^„3‘ÊÜOÃ!Ã)ÚÑÇMž%uàc]5ÄGÄãù^ç$¤0_$6¹Šàr3°8åyiß¹×âh";MüãL”ú8ó^‘˜Mã"FÁÒ*8:XuÓ2¦÷Ew_lìBçòþÚ'ÜJ6É Hq—õæ¡ôd?«"‚öâÔñ C+†à¬¤[5@ ´¨3ëTở.æø²ñ }DO8a—¶]ÿ¶Ilû^oÉc5±UOwÿXNIŠÎÃc‚È?w¼½¯NçÁÐvTP<âj²c¼vXgË´¶‘ÕYLCFƒ-SaI–½ü„ÉÅu^ìäå˜Syè½F›¸ìkÖ—ËbJ¶•Î 9_ÜçøTÃ(Ú•ÈE2Z"ÁÍ$8š©aÁä¦;ÉÃSL€³¬Ç×V¸Z7‘8ßuEçDÖŒŸÍr|àð©`§­²މrñOY¾«M0Ý<=ýçãûhË]ê˜u%‘ÿZ݈@rÇÄ=×ò\§›ñšv«àW|E+7Š Mxo¬±øãLFÎ Ž9ê,_i©oIÚ>ëÚ¶Û¯aSX^ýoëì#ôµ–ŸõêqŸË¾ðêËaVÍóÊsCí%ü‰.ÚPñ.e²HÔE3yçïûÙÂѼLÝÁÃË´üßñ‹´Ë•ƒÊqi ¤^TþªÇuäØå­sÞ'˜X4œ·謜X=÷˹Zæœ{N¼…&Ðu<8µÝóã>Tä¢ñJ)5i[•ŠÂ<¯îÝVYv“9WTXÅœ²–|—iºq«?–Õ,îHé‡í¹ƒõ~Éù±%į¬ä_GŒäÇÑ® ] 1…ä± LôîiY%ì/Sÿ˜1ĺ"½uF-¾y0‚P4§§LÝý56--O=g•F²$Öøa—ò);“o7÷žÄêìBSÆü;æüV醒'&&7( ô ¡ã•iuÖA®cŒ ^ë‘’ÕX%¿²¶ß™ëÔ!È„@»°âBŒ£kÊžákOS±4ËS‹ ³ûù!e£V[ä|@„†någÚª¸òU‚2{UÅbB®ÐûUCs%jüÎañ#«Õð‘3J†+ƒûýL.þ‰ÓbÖ«†žŠ¸tÃ¥MÚ²nf·£ý¡êBZª‚Èu‡öC}\Ä4bq”Í@À¡´¥ Þꔆ+åLÜóĵzýù:ûŒ±‹]v…¥âLjN2ª4”¥ýƒtãl޵i˜êµ÷Hi3ÄdHÕݳ÷pép®ÃS+³%Åï[I} ¡PÑf„3¡<¦RQÛ2`ŒnÎE†Cüp/5Ip Söü‹’ÛE}­-D,c Le÷¤Y˜ç–ýâ24³ŽœM­ÍYV)¹0ëËßXëã}¸¥B~I¡!]´k¡-ÈŸœÑ'/áÍí8ç ‚Ã¦Tû‡'îw[Ù_õ6ñoX+„7§æwˆ‹u‡ Fùž¤ì]ÛT³ÍÅ%j 5«—Ý|ÚcVገ-¤‘Ï5´0ÜîUÿõ¡¾`f±²ëQ?7ßÐ謃6°«:e§2~ àSQ’ÉÔœ%ôq·xfpâzb·!fÖu$X°=E£‘Ca¬ k×~µÈ}±€ Äáü°ÇbÃY›uÒŠÀ úÅ8âÒö=ó%ƒ¾Ñ¹àÛÿÉÑRŸo‡'Ïý÷Ê.Pzy¯Öt!ûq €ûVLèhñº¼Œ½¼ÖSÄÒ-|4X³Üœ£O XŽMS m€Öì01È‘"@@€© J_ûò\¸8Ëæg¢Ÿ¯dzVõx?ÖÈè ø¯dJdC2iaÙÈGÆTø6;´«Oyçá!<í…9ËJçÔ[”îk½Jéì_tväÿE™¼µ9äÞ[–Îäý¡cô–Veu5 ÉTAtp„v½UÙZc…9î7ÇoÍà$ðóÖ€76„ƒ ±_.¿†l¢⮀î´r 5 ž¤Êyó]—2³f¡\‘7³ôe}û{bÑDÖgÛÞ¨ ‹šúêi”½à3ì=ÞÅæ¨BÎB/vóY:@‚IèÛ,mÌìwqžÄ‚¬F-ÔƒB1ŽÀ#Q–F»ú@5]^»S}_Z§9ë. ÜÆÖ'%Ð^ôžë_á lÌé :¹ÿ"þ¸Â¸—ýwd¤o_áõd,æÙq»†=9©Ó *gFò:æ n7%¢añhUõ†Oû F]Ý‚:@]ì úy}¾Ç(•ºœ_óýµÒR¡4t£º­AøG.Ñ3=Û}ˆ;%¬ê`È£ˆ!ý)Hì9ÛHG –±Óà˜jËXGI¸Ðß.<`¢=CœÙû—=3•YŠ•8ì¥kAmSžê” ÜÏÀG‰*ÖÈçŸ<ÊÈÓ”èÖ¾Lß³2]s™Ó‚·Ò¿Ó±(b«ø,‘’’ußµŠ'KÚÜ4+d !Ô]žœ²ˆU©'¸9B÷¤˜z`¶É¿«™5.Ó +käõ¤QŸÔ=ßpØ~hå\bpLÉæE8ç=,”!Ô[Ü,kð+â„sªÿ8nÝÝÇéiºà¼Ë%—7~_tnóÕ‚öAº{m^xqˆÒ½4Ç$ÞÕoH¢ñÛÁp_$ê¤í5*gÅÇb¡tmr‰òÿÚÊåÛ¢¼r¾9'¥Ù$•È7ÜížPN+[6ýö õ—$¡ÓýdA@T*†Aaë¶“"^Mé5JJ}ÞÌé¢FÉjêšø²<©ª‰'ùC6uLʘ¹Ü‘áŽ+±‡£N€åëJ¶vÛá”ò¹lÿ!»ëþ][%†þ¢¹¨þUVäÏ¡/õK*•½vQÍÚû5% ˜›=fâPˆEÿ.{IÒèßÊZ¿´L> ë±-–÷º#í&Uë4<Úõ„§•N0'Úcÿ®Þ÷G+ù»B³l²sÏD›µ­å)Ž4€‹ËØÝ«ÚŸåFà°:£`E`b¶ åû˜sþà æï]ZZQÍD/±¾tˆÒgZUéÚ8¦-ÄòãPjpΪŒ^šáò?*½aO%4SYŠ|—Îõè잉%ŽiüZ5Õˆ„¬S§ëK_–]9Éx̃œVfFv.*§²ãÐCî)(g²@&»ºšuÊ··XÑ%öZAzT?µû«ûÎ ¦’:æbŠ¿$H*SöãT¢bxÕA$©¥¸ 4%¬vèáî®×“ó²Ö=Á½ÎÃ?‹Gl.®$†ØÝÓ*K: «mZ†0ÒB_\?äiíçÑ+ªH’•ªº÷×14‘l@È¡uuä|¤æâ̬êTâ#°qhÇ¥çâ,„]¨dS‡ÑGÆ÷ñZ„¸}ª®ot@¼/°a½?Ÿ_÷8ÈâÙWhŒS ÌGå(“NŽ{€šœèrcåqýzl¹™ ½uôѦÉüd}Gå0ýco°Ï<ãdçu d„¡Ë?ëfâ ·¼šm$Ž ó°4‚vI/~€Æôà‡U¨‹D±Áeùz~ìÁ(¨¤õÿ³C±›·½Êx*Ñ.4ó8ÔÛ—ŸAbc+‹«u ugç5àD¢ý%¬Û<×4¨!jvûuèØÓ§æqýSŠ,g6¿ ëÊJV Í/ª Ðþ®˜ótü+ ††„}Ð>†•#Óx[ñ… þB]¸Ûwèx(I/ µ‚jCÞLÊ ^± §Ä²LŒóíh-ÎFÍþê…XÐ̧N,2>×g [q#ùÙð#z|èÛƒ4‚žÿ«é ’›w­s~¥Â]¢pihïÆjÿ¹ÑìÁ~ËÙÌ}ÿ´˜læ\iFÓÉ^v\U=IZ’ö„&üõ¬ nU% þl_½`JäúK>|LÿâDñ0ˆ5FxÑ;¿3…÷Ÿv)þ5ËDÏÁ{¼œ-—>þ7ÛÊôÜ”siò*οpË”™n+×õ„%w‰ÓÑ’™‚ÚØÈ~{¸ûaB§ÔŸÿ¨Àh4¿Æ,˜dû圧¬hÃuÞû¹¥,ý$+YI9«ø¹ÒÿÅv4êJeG»jÚ¥+7kéR› ·Ÿ{¿•ލª0 %³µ~³;K…+%ÿ¿¤¦VQàRÉCG"ħ¨Wñ½ Zqç-Ã\P±J >@ÆQî>“sû` á˜P 29ÿ‘¬Ê˜…ƒ6“3/0@´`Øëú¶<ÿ£›'A¢^â[hΕ? C†™:]t‹í>3»ÊŽ?záK-öµí_¶Qå™M5°µQcs|3k&ñ˜†?NÅk‘¶í ØÑ“¨é?©Á‡TpÆtVô¾ŒJdÆVH¶Ì·$½¿Ù§S’"à†SIgð üJpIq˜…¿%Eë$¯t“Oh«-ð·sGÆŽXYÄŧ©çXìÜ3j„<~ŽiËÚÝOf*Šë>bcwm¥ÏŒxR3¾Ç7ã7‚âdzÿwCÉóÏÕ8)ÜÌï}Ì8±ÑM’2|çÈǘ±<(¾ÔÝÉJýþ}2¡mÑèŒ>¡Ô†ñT;và:<åÒÿ–“¸q”ºýÖTÉ-Ut+Ä•p3;½É™Ì&GĺüÞ.è,ôM*bR¾žd¬•¯ÅSk.ç<¬ðã¢ÈÃVz,˜BäB•‹ë è1g3¾bœäÛ{{ßo‘åXª‰±LìMt¯È©ÇÉT¾ hLµ|µ™>·-dÒ“õú—f6\lÇ#TÝSÓ>C鳚7”鿪l¥ÆM„¤B…)öà­Ôó¸n.#Všýœ±ïïf?^û:O‚RЇË;ãFö`ÐþUØèÍþ7-‘à~¹ ½ï/‘,dIáßè„–ñ[¦^_Õpz´È ÷u°WÍ3ómbØC,QckóœNäZjhøªΕ-âøû!ß{Ë»Õö:¨oÖž¬ÓˆÞ½[‡I­ZÍÿP±ïíý÷ųJ”¶ß‚4$cÇ`e¹Òø•¡¾Åq¦¨ì+¬ÁçÕÑÝv™b敪”K¼™»>*·I’޾Âоº9ÞÿÎ0[[ßöQ¹éN§èV•ÕÌ.X ê é˲¢Ý;•ÔyA,|z]lÊvó[V‡˜Ä-M MòÀ~ZêToå#4M1jvKëª ”?ªK‘DtÞÇ"èÉŠÈHhy0³üˆÇ ^ŒÜŸÜDå„T¬¡0HR½ðÝú¥&¬:8C°ûzà«¢÷ݼõÚ= Ȫ¤zz0SݘÎn_f\Ž1}ׯ–·å‚uí€Â'YíûXO ŠGÍ‘qÇBšñúJs7YðT³˜…NŸÌv\çê&ñAü­ãUF~vm©BÏ‘3ýwÂÖØÝ }VÓØnLàcP"^y ½¿ÝȱàZ‰ÐœÜBûš‘…SQÎUŒyrÌ dŋҸÕ/¹3¨>T3x!˜½¸%§ßY¿Ý³‹(Ö÷óØýq¡”ç§±$iÇúÑææËæçÿ§èJ=W½ úp?TyÝ,î"õÊZG0[žõ6M3a2 7Â[Fc‰œ#ÔÓ;k|“´R²oNý’I é¿¢p&¸PG¡ç(¬)4Vþ› ‹B×Av\ýshœþ›Žß‚(G,Ý“«ÀÝîûö^¸“…¥1#ƒÿŒ@Û^d4¼÷³jôŽÚký[°Ã&ÔÏs² ølO†¶éw§ÃÓBí>H롃Зþ$ܺ*Å™ÀÉ \)‡ÝñVXH¸Ô§ß|Ê«À)ƒlª¶$3ŒCáïZM¦G¦V…‡®‹åòýÜž®Î®Ä(ÕwÝî 9$h»Äó¡O›oä‹Ñ˜Þázõà"ô€$¼c1uÌeRkrýů ¾*Ãá-ðNGòå€dîò3xñvO›Ò=ÿU ò“¯éçLEœî•I@†{îì‚Ťfl.ºÛÁ_Ãq€*-‹å«3ë<åÔóc®$°Kí§ Ùõ,*ÕI§š'6acS<«Kg]ÑüôàGPG;Žë ˆC¾x¬õ±zò=rg:n:¤"¢F’„³— RøBŸ3Á1½Ü¾Õ [4£M”¾{6ø¬'h³yn9ÑCm ±%ÌŸvÃû.è­|» ŽáÊ%¡NFÂØ¨y­FùçTlOîZñà$—¨vmY¤µÍ^T»ˆãyE¢®'ú¨–:q‡Ó$r} Ï„èüCˆ¾VÃÜ ‚Žc.aý_½½Çη%«Hå¬|œ‰Šjžæ9139…§% I(èµdvÍX—ÆâÆÇÚDÁÉM\o;jUJáF@í“Ð^#ù7ý'¼uMÙ_â#è<5`æér”]þA(I” Á ò ó4%{i&PîýdG›Ÿ¸ÛôBFo|_bãç þG0t¿mbä:…C÷ó~ ëöÆåŠêŸ¯ î’9“­× ÚÀš\üô½yÑI ¢ZÅÚ†M{\¹¼§uD| ì³ÈVÂË/(Òèá+¸ɹë¬`¼%3ÆÎ®Žrw ßqÑŸ§ áÐÞï»Ê ØãÊ(…¿p¿_Š ¡RȈAEÊiæYÀå2 ܲŽAÑVÞÜ!uñÃhÐBÿ<óÞå¢òêÑkÂ%ˆÃã­¶ô)–#è—»Œ}>‰Ö™s‹øŸ„Ù÷ãv¼9O”3¬"Æe– »e¦ïᨡ ÎK?p€«rkø¬Ë¯c¨ì]ù6]…âÀPUoÀ¿™(‚&Qê%´¯áóðÈ®îA)øóЧçáK•ÞK©üØÀ¯k¦Þ‘þŸé]r³OR(ƒœK=eI7òj"ª’Ãú p?|\–ƒèàŽ™Oà Ÿ%Oª\YËû"ý&"lœ¼BIžÒ³Éæñ!È0©nS« c6ì‚@ï ÖЃ3¶Áò™°ö"e~ë#¢ðÓQUÓÇ{þ¶!ò-‡–Ͷ’SHïÑTŽ9¥1œÚJþ~œ"ï—ÈøâãŸCæä–ð3›&,ο‚Û8_|£ú⚫Ⱥg»§÷(¯…„VV½ÎÚZÑÚk #ØNW•t¹ùBŽ“!÷"3²>0pz{â˜)Ž—Q ‡+!b¹î<‡ÈÉÚ óö·Ï!‘.N§¶8²»¼£ÿ›ÏØGy’ðÿ"ÒžLÔŸÔ»ñ÷ÚžŽ²S;>ïi=M_¹ä§¬æ#²²6¦q`ƒ€’¾ÐôÊ^WUÈŽžÉIÖÊCºè\°¤‡†ûX¥ghI”ëÓ.Ã:¶4ˆ“dåÑÇýêš¡Ø÷›³\Ë.¾Ät±SyWókëųûšõîßR_§Þ¶ÆŒÖ|¯&Ø=G{£_‹ÿäÝ}z…L§¨õbšƒùÐ+½ðJQä*£IYúð«ÿÑì\ë鄃!ñ’dñ@?¯°R Q—ãã…²3òµž±šr›þùÞâ_"Ë}y H¥î.—•ÛÜ|YuVp,ôÊ$™ª)ÖD-‚Ëåt_÷/ý5fN©Š¶Ds#|ÔÜäþ Åã Åÿë¼ÌÔÄFÊ‹Rî<9W—¶´²–ë©¿‚Ï!Ê!ª¥õ%°Í÷ê…MŒ¾l¿^ÃÑp¢–F–TãîL&ÀŽ1öRy¡˜Æsk[¾?=Ó×ûŽÈ¤±óõyÈ}Ïa·æôh?™Éãoú›)ËÍž4¨û´í9; ¥K ûëEö#ÞB²ðo¬‰Ë·c€l°?ÌÏÏ&Þ @PHë´Œ¤•Up=ËD&ª°»Oöó’!¼©s[C[¡Áfî6ÃõXqa¶AÓú+ÕDúþøoíX‰Éº±YË ‘’£ÆƒÒrŒm©‚R†=øE‘o“.#Æ6zQ_««Œ‘™€µák×LãØAšÑmÆ€‘:ÑXôÃÓþ×”¶„òì>?LT²k±¹+ÿ²ó ΨZóÄ"ˆGSãJYÇãß½/ J}çýn®ÌݼCuxœÂàwðP€‰Þ3j'2ÁºöÇâ{òu‚ÆÄg°ÕlôŽÄšøé–²¾&×ä¥þ²Š¡/ÿ)É—Úf–Ô.tMp›!Ÿ—ö„”Áâ7Ìz5ÆcQæ¬w„T˧‚îq“¬X¢€¶ò!Κ“ßÍ*:–,l¡´z´d0¢ìo¨ùûåaÐ<%¯ ߟT©d[$­—èÎíÚýðÚVP­ö¿Ÿyƒ¡’uï¸ðYºyÏ@Ä9BÖúÿÈjä_ÍüÒÕ¤ ó–nÿ¿c™NGì¼£‚å9ÄÅ¡T]’±‡>‘}&£—Û›|GÙ+:Ìn¤¬è’(Dþm­î‚°¤3õòêòmËà4 · Ö®Rêík!zºrxv¥>0¤pM¸yÉn×x}åÃrØÐvBG7‰¹>W‘*âñY¼°to~Vqf|¬ ɇž@‘œ~QT~„…ñÇnéåAï§e1i­hVù”ö!*³ëõ¥Éš_øÂ†ã5áÒDú~8Õˆï´Y‚½÷åÉø|í{0} .-ÕJßßÑ90”Ú“)Ä®F&kz."ùïéd,eyJ&ÌÏ,q6Þ|%Å¡NýÅ…ðâ^TvQ¹Ù‰ûr°JÊпÆlêÆüÛF4…:G5ï3]}n¡„”CuÊ[‹R «<±-  ü†Àk\ªëüù p3ñO¢Œ/j¥©¿džÉw£?Ò€ Ñêûö"D0Š¥Øá’Û‰ý±(² XæmÁØ|í ¾úUO^€£g±Í9aÚ¶¢³3ÀSÙêêkcŸô äçÏ¥+Ä—+Rê8¾BÅ9[óñIÕ|B!ØOÿ4æÛ°1qÒwÈCŸÎQ¬OEøpÀ½Ãb}“·šXc@ÖâøÛ´§Û¶ûG…ŸÞ"„oZ–=­h[=P,¿WB€ñ[òN¥ª]3/.‚—ÓÙIÐp á:™ZáèÎ"«V ¹ºBüK.(ôìt’ÛÒ4ý´òËÞŸÓn;¹r·ÃaQ.€ËšâÁf÷ñ!¢8[Þ.+7Ò§zÃDÃ×!9è¡t}W.%è‡) ~‚ð>:|xÁð©ì^†„æhÿ³1]”ÉoâI’Ð"%>]\ vkk§¸*!B –¥ƒ$0¹|Ö¶5Q÷·àØHî}q-KÌÊ+øîLƒ2òn_ú‘f¾5ÿ…FBYŽ>!,SÒcË)€ß!2¾šAíc˜8—?kÀµÙ…p»éüž—'æÞ€®º} ×öW"ÁÇíµ½ïbþT¼„à99\@Öì|@Ý´F†ç%›ûzš……ð C9É–i4ü¹­™`E‰̱‰2‡£v$¾$ƒ"q†"<ÛPê«â"3"3‘.yŒâØ«iâ ¡ÑgþæÞ"õè-­GŒm[‹òXϹ{ÿDisŸÞ¥wÍlWÍ_íI:¾ØLàÄ>Ûri³’Þi‹ò3„fWc8бÖMü/–e/Ê©ZjwiÿÝPR7.ld.TX”!X'±éS8vtô§)âà ×üÐÁGK²‘œ÷à7§¶ÀdCwyFî"eÛæ¶q†ÿ1êsBa8Þá“4°™õêýåø¡fæàÔ¦ŒKR¸ÖÓKž`°ÜYyüeõÉF+ABŸ°äK /ÏéPЋªV&Ïôc_•=lÙè ™2 äjøÝ>M¥Òö΄1v˜ÎžÓãO¬ö“ÿ§SŠŠ??Ÿ¯;›üà3“Šð(ó£ERMXœëO¥ÐÅ ë€Áêú|•Áp—l)²ÌÏá?6ˆÞ³çC•·oñ‚¶drèäT´±Ž¬m¾dãíeèN)R•5¢G‰+ÖnÜ+u¥ëAñlã¡„P0PöâäÏIØWÐÚX=‘f~4Ûh‡œVÑKy¬°(òZJJ§ý*m¬·Yîç 00”¸Öv(Z¯¬!Eù#Žòóݰ‚9Wéä_bŽúïNï×þÇ$ø@iòÔß’öö9C?Jê÷ÊC1¯aŠ®ñ·¡.rã¿$dŽ{Þ·$ûÚÙ€2¤Ñ^j,n=ËÑ)–ÿrÆ•3, DsîÖU„ÿŸÉ©9×ÕaLŸ»ŸŒªòTjÃÓNTí‹ÿmžÿ|w£±Y½ÎØó†/)ª‚s[…àºV¡²¶_`äEd’nY£éîûÁUäÍñœD‘ ‹ |Íf‡ÆŒXÏÒ/=O[-‹íú78Šû;ªâ½ÏÆÃ}Zõðf>¼jq¤hÚIhy$^xC‰…l*ç÷öï úHò›ñˆå_ò)Ÿx ?P¸¯2uñ+Y›–íÕVï Ã&~ù^Þ1?[2„è§]˜šÎQ¦ôPÑÚñ^í2"Sň6gÔivéª?:ŽÖ¥ÉóPí±v<ƒ-¶:ä`q^æ\ÔÆ>þ×ßßÖhÞðE¾hII¦'~¨îÒºM ~¤µ—éÎîóöWÅ8Íp Þ ÎYmzp²…™u3s÷êÍ?éÌQ ph†G '‹ _T9¹ ´äëì–7Q0Qì·¯í¶ÃfÀ6¥&r¥VõŠhxf ’Øò9~]þøLª—Y”fæéüx)'ãl_] "u»\ p™ °„ ò=ë0jˆZ¶GIÅ{^â–ù½Ë°ûýéY¸V®þõ_WɱàÅiBI[ë¿"V¸Ô«sÊNèÛwU›T`Ì¡,XììK„òkwHŸ*ðÝ µ=Ïž³{©ÀL£¶3þ£|z¼ÈcÖŠˆxL½ð¨:ËêK1Aä9ÌÄËÈÂ+ž‰Â\ƒy‹Lë?úE›àYûBµ­9ÉÖ{½Š"íe!Øç}_&>eµGX$ú]jV#uJþ“ÐûWAýPÍévÉ‚âªCí"Çš*oñË (°–Seöì’ÄæŽÿ‡ß°Œ›¦4{5jFHo’¸µÓ™‹úÏD¡,+å g GÐJÔ…vúÕt‘³®ÇËÿA·6õWV/æ*Æþ;…M<ýfË+”ÚR1~—ðçD‹êC½st7‘ô½öÓauDò’?epQ¶lTÎ=ƒÙÉ­âÈ'IºßmÅœ_ïfôtoêv›¨ñZ5¿=,Þ·ßì-/ ÁdBŽwPó·Ì?ŒtJ(¤,‡“ùSÖtý^>2ÜÎ)û¾ôÏrÔ“Nÿ…¾v uWE$ESÙâ#R#ò!£û«µÎSõb|Æ3 ]‰?öäeFˆ¤Rú/¡gÆPåTYÛS“a±é·ã3†Û0T ›Wê>H0(¿÷¾ŒB$ô¶,ÅNjÕ\%¯~6»½_O˜ògÿŸÑïÞ G3(y8юǹñ»¥Ok" ɪ¡;˜¾itsœåc‡wUý»æWó-ï5&eÈsš>[ûp `1LàÏ’+ä>í‘4X3Ú*MÌWÙ Ç‘÷)õÛŽ=eß™ôoüæ¯Æ;Ià²Ð `8'=;¹’,N´y?ߌӌE¥,ž,|B³ÆqX™,µ='J ùRv"éSðО¼ IÙÄé%1à¿_Y¬‰ÛzÍ•ãåÞ¦¯£Vl“k2Nrwò>-ã(³;™)?{£fŸ\¾sìŠcÜ/mR‚­ùk‘ºf‹ØõÈÍNRÞ$YãW‚þ‚ª¿·B×Þ6äè…’JþµqI\¸2D3ý~#äùkE‡ÑÅ"‡g!r2ë';Ù av‡0ye¿èkEu÷já+ÿ}²J>Ê™ÀÔè¬q "³}XÛª~HG¿rkQèÄc?§{X’¡#S[Ñ/<ÙOéýáàÓç‹Ë¡aš­tƒ °úýþŽ:WwÑnU–ûšXT­E ²þ5Ý6|¤ú1!De¦«C”ãtañ¸@Ño@o’·gåªU9ÝÄ#~ ½·¥¨®J߯N+o–äç£ÙÏ»LŸÌ©énV6@7yL ^àQ$YlM1ï£Ñ-‹ÆBnŸ¢ð[DßËÝŽW+o~•]EÛ08#·¶lõg[4Œ¢661áúlÓóïÕe6m<žWw»r q»ç=ׯ¢‚Žyýˆª÷‹.¼¯Io“-ÃeÙ°.'.ÃÅg×jbtwy‚q–‰W¯6Ú” QŠ!¶d!®ó4]Ú©ˆßj…0ò(4]Qo®~¸ÔÌ“gi _¤…åsbzí¢4ĨÉˤø¼¸iüêZ†fù¹pu¶¹0¾4’7Ð~™ŠWét¡7#â€ôÐLçsp¡3£ º]pÔ JlÉ•c~—+köLía$¤³~ñÿÊHÏkób5 'qrmýlˆ£Âûמué¶ŠLsrÓ ÜŠ› “¥‚÷R^F›Žá2|”Õþª‚¯P£[ý®5ÿ{äæÌ*Ï=Ðw>¼½¶„SÿÄqþxxž¯Á·íáô÷jzìxH8Ý·Um.{óÇå›Ób†œ«i¢æa<¹6Îü¯¤2Žv^ªqOG¿õƒSò_îÒ 5%Ë@z½O†‡¤_ÿr|ÅÙ9pËÄv}*|ö¨J­(¯ ½w>©w u{Va’íRHö]ùÊ5§’—·J±7_tå¼Ýi8ç=÷ù9‡a±À&è={},Ç©t-?èÏ¡˜–*Sðrއ¦m%WñqVÖ{Ó+1ëǹF%)ÐjöŠbuàü¡õüŸÅpGd²ß9/’ \õ"{f§Ê¾|0{š³'ö¥øç¬¦™'9’xëj(Ä”‚ÃÞBr²?ŸIˆS5 Q'>Üv/ öw\º·ÞÉù/Ç×öboæÿ™a>íï[N«vãCîYÕUÇ¿­Ä Æz÷Ý7l[•"Éx[(Ä~ÎtDijñ' âö3ôÔ–èèxW\yB§0I)‡êsåÍÁ÷Ò»> ÿœu¿°±Ï×-PêçeÛ.ÓÿŽƒãéí̽ÅvWV¯EôÌívV6c‰˜lýÍsGÞé !ÿYƒ[b_ÓcœYÇ? Ýs˜ÎRO6ÂáÆ±UÙ³m:rÖw§§éõ‡c–©øeP@ÆlÞµÆOVc“ù}ãÒSPÞ{—°7õê7éGAñpýn{R¬ÑEl‡‡¾ÎÏüéðº-ÿUrQŒp+zFŠhò"ß’ŠÐm.7ð›Iã?zçiÅa…"Y¤Œiv8°2QŠP ¢C<¼†¤jŸ¹*;O¬Ì\ÂO]& ø–|®ª7‚.6;L¹jmA nø·`ÿ!a›-\! €<‰í>•‰a²ìÝùÁ šyÏÓqÕ%Þ”-pô³Ô»âÁUlºù>ýÿ6À ½kYL¥|7›™V=°Ù#ýÚùhÛo?¢r&Oyx¤Ûq%wiƒÎ‚%‚ßó¸jÏ™ñÊØÛ¥ÁÊÊ17/¿ñí‹\>Ðvê%XãfÛ’…>Z߇:/sè×JZëâ!Ü:äù-Ÿê\ Š wcü“2çú´*u›Å³3ŠT†ÌêË$á~¼(¬pö¿Çn/ÚÕÊY¦C6%¥jº£öàçµAžAúïj¤­ú×hIUýÆ6C}&•»²Ï}Ì)„>¾Ÿ„¾â TJîoŸöù›ÐVUñ¦0‡oXº+ìqGôù> Dh¢Ý– Ž€À5«T•8×9«êDÿÏ tæoðøEè8@*¢%nÖÐxNgÀÊCÙô#Qj•+ùŸœ>É¥¶›¯•TÆ—î™yQ¹úÅf0'—duôõÛØ¹òù ÖÔZÆIeò; ,êïý(Þ3ÿZMܪs…¸^½˜ËÈ¢ºq€^ÞüoÙoI…ù`~·.õ“:î:Ì7_ç+oG2ËŽý+ Ìðdz׭Xü ³Ñÿiù㨒±¹^<ÚGŠe“¾|¿¶ûæÿ¶¸¢{j˜}È?2qb_O¿ýu÷š–Ež*&÷8 ™ÀÞ5s·ÁKª2í GˆÜÝ_‘&Ø)Éãžw‚ Oôµß9ö ]¢_£âÊ•ÿ8íþcåz(’^¼œ(‘SÖÇl…àè¶[g†Ú‚/âÔþåVIu®>š‚¯VÄŽ,Kæµâbšª¤õšs?xû¦±O}E‡ºLa"_7"Ï‹‹&XgÃl_ûáí4ÒwJPûn8Iä;þ0>ò¢ÖÉ©è1ÈQT <¼dCostKÚa^[gQ–\°³eF{Þ^±¥•OÈÿ÷f=¼#¬¸ü ËÔXÞÏÒXL¡Ï^-yN1Ï¥|(&sÍ,œn’Tؼ–?92ÇÊ|(­ß’"ØÎÖ9=¿Ák\ssâ¦/Ýi€±»¤ø«Ï;ßa ‹Òº)Ù¢òæãØŽ[•Ü[R®=’ïù¬­²ÿª½ìS‚µÎZõ>⸭äb㘯“n ‰{ËT¾÷V#{M~Ÿéäàúª˜!¸Çµ²¾TÄ…rÜæMù/ „G\ÞÔ!Œ˜œÍJå”k,¯ðglÊû? -ÖDx3Íf§o^¶„ˆ9ªåM†̃ö¾õÚ¤þÿTÛe-5b"¤R°1˜†dŽc½‘ÑbhvE¨¬ÉŠˆp·ße ûñ—b‰„:ÿV%ŸS©†Ô§SyüsUÂÉ@Û«¬f̓Ôùƒ uÄdë§Ïõf_œ!œÈR<û›Ž»o¶Ïð é6rêo‘Í*3“sï”,[FÍpr¿íöÇGÚhùåÃÒB Åù5z>ï)ª ÄÒ"ÚÞØA«ìößýÍa݇™ØÏ' µµÁßÒÙ¼‰Æ)}ãLÇ~‡,þ¶J=S /NͪÌ÷£y´$>J[¯RG½¿ÁHöÞPvwïc‹rË‹pA…±Ô8†;Ô‘®âàÒ¿µûnÊ”ùœ~œq±ìy}$I%Öˆ #&4—i”ãwÛ÷Óï„‹¥ÿ"x®6õ¸Xû¢DÑ­Ž°b$¤†¾ÖNñ¿&"ø5ÅØsvJx“ûZ°Ÿ‡á—ÃõZ¢îJh•ª@èáM—¹ži |ž‘ç@J³,›yGݵH˜H^([‹“ë3ú)oMë•lVmÙ2¿Înôšû¶aùÉõ¦·»)ª`Åœè°hæ¿ìB¸LÖmuµÎI×öC ^÷êNµ¥¸?STÒåkÛQµëß#ÒÚ¢Éÿ"cÑhPM²3ŠÇÄe 5楖ñLÀIÊ/È]õ[°w×þºˆ/ ,TPl£ø.xÆü@ŒÁªS“úÛ­îcÖii™[KÖ×}E&·ÅðöÐ<0XK¿I/+SxPÜm’#,ýÖ Q¨6pEP©Ž ‡é°ÆÅ—ÈÉÃÝÐÏFeb£ ÜýœÕözþ‡ u‹³=XT·v%Q_Ð!)ŸñheV9»¡V’†ŠL—¸pÿ^Çpht bð¦=ý‹Å<°±ã®}®wpß„yÛíñ'®âN&'Û®"³„£^RBUk¾ÓüÜâK­P‹9µØølß jXh²¨ý?o>.vWÛF0J‡÷q»ÊÀÄ'è«B¸"¢œ?¸›àÒÌÿ]Ϲ“Ë[Ù}«»Z¸Á}­²I CôR¸6c"6ñT@Ð$Ä>¶úÉÒådš‡ #ÿ ¸L5yÒó¾ôÿ?ìÝí8Î?è}æ(î`ï#ÿó’e5–h3„h]ßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ#šóž8såœãÝâ‚…@Šû™îà]7¹˜$ÛÊ!ï°rNÆÌ¥ }€}·–AÊSè·NUÄ¥}–›N‘ì¶ RU×/ ö ø@EÊTnÁ¥½@l1¦)›QZ*'m@èÖ´4Ë" Õ°ñ÷SÖòÝkÁdNk#ïŽ'€HÓÑÒ€ twÝÞl+won˜x( ¤AQ»ƒ©ÌÊ”P'qoXPFcG§£í|úQRQB¥]À×lL.Ø­Ø:Û)ÓKï½ÎöÒèôžÔ¶·¸`Ѷݚ·=ÏÐ:Љ€ @ÐÑ@8{¾öϳÀ.X®Ö=ŽÃ_w®`4{+ZÐH·|{ÛÞëM·@³Û¨òõK®{·žzvÎ];·¸ÚÛ¸¥'^Û˜Ù½zô»Ýt¾½÷|Ç\çÒ2RZã7IV±Q7<Õ±/-2«mÑ®ª‰Ñ·,ë±èö°ê_n À|(‚¨D@| p P|êtûãäåºj§xªÖ•ztêö=ïum:uld}žx}_Y(zÌ”ûëÚ½·¾@íà °÷{Þt^÷u@h·¹èÕ ½ñóï°@§ß>êß%0CèÐÛ4:®…lû{€œæ {±Ðnî€Óèûƒ|€£@kGÛE9=÷Ü ö$uô}Øôt:(¡Gq€ó»´ôti¢û rynÀøáÞ›}ÕE9õÞ{ç€ûV %“<7Q0v1th$k¹›švÝÀJtÆw:ëI.DŠó§° žw8èk] $çwI#XTiª ¢RˆÓU¼ ð'§©{zT½»0XS×Ú:e„nö½:7ÑGÂ÷×slÏ£@•¤Zµ…ë@SCç›ÑòÀ”­tÔñŠYºozöw©ßyé ¯ZÖ¢«éêÙ”Ù¾°¡ÚÙ‚ûráA¤-Ð’ Ú.Ñ­N 2°ð€ÚP5¡"”«nGX6–ƒŠA•t-ƒA¡¢¾ß«¦šx5¶-@7Ù@W\ÙSfžvêÑ£²¼ûy£$¯¶AIï»ÛÔ‹¾š=°CÖ’ìR…¦±Z}½ž¤mdÓIFãÑW·A ñ¦ÁÊ™è=Κí–ÚÑ¢N:ÎêÊN»«ß5|˜6¬jPhômœÊ_ 3Ðû±ÉÒÍzÔW÷½lj†¯{r«î@|™P2#¼ôùH•$ø÷ÝÀwwž}Ç{³yöPäÀ›½ç `úhÐ ¸9wc»:{}¸Ò…³´XÉ îuæØ`›UÏ €š&šhÓM2&2`ŒLFÀ2d0†LÉ„i¦š`š£Fšh‚dž $ˆ‚&€ž ÄŒŒš4ªlÑOQé¨zžÔjiå4 h2õjÓÉ$BAŠmÑžšO#&&šhz#C#L!¦šƒMО©I$hŠ{A&OÔõOѪ=CAêhF&€z€Ð  Ð$ˆ@Ð#FŒ€ÄÈh™0dÄÑ5?@h2dÚG j§²i´hi§â2£ô?ML ˆ5?@§“L§‚Ÿ¨Ñ¢H@4ÔÁ ›I‚)²j#Ú§á5OÓz‰ú§äÔŸ¨Ú“ÓDõ4=CÊdhi垦†!ê1¤ú  P†€=@ÈNûtŸõÂáÖ°]üœowÑÕÀþº] §ç±¦¾ß}ß7{þÂÃ:Âü¿¿¿¢átskn&I¯èKÖÿÚ0ô%C÷ÀˆY¢BÁ?‹*¨>ÚÕ'ínV¥ªõ劧í„H•EªøÆ´ûD&v8—¦áÃsºìgwNn».‡\îø­jï)'œîtç¡›zîÂsk—+”wËôÿIÿÛÿ;þ?òžHúð?Í_U@š2Ÿ±wŸ'ã qôþoêþŸ` Á™˜­˜ž½Jäî–ü[9 6â·tºaÜKåa6Ðù¹íd¡šÊH’ZÉ ä¶¶@”"3*ÕÀ‘1F‰)"H,™2@‰””˜V0 `³31-Al……H‡þï‹a;¶ˆËH¯äC؈ þL P¶ÿb‘QÒ¸‚ þÊ ôñoÛ?öˆþlÿŽ!â€(|(}T¯œðÇœñòb~TEEÿ>ú“ÿO¶þ­¼™ýOî×ü>ÓÛü/¯ðÁˆ8ˆ &`}R¨30*½ZÝψc]]ª£0ó‘ ᙉÎé"\ÌÀ »M– Æ%E„¤!eTPbu"ܨRÛâ)‘Je’]2¤P»â³‰º¨$LÌQ˜›fquJm‰"j*(U‡KšË¥D…ÔQT*ºË¨ôH½ÄÁNg¹Áù “AªL×)å/rþaôj§ï§Èø&Ç6*´‘>‡üt ›î‚!ÞC¹ÜíwŠ˜“Â×ïÉRÍñµ¯0À¬q+dåu{äëD`í 3†^ž¸ô’<^PlqÓ»ŽÕ…ÖØó™°ØjÛ¼ G¼àáƒ5•¹@é¹N¨LÅŹ!Iä©•*©ªiÝ„áK"T»TnÄš… Ñp•†Rf\CÉQ5*¦îÅI»2Û.l㓎5¿2R!yÒô®¯Û¹'õW‚!ªÿõ3³à±ð±Bÿ.Œp½BŽõ~„ý¬[¬üoÒ(´X Ňô”u<Ãw !üDÊ\y@€ò=ÿA>Ï›vONǹ½ì•!Ï‚H޲q“õ*@ˆ=ýaƒºXÁD#" @d9{Ï‘Q¢X çYÿe C®Võ:elüüóeXˆÓ¯îËúŸAiã‰_Ýÿ'ü7¸2ÿ×ý{Z­U_1Ê‚P2Â/ZâG¥X‚òÌ$Çy#ú|©ÝÙ äbÄd›ƒ»,¦2×s /çx2,qß½Ï$!šu?Ö‘¸è7™Tú¦2§øœ×®€82†.ç`ˆÓª¡Gsš(È–<†SBœÕÝà ?“úÏð2‚Wx諲 ü ªýDó~b± NûuÁú²ªGÜ„p?í{a¡Ùz¾ÿ¶~^ß7…¹ûxFÙþÍbÝ5u3õ|þ×ò³ö}¯é~ûí¬ /åAÊ‚‰xŸ£ãÄßóDH5 xdCn`…O1é×%ù›ç·½þÝv…Ωû à½Ù "‚OŒ¥ƒQG=Ó@Ë9ˆ d ` ’òárTÜœgô«ô¾“Þ°æËu¹³ÕKOÖ­Ë|ï+sÜð5ž‘Iˆ»Iû–mCϪŸeù7ãm1ºÿž2Üp^/í%{.ÛᇤÓÁµû^Êÿ¨§/ááðÆÀÊÝQös@ÎíTyÑut÷ 4±÷ŸE*!"ÿRP“ïºi´HAÚýL¿ÿ?ÓðÐ^1;œç£hû¼è­ûЀ$ƒ,yΘve²9‡Ï¯üÉ„ÝÿŠäÿ—Þ×Þ®wëòv¸ožß#µÿ¶5®FO}ì/&˜UÌþ¤ sìÈ‚ ‘/ï¥Ø•ªú6Ôv¹‰²w;èºö­*~¦!Ý0.†D°‚¤0õT;Žâ:À|Ìó^¯¾û%þNç™ ÿŒ8<KôIˆÿs+OuÇåËÇf¶û…¼èØ–èßÃ÷ad·Èõ|[ g'àã@üp H¨=&¿¾ûh”Mäì—3ƒ¯æ~ÿ¯AÅÈš'¡¨§@*Ûà UTÙ! cP–yfªy7í¬ÇŸÐ§"ƒ!èúµR–ÞÐãl=Øõtz(2:ÚÎטabË^ȹA6%,CŽiêþwþ?Ì¿¾Ç¦"y<¿ï÷¿ú&vO©l÷Ù¹ùãû×ìúعígzcñ›×BÂGÓÒ&Õú7Âè‹õ’ ¢þJÿ=kž î›s`B“Êy½°Ì¬<=œ÷­ò}— äÞÎa¹|àƒ ÜȆU,ÿÓ—ÿ;þÊí(¬_ªg¼û’º}¼˜•E,ºÓ>ï+StþµvgWÜ'µ´W÷í×ówü]vôþí#å)•wïŸ~{÷û¿zÒÖfn‡’Û×úRðúÜŽÃ…~œ” 6Þv ]Ú£¥JÄ5P®ºŸÎM¯<¶š=ˆCw³ç8ú[CÓé!ù^ゆCb©ª”JÞ¾’®S£üàSÁþT«åüÇùÓþÚ÷ƒÌÅK^ù1«ˆG^1ÈúÑ7âµo){­sXŒŒ;ýžŸ†¹cFÿ3±?+×¾áúÖL޲Y0rþŸë2ú`\ý+«Öc)rk!Ę̀Cyñ´Vÿ¾6/}[? ú¹ÕSҶȽ¸×ŽïÈàÚ?NÞ[ƉyîÝhåAºFå¾å°<ÌÞs\©½³Ïí¢Ò?ôJŽFIft8©¼Ã·À(Z/¶C~ã¨þ3žédm6}M}³ÉÈIÆx+¼ÿým®_°=ïý°òõã€òrIqüÿ5UúÌÞöñˆm[õr¢RK÷°)€þd@|­orþ2¿…šêƒý¢@ CñÐE'ʯ ]Ì…®ÝZðo3Q×o£¥×…lqÀŽïìæ3õ¿.øæûLtã³€€Ú‚Ÿm_ßÿÿýÃüH 'Š ŸÑ‚}R%7gFúcö …&dgÝæX KB•/êv¥šw™\‹CtsgÖþ<.XpÀápÒD&àˆJ ¨²æÏ³²„@™"^>jÔTNªÑBõ½¾8 ý–àÐ)g¹$™“ƒ24—øZQ²qÃÁ 1£\›>×£^i®~Œ?Ÿ)ú1ÝZ^šdp’S{{ÅݾÔ à­`„ZâdÀ3gREƒ_Çac_Šïàvzý‡†E!ì“Σ ?š*ly¼ŸÝãïÿZ¶ïò7ù⃇›í·„îrwT jtj??fPò&qáÅXz?Ø÷åÞhòq×ö×¹„yuÒxhÔCða¿£ÑçÏÒ‰DŒ´;òÑùuËþÏîyÚÅ£«[e{=ÉÏijYÑId ¥¹Œívøåº~Ë›·«Ò^5¦dÔ¤~ùú¿«gR ÐÊeEª£!êÎÔRU—Œ7]s]¥hlØÇŽ¿g¶¶ïוMy׫m^¥u Ø >W-v€ë‚Ò †U*OZyÜÙûÿaŒðè 1’&Þ6µ‹sQr°F,nE\шº 6«5Þ5û7ð¾ßü+µÒ?¨ÇÏÇòo¾þç÷jLžs­þZ¼ÈEZñ#Â3t…d8ŽSQ)pòÅÉÊ6^[¬°U»!²Va4IT¡,‡¥‘ðÎêÇ´ºò3‰ÄB£¦zò1«[§^ÿ3 ºê²ÃOK ñ—µ¹¥«\мӯKg¼8‚qÉ$ XH Ân ihc98g¶«•Ç¥gBœ ¥¿Û–³ˆ…E6$ÖZ㊇¾œöQ ±"‹€ƒâwÖ«V½ºï¯6Žc$Æ`e&ë9¥«Ø€ƒ¢€ÄL¸Ž}Ö2Œ@ ½i$nÌ›¸c8áT°²A¥ÔùrÊF´àÂc 8p\…}\˜ Œ€ÛãJýUæ¶ÞÀSTí«e£œ-× ¼K)¬@¢o\ùÛ ˜‹t’ÙX@QÚëkœ!Ù¬´d“)‚l;œx˵QpcžªM( Ï;o¿ÅäÖ¬µW øLþ=­„™îç5öé]^f{a¦{©K-«MYóØ TXD5~²Å¤“ŵ[Vý¦1EITF4X±h6¬h¢¬h­[Û𽿒ü=Ï+¾ËÒõ·œÊiëLjÛ¡²XgFôÈr$=£vFyܵƒª¶ëÕ=4XÓÅ“8ïnCVïkÏļÆáªË*¥–Íf2¾˜¦#¼Eî÷„hFÂ0# “a ŒDQFÜGÝwî#ǵ`Žsˆê# vn#aàGÞÀÄ6/k¼0ð=n”_2v¹CCS9}Ú÷âºÅp磬¹P:áÿ&¾ÊªÙœ˜õÕêÖ…_ó~rg9ži¹ù´óëËGÔqe°Ä&¶Z±e[Řc|ué¹Ë9Ûó®q»~5Ð¥¯E¸œ<`ñs{_)_Çþª•ß+k{ûï&pd$´$´j0ðvu/Ç£9?úuõtΡú_é¿§Ó1·Ùˆ‰Ý™»n$îdFfeÝÞLDFý7z–ö"";ÞÝÝÝÝTn½ìDw·UUB«½ÝÞ÷¼%ùm\;(1C΢ó, NÛÛ¶œ#ȈûðhÍæ“ønî“»»»£wwwwwwwwww{ÄíÚïe·ÜʪªË»»»»»A+·˜ˆ»ª¡UUUH"Hçï„È"dD0`ÞÌàaÊ'¤®èqÌ9½¯WÅîaëç|뚣øvëîò= @è!9g5[WW±;Š‹÷©¬*¶«úø<òæÉ«ÃæmÜ^œ!ìrú0¹§‹/]=(uÃáq8Ò0çù ¶-‹Ã–ÇX<ˆh¼mdSM¦e‡›Ê´«¢X2“tøãPÔvN9¼%'ÕdÚoy˜J@’3³úლ‡ê³¬º½—Y P‰Ÿ=‰ˆ¬ŒœÙèÎ)™§³…Zr[°Äê‰n3ßW'wÔ÷ÜûL-–t®¨Ï.±Ù?…tGfÍ›mE|üýG «ÿMƒý‰ ñŸÕñî~?G¸´·b>™ô÷0u<žGgŠ«‘†:ZW¯Ã‡ûóC™ðx'fD©è®º~!1ôéÌÝêÖî:†ì(Àð•Ïylœ ozo”½¹ËQ: Ú÷0ä¯ZÞßÁÈóNa=O "£õ‰†ÿEúÊ‘*Àb9ô‡ô‚?K‰AÿìQŸÝÐ.ÈÒp¡ô?âcÕ+Hi‚RgYvꮬäÛ 3sþÐO+f~£âNúi²N…DA{J$ΪZ¡R¼ÌXööMÆ—Ïš›EÕ!§¡ÏŽêDV¸¯»ÔÀ/(kÔ×kþ•.øm¶Eä ¤©*¨!%l¯rþª€óöõòa®{êÃËÿ§‹v®Zù<¯ŸßÏ×w[ýî†á‹ýçßÂÉ—§™û=ÿB?{K©õ¤*õ©VZ•aă…߬ªÆÒ*¡eƒƒhE ­°fK†ÝÛZÖ\ç•uNÌrÓÙ€´Y¦bÆ,þi§nЬ[· ¹B¸c»\ÔkµÚ”Éðqa³Ž²×ÿu´¶úözû9sF£ËÂl!Ë×I®HeÑs”–îògšœ‘ã„ÓH   3l7JNø‚ãWh€/Í!¨Oa<Œb•ó*´Ý#l d}ˆráYOhïWF8ÚU­Þ… ø NÝqekÝwÃ>× IËŸ‚ÆÍ›pÀÙåìÄãÇd±!ÅcI¬14îV÷ÈVAú²â:{6lÓÀU °AʯW~k¬ÞAâ5 «hI-k®`ú½XÐßGÿ>·7öm¶F:€´y¡Él‰Û.^3 :¤Š]¼Ã£«ô¸—ÕNGħ>/FƱ+D|¨lh b‚ô›*°UtÕ"b¡ 8“ˆÀaô_…Ì%e5dÔB%ÂФS4htÌR©7íÊíÛ+$n—3pìÒ—J¦ÁÍÈ EÉ‚£^Æ'z}_ ¡w+MѰy=ïî®ÏCöøÛÊå}ö˜|º+œ]”½“ÎʹÝçŸgo’ZÆ5_ž£7+°þ†“ÛèÜf»DË?‡)Å£?Äw­úÚÈjý-†Ï·¨Ü`m\<ÇÃ)f×䥴ÚÓ¿3Ü™l¤†°íw ý³5°;Oϳ4w¬¦Ñ}nKù|Êåêá^bû‰-§¡‡°lÕ[Þ­»ì.‹ñ2³\j6¤Þnqdû>dÍy“ûÅ#ò\.ß/Ø¢­zsNÍ.3åÅÇ7âÀ|?¬Üõïs©³ù~ Ìþ¶ÛFز? ç±fGsmcî×}6]}Zs«¥õ,ŠÒã¨H›”ýö kýßw2Üœq¢§n¿CJ^8»_º:ÝËýù_äÛ׺DÀk|o’òò½ÚÜú¯OÖGŸ·¨î¾ÏGÛú±Ö*¶g~H7Žßv+ºòù}ßÔÈü?r4¸HEyëzÖ¬dѾ>"¼ìl_š3±¿Þ!{/­á__npW6 yù=ÇÖÉ]ÇGïOv¹5sq_ÛÇ1äJö4³Ô[Í_©‚ð~uw‹¸=9? ý2%l+j›GOo©Ñ÷™Y>½×Û²VãײJüè#‘xÏõÍìH^eöñ¡ø6´Ÿ;ôÓæ48l;¥r[.ÛØ¯×¢sìþÜÆ"û¾KÐÇózêù9|ñ]Ö°j£R­EÒ®™Fø?Å’"Óì>{jŽÞJ¼œ“‹×2Ñù+tÝëVì[kÍüí]Êì©ð}ºôæ—Uçn´ÈoÎÕs«órÿC 6WÙ{’%D|Ôe-&êcŸáR{4žž†½½ÈØùþ ™Ýä!ãr9oGÅrÚËëéygù;Tl½– ÆeLÉñ¥°ý‹ž>¢Í5Óûàq:^BÜ­mç™—ûö«ã±¶÷pÜçå}» wÑu71uùòÙvù®}?ËíWê«6û]«Í·ÅǽÉÕ—5Ó€™©}E÷æûü}¿Ã‚åóñO:ß~‹oÆ~þä„o%ér7•é<ý³ÕïŸk?knÇÞðz-Ž‹Ü_r]‹÷­DŒWKÐÀ´¹ZŒ.@E+›­”èß)¼Æý¿ÃÁ¹ŽÈäÝgªo3ü­–Ðü¶?›W3 U·Î;Ô½‡þc«³¿ƒÌ–\û”L6lRxÒ1ò{j§äDÝN7ÊÕk} „mçߺÐUó9ðçy7¿ºËÈäwTÝ˜ÓØP;Vη©®ëkQWÚÛKI5˜ŒIùo“•yE9Õ³€ýå>?‘îú¿+·zïzßbR È=÷¡A^Ðó¾íj(¢ÒßFiÐežõ£†%m«ÖuHYº–›J•äü4w4ØÙ)þ}"ßÍÃßv³¬wUôr³ö]YA¤œšÔ]à4ÀÆcqQZší“oõÊã$*|½l \¤OŸ—Îsº¤êý6¼wNד¯jw¸K}mÕOÍpÑ€D8¹3Ó-ýøíà»øV˜œ²Êu6«+*Ž, _?3¾KØ>kKZÊÆ-‡3ùrï¥ÔÎç:šk_†ìWù¹F³U©·Õ=ëÇ#þ‰i©ÁàÃŒÖÓ…²a#;ÞM±<öþ?s-¾®7ÏFv¨õ¾ý<×½ÊyS:´]¾ï=rŠ‹ô]«ÁÂŽ|_Õé¼÷Ǩccsµï}o9îãW„Íxö L<ó}­n×wŸNгìÿÉ"¿ØÐ&}žÖ2ÕóÒÄ]I}eµ{öàø½ÎWCëØ5zWÛÂÔGØ÷êý·ë½CyþKwêsŸ‹ëû¶:co 5ëÃÔNÀWÊvÖîÓºÿ¨5”Š{jj“!÷}¸Î>mÈs¥PX.""UÌl»|R AZó½=§ Ð彪¾ØšÄX¯~‹Ük?ÇêÑmÿ]c\ Êò„§Å¹¢%Ÿ‰¹÷Au~x¸Yùü¼ý^§ðúêýß@#Ëãúþ5ûœó;¡ø»rF­ÁÞpÅ~ýTê`„$ƒý;d¨ŸOYb9—3Ï{Pׄ%C>\mÇ1µxwp‡k° éÄ%*D)±ê¿[NlAQ­g¥æn±ì½Šú>8¾Q(-:Á¸Q$!˜­…Æ £ëÞ”L=Š´»æÕc'çd÷ÞçÌùÝ^ç^KÊ>Îtt¯ÍÑ A$,Þxwh¨ ÅåXOc¯¶÷ýã"IΪªŸk±Šï­¹²UfI ´µ¸d(ã=Ñ̉ !!æÄê³=mÙ‹çÚÖ#[2þ/½çîpt8ÝQ s]@VÄ›3šÊ©r(B@˜í†©Q¾•#èáà AŠ/NØ:;ñ5þ³n½½“è}gõ,kß( ›Q5læ°8á©a” nÁ­ô-&5 ™ºXȈjîPäq¨ø€þlÀ0ÕSeœ°5;ç&¨´OÄ îXä˜Þ³m±båPø/JX (=(V áL hkýð¹Éú¹ßOQ=DõRZJ}ïB˾2Y,¥X°ûÖ¬†ï¥V9æ=7Ò„þý{ Õý.¿}¯½‡wšUÏ‹‘ªè*ÙÓ<ºôº²çÇ3 .ËùŠF^‘5¨ž6káUÜ‚Ë77ÊYÖYåq!£ʈX*Ô8·Âæñë®s]öä =£Ë‰B$bÀŒ² “JMI¥›M´E ±™I%R›"¶n=GàØ£L³û9nQýa̵Ñk#>Š>H~ãâÿϨ}‰ ¯×#%¾dóèFÇèþ¿ _âê¯]æÀùuÉ>G0.…Кè?¬ç˜\ýÓËÑë‘Úq¾Øì¡ïä»0=¿˜!pƒÎ7­ùLˆl¹e¥\h"ʵ@'vOUª°ùù‰ ÀùÌ}Éô XP"ÝX^½Tì`€ƒ}iBN<Ðé I2—‘ëxê± Zç8ò,P¢U¥:8Q–ÁcJ"Ä‘“6 HGÙÊ~¨ õ9È¡=ÝüxTCŠ B‡U‡b˜aÌ©- N-΃A ¥äÀHíF<& wª°²³ ƒ©’t»‡eæ<Ú;1¿ 5Næ=·<©¬¶°•â=íW÷AUJØ%/G>B`êÎ=È´™DB(ÉÓUW”b†-ó§f‹è;c£/Ç·àCìÏ´L„DB‚G®¢P*ŠÇ¨ã9µko›ŒPÃ7~&–èÏ}4Ómæ8èa§%åkœêÃŒA~¢ô lê©«æèpPÛmÂ{\Ïäâ'{”Ùø¤ãP1@b€üEA@|·—_ÑL•E{~âq§O3F΂‹{úì휘¨@pt¢Çm"-¢"Y´—ñ[ѳ$Ý å¼Ã…+@AUEˆu˜ççÙÝ%;õûxž.ŽœÎfÞw‘B|xüž>Œýïrá„Ù™n9kÔ8ø¹¶a–ž,9£§GvÛI'K™0“fî#»{ÌØQ9Saæm¬;½¯wi«U{9x> É‡£#M¯;ÃÔ¸‹‡6dÕÏáõ1›­ÝíLN|¶À ÞÙªãßÞ˜€>ÄíwôÏRl,{ˆpÝãó…MXX–{†ÓÚUU_]@oláÉÒaž:º0ºxNqëƒ n¶68ð.K‰nF2‡†ú­Po*&ã:½“ÏqÚK©U*šm…ŽÁ@oãÕ¯Vë™6/7Ã9…òôµ}Xdk4äÙÆ ;|ŒŽC«V6™§,ÖzQËættÍ Ó/>¾Z·C`i[ý¿.Æ=–6Ãè¨ Îsl˵»Œ<8ðŒÇ…3„7˜ç¶øå]®,t‡0‡{gOòòkQ•r\ísmÂpÃ2ÒS‘T5Êñ(ªîáÍÆÞß^fîlMùmÃ-˜^æ³MYãÂØs"••¯È<®ž\5ëâ¶•kQÓÅÆI 8»XU‹‡\"€Þµrцxrö«Ê?GÙõiÃVeelk“‘@a¾MçŸÏ§E´¿ “Ñù4…õÙÇmwíîvm«äÚÆè©9=Lë%É/ú}zï¿Áª¯ã2Ûd¥)–ÕlËjªÜ¶Ùm¹m¹0Z%ÆŒÉ*+f[U¹%¶ä¶Ü¶Ûjª¨* cNýù›’äù}½§ ’0Õúÿf“·¥Œ:~nÀÓÁú¤â7&¼M˜éÕ®á9ùøN×ðìãÏØás¹lŨ—ÞØ¢î|l>Šžb€úBŠ£ðEN Ï Õkní[ÊÇ ‚ôgÕ†“ÐŨcÂÇ•GüOoµßèáŸhÇÔmc¬¿dÏœîw“ÒsQÀPFŽà¢ÖªBðÅ’0"á†I€–|ÊPƒÉßÓg3Nn^I8ù9¦Ù• ]@vOÕqú€ª+ß@TSg†=íøn;â§ݳ¯NÃÉ+É*nÎñ;f£n®ÖÏô7÷@ zxukÀ@ðÑæaÉÅÄs›§=kpäÁ.סIð ÐÑ„Qq'sY•¤ñt™õ7ïù£ØN#Ræcï&[ÞÍG¿ÀÐQ&4•P¤…F†0a5ö¿m‡nNyËaúýp~’9]þ‚â¨uTÞ ¡óéIúT}ú6.üøÙÛÑûúßÔ3H@ü‚®ê_ǵݯ}€!ûýIRÇ¿4RWë‡vùp‡£ó<çÐð1íñÇ=@oO°P›ˆƒ¦½.ø" $à<¢Éùúí“3«ÈõîåÔˆŽ9 ~þý§×ˆÚö@Ðyà+è¶ü Ÿ«¿¥×¿g˼÷á¯Mž˜qö˜·îÚm­g ÀoxgXi”ïc&øþüHïñtdskñóôµf–ÿU1cåŒ î•óêªà>óðŶa äñîý>¼Ê•¿A?X¯cXa1ýWÆ`%Îñ#/kõ ¥‰A¾¸¾Øœvn°XÆšôæûñIhk‹/RÔk×ÅÊ}>|~o3Éæ§«Bs"Á89É Dâê†à4)/·¶WŠ}i•eVöÊÔ ŒÜãÑn”i!ùÛÇI» É9@jewÖಎÒ\¡Ã1’ ­"k/*éòï$Ü " ƒâp›&xlÛÂ|íX^†tVy– ›èÕɧkÍÇ.xUÍgØ–çíF¨¬ÃJª¤XKÐá¹O( *« ¯:ª©7!„á‘EÁÚQd ÌD6%Ù†ULŒ¢ÒÑÉÄj «Šûý¾=ÖIË{J…üûkìÇåu!]®l´ê—¿‘†ØóôS†„åKȧm¤g—eù¬Ó…[ ä(ÕëDÊ̸T%ú® —U@iBÎ#`’Wú’±Ïmi¥fO{à¾d¿—ª¯×åìñIáårÊüÕŸ îéšqwf<sì®N¢½3gkZÍ]«:V›M¸÷)¶êññó鉤¼M‘÷ž} ái„Q•Æ[ écgp†Rî<§‰O¯² Hýâcàþ#3>\ÆJ!rFIÍ!LeË+ sð÷í5'8v³½ß´âÃ~#ŠÔk–8cäó»’ëÒ¹‹¡¦”r½%ö[mNå—ΞÃ*vê+M4C&‚àƒ¾ó#QœÎ<†Føa<oß¿k9ð0ņ|Tˆ[uS=B£ tóCq:k\$òÔÞnÆþm;aP®)V„…ά 1@¡8í·>/f­ªvœ„½ë+dkµùú¿J˜&5_xÅ?‡ÞGŸÏãø¿OG·ú zhŒ?£öW¡Xo/m)ÖwaäÏ+Ð¥9µQáðnãÎkËfÞš% Ä[p™ËÈØGFX\å¾µšÍyŸž yO uë7É 7Ýþ¿¼û¤AýâGÜ~Ì›"§òû˜ç¯_‡êüꉄ;õË="ªóUK3WNžFX’Ñῆ’õÃ4áS>];½:œHyõ%s ÙQêâÃIÙ &|¼ðáRoÛ«O‡_fºÙ;C³Ÿ3mX› ½õÅËÝÙF&ÚÛèûÝW/;ri x‡‰ÂRV*5`¡N$¢‚)Ôw { 2&"›È¸b%"F."Í4‘õ£JŽ”R€$•y$òjÇ*på°Æ‡WCTÆUS¶Udto·ï?{Ùm7a„–½úÆ-ÑQQQQE÷»ŽO¡~ŽŸŸäû7UÜv¨Ý>ƒQq÷“ˆÕ†òª‰Q«n݇FÎtÓNå\Õ.³×Ûm—)£¯æøðË«ÉÝZ)<Î ¡}{(/¸9ž^çk]íŽyÚ^º^nö¼ë^šl406›±é0ÔcgçpáÑʹM&x÷oy/Å <˜mâ6d{˜š!äÓžœœœú]º¶D§V=êòöëŸsÐtï< Ñç×S¸Ôoh^¸¥ŒÅö9r¶væîìÀ3Äì[t¯—°“ÆAˆÃnív‰Ü6ëßIJñm&©’T€…£_¬"Þ&E…_À^$'ço'’ýÚ!®Ç—}Þópg6C^ª+9¾QZac”îêﻉ¨áç΀պx‰%IÉEsèra„!Å9%ZÜv¾«ÐØû=ž¶­!]¾3ÆTñuñü3«ªÜFFÌç6¼m9¨åänZNS›–Æ®_0ôƒß¿qŸr\îVîÿN;8ƒQ ÷•Èyó·žîTÔó–ž.'tÈ}»-¸µÚâm†¬9Ë8Ì !5ÚÅý*³#¯‰7ëâäíÍ“_ß„ó98Mžt7nÕ¶÷¾’Qi 'åò‘¾j¶é&tËÍ×ÂqãÔ¼AÙ —ÏÊÏ\ßǾ«³@âʈá6Ũa s+–<]É”æàvµVÜ×_Åçãíáäõ¨ `Ö‘ñFåö×'‘ƒ~§f·ûWW¹CÊœ·<^Ð`ÚUðº-Zºµ¶o)!ºÕ&XÜÜc—V ä‡86 Üúaò.VîòånÀË{¦(¯yJ®¼Ž‹ùPÕž¸ô®kÌ8ìkðe‰³ (䱫Êÿü&]J¥ÀŒ2˜2”f6U¡$M„q`9& ¥­‘%¡E-F¡Ø0…ê­XBý‡FþcÒ—èúó³ºx·jÌ5x8ÊæàÂU2ð@£Ì½„åãìåËKÚµÐծŊ¬èÀÌvõiÍêùM‡=™¶<õa†ƒ“#¯,¦RÅÍÚm™ÆZ÷àçÀQU˜MD+››ÌÕâ íûCãêÂÐ.®+Í[wÛ#w½CAäËK%Á›!Sq^Pà —zÙƒK‚ŸvHó¦’Š¡Ú²Æ<îQíwv<ðuì¾9`ãÛXk¦=­š·kÊÏ]³+ L&o ÷óo€òæeÃy…tqØä(„ØV$µê¤LZ–Z¤ÜùÎÉëßÇ“£ZZÇ?SÅ•x…AÚ]ã¸ÁL(qP›$ÒƒB ‰³^Ä~Rm‚Œ¬¤¬¤ËL¶ ¢9†mAÝ…¦Öi°ŒJÝŽHv’f»-’5‚Aspƒ:Œ9…[%Ó+0£©™jW-ܘ€dpà´é¶4¨0ñ$É) ùd« ‰JÔr­2€aãd¼@6¬0—8†E4ѨaS•95ÔJ •~úÞ¢Ë 9¤x£u XW ƒƒo(… °$¸y§è#ÒÚ23ù.>è£Ñú³ðþã¿ÅçÈäz=/Ǹéºyç äúš‹Z²Ó騼8wºªÛ%:¤9gŸïðóW¤'A #‘ÄÛËõ2ó¹¹€Èèƒ \Åz’œ«nÑEv«Í<žZÅ$Øvwí®ulèÎÆ’l…UV7;üõ†Ã‹ÅžΠ¢„Ôdr`O2±&ÓV{‰ (qLѶ ñ`l„Š„èðj:’Hy;"ØM¨ÃëÖÊ<‰É®k&䃘 ”0±Ì] á>›iV+m0ó6‰¦N†6 µŸƒ\<¦tíYMàÃ^•²Ï©#&æ¢ÎIèBM¥ÃH¦µ´£/™7Íœ¨ozwg¡èpì±^y×_'Çìú¸˜÷¶¢Jµ'³FyPÖs¶!ɪ•Ñ[HRY„ˬ°5á<˜]qLaÂî`Ü% 5ZŒaFEmÔê¦b2<a]ŒŽbŠ+Ñ=zþLÙR\[ÓB\}‡&Ù‰îíÙ}ùÂë¶=;‹Aè-¾Ž—,o¹Å¿®ÝÞs-g/'$8o×|CÓ˜î£HW‘T÷r{9häHâ9­4Ç–ï&¼¯Íéš[Ú“ŠUK¢HQSªrÛ_ŠÍõàX{úËKëLKÞX®ÉÓÞ8hpËV™åàÚ{Y8IŽtÑ´—ÛV÷» äS‘͉G ¨Ôì “·VÆ_¹!ݾêÄó~·}­ZçmÃ>^—‡.M: Ÿ»Q‰fÑÊ!Ãf+ê( 7ra¨·Š¸‡`iá`~º­ê[´ÓÇBfLͯ.w¶ï97,8¡Q*†Þ5Ü <˜œšÌ^›—äÈá:Íj£2½jõ –›èä_ƒ~ïÇúyùè™â²ÙßÀ¯•w_¿ø×«ða(~J½:åOâ5Ò?Öüly{ù~¿ìý¶€ç?Q÷ùAÿDèÝ®Ýä'¦£+©X̲Â$’Èt»/&eQGÜ«l•U^E†ö¬uõu‡'•E§V<›(Ü®8p»«ÍÔæ\£~«ó è$Ì( ³`;w( Ks5"Ü%E@e,(…B¢ah§j›vŠuA³²æÃÊÕ¿V[ñ ]>]Êßá®ÎÞx#®ú·öK–ÉúÂÜX=YêÝ— ,iÜì¶ìë§VGìâÓ³yÜ…C´^U]œš¹8ÊÀ°Vú ³‰Ïá†uÐT+>c*œô{RN)iÜJ”`n´ˆ´‡É¤B†$—KBdB‚¥2b¥fºN|åÀ7G{·ßÃv¼óä·,Ë“a‰¿ øÀ€ë»úÃgëúõ±œ@Ãéú <ÿáÕ‹”åL‰¼Æw#„¼HgVÂò¬iÇE«Î-Zul6¡™ÁãºX<}ìsÄðøqâ˜M¦ª òÐæµ³Ã°5i+œ<<Ón:íæ—“ rÉÑÑ÷4usk³3;ÖÿGˆ|ð{_¦$¶?­S÷ÿ*¬T§Ëph® v—óeÜÇf~´±6éV‚€ì³Ååá$Û2Ľ½Lï‹e8¿ëFLûúC×n• Ï_ÌÝñuÇ´¡‚†ýÉ¡1üÍý–*XI²e%·0ÙŽ%•ÂHàt<p˜j<«ªrg\•7ø?íx…"ßíŽgŸIóár¿ªQ–¼À>ÿ±ý¡v~¥Dw6× T}W¨D™Sª¤X¬»Hb û}gúÇÁ4%~ç¬b%_Ú`³-´'Ž+Ðvñ“õºp#JºÖõB‚´@÷í³‹…–ˆ§ÐÞù?„-Ç$þä}?‘Wöó{TExB$ïoâ¼7ùü>ÌO4w®øŸ!ï"œˆ? 3úâ¿)ø6GRôÇ<þê2JõÎ8¹óÿÓ“5¼úQüœ‡_Óúv³çðüdDü¾ GÏgÑ+Ÿ“¯Âüaÿ[åñÜßíúc ¿pùî>ÞU*­Îuî|3áÐxmìj¿«=eË©!iÅÆë;ZèÃOOS’\ 2æ^ÇhãÝÏ¥nM„×éƒ"Õ­„ðw±¶•ͳÃf;=˜ãXø™ ž>ÆÞî¼xmÛXj¦ÇCØŸóèA¤?–œ¹rÍV-Ô<0¹¾·q=û20êînÔêŒæ={tóèt_o‹7×g>×»›ý¶*vÅâ`}°Rý_UÄxï×ó¾Þxa£GרãËŽq–/Z®…Cß[¤Ð¿×ÖF‹iË{_vJ¸´ÐL´ñí·!Ò[Lµ‡dx¶M'\¨ôëÁîÎm¦NÂ9ã Ž ž=pœW0î8Ç5·ÝøóÇu˜äÌâÏß·•„M»^|Ô:Xw8Ó0Ã’•^×j»\ ×iG‡>ì÷!¤£ Y×,†©Œ´6u×j<0‰ ÊÑa ¤5"»hH²Ê… cuaWæÓçM„ZÄÌ95œˆ¨šþ!c¯ßÒø¬Qíão_Q†F‡~Ôî†îSûÛ`sP59üßUãwšöòØÙßçǧƒª^‹Ù¬ÇõÚŽô-w¯«‹ïœNǹªg–Hy»ó0ìñy»u~Þ~`ÈèþÏʦ¼ÏÝøWìðügùOîêe¹’TXˆ3»«¶UCŠ©>wµäÛ_=N¹[4í¼¹rW.þ-S/i­=Ãä\¦ „ƒ¤˜!1\`ŠŽj‚)ha¢k¶D°z‡d²tMÜøåü£#.N\|ÇôOɤ ãž_£Ÿ²x0,r'ØoŸV€óñêêÑ L2©^Nw4ÞQ„$1(g¼×ï£QÏŸj¹N‚ï7![ÌûÒªV³#óiçXøqëîdxoÉÏ»´î~Þ£!8ÍV÷û;EóÏqÑáÙ_„e`îáÏ:¸¹nÉh©±+ËË—ÎWk_§6FÓÄä ø¶M;¶££~9ñN;œZlÃ'3äÎ_fÃfxû]ÞU:»†­šöóƒ"QÄã‚%⤽•~è0l»° Q£’]V¼iÛBh.k‡½0·{3ˆÛžtÌUý\Æ´5•†cÖwwºýmØßBXåãªí^Þƒë·U*…WÖ¤A/Ý«¡ðþÅÜ}ý$°/¬£ÚCHXǾe‡s„Þ n­KC°ÆìM²žœL_Ä[Ó"Nö®:¯âÃX õ•Ûǧ׽ï\\™¢ï9Þ#\ 8Κ ô‹Å;ËÍ‘¥”4WDªDܺZyë¿I$„{·F†îÚ„ ÂY Lj¬&0bPHG*È ŸŠ”|ÝP“(³<ï>‰59ÓA×ÎW†çB€ÃHvGLë3çÑÕ×~˜ †|ŸÕühGà‚O÷5¬íþÖ;ú½ß[þ¯ÙêÖú~ý…g×Óß}i•îý˜? ‰ ƒÏ•çÎMž·?2t㨵‰øŸÓ0> ÅÁ•…‚~· ÙD¸Tæ=X^¡Kùsà±ÄA­#£?vsAçÇ~GÐ"Ä×D¡ˆþDˆ¿cÉú›Ù¥“ñ¢_?©ø“íýc¹lõ]ÿfŸŸÀü¡ñõüdyì_ãœ÷BþG?Å#¿Š¨˜‘A½~>>Áõï{Ÿ¦=P.½)ätŠXÄqŠò…È¡é*•PkÐD:üýXÏÒîtþf‡¤{àý‘Þo[¬ã]ú=úX“gärŽ ß SŸÄÑú(¿£ÈèòÐû„×®|S¾*½ü‹›¡aßV>+êJ~yç§ ç‰Œøw€ïÑù/Dúú[£ügÜÇ}ü¡ÐО…x$IºµÌ‡“úÌñ|ýưOç•ø~_%Ñ “úÿoåôŠêüAs÷ïÍW+É|aCÑ!ûö§ÑâúĽ8#ô9ôOoæ'Ø‚ú’ð¿Éƒ_z .G·??_¡"ïž~ݦîKëäÙÃWUpšvaçp£)8ùùžp 9lªìµá~ËS°†;-7Û†ÏÏn]÷C|îëÚ[·–€ƒ¯sŒè˳«$2¤áðÏ5‡–á¨JhŸÊ´³èÁú+èü¹_²QþÈü{øÜŸºÑœó×Û+E7íY_o×ù'ó#ŒGöDLÒýV;úãÈWøšd}KúŸ O*Û,uòâxfÎèø§¶§'wvüò ÍYq`ù%aÚ±äľó)%qÍÑ×·£—' u9ØÛ W¨ÞµzFÓͬåŽùûåÀ“@×çßm¼iU–g;•áã‡O>T9ã†a¶Òž¹¼·¯’wc2éœÚòžA^Švy¼ºû$Ùmp¹ÚœKêÒCžQb:yØØ»z©”)$œ|ulbW™ âœ,§auŽ ÆŸ ¹„°ªÐ×e¥,è:'Ï8$Òd‚έtn: †ºÝ-ÀoÏ91Ú[Ç É¤*e~;‡hè@6[,t¢üšLyª¥L׫…¼yj9Í燳NSÁ‡ƒcÏ»«Ï¶ÍÙì­e°ê*÷å4½õqñK^JÕªé¡ÓÓ­@{0ä&¾öLv^±œzn¹Í´ÞLN#“\uët¯>!ó{;$bÁWéwÒóúæ°»f¶—„¨DËõ”P%³v̉+5,ž…Ý$è`­.Û:¬ ÁZBb\äæjû{Í'5øÛÇ-j©ê•‹¢õ¼éì.qåîZŠïïÔb'6x¹z=wë2Õˆi v1×ÜÚmÜo/»†zë.xôؾ¸ïÚVë¡k6 ù-ÂÇ ¯@ל7Ç»ƒØì= 2>ú娵$$íÂHZ85ÈSFÌ Îpœåç ÖHòp—v<¬Ê$w#eŽ‘$ È페Ö0üg$²“›»7‹Ý—„Ùw–Ñì¾o=—·˜fI&wA‰$FdqÆFMÐ Ã‰Š±^7úÁŠÃàÿÕ=|ž?aEÉÅîœvt;{-D`íTíí°×{Š´þ¿ÍD~{Æ¢¤‘íÖRÎTìñ˜¿OŽÌã›NZå3»ûk¬±Øáu¯z "OÊÌÕ¯…€Å#¶ˆ€¤W/!U·[Øé?‰y§ãx¿X-Wyï¾_K=¿®ÄÂÓÖ¸´ ³ðÈ KŠ`DAˆƒÑ‚¥Ê˵в¨÷^·á~ªð·Ù¿h}„Uü`Uö¾À‡ÛL!;Jê'9ˆ@ˆY Œ!‘ D P+,¶Il˘’³àðŸèfÔ|õe5.aHŠ0K·‹zYR'¦3 Á ]£l¸bÞÞxnæË*áú{ñθö(i@p¢¸«âYAðÿ¿¿ÌâìgG{‘.§$0üÚU1î}çÌóG¹ã Ttnû?9@|µóÔÕPšü'ê?x >‘¢È€)&æe1ɯFÑ* °4Æy´zfÕnª¨R)2M: aÄõ}³v „-Bä›Ãh,ê*ó!Ú[:h9UJãµsÌ!—ì4–^fã?ï0û6ÏØŽÅ}½/>Uþ_’ú×åñçOkçïõ̃M¿´þw_oÁ'‡¢4|ĺã<1øípú_ˆ¿Ñù~Ÿkóïèý<6_ ò¿lö(ÅP*ŠùJßhPÞúSôþ/î~‚>ŸÇý[»¼ÌÁ™—ýœV›ÙÙ·+*Ã(Jºì²f„¥Óat">ZР ¤eXM2É•°Øl*.«‰&`ª°q,vV°µ4³ŒÂÈU´ªìK¶t Š†‚Èl¢Õˆ™p uêF|ãê«×¸?Çü9üÁûþñ~Üý¸Âzál™&Ô‰!T š5È A¨ÚІZWy.*¡l9™l˜8&v,J±Ø»iœt¦Qjßø`sœDTHŸ\õ öI RÒ¨Z¢ÉmšVÍKE•HµQEDÒIi$I5–ƨ´ÖÉ$šI6–-mbemŠ+Z,X²V­Y$T*XUBù 魯 žÉäÙÞðp­Úry1³‡'ÎfÎŽf6rlàääÛ~llٱÇ7’¶lÃ+£v›*WB·c›¢¶UnÇ#›º1ÈÝÉ›7iÉ»gF:8FÍ+…›·W Ó££“ƒ’w'GFÑ"uiÈÝÞÊlèèÓM¶uV6spæÙ»v8páà œ•ÍÈÝÍf˜ná»›ši³U†1ÈÓssc“Jpá[+››v1»£G 7pÜ¢cš1ѧ76œÜÚttp˜áɳ›g$äæÃŸX‘<Ò âNçpæ%S«N®…pN;Šä®®ìè w7kZ8i\4ÝÐÙ:7MÍŠ œÛ¹1ÉÑ»‘ÃIÑçÜs€}oc¾g×Ó˜'Õy•ë;{«wwwkw^é;»¹§wwwv÷VîîîÖî½ÝÝÙÝÝÝÝÚª­Öîæwu%ºQ[©-Ýݽ4lÝ\ïùÐ(^Vyçù ¼öŸ 8õ£s¾ÝqÜëoáôL:ñ1w'ß‚’®O¯Þ¾ hùhôdàˆÑ8#‡šG ¬Ö”¡âÍë™=2öGV‡×ð^d±+ƒ‹„H>Ï·™@¢‡ém 'Á¢¿Ó¥ 6‡“çá@>4 ¿þ~mÞõ|ߺ÷öÝŠ¢¨ÔЪ•UR¤!$ÄÍÞ^y«VfÕa/&éa—î5«vËjÆ­«x®•«ªÚdT½}|òÑ“^Ž»²öòí …zrijE(ÚÙ h¢A†P¯¾¤¦IѦ25Z©oЗ?¯ó½ÏÔ÷šÝy~sû®ã›e}hf3?ÎìÉv&WÝoâb;?Çfén@­îè8ÏFÚ­jF”#ˆEŒYEú¯Ñú {ÔüÓQ=Ý ¯ï²V9Ú}CoóWâºc®¸iƒ2³íDþ§ÍÛßTÝ%ÍõLSÃ@5–x¢\ÒJ‹*²³‹ îõ¿†êwǃtíüÖ.cä“G"„øLˆC:uDff©øMXU 8„)Á ûØx~?·¯îî-zßÂr¹C"ö:õýuo—åë5W¯>Žßh‡LZ6±ˆÜ¬KÊSûxE«TeÓMK¯{JÍwá§úñµ¤t5ÜÛ+êΕï¥ÂÐæ¸ýMêå%ÇõinÑ7 V½)nÜ>³&¼mÏK[¬ ö+W ²5@€d,:›bËH¬Òæ3ÚJÍ0Bü„6—ho×ü2Aé8+sÑ ]ártýgª¸üŠ ÍäyH~¯tø_ÛäÌÆsÁ‹ ßg»Ô~í@pU £P”¤QOû}Ÿëÿüóø¾](óuq߼ͪ°ï~e¿Þãy‘ã°¤ÚÆ“ß[³Évàš»úÂtßÃúî,Iø÷Ü&«n›méá‡0Çš®yÇ”…jm!¬¶»ávƒ–VQÔ娸ƒÒ pŸ°Ïg¾|ööë0£Ð'>×àÉ¡æBˆoÕ™ žMÌ ]â:6ú»mެq²w"HÈèëè0rþž'&_ØmŸPìsj39Nly“VÝG£Í¯mùLŽ2І¸¶'U¤hÒ&¸”%Aµ³3}ΣÜ#J…ó;Úh`«#„û}5c²ΊL„ÐËþëñ°2q<—îwüOp;˜Öø¿—-ƒ#ûžE­ òÃŽ˜$]æ³óˆU0ÒW\Í“h:r¢Š¾p¡ôü»ÖÝœ½ íå¨ÝakÕ2^÷S­öòUêñc/öKó0®ß7eœºápˆG^‡gwu²§ÍǤT&¨ãͳv±õÏ%–€LQ¤œ_–ó««hÑ” ]ëY‘˜Œom‡/\¹*ó*9£@~ùu‚”YvΚë›eQ a*¾ŒKQñÀFÁg!>Ú`¹ÑªªlGͺY`$Þ­: lÃé@Ô3ò ¯Y'á°o y•”;~Ô£ÃÚðôe…æ¸g™®úí­2­]”w°¯gÌ7eŸYÛ{˜ß ݧ7¡á=£Òêá»gÙøÃ!Ás9õqjó§«ß<JŒIØh¢¦h݉ÁÝv†i@¬zÀãBµ}|½ l–)Qf®I@Ÿ¦¸f¥Vìªÿ ﵯp,ٳϓ›Ÿ¼±™Ž™éMòÅ }ÕY! %ïõ‹™VEeÓ$pةܗ 0ÍÖ}†ø!†Q'"BC‹™—Œ-•ö¥¦ùÚ_„Ú¢ W¥¾xò6­—æÍÿWÏ’ÿ¨OW ŠM§1"ÈÁ([¹©¬Q …˜SÒ ‰‹¡e™!v’½j¥"u•´h,òvã,K··\~hTAƒ0”¾5 ( Æ Ábdy·›.h¤%€ª«`xDCpý«í*`W ˆX»-¦Â5‰sâ—h¶Fÿ‹À- …Æ6`Gϯsê ÂC +pT Nn÷ÝUUª¾g{¿!.OÐúÍC i$÷O«éøhN$ü]½.ߪåÒfi ˜öVœ­-1ùõ»‰ÆûLl¸Ì¹UŠQóòß?h(Ÿ —êôcèàNaž%Q¦#à!†ô^h02ÍfêI³vpè½?ZmÝuÝÒ¯Y¶õ×]pœ# Û. ±:îm]êõ³nrë·g·6,;"M餖"$Íëbtrì°ìÎŽ[lÕÆ1ÊPn6x#’ño.S³nÙøPà¥Ñy@sP’A$q¡¢2–Ýófµ2æ"ˆ´G1 P̱úÛ –®<î:¶W³.K…ÊÝ/a>  ±à6uÉÛ9IóòËl©>- †S{ÓvQ†òµ„rZ«ÕåÏDœ„éθšrC9¯ròÎ¥Kï™Oàvï Êo6œâR—Ä“#°†®ý™&FðNA‰ÂROvÇ7Ç,:(&-xß½ù_+ÄÎï'6™ló;Ç”¢œCŸ†;íÕ7Õhg>ñÇÀ¸|ø¸¤Òן*ÞY@na-¬é{F{v(VÎ~¿Vú E<t(Ò„<…16~ñ-PÂnÙ´ók X©Ÿ<~lOP¼‹Ó7y¥F¬ :2:$TT#òòROÝH‰V©šEv-!IE%X0£ÆÉaSŠ 3,Ü][°²“®PàS¸qLÊR´ÓhJ)b£äúMeRmܶ7«Ë24îßu)^CªDÊ«©B¨YPÂÊçž8Ê3˜áž2Õtãéèí÷¹¬\è®—œ•ÏÛ«ùÖÓ«Ÿ¡’CJ$ãTžEÈ Êy~.\ŽÙÙËMÄ®K@±ѯKQ ‰æv“J ‘¯bC!Γ º©ÕžS;“ÞSfÖy œ“ýñ¥.¸yø™<þɹ$Âl×øÌ# Iä$ (ÃÅvøÐ• ›½íø¾.¯ËËÙ–ÇdÕ5B¤!®ŠÅ+ Ë0㱑10±‹W»Åz1¼_èKO,kèÄú ›Å2ÈÃ"@Lù+8Ä™BÖ§Í×W‹~ù®ü™ëÛ™¦èêÙ*»S½}Z·b†Re"OÖù>ÖÅp“yÂOÉ|$a™ç ~•öPç÷­Ç$a@úˆQ?J\ìi1wß÷ÿÇBHú𦂠õ–‘`0òüDUýþ€DëæCཀྵ™«ÞæÙÙIõÀØd¡çõ?îûßQð 3gíö¤ÏŒgê|\|‘D.HñûÐ:LôÜ/¤EñpÍ‹a"Uèí\X~ˆ È/0Í-©³ì*è w|OúÙó2„|þðT’È öD"ŒG‡bÍ’R‚(j팯 ØBD´~¢Ui`!U=h81$+ðƒFhfd曓EtZk¬E/^JRÁ½p¢ç¤ðœ›UA$'_À©BÂpÀ6 $°š6äe§/¥^É>€àÞ§m7צ¥7œßg¿ÃOà{¾v·ããKn5pyûxcMD",ƒ$ªy2Õîù>¾ ÛŽÉËÚÓßL —™ñJÓÝÃêzôLÅ¢ Џ«å`æAË`saìÊ pÈDÈ]¨·pß8 Ì?0B!“ÉiHæ´ºÁ!!³‡¨eôI`$±¯!Æ´øŒŸËKÊ>el~×ØÙ«•èÓ 1·YàžOÁ¹Å@á€nq;F‡ÈÁ¼£”ôôâ®%a½ÛŽWŒ‡–®þ7± “Zz¼¸:èô!”áâîïVËm×+©¬p§Ü®é~4cÅ« 0«mq,'Õ0ó³Êèq]Ðê0Ï…cmØÜ†¯%®#+ÄYd¦.”¶1ÕºÕe}Î_™dç]ÜV­ÿÂÍo³~…ó¡Ê¬Ëäà(H ?ÿ?ú_i"÷?™@„Ô !J‚¥EÖÜ–»£õꇼ·kÎËà£7¶NuŸñ3jjÛ•›æ¨+ûÿñ8šSï×ð!êüZO÷£ˆ¡ý5þ58Òé°–D£‚€Ú#.(FÌÒ¾¾·¿°|tŠ—S•"  HŒ‹ "…²JH¬c%•×RÖHýÅ*°T„þþCþ‚b1­hƒså(êýú€ú^§{üÇø—ü·]­Ï_WpîðÚ >ç”Í>©†p‰”?"YµPTVËðøÞà o™H~hŒ‚IDtÛPG7Íl"„p"ˆ¢(Œ‚(Š#[ëm°ŒÊD`Š#`ÐÕú¢6ª#B:Ñ¿G8 &CàÏ4™÷w@ƒœÛœü»a¢{Ûί#VâçwÝ%‰?-ÝèØ±‰‚¡7bÊ4†DЂ@ ÑaOÃäIM¶ÑšËjÖ%olÝgÒK4Nq‰Óáääî<èW‡,ÒÔºhíœÐž9·b$ÑØ ð‚Z{SÈ’IRbŸc±+žÀ Èaœå–KXäéÇ=çW'áK…Ž!ßÐ ³mwK60qßCv‡ZñfW–PÖFoLäÝݜӓ±GVjf"!ëÇ…Í7m–DØ€å„Z ‘„;†èíEP¥—ÃÖÞq„GÂÁ(R—[ )“&[jÍ5}BRD‘W> Jj$I|‡ôaàK‚i§S%È‚o+±h©c<ò‘eˇ+Í7Y]†io˜Ó¢u+Á®6 cT¹³ÕÂM@«ø 9È2XwLIÔ˜È$¤×¹nl&ÎkVtV¼1 iŽÛ]n™«f÷ÉtÒã#ÙÎqîÚ,»Bõ¯-ËW­ç]Y,§žô3M„“!êŤjˆÑOecäˆ2ÂÊ{ŽYŒíÎÄð\Þ¼¾¡¤9Ë-âÝÛJÄÏ' ºÍ¤Óu·ÅІ©J O «¯ÉÛxq(9L·«äÞKÙ¿$ñhnT¬{¶“J¤1ÄHô°™í%U×a›~„ÌòWÕ†D$*t¸‘’̼|E ëºÐǃÈl½\w›`Wcι9µœ5Jd#òB© •†0l&°`†<”5-›ºM*(òˆi±àŽ$ Ðõ[8m#ƒÒÍÚÑ,ºíÏ’Nm"°8Ð"Ò"Í4 Kõ€”`Ÿ¡‘«¥ÎP²ZÊŽo y‹Ñ=³èöÌÉ“ó×ï;§ÔL47šX¹Õ*ž®,·•1¶EZåα8QnK2£Â&D¤Ã£ü©üÀ8âîË™ÖÒ)Q”Oõ‚!ù—Ò2Iš.„íÀüåHTzË{úDÆ7D‚Ã!øQÎÈgV.ðتež'VQäã|n•†zíÞ PWÐìBµ ‚Òà¸!„`…ôØÃv"Ä؂ÒGðc~‚ _éµgäÍÉV‰ |ŽJ”<’¢áDýeçÏ„ÈD®¹I}w©ÍÖñ{»5¡;z½¯VÇ]ÄW5ÂÓú<¸œý½¹ÜùªÓ¬,ÓŒ9ìûϤ' 8ƒé-©â*GËŠ Ì´åÝ(’9ÏÌ€íA™ˆúb‰\”a!eÉ©å}_GÞâõÏ´PÇÛ†%ÔižvŸ(Âȃ,#DAè¹ë‘ò"ó…A4¢ìLAn&;TÒ‰¨, QÛª„—4Bñ /§Z°kPܪ€‡âð5jƒfÃP€¤Få‰|“k Á;8nm•óÈ‘ H¨GŠA‘|†Sçò&• Ë&I§ˆNϹãÙ|ªéÓ•ïîÅ÷<5¬Æq`=¶t„wç“-ù„ß’ø—»Ê¯†UÔ0aÀš–áœ[= ©bÍž‘´¬Éå& aH¡ Z‰#î*þ>‚lHG0*ê„NŸ@Ì& 2–9¢À™~&LÂm´EÄàúЍt_à;P Ê[b-rQPÂ>P‹FÚjÐ&À™åBC:|6ÓN”Ùu†»qsèÉÕøffuW›•Zãu㪶šíiª›€HœòLŸe’d:çNÄvUFÊsm>y2í&å8ë ›¾¸ñHíá ñDNuÀ·7Ì}„‡)bí\–ØT™*jT~ÊA5AæÞ%ø3J@‡äˆ2A "×$!;‡‡ßÈäI8EÆ9.CLL8è5Az(‘Pøùq/–F°¯Ø(“g)¢Vx7!/V“§a,¤ë›IÆe˜ìÆ÷XÛ=1ó½žqë²ÒZZz„úúß…ß× 0ÏÇÔ!Fåž6ƒ (j&oºGuìñ ÕuofÎŽu¼!:”œË¹ly¶é4Òí£¥•€ÇK»H-šóg êç' a8Ùk9ÓÎz¬ªIâVÛA å‚‹ÂÕÌÄ~ /°îY4=õsulVëw©.ófâÝ„°Öq©Á5ǯDQ¿O?)襤¶KB@âí5šUªÔÉ ­ÅšoL¶v0œ@‡V^ºoQšœÝ4¶²ÖáÇÞ'Ç]›É6ΗL"0V‡9º‘4³ŽÝ]îï7›§7bàŒ>Y1æï5ÐXï[`PÖ¤])),væÝ9A0 ¨Svg‘öàÔ±,ˆ©™-úg=üœ8ïl†äSX¹ß9xNJ¡,Õ0Ã)Ž<‰Áy!  r ÎaœÈš¥Öú(ôúÌüžU[AÄ1­CA6ÒI¨gú%ïwŠ“ª¶áyêL[Ét”0'5l½q9ÈÅ  `)Tá• B‘$G0œÊ0¥È,ˆe² ÁŸ­MSråUäYc›e¤ÐÝË»#¬5nÙókq”&¬'e%!‰2æ®­×V=Dy'ß‹Ó7:\»;c&°Ô#XÄ$¶#kqG–ÊŒ÷KÂÇpâ¬N½¶ôt9®ôòpÀ±s›M/'&él3P ÔH ¶€Ä*C‚>ã¨t)³¶»(B+-§Äx瑨=y» c£IXâã.ÚCaMž9«ËvÆUU4J3† ’$UDÌóâÛE&\" (DéÆ$ŽB« ¾–"˜Q]oaÄÝm€â,=¼wâWx?Þ: ¸x óî|ãì½-gjr}d¿…;\®¯;ï:,}§HûÝ+Ëߪ{Ú›}Ôýxm<>b àké ¾‚ŸùzGÄ0êÏq]ÏH :ÉA„€ˆ=®Ýcš}ïÔ,y¯Ì÷sYé>owíNð‡ŽQÇB€Ö*õ™”k=çê±ßÕ žvGA¨óp6¡n/Ãøï³³ç}SHßÙw¼ÓJûŠÜ?`yšOXt¡öÌåŽ&sô_Ï/D>ÔüGDlUÐÀR î ¦Äà$(¤P öþ{kž"‡eRí‰ø°à€Wk_:“ԀΠ֬Xɥܭ³JD#3jI…(—óÈl²2¦Á®…ÚbÀ×™æûyìõäßFR“ñÆl¶S7QŽÌ« ïõoúÙ™R>ð½z¦GÝ[Šù?âDWùŸÔCéãàþòbüþn @.@ˆ–L4”jЍºUiêv…^†Ì¨ñ6Óiôn>€á½Ö9CWÁ¥z8ëŒÞbJž¾£âZ¯ß亀õijµpè·}u]´¤#Ø Å> Þ= …uQáðKˆFN7ÉLrÇ.ÌâÙ§z7•’K—h °Ðr‘0(¨w‘]ðÆúIúq­=Qû¦k AZWÇv¿¹ëª`o³òrÕ–¹ÌËÑ>fôÊ!×]©Qì‡!²~ Ó qÂ{Îî{þVN»)%;pêïñzçá3ÕAßáBD¤ˆ¯ƒÙò€¸¬ ,R„ô(Öù_Iþ¯Ú Åb Að”@>‡»`Ý LÉ#ñ2#°Pï§ÕÃ5ùŸ32×å´«DõåeCQöeG㨠¸ö†ÁXZP¬xM tkÔM¶¹0¬gw ¸E/5ƒ¸9¶ë¸Üo½ZáÉËÀß ×\¶Ÿ¦¶rNIzoÉÓ7ÚÝTkY#0F*ŽEÝ” `toç:Eˆ 2O8ÃD#SÜw¨ì … ÀÕ³-4©$–­7a…ðÆ·aXa²ZPGÁB["¡âSmÒ qsâpj€q.B9F‚…ànv îƒ¸4Ù5fk½æš¦ÛVìi­F…œð¤3Ê·1J€^¨Õ6šç°žÀ»ï˜Ë†~Ùyë–@öy&ùìü¡;Ê'yÝÏ¿9wìî×'±ÝÇeáÇZ ` ÕŽC-FÚ݆¡uËÁܨÃb«R;ŽGnwŸn;øuÈͲDËV:·ˆëÔ‡#þÇNY‡7Þs’ÛKÄ ïxè ³+f[6Œ h­ÑG„ʪQ•w:zê†WD ÃnD& ™°‰ß'ÃùæXüØ 5Äø(êЀs]© ûÚ Qž1}mØÿÏíÆOŸ:ý÷ÔpË×…ÀPQn‚‘b XPŠ( 4(€üóvÎ_'}·ßͱo8þ‚¥ý(þ–ŠåŒÊ¤MÅɧƒCFfàHE ÙæLè&'fðƒSj·¼·/è9À'è®Râ%>[Aòg¼‹$tOŠå â3ˆ.p.1"Åò0O8$g;\ÞnÞ‹/–(g0`wÍÁÄB¹CâeãäÖ3‘È X¾eåÜ€#‘G0W90@±\¹Ú­n...`ÓÍÌÓb¹UU[§7wwy€Œ,r„ $U@±ÍBð‹#„@®’,XÑÇÍ6thàÞnV æo7wwsNï7y¼ÝæØÝ[»»»º#½Ý¢ƒæ 0@ÎPb86$hæógk7wwwwwwwwwwwwy»ÍÝÝæï7wwwwzG66›6c ³Û•ÈäÙÄàÝ s’89B8D‹åƳ2AÁ|Ø­Ñ|› 13Ù¢ŽX¡B…@s‹ˆ!w a`À†„!΢‹ sDƒÀhX½ôC ÐÍ£к  ¶ne˜Üœ' ÙÍÑ“›vÎMÜ›¶:ÌrN]@#@Œ0E0_&¶³s7whnëÝÝÓM4Ðɰâ`Öfi2wŠÊ(Áoìɇ—µ‰è3¹¿Ž6"%’`&pÚ„»“1ºÔ¨Õ ²ì ;ߊ úyüѹñÓ}?¶ùÖ#8þÏóêðùœúèoãŸ>{¡^üûÔø'ª½¨Ÿ™—Åõû}ô}¢¾üõî‡È¯QñëÙüvÏ¿ä”=ž÷vx;ž ;×ÆÕŽØekcàˆ[ |ÏUu%1¼¬°0>!Éš²#/F1·Í«_?Ü`P=¾]Áö¹à ><¤³©;T„h¿&{Qˆe“e-:i\C3§lÂ8ÛŠ37‡c/’‰ ›A&ÊP"†6Þ¼“̧b±Ýñ-ëz™2s¾Ú²„aóoå[Øì¸v6ЇÌoN@ÃÜÏ=EèÆÿ¬éyöoH}6:k«ëUQÙAÍ ›ÓLG#_ÿ~Üúämïÿ½øŸô~OÒ÷|Ÿú¿“ü¿w¨CÔ=o[ת*ªª‰E¬(…Õ=žLc ²Æùeˆ*ó$Š{Ïò¶2¯<öçÜŸB¿.¯7qqÄß• °äGÈ·˜5U.ari@Եĺù¬úÝœ·gØæÃ±Ã¹éj–€A`§‰:kù GŸ Þúe¤-€4¶PÓÞU®BýÊaô+:1íw p‹s*­«Uà ?HTÀ‚ hüï먯”aUe¶Ú´2ÄÄÚX±¬ÐÈÄ!bD‹bDÈ!‹`$@Ñ¢.o/TëyÊCÌ‹d\°ïöÿ?ýùN~_ÀݺK|žBºW\qŒ¡n¡L+CïŒC¦­#ð÷.Û¿}]_¹¼ê½Ý΋«)Ÿ¿iºÖea™6Ÿm»íëÉŸõóCé‘¢,X P9b6’rLaÊ`Jã2ÿ3;¦,²Æ%47Y|w¥~•ùßží^7¾mòW¿›¤E6RÕëK™/““ǰ$…å”ʹÁ‘„*X,!<žå±0ƒÑZiž–uXíÖÌLr¦Q•5„ŸP 6ȇÍ2ªP5¦¥Ãºw{ÅrwòïÌ®dàÂæ%„ ý€Šä¡Á{̹ÅUYÈwÊBÁ HX‘Ë ñ‡@Ù…l*0&†‰77¸x‚k""†VÅ4°Å72yj&Qpn6™´4B7n8¢4å…#l·a5ƒW"àBo!DnA`§‘•oM‡œ[Mªš• ºy qºX&˜ÌLÕ€‘«ØÌ.vðD×jî]Š‚fºÙš&NÆ Æ­ 6îΘf"2¯jˆd2‰Tð!¬ Í¿èþ÷ê@D?ÙËQg§Ñ±²Úö䃀!ò©Üu­_àõý_Í,iD¦ÌnêêÜP˜HN‚UßÞºÿÖð¬ïÿk"yÉËmnrQ%qK6´ ¨lp}T%0@pý¬cà¼<¡ÿ[úGƒÃi‘o°/¼£E %Ë ysF¼`Ȩpd¼–O,ŠÀ‘s‚ãûçÿQÿÔ½gîs€uzÒÀ€ØnÚ ݦD¹¥íE¥q !jµí*ä¶Ì×¶§€Þ¶9À1 D"ec Tr¦ ˆžDÃ׋kIàÍã)œðÒ”’ë™Ã3Há3!|ëI !i<Ì4!g$Ð4ÉyÍ«YyÛ3pæÙv³ÖÌܦ9ë¦N´s†ekärmÔqêBP Ä!DQJG"ÕZ‚êtœ Pµ°89ɺ@>j ›Ø‰Yp Á@GAiÎkRž?äÈÉCˆ€aÜWW4ô€‹#±ÊH¹DÎáN  eù¼*Y¹ÎL ÜëG«Úª —ïäþûÿOÖõ[ÔæÑôɦ„hFÁsLÊ.@°6Q? -yxÞ5žö¾W™âÝä“ ˜t¸ïêŠ2ëúVbO=í?¹9úr+f4Svì]l »ÊYɈ7 S††±wPžä‰Î"¨™µpÒ+DEäÂÓPw̘Ypé ‚2–'bf\ \»¸ØÎF°Ü¬Œ˜É²´©‹¨£™7{ÔÝR„ê¯`,›’²^ã¥.–‰Mâ«Ê¥p¨¨‘õb¹ä±J&&ÅÙ+nfíÞ#†°6î¤Ái’j¬ñ]\DÁ•W.â^j+,› Àˤ%ÛýobosTN*POEœœÄn*ò#à:$BÀGX™‹ÌÄà¬PwÊÅ*俉œuÊÝÇ Žš'o8‡D*ÍzdN¨;¹BàT»‹Ë"æT¥Ðcy8¢R€ÊV4 e`²æÂU]uÙ UvP†¤µ7ól¬¥o³æ9¢Óó)&[‹e¼ï?6³1:¼N®ÿ¡ YùËZ䣹R¾ÌÔÉÈ’‰A!$K¥´É¡EJÈQp²-ww9ìÝ~çŸ÷éb%é6”AKª„iEÕWsà Ì“W²[àTÕä.8·Æ}ecsà88ލŒ$" 1çØm5Ãeuê{ñއ±XÞ¯þ]qm5ÊÝRgºô-K¡íêÇ#­1‘? ßüì¯?^s ïb¤/û7\t êbª O¶áƒsåƒÖs”°—ó0þ.=  0<¥Ë¶8õêÈÀ†¿6׿~g07ê¬üþíµ÷«§Un‡ÒšKWÆÂ®JéCõŸÜÖ/äþÒjyCåž·•SZäÇ>×.<¼¥ŒLË1ÐF(0Â41C˜$@ ¬«ËÕñ±|3¬­™”h…²-£¥ŽÑø|E»äûz=Çß$þ’ccHqGœÔ™Y R…¨D Ú¡1…1† ZÇlɶ_J¾Wnp*ÌBиju;e0€ÂJ;¾iV‡€þfÕû8í6”œÕktÊL /D1úEÊ~Ž¡òœ^~õeç=TÆO£ó~r}Í3ßâ>ƒ4ÐØªÅ@pœ–G“w‹ð“e—Óžú÷¼ Ì{Gü£&ÅÃzͬ»?qùÛz=N¯Fçznîì×ý‡oø¶åñÞÃì8Üvqs†Èñ÷ÅЊO= ª“½›XP7ùž^~]¬y—¸Yð8 01|Â9Fn$3.Ömñ0r¬qqÈ30 ØÊ” `$T@Uœ8¯öhóæ^®æyçåHúÏtF×ú©¢abs 0‡feêYàn&rqowÁB÷4y 3mw|2kŠ»3åAòÄÌT¼2 Es6|~Z&;}jzv'óV™K_U¯”¶–ÕxjH°s¶†Zpàð]O5^8,ÁjÓñ/ ŽA"ˆJÙÏ®Ùϯ>ÚçïïšÛÕhp-ë;²÷Õ¾¼sœÞﮨÜÞµ[ é« 4ÎZaWµìè‚ë Apy·œõCÑŠÒG˜g¯ÁâHÁeVMž8­œÄ“Š$”"‰% à ç95:Z r£zÏ Dš½€¶p(›]W|ŒàlùÄ¯ÎØ^3«ªíiñwª³¨©:à ŽøtO`—æªðAo¥çŽ£¾K±^ 1ÎÂdjBø“ÙŠÐà±V$äæø7,@¸Ý=ç@åMæs2(ÑÞö¸mœ®µvκÎÙÉÍ™Û`Ž‚("ˆ¢(Š!(޽zôçsž»Uß¶g,ë·n79dY§ªÕ;ÞåŠèAw"Èð¹ 8…=ËÂVïnrè‚ûتÅä °éÒŸ… Š‘Ùƒ×b U ˜ „PŠ"„owëÓ}úcÓgß×oA?—îÿ™ä%Áç ~üâä49N2ûó-¶òßhlî0êMúß['•HÅWÚY¤ÁL0$HÎIóíà$1üÎîåºõÜË÷ž\Ÿ°Ýzîº?/åëš·—P`(J@&¤=ñ:ž·Ñ¶«¼D™D_Föó³Ö密û»Û¶ú{{Ë%‘˜È™P™W¢õ¼m¶ö»z(`"”=wH“é»èëÇwo^öýÛZø÷½Ì#I$~òœ÷qm«éïzõÀ$ÄWÓuÓNíÂ÷ñ]ï¶å^êýOo„! Êb`o‰Ü¦ï·›§ºNíñkîµõm¯f®Z½_×ÄDƒ_n½ªÓÉòv»®K»7†åâßÍ]½LF)5É£ €ÊIã„MëòFÖú5Ì!€r×(¢XèÛÉÑ«‹0­S|ÊÅò˜Ìq”T™C2ª+ LÆ©‚G´´s{HFžßonU9úÇ\Áïü¹ýiËŽ®cÙˇ¹§);øV´ì8„ýÙ‘Ï7¢J©Q¢QLiª€¤`+€¸$U1ÃH‘îîë¦lQ¡4™Ë€.um÷C&=CÂŒ¦ÿ£cgÒMÜKV[j£F Bøºœú‹§Ëkõ›ô¶´ú}þ»ìÀ! ó ì×í¬ºC 0qŇ{|¾^Ú¸W–ööH˜fHi!$´JùmäóµçÊh×+#eî¨9¸r-KjÛÒ±`ù„ØÝ¶VB‘:É8dü73{èÀ$’FIŒI¥Œbo–QDïÑHÞZ& ÔÎ*[ãb`Ú@ȈŒ“ãwFvë¼¼Þ^Sí«š½ËÓ2È50¯l²qr]qzï“yï÷m_VÞšø½¼bi,JŒßm]¹¯—]Üï/[Ïm·â¯“jûû^ß,’I ḑÇ>K¾=n^Bnàø¯†Öö!×ï½Ü:µŽ×¹mMIªª2B„ fú¶ìáyîfÍ#>n^¶r @Â<̤3¾4&tç{ãšOƒ#åˆBB(}©@é‚üÈ¡‡  kžâåŽþ°oò,/Ñ®°Ù°¹¥w=èC=Ç™šç=®KP¼î¹Ó.ì^}ïÔûz½½á&&A*HÕÈË^Š:pªåžü©¼Ï¢.;õúõrw[Çåø{{ý¯¦¾ŒˆA¤cH’" ö;£7¥óØ­}÷ªíRkg'|}=Û\Ûè‹jö‘· ×6qUmªï¬•j¹Ãišµ©Z’U‚æH÷uѳZÍ7škž-|íãW³šß]æðŒ²$7ÌÄà N§v‰"dX“×3v1ŒXwʯKW¦µê®õ˜Á&’v]C@ƒs©~Ye7cÂ6/ÇÄÏ&dòN_zøÌ1躉˱;5ë[E_;ÏmÁÅÆŒA¹õI“$٤ч^Æa\ʼð11‰ "HÈHÌ‹¥kÏ_ þæç‡¹‘¡óFÈJ¸cÔúÞ½|_kâ³³³©¿ZÌËn\eÃ1^X²¶ËÉÑͬóžè‘ÌI9ãÔÐŽïC›NÁ¦”–A,#Ó—Š„ ü·"´©AUE–,ÊÓ:¾ ”¹ØáÌ<„G¥Çƒ©Ü·ÃZ×µÊ!<5éW“›SÒóéW3-gb®Õ®u»wuZ;®Q®wg]Ýw8®FæaBýmåÏ"ÈAHêù%݆¶Œ:ŠÈÈáá}÷áflìP:Ê„*IÜê|þ6r‡ ðÚ=V€àà/†»)Ÿ¼ñò9 û„‚À,Œ0|–Ï2y&æÁ1 Â{sÁ ÀÎäñãÁ“'„d“@ÆFËÉy—oOÕ™+5Ç}™»~Y\k›clxÄ“Tm’®ø@KIòœ2HKÏOßÏ, ÀH#¥"¸zuwÞl—˜÷qÙ! ÒF2? ª¾|wpž3’„í²Õ`Ã#„'~Ï~î|“ê“5ûÿ§²ýwÍÂýUÔÄz;±®püû‘$OÔüüòÉö>ÝáKÚs×˼dÓ‚ÍòåÁ€ùǧ'=m”ÏfØ:ÔÕv:‘ž³Úûñƒ×ÎîÙï8øü8ê³Á\çÓ¿6 8ÈÂ#êýR|³™n}~†Ä£/×–=Ù,æ“}Hg\œð’¾G A¤©ÄD2øÂø…¯TòôwÏË‚D§ºûݽý{?Kݾ[®‹¥5Kå°Òlßw,ñϯù#¡!J•9ÀJ­ÛˆjËô³5I–i²Jfƪ‹Z}€" ØAvoÇóŸ•QÆrH ô„W.Š$L„Q{Ü¢ëªÅ‰+Àл:¸¸E6ø1ÊãlP3úGlýÎѰèÇ1´ Çä€rKŒ¦ó6]8ü[ð{']ÂF!¢¤7UI kp·ðûNLf[)Û8ç+ÃÊŽîíaó^ö|¤0„§ê/†p‘“–FGäàž¤) “®7¿•}ÀCõ€?%ϵװ34á;nïç'f±W‹NgQÊÝ7Κ©* œÜÜá:íÍ'*]Å˹Üâ Lïã–h`HLúy<|ˆõŸiÔßž–DˆuÕ2ïÓ¸Iö™RIŸó©ÉÈgQæÒ¦V3H†@9/ÙÜÒN9±zÈuOyœœÞc猲Ñ;q– À›lŒ^[vY+7&uõ¤É’³®u–öOG ¼€8ÓÍ$ïÚw©!£3¿/Ý7§µë{oÍì—ÓQ1ð²…–Ü[i‡r|g·|óå‰'r!Ï a¯<»œ½€¦'(s;{8œ%åN{k›-PŠÉݶ8Íëh†aW>Q„jíHy1ↈìÖË3Y0É™ì e 4ì9sPÔÈÓlú>cŠ«#p„0ŒŠE„_¢{¾Ÿ«ë³˜d,î|½îs_yž6±’he3ã/¥Ó881-ž &{o.W#¿^³MFÚ®j¢<špÙÓ¯^œ (Ý5FÒqÉžVn„•èÂò¼Á™ÌÎ/›iœ¡dÐlà”TËÄ2ÙǦ)MÂùºð¾Z¸ð8¦­¹‚<«£Ñ‚9ú¼ëá×…­/,dë)®w+vCÙyµ¡ƒ¤Š¶.þ"f€±¹Îq}§Ð_U¹žž,œ:MiÃ.,MæVå5ñµ$’HUJj©ÀÀ‚E=ÍËDÀ‹‚ã„„°q‹¸*±'Ëñëëu>¬“Ϻt3–6Ë›@züHü{àÚt1°‘õ¡™?0Wœc)„}HO±ùHO’'Ñ e?—×r[ÊÀi 9±qp 컊¹U¯³uܳœGB‰Ó»œâÆ‘÷±3ç{Ô=^ÏqÕùn|çÄЄŸ!ŽwÓ”;gš2vOh@‡^¶ç¡‡ƒCäÄÃY|}ûþ#ðç`}ÇA‡‹óû^ÿ}ß•úy„æn€É®wqˆÁ$ˆïâ!óè¿S ÿ:\œ!gu7±·N8à¼i7ÞÚÔ6§"»9Møšå"NtŒè¡A‰Bî†Ð±Ë ‘deXeXàãrÅõÐ’%2’Ó 9ÄN`9ûéBú¯n©D$>ª®Ó½ #‘$4B" ¬¥£¸©ZÅkP€å ‚«\--T“U’¶øyCvG!µÕmœÆN¢ç/Ãô{O¼»:buÔè‡7;»™wX1PXŠÁa/úûrGÜpb1'à“ŒÓ>gÙ®ë9‰!K¹Ôε‰%5†9qá†9FÄ rð˜[n­7nË”Då⸉YgÈã Ÿ(äOLžIÝnú-¬œÖNÙ‹Ñ:ÜaÓåǸ øS3Ç`Lf‘°HBT¼4Ë µã}ÄéÜzú·g®m×Àu;DNªŠ€¤„N°°P ÀS¡N×+Á²Ï[Ö«k/Jº€å½Q=®ÏàÙäwñ? îÿÅ»·Êyƒ<¹|Qxa×kMQ­½—²ß¾PZiE·µZ÷‚8df`[$´~Wä“Y…†$1–ápR7ü‚,æ‚sî—]IšLÚÍ’…(™|Êè¥JîFÕœ[†ëPQ0¨©›Y§Aʼ³f¢Ü•¦¯FS;Ü ×6£UTäEE±c!Ó.¬Ìi‘t¤¸ºvµØÍ uØ‘bôd –KJ˜ÚÜÎi1‹ÕW–UšÚÝ ½‡¶vã4IÉb#œÉ§¤àÛ'c¬keÄ›5(Ý”^(¤ñi€ìѧLU ¡y/vŲ£$NÂn[1\XI²" íaש9EÀ¸¤.aÌæMÖ£O6`وܼÙ׬FÞ34.°Ù0N*Öð…T mÎa¦²6˜Å'PÝ*x¥aRÍ4‰¨gUd«‰#‰‰·Š”à³¶ÞbbŒšÊaEVš ¢=¥S—;”­ žkƒ´C;¤/jxðEF ¨º6[.AÅ1”""ì+­Ëw.´ä:ƒB4 eA;²–Ô©™8aÕÎ]NdÄ$ñbW $² X™µŠ')È«¨)0§C‹³Zöª²Ä¤#1Û4Êp5L3l%•‚ T®çéÔÒm­³»sSvJO,¶àÖ‡·•¹yg66ç`¶¨ph¸‡¦Š†ÜUº+v%Éo!Ü*ÜáÜ.£„l¬ØTT ¹Æ ¹Ò)sY‹q\V2DŠŠ„ݲ€ª‹¥`³&«¡$Ÿo«ïø¿_ãÓqÌ”Ì[7}¼§f G -”3œ¥úªEÄ ×\(ªÊ`£†þ^U) ޝ‹@!c­R€—ÛîIöÚ46Œ I­Í†‘ßîÖ7é|Šc7JÝ0ôú0}^V¾¤¨sBXØeRB£[Û¯ZÿÅÃ3ïÚù‡Ìèã'»ÐëPç!ÁW{ÁøQîuXJ”ÄpËóÚ5³«Þøÿcƒ¥ŸEWOr¶k©0šxª£{˜’Û˨¯×W«ZÖ™ûï/ˆ¢ –¼þ7ïø×÷îGE0(BD(1‚E hÁ(`1»*5˜œK‚Žš¼þ?³ÿ;çõÁíÂsû¨®jKùxÓd;Ðåò½ÊÇ“/•báÚ‚]0ÙZˆ¿Aá7`\L,XÝ· x¿Q!#ª1ñjȶ#Ü6£Ð‡ Ñ[ ¾ÇnïÿÒŸ(Šª"Ñ„[ª×U¯‹Ïì ìÜÝ7HG!Øîç;»«—qÌ1±£§L\¸$¢JFEI€b¤H12ó»ÎÝx¸.^/+ºè‘s”FÜÜÑ$»»+Ï-ĉ$˜ŠÌJ&c1¢Y"¤$ VKZ©!2¤¤Šá ÈBIÎüç;êbdÚÈ"6ÙX8Ã$î)šã™²­Ê¶NYœÿXG¸Fâ?XEÓI2L™Ÿ(|ÀÉè‘j¢Á!\d0Ý’ÊÔÖc¤XÛ“)”Ø5vI“ÔÙíœÎ¥ "ˆ±½w xç‹’7;r¸ó¸½êÑVÙÌó½o7rÜ ,DÁp-· @!VQ† È’( ñ"Êã4™H#À§/:6î›·.ë¶).eXr ݲÃf(®5ÆÄȇ$Ê›¹B"H-¹jçs’!…Œn{yãÃQí;ήÌÉwp£{7 šðwnu¥ÙIäbL‘D "Uk0Ë?SœáßÛ¯Q#¨„hLŒ’düïcǸó­1‘Œúï7—–É\Imø»øQ¶ršXÒå¯;uüÏb޳LP·Všœ4mM¼Ò1ÊpʶBñíB¯6qÛÜqǵÂî©‹Í…¡1$‰¥e‰„´À¢Ý†§¯‹_NÍeô},ùOO ÔHpü ;×ú-ûÄx %ôè„ÀŠ#;hF„QD`M.Ù™rsK—&¬ÀŽc¬²V™))$!Ylï.ºÜNNµ•µäK96Ͳã+TßX¶l"`g"„ÂŒÞ2“\`¯žuäÈ•×;º“wpM’îæ.3œît•åU¥âyïy½šðd·8›$XÒ#¶XQÈÂ0†6Ë\ˆ6ÎkºÜîæîé¾µiؼX¢BAB F’Sd!ÉÂ+‘€J=Ȥ¬MP®$£T)2ÔH¤L‹Fa„ÏeÞs×]!äëÆ.e7ª´éL•ëw ºt(‰åÞx»‰²Ë˜-Ë™–Êévá¹Pmtç‹!kÖLÀJ¶z³Ï*JBüïhòøç›NX™†í—Õ³Ì1rô}®®êÛ•z'árwz<øôÛ™W3 Œb²* UJ¢¤)©RªjtOË2Ë-¼GÈÔñö«d©ÓOY\Žœ1œÛí·mðß{*O4‰,Ž)ùz`@¾TÆ å ‚#SFÇ-{*²0SY™I3*HÀ(—ßÃ]ÛÍqÆ-µZÎðj’Z†ðÚL Å±ŒŒ53X¬ûB&Fà=y l~§˜V­„±¶[vvÂA¹W?H§õÉ€Œ—ã[_zÿ ™Jü|ñˆdrò6Q4~}vG•Mpáøõê¡ËŸíŒÌC3VÊéÌG.h\Øde»8sQEF1 PpqÅqG# ‘À1`¦bE\?fúÓsM²GƇ¿s„Èù}°%ɸÃcӕ̆UœÒH††QÄ[aÏ…/Ô¸>âL$Kà–Ãï }UðbÁ!·ÆG(%›4˜£Çˆ9¶å6âËf¬U¾ni­Ã µÑ³ 0½Í·À¶mUÍírtˆ”n†ýrÒÂÀø‘ îõq¿Lú¼òf“ܹГÀ™è%<±”ϤðvNt¦I¤O§%²Æ@Èö¯W¡ÕyÊbUqdäatåqØü»>„pT‹`˜,q\`›*žy— é•Lr̽®BW5ZÐÂ+.ÞZ†I.í²¹1›“ls˜cÎýwÈwÎçe¨0àŽ?/ `_Ø #.yêEi† ¡•iE`e(¼fs™âÜŽ$Ù ÖßyRò´©¾ç9©5Œ*ÃÓˆ‘5`ÛC+eÔâçw=:V×®Ñ×Êxó{Ü;ŠìéwÏ9ôOlù§‰íãã9ñ C梢0„r"B*Œ `G Er(0Â$I Tçs—ÝêëN£E`óàp¬ðyXÑ~‹–YËÃ8i,C3]¬€UÈz÷¯]ð2jȦG--gž*±ñ†g‡’; $Mzûð aÚßPôg©ú°Ÿ¥*Î)Êö°,Ä" 2&f¤×:ElÍì’xÐϰûv~ÂÃéHŽ~WÛóüñ  ‹&ž÷]ñø|ß—\!Ë¿‹èžC‹çflù¨MpŠÊôp¬—d$;U_nÁAü-mGÚ<¯s3gÝ>ÛéDBXVŸ‡/®is©Ò0òå$żû·>bB‡GÀßpýÈ´~¾>œ$“ÃH±„bB16ý¦ÐצÙC«]ï²°Û†‘ç¥ÄRF!üžvþ(µ—…÷‡Ð‘–¨#îFöf¼êà¸ã‹Ž8Úì za´¬óàmÎCDÜi7Ö1Ý¥M–ÎÁ”dMr±{#H°|ôݧñvú~b§91‚“½Ý° Ýd©m–¤Ð„l#Q"Ò-Cò>ØÂ¸çÏòþ^»æyˆ¤J#ÌF‰‚>ÐŽñ"ˆÓìˆÁF¡'ÌMÈšB(‚0#í#mšâ`ÄhFÁ„hFèJ$˜#˜Œ;ØFÂ(Ž&„}sL¡#B:4#q"ˆê"‰&„}LëÕŸŽB6n#QGSDïÐGQFâ;„`ŠÈGîÂ;`‹ÏhBQFàFÂ6àEÜF„hFÂ(GàÎH'ã*A?y|>@Qõ»‡Ým^OGáa*! !$‚HÈ0b¢6&P”X0±±E&’Š&E±"±d1cB`ÐDFd@’F60X”~û®±GwQ‹wu! ;µÑ‘”° ;º0ÔTF¤”’ë®íÌpŒDÆ‚¨ˆ©* âªÂ „R #Ž,„bB0p8DB`˜±‹ q‚À‘R1‹ õ¾‰ø½ÙÅ#qº;qÝ;™uÓvì®4F!TPEÇQ@ŒH©!ŠHá‚âbÂ0P`ý‹lwí~Áâó£¢?UÆw?oÖülü7×Êù/“ ˜ &Îî–a0ņQˆÜ·s¢Ì Ì£3]×Q‘)BÅ0&`Ñ në»»‹·A×qË»°cÝÑÛ˜Nºäëº2ˆ,E`®"ȱ˜Æ7ºès·uÆåÜî:å3’ "Œgµò‡®iùErÄg".q¡ÊuÙdj.îHκŠâcuؘ\ç73ºärÜçLÎ]+»¬dîîî3c:UÝÎäs‚!Üî’¹r4åw º]ݤ ;º!Œ9Ä ’À”»±Nì.w]±sQuÜî‚™&Šwn&:íÑIsrÅ]Ýnh-ÄîÝ'BºhÑQ#CºåÎKœšéÌ̧wQºp´›šã9;µÝÜ//<‰Ít™®¸*1°bB0bE" ¸‚ 0@0 ¢„„‹b .#")Œ¥%Èd\‹‚.n“»u×]në—(éë¡$3œ»Îrà›»·H.cŒ’wq»ºîqÌ1ÄÉHÀ!i-ÅH‘ ÊQ&XPe)EH@À£RRÂ4¶¤1…* - Á­S- e€©"²µ¥0–’²ÐX8JEm¤%´©c()’Ç)Dµ––ÛmÅ)hC%c€-­ƒV Q¥m”¶XÄž¿ŒÞZ}¶OÅ}>äé9þwÓïôûý~Çñ‡ÝU?Æà—2†Lß̈]ŸËkO$ñ_ŒÌxcb3<šÀªîR¢<×c|ñR|~cíÝT8 öˆÅØèEÌ3QØz;Y0™B:cpÔÚwÙWD΢r¤” ™~-μܒ¨?<%ôÖOWœÊ8¤u§ã×Ù}ó½^(Ï‘>^ȯ)6}k«¸q†CÚìÍZžï§ÍÛC¸¶k*ÚÔ«õÑÚÕ¾ê$I©.çÄsÉ¿U[‘Q··Þãü½ÏíBžä’"¬ô×¾÷ݾ² ïß–üW\ŽsœªÏ w»=ò†V—Ñ¢cÏ÷±ðG8]ù㦓åO{ØB;3> ‘W1u¼p§Ì ,LåXx_Œ`hò²dÀ&î€=‘ÀÉõÝ>x½M<ð‚ùWf'(‚MåÅùš;K W¬·^;*À>f­7@pÚì9³ß§ã¿™mðÏÙ„Ðçö–¢-¿?~ñU2€ˆI ˆÒbRL‘’X‘˜’~n¾^}gáç{^É¿/ÃÛãÏ^Äc¢Hƒ!†¥ˆ%”ïoÏÕêbfb’ˆ˜&I˜‘’iDd&Fh~>ÿÏ»êþ·Ü¿AvŸ—vﮕéºÓܾóœé$E‚Ú”HÊd„´d‚ ––FO ¸îæàÂx^xF,+„IF‰CK"F2@²”0’DÌ2_ ¯/{ÛÖô¨Ålj5¢*D1D’‚B`¡ H°Ð dBl€†™ ó;§ÌÅ¢bñxIºï?å_ÏÁÿÝ Éåð8´Úö“‚¤Ì”AJÍ€f@3,BVRaEˆ5\#ê·£ ù³·»êìyV zÏœd}Õ§ê҆ё$$7OPž¤9 ´)¨œ®ê» …½¸BWLæÁ™lØ>"\À  3Ù¿ß»8Žß§²'N¢ÀBcIh³‚÷{¸¬0¹b_¹õE†'O±í^XíÕ{ü¼EóÁCØ€Åb …†"Œ ž U¢oyZULd,šUÌ?Yî)Ó çEU8¡ôÆ=«#XN+ªÎ%B§9ñÕöL:öŒq+Ń®†ŸËý/EOÚ|ûìùü·üüýaªf`Fit°ÂdJSÁbÊP™b…q̰!1&A¶ËK„2±"ªA \-– ŒÈ# ¨â¼òé2;¹ÍÊw\óÊðg=üñx .] éÁ‚*BÍm%Ý››6”ËP€c‰8V_Î3i« À”¥„ !-R@˜B~³$ɯrL‚È „N-c‹Œ ±Tˆ®H˜,²ŠHF4Œ‘"¥$d0)€-X‰‰$ `5Ar8±0’´”2¬ Et¬[32Õ´ýž»Å›Õ½ƒôv™å_F‹ò"åò;æÈâ:j2 * Tól\¾¬1çµÏ‹GYiÛ+’öߣӫæòWÄã8øÍ9@KQ±F¨Ž™w™“%Yfd¹‹p„'-° ”C#,„ñ¹çxuÏ;Esƒ)»»$,)IHå"+ Hª¤ ÅT‹•’’JAb‘„X…PSq @Œ˜ØjêW, I2u$És„ÑbqbÇU­3WÛbÛbË®_¿ä$ŸdG1x'gŒ¶\…Ii‰„DÀ VËêÕ]$Q†¬ˆ‘qa.îçfs¨s¼twW «!ˆˆà²+„IÁ`§nb£W.îwp›‹Ï<òWd©2b@ˆ·ú“†dÙðŸo? ‚IènßÓúiÀ€A«Iš#cF^udµ­Uúiâ·›æg›+ÎÀ¿/:ø8˜™bVX¡üœ"`±¢ñæäÞ]Ì¢Vˆ å® ‘|€3Œ]`@¾om™Ö²ž<¹5;ýwJ.ò«.ŠåÃýû°=¸ªòµÎ¦ñ‹œ£“š •uEÇ‹¬w¾yS&L„¶|°Ž‰QhÂÛYåÃo@ )9ÜìùÞÏN…Ø’õÌe?‰AòaN‘”Ã/.ªvväçVvÞ(BQ¤àÑY1U0v4Dö:g¹Ø 9ι@øWH‰C­Ev{]T¬ÅÄBBO‘sÉíÄIS7ŒYšS¿cѤ+=‘vmÑ͵äy>;J¼QØ’’Ф0B± 0j¢„‹ÏÄ\layä@®ÜE¨„*¦|Š’:y&²Žì‹èªÕ…ÜË!¢y]¨‰îQƒ·Qš+·—+Rӡ̇“q¡Ñj> ‚Ä®õ̱Xc¨ÍH+ÈBŒ`ì^ÌÄ$Š´’Ý—ºž¨Ž­Îš”+§“1ܼ¼9Ü×½U&V¹#M{" ¥Þï“„Œ5ØÓMº^RZç¦ëiáq/ȯ.p. .LjkÿKä~ÏàÓn˜ýO›>&«!¾nâ’Hšž"÷¨N-¹çY`kŽ×Ë={V 5{Å‘1pÇùU ˜)í³ k¾Ýu| ˆ[ ¾”À¶Lfûž$Ú>ƒW>„CIòã«›}z™î!ž3 gû±g%ù³Ö5Ù®²6bb@Á¹·qÆ1 “4Ƙ  ©/4&úʳÛÌzúçPËa³V|¸›k¸ÓnfŸ~ÄqŸ.Q(lÌ£ÃÉóâ„ÄßÄúæ$4#k7jL«9†Í§–œÉ†¬ìs œÆø¸Gtw^‹G9´ˆâC}PqJˆÔ/- á ”H?U×äs¤2eþð‘cÎI×q¸„XñòB1Œ„c BB““íNóÀ±–r”]õYÀ¸GŸXä []0>>ú r]åÛ6åÛn1Æ­¼qáé„VêO_ €çÞ ç‚øŸ‘^ç=~ˆDY™8‹M¸ [D"ãƒWp}ù÷­£ßcÐÀ„ Áöü¿ 1$™!3E÷Õù׿ò NÄ ð‚bÓÌM?v,gÒ†ô™ÐžÍqÀ/â~Ü^òG"!kÛ…î`êäA.&ðËŒÂr¾z𠎨Q5j}£êšÅÚ‰è0¼(}R¡èµÞÓDÎ ÁÝŒ8Î]f%ò,¼Ü+s²1’@À žâ=IÉ=‰Ù×9~fo|,§ÄI)‡õGN‹Áôp!ß ÐŽQÞŠŽIâ*IçaDŸ^Á^¾º—>Ä/}])¡±†ÏrZ—*)˜ˆ~ÍýG×wXZu³†iÑ£»•eYaÙá•Æ&-h$ŸŸÏíê÷ïÃíÞgçÚ×ÉlÙ³^Ybåª(‚í0 /×j\ëT¾%`˜s¾Ÿ#B âùžì{èh‹¹Á¹±ŒŸ¯M»4â q6DÛ¦2àp†Èã ùjÒû¶ÕíZFBP×…º¹ÓuË…=ÏÃßÛé>‡À x(óð}ﯩ½½þwâ #||åñùÝüÓÞ…V³~EˆÂ^¨ ©Ãf;mÉžduЬ¹èø|’Ä;QÇÌB<¡B=ܰ%Ò¢?\òd.Å.p*<“•x{öTc½Žž|xö®àMå3«—_.ÝõB9=A ∑»Œq@ƒHààÇÒöù:³>>™—l†k½­¡f-Ú "O mtˆZ!÷ïÏ}ô?ŸÃž~·¿èüÿ’$1„ØŒ’@$ý¼Ñð'mлåyóͺªæ_®OΣº‚G¯©Bf~#Á…>TúåJb…S¹å ; 2–/0%·µ¥¥­ºú¸ÐN6ü(7NPp€ðóžž3Æi.-“›"<1 <›ëæ‘È›£œË*×Ï*¼VXóiÇhÛîéˆÒ—é]„¦ú_/øW¿ÇžÍíOˆÖ#Œs @C@`<¹D" câ׆òÁ἟´ðzÞ!`H~swWÀ7Íúð„Ñ/mÂI£õm¯Ncâ!ù’˜îL˜ñMxjÖ:ˆXÂÖµq\m³~Î"ÈÂI $ B \S ma×}yñaމ{šÌ)„0ÁXèlC¶(1 ‚&bb>‰óåoÁvt“žÊnTž"±úù=áŒûp·°L£Û>מ“05 <’ ¡)|êyõ<aeÙJÉ5šPŽ^Iø¥ Œ  æÎ‡Hná.ÞÌA€ʘCX0µü2°õ¾³ì@(Íü߬¯ï¨ 7þÏE }#¼†ãtJWŸw-†¢¥ØB! ,#l"åIi?¹þ§îÄ~R¬ƒœ§ãý„éèxˆîEL“ð–›~òý‰1 F3Bƒ&DŒ””Qôî‹“wni,L²$™"ˆ’*îîF¹]Nî]ÜNÈEb€ÀqÁŠDƒtWW'73ºœî\'N»¢éaŒAU`‘‚bâ1LP$’‘)è??†&D‡jüþ†ÉßáüY/øŠ']u½>}²{| $Xà‹拌×:gM×iv»®îN\îÙÕÑ:qЮä:.¡×DÄT@P*°Sç~¼xõ=íüÚ{ÏsÃ!˜ÃÞ%$E`ÁÀÀ*EF21B,îdè\.+–ä1Å$I‚AV!+5jŒ’$ @±‰" @\H$bB)b+€ŠÆd`¸„$P‰É-ŠÈŒâ+œ…(Žî]yç ñI"@AKm²µ!k•Â6V.Yeq¥db¶Z*VØJBDZAcm”Uƒc`V€ÕŒ­F8带6ÒQ%l¡-e#e‚W.(QH$H\ *F…*™H)+mÊÙ6 +ÀOo¾7ãíöŸ?ä¸ûÿH,Gá¹ö?‡ÇáøÌÕŸ¥D[ŒÁé)7GŒR”fâ+ù̺9àÎÖ…w»@"sͬ-J’\}) §&¸fbï1Ÿ% !ö¤MÌvT‹ˆŸ`­ö"R›éÃFðY!ÎD¡/‹,âÄ´DÕEŒv)wyÙHëŠÇe*¯¯4æ~ZwÎl[ˆ´ráv¦uhòÚ!F!èÙ#·—Vøº|:á²|ÎÏGz²0Lå<Ÿ+9ò1lvªjt10²ŸÈuâÞR¸¾Ô *WIëAêÁ[8¶§dRA©8{®EÊ\¶ñAº>;á µ3Ô¥;9WZªúhÄg´ï«pìÖÝm§¨a·Õ¤%ˆÉX:+R´™B”|úûüB’‘ƒ$Tß–šjÙc\Û¾¦ü³¼ÃL1ÀÀÌ*9Y¿2}﫾KìÝ—ˆÄ 4 eT^\ás÷æÅW ¹ÅcClEú‹±ŠÆóJÉY3ÈrÑÄvb&êœC^e97BuÅ/c€œÒ .ê# °@òI\àWkw2ÀÏâäùßU¦¦¡*‰€å»ñã~I—²at?T##4-Ko;¦zíjÏ[1ÏM5kÄÿÇoލ¤‰"FI06&ýÔ‰‹$ÃF€IY"Ci$ü~ŸW¿~üõòÔüKP2žJˆ=ìÕüòóºeÃ×A?æ°»ƒÔz™}AD=pðHáÃ$È2IHÉ ™(D… LiÛãÛß»à‡ë¸G’W¹ˆÓõèI™ÏZèP<$åD1¢LˆJŒJM$h"ƒ’¶nh®j²z©Í¨™¸]ðß.+-Eú`u¸­þCèÕVB‡ƒ@@B-e³ÿ%"¥¶ZP«ñüŸÕÕ߇ÕÖjæY¼i¦ôj ²Ð0F`̈ >±*áË„­ŠÖ¸ÍйûOµþö¾Ç^œzñ‡Ï sFW/°åͪ *DùyBEOÒøš)ƒhâ>ÖÆö\\ø½ü—×\£†íKÓµ”ÌÏ¿‡¾®äÆ[+šËÅ31lÙ»Ó÷NF6srrcœ]:6X‘Æ2åÎ(ÈÁÎ9µ6Øæy_êƒü?Ïù‘ÆÍÛ(ª£«à{Þ.­‹´/Í9ý[^&¡‰õÔ>üÔ½›Ý»ë±7¿¿i?Pù”GëþÜÌU½ææåçNÑ˹w£ŠC F²Ó)h .„£+BòÍÊ &Ô´Y’L‚k6H\0"RØdB,H&qL\µ–HÚÈŠER­Â_Ÿn“jPÀ#l²–ÆF¥¶Æ®’düÖçGË=Ϻ}^·7ÉÖü1(Lc†ÿ+}vý2PMÀ$€+žùl*­kJËY\e„„+ dF1ÄgÁ¤+$3aI,ŠÊc\U*‚D–Å,øW©&Mæ¤ ’i DKë\º$ KL3E\@¥ª8@ˆ‰%1•H×%¤ü¼“%aL è„$H9Ü,®ÔmË­iiÅd²½n6OÀZ{ñ˜fYMT$qöx<~äy><ä¦2ŒTÊÅÜÛ±€\åòx¤@ž]vŪ®D‹ Ÿ®ÅŠ­B¸99âå¬O9¯²ä‘½›J«¯÷ŒEÒ²ÞîFå\FC4Î •ûòük®6;ݽɲ;aO{ÝÚ~ ï›Û]OƼêçÔxéß/.{Ô[è±ç›:t²¶áiª½:cÇbU`!•¨9ˆ)X'jªÓ d=½¯ ¹¨­8ï\EckªÔ¹=2h¤ \ö ¹u Ÿs·H]Áðº‰ê26à[¬¹U+zD÷u^÷½›¸¥äwÎÛ+ì<W888ȨV³q}F›4-lMdiÇeí­ØFvB¡$L!À>ïÚNNü/¯Òÿ.ɾ=í†y×Ñ µ}-‡ ‡ÇÇ`Ø2~•̾räA¸@ò8Ãã ±qü…>¹pÅß ø"…|åy¼ÙÜÁ?‚@ ú‡>PI}nÉh¶ïh|¼óLÀ¹VøÈïª|dd…DgU¯-.ÌÝŸƒÏO¿x O·Ûñ¯µôü)& EŒMIõ[C7T¾$mzÙÉMŒ>ÙÛw<*M y-k[LSÁOz·räâó;Þ<÷ߦ5MÏ»FÓÈr&ÆÓ^_æ˜ØÉÂsWÚ—O«B׎Ϣ0òi#ÓÀHƒÁp­!Ðx.n$Y¨QGH°@®ñ3Í#¿ødÕ¯†ËÍsi¿"Úë¸ï I!:d´Þº±b¯žæc v ]O"MýÈÂlÀ?3õï9‹üR'¢}ÇÛ§Û ÆŒÉx¯~|ˆæ ùòÄ¿·Ï¾´xHGàÉ2„š3üÅÅÔÊYr³Ç äδk-EÌZ¾í/mawbm’1„‘„$PÁ ‚Bç|~ëã×ÃãyЈrÂÞyŒçŽ/Ý¿pFþ<¼òèästý¼õ‘+P ˆBïƒêÆ›]ÅXñdc¡‹”½ˆìÁèÄ­ze¶i[ÛÁÕ8¦1Û¸]ò¤¡ÀÍž8mW•ñ\Âgƒ)vW÷_ö¿]µÐÜikZÆfÚiÞ‡ pâ„d‘„$$}–Ø@}|"GÞ&ˆ€6GØG<‰¤CÔ}ér¨9,"Àö¹ Ú¿Ãó$•"DñÝ\‘+‘ê¨3ïã¹èå†pü à#àz¾¡`øq|«ê¯Hi"NõsHPZ„˜<@ÏTž©;K—+©Y¨•QR¼ñ ß/ϰPAEo¨ ú#¾‡È“ $ðH<$#×´BˆÁôú è®s×A™œ®ªß“·žœùNg7‰鎜j¸Îšw“nǃØ`}J#œ€>e¼ê@™]½Säú#Ê·–ì1áÒ óZæž`"q "Ê]#ChÀÜ«Ù\Ò$Ñ]Á¢ÕtýHð@$Cl7gLíºº<;ãÁj­«-µl³ÅÈÓKÆ{¦±ÂÁVª4&õw ”mÀË«0\]S<Ã{zßpyÈäì×㡳dÁ«7IUŸ.¡g*ãÔÑ—32ÂùO¨¥V…TÄ}?Hv³d–‚CëöP=ó€‘éøÄƒçÏÀù<“õ`i&¦Ñ¿?Ñ|JÇÓ¾øª† 礣ê=!QÉêöøÃßÌÓ)HG«ŸBæ‚7’ÃÞè_ƒælp‚ Â'S›ž¶*˜àû}4<"Ï „€TØ&gÀ”žaã»rvHv¼ÝÙ¤Íðå3'‚DtØÃ‡úo½ŠÉQÔyÞuß< W ûçÁÀ €N涤¥ÏŒ‡$ç2ÏsæzŽH!±Ú&ÔÂä}ó‘2ˆð‘ͪ¡äðQõaÒ»hx(ðª#¿˜øǾÈcƒ‚¾¸;.öc7#žÌJƒp¸‰ëdd×bO](fJ*~ÇÒÿÉà–)du;íñzß}Wê®JM2ŒR$’kGÇÔH˜Óá- cÏ1>s@†Rcè®\4JAúµýAϨ2~#œGÙá<$yÚ¤È熥ÓD†ZjÓ#íÃÏBˆyÈ8Gh$ žDBAH>iÁ œpÓfΩ RUµ3(¬¤ÉN Õ%jð./©Ò…Ëþ3ÙïžÞz!É9¥r¥;ý¯ ’¢½è˜H °Än#KV§ºOÇ’Ÿwô­ügÕz3þÖ;ÄzU‚6O³šRpû"5ÆŸ1ö„h×.iŽb(ŽB*ˆÖ]ñ$Éý—Öù¿ÏÈ EqÄ„\H@€.1„HÆ)Uˆ°Œ7GHvî¸ë‹¥Î¹Ü@„ (¸Š ˆ$äïèùó«Ý~“7yé„ô<>¿!îíîPKXÂÛDKÀ­`µ–Ó±‹lV2•+%­•¥Âã*²ƒ ËV±XТ²*­¶R„²Û+‰€¬ *«råÄÊ€Ê`‘H ’(.í|ùëÏ^æ³{i)¼ÒPyt"3é˜vT]Žö‘··8‚‰uS˜GP{ ;;h^ÔTеbºï$×v†Ü¡±—‡º–á©V z(gLαx³w¡¨«2„ÊÚS—;Øîw&iõï_ôÄ^Í÷|¯#$Whiìwn0<Àjž½ˆo¤Üµ³ G•¶­¸1Gréæ]ʃ*g+Ì6€½Ôbw‚,ÏoMd±«¹ÛíÚ‰á·" (CQÚZúêRžƒ#ƒ°Íß<ó½ìÃâò"«_b»±sΑYÙ333š…ÚšÑ:»Ú‹DˆÂh’-)`À©tj£4EeÑ{u-Nx„Jœ7qHþÆ7мõ'žleyÊ ïc!×F}}¦Ì„—Ma¹¢[Ù8nÐÌ™¯ê|üI<<L‰–˜RôìÌL’)‰$x ýCï<WÇžÍzøžÄGŸÈ³žWDyë¸î|Œ¿IL¥¾ÁÐÍQU§±AæÉeeÃDـ٥\øÝ=Êzž¢m>J¸­¶´ŸSEò#ã@8hDAP€´½Ë—çíUÌ&8ÅÙãù˜y$ËætX=0Y†p¨x?ûV¾P¯$²|™vBU{®HEp¨+H^"Ñ>Àzäs¸“dI&O õÖ×|üÌÄ/šà09ÎpËü ý ­ áSüf¦ ùœœ8pÙÉ[¸Vî\Ü&ئΎF’0ŒÞÞLËŠÆVé¡wAÖý¿ô¿˜àóYUG¡ÅBp#EýóyqH0#HD‡Ÿ‘îÉ&OÄÏnÿaø‹fë–’Ý#.m²¥®Œ3ªœÎ¤’d2ÂQœ@…ët„ÛUV±j‹-¯V‡5,B@K‘M„÷Ðaf‰_—XÚãÁù´n×¼ß[©ÂC Y½R°"å>Ù¶TÍ]–\d´I2YÑÃHBÕEA¨á ÌKØÏoFÅ‘(¥F U9*I*ª»s§¶N¼zð¦Ý¼Œ€¦ÇhŹE‰<á¾ bB³ ¸BÅ\;ºÝrÅ‚aĉFŠ­[¸ö9—± Dßê*rw2!ÒµdJ!jË ¶kôôdiÖfæ ):1¨ÖxuŒåJ¢oÉŒ36Ï‹Îó-AîÄD¼ˆïbޝ#Àløo6M…aÐfTôttÁß: ¡¯®ÎÛËÀ€Á³~\vn|ñ@ꛪ?£ÀÍzò·(vÀx EAGm¸Û~zéÓ~›ÖôîÛ¶[,øàïbv¤’~wNEw0; ÀGW‡“k tUïr:‰’Íp¬D±O(¾™/gÏ:_{&sÃo\ôyådø_RÜŸ ÕÜø…*}ÏúâA;:šç¬ç×Z黫ô¼-–­ª²­ªAqÁäüL‰3ð3ê®*©ß¡ýà MpŸåÇúé1àóËïâÃñ'ø=Õ Þó};ôùúAúKçÇÑ{”8ˆ’OÊVÖ¾>dcâäWÚxï>ly\¡=P^€I$’ID³JCó¼ïO§ÇÅí1SÙ'ËÎ0‰§ÆC9Á#Ø8,sbÀbØ à ašø7qñõ!ÌGѤA$Cø›‘gÖ,%©jÏ9Z™“t€Ñ OéÀ‚-¥Êã½³sÁÝà[*ªÛe¶ß¹Õ­¦€cÀ;«ÜŸ"s0®]pUzËS‡¨Å|Â~o·`’:3Ð+CǪùw@žO¾>)â#3c<”NBB¾`-ޝN 2xQɺø0yG‡Üön É¥³cRPíõ}²E)¤”BÞeí­È®.íF´îtλÆwºduÞãy+~ý4 ¹¤r,BõŸU%.YõuÀœBh Aßì(ú_¿>x<>JÃè‰"æ:[õàó5ÈåMjzBcå ƒ€@‚Uè ˜ÎÚÏAØ',P©¸_m—Åì|Rµî¹~¨úö9À*…úñgè}.±ç¥{\¡ÀñüšC#Ã^CI&jƒæÔ×× yFXô}sÙ$ILM2KÏzõ=»Íå÷øízÚ¸,á&6ò>ƒ†ý.‰°ù¤t]ŽÑ+Áäž Ï óDãã.—äÓÎP@P# rókçä2#Ú§…‰4CsÙZ™ ‰#áô€Ê@,ëéà¸@™!<88H`ç¬;¶b_f©220Œ¬–´ªš† ®}©€ø$<œCàø>’=±Œ%ßµ|Ó],ÈÂÚöc°7ÖÂöêÚð hm¿  }¯•G‡JX‡Ó~žÈÀLØ"È¢:rk°.uÔ#—^M“'NS«}5ŽóºÛV•m•oáð°‚2æW¯¯ÔHÉÃ[ó¹•gÄÛãêL$…|êçrnÐd0±¸3ñT'ä3dt<øHyó­OÀ*¡gU8Hý;O™Øß'žR@#Æ,›ð0îÚÿ[׫wURÙ¦¹WNÿ VËjËVð’á‘iÔÕ_¥œ+É€ªczH®è&Å=À«‚!ƒÁá&ÒùàKà²×dsESÑÐÀ`|3Wrõ(ô¹&Ï„ÂP|ö¹…!R«E„€Ç0TÈ›Û{=ïo/>–·—Ûìa $c 0‘Cçuï篋ÏtËßßãÈÂn!2g]·6áuËfî]:6œóÉ­/RD…ÙåßP…W¥ßwŒˆ„ él|>BÏm†õi@‚$A“Áˆ $òÈ€–Ä&H<”aºì†ïQC‘¶wH#h*&-ÆyO©%f¤xYƒòõäÕ«fõ¡ÜFi"ëú7ç’‡h6ü]§Vxç x`[Wwˆ ÿzÄ9é]åá7+ þ? $¿Ùzþ¢ßOkɆìzª’¯]a3Qp¸³iËŽ9ȾÅЧ2Y‰½¦•”n5¢ë!R±S$ñqæâT¬\*íÔ<ɪÅ{²gNFs²¦’Aµo²©Õ¼ºµ{sµ—ªkµ+z(íb7Ñ©ä²o?‚1öj4ÉðxªÒ¢ukBJ¯<—sZexÎĪܡh–;wTìµ)« ÷­bt ¼wunªv «È0F—ý/6pνóTÔ´)qÈ5w~-š£~RéìùJûâÆ|í™…[‡-¹©>y™›Š»©{©dkIë­_ÏücÕJüãÃ>»ëפk9ÑRj}÷(žÈºœÖa*©ÀƒŒ(³vVÖöfžÅ·!@Ε‘+µ° DP˜[7c[+¦.e¾dÙˆ‹¸»MëþLVkÏ‚/Ñtü¹Ûä_˜t9ýB\‘R)s”ªªŠÞEÀ‘\‘ÂñR /FQþ®Ø!‘gT]e ÏN¨µ© ÏÞ.™D\ÃåÏ|ÇÒuäWRòqù=ˆ«îª®®+2ee%+iIòwyÞänÔÅsÌ*AìÈò…¹’Ÿ<;Ln\T¶.à+Ì$k¡ø³Dm H—Ó£çœí„b`ß Ævù¸ç—“Žfæ…œ;äFÑ7~i4fgÁFWšb ›¦õÍóÇŽÖõõZÃQy˜wj{$H£3 /‹fiPðʼnÀa!À¹ƒð’A’$þå( to‡J]êb*ÆqÄÆòéq×÷ÃŽ@“êk sŠvP G÷ÑÏÄKðHWC³ 8cÐã@p‡Ð9ëôª†Ç¶©)¿«]îj™­õâxdsB¾«ÐÐ@ð®„;aqß?Å&0L°€ÀRE,¯ý9sòGNzkÃ<¹ÙñÆÇ3hî4]ãØ\`¨äC¢=p<#,|úÚ#&*yóì^éç½\‚¡p>®s2¶9¾ÈðòÍ¡Ñ ê‹<â="ˆhÏš,XbãUIU–¬Kê§!@f½„HsÕ$d²_ÛæF€8>O}|˜ýæø$\ˆ™ê}ž=Ï~ DŠúŠgNß>™WôÀæû€@¾mèHç.À¾ÈóÒŸZ:ö×#T™°àùúù⨸Q'ƒÑ¢.¢KùbH& Ò† ¥E®—$\ú!Êë¼­˜?ݧÂz50ÇÈ„H Â<2<ÎD8ŽP‘2$‰ sVŒ<ɼàö‰ˆqèY¶Õ]Œé|WX€A$úÚZ÷íq«=}8ûúü¶Ü¢| ! þ{Oƒã<µi;pðh"‚89Ñ~Õ·½ü¯—·ßìd!„oãmZž{þ=ô¶· ˜NPV›4Ì á ÉhÕ¦Óp ›Ž8½'#³wWDG‰0Gh·W‹ß[øå«Æn+5£ÎIiì„Y&T<A!þÕo>>ž½ïo]Þ/Âûà‚b$#‰@CXi׿¿øow ¸'ädDh“îbI%Bý<@›‹ë"3¤£½Ï7ªÈ¿VÞÓÓÈ3VÑ£èŠH <Ô”0!TÁ0Ià³ÀævrBû‹±ìI“†·É|™±îÈ4ú8// a p¦BX·H_o=)™›å‰÷#ÀOð`PAľ >Öy½”+<’5C š±3Þý7µó¼ºïߟ-}¾ÐQ"$Q¦ ú%î篧ËÚø÷¾>/yïËyE–&w‘OäO¹ÈB07xÈ:X¢8É÷Û±kFKÀ†¹?5€ãÓòˆ„‡‡”d‡ÆÏòGHïW ”@İJg–yQO EiÒFŒu¼Iú<5J[lµeµY'Žœwïµ×ƒ›má¾px¸䀃‹bê`€ýÉÀœ€‘€ðh¿zëà<*è4£ä@ÓÀíg„qxÎx}ÆûtÆygN9éõ=ÀC€@ðÀkÕPðU !¸Ì‚˜÷ÀŸ!ò}‰9½“ñÂ.¹qË3Fb÷áiWÁ:Qˆ|@ö /gœ'‚% "Ê>åU¶¢h4BY…[7ÊŽ´ôãPã1]Ž«òtd’7P`¥„`„l#Z±kü=¹[B=%ôˆ¢=õˆÐŒØ”FÅÑ"„pQèÌl`F„QŠÇW˰Žb;`ÙˆE¸J$˜"’:âm°î;ø£óó^ ^û ûž(Ê'ò¨Ïré(«ð;«&^Ö÷Änhï“·cÊaöf™e¸!˜ÅÙÆ² Íêš}½]Ê¥¯ Üî«§¨mš¼Á0®¥JäÎìqÙ1¶vDYŽò{8ˆS¦no;9Û›ËˈÁ zãgfç»*ò¶¯çˆ=ÞµRñ¼¾Ä«¬+ËßJk¥îÐ3mwéÃ}}p÷c±¹éùª ºÕξún£ÉŠ/0ϯ䭪ȳžüõx®áv*ë'6ÆßciÞÖço;0æÒŽës9µnÒØ5«£ &^°KØ <Õ™;Áqމ9zcpÁÁiLÂ2 @4ó?ÕVÂÞÙ/®‘Tß~~GîºÑœñÂÝ~å@õê0Eœ¨ ã⯶;Þ¶6.hÝ£Ÿ{Põ]u»¼›q®IˆËè‚wiÙ‡Ó»•u]Û§7#°–ªZ5_Ñõ¯¾7z„ÁCÇÆÓ7ÛZcà?0oŸ„™˜AšN€5ߟ›­ÑMŒo•í{áÍÿÓ³û}íCÑ£ˆ“ò>ÇWI›ë%!êP'‚7@"€ñúâìÖËe‘bÅ ,*?#G}x\z½z]ŒGà¨6?‹ò)·éÚüëM)h À°ƒÀuۆȘcFœ8tcMÚth䮌p0^Cݹ¦ãË ‚èG¿ÿ—þÏõÈç> óÑyùw¥ûµv˜%0¥•úŸµ?¬@žv– 9m¡ ý¬„¯_›3C^ׇLbþ ÙÍÍÏÏŸUºK›Ž£¸5.bèÆ(!«”ȱMLÜØ2'‚pP¼"1h‹…Ø0*Öfƒ‰Ä û¿Bέr‰…­ËÈuæšìwu£tAY„AG#§Ï1æÊ¼>BNÏ™»n”Щ]òæåy`lNñ»˜‚û9 Æš®š9¶›¥;3Y;sgq ª—.ƒ|8(:«˜Y…+°à»˜¶^ÝëØujq—aÚdÖV%žOlfƒ¾k£Ñdó¾ræ"²6©ŽÖÆÏšÈ>7®¦k ½^ty¯J¤æ° hãRE±Q!Ðä&I2ãfóŒ7|;}bêÙ¹ƒxšª °ÜîöwǦ3YÓ»}”¬ò¼ó¢ýúØØñÖëL^y¿Ü¿ôdŽv#Þ$T7Y:*¶ÍkŸó73Ó˜ 8;çkžpˆ®`±ïïšÐcÄ‘ ü³ç…ì/ÝT=ÒƒË.`z\5È÷íÈËã9£*½ö<¾ùò(×P“‡žúÃÇ…P#¤"&—8aÓÁQà9,2(Éâ<àÙÙc¿\òÆŒ"âG¡Ï\`'бàßcà „üt ÄWÏÔyÊH]Uê(Ô§^1ÉÓî舩`áO±¹¢@| T:ð)$v²¨U|3"d“çAÌ?Áà AØ@ƃ7Ö¼«9$ÛYF[ a’h«UVNZŒcÙ«ws6¦³·_J˜ñ-·¿¯3ÛÛé_o¼ˆM’!CSá<$<#”‘5É÷òU|ië¹B·Îäˆ×Ec VЊ: O <2#‚'Ÿ»S3ÀÌGÄÀʪ_@„{ IP#ä€Ï$ö÷dM'Dµ‘^¤ì¤“³9[ïñëÚ^×“Þøëéë¿Æ}o²L¡@#ùãâùf0‰`\yILn;²k¯]'à(©‡}*DÌWŒÕ”~n¬-ôãíŽö̵æËõî~œéE=OöxÏ<éCÂ5 ZÂ,Ÿ ê*¶‹³8¬yëÑÂO"ÈH’k‘Za† NÛsšcspV›(×CËŽÄI^?t²E\’|Ž^ ¢HãˆgÃìð|<.W,ñ=5Èõ¬m§´Æw®± #Øü3/㢀‚‚Ev€Iá"ªÂÚªñNö´ñê®Î­ã»“®Ûsµë;»Ü<л>–$|v°É r¸ÙödX¡ï£ã³2DÏG 9¿O!d{ YŠ…ïBqXbð¯}¨NfßuÔðdfˆä—}ðï_èÙxfYÕÛ‡.™ß;ʪ©KmRÊ£À@è(_±ÙÁä»:<"ÖrüÉ2'Ö®ûô=ÄšÍB„ɬDȪ™ïÎk'>8ÈÒHð9“éÉX€‚ €6;Âqm+“ xj04̵ͦÌNYowÂI#A=_ÏÑÎsKÀ8½1`s݇“—~r2—ßyׂåú B ‚Aöüî|üäyqÁž]ÄÀ©p2Ka‘$úgâß_þ.÷תÉkéöŸo{ï~ ’ 0,ŠH$+Ûçóó×áë¾Õ¿íä ‰`,#ÃëÉC‘†€JýHÄÎÈðÉ ×‘ï}×Ï(ó@Guy¸Hã¤:}û9;õæÉÂS³ H’ëÜᇖyJÉTÂÀdÖ5Á‹.l†WPÙk£Ó‰)4ÚÐö§È’ê¹^ÿFHm[ØFÂ4#T¿Íþ£ú?SÔà"wÐý¾yø~©Œz—?*%vÍaýY¤9¿Ñy#2­nÕChTÊœ‹Ú®»ŠÅlh=ܪ­ÜŠê½}SQŽ3!‰¾çBT[=‡‘z¥^ëÇÚ|ÈšïbSÝÔÌáíB{NQ»£S+;šûb¡SF:œì·Yu7mYÈ]ËîM‹ËÞÅëØ¨Ó§¹=ÇÞÎ aËê’õÝÔNÇUbkv—hgk¢\Ù£ÝØª±›¢û¯AK.!e^aiN¬ÓÞ*ïBÉ].2Y®í‚"7ªn?‡ ^ÍuÞË†ç ¾¼7nõ¾w¶ë¶d(F³¶ª±GV¾ÍOcmþî9C1¨3®Í!×\„¦ÞË$]/ÁÚ9žˆ„₾ˆ¤—PØ£Õ+½©s3YÝ«'¹7¸„NQ}ÈÖ{’ïrîQ©ÊÝÚÃ0&5Nˆýc‚†yƒ¢<ó+Ï‹rjæNEØw=ÇzsS³˜jieo3;WŽðÆv–ÝÃÛEeÐ+KŽðÓ–Ò0îÅ=]‰6dñ]ŒË"ïf*fÕíÐq3§ÉÊý_ÇõŸz¹·‹²O|ô§ßzÎÎŵN]Qdõ‚&g³"ûÚª»R¨`îõÅ©ÃÃ3'N¸œanÍÜon*âúª(ÞNobúÆ0¢ØHɹ8ªh‡%æ=14àdOwÍ+Û±YFa]E­ u°r•¸º©‹ÅF£®é©…Ùu%EÒƒaiEUFZgòß}uûÇýÄÐs4‹Œ×óÂÀÑ![Œ“\gÕ#_Æ™äúÐ('¾‚Kˆx6«¸R˜(Wzwâüu€Òÿs\`ëûoóÒ‡±¶½æ«ƒù@BÀþˆ °D hÀÅ 0hÖÁ€±CC’R­Ø¤à0§EŒˆþ/¿×˜÷ö„„ŒHB0œtWôýŸS˜õw+V¾^•YËÇË…ùjÔs·ns¸aˆÙÈÈ*;g „oXá…‚À¸€ŒøxÇ$@V®\fÑÊ܇EýSRúoJ‰T,Bw&3'=Xn+§ÈŽ)–“€ûµ´1îàÓ·—س”;HÒ§KaLëûªëí&/d¼éí\\Ç{{á§ÚÁ½è„‘nj"¦$PIF¡‡(³Ä…[—çLB=»͈rû¥5¨BF¦‘A;bºÕÞ¯<1Z¢&üåjvs f'Ï<Úˆh8éc`ƒ\’÷µµu “6! ¬Ï + %†y5“æn‰ºÎʉ…ý™ï€Œ‚‚.ƒÉ<»3}yÀG ?Bˆ<%¯}%‹ê šô<<\'Ç=V?¿ë‚î¸8ý|1:àz˜ ÍžÞÆD^ØOÚqןÑÝ{î\Û¶šë°2-'Píw ÙÑw ¯—¬ÏÇÆhHÃ(ÊC¯·Ÿ;>¿O§¿×Û~^vD¹‘>@ˆב†n9ôŽl{J`i>sçÖzŒËQoÃïÏŸŽ¡­ŸQáá¥À½S³–¹Ù ýUd†x<<ðòlÿƒôß~ǂ !ë¡óÏ@ &†W&lç]uËênú÷žÏ&lh FoÍÀ︈ùõ»þ{ÞØŒz¸ËÁßgµ€å@÷3÷ÀCDÕEûŠü!ÀÁ^(ô úRøŸožíl¾:µÓÇxÄڈ ߟ=Û=uÖ·qá49ͼ<%¢Úµm¶*P‚LSÙ¿o¿·¿ËéçËڷŹ¿ V¸9ªh勞{g°ß8¦ôû8$_¾û=ý |ôÏ¿Y¿d4€Drø>ˆd–É郀ÓÒdF 9DUÛx%¬HÊ‚‡…­ff¦Ž`kuã»l’HÆH> Ñèx‚À‹|€"A^LÈNÌü{ãsÌWjžV‰AK+°{Æ<v ²yý̆ú¡üì ¾PK_ Seü.|›¤&»tÔ#UÊýý|\œú•fºy Ü{8î3Åá)mxyø$ðî·CÖˆ‚ûÛ/(QõZ¾fDy_QçóÐ>ê?´yÎR(“î¼OÏ*>Ï$ý}Ÿ˜>ípxD. ÊúJLé­ó”}R’Ï àE hŸÃòc¿a£ hŽyΰø=||‚$$gÇǽåø~=î½¼ï;ìûŒ ÁÔÈún‘CÃ.|'xc⹇ñê¶„€t{à¾Åªœô¹ðD”znÔã¢"LÊFõrõr­rb²"¤zÑB?èùëÖß{ñ¯ÄH¡__—›Ï=­Þ_ÛèÍ¡æ.Æ×œœÊÁÜ -̨á‰꼩³ñ2A§àׂ:χÝz`tí)ncœ¢%/FÊ#ÙÃÌ ÔÅ‚Z;‘R=.ŒÙé™A‘Ò=¾Ÿk½}ú}ûv¯Âû‰ _/qê¾TðˆhudDz¼ŸÎ… "µz~ó.úÚ¬ŸU?60ð( ¥å„½t1Îpt/WçÊùŸ/®\·ÕÒ¡„b†.S:› P“É X+q#E‚ ¾zŒ\‹¡ÜÏ\ùlSH`gàúý矕÷y{_{ê‡çÁ| õ1e!ÙËóã0Çw4“Ñfð |fàµêø>žâœŸ‚½xýûZx8@³Æx<#tðh6h‰<±Oüfð.÷º< kÙ–Îçg¸y=ÏÐýoàþÛCÜÙ6ñU€J(° l<}–ÿ3‘¦â=G¥‚0¢8PŒ4ÁèÙé4#Ö#qm¾nØI9œÛ^,L&Á#58ãUí»G8 rƒpüïŒý³ÈPc_¥ì]Dzª¸ªîå·:.´G]Ä 5PCì­Ãc#»Ñ³y—Ne½4jŒ]…úéÒ‘ºHY>û™áãèqmˆ† WjŒÎãé‹­)å/+*VÑ8•]ÕùlžÆ­Œ¬ËSn&<{Ý¥S—®×vÓ­®æ£=ÅËŒèÝYõ\BŒÞܘ]µY]ô¨²;±‘pqìEb¯ !a*½1åôçso{pS3†”6ÐÕ¤æíæ+œg0¤.¢;Õih'YUÙ«æ*µÓ&”lv¶¬ÄìP‹×Gn3÷/aw]ê†{¢w³F×`¤ŽÒ;Pz˜# Md^¾àÜŠDá[’â5XEÙ̳¦\gt¬'o Ï;NÇ{+žww%Âqt*àÂòh˜ƒP&0bV',×hUÛ¼Y÷¹ÈƒrÑwG§fdТë!“õþÙ . ØÿVÇþ©¨’®|¿ngïú1Ϋ/>6ï5n§°ä`lr¼ „IËK$Öìî½oÃ[;©žÐ݃@ÞF%Ð@R‚>ÈåµWKò\§ï.ãqÊÛy½yXÚUë×´½«¦ú Mœ•ÍÃg4ÝÆÎ¹? £g#g67#€G3S’¶˜€ÍH” ¡¦fzeÊútß®Jà wxÃì>&®S8Ã÷î²>€ÊCìSÃõ e´EÄ$\Tò˜cƒ˜/Dƒ’/3›Í dÜò~à½Tûª—A©u/°åÔEÍÀraÚÆ•gÒnGçû$`5y»ÑwXhâ ©ãË^Ÿ;6T58Å#É7rÏ!ÄÇO‚»df6Wr#²K»ƒÙ½ÜËÀ¼¯ ìNùÑb˜Ê¨Š¹Mã<è4nUùÛ&(v\<Å5•¾wº·ËŒ(ŽùlØ’ÙÓÛ—bA¦Çže\µdòÂU³”°Ã–8ì nÙÃB2æ©Q›–6jѺq±qâ™FœBqÐ4ĺ¼Õ¦õÉͲ£`m\V²‚R$YótºÝÞÈè±^ê4¡ 0n¯ tL?]1ⲋšïŠéø©&ÛêÙ¿#<SB¼³«&Ë2Ì«ßU#JñíY{˜Lâ ñ«µä/*jV¬‚'6õi­”×uÚ§­DMÃ,cü~Øÿaç¯dÂx@$$﹑'Ó\¨GQ(09–¢H€":4zŠÒg6±{ ¿qÎ>3>ör¼î8XvñçeÞÝ@õ>v8Z뇪~¼0Lý:ß=íuõûÛçô¦H À$žHzNû(= Å°d(NŠ)†ërë”(¤:÷@ô8Êå~>z;’ÃÓÑž´á»›Ì¾½81É>€æzš"‚u«â"I’ñáóÅÏG‚<ˆ<©ñÉ‘ÉôPÓ¾æ¤ òNž ½lÎŒ~¹è‚8Iœ:!G¯R @ßS”Ï’~Àg<½õeAßWà0 úIA¿®vÛ®ÛõåD“±DväçšÁ9KßË—¦¸Uââ/Ô¸*úò¢† 5Û%­(§ÿÀûÙ­õ—Ö_k¡ú/¥íòü/œÂÄHDC#4"…ÙwËï÷úooŒ£Cè4h±qÕ{ÚŽPÁ„gSewìÓøžûäèª! @­Êè†Góh‘jËxIp×Zk / !!xĹ bðŠ[U¬…EÙ|„x8à›H°’I— ÚI™®»ê‹D’:!WDg$4‹³ÈˆôB »P-KžŒ)#¢¢FPêˆjióÃÅ·¢=Sö¤ÕÄ_j`S„X¾_¡à&‚šö_/¯›ä«Ò¾Ùï{_a®5ç6 HêmóYŽç¡V†ø€~:R ™·è²=b5tƒàÇ!ÁÓ;LrÎYJt YÌ4Ó;Vü¿WÃÿN#âa5lª" @F¡ÿMý‡¢<ÓÌðÑ™B;Gú)üáà¥ð~î«ðå£ï°žÜnbu: ›ÙŽÙÐoŇθ²-Tyx&< «¡ÚØt3n¯7®”Õ.‰ \ªuqÚ‰Àðc‡7K±›Çc«¼œšá!]·—ÝÅQvÑ1k!LZU¬BšU˜"¶MwaÕnôÆäJ²w¹µ£uCÓslWvñ B¥rP¬£W”û›vU~¸ο o„µ7{$uT¬9çr^Tα]'r[¨pæ¹}5vrûÚpg9س½]˜¸du¾·UÐÆá;pÈÆö‡^‚ºöP¹²VªYR"Š4ŹHßLž‘[t:Ü=ïV%qæ,“PÕ%Qa<ˆ±såtîh7¶ÌÎŽôìN2¶Í Ù¼]ïTdUëa_wvM6Ë·¬gFªÁ³s:ä¿ù_íØýF»ãÀüfY1é{QêЋ4=faS ÖLæ[ºÄÖ{1Š# ¨ŒËØZdÐu"]VÎ<62;‹Ór#°Å8Ž*v-ßu[:.å]ó ÍY‘:yQN67%l|E÷<¬µšg¤‡ª5È…ƒÄ4¬»«‘‡I¨‰k!‰1pNMWvz{¶ti¼KFÅ“bRØÅÊD gbòr¡fU:=ªéÁ‘Q;/î2R¾¼6öyÛ0•Py9×löñôÇw¦Ta¤"!:Rúk3ÝcÈÎò»ã®ñŠ5sßk$Åʨa5H6•ôq_µ¿ÚÎ= §©~–Ÿ*Î×Ås©¯ÅÛkwXš…êŠÛçÑ5˜Lßž6MœJ²¶í6ÞÝ”•MÕŠÀDü­ªÞ]o.½ó‘{ì%fÖÌ{øÓLW÷;È&M÷ZÉÓ²Ctß{!yŒÕ½’ ¦;SyMåv†ÍŸUÆw¼a¬¡é†×dnXÀ³ 7—(¸ÐÝzÊó%—ƒÉ]+ÍëËÕ= &á %ŽYc–1Â2Y—.S(¬\h¬š,Ç}dùìÙ4ÉË5k.1ŒÆn}Ìû~XÍ9LËZÊ÷¶56lÉXÿ¯³iM2UM˜ši1pŒq„%ª¤d³,°„ósfYÙedгÉ4ÔÓ±*ÌbS&e³%b²VŒšYý,‹4i60Å™eššK4Õ^QÛtÙÛ&ïËoµ¶Ý1Ó|Ù ³c–1Å Be™PË rÃ4iL˜³lö•“Mš)©‹4Ÿk&šdÆ1XcR±‰ŒdÇF¹í1h¡ÀlÑc?‹Èò¼'G@Ž„{´Sc±þ¯Þ*'ׯœ<½ü;~eñ$µe‡«,2䵯+MY…wqúËEZ©»ÍÌŠ3s3D95gñ“²´¬ë*¶—ääD1uÄSíÉ÷DœÉ>¹Ù~vg]3¡„Õ? ÑQ h‘…ÿ{§Í׳FÜï]Ëåê¹J/¹ËÝrÛÍBÂÒËå׋̹µÒ¸³WRÅ»\«ZÌ é\‚‘–@yLÜTõ³~’pTAã™Íñ …Wê`·º ë¶ÿ ŸÞ“Çq©AFz¿'Jß`¦²™¢Á8Ÿ}P6§K`ŽDí4³ž`òð™×ª=æúÏ…:¶k·øåÍÞÖz¼x¦Òc§¾÷Cáô|Sví ìÓ„²šMœøtß9üúy>®ã‡Ç=«? õ« Âa*'‘v°°ã†–Â!xTÊbbh°{· ?•Õû^ƒáN|ðEÖEú˜¦è˜…DÞ“ê¡ßç9Ë;7ôçóp^F‘íÀ´ù³/‹CÛ‰„NÞÞ»[ÇG͉ÏìyVîÀµëÌ÷k—*_ >(Ldò2¾F>U­æUdßvg‘«Lðïò\Õ1®µŸùßóoQD•°ónKÕž=-¿äcÄxpoØý9ø'$ˆ+?gà™ãõSÏ0?‚7Ó€nõ~ŒPÉ¿ž…H“ ‹¦Äk¶uDY”ۖɄؔ0Í©ê‹@†¤7:Å(F}’ü¿Sœ¿OíÀ!ž‘Îià?ÔÜòs…Ê1¢6LtíŽXi\yž”ÐÓ6ªôÿzÆE áiˆQHqÆI./O­÷ý¥€Vº{„¾ùFJ ±¨I'¯g×îù~ÎØ2\¡'£[$P·n&³Ÿ}×ú’°ô-Sµ+Šù‡À9¼8ð3MSÌŸJg°ó†X.(ÙGeÁÄyš_‘ Þ/rÁÝœ—ôm¦ÿŸ¡€î/U:¹?ÕÄÀÀ…'`¢‘D}熰~£Ý«p93Q×Hˆg;L[Þ4g˜KÜ `ŒZå}APQq,€-IÌ¡ªLÆY²X:ÛÕ×@QïWÚ­`.ÈOï7úãoßÑü|¾rùìÕ^¿¥ûßù?ÿ·sãy€õÈDêŠ üÏ÷x|pö"Šûuèq{§Ùb ;¼¯D§åêº+dÂj‡Æ¯Šüš¿ÊÜU^ÀÂìµ{\!Õù‡-©Í´Øtá—ûó**ẛ(da¤“ºvR«váLráÛ…ØK0ß@|³Öž% îÎè8z»—Üô©­AÀ¬‚Ö)Åø?áß@ùøînn9kÛ’ÜUÓ2äÈÓ3µÕ”è§X§òQïÙd?UþrðÁÆ?WÏúûÑï>¤~½Š­“>|]г1õà&ƶ;[KÜþ¬ï|^}ǯZ.—¯¤¿"¼ó,k;í*Œ«fjÆ\ª5Ãõç?6[íqD6KüJò¢ròqóö¿7’!—àÓ® áPføŽÈ]"@p €iÓÏÀŠ~-¤¦t0ÖÊ(¼ƒ¥ç£a]ŸEˆ2I|š&ž;vªfØ\fC‚H"*)S`íÐtDd4`mê¨D ˆ ¨¸û˜e2 7uËBÞÉeŒG´&ã^A‚êÛÍG€ïqtôaÑàÙ–9[\-î^ÅësÙ`ó:ý¯=óHµ ¤²$ŒˆJN² êLÙ*ÊŠP¯QňR ©[[6«6«-k"#¢ˆ“J1ˆ€ÉA€Š PDˆ Š4QmXÚÁEQF%F*$Ø¢Ái,bŠ(‹kVmVZÖ4DF1E&0”b1’ƒ ˆ A‚€¢‹jÆÖ‚*Š4i*1Q&Å$‚B Œ HÈHˆ¡ö>×o컸<Ý0£svOŸm]ÊȰƒs0:lÞ0Òqè‰U&Ó*®é±Á7‹I©Èô6ãŸ.>FìñÛ^ýÏ|Ù¬õ¼ü|©ÚñÚ%Cߕӣ@9q Pœ¤qÃiWÀƒ1âúˆ¢á´ÐÃÅ £ ºH7Ž&d‚ˆI(£„¬ŸzB¾ª¦ìQÆÎ¥ò­ÕU CMu§RŒ8ŶnÁ°…£œ“yV‚Î¥ê1Â¥³¦ƒ•T•v¬keû %†WY¸Ï›VŽslËαB(ª1 =¾.k׿t˜·@D‘É` ÕVÚÿëøfÕg–­n“)‘f[,QD¥L’%KQ4Ôm“XØ´RIDQÉdšTDkE“V6’¢Ù-*fÑlÍk,Š6ŠŠ*MªŠ«`¶ÆÄ¥¥%%5(ÚØ”ÅÆÙ+$’•%IIQe(¨´E¢"ÒËeedª+cl²KQ²EV­ÕmE¨’DA(„×ëdsËÉ„Jžkˆ £–’EYí–ÚZx‹„4Ú̱Š.³\þA¯4S›ÆßÐÞ^t\ÕÓ|œÚÿl½RSJ)E¤×»-ÎZîÝ·*½—–xîêíDƒB*:A¨ ƒýZQúJèÝ@qPÊä±kJYI (•$B4(ª4¡J‹-HÕòZåEfˆ˜¤‘ dLš ‘™ƒ  µRÚb±j5hÛd‰i¦Foë÷íV¼µ¼mµ²´khÚjmªÃj³jmªÁhÒ¶ÀjÕ•R‘@b€ÁEQ€ EEÆFJ(ðû¿ýɈ >¿ä|­õ뢀€D‚€d@ˆlj0Û4Öví’~u„{”~ WËæ]8àNqß~«æzÁÕ$õ× ÌP‚¿ÕÒ•ö ­@d. ¬X‘T¨Â"žœQÒ#"|ˆ)ëv”L¾½@u|ðÖ( Uùâ…¿ª[ã%e™¬¬[·ñ-ªÍ`ÜP‡ñÄ(PÞ…™( "ª°PÙDAGé( …²ŠU€È( µ>¿hQTn”à‡ŽPP Ï 4 Ž`‘C„Q"®KmŠª‹%RšÚ,¡Õª6ÛR–Õ³R‰YcmHû¢€Ùù3P‡Á;G‹õÞ]ß»u¾š4‘u*$5Gš*-©BÝ'ÄÛn¿ÈåÂŒñïFçoæ_ç|sÀ`(uC (  6M´ÅÔgI•¸*D/ŽÕvo"ˆ€µ˜ÒÛ-¶ãZ\Ä—ÅÊ Ö ¥vMý9PaG+w?·|þ/4Ñ!I%1Hµf@“S#Ýá­$ýȲ6+lj+&Á°h²`£QŒF”×i«ú•m¶ÖßOɸ*¨½¯ò¾ÏŨõyÕõwÙU—wYc\2>…#ìÎ÷‚¿óðªuùïÛ€y_CÉ Éû+>÷»úT÷9~N„'è~Ö§Ÿ{òd-ÁºçÅòvóÂ¥†´ƒa6ÅEº.Z•𠾞p‰=¸‚˜«í„£w 57y•" B¥ä“ó®OH¸V-È[¯*ôˆ(`€ÀëÕþ\ÍÃÃ`3µ¬VÿÝz×ß…Z8EΩØÐйHe²½‰î‡/ “ÄrøÊ)Y€™Q‹¼Ñ¤H€©­àDT„*ªþ{ó”Odñ(j’€Ù¨ «'ü…£X)ûþwUÓ•smϘ…ªÅš-µ@pgŒ?b 0Ñ >r ÚA,‚xˆi« m—…~ž×ñw[o›Í´ V©V5£P”l%TÒÔ„ŒÛ±¡ Œ¦Ñd¨3žüvß?G·Ž©e¨¨…N$ˆÒ“iÔ‚Y“à ²fI3ÚË´dæÄˆ£RfÒÈY„e©Á«±Á@l >ÇC(•_]ªÞÚµ©µYe€€ fH€HH˜(HEµYµXYXe`•€ †``„€’I €@µZ( P 0QŠŒ`Šš€à¢¨Ù@b* 3ÌÆ–¡–M·Ö·Óõv«yëØ¯wWØÆ MÙ×éü@u(A6EQ†ÊTZ‚ e-b™ duE-Î*)I¤m6\*í¬‹VUEµ½;d—€åJ¦Ø-c„1T€'orÉeóÿöS‹dŒõó¿Gc„å©€ôßþ¿~^¦ß¶ùiöÒp…Û¥;|¸é{òUšËwé£Âªÿ /_ý¦üüŠô>Óè¿ÃÇð´øõ˜ Á@}oðzÿ}ÜýÊÈUÚL};Þ׫¾¾×õÞ>¶Ôô CžÒ¶ÁÛf—>U¯ã™˜øä<«³Š¬¶æ»Lð!EÕ–ûþüÒÒ¿Ç=ÕÃȯUO­?«Ó &!‚"""""hÃü¤‚THY« –"È%Dª?[w–9%Jm+û¿ÿCéÿÃí´Ò°ŸÊ±G,eŽÿE?ièë¿ñ¢ëMD?’ *=y®èÙOÅý}ŽÏ`Cí§à D?ˆ‡ÿŽÔE@(Eb¨Ä€Ÿ_Öúà%EWüáS÷ýíg´ ?´O¶øÖàíüóù6?1PÜŒOùì=ãÉ>Õ†ïOö¹ƒóEèì‹v{ïÿßVÿÇ ÀÊŸ`¼ÜÑøP2!?xQÀ!þÏì~ㆼtPûOk.,óÚáa|Ý «NMg*ýX”ßk•’|§Ár|8x[‡ R$Š/T*€„ªLÍQžòÐñq,ÖWIWD® Èp+kߢû {.±Æ$OÈ2 4á·±`KöbþGàf Š|åú¥²Póÿ×ÂꂀР؆òàŠêKåù`¥ Vþ&¶·Å)-dƒM„’¬¤’YR´™fJÒU%*¢•JUQ*¢~3Ó©3o¥yCÚˆŠ%S@I(­p2Ù®ŒÊ¢¸ˆ88ößW§êµn”QÞëhÜò9´Ý /‚ÛK0î.'ÌÉÜú»¸°B7ËG=$D$”wmÄbŽ>ýåRuÛn6œÃí(ª‹þJ:ÿâzŸø¹PuCòÿX ¿Ø?Çüý»Õhˆ({Nï…÷ßýüÆàª(b†o$?„Á­H:×òKS&¶˜ÖšÙµ-µ“@‚©øe”AÞ€©¢€ÿß~‘TC2‡Ý‡ðÏõ6ÈUƒ½÷AüóÈÓúâe¨Oí|qÌj‹U’9ùPõ”öT(á ¼PPÎ4Ì4‰wÌ5B}­¦‹Óþ÷÷?þO·õ|^úË u¶|â® ð¾.“}¥1ØâE¯ q¹ÿ0ëb µ@0º‚ Š…”AE÷–(ÃÔrû&´ u€©R”AEþº€þ`)í™~oòóAÍ@w Ÿ(ï-£åÎ_€fs§ýÝÜPú«ÂË÷¿BFɳË¡ýó ]ÚÀŸí}O˜`b>?Ž{0$ÕW¶sà€QZ™  tÉ€‡i$ƒ N„_÷ë`0)ÞF_oúOu@…¦O«õ0–®†¾Á­‡CȺ<Ä\â£ñ§Õ)¼¬—©ˆˆ "”AEñÿßûOºL’}?™5g“ÿ&ÏØ‘ÏñÔòDH"¥”åÅøƒJ€P 0 $H ‰J)B”R‘b€ÁåŠg#ó8õ¾jªªà(°ýo‚¦(‚‡æûõù*òÁN ¢¸4nýeØq }ß•TW£K¿wY[¿#äÜöýö?¾ 9¼ðýž QJ#áªCõ°ç€ˆ €‚AF•@ ½¤Ç…G"÷¿.ý{Ír™kU–§þµôyðg½3(` ø«r|B …!L_Hˆˆˆˆ˜Ž~¬¥u³ûA<…/¨Pj⯴ ÿ5ŸÌ‘=pP|…‹œ„õ'›TÔ¢yÒåAûQÐ!¬4©R¦ *’¤¬©RT”›%Tš –%UU*Ô'ð÷ýª±øa, ì‰ÿëý¶Z¦Û‘ÍLzçæÜ(~×åfD&rr@ M~á.$ ÈòÓÉŸÙµîWÐ)ÂÆ£Ã…¬ ŠîŸ¹¯Äü =GTÿ…1¤AžÁ=öÿÏP1û¸òfþÔs‹§ÚW6Ť¿v€oFÛIE2QJ`B%ˆ5EA÷ío~7oS–¶.ÇfK¨Ð3iÍnG?Øð¨~ëõ½ÕåX `£ Ý׉Ê*z^x)’€ä 8 Ÿç¾—ÒºùQùiÉ(3Pªª¾°©R€Ù@}œý¶ }Ì žnf5Ôê–EÐA„‰ò3¡º¶F·qÞ–®8ì¥™jV.×F1ŃuhàI3°¾õ­W+Ä]“ ÛkZ@fÑÍ¡#22ç˜ ø§ÛDÿgÍóìO˰k·ÝÙpXOäcªÅäL`nn\=nîÆ~Ú«í*¿‡þm­' uh¡ÈÚ( ï VÜÔØ]p±öP}Mci89íÝ»[Q™½{¿ùWò‘x¿ËàºS}}óyQc ÿ¥?¼oAæ^z¼í¬ˆ@‹ÜD1¤@­à Ãê~É?éôEO]@ÿ)¯é0?ÉðO€ ºŸò´2ý’€è ¡ÿ0qÄûæü;q õi¢*ÊÙñ¤„‡£øµõU÷•U WÀŸ¸mþ?÷¾®lª¶²™1‘ÃLU5LÇæ²d&_wlïŠü¦šÔœ°Îá«ø[l}ËŸø€f¢]„20lÞˆW·HJ`™Ç€ØMŒÛY¼¯b¹¥“þ}«ˆóï9{¯2FPŒ<1"þ…P$̲è8ä2ÏN° ɵʔŸž¡Ñ™‘™ÃÊ Zì* ц±OBnƒ"ãgÙÔ0uÿýd’8_?Ž¿ß 3óê ó¯[‰¶¨$ÁZH€Ü`¡cH÷{ÔMçz ÏìÃùQÃèjo‘ Рô¢Æ¦†"Ø–q·âû¦­7JΞ‡Eþqõõ$@¼5|ˆ‘záÛ 8ÿ¿M§€ž ~…´·þ¾Cp´v ù»H~ÂT€¨7ŸGçä 8ˆþߨd¢ /úA¹@l¨ƒÏ{ €ýä‡<¬‡k NR ûøA¢ÿø[ïÑŠ ˆ_e¨d"*»NõuPzeÃŽØ^ƒ„LJ±‰u–U$f¡ƒ3#æŠä+zû‘£Ô¥mÀ\õ–dœ¥È1²{ï(°Ý ¢” =ÅÚòÙðûÒ«_+aùrW¸/ÊÑl.–I,;m¨“ÏÝ,X½íÂâð©ŽÊ0\[NÓéèt»·†„Á€‚ oáÂý;ý(ÊãÃͽU ônÚHGÛ¹éÿOáãíç2Ë|³òJGä¾áØA÷Š¢½ÀA¾ÿŽ¢ /qDòPD95zÏÅÓx*l 1aÑŽC°÷Oô}ooß9ùþ¥[ÒÑ„ÖA÷_ö§ßŸ‘øÉ¤ OÆ÷ÓÜðà„ç*î\÷ðºHIvæ23õú°±¡õ|¿‘¹Uuÿr:Ѿµý_§¯9v‹Ù÷3êi9rKV¦*ØEíââ†&ká†AÞÚꈀ;Ð’”2±ú>wç`yãþ)ÇÜ'éøÿ‹­ï*?þ}̵|+|­¿å ÷P")Gœ 1:¾@)_!©Ëß2|`RÀ ø”* â"Á“àÿë»…ÅL“!;ûUEhDD„“7ÜSÒš>™ñ$TTÂJj£%#Çò¨éŸ §¥ö>ÉlhT±nø|‹}ìä&;‰ cT¸N·Ð°j´.8} ÖÇW„¿r†ßš†áýð´&U!ü8cæû+wP¡øêö Š¡@z?ƒô¾çàc÷? XˆýtEK*ŠÝ@E+P  =Œ(KL”gÄìí?±ôëøœ 4?qéTù:éG`÷A¥A–WöýøÞ—¿ÇöÖ¯â÷ë×$vW…G£Ð÷áÏ\ù}ê€ûÅÈ„¹ò¯Ä‚:ô(*3ÁÑ=iBPÒ`SÄR<ÿË Tq±PìüUØ*|$À½&̈K›hpîãJe±µü…²ˆ9!ÞsTo8¨"ÎÃ.’ VêQ½"†Rª) {’?gõÃZ“3]Ȳ›e>Ú}åË?WòÏÛ‡â}N&¦ã¢tC×Ea6 ¤dÑ„9oR*D3¡»qQMÁ¥Ïãä‘ÑÄççª<¹MÄÛiæwgm‰AÞ~2˜ºŽ-œ’æ [””f]lÊÏô¤³}PD¹)¾%qPpŽ1ê€W:[Ogy]³vþíGWW¶çZ£u²›m~ë_€¡ÍD3=ÿu×ÖŽé•ßó~ë“þOÃøóR‡Ý‘û÷￈ =´@ÙëÇÿ›¹w@ü/ëv©ô‚zsûó28Dúã`%ÕV6¥„S‚îAF$@¨‚È%DY,Ç逼@€q*ª¯åzY}–¾î}¨)GÍÖ"û*™û C.‹ÿß÷Ö,~ŸÝW¡v¾š7£ó_ç…0ÅWž~„Z÷up‰ I2A aL@•%Eè€@,{eÌQ\ ÂkœêûÂHF YÚ¸ÉÁžÅypÈ6¡¢jÑï\û(z•™ÛÇ»ê{ž¬ÅúqÆ y :~µ_Τ/=›®V±²Õ>%\ †fff˜fb32LÇ1Y$W1 Ç2Es“’+˜¬‘Y‘Y™ÌW1Y"²Ef"LŠÈ¬’+3ÌW1YŠä‰&$Åf$L˜¬““‘Y$Vb¹"¹ŠæEbH,ÀȬę2"I"$ÄL™ˆ™"³ÌW1\Ę„2åF\¨fbfbf`DÊ—0H®dÌVEs"³É’+1Y1\‰‰"²+’H®LW&+$W&EfEfLW"¹“"²b¹˜’`²,Rf+1G2EdVfEfE¤¨%EªQ2PÌöàŸCý#‰?Áˆ ‚óÍ4@ÛàO~r}ÛúßbÈá:i•uZÊ=ç½·µê!KÕ«[õ¯š""""""""""""""""""""""""""""""""""""""""""""""""•¡<Pý#j?<;÷ÉþÏ~Ä®Kš²¿ñ,SÅ7G]¡_ VÓŸ ¥¡ú“E~?Ûþ7ð=“ÚÞ6Åc'¢»‘ÛÛïû]g§ÃÄ¥±(-±Y•Hdü6VJ¹êR7€ÃÿqúM‚|_wàõh£:ÛªöÃÏÚ`üxb½«If Ÿ“¸BÇýYéyÿ DûaRŠG’A,DBÂ!ÏòòA?ˆIç€( (°}µQ]¿Cá $,7JI"Iˆ(H¡ö>’CšIÜHó‰É$Sö¹(jï÷ëÀP>߉Cx‡Ä@M0Æ?ºümˆ""E “¾"åÅLjB»Ø¶ûÞ>uïìçÍøŸíõ%²•ê?ŽÜ· =om@}oÏÕí0îˆÝü«÷ê ¡ðøÝœ”‚hs›ç÷Éõüí¿š¡ÁC @„‘(q8èEjj²ª.ûáÎ{ùØ]ëGõºF'öÀ¦¤ðwvù|nßÔ²¾¤„ü@ÕüL0ù]çò¥|51œOõþB¶µ‰›K“I„‚}l ©E¾>L¤ ³¯í´îõ|y}ÔíkîÚZð8ÇO [7‚ú˜mªÛ<éZ2Ó— y/fŒ€¢”õÉy𭜵†Š€aÆDW¥2Ô\Îv ¢%† à@´z~…É<|½oGyÉZ­9÷<Äo»µÎvÐçǦºá@ºé,?e‹2tækd™êV€¿8ýþõŠ)i™OŒ¯Àˆ²¼x:ã<:ðݵDæky)êÒOºŠÊÑuésªêNÍLpè·t6ŸFÇ:§Oé{¿Æç3HD+eLé €S[HëI˜HA( !¼$‚I´D/ÒsgO8D(¦õ¾fn¾¥´yÔžÿbÉ%ÏKާ‹¡p—ý*ì–G£-z3H9ÄYè%¾F,Ë"‡Ay© D@9LA.7îDêIºBPƒ2­ìêwX1ËÅ"Zåh¨²ü?©cáÝ3•í]ž5;úI,…pÀØJÑ$Ç-Œ{°°zšíiµ í(@AÝȳÄeŸm#{Li¦>¸4Çûé¿Ðný«‹N£Üþo4>Œ*|ú«ZÖ*÷ÙMÄOŸbÖA-×r÷A/kYµ­dÖµKs^÷A/jA*©‘ÿ'8üz?a!…Šü¿Í£ ÃÛ}¿hüoWé[Pmâõ„ôú±Úkÿ»~‹<®`ÿzyñóz»–=<éuêž}½2gL3ÒÀüÈú‘>t¬¨øÛ«n®ãU'!O““$ñÎ0Á ´U¢­h«EZ*ËDZ#Ž]*ºeUuÖ|{énîHŸJIØ'`=ƒ§yɦ›S³“‡fyðϧ²ÝWì#×CFËe ,À ˜‹Œ¤aΆîÞ•A“­ãƒ$‘$3;žB-h‹DZ"ш´E¢-»À¾ÖÒO’!ò'ÈŸ×ysj:újÉh[/Øc@&íCµµ0ϳÃÚ?C§ïçoèöW¬îrè`cØv`ñuëz:ùú<:Ë ›á×|ýV厜‚r<‡ ò<{tQ7W¿O¶Û¤’;ÆáÜ;5dk›!Q AÛ«-QÓTÔjº y{—°‰o€ó«u»ÿ×?Ág굯kÏÙèò?·¦4¶­;sVå¾ÞO§î‡v_¼é·¤BІÓ\êå_}3¶ËúÝíW‡Ù_%I†Í\¨ç¢¸bª»YaßÕŒRD¬ð\ŒVCÎ4 }‚¼6Ìã`, àp˜ð<*éMákEi %jˆ°dÊ ^¦\ŒL!cCFN ‰—ó±ú[„ÌÄ_6ñ(±¿À]ÅjûGwå‚rÀÂR`ÌD&öæ² 8aÙGù&§>ÏcMÕÞ©ˆü)úïÖë÷žƒ›Õ§'±è›ó¯á¥ 1oŸ‡Þ}Ýž<¼È½ßj2 Bå| ò/¶ŸŒXØÙ¦Gw~}/~VrL…òÆ,övË>ëèT,@Áƒ@Ä?ªxÙÈTÕK(åû…ýlÍ;ØÈ]oÕßê~'ïß—›ßðž¼åŸÒ¨ª¢M)1NÌ8NN£ ­º9&ppÙøaF<‰R¸@|!lÀ5@Â÷pªåBÈ!Ï?ÅþJû|}ÿ‡ùôýûÝeÙÝË’–\Ãa{Ý›!®þq“™¨ý²9$tæíÜ5Sö9eÝ ³‰fåìXIv$’ ‰¬UU"8+‚’ $TÌìLÌÒHŠcq˜”MYrÎ hÓc‰ÄpÞqx›æqµÙÆûJ〮 ¹\Uª ˜ó>ËqßÁ çêó#õû}Åô\™<ýïßu~{¹ú‡úB€ùúg¿Žì_C½Nr|Ó&±ŒÖd„¸@\a‡@ñm:rÝÞù§0rq‰ËæBÑý¨±V8N]¬‘Áárx˜<ÀsD{n#yÜGAÜFæ#ê#Ž‚9ˆä#n#B:ÜFÂ0GA„n#„tÏl ph‚À%÷‚„@ÕÀ;™Ùîwwwwf¤³\R•7"è.@‹! !iÁáä‘fh\í…‘™³J8ÄJ"S8@ˆŠÈE„IîÛ ä|n³˜ ùŸwé>çûÇ_I¸oa«Æ÷úxÌköÂüòLvçà Ìu5>¨}UPÒÅœ¯“+¬ú ¸‚*H>jG_›‰çB¯M+ñ¢¾ÅŒíLÍ.[3Ä&r\ÈøÂ\ëñýÍ.òEÂ…¹!†÷ßR÷ kÒ{W¯+M-Œ̆a¦”¶.ÞÅ`[mÏ.[. ál«·è`r—k1Šß\îÊUËRJÔÅfr™Fü8!ï½ïÄÏ‹#àŸ¿ûÿ]Ú0òg¹ÉLüŠàòNÆ›Ä>°5Mq—ò^‚‰!ûu€ÇŽ*#è|š¸™ILoRÓœó>ÊÊ÷¯ê QÒ0?’~̹yô‡¶”xþø‡äÜ£æ‘Ë@MÇÍU¹pJU EWêX Žgw£÷@ >I§”XAx}¸ö#Õ!-h‹DZ"ш´´U£œÃ)ºêµÔ$cVÌ0FQÈV±Œ[ª¡ TE‰DTþ"°EŒªÁ&,²°E¢,¢/íÏ/»ýSÙ<'KLcÄú 7}VÍŸÆcÌä>£°v¢}™S±@v.×V°Ø¥xàÆ1Ë*xØãè\ȯ„fâàifÉÔdl¤u\v£_/$©jœ½5„Ñ‹×=‰C“¢Ã·ºX{fçŒÄs`øÅz:uŸ¯/à(Ð1ÈPÝë䇒;Mo/)ųû<8Ì+‹È-·‹5‰ÉçßqnÅ÷]û¯ðøŒ²ïarû·ï+,-~¢æ&ó/)ÏMÕ« [ø­«^JçàµzH#ßÄï4Æ]Ä|DEH'ðûþÞë÷ß~¼úGÏÃߨóçØûNúøß¼þîo¯~­ó~^ý~·ÅÏÁjöG¯¬ï5|Èö& BoÏr>}{÷xÏP½fLùE“ðü:øm9Ãê¾ßHû©ü>ß#ðñøVç××sËBÅøõjèlt“Ì!˜Š0ªE£Ÿ¸îy‚ hhs×ÛŸzߺ0.l33³{È` ’LCê93!'ÍísIDq1yã¼ÚóŽÑ@s ‘ؿ֣±Ü ‚HJ¼÷­µc˜yúùøBFAÆoãã:£Œ·€zs2æmÉpé°Š4Im¿Î=+'è‘…HqÅð, Îk€œxáz«Žj9íVµZ1dƘ-Ž[b_×öw&8&ÿe¬ÀˆJ÷%‰”’=È_çën íSÁ ‘ó@PÙYN*À0´D?HüÎÕ¸ÛÔ‰Ü ïüž‡a …ür‚ðqIR I~ðñH'Ê#æDQöØhš)í>u‰ßùˆ¾æ³ZÖ®²KLppZˆÌ“#ORL„ú$F²oÆÂ4Ë#q8ŽáÄ}q„}³ÍgêÕûˆÆ£õ±÷R úéÈôøýù± žhyœ“Jÿ£ý‹æ„nG°{²¡!"JI+ðN”ýë0zþc8‡ËÛGå?lÈ|B>!GÄ|Œ>2i»âÊcøõáJŸâ*_OÁÈF#”°Ná‚(¦#Ïâ¬ø"¹Rª^xµ!Û៉†þuôøÉù"="?(Lâ#B<=B0G Eè°k·ÔH'g:æФö¦ÌöÄ`M@&JðM~ZkdŠYæyUï“÷kRH„$æ…î"ݰB‚Ø‘ê÷öí‰û¾¥Ø{mxz_I^®M´Z_­–Úë¾´„™¬Ë$úrÃÓ&ÝN8Á@’Xú–W9~JÜA=rUêÅHIÛWM8¼A7¦9 3&¯ Íl26%ïJã°äÝ2Ll9b¦8D̬¯²20…²èP¶a€[b6΂Áxáƒ0̳Ç9,!±P¯/’sœá–Ãrãà–€d!¦c&Òƒ”ævœÝ·œ06rhP9²Ù°<)8“os²%óÞ êHЦ7è‹ÃJ$ȱRvˆA递©‹•WŽÆX7 £¹†ó -ÚÆcl%ÑA¹KôúÃÑ“º‡&fR^ýË *eš­,–¿• ”e‡zÆöMY½‰u„ƒ"–J…é'0«töL5Œæø.LÅ*O0&³8Áó W1€‰ãçÁ©Î›ô¹‚Н¿Q; H%Ÿ¤¿{–Éʼn*Q´ï‘;Ã'óbrG(5$=IübàL2âëÚ…QÍÛmË~ÿ®§. —U“ðëh ó2¬R Ì,­ÚˆÙ€6C·Ó…õ¿3ñ³m€ÈK§}ê“åªDª¬!8èˆä†¨¸~š{±w ƒ—W%*q«äÅê@€Täeö­ˆ§[éPê€áàõ}~gS9å6ª! NÁ1Ü'³ÅT3ÜéíÌÂåEÒK•TØ.õ {Ücì´NZÁ¶‹çutzêÄÖ 2¢·çpzâú:"TO{KI"dˆÉ*š,iÛº$æH0ycœ°e‘*®±©èdÚfúƒU%¥TôžjA¾ÃYÄs0(³Å,‹¨v»THrDÀó&Ï…½0Pà_Áà¬úNXT$bJ”¿è×îtŒ•uã²ÛëàëyéÅ•‡´¾@+ÇÅ”N¿/çQ`by-…Ó"å¹F§±Ì£-u̹® ßÅ#3ÇUŒsÓ<–Ç,³Ø†bæv€ï”-šPª‡q1¾¹¯È…ZøÜ“ò®cåÍU2áKìæ-«›d{<€W ¹åÒ,…(¨›„"Å.¦ìo ‚Eà ,éè³ÇPãL$Ó2Ϥœžg‚ÞÂNõšŽÁ$s0C*”&2—åÙI ªR:­-È~{‰„!1"€ÈmÊ‘<ú¡‹Vî«m’bʱ.Ï‘òn›º yI0'[N÷·6•–w& Ã@ØN¢ý&úPïro·ô¹T؈>l{Ê”hÜ"I‰Ìóê…ÀåÜ¡d½ùhÎížeÅ×1¼ ƒ)®¤ •#3LB¨A!w®¶ƒúÄÏ÷½¼×;M‹©»Þ¶PÑgŒúz•;Ùo›…':.ÆEr¸]@€(©öë““ë?Êõ_-÷N¡©éXÃ}V £( •¢-Ø üˆ˜A$F!KIPÜfßÌÏkÚ¶€%ýö™¼ñêŸÂ#‰°E8³÷M>´ÙúïºüÝœ2½:~‡©d69àºWmuHŠŽ‹.?mY@àˆ7>ÿ$'Á‚\M4pæ` bP{d˜gKGÌcã(’‰?Ç ˜|­Vú{4ÞZ ób¸ŽB7ÒCÀˆåbl¸ŒàêØêM;6¡ÂÔ#ú^n±Þ˜uì#ŸÓŠóúœ =a>¥°×´²>±íÖXŽóÐORzX$˜#ÈE‚6B8™gåBv ‡Ü(‘ÎxEùýG›ÙÌê- çÛ]G«óS?£+j¤ {±ýó/¸wka¦ˆKm¶[q  •'ˆAùè˜ó|ŒGr…üŽGú€Ýç‹Ï‚!Õ ’– tG‰Pm·'ËD@Éž’ þ¯#mÒrOžYäJíF¥ÿÃʲ¨ùQ7AR .0UmÐ, ˆ€§Ü÷°>‹§¡³‹ëÜùW«ë³Ï´¶úNß3~‡jY™Pf+à'ÀOlø '€ñ™ŸB«î¿ß«{È-;+0'¸’«™™„Ž…m– ™)2¤e‚ˆg ?{ø70û>ßÔ°Hä|?®uæZ¥ÏGãÛn…¥¦nÃ(Mó]ü\£õÝ|pnÿdš;«VÀØÄUz¶uìµZ¾º­l>°þiŽ?^Xýw,†Õ@s7T6ôœOþ?Çü¿+?ðõ{Ëî&Òˆ}8 =g`Ýïþö‹ øp¿sÌ;;™>vÄ¥vƨ„… v»8ϾþSþ„Y*T?ñ>áÞÄüù\Br‚í‚È ¨ýfâ;Ô²7-þƒ=–¯ÉEdÑ¿‹ÝËüŽkzšù]b”e³Ê—Lú”C©(k@ú…3ó×Ò­vþ+ê³ÝÄí]Ë4Ý×IWrºE ΉÞxï?zÜ‘÷_ŠJr‘Qˆùd¶Á‚:ðÓu²o1‚õš²Ë>7ØGa„uþŒEÔC¡ÕÁý¤ÖS'?—äU°>¢6]­fuÚ¡4ô"x 78ù‹Ç˜”Ê…¬PHBZ9»‹È©º3Ö#ØëöˆÜ#B=0Fç¾Øàšl#ÔÐŽB7°FÁöˆè<^›åâòŸyZYlìT3CY‹f,à jâþÐ ÓÕ’§›—IGk1:luB¤²ç4.m0¢h;uü¨`[1Pø—lšcàcgpðb Ò¥†Ñ1™(Ûˆd‰{µŠ”*&T*“DÒÆŒÓ´HzùÄ‘ÖEöYõ#Å8 ý“kÞÛêÉ“#ÅÜŸ ÑqܯÛ&no’Ç3|ºws£›=wª\^(H"údÿª?{&ýÌ™^×Åó÷C%z«Å=’£)<éé^~‹…ô½W•ã^•‹ô4s_ÛšéyBLØ[s\b™E®q‘!T F/lP!@kwr‡Dc öÈø‘$q‘Û:s S8þCj»Ê#„Èá-$ëå 6äœaà8V‹-‚MNm›çðÂ5özŸ%²­I²íš¿NÒMvg¯V£ÏŸ‰]Þ. — `êɵ´rWô‹ÉÃV½J½«ÆL^N–D3DCÙÞ­+‘`Ôd¥²¤ª³³)'6ï}õ¡ñmRÂñ€f€hd L@rn‡©EYkØ[?Ãö ðb·7­lSèÈIˆ{ÀÕ_>Áƒ=ãjO.ª$×îjúyŸõ<Ë-‘‰&àÌD²„äÀH9C@Ud‘&Mr9pídzZJ °ÁÈá™Í¹½Ú¸å+„2ºYoÌú>×η‡É`(Vá´$J¬ô¿WûNn÷YàÆ!³:µ¥—ª'Ó=t—ðxµú™âü|ðÔP’qQ$vÓò`]g˜¦F]¦c Ø-E˜x€PG☯¶p#Ô#Ò#»¡d„ôV« ˆbìâ¬]ÈŸÒˆ .+lÒ-±Œ¤U;^Íy´¾dÊ käíìY²å™ „*+{ËávÖÄèã*Ó¥ee;¬·êé¬õ€N0{]‰;ã@nŠi£rp†/u{6ߺ}]ß ¿)ûm«òbq…D=ˆ¡A2>¬žræçpÒÖHüêוdùžÅãLB&"­¼ò‡vðÞß"¬[ͼxÈ%2WÊâžtw+Ž>jå´9!$“»àòñhE‚0Gðh‘ï=óä&‘ Š#rÈ#B(Š#}Q#B4#3Íý—²j=ßÅõzg«3á±ÉÚ2ôÁçÅû|õݬ |>áq]ü)}Ãô>/OÔ“Λ¦XLàíÕ¦ùtÙÒ‚pÄÔáN j$v£RÖþM:×qË säïšš›Ù+‹›Ò!rƒÌ¥AŽ…" —ì*•K!»õ¬|šœk0‰>úÙFˆàå }Éä‚=OÖ@6MpÝiH»y(Ì“LËÚ¡Ê œÕÉÒÒ±ãÛ}47æ˜E j¼omÒÆèTc>ùm÷ÐÕà^oϸ7ÉqóGÎtòXCšyðA”d.@1„ŽÜi[qîÊî 2Œ P¨TÒõ¦4Zc(7 jìx—œ[ùs.&Å;c]sÆÍâ¼©Ú­áÆšWŽÎ—·£nÛô‚GÄ.À8ÌOÒ!£"XgÐ7Fe/¦˜Ÿs‚'è\h÷Ð ¶ù- œè Içóe‚Gvâ‹Lá‘Èá‹cvT2–ß(«‰„‡’gd’$Ó%ž¹çe2‘œcÅ®øë³¤††É¤žz¸¸Œr"»¢cWØRï,ÑsEPd ½¬ô#’ÂàøK–0”–±„rå à#⇭º†‚ÚÒú¾˜‡+×:O¾¦¹ðxþ/Çó!æJáôÕ œ˜ín‘"ì-Iö!‘ð_¯h|?gGµHÖzìVœ!ŽâFB°,ÇlmÒPáé$á}½©dePš_4¸ÉÁÛ7OGÿ çØý¾¸=ZO§L²dé3»M¡c\n™“¦ùÀ>Ü »"õváüµÉ3—9ˆâ²Yé]ïçæ‹½är=•×€KõÏ> 2SkÕ%Åê߉²æÜtç¾Þ­š«Ë¾NÒÓ1ˆ¾:¶ ŸcÞ¹‰õóß2ùÂß2±âUñß¨Ž Ü9$FÂ0FØFéÔŸ‡Ö‹—×ì}Ôðxx&3’ h3õßÐì ²ÊåOsŸÛÖm xï"Á E”ˆjé†9mÝ׎™cÅ\µŽñ¤RÚ²z†o¢gq=RòWÆÆVejA:ÞË:úôéëù}á¡1zúGÀO¤÷ðà#»a#¨Ä`Ž‚6ðÜFÂ9ˆÜG6°Ž¢7ùÂ;Äx§–â:tÐGA‚>ÂvhvaÜ;t¦Þ–{C¦HBZ×kKÚTµ»ÉºæóPÜ“ÄÛrÁµ™s&Qu«¦¶*†Ù,|S2··“#{¯Œò!gƒÌëx‚äiLÍ„ $ Ty_ÊÐã2|Ñ8‹¸ÿËGö¼Ïô÷pïñy¤ôâIb4X§ŠŒ™4™e¤%¨–É‘#üè4— ¡Ð)ÙÖÐÝÄ„_<ÝÏôê ‡ lCêa´¡År‚:‹êïWó¼|Hf™¼¢P&Ôƒ0/`ͱý6¢ÒÂÄ D ÓÉBH?27’䆑OèĽä˜G éò_Q]ù®<{qÊÒa?„Š"cûÚ,dþ„êþ%+v ø“A7ÆCÊuôé‰ûM”x´)r%¬@Êåå¦ûبÚL¸é² ëÎáÓŽµpÎÆU8°/a’¡ãÜT«™_™`ÞúP]ðªÇ¼ú|ô\}×8åôx$>WÖ\x,kø8|=ªŽQ;ì#ÓÈÝC¾©SÐ~OÓãÁQÊô~<ãwßÝŒ\F,Ê_¯çÆß(XܯB™O”†}¯Zù0/¥Ñx'BÌÚvorK˜Ýïd`âFé÷ÇL¹eI-´«ÎéÅ«ö|ñ¨MM-ß©ú'üM¡Ÿ…–aé¤ï² ûÂ?y¯§˜Ì¸ŒVÂ:ûÂ:ˆÜF„’ˆÝ8}á¢?ÆÕÔø øÉÀŒëÕØGpÄv¸G!°ŽB8ÀŠ"ˆàFÂ6¸Žb0#ðˆéÇ}`„úS!ó,šHù*­]Ñ=»ÞÚEàJ¡m(í(j¢¦6æ¶m ‹0´öŠæV­¥õìŽÐ°Õ'oa`CDˆ$$d7c=.âzýïÐíûóÅÆ“Ç Äoáš›@67G•ÔsŠþY«>H'Êø™µ–гÕHMï[vq2-µ¾†£ie±`wÙ)E®³Ëš­Ë'ÖCW¥ð‡]¿¬«•+š€©#„G‹¢±ð9[¦ØÐ6:Ð5Quý"ƒéæ~âkÛ§~QŠ]ÎòšT:ä’+hT³<òÐ11EP¤áûŽù„1ôõRTؼž(›á–[È>Ô¯v_T6qš¨­”4Z­(±{JmH&˜¶6ÆIµe™ƒmM]àëF>¤2-±yñ¯Fo’™]ë%G¢î{ÌòÔk1概l¦¯+Eû <<@?a ÉÅUŠ|óO7•æx¹ÜÃÞø8s£ÆOÞߘI A‡S=«<ûh¢ªJ¢$3°6­EF+ S¦keÚ­DCV²¶«6ݹÖó¡cFöšïæÿ°"œ‡—™”;~~´5="hºBDíÙV/&NjÓ2K•Wò l‚R [-Q° 2Ò^±%ƒ+vˆóŠqD:É 8Ô#Áðl{áÅâb`œQ;„DÃë°ãMΰ $Nº|ÈI¨mC7ê9o»ÒÅí]—[|Þroª»¯âïÏS†œ6±µ'zÅM ¿Ê@`W-ó äÊgœ—m<ˆÖ´É¢P+B€._Jk VjlåÉð`Gx8‚®ˆþZ±40qAç±ïM ˆ vIS1 /÷È€G#’8A“Zc×ãýü¾r=u¥¨*oÖ#‚ùÏò«åú½“*Â×¾€åsp<|šn’g¦¤,][QÝ ’H"j‚#"qc„Bhk¶JjˆyfÔy"ZLÀ…C"Ò"Ÿã¹~[7uvz_f–£ySyÄŒZ l„¦M1e]jkö-~>ˆññàiͨôÈ%iTyÉb¤êóõx‹íä:‚y-mÍ@z]1+gkVù…è–Ûs1ç¶Í2¶ãeÌLyªm’ ¢Gá5õ„B櫾LËÊcc!é)ÏsZGXø°Äæ–µ±‡dßëhaà ÷gUªý¥?‡“ˆeÞüÅáî6?)dtF@å~i”¹cÒ¸D޼ãÎÚãUQŠ8ª,£ûné C®¸_ƾnEÄ‘Ÿ:ñ!Â<äw‚><:'„iÃ0º‚_“ט=1OâVD‚Cùš51-Ku2*EÊ1 µæÕ´&ÚÛiN/`G€ur~œ6K@‘ˆ08×&<ê9˜,.3H@kƒˆêIÉI âæPžÕC€Ä‹2OP™ õó ?Zpq}›tVàè9yôû85òÏY!pt¯ƒ O&Vì(ë5äeLŒ¢é¶FEAØ *háÀçãËʃŽhæ¶ö•Ý¡FÛ'Œà”%Å a‹†·.j:ï@j8Õ+U1Å@jÐ EÙ‘5'™†~ç½Ùé†÷ ¡+gjI1¿£ÉåfX’"-vG„Ö'爙ôD$) ’ãÝRHJÙO^ +NßJÜjÕ -„kvRòq\Ã,ŽAë±7ç¹d”IP¶ÒÕhð†ž*ÞE|i§ÑìvNÕ*ËNø4újN³]ZÎÄ Dw×+É㣟vä§Ã,ËPSJ"€Æ¥› ¢É¥C‘ƒµ=ÔrE!’¢UýàÖ(JŒ&˜<¤¾mi‡«–ØÀ#q3ÖfK‰LXJ†ÔB1 qqÂË"áΧ\]…Šp A®‘Ñ®<4n­ßçíÕ•=s¼Ï×™Âê1tŸ$É ðCýWü~ï¾ù-ü™üø Gé¢?Œö„QEÐÓãËõ: [Sî}oî?‹³è‡ zÍ«,X¸¸–­Uš;ìÌ.«*þRA0BeÞ²j²MªÊ—¥¹ZóFJ2É·5^-¹[Únk–Ï3¶Ñþ·ËªõÝÊs´³nÙ5Þ‹ËÊô­{5¤¯ÈîWŽ×Ço'›õ,ÕÄÞòS–½v]µ:yçyÕs‘F-r®éÔtÚæk»‹sEbç4É®»­6¯·wuçºßÍÿ/çÄ|d¨Ñ€*Šå‹TÿÞ°0”~ª`NM~6EVY=>±÷{ÁG¾æ#˜„PÐŒЊ#ßÛö~±nµ¸øPßœrËYÔGA®:q™·.‡GãgX#BIÌGaFì#B5ßãíº—îú?«lâOÖÎ5–OØÿ?ØGaGpŽh"ˆÁDz„`a©=[ÅRllccËcˆÈEê¶gµõ3¶ÜÔ# ŽAFQDt‚=mØGîÿ×6›ˆõˆ¢7ÀÛÍð°KB=¢:ˆÀFÂ;èÔGF„l#«SaDQk¡;¸íÀŽ‚(¢:ÐŒÈ#a#aF„Q#l#hG¨Gép#î‚=ñˆæ#B?‚ðÈF„n#Žb7ÈG˜öþóyì¿Ùè|æD# À!!öDêðqHß7–ãL;ÈsH‘2A’6v½üˇr®òƒè“ê‹éÕÔZA>hšný^?F~Ä´…B´&cxHM)öMmysÍR8ëNéTÔˆ`=ÚWëÓaÛ"öBÖZUtë(Œ©c7ÞÜZÖÄÛm– öâc…AØÕïŸuø[ðš2Ýl^ ÄÚSKhŠ9D*5¨3* @j Ô0°RñMŒxÈ…#)›kÍ UL„!S€våñ4‰ªiR‰à{Üç×`³J‘ü•‰û{¨ +®"!´³À‚‚H( ívŠ ûïu0~{þÖ|s@ïõµÐ!±¥LŒÌÁ™ áÑ¡ë’.ù«?íÞÇRu+Ÿ-º×–®MíW£ý— )ï+«¥Ñ늗z nõÉúžÿKˆv¢ãæ²9ë,¨GK¶H5Aøå’§pŠ ý¨ªT<¨µ ƒ„©œd?™Ib1$$d“ÔŽ}7É¡ÜAÝ*™¸Ê¬ÿò€ùä©ç¨ ¨d‡$¦Ž-–£'ê7–ó ~\y Ä9`I„„&ñPNÉÆJqköòû£þÅnžÎ}‡·‡ùD&ÊYêÌfeÌ3)ŒÆK'zT€ƒý¯_ƒ®lÖ\€Y¹ï"|NZòÆ÷°2&É·½¬D8I$c;²@ãlø=¡Íœdß,E¼JÓeJC\b€Ä‘;$LÉ·²[=­Ü'¼}²!ípô›ÛMP üH¼|c å®@‡ES6ÒQ72;B¿:rúÀˆpëAŸ¬j€!T~ÑCÞ§Ö!êÙ!=~j¯V¨³’uåŠ,#'Élñ¨ æã¢í0܇+¨—}Ýܨ Ù›uSJ'ÓF*É_#Gìv–íÎ÷×ÛRð6ª¡‰sxŸé,0`?‚ƒÌIŠjèÚ²_ùÒIä½¼§#Rï”I؈Ù¨Pà Ⱥ7r®ŸcÁ?«ºò:‘[¨hÀ ‚1⣡ú4Ü‚Nª"HHždq˜ŒÚ.lŠàiçt·ñ®¯t\ÊVî™2m$e)#eKP´™ÉGçþO‘|!¨¯ 3ÒÓWÉÇÞv°Ël¬ìaèioC+Â?*ÏYž¬ú÷êuKª2AåüÌŸÝkÐtÐ ÿù~¿ØÂBL‚:H)Ó¾ §òv6KЈdFNƒíÊÓðXšŸzè§·ÝE 1Û3º&RE1clkA±±6Sh5ÔVÆÐkQ‰‘QµÒm%“±ª(ÚÅØÆ5+cE¢£&¬– ŒZ6ÅQ l QV"Z1:Á“û ™d°eÓX»}õ®Á§` ?kˆ&p¬ÙU"´ôíÛÂmÅX ùh¶&ùƒ,»,™E·ž¼[’D²rĜݻ&Å_ªæ&!d¨eùP6{Ä÷Sà7Ë[¤„×Ïôÿ9¼¾ê(5jÄ£$Ú(LTOÉÌïñ™˜‹¨ûTëæV÷Û½BÜ7ÁpìF-\›höκóÈÉ'ePoζÉZÆÂ&ÑFCªÅo žfèK®6#ÙM¡þŸ8 ³¼÷®5¦° Aü8 ¯ž Ý ¢€×é{—Å;ëËz\î-GéØÝæ{ü_Üü~o«PûoóprWًשÖûíÝÜ~²Í:ŽŸQé5œ»{îtU­SúwOãm|âSxúnjÝmæiw›7™µçã«—MMùèµî~¿c³£ÀZ¿lŸý•Üüî¶ù?k%ZåÚ|îÛZ™Ï®?ƒaìTå÷4y)¸~á7Ú¯õÿ–¯ò^Î.Ò úãXÞŸ²üÚUY¥’¨ú£ðö~Ûñœ²È‘=àd “yÓèÅ1óäø²ôšvq•¼–Õ­w£ýŠÏ3PBBj`[žµ­ÍÅ!Cÿ5©e …F¸!ÂPIpQCæ»Ô,´¼âR”¡ª¯û|£“l\ÍõÿâàêÓD4‰Eé}Éޝ‘Š~ªçÞÿÐÒ«–[ F¬ ‰s Ó:ãœÆ–DAÌûˆ×áV¤+"ƒÎt¿-ÿë—ùÀ @|=®³ºv©íÞöð«0PÖ¸¶†å…JVÄ î <0qb[O.Ö • !jr«F^áQd%PIUM‰lœ¯d÷õ^ÑÝøö;#ÚÈ4e‰u•5­55ÎI M?–¾É“{Ú…<¾|›¨¨1Lq"Ô$LN°®€éÍ;vwHT¢FF €Á€Ã6P á±É6Í@¦'OZ_ŸÎÿNæÌÔ"qy!ür#ÅâäFìºÍì‘’bp ?zN_hˆ=hí5tÀÞM» ‰’áÐߣùïn#pnì’·|÷šÝy®© £FÓ¹dŒœÃËÕEIÔwK:İÈÉ¢k’!`±$d_ˆ(Á4µDÑ­œç¥bm;ó0 Õï[ؾ÷S¡—4d8ÚÎÁhó“ ÒiüQÂe¶ƒÖ‡«>Î4±1qDó¦ªuPÚÍ›bw3Úé¶´Ë;ÑGˆ0†Ed¯YFd¢/?Fýú*Pô€Ph|¨_QÜ×ç\Âo‘骔²(ÓO,JƒYPR€ÈÅ*[Ǩ^58ÌÊ«©÷~'ÅðU°û|Í­R˜,y‹ÏZ~Õ „ ¹Ñ‘…)™Nõp†f’L–‘ù!¤ûÇ®tNGîª[u¡¾™r.;–Fk3ýÿžŽ_7µÁ’g»tð<ŽIÌø&„‚P€x òÏ“,¤ †ÃëâþªU?Ä\tðv9Îp6ß Ú©ôT0²(¿¢˜(@÷^E?©ð|^‹DrIò%“<{ü_y;ëhi.íÑ€]CI´† ¦ çð/ |d’ d˜ìn¸–½¨ä%–[L¤Ý®Y%É™™2adL’BHH(¨áz*µJB­ÜUÁl"eˆK-‚½NsÖö{D÷¦Z•5ÛbÒ—‚/|Ǩ¶ææ8“¤usò&#ÞÓ2X <•‚To«˜”°$ý2Æ™8g6O¿ÓŸs“©œ®sY»¤ ÙkãÌýiG€™[¦ÅDÎ8?É6( Œ£EbS2^ „‰r sÓP}ƒ=¶L•?›:CºÁ¦ñ¼˜ê´¶ž¬Íذä¦ÖS|0Òˆ&‘+B¤c¯±¦ó ý);p§dt€KP*TKÕ8ù~*â/ØþŒX¦µfTiF¢M&±´d­FŠ4•ˆÚ‹dÑQ‹% F­Y ¦“HÈ‚‘‘M¢É„‰)¦j%–ÈÊ‹E°µ!*Ÿ} ™’%Tm±i+jX(«DR ‰ÉãÕäp¯8¨Éæøˆƒø–<·½øã¹Šù]o¯ƒ—ÒDúêöï¼zV:ÕËq*ß¡ky¼í·y×&Iä­Í6ÕenÙ¹[Å]"ÝÚ»MyÚ²-.Ë,Û»vÉ«ÆÚë$«’ºc,¯u–—vG»LK—\ ½è³ òè>q¬-ƒ÷õÆ¥ù°l&ùЇŒˆìdJé„ öDø»!ðK ž´x¢¨€åœ‰Gb„Ã2Ø ÝòDvk¾ÎH=؆~—̬Fø>–AC“b‰}à; ?#ÑÝ„½.F¯¼ÿþ›_?ÜáÄzý.Ñ ŸX =\ïR|‘¯§ŽèB*½MQ®Ö³ê¡£ï|Û™¡MªÛEFÃjë#-V ­ËPaÕ§q@lÜ î÷úøý¼1Xn> Ž=±Ý÷å– t‚ îG.C3½fØ÷¶y/^ÖyD„‘ÚÈü¼¸d5\ÛØ?`2ÕõàélÕ×s\Á°A(†HìÉGÆè7çÈ`Ñ9êßUuëÀ»Ú±kûk[¥@nR€ÀŠ‘*œähb7o[T¹rAb° ¤(‚«¥IÎ a-â©+<ï î¯/6ô­ÍµÙµÍR~Íl§ndV“kÓoM¬™dËNÚÂæ—Jý›ÒYkä³g$ˆí€3Æкt¤¼Mlt ÞìfBñ1D\÷€ˆ7«Ô‰Š½«4ÄQd‰4°µ$ª‘ ׃‘f^±ªˆm!„ào¦aE«Ã^¦j‚ñcEutOæú¤nR ÇbÄÿ¿°ìÐeIòË,é5Š´·®5ŸÁõç»Ëlß|yVºœÿ?¯­å·©Šr„ç0E¯Ô¿±aðþ( <Á¨µÏº].!šØcبkޏ¨ƒÈ¡*¢·OGrŽòcwÏå˜W]¼º¯,*ÛJ«j†§×^Š(D»¹í虄D3PÞŽ¼ÝUZ\ƒÄ!$]µMZšãÍ -±Õ‘#UR8Aµ¶ÉŸ$¡±˜ÊîìaléÊB ™$ÂMÈBù“)+Ë%Éið×cV}’'è¹ÕénIÏ–òÕµå¶×–Q¡ì£eDˆŠÜ!ÊÚÂÁkoÆÏN0µÞå<w»éhòšœÀS”ü ôn-ÚÙ>Þ‚€$«ìõfm… êvóÞílË–\c¥’銱¥30¶I«–I—Md2®“18ôm]ô¿a¥w2IÖH‹+›LÀ¨YbÕR”ZI J±_CMO¾=V×'fd©$¨WÍq  Y0ý½ˆKG‡Và ¥ÕÀ:¢u„{åUÉåž0ë¶g°SÄ$±S£qÛPÅpdD<¼¨ê#và-€ßzÉ’ªJ.DvŒÌ]×k–7ѹkéë’’AãñTÃ*IxÊ Ïa…`¸Àž9YÃ*+ªj Q¶Å;ñ¨T;r°ËÐqE)®X”SQ Î-qê2¿é‹v`X¬‘#Pè¬l²‹UXža“QÏRHŽìͯeR(÷Û üð¨Ðuœ|BÕ8!%Õ±H8­Ýý xÀÀûžeÈ€l#aÁ_»‚€ö±xÔßz¥ÏS…ª\ÌMŸ0&1Xý†Éa<™Ì,Œ|n956ØÑ&ïî½ñ7§÷p‚Íþ „&ÒXkP÷½,:vGà ۶ˆ›X‘{¸Ñ–O_c­û[k#Ÿv³©šL…b&mêlÍÌ×IÖê¶³Œ’-·{jæKs=ÚäPh —ŠÞòÓñÄì|Þ{5ê÷¾|Ï‚w)aÃTÓÞ㈀ÚÈÇ  ™(MEÉ‘’Rñ®–/ µéWÄE‚ÍÐFaÌͺŽSŸÊG H‘1p$—›_/"-Þá¾sœã€xËMôrÓZÎ8mÓª.q¿7Õú7Úä¹R÷½Érij$-S˜P¶€(+HÙÀÇÏË6`6”kÕð ‘umÝÂç­ 78±6jµ‹þàôuMûô÷Ï€A KâàõØçõ⩜³)/·:.ûʾÜq6û³I¨LVƒBãCEîÒlýOâÙÔj$‚ò}fh9ÕU£L «òæss’«Æ01ÿáo®„Ÿ¤YE/±U-ŸÎãÙ˜Í#3—…‹V(Q<ÒHïù=ɲz¡9X4ˆ ƒ‘:b°‹¤|:*+î“tp7t}üW|cˆI¥JÎÁc Såò?*`ÈÅ„CõóÓê'‚;섇hëE±Ò·Iâ,UZZ–¥±?R£àý3^… sP˜@õ!æ¿fVYÑQqÆ;âqp’Z’þ~ž§­„õ¢©e¨Zi¹rL§µÝ{÷W©¢ÆÕÞm^¼ÔKÆ‚ ˆ™„æ$¼NæX’X©S΃½ikhVI"®Û°·TÕ2òf>k~U ë#/LÌ—+26‹AšAÝ$9­vRÍ™#õµŒsp†+ÊÊ$<4Ád¤°ØIÔB£¶ôÈÂÛ‡˜ïÜÐÌí”›·Sg½ø¯¬s —Äì –À¤¡ñ:ˆ ¸ kƒ¸ö§l$*)Ç9-ÈZ5(%©¼lGèO“«…³uƒ§†\³qr8gêK$ãXÝqÏy`Ù^Ä7"&ç îa’šAøÌk}[ˆ¥- ©å6Jñá‡Gæ„7lÈ7–A£j´‹¤ŠK(°çïK ˆ‡o{´×žï©0Å~úïÊNŸ=µ=´oQ.+X8"A€±`€\I€Aa~ qÎÕæ:¾N&cI–¥ÏØ»ÇgöCí_­]36œ»`G`”‚GCú÷è¿«ú°óç=I5FL´íA¨(a)=‘@x´¾8Ê"ï~¯kV7Ÿ³çy]QiAñ…+»§vI5{<[ÎF)N¥¼ €qÚjH²È…°†É"Ämj¯JÜÆÛrÕ]5jVÚÚcˆH7ª¢š¡(J…E,¶¡UXBA¤,Ç´¨ƒYÄ|C'™!’ HÁ“¦z*YÒ†-õbÓB«¿éN%ß毭¾[t1#!0o÷[lSÑË0¨vðA½PÖ˜Ê4zà5Ò¯ÇMêbA È2™]&”`m½ö¾_žÒþOv__3ÍÛŒhùÙNxŠö墻WUdL’Æ=ѹs¢@€¶ÈHsÇ2>AM;~ qÓ; (ê(#@$a þÅ7‡ hò@¢LaU@AÂ*…á"-ˆÛmï½½­<ÖóȉdY¦M*ìLŠ‘&’Š›05³kc3,\ÛrõÜÞkº`lÔÊîµØî×m's6‹¶F«².mVn妺l 5a´- –µ$p¨¦ÙwuÚígå;Í]méµX‰¥¢{d5#ñLÃ$GÝ…’M&”Ú¤jYµE¥³e†ƒj2”CL‘-1$È™l«eî7uÙÝ„ÜÑ«± Õ¹ZK-©¹Y&,LRä’tdN"ûJ‰¾ÓAç‰"%çÓE BEÀä1+“»¶;ÖX°´¶ÈÛ~ù±µLJ,nÔ4‡pIô–czŽè}N¿ó/ójä¬ÎmXy ìê’òò¯ãÊYC4I"ÝküçR !,Â`z€DÜ-U4WŸ[0¢ 5ð+šô²n˜EÌ– ›âÏ'wìÉnÙ{m“†{‡‘IºÓI–…°€l• ¢iȺWØl±kZÒZ¶Dÿ¦½íîØ†Ÿ›Å8‰ÿE^ƪ1 òº?•x~û»öé4ò7kÝ»ëtçña©?—–\¯¸cŠŸo"?µ‘Gµí=3ŠF{òƒjU% §jX^Éé£Q†=[Ž!´$;¸rDTb„Žnvµ!Já †«ÔIa>pA± ‰¤ïçq,k~¬Ûh6²•¢Ò&)/¸YC(G’…?Vô?e^ {Êï@÷ðÅUÖÑkFß®­¿jWh¶+b5oäUsj£lQµ£"žË¥´:žG©bÀÐ9ÎUÁyG') ‡° =¾ot²`¾Dp –hK"ùC€W‹‡ Þ®”޲ý­ ‡`ò£µÑ\2é1QàÁc¼¥P–ñÖãmLZ‹jJ 5²˜¦jŒ[kØD<œ«ÎžIÝÚíd!š«k!¯z½$8rÛZ땇v’Τ5&Ž‘$„ø®‚ÂB(²_lôº¹d#n%‘-…«, X’,]~PâzδD¶IY ™[ã0ˆÖ)¯Ÿçy«Ýãnm½5¶¼k)lÂç¿dÉ ©ÏL¨´ˆ–¢mZ¦,¸…ãT±Nɦð€Å]²0W(y0µÆˆÃi"ä^–"ma–òu²t…‡|¡Ü0™<)¼²–žªbŠÑu.YÍ 8 XL¯Yp†ÊW{ŽF€ªLÕáÈÍC5tlTÍ@b*—‚2)" %VXH%s °Ò£Ýä÷‘?‘ˆ‚!I`Ü5œA³ìÿ+o¦†k¯É(·â\óhåB› ±%› _Öä Q­/ˆ–wás‡‡‹À¬çäË#šŸ6«ya·Ä”ÝÚuâ[°gÓq7,†J¹¬ed³~›=ã,è4•ÉùfOârraßçB@¸eÃI)±XØcÜvÙm¹2FÒBÖ«R®e†Òaž `ãȦ³8¶ç§u{ÙΨ Ü‘@å4=uÐì{Ò·ÚÃSu/µÊ·Ü ŒîÁ8ÁíîPÍ ]y¶åÆÛž˜’D„÷ø$`¥Vâ)™ &1ZÔ`îBþøQQ Œª7¥%ÐÕ­u¤‰Æ“ÃÚÍ5$Dc1ƒã >PîÎ:Éùø [Ð8ÝoÅkαCÉb¦©¥¸j]kÁ'³OmU¤KvúDQïFqYÖ#ªµ&µ„ЋܯÉ^ñ#P?m£„I7—! õÊ<¢«".˜e+½ÛPØ\!$’t9ü'؋ݪÚOª©õ*A,Ø©ä´s]oÓÒ‚k‰Iõ ÉÌEªfŸKCÃTÇâZºEà¶ûÙË.””0ƒ€‘^j~?÷…}Zýžù-]{V?âéÍHFÜgmôQ«‹“÷wüÿÂûðþVçiªé÷[:T¶D …Š=)WômO=êãégÕ²—»pHHœŸ¹Dg¼ÕUWlZÈ(?¼ù[°Ë}ºº“ Í(Ûöþ¯ [.<Œ }•aÿœ—½±×W5+2¨åÓ“ §´zµ@A@xÅÀxþ¹âàrêû4æåÚz¿ïñø„^ ( °AzW’;¹itF‘´Úu$UÊ µ›qé!‡Iª¤ÇÀ*s?Ђ¡Âœ¿¹ùqlܿ正“ü #5~§ôLz‘Û&§½Ÿ!:߬µÌLg0§…¹Ñr—É—#yù[aDó2ÇÃ=;X0<ƒ¢Mz`á/yßMIFF@!$1c!Vu¶@ÁƒEê•åf€\ÓÈͽq— 4h ‰¼S÷˜… ¼µLDåÜ‘DÀTjdêÉÕDZ›J‘•U°²a.MiEo9ÞÀQf¸Jk2%–KHÓ†á,#ɬ­ÂNI<”Ñú")q1‹àbý¿¿{oI"Oë+¢_n¼òü\¹[ü9g§LrŽ:áU¶Ù#¸S­–žçÿÝ)¾ø;ëj[ ¦¬ÕC,G¹ÖI᪥zs*±˜«#G¯l¦q½Õ¥sŽ„G˜ûÖ£„ÉÓNG3cì@žd‘d ý;^ñûãf¥§5Œ³ il™‡œç­z/£m.\ZyÅ9û»šÞïê½yèň’¥Ò¼oõ¸<±RQ׳} %&ÂHFÔuÖ%ïdq€>ô–ˆà@L¢Ú_Téìµb™@£¶ôÕ!‘jï@e’­¥€j\LËŽX!ØP{µºÔHzG~E„I$I Â;ª’9¢!AîñŽ(縮b‚ƒfÒfWOÒSã¡ËÙ5š#õ©j¥f>¹M5’Šg•ôñ÷ÚYŸÙÿÍù,ôùõêN€*d?ŠfM†E@ÝN¢È`..ºüw"â¬B[:0cÜ|÷nu,?,Ø?… ñ°AKD.I"0@tYGË5gNï-£êmÞãõW›º_tšü~"vË ƒ¶š:6¤Pѳöý_ÛþæY‚!˜ié^’Íå¡$”S"Ô„„PAò.ÕK¡r00QÛoìýw—Y‘zîÆ,½úäØÍz™Ý‹øçõ§]®Rš¼íÍæë˜ÀŽl3@\3m¯ç¸zîYêêÕ˜Föò«§vŠian‰—ϯ<çtÜõårX¯ Ï+ÆeÆ’C&6WŸ.¼Y$JJBd~ —«®ŒE×]Z³ç r2O_áÿ3öÙʹ*Z9S £$f4Í.°„‰|mêývfabʈKQQÙóNzG@fß-ˆJÂõö0-k[<î<ÊOÞÏ„ùXî~Õ»7×V_|ö „š‹ £ò~~ûìˆ4á /Â*)gx@|šZÿfG›Ì°LZ%0û+´vR‘¯¨üŠp•<\Bûý4ëiZÖµLÆjæÊëüŸÛžk<V‚ŠdâYÔ$XBÊnýi–›Iùéµr6€Ö{íû^{o½r*sÌ–™AbfŒŒYpsKn*sDÔÉ„‡qÃíÅŠˆëß, ‰¬BðQ"gÍ>òðeiódz.Ëš²ÍÑé_†¦¶›Õ,¥“$ U^^W|jþ$DÚjäè˜'gïÅØ 5„Ù“ÿµ "Ò’Iþ¡*ÓA7âZÖeÓÏSE­Œ^ÖlUËÜ» ‘)…ãaV lPÕŠn4«Ã;§%~šwž¯ ww™›¡°Ä ª(µê¿œnQ±èä«— õ()k' îH’<¹óK$‰^ ‚¸P®kKãÀ®' ~Ýùc‰QaÊS•’æÂL<€¶C}n§›Ø™ß]}ïÙj=þ=|t}‹.)§Çf-i˜¸d"Q7²ØN{çõ(ýŸµënÑrkWx/hí5Æø~âÁ”™t<÷.“)BÝ ÝF¢šEƛަŽp—U®ÕtÕ4š¤BŒ\SS~ã3îDdD;rÄÔŸwfmº˜wwáцXË–+.l¶‘À¨fž¥––£*ÓäÛ¶ÕV]H&½Ó¤*+½^ÑŠ€l/ÕÏGùùÒâ2è…6½.+åz´®y›}#éµ»Kö“f2I„ßNÝŒ °5h©êcÿ•ûΩYHùãe±¤…Hû„›î¸Ä˜Á¼X÷¾yìçÂܶ®DÌr­4°H9 p 09#×!.(‚ƒøgmåS*@‰Å³Û õÖi±Ú,ÖÒ׽ؓø9ËË2q²RP$D„—%eÉR`H‹“¢m‹½.ì’¨âåùøËÂÅb¸® `Â?Še†<äÏ'_7™ey®½þCÏZ“¥—oÛbÇY‹ú{&:B0‚0˜æõîŽìëcT1½ïlè0-D˜ ¶o@ÔuqbãQû¥¡0GÔŠ…ˆAÄ6Jd*¾Ã Ÿtá;¶¯ o±y4mí6Õyy´ÚÝ'^¼º“lÊX„¢KÊŠJÖjT5&©_}m·éMm›Q£BÊTŒ# Hj‰ïK²ÚìTá¼ÄÚ!àßDÐ.í¬VFD"E„š`Ûo•~¥}í¹U÷É‘{êðs:¢ž0íÕÃê­Ìò‡—NA9ÄIpýé)¹w”€îK+…°_¨« e¹InÚîÝïÜñ›šW:ťˎœíÖ­’ݺ®-bôÖÜó6Úa2Ù™†LÙª0™õ Ñ"Ô{-å4^U×jíÒÝtgrªÔŠÆ¥•z±¦¦ëZåºg¦òýêÌð¥òâ‡üÛ qØTíóŽÍëJÊ´’iÆ5VÌŬœdi«" Â$,Jª¼Ž òìCÿoéþ§àÅùøê8¿ª½ÔñÛ_å®Þ‹]Ž4Ê´>ìăè¹Ê´¶‘@ØŸ2LåBG`wWóˆõýhþÒõþ-…I›può?šh'áÅ@à1ê,=[ˆå|ÏðÏo¢9þ“¥pÕRS%ƒ ,Jå·Öîߎì7„ŒŽ|†˜Ø×½0 N9‡¢ù<ü‚åÎJ´&zPP¥ «R€ÛWñáùÿÄ÷—ù'v§Üþ|5ìÜvï¾×‡.¼ Œ²‘ïŸ=·dë©´àŒ0‹l@€H;pŒ@ ZN®ØñiŸ:åÌ#Ñórl„j©ÊŽÔvrÊÇ2ž‹V.ÔvÌp½ìXÝ¥©áktÓÝ¿[­1®=)@l‹òa(ÕÉ|°˜X(®+È d|/_ M}„_®iSÊ•77 %öy¨}`!ö"O>OBGªpz1Òç„QAà1CÓ2Ÿ¸è’qÐ__k²pqqå¿ Ÿ£R$ñ›>÷öwjÈáv _J®0õ¸ã6Ah l¹žÛ~RžÞ;½^áój{¹†H%§]b£œ2‹ C!DÒž>ÈúÒ‚)ú…òP–L[²+Õ@"¤;õùbcI¿¶0âõ P>Ò~1Ûú±u ÈÂ#‡‡‚àgÂ2(‚X½ÈqÓÇñÖ}Û #Óz¦üݳÖûîÍÙìdó¬áû[6p ËHkaî9ÍOgqžÃ> G ú„¨"Iá—e>§·±è;•\àŸAì<¡¦¼ñ;(DyÁ÷çÖZÜ,±dWHýF‡ÍÍ~榤x Pùöðtõü¿Ô`€ê0Û®Ö6Õ;‰¾X2P®J wÍ ¶§‹–É´í’„ c‰Œ'Yæ¹æ–rP­*ÒiµVMˆi/i áWùgÆ…’|H“U-f±:å ½¾ëí}u3ɳókçÑÁàóÇ‘AùPyÓÀýoÎ`«áš(ägó¦wö(õ?Ïœ=¦¾¿ÛŽ£?ì¸N?áÏ^}kÓú”¦ Iãø_š¤b¿Ã(2‰Ä?wó‡öÃtgG!c›oÔ`é«:ßjç½oÛ«v3ê~­§õ´„FÔ°ÿra´Ø¼àŒb?£-íÀÄÒö®#ö»]öðÊ·Ñ‹ŽsmÁ‘¤à’ ×cf¼Ën° 6èëëßšÌM96Ê„úXc÷H<骑†9û§¦xÞ0±gà°¯¤˜Bª‹­¤–Õ,åbŽæ/4¶p¨a¿T²€ß,Eô-Z/ãP`“üÈa°è¶î;5v¿£¶Ù¹»ÝBj"ék´´±J´ãɹŠûXcó;o´õ~š™ò kgÚ¨°38~7×VÀLó‚êœz,®4 ³§?ÊÆø1i~ôã寸•âf¹867©+z±:ú䌄êGYÑâu½+ª ’¥R e‹fÜl·úm~hôP'×sS˜1‘„ç$,MŠì޲82Ñ0ÒDRD!$s¢G8†XSxrl æ½iÅ5ʬo²ú$‡ÉÝkR{k¼óQdã—Ž? zL9‚˜íÖmµáºn½„.C[˜‡ :Úè BŸ/Ô«qF“Ð%:÷)OO•n*è‡èØuOCÇtê-L¼¢kåÞs8ã¡@ä*‹S™d×i!(ncÄ.˜ _ Q­‰™ÐpÆCYUì‡P$ E‘d¨ÛV65E£F¢±lE4TmŠˆ±F¢£Q±Q¢£EˆØ«j(ÛŠ666Š*4VFŨ´ThØ[Fѵ*µb-lhÅŒhÆ‹)4Q¢*"*-³,mFÑX´b£j#F1i-±¢¨¬kDEb±i"ˆÚ(¢ª*dËR¬­‘h„×5o×6H&ÅHjö þÌÃ}ªI  q[yHƒ+R!-V2^/.eÑ$x.ó²åµeÔ†šL×}Ò†¹Tkn3àY@`·+w_ïwó•Ù…° Ö½óè@-aî¸ñ}kÎôŒ9Œ˜(c !é)í*'†ïq$aj^R·ÜCYhN‘š‡R–’XÛ*oŸø»œðb_“ñyïÐo£àsÖ=úÔNi×ÕÎÔY]ÃZ"ñžÊ"Y@k:ø™ƒ¬¬KTc¶;ƒ:ººq'Ú=?’8‡Iê ˆõƒ©FQP;}…í©¡ìi§$y‹ (ÆŠ…<Ë ,"`Á¯„¡KåÕ¢•)Ò6°ül0a4ÔÙÅ¢†¥lä¯dåÓ ®g)Œ™”“zt]ÂõõRÉoP9½Éšvøæd³Ã››' °Â]aª-]âfY6]muÈL%Ù’öä˜;’ÐìD28©í³{ìŠóÄ![¸Šï\ ó̶Âåž¡ÀÚ;¶Ê7ù@ì¶Ýß% ä—¥äH.y§+¥âe_"Ÿií9ñÜ®w¡ †<èö{(û5ÕÀ€æ< R,ÑЉŠ¾1̪wÂâq4¶lMDC%ˆmÐõ%ï!·‰Ûˆƒ«`§ì ¸.&¢ý)’»5e³þ ㉌8µ´$µP@;P,AÜŸÿÏïþ×ä|¸ýº&šþ')Ãø8s CiUB„• Á˜34 !”Ÿ•¦Æ¥c|0Ï?»úŸÜѳ•2²HÅ{½ì6ê àŠµnO=–¾?¬$ y¦“ðeÁ`søA‡Á~Hœ>ò®>‡ƒØAŽÈ†Ck'‚!)³¹–G™|gœd&‹ø™n‘¢ñýÈr r@:±4¾•3GƒÍò8'›Aò×;ÃÄ1tç)™{ý òzß¾Íñ8ç<0iÞñ'ÈÄy¥!Ím|=ÝÎN³5—wÇ9FÍzuµM_Qîzy¸÷ðhóÂø>´=^ç¢Wê¹ A’ƒÌ<y¤"”ÌQ²ï§.Çt»$ä6!kJ§ß*ªDªòß%„àúKŽ«IԃϩsSÎ(OYÉX(s€ "yçf}MÑÆ2C–Ú Ös}ˆx€äÐó2i úùçõKÓçÚ7ÉSB8|<à•×..éMụ°¿Ô{Uî :ÛŒí¾Õz½‹Ó†¹· ·A@zpÓûLI²¦¦Å¶JD¨”Å'ewm×}­Y¥1,-~­~ue׿ø«î.›}¼yÞ­?´æ2Ë2¤+e–-Å ºaË*÷ÂZªVÃÝmpÇ|*Í×ñ¹ÿú›õW·×]Íoþ1Ò?ør×Ô®Q@x­Ö^U|âlë,!‚²öíº–Í«Mf‰¦$pÔiú ¡?® ™·Cìm¡ œ2á+B°1¶7é;<Ìe:ƒ!@bÜ öë1Uô¸B,—Z»¨o„»Aa2;0(¨1Ý•ìME³(¹a>½Á4Iuäxƒ>..Kw»‡'^Ç[Öx§’ÏUµº™Z|“·É˜Ì¹³sgu?wUý}báùmP’6H&>‰:÷ê;Ûü‚ƒofêÒÖPD‘&s’¨k€N¼ %‚ð$C¤H¿„27ëžo·DÀÁ·ëýHÚJRFúJ®E§áoo‹9u ‡=‘Ð~:ŠDsƒ ”¢œÊŠS×êAN)F"ŽfÝU$¹õ¼ò^.íuøYºm˜¼î楡•i-–†˜Ñ™•Oê›øóŸ{Ϧ­R×[–ѳŒ1¬$×s|Ó,G±ÝM_6W<,eŒ•i*M‰@…"’í3Zº€ÍòX„ç§çG4#$ï'—ØÂyîÚOqè™Dž¸ÂB5ð4–¥ìÉ¢ofÝÐvÓ‡Ï)4ÝmƒÎjÅs… n50Ñ U,!7&À˜dგ9Œ\ÍvÕolóx·³×]ÑKÆël·sšùíVíÞtÖêBm”„’&‹œöü;zo_ZìÛã®—_ý§X™5±Å~Ž2–ÒÞØ™mYaÓ’ì×.-»’o[ù_‹ãG/”ƒQ#¦$ùÎd‚WVçzñÚ_Gz6æM{ᬧ~ém±,K~k­Y»»ÍK•òöŠVĆ#Xwu•kï°½„T~–¼.Ê>5Ê ž5׈àì1Z,¨ž!@i¤ñø«zãÌ3‡a"CÌ’y6¹™¿.¨vOV'Qà‹˜ ö—@)6©°TU–¡eHÑoDX»PVÏTA’MZ˜×¡Ðdx°¡0c\ØqŒtmÛ\ÖdÅ_uOMg§áo~¤À <|¢m~²„a¥cü‡çÓ×pØëd!“Á M„M &tnËÏ[õœgæúg³äYµVA-}®w Z™A¥¨Å™Ê†XÒ9*7$\XiŸwì"spO%K„ˆƒÀ¢ ÀB<¡Ô$ÒCO¸îoáñpi[*’_‹{Iò‡Ë)* a­`&|B´ïr /ûÎ^›½J«f%3àÉ4Í6»-gÒ«"à =ªñJ„¼ 3çøƒýoêÿë}_ÅþW»? •†¶Yœ¶ø®©™'ç^J YŠš1éÔ Å&fuãBI¨a)¶‹6¢Ük–ì5®í¶ânºÖ•bP-›º 4m"ÚBJ¶U×FÑØR»#[Ù ¥4ºåKRÀ×wtÐØÍb]¦ë6iXÓ)KR–´¨åÛ¥šcEÓnÀ[(ª­ mSl¦a-Ù®ÅÝ pÍX¡ØÅ‚ÊãXÍnk³uÝŒˆÊ „qÄ›S*®ÊíbF›úïêY÷žÞdÏ·Ï™æz-0}#¥ØÍ±¶%Џ*Ñ•K¶Zæ×X£nk%Ë¿Ò)4và”¹l£q–$ Ý»b&ÑU%×i U®[ÛJÅÕ®͆S4p+šK ºêêFl¶+MwfÝ.Í‹ajÍHÛŽ[ «SdfîàÆ›µ%¶2¶šºìAÓ[)n• m­6îš:Ö+]Û ˜èì6°vܵÒÃP†¶ØeGL­»y_»ûÌ?VüŸ·´ûéðü†ÏË~Kä÷$E1@ù- %ÄŒ¥Ë*°%ø²Ã*" Z±‹”d4j1a¬H6¥©Yrk³c° (µ1¥HeZÆá-©¢ále"±b,HÁ ŠJ2Ä€$(Ã1ÁÊ ­P%…°-VÓ-L£‹m!¾Ó’ï eXrÍÝ£ÓkBUˆe¨\LĵÉH(²6V[BÂ6Á ¬HŽ$¶á. ‚ˆ‚FX0« [‹e£XFÑ1¥¨Ç[C©+h0‰Äc80Õ•RÖŒb 1ÁmDâ’…’Ó ÄÿÒé¬"¸"jØã I‰$µ¦ ˆÉ‘%Pˆ)ŠÅ˜Át–Yp‚À¤Eb´LD„‚Äc‹Š@‰‚ÎÎêfñç2Ž'Æ;˜ 0„ Œ@XDÈ„ÛrÂŽ@¦ a5Æ‘„" ‰KY²H&G"æ‘7nX‰‘ÖVÉùû-Yþ"Ô!8K(´ee"Bˆ¢Š8b‹kq‚+ô2S\©Z±ÂUmµD”•-T:mLBúÕ²R#9R± H@‘äoÿë/°ïÈC¹þTß},šËÞåçž¡îÞ_šc‰÷¢•x«ÔíKõ\ýñõ0{H£"#>ÉaKUcŽ6¤%#˜ÏƒeaXm!%ÑyåÍqsžœòL½7™qëבë‰;¢ü§žs@œœ¤`b¹¼f›ÃbÇè/§ËÑã˜Æät®ìêì—LA9e¨‘„DÄ"©È„I a >Þ:ñ½’#½Ùœ rÇNWÒÑ” gÊ¥ãó|gé3#ÐïvîýU@ò—±0/szÊ !0‘@‘IAÖåÁ ¬B‰¤eZÀ;(PDB1|“—i`ÂR*)q CØ›AŽˆ$e‰–Hh‚)@mM홹ÌWï§½ÁŒösß6Žû«Tz¨Æ¶ãÔõ_­Š]ƒèÇ”2d\÷ÎøòÅÏ{ØóÕî+¼s³j+΃Ü5‚Tn… eØ ›vj®Ý•”]°K,¤™e`â5üç"Ã÷úu’B/ôòýçh7'Éð(Ñ-'’YEVÖ÷ {XK¨ x221‘>tøÐ€HBCãŸqMŽ µ[¶·,môÛ.¯+û¿òB–Џý/H߸Òo!{$¸˜8·1?œ” 4’(®äWe‡÷+ÈIBçõþ½ðþ7á;=«"U‡¾x£ÂBÏÓ¸‡fö%ËíѲ%,Z-•b@€Ñ!fFŠ'a:$*ª|D¸i#V­«bÔZ†ˆö¬w!ß…†Áºn7ž'zÊB½x’y, H$„d€‡µâ…' ~j"ë'½Ãé {ߘS´ý hXüžÒŸ¦s QzÏnëcêÅŠ}hØç<¨ËŸn7M±·u ïìÄ#"ñI“3,¬ÌŠåî¸Yb[V%¶[³x{‰Ì8n¿;削nÐrb­õ ™û¶ey}×½ÁŒ‘-QUd´¶oUõ|þ–£êܦêyðÏ­y)ßTH¯#‘Ë>¾.¨¡×¿XTáûÞc·XH;ÙC‹–g³=§¨21ªj)”e˜Å©Æ)‚›e²A5.-ºt«B‘^šÞ¹[d4Í4X¢’6‚6„ˆ¢fÅÚ¿b]Æ “P².j$8 Hâä[PŽR~{ìþßþø’Z±D[–¶UHK‚زÀ•€°ˆaHØ‚Ò4ˆ¶ƒE¥ K#-¹*b¬¶\ ¶ËmòF5Hëef–‘ÅPÍAT²¹I`‘¥±–ZKPÄM³KŠ¥–( ¨‘©q—%l$¶‰fîÀÝaHNk.Ž)嵩ŚÜHV•ˆÚØA[h*ƒ%VRXUÈZÂ-ŠKP\Ä•Ê@´¡RÛ•ÈÄ\V#2ŽY`c›¶Rkj-KX Õ ]n›SDÈJÉ©e€TXÛ ,¥U`a1 hÙA£6Û±@ È~UµÈšJUˆ¬ +ÀÄ–4 H‚1 \‰Q†ÚJƒ¬¹X ¡€ @¥ª„aVу ‘‰š$  †+ˆâ$AÇ5ÊÜË ”ÄÁc9X‘é,6. Ä‚°D‘‰Œ¬Œ ŠŒ 1„DZ¨»AD1gà´&ÑÂ"¤\£*ŒD˜ÄÁ–Ë ’²Á²)ŒiLÒ‘s ­¿”e«‡ K"€Å‚÷mÅ Â:°ŒÄ'{Îà~åußÊjŒß?Æ1‡Î«s+ο+°·´£ÒõŒÒÈváò%-Û2MÂWPÂéˆE&Ä–c?GhäaBëôbfûv¦áÚèØèòøÃÉ‹!í¿‡^Hž†êµ¾ËqÜÇdzÇ{’ExUá- -»¶k²ÊÁB¬Õ(CHl¸iš4c+5ͰÛX³îµÓ6Ç‹,åy¤¼ºSvÝ êP…bº“s ÎF$o+ºH’P¥ãj;LàÛ.\4i44*ŒxNnÛ¥Yymäà—u,ÚpnÇ—v‹¬ÕkiÆœbÂ[m÷½ñÌüòÒÞÚÎê™bG£x‡ÎѵˆÕ_Ïéù]7rJðçô_U½Ê‰! >õÙRS, U¹&Jf9„ËfÀU"*áHÝÙëty¦é›¤wY)óÖß¹4 ãËw‘\Œ³9•-) ‘¼A>„Wƒ}€1‘pè q|¼¬FB49)FØ 5UR^)I>ñ­3v¦È”¹·IÄ(òo.yó¶óµz:7ÙöýË~åÜPáð2p‚PRk?/Îìùy;ö†~勽ÍÊÃx'é„÷KÑÒ¤(µB=:X;ÏÌó__°—k_Ê]cäD¡A…χEej6† íoþ¼ªRá&Z²FHñŠ€ÛÆÝ2ž9Õþ*SRe 2^Ÿ¥çj¹ø,=(SÌ'ØZÆ@?SÔ,öâȹE¢’)ûCe/*9>©²Ð9áöwˤÒT@Î&è ø¢¾œ 5*ŠTS™‹xèÜmPå¾ZvÉÀœ±5æ®´wæ#Cò?Çøñ¢*ì=~®ZÆúPƒ ,Êo›Å|9KvâSQãýwå¥ ½è)¯¨Òl=–e>4Ì·K3YhÈ[i[JÈoºÿÍüÝÛÒ© oÁñ᡽ò[Ðë5͘Q >mû¿.“õ„î|HVÀ¾K@T96Ê€`”Ø>éÞ{G'2Î>gü߯¼}Ñå'þ˜o„¾M¢/ƒô\¸óý8ú b€½ÙŽU·†ÉŠ»¢HI7a«\¨pû¼ú1Ó,ì=1¾ÿ[ˆL"Hˆ>³8qïÃBr¼¼\nÃ#×ý"‡.³!bÐ̪ËD™îÆÖ=müN†d@§S„ÊhbXÂÉl‰‘÷ûhÿ™k~ãÀ'Š=ú½ÿ7Ëä» w|©äÿµÿ›küâ?Îï’Ò®=Œ²æìd⪕t+ª’?ËÝÚGjMêtäcE˜De¨ŠQSˆÌnÍMp©Kdòó )˜¨šÚÔe‹pË\Œ4DÝkw¹–f”1‘0*€s)mÒBÝÚÅuªêÅéî¥Ëš¸‹ÈÑ™ŠÐ™#uH)B¨Seî ‘1¸Å8…õÏæ\úʃÂsÄ/Íô¯=FˆµEG“.âÕÉeÂRnÒ¸ŒS‘–”ŽQÕìÓŠÝ5KyUPf2bŽNDÛÒ¢)NCq˜£V¥²·—C$Œ4FN9È"Æ‚ê¤ç# Ê:¶¬Œ€ÔR¢aÆMM)ª)Ä:& I’ËÊWì-rçVˆLËŠÔ æ‰u„1P™ìY€¥B»9w"¢ð’È…¨ÝI˜JiÒ'rb1 #i“ ìNÂ!ÄF¥;›*o5À”m^ÈœÊÈáÓ0ª`ž)ƒj¥ˆ£™»l+®\¹êæÐѬÔ$Åv<ëËui(f `&cÅ i]<6p”-#Ñ]µ9‚+ê7Ûy‹&Å×™J%ÔÊsqªf*’(kdÔ)9J¢]¡Å%˜¢›ªÄ”`‰Ó¨Hj£jÌÜ1CVã_½îO‡O’çȦ}õ3ê„©HV“°\¨ËQËU2ulˆ{WbŽQXS‰… KI[Rs]—ifC›Ñ*åãHlä\9&dK)d;ÎÀt+ ­7hÝÅ:QwÖòÈ‘¬ª¼Ç›¶,³3focLK‘¢w'Äe]Jt]:‡˜´èY\Ôîàæغ£›-ŒÙ›`Ö—¹ITCiA— Td9[SÝàYy‹)à:S›ÁoYK½ÉšÛ1Žòö®$ÍmÅlf‘—›¯SðpÚpì8æ8¤À©ŒðÓD ’…o?žý}ý>¿'ë’.ŸÕƒÞT…4êjí^ªØ×;kNµ—ˆf‡rè;¯wg*¤£PC›SY6uß(ÆÞc©ÈÌFʉœ¥-Æ] (ÈÖ†¸2ª-l4Eæ&„Ëlê\D:k V™Õ:MHÞmœÍÂ(ûH˜Ê š›˜p2»»Ù²î ÖêèÆTß HÈ 2TKsiÄéË…„㢦ƒY“ífvÉ}¾ –¾Îßó\³]ÝåÜLÜÚƒfzÛe›…×P©½¼‹ÌÈ»rdú̧‘|¶h:”̈ȒéW¯£íÚôPõ|ÙnPš¯ÖyuWytæT%i@‘”w…¥—êëf"ÚÛƒ¨Îܬ˹*µš²¢÷"ªŽCÅH@Ó¼ÞA¸ƒ‘X§rtJ%`RHѬía7eãÉõ¥÷ã]÷~Y÷˜¹÷9Pqä ÛPs!´rm¹˜æÛ r–UzR¨xà6h\"2DC>®"º•n2ÇÃ7.×”÷ÕÙž^ 1ëH°\ÄNò‹©ÉFr¼Ó»mºµidzmïmnªú{pì;AžræÏ¶ƒ„ÆÏÀïvi˜†Oœ„þüSûɰïó·ÓWuðíµ^>öøÓ}É7½+–+g+Ý;jÖñøíF“÷«)Ia"ÂEª©ÿÛ1åQsä–dÐѲrÇâ0p:`ÄÕ„“%Aÿ‹Ct¸aSÅäO Tò+¤½_Îýÿá˜üRò ùÑ²Šˆ­oKÌS”\^ÅÝEEíìÅŒ¡—slˆ‘I"ÎÃZ™rî¥á[$ÞÔ»ªÛƒfö-=¡„’¤[­Q´îÒ)5‘:·‘sjÖé½U·–˜4ÎlÖ s"bâ"±-¨Ó¬8–g\êÚâTJ½ ÅÂdìíXœâSdèÚ†ç"͉C†# £k4™—· ìm­ýÁïú3úßà¤ÿ(èúúzGè>yÕÞ$+f¿©>ߟJpÙŒ7ô?]¨¾<Ú¼q92(;»y.ݧ.ÝJÂ`ÞÑ á¢mãµ2ÂÅ,b:UZOjª[¨3CmIª ¤+‚KÉÊ)¸4AZ¦Qe;;7u'/))IÕæÞÉZÖÞÍÝ1™ \œ\ˆ°«\؆J©u‘,ËÐݺ„f²i‡wpÅâºu|ÊvY³±1¦žX\ƒ1¨A£záƒf …¸/MâœBbg ÝÀÉS"¶¥LÌáå#ŠÍ=È1Iî8CO`½K¹ÛÐbjcá–ÉSDXÁ»Q*±ÛÖI¨½-ìÉ AÓ³ ^×*¥ì¹S•(ÃBæ`í€Y†“¸uô–3hfl®¼íI©8¢bhnÝ:Ü3ɪPœŒ¨Qf^G±Q4dÄ —@dxðƒ’J¡×åX(H€EÅúxØÇž½ »ø¹0ð{VuÈXÞ¶ÆW=]+WÚr_x»âRäüËâxî÷—O“?]Ž!†MÊôzpÅC3„‹08A<à±|!âɰ^$èÏ8ã|8h†Ôà¡’ ˜•))fTÊ‚Gd*&8¼•CrÆVØX)…QÿŒa?wófzsÌwl¦Ö¶úîýæóîô{œðãÞ‘ï_áaEð¦5W…¤Å¬eŒ !DwÑ«t¬«‹$Æþ×…^g'~o_¾@5ö«Yb$¹5Ù³…ÙðF¬ÑâµìaóÈÆ›¶i‘ÖU:9…Uk¿7ÂÄÀŒ/EðÁ êL‰Úªê5ÐL³ßªÚ÷âÛ”vgªÆ[ìük媅Lmkq)}T$øï¿~E“CfÌcÍ,U¹ŸªÖô{]^wZÖGFÓ`–Ü’€Üþý@yƒL“qB#Þ¹Äêð€J™ƒûµpKŠ”< M:ÜÄùðd@X¬„i+ÔV³")¦±Õ„jI´qPØ>Tøê-‚ªXõ(Õ˚宕¹±WUücr1Îp”@àþÁûO8—í‡N?mU)¯Õûm Ê쪪žÉQ•B¶UÕ!q5ص*B¦â; ,'…¡Î¥ÀHç$ðp&ëÇÝš˜ŠÓ¸ƒÝˆÑONÒ9CµwW™U²_q.ÄÞ•g·˜H‰ºYî!¹·"‰5UV =çMÏaÌo|-–%±Ò«3<ø]5Á„[E‘ ÈT qq£Q]P¼D¼ + &Z²wd§ädŸ6ñî N£`æ£]X{¨ÖÍué¾úã9^œg^$Z%¨ZZ´¨ëYh7+É«š»oŸvצøZøW¢8 ç8MEe)I^IB;Û±´‡_r˳¥½o²0ö°\ïFØÍÒ Ïçû¿ŸG8çï—¯÷*Í}~?>@Lj€?1ÏñOÎDU1\E‘¿%-à ׆%¢¶Â„´S:¥‘ bô¦Y9ÑçÆIh6§›m·óz¶×ê÷ðÕk«ˆ¼s ºWøfGTÄGHcv¤Ü× Š¾½”·0ÆT•ØäW8œ ƒEÖßf4Go¹Ó²¤LäAíîRO½ìÁ1[§œO84ðG<áh˜¶¬E­{¯¨T÷"*o fÕ RŒöúþ¦3·½ïFLÅDEyŠ6upžGÏ®t09Ë î¹×’r*Á§~ZwŒB¥Yå·…mu+îK£ÊÐ*q¾öÞ°¡ͤÚS‡ºs{yWl„ç\Œ‘)v2;QsÓt‡Bv¯(­2öBT<9½!³–£¶a@Š,öîæÞwòa|hý#Gðóœm£.¾o³^5ó[”Z/f¸y½™UEùlmˌƕKÃXœEÌŠAȽ­""“cÔ Þ¬µTѵÙâ*w¦2ÝÓ‘$N÷ V”NCàÒ4!­¨3ÀO9ÄxHÜ@È'…¡N.»ÕS´îvøÏQíå š›¨«O%AêÜ´¶“Èy»{³ßvO&`@Ì΄I$LÌLft08¥C®qm ¯…òʲÆÙ˜Âª_V{]ŠXT®l)è½ZæFnÅ+Q]Ñ—ß·8ÜÈ*Þ¢ðâÏÚ¶Ók<«[p˜ ƒÑÕHFÆ«E/”RaTQ@€h'Òýo†÷ÕŸ$±ØÖ">Ì(š¶zú²(·•ŽXÍyö­%‚K`9e‹kCÁ(…C¶×¬ÝnÒ¹Ë/ˆg)+, #• FÛ 5£-«OE!úV½æÄûÿ~γXäâî> œ™$3aã7+Km¥Œ11„#)E!)V¬ZÆËmD¢[T–ÂÕ[ˆ#$¬¶ l(ÙX±qûË7ñ?°Ìøo¯Lõ»÷ž¹ó€! ®DX*{T¢Ü¥a„à²)º\ ìþ1ç“©‘9ÝÚ‚ÞþkÇ.¿î÷]ñ˜„#˜‘q$NФ "1LnåÝË’ —´óo3'ÖSºé*î»Îê 1Iç\ž94DÜí ܹ3E)DBdML ¼t°Ó®guȹ×w÷ë€îÿƒÛÍ/g›BáuÂLKλh„Qá'‰ ² ¡Gù§—?À{QE.ÈÉšòZ-yiP¼í1Û…çWš¢âã̇rê{‘dé²¼—8èÏg,P=J;ç;±løQ,ºtV«­»~MJT3|/„’IH<$BXöíÙ¼úöñMçk‰‰ôp¼îKˆà @I„׿[ç¯]Ï<]Üê‚î')¾¯ãŸ£_¦}¿ÖÀEEXŒÅŒ1϶T1"±bÄbF(wwIÜî»Ñ0Q]ÇIÂGB¹n$Š8˜©„@Л¥ÜÝŽu×;pË™4‡w.å\ýß±I§9WÐg;’W+Ç‚dI2¼î Ó—r’†/MÉráLØ‚LÞLF»®’ $‘‘_°ÞyÑ#°!>Ë4”•BÀO¸©ðH)“xo÷œoïÇð_kNyæ÷¹“äùl1]ƒß1ña¥½k¯³q1Ù9{]O w7¸øó¦Ž’’b,PÂ6Ú¬ ¸ƒVcà HI ÝÚ[Ûš+;"º¼Ç²ç(dæF`K%©êÞÍ8ÆÅ8ØVüoMuW‘ƒ½¦Ì@ïJÊP&£Éµ²r´Gbö'`#¾7á]vªÔÂñ¡»çÜo®¤‰$ŽÎ HISÎÝ /<òòF4¦dLÆÈG;víÝ®¼sHcI7eyÝ¢L]]|—L1žn»b=wDó»œ G.Æ ‘Aœæ]×1\I\$y “”ÆÈ™(áí¸”îzë¸íœ¬õ‘×]•267ÏKFó+²p7nS aÀÁ˜ÀTvîwq'n9wRNäFÂ"AQF\ŽÇn;º.dîâ ÝÓ»”ƒ–ÚD©*¬p€ƒ#‚N]tDLMa3#Do—à5ÝØ‹]×RZL$L”Ñ@ ^uÙ4§™ŒRˆR5ÊP €Œ!‚\®|û\!$†0»tI½7'¿äf]óósÄîäË„C7¢‘¯´ýyqë=D—à8¼¹™¨¨ ißZL‘BˆóÎÛòÜ8žÖ÷ÐõÎÿ“úÞ¿Òÿ¬ÿb²^}‡3ÁìGººr„ wžµ"›| P©¤ª m/:ÂþËèAw#´Cι”âü{È¿4P À‘P*÷欞‘‘—¸©GÃn¶h$Zûͨ&ÍÌÏ( <(1ËžÓImÀëú[ýF¾«}oÜ ѱÒûª°å‰@@ÔMtvŒ Œ”tî"—+ÅÀx¿Ÿã‘¦¤D„­{èùp]ŒnâJ¿<,è¯b‘[P"Ù$Lʰ };Úxg@;ðí•€F!j´›‹a¸&KTÒ„؆í1ϳL›ˆå h¦•®,¾Ø7¡Ë³5v™âàÛ`ŒimV7Ïu¾¯iyW‡ˆàsÃÍc½õÝ58ž—Õ6±‰¶Öyßây©÷´‘w?·A+ì½,~ªùEÂÅqs»lý¶ŽÍIý]gÝLr;›µ0‘¾ú|Ÿ÷·³Æ½× |_¿eðï3z|ŽowÓ×e>OSi¹X<4¾²rÅo¿3fÎxÏOùºç<º&Ôç:‡ÏÆúd@‡¡[òö¾‡SŒ2ûÖ_½“àaz>çɈs}]‹¥êÏðNÛ+¹Íܰ¶Ìöc Ï?/ª›‰¡åq»]\Ü«šºc×øõö¼¯ý‰Øûo»OØÿ"L}7=þ7ϸÞ.ž1ÃßÎç$`ãøÿÍ^ñ-Ä>{ǼÑøñ¿Úðíuoõh5n¨Ú\TW–ŽMJtu5Xi¯ƒgkÍ}õ¥wó[»æù0qP§Gõ‰å©è8ö$0ÊÑlÔøòùùKÿÝû{¬mžËÛév§ô¼è;®ÖfRzß5þ7 ¯ü£ì¸µòeÞc@"~WÆ£¾Êã>½%ƒ+á`|ŒWÞÙ¾å|~?SÕ®ÚïlÆo×þ)m%¸Ìß¾‹¶9àCö¾æ>LoÏó²ÝÐQé½w´Û¬ÆŸ‰ëÞ:º¤qdg•›ìü£´t ½o™àîí®¶ëx=ÝìzšNü,,ÎïìÌ;øýNFÇEÙö¸Û †âbÛ5ÅÄþ±Y«¦íÆÒ·Õ{nî¶¢ŸÕú6ïÿÏïÏ—u³â¹¾Jq;|üv/η`TìİUÒÒa¬m*ŸDÎêk܃s¼o¢zÒº{ï“,àL5êþôrîé?Éè¿_(¶€û¾›ÞÒ†ÇòcìA~³THây—¦ýÓä©äÛ]ÉïU˜£¼è£¼Vâ¾ú®"~ž¼Ôã=Ë3G’ŽŸË‚†¥>·þô鬴4]ê÷SYêÝ&}:v†O/ÚŒ¢}uñi}ëoyÒ²¶-F“%+¢ëñ¯T¸z˜;ÞJ:ÝǨ¤ðû‘»M}•K‡`¤æöõ0rŽwÁ^8ôªÖý˜ëƒe¼{œ¤ê¡Þy14±Òùk”’ݽ¥ß±ÿÀŽß7y› : ³~ºœû¯DyÖˆ.¹ôh;Ç /^Õæî󲿌¬X…ãÙÚëÉ-£øöèiµ×ŸØ¸Jq™i~ ©ˆ¡çãås¿œ¨æpëÓn÷÷€AlôTíÑÞc]9ÖùÛ_¾×_ó¼b#áZïqßfŸvËzäÜ= O†²N>¼û£müëÙøÜ•·#ª©÷ß׬ö »ùî?K?Äæý09Öü5'ù×'¢µr?î«·#øî;ò¸?ºf›£ÇAª¦ÑÞ¥C?æ?óÃ@­ÑâÛÙ£îï=Τ„¶Ög±vØPà¸ÿ¿í#ªèÒüÁügìš² ÍÚÿŠ™Çí/úyl‚ß[o9ôq¼?ªóŸøú>.Æ[¯bü*+)½÷…µäú¸¯Ùr"«5áðÔkVu.Þ Ÿ wWšô öÓO¯­ì\ø¿¿Úû¥‰óýý퟇lù˜ø>ŠÓ}h BÿÌïö»vL¦35™ýv9^Ä?ŽåŽ•ŽÐ]µУl6-sW a`:ß[ne‚ͧ¾ì×µ§.7t“VÉÐLÃ×yW¨¿K·¢Š¦‹{¸Ëx8GGöÌÎð-±«ò³t½»Ù‹£­öåAQ)W7°Û½¼Z°¢_Ó¨m­msú¨û¼:¨¾]ÄÃ7Wc"ÃÍ$ /¾¦á¾ÛØ«¯ÿK‹ŠæÏÈÚw[ ?QO&GO²©­;m°@¾+#¢Í×=š™¯ÕŒ‹¿ßÇÔúžM«'Þ´®=Ùz¤ÝimYçØ}–oEýnÖ‘íóëÔüÊ~³úÔ­íô†Döè·WwËâü-}ñ^JŸÏõý«ìâqù‡É÷ü×ÂSquV骶f¿º/Ž/GS3ýþ1ØßñýËæ|÷,^Ïr÷ÿbi»TÒ0¹WoãêÙ{¬Ý,sÏ-œÜ:ýŸJ¢¸Ã»Æßלºd=TY®÷c# Kd®¦Ùïm¾'Eu“ãîÞ»þO y—ÇDÓòß'‰i£6H£+Øçz¹GD@ƒ^Ö_Æïkpü),ø9|Cº +§?ãÞúxùHÌÇÁ–÷³÷ìõÿuæsíönN+ý[F™Ç#þ¿‘¹ÎÝçÙÃWóX,%+ÂíËÝq{lÆÝ%o‘¾Gôµÿœ¼“ÿ'éŽÙ+®Ÿ·¢2VÙ¥Zu`Ï¢G)9nÿµÐvlÇãçú_fש˜§öçår”Ó:k7™»Íß¿^v—…eüˆuÚmmú¿ž´ºü(âœÊÙvÞýA^¥ëŽ2ž¶JÍ|µï°®ø|cõ¬Ûø8›]Î6çÒ±cn÷×_+íÚ»äy'2PÜ­÷n×Ю3*n¿½UúF‚Ì»Ëâ±îÑç¯Ð´Xð\ï+ÎáP<ÆáZ{eÁàëú{-Št_·ŠCÇÊì::ú9Û¯³äE5†©…;3W¤WZJÉSÁº¹èõ¼Þ¦afÀx´œ¹ E¢[{9oÝðrÞïñסYþ¶´ëÚ¿r2ôÌ}.õìïàöaøü9æ}m]â+9í¬”þ—IÈ_÷mÉ~Gôq–7cþLÅØ¼€@‚ýËDלãúg5>FÂÖã(¢¿.›ÕÇg¸mÚ¤‹Þì tÈ€é®k`ß±k+ïŠoÉ‘sžÎGåç[@þÿ«µ¯™¬q²õð5Càô+/½)‹=XB¹]ƒ¹´énø¬ç3ƒ¥· ›×Ík®×¾½v2¹Œ¹w¹Ž,Yý®‹Îªé8\·Ù{Ù0=Ç—Èûôk7÷ÊäiùÖ!îáN?Ÿ÷+^íèõT>T U§¤çÏPDœÌu_°òã)!iЩäœÈã&+¹ûï Š¾¶ÙO5êvz‹wbå~™'ð®Ï´2ž.~0î‚Øßqí %ÓÀå赜•º}>vÞ/P#0>µš ùJeÌé{©÷ͯÛoj¬u”éón[Já}JFâ9ü\e»#ª‘ÓÙ˜­iõÑ[ͼKm¢ýŒ™þÛ;bú4µ±Ö{äÏ¢æx-9¬ïêÜã©rîz˜&¹¾ônË5vÚg\/[—¥jëy®ÕÝ! ~•M V"ê×çëß?„; "¼™…g¬¶WßÍqtë·¹o‹Áïܽõ)0ö<¯×~Ñ{SÎ]«•}´Œ‹qA ©è{ y^nèt­߯ƒ¯ï°:o"³ÓôkqÖëæá™Íogí{::×?¨ÐC®Ã½z79.´-«ÍzŸú‚¿mıÊ{!Q/ R“4š{TÇäžç½ÅÈñ?¼ßýè·|Ü-x_üõo=”:û0þfr6×üGû wlÓî­Ï©û?‡Nw]Öƒã¯b²_­ÆÖ¥úÿ Ñ®þWkÞ¾‹ÔÙàdäQÐnn·žõ»iÕ¾v»5›ÍÌø¯xœÌ5ã}>èZ–OÞ¯IudãYéf¬·­ýŠ{c¯è1=“,ÙzçN½#ˆìUêì^=ÃÅ÷Ní1´¯-¿ÅçWüÏùßMvÿ›l´ ^GæËqüÝž¿^ñ§míÜÑ1Çó1DGjáÜ=¿OYÕS¹‚þáHl¥rÞ-úèþù¬£ÄD[>}Ÿ>›,§r¿ùì»=L¬…êñ7›òðqŸ“ùçÒ˜W«ÄÖl‘"˜ïŸ4Á€[æz®²kíÏ¿œž"×>†MWܘ}ú™J&e•zR…ŸfËEQ‚©_ý¡ÒâïU3¾Óý~'Zšï1ÓÙ½n?Xç»ÍßjG™1Úà%µºÁ=¡ª…!–ÕÓ¾ÜéØÄ[Uðz?Ôm]^]AëÜ8•ŸsßJŸu““c;´ïü˜,ç_U_º¿Ïß.°;ƒõ¨®Ö­þÂt*z²¶è‘øÃ'èïâÛi"l{±ÃÙîZ–ýzæÁëˆöwLVº8XÝþ³ùù½9QÓ—äÅ~_¸ô_gî·~ó©üþóX~‡‘sÙSÏUi´¿æ;ñ½Ô¹Ëî/´_³ª>«ÛA½ê\z^¯µA™ÎSMÛôõ>v;gCÏü0ø]—ëÎMÕHo~½GÑgÐyò¼ 'ɃzÏ‘%I€ƒ#½‘ÍFý?‚é×™*#«†/óö<3öŸCÉý”œâr¿\_{O÷t>¥z»¦·R|»)Y+5kÜñþf^ÛlÎé~©ÝÃÆ÷)ÖÍ@Õá6\ˆ?žŽËGðYyÚæuªË{eÎ…Ô’^£ ÅÅîü7fn7+²¢@Ié~Þçõ«ý÷×Rvn—©ÜH{U6Û<ÎûÒã¾·y·Ùíï§û¸ nm»½e‰ò•U!wù:N˜‡aÔçþ¬:¼–7¿ÅšïYœÄRØ»š1HÏÇaòïxP}ªÄwï<>-í]퟽ïßñÿÌ¥W_Û•qO—Çæ:ßöá¥ÔL.žõçÖº;)¶/—<˜°C1^ ´àþ[ ÕÆ»Ëé\}¢øÿ‚7aG´ƒoÜBÜd$nX˧«ÇNöö¿ªÇ¿nÜ·®ÔgŽËYôñÕ¾_èò®q23Ôºç¥bžú{½º<®.½ëIã¾E~/­íß9Îñ×­äé½M¾DÞ¯ïãdTŸô¾Äòq žËL¾–mOó#9…ÛsøyZMþKðÓÝézs´wOû÷¤2x{¤Ëj~Ü\çYîÕ6¯`l^¥“„6Ù›¾R ×ðÝOæäé¾·:;Ä——9hÀí§¥©<·º™çQ²³ÏβíþÕJÌÉî O¼÷wš]õi÷ÙyÞî$¨?õáEm/Çß;­{;¬c7 .S+šû´Î°žÚÝ,ÅT–Ýx¾uW³…¸¿üýLýïg™”ÿÇ¥yëBû”¡®üº¶ãÛêRøhêy VGí¶] jõº'7¯‹7ÑÄôvw¬þ˜üJÒ|-Tå®åðIì¦<_ݿذC½F÷SrÕãëÜ™ ÷µç÷5[éÈ»êZ”ù´HZßéab•™ƒ¡‹|¥w—?!rco¶ûù EzõøD5Pc»·=]³Ù¾wYµò=å¯ÿ%¢é#={Qg¶ôh%r²nìÙ®vŸCQ§…¼Î}ؽ¹ú™š¾Ò¿̶.MÆ—E³‘×ýÒ6"¶|¾F×wgåu^HËÆòñr›jüÖk\{ w½ê÷ƒÏ¼á¯:ç%®¶önýVç´~ì 䮹²Ý{’R~Wœ®£`ŠönѦøØwj“¥ú}ŸÇ-+ÕÇb?óÒyžö£ÊŸèaæøþÛLå×óÝÆX=¿–ã±Ü û-2ßm 6ój.ÞOØ÷üù÷é¹nz²ú{n+ jÜí²è•Ãü#ŒÞ:L´¿&ÏÕ^bÓ±N|˜ã{—»<ô3è—õâV27@kϵÚ¹ ËÙºæè4¸÷Y‰æÿ›•ÒK6 ¼½®iDòîyºš‚ÃCmåR+ºÒgýÌ]Sʽæ¹ñë7ýÿÚÁ‚¸l¾ ÷ î§[­?üÞ¼ïJ'¿FßYCjÜæo¼Ë¯Ý·ü-=/+ü¶ôìÝ×b ßûéÚæ-˜ßo§à£Ù~õÏ†Ž¯ëQ{º›[_É·®KknUêFçEjsGrÁÝýL-†Ù¿úzïúúîö Ÿ~ë}OéeyÚ¼’kæÛ}ùýÛÆém¿ O^YÓŠãð¾l›e»»n¿ÁçÞ]@òl%+´Ãÿu²]¦<Á]wgÍÐòýK ×{Ûk5^á|º) ogÃ9Ò“u[†ïK€D'z¼[žZÃS¬È){¸þ‘,²=šÔ\óSº¸žVº1¯Óm•O—ÿL[ÿi;¾Z%+Ñ_Oµn¼HÊó}‹ÖK@¼Üo?óT£¾Þ×y?ű¶ŒeýßÇÕ×}:×[›-®ÕÕ8ÐÞxOsv龪œ^ny¼£6¦³ Œß­}«{pí¾°sw»SÒ’Œíögåñ‡PÏØ­Ê~ý>vnÉ¥µPþ’ºÍºšíâ­5{ÓgÎû”wáK_žy?þsnv»ÿÅÏÈyùOdÿtm1ú¾¥ÚŸ=5þ¹˜±U+§×ÕÉ ê9ùõÂù »o"£ÜÇJ}Y ·GS³}ð}«Ìæ*ëe–õ.êÍv:ýÁçØºßÔ^Þ²Í)ôÛã1ÖÓw¯4!¬gù¿p¬ý«õgÞóŸ²÷!îºøC{æÈÐÓGÔy²’­o=Љðþ“Y]‡ÒuöE¾w¤®ÿ^m÷·„sǯܽ«–BóýÔi!ð+ó¼* -^üã{q_íóëéwG«wÞös_W;_<ã»ß^̶éúú WŠÐôb[oýʬ4Ë‹eD L¥´sîÜ[®þ7Óí"’=ÿ‘i‡ý`<¬í=µ²\r^oçÎèüþ~¢ý”òóZ/GæL8ô]¾„2Ž·"(çߺ3*&¿¿g™vØñmœ×…ûä'hï¾z×ÇiçÊð™lž^ë¦ÌÛñˆˆý¯_þj¥¦f}%z‡Ê¬»è}Ž&'›©ù¹›èW#uuøs[¶&ĩ쾜TÄ9Ÿ{GÖÇ9‡5¾ Q+ìe&QaâbyžÜ·KÌ÷‡ðúIÎ+îßû¿–ÙÚ=Í<§cæáLìjç~Nd”ÿ:™yzü½ãÕݱ`½î½ø¿^óŽc½ÌÏoœjk:ÖYÿ{ÿ´¦Ow+ÏûŠûOõ,ÁTClËüÅd™Mg1ñþt×·ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ†a8<˵>Œ0= ¯½»›çí³[Cf^{ƒªëMæ]‚¨h|1Ñ}´[M>£“Ië¦÷´éAfyÌÛ* ÓT•T:P({XÛ¸ pJÙ…"‚ D(Ñß΄”6 ÕÛ邸Än>·Aôà÷¦øû`Ù”AÞÆ´kW<ì/_r… †Åa»³ÛšYÜõezönÐM°ú}쯼>¾¡Ê{ÖÆ}U@Þ }çÄ÷¾ðEï´nxíÎïžöÆî¾Ýp¼v½Øôx"lÞkkmÛ«‡Ý½yñ<5VÃÝ¢©’šiáo»©òÞΧ§E{§Ó¼^£Ýöץן}¾Âõe©Šµ©®ô÷·›>Üæ÷Ý£··%E¯=ã··ÞÖ»»˜ù÷¬/mžëâ>À ñëŽûÞºôr×V]@ ¤Ú.|õBTìA˜èîb½Dôy!RERèÄÑ@JZÃ_Èz5ÐpÌÛ;¬Ð N<ÝÐ( ë)P4€  B{¹à™AÓ¢’UCÝ÷•Ò;Æš‚ïc¬éõKƒìð=¥ëÐt›FuÛ-{»£wtíYXP·wvû aÛ€¤í›eõÑr]ïyè|÷fofª#E÷¾+ì´›I÷tå«MƒaÝ÷—{ŽwIȪz{KÂü-ÞÔ·ojín÷i}`ÓÑßvº¾š§Q4¶uŸoIÄÚÛS­zÏTnÆGSPe¬¾z¹ê{z: ï`åzÕäøÞ‡¹žQË̆Ƕp’=½Í¾ûªóVÖÍ´›m¾æ€¾áÑ}Q¤Ô¶”hP(µõß{¾›ØÐVZµm«Ý&鶤SëÕ;ì>êÚ‚ÖÖ_f¶ëÏf³i–´­Wmi…³ß{”ßKV³[cݶë¦ÇݯXU“m©Œª×ßo0}cY×9ó½ƒÃÛº” ±Î:›eŒ"Ûé»5µf•UÐb»Þð{ÚíËÏ«m!ÎvûçÒ§o4îÝÚÞ§Íß|ç¤m€‰&À &˜ £#dÁÓdɦšžFM4ddÄÑ“L# щ¦š4dšd ”&€É LL4ô h&šf‚z%?A£TöŒš§š&Ðô$ýSÊy&5?SÒ›)è›MOjž‘²)ê4õ6‘µ<¦ƒÔÚš =Ôô Ú@Jh ©ˆÉ0‰‚iŸ£)´É¦…=ˆÒžÓTd š¦ÔÍ4CFž§¤Èõ=@dz€4 ¨24§¨h@D “I  €¤=L “M‘ªiíQíSÒ~‰éOÉ©=O4jž‘š)êbf¦õMÓOÉOSOHÓÔÚ#õC Q Ô4Ô=  @¨D‘€Ó hÂ`LjxL‰€h4ÄdÓCL@hÓhi=OSÑêi“ChC ¦š OI“MSØ™š§ TQCSKœ›žŽ£Žw.ÙäÄlO¸ÔÖè¡x^-ÉljSÒ~úOçýßé~Ïÿ¿[ßî$ ¼kK¢¨ªÖã%qÂËô_å$ÿCRP5n¶1me­?ƒ Hfeeþ3)zZ‚š¶i±JÛJ‰KJ#Ì F䊶ÕV"µб”Qb,VEQ’ ²)"ÆIöÿ¹Ü~ÏÞ™?ì {¹!˜A‡²ÞÜð{ì|îY—ÑKAHÀ’C%WüþWžxy›)´øb\¨eÁ2»TÛ+錙ˆèx™Žzì;»vá éuL{Ø$L è1 ¤Ì˜àF/ê9þHß"L XU§Ú4[4Ÿ…ñç£âë^O½°yÿέê*‹ï ø½ßšä}7³ùþó[­ö¿ÁåÿoÔý&Á·C’š-L*º( ÚÔTP©ŒÄ*1†@’‹L¦f`UEÄ+-¸¸fRÙˆe¥Ì¹Yf6«YTq!Œ&3©˜Z‚ÅP+ ©"0$„—(LZÅ1aO±Vû}kðAUš£î`å‰èàoäÀñ¡÷¯±úTì§Íd~ºÁö6#á²¢¢'Ï_µ‰µ÷\ê?R}ô;yþ^]'ÂüšûaŸqøt‚ý¼OöCcÚV0ùû?Ïo®ŸÏüêx¤!Ö‡"}T?!31ø¿Sòš/ÝýTýƒY-Q‘‘*±ÕÊ.­Ô8ó‚Ì&"ç.¢–±Rº‡¸£19—•UxôæEÖMTÜe'ª·OSsrð¢pš—ˆ§€ªxw{¹kººÊ*•øéÀþ8˜õ¯É_Ý þ^ÑÉŸÓÿÎy©ˆ_ìáÙÀôQܘHÃõ¿B¬¤? ”à¨)ÁPS€ ¦[p8;÷&%ðp•s µÝ×pnåc©Z%m–- Źq¦ðÖ|§N›jŠ®Ø·tää£v][¬Õ5p·7šÑ£)—¹¬.jÔÝÌ®™†5€Šª³ÝrG¸y‡Šl³ ·š*ñIs‚K|Y32Œ‹»XB˜z…-弿°ŒQ/H•y7u—3j.&.GÁó2­BwrLEƒÃÊ/*Œfc·_›¡®Ò°PRß·jÿ·—VÁJ„¯¼í“åÇÇ•þzôíû_‚ Ñr:ŸÁú ø¿ñ]„~/_Iîþ/°Ò ù¸ÍNÇÐØANLnC§óUÆÿš§®žï+OëÿrÖ`€À?¹ O‹JŠ{«þWgüôCû´|ëæb ½'çÿŸ¶¹‚"“Á”Hñ%'q(U_ѯÊû Eø‘7 äí9VOêãs4_ØúNó›u?z ìmÎàýä˜r0Xûd?ÈÀÄ1¿ÜqUÑ¥¤Çî YÆ/¶ÿWÿkr/C1Þ£ºŸá‹ÄTCëÇöÖÿÔÍ>ËàÒ€Éâ›pý ë"þ¼ø“ÚG8ôðíçiñCÚAççüg_<ÌQG@`5ˆÍãÀÆc\ à0ކ„éCЦ‡·Ëãÿ8¥}Ž©®¼‰Ñ¿Æ¤ü…ëüäì-8|GwVv4w`úL ÓRw—ñ´ Œ!¦†dk"ŒDE‰{xä4ãж4¤Ž}`Û i–ij=ѧ\ã»ÓN'F7Ò¼¼†¯f˜”÷ì „"Çp7PîT‚=I™,´€Qî¦zP–ž¶;¼»£d¶Ò”ÂÏxæ^Óûgä„®CÖˆÓ´ÕÍÒz:ŸhdiZv†ÃY4-ê ÝÄXs€FyËYb püzô ý™»l~nÀ5}βG”&MüBCp 0†œ‡ésG²Rf 's ‰*D×öýe^c+ÅÊÖCM3BMH ÎG½T„nU*©Ã†^Ÿøbv¦¯¾º\üå«,äÇfV‚gi0s\ß­!ƒÏmÌÂÜ‘…—Ò©G¤ÊÊȾðvë¾QÏÊgîþ}wÿGØ¥L)kG–Kͳ1exGVw Є V£Arb8ÊÏç•+Ç«zûú÷®F_œäû2@ RBÒ(ù1ÀP—Ô*Tê/¾}pH›ìì¼È“å–=»+1”âÐNuÕ#Ÿ%A/âŠý×Q-,òˆ„óº4IóÏž)ÿߕޯÖþŽ Õg:ÆK 0Ëã0‰ ¤H?Cb÷îK¹Á]Ùîf©î˜èlÐhôÕÓ¦ëQ¸«ö¾6î<ÿµÝlbæòµÈ³ 4ÝSß1çØa(Zû¨Ï‰$–¸¬B²süAtnмã-(¹Æj#9+DÊ­Æ‹‰ëœ’0#éžäiÆ »$fŠEæ r[¢ _8b€-‘„?®mràÞÉšöd ´¡²‰”Ûjçÿ†$C=x ±›ˆ<~æä˜£ÄsìŸ$Ca©Ž9Ôäny F¾vM÷ ÿÍäÑ/•Ÿ®Þçàº;6½”œb)„­ ÅâB«!rÉäCòO9ÁÖ ¬ÀQ£™;.*FÄ\Yiò@xã`[/?Qr{£šÕ,\© çÓ”C~jtkÏõ>ê¥~÷ÿôdÜ?o_–ÓŃû?N!2׾ݭhcC!ï;{Ô 5•…ß±ƒŽ©ø‰HPí\8Ÿe’/„! ˆaB±XæíîK‰ˆB…÷áDhtñå’¼[F’J½f OŽvìAŠiŸÄ˜<3'¦:õǃëß<çEJ¼àþól·Þ›g_îd쮥©¥kÏs*ËñæÔWâ(iÏGˆaÃ`Ý ;.pÛ)CËÞÍ*wNâ—–Åù´Ò•ÂrvU´G; à§ûÑ~“XÊ~}Ö¾ibSñêIª6ó0çñrìOS›ãÕ}wÔ©çXWÐ_(U4AæûÇýý>ÿÞû|ß³=dêï§óšxý¿ñ÷þqò?/ÌwlNŒU_/×ÁU~gíï/…»®oª­ «Ùã\ÌjAIœÕ“ƒþV·³ó¤†Q²ráùŸž÷ x˜~BPlÀ:¯›ß¹ +c$ózÖdñ’:'´öÙ<¯ ÷ r&(qmõ\ ñê´˜~•v)öSŸó|M­¼$Þâ×Þ£®Š;GÙ£—6ï²­ÿR—Ö|•m‘–?Bû/ƒ^þRáýìa·ÍIcÆÉ닱/í=¯mð}–)¶üÖD¡&V¶³V‘$dA:d`ª¤éŒ3Ö'ÖÖxyï'G¡B¤,¬¤@î1Aa0б@‹$YQBˆt9ß‹ %ëâ—yó?µé?áªb•N‚§©Æeø}ÑõÄ’9ÂøþF.ù¶m´A"*"É’ñô=˜´î~QO# É5ˆ& EÈÉX(gdÕ1PÌÅMyÅ¥ö’ÄA{Þï¦7ÊáqBß‹*I‚æ"UvÄß³ ÇÑûq1, ",I† €±%Ùɇz¤ÑRTJˆ‰˜z¸5š’&³Þ¾uH ¨oü¼9RÙE^ò–=¥¤Ê1Ã#Ð{je¢PÁ&ÊToXØpì…FT޶tçëX™·cÀõÔD¡t®æ áš½TŠ˜*E2”fE³|ÇKè²%efO‘(“C×TL·µª:xlé,Løî'üõýlóë]9Œ>“ï1¹“2Û[˜ûµß3–y¼ª ³)¨îRB~ã?DNîïÙ\úù¡¦ÅX³ î£>aè¶…~ Hx|7i~ªOFN^‰ws%>’œ=?;zª´’<¦áQ\˜*rãíçE{µdák€3»?V„„Ö£qéþ'æ!³±ÐÆ2f6ݘæ»1.ÈUT2Ä\¬h¥”PoR¼¬mTÄ©ß\Á)ƒ ~<æÐÛ ž\"ª›ücòŸ‰@ãÞhtTøaQ–ák ›À,’¯„ÎnQ `Ñ|ÇL I‘`qUÆu{‡]0`R.üâˆZBÝ9ÚHî«ÊjæÅ]U÷¸3œxw¸+Ϧ¶û&¸¢Aï5™Ž-gσdz‚4G¡(ËkÞ‹‘y8Q†&¯^ÊŽêu¼½E%¸ÐPmED'Ëûyz{þ¯RæÃßqùþò>:·üHOíûl„Ù˜[”“ùX"à£`©8û¿£$&â¡Ø­Õ¤;ÙÈðy<Íké4éU[rüÎ8á‹UŸMî ™S£«òï…ÙýŸ#®¬ØÑRÕ-VÚ-IaäQßÖÊD`/ØDDDö ]Ïß® ýߨkϰ¿rŒôtãÍ=úÌš*ÏÙ~ îÁ—kYmÿ‡ó XFåà§”X²ÉóêqÁtÒâ÷¾8K†ÞÕïã¥:mOç{o©xê=L+Z÷:kx^šÊå|ŸKðwÀ’u>sŽÖ°²®Ä:øýoøé:[h‰Ü¿<П¯¼áT½{­ŒïÍc×bÒ[uÛ1ôoN»‘n»K#?V1³8:–®«ÏlmÇ›Q’æúŽ&k¦ŸV~Ä™3ïŸC­¸fö¿•=ÒóàLîrTZ5Ç 3à+åþëxKjÚóä)Ö>† ©^~ZWsc˜h|_¼EcBKvX”ÿž\uñþ]îÙ¡ØBœû‚!%ðèH©ŸoI¼s#ˆ©ŒÖ…ó›Û1Ñ)ˆÿ"ûÏTÈE+á慨ÝlÚƒs)ŠU_휱­¿üÙ»T»^V¦Ž—zýD¡ŒØëtþêÍ~Ð:  |]â©•w€ØçÕî{Ÿ›€@óÛ¯6å¬dã\®³!áFü}ºÁ#–+-3{ßâd>e";ÊŽR5o ,Yðoy¨$TƒÜ@Ñ`p Òçê'Hsí‡|”ââ_Ç ¦}Ñ­ŸG¿òË4¹tª¯›üâÀÖSÖ»fh]×ë]Hæ«Äi¡"2*˜ˆ)Ñw½Mß3$½ÏñÝàÐH“‰veÜû}=Žlóÿ72Q_s7Û(úþç'§‰—¹ÚT1Õ½$1Aï¿_®¸æTËýa¨ÑôGRÓÀ» ÕêñõÓ«s๯ódkÀø™rd„:Gúhr:m$ó¸ I⎠Dh;ECNánJgÕÅï©b`y«”™ÌÛ]¶Š7œ»vB±KÍ]ƨEË(çþK„œbï–ðTÛfcðñžOíN9h2~³]Ú'^àÊ?†¶þŽêÉ;//Ü~h×?°«\LÏ––…¢2}„µ&ƒF7 Âc÷âD&œºG2qÝA0Iør¥¿ Z¯æå凭“Ÿì,‹Áú–ó<|‚õÜDúó÷»î@^Ëp$)Úû@J‚—éIáQfa}&˜ >ÜÎËO†ÒÃrÛåÞû^_ºž„[8Ý7hÕS‰Ë3´eé¸DîïÛs°“q uü«'Îe„'ò4‰ˆxÊmÛz\‹¾” ˱'¤†,”îO3•À„ß›šÃ"þNMHRëm¯ry#ïälú_Ùê å#w<ÚhŸM¼.ŸCd’GBµh¶ zb’‰š°É›šÍÓ¡±ô‘ýWœ°YÆF›åÂÍ«æÎ=:„&ønèW¦î>//å'—–·^¯GFAÖɦe/ÍŽð½IqŒ®fÈ?;pò­mf—…[Œž7OdÊÑêõGvˆËÛÆh§‘n€yö‰²4sÿ‡®¥›¡žƒ²ôÙ«p‘"\iZ ûJ¼sݤ ºÙÒÝ©K#æÍ @gHÒeíZˆ1,µx†^lA¬¸ç"„££ä÷RhfЫW£xÞ¤Â{ÉæïéÊô¾åŸ$ :%`¢?ñî’ú—ËPiŸȦû=ò.n5›ÿ–‡o–Š|œÌ(¶më£DOœ½`”UØóØusÐÀ¡Ì®›šÛ{êyˆ×\jŸ¢ÿÕÒ`§?ŒlÈõ ì÷k¹Ú3÷‡UÃªí‡Ø“0\Iñ½“ãûyˆ/£,3‘óŽTÞ¥* IPAßœ”‡ŒXNAh—C,©— Þ1œæôóÈh‡8CŠ2_§³Ç{o9±/ý®Žïn£õA5¦9¡ðè)å °È“/%LA¥P‰Q—ÇN™äyg•ô ·¶ïFAu‰¤ýè«-1Sš«øWV¼³¸4­Â·gÑw9ñ¡Ô&9O6×R&ñ¼Ö½wà}9÷¢*hRß§ ÛýuÀ@‘-Ùïq´Pа¾µ/§§ïö'~›¿ô÷¥p1’U;Š9ý'¶Ùä¯öÃÚKB!Ñ¿bÃO§[øZ“YÜ@ýÏÚÈå”Þ!ͽoG`?~=ÿ=VÌh_Ôñ1 t ¯¶£ƒ‡‡»®¼GïƒvS»“ÆFË‘ýp°‘\úÃá5¸_ä¹8'‚ý¥+ £ÍV†ýŸGÌôÂ}Æ}ÑÑ”°nè;­æÉéËWI^óHä_®Ïý¸˜r²ð6zUÚÈ–àq‡%ËM÷yõü2á†TäW°ºÞܼiÅë‘sói¢3Çà2'ÿ45Ëppƒá‘¨„ÍW 61 j\`¸ô 0€Z<ˆW]^je‰xRLä7ø´ß(SQךn^,02‡U’êt–6£Z›öËl–®ûm»ÇØøþ×èö‡iú&æ*¯rVÎÆ5:>‡5ú¬LùB7-Š/  !óóÞèÎ;q Qp†1š®ápQï7Íž/ÐÄwö»É‰©¥-Ñùµ6žÏé%,°²Î¬bt`SÖ[–&Ý £Ïªòª»Û[ŒÙ¥ËËò&Ó“.Bùò¹ùX[õíï™kó=Ç=ÅŠ¦ì*«z‘‡}ùœ¬±^õ ~Ï‹^&Վφïð$לB‚²Úõ["túÅÿútÃå­†Êz¯:GZ=g²f{<œ—ÓÞoC»,'î9jkT|é}ÕéçÂÉÁñâ+Ôãª(„4&<Í@êJ!¯%LÌÁŽò{ï¥>B‰ (c¥Ž·RÕ!^ȵÑ#+âX¾<ÄÉÌ·B(˜í­Ý’‚Kž_ðK.4ÃËÒ֭žÛ`“DþÖ1üc±ö{ôÍÜUSÜõ¿àºôó…—"õv6¦†þß«Çg§ âצãNs(fž7_nV"yT(øúš~V.¼Å¹o,ÃyÄŒäÙ~|È÷]j«ìíä€xð¢ómGnz."&×ê*"Ž”ug Ub:0{)Ôîp¶ÐÒ‘Ï(†ñÍ ÆòYÑ?ÝÆ¶À(;wëDNÄDìöLMª** (9/%O‚Þ_?6®±›|Œ£(ªª(¢Šý”])¤T™¥aín'–*FU¥¬ôzý>Ÿ'á±Ë.zyè,i Å{½²PûØMé\ñÂCÇå­ ÎÇñFØúmm¬ËîÛ¿¼²GUã¼vF$bH„ƒ DŒ`°`Á‘QQ‚Ä_´ÔAˆ*‚"‘gß>çÒàôιV¡õ|8ù¯¸û4¯M—r­ßYêf{˜d’©B£8¬7,<Єl¸k¢£U‚µÓcM¼´²å»¦9®90†/+Á«ÐÁQŽ+o7f[—eAÁóÀü¦ õã‘'NôUFfLå?òÀæt•«Ý}ä³èïR-õ³ÑÉ-œþc=•¾} ïçêÚržÞsõK’u¢ì4>¿YÉÏ׿g7žÞ‰~g£fÜÆú“s?÷=¨m\á{mâµüÀ9/ð¨ý>´þÆ©¿…Û-ûìúS½ì[N;òËþ§~ÿ e.eòžAÎ Ý»~EËÑìé¡_Ú믞et˜z¾ ½}ŸÓ®çn¯•8nÇ-!Ñ9ŠœÓë^ænÞKùþ£æž}Q`ýlŸG5ô’Ç7;ÉÒ¾èP¶¤G±Nsm†]žkÓúû? ö‚ î=ê­˜&¸|Rõq Hú7Ëò¾©o_ÎJÄûsÏñáŸÇ¬;±hý6 ¹®^ýë·éþ ÞÒýÒ"~)ï!$“ "Mé ‡äŸ`‘”AT!¶ôAÃ2ñ6޾t‡‡*VGK^£7Ju'>žo/:riyõ¹K«ÁÆœgSܾþžŒ=|¨“ìbñy9)j‹}Ë®½‘4!»‘HÓì-afˆˆˆŸèQ‰T ÁUnkœWXÑîÿ_††ž """{%‡"N0²$OàÚ ½M“úI²5kÒàzç¹fz×3–®ªðUŠ«Þ€pEUáv‡H'x¼'"Š¡˜¨I5lÛ åp“whÞÌ%Î$;>¤áárœÊ«cT7ÕUèiC2…º…/…,ÂIæÓ”¥ÿͲõ$lêÝßÞ·Ýd]‘~ö¨"_yòî;&Œ&¾#Ù6_â’} Ú"]P–È/¬j}ÀIìøë`ovtä+—fô‰ÉÌ9ii^uãLÇ›672ze°FÙ[hø#8ÊJ?,ïíз% ¤™X}Ç#*|‡t:l ¡Î#h…Ã}ºwÇM˜XšßÊž\ÚÙÌUËTKz…hû–CØŸ-P@þ¼²]œÜ˜×™õç7c¶È–9ÙŠY&-úápá_Åó³•˨„ËŒNÒ"•0Ðj:uBØŽ¥Wýé–Ô„ò¥ÌvDæä½¹‚¦¹³ÏaÅç”ê•WeK7+¨âÞÛdLtïçæØt(“Ü$΄ó"°ŠÈ¨¬Ša'\œqMÝJ ëBÌ¿Q¥r&k2 ±BJELX›=¾‹¬}?»éçy} ½*[侎]™…ÍêÔÚEv‚Û㈽q£KZlÁä®—¼ýøÌ´ó*LHoAâ ½óclšrm§l<‚ä«>›ÜÑFƒh¨þRªê8z7qí8AqàJÕZ¤“ÆÚ§wgA~ r\áÍꘈÖØnËËOnkIeÀ–pøªÒëh¹Æ4{©D×Wy® :°Œˆ†{áÓî&¸ ½ÀlÎû&Ì{-m–¤Íš°œ86ªcjõ.A4G¶z©‘#ÑV6Ãd<ˆˆ"z%”ãoF¥õ¾ù2ÁsGÚZXpçÖ?þ¼–*T©°ú¾,“/unµÆXòÜA8eʼM¸ªª“8ï0Š­#%tDDK“~$Âdreï,ƒzD95bß’rQr.BªöeËMʶ1ΦÇUŒÂ {îÖ¯ÛÐM©M2éRÈ +6Qy œ¼ì)+Î/½wÅ©Àà•8äÀ8§½È›Nh!£°_‰Þ¾°“4ÎÂ0r¨­.HJÖÏsO’Y· wø]Y®çV‡k=ošû‰”L”å<Ê?[‰LO§æü߲‘ñ·•Qó(V}s¼ó®TЙfuÉ"Ý9w÷¿æjìéÇ›Ë>Ex“ŒãBȉi/;?7Óx¯:Äe,+ п—½sœ‰:ØãK/¦± i#IçŠø©8ÍpѲ;çiNÁUUp›MQ',—^m BŒûµ!¶Øû©(fvçÍÒ´Ûmâ'd“DÉFIªª_ø/‡«ên ¡èã4&¾½Cçí¨Í4AÛá¯àªR0çSjD½î¹îG»é®æÕ.žÝÝIY½º·7w\–·Y™·F²è jþߦ¶üû¯IŠ´Ú^¨ÖôÁ!‡Œ,[44’A\JÏŸsJ'MŒ)³<$«Š²Û¤Þ±ãîµ$§„ïÙ¶•tì¡ê˜,§k/ä7ÓÀ®Üð¿sìÇ7·ß J¡R=vÒK€0p¼ðâ˜d2ê³3ܺVŠb|¤ˆèQ®ßÇÍÑ+TUÞ¥ðThen„èq¬‹¾Úó '’¥ý®W*ŒŠáŒý×ʽ”»9RÞ°¥w›;/Ó–cžñ ›vH9N˜Ö˜,_CǼ ä¼®‰ ›F6)Ö͇‡‚:ªUCªc¥ò†uâЂø©V2\­(>„@öAC{ßl†A9àÿ-§²@ÓÇ®t3Lß$–ÔCPö©UH,ôÃÇnNí¢ò-ªÅ§²);¬”áMW– å…‚˜×[o’oèB³§%ïiã/c½†tè0ß‚ÜÜC¦ê­6«z&‚ª×;n5©¢á!Y2[çp¤i¶3ßL¼kdH¼Þ}#‡ íŽâPÔ¤uõ³zEÃfvØûÇœ"nyÄÉe¾öŒH+¢,·Íà²Ù’(i-˜ncØÅ8›qúí3ýtêÝ ÆÛñ¸ç~Ï—º~*i×Çòàu¬ m·Š?|çÉÎi¼A†J©r¢@ð$uX+ NÑÜ…œ“ФHðÍ⳺£Ø´.QT¸_YRw ‡.(NÔûêŸñ™˜å­M!ÕƒÈ÷¬fs1Þ]À¶)Õ…²…Ò©InæëÊÝ ¼’e§?+™ +ù·:æ’5GnþI®ev 3Uˆˆû˜ñ¨HBÅN{˜H›_UY“ ‹¤¤·¨…0^(ˆˆ›¢O’)³;\¢ÀŸ)’Éçsq¡9Hp“b¸Æ ³µ®”_ LºÓÉžt’^—«#@¬vµ´½Qè -˜Ñ¤É#ÆFfè=š6Q„‚£›CµÆ$%Ñ:¬OYz1Æäš !U,Š˜réyoO UG.ÖùÇ‘&§Qtè9Å oARµÅú7Äì8ÝØigBï€Å)»Rk¬æ&.>1vWfšë„-Šé·Ã6Bx¾²ÔBè_ðÄü^ï!õå}{Ï9¢úX^¦¨ÄJaÛàøßœau›VNcdƒîû‡R¸[Ѱ ¤›Ý#„Eôñ1›5{ü¹ëöüfM_VC­Nàág{»J¡º¸ï×—y§Òæ‡/®öu7‚zQWÜÚNuç¶vý|ÃÜT½¶ib6<.¾B›éËfl£c„`´sŠ£¡èl¯!w7E0j胕¥–5>$DDN æ wc.»­vÚE,K˜tNðNgßÙdª“¨ª">ªzìMÉÓ›¶õuåódÃ/¥!¤»|é¡HÂÈ"¯c€Ç‹GHÅ#9¬±!VZHµîŒG:éGR±´ò²bÊÚ“ŠVÝUµë²œ‘•åTHîk3#q ZZq´¢ßoS)ª›ðöh\¥Å:°lsµy]XÄŸÃãºEÒwù'¬§àœgÊ™9ªpm%†¼ƒ™)ލÂ÷vLy&ýâ3Ý’|µ‡µ+³¶XÊÒƒk[˜Û’&ÆÜkdfжRõê‰ÓKJ4ï%4{î¦ëT±¢¤H˜zIl¡G¤¤)oÐÆùËýGZÜ_Ý«¾v¯˜š£ßÆÃº´"¸«²øArT6mõ#—É¢µ°³-ŽGæé‚—üÔ"÷CT©¶3³!ZPP5°™% ßËï_nJe[•Uoe6Ädñ?«H¿‰{·PSSÖêdxX]]¼ºjÑX©÷aÙq|ô ˜p&|šm¦™óÞЯgtsWðYä¢ú1JN kÂM|êŸÇd U]6&ÌàŽž|z‘šÁU™úôÃÇO[‘CÖä‡Xµ2Óæ—wZS*׬u•¹ÛŸkœ±4îàŸ©×Mv¿·­#¡ËéŒ>^þ!ö1•þK ;ÞN4¿¦U⥖óR1‰Ë¿£šÒ(Ùz¹ôðz×Ò–lnÇŸ,ò;Þì5Ù¸`ÿ}·)ì«NÝíŠ>-Žèù»_[Ÿg»º;=yËÙl8óò³NÖ÷ðÛ–Î&:JȬ¹¸Ù‡†½Û;®Ö¢´â÷‡åÇžgÙ”3õù›*J«®œ î¼ÚólM†!áTH(ISÞTOO¸Ç¿«ørݯ$!¶5²xuì7ˆb‚Òcág¸ž„åi±ò, cpÒk}ΓSbаt,\94€Ø—{4N•PU±B˜˜ç•ƒ°šXøàÖSèњʪ©ñ/TKî /^N}BwèSùáͯ 25Ã96ÕÌ’{3Ïo1™Žs][GzÚöFtØÔ>Ò8ˆƒ* Aró·{»¸ÔfQîÀ:<¿×Ú†Ó#¸¹ ®7üœ\q|*e—‹!ãô]ï:³º:³ð݈ëÐܼY9¢rw@rŒ‚·|^ü,¬’˱RÊ·­U.÷,bêrïk­·™M#âÎÍ5ˆd«-gÍ)No‚0ôéÊ`†œû|Ýv`zJX¦<±ÙWâ¼Zbž»’z™ö‘·Ö˜ÿ¦¥¾Æ|³ë¶ÐÅÂ>¿"}ø¦†÷„Ö¯ã°øÐåé#iœ@|®ÖÑWN[¬‚Û}•ÑÑy#AÍG]^ÆbÇ£ŒQV*l¶¡Éœµ!ÀÍÖ” vCÑÙ¾]íøžŸ™ÂpÏЪ+pbûp~ö{9ãÊöúyo¬,~R®±f¼¡yVè‹M9tp”̹1°TPó±Ü ›zb‚-¹jÛÕmƒÅn4‚Š£ü–#CÉ$‚Æmœç!ºET¿e7áaÛx‡Fúã1“KÌ¥àÏ #ßßt®°pl˜†5FÛÈø©í©Ád©š Å–ø&È -I7n¾pL{™9­0; Æ\¶º$T!“¨‰±£eù7?Ž$F}æ7eìüî7Ä(Z@ãÕ¿ âè˜}o¸W^YSé‘â;ýªyÊaúsˆ„ÚÑÆ™™ÈÉ%"Šo \úôÿ382)“"bÕ!Æáµ'.+¸IhH®(·JÜíVó5ó*Iº÷³Âš=÷E(n«“/ï9*=]ÕÉtìC;<ˆ‡LÏjÆžjvI;ù£õßÎ$·‡ñ6=”i$âEdÊõü£b¬-¿À±‰Y ©(R6>¿‡Áu&¸Üœ^ãð:@ÊfV@о_=ÒJ¯-t¤atlx;ôøÓF½Z¯®r'Ç61¦´÷¿¶¸LçQgÖ™^ü” æk•bYÄ1Qs LSÍæ|'Ç%òQ2ŽÉ1v´˜yÛ£)Ùc»Q=Ç ”k­LÕ!¡àtÎvö²b>3˜žîþ%‚@Ð*˜ø³s.•kèzU3R·’%ÓÜ⊗ƮÍÂÄ9¹yÒ*‚šÓ‹BVÓ¡ZȱçH±r„Ñ‹>Ÿ=vÙŒ™ÕIF u£±BjwuêEåq–X¢`t¢Wd±¥<ÒÈÊ54édz0ã†ÛÇ,œl¡ÆòuE!â¡çYÀV´Û®¼vO§=5^Œ‘ 'v‘Ótõ ñn1®)f†ŸNÔåT¤Ì9ƒW!é]Šl„ ã#Ãk‘³}¡;Ö¤#5>J*$vn“\Eqªú×ÅÓdaQ!”Zè0MGðâÆ“z ’¢lT‚››©Ñ”–ꫳ¤®ìùj*Ð)΋±îͤrk´Ttí³l¦¸Z[MV¤”Xfù#êT1ư¬„bDJ9Éîå—yä&åIFutN–??ÖÛ¯±™ñãRŠüsn;ùÝürˆ°dB˼5FŠDß ºë¶“WÇ’ªª,"aχ¶ü²×f@æLZ p»& ?K¦¶<¾AñD‡ .R¢Š3cz¬ËË)„÷pºÞFŽå^5Ûs±xþÄš;s:] ¯ƒª¸à£9Æ.Ð3\{p¬,¯ddeR©³”gµ»¦<§y(»7 ®á.h‹<’ò¬(¦è”ùÎ@É–œ‹3•'ÆHä "‡TÝþD5(‘s†^k"!ËmeÀœ:,FtÉQεGHM—KIónŽWTåçÙbs­9.z©Ê¹;‹p\mÛ×JõrÞà°¿[ͼ܇*ž&-¶‹amYÌVé6+Å“w±&¤ºåÎ$‹íUK X¶*éV’ä(nI¬,”Œ­AÐQo[驲0HÚü$”¬ü4Ûj=Ý’GÕ– M‹hb¨G T¼5*^àåÄÕkBÃÅò:íDTN‘Já°µÝðÞÖ“^u%&áÜû¸êca~ŒÐ2¹"[‰%;o4”†{ëž®¶JFŒB„Áé”ÑÌêc‘úg PFªß»o‚¡šž="šË ³õuáw—µºö½ØÄÄÅR‘Ï.©ôú#Ì_fÈrBž+Îô;í·g\†H¸s½wy/åö¹eª‹w_¯„%§“)R\MEì–µ”L'>|¡K†äǬ—®þìÊhˆˆŒ`¨QÅU¢Ìʪ­ëÚWªk,-(v÷|î&}#ÀóÎÞ¯Õðzîo%rì\öXú¹ên1òkéüx 8BçlëÝ»±Ù.5é¡„Zç»'a7&¼Iâ)q;jlðL{‰ÈÕŸ:[Oi‹¦¬Ù4nh*©$\-ŠŒ¥6ƒªÅSQæþ!¯=Ž‹êró¸ãùÕv¢¯¸ã›†úç,×½”ºôMúÂÛ·b¡ÎZ[Þ»yû\X›R"ŸIÛó¾…é]ÕfòzR“¡\Åçã¨Ø×@‡Žº[l‘°øŸ½EeO¨E6;ȆMÜΤž<™È:'1wät/?_kîv#¸ø¥–ÉkЋ¨º›†¸ŒNŇ‚”5µ5­*Tе—å¡sQE|ÏaR^Hœ¸~’ö¼ËuLó->nO­ü¢Mëjø¡»YXiê·-–u j”±²Å`êF MÇX—¼² særWZÛº7ÛÔQŸ+"B UßcÕ·Ji¾$ÒoË4.g‰F(>ÚOu“¶íî‰l °£Õ°‹T£)J6‹|n¡ ,lVÌ`Ï}ÖÕfÖÒDkk™ª59UZÚo”at]î&ðºW*a–¸"MÖB""%-‚ÅAÌÚN)Œ%ÙâÙÚæðŒ'‚=šJø@sêãÇhz—óñ#ö× *Š÷"¢ÊP—tGºäµo< Ç·[Fc“š@ÏE,)K°²]ön½UÖ3Jòø¼u_º«ç|ŽÞ;Ý_]jß!ïËGDœ¶UyG=Ï]õ·°ËÏa·q[N}©%]Š*š‹â$qíkÂÞU×m¼iÝÛóž1\ž9ܦ»q/¥1d‘PUÂäÃÂB0Ì••¸Ý¡I]Ý8d¹Ìg;Ö$ÛË×%Vém݉¶Ï­Pâ±Ò&ûm„±‰ãøö£ºíã«»(1#=Q °ã‰X»¯H&–S]KR;%}ž^¹í¢Í3¶ »s¨3Š—:ì.RøJ15&”“(ϲŒKk"æ2ø„DA \(*¥]®æTÛéØïµ¡{Z©å]ú¬Ý8.ki f$‰™] (±DF;¹ÅàN›­W¶ûiéOW]ÒŒuªí‡¿±á=øzØE|±J9K_îR Ï3›¢ 0ã Ù^]ÒÇr2Ú»š¥{47ñæá—Zê\®OÅú.·FزèàŒ`X芵²òeÍÇ$ãþööÿMíU®(T¯g,zŽëô¾³æôÿ©Æç}7œ÷ê«ëõþÛcìjv¼O¶y{Gº÷9gÒv>·Ú…0÷Þ¬T>ÌPU»ß)AŒ´ ‘ëÅWÅOz[´ñ±« õÇ×â%ÎÌÍ„Em­~‹A{vÓL“ßßfaI<±þ_îi;wþv5¡oàÿ>¹þðo‚­­Oß1áÒFøÉå‡[Ê;9‹y[J“Ä[»æ”àËþ.st:"ÓDH0Þ³'‡·Œ ÷'‘ÍÍ«!Ô*|IŠ€*Ù'ºZnÎ Ÿøì'ü¹²RåÁƵ²²„{¡%¨¢Á‚:ðr ¼XeN­Í3mÌâÊ7Àÿ<ØÂõß]Ùˆˆâ""a|ž«sºþ{mɧÞ}t†ÆóiÞ„3nõ¸èÏuÝNõ„ºŸõÿÔ~îjî]s^^4„yžÜ5•;$â¢Ñæá½Ú}DÌ¡ÂéÌÄÅLfô!›w­ÀÇG{îê…a©Ã%^îOuw.Z›ù¡ øB/Í®8þ | "(pøK"ÆaÚJȉ˜T ’O¹UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVI$“2ªÒªìª®­Ý-è‹içrËܾ0køä¼é1¡{_|@CÏœþÇ3ƒö\O©>èðÏJ}ñØ9P€äa8P70¤Pä‡ ÁÀÁ8X+9aËPU°ó't}ñÏîO½>1ñØóG€}áçOyÃïO8yóèîÅUwUp&€„ µ žm? $ ÀÂÖÙ÷$[kJ*¥ióaReçg ¸a¿Çø\ÅOT9¬>çìfGoÓ~}½Tàr}cîÍ„WÁ¹sMôqf½è­j¼­lÙÌL宪¼5UÿM«Ÿ¥¬’<ň=ë$‹'—r}‡Š°^ÎRÚZ&'TQx^(ìò³á÷^"ªó•WŸU^ÍU{˜v«ÃU^ ªñä5xöwgö~§~tVn•Ê‘±lƒ‘ð¿ûùÝ8_OŽ–Øß,Ûà ãu²[Øða¬b±Y݇àa÷ð!ÕÖ—ñ¹ßOó2Ê"»â×Â=zÒÕón¾ßg}ØR·ÛYG'ŽLˤ+•Ž,–·×XÖŠñ·~ènœ8Âe¶g†3 ÒÛmZ)ºk ^¦ ¥¶ßNKñ%­Á¦íÉuörí9‘Uë•V*†²ªí´*¯Ž¨th|_ÁöißðëÊîd›’êìø•P~}O9vLÌÏ9·eÝÝï9Î^,Íç9ÍÍ×ÝÝÝÛÜÌÌÉÈÚŽO]ß9·˜3[èô¶b·gÞõ{G¾õ¼‡»¦Zsp¥9ªõ(‚BJ*ª•)UUUAjEIHU$YV¥U•IR"Z%,I$ZµeUXPµR­$´ÄPPŠ0DQŠ…«Q­¥°?3$’{ÑUÙÞD$THDUà›…ƒÀ,æù÷,±Ì8Ib,’ŽrË$sîa¥˜i‚ 4‘¸Xç ,Ê E˜p,@Pp²„af’Y¤”I&’A$IÃDY”HŽIÀÃH,ÃI$¢Ij88hÆd‡sM(áÂnʶ7´a£G#sCVêuDCs›*ÝÃvî·FÊÕÑMͲá‚ÎI„tYg è’ƒ ,D–6@åAFðá hŠ0ÂË8pƒHᣔI¤G4rK0‰0¢H4‘Í( ¢È(qÈ0á€I¦Hã % å #š Ðp±Mç •‡B!î‰$Ñ$“†§'%t04aaÍцÒ:œ4JèÔÓ$݆ʜ'&L˜+;G Z"·n89hH…8håESFpðö’'jI$׫w>VtšõmÓ.—v¯¼_ÙÆÎõ3&uµôE-5’ª»ÌÝÍ×ÝüMÝÝÝÓs.îú®r7vfÍ7j""¶«i©ï5suÝö÷wMÓtÓwuánD9kœŠ®s›UËÝÚnF¹¼ÊÞ#›»»UUUºæ¬õ{*ç²ÃœžvUv\9W\ä!I«4tbÎrœs²*c¤u›rü¼éúçP+ç]B¬©¨ÍËá}\F^ɇ£œÔ8æòMË·÷ɇ÷Â?ùÜ}e¼®ëü Kki(Cž<6êÎvžóðsì¾ ý¶s÷Gwëî–ƒ–HûZ¯Äç¨ù?÷;y0’I€k¡„8à T0 eG!¼eãº.&U¼a¹Ë §ÃçÄpD‡}ì‰{WCÃͪOœ>O‚;2~`ÞÓ\¿t”y Ö§šj© {+FåÇ$€»‹Îþ1£˜pøn¶Lá¹Ù¡ùŒWJ‰¹d¿#™…$Ý®`jRGz01PRïêÏ!»Ä {£?aççY‡úÙFåõ±¬ñ7 ®ßÇÂ[Útøp ‰éñÓËúŒ–u[õ»ô‘: ð?oêòŸuÁ×È[‡Œ¾Ÿ­‡ˆâPãô>Oû."ΣYŽ˜|3Ó|ž÷FQÇ#Fe7€³BMó¦¢Û+aŠocã“ø}s}%:^ßOfS€”¡Jv³Eœzs°ôñÑ‚‰Ý?9îÚ§gÚvðú‡¯×Ð ××½íUUU8·ˆµUUEU[$ñB|y¯cu´!™I hÒж…´2/zÆz&³Ûe˜@ôDD±ÕT†›.Ë bÛƒWš89&Ôf8ñ×Iá³£8å鉩ÐGG`IÒCÔÉyï+„m(›W´¾¯U± 2À-²Kl-²O‹ZÈKl–Ø[`y¾]Ã¥î3¾ÛëéÓAþ·¤ y„“(Yb²²"ê$‰Ž Ê3Ø$ @bì<½û;«sîíÕÍZ÷ºº¹ðúz*ü4ªªª~ÏéÝáÖóñÇTU‰ÂDío6“C9‡‡Muf=ɹªqÝܪªªª»Úêrw=ý:t’M“¼0:è˜L”43~ÿNž–ªªªé¯ÆwöÝüqÚ@Ù n(A¤Ö•UUUVñ¢“ï‚ÀŒB$¼ÒªºµUWŒÌÙ ÑÑ'$‰8^-UUUæðpHk‚C‘’a „@½*ª*ª¿§ÇÑÏ™Ø1(×û¬ò°2¤×›õbWž%kÔò`‘à°l•ñÂ¥nhÁUªÌÿÅ4èíÊû¿Üo1ø÷–‚/ÙÞT³äÃE¤ÅR"ßË'¹ÜÊ©4ú6J ­å0”Ƈí$Fð¯už_ÏiJËjìüÍà)Ž}_蘞k5 ¦ÊZ A‘“L"5&æè2›£öË/à2hc6RøXO‰à¿éÏÁ)7Û2‡ â8Z}ó¿…„×í ãÁ*{ TMûS!l§ •þÍ£©'[Úz(vAÁ«€ACs!ƒŸ—`g¡5 P"'Á><Í“ý¯2å… ÌÉ£!q’ãšruíòÏ…ßìd£Ú Ô?F~ÕZrç°:ކ>µ›·tDQߣâ¶MÚ/Cç%±GÊìG’Û”OfeÖG°ácóþõÓ/Uéé'¯?üÔ@)y_¦Þ謽öVo‘ªûw–™â‚͹g{Ò4SÕY(“ãó£U¸±—¥¨)ÍÈUEÎñm­Œ˜ÕteT:ÿq«(06ÖM̳×y®ãc:¡žuë#É…ËbÂeŠˆèãýycüy|oÕüÝܸP·›Ûo7Úžõ-¦ ÑdxøúÂûk^^EvfUU‹6rÅüþVs˜ª8÷;1µ"Ñm¿h——¥^ïÛuü–«ã”d3‘î¸?Ý÷Ùïz‰ä†åvm?@µ )¦H KJ¹×Ýz'ãƒ' œœ&þÏÀq HEI‘:ÓòÆ €Ä‘<ѰAø@Mfð¤Ûw•@îYqýŠÜŸ,w‰ÒæÊ5yÓ(‘§ 9O7ze ´­TDsæ1B¥â==·AÚT¸RÏk;‘bòÁ?6òpսߞ¶~h|±­ :%>[öìü?»ýŒtíÎÿñ.»O Öe¿ð9³ùÞÉïò~‡½ñ>»Tñ_ÙÂÈóeÕùm|þO>96=rã™Î„kòæj7KJJHÄBˆ$‚"õšãlÝÞ³w¿õ{ŽãÀð;à"“APÑfÐMsßâNÞ˜w—Ç&Ó5ŽÌæè$! S‚Ÿ¸é²?ykýߦÓëÝ’ÿCVsü¡SN?¬dè77{µê7ΫMCŸÝMFü„Ó»W•o?Gy]ëHvyœÏ6£6àÉÒ¨x/ìîáæ!úµ´½Ï“¬m6ììì—ˆ£R”Ìúüâç9Îs—ÌÌÞsœæûÝu×]uÕîõç9ÍÝÝç9ç9ÊÝãóœç9|Ý~sœç/œ[¼ç9Ìæî¾ï[»±¯ÝÜæs®jÝÚç9|ÌÍç9Î.sœç9|ÝÝÝÝÛÝÙëwgwwk­ãóœç9|Ý~sœç%J-–R”¥'JRË)JR“²’,7îKA¥Ñ­ÏÞm{{{f‡-òç~ÏÖ]Ñu•én‹.·«wQwŒ°’ý¦ºúW6ÞC†û×ÓæÏŽ¶ÊvçÖIµl»,rÉ'@YÛuÑóq÷-%7*#(ËûûüD (¸°¬0&}d®Å~}Y¦ÜÃÀwxÇ{"I?¹Â–/K|08HjÄ_/|~K<^ ÆÏGÈ~³N=¦T¦+Æy}ØrN~žÖûÙ1nGG; )²9Ý• ¾¼}ÉÃzdEÕíS©ü„ ÍHµ‡zR A7vJ‰Hɓն·væÅ±¯.D(ŽS("¹È±}Ÿ3”'+‰ÝL#“RóSÓÌîõ»ƒ¤’a$s'7f9U†ò.±ê·k†»£7vâaáÌæËÄ»×9Éwª*•næ œPrvxäêtèäÖâƒ" æ•JÅ”£wWŠfU2/Ƕ÷ªéƺ¸m4‚¬v¹/7E éÞg¬Ìm5©žMÕÄÁwRLÏnNxzàô×lî>Ï˜Š‚ 1ˆ/6¥U–ˆÑ±–5§¸d¥Én6æ\ÄL0Ì\®\Ĺ­c™£F´ë.‹u¥TÃF„£4Íf—±4fÝåÑnhErdTîJ"TÍ$‰kÄ.QV“ÂÔã„DLÞolNgÀÂÊšÞkf´ïK²Úk 5™\]וU\§Cû€Í¯Ó÷²x :…F—§¨û›ûƒx({ŸXêzðNÔŒ½¬Æ‹–®j_<õ"«©1Zt–çJÂ=Í×n½G…‰b°%`ØÑ·âsÚѽ;ÈlLuÚZ"=¿cÏ¥!Ó•«|‰A¾n×ó®}YƒBKø¿.Ô‚ª{×iR z•xžÜJüöøaf yŽŸ’þ‹æÇJüWÓÚ÷xüwwîܾ÷{áö°—zw]¶ºî¶T¯š|ö”§ƒ^\}ÃnØw—¼¶*kŽž(7Á¬c\á5ÞÜ=Mt<þîêã­= mè‚®2<úÍIÚ>Ù*ò÷œ³Ëëy©ëa2^t·Ú™5[דÆw±Œ{v$,Sã~`ñG8 tà·½ýöšÝ>–Iù¬™î®/«/NXîðžÅù|Èæ¼|êæññ/3Ÿ›œæ\mâ›ìèçæ—cº¤#G]ûý^jçç»TŒ2||¸ôÅl®ÖÍ|['H´:{ûõôÈÍñÜÞG#úùßwüÅæçèåéâžC»Ö݇/'¥¥Á|“=cºŸÄ‡‹£&¾¬ú4%ÓÒWx ÏÖ¾¯žÛ©m y2Ô—±æl)ãä;=¾¢zyý}#ì÷{^ÿ®«Û±®Çó_™}~]÷ÛÞOòö;­ñîÞý¶wu|߬qÞcTU@I 'xè<]Ë—üŸHûGN1ëæÈeÖ28¿…5èÔã„„@€†Dˆˆ ¥uîóÉpy`©è½ÁFbIå­°7€3ŒH‚  ©¡Ž}ðööý¿4ìo×J L¹»4€©1˜Ex£éX=9pø¶FtÄ×Љ wI*~ê>€à Î`ª—YßGó°~d§`33ºœY"?̹#e'©M³ó-D¯,q;™ùä°ÓGörñ#“­û—õlµKï}¯ÍLø D„Ï9¡´¤39 pèhNçÿ¾ó>ŒAýÿ¸û=³nùê¯e$tÚáZÛw&>“‹vÆv‘)S‘h>FH›È=\&aÑ :bÙJ¶¶×£¬¹Ì6&¦ °º(廵W Sy¼ÀÓKG…÷¿…?TÿáÞûoYÝtFŽ6ŸÛúÏ`Î`Wýåã›Ç‘€ù±a„ éòNÐÑ!Ù€‘ C Nsï`9]ÉEBESm` PŠ B",*2›Hµ @Xi‹YXI&*²QkaP¨•1 ÀR°©He°Y ©P‹%B€‡$Eƒ ´ŸÄÔ«‰<ág‰ÍîpÓî1òÉqÒµš TI%P²éÿ"|ÚþÊèùûþv¶ˆ$ fN2ë]ÝÝyϱ½nÍö_D~vç¡h˰U;Q Õ@H„€CU¥'CP{‹ôjýþF¹,Âç=Ý÷?œ²°ƒß"èN¢¥ÓGÆ3\íîÁ]ÒŸLD’áËGBi…I>!ÃÏ¡±ÍòmnΚ(ëâ͘´²´åë½i¶TRpï˃0cæ$+ÑøßEuÙöŽMŦX…âÌA݃B"ÁD;{83»22(ªª §5ï‡r¨""u¬LŠ×®ô6”T»6ÁQºùéôªh+œ=ÙþDx¬¹©|äðÊÌû»bùüa²ý¥úÌm—{rë¦=Ý?ÇÓþ…?½ mÿ¦ZaÃn6ÿóœ×i¦=¡N¥¶Ø©;dÊóvÂ֦ﱢ]Wuua‘i[£{ó¶qç°Ò¹[Hð#HiåCÛ³/ÆÀÁïï¥Ø^äcu¥¬óÆ1Êë ¿B“ý®Ì9ý'lð.`¶–v­:{^åÚl¬á}Ü>ûØçË®(œœk‡òù²½~™ßÙÞÛuÐ >-ȸ¬©a㇎vYüÉ•*wû'¤˜²sç±îæÛÛ`ïo?^Q)Gì/èø?“ÑAßÍéÇŸ´?K}«^¶Î;ͼ/eÖÍ´ÑáÖeémîI8jÜ•`Ú©[†ÖÆ€ª\YW°XÑåŒ$Hœ¢@gS5X@»+;“\¦Þvµ*7¥pÀ‰BöËußÖÿJýf)шÀÎã†i‡¶JÔµHëMgá™ýÔdþ‡þ¿›îy}~¿¬“ÄVF(zZ@¢ ÷é)(©âÍ2“SÉ?i½~ȨåJ©á’Öêçg‹¿Ùã×vÃG[€Ô3žÛ=¤‰$‰b— JÙÇ•_Ó<_5,têÍð‹ŠAXWVSDr_ºé‚ãäóÍÛ:² âÞØS ²¤:¡D4‡%=ÅP`‘" ±AŒˆ„B(ˆÁ¨¢ˆ‘E€¢‚±}{Q ÙC£b-,¤ª²ÕURª–©UJ£’(Á`‚ ¢¡|}°r“°^:ë"˜ŠaR¢2ÿÏ7׿ËÂð:/Ûÿù½>¿¬í*u¢û†`™ITQˆ,E¢DV1*H(°X0XˆùÐ*"zµUŠ Š*¨  Š n1A"‰µèí™ *ur1,ùñé“EâñVŽŽ0*Ö 2ª…·rH }Pé3a‚öbL¦€ ñãóyÅmÙBaqÙ/™òm¹/1|žgµ9ý&M1ÕmÛˆ†ˆcIÉ«$ín¨®£7V?Ÿ·rÍŠ\]­» qßbÅÇ›$H.xÊËêÔ~÷ï=ÿW°('þ'ã>nüy»ä<Œ‘Ù ç©ï¯ÅtÓð?L¾A·°S°·?ÑаöåìaÔ¨*‚‚¦Õ7.?%äih»åì¶©ŸV|/›|‰þIUƒì/sÎëzF£:žWC #öA8`óÿýö·…£gð~~[ýÚP¸xò•¼úÇê®]-ú­7I ÔHH¾—âzó0<€ô!V|áÈi7~’y¿ÂÀ{v Pó^-ŽÏ[1Üvþ¬ÌûáÿuU â¶ T0O+rciÞð§¡ô9ºržÖ Y ’Iˆ˜$OøÏ±¥§Ù®ºŽàNª¾uUn‡ëÏjx~¢p°§Îâ®UUÒa†8ÑØB0?ŒñZ;.¬­£Û(Wî‡% XßX@âûÿ¤³›=g»ªÙMŸi<ÿ{†¢g£X}-ñþMŒ<¾àvÓ! h\Ëv‰€Ñ’9ç-?·¶ËjŸfÔá;Rã·öYÕd z•’Á´ÚdñjäuA.±šÍy%ÎKDµ>uzZÓ”n :»¾¬ÖA0yðÂeŠ¥±¢8Š“FKq]Ê‘”Zy^þz¤„‚Ùú«®µáé©Ã_èü!ÙPyûœþk®õX¥¾KdpüÜ?ƒ¤höÜT–üŒçŽªá<6¯Vp|ÿg·OB“Ùgî>'Ödæùã ÚLò$R06b¯"Ô„’H©*R¡# Ú<Íd mkúîÿD_‹—f ó›ð}²s¥¥Uµ„„‘1À4j\ã#¼ltøoCsX9Nyãt~°#ƒi·»Cpˆˆ‰j w¨ žÿÔú³ûùþÏî;O%ßp*<8éqó.üÅéØ$ºö ¦”ÌÙýz5Æ©eTÖ]7Ù²ªô[üWçs»>_ !$Öãš’t;=Ö&ù*ºzŠïŒáê%ò|&f:OË\£Á”U[˜e<+>b²ÅKØÒÖ¯ÎV4'CétM~4(Cž$ê§'1z=C—I¡ß?!£©`éiWò3…îÅÈÊÏáV€< êjé`@ V„!BBÝ –É,øk÷i0Ï«Îÿm\OØ?—°Z±v¤m¨¥_x°Aógî§ñçï~t,[¾ï}¸C|žïnèÌû>ÛGŒi»Û”-ù•%;¤¬³”%÷O¤)ÂÅÞ´wýe³À‹VdAÅæsžQ*M³åº2úLÿm óYlÀH"ºþÿYö}‹Žõ¥‹ü&+vÌ¿õâÝ1Ç¥¦».¾úqhÞÿ{RË@¸?tS÷åþÏëç·S±îû¾wÛ¾pÓŸÓR¼¤õà±Éͯ‡±æb¸’ìôûYóvÑY•TD;&¬½Ñtq†fwÝ5°*Q„–-h}ÀÐçËÀùñ4kÄæi ÅNL¨‚lÄû²êî‘ÊQ{oÍü“,‹>|«¼)÷ÿ{¨Í©cãùØê¹{¡Ló²aEUü ˜dÆê³4Må5TE)n äüó"‘Ìv€‚ —³™#ò|ñ£€:‚H„7H ‰†”1PŸVô£,ŽKD¹òFÇt<—$AµÊÁ3æ,m9d$„’a&¨¥5E:ª#³ð9ºü(Ë ‘‰’k´ªÉ »,¹‚Þdf–Ù9·gßZs@Í“Óe”;¢ûÞE 1Ev9ÑÃyùٹ/$ŒÁ:éTòçéö¨®òºŠ"㞉„D;¿_§˜¦äDpœsÈ( qÇqö"2;<¸òîˆtÞ_®Ÿ=ë:âq\PõD]“–_˜q®Rwî9 ½iå±Zs”ÝÒ°2¯7 ¶¢‹ht¼=vHH9Žxs±NœwMÌxG;þ/†ãCÂsÍ+$9Êi3 ùݰ˜“ó*wš”w›Ðª«‰7rÍ‹„"ö— /\Î¥¹³¤ªÀ¦ªªóqmçtÑÑ™™™¼çz|K©^Iòêë‡p áR:aÓ$ÌÔ€R×]º­UÄÔÏ\h¤•ºtî™\Ø™'ÚNµ<Ó뵓Õ5?måñ>[žï¼Ëâ?©ãÝòÿK¸U_IÜzSÑŸ›Úñ3œ­—åx} àô¾nª®Ï vôÔ;uOg¬wóWw×"«Û «©[‚!Š‚H)ˆ#aUvQUÀEV…UìWƒÎéNq:йÖéz9n’øüŒ…Èäì™»Í6âï6ßœu9;\å¬ãÁNLšq÷4\âæp›J·U\ªáÊ寶9¬T¬ÚŸ)”É\H&½í=´Så#¦/–¬­À¥¤ª.yÒ6™Þ»¿œ’s®3«Û µÒ¸ŒX!d­c‘ÚÛKÕ¢ärLrÉʬš]¨¨Ð1JhHºpÈ™MLÒàÜž$Ä#r""'/•æè:zIB]R“<º¡'›ˆzRÒ­òáò!øû1> . ­Òõᦶ*<ìF)œi‰ˆ#þS ×Å‘4åI‰õc°@"„! (ˆ˜z(1™É÷>•Vm-ƒŒêùµÙ×S&:Ÿaóþ—ôÞ'ûûî‡ÍþwÏï7ù¾·¢üM^« ¢ž\EO=>ÓÒBªúBþAÚ„=Ÿeqô:©è`ˆrHTA#P[e‚ŠŒF?^[…§ï?‚ÜEŠEbDU`jù3cÿ¾Àª"1Q#¦X•zÿWmËòȫમúªöXe¼'¿¾GÊï7ÈHIxTœ²Ôßðdï­3KËÏ Âðrå«U¤1½ûÌ7va:TtÅ@R•WÊþ¯1vê«UO®é}—€ª¼S²´°‘IJ(c@ ±DÑþý•Wªþ_ñb*®SU éÃïÏwíMþðçùʼní/ÚðøqUÚ[ø?—BñS§%+ÈOõ#úwvu¸í‚G‹]’æ¨ >l„#>†èÐ\Öš±Ø‹UZÄP1½pû7´=R}ÞÁ¶úhžbf3„!?é%ð~íȼS2¢A†aÙ„çªý2J*¾ò_*ìÆÀ §GÝjü ßÑŽ¡·úüý\] Ƶ&X÷´6$#@)I²¾'«?ICÆùÞïè×·â~çÞ[8g’tåzë}l<ÙÝ÷¡ }ê=§e¼Ãábq#è%¹ü0¿2kL1¢ÕQfô–É1•è« WÔˆ )”w¼`ÁUxGC†Yc—[s=MW–Æú2©Åu}ÞK48hŽ–I¬QÃ…‚Q–Ig ‚ÊçË&¦xÎrˆRÏw§"(Ó6‹ŒÁfÁñ>uúƒôÙø¾ƒÜõ¯_îçWb)çK!Âñœr’µh¢·7v÷w·w²f°²Ë,²Ë,ÙjÛœ êÀ$¨8bfàZ.RD¦•Öt&tãÍîàõwEQ„^é%--- #!$f¨_Zöù7s®v=, 0Ÿ•/l†?`±­¥ùD\ŽZÚŠ4~vÿw¬Oµü»¾¬8¥H¢2Ežõ%€°c#OêÔf&ÆÍÙrɤDÄ* SàÈoÊÃ^6E“n2,ù-m•ЇFB¢©+¤)) ¢2pê8 2JÁ ÊQY›°0C À(ÂEQfÒI'6¹¼ç@ÄÈŠÎÌÚÎ<|!ȵ±6oãqU Þ(`íY$¶aòÕW\¶1$5²ó1oöv§“ÊÉÊܨ¯†WÃö}À˜7ŒhaT655[o5£\ì8ìídXI…°@$!9¦6NUëY¬Hp‚ªƒÀj0ÀÙá ›Š[‘˸üO÷{v” ÀÌ?Þÿ£ÎþÇx䪴ח¿V–× 47në5š’6mœ=ɇò¡?œÅ"'ó’ˆ"°J1DQAˆ¨ °UR­>Í(†Z€X‚È«¬ò· Hpt$A„Œ##­«_»êÿ7Õd˵ÃU_R[j³šM'™³nróiÁ²8sh­·Y¦ E’×r0ÄfwÄÌÌ͵áëv!Œ'.ÄÍЈ€v°(];¦V†pý_Ò~µØÐЇ^3 êv%Ì ly”L'KJ6c1“L¼Ž@ÑNé3v0ãcRÂÙ¸ˆ™ä¦69hvà  ã6@ñ¶6 &G’~¾æú×Þ»aµ·DQ™Øã„Ësa†tVh¢Ç$0äµ\A¥ð±ÆË±SŽ„Ô‘Dä9 ø"$sƒ—ð0,BL˜@¿£YÆ$FC;ÑÙé5ÚHXŒ’™@Яì¡Ù‡¤ïþÆì—;°Æ7_ ­‡ˆ½Eñûc ®ˆˆ;ϳÄ.\dó|ŽÑ@ m^m9Lî\€@Ä"'舟”$#•Ðø |µ:–¼1ÒúŽDÍÞ¼t Ýš UCiyЄˆ=WaN߉r„ÏÚ­µVyÚ½2cz€û]4[¦!?̤0bCÜäûø+V§kžs/‰µSe2Ów¶ŒÛÆÄ.š¡ô½o}ßó8Ïøð½ä•/)RÛT\ÀëKbÚa †×ýö?ïð¾»û=‚x¬$’¯ñ¨–ï/vû’ö¹cfÖâéñgîm?T@ë´ŽlnÃ}tª”%cÔãKœ_ÚÙHâ1‡ãºJ„ãõ•ø_¸ûÿÆý_ÔûM+¶êÿ¹Ø1öçHzÀÝÍ$’F2I#$ŽìãµUYšºz·Ôiôºê¢%Ö`3~U`­Ísàë»Ý“²0¥,²‚´%`01eY‡B (è€G “M$D3H©Í¾6¤2¦ ¾5ÖÍ´9E鸌ÛX'‘¹D¤úƒ¸Ò~¯îø8{®£ vÝÂÓgàtIŸ‘¹c×x³j¢šj#EJRˆ‘)Bˆ‡í1V sº ¾Áù9¹ù¹yùì°³ZÖµ­•¦U„Ýr„OªùŒ!´X«!Å%bf¬“؈Í5&Ì{¹`s®o.6՘ؕª?\Â…”Чu­ÚÞ2ÍÚÒDD¹D‘:·ÑŸa]•ƒ²!Ue¢, ÛeϨûíj1A/ ‚·ãXxúö«aÆtQQJÐ%6*ž©²û%:1TÆTU•§40d&1,c#‰Ž8*,HE1 35“;W³“Ñl‰"É4ÏéòRm¨(¤4&ÙË]²êžL?¯Vtœ³›˜N"E ªñŒÐ/› Qz,Ÿ§Øš{h'Qìô$!¿`œØ7,‡ºÿq¿ÇNj~ãú\ÏMÂÓŠ¹ça¯[Ç?UÞ$æ6õÕ÷+èÞ®‡]3÷Hß;³œIÚ\ÜÅ Š¡R¤”fI#Qsì}Ÿ´þÚúš•ö;ò==a£Žt¹mÑDÍ–[h£0è0–ÁD§ % àÆ×3::tÛÊ’F £ƒ­ '‡XûËè=~”z=,̦‰nl,”ŽéE¬ —,‹ø^/´„KôÈRÂ{ŸiìÞ„õ•¶HŒO?‹÷o‰‰=¬b"[[Sq½É2@áâ0n§å‹©’9h¢)tiŽŒq.'w ÿpnÊ%’î9C9 ÅÐ ƒF)Múú:ëÄÄ t$" ††f¨pàèâ#ŒŒ(*!Åù‚(ø|’ÿϱ51χ·ëȈká(j0=URÑQÍdª¨ Z¨sqÔ¸C“0ªZW+Õ"!!³¸Ä`,QÇLaé2ËÓ¦ÊɵI×£Fa÷UÆpÐõdtDŒG€È&|CN<œv&§ Á+ñÌC©0—aiStV*ËD®ª ‰r©BŒÊêgÃççš WL.Ì9ÈéqÌç3ˆœ¼¨1º-È‚¢‹DB†Ê cI$Ã&·Jt’q¹ YÆI ¥+!J”`°ù“Gn%AÚ,äØh0×d±4R”†ÒQ‘Võ´MMS² ù$ F ”X¤PuaUŒÃ’† IÞé @GáÊ›øð—bgDAi¸7©‘»yËB… ÇŠîU-ü˜ÜD™2Īh ˜Ž#e. ©°QA|5˜‘a…:äB$æ ©  <ÑÃnà“FŠÁ²±›&Ò[Xê)¸pæP…¥Æ@ÆH)Æž[äÝ4mn²#{+mZ½{Ínë, )†`ˆ!––ðN—´°žîoåo`Ÿ1‰´å3.&§*ª"çA•Œ{é`Œ! µCg¼¼‡¾Ã{Ùæp›+7½š1ìÙ Ë1eÛ–[…Ô½ÊF×J/rÍË·±s%FíÊD¢‹LÜ7Ë\\ûöÕb¦àxí•û¢XZ(©EuÚêªÍnDÜæXšˆÝ`iÌÃm8ûk—ÃLnS D`£&‚Í4¨ùè»M›%´Sc7l{4Ò|²‡N4 ÂdQFFF ¬V1†==ïtöe`‰ŒÕ¯Ò""(›IO2âòò†ûSMʨ‡ òAVkƱ—Q˜µ+|ÜÄšãîÛjæÞ $nZ a­Õ£C‚ ÊSn A˜R¡ö0°# á™‹7K$74n»\kƒŠf›êÀ‘"õ]ª¨p¡·lJ%ÈŒ”̤ÌÉëÀÉFY–b5¬šI™‡»-³D†B‡ -v™E)«mØÙüí„ÚÙ†‚ˆAÎ+£ÂØòœ!àÐñÙàÆ“Náhè–Dî˜Y)JY)P‰(‚ òó6…ÃÖà0¼ quT-ÅU 6п,†f!…¨$F0"R‚,3à õxI50* ƒ" À¬—æã.@¨Ù™kŸgïv]³ Ü˜Ê_kmêníÕI·ÐV¦ölëÛ :ÿ£î;_½ë¤Êß¹ð;Ç=v¥UÙ_ä»û{›_—ýÿ¤þïžüŸ³ät\`莵@ò&H 8Äžæòðºe# ¦JÉbˆ€ ‚»½§r<ý?C|°ˆ¦¯]A×lþ=EÚÛ“]®Ð*Ú@8ÂUF'é’}x½Æß¥GèbÁÐ%#=µ¶$UûYo^fŒ5º2åuIL&a¸} ÷~Á†R³-q .}Ñno_¸xÙm¿¯ö?'»ÿããú>¼êg®;Ó¨òõðÆ¡Þd¤'›óí ñö{ Ô11€T-.øgFX|ŸÀzM[wqt³½Øt­^t…Ž»=gÕ„ò+Ïò>Ëê<Ÿ¬ðrnsú·/[Tvä$/T®Õ{_Uë:ªîäeµ@8Š÷¼þXúݲ@˜°RŸ^°¾Û\aWT£ÕTSùNѽ“»¿OÇ %‹¼äòöjþ¾ Á×H«F2Ëõòï0ìÎYÂÎaFœ àç EI„ @Èáb$èkqÊGšDÜÅ8ä«Ù•írjåÿËëö®úž×ò·ø-îž±þ_ÀUEQE~é„aKÔPTËRožýû¶ñßZ•­kZ×…n ¬êv9:}„s¥Fë_ç§k AUQ ”Y! E!îûÖ÷p)cd‡PgÏK5¦*( °÷úy™ ¾ùÛŽ•«ÓÏÇïMÈC¹:°œ1`NGi¤“Éè% î%!J’• ˱£ç;{}§Ö¤¾¡ _‘›ï=&¤†ä¸îî-ƒøÔÄÓÿ]5ågè ŸÔß‹ Ìfìõ?ï0 {ß•YdâUðÜurçØypÛ¯³~ÚèØ¨ª’É]o%G(_T–—E./ ¨šd˜LÅuvª2ª¬ë¦…RìcRÂòÂè‹-$é“ÇÀ:k´é¥QzXW’ЫŠqáéðù(%µ¶¸^Z8H¹•Tl!T¤HæROoŸì­b 2*\ È¢"¨(«,·ϾšíÆÜ qÒòqË»§…¹½†C8\®Òºü¹a˜î¸4áí=§iôvú:ªîŒzí9!Øâvªz?{×ÒðCù\nïV~™øüç‰è:A^‹™n‹’abµjnQ;]¬sö¯¯ž>ï™ÚÉàðºÉ¨eþž³õyóv}*¯4¿bM†ûê÷:ÁÙN>Ö±Åôn]":{š¤“äE ŠQ–eó[ Q¡ì +},–¾þfPħjŽ}ì.ôÚ0€€ €À™¨drjZxýæ6—L.|Ò$c¶cÉy-Ï«üßÉ^ƒcê§ ý_©üžÄè9bªUª²^[´©U-| x‘¼YU@P#%òŒI'H<¡£N2ö¿O½âñûÌžET=-/dînékB#÷?û÷ÞϘùZ+FcßAë y]+êz<@’0é:y:d¯ÌQ”YI³ŽÎ}ïúÞ"E:èvÝ‘ƒ Û2˜FnE”èÓ™2Â$J“ÂD`åpÔpÒDPhŒ(ÃK8iF˜m? ¹sJ‰D¨ÅÔÞc–ÙÁÉùa>rÒ©ñ©³ãdJØ\ùå~™åe…–Öµ­kY.þù¨–L„„dSDA x¡bFj¢€àB)ŽJŽÒ‰ ãžy?99‡ËN¯îÝ=Í}Ýosó^„ñd~­<°úÙiaú5»4}U™À¹7£ÕÀ<9¨·\d:±虩SRwå!«‚3¤$“=aõ<ö'ÃÖþvCcg=í2Ðc&74a£_:G§ÅÉ&ÁD?¦5¯ˆ‡¨£E©ˆbÖ¨S6Þ aµö4«Š½)p Â7…)WáLü~G&æb'(å'!‘Äôp,‘Ì Q̈#†·iLrÇ4eµ©¤Ù¤“K304R”¤jG“™x¯-—œèÕX½o!. +Ë ÎâF%L‚ÔSóL# NÑŠ˜$ ’ñ>¡#£2ƒ(zê?V&¶–ª©¥×Ùf¿`C; 3&ƒÀ°ÒS™u£µ Ø‚4B®ˆHQ ÔÏ:…P±²]¦iHÖ2 —>Y3(…qB2úÒL‚ϯ¡º#YaeŽË…[-ž\c4éåóaÙ8ðîñrÍx·ješX eÐ }Ӫᎀˆ:¹‘$»Ç;±Tºô@D"AÛ=ôÑu,$P5¼V5-tÜ– ë³±ÎLöu0=æT²”IY9g§‘;¹ÛžfK6&h1 2»&F˳"E-  ¹A2TA%T¾X©8iBºÖæF*X8áx¹á% bDzM(^(«}™†V™Ø`B("‘b1XZ£)%1ÓeâJXì·BT\ÌÒ#¥ˆÄXqÔTLAAT¬#cUC“þ•û L ÆŽ&xÆE"Äa²2 b²ÜT¼‘Ðwî®ZGò<³ ,àä!»²Ô=†hš2)G¿~kZgUË–-U›=…ê$Ã*,z¹Öö"K×t½¼óè/,H¯Q]G˜U_ô·Ñø¿êë¹[<Î{n2 pâÂMŠ'Óùøùôl@ADèÉXQÙ×qý9ñù<Í7/g¹íz¿±íktú†óÑ^ãx5Ž$@Õ €K’ßì¹î¡2ìÖÜçõû¯mŸú;OõÿgQõÜ/Ïë*~y}åÿ˦MƢΦEI8sr²~Èû4­®p3â @qŒ8Ä $J‹-nÇ õ•z0¾2íx3•Íé¸!Ôw×ðˆ.!ÒÑÕØ¿Kéµ¹Û½ÉÛ­(“ÊÖ3E± Ú¢¢êêæÈ:<Æþç鸓˜Äøòròr³Q¾ì…)Gx}ÚÒ ±šnÙd"òË($8`iÃI89£–icbM °4ƒ z»˜É$~Y[Ü•vO9šçc+ËØùgï(Cb‘¸ºêÆûï¾Ë ,²Ë,²Ì"ŠtsA½UETc$@ áJòsÌÍì¶Z$Wî Ãð,ø·Aª°«f¨ËµàÖ–šŒ¨êç¸`ugˆø_øfI$ Î)H=e™˜9žpÉ$–Éõm ĮŽ“MËia*crŒˆ{|·ïÞsÛïq¢œD¼=øåä–G¶Ø{Œã´ð¶sÀÖá¤54±…"Êã`¹ lÚú¤†7GAÎ]U–ÑûŸ|Ð[BŽŒçƒ¯Ðþ¿Dmåƽò&€„ÒùXEn$òv¬XçS¢8©cßõðB‘¶ìžÉ0¥,ü'Ȥê@Èr `SpÆÂù…ëJ8”™…{’Tõþÿ^ló:yo߯.ÝØe]ͱ¬ž ÷VU(ULc!Ñ™Fd±«}©b½Ûv•‘xáx¦\ÓÓ“1Ú@ÎÚÐ\-5™”¦™Ðß‘Lñà »Gzc4ö<êjPR"ЏI T#›ƒ»2U†fØQj„@ê\€!.ßÊ=ž÷$†Çi²hF’ã@d4 óW³TSXO“03–êüDL°víãÇ}K_±Á%? Œ¼c»µÝÛ0ÌÎ I&kȼP 2ÉDkŒã-€Ì£]@°{Ç,pS¯À{ÉM(T¶æÂ0GÃwœ¦΄ ©m+á—¿·—q£ÇoÀïâŒì`I)E¥–0õÇ2Ys ""Z m¾ØºÊ/(øŒÓ±×9•LË;X˜`•,˜*Œ(f†pz=•‹Ðh^R8söÃýöýñ÷Ä €yFy¿Àûÿ1ö6÷ à®Ó~mÁÐ7ïÄà\pŒ TWø¿Ïëþï úxÜN ÿ^Ÿ²òõùüC.ßL[¡ÿæ=HôÒœ•ßdχp¢óW[àjeoÃ@’˜÷óu¿ÈS®ºþ«Wû^Å—ÝÜ^”uF?R)©=xeá†YZ"D„90ð£å;‰@Íôß. È»˜¸»œ¤°ù¥áò¾GãaIcÀøÑkž63YUh:¿MyŒ¢xQ*\.gæå“Ø;Ÿá’I%úºÙîÙí·Ý±Þ¹èû5ÆÚÉO2E¤a#i¥²È(ÃNƒj hhD„0æŽÛ;3Í¢Ÿ•‘rr1ærm…¹•6C~_«ÀevžvíÛžKwwwwÆÙÒwf:PΚ–(°B+ˆ™eÞSÇ3Ûé÷ÏË7çê²I¸ ¨õ)*B˜µ©Ÿ·O¾¼ºûÝY6 ª§ß*OR*Á´Æ 8H¡L`ˆ1Uí»6a ±Ò;iFÎB$ƒbŒ4D˜Ãi¤±š"Fsƒ´³ ,ÒYš ³q©¨Éƒ…³K5³Q8QM@‹eË׸m ¥>ôDDD±â¥¡U¶±}†â1¾À¢(L {¿K o¶lÑl…5“&a˜fz 5£ÎÐÁ˜"Ž:8# îŸ-–,.0l‡&D¾O ˆà<<Œï'éø™5 ï̘Kq¥Ëa’˜d3 p`dÀÌ1_Óab®ûüŸž\ñ­>å’.¡íEy”Ìpc¨nÂ¥¡:ÄD0 NÛÞÉ¥A´´Hš †n¤™wwpx®wît]¦òÕyÉ”G‚Š ’ 8ÍÝxï.BÔ°£ˆQ‘ñÉpKHìáÖøžG~»aF»÷=‘ñ´ÖAf@v–ƒÀÁ­5e›¹ HhÔÊs†xkà à@DD‰…—­`ïƒ]ZKWsA*LtÌÄdêxÊ›CRjÌcÒÌaçIßáå|µ HWÓÃÙ‰ò´p Û.§ÒlGˆîJ`B€"Òž}µ Ñ%¦ÄªðI{¼»ó¯2γÁÎ;`a×aÇL(@ÝÚÈS;"ûwäwìví&ŒcA{ÙŠÙ2 B`D àÈ ŽˆŠÂ£&ƺŠ\XX;»Ü5ĉ qBášZÎÒ21Ý“‰2÷»î÷êÈO^J¢oß0þ®ù=çÐgÆÿ/qì{ŽÖˆ;;X] !ÓníïœBdýþÝJ#cˆðô„\–L’Àú™÷Bf§àÉÃßê.¤ýg³>ÙÓ{_Åÿ/ ‰à~?×Û¦æ½<çtO/WÂÊ YZì'˜¾8aŒÉxV6ö_ãü¯ÕúÝY2tž¨7CÓbLŸÍü¾cåmç:¨w©mÍz±J«”Ï)Ésö^©>ù}ë½{ÞìCûÞ÷"êy•¼Õ7tøiË,²Ž`„}ñƒÀq!YÑ"ÇDPtmKnæóLiW¤¹ç"\æn“¿Ä}ßÑîW~Ç~ýºïî¾µ+ZÖµ­jâX¡š‚ Pq†UA·•fQR0í)ün¨qM}ïÆØ¤Äí°ïÊãÂȬô㯈kžNSái#Ã_ÐH"(ŠªìÉ¢‰šÁ¯ƒîšÅôjf¤… AÐ¥daÏhq¦ 8DÂç 8ÐPЀ“K&G³ ms(85UI`Q4Ad°üƒåÔp7Ö^Ëtì‡ œýÏvøY‡6ÇÒ‡@ÉKñý °×†f sºèQ§Á'cÌI”TžDáÇ›gA;²“;RÄíNàQ‚j$ˆxçÞÝÁ 4a/=æðÑ£˜IÞ=ù¢" Bw4hdwO°Âª+âÖЀ:¹AÊÄf-gK‹­2Ï€ÓÃŽx„@b‚┳O”S3I¼yCyv $Pd‘]Ê$¡ºrâr8ù ‘Õ6¼\,§]q¤„‹Æf§@ñàI5 Z튒0ÄŒѰ!pª@UEŒQ|¼iÕ¬g9Ü7¯]˜hÙ î¸î:„¥ ¤TTd¸[×+œ˜tYá ÍÝR­Ä@å<'³JežcaÐ8„ÎÞ5‹Øxƒ¸çkuq}ŽÇE¶œ †HB ¢)'9¾+cë¿ôsçåþŸÌÿçöÅTCf9¸A@X|öpøØW¢þÝýnô}7•Èþ?yÖw§Â6r;5öž7È9†CâƒßŒ­0Øh‹uÀ.N@ÚÕÞÝ y/¿{&ž‹'«5&ž´œO°ˆ$,ë==PŽä«Ü¥E,10¤$%îâ—¥6ê#¤o¹}š]iµÑ'-ÂEm3ðŽÏGsU¦‡q§¶®½6ô!øzêpŽÃ‘ØA‰“_^zô&®Çžé­°œ€e®ÎÉÑê'ºôÝpã bܥŤbŽ+½`*­Íƒ°—²èáL?Óxþ=òžKåäk¯¹žgy{å”°”`n¼–Ô`è¹\]mÔ&8£Ú\ ‰H€ªŒk†#.(1‰&e8WG'Hž-çcïÅa¬|o¢€aa}ØçžYgZÔ­kZÖµ­­ì£µEP 1Fi¤I*Šª¡z~¶‡zýŽ>ÍÌåi”\|;å*(Š ¢‹,X±óòfƒèË l%¢É’"I$‚A¨÷&PauÙġ6Í㛉G:¸eÂpL²Ç%°£ »%™°jil%¸cpŒ0C0!ɞ°¢|Éüƒ““ŠçʺŽVëÔµ Ĉð½:vpT!Ù’¯×þ]xò(èðÍ^íÞË Áž‡ïT6i‰dae¥Wê¹ôåÍž›§oL²„ðÁ¢=ýÆyÏo"»‹£·G›ð‹Ó,øY+®½»©Ý½‰³a{Î&K^h*%É&Z[õá ¨–ŽHrè( {¡·gQÔß±‡G6Òu³Ôš­âb0•V0ý3±ßJ$£Dýû‘ß;1»ƒ´R; 0ÈL!vUdsö]Í:-µŽìi裸€–,(“j˜Pu¸Áð‚TIŠ:"\”•Á&. †‘ï± …Ã\ååð¶E “'Ë™µ«ýu{1¶Ý=gøßqÃøÆìÙÒ¿_UÍ·a?¥þT"æq·o4u¦ \0òˆõHN÷¹+ýcºÝp[\íœc•÷Íÿ+jkçøþwìp‹³½¾gk[ïDªu/iú¼Ë<§àª->38+ Ÿà`¾M*Yì@8Æ 8ãKB¤c,¯™®Ï“Øøuœ¶š-k̸UYÇ¥o‚ ¶’7 (±I¢(cH(“ $¢H 4,¢‡(aX‚AÌ0Òiãsg›WD9;w$Tne¿f:|™a^ι·&ÚwGµ m[0ÐrOs‡õ#ª×Á€[3rì8ÃA– l¿ÚX ‚ašÉ&oü+Ðè³gÄOŒžf&k~Ø‘½Úé]d_:âúü¿Žôü¹jßgê,5ÕTÝ­DOö×h‚Õ„"®¾`åhßÛÒ%ä„%°”— ã:–I;Oqã³F¥)ñ”¡D-(\Ÿ¤Ï‡z‚Á›ZD T|ð:C‚l6ƒe  ƒeš1TL‚¹)÷ЬЫrí‚8Ï¿¨ÄÄÁÒª¹ eÒD¦)úX\¢î «–¢ýâÂX.ÐÓL1D@°låEW‘bæK@Õ¢š§åúÎÇâ}¯éù8œŽŒL²§«ú #E¯á6S%”±)IĬežþìÙ¥fè¡Lˆaf`ÙKb"S"3aãíÙ°ÑaX;¥))L–ÊT”2`‡»EŸ>ŠL6Y„‚Dg8X†JTb>MD¤¬ˆSQ("d )´2a¬ZSvPSײÌ5‹§ÓvŽ6³™’ªYJb¹0VÊRR!D²”²à£,‚KgNü”4P””,F Q…”f˜~ú@¦¢hM¶ÛDDK†Nš4Ñ¢V–g³,J³»F\{»44m8, b0²ŒJ`†DÂ’”ÀL‰K0®[}Å)†£VÌFSéa£(¤JjSº‘ÀÂ&O3a“E“''¢hÔÙ…‰…˜RÌ’”¡D³ ;ML)e?cÃÓû¯nsÂõ:”jk¼2`FÛ]Œ…œ‡,ãò·òmh¬¡ã~'£±Š¾Ýó8E€ó`,÷ÿÝüËþ›êõ?„ÿø£¿Ùþatÿ'ô<Ûˆvt–^9Èrvm!ù[”—5[§æÆ×ÙKk')ÕëÖouÑ5¼ÎTa1[†ÃÖ꬯ùÏ„ '[÷µ‚!Ò#vŽªê|MÛ‹òx]™Žb¬–¤Á"´ÂAñŠ&)8™‡´ìSIJUXi±+ ²¹`R&Š+#b[*ÖU‘ Y²"ÈŠŠJ0$6Šk¬%A Z# Žsþ}ºõý$¿þ:¿è¸3à…ö˜/·éËp¸Ý1>€C¼Œ hJ}(œµöÔäÓZKgß4{è~Eºä6Ú„ê%ÁÄ&åüÅ|’©îz»§ |5«ÉZŠF2Œ¯/·µšÓœ>s&?[Ç?nD">W¡9åûïöʧ>#äÍC¤êTJ•‰Í‘>ªüíß\wR*‘°RŠ˜¨Cç æ¥ª»­Ïo6û)•u ì‘CÁ†Ü h-¡„ &´vbêÇOJÿ0Õ6ÿ9?ø¤©ï1hr€t4Àø‡Jqw?–‡ü—‘|žâývSë0ÿéÞQgÂ+oQNW<‚÷õ…QÔð; Ÿa»Ò3ðƒ'dð}̘p“³Z (ärÛKøCñá8À`Tk¥ ⟶ǒŒ ¿×Ïé/¹}Wà°L¸;¶-µtT5VL²·|ã)ç>¯@¤ê¹<ôŠÃžs“âæåðF(‰1Òb)4Ñ^'ãv¼cöм„ù¯ôùIçISú£ì T9ƒÜ¸ýV5ƒ*šXÔ(*~ÙAñ›£è`ñ\VR…gÚ¿Áöß=pógVÀ"Âö§éêÆ’O¥^:òÝö«#´[Eä¶Õëò¿iŒIw”ö7/j›U_ ­âìòqÛÑ¹Ê ˜0ÖQT+ä81w¦¶tê_=”y3"¨Id%ê^ŽGÈ´ÜëSÂ^+Ó¦E‘~¢a;;û%ôª¬Û&=†JˆF}oL† `Çl¢¨)¶¿ÇÕ3±•d­µé9v÷YPe}9ÿ ƒ¸€‡¸¥>³k'ÜN7A]Î3…`â\­b P~ÉÝãÝ>|O‡;(«lÁ^­ÂÙËÞ·f’ÌQfÑŠºÅ•³ŽÿÁû0Œ”™M°©÷óêr$Ø–yÂÞ®v®È˜ÔaLã'9îUÝ ôD¥…(ùÛÝ:*‘áx‘v”9xÝ*IgkX3欻åóÿ¿úªóÿ§þ­Øáqðe/ƒÁÕÂ’Ú—ß×>î»øe­æK| ñ™áðó<]jwö? íÏOW0¢?zV ~~¼ï•Ô´unH,!&@íegGRs¿K¸BŠ-pbèJ+‹Î £-Ÿ|ô!r‹˜ú¾þ1_×W2ËmIø¯ ž³c_¬Ìèàídê­U `ª¼öOg„àˆ'(wÔ-TD? PÑb¡ÝVlíçÝâñDM¿Þcg åÅeT@CvldtËH?~ß'G)žy^VÝé]m üëûcÆvõþ Úá>SÛÉ!#„‘ÑS·Zq,‘Øþ«Sa®Ã#^ïÆM'wÀPþº‘^iÙö<ßÉÁúøs‡îU÷ls¦:.}ÿG5‡U{'ÝØ¿õ½Í¿çòtßO[£½|U?îßÎRpjµ¶-uå‰cÊÈ3vÊžzR“–À¾û݇}š?UêöâDæöSÒ¨¨"Š’@çÍë(«ß§(­ «ŠªïªÉÇÉÂýlúü‡h (#  ý«U‚ÈI'P9bÉ"H¢AÞ:ÙJ¡ˆªâª±U`D @IH¢аEEUŒAEQTX#Tb1bª¨#QEXª*Å,QHªª(ª*Š ¢‚1EXª*ÅV@AI*¬D"ÅAHª«"‘dUR*T@P"©P€‰„„Œ$ˆ:ú¸2¥•VÕqU°0`ŠŠ(ª)‚Š(¢¨°F*¨*ÄbÅUPF ¢Š(±TUŠ,X¢‘UTQTUEbбTUˆÈ"*„PREŠ«H±A@PR*ªÈ¤YTФHªET`#"¨¢‘T!TÓïsÆ}'íáußÑ÷ª6ù((«NßðŠÏH{{½œ91‘ÔÖ?_ õIJÍdÌš qЂ¨œ8Â¥4v§kÚö=?‹ÜÝ–= m¿Ã³ËÙfùÑY»W–‘±lMï×~Ï;§ é×Klo†mê…qºÙ-ìtá¬b±Y݇½‡Ñ ými’ç|lu;ùe]ñká6´µ{·_o“}ØR·ÛYG'ï ˆˆôPP Š„!çE¡U{S§>Aýè]ƒà/ø‚ð.Àz| CІ`V [ \°[€`°W m `e@– h€–àå7ƒxE‡&š€Þ"GÜQ-ˆ–Ú€UéûÆž¯áïÐd’ PªE°Z¬@Ѝ)$AŠ((Z%«QU QV-‘UT”R ,"€)IDU¢Ô´²•BÔUE¤´-b‘iU-ÉR-ZZµ±%¨µd*…¤¶DØIT%Ha(UYE©À,U€)$$D"’E `¢È H‚1T‘”‚©•Tª¡U"ªÔ‚Š‘QIEóvÂ2¥¡U"Ô²€3¥°’Ùl‘abØ…²Ø‡ì2b}WíN{M°,v·§¶•HIMïlLñY1d$À?%”`~j@YŠâÒâÈþjCˆmPBÚ2Ò*À±¥Ÿ—‹eÕŒË É*) $…@X ml¢(5‘lT"ܵÁ#)JÈÆeFd’H #" YŠ«@«þ:UT°ŸPª·U[$’dˆ«[eX(¢‹@ë¬"^€6UXª¨raa!U`ÅPÄQŒ`бb‘bÀHˆ,EUŠ«PXˆ©ßl„‚’’À’b’T‚AbEF,c‚Š¢ˆ¨#ÿßéI ÃC†M­I !jØ•"["&) X’I0 -’–-Yb¨,“‹D$UX !V*¬ "‘}Þœ²ÛÊ*¯(¨þÿ…Uºªþ„V€þçîþµµ „!CGÞ¶°ÅF¾aX¸>{î ~±'ä‡Îã7sþÝt=ÿâÅáG'KúžÛðøˆziîŽÚ5áþH‹éãéàlC´‡üǰ·mñÏ `û¸S¤›Ä0õ´(}l{(¡2»D°ü(%ì^ÃÝÅ[ܼ²È™£¹ @j±ˆ8Ò˜Àö ¯¤º™bTeï<à)%U|@Tí…Uˆ*‡€*¯b&#°$BB"ÀöªÕ&O&¶SUs:´*­QEVgUYH*¤R"«`DUjŠˆGϪ¬DªÆÈ#(T±TwÇL*”P,ª°u‚4ª±>ÜV”)D ¢PJYÃ$ ,ŒA‰AH*Å‚È*¥”‚ÕTˆ¶$‰l@YD˜© J´²¶ªª{QUlñ2*¬Ê 0y¸MF¹í+ÌÝP5ACØÎ‚#ôcX¶>ÃåsØNG`cî bm@„À=ljl€q|‚t»›ØíSí¯ [i£âÇ{“G<ì’I5øƒðû³¸šUàïötÞÐ7ÎêÅ·ëVJ8 «(æÕ ÇGrŒ„]Á±¯Ñý®ç‡ÿf÷¿œÄ=mÄÓΈ*;Üòº‘Qè½fýÇIÏú®“'PqºŒß“Â?ty¯§,é·îˆOJoÿ¿ä <›µöª.\3CÑÛú_Cœìõƒ¡ÐCÎ*ŠLU`ô{\îvtEÿ¾¨ˆqÍ‚–ûðÃÓ#g£ÓËûpNÎO³ÝÁ|^ zb¿Eû}¾B·÷× þ”aO'«Ÿ`""s›~‡cµ¹Ž¹¬_lSÙ‡ŸôØœŽOÖXv¢ÿ–79aAüH+N»f@ÙIÑô–oµC i5@;88ŒfB0!Œ!$Œ `ÉÍ´×ëòÓíÊ®ù…±*xšm¡â}¿ûÞGäþïÅè:áUóÁÛª¯€ª´ž2ªÄŒ`$I;eUˆ dU`‚nwj«•U{d°(á•UeL÷é$’nÙ“¼EUˆ‚?a%’,‘bÁRTQ@þa%Bó$’lê~Jªæ-$‚«æUW@ªÅU×j**¥ÛˆÅ|5yEÐç7©‘Š‚’2 )€$ŠADdÄQPcdX$D‹TE„D"¨ÁX1CrNUš=gJRF,A¼ U]J…˜¨˜*­–IM”B`I$®¦©mV "… 6 )b¢HÑ\€ ‚ªÒªõª«—2‚i[‚ªEUŠE$’*ªª¨Šªªªªªªªªªª¨ ªªªªªªªªªªªªªˆˆªªªªªªˆªªˆªªªªªªªªªªª¨Šªªªªªªªª¨Šªªª¨Šªªªªªªª¬*ªªªªªªªªªª"±Šªªªªªª¨Šªªªˆªªªªªª È‚ ªªª¨ „’0’EUUDUAcAUQUUUUPAUUŒUUUUDU`ÁUUUUUUUUUƒUUDUV1QUUŒUUV1UUUQUUUQUQUUUUUUUUUQUUUUUUUEUTEUVI$HÉ$UbªÁUŠ«B„Q‚ˆª¹ÐÊ«@¥UŠ¢LôÆ µ«%ïi¦iªPƒ„ÇSÙ$’hÐÍHò„ûiÆŽr`ʯ²«ÜoµÃó½Êë€DUÙ†±T‘k^Z­Iêf’*Ië0*•¤ u¦ÅU½Lªö @pÐB6æUUï|ÍÁÄ ¢µR@†Ü¡„fe ”-±¬>C€<;]èì—ÙHê¤"¨*ÁH"C$[–ÀÑŠôÈŒ€ œX`b €¤R™k=û]o&îéIJBC æïF®œ@á tA¶Á‰Ã åÊQ…2ƒ—-2Õ5GÃ';,‹Êª·†ŠQ›C|ÓC%¥ ”<Ó ®L1…6{ù©½:’I5×…ÎÐCþ¿ªÏò_€Êdªªà‡ÑLÑÖŸô{ðïÒ±yjàón HR²’ØQ"01Sn°‚/0ÃR¿’IÈ` ò…jÅ̦`U$>ßb‹™s.*š ¨ûLC2E€£4*¬A[m*†t:@f….EW¿‚«‘HÈB,‚ÄTXˆª""(¢ÅDUQTXÁ‚ªƒ±µJ²Ø‰ j¥”B*!RI# Å‘Eˆ2*¨±TDDQEŠˆ*ª¢*"¨±ƒU1b¢Å!$F a°F• Ä‘'P¨‹Rf¢ªªª1QUUTEDEEF"£ЍÅTUQ¨ª ÄEUUUUUUUUUUUUDDUUUUVDUUUUUUƒUUUUUDUDUUUUUUQŠŠ"° $õÙ$‘¢I$û/I$› 9€ñ@v6ƒî• mˆ¥…*ËmUJUHa ‰ "E*’ÊYI*¥JIV!UT’¥IU*¤¥P¤)RK"¬•J ªUÈJ¤•dD2¤˜«*P ¶[ AUa )E$EFYT«e)bŠ…PYV•Bʲ‘UjªÔ•IUU «VJRZUU)*ªŠ @]¬_°XC½Vʶ*©(”Ò]UqU[@P(0HÈAH¤Š°‚`¢2®ÎÞ‘*Äfa $J*BÁcalDX*P©!Cx0BXARd‘BĸÄ7$N$’~tùI$çÔ ‰]p³X}çðj]Z¬JrnPQ’I eH›€²"¶g]´Ä4a¤ªç²a®706cÕ˜BkrF`obhøNÜÍK– Ù‚êkˆš=Æf1§:f¼Å£ ˜õ’8ŠÆ`bøÄEv‡¦ pW¯B.– ÃI9 ×Z6c°]“F²”ÚjC³ BÍìã*!‚ªÉV÷ħ´ÈiÀLÒBI.% uø”Š(Ɔ%êǼª4D‰Mùaö2kZ2ÒÚލ)¾  ɬ…I”Îû42 YY,@¨AdXBÅA <®e—»òµ£R‰Z[UAb±UD°°Õ¯:.Zq–"æƒ1ŒDÂZ²Ú1ŒcZX‰lže4ÕÍúXdøm)KJZQ ’ŒU)ûÛfN.Ã:YMU-°Kl£iXj–¤Ãüå)Ò›ÄXÒÇnb,Œx§£2"&ˆµGx\TDJÖ‚±´5˜ÌKM´Í²à5”)Ù—wlÜÔ¶Ðr˜d4–S 3*ÛjµŒŠ­”±i9CQ4i°Q²ÖÔ(ÒÒðˆ‡27ÇÔ1âI$¤àË%xÉZ4†7(÷Û ÿ­†`úà @ã…oïå¬q-ÀR¼ï§’«­ NÉWA¹OVtºaQ{ZëÊåïÏ@Ê Û@ v_ÛïûóW& ›dþ|¸h×x]U/á°ÚÞÏå58Æì8èí²iF˜™Ùb† Òô£ŸfãÊ×êeé0Såi÷ü²ƒWŠäçñi«Ó'HµãÊÔd#Ìv•o¡"ÈÏc"ZŸu¹£ÅäÚÒB…UPò!Bâ«M)@à…˜Å† 1QB#êüéh^.à $/òÊŸÎc¯ÛwSˆ8ºb“ަ‹Iv.Ù,ä”-¯wQyƒÇÍZpí1´;Žè„‰ª‘d¾,ŸxËP¸¥òƒ¡?{ 즴ƶ+×H’öi™Œã†Ý™ †1àÑ£ 0€6!"Ÿnª°Xª²*¬Š«ª±ޓɣ$2ˇÁµDê‹Ño>Q:ã7y—ÌöÝW‚µ6OàB»QÍù m¸mMb©Õ¿ÇhvNR{ £ÊŸEðgþ/çÿ6®¹•@Eò¿*ªÀØó¢ªÒ*¦:d’3îÝu¤AU~P ª!`„JBÇá ?Ãå© f=ò ‹ OÁU_Ÿ Å“®Ç)$ ¯ÏÚÏß"ˆÿ%9ös"xrÂOÄŠªô(ªí¢«W>öëe·ÍaR}Ç÷íé öPa•N­OZ_ãJi†|Å’«07(aVÕ'6zŸË¹iáQÝ‘-ÙR‹4ÊÍú¥)ûßKúçÿ½7.烞1šmÓ š<öJ– »Ïb_‘šÇ»±÷+¹j¡ßòù«Â¿Ê hQSãt/¶þçµþ¯—Ð{žo¡øZµ('âRÑ´£À’»ò5‚úîã!©PÉV¡{_ìÁ¿þ*¿Cªÿ_u€iñ$Ôki0äêÕþ¶°@£4ï~_Òø†O)ûõ{öW\\[ŠçÏ_Þ/sÑ—ø&>.UU̪¹TDóÀÁ²`vÿ ÓߣôÞC¨:X èWÙ'jUTQB¥U*¥±mª©%J©JRªIJ¥©IU*•E¨•JU**•EUR–IC'ËTý-UrΗJ¸üÇŽ@a=‚èž„^ ‚ðÌ—¡1‡UoW6B‚£¦Ð Œ0>zþ×G´5+®{4$~vS‚ŠÀ¾¦Ž fCÌ—™aPÆCÔ"L% M`åë ¹ä*¯ÆÌ½µ¨^ðž“ñ~··éxš2|{±ÇÐqj8FA5þÊÒÉ¿ïUW™õ>ÐPQ}„.Ä3x[:máú‚kžïàe@C&{þê©î8zܛӬ€> 邽?-äf"( ˜ª¾¤ÄÇôá#þP*)éÖBD 1Š„(I10@CèX*¨o§“ë7Þ?ˆk.<ýÚ×U_õü_'IÊHÈBDÈŠþÝŸ½ò= ¡è¤÷˜8رÍ#¯éв‡¢Ÿ‡Måh2e »ç-xÀ"Xþíh)dÑEUU_±UXgœ¤ÓE¢*¼TUiI$ć59”`¿F€üwô¸yx*ô˜ vn¨Ü f\‡Å#ÌÙ‹YÚ?…\ yî3ܧ„Ïg^¼q®ã†ÒíõÁO£+JÝnÏŸ ©é=ßOô\C÷߆* 8ê …Q'ïý:ây=Î'¾:£ÊÞýÝíÈd †ɉ†Om@Û»¢á¯È7\Q@HˆŠ ( XªU±T¶­(«U%RЪ¨)ŒF ŠA€DŒ ^ƒžäüs½ôšƒ´4W0gU^ ¨¨‘U~Í(`DòRˆU@*"RREd˜Tµ$ª UÉý⹌¯ªƒ™SQêñ\øú?÷ÊKjETÑãé<ùý4´€¸Šˆ{ÕUìĪ ÝUuÅWXU^GŒégDp[6±góÆ èÙÌÃG .!öÌçþy$sŸÉ[3Å6=+sv~(ø§©°”ê9!o‚k»ÈnÁô ÀÿoµáÝKÅHaJ bØÀ€ £«°ÒN <¾-g'Jޙɭ8#½5?bRòÔë:4ãÿÄöß܇Ì;–|oÈünoÏô_G—×-néW{{uª«XCÒJEî˲ ¨ç ³¬9ïñhãèË7;ŽoÙyxjÉ#í·8¥ûb*®*,QWiUy¬YâÄ¡UaJBŠƒÀRØ#€É$– _7²*®ê/íí¤T@Æü¶‘@€GÄz‚ä™-úÝ¥õ¿ñäý_ëÿ§¿æú޲׊aL-é Œ}ÕÞžÎù0õGŸ«¾Î9§tË?—í=õ°z)ìÀ0¸Â9ã— "ï§RIþžó&ÜKŠ~¥'YÂõ£Ó–þöM.“­=È "˜×ÉõfQÚæÉÃÍìì'lRkxŠ*øŠ*ÿ»""*½GšNÒ Üv¥‘šÛàzs!$“û퇽9¢Fl÷dÚî…JÖ¶·gù`„Ѝ‚ ‘ «h¤¥R¥AUU’JªªTJY"–­P¥,¡B‹$€uwCŽ#t±ÝP¡—Ëü¯ÅÖ$Lâ€ùbÞ/‰m'áú.öfב7)[ÅÊ©JMÊìn„ B`°÷Ö¸¨û2R>»§“pŸäö]Ëæ¡çµ¨_Óètꧪ˜F“ÌÙ°9{}ƒ!†…Eó»íL»x÷yÅOã;ßÇÉp@N@øSïÕWÌW™í E\³áôgÿ*|%“U²I%t§†8’Òħ»ßîì¯ÆŠ¡›‹ˆxeäý¯ã~/ ó}”¦·ëµÑýÈ,ÍVV…Ð)¡Ü‰i_… ÓÃNù Ì@¸,L·ÀLuý¬6ºÿã«Î“ÐU²òÆéΠBM""‚7óæ4›;B§©î5Œgm€'¢û¾óßÚärq¶•WiUt ŸÑ[óî=©ç9yP@º€"Ÿ×øb¥*®UºªÊSÞ„ãÍÓz?×Ã)°O[×d´{Öð¡#ßWDXÌŠ~|‚Ùa$&ñò EU‚wj«*®V‘Qá@K1Á!¨ïkøŒžOéîwžbâø Ýdrñ¢ŸSpiÛp"(ú fÑ5rØ©0ž¿ÔëzÑQX*{@ôÊI,‚ÂH0„„„‘‰<ï| ûÇоÏÕŸÃæ@®@RÃÁ MÐåí Tƒå̦sà~OàùŸ•Ú¿æÍ›1r¤ž{¿ëPïI~Ô“ÊÍûØ‚?1KPPE&ä0€B¬`T÷eƒ¨.nPÌiØ#a5Á†¡N¯>ã²ß°ç=Óø>u.q%…[‘Ϥ°¨sdÜ÷—?k[Îß;ýíPInŸˆ(ÝŽ«Öé`s¼üý¹U]ÿ@éæ ŽÿG5U~§1úT"ûØzèyeŽË“À€L3O]ë̤¶šŒJ*ç¸ÕèŠÊV…üê$S˜¢ÿˆ˜îÒN¹‚ _£U_¶­™õ` ž7tÇnCêO߬Ó?Âîéæ^Qÿ[T„-P­Ÿ÷s?¯OØNÔ÷;”]3ìî”ãTm ®äU]à?UÌH@)aMP*×TpU[¢OíØÜ5ÊCè@sŠˆkª­" U{ƒÌ¨"«Óâ#“`4‘Vˆ@ªÊªºGlDÀwCýpEû±Åú¿{˜û/Y¾Š±Å‰õ##­ é•Ûðw—½•D•‘õv¹$9ò¸>Iûú88J)vt•´üïÚ°g‰L´ª¼EUýJ¾[U Ÿ4yßi“ìv̾‡Õã÷àô ø>»\ç|'Ãyì[™ÆjŒç=®*‰1jëò+˜’ ¢éxú[0˜¸oÐ<Í1‰Õù¡îóEyy>VNÐi©T™¿¶¬Öš+  Â$ߦÕk@» ‡.³ß_…Iøü|õÕ—±³ó{7Á<1Ç÷ü Œà!à=…Ãd»QT5— ¢µ¨óB"¢7û9ämU{È*®¿ÿ¾›Ê¾Ðë>çÚ%ÜxÕ¯Ø!ÅäùƒæÉ 8ª¸ü@A,„Ð0Ǥpo‰y(„³|µõóÃ8Ç7oò0 ‘¹Ô&hP ™¯ÙùÉaž1wû¬1ñĸm$Ý0Ïßüºíyœ;~^‘B†¼Hÿ¦ñï-ðUç–èXìÿÆh­èÐuЩVÿ(¸ÙÈ=ÚÚ¬ûÓ©ìÓŸä¿¥ÿ÷‹ÎÿŒ¯Íã~µ¬_¹‡_ÆU_0z•VºøCAK×ÚI$ ”IÞ†j¿“¬"Úú¼=Ö±çDDOH\Ó=/T\ˆž÷U`mˆ;Û!ýÏ Ïø’I¢Jªt¢*ªì*¬1b!ùœîévDTUÖQT ¢£ ôÿpnôºl˜Ö$”(Ò€Y ¯· Îà,¦­uÞ—ãÐ|µ½Ú*o=|:wt»ŠŸ¶ˆ]î´¬é±òîæþ;¬£ßéözt‡]oN}šTO¡ö߯V|\þ8ñ•WÞ ¸Š«ùñxÞrX8féð¨Qp~¤QV€K  ×siÀÖPYØõuâWÌbª·ÿ•Š7¾ÙîGw‰ü¿ÞU\Š«Ê&³ ”ÞO­÷ lsôá972YÇ^3TòºŸAn¦aìC²>5 äî ûâIÙftíÕïû³ %ÿïcÁÍNOñ¶½£þ {ŸÝgd6 Ä@øèˆ< ÞET¡0^™þ•Uù»ßM¹“3²üÛ¿ÔUu{†¯Öy»:ç„ò}ÿüû?Ž:>M)ôaĆÿÿµù©nˆüÞqÌÏ!ÊLŠwnÒL˦H’Nmø†p£‡ýžûÙfÀúÝÑ­&•¥ÀF‚$@ˆ•G‡üý+·Ò qPú:Bcð[7ž¾EŒ\õêc"Qñ屫 wxÕ/C!Ä›ÂÔ[=¥•8ƒ±Ì ,ÖÈ‚ ·`Ã"²: úMÊ_( ˆD7ÁþÌÍ¿r"`Ì!l›è¡GÚpÒàÍfñs·Õ$Enœ‚Zöð•7 ÕuÆ Ž Ú7´n$ÅDרö«™OxÀÆ0„:@ qBŒUEÃ;IR:ùL¤8ØvØ]<,èwq/;ˆ>GõwõÌÚž]š8&Îʦ½DABÆ @‚ªÌf˜n!¶*¨¤UH à”J¨±Aîr§Ü®.‡ˆg,z¿j(€‡@DL޶¥E5Íyës|-œ¥ChA¸ «¨à*­ÇÏ@ÔmMw!ù±¿“¿=µñ Gr'¯ô~…ó¾ÄžÐ 1ê> •í`öá†Çâ°:´†/ß\n³E•{”œÈ»›fU5eЊÕOnô™0>ƒ¦9·èÓÂÔþLåWãñ4ÏÄÚt}ü)Øì3€€‚Q1Å|È%A !€\t¦ÿóƒZ8…Ûj|ž³ÐàsŸ­ó´nféñêgAñ m—!F,\ ¼ö3º'6IO]Á05ŽÔO!>Ãâ(u°äÁ*¨*©)„m i-²ZÐm"-¡m!+%a ÖYY Ô•©*[BÚT-¡m’[d¶ÈRжȰ%´%KiR´•(Z’²’ÚØ‘´-°-°–ØJ…@¬¬+R ¶¶…¶´%¶Kl–Ù h[`ЖжÉm-¤- [`¶Ø[BÚØØKl–Ù¡RJÊ’B²°ÛÚBÚжÈ[BÛ¥´¨© RÚT-¡m-° i „• Ô i%jЭB²J••m+*Im$–Ù ¬’Ú¶¶¶BZª´!m [`©µ­H[H´- JÔ$©m+$¶ÉZÈ`, l…´Ym•„-°ƒñ;¯ºï³hr ªfúà_d Ç Jˆ>ë"¢S½L¨ ¹Ps¦þ7±£€08š¨¥*AIQUk¹Î=âðÛ~ŒN"€zÊŠ(¢Š(¢Š(¢Š(¢Š(¢‚"ŠŠ(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢|ù#åñêUo„$?áÝWþ{’^§ìÖ,‡€3g´ŽáOñz~'‚n=—2ÿ‰r4Nƒ_k¬7e â 0€kÊy¶ˆàÇCñ1æ.hX2Óÿ­ž*iá¼îÿ½ÆYüû\ü{7 ‚RLl±ÝÏÓ–‚À 2ÓJÁwX2¬%%HÁˆ@!D †*'ÈPEWÿy­'ËóÙ¼ÿm§\¶cõ¾wçjÞã_ð<÷“Ôö"¤ª°ETˆª›>ª•W†¼*_¯AA¨7ïèUM( ‹QpÐâ®Î÷ãý¾KÀVáÁ­ñЪ¿S¼‡¤Îræ»ùEdU|ù<÷Óü+¡`ÙŸ¡ÝwŒÉTTHS$a ƒ àR­±ZËDFÖ–Ø1?Àf ´„()…”xþgò­ôy ’!5~\LªõJ_Qg1òR&žA¥À K„" P;X#´€-}½¿èý›mïávò„ÍO÷Ü3J~ÝüU³¢\-©és®ÓùõÒ{*/_æèÿÑüþ÷'¶À¬UWŸó§mæ;ð„Ê!õO€žtðW©{–Š­Ó±ÿ•"ª÷õFa‘€a€c,YÝ,·#ŽÖ]–ÉKP™Ã¯ó¥Ü¿]dÕ”€DΗê.†F=¬w¨õÀ§ëãoqæ2÷}AïþëÜuÿòøÝAÕe6ˆ¨¨´ùݾOß{Üúð}õ^ºNÂÔ)¨ùpîð<0ö`\þ~¾àŒ¹²a Ĩ¢Ó.mŸgM<Å/Ö…"9Ho#FO›Gê×ñ´C“x÷j·öâ'ùÄjÓ1îGÿ?ÙüS½n¾Y}°`kOÌwIÔ ³ ¸"´!B©ðTý}›ntØä=äûbÁ­&z•_ˆ¸¡-ïbVžºÅ‹I Lð ûNü¼#)_ÿn`ª¿¥û9:;ÃvBãB;¿–z·œ¿~íY¿P‰ñP®œ=N¨žå×ê*uhª‘1†„Šódþê**¿/¨?3/äú|ÆJÿ«åtZÿ§òbZ·—g`€dœÕŠ=²üäBà*5Y|Vï—Dº²¦Ë½=[Ï«Z#+„³÷¬"åç½§¡ú/uÿõ¾ÿ{EU캞³œ‚Ñ·{ûÖþ¼Ê«õJb„!`9ú3ÜÄ‹M1¸Ó¦¶ô˜×ý»*L,´º]8Vµ¿^„‡Ê8öÙ_ ‰ 1;km\Àâ€a$‚*æPñŽ.“€q$@!@êåƒ(u}œ`!oæbB¢úDÌJh‡Qý›8Ÿ…W‹„•ß»öÄ$ÓG>'ýÓ¡s zdq{€Vä‚HoÕp×UTjup8&$Ǧ¶^—¨$É«B×>ð§óô?µªTqÿz° ; 3ôϽþ{ëdÝ™šÛm¶Ûm«Üwa¯Ÿ»ö]ï^ºoþ†ÏÚ=$'ç>äíô‚ñ8ó?Îú½ÃTu{úö?¼Y߈vú72ûŒÊ€p`qâæµ9ˆè¶ÏÞÍ΃ÍeÑ&[Þ-¦Ó‹¦I$v´M¬KS½/¿lŠèm T/,2Lñvœ…åw™…²\…”QN€ ÆõÝ>Ì·q69!Æ50ýÚ ¢7˜[´µ¤ËHu å9é(¢ Ù}Çü¾›¡ýòæðìyöé7¸…¤ÁU!¸î5É\Eç·[DJR€L8ƒˆ€+U˜QÛòš¾AƒçL§â}cãÏ?E–œóÜéªÌŸÀo‰°|.„Ð~‘§gÞçýØ/±ZØüº™ž$Ž[!û6g¯-.>U-ÿÉÍ lÀ8 ïp€ =Ü6á÷–¡çK;qú(Îè;rÆùoïB~`¦Œ"B\kúî9× 5¼ÇÕfθ™Â ÷" Þ)$”ÒZ¿º@`Åv˜™”ªw°îf1‰²$(¸¸Â$# ʨ¦46“”-¼šOÏÒI#ýí¦$ ÿrwÖÐð£øHªÃëáò["«GÃ{‡ÎX*Ð;b¶Ù&ãa±…žÞóc@ÃJ‚À…C£ 2NÌļ$ÐÀ4…d•Ó Œ*ÃD– )D¢28µ´yú*«•ªl½þÓÙzÝ7ši!’¤Òmx[A~ú"”ßV¿ëtñüXxmk°äÿ)ÓPË÷Y;Øh ¥·Èàˆbý„Ê™ÔwP‰¤wVÅ’{]‹ •J¥TU-X:Õði„Óï•ô~ýýïø_·ð¶v:4Õ|³é¿‡‡èŒ ìíq83Â85gÙŠ«³ü¼à3œ®«ê¹xM¬‰e=?öõx=S“‘Ëò“oŽsøŽïD(ªÒô$$¡Um_©ÿÏ þߣßÐmj='Mó~/ÈìYÅ*8<â*°½Ú‚ÕDUiÝ+*î΂2I#ÕS*¡#3¿EWdõ&]bt~ÒC¤:ÿdsäs.AC%%b¨áKƒlmñ»½È—ÝÉ öΠU_`*®@ª¹×:Ù8}Ö­aG+ª}^`[Îr‚ ·È{pT°8Ør0‹PHÁ4{áåþeEVŸ4ûÛÍ”e;ºEU? ©"¾Ïw£]w™ì?Q¶tb6ûZޫ̓©“ÄüŸÏÁUqÇ 8¶-¹”òÆlà 2t¡š­D8Eï$†˜Tx´Ä··Q«.¸åÏ—û.qï¤áø†]_'å5ÉåŒi 0@ë¦*ÛajVd’K娾 ©<{§¡ZoÂÿuá·gšž™…~ž¨¾ÊhÍä4q›51Ž© q6Rp‹;á“×Òš| 4Ge’I.t8Q€ÙÕ kB^³T]1PGRsÄ’I¼ÈFÚs †¹º`”TC°‡•Hˆgcƒ›UCrâd&LB×vµ+€¯ª¶*,EqMÄ̬NäÄ6MU¾^35"q™™¥âæ³Z$’jåÜ’Iº.µ4RÔh2èÀœ¸LÍ`5”„*â £”ºÍhÓ2æaàÞÍÛÓ0¹8’I5cÔê@$+$á u”¥(®éœš±¨&ÊJK:ÉN“DâMgÉI[”¨hM:Ñ©O©ÜÁ1,‡N¹•t`—¼$¦<Øð¢ë‡Õ“Xñó¦¹ßݤQTR)À}©B™«m[*“¡ç’÷Æf™Œø>ÞÔ4°c/™kXµ¬Ø~ñ|´>Y ðõ02=ÚÌ<œV,zRêØ€£©¾[ò†f{=vy±ÎØyežÙ ›µ »c1$#”ÐÛE²^Vfƒh~"ûÍ¿Å:ýYl´lÁвÂÈ R¡µ)6RŒ šÝª½ö|Npš¥ðW`yŒ€0¿©Äc6fC+ ©ˆQÂJH¢Áv¨a¾†rFm’±üí"ɳ³¢ ®ìÄsöºMi;*vY3,’$F£­ÑYCß*­èe©$ ›m¨ZóhŽÌ·>&ò&¾3¿³±ó¨U”YéÙ#^˜°ù.­•jÉJÞ9Mí«cÚÕ刷¶Ûq " ýõ•|ÍW#ij¦7ÜP±ƒŽ\ˆ`"€ $4PÍ‘³£#ϩٺDw$@´²kª¯@¤ˆ H «ÌE]oWk[l -¿•³·(ì,tr…l`#b;ç™iN(™´[i’Mê –ËÃl^.õeêK–ƒ$­”5£Ÿü˜~ÏQ7Ô Ç™ó,¨„7—ãã4 “âÿSw¼ÌΈ¹ˆºÑïé¥5å[XMÛY@e6L-è °, a2ÄüònÑ`ÉÄŒš¬*Ä[VÍñ¤Ù¿ŸÁ˜´ô<,çIB@UXsšêŒß‹’"h‚Z,ˆ/ ã„5csm¡Uhµ÷aMÖGó6xƒ¾ w+¾H²tY®y¨¡À‚0‡Rª½Rªù{ÿ€ÃÔ²i="¿¥>œö·Eº1UMlÌYjÕUUUU1¬UUUUPEEUUŽYQEb,Q „õÈ´°ö 3²¥€ƒ?0=vOq9³y Î1 0a~*ÑÔA0Œ\H'ÃÓçð8žûEbÃÖë+äR}¤y²ÛDXÈ¢ÁHÉgÏÝ„ŸH‡`9-~›IFS”°Ä+ûYo‡ßô ÚN=Ì@P$*« ¬<>Ù¾Ö@º¹$30J‹'!¡¸´üY $Ÿ`üC=^´·ÕÓ2’Q¥±){ a’Ú.¦IQbÈ8W–Òín|Ð7R«æ¹™_düžPǼßZ3!“)ÆsmRò^ºqß8ü¤é­N'Àpt.i”k)¬’6Ê«—1ÃÄÂGEf/ %¯g Ìçhv{%« ÝFcž²fC½b$àáÙuèfuDä¿Ñ ïPZ¦xICFC“)Üäwη4¬*²ÄÕº›Âo†ìŠëG]s ÁÁš6,‹7`ër„„ºFÉÃm@ß7SÏpt.ó8”Õ%-"˜kp4Rê–ÞÓ@yˆE›9/«áöxu:V.ad’Fã–Ù'¦Àô@‘"!’ IÁôD%àør# «‡nÑ“7 \çáØí“Öü§>*s·8=r Í޶‘ÀÏ2ÉþÚÖ†Ä:‹U¶b¾–©“Å(>°Ê hc'µ5ì(ƒñOö>jãæ§†–-Å“¯—.öª§ÚžÏ¶h¨»f©0 y÷ŒDˆÀ 3“#O—rP›ÏE;rÞÀµ‹Çœ+ˆ®¨ª¿_ÒÊDNü‚?»Ì§ÕcçkjLä©¥ó÷Ûž»é}e[é+Ÿ«åΙÃrÔå4ö¾4çö}œ\þl‘ªÙHT ‰}0§¡UUUJ´²f)5ë½' ådQð¢¬E¹}Ûÿß¼Ù2UáJcᾇéy‚¾ `¨iÇù!éõß²ÔóØìdÜ í¥vDøh›ÿ޾±Ï»âªèDßñš,† €cë;"Àîæ7rÚÓXš {ýYLuðëUWÞq£Œì¦WTì'’9 ߎ Hk%Ý@”›‹~ÊÈo>0hÉFZJˆÄiÂEi"…((Qù[=§œÅ1ú]ã }Åä˜|‘Uf˜ôè‰cæ**¬ê}³±Ùl–Bžë }¬cbA£êÓ>µvWºò\ñ…³»ªHÖE‘÷h&ýö"I'­3¶÷­KUdêA`ù^c¦%§fÒÇÇQ¥“J-$bÁ†@&¿±zûÍèçÍPòÝ’+õ/Sø;ºK•íÓ­©~ËÁø#WI:ϼø¿åû“ýgT:u§`[ªõz½g…Áþé´fÓ  ÿõ¨5¢2£¤›ÊO¿ó^âä¤TBe€?𵩢5(uø4 ú`v#Õ¶‡9Œ?EÓ#`–ÕF«b!D­‚ÄPX()!ZiÀÈWf!ÀiÚH² )P"…k*C-˜Â°Æ-H,*VE€¢"#hTUX£mqÁ#• .P¹eAr†!ˆbT¬°«vZ"(@Ä’M°X1YR«miUTY¼ÌwCUqŠVb¨‹‰PV ï PL(T Ç31ˆ…JÊ’ÛXªZYR((ª R2VVB¥b«mI7aDÁ&o¯¸þ¯ÙÊò ÓƒêgžžxÊf#êsj†m¹”É“è ¤UjXmXÒìžc0”Yd)/dŸÈcýV;d@Æ©v²ãÊɡ»/þy­×8s<1U}Aøþ ›úþT¸¡œ)ä{zpCï½õ ø_¶q#·û\co@@ñ¡TlJU®­ ýº~B,?í QÓÿ&ìGIGûŒ÷uíHÆ ŠÚ?†:ÎØj?5”ñ²nÑbÌLXù,&>É»"aW«X²6…0yK|iôd~‡2<Ñuå9Ã쀇yà Üwøií eeµYBÍ7Ô’H”e¤ÅÒUk®dx "îå'Ó®ûÎ2ÁP!Uí)§Ü*®&\øajuZòôSuª« ƒCÃûrxÚ£6à?±÷ŽÄî=W¡ª[eSTœ°Ä±Ç»Ö™Yµ˜à<RW)³™ ©‘.ðã šF5FCj©- ƒ' ð`8MDèCuÂ,(’ràDEqÁ «O¨J­Å6$’ÉYÔ 2Y=šÃXNTlÌšäÁ6aHV 0­bPP*­lPR%W‚ö(º”±è œ Ó`Ù–öj¨õ„ÕÇ N„­ø‘w5Cà^¨½ÇàÏ$ ܃D8ñ;M¼ãb|ÕKÛÃ^sÞQΞªŒPëcý$gÀ¦¦¤ Iâ›j !R QÆi™VE¾¤’IðBI&Sté*0n_v02®Â¾2¦–IÎÃL#ºKÒ®˜óÔ뼉¢{™†Ë-x’Ï|?F#Š‘-ZµjÕ«WÕ9ìŸ-÷ècB¶ŽÈÁ,lìŽ,%JÅ߇© hYô¨RʉdSö hÉ j*¶HN–á{”+b,T¦[¯ÓºZ YL‚…L!A" d.$cUŠ Ä@HEÒ*–ÓÈN£Ë‹´ÛØt NöËaÙR>ÑlîÎV„Ñ '/$ܤ”7Ì$þ%òÚ›,­€é)Hþ†Ïú‘ṿbÞ2ÇwB»Ž·Ùíj|ò\*(9ê)Ij#0à :IŽ2ÐÐ7ÝëDÇ=ä&xQHCâv{[¿©þ/o•rõpÚ°0`¢Öx]MÆÛûé©Ìâú2µ¬1Ž$0o¹»hèü’ð¯¼ÍÅÛR’ ªÙZ°Èk#\Ü@,I  †ÞcælM1 §{‘ €VIg^0ÆT¢ѨM`Sf³­xN¬ÎhUŒ0YÒÑ¢6†€XÅEA8´éaA!œÛ’QŠè³‘™$€-‰Ê š!èuÃ8k+UP­Œ•¬‘S5ö${ÎS£2ãËÊyñw‰áâ\¬ÇÆú ·±î_(…Ô.uµnWa$¨J'OÓöÑ ¸²)‡Ô<68½‰ö•§Làê0ZÜm?Õ¶“ÿƒº¥EÑ©xS o29‹ž«ö.ž½§ãvž›©Î&¨“Å’H@õõ¾OO>6Þ.f'«æ«…‘–ê“Í|•¢~Ú € eE*Pcgʉú4;É"g!ØÃ %@ˆ¨‡¾á eÜh$áPa ¹P‘ÔB¦&9þÇÞu_âþ=tðB@›OJkHˆl§×š«¿ËÃðrgK›fév,ý“AA)©Y=¢`!ý/þ}|˜ÙED 1›Ê@3 I„ŽÈIi mI ¦ÀuØ(Lãuû¶FÖ¯¨›ºå­xfŽ>~C¼P\ª ç÷ËÚûV±ÂD5•:Š’*w!ä Ÿí‹`w²IÄïQ‡¡.‰ iY¢š(ÔC³™‡ Z’„¦ŒfM®µ+`²I$ ¢ @K– P°:Ñ6ÕWU4^œ‘m6áå’å¶B€Hîô3²“Ž ¾,&Õ€¼C/é‹4…×S9?~ަàpž¡ˆž\u;åîéiXRË6ûPÝæNÿÚ‡q‡ú 3eUtç]ƳX„C‚òG#žkü;7mUÐ5¢ÔMs2AÑ 3©l}&W+pc¢ŠL2Rm€UÁUcÏ‘ypáÖÄ,ø²Œ'±”éí1˜D6‘ˆä<í”õ:r/V^ >Q±ÁitXâ»Õ¼Zä1§aMØKòl`ª·aA„Â*®}jò3oœ4ïÃg¶t€z#ªËb'+~µÃ«±0¶EÁ‹-ÌÛC1=ìŒu:öE‰Žâõch,ÍNý¿L ú²õÞÿ×}êêzù]­Ï ù;PÓÜPLç—Çüßšç¯ïHÌ÷>ùìÐ yK-±?©I/ѤQ,xÅGšƒÏ?küWãþÖü€ZçHõzÊ¥ßÍŒ—œ/GêÞ‚¢eä¶ŽÍyR6£hªûÖU³å³[ð,xBøVäYˆØŠ€¡ˆ.< ¥>^gžÚœýéF0:3Áq")ï†)Þm(‡©a—z4NtÃÌ…,X²˜wç6ÛÎã]k>W3b2‰{MÅqRÌÉ$Æx¥V'ò­測çkçÆŸ‡"ž ÿŠplî¤âaHL…³§¨¬b!v¾ÌÞ*ùÚñV½Ï ƒˆjìì:E-•-…@>Ö°ú†òb!†\ƒ+E0J•m”ž3eɨY²à¬ÂæQG"Q±(“lÃe5LEÈ2¶D`-`" AI‚C-!F1†0¬1$›A@ ò-.2>æY$„½ 2¤#pîÑE«¤…Içb„S<÷³‡Kc@ú vS>=ût’u_™G“›Nµ¼,[ÕêÒ\ ™2ŽX««K„_Á¦»ñÙ;LEÚê¸ä;®ÄûÙ"""J“ßEXi›]Úð $Ö¼$Ch탈CºVMÈ_(tª­‚ôèS†sÛy½žØX·ã)áæsÎ>ÝÀ|¾_”Þz¢ g½MftÜ(´´m¶Š XQ‰-ÌËD"•0´Ä%(J•kB´E&[dÌ®PÔ )žxDJÚÀÚdĹrö¿y»zî}Û‰Ù·÷s>½Š>S²ó±‹Ms. eS Zç¾*¯Qê‘ÝPÂUÃ(ÁX‰+léK¥f4ì×~Î:bçfS É‘­&%Áqâ®eµW?³ûÍÚwUOÇ÷þîù_N{±,·à«õÇä—j˜úãD¸é˜ah¤„, 6lÒL…6Y Æ\׸= y{<¢©¿t !ÐýîMÓ0x±Ëi–¥Ct€Å$A Y$$æÒ”©°¼Qàpâ$ÿ. ð¤*‚ñ@’áã í ‘Í$’–<`–­)”©bq:ÑÕ©#A¡Ø݃1deIôÓô– !†aµ¿™%¼²<¥å=å I*ÈŠgd‹Äå&΀OùÁ ¨MóÖÌÖcøÀ­;z¾?_–%NŒÏ»g‹Év}~Ð?Éw(èíòp;Ùî.$€È¯CºNC§°Ñ9§·“G°rœ¤ ÏX¹T’bÉÃ1ŠEÄ–YVE,ƒ¹è¾Jf‚ºó[%jª†cd²z‰¬z>‡p߈r t'I|ªªÀ ÅB8™ˆƒuαÕUØPPÿ4UVU]£ç “„bkç4ájÕ«^Pzí²YGDÛ›2&ËžFŒƒòí´l÷9ŽÓe:3o?I¶ÆÞé†|Ö[m«e’ îe k`ÔëŸÖz4ó¥•8[Üм"ªÎÄ*QSž’†‚ôÁ *ŒQ1QQ]SŽ(MwSxÙ–y|¿n""nˆ—ô·g„ºN#¦ÕÀŸ7fbÈäÕ%âLëZtg/,ð¼9Ó¿NL8ÙÞ*¥ËMÌ€†@Ö¦yiRü¦*©¯åi ÔýDć×&ì\ñ yŒHH½Fˆ‘DmãÇhÐF¤!! ”&Úªàlèa;ƒ¯ãu~ºuÍÅ<¾pÞEY6”w—â&, ®kÏ$p’ÍÁL†–u:À0=."bhœ¾ôا6¬_rñÁí˜l¶"Í-¨Ûjç$ƒ¼¼H `H\êÕÈ–C_pNŽ6Ñ”£´£fï>çiÎ;Ùx@@!”Mšæ¤]LúŒÙ–lªÕµbÔ 'J ÆÄeLb‹Ú>TŸ”†#ÎÈ ¾¨‹Ç75Ì «…ØQÌ`…°šˆ‰¸!:Œ8´ŸAb0"H/§LH}ºã<Ì `tq’ƒùž¯”ûmDu¡QµŠ:C[®9¡É³€íÃl>åûH×ÁüßÿuÈfˆ›,žÌ_Ée1jZ"ÀãÝž÷ØÕÒ›®ç®†8F)ÚŒ ¤¶0êËGD<}¯ü çß²ÏPY ËØ–õaç+ä áK¬Ð€ŒË?H’IŠÀ0IQIPRI]•  ¤m%`åH±$b~Õ˜„8RÙ •Æ_éòåCv‹ÃŒš0,H(êÈþÞ“»ÆÚSó HÒg6Á(‚&Æ@³%†¢"ÈXJÀ¬` ‰öɰ ¡+%I"$Q+*b$L$(ó’‘¾¢B›Oaaqíú¼†X`V¾¨J¥6c¾&?+· óø< ªèÖác€x¥éG,‹ŒRë¢l§<.‰@wÊX[{Ù -¯Ñðç‘ëÝ °,ùõÜýÆïØÆ:Ü/ ÊÈpbW‡EAU…²ÄUŠ!Á$…5øÿºýr…RŠRŸ-”P†Y`¬žèOi? ò¨¢¨Tñ’I H,‡ïCrÀÚg PSMŽí¦ÆöÙp2AlɺmC$¡1U\LMoE)Òú†Ân¨)«‚*!·¨oÍÉòI ÉßDÆÎøDÐ)»O›Ñä°ê«×g!sh¸CægÓ OCT¦º0rz`ÞÉœùѧK5a‚¾9ùO ¢}0ÚS¥ †d7òðt6Ί¶Ë gð‰DÆd Æ ŽKÓ|£Á‰V"Óå‚!e ¼–À¡Å5÷)!–«øÿÙü½Ïåy'1Ë»œkIM¥>û2ÿÏE¢@íY9ÏGŒÆ%ôÕ(´‘ÜàP·˜ã…jc¯‡ózÆÄOcìé ²Z†´ Ш2bk‘4Ñ‘CSï2²:#º®2,PZÀÛQUfQU‹1Å×åÙ¨¿á„}Sßo ­ • ¦sÌ÷ÙûÛtš›\­8 «Ùf>UÕVçMOn²ÈW÷çÏøØiŸ©Ïw›ÆŸ²ø`ûµµx5nm—îNiú±‚\°X#5÷„®•AJ«È±`ÅB^ê! Y7¢?_ïãb9ó«ÙDVP÷Ïóù4H>jD´["¬KjÚª’ÙÚµJ-‘lE°UD H²" ¨¬‚€*"ÉX P Å`(¢‘VÈD"É"€°E° Z´ªIj-‚ØZŠ«J²%µQ-üNÍ Ö«gÎ5M®³ªZ¯âUÕqT€bP}Ôu)‘©ß®^ZéÐàPHÂY5ÖQL¢–Ž\©N¬R„„L ìêÈ"d¶ п͙à)7Õõ'ÝQÕŽ¯¿¸gsÂc‹9¬‡mX `¨ªÄ{ÇÍžðÉ!€*¯¯*$2Í2sµV©DÓ\× 0ôSÞ ˜ÏS®÷[©Ñ숢Pi}ú¶æ«† jdƒ®ëÔ.S`xôR㑺crâªÛü¦›c¸wˆ€€°„!E„!BþßjëÏâ-ž®»j>JÞLs^n£ÿºöA¡/<ŸTºê£{ƒðõÿSáÝåÐ gP²ÆÚß=Þy='êžÇ¹5L¿ŽMüÛ¦v¥Ÿ±/De[_×öxîâ®)4è| 6ÿ…\½Ì§ÐÞ€|ú´WîFwÃäýóš?í§Î=våÃKIC™Œ 6§˜/ó‹f[ϪßÑ)CÁ2cƒó4æµñœ'”ê’a™sÝ×ã}ˆz«À„%ð>¬;ޱ°RªÈO}»Cø|€‡¤úñÎp¿O¶úŸ ýÉOPíå¼þWÖMŽ—*½­iÏžÔfLñ‘€.Up(Âï‡ÐÈ_Ÿ}q ñZ0ö¿&“£ó|€¹”ù"iÁVª °bŠO{Æÿ ‡©ÞNŸÞÛ¬þÐ ¼d‘Cûæåpþh*¯óæ7tkOôòtíh˜sµÆOÂñè‚ÙÕü9IØÚ–íLð7ô¨(~GËKÆG·‰ˆINJ*R 0DQ°dá¹Kl%–f@Ƶm7‡êüeþ‰…’NäýŠu¿¿âI¤¨¶B"Ø-”²$Z- jB €€Œ:ͨ©Ý ¡DÐÓT¥«)TD°³Ó ’:iôôÙýñÄ»&ØŒy, ¸tùwÒo­ isiÊ0NFCQ“$'$ý“û’ÒÛ#nûû…Ô¨" ¢ëÿFÏFÂsÝKÚuəήÂÐ=ÈÌCQÍØèÅU†ŒK7Ht¶~ƒº'7“G„ÀémÙ¢fP$¨‰Ü)D£l*A€È1ˆ¢,V(EQb°ùè‡ÚUS¯ÖÄö0ð5öYˆƒªž&¸×M¶ÀÁƒš.v&¶´ ­VÂ7Æ×U_Â.æI“rÏË‚Ãýž´LÁUwÎ’NM%*ýI™ƒ\ ×¹(ý;È}GªPc”‚ *[fl¦ «R"""¬Sø¤åôÉë÷Ÿm² [B|I)XXÅ™¬XiŽF4¿$OˆRG«Â“¬c|Rÿ46¨œp‹+*X^—ÒŸIÇ— Ÿ^ £<õj3S aQÀ¤ƒSŸE¶À‚kËë‰_óù–A#1ÕxÔP/íaÅè( èÇs'‡—”OØX¯•Ô©ÏßZË)g;rÄÊfüZ øðûN"„ýÚZ’“Ód‚B@„Ↄ8Äáúü'lyÅN–>b#|áU¬aªà\³0#¤ s§¦W Í Î¥: à¸ä(F£æÐ„BÈYDU]/2.”á¶t‡JÊflMxñâmC~•ðIŒ=HO$Ð!8dYÙÙ>@ÂRgÙ§~k!PûHH²wŒòÖkP”´†Ù5ò¢˜¶Ý˜Ö–´®„ã*f4ynTt@à8†P!¿UÁ³5d³íÝžªÆü‡¦;©7&{—ºŠ–«Ѡ PÑËF“„æšõÃŽÍ”€Në¾öòI%H`«èÞu=©íE+÷}"»éï Œ?+ݼC1ÚÕJïìuvêM Žk¹%È hQrØ4ÛEЇ¹È`ErûyXW‹›{§‹ˆëܯ+bU yóåS@ݱáw¾¡«’›C¶²ö‡uØv&¦t¹Rp°›j£: Œ-0˜ú(×\èꣂÞL.;¿±Ô¦fÑäàZÔStî ØóÖÂvÖÁ¤­VGŒ[xÖ¶¦¹ØTebÇ R§™R>=ÝNíØNLÌx-¥'˜£RŠŒd†;“ɨI9/I€ÆvqbM¾¦C’ï¨öeÄ„$*JUU–Ä’KlI6÷2‡ K3$‡$q,¶*Ùm–RªÈös‰êõ[UkÓ«RY²©^…èhöë샭Ơ뢚ájêø²RŽe5‰N(pBÍØ|žqµ…dêÖ mE[¼'ΘpÚ¤Z}*¼ªB^¹úM¦`DØàöò UŽ0¬JY;ä’LìÈo‚€9C@Úkðl„úîØg$ ™7 TQf\Âc³¬ ÊÎUÞRN¹EAK>å‡^ E­ª¬õ/©ÙE˜‰Å>ZaðÚÎPž!Ò"¡Q‹,’HŠÀŠ‚‚ÀQb± (ÈÅ" «EUAB ˆ€¤‘I 2$b*¢DI!TT‚ADY‹,*¤RI$³¶HµieˆDU€  )1EH @$‘Œv^}„„—7/ö D8 ¹íð ×ÚzÂ…µRìƒ\SS¨ÚníADœ• íPHKÒ´ $È–ÖÖÊDŒ…„’KE¨#1…I˜•d`ËJ1q’d‹Œe¤(#ÄÁ•=ä]+ ,‚Š/•Ì”LÖÅlâ[>d×ê]DÄYw(|´º“ž4i¤bÚU¯”z_I=VGµìžÏC6ÞüuYÛÍæ£t‘ë{ !®÷tóOLwHî¨÷cŒ¤Zª 3,m•’¤+"’ÐÆ1*W¦:Á‰ÒùoÌLÕæoe×[…br‘ð Ì)“GpÖL„0–tE¹YVË(r•9q«à8Aµ‘?l¨;A“p:I,÷…Qß#>±;@õA¼O'7YALƒ‰Ae‚Ë(Æ\¨ŸâéÍ Ë!(ŸTÈêñ­k3x ]Ëjnƒl"eŠ+ˆ%¡Jc ƒmLÀËnfFbåŤL²@™m3éH’I$¨I °ˆu¿ONs‡¯'®{„2JÑ(>ÒØŒ ‘ çÅUàAUrZeZ2Ha ¿»}²–”Um°_ÖaAŠôeO‚&"Ìl0¤( ÉÄ<(lì-ƒì•1¾õ È*õšKðJKïéˆâA$d$ŒYBA‰T„E¤ÕðÄ× ²$ˆ*ÁDŠ“Ê`R É$„$„$„‘A ”&Þ‘EÙƒ¿Æ6fÇ\Ï>±±,Ë7‹HH÷“/%óCá–PßÀX–;’w+Ï`÷M Jh»™'È(ô§ÖÌ‘ˆ"Ȉª›¶T¢‘P¯ÊæR°V¿By/<Ãéý?£5;šIâdÖ!æYÄö´“Û‘bÕ­7Ã4iäwçÅ’É=õþàÙðå "™szò\·V±b¬U¥(Æ Iúl‡C@qðÌ…k$°-!PjoÆÁò~× ¦*åã5âì ðsÁh°C¾"s@NL}Ö[ñ ¡9ø¡nJ›OF$°˜GO+ˆ‡/x3XÔD9ú¡UyU:úŠâ”`e2vÛÛÀVHmòtRÜÊåËȇr Hôtd"KÂp%øŽPH0ì „¹™ 6ºŸè§G:›(€@¦(ŸQA˜t6kR“éØ3¥“8¿g-Çéô(à<4’gÉaÐÑÎÍS ËF$·Ó9{?0S tçZØ ¢*†PÒºàñæTVIHà0€B*&© )ÿwU=‹;Ñå/á À]iCî ðûXÌÄGNÞYÚP•^J‚ŸÙöÿkþžÛø½¯ý2OO:+Vä+¥ùß×ú9ûN°ÉŸ™[k·¶çƒÁ_9}ü7Í_ÚYÁ2M¨ÆxxzuáLg)CSöƒ`wDÈ‘çïncÕåL- Ü«àm¨TïxV¸Ÿ€*ŸE¸ù«B‡@e¤°•|åÌí[çúW_A¢ ó{ó‚šÂ`Rý„¸=ŽÍÍÔ’VPM\³2‚©uŽ—C„Æÿ†ƒSÀ¢M=]éŸÆêþãµ¢uÉ„Ð~?džÏõ‹¾%|Ôîi|ñUM0ŒÈðHÀd’[ŸÔPM+h#,‰ƒç©~|-*Õ,¹%nóÒÈÄ’$$`H pSñ`*ë÷AÃWl8xjG$’O{µÄJÌKèøÚ&yÛ.©ùèbr2i²{€;ЃØï` ŒÒ"Qà:!ÇïÂþb¢E±‚ªn”]à‚ 9“$‘r٫ƉŒ a.©-±ˆÆ2>†Î>?©„ÈÑäÀÿ¡>Ki'-9O&FœñC7!ÎD«$öÃÁ8Š?‹ì…VŠ3:dÈuï ¶kžp óá«–UÁc¥îã%IË#ÇáÀ¼æäËbEx™Z° R Ù ½«ï— ~¬|@ô„ ÙÂa Aê˦1¾½W“‰¢G[êFÍëâhûË8ó®PÍUh”@eý›99RI­š­l}[ ÍÚ^®â‹„8„w´Gä ܾ&)¼ºU3‚Ý »Í»}¹­7‘°¾x OHI:ÔèÙvé6šgñ¿“z¹i+‰G¯õ]6qf¾Ù£QM¡cYTÅÌÀ:¸†ˆá0Áó"ªåú_ËË“+ ¦^®®/HR,˜0ü;€b Ö&×,‹m]·`TÈ¥™³ºÙîÌ×âé²bæ‡V ›€= XD›Æ¸ùz‚¤üÞgБ˵=åè — y{ÄYH¤A‚X4”IaJ•"R¶Q!ê9’O× öÎuHQc#Pô¡´`‡xÔ b{ÝÖû @¬ÁJïÂÓn8DU#üЙãY³%þR#NÒBÅUר0IûfI=€’8‹Bz2uLcFÃi ]ÑÖgBš½I$¡!ˆ Ä©1€H3žÏ ÀÔØL˜‚¬ˆ…*­D‚AUm°Ä—Hd(Á¨*2i¡hXÁƒ ‘(%JX[FÊ$e‚Œ$åÌ¢’²J1б¢IP¡K"ŠªI$]\pËŽ" Ä!" ¢ä2Ž4*I$ˆªDbDJ”c Ì%,#Ô,’F R¡º‰Ò 1Zº ’™² ‘RД‰C)$e$¬(–@A$‚ýÀšÚ`ü¥ˆÀ]4QD"‚•¨°ZbªÑ)€QTª­R•Q$Æ."ĆA&Ãá¶­A÷³—Ï‘LUÏn¾æ Ršøé€`[)šþõj®…¾€i¾?ÈqWѤº\KMÄlS)+‘TòíOwõßaÁ¾‘’%[, @ê»6A‘Æ'í?¦»Bxþ!w®©Ú[ÛY§¡ØC–Lë&ŽB)ï9Ëb¦gã A‹¥|í—9’oV£ðìê²O®ãOèrs¦bTE}ºáßa™Æ{Øæ°fÐTÖ׸ž?ßäÄÉ $“[ƃ Ï cî;ý(ŽŸÝŸÎq( þDÎh*~fàžò'›<èEU²=1¤Û99ùù’ê&ÂåEW0Vš %Œpm$hó=`5Iêf$’>æ+Iø ?Á"\iIH™™€‰í%ñ12@¨bJ\Ã½ÜÆ êÌ4äB`‰"¬`¬bÁ€»m…r¡”‹cÖ7Ì&©¶=Df·ydO ˆmÄV,‰jE¨û T‹D´'Ï`Q ª¡RE¨­‘PÁ¼”ׄÙ[t{)¼¤b†µo¶BÀíD¥vì¼ïÓ:âû‡ HŠBJhJ$g[´dÕw¯‰ ,œK ø´ÚCx»€åråVȹˆXu@ã˜òXçK1CÚP›gI$¶*s„Žû*¡K j¥‘ 0‘P’EÈð”Ìnl”Z«"³Æ†!ïºÊ EQUVH ÂÒ’ë5nj¨`’á,5àßi]x8~ ZÎ…4 .PK®X©e±Ñ–$ž¢qàë„܉½‚ÂD$±I$c@ðÞºÁ,åÊI x©.€,ª¯}ÍgßËK·“£Y%¡ÜÈ,&РÂvì×6œ¨ò¹E-»½uÑT[$’NÖ­k 0 c×IóÄ_I$‰‚”ЬP\a„d ™(C@ÁvË=‹j­«c•‚Gå‘S•‡B³r–3M @‘$HF6Û‘rŠ«ÁÊËÀ0”›9à°²º¹ïZo§X0D×#˜ )¯M «2Ed–ı`aRðEŠ´ž¸ÃB1QT™h¥"¤DÛ^Ìé(aZÊœL¡”ËÍ6PØí¼æfÁ‚^÷ÞˆªëI3¬È$l*L(óGßú5™LPâG»®ç¡5&sÄÊ9’#¢6'² -¥ÅS ­©Þ+Óò߃9òÂqêæå¿I$“`*Þu5/ßբĎ„ÁâäH_¢KM¥j0ú²t«Ä²«w‘=|k4»ÍL‘è6W¡"# &×И€²w'íÔI39á0£Îö3V¢eL’—`ì+Áˆòvôò?|ƒë[aÂ$N°„‰"!àkR)ÆàÑÅ.ŠcTF¹ àÎͺg!!Æ:k¨ $7‚tŠˆª²"«ÐP†B8†Á žLm…VÅÔ›ÙÛ±ûéŽË )7(Ó[óXn3L±lÙ¸r\o‰IƒN q‘¼SK “I2p ‹–Œh<ÔlB¸·üþý¾£ÞýGïúI Ža¶$s÷.—ËÝŠhfë©ñCSÜVÉÝØ€tÀq€¼!£×ˆÂ:·‡ÈØÿØô_+Òý§èõ^öuû6;>ë„[¦ÝÕ%–¬ö„-0fªÏ¶?|§àÎY?tìÇbz]elDBû'¤{žôái€@=ï´û-¿‰IÆÐº ÃhÞk¤ð6!\¹(3cWÊsÕ üð‡¯L9žÓdõE””0Ã33S ®ªð>n>DÕ ò3ÞÒ~·ÛåØ÷Š.¡UŠEUŠŠx¢ ãp8Ð$v i s¥¡ÞÕÔ·69T²°Û¶HIT ÖÀÝîuÜ«Øÿƒu”h‡ßÙý?ê¥ÃŸäsõ¹h‰¾t>Qèq¡‡Êè´{íG¡Š¡ d:qJ¸>¿ùø ÷! ™;ã˜êðé†éL9柦,XZ*’§³^øX!2&£XUX ¼‹?B@rÝL“ C±è39S“ƒ«-âUW†“ÖÉH•‘)FøÂ°†"ÉG™ÕèëQQ*TN=š·hÀÞ_çxa…ÀÜôé>,èY ¢pÆ2Pl± Rñ2å7„ÙÑÙª|ÕÁæŽz°Ä8«³ŸÔæJ:vµ64'öY,¤¬r Å×›q$’Vƒ&wÆ%”Rdr§¡Ê‡XxyÓeUtŽ\¡ ?á¥3«§Ô%G?(¿©ù9&ÖÌv/Çê³PêJ˜Eó§µHÚ J±CÉ3(žª_±“mlëÒ{²f¤³Ô:*É@âõÑ16!äÊÈ{ P‡½ëÛÅŠ h}¨(dµ`œå†ÈÁ0,’Í¡Ï>’—'Œ4Ó¶lÑÆk„$ÔPw¤G]ˆÊ»ì‰OD…X›eø¹9<ŸÅÀúàUM²ãÃ&-6¡Qj0aEWÓÞž¤ø8«ü"úO¨Ëeˆ¨( ‰ÁB­“ÁOGLPÐÂJ=÷Ma“ÛMóL–Ìì,~8®-\ªÏ‹¦v‰ä/Î|úoè>ë“ëûžV!èY?¿µý=–'šò`ÙMç±¢‹ßü:-h0ð?£Û÷_Q»îsž ×ÏØÃºüÏüØ·yDŽõVZ  ñ¿§ùå5>ó¨ao!žXr2ç»Þ—"Y¤ •%X›ìüžƒóùž«§ÆAg«©“BlË(KÊïYÃÝ?ž@dÁ€C ²#€B¥`I@‡0çåIøØB#[[ñd€8ÈTà¥ùó÷¢hû‚Ͷ¥µ9²Ô@ Aª¬¬ªˆ¨Ä‹2«”ª[XÈžQ«:[n’¬ËQws $A2[bÄk&Ój´¬™B†Y)WŒ4TD-¬’IBÊ– +E(ÅQ,€¬A K•p\ÂáT©3Y‰†P¨‘ŠÁ«"T¶9–2QbZUA´¢ˆÕÖÿ_®w¡Q»»Ö·©$’˜Ú›µÌÃ5¬ÂÓºãñ×öÐà Šw!S’‘Œm Z?ɧö(jm‡x±Ÿcò¼]Ýèþ»[:DB²ôqɉD¤¹ÑNˆr¦øC†€P¡ÂÊž“ üJfU3&ÃÍ"³Ž#9a òNTžŸl–.AcŠÝÇryŽ9j´ûir€ÁmNŽz’I%äÿ› øßÃ¬~?BÌÌ'ù\äbM%,)Û\*?ße6…!‘YB F–[¥Ã.—ãâßVÿ7spü÷Ó±Ú_ÓV]Œ³4à`¾pòú,öÆ|ê xêÀÚ³™2€t9ý”Å»”)‡ByCqúê-IÎünré8b[)èÎqœfP¥'Œ’I’Å PÑ3$X)6uZå!¨Š„ efÑìbD;NEX*;dˆ|"ƒBÉ}"l*¬@@Ñ¥•²¯]YÌvö’&öKAô°5Ъ„ ¦3¼ž©0ÂzWw1§!!,œ„ÐhRªÚ«VÉjD:ß”hßxüÿ_û~]$’lšÃ-ÊJŠO­CüÌÜb¿ RV$ $”¥A‡”²RH2$$‘9mËŽ Ü2ŽE…¢3ÌIR ‰Ž!™“3.PÈPÆUIdcmeË>À[ŠÍ+ 犴RMT¢e]„’G ãû>À(8ǃŠUÅ<¶Õ¿í€û¥U¤¼m‡Ìˆ©æĬóož²æb†Æ}HtèLà4’ÊžÉ>$>om%Œ}O”ÌËjc‰V%6°UÈyˆi†­ƒl²îLi<ˆyµÃi¦î£Ís99‘´E<)wHª¶lÜÊn92€g!àÁÖ›R<Î¨ŠØO>VO¬•¹˜,XòsÞzÔ xv-ü `Z!xJUZj¼Œ‘Œ Ä6VC}3…„¼j!ãLH°™ Æ<×!ÇÈ—át%p ˆI"DƒÓ¯¶˜EUÞ0q +/Ú[ÆŠ‹Ê1ãô¸(WŒPC1Ħ £”°lñÕWžbÆÔ°¡KR°ñ?³ÝðS‹º*­æøôÄ EWWC2@6º`áOÂŒ$A’‡Á-xõR¥ðÊå·ÈÉañ Ö‘®A&´I™†®˜šÉ f¡„Û˜…éº3F™a4̞ƌæ”N=vaƒm,Ê; MTd¡Ñ(,q•Ë4éÕ%7†qdÇ„”S„Ø1˜Y­V¸ Ò…¸ÖT˜øEI#²yƒË·Tíj¾¢ùSJ¸™œ0zYd0{Òó^¹a€… q<™# · O¥*ñvS`Vð„°yÅYôÝÐ@’g6ËRe­ Ë’- ÓJªäÝd1lAUX8!j¤Df”Å&L@1U’lóf3!”ú ¶ÂDÙ¥ bØÁN†Ú¦â‚Eƒ‘ETƒ “ú˜ÇðMšÂØà«ÇD2B,†BüÕévgÙ…é¥_fžÈêI¢õ–Ø·HÈÙÈ+¤ÜnàuÛÉÀt¡ÈŒø¡¿ÃpJÈXK±piUo*EˆUE‹KÄ[J0º¥´,ATR¨Å‚AE ÔX¥•)„¼ä!»“rÃsün –ÜDH•¡m¥’Ù’`YÈ^ÁX”UA«¡gíöÅ|wN«!yëºeº§«ª!™bÙ%æ©Ô¨wôËé$’ZBC-ÖJ2*”m®”¸•¨¦@jJBˆ«!>œ„Ð=ààK˹2´ÀbíÂÅ,eiÞòš`ý¿Ž^Yå…§b짉BƒÇ?}î»Úö¾»xO¿nû•~ü\‡—Æém–JÛVÚQݽof÷J)oU“=ðÀ©ž¡WË/*Ö¼«á­W&“OÆ÷ûÞïú¾Ÿñ:9ÿÏeðyHR_Oiì5èqé¯fqsŽv{4TVEAEdHŒŸ|õ~ Òjxô*hgi&Ëq«è«›þzÝäsLW¾ ‚þÑ{iĦ¶uîO ³6ñå¢oŽ èx¤Û–¹j˜XºÕŠJèL¥«e”­ˆ•8n6T ê±’Œ§ÈB#´ES£KeY›ã-ké{7 C¸{ÇRÌÌÍ£Ï)…[®ž‘ÎD¡TÉî>QÛ”ü:š½ëÊj/`ŠGPCÈÖλ+¤îß­;_A-+´r îà“ÎÁÔ‘Ow=8"VI7ƳLy»ÈçS’÷d8]U»Ûé8hg~H&‡3GÓ^:Â0·ïÇZJn¹4˼8µÅ1Þa1üx{ãÊ~ã?¢"Nã‡9»ª\³¿/6¼´º, `‰…IëÙ‡©nΜ`áÚÒgΉ‰Œˆ¬ë&\ãi×e ™KÈU<„ð§‹®[ʶ¥ÄÐ¥Éd./p6Ô¡qWWY^uwdh,’¤]„%›VÍj=œ:ÕÌ–ÂÍ@BRî.G!Å‘äºáè·¦›´l…Õ³ZVÌs¹å'±l.(Á~mX2B¬ê£ÝâPè:gS¤G­³²i<òíìŸÇ/vÀÊš¾¡,›\¬¦9҈‰EeqSr²•Všq¦…ûнN\×1Çzxëg-Ò):¸‡g¿b/µcc337§0ªõ_£Ñ¥^N¿iñ𣿾†î¹wÖž›šEœ“¬¡¿Vü[—¥z¾îйÈäcs×”ˆG •Š?ÉRDa£Ô…  Á½DD¬`âÅA ŽÈËKå¯<߀é0XæSºó¹¤·âõLðð87¬ðï.LJ™›ª˜ ihvuÇñ>"¼ QL¢ìù€"UüÐñâŽýýþJ;;±oq‹‡w;òÝ.K«´v–™š¾Çí½mü"8QÛ)ÂòéD0/7„Ë>úÎ üÒ´ëj¼3t¿ªŠ~Üþ¥%¶îKº6ÝNk%Ic!á9¼(ÓgŒ›EŒ²Ùl.¡Rk%#ö gLÍhÍBSäÝ"nøQZíõ²‹•%Nüéãë";×Á—ºtc332P˨g_Mî+̼ìg_^ŒËŒÁMhé$’Q¬|@ö|&b™”™ö·+m‹iž"¸’´`:©¦°MÑ¢ˆ‰Apgo¶Áe0MŸÀÝÀÕƒr;™5ã”4ãŸZ2]¨ºÛ¥Õ´ö[¾éÉ£/<™Ï9»çwÝçâðå›ÜÌoE¹oZ¨v(ÖÕöÙ¤$•œË-¶È)s1J˜€çÿ¯U×ɆÁ.¶Ç4ãA¥À ÁÇ-˜¶g`ã~jw¦’›†4ôt:%z¬ G´Á6à >“Ðb‡òò¦nͬÕF{qK[n6Ürf°·4æ¢ß]ôšã=ä¡ïýÿÛßÒ&OúzN·__Ö"„”lÞw ê,¹`ÈJÃclÃl¢UDÂH†Û’Ùë ºŠ"w˜W²|¾+6‰‡Ñ&4&—™øóKµG¾ÉzЦŒ æé›£½3bsiÓš[˜$œFqѬFh¹  Ã…Þo¸ž =Võ"$R:éèÐRÍ80§ãÐõZqXLÙ«½ÉŒÍ:0Ñí˜Žä Œ)”qƒÀU]šºšÂ-²ÞäL°2àè~pQ<„ëi»“sIItxµQ"a(ˆIÓuõl¬I Ö¤Ø!YƒüškybLÅÜ–² —ª3°eþ`̈H ú”pLœ2äT´&J^'qe¾bC ÷.—…æ„óO:ÌÈ ¤‚‚2 Aa!€¡B( ¤ŠE‘`() °H¤R ()‘d"„P€(  E ¤‘dXE )E’ BAAAAAdXE‘BÑh[lˆ´­["ÑiH ² ¢ÂŠE‚„€´ž…HbÈZVH«-«jAb"Š*Š(,‘aAH - a-Z-’Z¶¨µ¨ÂD`,‚Å’,‚ÅA°‘IŠ0AbŠQdа‹DP‹B((‰,"‘‚ÀXE„’NÛtÈ*¶Å…UÃJªÖ.¼G\s„7=$ÆF É$™ X‚Ä(8×¥¤e™m)RÒR ‚AÂÖE“'ª–Cka•V–±¡8|N»I.fx±ÿøåé6 †ó`¤Ô ¼Ùmý†à_ð[æy/W(ϵ2[;<ØÊRaß¼ü›–},/iK\R0¬¨E Ï@ À§F´ˆ€%Î(ª±xqÈkUª‰­ùýØÊN§ÜÕóëÐåÓ¶]$ã|dL¢ø!²ÜHEÛ!ÖŠ« Ù”2IVó²ÕU¶ùi#ôdNÓòø›ËŒ4DÞTËЋRÉ’Ji…÷Pc=ÌÐÎI$D˜ÆÈ'Mföì-ºÀɽnš†m¬‚›=—z°&ã ãFßý¹¹“”^›¸æfE̲IˆBCÉ/à âÖ݉Mf…DÊ¢«âÙ æ pšH»$X9”°¼o1SUX³ ŽDâXÁ6(k+*Q¹Ö=÷´á„?B7< ¥ó ùÝÔ·ÊwrWÐeâqwŒ¶S ð+Z99Ÿmî~׃ðú¿¥ü î´Û¢˜jª–ZÔkìÉEf\ÁJ6CÖl¨&>m÷9¢ûºÝ¥ßùþ6ï·&µ»µ‰”4“ ÓT’”"vÖKÜö:’“SLŒWµ %GHp]qûo»Öm„&Áûø±w±ú7ôÁte¢z¤èx§å3Ñ{=¹ø ­¨L9º¼‹fš–D4!l¿giŠf]ì~M7c'´X¹}ü‰™)™ãQí)ÐýÜ÷îÙÚuK³ ü䄦]éáÚ.YuÙÔ¬âÉX+UÚQW—uKÜ‚:R óQ­ÌCRD:n'B÷ºÎô¨³ŽÓ¨˜[² Ê¢&Çãչåçœé훦L“dÑt]Ëœ¢Ù.\1ÛŽ†âûåÅ¢3­™0L‘Ã,$’:˜tuâfº wŒÃÖç$éÈ’),¦V3E²H «á<¤Ê[“JÛäÀ¶ç/¦G7®kQ{ö?ÞT|áVVÑtÓ„`d¤¥Ž’„UYT1fN$¾±òÃ’“]‘>–‡V²4A(‹–œ”3v ´dܽ¹ ˜U]ÑUl*¯<ЬÃmÞNM…÷‘@åÝÐÊí/ØêûDDHB òµV6¯HV,8¶*Ä ‰XƒWN˜TQDYF+0É€HéÉ!4ŸkÑ>rWW-¥R´mnnÍ•í>ôék§'uåO¿8xúÎÔÛÈé¥gnýâèK5½ß“m¹¿;û=ÒI&îÅŽªÌ€X²²p9GZgd{gßðþ± ÊNÁ¿6c‡jFÙÎÿ`PëãÞì%¹@ÀMˆé…üÃ3;èŽ*œ/Wq|³n^TtÌÌ  EW[C¬rõå!@[!Î;[™­w>Ì©–ºØkd$zxÐï&›Ë*)´ÕÝßá: “lÕUðÀŨ¥·SÆë¢v­ÖÕL,ëÞOè± ð@UÏ>(¿ "vÂ%ˆ…!]ÝÒ•­D´cKh²ÖÊw2娶·.dñŒ™#1¥‚¬c ™n+a"ȲTLˆ$æ[ßw“Œ ú_q±véD5êZI¥Íòfz‰™Â €NàéLÚÃvòé´ –ù3Îo‹*#Hù;Ï«¢È€ØŠæÇ@Ê7”¶HlEESNg`ÉäX;[ÜÙ¦wï0PïaÒjÒ—L(à–X…à.’*é Àiˆ@è–0&ôòSƒ‘D­E@¡ÿ3³Þ[*žDµ9´Ä•%l S×ßî ?w–~%½7öó $Î킪äU\Š«ÁU[&d2Íe… ô’Nðèt%Uú¬ú¨¯ïd4Â.™DØ!7ªHºŒ„ï2ÃÜo˜e _’*¯¤É€i5 »ì¨*ìF”U Ë1‡ÌÀ%I¦J„* @ŠIR‰$©*°6„¨eIRÆ(TŠ((Vd¬„Y„•„Y BcÆE QbÁI²Ojw#!¦n¾v…Šóâå®Ò¸0²\.ä H8­±‚“i uÁ×ñ`BBlhïIÒÄEUP“ÚÈ,’ §À {-Ih é>Y ˜ ÈÏËEW6.;{É+¢ÁpÖPÂ9QUçÁ#Ô‘£Wyº¬«-[mª– DDdD’ ©äŸ'ÏjÒ#üä;S€‡Ub°X ƒIâBìž]ôu£[ç@|hÈNGV®GT©iêì «Ðrƒ%^Dâ3u!|ư-ˆJ«²»ER—QÉ‚HaA‘L±¦ a§"¢Ý Š÷tÑP¼é€{þP-NfÂÙQŸ µ¼wý-IÆÇã% NÛuÂg NyÞg:¼¢›,¹”¨#Z’ïGšÇ tÌœŽ“A/9a¸¨Hªð<&⪵…kFC$q3±4sqyI¥E G(1S!k²Ð¢å¤¾Ä@ÀW• tåÖÔ9ö¶2¹4F „ŽÙ”Ί¹ÀØ?Zæ”PÁoß÷Ò{P4{(pÔ¶Å™™‰=ÙL n*¬Æ‘È$ÙÂö¬ø¥‘è¨ZÚUX^:`D óòwƒ¿áw>Ü}Ïöß3…úùø? çš“‡=Úì|¾rh·#[`U:úq>Éàz0˜À0 ʇƒÚRÒÄŸX÷‰Ôž-Þ{°ôÕÑøžÓNŸ‘×lãéûSÞ¯›<÷iU{z±.A(¦ lA "¬ìÂRyÆÇlø”•9$¡ú'ÞÖAøðT§rùÀüÃà n2[gˆŸwI‚k­âÀöFÎ 1ÔEŸ‘eU¥Øâ|üã•2á–˜Ÿ‚‚p]¼¨($UŠY^z•d€b±a1VÆLu uÛŠ"tTæŒ%•Ø22E„Î6å¨ C¦x¤ÌÈd‚F“Ó ?Mz3 îC¸’H¢ŠLA„>ÑdÙÉáõû_(ƒæÃßa `Œ[Qie––YgŒ&«§ÝVóÙðAÛºÜWêN ,X`ïò¨Ó=¤°÷ȪÄÞ †›¥Ó…ÏK‡ Ur6v¥äd„(T¿¹j$Ã2d† üÙPŒˆ¬#’C6ùò!F"ƒ”Š7óÀ ÏqbRñ8´‚A"BH©—5­m›Ð@TsBšøs?cSCæHz4 Al Î2»z=¢‚Õaˆqé=¶ÖT4’åDIK¥eEWÄ%¬R*ºËHçŒEµÂÛ´Pa )ZŒ…r 7i4ò¶ÍÄ ©"dÖUX%­c.ª²ð\PÀÊ#˜äÍów‚fÊ(kÇ3÷04ÂeEšñœ%àô¼ÚÆ®vš 8+‘ÿ$yw>¡÷ù¿£õÿŸÙà}$¥ÑC9=Ÿ·‹‰ÞùéÜ4MâS³S‚Qç¨=wøþÏÓíýæ¬L' U8ü=®› õ\m€ ¬êzw÷oçƒÄÚ¯yÅ KðÁö%€°Béé,ö…8µF:Ù…¸ôP$EL`•t³æØÞZRx^D˜ÿ¬Lðµ ð?Ä3Ë™YêcSÐnG-f&FS YXL¦a·$Öœ…Sj›¸8 Kf3L³1WÔ§ñì;gïD…CÛÁÎdræÑЊlLH«»´a©Ì7iPEˆ!ÓCé$’Š¥®1;)‰ûÌœe[œts“5rÅ&[xô?èlgZüKŒúe(JP[CÄ ´©Ð C€% »Ý¹1÷Ïî—”ñê/µzãR­åí7ÙtC½Ëý/þzÎG(œÎweê¿Sæó&L¥0 ‹']вD‘zŸ/ïÿ Ì;S(÷G8¸çà 'ÞØ¹êT¡Š«ûÙ†Ár'ðÒw|_ðÙµò=nS‰ÝvAÇÙ“é»hI0VMÀÁ;žfÝ,´rHÐsÑ;N⽤öl78ïxK𤉭‹"²T©E¥­‘dê“ëùRI$òQd'(pÕd½wÁ¼<8m6®uŠ%¡Åf…’!—Š@ú(fº—>mUj’É8q÷_§¬ßS¥u[réõØGå Ÿ" ûd@Yè 0à 0σŽ0ÊcŽXGUÞ_9‹ªÖ™ wÔBæG7y«®na§>ŠäõièÞ·¢ü_˜rk™1ÉL–ù=ÇŸç¿Ûöoƒ­²lM;Ak=FÛWMì!¤õS곈늟ÚëÍM¬6XÞ¹DƒûD¼~a†"’IE’Iý‘÷ÌçM5MCƒäX,[8fîv¸ØF.Æœ zýÙ-ɇÜ0ºø£ôœ "Ç¡tÕ·Xöj4ìTëUäD Á\y[=¼%ÝØœþ:ILf´ÚÔ9/ƒÃ{òÂITa*‡ J Pè¸@E¸Ã—Û"*×g ‡ý‹#¼zî#ë}Ñd½okaÀ€«L_ÌÄw6 ±†rSN>ïF£û8ÙSÖÿ¦biÊ)–ªÐT•Z(Ù†œ &H—,ày&HKùÔb¼„>uÕPßî<ߥ¿äÕPUúßÇä?Úïâ %q1¿üŸžïý•}u„µœéN6Ö;<,B¸é<¸éÔô³{±!”BuHJŸŠ=Û¤vü6†îÇyä@;ùË[/.ý ­«Š¤ …¶„܇»FGd›ßÌU,I"¥Z|¬Y‹ŽòrØQ&”³Æ‘𥠔¶Oï}í…Ó²ÈiÂÜË¿;•»%«Ð‘Í΢ ¢øA ´Å$MfÈßq1ÒÞüO®¶¨d]‡·’’¡¢Œ¤ÔU왃Ìû´á™ö¬ç%gT)«gÀ–(•è' +ÐvÞc¬;Mè5¶`V’grB„™©õöŠDb ÄU$-22½@Ÿ)½¼{·Ìö¶IÌ¡2™ŠˆB§aýú´¤TT¢ ’‹ÈÝ6wx<#—Ìw_2ääñ±è9†:r`ÍOD5¤³ …ÙIšºöòéòx•å†22q™£á2C&`Laˆ›ÜÙ3ñlÖ ÷N¼$]¼I~¤'ôeŸó|^ç½ÿ'«¿õß÷vWä7Ía 'Œc×­!è´oÍñ’™7…4ëqoššÒ[6BGÙùŽ¥ï¶ÎðΛ³5*­ácÒöë eÖc¿Õ¼’7¨-”Úòù•!NÌΘwpûíÂú©©uÑïÒ"“‰™%*zN=¹QPZh’Âç™<8n9˾™•9\€Ua´ ñl—F0öRØhB)Û܈LC"ñî ä[Gvµ®#ÏL­Ú[Xð‡Pšr¡†t^^?#¶§çI$ÂÙ Ïc6w\“qÃ…3ôrâ‘ÂÜ£ÀðR|tˆd…TÏÓ?{/n8ënfk•0ù~ë{çÉ5K~+fFà¢åÌ%b("R™€c°*+Q1Ìç-¡ÉDíüÝ­‘Ë»¤Ý¤M÷äïfÌ˦òBø57‚ˆ¶7WGÃK­Ï·TÄ´ýÃ?Á>å–Sß_YP’%…Ê+­øê¼þ<ãà:r ˆ‰3rò«ŠÊËb•ÊËŒ.f';àè¤JÁ¨00€Âp × SyÑ¥ÞÙÊbÝÁ3œ²ãxMQ©•ç`jÏr²*ª‡äþårgr¦ %6Š$˜êÊ 4œ>N °JªoB-jÝ3ðæ¿{¥å‹Zö 'E/4én®Žµ¥TÌ>/)5؇ËàuÀ‘Ñ8uá©Øvq©UÓRW?KÏ Ô¾Ê;Œ—"ý.ÆLI¢¤ì)c¶Œ ¥Ï›9¢ý¦lš´vŸíá¾_=Ñ*«ÊÀ/FFC_“ãÇâ÷õíÖsÙbÅ~›Ö¯wv´ï{Öþ¢ÅâOë6Yç"PO1TI˜'™‘8¯ò¹tOÌ:ª; Ñ=yɤ§>7çéöºõwáJݘûþ¨Oxõ×íˆÄTPh~ƒ{ËU\†É ?“>³‚‡­](À f”¼pØ$ÃÀÄžx-pMÜËÓÄ+õ4/é1H "Dü¤bÛ-¶-Ï4‰úaúþéÙNÞØí-,´«iJ“ÉÃÓºG¯ÿž$’OÐ{ýÕðaÐ28é‹ìrªc‰€bfÀ\0€`a 1á‚Ê?™ZHûÜýîÏÈɰ²‹3Tjà5p«ö‹6ÇwôR’a† 2ð @ˆ !É¢9""GâÿGãõ½Lå2wg]ÐýÔžÍÇÙ<]¸Ù–!b~°Üš=$õÞa ÉkÅ ´áØR'ßTî-ûõ ê‰íØïõ’ÿlãô'¢Ÿ‘0ùå3ê.˜-(‚ú¬…™,¬²‘²e²øÂ—#-`¬ý#-~@Sû¶—¤[NðãÓñ^°ûø¾zVd U4‚­Å~¿óm{ä°ËTŽW¨äýHŸÃô_™—9Ö$#ÀeËÕ¡Q–µYÞ~ãâÐ(íU¹,2gª`ÓË`^³z“ Fiu*øÃ½—Õ‘:s$º¼sªŽoWiÙŸO{[ŠÇÑ3JI^L÷—ÜÀ}MÒ¨V¥G*Ϋvžøö4ÉHöºÑœgŸÑk‡cj.=¯jùj/B™]:f¿Ì™‰þžAÀLœDó-qmÈ¢X4?S;¿YÖ$E1·;¦á’ÐÑøÖv?¾>+¤¥—º9îòC}»Âmmå³ sljðO˾QÿlYÇý“ȹÚOzŽs!“YŸj—c´‰Ø3ÿ!w¸î¾ºÏW éša­öçi]šãëLôßèx¸ ž: ï›]›À-ìc(Ù-È ËýÜOÌ4Í¢¡Î×_-QÖâ‹6c©ŒÒLË‚¨ÒØÁí‡=…CFÕ•p»Ó;º:IGÊYfŠ–ajþiK'¸Ì@ê·)|æqcc¼ë½/ì%«9«­?…]¾\¿7P¿Ã­Ä!ÚMœ ÛS¶]e%°åÔëV†ó¦ªŸŠuáuómG%Ífõ×OVÌ¥4ojÔyÓoòÞ@š8ì_ÅH¥¦žwÉM¡³Q0£ÖGËþ¹aø8Q:ÌñìàŸ†aÎ1T;?VÆG¬d1ßðäMÈôFùéªâþ‰)ó6ízR™JXVû’3ú…6yHü¿š®Š¼Ýÿ%é{oìîx”´ˆ_«“üΡ2üô^q\¼?0pÜ$|M“c÷G$@®Œt[œ;¹ª×R¨íýðº*“qÛiQíÁyZÛá}ýUSâœ8Ì9mnvà4lKäñ›Ô9\]½Çª…®”ãÆ±:l¯¦™oi]b{äçl©øÃc¹\ÖÕ;i“J³ß1¿žèç&5>Q—°ï?ÄoÚùwV˜hd|ùåd¾nhÍt;žW#í%†Ê›Aç*³àâSÁï‹ÿnÕA` /ûÇ¿”.óóŠª@ÕxeÝê5ùDËØä³'â4gkÛìÈŽ'érjÿ$£o£ß]Î\ôühb_g6>åA×VAa36 x=ÄcŽËãõÞlÛ‹škiB½ÍoÓ.øoNsªh4ÏlêꔣûÈV=ìÌ`VëÃGrr]l–’Üg²Ö>Z“ü¾—È Üe ®¥$( »û–G]*$?€Áò V"‡’ÐiJú`ÇHM³Áìkš)FݽIP¸+M`tkÚïÞ;/™¯| ~j^ 7îÝüÝ.BdJÿQÎJ1nEI!Xg_GyQ£•„×Ç!Э³JÛaÒÚZ K€×ñàÖÜ)ú¤,£îˆÈFuÏ!jú¶ñ{ÇTÊÿAp3v¦½Wöt…L•KBX‚¯ÏCœGñܲ©YEŸJr¦êmå¯ùÎÜÁÙî%Û¸{;Ž­ÝøÉ\wþ׃΅KR¤ëæ3ù_|Ó3×/¹œ³¶ˆNKµ™jXké É TΛ©)Ê?A?~Á1¦ÜYù›GêêèÖdΈÂZc-cµ¹Æö,5uÿ0§]tóóôF54bdÚí`H4÷:”‡ñ ÎÅ8ï ^_Œçf“ñÏ'O!×Ó§ûÎÜ﩯J£éH¸I „¨H{ÛËëNè:—Xž éi~‡)ɺU'Ä9£’“jæ7w¦Îtô‘ ¯ÉTö­õÞ(o@JÃãK¼èX~¨äà”l¿pÛ´´Rk¥ÍD*o“@“ú¯5jù/­ýå ¸,ßöíö†¥-rôxd°N-Wü7¿¾'‘ûë%ÙªU¾b¡3è ›Š[}s¸³¶)šÛâ`½öÞMóV%‰É¦™•šÏFŽ©zþûÇ7Sîa’bš»dª²é§yNü–§oFøÒìZÄ1j`¾vËnŠBÜ·o›qÃ5ÕZe‰¿È)«Š.}ÌÞsKúïÔµù|4”[©/ÊwÇÐB$×y×ö¡ÉÒþ1™­µ:¼]ÄuYôß?Ÿ‰ÁEÁ¸»gþ@L–´5£³î·vXXý¹hU¨S(Ѹø~»}þFf•ji‘õN?šˆÅÆK¸¬l÷voWœv‘â!ÔÁ#ÍÖüjn áÙLÝ¡úíù¨žÕ<ÇN&C©^ž‡Èð—%zŽ«ÒÝ4L“ªCg]Þs-b{¾¨Gc´—©gåfðá uÈŸ¤4—_ýØÐÄÙýÖ]7½Y§Ö…<ƒ¸>ûNÀÝ®&î†Ë‹*d¬>meWO¶ñp³/|Ûò¿¹&i½Ó Ìñ8§K®2ËÇÔ)¬”Rë[;âÇ|˜¬ ê¹#ŸÕä2G·Žœj¯Û{ueËËÃSWû “ø©t‹Úz´\‚ló‹Z/‚jlŽƒî/ß¶·ÚÕ°àòœ?‹ÑR«P‡­¶SX9ˆ| cÔrXtg±ÀAÑ_}õ9Ëý=YmŸ(¿]SÏkfÓCþ\v‘õxI›A®IDŬx½þ”-ßU*)úBÆ:Ñ„±áÛ‘[‡/ ’nêýÈšr›Ô ’Ð÷ bý]ÕÝGµ~e8eÖ¿jVæ,ÿ£ËÄAÿ¹ôf¸mìæOÈp nØäÞ¾_zãžë¼Œ0¾†XšF ZÍZh_=¬ô7Å NŠ%\TxÎÒk›0 ×»+ÐöZ¹+°y :úÞ-ìà9TóþÑ]…? »²•Ð{“™ö`Ýþ¸i-êí32ÜØ~çtÙN{ t¿áàkWÆŽäÛ)šo°P}•1S‘ý®’¹R}•¿¬Çû°y+ÅiС›3‘~±_P®•ÞRP}¸™uò†œ7›—ÝrNΜ_×c ×:½ˆÒs5Æù¶)ƒì€±ßó;õ]ä9L»²:»IƒU½à÷wÅçq}¤ÌìÓ­W×Èâ5ªÊV­¿œßãã+- OÉð¨Xsžw>]9@›pR½ók‰ÀäÄDG11'QĪBA7°©ƒ¦=Vݳͮ¥y½FJûXº‡Ø‚Óílg¸–®»í J"°uqy›T«0L4N™–éSš“c˜ÿ›¸ÿ7ZÊY·×Ý=Çû#t¼‰ˆ^‡Mæ•§ðÈ£§u ¯Þüoy¶Rˆ= ¼öØÓ¬ÇFû5à㊖Ô5I´fp£ì¬ëùí® ²"¦|qžÍæÌjÓ¹jš^ßí< z?èÒªêwK‹øþS©ÀÈpºÜÉ7„Îã÷]GõsZz|¡”¬ËÅÿ°xäwÝ™µó~e5îE⫨Á¿:bÉg¥CßÀº¤ûÑ=‘Ö'/™¯;¾Š¬Lœ[œ‘Ymª>]¤Æ8~7„`¼Mc‘"#ñÓÉt mmõù.·’}Ot*Ug]U“З˜Èû?lÍÊqË5/ù|€@ù·ñ@Ü$ËŸÞA"bD3põnB&¯ƒËZ0ûêö‰±ò¾_$6Ìó9}jåõVâ—þ'Ž@Âgmɧ&ˆàÏm°¬E¡…íèú¦©ûÙ³¾ï6ëÀq£Ô!ÆJóÞ@ž0à ¿¶¾æåÔìïŒs;™¼ cÏ"ç;=¦ódsŒXKæfÔëYß‘qtý_Sgáð&^KÄù2òƒ ²H³‡àÒ/i-Ê0›+IXd{û¦ã›Så§ó¢8ÛÃÿNé%‡Ηÿ&qž¶ß\:èò§Ù±¼|7éZ;#Æ Y>½¼¤òD-ÎI³fì¤iذÂ|¡RëjRéw2•æ\y ="îuËy²Z ×±×™{'«¢ÝÉÄt™¤#SÁ1{„wÒnÕrI8ÝíWTÂ^ø?ïg- Išqþ6öuPµÐ§‚Ž®ˆ¡Tuÿ{)t=Ѥo[jÜÉ´L-ÒÖ51ƒxÅÝwoSÐ_ÅXûXfk¦a±9UERZ}ïoÜQŠÞE/lköõ z©GV+Ÿ«öY;¿1c†ÓÆoÄžyhïuÂÎ[}IKmâª)ÜzžRv¿ªÉ?1§Óî¯&_ù¾,\á?^³å4&lÏ ¿!Ñvàÿ §¿#ó¦üQ®nªþ»™W]jå0²"¢w‚ä´pæãyõíE™ùз^¼fDâ¯ðªå¾µ.SWeÌŸ’Þ¸'1ûŽO4´‹ÑlŸÄ‘ÚY´µ &º K®ÈÞhµŸtµqßs7þ*p×ï(#ê¾å8Lz ÜÛÝ´C†‹-baÑ´î¼ük±-ßö{k´ô—Jôiè0“j[•èµñîÔHÁŸ"aôbzüKf\Ž,j&æy Ûóê~myõ½%=¦øyŠÇA+ì?ò’/ :éKY‘õ ŽréY€€ÐXŸ{Âß[œ‰‡æÞ¡WœœæR'u*^«ÅiÍãv–ÜÎL ‰D^Ö'·ž nÌ«×og;ý»‰§˜ÿ‚§ïpÎ)$ئzöòSo¿‚îü£´¹Ðýý,~X2¤>¬¿Î©‘Ó1ÌŽŒ.kM³)ñóÓo×»d¿=[??ŠßàÅHÅpY«èÍu]#~¿_ûŒLêæµ#%¼šWy`•EŽÖŰdïÖ:`˜›óŸõàå¢oºZõÈd­¿2™ë7ÖÉn7J55š6ÃàD^J˜¢½å.Å#NóÏŽ©¸(R¹Ÿ”<Ê5ˆï«tósš‹BŽ7ð#Œ¿‚×<˜U¾C 1¥4ÃW„÷ýœuØ?u1ïFªÌ¹?›{ñ°vŸ(&´¯•x¾óvVj¯Wuîx´§gkãÃÉ3ѯ™º6w“Ð[ÜX^BLð“·Ó¾z!ó e†¡—1eSHæµ_ðÚé½´ézб›À·µÊ N›Õ “‘s!{ëS•§g£7YPÛ‹®Ä¨JÙy†¹Ùi‰Î37ìR"úÑ®,ÝaÃkQIƒ—¬„ÍÂí6÷bE°óŠÍåMGØç¤²w+ÑÇôÒLÈ›ÙE-tUqñ&½&Õ³©oeúfÔY/-¤Tþú8^½È“Š€€`4Ù½ÁH‰+#ªžuŠ ¢õîI$ú¹fw«ì÷—}ûtÕ–ìñù#{;d×TïÏHX.ÞÛ=­¯ð `}âÔpÎÏzŠSúÄFúáSÏ^T3‹×tŸ”’†»kÆ«]*V›Íw·pÈ@ÁèÅ )(Lþ2ö›89ŠPhHµ×o"ÂË:ã'GVþVJ¥E©žIœóÁNß“º_¾À;À†ç4„ÝŠ®Y)ÓÍãû×ôÍë¯X#KæEçy+MŽ|\©ˆK߯û eî««1³)ÿ@ rLšÙæwÞ‰ÒºS:©î?wOCJKG³KÕN„ÕÈ ööÔÞɘ Lkß^ýsé˜Nèÿê0o )ÿ0GÊŸdWöº¬M¼ÌvôÌßÍ=i44Îóz-l#=í“9'—µïîWåiñЦa ÿjM­?/*ëoÏ©ÂæFpêÊ(Bcõ›ë§«Þ¥³C/=¦Co@·çʹ­]øÇÑCÐŽRSéñJtíy·œ}I›Üm™To¼¥›—3÷ˆWAsÐyS5p‡äcï~Z¡óçH«î=ôf}[}ÆQž¯”ÓGí‘`à9÷És!`Ÿ“L:à`Áë|ì¡Í¦ßÏÄ0×zOÒ$ü¹‰Ågjò%Ú–þ¿oDÓU³™:ýTäãdOt¥w‹É tÛŒxc¨­yÔXá¶Ê2õ?P=%6Ï¢p[+Ù$¿¡7À>I¿nP¥>‡|±XpžùÌÌ»ã+ýÉ‚èNÍQq\×_Ûb/µ=9ޝö£}èXñ÷"Ñç%üfJߙߥU¼÷oدà;üýþ¯4Ó>9¯‹¦Úz|:ÎIJèÑΛœÛ´«KCñ:îëR¦]XNtLÐ,8\Š=é„j{lVS“FG–ÕÁ×úbéb;ºŸ¢î¸eý¯]äšó²µ‰¤ðôt9¥Æµ-Æœ<^`Ѽ¦Õ†4ÅhëÓ‚&?TE/yš>rñnÑÎn" 1äío.㥕ìéy1›àÎBT„!³ÈáC·Cçê|#¼šVÂÈyÜ(yÆÿ­j~ñûËî(g]ðÌÌÑ:äqVACõbµÏ`<øfg–«anòž¨âÿ¸÷ænp×Ùꨕµ×‚1”§Žñ¬Mññnn!ÙôM¿±˜c:äNy2i'»ˆ{­8Ò¦z-^¿&œÍno£õõJõ@Ñm+ì®RPå_\ý}—•õ  ó+^¨Së Þƒ_”zÃðä'Á÷óTmdxÜlè+îÿZß¾Ù×z>Û ‚Ê ÷nÂÙž:ìŽÚ‘doK„žüÇ¡b¸á¥eÞkv¼úÓra ¬‹«ñ÷yak;?ÅûægÜ×Ü„Kvº`èø‡þàþýÖ!EEi}qöûûŸû~!Gøi$©Õëà¶|¦³5a·ÎÊ?ì2â¨ãle±T½1oRŒÕöwùNX‡ ÿA“VVŸ^¤,Õ¶>Ó1–]ÜïÚn¾äÊÄÑò?y‰¼çî­¤ª¸ ™¿û{ÚplNá2ÐèÝö)”¨>Á3…9ª™Üzkt9ìÜv[¢vË2{º²RY4ÔL­$ç?‡ü‡Í‹@+š’±H£Q¯€•„ãiÞ{v6õvجW"ç¥u+¹Nª[‚^eu2ÉÉULXÕ·†*¨i; ²ÇP{Ô Ö´EjÕö÷S…ѯ8ÃÖKù1âGaœâùœrû¾Œ«„²É UÛëå ¿ 2‡Å }Œ®)‚òê{š?³ÆÁepçøÉ>pÚÉèÆýK2YçIµ–ºfvÜÛÿÞ–VŠzåéãr¹%§ŸlMg M¦ñËÛcbI’p`Tú™ýJ2sXf°»~çþ® öîƒ`o§dÞº—3]©Lå•‘úœŸHiæ­Å ßó:̧Ÿ“Tûw63¥Åý—ÏñIÖI÷ï:Ó !ñ×Y‰²Oœx˜Ì¹&*¿²}$x#ÛéúŸ¥'lÏ-oÂ\‡sìªG#…ÓQ ¾xÈd<Í8ƒ3¿M_eÑ2S†XÞ;în•á¶ ¢^ú^jýÛŒ|:Q±/H=9Vg/|–ß*³Àæ{yÙÖð^’}:w¤ÝÉ·c¥ÑÓxªt2=ü£dÏ/SS³¿(¶eC“? ŒCmÁÝýabèÿu©ãËÁdâ+ížéWõ›äEFY¥qÍÖb°ëÑÔXN¬ÚàÛ'9Þâ+ÿ}ç£Þ_Gä@áé=[9i8†ù&_&±÷uM "c YÍ.=úf»¨^{Q}-ôÃdö<ôÛjBRçà“ý^úåÜú7éi;´Nñ B֨޲øý{{»?!†“ŒwDÿïlmUåÏóOp6¶µšÖ8Õäw”Ç3Ü{&wªt®\ÚôýlR³šþ¡HhZÌÉ6D#Š„c &M–LÇâß?±çHé†}ÁÙ·rà·ÀB!„‡éà}K=zs©N„¯ÔU¿Šþà;&¿è§tãõ~œ®Tÿš£k¾‚àÒêÑH#7Åþú˜gêzÇnBÍob™'P¤C‡gS£ K a|qÜB¶9Z °_8Æu²À0XGGû™½›Í?#R°ô v’< ,t);5œKš4Î&µ9£0ØèÖÐë§·ß¾B’ha³G­Tþ´ìÌíaôV¦åͽ¬ ½= ŸKçOÙiú_9µ>ß™·ÃÓTålc°´Zýß6K3¹JÑÜ<ƒ’ºþÆärÚ§çðYU‰’§—å ò\ËÒx ýe8Èo±+ÅÂá:· N6^Á¯ê#»à2»8òq±ûIŠœÒ`ûÊA!bÒÇzó%Íž|^}öíkpr‡Kr7ü½«yrGû‘Œò:Ÿj….Ò®˜ñ§¨®‰Ûƒt‹>ªä2zGÚ‚ŒŽ·£v‹‡ðD©d£Ã¯ïßÄu«þz穽ÍÌþm… ü–KææKó{Œ…Mǵ=¯kxÝB ížÄ:|^¡<ÿÒ°óo‹CŽÞZjbM°’ä\³o Op†¹äRÜ ïq rQùØHæŸ)‡¹€-Ÿâ_~îL¯Ió‡óûÏü:U®øl)}ÒxXT#§XnhÙ›ø³ôª·nëùoß?³ñøL®Q[í6YŸÍy:űçGŠ×:Žîµ7ù;ýK´2þ…óêÕsÇÝÛÞ~' m—Icû)™î*au™¹»Pj+‹¬±ëÃÞ‡rÜÞxêP'Ä®5/_² ½véŸo¦d# 1`žär'*?½ót\c¦‘ðsšb¹ð^?¯ âuÆ.ðý·*Ìî´MBÆ]~blm÷^dÎŽ£ä&œˆ¥Â6”ü]`´ò ¶p®ÐSúH}a±­ þê]O*1¢Y˜îj´_ŽrÌø Éè†^jØåþ–JêÁþç'T²G¼|‘Ö…Óøt~î”_D®S œä‘ë&“„tâ%ßd.RÌ÷‹¸Ê‘ûÁElÁzi<}DC­õŒŸc­m¬©6Þ¯÷ûk“®0qsB½ñiÕ6MÉ‹µL¾M0ïæü¹š?•§>X˜X¼uÈûœs`×Û!©?‰ Àìz~}¾§ž¯/¿_˜ïQwD™…æCJ›c×ßçÿ©£Nù4ûê[Ò¦<7“MÝO?}ÄL#ýN„îÛºPAWÿ'ÚÐâË,Ê+¸ý\‹î 0o0Δ³"NôɳöDÏÛ‹nÊbqÒ|àö©àùŒµ˜—<=XÓ>„ݵ­œ†¼Ë—¼ûàø3'«ª`›6›õ&Æûkû"ëpÆ7®üÏ{æqtühóöd)f7ío”ŒÎ‡¿£O·Ãá£äI7¦ÈÌÄ#Ër!Jù˜ö4àø¼_îOW9yjªK[çϳ`n©èº¸Ç•6C3XþYȿџ³§ÂøKx&gKTl‡o§’›Ùí tTÑ+Oôù]Ÿ¢üS]s‘G,|¸îVåVÚjp‚¡>McoSÜÙÿ˜}ÊL=× 2\b*kb!èâºUJz|MOß’—©ª6B–‰ äøÁG¦å;ù_ð›)Í*K%Hîù†ßFZ$ÕÀŸ‹úŒI!¦CûUw¡ÕÝæ’Ö{å©ÿasÑnáé~ H¨µ ¯qX•öëª?jX–š]åIÝ%B •ž~£¾Ý³ôźÞú…ÇœÍå)oüEßo Äg朄÷M4Kóʲ¨ÿ’ÛõRznL¼¾›?¢dh(Ù§ø¶+“!@Òb×DÆâ~¬†\—>åûÌv2öK| 9ËHò=ϺEg¨£çQJ‡E.»Ð‹,°ÎËUèìñ:òëÌ:ÁèÑha%£³q͹ÿ.&®›5¶9$Õøž^¿çŠ]õ—U_×0à«þÉý›N=ÙødÃ;¥Vi%Ùcw0a„äk‡×ÌûÒ;¡²SliÕs–$gwÖRòî¦%&¸¾( fÍ]û‘}s³´ LÏXúÉ~‰_G³»šÉYaèÑiäKnøo¹81ðÜ þû­ßúú¡åõç1à5ïç£7YmÔí÷oðÜ„ä±Ü¨Û×ô´ú,8Vœ\(‡O‡»¯»ê´éÖÈ©zúï2*LU¿¿éÃ#Æý]êÓ’€Æð?ó’e5˜"m DgÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþzîsŽá‡Ð0ëÕJ˜¾Í¹Æ;®¡Ýo·J.öà¡ðÏ¡ï]Û³_oCž1»ÝìöŠºôo1ÉÒ‰-m°kÛRJvÕh˜: £ª @t(4ª Ò  uÀ{ìj Ä>óH­à¸}/i*‘.w³áñ÷—"R<|û*j]æxB€÷½íîR¶äºîîÞùïîèª'¾Œ®º]Èî#Øû—ƒÇ}÷Ë K¯NÁõ¾»=Î{¾²^¼[t-õÏjdvÂ$$]d§nŽL÷_sO6Žû{Í´‡e™;i²}ò¶œw¹Ý–¶4²ÇíÚ÷p)ô(ª7ϹÑ{ëŽËQ íõÑzÁ@Ò­ï<;{ŽØÚ¬›bAÏ`ô5èè/<÷•Uô iÏã¾óÎÁ”¶ìàŽïH r<^ QB‘ Ð{†öK{]…¶€-Ÿ7`‘ǶUâ¤ä¥%Þ  :èbÈz n€(Ã` Ql<œTö`P(Pl3!“€ô„ï`ÐæÝ¥B‰ó«îy=\¡·nz/®À·„g}·4úmjž:1±nnl:h;»mN{öû=hôúj:ïž Ý!\ºjÛŒw®w¶ªC§cMšÈØ{æŽ ¬“ØsŸ]{ÂU¶î6ÍëÑUC“XíCi]Û¯:%0 yzû·-ßA½5íôÐ®Š‚w½ntÒ»ÅMîGmtëf¶ §n¹¹Ó˜Bî*Ýê}½S¦ð|îÌë©Áµu³Qm×]¶7¾áOz5öÛdœ´èûÞzöÀ:å±¶×3VvV¥Ñ»uv´I½îá†y­£ºåÛ4:o n›böÄë}Íôûì”اMß*ðåDkÙiÝ­8N ²Ó­Šmžø|(((½¥‹D/¶«à$‡uŠÄûç¨í–Ö½}ÍÒŽ“ÃUÙ®véOc×fX%èàƒ}7¬ˆ­f©»ÙÞâî§°5[x>ּݻӼeê ¾ù¶1’4ÐhÀCF0€hb11 4b40˜ h&†€Òz`š4242 2h A¦‚€  M42Fji¦4ƒDy$òO ꇤÈö¦§êž I£jz‡‘©êh4ÓÔäQµQ‘¦†SM4Lšz€$!„DÐ"dÉ F5M£ÔMª~™4OÕ=L§éM7”Fž£OQú¡¦‡¤ÓF€“@ =4õ ÔF€hA£@4Ð z¥$ˆÐ%<šhjée4ôÔÈÓ õ0Ô0ƒ “F4h= šh  "I&AÑ£CF  ɦ$ô4LÑOM €&&&šdÓ©¦ƒ$ôOJy“TýO@ž“ГôFM0£Lž“Ôf¡I@@ MBi=FSÊjžSôɤy16ˆžSÕ)êzmQêh$ò#ÊÔzƒÐ‡¨õh =M=FŸ©¤ƒÔЊêÔz€ ,ÕDkUZ.ºö:¾NËu#K k±5Á«îm nu9•ŽšÙÊ]jÂ×áô „¿þn~‡Uk¿ xrî½›œÛÈÍÜëønõ%\ÿ6KøÈ]SW†¢þË?†€5ç2¼ë½ºí†]Ý;ºœ®Ns»¹ÞúÛnkS™”ó°•Èœ²S1”½1¹ËnTlÌ—žïÇþ“ýÿÝÿ^§kzþRä9$OY3Ñ Xèì:Þ¿¹.¾vTÔ€" p ‚âqûlkWä5H»7À. zm ƒ|¥ Þõ.É1ãá|`A¢R׬.:>ù@µß"ÐÅ}™Ú™Øv2™ÏªÂk¡Q9§ç§Év­:|j'ø/Êï™ùYÆþ³ÕI@!ÜdŒþŠ)ÿΘH•U*@ŒPn¢l*©”"šŒu9Dt ¸"ÚH.(ïâ‡Zä~DRô/©B•PýXY·eEgW¿µTê!±ýØ­ÛPÒûÒxÈ„eïü"þWЇÍêý½ qµ†þ|™·ÅIûtSg¯õ•àÁ2LJ±@MíD$§è»†ªÓ/Ü:ïÎ÷oé{u­¶GûOúüŸüZˆtt”ú+î"|è—öWÏ›ˆúMZOmÔÚß}ØÏÛ›â./º.¥™´¥/“,šB?½L–RkÈ MIej¯aaÙD>ß2—ô?šÊ"ziÏ@ÿtÇóg¿öômüjú"{ÿ¿£—ÿŠ;ø¬A(V@jöÀ ä((®ú޾΃eßøèzWð‰Çñ—Íí»OÄÃ( ç TO!õâ… |z£ø§ìÿg»ø×þÄFšH,r€ûÍ…öQ_ød¦ŽÈ阖ޢg|Å98Äœã“?Zü…é(ƒ·ÌÇ-ãßqwÛTnož%•æ_Ñí9¤©G;ªéË.ÃM f—"ãC ¡Ÿøÿb)ê-'n‹òèdã 0šú‘ÚÇÝ»jñ³öR>V‹­–š¢ŽŒëÞ»ÎÊå Ë6¯_–æah&_RË&!«Ð%÷1®ó™˜,á?“?´Á‡ 6%êÊ(…¹¥DÀ¢ŵ%ݦ¾ó*ࢩÛpoKODþ@É(dÈÑ 2†˜·,æ© Í Ý‡×ô£ €¦eé¤í=¤¡oÁÊánœÒÅ‚‡òºƒÈ†£·ú çTn›Yxšöy^I¸xIÒÀ¬'r½Ø~Öygã`û„7ļ·­Qˆšz7±Íc:ص¤B9ýÅìaÚ€Oö³uòˆŠ([ ¹ù9/é®éO¿ÒÆíeû¸q¼I(í¹ÌòïNˆ©?üvê*ìËÔ8°÷>¬Š(a¡h5mx\°LmJ UÝJû# š{É-¹©WÅÝãQÿ•P€)Hóƶó÷…|®É³ß¤Ü*¤æU)»–_ê\¾Þaw×üe­æ4ÉèñµUqø]å?ÒyO‹¼r–LO+?Æý ­\Cß>-5-·™aåœKA ¼ÔnqÓ?ª#mp‰g<´\…î•LgÓ–dx,èåõ>\ËõM6‹…ækZUÎú\nº6ckB³Zn†è¸YŠMêK÷œÆ× ù•›Ç)ÛH×mŽ€ˆ€Œ™,ÛÊ¡O“Ï¡¨&uüóK–,ÛcÇ<Ý öiì=Ï^ÿÁûz¤•™”ÿ=“=5*¯ÙŽ„PxSCɰÖîØÊ©AÞÅÔm÷¹Äü©&2Ø6޾ß9ý§ùF¦µ Áž·ˆãMº®îºˆñoç ." " €‹û? ÜJ—ïæ½ï.»åý[¤C¨õÙõt9<ŒûZ¿šÙq]øŸÄ*/“•øb¢ä«5æu}VÅ䛽"ü?ãŸLTZ±½Ò5B]@gÊ>V gÉ_€SÿÛ¨CµÈ 0]J6Y¥ŽåîçÌUêGÛ;)û¶‚8Sºane¼„|?žÁ?”Q8Ÿñ«oÕ|£MÙÂàZ¯u·ç«kÖúçÒŒ& k¡5£R¬X„! "kCmî·¢"ŸLáé‹YÛj™-ç7Ûª‹ÿþ•ûÍ=møöÜ-Æ]ÝÕ¼ÈmÍ]Š‘ÑzN¯øŸ©·¹%ý”|Ø÷Öoê8eö)Óâ½|?c´Ly ÂЩéÕ.®xFõùõ¶u-J‘°Ò`÷å-ÊÊÖ*[®Lbl'ȹƒqŽO&ÏÏýÄ»Ä`#³Pt8en@âˆH¦€niÄÞµü¿+Ñôº \½3ý7¾úþ¾U”‘>>¥_ðŽ¾ŸVW%•H>Yï…œ‚IAö]Š”Ú¨h£5ó­óååÒ1j¤ZHÈ‘ˆaùÖV® Ûú³+eA×ï?B†àÓû¹?ÀÔ{"¢xŠØ«¨#Æ 2‚;²–N!sô©VT¡ÁU‡yÍ kžÜ.hb?«æüÊ=f¤¯´Å„}§Z, Ø’zWD”(Ùnk‡As%)³É.=SAŽ@ԥçƒ]ÞÉÁã•E±y?¶m&ÒF •U¡ %­zÞ’p2‹a?'šu!%Ž2{e’H¨ä‚×£ä* )Æåqä*ÆÓ‡q [ç ¢øQZßÝ SÌÊËùª¦ßÈu/™ÄÏ[i/ö¶ªü£wÙ‹@‚§ªÛþ‰ðY@"¡Ê)byù8Âe„÷ìiÊû*,ð¦ø¢‰‰ìøU”Cc Ý×a[º2ÛjD×Á¨ßPÂJ«ï~~õz^È®vGuÜh¸§íÀ_ó»{ºŒléz#rO Ô?™ù³2ðØgvÌ\øè8αٽ›Þ¯ øm\qŒ¶Ë*´¬þ\t§–¼-ñd÷HÁði\ZgšÏ=ÖkâwDÌÁÌ¥¯P1z¸t0þ†a¼ óƒ×îÕÍ/FVøŸyN~{Ëh mC#ÏιW’ܵùÌQ'G äèá‡ÌEøKv¸ß—FŸpÕÖQ‰N‡ÎçN¢ä'ˆ2‚§Æu6]´g¯›¯m`…<ö7 X4Ç]¦ýÏ „n[ÏCAÄô‡g}£?/?šÈ”á´Þú÷ _§ª5{7ELùβ-‚ËÓзV dðsq·~°âe è2!&PN|í¨ åêëj”ï¬6wÜjšÁL0…ßN‹+¯–{Š:™F®»MÍÍŠæ*k<éçì¸"A@;Ýj“Ž2p6íUÚº½¥Àb.£ñP ÞôVÓ•:ømÇ¿ÍOAM„sFúrãŒùWË€ò·©x¶Zn€o¢Ýn†„~|à“zQ­†úð'g ¼ïÎl9G[ê›ü¨h$A9pêÑñNôùhË~ ÚpþÁk÷dUt¯…yÌš–9eYÜ–7ku/c¶{U”tÈU¦zlª2öIÎìyú2¾J²ú—¶ÁèÊ™ir‘ä÷z½2Çi]Û,ìÛòfÁ™4èžSE"c=Òæ=g…ŸÇ¯ãþ¿Õö}ïÛÙx“žã¸pØ´˜Š1{ÝÅ´Ó’[ƱƒîØI*ÓátŸIVÒÞŸ‡ó©cA8“c.åü¸ðzµ×­*ÿHm维Ή „•t—6êí1âÒåvÏ47ÔÀÚJfh‘¤f£jŸLq<Σôñù±êí^>†ÿ'¾ìÊ_yC`"?^Z‡E|Ë®RVé§ý’¼¾×{]¹ý2:ƒ±Õº×pöûY+T6£×6ªe‘¼ï±lx¯Š·§1:(lÜ# ëÜÎOö+XkñÈ ûT0ûnàV>.nI9M<–^²p€€bÿÝwª,ÓÀæ»íi_Ô/³—9sò2tPÝ&”Ððh2s©”NåYñ Ó°Á5 ÄL’€@0ÿ[Is/=<(“Ìí6¾B¶8¾¡[C“¼êîxW½ïïŸS‡‘%ÀSÿ;hðþæ8}& x‘ûHŸªîàΚ~ñ|ü,²rÇ–c4žÖFÞRR_w‚¶µ/þæFF½nW5ª6šOÇ-þ¯³øÖ¦}sŲð`%zïêÔúã6¹÷$tÓµþr:zUãÿDÄvƯÖiÛ¤zó­ˆø½Ü[ˆÛ^oߤ椪=˜66‹r1Q:ü YHw_·½q3°çàÇú’a9§¥ÕåPØîiV)þ Í û.®BqW® Æ³Ù”üMP‘;áÇœ‰F¯^±ÃñÛHòe*'¿æÜ~s‹åíh_Nn~ Aö@ÝAï h£ 5H»—É,öÑÏB±#¬Ï«ò«œª:lóÉýØ]åNT«T³¯­7‘·0¹ºÊÅ|Ýògú3Îû-Ö¿cª»Ö‹vNñ¬\&niïyÞç»Õs;yïy—^ŠRqR¼Ž}MˆE±q¥)†Û$ýÖy¤|ðt\çt‰˜—Õ„Wãe¢ý@÷Úq í¨ÏʱîÁÇ ìÅ÷ËÕë}oìY­¶—@özOä€2¾I“Œ”‰îY’Cœu ¾êA¿Màpi¼Í¯Tå¨Ë¢z©Ü² ¿…sÿú]}^1S;÷ƒŽU³Ùb%³=HVmòðKêv×y~ÍòX€IÇüàµJœx|Õ|Ñ™lv^²Žv¤@[W^¾úñì¡á%õõ§;ó¹“úã¼.Ç®K&ÌÓvf÷ϼLv-ý‡§aoø%„µ³2[_}Œ£‰ºäoUBÃd„ ÝÛj€· ó7µ=ks/Ã\aŸª°VFƒSLnNvš5­•öøP«­t(¯S3WîËž)Ð…Fܺé—Ìө’¸¦ƒÞFi)LÈË<­Åi‘Íÿ»>¨¯CýF*¾÷¸ß-^¡[é5¾ÊH|é§ü¶È:†ŸÞ¢ŸãÛ= ×g{—+â×K¨‹5ŸWøç<Ž%º;äž=w,@@(»¬R{Ø/ɸWŒ÷;vP Ÿu¶õ_Óúÿ¾…õ¡jb·Ñ¿>ÚÅÖsùoGÝÎr­¸¼”a6.›Ô@2(UtN¼suš´iú¸Þ/óÅQ‡Ú/â¤J›gPþN}´« Ñ=ÿo›Q 1óŒÂã%/¾g¹Æud¦ñ·ôL8°¦cÕáõxÝ{E"x,Fdnø»&öL¶(ÍZƒË:‚+wKü“ ³# ”¯Éž³fÓ£NÜøŒÉq~Þ7¸ôP=»‡b°n¥Ñväëêš¾ˆ[»îËj|Ó…›=*ì½g%#÷ÉåùÕ³E$ûã–óçì};2nI|«^©ï·¤‘²,Üè—kì€s1=6‰ÜÁSüÛ *³À¼†…c•[×¾gÌ¡µ©ÿÝ•=3‚/é÷#bl@DÔ@h ºJÈÈ€£Ùü–Ê Ÿ¯ Gö¡ë¹w–ø‡Mäõßs¿Å±wçZ7™N÷žÑ& ˆ\Z_¯ÿ¡T±· ÕHEó|§ë%‹cFwœ/ZŒ´Å-ººÖ5ãAò"#þ?ÅñìþÄOÀßý Æ—Õÿ ²_Ì^•õèETPÔóÃr-€¢ÓySmµ}aPá`\CìmÚŠ]¼ýßá»ÍàÜ ˆ5ާÎÚ™âbúˆ,HÕq²–KÉC¶*-Àû§¿•>s3#P|A$Œ¼ Ø8zª´¥ßy“êNà’L þ±ÞÕjC=ô{ÿaÇ~³ÆX…Â(~; *‹MÏóì ŒhôþyVsø3ðbÑ€ŒËý‚Î~[ÆìrL¿<¶-¿“í÷…ƒ#ûÞ›}¥šóYÿ;, ‹h¨³¾9¸(u0×èÅ<§€ÏƒÌn‡XVª'nÈŠ5,ßb Q@ô.¥@‘ÉŽÇ{ò6º{³:DjLjS¸€ZаB%Ûƒ>qCy¢?zÂðaœ<¶bIj*IêŽ,qT“¡˜@ HZ_ÕÄ^¢ä×LQ¼Ô¡Áª!PÖ_í{Ú¢¶÷=#›ÔÖ5Ï'Þ5˜Ÿæ*/’¢ü>n59qÒŠþ’¢àð/T¢õà-"Ø9r !y?2}ë}}ur‰Â¯­‹$H“ÕNDF×¹ghu˜‰ 르R ~Ö«Jj†ÃÓ‡†í™Âeÿ[¼¾n™{7¯ŸðU?»‚»þ}G©éô?>uÖá;xgX¬A´ë­!QRD$ tâe2}<j Ÿ/ó>6Ö®Ï;½Íº€)Àà—¼bšœó «¤· ÇÁµUû­P ø*-$T_“š6Ç4FK·;ü:½ÆìÒí¸n8cX¹“¿¶½MhŸ… à¤v6 ì>i·=¹›A—¹‚¢® p×9îþ'¹ú]ÿ!•üöAËë’ñäË~¬ÔTLˆÂƒÆÿÛÊà|¥åxþ·¾ã•J܉8Âm¢K§¶uìÞ{/äÙº»ª’|®ÊM.Lë†|’x5Ï –/i‚ˆ„¾“æÂ¼æÙòøHT…0zñNæ0Ï­×ÂÿôÆÎ¿{m-ŽË" B"Õ„líÝ-ÌæÊ'uQHAܪ‰Þ¬¿31>{¦¼-©ú2ÔvÙdiÁí^ï±ä8›ûgôÔuÍçØÇÔôYuΫ/çýw üüÒ äxš¸•4;ÓôioyEö6LemÌÆcìí|ïÜÕÄ—†l’CPåÁmþÿ0{púxÜãÖpôͶKލ^J¢ÀRäÆž§›>]=¹)*§!aüº”˜óÌÈü¯ýÑì8[­îæn`ÈîÜóþO!AüŽÕL[<)¹uºç[Ä×;µÛtÔꪕ)“ÎYí…³ã«a;F¨=Q‹j&,0,Qt €´J%d:¢†”óÑ',ü£À8MߣÏo-ò-î|+x,X¥•EéšW47^ۺ׉;:»®F»{ä[úk@+#“J ©Ê¢h¨Ž~çô>O€RÓÊ5µŒ¿ý†±4 È«R õÉ$N&|žçÀû[¬×5:kch’1TT °ÊE6TQ±ƒ $:„gßñ®„•›øŸÂ}üñ_–O?6µFS?5дà fô/—SÆá·äÿ]ªk¶ôAm²#“e¶NBßRÊ H%EáÔ„A&$%I¿|•rRÇù7¶uÈê“öoÀgxò3½Å@Ī`© t|r£Ü¸ ÅFµ¯m\åEëÕÉŠ1FM}þ[âD.Ïf£(Vóï‰l2”ͤ"FèP  ƒø¤ÕüŸÈò\“Ó¡È=Þ¿²I>5<ý¹ó{óc®´}w! ÊmµHTu›§›Ì²žD>˜=r— çáë¼–»Öó—ÓRA8MI¡R_LÕÆ$WýƒA*ÖÞšzgžrñI˜±oÍM£æ§;k£‘/“Üÿe¥/’)³O¥:™í·)ú7¶&Í/–¹:¿Ù¯áñ9®îû̽hª.ø:¦BHA ‹QQ¦’ÓXЛ"a&6clÌLš¢ŸqÊJHL“aê%#ó}¾þ߬€?ErY`Þ5Á €8äQ‡bõ¿žMÇïÖ]2•Y˅Γû4XU(8ÊYQÒMÂ\zèºàqñ]JÙ&EÀ¢'…EÌ:·ª¦ %Tf[D©^s+="Ú/„F½lÑÇ+da! ¥­iFþ“®ròÜ~n@2T]],jð¦6ÂSPFMÐZTUÒ­~½5Lá!ã¾&áFBk†ÆɉX5Ê£7R€š­¬­)òàDH:¥Šß± eón\¨¼ÿ oœlY{¿ ±¥}oí»ºÚój ëØò4ó›yÕ3 6*ŸÅº!ÿ@ ÷¹‡Ã”c>ÊœŸÄiâ{',ø·sêïÚ0èñ:÷n§íy¾ÙþÇ/Ýîµ±Ÿb¿_,ª. ï=›¢Ùè»·|+”G8Gm§¥ÑóYû< >G<_À7œŒ|îužraß«¢ä5÷áG>ô)äøq§¦û‡ 6ù¼[ú|óìñ2>¥‡—pøöutt÷iÕÌ)×Ëù@"ul˜Ã¼£ûÄÇÁî°p¾ŸkïÆý0¨-/dVŸZš³¹'Šd'ã|×n`Ÿ¥õ~Òó‹×*‹Bª¨ÞÅP(”yj‚YA.¿+)·Ï×ËÄÛ­³‡/s\©ŒÎ!D¯ƒ«¤ß$çaÌ4“†Ÿã5x@/¨:{˜g1Ë­Øu*ä>…ÜüáÔý~ÃÝ«žƒ6äZïtDŸ ‡/Rˆ€€¢¢äÑО3d/Ê¢ô“Ÿ¥o˜óS?Èß(|]Ý¥ž1¾ã2áÏ»²¢ö*/d¦¨¨¼¡qq@6õBôÞ:÷‚˜}3¼(èQH€9Èóa6õùþغ€cçWÕA_&ö;ÛEE‭Â1CÒ>ÀúiÒǼüç T[û¯ kô²îžu´¹ÀÐT 7|BŠ¢¡}‚ßgÄkßqšù–‘ø‹óæùOÚø¶ ‡vúH¾ÜÉ—n€/3¿|Of)A…/X¸vùrìÙmüâü³QŸs}Ž˜`뉰°#NíIî2u!A†«ß×0 Ù©Í›£,ÆÍÐ|™á˜úwí¥u ‡5_Rjöj4ö‚ù;Ì‚˜(ã»Á 01˜jšGTjÚ¤âç pïñ—ÝDSðÀ@ø*/Ï^§Üö} #XQÖwá·$ˆ˜ Q@%(Û|rTÛõH¶Œ½n>Ûï[Ãò`÷û’ŠÍñÐEõ{h±„*=¼|yÚçÅÓÇÄ‘PØûÛ\0AÄ çþÌoÔ6smÔûÈ]´"F«¦áÀuåáö))_ˆPáÛ-/Κr½^8<ó‡!µj —#뜨"=„Ê‚D¹wwÙøûžXïUD?À/Ó—uÏ–Ç/ªëó³pÍÛß`ñ7ǬUEóà{2ï>ƒ¿7šrãžÆ¼h=iذAFÝ "oa8ž<5kæ£å²+‹¨7Š5u0Þù$Ç,‘"9Èy‹ ë´Kw_ìA®´áçc/wMÎ`4;¸\øñ÷7,IÄ Fû¥WŸ¼â˜¸K$`͹A6ìÓvB!™5Ýÿ«Ó²–NaÌ:Ô„l”ú\I°lv¹eJÉG' ]19ï¬ ¢\c¿»G–¨»|xCMº  Š"›’Є$_G*g`ù7óè"¯=¦Ï™•{Pžg§zÑÐ °₸úΗòÛ»«¿ÝÑÉtÆ ?‡¨0ô¾J, ¯ úg•“ày=ÁöýºZ¦­mL€Åî@e¡ 7Ôy±E)yäCnJ£,O·Å…²)QrRäÈþŒ)éŸÏã'Ñêâ=¶ ¼»6€Áàª.Ž‚D8j Ò€ƒï× ÃÐû-úG°ÁÜ}(Š/—’{+SÇO¤ñùOå1ÛO—e÷T$ü.IýíÐMÏg.á¿•ðö>iÕêxMÏÚyýùž8‡Y¬Q„Äj Áó}™Ü áÅ7búÙúñ¿Â àÞ‹»3 Ÿ©!Ðß«”N¸ètiœr!­ØI·ØÔåéªüéÝîÁ¿ ÖnhØ@ˆ<`Aà@îܭs3à#¶F‘å5ƒºÂµ÷,Hy[¢·8 RhÖ›&{ÔÚêYkIa†8¹ÞNîȶpÉLþÅöaJ(e %V¸;²Žó/I¾”aßuM gf¸tšWˆEâTi}íKû&m}NúÊ*˜e]{Ã3 ±2äÞ –g“œÞFB‹"*o?½:²—!³¿ã·¾oš%:¥ÇC(ÓùT8Iö‘Me¿~Cgæ ³º(Ù89 «7ƒ·¯ñ¬¤|63Ûž qMõz§×©j-9ŒHó¹ÐPg[í³6œ}zz/ápG5Üš…ú»3ìÔ/§x}êÁîW•LÓÌüR.vp°ÈX×P¼KTŠìé\5C1À‚ª„ù%’á1ø#íßAà½5>Û,p"®Ø=Ú#É_šË ͪúá8Ç/Añe)¡MÀ^ÀÀm$ߎè4G ¼MŸ^’µÚ~>Öå®Ì/¦ä¦êŽõ˜c únyèG©Y©|˜-Jå%C>ÀÛ\këQuùß·“öS­ä@ ‹À>ux²úXØ€`¡=hƒ†!'ö‡å[œ=÷¨|3XÎÞ|j•ùí®¨rÈnïE:®õgY®ý~*èîÜO5ÝP’¾µÆëÓ ”jUÇñYZáÓ¿ @ Q"qXk¹ð"RíŽ& ޾šv³‚v?(S¼#Ý ¤{3êÓ§†gðpܾ@vÏœ©2'Xç–`D¬¢J¥¾»wIçÇ; …=c™Œ2Ù÷ÏQIYA(!~“lTƒØSÎ}ÞóÕëlZ¼ThdS)vè¨ ©³×ït‚~«ŽDK`ªœx·—OÞò.”é!Ùòôø½×ïÖníîÀ++ Î @¬ÔÇ ¼[;º¹eãˆà»¹—“¬¾ ^Ò¯Sw.Ó9e½(´Àb ÎÌ6\8‹íâçk ê¾ÎŠÜûƒ%NñÚö#¯Å·xœýO¸qØ0®^bïÅ&;µôÏAÈqQ=sóT¤ú7€rr {«OUÄæŒBšm¾bÒ]Q=˜ø¤c>jåyå[Ø“zªÆ*e2-‹"t®á[oaq¥›?äýéQ ôrÕ¦/uZÌÆèuQ =É’iº&› FÑâàäÈüBƒµëIŠ9(¬«m¹w‹œ Õ¥}nøµð'TæœçÆl{ôœ¨,Á{i ݾ.i~WÛ cªmݶ)ã­ƒŸg*g4$mÝñª^29g¨]\JÊ‹íó·ÚÛ˜—ò7ôÒÙc¿o(xBþªÒD3˜dàfC:ªþ 2)R™K ½O7µwT@9 ºÇ=ë·Z¼ã¾RÕz'H¨´¨¿—©û¥Nãqõ‹¯ðò "ôAø+Ù|_»…} ·bWä6~¦›”¾* q!÷ïïËmñ„Å7/ "`[†p&ëºY¸í¸ŽŽb<‡2=J9ŠyÈRž¢¦#EjûŸ«v­È‚h. %Ã5Èø·‡u-ÊPCX&Ö¡ýnw†F!êÀdnñ¿y>RÜz[è6©0kíZoT²¨¯Dg'æSgš" œ ˆ§]ì2ÙLï8oÛª¤×(-l×ö™í4ÎæX+;ô)`(|È9ÄRÙßnIuUjq̓5ˆøê’œ³iѰ”¦²¾¬¢+­°"ÅL©pbŒF î°„ªD´QÈ+®¹†­ IÔXð¹aL[ u@/‘ÚFß—R‘oOy6_cZ¦K8Õ¢?—!ɧ7¦`òz´ãæós÷¹5åpS»§`Üñ¤R@x}ùgÎ8´“é.â9|ÅFþVëns÷寎© o¬¯W§ˆêq•èJ^®KrÅv I°Tz5LÏȵ;B€¾fü³¾Þt0¯E…ƒP%X’I$©%õŒ™. Hç=R¡Ï™Y•9d£6H*ͶåŠáÛ¦Û G%í0&G•q¦Ú=Qù j! GÓi¬CÏ7IIf„”·„žÌnÒ{´`É·A,§Ý¬ íºÖ‚¶WìqiÚÅŽÀÊU„òì|9Åd ™q®Y5SŒÄlÍo’lQ¢O²‚·ô¤úB"EXˆ.Ç2_~"ýD`õ`}«¯‡èÒ¨¿µáãÒþû=¯Rwuó¸€wŒºQ’zãl.}ã}ÑŒÐtÍíTïÄ ‰â÷Lâ¹ãì ò½Fò(›<0Ô-”@’›B¨‹ÕpÊát^D—È¡R³±µÀ ­Hçûã&šb½Û%+5 G0¦°Y±<ð‡ tºÔO»—É¿ŽW¿ƒmu•Àd8Šo¼Åô®¤]zÕõ[…ë•hƆª¢aÉ÷4Õ!«„Ù)@¸¦ ºR8<Ø S ¡Îå !‡ ‚I¸Ö’Ãxæ£W~nÝ[’Ü3_ñ)¨ã»@›ì<²Jo]‡ F‰\„)(!Š„°ŸG c’è®ÝøFÝ ¥Ö¥æVwU͸9˜ Eˆ“QFÇ Èq1Ÿ3Œ„L%{ÐÈî-z¹ãZÞ5ЖºëM/1p2˜’̆æ†&[U—XÒ7³°EÕ¢ê–ôDŽ&Q¹ª=m#CJ;ùíÕ%Û ?Åñ­†ƒ8ažVB¼×ʃq ¯‹°3]xZ\ízöy%Û%4æ’Š‹ ¾oMB¬ŸAd ‘ ªŽ¼(Ö#pùš`‡ïsÞ;£-éb°ƒ ¸mÓÂy]XH+ Ø¢£eÐåÕÀùëã‹4]€Å/†àϤk9Ao„*da(ˆû£‘/âåélïô@õ|ýyŸ|;Ä9Aá èêàyßl_ÌÙ?s¿³.4ªó÷oî~<' L°®9ydõz8gYdªyà;ßwMÀžL4p2›¹å uœŠÀfrÙM :¸¸ãŠL ÐL—¶ Ø¢;L¼„k®%øpµÖ­F7ã;Ç0)Þ7ˆm\´äTÁmBßBæÝPJwŸË°m"¡y\=Îþ&™Ôt÷r‹oïvë÷·wO»]Ý™ãïANý}žµ»±zÊ9ˬNíCMUe×Ð,Ê%t€©ßÕ½WànVêPI¨F…›ô°ÊT[nt³ñÍìóFu›S‹ wówxúúŸ¿=Úûu2:¦â‰AÅGT‚¹B6Æe€ã¤ˆP—|ŠdºÖ¥ú¼{Á31r X˜õçøU£A$¨XàY‡—:ŒævXUGPד²wÀ‚¡…R|uÔ+“vÚ‹‡Ãñ6Á•'KíA&è­[cÏÕI<Ã7ñе™U}3dÛ\FÎuF½”Ü×ÇÅ;¦4Hò;ƒ¿½í/FíêÖ­+EÎ «‘jKA-5{ 9ö_®§Ã=5Ðn-uOw?ƒÃ×o&“°¸ò†.gëÈpã£ÓÅzü‚öÀïjˆP/ŠAôMéÒ9óuõªEVó~ãycÌqé÷š#žëRIžËUÈ w”\ª S6Æ@AŽ7˜ìZWœ¾ ®Ý+çsÛAâ6ÙšŠ²›™nú—Ê€ÚLÂj»:3¥ÓÒq‚‹ )UÆZW¸tƒâŸ£¿JÝŠ¨SÞÎRÁ)“êÖìâþõýL½x‹§Y„#h°.F‚›FÄï( ÀUUV3µM,ÚÑ ;SºÖ-™ÏC!Zsƒ˜Ï®9˜+dª|×fuªñçåA1£éª„( ˜ñx;6!œ¥ÃÜê˜øZ¯Þ¥XzTf;{pÕ<*òW®«å·zNt–j¸”WŽÝH2oáà¶GÖp´·­§•< £/Ñ{Tù/תc°¦ä¨Á‡8x$%w×ÇŦ¾>¹,¹uö} ù½s]L~Kó|Oƒ/{ìj¿P³uð×µ£^íš]èÅ/ÖæÝA]šËy$ºîøöIô‹¸Êëx {¶_Í<>a/ú9ã {uÎVü…—ˆá˜4 _×ì¿w>¬øbvâ.WT­×ÍÊ<ƒ.ý¸ë¦|c+þ¹x§ÃXüJ'¿‡Øù¼Vá1—å7ŒF¦°ž1ŽÑãçŸÑÆ“¥¹£íÇ'^#Óž¿…ÇÚ–B¹fœG¿î N’ÀQÊw—¼X$Š'ÎS½‡"›ö«å ÍíVÚ¢mFvŸ®NÏ&^Ÿ'•§’­Öેò}ÞßT´]c½õåše!Üß ƒð”lʾeѲm=ðøñÆt*Ÿ UIgZôqQ¨©ÒP=ñ®S½S'Q!ñí`5ÏË›øŽò3¿Áô¸lÞ¨Ÿ5ú›ß9ø$’IRz÷³cО3ŸßÀ“ Bþ¿~ ê"ÜðµØlÉt=9Ͻxò»ý<£”t> BõFð;]9$çE`z2”íw|U•BЍYŸêEîöM ôtfÖa‡‘÷2u ƒ>Ûé3FŽŒ¾@d,0“ì²âz!`¤ qu˜µÇÚ—ÚSÌQˆ­ú* »nWê‘«R¤’gH9Á=¦SóuÒB|þ |C´ •¤ï9èf¨³3©#À¬èˆ7XL˜%´ú¤jÂù­Ö⹉uj­‡}uà5jÂ/v¥ëˆYÕ —k{xâ³XoñWž/Š4¶›–ñ‘¸ª}Bƒ^©ç9oCªÿâoî=·óucÏÇ6º”K¾Ïá©_ÓËuÄò N‹ ~iz).±ÈÏÄŽ* KoW"á×KmáÊ“vc”¦SÐ*ª…žøÐ4D™…§å¢ f'p¡ç²ìŠêhït¶«sµyd6ɶLÉØ"ð÷]ë± ß¡mɨcîßtº$êö². m%u“­€ó”¥ÀÛÐGPÙ„ÑN»ú.ŒÖ½×£ üðÙêøöWÃ-âíƒ_š™èš/—¾\,\Y‘fÂ’ºR´÷ŽRŒ5ä‰E#»ª¾Kù/ï¡E‡ #|†b“ ÜBr×Ñça.øTdoÄ>Xí#kKµü ¾† +ª‰]«¦8ÌQ†YÑåÔí"8 ”AtámÝÐåra¯ŠÊ‚±ØŒ\o¬ObÞÍë4‰eçæá 9µ(ÛªëYnñ;GBê(7}hGw4£D€P+öÖΠ̬° §"¤·òUiÉn7G0yd£ÛÊ(QD‰UK" ˆ# ±br$ŽMãl† ¥7ÜÀöþ  ê—·xŠã¹™Å‰¹.4íTPfT—^ú@xv„2ºÝæaQ0Ëù•}â×6]uN¿>zŠû|¨’BMQ1ÑÍf°MàF¾Ÿ[6ÌgK—ÔžÞ®Ìi¿\¬•å”~Fj³ ª'WC¦tSs©u§(•ÕÐ?6Vyâ…y”¾^Êχ.¯nsÕiPŒWe~"‰}-Óy助`1t‡Zß®‘) ©²XÆTQÍ7(|Ó¬ÓyUV~F|¬ÌøoN­ùÙ*˺üØ-ç2-dbJe“£¦ f?Oñ$&OvgŸ[öó¢Ez…zηñ4k‰L§*°wr%Ps†ßé†-kœAÚe”1°LÊå%?E|ŒÛuõ–¬ÐD1ºY¼¹•u*© °Rd:T(Œ¶,#•2*T†L”+^ÓÑñ¾öèå£I‹­°–yH5*È›3Á®&ñ’ÌXÅb"L þÅ”¶(a;fK™BÙ¢{ ^»irpºæ5kQ‡^sÕE¢µ+W‘X^,DŒÞs°ò¸Ô-pYƒ@H"±Aœ¨“ôa¿òøD…`bTv¼ëöɳ®”0‚Î?'ëÞWôòsá-«Ê5®ÍZÍ~ÊL -i-´UÄÏžú}a¬ïùq¦ÃUwÔFÄ ¬èÒoƒ=µøìj²ä¹3«æ½m ˆ– Þ"žßfN#KÇID¯jŠ÷åNDžFw±<áOïuY êTïÌFæl¹uǽ*²ƒK†”š&Æqy€}*ƒÁéõy5}Š;´ÇH$>+Óä~V »¦(mB¼}ÞÆ˜öôÂL7 BúP¬Ê`;ºrÂÉ.ÇÄÊ^ž*…)•±fT‹·vbì6Sº^Áôt¿~×U…ÛùUñ釸pšàFÊ‚s¾Pd 9¾·ßTÛ×€É/AéAŸ7‚0Î1a«pP·ç©­¦¶i‰u˜ì†£`˜ÀÚ„ç&çæçÈ£2*9òÊ/ZÒa} ­éòÏö¡ÖÖ‰î¿-òl—bˆ$‚J%`+LݲøN'ƒ*g@¤!÷…Dλ„°?5<ßøk« ôƒ„l.¥ò€ã€…µì*›<¼Á>ZHÙFÆ\AæÃ ¸ å=Câ“§ŽFOHXˆ»À·Ó“br3óÝ;ðVñCÕq=»0•ª7\·lOEëbDb£Óx¨Yñ#ú>%éùu<ü’ÃÈ¡±ÑÊ‚ù …‘ê)&nPÅ5êZšÔ‡ˆ²29GÓt ð– ±`3X!*Ñ{ ÷]Y³|qéžÓŒÇ€t$0ØFßc„m}5©ÒN> w•½øÃè‡er¼FÆß‡ 'ÈÓ<·Þ-•h>,z›Œ²q™môä²=›—TõšÉ*/Ü‹c¢¢ûT sRJRæG²¤v¸^µ£dd…Åy(Î+%(ÎÃU5 c&ÁÞzäÝø{Ö+{R Ñn .7‚ú0!âxÀ†x~·flB±7*ˆËb'4Ùs»ÐÀQ…rÍë[ÌÜ-Àãe5¤¬ó++Ù¬ÌÉVbÎ“Æ¢ÿ_+ð¦çZ5™–«…ðbðÓEŠ”®¾´vd,2$^âðák1`òœ¢û¡án´Í a6¡ºê†©Š.5Õ€yµ÷_€˜[ºða,V'LV°M®xØ`ÕíZYTß ï²"û ©4Åç˜WI\¹5.KÚÀÕÆæL3Âú |È¡=xÑŽšÕ£cf”JD‰Z²4Ì6sšÄ¥T’‡Y²Tž8àãŒäãD½ž _ŒZ6MHtf×9]9¨–t‚KéUiÊY¸Q q &â ð+jbÁµ> ¾w`ðp Pi?p¥XHη?—7eTgXಣ wÀ¤JAÛ´•íK¼[ ËI>!œ¤Âà$Þ¡uÆ»í ˜«Õ^…7 Qva'!@Q†ª-ÄÁÙ‹PÀ´ÇÔPS=À’¥H*Ø牜}<ÂÌH§!ž³‘²" D]ÚŸ =^íj•̓hƒ¾úOb´K U—T¦ÊgîíòµévWÝ”­Ê’“Rt˜ D¤@–‹)ÌM©@[,é>u+2ÆåT£²3M¡ëˆv»¬ß 9 ™¾• Mx6:4 I,ËÐݬŢ³Xƒ¨ˆ[¤ãƵÌÒ—Åh*s±¨ )ÉÈúÏMhí¶j\‡T0|œT}Èåb³#Ì·[¶ãï€ÂŽ:Éâ쥯b§iK$æ¢ô/,ªYq¹æD—[?5×Õ­÷¥ "¡ *…çƸ xÅúH‘²äÂxrV݃fÉçäåJ /ˆà@‚s¥}½Sw˜3pš’ Ò&%À$‚Ž)ÜÊ0áw=2é+tÅkÐ-5Lê.¡çµ6†“¶«ñåaª“?H­E´Õ§Äb—ìÖ×»²RìwæQ›É¡ÆÂë(e2Émî’êÔÃK–²\ù¦×3L õ˜J€ƒšî“•'vtå;ï’ò52¹FœíMj €Bó e;RøäQXg{(mHˆ]åWaú«aiÝäØä¸¾áZîÝÉfÝCÊQëVŸ½€V‹±S¨2‘`[ÂÞWÜRÛu·~ÛáÆn˜†ÙLÕê²ùhš¼¦a¥Ð[uo¾&ª¥©e­Mf’Ê&¥Ëλ½àˆý¼õI`B½—±Fó¿z›²¯‡_)Žì¦BW.€AƘ«ÉÁÈR|ë¼·QX鎈ڴ`ðß‹†œÛ|àœÔ‰£Þ‰Ûm¼œVuIW ­3›ªpdò½øW\¥vG6¸Õ.o_¿N亗è¢0Çèl#=‚]ÔÜnÖ#Ëbÿ3*_ç7™1Ô’*”7R„m¾©î‡ÚßÐ9€°õz0ú/Žx%ˆ|„¼†ñ’<ÿ=^¯©£r}±¬8¸aQòì˳×óeB9A>Ê7 ×±ö€¡—®5'1ϹzfzqpÝTŸ‚Cx§– uñösŒ#OíuwR·à>æ×þϳý¢ïJÙùl­1Aš@*“7½-3K™^rM*ó˜{¤ÞV052*HQ!Ž—Ñ¹Qdxêj@@PÜ-}î‚"òTµIÁb('ÂH‡)«ÒìXìæSøåœ¼ —õ³ÞvöP|Ûìç‹0ö„DaD@‚ áÍvçšòÝ÷Kß:¿Ñê½J¢ãñï™ïÒIˆFð¤¤<°(ˆw¢ˆzGnÃ̱)*ŠH&æÝ:Dƒ# "…5¿ÕÕ  cнáWÖÅb \]⯠54Î1'€´¾ä7Qé±¢ì#ô üÐDöß¾?q1#^KðjCå5 q1ú­q8-qüè»ônµ×J³µÑ«m¡•ò3?žñúZIŒ]3úZÿ{Õ’îËi¬®Ã<~óÁ|¶Kh€l…PD?aG÷Á×¹ÓQD×…Í,×9(GøÇ"†¥º[¸gý'­”j"½*¥;¿{¹ÀÕßídsC°æøª_fl4Ò‰²8¸v£]{%)^“Ȳ/9=°å—(5›{m¦o‰»i¤ç—ÝŸÇ]֩׫|lÖ³è¢ð5°Î[g~ªåªL+–7Ý^Þß-5óü+*/”wå\`x@åµTå$Î!xš÷½ï'. xåË‡Çæø˜÷((f£”éÉEm·;q ‘§.jCá5 q1ßÍk‰Ák$]Ëu®ºU®]ûC+äfxæéå?£É†<5n:¶nø~…Ø\LO›ö?±[\PÕxkƶWMžk©ÈĨ·*/øc°YQIìéQC²ˆÙ´o£Í§ÞÛÔéGžØ¥ågÒ¥ÑFÕE°¸mÄŸå½6³õ…®âO Qwê‹åÞ*¢öª‹Ù‹Õ ήøsÕC9ýÿ‡~Û‹âåÉÄçk »œ<ñ‰òrÜÃÞ¶?Û|ÿ¨7Úüm¾·ûž÷¹ðêá«U;?/M~©74¡óÝ)ü?%؃û? ^áh£lïáÏ”µÖ'NާÇ#6w>:îß¶»çœgšß7bÅß…%ȹïÒË®ŠDªÜÛ6ç!C-ÆVÛ>ˆ¥M7[ç›dlÂ÷Y•·?W@Xéêã^mæó¾¾ó.Ô5æImÿ¦/Qvê‹DCÂT^m6¢ÊCÅûL\,y©â¡²byìUÂŽ&þÒQ)Vµ­Vµ­kZʵ«TVµ­dkZ‡­kZÐ4¥&XHGyÊNói2²x‘WŠÖ•ªÀŠÖµ¥b)VOI©œJæX5"QJ¥LNF©ZÃ=%9„›»2Îf*Šô‹ U›ëÙÙÔ7qx^?–|sx+y#ÁÝ|—ákcàïLJ‘§ßZ2yv5¬º§ÙYalµÉ…m•ï®û6»üzDæ™|ùßA\\x1àý[ÕéžµÕÅÚÞ‰SÇÝ××Õ“¶MÛØ³‰ÈÇz»˜™<;Ñæ'*N´­(Ìë)Ns¡VjTѪËVRâ³JÔ4–•¤ÍkuvV¨ƒX†pïQÜ­M¦jÎíW£…⓳™HR”3´î¬¢°k½ë­g/£9¬9’¯›¾Uò·”ïzéÍ:æh¤âS¬DéU¬ÜJ @‰ÓäôìüÈóü¿ƒñàüàÈ€èùÁQy– È„ ƒ$V¶J¨‰”M,ÒÄRQ(Š(¢’¤¨¨Ú¶±-+h‰eŠŠ,Qb¢¨´DX”±Uš–ÔTRId­  xŠ‹ÀUoµ@Ú7%Ѻ(ÝY÷lû«î û¦6tYBƒd!†Â‹(„((賆Š6YÙ££¢È6th¢aˆl°á£DtQ£ƒ4`Î:::,ØÃeC¢†h°³ 5Ã2†PÍ›(Kf ‡D l†,ÆÍ4th\gFÎ g° ³e–x]ž†6x4hØQFŽ”Y³ 6hÑ£a¢Œ!E–pÃaaÑGE4QfÍÙ££E®ˆfŠ6pèÂpg82ˆPlÀÙ‡GƒÑ‚V –p¢œŒáÙѳ†Í8Qa°³¢‡h’’Eêª.áƒsBƦÆÂÜÜ7 fæÊ8tvh(€t+4@‡Ù…Œ²Ž”aÁhÙ°6Cf e”Qe X2ÅF™Ø°\‚f8,73:}@ÅEŠÖfÕ‹ZñFQJzEeFª´d4SB³£Y¦¢c:-tvvrªÕö·»[çyÝ„ª­§“ºe€&s”©:ÖuªÖ½µ­kZÖ¢³œ¥)Z)‰WÒª†ŠÒµœ¥iÎt•h¢LRKYZµf¬ë)¤å(éêV²ÙFë7µ—ãy×Fk5¾E×35£­Uu£\£yO0ë{ëÁ{6lâÞ÷ØÉ½g5©%¬â­bfÓ“Ué7Ô‘YVΫ+”ÔÔš,…¤Ë—ö…çog5Ã7Õ1Úׂ3O[æC‡†jëÔë'ZJf³«­XÄáá§IÊ‚U“4åW˜24„4Q+yÍßnîºÁÍpÕÞpôqg[‘agk­K×vVûy•ß“a¥ßVŒ´êo‹+®Q«!– ­mKœŒVÐ+ZÖt”ÒO1@a¥ZÃBB¬•¡!«Iõ¸kU¥W•«KB¤•äÒšÖWÀ ÒÒ´ rÙåsNèƒ4ÕLæï?z–¨´¨]kš†ºé—¬ºÃ3ªÐkZ4háfΆSêó/‹[Z²égòþýõÎh]®Ê9™|í^å«Ô«…˜X¤(4ÞŠ,'F‰ÎÖw³<-$èë)× Öòû!Uj ˆ†(¨¶Š¨Ô£Q@B§20ÅE¾¨ë`ˆ¦ %Ȫ*˜‚¨¸€ ÞÞ?k«ûßüÔ¸Ë ?àÅÆ1¬ F7uþÙ’ÓJäŽ4%’ü‰uÈÇ?¨Â¸@†1ŒNI)Ÿ«VJ¢Š¬õÕWܵC8‚µAÇ~WúÏ5í*otÓ®gQ«®/*„8Ȩ )ãþ¾ã°¶*¨âi! BhpllrTê8€PÊùªÊ0AÞEF,€‡èîó‘â“Ñ`¯ª³~ÏÊ¿Q;zëÜÞ»5ñö³ì%@Ds„Yñ 9.ÜÀO >s–€l•2_€/¿a$X@DD?»-ôÓRkÑ  Qù, *—Ûó~ÎCG¸ã–\bó<ùyëÖßG¦byÓù«ÐËJè´¡EN¹bFA<Mœ0lVmx¢…\¹H¨iy+í}ߤƒ]ûãwüßà¯ÏÀÎG–Œß»Ù¿’·Su*j›ð¸Þ#ígûŸãã†S#(ƤܷW,?;õ§)’'A¦Z~ŒñÆc§=Ñ+ú?—¿²…Ϫ‰‡Ô›e¢ÅÒmC\DîÉ?‘ëÇW!â¢R¦o¶ÞL²´gÃ_RëeÔ'çlmøZ¾±à|+p¤û®þ«ºI|{ ÈÇØâ‰røœ·èÖöÆÚü{pÒ`>‡ ÜQþO¯_p “0 jÿ´_܇ãBèI#"ù¯Á«E‘$’O'èý§Ý{¬_ßõ4þóû3Vµ—ÖözÛÎQ¥Û¦0篯Oò>M¿áÖ8N óÝLx5k·EÓ߯ïz`œ ¾>ç& °f‰ßÇíô.¶ÉæÉçííÕú:/›’ m*,D4@@‚ 7—‹MšÇ0ÙTU&)÷uÍŸ·ó𗦆Xcêä/~úìyå‰8ì%õ¦¶cèE¨ Ä^1>ú]$ ƒ!5k`d[DP20E@BéGY"ýxQcâóßWœÛcââ‚MÄáß`ôžKùWp1z¿aIhe ¨' äZ. E…h@€~µmvRÕyï2‹V÷”‹ãw9¸£ÿ6d#®ðŒ,KÍ¥IžÖÔy(4fŠu!LŽE‹lB$:“a· QÀ‚zÙY$[ÜÔƒˆƒ"†„oæ\÷ 8æqÉú7åè_ÑýóájaŸÒ“¦ØÂÄì µ-:0ÜE2l$Òa_G^¤ŽÍö9Ÿªe¶'ôOZ_§lõ°I$"Л<ù©5¬¨ŸÚž†sÏ­„YzÙôÿþ)íÒúþñì{î`zÜkÊxR¡…Q¦¨W³1³Ï¯›5³P„ÆT†éxúW“åúЇ´ Æ1Œl$’IáŸvü3¼¶òB¬qÈØØæs–•²ë |4í1»ÂfŽP²kÈÐ c#…ûp†õ«(@Q†°¡É­ÁB² Éb<›ÿšéž½•Ø¥P–?3ùÛ¯“ƒô“½XwÙÙ¾$3|á˲¾¿œ³è$o~ŒDsÅ_L¶?’ϯípˈˆ ˆÄ]yŒAš£³8ƒBÊ¢¡kP0QÉZH䎺 ”2ƒëÏ› -Ÿg´€6¾Ñª‰ó‚ž?¿á2L†%$n…X*üÕà?ÅXþIÌgÁgúýOƒ¿D¾n¿Ýhõ»Y”“¢øÝ@µ5˜Ù˜:H0ýiøÿ!eYYöÒèéoÞJ¸…}+cX×4ïWÊÏê?ÒaÛJÜ¿£nÀ?üØ Š>©P€&¨;uegcÿ¼åùSüþp;ã0Š5ú½¾Öóeçñþimžê¡eà ”ÐHÚ;L4»'àQ´\ˆ8YG)SP™r§A~‡4.0FŸà†•WÿÀÕì°BDŠ ÂP…ѧëÕ¿§kà¼^9û“„| ¥Àb<„sØÖZÅTƒÈÙ†TYFß{ûùWD*mÌ  cf$vçè .Û‚1#TþÚëÿ1 p;¾Q‰C ¼T"t÷Nk.K;‹è/nÍÞ›û0`œƒŠmó.pù+ºÂ܈[Ÿ ´‡I“sç÷‡Küÿí+×FÔ½ƒ#!˜ºØ,`3;1ï{W€F*­=cz?.ÍIêªê`àD@„„HÄ‘Y<"ÒBoì¶sñOä'2\!ì V^0>Ší{OJ¬(ÈÝL Ž:z}nÍdca…(‘ÓÎI¹õ_4t„ ÌÂb ‚Œ0wÔß•!»Ó=z9Ÿ ùë’Òá˱ƒ©õ3ÿSý¿n†»rGë¿Ïõœ߬NðT¯ëöö7uºø.¯àßý^®KíÚ<Öãþ±¬iÉÓýqáÿsõf+^[ZÊ(°°°°f­E…EEDÄëYŠÖµ¬0`¢ְ°¶Û Ãp#>øÓ¿#¯=›^{sòâßÖñ¿§ÇO/¯³Pž8ëÃæQáçç³×üª/¯–ZOÏ~ØücÍßvEíc²ê®u3ï ¿•m›?bkÃw#Údwò»“€Ý¨€ D_Ð@{QÃn.-ùÜOèiîþÒ‘÷ãtÅíSkg}ØMcÏþmö±?‡½Û9_ß+v®O59Êç˜OíïðòuË˾ٶ Õ¬{>€{÷SXøì¾=ÁC—ØÁ•«’¯Ì'9øƒŽ9$Ž9ähG¿j÷*Ûm¶Ûmi»ºÆß矎pú 8£ ?]<¿ÁDû+'·]ô¬ãdÛlA§øƒ¯kš333 Ó%Ü4;i·FÜ“N©JqŸ–9”§?¹?E”A¹Q¡B§ çÎóž¨_©uaÚ¾^àûsäØj¿ãê½Ü’O+p纾ó ?€Dóf]œaEÕ_1qŒÞÃ0¡A˜KÚäºÈ£ êçÐ ñ(©.ªfMÒ !³ê]QMkž¬kq Ø}¼÷ª ãñêìq¹$Ên‡éÇLlû\µ¹Çü5+Œ¸þOºÝ\üÛ;ß&ÌS?ì ×Ü @gäÕð3#ØüÜ1øä>sB=£_ˆïò¿cÿ« ,šÀË»¯Ù¯xÿ4¼¢`}úúß'ë­ì,c¸÷¾—g=Ù~MÚ¾«î¥¸¯¯¿o6ÿ‡ÕA§w à?¯Ó|úÐùdWÙìùÇ7­GŽkÏOññÕ–õJrlëøºz§®2ùé¾þnwŸZçۆíûÜ8pºúÆ#¦n1×ÇíøGÊšå«É;›¼1åq,FÌbsnd—$l×g^Yû¿¶ì¢[ŸäÛðú"YíìÓÇvåñð©þæ»­à— ö6\®½~~{vx=?C /òªõ(ëíöÇ£­§—«?ˆðËe5ò‹äJ¹•Ú¨|¾7}ž‹H»äuõÀµº1»O¡šRí[bÝ×ìÃÏ<@ËÎ)fôŸV+ãï'{Æ}0«æ–¼ð¸t§ré¨( ¯&ñzTø *ùz“çåàÛW@Ïâßo÷ÌÏ…¯~=dÅÏQPNP9ñ1Æ0 £IK*æŠûŸ.šûEí_]ì‹pÊ+ ’ä¸FѬ,TÎcRSC „ K;‘æeóGN‚Çî¬>ãE´d?¦gß«m¶˜ÆÌgîy-¶õ; =Cº:‰«5jᱬx>Ïø{uóhýÿÝìÿ·ýF¯ÖšþœºÆáqOá,ïlT´†dÅLs)@, FÁ ˆ@@y<¯÷uýg=°y¦/iÐ4ŸOægŽdCÊÞt½¿5Éäà=ÿÓü,÷²Îùmø°Œ4ÜbŒQ±¶œŠ7ßóŸ9ÙpnoŠ•CøGñ?ƒÚÌÐ~÷§ ‘¹EZÅý䟣º2WعÎ'ølëwþᥩô¢å†Þ¶ÝØßq £Òª…*’ Þ5û?Ö»×ð‡ô~Ïoí)]ÁŽ}a/ ÌÊXGEØîð’ÚnùÜ¶àŸ§£Èí¸Ï‘¥„„މ£Ÿqq ~nÁq\ƒD}5ý *ÿ}öP~^FÓóÏ—±÷ìáb€ (ªÂÀt€…6àsSǼÐû™x;„ùÛfÜÔ^—É*sɵ½¥nÆh¸†Ð)úýÂpO<^äçèN-pï•ÃÅ,bçç¡í&†—Z'ö>Ï 0ËëÌû€GåiKäw¥ðkÚ±OÒ4ª§ÍY@€õUR¤€Î.ó{ê7¸¾ˆÖdVøl |$Jð«‰2hì]+lÄ¿ò¾·tž|ép¾G^zù÷ þÎz!ñ®wÊ›†±¸5{²c—hØÞù4eÝB¤‰+În«#vþtÏjÿ}ÿéØ~˜§l”Ò–ž¥T Ðî…ßòO¡²ïòüPhƒƒ½Ó\]ª°¢‡ÁÀWž·òͺq‡ª%ëÈ ‘üåùÜdûWü6 ÓA:-ˆæ}L©;§ý¯f–/Ÿ®ë4¬á£‚ÿž¦ ÛQ„”lo\~›Û8ÆÆ¾Í=7?XªWEoeí»='8кÚIàuýfyŸð!űXÒø~¿êVV3YRË©~Õ)þúÅ·Zý3@£ç! ¾_µªÓ¸&ò—ìú¾ØmÇ‹5x[éë›Ì•Ã6‰©»?GæùIÍÇÑu^÷xmõw¾,¸VßÝ+,í£ÃœE½½uì½7å¼kä[–Š‹L „¥´L¡xðˆT·¡GÕ=ºý{¾¬´÷WÅÞq·:+µ½øté®~üVtTÍ¢“hð‹ˆŸEÁŒkS¯os½FHH60 ‡Õ:øo_ËdA~ùиíÕ~!"8àSK®õå”òòñw¦_qJßd°I‘]{Wø£go à{*۱ɆŠÍ¨/?³òûØþ»k¨OvñŽk­/_<ëäÂ/§"‡³+Ê. .ÃÛ»’8?&7¶½P'ϱìvw~Ÿ‡+ŸúåËòû{¹¶‹ÆÂ2}[5i®uM•œªŽB–µ¦!âm7vwšó6½{8´’ùÏÛDˆËãè•Ç> }°øZv±zjPøÇ3EZk¯mÁé°ïøãÈüp°ñb±íý¶üîZÞ#­F—)~Ÿïpß·%~¼§ÛÞßIŠ ¹&/»}gÖ}JoÛ½=g¿é?kYƒ³uHBM~5¹~^û/<1{7Å%c¦Ÿm@9ÕP4Á±Žþô²ÔÛ®¿wøžÆô&Úì’fYŠÙUж¥¹D½nIG@³D3h`ÛvŠ”Â23á">Ì ÛQ¤§ÂS)ȳû¹úýP:5 c9rgw¦Õ¯f#(XI¨c¨®L•¦ßä•ùNƒ–WÐuz¦u¸¾ƒ;ˆ‹Ž0³ãUcÆÛÊü‹†â\¥õêÛG:!Ö…Ÿg9½Mi›j®HG<¨pl0;è¯" Äsj¤¤`înzˆðuÍÚ\·. ŠÝòÈck˜Ü¨Ô¥`)YÊÑ;$¼÷’€B.™­v?c8TklÞðs®9³&äÙyÍÍæ—…w Øô_(.¬ àÛåEäT¤÷fJd÷bJ"Øi i `ÉrêÌŽ;¥h&…b8€â»ªê8cÑúÌ^‹í{KÏÅÑ;0ø Ø^xXéͱÌêy&ÈXC° Ê@ÿ6:Ûz[Þ@C:òó<èNs‘¶<^Ÿ¦Ã¤ âkiåëys9š9×Vó Tj@‘$a I)95‚4úéj?þ~(ßôþº/žíÔçæg.^A²ßÁüÈ®\:u—œKpç~òòöÒ¿ªTzÒ¿µD&Í1$stý©Ð}óÐúÛ8ÈæÖ›qx‘èüwËtÆ[fuòÀëïèN¦ýòð±Ï‡Ëã'M“Dǽ³Hþ*…7òMǃéoí£\íl@ñö:€Ö¬mZ-á ¡€Ø.ABd /!rh‘.Ю~T .Sûi%DEg”6Ê{o>ú‚Ù}`¬ Š/áNƒßÑüß÷·O5÷•x}ùNÅ”Wñ``\aqL«­áËhKŠ c%Bèw%©>Õ/þŽƒênÿ; ß=Ï̇äÅìUPÀ¥E‰X]a£¾( Üš”/åQ`ÙQh¤Ž†5 ÄKD$dŠ‹ÓôJ‹òþµw;»®:Ì–œÂ[“9Qnë¤ÅÜ2W.ÉvxaµTFšmF[s÷þ÷¦2àá"yú`ÑIÑôÕ:!¿>R çhžTë 5³ir ùÙë»~DÇ:ï6·i¸ÐŸÞÀ8RÃ+ DžB–¹mÂ&}D„ j{Î&ÔPUTrJ³¸Ò4¼Æ®ý8`‚8ßÙÉS‘ÜwœÝðˆ [Ïa†ÓE‰J º”AD_c_nóGµ°"A@ @d5"¢‰- ”XšZ§}àïó9ÓAuC¶ÿÇ¥Þz›ö¶àF.¬„V|.Œ„ô^K4óJË[Å2¨®c/4ßsVh¼Íîï ¨¾§C/ŸÓÎGYV«Ñq<Á«šhâqýû¬Ï¼w}1»7Zñ€y«¹£)¤dÝ:\ŸÆ”mÈ繸½–Vú½¦zþk¡ò|žÀµ;ð,iEÏ™ßkr âÚÞ߯œoÜ—YØ/Ô…F@97[…æd?RoÓbb‡ ó‰V“ü¾à‚€f$k6×a:'¸L”¯¢@Àt€¹âàˆ\çÒH™1¸“ð}#¤[Òè'w•S ¿Õ‹äh9G4À¼òh„ÓíÊX³y 6–Š.âØÒqà‡ާ€³Â’Ñ`4(õ<Úd ,!ʺþëíDŽ'Æ5ÙOÒ6›{Š”;!ÚGë`ôŒLªì£s…á!]7ÂÜ!èÓ•Å=—ü‹Iá.íÖŠëä¿’>'¡»t•¾#‡Ü——Æõæ/½_楙NÖæ¨ïÒq÷ãi¬–m18K£T´ÅRÕº‘i:…åÎúÞE š@:nûXW'•àÍk‹é.ͺõ,O¶÷gÞ·ôª¢ÓÑ μmûå+ƒS2"MN/ueqò6à ë;œ­l¦}M²êºÝ¾œuÌmf~Ïû¿«P‚µ®‚¡ˆï·?]!Ié¨ëjq»'x¾A{æìü‡Å\++ÜlÖì(:¶6n²—ðëèµ.OÓ¤‡M`XÇä2´–Å3þšÅÓlaì;h×Mçºk(:©;=PÖŸÞ{òíäL²?Òdõí_ £õäZh&~-”©œþtµ­yó= nS¨ØÞÌ|-3S¼:u_)£ºÓ+‹7iµ$Šo8~èÇx7žRŠÎÑö–àOž}|Ó±6(™‡&Å<”ZGÍôÔXañ¡L£­1Þy¾Ê6¸ºà)|±Pƒa÷rϘLJ‹¢Ý/À¼/\4J×ô=¬5‹¦xÃã^8zãl‡xx¿OWg¿i÷졸LŒJª*IÜ(lcCglivý? õ£ÑÑèÑ*zÃBëTÎz¯Oxë­ùèºß•ÅÒ º¢­¼iBå46xÆ›CÏ+á{3£žnÙëÂÊ8xm¢a E^ í$„½«ÇZñã×5æk+ÛxJšGƒ ) ˆž"($=4€ê™¸;£Y‡U\ÚÃgªRâ½UÜca kpÊ+•JK8ïr®—Á™§¿/~CíwïÊcýÜïYbî±Q|g­ÏÜ~gÏÌv¿A…ÇKï?›`ïõ• zY4ñY@W±®ÕÕîòu»©µ×*‹E̪-€@¼PbPlƒDPG¯U¨´*/±Qy‰÷vøþšíó|¿/ÏŠÆ é'\¹¹3[ε4KÞ¯ZÕÔ9—ÕkRu]u\Í;|/N'Rže¹½îúÖs0ÝîuY:곩WUÍVQ{‰!-]²b墸¹³}oxûæç\/4ÍkK4ºj6 è´.0,ë¶lÑ t¨Ã ŠY„!†Íš6l8¹Î/F±c(lÙÑa ÃibÃáÑ££F01ºôÊ(àX™ƒ:“[!Ðtth³fÖ¥ê΃†ÁìáÃkzÖ¶QY¼]8læ q ßÐpá°À±³kßG S¥ š ‹h:8ºV`aÖÍô¨èéÚÃ|4›4RF6l†#¨Ñ££ :8YjŠ8Z,6DÇFŠ!ºK FØt6Œ8kAÑÑÑ{,è!p43†’†ƒX©agF[ Å£F4p±@굫(áË,F‘šÎ!¥¤i@â6lèèèèÙÑÒaÒé.‘ÑÒèèáÑÒëfÍ4h0”t•Q×_, :a†ºÎ©d:8=¬4Nº¾±qÑŒ¦t†ttl¨B§àpáÖÐ0f†¨Õ"ºàp,\! -õ­jˆ!}8i.hEhc¹aÑδttmmtqpè½›Ýo´b²Ê:]fèÒ’Ãfµv´°ÕÔ- …ëXhÒ3†,Íë‡]u×]páÁ#‡‡G Û5²¨Úß’‡HéZ݆stÍ»-q ,¢ÃG‘EpàYgE,ÞŒ,£ÜÅÒ ½Œc0àÑÃg íQÅ 4YųC) „:(+}lѳV“c:4aÅ££€,³EQ…afƒ5½ï}.tlÀà fë¡p  Ø´%¤i] ×AÑÑÆùÃAT^Z¨¹Â*æoor‘„aFL™2dÉ“&L™2eS±£¹“ÀÝÜÑÔÑÔÑÔÑÔŒ4u#ÃGSGSGR0ÑÔŒ4u4u4u#ÃGR­í2õ½¦L™2dÉ—µú·Ð?¡¿ïkÛùÁàÿ+WŸìÉ_¨Ž@zÊÔ°N«tsÒ+jÏ@Ö\%®)K¡)[”S£C1`Ó n¶ñ錳Õ&uˆ¤£dø:«ÎañP';`óª^.x/¡A}Ú±´¤¢Œ2ðù\‹«Ta¥©' “g.köíÎHˆ?¥°pNžQμˀêËÓÕ)-&Îz¡êæ ÖP¯JÒs›Ý%¶ÖÀ³™WÀ3`ÕïAŠV”³G]cÊ:ÎcÖjúëFoùÔ9Öõ}s›ÝÔ{:ÞΗ 9»×Fù­e…iÙÓ£];«Yš5ǽS¯‡Ëú´ŽûØE}Ï•ü½‡‡œcó>İŠÁAMë´’4L±-SF0Ós·hÈfþwDþÑ"vÊþù¯ÞuÿFÿ&‘Y®§9I°‰äC¼"©`¢õ'›H¨µ½õòÎ1à.6ZK,ÛY›l–6ÕY(ÿ¥Ñ¨2ý³öõ<ôÉúë¿?ûwõ·–ôõ×ñ)¨ŸCÛzKsÂÅ= ¤#$ËÈ«_@T’@ÁƒG(H1Î’ˆIZozÑ2åÛنᵖ¢CRb‰:ß¡â*-Ýz¢ÌOCŸ,Ml¨¹®í‰µ-~Îý{^ç´é¡$;iÜî9Ì-'£‹„\&Œ¬Wwöºè3P°^›6¾Ù>²‚ µåé ¹ ¬¨½µ £ù QHúÎr>Û¨·k…å•WZšëšPA±Š‹¡âöÀ)û˜…Eà¥×÷aDISñpsN˜çúg ¹Ñ¯¿g¡sôϯ¿×·3cÇû/Êoû-MâŒÁ©ÓäÆxº(ìTÕ2)¨«=Üð "yu1)H–œP‰À]Ò¢ ˆ–ˆ„DUÑ@µÍJ¢ — Òµnqk²è·QèóZ¼¾³Ý/øù߇›x€'S‡éçQ\×*×U‹¤*î¦ JæîËþ-Y­j$$ ü,B?yÏØóüwúü‚¦Rb¯•®WbßJø~.2`vÜÆîÊëo°C&vÓœLÙjYC//œõØŠL'qûÝîÅÿqXÜ ªšÊšÒsc†Ý’:ljâð ,§²«O?v-YÓ_i¹¯³ÉS>ܦŒe×![B_¦’[BX³¹ÏñïqùŸ¯ÒHK®p×7Ãñ®³ª+{w}Õu\ÞŠwŒåï9¾¹ÖuEÂÈpØlÁtl\ 8p6Q¢Š8láG „41룦J­•)îT5W£­–æº2¨Ãg:§£Ö”jLMhÅ`ÒsaQX”„W¡>r³žb sÏÒFUjÕ±™—õŸ Ç¡}ë?Ùð0ñ¢¤ôÒÖŠH“`#äIj0PI(”ÆÚJ+W©¹I¿'\Ó»‘®í×:Ï-:WÁ¯š|{ü‡ÂùžW§s«‘c!¾WÇ=weŒUôÜóµÔšÉõÕp4ÜÜ¡4˜é“yæÄ[ÓJÚ)ÛQ〠–÷«’là)w`¦ŒÍ¶çk\lSú¥Á‚CpŽ»àø*-̺Qù`-¨õè½g•êõ§Ù‡âp¿Ÿ¯D-iOÃñ«á 8p‹ ÑµEáÒÊE\8QÅgXsH:(éGpPe²Õl0Ùâ‘¢Ž–Α‡G@öŒ¡@ã)õÎ#Z+[:ê•oP?‡þ-¼×W}?t Í™[³àà 7âÝ{õªµï·ÛZ«_Çêý Á@Q"ü³¦" M&»¸cd…ˆÚ$‰âWºÅpZ(~gœÅ:Pð7"ѰNׯÞþçú{@W=ƒ9e°dpaý}ƒ4h”Îö`W ÄlAXbÚc({£gG …™šÓ£c[°Ñ…k…%…¤[,‰ABa}ÎÿgpÐÝKª¨Õ¸á'lº{ÈÖë.ì¡X¤Ö®–Ý÷':~ýÀªåóßéÒÿv¨/Ežaέt)ŽÀ <¦ÈT·sj}äК¶ß³d÷ã¦ñξ5ŸSLGÔ»è÷ŽÓÍ&Ÿ4g;hï¨Ft˜û=¥öšƒ»æ½‡½Ðéùº' ©9rº›Q-q6ÛÙqWVÅŠ÷uˆb²ÿÑü¶žï»øÿœ­2 †#ç?ÌnubA½_@?Ôü?٠蟃õýÇòoI£‡ÒÀ…Ã1-BÈ•š„Ss‰ÔfÿÆoþe3¦Rýbîì»M¸’I3Xðc¶‹²c¤oÒe¯ FêÀ4…ETXTà*/ 2Î@A.•›öö8G⺭ADe G}Õ9•4O¸ ²¬4ºecKݼ?7§+~‘‘ ÛŽ›\üíOŒ‡Úí×,|nÎàdˆñœDPªýœj¥]Ì©f¥*ÒxyÎm×[åMu]9¦3gGGDaf c!Y†Œ6QÄ6lÙD±—[ßZÞøu×Zé¾JÛ]>tiõÇ|ÚÙG\7·5³Ozª¬gj ° †¬ƒ ˆ°ùMçþíðÌoþ†õ! ož¦’“‘C–EyddX½¨AJ"¸ÑõbÊl¢õ>Α÷™:Ùxä*\ͰgÛ/àgú‡)1†MM‚è Q-G†\µívì²™;•i~Þp]ÙýT]-ü ÇÛa;qI'l<u_išgÉ©È ž]3ö¶U@¶S¦Gù¿Eµo¹”ˆôÔCJݵüð&j QQÚÂËÚ»U¤uµ™§Oäö\P—Úè›?Ð{ÊÚÓPÎ¥¶ o‡ðrç]FŽŽYÎ|šöw韻–DP׺VçÓèBò(¦U ‚;µuÝÝÜ) å[Ÿñ]ÛûŸk¶Û ‹2¤j¿OÑîµ}÷zµ–(úJ lQkö¹…œAÍ„€qpÂηÄ ÐDþñwØwˆÎÌ.û6‘fÍ‘@ pÜÂM €(hˆu«Ù”Õ^j^Ök1¯^Ä-ªõSËXë*L¡ [#˜ÿþ¶§ñÊZYñZŸäãnÜ6‚ ÁØÄ(µO˱/Ìarì}$ÃöÄ’†$¬ÄûþœB<À®'#™„¢V»wrþN²±öz®{‚Håå¡p÷@¶C§˜\„KÜ ÔIŸã°”m Œg†Aç7TX»µbhciœaÂA®„·–Ýyî{ÈOÖ÷ygûó^ Ú~ÙÓ¡©ÌÐà\Ì22’93»ë¹6Pä™HÎ+FÊzÓSnÜŽCÜF(ƒBB¥I-uyvóW¦¯=^¼™"C>™C²Ei/Ó§B"ú°ÂØ3WvÆ „`J*pXRƒ_Y»Ãqà>³¹ís¨åÎÆU´¨T·xxpêðPìdxŽ›G±ƒ‹™pÉÌ9Cÿ/\ Ó 82Vˆ ©Z vü˜ˆ† ¤},@SGíÚpÚg#_‡ã÷·k® l£ƒðÞ*aÞþåÍŒâg8ê@eQc6Yi… kãD¥‰Ð Þâ‹Z}8ž¯Œò{«ê±ÑzÇc¹`½zƒÖ}ß|Ô3x@õoÝr÷C˜wwŒ_SŒ²ÉmZ°´ÊÙ锋´ÊLŸL"é 8\-GNF6Êð0$„¨‡C4„6!2Éj™`ù4*4Q Ò´ˆ4¡ÃÏÇœ\5­«aÐÚË,^ËAbÍÝåÔÀ&ý¡·à©×»0kAäyxj‡^™œPÕà\0qMã—`Ìç®3s4ÈùñÖ‹ $kÔT`aFy>}V–*nÔ>ä*&Ìé…šNÆ’Á‘®¿TikB^*Ú-xl3†ÑÝ¢ ;uI¯£KIuºlP§\¼7LÕÆN&ñ8¨nM(Ö*5‡Öo¸ cr@.›C†³ˆˆpþ=ÀêRX¦;ãr!ÂæYH¢a L°hj†‹N¾dˆ@eµc¦i [Š4ÂE¶•s¿«d ÎQbÈiφ]<áØ7÷zn(°øø¡¿UÁàxK‹½ÌºCnì²<ìxZåïH (‚Lh‰ªeÙd,>L¶‹E ¢)T‘$. in^}|zü:sx u®Àùyc‘È®éP¯Ÿ2k¶g k±ƒ¹î! JÉWÖWT¤™¤ÓÌßCâ*h{d Q&1U¨c¢Á2Ã^8ŽÒ–@)«È/à fêšZ  _‡ÄåQD>Ø y"IŠ ÁŠ@‰ ãph° ²• é¢PÀêð´1…¦ÅUƒ²Æ½èª ,\„ÝzìpCÝ6 õå:r.hr(-‰7–s;pr¼æwÙu67/s°pÍ223«åÃ{ö42Ú šøVXbUl»±U°°¿l̺%0ÂìLwiaã1Јì®BFYë×ÕØæ4ÃLu*{8KâäÞFn¡˜`ªÊºîõ;A ¡@i/œ~ûóÉ—½Éë÷.× ü§×äÅAæÿ³ô«Ìdäìg†v°ìöDY~ßLPÝDj/HƒïˆÈ!ié-‰mêÄ!hˆg ÀõÿÜïïÙãéa‡4FP!¤QDư]›´Í>9†œŒ7Í©YÎLwísÊЦάQ Äf!ràK'‘ ÉÛ 91”3±“ô¿Íý?¿ýçëýÄ}bŸCë{«õGÅõ¿kõÄTU¼ª6÷ñ‘aúØfÀÿÂCÒiT3Š_â}=+DÃù‹úŸ¤±Tšá¤Vy 2Æ¡Åù¹×n.øYj®ñj­ü¶gÀ[êìqÑàt‰9 è³~ùD8r¿Bpħ†¿² '°±²Šªˆ—/T+ >ø8jiIƒ÷'jDyBJ=k¯=Nníç\­L¾»èfÊ:!F bà 4lØtt,ÑÁA ÃD5*ôQY2 ê«cŠËzêìͳ§¼½Q½×Fè«ÇJÝgúVì#âÁGòhôx„2õ@ȆŸ;)‚ O”"g4oùž¼‹e¾Æ˜˜½­ø 2 ÊOÝ}NÙÇ%¤…ëÉ™ÍØ0sºè¼¨ ãñÝÚbþ­‘&±‹ö~ˆ[Eü%17J"8Àr8}|$FB‚€ÛãRЙ22ÔÜ?öøHßI5ú`'LjáÆA†YA`Z;Ø>jÃq]0‘Á5Çï%Î#à<$8e™Ÿ?ÿ¹† (¾Yó(Kú:Ÿ¦×Ðeð»7[0µ¨¤°×Ó˜±5IHJdµ×­»¿ýú{?¾ãÓQ:òìú—¦™¹q”r,l\-sË+Y«òÛdtõ¤ ÃC²ìl??,G^ƒçdfQ˜‡P-Ziƒ*í:B Æ’ªƒ¤‰£¡`Œ²Ðí%IlÌË c6È1°iŒLv€È,-~“b.7OwCõé‰!“ÓÏRõã%-Oƒì¾““pÉRo\Þ+ ÃQË…Ûémí¯ … ©×CÖpàä§<¨¼@‚½ÊŒ¹ Ý^¶§®¼¯S[›uLJD—![."„©êè¢ÄA)RƒáÑïæ¢m "¥1±Òâj¡¶§/Ti³ {Úä—[§«üÿ#yÊQœhöèòxÛ);ë/~V-ÒÚö::š>Sv:œÀ¹¿J$I@U@ꪀ:ªÂñ °»( Ù.Œ)DHA±¦ë ;we‚¨€é¿ €àkýŒ“T±:ˆ¼¡{D;äR5 eI4S™‘ÀÍ_n:È7C„6™LŠq`ñYeªL¯„+€ ,2'tPе *½ÅpA°Ä#Z€¤*Å Ÿmä;séXxënfj@:[Ћ°›ÏXØøR*…ƒ"ˆ ôå0–¬´ †ªP4Á "¨ùU]Є_/š«ÚH¤šuP  !¯êü ÁE¿ŸÝõ8@Sˆ š:6`²’I¹:mp‚ƒ`¸ €l3ÇÜáù‰E3å}¢Ý},¢ÄåQ9U7){ |¾ ø3Ô;¥ÝEÔæïv‘hø| çXiÑG±Ãè3= J…tšd#oYXË}}¸x@Ûß¼Ÿ £‚[*ªž_½Úd4{ÑíëHÁ¤ZkÁáUw3ÅŽ£,‡ÇÂø˜QFŸŸ'·­”‰!!ÊŒœ@”¤0¥ÿµçҸ߆5Q^ß/?¯WÌC/ÁȤXËs;µC Í"Æ~D±bÅ TºLýG㨩‡Hð ! ENnLÛ- ïhÒÿ¯óz¯¯ý?uÎv=IÕ£ªœxZÅ !¼?ÃgÔvõ¸:ntœáηìQÍ¢û îüÝœç2Ç›è‡?yÐL!t(ÒÐIéà–l‚`€7ç ÀAOR* ¨¾›{Ÿ´ó¹ëý·…—Ùþ¿gïûƒOsÙö¾ú±b«[»ªµÖ–(•*TRHŽ* ]ËI]å ²—õ{>P`õz}‡ÀÓþá“×øÃZX}Ò‹zgVËɃ¤?OÑ‹’áRŠlfÅ-$ðjÔÌ&—Ng[‚!‚“ÀD'È*ý—s„¸¢“¶M÷_¾Á$&¡Á %q…y†*{»<óù>x@ fœ«ÄÞ‘JVrf3¨…“ÖR…³‡E‡pÙ…è‡ 6hÙf!‡ˆB:(8sú õw·¼»æY;’®±Îžïd33tUêhÌîêý½Òš_¤ôT!!ÏÈø:ƒ±Ô’ MåÜ#ÎÜbî¦Û¾¥Åäâ8œ8oœ!ìñ9gîr>A¨Õî4Ëg ŽÖà(¯€Ÿ7<­±¢XZÀ•XììßÙºiÐþKÙ}#a'`ΈI$jæ<½ÞmcîpD~ÊÝ%%1ÏßÄ0/ïl_Dú©S -—B-–À¶„F"Ü®…0ºBF”ª*`US²ÜwßzÕ²ITÓ(åùte2ª´"htùøÈwíØâŠqáŽªß á€V£ˆ“hX0{ƒ ¢Ó<ó¹Rª¨Œ€Hwoöm©mÁ3¿³ØïÛ­ïÅCÎÂŽ 2:¸¦.ÐkcŒOLbEù(ÌÒ‰1—†¯(ç+PêðÄêu;͈bÇS±tÐω™»±&÷[A¯˜> ªªSñÐ(Á¦Äʲà»@ñç~ëÝóìÏcc=ð~/ +ªÖ‘ÙFÍ#gx³&/_àÒðšU«0b¹²RJ"ÕKÈÇúúi}FVb,3Ð¥”&|mžK: FΑ˧Ÿ•ﱟÆK êá_X¢AÄŽ… ˜Ð0µ©fu¹×O)Ñ4¸v€Ü. 4ʘ¥‡ÉÈâQ« Í ê« ¹.v²ðîE0[¬h¨÷ÄÊHª±©¼×ijÒ4BDÆ`Ìsgh%,Šk}…UÀ,(¶Ûózh,aéò¾×c!;ñ³â™eÃéj&A£ž<èêC‡Gvy»¿o(^’Ã~q¦?C7‡a <øßO­»òW¹½ßt4ln¼ÅÛlMÝí¸¹ Žo ’ß?†kÌQç" ¨OIæêûÿ©ó{½žF¹„ÜE©Tùd#*"g&§øóÞ¶ãès{ÃuµAÀ:J‹öwÿǦø_šýéúzÈlðšä– m{P|bØH\.‘{&%ötˆQ@ ˆ$@@BİújßEàGÑçh%ÝZ‡ÿ‡ôE¿…诫ÂÑÔžÁçæŽd˜]]åNï‘õþ.38x®l‹àx#KkJ€/µ¬U©9ö§Ø´\ŸKÓãþ›sœ˜Ê¦ÁŽÈ·öןµ{0y p²ø).€)#*/Û­b$hÒYUè±:Í£dtt`Íœ4tt0,¢ ÙÑÐÆt`–Æp (èØ†ntm]u§ÍåCVHuÊœ4Ë+%V•ñæÎnÐqÖuѺ®ECë7©—Ðtë£n·ŸRýv’òÙæ§ô1 7µÓ(:Ÿ)ÕRUÓHµÛ½¨gwù‡ɘ¦É†´«FkQP‘Ñ›ïgr¢ço´+ÕåÛ& ‹E ÕÚëW‘+•æåjîîÕ -ɱF(XWåâysÐ6„6 zq4¢BcgAÖYjtf¶‚ŠÑIqae0ˆfË :Xs Úâèá³£@5´lâ³…àÖÖÊÕì׊£è‹ì±QÅEšÀ86¡b¡Q›y³­ro®w×Ò/B84%Þ¦_·òûÞžy^®²Jë½õF `z\†Ñüò«Kƒb¢v¤˜Ï½EŒî-UÊ0Íe™&itšg¨8´çö³Å žˆ0Ðo¯KÅüº†Í=œ¢ÏG ,îÍ?½ lø°Šƒ41­½Mùg¼ÚÅŽ†Ç ±“‘V†òüµ,q@…/fdq2ƒ<2µ¸eÏÎ÷á»g“Äen¾×¶Ÿ ¥‹Ñbòíß…EëAR|ò“)Û k «e—œ´©ðj&Ï3<X6hò™ÃnÐ篖ïy3JÂnjo˜–r{¹ÛýéŒÙHܾ ‡|/ïø-œ9ÂÏ(Þ¼³Wuù=rYJ‘„V¼øí#PÕ Š×Ë´‚Ñp‹' ¤í‘H".œÚ>.­áà°³ÐÙd!M¶!¢À1Xw/7籸AÂq• %!ö{¼1bªè)M÷£F…ƒ<”AZ`bÅ8äc± b„òñèߦvçn†,L_R¬î´H†VÀ"®yKwíJ7 !t Ä×x»ëÆZI A–2ÏŒM×7O<͘p«T=l64ûÁ¿r˜Î…hó¢†auž•¤¬ò+pʜï~ðߎ>Ýü<«÷ @?µù¼£ößêÿ‰¾Üf…T€’ ˆ 4þı{B6ß•8 €j¥©˜ƵOy½èw¦]ïx'ÝÞâ,üe½¹ ×þF•¢5ƒ€X€€\±@(DK»q ›3%¯ÅÊþ^—ës|¬îWWV79¸}=Žc©_«íräÄv$jÚŠ‹ ÿiý/ÅF§‘Æ{±F?„mçªÕŸ@ëé;5ŸTôÿ U{:¼­$„¶NoÆè¥Zß ×X±w[YÞ°ö«N-PD„„„à …T0Ù†–hÙŒè8tPÈ-8ad4.…²…² ²t_.ó£!Å®úæ-îovúÈú­’îµ]Vù ë-ëEM®g9KO³ù¯ç5à„‚†#€‘–UA lU=QÃx$ú¾Ù{¯¸6ÔÀ¥÷ ×»M.ò„c÷£”2ž;øœT„ÁI ¾aÜÝ£TîÛ]Òx¬5¼Þ)©R$"ÓPŒV-xß…'†U´&5lú¶8>`£‡·…GvQxQ ,èè„(ÃAØPÌ8pàö­­š7³µG8T+—I#­Uƒ¢Ì: t d J@@BœNT†z‡«Å5n:€.8ÎWö¶å˜, c[œ·–#ÈK“{šÍƒózœjI-TBƒpRª„%@‚£ e“ˆ¿½²ªH 8Q‚¨˜dØcs.63ž{;,‰}ÑC)B€Æ*\ªB€ }e~X<Ìe•YêÕ P]V“dZDDžc+ÏuèÙ9®¸{@Û»÷t4ÇH¨•aùß>´h  hñB,»EíëkÇî{^ïg»R³/C5ÄÏ÷6Ìo<<ÊTÀ•CÂÁCœjžuM©N?«Ã–œ+™ÖûrçocÀSç_3øø#eLç gÃã {bGÀ²Â t‚ŠM é¤ +c•ãO¿›às®¦6ó·Í@ôE èñZ ¨Þ(â‰|Òw=P[G|ˆ]ùø•çÌÖ¹Tx •cƵ^@í o€ƒ{õ~öè'º‹9÷P4¢„¢èqúÝ-³¥°#eßfÙãHL?3´Åú×Óõ?Ñìÿ‡?¡9©ÆÙ–—\ÜíDvè_|• ¿žµªûKïþ¿ú|OƒúNǨ??âý ’áEûÙËtdšµSNÖK2iÑV«©ò˜ýÝ|ïðJ.ùú3«¸Lݹ/|»®^¹{L‹4YôCf†aГ P`hÃ!dC,L6Qd9œ9›/šë+ެ½˜jÍV¹®l½îÔ/‘™{Ƕ)Z5 ¤ÓòÙ½€‘yA‡ØúܸŸóá?__ÄBŸ}Vù·\šßJ¦¬®Ì(R@º!h !,„$ŠH¡$! "HÈÊ eÝ2ðò«uïñ¢-ŸQÑŠŒÑüÁuÚ£†ÒŠ `v‘Ù…˜‹;)v•l릵d9ËÑ ¶Ph0‹Œ:iœC”-Prð,W¥Z¸­*‹YR»õûe9SéÚü/È ”Œ¥7¥†Ú BjÕÌÀfl7סgE:ÔÅŠDêµ2wÛõ¶Ó6QÙ>C¦y½ë«/û¡G+¸8f­+´râ ¾¼yS¡g¢†ÇýÍ<MëÃïø2ß´!‡°r]ùìŠÏfÙ¢˜Ѐ2"¥o·ßÅ\›„Å჉ŒDÀÃ8йpÎ:pæuJ5$DˆKD£2xA¤Þû0‚Ëk\4½K3 ÏPo`El¡-ûÏcÛÈ9Y¨;Ž5©!u)páÌäôÔ4–€ƒÂ#Žû Ö*(2PŠr’f¨ {ºª¥AK ª–ÐQHc‚$ׯn½Ž…ƒÆ]Búñ^|x=Õ ×šÞׂ͋ gÔÕŽäòuìç]Œ¥ ©™oÈ죣G£BÑe-.ÅAãj§¢«‘)Cjä "Š ÈAAÂÑçê÷®üœ ZnO¯±™îí/u×sÑè IA²HB(u! ¬ñL÷á TwîÕ6,8rGŸ ;p °:„„D"ÆL §£¨>gî‰ÓŠBAW! –(™IŠ’>§BH¸<â.¡òîy Ä= -Ñ­Ž]hÔF-¯²úø+Þš®a”J!“å‹bå!µì‚Þ˜‡B€ ?†Œ€™¹Ù½RUfЧTéI™«Ëç5›/G\Ç:®¶BŽ6ta³†Å£¢Š0á²Êš(JŠѳ˜ÖµfÝo­båYmÑš«Ö²eñf¹š½‰*ªÖLЕ«Š~•}àH˜»êlúéîù½3Çkt6Ü@$ Ad'y3î®ÿ ~¤0c¹àY 7°>„ÍBŽ‘¤u†È¦ÎŽº˜ÑÑGEˆæª«AÀÁ‡tm3a½†#c1CPnst‘.s«Ýç蟢W†lXÈû÷ë¾Yð8œJ8œSƒ¹‘ì(„e2š$&O)Ó«¾ÉÝqPm1ˆCL!ÖŽ§’Šê¼ø8)Fx±‘àärþy]aâß­~‘—J¯P=7éHÇ Æ&4àrž`÷ 9tTëè('aU%ÕR”-¦N¼§ Ÿ‡úuòrá{{Þ¦æÿWõuÖ·zÓ®¢ÐÆt2°c,у8Y²l³„(èÃD6B…†ÃÐhá`Ì6+ºr¥Îo|×/UÖß/˜_X¦ó¬•7PÍóZÞ¡³­î9Í®ikNrsz¾ßô;…ÕYdµ%XÞ-÷ ¢ßÜ>üB”„$¥Âlå ÆŸ• 2X{%‡°`È1ô5F-:LhØt¬²ÈJ6UlÑÐ.—[Ø`1t@ !º8”Ù¢Š è¢Š,è‚8ƒ¥abêŸ]N(úÊèÙúk{î®Îƒc(oYûuVe³b ;6€„”RDibâÉœyÜÙ°¬¦Ì!ãÓ–vsƒóQ4‰ä‹¡‹`Á°Œ! …U¿¤sü¾œlîs0AhwØÃ˜â«…y)6Úllu 4ÝJ¾õ}?cGƒ³1Ùüí}‡ òWÃ×Z³ØÐ21.ýWƒÉD4QáÞ;•£–¸î†r”XJfëPXHTQuÅðh¯D@°¾ã­úÆ3C6QA#-…"…î¶´sÀ6 ÆJ†(j¿Ľ9™‡e":¾êŠ=×EœƒJ púCÉñõ^Ê!˜v|MUóñ²Ë"àzíé˜11¦ ¡ý‘ë|Õzèa[–ÌϾÀy0€oqxAAXKÁBŠ~«ÅET]W¾“ÿ-Þ]9ößšRƒøA(„E"p'-IݳD-q–Ó3N§åvß¿x­ºGIž³gª/C‹}ݥ߈äœÏA¢Ž(; \Þx¢àd4f" "Ò@,™ŽÄ¿;ýegÚüÞïªÎ3³ï2c·ëùŸÞóÛÃ,G¬Mm-§¢·“†i" enoê7)rvçð žÏ]ô%.!¿ãÍØGUQx‰ f ~Š ‹Ô È¡("ȕȔ¡26è ¤H)J¢M¤Òm'Œ¤Ä¼#z’Ïò° 7#ÑVZ*•”ƒ ¤oÇÜ>ÊHK0i‘nYª‘$–’Y¦ˆÃl*-Þ&$Ñ¢SRE(·BJ• HÝ¡E¹²¨¶ aV*ªžTZÃqøÔE Ųw¯z1DE È°ïZm–—K·»Ãyyº›¦éºêò¤‰”)JmEDmÁ2T(m´¬T}t$’FØœoéd;بk ¡×Ñ…F qº¦ÓkîQ2… TB&A‘PÖ¥·JÏÆ=¨°ÁR¡¬,ŠÆ YA15E¯ŽZd†™»¶ìþÝÃ2 „ ÓYB…neç†÷¼=e2õo/7ü¶®¼ˆõ6¨(ŠiàtÊ+ÎæE]ä«×ù]‡Ê'suw÷ycËá|¿Ã}Žü/0½ãÖ•ŠŠÎ´›¯–’s E(ìa§iMD•á¥kIe9ˆ3z´«­`¼9”QDÚnõœÖUœùQ"tä°õQýåïõ±¹Ñ^¹ˆ|ñIzÞ9o<íç½]„§®‹WØjï]µé—·®·„œÑu¦’EÎñ]CÇR 0Ó#[WŬ]J&.0ÛhàŸŒQõÿÃæhoTWÐ{^1ɸÞÇ“PSÓôK€€p˜Ö¶ó±~0^]«O‡ãÉ‘UpÒ4J¨ˆ3X'&ƒšqC¢öü)êû#̲ñ¹Ÿô~*ý`þ?wÂæâ.Y‚=À§ù?|dÓ9bø™ae õ™ýùÎåDø>úȆúñ埲üŽÜ·kÃôôÓ€ÑDñ¿¶÷Šà'9µó²¸’TRñ/óº©xOÇ€beù´»Ã¾;›.S.‰,sÑÿOµ Â¸3°Ù¿Vä/Ý/ßÕõÝ{T lûÇú=2·¨W¨r¸èšÇk‡£MŒÝ—8…’÷ñ³š¤Y¿¢½›^R4tð˺bÒ­REC%¸MC’*TÊÈ׿áƒÀ eÂt^eùž¹‡ÁS05ÙŽ™y§Âo!‰…«A²Àa¼¦È*"74ê/‚\*Í™‰† \/X3´ÓOÉ\ˆÛІöPBâÀxU„\@c Þ¬>$“¯=m|S%ÿ>ŽŸÙÖsÛÛ•¹òÿS÷ÈÔéϾpÖ7…K2Ñ-`.*ÿëL"$ptì«·2¦„~Õ½¯âyêÒWMd²ñkPD2È7ÕT’B¨øëߥx‰÷³KÆô‡´—‹¬?…ÑQ|ï‘ ø•´Rý•ëüÉ-—÷ñ‘¸§¸Br!QTÀE÷pù%̃}G_ŸË_“‚"š-ïx€Ò¤ q ?â ö|~ç(ÞgE¶¦¹Üp‘~J?{/AGèSV„¥Ô2ˆQ Ú,»OjïG,*\V£m{É|.½7±U² ×yÎùÁQ|$5åE$A‚O™Â@æE9‘@ IÔôÖ¹QxÝ®ÿÃæjN=øcÙê>±”*ÅÏïËD@€KñÌ9JbìÆ³[MHœË\s¤½•úÙ}ß—êN¶úçãí‹ÓUÿpOO©=ÅÛ û°Ä\±·•ãìáv•%ç/«n|w „|£ê”}AŸ†5=¨@Uçªk)"1\uXßô–ø¯þï·>¿Ü`%0µÁT²Ï×)q/%Èþ1nyôÌÿbGÆŒØ]ªy1&ðä·üÓ1â³TéãÒäðÓ/•{þ5–rxˆq#i@lUµ¾³leuÔ nUºtm“ NÑabçø|84„ŠÜfMî^é$Ûd–úf:–Õ¹‚\´»_ô'ES*õß8¾ b¹¸±3+Ê—Î߃¯J}[®Øiï«Ýö×7SÛvöXb9<™l‰ëGʵ–óQ"ØšÒ+•Î\ OŸ³îD‰M°²äF#€ ÞR¨ýÕ¼L%¬ Ón×É„…íAru*Üë§³´³ã„êo={ù8ñÔ%yQkó›ÈžËÄÅ6W‰xšÐbá«!¯9‚ÝéÜs²ãÝ Xsu1”ÈÊŠ¼)!IŠžì´€Ë'ìÝ|©#;Ö¡Zò¨dáfô0ëAvÜ(#Ò¬m]µjQðOÝ7¯ÝýÏö?ºÊÿûLÃútmÙîÏ|âot÷ÚÛ|h"µá„‡ªûKÕêõx:l%’k³úr“ykéÏË«J×»“½S>ðõ53°™å²Æ}­wÉ©î7=YŽcÍÊïÕ®C¬ƒ0s­_Mr0U\³9PÒ&K(µYb“]ÄPp Q–×™ˆü­¾ÿ&8Ë_ }åuÇŸ+[Æo+%?~AzÆýzõá¡‘œ(PíŠ+­áφWã:s¢­°[<éÓ­8Eb*M¢ì^Œ±Ø5¤'€€2 "Å™•7Òpê 0T–†ÕTe$澡³âïé¦;>¦–©Å?#·e&³D—Éïé1¼I¹*¢Šìîü—\N"r¿;Ç\$…ÿ~WˆAS"_uG½òrãª}³AF‰`ûu*.ý[,š½·×bÿ*›|áÆ A íýk…Qíé>Ó¥°‚Ü*.r¢ä¨ºŠÙ  %@I U…Jn$4+ívûü, §â{•ð¢‚A'â(Ï,áa¨¢ÔW»zÜñ÷C°Šÿ.s]•V„ZÒÛlF£BQˆ"(Œ&Æ"1@b h ¢"0Qƒ@ŒAŒ4µ±ˆª´±ˆÉ±F(ÑRh¢ -¢4b1QF’‹VÛ*Û+mˆÁhCj1E„ÁÄF(ŒA’ ¡4DF 0hˆ1ƒF€±mlQTh1c“bŒQ¢¤ÑE@Z1DhÄb¢$cVÛ!Â5?+¾‰–¥\|sŒåäY%ë÷hb #Ò9¿OÚí¿Ã•Øt}‡GÐqzÍîåÕΚ\Ÿäêù{+Í^^•›ñÃÄöô\Ãæ¶?±óú¾Þßßýÿ£ó÷já«U>o±¦¿$›šPùî”þÏØ»P~·ÛkÜ-mü9ò–ºÄàIË¡µQ|ÂÆÿžè•EˆÄEˆ"°gCMH*/9ONõOúFòÛØ?ü=æ<§©}ËØºo-ìߪò^KÊz§”õoTõ/hôNñéëÞ™å½Ûí^µëtbÒ.¢ø.ã5£Ž0ã'Àøà|ð>Àøà|ð>Àøà|ð>Àøà|ð>Àøà|ð>Àøà|ð>Àø׈@ˆA-Y$Et€ ÒE2(Ü” ¸þß`ýK“ÛmmïºÚªå¤­™JEbҚبÛZ*Š*šV,Z,V-L¶Qd‹h¬kc’Ù•Eбhªf¶5fXÛ¦TmFÆÄj5’´Y¦‹IµEQE+R–Ù**,•¦Uµ®­i6Æ¢«)m´••«´²lE"R"‹i)JJd–J-)j&l£jŠÍ(‰$¨±­ŠLV6¨µ-‹dˆªl’¥¦É²U¦Z6Ù 6ÅTkU-”ª-jf©-VÛ¶ÌÃD"Á2)B Éh @DiH„‹1‘ï:™r[Ù·¥k‘V®R¦ÖŸ‡û˯,±[ñÊÆÑcco½nÆkò+—¿[e¯hr”¸•®™54ÑfB†Â•×k´3r»(#Q’±»®´Scc W.‘ʮֶ·6Õª­–«§ºJT[*U@¢–ñÕåEíµ·òíêÊ™’ƒi›%J0dRS)T’„FÓ)d±o+VÕO¨e‚Ê‹LRèÂ+" ˆH¤Ô”Ñ >7Y2,ÔÄ’JJd‘iZeV4jÚ+bÌšÄPHŒD‘ ¤@‹ ân¸1ß bU1’ØÕ¢Å)Umñni¶¶í¥«l ÃV6¬EFÛ[*ÈÅEŠ‹ˆ¢¡@˜èóãù[ÅEòø Zÿñû[…EïpT_ƒE¾äQ ”IQ¥EŠ‹ÖÝO} Ó.]RäfçøŒ¢ßÚRMrë3É&ƒù á¸äð\0C#œ  ƒÉ…Ðd$è$€:qðâÑ]/YV†??c?)¾H˜ˆ=±3ï¤çH°ïÊ•¶ÇÛØ$ àr –ž™óÔZ ˆ™äôµA¼µ'|œUA+x¨¼®ÉEAv¢ÄDC€*/r ` (Dˆ ­¡6S(Õ~rÛ[5ËmêÎU·A`¨°Z)TXÞ¨²”AH(,UE@÷Š‹VÊ¢ö(Š¥ô¹EQaÚ)Q|÷8Y4*,õaã ‹B*Ð*ä&±X Ê‚ˆÂ2)!V+j™U©SJF£V*Åj©*Ö·*±¶·T¶Ø­®kk’RM-”Ö´%­³ -’a‘mª5¬RÔ‰MX«,¨2Flˆ‰3$šlÖ’M‘)¤*¶Æ¶µsm­¿7*-!‚¢ã@§4é÷‡”àÖD¸×ßÿÊÿpsç7ú¿_%ysgDãs„ÕTªxÁ<ù6Ðçý*¿S¹æÍÿCŠsÛ«¸Ú¦¡kå]'£=)Ÿ¥ÒÖ0Ò‹ M2¼ ÒébôsÆ*.:¥ŸÆ T\v×Å+¾ÇÙËü+·×±b¡nµX¬{Uñt4 aÌãøscÕçŒí ½Àɨ ŸÅ³Í¾[gÙ×ÙÄóõ8ñœzÌx\rLJŠz¢ qü-nôÿkh~¶_×1ŒÓè9Óű‡^ju‡¸ëƒXÈbr–ï9ºIM¸MtÐåètÙ.…P(‹ýßÞèÃ`õöÌ]°(¸æG/ÅÍϵƒù˧Ʉ¬=ƒŸåöloá”g«èâ?xøMŽÞ¤Dåeì{.ð˲grEI‹c¹êøfµÚü„ëbzyP>ÙîëN$××/ñPÑj©ê‘R#A_Ø4ˆ461€c_ŠÕ¯/‹µslW©W-Qb£oºöîõÖçzîËÍ.¥$CªéDL*²ª“ŠH¤‰ÆÚanÜŽœM1·&¢…–äkUnÛ§TzdhÓ<[~/yѯ kêwDÍ4½ÝÅTЩ0Q ÒvÉH…È ¡6Ê•@áÂAÕå\q¶â“¡„/74IÜröï*šñÓvë¡ÚtQd#nDBˆã\îé2 “DÃwC¡A·›n)#-:7îU Ÿæw<¤fîîžî×¹ëz¢wr#´;›²B½7o'ƼÞg9rw[T´“^ÓÃc:*\‘¸nÝÄ`OIHT £¢’%›²|ë‹Y:_/þÿ»Òßû¾‹ó·-K’3ÒFG.Â71½¨Bã¢Ü"ëÀÂìx›@RCV£‡œVS,œóÞ{è1íq?Õ4W†Âéé ÚÖÐÃÄTD3ú£Í]£&âÊí[yÅÝAø·ýWε €\ÿÉ–þˆ¿%ÿãû±ŠY»¤J0dÄ”NÙŸ.Ç{ÀB¶´’¤ÏPæÀe>Y†þÒïeµÀ÷Võ:2¦æw‘ÛËp¦â¯ˆVtŠÍЭ«Ø7m€é‰9y¦Ý;ÿ®a ÊßåÍý¢N@9àD" "@@Š‹*,Š‹b¢ÁOÁ°ûÒ$ŸlD¢×¨O$ÄQóØOù÷›ˆÊyIö´ø?v"8Ř£þ’cƲækOE¼të­ÿ&¾jE$õ¿æzLI…õP¬ð’|åAf~Ò‚#ï@öÓ߀*k*,(¨±SÍ<øUjªé2yÈ)r¢‚¿| ˆ„PE(ФOv/¿ypŸ–*¢Ìð %4E³áŽp*½:ŽQ@ñÙüÃöîÑFXý éjµN Eݪ‹¢ª/Æ'Ì£^ÀÕ¬™ ÞÍÔq“¾ª8ÿqoñ¦¿¶½ÖRõ0Pš¾Kû=ׇôýÿ7õFdòö¬]#=õ%I1BˆANôÌZöõ×3CMŠ­û@îà÷Üà÷R«ožÿ\yUÉ«}í|ÔMÿ1vPúí#d…æ« * @D#øóÀãÔ’MžÃÛ]EU.ØùNŽHþÇñù¯'ƒàÑUðãÜ~ž§/œ×2z§ƒ%Ö/LZ» þÛ•!>^FùušêŒT\ŠdSé_àd—*.%EÄ‚'l‚Ø]úZ>dááÿCçÒ¨½ñZ¯…²ÉZf6RjX‰R˜)$©,’Z’ÙJ’ÒÒÛ)i-’JJ¥–HDHlY=“cî¹â¤ÚÝz/Mˆç2åhŠ_à5߀  ‚„  E Y€Z'i§óŽp_ߌ:—M½yöÇÆz J .DL™èâÇ~|ü4yÖEÅ•çA&{1ËîÚDgŽYÒA˜, èd+1n AOª]‰ûnó’ •=QE ¶  îñ8ÍïÀí-×dñçÚÍ\P„ žUQa䈂!9ÎÃRô»Ê !4ÀÛˆÓ<ÂÞyQ/DE;a{ÍjlcA_ÜÆ/øÑò¶ ˆ;(H@ «1`E¤Šƒ"ŠPˆ)œycÝ{œÂƒq™Qw‡÷pS1cÈŽI¸Ù¿’!|‘<Ì—â%‡wtF–à_i%êˆ8F¢mÙßãΤPdÎ'’u¡vf.‹ &ê²ÑRF- ×}ŠI3ä’´ódG? þ¢ÅQ~eQ{*‹C § è p‰b(€‰€Q'·øæ:›¼¦4l×Õž{…¯ÅÈC1»Û6hPL„œ9ë?»Ž¤ÚÝ0ŠÔAB| ÿàASˆ—ŸÍŒ¢» žnÒÞûâ·JÄ!¨¶+EÙ`’Ñ e&dKFÆÅˆ­ ™T4¢JŒ)Dÿƒéö¿'øŽ·Ý¿Fú/òþoË‹äNÍQoåª.¨€ ‘Q}X”0ˆÅTˆª,PÚú}êÉÀæ ãD² €‡^€ïÐ@DóAÜæDÈc³¼¡Aó%… €‡ñøJ‹åQêøØÀPpT]EéQk¯ô"!òF `˜c%×" õ¥®'3ýþ›ÒñŒ÷ßóƒPõÙß¡è{ÎÓíý&¯òÝ%š¹Éö/T[ÅTX*Žº¨ºâf"Š*-L‚*”ŒEiJEŠ‹:¾èT[ ® ÜWeQnDR#v‚")Ú‡t•E¥EîQ åC9H§_¦i("€­gñýv£ºôñó>«óT°bÞwÀ\YܾfŽˆdÚ·hf)8þnô°—2!l ÅXÏ~ûQÈÝÊþ.Ö~½¶ax@@"21ýZ<\„O÷ Rã¡ar¤¸£Ú'·¦yž).„(¾¿ãå4øa¾ù4rÓ¢2'½G/O>ûO¡ûž¼UŒU`Š¢æÆ»­Öý;‹ @ÊrXžF ô訶:g’ã³–ƒ“Rß|úÞî@¿3|±;^ûóÚµ_4²’[)IlØ5%H¥)%*’Õ,’¤ÁZ–mK-(•[þ=ëå—ÄüCÏ>U@ «€ úwµ{ó¥ŽÇ®Í²Sßmãußgž)Ù Æ>ÈÏöQ±O o'ëøûð=vó€dA@>Y^ü¾,ê“’µ<UÙŠ“«Õ sÒZXñ.=ŒQ‰=6ܱözM¾½Óì‘îÒ" œlft;µE÷_ר†Š£¯Êp6"äñ©K¦Æ ÷6Bù5Ê:ì"¢õç¼¹¡º—ßOC×Ý﹉ôo5 b¿|p»Ç.ˆAR€0\ˆ@@ d}KË; ä­’œö™çIo¿“²ðr¼ƒÒ¨½UÕî7a¾…ãˆå%\T¸™ôVÿgŸôþ Â!‡Ê6QŠ!B¬q3")Ýzú>§Uþn‹”ˆfT\Ê‹œˆ§‡Ôñø>'íó1ªŒÄ:”E(s*-Ê‹wÈÓóÝpröœ’{\(Ö—BBnéÞMä X¨„%$…KT–*¦/–n]ŠIËX%E$üŸGc¸þ­%Ðúo¹aûv Ù„?lN„Ràîœan'”÷Kâh„ ’‰?(ÄÕáW†Ä<¬9â+Ôÿ³×]'\–-kZð’U?íúwdâ‡a ´!ªÿ˜ÊýOoì3ñ˜Ã%8h)Úçã¸ÙWXTX=R¢Â*/ºç,¢“í¾' þï=ð®îþÛÒÏ™Qg Ïöòï:~ž‹û„¤6“«YóÓøØ„@@*C’5û>‹h¨´Z-ƒQH‘@c‘$„Nw­Uó±<4è>õNyôh‡:'ëðDPÄœˆìª. H*/:­È„r~KzuÇÐÀù®W±äŠ‹òoü ½¦‚"&\^‰!ö}e©eQwÅÕ‡æ ã#ÿTIÊ]cþ23¹nÏ¢PA‘Œ×çÕ¶6ÆìmHýŽ@ý±‘¼"ˆB^J”ª,ZŒ„ýT‡f^„>š,ºáÂTxÎKÏiˆ¿ ožþÿ þ̺ƒ ã%ÐЯó÷k°ýÞi.Gó‰Э÷ÞÍ<”ëtJ%”"[ëÓd8Å€®ì ÛÍIˆ0S¹E dvºjýM9™8\:• @à`E¯êŠ•K˜eA80 tÐy®ØV«Ì¹¯n k©mñ1€€Aq¨_[!ŠÂ5ÁLCFf/³Â(¼>œ4Äîè•Л¬‚‡Uùæ0Ãd<­u<|Oï*"Ì‚è…,®fo¨T7‰±o ¢ ÁäŠøÀ‡#µ-Uâªþè”[‘¯¼…é· ‹î® ¥Û"ƒk®“¦„U.!‡9O{ì+Îyû®µ±¦uxYÅ…Åw»Kú7ý$! ć_þàÉGU ‚IÑþ]Ä.p`èúGh"€‡ÕëèÑ>‰¹@;cârÅ6Ú]¯è7‚ƒË5xûÌnö‰Úœ‚ÜÈdÖûÛæ*¢ùƒA € ô8pO,¹(< ,Vê ¨ÖZò.ÛÑÚ“õK‹ãi¼Ð S»H^؉P$m·û½îPì¤Þ™ n{qCž|¯ÌÄ" "• °rÝåuÃgie¥ÝúôSý—}µ{ʪœ1jí]¨舀‹ø„T_ëÛŠaþ zKú|Iøª 'WÖb°Ãª‹Ó/n¨º(…¼ø;H…â¢ãTX¨+×€"0óüÿèéúœÄMDCK(ª: „@P`,ÏÊùbë‚IŸà}›ŽÍ ÒûqÓû«5ˆHuiÛxyw¡΋"“±Æ2ã5¡Â¢È¤GÚÿukŸ­øaïóˆBpÁCŠÿ×f•ÎÆò_} éÙj”Ù“ûóìšë\ê:ˆlë-æ!À4ÜêOr)êU ° þaQ~bðþ'Ž¥à‚ƒØ€":€ª4 ˆYDU2 €‰mÌûµÄ‚ãT_ãù~S¥GXDë +mòª]ã°=»ñNW %æ\óËdíÁÀÏè½ê(vÓ…3ào°K`Vmö:ÎúFï´ãÄû{0º%)èèÂh@AäæÓqx\ª¡Ûv¿SãbÂ=v¾qQöºû^‡ÅÈs©‡?R5ÝÊ‘’$‘ˆ×*xƒ‚ ¥bö3Gת/¡êùhpû+gù _¡¨_Yƒï§G±û?ˆˆ\þ]J‹ð«Õq«ruÈR~ ØóHøçô/öP7ÿ õÛ>¦ŽØã÷Cœ1¸áš}•þò­k}yHHþ `Óì5Ó@Ò=ݼ›.æê±00…‘±B"'±áÒ1¦è Va¶¼@©îù³‰íZ‰.´fÈÊ×Mž*Pîk±!pÆQE8“÷3Yqw`ìp ÈâÀ Ÿ(Ãé ERá ŒtÞ hlhjd…BÔ€ˆ!kyB…ÛÞìöõ‰ ‡Â‡@FwInjþÏñÞÛwÖiø2^ î'³t€»Š‡KJ Øy®ZÏ¥ˆ×Þ,ûù$÷"ì*/b  žöãð“«OÀû}£ÍÍù:ZË@È?Ëô«˜c ª¢ª‚ª¼®§/5Û0éÎÉ‰à‚… »E˜ ztEVô   PŠÒ¢úR- ŠDùõïÕ3ŒEÛÚ€‰Œ£îÓÇÊeÔD(ÚT]9½4ºO¡ôlô†ÃâbhvÝÛIEFQ*ë¥Ï«ùkvÌ ìÆ„ÝÒ7böÖm!´ AuC›'J.‚À\&$#›‰CD@AP,x,öYŽ·Ì­+îŠKˆ~3Ï.ëlÉYžU¶•m åyÞIZÑ•1 ¤â¯VqÛu§SÐ"2Jd ¤6ƒº™wáE§pÀáÁöxPGaÄ|›Ç&)€ÐŒ!"2/kó+;ÚÊÛ£™Â:Hi&#­ï?ЯQw*@’&ÐI24@ "24‰"‘$I20’ 90Œ6’$ˆ‘$I£#H’ $‚’ÔiG”#i¢HI(ÈÂH…$ IIä@‘ ’ $‚’RDˆÂ4I’ )"RD’’(ÄDAÈ­ÝÖ¹guwtUwvÚ6·7*Ôj0äJHDIR@’’’ )"da$B##Œ) ¤€”a„$HJHDI$$A$H’ã$b‘hŽ21%$ÆD%$I(É! H€$ˆH’%$ H$FF€‘·#’"å»»\ÛšæÖîê«moö=ûoBÄDO ü0Ì\†ÆÎxb\"€†‹PS@¨#Þ>?3¬ác@íï=üW>úXŽ˜›"24T÷ëJ‹Ù†qÝò·Ò•j¶;“¸Ön;ìêWzT$$$$$ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ»yá¶–¬=é³Ñ #¥êä:»ŠÎ7ºe—Ó¨gõîpžQúfÜú@½¼–Ô²X ªÔ@(SPX/»²÷sœø†ïœAüDÓ ^ý÷P`_Œ'lD@Hlö'9ò‘EEüŠ5ú»èsÎûfóïÎéµóßÒÙµÙâ_ÚäÛ/9Öª dE  슋QHˆ)öb¢îEiÖ² õâˆ6aÔ¨"r‚§T ©GDûªTĨ°Q@„ˆŠ±E;µM48¢(¹ ÍLÛ <›—¸²¢Ü¨´*.=%ALˆ.ñDU=ê ëqˆ ­ ŠmS³D~îÙœ¡ª†¢ pomÜé¦UEïÃÊỉ©É7RGàüjU°íŽÌ:Ò‘1õ¤0;‡@¾äÏ%šùÞ/-Û¹ç\Jó³¹ÈÞwjüSïþuì®jäeJ晹]×jîUESúe‚Nv‘e2Qb¨¸)! C´"€µh‡aF;ª‘ì„vpí@c«Jj¢i“†Ó¬iôÉw1  »˜³lkasÑ¢¬®H\?åoYïðò6¾,‡qðwzRóê”QUUTUQU|®7ªö=/aåx ‹änÎÓ>,^ÁQíÍQt}à§r©¶åþr!¯w>ióÈ·aS"¨³âþ%ÉD;)ˆ°&H" "Q €Óþ{ȟ׵§…Z‹Z‰ß*'6ÂÏu'ZÓ²_qC§8ð<„ðýï7ÃÓB ö àáüüÒyœáq¢¨+ñº¿|ÿ„v>,‰ÐcßÁ…~æJO\Q#$º­Òt”o1Gç§ä&/xÑÞàÅÕlh<ðøŠvøIÎ}I]…$§gq'’œÍá.¨øð~qZ0 Âx¬c:¿0y¯ÕñÈþWÖZf<¿ý©O ÂèõN«§’O`uEÕ0éèÔ \8åï¯ï ›‚*=ü?®FCý~{™ÔÀ¾AW_z&¢'ì¾”  à-ÀÄþA ‰þÜ-î³sì‘Oúwë9¼ÜA÷[´œß¼WMBzþ™¢€Å À€ˆÆ° !&åiÃ7i”K¹ÊÖk.|+¯:.Õ‹v[°ÁŽÙ¹™³°ÔBesÿï;…/(úŸ•ÍŒ5ì‚".£²8  mc | ˆÞ/ˆˆ¤nƒP€èö^]€¸nçY§®áövžJ½ŽÃ€õðÍ.–†N²Ó£û’{KI€ArBWP‚¨hH áo÷×4¹&IVàÕRs…b8ˆˆŸ“Ýn>®jãu¦m2¡9RlCþæÁŒ2À€\ „` 1 ØÔ „œÀRñÿ‚ßW²Á߬ˆl¨1T‹w±7:F7Ç]¿S;ê·Ò·×÷Nôü*¶sL b€ `ªf––Ç’eŒé6Œ[£˜‡iû ¡<äBq%È $ñ‚w”€B D"[)PÕ¤%hÓU¹!Uó² ®–LÆÒcÀeÁG³G韈eë¾ß-™½£BXØàëjn P˯O…5ñ`YÂâe#¢0ÀîŸwÑðþGñ{``„Q›c”™D2ä¥6hD ̈9‡0Ÿ•æææåâ2—/36šæÐçNýÔ†±õÊ9†ŸUýÙ|óÙM@ÐMüú›ý«"q ý«¸ToÛ·c€1Çn[œ$Á>±­µæÿÄÓþM©ÂËäÈxó€oi?;§k=\ïOt§ ñ®NŽé ƒY¤3ÍégZÒ­ Ïk.Ë»*¿qà_ä?÷g÷o„©?fŠ$·ñå}O¹ Iµ…s:Z¶ÿ†áh›$'a€ŽïuÅÝ ÷ÆØ4hjº6¸äCè|±-×x¿¡ŸÊ=ÐF¡¯Üyß÷¸Gù8ðÔ¨OÈÌ>Ï êZU-ùÞ…äÀ­”AÑåð÷Vqà"$4¿"Ü*Cê@øA{>¬ì c¹ÜµKׇE_Q$’B0‹ðEÓ±ëÈ7ééÍ’D¼Ö˜Qc˜BÀª•¬z®Ë„pJ7ØÆãTN¯1˜8F aqø%T4Áú}©PÏ!¬í XsòBð…ÁD9…Œó1°{Cn„Øš%‚îXƒÚŸ žîÃà†p]݆;Ï_¿(Î3‘yhR,€X±fÀŸùcP†õûO+›o—5ÃYz«ôÎYuÂ/ÂÝÛè·jÁžX¹Á·«ÀÅæÿw‘Ðz>ç(õ9þ³>Ž’ÝsZ°b#~…µ—UÚ­‹¦!­}þªb|•+ò2¿èéûï©“¼ºØòÍS?3©/Ém¿°]“–šÔµêß&9Þ>çï[ÿäþMW¤éÛö]Î;Ýq·%ß°Þúy¹¿åo±Õ‡›6ú ˜Ç'@aùÿ¿³ 4ï ½ •[àWg ‡—Wñ)uЂõ}=SצG2=Þ¯&s1¶ØÓÉ!ØÆÛm¹2µ÷Í^¯ê=ådb­T¨ó"/#Ú:IQ!´ «P³4ïu‚TâZJ쥋1cj$÷r÷¯ï®tu×]uÖzk| •Æ+Â(ÉCœÞaÖ‰¢të6VgYÂ÷ºÝÙŽ¦]*%º•½ækzßï{}u×]o£o¶tS}Y ¸±ðË,ÓªÆ7”Ì)õÍ\aF,(0ŸŸé>?Ìô¿¦ü³ÞóÚ\¼úÓµlË™k¶n =|WÝxRŠJ¨ØK+1m“w$(!¨#€ïGxoîëþ·8‹Ø&J~­¦ïÓ#¨ö¥ñ—¿Úe:Þ¢.Ñpú7µ›êˆ£s:»4w¬¡ï áÂ!ûýNÜþþަï­%ˆs€]\ÿkí¯¾¿„[/U"ØAÑ×î -¢ÿ¿n•xÿ6æ‹ ”=‘­u¤´o–Èb-]:s÷ÿáûœ/°k¬åšÅ?GS¬<Œ_ªúþðûÿÌûnžhû5=‚qd÷æ¨i†TÆc4GÌ‹2àÀ挦J9³`tC½ý¿³äùìÐûOiéTR~^ß©gº¹¦Íc‹zò¨/8ˆ@„S bŒ`oN#Üõ瞆#ž'|ãØs~ŒÃ‘— \>‰ö K—pǃì×(ÎeºJö̪*ËÌ ½du˜ˆ„`ŽH†ÌÉÚDÙ‰Ë"g'ª/ZIþÒ“¾Å˜ºz ¸*ü@ƪ. Ê4Šo9~¾b²zX—Äó啌NÂt¹DWu[Ù¤T×êö¿©ÃL*¾Ð»1Á¤®©s®äJI:®êëš„J¢†IT2 ’EÚU}˜ønì†0@ŸA‘ §„Âåä áïtvãÚnv7†ÆÕIl±t¾±‘î}Ò2gª‹µ˜:|òmEàBÇÚ :ššð3Ug½îûGñnr;nBß„n·~û†ÂMIóÛP!Eâ*"IéK¾ÿü®^XQéa+&€XIƒ¯2d#d€¦y\ùNÈ®0²Õ]sŽœ:RîG“[í6®u5‹ßTج i´$Þ—2¶“Ê«ª2˧‚Ý&lr®VÈ-S-nÁ†n¶8½ômBõ–m\)3)ÕjWwkïÈç>sb°5¦Ð“zJ·±V‰(‰Qî{:¸œUjEÆ©*&E2ZÙr8ÏI_kå0¸¨º³ji6¨Ï­¥¢ãQ,5QLÅ1°Ánq:S g Z…9!ŸÉU ƒ j‡8='(º5ED鯋“ÍÕ]®µV+je}g-.œå&Ó6|‡ BƒÊPfœ»ºuà€G-‹Bi âì¹-€è˜GÒR˜=¦CHlž¨º¼…×þÀ×€ Sp`PÃå=pÌ­«4Ur|ÿ¾ÙÕEÓ«äÅQl®_6=ÍÕEòNWh7#°<Ѥg¡¨º£˜1†c<È!ç:Ÿ©Òßú¾ÔþÜ[„¬Ý©Æ)gTw&ËSñw'õÜ äoliìA€ËÑ €€ØýèoD!\Œš;K¿A/Ê#¸\DDìŒÝç¬É‘< Ó¬^éË}’ºfÑ:«MÜXó¦PD@ÛIE·B–šùïä_ÍÙ´ÕÏÓÙu€pŠ<|ÄKÕ£@ u[fy}%šOŽ–ô:ž²,Ê’e?´ÿU±_ —ñOù~×¼·¾¿¶ÒWa`£6}#b;|VO_|(Ù±|è$ÌÝv³V©!5¢\E ¸© E$ ù ´Y€¢¢ÕòÓ¹0²½¤T7‚t$–žP.Hȹ±xÅÎ#¬€BŠJ¬Yµ¡ÈF8Þ‰öÿåïa|þ=‚ͯ/×JRV ú5 JúÖ‹™¸%”!!{w¹Ý:ùh½ÙF†ÍhS¹ìkÍ™ÛñôT×ü##cjR¼ÊwÈ®' võiÇøqæí'Ü3þwû ·èÙk±„¶ÜÛQ#䌷Uưg÷‚"O‹‹€7¦¾<¡uÃÀü¸ìyßXÛ6ëeÙ7-/ÀLpÜv#nmqEÖ4B•EÆ|à T[Ã|BRŠ‹œUC™€45>ÿñÚCéz?Å€ez!ܪ‹ßq%ÁQwqT[ ¢¡å³¦èïêI$’“‰U¥ºÞ­:ÕIyšö0³xT0Ñi`„!ãq%¼v`ß ½­ò**Ý{VßÜQ9Œ€;Õ ©£<—6I HÆBHH€½¹ ¨14Gæ atŒ‡8®±ŸqožÕ!ЃÙ‹l8°0*¡àaÛB> >ŽAèÙBË»û)Y¨}ð¼f—Ú(I Zj<ÛZáë P$zº¤!3@PæÈ[‰HÔшT¨¤“*Ëúª‹,Uàâ%àZ¡xD‰[NeUEµ÷6=ô©Ýì‡=ŸQ:ö$È@ÉòÒÜEö©ý¿škˆB0„\–š0Ý~d3.¡´“äá/¶ÖßSéƒí½½|›U¯^À¾ÝÍ);¿èʸp=xKÁ`(§wY‚„bl€½Â@ùN +ÔdEYDAHqÅú6ôFF*,ƒá×QØâAæÎ¥®œÄ.À±>”p÷É$˜¤jH¿aô…Ì?øžçÅHâ( ÙèÆIì”$õè*HŒ}²” ¸[-bÆ€_‚Mz‘ È„!êžè™õПYÝDê ´ðŸ±”Š‹™÷pfà;Àúb @ýìKÞ•0qO •S3¨»ï3pÈÔßÜøA@OR'¤)-$¯†å‰°0¿ YëT_ÅT[÷{²?ðXéÕøϺåWå«I # #†ªKÛ¸»¸ 7q¤‡5׫ô¶ß'ÃäÝ@ø² ÷6Jd¥m”J„µQÄ"Ó¶2 ›°jF¾ÈmJãÑ[ÉAˆQ8 /®‡:؇œC—…è$!¤—¬”éÓ¦VLe’(4®HˆFÂ0¦ -"4¯'zð¡´$Ñ-D *ª4ÏÆiô€T$e¨)!ÔÃB…˜1’0‹¨œ•ÏÜZѱ 0ŽGj Œ…Ø” £'X¥$Kk–}ôT^e]ÁÔÌ#âe4Ô­:•‰x^!AtÝ—Øî^+¢eâãÆ{¦L`·Ü;yÆÔ‰•õïÓM‘Š$¡’„(š÷gÀ€ÄmvR™p|ù–Š(Ì0kjRò¨ÄQ[D‰dJÖÊ‹‚€µçу±Nƹ[]l½çÈNhWdhRð„@ø˜¢)A§ÒÑ¡­øŸÜԩʵÕÞùKNj f·­Zªª(ÖîÍ0{•š²Û=Ö²2V¤›xn¦ÍH• )+i;R¤leÞœ¶·­I¹4^i’*‘F‡E·"ŽàвTda[Ê3µ^ïáñ‰ hŒ" ¤˜„=~Dåoå› 3ˆ@9A‘^"b @ˆ‘€uÈØîâÙX·ÊpÇ'™dCš¾ÅÊ»õ¡x쨽äã2B = s‹Þ§:œz Íˆ\ ’q49[glm¹v@¡[>ŒÎÓæáCѦ€ `Õ¸H£¸ØûÖ©!„C!?ñ¸:{7<¯½ßè¿ZwÛ[®ÒD¬:³A€@å•@°i±Ó“Mï9â‚L *ެ<®ãTä@Qv=C1A$d¦vò¸q£#ù“7.¼Ì–±¯FŪbš¿¿-zÖ¾Ò®,¥a¾¦rAy¹PB^â<ù…‹@þ§•x™.´v „ˆªD„YÈÅË»eæ@@\T‹ƒjÆŽëI¬‰eܤ¨¨€•0’aUP“ °rrâÍ+ˆB"œ5Šàü*m Jò¦úŠP8‘W‡D…68zz¶ô\@á @ÇD<´*—j-$ìÚw/ÍÜÑ®XÒ§EC†oÜîÛmäâ-ñkû7N”Œç!ÍgéWÃ1—†”.Ö¥3®}Y­ á„7„ŠI˜þÈ!Êí±lO‹èß+Q>»°›VÙÎA­«@…±¤PÓ?UHàˆ`âû×§Dðâ'ÌÜèlCZ&}E$áQcñEŽc5öÒ@Ž!ÝbÕÍþb()¯M¸çJ9QH”©¬±D§›XʯñFKD7ô<ÁÈX–÷R–UÈe—1ùX“í@ä¢¿Âø'§á!+ ‘NÑPø„"€ —«é†Ó‰y¤ÁnEbÈÞ|\ª\¸ˆÿ]Û{M¡%ªåqhE`?o$´‚eЈ_d¤Œ5 óRÔI-AkY‹ìµïÚõwqÕÊ#îúì^ëòwè¼ü·á\4Üi°}•E1ÚüïÍÔ†j c`ðiÉ!MTU¥þN¼¶ý•é–^?olÚšS=ÿpy¼Ü{eTVܜdzò¼¼4ð ³dT]<›3Li:§[j·nRËÞmgý€cÙ3ï]Z[hÞ’·V´kŸºë§E ç‰Ã–!ŸKæeò˜¨Ä™,ðZ¦úº§*,»)b`é@ƺó÷Ê(ÁÄ¢ÚeÔ`ÂÚH#hü‚J‘ {2÷7kÒ¯pÉæÃwÆÛÉ_2ç¸ Ä€+Áˆ¢,Û¢·pCqÕ³Thîé¶íØÄTàèEÙ̆Š**ÍÞxF¼ž¦»\166›Ø áù‘Ûß?:‘Ó|;[Ý6$CmlÈ™’y®ìç4©PßLÁåÐ$“U"|ª) šn¢LÉ7ú‹Ç½]òöì-µOc­skâõ<Õy1©H¬o—º{v£åU2n‘LúdEM¿6‰W¾³Îˆ ãÖµ«Öˆ¡¤Ë*ÌmÆYûž¿Sèÿ«¶›ñ'¿GàPTý²RP4ô}ò¿B¿w5T;‘úúl¿ƒÄî?_þkôsù\5È}N ÊtÑM¿Œ)öœ™KΖØÚgGdHHÍ|çǘÀââ à03oÕö¹ý<ÃÊÜ!$’£ÛÑpª’üz•çW›qÞkY¦ªqlÛÍNJÒßÿ߇6†wlìh`«8Cñ‹Qho,°u Ë¥ÑÿOIúö ʼ²ãPM_SŠ~Í­&³dÏC"jQ×ùþç«É›dðûà×èÈÚ€tÄЄ! ל>dǦúMuâÐb!]éi»¸K¢µqMBÑçÝ·L¶£a 6+¨SRBIÿ}¡]+È‚‘l)ôb"H@ƒ(H$’,ŒH(`rãºKéö½ˆÄôy @}à‹^ Ý+ŸQl4Pkjo4ë%¹uWNÇh9û¤/ªDZhaMƒoú(11*v6ø\ŒGó‰×“ =ÙeÁƒtTÍ+%Za )úͳœ­ÜÙ †üõ`¨nS•‹äÙ^Ý.•šžAPQXÉlµ$-Б„êpTX ƒˆ5öQE ÏÅâ¿Ç3Is@mz>lIvÑýWà S^Û‡Ml53?¤ÂDä®6Ûp# ð^-këøú§óVXc½îË9„JV0 Hô0oéM{1ýa ô€, %3©ÔTYÞp³6Ò/ ïòÀRà>ŠŒH’@5þÿ¯Î$$RM”Û×IÞ!ã‡NýŠ‚T*¨$i¡ŒBÆEzTVÈ ä¨½)yÄ2ª_| {Õõ„`Db!„ zuEEÕ7.PÏŠq 2¦{ݵ鴴JŠH¤ &æ|e||‘Í¢>}jj•¿¸×Ò\¶ Ï I yç=9VppbÒY¸…ÿÖ{ÕEÞ|>(rå&åQ•HQb¡åGt †!ØO‚@B<*eÀ$gAIÅ×s$ì¼9 ™èžõñµ±j4}rEY,¢ÀGWj#~‚óù¤Ðz“Ù `gíù“ñL4¾Þ6 Æ’ª¢ëÆYØÊdc)5òt¡§óªÓ‚­‹]8ÕZ=uÿÿ³õnhiÓ•ÐW‡¿‡iØ.Ÿè²m(Nº *÷X f6 [©+ -ËuÏ%€g¨ËÕ˜ ¥m„ä¯'´< ¯PŒÕb༠±#ZfÖ6´Ý§‘*"ð$oº¢ñ’/¦¦ˆ!Œ<²Ð½õë·ÕsÄHéëÖ÷dÿt>‘ÏmÓ>5UnýHG#‹¡Ã̽ü(èÇ Å #æÒòÑ]8ƒ¶Â’ 67iÿ&!­Íš£1ãvëïõF¾ºï–ù~Ê¥|OŸ)Þ“Üô¨Ÿ&ƒŒ ÷ U£qdŠ{ÚÙËK-ÔÉ ‘%"ºE̸ítÀ4¸è ¡–ÓkâÑš„}´yë.68Üm’M׳¶BDvß™}Ât5”5èðýwäÍ=á-6Š„glyôîüíéÔ=:e³­B0ŒŸ^¸ÆPXÔZŸ.¡áfë{ªíû½Ó‚ÓHÛ{øùãëÛ{îsÞè|ÚBõhÛVÅçáäå¶Ž¼³tuÔO¸Ž|ð„ß*—Àž˜¥$W!ŒÏ>þló SãÓõíÝáÀ®I°.…&„ßlèÑ0gg¸.-fK],k‚´¤ÇŽ˜­¤iù¢bQ4À¦&Èéê²£ïBné}51©‘zgXú¿‚¢ûÊ9æ"ù ñÎyê˜+6׳ëžýZòź=W^gÔšã\Ñ}U(gâ³Ë¯-™—[*‹Ä—!}oy·#<öÈêJ‡5€@¦u£Xlw]+tLÖr'1ˆ¿B¡`ZèÑsµ­ tÊŒ¤Ž! :ë¸æ_mµÜsáÍm^ÑHÛ^µÊSR>y²—¡¯wp¶’l4ý<`|\g±Ô8Ãc0~Ã[øKÓ cò‘‰g­RÙ‡ ¦1÷È…^ä^úºVÆÊ‡LÍÏf${ ¦“gmLˆçµë2¹‡fÆgÇf·eWÇWé«f™LŽ:ט±øìШ‚$[gIú`y}g­…ø²Sññª×ZbŒ:ªWg»œ#ön¹³Uf˜l“½óUaÎý›ñ³Å¦Fa‡ÂgKg.Ѥcmº½|ÜÒÞSשHòÎÞH¶3àãbb£ ©i0«"PCÙQÑ„a…ÒK’ê+u¦ÎÂØ‡äBÓ,?…e[©xx`ýRms}"¼{E¿ø]k¢]øñªëf¯ÆW~"ß‚úI wóMùö© ùg^º’”—EÕú£Îù=×+\’zÊ+…Á¼¶]9LÿT¶¡S”qç#À®WMÖ&Ô‰QºÊ\ã1(Y;T+¡38¹EÙ(Û}EZ½eŒDÃðOœ °äa@8&ÿéòïŽÁ5×5ÏuÍ ¬Ézàë¬Õ‚¬e®.¡¥7\áX¹™Þ«óñÍÔrCê‰ßÀÛÕ$†øbs´YK/ËPÕÚÂ+MM!jVpnÛµ»ñ•¸éáÃl…ÌëÝ?"©°(:r}d“¬*5Š8ª/<4dK]J±×Ÿ²Åúûw·÷Ç©óp+׺þɲzSé-¹¶¥T”£ƒŒc ÀŒ ÑTÄAºŠ©TªE6Ôfåâ6;¸Þ*+Åê­^½NÖk—°Ø›’#º¯"K:í›Ý½W7£W»|ŸM“MÛš’,EÊÑŠß*sÞ³¾ëUJ‚"•uêNöìóçÕq¶ùçŒóÑë!=ýéºÑ7­Þ¤£kBD íçÿiSM[…b(ÄQ (EèÓšnoîÚè¸ÔyÜL°6;mýlÎãE?KCÃ’ž÷óæmûºœÝÍ9€ž:½NL†?ݧúíßÓØ|Ýzw„'S›ó| yñ¤‘ª¢Dª§Œ‡3ßû3‰ÓšùwÓ¡×öR¹T kŠ€ÒR²‹|*( ’!’Pd‰´”-5|RáçùÞfà1euÔ­=,!ˆ ê†= ‰ÃÛ¨¥ÑDÑsº]*¤Z¢–02Âé%­`ý«ê;X;'^îÈ™ˆ ²Õ"˜¤"^¿•21øqXçÙ¦ÕT7¡=q# Íx™ö1"¬`ea™&ËHíe5ì©mþ:Æ_?+þ5ô…¡A/áMˆ’õHšè’‹U8µ§€*v‘ ¢âjvìóÊ9N6’m—ºu:Ô_kÄÆ .$%ݨøÎ¤‹$$އòðÈÖ¢Þßy…5Rúp· îµÔ­ß·‹îu)ŸŸKm–J‹ ±ÊæœÊ76ÒL·ÃÃju¢ˆøQÜr¾8àbs+‚ª\Â!l³†Ò<•ô¾'„ö»ëšüV7èÛJUÌû¢jsM¯„‘åÝV½òÝÜ¬ó «øÊË£­±Ô e8Sô4x£ªdÞ“pmÿh3‘Ý‘ æH)d@=6íô[\¶V¢Ýl·K®]Ûb™T2Š*#TR< f9Ð|S«ßÙ™Õ^hé^˜»ËHŸ‚ÆÂ¢ØÝÂA!0£ŠÇ, ›ÀLeÄdQ¨Œ­¥‹PtT[€þkE„W˜ú²Ï*ª’ŠNöÜÖì$#"t@>˜¡œ+jDŠ%ë£ ?ôÃ.3»Ô×Sl{ÊBŽ Üfœ^ ˜5¿?RÂ{~%Ò!uE﵊vJºÑŠ‹ ÐPmW&&+ÆôF aο(@ÛN<ÁNº¸Ëþa›øóG=ljkÄ–-ì3^Îqu”Ó\)È8É­sÉæz¶åj·)b÷94íÎ%B- AE$´* hæ}½¾ ˜ÇgÆ!² ¤1Ãsƒ¡¸Ô!ÚŠh` ¢"^ôï¢б,X3r59~ø ÷Ý&üþK¡R‰q—^¤M¤©$%‘ "²án*¥j‚l* ˜ÜüÕ5m¨t?ð ?¬Ë¡ºÏ•-ÖX£Ì—d°Æ‰NïïT_DZÂôv,%¨C±{©fYQx ÑGâY HB$c ¨Qc¡·^sQ+¿ÒwüýÃôÉÌÜp[ǩȄ€’ƒ¶ÀÆþ•øß0oŸ;š¨“e³$e ¸£Këª-½Bn Ø`XÇ³ÛæÎžPäz6Dl£($7mj„“TÙR5Ö÷Ù]xÞöeNøÕ5}|HW‹©” f„{é-&5ŒIYfÕïÛ4Úøþ•Ò/ƒ[ÇŽtXÊ„––äª-TXÔ—© *‹ ’mõBŒê ù)Ï#¢¨¹ ÜFð÷(ì!’t|8Øæ>$B-ò^˜TS ëðhÉê¼h†kA‡,ÏYI¨W»üŸ…×y6XΤ'ŒûDj•ùç‰oL#êWqxèæ€ê¡Þm‚U/åŠ_O´+«,TÂY_]BæBº³H+”RHKIñëfÑìÆ˜nÈ’#B.h.–Ð?nè Ó8Éô»6³ÅÔÀÆë“;¾¸Ûgˆ l¸¡<ôÊ«õÆgã²Ã:Ÿ^¯Ã¢‚Mø¥ÚŒó‡\ x|ºz•_O©X廬›ø¦¯tK~ÛKµ†àd9£¨˜±uë„2çZŽYЕ_Mx)ªD¶Å%¨¨gÊ*{¤ã¤l °5Îè^ ØÝèÈqªQ3ª€Dˆ‘µç˜ª»o;«çêׯy`-@⨴ PèZ¾ƒ¨?LB# .Õt¹Xƒl`ºr}¡ÉyÂð¤’33G¨+Dö‚& ²ëâ~$ìxVÜ l\ Ð!IÜRm^‡€ÃW.ùô6ò$’2Hº—z=É®Ä1lýF§Þ¹‚ÉG !œbDFžä$Xõ5ŠT*4RŠÈ"°*F•J!b€B•Ýl±!rð¢¨3¦‚ä ðŽ‹¢mƪ¨f0EÒÛ@1ƒÚ2dg\a"h1uøîß’±h TÙ5^ß¿×Ñæ«_oœ6‰fÒ•¿ˆw{(âU𝼩ê)PGnhÉÁ'½ž»UÕÝ´õûÓ\% ϳÂ#Âð‚ÄЀ€o»mb“‰8×D»“k‹SÖ~Ýר,ô„©$$ë÷öµÔ†7aDüáQb*´- `—³We^-ѱI›˜®½¿)ç强ö{K\Ù6÷=-Ùµâ±WÍ×W¡\©*Ü¿—³k&Ý›Öi)zíÈůÕuåøWkÈ5I·ºW&puRä #Ї~7y­APÄê Ä…¥Â+hÂ*H¦“`Tpm67sQ¡6îêå\Ø«A«œjÂÓ0q{ËZˆW*,–*—ÕÿN[\bpÉ jÒ x”ïˆC^6a˜¾ýœ_”BO.ÿ¤ˆ'žK÷©“Ù€á¿4¬íþ-ÚîØHVm¥‘QoïëõÛüÄ}ÜGÙD2ǯ콯ÿÍÁÄ9ãWL¸§·f"=È 2.nKŒìŠxC;(ó˜J{h¥ñȪ/t\¾(š&˜±!szc‡Êö4bðïà¦qç"ÚÁW);‚‹s9îk9tA`Þ;’(sžš›€Õ8vÔš ‚¤ýXó† ^«ªqdIŠR³$ÊJ-jÆãøœ®{o«™ït•$$¤Ò")‘d Š2T^s9¡|Yâ’g8BBämŸsI%U×ÚŽ!q–ÄŸãë¿Àøª‹Žä² Ä:Á9ÄT8/Ô´*4óâI%SKê|yC&­Y2›VØ­+ ©»MäZÄ'øÞ9u®¬ Èj@1€ˆ §Y2†Œ-DÄ»–TÞ_ýï€Þz'wä€Ëœ®z9¼ËW ""ÑÐÀxðâD>/ºÿ™rÈ$œ8’H‚‚$Š2(d, %Ñ[¢"7 ?ÞëÏÃ{½cÏãÀóýÅñ~c«Ü)¾n©–ª)*–(èˆfˆÈv$0è•=AB2BèRE„:Ü<³ŽSèó/¾Ù( jÖ²HZZÔ—Zd:Õë`¹ù4Yq§˜‹˜l§up€7Õ‰IA4’#$ƒÝŽÚû¶Öok«¤1º=Qk—A5­`«PõÜÇF=kÆN0´&ÿ©+Æ~E\ X¦˜ ÐE·„t@‘|Ì9†‘§°# Ú•AôÓÕC¢À‘Kà¥=e´ÛG|€&µ›u,1U!LÕ D˜T\/œ^\M< À( <ùW«Ð@;xžß ÑÆCŠé.–™bLjíéDN’¢&‚ŸšÒÙQbv—ü±3¢j€€ó9ÁîU~Þ§óÿ ÙóNÜwãÖ5” /j$l{ê…2ä¡È¾Pë±UK‹R(”×!!ìÎŽøÁ#-8UQA©“,2–5­Qbȉ½ðªöâ‚Ø ìÒ]0cRÄUZ‚Â$[²îÐwÓéøßc{Çý­÷×úEƒ×Þ*þ2î¥Ö"Ì«[¼›Ny\È Ëž‰Ëôèd „"@":è…¦Œ šM¾ë­ßFÝÕô;‰ŽnX¢’’Œ¥FJñsD—Üžrßì~ÛÞuwããÜk_ço®¿qç™<ªª }ŒççæÚéý÷æ^¼êI+"¢÷ô–T[&?ÛØá¸aþ±<¥›‰C÷Žéuðù¾­Ï-°}@àX ÷›«m£ñäUŠ%ÿi·Tmu0ÂPbbI$’Lˆ}Ô^Æ A‡ÜEùfA¯„ÎÞýoÐ5£U¶2¥ST­2ÔkQ¶ÉµEFÅF±£Ucch¬j"ØÔX¨Ú-•”QQjJ0 `ÚÅdÒcU­25bѪ"ØFFC>Šš'‚Ñká -› $”ª,¢\US‘¡R%%S'+k©ópÖÆÚiŒ€4"HÔŠš£å]W4 ¥@$Î ðO"¨âj&Žy§c€|³%RsWm¸Wä½õùø©$dÄ­4N Δ¾¶ù‘[d!Tˆ@ .™ãüoS!À¨°ä ¶6ĦVÓ þ\\',4e%Uwõ*ÐÅz‚>L}1zgœO‡ÉçŠó×­·Ï•ôƒv±ð¸€†QLâš†Š‹i.wžÓªÿÞÐ&tUêUQã ‹•Qk/ÏÅ¥(ß#a5Ë9Y!¥ç|à ú[ú¹ö„¯Ÿ«ZÂ_¼¿³ñâ$™/AeÈIÿ¸Ÿièç]¹ÿwNçìY÷òëýÇÀ„ïE*²dd_Ü·ûíçx<'ïlÄ£:ž5L/GaíåÎ~ŽIùxÑÿ<^¡e­´ÇeXìNË4„LWߎÃ~Éöñwðëþ¶<‡ Ëe¯Ø=äô»IæøUZW¤$¸½ïüøÝg+¾ÖØôþ£ÔŠ‹êR¸³Ú­OWí3Gסv"ò@„„0r  Æú®«gÒ"¨Ï,KÓPÞé%ù0H2¤mù¦oSÂ'‹ñ=ßîeŠOÃ…·ÊCßDáGç㯉|†b«ìâ~\ê:S# ¹Y÷˜´>S)fEé íÄ¿+Máj¾=0¢ áëGÊ¡R+ù¿Þ«¡¡ý TZ!ã||ñ¶Y†äÕ·ëÂòð¯ ×­HÞ[7Þj™è¾Ÿ¿úZ¹v6Öûû‘Šýâ¡ÖCH A2cÛJT²º¤CõvÎØÅIðÀ à‡çð¾$ÛžåÚšñLÍwR*æÂŒm!¶‰) R_Öè…‘súƒ­‚h& (‹áSDD‘`@Ž$Å pLET…_ç^FHŽè“eÕŠ:i”À+Të®Á…“2eYc°o–E_&…ü <ñncŸk$„˜«]ç‚HËMü–&Äp/‰$Q>®äQ‚fÂ/1§ @8¢¢Å9pçš„Íöî™C3züùbD3ðßÔžw›hïúŠtE÷¿.Fm!%ÎgØXlÉŽ8Ü>ìçÃÓÛL' B¸7ˆž) ÞŠ„Œ-zFû×t±3ηéõhé ô0K•E£·ß™w¡"/ýˆœk&q½T_QQ„#í =Á@æÐÈL%BeÔóµåø^oNñƒ…„a !]T‡çNDlÁÒCiº„w|š¨¤Ü´¬‹Q ‰tÐ GßFôT! ç­´#ñˆs=&C‚^,„%Œ„R5Œ¡çð<"eõ>³`8@øQôúï`€¢ÂQE E Šêyñ6yÈ"*D^§•y§«ÖÜ›Qдt DÁšÔCÁ„ &ìs!YiÞ5A†Ý$Ÿ‹Å.½vÇjç”!I6(Ï•¶SUuCE.Ñ È{¼dyPH>q$BI约«}Î66ÓwEI$¯ *L¨ì‹›:T¶fIkÏ5‰Õú•¶¶ùöݯ àë´ê$è‚Òý—¨D·7BÉóùuðm¾Õ¯¾õ×Û^scѤÞ-âÒe«P"yCÙ2ˆˆ)#*ª òÊõG8ÔLF¹Óø‘s Èâ%A œŸAĨZiÍâtËÄ×~¥é­%­àeé‘4T_vŒ@MÏYŒT Hëæ$áÝÇðŽ;õ‰|¤trUÔ+ö;ñðÓÃæøù8 YFú}­õ<í5á.¯Óò¤¼Þo¥(²D™Þîû›óíß™->ÍÚêaŒÆôÎßo »îA‹ñQ櫟kÛêF‡x•LøÙñ„$ÇChüÜB1‡l¦!¶Ð6ŠoE…¶Z EÔDI‹Œ× 6q¡äT1½ˆI$Òe(A9$ƒjI×;eVز½Q˜øÕ¿Z¶¯L`B*IV,ëìcSiÚc$&)_cÛÛËoÒòùÞ¯X_VŠîòN¥‹û¿ÊzeÚÀ®!äzÐ6æì0–B”ªð3ºqŽ5RCÔZyB#òAÈ" îàH-ð´AJ”Xªlµ£hÒõ-–˜HY*/õÿƒà‘CI+˜@ü×%Ò8åU*¢Ž&™Jî//`S±OÜ ¼TkÞåW‹¬À$½Ý¹fÒ´4949#”/$ƒC j¾è p6¶ÀcBª„1ƒÐA2iI8ÖæÔexw>>{ÀކtpŸKÑ#!Ô§·$‰V Œ QˆÅj"*J6fÚ5FJŠÄ«i[l#1*% 1ÆHªÕ 464‰Kd–ÑE°¥h£VØ·Ím­š®DZfÖ,lZµ°Z’ÖMQEcA Hst‘Œ„†Ëa m¢ îPó\Ó‡88Þ ™Åkîº-Ô1ÁŒÀµŒ!­ÄÛ_YXòZ-ãv%Ös»µ•[fŽr¼ë„Õ¯;¼«Áқήi±®lsy¶îÉ%¥M¥HÆ¿HÞiã^›o³o^¨º(T!m©$‰gMß{K¶º`PÇJÔ “$UŠ"Ëü÷ÏÌüsú>^±õe µ$’@Õìž»!`} Û_Œ}À"YH£Ôh«¼6ÍQl}Ï~,É,UÖ/ߨÁÝã™éj_8ä@‘Çù¡ ²¡ÛnÍ Ñó9ñT‘Nyp'qÖgslÍ ‘øÓ͇``l†þ2[eÏžêHØ/cM´Ý¶Õ’*,¢—ŒC.`gÎCλ¡LÄ•M·UZ+“…lÖIhIßEäž©2ÃVÊеº¬! ~¥Î£æ=¾¨I,—’^\8†Fá¬8Dôï¡Dí@dRE¢1‹ FM¬Þÿ¯J&Œ-²DEy ××L˜*H¼bÔC¿Ù¾¯Ñ2¯g³$›{vºù¶(rº¢UP€½.ùý¬§Ôü¾§#ÄÉÞ~·âë}×WÙ÷Të&ѳcá_àf¦1q6öd®A 9"BÑŰÁ¨…ñ”(Ë ûãÿ5¥‡'®¸°¯³ü­,ý ,n1ï·ºJ¸±¿~cH·-ÈDO;‚„JA|. *f¸=‘ÍÓB8©C6Ÿq`}œ©…Ûc ©‡Ë”ÿ“\ãÒÕöÍøÊ¿ÖhV,þ£MôŠÔ#½ ïGçÒX¸‚'Ôëô—×OAõ$C©BŠTÎjKÅ ,W,Xµ¬Xµ®„%–æaì=%æ[ŠMçKÐh/”—ýŠˆ§ôÿ|ÿh f ‹ÓmŽÝqi!A bÔ>ï¸Ý‘8a£-ÅƈeW®TXxÂ[$’NŒŒDt1¬žt8KZ_;öôj‹r?ϸqžO$¢ô¼°p ˆ‚·?ÉžÐ+y¸^„ÅP™¨© TÓ/’Q6…Xˆ0\@º8h€ÈàÊö¬Â¸¼,¾!òæwM>H_Ó16OÄð¾·K¢»è<™¡"“sòõÿM©†õæ®óÒ÷«Òô°η¥½uU^¼í‡¶IU@”8J¼õvªê®U.ÿêeý}ö0âiþÖt×líL(%ÃÀÅéª`ˆõùÕI"4Ùês"èÌ$$eÔØ„‰J‹n ­‚Ñ%é¨5­*.lŠ„'ÎÿW‰Å¨D7\¢0SÔ:e{kTòi‡E±lÙ¦&ÇüG‰!*9½îÖ˜Ûï§ÐÆbÇaQt°Ì¨»|§GÀq y¸þ›“L‰B-69½"Ö’Occ«VÔ&¹yWΫì•rä[’ù#­ò±Õõ¬øöaþ±Q|—@Ýbõ4ÎUC:*€€m€7¸}FÀ09tÊ’´Q-qºë8<¥. ÐoÉ«¤ ¤c”‘* u»ü“T=ðËX@„dc"DP0=B˜ÂþNõ¶FŸ-†„‰¥4D‹*KmÕ}ªE6Ñõ,?g"õRÊ–Rq×ó'ÓV™¢Ì¤+“UGá’çp!kV®A¼‘ÕØ¦.¥–¯- ›Ñi$$Ôi²™j“€k@n›Z§z_–Óp.1·o¶µO(w`+00ˆ¡¹@¤ʃRÃD ÂI!7ÐäÖK¾%CÆ.ö¦µÿ2dØ⨹ƨШ¾äÞãLÊrj+ˆQÅwkãõ†Š¢ôžÒ4BG_']ãWyÕÊåM…M››UUMij)fßדé>-Vòlœeh¬. bõAólæ0>Ö†!Â2h5IE‹d“iH¨0Ã&ØÕ­d‚A c÷(t'€B £B eÕp@„ i¶Á€ÝÞ ªv‡±9£ˆ§Ô{RuS¸Òÿ·4>s©ì`d‚˜&DS8è <8X¢v­3B¡´øË8u»·æ—ž7m|ª.Rš¼ûNÅ1Ò¸†t&µ=»~½8¥Š@ºH…ÄíðÊ:ÂÇx×e¦ºØ„„UaÜBybƒ`äM öe*Dhj ˆ›2 iêµ6% É 3ÎäÃv“=y¼×5â¶·‹¼íä³hÐÖöPb!ðpàBéêìs2ng=/óÈ‘!¸¼ ’à7¨~.óXn"¡FŠÃBRüâ@ÀÛÒ¼3Hø¯ïãke(L1B}–²¾Õ lX1ò¯S¡ÿº‚ƒg}åWô2œÿÛ:„‘ã¨Sµ¨ lDvÑìé¦Éí5¡ÈÓu}r1ƒñ.›d•tJ-©¼ˆ™oqÁ>€Š0qKn:›qlíˆðO¯å0XU^†¤?-¯oÆpu£ŸbègÞ$ÃMf‡øÏ@/µÝ(Î<{ªˆŒøßÏv,סÜ(ÆîeæC•´ä2à£õ–ƒ$¾4E@sˆƒÂ.xßiaÿ·ö|\V:oÃTɉ m½Ã×ÚÃX—·—šIÃêý&7˜9òªf›jª«C†?/ñ(oIhˆ)àè/{E5#~!_’E¾¦ÄP4hJK}esÚ5òËiA¶ÈÔþÒT¯ò`Þ?,@ÄGxkïTIJ! òKݼßg®G«¶-åçžwp™f$ÀÛÅ%86ÕT(ƒLiµ #B÷ ü0àö9‚Ÿ“®¤H^Š&r¤¼JFIxY Ú*,€+ãr¤µèRV™Ê¦“b13¤PH¡±…˜‚„n„G6BG1±œCADøÌü\\š¤O­N"h‚­GiœÍ%ˆE}Ã×§bª²Ë–Øvu)MÊ€àSL¹–ý³ f2Õù¾ëÊIÈ‚ªl ŒÑI¥AUTÙ(ZAd.sp ùdÑ()¥§J)³IÖ%„!ëŽ'¶%|”dwxÊqqÎZ4Á°?=‹qؑcTÖ™MµQ’€‡ 1Ø~àõTmч¥Žÿ®†„êùP¹§:^Ÿ pæø¥'y3úx03*šÚ³_ƒŒ®µym͉ÒÌ0 ß“ø%Öìh†Í)@‹s\³Ó.DN•d¸Ñ±jBÄ!6./×"ËÌ“í Ž6=L8ü”ö]çcM `z :$âh€9¢@%PˆXh@€f.o×ók©/ÉVP‡ÏóüÖçÔ‰Ä8{½Üwæ(¶áJªe±ßÜss)ë6ûϯø¶æßäÂ%=»»‘)uCi!*§. #¶ÝÓªŸ¤$„¿žÝ™¢0É4´ÐÙBFÏRî»—Ï.A§¦¼y“|^¯¼yxÄeš,‘ýY µ"ÂÐPZ" ÂgµÝ¸«—ÝáŒ2$ˆ«qÑZݪ³ˆ^$–ªsyãhæf¹:ði;›»®÷v½]1XÅŒŽ:;Œtˆ –šÛ,v‹`ÆŸÁL"‡ùÔzxë.”ŽÕKzy˜1 ,mÀ)«êÕ¯gš…ºª«ª¶Ùd}1Ô(¿ÉÕc Ée6ù”i“—MmÅ.ˆ!Ðá•0m¶¶[SÜˆÓ ¸“ÐJ®¹iKÉiÆÓ‘MØÎб»‘ûæJ‘L%7¦I e3ó/l‹æ ×HGé åÔB©E«¢In»7Æ:$¼Ù1o©‹DÐØíO<¯òû,ãKOO“kŒ²[%Héü¾Ôö>–÷ät¨Œ?g[XÆ Ç lœª-Oš¤=•¡`ÑQh¥Qh®ÞÏfÙÿ¥Ñ2.h@@ñ/OhTpÊ©î×Üq‹+)¡J‘ã {h^ÿ'´T¸¬E¼ ®Gž °¼¢öŸŽÌ.pœ U¡¹Òš8‡°žP?§ B¨(¢‚š‘w<ðüÎå5D@‰ËD)Qdš’$ ‹ Tí EI&`¸‚ñÆ#ƒNªº?™dyn®/|?i½ Kå ó`3ÔÄIàÐ@±Pygž@Jñ¸j{«†d(c5{½ÆM0v‡Úέ.AÆÓ#ÓhMR/–þ^ü ÜP§û Ü(#Ú4lGgfž1m»˜Ỏ\â÷HE:€Á>Ò!zįej5VK[FÚ¨ ")´U$;@Ĥ¥µ­VªÝMkmæÑjw*WY[ºk-‰•¼×›µkjm¶cVôD¹NäæÈ]L…Œ >†£Å (Úöj„’þÜMFÓÙP«)$ƒ‚È·).XKÑ µ÷†€q èRJ d*/¹‹q"€: Fáߺ=ñ©"yo<°Õ2Áp=‡ç-;r›åírÑD²°Ë¬³Z Æ$ª¤±3D3oìD:4bT!$OHHJ¢B[{)ß=!lKã¿Ø'°Ëq6†y£¨tYZüÔA‡ Œô"ÞÇ×À;/~)Bˆºu¡ +.¤IŽ&™ùì!ïp¤[IYWÛµÃZóVÛšÚ÷ IZæ¢Å¢‹h¶G‰Ç,ÂØr¢t²‹h™µ:›ko%奫mÕ‹h°ˆíl´3-²’Lƒe§{u·—ªç[³kk®«‹»n Ý£.lkš»NíӜ޺·K$b±«mʶÆÚÛמëmÔÛvyeét³Î×]gžo´xAm­ˆÅ26[ÙíæÛ¬Uà„ƒ°††’² *,P‘ ø‚X)$x‰™$pª \¢@*”ɪe(ÓF›)pôÈZÁHk Æ*¦+úÿ[Õµz­÷o{Õ,î×wFÜ ® '½ÑVÛÎíµ·8îÙE©UA„ªDVIÏ€`²‰°øC´´BE‘j*Z#j=ª{Ð14 °ÕÚ]Òl 0X@$„ œÀ-a¦ÚH#üýsÚæþW ÿYÑ¿è:ïsçÿËÈ鎇š¡ñ,Qü¿ðépº75GàÖ;t°$A\Dñ!1áÐ Þ¦#ˆýL5–Ò3yB"{Àx˜Ì÷8>ù£ša~kÀÅæè¡¥Ê…9Ê¥d7átEE¦6–Ú 4PÐlÞªÚ#L;sðn‚˜[—eïÂf~åàXo[ðÂh:]¡5â›Ã"Tüì…ø¨¾¬hÕäÅ›ïsÏWœçàvhþ:m|z–Í‘ÖW‹öz–ãÌ ‹r €Ø»pW¢Èòਗ%å @窋vH©óPƒ‰pzñbªçnÆ¢¸"?8ùE&Ç»¢Ï ±bCñ­Cýü$4S„G¤yj*B#"܅ȶž¢©It(«Éyj÷ÞµºÖ÷Ùm‰*‚Ë-I¨(Ú’ß[ËZöª÷SXLöÐó™G^"¢H,Š\~EãV-©*ºV¨Ö«›k‡ÝŠx€þKðÈlª/K›Ëø°HGBj 7­ê£gH³wqksgÄÄÛ¿+’D‰]CPŒšy¹gìò0+rÐ’$!NY§>‡? ?l[Ì–.!_RjpN.ÿmCÁqpÕ t$6 )‰UškéÛÊKdKb“V§¶ï…j¾5ªEV•6 i¢©6Ô©¯­ªµîù>¨|J5¤1‚?-É"MžãŽUUWʪÈDË#¤p\¼‘$žó'4ÊpÞ‹ Ú?ÂécI‹8s(-µNY@íÒH#$€‰‡> 0b‹ë:nîf:!½ªíºlbÂV“Vk/<>Ö·ÈÑDZµ-mŸIÚQ²ÕPØ¢ 0V±U ĺº"µ#îN5M!#âÈÐ!¦Âù/·ÁJ3R––å_5¶¶k¶)TXªÂ) †ÑGЃ@@ à¯tâ›BÊþD,ØãÓx s¨"zˆSÖGïSàÑL¦ƒ#©_3’Hàbä…^ …EÍZq£7å±!ö¨EL ÓfŠüâÆ~ŽÉ¨›§y!x%;ª,RÐ TXàG2’=ãJ†QHP‘$2RE0Ù†3~è°î7Ïõò6CWÙòq¤ }€EfÊ¢Ò¨°TЈåÕí’fY-$Q#ʶ»uúËø“t×ï9uõ÷©‡õ—%Ó*:À(1DûcXØ8Y.“r•$½™9ž¦‰0b’ªÒ²Qñj†£¡¿ÌnI|ûeÔp,êe¹‘j O½ÀÓ3¦Aȱö qñÁ슌„e†1N—X-ê)štFT0*&do ÀlLm¨Nµ,WDö¢ÈáØ’KëI =´`´ÚwƇ\óW ²Š<@Šs@ÙØïÖÁ&ß}~áûÊ0`õ‡¨¿ìoÚò$@V(TS¾‚T‹¹2:Y$[ƒ»ŸÌýp!U™ã‰$:Êsv¼Ê€W ÝùAŽþJ‹:ýµVâéÎ$aöˆ n~pä‰H6G"Pr(¨ d„!åAÕH‰ÝÅ0†îZnê‘Ĩ^Tàµs®¿]ãˆI =C·²¬˜ysEEÔó$‘@ÇO»Q%rõŸN0Œös³¢]…}TföÊ9¶J²ìÊsâ^nÓÏ“>;xQj© Š4%Á:;ÄNjϟvïÔ½WѾÙå|t Ú‰D™~'¿æõ¸‰È ¾Ø%g ÄírÚÏÏ#,&¸Ó‚Ý7ŠƒÉ"Ø7ñvðç˜Tßk›fH@%”lÄ‘%‚KERêã°®uú´ð¢Û÷‚I ¥ Fpù!ÂÚ@V¢¨µâ´ª-P:?Æ€ñ±ñvàh<È”úí šEöÎÿ 4‘Ú~ÍtÃÓô\U÷›°ªÌ((cIN-DH™Gåã:@ÉÞð§ÌÌ.º%PÂú$-,5tÙ=—ðÿo´÷žÒú^güóÿß?¯[m°XP—nà—TƒošU0h"±@¬B@„0]pM˜•‹V±ËBH >ü¤7ùíU«ÿê×áø÷u³Doô™u§_cn«$6e›aû”V|çË©©üefLηèct]/Ïð´OƒOí²9Ü,îTw:4’¨$É¢µ©˜Ès²úPdX¤Õ™ë¸Òoì;ûO ýn,(nrªz*-•E¹T]{Þ £]OõeË¡³Ik©Ô–! æ!ÊáèzaHbEE€ om¾­õ'Ã-Ê‹Dl}eð¨@´U%P Ô@G¥kçU+‡lcSÂC¼ð´PENï0dŽ=ç±°Ü{æÿþÝ9N´Äjm·:š°Z­½.{¼b 9úÄa2f¤° Ïß0 ƒhü±ÖÍÌ`ò_/Zäüñ²d*.íÛ¶@¹µÊpÊûq2 o¼ºôÖíÕÕ#Œ"¢È9 …Ab=ç=‚¯º%8Îå‚O¿<±gZÎ äf$YßÇ;—0¤¯ßš{[Üñ—"|ŸŒ §wqâët‡^Ë™6?vžzXëĨ÷B„ð·}¯ µQ•Eù ÈÉÊ #P‡@+K$’Èà6#ÛuK.„ q±€ÿmQy8ŽÎ¼ù›sÛÊÚC´5ŠŠ;ºÖº›¢ÈZ%î‰RGÛ9ö]Q)§ôÏ-XŠ>_cÁí„×êžñÙÊ€ašX½®Hrlî»QRAòQ9IÃâŽÞ’DÔ˜=AÚ`.[ü#ø‹Õ¥BUÒì"DIpOXO–¬{Ï‹#Ú  ØØÀ")¡<ÞÊ?p„t„ŒNë¯ÄÍýt=Äc$‰Ì|ó¹(¢Ü;ÊKJE{gYÊ:@Ò¨y¡>_pSõRLŒ¯–}ÌÞÿV›µvÜNg­Û^yÄ ŽÒ¢6 öü¢¯ꈅD3Íéh^‚Ñ®¼ãîò¯ êÐQF¹Fò˜+Ýü©0þÛ™v  &„m¶ši~b8^´*nØÏÕ‰`à;„„d$¼nÊi&Q€ÏlèðjÞœiº›«Ý1~ÏÝ7ïgœ¡ò#ím ³N¥Õ>‰ìz燈˜«É3©qüzgžSs 5衲! „ØRct m4;#Àt?¹ôé‘(§F2Þ7tvQ†É^ü%Ž,ëìl&+YB‹)Ø¢A ØMÈ”@=#Sž–<梣Y/3Ú;ÉSR[ëÍ÷ûŒUCUC¸ªºªBy|TÚHI2o>Æ·×úØÐÃ4_’¼1FO“µÞ:ª¢KÕÍQ÷ß™ðÁò/a›Ü›m­_›íã×sù µÆD…íœÙ²™[»WÅç)5¦›1kÅÄðÌ6DÂeSBb“ÝÐÀ’4ÛWuHc‘±’Dc€0îBæµt14‘·¤ºë­ÛseÎÜæm¢¯’`6„0l%ÊE„ê’! «¥M"õÚõy®Ø·7'NY™D L³,¢"!±(O:ä’_‡tôê':›kgOwžxpoöýý´õ¯ÝëÀŸ’ÓlêŠi¿â’?Œ]Ä•]¿ÜtÆßp•y£Áe±jBذj1þ'ñüíbÁ¦l$Âvân´þaürT«XÅÛÀ«‡yÐØÅD"•ïq>F0÷FbìtL,½àÙ ÄcMTHJ¢6ä"ª 6È’ÁXµ¬ý«YQe¡U”Æ&L¼ôº²„_7z¢`à°( ý6 ÷ʵEÔfstæ}¯ 0ÐDp Уða£ûh˜ –€þ4áæM0ëç¡lÛ’ì…²,m”BGaò&€:Ue†OÏ.†lŒ‘ŒR;Ñ!sø:)­ÌìÐP…¥6Œ*‰¼Û©wI%Ô«©UæêóàšÉ/Ã'SÀ¤åÚX&µ\ÖJÇ¢H¾8z,NŒ jÛݦwÞኋíÅC¾ÙRð*9í¥¡"ŠÈšÕY@â”6ÂûÜÀ N÷ëwµ{†H1%jLªc:Au4LxÙ®ÀåžwO€*-à+vyz”ýSŒP!i*¢ÏFE4lR¤  `£lI$önª5MSÔq1]Õ¨b¥²8Ò)ƒr p2*8éãE'„.•*€éÝËGÐ'MS僢6àÛe+~†[0J¼‰¢â6ÐÜUzÞHm%„ãX£pÂŽ¼Ûϸ"5TXneFÛÿQ†œ`Ãs4p GøöƒÞ5âz­ôÇ®†<¯VÚÙ“*(Û&PZí`¤Êì܆…9HØ?67ÓÝi”âÃȬa–˜„±k"¬÷C89 ‹ãeëÞ{Ox±£’=%_g̸ͨÏ50ôŒ$ 8 ‹¬ë·~‰ß$ÐÓÓÌÞ“h2_Ĥ*¨ ÆŠÅÆDóýÅ÷îÆU&gà9p{Ó5ÝոǨ¦W.B\‰ \?ì"ÞùDöJ›C4š*,¼ö°Jñ¨¦F„Cˆw™‰Æ<"»}¨PiñÁ’€?þ)ΔɚÂU„¢J¤†IÇÖò9A€Å‹µ*-©e˜+csRøšÎ@ÅÆtTDe!ÖÈ}Ä–CÇ#ÔHPäP‰yb°úlr;€Qg?ÁcDHª.^n®n<ÓCp4#L?‰¬Üê]÷ûUbã%†þ»¬Ñ‘þÑ©5xvÐæñdÞ `Ú£#ŽHIÔ)±/“ö0%äû±ßÚÌ)ƒò˜ÊdM@¤!´Ê#a ¾â6x‘ÚMœ­5L â›àÆJ cüÞ¡O#$Ê$l°~&&ènø\_EˆÎŸŒ‡çAÂ{Í4¶Åó}£-œƒj¡*‰¤Â©à@àwŠÊEÁåû°‘M!ÁˆœöÀNþú'i3è 5²4)ä< †±*$……¶8”‘Ñ*³E»Œ:àÛ´™ÈD6TH#¡ñ´”Á³…žJXBÀÔš¶ß·¯ š^msÚS»¨î¯^pFÒB²¾v™ÚÓZtÏ1¦üº¦zpåQÝÀo\Âm»1)'Û»®0’h·(—9PâîJã7ï5fŠ^'†xñÙM6Ý5åoîÕÞ5¡ÕiÑMÎЪ,q(åX±ä/s]Åg’¶¥‰*f½¼§$Q¢Î' -Ñ:–[‘x/ä1ú¢9—Lè‚~Aád=0RÂè÷ ¸¡ÈÏ`§c?W]Mrèén¯¿Úÿës†]ã|ÇÏ©ó&¾ýcìOz”é’žW6Ý]¥ßÎi-×~'¸øüÏf§°;yžGöÍJJåߨ…^ðð3@×J¾GƒdÚ×—r³˜_±ì(à ,þOäéhøëÞ©Œ1 NUd4ë,îÖÞóP„Ç3J©ïCÜ­3_×—åì0Ž!ŽÒAUŠ3ÁØÒ=›ð »Ù¡¯Y) *‰³`¨Z$‹4TtŠ2*Æ$’@Ö\w­]Éßr”¢ƒ_ ªÇ3´G É£rqøù=–+’㬢®ø¢œ1Ï*2 õQªGnPí‡ªÚøŒ°ã3æyNÄ*¬:x‡™00„Äê!D@mvÄæ'bÇ¢Ps[[ž\P¿%œÖ¿²GÆ#ɣ饌ù˜c‚“Õðб ç½"Á é/ȸd-žšÚyœ 9º+¬S¢ñ``üX:鯶øÓê)öGŸYûv}TXfÒwÅ$@ ‘SmTQUZŠÅQ¶Åª-bÅQ¬F´QQE¢Æ¨¬k-¨±¬QF£b¶6¨¢’hØ­F¢Æ«-¢ˆÚ5ŠÑFÚ5h­F­Š4Q¶(ØÚ6Ø‹E‹QTTQk¶Ûêf­¹ªÅjºm«scUŠÆÚ5-¢¨ÔU‹l•FÑ¢‹E¬–5Š£Q£U‹Qc[6£XÖ(Ù6Ŷ#j­FÕ²h¢¬ZŠ*-¢¬U‹Æ‹lX¶Q H ˆ ñ6r’²mJ¢ËHwf`T\«€ŠÇo :÷wÅE•ee<ó»t¼ãxˆZÚ\é´‘çžï ½4õ[£RÒV7Ô¾{©@| „·¾(Ô¢§X#çö'ÝGÑeŒHîñ9@Wôý­Í‘×v‹S)C8,Ú¢9ØTX>!Î’ð-†´,—#ŒqTH_”{ÎwGPÌðC3=Ï2Æ'¡îà*.€òáñÀ1 HH„¨E¦˜ŒÑX¾0\TY³„º–¥,‰÷Y{ÉÔme A„‘ Áx13Ù ¦m¨Å¶Fï.é áeR¼€dÄe„ÅKǘ“rU eV;„š”®K¢E$i¦Ä°`‹ÅoʉT™"¢Ü!Aôz¼ïà ¤ Š”åzLâ‰ëªÏïIãÖ­y1yâ-½Ù–³®žîœÔS? K“êST2™ä²šv¤[‘5^ðûG’™dW¯ïíKóÕ1 ûRcßühØŠZ¨{ñA©øl4ŠAØÚý+aD¬·W±pÚ/á’âìGœT€ \Æ«IòO]Piö¤}aÌ8bÁ=X±]ôm8ÁõÂD¢±œëŒ,EÏ—ˆ–dIÙ¹’H±Šâ)‘v‘ÁQ@<÷¤€ ¥£ˆ…±`áçößOpZœ7´úû>ǹŽr.ÙfwŽ˜˜B+”®E…’‹])€$ãvr$G{Ù:JÝ4ç(½^RgŠÊ€ÿñìîþÏüÎÿ¹þ†Z[lQÆJùH±ë‡u "™‘¸£P¯tìôx©ú“¼æÞ6 sèìÅæ-HaμõÃùóqªÐ>˜Cl#Bhö‰P†Ílö°˜0¢Šî߬71ûex œæäåzë]Ãr«Æ¦.³/Wƒbº‹êëß[:~¯kæ·Áë¸Cö|¾P¨c)„æP ¢_ƒÊe:©a R`ÁPÄRk5†…»ÛckìB&×ýŠ4¥!‚±œ¬õÍD¨UbnZ•IV*ò‘Íã:ÈP§É½*­w–QL(ê}ëw~õ· ²aVೡK „³Z™ÐJp%‚Cͱ*Ó”å=Ušc‘µ´¨qZÕUB#TëR¿#YJ?Þïæ®Ûµ°ßVªòˆÌs lfI—~/NþÓ¿gãß<™åh†°l©*[*ÚrüžVî½i3…¡±Í•EÒZæLß{i ÌE剪øLƒÞ'Šé| ‚jI5Ærp¶wW[xÒ”øA¾À€”ä#!”%Ÿ3=6 "Ð=ĵ²0´7.ßËiÚãŠ_Ef(Ò϶[ÅÛ) ŸçŠmÖ¦ì/V*-•Ô¨¹)—·#  üM_E‹B|ß9Jž„»D`ØHE©¡Æ‘³D@R`ˈI¢M¹ÍEEæŸâƒ7.BtЬ_I}ùãmãmÊ5¢ñµQ[·wm\ÛF«ÅZ ’ Z 5jFÑD¨£Q‘d*"ÔSœMU ÿä…ç߈jΑ8ȉ"aÇPqÕàÉ4,:jðP¢Î° Ç×€²ç‚‘$$BEp+¢úÁV÷< Ž/’Ÿ1ø­„ù¤¤"€ï¨HI 6 ‰4CÑCIòëMçKRb…™”ê§¼‚úÍ€Â` 1$$Y]\d†b6Q« â„€•ŸÌ•.ÒKëÛ¨]€œ*8ij͜9@¡îðµÁÝÊsÌø{gKa;×cnFJܱ–í …’Ûj8®'P)ÈaãNÊ‚¢Jq¸ Š$S¯Ñ鋤s¬¹Ö{m­¼Û[w‘T"c·OOÁ M•)Q!¥’“he HB¨õU­JŠõ]çY¯ié¼DDÀUs«Órôæñ^S×Ƕ¶ïíPÈ©HÆ1ŒFÆreÛTQ¤HÔP’$ÁÈ”c=u—c„ò k•‹Õ´{îêw2×wdåt­ÐF2i(©'½çáè~ÈÈ:쫤!¯ÁQU·2¢È*¦iüÜnŠp—±;'¯©Çä*-J³J«4éj¤–°¥Ö$Cˆ4›0ƒx¢Ã”5HîÜÆè´´@ 5‰ø v/Î?”•+Dš·ëŸ{|µâ±ò6=Ê´%èªa’2¥~9ɺ< F*,\Qbù˜às}Jè; ¨"‡W¡(EQZ [ˆY¶‚ºÂ—¢éEEÈ{Išdé›!!n4U@ (­ì1lDH0„X1 ‚ÑxU’y%'v ,=Cô!"ßJ 0 `^d()Œ -ÄÏLóÓ²3 2qå—ÚCZ2 „Y ˆl5TÜu’s‹j »D°b޼ ÏH…÷ŸÝ[ä÷,eÌ@î• a5,Ò}j¢ÒRbm屜émÅÁÙÆÉ·ËHÌ[€Wí.lQU¥5øvï°ÝM_k$.A‚D&{ät¥¦5vÊ<‹vb‘£‚¡ ¹žÏd?»¼ƒ | wJp$üÒô|¾X†DJιü!"ŠHÈû ÝJ¿ ­^6¿&¾Íøºjô¨·6ø ¨ çõOìÐî×S¯96?±µL¯fÄŒ9&ܲæÛ[õy¶Ö˸¾XH ­ ´aYvˆ0r¦Z‡ÒÔXˆ^íÇ9rZ*‰x]¬¨½ò\®о2. ‹/²#–8mއ½A†ˆ0Kc\Øé+Æî5­»oÝÝ] 2Ëi„õÐŒ[j#­Á`U +óßî[e8}ù~8~¿ôðüý5U½µ…˜É’©ìósÿíîT ÿìè~ ÂÀË›4„ÏéícVéoÛ†Ç놙ýR%úƒÂ? §J;¡¨:a²B*iÓ¸†ÒE ԴЮBÓ`ÇŠòp±.èé#zݶMÈ$¦¥ $s!†dΊuñ¡©j=Lî˜}GåM+Þ¶$ÐAKÐ ! X«ÄWƒm4–’ùË+Õ›Rµ ŽÜ ®X¹©üúžnÇŒMH+´Ym¦ÁFåè)8%µÈT0/×.DÀØLAD<An<à¥Û¢Ó•›¡ä°8}ŸåX¦%ŸËÁ¡û)ØHç'w½¡± ©B3­äZć9$´‘$7ó~G‘ÒX…§ñ1ºc17eúôôCÊ0 Šù‚9íÓÜ{?›ˆQÈêzí'mèý%‡ÍDüÍž+©`ÜG«êªc¦ž:TZéî0ÜS„¡€šúèu¡`oˆY ®“I$„‰Àª©P•"…@;¯«@ ùè)‚‹’k:Á4€ÔUMeFÒÐB2Ej èB H7Ÿ7!ó º òbÈ ½Â<ìtø ‹Häú4CÆÏ/Ë Û¡)‘\&e‚™]‚€¤Û¢®nɬÀ>'å{Ø|~Nçþ}Kß*ÏAúawm¡A²qÏó¡[ÁUF(E€ Ds¥€Ê¬6Ëôµmvjló!D„ýÇꗽˆ6Í øRóãë‚Yj.!¤dt\Mmc£ô¤kf†§ê\7$¾TU$$ª¸utÝ϶×^QàŸWàŸòÞ'Øy¨0ÄÃ6œ„¿Ðn‹ÔÑÿ¦m6ÆJn¨jÛlvÛwD²Ûm±ÆüéDÎÕvýDÓeü¿Aô9<¢x£/Ê(7DÚ×ëàú–ø7Dþ8¥Òk~ÙÀ{×@2 -âsΣ ÍJ;€ A#*Qÿš4:M:Q§u·£ÎÀ(¡A@i`=¾ê¦g$XÔãÁ•b÷ÿ$ÊU5¢žõ>%?åy»÷;-¿ÄšèÞ»§,³ ú™zj Y×-Üÿv¢+%iç›`*æˆk@<†F,]\Ç ­Öâµ×Táê<ýâÞðšÑÿìWeûÓXÖáù`Ö<ù°b¦ÒnÃgkÅ5¿W]gï¾÷<ã—7a»?h±Ÿ^Š'Ð1¹CF‘‡ôÿ¥!€Œ€cßêÉk\°†¡ù4Š‹‘õí`4^Ð Љ ÂT ŽB½IíÑ‘Áß¼Wœêa¶H¢`‰‚£‡R€ºúF°6Ÿ\Ðä$ÂdÁv`PÛ¸¾SÛ•øDYrd¡`÷wûÿêÿçìïvý?æx»¹üåWdb„ôaÝæ„x+RçóG¢å`BÇ'æ{?¬ñS4DÃÄ[-AÑ¢?6p@!Â2–‹ ´¢¸>ý°™Î¹gE‹6€fuýHÕnCRj>,´w1hÍ~.‚Œl¨¤zox)Œ\º-9K þ–Bݹ"H®n–B!btH^ÿúeîM¸©ú©OÃŽZ-åÝ~ Í^ôË67üYÞ½> ?L¤ÆëhT_T†äì«ÓÖ´ñ&ØâªxéJò'’¤§M´I’ž<5ãÓVUjPîÛ~Iãôw¦×ƾUGª¬„̪4v°*ËD®ž‘~¡5:H Žó^È7 iÌBœ÷ó•P¢ðÁÇ| Ý NªeI úEÆóÕÏy\΢‹ñ×æÚ†ð´w0îÔä^í„x:ôž–}w8`ÝÜãÏÏÊͽ0zBCÝ‚Ÿ—²wÜŠðûNá è#Dæ.>ÞÇÊLuÍ »[CZê‡WYp¸‡sþùW=ÅæY¸ÛfÖ°¨»ZãlDa$¤×¢ìZëp¹­”1„³òHA!©ÚÑ$î3ÑÓ+wÄÀÓ±ß`?g1öyÏÁ×þ¿ÈÙ֌ݛ í3…Ïu7VÁ79¡;Îòàï1ÎÚFã_9/³f4ØÑ!!¸‰¬b ƒ [‹zuEçì ¾ñÈ|z»t‰×wá4´Ufxé`H )…¸.ßxc5÷|2ê_W½ ÌI£ ,rŽ’ï$ˆ¿çÝüÕÁhAF.CD [€€3!åÇbŠ#XÈíÐè/âä, AìÂ8BãöCø9Á|!H,!—8ÝhKM,¤ÉùW«z²Ë_ ít’¯H£Ô@  úù^/ó9»i˜‚àž •ÜT=”'rí‡í£Hàú:¾{Cœ›†ƒBÓ9¼|¢à©Î ¾:À&–Ó'yŽðÐ;$YHï #vr/Åp³ Èéñ¨_½úú3Y3ýnuÜ´ˆB"¨X²éqÈÇb•ÜúÀ<¹Ã¶t®•3Ř}Þ_ZX¢¹~z®ÅøØá…«ƈ˜Ì‡¸€‡ä†‘÷Æ2ãð{ È`= F™FK‰«¶ã¡¿?ÈÃù2&#GßûºæÉ¸Ï5.“ÑC2¦V| 8l8GoPÙîPªhЩº3 ?äuWÆÓ| DŒ¼å³ÂëB ¿°Z€RV­+›Î€ÿ÷ƧOÛgãHåÞrVÈÎåiYüŠñ´ŒQË«¶ØU[„ÏMœ<õ…|.$îá‰~õÛå¼`»üõá­¸’\>ùb0N{xëú— •7Á}Ï]8¾˜‡ÌÌß™2Þã¡qÝéã"¢"™¦O^xg-”•_žÁ¬å´Úz¡?>•ÜhâžÑ¬Ì}TÁ0ó!§6,ˆ:l¬z·<´%»¨ãã¾2#×ÉÆ­ìéa îã9(«ø–ªòîšYdaùþ¡o~;wã"RÀír{éœÒ<¸½ÀûIrÓÏmÁDÖ÷²˜Ò³þjhŸ·3z)íÞïÏÆW©~äž¶gTsáý¥Uÿ*^]킵'ŒöÉ4ðT×7G§–];0ëÛÿ‘#侌‰3>E»ÏDlëuÃæw´—Mµ&ÊCa›™ÍÙ¨{°:[ýo…²à[-Êu¨žwùMþ‡]7s ¨ÕMC}]›œDÇsŤX‡ôž1®¸~çs³/7ÙÔ43½FAפºÊÔn4¿.·…“/¾[D‡§ÒðéúN1Ú•Ü#˜5Ó¨4þLlWø/b‡ÊvÅ_ñ˜cÕ•\[²ÿ©ÕíK70í›?-/Œ³D÷ƒ(@1œAš@@Žó¼ôŠ5[m6±Ý?·sÞÎ;Uwûô3¿^Tßë>Á+¹v{Í㪲³z µ³ó‹µ=.'~{çdż~öw„@pP’YV¼Ÿs³äõ[Ô5&Dl2R¹% Ì›¨RI‹wø_æcËFÎT¿¨ÉÔkëvqTfl™úŸZ N÷cÝè"ñ›’‡NÙà²${±ÓOöлûg^Šƒ>3º®_OÜçœZ¶Ôë´LÒW˜Á±VôÊ•ûH5OÏãQiLMÌ~d¥,;¿M~.‹cÌYæNgÙ>L8[ŸñXÕùø Rv§Ó-l¦ËËûå×Îüù4ÜÔŽ†ïÓŸ¸ Ý}\^:,?Á’ErY¬øÊ^݆ƴårik¯ÃÕOªŸlÃyueîÿqÒÓô0soÐ ·ÐRbЧ2wuë—³þqãæ­&)9Xž?Ü´dFT ÷Ã1ƒ}oÙó—„y_L«îúOæn¹¬¥MìïwÙè?»ã(S$¬´]œõŸ¹Ö¡U ·EÛC|iÐÖ‚d~õEÎZW%x÷-îæ8Õæ~SÛÍ¥ïØG?PUýâ|º}_Gô]•¿NÏÕ…øó®1Ú5 ::N¾'óYrŸÁ5±ˆFö|ùµÈmïšýÆOí]WÉøÊ†Ù¼éŠçèdö±iÉÌÕR|7:l¢’··‹mËmx€£Êvªìèòwh,Iȯ7ŸŽfo{S+ú™¶A×n*e¡TÔ>K˜Î]¹Ÿà¸ÎCÓh*vë)Í›—ƒ8 Šæx•G%ó¦å1¡ÕüS[ ̾S:ä—d4%bPj´ÕÖt '+`êŸÆÀ›gÍþt½½*ñt9=§ ™%Û®÷è™1YÊäÔï:ô§ÇϤ˜Õu|íeE'rõ5ªªÔyøîuŠÖ« )v‹=ÝîÕzÜÕMs’w:Ä[›‡×ö½U¶­ðÞÀm¼°œ¾L”u1¼î×–dæ}÷_i(öPèåÙr]ZoòÉðßyWûÆÄìu†ø ›%,"Ê¿§y•uT‹¹ŽÖ`NýwYY>NoÔöײpßÓ-¦ÊGÑ“ÀôÀ–e/–½»¤¡†agÐz;Ëÿ4M5×1—Å`Õµ…kù2ö]3«àßÊŸÚe5g_Úu†´O0aÏØ|ô‰ždtÏ‹§KÑŸáT±*lû•ý)0õ–}*Øgê]–ï/!Ûã1ýE‹·«q£æ*±ªg«â’u ZÏÄB}dÏSŽËŠ}Í?¼uâJ×éç4g?|½’Ú‹2*Vð¢ t;žk?q1;ÚôýÖ/S±¾@Äo°ÈBï'X$"øâœ[q¥’e$ür-È)“Á¡ .H•FE%H$®_ÇJÝ>Ïî›72sß°ãû5|Ôq[ÍSˆÌKt<Ïß{﬌WÉꃉîÿ¶Eµ?)dö[üý†dsoJRß[ô^ë¾U$sèÒ,ô .˘¯]0€OÁ ü˜Ò]·½•Ø7=§WòŒ^ź%ýW.¶VîSl¼O|«‚K"± ǰë§\±ç#o]$Û #Q0㢨g¹˜* 1r=|†ÝÕṲ~…­ñÿ1ÌÔ¢›µï‰sNÝ®´ùs}Ð;;,ÇŸ¸dSLôNÇIø.W!öùN Ï-;öqÁ’nòïœ{ögÐ¥_»ÛuÐ~t=•›'À¥Ù˜M^ÖóÔšü1UÙ%ÏUv°7|Y=Í ¾ö){îÙ§3g@­¹SÖ<­Âòû‹Úšï‚ïŸ ±¸?ävÄŒMɧ¥ïñâ&ý®G úBo‡ r‘ûa<ðÑí¹–lŠ^kUŒãÏ_‚ùú|/$¬k Ï+ûû×vîÏøß}Î%º`&€sè!|‰yí¹²ÖžñoÙr·oÎÒ¤k|žä­íjœ­1Z?7J“Ló½ÈtåT';Ô”‹MÁj¾Pæ°þ —ô¿6‹®òÏ»X…ÚÄÀ*I±ëª¥áåêë¢ó¼8:–óŸà¸ ›¾÷R†cg¥RÉ¥ð×þ0úuÜ)ÝnÊó‰˜Ô¼Õ­GOùÐï’z+‡›ïíÙ{Ö|…DŒs®6™B÷¶ðó‰ßQr?ý§ØÒ£òNe O/zÚ :÷ HÃðY[èrµ½ž¹¼ò'o郜:æIemn‰)†£ ûgänvšO­~’§mÈÔSjÁPD Ì+ÀA=£·­†WÄd,ºóe»Èÿ¤¨í5KU=†ºJè# ‡íéñ˜›¹|‹ÛÕx®Ê¾êEòŠ­y×E‡•Ãó¸ˆÎë>§—dÝ»WÚö¸Vt\ÛŒñk_gÛéDS¾B­‹Äo›ûï1ÉS³øH¬?:XcêuîØM^™ß"“ïϺ„Ôð³DræP~buïë™_‹‚òHgÛ5î³®¥âϸ÷[Íe?a…ôAò?p.âΚÚý]ªŽÙö‚Oä¦Ý–𒵓à•{w”tEhò¶D¾Ol. ßR6ø±šz/²Ms§½å “¹”sЄ^?ªYïwx{såÛ¬];M#1w™lÄd½ÇQÁ-иTsw+¸cÐ[‹ÂÖrÒlxZR5óÐ(lýåƒ×/È/Ó\æš7‘KØëñ^0?Íu¨v]¿ƒÐ›þíФjò=UNX¬è»/…§ ˃EÂY»ñq k<É fMqûaÐjƒtµºß°í¬PlùŸdÈ&º;yÄÎR»Ü®²’Ý÷{Oé »³WÚs °e g¾}kv– u[Z¯Wç¾Üpyð mÙª‹d^ÍÚßÖŠ=MƒuèãšÏÑãG_~ sŠ?ÃäZc³)¡Þ´€>Dðq…3rû„§wç¯ùëÞsÞ]Vù6üôšh^ÿ>‡Hc˜¥!‰¬ª· Xì¾~9÷TlÍZØL忇L¦ñ YÊýqPÕýüÛ¯ã[zÎê¡ß´gï}ë®t‰o‰Ðè%ñ,v²„ò-Îý¥'oX²cµª[¼xzÚ׿/ã·©Aµ¹Î{Î À4Ëæ×Ÿ¹{Û×9Ôs~wY^Ÿ+ÛVÓ²y™Å°‚$­SKïæ¢Ù78ñ¼«ï£½ÿláî·¡â÷Vf{=p.ŠëZ]/_k’«ÌÝÿsÜžâ-^•ÚèO¯%k×Ðlßs¤Fƒ šðÂpÛ}5ɺ0†ÌËŒ¡…šž÷ ŒBgãK@º&Ds”UwõX³gÃZÓŽóµsCþúë ã~Ža§Vn¼]ânöÇmDd@@# xK>¹¿z£Qòvc—=²ö7 ¯<¥²ù8×ZzY1ª4~3¡ºÝk9'ª7u|ÆðnLÉ‹Ö *;Тàwh½z?&Ÿf• JûÔÌÛüç0”•CZñoW9䟃Õü;Ÿ¬éïä³Ã‚ës Ï“''hÎpܧ{ï¢}èZ%s½ùÿušTÙ88ˆT)ž–ºŠ; æ™¯µAO€³¸´ïÙ™…˜fù€Õ+³æ~ñ0ï³,!Nõö’:xž&< û­'½Ó9ë¦xK#s-…ÓÕž–;|Zçåó~G$è/ÉZ#Y¦ÂPóè¹0KÿˆÚIR´Åp#j:pPÎ-§|ùÖÄÄö ~í>ɦ-þ»‚«ˆmË+o‡1æž[áÆl+¦µgÄŸž,ÅÏF¿öïiy˨mLºÌß2/hYÑsçúHˆvzˆ+›*S×iá¿¥´ãòëó[oZ»Í¨ó¥nx¹»»]ñÕºÿne çGgÕâ+9'á­ÑxÓ,b¹u ]dWBh3þ]õ ðÿÞ/§n¦’æùa?Y•òóʬAïš i”î›vö÷5DZ=•u%,gÚxÄëúTƒØBx´ö;ÏZÏýQY»TK¸Ùá¨f>WÔùðp–˜n ÏÀ=iæë:½mä ¾Ë[æš$zׄÈ_ŽJÛ5µ–} ®Žª’žÝñA£½ÿŽ’áø×Sóã—öôiµ-¡ÜÇÞÄ]Z<«@CÕøpyÕ >áöžfÛ9«zÕJ|çgwPNš„íÿO½ÈÕ§k`«´õ?„†]ç8QÔnMýp*«w~*>ÏÔÛ¨ˆ€Ž¼ÑB õí‘»“˜ìØfc[z²ùÉŒ¸¡Dv'ì–÷po«PÈu.¡²¦[×yž­z¶kàìã³i2KÓq*1ºÚäLYí?"o†±7/èAßøv=ÂcV÷½¢ª=×_„êµ°ÝÔù#&áÑ€·É–kÖö Õ¬Úý<×ùO¿TÑd¸c˵åãî2þ>ÏÝÐ#!åQ™f+¯iíØ¯¿½:h2±/û tÿé&¥’ß‘0á«OÏ’ÛfÇ©úÛRk)Y<èÕŒyâ0ší¹ö^CFõÍ,ñ3b—Y¥NÉ/ÏÊám¡9[–MŒ×x*Râ´½(]ó Âç:k„crx gQè»GCm~[/Vÿ«ä]âÙDÖáØÐéÜ _ˆÊÅWÿ\3`A“Ý9QH^Þb•w!NÏ‹qo¸ãœÌhÒºx­sºÞ¤ÂTŸ&‰¦ŽÂdö!K³õ{ '^ŠJº› ÿé3:õh¥œá|'ÍÒC#Öú| ]‰­L÷]fZ¯¹Îç^­µ}Wb޽Ù\6m|_?¼„¤š‰º%g'俽:qkïj±›R™‡fu¡úï» >‚õ=´Ç$FÊ ߤIžVLJa¶ÙÙ¥9åî:kZi^Á»«ï6cÓ6«?³êfð"! óž*áLÉvå%"ºÅìÉg„ }\É ÄZ·Ê¬òdýoÕ6ÙÛà¤-kƒÄÎfJþ&"çÅñBÂçKepìD×Òÿ‘Ÿq´ô FáºûÝ&׫´ýý«“©¢™ìËoåŸØ{¨j(*õÖ˜"ÿ¶Þ»˜W£¯Ü$Nh9&5 ½%=-¯;;Šý#ËèJÔ¦uÌô@c¾åjÉOÌW šM“&z™øÿ Šòƒ™ÂµîÁ+.õ’”â’á‘ PøyË¡Ç|ø-ßÚgý0~‡¾ž»ìÕÐxÐjõÛJò¢¿£@‰Àéß«Oß×¶$V¿Äq.^pfá›Ó5R¦\([k]æµßËuݧCõ²„½GTšïß©±ïútÞ¦)0ûbàôRácŠÍÆz¯ÂiA³ÑÈeƒžCiFáàp2ây^–£Å¾ö|Öy§¾)ÑÒŒ$f ;ɸvOWéÒã_܆È«u3=³f¿Æâ¾ª¦©xÓV[-n}eŸëCäÝûõ©öÌMX¿ñ1O9›?'øürÑkWØš¬TÉ %>·Óå©U8-©æµ| C&v×å¬ìþÑuªlÊ•’÷6NJ†œ¤c§3¯Õn8;žùŒ¹CÒ k·~®kßoï]¹÷t(|;èO²ïw­¾š¨x‹Ãšã2íu`a]Y—YšÈ ôíÞ‹ÍÍV̽ÙÌç g}¼u=N{÷ƒ¼ÿ“Ÿã-Ä© È™‹}×.þ{éê½p9Äöc~ǾT|ʇ_~3F»Q+›-ÜÜ©ßAKL^èÞ¸ÙŒ.p뜶^þgqa}óÙ\¥‘¨†Úý&˦ئ'J/Å6áêõ¼ú-…¦/£%¾5¦“ó àdóøNŒëªÛ_7EwVãEÆ{_—ÎûAYh3½E’Ë)7Wµ¾´Kk‹‹ 7ún×ñFàr)Ob›°1ÉÏ><ôEqý¿ñ`Öï)¨’ü'g £Cïw{Ú,,× gìá:7³€Þù¼ÎhAG©ë¹Í×ฆ¨Ê4M?j1ÓÕÆæ{q8|'ÏÖ/µ‹š_Á?¨Úz—«·4]¤îÃæk£ÏƒyDýAÂ~ÿz}VƒZüqT㯹ÅW³r®‰jÑ"oí´Sÿ Vüþ-L>¹AûLñ}¹S˜±x²‘éðn>5d¥eOµõÜg‡µ‘xâ<î/raªç/™»L¿dÂ-Üqé*Y¿×μB:Ni=ÊÿñÎr× ÖÚE[4á?Æú)T1|çú½— Ÿå†îË\oCŒÏ±—ZW7:ÏWR²i»Ù…„냋®C \€KŸ¾I†bhæ6ë7Û—ô]æÊ}N{?‹|â7¡[ï®E’9 ¯¥ÍNéï% Çù{ ÅùEòM=3nó–'Û²`þö¿lE;ßßykë|š¤¾ái©©œì8·ÌR«]Ï7ƒéòÖÝl;\ü&9z¹/œkzÐR|¡/æs-+õnékTл©÷çp=ßö 'HÝÆòQÝòE/]UOUðü½Cò÷Øo ^}Æ/ÉœÝd§73™a®Äú¥î–Ñ÷6\e/+rŽY< ¾´K)Mc±…­1»ÚdΪA´\ƒ‹$»W‘ž¥Røú]#l™aûüxf¯âfÑfZSLnýq7£›Jf±§¿¬±lÓ-„w 54ÿ¹ò%ñ#íÖ=¤ó²p;¿Üô.Ž3~ý ²‡¨‚ìܨeñ5øî®^'/«k×óúž©þ;x ¦ÏKÛúÓx»š }ŽöNÏü·y…Ú—ŒÑ§pg>ïKÓœw¬¦ºÏÆæÍO–óïO˯¡Îå¶w–’ðÕóš±ø×{vÏÞiItÊA¢ß›gÙLè:ßôOŽoвkêÏ"_ìK5ù¯©ÉY>i'GÙAUänÕC”¬zÓ|¯E[=Íä˜HùÓ9u9[~5îÓgîKîÿ_Þx-Mã?UŸ¢jÜÐXð'9‹>֪˫ĸ™¾?«‹¤ërQo Þ2ùÖeéW5Kº¬÷§µþø}@Üó½\M—·ªÞø{¡ªr¿¦ƒD{øùœX¼Õ|œŒºý ÏZ¹¹ƒþøc®•\ݯ ýÊûÑ1q‰°ÎÁx›MG“±Ð¥©›}ü}|‘›FéÞöo2m]Ôs²]a—óMÑñýù.íÖ“K¿^‹P»eIRµ­UòÓwôz­qî3÷ÛÜZ^³X”?iÇïe«Þ³®?©Ú3mù™ü>¾Ÿ1~ñØò¨9w’6æ6qˆÊí¯cåK@ÿ#ñJT$èw³Ý xö³U]Η;»ÄüËA.ø´’­ÿ>íãn— ZüãÅô|!”D¼ì ÈÿË÷“•JÁÅœ·§´CÒJS¤óï›zÆÚãQï| Iqq'ÆAd’€PˆšòùŠ É2šÎHµ˜è$=çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ k{Âe„/·Aw¢P(R€áÌ÷›¾oze{²êÃ×EPt{àòvøªuSèW¶õœÑ­ÜÂïX=IT€OZí¼l³Ýîh@1Ê¡­¦öt¨*IE@ÛàøÀ÷Ø5ÜÁ‘¸½á! À¹ê_Q¡‘K«éó¾àPz{ãÎ:ÛA@˜»ç\mÓ”µ•è ”y‡@ûî> °Ö@=ïû6PôâêNña†‚ƒ#B¼ë´—¾¼€Û}æîûÑngUÏ{¼ƒŸ6ñ>»¥ÉÙÝ—Ó£v$l±°Ä¬²Ó6´ÛªÉ=óo«RTÛ65ª­‰›.ÊtÞÇ{sîâ¤é¶h&ÔÓ§T=}²ç§uÃM4¡§B½}û軌65ª©ªë/‘éäÞë•ÖíXìÚÕò;Ú/¹Çd+è:êw|ó)÷Ýò4ËÜï|ù÷Û&¦úÝv¶ÛnÞ|ùðˆùqyß=æêû¸ÙõÞµ ¨€1z„B£Cè\±éí­{a•fÚ­R ` p8Å Ò+cÐn`2ÐPIZ]Òë vÀ¡ ë 8î9dRIÛH@y0cÁõUï7{žú ð|žëßέè;+îë6ZΛۛ¶3Å6ÃÜ®¥÷Ÿ@.Ç—®K£{:è(€[×:É›Œê³ìéÕ÷{½²w]u͵jê÷;ÇžÛiz«Öz^ö Éî{{Ô¼ÛÛÇ ¼«ÞW£³Ù²ÇݸÜhsYëpÕ%¶ÅºËÐa{.Ývð çlúßcÝ•ic6†µz3˜ (dìë¥U‡Û(ÜàúyÌ–ƒY ¶ÐWÛº^¾÷y÷×^åꙤ²kkDh¢½šu•AImZMRm¾±ë 2µFÚ£EžÅ«[kg¯{èû°{±46ß6ØÀëÝ«mkP•µôåÚ!«` ·Ý÷Ð}$ú ;w=w™ë­Ïby°@)6ØÖ»_q¾P/bã_wžc—T‚PÙlì:‘8îÒ]ò9µm¬Õ‡VuÒvÜÛï¶WIôßg{ä>ôonnß[Û€"D€ ‚0L&`dÉ€†Œ šb4Âi¦hi‰¦€È 4122›@i¦™‚P@ š4È&!‘0˜š )€§„É2Iš‘éSÑ©²0LLSÆJy=Æ24¤Ò<£#OSÑ=L™©¦‡¦ˆôÔdôõG¤i b„  §£BSòOSjf„ÉêžHÙ&‡”õPÐØšƒ#&€ €hÑ4ГI! ¦š ¡ Ñ©£=h§ú©³Tý0šeOi= ¥SÄôÒž¦õM”òGµF€õ=CÔõ=6ÐÙAêFÔ4hÚšÐhÙFI"hbÉd&™00L™4F€M3DÁ04™014ÒŸˆÉˆhÓ&Ð2M¢z™22z†Ì“jz ‰ M@€€M©¤ÍIè›j§²jzIå0›QèÔzš4ÓM”h6¡êiú Ôƒ ÚšmM ÐÐi@“C@hÈ hÐQ ÈEèÿÁîèxtEUgÙ‚™j Ñщ›ÃÔfêtMh¨4ã(l¹2ºëqó¿Þøÿ{±æéÿr½ÍŠ•AD•ìD·,FÒæQR¦\•(¸™ŸÊûp ?—$ƒfoDvÞfa~\BÎAª;m #Œ* ªÚÂвڣÊ ÌŽUÚ6,ª4l£(¢£REY#öñ?wûÁûEùÑu ntIÑRH×Üõš»Iºî0˜¶*‹ÊIDª¢Ð}mÚuþƒqßá1ø~“ÊÎR·’Ófæ-é›{š… G9\*òOPKò?m8„GEŽüõ üpÔp XàÈ…)‘Îô/þÛ­c 7?#ÉØã÷¤¸ ©Åf<°Þ6æJ6Úã™ß,ÉâÒ}ÁÐûÊöôu?ÁO·œ„f¼$0ÎçBôFÒ7ÊAf)rؘ·û9 „„-Õ…Ê(6×eÃ3*Ãc2Üʹ˜¶ÑµDm«”£ jå*QkaPT* \Œ`B)¡Q$##Ù‘ûPЂ ùX+ëàù1}¤{ˆ<ìWQSìûú¿‚¾óû)E>u⢜ÔåGÒÁ¢´ *Œú~›ÿÖî4/ÿ_»zç~wßüëƒG™£ú§'_·ücÝþucçRmt+ÇÅ?mˆCÖù›Þð !ÍþWÅÜU¿-»Ï[â’-ȳ_Ø©“…Ë‘(9*ˆ4eL‡R•YšTg&ÌÑ,‚‹¶&³.•VQG&¦¦î››¹6íªœR°œd]âÌ».Î\Í‹9uƒ ¶­ƒòÿŒælf‰ÇÀ¼ó5Sñ¿ÞÙ÷<0—©âU”ŒÍOÕ&IòrÄOï¿¥@Xy€F{Yiåé==º¨ØþpïãÞC?ºÄkÜû€B0!t ø„U—TÈGÀ04|UÈ Èh_:Cî -5›{k(My»"‰Gÿ¼…“õ½UØ[…Dø3å~–‡Å¸ÜÇÊý®O{v_Í¢D‡’ƒK:o™bÄblüûãtÅ¥©PYÊÏáüª.C¼”í)­×Ä«BO_ç~ýËí¨÷ñ*Ùþ G$s¯¸àp2Z¸áZä:6Nø„@Ü=&;""•Ç…œˆ€Z Y«’D,Ÿîì%n‰ˆ[±‚‘q@„KVYá€8.ÄÜâY÷Ã.–‡~çiDëcú½Þ¹ñ£4OïýZ9¯»ÐØÿŸ@ziÿ_uG-ëëð†…Ï\{±€aÌjjýóB£ÁTÄgùÈ*ëK0ñmŽ9ã}Ž\œî‰uý#—@¤þ‘v§”i /¥¥¹C.@Î)‰=æhGã›CdlòWö{S#…Ö’%²% G >¹fkqåY=åÆ0˜òÉÿˆ€jšŽR`uû#åGwR²RóÙö!Çûææ¯üT}ð ûã÷mÖn)¾ŸGcm<‘Ã(…™ ˜ŠoÅ)ýÚùŸä:½Žw¹aÓð:¥‘?*e›þ1µ@ˆV6©< ŒoœNÊö¼¡ÿmܼ;éwlF '±HüãýóOrw0üu¥#!NÜ^Æéñìa”HG+oë× %åÕœµÞçmM}ßsx.ÃÌ÷ÊjçsÇGÕõ{|ï¯ÔúnªõGVñöŸþöžïMÀB®Fz}>¬€˜EOƒöââðO*|YáÕî­` …Â_:$¢I¥ò §Í£gc³!7ºÌ”¥Bó{Ïfù»¬JúÚZºè>O…ñO©2åÌ»ºTZ7눼0„0 ±†q„!:#«é.TΔåx]º›³/OÓº^s¾RÃÊrÅU¸gï“8*+Ó±À@!n„!BÁ a§ÈdLnßCø=¹‘åsó_»ò^ý{ {¼T³Âï¬'©üî¯;ém0*»ÜŸFʉÍ ~©Ó.§ÁànÍEâÁ¸»ÚˆzÊ”Kþµ™~Îâäý'x›ošvÙ4iê|§?zû”í½kùâ ÇTdoÔ!0Aó¨õÑ…¹h·4ÿ[if]üïÒ£[˜˜0†ì*oªO£-Oìµ`»‹«wu×]WSn·s£÷þßÀèËüÿÿ¼¿ôÿaèW·X–07ÔçÑíõT¦S°añÏŸ‚Âmð‘`3 XA€BCêý>J=í¤‡jé„—~%:< çK]L°„ =,‚gU%`]µ¤9…íå¢mIºÙ±3Ek.]Ö'ûnwmKŒäf›sðÅøí×É^¹7Úô>=ü±_yÅ1ü½#ǘßUòâÖ¯3ŽÑçEôß2R¾þüÊÒµ.ûÞhïyQXÌ+à\f¿Ne8yš™k0vÊ9' ÂM>¤öŒ"_~nãáÞ+éO¼ßtfÝic瘲ïZNz¨Ür©¹BŸ€<01ý©Ü½]c„&pƼkÖmŠvî²^ú¢ ¡µ ­þÒ&ì'“ŽzúÿíE'–ä+%0Í_Z³œŸ½Òó¾ž1x%øã/‡¤£ëЧ7òø•Pn&©Ú‰"‰î &ÚcCü†t’£JûydÂvÑŽ†Ÿçþi3³– ˜;`îsbÖ(¹\ú“`crá%‘«?Œ€„ àÀÃ.Œ¨DåD8A˜óž‘q.œs˜wyÚéOoå;¸—ó|æ Š—UŸ¤U?0tÖ¶OŠA)1® ²¢ szðàu5^Ô¨‡ø³5œþ‚e¿R„3»5‰>£ÔøFPÑÜUz}‰³'ã“0œk¾1á8r/øÑÝ*eo0YñAÊö¿Ä{w˜Šaå¯ÂùA°$º¢„C­R±Œ_‡"7¦ÈÀ¸˜bM}×Ngn7úþOÉñŸhþH§… Öÿä¸>“ð”‘H$?ߺZ`íÄB´Æ€-ŠÞrÙÊé‚„GÛ“öAHÃg¿dI$šIDå„ô‘u#˜åY󶏨ƒ¶ùÁ]>ØIx†ã-þO>FPùKv†_uÔJìR3Œ¬Wo¶É-u;¸éW\ö}?¬åà m¿Sv- `ÒÃܽ$¯¹È#0ºf— É h“ì.±œlCy$”œn·óÈÆý'6²ð w—fwþn'‚¾‡ÝÀÊì½Ê™UùöÊPunçºÇ5)hïaV¥€RoM…[̉•Cò€Boô¯÷í¬úàIuiý·AöŸ%åœëùµ¯Šìïÿz×/Ê͢ݾýöW¹ãv\9áò–xÓbÜÆWÆYs¢'B "aNjt!XŸJ…D ŠÑî ã_ŽÏÚtÜdç%”ÑQ‹#TQFI$XÐXEB² °©¢‹ ‚¢‚HHš›x|>ˆœ¡‡~yàC w(NPvT’ìÒ¾µ«ó[Eßb-â~×îÉþP®»¿èß6÷:#¿ ŸéRÛ·1)³œ‚„”š£ìdV<šáU2Lq÷gaåÓuôçõµã*’Òà»fÌ5‘%Q‚Œ €|þ„¤ O2oˆŒQcŠØ‡,‡KŽy®þ”ÎÕázÆÀ<ùмˆù t¨¼¯BÀDG–›…Ö¢è) HÄ@ÅAw™všW>:ßdس¤zQ ½Í“êß;ž¾ËÀÅœõ $W¬û)É^©ŸÊÕ%¿i5T•Op±òÚ9KÓé¥Ê‚ÄOc¯lò†»QË᪃Î7ïãÕp—Îøòý¼f¯ƒ ¼7¸¾´sÏúVÙ55eèSл%g(ŒUbŒR(¢¢È°ô²Å3nÉÕþÛsñ\0¯î¾†·ÜÏó\y3Jlû<¬zlÉ?ä6½ÑÇ¢Eéêr…»ömÍÓʿج¸bš'÷;¹ëÍ)tX/Ž"ß ‡&:óé>÷…•öª7MÌ7–ÐÎÏ)å¤cpÞÌnìÃ)ŽlÐŒîÍs‡nT܈xUPYäB¢Xíöw¼Œ"H¨ŠIôâ(( RH"²) H I=©ŽêC/émó{’„Œ”@ãní²û½Å7Ã]^‘2¦à@7h‹èÁ±`$Ì"!ݧ‘::éJ .{у3ëïP=>ð›[ìõÑ<.…F™¨*¤‘njïþ|.߈a=vfò(V Á×/!%¤%\ JÎOWZÆ™È4¸”H/wõÛᇖ9?a5ZµŒp¡n‡tZŒaß!¬‡Iˆ '/‘Mu‡@#*…>üÊ1/t¶xh‹p"ª"*œ¯bÏf šByNKOiàS´ú~JkÛ°vŽá”éòX÷Î|áÍrE$+Ë+ãhgu'Ýjý&]ÚÀûÇÁû§Ä@=„½Ù«¯ÀH^ƒÑŸwùõé»Nœïû‹žîIA–I_­J ËC¼ãX§ÌC¿%œxXdQÐXTCÆã(«vÐHqƒ¿ƒ|º´9LH ૚Ê>Òwc8ñ`_oŒ &E“2ƒŠ&*Ñzø´Æ€©Ÿ¡Òd&;17CÎnÛ韖D)X‡‚6¼,…ÑšIu²”euŒ+¤­s—ßykŠ ¨Ÿ-S× Q#ÄvÎ{ªÐCʾ)ûg~ÎM~gÖ¢×C’§uÝí ™~©ÎUYl¯,?ÊÒÓó{p âªt"^T¸Ø`r9ç÷Åd6lÙ³fÍ›4›6Q³fÍ›6l˳eG*T©R¥H•*T©¥J•*@©R¥J‘*T©QÊ•*T©REJ•©R¥J•*L©QJ•*T©R¥J •*T©R¥J•&; ”lÙ³fÍ›86CfÍ›6lÙ³FÍŒT©R¥J•$T©QÊ•*T©R%J•*@©R¥J*T©R¤J•*Tr¥J•*T‘R¥F*T©R¥J“*TR¥J•*T©R…B¦Í›6lÙ³fÌŽÃfË6lÙ³gÈl©R¥J•*L©QŠ•*T©R¤Š•*9R¥J•*D©R¥H*T©RJ•*T‰R¥JŽT©R¥J’*T¨ÅJ•*T©ReJŠTÙ³fÍ›6pl6lÙ³fÍ›6lÀì6l©¥J•*P¨¥J•*T©R¤Ê•©R¥J•*H©R£•*T©R¤J•*TR¥J• T©R¥H•*T¨åJ•*T©"¥JŒT©R¥J•&T¨¥J•*T©R¥ …J•*TÙ³fÍ—M†Í›6`Ùƒ 0lٲɳfÍ›6dÙ³e&Í›6lÙ³FÍ‘6l©R¥J•(U¥J•*T©R¥E»«à[øAý}<>]]u»À îp÷=¿ ç7­…9Å„ö¿™j¢«3{^²æu5T, GôøûŸãxþUAWàc77ã °ÐèXƒ»Ï%¹XV|¾B$šGÔb T\ã·&K”÷x{š²ùU’6?ιù±AOí¬—’>nZ€é¡ßûØA†‘·òøôÈm»¹T*¡Î™•÷²Î^½´ü´@Dý”§òyÿ›öõª¥—³ä2eü‡Wc¸zjñËáéhxçê\9Ò²Ä:T>ƒ–}=¶i—Í ‰w~g±²5=µ¹ææªÄ!E+JEÌ(lçoRˆi íŽ ²ìaÛ ¾E…Š! ín¶i+`ü—î!@UŸdIîÚìx³Ò ‚$4âÍŽêNv~8D»™£“£Ô6½¡¾:&õC÷—Q ²S}øìæÜËCݳð¯'Š!ºòjèÊEHÃ>jÁê8”—Ÿ Ë]Þ/×3]}a+˜ÔÔÜàÜC^HlB4†GtþÉyâqüï0Ì®|c–·ù1¬ìH¥20J¯|W“ö/Ócg"o±bü÷–§‘¡Ÿ_eùÔ5Sb †Ø Ùïòá[¬»@UE_ß?4$æRu¯ ›KðœÃlö]§”Áä‚uŠWñ’šÙ™Dü[%TçS¡Kþ¯Nݰß+)05jßI«½oŒ±`ìBÐíæÂPItVèéeÍ ñ#53“ 7œs‰8Á·ÝíÜËuwç§Sù·ß–u…ù.¼)¶©9Îê/W4ÄüÈÄds‘ÌŒN€s!ÄTlQˆèŸ>xì q/÷HtO<™  ÃGdŒ·wÅåQgT)ä¿ìÞ´ÕŸrîÐÃ|å9&Œw>´‰y¨¨*9•/"3(OÉŒÁdò•ïÞ?ŒCýeÌÐ÷¨žG¡L§‚›«§ØázåmÞST$O¾E{·<¿ñî;ü'²OFoר]ÉÇú Úfqú!8lT(BÕ4dv s&gÎÜðTy’œ¼jüR;·¹üØj¡—'„ÏÍÈp|¾Jh¢øT9^0šˆìFКsP·0Ž¿ˆ«këY¹>VAâ¸,x îQ0©i»6,”Òf(½LúÍ8‰7(ÛíJ²–ÞTÙÃ.—‹µÕMøº¬äíºæ›ûy_¶ Ç\įC >N®úúoVc\z‡=V èƒÁÜd ‡ª–â–N`ˆgToôÅpQ“Â9WNy~ÉšGe3VH ð^mÙ¹±{zgð³n¸ýê\öPµÜó ³tçûš¥®õYÔåë åûŒ¾7X\õ R&×å@‡jïš@þ[” ‰`ïö':ÊLííÚ¸£jµx&}j#Õ1½òé à%ùÎÚ8O¨žÈ|'É>OÒÅú“š<7¯í Ÿ¼ ‰™jÏ>}Ö Kó¶!¨šþøº_Ì„7{pû›³çtdöªÐdøQ8?o܇ìÒ;€@`MIóÔê­yLz–XêÉ>[¬€õÿÒø?e*îFrYÄX[U_Öüº6¿{‡óq€ôY‹U&µ÷(ÎEóõÐäU À\öy6‹&ÞµìxW¼íú”Œ¹›ñ?ê¨ÖUJÛ?)õòv~Þ¿;V!\Ô|ÓÛ¤Oì¸o¾ãû÷(òu:´ˆÅYŠ]e ±°pÙ_H›’3í°]4«¬â.IÖ«ËSI­H"ƒo˜-åüÒŠ,Èõ˜²—}K®^s(6vbû¯YïFhï´`§íòF>­á¹þ=ÿŸ‚0ÄÒ!~²æGW´Èä±SÓ$ ¹ù1¾¨ä¼“V¹8­RL ]ÓÍ©.*¦Z“”rœºZç=•£´f,9†ò%”RY‹Ýk´Àîq£ä*6e[Gt~*§Ó—üs‰B“è–äL[„çgöE³10Çp&é±[æcÎy:9ïXIÓ{uïñYQºéÇüÎ7à¹Ã‘íwúë£Çl¶ˆ!ÐîgJE–÷‚RÛ÷á—…’Ò8ë‘jlFµ/»”²£õH0òÏZ?”. -LvÊæÐq ÈÚá!úU«_gVц{ÔÌñ°/wŒ~»pq2.ÖÐÈàc2tdÝú¿Lq™áNSÞâ¼²p(*7HÛT1ù¤f†Ç"â†uœcÞe’Ϲä<7Ú÷|Ö”3[Æ£¨è)j'­W9èÕþuü$ vÃîS@¿k^›PTA•%+¸,óå m3gcoe2Ž·iolê¤4¶úh³÷«)„¬oTÕ–îz+YUˆ¿¼¬¼¢o¨ ;Ì#®ÊÌ×¼oss)ƒ§I]®-ƒ÷Èïô• ŒÀs€¼lM7‚Š8Ô®Üí¹ÿŒÛ;Hÿ6ÜèTü©kØÄnºí9òÁÆfCß’Ž”ÚÈñ¸"]1#ÊDMãpSŽJ¥-ÊÇ,-6:ž-+™ía2ò!rVOÛ9»×Ïöí^ÂÁPD"{WÏǯ+¸‹ã››ÙœÅö˜¸ Z9òeökõ…[¦cÇ0صp1£àþ»‘Á·æ0åŽun“ÿ;ù==1Åÿ#8Ï×c6Ûó}$C€jvÔS¦ÄTÁKRÎæQÓ† D Ä‘_ûNŒÜAjf\{²Õ8ÆDÉ+¬6–1óªÈp/Qh²~Dмªf¬ûQ¤R”~¾iUÊæÔƒïq„ˆçmÿzZò…‡´-ôës —1³¥&‹·—ÎBÈÄðßï,gøs¯*–¤¬gÓ’ãðAEŒÆ¶U,]åØë×Fr=uûᘦ y¯˜ ~ˆø ¡…ŸßcLúN}N6&¾©(.­_ú*TÙ.¢ô”*ôorÝp•؈±¢)œÞîÒè Y}£¶Ù[¾–‚£~§WÂä¤Òô¸™³™T{ÞxšZ4¼]¢`~ÐýG]:§ØÃ Å*÷Deß'sÇeÞ E•kÒa××{@HØÝà@æcÉqº¿n ŸgB\5ù$Wƒ%·'s©+"IÆ=]s쓼óMÀY*oè”ðx,µ ¤ùHÔ‘yGë' óÈ…zHä@®ªÃºèp_îò™«×ÿyr¬Å<‘rñ+[óš¿ø•×k„CÚ˜w:Š6ïá>̯þYé ™ê­¿†»H©ÜbAx½ÏøÝ• iÌÓ_öGj~c–_ˆOù±÷KÉ%ÊVæ;E8 þ^ EPc-û·xÊß›+ÃÉÓÚÚ¯v~Ø™åôå–qxíO¹+Ì ÊD€(3ÛˆwÞƒl›~*HN,¥¤Å©çþG¿wµÆþŸÄësüÛ¯>Z"Ǽ~ƒÜ·1É?UÞ¾5ž·ÃÏY&Í­LèU<_ ÿÆÍ ôq©Çx6EWØM(‡QAó‘R-ñùß`Nb~¼+‡çüÌ=Áä¾@€ŸÛ\ŒƒjÌ–4K)@–¢Œûx¼…dË-â]çç׆§ü|«"Œ~O› øþ¢…ä"O'ü”'—†hÿgØ·œ°"¦áH‚›`†Ò -½JÙá"¢€é0R¡ ²?ñ¿ðP+ë´@¢Ù Z¥An7oM‹ò~ÂHp$¯©TirxjÂÚ¡Ag/±¸‚¾)‚a¥HYáS€!¦]^¶ Ñ R %á0‘‹lÃéq«.þ¯³‚ÖÆaî».§ämm´Ø»ýåà×\Åý×â>?ÜÿsAj&®Û¢Í°Þ~¨÷{8@×êï?ž7ØÞº ì=þâ|*\öþ²¬¦+ÓŠ¼KÀÌ=|¾tGE²—0™…Ì¿ÝüGôÞo“sŠÁbF2¡*FÚ”é&ìTQc`Ì-ô½ß”Ô3í£œÐk“F±<~äAiãüÞ7s] ØÆ+°[ÔLà§Å¼‚Z haŽ ŒŠ‚“¤Ì•Œ µ0ÝŽ¡¬=)¨&*jØÙ›a¬~nµßþ°ßT'_eÉôèhdÕßo¸|=®†-½(¥4 [ü+s¯™»‚j’Y$¯AN;]·¡R ‹ÁŒ”U £Æ»‹¶/6ð7óüðä·Û͸*2è~â‚çikf«Ã‚ "²RTK@0S#¨#¬”~ vy‚Wêyìšé‡‰øòþÃú?»m9ûwK;›Øá¦ &àUŠ ‹ßò»;];­ƒ6f¸»š«j߸=hûk¬˜2!s¥[f¼V ¯øY0oÖXi©É#€Úз HQÈü¾VáÅ¥®JÇqQdÍ2Öcz{±t«É5æ–þ\z8c¤u<Ê?f.¾f“#¶ ‰Lf{ŠEgï@žÖýµ;x„&¦ÿSô9ÛÅ žó,Ö2H$˨õ’ýdW¾ ŠoŸ´;Ͼvn»·UÉ%W 1ßÒoäy|Ä.ÐMwg_3E +<ˆMY–43T¢ç]b¼}ÈõD½ÊP~›±ƒ^ÍØÛÔ@»RóÉï·t#ýNGoò¯Wõ nÜ¢úÇô¼ððÄ·=ÿoùÿó!ü®Ï,•U=::pÀ0ÌdÉGçSñ A>”ßóíÅì'J÷f"xÓÁOCÁv"Šu*6'®UN<ô‡Yª\v "('¬<¿]=§Œ}e<ÝTñÁE\|‡iþÇL½ }ÁgÕš$ ’’GîÆÀ¶²Ûe2…ŒY‰V±¶¶¨Ñ(¬‹j„Q,²ÒÄ(Æ v:ÿ¤6XXÈÙádDõ7ô@Sò ÛÄ¢&jñ…ðÀU3©×ˬôõëêßì}‰ÉÛ~ûØŒó$¤Á Ë^9N–oq# Y (ÎI§“:ˆešÛKb»T}‚UÃ%\#í_oh9hOÁà<Ço¿sîC·#·G“*Ï=°ïJ—F™TåP7»®p »ÇìåÉcXÎ(nˆ@'sæçI ´ ÷Ð’3rˆ!Òyö…6Ü·ƒ›ëÆä…ÜVÉÄÉþèñq.ÙÌc’Ù½á=A9°;âBFEìÁU@Zø4Jo3 Z…<Ø P}uB)ˆ!xsôŒòàën\vîôø}×!;¿‡™ãá‹°êž Ÿoêâhãƒú^€z`¡˜˜ hT$0=y¦Ã“ÿ¡ÚZ¡t¹öÅ"ܨmP‚Q"ykˆ…â\Acçž/§Ñr„òHV2Ùç'¾fùÎri¤ý>ÿB!L„ƒÀ6š°2×̃âýUƶŽß!h/ÄŠ ¾%’ÇÝžkÖÞôlOBý_]×ÕUùßf{rÅð_T'k ‘Û+½u[¿¡ô[Ì[üÕ(ßçi‡”-o. ÿbq IóIúñPDTF#‚ÅQF##¨¬Eb$EbDX2AD ‚ÏïG…äƒ÷ÙÝívÙævó§G‘£-¬éjƳykͺ¥gæn´Ñ@Žnˆ¥¤àI¾X²’;œ¸%zf­»ùòÔ*´ïp@~©b‰0¢ûLŽÄi<ᢠ٢ó¯ƒåß-òïßÇ—*ÉàÅí|ò½ûô¼Q4(/E4DËîco…þnœz{¾‡Ë)ãç²5oì@ÇÓ‚¹Gw#‹'zÀìöÙEÝ¿Õh¦Ï/g¬Wo5/ÊÜþ-y|_Ïoé`ßGý¿Ñï%ÿOå÷ŸêÉëáÒy;#–˜êi6·Ü.îüøýˆ÷¹S›¶~çgg@yàOËzi\~,ŸG³ÜÛ“»¨+gþ¦íkžêjršxû1„ŽŠôeè>‡®Nÿ'¨~‰òqË“6ÎÿRî©w>µéè}Øååìü Ó†ó‰‡W{uø-º­§/[Œ;Æß4ºmÎXà«· mð¾F"`ç¤B7P=óßÀy(Ç‘ãs: Z#ÉÖRæ†ÛÇ"K´jÞPg†fÙ:Ðñ¾„U´QPåN}°*¨ÎÆjë"‡õô×çÒb "mö lìåççŠ,Ï8À¨¡¨æ|¯•öhšŠ|Ûa›D³¢Gy”@D$Aùê«É yšEäçö¾:ë¶>ìIÍ€KfkCÀæÝ¤Lä/¨€‰´DEDäÖ–7&ÿ~óÀ#Ÿ‰U@Õ¯\®“Îä×\X—ÎÚ§oGw1öÒ1º˜Z2O­Ç(ö‹`TTJ6l}÷WŠ)12âu؈•7" "L@žå¦¾,¶Àú¨€ˆÒ};üyfðøßÄ­Á´4:SÅÙðÅ»W„i°ALj\e%Ys\s,¸‘Q}ß8:œñ··rÄîx¯wKõýؔڧógLÒ”"û¼’Æ)°îëàÐÛÔÂþ‡±’[›)®][:šsòÉ)»d³Ù¡Î¢ºÉyÇeÆ%=†8(%$–íã™”ôß…Ÿ T¬KF®uÊrÝ<ßh§Cy¸é—¼÷ÝË/g½ o9÷§G7ÎŒ‰Â—m¶)ôWÏ­ÄKVL¤8bVã~ªî5t@Qâ¨-°¬ý ¾ëo0Þ±Sb®ãÌ¢p­0$¹óáºJ4XÅuLò95U ¦øÔ"«Js˪£(ÌÙúî:—ª" ‰éQ¢Ä<ŒAGïô͸4B5Tê|ËÔÇ-›!·±Öíæ”£¾á%Öç–ÜÐ}{œÙÒ·UÆ–%ó&H½zRLt³½¿ÏDE‘Å ,äNͶû+–uxrvQTU[iÀYkˆê'nìf§2Dì¿ÙÛNÙ&¿I‘w€Ðç¯3Z (Ê$wz-U9˜è<·ª4Ί[ÍæÝƒ*'~G·…9D½³B–$ª\mš÷k€Ó{[¸ÜþAA‰ƒÜ±|+FîãSƨ†å/&·‰w€êŒ‘H'? e¿{o}ýG§É? 3ÒìÅTRþ|/DM8Ÿcf–ºªÈ]©Ìä}¦ ¦UwpN‹¦"*Q‘91¼ØûGÕíÊ»–j`..Ãr"j—–[‘à0 ›Çî¿ã #®mëdFèë.40n‡lU›§;Ó~2²©½¬ÎŒó,ÞMã>F·Á˜Ÿ=A9¥èçÕ_ÙÐÐöͶ7ú·N¿[)©¨ª"<–Ð ÕŽ#'•LU&‘ž75‰fóC;êÇw^ݸø…Ë÷Lú©þ23á² †P‰¿g· ]šØ¸å«'xu6ØúiÉ3¸>Ÿ‡iO1¢}.÷&¢nE9+¨Œ¬¬¬¨Â–<ñæ.œ¹å ð: .¯5“kls)Z²Ü°*¨ôPåÁÒÏÖÿ Xë7DD— ªÙ ;ïfŸ˜]#($„7© ué>ÙùˆÈ)ß __“û¬ßÇÏ·ÿ}ÃËÛÔò[¡Rˆ7÷xì–\Ð2u§ŽÞöëô÷9Ë"¤ˆ·HmÍ<>Âîåµô‡)ðfœU)u<Á±Ú’µUh¬¤æ${]OÕ¶_ÌgèËÃ)ˆ=Wˆî<ˆ&3ܘ¹ô©çW$Ψ×?œCÎû8áiÒ?ãνÞw[Œž Ãb´¹›æM>´eo¹(§‰d퀻ÝS »â˜À„ /-cÆCiY¼ú¨ªÉh18ñ”D;#tc"w«ÔzWœ“©S_jsæŠm[±ÑœãDÕõR˜V[>ÿxo­°}{´é¿œx:}|>^cÄ{"š‰À .Àû£# š”~Ú«O¶‚2¿hho±×ŸžLKò"ÇGÙÚå&b£µÕa \…Ñ"Ï#’£¦yç7ÞÌ¢š_('ÎR(ˆ\Ú» Ìôq³å`ééPh3-ÑÎ-÷C³Y©[U‚T¹¥ 0ù@ø/ÇÙíøŸ<±Â-ô»z8µç2¯oÙëO®ºrÆ=×ó}Ò¦_+Q§~ê2a$ò¯rž.…9C§-–ÀÃušy;G;} Kµ †8Œ'ÃÝõ̯ÒÔhù¸&÷M½I­÷ÝâÓÆùå^Õöù©ßë§7 ëäçëÛ%UXËš–6Må娾xZéŸ^/µ{‹w,ñ‰Á™Z0rò@qNöú¶£Ç«Ù_‘£¥Ê„*Ôó1IÍ»qQÞYþ~uîÔ:H¨½TsÀ¥<„œTW‡Îsßûo¦âý6 —ä(ÌÑ‹º—>³‹ôw2¨»É9Þ³ê;<¥wKIzÙ…S¦üÆè/áÆ‡vƒMû3êÀÎ$œ(™9eõ'·v0­:Ö{;+·22òô+v†:‚›~k[q¼¼gFÀó]šlÇ–îz¯?‹—“&UÑ™W·Ê¬XdÔÈãužzwËØã¥éþ\} ™*"ª¦W–íá`èoUc»sª¾õ‚= »ÙçH˜¹„,r÷}škˆ—¾£ùöÈÅp½TÜ|¯ß:Í:U-jÒb~%0Ø‹ܛ茻aÁw¬$HÞufŽf»Âÿ¸ãtõº+Çæ@¡á†,ÒÌSs‘Þ?’¾ZÆzÂ2“Œšåt%‡¦â)q\§½PñWŸ*\ÖQ²^xªÁÕT¨£]¦-*—]àþ\x™ÛSÌ¡]R–ìI´e.Ï峬o¤ø`·‘Q(Åʧ®¦¢×›l¢ƒEFo$Oj(Ç"ÌÒ“! 4ÎS;cigqR„’ñt¬ÙÅSz²¹gV"Œì|\Æ!¦O]0N} PÉLnf½RÊ!Ù C#±='¬poeÇèV®òäš÷ò¾H&_-N tô¢$!‡qþTSqGóÒok ÷âJ%õÙ}q¥–­7«öøY+ ½yÆÕÂ0‡j–J:â¥ÊGt·Wkºò< %p€e#›‚“TÊA”¾E±†-\ˆÜ戆“ …50áÄïˆh¦ÛÜÙË‘ª²øfâmÇ|›üÙì}äJwÃLPÛ¡œK3ao†1U0BmÜ_…´)mWj¹ é|4!͹UKp¤m2õr™)¼EJÍEP¸ãî´L°Â†}s‚ÍVLpq‚+F(¨qfëæì®\5ß„WHS‹òï’ž÷1!¦‰U ða…æµ¼è†Ë t*êÚ^Û$Ÿ änÙ(S©šùô²ØÝ¾ÚßÙS½HW"=‰t¦£p~+å[i®ªª|{Ù:C}÷ëì‚yó²‘.Ö'žå#™Ž-K(Cg)zà¥D@D§Û""é}® ŽÃî:[>èù4D}e>ÞÙÌYk<øB ¬CD(jbÄ ;–PÌÔʲ$÷\|÷÷^T/Ц;Þ U¬¬7s:*¡ÏÅÝæÙŠ1+9øéj·Œ/'3éíµìÌÌAY<±aM@åÀÍd¯žæÍek#„ùCmLkÛÛ;TäDÕ|¯å'r.˜×9GÑŒô˜¨’–Ì9!yq*Q™i· Ï¢ùŠqT%§ e//AŒmòx_# ¢µªÉyÛ"ÅõÙ jÍÐè Ê_xª‹|¶K»ÂÉ>ž 3ª“â‚æÐ²Šj¨D„1{•Õc%å(ÂpIÀi)þŸŒÒ]7ö/»ªo>n”5UžŘâ.º"ë:;Å¥=…Å‚ÎNèl(î™$k>3™ú¤´ïŽn×ÑNtö¼{IIgŽÛ™úêéï{¯7WWˆ¦õØ Û²º={&æÆ7´¾ÍäQÎMÙÑ‹ã/ n^̾d®~¼‡á‘–\ríSÝ™ë-ÝIt-¶ûxæÙvs}Íq7tž8Kàrã>í<›èiÃd6›‰+/!ñÏ—›·ªÝ˽ö\sìoa¶k-×Q¾ìj †÷:‰î&›Œ«{žîQö§Û)øz3ü>‚pòô´|³x}çö•Ž4îÏ3ÑVŠ­þ÷­—‹‹ß‡>ø^°á?42ùn‡6åÊD·C©µºÿwnûy¼WÄ×Ì-_.SìÕ±¦ºïçáò7RwZ‘kùuã·õ1º‹Žþ­˜ë ï㱯†˜dèAsÖù)Çdð…¿³M…pÊGY {½¿}‰Ú²4øp¢_S‹áw‚%Þμnî„÷ããðFmßÃ-/:ÔH_[×=O©æ€«@}ºÅõëíïéNýw8>ºìÇÜœ¡ÔíwìêÁ#«Â¦ú]ÞŒÁ “&¯¹êlíÚ²ÇAU^<.¶¡ÊÂí&²¿‡WWs««GÆñî .ɽ=^õnDO=}Ïpî®ÕðÓJèÓ¶cÀ-‡ìwVìÙtQ[ù¸[ SÅ_àz‡-º<|3ÙžÌ0ÊÛmÀFªûªÿ›œ÷áѲá-Àá}¯-Pú%Ý2TIgsåZHø¶ÖÝßÀ²ZR ‚‚ŠUúÑP_†å7AŒ6øð3%-²L)²ƒz /}’ÂqÉž¢õÒ\yUB:VVq—^çÑ´~y¨Ê©&`uK‰4¸c-ÐÁÿ ì'è¼È®ù‰<ï~O™*ô1ŒQ<=¬{Wñ< nq48m…Gßç×?bßfò,-gÖu×Ïœ¼¯·}þ–Šúºw955cl^^——ìy·NñëK)l¢%µKlAKlA+£»Ê@DmTè¦h€‰”ºJÌ«¿Ï”zý£Ö¾˜ˆ÷·fž)p–÷6ÏQµ„!ÜþöÊy Òc€±.ÞœS89NNj¸-ò…š[®‚õ·tæt7Rvp Á}eË©tœ€ÛÃÖÜoT¥ú¦'N"Ú^ˆ@^¯m¹¡Ûzo¼ŽÙ˜P69uN²=ŒÝ\kq°ºF¢Ý•;07nÆ Š’Uª¯Zhuå·âÎx˜»Ä¶ve:--â”û/•äWÁÀšÿp‹Ëq—€ÉxágbìñN†73'¼¨:ž>ðAP¡VcÂÞ M&.‡G1ôu­ý+{ݼcoi1¡{B0#Éž:¥ŸV ßJ'Zž:?£eiYHH ÷aH™Þ›"ž[‘ΨƒHP-tqAñ¿bFIn¬Ÿ©¹’'$»JÑò§‰_l ñ“.æ3[Ñ}™·ÆC®Ùóœ1ÒÏvË%4Åo Ì!¹Ž_pØU¥³pò‹2ºÆC"GÛÛ(%w5‹3ðRËÛD¡i.F{‰#ÔÉ…8ï’1¸óèÉNþHDz¤ Õ•…NÕb1qÙê© ¶¸vìåºIéíùûØ—+»qH'œ¼Ï ¥.È1Îtý§žj•vUa†»U;]™F|ºÞW©íC±#'fURøï 2Ž‘As®€*H9FVgßó²ä×ÀœôÇzúUL‘ ù>8®õNLŽÈxgXóçV¥E}G{rFGŒ°¾ø€ËQ… ü4Œ §K69uY_n)vNçæ°=‡“à=:\ͧ¦+$Ýɨ¦1¸ ±¡§ÇEY˜ ÖZo‘ê–œI¨’=½S$$ˆ'½æ§;Ôùö± À%!õGZÄÒq%Ø|>À€—ùOpXk–ÄÈqðËûezŒ!ú÷gcã6ÐðKñ|sM 0—o}Høýâðž¡*w‚Œ™Qî"æ}ÒþëÏËʨ‹J/€¯†_DˆÆÛíf<üÙ{®3¶ØsMcfçå‹V€‹` ¨xùSv>w×bˆ&?nß•ç™ç<ªM ‰22L|N]b¥=w£ÀYUŒ2]ò•Ìi…:¢Ø^ìW{²ú;“9ýãOªôíÉ¿oõ‡cZ?å|½ÚÅ÷ü‚­£¢Wyðuº©¯k…eçà˜Bõ¾èºVs›F’ûKu*'VEµ^yµ:»ãæ@¹YQëÈÅzËdv^¦*Î¥æX“꽆;`œ& ¿¡"|]¾v»òãß^Sè]A~@·ïmý×—#¯: Å‘«B÷;r„Ô ÂÆx–!E³>g,¶Ç4ï+ ²á͹‘â×4×Ñq@Ø™[ÅZÊÿ[Þ„nì(¥HlÛÞ–.õ•äÇân×IÜÐØ!I©˜‘1Q²5h­Œ0ç¹8_|EóE ·Ü+œÌ'H°µQâÄ:*·;?D"jŠXRìÅÝ‘ }uÑvÔjîl`pa–æÍG^e5}ꔣ7*hæ«U.7'~Ä´RZ—¨®ù©Žît×D6ËE¨ÙÅÅ–’FZ$b€ð!mÐÆÒ8jŒ'RÈØnÇ£&ðG(Ù‡>)p¶z(o“$®”wâ…ÉŽ,•¸ží6 ˜©%1ÙàHÕfLΰŸïç eÒ¸®bŸ,ŽÀsnLlm!ºáµÃZòuºW‰ƒÅÄ¢Ÿ-NÙºèaŽ}T@çÉ€ƒ0[š¹8bªC59Q„ÛµŒ@4QTEXé÷Nž»Êá·[¯|¨¯PÜï<8;÷9÷ê*‚ˆí¬ÛbÖ ð nŠn"Ð:™‡Ÿ†Íõ'n _¢-¼Àï‰i‡m¹™™™Õ™Xå³4V3F Næ¼çÉå)±òº~ž:Þ‘ ëX/T¾™ã‚KÙ±ƒYóð*½&þf£=æ@3mPàö'¹‚ÅDó,0gÞïºÔÙÜÝc‘”oôK ï,û®jb< x°µ!5ÛbÎd9ŸÑ 3aÛ¥À,žÒ˜0q‚Ò‹r~ßNì^ÃS·sv‹±H(²ì¾þÓ`hèò™Äëd·{s×;ïeÆT^°N›­³žd4æ*|¹+·wi4¹D¶ôà›: ›{Y²ó¤d<#«?‰nT8g¸çØ0/0]jAZ°zQ‘ÅMq.u'5f»8Œ×œ‘=ƒxr KZñÒÖ)ÔT-Â+t ±qˆ¼Ïàbò:Ò ê[\navBrk:w(lP䡯Äh¼n–ü×qNiÈØ¶NrEØÞ*]•<³Æ7–—ªùó‹Eô³©ÛÓ¢’“)÷r#Ô›¶¿dºÝWØ’qØm‹p˘ÃUIsÐ’M¼Ú² ¼C³ î/]Êð²Òé-ŒŒt8o…ó¾*lV²ÏŦHcId:)åœå-ÏÓËAÃÈždPD@ž°¼¸gWW!© ìÏ)DÛfŸR•jüKõkéz‚“ªpË‘Ž1UÅi ÕưDƒvç:„oOBbbuLwà¿zeUlôèñØ¡XÊ¿96—G¹_¨åU ýžTœv üXØQ[J×°Š "p˜³óÃ?R“ú!÷•ðÒ. 7 Òt*Aàc”5Ì‹M`ïÎ|í":»,µï„–»¬yAálÏÓÎo»8Éj¤'éU«Êò ivóhÞì6ëÀ¥UiOv(^èÆïg ¢ÍëÒ+£ €g¼ÍvÍ'zÀðW²ù"új€ð9ÏYñ:{Ⱦô_"§ë„m ðÕØ÷Ýyùõé±Û½ØØŽK·Ž×WæV !jÈu 0É,éGÊú®æ°ù6Êcuó”ÛÏ͉8*˜Í²r :¨´yB¦WÀ¾1ç!‘¯®¦‹*Bdúß.ºàêúA= õªƒÒRº·ÛE£Ü£ÆËV<"I¸ÚÒbÖowö"lZ3f§Défžîáp³3ãŒN›ãEÂ0ÕTð¶Tf‰¹:ûϲåZ‘6Ç^/Þ¼füWƒâš>f½z]ÏŸ^T¼*Â'ßç7îí/® ÞŽ>¡|@u5[Ô±FvQp…õÃ+ 2Xböu²Òy*ô¤l]Kã.P•õ¢XUÊ•µ.¤Ù±ƒRë±PW|°÷%Ó%¢~Ó›¸—¬‡¼~] Sâ3ˆHªã n”ÅÆ`Ñ—ÊéũОÙÃàÛK®µ´!¢}ú "iËæºj°TÞ£U†–J`ÙƒJ µZ:œ£-W°&Jl/bÅo"0¾ÜñŠ˜Ì´&ÍÔÆ`Ÿ[^Þ—ÑÕÙ$¶Ìäöõ¦h×°gB´rîs|]Ê6Œ– ¢þS„ò'>sÚ…ƒV÷6ÇBéŠPà—Ü«ø!½Hãï`g{Nç¦åöËà0ŽI+н‰XQ 2Œ ª ïñýÙñY¶سt/áâŸF–{”5³UÁ„^›Oj£îtu‚R÷Ê2Š,`†(ˆÐ:ošyy5æóRÞíǃEuÂõ]œ2l”u‰·ÝØ«Df¥{1ËïDDÚ™ãºG‡ØêEÉ쿉Txöñ׳ÈëòqƒXBºï¦¸J.ÖÝ{ä ñïîÎNuGwÓ3aK´Ú\¥Q —ÍÇÜÇ=ÙÍï¸Å´ƒZ5EKêÅò½6_ªÈfõevé±:ú§(Ëÿ«qîðMStÙZ9Òæì¹÷å]¡xK 2àa‡¬»/œì10ŠèËÐ×cÛá릈Ø9¢â½ É¥FU’—díæZ*¨’ðÓ¶|;ku¤.$°ðô^ó•ëWè…£+Ê+Äî_xDH±ß1ú‚ñuáÏΧ“íä›Ö=Yûý/Ë4ßdvÛVø!ÚýNÖú{ïyuîw\!×ôáLÌßÉŲfe²eKÁÔÅb²ƒýîýr_käµIöëÇc¯_–›)ïùü¯wŠ(KØ_‹’uüã=\/nq¡>t“Œ• ¯ƒËO©ß?­¢ÏÔj¢ÍtÞïiwÂ')ø¹Û‡/,ë4¾°öË›„¡+ƒÀ¾äMƒ«ì» õðgÂÑ•1hÏcB¥Î(í]Š‹:¸yß½P½Cú£Á™ €@z\]O~0`.czÇ¿<"LÏãí!·b¤ü˦zþì—Q~È(Ç­ËÄ&Þúgèj ’«‰hgÿJÊìË÷ÑxsǧÑö½ßÕaêQ›í'WÂñ|ëm|ý@„ [6õ€ÍÏüΣçiRqŽ©E¥±ÅŒw3¬„'ÅF±[š"€-QïóŸS»KY‡e67ÎP¼lÇ ØeŽ9¢´lÚ¡³yUÇDé¦eŸ÷]ÿ{¶Y14¸3¼,•Úª@M“uWŸßÁòÁ±×œˆr~d5W˜€B·â„!„!_Ë|O¿û;åAx~öUç'­ò$H@*¨ð*¨•÷~¦QD %R ¾ÐäŽTœ{ëp\Zz¸‡/ ´ìÛ]é}c®qø–ìnò84}Fïge×êÛÿs~‹·6g]Ù~ÿÆm馳Æ+H˜– ’îþ4=»¥‹][²þ À½ˆ­û\)ûÍÒ‚esÉ9¤ "*ñ¹¦Ôkö+DA™p›ç†éˆ:˜ T.ù>ä Ò6Ä$¡Áé•ñK. `½_ßuwþtR³¿„ÌÞA¢ÿº$xB6h¢©§G«^ëàÖUdÕòxì#DŒEe.«?b "f"2þé{ð€¥W£‚ø*âÆÅ¦qlñŒ,Õ:×|׆\ê§-fÞ\(/ 㬞Wå DÄjt•U¯GHvJÆæLs¦íoJcS¡D[ää ­\wIàû!¾\6÷õ_uû~ëö®ÕV]qïàmãM'„V‘0,,$+Ýßû¥Á®‹-Žùw¬ ØŠßµÂû¥Ê4ç’sH@D_y¹^ËL³íW@ƒ.3}1ß1S …Ñðø``ö–åˆICŒ)•ñK. `½~þÏ R³¿ŒŒÞA¢åá‹¢G‹ÂÍU4àÈõkÇïÖ÷ ÉO»Š×o#‹Œ¡Ïuoš ½à‹S«ÂÞb-—©{ù›É«M#£å-™°mZÁm6ëʂ£Ê‚ª¢;#ƒÂŒªP‡°€¢@“§%UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU\Š J ‘Az¸›®@8”›¾%´3­¼¾]/Áu]s‚Ö»W˜°&+æ° >×m›W¿6¾Yæ„÷/¤{g‘}»™õï—{—ðrøŠtž‰åžeõ/*ò»yÇã>íîßXóé_€ô¯Â|“ãÕòÏ£~Õ=còŽûgû^áü'Ñ?ÿ>éøoL(/Šó'Gë¹ÞW®:Ž·©/³Åÿߊï¾0tT`ëz=@Œ:B ®ÓG\èŒJ ² ¹ðO—ÞÒ(_ôèWú¢ ¹û¯ÐzCÊ­ôsŸL%ÜZ·DJÉ:+]:GWW¯P^ ‚ö Î(/2h‚îTp ¼ì¼mIÓ`*ù¶ÕÁk¸Æœ)+=|_…òâ]»§Õq þÎ|¬$—O9VŸ#tȬ`úNkùÕþš‹*«nf¹gëÎÑÊÚwÃð-+~&P4)ÙŽ¸ª¶Íí¥oS„ò|U3ƒNq†ÉnÜuiÀeVåÌØàFbÖýï9,ð»âÜeÊ{Wz0žV§?0ØÆë²¡(™…’}<êDÚ(,T Ø¡AaÚ‹q~”~7³ñWçÇ??DL¿È§?‘˜ª7áÜà³Å¼ç9Î*¢kwjª÷yÎr sœÁ ÌݹS)îsˆ®s[Ìç1ÝÛÍæóyw{|â¾^ç7y\ç-íœÌæÎÀZ¹ÁƒG ”.÷›Ãy¼Ööï‹“»\³w¼ÞKy&o—šE«D{½¿Oã÷DϹ|†fú–Äü§§½ÎõŒ"Ý*vÆ0ÕV0iuÚé2Úd†ÇÁÓZ´VÖ~áþžpù.R§7OGU0»ìÜ—,¹ß§–6,Føæ{fñt¹W¹œ»«™¾«†—.`®Y½)ññSææ.]eÝŒÛ;³É»¶²ŽÝ4ë‡Ú t²D…º‰lðõѱŽó*ÜÔ‚3¬ “”,‹çK«W•] Ŷ¨±s­r““AÕq'¹/*¯Ž³™Ê®šÌæXˆ;%žºHÞ®]JúìªçŠTï.·· ÑâÖªDöÀß,×;gAö—Ö®·”B\wÛ]H»Ê¾ÇYÍžmŒ|žnå ¬»¨á·É#—ÊÊåWP&¤j<ÚVØ;/:§›…6/˜lÁËÌàäí Ë–/Œ[¡Uã°ØG&ÉÔù’O9vnó›Êì1Ý«m¹ú¹&2:GeÎÔ*h!1|ç%F\v=B“̱×T6Üè&]Ðéµ{ÚÒ„Ë•étl{¡uÃZЬRÐ]æ4yŠ8±¦ˆ ^X‚ ( OyûÔ\QÂÿÕCì¦ F% BK‰!"#$`CàSÎØ E î_,"Œ³™AI 3òl ¤Šˆ1H.­ßí¡Ï´†ËÈa§mXúõLd„Ÿ£˜FQFFSE{Ìû¾Ÿßü9ö|WëýîÇò>?½úŸTÃm÷aTèéös“¬( ›j’TrQ#æÑ?cƦ õ^'dÄ'Œ’à! /ÉÚòÝ¿Ùï߉Êö½G«DOþ݃/ú}¼(ÿŸí9ë„’…&ñKãóRÕûè0528%ž_­ì6;×eúL˜cÓRTù+¡.4˜ãLÊ"ÎZ:§²ù¨7u …”T†ƒ9ѼøÄ˜Æ!^2ÑØàW( !Œ +(HDéÉ–$YcH‘ CzT¡¡_ùú[Rï1é÷ÛørB%U=Ä„rî0ʬÿ‡þªŸÛ}[¿«ŒT¶µOÿ-}hVÛ3usi+Çí42©ëštâžûqüFEã E>¾ƒ -±šo÷ ¯Ñ“6x¥ZÖgy ßørVkªÝ…¤çü![ š±1Ô*Ò/&‘\3¤ßíÔ—UÉMW4—úÃ÷ôáöûä·^õI5Ôͺl»›^yõ©2ŽD¿M+G6|.ºÈ’€Ð%»îÌX/Ô©rMË‚ÝqÓ÷,Ýž¿ÉKU©wªµ»qŸƒø‰ ÓDÆÁ!M·wŠ0CÍ1Á"1¿QKèy*ø_SdòZ0ô¾þƦ×ðþ†¦ ÇN¥ÏÒŸ¥|ÉÈ:ŒP+9ªëð r‚ÁBáÄ !‡;îò©wÞ;ÙõÞæˆRºw»9ññE÷HÞïÑþûØvý†¡#„m%s\Â?ƒ»ãð,zžp¼6]` ÿü´¶P ÊV˜µ.f" `pÀÖÖGÆ1ò€h]˜FŒ?®qꙹøÌ€ljlD¹)ÊE5Â" @y%TB[%²@Ëû×àê“ÞD¸•?VtÑ éØšýtñ½Y€:æŸÄ½¯å‘ˆ¸¢0‰pMVâ]hZ­ù*Īy½Iÿr~á󦀓«]~¥j‚µ[ú»wNñÌ*%š¤ÀT¨xÙ‚1jçŸÕåNÏ.<& $!ÏÀa†Ø @@š1"xËà3ƒö~73v//ù%Ñ1t]g]šàÓ _hü>ãÇKdì÷­ ªmû;)Ì*m§²ˆ ˆUè*ž[Þ6žƒ§ú‡æ(¿î©w’0ùzmÕü 8\N&*«µ‹Uäÿ ‘©&Îp^0ˆ·²—Fä­Ò&ÄÝqAbíDdL~ŠÁ¬^¢ªÓûë³…Ðou$‘ÁÚõß׳_žð÷D¹Ç‰Û‚ÁaÚ&ód‰ò=ëÑ#¸«?Èü.¹Îs_ÌåÀŠî9ôÔ„½ÑãA®ªƒÁ“ü…wd/Vï‡#S æ„‚1>ÑG÷ddL/zlHÑîB;ºänPq×§@À[£½{pNôAØy  ™d’K6Í´s÷ÛÄî-¾„”˜ó²%Š£ïðªy©õ¿‹³-ÆÁtw^õ¯Kð¤ ˩覵am l-²Ú{q‘×$æ‚/ *¢‘JÀò{ õ 0=ö{¤U¦—”n0y#ÝÔ°*„[òÐp¿MȾ==Iþãëä¿ xpcîp‘!€àã¦åm茌Ó7è-"z¥0p‚^y‘X؉j©ëëáYïág ‹aòoËfyº&FiDöphŒœôzÌ‚h½Êd¸e“¸—™L=ƒ 'üŸ2Ö¨’ÓùÖÏ-oIî'ð*a†5 ; ê82”Tö°(ñýj{ó÷rœN?åÞ Ëîèm¿zf­ËÇœEüÈGòíçVx]mž<¼½)û—…¤fÇñ9,µþGêcß×ÿ »ãŽ2 ©øqê>0óÊü½½–R?Ù~}éó¡àÆYÚ¿G«þüù§t4λa²€±TV¿q=Ç9"YŸyûî9¯ª‹7™Ü(é4û~fÊý’éø×y¿Ýyˆª)r“J|§òþÛÒ¾®|3—~1=ß„øJ'‰mÅ1.Ù퇰'›õÉñÈž¾õ³'¯ž®¦mÒÚ³õaiIÕ-‘ÿNšBå xR† B—‚:¢Aù¹@&¶ †?r•B0“19°$‚šú›ÇáÄ’û_?#Ýór ÃÞƒ>_’¦Ë ‡-»jÒÝ$fæìC¬Ç›Ú÷ã¼SÆ€sÃ’G @tô£ÇÞ«x»:! q›ÁnF½/çíÏ<åý^}ÃÛ(æ—r§DÑ”u²®]Ÿyø‰ªªŸ0Á ¡ä0BY5â_šgú§•bQ8"‡—ëEåo)R«á[¸÷ºˆ”ϺÖÉO{TÝdÖ¬V-n r±§MMÕCþ‹&8–ÇdÄ@.T<‰ýqTVÓ„ÕâE1{Ë›EV| y4>¨úª|‘Ƭָ¸[sKÑz5ʉe>Múü¹’BBÖéé9ék’–PGTAŸ®¢‡•… þæ¨yÚj "j/äôšÜÅö ‘ H›Ù>Â|_'†x ´S-îáÍ‹¯3Ås* ™îækoï;™ä)ÂÈ“›{‰¶“ŽºçÔ³¦‡ËL|¾tjâã „!2áœÞQZ8æLÅ$œšX‰Â@МI±p&hÐòôâ„Y<Ä@(1¦ŒgàÚÌkXxY ¤ÌüG-åË‘@íü7±{õ§ËTÄ̦„Ž­ØØÍ¦µ†?·‰í4*e ,X]®\qå¹r× Zù´z[gù'àλÁ ³@rİÙ8òü­Üÿ§ûßáV™â4ògÐlc³þ_kù¿Óþw×GéÛµ|G£×òùîÿލ7f8ñ•W>: Ñüœ´ý>^3ø›ýçø.ük´àÈÏϵOÝáúúR”8zÿ°šV¼ö·]u×WÈÌÌÉÃ×9\ÝæG8¹Îs9ËŽ°ffd|˜òñÝ<º8Æ<£ùqôר®?'ÇúÅ=œt3ËÜìü<¢'ê$tK­>ŽŽŽŽÏy;)[ªµ­e?7È)hó¦MÈË„›^vê;ëo“åè÷ûK-éSF$nñx»Û.Ã’j’7rþ.§bܨ ¬¨Ÿ¯L˜Н”f5O›ýž¯,½›8/‹åÞNôc~Q?q!;yNuçSžЄ±½¾î®îꪧ痨õº¶m¼ú.Û×ÖØ²cÅ¥~n1é?*<Æ¿°¼xA‡üX:‹Ú¯ÎÃ3AÙSAØ–K$„Œ¶Ü–mû]TÑ^“÷ƒÖ~à| i.£N©m ÃEz0gäùñÔP‰ßÝ ñ!3ßÙþžÆ}Å•7g&å*1—Ã˰¿&è;¨«–“‚eÑY9ýþø&`ëZÿ£ða¡•Êöxžz©±bh×|ñåbÈžJ*GéèM•ý°6O?ƺø|ŒÞõ'ÑnsWÎÌÞgw?GVÛz#ëÇg½ÙàIÏvéêΪª£ª«c²ø†èh~ᙥ¦é+TB̬ë7Z¯[è”é1™æ­NŒüz˜n×Hk™U|±Æq"mYôyÕ –I%Î$TQ_mmä†Ò~ò§±*f»±wxp=cË,Ú‘-¸F9“ä@µg+«µ`u(˜-<Ë™»¤WÔ¡ë?¾}¼F âá?;àû8ø×Àý?àsK‡rÍdÇÓ~à=J|=ŸÆñã:?vŽF¾ÞnŽ®]}Vî¥yº,úŸá];t®?ÚGHêu×Ú4ɾ¯Áâ„ý¸<ü½m-ìú|ß5ÏÕ_ƒ£Ùõ»L1ß~Ï—·¯ù{2»RœÞ?XúÎÇ6rë—Á—ì< §§©aÃ}¾¼_§¹±€'nÁ^©BJ+•Œ:ù9> íì°üëïžþ[42ìˬèj”ÌÛ¦Aìžü¯§»×ÅòzáÍÑ\œ®KÙwÉ^ãDûdÙÞñ¯=×júã£Í-u·Éé÷¹mñiعèÏÏ×åËÉïÏ9E5nR´cëôt5ç¢Ä[§Ù…¢…O•WŒ9ó= Mø{ ªókÛª8Ûîõ’0¢]p/œ;¥îCc×ÙÍ”º5<mÇçå°ôœ—ÚæNOíz¯O—Þ½Þ\³¸ôE½¥½WÇé¹à1ËÛYö%×…Ùy´ên^çñ¸_é=ñB=*ˆ™(J|òò|ÆÆºû æÒïâ©ë3'WV]î9»1DpÈ{†fƒZÖ?§yþ_ãþG·ïשֽ®Öæäð Ì/úë™èF=(LÙܾúTù——žÔsÜë'aÆne'&u„Iû®My~‡Òç^Žoþ~Þl'Ï8gó±ŠeóÖ ü}œ ÀŽŽQŠ<ÞXºfvªá䎎 6Žô^0ÒHèoF88G7¢9×Khõ¢ôÕW/¹¸3qÄ(±Fp$"³A›Š›tªŒ°›–Peš¡»ÿÎe ]%irâžNª~§ÁþÏÒûo½ÿŸþO?é}5’ý&ˆ|Ûm²¢¼ÑÉñtŠ3…·mk7Úh&E°¡ýèºVGpUÀE€C- ² îßÜì; Ìü¾;¤’Žk™¢‹ª¢õžÛ­Þ¨å #/^ø†L;ã-ìµ²tûc5$Ó§Pì Q%tÝÓa”)¥r,Á/Þ‹”_â}¢ý`Œ"?\þGëþ ÄG•Çpt÷õql¥H¾CFŒ``{K"°XK†!aBáÅ(9óûþáÈ'ÜŒ5¹‡Ý QÇ/¼ZþõäŽÒ Áô—8xK˜9ÁT‹ŸmÏðÔÝâüŸú<ÇæT¡‹²âßu»ïÜOæ/»»eXˆ¬ÃjÂùæ$øÃèìÆ}„WÏ= •sub¸?}¾GÊ00¹0𱣊û·õƒ 7eµ‹¨&+<ÿÁè{ß_7×{ßàßú¿wì™ù¬Ýna±Í¢…5$ñ@L,S¯Ü{ŸùàìKÈÇtá,–VO¾ÆD D†^îÝŽ§å8§+ŽÖµ=+us;CêOÃäkàxf™lv;nBã:Öw0Áƒi‰âúžû:{Q€ëuNæÆÁE»©q­Öv«GaÃØL}¾vw«ërõÛÌGòw/h}H»2uMÚŸvØI•EÕ‰õˆC%rŠ_<>ä_¬³¥eéE©p‘’Æ]ÓŠùöÔþd%L_quK×Þç—·6]wÏ7›€·r¹«“‹éówÉÂ(¾~Ïmè?¿ÿ“¡ÿ]SŸîs_‡ªoIõ†¬+"’*(RQøTœÕg4i+X€Ë@ ª1Ôcæ!!&H´2²—ù>ÇC ôÑraí·Ý þ(Ë‘æ³ôÊ(¢‚‹§Ý˜Du‹$:ûÿlˆ|ÕÅþªüRËó·Ì\P9*JùÌÜÏÝþ4xÏ«9/Ý?BĻ嘀‰NB`ɦ”—ÝSjRÓõÒÇï?=cØo±Ÿ_›üÉGìwv¯ª¼·‘UÝÀ^Qý-¥Q09õÙ±ïSÜòs7ä—û^ßóîܼ›7Öo©OÆ‹Gknew«iöáÖ±!,竬•7»Âºo6I‡9 šwúï|Îz÷7aƒg=Çùyìyw\ i×éwÛS"ïN…?…KsS»š}óÂ# \KáÇs¼ü:÷ÔÃZ9·§”¶4 ½Ùc£CŸŽÕ¿YãÖ´ËsÓr"pß®IîZûÏûá·nÅgM{WüSpN)=—jöôätwdm¦-\Q´ypc*vóÄe¯ùŠÜž¸·1elqöü¹rËäø­½ ØB}T:ð]ÔòË£äôOY´«Ò í¦øÒK¿ZxÊÆQ¤=—†ã˜Éš6ŽØx¬löî5´oÈ®ùúv±…iâXÝ.Žk¶U´»*{ÇŸ?4¹¢˜ß†ÎŽæÊö’ÐæŽÕ–ÙÒwØZ4xÂK Dvñb¹pZîõ®¥Ñ<‚.ì[KËî%Q?™C‰ÂÞø}þ÷¶U2BI ä*MÀÈbt°¨}KaY]Ò ýD%þÇñOÓþêqÈáô”¬E>ý ‰ÒëDÛ©ôvù)w™&§‹-ŽœP¥ƒÞáɶJ*9Óâ\oÉ…ºïï0ïÊsÆâ­3h™–ëçá°F&×I‘DŠDmlHÁd@cîw`` c ŒDCL <­y ‚¬Ù¶ƒí¾ ß«ô¾‡àqºúæ‘HÂi€ÚÀb‹ݶhÂú¾ê}/žÎiEK-¼°q^ú ŽÓ¡^toZà¥=­“(. 3 qd£¾ððÉÍ<ÿÀç®{î_¹¾w7iÖ{sÄjc(‹Œùÿbúž ¶vNÝ5?cÏ­ÙzNP¶ž¦ö‡É4’”â.}ÿy[G2q¹ËhåôÔUxZú ÐàÄø§b®gØuF©z…Ñ£ÙL»2Q=J*áÿkŸáÿéÎ]Ë“"§ióf}NÙòåñwÒïW2A?7¯Åò»ê€cŽ/{ù=<7Óケ"§â{·o>aó›Ã·ûÇúÚnÃæÖ¡Íî¯èä~Ëàþ×ô>½¡âBåD((}c}ññ)á>îŸP^oxbȉéåìg݈$¼^Ÿ|/â=JŠ{>Ë_ò8ãGŒÇ³I© I"‹Ðâ»2 žž•™Î¨l^¢mÛ¾SóûLa0dj¥C‰€äoC Oâ˜tìCãRþ¸|Ôð¥ÇˆßD!ÜÈ’¯Á³úŸ±ìž‘êTÃìD<_7œ¦í› `—Cp´pÿ¿ðO¯§Ùöü^ Hí7{~r@ØW­àX <ÜÒÓ¶§ü…üåÞÍ©/®7‹È2×mž›ý“×%º•(‰üãuüy«N^†è{¡Ð(§¦ïÚA›)àl²w6N´e@µ«J¦b Ì Æ Béñ“]õ›f«¯äð|=]þ—ö:Ì Œa˘A;aµ¹±?MNT{"kNÒ¯1uô¸ƒGw³­Íbá¥4x|è«uOÂêzoKõ>—¾ùýÞÓóˆ<m!öà öÛ¾ÁâtÝáCü7Wcä·æIÇPô”1At ±(@ûõrG¼2ð\?<Öi+ÒÔ›¶q¶9"/ØWj ´ (M‰˜A|T}+à‰{Òá{CçÇîebýoãÙ t|gÙÙL&~J—lWV¿Œ§{IèS/ZÛÊ}еWŸo†ë¹†ÇÚV©÷?÷Ôߦ*ôT¹Iß鑯—'56[­HñÇÑh».ú¿ÚYÓ÷“( »”cÕIÕïãgú­§ÝìæŸÜð'~ sªåU£ÁQüxËš\?U_Þ_ÌZ¤„sìÝ÷ßmý/ÛLÃâ­ø-‰»*vlZ¬×2ƒõ¶¾»¢?k×ýþÎWíç¶Ìÿ 6¾¿ƒnš[q¶uÍxߎÿ`¬¿þâž”öü9T+Ÿ2>;aï|Žm'$û¸x•-Ï|Ú«i“òÏÏŸ¿ÓÏçx‚•$ë‰JEd `¤^–™àuÃì>ÁœŽuáÅ1–uüyò½o›·{{ǵ;4ê]ßž~c§w-y#@'{b*îâ–ƒ" "¹!"=ðÚ:ĵ³‚üT0?m}aÚogK‚®¸âË(NRHqoºÆvoÚ¶ç Õú¸£î­»n¤54RÍ8ëÛ4VUÉU|¨É™è¶F¿]…ͳB@Õdž}ïç¿I¿yU«{ö,´OT|g*ËÞçiòg’v)xŽ™*CZ¢À£¶Ž5“>æÎl™©e0ºØ¹µ™%œ}ýéÐÚÃë£'yÆtCIPçš5YÝ®]åx‹›dk@@•ÊžXÙC@Ѥè²ÒŒÚÒbÑ€e7T!ûtu|$%Á aã ž¬G‹U÷iË;mP@ª¡£$‰!ÏwâO;d’"*.…ž “Å2€©MH>ßúê‘Ï>vÙë­˜½J@b°4áG á©çks‹z³qyˆµiÃC±”oކFvÀ÷`²ŸÍGDTÄ›UY”^2Ü & LÄì„ Aƒ³ ®÷@x4dlô†&6¥Ò­÷K9WB¬‚9½,½¹›ÚÚDC“å¢Ï f¢÷¶maµv‡F%¤Fó­ZñMšu–W)¶ aÐuÑ™RíÀ ]¯>®ü Å쉿üÆÕl (¢ ³¶jï´Æ *E2ÐåLL æošÀ¸¢v:¾í’FŸ}¹‰TÁÐò±>/¾mjŒçŽn×DÜtóÕ ‰Ä(‹Ën*H@Egu1+€”ƒ³k¼øë ­õ³BˆÂ22%QŠ–*iP]t½¯Ç>{ý½íË7½ïyϨ=SÍ âËݲ5z³fÄ2 B°‚0Š0gΪÌIêdTŠÙ²%B%®m2^‡l¾.ðmOu}ä è(HtµË1ºú.>®°â½¿'·Æ>¿Öþ<£Có“õ´·þ_Ûþ%Ž?/æj›Í‚o·¾kŸã^_}ꊷ@aæÔ\-*"öŠn‹—MçB¨, º£p ÁQ€+aA|P ·‚‚Р‰àDO˜_‘û þH;Àóú'Y¦Ó¡F›No»¿¬Ó©svÞm5zR‘*Lܺ<æ_&@Å›³–ùÁ|àÎ-a0ü€"Â"à!±=a ŽZ¹äõ͆,8 g&¹x9<QU|+›•<„!FÅ‹ 1cƒƒ †(X¹‚Œ!cƒhpphÑÉwfŒ›H~dàÙÉÑD9ౄä\6lá½Ó$''Y2QEl »¹ ™,dÉ2p8,pQ !Á‚Ö Ùƒ£‡,las‚!€(0EŽ»#‚ÓÑDX«Á‡,ºDpÁ£& ™M9.«ðœ:\†Kh82`ɀђåÍ82ܱÁÐÆé¬,Ø£‚îÊ!b4h¶ —u’œœ2ìvp\§Dvdx84p˜!räaÁrœ8W€•™2DqI’H ä‚„ÈŒ13v0Ãdn\ๆæÌ—)åÊ6X¹c'Ì4pQFÇFÍ2lÈ`0e±&Ë4ѲãrŒ¼,h¸‡^Ž84 †ƒ‡aA°Û½ï@M ™.6oZL™pÜ.iÒaáÙgÂÆBæB‹›8$L‰2ÅKT©R¨T©"ÅJˆÅJ„ lÚlÙ‚ 6mɱ»s%Íä°c‹‘ !’ü24—4d¹rîC ™86d†Ìƒƒ‚ãwŒo;Þöï{v›v›víØmÛ·{ÞÝï{Þ÷½íÞÝìxíìBé³Ë. –lg& 0¥ l6h 284paç 9ÁÁÁc‰žnŠ#0Uº€Î@Lr(`‘q¸Ç±[¾¬ ÁC“fš8,XÁ¢ƒo;¾LÆ —WiÀéÒh4ì7½ì­»Þ÷·zwµeˆlÁEË;6LpQ“&Œ¼*@ I Œ@©… *TR¥ (I 8,p92`¸0†öðlíÞ÷½¸ÞÀÞÛïa°Øl6Þ÷½‰³f͆ͻÞ÷½ï{ÞÔÑ£Fá³r80drdL€àËàÚܱFƒ%˘ A¹£4X±“D€r£ŒÈЈ(@raBEG©"NÉÁ§[ãa½ì6w³a½èÞèvrwžÒ@“º@’tàQEQEQEQEQMø8ìuìväväsäsG49 HæŽhæ‚G49£š9 IϦúÛBŠ(¢Š)èü7Å÷+øŸWöDB †öSè6ÞíÒæ­’—ÑRñg_¹{ˆRnlktýu×Ï:9?=Ï;É£äçµç¢r°/W°‚ªæÅu'K¥ÑÙϮܒè™]0н’Üg±r(” ™Û¹×bg¬Q¨š”Õ6硈Þäjˆ7AÖ§J}ˆ©ù~ÏÌ–opÏÍ[©O4Z3¥·w6ÕHÎ`)²1äëãÅ<’³€qmh»É^cÇëHÃÛ SÓC´Õ(Ikr "GfÞa¶ÓeÖËnݺÃ]Á9"òû_”¢lßü=G=Þ{oòù»qõ¸Þúž'ÑõÙ=oü¿O+SS4³÷;}5ì-îŠWâ×ÈpÜ3ìÄ ¤&¤€Ü T~Ï„àP^£ƒìíã¹Æy?ÇÔs*‘~‚0FØBˆ¡'ùëVETbÀ_ßZA~‹OÒß?Ö³Lá—5û±ÔÒ'. LRÐ+ò!C!öTBNÒSø?¯j´SÌÚÖJ Î=}[É(/x ´yµø'iÝvê÷öÀBf-RÆ­ÆãÐG–óYÛoç€E¶Þ‘ #>µ ¢qþ±’‚êynþ^;À_á~Ý‘|ÄS‚øGŽðßÞÀ(.øól '0b¶óµ®LÛwÜÞT×ë¶nþ Ïš|Ÿñ\jæð\¨%Ȉ>·â[QQzÜ{oò?—øý¿ó~¯’ùÚøÿÇé¡ô¹y±h9ÇÔ>žÿŠ9ë¿ðIiÕ8Z­ˆ@ Z7q&(† m¶ÿs`B>½ÛN±Ó¹¸ûÓößì0þ]zôŸ@3ãò¡ wQ¬™Ð´íg 7ÈPÀ pÿ… #è4UìXª¢´#+æyOAûsyûƒïÊ”*)R¥J•*T©2¥F*T©R¥J’*T¨åJ•*T©$H‘1Šã†#8‰¥£o½­è=¨­×–þ¿Us¶²%vñÙ__¥ú@î\6õGÁðZÁÞê{øoŸ¤ñ¥ø3n”ËÜù\:èHþÕ@L|gmxPZ¾uÓX䛿lüxµlØÌÞfæ®nÖ‡ÇB«—¡0!€Œ!¡ åE"$Bƒ“‰Ê&TPbB"Å ` =œª„ÞÜUrÒÁ•d£bÇ¢…np½F¯”ÒŸ8Hœ q)¼©ÀxùÂE‰ÜÚ .èí±Ë»(Ø’Ô>p^~OŸï~«ÿ?ØšŸ¦ðþ~ÈÉ™š@€ (ŠšÇdL¸ÆqÕª ,yœ]nL˜9–½~wöÞ\…ŠH¢¾ŸDtà©U‘`¤CþÁKËÅBÉÚχrÅÒ(Œ•‚¬QDdR§¨y©E'“%HÄ™ièHQúx™«-,•(Áa¨ ³‡\“ebÁHïJ‚2+Jn4´žÿÁp=ósÖ›E0î5‡<¸}yúë²Óø` pôÝ8« ”ŠŽÃ"³ŽÔäðhŠº¿;sô-cœc£2„ "“&D‘BDÇ2phÉs©ÅˆÑ“&‡c”±Á¢âmx.`³ 8pÁsfVC‚nß# ÃŽ,NðrX±CB‹ ÅÀð]ÂdÛ“%ËM› _Z☶…Jh±ÁB\šl`bB *ìÉTyC.hQ‚+†›šD;²d…瀂'êý¼‚£V 1ÿ¨Ðb YmAU‹ lIQ@,ƒÿC™½L ì–±D‡©·éùÛ‹ïÔ6¿c¶ú?Og Û‹ñrò$LÊ¢#Ç>UZ(ìFjAbâ©EšxC&ògÅ!ÇáìޭЏ˜aÔa¹Ã†Z\-ý/”ÔÀpŸ{`qwNý.œ ‰fHl“—ÅÛM†Ói°±´òtj%‹ ,X±bÅJ”*)R¥J•*T©2¥F*T©R¥H‘"D‰qà š›U4UÓI2ͤCÅû‹t?•ý½÷Qö¿³îå¹=¹ê\¼ÞŸÍ»é7o%µH:l$Èw'—¿èdý¬?˜S4à(,Îô¦uæ+êNÂà]tEY¦åØ—åŸÂguÜ—7ÅáiTOz6LAŸN¬ú8½¶Ùê›M<²¥LÂe×P^¹¶%Ša·ÖúÎðKÃÒŸ|ðo?-ÔàÅ$H±6бƒ …$F&8Á‰… 1"’,@RP³´9ÌÑ¡H²ð ¯ä\ëz_- ËäÝ =¨{=œŸž»¼þ·EN˜¶ª€rTLy±g^ŸMÅg3¥ù™“ eQɆ¡D‚lœŽ&â/«\b¬×¡“î×Ý ~T[×ð“z/ªè Æ1ÊÊ.A^n„Ô5‰ änÑQÒõQLT êÈ⌠ÁÞð/›Ò±6 =Ö6øI&¦ûÞâú—èrçêØ¿€Ï€ªÓ9w“½§ÓŽlÅ`Û-† ¦2ŒY覬éó®§÷sl&ZQÀ÷ûÀQ¦+ïx'`ă ±p:Q‚U°øÔT‚Eu0A‹5òög–:Üî½½=rC\Hº¿…ŸgþS—gbw{ÛLŒ1cbdp‚ dCzÈ((ÅÑwèÞÃ*Âm »ûÞÁí½Y‚W ïÒ㘈ɉI¦#ƒP+©Î—%ÀÂ*0ã—íP @ØÂˆŠ'¬Ñò°Ñ0îÂvÃR})D& ð±dÂ`ÎbðèÃ#‹Š/ýø!¦Ýùüî;t3J IÄݧNá¦Åã…Ö¿2ƒŒå:×¶fñ:C ÛÊüŒBôb$“¦aõØrBòñ”TPè 8ဠD z˜ŒªP¹œÁ.3† w¡3F &Üi)l¤paL-¶RÁ˜w›#†ÂmV- m&åÌ¥I¢@²÷ëƒÑ³p™á ,Ãà 2#(@D!PRš“æÀÂ<Ç0kļ ç»}M $>ˆ*‚Š#×|›×Ì8 hù÷k&fôÇD™ (ˆQ¬U|X€¦heM"J-)Ññí LyÓ’Ð&L‰‚æ „(ã&ó†£ß®Á‚´ey2\† Š”EX‘@H˜& Ë! ÅD…ÃGv8.jÆL’ pL;ádpLCïˆÃÃÛíÙ4LêX€æë¢!ЊҶð@¶ÿç\€V”( }Èâ,ª_¡ ›KDbQTÍ™ @Q÷ß$Mò€32¤o^QD‹ŒÄG¥]#ç³ÃÑÁ‹ƒ& H`î.âÅHµ%J!“º‚͈C2ããÑîþ££À:©æøL¸sa°ÎFÅC03—h¦á÷e•ÍËùÜ‹Õ |×E^;ÞÃÐî,t:—È=Bqàwðzªz†U+RT´Ñªz çe›­„Ô˜i4d¦ú) IA4aMh¤M6A ÔŸ& `¹Ôš¿nþ8.lÙPK—8,ŒU0‚Š ÑÃDŠ ™ 514Ú "(œSY„Ë}Ç<÷œoD «ZœM„ Û§Çà`ñ4´zué.„1’9,7=ņDÜØ¡è™¢šˆoœ&ÕØ›p†ÓcŒ™ª Ʋ˜1‰ìÉíÑ£)•„"pPdÁŸ‡*\»}C ß·«ÕרùDÙ¥L• ›DäC¦ $®Ûää!žr©C±©¼~2ЪLÙ8j0¢¢Š(FB”ÀŽ5ôôŠå+ La) ¸X¤‡£n D3 ¤rUȘ ”AD4j˜!i«ò½Ì74x'šg”1nYIŠÿ§ÏÀK×0D¾ÅÃ-ÃnMÂLÆF’ÃL4&@`%9PÚa©0‚ K©†¦Hhñ¦ÆÅH¢˜8"]¤¹ï 0E…ÊBäO êzÎ :NÉÐ7É%E$@‚tÑ™[fÍP.D×>sa‚A ˆfK!›‡€ÁК5 hÀÉ43FJ`"&¤AB”÷p°0²Ï”D0¦Ä µ‘ ˆŒ4Z" Ä *#)UQÅ Ëa+uõi*©~š:ì:ßÏ(u^FQ™±l¼køØ‚ëÌêÖ?Ãú·âÐè%lçxš‚à ªt£Çô¿ùò:_?ôŸÛhš>ócu¼· sÊ›È2s,±U@ $$dEdcA^ÇwÉž;Üxf€œ `HÉE˜7.AIJS)!çôM–šWÆ_Ââ)аj6ð8S‡›H²(šJENýï_±¶õ~“°Ôà¹Ñð­ZÕRÓf¯…ò0¾¤T¿¤¼À`Á™qÊ îÇÙ—$“ì@‚“bÒÛû)"¥É>"%‡(*TS„Pða6 z‰[D»ßÒÑ"k|hhèq¬vSˆwmîw~36‡%jŠáË@Å$Jˆ«z`F"2« ¬Ûצ‘ù6Ì9^ÄDõýqw?f»(ëå6=}x<ɳÂëzGÒË UlРÖ X¹“BÇ–6`ÙÁÈÑqÙ’åCEnó™ÁSjÍ3*yÉ“c“+—\¾wo™£‡k›“œ«ÜÛ)dÅ Šà©×§m(UŽˆ´…):C‰K MXŽ)åˆÉÐuŠ Š0+‹+µâ¬ùÀã¥5TÜüK‹‡3ç±óŒgpÈudÛ6ÈNDUu÷6nйoï?yèü¬&‰9Ë$+ß=DÆÊ:÷W^§§×ðŸw,yú}L]}Ù¶±QPÝìdÝÍA µÃˆáÍëÏö¿2¯;2ãÖðK£-°FÕ@ÙŒ{¡¯î’>#íjz’MÿìÓžæï uˆßî;w:³Ç %Ÿäù~l¾%9ÛÕŽiƒ)| ¾ù'Ãü9Br`ga”­y´ªDçPŒ£aVý^gùªcìu{_æÝc™cÐì¶z’ªJÉñ~»©6ü2ì3ꚤƯO×¶;‹’¡õýŸ_â°9”Hi’)Xc –ØÅT5jÄ4…ŠˆŠ¤Y?©Bª~»NW€ûb¿l˜}Cê– î AÒ¤’VAˆ J$F"% ,a— ‡¸éÐ\£L8 /§øÅ`ãƒ<|ÀÆ9,2`1¢ÄäíÍ®¤D H$’$H ¡d@Rµ”žŽµvý¦'DxFoƒÎ‡kÁþ#ÙŠ86\ÙØ-lfË2JVßÇ'˜Ï*Z0o-ªV¥IŠL`©B!2aAÈLX¡#@°(`±@‚0Á Ñî]ݪι—˜„Ù³UF¡‰’:¹r‡2‹Ò%ٗÛkW£x¶ë2ÇûºýéâOÍ{_AHE²ÚËh~P¡õaèOƒÞç€ ,‹ý¹fæ‚Õ*dÉqû¬~Ì'ÌÇã^Ùz©P švºväšSŒz‘¶0Bj¬1ì^X¿Õýêí‚’cJ=Tœ1ê‰ÆQtcdØaÏ´ãÆ!í`×G·S¯¬ % šCñ‡eq<ÎHÛ0Lä|ä½WÑóùwŸ^{|/Œ(ò>¨­–ÍøÄ¡ÔI@QS½˜,̪8c˜bª-J¬Z…D£Q•ô¸ªˆcYYÊÐXªˆgùßÄ??¡çÐÇiÜHqH’$9ÒPˆæC&A(Dr2hÀQ"9¨åHŒI(@ åj…j—Îe‰–Ø#‚9¡†,r9X¹B„V 8 RC€ÐrTaŽƒK"¬j×9C"Ä Ò ÄÃy¨Ê ;ÊóŽ"íÇTRã2ò!Ò—s—`ßÂ} ä·\Sm+Jm†`&>VbQ,a¢Âl¥=¨MQJå”4ÁW€¥¿]ð/÷«êþ¶ól\`\dp=ôD#5Ô‰#`mŒUžÐ†{ø‘Æ‚H¸€1r(]sÃ\Ó4Û=#š5ü‹u°lm€°â!ŸM5©²F @qØQHŒLa†ëmpL‹P‰CØMèæuÒwƒRÓmõ!2… ¢T‰ ‘–$Ë^FzÜ0»6QcVÇîàbF&p€Al÷Dhm»"97}pfÚ¸•!uÐÿű2›Ì •1!j©€¤JR0“@„ui@‘q1Ó7;·=ìxq{‚Z^F& §Óa†2›aDCÕMSÜÃ'ÍýŸp½ð!ŸÑ!úàU_¢X@JDüÏ‚qŠ‘b  ‰âi!aq#e\a¬æ°båŠ#(¥„;(ã¡A ©DÜÐ1% =ëÏý `©®.¶hf˜21&E1`Tºs°ì0¤6ü÷q¶ˆL š6$t’¸©A`É…“v@КˆD,Œ€{˜\ƒ¸ãJATa˜€Î:Ù³Õê–(bX± ›(l F$(¦¬N¹FtMƒ¤Â¡™7Ç39á±b„â)b(BÅì­W…ÓH”Bs'$‹’fE•fØÀ c~Ÿ™¦Ál‰˜*Tȼ½#-Á)¤Q„‚dˆÂÉIpô¿s°A5‡ë˜ Vä‰êS95"\!¦+°ã$µÜäJ(.º!bxè—Š–²ËI~•^ðzù"hu!ÎO~°PI Ä"‹ƒŒâ¥„qÇFa˜ÓG/*H¸ÌŽ9€Š(Š de¶VÒ…&Qèn ôH‹BJd ‡ÀŠiV&OEOc(”‹Ž ((>žì`%‹b¸Ùì²ùû}ß“|{Î^”ø:ÈUU¥á_/ìþ@¸_ð~µÞ¨.?—C4QHÈAÚJ Â(ª ¥úÇ¡LâWæÿúîÉõxû[¹áù<¼ÇûíÃãÓìðøåœ wUi <#Ö3E/ü¶Æ[?KËOÓø`2¡<ýÑ5ý5Üæy|3&c„täò@p  @ ˆ–´¤FîsôZüur5ƒ ‡ÓòÞǹÏáð³ý{xÿp_¥2JÖ‘¢Â¦„ ›5(l>‰ôŠ’*T¨ÅJ•*T©ReJŠT©R¥J•*P¨T©ŒÆc2&C€À`0²úÌÙß½öÿËôÿ§÷xœæ®hmgÚ»1E6‡Ä„Y‚ÑšaþM2X RÔ€OÇñ|?‰TÖ»º?ÇòhÜNk¬»áâÙÌ»1 4\És‘EG#AEŽ (B€£FæºÕÔ…ÇŽÓ—Äð™# s/d.¯zÞczøÑ•R3FÏSÆ-q ½ fT…IÎaXQ)B˜{-çØ½B "_Fm }ɬ•:ØzŒ*:†TÍUì/À7Ú½(±*ùqh^´ ¶¹°ÄV€Çãð¿#WLËQò>,WñU’œW:ZÿÓЬïò̘ò–º§ŽÞà?…Ï»”#âîïîü†ï#Õ $j ¢ÁlÁ@Ä•m!Ž(€#RÛ-dä(É4¨+ ¨…°ü\dÓïïáï\6ô{½ÐÕ™ÅJ0U¹¢®Y°Xö ¶L´]mb—.1–˜2`Øoƒ{w»†¢n+Dnp †Ð 9—|6DŽn‰Cgŵj¼ÝcXæôñ£”èÔH ¼IMV†(H©„KðI†–vƒÍàd7õ&Œ Á"`1¹XPü eìö½ÄÂTƒ’y~š$AÉ ‘b‹¦Œâ“9Œ¯û_¦.¶K\X„ã5¾íXb"½ Ï8P6”…Ä9%@¼Ò(‘¤ XLx‘nûÿ¾èA AE6G·yJ©Ž7’\:YLóÇ]s£—™œ6qŒ&^)Q¬g›7Ýû¹–¡7s\o(k* 3Š!ÆRÒÄJ( £·k˜0˜DÎæ qË1€´HØT\T  é•µÐ® B…åˆ"Ò*iœ[,àù©E0©pè8MÌH$*€‚á"Nâü¦‰–t§Š’!#L ) Ie—ö­¢¡¤‹‡*hutÌfLÐ* jk)|ž±”ê•Û*ЉR¥1ψ¥ëç äúèHá „3âFDU0`.Ö2…]rRÍl`aM.*`H‰FFÅê6qrRÏlRd/*8îãµl#éX£ ,TÓp™  „<œwh¨ä !]u¼!³±BfM·ÆZ̨¦ÐÑ#kÝÝàN–Ëà`)T‘\ê]ÁcQj,‚®¨ëF ¡Æ `½‰],‰51Åïx—îüøFïí'LšrÄ®†wôü£àT*f¨*¥øŸRMrª ( ªŽî([i”-q%I\¨±-¨AVÒhPR H(¬Š"‹Ü’ˆÃÓèñ<þo*ú\ìzpç6 h¹bçƒ.͹ äÙj¹e±cÒíËdÛ£ƒaO .\Ñ}†ƒƒnfLš6pgD5¤ÖpoxpÕ‘4sƒ]˜0lÇ‘8Ñ£Bh4 Ëœ÷ -gFG¥hä"^Zî‘*ô×(ÂZY¾fž†u¤Ãc·3±øœE'›¶Œ‘5rÐõg-Œ˜Diß÷z4Œ7£±¬š ßhÉ„CÇ™q#áfcãÝíüO)æÒ;œé®»9–(ÉC\X’Z£ëp —ƒÇ 6|µgl¡€“L7µëááÛÁœsà§2%ÆY9…å™AÚ™I!Ä‘ €°ÃŽi«žö<]é¾ÿØêu¿oóØú^ÓÎúÏëþQûý/²Þíø³roªæ‹£vôDKѾꜩWÁM”L¯ó9½Ÿù¾÷oj½ßK÷ žô¾L<J¥ŒŠš"`XÀ©¥J•*@©R¥J‘*T©QÊ•*T©REJ•©R¤H—¡$K¥qþÏé~ÛÏþ?ê|_Õöÿ“Ýø`z¤ ;Ûêe¶¡çƒX ËûÞâî^ M¶›MˆÊ¼%XZY­`-¨H‘"a@±B‚DˆáBd DˆL‘@HˆŒPÑb(! XâŒQ:ÜéÛ®iÎ(rªùIÊ¥D¹/bŒfbÚ™S3ÒÎÔÎeiHT™â©O{ó!ç¯ÏGUffo¶/“兀j¤a4|ï4‘‘œÝ}õ¨”°ð^„„NÍòù—)%êÉöºý«Ó¯‘¤QF>ÓEˆH7ϳ¡ç-çì¾í‰‘¹ k„0xœd‘‚§$0$ ‘ƒ#F,£‘¢EŒœèÑråÃfCƒpí †7²•†¤€åIZ„ŠÌ¨ÔpªVPœ)ZIÝ Å¨Š@yun$1GKhm.¹d*V ô:œÔæýN>ì⇽î>²’ð‘¢¥X¼ÿ‰²R„ÊšÇ"BŒéš J¡QЩpî5…„ÚÃ@ˆÆ&)®óSE‡ÓQTqeýZå‘RÄL¬B[(€æbŒÈäm^CÔí î…¥‰ w÷š1c/‰”ŠYŽÌq pwåÊ#\‘BÉ™ž ¦*Äq0¸±aUËÑP²)¼tH0Ø aוE Š (.”0YˆVuXô)B¤ ÊÄÆD k¤ÓÏ0ç2‚¹+‘àõ-“˜DêÜÏêïà¨&ŽÞ4IŠ•àˆå '+êæKþµòŠ Ûzð݈÷°‘»kɆŠx4túýÇqˆyøÌ7NîSÇ×N":(Ø´íÆú)ÈähÇq&T€ ‘.F-×ÕiRc” ]~ã($ò¸DqI5ÊŽ!2ëJ躕,DÄŒ­IÍN*Ö{Ð\ÉGR‹«ÊéÎ) Є…–%GT¦ž®ÆŽGpöé¹¹ÀñÞ×j1«âc³‹t2pv6Xá'nÛ$á!Û¥HÕËŠŠ¨Ì\éìX‰Sa °›¨ã—Ó"YB1Õr¿]V=ŽãcƒyŽL†²½Ä Ø ¢Fo*5ìõgÌoÓ}×_ïÃÅÿéûÿäÿGÓÿ^çßrîÿ–ôÛç€õàúóœ^I´ÒZ0É·:ˆ :ÙÀ¶ä@Á¬2qüª^×tƒÖ ßÛ(ÐB‚G¾‡£Ûö°P$Ëz)æ×µ,ª©RNÔ' ‘‡ H@DoŸ(ÅUþƒÎñ&®ß?ù¾¯ë~ªŸR¿OìàbddP™S"GÂ|£•*T©R¤J•*TR¥J• T©R¥H•*T¨åJ‘"D½‘+ý÷CøÝü$ëöN=Ü\¬‹6ÃYÕ7"fMt(v™w^<·Ë•;†K×jô+3Y‘Áa T©D AÊ @ˆã `‘ h Mkzž«g——»;PŠ«Eb¨‘ˆˆÎb.tÎ,«Ò95·wœ©j‚ãá)>e¤@-Hi ýí_à)ù­þ7¿ß1þoj_› ½„`Ñ78:AÜJ~טe¥î0,yÇǰgà茷tø °Љ‚!ã¢Ú…¢€ÊÉH ,‚¬0Xƒ$YTPY"¬,‡—¼¾÷›Žçß®ÞÝM…Š$Mˆ#Ί44P0P˜v,XرC‰#] @pPÁ¬!@p:§ $TM uÁ£G(UC–4` *Ru¨‘¨ª­^ËŒD‰yöb3ž qaÂÜÚÝtóÌÛG¸$ñ¨Ÿ—Öy±˜ôiG‘”²ï†‹(ŠRѤ+&e!‡ñ´¦2‹¼‹ 9 ñÆÃÊ 5HÒ)Ã4¬ðI–ÐL ¹ (h6X ¨XÇpûõaQ”2\¤i" /Ꙅ¿<±ã"¦d ÍÆ‘. iÌ ™*$̸Qj†Â€*“‹£¦£hß?§ M³ÐèÐRØwòò½:lv/ hIóå B3iF¹—*TŠPªãʘ ·¨r‚v.]±TQ:Ù¦ÄH:rýÆòlÁÐî1x b_‘8"*5ÿv]yõà‘q’ÚYÖ* «"5 ãÆíà³ÄmI”svïÂRR"š&mUˆ“6&$g‘$ŒJ 6.žAE€¤ÅxFÜ$9†e.ŒˆãÁVuŒ"WDcc†X”%rdˆIõd{ÈŸ8AÔ’†õ„Ñæ=uvóW:°XQ’Zg›ÌY“*†DH†v*Is½@’Š'J뙂ž±”ísɳB¥ Scbfdìecˆ@Š„$œ ÂȲ2=JæÇ#©±ÒwlwÙC©iŽ8”•r—$¤C­¨à ²SZ‘±Þg.Ý8Ý;™£d•—ÄœŒ‡'Ë<;.kŸHjM‡Kݹt¢Ä -7”÷l’Xòm¤*;gkLïnö:ò÷_â€?rúеŸbÞ½ô^ ’êp ×"Æ‘(I­ké(ÃÂJ"‹[ìÝùËñåÍ´‘yU ïSy¸¯¬÷ã‰WwÑ-÷å~ül>a6PJ°Màf€l(,¨ÅJ•*T©REJ•©R¥J•"T©R¤ •*T©¤H‘"}"Lßèú~÷ðÿ¹øL­ï!¥â%O‡È•èœ2Ï«ìd@ à•cÔ—³gØO]ó5fo/‡V¬Ê¢41¡Š† p 8H‰2¥AŠ&H@¨Tp‚’“¼œh<_œ®VÕ5¶WªAÐvBÌ•†ÎQdŽ rŒ<+%Ôfiî!TrÃüŸÞ½¿ž±ùnèýúUÖ9ÆjÝWÈ•¡¢9›þ¦‰l=1×ã2ÜEù ·íͦƲÁEÙ%^í»©ìö¶)€yÏ9z˜£ÄRÉ’&8¡"#‘"Dˆ¤ T™RéÂd¹{¹Ãm–8Ù£ôÕ׃jäÁ£²nà‚æŽà.p4(nÇ …H,*Õe&(ã›K¡ZNÎ1qB%ÄÈ ¢Ê¦ØOu00d˜X‘ÖB#|±!VÎî+ŒêêÂ( Êã*qìÂ@.–òrLMÀÈÈ™c$‰4°J¨@.)bx!QXQAdb$haÓø”æu:Åß—jnS·FçqjDdH:<ÄÀ»ª†t¾ñ (²¾q¼™y#ûÉ(0PXÔ±!-ƒ‘KÆ83˜2#,†AÐÄpÈ(HÄûTÂyH€äÚ9<0HœšppqÓdÅ@"Bf‰ÀÈÑÇãܧÖÛœ ™Ì2Î&dʼ¡#@PˆÄ`¬ H^N¹$R ! jàÐ(ÃÖ–P¥î`”ÁîñÑÔð4hoMu)¡sQÍ9›:î”Ãcºjtí¹z,&PUa…E Z?²ˆä ”ðV$H‹âB„QyŠ¡Ðñc@àÎðô@"a‘Œ(¢ö99é9à4VJ™¢´tW ¼Ã˜F—cÎ;ŠØ†ÏÝìs94kž ÛýÂs†ÆÍí×±lñ¥˜-Œc "ZXøÆ;ì¸ gœPë|ÿQúœÖ®§`ùÞgº=~÷¦ÿÆÎºÃ÷’TŽ+ÑØ´½ýz­î¼¨ÜaLW͹IÀõIA)^ÿ¬ê~<÷®êŒŠG‚x¡ý9 ¨Z•{ eB Š‚.;©Ä Î  ˆ ´ €Ä h¥F*T©R¥J’*T¨åJ•*T©¥J• T©R¥H"D‰ïüÿÂÿ Øãµ1Ó=ˆª‚é `+Ö½dF,läBÖ£~»êœúÝóBW Õ»7Œk9ͱ+Þt,!³fÊ,d¢‹ Œ@#’‰!È• X0Ά«*¹3¦öp·"÷•()@Œ|u: .³Nh[tIãÊ¡dMT:ÀëmàPò9‘œ)JÿíòÏï¯ÅÛì·ÕwCEUTÅâ­Œ`¢…÷ÀÊ3”Ÿðþð Šf¼Íëñý¤×ƒ^pEUUÓ(fÚi,8C„Ȭ©2Cg ËÒÜ6`±gÌÍÙ§f›cå‰H2HP"%™"$ ¥(Pb‰Àc‹%Š2¡—& dÙD&nÌ76›2mÞ!œ.\ÐlÉà!},+³GoE0X¡Í1B( ੺ó)ö0Ñ´ØÛñÍÎéçf‡_ÈÃ9]×,¢z!†t;ŠÁÀH¡ÞûÈHÑÎÔüôЗA†Ìåq'Œ7ÝEÍWXÅ½Ê QÈÑ£©”°ž Í(9Y „‚¥Ga’B)(Ä,•Å,XäkrÆÈ™%óÔè`ÚG†r:hRu%«Dé†ã&  s4u9…šBŒÂFרã%äKJÜ“vÀŠu˜ ¢e uñ›à›š;ŒäM„œuzjùÅõc¯RôD¦Œ˜¹pÇTÃ!ì°-B8HR.{Ë€…&I]_å' Àõ9¯.½Œ* JŒSt¢º›˜s;’_¯MÑ@ôíwuqÖ*åÉžd®†ŒÑªC#r,0(¢Š”Rß½bâÅL¬`P¡@Çfbõbv BŽp¬[— …޵.Ï¡ŒRC*?’èZÜh`H€4b2°¢TS5ÜJtÁ­22‹Oð6Ÿöõû?ÿ¿ò¾—ÿ}ŸïdVQ¼ £>‹‡ ‚ `‰ghÓ¨@d”hYi xÒdî Ã|ÿö´±× k­ƒMaLëÎÇë¸ÁbÏófFÊdžÉôo´9•aAÉö‘;Àq QT`b¹ïñu.à þ³÷P`Kֺ–¿˜û˜±{œgwáýçýîÛôqª>µQŠŒTrm]]l& ‰tÂ÷,*P €°‚Œ‚Z”Dó`5» Äo/½íû­¢@“ÀûØŒFa÷‚~Ȩº¤  0ÑM“>Ó6ÔYH”¤¾&§6`Ì9÷Sr@“ci…b"*æJaZ!g½…–@“ gÅK4s}7P\4q“´ †ŒX(ª 0 S¤–U‡­‹¶ ) À ¸K’!CÝùm\4Ã#ï ,ü¿ìr „!vŠ!CDr8)á´Í:!“cFÉJDL*90eŒD”¢`&DÄp †JXØa¡˜Vd¶YebňV9)DDK0f­–he)ÝÅ0ÔFn`$³ÔzŒÒ»,‹ ¥(yµ4Mˆ“C OŽkžä¦Å” –!JJP²‘”76ÂkK¡2S 2¬,¢tB˜Xƒ)D¤²­”f‰†”)f(3PÂ'CÿxL&¦ƒde«–Ël²±†L00¦Jf.Dfy –&[XŒL%0Ã&0*8KW„˜ †§°¥)Jj…ÃA¤eÔHÊ¡”,¥)=šZZjx•Ѩ… 4††`yÓ › Ûò'Mà Fö~îå0à'Êú9}þ|wæ+øÓB Ï T[·<ô{½±ƒÊw·}œÄÏïwSÇöyq÷7`¿Çw¸n«V°Êi»žœtÄ‹Ùfw3‘É{§%Ø4E2³j×9Ê[Ùu§g›¨ºOpýQð@ïÐßÍŠÃIb<|ÓƒT]Ø!P.µZFýœ"º¢Èíu›dvºsbL¤’ ¡B²‚I” aFQ Э …,Pèš`@ÿmʉ")¿Šõ]ÂáòiìÖñ:á¶y7üþo7H"ö„$Q£‚u<ê€&Hˆ¼–MeOê¼còÕ§¤>\†úŸNùÚ°ƒŸu6½b²_¤€€¥@@áþ^wË«óÎXèxÍFd÷Åû'n¿31t0¹‹ú—Ï žû d°[-ÛêÅœÖûŸ:³$• Ø.‰ZXô0m{–»mw+ÝÓØ½óß9³]Lý¸Š‚åÙ¶*>åMjÓW–¯ÎüÏν4~ÿøx,Ê«—õF.xB0iÍ’ý$üíK{sdª³ÛµtçïÖ{.×ú'¿°ó·Ô!i–¡ºË¶ ‰U>\Ʋ±’à_£PwXþûßeuIcø-#õ‘®Öð©†MŽm±r‹RZ®wÙeVcŽ-h4‰ÑöEÿSú¬zg™á­¶ÝiÑ‹øøU÷~6[üŠ™Fˆg28®S—º‘§&-qü\‰3ÿžm!Ï(>±lpãTºUå+NèeE“G£ûO<ïcð®±;ógwLùHÛ†kLmНä{oÔïyÕ%†|pº8ÜÎg¼¬ú—UÞÑ‹.mº8`êêaÁ¶=| Ë w`H€¯å\}P”°WÓü¬çts’͆³<6Éc"ѹ†Øóƒ Jg.žçØ*SZËÅÙ—D-ö»E€þEžt6Q·-»oLJ"ÿ&|ç„æóï(yÔšóAÝ[QyáºÔu¡¹dê¥6èþ· Ï®6^¸ZÝ%mîy퇆Œ¾µÃ¶yÖì-H*¡Ñ(m”Ôº½rÒp•ŠÕ7—å†QÊ-÷%Cm<ŽÔ‹Ú´l2’ea†‰°Ì©æ*32¾U·GššàîŠS6„GnLL¥6¹“; ¿6BM^y.0xSs´ 2îïÛáÊ+y?<2æÇ'ƒ² ß^J£M9—Í‚ìÃÝ%küت¹Œ´Ý¸óF9±wÜ빪ü4‘\ÌKàØÂ5õ®oC^)žãCz£ä°‘"{ˆÜô|WÊÃ]FY0&J,p{Ȫª.¥”¦ËWÕêö=Ÿ. ¾Ô¥/ÏîQWò-ZÒÏóyùò]‹–$¼ÝkNeqAwÇ• ›J¢q¯ŠÐH.iÖ¬c¥ŸÒr`¢ºæ´žgÆ¥Vy›°øFŽæãz‹Ž•3|d®w65à̇œÃ\ü7Ö=c¡zŸ¤CUASòð^=Ž~õüù4vé[\Š~\!Ó\ñH) Îê·<á>ŽËv|:{–¿´Ó7ã§dR³ÿK²‡eaßÑ®ËÿFiwø==Kº;tð;ﯯ¬å.L‰—;:SÎy˜ÉH„!  E€õÌÀQ¡AvÊ ¤ ´eÀ T$Y é=ʨ”Ê Š VI’H¨ˆŠ±Eб±TXª(,PUPQE`¢ÁU(¢ÅX«YUb‹QEPUФU "¬ ªˆˆª¤‹AT‚¨²*‹"ÁU@Y "AŒQ`(*‚©R($d $‘Qb‹b1b¨±T(*¨(¢Š°Q`ª‰Qb¬UŠ,ˆŠª±EŠ(¢¨*ÅR*‚‹$$QVUDDUR Å€ ªÁTYE‘`ª ,‹ Æ ¨°BIBAQ:8fKbs7ÉxfêyS=˜N'¶ÞÜ`š3†‰³Êº&· ªî"{\¥_ I•e€Ñ_?¿'‡g·;fªÒ¯ŠŸ7çD»nÏfâúpÛ %ÓÎU§µ#¢dV0}' 5þê¿«&¢Ê…*Û™£ÏgñNÑÊÚ|Pç´­ó±Ë÷Æ]@Ø,;{ Ô8pH²L‰KJŠê˜˜0PH¥¡(°¶‚E„X)#++ï›E‘Ä ˆ Å•‚Ê«P! @UO½…SÊÒ %ÏÎP[””ÎR5…IˆTY ${8UP7 [(,Hƒ""*ŒEb °R"1(ƒVÅE’(d"É@’"Š*ˆ"‚ÀHÅQ,Qþ?ò~0†”K‘ $X „€?¦(-HBEXÆ"Á¤ƒ@X¨ PX °QŠ€0@ ÚtbºÀˆ'ëî²ØP[ÐQ" ㈠҂Äü.{éüMïÛî7ßé±Ðð¿ò¾§øè¨¬7ÖBTrFñ>ä4Z^°¤=EÔåòWT€BГÆ€a€a€p‹•!ƒm\ÙÏAx.…ð")yáyÛ= Ü}8';Ä*5D¬¾r’  t~$DôP´<†[ãÃE{uÝ €Ž ±U@ÞŠ Ûz±ˆA¨EðŠ3qAg·òà6(P](,Q(DH(, ¨ ;•€‹aAbYE(AD´;NèQ ÔU²‚Åì YAaÝ(/(,PV”W 1 @DD$ ) AaP T„¤` È,U É$`¨AT„ (H hP[~_J À€–OG ¾t ™B´P»<óÖóÑêîñÆâäÚ—Ò™³ÅR¦"_3ð·^bý¾*ã°êbI<;dáßÀ°œyÊ;\¨˜°Š “z²»¸æ+ÁAy ;®Ôñ¬‹ä-ÕtüÏÖïyqDO×¾¸þ3Žzß|Hõ°géÁÓà·Ã^JµÉ­¶£³{]¸ŸÁX v¨€‚R œæžÞ×Éûp^J?1KÒÜÿÊ~k.Ó!ª¨„b0€@œ$B4eÓ±Äxx¸´vT™qÓ€i °Tòyí}"”bßäÌ_Bü^ ~‹d Žö@xâg„Îf9ž3;¤å.9,—ÆI(cA`¶  ZË.U2‡·+Ãt!­Ûujë.)ÜŸFù£=9[þë¼>Ò§aï°òúù©AwgC'hôýÅ î¦Î»}¼Ò0D_@ œÍ¬e,fbeº×ÆPx˼¬Å¿¿øôëðàòÛ­œJ'Tž—©í3¸ïÿo9ý¹2m6f¥g¼ýê øÙ¾Í®í1½å|ï  óÊ ®žÃî$›Ú’Ê r‚æQC|´÷ŸWª—½Î÷}Úx÷á=/Óø GÖ^(/î Ž˜Â2 €‰dbÄ Œ@ˆ€ˆ !$D$Aˆ"$DDA"@éÈØO¬ÑÙô%Ý„^z`-ÿ8j]6áüžÿ…„ ÂäŽ?N¯#ÝßÈoœ—†½ùf=/iANcäÅK]×¢_zþþ¶Ð“Ô:;Xa mºý?‰àuÛ·´P\\)ÖÖÿ…Ó7Áél}·N— ž0N˜|o¹å®ÐÁA0YÊßP[½s‚9ñAA<¼@b*yXa¯ø!lÒ>¹ ù*§^w»„;?Óî}®¦;UDìOîÍÖ< ®AJàR‚ó8ÏÒÂâ±(ªô~8ºbDŠ2Q€ „d" * rˆð¢!È`? (îs”èûŒ^rõUlñ"Fp-S°×äî»´®ÖªÀbòí. m>ð×ÌÑþ¬\Þ‡M¶Ty;b|-UUb|ïÄüÓZ=oï2‹Ëë}ŒÓØî¦ ̪ȮãÌÖ—D-óÚá±p(È ¼w 1I6.P_V ³åTt(/b@’àÈ ‹Ä(Ua 9µVwŒ0 4)HÛR HoG'ÌÕ—+ Ô°sÕ©êQÔSz= ßÎ c´î‹í®ü›"C׊¸í$ ¢x< Öæ—žò9¤aíŠÝX¯ˆ €§ñS| ‚¾nŽ+úÕ«Û¹­jª¯Ñ,œh^=Îqcäj—蛨a0Âòuš¹Gh $‰ŒŒ‚IR ),PY"$€ŠÅÂ(Š)"ŠEEPRE’(EXH H2HB„¾ñö}Áyî>¿œï?½ÖÏÝ P\r‚îDPŠ ¬!B*(A "E@Oºtp]&9©;d—¾ÐQ4¨ ö^°ŠŠ??H7¦]ôLó¸:**( fîÓ «æP_ âAÄ ¸U_ØÝûk*¨(.=rñÞG÷uö·7x~{†‰/Bñ’ÔøéÉzwI؇Á-AãyCÇÛâ`•)Y5*ÒÈxÛáµ³;Ÿ]ockªë®áFÝ׬V’ìF'ýü÷ͧù¿â¯¯c+ïe)žË¥6  õ-ÈÉnZ›KS;Ͼ[°Ï‹Y¾4Ñ^xd Óa‚w˜Õx¤J™M. o‡ÙÝ7ßÎM¥k´¦Ô]6OàÁÆhæ×ÂÿÐCïæÄ„!`„!6ìB‘UP?7ÔIH‡j…î|O ñ{ôùŸ+ÊzÏm—À÷€LŽ‚‚ù!DF #z‚ñ˜ ¸ihPYHD„D¡b€P4 4+ÔbÆ7ªtñUDà €£aAùßu‰Uöü€ª‰ù~ÁA|%óŽ’ªy_K±îËÈš¢*(Cã`Õ5ÕT†vØ gý5Bß3äžÝï'¼žƒà½hc[Âþ -á þ]Ÿûy“ ¼â§P½â"¤€ßn®%ʩݯ]5.Ía@&¯ÍiÃæãOzŠrùDãg4±üž7û?[ê´ÿ嚀>Ä;'gHùžòÿXù⪥iʪׇìïæ»áòÒ³Ç`I3?:ôØÚ|pŽƒ·jÆÔx¨¬\"íFi *Ì 4Ë ¹såÿ'ãíÎUа€/wH”‰ð>>OœEÖPƒþßÔ‚>tÌ ¹”*«¯Õ|ÿ:þ ‰A~ŒiõŠ­(.r‚Ü ¿„;oIêÛáoÜ{5Lóßý·ZõtMÍ8.B”º{=䟇dÃ.!ã}ß`š;ºð% @ €°à^‚B “ ¸«Ùw5ö:¨B?…ãíü7ÊÁªÂOîPc]Eòô{súó>)#5ôuYdÑ%€’'÷¼®rF'$ذ0 ,7ˆh"t…ÉÛ¼o ¨?Õ¡ˆ]b @´J>ÅÝè~¿Àè=Dè*‰ZÎÊjOÚüÑC0 ±:å‚@†ye$bDùê﹄Ÿ¥;oÏžèdÄèf«!v³Ðü;oF)ò\1¿åú^×ùþO®í¿'÷|o3ë÷Þ׳ünwò?“ô]èt1UDŠ2 ±ŠÀ@`‰$’EŒ$„dp#Ëí<éØª¼²(€¡ú`8ü?2õÇBˆˆl.Ö” ¤à:0N¨ÿ×}»4½ïàêg\(.{˜3e:Ù˜®¼è½ò~7à¿$d„#·A2pâMŠ$’¥,EO†×úš1S-þ)ÎD§Æé!È(,ý¶ÿ>ý9?@f¸û©'çÈÎS}7n#8-Mн¡jªªô9Ÿ­Ï`áßó?Âý¿ö?ìù—õO›³c˜'¼›ÜÛ_¯‚Ï×ÖW}Ußôk¿‡›dÛ¾¡w¯«~þ°)ˆN»`RS«¿O»ýƒ¸`‡C 2<× §7úÚü=×ñzº{?UÙÎ*@E€B Æ—Ë2"–¦¢6„"U3Ós#œ9ξ>xø”7¹n'©Ó.ɱ8ó¹¦ü`%†Yd¨™Súbò)Å—ÅW"„K¤0v]OãE|J>ÂŒ8Ïâ Éôÿ!p‹¯ŸA+RÄÛñ?'ÖNk¹ô7™'à’Ià$d~€) á*MgQ€XOŸd…;ìÓ™Ú¦óD$a¿)'J4”Ö´§òÿµkz×]®¿Â{]íóœC—Î’Qªþ¤*¶x3þ8e·Ê Š„¶hŒÌßó¸>ëQ©«ÑTvO-~¾ÜP_›¸g×€QP(ƒ" H²à£À ¶æ+w6ÛxHWͺžHPS"¢‚ìU°ˆ,P^Øí€ôæ×á ºÊ È HHq‰‚ä0oQD ­>Ò€'ከš"r}7ÌÁ”t›©$&Ýi7´„ x„'·™²Y÷„ÏE=®e-²±?ÈäÜ^<¸'¿üwë…¤øòaƒö½á¿À|‚òÚ%%nlX•CÊy‡ç(Ì`vdÉ‹¢/ÏP[±bïLüÚØ¶ß“H°a^o< kåu örpþgøï¸ßÁ£ÕûïÜìe«ÉÔ9õºwÚ~&”_cŸ*­áˆ]wvæBs$Å>'I®Ç½©wzŒZx^ZPH}®ØõÕ€öMnÌ’$«S«0¸„ˆdΠm'ÝÅkAÅEN4ç\9ºên6|€ (¬í±P¢#Ô*¨¢"Õª( ~‡áx´ÓýÞI´íý?oºó7ÐÜ.¯ÝÛQ·€mÍü«uû‰ Œ* wmA »‚êÅÜLR´\.àßUWúüy¤}/×ßu¹Ï€'êúoÓ|{ßߺ¸ö± è‰ê=d´HŸ¼ÿÏÓ{v:ÑûíáöïSiÎ8O…Q 8ÐÀÈB³!Ìx?˜ 2Ú¸8ŠóÇ“äÍJF·Ïãú½×¸ý{ý? ’ÚùO½ËûoÝÿ,Þ/›Š;X,z¥è ¸À»£! çç|k¸‹ò8ǹç ù÷®Q:ÖTDyî|æûÜÄP_/ªíÀû_›”íÕÏPX‹€U€¼/Ñò¸w>å‹#‰ʪUa…œ¿ÄÝ\lÎg‘vÆ ƒ)Ñ^õ{f®“<ë«pU¡aF/m ŒF.t?” "ˆ€ªPɧlWm]®Z<Ãï+3=5ŒÇð¾{UGõR½yÛ2¸uŽû–ŸÓÑþÅÝ×CÏ<§óò(ƒë|0äßæý½ŸH@q Ðmýη¿€G¤DF•TEp¢ŠzKÌ‚*(sþ/g¬è¯AÀ ¿éÃþ<>ëÔwÜS©z2'à ‡ì{Ó]î½®³RûBWŠX2B 8M˜™8ždúË”ÿÙÂrè¯%ó{X$Ë3âCFówÒq!ž ÿ:LìÉÅ!‡OAËŒvàd¨0 žE0!B0I@ !"‡ö~^[±n¼>w¸„#¯Ú¢wªïõzœæ@çœ=’"ÙX€õê‚™à#›Ì qUŸ‡àÎëá(.÷#¸þÌÿ¹Ýx'¢úýEyC±ò€3ð¸¾ÿþ:ý¦ÖoÃãwÖ]áëï-ºö¶±ç'‰}׳‹ä2áúöœœÓ†7ÞŒ5Dª,åó¾îèÎÃ!ä9}:æI2/:d×Ö ì,] Tg {ém«‘Z ¢$žlªBä§úÝ_'ð¾žùNÿ¤þòâ÷>Ãï|ÿ)mn?_ê…±0[õGˆòsA~Eú*$¿ ɽí퀛]üT•Ë¿ú¢zï¶ðy¡-Ò$NjPÇjއýï1”&!qW;—`u§á†8zñûþ…Ì0ɃÀÃ.þX4mÜ ‡rÀ¾Q<§ŽI`¶à0àò…ÙûQú‡²% Ga¬º{Ïà˜AÛ7x½üoª'&\úÑ—Z–  .ÕѰ‰BOL€—Åǹð?ËØ™W)Û%uÃrO¾(À€ \€øEg‘*ï–ý£šßêî"/ µæo5®6û¯Y®uûÁr ïÈ;Íѧ)î ÿÕáæ=G»@GÓV¿¯éŸÜˆ·Ã߇Ï@¦ÜúY…ve‚†©µ‚›D¨!Í\rº(~÷©ê´q‹gêŠ~¯·ï<ï£ÏPÿ;œid_Û"¹•X";A`"‰Q/"‚øÐÛ{DlŠER¡à*¨ñANáPR PX"  ¡A€*=÷–A€t™Aç5EÆdUrT=mËÁÛã½Ap(/ŠÎ/{­TMèZˆ¢šØu~DPÊ ¢±@@ïb*ATGhƒÀ4Ó"‚è¾%Ç–ÛvÿÉÞí0^‚.jvÇYÝ›ÎR@0ÐWñ]/}Ñ¢Ô-²ÊZVZ17ÌhØTµ°JZ¨¥žNe5ˆú'îoä àu8È|‚ój ÁAq–Ï4 ÛÀEæ¦5 ÔðÂq nD@`êiC´Ôé*µþïFýEG7îä׸‰™å}ØÎ7l¸µ…É]ë‹T*&™â@öˆ_… PkE¡-œS*ŠþAáÀ1õþ>D¬“)Í 6ÛÚ1eP_%nǯñq‡X O®_®ýÙ^eßÖpÿGËéyîæýoßw¢‚ôÊu_3‘'W²(¸z“‘ª?+ý÷š}û~ïù~ì_Îv}.ë‰æ8ý_Ÿ¢…LGWù*PŒíï¢7y¹\÷à•aíwa’(ºjQMR;Åä€a(9ˆLB. æ;N\»Òz¿aû|é~>y¬ò (‹ú9ýf÷̓ö¿éÙbØú~|8Úä=÷¹žúª¨¢u$¨y˜ðÌ¿Òe¿`ù¨æB[$#ðG¥"ÔŽ¨2íÑCþN€¯Í$»ùÝû|ÇŸy&oQÔ•>Üî þ¸¤]技!WI2c¾!­özÚ½OÓÇÛ· ¨÷§‘RÙ'9ÓLöôÙx‰N9+.ŠzÓ‰QgS Äÿ!°Ë78®æWridÉ¹ŽªbÀz‚É»C,BœÃ<ˆC€€Sü%‚ÕpÎÑÅ:Me3{¸\(9Ïgåwö×õø¡ä œô>ÔA='f àûocòL?éôzo‹ÂU>;Â#fÕÎyFìÓ1k±Nõÿ†Ãu‹âÞÑøOØW~;ýW½nÃÇQ {wÆýýöôoŠÞsÎ}>מP^wuн/Bô¡N tÍÂYÅ77 Ó±¾ô¾ôºÄ.¦ë›“m?‡kö­·ð³ðš å¨ð¸Ê…»i.bB¿t4 œE,1ÔŸ¢ ùòOÄÉݽF0®äÅi`‰Õ\¾´Ê±±âl"0D !‚O0ü€ ÇhÉ 6·àLI‚Yoü?I“,@ óßèÚ&Ázå˜ä<‹ƒ†‡Y°ð@¢#»žÌJàg{à ‹þœ~e‰ãeù­í¿÷]xÂâ]ZBß§V‡ø£r{¾H‘  ¼_ªˆIN–Àx™Ax¡'¿<…Ý×ó½OØâIUt.’~eV,òþS:Ò¥TÀ0ç`» í ýƒåÃd•(ª’kÿëø7˜Jû8B«³jºîÊ]‚Ÿã9ëËïÏŸö/oE9°GÑŠ–ÃÞCáL: '=îΚdFæAýÈòXèÕÔŒ46×ÈihlM)w©µ÷àØË±‡ ‰° ì+°%Ùý¥lÍ]hš4a°lл׈à©6'Çì½öêýµ¬x«jbm4ö´l¨ìŠ+²& pÀÍ8”ÈB„Ö‚ÅN øÛÝË‘ò8úM4¸MÆ£ïp 舛Óx„I(ʈZøº.}è^åm4KjÖHʵJ¼‘-óçw}á!!‡~óß*Ý—äð~Í ü[Ö“Ogü;½§#ªpv\ëªÓ”ÙûF·CË4>/çaËÝü#Þïû>ÏÂÀ]3±ZX¨‹mÙé{ï›ÁÿŠïº­Ù›TaÜ*I‡›ïKSÕ»ŒRu”úévþë²2ÝÿGésC@˜vÄ&Wwe¤B$ø08­y-7LFPAb¤Äc;²9!Žd´8\ÚêPŠ|0!!oqj™ß…¦tî+©…ëG+ÍfôŠ\ pˆô?®ì`׈&[È´@<Ð`8 k Äp•Ûë+Øz¾N‘;ÜY[†vÚf¡¸Á .Þ]ÕÚäÚYYó XÈÊ<üÀ™.‡j…ØÉfŠ~•ÔŽxÁŸ¾æ”! ¤ Ó %\Î7ù?‹}Y™`ìò‹Œ_óx¶6äñ[—ãXq£ÙFÊ›‚üßgì'ád ö.¹0×už½ò4Åá›´þ/îwçwµî‚éÆ Ë¤Ðÿ!LÊ4µbKöçGØÖqìþêarŸ~ÅÏ‚Ž`ÐRXe0¹²\R¾Ê]­5²†a™Šãr¹•2PÃ3FÅÙMd)Œ¦Íb ` ­¶ÛbØJ;DH`¸ ­Bˆ£‹eÈÀAÈØÖ€*¢3I€l˜`0C Ô£?¡óRt§>wè¹Ï|u›õ ¯³…Á×6HÁdH’(!‚ ÉWeÀbeõ4Ð.üRLÖwÞõnÉ'1#­Xܶ…gM!µã àïw‚0»uSPLª‰,€BK-¢¥ÀlV”4ÔKq0£[Tj©œPã[íÇËåÒ±Ýk°S‚'¯öŸ·ô¹þcóôråÎÊkÆ µ’U‹I1‰$1"C¢¯À™ Ûä€4ìç­Æ¿ÇÁž°Šù¢|Ó8üÞÝ“VéÕI•ÙS½¢õ‡r’ t«éÔÿ(ç±Xè-F¾VgÑ€B€$8Àà àf æ“)ŠÓf˜0m3j~”C66Ÿâàm­…S ‰ûå"Î+6A$ʧ#@4\˜}þï¼…¬³&~yƒýï†è…ýþ5?§ëÿsï}è+üN9žöÎ2jqÀq PübD@œìW;ÿXRC5mO(ZU’ï\»6§´­ ðÄŒë+íSòóå.*š²\+º­Ž¢:kàîŒc$8­0{ÁÄÎ.’¸Í$Tƒ:Hç¢õ8/÷ 0CÞ¢"3o²D• Ý:—@Æðkö\qÁÀ(ñ®yÎLªŽŒ¥P'S@…Cì]u€Uª¥j*gaáõ͇Âôü(þ ±ÊiÐ|{…ñÖ~àÒ½"‡k6”ëì”ôaAÝÇÒb¦Lû9ê Áë ;þvI:GªeB‚!KJá˜H–`[IX)cJ%b…QAA)’Ò‚" ¸ ¦H¶…‘PR¥,­c!EPlIbƒFDb¬4ûv{I:øö @Ó0ïƒqp`6°xæXr<ëFãö–Ç ï³ÂçE­Î…)õzò’@’ú ¿:ŸKÇßÀ…Y}cšÃý…D@DùÖ’³hމwýX—cúψ¸M›Ùy}Ö2_I$ÆBM5%„Ÿ ’]$E?Úûnkæé ü䘥ƥƻÒ{,`ó’Q!I$}$Š t(E ïZ$m,”t¥Îb¤–÷°a'œlô‰ Λã¤Öšll#«jøc²êgKQ®Áë­jøYKÑ©$„x^¬¸ Iؘ vðv+ Ñêe4fJôœ|êë‡ÏXÚi9Ó1ä|{;ÏŸm™ÍñÏWšÝƒ±œŸI—ÝIㆻ0û0ÕÛ6m•w¯âªî3M#Z·{*ffØ"¸a„nºçºÌZk¬#Ô†ó +^z78 PeIC@¨ÍÎeCg#°dùþ¥ï'ˆqÀp'õÉÛ4£©xÀø%pLbÂ@“SqN‡%æPæ_Î1’Ž ÷Žþb‚ö “}(P\7tX]Xb+ãôÿ‡êý—Cÿïòç~¿ ôÝ(Œ‹ù…Ï9·–ÓƒÀ‚IGí—J‘ú¸ú®b©’MÔhç°±8¡" iÙ¢ˆ£ Ì{'úD[ñ„]¬»*óIõiX[/…J¨sƒ»•÷3T²¸Ý˜–dÄôZö‘ó°K> ©~¢%Å*zØ ¼[h[⦶†Å„ m‘òÇÝ“;w€½Ç6‡Á° Ï¢¸ÀŒÀˆÞàî‘z„kܾbK Äó6Œž%'¬Ð‘¦Y*Iâ!°Pwyj’L¯¾7¯ OdÁSDdº†»‰{nÃýt×M`S™H$¯¤“GÓž«ämÄŠs{ì~?ä·šoèýîæðÝ“N:B Úí@YûÂ@‘»nX~j ¬*µ³Óü†ºÆÀ8‚æSt6–PÂ~²ÅQDCú©ü}ºønm5¯õ›l‡åÑü¬‡™?«¨S«Î:è1‚b¬Ÿ¦ƒû(QøÚ?C^¾¿'NkÅï%¯¯y a÷2¡"Te^[ÓA0c›kMÚvÜßò¹ø˜ìþÿÑÄ9—)êî¦],v°ÌÆn: <Ò_à{â‚õ¾ÿ‘ô9ö2†P`ŸƒóºŸØ÷œïGÇ÷a…+&¡Ä=‚ &õÑ]¡°ª n~ÿÿ~‡vGsŠ…®B£œt½9ö¦ç–$aµÕ&kò6JUˆƒNî&ÓÓŠ ‘zƒÐÈq…ñ¸ÍiÃsƦ¦ž©ŒqÊ"S$¤¬•ï *©¸3À³VTe>lì³q]QAx¢‚È ‘0–9~09ÉŸÛb9b`'¡ê'ÝÐûá˜Ãú1:ŒQ’1F# ±b¢ko}÷="ýÛ=LŠQ£?”e ¼d7:˜PŸOºžnŽÇ1Êwò–ü8À„ò\Z&Z@MÚ14ùrz’m…–]m K¾À•¡ÈƒFhÈBUXP-ö:ÅÀL)‰ŸÑñ>æqlc!Ècö ¨<ÚM`†#p?—[‚% 5ಂÁ9m¾Rk)ÇyÐÅ´\«”Š IµË“)0‰µÁ¦> `r!OåðJ©€p!,ˆ[€éÀ†è\Ѿ²`ÈhÑ ºa£`±vû•´½ó{ÑŒ—Îr–Ž”f0–³‹¾Y±”MðÀ—Z`mºæ;`Þe36Á·ÍLEÙFL¡ %‹Õ"P ¢4UÜ’CK]&6\`9%ˆâ®(ÑŠ d)Š z¤ŒPZ­]BN1Ž“}f¥Q(Ñ!­q©hC&¨¤Rbn:x3}ì{S›®9‰ôwkʽkÜáAr˜°hÁCD$ˆ]Ze½ÂűlT»"@,MØ«Æm82bÙ #p#*-Ü` ÓæD œˆ\Î0å ¹n©EGY¬3PD¼÷7õO¸]Í ˆ,(XH°Žø„ß4–ƒdÚB!<)‡È“N’$ž@w½ÇC½]5TP\.)(“À¶I=Päx0ôv¡jŸ†Å“?R€† 9¹?‘$IyD]7 ¬¬jèèîïª%wV×)5TBŒÇ*QQ”(‚‹R ½TJ1UÉ@¸6d&z;ÄݧPg&å$!,PMéHCŒ àœ“+æ¬I1ª€€—úI0 ÝOa5s0œ”DÜ£ ƒÆJÔRÄdÊwYÍì…f®^ð®R+º ¶ä(.Ì&?™ú8Þ÷à6æ‡LÒÉR­iIXQAH²ŸB0OôŠ¡x½Ð´[@X@!T¸:%*žÏX9¡òà|‹ ^w/Úüb2žÂÈeóG›ÎÀB3T >œÑj ´ü% "Ÿ6îÞÐ’B!òïa 䀑‹üQ»G`Š! nmuÈ7¤i/ôà,†|÷øÜ™‡+~åGa”$ <Ò&Óîý^¤gÔ{d¶± ­ ˆØˆXxRÉŠ`3ã0ÀAL§vS ‚i²`Ÿë²––ü i§]w浚ֶòù>ä$"&,ö²{áE‰óºÀѤ˨#l‘`ƒø[ªæµ¾ÇJ œÜ†fG¨àà5ó>39J9jîR E*¹(P…€‚è‚LH]‘äGƒiC2&kŠ!Fhš7LH• ¨Uv©dÜnÖ¶¢ïNθ]¸Ñ£Z0•v:¦²åÍ$€Cßp, Áð ’ñG¯ ö+±®˜’Ì%š„QŠÝóÛŠñ¾æ$ØÙáãmz‹óŒ0#çG¿ßì'Óäd ê§œB !ÊH°0=Û'ÄÄPV 7îåA’“;9SÑÛÞ/Û×ìyòD_ĉï@è@Ù,oñÿƒsgO(žeP "a=Å`_ŠÊ9™"±ã=?øçõ¨¤W\=Û'¥Oø“2-;†×ÔCü$ÇÁ{céR°¾b80ÃV¬uW÷ Ü̶:”Îï˜%÷J!tça *T¨Hª5æ©Ç%«³í2ðüµÁ­ÒÚÇu¯‡JV‚B38GH¬áôòâ™9· Ôñæ2Pˆ¢at2XÆæÈfòâ—hGµŽ§ ‘f(²†©2Ä4 Haë#Ì¢x€‘vÚ``zGý{ß½ u¾[¥¶Ÿ³ƒõ¯5ÍÈa7D××íò°ï<)Òº²¿¬(, rSØ… €’ !ÇÂ00Å$DÛÅY ‹¾ \a­ë¦kÙ(ÅžÀ.nE΂²×!XaǤ&T­”M¬Dué€ Ø!ÇßÂgR•P_ÊÓ4Shga6a Â#ÍådNbè b'öz‚7?ÝŸhD…Ú"`\*Ëh¬´(ÂBDb"6¨Œ²P´I@#MF¬‘D¹õL|{0*äq"…Ç1¥Z!8>  ³\3«y‚Û‹ß (,€ °7&x¦—1öψu}PêBÃh+BÛà¹Ýª×êÊ*ôú-ÝŸTxŠª aA~}Ò×è¯+®n©ÉŒŽëDEh €¥ ™`(@0dž3.³˜?(ò”ù;¹˜â6 ªŠoùV¥ù#°±=%O%!¤Ìóê£õ¿+ü«¾ÍÌòò/(ÑÕŸ¢ö¾kÅûîwÉT”E%d´æå<ûY6‰6 V,¹a‚"e¹…ÈK(2~‚#¢Ñ_nÿ¸ð7ÍËöt\j°È¿Õ~¦rt+|ñŸë£äDÎÝç™ïQœÑ”ÊŒYëd3gAAnc=ŒU„É^D·2û½ßGNœËŸ‡• Žd̹lË­Û’=ØCc¯$²Q.?[¯,%Ç'úna#?‡÷„æ  ³û?æÿ«úÙ´Ó)äjC·4ƒ‰bÅA€ƒ à*§t!¢F{É `¦Ø~BlRg½aXª§ä¶3³0ö×]TwDÑ\¨å‘‘ ¦·âQÝ!ÛÐ  ÛôSÄÌ1‹¿tw„¤`!œ®ÅØQÕX ¶Â‰™˜€ÛUÅ‚e}lj×â$i›äQEQ¢Ûæ@¼{ÞÈ+sï‡@~c1õÐWpÀª©D¨4eV `±JÖEDPU|jªª¬EX ª*ªª«Áab¨ªªz'…rª3²Vú)PŒª‰"Ëh³Ð…A^¥©‰z……VFvävãƒiºª‚#ÞyÁ­BI%‚ëú<‡<Èö“žoéð#É bW€ ½]NÝ {\…®J,†{d­ DŒ$@B0øL#ÀY'!8}jˆˆŠ§™½B•0 6ð¦™'å­V¹·¼i}k¨Ÿ|X¿YI°¹~“æGW3 QcÌ>ÞN4Ow…d»¢º(x°ñN~Ü} Dª 78D@E"PÞHÍ3Ø2ò-g«&2eˆ¹`°+bÛU (ª mh ÊÐ,›v$ ;™­ýxNP‡;·ÊéŒB¤Ù±WõòÔ’@W”d±$ÁB,€ªªþöÑ‚**?nÕUEåí¬Šª(ÄQD^dÛ÷²âï‰&A*Á(îøÑ£ûÄ4ssË|xn©´UUUQŒ¼ä’D²J§Õáí/ÑI2OŒ¶Q…)RCdU(†4¶Q´hPBŒ… Ùd„¥‹~< uh¶›SF©SfÃeb ºu\EQWê›’ÊCb$  #²³!@A‘@Rd6ȤÁÔ`VE‘TVi”YciRÔ„ФEA`Z€”ƒsàSÞ"‰@té%%!8( ó‡"ÔK°  :÷= ï“fT“þ_ûâu?cû~EºmLߣò>?TïR‘FKt\Ó”œõEõÕ¤uùëÉbPLeñÀr€ÃÉÌÇ'nN̵IÉLV©þÿ3úŸéùÖŸÃö›‡ýýþ‡¨ÔÔ¶ÓP6 êè$ÃN´׌û¯ÚCBŒÒ\`\K/*f ©’-“c @ºb"Á@!Š’Á|( Y¼*TŠ‚ "Æ:T1€‹èfK•C³Ã³S”Õ6T ™µ(à›Ú^–MmÒ“QÇ3-GFÎ× Ún”Ü“fb1Œ3wž責bå(Ú"(#H²Afk)œ› d‘V'$4âÇó?qOëëcÆ÷)ž±ÞC1xðÎ!ƒ%%8ZAÈ¥³X¿Ç}÷€9!˜x GK´Äa‡æC²þþhñ¼½? åÐÖÇlí¤MykHæ°ðJÜmÜCw¾ÿ+¸ØæÃ©Ð(ú^Ý©=I§£º:VSW»ŒÀM—gä{ws>ØË¿­×œ‚£ÌU +Ä\ÁKÀ=ú[BgëøpBàNg€‚p‡(z¥E Y‹ÁøfE†ÜË©B¢bR8‚€:vÅ#p:ºeí碦¸4°?Rg ,{ì¹Ümäô½n®ž¾ 1a&eþ­ÞôÝáPÐnPí¶£_›1é˜Ù£$©$†`Ý,‘ |ÿ¿CÀ/Ø·^vÏu²‚çX·'ºQ.!ñ@Ù "È‚J”hwyùàÀ†’ú'y À>4’ ¯¯2Ñ·qÒØ>¶Æp¶.@=²ò™?s¥4ã˜w$Ò,îýZ@1ÐÎÒ"ÀÄüþÔðÃZÖƒ½€ Xw&czæ%ǯñ0ódÅsrçé,3ÀfÂr´Ó+Y²`ø5Ͷ¦´OùÞÿgÏ?ó½Úó"8(˜×3-ëÕwÛ7âŠj¹wQvêXW Èõ`úzÅGÁ$`ÈÃ6 |0÷ß8Æ-·Ÿlì#_UŸ°ü»Þ¤8:´@åËn(4º ‘ïhLËQÔQ¼‰®]Þ=·ö§‡j—«8,‚+˜­á™£­ët†.öqÔ›J ôKòa—uÌ~)4 'ßÀš+ÆØÅ‡¶9^ˬ[+‹Ô_ô[5LL§V„¢d(ê Y'›;„r÷Î ×ÔÐÖ9GÆdðŽˆWD¾s€…n‰„¼ÊBc‡;ƒƒÌõJ\Î.àZðE‘Í”£ÃAÐ tÖ¬Ö–†hµg]¬öÑÆ‹ò*Ù8s ‡“ ºÝ›ª+vE;ð¦ìÂMK×NzÁȇÖAT´nŠ‹ÕBE•‰3 *…Èй*NW.Ì$öb–Ö.ø`@ ƒÊ'hU¥âÍ™Îêúœî<3|bm/;à˜Ù]˜3â;ø¨ÅŠ N©š±Tú=Ê"³LDñ¬Øh’B9ë-åÛ6:èH‹U~Ådm…¬y”1h¯_pcÇ|\:PÓhn c=’Ž·Á9ºï§zsz'’¹<]ö9Ž´Yº:¬qÖƒ=i7´;ïÞBd®ÏX9!(ࣰ¤Ô ïï,ÒUÛ&Û-„î<¯{#LARŘÞ$$_t6òo@P°/ ð[<Ú¡Ã!fŽ¢©ÚΞ[9‚à—Ë>êg×HO'äG‚3”ÕãŽÒ†øÇ¤uH©q›1‹k”Âj¢Åks](…%ãÈÀÈE——–`šŒÞå„vÑ•;ëXÖUscU¤Ò¶¸œ5O^8b·«Ž] œ‚]X$Ñ“!ŒœbbòƒÉ¨€"&—²fÏ}^H¬Ì¼¡œêöâ:—ÐÞDàêIBD‘7IHEFh¤HI¶= ¯²F§ÊC© ÜÃòÌOÐnÑ÷qEÅ7C-<ô6Aóvbò«e-Ì2Y‡[•^O¥êÑ™jÎAÒ6{H¤T”6g›}¨*îf»hïvXbˆ–zÆÂP5g–øêi>š$·0Ë…Tq¦I€A]‰1Ó Aßü}5ÏØÁ­¿šóD-›h•¿¢øˆy»võüw–ÖÉÛy=Ùâ;5Í#\(²©mG¦ °É,¶Q2H¢(bæhÉ¥` ¶–”LTÂbR›@¡’jºe6Y 2z\~%¿_çÞ•ß·M×UòõòÙGX8pÎÙ§/Ó>ÈOG1- ¥ÏwÌ}»ô»wÉ<àHõͺ¤£+¤ßG¿—Ž>ùà ¼HA]ü;><1s7‰uLÞ¡Øh®ás©¸“¾•Í}KV×`´¹«:?t@)LQvÌiƒ&Ã'SÃ[êB¢Ôýžº°CˆH 86‹õÒH6[‰s_~3—IÊWÎÞ7Tw>Ì·ðºø¼Å‰VC?Q ~Ç~`˜Ó/Á³&»€û‘ÔDXHÌÃPxµ\‰ÝE1Aya÷ÑÙõùŽï‰PáˆáŒ@ÈEÑŸ2܆L®RqŒMòË©1‹(,9ÂÖ: ëœ;GŸl#¬”ÅÖa0ZRÇDRïÕ|kéÚ}~8|ß`èîë¨êeM!MU ִݲ‚.4iÀ&}kËÎÅ‹ñÐ’_<ç¶ *Õ&ŒÒ¡F;ÔŠ<Ú 4ðEÁ<‚ßð}¸]ý“z–N-«]$"/tF2:A_hv€\J@¨(H(ÒÊ$T” •(‚š ©„V÷ëß!žC×ó½çe[„¢¢ó÷–K ‹—ƒâáaþ ðAO¦aP3G`hšª ´^H€€È ¤“ˆX¢ÃŽC=sÄŽÌgc¸Ø‚ Ž"ÕT”APÇ\Žãaà™±6û£œ›}#Æì£f€ —«zê'“ÓXÜm1ê½Ýmæú6P]ß<_bæ:˜ -iËU×ܹI…¦ KÍ ›^T’@niðhw‹êÍ%ïX«•¼LL|¶çl˜vБäë}j„ƒiAT ªnài†á3ŠÛ›„5áQ`P#qÓÌßc勞ÍIüTÅ2Áo¦ÊTµ‡+í†!¨Š— Lu¬L£LØì{É!Fmá˜rIç?)sš`¥ãÚ?„Þ {«éà”—ª=ƒˆ¯ Al䌊êZÖÀ ½0i|ܤDB(,A‘SkˆámN ¶¹€uMpâGæNFf:@^D6Ñ8¡#rÃf‘Gíåá-è®äؘwa°$a13*.=à¬,€‹" ÚÖ–mzР¸JNRJSòa¬‡) ‚( ÅžÞ’"(«D„yÀשÈxO2‚ÉšHAR ()M!ì`öíÞ¬S«+ ¤™J Ø$ Å $µ[­†YŽ|wó¤“ÉíªðQ=u•2ˆa ï‰ C&¨Y¼r—«³,»Á‚@q†±Pד½[:ñZ•­‘ˆœ…ÕœÁ~iÖÐöeÛÑ0}½KéõçMÑ-SÔ9às9ñn^¬ÆÐvʵ©c(PwVºÆb"DF—¡Æ‹³: "kqb‘¹Ä“Ä«ÎP…cÐßáye™á0»íÈîÊ2,Á$±?—raÉ ­:òô±C>Dì]±7i÷ôn‘IRbG[çDPL`0Âg¡åR»“4õŽlÆT|PñÛ˜põœ‰".OšÅ«”$J’õD¹ÎT¨/)ÒûHu9:G„ŽÓHC±…-i$„±ÕrÌ—´! œ{iP Tƒ"¢ó (dP8çÄ ;.¡Ÿ¥|@,\múSž¬=ÄŸÔíwŸ"EU‹†üK‰ ' ªƒ ªDDQ"H!ÁäÇá ôº^vøØžÙ°àl†Â‚ÅÊâN Ú†¸œ4€Â"àÉÚ@Ê&á9 c‚çÓ R‰*ZÑÝÞP½±cÏ5Š•-Žõ«\ÄH15  €ÌL;œò؉ˆÖ²„!f’”‚ƒ‚u½°7œÐ)Ó=h"|Ï5KÔóTnxn³ÀPNÈ’X:˜:“œ@¶ "öOž#ä Ò O•îj´Àž÷c·u]¯·;?N ÜP©+½ÁïŒaÀz0Š»Ñ¾PŠKÁuí®™Á‚jøÞÍ–$Rq¤1É’ŠMªì¶~. ‰æ±«¦Þʼ7µJÐH’t½T܆ð.Y¼¯+xº´Tâî§6€MEÂ9Ž H\‡@P@X™Z¶UâEv1Gf¥$¤†¼[”¨Y&ü§ˆMØŠCŽ‘‰¶»Ô×Ù¯ÙéŽ!ç6E-]t„ð˃\³É9Pp*¾tî.€üüRhHa wPç–ȸ`š0œ¾S ‘O‚xÔ9FütÒ:TXQƒÎxÈnu`——”)•t“WyY!Â’Ü×/0Ê—ÅGÙªanvžV-øÌ¼á’ø„‘ñi›ñ8{» ‚«!]È] îyüRê¾wŽÉdCw½{¨{þ~EPøp.Ï]uˆ ,›t-¦ñ!¤3#‘€Œ%(iÅáÁ›dÌå´Ãú›TÈ19Ȇ[Ù »U† %d )H[ÜÖ¶Bá)y+öPù<~Ìÿ*áòçB©«¥Gî$™&6 €´Š´æ€-ŠÜ;1ÈÁy‰@N „Ýz\»‡ÕE+ØAò„!&îK‚Añ¡ŒÞcÃGô–µ¡ÙX¾ãû0Ó¸ÿŽž5)ºOs·Q¾Uýsúàƒçkþ½y˜\·2îzƒ§Ša žúlø>Ó·ûü~5ßø]ü–ÔRbxUÖ\"΢‚Ð)&„ÅJì$—)1,È‘DˆÉm$6ŠÂh¢‘Œ”‚ö™ 2cº`E‚‚Àýoä톙i‰»"ÀÖXåå1Ë1 šLË!‚Ipa¨XƇܲ°4’)sJ“T•…Œ„Q°€²”Qa¶®éƒñ¸É!!ºþ¬õŸÛí8›S^韈,F+Z’žÏeßî;üï2Ì¥\Gbb¸§žçÕE®OŸy3mõZ dκTðkóqêŽ×&hi3¦4kÿpP\Fd>O!¾þ{ïÁüØ<ìö¾.ÍûY¤*h&Ë´ rk¸ =+ÝX@ígb;Ruõ(Õ ¡ à’'¥ Î`å!ÄO·#àF\°Ð³èõ!€n,¿Ýgò+ª(,»ïåÐqšÄ‘ˆI2<\q´V¨Cáöÿ‡ÓrÆ8N.Æ1šGêhˆ„B–ÁÓˆX;Ê" gqT Ƨ²óî=qTF„àŒDHPX0P]ùÈFËÇõø&·|>Qéî]i² Å ¤d D42æQ2Çë{í·¶Ô«×35Rc§nסçwÕÂæxWO$±QŸöÇQÀ\Ñÿ¨Ø@BÎád™b<çMÏswqH&Éé²UÌãBQ>æ â)¨æf(f8Ž8§ôEfI7xaZÃï\\é™s21¿{É",W[6hX Ø(ô~ÎrÕºì~»!›9âÓì}ÿNšS§}‡òÙ"òŸxKëh3¾Î§uŸÚÁþŠ}ú{ÌtçlU ÚÒØ„“­úšf¡AnÓÝÑòÿýù˜.0v[ìœ+áB_z€B@=ÁŠÏ0”Q¢! hºÀ¢ùŸö<ö¦ [ÐÐ\ê骢0‰3üzn¸'ÉÜs“Ö’ÄžÊQbň0 ’FÖÙJ,)Bø„ “q Sè~ÑÆÄ;²7h‚MÜCPX’T* pö)´°J„¦¥YcG­1&x<ƒÅAØ=ГTôaUšÖ`(Žºï0†Üwçbå¦J —ÓèA¡ë_ j" öáÈ *!Ÿr¢å ÉJ‚Éà÷}JM/¢¬"„¨R} Õºƒæ@öÎú*â<×obsE|Ò) b®x¨[FƒËötjDÏÀØE`¨sóæ®»«Ï÷~dØOs” ð‡ŠÐœ2ÜÞH©ëPDºÈ7D!ÁR$EçËP¡T!…y¸¡èâAy¸\EÞå×ÿöPø'6ídsIa D„$€ˆ©°X²,‘IXEPDUXB( ,$,Ab Œ" (¡,„R Eƒ# ,b “á "ÑПåјŒN‡ºH'Å_wf ÕAnT&Q3ª= m@£š>Ï Úm  n@j V ¬ ­C=tñÊA’0(@ÅÚÁ!§|«k\&ÂýOÎU sP$@‘&¡ræ/&‡Ómƒ÷ªAÆ? ‚5ès<°zÆYO2«""1!õø%­$ x(,+̤LÚœ/÷Ÿ‹p7Ô;â»|É?´EgbÔ7@ü6¥ðn6K#^ú3ÿ[–Tt^ €„ ¯`€¨/0(.é¾÷çM,ê£þ8ì{?ÞƒöççÖò—×2çÀXªþh-pvº¦j+¥XZ÷ž¨ $Snª‰É§ÎŸIa,ÖFÇÜjŽÝõ®òJr\¶ÒÈoMmý¨@¡Òþ’fts;’œÇú\à3{Þº/Oví3}¤:ÍO‰ÊæÇÿÕÃpÑñL²Æ{'®[ï»ïY‹± (Y.þv¯lK])¸íkg™z‹l·¬Å1ÂX¼QBÞB Ø; a.!XödR‚sŸ8/ñ jQ€`B›0§SøáÊ16ù0.ÐOXò྿©LêÌ܃Öý³?€“ùT:Uïèq;ëOÍ,¸‰XB¸À¸mˆ‚ð î5ji‹Ðz\cµdo•o[ñ?·ñx˜—àõñ3]ý:hZ Úš³ñ"‡=´¤ÙÁG÷~^oÃ×Â0ÙÍ«iUâKÌ2±þ-³Dä!‹ºÄeE’.’§UÆç¦Ž,Lxí7@ ¾ËÐjùŒ\v'ûµ43IY›É2z¸ ½ì°?‡RÀdÑjë™ï`Ž¡w» ¼ö¾áœ†Ì éPX‚1…abHVRØ((²Éýà $¥’ɯ?¾”Ù˜¢¢þ^4ES´IÚ³tƒE’EIAãézòâÆ$)dYJW`¸HÄRbGñö~ï¶l],ñÑ<ã:ðRp2yœ˜#T¶CàŠ(pÉj"bTTªˆèë™ m±®œ†$ÀÔËíЕ1¡ðÊC·ƸãÇÆ5•¸Ÿ´óS¨U lb&¡²Uññ)EUUX.‚ÆÿÐü¤XG稌P,Ub PL¨Äbˆ£!. ôý™²k-)fЂ'Õ`VMÓî²ÓöØ{†`ú:Ì=gƒîLºêPhM>%x¡ú/ÄoLÆä!vT&{±EB¨ t©)6Ü7£å´’'Å ÈžºU´…] ŒD%kuEƒ­`ÊÓ GâO#Ý‹"‚ Ð;á0H­d9ò`€¢.B0"ú‘Ar9ĆúˆBFåÅ’XuŸæ&è5‹œü7Ñ(<‚ð·eƤÎÅøV5¡µ± ¥>ˆ¡¸¡ˆ²"‚—à€aïÕù¶‚È{L d9²˜Àí™%UÐc5û<ž£€EøNÁ?ùÃë¿ÂXÁhŒž¯\úOW´{ΨYû‘oš=Ûq;vòJ*I#$Á¤<Ù>b± m¡šXÁ@›Œ˜­’V±c ÆD…$ ìg± t>Ì L¤@k`¢°‡³‹3P¢NV‚Pkd"Ãt˜È  d‹¤±H‚Öä )Üú‹s…ETQY÷’ÕU9k=¶¬UUEUU-”TŠ"ò)Ž*¨ªª•©Zª»5QEUUU›ª"ªªª«U^-AUUU^h³*ïáæó¢çþ×9ZñçG~” DfB×íD{„Â!Uƒé±RÖ“¡ð§püQÜR¢øÀWŒR—¸:‚Þ+ÃÓ‘r ¢l™¾Upã iÀß@¦Mñ èHR;ƒ0¿NíCL 0hOµƒ„ûõ4Þ G® ÚÅ|é²"-Oum 1Ah$"=R¹{žzb‡g\áz†Í‰5Ï™{BòäSÔÁt?‰ÜIÜOgw¥WÖªªªªª®§¢oר‡b(žRÑ*+"=b%ü$• ‰‰9ŠC² ŠÅ A0¨ê žÂ(O#æø¡‚ ¢Õˆ( ,—r×2f@в­JˆT ·P! ›ùž&Ûìç‹©ó÷;ïÕ~×ÜýÜŸ£Öú>&Mîÿù÷ÿçø·ò¿‰íþg[ô¹<عŽo–±úD=¤Kƒ1ã)Á†ö½-& Ÿ½ ¤ú?ÍN%ŸÎàý^˃úOõ„žêŽp ÑeQ»‡»åÐÓÒ‡3ÍÕѲY—J•E¸L‡üýï?Ó¾@Cd-™ÚÉ:VÝ«0[èαÎÈ7™¬düÖñë>|ýî‰ãÁDO#ÞO/ÕTNBþ I3>ŽgÛ~nMQ4™Vgà·ÀÕ/öÖy# yƒ™5^g üÀ §;åP@ ¹²`3ã.…L^‡®¸é?ëÉØûžPÄt&¦¥ˆ'.tÄ4v‰‘Ï(I£ŽŸ£q|©*ªBËÒÎ3ðL?†XÊ\íe¦ÁK c~ x Ùò˜$Ï\NB¨óÙØ¼Zaò`¢TE¸ÊÇgU èL…¯™ÓF2ôÓ4t1“MÚg‹tuŸ§ôs·ûù_õúüÕóÜ·Äþlò¥mß.ìþ4~Ê,´FE)÷× 'y¢ˆ NO ƒž0…åG™ "ƒ!ˆ‘2(/Ën'§òW±–¶%ÔÔÝAc"†”ÃOÛJà¤Ò„3$Ò(BDa"J P`°‚²Š2,YNH@öÃ%Bi(DèÊÅ"«(LH¢¬*"ˆ B»$iµ€¹ ¤PÁŸS‚„$úÚ¤Y­!&µM¢¥#R(ÌË&Èt8 ×óßœ86&*³LÝ7d íIÍ2ÛÖ°•6Bc&„ü„1 c÷X“çÉI¢ Œ:!LT]$T~Gšñö%ç00,w‹ŒÿÞîvÿ‹Íc=4P@Ö‚üÌMÆàµCi[T¾,YÄqZ†A¼¼Œ±G»†Ü+µì è£çô‘ÛEi×hRŸL` ›4ŠŒ<“þæŒþ`ª1‘º0ícCøVX ce•V›•Ì"pÕ‰n°($"ì%ˆ¢“PÊ#~-¹rÊ1•kjLµJƒ’Y1Æ‚«š30ÁøE¤ФPdÆœH{KL‚Bz½¯¬b~L*Æ" J1! ztÜç.© šPy+“$èâ‚‚ïL4Æzy–% $hH‹ˆðöMÉO4w/¹%ŠL­$ ÀA€ÄI8ÓÔ”ÑÑžá€P›€å#š•P ‰$:äõ| Âjáñ=f… ¤"Œa ‘в ‚*I"¯¦ô:Iµ÷ÀjÀSadDU$€ÉyϰÉMZªª¢¢#!B-Àim£‚éÄÆìhÄŒ5ˆ_ââΟ”£˜]üt‰ñCm÷>”ø}’DX€UA˜é>Ç>ÚXàtÒ—ÝK­RrÇ‘»Õ)WÆl¡yŽ ÅX­¢±Z¨U"‹FÖ‹òÿŸm_ª­XnÛk#"‚úHÐȰ“ù;Ð1d­#òÒ 9Hb1|¤Âã¥ÑŒ%0ï&‹ J‚ÂBlYq‘HM0S¤î›éLa“` à$ð *È;Ñöåá³ , IÄf$žˆé„›…¤Ä±ñüi`¢ƒ‰Ø;  ŽÈ™õìfFDŠ@ux®yE×´lI4è4šQ«¶ûØsD0q8.=ÑÄS1FªU41¸NÚ¼˜êŒƒRë7VEŠôXûP&b|]lˆ–F mr)Ž×Î2z\`EÊyÖÒH<|ÝßèÌ&ì¬6fÈm«­ðÈb9˜˜6Im“/⺪»iÁ”Ÿ’ Ê6þÉQE À‚«8&²Ö×@q ˜ hB` òjÖ)~“Ó};ënZE<ïõçyu\÷úÌ­Äð>¸%@wH"u:GÁÞü3sr¸Ïç9.'’rξX¾{+Œâae 8¤“2ØA§gîj* b²Ò "|Ü0«ÆL•µF2\™™1&2|z½ðT•ƒ½éª½üÑUQãÿLd„Ì>Vª‹/»~ÍXÖ›ú3Îo2÷-U÷ãn½þ«ÊãÀë9„? ÓN9!ö¿RÏáíEÞÂý¸ƒoფ‚þ÷ÝÃ%2ÛíÄY•ùÅ%ÓÒñ™§%eÉWB…„©Ò§)èqCFÆ;‚;8E®ÕðžÕÐR¿wýl’陈(*?£œÌHz…sñ[>¨ØÃ“,7ýï³¹0êjNÑ£ 9ù InŠêà{ŒPX±bÅb•,T#¨ – ’¸A÷$àX‚Œ‘B1Œ .“Ù0U+`PY™T¡AyèQzÄUü¤M覆ª«  Y}@oC%°¶H`;_[e‚›ã@ ¨0Sbäí4µAô,2 €}8—r’@£Ùšíš,°#š1éQÄG“kwÄ 0ÃfËr¿s&îM$Þª„€»²HÈ>€ô…?`ö@4MCxˆÚ‡ÖÌ0µ¥­å dßU]Xà¢v‡ Ñrcµ½wD1Ä„$’'ÞüV[E‘AdOÚ±q†Ì’êP]HfTC¯MÉñˆM¤ARˆ¨(!ºt$°…œ0À 3‘Aj>~®?rÀ„`Ù9h¸Y3ê(=~$BžÒâ[Žã´äÀfK}ãÍ3ÝÑ4@Ά “ùÄÿ*r¤Ü(Äô0Ž–àLˆ´Ù)²3¨s|Òv)ðù—3ΤN]):FFžGÑ?çrzÉï”ר¿DïÜ7ÑÜ{°ÐŽÔ¿ÑVŒ AÐ/ÑD|l’ETºÇì’E²6‚@ŒbD6YBË-ó8,ÚgíYsláÂrZ[sQŒ,NJ‹q’ŒPÌ‘¤úžŸY ì%Ƀ¶°†Ñ5“Hå–cCm4ì†!‰á 7xþ£žþo¹ð¼¹ÇòY9}±½éwoóz÷ð¾wûßg…áhµÁªxÛ®BÉ!|¼«nè-qTÏöû^÷<‘¾Æ÷™(änjZ}UB¬žÆµP"£v²ºt„´¹•2™ø¤&ç-ÃmŠ–îEü»1šiD·YÙP=¬£‘¨ ³„ÛPÔQi¢Ô3FÌ4`É«$hIWñY¶râ:¹ µb͈´7B¨˜ Òk%M¦ûë.«)úä426æn©}.!ŒßbÇBKªPÄó}jhß³ƒˆöÛZëK”£³- æf ¼C0ıJsš,ʼ͎ëâBæŒ*bŽÂKƒÜëI’ö™(ŠË»ûèã"‘PÙ)¨½æ°ØíÙ9=æâ-TŠ~#^¶˜ãˆ[b"ÕíÒö——½­Gr~'Ôåpà§êGe•8‡mú¡©©´DC"ðÉ̯ìvÖ¾ú;ôŒ}‚>Ö!ðgþyá¡FüsÚûJ¤W¡dÜ~¾×HIjjü¾o\«ŽE Iõ¡(D_l×䫯2¤ß’‚Ú‚Õê‚«¢Ál  €C¦¹»¢ W|ÌvL@[F^ª-âKЫz®¡õˆ"¸À ¹u ü‘´ýžh5ð¦lAý®0\D³ FÛ)HEsƒ!ñq†Ow®.¡™Àd*µXµ,Y¥´±#AKÎï@¨ÌB£2B²Œ„$EK,Å+sÒ‰ö_Á¾{©SüÈ<§VHy'E"NÉ?) @É0&~ÐUP*›§F.B3¸ÚAi ÎB)ÕvXU•ß»rh4”2×SwX"›âÂLn@#‡rqœÝĨ1‚(«øÖˆC˜ÊéŠRÙM¤ ,“3á³$CK`ªP †RfH@*M[§˜ÈkuPˆ®@UšË$â»æ{x')’HrÚ 2ÀД’Q:ë H ¬‰P1†ÒË77¡)¼¥$JLÀ°ÄÈEKa˸ ,c>”‚”cHQ›6н}¦mæI WP* •౉>g.J ¥Š -kˆ¸@§x§Ú›ÆŠ(Š)Ù–›E ‰x`U#!âÓhgg‘5 è×ݾ«=³º:PTNƒ'äðë$‘UI$XÂB@ʬ´$ EQr ‹Q#K¤!âè šŠŠ’@E„PY+ÓN°‚‹!F!‘ ‘4@¿} çµ(ÒuÃ÷¡e ܬ“™›0ÇœÐä”4ŒQT"‚Š©5Hhº’z•6IЛÉuØX€ {h¿»õ41@5$‡ Ö×-¦õrÝ y»â0°D‹,V"HÈ"tEY)@«YA"ˆ¨Q!“—µzЯxšBj{4Ý­ÇngÌ‹“Q'üxÈ~gSü×3@«¤̹ƚ½²È{bA`vd­B,?ý7ćŒ¼9㬟«SSÍ!î‚`@ÁÆ>Þ:÷ÐTB ªòâ×…HÝÆ(Z‹x|Sp³W¶.SˆDE¦IÐÁ!¡„1$€a”äy~º®›a‘2-¤‹ ´” ´¦‚ ‹IÒ7X'È–ˆb¤m¤*”-) _à÷öÞ¢)U¨ÀbÆ …k,¶Ö2w3¸Æ(2ÄP¬‰FQ »:ÈBGV’ÝÀ„˜ Ú+$êDX1Dk:¡!&å jÒ» ¢³(¤80¢`š23n{BK´Ê  ±H%¡áäÄ„„4+A@˜ (CL ‚ 0Š¢!¡‰ðœ“¨Y7¢ÐtšÂK  †c ]ÀÀ’|z ›ZAˆ`+-¥E$YE$ -’¬ˆ’‰D –––¤ª Œhöq,‚ÀEQ H‚êB¢'|{»è B¼PžG€ù›;Ђ0EX`}Žz'€h6T ‹@bÔ$ Aù{_óøÛ?Ñí?ÝzŸðóKÌø¢&túQdݽé{=ëî#€d7Aùä£@ò– Àš0€vHˆ@o·1gž".þvÄ–‡–”E!÷h¼ƒŽ!| Ë/F†ÙÓGm*g)) “³*S‰hÅ2Ð7B "¼õ†¹R`“¦è=l¨6ƒÊÖæ#ü¹ãsi¾gÍü ÷›¡Ö&S”nOIÀöTæw”ÕCÁŠ˜žã_6Åòë®ÑÔÁcGîêÛr¯¬gO‘M2”:ØÃ2¾GžÏYÄ/ù‚àA‘¼éBøxùJ\’è•è`HªHF@'ŸÏܰ‘VEdH0ƒ;|0 ®zl._vA¡H ’Ú÷¼©_ë”<]J#M€BY'ê$†ßÀuÈžâWiÁ¹ƒš{p¼ƒ*7A´I`D @I dX‚¤?4LÄDUšÀ˜¤‰ I/²0âË¢„œ™ eWZ ˆHŠ=\P**•’ $ŠH H "£Q¨hTSÚ…£`Ó (m™H9 X ‰­›Â<ž—rm÷BHçµNgÿjû­ñVE-ÝòFd*¨ c’1:ݞȔcÖ6á¬âÒ3¹2?Àëš8C9„ýZCP|€ˆ2DØ,îº"’H«AF0ˆ±1V‘$"1VBHÄÛ ‰¨ ¡@Í ,f‚'£M‰•+uLDÆ&vó'X §kÏæJ¿9— D7$ cGüщæ@¥‡K+DIsë""$$R’ò HY„a#ŒŒRDH°Š¬( SÖª#Rd !"Á‡Ää“{ÀH¤QbDPˆ!¿"&†ùI ¤1 €*b2 Hb…ENø$0PJ„Áë"=ù%Ÿ hp'^Ña~OM/}D`öËTê½$ %k|R™M ˆ¡±ƒ&µ¬UIä(.•qaTšù&È%³XÔ6-Ó% €ÂÏ|P‹@È®xPX uŠªæ …‘hˆ+· DE ‚‰E$‚‘ECG2D>JɈ™S>Kû$’Ni(I! `„" ,àPZ "´Eì˜sï,)ò@/ ½æ)f‹¯!Zwâö éµ!ÍÀ„ˆuÚn¢úuÒ,¾Ù®[\°nÙ IDRšŸºÖ´i–f‰ó†f¢›eÐR͇¡ëAmÏÄaÒMu6c’&ƒÍ.΢¨ÌJxZȦ2Mî°Ýè”E©F@‘F õÈd±V`ìêC$‚B$‡ €à>×䣸MìŸ<ÖHQŸÛª mv±9@ÆrÈ‹MŒ›§>0Y ñ÷ïÁ…Á—ÈŠ.[y3ª‚äP5°*h¡ ìÀ'»BT„c-‚R¥Èe=Ááò‘ÀfžÆ)9$%`¤Ið0xï üñŒoöMP·M‚ôß=Ai ÛÑù~Ÿ›ñ|ý»Ï'k*¾Úb,+œRË‘Œ(‘ DLÁ[U­±dõÆøÛÜ>/„‰ @Œ#œƒw¦‘’¹^HŒp "èë½´'“Æn÷[h¶F6JU’HZh¤íˆK‘ ›ÀEÞ;µ5"ä3Mb©è(/Úœ#êˆtC0ñ{<zùè8ƒr‘ÜÿwÒCÝé:áÓÝ£mL£KŒ'~BÖ‡°>5õÃRN fõŠ&‹!ðZyh†~Àµ‚ ˆÆ>)R1øwóæf/ó3Rs'_QKñËS]9wr[› ï‡*‡¨9žcWA+ ;ÕªH0<ƒ”a"ÇÒÀ÷XÁ{˜*iQõm+6ÅV³ö¢Otœ¤B$aËÝ¿¬‡Ã>Ä…02Å6†÷®‚Œäwè[Á ¢†Ô@`(Q­Ñ^4¦*q‚( I½;`öЄô›÷•:>C:NEN…D£µlK;ÍÎ3tÉ4]P%Io“58ت³•0d8 ¬ŠO_K ™ !&8Í„ùÀÈcÚýe¯Fäþ°Þgª¸ý'šYõüKßÊê‹B6">Æ Ì T<p…éî6®{¬kêØd»{¢ˆŠÄXÈ,Lay@’goïåa9àTCÀa€R;BŠÖö\ŽÛ°>ݪ«=Kq=¯V•:7h¿=YmÊþ€Û¿à‚ìwŠÄÉW ¿j¤ û¶ã¨€g€p^:6{Xëƒ(èr8€€' ß¾/öcÒ¹ÓÆó½M'ŠüÉu‰ ë¬Qa„9€<ù«láP‡ v!ÊI´í šÀH¤›Â Ò0„E¢4%ýš™ØQÈD§üéðݹú…BÜÖYɽÏÂ-s·K·}:ÝðŠ*×ÚŨº80¢!#iE¡S÷yžÿ÷¼__£±Ôø>ûO;@DLýÔ,”5$´†-¥Ðª<¼ E´oA÷~ ›ÀŒ¾’À?TÂåbkˆ1RäáGMR@@¶ÚÙDH¸…DÄ+FÕµÃ.+¬–Üf1e$l²‘šÌ‹0`0ȰE ÎxHdrþý¢ ³X,WV]ZÌj ÅE‚¨Š ÚPYD« i¤SŸÎeé—?nDªÒÛhQºË­W#U¥¶Û H”kMY˜fQUÂÛnž‡ð)Üîo Ô8fAbEÈ”B\ɆJYd 8ÏÂþËÌ.:?§¼òüO«Ó”ìÔœ¯<×"¨Ÿg[# Ui}&Ü~–©é;Ì ‡”$H±kJy‡M¬¤Ìüpš$¹ø¹;âž4Š šº_ùCZœ¢½Dí'©€Û„C&‚‚~&"QO¢tF°cSWpÖ½¶‹’”­®" °gu/£å8Dï~¶—‘ ¨Â)Z‘(•AgøhÉü|ŽLay1ˆ¨ø˜™<Ø̓PŒ² ÓÖ†M¥Ð~­ûM$†©§cˆvׇuw7»Zô¨Cߨ-Žc@/ i©Fµi­æ¥¬Q¬Ë˜b.:Ê‘g “lŸoÐõÝŸ„aG:cB&Ú;t^ãx´wmZÅHdƒ Z$è—ú×>}|Ÿ‡¸ºC”^+rˆd'¤ýTQÀãÊ•žwC¼žBù«±Ae$‘–QÍ4¹Ò¥pV}yʹÁÐPtl~BöăÂ誤"ð‹p9u¾ ’…=Õù»(^6L(.[R 2j-ö&Q^×9 ÀdC^œ¥Ÿ§Ê(“[ÝT]¨¶ÙÎ`üØ) "‚à¦2â•(ØÀjO‰{„7”µG#`Ò–@ÓX*¸‡%ƒ‘”Ål5Az.ÉCŠ[RFPk`!÷gUžü¡AqðHºoßèÂB ™!c#î;NÛ1ïQùeÖßYªnm_r¾ ›óÚæ& išJÈj Ò …Æd8üíH*;3¦KE`‰¼³‡!½8àö8È ^%,aÑ”}0WbÈå±*3¡ëø°6v¹Æq¢‚"¢ŠO$¬Ó?–['-º D®ûm¢œü6ÉÕ‡$ä6ÛÚ[AEˆÀÑâI&@„倘ÞÅEû¿+ˆž7<Ø„ôâ‰o–[Ÿ¨PZCr†Ÿ¢=Ê …RDŠÎ¬"Èn£­L¹•UDRR…„`F¤U‚hd³I&J’È’L¤XpQ Ch|pŒŠ„@"È¡a+RÑ( á²AUdÂi#$@Ð!¹B®½ß •uÈ´M©­Xƒ"͉s OÇÐNø½`ÉD„ 퓈ò¼ÕÀËó,_™'¾Cƒ:vaè’Â} Цl€Iô?@ר·.ÛdP2C!2° !%ñ,ªÌ»e‚‘TF ±¶V¥´¢3kt(Ý.‰ŒEÊ¡^ $$¢™¬Af²F1ÂŒ1F0€„ÐtADE÷iPÚƒdÀÉŒS‘H¨¤j4¶Ëe$¬ƒ%– ÆØ0Â17 uŠRU-<  ã®TJ5³5d0$ ø.®r(-ÀìE>¯dä ½¨:À BˆDÆ6c½-®Š"`BEƒmŒ‰X Ž@CˆBBs ŠpP‘)vÓÆûæ/Û"$2/fKSýa-®ó˜h:ß¹ãüÖíOãÿwP- ¬GŽÁ^¹~—“«ô&ñŸY¶™ûQ†Æ‘G"L›*Qa.‡àë¡õ{õ[¦­q[EÉCèI’­½fEq­)óCøþ¼¸MùŒcà6|…/CßÝ,[›uH©bbH&(©ó'ù§`Cî&GØÚÀ#²ÀR„Èév›‡=·Úbˆò} ænχÆÁTöê¡a› I ŽëÄÙxí¤¤¼r”h·-( .Ð ’‹,@Y ×ÁkÕ0Ê(ŸƒW®î3®:âWŠlt{2\l¡E£Wnêß"Û—Ö„s•be’-u*a,'ÍÒåø>qà7Τu¬9 ö 4òDwµ$ÕÁ8=œ#Lwð*åéîç@"îoTv¾dÞôf4½ÎT8“—Z·vzò;õªÁHšU@ U·WÉÓ …ºJ!”zClzMòúoyÁΫ¿Wb.½‡°í–dÁ–ã°9çsí<ŽjÂá$oË/–ŒI¾¶Î¬×K»uPðÊ* „MW”Y-nr§ª†Am…8¤®G„¯wj“õc“ Khz€"æ»lݨ. ‰JDÍ-wRæÇy JÕF©ÎÛ±âò'&y äýß^9~-É”)ÒaÇÝÍLÀ ú‹ liHa5ØÄ™)¨ìÔ&™2¹³ÃlݨšK^ü;Ï-Ž»ñ»tQe3¹’Ê”€’’c¢0Yạԉ"zõ'ò O9Êõs®Á_x‚²»Ois8XDÁC6bLG‘dxƒ†˜nÒóád1àÀHØ->Eô™Id¢Á“áXÜ|Nnþ—ïVU2TLÙ rí|“ÈjÈå.Ömoziï7àÌ-ÖÙIˆÑ ª7IFwZ…£ô l ©E%Â$𼠇̈#ßå=uºWM9OPd‚T¤dßnÔhPbû7g‰¨r€eAR¬/Ê{k+ÑXô]GŒksK¾TñËá?€FòßGõ.}´ü½>†äÕO£ãgßï”s…r£Éà&&¹“’˪Ä*Q¹ö7‰$ÒíBdzô½ {}Cßó$ârÙþ›ä,óÏŽb•ƒÎøëm„ø,Ö0]ówçá "$µœh¬n^ä¿LÝ…29bMj£»ºQ3©U¯ÕÝësOÊ/fëKÌ.Š4SIyzq<ŠÄÂ/£~—£CníîñaoÕ`û»®:FZó3:‚³ni°U?³´Î;5@ϺHg7‚ŸBs» YLuåü±;ƒŸŽéô `U~xŸ9õ]=Á¬hjÉéÖ0‚S ÚaÚFƒA¼¡w‚G´ÖK„,6Ѱ(²ZJˆ¹˜€"‰Fƒ€æŠNÐÏ…$*ú,*¢ÂªyÑ¿Ûy}#éz©çRK‹€…Žå;؉!ÆÜ±`>¸'^øÊŠ¢žî©á¢°4`;îR¦Ø 5"! ˜ J &XƒÞ)Àª u F¨9Ç-£Al>˜9‹‘H=fA{%ÁÓq7šÖƒKndB{ÅÆL"öŠr¨# ¿öœT«s:ka¿&sÎaBû Œ7Â"È«çÕJ%p>á0 Ý$€CÓíj™#!2Wk«‘–ä´0œ\<¤Å~>79 šˆ0dÔ$OÊ/¡àÛK­\¥JÝ€,¬}Í©•5“N‡[[‚X–[µÆÀ4ëképMÍ÷Ö‹»©¾Õ0Ú emKV4PáÀÁ¡Ž±òyü~ÎÁ®CÍ*Wž´6”œmg‹jnÐÇ`ÜÁÜDLõÒAƒ?à¼"Ÿ0îÃF¥SæøL¶\ÒáÛ¦rßtúí%3XIf¤a Àfc H#"aôsQ?Âv(¬R*œF™J èJ:CcèÓç4X?sƒè¿`mIݯ’¬É³"òFÆ¡Ü@ç?_#ˆ|¡Øê!`O" "§+ öÝ!„;Ðá_Îîån›6d++¥œà4÷ž& DèSÄ}ÉàZú9fÃêˆlÎÞ›$ÊkÚèPP?¦Íò€°=f¢€@?ŸÆi5±öúI›8©'§ùnQ×>dvk 7Nóh)z¯c$eáú*¢ˆyWG=gzFR¥Y®Ô{)#O{T5¿˜@T5YƒõÜ>«±r]†'^0êa¾ñ/5Õ…èÅÉ­ ¾Øg›â•^r}ÇØÙVÅÛÕ=Š'aBKê}ÓÇ3'OÝ3ä,ñƒëÇošdÜ “†‰"‚‚¬T‹Š0R$@ö}ü>Èô¼Iø«eÝüM²–U|¡wì«fV°ô`åT`òõè·'¯„`®ÃAøkrÒ±žšÆùiîÿ2(.Ûi!ÇfÊ`P[6 ÖáÂ\¢€¥¢ŒðŸÎ{€Èw7ÑûõÍ\ L%¡·¾úžÈZ‹ï©¡†éÞfØwµoloŒ ˜bCfÜÙÍ¡`,èÿWöú\7ˆ‘1y®ËOÙ)p™¼ (~{q‘A{9;%|qÁ‚ϘO”!žô”í ¬w!{Í ˆ¥¥`"^=ãE‚,LAì›5$@V/;Q F4nš$=µQ;O.+\и÷¨ Ab€÷¢ b€öeÀÇĽÀ+F ŽÜo•5$‚e°k½?s›8ím-—b`Aˆ ˆ"$Ðë3+†£h@Ä™˜Ä`ÄÐ… PÁdX“skAF•Â!¢B 'ЛđK††(SŽ™ýËCVß…¼\Á5ÇR÷h€|Q ’d ‚& Aqøú˜·@ fáÂîAÞ–ÆÖ¼Ð¤ÇYR‰A¥.6¤*M2ˆ[ kE† Y2Ú:AMkWt†1YihÐUÐR¢†Y. mÕ®¤ ,%ÖŠ«râ‹C5ŒÄq¸å *@!¬ÍfZÐÓK`ë!£5RÆHÁÕIY E¡ ‹­B…J*‚+ý¬›%CfY‰XT¤ç I¾¶’i`È+",XÅØb[–ªÉœ9ƒvË–%ZTe¦!‚™ÖCÇ8r!ÍÞÖ‰J`XÊ`¥–¢T© JXŒÏM†‹Õ–*1à€* Å Š–î‰È‡©€»"ÅC–X9¸Å&D{Í-î‚\Ä8‚‚ÃP±‹=Ã4õ 7ÛÔ±:@H¦p ºè®ÙRãLf ‘| Hú«JÉX)`‘“ ƒ2Hdª‘² ŒDTDïT¢'—õü@’r9ó ç$.waà"(<Âe%lÛ0E½6EèJ3`äðU@whËØCk¢‰`EÀ| 智·¢StHd‘‘"ÝAi²)ö~Œ„Û Pçf>³4ê‰'¿·K,ÓŒ4ùœþeøV½yv*ðÎx²ác9†ƒåCHKÀúvvÔD’`bpˆ“’_żr»½“›6ô¡ 3]5 „o{ôµT«UÕÛj´]ñG2˜A™µbŠ’áNi ØVå£D9óÔÁGH{;þ±ÑDỗ¹Œ!"C˜$3]·Õp!õœ=N£‚Ñ›’ `<¢L§z¦pÊ÷NÈ›g‡Ò ý~gÂGÑÝg²–hNŸ¼yÑ9;Û M9¿jëB!œ(&aàLe¦„Ít ! Œ@nØ ŒgÛ.x娔¯×ºóðk†Äwáÿœµ›q6ÙçÌÕt'[=ÍL$YŠÍx½³òѽÙ=HLƒ km¬‚pàÀY"Ä&úlßwDý¾uî°ö¯®êcËR"ôr­Q"!^ YT"\_ XA`õ°K£#Ø¡¾À”‹·EѲ¶€8ÔcP_6DëI€°`À^Ïxg6òÿ'5ÌÃWÚS B®¹|lTzC˜ã”“¾"/êt…œC qþ/bŸ’t¾´Ä iCÆ‘V!h@âh€^€¹R”í¶?8Ï3ËÔÑìã– …g*,ÈT‰n„“P"² d•%Q†MÉAëò­¸žÝZ[G^è¢RAH…Å}0ò_$HÈ·ÂHsµ0æ hCê°l™(Úpé°0SL„ƒ Ä# "œQM«´Á­u²ïQs‹ƒµÐõú„…Èdø™ên}™!"›á¸ƒ"CóIDô~ö±…JIÔ0Ãà ƒϵ]ÖZЏ™$’!hQ 8P^€i¸º5CYàÁ)Abš£#¸¤àÁ= ;1Ñ0 Ø#$ÜŸó}‹ñ“=9c<¼©kk9'^ÖëÈeÞëcÇI®~w+wùß;•½9ˆ¼é*míϼà9ãñ„·àX¾_EØßq´…Ãþ~ÝÞ~þ½Þý|g+ xjžÉÒ}*©½Ä?3ÖQÉA<Ç¡ç¼ö@ñx´Mn©<çcr73 AÞAò¤ÑªNŒû”œµƒ=f´O;üÄ苌옂ˆ„ün¶M’±a¬ ¡»JéyÈžØ!Ù_5 ÙÔ B@ zsüñ¢>Ú$4–XrpɤSæx•ÑaÌíè¦"‘IÀ”d0/…‡¸Hˆ™Qà€@°P„à„ ºi?T£÷!ïKe#»à]ÔÉa›nL°ª±ëÛ“¸ÐWŸöñûèi~¥p]Ná‚PKƒëÃ#ú,GÈÛµlÙÝž>›ü~oõ~×oÅè|^®¾¹qù=)vÊÚª@d»«Ãt¸( ‰FºBˆˆcRhÌH¡ ?…÷ÿký©§Q_ Ù?«ÉŒºSö:µ£9¸AÉÈþ£ô‰œØ¡R L&ªhPC± HSPQ·p0z,å­‡†œðþG_Ýd¾y Ñ˜ª^ßw\ÅfÊŒüš) ;AÿBÐ"++©öiù‚º DÿWý,ûûîS™¿ï_uVà:®Ö83C rº‘£ç²Íî=Íýîé-ùm£¢0•(ßmDRw[;›°Û²Ð¹¡!) gUTÍ™I$™eãê½µUD‚`t Kµ¹<ÔõYsi×] ¬´Ö«íZ6Òª`˜¨ÿþóúµ¦ú’rp,ñ‹2C\0=¶Ásœí6‚ýÛU„à¹N:I±,¯JtQçeIþÊa Eµÿ­Ä[ö@1f†~†l.ÈF'àRãóBˆÏˆ×¸íùèl|èõ}±ÝºÇ&m5KNHál68‰ááã-Êâ-9{^…ô%ʵ L£ÊǨð⢤QH 0}¸6bZà±Á}eà¶,Ê‘òÞÁû^ûÌÜ"™ H¨öpiРТ()éáúå:6›½îôO×”=nuë“Ê ìzŸ®,L™dtÑ€Å;æ,|_ĸÞ‡¡þØ‘=é<Õ†­ïûoîÐ8~VëåÒÑb\Wì›2YØúÿÖßz_^vÜÇÎæn£Ÿ£¥ªd.×è X´9Ÿ‡ÉÒãË–û¤˜'ÙÙý¿‚óèJPX̰ڗ]qñ(зD_êq T‘ Õw@*$]ßDîå‹1x•ˆ© ´G®³ZQ9Ó[MI¨'츊H°+¦ CJ`RXH‚¼ƒ(Ÿ¢U9ÑÆL(H Pø*û¯°”cc?Ã#c¢‰ÌÙ$$ÜÅ{·ÜͤwÕµØÌ{oƒ—þMÝ5 H§ë2 ÎvtÎlÙÇ‘µÛŠÍC?™ýMÌ7éL2˜%ÝqáýîÞ“ÎmðÄõs͈b › m3?ƒò]¾WÅxöYï«!åǶN•l,Wž *¢“aŒd3¯Ü9õ‡´E<‹cvV«ØhmïÍ ν*¸W­eI½š؃­ƒ-î@ 2¶¬ ™ÄdÜ—yö4ü•Ov||/¼É'›œ¤q}†áUMâ®ÂÛ¼þµa]´þñ¥“}©r©—Ú‡N-5¦5êŒ#|qÏöï}9£oÈÙ,®ËccmnßæÑ÷™§Û,…éäysöûOUÿßøŽ‹KÖaò8ªà•—«6J¨Âòöj·oìþ'6poœcôWãáì© ÿc×(~¯ÂmÔa›ƒÿàBŠqòϑϊ\FjŒ—4 ¾ôè¾WŽïSõ”ðýM\à6ÌHÀ܆g= q˜B_Ìò¨¦A5}øC P¿ž‡°+HU €v[ôª~y€2EE =dž³€í ÔzHÅR@w·ƒz§ävšg…—EAyÞIÊò9«PÖ" êÉë„“LÀSDð€ÇÈçrXP9nVGÞ.ÅÝ#íÑÁWØL ,#Â> T­å·÷çõ?úò›ŽÁÚg<Öó¯×ç­ƒN‘:88jijGÍÆü~~o“C…ü¦t«˜zlXW¯÷ݳnÏ_‡ÿÔ#+øÒáÈÊB¼>¿ÉŒ>¼•æË¬3[<-w¼Ÿ‡þ§û7þª"/áÀWÅŒ?GS:H›h…ˆ{Hî=…6èªÀà\„–’eºY—119Óˆ9zèvºë<¿}ܾ¾èû¹á´!-+Æ$›óO¬Û…/F‰©h×Uj Ñ™0Dà1Ù‹]pRmD„Â0 ÂÁä¦÷ͰŠLÀØ·ïXÓ8ן<À0  Ȭº" U?("à̆oÌþç—jJ ¶ôîopF vŠç¼Ük£¨ëàO­$%~zš}ÌC.ýÉKÖ×Îñ «X|˜ï¦ â^ôäôf‡ËžÐ+ž§Ö—ø‹gu]÷SûP,ê“b]5›ZúF@TMýnüY®òüùk¿içæã_.³WðªÏyŸÒy´Ÿ4èz € H`K8c@r WSžr¶f2·ºÚ" º#CƒaÂÇr ’_ê ÅpŠƒX¹¥ú£zi ÕÛáO¾Íÿ£³k5ç¿ÚÿmEQM¢â«¶™¸žfº’ß9ÿ«âlÕm±S!Í7ƒtÆ/}W/’K‘xé|PóÄc8 ¸»CÄwÇ#9 W`“à·fc×DÃR†¹èt'´ ´OÈ×ÿ¸Myø§ù ÜSx ×[Uô¶ZnrÒ²'¥ÍŽþÓ¦êj{]ecÜUzŠDa8\¾æH3§JÀct%^8z¦Ò%)³ÐÓCWÝé‚7n™S©¥‡Ù;ÿLº…Mº\Þ+ëVK7a­ÚI ø@/úêAƒ§Ôâð\÷2m¸ Ũûè|´"È9&zqý£\*¶+s±úÒX‡ÿ²gÔLbFØîí÷°ÙìÜi$ËÏ>⇹Ÿà[‘jáÍTÊÆ]µ·Ùås…¸N ¤üËfS~MšµÕu¼ÊþòðØ/ GÄ6o|JW 8*v~·»ø(-JE5 …ú%ýÕ#^7}ûc^¼×­ Ÿþ%¹Šúâô~E¢{á”Dùç [7ÀëäL`Á÷F3{(ˆ+™Ý¯ò6ð”©LM ]ô?"LAÄùò[að ±zp»[‹fÕgÕd.Ø?9I`ýó½TŠW³Y%›òô×8²ñ5Ìúç5é”Ï’¸­þ†¯6jú”¾Û¿5z÷ö×ûùŽºÃ ~7)ÙF÷Øx€Žêã«ðçx;Îõ°ûë,§e0âÐóÊÇäbÐÿ–ú !ÎeT'{£?ÐxõgÌÿ95ý‹¤÷ÿ¡mæð5wÔ*%^[üwÝÔüSZ‹—òË,òeæ%³Jõ„Äð \¼\Výg îþ"ñ8 s:ó`}ëC%œñ ~ÎzǤ cÜ ßÛÿ~Ô²=¾”/¿Ö}ÿÓÛu‰^\BO+¼rˆ{Ý»¿ÃNŸ³„Üw¾vdöD¯=­í¶"åd']óÚ{ÂÛž@Pv8þx ÔW¯æmm¿d’Ÿ54d š„¯«¼¡ø ÙïHvÙpúß´“wÏMíÆï^ Ú¢ý­z#Í{ù>n,B„ë~"ý>ÁšÊy ÿ’û[–GxÝ'[ÞlúÇâj¶ò,O¸Ý¯žPˆ/aêöO{¶®®Ž”Ôö%»¹lñ†½ËY'hÆ‚[½™¦ÖMƒ¸xë“ÿj¥ìI9“šþÁÔò&Ïú+˜èYl,`mVÿìyÈ_7%w‘9]º¦^ ^jX<Ÿm]ö£Ü ò[6}«Ðž¢ßF6ꛄÿñÇâD‡[O­Ífõþa¾èJõÎ=®µ³-'ú:2u££nfÃÅÊw.+*Œ%gW@2f·f¢Î6ü³P½zÛ_¿+ß øøYÏ«õÁVßåM” ¸|ì‚Ôú¨|Æ¥Þ†·ltmêPƒäXÈîó8¦b}ú­Íñ&Ý9×tgÍS¶•Èe¼O*]6o|fßCÔúÐmûê·Ý×4D—Ûý&ô²û9*Ÿ’_Áãµ{Ä«å$>ÎY«Ü¥í÷ÀôòÌfJo2PßÌaÍ;µlF||Íf«­nMAm¿9\¡…² ã]1BA»pXJS0ÛÔk½òõ&ó{lâëÅmPê©£e}SÿœÚ…Ú±Ì35þŹ¥9i¦cþÂw€¥ÚîðÁäΞ' F¹£Ó_Wu^†äï—ª”hWk™ÜÇá¡z€¬3r9Ÿ¿’urcóžPVüU'[šª/Ú¦‘kþ-ÍåšT¡øTÊÙw¥JF Ëã°|y’ɼÜnŠ˜]…E¢œÄºÍŠæt—-Zq/eú¬_¦<W I›^ ÌFŸÌ„«Çñá¼æsžÉ¨†kOè\JÀ³¿i^Î_y²?;OaTår~Ï‹²Eõ£Ü蜅¡øÏŠýv¥ò½¶0Ý.­Œ3~Ú¬²ˆÆr3ι«è1;eV“¬‚ò-©³*…ÇÐáw;ÉÖÞ3£ìúòŒÛ,Ó²=’Œ'1õž>c2\ëȆÅá6ö5µFï¦TµÙÿNÊB„Ý~ñhÕ ÿâú“ûÝÚ.íÖ°j­Ž›W]ïÉ Óo´ï%Õl¡{¬1¦~Öj»ò&¦ðxð^[zÛæîƒ£j¸š”ÊCB?ÎЊ#®X턺VùïG»cö}à[ú&iÓ¢U2YÒˆô2¶wäví¾Í^Ìnþ€»Ù5ƒ‰zøh\Q9ºáü ö’gvk¤i³`5J”ObjÛæ&ç<1¢Ÿà_'¦V®½¥œ’@ÑQžîQú•?Œ8+έþ$7¦úÅÿrµ5zrhÜ®ÂåÔ *çìŽüàxX¨*¨#LlØCC?5R[AÚÔòáÿDÖ¾‰ÇÁàð7`Gv· œlikDåèß„—O[jÓŽGš<ÂÓßK¯né ¶¾Bêwi Œo<”ߊ{%_ú}L‚c¹oT…á<Üô I\o-‰Õ¨Žx·Ìák¾×7©ì9]+«&¶ÙþByU!°æe=}þRœ^¾x€[>·×ô5ŽÞŒ!zO?C-œýå„y÷GÆÁmôæSôãäÖy>‹ß*¹/§1¯zöÊèúÀ '§X¹ °P—útÀ¤ÄFI„Ø•·5^COqõlj'•†ŸJIÞ£#/¾U ¾mv4Ý]sù/çïŸuûQ&ÆûÊY‹–ÁˆÞ:o3Ÿ\–Xº}_IÉî·ÃöŒ…IIE ZJº³…>#œú úTå®_òí/­"±:‘Ý÷Z|,½ês‡þý½ê|.wÜëÛÉáðô£5NX„ p*¯-vi^–N¿ÝgF¶ ßw»üx÷¥,–” 2í¼Ú3s•ü+¬üWTÂ~þ^w[‚»æÕ^ÏCŠS¶qÞqÐWÒk<ü¢Ó™HÎâ×ÞœC©ù_Ä¢úŸŠÃ¨f„7¯u5Ã=i—µÛ8oЕ<Ÿ§å‰ßèÁI<>µ‘oÿ5öåë¾»ˆ—Ϭæºm—”…š UÙG‚$üsKȽMeZGlúÚé®$lŽ_ߪØm„»¢ÄÇÏðÕ©P({Oï¸Ðç‡ùù»¿ÆW{ÈÿñVÀŒçvP¡ Þ6ET̨8X¬]ÃCÀÊõòÍ ¼#œý½ït­{ËH½ke½¬ÃĦ/¿bÃÄÍÆíÌ4Þ¾Öx~ïR»þ¯óýóâx49£Gêû”´Íÿ†6Ó¤åÑ}ã~•; ƒ³¦ŠhžÕ¯¦ÒN$ìÍÎá‰EåݹØ×Õ¶‚â…öüüϳÍVîfî«p0Õxmß]¾³i^†¦ë„4XØcÝÎþ iK»ñúFGþ²»¾¾bæ—©j€¥ÊÑ"Äf‘õª…üP¾œvŽ Í7ÔövÙ‰¨¤Û(· Wݾ: 9;Óvq›k[3¸eàé°ì.Q5äL#5óNé:'°Ÿ\üZŸO±mµAÆn·í“Å(ÞWÛ«¥å´‚Ù=¾0Rë§*D|úÒب±„85ªzǰžŠíôjÊ?“iØò}ùB+÷#>é²Îñ=&Å/Ÿ&;Ÿrú*ÉïG¤ÔÒÝÉþ2kïRcy¹[¯¢ ^A)~Üeô’FaÕ}á[dûC]á¤ÿ–VKß<ˆ»Ék±¼ØtÜy%oÐïæ?åõ‡% lZµòŸYŽýM‚ ü(èôIw¡¬«QÓŒàÖ|ÀÉܯ*ò@;›ãK4¿×P£ËÔõïá,'+/ëË·ýÑ»0gRgËêŠÑÀ Cñ8´$ï/ð•k׿`ä?Hô©ïú›Ýž]ƒóZ9￉iØÙ“LbÓîÔoñÌ)M ;HøŸÏ¦Ö'Ñ9ûíÀÈ#¼dè߯>èÈËÆèÒ7^V³ˆ_Õ¿>±êÙ8|ÆåœÇèuÿIÜr–emñÍ¡Ü,wœæ-AtÕÚŽ"wÞæjè¦6qû¨•åÂ(¿gÇÑÒ®ùŽ‘ßÇ ÷Ö&o–Ï×AWÍOà›ÌLNÆ>û¹¼[Ä€•Š3«ú¹®ÕUjÈ<\ y>;ó«/ŠÝ_U¦hyoþ^Õ+É_–mؤðé:ññ‘Eã_¾¿Ùlò×p#wx}GEüŸCtnbí>ó1x;w=}Ûçü«‹Hžc{î!]ì„4Äψ‹Ô-H}“/K8/ ºß`4mŒ•þüøüm“õÇÇÃæ¹L9¹Fe(´½W^ÄFÚIú7UFé7±Á;J’OÁ?¹ÏÄ?ÔÍü77µ¤Pp)Š¡­züJo6(5;|ºØîýûÃ~'î¦â÷q㱄“,×Â^„ú‘>P9›¸áî;z½¿ãÝWåâ½åöABS±£fÁï×[êÿ«ú lÚ’Ýnô_ƒ3ŠýqÈkº‘áÈs6•¶÷MÖ[Š"è¯ÕÆÛü™·.¢VÛŽ˜¿ÍåH²úŽºôÚUÞ›DH±•cyo»œhÆÃièràV‹ ë+ _sÈ3ðï´wœ–öÉø<$TÚWC3+X³fÆäZ¸“K.VZ³œ·ý‘ʇ|R¤§Ã‡ßŸÆÈÔÏ ‹}­Î¼Ò)ìÕ§§c—ÈõCù‰ÍaöèŽì¾©_ëÂ'y»Ô†5,¸ÄŸçf Q{»_yÍ­tlìæ=­¨[êÃçñß“ø5´÷ê)ËH#δxk2·Zn5¿îÓü³éU ²Ö;’Õgë’?&mŠR}LœUž`Òé·Aù"@@$…•Ï•Û"GJ3Ö\È,gñ„ 0GöVBëž’U æKâá £"¶¥óQ£ô(¨c g„×z¶Œ|Ÿ£ò/fî2ôïêš3;½o=®Ÿã^•ÞúrZÐõQÖøöXT¬©tUü}d?rÒ\¸JGg5ãÇ1û(ïq5*Ô|¬£;'„>DÖ_µƒÎö:±É—µ+ÛR¸šzþÕùÒTs:Çø~.öOÆ®#ÌOúº£òaE-‘šð¢³öqÊbåÚdoº„íñ%7± ­rµTûˆÉBÁ‚€’ʃ=•½Î?òÜÛï•Q¿Öy{•K!h¯ÜY_¦j'í¯e"fúYþ«dýOÞ8ªŸ˜ø¾/< k¿ «ˆS“Ùnåƒ^OYXüÌí©Îͪ‘Vx!ûÿTtCHË%Ê&ÄÎÔe²*U#+bÍÜ£yÎ"7£Ó\=izrkÜÐòÖ5»ÎUG4˜çêÆ¼e†‹ áHN‡2Ó>Ú»åóq0ÏŒ²žù}ƒ`¼ÒKDéϴ¢W|x´(× ÎAº[c#Ÿyì—˜k£ßt™¾U±Xh•ŸæT'µ¹¡¼Xmñ2I²{àýÙ{’Ž]‘ÅÒÝ*ØV²Ÿ$eŸf”ïbŠY!7–}{¿-C\Ù¹¸>–ø°Cóì/ 5¡ú&XÉ„µ†(Í–¼[b:»£·Œþn‚±‰m&)NÉ&NOÍ;àÝSˆ0=ù\W¼ý$b>§Sg#Ջǘ,(–Ô9¢kTf=0Dç*g ˆC€ 4hcbd~ƒà p03¿_Øvßõk$Ø y„  Âq”uý!j’Eµ)­™‡ -å2OMC•°tǧêxóÄa¬Õø@ªFîª2‚Í—¹E]¢£ƒ2Éá‡ÙW¢ÿº†)Ú4–C–‡ëù¥_Ñ̵ˆŽÕîæF]èMi¢¬¦ûŽØæó`þƒ‹á¯S<óãŽã¿”ùÞEü°Ì~õx0F“$dË£ÎÛÆ»eüG_!=»&ÆzçRσN´µïhÏþaåŽPçÞ‡‹¼•¾¶;º‹rvAaÞNGo´à£ÍAÉ? ÙĶ]åȦœ*œIxC¥zMhˆú¤›¥OTD÷k¹˜`3þJƒ¤f0‘õ#w  goùÒ,Q‡.dïÍ`fŽ»RK‘¾›/ÅM‚+“ó}ŠûÓPjê{îg›‰GÙÅ]65ŽT;= NÿüðôúøO‡{“qêJÑçÒz̺n^š8XúŸû6î"^*IO…G¹Gœ§zê·¼UPÛ ;nÑâFwÍe•äùX–!߈:2ëa9—Çz¨’ÞŠ\v‡wýæÍ}&ÃÒ1¬0òw¡¿og/­gÙ¹Û\/w’sç¤ÙA®gÃ5ˆËõeDª­oŽl˪ïÅnÔ«Œ‰ ®-¢–ô*h>L§pØ?Ü/Ñc³Œ_ÓL¦4±ã»kjìZS'±ÚMM}‡Âå«ÏóWÒÁ1Âs9éZÄú¯ŠVùAó‡õLëJ[%á®ZH¥§g“ˆþv¿­Ó%P¹}_)¹F#ñýSòù™ ´t¨Þ¬6æ$•Io„»\þ䫟ZIIÅÎ¥`òG o!J&œ"ªLãM­Ë€ßŽ^²þwE®a{Bè@$¿­¢NÚ®“㹎7StŸèõWt®žßÍ ¼X26\^úZ¾á'‚m lúåã”T2 4&y~ëã"|4ž>MÎ/Ýþ‘šÅú¡>Ǽ¶ôΙ=RÆx»ÉôÛô…O@Źû.Å66°NÄ1K+Ô.PÚߦ­oxçñ_'¬›_/>)=‘|5û³#Ÿ7ÑÙ/¹ÒñSaö¤ö˜¾O6]ixä¹_‡ŸµIËSã³D*‡c¾e¶Mn×ú{±ÇÍÛntnõ‹œ0œ»+qu”¥ØKÕ ºñßméÕeùÛu<¯6¦jQªÛL‹l"‹L‡h5= –”$õ3}r{Ü:®÷­Z ›å1³la¶D_E‰‹ZGÞwM!®h„ „Âr­“]=bï„›»ØÛ³oÛ—Ã'^æAïäå‚K cÂöØÄ2´A—‡¿¸Ñ+oÀßî·~×ÍuiøÉ ç÷ÿú+НÔÔ•·Ÿå‹B©™ýô|Úùzë6§vqýG~Áÿ"xÊíTeS¥îþéy¾Ùݤî=võæs– <]Êûk17ˆP>œ\.WèÐ?͆y‡™¤ý«ÍWÍn·–«¼ë¡—§ŽéÏÿ;Ûþ|ÈÔØ°\cíÄ¥LÓÂ…û¤Ï±mu– yØÍ† ¿ÀÓ¶9qHÊÆÞÖòúã*2i?ÎvÑ ª‰ö,¿Áuý£~Ä»mN…³¡ÚJ®§»7ÄñŽb„TÌÚ¨,wz,\Å…¹Òõóå"#íšdsöŠ8.U¸ÿn‰T7£ü‘8Œð=H5銲è¦Psü3&_>±ÿ(±×§€[ ‡Îy70o“+.©u‡l‘ikmZâéš^¯Êߺì$¥ÿÖ…ÎÙ·Ñ‘´<ÆØÙÒ”ËôîåÉ\6Ì/ôB†]/"¯N¼¹ôß¾‹ÃÙýÉ,Ú**õ&ýnH)n` ±ŽÍd7.§¯ž™ÒÈ,Ù[Aòþ;?ËÛ¦SÎoq:•çùú³û]DJDyï§u ÛŸ_ó19°ýÖ–Ç%èxí3®ó½²`Ús¸üR çÎÄjǧù´.Z\þßv\5I6|^C‡Ý½FlÓ²ßŘžÖî÷ ÞŸ—’ûœð䵉»òxX‡]§\YÑý|6Þ,ôIø%•ƒ¹4l¨v]…k ãö‹Iy³˜K|“\}§ÝnF¹¼ouŽyB³ò‚1#NB'Rn«ìÿ?‚U¯õ±\¹)ù°öþ 4¼¦É+úž53ÿïµõ%O¡þãþÊw"8ØïË››$É×\Kz·o¨ÅñÜO\4}@ 4øM1ŸE®2)«Ì+o]ùWÖ¾0µÜ/îðî²vàÇëw'úòÇb.1)¼¸\Ãy=¾öcµJ 'F“K„p .Ôø ]—Þl£§sŸd…#ìD{/”Êör¾l·çæ0 «@åU¡0ÇØï쳂®Û#|’§ ˆQÍí³Ùac¬ÈüÖäåÜ™ï«ü Û\OÐ!~üû¦ÏÞëè‘Ofâ•i]—ù™Nõèbðפпñý½i=ù´evÁõ¬o'‘³÷»x¼úF¤z%OhçŽt¹WÓ{XݘŒ7Oƒ#1óÒD  cs_%,äž5_^='ÔD?éÞ³w€Wi`gùãå/uË[ßÐûhtô?>ÏînvGSvÓ¿ŠXoi¨3€ZjÒ¹¯æzßCmôUÿާIªk¶¿ŒÃmÇ ›9ãÓ’ÈxžD¢Ž2ã’=ܱY køèeM£”ÈDS8U»úøpühwŽa»Êñ‡:NÏïÁƒÎ²uÒÓˆL…I°ãë2?è!«s“íá8±ÜMÚ77¢êÝxŸ—Åò!s½¬Kýî–ç”nƒïC•·‡6ZþRÖ}˜Là{ù\x{ Ô&óI"l”Z›7Ôô¡ò XÁÇ ×ñ,%Õ,᤿z@r\F€®Öˆqñq´ãMèyg¹r®FAbÔd¹}nÓd϶¶þÍÉön¤ayX5 q¦m¶^¼×Ö+3¾‰10µ¸JªœZ«£‹¾«Ä3OÎp¸3}Ùùªêð]áõ9õR9³‰˜]ƒü)ÁÜsÒìO ”×Óbc?ýÛb|ã²MÝEv‹é¸êüý0F÷>˜^ý Õ]g‘C)rî§uãÜÞW7ó ?µ¿6G6‡£;iFbj$ùe¶š‘HBªó—7$¹×¼2œ¼õÞÏGüoëG·Žò ×Ú³\i¢¼ùå^+6ÏýšäÕË“–¤ÜGçéžøÅc†/ëäi7?¹ktj"Wãé2›·©º¿¼É1F½”îìéÅÀ踛s^Öý©è8õûóží«ßlŒ÷•ÁêzÈö ‹×]a©¥„oÈÁ³ âÀ;©ÉNŸ¿/>ߥõ}ãµKk=ßqÓå:½dÞ?Jf*£#k÷ÑCCõú¼Ý‚;þÛƒÚ~× º­Ûíf8Øïp¦úÚ¼ÃæêzEeoû‰Ç7­ÃEßcís³Ûè(9PZž[ 1ƒ§ÎÐßíæ?‘ڔԫƦ7:ÌQ‰1üïʸ÷a¡S nùÚç~|ç31ÑüdÖ:KÁ~Uµ8âlñÿ׃ÒÈàxfu¤´°æ.Ý¿0ÁÞ±ßÝp.tLã\fjeT²<ü ˜ÏUh4˜ó¤u˜N#ù<ÂêØ\(îñ.&• “½ôBÚ7uP܆¶qü"u%óï©‘}U–9ê1‡Çô$ñJ˜ÉÕÒª°Ê;/Ÿ¾3µ¦-瀖 ׿u\„15ùðTúEl«¾ß¸‰…/û™ºc"tiúWû²3÷9gÀÑÂÞäú0f¯ßçxÊukðÏ|ù}—O¹yV˜OwÁÝ/'r½ðžîkôËþUFq¡®Lìr][àüÙùH¡™Ÿ?zMek Ÿ4eœù¯»þOY—Zj8ïÏîMÛé=,àõ,6ý%ŸIΛl¬ùjz‹nµ´,Ço•Ú®Ð1®÷üMÞ}'/}*#l¿yöA_d‚ Áó‘ˆ07çÜÀîþгH!…·ŒžDGÛ™ ?>š;Öÿ!oaÊéªã%Ú¥$¡í;u¾U.ž@ ÎÅwu¢C‘œH8ñ)gºoN,ƒ÷ai›¼¹N¯íwSìéÎô±sU?Ÿoî7Óà’¡ÑrñGRCÎn˜ÜNâ÷¨¹{öç œUOíÇóͬDãįùíT¿|ìË(l÷8ežþèùm÷”îbü9ö+‚H>×Ô—¦…\ÍQõÞ±±»Ôž=‚žRÚ ý_ž¼Ë³Õï)~£­Lž£ÓíÙþ¨O)$çîêp‘øÚ‹S¤<øG>;S·8Å4öËùSÿsïV(—#ªhÓ8³@ßÊþGâáçÀ?ÉšàÀcˆæ(+$Êk6˜3×€Ìkÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü×­õy$®ãÒA(,}XR$©(Š@¢©@$´„%_}¹.àáöµ´  ’D5´Û%)èÒÇ" $HJª•R D ’UTU*$” #YJ¨RˆET•*©UR‚ ”J)E$•¤…T*$R¥A H‘%T *U**’BB¨•UP’•Jˆ€*))Q”‚AH¨¤¨H€!)R¥D¡$J•UB ¥ IHR”¤J¥@ *„PE(HB¨H¢U*! ”(Jª¥ ¡$’!I! DIE) •%TE‚Šª”ŠT T!Tª  J’ €”ˆQB*¥TH¨Q(%H”’‰*”I…$¤ª’©‘ µ©$ g6ÄnT ¤”…B„U%E$J)"T’ª$»¸âª„’ª*Q(¤©URU)B*%A*)*ŠÖ ª% ¤„@„¨¥Dª’•J ¢Š!4Ȥ¡")EIJ ¢JABAU$ª¢«c "”TR’©UB(*JERª¥IT¤¤¢A$Ö@’$©EA ¢¥¤„„IUDR‰@¥uŠ TR©J@P*IJQ)QP¨AU:Á%T‘J$U$‰(¨”’Pª¡ $J’*‚E$H”UTJ¡D U!(Ѝ¢•%ATRªŠ$QT©D•RQ E*‘RR$ª³5%I;‚Å)*A)$ªE**ªB „¨%%J©T«f‘% P¢© ‰ R"B¡*R‘E* #@eT¢„R¡%U"¨( ª©¢”ŠBm%UQE%(ª¤„’)TUI*JŠP•R” $¢ ID(T!*PŠ”( ‚’I )"„ATER¥R•*UR(‘%JHT A%J”ª©J"J©P•QEHª‚J’ªªI*‚ ªEUD•*¤¢)AEEUPEP@ª¡RªHªˆP¡)I"ŠIIJ ’DD‰%‚E¡"¤‰ ‰¨**…D©M±@¡u«JŠ„EJ $ Tª”¥€P*T¡%R$(R‘!D¥EU EQJª (ª% QUIUAHª¥DH”ªTJ Š„%DªBUWZ•$E*JPb%°¨ª„D ¡DU*‘"%$*Rª©()R„ªª¤¨¨ª¥H %JJ‘J%•J¨ª”$U)UE¢„ªJ RP€ *¨ªT‚ ‚¡J ‘DU APHˆˆEUD©EH!U’ˆ’)*„ˆR• ¢%IR‚"¥PJ¥J‚„$¢B¤U(¥!J¤¢””HR”‘!Q*€„U¤ªIU¦¡Yݲ³•$TH¢Š„”¨”UR¨Š"”„UR©U ‰ ’¨€AQ*‰*R…(¨• $$U!T”$ QJ¥PDŠ* *ªP„‰"”EIT©T¤RUR¤”¡IR’’DŠ¥J•RBNÍ"¥* * U)IQ•B¥*ˆŠª)J¨’PT”•ETªª(ªU• AQ@ ¢©T¤%)"”ªA% ¨H¢‚$TDH¥T”¨)"¥J‘P** R”‚Š"ªª*ˆªR…ª’T¨(%J¥TB J¤RH%%IDJPU¡J‚U P€  ŠUIIT•R›d‚©bænHR $!UT$%IQ*QH!T…*¥E%QE"”¥DJ•ª*UJ©ITR*¥(TŠ¢ª‚¤Q H…"ªTˆD ªJª•*¢B)T"¢¥* BH’‘Q*Jª©T*¨…IUIU ¤•TIR"ªH*Q$¤¡T ©$ ”ª„¢¢J*¥)…%JP•B¥P%E*’I( •H‰T¨* ‚ª*ªŠ)RT¨U *ˆ$¥)”¤©(T€‰PQŠ”"Q%U¥©"R$Š¢)(@%QIEI*•P n•w(B(J*Q@ ¥ EQ UAQ”I*P•U*•"(HHH•ER„ˆ@J@Ñ¢AQ ¡(’RA*¥"ª”¢¥EUPU@‘ Jˆ*ITR)*UUPH*%R¢¨D‚’$Ž´”¡*ª•EB¤R• Š!B*!I$J(•JAR‚*T”ªªIU"*•P¤¢T%J!D*J Tª*% ¤%Rª¢¢ŠQ @ ¤¤D"• JE"$!D©B¨PT!UH**¥J%) ª•(A@*ˆR"¢ªŠ * ªR¤•)"QURD©%T•CfTŠŒîÚçB‰!(¢¢©T‚ª * @‚¥"ª‘Q "JJ”UUI!!*¡ITJ*P‰ IU*Š•*IQHJ$D *ªT)HB””J‚P•€IJD¨ªHPD€ UT@%"”•%T(’ªQJJ©"ª @¤"ªREU!*¢@H ¤*¤P¥PTJRª(¢RJJ©* R‚HJUJ@Š•(…R„””ˆ©DJ‘DR…HT%TRTФJEITUUBª¢UU BH$U)AJH¥H )P Q’H¨”Š ”*JŠ‘T’HQ% •T%I .ÎâB%)%)!(HJ©!"ª©%HR(…(J¨ªB¥%R’Š…EUR”(‰IU ’Dª¨•PU** %D¢Š!*T”T"UŠª¨RUP¡BU*JªUJ…¨*RH’„‚ IRUQ$EBˆPI)"*ª¨ªTQ"EBAA(¤%•IQQTªI($¥"‚TUR)”ª”‘T¤¥!TBIJˆDB”‚¤H!T¤J‰TTªª¥$¤¤JB•T¢„–ÍD ‘ID%B¥Rˆ”¤©H P¢¢ªT!R"%QIJJŠ”TRT’E! …+Y)2ºç(UPQJJ©ˆ*@TRU ªJ¨JR‘P"¢¥RR•Q ¡*¢P R„U(BP*¡(ªŠ ¤ QHB RUJRPER‚•¢(‚Š‘$T•* ˆ)HUˆ¤¨E*©@¤R¢‘ B¥JBUTU  Š’EER” €ˆª‚’AUTU%)¨(T ’$D•)B¨¥I$¤ªT"@•T(”JP©A(*‰H)UR”RBªŠ”„J*ŠRIUBP¨*U”) ¤’T¥P‘¥Tˆ"•J ¨ªEE!)UTUEEP‚JJ‘DªJ’J[D  {J( DT’”@T5ªç¨…RR*ˆ ¨QIH’‘E%J…IU(¢%U"‰JäAÛIAC ¨  U5 …Ù¥ @y˜ª@€…P@Pôm€ 4Ó@ QJ¢‰%öö ª%H•Q*•)a(@ €Ñ!¡¢dô#M Ði€4È 4Èbd™=M¥7 Òm)èÁ h&©úi´M12žŒŒƒL™2O0@Ñ”ÓÊ=HE=£ )EL’ž¡šš ñ@ 4ÐÐ1ˆ  €) ©¦LL˜OI”Ù2l¡“Ñ=LOHÚOS ‚fÀ`¡0L&@3ALbi£4™2'èM5OÓIå6Mšz&&§´Fjž!“¡üJJI‚ 2€Ñ …MÓd˜©ø‘éèÐ4 êd›i)þ¦iM‰¦Tü4ÔÂ4ôÔõ'èÒiäžSô¤üe SÅ3M1)¼Tü˜4%=¨›ÓF5'ª{bžLSÓ&ORcLOU?jb14Ó#I¨"HhÓ@&@ÓSȤÃDÄÁ¡OMe0Œi?Hõ&Êx†§ªoR~“É’žŒÊM©úM2Li©¦MêM Ú§¡ z¦Ù{þõ€Cô(Ÿ)PÝ `ü—Áý/UïäÏ·;sÍõ|‡ o–ß¶ëdØûO&îV_n}P±%6tbçïZÑ]HÇŒûm_µÁûºqp ÐìJ B~Ðkó?ÛŸ“È¡„FÉ›Ÿ²ªÅ»ö#=ÚúC°ÒR20[Tƒ…Â@‚Ü‹¾‡%ò»Ã_øuªAô ì}¶Nºÿ}á»Ñô}ör(Ÿúò6 y动fö\—°ëäù©ø,tY>:ù-ùýÖ§ìß—g‹‡ôú­ãŒŒ|I¾Ø9˜H8m ˆ´D@éI³¯üª%g¨,­¨_œ­:WˆÅÀïSD“›}…¨4¹´Àü=±Fü§a j¼˜û(m[V¾R–$ ‘íËß nŒMkŠ/1ÓáºJávXQÕÉsS5 3om§C5£5¾.–#ÑDRK”L…!SNÃÖÐ^þäA²(ž ÇO€ëd66}ÈÇE—²o5÷Z$É+Šô~û¹Ÿ~ÑÉÆ²`§ôÄþÅ £äûa?KèÏ«ú`§õAOëŠf b ˆ‚ t}§¨ë¿«éWíç52ß7cùTJpÚ¥¨Eí«q`ÐÁü·!.ï†MÉ~ö¿4 @º(ª–€‡òöL<‹ÇôÅób!~¼:%EὌ6[—ú½Z¾ñ?¬~ó„ãëÎiÅ·ûXˆœ¢’ôµ Úsð×/érþW/Sí+9&ÁM¢›C B ;DHAA„ ¥1ÕRT ¤°}+‹ÎÎÇFÖXШÁ’¡”H§õ6['U@ʨ¢‰!œ†0ç9²êd‹‘¶TO·‚Ò"§ð½]¢ AH CB?òaNåÖW‚õ!âáðruðÒv‰Å»lµá¬$S‚€§ TÕ»úU¤rW¤üŸ¥¿_×ë2îiÙQ±æÎB¾ÞÏ&ùa ãYŸ¯¨™—0Ä5Ä2&r^Ö  Džž£`ø7*·YÑQ”c;ëÛÁ¯—«óÕ!¶C@­/"¢Xå4Ô²3c …$uÕÐPº¾ …b ª™Ö÷|nãÇྸ¡Îáböú§JóQL(÷ÝkðÌ<›q]À®ïzøaÏjž.]\·ô ñßPèÞS¯¢­Ö c÷£“殌êÂ%wñ͘^Û+M),×E.,ÉVý7¦ u ³I†óµÓ³Óº•63Y'Þÿ‘VˆŠ›rH/°3c’§{¾s#,Ø 8™Ø•Ùgý§â@@Þ,†H§0(4* Xhj¾J^.¦rˆî¯ISòôT\úåÅ5UBÉÓ4SådãWØ©²K:Le1ûÛâþþ¿5ŸŽ ³3>Û}d¦ñ:Û‰ \éÜ\“€•Ìkºé„§ è†ajšRûGæ7×›IÙûÆ1¹Õ,$(ÑpóMù\_.|gZ“ºŸ('õgøxdÚ®0ìóÊO¾ÅYæ½Á‘T·¸%Z§y›zü†‹!ÐEÜÍÕ={‡ÿ”8ùê¹ôPn‘<«ÖÃÐ&žkæ­ç’½œâ–k¯vY@Èw DÕÒœLe÷”€ (%_ÿéøíÙûíªÅt<Æ&½3ï§MÍÊ d˜``r¾R*0BoÙ³¡’ÚŽP¥sÖUâbAçÍZ¾ñ>‰¹û„þd–žùD±.ɽNéÖ+Ö|cQ´ RsËÉÔ‚Wyëî5 œ¤¯“*ÀòÚ$~ -#•Û3(À´ë(zý4ÆG×~=ß‘àFºÄ­ËþC_U,‹TFøÁ‡¢8Úè>ˆSÄ᳸‹×‹¨I6¶vjÃg~îåé÷ž1ÝVf“Ïwæú Y*=â_`‹Ù!¡ºÒGuy¡á-êo‰NH@@_yĈ†¡!Aó¿¸U1~ü«Ò¿Ù‰DcëóOü?¥þ­¿B*?¢ @Cï4wÍHeSçmäýD¸)€þС€†vOÞý÷õöäãDÌH‚(Ĉ¨ 9¤&iMRSôÏ¥½²’1AÂ$€ªÙCüh‘GïPÿ³S÷žï÷®.‡÷Å2±‘vаcÔ•²DÞ7JµÉPk½š,Þœþh¦Úý^ZÏö,}né¿¿ûmJ¬¬rZá| p¸¹þ³_êÌQãMÁ>ç¥ìéN®PzßÞÖt(¸°7yîÞ{ SÿÓÞ­Pr®æwä—BC´fd2Õòªh¹œèSÁv©ºjÄ"M±;Xh ƒãøš˜ý+Uº´KÂ|³Æ…ŽïH¤¿Ó.p×-ÎM¿VÊz à‹!Qd*¥B H@¦ª|E‘3¯n¬:¹êÊ?Í'™‹ – ‘ kAr°ö5šë]ñĉ¦¿kÝlcäVÖÉw¬V}ÐR«®)h*§†¹Edy{•cn™™ðpµGi×Ý–{0×o:Å¢gF¢¤DŠ!º* „PIB  –ŠŠ^Í“Š±â«óTs‚£œ@¨ˆ£¡qNئ ÅqE"¨È‚)®¢9"Y Tj" ’(–ð0…Ãp†Ý .²Ëcñü—ï繎²º=°D/ê ª"€¸ßžF’ÆÞƒ%–-²”:°Ak.kÞ‹ÊZÕEô|-Ž«ßF]Bš`fBšÄX)×óy~V®î³FÆ7»V®|ÆÛ=ðΪܹßp§×ä6ñ¢a¿j[¤Xgè¯ë"ððÿº&®¦—W=e3—Vûkm“ "ø»€‡‡¢ˆ À‚s‘‡Ñ)BÊŠ2k<žƒptM¼NPÝ4ûµN¸)~0SAM›&|i÷…5S¿¬ìñlQØsñø|w=ÖD0°ˆ=!†y†OĤ(¸o­·xkè )7œÂ›Ñ‘N.=þgèþöË0EñŽòàƒ¹861Ú¨ì>±ÉoWœâê`æw=@ï {G•‰O0]‡OÕĘíï[A·ÏO/z¬qv˜¶ zúrDÒNÛä|UtiV~Û–ñZ·u‹fÚ²ÝfU4TñB!„Í´\b¼½?w¿®ó× ªçäéý¾Üøn'7=~d(ñ‚/Q/ñôJõ°CF|ÎØBîu ¨Jä*¬tAϸBÉͨ"™®çnë,.aŽÃ ×&‹1u5ØÞr©R†™5“aÇÃYåÜwnvòyîܸ;$ÛÇ»–tpmâT;Ÿó‚€ú`šj1ŽãQ¾Îß&ΤӳîÓÚ!ZE¸ å]@Hfv ˆ?¿¨ÐÁ£»¹!Ma²:»*=Q|ÁîuzA5ñjó:½kOwÑ…ÅqµjÌêl¬}ÙÉ'xáëa×Á·MæTºœ †°ØíÚı Ö¹z­]®·!~-–ÍÜudëâ«®‰/¿ÈÕ¯ðRû«ª5ij° .3Q£J”/àb­ ´«%\'^Ê™°%/<˜‚cÅqÑ‚à˜É íì¾Ú®rY*¶ò¿ܵÉUÊ·†ÞäæÓ¶åN{®Ž&’L\mÅP¹3°yõ+ Q0Íò!Ýäæt†ù;Pεï«Üµ‹–µË°y »Îeù,aœ¦uœBå·©ÈD1šPr"j<¿EÞ9SÒ=(¡Ob\R v8í»’xaÈž}“d&þ½k@îâuºÁhëuéÀ^Á뜼»FŒ™ÂÆJ>¦*V.gœx¦°­Î:RšC!‘q‚¹MÓ>X®ÙÌÎT¦Á‰Å3¦˜¼$~H™éŠª’É–¡ú·•t¬Œƒd •hP®Š·V*‰RmâäµJE®Ý©ÆHÓA4µ+Ÿ%R …JëègÊþ†ú)w,›5Uš,µBo†¯c‰õínJm¤¶A±Î‘,ŠAn’šš ëÕkÕº„I¶¸d¯¹Q¢Ê¹w%ýªk{&Ìg%ãaRãi鮫¹–ÝiU\°j畹oÝÚÙªYlÁîsWBL|5µs¬eâ-çò&GÝ}ìdpº›pÀáé~ \r°W°cÅ–”Ò Úõ:—ùžG3Ûh^ 0Ó,/Ó WðT¦M9àªWäÚÔª€¥óhçÈÎZ°ã¢!~Yï/åν›K{•óRi”m źInÑeÚ.zÑ_6³ì0³§K‰w~tBÜ÷¢V¨ª‹µ£›†ýòx±9ΚÁO4S.œvsK9:>D+e`«‚ÐÙpÂÑe g;öÅÊÈgVÑá¥ûØ­Àì×®gÁÖà¾ÍBºÝ»c~°)Õ8ðC’J5 î3âÑÃ= ÀRÙ–Q RìwyÖÅá%$µ¤®EàL£2Â1‰Z$m¼©kž;*ÝsÊ¢™Î0ò8)ŽxʵÔÛ·3Àé2\Àbu4.;‘å²kU±†å ,W©aC,ráÒ†u$¸d RvÜF/iãÐ{o´“l¨Z—u5“ME„S?y·¯z ª«¾¸Î}/[Y©*oö/d(f3t›7ðo«¿:[Ý:_Ž- ]æl³“e¼ÌÌçÇ:¶ª»~¬ì»÷­Ë×t›„½#z»—z¦F÷¯Z3ªÈFÅ5WVîґԲȡ¼Qm¿+½{[4uLûmÓÚ¸Ö6™©z l™Ú5[Ššô˜ŠÑ˜ß°Éa¿Gëj` ¢!»Áx3õ²g—ᩉq6©Â,}™Æ×rmM+/É®a·%˜²†AqÜBmK…ÊžÐËaY«:I’ò™ØHÜ,Õtá åfVÃI˜EÃVÓ$õKÍŽyÕ&U;˹mŸ&˜î<šT„”–X0¿Dɧ¦üìúæàÍ̆j!™2º¡{3 4Æe²a§z¢ÄT2YCÓéÞðòn!¹67.”n’W! †Èhœ•Ù.a0’¥­’ýÊE…å2¨" T¤×yËxUx`sÙ*X«é4%|/ªªµ×2,´¥I¬SlÎM‹”Œ(¬âp,¿ë\g 2oc%O"õ]«0¨®¸ÉQ\!BŒäÔܶPßV5»2_x¦¿>ísnÏç!;Z­»¼+R"‡l…ä.iR»n0Äc‘,gi 'Æ0¼Â[¢Ö–£|$¹T…pZᘧ’VPÖCŒ×Î[±5.ÐÕº…ZóÚ_™¶sß;\¥o¹]Ww&,wl75à.ã%‹8~†s g&í¦6Â’syŠÚËÍrXã.b²8¶&o0ZœæNš«‹j\à›è등‹Ã˜åŸ,¿vl`.%ã:»•n­À骘/ngÌ·sšâTET’¥÷)yØU7Ø£q°ã˜å'Ž"¤#?HÝ=Ö©ZãI­*Ú_Gã¸;ÿ-KFÊá#H‘´­†S8Ú#÷yö`G¤ÕÓÆ^U*8P89‘ZçàC™¹K¥Y&H­{m,¦O‡moL[M3s©x®Ò…¯½™ŒÁ”6DPÒÉ´ÔÕ‘(…û¥—Õ€?B¼̤Ҭè’EŽ9LjLÌ9û²áxaä&÷:ím]r}í¾sœÜ…Eoe*™SàHeV¨Iœ3XÓGÍØ¬†­³sÕ íõWat²2W³Ý+s¡6w _`YÊ›C½Ä/ËkÕzÝ»eïUŽzµÊ𻕠mðnìšN;6µæqíĹs 1h›mžÍ†V˜ß*Å>-ëUÆlç:‰MÊÖ9B¢ôL–À•/ÊoªçxD)¢ò¼œZj«…c´{¦1ÒU ÜNŒå„æ\‰uÉö£Œq²Žjæ°¾Î[Ñ›!¼àñ,áÆÒyeƒh†\xæE 7Çë²#ˆ†"9‚éŒÒ1=G`‚Úå6F¿¶B.%IIÒå¶es N36níÞÊ”›¡|¢cÊ—SÂgRU¾æ{É_¶â%i·rüÈån¥àÇ¿¢¾‘\dŸ ¥žHìX(%¶ šÈ¼F­8?7þþž‡“ã‚!Ír€ƒTD8\åø»î‡ éØÂˆ'Z£·Îžtù a=$OwÁðöžïÔ¬'Ú<1m™~. [å©—²›O{qbªå+T¼Þw6äè”çð§{rµ| KΩ‡ˆHDxëÍæ¼<òaÖŸéx ~E&ïq{¨àqÒ }Ÿ¶ø–øµ}ÇßçïZû¯­âöd+îŠR@  ž„>¶ùF6©ù?3h|ñNЧ §¤";n‹e:Áñb!¥“ˆÞ/_W/X«Õô»ºß“.|ÖÅ”]᎘j¾Fº×¯f[·Å=°¤Gå @S*ntú¦êöSâŽêÞUªŒg)IÎs¤íâ›à®}!JO»¹$»»»»»»»»î®¦òëNçS\ÍÎcªÀ#7ë½uÙ¥¤ä›;èû—á ýã?Ýÿ˜ÿ½ÿnttv½d&íî[ãV7oäÉ“*僱Ë7ÚQ©–…:4ACiŸð{{ §aU;,EWä uN.H "'!Èò9 ˜'Èf<†D3!‹Èhb‚”"D™h 9ŠTV 1"dÈ”¨¬„‰•ŽdG(Dxâ°"¬ˆDbèÐ!™W(¢Ä64\꣸Ãa–X¿%þ>øUOÛ»þ­:«ºîÍ™4JA>Ç®ðÓÌ9ÑåDñbÌ'(ÄSeX9[W¨«ùU¤ðV«]wU>RhU˜¥IÐíI”•ڪ䕤®Õ:»G†ÞnÝšLÔ¦½k­c½íL“Û²‡1Ôn詇>•ßë÷üBf~§¿´ûÛúî Ý «¦N¾â®]¶© ñô€`¾¨çA0ñ±™ÕMóî„a%NéÌüÕï¦ÆVóåÌhçný¿Ò)™Æž]å½ÙT»­/3‘ véçÜó C·qÍÝÍ® ²Î(1á¸kt·µ%7ÒsWÌ„é 0¬J2”ȹîgoÍð"ÁQžcP¨©÷ÐEjª^"€Ê(dú©>4²¤ˆ‹=¨„!j- a…*ª… ²AŸù>§îÏ×Ýöëñþ×¹ú_N ƒá¼¡Áý!QÿQ\ˆ ˆwì’ä¯fNc+óße£)ú; sQ¬ÖÄ`SÚ½»Ð$Aݲª›KžñTê¶áñ¶Î?µš 7öþã9UU9ön—ä1à¨=}¥¿“§ùwðüM½ðŽ÷IµŒÀ€t""Õÿö'CÁ+,ª™ÝXåfƒ##º c·À?OÙþ&Üq¬GýJºB(£ñ… ‚Ó‹?}ùŒìÛ6e~KaÓÑ}åQWÞ€:t ÝœÂTjà.ˆF2¾dqªÁpØ5€2în7u»‚«qn €¥ò‚sm‚¡àö?NŠAV2->­ä©XÛäæÓ–X6‡^ù{biôGŠ`¨:RùȃŠz÷ß\#ú98)ÕË˹ˆr}àÉRÆvæBÿŒO;!kdl•ªwðob)bÇ>ª UèsæY±ÌiL`볯åЦùñÏ óÞÔsb–#yF±è…åõu ’4ƒ)ß›†6Ïó}æDûþo¬î>ï©;®ë_ÿ¿ÉÊ~î߈ˆtÜçOR ¼ó•9SôÙwÑHéGn¤—r£O¡ú˜½Î«Ø¿QÆZïpÓ*òd'ˆÇ’±h°)²h(´=Róæû¥©6¥êÒX±¨ ÷ ÝòêÖØ´±t}6¦)µÛNãQ›¡ÌåÑF.â~ .Â÷@TWŠ·==4±½&¯cwEÙ´™·:©Ñ§¡ënëÕ§ñišO¯õóØŸ1UWœØ““ž¾]‘±nL¥~{ÌŽÚ6­J«ê£'&Ó$²[fM#i‹£XÏ\¼ÁïþI^Í¡œ­^2À”5@z¤\0@³Æ/úq Îç?L\ÕPX¹Ï¦Úß›‹ru;ãGô^óëün\å~gÃûÀPé–û0ªî\?sC}±DÀO·ý¯cXw_ðu/³ÛûHD½“·,I`’ªÕ|¸œ=άzµä9·OgtþHîÕc`·YνÁ±TeüÌÑU‹‡Oäí~wûgóÿsýõ½GÕü4å>/¸Ï €ù8{kØ÷ºN3ú3ÆiFP]þ“Þû¸9ÚL¤x|‚ßB~¦L«Õ YVÝFzŽ<¦´nŠ~“M(ל/ ºæ@è:ÏÏMäy‡t]g‹FñþaÚPóîaA:eG ®ÛmªJã{ Ùz®×™Ú?kÑuÕ½ƒUEÂ8P¶ó¯½ôÛ†úq) HŽÊÈW¸Á_9,™Ö¦¥0{Ó7kÐÂÙŒ­îL.ZI~<ùãy•£Â”’¯']VúyOVg¶›VÙ|cŒò ˆaø/Ôóœ.–d¥kªvDÀW[G³®ß…ÿ+ijÖ`»P?UŸ¥È&ÒC\Ц»2¨~‰ŒàRãè³tÙöE­ÆH1‡j¨a##ByT”L =&¼æõ#Ûú^]†ð!›á\“ãqSÔ{œœæs#¾)¿ )9Ûù1Â`,®·¹É·Õ/%º6´(VD‚§Ô~ˆûáz軘¯§Ø™‰POwyLt¹ {2îJÌô“&rìù¹M¦%›âaEXªy6`c»’g€oÓ\øbˆ.ª2dOô9?Üä».µÿ€‚œâˆ‡}÷¿g1€=˜Œ*|–èü Á¸ûǰÿšáý1OxÁLF!a+¿'JŸÑv PІœ ˆy?’;p€ˆ=Ûæ ³™y}Ç)±Þô¨¥úhŒ“Ø©W˜ãs °ØŒC~Ðk5Ä÷願¢x§Ë÷s‹óƒIÀļF[Ñåpô³À¬f9c™ƒ{…í¦¯UYa†i¦2SѨµE*©!Z¬…¢6‰{jÇ®ëLœq¶E²-‹”¬ãs–¶R í Miv×ÂÕ •ñ1׎ßÕôõo¾£€)@êÅûyŠÌÔ+ŒÍ«ú¿ðÆ—êoô?ÞÁ¶…ýMU%T=ª:~B>ïîµXèýB™ª4Tz·û2RPK^Ï™TÞªs­sºÈ•BªÉÂê–ô¯UŠd’~Ë¢Cþj€Ï´|AVWÔ¯„mc mÙÖÜökËJd$VUâI4ÊåËZ×¢“zÖÎT‚ƒêu¨ê:3"Ã…eV>vµ,ªÁ Rõ…ëL Íÿ¦øì¹²˜j1/`›®®£^¼n¥UÉE´±w*oz¨jæ0©+K—¬×ÕK~@š£ó'ïúzz\ þ@úŽó¼FQhª¤ ¶Æ˜›mg jôMËÇ›7â!Ôú.1 ¯ÁÊ?Áì÷¿×Ú)º²Ï×®TÛéù›µhÑ炞x)À XàXö`¦)@§TSWo·ØìZv¥û—†Ë÷ræ©XÞŒ 6‚˜ÜÉ9eù*}Q´3ãÑx°n*çK¡tgÛN˜‰ „ÉD£¦8âC8aàðÃÉ‘2RÉb(9šJI!Ã8y@“"'"NCDšB$„‘2d@™2dÈI‘Q‘(D¡H‘"Ldi$‰H%DbCÄ™@¡BɤE1F&S‹€ÕǦñå„§7ý'¯Ýí¿Kñù_J!Û(‰ïƒº)öÝP˜‘CÞO É%U## I 0€BHÜ y¢•òE>p•Þðù~,‡P·m=ÇÑOù¢0)À'ø '¼{º’Q(˜Ü)ôhä;þW¤D•:ø£sbþß-~ƒµÛ ù2ÐÔ¦ž¨›2S`{"¾ÉJR„v N‹›'IùñòÞ&çäy½ïÒÿOíú_ŸÛïÑÞs»Ô@ Ò "kC“ì@?è‰éÑ%iï¸×s]|Š=ìsÀ§¬«—¥ÛÕqOƒŒ½ëV' †xå®X̱ rš¶3*ÿ}1e ·&ýYE?¹ÍY*u~¯ÿâ ëÄÄ‘f … ’‹àPB{Z …SEåv¨½ë„ÈL}¨§¤¢{—ƒ·k}°â‡'!9 r29 ¹—fA‘³$" c)Hc˜˜£ˆ… "íÈV–xŠ>žz×(ýç倌÷7v¹ØCLµl=Ü{‰uÝÔ&ê®ïžs];:Â[Þ3…7ñš0’h¬»±à²ÍjÌgÆ Ë/ 98+ݦ#j¶îKê5¦¬]a‹…5G)‘m¨ôëÞu@s´#Æ@Ï…2*uËàFâzi„€Ý®ëEwrÌ”ò ë/Cjóƒ®åÛ÷Kã§d©vúø÷ÊQ¥bør¼”Œƒ2mž°¢å^f@F+ë~ó¥+³ËÊç¹^® Bc·Â„å\io –œ¦”õ5XÀßvZ­³Pšë»¼MfÔìçjßqÕÜB±©@WY=Û)f9œ]]><²ð,+EwV³ 6®œÊn¯s¦.à+¸³Ð © ÏR"=:`æUû˾>G½ »É‹ÇÖO*@¡Oȇ^ø­JüËì«Â9 ºO¨_ ¨5AOiPwnŽ›C˜~¹’;”̘3>S}ÏÑÜtŠÊk€O jz»³û/­D6«§¨x^õûk#'½‹ã7àqÍ©ó5PXêÜŠÛI»V…_QµÚk‚M™sB.0éÇŠ¥¾Z"r²º²ÊÅî;7ˆÎÝå¼nÐèZG7³°¯øVÍΑÌŽp³™ó÷zè"ħJÕq^U¡!Y§»¼ß»†»;vÓÚîM˜¯M1ˆTÌR½E[óÃñõâ÷V?Y ðñ5µkr 6'ò,ªØê'õãºÞ¾z£µo—¤&zDk¤.Õ–e]5æî™8†·#uÓu¨Ú; Ù£…ýÐh51íœ|ëÐp­ºhx?LÛÝç›W[ÒP˜’ËeÊC ¡ P—3Ï›Þ4˧wÍXæ‹VT™ØVR… ­wV '7@¡•j’åOe·„VfÞËQ´°›—¤\°o±ÐšzÌÍçBr­÷g¨Ù:Siòö¢:Âà®#Ç»×VÞw´NuåS]ì¾wkʵíê0Éa qjÎVp.y{[PúBÓËäì*ߦiL±hóO±áÓew«³¶¢TÚe <Št«z§ ñ›ƒ&ß­gb‰e«®Ýöí>ª5¼·˜5GG»¬%˜Nõ]þ[nÂ\Ò¥ÙJ©º©Íï’¾0ú}+Ê" „+š³7áT…H•HÙe씵9fNÎlæ_ù+»ïzŒ6œ'Õ¡«Í·SÛÀâÜAjˆwu š]3@íôöBýÙ˜xÆ=„Õ»8´ØYg²^Ïfô‰úÑ<oˆ" —1¿zÏ¥› 3—¥œÅf€†5ÛƒS¹ä”èžÔ7gr<$¥ã›Wê¿\ˆ8õ;lX5Ü£.ÉÌ™óOŠž(%ºÔ8ÝEþ×ïw·R¡¾òzJçï1C§k(T†IAäºZ´›8bßÙ„Ó¥Rohµ*uôz^‡Ü2SnþoÀ2¯ÚÆË·ZŽœO·1Ù˜o%hRáÝB ›Ì<‚4©â. ŠÍ9B§•ͬ)­/£µŠ¿0j0 ½µ¾1W£@]Þø‰hJ F‡W“¾Ýïg¶­÷°ý~YÔ¤4{LtÞáPõ*¿„î”0£ëÚàÊÇ0:e=­(÷©ÑcÔì‹Íf.¡æ¥­­EgÝÔ=k¼6 7~@Qo.êÞb1¢ ¥´Ög.çyº¬hÀ†>x¶þ<{¤¾6¸W@½ÎeëNA݉P*¶cv³{¬0…ݺW.šÈr[¾5îK±\7OÔwsÏ·#W·â²ÞÖ»Ñã¿ç$Ç{l¼*›­Çéb¯Ü¤MZ¹Ìœ•lvɰV%šínvÝá%înÕez¼Û$ø‡pìŒ i¹×Yg¥ÓÅ‘¬wn;•“-:¾çÊ,F‹Ø‘“—¶Qgh]yм½ÉYT9ÐIÌ5n³oçPRXïtéim¿Ô¬¬o·pÓÊh^=l9Òïªó;/±ÞQÄΕd\ã¦ÎŒ.–¤Øïæn4òóŸtsLSR±"›wx¯«NsìqŸ†à#” kN{Ó\¢0ši]¥:ûgojì0SJíIÒ`®××]J±ÀqÐ+©^[ b«6É|«FÍ«¾b^˜ðþ}p*òÞÒ®æèoˆT¢ö¨jíp¬YÅ]Ì1aUŠetîèbvWÊÙë˜9WUÏÕKQO6¨¤w&gH!43b¦ôÞ∠®+{À¥:s'å;²½K«½y¡»&„ÒŸ>À×>o.ù¤»7n\£J°å)»mC•gÖ¥‘iÞ­¶[®¥UÓ®ù×Åå÷°Ž ÓÀLäHpdÙî¥_£[ùzÏ/Æ<Èr¿]éç'2Ü5¶.(3ÌQCÇêB¬:'.¶GOØ=O‘˜‰Î`îŽTr k5øùe¬WŠðùcïL¯M`ó¦;m|<ßPòVmu!0²d¾Á½{´:y{ßµå#^Jvîýäè4õ통C½pþë±7¼qPw×¹L°3%^ñìrG ˜iîÒ0 ¼wÝqqåÑ©Wb+±E-¢µæ tœÇÀTQw‹Zï]tõbß{2Ȩ4ÐF²¸dÃJY‹Ï;ö{Õ¶^I¿pÕŠÔVŠ2²ÜÃÈ©j-­Åuçvëe¬Ž»¤k4 ‹U©{1íðëSÕohÆ2¬NbëHcsÖÇýY+E.Æn…h™M„—…ÙÐ|Íîäï§ |6m,Á£¿2·RnÂÇÉ a'Mâj$(ØÖ²²Ö{.êJ·p]o ®,k[R­³ »œlï$R—¯º]‹hæ¹0¶–ð;[Á‹åGL3J—Œe„s•L©ÈÖ›<ô¾Èû¯´r_®ží •å•ÈaÂìŒi7›AicIöVtÞg"+ £2¯q•] ß[ÑNÛÊ튱é9\î—Bêoéå£Õú¿OØÀ¯Äï…CŽÈÊɇ^"? ÒºaÝΜ%'8Ý«ã×]çä^nø-½ÙÝåH*8”]´¾„=«íXs%©·éÄèòHVm·\ÐHÒ«½¢˜óÒˆ™{Žæð×çåVzÏx` o§ ­Âòc¤Uõ-ʨ+^½ÛÏ9wºIë­Ïr'Ôã¾÷§_“öõ=Á¨ø.´ 5§§V,{l!È.;KªêÞuN†¸å»­}ÛR× W˜£Ù9•f‘šNǵ—ÁˆçºípûÉ?b°¸+Ä&¯{‚#v|GQ¦¹ Ün|£G%£º’:ºD*¼¿VhüýòáÏYÅË3Æ…Þ÷²\H—?yÄ2í³é휰½îßmŠò^…Ôš^ÓÅ]_VÔû…{Iéæï†({Jù êYÂÙZ(틺»†=&…>¶±TUyR6Øáë7}£ŠJ‚÷¸œRtû0LšøæMŸÏ;¦•Ð\N„Üc’Öƒ¾í©z¢ZÞ4‰êÖ]g¯–¹“S½tió—u6àŠ·Ï°–Ò“ªVüè¦/¢”Z¬zú†]dˆ²Ç/W·=e9‘x<À’Ë’:ýuê½eP»lϲeå>4Ö@̼:êù³%\ðêÇ&ÀÓEûOtÍûŠ3·1ØËFà”ØÃÚ´õilºì©–^ÐFp^ÌàhßW\£Ë}¤9iî¯Áv·êJ‡´û\öjw¹–_ QÓu3R¼„¯oûÔhl÷z$Nªî·™8Võ·N¶·^ +nnì}×f_2aÇÉí*FmRLQÝÕ¸œE¯<‡wzçô¥«ŠÆF^ÜËŽ¯—Q¹ÝÍË´nYê[„òÆm™B@µšÈçKx‰…áo×å£Ì³ŠpWNHýÞVæ-¼¾’¨§prû¹œ4Zw±—X ‡)-ÕBdt™ë¬œœí8̇5¼çdóòÚÎõãíÕè±ÙìPY¥Š†/{Œ‡ª^ùà–³okò§±ØbŽ­ÉÔ|âè+=­zï 8l ë`I.(ÄíÓÁö.mÎð™~¡€ @wM¥m0êëFM?RÄRÓ«×o±³3-=Õ¬ß(ß°ž¤ç¨ç;½­’FæéZŒ³½PmwëÅÀf‡’Û'ÁÝÆRò3ÁæCÒìêO¯‚“*ÙL º=ÚÆ1‡Ï­Q4 ›¹ë¦Ë¢¾XÀíStý<‚!Ú…Pø#žñ;š_- ÔoÞÚäÇÛ”îúÕŸq¹~å€\â3¼±ßfm ájÓîélàv¹L¤Ÿ;w«@¤wVýšž?_ZÔ@¶Õ.æ½½]«uÛ#.×rÙΠ0[:òý§‡¼÷:•×QÃ0MðmŸz5=¹ÞoŸ-£añç/@®TÞ•²ŽÝÖ{2Fܼ>gÇ.–×iùo³1Q¯g¯ßMæÈR’‘Ñ‹Š÷²eÐß^ì­Ïrhóš leH~–¼©Ýv—:&$2Å:Ø.Ë7oSc“Ínè¤%bV÷©bû¼“µá^~BÙéKªô?`wBj·šœZGÑê}^Àô¾X_\í5ÌØñÏ“«Ü™*,]-ã´—·dX3«¨WS§LœœìÑRæ1ãS½EøÕÐBøïiÑ®Ì@r¿<ìçSؼXÜ][2îšY‘úzÄg…uâ®uvJJLå-#ë<žÎÐá¦"9Kî²wzg®ñ¼Ë¡¢>\\º™fó™Ë¾n Hã÷²kôÏn5v© ç@Vx}çKÏkÞרkÕ¾ãè¨åT ªä¢ÌvÝߞĤ×wÔ®RZ%û&{×Ðz›ö{_ÐðÙÔ©ZJ_7ypöð¯Pv¥X¡°if%7~C²r÷©öã¼åŽë« ¯EkÎkqÊt(ÛKž}ÄRL¡jMd›Ä1‰]6ÖÍ©Á+å\¦f­/kHWl¾½­òNŸl=Ðaç ó:ïˆ_^SEïk»íáda<¶­pËeʰG3/¯U¥Aî£ÆŸtü9P ýKÕÛܪñÅ0Î{4Ü­ViTô<ÇÅkmP•ŒþÚóÚöªß¸à)9á=|©öø+Øè4ûonü&]xžm{a&îë=Y¡*H㘼v¦cfôn³$Vò¯zP|ú'ue7ñî–~S ¶ò¡”· Úcά]h·u k}¾VV?Z£†AèÕ.‡hXÊXû2q"÷²…½àF~Ö¢=*5‰æ¶”oŒK0'-W´b¿W{Ƕ„£‰¤Þô­Î7`–õo–Ãì,ýè<Ïq.p»§é³.•öœJUÜÚKo×Éûºfèž§žÅBÙòz¸·h1œ„²çKWyÁÅÜÞ:ê]&ƒÙKîuرô‹’ší go,±{OdÞÄ¡K>½ž¡9©ƒwruwXTS«Õ0³"]«1màX)D®5¡™½®‰m L¦»ðL̮Ƿñ×$C¯(7*Û^NöâdàB¥ P‰¡ˆCº½Û³a×µÒXê–˜Õ¹Þ2ïÔûܽMïµßyû׊­¿¨}:åœ6—Ê6eÙ÷hO ãé;¦JMt§ÕÛ²ï“zþW¸…À¹]f¶èe*^ê5}HÛ\}%K'Ÿ,ò8u˜t+Âã4i{²Ø™­#Nž™Xe+9’ý-ý+=6ò]ƒ|÷'PI]ó„Lg¨à؆g<ݨ/žôc ULÆdè5Z]˜W,»áÎÍ^@²í3,è”b]–åKš%«Pbßx÷ºæ)ä+.Õ”vðHöÖ#ê­£ ¾7ÛæêÅåÂÞdÞvÃt7‰=ë>–ï%;-ÜÕY\ºµ"®$»KaÚ6×eõ-ã·†™GÙp.²Õ•:ø®ÆvÏË£$Ü9qÍ[¹,/²JÜ÷@ð*oK™r[Þè(¦ú›éXÎà„SHÕÖ­ùP¥»‡z¢Ô‘1¨®OE¶ûÛ25gáí {o‘]¢9™­$OY®†eÐd±Øòë5 .MjA«á0À®:y.ï;` ®•Ýp}Ã9•V¿z¿qÁ…á.¢à‹!õ~å¼áº^ϳ –Šä¹a3/¬ðx™ãÓø6Û¬E:ÉFµÐHbà‹Bòï1pæ49ôÙÃWº|©“äg.·=»å\<"ãjÁvšÌ«õ›£NñQ^󎳖ñJ ìy.š: §~ê~½+ëR¼f•k¤îíQn•¾•k/¼»mÖjQUåê6c›µ®J΃+Œ91×R’“n²S硃P"cnNK M<¬4z·¹f“¶ÚÛ.«7oBz­ó²PmC£/±zÞŠ~çÞC›yÕnÓ©wK…­‰ôì-Ö 9døcë[w‘uêX.Óx®5Âs«ÌÙÄnwH¹ Ú GnÕ~1ˆ1í/W\özU†‘pv^Zk‹§ªœ îÌjðMÀ ÝÙm¾(fhê%íu>ì~Œ.OÒ‘Îà4öRóÏD…ì„2eÝ)ï\8žWåvtž1CêäfÔõ‚볌ÚGÊdWÑ{ë«Õ8³PZZMвDéá ã®ÚE^áÚà Tδéõ™xg×´ø·Öw»…qæËN—epÜ«{‚ºfº#i1Z’­g*¢ÅLР͸'Ž5™}GKÙ@ÖØ;±RÂÝ-!Ô«9†-u³:ã}}¸€–ø í1êÊð Þ˜¾ädf Ñ`P·)tQu!ܘUÓ&û¤ dV“pî›ÚœŠ·$ëWÜým€=¯ È.g=̦TW® ë}Ñl•+³y#º‘Y\Åšù*Ig]qGØ¥ía8Ç_­zKwÔµs“ÃÓá%>öžK' Ã´ë ëç0»6Q¹™Ú»qYaÓ¬gE,2ÛÑÎAØÅ”Ï÷‚­¬ºë}ŒÊÞ†XìºÀì‡:æ_:ßMô®«Œ1>‚¯‚®õ+yQZ”hKД¤eÅž;Qz`¹^"ôò{M« ôOe òÜÀµOA©gQrže]yâ@÷«{z½¬dÏbUpxVfŠí%×f`¹JáS]¬Kz® ,‹°Ñ·¹¹‚† }³uF­HP|¸²¿tsÛ›Š¾§å0É‘ [ç‡7¼ë¶_:W\¡bÌ©`ÁhÞC‡zù£¶û&j[àÁ‘JIÂçˆÚ÷Ü6˜s¬ŠcwPõ¥s.[êÕŽºyýÓ_ŽæKìo¶hÑvÕm h-Ý×CÒ«rÇdA 6º v2œºšçr]Cq€úcÕ1fÖ+ë§ATW‡²¿ZDzëļ߬ÜÙ‹µ·¡³öXA¤Dç“Ð7Á½G]q“׺­ûÕ“Ò cÏfq"’·{×?dG~¿s•xrþkrQñ¤È†0:äû/˜¥˜S twã}Õks‡À`b+¯¨õü/À¤ª ¿tU§+VùbWZ ¿z­41óÚ#¹]#“NœÁʸ=Ù°¥¾,:8°¡W|ÖIšÑE++6°Åc¹[ÍÉØ»~¤KÜ‹‚) ®í—¿^𧆯¹Ý#Ý®;[·†à\è\†Ët^>•;yݯ9ÍàH’¢î[×g¡l,øuˆ¡[Û`cÈA«» ÚŽ˜ÍpoŽtÒÔmUŨÙÙbˆØÀ¥hM|-gZ2ó]µ5˹6¤e•.RŠË³À†'ƒ2½-;BK†ó±2/]ýší<2NÜÃÌ˘’ÅЦþ¬¼9l¡Õ݇GY¥Å5j­u>«ÌîwqA×KUÐÎ23Á` ± ŽJµW”‘Nxxñc%oje¾õeq2•ï$òw iæ%lÛ{Ý‚x4­8låFoT\õ«R¯öt¬ñÜ]Q´Ï¤•¾¦'aèßi:÷ŽQã}Õ¤,Y]{¤1ÍäWs³äéw\Y%]ïF²^ãè‰ ¢Âì÷Š‘*ùg ÆÃ—à»k»³P9&köоyYš¼ÚÐäcoÑÒÅV¿^'QA‰VÌŠœúása³—ʹZ{·×›#3aÛ¯exwŒˆ¿o—·Ó(믂³‚ü/§¾=’CÖùí¦)ÞO ÓÛã^<ÃÝ©Û(ÖA› cYs1‘i1³/uk¼|TÇj,ÛV¦ ]j—q ÏrÝ@*u°CÍ+¥ˆXÚÛyXáã.ÓŒÐìœr‡^Hë—wC@꽷˾©Š–R¢ûpÎ"K\rá”kU­¨ ]¸¢/µðìh:[ª¼¡U513й”Ò'¨J‚ ·„|-QcÁ²ö³2 ½Óe^­|Qð>±×ë®]¬¥Ù>P1}µk9ô¿woªÝuÕ‚`÷;SÅd r›ÞíÜ»Ç)©ú[Ü ½æýŠÓÍÏP1S–¢Uzø”‚­Ñᙚ«¤·²ùÞbR· Ûr&€죩ç^â_+s{«¦õxzOu<è ®^¬Ù%¤Ðæ1ìÚBê[.GεÃ\m«@ ×£{ ¾p³S9Uä/Zu7·µ!ÀâK$µ×œ ­“™Ž[Ó7:™·Steî¶„Jf˲™uÜPîV]`#vãÐ6eB‡>GK[R±’o9R6"¢Ì3,¢óŒ¥^^ƒeËêbÒ4ÅWì›ßmÛ33–ÛÉ€¢À/é pëË5~^Ú÷ª2º½”8¥çÇUa›LdŠRWí»–‘ΞÌTÞ9ëÖ0:´)åšêß8cwPàRç¨2µldÝkRž—N‡Z†¯1K™Ú¨Vœx­¢œÜ\C®™U Ð{µ½§»©3jžÃ:QJûoh»¯ÈNû×ë°ãi;c&Ì»öîqU@t&ýsJÕó5ŒL44Âa¿ž9W˜æbæ•Çv)ÌvB·‰f–v»Ì{ŠV´”VŸ#F»Ó=ï=ö`Ë¥¨újÐßך50«úZ­gWTåPTÞÞ£m.çEŠV7Ó¼(Ú«óÀi+]š²y[D¾Ç­ÛQQ®"ø´½ ÌMõíY«Õ‹ÛÞcÙ]z¸ÍU 5b»·R¬6ÛÎÁÐܹ··ÏS|ÈîØÒñá¨m]nùj“7¸0mëúé qCÃ×ûµÕÊÎýúh¿V( ×ãoªè*Bô¬ÉBžÈ*èvgEOk—yoèyšUí,7hK7έjÉ>êé O¦âú䜭c½©Õ bñn.[¨iH-¼]îá}´"!ÁÐ §Öú0ÍÜ„È{›“å=ŸA¾.Ï)`¡SÔ®²ß·^z½‹Õ½™=·ÄË(y½J®´EPrdž¹=[ß^VÓ4m ÒospÅMõÈÈ©0üâÐhJò^Õ”7O½™¥ï|8_ªrº/,ÆÍ·Yà VøsæmUÓÃ,DhX¤ùh¼Eõ9äUr‡úß5-¾ÆE2¶ŸRÀíhʹ.ŸÜg€Âûlðí¾ †XµŠŒT®Í}¹ Ë´¯Î—+ÎŽÓõözuJ[ä—|G¢­ŒFxß’NñnQ²ø8–×ipâÔ®y«'^ÙÛ‡{y.cld»;(âÝwMA|ƒYÕÅNаGYF€÷ªsêíâ+º4žÜwÖ „{“g|dÅ')m™ÝF[äàk)ÀÏ+å“.µlwr¥‹©^i–3*ÜoxVk—`=˪ÓŽ=[Ï3FÇjYø8¶ä¢±÷ öÚ÷zpN’Êõç»iûÛº¶W‡¥+¸=ën_.½”Æ7ұҸ̌ç®}¾Ðyqê]š<.ÊãëtzôÙ“Y¡ØÆTã¶b×M(ûOÁŽY"l;<»\Í®»W]ªéÐßb=&[´ôB/ž& N¹YrÆO_]ÁÙÍf¨ŸW }/àgS·™{Ù,8Öõ•”ôÍ—Q.îÑÀÍßrCì§(U£éï$ÁW{X‘Üç8Ü|ÃŒÄkiñ:@¢öû¶¥_7ÛãéÓK8#Öл½íW´úŸ çØ½ÏŠõYi_rÅ·ììÚ¸—§W{–ÒÒ½ÀT„ñ].‚\ü~ñ=žCŸÚé:#^Œ¢ò¶ˆ›:wNqÝÉKšomLéK¯dâêEQy¬kIöu‚ô¢7ÙCÅ_^®õhöÖ袨Y­æáºÜ¨ÈêíM·OÓWœf,Óëëšr4•+OjñÒ±ž4)ì¤"ïC„³÷£®ì ¿PÛß•H}o3~ç¾â» ˜»šÝ]—¹€ÖvIàÌ‘27Ì/Q«QeÞZ½+Xû…ÞõÝÓož4a¼¾-ÕÆÌÄôåŒ.•ƒÂØ¥[X„bþÒBœÍ˧YU44ÞÏhb y©Zyu7œè¥ðD›ê‰j"•ºÂ)°puôŒÖâç»OwªêÍŽIb4¡JÌ–ÖA1<"SÅthàC‡:5‰½¡÷;ê#“Q½ºËXÕvu5•‡v@Ÿm‹”çqÈ­öû}áƒyeÏ]xJF;ŒÔâ³-£¤ÃÙ.jÓM ˜~ZÃãlÖÓ÷¶lì<[žx δ&Mó+|5ݱ…½®UÚ­ûÉb=OÇÜVž‡n³ÞÝ«/¤:Ýw^n¶J9A¾C½<¾Áê—·¦a]hG}9YµÌPµÕŠÙ1\ç’ý¹”ézîÂ|ÆÑTü§'oß \½§:ìõ{OQ)þ·ûi)ûÉrõMx¿oçxŸ‰ÕÒòÙc}zUû©„A®F7£Ïƒ“ÅtŸhã4*`:Â0woew=ËóÏsÕ ÖU£;Æó,%‡£G—Ãi2úž,îF0Û`^\ëj™®,J½Ð×tÞëkØI›[γÐ{}CÞÅʦ'â*`tauÍKÞJ ÍÒû;œºKÑ3» “©FÞúç¨ÑÎλ˜Ë·›ˆØš¬^h+8iìl«[×tVVEËžàîŠõ–¡ïŽ}˜…Éy“7[»WN£Œ5¹]]¼©¬ïóìßz…O€¬j½[Ôóq¯Q+0gwéÍ^YÈÕu=9yÀÑ…rÎ9ôR¸ðÖœ¨Ú½;¹Ø'ms®ã´Ò݉q®Úê™\~7,ÛÎlKµ;¯%œÄµpÈBç ]€])¼èä\Õs¹¹¯/©<“y<ë8«°¬:Éö*Ó)—¸êXÂa{XÕqC2|­p©o{ YÅ#0 §;•O–ãýµ™Šu6Å{Á‘'VUÇÜí¹ç„šìŠ‘³öÖŒ q{ëëµÓ¾òÃ%xé^€udæƒ>ÁwÎ8VÖÞ&K=Í}2…öÔV›Y"´< ÎW–”swB[Ô·Jànž%Ýä׫.‘ºËÓÑÇiܵ«º9Á©Èvè–{­jÍÃ}%=â¶¶’&Ûq$gUÖn•g:ï±-7F´NVÉáW\ åy¾êÖg ªzü]nhÃཞ]u¼ÁÍîjì¯hg*,M,Iä0fZ»~¯WbbÕvMÆ"˜±”p%¥á)d‹|M·î}Ïc›ÇÙ”¹ ¿Gwn%u1¾@Ø«˜êÎŽ>ÜËR¥úÖm’|6Ø^F’n{P~Ç+9C7®¡áoŽRñª©£+D.æd•-V¸häå-í<9É¡%tÐ{uq½Zy_ —ÍFžLŠÞ Øpwuv }žÊçS…à èýb=#™™‚烹Ƌ6³9T[iÛíGb‘ç#@®}’··v¥ ÷¢³Ý%õÓCœ]u×rhiîÖfL‰ pdý¢lý—­”ú›6&_«wPžN€áµ#äó(¶è¹2ëZÓ«Æ»Ò=&)Ö0A™x W*÷ʻư:õ¹xý8ª w±¢´NŸ`ë©kFv´¢Óž›èD·;çá‰öF÷PîÉ‘§N…ž†2¨ yÂÛ™ÔnuK›ÆÈøñ–Ù•€ç1|OþíÍbö;¤$s¾Š¯&9L‘fÊg%ò7 i§ÜZɶÐîgë{ßu8JhÒ œ«»ðóÓW§ ù¼‰Œ°e“à/ÀdÓóô^žYÑq°ý²9M7Ͷµ2e- 2%óœí´kCrêœwhæ ÉšOHÕ…i*¼{tž›í6¥hîƒB#¡®Ìû5îv¤«!ï…ç;RÓÌ¡±]`¹†ÐLË]œ‘é/=‡W½ÇEб¸œf0§7M«/ÓØiî¤ÝÖY%M®Ôk£-îܵ—&Œ/:üj]e¯7Që퇓èýf±±û½ÓÔ{½g«2Ýðʼn<sÊøÒËWÝ«(°Ùl'Ô Mæè¯yî—rWmaYÞržôŠ€›¨>Ìýâ{·{ñ«ã\ÍßîüÃ;¾Ùج%Ô@¥é\¥]q¯T§u àùûéW¦¹ºR²êgVJÑˈ3;¶Ñ&Mr““æ°…QÙ¢b±¯b±·¥Â»âÉtÖa à6ÖmžÛg9Nt«¡!Þ¿rœ)Uœ©#ÃÊ;\3~õצ%½ÚŸo'%9w.½'ãÎén¾W·wv§l¶ÔÓ³ÞÕ•ª¸?–»½ž×ÀuvتñuéYlð ¨Nj²'›… ÈlñáÊp¦d$uÀ²ˆ¢¡9:2¼kW•g·ÞtýWVۇا¦FÒ ©ÛPnÜážçu›SÛ6òn¢Ù±ÚT×3<ÙÈ&Ž]Ý7{>(©ºÖŸ‹¿ŠÊâi“ÞuØ%Ñï?d«÷¾Tw§ª9fWmkÛO¶ë”¼§v¨ÙÃÔ€y4#êÜ ã9¬®° ‹ZsºR…G¹õ›‹7 šàN1‘'GvÔÍõAÏr]ò6»“÷ºÈ·ïeBÌ=9xõ1¾Ñíç±P|*ãUÞ }P?¶JËW³UI —díŽY˜ÏcÆ˺:5ÉåJã«a+›^ñ’ÎûrƒO/ob€c¡öð~Ê™äg¡ËPE먭1Zö/[å[ñôÏ*ÉîfÁ{£tÆbÚÐ"÷“Ü©•áÍV÷$ýõçUªAmyø°-/V¥g©ö‘Ä‘]ÏÊ5Ìg[ÍÞ6¥ðYWBžÍª^=íàö*¼?rj/\6)Võf÷¼Z‡¯É”|ö­Üà*jÇyÎ.Aw¯7β±qÃ; è«•ŒàYŒó]z·"}²ö]_e„à'±qNû"8Òä‡a‹×N9GºÌ¦ü.ãí§µæö¶ó±kO¸“:ÈÃie®µØSsÜ^]ÝÖØud}èúÞžÎQšv]rJö®eJ—]«ª4%èàOåqòåᳩV8 ö–…ØÒ+/(!t­ˆö£ºC¶ Kn2wlà-½Ò)ÝpîÜîèµîä¬Z±Ñl¦è“×/j%M^â»wmô™úuÕ9íóNì’®æì©]£â­ç±N-˜Ÿ¼bšÍK“¯_Pꜭà®bÞ!Ëèg¶{«7Êi¿mu:AYßwwœðÖ=\Nâv™j¥å"¥kóÀ‹»È9:Ì 3×ì«- ÅF·pe¡iñO}ŒöŠŽé2ͼX3$Š C0JIç|¬ž.D3¯ÝalÑœ¥ˆ]"3—«@rëeZž6+‹6¬<Ãè·f-&L Èn¯:sJ,ËI °(îóA凗t÷¢›¾ÚF"èø]îàõêcƒŒÁpð±&\€DuŽÞOîœeãË ªÂÎvhõdžÔ&Ë‚ú+E ÊuÞ{݆î¡H¨Ž÷$‹áÝrA—Ü2×2­šì )—ÍGë^¯ ®/j¥¾í³^È‘¬¹~ì‰x³²Ÿè“â…éFŸã:í½ñ6ˆÞç·ÛÎ6º#Wfø}næT‡u$ÄÇY@[Én`½ÔûK«jn‡Dî̲ƒºkü€¦<¸‘ãÒöÉkNŸ¶ô]4,D,R­œÊ 2ZunZÏiÖbЃ;}•ÄF»30X¨K;8±«ê×W;±YN«ú*k9iG˜·DY»œÜ5ëç»SwóͳÉÓÜá<Ç•Ínƒ8¨¾©KvôCØò_«‘Žb“l©uÚ ¼6û%ßa÷M¡\´_ ¡JZn˜ç‡'wTÅDÐÑÀ*·;NROE}žÓרÀeÌõÆY²UÈ<ªV6°KÁïd\¤îþLw CPy•g¦¹Âgv,ÞniÉœ•Ñ3¯É•áÞì<^TÅÔ˜”;]vЧ·K°¨ß=~Îy„óÁ4SUßÝŸ·õ¡R.ö!Á<§íýåÔ;x'{RçÝçË®îÄò‡´<}”6»/BëHÃÆvÞ`&èñJ½¶ÞÙ€c« TEàI4ü-Øï–À¤YÐÕ ÛåQLïJ÷º=XsÀÞçvÇ©÷¹Ô8RO«“(üUÝ‹ÞÞ=—…ðô* õl~W<@ò6r´v‚|Û:òµ g©U¾K’ v3‹@àúVjâ“—i³«{yÝ+™èÊÝÅvÂ}îô7Š…ô^±`.ÇMæ®ïoyâǽ yѧC{³je½Ü}ß knT5VÑ¥;l”›¡‰²[Ãï§{Õ3·q¥kϦ³4ߟ¨{mSÑÖW¼¢1¬fÀÏkzözêÄá=ÖÜœ÷šUs-p1Æ#*Ø3­ó”÷Y¾WÁm{ÈÏ¡íËÀ‚¬w¶Þß \1ðÜ •,ïº.â+ZßlÊB¯Ñíâ÷†ÇY¨Ñ®¥)vÝ9滥O†6ÁήûcËûª—.­*,¬o@ ·‹ÄÊËZ¯yZÝ«AF8ѬMkÍ¿¹ÖvN]‘£¶°ju0$JwœÚëlmæ•×ï¢ÙmÜè¶"·!­ã˜õdS¹Í´“Ù¹‹lYÚ‘.9E˱ ۵ȸËáÊÍ.KŽ5™xÞl°Ûç5jfç=±\â,[µxž³³ ÞÔò+êfWXYΨ»jòË]/èÈG†‡ØäÉ)GzëžÖnŽy:¦‰^A[=Õ½wbP½ìFŸeˆ¦>|œéíæý»tÄ~@¡çSn¿f5uX=DÝ] ò×Vhu'ÚzÃg_½$ì ´Ü¬z3G!Þd€ÝŒKש·ëí<2HrC0úR¸<ü5{9)Q^2VŒHƒìCMlæY€òÐT¬÷C:<9yRKì]IÀ ë3DvŽo%OŸ[·¤£¬3…_>,fsÝÆåw½ÈW¼éJÎ÷ºHýÛiv¼¢%u+J¬¬}obêœrS4™‚<”êtÖp…½Ë-roÅ»äënû–Ñ}Fcõ$þ[Ò÷·—¼’=O¶G^ßWg=Zç\\뫹ÁDÛ¶*[¢QØð‚¼øç™×¦K¶ªÙ«¦)ØßpÛ+¶olX©|4{6ÞßpѱPW¥WªQg™<@½ò¾B®ñYö×thðŠÒ7ï=4‡5ëÚ׉o¢TÆž5[+çì—wí·ë¯:Ô×t¼ÛGo îÊ´ç|ö^wl7ž}M‚+Q¬‡8!¯¼ùë 3Õ,+«÷—Þ¼¨+€¡BíJÕâê»­3ÏHvçÛÕßlGXî±–'q“»WïK˜£¥HTO}¹wñ5æòñG*[ÜWÑðѵ^Ë|X+ÎÕÇåŽ9Ó²);pË4pÛÉ#Þγ]áŠÇ¸¶m®|=œŸI’®´ýlãº}…x?B|{<ɽâ;«›ØçÙ.³qå ¼&Ù#"U¾çÜ9Š"»Ã·_->y6ÅÁ±{¼ë¬fÆg0ÏŒçÈZFÔn¡.áë¤]‹ï;‡«Æ…OCìÁÌähgNã|w·•’ dtºÞY;»Eu6êÞÚ³%6@ u>û9аö®t'ˆg3„ý£_µ‰zö™]~o´ÝK@ر±zr ZÞ—gqElÝ îÙFk³©‚)ÏAÏÛš’GˆpVÐtûÉ㯛Õ¹gr»•ívÁH[®…L'«’x`­íßd…möhöu@°é0dzmB°ZiR¡µ"ïo¶¶Íh†C£/ÙéF>ÆÍ'™nonë½ ß§\ ¯Q¬ò*^Hë1ï’÷÷&gá¦Ø;,W'ßr£b§Ô];ÊìÓÚNu;hnkBY¤óbCµ,£@­ø-éÜ{Ÿ»žÜ“Çéh Óט³–°o«.“'Þ•ê5 ˜í_·+JÍc záæg¬béË›CÖIÌ;oTcojóÝ+:×»|ó‹Åí1صŽÉKßuuœJ Ń»}]×/[©(nºÂsMËØiOÉ(öú{×=ÕYÚŠ×Ïm~ÆåÈ_†»À•¥Y«·Êeiöeø{„dêJòîúëËÇÕr“¥š¬Ë®­oUtR½ä¶üZZŠÞ8m@ðÓ; y¾Þ)ëàÁ¤ëœÜ\oìíóõbg ‰Úq„ v¢ö¥ÆÛöÔË¿§}.vÆŠë} ­ŒTÀý y‰Ãíã^ÒyܸÚ1û‰”vLÓÁÏ(žÅáMö½®¢q!ൠáµÝÈE¾Åf ]EŠë8Þ}œ0D¼(P:ßw’/%*P"…Ï &/³ÔOlíZ ‹£À¦Ô6=uÕ2·Ô< øÓ÷ëj½(`R5Ü€GéíLmÙU ƒr’‘æe¬Ž¦‡˜…@-ä+6ÐÚRÇg|Q®àfí •6}2îu}¸¥q¬Ô¡érÚôÍ’=¡¸Ã¹—½j´%o ˜ö’‘ÉAœ~¡O»+E]Šg=îy±ªÏ^«Az£¿‚±ÚSïÓ{ÕvÎ SïÙ 7ùÞp<³Qµ•/… fe³[:.ë¹ÜÊh»Œ©DuÖ–Ûº˜yQ¶Ýµ{f9Z|þÁ¶ö.×J7Gbˆ×Dj`êy[b„sÚ8h­c¿?[ú΢jÇ¥fÉŠ‡;#;¼O½0åªô³2ÇyŽãQê¥õ!+$ìW¼µF+eº÷;÷Ÿ­ök€µIÓT)¸-iÀ™Ý^…Rªø…*÷«èÊ5¢ôJÃZ¸*Çd;$ò†ÞZdüv§ÙØE'v^cYQæò‡OV×VËVwÆ{ŒËz²-{ЉŸ¯3ÝltjC½`(øïÚ¤Ñdw4ßQVEØ3êÎ+¨Ðäv”uÊ(;»ªÌX[4­,í2·E#§’ò¥«Ý±WZàèÊCc+iç\¦¬Å™|¦r ÍŒ@6eºN»MÏG ¼ Cö$B/æÛåé*-ä¶À£‰Ue°©Î×t” J`ÇŽÛ¹) ½Ä:qèUL¡F¸Ñºê¸ò®¹(”ä1 t;€ÙwÐ'µ®£³'Ü+­€S[Gk²PÎ: ¤£ÁÊï»Ã¬ Á²½«¡YŠóÒÈóP+Êxùb§ö;ƒ’ôy•$Þ>9Xöâ¢g /lºÊIkcÆöô¨ö@(Ÿe3•åAóW(«í³ƒäIÔÉOPo¾Ÿon½Ÿ]ïdÌš²†=1c²+\]XIŒ×{Y0=æ€TëÓÂg)+ÇÛÊ_  Ë§çRB–†»† ð—×{ž“Ʋ€“<Ž:åãÌ£Ü÷¾§¬°Éb±Vøúù#ÏÜ’VA8î,§™ªž T]ß$ÍÎë{iƆM¾¼Â  •o7ƒPä#«ÖÖµ›OÕ$Í@hãl¦FÖï-çñi©íÛï•–ECcˆï<µbhܽÙÓ´W=¯$<¹š/“hdΣ}\ÕÉÝÕÅ›íyò£³.Ýv)ÚH÷³/ ¦û« äΔ;VJn>’KÓ=¶¯Þ­Ï¡ô„Pêk J¹™¢äݤ~(å £´<¬IµˆºštñŠ˜”wÆæswÄt{jaËÌלÙ Ð{•¡S×}Í1¼Ý{<8v/oBs ðç(ºößÓeUÔºj ×t¶ãêf¸R§{Á]ÒíêëU%Û³èì;Ç5×hÍ nj :˼¨¹õE1;íd2aíßúnö× øfõÙ~¹²êµ‚&hmrVRKG<Â>àÍ‘V^7¢úghçG'ws ´]jÉØ¨#Õn³x Éx[ËŠ;£¹ùˆ±dÍö{Š[~™[‰²k©”–QîŽ^o‚õzøû(YÍ|Ô΃;3Îúó=9úºu‚hYæ±l¯GD¹Yì5 ¥~éÝuq÷3 |ñ,ç‚øxù!`:Lž£c통íѧ×XkÙßpår]YµqN†:=wª•º¸e轎s4«8uê9]ÙaÝÙuÂgtN®i××ʇºŠjsèÕfí^gÓ´æ«iÅ}}g~ŠJºOÝ«~弇–Å~uµà9U±¥«å¸eö熲Xp™M?<õKÀ|Íoy^›í›ªáÑò>D¼9klã§Þœíú›œ7]³ˆÑV R]»ÌõmlE9´½:¥øz{}íš#LŠi{/)³Ù@çr‡kwsæß¼R>ðÛX9"ËR´%O½ÉVfuÜ øL:\S‰B‰Û0p<Å×U±°Úé;7¡‘fN©ja9•¸ÍðWÈè±½‡ÏÓ}ÛoÅ×{^£J§G-u<Ý¥·à5;½æ²ä˜pð•±íJḻVÈ3¤ù)O2Ý(G^ÝZ¡©n×mG¦‰¡¦ŸFð ækOE°ïIÛµjãÅVÌLsš^ňóÚåï2Žºô¨»ÍÜòA]©Û†_½0Uλõñàî;Þ¹¡ˆ916øçG‚í¤.ílÌÍ5yÁ>OTéYLÑró75i³×¡ò®Á…š*åLcPX3¯ž¹Ø5Ýöö×sã¸fœÊâ!v€{ëMë{Õµº:ëhM3@ËÌ;Ž¢Q‘N®µ]o]É+5[¬äÉ2[êh™Ø—T::“åÛ×Ýkcƒº¬ì:Tjάu“+<Šî!sí¶õw§V|g 9ÁFµP›Ð4rJëeaNÜÙMýæ)Xþy‰e_´’²oQRÉBèì+–ØÅNëJÇUÒçvjL©¯¯ù®~ÓãCI~aÓ? Ñ‹:XÿRßA±+AX5´ë¸Æ[û±ëÔO­JCnïZ \_]ѱƒ "%õ^»»y‚«KÏxy_„4«d¿_u=vXPâOØßjËýµÃǵŸžûmo¿GؼU¾ë/©ó&°Xعèƒ0£y˜2mͦjt®q-ŒèBü ¼DlÏF×gog¹ûXûõÔYæú-š ZœsmíÖØM–Öæ›Èº_w;ég¨Æ–X‹¥;HYÈ*°Ì¾VwÇfwyøš~>¤-‡”.²¸Y_iìèî7[•Ñõ 쾂º±S0QUºúöCP'´À&óÞ-`¹XŠªÎ¥ás=ƒ”¬?^\«¯¦÷#N0ï9§[…ÓK¸tZ9)T¦k·È @‹aݜ㠀Õ5m¼’¢à9êvm«±0b"‹âƺmüñµ/+*êJån§Ù¬â-Åó¿™W–Ù­ãcžbç¢:œ«!!Dß ÷]Qín,^KB¶Þmœ¥)Us&ú:åj—.µY‹¿#':úvÝì{qÔuc’‰à²òر†,|+" ºeÈ,yÔ«yv t“¯{Ú2¥¬„ú,#áãéC®ÚBRr¹©‹Þy×”ò>2vTÜÌ a.ACB–˜§o°áø-­€á펠—˜¾ÊEDûK»W¦däÐÐ{í: F·*ÑkœQʼ#-P Ò¨6ÆqˆVfLÕÆ¶§J5´õ[·mt޳_{#Cºí»12Ÿga m>”'XºÜ(ë³·)øs°n•—ä–¬^^«C×çÙéCMŸj‹=iÈÅ,¢ôË ¯¯ZiYkXÞ›­mnM ±«YÎØ]W”'áK9îïÝ©_ߞ˒ù{»±])Ô2&çfÉ6v ¯c~/nõñÄ\uc!]¢µz7 ç¤kW{ó§8Š\ê¶ú³…cû”]kmöE–” dFÝ×nË%«—´»-X­Õ@1ÃÍ­°=¡a­3×Q‘ƒìÑìc}K_PCáÕ±zû¸MÞârÎÓru@Të/’}•zwuׇʴuy,àW®è‡Ð Ožì›£_TÁÍã.öF kŽÝš@`$ ´;© ¤E$[™IÊwÑe]ËngrhséÚbJ’Úè.Êje¹g <ÊY÷jçëÞ² šÁ1%è¨^àíö÷ž¹¾~ÌŠè¹å11¸Õ…Ûœ{–¾3 >ܶ‘ô¬ú iúeâºCâaÜu°9Í;ƽz¯"—H>wYåq÷ ç++Äq>™;Õ¤~j¿l«T’·P‘+°ïÊÉ”VW­2¬ö»„t7%¨ŸNMðe‡hbÜ«ÆÎP=ðÚ+4`Èu ×ÂqItswe+.eD¤Ê ú–u¼o®ó5=ã>a+ËIG;9Ù0'ô‘YV[üäc¬8wË«!Ï“§˜ãð¤¯S°kxÒ= 1Ò‡Ÿ!^•$òSÔ +ÓQ®6yÇRãFÉ»ºÔ{•ÖRElj¤åïhVR«+sÎÇä žã¯€ê1;•ì}çJîøí¯ ËòϹAÕõd‹ÙÎß8*ÄÜDûÙii‹¤S½:ö5³µ˜”¡l‚ªÀ]aNÓhø]­§ï$·j7Úå<«v„¢ ŽUåîæÔ¶‚ŒË¶¾íVñŸ`ËåHN9I”}’eªêòì9–«Ó—eæ‚%é½ÅbM Õóд7Éc+0é¹{¼ ¾- W-…Xw³@ÖK k«-õczoº 9gz«u=BÉKUÊJ¶*¯¾¢i¡Q¾­8ÜàíJŽŠu³q‚l:” ìï ÖLg²Ï[ˆ*wó|EyÖzÊâ id圦7sbƒê $uMɲ¶Àá#=öïâ»siw¼–R4*ËN-^|”kŽZ ³E%Êïò¯7ð=].üB¸öl_´Öè§Qµ¯Ç~¸ù?Lñfsöã&š¥I+[—ÙtÀœ;UÎîÔÚSéL«ƒªBO£Su‰ºîc; MŽ—ˆÉÅ»i×'oŠM?®ç‹»é—Ú²ÐÇee{~sÙc¤Hjñkd\Õ]k¼F·” Œ‘Çz²¤ÇºlÅN–Qí+fE(ÅšKåz‚5wÆŒ–¾|éÕà­æ&žy1ÐáìáAu85ñê/¬ XîñEÚu›*ZDÔ±áê†RÂ;Žà\5çÝ<&Ô¶Ï ¹-Q7Ô)<Õ£Cë»w¡¼O…P{:¤Ív<öç{ÒûÞé†#J¯‰`q4ˆ¬w³Çʼô~ý””†_+ß6mž--mf’߇cÀú³,émË9N¥iއdÅDŽ`ê<ƒîRQÞdUµ P”ê‚­‹©vïiËBN=£¡ÌÁl€µ©‘er‡MË[»ß¸8牭ÛÄÀ½Ôtû䛈ö\ÝÙîÄMssðÞ¬ê7ŽÔÅ@ѳhÕ¾WAÉËîh\£ìU½B eŽV: ÍØE©{DPTN‡ždä$+f¶nƒãÝi`}n¸ˆlÛ–¸{íí·«‹»•r!É‘smx{h-'M &¹e‡÷1Ó9º¡®¾çSy¨T•. MÖj‘Ê1êâ$ÜX¢ÕIx§ e‘pqv¯´sW‰â«7ícDÚòò=êõÒ˜q.^›kÉÝ Ûú®²°”&QùwOÞƒ²ñ®XŽÐ"ù9÷(ä G¥¿î¼QÌ^ñ½K>|»—nǾNºz—{„ ­x¬%ûWºJ½=N° ÞÚ"w 5Ù£•ŒGçCÙ\'¤Û«àkÏÙáV9ªò …{×Þñã^X}ï\±¯@]–BïR~Žè7!¢s~éŒó«dƒ+ «O=„b^tð{}§ÓÒƒ¥¾5««º*›’ÓGµ «ÊClùÖ'{»Ñ@öPË›Ì:æ^_n·bë¹Tɵ·Ö“aCϯNEÔ·p:*L87'm¹ÃºL<ÑÎ[îß1àfì·Þä°EA'¥p…Ymã3¡Y–Ô¯B®õ罋ºpΘ-ÕÌ—hžtÝêÉZµ¼5‹•Æå‘®²­N˜øPÓR[L¼=ެ¤’nñX÷OIγ,>‡²ð§OË:Òé«J{{7Ã+Œ9…ÓJÀ½šn†*ëç1Æîú`ëâõõòšm-½f¸&Ù†D´Y5{fÇeÀgP˜5Pí§HqÜ¥ßg“ˆf]ŒOÊ’X½§½Ùãï"+'•YfRÅ2Ƥr€½ôw+VâÁ-ÎÒ™ ÍYµ«¶Ü§¾êöç{¯|Ñ­ç7mÓªÅiëÅ«Z¥ŠX6J×¢ÁÎz@Œ°607m €¶ÕôÑ—[è©#ª,ݼæ.°[ø™ÕÙI3÷hÊZ—ŽšnÅzS4qyY1ø:”`_vR‹¢c:µ¶B’…’ ÖUhÅgÆ»}œÌVñÏyXÓmeÝSµâë}ŠåyqC“vúÁ‡RÅoS ÕÈžŠ;³ˆ›Ý¼#†÷¸¯;=èÝ-ÞBý€®ÜóÉ¥Ï#g¹ÔÚ…S¨G~¯n¼íË1ìÍKÓ¥è¹Oiö.ØÐ•±ÖT”¨À^é³›î.&—o ÅÁ~tˆò¤.ŽŠŸ»«_yoÔ°0Qê<¨qó­C†O<Öt¼ìõî|û…ŸT üRx\Ð@9 Ùl™Xð=ôû)Ý–0Î3^Yâ£wvâ×å­©Ùö6pfbì;s[edµÊ[u¹˜ôR•bÌ|µÓ¸ª~zÉ噯xûÝÛ”rýä…‡í—çd„Ö±a(ù^eƒÙ¢rÅvq pYR5¹¼ê)E .í¼Q¦Kâë®ÑŽÁÌËU—y:²§Ý  “žwq/ òõÀvÍúµpm×¹rýÒ²{íÀÐó9š½å™wÜShÙۦ©æ‚ó%uw[ ÒŬ©¶ÕjÍ/VôuiÙËå®Áv*y¥~{‘t¦}xrìÖ–¼ûÅÙÕÊΜ¡§Õ¶Móà›|;HÕ©0k©§n.Í0dËÙ·|­Ô8i¡{KŒ õcVDuàã¬:Êât}u;»æO\×ñÊÌÔ—¤ž¡î={o—³Æž õ¥ìÇutÅg¬AIó8ñŒHÓÁM6{ç³.¶îÏ:Ôµtu𠬱b—ÛÔP­Þâîú˜¹ñ“cJ ‹‡0žØ¡ºÙ7vÕbÉu«–j¬–¤ó^½ÓÓœt ‚ú]‘¸fÔbô€Á.+!}¤CmîÛO'Ï“«k·˜MêÌ‘FÆ^¾¼©EQ“‚uÌ9u²"¾W8›8ïx{¢Úß_¯’;oa/™ÍDô«Ø*]¯J j†°ëSíê šÎ :y`Ëw ì¦vQmÃ]yå.½…ñD€pä¦[%Æ(^æ3 OÍñs±¼ÝÔ)~=vùÑy‘ì~_²ºåmzµuróŽM²ŒÇN±Æ[ZÅ Ý+j ™–ß;8kJ”,(+’·ÆþÎɼd¹Jlðqºî¦j¾V­¹Ä,©)Mœ²]:2q;Wn×0”¥oVx‡T6_½®®Æ¶ý­í<¬¾ÃltÙ¡¦Ñ‚ƒãʵ­^:ò#7P؆#§ÝÚGžÏ. âC3•¦^Ý—¿Ž”Õz«\|vºk y}÷ušïmú‡ W,VÐÅzDd>0oiO—©Þbïp8ƒßw¦“,%éïodT]»½TïŠÕ;÷dÝÀô.×´lõgÜrPt„ ŠçJ—5vtsº½)bëÔkr´#¹Àœ³»Z] ©WO覆b(XîÝ9ÔU-è°N_}7QLJ¹ì ÂX66®ÊϽ©Î×@Ê»íî ²wê#«¼=VÁÓ¤7†ÚM™xžÆînûE-«©q¼ÃG*;lì™ÃªØ±¦n{rz³ÅøZ“çž¾^ö[±ÒSÞz..7ËaEË” w„ç çwxjIÕ¨JÆ*õd fÖ¹W1BË£¹8ˆ:ºã}´ é‚ié—Å:QEojù÷d4—NGÊð»oL^?¼YØ~W9ëÇlÖ+ë;jê²Ï +'3ÑŸpÁÑnlÁ¦Ò±:Áiv[f+‹ÑBÝqº=S.³ãk¥èÑDÊ€dS;´®¾ø€{{Bº¡úW­¥…bã=qz ó6û8 ¼]zõÁOUßvF`{©÷m>œ•pbÐèr¦´‹/î0*uÅ{Kôð>»ð-ð^êϯf.ûTÕhS°õÒJUò¹™Ò+¹ K]æìMÜ…&iÏ\ì[^áHä¿!‰ê|žgE¦b肦¼¬ïmw­u`Ì—žïkR²d¤×ÕÑ©“«l×fœt¢9ðbhVª›u®mlN·zzý­òT\2²!8híÕ'*άì1S£ g/ÇyIãpvèOÙºö ½I.lÈ»5³J¨a7¦ð<º@ɆdPçJ•‡:[Ë{`4¡3kUö{³6ÀïVÉæºÛ LlŒrÕh“¶Zò‘œ Æ=2¥°$çÞ%fnÞ‡àfïÓ­ç:ÕØÀ£Ó¸çyðª1 Ý#4åí‹îÕÝÝò©ªüúk]˜µu(;oMž«iù±^Š yLRY¸[®—¶’^Oz®ø*BUé¹ozo%½Ä »q'ªsé`Ü}Ôtqã»ïÃ+ÉÒ~ÛÍÜðK÷g*[¯Ò´k¯¬IRž¶‰·0Y5Õ–Vþ"ýï±;W Ï?Z¯U¯UE)síº†ß,•N£†°îFÒ]jº\É-0&ÐE’e> !å|á5ݸÕ´­¿]:Ï Ëëç§Å·Ï×Z¢ ÑEAâx7nÛº†] ¤¾“¦½Ï{ËԥѣŽQæóÕÅÚ¶ Óo³™R„䊙ºj ;o½kO© šüÕɯ[žZ÷SËOàÉöЬ×ãÛQio¨ðä™n²ÖÖ· YíW97¤S{s»«Éqª=K«oçtikij™`Ó@êµÖ bEC}®Ú[ƒ™®×Y”•òá ^ÙtgM#ðçšsÞ×ÎýZµƒØXCµ¯‡à¹­ñ£²­xç]~ëvÖã_¹Ž…ïFØ›ã¼7-äc°13æéJăG!‚(¢y‘?‡—VÛq¾Wc6°úç*´yÒ(Ó”°î/W²žØ‰…~¥çïmµ»ÂÆØõmЂ<÷Ð×_bÝí¨ôpH åöü&¾À¨-ÎYæ(Fo'u¬ZO'ÇO«6æ^']JõÃ/E‹¥¹%x µ}Ó–Š÷±øCu›Öq÷‹òKÝÒœ<ùŠß{2ýMåi]:èc ¤vQÚòî8Ž6RèÃdRÊôo/bê7*Ù%«Ù—åÇÈû}œ`à5—òËË—™ë»Ý7~z£7RäšðS­CqУæ&»§DéÈຶ;¶)Ù/:1Õg–áfæb€)tì1 ¦­-âô=¡©ày(‹è–K™W¥ó— ­'Ìi—5íb„æÅœ{ˆë^ÊÕ=Û]rûË·g7s¡@ŒÙš^=]¯X¼oÞ%m…NÀ*æÞe(û›ÀQÜ qÉöç´°‹·¥ÅsX“º$FÖÖåˆåG913mª‚E³ÍfF`i­ï“{ÚÑ¢ngO’©w•ÁVÝu)´ôìUð–%WŸqo·Æù\”±VYyÑ 2ó´yi›}c2ŒîÜ/9W8¨Œ¨éyÍ>îï0¦[Ê¿ ðiÖeøï ©g«q™­nÙð>B3ÕOΗµtoÇnß±pX²´)6­å <+¢¥}NÒ3¹š³#oªÙêñÕoÇÂæ®¢K©K©:u¢ú6Ìf$®âî{‡;ÒÜ4ïÄ=ð€ÀÓOJñ”¢2 y™Wââí\ßR¶#7ŠnvèPû)Ì[ꈦ%w‘Ån¿°íµ°åØw¦yJ›ZŒ–ÏÆågIÝHQ !›Ï³gI½:_á½Üx°^a˜}<õâ»É…\™ŽŽggnÊNºƤ­átm°°LÎä­, àé/E+¼/‡R•¦®%zóHówRß›ðñÒ^Æ–%mæ--f¥‚V‹UjÍæ¦à±©ñ¼†–.ÜäWì÷r—9÷{Â÷bkž*É6Eçky§B FÚÜ»jRÝxpl%€¤¬sŒ;øZ˜ôu·<É]›&׺‹ûÖœœ‘~:‹×y <­–AY†¶:ÁS±´w©Y4¶[\wÚëL+’ì÷·Ç"¥y­ë °¿[§Hõã˜faã½/|®h¥„jwîsç3Q("vkáÉL ŽÊ\¦åG«dc4²”k£‹.å¶îu›ÕÖU82VÑ® “ÕÓNÒ±\ù£k 'Ó§ µ{V¼ÂÆ­øÉdá[¼öf àßœšm륔cìãZOes&|i(ïgcé÷‰YîƒÌ½~,啿´íŒÉÒÌy®uº}”ÜjvJ·€ï,ö ®Òw;G1‚f¬›^ç>±…XÐýW®N µ v¥»‚9DæÝ›B8ÕRfóÚ³k£v*ájhp«ó ÝCÕŠüMß{‚gwVžÙl‰S^Ì›mÞt<Õ*Û¼šÒÇŸÎG¢1yI~Ѫ”X$Î(_+5z% Æ”ætîgí±Î>¯ËðGA~Eut,]Û™Ÿ~‹ç\=çÒd¬"Æ]7ÏÃVϼ‡RK…î´|-ù«žW“ ;äUà×¥ƒ‰ã»¶¶f…ã*“ ÚVI‰Öì9q Ü…æ©guo b°¼ëÏ™ã6ïˆ:*-PÍ÷s´WyÓAæÒO i¯w‚ ïϳ"¯1—ö£ícxz6ó8¬ü;%ÊÙMä 0ÝÁ–zù0{Cpñʳá»”¥ Uo][Ü…`âÔpçEÚÖ[¢v—a]ÜW9£‡¯˜N?Z+«7\YhAŸa‚ÒÀ Õˆáû¿Kôøy¬s8õ#·ô§НË&år“ˆs»¾‹²çÝM:Z²-=)c«³ÓuCÛT¨ÔöTͲòèuŠÂ…Úßu¥óœîÞY­³Í#rZݬͬÁ+¦M|1@jþAf8å?q£Œ¿t¤S#§¨ù"×°*ÔcìÍ“d Œ·Ës¬Ñi‡Íl¹WÕu)Ýê¯*uu]¦”7¶ûC¹RðpxÊ®Xo»hSu²ãÞõàÚÕ™NduÇÃÆmd¨nûpžÛ…ØGë4‚³é\O:jîïGnž6|E%Mš!;;U™‡Ë¼¸1;°V7J ~Ü~|ÍÞW¨ Á”Þú„÷ k¹kÒ…NÚŒâèøê©ó¸úÅςӗ½2<åòc|·±‡˜HH‚5fÏ?'·-WSxð‡«’7ÝRÆt_Kq4†•rÒo/R]Î î×’1#v§d¢ðCΚ EËÍ|/â6.yNðo 8‰ØÄ¤è¼Œ©•SËk=c?e,¯cÜÝŸ—é.ô+>Wkò¾)éFغííŠúÏd)R¨ãpSîeÚ¤ÅRéFöåî]Ñ;<ÚtÏ·×Äs“3±MÛŠi79+°++²nÚB·Véu°)Ù¥‹q´W´s„Çbë:Y«É]Õ ,EǤD<]&á˜+kÆ!aÔ]ìGQ<£®Õª@xÍÜÕ¡ðå-ˆpœæ¥éuO‰Œu=ÊRÖºgÒ@yaZíy8ë쌾+§-Qâ/7ÉI~Ð3%Cs}²>AÊT>«ýëð™c÷ï`cõçéž]Hæs–{a¤µAd•kk‰=ÄíºÎîËw³Øèl &–ÛO>Óß5ñ)߀6e\ …gd¿rOÍo=Þà Îö»ÞYWÜBz±yo¤êèPõyûÇg©]jJxpºhØy¯³Ü sëž<7¼}¾c¤Òòähùyzs_kHûœ•o°Ÿ\«Áå÷šu½Stg(¯–—[Ü·\3z–b–DÌây¨Õ¼ƒ«×§Þ2u3ö& fJ˜Ê ÉŠ-Â:NñS;ùV†îJ©¯~ͱ¶Î!߸ «5j})Qš>½(àÚÀ%˜é-»×nôµ@ —Wwû¹›6ŽŸ]Ò°Ô^/gq8·¨eí\×P™.ˆ¼š˜ÇÂ:[½kF8T Ôr›Ë´U‚uÁ!âÙÏwŽ—¨Åç¸Ó1Uº¾ Ý ¯V=§ÜòúØ®¬ÊÔÒíåVÁ(ËExêëY»f‘9áà2Žw{ÚÂÆ1Ò{²Õî=1,ײjuŠÞ±ˆøV¡už¯£iâÑ*í …†Èñ›çžÍæô½UÙë«ã=œ/Zê>œƒa¥\)¦÷¸ÆÇÊ&î’áÂ9WÂs²Øæòã±VLÎöÙÙxSs jÌ]*×·MùG;Á ÷/AÜμ‚¯wžá¯K•ãæü—Or~@gJã‹Aí»ì²Å1A, ¹èçƒfékioeK—‹Rzõ‹!Ñ»{S•ôÛ»,¥”ë£x:ų3…+÷¥*Às7Å`QeÉ ¤'.Þ¬¬42q»æ¬LÇŒR…Kå"Ò-f1S>}G鑉•·Ù(m ¹´¬oÖ(Rs+®ë\w\ÉÕcVå \øŸ½~ÒƒßE—ÃaÚìMFîÝvÒÛ¯>éÏ7IÅ¡|Æâ¬6 ò‹Ø­wÅÞ*ñOŠö·2Q±’Ê gžŸ½Тô<½)BÅï¹eª`¡yx}êp“cšÀyY3Ú…£f#oNЮÆVûÓ.=òæ=ü÷‡i‹‡Rý›úXý=æïËr¼ ת—N/o¨‡·cÛñ­Àñᫎ®IX­b²>5½’{«ÞT}½¹a=' à7ªo ʼԇ¸v…SA껈_Q R…·«¶¯,n÷Câß±,÷ºœÝ™ÜWe¬C€­zim'o}¼¦[ΣÝkŽRigPÃ5H³w¯àôÔ3]NšÞPäžÐ­®]†ß ѱÝÛÖƒJ˜›4 pYyðx•ÉŒƒ¾jP’®w–0ŒëŸLÆ< P™—m_q1bíÞíÉ-V¨F,Ž(òu½2Ýu_‡o{Žƒï9Þ¾S­1àó.Éó)Ø}ÄÑk†ºO=³×x¼¨e¶ÕæyU5£~™÷b+2c©dç¸L;Nºêäpò7YS‰{½Ý0]JG'RÌ—«ß5×|ò³I-%¢ç¦VÛ[g<éΔõO :h<³×y¹¡öÁ[|:‘ éâþxÆ&§·Ùîí¼5Ù+Û  r§$émg½rl窕ªäVæV«Å¦›® YÃÇsösóK«1g—h¤ö^vYé4e] ptEd½Y;ixÍ¢5 £«·ÝÛ˜¦zý>¿rKÛÛQ¼´²¦ì&(g=À%vÛ£ÆùFÊãÅ9FèáU9Xêãžs¯ØÈtýæ9¿j½¥ì Ú~¾Þð¸SBržç<Þ6U'í÷a÷u•׊"õåíÎrè¥ÉïYCu^<ÄB×ZÇQ*3³LÌ’žv»²!ÖìÅÆø›©¾OÎ\ÝU|<&r¡ïv óI°Ðé<'Y^ò÷…Ãg§C^$i£øà í@¬ã¡<;r—"¥ÙºÜœEeö±{σ{›H|Œ³tCT®ë*öç*ULp<-ÀëŽò ¿%žv¼j0DÃÈ¢Ò{,™™‰S·O·¯-À]qítsÞãNèîZ‡´K¡]œ¡5Œ õi6—´á–í@ò'¥ü•ß©•k±Ÿy¯ x•é¾˶¿×*Q‹va-<†>úÄíØw Ñ}½}:¬Ý:£Ó˜Î¡óìOP¼†ÖðEÌsw³]šËlÃN5º96ô ÖîÑNѧ`>So…ÕsÊŒïTSIiزu¥µ³¨lrl§TñN«Pí¾)Šè:ÑÈz™[T^ˆ®‚cÛ®ÀfVñÁË»ÙÑïn u—×+Q¶XÂZ[¡}–ë-¥Üäq£M*\ëGhÖôÐ[™ ÓÀ[‡¶ˆ ƒñg#¹ol¶kR¯Ÿ}‹*=y]½ 6Ì.- vò[ÒYºÊÃ×]8rŠ´Ã¼µÛÃM%›Y¤Ô á½Õ½ÄV鶸BX‘¢M½EÐ*yzvwO·­Õî>NI×`ÞƒÔR5ÕœÅKµšÛÍ‘vIÓ‰6‰2¹u»[.•C›÷l5¡Î…ÛÝ óR­ÁFIš@ 'ešîwÃPVÊÔ,ô\î¶ù’Óιk«;m¯#„àà/,:ujø-ÕQ–¾ˆc¥…Ú`›™XEAÿ _ðõ_ù¯þÆþå{¦»îü}ͯô~ϳ«ö£Jýæl9È-ëè©‘å ðí”BîÓaUJÙ‘MŽÐ vÌêÿŸšQO+TNGÉt©®!½ ì‘›2¶­Üv¿6V^j¦çÊ9íyÓTtBƒÀlg}ÏSjí®™ |ÇÊwe¾ÜêÄÆùL.\Èà¡U(S·%mÒ?åØì®ÃJ7t2³˜píI£ DB IR ™;ݾˆço¹î/E•çKKü}=®È…›¨Ó‰!Rªx¯Y¨æÛÖéxlŸ]ª‚gœ€Â0"D€ÂI²Ó€kR(^&oS§€Ã§ sاªddbD‹…G‘|Ê) P¤ÄqäŠ ™8LRl8‰2cÉ‘"#¢ŸSJôî´%臧PòÄ´°‘Êëê—¤«‚ÖÅV~VéXë^âUJSsBeW¹U€¼«Ú—#¥Eñ¤{ã›ðÕrjš7…sÛG)ßP7ŠmÚ좧µÐ]ÍxÌÞ 4Ðv¯M‡¤åvÔ•I³Ö 6Åœ外ãÞ£ä$ñ¼«×ê ø­ÕÕ|:‡Ëk1*EôðÅ}Œã¹c=;»°³¥­¯v¸ò÷Sõ R,tËóÍÈ5>Ú“"€íŒDÀ wI®œu5h²¶+éÁcËãÑa‘­¾îUí¨:ˆ¼öãëÕÀçü¤vU”}ׯáóÛ¿P©mQÝqì{’ÎÉÜÖz¯Êv!y*»_…ÞyeÊ Vl½ 2–îú¼“7 U¯~vþhO.Êè¤H°eÔé½h\ ÙÁoÔ=›ÂXïí«»¯®nÈ™’“‹1ïTI¾—µ¸`ÁIUì~îïió -wV¹«É]]dÛí†VÞ>Z:¢8ÍRÅx:ʸ/ƒŽ*UÏjÖâÍ6NWq@äAem”Ÿ¬ŒÞÂÉÄAM3kºL1ÝXk|+Ø÷´Ðl(úÅO,Yä×¾V뱈sÇ’³åv†Uü^ǰ±8¤5 »ª¸]Õ¥Ïs¹âM)àj ¾=)3ÌHo,C’5}¬Ñ—5%ÂLåÅÜ/º³ dŸ!ã\³°†ÑÄãzûdZY÷Sõn¨·Þ~=W^ö¤l±åº¢í•½G]ð“)Õ¾E_n0CòkWa÷[»z†zý¾¢«ã;öäÜáoõ$ ïOÃÃ,Ï«š9£SGad]¶«éÏ®ôkJ¬g-Á „°öÔTº¼áËÙ꺰^ÿ2˜öºÑÎïv'yß:‘[¦ÑÚ98;SIÐÞy¸Z¬œ‡;ybbòÀµK”¥IYÊy4]Ö/–lk¬.}Û[—¨"ÆTÜT«YlåмHN‡Å9GŒ;¼ßqØpGœ½ã×·odFnÎp*Y®Å>Ø#<ä-®ýRïÞ¡ˆ(7—‡†|¬Ð 2U7ƒ; fw>§”Ä€t¬¥JÎÝõ€üCe]õ“¢Âèj ttÖW.ÉÛ,Cc;“Iýªë½ÁJÛS¬4êá{~¨^ó'/×Ù=íõiÃZVb´Çñæ%%ëÞKh €Ìœ^ÄÑ£Atn…ZÅ'©‰ªw͉ësÏz§u_Sz¬ónë]·°ä¸B€©ozŸÊýîV6ó%½5î*pí v„t€l^pS3uµHw`»±ÑÙÖP'^+™ISs{sq ±©—ãƒ?9xžˆ6Ø2úÕû±LÌpGŽbu @'ãîŸz_êþ¬ïß©.ÔU Qjç~©wû~eÊæ‡ïïvR‚¥Û¯F‘ÊŽ-Y ÷-&VÜ«µg³îàóB«Oøãºc€ IªwÑXKÓÙÚëaÏÔóYó½sË®=?¯¸tí½ä/PÜÉ)³Cu.éQJ¨‘˜_æ«{qIbaz†9œ(ñ‡/m¨Ú3‡:¾Üºf[éFýï <;ß·îÛoB])Ù¹:Óut³ÖTÆùWŸ¼á¤ÛGýßR|_ãíæÇ[yGàl%":Ø+,Q fí&ŠøµWR*³åŸ ÂsñZJéÈè¼^[EÜèzº‡òq56¼bóÕÿE¿1øÖû²!ôו=·O[ûûú¦ŠËúÊb/îö=òØïö9÷÷ïÐö…ã;•cÉꆊÔåš1»¡þÝ-æjЛW•3WWXBÝoö×å~žUµbæ*òÆåMçFƒÒÀTue›»þLnqÎî¶%ÝùNs5i6‰žlé|íÁ”ž÷mêC=Îí6ϼ×ijõß7vä«~¥Þ°7%Ü1_™Ù÷OP¡ß =醵¼†ãé- å„jyû^xb¾ …·éO;Á[8/L—Õ[ÖÒÊW® ÔB“,ew¨ÌèÅæswcÐ×g¨‘KÚÏ”ôô¯vÉG¼0Ú•Ù#àmo°¤eYicYî_r¯W–‹+½‡üÔ÷C6Ȳ¹=Œ{s³÷O6øÔ!ßçuoaV·ÝKÜP®ß Õ=u_°V,…Ó–v–wçx3S*› ¥nã4©¡¢,W³+e(yG^×N4ÆÒ¯TÀ†ÞÁòòÏ^¿z’±éjjÚ–?u:›cÄòñG—”›Ó®ú²œ»§©lGÔÛÕê¾Ýµ)û5çhÕ+ÌÊÕ”‘üŽAçÝÊ”ñ®Å]†t9]ÉP¾ÌÇzô¶ÏÊNzž®Ç–Qhé}ÞÞ¸ Ïs&qZg­}Óá«& Ív÷êEÆ«{ ¤Y8/Ðú)n;oÒ—¯Ë¨ŒÜFKpûqS#¥ï ÖG¡õ:Åznk2ô[Ë*r—ç=Žw± àî¢ »¨Žï`90¼f&/Ó<àiâ›­-ð$toÁ¿ ¯`ojâË5ë d!íxÎÂ]+€À£[^5«ž[ö(NxÔ·—w^•k%kÖØÒ\ÈÖÙ¹³?¨®î«ïrÄEĽw¼Òàß'k©"SdïeõËG0EÍØÍáÃö@ÞØ²ú¦Ô¦„©”ñ0»â9ŒùϰéÛlj²f‘+T‘,•RèVö•Ü« ±òÛ¾v²îDô¨;¿mt£ïxÖÏ-¿=¢¢7âq>{÷¸­YΘ²÷Μ~õð©ÁêÌ4½•ªgßÕýU~½Yà{ßž¯Ñ­ÜLLuÖ§u!eò¼ÕÂî÷U§Lx¿YŒ6c‰?4• ·ï '7Ó~ !ï.¯|Ù÷C SöNzImò.qT…z5ètUë«táÕ⮵˺Û…‚«£»sR8Þ¦M®}]Csªs4Îçhî=%ðÆvã”a8JÖÊ[µÀHÁágA›ØêíÜ*•æ.È4º_bi‹.–œ¨Ül›Nåbk'a.€Ü7‰­‚vÕõë~~»¡ û3Î%ê³ÖÔÑY5M9y#»Ûä¸ôÀp‘Sé炜Ì5¬¡s/ŸgÉa ©íÐÒn,ì·•G%˜œ¨«®¾ÍÅ)žºU³²›@á´¾Hý]|Ω‡0 «¹RªýV‹LæçŒa«Åå)®e¥–/Àiï¤5Ý)®·v¯¢Ñ@§‡4 ˜ëY¹é[ÃT—ÛaÞW¹ÁAªÒ]e#UŠåÊ[w ±oºgoÝN¯ 736K^€>µ ]-Œì¶Ù¹Ïtë%'´ê….R3›‰Ót´üïÅQÊcâÿ•ã«÷íîýçê{v@*3r îŽ讥ޓ' °2¤¾{]Œé—N(z k®®[íþ{}Ö¤ÞÑk#QËžNRÁÕnø«AëÔǵô7¤3ë½T½ÛÔ;íMt?f ƒjd4®ñŒ rÎÆnÀö\Žç‡÷VÁñŸÙ˜52n»§rQYâAÅ‹R¾Ç!åÅäµ×„Ùu–X¼TP m ž_K{8r×{1Ç­ÖîaÔÛv^ààë:Bå? -ª²]IjÕ-7^ïg ìŒ9ì¯VNåáY¼³×,fNýT»Ú·SlRó[yëÀ†\q¾Û}v`M( ³ríX°WY¹_}÷Þ¥_אַç©þQ.õº?Ïø&[ˆÄΣ½¼¥Ô';, ÇÒì`Ü·Ú2 ÍÒ·š¬Üu“Eª¯+oR°•ÕËN”­™y±œkb[W—óðHMíÆ¥-µ‹³˜&TGŒE†ãB­¾°ºJš’[Ä65-¹MÝ4÷hVî`›sqVd91—„Ó( =Ûrñ,Û%„íö¼ ¡— ¼NÛ­Ù rèÊ'),Ú[[¦¢îkš›zN©¤ƒŽú²>™yŠëA‡(Å1{šúÞÔt]£¶kE,à`@c`$1›Ûzñ ŠÈ3nüô©Hʰ4ÙLtï6Ó™nìכּ6‰ ¸wÓŽU âÕ±`ºŠ;gRº¤ó¦i¦ºpäµSíˆ:ÒhêÃ×w±ØÎø×î[Žc}ŸL^æû©Š— .*§;³[ÃÇË=ÝãéfaôÏ+žÙG$÷³nW°Å_wü ¦'–èï•iÏ#Lteнº¤Õ¦ “¶+G$—ß¹[ìkÀ‡6›á={Eí%¹iÎ9öòrnÝ5í† §YËyXx:ݤ±ab?=$p.G×Üo¼Xë/}]g——]1é&œñÇè Á7ž±®÷Eó²Tô¨¹jÇv Ñ[³¤^ëe2—ÀêQyW]t% +hËr>¤ÐjÖVö æô®Žèo\«šË!ZšÂÈÀÙÁ*ê`£hâ®ìâÌwzùN$±´^öVbvš8¯þ+½ÏÔÊßQO¿_¿hì§ê³-³;}TÇ«ˆÿª6åx£ºÿp¦3óÒŸXÍ®­ÎwÄãô§RNήãaÏR{j½¹L&m@šeœíó7sˆoQÕ˜?Ûõ{ögæ_çúûÂÿkÐS‡) 9ZÒHm‘BÖú”«~Åïcë¸ütà¤MfŒs–X”%ê¦o@ˆ*7‰wD™*!Yhf蜫rŽŒa˜ÉUêy]³Š¼À®#Þ¡·aÙQE;L6ó ê•Íážÿj }êÊ¿,ã/Úù@^ï,¡Z#JŠ®ß)¡7 L° ˜ò·ÁѺÈÌ;vR´ÐYîºÌ&Ý1·Ø6uŠ-RÇPÇòŽm«*v­¢ïëÕáþ/ÊÊæ¬¿¸ÕùwTÌk‘l\Ü#P½&½ÃܵðG®Ý@Qt£Ã{}¸}8{¯=Ö‰”Àºô”DéЦB¸ì 2ý%`%ò+~UÄämôóÌ[»À.>“¥W…ªçÉ ‚ž•Âíò<õìØw©ÒQD®‰ììʼ¶rÖ· -¶åRŸ}ÇO—o½Ä­ì¢ÉsžLtíÆ??á;mbTýFÒ9³îí1ÝЬxo}¾[V€C•Ò¸ÐÌ×jŽ®;P¦û=áD5H,øç¨Aw¢y:¤C}y]Z2ù‹ñ»ræW¸ý£y-˜žG>YPž›ºh¨›m6”³ÆsÍrÏ*ჱVhçÔ9r²5„¹´jÈÔ˜Ïu(o%£»Æz¿«ü¬»­UïCºOéþ¤k"ŽÎA*öûs¦¯çŒ÷»Šû×… <–zÁ]¸ëÜÚR‹¿(¼Æ¶pwžäžŒÒ‹½R.u{½>&éÔ|ûJtË­·ÏºÌ婾¡ãmê‰û¤íë]* ‡–¬¾;kJ*wr[JeH\7€[Á€×QìÌ c·Ò¢§îú²‚ÈÏ_A¦¦L¤owõµ' LóŽîn[ØßóŒ?Xºp`÷ ^º”zJÀów”Á·-^RôÚ°DËÛ¡C ]&QÑ:”±v}Üm‰‡«U­­!ªyæ_†lob9oˆa}~ëqi1!î9ïÎêò¹×/t÷·Ò”Í«ECÙš;á =Q*Êl®gM&iãÓç§Ø,'”=Ž: .÷DÞÓÊëöMè« w>VndUʼë¡5j¬ð€JÉ.]ÞÐq¼vBe½Î©G†¬·‰ëuº˜E£¸efM¨+k¡‡iJâèçw9{¬î‚¶‹¨M6Á3Nš Õƒu×½>ÜQe7™úßâ+Ëо^®­U±ó{Ù}Ð}™ÛLê­N‰õ£ŒŸyç·ö¸›¶½îžåA£p]£Ä^Û¦,ìV9µC;B×ÜÍv1`u¬Ñe÷h½–[ìûU.r°ÖpЮ-]MtÇS»{Íöï@¤Õ/Ö³ÚÉ»´&eõš]’¼Ì·¼ü lf«WuÞ-ÕªÚè/|+5½&–)÷«õj¿:ÕŠ ïØÀ<»V6˜ÿáx {91f3ÃûÿªÝÑýùo¿qÃæVaÙЂÊë5)þògP…w:z½ogÐêYà%ÞWûvnªb­8kÖØ‰oTWtN«©{,X,Ãæ \+»;SÍàúN—›)7×dz[À+t ®³íç]}æe-àæÔt)ú‘ˆ)ê¾ýûÕ=&~¾ü1 ƒuþ¸$šï·'h¾& Áj£¦¯õ'©zÜõ`ðƳ&à=Ó§PíÝ7PGºÙŒfGœò-͉RS.û¶:ÍãVë7z‡dðÖØmQéËÀ¿;^ *k²Õ_gh*Ùýbñ¹¯Ã½ÂÏwö«—LÓœ{ÖhHÑ„6š·ûÑK=+–< .¾Á˜Ç€}h‹êf‡:7ÙÛgoUô÷g½EcÝ^¡B™õ%î6¹SDc²áO‘ò8åÉXEãÑ ·ßof}Œ`Ó'_v»pÜ»³UX£ÝÈ×’“§½ÇËPw°¯u†Èz>‘P|óצúDªô{;2§bç­5tÃͬÔ)*W·¿Ôzº½«Ü¶•%Bac–y4õó‹~³Öÿ#z»Ç¢§ ½§éž†,«lG™íBæqÜ•gg'\"ÆúaÙ{«!© ë·©fËvpÛ‚òÖ߆è˜ô –ß;oÀä}R•¹Off%iœÁ½‹Ùb€‘]‰ÖÑõ/^ÓÜ”ÜO´žéUŽ S˜úý«Þ¶ð´èê̯ ýQ®‚Ħdãíà?Tï m):~ê×®ëKJðþôØñµsÂ’lÛBÿS9_¡~CöôWøgëIå:¶(7XØÃMÖ_¨]Ü3¹eß ð.á›3-_„½ß)ð~õeÓªGÑÂRÞ œñåîïYÜßZ§Àüî»Ö_“f'Ç‘DÃGºlC”á[w£‰ÝÜ•²Ëk1™ìçJOsèñ^øJib#„Bä![—¿{å$…¥º‡R?Ëý©/JíWþÎZøT?ÛßM¡"¸ªyY”2^ÆÕ*èÙiÖtºÊp F¥€†uÄÇ-— ÌÐËV›kç|mÓ°mmwtt(¯»À6úOg_®³f<ñãPVègÚa÷Žë÷5'”UŽŠ-Uçq»›²û4Ù³­»qªY{܉”Rxû»ìÝáô®®ªÉ3õzý<ôdÇÔèÑö×ï³v?UÒ›®_î¯êÌ¿s×N‰¯øz U¦–gÚ¬µï[¿[>¼ïêþ­þ`xæ7SÔÿ–®u‰âÉì¡m:« êòö1ýE=žü¸+h ý–a³ˆîîmgâƒÛ ’aöÞÝ\õw_Æ-‡;z<ÚñÅñLw9Sª_ˆë¡PT±ÓßoõO^òÐýÄ]Ø+c~•¾4øvŸÛYÒìQõ±ÕÌŸäÿUû qéHÊA°:‡cæesTîCSp‰Vyǧ^?Ouy&²|wV¿»8—ÖÖž{]£s»íY^~§«¬Õt®Õ2{¹Õ‘’Õ\wK@m­Xój¿«îu¬QÌ£µÙ÷… y U‹íî´êA}Q÷gÞªÏÚ¬ùÑùߌü>×x'ù×£Ò4?uz¾÷ ‡³ í¼÷‰s­ß»˜éͲ4Ò€ôõD+ÕŠÍx½Ð†ÑH1•çD¡¸Y,ÛÌ2òÎâ#Ú4<ÜR?§µõÔê©NZ·ÆKJÏ̇…w1Œ©W«Æhv¦ôãÚo’[]¥$õenaBÀ{œÐË®Ë{{R }«è…)Ö{nï–÷â­Åàü=ŽÏˆ.·K¹wî âî7© ~ÑKã’Ýög*6ïÞyëדS…ß¼ó^‡ÔöªýR¯§¬!N›ÛõúŸ‰è÷¬ Ìà$ë,‹`4ÓÄ.u†pïê˜%õߣt´y {Aîdúï/žÙb‡Úx×z<(÷§ÈdUßX§––i/AÃQ_ íØjY‚m#ÖßeAƒÇ&.Æõºï…#¡’<{ÎÞš5L¥õ»i­—“ì¶¹ %iÅ^Ьš^­Ëõí:fômy:ý”ù…›êÐëýßäþÙüÿy*Í_ÖIy˜+RӢݽ¬…ýV'Êzx ĵõì#þ €frÀô* ô¢Ååeë”kžý5aß%ˆçK޼*ÃÊÌUlغô^ËeýGªíÖŧ·¢º±à×FÕlãwÈ’áìE(åå«OÛ Î`lÕ[ᾫ1R S#Z›¶:÷&ìÆ>Õë]ÑΣÉÍ8k”Ê+Íø3;rá1ï ±G³f);¼Ûu§s¨½ÚWb­­Xßn%Ê«kw™IëìPnÝ{÷ÝbåoxŽÅûåßcè ©Šr’ã_±-­Ó¼"à·‘V~òF¯ÆKÝY*{Õ©VÚÐ#¸ºxR®ïaº9ƒR%Æ0û;%„³ÈÔxh¯h±íä’mæC‰ [vv÷kHrOkë 'àT¥ž}fE›=®ÌÿsŸ%IœåNȯW=m‚ë–€Ôûm:}«U] XÑWIV¡Sªô…8)ܸê×Û²ôg (/­é×›#v™ã£y.W¬6lÁ¨ ]JÝK½Ù'K=W]Å;Î}ÞØûƒÕy ïÞªdúu¹¸d‡¿-·îÙ.§”¾^•¶PÙ½²ŒYžò´®–ÿ³ÏÔêªɊ¢áì0sNbßuÏ7i«rÉTw~c¦áŒVÀ†fb=O{oªÚÓOªr­j©‡Xý Xm¯N…#4ùës<œºâp^aÈnÊuOµÐUj臖‡º©u·L©¼ 5Õ3.eªI‰*a©»Ž¿Ûû÷]¬?'Ü<¿¿µvuù7kú‡ÊŒË¢Z¤h7ÞÊß#»äliì[Hzñ…,)q*&Éó©°â¤ï…*ô÷aæ¼³ËΖuv<Ð <Ë™|XUbíWV‘à'›¬ëºÎ1ÙºUºG[îNGNÂ7ïU×·/]ÇŸh†¥bœ®û-r5/MЦî×$A>ë¤@¬+=˜17Å+¯êÍŽ¼öwfÑúç¯ò{/û ¦£Óø†}ÝõEYRÄ–†Ó/@'uר÷ZP仯ñ9Ü-¸jãüþ¼½Ú_-_2óØ9Yþ©Ÿ^èkÏ6»ÃpÆP§Í'‰gUß&ÈJéáàÖ~­D½Æ×0»@Õø.º•ê>T¶ÿзø¥ÿ Ÿ—ïο­ jXèï"›úù@­J󡼸‘ÎÍ s &¶€sgK¼)Z 1hnX;¡¼Â›XÆSi/Ÿ%k~urÌé¡…ª¶¬ÒìåšAîßü-­—Õ›â$[”='¨ ã¦2F_•„YEj>°ÔÓ'ù {9ýûêª~bQÿJÿ«ŒÁýE¢Fkü(Ú,%cg ¡pQzº¥ÝÜf( †eu×([˜½»rå7Ê’eéÞ}¥åZä„ËpnlÚsXŠËFWÒ³g>žåÞÆÕdiõ×a¶ u•¥Hd­Á[Š´ ýlüÖ¢«Ø{Äߺ,Ïõøåu]…”ñV€³gœ0z ¾¹ê†ÉUÙS?ˆ•ûAÂÛ»Â: × ©—V?^•ÜéRÞ¯ô¯çß¿kü1Ðmõ +Ág릣®tYÍ.íYú¿gw¿/Ý«ñÉûø•L$U-e<ôžõš¿ÕÙí÷ïÓØü?Z{úpb·ì ¸¬)‰]í£Õï͆óÓá5³Ð Áîbˆ·­Wi‚fÜpî¦b³w™yƬò1î¡óôCÚO¥\4 Ê÷Ó=¹ƒÕY€4ï_•žÔÚí‰øÝ[|÷ÏæÂWÂð¾jìØyíBU”futMÀÝ;êhì©»yËŽùˆÒ -åÙ1_v´<©r¡î–ú¼ÛéWì÷¿•?TjÚU&…ÝKE{+ÓX6ÜÒØ'µìæ#ÝÁªÓËÖaý]CòMôCÁ:‡g ™Ÿ:³…ò]ú»¾¡íž§X}Ò´Àõa’±Ë¤ ÷¾åëò»¡Þ»òýK•;ýup¶}.ÝúºÞ%ËŸXTç|#ÝR4‹zÁÕ8h¥W‡¶möîô*Ó¹²ÍC/x!M­bkqî¯ÝçÑï²»WQhú³é#G–þ5»ÄŠá8—É]ÃVòˆ·›ÃWfÓ½ÑPIYŠÊÐCBæSwhqê÷«VqÄk¯9ضmx2ô{¦Œ©ÜNÉÕfŸVÑ+½{'ƒAêy4v|¸«¾àú˜s'•[ºÃa„×|póÎlt_¾¯aô©uß«Ù+výµÝ­•£%.[—Ax)ÏØøÞfJäô¬ æø×ï§j k3+}ïe+BìrÞmwÆ„‚ñUãËùW]*ìWuùîšü]ÕqûÓ-À¸é½;»Ð\¶uÖÁÅ¢t Ó[‘ êgˆÐrõ ãQc¦ÆJÍ«[Z³¼ÜobÇéKÃ=,'ŽW™@@|,ê(“ÏÝÛ†•FùY‚IÝÊÆLîÇìïO‡hêU:·ÄQÖäõzïÑQ ªé¶_¡0,DópÁƒ1ç²Ö½Èu½ö‡=¼G]勈ên-ôÆ,Oo©»võUÞFÐòœÅXÛ­Â&DeHó]ô±¹œÐåî§´g·©`û .Ž—ádóagwò¯Ç½Õbv~¿Ø!¤Ì `—j§àÄÄAš6ÊÓb{KúQ¹WÈi¦ag7ÔÍã#¦´³ £Ÿ7¬˜lZÍD…ûq TaÎqŽ‘A,.–…üOØFÏÃø`îµþý=cʲ‡8«Wûjbý}S¯ƒ«óÞ‚‹NM„ÎÄÜ4©Y뮼8¸`¥ÉæÜ)á…i‚ã/©.· $;nN¶Ñ½ÇrÊ’§^‰hÖü¿Ùê åൕþÓGßÌ÷öÖ¶ÿ«+|õ8âÅÐæo§°ê•äÌ'ÞdûØC]i6WAÂÚÙªHWo;3ŽžÎØ ½t@Ú×C¹ÝÜëIÂbs†ž‘Ò¾}ˆß4YŒœ3iY|{3·(s¬®Š³b;5&Z½®XKÃ[t¸«±jrƒ®è°'¸"ùï)NîGVçcí6b©8n¦IxvÄ™«9Íe”¥<äž½µÔð'Y†S賺µbP –…—•Ef§YƒeJu˜¢ºÊ`”Ÿ¸s>Ã1uÝ$/rׄ[«„åÆiY3Ht“ºÙ¬]·G³DZx”c«µ7¾áž’¿»žÁÂöÇÌêSv*ª k×{…yji{¸n†¹®h¡[W£ÙE4#ÂrNïyÿªÍœEý‰è.ºgx+p›ÄSZ&LŠç÷½¢ÿ¿nЗcÂ{¯ ºïM+Áû‰5,ɵ®iYÝé! ÍûÏÐàž¸-Àéñ:ˆóO\›Üìk¼,ïKYËKÊ·[D!ò#usx§Õx¿er‚´wŸ®K« ½÷;Ú+´S"…všF´¶zà÷:РlÛYºü;µö‡=cÐú]êš—¨ÖNIÜö®Ûî÷/R¦‘Š—†º´-W¶VÙ•¦ÞûÕïºv «®g˜KÜžÒnëÒTž&+ì  cwOevöðÀƒyÛ!Q°…L3HxJ¼n<32ûitéQ“zs©|¢‡ŸK"šÇLÕ^»Þ3Ú~ù¯zÞÚÜ"}oÜùðÍ£(^«®“i(†âB@cA9ÒœÁ¼õÇoLxýu}‚‡ˆ0Wm¦ë=™÷À˜kÒ¶ð¾Û3òõßÖh¬©å]vë«kÞÑW~TUø^¬d\¦ª[÷%º:.+ÖuÐïtôÇJû»{­±öÙ{NLmÞLî© ™t,õò§µ´­l·ïeûÏjçŸç»€Õh鑉êë—ïÝŠy­øSóùQoF^OJÃê2üó.±gÝ*MÊ’½ÖíeÖR+=)Ië|}X­ô.cÞË£š´Ç¹*}‡K¦z÷¥:ú’ ·VŠŽEÉtÝV ËߺL »ërûÍât®w¼WAh–t.Bî‚nÏJ»á‹jJ>è*ù¿GÏ;/ v¿rY‹VðOó¯UÙ¾X>ÿ/XÚ>G9ÛK4€–íÕ¹®G>ʵ΅{Ó̉¥yÀU†üƒ¦´C¼ª–§cZK­ËT˜º¸·úÓ~ÎKÐäAú¸oÔŸá—¸÷Ñbí4õûÉ­íåä ”ôwu‚fz•AÊ›YOµó®_s¬êZÕê•þzg¾ö¹Wrß;Öa ŒÃ=wµ©šØ—'¼Xé\U÷^Nê§7“œ–Jߟvôy}€‘g—Mí>m'™šS{Øë9p [=°'»Ëë¿‰ŽŽv…±¡ ³im®Ì@¹»³I°ÃV¿Û÷z=ßb½µ¸WRÄTÊß\ëµ]ÍÌ#~ùF?~›«÷·ïÝÚšü·Ù6e]Çû])/fx.~øu:?¸³ÛÛéM{¹öÛ¯Gê7“=…Axïr~odur»Ù|ú9mw70Årm|¹eç¸xo'ÌW{;Szñq¿N}ë'…qCOGÆ5w+‰¯x”¼šòÛµˆâÎuÜí¢;Õ¥Ýö¼P”.åçD÷]co¥ÙøíócpÃ9¥ƒH9Vަ—1åÍØ*ŽXŕڵµœøžL¼€:š¨Ï^â÷·+*NÅQE¬î¯tY·y¯dRñwUÓ=`>lÁ;M ’ÅËK%ô™ñ-Û3ŸPkzå{Ä4ær³JŠÊ—‚·xç 27q•Ç á¬Nc.ôÆ'õ(ýçk6*ëù«:™¬Íâ콟„³ONÀ=·ætûho Nw…×{-ìE©S§´”²ø åÚu}ìò7C’­îÁæò§9 qƒÆH…¹Ù^ÒªoŽèõ—IVÌß?xÐ99ò–pv»YÄ‘*í&ÚZ_r•— “h¦”¬§—u%φÁ:ŠyËÍ¡š:qJ¯{70¢Féh1§:¦ôÝYÖ¶ß,Ç9º5ÐPÍOz6ó:ø%ܬ Õ‘Jy&µ‹är(l¥Õƒ'iùeÔÚêÑ‹)‘?—Þê±…y•g¯ðén¢75ûõ¶È_¿aËô÷Ш›Ú×Ñ‘4¸lz“N¬p™8*ãÖ1"¬&ïmï.gµac•#°cÿ‡îá‹¥w¼Vî@—3yV_m@[íêäÁØå:55Š­ÃÊ•L½¶Í¸1¥—˜&’§fÖâ€uMYÜû`£¿‰Ú~é¦K`¯O(ò†KçH‹àzŒøá»x]L¡;|‚Ïa[— fÆÆ]ìø*÷,yôN´Æðí7:îì÷DórùÎÆLáÎÃc©x¼¥|A°½÷DyßFÏs! Ûu»ÇŽðëHõ’ɰ64þ͹p ë “¶ë²kàmcÚÕÛ˜Ón\äYW;Ç ä*b…5cYÇ7^ßPÚ}ÏÅß ÷<5ahöžSQwyK®Äé1ËTŸÁn<|¼§„4»ÉQÜÏ=Ÿt}l.æãùõýšmöe>±ô-ý·¾˜»õƒèék'âÝN†$Í]'RŒêÚ³ðÚü¼;O®Á)]ÏÝÖ³¡’û¸bHèˬ¿3˜U4™è\•«qoY¬`?ò¿Õ?×ãÝå*Ê_E…ž7xžî Qþèi)ü^í¿.ÛŸ«ìû¢™û©[kay¹í4:è;·BSšyõÙZ¥kº²c_¯eIÕ.¼òïw)ªlªÛïqÔ:`¥er¥Äç] ÈF!µ¾ô~^}¼ð3ˆ ~± <€æ8´#–Fšëw(¸VGznÓ2º–§x«²_µŸ«ðß!ùW翹LŸÛ±ª‡m $làYþ§Ø%Ýo©&%úH©èv° —ž3$‹å‹è^_aÖÏ÷« ìòˆ!\{½,—ë©^~3ÍÌÖ¿Pnó+¨Ý }^B¦ô¨>J—ÒÅ´Ór ¥BÚæÁ²?ÝíOÍ{ìi‚EçYa³p¶Dåå…ØÇ\]G—óìΜp®"µ/ö~5G¿Ùõ³ïçåLÄ' Y0¥¡*D¸YFÕ[-Vª¹#¥_D¶[¹AÒ¼%»®y}•Ð,ÌÀÿÚcï[ßÔì:õh͇ð³ôêýœ»‚¡u‹N]̇n÷€Áz:§Às»LÕåÔty1ʺ¢Á´)7Ú×Yox~×¥ŽRÞxÇPÅÐyäîLЦû$`«炱=wa0—‰Ï ®i).aØêWgÊtÍε=›dßzêç/3©%þŽø|=:Ð?´-ß÷ñåÏ¢ðH‰?¯ÃãfÍ9xå’è=µZÍv:|Þ|øMîê¤5öªbõöEëÍ;*Õ©ÕÎUÓvw*Ô©œöÏ{ÃÞ:kO«¥§ž¹G$­Àe{A Ðù`ÇHÙÞºwxøkð7ªè¡Œ\rá#Ô­ß7‘WŽ|ÄŒòÚ[ÑΩp9I~4À¡uŠ—… EAFðÒ÷½Ô+ :««Æo«×±7;K(˜ t½ÆehO Ûg\~·¾Ážôð1ÖxÌñÃ×ÎtÏÙb @±ÀÕäwµÊÇ<2‚†Jëí*-ÿ*½ˆõ+ÔûM/DÛ«óuÜWvjóK@ƯôÏ>Û‡ˆS¼¨¢­Õ2É]DÚqÖîêvj¯MdÌÑ¡#Z§·Aݾ.¶¿'©ÍÍØ5H]ַרõÝkÀ¤¦ôr£vxpç—Ád«¦Þh¡¹ys5õ¸ó³¿€6ëö¨‰³Â¿~OñüÏèí>BnW^L\µÛ¶¤wù…½‡¼Ý‹ ¡Jm¹G~Ê9½£äK©½dÝçV”ï÷(ûkRdœŸx^n“Ë7ëtªT×RçM.¬Û§ ̬3i3uWÔ”wt¹nßG V­~+aQïg¥e¥ÛoxÙÜ¥MFމ¼CþY¦èvªÐLìÄÆþ÷%h:ýPŽaß…±aºXÅzº¡«šÊÜ]RÌýOõô#ÃŽ‘ÛëO6ûdv5iÆófbzgld Ö°s*8¥„8Ô3UÔÛ†OòF‹Ù¸êikžtά3Òƒo®²ˆ/·¸î}˜ð 8«pM5b°~iù!«Ì8ý<óÄFÕ‘/+Ø{å‡(t±¸µä¢j×]‰‹ºÞÓg†©ˆ †Û׫»w°œ…h6qžËuWÇ;£{ÓV:J5¼ßHž (>#"2ä6ðL²­ÝZÄÃÒàJP_2 \Î:ƽ–ôä|i,ÉŒ¦¤`˜%Åk¯ª—Û|o•µ9§ÐÙçÌ>nv²è°á"ôI[\*+éføVtnÒ•³ÞÇó£Ñ‚J:³÷žÚœc«Æ­šöÔÐPîô„…íÏ{gJ>!Þ¶N!dRɕǫjØ·Û¸Äâgeq1QÁÔŠÎ5% Yn`Ç©níg4NmÊéðO9^âÝÞBÅ1Ì|ƒ¹,1 ®SãÅŠû$8r‚0R^jÒORöB©ô ½¹Š§½Þá^·»y’—V+|×jVº|Ð0«ÉØöç×{ðê57tƒÉÔ‚nðµšF÷d],y½‚œѰ´Žà©\®6&Föþæ˜ÅŸvr¯Êk_¿á<Ÿ„(Þ4IAÒ«Ÿ¿~ñ­Òm?šïlñóÏ ë¼ËÍZ—½¦¥¿/+I½,îÉf³ÃXF'—«_Szn “]¹Ñ¦ðMË=9UÛ)šÞY™Ò¥”ÅÑá¹Kº­%­^<6ò÷ˆ}¯´S[Û'R•0á–+·{5î¿IH“¶Ú8›ú?;~ÌÓÔis·•1£µÑ;ê°Ù|ó¯\¿ŸNPjCÊ+ä á™´ö ¨mí-à6Q³~$v•=ê>¦S‡†C) ÝV4W®ÔöºÙ¸qnÝrÛrÆ;ÝÙLû1¡ÍcÁR‚ý£ïRðê–:ñúî[¾ÚqÙù7EzoilÐ…X7@u¥A<£Û5dÚíé(ÍÂ=ó¶±£ñ¤c¼`éK³e¼.~¬’?Ú÷VÆotê´.{…ÝÓ÷§ô·jc…VúŸ¢£8Ñ­AO]ø?ݵsLòV(®Vs˜ÌèŽÌØ×~¡¦'íÀv|²ÛWë¿+N´=ïï%€wÏÖ3ƒÔ™¬.“å¤÷2 ²B¨B¥›ÖÈà,™Y«NõñÊ üiÞ-U5kc³t±©p¤‘‡kÓÚaàÞ¨Ú&’9¼ÏW\ |o¨q#wÞ"Ã~¯]ûõLä¿55;WäŽT×ù`ßš8ïO|€»n›è¯e*šz^‚·«gÉûÒž¤“Çš —§ƒÚNˆ›Ko½pr¶{ÒðWY¥gàË}ò;|þw—­æeK]´¤w]³o¿Ïí™Á~ïJýÝ/G–n0„º¾k¿Tù*ÑÒϼêÒËOhbÙ[XèÐí)euëX†öí$î÷ç|¯:r\ð.p²w´réNó»9MѼæ+v¬¬{'[ͰJ‘_Oô©YSÕ÷x¶“ ì „ õá{%x” þºî_«Ùùã=?i¯Öö¿tý^è.â¼Ó+Q—£ƒS,zãAд6»OZ©ƒ8¼NnŒ >H©|ì7›H]‹!EW—›Ý®ÑwžÝ÷dGi9Ù-õ Ú Mbœ%­³ƒyﱿzÅ1\wËiî¤W,yµìïw<¹Û›¶„°}ªn£¢Ã­}Nã˜Ô l‹ÿwüåWªóù/žþ+Ù_àÊÿ9eÿ’vRð-G›¾xnåù; ž"Vy£kÏb&b²h¹ØñÜÍá‘P ¤ºðPšÙë­*¬”o™ü5Uø!½ægÞŽ¿ßÝš ­ßÓ,N°ñ è«™¬½ÓÕÊâ³€oòzðC«Ú{o+ά!í+Ñá•;/’%î(±å&ñþ{ïGÔϬïéúSÛH¾¤úZ½ë›†À꟧<ïhmúMÐQýq¡kz <WNï†BÇŸŸ3ø ·úo/γ÷âÐí?¨³ÅïoLQc៻¹{Ó Å|¼+Ëka ݱ3’ʙە#`^žku™ŒÅ»BŒÂvq´ÜOHT#K¯_JÇèþ‡{`®R›£¨#;±%}Y˲ +)¦QÀénW4má·rZ¿Q‡jǯ1o>“JPÕ¿\«õZ¹Fçê÷Ú<öS<÷}£»ÜëÎ=Éo3Ç´yrhoŠñ¿ûÇfì›°Ó§k9×g  qÖË´«fc¦^…Âh¾ká|Û»eV·»O2çnV›{8`òÍ;§</sÞöÐ\µmx[¶=×ÈØšï{ÒêÜñ÷˜|},Ö*ß¹µ‘g{ÑM=ؽ4 óOŽY¿Pɽ7<‰ÿ=úË?»;–~êE6…f­ÌÏØ ¹÷?Ÿ›«§›`0üñ¤¿ß_H/cè)VߊÊY†÷Þ›ÒÝu£f—éìÄRõ€Ê¢ýÝ;æ.W‡[µè¦ÿ•WÙEÃg÷O:€ŸÕ˜¨ãtè:ïÆÝ¡îvYçç[~fÛýÿ<¦Þ®Jš£ùúÍÍÝ_šçœŽõ'Z­ ⪘+ªÑ\«/}ÜÙAè›uü1h¯Íþò‡Õ±M»//Ô‡¿µóq+—™Yìçø™‚–€±èñHJCö=Ú¯nùÕ–r)aÌ×]ì ?wm²|«é7Bº÷3T8íö7ÁÔnnº¯‹ÔÍ¡Ü5QNÌ2îÛq›ÊݾŽùb3KÛSN\߸«®m"\R$½a×€ÿoãʯc@û/‹Jôæo—í%¯lü¯xu;ºwæ8-²V]¯×yªa>€ú™©7³Â¤Ïîöç ½úe§‡j^ªÌ*ƒðüÃY[W¬¦<DèÓ¬À¨ån-¿wɦh;Zçr2½§j{Vhõ ?ð?mŽƒ)=÷™m%JÓ0æW^âך3ªV{*÷€ë6(\œúbSdC»pQ„õÍÊÁM„¨ìFÜy”-å™'Ï„Û<‘d‚bâŠÿf:³â/'úh3«´eï^•h¨²pèé=âvËc¦ü1on+w^WÁ÷T½£žx40±è÷»0ˆôÌ¢Å,R¶ÍÝ­èÆ¹Ze!u#&2ù×=§G*Hhªðƒ.³¯yÓxý{~³+|b¡ÑS>r{5ÍÅ¢ùÊkˆ•u°jÊ—u{¦]LuF@hîä®138èî#·ÐœÚ„åì¯uPœ–Ìíê/<[y䃮¾µ¯>iàÌÉP`ûBâo°bM¶3¯ <ìþlý˜ý:…/ÙžüÖñ¨¡uu¶ù_óÇÇÏ·yZÃ<Ÿ€YoFáÉ0‚«.z·9P¯yxxÏö³é¢ÿÔ³¥¿ì«?‚¥ž}+n…ˆg·»4Z¨Ôí§†Ï½Ô¾Ék•ÕÎáèÝ­“ºúï)òNªN¯óZ©`+ñ£‡¾¸¼ù¤«héÜòºµæ…a§|3oyÙ&¸¼b‚s¥]¥[—FdÝŸŠÉÕÖÿnBŠšJïÙU¸7Ú—î^¡S¼Nyuz(ºŒfô‚Í<ŸÿR¢ šâú²·í麆ã d­ÐÇî¯9¹ú½òÎóÅËö;ƒ›€‚¨¼­5 [ûNд±ãìˆl–Kä1Lo‡OØ “„ñ ÎqïÜï5gŸäR¼Uçì¾óÈ(¡Q€°õ„³+Ý zÊœ¥;®¸²ÊY£>Þu›&9КüºQ=žçC^Ðò¾Å¾c2éȧ|FŠiª2jÖ=iäÚ)ÕõM\3C}‚ÆhSl#ÏV`2ûƒ0W^ö &–ZÐ0`fívu÷£±ê/må•]]„jÞÚ,û# ¹—{]Å5g®5}ƒèÕtæ:ŽÞumÛ Ž¼{#ûÞÏ<ÆÐœÚ•–vœóÓ~‡Þ—/¹×f¯,  |÷yñR©% §´èmußY}ˆ¾ëÛT¶g,†ôCÜrÔÑ£±â”9ÉRεR†o)¥…¯¨›¥Ùd“©œˆ¼ÅYÌ×—F¡{]öž¥3K´”ù,`"VâµBÍ{³¬ ºjñ×}Ö’µ+,AY›ÃnTV/'DQ=A§ Ús¯6»ºÜèÐW^Ê[d!VºWŸ¾Ïõé!œ§éµ‹.a×3v@ý½2!Ùb°„ù›Í/¯yDÎ{\ؾ¨t!/nÍrb~¾Y†©Ú‡ÓkkfÓ®Ë[î*šjº»¡Õ›ºó‡5ã¢î‰ÖÒ ôó¥;xõrvnÃ[Ýv¼0¾[ªMq¡š~¥O‡{×]áJ¡º_w€õ[¦\µêðð~r½]÷­>P½î«B–­+®j /'b w(æ-1wNºÑîàêí|¢îB¡À';M_ Gè´ÿ•f?_š§û*zÿ~j–Ûï3`Ùox²£yaÞ) áæ¿,ÚíÝMþù—ûôf6ÃzSNVØÐýIpÑæÕW’ÃéÕQUsÙÛˆ¤ ͬŸžÇ­;Þg–¬s1Ì@!tlY IrÕ⳺P"â\kÈ_¨ÚïYWÀÑô•Ö= Hrµz¸;÷S@p÷±{9+XŒÍl_%yG¾•ÔÛ™‹µå‚#ïr¥u}ï^5«¨=Øk»­ß#„͹-dë@mJêwÃj1Ê"¸Ñ:ܬ¨ÑÎÅÜ·³C³)*• H‹QY|;‡»ÇoŒAÂö²VDßm ªex ¼z±-™›î¹ïwšßz¨A†T¢V¤ŸÁ>­|﨔Á»Û䘳nQR¾R÷ù÷ÕUþJí=ü÷¿'å_Ûü²CþõdË·­ aªk~£¢Ä©¥I4cêÙ)O{Œl^«õÎÀ–Ÿd—Á.¶kOï¨û rO 1ÓS_®)Ã9ޝÙ&ñ]nxNÚËmß©fÊn­®çÎu{ÔolhïATá` 3÷§³­%™“AJr˜„:´©ÙeÈ ´èñ\z¤»/K0åíÝÍZë„WÆûZg¥Lfwnöîfµ—M;§1v: #²QŠž&ÿ¿S¡î±’fñðÛ¬ V,ÔJwZM-Êżó:åG…®¥¥·®Ä^‹¢Ð¸ÂÚÆî¥Û{Þ«…&ÿ¿½’“ýŠé'¨ç¸SÚ6ð÷*9ò÷t~å_­ÛT¯³¦Ì;úîgäëöwøó·à)1úÃë=y¥¥”"ØiâiΗ=ï>J+y¿eœzúÓ^™•rŽîeϳ,øš®ÂSpîÇÉ,Nš•1ï,ÁAûy¨¹ÕÞ†§·"¬ø‚§Ý«/ È=Ûu)¥JuÕ£¦¼¢ÙÏêÞuã6d]Ëükü»¿%Êô}% ö_WGk]F½XžÕõi,h÷PxÅpð¥¸ã4^vÖenÙÅ{ÖQ·O^h ÑÄ»@e¬ZV\§B§@aË==Y×ó>^¦÷ÚÌt⨉G†uL^59`WËkfÈû s¥³+léë>á‹¥r¾½Û.ëÐTa$öû=¶¦¹X¶WzÄeõÇzZ0N}Ï;åÊ•ª˜¦¢ ® 7(ò¬ºzBDŽÛúVå;šk¯)²-¼³ÅY¦iᆎ^…Æ;ò¸ik·å“×}Ù[©Íò¨~¯p÷¨_°ùxúºÞˆŠ&æRÝÜ×f–ó $Ÿ 2.‡$¶ìM° ‘Âû›³‹Y+JUyÕO/ ‘ËBNô·Õ¸öÓtU¬RãKsìšq²Ó~S¯˜÷‡§€›sn߬]&†=wÜßj©¹°®»[Ç…"ž§3,JÆù›Ö¦oj*h-­aœ×V…Õ¬¸®ÔÞ}\ýîÒêò»ë]í2òÅH¾PÊÝ\:ûEsH´÷TÑ‘§£J^v«2S2¢Ú78ºՎ­U¯ŒUÙ$»vPfÓ•í¾^WSoÓE±ŒRgÉ ¡+/UI”:GÙXÚê}.£’!ª‡Á¦T­Ä–Dúj‡Wb‡:Õ€K‚h.0t"‚téb¬.‡s/yÑ­±f®ï¤–%ðQ7ã•Ì0ÕyVÒöDÈ æj!E*ªþ¯°þýYiç üÛþÝ4ÿWr/ïðŸ;Í/»w%hÚ†Þ@œ]ø»ìÒI[¨¼¿ó~Ê÷ìýV+£g®ÆÈUºCSa3èH&½Û#T®óë—‰W`C*q«¡BqCƒOJ[w[ãé^—Þ÷Ç÷9&HW3ùKep¬ôÇYíÛxÃÎ3Y¶òQü¤ioî÷¢tÒËῪ®šïTy~µº+¶kܧê&ÿ>²9­ê[ÁK¶ÕÝ~¬ø;ne Ç—áp£DÃn>—y)îDWZõ7Wžžz]傈õ>xånv?ØvT”Î÷ê^矕^·ÚTþOÛð´ý¾9äF{ã,kÚ×P‰+×Ä_ú™¦ýs)[`rß^¡J… ý¾¤o¹ô^õ5YÒ1½¢·­u/íÓH÷ø£éZ¯Ö_>Êš.—çZù¸{p¯-°j"  µîÃ/ ÎB—`uÕ7;ŒCT‚™—…NM‡·'õíå‘Á¯<¹;¨öürÏ·žíÑÍ Ò¥|™µ×€=C>òÀÖà“lía¦†,Áü§†½ÏñÞ£~—‘F·n¿r^¹®“ïCýî¦+¬@îã=¥œò§‰q¬ KzP;™m!(ìÞR »ßÞäç]Œ;|â8¢ÉÑnIáíò÷´S½ò¦™/tÑP50 ÉH<@/€å¿¹ÌÅɇ²ÎÄ. ƒ×YÅß™¡”䋯µ‡ƒ¨°QX<5÷m*š¨ÔØŽÍ®ŽêLÊ  |î«°ºDwÃÚäÚÀ³\ ½¥R–cí®Ú/cæk)åû^ –›–ó/¥{§8#8#±IR³Ç J…YóÍ*KÊ79,Ú{ËQåB¯\ÏxnµN+™PçD3w-о"U–åšö#ËÊ'’í)™Ú½B`›ƒÇ«·Õ=çHz/)Æ`œoåk¬¨p Åy+Ü¥%UsÞu„Ú4H àó§½³kor>þÞýÞ'ߪnoá„z ÷cLN[CûD”¼ëʽ"Ö-TýudwB“‚<ëx]NïøoÕé7;~ôÍcy³ J5t´R—˜°LêX¤WÖ¬ÖˆhпœÃsž¾ÕY]¼O )ŒÎZÐta©EÖ«š˜¹,a©[tÓ’¸uq æ›nõÉgÂ5ó‘®ïõŽzýèTjÅg«³#QÒR!—?ÃO÷KÞšY;~°gŸð»ŽÑ¨é1nìØ¯w×opí[qQÜÀÓ´!\ “3E×Y;º±j<•RÄq­¿´‰”e=»tæ¡îœ{¶[µ[nè·á„å§^KÏ»Sé‹ÊÑ7†åð¯yÄ‚Ø)WZ¼ ÛwHnnuÌ[H·@ÌûxfÉÄñÈjø5-ѾwbÜAI®—Tì“x±…QPñS¸RÖ›¿ÕÞ½·Ï‡Ÿû{)Ø9øz¯\ð‚׮̕mÍœµ!-£³n>O˜¾Éz%¦nÓ<‚cRYÉ\NÐçÒ1IíeöæI0e ÔC)µ8q ‰¼’±óW”ð,kd°z“È­×jt³õŠÊ™üÜÁú/ß¼†¨é ƒôñ©Ptݹ¯xšyWpÈy7‰Beí¼6»Ã/|=~ WŽŸGžäšÝâþðßd•€°%ùUŠdg—“½`âp—6­Óqí`»…ªÊÛN!pD¥ˆñ–"Ò5ÝpåL&ƒ{îùû®ƒtùó‰<ë×{–+M/yö­é%™·ƒ|ëÛë–_ŽÑí¹wC›L&£ciq§AxàÈ38+gC7œ·Ý·®.B1‡()b½XÕ®Cíú}Ý¡öæHÇÇ]¼ïw쥱AÛ¯„R÷‰W[© %3Ç ±‘ÙãjÜs5æZy4í>u5Ù›”85¥žWtÇ OM¡™cnQ-ܶ Þ¸¦§KöÕº4RÜKÃνJp¬å¶ãVv—W]…ÂgçÖè¬Ô=/ÇuꦪÍëÈyb°ÁÚ*5lÆUó3ËÖÓXÊBÙ±epr÷:N½Çϼõ\÷j››Iô è­ev"UózºÄvøùµW'•qÛ oãäY´·ô#Oi¬(–Qý<îõО³¡ãfqfvu`ÿo{c¾ß[{ &!Ø+º•²{;ñ¯q‚:·"Q6²Êß–ê #yH*å+HŸ5ìUïo Ts¯,d}=æþñʦwµ{µò®ŽUõx¬Ã™2'~¸TlŠõ£;§Q÷ªíïz;ä{€–/ØÙñnú­ªÅ—¾€+€˜$½˜2ô] ‡ÎQ{½áBG®;gŒ²vóý«ß™ýøb¯Ja³WWî ÓPì~+y D ;»"ëýP;î/]Ù¦žêÛ6I=Ëõ5žªö;~@Rì±mn'’¿!Ÿ«Ÿ]•Ž´£t©ÐÞ†|oDÛ#^SÛ½Ý=èÕîHmªuÚ¦:ï—`lš;mfö2UØšOºPå•á.ýS=Ý~Àéù-Üñƒë:$ÔökÇP†ìa¶ô³N{9ô@Õ­B¥^ÚÉtB¶Öªž†ÐÏ;oÝeoMOƦ ­îW€Ôƒ2’îtÜv,pÀÞMKr)žàˆñ¯iQpÞá„Ç{ˆˆ¶õ“îQp¤¾{ÈÏ+|Ò8 U´Î—Ø”c}Xïâ»6|÷r| å¡é$¼¬æ ÜÄ=;Ûž‹óñ½¡zèz7©JÂWƒö9Ü[À´y{’õ ±Û¾7;6ù!ûÖõ ¨ÕžÂ6 XúíJœá}¬ìÛÛ}H×f¦lñùê¾'+€U‹M+ïŠ:ìRj7y3†WM®Ý¤ê26ºm+äts¹fålDqMt;*öè𻲥ËòùŸHO¾ÖjìüJœ51Ô: z)θÑìí[×o–-YD\aRËä–³.¯bɘ×P|šqS@¤ødªEŠªÏ*¢8©‰¤kVXº3rÕ4HþmÒ•„òU¡Qã³µ‰Möuíû¶*•qŠ·mjîé4)Þ”LHÖŒÉëÜë]ì>õYæBñ‡zGzóÅyŸ-§5*ÒAúìZ¾è2·VɳvÛ9¡ãΰfŒ×tùu mŒA¹¶‚"ÚíyòoŒlªyµžò|ïŸnpÐfãÓé4ô¼WI½ðîëßf'”÷%d‡¬uE9÷þYŸ¯óøw–,ý¯CUušR·NF¯pÔ¯\ÿuH«3ú“dWíÕ˜ÿ@Yµ÷£07˜½I> ƒÙ+xzÛ™ù)£Ej°Ö`Õ7[P/mó°’ÎÑwØ‚,?{¾†&³8Ük}ÀLïµ}‰¹yQ¼ÁuÚšvpò‘nòGA}^)Ý÷¦“¾^ÿJü˜¿ÁY >Ÿ¿808ó{ž–#}DßUœæqŸbµòB÷¶°Îpeõ`òm@é`–æâžÈ:ØÏÏw<«ÛuYSº‚G6¼tyÂë«­É!(pC"iõù  éÓtéc±Œ†wcy[2ȉ9;f@_&€7ÐX…_shæ'¼êï³+(–d„J='Ã’Åf^m¬¥b2›åd ›'³©0¬¼7ü­›=šQ,…ÙPFfÔ#n5¤xššîÚ¹S'=^§jð¾ ¯×Ëç•Ôÿc®ï¥71×­K6H¦X©w]›"–¹Næ‚;î WJºN„6n±ZûwíÍ—Ì…GcŲ2+o6MÁŽvÖÓ‹Z^qùzòâ­kÃÞ±C– 2da[éž –ØŸš±~f±g^ªÁ¾÷±A£· ¾T!K×vÆÍ¶Ûå´Œ'6,7Ÿl M¬ooãCO%l„,(ŠuJ™ÄÉ[B¨ñr Ã÷½ßlÓêcYt¨[¼¡šåÌ‘ÊbñJmòbμíƒiÙvqoq®aªÞMqÊa9Œ‘’¯mU¨·ñ^ð‹©Ï<«َEÝÔ íeoõ|Mvo®˜gL‰Úð”?ZÇ×N +ÂÅŠ³žÏRSS®âî?~¯>°=]_§Ö¸,ñ±6O­×ã´¨¦Œ&ãC¦÷F+Û0ÓÉŸå=v*b^¢xJ-/ Waüo:ÿl½¨úœ÷m(H(ö·€`·[<¹7+] U<ë0ËÔlÛ¬«Ç†¿Sá¾ì{¼|tê*½V½]5¥{~]bVó÷ËÕy²³÷RÌ¿2–1_¿võsÙÉ]u0•ä§¥ä84öBâ{­Xú²¡°Â¤um0ômµú†.Öz~®¼öH¨ÿ^»ó=É…¾^Êy67¯«zp ¯´~;écÂúyWCÙ:–dì»Y»~e¬ÉÒ§líõêÇ_ ¯ß«ŽÞ~Ö$S?m=x‚8ÜqOx¨bâ=T)áÞ³¶ÎÝÙýùÒ·‘Öh¾PÝf[N†AB~:]>lÿo÷ï~1{¯õmþíSý\É\v§®Èu•αfרAšR™F§—‚å3Ò[á»Ý<3“âKÁõm¯k|ÈX¸ÊöJCµÚg4ò˜‰:› ±°R¿˜^Ú˜ß9’yµØH—wHÁ=«6s)5*~¡E—|G»õÑR®˜*ӻ޽¦Ê«RÖÎXPmÞ'‰_áž©Äs{*rë—í;]mÏ[œsŽ;†²vö¬ÜP7i¶qà©ï€Ãëå¯ÓÈWöì“Ü(!"#-ßVÖ{º»8ôse;žR›bÙÁR¼+B ÃçÛo+*Gº×džÇÜ0àÏÞõ·žNcÖæ2(s°ûÝç­É!(rw+Ø©ÌÁ.£€²÷÷ó¯wcü—_ææ~ÿ]nìfqåÿuf5Œ~Š¢ú°Ô÷ˆ;¡Çix7¦…yxÖÁ¹4–_sA-uy˜¤e»þ¨»×~ÛŽ”|`Óç1VÌ­ŒPtwL<ƒ´ƒ8“CM3Ç`Wnó,'ØWhg:ò_ÖFþ@K»³˜ h×ìy[Ù;’õO³+Úf—Ò\oJ|ðß‹>—ö6“íÄòâÝ~Ëâ«Mk]ÛtL\ú“¬/$}j†‹¹]‹¹pç[{XP©xãöÚæQóͯÜìto^ð~ËZêÃú£lÇáXÕ‡–Y¤V0ë×&œ<ï¢ATÉB×L˜;9öÒwG h[§Ð,üÁ7-¶v¦0•+Ñ])B`5ú²Paþؽ[%Úh0,ú âó}iؼ7ÉhÈ{v[ºƒx±ÕÆ KƲ´+£@é?· y:Íú×b«b½[Éó‘qnËT=®gF5Ü1ãºÂþR¡|/%Üѳ0N«b3¿ˆ’®µ”Ùù÷Ìåö$õuî­ 5C(4ò4€Àu£ÔÂÞËêÎwK«to)­ÅxÁÖ°§³Ÿ,‚L5ƒz’èŒW_ݽë})V{HíÚ™R”\ŽðßUâß“S3EÞÀŸ6Š|â}\x2¦ú\ÞÂ.r6ñQNŽš|q6P~õÐC†í Ï=W·=וâ\ôÛ—k¨m-,ƒÑz$6òN4Û4564W>‹¨Ó|7fX+·3{«%Þ:þ©¼e¼¯V¡±ê¿ÆÙ*Å­êì‘Ã;uÒFiwe{B`*‡ì̽lÖ#Œ• Ç‹"u7ž©ìSª;9Øéu`ùÇÐl¿IN®œ— ™ÜÎ6ØîZ[@}·¹ÔX[Ž¥I•yVè:ËÏSùl¾¦éw–þü’µ’'[³ÕdÔ&-}be] kI„Ojˆ7¼ HÙ¿xžX{µóäçSGÌŸ68s\gÆ^pìÕv⤨ Úç­çBħ'=›Å[ôYZè»~©›˜I™šVý¬ý©Â-;hUÔsÙÞbåMo™©¤¬u㾟w’ß ®µ«@üz(xÂü³æì”å{û¥nyËÄRůÙy»þª‚ðñ‚t)øÿžc21©Gú,z~˜q §ì?ç»™Kú Þ$ÖŒuä¯áœÙâÄ„ìWw›:…èBâWú´Ï`}|=÷2q:Ùy‡ÄLS.¥cúF ÜwöÝ&½E 7ÆÏ7ß¿lx%]Ýo–^WîÖ·ÍÏQ.#‰ø7:ëkJÍ÷”f3×7 t}«Ó½í«ð¦†/%ï.é×An^ŠÝºôŽV{F³c—åþW<öªÎG²À÷±;—œÈ(¸s¥!WvW:dÃʬEµ9ÊÒ¼•/=÷^5z÷ëÈbŽêj›ëËÉadÃògþ¯ï«z~¶?i¹~Xÿ ©ó˜¿3™\µóD‘ïQ­ ˜Èoõ~^Ÿ»WïyA¤êÿĨ_Iun³èMìC¯.§êý^Žu1~ýž™?e¦`$ãÉCËKl«ïŸY´û‚Æ ›÷RVpÛn¢,½R¦mÊâå ¯}÷iØýIvêññ¢{N€¦Ôçt7øÏ¼<§0ì…¯j׬mô«Œ½‹¡¥s‚ÃMhË*#MN¨®=9EhIž[wìñ²€;çžļc ›œßgHõÊ:JWº–˜áÓÁ.Zâ­zt½ÊÀÊ«ºaì'ž•óÑuÙÒÅ ‰<;Žñé‡vÂØèk//îˆh+æø9î£}Ý¥˜ ¢“¸[EZŸ=5’[h.»¦xUŒ^ÿ)šPr£W,Z»üsÅÐtfÐH \ÅL½°2­Ó Û¹ua0(BÕ ›”\|{š¿LöÓ§‘U¶¢²&™Øî]Û§êÔ³†qô]•ÊqA][®?«®ò{=E¦p_úýCõÜ$ûk)ZX;ïÇŠï0V AQUî4î¥ÄºÇ]`ýBÛü*ñ[=0‡ì–°oèê¿d{vrø¾Ï3Jg¯=é›êH¡gý Ç^öW”êCÒô¶2YüüºÊ´/ýi?¯;;Rqƒ_©òŠÀB¤3Vga{ o¬,ë?­2+÷ïÖeü êGs‰Ë6Æh«¨ ¿rÉgð?¬©–„u?RÔ X‰£VœüÙ¨Àªm`ÕW~]Þõ/s³ç«4·™´Ïv¬ºz$Gº¸ÓÙô!6c£Š·f‹¦vmIu„­‚#©•l—a㬼‹F5a¸÷Ûé¾EŒ¹~Ì¿{4Á܉î¬|ò_=Ì͘;"gàíneÒ}Kº¸lEM[ÍaìÏ>Ò-ä=¾ÅjêÑ]éd¦‰á[u ž.ËÊG=§Ó`J$éR€!ë÷W«o=îëG,©^f¯jµ'_räyEcÎwõ{OÝžöäðw:œ w-`ç6£:©Ö‹t¦ÕàßïÞýƒ`Ý~7å€fS?€õ•”p`„µ–!£ÎVFó¸V9µ”{¸ÂN—Â)LÓ‚“cõf'|ê…û„;t;U0ó,Gfêèèò±µª'ì~õïÖ¥äwàú‚Ux=žZ}Co)c1?m=púzX=Úfîhu õ7JÐÐ+”y¢ë7Ì^¾.ÅŽ£\^­KK÷rõóî§ì*Ì¿ *oM•¢´`£ÍvR+©ß`uíõi†´ReÎxû{ÓOØž–yxœ+Üúo!°Ñš5xÕÞ Ó ê‚¢EÑõ'™×¸1n ß÷7sÃå=Ùì2‡¡¦,)ÔsòÒšÙËa K&õK«ÍœGhî·öõѬÁâs§‚­])uªæÅ[7³Ü Z¹š·KGðÁ#ѹS\ó¿ P(§Næ¼è,D߆£KÈ 1 Ǧ‰Ãˆ›Â/—¹BຕÕDç§Ü0®Ï ¾”.þöЕ”ñÏ–¤°''qÑs²Õn¹®F+y]—R¢©%É(¾ÖV®]x™„ó»73ê3Û¬[«Æ•û1R_SVø»¶µ1—z÷® uÅOÉÛkwç[g¯G«ºÜ.ÙoW*’Z¬µ@Çno¤PqŽø¬4ת r°øñ<¯®aXw;:ò½~Jü>[qâdéÓÕ´û- O*ïL´âåyB¹â•fÓSÞ>²œ‚üÚ­¿í?o&߆ú^A²—CÑt®„³œ,¬ƒ›–xa/SòÞãcoÞSÒÆ{!WX¹p³>”í³˺ ºxY¼pÔsTT¶ÈØùŠß¦_Ä^=Šboq‹÷[öV uy¾Y»±[~*“µ/_ú¯DYœM^õ#YG[ÝòMAËl\’ØjìÞ[¶œ\•Öf‡÷1Ì's³¾r¬K¢¢½ñ*ç Õ†Èé8ÛËä t„¡™AöyÑçxR4;Ùzñ±0}â[å¿emï‘8¼- ˜ »M¢óBÓÛs'6^²8]iTùØø3p–lªÌmÇÆ­n¥aÐqî:ÕÃï²1ëQg»Ç70u*½~ç»MVß—hó ±µ }7ÞĹ¾mýÔàþSy ¶½£A÷ºØ™t?‘x{Ÿ7Ç®Z£åûúnÿ~<;ß< ýüòê›­îû—AIqˆ%¹Âøó‰ÿUOubMÅwU{㬻°)î73w=‹+ß½ùþŸ¿gw²0t¬&v¾jû‰?»9˵Ö}ñ÷á“”X/¿VéƒE\»üò³mò²/]ø›õã®BÕ3ÂÍ,ñ*ïá5c]•ö‡å×Y;’ ÙÇs©wï©{¨>®azx‹öº›+À {g•ºs_Þ/¾Üý~Ðv$=Y=Ÿ¿«žÏϸƒà°îWõuÎ뚟7‡IÀ™ì2$ëÃ}SùòŸÊ0n4Òä§é`75lz§p«É×Gwj]ÊwVm"pæ›4Ãqâ·MÌÞŽ&âFoBæítß}÷õU{·{4%ú£´é5âºÍ*å~ù²¼üéV¯A´0—ì±í§6“u£¹ï_>:Q·qÚ‚çê}ZuKàÖà<”õuËuÝ)}†lCD QìÄÏVÒÅ—'oMîS›mÄÈhN¬Åu“vWª¿.¯ËöëüÞÔr'„EØ]!?[­ä×4Vsî;ú±ßªg§졳ˆç2Ø*åÔš¡Ü.AyŠH£Wy»u CƒðÔ»-QoÕãîQUö>!ã%îEJ°w·Ä÷W{ņ3"¶snŠ©ÅKù/-ÎQ!O,õ+Ëæp®K«àó'7åžÅîÑÏ9€Ÿ©bÝ­®kž€€¾«}ÎÙ)¢gs›RÖèÒ'c}ì'’¡–æð{û{ÄŒåã}NÛx†û½=~Sp1ÓÚ5ýO¿ ý‘ŠÞ !Ãì·dü­¢|·gJvócý>éo“ËÑÍàÅßœð îÒÏmx/TcÙJoKÕ íK­CIs1_Ø>:jãðö솼Ô`c_³ÁþðƲÌ*šÏ;«Ç°ŠÿF-"]"½Â˜Ñ ÚéûÉoí¾÷´çãtª¡½ž:Š2”K/r×®[ú—K&u5yï`6»§à/ѧ=,lÅé\o‚ívüôÜ»ãÆ¬=ÐÒïH‚~v?xÀ¯Ót±F{Fîu]¨Œ¾;'TîÀmÞÚÜzé.5‹œáéï{;}èèxœ;‹_uûÝsçfð¡´’¶æÔo)¼Ñ–ôДj*Æ<†pë= Ñ(á±B³Çv¶ ¹C© ›3Q°Ô¡íô#Õµžµ¾½žØo¼½At¬µÕO­ÑOm÷<=‡[“q`§ž^vºÏ…Ü/¯È–kÔr¬ŽîÑÚêÐq]ÍR¹ž å×[UÄQr·T5¡•0#2.ëV5r»æ©¬k×Äû¥p>Ê÷ži÷{iuˆò›ñ{ÌBJå~ã~·±+O/]<3Žà¬Æ¦‘½¥¿u,iææj„IÚ9¾•Ï­sm‰é׳׸ÎBi¯"™•–“ö'®ÙÕ(maž´ç³”Ϙ­T„ºÚžÉ”Om6DÜÆZti.L:…åã=€ b•]>( ®û ¿÷WüŠ]Ÿ‹Tk*½C÷¿O)o&?œâ*kGö(uÙý«H`ÙtQ‚W•-O@×d¼ˆfc°C|Þ7W»¨?0{dYç̵É2ãpÁäU ½*•²¬š«ï!&V³·jëV¯ŠÄŠVSÄ×.ÿJµªï{‡ó¿ïáæïÜF'*F7ø4ðÌáNÝ5fJ¢{ÂôV ã·œŸA–íò”U¼´`à*\ÜÕ¥ýžçµ˜{mS{X5×»}΄ò\VW?K~êδUXX‰§ëŸ?pAo w+»6Á±<íÜ–¼oêÃË;ŸX#Ú.dñ êZîEøP>æ8ùökˆê©Ké½C¸#éí§ç|¨ªžùf9\Õ‹Ý<úϼí¶ûz{·]Y®ÕÛ/U~1Z¬Wýè-é!xÞP ãå…¯q¼Êý{@Þ¿»ô~ÏÞb·ñö3Å\òðòP7yŠúnýs^P7ƒª;ý™~ºobJå5 ÒÖ¯ˆÇ™J>R9ßA×-«/;b<·{XúH.²ä’ÖÇK–ó˜°$Ý^Ýûß]lRûPã¾JާËoYA˜±!Ã=)‰^ìS¸2÷C‡È³š¼«©©|•uÕe9î.Vî[µÏ²‹¤ÏçCëÎ>Óä{¸sÉÝËaVý–¥ÖG;á@B=áºTÙ=à½GÛt%†ñçmu7pAu›¢…J(0ÙVk±£†*Et(En£ zey/G„bÛ¡¹{c;vV3î•wÄ·Õ«i9«„n–ÊÎä #Ýí¾fÛ¨q½vÛ7ŒýÇ«Ñ&ùŒÍí6ðÒÓºÇi^3•ñ³×(<¥tö6f§sÕ0¼«oÁ9s{5õðTÔè›[C~í6Ljéų c•%(€;jÃÊPZt”ÊBsËÉ„rÿ(þ[ܲò£ÂßÓóÎb ¼kr~Ä8ÕwŠuøÉÜÇkø2îëiïßÓúAç$W3);#újëHÓ¡ùéý_¨ÊÑ;¿r¢Gö¶$¼_Ö릹ö¦0¯˜íð(µ”‘g+Âpƒ°•åžÐȾ¾mÙmZøóšìl˜:émż· ¦––|e^œ"ÀÃ7]òÛ‡l ž#´­Ã9§(É.·vµ€ÃY­eó øtÏx9´<Ï»}¯çîëx!Z#ĪO(ê{5zS…^zaNéèåKfVCæú¼‹¿kB<=š- ß ½ßõ,©,òµ”»€ŠQQnLt¼ÂÍé·ª ¢íê/µÔ°¡k%Õ— À/–W!GÅžN±8©É”Ä£Ù7>7ÓÓÞÝAèÏyû×ÉØžëw¤›á]Êû}¾™÷…ý·ÕcÕÛ:ÌK;:¯ÏYë® ÓÃ].K—fç«ËÝ}\7ú£¿+ã¶ËV+ðõ³x¨Š1fcbð´¿Û„Ñ[ŸŠSX H¯W:ÎÙ «µªåâzó`QYê”Õó¨ìeG¢ÓY²ZJ**¶Ê4pÊ g#€¬ÞÔ)=Ë:FOŒ*9Ò¥NˇE‘QYŸ¶E2|Û„cêïÜÃs ÖsžÃÜÐÀ+9Ÿ‡EðsÈay BŽZQ\ÑæRÚí T¬í-®î³Ò’O'Rº‹Ù‡Vkæ%¦Å ömN§”)òwšÞ×QV v»7?Øý5½òîônx"{¢–ɈvP õñyX{…N׸ÄnNÝÍDB/ºdë„<õVgÝ$s‹æSªé—Ç3H-Ú£·YίUêµã—|ó*CÈ -»g4µ»š”R;ÙwÌ%RÚoFùoW@Ç]ÚÄѲzí;ªó3k©,G£Â«&dÝëÿxž´œð×^ 9—|Ås;„åŠ5ÈrÝ®6WHuR`ã·Y¡]É4;'»»ë+†'Ð{Âf‹2usè¸î^vß ãt樆¯ÙÖšêÞå¯v¸áÑKië9Ns(+zÑÛw@åf°Š¹uª.ÙBÈ‘O¶Ø™VîéÒú ˆ_×} β ;Ù¤ÛÉB1ç}Êwk×b²›\òñ áci4¾†Q4vU°ÒùÞØ—ðƒÐÅl$TÛúš¸Md^§ì~wÀü_þÇ÷¿ƒîyopÿ͘о~v‹‘<ß°å¶ëÙê;Ëczá6šNLKÑðR"q·¾Ì×J‘SX·9ÓV!çdb˜våîQû|Û—¤8’Ÿ%‹n-²-Ï|£¤v¯„T} Pœ`æEb’ä%<´&£Eïš«æEÕ|þs™¢iª'M¨øyÝÏ æUÏpç=.rÛs—GŸ‰TîÔç¥ÅdK/‘Õ‡lÑÛ6öÓF#¤ž÷ž¡a£u©´Ië0†‰Ÿ¥£¦i@CHz 1G ø$HˆÅ&8ˆ‚ )1㉃&DÒQ‰ (àyBc‚ƒQ© AæI‹`ôªË(?OsøùŠU¨hAD×3Ge‚*w>d£F‰{+s™æ ¤‡P¹™ º°»kG«kլ߷ð¿$ Æ ë˜Ü†è»“÷¯å~¦¶éóÌ}Ý+Î¥ñ}]ì¡^ñßgRww@tÕV&ç—ËשÜ÷™Ú÷Ø=”áïj륻Õj¯ذÑ@ö[­<® }låFÍ&ÈÕǧÀ¼ ÑV³‰)ÅòëÊTPctÇ]¤»ÅnwûßÄ×UÒVÆÀ/nݺÏÏ•¾ZÇ]-Ú¨zÁ§¡õãK÷vZsº×Þ,õ-*+UÜ;‹³7Vä~÷òÀ²^,ݘC ¯f°ëGî{7)p 9vožmnu<‹)PíeôéË¿Z劗½§Žm#2Põ¥rìqZ7Úª±e‰µg<± ²ÙŠ¢uîƒ<ýé|0üµPSE¯’Gmö#[×JÇö]{p=ïJ¶¢óözo»Ü6>Ò–K“Õ”øhdv ¡r?ì¹8Øôþìü® üè`ÏÍ¥]\ú—µ×J8úÂ÷¥ww.±‡xÊw`=KÇW„Ÿ¦¶˜º^G~KŠ–Êú¾¨HäøHB§tîØõUö]\™2e¢¼öÿ¤U¤ ‹ÚîôKÍæðŸ§¹ïrøDªóÙá+‰B½ØYDgÞwW¹Ô]º˜ûo#XfR¾ÇÝMÛ±=²öÏ•þcš÷ïu¸ÎЇÜuí7².Ö‡_;{ZñXyògö{'ƒÄß ÏòÝ( ÝAÂnª¾™nÌ ú…¼Ýý{Ú^kH«¿ I…j•gïs#Ç;•_½³Y÷–ñš‘6J£Ð¬÷‘yC;<\è÷7wÒ¦uŒ”]Ç|2<Î¥]­ÝÔâŸuîóÂe‹(Wœ·8g­vÚX%ek+ê3ïËu®ZŠ‚ñÙú–ì{•~ïÔÁbÿi@æþÑ$X"”j—Wï†G™{têPñU*:°)j±‡tTw¦-´Ö­¾û,_Y©vÜ¡…åITo¥œÎsÍ"]Ôw…CM)ž‚§wfW&"««¨Ò+¹ïœ¤ýÈKWÏi™HЩ£6î¼6è{ÄûÆ{PgätE+¹·»ïTÇ–®_KYƒcÊUeÃh#wÕé:»YkÙÞÎñ|÷ÐC®à¾åÀË¥™Ç}&ÎŽ±º0]ºPÊî-ëÔÕ 5ŽËHÍʸ¡¾Ø†)™3Wu}ƒ.›˜'v†Ñ¼¥§”ÝΔܤnrÂˆÖ `ÑÍ\Á-ð8Ý;0âgÚ›¹˜òo+=¥ëëf-%Pu¹›É"o­r¢¾·šWê÷m:±2Ä ‡Ÿà+}œiþ×å;ÚÆÇçYg—,ü¥Ã:±.À)_º®óÊ»E- ©¼lwÐ{ï÷×RÑv3ÜÕ{-‹Ñ2Zý³–.«XØ]Üíìq$)mÝû¶9Y´ÄÅOC3zbØIº³“[£Ù8çRJ»×üˆ0p'Þv"™ø™Ÿ¶È3nš¸á=zæ‹ €.ÞÅ€ëWc9)óÀœh¡ÛœYã­ŠDq ]9B-q÷]pz9‰P§Ê‹»ãݺ— •“zìvòømG-š.Þtñ•å2†ùÏ«ô±Éô†ú¥¿(²n l"ºvƒ|CǦéÕÇÖ{¤î8—7`ðÒŒ«XN]R­Dg€ñ¢¶?!B:OåãO;q›ÎìV³¤¯Z^ÔFG&P‡}0zŽ. }©Š~nï§;™©U¯g—9êjñJP+­ßm8~=çc«O›ìÊÒ+É ¬_yéÞh&ãÑGÐÖäÒQWJ2ùeó[kçlzvýäòµÍ$ú­”©KÌ’]ŒöìyÔ÷ïêêþ¯Å‹¶ö9_¼Aa kûú`‚R#ùuy2Š ‹hÝSROo‚³–/tf`óœ*Gun‹r_ <ûºýê~õþ£‘6=º3{ïŦaÇwÔÏ'HÞ—ÒE ¸½q«üåxu¯º « _{ÍoMÐ÷ÃÞ¨©w¯ßÙ2îNqb nöùÏ‚åÀ¾½ÓÃÈëp”+´ZèîïòÏs‡+ÒÍ‘4»®‰½—{ç°¨•™ß!¿Jä¨r³ÖkS¬ZG»+‡7m\`P¤Hí '^M¯p½4ëµNPÓ'@²™Òñ`äÏ›±êÝ®K³œ†ðzò»cNC§mn¹ÞO¬ÂWWk2ĵŸÚÓ³>Ì™Ô=øK¼% H¡û…þfð9qà!Ìfa~'וéî¯c~¼á]‚Åyç§vÇä¡ip‹ç„`O.½³/ó¼Í"J ªìïf"w,k5Y,å;emñgБ 㵈Θ®×9Ÿfx0 GÐt/MûÉæ ÖV*“D¯-Lf\s{µÈji”^äû=Êå+Ýʳ•zq¦rÝéyžRr‹Ñß &¼}aѤEÓ¤õëÚ»´Æ»+rÇKMË«YšùJáµ_Úžv <<:‚êë‘7 y©ÅLÍC¿M~Ìõ®›+'³T‘€¦¶7‘Ì£dÑfQ­ß!õå÷Ø @:k¦QÕ)ùbï@k^ýáz/%áXÕx½‚ë –žgm¼½¬Ýar—&ç*0º[Í;<ê;èóйÇ»³A±å¾¬ š{×tèsˆ%œßojÓVáîUÐNç­äÒ©Wh˜w§Ï)Ø!ÙÃ[õÆ‚rÒPéÙÛbã+›¼åM•=¯7’}¨k”Y¨0ez€®Îµ!·¾Ρøêv§2ò&ML±Áb³I Ðó¸âè¦ÊPƒ½F^“º{[¸ œx‹÷¹¢ÔêçPŽÕž/ïy RyÚU¹å‡zpÛÎÉ9Îô§ÅUð Õ0矎+HXWÊe×õq„Nâ<|mø¬«?·iì®oöMÄúË„ô8Žc‹¦Õ‡ÜV%&Rz‘(l]•;ki’ž ›±:´DY+¡»yWXÝ'— ìÜØçlšž¥ô“֮ͷza·OX»qAoAvçIDzmë"]“˜–p½¬´ß¶=ñr º<àDËß Î`*ƒ0F0™œrT¬ã<·_”ë<¦ÔH}¾·X³Aº{¢¥Ðiv93è¥s|ØOÞÖ]qÁçQk`Ló«•‹¶Œ}š|îf~\ƒDkSØO³Í*±L;[ïU§³ÑøvÕúØ&<¾¡)ûÝÀמ\êuÊGÓ†Šœ~ÎU…΃S´4Ákw¦Û®fTYºS†àWglŠÍËê³™MJÌ€ƒA(í2cE„ ª¤^QÑm'&UMfÍm  ‰̶W*ªŠZ‰æ‡øöÐÃ?u÷Rö.¿Á}\°úó5þU{œâcöžM§N[lJofMÈÊ=Üf (5£é¯ú«X%ν¸.&Aé]nµYi.¾¼èÛO‡vfR­›ݬS§é~ví*Òy«$øxF°JÒ{"zz‹S–ŠChKѧÁÊôTÞ¬HÔ†Òèsy¯_$}sNöñu=Ë‹‰ÑêÇ­á¥Ü¸™,›×KKZànáòŽ9áß-›ÏUÝÑ 2\ðÓÄ?Q:½‹œ-e¶ûÂñ/1¯½êæ²×¶¼Îk[¶®ÆÄ­HB›%üsƒ ˆw%›`L‘9…™Úf¢ëi+ÞÌÒÎ XÌ’a÷H`&Ìöÿ¥:Ú¿ÝaN:mOÕŠ½1Ñ7ÕÖ𴲯 %‹?#<|¨×õïvrf®Ñ´(Ã{C¾õ¡o]÷e@{÷Q¬\’Н+® ¥ú®S¯p÷¿T&X“Ó.qÆsî¥øû=òþOóîsò•Çöllè=÷ëQ9êíÄCŸ$§X eŠ;…!9öfËz fqêÜÕêÔ0îáØtSxTîœ_ ¿Êt(÷Ìt†ós«2Sóá‹j‚s¿L‰zŽú½}^_«÷H?GYïË3u8hLý6jËo&î<ËÁÊvP¤%Ò•…V[ü8¹”HΕÜöÍ[r½Øw«W×wYV±2ó÷u¯\·ƒ—½—žQvpP“·a®e£teEöÚ‹~¹(()h®£ÌF Ù¡> Ý”…õ\UË#Ե知¡år´“ç•ãºø“/†‹tÛåÇä:g»ÇέуºfÒ*ÎTý_ìÙ?—(½þú~¸ub¥üÊ ä¡k —Íæg¥sì—ØC¾wÕ1Tb÷éÝ/¯/ª§^V&äVV¿Œ †Þ;ÊfêVgkÅ .AÙ>¤¢Üë;}´þþS½Îç£Ò¨ÈÒžim¶@»#’í}·Ù”gVε¬ý/áÁõ·¢.éhMGœF±öSŒik2éœ{߇Cž“ ràÑ.]<5&Åèuõ¸iS¨Ÿ9—o†ZÉÚk{ך©å0HÊ'-¶¨éóìj^ŒåvÅN:õmòÞˆÓñ1fN½g˜‰ÕÀ·aÚÁëP†çÊ57z§Ü:ñB#­º¬BsŠPIÖ&®Ì´LªS£ÕÑuõ^ù¬Þ^{^×¾¦PnÄÛ­Tò„YÕ€ÐM9X†Êë‹ fîdè%:ÃÔ-Ò•Å¥´†ì̧{È=½á@×ãC6…{«­ç„§º]¼$öüœºØ‡.ÂYJ‹/Û‰‹àz•míWïø£_ªÎýÛþg÷ù- Ùi ÿËVàRÜá—_æv8UfÌÑXÑ©‡6ï¢ù/f”:ìнÌáMúŸPµ™ì›}Î_ ÜÔ+gºew°‡ïK·%KžhÃKobq3"p™~¬$Ì1k®µÔÌ+ Ó»o¹ï\ìUƻآâ[À*aöct¨zýÝbˆÚ:®ÞÞìdŠìK¢2`”^£WSÓû^”¬™1ÕÒë©Ê¶Î­ðƺ_+J…rIa¹42 éëëÜ,sÅÖ9¶Îç^¢³&OÙ½ëløWC iÓ¤ËxµÜ©r9tb—¸×‚uÄ#Sz¯¡U¸AÓ=å·zîk¸ý/·_<­™Á_Û”Û()Nø@òˆîÊtå`9pDAWáÞaOsû+MT/¶V{¬ß‚Ä$HîˆvJxÞý‡&%Â4mõ‡{…?Þîžâ|Gƒ}^[ÝrC ë–’í»Y%7m‰}NÍè8îÔwHÆ’r7öØæm_Tïê Š±îtÎÛ¦§íØÛõšÜt¥¬5}Uê™_’¹é÷‡ð­j7~÷,yÏ>Þí¨ðnNÝCFéH"|0»«ª™ÛR ·¶NŽTG<3¨o«{Ù—ÞéÍté¯o2ûì±BÛĉÚãu92ÚK¢»ŒK F®áŽ£k³´ï¸ûfUû¶pÄË£Ôh­™d†Ü$ÑÕ“N)GÆú@®-Õk޶÷F晬gxlô°=ý_ÕýV¿V!Vjü?”·ú±†Ï³.,*ÜŒ~gzÎ+úο ‹<î½VÛ[âJΰ½›‹§”z–Ó¾]Ëzß7«V†3[«×ç„ÎÀÙjÃÏMÛ8å}Ó×­lö»ËÛ6÷5–!u*ARa`Q„Ví¥àâ¨;L}.Èv„Eü°f  §š¡?së qî¿ÊÆånê'.GéjsYj¼zf*`>$c­µ-HΧ•ã*ÉsZKãÞšªê”@¡k˽úÍ>«Ü «Pœ­]§ní²Öø““N¤¨»&äTÖæ†¼j’µvezÒ÷§+ µjõúêõz$V:Ø•oIJ˜ôOA- eBßdªÏ,ó^µ ßW¢ð=<1á p*\;ež £Üóç×ÕŽj1SìF¯6¤ê²¬ršI<9æàÅÓŸ¯¯9Òè‡P¿‚À¶EX³Fá/*úJ™vuN‘¶¬&ÃùJvÑ[¦û\w/£Y™l´ìšövÙÛÆE¿#%ÓºíBéq÷w`\ê\öVN÷';ÄÔ¦"3½sî›õ[(@à(Õã‚mâ÷2ˆ°íÅ Ã"ßrCÞ—×MîA‰7§Åß½ç)÷5‡_T`‘Ì_…ñsÉý®ý€W®¹D®oi›ü-úot_ºóÍ8ÁRºnpo¬`¡®bÚǼMGÂjÚ”+ïs—³±ã2z—Ÿ-¸úÓÛF½6ïÒ³FûË£c7|}Z…[])ÝŠér£ÎY¦•|²ë³Ê;òÌUÕ¤w ÝÓ+Ü;%lp.ÝŽlÍt)tÇšåÜRao‹¶ÎÔ óxë0® µ:B»Ç\f\9´{-î8žsRiÇíëû‹–©Á}„²"Ÿ[(Ÿfp¨¦Ìù™í§¹îǤaLyÞnûsÊ#ïM¬mŠXXVÂúÊN$¬½mdN+°wùáy3Ÿ°4êÛ¯S¸+ú•ĵW»J¼ŒzÛöEé|OA,ö? ˆÜ¯{º×œÖS•׬Z‚à‡¬k¼¶4> VZìãn·n­·ü½Û˜Hq'@í?O^¨Û4`/üøªÙç½¶xS›« ¡}ã )ú»Ù¾jŠÆ¨W¯ú®ìýâÿO¿~SÍß5Ÿ“uwºñL5žýW«öP˜3bü^ۯƣý­¬híwÁBÔßnö[ò¢Ï¦XpfÄÝùE$Ê·fZ^yàðfÍ¥3ÏvnO=I ÏnRßGävCž tãY,ÖJÁ·SÝ‹§-S¦^ÚdVºîXhu`(G{QѲ³7_ æùx#CjÈ‘ Úï)Ûj5Rf¡*ÅNæÎÝeSÎ¥;”Îö²ó²…Û¶Üëb¯/×ꇦHrW¦¬5;íîÕÞó«"³~­­[ë»X6bp{¸uèp\î¸i--H¨yÌÎ8.¥×ïvoHB£b­ÏO ô'qgQîëŽñ×SXº ¦¸ýŠ’[•W• Þ¼$Ô(Il]hCy·a¸.0“ß(ÎÆôA‚c @‘1àTä“ã\¥j)Ü2˜bUß÷ÙIm6¨^@­ptï›VÁ¢@j.æ®°­®KS×_åïûW¬~ö{¯ðØvåí¡â*2P þâác¯øz…ö{öß!€ø…SJAX“YØ4-zŽRuÌl™wØ[É€½Vã°øÖ«ƒ2iíÁCâ§aÖF­s8nÖW¼æáíöZ ­Ö™ðx¾\ý®üóƒ=Õxzvº…›Þ¸Wsô¼¬”#Ó}Ø6CBL˜qÄjý‹{W‚ÀêÍûÕÞ½õ”À‚¢¸Ÿ×V@<ùvuËÁ™Æ«ú©hzjsØûÒŸ¥ÈÒ[+öRWîQúôiàrkóî§³5ù7{™+´çµX}¡¶XU»]àmßN:XCDÜfßèÊJÖU‰ºàwún÷YyÕÁ”0QdLOM'–WEé\Èz{—ü¢mÜð˜ ^mS°ÎÂø+ùÆd¸mig$~Wû£ÊøþvK«Žþ0AƒJ?J oºð˜·¼;xà(hX{Vob­Ù E›W+o]ågÎem‘aÒn6¥ƒ¥íc?’÷³Ã:‡³ìúnIŠ»Vkµ‡åO½³fŽ;B¸åã2+YÑíZCkõâSr)\¥ZÇÇ)h‹†ß ³ðù¾ªûú£à¿~ÑÕã§.°$°Ý¿ÌÜ[št;¶´r5Ú·zFÆFLˆiLæ_Øj e:”•ΛÛ%X†Å ]|•ãÂÖT;B¦Í¢èÝ\z4оäjw ñ¡'Y£}bÈBùe¬¾Þ¡‚öÐY1”³Açx줴+ÒlÞõ“ÑÑâõÂâ·°Ö%VmïuŒ((o”³Ͷ8ÐÝÆi$b’X»[ÖumáhjD-Ëz©2kjJÒvˆv¬ŠÐïs/ ´é1\µEÔÔ½¢XH@ö¬@4HÄÝo)­[YÐÓ¹}} ôV%hQÑ×5ÁNáMax¥£J\xé2¶+ÿ/§Nqm†\ìrIczìe¢6¯†̪»*r›6ø£­ýr&•õ:ccl ‚¥@'»©Îê ÖÊìnì©5”½Êxú¶èJšðòÈ[®dÖßw:Ørö1§˜tn»š%T=¸¦¶é%´irÒ˜9bS6yÞçg·z”¯ÚÌʧà¾óë¯E´koå×­ñ­ý¾õè¸ÄjN˜PAY©ƒã¸ykG-m隸6–Vj¿°»s¸j¸« ©¹‡™éw‚ðžùC=uÞ¢ƒ‰æzT¡QÅBFõ†°°*›Z^³ÁIMé⣜°m%Šó©8JB9Ô:Ò´tÌ)CFóºèÚ£@dí ËvĪýBŸªÀ;Þgzü{-®®NE[&r¸xï;‰æJC’‹‘=Úõd¯ïTóI º—»~: {Õ€ÿ ƒ×+ÑxÔn^Úq‹;r2¥ë|ÝImÌgj=÷S³Ãâ L®ÁãIZ¥ˆdÚãõ*Cc0L˜ò[Qħ…æ"o xÃó¡F,•hfݺ°æ<Þ|'Ç)A«2Þˆ´q·Ñupîª%Z¦*ß.ϯPö:‘v8^>¦V¬ÜKVYÆSâ)]Ù®¦‹ç4"·)æ*$Pzô‹BÉt?Vm£qöí{–!—zAÆÑ`=•¸ø¼18çL>­Íïyc1y¥ÃɳFµ>U‰b­êX6µ˜I”#¡wÆ3yÒiTzóHk4 Òάڃ.Uís§khnÚ5“ Þ8M§”E2we`¬†Çk—rj »Ýܯ© OŠqÕí¾dÔë¾ wiËpèœ3.‚ì/*èô†ì qo ;.Þ‰F[ Dªxú£.§;áÓVäÍ/;á»/žØfXÆp_ÞòïK±ÂúÙÓÔŸœœYÒ­„ƒ7[ñ«”¶”TÀ½pÓ‡zbh‡±…ÌҺȩ½ÕnVZ?^avOo®š>ó¦Çz Ç»s´ühºvÐQíi/Ÿ²åúç„LxK0‰YRˆ9Gà0¼â.ZÔ¶Ðôwˆ~ 9–o.¼ŽÞ¸Ý“0sFìݺò»Ö+ ¿p^ÃjùIMT}¸õÍv÷å 7¥‹³-uáVoeÇþÛõ.…à‘b¸+¨G­‹er­Lê¤ù½Ë“gN¸¾À-Wu]ž°šìÌÌÉ3N‡uS»"ÓÖ£ÌLA÷L±¦v°8`sX¢Í߇&×ùåÌVŒ#‡½­«óœéC{xèuÚ6Ýrù[ž³+‰¥(U®ºÕöf+ôs¼š;zoNA·à½Øê)½×Þ×µ=Ë(‡Âu„b¸eu-WÔtá÷Ñ>¯.ŸyômšÉn4>€¿sÂì«©zÛ7•厳Ÿ´ šô,m÷ \Y"ÎZìW\m{ÆîÝPí¸QToÐôhN׎ŽÝ:÷±)uåjKÇ®F«¥Ö:†£ oŽõygØu)öŠðeç†1Úèø—:•½‹²÷;f«®ìP¾®½C­å£/u™µ–Sæ_0Þ½–{2¯ªB»9ÉÂß4“eåE§*ùt";«925@3Ë7^&´šÃKVs#Ã}¹„›‡(3g#î·_Wø?°ûóõrž‚°K»¶UnÂÒ¢8îX˜0gæã«SÈUfyߥï®#ê+¯>–Áä W™ãÑPŠó’^§Š¯¤m-ô±ÇidxðWp¶–œ(HÓÅ}áê±·ê”ÛÝžÏj¬í5_é]ð\¯)XÔhª¾£K²W¢a½ÃÅÐ6«%·†!jTÚýíê˵á=]ëÎ':Þ+›"uC¾U溇õ©ˆ’½ÍÊ9@,Å ÐåjÄ)º6–ÚZþ\·ºvòáNߟG7_§¶ä§–-œ#o/ðš,“£¥ÔýAwàÔ³û÷ç_ÖùÂon-Ü$4™ºØy3™æºÑpysQz´«¤o³RÆÛR¸úçÛÒmø¼—«›¾#âC‹øwHnhYî¾çÀÅ+>‚z‡l®ý_³¼°Ê2¹´¤3˘¬Ì›‰Ó#d¬ÿut Þõõ9ì.¼šg}˜´×:Îѹկ?•ŒÕ—5¨üÏy‡/« l[s³9^uÝ3[dJ>I57¡›iolÁY¶hŠÏ;lpà…®µ×(!1ì4”˰&RÛMõl)}ŠN7\XÈOä¿Íº¶kn=@'S³Í%C¸23e%:#;wוtoïíëò«Õ×–˜}«øŸuw9ZÅs3„Ñf¤ÞÇûüùgq³ËGïíü£,¾ši;lÝ,x+†d+¦ÙÔŸCxû­s ê:º"þÙJb‚½Ü&[–ÇN¢¢îµƒ"ìUjãwlgòWY¥ï`ÜiXÞ±Y¤|=i÷©ÓmÔ¦]\ªJeu‹Þ//t]{¼o<Ûmo6õøïTéäÔ‡hö¾¡õÚ=¬ë˜ÆÝ ÞëµØÄTjx¶¬kã …™7d)ÞùÞ$„%já,çœÏJ£;ë™éÌ£žá'f©`:ņtbË)EM›u:4‰~õtÏ?ÆÝïÞÕúOj~r˜¿n쬼sz ðñYQºµ±ò¢¹ œóM^|‡N·«©÷Dñå:éCiL÷&Õ[ª}šG½yG}ä)UÀ )ï"~窹½ýÜ{d®£­gAŒUÑà0uxšÅÙ×ÕÝ/ïxåÂ}uÞ^¸Y"ô×Qd®`ã¡u4ÔI΃žÅÈgI’†¸t:Õ€¡Ëijë’¹^R×·Šßn²ŽŒ“;Ò½OÕ¿p±FöCÒãÀ²jÚ@ävݧ“»ÝL\§Ï,±\R·½Iöœ[ï(¿WN™ûÂO²þ.¥àÜ¿¶…–«ò_¹PDp€VÄG”N1¤ðC§³xe4^W vǯ×Þƒzí_Ù\ë†<}‡ü¯r»kÙžÜëo*ê6¼äæ÷.ƒxþ¾¬ç]eë„LÂEBʘ+…‡Z ôŽºa` •wqYzz´×\‹D¨Ø¸éã"9S¨3Yîën›;0U­ ]>l"»ù®vo¿„ÎøÊ6ÿ5V~‹â?ϯœ?‹°§óñ]õ½¿£¡¢º$@,iµµo.3 ٮݠ›°\¥^_¹3…ø+ò»óEÑ€ª%h1 AîÆ9Í}bDòœ«›»c•’:LĆT\{B·&Ãd$„ÄYðý_å~»³yø¿åq+‹ñeŒþ _ÈaɘØû'óÇ’@wöK.)©úã©:îËaÁz/ Ò7ËÎ¥¾5tíw‘övq ~f¯»õ/Kï*Ü÷­Ö÷©}|¸{„’òô]`ºXžsÌ ‚ï¶Ò®P²¾SVÐ{¼^ KnVÊ ª-ªÁf·Ý›ôõû‹(~¨@4,ý^ï u”ðÄ«…=-ci\z맨ì@5íí>ÓB…=¯f«ND{kó#xW»{¬'³Ñ>¥»wâ¥i€î0èø…F“;ÖÉõ5i³ˆ_*w}S•¶Ú+SÄÛо f^Ë*yg: é;Ë}á’Í0£j¢"®ÇvÑöæNë×|–xŽ]¸p4O@»W"[Æ‘ìnÓNCz’î|ñó¸r,råHë¶¼ðõ­óïS‹Û½Gøgdðñ5{Wá«Eƒn‹,ÍË &nýºVudöjËÚC÷8Šö•Qp¼‡3Äd÷@¤SÌt÷ ³‚Ç%ˆÕ±ó;jÏ@û[7;¯~•Cý}þÊ¿WãYDP¥_x’ŽúÔ• áú¥,yúäçºp MgõùŽã»ì3º·áö‰ïõI„Ì_¿p_QS2T%íÄc$8Ü1eèA47Eœ#Ëc,R¯TK˹*>rÒ++]ÞJ|?^zv-¿olT…Î>©Ù#Ò:Çzò†‹ìÓ‡ÍòuíTœÜÆŒœöíöÜH’Ø®­Û”¿ÇϯÔOïß¿Ùú›«]ë8ûL¾œÞ|š5£¿ÓïcöµYâ¬Uö Ū|éL‰(+n9|˜åÊ]fY«¾Ì®Bßl#I8K™>Ë= ÛàÍÜáb uZreóÈÜÝ›"*ìuÒÆ;oT¾Æ+vÎèl·u,W›PCíø4‡¸'…0¤õö£yÚ·þQWöœô£ÞøþY–Þ;5dãcë¿~…<2á¦foN˜.­T¬ÇÝÐÐ6ÔUÒk¸Ê®i ˜z³GW_¨/.jmž9FmóUuüX£Ç±{×åV¬rÍoj} ‰"çêÍxã›Æ nö r­Û×. t^ï’®Ö·G¸ž£¦â¾ò{vÏ'JƒÊ¹¦:¿K—0¼¹Y[EPO¹,ýy ߸¸Ê»¹Ù`Ö¤Ú]Ưfa9ú¨€ œgO>§†ƒJkÚw˜Æyù¸’ã¹ÑíÅ¿ŽÙï—¦W&µXK_R©gì¡*\JóFëƒEgXh•ÓÈñ£P\"\òõå-ïMN÷zîP™ÕWZèC§ÇX·L1FïjÌîd·K¢{ŒËêMΙõƒ—ªâx/$¢kú¤]…s¹[l+TÝTãÕ:ù»‹ªç}3¨?µ1µÝM‰×X”-êà¶…¸“¾ãÊ~¬¾žß{© b¯‹Üü½Ô³ÌÑÑŒø»Þ›/?o†f-ýù{Ê&ïöµÉD¬AçŠ×á}µ‡<¯ÑgêsÞõåÖ/!®ÜZ)ä¶²g³2žþÛîóO=m€!Ïò½¬Sõv½–OÑÊë*ÄÌ´Yü;KÞü±|7pø;Óú¡ëü:–!êT«¼Nu¹Bjuss¢%"t¼Ýnm!ºÁ­‘I§æe7aÇWoz´+l)Ÿ+Ëèr{ûš¼gÏÕ£5Ñ_±}›~^SzCÈš½w•ÒK]Hô»7~ç^GM8™Í¬¬Í$Ÿ‘Zš¯-çNßi»$eÔœ«.³™×áóïOâûNÞ_§m‘²²Ô'9ÕÙ,Ö2[ŽóWp\`w¿*ïAÓïô½ðß.¯}æpL{6¤Ê“0MýKjiK¸ê *Ö2I±C€þÖ;‚V@¹ûÏ?…xûÝ^]pª— *âôÖ4Kî®X"(òËÂØEѪW±É]txµ\‘#Seª‚»Ô82«µ“”{%‰ÊWuaßUðâ䑬yäŠ×’7"wªŒ¨M÷MÊ;¼ž-Ûœñ·Ê¥6Ë®ƒw»„rÝíç]Œ5³—Cf‚°¶Â¦uá²`7fÈ䯑·½ngwMVÝÕkTbÑ¥‰‘ª>¾^JTÛg‹ûÍÜo©”=tÇ#‚ò–V™!\ƘàÅqvðõÁ§q<ϸA¶¥š´KBÛë›S?•ñÎý^çÏÔ§»î *«PKÔÐËSV¶z¿Ê•_©Øƒ÷ïàwкü9oiùŒ§Ûx0+(_WGu%kõ#5[æ³Xàñ½ËÓRÿª;¤·‹ÍV Qªkð˜nè KÔÎ4Ç 6òâÈeÌ›;ºŽÌYhg3Û™Á&µ­±•¤½¤müë•vî7oµ3Kjïk–7†Þ» T3¶EM—º€ÏLÂtêýî;ø‡â‚í£çåÙùö×GVO͵KebJ{™nÂé—'R‹=¼®Y]¾ÝU0zQLiž¼·˜ýÔ  Aм¨h½8sí¼uoõzMî+²ˆðñ€3­šOXîÏc{HÁVvfö½B4ºýK¦ì¢qéådßQ4*Ö/;‹óã¦Ö3ˆŒó¬ÐZ¯Õ^ļÍ;w2%~^•1•+ßÞìžM†dKejïꢷ׆=SJºÏP–У{°ºPô[P¢U­ÇÖëï æ{Õ7Ðð¿ 1M¢e´zú½]d†Ë;Y7Í#±a ŸyÅH€®5×]¾ÚX¦ºÉBYXúÔÕyw£œcq[Qj¾J«K¦a€:P\Ù×róÔD¥=s®:Ù“žcŸ{s=ÜyÖSD1žÙï¶t¾ît:ÅZ—úŠÊŠ4mmgL½^Rb¢GÑâˆÂÕBqòc|L“¢´··ÛRožª–7çÌÆ®¸í ²&./?Ö+ú®ØßoóUüóûö³”r¬ÿo§<ñÕÝefÙ¥¤(…w>Cºf×>ÔÚÈE´lħӫ4f^}i\Ђï“ëÌ:“ìŇþ«þ…evr 6¿R¯VULr >BwñíE]ßG«Ór¼hg´ÖÔñ8"9sÆ@è PîÿUʬÔìÏÞÐýQ_£ý¶6ØóÝôÎonO%×jæ–“Í©½Ø½½+÷½ƒ¤ê ¹»¾¾.v4/dBOlÅ1n<?IÛï êWx_{—×zk¨C–+¹âϯӻ»ÁïӺǙWÒ™Koç{Ü_¶”pv56rü—Q¯ÔºûKïË‘ãïÇj3ÓoŠÈë`6µÊfVÜ~g éÀ.ÎÏÕò̧™ú8Rl{è¿×ú ÜTºÐäêªËU x£ÍZr“¥j—Ei€×<9‰æÕKÞ¹oŸ½öûž©ÔƒB DÈûn#Îï¶…ð‹•û{<ÿWãYù ¯yOÒm/'½Î·ŠËÓ»+Gñ§¡¬‚RϺäsê¯ÓoGTíë^bS 3w4yÈÆ»ìZkvÓ]¸–(=U¹Ò‡‹Î…]N®þÈ­)) üù(ój:Ø«¹ÏÕ‚¯—ôævî¯*ë"EÛü¡ýtñ>>#2üH¯ÕmLãÞ!†‹`Íq 8ëQ>ÙÊg1Qc®ÙšëÕôc¾\yh{?VÈ¥ÂU#øú÷”ŽŒÉtrÇJŸ«á®ëôüÕæ{óý ¡P­¨2í8†ïæ¬iëÿ(æ ãYšºƒòmdáiõÞôº ÕAuËNLjKTĬ±b‰u‰¨WcÓ6Þjœ¹ F† äU%÷-’à©ÙfÝn³êåè”cØõJ © ˶JƒÝËCÛ»Ö¯T¬›kq싺°‡Ù}šÓ¬?»Às¯j{Þ²§£ïaÜÝç>̈cv7ŸŸP'|}ùcw`IæB1¹WQ@óLzâÄgô÷µH¼Žª±Ç§:K/=|¹CŒƒ9I! ÐñÑãªî‘ç…ÐŽÒ`ü½d14R¥èêÈîoSH­«ÅobxÀßMÊ3ÞðdèY~r²—eeõÏ{Zæ…•áF·ÙŒ-À"Ê1ç3l÷³Ú…ñ}]Ô²Õr·ÞT¨ï{:3ÝÓiyÐè½sã7ß,·7Z“ìZZõÐ-^ÑÖ‚q×j߀ֵñ‡FÑ¥6Û%´¶µNá•ÍeÌÏGÅ]^åæùù}çC+®oW€N¡ùVër ¤‰°ß*DÔï²ó(Ô$Ή¢¡§Ê¢„téFèÅöªá§„Ø^a¦¬›ìæa¥Ö½yÞ×ꕦ¡`:1=3[ÞA~t¼}Ý\» CÁt"Ì¢1œ­F× §d ô7›az²¢Ü¨†ÛaV.k½ÒìΨñ‘|hëÌw~ˆ…κ¶º­egAWôjdl\ËLVàC:jáŸcȳ¦ûÂ[K+Åëò8yÖa™Û¶^0—ŸUÉ"¨§O}‘0Ðìuµu2¯ìHîRêvPYxvšEgÄö†"ëßy›ÐùΞ£J€B´vß”÷—¡ß ÌlUî&¤ó§J»»ȯ~´èMDܧ8ðάÎ^ NJ{M;öIìô€.â³xvífœîl'«˜’µÏ`‚ArÀµÓ-¾Ý~a!¾÷›¸`ûZìÀuiím.KcÞ…gC¦ñNc³çH‹²ó&IçgT°Ô¨ûÀyõ=zƒÜÏ<™%žw­âófzðôŠ_*¼õ°ü*VÖxI¾>ã”k ñá~õ+P«f†Üô=7x|·|äžqöL£îZÅùû zmmk¬6•õ *ü©¼ù,KGÏ svåyŒZð;¼Õ¨^ù§wZ9ºâ FÑÓ¼á¾~>SJ9¯_¸ð—„`ã.\gµc™•€  ¯¢ÐÐÄñ9/•m`J³«ºgElÕ?*SÝÛ½ÎDPËÉÌÚ°ÆžÛúøUïB·8ï’Š±"7 vJ×/£jûžÖ¹-w›8ºk¦÷¿pý•ߪóku<âˆÅŽßà³"ˆÛîÊŽŒ>É6±®C9f÷m¸´ç~xe{º_™‚­]j§âzý¶ץ!仲ÍrýžëÚT‘ }é~í¸3Õ¡+É׿;LuYÚÁ»‹ ðOim=’²Ž(Jºñëå)Ò½<ÇÇ1^G·.¯ù~”ÁìÒg-¶K.£õW_¢Ü¼ËZ)þ¨úýþQhÎ/Ø;Ö™þ=µ"jãõæf*ÊðIbÕO«©â¥Ab¥ë«Ë–èRWO»K`[mo= 9|ÏtÑ(,Ç\?“ÜhT¬MY¼,‡÷eŸw#ÁÅžÜ K<¼È¢k×äªÝð˜ÖÞ´±æWSÇk³eÖÔ…MìÖºÛ.¬²¶JÊJdÉZ›ŠT«Pr n”tv¡ÓœË±ò€þ×ÚÒ»÷ªèÓÀ/"¯_”™Ib&ÉΩC‚NK4- í¾£®K«%nçé[î=pdõEaâì`pœ;pº`)u$í­Dn˜V2íÍ”·­W%.늫"ù=áí÷UïÕçaJ›–Û Z×C3ÓX§y†¿Êç×m?P\°²V{ÙdD®ØòÁ ë-@ñÞR¸MÎ*æò+žªàº‹ç94Œ¦»2b±ª=D~~·l߸¿lÐýeÖB=~ÁˆfgfÉ6'ç‚^8¼ ­Ô³î®¬íZž\—.Ðn¯ËÌx[îœúî·k1 Ë «Ã93ÔÝ\«€’•´ôÜvÛTŸ*o}ċK9 Ç70…ÜÁ¡¿=µOÒw<Þ0oû¬Š.õ/vÃK£¼[k«¯ åK‘éN¥Ú™G4Ù)îVK³s®™¨вÍ1"\kº^p Œ è]mz¿ª§‡‡º‘ÌNìþ òÜ^.eMS^ÔÊ£ÎÃê÷Û«¡x±¶=ŠÒžAkíÇ\¢6tÑ÷g³ÕÁ¼´í]Zg¸!=ËŸ¾å/‡>{†ÈJUê´ÞêðÅ\OˆìÙðB”o HUݺb®[ï\¤3Þ唤ô¢ª[ž±b\8(sÍV¸¤ö4iV^Ò ­'ˆ–r®™Ø&uÄ`ëÆ/uÕí›°Ü×*) ü_V÷Ä;Õœá]#•œ_h#Âñêêž«º¹º&zü”µËÖ}™Jl?,í|"ÝÛ)±ö÷Yä,6®ç{Ës²áok²øzâ3<» GµyzëK”çe•¹Ø~å—¨œR>>÷½BNòFëÈØ÷vm u}!­»®…·¯ jÄeÛUºÏn}ÌÕÖÞñÒ±ŒR ¢fßÚoÖç·<øQN¦¾4J½ãÓ°J烅ë4¤cs) SŽÉê1ôša±ab³¬êÁÀ ½e+u0^Õ¡s±ÞÁ¨^ð"¥öގͦ‚bY Y÷rëqʾÀÙÕ¼jƒ%’Õážî—=ïs}¡^œW0¬ó›1VÌW°µ·àRˆÝ{n¯¨š}ä`wÔ«‡P¡qè»@J[n¬ÂlçK€n ËÄ™{@g@x‡õ€µ®êašP¾Gì qļ<ªQð‚a˜}Kï-¡á•Ù¬´³Š®‘AÍ7 zN×nn‡ˆ¬®<'“ƒ§ùÔøòÇß ý0šþ"ÚU";WVL[ÝLÕŒqM¨õä® j€»¼Û«ÆÒÎá ;µ§ºPµW¹·¶º¯dpkzîËOxÂåíGºµ…Q'™ö÷)r¿“[wÎâõÞw4»'V5•m›U ÞÎrðï ÿ%ïÜün’iºõÓs®~îü—½ˆSãBç·Ü-ï¥ë7BØ8ÒňoßUWoeE Ãt¡¨èï/z½íw¦ZßW+O°t•öîm¥ÊXd1u‹Iõ 4LÔ†Øî_g_^®•ÊMûFú5ƒ‹«õìú6ÕXæÂ¹.и¹mF0¡°Êc=s¯«®IÙ]Æäï“LQZ3¹Óÿ+}_å5¦ÏéþŽWö7}þT#?Ïì_rE¢EÙ;ßFyCÛÌÛC¯E”†¦.èêgà;®-ºí=³)QÈ&hÒ–YD=2>t*UšŸ$å¦ÅÙ=îí¨}¨ïe7„€×u~ýãC§…fË듉ò>Þ÷EûÏðø¤*<µ_©é<Ç0 Ûɸ=Ê›žJHt*¶Éê=}€.yq1K±ÝÛzžD«ªe¹Ý/9Ž:p²Ð[OQËz6gw^ugæÝ{OvÜv•Íòwb[Ô¥”z{›,#Î+°0UäùýoŠŽA±iÁiתΓM+Äï@»¶Õ÷ÈåÒ1†¡‚cÍS*î"rV´ôŠC7Þs´ÕùÞ_a\¿z,+Ô¿#ûÆûü¯ó¬Ÿ¿y4áuï~–Îÿüñík¨ë]A]Šæè‹6ˆÏÇ¿­³‚LJ‹=¤øÌ)fÓ«Q³ CIÜúB¼;imž±+K¦%­Ð\“ªT0´;:guv.zŒ¡jÇÜî ½]ð¤.ŽnNåÍ®EõÝ­¬´*Ê$„”Õò”z†l‰Õ‘²ìÓo˜7Àui9C¶V™\ ®=¡zuⱇ°(ú_'MÔÉÝSËÚg:½e{ÕÕê¡p¾a¿êâ(œlq¸FqGè†`­º^cu^øÏ[„µæ1[öÝ–tƒ¢µ2hm²+<ªýê]†fäÁt5…ëÞ^Þn9×ÜêÌt lW:Ö« ±°Q˩ރޕŠ[x§ò„7vBîýûðv‰ ö"smWë2qE!¸¨·´úÁñÊþà÷x\¹‚¯$ñÂüžÑ¥«Þ·ó§ãÞ6‚úö÷£É¼=ë£Êžg7½£¶³CÑSjÁæ•_5³m3ª¶Ï:EŽSî`ô¢}.ƪ}Z}ëï©¥¶>T…–¦ŠÞW>íW7LO¸‡{çîpzýªÚ÷i™ÇI˜ÝÝ wY‘-ó+´ŽÜ§t3\KckŒî¾”Ggtñé—ÚÛÍ úýlJ꺹D#½¢QË“v‚ÌW(öÝØ)c_rÖÊÜÑö´¥£á¯–Òwí‚Ó£s í•,úË»]BÙH7ÄaáÃ+yo­3ÎN0€#á™FÇ? žûÚÚöh$ÏÖÞªÒ?;´WQ·žH_®KS³oËÇU8ŠW{Ôòìçto¯y=¥¾ÊBy·F“ùÒY@ÒyJÑÚây7Á ò?20pÞ°Ÿ‰¦£»~ï9Ö}•õï‰~Úß+åìG“‚ÞÆÉ˴ܬáÝv^ ^YÚ%tVL&ßEíp^C—&"póÉ;(³yÆÏrߊî_)™:±3SyuÎ5ÞéžuâÇ Ï`kŸØ:Þ{—ÊŽÔ{Ô›§™Y÷^”5î²óϽ]”ríõž¥‡ÄÝ h¿&#Ë6¹1m¾°¶[uÜ7¶–míºç[e^ò'ËÌptÀË÷eÞ¬öó'ŠÈ\[¾‡k´][L”\_^X;¯,¦%¶$ ë.á[ëk&q®’è!ÇäìàÔ:Ê:vëy<´+ÁååžêÏ¥!fûF-X,Ã< —ölN£äŸsbî«íoÓ=5”¶elÔW׸ØÖzñàöwƒ…û–s”Øá23®òóÏG\èJÓ^R^»>(ùê;9ÛÒ¬u~Ü­´;¸ 8Ù“=éPo ©·Yu†l¿=)*ÎÍÞ´èN%-6eMT±Hk.²Ô¡‘‰›è7ºYZøê +Âl¨ïUão­ì¦oA‰ zwfQ½ªóõºF=1Šz[áw©OU¥½˜év ½·²ä.+ šÑ»mq››YrmÍ˹E1)¨D);¯»ž£ð×9ufIJ¥í2gÕ¢/n².k:6ºDzxexÔx( ެ­Eƒ•6˜ð )Ä.Ï[Íᕲ w‰-¼vOd˲¾÷½Ç\Ù)›÷´•¡ÎÁÃrGÌmk…ø¿´}2³Ïßg´u!pÃdGkdÏQXwÅï¶SÊɽ•:V,< ñÊ›½¢­—Ž)WÕwRÄÝ)h«¤˜¶k%Ù=yr¤¥F•Ç]ÊŠk[vì«uâ‚»ÅÔB^ñƒžw2dá|‡s6Qí£ÛèÖ›êbJœ&W^äë\̾«Jܳºéï¨Ç¡RåtîçòWì´åm“¥¿^­Ô½¬ÝðTÄÛô<{:>÷mfDåy¶“<²ÈB•bî%ã7Îe­ÎÚ‡â­é‚pŒ:x)Ëæï…ðK¬Óaöe¤«QäÖ+¤ÎQÌîoÁÜ÷]í¯ñQ-QنŴ³V4XZ/ÜÛ\ i¹öv'»r¬´Ø‘œÖn`¸}ã¥ø8}Ý›‡ ]/|•ׅΓ®x{-]dìOÞñÍšñXí+TN<Å«}IøV-ÜÚMi¥Õ®Ü'qÎ-ҥ˃Kܽã]–»îuÐÛ%öLÀWe¾ê8¼ò:á£ì܇ P)^ãw‚®ÔÓžáÊ2e*öù¬Ú;½6›N¥]{²éyÓ)Ü^è=‰ ìU2ïTŽè÷¥38EÙCk]k¶“´} à2ú%Sªä¥¥ùCé9wz" V„!¯'Z•n,ÎP+M4úÂV´³¸½Èë-íp½êš²­|¨Ë“[Ðå£ËÊ·Ë ©Ø†v¯e#¸w¦å(Ã}ÃërN¾¯´¬mPepv¶n‡„pQqLtŒ@d¾bú‘÷-iëPbq¹ãq²…€Æ[Ô H7Añí}n—N#§[—ƒ`§Lpºåš8UgÎ¥ˆÍšÜê½,Ð{Üžñ¬¢í-}²ýÇhJaxôyµÞ<—2/®ãVêÐåfħN4ú,keÓéË o°-4e-È *­Å–Ož†×½ÈxNÓ«bû³„±«w¨„Û}c/Óê¼–FWW#Àº^6 ä m¬c[¹C9w#Ã͆vWºeQ»Ï#pòÒ¢€›·!žò+0r/«×šò÷£”ÍîmÏ óG2Ì>j{¡Û¡”&­50.~E‰5Õ¸R¤æ+õåü,ºõãn8uJi.ÄKÇs5f\ãéß_I§qÌ6¶¥pôXVÐÔ'C5×:à¼!¶8§]Ï7§báæöŸ ̾º¦»ËWLû,Kð^Î`º×Êmž`†¥]¬jwW›wáŽ`ô¡çjûÙêÞ)¶Ÿ`º¾µZ£ä=Ë7ï§IÙ³;GiÇ~V˜Ü>öç™Ê=‹í“”ë÷v:f4SÉۊ븮C–CEˆÂŠYícèZRrßÉ^ËÌÒÖ¥^•µ¦jßuãCA unáëY½môpŠv 3–åttm+8½ÌvñÉã—™·CeNø4Ý2î ¤ßf .ï?Ýõ<.Îß7±«½½k!ÔÕm Û©Ó?>1‘/‡,"¯6ËAŽ—«1·Àå€óöu²ã†s½wÅ-UžÅ\1JN•YS»·.„­P¬zWtùí˜|èî×F¯_–­HÝH'kÒ‹ãEÚÓÖ0ÙÜÞwJÖï(7šû)㕽n];Š_®žš‘z‹>õš‹ÇP§êZ±ê´ì䯿nA^'¹Ê4Í!@=‹.ìÅÓ¯e?"žëºnòG‡]À¸òºëι8÷jnåû1*ä~’>”s3€‚üÆÙ§°¤GºÐ°F“¦Ç7äýÉ*ç@zsžÊfVä›YQïOuAûUÖûØa~àÏRYsÂT,ã±¶N‰X-`‚ŠÄ¨×|ÖJ5“»[U(eL»óÔCljT[IK„°¬<®êËîð5î¶}ït“©^O03àÒÍàÚÚÌXîÅbåRå×"6ýHz>ܹI/ìÙîbáx·µöñ툀(¸ÍXâƒÃ•%Ç>縦7‰oczÐx±êu·o}:²/ ô5ÄxW=¬RÎrçTÇÝl„ÜW_âa&‘î®ÝXO«%õWS—{%®íˈ-ö¶o®ÞS«W›@ª5‘S·Q<Ûw]2‹Ã:!¯Ér³'ŠkÓÞÉEާ™§ÀMÚ÷®C ¨ÖPÉÑí&p7tû3ï_˳ÍUUè®{ÏÜr¼*£9F7§«60ëÃRÕKê­Žˆ%¼ž$ùÙ½´{q®Œ^kJ%jÍîîpžæêñà·yíÎnù=ÒíÖºC¹lVUôy½¥mwhÅfB˜Úìƒ@£‚¡u©Ý¾™b«³Ö“X‹ìµ·˜¼»Ï(*•½~¿:ÖzO‚g§$H­0’Éë‡)!Õj ®WزÅ[Ë‘»€Û×ÊãòùB}ºžg¢;š^⣗K²¡©¸Óƒ•7çì’{{à×ÒÆŸr–ÀiAÍ–Éšã½qyûÝ(Ñ7IbîªÜô7n§?^NsÒÏG^ðëckºw½xiçF½§UšEæ†æ\&Ä‹<û¯}è9,óÂ]וž¤L}ƒ̸[4¢…è¡•Še.•+…pZVÚµ@pÁ¦ä¬ìÀî›®ÎÔ'›Û#ÝÖz=Îð/o•E“'zïÚp¸³±ÜÖÄ…W$¦ŸºÓ¡ Þ­|&öò»³d᧯É8¬F­ÇnwÇ',ps lÛD0r¶–ÊHÁI[|•Á¥Qåº@PÌëýhVâ–ó¾ê­uê4&/¡Æ­sê¾Õ®À ¬¥YÉøxy§;:ê]^ŠÁ’SuäßE"‰q™‘rš*”w¯1+©[A6“eBH¨Z­Ð{….Ë’®²dí5—“:áʵu4û½”kºñlÞ1Åtù¯k€y÷ÏÇ wŒ¤¹Öj’ýÎ Õ;TPõn§ [›{;SQŽœ™µVåêVr9w¼I¼:ÄœmõÝên5…µ½Î±1eG…Ýéëàðö ßjôa÷_<Q_goº²Ñqî|®ýZbóÞ¬•ByYtÐ3j+OƒÏ{4søfWáo×`µ’[\%¼x‘/{µ-ìÒ·’±ÚjDͬNm8o5íëN­ÎËî:ò–*‡rŠ•³xJŒÖ!¿:Ðåü’k_éþÊùÏÔWò¿(œ€3Ëõìk‹ÉbÛÁœ;‡KÝæÞ¹ ר÷CK©”{³6½¡g½§1TJº¦kr°›«ÁbéM6ÅY®uÅžê”Ij±Z܇ƒ«¬Î+N„ËãǪЃd Æ•.V³w¯É(¢5´¹W¶Ç½k•Û`¯ø;Õ8ð gï\_«ÂœðáNS¤Øà\«Iñ¡Ÿ¥o7Cå9ºìHPB¥. Í%töøZjˆ5·¹ŠP;pìÊ¡æ7¯Žžìå¤BÏ= eZ^^`q'LƒËØ3›öP_ ÍüÝOÛÔè.1À»¤ÂÆ`¿AfùúèXÏ{t¶7–áW>ÕÈÜ µoÆÊN*q·òÃ×Õ |50ï{§ÚÙÍÞö˜ê%BcÓ§jÖ Ï,Ѱ{ÏV0ZGÛgám%Ï×FǬ§}‹=­ÌÈÇRï/xÎ<óÄülûkÙ9+ózH¼—ó„xÒév ¬í»ãÀ1ÏNBH–J±¨ÉÝEÊíìÍë­™Iõ‹Ãþfmù­å4:Þ^ã¯gÆRKŸ½N÷ïÃpÕ»:Y5¾ÆýͤFs—vGEðë#rû[§–+Ó®®–0n®Þ‰ÓS·Q£}íçv·Œï™õæàíõlµçdÙTÙË«dŽSG^ò}sEÝtî˜í« Ež«Èr­«U»ÕBæÜoí"JÀ§ÞæT=–·+†é5aWZƒÉŵ8 î·;ôUO¯Š„í'u)€°uË·„J"Š’•ºÃuÇH‡öžG‘ Ú6:®Þ—¹Žc6–¡»™º=bXõzÒ½x)Þ€‡EfX¯ÁÁq¸¤u‹_VóÑ!ÎЯšûªÀÑU£žJv5RdgXrùÚ”ÕdoG©puçéuçƒÛÇsëj†Yœ­”|£Vå{͸{…y`ŽØJ£žw|¹ ]PVf|ªñ Ôèn ¬]Ç2鵊FÒ·ÛW;­õ*n¾è´ Šð•/¼,úïoÙmgZ]€ÏÝߢïÜÞã|Û¿K¾[›NãÇŽÃZß^ˆ7i;ã½Âu/Ðv¿%ÞÅmûÇÜN&ë`‰ÖÅ“¯©Û Îí¥&»O[DáZ¯{†J{¤§VyÒáÆíºš3¦`GB¶çö¦%võ€=ƒa¹Vn-ÕèÍï“»÷)^‰ß®êÙÿk¨¸?× ú ÷ç‘™@dÝ—ùfP™v¤•'²üB’d™K•x›=å=”ñZýqkBJp•Vs)Lž;Juó×tÆôÜ.TÌ]Õ’.Ä15SªÙ ×â…šGOylçuLJ³Ql!F³âJk×Ý ÀT ±Ó¡|xј+•íÃoä #mìCä«zb^8hÚq#z ³Zb²Nt*Ú[Íà g·Në¦ÏÃËjÅÔ1ÉÜBV½«À•/bWœ1û%¯Îq¸x¥RñõÓñxñ§Ë¼ó¸¶D)wˆÕEX<»ž~»b¥O>N¹$nouFV%Ãæ3¶²xî{—‡½èpÅSLŠ´²íÞò!"zÀio"§-J±]ÖUcA“Ø0ëAWeE[Û[Lû6‚tÓ$ö»Ç²ïÕê½Vˆ#WÓW:Ï1!ÊÝNOx“}œ²k6[¯^n7twº´¡zõßT45F›Pàéïµmzp'ìÞv7%[¥ìÁ¬ëOgwÓ¾ôöѨ•L5ê&e<²œQT¼®–½qníƒöÕÊ ®¼Ä;Ù´—Ökr$JŸ@ts¡k Yyvo¥ŒÄ•Y!ñÝì"»7E·),9<'`^8[­Áóò¿´ØÏ­ž!Qê[™Á×Rt1ŒÓIáÛÁÜ7ªC8åñ©L÷^hæ7¹to­Óš+1ÔºöÊÐ/Áç«}>uŽ€ýPÒr„#£Î6†ƒLÞçndÉbe:÷?{ÔáÝëΛm;–¯€d-®èÛ¾³¨w•éè:‚xBçx1Þ/ ÛjëZ2¼Òå—¤ómõœaU ® 3†ð¹ U%%[Šc­ò€^W–kí¯#Ž1.ëÆº?3®uìöÀäë—ÃÛ´]r=žß_Ã¥ÝdË`åb§gÒ=›²ãßâ)ôöêI:j÷­ö|¼p½(S'qGÕƒOVßqÍ!½3MÓ@LX‚çPV¬ÎŽüoºVu—òo²î ã™*oe Wwº”SœÏyÑ«¡ë™yåk}±³+!~XOeîïy‹ÕdùK¡9l{ï]kw8kÑ~¤H"¼ßÑy9Ͷéõ†úíœXRîçy,Ù@Êìô¤–'ÀûzïÏ"éÒ6ôÒû‰ FY0pG¦ 2™ÀQ•µ0|†Üäf»£”±]ßc|.(«šù%[·'•n`«Ý¸Ùå+Ýì"R˜Vùæj|G…ƒ©u—@öÒÏo»3:*ô¿`õj [†²kàFó®S¼o4ß,Þ“i,[ÝmÅ<–Ki °³²óxÔûÎ,¬—”3Ï6á%לòÞõ™'6–n½Ë Î¥·›øÔÛyr·‹ˆ=2œÃM”s=c›b¸ßùÖô}²­ÈÞg¨‰ë¾Çwj¤ OU䕺Ô|ëZé|ò˜\—Vš»ê•Ã^Zvú1Ç‘e¥®Ã˜®ˆFµôpœÅu PÎß{®,u‡î~¸üÍwâ’ǠߘÍÜÞWz¢ÒR–é×®¢ì€¡;Ï0æ›ù­f±ê—»J–ônÛºí/1'5u@G,ÓJ+;¯ˆã]Ãvðy×:9Y{éÙæ©íJ…¾79çXÉÔó#pNMÈ´§²ï:_LÍÓXÎĬ×tZ'Tv¸š|fØC.†ÿl+‰|*oËòÊ$Z>[½˜…2#«ÜŒ<ãEßj}iR,_aÞ––ðcEkpLÁl‚º »®Nh溡:g¿¾ž@ÃßÍý¢³kAreßí¬”äºx3¿AÎ-ÁˆGf‰¤hÈúOñJV{iÈ…tåJöÕc(‰¯mlƶƒá°ÎcH¾]G{9:ÅB‡[¢¹du6ÙÕ¢NóiKTv«Ì™½Ù‚-vu:#Éêý–9Gw¡ê梽ÓZçzŽÞ{IQ^É´ºy±G×€+6cºÀHCȯL¿dëÞ‚…ØeÅŒüýV:Âlg½ÛKŸº° ŠÏ"ÝôõÙì«0á!R"&è³8ÁV>Ò¿qG—:ïWûQugS½våt÷«tP²F[ð§r0wæí7¾e>¨*z¢èÒ§å×kGl¾yölW.Ø›×\¾îè\7¸B¥+³:)ØÃ[ªßÒu.-À®ï´3Ã(X'ÙåÖwª7W†ö™Ü…º½û³R~oÞÍ­œ)+¯t.U’à©:Í1ƒ™µ–r®”w8å,Þyrºûªûz’N®tJíûwÍx®÷¼ôÒ¾¥£—•rë)€2– ÇÇH­ƒÂOG[•yŠHX:½X±¶e”¯^EùjÔ³{\\ˆ9y1®×Ð>HÜ|MØ ÅmZŒ{ÛN¬“š¦ÚÙÛìð±ÍmÔcÔa]SÐë*½¨l÷w©±³Ãr¯©_ÝNâ)=†áÏ„vo°ªGKéÎV×ÑóÕ¥»ìu%î%xÖÁ‚®¼µŠÖF <ô‚ÚÕzø‚GP­û–·¦”,øå\ö{)ë©V¼7†¼ñ .ÝË®ÆKNôë¥uâ¹.î…\¢¨onQçµèç«›x¥é”®’ñN^áÙ…YuÙÏZŠmœï òmªLt …ßÛØêç4òú=‹´Mç‘ïJÒªýÔ+Ó»VP呵|±ùéXâì&·#{Ó7pÁ¥L­Îu3ƒm+Ík>õr«¼‘–Ûõš>ëÄ"K½nîž^ÚoX÷šÔñˆ47’$ìÃ;~ô€Ì1¶šÞÒ¬ÔÆ÷°«¼¼jî˜Z$Oõ?Óo«¸l­8zbÿ ü&1Ï¢ÝṌIÀohî$v&öò“¹]*WLŽÎFaâ¶s¨Ðw+¶º)#¥[“´&͈»ïã™Õ½ä jp<$ß¾»a´úryÒa“*]öYØžÑç˜4î´ë×êõØG×ÒVÐÕºãMÓ¡¹ÐØRÝ³Š—}FÒÓoû:å>Í÷7Ž{ÒYÐô,žyí•6“qiž£L DG2¶ºì#L®«±ØšÉ'¼GÄíÝŒñ~¾¹/¥5u*êáW“Õ6p‘e¹ºçk¡Y µpEF¸aò^í+a¡ºD÷¯%zm{‘P•ƒRëÄUÿ ýGn‰¼©ë„ÿ ç‹ö9»X×ð8nY‹«úö*õ9 ¡Ý\DfW[û…eÔˆ;ݽí»4þIs©™!1I4VibC]œ:Ö.å軨ªÜ×ï/y)Š„Ú—íVŽNô”³¬ÉÙ”né³sÒ-W¾ºïgDu 9…«ÛH„·[¸9ô9K6Ü´Ñ®ä¯0é­2nò¡kÒ–‘«òHbßjQ|·V×#Ý—@!Âõji}ªxO©îðxý=¾ñá•ß ¿]«S©872°[¦™wÂßgPËÞi÷N·¥Ó¾‡­ªmv‘}¹Šô+ȵ+kÍ®õ±a\ð—ïDù#—åG×~áõúeúFzÔ9Þõ{ØÙê“^ªrçú?ñî©f~½y•üy,ݺ•ÙþRÏðûªýW´møˆ‡îÎ7£¹k^ÐEM5Âì”%LåŠ[wqyr˜¥œµ(8*‹ÅL\0¸jÍΣÔFÊyªÎ„øQ=nAo.àç]o»’ÎÛ¾ì·ôÀ`òÝ4;fšv.Ï‹•s»Ä5MRqòM-•©ožý~„á¥|{<¶rëZbt­;›®Þ…aÏ0ÁØaŒý1ÜG3°³–»«Iiq1 åf`Tö ëeJ¼@@º-³Æ¶^Ò=ºË(î®$KÛ\2£Q'{ßB^äHíÒH›Ú# ½k[ZÙjàCÅvNöMî{ë´<€õÒð«dˆ¥ï\hVìÕÉ,®Tdz;Mº»½rêÁ*Gþ­¢‰ê’ytts¯ïÉñšµ¼û÷s»Œº×Xù„ðÉ7Mb›FpٞݼßAÀ°^]`ù'^ËëŠÅ•eNƒzéäò–JÞRÊíÊóí£7×Ck»ÖD•nÜT|ÙÜØÏSçF:äèf#¡W(5[];f[Ú+xÔ±JæÕèTvשšùÝt¼rwö—CY´ìJ¥ìæsPÞ陓¸ qÓxò43ltZÁÚ£[wgQ{˜ÑÆÞ^§Ùº§b°íâ_,¼Ã˲AXÀÒ‚R ¤¦ðS ãš:Ÿ;)h*[0  ¼Û¤{` .Ýì7Viía×Q—šƒ—Ôøb¼ÎEVjÀ¬¼R^G‚=ï)xûÊ’7œ¶bÖƒñ¨ÂŸBáŵ©Ä] ‡¡¹YH€`Pœ6£³þÚ¯åjÑûó˜>»$¿Ò•ŸÝ¡9Ø¢×b·±­Õ Ѱˆe±Ö(q§GŒ¦û‰z뫌ܙ‘vÛç ËîíÔ4Õxž3¶å^€ki‡o,ÖÚ¯øµœAÖáæª–ÙËµë•Æ¹9®»ÞaqEìVw“Y5©¸ó9sé—+¹ÌN¯uUŽ>‘åå¶¾É×=~ö£Â2±Z÷<ãh÷_NÕJì9i>Ý×›Dg@üßöõ?b–³Þ›Ÿ€QöIÆ~¾Ó½›ÉnÝ-ºä½ãotòÛÊõsœã~…W-ÛÃ'Q›]ÑkY†‘ìf=„»´wYgZÑ2Ù™šMæÁ˜˜qð›k6j>{Ù1>q̃‰D.×u4K²÷5Ý6V“T®\è*}š´*t•ê{—lRYR¸q+4EfÞÎÚÍ»{*§{…l³½Î¬ðJ ˃’¾åa/÷ÊÿàÿÃÿ»ÎšþÓÈïO6, 0ßk·•æÂ)ø\å’áW"ÁGFÚÛ"ŸVCaT"L[\÷Ž0„»ÜwÜQbÁ¨­-è•Ë«»Êˆ¡‘Y7tB¤ªç.q™›·Î6•fPod€º™¢îû)t$Þ.\\íˆzÊ{}0ð°§<¾`Ñ•±ñÕ/^IXRO"/o9e·k·‘yÊ=î·¶mĵ3ôxl‹á9›.Ê4hÒ—-å ÂÝ+ ñÜÖÔy[Ë,¼\ª6¬cZE÷…<î(›M¬¾tëY¬töÜ/ éjèE²µN»GmXÈËÜôO.ÛÄÜ$•®Ðqcìû‘&¸ ÞöÎê™ÉvÅ[3N]>v¦¡i(M¤¦ÈÉEnå@$ÁÇì=V[[Ê:è{ {Ëæˆîúµo3œÆVVã»t‡]røŽÊ¼ «‘˜<¤FAˆù%ªQøÕõ²œÉ[Zª× ¥X£[xÇUáœx_cºÙÈÎÞù£f2¬ž5®—eJW?ôsH ˜DØÑÛš]°†@èÅ'£¿:ã’ÉRl  ¦ôv¨ÁýÝ{s'ûgà³°þiKRâŒÈÂ+i9U¼bÓ‹¯¼¯KÜ•gÎkú}—š&½´a ;õ¤²n™;ò \Â…ä‰N!ôU[½ÙIÅV[¶‹ÈÄy1–kµBÊu±·³…Ó}ˆ`¡,m¾¦®?ßWùþã_ê‚ÿ…S‘Msƒ!ÆìTzY,áÙ¶,©Õf›¢]VU…^øÞ!H’ˆHHÀ!=¦.\´Îs!”ÂDt £Ë1ä† )"„ÆQâ’ ”C#&åXÀÌÌl-{tœ÷Ó,JÎÍ'!ûl׿åÞÅØz‘ÿ@ïvD"ÈŽì½h¹Qò0nín¥k!¢Áx¢' sÏż´{Òý ž³Þ\Ý{ îòˆ/k»o³Ž Ÿ’­Ñ½‚^ö•×Ù;Éc¾^\OÖ¯ö~÷×ÅÚ›ù$‹ÒÓ²Gx^p¿-ñ+w…wÓ¥æšñÂ^ŠAJ¶?z¢íÞö_‹¡w ­*n Ït© ÿÆ×ùEG?ZêÂ~#W‘¹ÚË ÒµNbÍb¦RËot„t—?1vº·“®Ó•‘¶s[‰L¥”•š›ÎhÕÓîVëµ^!l¯G šáåëc.kå¸ôW<•7ub›Š±º€`À‚¹FíR–6CRê½.{ ùÒß9C³ÐE9¶e*)¨º<Õó Q£´{§uõ¹»3{’»™íÚóÎM=Ú¯_¡*˜Dbä4llt«ªW Þ5G„|²à–“´ñWbr²¬Gw(]¹9߸…Y£É}¼nˆûª;ËAúuBvbñß|Ö žE{•žbœc|j °¸û¥:©ÆxÙÙDø÷ºú …v­íQ]<¸Wåjý)¾™Õ˜¼[U5Dz®e‡?a§5”^®£ôPky‰Âý¡,÷ž¯Or‰:*û1®±6Búzî—ŽËwV7Ávզº(jÉ»ÑàGößqëhjtîE˜$•'#<ãT"[‰kõ®÷½çà½޼JìÜ{$xö;ÇvÄ4a}‡$‡V yFÝLÇq®µWx22Ü:ay¶w-jx®—˜#GxNÚqiÍz©' ×iÞíŸ`|}žJ]>ûWð0' #Z†Ÿ©ÌåZŵ7[ÌiI^ìÁ@-gFIµÙÒ¿Z¶/¿¿z¹åt__ÌÝm¿>ÀX6³‰Í-#Zúù¤ôW¸ÉŽºrúîü¸Ï<£W¹K[Ò‹Ñv½\ªyùÅçˆ_‘¬s…ûrØFæ%Zåh`k®øÐSO¬Ú€ÍÛKW Ô®4¶ÞgÛP[<0§X¡yçå“+q¹zåzDéâ:¬¬úí'…)FØ^“ní¨m… Ì}CÆÖ¶UÅ]’9€Úë‡å"é©{L÷ƒÝßXÅæèà<6D"=u6&~í+¬±ÜèANú‚5¤R·—X¸öZÎ{4vÆw=75^ ÒöRzˆ]•.¬Â;3Õ"Û«žaé´ƒ±ŒH´pf ³cc žWÐ3_°î7ÛéY†O ñ&QC+÷ìGK@gP+OQ·`+ó¬¯cáBµÔàʇ»Í½f÷šõYÜÞÄ»€‡n 5uóÊ›AÆDsiò“´Žº3¬ ›OÝtzð. ìq•嫲*—§ÊÅ£³-±T}¤›êج|OjžaIæpJ:7jùlY£.} ¡V•Ýhv:9ÜZÓŽd˜žŽ‘ËÉK”ë]+©÷ê“^ã?y©+¶ÃŽTkNð ¯%@|òÐö.Îà|¾EÐÓjc5º7[Šëº¬,Þ¤ñ(žG3Cj¼²0X ºÁYµu…ˆÄ/DC››>  ²¼ïk…á}MÑß3=[WãÜ«ÏseÙw­“oLB„s¸†Š6)võáUÊnôA;9]„•„M'/¡‹Š$™ 4C íhî½¢Ö¥Ïk§yÅç3×p Ü~ó¬D¢=GÜãàšþZœùÎÐ,êP®möMXh z ·>ÑV³3îL}јèE(»*û[ã/+ºëaƒì­ M—“3îäLŒœO] ;;qtkzë"Èï5Í–ifm‘R‰N”êk6öû¥ô4İáºK%ëç÷E½·g˜ÁS¥ s‚ pí¢VG(bL™[ltHÙuÌ5:ÅTÓùk÷Ð/sý~¼©ÎÖïSUÙÈÈÝ Nõõ°ºnæŽçu­W¶’žåN¦çREzV Ê1³)y.u7Ǽk}f;ŒRÑv;‹Ÿo:Úçe¬ãï\ž “ÙO²tzÔŠ«;ìèÀ±ngÚ{+‰.‚ÚÅö,öÔöøêT¬'zùaõ´†èóÐY©7cáÎhêÝ¢Üf‚æÞ}¿ñR¦ï»x±Ë‰z>ýÕ:Ë`XmÙnJ˜ÃËÏng±ö€º±ìÆ%ºBî$RŠoo²Þ;|‚òëVÒcÓ…—ž¬rÛŽOzæØÁ1xÙ£µÃ6ƒ¾Ÿu±¤ç¯„êzg± r€nžaêt.Þø:pâñÙÁ鋃_lû_T»ÔŒ`n¾Ö& `oÒoî‹áê˜FËzÇ=k¬IjѧšÆœI›¦¨¥O@êËy}¿æà»W‰Åèyj.,ߢë[ÆmîÑû´Å–ƒ¥WNß %-úï>à·.¯e@çMá}¼vØäÿO.»LD.+öz!ªm‹W¬º(Tiô¡1P»ÜòÏY0âØêÏ6aW²žbíH­¤åb-?wm3mϲ*%…ì"Eo¯ï>Ê~Ý{}aÄÉÈm%ô;²w½ÁîR^H72egËlÝ=>#½—vË€tÎfs¤~FûW "/]¬WÌeõ›¦Ÿšy¸ñ¾™x\ºÈr;Çn®ìµpa*Ö}”Á!sÕŠT{J´1ÑrÂ=Ú´W^2µ'œ»9b$_k$…×<è:nç<¡¶·´ÝRàä] ¹Ô5K•¥W\VT§œkסÝjÒ¯ õ2òqO›ÜÛK6 Hÿ„ÿ}ôýYBˆªýê ¼hûÄGýŸÔ6úû»Ãý«¹îß1¬5”i°Õ¤1PÔ@nÂBÚÜi³n£ÙZ„æé ì¾9gV)´k“¦ú˜ìÙUÚû).¤GÁ«7g¹Ù‡­IUìYû¶œÛ3o`¤7híi©¡uEaõkTÈ÷—x[ò+“\Þ.”öä¶FÖZ¥¨fG­•O…lã9z1×S7YðÝM/] M;¡”ÊY{ŽC}ªBŸS|üçžzIõM»s=š/1”¼@¼¤ª*ÊöYÏ0ý2ß“dB†eø8«#ì2GO@õ¾§é°’…g£Ã›}ÓìŽJîè^_5N9ÎÀ†ŽÄ+е·7osëÜhØZ[P7¾ŠáÑŠ{ÙËü­öþÙ"ãø-&²³‰R߯mU¯ÜÛíŠÙ"£]Ÿ–õ÷i¥N:zÇ/gj—Œòó©}½Ü6÷2½ØÒžƒÀÕ¢ý›ÃiµAº•sWÞÀ½]æÂs×…õÓäXgãR:®Z ÎÛk yØ_¢ZWM¼ÓÒwyyø®ÕƒsÚ)p=–(;·' _'L»‹/t-÷T¥]ÂýN¹Y"Äz<‹Ý ÊÑ£ Ý|ƒ»;ÈYv=òAmëº=V.L¥8 šËºaÓº–ìc»¦ýìÞŽõ ^á4RáJ€ñÑ ¿]Úli¢ö¼ïÌ#=`gv[JØéI’‡pxãWRäÔ„Üç7Ú¬òMousÕ¹î¬=ï3KT0Vg/UNhÈmÞ\£ºUd­öN¨íí ò6ˆõ B¹°&,Nþe¤>¦ùÓÖþ¥¹FŠ ´ýU—FÅV5SõŠ2»Röòt:wIiÜ[ò‡#ÐíòU±µ³8íao[ºèk7ÓÉÌ÷ÑFBBñ÷Ÿ»6³îÙtUŠ]`§R¬ÒƢЋž¬.qÖ;(u¥£wt³ Tß ŽŠ áxm®¤¼Ÿnú HŽ3PjDc/¼,·°Ê.­fv…Ž™Kšµ!Õ3K\¯1Ùâ©öN;!7ÑJ€÷½nûÒâêOÆýöçØ¡¦µyÖׯtDOÉ 4hw·ˆQ/˜yѵÔK_ï›`Dö¬Ñ®Ÿ)_YÕk4Ô7ŽÐÚÞƒ˜<â&t’é¾Z¼ô²—ÐÛ›£¸öt~»{6‹/¼‹€¨(¯W ¼µÛîD®wÂôXÝw›õƒºæ¥ÖÝên¥¯Dt!í÷«fÇ”ŽòøcžÚw¤EWšºgXÝwJý‹í̓ЛsLL×,Ç‘õÓ–o @?*oîãSy%;:1ݼÞí¶³ÁÖ^ð•CÙš¹çˆÍ¸¼‰!\/Xî#;Í ¯R¶~*í~§&ck9˜íR¬ò}˜º7gÒäî«ò»¤mŽ~žN®·(¶uÖÐ4nšëžÌsP­œ,»½Ìk¥pÏ3çŽ_cBéŸÎï{p{W_$[Š á‘MtZúm‘Z=ïZòSz¸™¥^?J­‹ø«båÔUmcw#CÓ²ü3Ô†ÂqX¦;,íX˜·Níi <›0/z¶ßSè«Þ@ªšÑî}—\SJ£„ë˜Ýv?®ã§Êö»¥Á™ÊúV$£2:V1ôÙ§;]B^6ˆû3’\3« »â)`x¯rop·ÖYºk“b§Ü²ù)ÖDãÖ.»tûÏÆ÷qô°Z¦QÖ?q]xÇï-½DʳäwÎ_n°(J=]sk%:R²iÍ8ƒÝ±¶ÓÓ»ŽšQ¡»Î‡XéM±˜q³Útv«UVÁk ×c®ì ™mê·×¬–©Åª^ZÄþÇŒ”¶…¼Šë.žÃA¢ c%¹ËgvݺÞY)sëºÜïšÝC/·šöEÇ4‘]Âó9+ß:¾·Ëš¼«×ÝonçXtj2w½7b¶U³cö¥Àèº×’úº—5K[ÝlŽ”EdÅ·'£§Ý3©pämQÆ÷7o Ì·ðëJíd\.âîèÕiwnù¬»®0t/³­Àì]@g(þ1:œoMŒë¶§cÌà ác]'N º˜IÜ|PU±X™³Ué:ˆÆðÎÉ(Á•˜A‘;ëÄÈ:&®á'$ç6l­T±Å%Éí‚—;–ÂóÔx/y¬¯^u›fŸççÞ~®?Sö]J9yû÷É‘“UÏ•žÞo…”-›ôØÂv/zÕµ‡å<ºXÞÍ“å»Ï$y^¸¯˜ËâGHF#ˆïv«ˆêö Ë ªW5<|:‘åÄA¬5†<¬×Äñ×>}×tµº·‡Á§î{I«QÛª9>äð/ÉæÙìF»Kåí`g«!~½9U4ʯÏ£¥Ùr^Œ®êÜ+»³eÛî+”Ïb~O}ç=jµoÖ «Ìí%]Ë'c^WèVhsc/uØJ³l£/g5”ÝGÆOú߇Z÷à/?YÏÂŽxU‹DÙÞæY\©+yËæâº¸_ 죷Y¢Xp¼º¸•½´lò:N$µòÓà{-f˜VwŽ?)jvúºå$;;»fgžö@û;Êq^ï'ƒ&Ö¶0Dó¥jT’ÜŒXï{×pd3éÂP£n`Ý;òV:˜—ÅawD{Æ{é“À›ßSûz˜Å’‘Û!×sqÐ[\b¿ZÉp÷or `Pwj½èbךQòÁÐPÌX•;¥UêÁß }žÝ8®.ôðdYò»³*óÛÈ yV/ù%šÒÇÌïÿvÒ._~Ñà§‹šõSв–¿{Ü<ÚyÙÕ·ió2cÚ°Û@è>O9hÐàÏ•[©ØR°Ô(øöæù3’ç*ì æŽíÚº ®ï7“{ÞÙèãñæ×·Î´UqÊÍVPÚO7'mÕ÷w` ×RRì}™×vºs¥6&Zá]Fµ¨”©x#á2˜òåpº·æÈrŒúS®ÍHÏl­÷"ž÷¨sºä78)zj[Ò¨Ýv.b²iê“a㦰V‡/^D›uÅã«=…v Ñ»ô5®>™²åÿ>£øçîåÎKÉõª½Ì°ˆ šý™•Ìq<µénò§SÕËö iÐ\^K—!ë/‹q{±ö…¤g¨…%»CŽˆùííyµq²Z µŽ•ʹ¾ à>>¡\Æò$$+«RÖTì±§…·Í¿ ~,äÏeY†VtCfÄóy«ㄚ‚©ìT8aAFêúìåu§9ÚZŶ…fj¢3/%³×P‘æP×Që?0Z ý{ï µ|ûEì[|Š–Žö¿UÑñ›Ýζ,”‘¬ãÄ^ÓÕ:Vnöý•ÝovûÒ~÷ÂÅì§©[й]b\íšøe^WSç ¼Z“]½´ÚN<í¬å5QÜÖÌrWFB{–+BgPt”š®ð[ Ù™ó2Ö6vÇŸƒº\/=¸üÓŽn2g¼vƒ¼>EÝõ,Åu™Ú{¼Ù–ë,J#y§'xR¥ŠW³.èÝ?t–,‡ö„^K^òßT¨]Ä8t”^±ffHðœÞŠN¿^mÓt!Ú{Lù-gpÓwà@-±¯CÓ Œ/¶ùZQ‹’‹â§G¯“w×LçX"\|¯¨³·¦ÄÄÎI9dFâ-‰¢o²;wúSž¯ÂD.½¾„~yî“»»3Ui²µKn`n+&µñˇ¡l­;Y†ç]>pS0õ%™Xúò»·…î=G£J"æ2@ÝÌOËP—YàAÖó=ç÷œ8¨½Rjô '_¨«*:Ž®dI÷P¤°=¹›lÎLÃ×\1 ­*å“Р)¦å·ÝçÕæ) «þ ¯Ý/Ö‹¦¿¿ãëß‹ä?æªaŠØ‘“¶~Œ¦ã¬µfÓÎÓáí÷†(z é |¼rŽßÊ»*¿.AŸEGM÷½Ôˆ[ïSßT­âLÛl¶nX¿8S¡ì 9Ð×whµÝ{Ûí5ƒËïzy­K?fdÅòE´­”U‹Ý¸}kÐßÜ"Ï ÙÁ/UÖ¶ÍéË©ñsºJW=ÊFtרn®¥Cœe`J·¹]´0?8xõ&n3܉”äqæçŠ>Ú~Þð¸¯Qì%sÇD˜^\:/y¾ L1Ÿ9Òæ;JÉïo ý´!}[1Ýí]ÃÙ4Ö¤b7CPaÛFÍj y┣6í»«mÓH“££Åui‡¶lÍKƒ¼æÖ® ïùAô›óï9qž¾ÅpÒ7®wëŠpXšÀ‰7EÌäÆÜµð÷·Â‰JÇÄW^ —ŠREãe*±¹aY bÈ·¸™ŒòÛ\UÙZ¸»iìµ®¦rZ7‚oTO)ÖµÐÁÖØ“2ã—¯¯ÛÐo‹ÆN¦%6M¶0RÕ‹ödK·ž³ôUäMÐG×j´—õà¡Ãqb‘K3w:ÜäWÚ›FÖ{Ú·$}”ôN¢“®ºŸá @L·OÛAuÓ}¢b^“),Ý–bj~=^ò˜)¡ük¶‘Ït®bŽXªÁrjêr=:JIL³dܨºmíÕÇbÁ=Ô]ÅÜ>ïŠ&7aVu 9æÐ.nñþ«¶üKViøvôßlxr¶ºÆ[×JµºÖ^ðA·.¹ÖžŒ*¥w–ŽîË]Bºç)¶œ©÷>ŽÞÿ6«ø½=™é¼_8«U ºGК(‹š”òøÞºá…ò»°’æJëÓÕ:“Þh%Í:f®qÓF—k]-Öe§O«_;¦=ª]í.~¹ìÞmc´-znN·‡rÖ;¾P[Jå]^,îÑ(n¿›ÍÀ†ÏYxÜ”úòÝk/ëͧS¬µ7X°¬{ìïTl ЬìUÁ„Ým[â]?'ÞWbó&­ÕÌêòFðå‡ZF»ŒS·Ãã[eô!¡Îš–öšuËíõ‰Ž—[ºç¼ªfç“è£\ÙÜFùŠSÕÃj¹XêÒ ÷>[[oˆÜ% h…‰ÂÅÜR^#n¥ºoÜ}ÜP íe’)fguÝy¬Lö3·k}ê˜õ¸&]ô8 áì~Ê¡×êg«©Sý÷~¿šw¢ÿwtPä7{+{›DgM͘Y5)žU•Ï}‚{‹g§•Ê:è4`Ì;vîUÑv°´±èT iJZ–ÝøSw,Œ§ë÷f³žlïu`Q*å­J:=ÐçÀMÓ ûšÙL%¾U½ä†ûYw±—0û³¼ºµø»=˜ý1Ź~Æ(ô&3Iõ„övøØYzÏxÕň^:†Û¢ñÖžÁܵè^Ìq¯A~íL÷s—·‹Iqh®¾!¾]Ï. ÎQRWMÄpW«»í¼p÷/SÁóß`¹©!/ ¯SàóÏ7|¶Ø»¥ú÷X*ëµë&¶B8šÁ¸¶Ú ƒÓ£…®ìÊÊÙuúº§¢çç_“÷ê_€#PĆŠ¨Åû|TDò¼ùŽŒØêÞy3×p‹ob¸êÀ Ø|õñƒÁ‰‹"ñ7RmHº“(¬9GÅÚ#áâS÷•ÉË;ã¸%{.“©WÛÝXmNà ¯z[<úÄä]’Ý!iáÏp¤§¦ÓØ€ÙÜh+|ûIpka]í^vÚX3x+ìKÖ`UUÇ{ÝÓÅ`óGétã"ž‚‹Û®cFŒ%7—{¡fí4±)œžJ¾£œ™Îr¸èÀ» 4$(÷uÚ5z0]\Ž×LèC=Ào KÇ”X æ{©ç¡òáï0X÷IŽï9òFNâ;±ÕtN7”8¸TÓ^Yîo»Œzž(ýŽX|]5"ú³zx^×âÕ×ïѬ‡÷ìé9‘̵%fçbœÍG'¹ë'½)Oess4GìTk]WîÞ|õTòó^œ˰°r@ûÀÞîïyX¼kÜ®†Žë½cÕr½Áï²x³ ”áL2·q>nx!ÏwÂ/{ÝjÆ‹|&yìö_¼üërZ)Ñh6+‘)N×Ï0-0Þì­•-Œ…ÌéSEØ!W˜f¡I÷ËÈï¬ïÞ«1€‰;Aª_‰º•o-ï­™Ò¦ÊwÍûSêö­´kŸ¾`é«O2aÌÏ3æEZíê4Õ —ý zµÍ¾îZ´^ðΓw†]ŠÛ‘wq¯ 5xwÂp g\“Ôô]fdwÇ„?«Ý]ëòý“í¿JC÷IùƒÔ\ÕŠîW뤤¸sk¼¶Æûmí1âÃÕ‚å3—ŠH{ŒTE£ âéÛ™XŸÓ|ÍÅÝÕÞ)šSãs+:ÃðûÐuߤHÝè–ß§€ ¶Öw6tƒ·Û å7è}w"å3`çJ»„u0aÇÏ4f¾Åƒë¡ãWœ1 êL%3[^Á®æ,æb7«*JÆbe¡xy[ÜÅ¡Š{‚7wµŠ•o"XÜ0Ý X2p¦zø9ëë|-ãëëÖB¶Øai·P%ìAó¤rjª‡¨´zeÜNŸXÙg{†°²dõíúœNk+ÄZ­¬Óa‘ÚkmZ]+tà ç‹îÙ£\¸"ÀMµÎm1\ Ä¿SíŸwkðÉàý£j¯Og S\nÙèõ ‡ëç0¾åÂÌk)±gÖ2®´f©(€´/žîÝç*ÕîêtéX„ˆPWå‚W©Ù)mÄrÞ±å«iõdM\³º÷Vð3k^t={ ¡‰{¡»V*¯’‹ùê‡!{/@çñzðÑto Å Û1˜ò ïvd—}¹ì‰ŸpÖÅv\t;`Ø$ö;R–£± 0½„ô­²)õgtíÌÔDμ}]¯]´Ä¬¶ßÇ Uu£ég@em´çŒÀÖ‰9‹XÎn·ëõ¹Ûg³ '…G®ÌÚgL9ήI’k jwUªv¿"¶¦Ýz²ÞC˜É –jmÃe'.z3Ó?—ü¯oõâ÷ð~ŸØ?‚ü½¯×]PwŠ¢~ÉŠÌ{D¡F¤æÝØÚõ‡Üð~öÜÏyk¯q»*¹J‹;º^¢²Ç3¹)ú:âÚ[«¡lÇ“{}A}}]Ô©¼¤©j£ûsž ÈñƒCjd³-ôfÙ®ÔˆcýÇÛoÊ»?¯ôw ×g%i¬ý(ÅëÍU‹ ëÕ³'„ 9—ÏÈŽ<ΫY±g,Fêð{Þucº áŒU¬4Gfæ÷-¸›™º8åÄzÂé+X&Íkkšõº ÜyÄ™}'YçÖÇ]žtõspˆ¢·¡¬‘PÝe쬙(õFf{mÂóÃÉlÂ缊ÉCF¦n_jïNáY´#~¢.Ë4¯+h÷²’ìÕJžmò ê c}ÚAÍ]Õ`VX¨(Šhî/QPžÌsx ñ(æDD/`gW)•T±ƒ£B¨y„¢]':N~ÿžVgë­ ‘®4cáªy«{Gúö{=[¯¯»Xltkg†7¤–xT»¼Bzu’6<~ó˜=.,TåFÑÐU‡ìº~ÏaÌ‚a}÷hFá×,°8Ó§—®¡ëŒÄĮԡ¨çh3æ‘h7t:ó’=:•AÜ.¬ÛÇܰ†Y^a÷‡c]ª>ÍZõß‘ó†ÏiCÕí^‡s¬rT}™Xk»ìC;¸:ݾOdî" ¯cŠA¶°1´ptyÛ`JçZp¡q°,ºÜ\ÀÏ[«…ç»ÛuÖ‚Sa•’Õg©]g eN¹qªµÏ»¾]q?bû€ÕÝŸ×v/tIíŒj£¶éÍ•j#ïš9>Ú]X« ÕýGõ~ýyûð–¥uåF€·—ù‚ºáu'Ówr2…Ab¥íÔè5Ê»ûHö²›4|–ޝYYÞMJ*[Âó©ãÚbÆÍ䯳³49~¾_%¶Ž|÷D·ÈóíX‡97˜8ßqäBëéZo6îâF!_ê;ßJS¥ß°izV\äcÔ\YXn¶'pÝ–/:¶¿u?[á%œçOÄ/b᧤¼è®úð¥3jÙx¹øº°¤œ¹P43FÔU¥ÕèÁ¤í%šÞÌvśĦWWr—©¡€{ËÊ‹Š^¼î~k×ä¸å³ÛÎûT£u¢‰Ï ç˜GvÞ”xê×íàå.>oÛÍæ(„y~,ÝÙ±‘³„Ó·i¹7?qÇý¯í/oóÌ~¡ïà /å ¾çZÿž‰q'М:.ìsO”Ì|÷µ7W×ÖÞõœ`ŽuoQ.°¼Ò]IeëÇÌaU,xïJïC2× èç±Ú•µ™”r…òäÏ]¾xglµÁI×5ܺC³—Ë O 8¬gà'Û7. IG¶ì1uw›¶£Þ¸ÌO9ºyy_yš6º¢Üé©"­T1Uøôd9WÀZ;)Úô üýB¼…æžíjfõ à¶é^N;iãêØLûsf z9–p‘c5¹—zï¨å¤:5*&öÅ9Syu Möf—3}Ð9>A]¤—&/Ïöëkµ‰°®=“°:Üùêéuz\í‚„0èÇì‰ò²ÍußdÎAcEA°°®2j:ÝSYõˆÒGX®|TàE ¢ë ì ,-4úólÝ*y·×ÆûŒî۽⅗ºë¥ÍFP!<” :¸fÎ13o~馬ÒU3%kyµqÂ)Ò²4AMœ“JwSÑó©)ÊSÅ] ¶\Ô·%äà Wn$$é*w¡ŠÅFÝÀo­;R•÷NȲb7mÖ¢&U©ˆ£ÅгQö:sBÅ%Æô¼91ÓêëU}¶±wYk-Ô­R饊þ• œ Á‚•moìMUîÒ•VÒCÇMm:ÐÃct•w­ÖçÙ¬hAË_â í'Jª£š…ÊÚãîAžëŠ÷=g&ŒZ¨U(UIÉ/.ÇF’HÒ{ftº)ÝiG²ÓqKê™ÛÆ # ¢Î£k*cÕµ¼ë7#Ʀr’«8âÎÎÍt@Ó.û[æø‰*wí^Žñݬ®­wœaë~ñ¼gÊ’£ëôž{Â{Ã{¢t§:—ÓÓ¾én^øU{®mûdyÛÛ÷{0ÆS¦ ß¹´"£ž"ÚúË#ãrW!X­Ⳏ§“ +{­?0çM_T{Þ7™Ao×:f'ÚùnË®„t|+Y=YnóŸ$úíÆ”,_! ·Å¨{µtB×*eÔ•%ãÿ—^[›ë¯È7÷æá>6Æ­ü«UäXû²{޲‡{ ožÛ?ê¿ÊìÑ»_ Ø$†¨Ÿìÿ@é¼––®èÙu¦nÕ:Z8êu*ZM «¨Þ?¦/ã£(άÚ±,Èr~U|ÃÇ›OhÛšŒi]`1„]q»ÝyÅåp—E¯’wݼ7Šðé†)±Ðl4ÒËHf¾¼ÅÁã#}â’ðu½Çbì§¼* bºuí-q‘Œ7¸W2ï4â{c½zNûÓT/Åe÷ÉL–¼mC¬ÓÂæå‡ÓÄ­åæ}xÑSÁV𢌰38é´žB8Ù'.ÓÓ•j2‘Tè]p·œx³Ûî$Ïl;ÉqÈ칤{mëñ{÷%Õ×éü¯åþ%Ò¿kX¯ÕùÃjqîÌíY³^j§'qLc:«¦Ve÷ðžôõÑß'“}͹Î9v;×Z‡r:ò^vr|ßsë&è!z ~Û£Ì,»¼BÎuÐãçÃÒݽ k³J§[ã€b»[ž{ܧ{®¬^m* ©Þ°›¯f3º½`F*]­fÂ'¹§™¾»œ[‘óR³Ý—«ãµ.…Ôµ%Ñ5›•eg¦G܉ȪnÿY5+ƧsÁà¯Û5>诅ªOº÷Zåštþ¼ì®a^úÏiª LʺÑêc ¹NŸ3—^÷wŸO¹ÞVZº46ÉE2‘Ž× ¨–ÊÙоÿ+ü©wYÞž³Õê9ýýÝåt`¸éä÷­cÆ_sÇWÂÞV!åLõìïžI³[µÃ-KÕÈà<&sÜìÓÁ€²w²Rö™hÒ©sU÷ŠÑæ’]:¶ºªé䌲€FºïEOa­cÞŸÔõ~ÔÏ¿~Õ—žò"Ÿ¬ûÉWX·ê÷^¿@½iNü‚˜#¸þÆ=iÝz¥c2z×qŽvЇ»é$ãJMÒ ôc¼ãïzƾ٦¤v{»35Ib õwW?Jlvïyn¾c+ÏJ©€ ÕÍ?[Ÿnæ­†Ú¬N½²]’7aZ1­÷§†iÁóŒ)d=ørÐÇY¢ »+pOEWãøOÞuµ.xÕùXa³?·jç¿Êÿ>ªïLYMÖ~]•êüÏÑÞ\s Œ`_ØVX«z¨øVZu–C°JŠ7à6¡î 1„ë¨zÌû×yÍᎷ8hž™bz׆66°%£µïBÕd3³”ƒ¹M½ž>‰‘öbêuŒV:õ~•ÞJ­ßzºèݼag;/iÛ„bÆÁÌXlÕtÄ´" åæ^¢ï5¾„öÐkÝî™ €7*¹Ðiز›2†+9§>‘PÍ+ Ò…¼¨Î·•sð¯1êÁï/ZÏ×í^4\ úynü“UÂî¥,Sq3”»;¯ÜU×»À½“Dññ¡iá'ÒtY³IY:½\ôà-PØÒ]Ó¹ìø›fÓ|1͵âµÿW÷Ô}ÞýäTüMròda ~³9aåb±œ(÷:5Õx»w·O=Š[Hß»áÃJ°eœ¨Ws©ËF”©ØÈF*ýWPW$û׃ØtHÖîEí…‡¼Å¶ó­º%2.J©Æ1¹Z/Þè°t0Öùó;ïFü¯«W$\껢}¨³Âó‰ò^;ì] |õ^Z_y{Û}“¾•,·{0E &ëÙó{;]ìÌ*ÍàiJ†ç‹¾Ú[Cbhõ3¯ªtÀ®Q}—W×x@IsÁ±,Ê:è:±s²/k‚ôî^S†öÖÃ(Á+Õ¥óp+²9®ÌÜm\#|zÞXÞèGaráWwªøâò[ÙÒ—Ðç5C„vÝ1Ê=gt¯CZŠ`ºƒ.¯¤DI·0KKÓyKÓ%j¹èô.îYÀ:–‡´MçŒW}õUgûŽú…u. »Ôó(•ô¿ÖsùoƇ? 7¯]Sä4_agÍ–kH-Ùy‘7YÞYÔ„«ÙË¥¬<ù²zègÏŽîZg§BX¼lïöf³´ç¼ º÷›¨ÖÎæ:Ï´]¢ëÊïu¯tëVwšÚž‹¨ß;—S„Zwjšw†#O¶ôí7Ê Þ‚æÂ#µ¤ÇNkÌí û‹ÙºŸl¬É=áŽøì½ê^Ø’'¼Î[$ÍX…›—h­]dV ý‚ý¹xÌÍ%©9¯°‚ö®PW±®À¢5ZÉîÓ”ûŠJãæÒÝ<Øá]KFk[°ñ@®ïÛærém'Š{Éø*ÌÓ9 À3[óÏo‡«×Ý”®¼“Õܰú2ýI^>¥5iì×xŒ;oíYýX[Âw_¥„qºß¼ƒWtƒ×ÚPY£;%Ƴ_qH'yŸevòÙS+±ƒO¥Ð²÷®ÂC;® -1vhv-`ó¾)ëc}ºUm­ÒÍ+ûjß z_[•j’ß{Ef'Y·Z:ç@ÌIrY;âæ`Þü<ë8 ºåwòîPWK[0JçÛ¨q£ŒÀ¡—R]†Ü™2ºµL|;†3Ì^íã=Úý·æýaûnhs˜üåmœR¬]w¥êóÉ9vØCÔXí_ö*E†´ÓZz‡+Ë[Fé¿yCžww U¼F»ÚD›ã9èË5«§9ÏÁÖÌì*o{·hv±ÈïVv5 ä„{±Ï•¬>zêâøßk¬»ö§ìÙ%­¤ªû±’îØY˜é騎×kª 7Nf/Ͻõ]sE ïuc~’»}£E–äÕåìyq÷pr?.à‚ùqÅÖôŠm 4ŽÙwh¨!li+‘î4s ÌÕ8ÇÄÒ»¸Ï AZŠoêvKÝ͘JÔY¯Þ¢¶2.êiÙ[–»1Qö÷OŸ‰;Û^¥* ÷©îƒÄî’©Û]s©u<Æ]÷QwÏ:¹»he!gbçL³óËuÒÑÅà½Y‘ðVîf–wÃ|Á¾î1<®pcꜧR5};væÀÍG§SözØÜTx0#4‡]”«ôƒQ[êÅ^Jƒ 8"›VûŽ9vÀ'3ŠŽ½Ùí~øÀIrÍ[ñªñºí¾{¿bеM3i:Èót¹ÂéZ=À…¼ÏF>Xû/P(|À®„‹Ü[9÷V1¶­²ÁÒVƒkën†ý‹áB¹ÞÃØÝ«w ºìÂf7Ÿbyµ·*'\Æï_ÌñéB®—{°ÕÂÚw[½Î»Ã_*Ë8•tóãìØl–§jÁ³“ÊÚ˜Æ"…V ñ§~›f: W]!ÌDû*óqÉ㜠÷cGÄt‚ï¹ÝfR~ÅB¼v=¾;ŠMk8Ɉ[•üºÖ?+ ÒcËÑ7@úû]bE€·=‚^B/1,¾]àsœ¬”âÖ©L X‚Ñxó“ÊÛµëMà‘:¹Ã¾rå¾öÿuûÙìwÕ§<¶Ÿ0Œ­ßSî”+ié¨b09Sr|¦öm,­Wµ„wV®Œæa3)K´äxÀ[¸€¬ A»ÔntÈf«5Äh®Þ+¦ÜÀ¿Œë9ãé zt¯}wI*üÏžJæ&§„^ð1äÎ<,ð×zo·†ó#ÞùÜ­Ü\, aÞ‡FöˆÁ¹•#iëA[|¤€¾5»ZM ÎÁ¡¾ÙX‡×ÇX®ÇmZùr‚½¸%•¿‡rŒ_îçN½) —%øíiÚxwN­Fà0¼9ßMÈLÑÇðw£|TÙçj3áà êŽ8ºÓ¸îJ¼ËBû7A l×atöìì!4dzEJïJô^Cë/תö°+ÛU{bR¿û§jq›7ÒˆåÖÄÅô³Å‰\å)]“OX¾{`‚ÜX(-"5›[®òä›{m³—ÊÂÝArI×ðû2w(®§ugcF¯]›x3×ç¥GÔç¥ò`[©ÍÑšžO)››Ò±ö87¸ãVrêñ$  ­Ý:uÏf !ó"• LLœÍnÇ›=Úî‰]@õý±ø˜ær®öÇ\Ž©×SlÞ^[„f1G||<Ã;¬g±&b²¦.ß³‘HÆè¢Ï¶m¦î·jmL¥>³ÚâZkÜ.Ѿy’hšá–Kõš‚{ÏÙ=²Ññ ë©yo@èæØ keZ{^ìñ~Mlc.·C½›Áz™»ñ¬»;åYkÎì5•@dL`wYÄÌ;ºà{u©&‘PY~ xJ¾¾«£#^N³.°Á¨ ¿¦¶ú: 9Á¹¡RgHÍ€ -ÌÌÞzg‚Šs’þ%íóϦίÊ}Á /¯wUMˆ‰‰ï&¥t½ÎɰY²Þ™wZ¼¶ã¼vD:Ș.)݃**;€nP°íVª2¬vu^)c\–ñ¸²·£L5)Vªè-Äð]i´h)šÌ÷& á]ˉÌáx\pÚîvY2+TÃæìVmv‡J ö\”%ZÜ é©‹&¯nÐ×,6ƒ/Ô*W2ZÒÌ"¢çtVÌ–ïhQ¬»ÞÙ•R,‘ò”5n\Ð[‰ì^¼‚Î|¯½HIÔŽ‚½‡Wd½Ói GÕ£»XX„#-϶šç bæÐ]ãÖ8yGà)ÁNv®Îs6›7R.ÍC(F$íÌqéÎË@*Ú¶…5j‹”·¬ð0%teó8c–f- ì)ØÑ»‘{©{ïWC¾xÕ×8ü»Åà†õ7î[ãŽÆ±—ï¶ü<÷yãYjè`¤Ht½dÉ—}<+[õ¿*œ@¸_„U¦ø lZÍsîÅ!Æ8qÑí^<Ó>ö?6Š:^Œ«Jy%.;އ”º#´˜; Ó¾8è÷P½Þc½+¿›FȪûIk‘%…­Å_¯4¢1~­¼è´Cmž\Ž>½“H·ûi-ó` ¸z®ìÂÌô¿žp¨ì¼+/J@Ôµ3•åÂæÙ¸­NoØewµ‡<¸6p%–:²²Â \y–œó×ÂÆû=]§GÜ€"}àœÓ š÷•Й úé=ÇÕ!× âeäÚZ¸Nºyºµ®qƒJ¢=ºî3H å´2wµwÖJ¥Ä;Ö ©®Öè4n´M?65æ2²=;—ÍQÇv“ãSÊ­¦÷Ó(¿±fˬª½ñêi™çb÷`ZcʕӸ L_@ùu+Ìöï{Üç‚oÉ»6èJÖ|vm.T>ÿ}Ýë­¿xWÛÌÉhäýB¸Z¾ æ åõåü£'Ã[9`{¼‚Ö6 w](ØQõd>Óé$¼lϘUlè¦sÛ'VÛœ¶ ›õ¹Jñ,•œšÌ‡ äU”©Åˑӧ—m©“ÁÛ’W)¨½¡–Øu>OnŸvV/eỄ(÷ÇÍÜ_ÕãÝs6•ÓB±9;5y–‰0q»«¢;ŸIÉ\»._CÃEžvë½ ºÊö5Y~ÅgܲàÈhÆóéòyï(ùRxÓ\b¥”ãiɧFV£™HúSí>ñË—Q¸îò÷6÷¯±ÒY¶kªóæ‹~ÎŽî1$S²ö¥ÎTñ¼«˜®»Ÿ_˜ÙÝ~^z´¸âƤÌS¬dêžá–q¼ŸufßKWy"—o€‘eÝ·\Ç^å+KëÎÚܰ®¾ÑP<±ñuš”âÂMõš²p®K˽CÕt½^®øŽˆuî”¶ÖÕÁgÛ~`pšÖ>Ÿ:̉Ói ­ÑÚÓö£O² g©•îõ×’¹ìTûÍgÇp_ªäÛö Vüñ8d‡ÚlÎ÷ˆÀý}²Ÿ’Z%Y=9TаÕîÝ©pµ½²ÚwÀ!±N¶¦§[–i+§š^ee8œ"‹­‚sÀÁ½×5â½ \+i¯[XÚ{âFÑi7œ°ÁWY¯´XÀ·±X{8F$ÞïxãáÒ)š›/·».J•‹¨ðî÷¬õµ×Ê¢ÍÏ'Ãw©ƒ;“¢/~ÐM«ùV5®gªaîg”&‚gÈ]Xîô¯E\âï eî{Úúˆé6|Ðë[@9‚¶ûlX…ÐøZíFˆ¶²/yóÅÉCâ+Üí¢†·Ç0bHÐ̾*W|DYx­óU‡é'®W– }Ë1ëí·ÍLšÔ™n¼ò -U!j—Ùƒ6åiÁÒwg…:æ_Oc(Xqžù[WƒNìÜnglÞb×]k¤·¦ \V6ç_–#\ògvÚÆÖ`««ö'Ã'(Ëx\´Áûuë·<¢)~÷RÚ»¡ëNAfÿD / 5úõõÒcW¥o»gŸŸ,ÓàƒÊ˜ìrú³V:òK¦®©x'Çh–*'»Ó¢í£²c&bFÝç#®þWì >²'h+‡Ÿlœ{ƒ=[ºÎ¦û’^º´ªa´¯+¹¬mËWÖo“iÓå¾÷¶î¼0õy-&×”V°ë7$|7n¤¯Èí]â¢ºŠ§Ž@ƒ½Úe›ááº8'¹±c㙀‚–5jý3Mû¼’«×@ îž©n½´"é—Ãiô7Ùñ­ Ìy¡ÁÄšx¹ÀqW‡ov_Ig®ËW  40¢Û­5»S}Ø®YŽ¥Z¡!Õe*ëÃâü¶{iøë¬×ô)нD·¤ƒ,n•§‡ T‹«ùÒleƒ“ºVœÝjaÖîÑÍ3•âîO³Z¥L AÚQFqy-îÑ«WYÅC5ÐnÖ’šÜg9VeäŒcØà|hs\¶uÍ ],gÒ΄Ç][¡(.}{Ýt†o2_s`C­k6Ñ{w¼°UÝ©µ«ªÜÉxÍyÕ…•ìwBÈWt‘ï ήÆ9ºå”~ã«yîã³@vJx²k$xܾÞt6|YÁ¸ï1è«w¤m<½ó)–;bo#®!Ì+8U΢­Ã]/zõŽÛ}Ø…tx…mNÅÚýÐz@tñŠWfüú¿> ôz½ÌÛiéz½²v]]”òÂædÝ’“C »¤ë±ÑÚâYœÕó¡KU]kœÆX*:êš+±´Âof%@ÃïkÉ…à¬]/ºå1êW¾ÔkOQDÆ GSõõ Á8öÙʶ%”) 3»’óz=gÏ_¦Xö|UæÁö¨,ÚÿK ©ÛÏß¡À†Ò”2ÿ>¥×Ûæ÷Ⲟw*|î|C‹ì~õÕ5fœ±’û²é{;8yéè=K€^JW|Âñóž§êÆ%vÙçÆ<¸ê8=w=;LóÑuéK™„޶±Æ²»M©Û°ô"Þ*.Õv}\£Ýå"¼ÁxêÞn£­¹eô‚”¢ºÕô·81Ùå9qËûÃnxÝë¨NÖ£^Ö=ícÉ5Ýù¡&hÈ3;:X§^†è|øLNÕƒ\iÊÝ’eWTëØ ]Þú‚†¸Ó§ün[nz˜åÙêèb)EÞ—½}Û±c’v\‰Ö‹9„÷e^‘¤´6•éê°fê=°3¸ÒT¾„g6(þÀ\~ßäÞüU oó?˜Gô«õ%éNd×0u‡ržîn^ P¨ðôð4ÆÚ®2†ôG»ˆW-]:>Ȫöèm7bߎyƒí­5ÛÑ;½S¨v&êð‹&tÍ+¸SF·†áN¬*hÉdÊÂMéɈGY£"y‡Ëµœ2Ú°o);·ܘºÁf,¼«}ÎÖ‹}·ô¥'kŽœ¹9M4ÏãmKµ}L³rá÷óŸyÚðÖû5%­MÜ÷yPrÈ+NEdÀÅ¥¸#Y2®¥¾X5\¦1ìÍqOÞY^ç¼¢KqUy©G#~ןÏǾUã= L¢µÑÛžO^ÇNÍ{²šôõÏ]ס º»yI9ÔNŽ3«¸önXV5ÖP„Ôæ`‡íI¾¥´d§Eõò,È&ÊlOý÷úW*Úðò¥m{ïóú¯—?ñü†ˆþú¿ÇïTjŽ\ˆäÄ[Á‰JNf‹Ò] 7ë¾ÁF’Á/°M ̹zW¢]:êYh[ÎÞ8ZV§”ôåÞ8ýFn{1Ó«·Ž:"º»/¹šœ¦§O°_oOs£xyRy•¼£­cÃ÷ 0÷pQc`jLܲxªTÞ­àB¡{`ã­i=¬«¼î}xéÕΓ×éEeñ@íHþÙW³1‹YAvtH¼CÝWà+¾EzŽ'X;3—vO;>ìù-T_¤±¥VW—³6a Éï®ñ^6ÓëîU”–Ô³:Ò¬»kºíužéyg›L“=Èf{Ëâb“½ô[™^ÿh¸Uß艟ղgòÊüÚ…¡8`T/Ý{ ®PäàÅí÷Ïh»)«×½Z¡îHÚ;Ô.ï)ö:{R–SçÚº°©_ÏQ|®O=¯<Ó¸ý±5ƒ&Þ ÝZ˃2ÐÝÃ÷h\f÷*qLw÷<9Aë¯R;ÄÞè+Ü×:M%õä=RdvW+’Á¬µsicOQ¬ x4jE½7 Þnõ³§*;äìnLÝZº6È(‹[]Ä82¹lüÊô4{ÓåZn®û–v|¯W/Wu1ó–ðëÊV'œEge•2Sé0Y‚¥·‹ Wâ­Œð~¿JWtŒOjæ{×pFª?eŸi•mò>¸Q«ðòwÂ._Ê{YϽ‰ïo9·{†© ƒ9KëyÂéê ¹Ó]\w”²ŒÈùXêØòzü¥kzW«Ûz*èR•uluʼ\~ jë_ec8ªDæB —;£Mà4$3­»Ïï6ó³ï:TèùÏ?†ÇžÊÂÚëèÄ|¸ÜºÐ7–BG ìW´÷¶hÕˆ\ÚæZÁAu‘Õl u±Ç#¹Úpצ¸¬xœŒ÷&qhŒŠöAÛ¦œü”Ÿi¯7?:å¾­Nï_µt¹÷½—òçt/§ª1”¯kÏJ+Ä* ÃÝL]z×%éôî{Ù‚‡on_U¢SËCO‹¿•]ÞšÖ¾7&ÓŠ[%*eåçs˜ûPy‡´+y¥Ò¶ŸÎ»TYyžQ^ŽÈ­„è]ÄóƒÏ»Xì:ºœBÎ,®ÈŽt{ªaÜÙ7qóBÊZ3†[Hõ育[Ñ´âÅ™,»º2­÷j‚¬PÆ[iŽUÇ2óEÕËÎW–¡VéeWxë¹!+ÀÛï··/åï(ïZÃŧ½ìÊà§YГ”.Øð«‡Í×g\ͬfö8q¬h¿I0uÏŸ( 9“Ës=ecƒªêûy—›ÙêìàU`NPu´Më\iÓ$Þ_ªÕF÷Ÿº¾ÞÌ©†U¦79;m^Î¥^gÓw=·4Ù~iŠ0ÜzæO»NøJê òõê ÞOm]WJ£Ü_ ç2p¢Árî}3žºÕÉÄÖÓ|åÚµù]ÿ¹_W¤óðBË@ì=Gý£wšwÝ\¶f[0Q*Ù5è[)L´Þ4…üz;îEß„òkÞ§ÁÏd–«»¬´à¸‘”¨+àŽJÒ/+§o÷¿Uß§UûÞ·øXF…/I¬hç+u‰ïw£|#Å{fçnÒóÌóÔÅ=‹qYC~°â–þVk#=6Ÿ½Îåm²Wˆ£*Ô²®SÄÌM¶ÛŽÍ^a Ðë5¢˜‰ã.¯+°¯\‹ÉðÊÔŬ«Ñ+.:ÌŒ÷Yð뢧ˆõÏJJCy gÉœÞÙ{½ëq›—Üò•û;ñàÑ’[¯;>"Ù\dÆË÷†À·>U×äÈÛjP\k+Iõõ¬¥Éãîî(õ:ZP6+˜7ö—©Ó+~ U¡YÅRsÕ¨|7ømO]wjºó–¡±ÑÒñm<ð)Õ»¶/Ù‚óÕ”9Ò uÝéÞžòZ÷OeDw¨rå½ã\›ÉN¥/²H;Y=\ó˜·$ÌßIgÏ¢}Ù¶ç——–õK{F¦ø›:¹ÆsÞ“N¿Ice/kõξð£Î2{ù.¨iàë©) è {vß»[…²´Ñ¢B\NÐíT€§-¹1Ñ£˜Ù&V¾ )`Û PÛºR1(§/˜hlš¼îÃ2­N¢Þ¶²TVX±X,U½”oâ|ëg»ìžê’ ˜|¤x—š¾®s,,ì3t½?…ùúßó÷öS£ýåü?Ì!ÝQ€e u¿æßRZªÓ®°P§—®{¢Úìc>ºÃ¸Þ±³{Þµ8lô…ø]Ðά14Nó³ëµÈN·Tì-4KǽǕtÉ`cwks:åës½ï.Õݳ>á<d¢¥o³++ÐhY¥{ÃD/Œû™§Á…]V5ìázÌYepë£É¸>Âòò,5‹(Ï-g®ÃóHšéíØûˆF”½;ÛÈáí­£qvY«ãÖ‘úð$IÍ6xÂS5mÓ˜µöÔ9Ù¡×h$¾Ûzªé/FgsÉç]ò漪>r?vçS\4hu]iŽÚçy±]|ňñ½{—?ÊR±úŠÆrüÞßV6EÓ%É®ÛL¨:µçTÚ4ë8˜ÿ iÎ1îë¡jÓæGC{›G=‰ÛGº‘®2¯Ý VœR¦#ž³*h«áR^i?Žä©Äãßr›ê™Ü:Rï’”f·V²JÓn+£»¾ä’Ú÷o‰#|ù²Ç—²hóßä)]¿ÍïoêeveNÜgô»ŒõÕøæÐ!yÍ¡õû“¯mƒƒËb§ÏÝy;$‡æ`ó¤Ç‡hòt"]æ·eèWÛ-†N qöÍ~N²ëÃN/z—”läDÍÃ}nùbã Íê0¼,s· ÒËìéG2›’Ö{©L3©Ü㼟G—Ô@¼íaèríž·`Ö„þÕ©>¬3!nÅœä΢ö ™Â“Ûg u$U7®V–*Ú#¸—œN‰»ª¸êœê[fÒÁ[Ý©b6ƒ#šr¹Ö›2å*\Ü7ë\…ÍÅoÈ$¹xö&Z̳=¾aÔvß]_$Õ^G)ÙPÖ›ëé²¼FÌÖiÞZ*Ðø< ­QÜ~(À&v%€bZÃ[œÙ± Í•wùÿqJñùíÊŸk/ÉP»€ºþþ>gËk)Vvrí›…‡ÙmÕàêµÅSÛhÄ¿Šu]Ú&Îá̺}sEô얱芤fV¬æˆÐiƒ(‡zášjlî‚=\j@ë*ÈÇýv!1ÙÛÀD¹[ˆñU’o¶4K=Ù׎×ÀV¬i†·š¼™ÆùgR@O[”î®érO¥J;×Ç{Z}\ç^IÓç1TH_rÝ. \GK.™\÷1U‚÷hj I«.­ÊårÊäE*ÜN޹:b«{K2A wë¯nÛlm`õrˆáìòé8ºmX=\ CwB ŠöÍóè-·k§'¡’wxryy"é׎u{ª%LtÃâó”n˜Ì½¬¢5ÒÖ?SΖ³| —Xˆ3u ¥Š‹@Tôgtgu[˜ 7¥½±¹Á”î®®&·²ÆþêÛ÷R\@V:9MûuÅîËz}XRµÁLª|Å×GeÔ‰¦29QcßX¿²ç³Á|…¦F¯&óròmo T·&j[Øg2 ðT0{l§N¨=$—t½7o"­]ž¶.ÅNÎËUÈ>JÅ!{nUÆÒ¤Ùn˜ÈnôÚ.ud:;òwub>à;¾GÚŸ’Ý]I¯½—8ËU sÖJõ7Û^^±½Ì{«Xº4‘€ÞwÓ”Ýá5Ú„p-½W(ÝeòÌÚâ5e(¡KjfŸ~¯øMAÑÊñK™¯_—åýó¡iÖŽh“.J˜å÷‹ÍtÞaéžÅoí åLꌦ+sý Ôÿ­‡Ø„w“f?<´?zp¯kͼÌÕE\oÝRؽq—R—^q¾ÝV›¥{°¼«›N…Q".R¾ù…d>×vm€j>7’Zœˆ­™4ÞçÈñ;ö?T”­Q«"»ËerCîDžì*ÈÁÚÈfvëŒU™tOtÑÅqR;{«^ͱF·_ŠçÁ*? Tåµc¦W_‚óà7éOZt—-YŒG\ é›—¯D.(¶ïZY¹¸+4w4ºS*@º·+Ág‡—JéR“”…9{"ˆÈܦýgB©fïpµ³…`«!IA>ÖÞž­¿ò¯¼ýØ'¬}ãåA›AßqºRÜ«pÇ\re)!Ö… ¯+Š2µ‚ÝÕ€›†<¼½ÎÚ꽡+÷T ±¹Ä¥wK4%VäùaE*üó¸WeIå`èi%mVæuÄü¹¢½™•ÄZ{îºp‹døÌï5ÝÆÖö3³ŽøEêE¹¼—;]k®®›‰eݬ¼\yd|+k¹ëÌæ6û0SAÁÐs¼¬]  Ý÷×  ±aÛ;ÑÌáÏ5 QyGK ט÷¦ÅŽ˜ñ¾áÔ§ªÇ^´Y¾^YìÓ¶t½PZêÚU´ ¬ÉÜÒ vwQG-{*Ë5φKð­óÔ¾ü ~`j=|0Q«/ù`«? ýß™ö#ûŒüå=LZ/Þ¾U7+«ÛQ$«%(¯ú²c}_s‚ýë_Fo«z»†Ûë · mqD9¥M#¶ãåÔ@Zr*ÁG{»ð}-TÀ¨- ·~²ž”yœ}²Ë¢Ï¥œ;¢êöi(‰µÚ{/¨x!šë°Ð•Ï{çUÓ†šíY]Ìð΀Öé±$j–û;GWmýѪ—­ÝXðÙÔó&kÙ}%,FVÎ2NKz/{+ʚˇkºŸ¡Åq,é+z¨˜Ÿvmq]—ιEÉÙV'¹›±Î-Üøó«JpøQVö}m ÅK|Ä„ƒj÷µß·¯x¤2ÜX´‰³§N'5™|HÉv]7nNêM-kE• rt&?V×·¥e!yYDÉØó&QÜôŠÀùZ©Õ|v©é{åå^ ,)切»ÜV­ê­†·Ýb[&².Úv*Q¥ö­asu½ðt¯2¬öú^?b£¾‰5“³º¶¨÷*Ulƒ†£[ÚŸEïPñ¦×.Aç·=b¢Ü$²Ÿœ;ÞîëËëË–ðÍâ;¥Ú’vÞ¶ƒw&¥R*<íhqQ9·ÐÒmPÝU§«°u ­3&äÇÎ2†À_¹Š+WîíêÓ^žèh^)¹×IÃÜLÛµXeÚu]›P¼×ôùû&{à ™/*àöw»ªË<©øeî—B­È„U°w='o½ƒa"R5ÖÝK “Û3kÆ:{&Dº oOs63,g‘¹é¥¿T6»Ìeˆñ"’ëÚöëY¤Ã€Zµ|Ñ.ž†˜Üس]=õêçKQj+R²v“Ã)öƒ6°«-;Ç„‚Nh˧-íu›00ú*}ɬ¥Û¤hU¶Rît:’óq ‚•ÌÖ°ž'„IŸ‰`Ƹ©×¯»çކý”G\ :¢O2@ýÌR¦TäÝC:±Þé’ë5hz×UÞYªÆM*àUÎÞ6—&Ʋè‰tÀšË둳ٽ…ÇÕœóÊM^ßgŠÒûf!ëQÚäÈ¿ßU:žÜ­þ¶çû¼1üÆZ$´~óˆS¼%SV«—lo Y[ûÜâölûÙqÛžº!Pc’;Ö­¼áw:¼êà :R>ûØH9bÞj[Û¨ÚÍ5ß­TÑfÞ$pR3JÒÛ«×+-‚¸ ½bLø7°ûA”|_u¯QXôÞ›Óz ²K.;]íÇÕÁß5pšAÕ{1¸7¤³YJ™+ ›DË%>Sî w×¶µËºýНXµçÕd%'lI¨ìG¹»J»èm`'†s ÚÁ0¬ Âs®¸æŒÞtºP¨rIò­7·W)Þg©W³Åò× –×w_\̶¬xi°\üF¡¡Òë;O4óU¾Wüªÿþ©]\rþýYí%ûõLVÚþŸæÇuh5Þ[¶äö ZvùR¬‰¬;tøB¸U†u qÓ™ÒŒƒÖÈões»}>N"ˆî–l+Ú¾~,Ó ñ܈ J¼®®îŒª÷=Á1s½Pq;;‡ÀC¿t4øÎfõp-Ù€]ÐÒƒ^Ýo=Mz–ké—¾¤€¾6.&4xq‡%ZÝ|eÈùnó‘Uycybd‹Zwcç™A …ua·YyqzyÌT¡ëG›CÄßge Ô±ï>ïõùg• •oiu`+yY—g(XÝI•pµƒÂùT}Cùd¾ñÉ<³}{ÃÛoÂ?N¤\LÏ9„öñ}úÕWú4ýøxˆ«ðãSº]ÈMb¦Y¾mµöƒµÎs9˜@ðb}´2Þ?Ê!c3Rèß #Îçë—~]ÛëõœÆÍÖec].|NãAÙzákЧÔ7+13ôje%c&D{Ý2ÎûÉ÷Nð¥žäHøl¥’žë×7e†²ênæ÷7ÕÂ^SG£„w½/-‹Uì¾÷)çwÖò+ØI^î†ÂUÕßÖM8¿»³/ëA~´QÅí8¼ôë¯yËbÚõêÍBŽÖùyRUëâ«`zégn —Ù\º]ëG¸ïJ὎":« $åÚ“g¢û²»{…{Ã6×µe**R Lâ†pU±XmÕøåëÙÏ>FÞÐ ¬Ô`®åñœÃY„iȘ=WÈåì¾ÁÐíjFpS<±î¯šOýÔ•]Cê§]Y®•:3Þöaµ1 òðU‚Í[èzÊÅvÏìÎÏ?6êëÃÒz:Là5oÃIáLTÉ ÌÕfípðÇ;p%^|Ìl·W.«wYÕ1,Z×Ûyª6¹:5w ­-Ù±ÁÜŒ§Ïf­­FZŸK]7·y¼Ý»4Ûä*þÕÃYmÄ™{Kps1yw^@nÚê¾e µ»ˆ¶ï®y“óÐõÖµzÁà÷cÑv«Ûä9qæ¹î€™É¢àKÞñÊ²Ï Á¹.í\C;µÔ©pÈW2Ãij–…MØÅÚE•ê=á{IB3(:`Ó[…yÛ”%ÅÙB¬Z¬OT“ Ó‡q©ÜRá/¯^mÑ*4:èäÀ;Peöví8v•îøž íí˜.¾™9Æž,pч©ãêF…rĶbÜóÑÍOb—~^mµµ¬7í3­ïuÐzÉ 0³uqö«¡IÓ6÷¤æË ÉÀÝc¾“¬s‹Dv ˆä/ âÆ­Föåj&i»+Õ=é=o]JŒó#ÃίÍôx/²÷SWËVf|¬H¼¥÷žåßà@¬¶zmEöw¼³y¾õ+‹És7£ÖÆöºÃxï¦vï‚Ù~ç½cÃ^.g û7î¾4£X7s“òɃg°‘R”­¾™·é ºeÚ„;{cáɳº«Má¥Ò>—t†“}ÐwRR&Û„vÔ¯ƒâ3Ñ$²êmÊ=a2·xT3ÌÔ­Åò ¯žcÚÞ&ïnœ3’Ü:¾°Or»§*±z;xVN‹Ö«óM§Ûul¸;yôp} Ø­•—™K ë´øC¼l ì› aò–íkÇËBÊ‹”Ĩ´{hV¾¢ ‹ƒä­P)íÉðŽðK— ®â05вP´Y§Ã/oˆ­›NuŽ:êcÂ:{cÞZ+-—ñɸCá[³J»5#oy‰ª__:±<}ÀãI])¼2&ýR ðÓ¿5Ks“vÃÎá8œ´Ýyâ <;]s4¨´y¹WAËLveŽ®Lüºz×^yνYN#w^Êlo1Í(3 4É™£¯‡æ2M­[YÛÕ{ŠKUÊv.åfZ\‚÷«2g64ªtk¾Çk‰ö¦%r™ÝAÖ‹ì&”nZ&ì\—:ðZ«¯ñ<šOÚœž£~$ÌÖ̓‚ þ­òÁªÑÆiRöZõ]C{¥Ê˜¡ÂZò™]¢9W|VïïIOÃ!íü0n×½½Glúwã ¨ûI橺vrB‡Yòêêz€¡r’WÜ=ÁZˆ½)Ãh=3ºbôgvé´–uú‰Úëme=îµô»Y—k[«…ÍÑÊvcD´°¡L,mÞ¦öv²Vp˜Þë¶t«‚¬²Ã­yÙFÝÖåhQ尚͚:ŽvGŒ†öê¶9pÊá îô¾9ÓÃr}»ÒZ¡;9]Ýl'ƒFwe;5’«ÊÇ^œ3¸pAyKÄpÆ[á…TñÙê¦=§Ü´SË^¶Ì7Ù^ù⃷r•0Ð2Bs<”fM‰K¨©Ò¥„ÞûÙS)!‚^ë~†«^)l¶8‹½µe:r†úÔõŽîü÷¶JbæMe[Å:ò^’8ƒ—mg]îK#Ë7Ά0¬ €&‹»'çîØÉ–¿N9l˜îˆi…Õšj*k^R‰ugËÀ§c•ž »ðÕ‡@ž¡àéµµkS-à>ç|næ‹|§½å‡Þ†Oby¨.ï6«ÞÚ?XíXÇÖ5#[p01õ»Ø(­«xX z»¥÷ÚK-4X”woqPÛ»¬ÝG¬Õfž=Ð}šhW,&pp“ÍzÑÏ£}Îï®Ûkl!f×*ÄË÷zVú½˜ˆêäd"£·0νy.R9‡²ðõÈ-‘™7–ãÍ‘g@jèFUÇq`Ôµ D–wXÎú ²_ ·èîW¸6¼ˆ›Û Ãó“®ý}ë›=vžÊ‚ï®ÆöòÇk«Ëhí\©ºƒ¿¬0çÍÞe„ÁNˆY°R¹Ò®XBºÕ£ÕŽ•¡ç&…¬Rúí­‹¯®ÏrçBØÅš{:8û)(W Ðì;Ø»&žbÝ´²äS¹€Jï…5ŽñnÞ3kÚþï¦Rò}ž~ÅÜËiÖÍÊØ‡eõî_VŒ™ÒºÄéC ©ÌÅ.{~0N?<ˆÍTy!ÁÎK/3+Õ3×÷'מinŽô]é¿iºQW1:?ûèÍ#†þTJ÷«-ñ…Ù=NX“§WŸ_5ˆgvågS]°ÏïûÁ§ï+­Ñõº«ªýUÙOɼR—îÈéŸè3E–ža;'n³qæš7¿8óz‚îJ³w6êS½efÑü÷H¯Ü5$!t%(k2ÈêÐ=­ã«MP”ëžö¼Ì4ñs¾¹{­¹Ü€‹Ï1­zÊŠùM†Þ.(Ž¥¾=.­înÕ%ð±yc cPý!¥Zà3·¥Â®™ÖuשfW½£ÓÝäðªj`äË@á˜eÖZ5°sN_;AîØ=bWÌʽ9·nVåîFÔέÌâò³Ò³¢åšÄ̘cém¦7zú‘tkBÅ×À'Y“39Æ:ºÌÙ°ß8¸Í]ަ^f,{k©í;¡@ЬìDR„Q±+y +gû–v]7漜ԊÎÙV;éÓ;BšK²f²NY¶±Æš½2ÃÛdk6©Û×ù«Ê p o¯g®bƒÃ£öj¯=óºñÅÕ´¤sˆ‰N›:Qq:W Ó,àÈPS/¥´VÖu?,«zѺDø]¾ƒ¤À„‹KLšwì§±q®—Í;.ÈDàô”o¶´«ŽGš·Î}İãÕ|…о]Xq˜¿]ßëµ3ÙÖ]§žjBUδMåMC±&ÛÅÎææÒʃ§kuÊ!×gмÀÑ¿Í7×~6I§íh{À±¸Ú»”s[êEÞŠS±lN31êÍÝ¥¢Ë´äÄý4? ®¦OÃpSñwé˜qÍåCxNUwH—ÈYæ°ÖDFä›´˜µZòÔ¹‹c»kiå¼²¯dø½l鯅èeÅFùc•ÑÙºXïo32ñpv'si޵yO`OZ÷µõzסyÏ}JsS·‡ w¹Y ùíc^TýØý¶l?@Û‹,¡|m Û¶Sâjï]õ]æ6¢S& ïy{Í•koæ*C׉8,I¼Ë' ª2“±k•KJt™j}uÓ³T¢lš¥Ö‹5°±öÙ¹Ö êÉ5£¦LŠå{½'ZY1cv1RUß‹)S>óL¿XÐ)¿‚£zà¬öcІ`]K¦QîLJŸPá¨?jN‹øøIڃƈr^ZaÞ%µŠÂð¸šæ¯ £™ÛÄFnXÙÑíj—Ú×Q­È! k¬ÝœoBjµï3I^¼Ík&Лl]©Fhc^eL8Å–¦ ½d=†ÊQéî<®} ª)ׯzæô+Jʆ÷Éaj*ðÚ/ÜFx°¸NäëÛV­ÑÔ=§ÚiV/N›êä0ChW…+˜j& ³tïvéàm7v'¦v[úw·¦<#(p¢<¦¯±knÅ¡o ^^ç¤\Mt}¶ W©ìB—_3}Z+£m]é ÌæMJî2ô‘Ž%. 2Ž1-ʘv^GÔ{†¹ÅË‹„¤ÛõíuÝÂô³’mo;_xz²®¼š÷ÛPSuÜæ uGØ):cÞꜙÁOÍÒ±Ö·Ñm;=dM#"®ÃORW¸mÈõƒ”Ã<'u[|1ŠÁ¯æ%®[£Ó`ñ•qøÂL—Ûß>ƦAÌ ‘kà‹«UÛW](í¹º$rW±Ì]{³FL-±£i°ý¬Ñ–›ÞSz³Dé ÷?ÀË]ûݔ֦‘yJÝfr¿]E4çsn} þ¾jè;¹§· ÒŽÉXÄò}sTÅtWݯÁYµuÜÐK7n+Ä1GéOÓÁÙ*¯+B'ÞLÉ4Ê´%æšâ¡Äð‚ï¥tWb_Üfû·‡r<=w|½³}Vke«ôî¢ùÌítÈwÏКÊð¾ö׫¼Þ÷¥pUãê,ëç\_÷kaíXzbý¸ðe>“²Ví]’âÕx''N`äô™Î ¹3hÜhÑ‘ÂãkùåÞû³{iù½K;,Yõ82öµ4×e"ªÉànò»g:9‚W;6¯2ÒÕ*;é2æì4[½J—Îcw ¸†½‚nÑH%†·:¯züE}*E¬Ùs|³›ÒR†o7‚Õ(ÁÎÒç-ä,X·ra£[tK̨bftvÙ¸[³pd^úÈû«qã[ÜŽ?-Ë„KE3‡k+Íש‰X"íµËrH%ÀmA&ÞS¹y]c¬rövw{¦òôìh¡\ý:ussÈaÝX#Ì7eeOZ—ÔÞÛc&`‡oRÄÍΩ$”®û“»Gx·mtíÍÏ5ÝnÞXì¬Õt§{§[|ÆkYwš³`ø+AwÜ"®WŒv÷V¹ºu2$ÀOã–åí¬½×=7E„‰÷kw( Ûé½èÁôÙrÁT9`cEÌp }Q˜ßªXê· JÆ¥y"}H$×¾õ5S«Ã}]ÈñKe]Xùh²ýƒÄçRÓßkìØ7^yRǨdøÝÝÑߟÝ{íå`n”%qpK:ýs<¹x f1J¼ ‚g½§›óÉç½4MóÔЫ™ ”ú,•ÄRyV-÷zóš­Xýk{ŽÍóáµ øqïć{=”æéjz»&¿>ë÷”7×=Ô@åYæsNòÎv†Ä5üD¤n”¿*DZÕ× íåE' À.‹¥ÂÒn ¯[n•l™Ëå¹OÙw;(+‹4o3ŒÅ0ÙpâÌå~º5ÔÚ‡'mdõ™Ú[ã Uq9™l/Âü; KJòcÊ(nÃx½Ä#·ê.•¬”ì{Ÿ®˜Ò¾¹©ÐÜ;~;7»ï8ó@Úè;z±©éÞÇí4ÄËò‹%u{:üjiêöæ¨ljG ÀñD×­W‹ÃBµWTfrY¦ÑgdÅ’}`Ò GqÖ3M;×jÚ¾¾˜ÜW¥šâ^žº6¹@*nöÅ´:ŸÜX¤ÖTt ç9ïª+ÁäLñ?ãCúCÒ`I!|¿~úÜ}ÌÙX¨ÁDËO঩nîíìBï´^Qh¥&»û.ï_G6¬qóƒÃMÝ_T°:è*VçTÑ”JÕ'QÞb[[®j¹‡ÎJÌÇK®øÑqû [‰;éÌÎz7¸ín:ªY¨ËÇKB›][§1kæ ¬Ägy ¼^u¥|M"\_&0Jå5¶\O¹ØÊÎÂEF¯J—ªÉLÌ”€ŽvâDV‰W-ÖÝ9npÂï¥HkÇwt ØópmÚ¡³¸¬y-é{RãhQ½f´ÊÊ@4ei­hF=ÖqÇÙ‚J–²vb«ÛU™´•›Þ}|å>c¢®T´‘Ðïu²Y®Éd«—[‚Yç\±O—ª‘u7(ûpjÖë{…*î»O— ÔÖØéqäÝ Óîâå1D¡¦<êâ²ùŽÄ!ÓÙr¦ƒ-*Yi}¸R®tÇ-›Ip̼åØì+– êTæ«9n¢Òà‰Dþ¨ë6§ÛÝß¡·Ø çÖößK±ÿQï®ý¬w¾–WfLüÏAðR™•¡g""Žœ¶¦9SYV›Õ‚J%é·k f]­yÌò–ʰ03/_Ù]U)VÔøS¤eÃï×}Çë«»Š±f®”bªRr¤EhÊ/g9¹ðlQ4U7ü M9/Õ˜o8S kC †p’22ÖdK # SIÅÇÈ‘œYqqóC Lp1LH0¹ÌXÄ1.c!4œ Œ8›Ç„(P$8’ @˜Lfza„¹ÏØ_3+(Ka†Àt8>æ²kÑ üü•¯”ó-·³_àëçµÚ®®e¹§ >é¥Ça/£½$ÃÎêjŠeß)¼ ªoyÝØ­|•ìGtÎÄr;ó+ƒVfͺfÿ›DC2j7F{¡äkcG`¾ï¶Æ+Ô7‡Pªú4Ò‡#“¯k]’»¾ï$•`±NžeÏ*âuÔn@¿¡JðAçpª¦ÌÖ€ÀGQè°:“>Q¸iÕâÀqnW$,öª½I.Ž ®Zhnç¶lÃÒ€(åxf” ìqd‘ò·qnêU›K¸ƒ˜¯:+!æô[ÞT{xùö žqªÇá{"§É@1_fˆºàÚyÁõuö’A•šë§$\9R'pNœ^Ík7oåõÓÓ­—¦°÷ܸXùåoŠXÒó3Pd¾ÉŠvª·jF¹ê7‰rZ¯2Zè°µu·õÓ[ÉC —]Ç@æhirºßzjæ:Íé>Ê^äq4ʇY”rÄN¬u ð'B.nfíÓG¯ŠÄº€7!£+ˆQÜÍ×£&GZîbè €È#iÓÀ­^D¥”x™Ù”î¢b¥è#hoF³Ï@÷_Ž÷•JÄÎ\ß°Ä_-ÊêáA5Û£Õ£AÖs¶»ïØö_²ƒö˜÷¹›L6 ¦™ ršS»i›œ,ë«%ÇhdêÃwtø¾”ÆT”]ÿ3ú¿Õ –k©Vsm/~’aÉEuÀ«¦Á?¾tzÎ ÷«Ã9b³·s^³‹¥A›§Ô¯Pïa–¯*|ÜðíFæ´]uq©ÍïWµ¦®–6»[ʃ'–åÞl­ìð7Á+Cº¬V„öJN¯7RÞ¬ôrvøœƒ—¾”1µíðʉF0ãׂ9È¡K¨½6ò(XÄ!'Ò ­ª-Ñ>áé}<·B>öarnåRyvŠH+(ÕÜ$Zб Å^+ªätZØ%ŒîRNí[Œ¥vºq«:¸ê´h9mdsîù+>‹Ñ5@&€–¹Q§NS¼XF%u„-&EkcY™¬ëÜÝǨ–'WЏ¾ø¹JÚâv‹£Ù»öTÇ‹~Ëë8è")º–*w3ÂíXÐ|¸·ÞÌeß½Ó76Ñ¿;÷’ ™Êº÷R·ä›Ådés|‡ßä{¹ä°ñ§ê7ywW$âUG‰ÆhBú;¡´ÃIb¸*[ÚîµD*œ¯.„ísJdäŠîvæp@,€Â¹ÉøYëxëÖºôúfe£‹/¯Öý3Â⮘¡/ÉPY]Ù£ó”·;nÓYÖ•§Õ°àßjÇ®òþZ Z:à­ó8`Ê;®²m¯b‘ãÞM,.[w«1,1’¶-€SU-}bpXijLÆH”{˜›%ÃBÚ7|]©Öí n ^ÞD~ª·…­¢Õ€Jr¶ó.󕦪&6²æSsjUñíÖêιÊñ陯2.=Ïã“ÇÝã~‘×¹ƒ@#0¢-‡=ÞͰm?B¼çw«Çù}àóÕí ¹jõÿjîÔ.‹_¹/·M{ùƒô>Ì{Úï¤.Õx§ÙF¸&æ´x8ŠÁ º"„×mÓÛ¢«çT¼0Së±;(JwǨ©Ù…R§0æ½SVfçs@E°mNÑ2³ê]¼‘Ùt `’Ÿq ᣠ-Âæö‹Ú.¤Ž—‹‹ÝÞÌéMέ¾x8v ˜_Ž}pÛ¸¸×q6¢f½y$ƇÝéÛ²zÝg `@ï%Ûe%h /§¤Õ f]…;ÕÒ…:컾îXT˜‘ÌÄ+xqEaÍ«â/¦\ù°ù¬´rp¶ž» @µ;~ïV »àE/zÞÑ«Æúμxd†ÝDsÙV«s†=“*pÓM[)ý¶Óa¤i'©6üe¸õßeŠëHV.©ç×oÈ0eug^¦ÂÉ`IÖ›!šNjÔû­ª`°ç£õÛ~É"ÍßåFÉ´WqÛ4+쮿JcÞ¡[¨$'8(ù ËŽQ¾+ŸS( táPàŠ‘sç<Ú×N¶Õs®àN¥Î8V„J}Ò”×ÌBNãeTÜÔ8S¸i(üë/ço—qêÙ,îç£yµÚ‹î¨1©I³4踎fmšeE[oä§­Á¨{GRÊ´ðeÖ¢ž:í“›MÎåG·mµÓ+³°F •ÎHlKì}49/ŽöMuÔ-÷SNAeŽ/á3¾ ¸fUnÉfëÍÖp+pRˆ¾°|¦öú‡‚nÚ亶EÙÔžå{yð=W&ŠŽÁ]þ/Ï}ìòý„OÈr'°=E7õ‡rg^®´à׳~å/D÷Y“éi¾›fhÝ“–[Dª}·c²ÅYÚ8‹åB^Ë¡K‹¾Ô‹ÚãËWÜN´ qž±Y¹3BÝN¥Aöd¾<%ñ¹ê2¨±õî8@+lÁ¼ÑÞÏ{Û}îéëlV‡ ¿SÑ\ñ8 ^S.õmÛ´O.¥ä_xMÛXèF¯Î¤­hàY¾Mí ½U´Œo‚â Á­ˆ]p†ÙÈ­Iu‰y¯¶1Û"æ=™±·),ƒ³rì-=㫛ɹ|ÑäÙ³€ûÞ&´élJO;JûšÊE*£Buçhˆõ·µåä£ÚBÄÂrQÜàèîsÏewºlEù<¹èoƒ¶p+é¼Éƒ/[‹C|H¼RÞïÐÞ\{MÜ´:³¼=ÏoO—¾*¿åýúï’­ >SÉß݃زÙâPbÇÜ»Föª Ü×­H(×F« îÙÃ-u5쨻N^Š.:¾Øþ"t• Í˨èK¦TRvÒïžtI«} Ô:¥„1Û®©l»oh®ÎÁ®kh è¶Òpœ–\<çáQ;t­W]{´°ŠÉ$cjÍÚ±wSϧ1Eq]j<Þu'…纻Õq¸¬ú ¯5˦ãÇ—bãÁë à‘ê;v"4«ÏæYw²§3Á‡ãƒ{,‹î±Ìeû ÏÔZÓÉÁ~o#Øu›Óƒ½ÜDÛlP͸žµH ~÷¥Ž;Š¡« Åûû.„ýx9Ãz`÷»¢‚f¥Wúr\uyqQ{Õݲc¢fÁ1¥ä-#Ûçj¤¯:½fŒò£o‹p—D²;ÝŽSܯŸÂ±î:s¥æW<®ÞމUYb0)r„ ®N)ä¾×‚”Kxw_6rLÃ/®ä¡.DþžRæŒÏ•æ®´x` ã3«:M|z»»VÝtJ®ËÙ †£›rºñóÍ·Î몮¸%ï^à*pâlt‚øå´JOäåå'TªììíÃ7ëYOeÜËN“ œú7v)‘Õ¸mH{=Zq¨|ÝËPníÆøçfà˜»•¼Æ.áê(Q²–dºëÅÒ+zûÃÏ5§]nžJ>¼G^âÑçP‰ÈùJv•Å2žB(µ[— út†Z{Ï$ê˰åfIÑ"¼Æ£JÞqÅx‹N†#õÑÆöÒêïιÐöc~•·Ä±ÀÌ8ŸE{fÖ1~é™YÙZéÐ<ÓNÛp÷M¸>ßY êµÝ*uà÷˜¬%l¸»l)ùbpVYgm×\®í9ÕvyÁ°µ¥ ±-EtûCàÖn6×ç[„<ïg‰ÝZ×®³Èä€G_ãJ|XÅZH0UÞ»ýìrõçá]Iï{¼Œß¬ºIXòb×9ÊDãZórW}hß­Ô²Ýk©†ã>Â*ÇrÞnôëï¯ÜñÝŸhM®vöü«0Ç^n!°fkµDúìËe[ɤV(ü·‡»/´µ)¡o_¦]áë ô§ÛWÜ¡¡ææÞ#©JÝ{ÔfÔç¿pÜoµ®"ó.Ç+##n+¨i \H¥ªfœ½ë¼‹½…¨èïy¼U¤–þG.À—|'ÜõÁº+…+¢fæ9Ù/„yP“©¼µ”ª#Fèž¾{ÿ/Öxeßò~݈¡šžnþÔC-õíû–0ußJ}Ç £íÌÜò¥¿"i†NŒ½ë¦f!Ùme/Uôf½Bñc}€ÐÅCÞ.¨!îð%-©Ù«ÔPT§dÇ[Ìäᕟ¶õ¨ã¬c,mܳlôuáÙÌn üŸÝçÞ3ŽÝùùnù7N®žSÁ²·Žݪø¸ô>­ËV3]ç$\¦ó±Z®Üy_>}I­œWѦ€HÑö÷uŠ—ïpæþè ÏØoÊ8éº^Ï%·LU¬À?Û…ÌÜÞc»È—†EÏyW(¸ñMÜêÿY.öþ5ž‚µ£Y#þyUùŠºžT¸†!XÖÎ}n³2iáa[ 3K;lwRhönðX;–æ+Úy^c‹N帷€¨ð;ʼzãê 8¼º´¼ÿ‹Ì6©Ãmx?˜¦íP£AºˆØƒCÄÓG«¹Ó-Ó ”KKšmþN]OX÷ŠxÓhkÎÑ™k}[‡·³ŒáBÙçxk‡É ñ 0·×Ö@Ûk²—a¾8]rôÛ©F$–¶ØøRÃz®œÜÍÀJ‹Þ SÝÁ§#7F«÷S÷kôÆ6î¦p6éxãÓO-{ÍúÊbÌN¼·õxo*à8‡Ã“Ï•º·Â»?3ÒœÖÐiò㻫Ü}}‘ “¨Ýö³(*j½V2!bÑÁŒ^ ]ëy0¦ŽÓÙ9e:âµ{2Ó}¹2;$ß´;ˆâ×4Zp)u®Æ ¢«Ñ3à@PÕŠ+õŸ{x(Γ¯8=Š Ù^v2®ßo:¦ñ ·¼ûHW§šò?$tæÌÐÛ¬Šësp&nâÜ8©¼kÀ¶j]äÃåfaJæáÒ÷Kœf§d^C&?tûÒòü°yEuêgjÐ{9ïű‰±yÚ0YY]v§½Kqx=Ïfâô¸!ît÷ë“B‹ ù0"Û²]Hex:ã]iƒF­^{«®Û[é$ÁV•îs @ꔪøCW™\Oo5ÞíöS¶=L2ùù£tÄqg¨×*ºS¾·et†¦ßG×®• ç.2ðv®®§ªÃÈö¾a=\1]iýº«|™¬^Ó¶lµìº0äÄ´)0 ŧCHuáÑ~žÊò›Æ½(øymÝÍØ÷eõÃ\×pÑX Úy\QQv+¬vJ®Ð_°bînôKçë~u£0{”Éà®q®ðT‚nÙHt´*='1ž{íºÓ]Èd]ÉÚ9æ;Ô¡ÎÕë,] —Üy0ð…žªÄ€‡õѲ.¡Ï¥Ë&.íˆCCq8ÞÜð÷…C£Õ{»Ø÷¶ü(AR nÚf‹ÃÓ°C»3ÞÝ>ǘÍ,^ÛÂÅM|Ë[ÎŽqŒÇX)W­{Ù¯*)ªë9Ï&Ö®Øóvåvù<³(“Xrᮉ PéÜÞÆÕcЮàÜÛXÕ2ö™®ÿv[öQJ½B²FϬx¯wãsÂðdõ3ÒÁI´«»8Pìà¼e:»ÁPé=sg°•ò¿#Z«V‹E«¼þnݵ«žüîßÁ8¾595Kضzós¦žV£6óŽ4z¥«C{,:ˆuv toÁ¥ã‡ã5N]Ïî™2Í··ìÈqíÏqVj½‹KÐjM¼­êC«:‰å&ëä»ÅšãCH¼yò­>>ñffzH¼HÃ~ /c(æÕøS ²èC5±»ÕÏ:‡Q¸Ååª-v㤞º~UŠ·¿}û»óºYòº\í­©Èo‚{Éß8ØÑ ï[v;³sç×t€=ù÷»ÓÞôöÓ½\\‡¹Ü«›Œ…¾¼,öCŽq$hFeÉ •s¾X^Í4;˜Ë‹›¬eÔ\¹Ö.ˆ÷íèéœ<ý©—ŒÂds”ÜÄF{Ô½›rÆÊÙ½í.Çwvšö_¡1é™¶Í‹Ú<Òt°ýJ»b„5´ `5…«önVK Þ0z½µ ì­Ù´{ã¾ÌéÔp¥@ (y>¶Ç”ò\,³Ò9}¬®¦µÖݪPHröµ‹Ìàeе2*›½*=Û¹×¼. 6km“»è„b«OXðQêÛ Ìo=¥¼I<Ðç»r¦g#ž÷FFñUû(!òTmô ÖOîyÑ)9¾í³¦Ô(]1¾fÏ«}GÕJ݉mvÅÙÊìféa7wÒËÞöH6§CÒ½>WXÛ³ãïq” Ȭ4v‚çoçzÅÁ—EÝÞcv•ãÑ×+º°;“˜rµdk½å]šQ¯]{9š"š˜eÙžFßgZ­¹Ž1»DJ‹jk·ÕeËÐ%`¢ì Ü@î‰Ô?_T¯ÌørN½·}zIÜ)l´Úš]ÍÙyÒZ§0’;rwtÓ®®êÐtŠºVÕÏNQâ®kwÅ&«lV)h®³Ú®T·oMÛ1Pî‰d'):ï4±H컌Œý†éó­ö·å‹ÙØÓNëFfî“Ï)ñißµjP ±Ü7zyòݬ ’möÁ §Þ‡Ÿ`hcëÄvo£cœž8,ÂS£{é¸~ŽxšéçÐÓçn$zºéêb_±Az^#«´[ghfu[e®vÚY]²n»J¼·òq#Úˆ}Ö õöò¬¯o¯“]N÷3l2| Úí]YWËî’8©í¼Îˆ¥­! ÌœzôušÑ#PÎOvÝxwšïVÞïY5»åí› å¨VÆÕ>œ+$ ïéÙ'W:<£9³ªvF®{kž›ëÞ¹ªï!ë{ã’Ñ7"„êuÚÊt*%}iR ¹jQÍåZ&º"o–kÀ˜F²%$ö‡Opo0.*2ëîûÊ›~¾\ŽŸ-Ì®Ï}*Ï^Ó—U¨ô›®ñîKž ¸5%*p^$g®u†‚åÏÎWæ÷ÓWZáŽ/•]?t‹0mƒ™©ðé·d–5̾Ú{Œ¨¡ƒ¶âiGŽ.—;8¨±bÌ XÕÜÌÉÏu®Î”÷j¼öm>¬½ÖHCVüg–°Š¾ìw0Ôî²ë#´GV:±·6-’–2Ý®)­« ùý³3>ÄÒ>>=rš€¬¼cKTÁ<ˆ»66õæÌwW<ä(š¨ÕÖŽÒ’Âæ¡á›+s]¥S^Ø …ßÉ’¹tx =¼^^//½J…¡xªèÂñÚR­Ú¦ŽyWµí'™¦•¦t:¢ÍOvÌê˜ñåÑ+¶ òŸ$o%ŠÊḴL/º†“zw®¼õX&PS’Ũ ‚­÷MÌ[î›Kæ•-ô®†¤YnýÞÚU‹ÃxfˆÞ1Ëì9Ü-á¶%7] O·¨ €k`GÄúy³VªîÜÛÃú* —u —EgNtôS¿J]Α‹ï>”=t®Ml`‰î=4ÀÊé'×K:pã²JqÀ÷¬ó.ó^ ”ò£:€ÚÓnýï¤Û*x×”ÈǬY+–bÌY{«Ž©6—\¦|³yØEºA,ï ‡í!…¼¾#¬§æ´ò†ù6M:›—ŸSÑåØzÅ®¬¿{íiÅåàÈïoXÅÜî-À ­¸êw ð~½*¶VÇnײ?¹dL,ö×+£+CÇ]Áä2…7º¸ñí’ðbÚÉ[^Ji­ú­íÝe ÄÒŒZœ'O%›ír¬#Ñ_5K,vÛ±&5yטG]´Tl{qW‘ÏfÊðÂK×pןKóò cªA;¨ž_SÓæòBúÖØV‹óЦ´·®u,[Ï\wKEºCÍ¿Dé·G =ešÌ›#$[Of¡ÈíTSL²„› ûnáÞåß=¹>7Ñ ·¼d» VXe$ÚXÂï;7}}cj;9‘£¬ ±‚ï·ZºTÇf´»»¤{ܳÝq–èù;4%îÔìZëujÓº¹ßL[g^ú?y¾÷[¥÷ŽÔ¢/!PsDNV²Ù˜À{¥¸‘xû{9k«'M£c1õÇ÷…¡÷3s|»¬œféIˆG¨À{ Elë°*ÇSÇ*ñ÷D€Mrß·×–ãÔ=á÷¶,qó^›¾ÈìüPC"öð¬Ðº…s´÷mi…—LÍ©ô^ò´7©ªjŽuç¼|ö€¹îÒ—:¿”ÁM!åm­`{1‘þOÞÛ¼gŸçAhÂ${±~æåaæUíê`ü† E.Mdàe#S»òëÁëÙÙê3Ûžïm;B&5ݦ°‰mÎïym‹ë$…·†#Õgn'Ö/‡v¸ª[Xµ¤6–Õõ»šíœ`šÐÁîÔ©]gaXÐÀƒ®[pK;ð¸¹*’c› åš¾6~HÚ#ämSÕÜŽKíyp,v)ÑêÓý!².ïNzåÚDŸÙ `S//vI@ÓØñÁ¢fu§kŽÊZûºAŸuN§XìZií[ÍC{ŒýÕbª¬`ª«ñù ­*—\ NQÌ©µ"Vuô|w´“­Ð f@£Ì†\ƒÝâp˘ú×¼p4ªojÑhò•tC£=ÖÙ«áÞÉëò˜´5”¶ž¬tnùxõ‰ÏԯΚäXÐQ5LòKo„«÷¦­Ke½Ò/Vˆñµ“å½Õ/ÛìáyÑÚðM[çö×”¶àžÍ$·³ÏÅbá]½ƒ½]iоӝ­¹}C ‹0Ö Þ^éKAÝl¤k^W¨K³ã”ì,¤Á–ÜŽ­É›¾ó©P0ÑÛY)Qs‘é¡NÄb•ÈÕÞð„DçX€Ðî·™ Î c:ç‚o¤¹¾\ï}¨xùuùùˆÈÛt.Ž5wÐG’ÝKOh=%•lÝ‚§mª³J·ÏnÒ¶—‡”ïk«ôlfPnók°®7F®:Vñß2œËÛ<+P—Ëò;ÏUàuÖŠ§–’†án¥Ù…=ö›j×Y¸ï¹ ^îXÈ-¿Šßjõ´g-Ì×9mÄtd§]2”Üäh±%>çpòÝhòï5äT¥°×ÌKÖÙàÞ-IªŠñ‡0f-}«¯¹\—K‡ABîï¤\ügw®é'›Ü÷†·{ïø›j³¥v7£®Á+ˆä=ãwÚž:*äƒñÊ÷&žOX=:Ø©ê/t{ 5îÚSëg»t‰þޱ1÷Q©ï ª­‘l×›¼]ÍSÿJg×~Ï S}«wÉo.Ú½ †‡+þÛoÝðö£‹«ò‹¨µWŸ’ñ9ž==Ń^5êÌ»4;Ìchù'Ófq—›É]Œ’uë¾  Bï†:mj¥R·ÃÃÓUáïfÉmØÃhèÛÕPFÚ¦aj½‹;\ãJè÷†¹pâ#s¨zØY|ÉtnÉ5òM4ÐÐùû«{½ÞØ+Æ»¸ éÛÕ­æm.Q×R§y@)ú ~×ïh~í­ê=å•«ªÙÜN™/‘/µíwáræ/zË®£î¬eìi¿¦Û+u·»çî¬ðÕ‰yiÔÌÌ È·½L’Æô†o´ ï+®ySúÝMsÇN1ZÆV™gY§^xÙ$•)ò¿óvb>=°}žIÝÌ rfùhSå‘H°- TÅÏÙNfsÐ#¯.<òË%ÆÝÚu‡Å-žõk1’;;{Ú¼#¶Šö…+—W´ žÙ^§9R‹Ê’l¦TÊÄ.)Üž3Åžã÷‡‡ÚwE™s]GãŒm·!öLu&vgTÓ“AhRã9âI›?uõœµÞî^<ðwo¥L¸1е4mo$öb¡NÖìb—;É[7WS±Ñeå§ osÇÁõœµd[;µ‚réóÃGœV»¼h7Âæ^ b뤛{“¹_‡n–Âh •*ǯ§nÞ”œýñÙ {g•îY°ú½o»‚7ù¥Ž9»P‡öqîÉBïn×î&ëÇiáv®#^î#“2rX÷Ç7¥H²32–bpjµßvcooeazI„ï¢Ê»AùÃk•.S&4yÅDV]a÷°ÊìÛ©lÓ¶Þç–l£@D]Ÿcâä"—o–|<)ÅÌ«$·^ Ûg@}=í"j‹¡Ìxkvj‡ŸPš²½Áú¤lÄ)È'ÞÚ±}ÝÙö˜Vd å¢H5&—{Z…K¢‹éSvgc1 Q÷\€-yô̒ó4%4¡Ív ÊF 8s+³¸u¤yÕžû:¹K#Z[cšu«J«Î%ݾçzñ[ÆsØë·ºN•­®os÷Æ="½Ô}@¥5çÑû'«î®²#¢K¦¶îV ôÒí ëêîŠßfZüsÆÁÇç‰KèöèÐPV ÇÕNcËÓ˜<Ð;¤n[©W»Á8b¥—½„®ÞIZ6cow(æ>qÉVyuw)ÅÙ*é0²üy8³È{(pIO8²ãÖø¤Xóî±Kt,óž6dÖ=›•ƒ½–è´;ÃÔ6X†í`[xcû®Pºç)·ÎiO:•£œp¡›Jv×í„ïdïEÌ‹Ì'¼øVŽW)Îïì_5ÑìïÇ£°.¼ÝÞš_E hóÞ}Ù8õÆš–Èpnü°vk¬ÅC2¯õ;ps ò\´…Y‚ëJ´ÏÑ~Sí.z ÝËì‰/;‰L<ÂUine‰VR´Á¼ËÛÞQíóyê!¹ÊñùB·€î íÙ”ér|¥fhº» 7ëÌxí¼r´ÊßFÈ.â´(IK,¼¬Ï{6{·Ô7†*V{)6Uû¤µ§âkLc æžÜ¿wK¡~ŠCx’ã+=xHxë ߣ ¿ŸW•GY.+jDzѬÙKºº²·|Ýúø¾„{ׂÃÏ—• LÎ&©óÚ̳—9Zº}ÝÒž‘ÛÚ"SZv•^QÍ­³wu+Ì厣-\™{3•C}冻´µ$­A¤ehY5TöúXË|Ÿ¥‡ºV×ÎWK2}¿„•š±ìZŸÆŸ¿áœOéeû|½§;½æòãx­cÌ£mƒêì§¹N‹“´i®·­LÜYÔå6YÍ«ÙÂÎÔ 5t°*êçYÚ¸Ò*Zº„Wj“A+“{w³ºòKGP ¹Uå^¥RØï«7mž”û;ÊG^ñZï×ÇB½¸á«Z}ØtS¨ògó¼| ]ԶᮇԙF½7ÀÒƒ9FÊ·=•5ölã~ðO׬᭤V¿EhŠš¸£µ Ìí¤‹6*Ôµí«ÇÖm\H®ìc$ÇŠÄÛ"ŒÀoXÝál¼¤/0`ר´²YìÍ ·y³/ÇÛn˜c"ŒªÚuãî¼RÓ!^û°7‘Ë‘ÆÛÈTÍ;‚÷›“GrL/Ž3oM…S-Y²g-ízOwþó9Jˆˆ_¤ë¡YS•Ê0<²¦,®orÁÕªNª ;ÅésØ =©µš=zl€M„ßpSž®ÑÇ:r€nôwšŒÈúk˜;ÑÐ…o-i-Å!Ë›éé6'áß³O¾«Ëå”;Z/kƒ|諽pw1`ãêìÿ‚u{ÄxuCÇyPLÁ)8AUzølŒ»Þy™ÙZ1Ä;·7p¿!F½îØ7yð›èO^K‚Ãć…ícã’I°mvxzˆ®`v/#g$Ê gºÝd«±µ+N;r/\ÄÒVýe>ûQ}7k­'oÙk .B+k“CÙë8ñ¿yr‰ù't— ž}¿a¹lå­î:}ßw¯¡Hp[Ô¼Ÿ—ljÝ.`“î;êó9){r”Ì^ b4G¢–o­×†®ãÙµÒ›—çéW„æÅ³Í-ëÄ܇SÞÅâ=gÓ\ÑU“ÎÅì x¥ohR]R—M홣:œ@ µÑõòk U—R/½pn súCô칸"òªGæf‡‡rERº t•L°hi*¥tep£]ïO»Ù¾ê¸W§}Ì=bâeµudêÚJÊ*—/<{®<Ëb-íɪVýo«5ó½·Ò­ÇRÒÓhªlá·²³ÝÑ5Ö\>4W¦nfKZdTÊ} žf[©×^¸Gå;gIÛ”§ Ö ©{+]+pbÓ¹r=ۺ̆—{_ÚyÐx.Fö²Ÿ™›œË&ò³µ*ô¾ceV 4ë;u¥}ïô>öé&¼e3a õm¼{A©HaÜõöötíçî kÌq$·$™EÎë]PæNdR{Ÿê}O×xéñêój¬z®‰ù|¥h›'¤êUË`Ê4´Ð\K:]ÇkÈ9*¬Öm[,aîÔöþÎ¥ô¢•×;ºM—*Çv:†¬Ý¬›½\p ÷P•ìt5g/TÚGÁ¦yð}}J³C¦B¾Ò޲ÅjB“||}¶¼J×^‹»^ˆ¼-ô£)û,\ÓïWAtÜPSšßžîM›JÜ[fEWa¬¾Î8çÃD}uÐUY–M‰|K”Ak^Õéjºæ'Ù&³}q‡+–æ]q-‹Ðr‡¬Ðö{KGÆÅ¤—½P‘윖mË Ït&šÑìð :hòy”È4åž­ÔÜëvÎí)À“u×Cª!pþ”¬m{0U8t•3±^†ícmÜLÎÅØÚÅOå«u(u½Ð»y5n[*ëò>=ÏW#ì÷³Ö•ö7+·ôk¨ ¥²u䯿áìÚ!«ëúÞhß½Ýë‡Upkbåì¬ËÄzoN}R€,é¶¹ïiçÔ³JÞMD>ïm£Wpð˜gW‡9!Ζ޾£\{eáZÓ«fLð>§úÕwéí6Ò_žbw’Á{и›O*ñnvÓ+9¶9ÊËIÀÞaI~:÷ʸ-ù{åé×¢Þ®½¾Àëyfª;\zOhï=õ„6à–P; }ß}õx¯°]mŽ\± zƒóWJlä¢'ºì‡‹]Á;iå;â…Œ«ÁWn³u¨¾x®¢Utl/,Ô76„à¿^úzè>6 ôƒ˜³ÎäÈbË¡oke]£§èR¾#‡’â%f-#¡ÝäëWsX©&Ú}–+we«Ew Äû,îœoNC…ÔœTsx»Ð溇´')õæ FÔ¤Zk³ì‹[×{òmÒ³§SÒº±æÍ͆޲æ×DçSÞÞmëÌ Þ%6ƒ±l™h²øÉ-S2Æ8ç ×W%ÝIÚ´;V¥2:ï*Iky†´Wð)²@þïÄÞþ¡‰p½!¼üZÕ@pKÓÚ®É#zf7=Îsb“nN²x‡HPÑ|k@wäg¸5hw Ñ;)/Ypù£Cº‰§4»¡[±r÷‰è·bì˜è䎎ÛF£¥[3Ëk-ó‚Á·¨W}½TÀ^ïsÇw³vufúþÆí¶%p”ÍA»—Ø#®Â#r»4ôþ¨—q†¼Ñ¾¸r­›Ëa‚¯ÝV®²£jÌ‚éÕt;«±–WPHì¨ur¯fïÛ´×B³¬^þo(<ö¼€ ¯1Y8n7’uo û¼TVϨ]Y¼§“ 2´û/+i£w—ÛÜ÷+ Ç]žÉ¬wEÊò-’ƒ“ÑËKŸ>Ëíºí:sW½Obõ7³’ð¡Ï:·WÄЊ—r“H¬u#ÙÜUVu~ôÛÔk=^ö9¾vˆå¥S*ùŠžèšÆLÂñ<«¸ûޤ:¥ˆqçé‚#Eú\(„]JÙ2ÍÙíóVUØžP6Ê"œLeö£J»¤í®¬&þÅgAbðcØŸŽ#Ѿ•¨'áæ<úÏ^£ºóWÚKú^4Ž99Ú.RQpÕ–šè+×8ï\Ç‚¶ƒÙ¦¥O^ûNÏ PWl ˆøïsåZִדV’±áÅ×µ›W‘éaûÏnÞ?tнÀùWÂßo;­É8¶‹¬9¼ƒû—R–œçYy޹åq¾»~凳жš)u'-ô°4Aæ»Ó«ÝuÇÒa]äšïüïgíý×S¦ QÏÜ;÷{ܶýyî•oõó­tŽIV§áƒEþíl7Dd®¬‰˜|Ýökw²w ±Øãx>;FžeMáš1AY41FÔ[6SLk»bdÊfÔišé@¤‹d´n^éO^õÏ^?yuõ{IÛiQeÊf’l‰›$;åô®¥ÝË8Ê·²¤}îûoÀ¼ÀüŠÔTÄw‘?2»¤{—…<¨}Ì~Iå«îvÐ}6ü‡pÑ»t²Z¡É ˜Òê@2¾˜†œÖ;Š%ÄyÀ8|ìÒÁÈlÚÕJ¬ßwwŽ*ƒ,ÔÎíõê”<ìŠÛΣŒ° #rEÉt\%ܰ;6Ø—²½áíc×W^OsÞ}Ь‘cÅû«Ê»ÉҼ°¬ 0+™x8帇¤»kÖkÔØÝ¾Ë2åÓ‡Èk»ÕÏ©~íš”bwZ•ì¨3Ô)æoÚfÌâ¶ÍÛå)qM7Þ^ÜK6y÷%žïŸ%•wMŒk^Ùá '…!ÎË¡Ô(cƽֽèG.Õ¢¸Ä:ke@½Pí¢2Ø×Úì»Ü¨LÂ"¸±LhòoUÿ³[÷LüÎmþÄ ”øÂrÈÛý Fø.ê¢k;§†(çî׳Þ÷­SãíÊï[( ÓòöÙó²LUµ‰SÛ¶Hú7gw\qÞÕ†˜3pޒܼŒ*[^¿TÁqŸ><§V*÷u'‡8ͤ9;ÝÜáO8{Ù‚ž‡¾tlG׃Ȁan‰!ÖÅu¾á.:¨'ceÖqÖ>͇ò•åáëá]–÷ÞÐ1:R콋ùo}SÒ?xÎ]{ÂeÕéFµÔaÅu4äÚ¤AQ2ö¯ç¨Ÿ;™{àäk„l„üH³¼56_)ÍU´ýæÀ¯XÙ]Ë<Ü«ÇC#ž®ƒ`#[M_­¢k¯yíÂ}x‘œé^WmÒ¯ž 6®mq›ÕjÛÝYbW'ÑÍ›šmÅVç ÜM䃳iR¼.ak(ÉNrÜ2¬'JbîTohvÛu™™5Ô¦ ÊÜ;€5Ðb°+ã…ûŸ]IÑ¥iôÉIÛ|…Ò À€©mŽ4i“AÉNÝîïÕç §vä!ç÷є¾ã3ª'^ɱîY½uâ¨æ]×7ÁøLiÌ&‡ay¬'žùüe;Ș!îšæœÃ¶ê\Õõ£K+–¢¯›Vñ¼¨½åsÚ‹­ç ÙYÚ“w°åŽ-¡OÜò…gf¾òô-—±*9 ãjYÞUÁÙk/8”Í·~ö5íÌßP]ËC–çn=™æ®¯©ªÊ+²QáEÀk7=)ڕжUjÃX>ÛúsNâb¥P¡B–{<Íg޶¶Nº7Ö-¤Kö¬st9üŽœ<­_nÈ^s¼A’o­NÀ°²x[±4ÏzûšãnpûÕ¾öùùʧÛÕ¯µ6åtÝo¯jX¿t¾dÂÖ&ç…•ã \"¼V1,˜É]Ðò j¬Št 9‹8P¨úzÃ㣭šº)Tnï9ûFðm)´\»ÀuKÚaßàr®òÏÏ|g«„ßÍÚÀ° î:¦(¡õ®šW®*Å ÚLæ±½®ð69NV›Ü¼{—#’‹¡Ý«,vÝ#ÏWaMÎä0nä,"¥Y2œ+ÞY@ðöõ–Pj^ËIs3l Ðyl·mgSƒ¸mævVN¿†3¹AWMf=ÂìÓºV2„Dä­îŠß…Bý[hÃzó)%ˆ¥÷Dwo7\÷°ùázsÔ>kÓV{+³Ou©­œÈ òvÍÎÑ›8´ëmNiÃÖù°V¹óØòUÖž / äŸ âë.Åg«Ã;Ç]q4"X=´èÍÚ m,Ϩ¼üõÓ“ÖzÕ¾¬½ážçS•°‘¼Ë l dÂä¥ÒƒnêÐä–D:¼þ>ÜnysÉbåêñ¦d|M_TÉ(öï¶ã—@%bø*tñésÀò,9wA*ÇÇy”§BærLŠ€Q·ÝµÀ\#rmP¼ˆe@]MÕ¶ Þ¡Ñ©F³9;yõy_M&û»aò5šH«`qìÛÞm¾^ ße™7ʇªkÃ;‹|ÁÄê銜f’¬¤ûOû•â.¬}yî©^˜Á¦ýðɼ„½™"™œ µ•œA£ÂÞ ÂÆMµÞ[Åo;»TsõÓ×…x<4ç Óµ©Öy(\‰]a”о„Dç uÛ5¹ÅÊ'4 U½§zEõ>qu–µ§Àî¾÷€C0{Û^ÍS¦¹ƒg­Þ7ØR´¤Íæóà*U²Çe%G.ñ=({0<³ï/ä¼Ç^àx:¶ÃI……xfï"ô›¸“\ÁÍtŽí™š»°‚í_mM5xP%ö›tej—o-J±EÎäÖÜyiäñfú?w«­ ‚>J±m… œûf^*ˆÓŒÕ¯Î˜¯F¨ÜêÕöŸJXí:™Ò®‘¼©F Ñ^9•6K½Z­äÁWÛ«Ô¼m<…ëbý]ÕÄ}ÊîÆÑ ÆPáÎcðšÎ R.””™VÝù¿]¬ôì<}oÓRÄ‘¯? Æ(öå%æÚö«Õãêôù̃Ùçî’° †F^3ÃÔ,rn-©gÖ»L곉™inì»~éFDàWÔk/Ý ”ÔÁD-–/`=r*㪴ZÍÛNãŬ†«Ž¸ fâx¼=<Ç»°Š÷®§LNîÉз½ÂP§6c°=›­Ìì¾ÔVwžiú]aÒ1L¹ÛÒe5w2¦$×­\c«Úw;¶ül¤+(®ê=1NöÓ‰ê#N¢  &.q½jÌ,;/¶9K¸Àõ«SqÔ^ìžôïo¼ô>Ö•žÍÕµ(-ŸB.ÜíÆðʾñ¼~T ¾\ªºUµ‰‡~ÕXÙ/8ÕzóBÃ\Ýöš[%ÔN•=Ð]ŠˆÁ+HµÊ°¦·A)ì/•í=ñ˜xq¯»²ïÚ*q<º¼%÷¼ç)t«µæ›º‹Uûž°šÃÀû×nZÝW ‹#}´­öfÜÁMÌtׯ+{ ™Êö´EmµÌ Óm­Vô±Ú]°7*ÆPçÜkÜß{»W¶²aLÕ s­Ö© ¢íŠ×a5«¦êx¥ÛÉG2‹ •Ñm!½ug¤7°Ü©³»¿G†ÞÔ¾kOjÍÞímX`„hZÑÌÝ}ÊÜŵí{ˆT4ò™c£É;nƒNfÕ¼¡²eňw¼PgL¤Ð÷^‹uO¼M¦a½Ö3žišÌvò-g(²½¢étËÑúLôö¬£Ê½æ²hî¯,Ñ~T%ëAò¨î„Ê[(ö>©:<9 ½ã²ëœTÜo-÷Q$‡ ë]éñŠÕ žÚ†‘Â=OQ±I:umø¯ îÊã§4Öì6ô_Ób9oÑi•Þž— ‚y¹õš*jï¯tÞÄNUúƒ^xP¬®”¬{wÛ¾À™2>ÍÔooQÄýé \ÍoKC•oSY¶—žsÒ-\ÌîS@­y( ]cF¹¦l_Íå8·U]v>íÂöé¡ËŸhg)§œ¶Nš˜DÞ¹þ¡Òª˜+8Uý•ý®¯Ô–vÖ×úýJ­õÚT)´ ¿Q¡Ü÷]^+²LÛÛu‡RÛ×À¼ë¢~\®ŽÒZ3/MÅý|»žøWx âïÙ†Aà*ÖDR°ú։ޫ÷¡Îò·að,ùýíÝmW¯¢×:›ïâebB4ôËTÛ±t÷–JÜ¡°©ÇÛ´êÞíL—w«µ”&‹¾»Ù‡¸Ö¸÷ä•2²ÝÄ`ã¬7 hy-b!t.V?wžÚõ,@¹3y«Hí]JÎe ~û1f—“XÊé=ÆéJàÂ!n½Ûµ$pzKtT;³ŽƒÒO3®™Å_gT>9žÙÎîcht,çoüøôiΕ¾h&…mœ%u_hé§èó¥M*M Y&|¬.Á•~Å×µ­Z«ëz2’ñt&¯V˜)6k{*ñ×¼}ß½á¼,r£îµ&K/´¾ i ±•ÅõlG¥cM:µCmÉØ*uû[wëÊãž_5:õ{½ÈOnžNþ'¢ðßy_ž©¹›–Jz ò~óÉÃw…ÕXð#o¼nõpœ½×Ù”Ëy|ñç¡*ˆ ŠÍu›<³›seÂ}¬ëÏSáé+|sö<à{r‡8ǧ=ÕÓÒùº÷“ÿ;²ÿaPf®ês=GŽÝ " }ÏõvN½“[±’®üaÝΞEø\š:¼—>ó‰*…ô›=×Z’J¹@¾¨°a`¥Ü@ÍÜÃ*¾¯¨Ó’’ä­^«Ä³6RV°âÅ|ÎnâgµuC"É™D½­=·:øª¶ÆŠ XØ´àÇtºuÓÏ+Ó7'ΘT£ì¥P·–ã{yå½5ewgÝ Ù»«šÊ|zìrìºÌéÖ\Phׇœ4ü›è ׃9ôíBz™–P»E=Ùs8F­¿¤¸Ó8ëì (_.×kìÅNÝóY¶*ú$I«K¢ÍÍa¾¬‚aQÞz´Ó­ÉwÅœvc\ßWfŽ‘•9!s¸ ÚûkdaaØM¾ùÝ]¸%Û:"ç Û.4ÅbÙ*4dvТ/Aê³ÇG(dlÐÖz‡»}1Äñ*„‹š¯|VÎmô›Uõ$ZG=V¶'Û×ZïÀxj» x‹ìÄýU{b\Æú-l¬÷7©7mwœÀøµÃ:,•½/îU,kî%aR»y(7“lZEwaT,Á¥Â•½³3‡ŸYtf üø–ñéàyD¦®uáìõµ«‡œ|ûÒ|}ÙU_d÷­·‡wŸ°úÜ^›IÛ˜vºõÒÒ9õKŽVöƒ]שsuŽìÞî `™Mv«³Ĩ»®þÛ¦ÕéÌzû$Íû—RL*ž©•4+1£•#—íŠ0Qì„“kwìjèÉÝÉåàS:Ü2r`àÍ÷[u–‘ºÔ’Z. µÈœR.Ô‹Ûãv»æ5ÎdÑUÖ 9Ü´T¡þj¶¥/¾î;Ü—dúãHʧêfܺfÌqÙwýÅäçšLš»|Õ*í·vO½ëÄvÍyeµÎ§¨“Ï&.|C4i fVkwîK·Ó¼5>Âé¹Ödg›Ýû4”<†úL™Û9J‡]u5Ôt‡F«r¹]¤Å%X@‹d@ÙÕϱ®úesºt"ïõFš77Šý¿d¹7ÉXv;ï®Æ'Ù:·f¥|/z¢ú뀤q v£?ëÛP±¥âzÿÄýä8ã©ûSµEÈ\Ýf)­7Èìû-Nd!WjìPU ŒM´ŠÜÓÅî”÷É^¼é•Ù¯;m+ ¹«q^ŸZ Vù$æ<ðFô+>^žd†½½•ä÷Ë X-X:¦H÷4Fü$ÞÚׯ€½¿^??%IQãATà6_5Ô©2›+x9@ëq|öé:3ºežÖ¼ýGpvíG]&“´œè†R×Oýžª\ó)ý³ÈÙg]o‰¦loI6Æ*ˆK«ùeÌk¾æ»)ÚîÆÎqo!»³Z;[®@ÝÍÐlŠN ù¾v¨±o­Ü7”XŠ%Ç`w)ÌËK-G)éÝ̘²Ûì„°û¨Ý•˜Vþ¶Ö \÷•‘ÂöNBâµN;±w½0<1W.§R1 íºÙŽ*põp A²N¥ËËSÖ<¾![”ÉÊLë™m¼5’€y”©>Zc¨ï×8 -áÀ ¤ó²m¶w ¹Š¸Óf.¢uªÙ½g=åû¼c­q¤DòoŽëÇFíb<7³®:v÷Ûé+{hIÝÙªêÆ kX]@©UIl!]ãYY&‹Ÿn`¾h_SÚjh6ø8ƒ›Ê–]H¨²ã—=-ÙOxví»úÃWð|7É(˜EæÝ[{K_Zº_2ã—»|¢UÀ[÷’¶…©sÔ³Üíïo+íèNV7Æële¼iÜu3cA'îûÝïpÜÕ§änõ×cj1[×Ý¡ß> ºÌàDtã¥v*4®‡fFXÚ(\ɦÞÔº»»HÔˆÔqÐ åî^õôî‡ ÆíîP> #QLsÜôt¿TjÊï-ºõ ½ Os»tìióç2°_hº9՜ޞÙN‹¾{­kâÛx;áÏ-OÞõ_d÷˜ÊÚ4Ȩ÷®áµ†Åk˜¡}P3“­S¼Û3UaÎäVê]|UíµÒ»Ÿo×G²WmÙ¤€p½œ¾È]‘ݨ8Æ«³o{r¯•$Mí½h™‹’qh1Åû4=Z[»˜Âà®nlîÜc1RußVÝsYØK}xJ‡©ä#, Í,zæ®È£9w}áZMùÜ×Ã{ÛêAääo3‰O¸Ð%FâÞÎÓëg¥:W™å| W¾Û¢6cÜ2nR‘^ŒõpˆÜÇÖ„j NCÃbFt[Ó&ð¼1ir‡;¾Œ½;F.‰áž´§—!åÃ:vÑwuÎUùÁòöÞbìfímcίošr•œ'R\°œ^§žr‡‹=;̈â<Ÿ]$·äcçíš³u[^\5ð¥vû+bá]›®5¬ÒDU÷œÃvù8k/¯{+L|s€ºj†;¦RJúÞ·CEühíN«Û{¾Tg,‡üWûõ{6 ž£gÔ€»ç.øU‰ßܷ療€óYéϪg ò‹òsqÒ"b¬Óº©\3Èߺžr¬ûÒþ©¼ØÞИ=¹Røøúþì]•L··:†>™cW.:2­Î·YQ$nU©VS²®CÞeµšW&•ÄvÖ¥’ˆU·å^“1êmÞ8£RuŒ:ÕNi-ÎMÔ»_=5‰S>íjº îvÿ¢³º“1޵y¢½«•‡rC¯:é4”1ÝkXu×S•øãßt[ÖðvØÁP;³”&áóÔ_xzA¸Ù Ѧ'A;©‹ÃG¿rqqÚé;LÎW Ù[aš×ì&X®©d¤v‘Ï9:ÚØ_¹ ÚûåýóׯzüT×G_©€$ÄíùÅ=O%m éÈfÏ7ÙØGœÎ¥­û°”iúºïº­v¦â¡T—©pS7\¢–¦ÎxuÝ׊{«ÔNã¢çzöúíùŒ›¡g‚êèßk,—•¼m–†Þ]üW}Ö4-H¶èâ¯%·â÷³–&;^Kˆ‚>ãžWØ¥ŸX èC=”–î­—=ƒo¹àQæm§³·È+úkßÈš7¢ŽÖñïi帻E=/`ê5>¿YïS[‚Õ3™=ÂU×»˜[Èè)œ>thw|/ŽÚ4¨+;bæ™w®ˆ{»ò¬ˆ/WÅ{Yç£BMÂL"vIzÅé³ã=ûÙC&YÑb^‡ë•ßÐßî/ÀükUþ9n¥€Ü£b¿ŽvÝK=Ÿ~ÓL]w7¼Ñu—a™†gÙüÏbø?V:Ÿƒ»Þß-~®dõ?eõõMŽ”Ë¦m#^2yV²W\+~)®S8õ‹5§…#Œ-¢¦ÀâX×­D¸Q©]ĺ¶4aK¹ïL˜Ým°FÖ&›9ŠOcmÜÌÚé”ðíq^¬î§”Cæ‰_Vo"E;‚×L­&ËíO{àô,à9¹}½J´*s9aŠï¹Ì:1æ§K‚¡´³sËÒ_Á÷—Ÿ Ýt»<Çô´þÙ_´ö3ü*À6lßä𽕻bzýlJ}\åæ`é)ðÒ²lÈÐè†R=²ÖÜ'âìïR‘tÔØ§†òÝåâ&MšShåh¥Èm¢xPÜZ«€£Ã²€8T^êEݾð>òxH>OJÊ™›¹Üç\Nî ì« »×½ì«ñ¢ gÙÀ{§kècrÍtfÅ$ç`Þç^â‰Pçpâ¥Bºh`…-<}¬¦A%^v>]Õð'ŸAGª ½™¾ð®¥œ¢(T´»wÔ÷\¥$¥u½Í¸›:kfõÔóÍMvçºzò |læÒÎÞíBpÓÂ:]¤/#é’Š5AÐûÛ…t²úûÉ(|EG‡¨yð¦,‘‡ÇÞö_7™ô;Sì¾õòeUà ôõg¸RòO„™Ô.î»uq˜8þʜ֮#’ê&¢KP^ˈ©—µ·xžp´«¤=]-Ú×цwu„1_tªðrL‡G»"S’FñÏLÇâÁâ¨PGÕÁ«ðF zE^Ô¥(Xë‡ãÌÆäìB\ë‡*JàNéöìÐþÝ¡<ª­,ß:Yè¦b¿ÝX|„5¼¨ør*î/ÝLëVhLäû)—ž£Y; à=´>/.Þ-ï©6ü®Í×BV‘•g9hÜꯢ€ ; Â,é‘ÖPÀ_t»EJVа})Ü‘ªÖ©±ž¾òöÓ¨´Y[µ{Üõ:8î]4Q±Öw§Ú¼==éRýëÍgFv™þ«ýTqæ“t p‚ŸãÔKä)Â&ëÆ¯ ¿]wb[lϽˆÝ®cÝ—KÌCÌvùûÕÜT³¹6ϽTNì›ÕÐtÚÒû²ëIwBxØá`ʼÃw˜¸^¥#Óaƒ´p* »›¿%·ÅØy:ñú<ÌÚÊ×vôܹ‡F ;Ÿ¹Fnr¥Ghc‘Èïl¡±¼h½­îq`²úíÛ®êGˆÝ""¬u½³—{Í?nl<÷a”§¼¯€~Ï@êg°¯oHû+««#â3²ô·’*Fåä¨PK…w§›S(P¾ =;Öèü—’îá"ƒ^ݱJ ªUA]e—ÅøV{g'SokŸ y€šz ÐÛKÊîèà9@ntÑ9D½a™{óWÒ—ë®&¥µïØ$ï?fæ­B½£‹?#~ñígc\pJ`pí e¿q}é¹íº€½q.Ô#®°ÚYq •ÛLW9—–[=ÎSˆž„^å±1×¹õ,¬ž‡Ì€òìνÒü¡êDôx#Šì§«Ug‘½xCÊœýÒˆ}bß é”³áhåº-ŽÉmjwVít}z©Ø¼îc¸vÞ.Ý/°<Ýc)otÓG6˜ ’scá½ÎÁí±@÷píh‹SZ0\éª><»g]ßl7PžérQµÔGm“åæFKå¶ßz/¶ 0£×brÉ31²è£¼>ÚcjÐȰš'¹×jÞöy »»œ(–îÖ&±2ç[…áÙö”¹$ 𬿨ö›4Óôwuê@>6Vôi·¶fZ½¡ mÒËÜÉzÆ®#6m×_:TɱÛ6ì%fåó’bÃ}¸s/zö ‚Ùˬ–šo[í“Èìß//í‚ç²›¾èó}°÷£p gÏ•é)ÝÞN×Mð»­îXêa·…Ÿ‚\x]—mÍ´øb&KÛìY²Õu¶Å(n£[CLìÔo¸Æ~–æšáeï WÕ~ãHMòèmøGW ÷²¢o˜ _D8ÕŒuï ÑëV^•^qzü±¾Ðm:xf6^üñögš±Õé˜o ÷ÁLUõcYåfo ݮ̴ÞcÕ€ok ¦çtD2¬5ÔpÀn_:ª·¤Zã´Ì?uÊí=¬äO[Ì¡´º^ê¦>>ôgyoÈx‡ë+ÞçK²ú›W!ë.ôi•¸”ƒ’Þ\(jÊ<‡laÉ·5l¸±Ê ÝÌá1'Lªî–¨fÈtï!žRž¥Í©V±[çR¥ècs©qMvÂÈáÓ—žßyo• ‹n—º?®lîÄ(ÂIr¼JÞ!y!®] «¢"½W×d óÀúŒyGWRYW^ÍÚ‡›¦‹´ïi:£Þº]fý^§^ {ÝÔxJ<±àNx–:û¤›]»îÉCqñjö­ª™èv¶HArD8ùz'Œ/rû°¼@õ= %àú½læÂêìàwÆ^õ^à=lü–=ïp¾§ ú…JÇZ»9´× ‡n(+=6°I²MZéÄ^^}kexçʼn‰wzP×ر€ ^–kù¶ûöÙ!•¤b褖f«TçãŸÞÜ#±^ÅÃðÖ(u÷]× “•Æ Öä£èêáX½Ã×)ÌÏ_Ç`2ßŽŠ¦Ê¢è½O:˜ û2‹«RhM|Àö-PM͹œýŒ'ñ‚¯í±å6WsŠsÉÈeüMZå64Éõ’½ïB2í[Ø{ÇÚ˜SÐĽ=Õ*rt¢BögB¥ºËcGŠ|76–<ÜU½4t<¯KÀÐÂ8yçê]¹µ£±Šy««¯lGwEIJès­ºïºµïp—ÝZ@/®ÉŸï,Å]`/"…Wù£B‘v¹ð½Â\¢4 -[siä¤IÝþvÚfÈ:T±Œwóši}£vîÑ©D¦+€ž  §.çÒxþ'læ©Ü´=¾UÙ.ÊœµvNëÝdu!»íYAûHä©~¾á•xÎõòP>ƒû±™Ç§è?%Ø/²Wn˜w9e*×,Œ€oZ¤VÆ©S2ũ¹lìz:&úîÖ\¾?—›1{:<¹Ô­¿Ié<—€œ›ûΗî×Fëw.Zâu;íOu4èN?.çkS¬î¥ÝßJî ¿§©÷eiîEz·³8 “´Üóºfô¿N½¦'m5×¶>ô[kØùLš²5 +Qƒ»­-.h§& õ¤nó­nI^ëΓg``í¶xu Öu¡E<»óMP¥"ž4_mmûÏkG™óà¶«¸ÙðÊðé@Ñ eGÛ¥lp™º+ •¶öu”;c¬º›š¶ã£Q]ƒY]pîY ºuÞôä1$¥^à=ܪf OJ«½qxAáêÍL†¼9qۻʵëH•ÍL€˜Qwu¯*BåE]™ºŠ/-¼l¼6¾Dï¶¼jWº¯bf[ "²~†¢G´g“=ELÒA¼sz Ëæ/¹÷lêØ5ÙÅô o³V‚úŠÓÝks3¥âOâ›»•}ŒhÉG†Ãw¢Ò˜rƆóÍwMˤ*uÝÍû’¤<\!©—§³ŒÈû:DÉøÇíôÌ÷†š™ªç±©]«k¯n»£(JCCLc´ër'hÛÊßµMë==+(ÞS‡/ݧ¦ü}í´ð˜a¬8W<̼‹%»mƒ¬k™9áb:çúÃåVݧF³8†il¥Ú°Û¤Ý[F‹5Òmk}ÊÍ®ÁÀÔ¤ÐAe¨ ‰$]qØŒ8l·Ä<Ô!”]¾túÁÚOfáLö;Ü!c}:=ÀàgvMJC{·o•¿sr̯m²£€Q>ö©ë‹%öµžó&ÖÚ¬~öyŠŒ‹¡”¢ ù,4(F¨Õ±”xÐZ{rSívÜÎátZúÏ•“c¡Wu´2ìîÞ¹tЮ¦Ïw#Kº‚ò¾—ƒ/ŽE‚%êêD_Í+}ƒyÃÅ×Ýî™ØJz"¸\ú¸&r‡wïǦ·­ÚÈß©öмQÞi뙫^ì«î˜^Öw^9và'"*RÛËHo=—¢ôÛY†bÃA#»l_)&ÏÜð݆³’¯˜¬b ‹2óƒ‘C!3jÅË‹V5; 4÷øíXºå*îOÎû ^*ëf–f4­ÜhḺ\Y„ìY‚ðÊñ ßëQøÚ3æ9ßNéÁoÜ“Érú4:ά¥ž=OÛ]:š?#d È´Ï›87¬bºé!]Ì\œ¼#÷äõnM2w µ“©øîh,ËTAY[ :”9<–[¹µ¹®ºbŽLÌ*rLòá\`àŒÞm š%—kT“ŸE‚û'@ûcÐÝÑ€X#¯´kÛme‰! Y˜UóQŠÃ¯$%Âhm½ Ý8p×.öÞf~ò÷“Í7“hr‡VWL¹X£™ë=/¯«ÆTXÕùÞBìjÙ¡+y×Kn·}ªG)ïº{Ø/®ƒ Š,z^•ÑDLy™WæüU/+¯ö¼Ú¾»¶¦ÔN¼{¸FÞìÜÎ5~ɾ;^ëž Ã0^êExyçðïêçíý{_‹ûn~’½”*x_©º¿—;öJÚ™¥=hTç†íCO…õ*ÜC»`Ÿuf>¶Ø/6¯šê…ŒÅ¦¯:Så§aH’? Êõóø‡KÜQç:Îû+VÔf››‰Pé[‰eé=Ï+1BR‰î±™Îmõ‰RÇnVüÄîÈÄRì°,íŠÆªåedCöö 9[˜gÊïœÔCÉ–¥ÌîËIà4)z`u0Uþè½~é)^ć—>‹ÝWºý¼¹Þ ” mUÀƒRï²ó¹÷;†6&Ìzy}rñåÀ¢6(4[i±qvúJ»¨Ö¡V²”´ »ù£®ô+¬®Õ§/Ž©œ&-Æ›¶šäoý—‚§¶_¥ŸC[mØä/ÜæªrëGhåcR—)§Ökoî|ÜÛåÁuš›sŽXª.Ã¥y`êüÎñº7æx,ñâ6"ì=[º9âYݽW]tDa“uxÔÏ9•åÔ^=÷ºr@Ú÷±ÎÍc§qzþgZÛº :®×ô¯Æx&ö¶¬o¯jz–6QÙÌ`Ù—ϳµ§‹Eò9­oîìž|4]•÷È…Ó“«k˜š÷µýmubmvq„MöÝF¸›¼Úð¬ d×Sa‚Å‹‘=¸ÇUß(–—™ò¿_vå÷­ñ„úã»äs&ÖÞº¶ðË·D_½<ç%9àžœv÷¶…ÏËô÷¢önB¾>°¨<<&‘£Õ™&ìºßCD²·RHØWŒW&N+‘œËV—Øê/ž_ 9Oï Ý‰Í ë1qå¦e“[Eqîp:ã–t„Áâ®åœŒÔ˜³Ù^5=¼J#ž¾3¨BLÐö‘Ä&˜NY÷rçµ4ær‹^Ûà¥Lïue„&U¢…!jymsÉœ·tÉ KÁíi™³—n){‘-ÌZZoÉÈi¶ÉÔô‘qW°è€'ëì¿6ñ½»*bö4˜ÎW5 gd6ÃzÚ ×ïËöeØ&‘É•Íó¡å¤z³ÅÕúSêó}ws‚†ÂõXËåR*Ô7F^*K¹WºÇåî,^-‡Ø—½\,’;i—^äk­õËÓ/¶&aà½äcðé÷ijå6³5\[^LwnʱÍ Ž:›:!ÙaRÓֲ̅¾ë»v‘—ÌÃ5º1mÃc<²¯)žêRõšòàí¾ÍHb&õãë–ÂÅšZB­\9å¡ÁSk8TU%î½»,¨;­‘g°zìöô2‚wNÕÁ ~"¸Ç–æõ9ƒ×EBC€y„À¸>k’èñ°Ås&¸f­×¨Þ+´ ÕÜÒø™|8t!Ñϯ‘íœb9îÌìôx`âvQWzÒÌçÐ%5NöÍg^åõþÈÇ…®±ú‡±rÚ}FŒ56rؽ}}1;ö½ñå'ïyß—=ßW;ÅkõÝæe×KÙ Æ €ºáî><òÖz²ËØ¥ÇÀÚU³{·y2U³ÃÎ`ãr…)Åuê §D«·®åÑì6]vëìJ°oÑ mÊ-P] ÙÏ1ìâ ˜wÍ¿Wfuߟë[GÛøZ6úó0ú%~TDë@ˆÃš–è7Õ¶ÒÜýé¤.ë‚íöƒìÄM·‘^Wµ¦¬e./±ÈpŸ½¦ÖK½çL™¬ðêÊ¡ } ‡Æï+}ÍÝO¡3ÏjùTíy—ÅSSiËÂú)3¹{*y„…{=~Û]ÍÊïo¯À,«»Xýîº ¬]:¯ n¸3ËkØmín‚é½q™à3|iGû¸úÃz²¤—nì8 –篟^¥ËŠ6±VzEƒšÓZ¯B¦2¶ý¾÷0&vê÷'ç‹hðôw÷;=~Ñ«f45£|±EÃííˤM÷ŠÛˆVeOœ›EŽæAZi³ín¸ÁšrÔ¤G%39t+"©Ôk‹5µlSÉÈÑ ¡yo³q»0¨(KS3µ 3aÍõ¾½©ØÂ¦tŒÒ5½çê¾!Ãc0¡éïVœb³›ÃÜløŠÔ²ùú ®¦9:l=ÛÆcê}*f‹»“fô¦d\‰ÊвQn¾¸‰žÐ‡ÕÖÐq²kÞ"ÝŽ3݆*Ûµcc©%p"rØ•z«|Ÿ7½w®œ8ÄÜâYr´ï–7òý7%€ìzT¶‚ÔùwX¸îÆJ™Þ¢ºn%%…½îáì¤r’BëÜî.ðû³– µ]¼•©Ý<|1fê@÷ (ïP'lj$Ön’¬ZyÃW]¦[‚»xàô* Êô–:¼í³h8@ÜwIÙ™ÓY=¼ÁËG¼ìfzW—ªÜ@‘zàónß.®zf+¥¯)wv©ñ#¸eñ›– F¨ï†ãã•0vÜSpßγº2Õ³kVËèÀ‘©® Îuž: ¬ò²…Ö*'g5Í•+:7[cD¡Ø½~¥Gu]ëÏ­å¿»˜ã¤…-J-\P“ÅæØ²çoÎ]_yêÞ7ŠË.˜Õ£ÙKÜîzƒÉïTïÝöè;ßhn€½Í¹éV /w—V Ì÷Ƶ3éXV—•âÕ£pyg­ŒWwÃu®WXÂ{2ЗŠh†Å‘=ÕošrîC”±ä±Ë¡´ˆ¼kí¢ÏT6êÊlѧ°Üµ-_Tà"yœ¼o+)æß”o=ž›Œ?vW0ÕŤŒÙîë7¼êÖJ1}«‡=5x…0yÃo'¢ùrÈë¹VÙÇΓá8ðg+ç¢c6Ð4&uÚÎBó;›–UŒ [»gÞŒ‘Õ.1ž‰^“w™Ø†…¹z¦eöô±Õ7’<¨}?±þü¯ßŠ~ÏÛI°pønÃY•Ü»SéZ ¿ÉwǶÂPM5ã¯׸+Ôxñˆ)è&é^Ã=%uãËK—ViÆÙ¾½•k¨íN1˜rÑ«õ÷{ÙîóbÃ^’ÞÝK¨ö’nޱ»Â’ƒ³OÊ(èP˜º_o¤v²S^„j¬ã’â­xžðBsŠ© [ׇ++¬¼+ZW6ÏŠåŒDÅgÌ Ð}k­nÊ_PnS®ëw¾ÕªäÇyws:Xö–Й»¯É¤…,FÂ+Tƒ(ë.·w%¦êúA¹ÅÐÂ-­BabUîúVfñ*˜¥3‰ÕÑ«ð“î¼³î×Ùóc–U‹º¼4x)ó#œÚä DN¾ʳRô*º”\2mŽå®ÄééÚ×u?x¢,‹7ç@,¼«ËШ éZ=a=X§rí„,ჩ6eÓùœÎo­£G0 “$ˆ¯£·[÷(VûÍѽ´…5±šf *ôûÝy’Žïà+¢æo=äÍF¦òX\`,ï;ÏpÈ…5Á¸¼ ,|+ÎU‹õe=´ÛòAÉäÙÈËo NsÌ«NÃf„SšÜväµrä¬3P]EšÚŠã7/°¥›&÷×Ò÷,┫ºq=WßLLz³â³–c7iÂ>!×|ï_f páºÏÆ8XvÓŒ¨ñø¯m SëZÔ ñÉô«ˆ_* «”²¤²n¯­…SqôU1bOZdÆÍÅÁsY—j¦š3‚¬Ùkëî/µj`afL¶¡+–ó ³·ËÚfrÚìu»]Á…µv±3)tWniÂFŽ©»H ybnÄÇjç+p&›nã©|sî  ³Qu+Ž>¥E鉔µwRNÓÐi*¬!Ydˆ")l(+²ZÌ«¬B“'6†¾.íW:Þ/öÛ¹ÅûhõZð5hrnp«ïc«uɤå;k¹á£Ò¯®äÑLÙËÛÔßNxgIË5Êou·1P}2Çm¡yÛ…Úl˜†GƒÀ×Ì@ÅÿÍÿîÿñg´L·jÆÞ¦ê4›ÏP ƒ ,Ú$$ÑET’1ŒIÁG *j38K¼$A‹LF<ò&<ƒÁˆ¨@8$ Ѥ8 ˆB2&¢½Ã"’&D¨ðÌćžuXàoŠÔœÊv*³¶c½¨øqµ¿ßo}åŒÎN¸º=h‹ ÷é*‘Û±²ßCt¤u¨L5Ûb ¾g£ÐT69öTX.‰±léëÙjul#imѺF)Ùž ‘˜³½Sªî‚§SwG™ÃMÊ7ÎUÔ±:.±ç\š÷gWµÕ©tœ’K¿iìmÁl5EÓ{"\÷¨;gÚÝpc2Ýf³ï7ñ|ϲK}»]g$¾Ë·ÌfKÒ¥dÛÐ]Ñ‘¸(ç\<»¯cm=VMïgq˜ó-ØÔƒr‹±‡6Ùr*‰)®¨áw‚ñ3V%Ôç;t[âÎQàf‹«‹4e†Ÿ=ÉtÞïšÃÝÖÙ”}«~{MZ<*xÓ*ü¥çQÚmŠjVÔí¾c0ΰís|ó”§^E©c»'8ì¥R†5aê¿ßñ•ì–+{G§ëC/îMü³–hþ‹Ç³G«r.z-ϼkp-=”¼=4/tTgÙ7¤¼r×¾so\\ŒsÖÌí¯[Š aÖ -f.á™vÅê¼÷g'Ÿ_Q'ÄVxK3CßuÓ½Îq¶ý¯!±“Õ×Þ;#îd*å:£wlz5ìbˆßqp1WS«p~LñBܧ¼¾•jt½»$Õ›‡‘œÆ<´ôý懰 Í“<–%?†‹“J9RñYnç5L=½û¯’ÁŠ+ÛÒyÒ¡–ªwÒ§ØL§Þ-Õúí/(åçzú˜ h×h’*Åz‹Ún9ANV…ïëùN«ÎQ×–pÏ.ËBêzB#.ÿ³¦–©éà“ã¦Î…ZïËÓÕ£ËÃÔÚ‰A2¼•…ëÓƒÍèëÞޱÈ÷‡—JÞ—œMza£0:V£®«”ƒY"¿Ýœ/ÒÜôÎ TÃ&öÓEÑx±M†á¥µ"jþßBÄrôÙÙÙ¨âµCdã1Ÿ´>”ù8ñí¹µ•KA£ÖËÚ”°i} ËŠs¥½Æ±ÚÇP`ËØZ‹ ´©¸‡)»½K‡VR¢§;Ó§´»Éßy5mªÇ~¤ªìîøÍ£/zæ1vùB±.’—[vZxø¬zìa¢ßÂ*"§×A‰"Y‚›²¬’Mç»Yl¯±>¹‹i_QÁ½j€O.·¾ŒÜ°PxÌf••¢s<ûUâçWv4rÚ[3Uâ«êÅXÊfÛ;åäG!DWÆQ§?€/¿#[oÐ~ìB”,/Óv»Û™•¾Lɺý;××ó/v‹«¼q6bk9Ò¡yxy_œaÒëë5kp ìÊ {¢O²ôM#×m+ êr«*÷&åkp Þ ¡¶ºÅŒøEz¬âÎN†c0öBÄÇ(ÎÕ5‘¾nVh'ec$ŒÊ[5w8ºÆhÖøÓâÞ5|s'I{þöÍÔ¾ÊáŠû«¦ûã%=àj…-ÕÄV«ÊS‹’=Þ…S&[êlNê{«’ƒZ_¹”Ö Ì­ÞÌ"½Q÷:ÓôøQAX ®s ›ÌëRë®O½=¾9Í_½Wæ;Ýõ¶Š¼Teåz´½®ä/‰íKºUª‡«0­'…Ú¥êÕl:U•|ç W ë—luˆõGç^Ö³j éhQ¼TØ„Už÷^$õËO®­Y>˜Ì»rµŒ Pñý=VÝ¡»²„ábò¿-ým"ÿe4`„·Ù§ùïF¨Ñä¬^W)Ú–r ` Ê)î&¥M-ß î`ÊÕW³påÛNûîYŽ9Öú™ö•auk«QwWní7ÈVJZ¯–=GÔ²Jjëusp‹ZÞwLµÕ¨Ä¾B¦X1å„6È0YZj`ÍË”bvÖNÂù øZ«$2‰aÜ&Z… ý!­ÄŸ#­˜ïzÇ­JBqܤ£©‘£•Öùßµ—GÚÊ4Æ¡ð<Ì¥xËupš‹}Ó^¬Îû-yWÕF¿âñ~j¸øƒQ!Ù²¥œ>T„bºqN®úó¯;ucXxêxô¦z¦IÇzsZÐ/åõÞÈŠy¬*ÚŒu`y¹v¬ÔzÓò«öI¿hñu{È.*PøAí¿)M½û=D%L`tʃws_U“W”jwJwßÝ^ºëg«Ô®yµ ;Ä7Õ¬vÝm<;x—_¯-O/yÂE—j%k=·#³yѺمPÄÆó¿ËÀìõkðd‚ò…óÙyq kœ¡†Ù‡,PdÁbÇlÓôwsk OuÓšÎ^‚¬\m:µÔ¸Ïn`w´ómÓÖ3+›uo]¥ˆõ®Žs€Y–ÏRkËË¥º|lone3Aä÷™W{ÞW^£š¬Ø°:€ùDzâÃÏíšTìÿ~§3Ùûi²¤¹+«}6aº Z]زhF„Û]fc¦×u®XÔyªg çiÞÔ9«ùç·3 ¼ —ªQÝI/k¾µ¯.®¢³ã!ž6ù¿^µëD>ëWRs/ÂÇ\£o“ǧŽT{NwY+©ŠíPc­c¢)ŒLìÀkšê•î弇E¸ÑÞÛvè¼Æ²Ú"(‰›ô­fA}7i»{Ágnó1]™/(¸zyŸ‰8–ÚýÐV~™AZn¼ó¿ZžÜóôg=éð¨mžëXqà}í+»t ÅݵºhµÑhœš’ƒ5•¼9¸ÔØFRKºéwÙ‰1T\=€å%)± óæ<rs´ûÄŒÚ=ÖvÇ'\ÆìÑÜí1ì@šÒ©h’hÕ¤È{KÖ´¡‡«XUÔ`RÚ&¿Þp%yѯ¯Õ‹ûû£Ùê+yŸâ÷eÞro[O(›Ù­S”{„Ç Û€w|¸tP„«‡sWÚâ@ oauº,!Z޲$£»Ã=½z®è+ÖFdAh.:aw=¬Öî¡—¹î¼.#ÀŽn ¦é€5¦úµÛà¨#ÌCv™µÀesÀ\zk0åt˜‚Ë×}ÔË—sg—]ùáê;팜ñ áî™±ÐGxVƒz3]¬Ðw¤/<4Ww®&ó`c¶ªfÑ mäÈج›;ijÝŽÍw3z"”£j‰áZ«')‘f<©æ¼ýêzµúm—êCv‰¡u¥½Œõ#€òŒ¯k©yÞt„ò½ÆîÕiw\¶ºÜ7¨{jÇY×€€Í¸(méðÞ›Ã2ô¾#fo¾7©Ì óÍ'±ÏНoØÀÌR¶;~³1&Þo\©c6—<€ò‹ç{f]$´5´M®Ûó>¡.Éç·Ýž8õTïÌÑÆžmä ê~ƒ¨ø.绽†PuÕµÚk=€ðaƒEúÊÝÝûÀ­‡AO¢Åö…Úk&¦éÑF´vX[¼¬ÖC›N-×Õ¤ØÕ›UÓ±tµÁƒÑj›ë½÷¨Jé)`ÚË^-hp2r:¼©ÖŒfnãóå|Û¥µ…R–;·Ï¤ˆ^pòsÝÌÁ{hø@žuì¢Û˜•¦Ÿ6À9 3-¬E¤iv ®Ø1që…ƒüSû½äÏ`#föûoè~Ñ‹Q¹ ¹û-Wíõgwq7ídú'İ¥”EÓyàîú ÜÛÊËa ˆ\o›“5Ä`ì˜W®?·FŒI«3Èg>wI Þ©w­æÚäÒ«ÔÞÊ1¡Nç ä4‹§ZÊÛ¹GV‡¢Ó¢ÿVÕåD¥\|Wº-,â^}u9¸¯µk²pÈ,^tF¸`oIì¥E/{¯—™½hù­Õ«ƒžˆSég|8xóZÌÖJ[”zLöC=Øœ>´¼£iü¨ ¥[}‚OuµV«&í®œ…@Ž=™[£ô­Ú˜ËöÏ'\Ò«ò/uÉ*TsU*æhrI[Ì[7ÛnMc·‘Rì;œëžrb4èQ ñrZZßd\ ¿¹Dóf—¤ÞγҚYCe™™­›;oÍ‚WRÅìi¡š¼MzXëõv¤´Í¨.P«ÚHmê…ÍﻩU{õzãÌBI+lfï Íal/WSnëchq{ÜÑ(ÑäPA!®yÑ;{Š÷‡;!~¬ø=µ~†f{Oºô«7tV$†Û¼X•à•Š³·¹žj…†ÃºîSbNÊ(뜖svŠ2Þ…vIÀЭ9™b4*Ó”k·3^Y¸`I-¥:²Ã‡÷-}†º›/“¢`¸øå*¼Zâò¨•¾šª%µÚ%§ò÷¡sÁA¦åEbÝGÕìõ齿±Þzß!ã#á™êáµ/ÈuÓËâN ¡{Œbl…¯2nÖíºöþ”[Õ]ài´Á?›üïÌ™£Ú1 ߀0VÙ›‘uvbƒâ¿lÞ÷l5 ã¤cœAx¼jîè÷+¿`·–)µŠãS±ºdß3´µ"¬Ûµ÷Sù×(ʯUÁ?oe\Wݲ˜ü,‹—²Œ™k…×òê»íTºK²©)Û6W´ÜŠ‚en™+2÷l—ûÄ{01¯+±ò>^í ¥‰dnzSdPº±ËÇÕiScÂÈ)³C¸|¾ç|_Ô«µ¨ívðË=ÐáêìÄ5 Wλù¾¹ïsYzpÅ^°éû(8HK{Ç|Ûk0î—#ÆŽv0Y™¶«÷»]\÷Gòä…,, Y³«Ï.|y5:yö]ÂÆ{‡¥šðê!\Lï¦ãlù)Ç^–¢½q>¦!6%yoîÖ5ïÙÛ[QߤCÌÏoÓe»$uïþgÁÖÐct¾ñ¾Î'rè·š’9)L W”Ýʎǧ€³ÝÜìÐö²¹ø_vå$ÏriºþU×Éñ:Ö ×Ù*GX’Úµ¿e[½“Sšh7ÔöèoY™€9Y8…–'ä(2üW.¶‹ x2ÕðaUçº+n3u¨òÊŠf+Þ ‰]+Z$ÖzýfVUЖÂKo¹IêéZ÷°3 éÊl9›¢ö¥cyI qúh©ÐÉÓà^q \Úu.E¦e´ŠÜòRÑbU*YC—žèdš8vÖds$êBŸ¼ëë³áèýW^õ–=ÒâðÉÛ3!TŸ©—{ð­F<ÃðØæ q‹áLlƒ‘_u® kb…PÂù‹¢ô²V‰jÃçh°gfÃ^i‡xž*Ú µÈwX™cJÛµéKfòºwZ¥ë¯ßªˆgõ(ÿbð¯W»´Q] •µÌe˜‚w—7êåb÷j´]ÔxîËâæ e1…)ÌTç/¾½$ç.N¶·*]pâ.%Vop±RsÇÎdˆé¿€Ú>›áYµÁO›]Bõ`ïn™|)`ÄFj ¾û10óîÈCa§”3qJ 6%š… ·]‘ãW¦|àšeÖeà çhÖçq}­ÖU·{¥Êsœ÷Š`®[§ª»Lá5`Ø'¾SÓ‡²À;×´W°6ߨ“fQKÃí™ãœ7)+/=ò"Ë{…E K×iÄxRÎcpå=UX€¦ÖXà­Û[@Žº°,®7œl›Åå ?S­ºÙÏvíªœï÷ééÛV²wŠl;)ЧfýŒ×Iå³t®eAãº9Ú,bšt…VúEG=[~5×íCÖesS¼öîç]úë|ÕEsž[‡ŽV:MÈÚÌÅ{‡ÀaL­™ìžKØ/¥kÍTú¥N±£$ ÇK”'*˜ 71ι£ŒImý}nå0–IJµÞJ¿¯˜çyacÑ^æ×S&I Õ®-Ùu0éWvîK›+¶ve·5ôà2öR§dñùÁf<9†¨%a ŒgœÎçs­-òö ÝåYiê˱Çm×nB4fxcÀüß»|{“¯P¿a›V±p[X5.¨W!{MIµižó¯.zÓ»ê^Nnèé;<,FÁ] îñ´ÓÇ› [›ÇÄ9›´*‚vÖ w0aç52g$ÍáÖʺ7 kÎËQ{ž^#íWKP¯#Iâ´û+'—z>ËF†{–õ=x²¦PVh‘»Ò–î´2˸¡"eìRªL©KÕŠ„jí**Y¥Ð®e%í³\×…Yõ{.»|>œ½k^çXpÊ;së[‚šHakbÑ~¬ÅR> W ^Z•#¥ì*üÄU²¶÷]¨z¹ Æ…ì¬Å·†‰T…ïˆköZ>Ã|w)=ñì Ðí"DzO "ý˜¼Ëxýï»@Z(Šœ7.ׯn±)ÞiÆ­va!šA(û+6º3G^ËìàŠS¶¦qÌO¨wPÕLÞ©}«UõËûŒûO^páß|vVŠÇÁ†Tv`y®àîÍà™B­¾–_vȬcŸÎƒI Þ=_êÖJ8Õ TéS¿õþU~ݽþ⩪^—pm¼,h û}–sEæWS·Î—ÈÙ“ú½¡Z 邤bÅ›iÊsÛ¯ÄW³EOWž¹–¯Ó– 료ԥòê¹¼üZÏXñ›<ÃW@Ÿ²Tí0Vš\Ú­{*@÷X˜´¬,p KzÖÚ4ÓU.𪩎qÀqò¦UDÄ›;s4Fsf&#UË^šQi}|ÔÊ9wXnýf<öH¤ï\ôÊïNsSöµÚí}Ú¼ y»º»®Gæí7ò[VtE-¾ÏWø¿wÑýà†~ühã§2v,õn\ëv“`F9fpðþÃ8º@+}ÛKÑ]¬¸CkíºB›ÅDÎWþм}]´æÅ©Ýƒ™}ž˜`o·PJ#bn«…ÃS|hU½îàÔ5ÈJ*ˆYúãšhèK|Ý×»™ŠË±4Vz®Öð‚lpµIž¾7©Jº=³Q"¥9Í«îÒÝdÅo¯{s-ãË =Ìâ{ãá&ªû´w´62Å%g倌û L;Fì9-.ô­óì8¦D/Ý<>˜4TxUtîTÆ=Ì2'énupZ²à¬g“Ä`…èÛÚ*Üòvíc£]Ý1|[ |yò†âtkuwGžíùø{ºº"èúRÝY=ya»`eÖ[¥ü*yíyEʈާêHwdìÀ]—¨›á½ÖŸL홽*ùö‘¤6·«)ê½:õµ¤fîˆpSuÙŠë{;`Ørº3»Ï-%[,šea½—;S'gÛAÖg¤‹±·dv•Ö­:ý¹Ï•7׊žœ æ*>Û„±‚šÑ‰‘èíUç.ëë+s:êë{®£¢´ÎYE*ÁͳaÞ† Œ¬5"Ü®ÛÎÆ-1+´Ú¾ÚÃY Vœ†ø­d®ÍmЦêüÔ nœ#¾-TÍîì«ç¼¹o=*b¼Öº»’Ëû8äqiŽ®³@IÃc&wPb½ŒÚ´æä¾ë°ûLÃmeŒTP<4áUY¢±Ã}jéÓÉÝv]æ8å5«CuQÉXz0öÑÚߣշÐuü3wN¶¾·4ˆ ºÈ! ؇+(ÕpÅ[Ùèäp^ˆ.àëŠõ÷f±öEÝ&°Š,hÛ4r‡ˆØÙ2=t͸Óqí_éçu‰¢ü÷oxìÃï_Zã@o«kÞñäÐSx÷´)™CkÙ[¬ø9æ9Uõuöx•Š2³±ûm3Ùë¯k Ó.¥šöqŒæÊ]²Yx§s®ÅJÒÞûÚV./Þâ tÝȱiÇ X¬^‰ÁË}â)ô!hf³Ã~ÑøŒ™-Їõ•lA¦žYÛm*·îÆï&cu2ùHqkævHrÞ-o;©œ&V±hLë®[ÚæäìÎ&Lú仲‰¾vƶXí£v¨×Úݽ,rˆ {šQPh÷Нè–ܦ\ÓIÐ_‹Âi¨(ˆ0vÞë®À'Ÿzüs·«Ê8¸uNÎ^¼¹•¶éüq»©•EašêX£ ªÕšÅ Úߘ’½|ë‡RTÈ&Ú¬Þ3©êÍ®¡—ÁöëSuVQVÄh7 —P!˜&…Ç/% ×-`pü%¹] l<‚«™{ÒÊ“¤©Ý2ëYT·{Õ5¬Õfpk(ÝnáûL?œçkÔÆÜ:)Ëws2¼=dU¸0SÂÕVëÞmí5Ø„ËúñTjÅ+/Z‹zfg躉ã&v÷áÂBFÔ£¹Ýð¬wÉe×G¯»©k¬¡WïHxàa¬ úìÓ˜fOK®v¤k·‚·vë–ˆvUê«Å¤]ðU"U«'w+x×·®ô€†^©÷VPDnvõºY1œeÈîSÜ7'Qnåû~yYuÒóJxsº»h9WÚv‹éPr(v›ë¤‚#3!è´hÃÜP xÛÑŒ®Š»éº°:GÓqç*ZRº#Ü⺵YCõÅJgƒCq5û(w}ûSo¬¿aàÛêêÈÕ¤ÖT×£sLµA-Çw²®]MfSÈ{fnfs§-¾ÜRìž®+™ÒìZ‹zˆ½jœu—CnŒ¥I\—ï®ÂÓY†ƒÙz¨­;íuî/¾CmSPŽkÜË—Nˆ]Òjét<¢ÙR¸×>ë8^îìº9NêÝ hõö‚÷R™®±ž MqZ !Y²VAÈÏuã§y¥i}cË!õN1Öí•qAOz͢ǼkɼÎf¶%¥`5ëÍó§¶­Š`Üܱté<$|M^ÜÒ½z¸ZæxºyÕF½+*A«hçl’ » ÔiÛÚEÀ7žÜ}m·¨Î‹„«å ëZͧÍ ¤'qÔîfú#ªí5óg±uXcZÌöîžg܃â½JÀÌ GL@ï&‹æÍn¾VyQæèÕrôv®5¢Ÿ8—cÏ?++7¢§ IÞR’`ÛY^ÊÍfQ¾7pjˆÍXçtèVñWWš’&¢º) ‚´, ‚ ေO»Ó:NSkn»e½5Ï»5†2ˆ)Y]ªC@VéŸ!˜ó·e5;ÌäÓAmÖÓŒ›ÊÄ–ÄYŒr±è½æºx!wQû@U]²0ÎÉÔ¥'œ† L<ÅN…”à™†Ýõ¯‡Ø—¸à+µÅ»Ò± £1Õíëù,«Z<·;ÛC½;ÒUôõMçã–lº¶1].½EïH%Z©ѧ‚“ç)âiÔ×Embuy0[IØ’áC¨¯ò¦I‘ñ0ÐRàn®wäÅKñü¡„ÃÇÚÒÌ3W­÷¼1zºº7(1Ôüg‹Õï(z·s›X‡<»<«`œÞ€Ù@.ì{zgP×äQ5¼ivhôNT7o7)FtYövw¡hW± ’½bôb‹Ç‹=Ò_5Vc–PY´¬M.lðÍy¢…%O¹"’ƒkGw]µ›¢ñr#e‡)+ÑÏ´0e]:=÷‹³Ôk½$Þò_Ž)Èà¡™IZiv«‹U]øú·VEçµü×Q“õj~õÍTŽÓöú®{<ËÝç,*åf÷Pµ@¿`Uƒ«ªW—¸±…ú ßJ…yS¹´ìXV*Ëõ›“Ýe9ÔÝñÀÖc » Üø}ÕŠ´T.:F*Þ½ÍxFm®êí.é¡(•”—(µÀÁ|.xé®]^¾Ya׆½ñUžZî°Å)W¯[ÅsÚÛž÷½ÚýÛ†µ¬¿83ië»ñÐ9;¬àá©“+8/&Ûº»‹Ø‰VØnÅo å—Ú´¿ºîËÎ/38FúŠ\|ô(á®ö]çN³Ÿ<9ï—€Ìöß`•’ž¬=|î†0ãÈ’ºQ¨ßgUÐJ…Ä,WÖ)w(ŬøÅ[ÂÇ®SîÙï>ÕÅ)¨öhḬ̀õoËЈ­\}ÒWgBŽ÷c 6Ÿ¨›hQ‡¢ëVú>á”±ŒsÒ󻡼À9Kͽ”`á8Xº`±]wr®:N»U…Ë»‡ÎefÜ{©ü¶1ù?O)Ú+2—«ï”Êá¾'ÖOzJÛ1Ÿ¶.ð‹m°SS-‡ [ÕªýwãåàV¾ò¼,Ól+Þu®áŽ?×ïv žlÈAée : V+1ï†ß_2ê儦Rï›r•,/÷ˆÝ¡|+ÏE·žnЭ%{°ÁΤjøeƒtiAôî2í!³†[]f¸V-Á>;g%aÏm8Âå…ÑÈuÏ{ÃWtj:ly“s‘g,ØíU)bºCÒ„ØP7½KTÛϳ=ôïÊç×?oájÃ=ú’®ãÈ Ìy«£ 1ÛÊ‚×ϲ‘ÃÖ{k1ð©*Ås²s{)Q{'OêÇôþü_ŠL0â5ëÔÜüØWûòÛÈòsë{aKœqö^9Æ–l×,«èf}áZç_ ãÞ墀œ·…ÛÅõÈñ÷JAÓÝFZßdm¯W¼ˆw:iã/t†/CŸ\$âyßkÞêO®ÖC%{i¯UΗìÚÑ¥±­eÍÖtZb¶tÔTŒÈŸÜVÌÚ\F­2öûWØ„êÚ̵ƒ|}Õ=|Žv*~k¬Ò óÔ¦| ÁTw<¡g²ôéqÁ,…BÔäüèîÏz¶qJ·yåX¥D4· ¾¿È·ÖŠê÷ŽQ¼ý†1²ÖJôå“‚¨ö1C©æûÝ…ðx,uyÒô©.eî•XûÍåû½Ã i.‚žo¯¸à¼ÃE‰²NÑáèÚò<É›L¡¼õxù®ü”ÕŒ1ñ<ûÉÖê¡ÍÊ—»pVxu•“¸õ0ªèœµˆ,¹Â°—c+‡´÷!ëpa¸÷nÖÛ=J‹å•®ìVÑÞ¶ï†of¢+l6XgÝxµ6»<5fÏ6S÷:›:eªé½u®ÚÑKB–ÛŠ–hÇ Ñ˜-z¸Ì3ç0 ¶1çJºWmêRõÙß’¤¾ÞÈ£o\ñÌźÏ:v dìåÆßg5#é;bÕ9+Ô!¨ìŒ­¦U[Û5³c4óQ­9M*æRDòPnA{²ÉYfu*Ûš8åA]«œÊT°ÖMµ™oE/m˜º÷«=Ë›EŠ/už«öžf½~·”g40Í"Iw§[GW\ì˜^ yÏ0¶„|ò†uò»ÔwrƒñLw…eK컺ñkÜkz_8«Áë¡æ6Åžk% ˜°×l¡z\‚³˜À7Ùm<á6ë(a•}'»mŠ9WOœD+[Vj.þÛ#:KÊ¥,£¡ÚC0‘¹×Þ\£”P 4¸»m4#Ðæ"=,%Ö²œšòépÝ´î |Ñ­›½Y´)W\¾”«u›Ýé6KOäksž9rîÅ’®áäÌ…ëä{9+D–Œç´o&\nÐbÁ–úű±µ%˜z–íbãÉ)}½@¥ÎmõEÓòß?Ù’¿/Û¿„ƒ÷eïí¤­k¶:éh•½@œJr©î,Üg9l´F>zF4u€E¾mn9JÞÜC8nuÇx»áHy܇dêfýª•>™÷ ¯yîÔÚìC{1_$:ßÜ–µÉ.Ù4ž]t¹–->Ð~Ohƒ’ÙW.þ'nºžÞäy¹A"â¢pì)¨+¬§EÔ]³ƒ=™Û-‡)fÎhå€VWf'B–CE>ú*³†éLÚ°¬­£5Hö½­[E_.Ø-œ™ZrÚ/P1BkH¼j¶íc¡ÈPZ·(ÞÓ•Þj€uå€zz›Û&‡•úmèñ¡åLÐÕÞ0VtÞ½<_pDÒÜ»AœóâayAô¾ zuà÷TíëVöï%'|¢†±åÌiµPVÔ Öï'à ³®ÎΨ÷~ØVÐÙccÖ#eeu3}W­Ñ"eÐÞÛ)=¬JL¥Ë²‘=†°nYËÕŽ hòÖ]s­S¥ ê]Ù] Ü8©êHXT^c¨æQªÎ7¤É2¥4 ÀWgEܧ]ua\а@Åeòœ¢A7y,äÖÙ0Jˆ®ËŽÖš=®;ÄyJ™ŒûÊé÷µ‘WCs57º‹±G©ãæ«A«ªÅ}¼äΗ“]ë¾tV ìá½µÔ,Þ :Áåæñ»·~¯VõCÞÉÙ@£ X¡é·®³Þ묇ò¯a¹ç†f¿ƒÜÐ*r±eü5;kZÔ×™J¶·ùT3ô}¢ë÷<æ]{ð_cf‘(—‰$U*ú€²P}¼­¨&“¬4ShåÑA«»Šœt« ½5næÊÀèsšÒä×<Š“Ný’öµÏVò7£Øðìòsu^}/D7o»OvÍX¥›ÓÜ@­¾cNTÆñŠ0 ¯)÷c²¼3((õv ÚÂ3Ál¨1ÚÍáD_ eÐ-içSÜB•E½mèêRÅÇWg!Z; ÃìÜ€ªvàN/‡ÁFÝBó»X±­Ëßu:Ø áçÅå ßRUìÕž9¶1<U/fÆ¥eæÁöR€±©w¶r ÕÚoÙë ¨agï#’Ó¾wÐ{3½Ç(¼,}'9k™jôê½~Бêî”ö*ê}tÖ…]8縡¶€›nog= p–v6ñk4iêÅ—RˆÂ º…×U×êÝó¡~ïaëe‹'·¦ü€²Tx÷n¤ƒÓÜ::é>X—áÚK¶Í “‘ ÆÑµ¢fb/HVsèmW )î¡ÊÄÈÞ†×cÑg.µÜ7Ý]('Úk²,9_ß²ßÚ;€°(w&ÿVØXЇ”¬™qæèÔ»8gBÛ"_YI%™Bý6Iô¼Ç+xŸoG×>vÚOK…ìg¯¡8ze°D»æ¶ÝOdwËÒ•ò¸‡¶+3¹Ó¸é=Ú¥ÌË+FuŽÞæk¦U¬|¹êá—×¢¼±Ðä*n?¼ÝWÞëû(÷ ˆÂ*/n<}c&l²YåuxøLow*r¯ñ[K‹^ηãWCð?^O¥ðÊퟄ…WƒÂ¯+¸Å–Sç¾¼='GßvGmB™¿ È(z¨(õ¾½ofû¹öq÷,@§[Ç6ìã´Í%yï }¬ÏÒ—¢.¢ì§Î±‘±ô©´2U®eD™½âðž'{•ÑóY‡ÝëÊïµÜcDS Ðî齚êE›S¥$ÖPì/ssrÛÙM&-­Å5 …,XÔaw^ÁÖ±mçbYNŽÉÁ"©ÒÞ€?z¥º¡c¬‹º{0•ò”' }h†{§³îžÆ²­®½]j%«+xfß}pdãG£CGGÏ,XÎPmØë¬Q}…™f*º¸ó¾ ¸ÄF|9r— @Ë8XHuŒ-CGMH™þWš60`àûÛHŒÑ·—á­™eîËBºÛýê#´‚öª3¸Ã=ì¤ây¸Hڹ乬hçuà$W‘“Z>&V¿ä̇R>§Û€-7Þ¡…Ñ»#›E»µ¹R¼™Ú›(c!O&³¶¹ñ³®Ïµ+%zSëVÝÂÏ5Qð$돠pœA%)áˆynÃ,G¶µ«v‹QÇ.¯‹Î Dân×ÇËÌŠÛCDËÖŸ™t4zénZ‘f.ÈÙbõâ¡£)^ò¬˜éVyCZlç6ÅÍ÷*ž Hïª'çLO³)\r‘¾ðÒ«ãv »"Ìñ©~égžï¨xzû§)Ø:m*Õo®Â—s—¯^ƒb“’äÓ83‹O'²„ܦTEm¾1·½ëò±;ÏQ4+s†¯hÕ^ÄUf'\-UÍ5éú_ßWÆþ¯j¨³Íxe¥à~òY~‰¬È³­äºØ¶Ö®íl{kÎAÂ÷8u‘½…+«Í}Ïöñ³n¸œì{µuâHh·ëD×@ê@îþàÀèr#AÍóO^P£XësNd!k/n8zQcˆ£ð\VÖÛœ.fÑé)þèÝyÎ=WïÙúüb«©lü¶Æ$Þo´ï7f÷]>+–U¹VªA^o34Õ£7OîkÈ`ïq¼ò­”UiêÚÞXÛcVKé“XÖÈê`f}®ô\©^ÚK€fû;µ»ò¬ÃØpûQWYÑw¨D.¨«³gÞóœºèÖ·”ÏÏÙ]  YœÎt «–§/å-M”IÝ–/µæ½ êÓo ¡fÅ·z`~$ì¥O9 Ò…Ö*õ‰Y‹áo(Êg½3ÛÞF‡Ãc[†Äöx˜E{1ï/l‡³¯d7s¾a{¯ÃÁ3äÅ_"7 &=à]tÂôJU ¥¦øme 7Çnƒ¨Ü†ÖÝ=°z¹T’ʆʼÀgÜ·LSéW,7RS€·:æ_.9ˆ` æa¥+Þ5‹Éû½<Q36èÇ€i1Ä õ ÜÑzE13×ÝfÔÜÔø‚ŽfE—A<—<é«[sÃy—cÙ‡D–³xâÒ¢q —–=;Îñn§c²)–rNÚ‰4 X©àу„™Ÿñ¾ß0—†ÐAyaS:Ædœèú·¦›Tmðtõn\¿€)÷Z¹‚6šÙ]gtÐsˆÚØÕvw*:‡N´…åìæžËväKJ5ˆF©uÚ€àŸsªå(ö7²j1Ôè, îà˜ù û¬°K•·Ï:±o^'U’ì¶ ìß–C vþaÞb¬¯Qoé ±™ (vßuÖx§WfÚ ì¡í•©Ìçg­`oÖêjNÍŒQìÝj¤Ë)ÕŠÁPÖ74:ÝZËd裓:¯*CuS.œÒ Þ2ßvXe×Ó1m§zŠ l˜γ)×fd©Áò_LF–cá,ÞfÞó6õ÷[“wC4·bŽ¿Ê®v2ÿJ5ûsÎÑcöžß¹mÏRôZœì®Ç±o±§`mJ\0 æÖçW.ÍÌ.7Õ*£›ëîÜïUñ‚E¯g¢ ÇÚRÀÕðζâºåg šøÞãÛ3D0×5!ícêj1”'9Qn忇l{ÃBѼá9 <·¹ìfeÍÍMÕófuË`¸ÙVkœ†ûsªýNd»I¬9™¼û Åê—™cº½B„ÃAÐù«§4…°` ¬k¦m³]¬xWK«^uŠŠŽ¶V?^6ö°Ý¿MËÉÎk«m‚¡¹HG™åwPûÔjÂæó*Õx_¼.ºÂÚ&§ÛÍ3o_IJÕa.Åuç1vÍÈ’®C´Åw¾O{Ûœo’õo*±00,….“.ƒ×2ùºÏ/WAçSÙÚóÛs Ë“äã²êïÞƒ®leHz¸ÊÅfªap[žoгì«;Ο¢Ë\¢óا¦wtÏ ¹è³s®ìgW¦õGz¼Œ¥«¤ ËÁ.¯¯^_ µê”¹®ôæg´kÃvö„U•èÜÂtÜ.VËÓ!ƒ˜™y)Q–Ï}¢K=VTËÕ9GƒFÒ’Þu35‰ Wc-k‹sWÙC¨Å³in† Ö–}‚]í»ô>¤'‡¨vñ^ÄòÇkƒ #Âà\õë]sÝ×y{Ü©r§ªª,ë–2¨7µµÚÕ%W¿â¯o+ÏÀX¯ß¼`)·j'ß­OœX2˜ôà/ÕÉVn:Mö¶¶Y¨¤2®Ðx»vlĽËd´2‚ÞòNåû»Ç:—A—S·žO…_Wt©»ÛD”º˜ÈéÉÅíòb±4³¹šÓ’öùEnløÙ»Y¤ôLÌtÖj[-.Ü™J‹»Î´ö¬5GŒ•ƒ; ¼ô`ÍÜ1Á]…L±ËíÏ)7؉ן69^ªŽþsäA’nHùæA‚AíùPñ«¶è¾ê}7mâwewO®±jÏ8P«é^¢}Gí{ÝŠßÎ †mƒFnáµÒsÒÁ—V^y‹˜8Sm‘ªwg”w‰v€WÕõ++ ÞSƺŸ¥Ü«ç¹Ú0÷—'9´Œ¼YYK*äGmë-`N%£K#ŸS„-§m9b¥89 ¯Ž>7yqÎYµ«qÅYN¢NÆÑˠЀƒÑšy(kî~õd­Túãc–)«!Ìò°;BírüuîIêÉ•ï^*—-’¨„ :áëö{©ÃCÙ7: sïda¾¯°.¯àù•¾•ëx—µfQêkèX‡s,´¨—5·ËU]IliëšæGDèÞ7Kx ik²V×v{…&7¦‰Ë³+)\*‹¦&R½°OuL× €ú뉮ÃÝXÙN>Vå½m¹žxwšó½¼Ïx£tC¶¯#+kܺíSc†äK¨7i¼jöw)|Î¤ÞšÈ…Ñ­Ò ¥`ºføWuñêÚäë†Õ–ùɽˆ­ÙmÀ¢ôj`.#í²)미WÕ_u ¯Õê]Uš ›àêxž„ÆÚ¡FCCÉs¡¥±k$›A+µpgoC¬uºÈ¹‹IR눛8¥«÷€Þm ýÎñÖœÏ!t„î¯zs¯.̼óæ»â'[4®Â›ô…ÆË¶½òÔxizítà p×dãÇåÅßV¯,ô—=×â1*´@ÉŸ4óÃÙ¬eÝ_|:QĆXÕŽYµÖ•b¼]xUºðKΣŠÌí=2dÑl¥›>5Ï+Œî"»vè$Öʲæ…},«²™¿¬ÒeõEÛLì1 kWM|‚˜(+Ê€Š;8Z%wZ²Ñ ÝKºÁuÂ!ŠŠ uwS6;_UY“¬&2k£»±ŽÃ¼\Ê)ž]Í]O’®ƒïåunÝ;»¦«­î¯q•ÝÖP¤2N*ß30.Ð+Šî­]Õ”3ÄåÐë{av¯ÁDevM¹Õ °ü À·ßLÞe¥1¨—A›íµÛB‚wpåóN·q¬ñ™¿N©õáQ…C¢ÎÕ{·o¹_¨û«V CG:¼LãÎu>àûÙ{yX‘Fã¾¸í£€žxŒ8†æ;å+ŒåfîJÁp×eu]8¼ë¼Yt¸Xœ˜ŸgH€/\›¥bͨót|b›»³H¾ÆÚ Þ£Z¤Ñ~žµ0T{‡¸¾Š‹ƒ½º6jgI±«°srwÍ$’ò×Kyèef·´)Ów9¬Á—Ð[Ýf{×N[]µ¼YaËM!ÌÝdâë°8…j¹°lCc½îè±îq‹ŒìÑ[vÏ-åM˾‰÷sΣ·Žß®¼9EÚêï+š.˜Ê WöÏ`@œÛ“œ¾6*¬S7cN½YP³»P_o"è—7jÚ˸µí÷òÿkãêŸÊ·Ps7}êÊ׿Ã%ÇSHÏ•ÕÆÆDÿœç]råzâûûeOtáãgß1×qÞ쭦轲ËÅ—ãÑ3±[Tk•9Øø\][ØâÞ9%{!¿*ÊPí¦ƒ¦©Ì9J'ŒåìÜÝÊv§6½¥–·rÚɤ§Í€uõñÝý^®ó^9Êšâ~¿'ƒoqCŒê_^þ÷>ɾ>ñy óu•zÀ¹@ÐõÉVïä  x;9{k¸·Í­¶è‘HfÞ:pVuÙƒ‘ÐJGü_øAÀ=N®Äì§td‹ì!þ­Ø (ý5 mk]3Ã3¹Xœâ%_c,õ*ö©.÷Ý´=À ¥¤¶ý]·pVo"MC£¬¡ªõT ]KW^o'¹ PÊ^=„©êw{;ròBö¢ÖÖØpPÀûe?‹µ#}µ )÷P,ä=œö] †£Ž³ÆzÕÒ⸋[\a’eÙA î6Îu#k5ͱ»YYÌ6(wP‰qŒS[¦Ÿ`+ß&¦Þê§w¹Íí."óâê(€/)N¢ÇM£—®Žöžbm×e»¶:õDÅi”N•”Öä’}r³7o,fU„‹Œ±w0T›Ò0ê4!«iœ¹_ç–燧½ÓÄw»ëK·à¨*ÊK.©`N:Æ«dÊréPƒç¬áKD«µºën”•Ha˜Y É•™¹®áÌŽÎÖ!@šCE+¼0Ž9ô8Æ©¨KåG.ž4ò· †9D3±ÝÅ¡‰¶È¼µ z#ФÃëÂ÷IÓÇc5%âšÉ¥ ©;ªcâ¥No÷Wòÿ|ÿ ™êCs±y⬋2òUo³Rs¥q¬+‚¼rµ^ZUåfêwa¶Ö1ÛmL£qÍz+X\%i£—!±g`K«a]ܾ¡N*yÉåèÉ.Ñk¢)4Tìm,i÷é›Ë…=J=wññ1·F¯)›¬(ÅÞZõtóòÙíÜxÙ¡×J}ÎÈmÓXMó²#ŸV2 娻”dÁX1™\…jåÃ;j·JË·¨ÖXÅ­íìŸz,T%áà`zi4¶Ý]ÝÆÚWŒÒÅg%°`!%’3ygh_§sx.Ùò‘øV[}1Õùȇ´Ñ®Ùx¯jòŸeÜù%QÛç1u9Jæ ³˜Xß~^õܨX–òÏG³i]6í­gf?Û‚ŸV‹®„ÔüûÆÁž~øÈÅw¯Djû8wÄ}³v ºhis Ù]Cy‘¸ÌHa•éì©ßmL†¾Ê/–ùôÔ«8+©ywªæåM¾nú¶ºíÔÖ–ù:·¼íÀH^¤´_^]jØçªæ«RÍ;89kùF+ºüü0ÚÅyY}/áëÞâÛàà¯%,âÚí¯ÇÚk©TœKÙ.è_¤=¾³¥û^6ó·EEYÉ!ÛqOUµ›V(˜kÝÙ)ë¥1KÎåyÜ6ÓÕkí!èºÝ`ÔwÎéÇOåÉö»¾›“Ç–Æüü;Ô¼›o)*IâÝ©n,$NÎë —“w ÅX¹ÇŒ—¹J_­w¾~2½Â?Õ5øå„Qþ÷T¬ æ^ÛQ]vUâsxö[ý»Ú ñ«ÎƳÕíãfTžKiæ1uï(»Ë¶ïžôâh“.Äoµ¬èz §EjlÝ+iÔH±ºü½šAˆóÁÁëÌÝ¢Nm‡2ÁÀÇj/Žud¢À^ã$Þ©Bå¯]¹•V±¸éÔë6ÍËç²[ë^ç›Y/Ý,[ãwKŽû^]á‰Ì©³«93 qøAÉŠÊíW¢û.»¬®Äyíiè2ôuwdZ§2\¥·¬­öVcKÀÕi-çWi;TjúÊ¡–ªÅ×6 ”(yUfH‹¹ŠM½;ìì2N—ämWhÔ脪ØÅ‡³ìá½®“£ž2wÙmƒÎå&]ÊŒñIžW¨9ÓU*K9¦Vv:’ÍÔŽ… ¬¥c3;²Å£]“§<  Øb`‡F¶¯ÅTä…^ìÇ¢¶õZ ›2KÍq: Ó±[F±,¯af£FÚïwŒ¥ê÷”‹Šu)Y%ût3#­ø;ulpè²ßÉÛ­«”|´!‰«.†oGØ€‹é½¤é¬èäU 39´ê¾ªê¹`N¯ÕˆÁ}ƒÄû•ú-¼žºÊ–«Ž§&u†ÏÞ[×¹ÒÚ'Q«Î/œV?w•^éåM®aÝË㛨¯+^ö1¬‹‚W²´¥¾“‚”ïTÅBv.6€krdÎgqð«&ÖGÍÞÌŠ¸Éij=¸Mœk§CPšÄzyá´¥y_é›/Éji­nò`UÛGP”™™ÛÏdŽqM¢vèÖ»4å®K‚“†åuÅ]10u ÍFFFZU»£™:÷$È(!F…ï('>Ž5M.Õg1È÷uLšÇÝ óµÉ¼¾(+D²8Dü¸tùh|7÷Ÿr­”³Ç>  šîU°7#Æž‹q,‹²øõcîô72Ög Œ_] ОÑ^ö¶¬•fqÔòÞö6ÊæÚ\©ý_Õ9òUä«}wµ˜¿/up¹«ø±‡;;•ÛŠÍUYª*Ì•DÛ@8o Vôíbäá¾X³bR„VÕó ¡•x— E¿ëjoLKÊoŽšœ¿çÑàÐm±¼"üõ+­Ëx+¢gµIåO8{2× Õäíöª‹)šn²¤X‚w6Þm{†èJ¯ À76*áÝáta×FeÍ[Ç5èÄÉ;Èž1zUbË·±övô I²àjƒÁ’Õdî®Y]´ ™9KÃY5¯ÈÌê×wÝaÖ…-ìöû1{h¦Fª7rÜbÞlMb¾È|Ôö sØW2ô¾ÈM¡ ÕssBˆ*ñdÊþ¬k«÷¤\êõù-ö=úEzÒñöB¾ï@½pïpv"º7(ÁÚ”^mn«¬LÛ=´w1H|¯«&2ùh£õŠÊÁG–UîîU»©6gÍZ4øŒØ)Û6Š@CÏ`®º·Æu^n»K)½«ëIá•kµ˜õ¨¸37êº-J5¨u®Çn<»Ø=ÏËyÃ{q{etøå¢êøáTö\jÍàŽ6dÞr4¾`Ì.h¡»..i,YJ¸¹DQKµ[ÕŒÞ4;onãžÃWWé·žÕÚFøˆZ]rJ 2{¾42µ®MÓÁj>¬7ħò!»]šÑê ’«í»´+ÌÔÅåí`ë5…ök Š—%ê…-X¡cQËT°¸àyå•€¸ýÈûÐ|õól$sL޼µ\fÎë°ÃÖ/Ötº¤]¬ÚÏ%Äͱ-+Úxk7:K§*+O-Ò“Ég¯½è;-¿5âtäÆ /ÞîÕg°I—8ÆEÆ¿— åi]}£NA\«‡{[é¥hõb}×qz½¯2ÚcÁÂv¬ír=©Ð¯gf*¿°_ Žž“€ì]jýïYX½ÙZÖ¿;K aÆòËÓ™Â[r³u2€ÛÌØ6³kÜiúû)n9½²>{=œ«Þ‡k±òÈŸ5]t«ŒÓÔQ ðÁyØgW®¹ùì­Ó…tÊ:/{C£žÓ”±[ή»®q«M­Š¯‘ £zFÉz6Å;·K@yJtðÚ§kÀ^`K«ÅO® Ìvú^¢=évö`aÈGqhâ[‰d‹é‰gV­hÙXsub®Xú^Η”_[K $îiåÛŠ··%šo+ois“ñ¿ít©ùñ^È=^¹¤¥&ý³N¬¾ã/.,ÉV©XžR{Cw2mäñÇzÄùÝÃéZ(ûåY:žÔ9ò$º <‡;…”Ì)ær#îïÕÞ ¼ÍåŽõ‚Ï®[Æ—§/:ñÁîõ\—K×0­©UíYƒI¯~6©»Ê¸b.±r‹k–lq!‘kïDºíß?yæVH¼³Ì;Ôy]ÞÝß‚x"ÌcA+¹é+a¦";dLç·ž-zý+ÔÃCTÞ­øùOm–W{9výjñq¥\YŒNÕtxËW+wÆ¥Ôºƒ”Ñ]XúVÚ ë3JÝFksÕÍyœ_)£²øƒT7QZÃÈ;ÝŽ*[›Sy­³Èµd{‡8³TéëÏ` ÒSƒ­Èñ³¨MY®æ8Ø ROI«¬wM.'QAté+ɬt7 µ—W°t.\ÄÍñH®$hŽëiÊäöíò勺feäÓ !×A\ Óæ…2š¬Sefû×Çôw@Ê®Ïë‘x꾩߷½¡x*·kÕYÓx½¯¥Ðº|2€W0v¥ƒt$’c“,¾¢°+~1B¹kß#WÃÉÓ[}[ó­½|òºöà­Zw%¿#ÕÜþ^øÚŇ{Ó̩Ǩ´zÊ¿zX{³TêQÑ)‹’)]Ø—dñ“Ï··½›à:€›9vÞSQÀ)NèSб‘e²v`GZO 0äÓ'X:Ý ^Y3º“›çOÞÌ;Ž™;Ê´uxv³´vg;‚­ú°PÙMð|‚Çîjü¬RÎçïtFDÇ…¥ëÝO–6io\:Pb׬jÙŒ »ÇÅÝ]Ù¹yo!´ÖòPUfÀFÏ^m=µÇæo‰ ç_عTͧ٫• }·G±ÚèLPì±ò¼}²‡mtçS;žjzïENy.À*ØvUÒ³ËCì »*ÏW'eå}S~ê:þ¿pè|ÚíH[ZQaOݹ𵼑Ð_~ÚžRþƒ¹1yÞŽrÕà”ŸÆo-á|•sîBÀ]å æ v–Rí|é+ËK«0“b‡]S¾j¹ÜrEÐßÛd ]šö¥Ô§®óÛ¢;Á |UûÃ+O½tu;J-e;HVçJŵÄm˜‚puÞ×aëcÝ*¼n±ã*`-ÝfSç\ ¾o•ï3'ÜÊÚz麅ð½–Å_U¢>èw1‹n'½Í{±ÜðuÃå®–~±ß52ô:Ö?:™Žk1#–ô•wn8_VNÇQÚ/–ƒ–𻼠uA‡0r*ÜŽèFEËõšnñ5³Ñ]fLôö—¼êâu›“³¶EOW7¯¢ÇÍõN1e8éÇ»Ê'jšbøÒÓNÔ«ØßYeO·kVY‘¥×têö÷Rà‡Î‡Z´Ýß´máÒ¡©D†¼y ŽëSù ¯‡ sÜ¥Òý ŒžÝå~1‚â×ÒûeÉß<Û¬È׺¥+©6®Gµ¢|‰Uv7wj0I£3‚®º—ù¼qQêݾÊz|Ðuwuh¿¦‹Ï á[îÃë’©ùÃ3É +=eÁXü\Ž÷`Ê”U{­i"¶nÝ`Ý|—3+pPlQ°mò*•Ò ã}ëÕ0øàH_?5X¹ã n§[<+—÷½o‡oÓÖIåŒWD´[±ñ>ö¨-^]¡sÙ[´5?FS¡‹Ø›·—ÍAv A0U…+½µämæúˆë+¬N†µhîwen&å·½]Z×X›j­V‘‹l-—nïœN[ä¼î‚þ°{¼u`ý“?m“§äåù=ãŸAtëw‘ÊYª®*%Ö:67p…“Y´i¸ËÀí;C¸ÁœñŒwÅS‚Þ㢂˜óoZŽÎ»VÙg âuÖÃ#kÅ;:÷mÉØn€¶8ñ8·®ŒÅò-PîXW1$ذ Ѧ¤&¦šàµ[œEo‰WÏqçl­©•°8ÅušVJK/†,×3Øû9±¼ÍžOYj@ñÚˆ*×JäWHJÓ¶€Ëòo±îÊÍ{/¯-Íùúlpœò=kŪö™)Q{c…¹Ù™Ê»XÒ8‡ÉèÇ´$Xˆ˜rœÖ«€ËÕX1ö5®Åk¹Œ¾÷Y.áÙdv¡}òÁw(0_Ä.”öX¥N…ïÑ9ª'²o¥ý:Èç¸S[¼9ÝÆ‡qWsh}@#qœÅEZsÎ}ŽÁ¾ÀòóE; ÞROÈàb?v~©puy›‚xÂíô›}ƒ[ýËŒ©¿`yú‚Ë{]9³™!÷wb Ýeu¼)Cwº±§·fX™Žþæ6ŠøMåxêk+7qÐi-óg=lÁ]Y×zèÂî j·}à‡…®ôÞAâ –1e@Ï;o|ü ö?^Ëö“¶1¾´î¥&´=Þ|iF7BÆuÒ¥ÒÓKl'3¢zÚ®ºÔfïòÞöL« Û ò[k—†ï[¬Œl±>q~¶úvòzçoi/”ÅÀmâÛ=ËÌV"¾¬QÒ»® ßB ½Ý•ÙǨ!¶7»9x7÷‘™Ç#¨.EîK^ßoujG@àC,l«…Ð<0éS§JÈu˜¦aËØL`—,ve%±¾Ñ«J¡­îNÞ.`†!@à c8„žãtGˆœ•¾ õnÅWåLÕ¬á¨gwVrbûŸKÝø•(Ìi[¼’Ó‡±¶{‡Ê'ß Ò¹PÏEƒ¥ùyWGj½¼ïBh^pÇV¦í^•ç 2+;lÙQÝGå­ÌXh¶M.Ö¨ÓÎ˱]>=Ó¯>ø!² »N¤£áê ½_Y¼©¯Ä^Û&ºJÅ”ñ§‹š¬¥9l«åE˜o%Êt/‡mÚhq­î¢e&ŒÞàñ_ß”½­^Òã`PÜßÕ¯w—HîõW°Ïd®te{}Ø8뜲í1në+"jG|I(¯Ü‹¿Mù‡X=ì5›²nZÂyᢳÁ­žn" Kd4¶.&µ]ˆý[6,˜U s®˜§x—fë™Y¼ R»Ž“‡5Ym×…ªÛ÷W®Êìo&1MÊX1ñ+§³ÀãpnkY :æ`Åp65ì³ÛÄó…®er/š.Že*ã¿v/OÀÊ}pø.ãCxîÇB.MÕÆ¯€x²u*€‰ðë{:)›p§ÞGÞíÕ'/Â’‚õõÒL8EBpú-º±¦ö6ô7§°E’ W× ·jB˜ë]i²ú-‚¤õμUg¬ í%¼íÁ,šò@AïzfûÆÑ*çÎ_VgWŽä|›~â‚Ý;?BwÒš±•^ö/(y…vãð-Ö¹WKc™u~ÉÊáíÇb³¹7V+~c¶2ší2Ͻ¯ð`ê•}îpuNy£˜¦ö_é½2Êz…Äyö†k]hé›Ro7¸†opÐôP¦-S¿T¼ []!Õäç9‚­®.S­S{^°E³Ó>×]¼<­×0 ëžZÐ&RD´½Y*×55ªŽ@6Í^7%PYg yÚµxSã¼tÕ·z„R`#N€à>ÌQXöÜšL_[qVÇKvùÙ¸^î3¶¯MŽàâS­—œ?á~77zÙãÆ°h=ÕÔ‹"ö²Ú‘› ]Ü´gu® ÛCt„è^)'2‡?Ý–Fß¶€¦üE×*2¦#êç–[y;´,'tÔNÚ½levÒ¶/¯.q”¸È´l²åGy©ÖX½G_׌Dò?’·<µ?eãw̳Ÿ_>–ÝøZý}ÕÉsÏr¯9uúdYå†=ÙùžÒHeïÁò…Ç!ß ß-u€ìÕj×[õ^S;;­1×ÒÚÛ§ÁjܶÝßoq“˜³Õ•ï`£t¤Þvr½ûZ™ÞìN‹U¥_¨€v•*©]_åx¬ÝÅêX`ÆŸS]å½Õ´—ëôlͨ÷$®çVe#ÖÕ—lÄÈ9c†Øòž—Ý4øK#µ½Ëd^é^eư²öÐEUâ¼» ôÐF]2sqSÝØÙXWLµ3%ý±YSwÖ´ö®œ;\íAÞZ¾[/·\©öÔ± í“1È1 ]·Aôè‡-Ëz«]•쉟'}ݺ㯪ðf£ÄŸ |êèÜ5z<:±º3$F<ó»xûÞ' ØÔÝÇ¡ïÞ]Ñ×­×x¬¹ëõÞ„ÇŠí‹ÕBÜû¯«Ù£…³4Þ:ÐÜ—;z‰4KJ•:²YÏ?#:ˆÏ ÊŸd:L_´R~¹|cî!®ÉoÎ=xRÑÕ2©4vâˆÖ¨öPe ØÎçZZê9‹{¨,XÞõØUhårWN „fv¹ƒv÷.H†d‹¦ ’˜õá×ÕÒÿT?¢»YCÙúéÅß¼W}„ø+¸}Š{<:PµÑdq#œ°ïŸ$z]õ†jòù«´ºZƒ†‡¸kËyÃ}w  w&:¼®u<;´A9é/zd·Ü:•>Ø3¸üÖ™šÕ¶¹$–eð Û.•_!,äÞ,ÖƒR.Âëu«屸g^Œ Ì"éÁL‡|%\ÐÞn|üEmNn´ûyVº¿r…0¶&”~ÙvâÝ­«Î™JK³´4¬§¹C•¶¬ î»îM§y@ìgºƒ¼*඼؈׆‹‘uèëò®¸WŸwIÆÁŒQÇ‹T˜gtU¶kâe–1Ž’–WgoI[`å•‚XRO‡niÁÞyáQ*½9p/ åº)ö»\]”)mZ)vÞr«ž]îS¿_…番Eèm ¸Ú <ž½8e‰ÄîœÈf5£·@Æë×d Ýv¾ uuìZ¦ Ҝ뼋H$0´â v0pÌ¿3ϳ¤š0±îÜ®æ»/ÖÙGDÄh@GJÖg×و߷ ÷ÞÌä÷To¡»=âí£îµejÏ-‚_ÙêJí¬õŽMž«Ë}ßo ;3[7éÙ~`=ÑU†‚òÕtñLö5}Öa[Ómf2J4BåTéÎÎÊ1ÞÓW#ÞÊ% ÚÔ\ Æ/«J²ìÔUy´1ñ§Ý©¸ïsX•´òPêc¦ÝÌ·…t[ÞlöªBƒåí2„Ež3ÏwV «Ù›!/7H¡¨-gBŒÖì󷚈ì*¼ÜU¤õê­6©ÂõÅHÏr€\ð¿_bÚk…ò¯_\l’ŒÔ©ƒ|ç'Àí:½Úº,Ý0ØÞwØL£pe @’#ó÷œ2³Àn¦Þ¿.ÉN±ö¬îwJÚ[´½o<‘º=ãoÐŒï)%jÚèeâÖ;ƒªTŒ<µ?&,Tòé›0¨ÄÎÝÈüÄÚ̳>ÄêË£ƒ7›Ã¶oZ¥O›¸¤˜ç^€àÞ°…>‹ºƒj §¶Ã®nù£¶¬dòaî(eúëßy›]ç@‡Å__•+ÚìÝÅÆ;}ذJãw–ßoXÒZO4_g=•†u-»ÙÛwšÃBS®XR»—0åÄî1Úií%w½Õ,Yø94QÓ•Ì *äÚ]ÂÔÌŒõVCyö%5ß%J›DjáT~r¶w{èÀºº}FEIœ4âOp>I•d*°®õ6ˆkèËfɳæѹԼ•ëj锺¯Çæ=¹~åÇä+\SA¤ íya^<®PF˜ÆMµØÓÅvÿ£Õs“ñ˜Áó¿% ¨i±ôÖã¹í¯5´ZÝR5Ow¼ÆÕÓ7ï_„ZÍX ¿-Ç&QZñË”Àõ›Â[ý“{LãËÓ¨²´¶xûT¶»{‹ìŒ+[;@¡€+Q³ŠëÖN@sÒU¼í}ê$+¶¯VÖD)Î#(5g0P]Ë'—Ý9[ë£X-o#@ŽkR¬÷}·k™W+2˜ÉÍQB{·kž×[5Ý+%a-%àµï}´µQ.sLÌç:ù•D‹±ì9šo°SÉîÞ}sžñßG§lgÃ{Á¾ƒSÚÚÃWîêo¾ §jÌ_p¡‚™»ÖSíàõ+é7¦6ž;¬ì<®™‡Zà%œ[±Ú³º‚ÏOt:N.i"Œxs$~µ}Ë :AáÃ*îµn«YI[¡Wéw7m‡uµ²3•Ï‚j¦l@5–»CKeбÝuݵÔÛšlówW¸×4²…:é{ðË|ß:u¼Vny¨÷í±š›ë(V‹ÓzÕw²Ö{}ç~q*åÒ™à<îlξBb¼}‹:ýÅ{ÞLÖý³œ¡‰ü7 ë·B³5Z±xÙ^¦ñÚx”ôC/­Þ[Ú¾j¡npž¡æcaCšÎ€”¡ç™g •¡Jê}K¥vÖ³›ƒYçÇ_=d÷Ú ZMYNæl¦–°Ðuƒ>†T(M«©Ãe¾ý½\?ÐûF_¿û]ÃáS{Ϧ-`ï;UvR£\´é¥.¥ž>.¦we]ŠÏî¯=ôî¿wÈ(sTó{S’è’æ cOK»¹"ÛZK í5iU+5++ëÆó'4Xc¹O:O×{k«éïë»ÛþyüðŸ‡ñ;OrΜt–‘Ç´73´wB”ÀâËJ×S%|ço^·ë-j¬km_Vy мäŽT¬‡aÌU»¢|xܸa'©œË'´+_¼G!7 l¾–¸í É.¯%y]J†ú…b¬•Ù¾*äYÕ«àâOâ£ããï9õeõL¤ºžfQO3»vœ‘§+ B;ÅŒõ'/w= ù*ðß?¼´{.PL øƒÅdžæƒqÛãÅØ»º°|)L¦«yÔ¾÷%~ʽwì3Û«À…ïIàæ;K9 /ánç°ß¾U6cÎuÙAå 7¶Q‡=žWïw¸g¤´Åí¦©g–Ý ]½ôkÌÈ1ÐX¾ËžÄÕ«•o ŽewVAÅñé]* .TÒ1U»> öxÍòë>ê¤.võêîýN½-ée ¼ëG^Üø\ÆûºßW!×ÝQÔØA×»W·§i3I!™›;=âÝeÑ\ n-»i¾´&½u–ïE ©°$pÇ™™ž)l‚û¾ÚÇPÑÚ!_Ð急M4÷ €Æ"©Kyd£—£˜“»LÊrÌ,˲.3:ØŠ§KŸ,V49vbCiæÅ¤Í±Y½{L!XÖÔ4ßMÇenöŠæ9j:kHÕ«¥ ¿yºðÁÑ¥v…íûµ*KçØœÝèÁÝ:uJ¤/§L®^Cדçnî²VƒÃ¦iÑciÜágs¡8áJúÐÿbZ§ñ¯¿µþª’ï.få`òÍ»”7÷·ef‹©#qYRjáÐlbû¹\­,÷WäF:+-£Ú­Ø®Ž±v‹]´ûYþ³©›—"ºi´€ã7éš:\wGqö-¹R^ãÊ›\¥âk>…(d6<ÕÖZô±ëïJ¶Z^ì5۠ʀ¾QÉ&WI1é½ÀÚò«ê ·Ô}íÏ#“‘Q]7k¥ÇyÒ„ääÍÞW"4€Q™*è ·)„™äAîW·³ˆ®Þ±¬“—ògUÊä‰ÂædYCèöU½4Ýᘆn\Uµ­øëáÎýÆóÍIVÎ^¦slŸ ”Þô¸øXmÞiTì0SÊ›‡*{¶A’÷=º|¿SÖ^/_ŸŸ¤³½|®ýÞû±g©¶SÎ#´zû–à"Ю,vBb«µ7u¸ú­NIk‰œóF6¶—2ª÷m ½ÛF 3#ˆ]>z÷ewcÒÕö¡D%Da‚ŸkîºÕ™Ê&xQ±D{rú7<ÑÛG1Ÿ}ֽԡЬM1%÷1–­b³E1ÛKì´ÆN+±Êx®¢ì•¨Æ>tiu Wxû¢|¢Ðs¬Ä…IxøtBabŽsÙ ˜ðËM˜…\žw{É×X™1{ã=¬¬û¹%3†“-%Q«ëà銻®á8-•¤ƒ×”rP=Ü·¼=Ò]?^°}Oåï{ºwm:µ•vÒóÑá®j³ «xÓ½Í ½Ôø%Ù¬ìN]±·(ò©Ð¨ ¢¯{ ©%_±ú£—f_™Ã«Ë×7x_I™"ç!7G;“×ëJ™±[P°}OÕn±\&É7 W=ɧ\šu¼«ÿW2åùVzcgÉ‹6€–/©œT]w}6ã éc^A²<î²QÎ}“;q»‹4ïJØS°ºÊdÔqÉB ýÙ~0#×ÛuaŠÞ¦Å,£âL«§hz ‰=BÏuíu)vÜÞÝ-VÐ=®8ùEѼKº±Š{<úا-3^Á›‹Ù¬xx¸je¡F”Ç©ªØóJVÑ^ìÍ\–W]ì×Þ+Õ£×9.W€ˆ…ÞÚW^˜)!³åk‚Þ¡AØ–ÕáEŽÅK†×3ÖÍr1Ùšõ Ï7?«Ûé–Þ±&—å7^*ÉNÞm4ü–Á¶UyJÓè÷y~ÎÃÎÔðíî )ûa æûݤóu>±ÕÄØTD®×q ¶vÎ*ؾ)A˜•]j÷º°i˜rsßnN^æêöðà‚ºÛPÇÄ*v#>î7ÖØóä..Dw\ËÕŠý÷»9HðWWYòðÂZÁÉ—cK Er­˜É”µÐÝÆ›Û[Pá=4ëîrñ.¦ŒÂ&eaÒÝeJ4óŸKd©jM¬Rœ)næg02ßP¨R²®“:ÉìÓKî讥:ìFTÒQ½·çÙvºµÝÜÏ¢²À7ïo”ÉØ€š ©³$©Ü]ØHn7Öo8wZæÝKŠé':#"ƒÀuàŒãáKÜZ/Þý‹`ÉPÓJ¶÷¤5|¤ûq2MD5ðÌÛê´;•j‹z »t€`δo:›NìñÊîαóÝ®í Ýí5:Wb,Ÿ–ja­±kí÷fÊ×<ï©™Iù@[Ñ<´å«© c,Xbæ‰S…Â2¤œØ7z»®óÕ«*8¥×!ëKh[îA}`õà冱$€£.—Ún£á¦“ÓÚ+Ãt”¹xƒ—eä¿\ߥ6X½H`‰Æ;lRÛ·O`‘åÁ\ëšÃÑñgo»%c/«·trå—¡ª|ÙÐÚ½C­–û5=}ì‚k´Õ)Ó±ñ=K{;¶î`é1~‡ØýãëµÎN“LÙ&È#7”É0!N‰‡r°dl½·˜gVõiYB'îÍ!÷µ—8};Áv7Ý«4ÎÆå³quIÔ SÐg%dÚ¢»6çj¥¼û=šõÝVÚ´LŒz¢_k «ÈŽX€Ù™&>W§\Oí©QC]Û‰°Æ­å¡ð7ܺ^®ú·œîØ€í)*ŒËœN®­­³Ma_(ÓùIC2UÖó®²9X6‰ tʶ¥ì§É«=Ýë^=‘GB1ã”r÷føÚ"¸ÞÆ üéšK"tyÝ ¾ê›R™¥x.ŽÁîoÓÙ óöçV»NVãÆÓ»ôÜL¼GŒ¯>ÎLzqú›Y~óÇZQ¸²ý0Êw²§OL{ÝÒëÕŠÓHû5u3’R½ìGdUyzéñä¤å×OKFk½Ú½jºW.döóå{`ñ ´Ý²DcÏ{Ô×{ÀéU€‰Ô_¯¾ÉŠ_C¼æÈ»z…DÑ2SÛ¦Wðü2ºÅþZ×aü³#ÛýÎõ*Š»hŃ7¨ò`sYÕ2û]ÈužçIlë&n„ÝAzót¨ÉF<™„®ÞBÆ0ŽS§ckyb†¨ QÍESÒB¡/¯!í’À¯@†ŽÂ}Þs6t¥¾Í4yÝÌJPgiú$"Sh—Ð7÷/W°vÁv¡ȧÏ5m«¯‹ ÏnÚi¹ì·¾Ò%º­ûõMOGÞqg°Û³(Þ5J›eÉÎÓgŸw©>ž¿PðÂ7^§²~•žØûÊèNCrWŸ®˜²=^·N4 vú³Ua¸™YåbW‚P\à)R½áR·Ó ÈEŠÏ·#ŽÀk‰¢·MËvdݤӴr!lØzHæ„ë£khž¿¦Âc€Õó­^Tïj3æcð™—C«Ìƒ¾½«¾gr/Á’.íø§"Ç2ÂZ,nïfÝ;ò×? ¯»Ã{¡N•ÑÅ+|–ÕpG@¸=ÒvNÑ« nÓSC¥q_ŒÍVæž,K¬î*»*Ç#fºí[-…Qsîbîrîï±õYça-º¿<­‚Þ[©ÓÚZÓô$O¥i<û<ño fÎß™§Eã*»ªßh¢Zì›°¾0¬wA±k’¶V¾§¡Ïsͱy»k@®çDˆß)«ƒÃÓ™,ÖA]Z»i, ¯«„¹}É 23·Þ­ðóœ/2ü³aËñì*oUæ)R[æÁ^cï%7`ìåù(} à:’š4ÌDWÉ/´E½H‹k*Ý.]±Î«ZôÒHœä¼ÖÊkÁò¢fiþ,„ª}¨~»r~YÛ¹„ÙÏÆÔƒ8F¾aãÂ<Çz·sŽi zÅÖ_Ž{„÷hý^åÙL»|÷ªþ@ˆ4§˜³q~#Ð7ࢾÉvüâù>-Y6>åmårˆ]”ƒê€ºÊá–Íq+vºµ'ª,7:Ÿ®„áb¤Ø·)Õ÷jc­§å)m¹›ëQê­ÃÉêÀ_–#]ÔîÞÍãÔ®•šånŽLÛnCqcП¦³Þ"–ßhíxì´M¡ª*T:±Wþ›þ;ÿ_õG•ýïî3ÈÄÛ»þ»ÌÀ©Ú¢LܺQÿqtÓ‡§\so4—0C}(__#2 dÞ.œw›Þˆ_Üy®°6t·™ZÅ8@¹;쌗Õsz×]E¬ö1ò8û-Y§¶Ö͇+zM¾®X)AM½ÜKí÷)!GÇ:ð[3k³«k†sRÊœŽï^»ÎKãUyÄ6zÏØ¨M<2ìjê8‹a¬Ö5«¥ K&;V<Ü©$j%IÁqïÛsË*ñ(£‹æ”"P áÄ !I‘£&ÜÈ¡…Ì-•ìÓ(À†…ž¡“¨Ë^Yaªî³;AÍüЭ—DIÔ¥÷ O:Ô”íÉf…q8yŽ…`ZOÍɈG¢ÜœK ô䳤Ïv-VÿÇO·\²õk"Vê)Û]¾ß^u#gÉoyçhÉŒY–à«NÕ¶RÝÄà z‘{†¼ú_·§ló4|Aâ1Ü—·£Ýœéú7Ρ="¦§Ù»µÒg„Ný×'´Mjø×U¸Â¤¯²>ŲôV… Ç ¡õuí{+ÃZá^®#µ;ÄuØÞUê2ŒÀ¬½`NŠAÍrytŒG7Þî¡{vSØ Þ*Ž/Tjsfp×Ëž›ê2Ð`œYnïì¿8·¯Öìÿ…‡¥?DZRí'H{ð•‰/l˳º¹c2–ÀBÔâ›iîg 9èÜiæµØ7ͬ¾¡ß\ÇéTÑZoÆõÞ¼-[Þb»-oUúÓvùÎ}ÃÛ.[½e2F²5Û„ëöze^ã2N¾ö iá1.N=¸FzÅÙ™êËF])6ƒ¸Ó/+%Aë‘W^íû•CS«µ[–¡ê+©*Ú#ÄpÐÝE%¨v›Ðî´‘s†¯¤í¨Ý=ÒïvÚN­g,ÞºŸij³ÏÞBõ º½~d¤IÏz³S`‰µËʘo2û^ü^÷¸sÉIfµiËHè-=,1®Û«AÅæ}æ[Uíöã ¢\¥G²è=¹ÍÄ£uãÜ7Ó6¥G.ØUžMØÉ}¹VR’—N*r­—C³3²‡Á”•Ñ;9,»í8äÁ¨Jvtéš”Ë9îg½œ Þ}¶'€ÜtCÍu§¡Éu‹©E€’mfÖeÖ‹±‰:t>+•6êœùÇB½k|¶’t8ò Ìó¤÷(ZúÁ§.a»p ´FNb¹µ'>*²Ù=Ü+»­W &èt´T r.}½W¹.pÍ\x00\íâUz<2êñ‘vcœ›ÅVPJÅß+5q½2‡B Êy̨—Y£}¦áîíVº³.‹¬êZH‡E Ã×GÞ§H@‡ln½ä©i¯Âu¼7ÍÔ8¥4 †)»ÈÅ£fyÙœqš«Ø\ÞêvHox´`ÎÆÚ*øÞwW9C²‡hÜ+{PÒHõ£uy]åYDfyÙjˆ{$—»ÂŸŒ¬­Y=ÊǼîœóa0‡½^G¹•,ëV•é±-Ö^«©@uö¾(^}×Á x1’ŠÎ»ÀÔ6£kCíî­Á¾ ÄÜe_mp6G©Õôëø«ì9$2Ò;Q´L0ŠHO§d«|m¼ç\†·MÎβvñîŸHu“×aíÞ÷GÀ†º(t`×/Ë›ÅoáP{fË{Ø' 쨂¼¸.µæwnþ·î7}“½­^êçìðË)œÞéJ¼aêžK¬ÑôƒO’ïҼラåÝzØÖÈäy½«ZšË€¿AHËß1lЮ2ŸmÅ*±)¸™ŸÊ®¨Ê܃`Ùµoz—â+:ó_"=‡>öŒ½êZU^*KçÚ—WaW¢sÔÅú{×UŽ– a…á娑@ïÏrêëh7DyyêóôqYUƒ»¯4™(^Ly«fÝ·âEM¼®6"úõ®1hÝŠŠ³REÆífFÄOpÕÜ×›Ça¥Ï¥.ák,¤Î¾¾ºšª5‹®sÞ¿—A#Õb­wS@ÍØ¶æýî!æðåžêG•$³<` ÎsjY‚¢µœ1¬Ú"³¨Z™]Ðü‘“¯—,)>JÑ—KÙÍø:¶l—ÁmœÅ”´­«FšÛfünÜ+ZÏ.bîù)£µepfÛ•*•Ý=T&TæE‡a±"ÄcÈ3{%ôÊä…w Ã…àÀ÷OS“+¹‡E6òkyÓ€è7dNÎémåËâPÑ› ©pÞ¾b 77dçÜ0zðDºã÷ö©aºò³ç•Þ{»á„…¸ˆ¹_­ÉyfTý見gQ|N2*0ovh‡¿jµF»Âômã¡÷›¬bC(X“':4XT´˜wlVK~úÏ „!­_ÓFö9ޝ«6Ê>g´!@cÍÉ(7’f¹á8–êW5 [np+n§§töÍŒoåێøuBN´ÊÇ ¼»jóZX;6*OJ ªÅã°GÒCr÷í×Ü‚‚²³™2pEܶyЦߟL~P²É fëXIžý¸‹ìåÇy„ ér™Â¢z޹÷¥oeÝiY¦îã×±í{ŠÇ–A;´M¸ýa|’%“·›( ´0yf’²QœTå<à†ù3à:LÙ¶œ¨]×™½¹‹Òê\˜¿¤§X2—J”4iãÓ”_P´,k´µÍ¹S¦—pvÊudEms¸ÆæëÅÎG§pÕÓ¶ „Üܶ/¥W¶Aëš™ï1áo‡\Š/¥óËÍK•¹zÍuLù¼8;…äÈSÔûn]˜ÊޝZùÓ¬äñ_[ï^ìΛËÞžt{ÎW{–VSÛ)(qŒ5´ŽxšÚ~Ÿuf ž6ìëøÚ@ô¬õDGÉ߆Næ‹îWðZÃÍ[´u ’ò­0Ë`öP —+m¢¹ËðÞ‚ç®W?uƒ+S™Y6Šc»ñö­÷¢Ø 6•–vô÷ˆÙ]”4ç{4ùÑϧÐèg,§ƒÕ1>MîÁ(wf[”²¹Ùx+ Yg›­«å¼ë@*då ¸#‚èõ×v:UÒùGE^^ídfÖÕås•Ã)v½˜Æ>·Iðë16Ÿ=šÚsIcmÝëÉ]Re_Vp•Ûƒ7TÈg¨÷”Òu¹8£^󥹿`½à›>îO¼ð¸VíúãÚu¼ŠI~ßzx·~¼Óàj†—»Í%¡Œ÷Lô:@¦è<Ù×ÛõÞe>׉è™öŠpNù“Nžò®éz°#K¢HdÆïô^Ì`xçë¿J)ÓXk÷ìYôn¤`>4oëÑ›>v±t8Hxæ¡oÇ¢*ÄLÌ®äP'‚5¬ººLÞíëÎV®¸ÙT"~^{RJö`í§[šÞ°MjÙ­>熞N¹Ò‰£/šç¦n^µ¸…uãêTkœJ|14®a£Y²â&²pWÊÇkºoèsÞ‚»÷«Y­çaxE_³×\* µ*ñ£Kr¬øé.ûÞÆ}½Äe4¸dT›¥7_š5^  6áæ Pé.Xš’¬˜ñ>ŽiVæ?¢¼®7½â§Œßo™^ýWW㢽ðýKÞ™%9ú³÷'5ÇÞͧ©å÷]:Þä÷5£œaH<9/˜º„öëÛJ*ìÎ)—(ô²ÝŸz»}3¼6ö*eùÍ8Ù¢à—$Á`Þ¸?oòÏΚÌPd÷Â)ûÔOjÃßߊíBí±=bú ^ðÖ/p¬ß&4>1/Kë3.ɷ޹1àU³Ìd!ca®9aÎ<ªÄU]»M»Æ].Y5mš ŵ·ze¾c>å.¼ò›×[”ÃÌ­Õ3ãžî¯mÃÍðCB}bÎÌ¿F¾|ÇAÑœÂÆåq© ˆ8¯{i‹zöŠëž4s½^ݨ†>—^oi’¹ó êËcËËÞ${vv°±û‰ÌÖgX+ Xï»jê¾ÙLâåG»§Fdƒ›=x.^Úˆe¹uÇb—Ÿ)Swq;îèðõwSÓHyIG}¸¼Ë.]3ÎÁΠ”SOwP–uwCÙ×ú;87®¿Õ<éýLSÝïÁOך]eå´é.÷}ÏJt«¬xgnG™.·k±Da-€æ§Ò,ou5ÎQÊK31öU¹©QxQÎ"ë²òÁ]“vGMç’Æ{Ûׯ>¯%, ¼W!ÉXjîB>Û,w-ܰU‚ µfV‡*æ+½êuÅôͧ*ú÷ ò…Aw~åïcÁ­w¥à«{¥YK¶š@z´ ³»Ð¸…ö[ž¸RZ¡¹Ví 4<ú<¥™®ÅÚ<,Ò" N³Mù+‰‘VÖÝÆIs8|ÛQª½xfœkwÊ^c¨~¯c±ìè{£¹Ÿy›OvCOg:Ò4×vj¢ã‚°,¨kXÜÛWpO»y^.¨)®ã†fCÓ£—’ƒšè¤?_/(ýˆë¨-Îov[w¬$õ¾ÝJ»×±‚òÏÌf‚愪Ʊž°ï/ÁŠíCÜêN¼O«æŸe‰Æ›XÞ„•_»±‘×(³ì‹Õ Šƒ~Ñ·žœ´`¤§P©•g)j 25íømâWH$krYoO=wÊRãißzMra}åÜe œ°-g|µfœáDN 8m®Ç·5q…ZÉ «¥v7³mEÆpŽf ëÚ"¢¾í_B¶÷Z›2¯È¢û×Ýî”ĸ`†®Ó­Ø_êFœˆ«ÒžhdÏz¸èîáÚs²lä^üKPì¥Ü6¹õçDFfK8Þ™ZNa³\¹É¬V€UÓF¬Þï~uκ‡Ÿ†‹à5ø„ عÝÁ…ö± 黽§®6Ì´ ,\ö×›ƒè£Úïi]g·×C•ú—¹Àúzøõ…lûÍ»^„ :GzŽn¼ ]«õìTÜkuÍqÛÌ}5 ¾¥"—¸ñ™8׬Î[Ûžž÷â’Í}Ñ|e<5n¹ã®p–vêÚ>º÷ Â7ÞØïÓXø§šr·XA#´;)ôjôÑœÛÀ*æ\y«…èÉU}ioÞõξáÁDEz3½\½0ÛÊnºžeý‡Œ½|·‡·XÈëò©¯Ww‹ÑŽo>:÷…Þu%½RýÜ@†{²®ÇŸ©å°îTÖs‹G²‹îÞA4H:õ6™˜:éöÌ9ÍëS#¬*.³ =5ÓQÇc3?Žæ˜¥©GZ9¨šé¦ñÉÌÎ# ž1ÓS5Ç| ƒÏr²Ê¿VµÆÀ~·?Æ!þÁªýÔØ­ðE\Ûû¸@w•+üûu-Û¼fu ûO Þ¥+µT†¾Œ)]Úè§\rbìðÅ+ÇjT{VFQ¼}óH9pI{œw…ž;•/e=ÎRpÂjmy…-WwU†|n»ÄÊ+3OIÀaÍûvúžyüçKvpî;êò÷g;®\éñ\ˆß¯3`Î+;¥«YMÛž²R¸ äïDõ…[¹W{®½Ë¦Ž|MA˜¯E]—Nß=ƪ^¶ð†ºò*V†»8$´¦k¡/-ÕŠÜ©Geçm#™[dËж ޤlÄxš²í7J²z‹ŒÖóÑBsäì$T*®Üè«^yB;ÒÞz_§ªk>Y:†ü­V™›v=¬Uñ½ï™_9ë¸z‡W¼£½]~AºÇd•|î{JNW—ràu†ÌLUnéÈÉDcׯ.ìXIsJo?0€žO[¢nÛJ†>RÝÄŒÄD¢ VµµÏñ"žvkß î’1\ux¯m%F_¼É~m3wwwx;åÒš8í8 ;© rÊÛn±*À‰ ˆÐtl¶{V¶žCÁÙþ\=\n.ü’Êýû›&¸Ì¹(*¨A1ø[š¶V] œ¸.à)óëÙ/ >‘TO2f÷/ìç›'½)V‚|½çHøæ[C=Hzí.ÌÕÏåO^Uüº{oi<´#¹œêy—I>& BS.ÔsÌäêÙÔ½:òå{»ÞLºÇ 1.õåN•yÛ±ð û\o‰“ê—x„DNìf÷M®‹‰z,õYìz*m:7wÜA;ݸKFžn²K잡ۛÊ.§¾ çv‹-lr'[:¶«ó,h®íñì ß½SÎ %¼ïµ]ù¥0!îÞBíKÕ×|g^…4ó“.û¡ßyW·}ïASÐðbŠÌÓ{B> hûF[§+ðš(ü/ãòý©ÙÖ;Ú Ši@œKÿá®»Þ}ÓxxÝ&çuRŸaƒvà©» I¯·µýv©Ù7€rJî)`²´7Iº”‰Î\î†wn_k—³£zTÃ*÷ºë†pÊy÷bGr0¢–{¯@×׉¦—iÞËÚ<÷S©i£Ûw-ò°+¡Á“–žÙ Ö¢‰”³8JoULx¦,ò—¼¾oâ'Ã_u;ÔMÎÑY•™¦Zºø^l.š˜º.7*Ñ„ò‹™_¹£ž ®{ÃAÔÍ"æJ ΈíÇOLÝã«lbh=)żV[— 8è^/{·pwDíí8eÖ¼‘Ç`_fÔIXçOz[ÿù¦zÂ×xzµ•XàË<Ìë¢"ì+WzØÓÔO .UËÎR¬E# TDÓ’ðnVš˜§Ø^KíÎÙ§3…çnjÃH¬-,ãc§Å>0gFe£i/5b¼´«r޾†C3™WÕ•];¨K’­ò8x2:¶Šša²˜ÃŽöe§ßÝ<|€±¾õåºéETž™1nÒbæ57†ÂåçnÖjš U òC¼¶¢ºŽææÅ¨uâ|0ðà'¾{~¾ÜOÞGOmí/îÝsèÎò<°s|²+nžÜ!]pãœP™¨wM¾ØWcRz!{îï@»k¼‡F¨ÞÃuês«Ý)f˜à;EŒÐ», §®htu*#·»^Z‰,µ-éÊ/V »ãAac‡<ÿr{éõÎF¡3#yqµ_ 1±/BøL&¼j´”/hZ8Ë£W U`á ¶ˆÜëQˆKWŒÕ¬•ŽÊé-„ÝØ×Q}“–Z¢xÉyZ뎋Iõ°WóƒÄðÎîwë·×ª%“Ä]6e ßk¢Bfì]Ò ¾qæµnî §¹Â¥N¨-öµnÅ®8t°!©zkµqÚÞ·ƒÞ¥D¢vz’¡…£÷;‹‡dùJÃ^žÄç¾^ãMW{רf+l_“ÄÞÙ™K¹Î”E=Ä»¯sX='·߃§™‹8Mñ`ëg)L¿¼´[=vm¸:›ëy`%ƒ7ž ø€ùã~ÞÏñw¯³÷-ûö ÿcË[„„Ö tW«nÏ7C|·:{±yA×£qм±œÊ'¡nî^]¼Õ·­±¬ 6cˆòbøÆ¼6½pïkõÔÊx³u¬žìÞm ºî=Ø'xµ®ßr&ûÛǼ¼2þå pÞUŠCqPtbºÕæa+Á]‡Ë«))Ê×=å‚Ε&6ä.u‹¥Aj5Î:Þ›¿kîÖ|k¨ çê÷kíçÙ™7½¦_€•ë°9ëò<ù§»T­×›6äò{W„K»i$¡×Z§²|1<½u‘˜«@Ûfˆ†:är„µd š„æ‘QT¤9]ÙxÕƒ^¹Y³S!M!ß§°Ù$͵EÑÎç,¦ç]Ô×YåÖ´…+G ÐÒ¯U;“U‰£¢û·V¶æÌͼí¸N­œU.êz*瀫÷x£6¼ Höz–¬k7kÙ ;^Ã÷"s96›{«Â™à,+£QÛ’_xvΨHØwMéÊg³3 4‡Ú3‡“’§±Piãß5Í{²\ÒA”ãi™lelÞ§•5QÍ—gƒB3–HìΡ97.1[”Îvp6U”Õ¿º¢ìS¼Ñj9nýì¹ÛŠ 8D\Ý žUQûÓôî#ØÈs7’;[›&¡Û,S†ðg,¾¦¸Qêx÷ ­~ÞÀΆžužÀžˆ£÷ky”7l­êZ¯…6|)z­ïrzåq>'ÒÆ^œ{ã›çêCÕÈtÎqÕ 7ôÓ=×À1^{w\À[Y÷u˜qžéXžŒÈ‰­×X:žlÑŠ¸^ˆ¶Ô;b¤É4j—¢€lð­hëØºraeº36hÒ¼»ÌìâdBøWBöúl¹Ö¨tÍ=ØéÔžöÍ®ÚyïPCלô&´XäÞ¤Ê:žç#×Ç+)åæHGw…#«Ï7Û6_Ÿ3xc>MK¼ÂŠ\V ¥uÊÖÖ*Ì›‰Öz>ÞßLö ]:Xíe¼¢-)w¥dSÑxsaò{ì/;5'së^ò«}ݶµzf>ÂUO/'Š^ÇÄT² Æ5·»¨geöDÇÙk3¬f­‰ÑØ:ýœ[×è³ØLîöLî™Î7Y8ÂñA©8´$iúѽ3ZÓ"ŽK&Dq¾ ŒÊÚ±‹¥<“¨=±d2Üzû)QjñðùœÚå“×u: =Ê÷Žk©Àñ½½æùwe.ÛmìY‰,êÓ‡W¼BdSHvGïÝ×øhμ6µõ5Ì×ïÞÓêZõ&û7l9iâ:¦RDÝ»‚•æôZƒûUCÅ%/îÍB¶§—×ûŸ‰¨Ÿ‚ ûïÙ/° ç |·03‡ Ø+Q¡Œg~ÄÃÄå³—œéɈÑð° ”=µ×òJúá‰dAçݦ©rlÒG/X•Ž %Öq’Gy¤œ›H>›¼/B(7¯ÏwUB€ö> ½À<Õf'–²öJá{ÛE. »cc)ŠºS ¤5XzïUiÞ–­¸2ää|rYði§³Š5Šæzc[Ö½J÷£˜&a£AmÛ1¹I{ºy Šžn¸ }oeŒÖ!£"«»Ð“º÷q¨¸¾Ï¶¦¾µöš$-‰P9WE°†s¹C1ª·´2ÖÛ{³Ÿ=]5²òD;†HX×U>Îá]³*Ö#g@‹²d;g, –»¨®ÌE:r÷àµ+¯%Ú¯ÏÔ EéO_¬O Í¿iëá\†7glwgˆW¹E±.˜<¶ùš-êBe_Û2Û«^‹-¼õ쎷ËK3Üiž¡IvËÉÙ˜s0¿ožŸãG©dº÷”÷3šªå>Ɇnñu6#K”':§]Dø|ìÞPrɘ»xfpǸc¶ƒ‚%œ; 9f Ó•Øj4»ÃCt3îjnu:²-kËWäæ!S·‡ƒ»ïFóÌ:T«Þ}wEbõ‘áöâú¼\Íë蟥à[díƒp .!Ùrw§:bÇí<ûîñIž}2ÛãÄuÓ…eñ$3»B¬õŸvøà\Å6&Ëný+rò—*Ã嫽=´&.AŽEvÉ,ø.¬Q–ÍÜÉK©aϤE7Ñ„à.7Â^]ô䬎ás§c«ki^X·ÊÀ–¹ÈXQEu(+ÅÒ±Y1g¼MÊXÖcÁ{ïCÖ¶/}™ÛcÝSÁø%íÌ[n® ×næÍ^I=a‡m>6Ä­•bÆ—$¾Ž@˘ŸHNÞöòÛ4Ψw±<»î =5 -S©‘Gºáçí;¬õfÚ˜ ^)=ë’J9Nówpa!‚–V0iPøÝJ‹Z¾ß§^ ¹3k½çÅŽgªÁ>÷¼Û«RI” ÌGšÎ¤÷ËÂ_‘Evn&xOHµk `‹ˆÊ¸Vÿo©õ¶M'ê´jWÕ]æ_˜ÞÉ}0á›I* W$Ü|Û6VŽª²[Ì5P¹WZ—ouh»xÏQXoŸÚ}^R{|VÃyV¥nRÖ•8U嬫 ¢œVØ»UÙòöON=&RBמåˆw„†ö¼¬~Nß•bœÈi Ü”=cïanå›~¤<¤u /ÎòQtð'vÒ¨ë D«©]ÓӼߨKl>y^{Ç.èv°Á¯; ð«Îâ7Àé^ÌÊšªÓùKðcLÑÉmü sÄÓs8êÅ ŒºìVÞd“ºÝhtâ¶®í}´!XVʬ²]ÙtLÈúy)¦W!#åê}tÓÙö‹Í”W·n:™OlV¹}¢Fæt§É-•³­õe©bf½Xœý~Ïìýøw_¿S¯Ý¢ºµÞ¹S«-sÅ·«•5}\[Ht•Ñéy›ÅõŒýíMv_ox­MUˆ5¼”uÞÖN“NÃxG'¶*¢Nñôä¬Ne Kgcd©—hïC…t4xY5‚²¹·Î™’Š[öÚ—“¦…æ}Âëƒæºï³9­îº]BS‡aÝóv{®ûÞí6Ȭ˜ž*Ä5ÅÉàLLD$ëy÷lì¾Þ½btÇûT?uÙ5ÇR7ÏqŠsžX¨’÷8³~®ö¥6o7ÍËáÆõ®ô‡—p|VVCܛޤ·GCJóñÛ÷é•Wáˆ~¿%ãMN†£©¶K z²®,î³SœhœÍ]s“4s´Tš¹K¤kù¨Ÿ{Ï|½æ3¢n‡ë=£Ïy—]w§_¹u,Ø,ªÁ%Ö÷·h%¸Û%Ô6"á::li[›]õö÷ w#ºÙ¸Én7c³~[.yì/÷SèDG°uÝ<ˆ;¼^ñ z/S¹º³–/A¦#ug|Ÿ"k•КÈ>‰VÛË䃳’‡`º˜³isØhe9@ªÍÅB.¢¼ÅùWzËïuÛT©µ¼Í4'p½U½½Ö¸ûu6÷8‘òá^Ú5~«Œ'¾>©R>¾†qB̞ɠ裩úz½;Ãj[ë;CÕá¬&”öÞ&»È.îÙ8}õ63X>>’eC™E1bƒÛ—}͹iȶˆ—®»O È"¬ÐÿWú¯~ïgåÔ¿Ö1ÈkŽWMÃbZ›;+z6âÚ¾r•²ñžš8ï¬äÏ)2õÛyIb–Éåìóóÿ;õx“?=h{]LüUwˆ¬:Í\ý)ñw>¶RiNº0~¬Ý7®³¬úVß ÌÍ‚ZS:w)»d7+ Ç2­ ÊDÑÔ—2ѳ(Ë­Êxµ^5}]¼úß}ÏV§s˜$Õ-bÛ.é4E-Û§‘íËèÆÞ2žà9O©§¥ÕµÝ6§}Ô˺±‚†àæ2Ý~ × È¼´XVW²lÍGÐdÑb')-mĨt¤s®Ò³x<¦­ ¡C[=º©¼«=ÕgÆ•MÌɺDۨʾíáÔ›H Lš.ÞT´zéȘ;ŽÐŒ"§ãêÞžœ ÷=É~Ú})Zp9• «»샅r½ÝÅ#ëêZ¶wÛ[@†5µªôÖ]NQw ® Îéxõ.O¬>8³ž6!‹X«WnØè÷Æè“Ù ðΣ̅åŒÔ–øÃán¤Å‹¯õñ@v`ÂÙ\Øk«‡¦•îzÆŽ¸ÄZéÞ;¼ýʹ«ï´o„ìft­iÞº5oâ½z€ºµ‹@°þ& Ý—{ɦ°16£í ÷{èë(jô犇E_$§țùöï²³zWbã@(Øß d´k Êqû£ËËÓ/587À<µx|]-çî²eg-¼ñÂÀ{Êïf¿WyN¼öÔ­À;ã^§¦š§žò¢Žµîï‡el†(±¹×²v0Ô« ÏsóÆ÷˜!<ó£ég7yn‚I®šÚJú–Ý컢—YŠˆU΂––[ëuͬ‹àîÒùH†¸zŽÍ [ƒh‡uÚƒ^½x½áY~OÙyM¸fß"oẃH÷lë3oÕO ')cÔù«¼jÄ›ÀÐ;ÍaO7žÐ³‡­ÔŠûgÎà“*zôR‹JÂÜ ÎKÇAž®ä㋯_bÅ@Ká›Ü05W•Ô;T†É´-æÅÏifo^íZ£*ÂŽÍ{¾³ƒÛÛ§¯ÆØ½ŽµÜUÁ:…s«§ÆÚïq\½îöøåøû#öjŵx½ÃsåJš­a…S¼%wF°)XáÛáµ^Áê;¾B‡¨£Ó·9ñkŸÂM{{R³‚Áò(`[xvWŽ]`ޱ)Ë^±¾ŸZ÷¼\¼Æ=Ðw·½ÅÌ­Ù”ŸÙƒ1+©É¸]ê¥GÅßmR|fCž>Ñî‹@xÚ”žÏ.Šœ‘>#îá¾§ãÐ÷r¤çQŒÞú£lžð|·Äp»áëYÁ÷¯Ë5DPö2ÆöÒ]Òþ6§`›çž×.­½µ®{ÒlšÝ‡Â¶ìá(b¹ñ÷¥'^Þì»cª?rm¦° ͯ{'¬®ê*‰¸@ö§ëÊÆâJçjàÚ¼ 7«:¡ž£:´bËÀ}Ù}Ùg›4ªlv6oªuçgfÒ'¨qµYǾôZœÊÆ»_¸±»¼×=5š5óRÅ”Å=7‰ì}kŠÑvêÁšñì§Ç”jõ´ÍêÞ›Hcç¹eæ65ñ£ÝË/jvÚ—8[I™ø{+Ú y¾2·¼O.uŠ‚ŠòœåfµëÑK%¯]sMJêSD«ÂÅo[²jÌ]ÌMÊ'·H©1¾U+¸uÙ“í!¥mŠ¥Ûé6Å—ì8sµ©ZKØï,xŒÓ;¦¶«®èˆÑêt—OtUsëé<8Ÿ¹ùµ' ü¯’ƒàÀVz™‡ÌÞ¬ê^¿?vYå¦'Bõ÷ÒÓáö³Ì½¯óëZ߇{Uº‡áq7.Ð>:®RxÆé³B¢ìè5Ób+&÷®iÜ”T€;aiGM{ÆŠ•`ÒÌOyNni7Jv¹º¹ ÍÃ\Jú'Ù –õë{/ûapçåÄtöb«Øë(‡buo³imy¶äk(¤ï£ËÔ¢y‡UóuxåðÝë\ ÎÞ“næ:•’¶®ÎE2nÝu¢&ˆ°´ëŽ9®—="ÚJÄcWQ*–“· ¼ùµl¬•j•¡[—Wç¹¹óiŒu’t¿&é£Q½.òh8ß—wnòí½ß_½ÜW³N©/Ñt3êR®»ÓÕÝŽÀmv3ƒ«…u3»Êú®ëšyݑٜë©jom÷º€ã%p‚†I²¶‰XTî»*öaáH=»šæÐ°náÆT´rÑ Ös¾É”îµ%,[&™ß“TNkñßBÖÉ«<_0âÕ­mõmû^<·AuÂÀdË€ ]ðó:é1Xü1 ŒEîÆ¶=îî'[]cÞ3îÞY×ì¼õÎö±×áÖ‡«ÍÒæôq“J•vJ .5Ú0÷6[}|ºIŒÞåpêt±Fk•n—bœxxKÃò¼¾Ý×êjú÷#Ìu¢écæö…Tª»v {[´ˆ œ˜á1D³cáŸ2°äÙv)W´$êèﺑ¥ÔÖÊË 9ÙE_+ÌÒ31æÊµ”10®˜Àb9K©^áµÛA«|)x`¢Æ¾Ü¥XNŽ×¯´’—’½ÛåíÝçç㦄3Â%}œªàao·¢Ë¸i°{JÉ“¬=ôìƒlôø2ÝzµãS•„Á*sºX°Ý8iº›º{ÈÐ·Íæ¹ižœ˜.•1½Êëg¼òp &'Sp7±}[4õGî0Í’­¶þŽësš‰c¸Ÿ<6FÅÑî]ž¹¼--ŽöÔÞ5fÒd¥€Kwc¨NCCÉ5Á%ʹV©€wÛÁ¯oºýp²{ôˆSõòrÙí-I‚åx{Þך‡W£ËP…•~ôY®Ïpè’VýlöZ[%ô›ê¼»³¸éªæDû½ïŽv#í¨‘ärU½‚JóíÁk2é%ŒžÓy°]¹©ÕÄS»¾³×†ëØ !íÚ\ˆ¡}ÏÅ“u3JËë‘»s!á9vаñfSг¹L‘4v•Öù>¿YÝ^›0$q­@§Ö› ýPëº-e4w2“Ã{7oM8Ö±€QK à nY%€W}O´¤Þ΂´NqÍÍ©¦óÛO¶ 6·è©:S0öT䯠ûꪗ–o;¦Nù‰ðÔWºVèXÕœ€ÝGWÝa–>«()”ÚSÐ]`"/°‰*ê»S)öJÜí%˜ìŸ¥vy‡*zñ߯JöhmsÅh#¸¦õ –8õë¼Î»±}!Ø}&áW´vF¬­Ýu{KŠ76s ÛKf’y·.[ãy«“j¶Vü²—²'.@rUúÛÄí‰î'ãk6­S¾¾Ñ8¤v÷©'=—áмk¶Zq»C}W›í÷oÌ9z©EîÛ¶¨rêå|•6z¦Î¤ÑZ•\jNn«)òï:¢•éQB9s^¸¬¥Ž1}hN 7ÖVva4SQEQ­ÓkÙê#³';Ës9·ÑM;´iU¾?Z±û‘¹èF;J÷¦JZfàwp mæSóyœÞÐÚéãë£B£yZ2íðËÇvßD”dâ¨_b¼ÆB:œöeöß.Zž<|±QQe[®¡MQ{hvªê‹1³[ÔQï–ßu_qÝ[t9ê©r"¦¼é¹¸µ™Æ´t]•áEvåŽôáÕawM·}X #×Fg u˜5“…—M«¡½‘×p’Ç|xiÅ— u>L'Œq§ +\¸æ“½{Ù*ìCEåmpÎm³QD±Ùwµ›¡!²6¾uÝŒtá²v¾¦»(Ô}vòØ™ WxPÍg‡­úÍ_-«CgzRs”Á/‹éÄ,5bY”ZŽRtRŸ;-ج(OlÁÄ=5²FÔ¨Ïe1µQtjEænot8¨Ík»fpOo•µúü#¯}ï×[ûì¶—½ÃLW7µ®MSGûVù-U=0{oÕªJŠ^ %`)ªpnöb;dM¬éÙºŒ‹R´ÌšìWSµv¹ÎÖ¯ªä¾ñ®¸rÒ¯B_8ó½Ø ®ÞÒ°×;°65 öòèô¾À’¾:'˺¤ã½bÚ/Žùâ€UÑvÂTw³ñ¾íÙ¾x¶ü+fÚåîT— (fó´t@‚%îht©.ÚŠnVaYLÅl+ »qò±IK›…Š53é,£ZQöç­õ*÷¸zË—p¥É+p^ö«FFϰ™MÕžÀÎÖ‹˜Â6D]ëÄ*íwpGÔ7ÜwÜky€B¬$}oÆïÒ„ïߺ´½ß«mßêK,¾Jú7îYMŠAÚõç©*òÅb¡VÖ)²F<û&Õ.Ú4àïØÊ•h½*·ˆ¬ ñÙÛt€ˆ ß‹¯\ë+¹­”ý'1•¨+¥c?ÕUów -ýmÁB­Á?2‡êÐû*ÿo˜ºðBÑêÅ=y]ŒÖÞW„65VkAm§“Yu¸Ö!q—Ô×zmzzÕYìô/GI—ea¡MT³“Ê-¥·´ë.v)œ{äv»yxT˧™”|•Ln–òu)³€å[Ú`-ß)Ö;†RM \ ¬3&ÐîÃN&^zszPÉd 'b¢:uÄšF›ó?zÕsž÷ÞÒimåô ›¶fÔÞ¨­Éº>âÂ_{½gg 9é}Gd¶¼œÕY¢†+ UÂ3˜û‰Ù†­©r±!í£:cÖm؆Sïgo ^s=v/6Ö ¯J§1H¾ wuäÝÑ·öËÕÅ7¼ ÔÑì#·1[£Y3{íz»ã§‰¼XæÙÜ/‡M?óêûê+Ý@$:…S­¡Y]áöìg²¹Øªï3µû1ÇyÒºÞßY‚Ï£ QÔ óµRsÓÝG3Ù{±™n´Å3£^Ä6Ø]t¾CX<µsO®·§žEr±Áuý&Î|iàî#œ|Fªì{²ö“Aä9)Õ¬¾Ôk2u¶Vºõ*étΞUÇ»Rè¯+C´ðËPÒ½Åx5ü¹PpHœìS•¶áÛx&Árç35¤‘k<óÙä¨iu ]wÜî¯g»V¸-ê7]MÝÖÍUÜ‘sì•zŠçÃÐéo%³Ï{eFEN˜ 9œæý›EEr4íhîrܶnCIk.›¥X´áš^µažØ¦Ž«÷5½Ù„ytv/yÕùè`H8nì¿kà<:N¼TúèmõžG%¬o¨W2þUÇ ZÞ2VºÜ¥ØKØ5=ì×fÝŒê*ŸP[­7Q#NZ’Ú³ÄièÄ*-Í¡qöq´J·Çt‡éÔ½tùÑÝÁ¼”OpM<’pŶñƒ¸eièØŽØ¨ÅLs¯¶ˆÓˆi|_wÛ ÛL=YÞ¡Y•t.êžhz±,ðaÅnº²«u±x-vªÜ æÑì«W·Ã¹ÑyÕØÚòw÷uþ?½°¬ÝùÑüGàßZ(ríVv°(‡µÝÌ%«µŒâù%Ã#ªÛ&ÅíÉ`ÐZ K%>f>›¯ˆ<%w'LLw–#3rîÏÏ*hµÌ=^ð­TQš+Ζ2:u·÷[ƒ§@`¸bÛÎx7¯”R›yC÷¥Ó†»Ö^˜Ñ]¦²‘Y†xÌÒñí±uyG`×õé<›;|• ´ÞTú*Z XÝdÊWw­³8—]ÓEóîîtéQ·¼žgïdÄ”è«Çuãì‹u“·Øg&¼TuŽ¡b÷öb@WqÓäI˜ï&R¿$´òê®íC¼¡5]Ûátß^²ûìçYà/ÆíŠÚRözÇ8L¡¼—ÏœôUÛbü¶ýœ-Èd‹–HP‹l–ÊÏeÐÆñÓ·žÖxËËï¶îµ×–•Y¡¥‹CÓß¹ú¹¥Zäg¤6®ØÇ‹Vú¦Þ½òœ¤ë¤ÜÏ.wè«»Ë7á`¤ývZ,Ë@îÌX:­3Ô•rC< ¶öSζ7 ©µ¶ø%ua ¯•XÍc4cmNç²w v+¶¬"¬ß³åÙvZ8Æç(ÆD:z¶–µ§7EäOvvš.‹Ì½ëšû©¬¢+5­ÜC¹seW`‚Ž…”¡¥Ë z“@|[éÍîÁ¥ªF2VA—;;jfßWkÆo½ÍT}uço½ŽvË<ó±… Ëm\ãζ‡wÍfœçbáè7M]x`«–ZswžêµÛ’ ‰ZW¢ÅÒÊ4·î¾|ûÛ¾XÝ3B¯¯$¤F±¥甽Eéͺ ®Olúé=Û­Ýd¾§öÓÞ½5ŒMêyË,=çEõ9»ßdÁ”€šg X ¯‚¡]ß%V÷8ìuÊí{€ìåÃ3«½tÊKB|ðŒ¥y²Š<-Ú®v™Œ°s•B×o­Ç‹ìðõáÏk¿ €'ç{–d‘‡õ­çW5BëiÖ…®eç›L{Î?RZæf ö}¦ÈÎø‡íÌä;r…õf·Kmþç–¿ÎÊ»žóö´4ZÈDXÞîKõN{¸¥ ÙqÕ5ÓœìðÖD´ºÃµ˜ íùJY•À9Ù‰ÖR=»8DYÞ1‡sµàè Í} ™µÈá­´M];†¬Pà4fÎÜÊŒï¢"²…Ç+\õÑDí*©]]¹®xÑHÔ~Ú[7Žã¬K¹<’¢Î}û°p|ûtd5$3qIüVÕ ¡>]œõœKäî¹f óÉl­9y…L×–·d†½J-T©‹„ŒÈåŠ5¶·¨'žzb¾b×Ä;÷—£‡qƒï0´½ÍêÇYB¸Á”ÁÈÚ^£:ƒÞ§w·\@§œ@1Émå`]%îE´24ÛÑ‘nóå»Û;°} âX·N%ª±Ië Æõ߸—k}íÝõ‡~Ý™ÞeUz¢vNŽiÛ@Ÿ2¯aÎåèµg6rñW½K«Ô7ºèW¥9AÄä wHkJ:Z–o£:9·Ý9jz¥ŒO|ifcâw‹ä¯ªl#:–f(Ì[ÝѪ$Ww7~ï’É®v ¤;,QųGd+0 RŒ¹]Õ¸•¡Xìf^ÝFþ³(aÕ†êì5¼|i¤ïÙ7ÀûÙŸ9ñDë§ÇV÷ÎëîÎ4§(89]Îç+áë>öÉ^ËWSý@ÇWŽ(ûλT¥NsE£ƒÞÙƒ_±•×ÞjÀ*QîžðÞòÏ×îª0ñ¥Ž×²ë|»È7­úÆ-ÉY=f—rî•Ç–j7uá¹·H‘Ç­±XILZ5™ÕÂäõº#ÝhÝÑqï²lóî<»Â½½z¤Ú\Žho[ÙWvJž ¯i_RL”³:ú»Fwð¾Ú>PW)׿|†·”«Ó•æãËV-)•Ëö,†åÐ ÁŽ=н’&šâë;&!»wS¦Ýkvõå…f¢­¥&¤rpâë9)“6’¹õåój%u/®±¦7¤$fÙÉîÒlkï4Õ©Ý“`¡á³,‘ÏlŒjLûm´ìßsÏvÉÝîèD;X¶X³¤óëÈÔF´â-ÎkBðK–u`&x8–¹ÐÞÓFueby~8¥?=½©Ã=×o«£~*o—œ«¦7ËE ‚´Þåñ[ÆÆ·‡+Ý–n3Áöç»núèW¡5=´òÚž}žû=5'7¼7¹ó–ì,²o¤chÞ.ölHìŸLâ2TÉDŸ¼O…øF<;Y`úý+Åíø{Ò²:¯ Æ»<¢h ç»ï0¶ôAX®£ŠfˆG[Õ‡³”ðïwa·§©'W@)%ù‘Ë u¹ÙœÒunPdÝ#·¹m¶nfrœÛBµ6²É§>ݶ*w•¢éS9W»=Þe·Þ~"G+ÔklVQxq+ ßœOJÇâî¡2æ÷¥¼…Þ4È­ Êx'NžeúN<µ }ªÚÀ,¾ ß²GÛXè”e­®¢í9ÎÙóh‚I]{¤!¼5‚f-ë`1]€÷­F}ÈQ Ž}õY±kÍ¿ Ì–,{Ow¬yc¾Çžl.CœçC¶,ê²§nó|‰Ñdz%<8·ºÝïvBܾÍ×Õð–•ØØjk7×ÁѬ—•ËéwPåuq¦ÒÌ ÁÀèlë¥-L¡½™ªÇÎøç1§ª\Ý6ÚÝÏI¤ÒÔ£˜±ç>§3ÝíÚÊŽ¯­YãÒšEJJ÷9¼oÔuy¨f ð:š9¦SejK•»Ã0o—vv÷^ñ먞©ñÜ˜ÎØÞw:öväEYï]Zõ¼¹ZÁåFµ2hïº@ßoqö];ù»¦"Àlëã:ìz/“=çÊô³M,í›nš-mE×Ç_yL±Ó«Ù¥z½é[)ϸêŽaƒ®éôŽ\ ÏÑ6zøX(e1;Èhµ=îg¥ Ý@mw”5{‘Ü0Rev¼Ì]òžçWÂtI­›~qbe]ï`ÞšÛ˜¥ §WÓw­lÖ =­’æZ~»^­7½¾Ÿ«¹Ntƒè8W hÚWc½Âë,è«¶7—4JãJˆÂþV·â¯ÚѤc{ŸWß}þ{·æP£µÔ¶®’ÏzÃËfºËë˜:ÞD§ ½µDs“÷áô-J!סP_%ãwâ{J!ß»³S"´h©‰´]Z3ió3ktÚßo*k·Á­ó§bêðwf̧ʧuȧ¢Ù¾•¡!NÙÀ4wV×C§-‹µã½¹ÈÆž[–슔ï…ôW}Ò<¹Ç·|¶C]–£dÏžO÷€uêÉ™åRZ»^ëUÕFïNGDÏÄg“ë*òȳÝY|„î´ý ³ª³váÔýVèÐÙ‹­{«B®+`³ÆRqÇFz^ Óv é1àõïË­r÷ûêïïçyÓÍzÜý¬ÎíÜKmepâ.´.½3FçénP}·|”ñ8{¼îNÖ©¯âJüóOºÓd6nÊuÙQ¥Ù3©¨ä$ƱZ ŽŸÛ5æ$ú «¯w¨Ñóa{Á»Ó²äŒx.úÚË­=‹°«¾¸å!‰ÀvøpXFÙëNͽoš- »¶eçÏ5+}kÌ×®ò³{ͱÝêô{껯kÆ'®¹L·ˆRî6 ò¶òêu"ð¾ämd††¬{ÏcÑÖ}eu †ëºAJ«Ò?_¸êëhJàvÛLí=7É„¸¨©|óoQUBäBëmýpé=yjÀW0:¾™^ò¤Ì­ÚÕ3…ÒºÛ¯ÔŸš÷ã›æ»óŸ©E`L«"Ò ’ÃË_µ•Ü 2fµÑQù¤"uÞ($ÁÔÁYeyj]ÏcÔ–¥ÛmYh}éŠ «rì^ Ú6Óì×ci.Áy½Ì²‰}.Y‚Œ=Ö§D¾©Ä ŒÔí®Æ>v2<»Ðñf[§béåÅ’ ŀ߹ä>7Àö÷&­m/9†½ªº¾±Ï¬ÙÿúÞ\ÙBL§ƒ4—àš_¹ñÑ’ñîÂs2°\˜–õ=Ô˜=›Ó•cOeL€-*aÓÂÍZA«³Ób(ýsäÍ"1™—uÔêûy.Vñ¼ú%C³6ÊIä8´j›5n×)¼÷ƒ]õ«k³º9J²ù›Úx¸UPà?„÷—h~­«ý¸*¡“Ó‹X57ª3\õuÓ𤳮>gQ—ÆPK ^â òb«W·@ÿk¹BvRÃÈ>) ¬T›é‰Vb«ÞäKÓ[V w_›÷¼Vx (§¥y©ç™œ+i,®­=3›¼{³8›]X¶0Í]yz¡k"Úl,¼É¥­ÖÇ0¤éuí®¼  ­°·óâ—9—\]‹ÊsÄlm ¼ YžR Gspð4êŠK®û”-]d»‰á]„mmtáMôܨ„Ÿ½‹s´XPx¸²òΈ(äáÝLkq¿n#óÝ%`,!é†ï'õm­8ß›ã]yI/)VTN›!´¼.ÝénṚ{>ÈMF3à½,uvùï¤Ù]ÁÖÞ:ÁXG`»¯¸õ> v¬Y4yîzßkÜ*<®„:Å<-U§ÊÊY—W;ÑÑP‚¨cõ QWf‘µ·Ñ^QbHnËŒÍóô¤EŽÚâ7ÍŒTÙڼ䋛¸R´h]Œ¹kÔ×uu—C¶Q©—Å©QsÙWQN¬ð £µ.aö»"­*3.C`gÝ)NYÍ¢÷ªJvýKˆÂª0|=ê¶32ÍÄR5ÁrüýSf"³Ýð÷uÕöX±¬5ι¾{4ŸN븚oÒ`Á:vÕ,`UãË8¹ªaðy”ÁJX;xºßfC⮕šûï¾þ¥á/ò+6p¯~‚æ·¦2eFÐvŸçt1b@f ¶¦ËÁC28.€0±Às l^éËw®¬`Ó‰3Rµ¼€µæÛÈ/ƒ*Ãdæê U88]&Â0Ì£Xm¥–³+“U*%mb핵£)h‹íëaRú¿‰ î5NûM±IKO¢šåÄÞ\©J÷nJµ„‘îmów•}sIˆ(ÓÕ¢žS"ò•õZÝ»M·W”sHB‚¤ÖŽÓ U+1—HUÒÙY†JLÚ˜x8‘Îg¤Õ\±rwŠ–u•hÏŸÆRµLžäݽLâÏÕ•ŠÅ(Ç?mÔöOÍŒéÐ7êØIåÑzt¾ãµ²….Ï)[S‹fø ¥W·Þq̦< ÖôHÖŠ# |ŠÛÎQuëÏ!9æ ågâöýÝ—â‚Ë~«t…•=Eðõ,ß±N܉g1xðû>/ìÑ]\oŸ4û¡AO¶ÇbG’|αÎÌòÛ¥7ã'x)`jzûÕào¸x¤^ |Ð÷¾4\ŠºÙôXz{…ß¹xúöV¥%K>°ß*€fãWíº•ѽ/f¢¦ˆÅ Üí3 ç}¬L—zöÙ1™¶¹ÖïEc‘c—n:›ñ…5ãJµÕ^ÁpLÏ‹Ýv˶&tu«£åœ}VP„}é 3/ïž´k…ÞØ´œÂTóŸi…p]uÀõi9™2õÔÙà,E›]Ñ OŽ´DõÛVº+ÁhØ/ í®]§­VQ›c"©1\O÷¤½Ù1ضǗ·¶½K©Ó™jjЬÕîÎs*Ût54 –¦3-9~ ~¬¦´TUïi~‘çÙŒMáÞ~ífÂc™ëegO"0ÞÊ­Çvu.⋳EÞ†ÐN×LÙ;îB*ÜG´·7#À;å[‹P&r©ÆNÀ- S³`q£%MíRš5zJ˜|ýÏÔ÷„÷¡aw\°ä]į؊0 82¾’6=Nm룺›ê8±›ÄxeÇ$¶Ï]°10·+tgÎ1b íf±×päõö»©1ë¼`mXl\5×^\Ô­b•YÍØm½º|õ¨®—õ%gž‰•a¹yÒ«¶¦õÎê”sŸq5|wýtª¿}@­º+jS®ÿ+ÑrF—÷‹=_Ľ(᪇ìÌ^dµ¸¯[yÁvëx!ÏÆÓäµã7N÷“›…tš[«ÝÃÝÅ‘bÜ å³%½6)±ˆð¬¾t L Ô;&¹šî›Ò^‚Ñéjº³„2‡®úU³[0Máûi¬<”ìÐB™,fkëõùšâ«Ç4¦„ãìËy=©,uç|%X[^:QLŠÊcËwEá¡tqé¾àÚNgrDÚîWWÊ#è)7We®åîû€°NèåÞr‡˜Íî­ÀÊLÝ ÔæDÔ>N\nûFz½¶åe”‚›€L3_t{jí^ï9ñîË wcÜ«;X„íE…száÅ’{¦JæG´ÃV½}íj„÷‚ãÃùCœAnÿJ¾õø÷.¾çK•ã»§N®ÀT?fǃÔi^¥8•ÖëÔ(Ú€o»%®hhå)/\”ü­Ñ‹DÌÀñ@(\¸µêð]FÓ­Uî1ÝŠvÅ${©V¾ê,*_rroÄã·2HÎË5ª™wÈÚ÷GÞâÛi/óóöî<÷”u ¸@‹õu(ÇM1ä§^¾%Þ1åvá'ÁßL÷VqŽè®ê“N`¾=KXÖ¢òÐó#øÜqçŽ+Çu×JÏœ]ðk>»õÔÇmBà›¯¼‡»œVÜåV"^~ÁÒ¶Þî¡ë§Øs+Ï¡šê\|l±Ã7½è%z{œ·ÌwuœãQ­Zu ƒ[WVxï ¥O<„Ñ}Øè«*MõŠ>Àc×]-ËÁ?iöå¦_W—{ÍÊÇ9ÞåF2•ØšÕ@®ê-ÜÕ@&@}Vöêæ¥Ü£žîÏiUtÒy·¨{ÒpÆ"Ú™©®0Z&k#S¤ÖòP›Â• ãN¥íá·8¬Tó¸¥UÅšËÕÔå£Ö<8pÉO—NÅÍÂSs5¶‡©ÌVs8 á9‹²Ø±j–hR](M'ÙÔ¢¡ìÑëòU®z­ˆÏ ‘[òÅ™Ä*³gÓéåë;w£r 9B±0©‚êÁLJ¸ßº;ÀᎶÛÎ<:äëL›ÍÓÃnX³‚ßAÏwMs«WL¾¬¹*ç°õîá½&ïj,¾HËÍ¥-Eêéµ[Žm[¼}81Ú~·Ñ _O)„h÷ÙÍVt†êᦊ[q<Ý{°^™]Þöö_»-–÷YÑ—oGòž¿ f’êÎV>T´*W”ê{FsfÖ!›HÑÞê4¼*÷we\8øœ³ã.žSr¦Äi°áêÙg›v—¯²ý ¯eRxF°JÄ Õf·Ò¯/AÈz¶M R Âë)ŒC¥ŽaW˜ïy H9IZ@7%n£¬•vÊu;NmaÚ¿IÝ—R0®‘EïxˆûUóFµ®Ö³d‡«n§Ût‹«õ&O³Ç¤Ä|©%'bwݸ»Ä"qVUýñöâíWâ-"ÌÄèÚ‹ž-êélmärÒ°ƒµËœêúÎß^Š#.ß·UiŒyµŽÎêÝÐx¸èh)M’í{»Ý¾ ÖOdÄï«Sc j(ž|"ö]emû;Û§ÑÅâà«^Už{Þ®ašäçIÇ]æ×mÓ·Ü÷7r,¹¹`ªd]>[œ&P¶ ‰"9ØË‚Î$­À¯x—²‹§¹bÔ¤©GǸ±¯ uÚ¤˜jmmÁÛj–o „¯Ÿ=¦¤jrЦ×a‚Þ!Év¥Ä!ÍöòYbs„¨†¨–!˜Wdt”’À‹A–œîuÄ,‹nã:’ä/ZêË}”o®¦9Y¸Õõï•룆õµMà‘ÅWò;ÜwG…] ¾{ivµº>“«;–ªœ•Ú󕸦N¶÷ªé·]h™Jk Nòó4´®S9AsbÄ"eºÈÐZB¤€ÝB‡m'µ‚ân÷Ù}Œ5^OTƹõ@ißßb«áÇÀ…Û} ŒWMÛÖ`³ã7¾ì43`¥ttªVñ?Þ­‘V¿Õ9ŸY”;ówé‚×låBúÇœ˜ruãîln®Lçv±öpBÅ­d¦–ŒÓeïÒ ôÀ)ïeß…[ÅsÙøõèñç§W{rI3,²ŽôD”&[Vl¥±—]+YûV»WÄÄ£öG—6êðQ”Aà°=´ÁG^ÃR¡²š›Î™’õuüt_º—q€ÊÞºoÌJ³gÏTÝWsH÷Lܽ«M)¿£KìjÁƒXÁ±ÅÈ× ÄúÔ¯lñ3aÛ(ú™s:éè]HZ­ãÒÁÊì}lãZ/S¬Úžt–ÒÒZÜoÙgiR1† †½]s¥Ô0ßPï ý]`Uúp.ç—íqŒjWûYa¹¿½âjðIœnn³à©¢Û,ÜðÚ…øž1×[uwE¥dÅœd?$û{6 ú^A{²èþõ’«=“áí¢I6.{Þ¾ùñÔó\ÆŽiÍéÜðKq§œ0½ºé!vDøo¨A|–ÒWº(Zå-4uQ*¬àv*•6t òQ,­xr•Ï.xoRëÎì‹2içæ>~ßCtæÙ¯w¿.^xô5’z»iŒtxsg­ò‡C7-»Þ¡ƒA; ÷QÎ{ÎF7ªY´0¶FÚ‹ÙX§Uªzß±£~/Ý´àÎúø7¨g_:<ä3bÜ\«Â·¶Ö®}™Ä–+^V 6¦š#ïÕùû-Êó½Ý5½%6ÝX¨Ä7VxÌý^÷QN@«’žæ¡Ï:¿?áÞëK¥`, X;3&~Ê$uÛPìØæ9GYCgí5•–½W»f¦­ò6]y)r±íjUåyErŒ}7AÁu‚®!‡VkÝTiÎF??Eésy1 ¬‰Hõà·~ßh±š¤Ø9æu}nùf¦›¯pOÖ3®Š=)¿„„E7FP3´%\pfpÙŽÏ¢¶¶{+$ý¹AqÓi`$oº=(ªjˆðò­ï†PÜ/¸Ö;qÒ;µê}@+ /1“¶ùáÎ>ÝGÔWVøæz³¼e6·0„"¤üŽ²Ò¾Æ{³¥X9ÏœF[µy:eqvÛîÝsH»£Å±uü¤°y÷.ç‹wÓ‘Šá?^Uš½=ËòMѼ•·ƒ×#¹ Ä ÔÅàô_9©×Á­ ‚<évufjÍíàlP±[¨‹c—Åjlïc»µMgUìÞÃ&nÝ)l=oDÝÇwÊ:S~±˜ v¹f®îXù‰­iÎjøwŸ_”_vQò»×©2í6ØÇÚñbö3ÏÆwØM€œº¸=”jSÈ~$àðzÒB«Fzm] îÊ.•ŸAu®–mŽÂMåz¼‡Óÿ2½R–:! ]Æãó¡Ë³Þ 9‡Dï2=Jä`e‘;î2Ç%Ø¥­vj'yc"9R-æ' !Ó¹ªùcŽQ2»Uº_çpg½ÊçSÜġ׌Kò›|*.»¸è.•µƒˆ‡oDeÊC«k‘Œ'™þ(Š4ëiWuWö«¿WÛz7`¯àÙøŒõۙߠœåBä5Ъr×eë¹ìå¬Úzsl(u9>–ïKyM>í¾#?ª£æ/½W5n¡«æè%ï^óÙ¥Z×d`ý•ÑxTöm{•f˜5ãX(k­ÂÅÛ¥ò÷pÜЉÛìC]åÈóÝ6O²µÂí´°ó)7ñÛWr,•ÆÍ¥' u)›÷kFŸŸ{-ðêUÔRu/eopãÔaê½¼©xÖs\$’`1®Î¼oÀáˤóøzÛ¿£<ê{Fmîz¦6½﫺JuùCnðøÛô†_×Dˆås|šºàÉ u¯†FëCÉõê¬yݪ]ïkøUÜ‚5o“JÍŠl&}Y$ëÅqîöp4Ÿu޾ÕIÑÍyõÇöÎQ×>®>ôÑÕ´}‹·©»+_¨;dæ¥YvÉo$ê(F†çn®[C¶~ÂExÞ8ðßm^ì踕Á- Áïj”¢¬=’ZTJÜîâjZ›«g…Ù©aƒ¾!h]Õ凼½¾°07}ä¥5¡«†R¼]>Y²‹=źÃDiÛŠç²Ã °‰ÙaÀXj7"YJÚK2¼B?e®£ÄÑôçÈUÍy´¼¤7¯2)Gâxé“Á2üûvΕlýƒwsgAêv$­"±Ñ Ç(w;Ř7;_b¡œªR®À£œÎÜì’m¨{^Ñ÷‡!£Ì=¡¾9ûÝ~F¿«6?ÞtIeò>ïu~êìÅ[ìí¤/7¦Õ À'4çaç—tkk .lŒÃkîÃsV–÷µ“ƒø{yÛq.ºÈõ®ÌØÖ¤$'1–×’â–¹ŽÜiÅÒê5Ü/xuK*ì®ŒŠ‘ßeÜ©ïzå÷,S«ÖÇxëOËÑÙ¨œ¿ka6n´z±C[ë<&æÊé£ Wêäž¹ÌîýÍ›¿Rn²…Z]^¬LK[Dù‰Q¤ùe56îf¤ô©ÓVÚ8°{c¾Ú™÷˜›äиÏyôž"o””ÐÔ]EyF¯5°P\&l­3Cu±NðhFÆAS·‹´|CÎήb[ã]¯…힬sÞõZ¨¼FCì5Êafä i]Y¬˜ª]¼«fmn½ö¡ÓyÔ•ø°¦óF ¤°e†7ÕÕv¥nØ*µpºŸj6¹Tí8âÛ’Jï¤ÍFöÙîß”#c¬'|I %ò>&úùú¡ö©}¯'¦ÔÊ®³·£€úyÆ"ñžJèrV®õÚLZ¯·ÝW;*5TÊʼwÖDEš'¦ë¤€ãŽÌçÄ£ÉqäŽы穽ۛ¥¦í>ÂnSIp2Üt–«^.‡ës)›bÆŠÅ¥¼;+Ú%n5&杻' ]©®Âžx/VLå®8n¤›±ËAPÊ^—PÇÓÛãîØµ ßkñö¼Þ˜¼«U ÈñÈñ¦ØN—|:ú+5÷5W«.ßyv¹)å]‹Øoë¶²±‹½W½¼›ŽÜJ]ü—Ê‹ªüíý~üÍó]*±LÔó‚?–«Ý^ô¥w—¨ ì'ÒK®§Ë%×PÖN*ÉÖ]”°^#L?¢¬êµºá»(r­–ó¦ŽÅEĂ쑂´¸Ð긫§Ûiæ­ëç×Öîë¤á«ã½~-Ÿ9bˑ̫ûß®¢3´V,ûeôÖXñŸ+ì¤ò¬>Q`vNâ+*cjÁè•X—j›Íè6š¨•A±·xÒvä×¼£ß¬…VõŸÈÜ/Û% C¬ R‡XÛÙòt{2]Þ—°Íz›cgÌ3]+Y”%½,:¹ò×e4êöÝóÏšG3ëÏZ‡!=µ…¤š” Maßuù¬ŠŸf/em2vÞbøÒ{·l¼µ€,½Mhïi¤úÆ ¯¸-åØuZÐÍôGŸÿ_êzŸz¡¯Wú¯ß~®©NÔÏÈŸÓº:÷ðß~²ß¢§VÎ+# ½ÄT=íêž—F¥—ânQ™nQùK°ªWº©Þöö Ø®.C¶õü’¿†¨N/xvœ®½òzƒW·]AÓ˜‰‰fÏ!Ž×JÞ¯wfš•Õ¯|Ž˜éøPO`L¿ow¸èê|¨øáa[²¥ Q†V‰DçVqxWi§IîØD»ŠÎª ÛªûYÔJ‚ë~¼žÜ@À<|³KñQš5‰U–íg!lÖ÷d­¨êðyߨ=ú§bGœWíKW³/µó¹yŽFñ„PÞ9ÙíC_²!IðEÑÏ1ˆ©YéÂN䇼ë¢ìé°‘c¶έ‘hßs²¨æY!ÒͰ>¿õ½:jz_¼}ˆ”ØT®Êî‘?Þð¢ŽO:laÇw^^eç1hR̯'YgAdßÝÚÙ\ì4MqíK2—+†Hä[´I¹X%xïyÁWpç‘7ª†WëÆnN›1²¢ŽÓà+2V3¢˜¾¯³+šž»éÊðõ Ù:ѾX‹ã>±+’“XeOãWRUàØ¨Ü»Ëã&R!zT­Ô&²ljG¯c¥Ê+W¨Ô¨]>ª¸ ÊÝÆ¸Ñ=j”“8¾ €]ÃŽ¯¡–~ÎĹT"½Ý’®Ø¤ºQ¿u߸‚"Y½k¨õ qaÞž"Üu—“r×5XVÆ®|ë‹¡r—ðEõõëíFÔKo8Ž4b“R7EÜ•œ-tßCá•áö틺>*ýdãíé’U¢é¨½iÌâ3Η«aaÕ¶s†ªßœÓÚZ dC„î@Ìv#ºô¿j·\tº¶ä¾¢Ä]~ ì*cœ1%äÁ”+gM†£¯{?•ßïVhóØH¹WÒëÏk„%¬s-&Úµn^ U€s{c´î^Ìoéëå¬UÈÕ01àèĸ\6Ø¢TBÏ#Ž2³Ýð{Â1N¼Õ¶`˜¸}qÛÊ–*KŸ<í¾7–§&»íiŽæKê Lã®§µg«M¾|¶Œä¦¹K—ëa³½oPì˱÷@ùÞAÉ^Öu¿vÖª9æºÙ²¸5&)½lÓR×l@¶\¨Ì®î¡}E®°,]ÑS•u*°Mvì³òg€å{až½íÂéN"®+œ¸\)fåE³jNÛ$ŠÙ¿\áLéFœÙHŸÜ¿i÷zȾñGr…øí·S2) ÝÐBETjÚó­] 8b·¢ú_xæaê0•jZ×½|-¯Öü[ÖzüMnA»Ül´»±ã£ïwºùÏ;˲ðÄèeöA¿qÎÝ%Xùly3ιԕ™[ {qíuñ̤ôç,ÅÏ”2'pºY٥Լˣ(Uû–NAš÷x+íú‰l’^/K( ìù¯°JözD†Äí×Uá¦kqgªä´•ý(e‘”²®ðŠW`igžw+¨M1Î/ÁâÛVÖe ñÅ›–<×]ý™­$8o)™jêݧMAм 4ó–›öͯã,†W×ã?Q˲¦»xb\UýYx÷Ô*b¸˜MwðÕýw; ê9»ç+n–w^­†Dö¦jºã”™3Ù¥›õo³fÀhd×k¨žô¥'^Ù¨.„¹ÞfäóljÝ-pU…sj¥Ïj˜æêE1ul5TÕ9ð7³&óOyÏW«o7ßw¾®ï\ô«€v¹dZ«=Òe[Ôð}ë’ô‹)ÁÒ£W` ~ä^öù£P]nÏ?H·Ñ×v†9úÑÌѼè,R"^Õ¸ücÎ;û^ŸA/ÏrÁðZý()X®8’[»žo¥q¥±7çëx50át•"šv¬¼PÐf&:ùqÜF¡­çŨfIÑÒØ^Ø;—R# Cð«ÜçijwKÍð§îÌ—ít•D× †dßiËßGpŠå]&Æ÷j°ªRÍ«­œAƒ™\ðY·yv5ûÝîQÖŠâØZ_D»\ÚÉܸ”Ý‚w^³B×}±ðsUBm0‡rÝñ\:ó\U]<ÎçØ.k¼îs7Pxn_)OœYlyï»Þ]‘_“¾äÜ@®~½-!¨o·Š§"›ÜJábó«tÖæ°·N“™N`æE´àÜûo©Ex*F·…ö裡1›îe3÷ƒß½;‡P¶P·Û^öÏW¼WenøVS[#s¹iZ©®x¦ÕØVùãÖïŸ Ø½Ôè;ƒ/)ÖÖxe¤§»^ßÓŠ1X$}ghêè-ò«3níζºTÍ› 3NYI x>ÏòµéïUëâóáé ËìMQ®î%>Ð1•ûÞ¬¡Ü”•ååwí¿%ν=r]k§Ú b¬óºbœ¸?ÏÕÞ®Š‘özÛõ'1 (m9ŠÁê›4÷6@ÇS͇n[w)¹¡vfH2(Êݳ{!­r¶´µÔ9˽;ÊXlÊÅ¥ü[ q»¡±ouj9G‚¨(f$*úV€E²·u±aA—E¼Ÿq¶·{[©Î{W—)̳v¹"kñ®Ê¹å0³Æ½îæŽêl¾Äni“©ë]½"g°nx<õTû²¼y`]b.=Dž¸·£ÝåŠYj K/ÔݾÙÉÚšÖ†Ït¯~+Êå/{ÀŸ¹@;‚Φê]e×Z«gEÞ²(9¶ßVäzóyº¶_am$ î“: ùñrÏ9"Xö=JB’3Bs„e,w´2cþ»eU•WB¸|_bÊÑ ¯º°ôš#ä3rsÙp­rö˜¦c+;“RöéVï`Õ ±„‚ðü°[I[]Ip§¬çn5κ’êìå´k®8÷Gk17weM°‰ÄÍìpy3EoJjæ¸IÌg• ,îQöX)’¢-DzVÀŽZ&ë n‹ùÜÇ›¶¿Þ±÷:¼pí =’ŽÎòí7»Ço]QYÒ»¸Q}±É‘QÊ v¡ƒ2–N¨ðïn`]F'×÷[Þ¾Ú@ð«jU ÆẀ FÜ^ñœŽx·*‰k•׃ivª¶aõÛ½]Æ[ë­ðwã¨ÛaWô‘;é1ìW]ZHÜÚ:+³¶ÝA&îQÉ·XRŠú7W|o+§& ^ó¦Ô̧7Ë Òý/õsä®mÁ»ö*[;orôÒK dóHÅI•—$ ,H“¢þ/zi¶2§q´OäòU\¯•`y²ï=ê7›l‘R¿â}Û•Å4_~ü½¤/Õn‡rývˆ•î§G7çO­Š‡xK–ÖfÑ•ƒnÖíb:G+®î#Bè2C|ù7#‘Dìn®€è]}W€Ê\%•Ô†k7Êû{¹p;g=Í%,K:Rk5z±æöÖŠíµ£¹œìY@¾?X!Ê Ðæ¡Î9lcÌrµ ñtivÕ¶’¤â¾w*ÙJosüF»o·Dâž¡X@[K_ÇæŽüñæÌóbë ÄÕŠ:îo…Må*ı«éÍtvË¥ ®­ÁRßauÐoíÇZýÂ;zè•cÌ2®Ãê t;\HàY uÙå=|óì–ÏÙÃwjícb<§ ê&6 vCY4îå­Ï·ÚÆEQÚ΂ÚݹÕ^,ÜO:4ô›é¬ÚÙÈ#ƪdçÝ£ºGó\åó©×FKÁÖž=N—¬c·§ ¾\†œƒ¯—,!ˀ탴T˜ä¡·¼mÊXj÷…Œ·N¹4m\Üc²²ÄåF[›0ð[z…õë1dž´‚ÉD=zÊ® ÛÇ´uB¯±×>‹h\¢UÚ&Ï?»€ðçìä3@ô,ÊÀ½V·5 |Lßkz1-[3FÒWd´lmh¼¼ðè’™u{‘RÞ¼5ˆRã÷u}†àó±n‘™l_ÜЩͼ ø½JÝm>˜Žjèu<~Ž\õKÊõgJ%Œo›G.5ÅW^Ô³YÖÚ|iuÊivLùš>ÅàzÞ[|ì ±kw‡¶ÔÚÊ!&ã&*åË,Ì{t%8Ud-Ö.Ü{pn†Ý¼•+ÎNfïSoBM”¬áô{scá±Ø‹½låêÏ>Áº)K^(–4ˆËäòæ[oB5ŠÀ’=éF×Mį:íôÙ²÷‘ËB’vn»etåyyÕœã%œŒ•+N]èÔ¾ì<ÛyG²üq\¦ø{µû_ÚÚëUyÒ­X£º5,m®sלiTË  uç«—Ÿ½^WÝžà7þ/£¬ð>:ãœÜ±âÿaÙwä,_Æbµi”—‹[F…U“~:«„`P³J‡†Xîùú„™¯¨R«r%í¹Øs—wË‚•~•»wî¯6<¯3噳–ݽÇO´Mǵ4@‡?®wSxG¬t¨kæëÕM_ºáÂÛ|5¤ë•šÝUx ÚØ+s1Çh¡[ìŠìªZÙT}Þ°DvqßovVa¼¦©ñ»æµó' Àº ;á2Õ»»åÚê Ë!Î"íMM¶´²²’ƒ ;£ *¾‹yÞPþBä÷NõbnM]’óc ±LßÛ^»»>wZRuê­©GÑÛàCï[wý©È‰ðöõZ‚Jf½Å1Úv†ÓO//Ué9µ ¡µÛèi<9ì+ }õ‹C“¼ãmõ*Êäù>ÂÓâÞý3 ›¢q"ìQù#ÄAªÎ{lNŠNÎn—_5e}µ'Áëåvñúî½qEÝ0iÚ]™%Œ9Ť.Z]«v³:q|ú»4¬g"­ívÝn)v¹£Õw׊Ìj²…6«®±ãæUöÌœ^:aÕ¸ï{œyƒ’ÜÛ0÷Xóö׿=s×à[j±ò²SâÅð}|ç?{È#¶wW ï/`áéÞ}ÇsÀ"÷L÷%e;¼yÖ+YË‘è¹9ò­¯’§À<]Y:¸OÒ´Âðf=} ™¢‡Ct&¹}}Ñ:–;ì¿b£}—àmx#åíGbÕ¢R§« Ä6æ24’rJ¤Ye„.óöõŒ÷²üÀ¶((öo³|CA@tyxÃÝ—ž«¡Æníò£à5ªíÖ–bôGÜQéìÓÔ$Üð)yeÌ)S |O-çÉ]œÐ9ƒ}Bj™hý¦øæ«ÇjQî7 VÁN:BeŒSðß0Ï sz¼?;€²ðUè±B@}YW7•œ6nåséNÏpîÈ@m»›V:´S­¼<NDÙ¡×o*ík¼i&A9£Ž|ðõ‚6Œí6C•[nŠÐˆötºÊ?·u´º¶“ ¹TW)Víù}¬Ü@?y5^å6¦04`§¶ •’ìsMpJ±ÛI^tí/3Lðñ9×{vŒÞzRÊ¿ðâf¦ã{²›{g,J”»R’A3Ôz(v.±*_Yv7¸åãÚͦ9:$ð}åyº²ÉÙà<åågy¨œËª»áÒ,¶SXodwÊc5o¶aÌt¿*ÊÀùwÖø 3×KyŸ½ïNÎ%1maÁœ)®žŽ¥}ÅÓ3y÷jñŠ¡ƒlm_s6TçŠ{h<žÔM£CïO]YžcÇ*u”½qVÔ’[ºÝÑ*`»­š‚|-P³AW³I}D]Éc°¨ÐLß½ïPoÞõ ´ÆÛÈ™®bµª±ê@ øsu áCºãR‡ ½ [èxá$M^bÂÖë¦ÆÔêi»ÞrêÛÚ¾– M—V¬m=ï{÷^¬ý´RÈÁÙéý¾‡¦mi¹¦èºY “Û”®Qý;ƒy9ËÚ:à|ÆV‰YBÃêèõ’øp®˜ï“,«ëÇ'ýëþKþøêÅñüh/}¾¡_9ûø2†ýpeXÇ1Ü&flçð½•)>’ÐîL>°°ÖÓBî¶WZñF¶+¯µ>ú®‹dið·K|M¥HJ-*ÃîõνëLÒ²0r¶îys£•¹—ÓIhq[æ—–§$<ØC˜°½•vsÑ"Á{ã—zÆ­B7¾¼³¶+æR<É’r2;޶Ÿ½9)V%Ù{z­5C…N7Ô´a‰®}vÉ®£tû&Â8Þ¼è9¥ÞÎŵdœ ð‚ÌŠ×[gµ>f޼Γ·'hò*B¯‡„Ñ,=&Æ^:¢²í¿$Ú¬:ì÷ûßxßòfC£ A²¯0ˆ;x¬s®»}¾}ìõp K¶èø­Ì•â¦òù½Äiv±‘.ê;•fñôlÞûr.o_µçs®!í$šö÷J¢ÜÝæ"‹;uÌ'Ÿ…±u9# O dc³ÓFðVÛÆ‘ÃjE=j4;udö±µlQOÞä9»Æ±n½¼J¥Þy¥Ï* /ÊXóÅ‚€=;+9s{fݧ:ø±Y¯º¦ ìîíÜcK%KØKZqÄi¥JÊÃr:²Ë#µt¾®ââï­[˜kVå)³XÓ·Ã[[C’슂5=C3yv;»3ÏÞ>Ü^ܨ­.ž×®ý–ÏSÄæå3õ®œ˜BÕ{/;!”ÔÔ‚X´äßõqAìß2ˆ"ÜgÍ9§wéíüº–qöÞŒ—] Þ{VûO˜‹Ã<<¶‰¼©5“ë¦y³®›Ñ†ÑŸë]˰Š÷§²°ƒW‡/ÍWïú=^DƒQ<›½jÄš¶o^0^¯e»É¹w*éót]ï!×z½J½,aÇ„t‹srd+ÂfÔƒU Yºõ‰Î°c†÷ƒÄB/Ébú[“3Iî®Úé|^L`S€¥Nû{r°ö݉Ð^KžO‚…Œ”ó>ÒwÖ*Æù›ÀÀÊ0Önñ׺í÷tzÃÉ󺋦{»› Áf“Yo ÞàeJ›,'ؘ0 »ûý/ΟW¡Îš¨3pÔ²é)Õ˜~‹²„*æl=𲻆!6†“‚2éUŠ]@(ggR²à³‚—[/lÍÚB¡3£Š ÆK($Ê™21G³AáG?·w´RîuzkÚV©ö=žw'&Žø´iY¹6ƒ€`õ#è/F-¤Qžåj«’Y–(?KºS`±Óp¹s3Šo‘ÂtGµÒèýãb¡£¦k.‡°eÍòW2çVŠ×Üâ¥jÉ5Ʋëo Fp ¹Wrû¨5J>ÀãlúÈ¡{˜–õŒpªÙéfN—qñ¡Ï#g×G¸…Wn°žgÁRœã²œ£—ÂîSωÛäßs÷òÞøûÃ7 oí÷®ñ/Ó õ´uÎk²z¹*µwdm,ï§>í*E­Y¥™Š)@åÍ"ŽŠ¹h }%Id ìGûV‘iöMÃKü6MÝõµ<9ÆxKÜ8Þ •ô´îI•A—¤¤:CÙÜm–b®5—pÝ‹G5N_Eg›ÜV96®€ÛYJýÞs×î\0x­Ò0 E,]e’‘M]/ `»WXF»¸¸yaÞô|;oÖÄP½ŒbÁk&1w~3:ì8“uÍ£  [½Ë Þ=u‹ž§Ã%ùzüé«Úë ]- ÅÛfÎp ÔëdQ±‘2—`û´Ê93J¬¬§z»¯¥&RÆŸsÐ,NH]I6™ëéú†õx÷~°ûÆw«½&€áxtõ!ÙÞ½ö@ÔÕfX§qòšÚ's¥ŽQµs#å[Ý´z€%SYåïL\"Ï—fZŸ39ÖådÞâ¡VjЬíè³öûÏo»•A„W]Œ•Õç]ܨ$ïtóiŽÏºú ÎçLƒwn*†F‹Ô³Mj{™6íÀìo—Í» /J^¢Åå©·WnDŽÀYyÓ¥á-ÍHö%£³üÃ<¤Z.±uFTÈhW…¬³‡ÅrBºWK.V ‡×õÄ;Ö3Û¾¿\ ‹°|ñ^yšæ³ÁÉoØß«ÞO·U1b8tõæ÷]/³¼ØñR²õ)ªyÔË!p¾Ö Š×僄“M‘7KÊÞ›|+F ãWب̮0´/Qé å¿–ï,±ír‡&Lá±Yzwjo'÷dËZ6åÚÛá†ëË„S}f7 ª`ž#ìÓ¢¯9qTÙzžrÛxÑ‹aþV}¬>Ú~ Uûó;VÖ:ñM²µïåÂßãé`£íwêYÚ+Þ„ìØoµMДÈõá;ÙžtòÝ.õÕjÆZ¥fq/3ì²k‘N¡Á´SʼnÁ¦¶ÆíêÁñ>yr•YÞ‚ú-Æ«w®ŽÄã]nJ°z wªáJN»œðŒP.®¬›ZÔ¦ùžH‰îB¹®Ï²’ÕBfc¾9•…Õž>ÁÓ¥B‡pá|-îm»÷ñý§³]ulßߪÛ"²ø×åOÊVÖßžQuäW­·Ê÷ºìú]9êO¦Y±é‚ñ§Zºò0Q©V÷íáº+ƒ× ÊöÊÎRú+N[¤©¾!n£]OÅÖ7& |B»Ä;u<Ìô§øb÷õJÿ¿ ÎÄþ)=çïÁy."¿¬véç½îiϵ»ÑM¦¸å\ ¯tpî×z^íõ‡éqym=º¿BèN½—2s`&™­X·¹œ]öïPÙ€¦Ñ”oÍ4 È;›—›´‰J–Ëë5¬â*礚ë½*zôíû»¼'dîy`7›‰-NT4í®˜7¨Á;& 1ÕXW•.ÙÔn›ÔkÜCu§gŽ‹è”Ñwå~ð¡à$šuÙ»Àë±Â[Ush;Nùʼn_rܵñXúLâ6š_; Gаd¸õžGƒ™s4£K­ÂWÐ¯ÝØygùOã·ýß- úóª/Ç»¹aÚÅNwKlæi“•Nˆgt 8Õ’ÖǦp:€f¨{Xc×CÐ^~µ§ÊÞ쮀µãX´«ñ£ Ö2ñÙ©Â+Z°+kÝbÔ³«²ëÉÊÃC>>1ìºíUÁÜ^žžŸg”k´Ço”ˆå;bÂjã7ç–þöÐ{M2È]ž7™›S›v±€Œ¬ ·¡ªÙ|*Ä& Øø½«2²U³\Nöqç]ëêëyðæL†ü}}¦úŠª(sŸw¹ë¿VïgÖ£n¼­Ë>Êé]XmåëžÙ$׋̶’€ØÑ>m#ݪëXÆ>Îqìu¼ ¨íkV»³»eAÅß3AL½ç7ºŠ¢œif­lkºN°ðTᆠ໦jÝT¹a=vP¦¶3Ä'¢âMgaÐ_éÿ ÝÕ®fÕýN¿Õ…HOïí.».›Ž¢Éô¡DÀ/ÃûÔU ,î§;e¦Ù#sZ4Õaìy¹9›Âù—‹ÄÈo–Öb—˜ð6;Íèºõ°ïýPs ¬Ê:mqôÅ–h-áÁ*+Nò ”À!d %êÚÚ¹ë7ï~{FÖ¤o³ÍË>È«UØQ5,oUöÑ uWX›Ù‹‘’áOl‡ é[‘V«`K~ͧaçt$™Šö¤ ¿v/l˜°^oc-ºÇ=~õú™öï}‡Ò©ZvÕY"°ÄÇ Ìá³·‘3¶µTŸ#Yra;­ Oœ½ø|æï…-¯Z¥Eâû{ÙLð QWNJºO¤°sÑØ©Í ¹íW5?v¯a¥DÙ,ï—²aÕ륔ûΖN«<æKÀ¿ µãäW½Þüç]¤øêþ.Ƶ¾”O`ðƪÒj@+)Ù&š(Fr±[õºÐ¬;šmviÅw½ô ÙˆËx._5k)æ=J‹!¶¡}zV›ËCoFðwLXƒ„Ÿ©ÝD•,]æÕ̼iÛM®äïO:>öÇd#F h“¬•ñomYo¤¼õÞÒ¾ƒkkºË…À1¡k¼=A^8uóø÷RàÑå|yL;ÂÑú;[ißÂÒ2§³Ù½Þ/ ¸}Vœp`ìjá^±Ø!¤ûë¥Ý̽Ë<‹Áå‘FˆÇ½hðu£D×»çîöd®Yâ³Ú'•ø[®;|Úñtö·/5Œƒèò±¹Ï»·Òîj“ /¯à|nÑÀ–q,skÒï8¹ÂA¼» ÷s§×ʶx”Æ`îêÐ~ÏW„º1Í•i`à…èžÓ½>Ë o»z_¯Ü;ÞzúUF©k¬õù(0 œ)ÆôZÙÛS¶–â¾ð«@ lqÉûIÖœÕ'Š¡e;÷ªC⠫̰#ÌÐæ‹rSâöºáHsB.ïlí¾ïB8¯f'nB Lo+•;¶K­èÖ{Ïaº¼ñáÙ–-¾ìj‡^bù¾µ²†ƒ¾ï›ê¨¿l^ýZÖ÷?=jôezç6ή-4²û~=¼Ü î8Yæå1¿šnl¡"¦yX[Ô^ òT‹VŠwÖKÄrx®ÜáØ™2ñm”•J€žöTkÆxÁr½‘Ö›±=Á*Éå›K´zPté,.4§mËNñU“[­_À%ÎÆ”¦ƒk£õëòÛ}¾>µxô ³Ý<4‹Àwk¦" NëÇëÓòv=Âw­¤žt¯Í÷¸Þc³Ú?nÏ_˜tGgS¹6yØT5aŽVµ};äS•wºß ¡_Ú˜n{ÙÞZŸ{ÚxÀÍI™I6'Œöá5ƒÇ”+×Ýì]®ì%lù›ºòsÎÅMš=µÕÕ‹í8õ ôù¬n¼–¼&ÑÑáDJô= hÛ+8=“)òÍw¿ Ë£™ät¿?¼òOqÕëÂ'u~ ^<£—ÓŠù]V»#ëÁèøä³ÝÍïvó ÷³mšF$ÓÁºWWÕäðßç¾õ»ÈwdÁõæŠMü÷s:7+1û–[>ÞñÝõ[MìôX·®™VΊǙU ¯t[C¯Õ»Ê–tiù×¹—’Yk`Ñ‚›)†Íåô®ÝÕæyæG“£¾½·H¯a¯_Ú¦»‘´›¹*Aà» ³–ÁR ÑÂÓ^¤›~·}äá.ÖÏ[ž(Nõ=Ç{ÒŠ(i8G ©³»p±–uoqɑꋒnBU;x¹ÐÚ7Ýu.¯‚³î×·¥±ÑIÌ•dõœÔ\å+vÌt!Åvëz *„ÚÆ}ÚU<:dHM¶UkÞ¦^lg„}Ôž¼ä¥@ìaݱ¹ˆj€®Ðd¡eçd½<¢áW6šrЫ›V:tуtƒ©‡M£ÁÕyŠVN·¶ç\lð# XWa}Z±h)>5Ó3«–„Êw• ÓK°:;šÈ.Å#4šIR½s,~‰)s^éÖåì=&åXXwuÏ ÛP;`JCµf§B¸;[\ŠìºBú¸«½Ë¬Õ’¢ï/–{4Rõp+õHK–éï ©oܯ¹J×v–Aí×´;"Yzën*5ïWvŸ ð®ÔÍžˆLJvêÑstæâÕFÀ®øµEî ƒ©7ÜfšL &ʤòe<³+´‡OkÍyjæ²DÇ}¹çÉSìé¶…r EìÞT0ÇÙÈÙ|4oG»ÆºÏZ÷Q-gB‰f{}iÅ”¼6vç¬ívP¢Ï*^´•ù½Ö›WªýNêæÐ*ü)° Ne«²•{V^¦¢Þyg1ïp5ãaÙ’²;ê„«­{«¨»Ïe èzM¿;ëT­^U°-ù*xö˜#¡“³†ÖŠÆçbÝS.×®}ê¹ïUÞÊCàj÷äFÙòºŸÊäûØ2½4fäÚ›Pùuåµ|ùn&8†°uHJ«jÐWtÛÊ7mj¾ÏÜé¹êê'Ø9zÄ(ÐhºÝÇÐr#³7yá<ž)z+T.JÛPn:À+¦XdáD6–ê=n¯¾úðå°³½ÛÀØôiåg®5åÀÕó%Jö‹™v¼Æ˜–º•µ‰M‡–õ®NAW™nw \ñà±9m"ïŠ]a±Ã|(êîÊMÝÖQ­@ZËØ©,w\ º”åvä9¸ê*-,²çSEȉÄ~ì½¥5Žº´;Eg#0S  ”±^+©|Â{bÅ<ôóÞ ÃÕñå•ÝÊv»¶‹põc,ÍTØE„¤ØÝß\z,Å·:ô¡¹ú®¾XírMç I¼˜7q ¶öšò®ÝÌ&\£+õ{Ìö†óU"•õÁ•ÛëK±ÊaÑÊ ë×tôï·¨gz‡‚b³ºåDV±®GW I‚%BÀžô—µ5o­bÁJû·cãÔ§'R{y!³‡½GX³c¯~·ÞÏh{ÞtÒºôóöà¯u^z?W‰óÜWï ¿ }÷u+AÄ àuæ„í+[⸒%Ô¤úÍ^éT0ë×:E™Ãn6á**ÜÓT,DȇE¡>¦”rɯwRßm!µîØie³jP­>¨í´òîCi6j[r/…#s…õ;™¥¥É ´Ô¦ÀÜvı¢W@ÔB`óù; ÎÛ³»;ÉXY0å±B°!uls©ÙYG5–ù“v*ÝYW°TäQȰs±íÿµ´Lêt++ú:óýù/ïVü?~»›;<é ök³‡·‚ì]*|æÉ)q”¯¸®çÚéÍ#wjå²YÊ0S(qϧ]fxк¸ÅÈD(hó©RŒ±³®‡zó/ÕŽÄá»Ê¯qÎ8‚.ò·d`ù±,óîöüWƒ!¤µüqË+n•ÒYjÇbÚõýénñ<À}•ÆÎú6·N&Sõ·p\Ö"k¼-'K²¦Û=Jkö®á¾óoÓ¹Øá™óšgÝåãJnP!±OÖQƒnƒ<ãtíR8zÝUÁ[±iH!°­ws'Õn¾Ín4s #…ß)\gm¡eòÄãàîìÓµ´l¼©–B³}ÛÜÑù“ˆÊÊ\òÃ{5Ý ,4¨‚@ÞÞÒ{iV Q¿ñ,é»ýW_è×üO?ßç?3ñ÷ù£û€šÖ9Ï1=‰l}V½°ìÑuf†b¡©uuÇ.†Ýü^œ¡ÉÌY¾•вée7µè)¼•h{×Ñ —°Az¸í#\RjãêUÊÇž—ê~Ä#­ZØÉ†òº‡ªY~¨C/ovF×§ur·ÙS×ïbÝš·™|ò YP¼Ê\µI‘uÕ›Ý>®}œ-€³D^êã]ÁV¾kØÚNõir‚·]fó_$ÃÄœmR×Ç}ÕŽZ¸«p°î·YWM÷+tŠéŽç¢}^» „o öÝíJÅžäêIÕÒ‰ÊxØUN6'.eeùTfé‹à·ÆÝ¹/k€€åª>Ü âŠW¹ɲ}=öVåÔ^}›ÑñkinR7r‚æ³ïXÖ3n-,‚ äBžÉ¶7_=´X%>ET7Xó›…þºîÐòïs‡–Üýú½^kóî à—Qe<îQò=#ÒÈc¡õ]ö‹õ<¡¦.‘!ã‚tàÊo7ÏÌ"ºæñß™} ¡[:þ]ïx žî¤q«uG¼Vó`„ L˜ïYvnéf!kQ¤@=OÆ—@&{»>ÎС,WgÛαÌÏʽD!qëÙ£ÍúOe$‚£W@eZ.V}¾wã´b5ã3° ­…êQô)lÚËu°à·……jó ¼ DÁ’A˜{]/[µ}¼×«F¾¯SëÓïp"¼¬ÎÐM(¶®µbKÙwвhšÊ;¯”ëh]ÚÇÎzy©N=H*¹ƒ½žÝì‹J7žgxrÄÍ!§/Ë+žÝB=Ú „†/lYŒ.g¹ï`‰â+給-VA©À–7Ô©ÏÒ€ZX5Éä<5fT,úh›»’ׄ1Ìš`å~/_¸hêï]dw—yIè6+´ß;õˆ ˆ3ÙªRû2ó]2´"®\Z Ýêš3ÕÑÜØÝZëϧs­Žæ‰‡‚ºmV¬*4ÀwE–-Ôbã¼êî•߃y\Â=Évb9Ke'xð‰Çˆ–vñœÇ¢ÔúÙÌÉY³GiÜç7‰\{ ³OUzc­]Æò žc'!æ1Ê ÂØ:öÔÕ)ú© c¸™~öZÜÉK„U¬±ËÆéßïÀhíOæ9ÞJØ×£­ëH3‰—5v‹ûRæ2Èöo´«ŒC ޫΗÛ?,›ÖžÃÛí§ÍtÕÏå_ïq§Ã({ÍL­þþ[åuêàºÑL·O<=ú×nN£ë[•›¾Zö¡É>‘uKÖ´­7G„ÅO«és ”W¶™Ûé+9Ë£S0µØšôïŸygtQùÖcƒÚýS¬ÒoEïcñ§´VÒ§\—Uå’#°f¤ñŠ$mÒ°zh^‘’ž¼³,80¶FÔR÷µ~È“(¹¤l÷yc>]×ÂÅ`³²b>ù“—¨ä×k%>wp¡S¤meÇö÷£Êíë}¶®í_•­l…´¬·SËEj¦-%½dÑÎaˆ²vmXgg[LøûsÖ´Ðh>Ï^³£(Uã°¦¬wím…‚³±œ9nõó»í›$TúB(ZŽóvº'‹q^ó™)÷ÖÈgœÎíÚØ×Ò>G‡0æ.hU­Î8%uãN¥dâ8tÙ@º ]nÈê<¨>k/å¹U™›^Ák³Ém‚Õ²•uÞfrÍbe{™¸=JŸ»F¸œÝQýÒ¯/*'b°Ç|†]‡_“¶êú÷{C™}@ ÎzÚF$¦Ý»ÍÚ•–†uÕ©…ÛÙâ'z4,¬ñókrgtLewÜ.r1Sçk8ïgžS¾ÃÝÖWW€-{¼Uöòí>Jp<µÝÊÎ|) {’å= õË:¾«´´Ð'… v6½´ƒ­¯kOa þ# ÞåM~¶¸3Fx@×áXÿ ]—é+Ù~}œX9‡ÚwÛ‘˜-p2ðꬫ~ì^Å}½¾sÙêÂm£yäëhJtŒ›RŽk½háw²ôaAExÒÞPVõ6êפ¼>žùÊ”“°¢½çg“4{p 7x­¿ çŽðªØå{3yOºéfìë¹A÷[åXh) q+)öß½¿_q^Ÿ$µùBdßAÖ“|oéï{Ð ûvž¢>X¶*ïo€u_PyGÚ¶™Ãj¬5‡ hû.,çxLQž­Hò̆ïje#z¶˜º19ª¢Ooäµõ`xÙŘ{–ßc:£ÝUµ`jøØIÀ; YYƒÙÎø-ƒE5Oj²‰]ªw½ãm¡q{ãWo{«¾<Þkié.YVôÓö·EóG¤]37eû«‰kÕÙÂg©RÓ¦€ÎµÂ¹š½Ýîž­ò°§³15ÜÞ~ÌíÛ±š²'RÝ6·ž¹•+™1åݪ@¬Æ–Qô‘ûž+ÌÇpþ›—A“°¤¾-rÓ~mÛMÍ€WVÛáAs`ÞãOE‘ µIÊQ”êÖ>ƒJ*¸•šŒ·;ªçÂfó:ö'¹¥Š˜¬,æÖž«á›CúU¯Þm¨@c½yî‰jš3… {#]4^ßíOƒìŒ{{í£É‹{QÝJZîü³ËÕì¦X±±úë— ažž×€øU÷׬Ív(N„ÄÚ³\Wh@*W ^<ê8«pmôzÄì]ºþÌV» ÑÊÅà€£#ã䟪oeªGŒn±îMšP¼Y‰XˆëªeÁÌ㑺„};-¹•‹6:`&óáÝnç"{£tøíá«'YÛÊ"e­ÆÚa=}]´>ößœ§WŒ‰^*®Å£·/.yv u’žs@“§`ÞrxL+gwžkŸs‰Ê„> óÏS%a1ßš”¹^­Äøk*p­$êtñ0.¤½›§F ±R{Þ3¼×¸ÞÞòࡘ7o2D Z6PѪ"•×#X•äRƒÝ’Ñס´,0€.Z¡ôÌcAÿ/<'ÙUÚþ×ïÞöcÞþþÔ€vå¢A²wòx¥F drÚNÍŠrŽÿ‘uâ·€u+§W{ Mf»$Ib‚.Ìm¼ºWwiew@—I7Xù¦”ÅÖÕßXÅ-óíWu»|ô&Zî;Ë\ÎbDð –"÷J~ö™uå{Àk 1§Ckõa÷Töz)YêO÷ìõ{Ž`{B/:ó“Må=Ù{t†r•ÂŒª¯m=<óŠPsÄÖ=™…³²ØSVF­KWvæå¬a±+oše*Ì÷Žª÷b3jóÏ1~&Åj¡G)¥å¬öýt—_2’²‘…=}ÚוŽ_ªÑñ‰"•îû»…3æ¸Ý7tpVš•x¨¬Rùb™åº™äÞíï*S/Ú%m–.òx+ÑøgiÖ¤¾{wJÄPÎ7PRaUÝÈü‡‚^ËÒi[±j‡·=ïUİqDõxÚñŠó5Úé}n‚¨å]K…Žäw’ì¢msUÍcúñ«yyW瑾û;7QåýK({V‡¦o“j ÚJ[©O…nZ®ÊÜT±þ~ZßyšžåOGgÆÍloV$R¿_¹]¼Áñ¼8sÓ2´SQt3î¥OØ郓gYM˯^_¹.ŒI­EòczÝ1~òe„r{VoùJ¿Ê½üz³‡ïÔM PêCæè3¯qÝmÜýÎg÷ˆõÆg…³ïTËAqîÁ<¯ÏßÍ=Íó‹ºZdGa?#µ<û·ô<”BìnۃΎÃ]-TWçov!Y*Õ§Ô¬½¨‚¹ÒRLÜb´è3ª!È÷íóy¥X³å9P˜ýÙx†û³Ú:£«ö)ãÀÃZ:Tp)]% k]^K2”:‰w0ßä°°¦oÙêÞ“T´6Ù[Ú;ŒhÌñãYN™€­´îVw'Sº]ºCãìÜíôì¾×›.yåèö®ÛÀ{¦}¢…¸'¯%f&½á ‡Õì “š+×GÕÝž,´O ZX«Õ×mi«wœµÒ¬˜P¢“•»‰#0…©`Húh¯Ï?ß.Æ›ºÇí„T[Z4S¿Vˆ ì6!MŠ{eþZBæ]zQK×Jô˜7Ã;´a ‘Ë~?EvßnȦ¢2¯@¡jZ豚SZ X«Žzµ•Øñp½®·W-@Ž5E qªýbx±[Eú—ÍK «×~qŠì«}wµ¿@À,Vfѧfõ]¿¢ÈÂøÙ.ÍÙ¬?{0ZÞ›8…<©c/mú<¦`²¶òv$¦F»PF”yáÓsÝ*èø÷…Ö\¼î…{:ÐÞ=¦z¯6‰ECsÑ;áaføîlƒ Ö#˜õ•|æb,W^ Í%O¨÷>»‰Ž»ÙµV´•ãg©Ãu6£]XÓV+/M¥RÚþ+ûN¡/÷¿gìÐfçðsÌ÷3¸R;¨y¡jç§9ís«"׈ZUî´ÎÁì«É¨ýìÎhE¨%H‡=ãž´!å:º¯«0±œ¯8ÍÇZȺ”Ö¥³´¦©¶{–vŠÒAÁ»a³¿ÞT5 ÏhΈO=&g·Rœ¤O£ëž®êÜÖ«*ôÚ.yS¼eD³Í‘é^ÎL,5ÔÞqáFxx6#- <†i¥ÙYÝödPN´,åÀÖšÝ=¶Õeh$XËÍPÖ© rî6ÝíIy¸þõ¯ÑÃ^+gfOj•²õÛìe¼Ú%sV¾êÉñw¸ÕÐÚ—Î)+Í ºÁéµÉbošÖ‹ºŠñæ¬ ÎXå‹B®ë­aΩ/Êà+2-€¾³Dìõø³.ú<œêr«×(ƒÑovT«¯ o<+ñ~d^$Äê¾ëyQÝm–…okP€stg£'‹P™1BÍmj‰›hßޱ/(mGM"kçÑMÜŽvfê«%öhžJxNô†Û5¼˜DƒbCPòÎfq}ƒÞ²é1Vì{ËW½«^lVexgm¿[šú‘ÁœF(Üòê·wÇÙ Üõ‹ô(üM‰ "*ÐT…#yõ¥Ãâfƒ8¦ ƯWéWiQ¾³+…PÃu¾¦üm5ÕÍ=ruIgüxBëÃÑîxîfafÀ£~¸ÍÚºV˜@CÎK§Ô7s‹\úO…±¯ûW®ÚÎG©ìW/ÒTLÜ^dhì8CiåÞó7}Œ÷b&ÉUi®ºú±—–ê7DZUÎëйû»X¿T7ƒÓ²;«Á«Ó¸ ¼üóŒ—ûÊ—Ÿ–cV[Û•,ÕwoN;ÆH DoÂKžõÉàÊu™í=i%ïR‘7^i“*^•tî¼Ë2#áG/Bùeb 윽“jã—S6g ñB3Bj!Ùèr±—OÖk8býI,e¨ëvfÖÚÒ_¼èÓ߻ޢF@‡lðð”—†'qò7ïxy±jžå{Úè{-œ±&#AœôÙÃ! à}îQ©Â¼«Ã4s V«\—^(iî¨þÕï±>B¯Ž­°iÚZõëðÌ…G{ÐßAgÞWãæõZÓˆZõL§òUnëN½í²þQtˆdÀ£ †èò¦µV……²¢/ ú~8[Ó˜©w[¨$Ãptß:.ò‰Þ{0ýž%Ä=ǺÐX"Õ®³*¥#xÑ•wÔ.Ίg:À_‹µMUºSï)ñ1ÊÌ]xê N›Ã‡‚ÞŠÛ™-®W­€Óê…Ç5ËÊèyåB´/*Êw+&»j5ÖiÕÁÂÁ`óðoIâÏ5ÉRâ°Së©XüT¶#½WŒ[Ÿy#ãC»$ĦÝÉ6r°èï:¤‘t²;}jÍyjb•aáK‘øÖ«,æJÝÔTÍi‰…ݲM56AáxhëîYþÐüÏ}ÔR§UþÕoËÛÓ;ö ¦æ%„Eååµå9§‡w+^ß\¶™&>@6Ë"¢´¬,äµcìØî¹Þ'¼§L³Â5軞K×èME ô¯#AfÞm¡ šßqŸMµs´Pß-œ´ìWÈóî‹H¢6Ðu1Z^ŽR{Ù‘Rv)÷˜kŸ¶—¹º#´®í~‡xW©#Wl,]t¼YÞHíé‘vîÍuž¯T›Æœ¢ýS´Å‹Œ ÚòÖSœ’VÞ‘[ëEF¯GªðŒ¡Æ3z˜µµn9~@µ.Øío1wå¸h²8bۮ̢ørÍñ4œÒPÇÌGHU£ÇÒ½—ÎVÐáËe«'–WTKw¯ ðíæKFºŽÎ 1ú—+›‡º€<–ã3õÛ?ºÃ«õgž¢'bÏ{1Î iÙõ¥¼¯ }Z8g]ƒh „Òà¾vé2ÆÛö÷˦߼cãRßC“¯/´ î~g3™FÖ͆Y7‚4mnuÆf÷Üøõ J+Uò& V_*ƒ¥¢¶ç{@¨VSÁÝ…uõ,·`(Arøé¤,Ç Õ“Là¹,ïš±û:i‡›BÁÙë»Ñ¡«œ†ÖR„ëÎ{g¹­yè¡ ¦N/²uáS'}¾¿sD€¼· »ˆx÷©ø_¤ÝÍ‹»À ÙÌõÄ× …×°ÇÏ?±¼[A1?Eå×úÿ ×®ãïW4×v®|$ñyæC»C‘A¹ÜsãQšß¯³ºÏcOŠÞ[•|T&œ ¹Ké”/[o¸( ‰*:ÕÛ\+½øZº"}¯T/®EHoRG(©ÔX÷RÑWñ£ïP«¯mæÔ-Œ¸þYšXó7W š × Êcб°û 4aTÂÙ<¹’}m€-ìg¬Ö÷. NÖ%¹Ù³ÛÍõ÷´…Än‘ÎÀ¥í”Ïn+]M.u¦fEIëNe¯iZ{×ï!FÆXT¬”\w­~áÙÔëÁvAen¦ »¥©#3ÙJvýîñ§ëqúºûÑ¢3—…,69h+;¾ÏV¸ÓÛo9nž€ya&õÑXàŽcº0<«dœë5h- !Q•wWWu³¦ojôW¶w›à©à‡¨¬£ç «o}Šƒ’^áN¯M=8%w½Ü€f7¶sÞ«¨Yá š´Â9sg>Ó¨º6 ÃSmªÉsk‰!ÅM^ª­cupÏ]=!Ý”¶¦%Ù·™î±Ì U3žd‰ÊGiÃÕgy=ÙÙ¾cm5]+­Ï ÊåX·{ÝÆ½$kÈcA òWªW›Û‹6—zì€U ĵÑûVýƒo“c×çà×®ôJŠ<¹äs) Ë-éa Ëåt¨ ¼Ù±S¥.Ú׃ÅvêÕ,º‹±Ñͳ¬2#«vÚ ³(Ëä‰P#ªöÒì×zOÜëÛÑÖš|…÷¥Þ†0î­<®îîö%méÌòuéîÈ2:íT†Vq•ƒ\IÅ„ãcM/{ÃY³Ÿzö1OÕ K\’Æ»)2z†Çgw{AË£N•è¯I%0ÆÝ8>ì–OrȤlMÚE•lÑãvˆÛj¶7{´Úé #—aë¡Äýì¬Õºop^ø±æÓ»‡’-é½ðº·]—˜èöú·°AÖS+ËÕz°B¯‡º'è÷Û^´°Ä+÷¼÷Û‚áQg§~Ö+Ø=Æ¥,+(k¥Z|MVŸ>ï•Ýy+‡Š¾ezùÉC†œ›Üj­fä"ÖO+Ù¥£\,ß>ô-â÷Ös/Êó¢RŽJ‘ö÷$ôå ·YÊ"S[~)jóÙÆÝ{_åŸzš×—í»Áäæ÷TâÕ:39JTÖ˜·Y%,&^ÞËÒ” ʆ}%JYiΡÙÖä.»¹­Ù¤æåÖÒ’3¹n‚†ÞºêMK"î®Ê×YA#Û»«—Îø¬!ðƒXŽ©›ÆEYÉ9KÃW=ýaŽUhìó÷¢ÛYåæë$& ÷¤W@ù¦íÞuäý%-öÞ~ýŸ´>À?.¾ˤ“Ãu§k(;’r§_´ä~÷g¥t¨…ou­o*$o7,ýÒ/%|y¬Û .ôDÞ+q½ûϲí}zÏ+ko^AWÇD“WcíímmIB£+kª?ô¯îêT©xVÈPž.!û Ç? ®ÚᕾuôQnüûuk¯$Aó’ô0óŸ/8¾öë좫È=…›Î5Ö¸ÁŸ|Åëdé¯7—˜¶ô­«† Zƒ‡¹aa¼«Ä™…0ÌÂDÎìG’ÙÔ5Õ‘}±Ð­¢ºsÑö“–Æ+[7ViQèÎñòJz|ØŠ÷֮ǘñeZ;ö­®•åqº´ë‚Êç[3g{¼%À––a¶üíVû&Yn T®ÙW°7œ|xÍè‹_³Æ¶Õ(Ñå6VW>˜¦`ö!ÆÏaC4ûS,ufÙ”éÍ©æþñô£ŒãHû:I¹ë¯€vïÁA¬{…Vå¼®h*k=ûVv‡ÉK¦J”†Ò,õX{I¢—bøYU¤µV©½xºÐäiL™Zu“Ç}†öênè:nµ®‚±{Ù!ÔÈï3зÑáÎK•ûª +2ü%fo‚à­:²D#‡Þ÷¼pg¬îÎ}JY½Ê¡&LáÙàPÏK˜ZÓîKÜáa Dn×°b¹-ßí¬§CbÛPú¼ºíXÞ.ó‰é£˜#z-³‹jt0âU·¹\•]u ö¾ Ì%ßcõK®YuVÓÝÏX+@<ÑYÔ>á2•^™º~®¤)qŠÎnÎ f˜iß0¹õ«½¡Ïjîûþ/Ùó¦>óð«¯cjv¡‹eb¶òÌ©ƒh×íìEqDcìY*Ü R¿r#xw]•—I}½Ú }tf½uâ‡Ø/ˆ¨÷,»R°m0u ·Ø«¡ŽuŸn› vòøÎ4-õ»Ô4Ýt0€w'Nëp\ˆ•›xGy¾²qL—`]yëžMÔÛ“¬Ç6a#ì½Vƒ»OeMémƒŽY>Ì©k2VNEj=l²fšÊü¯¡±e”’ßÓW»™<’C|žX3"ÞyPfzyöîBP¢…Ú-W\j‚Rø×qîDki¾Ëë¼AÐÚTo­rPíæ©Þ€Fë¼3wFR6ºfŽ|È™ëËŽåòy¨b$n¥ëÇPÂ89X÷e›[Ãç¼VX 3¼»·ŽÔ˜Åι°ÓŠc½=O–f…ÕÝ v’–FÁðöz.®ðíyË¡Ë7“C¯"ׯ/½ê|…ó³G’ñæLs¨kÖÚ¿ ¨N¥Ûˆ-4èP©GG¥¦<7¶‹Ýóôó‚×fv¼1Tñݶ 5ë*g‡½tÝp½Q°óJ­WWeÍõí2} ÷½¹÷c•ö†o§št/{[ßx¹þ=S)ƒµÝ×–ïuSóòîP(O§+6+¢j'Ço· –êv‚¯å×uÔå2·Nœi¤òíè '¡3ú^÷—¨¿iMùz•—¶—/mZº÷¨Ý* Ä7%ÔÍ/²“¥¦ê¾Zš¤ŒaÙ£Š­¨òF«¸K,ݾë;ÔIÎ;TÈǹ¸MT’­½P¤èÊL×yNÞâLäzÞ: |†ëºú¬‡hÛ˜aϧú•¬‰í‚Ï]·„ªVNàï!ŒÞ⃠²¢½¤{ÃiH-Ú¶ýêÅBûÝ~«Î÷ÎB§žÄÍÄí\­ ~À]íŠïg¯´QÞ/(÷*K<4e²/Õ×IÉ~__$Ã<¦kË…óë}Ó’o¦áÞ ; å€p‘E:%m®M­$dqí3¸ÍÜnsæd‚³2™…ÎÅòêt=é¦fõí²ŽfN=î#»{Û•¾„uy{Ùs– k‹Û`½Ù´;:].RL}:eñ¢q¹š Æêü½çX,¼÷´Äè^£$e·»[¸m‹2Q ¾¥êY•´˦@ë’žH¶h2֮ͶSÁHV«¿bWâ:.Üz<Õ10±…/ŽéYžP`6m`ÌË’²—JŒVM¨HŸãíóµ‚ÐçÙé4™3YM͸¡·œ7š,xpÚWÙI¹cVådé(i`1-“V†uiWϧPêºÚ½\ìH$Ý]£™žYüï|/©W*´îê0šùײíf x„ò‡[£ zÄÊó0}4ªÒ{N>ûÎÐ0Z–+Òë½·}qÓ¤óžW¼<®mÕ§™W7‰Eyç`‰u¥Zs}^¸P—X»)$è’° >•lV]jõ„p׎»Â¯%xÌË‡çŠæØLý·IHÓè%õŠï†6)5Öõn…¸Ç/¥òÔ³DðîEFÛX†â­#–]b›)ë}]CFîòˉº‡Ivˆ/4< ·ÙR±+á #M|§ÇiÝ­%é:Ö.–¨œtfn†WÝ]ïg.8æ%¶~Ž=B¥xöˆsÝžÝxˆ^¡­õ1îÌaëʵ¹AËi‡uÙ’ê Ú¼Ñ]Ì"‡fß;rx×[%½+•ÞÓs3ô Sc;DòÚ… ‰`YY„Ò£û9¾{jßAš'½­2æù'¼ÇO¦0eä†dÑ´%§¢ÈOiÀ!úÇÅ5 – NæãÄù¬s4¼;G0k@u‘¢Ã ´î¨¾Vo(¿ºC¼úúu½“”85U’ÔŒ)½Ž`„vUp¸Ü—±Ž^ÅÕï/7Ó91`]ú’°léëËçM©Üoì¢^Ê{QEŸ{¼<ËõÚfל¢_w†ëFx1yÉ?~ì];÷? ´+toMÂ2ìç¤zòêHC»ÌãmðÁÇ2÷¦žÃ¦áÎ …Zš¹|‹S¿OtHÜ÷²ÐÞ]Û²îæl6¯Þò™+(õsä*ÐØ+×]oŒß]uªõe;2ØÜë«“4Dd™…ºžðtK5FQ5͹XëÁ¿Pi‡¦­¹j§½8öíû€u«Ï×LL>¬–¤ÞÉÙçìWhônA÷›ÂÙ=›E·Ö)rôìÊiÅÀ`BÓžw+W¼ú¦yJåXlÈ w$ŠÛ| “i”]'Ã-åÒÒî¥#*ž%³–R®¸Ñ–6ºðVp•¬›g›ºS½±ŠBú[îײïטJÏ¡åêðížë^Ô­{ êk“®vüƒ~ö(¼+Àç§–ÖÒ+~õûD©aI^GD§ÛÛ Ÿ Èr÷^´q–ð BçVW'yahkw•;”« ]1׫޳»v–€Ñã4À8Ut7:ÙvºMÍí itØ„­çÎNyÉêÎô¶bY÷Okì­è™©DeîèH‹uf+iE%önÃ’ãæ˜![t÷il®=µ”+Çb[ÙÖªÆ*°}+{0RÕd8Êìšýç\+><ÇS¦®sžJ÷z¢¤rZãË»µWq(Í –;o¾@èébøëUÔœì9àò¥¢ÝÓ£ŽÁÒÂ9¯±›Þ WÂ(«FØÞÜè´ïƒ›ŠËó—äÕIš·¤xš“sMygRWžêÊã”pä«EšY;l‚ã;f/µaW4ìè–[EȺ\Y9¨5[¤tnl’]H›öÒ×¾¾ëÜ×¢ ‘ û6B²Kf=ÅÌï¾ûïö÷Ô²­ EyÑ®¯TçÙî¡f×韺ß]èdQö vâ}&¬È¼3Ìýî9²œÙêÅÃ,z‰ªëð쾿† 1!÷u/fáícܨk˧=¦bÃ9£Œ÷/Z›êÇyWY¤¾*gMÞWÌJLЄqƒ/T-_Ü”‹tž£ÖÑ/$­îÌî¦ï\Éñ¼¤‹®®2êW tFe§®Ž§žíaÚ¹:, ºj‚óDÍL A¤r˜ÌÓMA “ÉG7)h;@_u‘føW:=¾ŽÅ–ûlq£Aá]uP»ŒÝÚ;ŸN»q5‚‚ã¾Jo"ÒÎôíø»]»Ö{Ò—Fñ2³W?aYïà7ËÚ=/Oºûº¼âÓy„¿kìŽgK–y3ºÕ_±5§ ¶e£mˆçµÌ¬å\ó³{Eob´# °Õ³ŸÍaû=u¸—Nã¨rf]#Ý£ÏlõgPöæT £p;Z½Q„rÌOäÎÝb¡¬#®&g¤]îõlžžmy|ÕZÑ‚ö¾UëW®úÚ‹ÕV„ŽÑ+·E¯rËW­«½ê fô¥NÙì&1ŽzÝ)…rØ…ÁÆ´ÞK’aÅ \nÀåÉ^ŒC\}w¼œcéÝØúŽTâYà7b9Ì{¤¬ßn{ãqiÖ÷ƒîëóöó·ÉsW8í@ÝÕ•ØÇ,ÐiÂ…k—”òƒz–ô¿·Ç{ÝÀW¸<ð3&ŸR•ågÃ|M´­úˆ¢¶…î6º’A¯SeE•§)vÚ‹¯q·ÜŽÝò˜oÝÜB*PÖ•ùg¸fä|¢¶z°n³t\¢©å'4µÀÓ—½’õ½´ðIO ÃÔ£™®^ë¾ÐV"o>ßvïUý×êmó¢4<´ÓÞš"êjÑV(Öï*„Drà­ökC»*Fz4öeÚÄ%¡®´¦éO†Ê˵”©ã¹gÙ×Ài¾œØÞLq‡5Ýc·IÓPІ׆[çÓ¡ :g‡ÐT+;_yÞŠjë3×x"[t+jê•!¡ÔYÔ¸§-Íu*xå=Æð«• á/¹1,f ÉÓ";¼Þ¼±’Mƒ‡Ü‡×8«C1˜\´OAGr˵¡7uWZT¸…¤Š cÎúv.¦Á¼¡ÍW3Ùvô ó 84u‡5ý¼x_SöZ±/2ÂS¦užCÓÃÞïz9~ð]4{ÞîÛÁÏzŒ™¹–³¶*¹iÎgÛSɧÛG¯˜ß=]ƒ¸c‰ÕÖ:[Ég˜¯Nb÷Ì;7.c×jØóí¬ÜóÄî‘Mà€í®ôÚ±ÒÛTðìë°çñe°&—3e„_ åhÌj繿>F_B0#[…VvW)XKbÉ?mˆ¬4¼.‰EXyËZ%įb >™×µo =•ÑÇ®ôÍ&†×B…ÚŽ‘ ›Éؽ6öêrvÉ~ÉZ_y6Åî̯JºÃ6¬ûìC#›Ë[•°‡™Hs"€ê„Ú¡’1Àe¼.‰ãâ“›¬i9åw»²_ÓËxÖŸ <5}='PÏ,]¶l市ç}g–vE‹]„Œ¼Çí§^¾xbolÍõb¿:gy¸è6PËೞÃÛGzN¿Ïs»Ñ]ŠóË2Õ¹N) àxÈ'C¢Âpœ«µ®és.ÂÚíÇ '0 K"§±Þìµ{:V”U|/…ž49,G`QÒ7)] ŠeÕóࣅênæcVðvDܰFj<<ËjÞó§Ô<º×\Ìkë݇WÝìÚ~rgs¬óÄž(Ûc`­“ÆÊ\›³s³ ĽØÏ ·´kžµå™b=æ«Ï¯3X’S;M¢w½J§9<ô>F(G¶?sQ]˼´±l@¶’}>‹^në'-å"åä– î·Œ¯‡ÏÈWm·¸±+­ÕFõ¼ë;@©tn›¦ ½«¨iá+0sÁž9ŒÊ»=ÜûyS5ÛÄš*qM¾|èKÉ,ê· ëÖ‰+zÏ»LëóÉìòÄöÞ,ÝÅ·¸£w@ ŸNÑ®\\iˆ•jרhvÉc£*›Ã¶v¸¼ H;ÈÂÁEŠ•¡Wc”VÌi†»³ÞUâUÖM9^Ýì'«v€wß …°f\hvº·¶¦ÆGq*ïÓÜóeuaõú{ÇœLX«ìÒ+¶â v2Û¶X«×[5s¹ðÇKºûhrܧÈœsŠíñ{êÝ37ì7:V³œÑ™o¶£Q»˜í5ÛÅKD/(¤Z¸ëÅÛìõû}³óŽå¬ñ¸à‡¸B¡/JK3glÅ>ðÜ—Àh[yÙ^|ÞòÎb³½ï*ëòû¹z„ƒ9gœÝÊXÚEóOkp]ÉYÖÝ+0ä0v‡O*à˜éqJÜcs:g&¨×û²¶u*Iây ¾87hˆXÉÙeœPâæåîL¹1-/lIrÆg=ºÉÜ7«…2ŸÊÝöÈ”æü7;½®2zLÈÑËÉáJLͺ°Õj£uÏ­Þze]]âxaÖæÎKDÌ÷© ëÞlh{<‚Þ½`‹Ù†ô€N­|øJZŒÃ½'wZ›(ó°‰óhùîâÏOiQz=™Ì%˜ÇÛ•×ÖfÒ´v ½ ™W5ÝÝ0SYi 6pè»¶uÔ¡a-¸¶œ¹HnÊæ#W @]ÖV&«C•æé[xëŠòP4Î/­¼|r^0VR­¾\8Èqo…)%ÈE¡¦TÔ2ùM@«tJÊ.[ŽC›YÞQU½·+AG:Ý, Í Þ¢‚ë)e’PsO¶ˆ¹Q^[Õj°dIÕèFÐJ ÍWhR·§*JŽÑ´vÄHXQmi¡FšAÁ´‚“+Fåå´# K/Y¦=’‹W‚jX|±†òµ»xÏW¥×§»uÖ÷«Ï‡L9êØ»0Jh´ÍøóºÈnùÛ×6¬MÌ׆”vtM.m”•Dë³³®—ufäùI½a-Ü .:7%J퀕ƒvéYèÎÔÜMr(ÌìÑnæœ9J–ß¶ Tê|«HÃoËÚ÷0¾}ɉWÕ}æSÄ$ìȪ×4`©·z¢ækÊÑ•Í žÞºÑ¶ž¾`{yµorš‘«XÑXç™r˜·åWÙêv’qÑöú­zÅç,P‹.¡%½Ë1š¸:qƒŒÍ§o G%ÕÃÕ{ÃNðkí“›>rÁÕ‘gªÛ«Ï^+¤~:†Òu´×{‹ôô¡"öç·ºd\¾ÚU.Û®Þºƒ°TÌt‰1µ3¯º•Bø^˜&©ÇŽôðßWºE ;W¾MEâ85Zei5GOÉ&©ç{9¥«ûïÓØ?!á–UÙõלüï®Ó‡È¥·HåÐâ nu³´ Âà=w3_s* sªKª9¼F~>‚yŸR"öËÍö*“*̤ŽûGïP[ÎnõÈG—¸‘»Ì@é»[¢£Þ¸íˆ îœᯯÏf!UžìSݯbZÞ”RÎ Vi0p½‹®Õò‰,’ ÝÍ$p˜:£:hf¯s©Ü¼s4¤«ê#±d$ ›‰^f5˜ÕõŽ 6­1Z¯nS©7:¬)¼ytä•M9tæƒÆPÐs6@oq¥˜ ÷‡Ýut+åHù/Îôz:>üWzžLj3›Révqw¼t­Íjò®ÛÊ>tmÒƒy³¦¼°áÊÇã1öªµÔ~àO<ÎCÜžKµ{Í‹…B™ä\«ì§VXG ¢×YÏ6†Ëç; %^ô¢R7Y+5IÍ7ö˱AÙ6”¬$hë]N†cU€8<2œÌôÛ½f¼É¿=£‰GçµyWd½¨è¶f_qZ°1yx•lì¸)óƒ“…ÃÆ-–¬&öšº¶œ¬„f€î€²_fõ¾, æ+°ä£nrzägÜ÷Ù^Ê>Û]X)Jöa‘Ї›¼qÔX[± +¶ƒ™‡Ý5ë6—/ºx&}[o2¤-X§¸{p®á£‚a3¶Ä•§)–ž±¡`QÓ©]ˆ÷‚X5^÷®@ë<“î¯mººYoÔš¯/=í.³!Ý2ßZˆò=ÛWxÆ‘KÀ›¿HÞç«ßx->¶^4'x#zÃç‹+¾Àh;™÷)Ïl‡€æ\´¨sã‰Ób¹^¦µjo‘‚4q< D–ž±Z@ÊÚšŽï!ª“¤ÙWSçi]”ï2éÊÌKp¡ÃÖ*y'Ö!Ù’²_±«Å^òÆ ˜9…ç·ª¼¢¿ÞÇûβŸ»Øèæ`ªÛ2kéu)¸õpu;˜ÝÒíUΔÆß.ÍÑc´Þ›á†%4Ó÷oÆ”ê5—Ü×Ùe»¶Â/{­*87Ð<Ê…TW÷i DäWRœµ¨î¾œòà:õh*]R%ö°od%)Emü+¶ÍXyŒNœq4Ï[þÛÐð×WxXƒR«³Ñ¶™Åã6~©×åÓ/_º¯ïr¼³ÛÆåt\ ÁV^ž9•ê÷GÊùl~Å^X(PغÎcd܆”.ì6ûÙ^ßR2´K' ¸³Ö=~ïN£X$RaÕÖkvpzëÔ~7îQ)“6÷SË­zSëÃÔï™–©\ÚÑ ræÖ€^1Š.ę̂ùæ¿™ÉB±X6 „] Î{è’ö +F^á^ΦúÅW@&ÍÓîd&uó÷š¬ÎºðDÙêWÊdzmß±bíP 27ùmDzýÞ(¼–šÔwNê4ØÞY2„§pòÆ-táèë®í&ríÉH­ î’ÒíXW7W6ºÚ<9QV¬ã״ѬNvÀ«s´»´£s¶£ƒk+O¦'‹2¡œ!YÞÞÃÛ¤~>ï9ûÞ®žB×g•…t24xá&“ ÷¯¬„oNîöz¼>êPà@Þxd@û0Ø{r#4ìs˜B5p*¾šjB†«:¯{»Òxù_g{¡ž º³®œò¥Ú 7Æ07!ööý£šè…l&Çn̾î7»JmMŸ"ÞÙåÙ„Rj«œMëK(Í—Z¯a²,Û‘RÍÁãoÛÅ ë°…b]Óõ ¦kSëˬá©gÌGg™De¯tóöõ× ®^¾³OLÝ:vÅÈÕ»¶CÎ7¬ÒëKè)Þ¾ÛV¢¼j½ÇK»¡;¡P¤à¿‰¾:¤1ë½ä/³W•zC6ò{œ±<vc²‡hîrÔu…ÒQ^Ýó™0PÊ:_Y‹†MEt:òµ­ªw-y:vÓ=Éà貞³Á¥¬Š®°<èôš\©”6…^BýãDYˆ¾°1ö°ì½õoq;U¦…ÝÐwx¤Àï/ r»s•‡Ii“å|“bíÒÐ~òq­×‡£ËUŠÒv׸À2á5‘n'nºz,Aû»ÚNëUaPc'ºC}0Õó¤nn)nÍØVéFh[JdO05’Íêóëq˜H¤øg±V ¿[ãxƒ¦ú–³¡‹œÒëîy;o´œ›Ëi- xΧ>–nÝr‡wƒ©[›y<×37@×§ŒA£.§ÞT3¥»óè`ïzz.ÎIšEºw„ Y$zÝ'Ù£‘–)œ„eè\"{[…Î¥‚ßiÛ8ïS f<¾¢£:æ3M¾ÔʲQÊÇMhų’ås&Û‚é(1›ïfï±Tj·‰¥PåÒoÔâ‡fP}½k-Ê Õ*Ö1Âðâí[ÕûböçMå#ÅçËõs»»Æ(O¬©~¾WR™ôáš²ÞÝA;™GÞòãV*x—Šsݶöo1½‘r§Qôm BøUÑäÊm,X¹AGŒZ^ìûWnu èE«‹Ë,ðcDrt˜òëõ_y.ÕžK^Ä^En\Þgw [×±µåÂÎ5 hËg!¸Ð¥h^âBG)\HÊmsþ ô­Ù‡e³]Ù/J°ö€qJv{n4ÇÓ˜Žk­¥%+ÇÖLjtq–„}zñ‘uÏKÓÌ.Â>BõV÷MÞ0;6ijî÷ÚûÒû;kÖ¨k*cP¡{Nnh´°wBû³º”Ôº—B%b7+"}yˆ:`*²óµVóåžÇ4vrÀ‚4¡z®ž¼„‘h†€é×PX~ĉ¯¡ÓnRÖp:õ¼6v“å¢ßœí¬ÀMc]ð.ë‹×¨Ž¢sGfòF&ͨ÷ž1¹bë­`EÊÜTY©§^å[µñv 7ïsÒ5ï ¸ëJRì“…‘ß³÷o¢ËåÇ1·Ö`–'…âK*Õ –p'·uÌêì˾“X‹+-Î߸«¢°Þ¥ ´^ÇSEÕµÒ¯ƒ¹›}Èê"~íó¿]÷f‚©‚‹êa§ãñçÀ8ñ?¥Ò}®vIªíÏyˆÂk˜Ì„¡²ó«µ®çÛhú¥ÃJfAvtºáPôÀ*ì"û¬êƒ)¸ºu;=wÝð†IÐÝG 3l]Æû§À>[ÛÒõ‰„ áVòÞÛû‡>½š+¦r[6æõæ ±ÛV.ËBd±‰!€9ÉXõûïgº™yG8»} ®e4ï:Ò·VÅï,ÀÀ|R‡œX¼ª]<• ÷Ã/.Ï…å^¤êÚ ÷*Ò8OKzñ©Ân{ß=ð]µ{ê^ž~Þãe˜MÅ~¼öe ë³qœ¬÷­ò´/¥Œ«¯›]Œm†‘­úrÜž;6Xf*iÎSƒ.(WI\¡ìuw½£nêÔêbÓ½ÂÌ Žž‹UµÚp7K7YKÁ§œîexu\Ý~f4˜=u9ôŠ µð‘kÕÐ.qiì¡ Ê ›Úù“¼‘ç«Ìk¶ëpåÜtPN›M[†Ï6’Êå»hMidŠŸ^‡òãùØÊïf_¥GÝJý–î)yc[Ô x׳ÉwmI—X”|í >ïWŽŸSasX‘ÑKÏ\žÊõÛ­c³ÛN·p>l:ÕÖI´(Û(ó™|ûw|TMyí&õžùÔ{]2¥›k´¸Àu~©z0•;>’Eäwo£Õ^^cX7{fEêšµ•bxßu¤¶ÃÌB®’úöÏëMïfÕo?©5YùßÁÑâö Ù4ˆª5_dÃ4’©a¬Ó Ð]ö¢ÆBVÌQäÍD¼çp§×Wc»¶iQØ L﵌Rrø¶;áFåoµçröe[L¦Dhy«°±ð}—}Ó&t:œ°.RëçNù³œù:ÒÇÿ·û÷UM«\®«ûÔjPªïáå7/GÆÒ­á˜ÿ•ìï¨Vqð<˜¤3ë/ëÚää6röºJ Üo3\Ã~‹ Û„ìw8zÖÖ÷¬YèM«…ð´Xê¹¾1T±’m.®²ÏÒSÖÜdÂ×ÖDŽ\£ºüCº>íË׬^\dÔUuã›Gƒ5s¸­ÇƒVÈmºõš²ùØß°LÏrmy}eåãå¶çuG€×-®¾à5Ð0Ry…½·¸(5S¥'·‹U+ðB­Vs¯­›¹Œ tÏej,a¢)Bƒ×{,m1]ÖvþÝbkÆ}î£ë·,j:½‡¦Ô+Jç–ËÍ â6g‹’¥Â‘3G-ºß­–²5ᦽ* nƳ ëã–G¤÷vàô÷¼gsëÿõyU… 7W³Þ+ªqŸ1Œöï5[7Hwøâ·VνöšCÛC`€¦úácì”p1Rºy{èŽ~‹Ô³€îÎBÀ˜ôîvo0iìz;«¹«û¢?v›}ZþÎZ«Æ£»YkÆåõ4/JtîzTR—ØQ¾×«5Ùxn ÷•!<ó 6ùß*Õ|Ç5ðÊ2 àõµó‹_©Ð˜“ï:ú "ÂOw<§¢ÓHÇÇ/;V¢[Ú݆¯R÷×SÅ›Õ${kîNôi›GŸŽžáïl×[ë¿tC®Åx˧ðÉÅçježKvSxL3%‚Y} èi¦U èµc2¥Š›¸§_@ÆãK%†÷ª]ƒ8J³%ÔÜÿz¡Wò’ï>§ê7n•/Õ d¿¶î-ØÐOù)PähÍAlĪð¯àè§ŠÃjAC{·]reWÐÑdÛØù:x×o^éÇîURù½|ˆ2´šÌ¸ë­”Dá‡m[ïMõĸMºð Fjö:ßÑG˜ÄÏlÌáI3d$ ÂþÀoÞí½“-1è–¿¶iøG¡£SÈXxwʺ°yQ;½Ã)¼ öh¤æüåéÝOÝO¬×eîãëÎμd¯3‰CªñÊFÂz ­9Û•.sc¶®;®2ÅÓ°0R¸(;,¥~u=ÃÞ1¾´AQvScί å¡e—]Ù¶ÈÙiÌxpÙ¹Òî=ùiÑÕaÖ”ô ?¨~¾ý¾R¼ÊÇ‹öþz{o6`Ñ wc¸¼l±&¢xºqÙqâX(Nk«žeºg…pÖ[@;Ðw²ˆ¨’¢Þ›ŠÌTøõõ7£˜yZûBI!Vƈr:7ˆîœ[Za1®îÀ‡r+4Fš× fï®Ö4UÒþ4y7µK{¼kÎÂÞÂÕj'K~G=(Rö"³WD%$ïa.ÏJÆ÷§‡²@_GÞyš7g½Œ»ÍJS­«‰3@åå¬QÑYl {l”LìE)Ù«)È·›*<~éè¥ìÏrÍ5 ysQñÎ{1Éñ“Íj‚®¼6˜Ù•¬‰u€°û±VÁy‘:à{Ahuð­·T¾'§­¼™ÄÐçº×¥–[7ç›*å [ÍÞ,rû˜ÊÐS‰PŽƒ[Û›¤µ£Ø¨Vtà0ß4!R¢‘Œ¾Ðõã §¼«+Ó½¯ÓwÞsr׋P/)xsLð~º5ìÚΘÜ÷šÉâùI^‚ŠêçDì•!>îõ·ðì÷;ã|Æ‹´æ+@ÌWÀ ú¡/ Ø3­Ç®ƒÜ±}Ý”T'–íxûÝè¶ëhÒxÌS(Š­ƒ.Ñឤ•»^Zfptì7}“ßlM;ö»).?xÎÿeêñ?]~wùþàW)?fùÞËêYeË–Ü¢Œç× (–ö5]½|¨»Öª 9~Ú !Qô¥BWlÇw¶Í韎ÃX¼‰'°š%3¼£Tl5„o>Ú•—XðÎéóÔžbòôìTÉ6ßSóÄZ[]mzž7j¢éÝ3·qí»›¸îœV«€C]çRÚ¹ô9D·ÀZù;ÙÔgCvºû»(÷fZUuÜñn•²­|k‹¸Á†¯çÏ&˜q9N;Pì“ •”Ùî¾”¢‹ÀõÞ÷x/ê cöI½gO½M§6 ½^ºËá€>×R½îo1Ô®l`Ž> »×6úü­³¢’}Ü­ÒÝHÄøöõ‡­àÞ›JmWQÔ±Е¾b—¯cÄï®óÛ5fl”¤N²—ê_}¹Ð5ðZÿV÷²>Õ)¤š¶r Zººz¥¢ϸ•¬ÇÔÆ%01<Õ¦®Vúef‹ûÍò$Õ ¹VS*MeTÛP½§“I}Ytààå©hAîó]¼Ä£ê¶`{·í= .Y²`xÅna©Ø4'!©õwfð±i×6ª=U¸ïÅm›0jÙXz½nñ?b¡aIÞð “@ðQ‚aìñ¿ ´íŽõªë \¥}Ý»néSÈ SU·{ŒæiË&Ü·¡v´ÎÒ¤I—–ç7»-J™Zsu³ñ|z³x™*ë8¤ÞãÁn†A.ìÛçK¥¯Ö:·Áqî÷YÉJ×VÇo„¥3©oÝ«Úí\}SÇÐl"yi ëõ?Âáä·ÆŠã—Ì­Ìúý”Ì”vÏ-íþU!~2çzTÜrñ„µ´'t‹ºOÛ½©Áu ë8ëjà 4BF_SÚFjY9¬¾¸G€r;WŒÏmzyÏeìÎå ÃĽÛ×ç ¬c±îÅmf®Kåãˆù±½#$‰’¶¹N¬Zð)f €º¾°²®(îc¾-ôê-Æ2œ‹áAmqU¶î x;ƒ•q¾¤‹»HãцWU…ÝÑò{yÙ}mGÑÙ¬Õ)D+JÐöï˜Ýw€šÔŸ-rìô§Pê–y'(׊­6ç°Ûð•ëiOôükö°ç#Û+%ho±©]Ï%œº5#afÔØø<ˆ.ë()w¬†ÎÅͬ¾3¢N•um¨ 7¸ˆ«‹¨#Pè®ÜçMà·½”Sî!í=VñK×8 k¢]vÝ_d®s)þ'×2·±y¡rŒj+hœ§èŠgBޛ䒼­ÁyÝg¦¦ÝXé)bRîñÄ ·JDÞßC{b0TCMž4S»[§<å-†zË×9nh#_qT]1kÛåêóKs»ÎÎd!3h*USHxL;hò»å…Ñæ]6ï%dœ«Ü·¡ÝeWz϶ÔöæÕm9Œì€n1Ý*ûc&¢£OnS™½¢®Vú‹‰}ƒØ(ñ÷éÏ6½æUîÄ“®RðO@/)_ìMA~?¿y#îõËÖpŸÙxµbÑÕÅMx³åR²²JÁëQaàT7ìôå»Ú¼×‡¼P¾¶9.>…›Ï°½»Fv¾p˜jdzí Êï^óU-_¶¸z¥C GLJ§Né™Ol ‰;N6]öNìÙ¯<¿,êU+tÝ‹É!Ä|Õ,s]ç`ém†ÓƒÞÙXk7§õƒd»PW=B狎þ8ÌÜ’„nPÀÙº{å×»ô¾Ìzz,ŠndWÑIjX›‘ˆ½¤lîWšIöÍm˯`ô éâúÞxflïnúÕo 9gç°. Ô³E¥– WaÎuË݋׳ÂXœj¼_<îç :pž¬•gÝ2¹WF+š£âñtʼ÷ù?Q¶·ê5àg—hö7’\¨,ÓËà†–Öa¬fëÁnk´òTh¥WqÐA”²ÅúÛóÝìl˜ú·5­¡S6™f¥oš¶.l+S¦4Õ-›L\Š5Ý‘—UÛ×Ä`—c¥`ÕÙŠÇjùÈâBÞø¡›ž,‰ëC3R ­¼£°wêΨ»oÚêêÝùç˜úJ£Á½¨r“Ìe,Ý!•Íðε[5Ì"1Ÿ³¦bÔ6{ÓÖ'`=„ KF÷·mÝ–6êGS… ?{i¼^Oš\=:ç¼²/X2{ÍzÚq•€{Í\Ö…Üòº¾ Ḙ̈r­àQÅ•—êPÔšÏú¬ {Ü <ÌÅ™[µn÷ÚǬ¦ÆóT¯n•Ju( ólÅjëQK‡_&æ‘W¼Ö=Õ{nqß,«#Ëפ–xÏk2ëÍyìUyÆÃn€Ks®Ñ¬ÕLŸh½ètš™8Å ê[<ÒÆåeÔ@åñiå¤NÊÚôõûböà"R'—ÇBž=~^T¼}{vîó³vÜNÔYC@CãE"édV3ð¾}r…ó;Mfð—ÔV³»z«—.ãKDî[žöy")±è­C:K\ªõ+ïtÅÝ솔ò~4~ ÑGÓß_†=rüFåÁݘk¦öÞIp¡ÒÃAr,“vµ}²ð™wÒ£é½+«+³âÏb*ã¾o<1{'ŽS6ëDÜÁﯶ½§¾Åέ=7(Ö©‘¯ø<ò”\7š¯Î/NïÍ<Ù:º¯v=·jsÅÇ ØûËÞ÷nëéÃ2º¸#î|!vDò¨QøŒÑˆlêËŽÅn§éà·SÆ4r³(æîâ!âêã†å;Ä)¯ ­ò©Šègbº"ÓÜzéŒp"™0gÚŽ'ˆ jü}Þˆñ>V}Žé<÷¦Ûäö à],T íãbëaŠº»‘Êè¼[;yÀm±ï<‹oò¾*z¯A6cŽa ˜§ÞÇÌy³ÆaÐýõl¡¢Óµëiû7{FWxº>kžÃÝ0´(xîÎcœ.úmõgJâ-ûŒDgëòøº.7'Žý¬²¼ýÖÇŽl¿{°w½=(xÕ§Ew ½áÉ]w™,é­Ê€ë ºÜ^Õmij­1×Ó™’xœê%¶_-¬ç|á T&ÁÉ#VV¬Û3¬Q§ÛÁj{ö¿^ä~f‘±ÞÔwRvÆí.OuD™Þ¬ì«XsÐ,0K¼@ô.Éã{÷eó¥Ñ}Ê1µjùR7œ{ƒ‡(?›Q„òÕÑ–¶´®¥Ü¢P¬ (”›Ía詇Ð^RQÎJÙÅ-ìgÃ,Ô7-üKѵÉb]ÙÇ(ÉÆeóV]Bxú½K»Ôh ‰ºT¸íÛCÊ÷r».M‘htîC.*âÕuìÏO²Òzgyç'@7w“´I> ¯Ô›ë»D'Lß×¹»øßcè æÏ‘ã‡µ+dzôj¬íhZÓªÑßô®Íë+ÙêuŽ'Z1áoS¶žá–GDA~rûvJݺn@ªy÷bû×ÄX“kG¦:+€ÑP¶«Ò“eÒÚ›Ñêž¾,3t·,á ­Måm¹«¿: Rî'¹Ü¸ŸP®Ž•“MïWC¡ÍFhìøéêjûãÌ)%™_‘YÜ=]p{Ðãå¾q2*b·2»UuØ+§i‹k£ì §òÞ¨®ÑñéWq{ηÔ>¾ÕzÞÜ‚5ì= êÒèŒ>ò"_.¸óìBæxÓ§ëÉÙDðøÃÈ kŸ^ÖϬDz {ßxÏ?)Ï(GÙ‡='k¡–ÑîD\ÅÍQÅ!}R²›­iMmn-}Rmië¬÷=Ì•&“ÉÄè}ƒYÍøÅá¡ÊÀ:!ÔÝx*šž n…n+·Ã—Þä}åO2% €Ì²šêÕ»¢ö{Ït]^ÎòWo”ÚÚ×´4V–2%>Ú^'Wg/ß¹ü4½ú ÍaiúÀižýì©G×ïî:+Å`Ð2áëi)Ô…ò›R «Ó(KYÊF—ÑM“Ф‘܇åor;Ñu2´pµÕÕSìv5 é"ö»žÔaÖ‚£»¾Æ¾½­{ÁÒ5qì>A‘·—dWV>vúû¤öí:9^; 9_ÚØGÜ0ÖfóJaÂè­nâ—Y,Ì¡Q¥Ø*9€«›ÖbžBà¸í~ Þ­òt:Þ ¬bì¢qLï¸Ä¼ì5Ç©Yíù ÝYrñ¶1>fr– Ñ™Õ×¼:í;«÷—‚Yêã çÕŽóNqšUïµój¯d“ƒ²¶UÛPEeG’5a Ösleõ=göÞÑ~ý÷=êu6ŸëД¯5/ x´)žwwŒ¾ºû7¤;{/>Åqq¦÷iòºÀ0qÙËçOÊF4‚}¾¥ì72„‹X;jkê¼ê¿Þ¾{ÑwL«ÈÛø4 ¿PaÞå§‚ˆr€ßNŽ…Á;8 ©íÊØ8?r =Ì^Œ)ñ­X·ãçÂþììvm3ðydk¿U¥zˆôÐh5^Ígw¼=Ì|µp¯.(xmì×ÕŠDL½¼Ñ6”Çç?¶³Š¿L¦.µ á×…»-çÉᔌ~ÝSipuïM¶½ p‡gk•±^–Úóíá0Ö÷4§®àù9«^M›´soNq»AæêÖ¤èå[=êÂ;_zôÇãá‰øZð$RŽÔë[ÃwØîxÒg¡rÆ®¡;¼¹‡ãæz O]‘·‰sC*ü¤ç£î5‡–O‘x†ÒnòבҢõ×{Fnìà7Ï/ö{×Ê#n+€¿ XKÔÈ­ÀM=¨¶•`/G»nÃ4G[í Š=;¨¦€9ÅoÜW]öŒã™ZÀ<鯬dÌiý®RÀë1°ó¹m› >9ïo‡ ê^ß'ZÉÀ›‹ÝálgŒç§Ç2§‡6×ëð¼¼ëU_W¢T7‰ÝÚ_¦ÃƒGXß‘îÀÕu@¡ k¥y[×È‹÷¨óU½–N;Û+{žoká®r€¨Uå=e+ªåX©UÃg Ãob0Ó±aÒš®EÜ®òÝÔ‰3O{ŠO@W‡,£²°û0ç¯(ß2vmõŽ4;‰µ¬Nà¶°%Ý\…ör©Zò°bÉZkljF\^Íݬ;YR55ä-$ ð‰*Žã½±ƒÁ] ±ìKb§=Ðíú(:ðnôŒ^Seç$æâžÜÍÊÞŸ{˜„g…„¹Þ9‘‡Yï—©À«³+°|3\rš×°¬Õׇaµ‡f=]¼!XLôÎ%Vm2ºù9Y#ŠmK«Æ+TÚCŸ_9îÕÞÔî[S}{±Œœ›°71oF÷Sé\iªC7Â÷€õªòJçsÒh^¯v^V=áêìÅî÷zç$Y¨©IDl÷#ã§M tç²·ޏ.Â߱صղë=é>ºô‚Ⱥ±ƒ;kÕ¾ƒb-…Ã}¸-Â>£”éƒiÖièY”Ájä¬ÛÕˆÓg6± ³j\‚]Ô=w® b¥Õ7š”†È_³¶`}@Ë«¥uÎd:˜Dö×¼¸6–»nˆ©×s-`fº¼R3W.Z/,^ýÝ—\2Œ Sf¹sHùk£ì÷R´f÷·¹!“-8îq»>}–‹Š*g| ÌXÙcÚÊTl5£Jy§½áîyŒÆ¹•­Z¬&Ôo—©MëÔ…ƒ.ë<²kUd\•~xñCËwiæ."¸1AöLºeö”î¥êµ”kxX†Ý ïFXº®ÉB¸¢ÒÙƒ¹J/¢¾¥W¶JS9yxrÛy$XÚ¥ª¥÷g¼Oo#Ò—vª¿uo¯Ïƒ»0×¼{1.öKޏ%ê÷§wsu¯»ÄsöC3riº>‘\¨•ý›©—­Ì–YÒ°U}ŠžZ;º¬yK^SÅ:œë¨uzù¤üêö†ß„¤zî·R…ム8ŽÖó¿®s¼®ðÍ}K"îóJ´Ò3·¥kÞøìë¦)„ r¶ÿßÔžV+øYô:—z®ñ³5F]ã­Â¢€m–pYG·¶)N§ЭΠ”7ݤphwÔaßÁL!›Â7Øj¯)ìWØ*öáö; {ŸN¤†_º=ܶë«kÄaÛ=´ŽžFHgžzF½äACÑÅïKÎÝ K«Þî=qãÛÍ=…©•«Lœ€ïj¯6‹ÎgˆÇã”0öö®t‡f66avîÉÛ¦’³çÊuᘭîìá3|kœà˜gÖ¹,Ÿ“×”¯ºV¡zÍ>¹¤‡ácjck©2 +«.aUÖkvÀ(3ni›ÃŸ& ËæSÀDYw)ö/a£ú°{÷~)êÔ˜ëõšæi~¯O]x¡M ÕûÂèûÏcð鵟‡}°Êë¢ÜìôPP N²£»íoAä یũF)3£ýnW>ܽ» nmEÔùUàÀç$¿6–+÷Íc.¹}(ùób†ò±ƒv«™5ÀÐ;­pöNHѽ©µ"ßn+›ï/fÎÞ^U幯™í3g$«_+­xG… oT4<Þâ¼ñ.¬ÝY¶=6+xÜòÖ„‡"Y[¢c<±Q6vÈèo:m{>‚¤ˆT)fÖ¨µæÅÑ©[]YCAÍ!”ίgTÍ"mçSpP»5 î’¦àpo*ˆ%°nÂëºî“€xÝäè×*³C\žhX…AÊ_ïmz*ár ¯gxºÅ¡ózyÛ¬9³vLà))@ÖCZ­œ|ÉY/,.ƒÚg3²4op¯³µšHýÞl%ißA嘫ÈêŒcÈ”‚o1iTZë»0»è˜×Ö#ŸE$YQY#ØÅúW{cúyBiTðºØi«äëf]:Σ½Þð"°Nõ=W8ÖÎ& õ‘·ªlʼÌ(@•áiGjv_z2¬âu·ÏÓí(|Y Äï¬ë{¥“Vw|óÍqï_Ÿ¨VÛ(ì(0³©$­éŬ;ÙÓ.btêVÀ©¸q Ý…»ébG•Ý/pÛ­4Õ] 6.ÕÓÞME*º:Y »ê˜ázë/'yüŸ”yë´/`9éÜJŒ¼mvÞN—lxü8±:n\á¹o Ð8b˜Ê~­Ë„9{f ûs¡o¡ÔS‚ïk¨>®×Ö†ópal<˜V¡‚Ü¡W'$Ê™„8÷yØë& ÍåÉv7uªê t¾xºÝfSz¿_8‚áè'k+÷éXתû‰¾E’c"dz ëç]:õ‡ÑôÜg—†-Ç‚6k+•Bð&] ›´"ëĵ«³UhD«1…Î^m5¹Åµž¶°owŸ©7íÛJÇ=ܾ·ªî•Ã-]ín,Oð¤*ËO7XiìÓSËgo8Opç–³1.S®˜9Ö"Dnišë¡{]%zzòêõ-{Ó²O’pkj‰ Ù¡Jµ0¬1í4\u‰Üö”fèéÒOֲ𾩲þí§3{‹)ì÷Nö>»/9R¾õ ‡(Rïîî9ì¡Ùãâ|·(× °ÞTÒúõ6+*œfÂëÛç´1—éèU,^¬EØí•ÚO(•ån-ê`ΧDØžgÓ7ÇÃßO=zqS°a¨ûfÔ>ÙJnåFË1Ë%R_>ÑÃrÈ€Š:(±‚ázµcrÓ˶©†ðvúë¡Ь¹–‚ iß^:&ÙâV.ѹOÚ瑾/†ëBVc‹±UÖºÄß&øg`¸:­Ç–·iÜÐ9ôÊàA{dë€kÔÊi±”=§×å¾ï x=rxÉ>GÉ/«n6»6î"6,ì}’ßêÝþxqª´õö“Þvž®åi{ËxyêþtçàZýN¥+÷[—KND9ÉûG!&È)u_néW[ˆî¾fUðìж ò¥XRÔ¸oe߯܈ÏomÂݘ þp~啌{¾-fZá¥!#¹T+“ÒÇ_i# Æ8l}¹”9Íc˜zeñ|)gpÖ^ë¨ Ò†Ø}ÓcJ‘_`ü3ÝîgJ‰žNû]m4ºÙ1EåëÝjñò;+ÃÛõï•eàq,}oG•Ð"ç— ¹Ü¢4¨¨]CÑ`Õ[‡xwXÞT¾´”Áùg<'´[îò·/‡ì$Uª…]þ™Þô`ŠPf5á Md7Šï1ÕœI° )ç\í¶@ކØÃ¾Jº»3¸í»wÌ®øg¡cÚ{¡K¸28'®5Æ •a]ÔsÝ'•?.ۅű£ƒuÛ«óe¹º+Y•Ì£Ôô#LôY8Ë/°©OKYÙǰ{¾±Añ½ žø0,È&fÑ$8)xp£¼ÝÕéÑN”¥ «íXó¬UŠîž´â­ Äò¼ƒbè•׶^l¥ÔªçÙ”{z^ž¯h†°°­gÊ ²¯'.žñKWhw]à7P°çv@žWîÐO˜ÀXõÓÌÓÔÍ{Þ”¤2QÃãÑŽuæ.K™%–fOf ¦³<о!<ÜVWˆÔüß'bVAsm{O—bd$;.ùe_eܱ<16}ƒyöbçz⓸æ^g.¹æyEWïVÕ«®~÷Í©—ª‚ò{aqyE/~¶ÞÜ¡†JÂ(À¢SžÓ«é*Z8Ó]öùÊ”'C‡Šš1†ËÝJTn¡bÃ4lçg ]’×¾šëo¯ÁnÓTšŽ°Tœ3JÔ}‡½¡ùre¹ª“±ëmz¢¢®èóöq¶÷ÜÂÈ!^êiج‰Á–Š„Dw××|üz0}<Íw‡oF±]=²é @Š•3K{®l:)>ÖI±zýäìÌNV—H©‹7f­‡x*ºYj±ÌÅ<ý9àÖsÄŒ*rÅŠŒ˜­ŒÍºöäNvm¯—8ÕYŠËä2dBâöð‰ÃzbíM•–<ÖÑv-yE4O•G2ß a'výI!»«Çz*‡:ÍvÐЭKž¼ÖAÓdo@Fý“ºîõîX×k¬ëÅ,th tžnñ‚ÝwA¹»[;ã\ZîLup£ÎÖ›º‚kâŠæ)šï¶àÆw.ÜM‹ç‹b*Ãfíšž÷z*nY ÜùxÅ}ï<PßnÕË n^<ž43ÂÍš¨°1™^U-<ÛÇu».s¢‘sqÅx¤›¢Œb cÖpM;+Ö%¬ÛéB´Ë؄Ѵ$U/;8Ü’‡p`pb°šèrã(oØøÒúôRÆ“}G§ÂλáÔ1|­×IA-ØjéQáœ&Ç\‰íÝLŠœ¥\ÖðôüÝ` öÍïu––3tÈr«ÍUå̄єû¨¤_}Û»bñ¸ÃGºµc„úÞíìDÔ•ÔýêA›6G àúF?;¿~aÄn÷·nˆñ‰Üž469 úÞY,öæ]¬ûÚäV!zõò{I$EãÍâ,»Öow*Ÿä9õ'µ”•~>b žX/›î®×pÎ*ÐY¯‚(Œ³z¶R/»9s×™Ûhš+ºìŠÞ—\êÛ§Š#œ˜Ã{Р]üEÔµHwMh^V¾©YÑí&­¥§>¬8ºf´µf³ffÐÖœí¹¦‚¶3(¬îë2‚»nˆh\á²å: —jµ™·vKbú÷Ò æ4Ž›Iu=ÙŽüøÎˆEá·«¬-A*º·^å*1o›Ž²! :âÐì̘¹XÆYçÝ$fؾÇ0ÎÝÞ[0¨øÃâVWçî‡8«»®4Ê®“ñ(bÔÈ]LÊ_²Š=½³Ÿ[i=]3o·U*è§]Ýö ¸ÎÞßtõûÛ#!e/2Š·CÁÞbžÌÚŽVxÌ>ÇM-í³ÔâVë¶ŽlŽ»­®;€PÕ«å¶/ »ƒrßUñvv€Ú¼íÔ×ÙÄnýÅÑǼ^rÓ5¾ˆxûw¥í==]ÖÝ›}ÈóM®RCy…Ý\Ü»½|ërº£ŽŸyªT§»'‡'tæ}AXxW³a×­"œX([¦'¹¸2Õ,jÎDí^¾†\…Ñà ØxÞÐéš V-ºVœVdj[ ó/¨¼QKÁœhb ËKbšÛ¦×e’—ai<é(w›Ñ~½—}îËÆð€hò#*("v pòÌÜ÷gb³µá[¬{ô>O˵¾íŒg¸ÆKUîŒ;®ÄtP‡¶ü®Ý ~s¬v„.œ*ÝjNÖÕ^ï„qOf¿Iá]zx/h±ÐèWè¥@n„Ó*gOD¦ß`h¼º¹57°:{k½¢b-]k|êSB5;äVÜ[J•¨ÜhßuÖz¥¤` Vr]¼¢7¼&»´÷´ck:¡]½ãH]ý ÷†Û]ž÷.¼U®ô®}I‹®"0ýO¹g,¯i'i^`¼í'XßnÄc¿tñ‰0”Êð¢ï]îi\iÕ”°Šõo ܤèb ïlÕÚÒÛê¾l y§*Õ.xÚË?YÔA-iÊ3t=γXhf«בʔ$J ¤Xß*6ʱxÎR}&h”ÍI£+¸³‚³KtîjrF)O˜k‹Gt™..ŽÞåFhžÇfy0(¡éK=ºP™ánêî …^•VðëíÝ’8eù´Ö;w•!Ó¢¼ÚáŽôÐë”BE.‚mîÏk±hfŠ=4»íÂrõ𬤴a™"8CMè¹s<]©Õ^õZ°%ªˆ3å -Ã(qxë8;¨ ÅC)Ó÷j“yg•o0­±5¼Û$ú9c1³á:½ÆüOãKïyê±á æ¼ÍcR'{Ò&á„5”‡)QTKöE î|¼XX {Õï6 ÉV3=#ÀÑš@4€Ùª¬ïUµˆ%[æû«8æKçnBQÕàwzÛî®Ö``_$½lVêD^vïS>ã.ÉÛWiªÌ- ˜Ñ”cºíûN霫٫+g~6è=¡W:jfa¬†^xõY#8êV'‚ÏOy¥çM×–5W3uy¯UÌ ±&™܎>`VŠ´ûàæ—‰V›º%ºÑ§`îìrä!F$éÚ²iŽàºu•µþZ—z8HBÞÚ{¾¹á]Ýzná4þYƒ>Áµ ç’Û“eJ5Æ>鵨bVç.xw缑·Os`‹vú‚“÷gƒÜªåRä“Å!€/ª^iÈ4怾[2ã3éÕÕ0tìÇê«Eó—¹%#Aa}ÆÍg̾¸9–X%÷Š8s!ÆÃ¼zQ+”uÙ;»k1ò(ˆWJye,7ºr±ݵwÍráV'¼»Þ^öxâédòÓ\ÄÁQ%9¥ ñlÈuÍ^Ú2÷…Þ™2npÀèÍØ9 Þ¢H‹‹'£½½ÃY|ùPÄö±|7"ă•Ò¸-ò˜™O©´úíS"{Ýeá¿ ¤Å4%®è{´’˜z_ ¯6°>c;ÞË|Öòìyvéƒ[V½Ö<&Nt*³Ö• &öúü™Ú5$¹è¦yþ{ݳ¥Ý]!Ø æžBF»¨s.ß­d{_ºe>X÷—”Q¡ëwm›‡oW…rm˜^ÔñÐê×V¦(Þeù5cܪPð‰¿x°©lÀlœ÷=ÎÂ<9Ž™Ùy‘V‹µ·tä»x®bʾ䒲(é}}Æp&ìr|v@¥;Šyc_{U£t­ÐÈ}@ºÏm{gu\2rËøîêþv–•|}éÌ<„;w•Ðhh]æE×B˜ó¡ ®}NmytÞÂ$n€l_}–ërn ˆ.¦ž§Ï”{½¹n^ë¿¿—Y»éSwð½÷í~i?DîÜöo¶èÖr‰l{Z'|Y…Ýø·~ží®¦Ô8Ïguº—Z©ºŸjV“g»,õµá–’Êz]åurôk·ÊvöØî~Þìò°ýŽ7•†ÄÍy‰I“ضlè¶¶ ­î*‚éµÙ2ݱ4ueÁ–Öb„¤,û–Êyîµá—Ç­< "}tÜ|vøé®kî”]»›6-*»Ã‡Èëõí¬ð…ÃO´šè¸ÖÖpjŸUÇ3yõ]ª–=)ú^L¯1†Š¡3޼ÙvåÔæà€Œ½^Ô®ç›"x<µno€ÜÝßrñ¡ÕêíÀ#ÚÑ»ZŒzŸ^•`vt„'ÛëŽ^0Ä!(½sW°u_Ÿt÷}jþ¿\º¾tóËÇÁìe #‡ BÕ˜ú‡SãLsÿ 9Ÿ¤üCËÔ©p».麰4eþ{Û:íŒ|”Ç/­p¶ÝÍ™ÔwäcnMéÄë:Þá®2·ÞºÅ½Ú³€>áH•ש_‡Uœ›ÊåÝé½¼aèȇfEƒ.Êrâ”ó ä œ’ôD†õ õõuÉX™ZÕ_cBDNkå—g®r˜ævq[É›h¹{/*í×wy¿{Ô®¦eâßvog¼©¡nÜœbŽÒ^º¾T¥æ5&ƒ¾Úƽ³š´Êò~'Ø5’k³Ñ5ÞKqŒ¥ª—ÂŽ…Ôfj8n”"̬hT»|ë·J¢r7›]”ßc1ož÷ ˲Þ}K˳Q8€[rM:•R=7º¡Ë]ïs÷>5ÙèNç£,(ºB° `3Ým¬¦k­+•,WÔ /8,Dí󜈫´“©Ã\6ñàŒ*ïó]|êP»¿(o‹gá<4+:MãWu“Ï%«WÁÖ©Qøãñw­fù{_ÞM_x-ÞžRçrÒîV°t]Å4ßž{1_'-Xá…BæLSËÃ_w ëd¼à­Kn»veŒ®a:*Ï+y®HÙ¶:ÉÝCU^»†Ÿw ¾Ä\Q(.ìŠ+XjâU&+]˜ê¥…Êë:RwJ»*Y|ëwÝJ*W­/y]”_µ=PK÷Šd;ì•¿FÍ[À J¥ÙÝ3ZR¶¶.ólÃSŸš,r™F{O›d«Ô¬QÝ篡…ÂÞ±½x!U´>%ní`xª.¦&+ ûS¯9-šèŽT¥ìì­Ü.C—ËÓ=‹ƒóSTwÕîžš±®zG¶ÂcO¶¼v€·®¨Áy²¥kµoÊ ´úÉm Ø«`ÁN±Ù¦«°-£*n.åVöþ¾«4°EPªê³ŽsŸ3{) „ôég&Ö»çL W¡d3ƒ ûî߬®ÓÕ8RL£‰øcÍw`“¨º¸¥<€²ü£Ý©ž›]{P« Éélë h&Á”çÓ3«”×ZïR”ô¿ÇSÒìó[¸¶ážyÞbÔ—Ûé|é K¶¥Öjiïq¢Íââr¢Z!D%ug 3»Ü,{[é}Öß©«“À×qf;BfSÊñlÏP[Ú¦X¯B|¹ÙÆ*s± ¾xè G­zGcÜêo˜Î Žj³B'²Rw4òä‰Ôz/:~ÜR½«šÀÍ‚¼äçkµøëß_¦¦½åSù‰^*‚LnÊS±ïº×8& ;/S.OVså”*r”´°lê+Eö«ÇÀàÉÎ:ÇA{w¯Áx¬Ü»ÅGÎÛ©½.n“à†DÛ8¡Õ–r8E6ûRKTê57­YÂûh‘L)1¼LÛ-²¸åÛåF¯Vç!l\sι‡Üxwg+¯i{h|²ÖYêÛœ‰k5áyKŽ©M‚îIêg‡\*¹:´|z‡/7GË7H5¾«³l6£Ê´±áµK1)”pdï/_°bîYF »Î¸£áÙà½Õ[Vâ5¯ t†;tq(¯%/Sžö?žàô8?4ýÓ7ý£«­­£¬›Œæjyn|úök—óéŽ í¾{bX[Þ³9qж0ï…_Ä…3JÊBãì!³ »½bXùw\ •t„tõÝkÚSEŒ©[ã¤Ç+ÕaÀ’>­Ú{RôÕû!ãÚW- n¦moÅíM“W&ž¯!™ªAg8¥ìT‹Îïaì³ÜõõEºÓÈu›¼­‰GÛšû‡½‚ù ’]̧e{ªsßo”X½(z£ÌÈŽöž’³&47bË䵸¹ `]aU³“9\ïJGÝ^bÕñ_=Í?uöç*Ý3a)‹O î²êë‰9¶±®AõÚ€Ò„åÂ]ÍZéö»ìž~[zËà^jO†¹:¸® É£{l>äó¶ów¢%^ÓB 7þ/S£K¨ªÃFõŸÛs9_ë‡ ­óK8Á§{¸ ™ºæÖªTçÁ{NÚd¥pc÷¡ôBñŒê¿tö”vÛnhI´:öËn€‰»÷]ÚÉ&µ²óEC¥^㦶]]›(Í]¦Š¼ ûaVÞeX–f;Senò¶ å;:¥ôÁ·‚swpFN¤_ÐéãC·Þ¡ ¤mêÊÜíç<öÝ×Jëì¾yj^Ôu17\Z4IygegK⊥[k}‰”‡*õ>%^ÖqІº²í|k§>2ø×1¡·Ö‘§hvÀ ÉY‚â±4Ðu›5 ê_ v‘w:Ç Sz :r€À™ÜÀËêØ'vIÒÔ¬yë;hèé‚»ž/uìºí?@ÛºÙaD1ý6GÛj±¸‹Cs±W*C .–T‰7ß] kE§Ydf¾À‰Š¶ŽYZÙâÆ‰DnY³5°ãâŸ"P gkt­µ˜û!å)`™Z´nqêxc0…õg¼ 8< (ÑF®îIÕ­ÃÅo·y¨9t$¦£{C\3NYxjÑîèÍØ;*²F²;U ûÓ"¬]é< ~m”uóWVì䣛ºP" äÁE×=žñÊuï>%ÅMß}Ÿv4°õ#«ÛÊÍå×rŠâëKJlžº÷¹ïmÂiY熄ä˜ Zð¨}ÄîcêŒAÙú“­ï,Ç+k¨Ã7#•뢩…v©›Ó¿gq¢@o©žõy¡ö­w—%2Y%÷u 4êó¹,ÔÚʘÖÞxÜåzÓø×Ùt6õ ¿nÚó *í.³=ä6ý,¯oû%Í´;÷¼j]1@£öWíÆeÛœ+x´° 6¬^ßÉœ’ ƒK°^“¹:íÖ3ÜRÞ™G,‚ûìϲ»$Àe”{óbk{“UÝ‹¼V˜Ñé²{ÕÆJØnŒ™½{QŽ-ÄήJÉQîõüP!ÝšCjhQ”·mËŸ‘ºòÕZFuÉÃÍ¢ÙW«\N ÜÛTµ­Ø¢¤^á«~lЭÎëÎê]~¤{»(ç X-€ëygW=(6"yýMO{VÎþÆz÷ôêXƒóøÒNVâî¼N÷8ñâ5OvR‘ù.!»4úo ׯ½½»@*ßm˜0 Üñ´¯h '½<ººwGvåàÕKmÛ‰'¯=–¥:)W.*¦å`» JËè)ÛǼ¡i’ííäë÷²¯9Ù‰‰¢mï²yFÊÓ:ëWQ£w´¤‡Vû‰‰w,Ë'«_3²ºŽ-‚.Ú”PQËõÄz·)üËfó—k‹ÍT'(_›.uÇ‚÷Aq²8\—ס»9C3iLºX¸ä o”º}›)b€Bi5Ù6K^»CÒ‘utpnÃh˜=b]:¾ ì‘—ƒø§&PÒ¥b>_;{÷ø§îîñ'.rü?\=œh¾¶æ«›ü²/ôcK»D•Ó×KZòé¬Îì3e”쬉ÚÑŽºÃÂú\3’— ®Ô¥ =ÎòeÂka¶sUÇw퉘רäºü3öÄmNzTÌœ3¢—%áâ=ÔÍn¯®\WÔF•g¥ò*Þ ÖÑÒM™Ü~¼¼7 ÚF±¦;Uœ½D£W´ PÜOUªã™­{˳©Rû7¯sMd5ÓÑ?H6·Kˆß§,7ã±Ýú—±Á³ˆw‚Í´éæW”„ÊWX. H‚_3þÃ:ñôýlûõHÏé/<ÅgŽýƒ­^õ<ݸÖÍÃûª¹û9‡CñüW¥ò½Ré;ð„ÚjûOÈü7ôuha°«¶ÎTU:{Ýè>Vެ÷Ýâθç+5”™¬íÉ@WÍ–ì›÷!®ˆ'´Ô§Ú鬇?—QÕ|³8f%ˆ¬!Ì™9’Ÿm6Ÿmç^‹Iu¡C©ûÐz‹GFºrêRî¿ Ir èX’ÚÛê*Ž:çz±¾öЬº([>=‘øoN§3.wðÕ’2ódÎ' y‡GÚŸÆí W¼Lö;­g›¹Q<áSZ˜5ç[Lqjñ{Ô 1á=é]çÁáCMqÏdñæW< ùÌëŒóRK‰ÔLÙgk:W LóøfëzÒeyº»MOåYŽÕþ,à¿7ã(ÜýÚ@sÔlØ«lsØíIŒgbÃk§w 9°´KÃ3é¹°95—ßïÞ1ß‚ôOËÛxm~Gvß×yã²a^³~‚¼.ñ¸2o» g¡b˜Y.æ<7L"Ü‚^!¾ÍÑ»Ï[÷"Ìh-¯rèJ³­Æï©ºWÁŒ|K¿n^®Æç [ºü­ýÊty¬‹Úxʸè˯¥öL”îF-< CÎÖ½¿[1ë~¶à§»jÂs.ùüïh&5ÐÊâ(\¿¢e1]©HåòˆoPçR÷nP‹8Ò3¬7¼²¸Œ—ç(÷{5e¡é…3àéÛÚuy%ëG©wD¶¸=ʶÒ;}ÕxìÒIe¦K…ÝšFœXJ´&öÈú±ìG®€šŠÍ°â©[Û‡;·eÑO™ºo«1/HÍ¢ÝWvžÊÆ×5œ¶ó'oAÀIz¶Ôs…zéI/!ò^°›¯Vâ1í Ý[£ÃìLºÉ“/ÖC½Ø\xz…Ñœ±}îr;/ÒžFˆŽÐλ›| í®†›"´öq í¢.9Ƨ~Ñ)­ÏŠ™õÜÁ-zQÜïUò»Ãǹ«¶Ÿs7Ù\œÁ;Õö•CÌ}«$DC\ïl§©á=’{Ú÷Ã}Á<í­ô+žBG*SQlnn¥ŠwΜÊ+f ­m_ä#)‰Aû,¬ÂÞœ[þßê¿—Cƒ÷ÿ÷éýç¦ḛ̂ uѬ39d³Æ™ ö>¹ºÚSšnnp×ÝyJå ˜ ÕÆqÐ;±5ËÖ¾{ZPîWÆV¬¡“…Y8„d.¼Ù]À€Ñ=Ênš…ÞK¤Ì²Kà³6Æ.]ݵœUÞì·–§gX¶ós‘¼ *•Ô"ÅÈW;ò˜ø,¾¥0콕c_{#Z‡¢ÓàüÍd¿ÒïÝuÜ÷ Ïì9F³#T Zç*âá«‘ì¨kì3¨ÝÝô­©¥ £Ýª¯~"t¼û%Ʋ9Å4ºr†v½çu¸ùsAh†Õu¬£™¯-ûÛ8W(6l戧~ë‡Ð)B6Íê&‹IÆ=äúÈÎ ï ºÆZø‹æÃ6¼õ+¼KF%è™Ó·+¼›N+je–3“pÔU~9³VVž÷»¼ê­w»Øí8Û~ïr(xv?`œŸ4;B¹Ÿ Æææ:ó膡‚Û;¼©®û¹Ù#Œ6ÓÒ6®Ïm3yf¥M¨l‹¡–ÈîËê)‹àºNS–ÐÞ(Ïo¼z*Üîöz»í½w¥ò`u¼ÉÙë7½Î•ãR¦³ö¬aÎ䦎Ù8ší§:²šêN,Á}« ¬CXšÍg±½²ìXbÄÔ0ßZ|ów/làÆ _ w°´Äc;”骠:Ú0Õëz.Þûݳ0„W„´é»]é>”w2ÐYòƒ,.-×½ïyú½[,÷¸N/“|ìœÆÛÊÛcÛë–=#¡‡‘æ18»²ƒ/t”ñãQíË¡M†ŽµµÛÏŠa±R뵉Š'̦­j{o•äà/cç t=aÙ^8@/”Ý¥¥v¨±ûX©ëÕxŒ¶ºÆq¡€kq Ÿ;.W·,ºŒÛLfO9îÜ÷”'ʼ}äíL4±Û>¸RìSvšÎ‡¸{µ¶¨ŽK‘à3töí ³juZËò©]£ràˆ±"É·¥ôƒ Ëî@3Ù¸ÀÀú¤œ¥»)JçW§‘f¨â5‚øZ¶rî¶”í[a\ñ(O!–zÍïÞø0Vnªo 8}y³ÞÓ6?%Ù[eªÃ¯p¶ñ¤Uç «ÃvÝÝjf†oÎÆöå©Ðd_"$™Û]¾IÊ›ífzOKvÒíJ–ÊGTÙ‹l*3&à åqs¸×7i›åõ)³|:‰§4ÅC²´ƒ{MT™LmÝ vù’+vhí\]÷ 6€á5àyÝÙX€ 䪞ñnfU‡^SNcô”g©àäãƒ4Rß:ë[÷îã"¿bÒ ”„9JlÖÖóÑu%•A‡®úÊ®µÏU­¥[ˆ¼jÖÌ×.åZ½g¸Òç¤Q€”èÃÛp-Qµ}ìÁ£ÒÅxWDMª\¥ã”mrY=ç¾®8œKÖôt´mÑáC¸Ù |)TD›°õªºW:äÙH‘wÛ,Å& 9eZJùvaºÅÒ±ºwª9Äq»=˜—!} Õ¬šºˆ¾qv¹ÛI*ë—WOºÞe>é„5rë€l8†5Gᜬ÷_Ò÷îÂåÖ³­SH¾”¿KlÃHûœ¥áâXfúäÅß«¨;ó¼ð®âM@ŽÅàuæ)Ja>«64*~9×(fg6ä3Ö_G½f?{Þ¹m‡ØT\m`ŠzšXª*¼²³e^Ê“×O­X;^7«„)Qü—-Ó˜½';îöÈ®DÇ÷{‡¦»®œ¯ë°³yßw%܉™”Rxä|4£³ÙY—ìs>WëKЃ¨Ýâ¬øû£:ß;ÃWmZ—·Mo¯zýœLT¼ôuÑ·0®gRÎÎs™1Q ”§ÊfÑs)—ºæêT$wPm¢¬¨+µÝæF'TßšX;]«¯>7æ÷ßã÷ï~¯~ápø‡{°fä÷DfêÐúÕa=£Ä°~"õ^…9ñmP+yi«ëÇO`*<^uuâêy Úåß=½·?U—Í&ÓÒÉKÇUâ8ØÌ™jš2ý$ÕG¤ÚÈ[¤¬ÊUÚhUÍ¥„ý¬V²n_ÕÕ8äß"=Êpo¯Œ ݶfÑ1ÃS”WÚc¢%…¬¬Þ´C4¬½ -Æ%áËÐϱ0¥xº´#]²k.b±ÙUB.ãG¿&=ë¡fž)ÕÔ¬{âùZ§¨(,ã6KO­™G6NåPP¬ëÁ‹«©µ9Ôö#«79ª#Ö//8-Ò÷K·Ÿ昕OTš·HN&Ï+Ö4òÇ«.zÏ+ß}f?¸Ñiy+¸‰íåïP¬NX>s¼=›àž%s=ì¦pc=”¡ Û§o9ŽéGJƽçït¯7eͱ*sÞ‹\ÝêŠt'PAeòëBhñ¾«~å’z·G:è´sçžÝW–üýÇ5z•r¾}©È¢ÚDnž]ÈëϦ¬ÆöÙ÷zçuqåÙÖ5"E5v -krçdXÌ÷ÉaÔÔ ô°ûÝ(g.À:†”¼~oÄÌì^ºÞÏA MP;äÌÇgÕÕ¸žQaãuÅ”)¼þëbå{|ú™myžÂíµ6¯c‰ßY1]Gtè÷%šüW§_½çA-š},)kˆjkï î©ê5Ü!•íÊ7ƒR¼¯(6Mig {OaåE x.xm_ùã&Fñvg{4Ýr¼­ÏÐA¸{ÕÉ—+ÌãtÄX¾LiΫÅS([˜£¬œ&¹ksZî7*dœ–v¨ æ{{¬Ø}ª´‚³š 3puÃCsk±p¡[äçt;–M7Ç&**ÌÜêÓÌÝ=y k“ÇÄëV;MáÞ#^ayÚ"lõ€]e` ]5Y€Üu{z˜Â(nÎ%¬¦ÎZ©©R‡¥‹–æ4¯Uut[§wrÂÖr3ïV÷´W¶}ê /ÔìåägÕB§ ñYÇtP[+|p÷{ŽÝb²í6•7¿U˜-Êë{ϲg‹÷‡™Ù¾®ËyB²ø¤+Ùâ§0º¸ÐQˆýÌ5¢ê\„îÌnp×pÙœ¿œ2¶ìÐöVô7UÜ7>À.tAÐA‘¢ø³Õ—‹;µQï˜o_Vrh®]¨P& R—8^Ûdü1Ì¥gœ7õëØZ-7ÜYÿ”º…mJý£‘Uàû÷— Ëô›S®»œæ^Vr/¾ÕÒžÊ ªÛ·;9 JÿÆï·¹Ê »(<§Ž½ô©—Šåš¨÷uh•¯üݤ©¸+:V6™Tžës ÔMóú< ;³2Î#—UÙïG³r´]öÖ1¡|«É§c!ê6ÆÛ“ÞT(ä€RÊq©×¸÷’’¡CšËÏ1©ÔÞ>¤–Oqfîøç 7@|MêvlvÔÕ"JB³Z wròn›Û‹Ÿ´ÉSlÓ˯ ]Ú7¸qzºâ¾DYB §ŸcøƒO]¹šÆî2ùr¬®Â¹»¹zÀ¾Á˜2wX¥õÚ<8ÞF¸o "¡^OºÇ1É›<—Rå?³ å»M+ߟ® ë«1La<­OEvÜ¥ú™‚Y†g_7¥ê&ÈWl wǵáʇÝd×ÛêzŸef(L ¡¹ÕÇZµ]bÞMëî$ÚìvÊ µ²Í†ªV«•µ‡ºþ.æh§qNì9E¾ÓÑP€M­Z<ɤù/-Bð5‰bƒŽ½ì7PMbÍY¦]ŸVö{”ð‰—l•²Jã‹3ÖŸ…uIì"tc¥¼Ñæ´‡t°Î©ˆß“ô«Õ7s‘È.]³jµa»fè]Sºî¯c=ÚY Ì,Û.–ãÚœ`z^ä–y–´üÄw¾µÕí^¨f\»I„ü¥1KÄ[óçÙ‹†»U¹¹ZùAÒnª6n µ©aKå÷±WQ(›TM5»»Œo[EÖœ«é—޹ðÙo킈ËO¬Î:_!ÑÔG°í)Øl®Ñ%noRpÒ›ëÌuéÞK¦xóûªZa¨]g¥ëžàõyz]T太è…ö®¸J< wyEk‚ ȯ026>ê•Ù{ã—‰ð¯@<4£¾^÷T®z¸{U/]Ú^æ´Ò¥¡³8|ÇQîØ÷7jp”[•;¹åɘr¦«äj% ãÈá·“¶tê+\gydЂ'fÊ‚`¾©”ýàwò-Œ¸õx§z¼›õÎã<ºt]¹›ˆø0«*ÝcÆU’®GtP––œÃ®òÄó¦µ=÷GLuf¢à7į½+È{xzÕ¼œ«¦z+Ý®”Ñsâåz]ò@èÁåA/g€Åk|0<¨²žÔ÷]ÙB¯×ãÐðçGÅ÷4Ï—´cÏmqÞ/ŒÎ›Cƒ +£Ú\'Rû~ËÐÙ·@›HvâV¾r¼«Ô¼•,W¢¢çÃÃ_Øó¹û+Ümy¢½ï:XXT³EÉ«Ößr¾ÞSh:Ù†ù–MI[a“9zÃÛ9¯W±®÷‹Î:WÅ¥4›|V—N@¤<ÿeHotL¤–ÃêkÆÑí÷ˆÄd“ ®^š+̹™ÁbÜ" 4§KyqíyùC齟^òjÝKôŸNØL<;¯×’å½Íu#í«ÝpÄÌ7J´f•ưQ÷gue«ÇNS-ËP`Xr>¡9«m=lÚ›Jê ÕKµÝk.!s–ÑLx½â_€NÆ’û­K4ñ¾Êne§7jE ^ƒ$ãz‡øjTðîH9¿:ðý‰é–¦4Ó ÿZ’ÝžÈ;–µ9•v%šÚ|+λÏ]ŒThiXûרªî¨Çsïší?WöŽR­ë ØøÁÐOYí=̪¼Þý>ï{€žÝ3Ì£vÈØ—Z šM¼_’™ÍyPΖ1ލúȹºæDœ=‰KÍÞÔ½¹¶GZÍâ8ò”‡šÓœ»ÎÝ{¨¥mýÝW^Xi½Ã–ùk"³Ú©[¹²ß[ Þt\ñ×JU}B•ØÙ/‘½)âÍŽš ŒD,@ž#s°Ϋ0'SˆÚ¼Iic®Õ—¢Á(Öl‚¹‹¥PçfòYÌõ ¼(À’¬5è·Íqëô^½²7â_W:ÎU±ÊÚÓšÔº‡¨ëy-V÷˜›¹Ä˜Óâum4ú÷s o1ÖØØÅ!-„3 ÍJºø¸xS>Q+Ü÷d¼£b!Ü‚-Ÿ_€åŸ9µbqŠ”õ s2€„W¬u»Ë@WŠÙåx4´ó¸üÝç’d²ˆ÷"!Ùiŵ6OV½&øïi™ÔoT§ì`ŠÎËbf›;-b9Æï§T.Ij YÌ`™uÔ—7Y)·V.m¬†æW›7éÏpUåÊéåÄc¼Æ¶8™…ÓU„®«DĦ:ßfNð>âÅ'Ö2’g’ÇUŒ­C¸m8À4n”¿JQƒŠ®®èÖŸz¹vÑ5.º¦wÒ·|Å¥^I{«Ïm_P¨µUÉžÙáÙ=”C¢ú%¸½O8'®û¥æ–7{Ó45¨S3reöZ0].©ÛÁRH·&Q1 Y’m$l!V2èç¼KÊ·cxg™7w<Âå»OÒ¬OxŠò÷“c(XlÝŒønÞN¤¬«Qñåì'N¡†»L_cܧÖE=£¹á*k¸yâµ [¹»ÝâÒäß6|ë~]\5‡çº9œ+ì¹Æ×jé×Â|ç9[–ðð­¼.u¶:³xþÅÈw¹òë­ÜÅݼ úò†ÛìYN1`Ž©‘Fk!µ¾« ^Þåš½]*ž nîFþûè¶þN¶-åûÛeÒÝÍfQÙöWÚö×`ÉË©·ª—¥g®„ˆ{»dU¤x°OoMÑW•:¸ÆõÝŽ¡Êü÷×3¦p÷g±Š×Ëj6j×9Ǩ#Åw— ^½G¼ Z*zöJm„ýf°æëŒ:Ìr0ü/0üeÒ]çïyz»×½3×硲)Ý<û¯0õdô]åaÊÚ¼ÞÖ¾Ì_ß³ObÓ§°„–z$<ëPðÃsªýãåvÖG¥=î®\dYÑ©[Wϯ»6i˜w" °)=ÛV±U…•¸W,@âá;X|  r^:,²iú=™YŽ–C¬ì'—ӘÂÑp/Ýš‚±Ì«]»fé›RÇ,èε›  u”³«oTÜÙ€öeDÂ¸Ž TØ€}»dœ®(~hÞ–s©'æ@^B=É;~o7™¢fîÁAQ š|€'¤Îã/ªÕe¼•2ËImLê‰+v×_dœ—Ë: ë¹iÜÁ%×MÙÓ ä÷·Ãä<À¯p{½Õ·³{0ìì¯GÓN§;OQ¥ub³Wη+WÀ²Êܰ º¶ZÕ„rÃv‰r­î\ÆlʱtJÌ•ÝØ¸"ub‚\-ߌúÆ‘/X²ÆoW½ãƒl°•íåÕ{” ­GjǼ÷‚G.h¨ƒö¯`9ðŽweý}]v;]Ç:䬋£¹’sÁ³i#h— Ñ0è«PÒñrÿWP¾SÆ7.üýbô±½éÑ`¥Þð•¶ó8w>Õñ$Ô÷H1êÔó~˜]y÷.9Ôá ×ÕÂjë%¾dž<µå&áBôiÍ*øžSHÝ=À%Õt ¼ÉÛý³Ý^bá3š98‡=ÖÁ«,kº·ÝÒ( Ú[Ô¦!K;‚Ý[’Zèµ;;›ÝwS•°@A4ÆkÀM0ôü~Óö“ºÚõYü{¹i4êË÷R}NxJ¾‚լǷBhù“g¼¾F­üÊc†ò>âÖ×K¡%öštkLÞ-A^@Và¹Ñ®"¯A=‹fåuLºP}.É(*šCÇzR«îì óOÝ&ÿ!ǓܻsGsDKr}MWóÙ8àç»kGaÝÝYC'sªtäÁ‚_juaÀ4 Û$%S’ÐéIaZU3uUê+(ø‘Óˆ6¬ÇüUBmùÖmž¨üÝ-ããwvÀ=~žL®šè˜nì´T2º;¤w!®ÄîY#èÝN7~T½¦v\V/+׳µü}ÙL›öà¿jvÅBV½×œº›åX ÁMQiÃßeÔŒ±sC6Ètçmí^¼ä5iD_°¡µy“CÌíHçlwCR3 ãPíšFPåxªæZM‘¡æñ÷ºˆ›æó(GÍcòÊÓÉÎÎÎeVbö­Ë_½x'ºó*³\f žÝ¢¬rû1×5ÍÚ®µÏ®ß=냬ì ŸsºŒ¬A¼ÐÉØ_4é%Î)uÕÞ‘€Ë\­¥»Ún˜k‰ “ÆŸGLá3©Üj@俦x…[½Üd<Ì7P£wÛWVGç‘~ïdú&ê{†×T#ÇëyÝ×¼otb^yø>S$&Ÿ‡Œâ‚¼:  ºe»>xtÝr¹­öo® ¼öá×/5E^eÐÔÕ¬bטud¿Y©8?¦¢|>~¬½¿BR™P\BõÕǸÛSdÕJíÎp+0Š€÷e•Û¥N4/`é‚«Ÿ7…€låY•i¶Äí(ËÚŽné%ŠÃ½ÍÚ<71>œPʇ§0#sní.µJh&MƆ•–äYqklH·Sëåé}2í5÷P¢`•½m›Vs¢¤>NY=×C6ïDYÒú¹){6¤jؼÍìxFÖMvšLwn/XmzóU|ªÇlW)’œ¥ºïZÝV5c)Vê×Ìq†ÎŃd$UȾÂîp®ïªóp‹±Û xNÃ}ɼ¬ ½—\’»ÎR™$ÑɧívEævÅQ­)jñYÈzë®öÍHïÛC~J­Ë6²Ìé`-¢©; ®ßLt@^ãÍv(ý5öâ”ôî2÷ÚÕíäÊXoÅæ/°)å‰×”vô­´Ân™/^â—3¶÷ËC2ZƒcÏM•õAhëñ8;¢kr ›™±d ¼÷Qxêy漏d®µŒ¡—/\C¯ë幈juÌi2ÐùàÛZî¤)Ô’ä·³Ÿ]¥%á£y{Ýl·Rtvvë*þÖîuÖ]p~8ߊػŠk<Õ£E¹š '×8>Mh=8TÍ$φ‘ì/ãÏÓ^ºÍ]V¨qkƒ´RØ·¥O.÷6V·¼¡ÉTW×sÌw5ÈOn_J‰Ì¥šT ,ÐwK %X|± Rv÷ ó{&’Nb?%Ϩs¤™¼w 3›íº°¤i\ÅÛ¢,·‘P¬Ý׉WÕ‰»ï'>RÝŒ:+‚b.8øç’÷–g” *Æ([‡†Ë7®cÞËŸ„e?þ¶Ê×êõ{õðã9¿GøÙëýÓóº[7»= cëíÔlw+¥Ìö|¥7­tGO>§ä=ÓÂú—Qhl¢õgÌMüüû×»÷<Åð*™&®üía@üæ"oeg¼´*v©TE‚–Éöö9ànTwåp!KaÁ€nf´›N´ íò›j½è­PàOŸ°`M›éYMK¬‡•Ó`o<Ë¿y^{Ö¹!KÂ3/U öV\›Ã´Å¦¹ˆý+Ïb¸ct Ê|Eà¥8ö43rºº”Ît«©h²»ªä—áø4%[în©§O©,§^ËÖXêxc—ÞOñHOV¯W¬³û®R´e1· VB.s"ݾƒKßw¾Úì§Bö9¯Ã‰,nS”P>O.7•§¤¨¥Ì8‰žÝP—MõZ +¯|ÕíÁæ[÷yÍb¡åø_ ¢6ˆ”·³ž<¾"‹ ±Vl9eîgÞ9›Õì´äê^OU¾T„ŽéY¾<Ã[YhüåwmnŒ©9¬—ÒTzt){™d¤Æ^“š·qX±,¼`Ø}ê°Ã]^÷©ž©½›^ªZ¸×kW®µŠÇYd“–÷rW5)#µ}"†_µ?XVÑ>ö6Z¥Ò߸Û<λÜ}hË´"=gGf¦l¬«îD_1 ¼|%ŒskuRåÒ;ÃÎðkˆáçA¼WLÁbKÝMBUV)Dxâ%% ITêMT{ë‘ý÷íçÌeÔvnͯ‡ —¡[­îùªrë…žÑ eæ$̺³bnoÏ"§Q<¦;:Pálhv l­ì®–aíAK_qˆâîl5RÇù²p¯hßqII ¯Û]w«:®´„ï2¯æº†Éiï]÷n³ wql<Ò˜7«§mËy¡äóÞ7 ;°Oo˜¡iË£oSr .Ü5­yá^™MWv1t÷2×8ñu£x©DÖmtÙv·®ÎÀÜfe(3Æcóùª7Ý@»,·"¬¼–µ†ô8ëÎ, 6Û¡:ãâJ¢dÁf\u„•–¸VáþI~áÛSÞ.ë×ùù‚÷Õ]rÀ¸`á@VÔ­º´Qx¾Ù™vœš*뫲%9v êîÀ»¼&9{¾Í¦€¤ã¿m7HP®½eૉ¡”öüó¬ü¼ØÍ£Sš˜øTPTsÜ#{³ßÚz²Ê¤gç’½­yì§ã|h=Û™§KÓçÒF¦óîlP±¼VáÕÐX îìÓ#.¹›]ÖçÁÔݲhãO ¢Ö¼v=Ö¢#®ƒ— ©µv.㟭×>¬q?K˜^Ê–f¤s,ÌT+4†qçðY´ûÖÛ£ßvï“a³Xtó»yöÃBû´³¨3l%ƒ™õÔtnÅ Ê]íÀºR©}«»:Làƒz†ùgv,اã;JçìJ}líÆ›Æ´e»&µ­G_;n?‹Þc™åضʽÉÀR­z}Æ‹¥ÚëÞÀzEeSH˜²ÌÔ*®²³ Õ}„Ò×)ÌÈçÇ“³ÃÔ¡›X®nI΄p¾ 5ööz󨍫­¾]/€æïdµÈÚQ¿”5àÛÒ’.œ\1Ô»5®6NCˆ_màV&TDéÛYävËë\½5Ýîsö¯„acÐS`‰ 0 »ÛËw{{çâ³3Û«—¹íñeg¸z¸/z®tJíÃgsº6©JíÌ[»)÷c¬³ck_̇×:ó fȯ¢®Š éÒ¾Úѵc)¤¦?‹ºA¢±kÜMЬã¨ý0slâOÙÎF>Úº÷3›ØX/GBÀIj°l]ºD•i¢.Ëž¯zT=30­öÕ³nµ­å›^gºüö=)züÕ@:nH+°ö"ö g¬‚Þ·?©îòU<±{Ô)Eà–ã¾×FØu›KŸöu–÷½`«ý„SÕÔ×#ŽÕ-¬íEÀì„ì;9û«}§ÆêǦ®I Îef=¦l• ¨év_Æ‚öE¥nrÃÀâT­É+„í ÕÅWt5qº+“ Ô<ÖÆ;¢¿–àöŠàj”ûhs¬ñJ?eOqº]«t´ÛR¤o(ËÞl-6\} ÜQkkîYºú±ûÞÛ÷ªåñ÷«æAæ¶­å(|=<ª~g O0ŠÿP¯|–e G@~õ;Ü=ÃIÝ[fi–034ÙÝXî13Èfñ ­«‰Â/¦®w ZYª†íõ÷hNþpHqŽæÚ¬©¯gN íäìVµEL’}vL‚ùœp«4;¸÷:î—ÊèÌJ®Ëײ’Å6Åi %V1©X¯Ž5&ÒkqíEÅ7¯É¨úU¯u½Ü ïW»G‡£2”ÌßNìÕsC¤uõnyR ns•†ÀæÎ¦½*èCD\WxdaRô³ºÛ‚¯_]Ø9o™TE (T|¨çeÔ»ÕÝÓi•è†1—¯W;~ÚwïYÊнAÃ_„wk†ðc~Õ;µ…ïrXÏ{Ù^û*FeƸ!Ú3·n·jÒÇVÍ9ÃFõ‰`rµjJ™\êÁ—šc£¥Yöñ¢ÏjÅVçàKbÒÎV*ù„s+Ÿk kmïe«ïªVå ±êŠiUjüñ‚Iã¾@gì©”ÅÃcÛBîFˆ-rA|ÇÚÌ;ƒ¤jãä27o ÉÕÊÍ Y¯d‘SET‘›Ò.Þlv$?ŸwU¬ì(xW§·‡Šë7}›%ÓӹѬT¨U±n|áe§®–ÞÄâà;sd¶‰ËWš×I 1,Üw¡» épfn'Ìt ²Fð@7…\§‹Щ‡/ŠÉ|r%VHºb•u6®m[YJûá¡=„,¼“¼´èe»Õ{#ˆäi@í,ö³[C9eXÖø|Ýo¦.€mÙ¬$¶¥mC˜Œ_lG?”‡ógéå_•_ìîOªåto–ª,º[Ÿ~žÖçŽGíö×7O]goJ΂–sSe‹2.”°E®0eiúHcÌê¾N˜£ã}ݸ+tÍɬ©JÚ{Ã޶űuƒ3”xÛöýï3ëJtE)»ºî†Ù⧤¯l®öÒ³2‚|wT¦76§¾Žñe+ ì·B·…ˆ ¨(Øw½¤Uµm¬·^½©Ç1äàÆÕù©~[·Øèt¦7—y)ä®jò§Þ ºAzµ^îûO3J–ƒ¸‚ƒ]ÖÝ]fse™‰bPŠÝXx÷E–2V ÓÃ.`¤fEƒ…o •ɨù2¾J£M KO'H¶®ç;Y›Ë¸P-vÔG9¤™Jú¹îïK©K<ýáSûlæÚfÍàÁ膮ÿhª·ìLµAÐU~ùÔ¯WùU+ƒÐ÷ã·P«]£[ÁìÛqwT®Ž•qzUv9ñh>½çþ}‹¸À}÷Ÿ³½ï*qªµ’v/W°š\â{B;‚þÅÛ]º é#.ý…—NŒÍ}Òo·{oÅ/ r¼&fÄbÃh¯-)öžb¾Pºær®3 ©ÍêÚ0Ö|¶»(íN+²°æZ9¼âz^8Ç–lÓ¦³»W‡y¨±¹}wñG{À{Ëá¢Ç½»^Ëë’IFÀgÇ)=ip°Í¾7è’@K¼ˆŠž¯læ>*³&¡Ú$ÎG]]ˆ÷%ýS—|5ûÍÓ§ƒÑ»ˆ-Ô[®zOËC6_›1Ñê^¿fùŸ»¡B]\iq‚†L®»JOªm¶ÿ£Ìì}+X¦ë¹¤}o­öl8¯˜œt;v€ý…µ\7…¦îú/›ï_äTÃï݆üHÖlî;Éw:Æ:CÛH-ºöÄ…¿c{{w׌øû!°ØŒAFeùœŽ™ õ ¾X–àäü½:3Ã;:Vå¡O¹`ÚÔzÔ™´‡Ø¡ÅÜðKÑQ·<Ó®#H{ÛKtÝ]e8_Ú÷¢ÌLj7Àp¾‹ùè{=~é–Gzê}@šf“^[šŸW—ev\ïa{;Ÿâëî)UÖÔîŠÈÙÅãL(p¡† (ôïV6à­œ‡gÄL¢®=$AÒ‚ì¾\…Í´ºØÿ>­|mQÖí ¨¼ÄÑ»ͼ·1\šCX«|YN†Û¿Ýó2϶{®D‰2iË;<÷½{ÜÞIMÉLà*øÒØ+Ó]{9ßQ»ÃÏ}AÇSÛujººúÆÐbÆô /j>4j!üªö¿+¿1×'‘¯evòÙC¨”5M^åè`ÒÊÔñц÷3”ýE­ÇuÍÎïLJÇ`cR]=žÚ³¾ëöXêBý¶=𼬠÷D˜&fÁþ›î?{ Å~¬Vëx»ÉBðq¢C¦•V¬ê.·ÞíòÉìó^¤ÅÞ:b=ÉÙG{ÌQÛ"âÛö.µ³¶½¥ÃÝB¯•v:+²èÜ¥hã†WO$$rA±-oPì2ÓÌé™Ñ*FÚÌÄ‹lÊAŽ›×8˜ßu]A]·ÛXà³=„rÝ–}Ñ`p½™¶ñpÅâhÔ—I¾­nΩ uï˜ÙDö âÛº˜°‚jï7'¯|ré1œ ŸÕTSÏÖè½ûðòÎs·Åša|¥ßçÈPË«—¶Ó ÷…ÖØ\\ îçdf=©¦²‰¤LŽÕ·Þ»/°Çl(ðÀV²®øI¹B© ˆí¼Vd­T™J,¬¾;]Îïºkt¤áÙÏÕŒòíÕ,šÔ7p׆Îì¨]Tí¹|ïhQÑï«­äötÚÁÞÎ+½@\½W+м¤ØD Óöƒ­`9}1źnÊÞ =¢m)E;˜ilÝÄÓDŠqtqÝß™±íÁæxae "G‰æ£¾m—‹ é†(Á19jÇZTÔ +–‹ÎÉxE€•ǽ†gŠu¬ó{¹iôCUé¦3”\™moKà¹ÕÖ ;Ëí?ÚÖûÝXüAgÊôX³%mym­ò©øç¥¥¾¨=¯Cñ\ÛôÉ}En¶Vòäf-C9Qyw‚ ¤Å±¬ö-62´»×K /xŒ±*ŸÝoIë_†`ð@pì£iß „|¯r‰®EÝ“AVêò^¶÷L»ö°î__S’¯³ij¢ó%BžÛëFgS(U›“,pÜÊÑÄp¾®âñvrå¯cêë©Í…‚ÚÔPŒVÙèmʦ®ÖÕå›[¾K†:²*Jýûò¶WëçûöAã}XÉžæ;v½ YÚsxbQí$DÂ(M‡Œ`ZoÀÖ7H«ù·Áhiw0+öãêý7÷—Y`åÛõÃGDõ¦nÆÂŠC¼¤$—iÂRtób¼ÜÛu²ñõ`­ïO9uèžR¯*Io±líà«4 ›Iô]~ÎÃNé?!ç£r9ã¥z½íp|*r gÖqImo'AÝ7w‡Q‹^?žæV'k°7ƒxw‚æbÊɼô¬;ª6˜®Õ:”›§§LeuΊ‚Ö@Èv¶zn½VÞO¯Ðè ˆV›°{GN£{q–kõ¼ËÇÞò-L>^ã`Ðh;Rºšñå}Y™W>tÉ»¡:¶¯¨ŒÍKÞTû@¾>ÿí²´tµHíßìüµEî³:»´?Y1ÜèØÆî3in8ó^ŒjкÀs¹nZÏœ¸kiL›%éÕ|ˆIcªñÚ±µ¨gzgJÕ–;{-v2û«y»=ɲŸZàû¶ÅߎéBâœ8«#Ëë3nV+nÒ›£ªãç¹KrçÝZ¹ºe#¯äŸetW½£‚óîÖ«d 7¸X¢ZÒ¸årÒ»·Z&Þ0ùóˆý¨ÖŒÒÀå}gˆ¾7»+º‡*?{ÞÍó[M!t ~“+Ϧ]^%¸ØF…2³–ß[»wrOºw› Ã[¶‚÷*ž>ëíhÚÅæìèí>®Õ+ É1ë?Ep·ÝW8O·7¬Ý° ·WA›å•ï~«õ>]×)s×7)ú›7öì¨n„v-ŠiþH}áíY8«Û¡è×øùŸw€‰Çë }b•Z½•eøÇNï}qv¢êv~º4Ó›˜¥{Çxîß8Ã`E»…Eš¹Þ}õ¸àÝît”´²Ítíáæžï#í 3e¼íJ<öNгRÛ@Ô¬á¬äîpÎÇçt\˰1ZŸNƒ;¤=í|{—Žò.ÈðL²tÞhYÅç]ß7Vª4!¡©Ì]Ë€—>$>›³LNÏw5êÊíGfêå~4dzW›«N‚ôûAñËBA.ÖÙÛ˙ηգ>¤råtQpŒÇR£ZD¯7¶™›w(££º‘“+^‰æ5ó-‹8XÙfÓ^Ý储ВРÝ&Åõk¬k@`F4)¸s3ŒG Ø¥¯éDs]†Wvgø©Æ Ëwÿšo®Úíxë-,„å5±©'I•ZoˆÑ¡E¡è lÿ!b9šß]L¼–Їê›Ey:‚ÅOG½ËC¾XšU:.Uï³SÔîÅŽË«U' UÍØVîÙœ(VTc²¶nnÓ­Ès %œà"Vk˜®Úa½Ržö7Ó¶° Üd;9÷fÝó)0Ï[‹(ƒÊ²»••5öàB¥÷ "ÞvãéLF½”(ç]¾œ˜¾ºÕ.žÓ¨»yÂÌ»çºöåd*R÷¤ÝÚ2èYØ„ëE’ëSV2@Ñnèõ®®®§MNºWÁÙˆN£ß<±|øè& 9 e]o"ðÓi^npg¤¬S®îé¤N#rÜÅÛÜàz¡Ä…_+}¡>R4 ®ŒN‹"ìg3Ýåk¤×l¬ÊOtß­ B%P™x»±¢ª¦Ž jdBGz'”ªþc·–ˆÐ­–ì¼.À¤"Ó 8ð& ÁŒdãö!Z÷jR‹(´¤â”£A)H‘)'N3£?uÛòé¹ýïüw–õßkÖ~MKà‚w_gócÛ†5 ìÃ#Ñ[ËæŽ„³Ý =•ô&ôŒœèÈA ¯ñU+«¾Í­ãz{8³ò¼`ÓEYut„yóß2ޤÊ,(¯£¥$›é(BžæÝnÒ²è%t®áKXµMÁ7\ÔhQ£ XÑ33Ä0¢ŒÌ†$&% $:›Õ]ÀÖKC ó×î±—º¨-{ÔÓŇªùh­xSpr,ì¯'âǧvùÌ f{>ÙÔˆ÷lžK¡b,Æ/žQht—@²ºN!vؼ3;6£%@»†tƘ®Yœ_Që Íîf4ÐiâÎ}µÎ—tÛX’ÁoimnõMe)©j0" 8r¿Ä~ß?ÞñÑøþíÿ›TÞ¹ e0z÷9­OömöNIaI~ôòƼÕQò$Üær‡P;ÛpzÔŠè €•Éѵ½ž}Yè0/U÷’É•Ûöi‡º§:O º’"£J·€­Ä™—lÕ¾+¥’±{¼óÙàÕã>Œ¬ñ®~²U@êUñaŽ£ŽiÛ»cuæ“«K×´N[”Aø†`É)^íÀ ,™[ŒÞÀÍìî’Ë·ªôï8ûq(W‹¯ÚsvÐÕÞ<©;pŽ}u|¡éqç´yæ:›#˜­&k¼é܈¹Ñý†ëÌë¯{žß9¶ï¯*M,Xrýœ;Ñyu‘JÇ™¢%'dIãåµ ®6–_i¤¾=Bu<® ²îåì¦ä"µDQSîR=ÆÖ.ï« –ö¹P½š,å0_¼¼:øÖÌ4öíô÷—½X±;X¾i¾«j¢@z O‚ ³u×íç7 ©:c¯A‹ªâ§ƒ•9ih­‚Íøã ón4+Vºû–fÛêo©ºØqGìÂqï{Rì~0.ýgò½/tŸVG}¾šÞúC´°v“ðÊb¯Ãè—Ó²ÊS;ïzü‘õ ÜÝ2k7 Ý[»XÂ>wÃW_“Ù²Ô-+ÇVÞyʞݾûjú¸²E `‹|„¦züýLoUÓ{Ô âȶUZ55î[cš€_28ß‹¥XZ%°nÎj¡¬8‘ìz5NR±ÉÈì¿ À]77yöØ­ö‘Íô!}ƒ˜E«=Ž_*òŸIÞ=]g¦)žÓ(?—¨?“n/nsíOt ½WwCªW—CiMË jd£‹r›,ÈÉX¸á¥¢1ä³}BÅ£$¶I˜èå]kÇNî®GBˆ$Þ”2nHNTšl¹O^íÒ]­l‚Uùi‰Û””€¯w Ìò¸]ÊÊÈblÍsè§VêPŒ[$77yK |m&þ´s®˜)à'(HMȺ®LºáÇ WM(®^«ä6A\`‘_O¹Á4€¼n”Oržßªã¬·+{ï>¡4MÒ#1¦6û®½}ÜUÛZ9¯7™íiæÕÞŠÕYÒÊÓ7›´Ëß.X½òß ÷hràè‹Ö@»¦M5`gjŠbïVÙ^<ë²™›25CǵZÌW޳§ÃÁô$ 8Š÷‡@8û»*çvÄaÏ&·râ*u…péêGÔ5<*`Iæxävr|vë¸ïÊÓ&3l=·ј¬„;–ûD4¼ì¥§î|:š“:ö|ŠØm:ËTœýIÕÚ Øý¹ `zDl-¼{¤Šßv%J{Üí¸Élý„kulQGñسJ^¾öWCGÝZº¼´Zò•Ȥ«%IºX{’„¹†ëK[CÚô, ±|v°žênxi~ì{©^ÜDZcÝËZyØC™NºêÊÙ]5‹–nï‡6ÍKFv„:êü ©Á ÓÝä@e-¿ÁT¶†«†ñó—%ïá»Gl·‹õëõeóOvO.ëë7Æ;õ8øÀp,;Bí²n˨Ðß8¼ú¦¶Mj¸×m„à¼Ív|jTîܳy sIÙȬQG6T8îÎ,õ¼Ñ=Ó6ˆ ‚ûÖß<àA­¹ÃwbÅØùï1ÝJäb…Þ=ÞdÎWÆ-÷{¼ö8é¦ÌÆn_/¼ÇÌyïºînÖK¸Íp„ypó˜9h’ûâki^õªó!ÓöT€+Éð~w~ÐµÞ ¹Im”w·³E=¬l-e λÀ¦š’¤:È´kR@öœ[Ó³o„O@¾°:»Ž-òõ¤¦+/Ð6Ó÷ÉoÛWã]Ò‰ÇÕs¤O-s’·*\StS È0wKøÞï@gê¶”dô×ù€jeþ¼µ»û=ËɪÏFª ºuÞÅOʲów¥osHAbV®Þ›^ç¾éMKTfyku/ªñï<Ëêw‰ŒuÎcku/wîÍóžÙ}]íIšõ85H~5bíå%åGFg<=x"%ˆŸ ¾‘{`\ÑÜÜœæ7“´·×´â•Ít¾¥)*·¿uÁ¥á|¯G?­µºT§Œ qlLå‚{ºÍ*ƒ¢¯M•}§©òëM'5ªä6ñ×f± íY§3–’ØÜŠÝ¿{È_U´ew§»mܦ†/]K7î’,8ãÈís® ® QûásO¡¦ƒ­·+.÷*Ö¡ôF”½ßr@ XŒ&¤«k°8îášA@:pÛ}’Räxv¼npº¼û4©J/[ïe“ÓŠÞܽ>1“1f™pÚejXéf§Õ) –5[Ôx>{»Ô}æd<&™å›¼öºý%yRc©Ca™”»}<öêP}üý˜é0ó÷~´Ö/€•}YP÷o=ê]˜è„õâ*Ū¹n•Ûü76JB¯…]™HäG{¬ Àg™ÆwÁßjý<-m%zpí«§!:ï- ÒÕAt†î—®³…ðÚÞ)ð§W™ÜªRY‡Þ¥‹E/ð›î[,rõo{Ä.’ÉÞùm½aÖDŽ÷UpCÁÒcáÅô:Âçœgró]}mÝo.ùyZ> `¸”êxJwWÜ;’áW›¯(zºC(b¥²okhͼwå]\᧦#ƒs ñMš¿?WV(¼zÈíºÓέR~FfP5á}šØXac® ;ÔžåàÍÛ]XŠÅ4©>s”èÕJÖ5{²ŽÒåhèC>£ÍW¨@—ŒÂ®8CŠñna1¾F¶deKçØ…¬ô­“¶´ØÕú|¦º›*&8ËeçKs§Àw;’!즟uÂê™Öy›Eõ[ë5×lZ qðîìÎæÇ«|Ô0míÁPÔ¨_ÔG]$EÒ–QK]¾ÜVA5²4Ì϶r†¶úp›3™¸–ªÖ UÏ)Q_ ²¯Á›ÙœW+%ì©Üžƒ¥‘çm‘Y¸¹šosÁùv Ÿn¾uinTˆÝ–_Öô;`S>Ê}ßr ,×tzî®Ç,¼µ» Mæë+ÔôÌt KÐo­º{¶˜à|(«Pa«5ÝÕ›(‚<òž—§•Ôä;ª’-·@]ëQmºw¯pï©zßVnRñ’¼ƒ®Þà³1£o0‡RW¾UšÕÀçv>ÎDvÛ6‘Y›J÷:ÛÍцèF䀨Yßdn'¼6²WZ% Ö6¡é²lÆ«ËxsU£¨OnìóÖxJJé³*>áŸ6™R§»×¸fšÞýcÛ›¦Iö:9KöjzŠšhûª½{q˜êW\×°uö¥Ú#Ëjv´jˆ@Ýc2 ŽºbP·ÌªÓÔ¯¯«å'9›·¯¦ìx:Íûµ¬4ýÔüVÈçJ+ÒÖg‚Î7œŸo$ÎÎvV0Ù#tÌ9*=K³¡îb¥Æ<þ]CÎæj^ˇŸ³Ùš*èîÁeÕÙçÂi›µ™Þ{eé sÏÀ»k¼7 ñÚSÈÄ5ìÙlÓç#3 01ÓÄ7fÞÊ%^ãÐ_,¤ Ê›Y"iÖÓ‚ zu#Õ™çÞ¸ü¹ˆ°²]ŽOAÅiN}2¤Ù—ÍfÕª §ag_P—Ç(:MYZî‚Ìd–k_cn”º€!Ý&+¡îr‘é2+ŒÆvWSóÓÆ‡®Ÿ–UÏzÐF¥8ÐèçzëKmöò1½eŒÀA÷yfÝ"mÏ.2ÃäÅmðnjNÎ'PöÄzn.¶yÝ”ðõfŽ€»í½ýïy "ún7€µ*p»ZÖ3qcµ+…m¡’bÌëä(b.¸mÍiv=r~_ž{ÛçVòÆö#Ü©ƒ¦ƒ÷¸ñ¿pPRÁØ Õ®ÈèNA>$Ôö êò}cVW¤ÛJðr¾HÑcŸr§ÓŠí؉ZËíN˜¾Ú÷o+®V2õºUŠïo]r­ØI‚¢½+\ø‚æäñ­áNz7£dö:áImmHÊY¦íR£ÕÈY·`nÐæ–pÓ!—n^¼©!%p¹«ZE9Ö÷˜îë4+|KØ7¥Xá*4‹ž‰£|¶h§Fh"ñ¨»kyå·d%©\–öd£—iåá€ëæ2¦}ÅÖ%ŸÕÜ]ùŒg? +|zP…~nºÌ·Ó½•("å2¥Y.Å9rÆÜµž3I‹¤L]“{•Ýìu›7«ÙΓ]ŽY:Œ8Iq#@Y¤–(ǰÀuºz2¬‰x—v=¶Úy¦}k}ƒ–Ž:í#Cd±žØè‹ÆÅxR÷\€_Œ|ímqNêÅv©,€.Ýõ_.X{¸ Å¡<»8O¿œ \-õqf2ègSgw"õ‘:Ð/Šmå<öï Cq°uÝö+NA£_c\)¼ß׌S=[ñxó½Ùx˜j°bÙäÒ»G;ª÷ZjušÄS•Øùïs’sÝîÌ×È{=á÷¶Àú9~÷Œø&˜óé·Ðëc&m]w1Àof êqç+ ¸‡ ^æ£Uغ¹m8¥ s³lÎFAO‡x>¯ ?nÔÊ^"€ø½âq«uN=¹œ¨¾<. ( ™7°oí9Ju9lô®Pïwk¬í „*îøåµ’à¹lö`†ö½{JÅ(}IzÊ¥\_®›öÞŒµfæ9lXâÅZðö˜”5-5Ûr 9Ô³«8 h&Z…o*Â3.NÒþwµMPú‡ÔjëÕý¬ãû íÕ?Ù:¶LŒÓ SÂ%Úyû}Ækç*+Óµ•pNz<]*éÀõå\Ô/ø5t>Αæ#ºòÏz¥b;.¹Æ‚Ù§] Ò–w•ûEƒKŽˆf*ï>.äð~#y¬†înð B{׬Là ý2 ƒÁÏE—Rc¿=ðضÏìYYƯä”xÖPQ½*ŽvÚìú×¼|——’Ÿäëòê$þ¹ž>Áƒ›î€[(ƒ™Wn<ý3¦xæÖ®vÓÕ^ãöœÖØðyk—®ÕmÂàO…/=[êhf]ñV,lùDö‡Å˜ˆÇ¼ŠmŽQîÓîû“ÊMëÌ´† •}u”.ì©MœŽ)™’ùV¯,¼K½ÚêÜîÝðÊ[¡¤8{×¼­ìØâÀ€z%çw‚OQ¬Ç{SÛ«G{–¬’uJn£¦û$K‰çך²¶59çcw8ÔîNi,!ºQ#†•LÄ¥•SsNb‡®áœ{‘Ôç%uÁõRðtÌ5+±â©¨ˆ¤|•I™ê›||¶”Ó2rÞÍ.‹`-´Ë;,ñQbåykX†‘Ék#F S—2öÙ.£7‡6EÙíºK™‹5'»—)b¥ÛQë/µojylˆí˜hÈjz+X=ËÍ™—j-ïŸ\ÕEÜÅ V…mJ"•u„èÜ[²ú¯±E;\¢P#üëºéóËèú%ØÜ½u­m(òeæÒ}]ѹ š%A:ðœÝ™H—|>qœWáÞXïÒ½—ž }jŽßGÅS µJLÕ~̼©ëÑ·~{ç®ÅZÒ›ÒÙk{—ͨ3›“¹û¸ òó£lÙÂÊ÷›Ý–õ­´a¥È‡²ç·gºØzžæk]j¯²Á•(,Ý ÜV›<»n²½ð&ëi*÷$[îÈ(\À˹à}£¼ÈƒÚÚ¢—•kÀ¼Hœ:4vgXî8~:O»$sOEWWN'ªï®¢ˆè€I7b—¶òdvü.cckÁyåïJŒê:ì:kÄé¥Ç¯¶`ä¦FUõ‹ÅAä¥^Ȩö/fo¼Ïºj&œ£»4ëo¼]r°wÜfÌVñé*(+­ÙdÇŽvºëè^í#=uu.ëÙ}–u¯BœÇŒ­—ÁaØŽá«ÖâT%ØÒzÁ÷f¡KÆR"ìúÁ"T+Ê®ÚO¥Î¥×ÈìíÌXh!|:¸ Êá°ºU._R)ÎÈ;3ëÐ÷1rg!$'s´a`×"ÉHº¼ðÑ®š·®yn,7¿'*/7Y>{jaŠ¥x)§ŠLŠ­Æq—êTG‚#Ûõ#j{Ê^nÕD·JWǦµò¦:WgdJRÂ- 5|{‹ÛwcZ›¬•wÂ̧²SÎ{æé»:óäv‡pʹá½¼£É4bµu•ü­£â9ñÇÒëöRÁ`Nž›…:ô h²mn¤Ûú;y“^ò]6Õ·u•8PÊØõK7¶Jnúè3o—':X®mìÊ9|ö6æ ÈzÖTÛ”2ñãºEE(40³VdcÝHåõ©})cì­J(§…öc@ñµòß{×°ùͯ=UÚ¶$ªSò<¼M4åܨÊé•ÖgnÐçx«—¤¶Muá„ò(¹óïØ_ˆž_ÍÃtWïÔ üÒkJI°OnžTS+Œö§å맯Æ[÷ÞgÞ‰yêõÏè}ï<õu.Ì =.wu ·ÏžMáÔ,‘…íçEÏŠÚƒ¢$g`tÈmá#¶V·Cü3x[®Û«%sÜ[DæøR§©Sþ¾Óxù!攊Vó]'„ºí‡ ; '\-GCf“F)Hç#°Êyuô¢s8v`óyF–ëdPiu 5Ppƒ ³»,£æ¼-­¦úð îÂÃ^îÈ¡* 4ÉÛƒo%W*\Ž^'œµoF@V ò®KÀuæßæ,­ÀŸ®.¨ì Î1GtùܽëU»"·wȼ†+4û0nÁ—«$”cauÑžL3t5Š ÉÜ)a©@»º¼Ýðo( ëñ´º7é+Ð5ã#݃¬Y§{*ô0«Uïafz„Þ«#Ó&Ö¯ÞýzšŠ†C\­¯V‚›Î{0!•–2ár·xŒJ°Q7žkû®–êIñVº_5:´à |qVØW«­  ²²Â¬Éhäê0õceå:i\ƒå'çÞ†]?uz’VÞãÊ:+•‰öb²Êînõ{_hÔtÆ÷¼ÄhmfU™‘×ï}ù~ôüÿG”sžþl#õöÝO¶ïh[W|†&Òýe~ydÌ…µ¥”4æÔ¦ŽUùnü\ôÞu=VÞ'‚­Ùz»sCt.Êç¹C}MVæ<Ï_YàFñmCwé]÷¦w¤èùëµörÇ4oV×­SŽîr¤Íí©ž¢—¶îJ«W«·{Âv¾z+¸mè× ïdT&¿w\w,Ó”sÖ3Ù®øã‹Ü7ésÈ[O3Ìœ±¼G5ë‚ò*ò…¥Ô=r»b÷8n®À¨S”짇*RÚµëAÝjðÚz=Á¾Ü¢­Œ^ã:¶¥x&ïö ^n²…uŠ…Óݸ’&#³³‡!ƒº–>a ƒËâ)h­.ïI`ðªnôYÒ­ÐÝ­¼°MûéÙôÄR(rMZ%!³·Ó ¦ —/j¦u%’ë›;7«»ÌÛÀ)çuè]ü’íåD*/ó,Qç ¿Ãô'¿m™Ì›ëw¢Êòé]Œ ÚD®t©P³°&%ƒV(£3gVlfGê7®[ª™Â0«öäVSÚ/«í«Bv)™êO6˯Q~çW5ÚîÚ2¹1ò½6ÁŸ€ê(n×°oèõ3‹ôµwµbQ›øå?Þ™.Ó¼–%Ø·â»[õ±° àwF‚rÎ"cÑÉÌ:é›ÚtgEb8E¤m¾º¦uÚJAGÞíUg^ª/±Š³mÙœŠNksv;mµÎ÷9ß Û¼§E8êúá©Oì€_q@»3-(ZŽd]››­¦§¸ös÷½+ÍK÷Öï/µ‚èŠÚÍ|ñG¹³!‚p¢º«¶Ìwx´˜kÑ>T·Ûµ!¯x ‡&Wt÷VÎ]¬ZסS<óÃ6JåØxÞày6²€ÃË‚°° [ë{تñSè_ tÅ g.]žÎo} É(Öm­NQç-–cÑ;×~ÏgHì‘÷½×K¬ª5}‚¿C·oG¼Ï*ý)cÊ ƒcöï›÷¼îž z•yŠll€Öñ×XÅ +7žºs> ÒN_5ë‹Õ•îÊJ³R²V« 5[E†~ÚòxïbÑ—\n•ã­-gmÖqnŠši²x^li •8˜6´meb—uJu›ÀÎYöÆú>Ú\`QgH0æçk ,wfû hØúñpI§×W=yÙ7o”äêCDÛ“ŒzÌ™7 enÊäû/¢©:Ép²Ö{€ÍYOnÈx:¢tÕÙ;fµ¬íp%`MW-³&Ý.î ŸS)vø°ßx»_ƒ×É¥·¾²Ÿ|.w¯oðç{õþÚöÐSÚÎ7@R‡˜Ê¬¾qû>(ÕŒæy,îdŒ=˜k¸d$ÊŽoj!|uß<ç”ðÁØì<äâÑRj®ÕÊÞPjöÚ[Z+Xé ýá‘Á]y¬1­œÕ(PuÄn½œ/1'4<ÞóKÚ+µ€¸Uû,éa>íy-ì;¹ ~ÒIîy€UоnÕ¸ßkêKÙÞ¬¡{]äŸQÇ«ìm½n’æ½´n{rWsâëË,UÓo+±Ðà܇]…”usÈo%jN@dWM XD• ™›(n@ؽÝWMrZ® Š4eÛ|P½¬Îµ) ŽÎ6­Ó·¡¡…âÜʶ5ßewdË׸6½ æ]¹B÷õ|©¾ô’]áH­¡zkZÿoJQ‡šÛ !áÝ¡&p›g[ÉÃ,ÞEXþ§GG)YôZ»=;ÖÌ*ÆåûY,ÚB²™>1“à­¯bÌ›'yw9iW[¾QjàÊ-6ÑÖ¯°xç c>Z·-Sžk$½ÃoT®í—;{qö@×ÑôN0zë Xp/^)žö¨L PU³ƒuÔÆ×–× ÍpÀôèiœÓ¬1,LQ¬•Ö Ø¦ã ­r„@¹\¡«Ë7Ok%[{Æv-§jK¬“J•ÐB,«¾+ Î³}i=®•î*ñç3µð~¯7Ûp^ ¸>mçeÚu1?“7G;3…1’=²b¦Ç [Ö êÝÅWnÙ™ÝåoØaâÚß!¶(Õì­7[wz,/^ïPØ<á×õ^‡M†'S‡;ñ1`®H„èûq˧í}c­®Õ‰®¼©%6{YÃ;ªÌ@úÖß5˜Â;ðÚžQ&fUÁ¤ò±ÙtœÝ¡Ôgê×¹^¬Ü÷ñN Ît—p/èŠ<ÓˆæôgL],ùùçDÅ{VÞ{¸œvšÌݹ[»Ž•;»”û<ä{Á|'³{HoK™ipËÞr³L‰õÍ.øÁ½•ä=Î{Æý¶›Àlç´\qrÃ:ãr¦½2Ÿ—e9™à|! mVÑTü# 9G¯uSzðhÂæS‚7+G§°tÉ;@l"P‡,ÊÁ°Ë5)4'E‡®¶Žž›”å#DŒ=Y\ï–SÁ¨|h· unuÈÝp•¼Uí±%=¡‡'l žR·½—„Vt(ÚZ÷y°Œ©Ö"âŒô×#O»2ç¥ë¡'®NÊyh#¾s©NÚë)ãkvI^”7Äç•z'{ÞK¥;¨öëf›|€õ‹øÇ¬YŒÅ¯Á ʳºëqÿ(¸oš17ë«ØžDÕv#'áû«˜­žyBhú^ëÏX_%òÇ:Z9Ó>\Õ7•‚üßI—C ˆ*òv•¹jæ-F¤Ì]ÞT7Ï/ M`þQ®ÛŸßGà+žÃ¶é[>Ð2jœµª+¶PüÝÍ7vnyYY®)°ri–†°KŠÉÕ–›Xx­¬UëâH€{|×O²½F&#ëéržOÍ?{SÊõèä]^o8eõ_U*ãbö•ª–ó…–)³iÞœK3žz`ͼE©Pó³¢Eyuµ×ÓikS&{¤‚Œ•ÝØs˜ÀkL’œZm¦j(hᢹœÊ'²DÓTÇy'aã –^~Y/^S¤´^å;{nHŒïl÷¼¶ý+Ö7Éf^:YxoQ]ÅîY³Ÿb:1†·¥Ô\;"²s< ÖJÁ}Óî£F¥*?Wò¿Åu^ýê¿Ï#Œ_æ;27gB]Y¨ßÀ˜X|gÂIÔ¯vx€‚Ú\æÇ·tã¿få_3S0ñVcwC1‡]ð¦+ϳnü,uoïo“§°ð¤¦[›8}Ñço6,Bôv•*ISN—®LCWW-Ë};<½%{+ÝÞqÎÊJo.y|Òm刺m. !9á!q}R—vpKq»ÂñG!ë®6΂j+¨Ä°Œ ;;Ov=‚‡R±b™5cÍàÚ]¿Ct11*mÒW8² е†G½Y}[£vW:båOC/³†Üun;4Xäì ´E¡/föWº¼ªï=ïTX/V%ýUýSßÞT8g®ŠšUèZÁ”q¡IÜô&ØçÙ.¬«;BxÔ ÈU÷ ÷¯EéÓ©¼ÞZòË{+s͆­$Mº1õÖäMö›$ÈÜþñDÜ]s'z/±ç¢Ý¼Ï+>õ=’j£»îÞê˜ælAs*ÜN\øól:[ŒØ9¬dA„YXH©õÖM`)Ûµ³®º »ˆ,å9q¤,“9-±O¨ØRÖ¡2‰äØ¡{^Šíëç°3üþWê-Å¢´ÿ_ïÄyöén:„ÒHü½Í]éÕ%ºG _#t Ü™þÃÙÑ@~"½Ôì°¢¤+VsÐÞTwÞa®zdCí+n*ñš›*vîéè•ÔûîÔÊÛs´Uà©uv²'Éܲ£wÍ ý·÷]%ìî^~vú\éxÛ¤/C[7|W»;جzGä°_ÁÄ»9÷#è}á~õ‡K'¼ZleK¹«fÙä%Fê°«‹HÈyÒ—È,WF•U’´ô8žÐ}“c~öåIÛíÛî¶<2¶’})E:ëp¬XæÇ|+ƒ@— Ýs,Rê‡5ZÝÙÜh0µiø,¤%›oð}ª=7ú‹–my ‡l'ÒÙñ¬É7啠⺸yw!|øÑ¾òîð³|*ÕŽzºS¯x÷`9³Œ%ߨ¬f2Ó¶)-%;”eq˜.sÝG¥Ú~TYpt«‘Xï5 Q éá­ø±\²ó¬Da‹¤fëׄßw•Gï,¬Ú²zß OÇ@Þ=:jØ•V—þLÐåZðõyVÚ‘ðã†ÒG£DL…v3Rà9ŽòûmÃ9r Î^tJ›1èuݲI¯H«·R¡îUÙ«c_–!9õ·ƒ ؾ‘¼ªNc°…Dõ¼‰DzúeeœVÍM˜èkU"H6’¦QJ•ôÜbDÅs*zRÏg®çÔŽïC„¿tÌ£NáÜ_º?®³ò€Çn{„ƒ“ÂoHVzÞ·[ì‘ ÚÛ …EESw£¿N¨ºŸœk˜ß ˜ÆÜÆ}£^¾¿užžñ?>m·rW³– ‹¾†3»€ã††nw nÍ£&› ž÷¼¨o^H®Wo‚9vW\ê*î倩íj˜÷±ã÷Y'tžòÏ¡¬ÁàUªÜ\6ÆøÒu‹ˆÞ¬Mzñ¢VMÔnÈIPÔo7s™[­ZßF}º¸wz Ío¸z³µŠF¢€ß½™FâóïxpÍÉ€!Œ—˺€aŽÎ±|¬vA¾ù Ö°Ö'/VTÁQ7¥š¦Ï¹­àœ2Jë)^õÕP†¸GQÚÉæåäW¹k·¶é;p3O2¯½’zÇxzJÄÛÖºTÀ©=¯ ŒðržzÒéwa~5çÚbÓ¦ð9xÇ`‰³s˜:§Ž+¶ó¼yK4Aå̳۫v[xy`°†Ò—ùmhщ®¥]¢ÇïÇ{·zÃŽšÈáÖý{[­÷Zú³m½»#M6ý7Ö¥ÀC¯xøÉ…úÝÇ]§×aXxË„(;F†»ÒNùd;;5ÌáJüùüçÖxè’ÜâCv:Úñé #¶R•táZC²¶ÐÏp'ìp€íc©Ô:³±-WêÛàÅ÷. kƒKn ½÷ÃPp©Á/\Wˆ3<·©R¬lfµ1Ì–µ|®°RáH›wbìæªiŽ—É7F¸ôX¶UJΕ™B}BЙÔ3EnE{Ý)+:gAçèg²½v½Èšt+¨¦zñy6›=xé‘Ì cNã4,DF·€´ø ‹\Îïz÷Ï óïy9nŸS…êˆöî÷Îkv+´ Éjsôœ_a,*lïˆp«ÍuíèóžávknM/:Ô4[Èa¡Üû”쯻•¬Ü›”dë#–Yë?ÃáckiѬ¯Ÿ—º°ô^¥ë¿‰¢¨».auÒƒr 1ó1÷äqw€In_%¡]Ñw–˜¯nˆ]5]¼õrë¾ò¡Ÿlš¬qº>/×,h:™6ýqõŠYk2ú’{:㥵½{ÎeFº ¥)îC¶ -ÖÒ™óÖd«wqPQjâu‚d¾ ΤªLÀvrÊfušLR­,;™,¥t²ö½nèkÈ¿GÔƒ­)ÙhBê|Úr°]ŒÖ ›Ò@«Úh’‡oº‹Líýž×#t}WÛ͸6-Çm*%ö½§déí˜Ò[íP㞦j;õ˜ˆvÄ£r·ob5Ü\vïS»ôôîai9î3 ø‰CÛðÜë¾f˜g9Žš\­çl`Öi+ÐÂÉ—£ç]Dœ™vÄWY\çò®C;µÔïnºw-«öww@ïb˜åÆ ný5}øW½é™ØeÒ:«¥=ÅㄟÏwŽî€ç.õ¾‹«ÝE£J®ëÊ)õܯNÇk/´g`䱪Åã‹°ey ½ yˆ{|%^a÷[bÀï%|â®…©£CS(’o„Iòr…#k Ì£H>”,Kî_‹Wwعî^y±eœiX¨*u•® *qÔÝòêŽp x‹/ʽÃXO0K7J#0ÒØJÔÞ¾²P³6ð:Úr§JÇôãšìÐÁÀaIIÃÚ®°ëwDB«`ËÆž+hÐèu]£Û™2÷’³‹i;ʯ“ó5zýêßQ/}µÝJdA¬ÁêNóg Õ¢º1–§r¹±C±YÕiÞÛÉ+qfuÜ•2‚ Jq™Ï£+_,JB¾æw;ÎFbÓL‡Y¯¯P­ö–k}æë\ìÑV›aëCÛ”4®«².ð‚ã••¡à©¢È n¸ŽÁBÙµiã]#5àN‡u›áîYÞî°X–ûÕöP0æ÷§²*=nŸB¡PÖŽYF§Àk­OÅ6ErÊÝÓ]´µf‹`Ü=W«#j)®Q:ºÁ2ÞAݰnÐØ#Ê ^V]µ]›ŒwÙ¬Œ+r ëºÐgœéí§å=Œë{GeñÂq0Ž.vJ7†ÑÜ.âNîæVæV„-¬˜Ê:)Cp·bò™æE㇯­m§—”A½»ÇSk± ¢Jü¡§@åoïÔkTåhû7ëé0°/(—Ù$ñÚR®®ël×X*±-!0nnŠ \Í[ç7·gΆs^¼™mׇ,{tªøÃãí¼·‘Î…Øjü–Þ¦ê~ḐôöV[ZÚ –Còo©u-]ÝÙ‹¢]F÷;Ùko‹{[p/cøfjÚyèˆ8]ºÕ6ë1¨àøöË2Œv¸œˆËîB*è髃.Zš‹G2¹šmT×2ù^ê:Þý†.>2hN߀’ZÐÄÞFúÅ5L˜·á²YŽ?n€ñ:éi vhÜ>ÅÜMá¤_rOÿjgîû†Pì>5§²‘íú)yûÐìOŸ‰—çs×ÕÆ£êÅ‚´\êðå}ÕÞÐwͼÂ]z”^}iW"틘ÞÃâU[ê‹}Þ×¾§^•®üi˜ƒéÝà¬yú{£îÕ|àƒÂ²ƒ©Ò—­YÊЈ¬—GÓ{¹çÝ.†vîpµj7Ëí(]‘¨Õ„/³åóPa±Krù=îÐÎpð§ KWêöùÉÃO…ÉQ>«æþì? ff.]è×m{»!`{v¤Ê›Óc­ñXuõ-ˆc7®÷¶®±Rj;¼E%Ðf¡L½œ4W)\DaÄ-Vä¶ì`e9ÔøÍ²§ªÝ_ÊåÏ¥>ÉÝs\ ¤Ç0•tSîÒÎSáA“ŒB[˜/­U-:ï>ÚwÛ‰£r[çOÍ]8¨cÓî`JVæ[Äjߺ·sFEÔB7@(ºs!€qŽ©{Ù{]½Šé®ýìÃ)଻#ÝYç P‘ð¤s á9m†¦Fpq‡ mW( òÎí·ž¦š·Y¼†Óö;ÒY€(Vzëq ö¤­Zu´KÛ¸Ñ+°ù¯PïR̤¢ák<"Š¥[;b®°˜ÖܰR›Ҏelфזi)uØ^ :¥ÝC…'t+os%v÷‡µ³^!KÜ߽׿}áÌ¥·ëYÖêúêÏ41Eæì«yœ¹8²‚U ˆ¡—”–£íž9B{n°ÔçxUGr³åQRëfÃÃ`ãìÓíÅA`#kæêU½Þ#VqÑŠ|·„Ãw¹Ê^ÊMêfž“¬Þ˜€r¶Aaà•Ì®}yîKid~¾ž?â2°]ºgã@µû.Ý+)~®z®‰¼oÔÆåð©ì«æz ¬ƒ2uAuì^êêç—Ë2€ôó¾à<¼ [®Ú*g˜MØMx;bœu}}©„ Vv¯’Në#•8Y,ž]Ù «­º= w¢Ç;¡XœbVÕ·*]äµW‹Þ·+…š•1iËÄ|ñò½ÁDwˆc¬¶ë=„1Œ «MrG;Ò»Q¡ñz³‡©õ˜º@Õ›æùõ°èbn2ÝÖÝ!ó`)”²Î,¬¼êíw  J³r<ƒ_øáVc­ûéHfW€£Å"±óc]˜ªÝ”}¼^b¹#;’ùYÓÖ´µý‡{Ý ÑÞÄÕ=J^—ÐϵÒïR†¦åætȵjÁFïÜémJ]¼ybÈú++95Õ:öó²f -›–û˜æÑf¬ÁµÎ­äÅw0äþ:˜*W¡×ïwí̵½²{¦Ô®Uˆû„ ð¶’63œˆÂO¸dõ»=µ¥+æÇŸt7åîUÉ—ïZ­·Eààk[UcZ™Veòb”sÖvýCXMúɸÞÞ‹ƒÅ»*½”}®ðÂcž»©Ø(íý§«iL.âÇpϧ ÕÇÌ{JwíåSn§y÷P²õxmh.Ï+¥c"ö6ÑAò=±weø"s”•Õp óß!bèî,­(®˜—Oìƒ@Ú×'Qðõ3\ŽW‘†oø^}ú§¸Æ(°ãÛj~iÇÄ6ðp•|ÇYŽŽÝ5ÈqÓ¾µÂ~9î 徦–u’îxûpöV…Ó#§W™ó¢­å14ć²ä×5môQ!CÞßjº<µè˯,JU¯®MƒÛ0ªìõL^tõOh÷–õÍ^y¾bS>’‚¾­ëvpõ™¿ Þ]äšYã¨ûRѸ8VÀô€8wJï4½bFëNúüCèÚ¿wmM!@zå7g!Ï_nq˯-'n—©Ìýž;œ-¥7²Œë3°0·¹HrÞûXÎ^Z¨E,Ú««6> 5 yÐæ…ËmQú­Å+R²ó¾ÎÓ}ÀL³Œ¶šé­å´é˜f¬2PêJ¸3Å>ï?=¡´Pß{7r‡uÞwŸ“õìweD{Í*e¾Ùë¦åN2Zí„VÎã «òê»è=é>Á5>.Ì»Òw- "HpÖÁQ%£°?’§\•îmÎËG»s³Þçëo™Fg,Ö»ö q-© ~Y]×lYk^+}«µ¨j7¶3ÖŸWlÆz7õžóVÍv^|3©b}µÝ-âËr^eENr9-ï^Ý×6w*e5»3nXå]~W4i´Ç+ËßRÍôv¹8**ÌÒ²à¡Yœ©—=ޱ!ª BeäÄB;œZŽ_ÈG¸ú)©‹+¤¬uJÙà†qšè쬽7Av`¼§yƒ¹ŠMô™ƒK¦Í=t€ÎͨvQŠ›ß4C®Õ©@œao·µ7nϵB[Sµ£v®v褕ž5f'•‘øMåÖiú·ÊÕÕ¸½Cí‹oU³qfȲ‡: ”Ë\+¨X¨Šy0éw™›ÃÒµäÑìãn»#çè÷Õ”}H ÞÍôÚöšô£ÕÐ Æžu¾BéæÝkIEËA€•sªÅvyÁYÈn&×(;;ïÜã™cFRxëÜÛä€>“¯wŸJa½ëæ®­˜³ºõzú>¯W­Ù.•8F=Ji ±®Ä»Ùãâê¾W”mº-61§N} 3‹KŸê¦oäžsg®± Iò®›ÆÕlÜZþ5nóš”Ô{ÓT„Lp3ªKã †ZÈê:j€²ön³®¤ÛæÙ@nè½Rùi6ªáîa²¦XtnàöB®„´ðwÑjvðvÉ·ÍV]Ú(nÞÅö=ŽàËݧYòè<• »ö‰oÛÀ‚mŒZqÜ T‚ŽæÒnzo…<ßu¯-Ò^D<šÐ»n]jOyS½ëÀÔäë6ºÏYuŠå©&§YF¹¡¿+W½Y`õnÌC`®¬<¦Wu GÎÄï2ýÖ< /…m Ês “gìЊ"ÆÖ–[|ò+”¦e#¨‡5R…InßSÂ4y/m:Äq Î2t*-à%°–ve Sä—VÈ×*åLÞdÚžÎGνNõòmö,‰ó¡]\To1ñúÝ&{‡¤2óº’«\¢ÌYÜ)UööXmÒ™É_C›¸&ÎRPÄÉœI¬ç{•3*ÅÞòÆ1·”:÷³†ãêá ×XÏ´x ö¦ºfN¿¡ºTÇéY•˜W~í‹h6j÷9ìÆ£Ovæ÷V¶›w…#@ã)Y„7Û¹¥ÊÍÌYΔ¡¸*ï•#ŸJ:–”—H2éVÝ‘l³’<¢;§¦ž}@ZÊÀiqì•wYo‡ªäÛbY>ð⎭sû†?/cþ·ñ1ûÕ=Z~‰x¿·?7êý ¼„wåbY9ê—W[%6oxëx~d=ÃîÍIí}øñY9ï7wl¸ËŸ†`A.æP„¥¡°Q CO¸¼’Ò/Û’ã»èF«QP¦}¨TVw+ÇÕíc-åéèÝj)VD^毗»Ýj7(ííû=’˜áÏJÞ0¶¢»YÒ—;Ô+ÜÔöà Ð=, y’­ã˜)xï}Æ*5Öpáh¿d¦?µûññ·½ûñ.âÑ4* Bê;žé¸+y£9ëãSNvÎã¾Ô]¬O“%0y(ÁZ¯]sÓ³·Hù®çÝÂks‰ÕöæÔ÷DmöíËê·t61Š=P|jgf•Ùéo씲çŲ:Ë8-,ê;mÙ=C”ÈΑ†”eÖ—ÔËie>JÙ}ñÙfÕ«wÚ›ÍW1‡bRì{;UIF÷«3 ‹='m¼‚_ƒzФD"qêÉ/t ]™Žs:§“º[ù]]<Öá{—ÀâLͨíçxnƒ—™Wá¥<>ÕÔëÞ§[W'ªCc7©Ó¦ªáª.ˆËXø*ÆÀ+ŸvRàh©Ýºo³Ž–wµòáÕ‡ºúÃ÷,)àðJ*µ¸ÎA¡'Yd±M Ìì‹„ û?ç…mVÕ*Ê~õ¡uý¸¯¬zèÌê´«tõÕ‚uêèHYš©#Ò¦Ö›á»Hÿ6ëÁ@lÎ5u&ËÊM_ÚÆQ¡²¢§Äòe/X¦ªä³¯,ôí8!œ»ÙÇf»ÈrÓ‚»V{3Ûç伓õJœ™LΚ5:ÅDzu;κc‡NW.ÆuŠ”@†µslÕï(:x7íºck¨wE¥Õ£Ïw†ØÎ*ïÏ­ ô5íºµí¨»i€“Ì\ cz¯h«zÔZ•òs;‹³¯ÝK+È:õÝ{>ŒÍrKñ‡ 8gœg,½Ëã|„ãÂö íî÷c³å)/xJ„ÀátŠ`ÞC¹l)£zÞo—³[×XõðÉuè’WäzçSÍv-÷UîKßO-ó¡xô'=ç}t¹|PËìњŭò¹“Mð²Þ›®¾.ù`\×;%[Ckzn„¦ä®¹}Å÷Iw¼_B§»Pmè¾êƒÍ¬½î|Ø×È„J̘» Kj>a¶=˜]@ãóœn_…ÈFª»ÛÀkºdÍ ”ŸTÚ˜º½ªç"·¼^ÓöÒ¶øó4†D†c<ÖîÍßî£àʬY”‚ƒ»Xå^­|ÃwwÓ‘•—^Þ‰}îó˜Ý¹»àö½\wÚdAú²ƒ–æž7xJÊß[õzfݳ¡ªà±pÕ•sj.5zéM¡píf³›8ƒK4n~¢—îFwy ÐÖÉMçë¼ñÚ{@Zt0õNhœº±Òî{”­ ¶ëzн~Ïzº±‘EÖ©Œ½íÑmÅæ%¿±)ìÔžÚÝ}Êͧ|æ_dV®ÜÞgk%öjtˆpâg6î(K}˜óÑ{P­“½ì½ØI9\~°Þ®æi›Ï¶‡2ß=ê­,c©S µwÛrHv6/’2}9¤ÈùÛ®ê æ \!ÃYC×Þuæ×ôCy¨ûÜ9lÉ?múŸ¼{Õ´Ö…?/Õ“Y¹˜J÷Œ_½ªGï­.uÃaô§Y…l"uLe3ֲ͞ûF 5cÆ!vØœ½~ž÷»Y÷Eí[êÊ?¨ôg+² åæ—kµ°&Œ½Öx(÷Ã)Qx¦Æc:âÝÀ×7.Ðó©,•Ò•ÍÇñ^ö×La~åNz÷GÝO´*}j·©õÜÌ<ÃîÂCÚ9Ïv0ºùÝ]¹>œÊˆ÷UŽº½–H®oOÓÇÏ)õhv¯3}uº>£{z¼]½îÑgÏ״»ïW-$Ôåf7·i•¼òþÉ¥Œ2Ñéͽž½=íèrüÃ<¾ëuí­ôö¥×äVPT™² £‰â2ôKV]ÎÂÌð$Ãñ ´ár–ãy¬Ö¢íŽ­*PÞÊ}©Ò*LVû ÄnÕÙÛâmìíò.µ9 ê‡fx¬uÁn; î¦4‘4:÷1³“Þö`áÍ7Z£.ðœÏ:1¢ÌÂõ|&Yz­ÇæåuWÒÆ'çeÞ()“¹+¹Ï®¢ªC\X5]g!bç±þôßÚêÈK‘“Ë£?Œ=o1jš‹RVü´ᶉӬ’²‚a™Ü´öTaT Á¥fÏfã% ‹jgÆ¥H“âùoVì‚aÕ¹Ê%i›bßnak¶f]F®1”°â+²gdpY+´Üç¤,ÜœAtpO+©nºŠaö¾¡Ã™vL×ÛŠ¯¦Áɼ݀ÛYÈô-Þ×DE©K¤î[ØK•ƒ`p Š×¼tØæ.—.Ë2+Ñx´oóu–.b•»™Ómg¨«ÌT*&ÖäAnìûn€³¾Ì8$³Ðö÷šš¥[™ã”»Ï|ð "b´Ýˆ°Ã&¯ Ê;=tô ®¹±GFìv¯Y—/Ï1¡\¿{=>(A¸ë1L+ ¬{6›ëaç¼JXä/ß{zèùç²ñÝ4Ê-¼ÚÓÇ7 •gÖêú±ù(â}¿3'VóÍx蜳:ú@{kˆÞºÚήoe'ª›x1hG] ˜úø€=ÚN‰D`TEiûÈ… Ï{ŸjÁ溘¹‹«Ûƒ«Ôª•înš½"2¨Q’¹¨<|Eˆ´W‰„EûÏ#ךðktÄk«¸á¦¹ 6E¦`¨ïKú-M³yd\Ævóø5Reã44¦tNÊ ¬¡ehŽ—T\ìÍ×}W©“¬Î««4É”ê'WËM‰°w0ímÖ6ÎäѺ-vdÌ”q[åÐW¥ÆT:°Qèiïb^W­U³Þ÷R­ÎC/—' ÷D<ÝbÅ2Õí»Ëæã«:P”ö&ûhçu¨&G*;‡³±Òˆ[ÓÖ*ò¼Ç·Ã¾CØ4)k»¥W9Lû•âš” M™C#ÃzI=¥:×®÷t…&¬–æN7£leÚZ-Št(9@”ºW#ì”éãîÖl^&qØHã•6€Æ¹€Çößeº•”ò­yÔ;f¤0(tÓ8DÄÝ@ó)n3 9|:(é‰Y›Æ‰¹»qÕé”xu2%å àBêæ§c¡Hgêv+erÊUýuƒ¯ôù~Ÿ©+¯ÙÍZŸ¡œòš˜:T¾²³eê)Æ•ÊÅW—\Äûev9üôÞ`bp³Á»!çŠYfÕ¤0oÑ-"D€.˜ô~à*û}£çDÔΊAê&×Ý~ÓÜ׬«ïMôÈ‘s±½4~=ë°ÐòÀù{Úi³ë£Û߆´²ý»UËÕfzO/©tëzvó9Ô“ªYu¯´z+¢v@vmMè|«Þ†ö¶7£J Œ v“hAǀͥã]êìÛ>‡opéÀ<»P#§+qg ‡M2cò‡¨c*}j´¤Ó<:¶£Ú}»J°HI4åõ_[”'Ðý†ñ*wG '«^óå¼ Êp²*ùíØöûØçWƒËšâö'ä±4Ù¹zµÀ»­ˆœ:ozå¬©ä ŽjúМ\6¶Þ¬Û †¾ÛwäIÌêÛõ;cžË¥}µÞUȈ¥lɨµ³I5°/WMå¾@¥Sðïuh~Ê ziÝ£X ê'„‡Ý59æ2sÐ|§¡µŒ¯]iÚÅWä˜V…2èÒ—éknôîüð#(7ò·ÕCph‘sÛ­ý.¥®˜ˆì¼ç{ª×[Î7JU‘q1˜eÙ¿D] ×·ø¸=^£Ÿ‚+k1A¯Cp²¼zùcYDa¹u½$ßW…!v:ºýÁѯ`ô¨íÒf“ÊÛÞ£ˆàÝï]Su°ÂÊU„ ÒûC¥WívlÏ^)>J8v®ì/YÕ¶±'Ý[t.—ªØÅ^aæï†yEW¼X#º³$"}-Ížèè Gw·(ø_Æ8›u¾UP„ã¡€ñ|_võe[]<¬¦u-èÆao^9[z:»ƒ•žËXš¦»VXCÖ{Ö;Öêû ¬uoÂ’öÊy%éRïÖÇÁ¬#}·A/z ñ±G¯¯—ÔkŸ¸ÎOzxûX£Ãw…óò=«h˜°¼¬}ÚßÝQ;Lóëù¾k> ‡VÑ£2KyR‹h½[RÇ qTC¦Ûc’=7rUðJlc…õ]iÿmT>£¿aûÊ[Î:óðt‚ƒq¹¹ÀËâ°7—:fŠÙØç2¹Ù ŠÉoXi>­{CõÔS†leiwƸä(·²¹¾*V¨oÍh‡VÚ¹±Š)%ƒÎ/}—fÅ÷‰öð{( ˆ¿*ß,Æ 4³kÎN¼é¯x ÑľÕ~¨¡Ì‘!,×{4k€˜u`xú÷P“ {Éý!µil£õàNÉöìaN ÔÝÈCXyÌËБݣ©ÓÛÊçJX¾†@Žæ]ÄÒ4¾H ƒhsË}cN‹r€ŽÉT;ìbÛ0Éòöûlý†ñÁ¾¼ òJ«Ð=RçN–•\8º3fìw»Œ<5|¦Ñ;ÙÅ ºlÜŒ#׌¢Vƒ´ÛÛ7AÔï²g¯ä볇¸^íé ä­¸Ö |Ü7¬{Š´`¹ARnžÀ€­ ­ŠŽ‹ßZ$vÅ!0&·ýgéº:Ò•›áB¬Ögèkp}¾Å]ÄŽ»ó¡¥lƒ‡~Sn?tg=â¬9éÒ Žñu pNéÒ½«XždtÏ8šÇO—®ì]–žnf·EnÀºQêch¼€W0ök¦>ܾä[Ûµ•‹šÝêtmj÷v„{‹r_›Ý±voʤÄ4<é7©GåØ{z•Z ˆ´É¹zöŽ$²tûe.ûÒ·íñóoŽº¼Š½1² |èVo m=]×ÔÀÜÑמɸ*ü%·»êBw"]›:áÌT”½ýâúž¿YÒ|™­'ØâŸmò•ÖŽ<{^UºâãÓã{Z]«lsÎá› \Í‘KGd­ëfÇtœkFrÕz…ìYÒÌ”.ð0°ðæ@ú•]ïéÛfê+ÍO_f6üÆç&.ʰ'×¥³{{hœ§ÝDbY†1Ь‡:å;L Hë„)f±—ªd÷»Í.ýà_¶ òÝNÂUÉš:ù"ÌŠl”z/‡lº&ºp—siÂG.æsJ#‡U5iʽ]ONEt*ެ¨ù^kì¾×ˆ5ÌpŒ<éZ¶4<¾æ}wœìaÂj vòØòn¹Çݦš$n»fŽ®,0޹_eý{)ì{WÄš6gJmÌÝΔ—Wg^LW”m½Caߢ0pê(ÞöÈí,÷ªEY…ßq¨wp¦ÚÅ2+Î¥Í,©\ãmìS¯+o™Y5ÖVô@™éÓ^âXD ÷jV¯¡~ÉVF_U ¿] r{²u\Ö>TOŠìíNAϱ1À`ϲóqŸW5t&yð„‘¢xuxM„2n­ÅIMÞÃÆF¬à@Îf_²çx< BÙ6>'´‹áytǪáêãÝAµ¸Qz,`Ð"åðhAÏJ©rïˆÖpŽÖJ,h(R&²¦ñ™ÑW^5oHÒý.¤•agiÉËj;õmŸv ¨Z«ˆPVÄIŠv”šŠ»J]{*åÚœ(e5wÖÕ2p±Äu‚;Ô„e½•n2S_Û÷lUè{K_oÒ¢ÃÓ5øXòxªÆuÈܰý(FcO†»ë.„m\2äÌ£j盕WƒìßtU8¬X0e- OX¬ã@Æå½ÚÀzn#³Š›fRë¬kÝäüFjµêö/uŽ2V¬™Ï6”ŒNWE‡K¶êK¶Ñœ‡'*儳<}Ý`÷­3|Qó/Ý©ñËöb±­òæø›B»rØjR²±õú…ô’­òçfUà‹Æ²{”äéó,‚çÞÄëa<’ÃhÌljh‡s¾SÍ:ŸqòÁ¯Ur5Öã¤ísÙóC_f{£Éæ³bñ^"À€k©#èû_¢¡–§;Îtò”<¢Šúñ«±Íd¨gåeZ4x§×b v:®Ê߀™‡!ø‹¤uâyDmJAŒI$Ý©}ÞÞ¼²†˜õôw’xá*—=Û5:½/zj·ã6—¯æÈ.û©šÈ/zñGcžçBæoW_Cõ%ÙœÕ툶ö ë½ÓÂÈc:‡¯Ô0‡Œ#d˜P/4’ž¯JËšÅîÌ$öÃ5jîŠ–Õ ;ªÃ†ÆÊæ_;˜%Æ[½[nÁÔn ìšåv±Gi®¤•5AÒ»•¹Úkm[¡F†§“®Å~š´jÂÖ(MJ,tMXmûÇ2ò­Q¬¤wç [伬U黩ÃÞz5\bÖÓÆGÙê’± *±ÕŸò$ñŽ õ¼ºÀ§4yV&¯+3yRÛÝO·4ȯ©íãÖåÓP@dðy§®¡î¡lÈì(ÍÎoÞ:Pé^6)¹~öó=¾IæîᓽÒx¢wÈ!ÎòxB²Á©xß‚s¹V˜ÜÑY™‹nˆ=Ê#–Ø=¹¡à®7j-®|ýRřܼߗ®{5>rChrÝðig,Ë\GAÝ%´&ý˯*ÒÓ[om»S»®µrR§Î݆+æ,[ƒíœýu´x]ÙZº’¨ñn,ux‡Wrr B0>U{u•øÖþÚòõ¦œänÏî:W‚g—i*#1·]f•X©Øðæ¶ÝeÒ:ûxëNpó“ʽâ;Ø) nƒô%ÛÜ ´%fÖºìx_ ÛJ±Új†Ï+Ú]wG˜ašÈ´çµ·d&F¯d¤¾°¸›P v^¬=QôDÀ÷,nOŸ7d^X®XbÔ¼ •Xގ朘‡+RbÆl^v ÖP£5¦P«o:ƒ[@bÁ¯PøBþ{Z;–s¨÷>¯L›é~U›<ú7:Í…dÞo:V§u´3['žhÍ®¥¤–¹@ïµ¹ ÓÎó²×´9•Ö=ÞOzEà2]DOuÑÜ4ŽUÑÄ2TƯY®ÐéÔ‹ÞM¼´o›¦07ÔÕ´0öb@Áæ²xAÙüÜäü¹Ž¥¶(•tMm×îÛ;]¤ìJÑs¨\åS­-‚ó,G;”¬Âå-k¬]|ÅmYÉûKc¬ªB¼®’÷«AÙº®¼ëµ£ÂÞŸvXu'_[<¶Ý W «OVªö¦HUë@zÚ[êïØ\«€XÞ¬[V÷]Štù{´î¨­þí`1<*RÍD‘ûóÊân¥ŸÃËoW«w">júxDµ‹ê×KÇq§w}•§CS,ªäýØœºôõ»»a¤@ì ®Û}‡Œ‚Þ<«Ó\µg¯9z¬ÌèVÞÏ“w[iÀ,*©£0ßR)vl¥ÀÆ×Xˆ•w-Pd8|ú›è-É£* ä®jÏ¥vRîÍ;s,rd2ÐVI7cQ‘Ý÷ð›pMÊ|ÙÌÍ%÷ Ät…6[ªú¾º¦™Ju•t_@áÈ5_q³5:¾ÓW[ÂJ5”× Ê‡/Š4Ô[.¶1JjV ¡»·H-ªëÄS.êh³W‰XIzrS;…)ûÖeœ¯Vq=­V[¨uÛK›|Ô!Yç’NÓšgyb¼Õ‰c/q@¢©•Ë\§ÕÙ—ëíôb‡n&€êÙ¶†ŒŠ)ª’õf\æº"C«E\—]j9·b^ý¾÷k“‘´/màÓã»eû«n¤Ç¶L‚½H:‹06}É!{3D~^Àfw®IR7BêO!^óT:½cí½k_‡Z£öƒ½/åbú˜Ð=Jóq„ÚV^ ×îÝ¥ŠQ‹n"x<¼[,&:ž7P¼ÜÏ¿Ê7b*ëOŸ›Åµî];™ö×R=Ä_=ë½ýi€º÷½˜‰Ù0ye*Ř­éë[] z”¦tÖo‚Áx|²3Â?/q}—:ÛÛy¬‰Ç·l›H@ÞÅëWàð{ÅöÝ¿ŸoÉ jõ ©ig®°Å“{§pAa¨ù[•ŸDM”…¼”k0ëD¾„å XzŠö7¦/Jgƒ\ÆK‹ªß8k^iÖ3„ÄWŽu ä^¦Èótˆ¨¾œo}j¿R!à©ZØ¡x#ã-,äqYÈùèºÁÄÕíf±V¨átÅF°[´¸‘³pT¨&ÛÓ ©]bhéI×Z]D ×ÄéƒÈ‡ÊÂKè ­L8´ƒ8q}}ºðïJ®8:òwêç7t,S½›ù¡üñö +·Ò‡]ò¬„à¥IžÃ·Mªß­ˆC1ZS,X†¥!2\Šºz²Š»—bzŽo£ÓÙ~ínL[å›Åê„V–Þõ6WDÚ»ìr¸O•­«)–Ä(5ŒS—:¸FÖ=¾t[ šUâÔÊÅã™Ëͬëêìî›|Hêi…*åq„…±$•…ª.º²I]2È­§ß\å±`miÜO @™ÔêøbÖEl¾{°½É—lî ¥8f3|Þ }Ý.åòŠ¥‰i /–íZ uéXðÞ³¼<ëÛ—éd•zÏY8îAe>픟Ù’³%ëÎí§Xªæ—kî°º<“iZt殜ue§ ëâ\«unBÀ.Ï ¹}ŽÝïwxÊÃ|W7ÖJKBS×Ôa´&™ö w9Xc%˜rÝ÷1åÖ*ˆÍÅxÖ6èEÆSÜÒFšŽÊ7g: ¤ëùuó\]ˆ0`ÆŽß}ȱÐÊÔ]Yê¾Þò®tL°M°=s¥7–ðÉXÅJf¸YõEˆ‚µ<¥¬â(>H í[¸_J¬U¦¹k•ÌÉý[o*ú‹N°Iëì`³ê›r]å³4ñ¹í›Ê°Roæçã:tפcîMƒ%ð2ØéÞÎãv»=tLz=|²Æ*ðTŸ¯¥ðîÓžì÷vé„RZZ}u‚‚RÞeäÜð®ÓïC8û?†]Hë‡îåùðà]hü 2†h¼´6’[ãâêkÛ÷³½é:yx(YSçj]‰ÝÞ=Neì¬ã\lüÛo*øë–ò )^oZvE%lTàLÑ„=Á›„#Z펦ÄY®ÊY¾”˜@^Â^qÆ»Håw4Ê"ðü£ÅÉ].Åi‚MÓ}ÔGT’ Ê¾ãÈ÷:¥&^¬ÊÌx3·(b©\¹M ì%¾û—Ó¯Ï:Rê™[uÐØ™ëC¾°és­Ñàò¢ù¹–À󩎃{:…;ÐKyÝ:\äƒ{ʧ¶õi-øP!Y£ÞÔ…º·Ã(ŒW<ÇÓMv«Yžô•—ï×1bè‡w”¼ÔŠÔí°jC±åæá·ž¹ké¼ó''Ûd󿹫}4 Àäiõ `/(m–E§ð±íÌÈÁã—µ½(¢¢€§•¬ÛÝãšx½éÐÁ‚ÓÞ™Fm‡ñŠƒ>K½ìy<_<‚aÈÃ4 F1¸[Ñè&âFú¹01]‰š»£'"rpouB¯¾–Æ«•qWŒ{ï‡P9¼ó]Òs^Îæ": ϯ§Ý¥²…;µAÛ/9¬Ö™W ÕÒ«Ž )í[zƒ€i@´Ö^“›ÀóÐÑÞCiPZhuªä¦°jBš[Áä(3¥¸ÎËÞ*³;¦p$=S²µåãY;)qZópë}YŽ9ߺŸÞ¯zúÅL4‚ýئgí!uœ¿Zø#èål»ê’éìV9t¬¬Ì­é´©.3sC÷°2ðt¥Þ¦Øó^*ï,Qc 9Ç ®£óÖ·•1¦ÃØ5_Ù³™­ä:Ý ùOuwÞñãqyÞ×½ÅwFܶÛC¶]`“f†0:Yc·ÐÇ{€²6áÚŒZ8}>^;^ήï8¹Ž®å+Õœ««}OâcYNôGIŒãë‡ÓƒÀвŠy%`xeâ-VÄn <«ƒaã}…b£jZÖáŒBnëÙôËiTöãP;­h t¦£X&âEFÊ•»[°­¥Çªû°qèWÏ·X¬a®ËZìKîu¹ï•ë.cÔÏÁ¬8«7oÑ‹µÙ…K¾f­·Mgí}Uc7µ~oì0¦Û×î¯ÍËê.­¹^ç-åu—D#¬šÖ…4Äh¦Áâr¼ërtS_ã+¬‹´mu=äÍvi·…t]º×·—¦Ž 2Ý LÖŽô¬^õ:ÍÀlàç羱ة=HÏ"gÃÆ}ØÇ„ÔëU\SÛ»¹”g=b‘+… ¸UßÎàæ{ÉÙÍ™Q“^žºóÆ‘û™«öLít+.¶nh™©vKêmRå@,ùÝoÏnö@$åÍ-…ðqж§‹4òv÷D¾¶ü8ì©PTæ-øï¯ÇUf-ÇO)ªWÍ@>ýBfïR×ÅNWº­ O´}‚ÑÛ¥VØpðÆ8I“eš[T—ˆœ”³7y½ÊÊ›¼gVBÕsšË}t@6úV!—X2•Öià‹§àÓUiêÉe¿vïU•ݽ×Í;Û4.$ËÓõŒYó5ÁñÑq鋃‰Kê¾:¯oihçI §XÂùÖÖe eó”·o *1mW˵WB{ï*–G½ì2÷¼:‡nÇ+ÅðÚ·%\Í :® IÁ]a¸õÐ*ïÂß±/_.µá懹uŸWÕò©xÝ7Ù\kKõ.¹ui Hûµ§C´ŒQÅEÌŠÑqT§‰ä¢/fÕô²©­*bKWZi!N†ó©$Ýr–'„QB^$omE‚±˜»AK‰X¢¶Û.†=[ 4mB±€L†ÊÊNÖ;ÇqÖT°/Pƒƒ4´$Ú |5ÐÉ2¶¦³d6p´m 2og¤&NEœÆ« 7-ÜÛ¡zay6ž4³nL`ÜšY€öÙ{‰·Ù‘ª˜fƒyR—PëJŸ Áò·*[êÇmJ¼ÉRîŠmUÊTiaj ; ¢îŠŠØÓ²,Í«C–Ÿ³´NQuvC6è¹V@î¯v’¥°îR7ÂwgV܈ÿºòìÓ»÷íüÏÍ ÇüÓ}ƒo’nþpSt; ø[wk1uL»4þq䵸ËëtZöiÔE_b¨ðuë§vnßU6÷¥uÒ¢;»lw_Iʯ9˜¶êÎZYó;½îÌT€$òVá®:iÊ7wA¥‰à\‰í­\+1ÖÁ¢;}¤”lM޵ÚrÅqVS«ÈeðÄn¦:Þ—ŠõbìÎy4êød=:–®Š­"¨f©rÔ.ú“IjÌëÕ-¢-o6®ÆY[‰µ®63 öáX]ž ›œÖ!2ŒZ‘‡¢Ã˜¶ùñG‡fG5µ’mÜê™Ã1>âL1óÊ÷Uw0óó9²ùª…a6íÓIï ‡ªtXÃÆ3¤ÞÁÖígmtº:d¾jÍÇ›´b`ZG®ùßV˜†î¥}Dw~;¡RÕŒZ…ª ó›Ë;EîUЃ8ºÜ®=AV!FúehÑÔuuÚžBç%0cÕ5ÃɺÆŠÊÛ”áËW&q=gFkœŠK"™7ÂÏDòSGÉ{ÏÞ·ätœ‡sÖêú®|U?!ãü_½üž¯öÿøà¼þ¾œäPÛù›)DÍ/ù.†âå4”P@¢‹B”]±E4FåÜ=è¤,ÂJ.)GêX£ý¼,l?›EX¹ Ѣł͋5l¹bä(ª“©TË h ÐFÇý s;¸3í67YàÂíšÄ¦”ÔaEË60ƒ#ÇŠCd/ @×˺ßowЄ îû}î庈ç‡LýXWZ§<©FKJ"<ƒ>€[/«õ‘ÔPãŽB(÷ð›ùŸ‡ú¾Åì{wŠhÊL(±Uä÷su¡ÎŸéYãÇV—óÈQö¾M…<3%¬|œŠõz‰ROs¾½""о]wDeÂŽñU_œÒÜ4ã~X|¾3®¸2TQ…Þ1ž¿åèPALp £Ç7ÒGïöõ\(RX!ÃTuºÕl_RÚŸ7 Ÿ²­êÙˆåU2¹5P ù"{–ɼßÿÓ·;œÿOÎ{ÿøÐãùoÙóÿ“•ù¿Qàˆ†˜oþvˆˆP5´þ^¶{Íw$‘AsœùR9·GNÎ#l0åUt[‡8,ËnLœé\Üö¡Ñ¾ ÷î‚ÅjФט£/:WaµËhñÔùP¤ ηÜ^!é _zYz.ŽFŠ¿£U°”Ú3z®;e)EêÔs,¢üú?²•v᫤SLë(°º+•¬»'¬ 9Îh0´|#~Meš¤µ%:¤#ÙÇ•QæfV¹H_g]ÚÚèÿ­Ç–pZ¡ ýÒãâ4­KÕF™£´‹ss©ñ^Ôaa«\¢dÏÒŒ),ªª•œ]f»G:-!îxa‡¬®sÉ ':뮺Yeõ•i`¬·¶®–„ÝyìòÆ©VÆ)…¢Ü~oƃ•Ã_S«}«œçŽ!Kk£’M•Á– 2ŽŽzëgë;-VÙk¬Å†nµ÷ÑhAiºd…©×°SWRÈäϹY™u+½ e º-†øûj¿~] ]«‡Ü­9_«Vp¿QvKAp¡]^æx*¨ÕYãšÖÚ·µ¿S]Uª¦.;42=fTõÅG.ƒTí\9h[¬µÚT¬í[ëb<À¶à¤ØWÞÏsî«‚«š«¸Z¨Jã®Yr·®Ý qðó8­svJqTò*‘ëúçih ?žL)sÏ¿CHºÖU– ŽUªôqg­;-Ò¯/ò÷É<ÌMÛp™Í¡Ôå"‘€'s¿ì(XíŠf)X²1>§ß¿,P,‰aHƒ °ƒdd$d$$‘$‘‘‘RBD’D$ Eˆ‘FFFI $d $d$dT‘$‘$ FE@óá°‚(›XŠ"xÕÝ»ÿW„ìÞõÖ߇GjM[iß¿_µäg6r(œLˆ‚ " ‡Ñ úO}“Ä4Ëçš7†Á¨o CLùfä¾YÈÝž æŽèí„{£Çɸ<‰Å9´9ƒÄ8à3ž<ÑÑÄ?Üèr}Ó÷ΔÙ6M“dÙ6M“dÙ6M“dÙ6M“dÙ6M“dÙ6M“dÙ6M“dÙ6M“dÙ6M“dÙ6M“dÙ6M“dÙ6M“dÙ6M“öOJ¼6蜘.éçB…?yý ׸¥!H£" ¤Š¬‹")"ŠH €‰ˆ«€°ƒH‚BÀj(„ˆ’ ‚ HH‚!@È© }¤#j÷Ä!k_4ƒ "T=¤¢ hQ=•4Þ qA,‡í…,)B–# $$ PФZaB@’’BFg;CHDdA ¤Š¤„ ÈÈ¢@`¤€ 1D"ª¡`R„@ €A ’ )Éý/ø?þ}wò¾ŸÉìõþô)_‡8à¦0SÔ…ÞPô< €ŸŠ£èž€`²ّ½”O@S* Så[!K@°—@f)H–,¬DÚ€ØA R{AOœ A•0‹H#„$@a$!@$Dj" T$ RDPÙ–ÄS㈣EÃåüï·ºUþÆýüuÉ0û .qÿ¡S/o—r}×`®ÆáJDZÙÛÕåóuú™üï¡‚å9&<„s*çmWÈgq5  ‡¡è‹¢<ïØÍý[ŸîyÿSßè|g7_˜D8B!ɇNöb`$XGÚŠEìaã‚ù™ yb(ß!Nâ9 R§Üž # Gð!´Rùýp¦b¥{QMHSr Âåò=O•m-BÆE‘„‘’HB@„I ûž¸Á ¦–¡HVLêÁ¡U!zBâ”)ê fh¦´KˆŒd’I$’I$ $’I$’I$’I$’I$’I$’I$’I$’I$’I"$D’I$’„$’I! $’I$’I$’I$’I$’H"¤€À`0@ý°¦‚€ØRBA:„ HjxÅ,lDÊ")˜)ƒQˆûÑLŰ |²¡ ˤ²Ô+T0a!·ˆ¥0’è5Âĵ@Ŷ7»y"q Pž¨zÁr‚0&‰Ám#’K³ ´º\h\*áóÅ1- )…´–@ÿwó) †+Q¡S!Hª‰—0s±Ž±LÑ=‘2`I$ƒ$ŒŒ’"2 ° F„ƒ$ŒŒ’"ŒÅ"» H  !!AM!$’I$’’I$„$„’I$’I$’B1„’I$’HBBI$’I$Œc $’HBI$’I$„$’I$# $’I$’I!$„’F$„$’I$’I$’BBI$‘Œ’I $’2I$‘Œ’I$’II$’I$’’I$’I$’I$’I$’I$’II$’I$’I$’I$’I#B`ÂHI$’I$’I$’I$„$„cI$’@$„’HBI$’I$’I$’I! $’I$’I$’I$’I$’I !! $’I$’I$aI$’I$!$’I$’1~@K‚žÜ8Ä2ÐC„Spb úÄ"Œ"@Š)Ф  0!I  @€ "$0 $B,@¡!D FPD! @a„H0a€B „„—Ð8Áuà Da´’Kk8 ‚Å%$"D‚Ab$³ DH ‰ BPf"ŽaN²†Ä HRA¸*š05p¶¾m¬Ù `¨üW €|œh9šqá1 ± Œ-`°A[’&ÅŠëˆÕÀ°À̪ ^ÂX&”à)Æ)€Ü01ÊKÚ Â!ö ZLàX¬¤%$*ªBBE$((™K"ˆ!* BIEBŠI¡U ª³ ,Õ-Vb ö}ŽÃ@wjæ÷7Ù?ç÷žÿÕÿß÷6áÒ"v~Ëp®Ùï~·è”Á¸—ÕÈÉ€û|¨ëcBaûŠ" ¥ A !%Ì{ë†GðDþ·ÒÿÍÞ_"žÐR „ƒ О¯„?•ûïÝð#c!åƒ'Öû;X>¨$Õ°Eù~ î”ðÅ þßx P€f¨ |ЂƒU‚iä‚ýИˆ¹~O¿L‰ú™¾[ø¯1e -DÇÒž0Ý"E±UXƒIžp^¨ô $Þq8¿÷òsŸ¥çö¾ÏË{oÝàx}j ´6¦SÓ¶Q9 ¼ÒëÆD`SÇé󯥅,)š€¯u-þ8"ùiûò Š)õDr`A B„A„F  ß¥±xU0}‰€“]ѽD‘‘þó¾×ñçË¿ã}/áí{qßsWPæù~G§×ʵþ/ÝþÛ^ºõ€TOƈªcpÌGøÂq9¢Ú¥üH)ü"ú`Šyb@€Å""  Ø "ûð^˜‚VÝ.œ‰Q{Ù#k“F ¼ãôû‹‘jXRâ“ÕMt vANR}¿/³ÿ×ð÷¿þ?Éí~ãôÿ}ú_ßæëq}zˆr‡ü?\ë H ²’È,€’„ñù5`ú–Ì@V {úaTH¤Q"è üüŸ}ÈyÊ®bŠ#ç ãPüÔ ô~eP~h§ŒL\4U MŽßög’Q ³ù6õí{Ú÷?,汘|Užñ:% !›S’ñ§{×|7yO±ú<²`" " €QvDåX>£Îž)í@І"ø‰åÐ!@¤À¤  DS¾ W¸DTyH"£Ìîyj€ Š€)øým8ÈSÂ)áp¨ßY[”b^JÒÏéãnÉêñÌŽ?[ß »=Ѐš^iŽŸ:N'žò^¿ìüLÂgšno¼ˆoH7ÈÛ£¤?*¨sȈ!æ¹ÄD ÁLÀþÆgå‘=ôÕ÷gÏ|@)k¾L¨OœRZ¡“øCÛÆ !I*÷“èP4ÿkâßÿWå}Ǿö`"xè[ØýÜV7J‚gŰ'ó"€½èSþÏ[Rtxȩ՛ðGäý6¿‰xKýþ÷³âûÃñ!þ=EX=×÷|ã΂IÎvC ›ú{ÄÈS!M`ŸÝXÊ€ _T…0¸¦á¬t=zªŽ4ï6G¦?FÇÈŸW«ÖôÅÿ·}µèyü\¾Ëo@äI¨n¥ ¢+”×ý¨† "Jj‚  !ÞvKèýÍ/ðóþoú>B#ò?W¥€HÆ'œýh Ä"€¿ƒÀ' ˆS있t>X)cþ¯©‚+ØôOÀ=SÒöä×ã{Å@ª”Õ9ÚÄb¡œ‚Œ©åJ„ V?`íOF\=@”òùOÄñŸKìwá{_oó¾O¢?9ìòr™áòN0*÷ư§õ2= r‚r(¨ª¹ß±Îˆôz*rŸCð8ûkT9sÒt§=/¿ÿ?:®WÎIÙ:‰þ9g=3Üx€oy$’Hý¯Ù~üŸ¾ø8yb‘ÊOK_ •ž?‡VàCï÷^»ßûÿûì,Øʦp)âÙ“CvÜòWÁLÏ»„€à=WOâ/®ˆ "?R‘ v¾ ª‰Û Ÿ…@$! …?)EvA·ÉDå] ˆ.á%÷çÄYŸêqÚäbvÎçÖŸlQ‡Ö˜ý>õ픪“m‹~3èµòLð´€I!$’ANqH]QÊ O<5dz|NËšþï©õië?‡¯ŽŸ˜K‰¦†èóÑj ØÀ:Úxd§öÿ`4‡¦Ÿ;À'`T~øGê÷h'ˆ@>§8¤ß³ŽržtÀSËÀ¦á&0l^X7Cx±Dqäûü"!ä>'oØwSoíúwº¿ƒÀùÿ±úýîÎ?l¼àˆl‚ˆ†¢?auè]ÿŸ‡¤l‡n"'ž06€ ñ6‰ýî¹ë‰ìLÅ" yÀ Eú=YPÌT`¢ůúžRÐx¡åO*Š9p©ÐÿŸ‰þÿoÊ|?_ÓÿŸý´=¶¸zþ¸!×a0ˆt¾÷áž_¿ø˜ <€P?–ª*6W%]<¢“OÌüwí;B›û¾iäžøýl1ðáí…ÿðýoñDý 7îÕø)ù"?N ÿŠ„ ªV 5JªQ*¨ªRª•JªP¨TP*©Jªª ZªJªQ …@ªj¨ ªª‘PÄ@=ëñˆ‚° XP?þè_ÑkvAOŠ[ãöä¦}d‰@”$$$$$$$$$$$$$$$$$$$$"¥sÓ,aõsUÓðI¨Sá¹+´Üt__Áþ^ƒü|ž¢")ÛjƒÑ0ñX)ü¯¹þÿáùèª’Š¬,zº‡št‡…Bà‘ACˆˆ€@ûP å{ñV‰îEGËD0 XR¢ ÅTHªæ*£îÝÿ¯r`™”lÁJýÈ)´@7èžP ¸+ˆ¡=ð(ÉÏ\"ŸÈþþµSÇã2ðÇœ¿ É zÚxÉÖ©UEI*’¡âèþe†ðç5ÄPD9ÂøôD<â/îª .>ûïx|_»ñ¾×ëÜöŸÉ®àÆéc„>çñ9?wóÂ)ç›?Ûø¾ÌÝÚ6¡J:>WÉÿyÕÃÞ{¯ùðûŸ·é~Wþ8ºaÙ`9¼A"oýP`8ˆ@qÔDð¿oËÃótß#ø=óþ=ì8ƒÔbéDACÌAÖö Ô|­q•À¬ªW‚¶`Ðÿ!h¯Kþ=P+^à÷eÀÙæüößW»òX}7šÝq·ÿá¾ÄSÒpÏórzDÕ÷ÊCÓ/­;n*ûÀO%OA}¢•ÿÐüød~WØÕ~ Êù“€C€Äàœp tºmȵË.¥Û‡Y&G]¸ÂÔÚ¥uÙeï>Th†ši–ËÕ‰$ù~ZuõÝÏòãÿ囦Ô9Ö˧ã%IËõ¯è¹.ïº×õ=ï¿Úûôþœ³s¤ñý`ß/ø] l¥7¾Ká<”2û¶î…º·€K[´†F1[ÜêêÀYU†V os¸šèóBÎ,Y®4§Ö«cÎ%b¸9®¥¢ïAÕÉÍlr€$èö»‹¬dDÞëqõÖÔOx]¢éfËRò‰Ó2¸ Qõèèm­0Û â•+ÃÜ“º143q:cOEyHSÇWƒ´ѼUœI¤Ò5hÔi©›3TSJ|õ¨…½·)mféC:³ o\UqÍ®êW+³AÄ>WX&\5Å«nÇÁðû!y*ãDi¥4óˆÌ¦± Ufõ6æe J>ö'ÝzñïF°êÅâÊΚ֨õuIݼQÜz…ušÅŸ(W,]€[“n¬bË®f€®ë¡¼, @´‘ÛØ™VêàÛ•W)Žàhç3Õ…Þön·@[F ¬Xö‚E:Jk:€;·\¹m'ÙwnC}wO£¹Ù¸ÔÆNÕ…måìéIuÊ}Lõ+·’vÓ„=Rî×_(ž¤ãá®ãh ¾væ;•"qÚê×†Ê ~¾{œ9õ<î–85격“JûTìÅÉgDsA‹±Ç-åqXŽ0C4m,³C]J»ß´Uv…(7~@Ñ©jv“«ë#B³59˜‚º[¡H¨pežÊØsomŒ×Á­¤ Gƒ·²!ÜZ¼ë'¥'ÕD% G ­ÝÞqrγƒ¸ßÓ+"˜¶r4óhÔV{ã2]ØñXnw.‰q­µOBùÁ½{DžsâXCÖ·wŽ  µ‘´ø CtW‘BÆžªTCÝì—jßm.‚ %¾zrPÌêÈNÿÀ2»fGÀ£©V"ô Π‹×•uåÜ- ][Ó;Huü=Éf€kEYéb“´`¼y­×ƒ:mnV¹:fpb§3Ù(!ÊÞ´inG\mÇu6 éÑA"Q<kµea‹Â™}ˆy/y…âU¦¹FÎçPÆpÖŠêY]2]ƒ#…XËãHµIð‹¨îíÒîn±IÔ»Ù0¥æ;Aq»¦Ìx÷K«pž¦rþ=Fƒî¾­:º¾ì¬Ák–èË )Ö+¨Jrõë–ö¬3¥[ÍIŠ3®’îkº³o9Y-p¾8ÂŽ@¡E½±@Ý.à Ã)ˆéõ=ÛAÙ“Ž]ç^€pU¶¶³¡œ30®nØ¢ÞЛ|Õóޤ¯†\#jÓy¦³f–µŸ0ÙŠ;{x£n›²9-¨s°ö½.Öô}·¶õ ×»GA«êØËÄ%b½o{…îB1kî«YC¾A-zÙ•;næQ!+ÒÒxo;·ÙäWƒq$4ME·+8 Ós^ê©Ñ‚ºf_”bǾëSjÕÊSFR@ç*±¼­¾™Ón­î¤YÕÕ†ô>ºá]ì˜FèrJqõFf¹6·A˜(óÊÌCœ/4C“Þô–jPõWµ«¬Û|¢ƒZj{c}¹[¹p;±ˆ‹½ëK¬5$ßÎÚnC[µ­Î˜¸1µV”÷î.žåš˜¯­>Ž ÓœÏ±Xk:$›“°¡wÍb$CƒQÙ›efÖeA×9ºU;¢À{;kã—[¥+#¦lM ‰Öችâ,*#ÜÖ{"Ñš;NÁXNŸ35â<2”Û4¦´o>ÅÜy©mn6ÜÕ1AÂn”î½S­ŒÚÜ%öˆø$Œlλܦj-8.”@íJ$`)qÍ{°Ñ¢3)s¥qrÉÍ]«²Nï9”U®!XêÖŸGQ4¯©í_ ¢«`´%76ƒ[¢K”®¬ÔÙ¯ªG>ÑO¨à=|kwGqnX½ÎIÆwc¢ Æú‘ëâÆ>Ù¶+ G”‰Þn´gÚ°bÓˆn÷VEÎíÒ²Ì]ÉË;¤åÍ eÞŽs{ˆX!»nq¶4è«)ÕÖeÊ ®Þ\{ §2²’0H‡ÉAM>p:UÝ]…ê­‘ +:Ta%“äÖR#gÑÅ]InkÎqjNŽîó9u,>‡nUÓ«eU¨uMÈA–šv´ÇºúÚ¥§‰WEgnWpwÑæ`7£y v>A,øÑ½¨ïR![Ý݃¡–/ŽMÊÒíºÕ ÖÈ®‡hÞnwqº ÉHй_=\9†¹}.»”ע­¢ŸmûÎÞ‘ë%óW+·‡Mº Ö“;åjpW°emHk9)]«_Ì•S³U´êï‘Ü„ÖM–uÌ "+QËÇG>2‡(ÙÞÀQ(¥Á‡­‹×smáx½tªïj;-MN\v<êÍ[ۺʼ¸h•©ÖL¸]JA{²…¡Ì[‘v´1s¨%k082:¸öôq7jÞ aÞÎä«ÚÙ?m í¼¥Ë2Ï,DÄ]¸»ª XjÏ5Ì M›³Ûm0ȯ…½c0.ÌU©>éV£Íâö¶9͈d!#+•]XWt4L5tï}½¡ŸrÍ„*3¼Öñt/uÈGN!ŒYË ÛÊ·E\¹ Ø«³n±A]äpæƒÎž¡±Õðé»h3Ë‚*ºgJ–"V¾Õ(·ž_ Ì:¥Þr ëÎjl¼¹]”IÀŽåCa+xN±ÜÍÞà¡Ì —º³Ý…ó!w`»U©‡:ÍØ¶7•ÝÇÇ–l—™C¯x&˜ôE2×Y˲9G cÉfX:_nQâ £Úä‚=ñ³7´ŒÓ»f±Û˜ÀÐÈ­]eμEÄ:w*~ïfÑ̦ÖÅvŸ¼0«jêiY’!®k2è4åÉ7í¼Yu¶‘¯$V,½]%ßu“# Ö-½Ñ“F¦@ÔíÏt»“ÞðÒ¹è½Êº¤×ÜøóâeðLkêÓÀ6Ò6¯FóK­Š˜­eSÝœUAY·±«©Ø¥íЫ5‰ˆÜÛryXÓ7d•¬|²åÌ›]›zJb3ϨímN¿ùÙfÑÎÕ›Eça8H"j9o­VœKæï+£)ã—«ŽÒÙÔòÀ/ ¹Òj$ÚŸ[Óª»"§T U‰œ«,MÝò¬¢¾ÊÀƒ ó¨á¬Å€e뺵°ºozV´@±ª}ÝÛv†å2Í––‹ºÔ ‹ͪЕ5˜ŸGx)q¼V0*x±]ô’ðí$‰u6ÔŽMrçlWØúø lÉ&^ÖÑP¹€€Ê™ƒ8;¹Ö…ºo€o2ùf€yClåw¾³˜´tæŽuŽÞíqðË6ëu“ †‚çq²5_¯Ö+Ý䦬™[•Ί>4{ÕA¡[·ÕÅJ.n¥Ê‹W$YCŽÇl'»8îJÄ)“A‚çRf§kÁkã,p™ö©op:Åè(s–« ŠÌ«Ë#áNYÝ(RH‹ÚçÐöQBdÞ¦Û-uMÉ/a²é'ÑÖÌèf£’\è¬`•&dYh®xªK¬«ë< )dó[©Y=ËGÇN¥]`€DÁ:ë%<Q5hu­–†*wÝ DÏ:9x£¨N æfÆkhs±1ˆk¡Qîˆ'f”8î²ã¶Ä `µ°]:Fo«…kÚõ#×Õy@ 賓d•)ö áÝÕ+4à“;qG™F²FÄ}†Pí#lªY˜ˆ¥³:kçƒí=Ö«çLZ•ysc¬ìŽ1c/ƒ¹Ù]ÕxN1¹Ö®q¹@ÌÝƦJœ­e@ïqŒPܹ•ÜŠ­w–sç¥ó–8<@bÈ«íøg Ô»rEÙÑÅ>Êœ¬ëU¢ä®‹6…\€eòó»âÅ‚æÓsF¡´hæ¬nm5qûUPLÔ£K? ºSÅw؃5˜Þ‹©Xåo äJ“u‡[“£¶¶Õâ½»•JˆÇ U¶qÁQÜ H¦¤ÕÃjÓ@çm\v†vYû»srM%¸(´ ¶´ªc,ˆ¬é(X™†õÍr„\\3L÷¶ ¬¢P(cE&±;À¦RžÊ•ΖÓÞEÁs;vêdæ\‹‡ØõjK1Uð§eâ"&ÔvcWz2¾„zòùÄË6$¡2tTw¦ ¶{_VÀêÜá¥XÐÙå§>m¸Z±¤¢ŸÚ@™ –MÕ—L]ÅŽ¼dÌ1öåqs$ rALNŠ_gbÕÓF,{Ãwle­O7o±©‰ÇÊ„¾ƒ©d;…·Ùo¶±é¦8Öð…¡†Û€ôÌÇ„ÇDÉI®Y»É³c[Kect{F(±:»®±wfèER)dãv+9è­ÍëìXÎuÄ®•*'ŠÁÝ—ØHÍÁbRnx7´yZg"·µÐ–áq;Æ&â_§iNÂíÛKB/»ãJõÜæ¼¾J®°+ ío(:ð†ºåôÆ$æÍ‹í*ŽKYr…-‹Pû-Ú¶r5ÎÀ¾[Cª<\QdÑY¨«t¤è¬ÛÓ‘3o‡»Ý‡´Ýµáñ¶ý’cèƒ{€&ŒPp+Í×p&‚‡Å£w)_fv??oƒ•÷ß·ÅåÖû/YíòDÝï>Þä/9Qã"íƒÓ‡$øA•N_aÉ2=lL2×ùx[ÙV–¢‰(’JjÖ«J•ÕS$%A(³KKd³kÖ!&£çÕÜ5JÆôGyâŽ0°Š¯ÎàÀpæ™U9%„] ˆñ$ƒ>*+8SΧOò¾†d Ç'áÙ“êÞüÅï}ö o©õöšZl¨2/•s9UE4…CCH6ý_ëqº^©=Aã'AÏò¼n½½îø3‡Û€§¶Ó'GÎß±`ˆ(–¹·à€·(¥P„@PÈp€,€@R(ȈPƒ~Ñ4 êž7 5úžRò7“öXy·/ý_®.'€È·Â>¸^b'Ð6˜¹™Ói°¦à)ѶX›88/¥°˜ã•ÌL+*©n 7»ÿNUT>üÜÿ¸?±òWßñ_É¿ì™ûÉ7ú¡’1¢ã¶ãÅ®-ªå¶Ù´’‚…´@Þk…ÑGŒ\.”•cÚä›5UWŠÐÈе!%Bør‚‚{/qø¸>kq}Uå½Çå×õÛ_›´NѸ! ðlzûPCci=ú ÷R!ú¿Z_+Qµñ'³ÿÓ~ºÜoó?×ËœšÐ?ø?sðO¯õq;¦…Z)E’ˆL® ‰W»^)€V ¨ID¢ ŠÝý"M|[~/* #¦’^¨îÁŽõ{+Œ¶K‰uP;°D?×à3ú˜M¿-õ½·íÀ×R@@?KÒø¼|D5×—£õ¿Œ o8ò¢ÏVÀ¥Ììy§Êí#tÈ•¨‚rÂ5PˆõSïã;`§)Û a@)—I€4ù„!ÔÜ t|b)ºHña¹O“#Ty9ؼ—)êv…®K ’ ÕÎ…€ "(e(3~×PƒT©ˆ—$0XsK¡õ®ž±)¯"Y ²¢;õiçu­.àH)p˜,Ž8–àÅÉ äV$(’‘’Ó«(¦¦x³¾MŒìçMU ÕP¦b–Â]ÍKZ‘¦Ö˜ÕW¼&‚™ˆ­ ²)n¨º¯¥e%õ¬š ýR¿ë.•ªy‡6½tEóû-¬'ïZˆ™ð6l‹,kæŽ`[£§–T+„ÍT-&‡ ›½‡j‡TƒúCn?Â{J%üżCm$‰±ç¤ßG·$=)EQW(á)P@«cY•à’/‚GùB¨„Šˆb '"ò^G©ÀØÚì2;fþªsaÛxSDÔÕŽSi$QÖ)×_&¢Â%ˆvš l¹¤èÌú»!EàFu !4½™ PÑÂ˳Š\ÙÛŒ@MáäÅêF@²üÁNrûÁ"‹È±îyÀs<çÙŠyb—‰ÇFÐÏœM‹¼âB¥&EŒ9¸Dé­ä…Xð"D¼‘Ç>rëD«Îs³¼¢£T•H R„$u])lÈù‡†ˆwÁN’“¯ÉA‰žÎ(Â$šI†›‹ð£ÌG±É«©-“pH¥ YmÚ]S-Z,Q  ^¼éö/è‹ „1ìjµï1QFÕ! ¢å6 ùË’¹Rµ­Ùn‹xJ ¤‹0ÁCj@0-Þ2¨ ¿`2 ¼”ôî³!öXÇjíð½Z öKîbT>—òÿàý¿êÏ:c€AÂóœsŸsᤥóRâòÎRNî‡(ÇîèÿˈäÅ{ÑEje§® û!`ªŽöàÈõľ€§p" V²)¡A@ú_$Úé`KÂAþ Ãp'dhÆYêQ'°)·qÃ0® Üî¤~¦Ì3¡R‰€JU€ nN ¼Yx–÷àÀ pÜè>è@ ž!Ðé H%”kpœè*œv_!ÊŠLD> jˆˆhgöØú¼ÿ{þ^G¶õ¿O¥;ï  2cî<îgª<M#Ôíóääæ}ëè ÔZ¶AKÑkåÿÛwü—ÞÃÙäù.'¹ëÿ7Þb& a ÈE†Ó*ðJ¹;_ IM©çy”ç‡?RW˜0ÛI TB5 ¥jªÎÁD-j°¢†ÈõΚ2? )‘D™§ÊLa@uɪ3ZÅI Ÿ¨¡KQêjYÛ&¯³8ÍxÓ` SësåÀiÄŽö(p%¥ ¥ ÑR‰6“A 6»ì ñ=ÊêKjÈõImÝÙ,Gê•Ñ uÐQ=ëKÍe ð°ÆˆÚ@”RH9‚žìÀàHÜ1‰ö{èìľò”Õb“y¤4Gž‚o$ AT¾ÀÀ:¢2͈˜irp ˸˜LÞA´ ÊNŠ­)²v‰E[Ä$X À‚BK r9¢‡äSÄý]ðù¿ûý‡Þá]/¸Rò¹þ§÷¦¹ ¸š¤^=ÈMXÂòÃ{¦¨´00J¸¤‘ ÆØX*c@$¨4P”RŒ"e‘P…%JdBøZÉ$$-F,0’×½®2Á+:ȾlaJXçèe:¯¨ûxŸ1ŸìÑ‚“ ­Û®ä~§¸Ï€4¨pAªÏM¶˜êÕs Š‹wŠœÞ²²*u"#ÇŠ‡Ić9Ƹš3õý·lÐ 0CÃÌ’˜Oe°òŒ¤”JÝ<êÆÏ) 9±’!uÚ³Qñx|åàÉ›J[X©½÷Ƭü{AÒ;ä ¸E4uNEV¢gΜ¸«´ôºÞyó²0hVC5·±jmP5ÚðJª\'9ˆ~hNe7 e×ûéFœ]ÃiŽ4rd›B{#j…‘M¢“6vZ•Ê‘=T xã6$]> ,7)¶c»Š?M (6uNwfÕs¶ tRܪæLE‰Û7oé:‹ä_ÉLµwÆ®fj»d†Ý2»Ä’ÞÖ˜í¹–q(Àø5Éž&ø&è`͸gmÄBú©L¦0ãœMñ¶s(ßB¸Bc2ƒ£¥d V5$™Ã\ # ä×·3LQ›e.¨¨gÛ0Á¸ZÛKáâÆÃŒ$5E T xK‘¢W¬Gvyïȶê£B·Sh[‹Ü×ÌémÇW› •šDÙxU°£V£#%cŠáu”™1ÔxŽunyRΗëƒUb¬¶q3Ù&–›Å/Ù/´EcpÀÜQÃg…‡EAÍLž »¸É"­:©DW5ü)Hˆ„&¤Ç]kfðy6 \¾m›µçª­ŽÁM*õàǃ†³ \¬ISzÔ±Õ&)&¾ ¨—­wÙkç²Ør°ŠëªÅx«ó5V\Ú ¼s†åwŠº’Lê°±ql  š ¢”QGŒV¢±|qI¢O¥x8¬SΜµøÝ*7“Caû”Чci÷Ô¦×VýµRN<.`s¿yG8„#Ìm‚…D7…7‘.)¸‹g‘Gßø×€à48ÌÙɧ]ûèä-]Œ Û’”– äÆoeÈ.lêI"G°17É£l´à˜õ,Z*^Œ-Ri¨µ²¹©éé°ýîv/F¼ËZ$ ¥cÉ .kЖҮñ‡Zâ°ÆFsÕI¸ªÑ(Žýt O Td’I$’HI $$˜ihL.PPJ!$³éÕ‰<ÂTø8lª§d•'ÖJøýËk¾Ô€/¨¬âÛÈË)rð’I 'º ÆX„$õÅ%I3¡ ’I$ÓlH°º‹ýjIAAS"‡¡‘%]De[­#ù¾¯­}ÿùÿÝBRyx5ÑPíBDÑRÐ$7Šy•"œ7)˜SÛQ*ÕbÐSô?î±ÿãï1;ïáÿ—eÐACÓíOÞ¸ð±T¬Mý‘ÿ7ãÈ@üõ2ëf4;$’/ıŸGš Q°ùD­Å47Qµ@ë j^TX©¨Ë»™ º@‘8̨ÔÌSÚëT=–5‘[—#̃œFnmÄ8ðX$Ät0‚[ß!¹· ¼b‘üéù0v„A#s€V|ž[Àú_cÁéùcîõƒ*ì3 ª*ŠŠ¨¢(¤ +Þç±ô½ÖØòª¾}T ¤ – ûÿ¿»í õìò2R º` é ì̈H ȈH¤‚"H’H H ˆH‚cV÷ÂT)D(#çÀ1Û¥¡ ¸¢ŽÄ9¡KÜ`Ÿ^“^›E(:DıMÀR&² ¯±Ü’ö;š¨È2™ki(¸)z»UŽ`?1¾p_t+L<âän3w*r ½ËƪE|ãm%GT• ʲN?éZH­à'ÝTÏ’Ö‰Pêæ!Úˆx?]?JÌο{†œš¶Ý‹÷ÊQøKüPÀõ|ØH' !-KBz](œ1KÁúp‘B¢‡-bgÖJÄÄÈ„b b)é✚ëY¾±ƒ„ ”vÁWŸæ¡K8èìM MãóAL„Ï•“³(v’Š,W‘{×*…X$ !¸Çéd©„©ç8²ûk}0?öHt¼§7Óˆþ-Â)ÇÎÈŠ¢’ IyRA6ûwxñD'À« ‚òÖObÇ¢H ¯Š¶vd$óh@`S™¸‰qý¢ÒÊÛü2hk,=h_o‡=Á'ÃCПI ß7Ä‘¢8xÉ;¼@d»$˜™)?<ä5‚æ÷Z<°ßêÚ!>Äè 4ª§!AÍ«‚Š Ïâ!šP)ë ¤,¡Œ3 äaÖÚ©2f¼œC¶À1½ W * ŠÙÓÏ–NXÆÒð|Û˜1Ê]»œ=£-Y†%²>…P#xÔað:ûh׉(` ¶h„ŽÂÔ! >P¢Ü@ ¤„¡Æ±Ö€‘ÞƒÄ6Ê/†dÛ5-ág…ëUSÀ…2HÙÀRÅ à4¤©!W_ïZä„96¥/–Ï/T”/}„ Ä í(r*H$DEA @‘„#;¥’$€I"2µëpŸ~^ü±‰ìΩû=×ÀãÆVŒœà±KPT[ÂÊ$#@„*UU!$FðdmÕž €U›˜Ðu÷r!Û|íç+Üêˆøy›¨Ò,qõÀSÊ ÄÖÔk”;EÍ B×! d„#RúXḬ̈UUÊMDg ËÖ‘ð¶?Þö½×Åõ<ö•Déù7µÁO¸¡~HP¤R`)]ûR­XÄ• ‘$Z‰Q"-Eí„(‰#"U ’~­ëø±^³:¨—"²º•Bž¦ ¥Ïîýaqà0¬wVîµ|É„/b¯XàÚXIjc{ÞbÖ9 g‰Â)aLÁУ‚ž‡û›p,E! ¯2ú€¦¾ÛÅ&F%¶‚#Û³åÄ c}I5©ó<¬aL‚¡1ÅfÀà $’I$ØUI©fýËÚI! ·°4HsX¡‡ùêfÞïµÇS…åÎýðº\Tµ³°ZÅT Æ€J@é1¨Q:¢(Ý  D „3c‹Ä°·l’BI° ‡¼¾Ìqã0ÂÒP)Äf}S ÃˆÐÝ5 ¨ºÌ‰‘_ [Z5»—£3ü9ìPüi$#"Â*‡ìöùþ>5=”¢ÚI$’I$’I$$$BX±²E HN9\õ\•(©$’I¦°h^òHBI ‘U$’qí˜Þ𑃴N&Ä(©)é–ÒGN§µ n˜I[´6A]‘JHHHW+A²ôÕU’ŽDÃ<èL0ÀubC0ëi£4çÇÂAKá ¾4ÆIN e2I$’rÊ©¸Ó²$5£óϘpèç¿ëÊ̽I!$’I$’I$’I$’I&|AŒ aË,Þ`µ¹ý²Å!¬ÀÂ3'†X;ð¢p8¾8“v³WKˆ"±»Wn™ñfd-Õ‹˜`eˆ¢ÉñÙß©îtþΖiX¦Šø{_Ôô7bL* %Pp¥`ä"^´U@Kuí~‡üYãÐÌ8+Ÿ ¹²ú|ü0…œL1¼¶ì³Çã\ü¨`]À?ö:0ta¨´ë uö™ íŽÀ¤ÌTêÀÌ‘XVÿXÖ†:ü3øq4(@!äp­ìBAÌÁò§V»®QÀ&óS¡¬lœɨR$TÔ±$€ ×((éH=N··(n.*˜"€"$!¸†ÓÑ{T¼×¥±ÓaNÅHNæTήVv´I{IfX`TiªB¥‘vŠLBŨwÚä…l 4GÚy#üà>wŒTŠE;¹y¢œ]MÇSo±ñU(ØÃz‡µÛÚ[މËvòRHEK ¥6+YÎo é;ZôÒDT„òÓ)Øìsi5XˆÚ­,¾c`;³¼wCŒHrÇÕÛ$à0/êŠ6À ÔéÚR pòèQÒJÕíz¢˜§?.êò5ëQ4Љ‡àÜ=û=zë3àBq5½%bc‚caBÑ.zÿÙíû·Ó{¿Óê¸zHznÿ[2/<\ÎQQWïgÝît35hÊi(‡Nhêky©ö›¿{ájÊÁ–Ç"_dól¤L R ÉpE• C „ŒÁkIݳйTyR°ÂÄ’E‹|*ÑcyPŒ Ç $JŠ•‰kX¦Y,)c‹Ð…¹è””&@¥gEð(SÆ>Š’ˆ~g‘ Ñ&£)z Ú¬FÄ”ØÐ¸¥XÂWª\R´21 BPHXþ>0¤\ë’†¸î‚MZb•¡òÞ}¤lŽ”¶Ú€h¢…ð1ôMEí‰ó󂑺k0 @a‚/­ {ÄQ¹¥Ý„„Q‘4KüîNpS™ bšÌbT©$ *I‘@£E©{i#U$#!J%J[ZaW \”¦G»P.…††°ôÏ~м°õ“Ž?^)5x0ÕÀîàé0p§Ðùeí¢–>c™°ä×Ö5ƒ\ê¾Ù±“Ϙ)o-0%Ò3ÜÉ^ó£j6“Ánlá2åêÆøJ!Ìã …œ#ª¨4ªìL7œ»×•Ó㑇!Úl æ Z%Ô:;&as"´Èžëdé8„€¦¥O‰$ÏQ÷´k%©'ñ¹ [ƈ”Ò’K±ëI³;¸L2–…¤µ¨ˆs`adƃ .\³ ¤ñ ö)7/Á ·­ ¤)8õ¨â6*'s1(‘õð;U2Á¨á6¼[꘡0¦ Eà9#’Im‰]#Í…®=;ÞCL…Î$ÉëÂ^¶›ÌØnS 0L6©°”©E$«J„H)i"„ˆ%I ÙJ!j*‹ ZÁÓrø[åâ7™ ܵŠZÎg…Z —µ°ÅdfffAXʈñå9_Ûï÷½G¼ú^Ø^±Oä/Üxu¹{ØÝž•WŽ«±…´ •íÖº˜IËÅ/‚~Ò«sIDBmeb•9U¥GM‘j¡GiM,u«5-P¦a¬µV¹G¡| ³-ªÓ:Ç Â«ŠUhçFwªfU¯ ¹&8J¹è9]Îbae;eäÂUCvҀ̉†w­/®Âa5ÍSl®^dÞŲÛc!Á2lgV‘mRÕ™vYïH‰n[d«ÂùYlWßWíþÙýb°)þÅèk÷â2÷ë,LæJ‘-XÕg i0˜*Dµ`KkTàÁ2ƪT±7ijä_e^“}ªò¦É[eè¨0ʂΗ3ÎÚ_µÜ›…4x¡˜GdE8fÅλbERvÉÅŠ^£RßhÑžætãr„\ÕE˫ȹØq%AmW#öÐäùüžL’Ø&´ÿ¬¢î¥ûþqúØoÃ>C‰…5å>'ðrÂçEü¼ÎwÓêõ !'-­>QÍý’á$ÛáË5¶ò]õ°«p–• UêÅŠp½á®J ‰…4PÐV4–BX#$‘yº ÅÅÙõÔÀsà I|u´&  q) ÏÎ¥ Ö{‰ÀšQÿîÞŽÅùªa\FóZž×‹ÈlÁäžže;í)³¼Õ„ 9hêé\ÞÖÐဤ‹ "«",ƒ ²"’ 2 "¨H ‚°A¨‚ÑB #!¢"H²’  "¢H È ‚È "ƒf™@SÖ œjš'á,Ê”Rä-‡¨0R6Ë‹ÞC^Gp87ïÉw¬5¹~˜ŽýO^Z«6Ö¦ÔpW·1è*˜'† 0n™©ïÁN+‰1ˆ‡»Ëš÷PˆèG^\ð…© ÔÊ„$q”BeBÚÁÝ–@¶ÊG„–&j)®qd£Uèõ«2ZbìP<']¹²ÞCR­´; ÓZ¦Ê]šÎ$ÉùÛ mÆb™ïÌêU$`aC‚;ªØEÙHc5™cNùµ…vh¼L‹xT ÁÜÿûœþ﹃bß_½e˜ÏÑéô/~éMG>Ì®Ž‹Ø/AÆQ|îU¢t¶r¶¬©ÉÝYažy6af‚íTµCZ‹^ÁU[Cò¾Q7J»Wý¤fŽQ¹¶—ìK„’GcEKó”jЧ¦Â°ÀÛ 1½£U¥±e(´±¶<̬‰‹B”ÖѰ¦ƒß D 8 -kfóNå«>|Ý bU ˆ¬#Ë3QÂ"Ú7‚›ÁLÁNÀ)¬Î+°ÍDÙÞR! rm×—í˜_=xk—³ÉK–-¯×íY•ÀšUuÉTò;]꯾§ûê0˜ç fæ£Îv3^Cœ Ñ´Ú ‰Oš‰ö!;চfˤ2â)û[…q/ŽèBBNB›P"}ä7 @ˆ ¨À7‘MU¹8—JbµŠlKm £šknÛ)¥¸ªÂ’,͉Xg•¬ê ô¦ÂðN‡\G£"‹ÌAÞbÔµ¬Ú&¤ÃQBö‚ëyågÒø2Ër¼ŠC‡`§„SÂ)Î)’š°0G^£ˆ}” ©Ù ²Ú‚žÎÕ;‚¦ÐÈnìCtݹ ‰PR H$‚$ÑD(^Ý­z.©yfËX¶qâr*Y´6ž,1 19è8ÒâÞuú‚˜À9zã€W[‹‹ ‰¯Km,^÷¨Õ.fì1”Zëz©EJ/zK^ÕfõIhFðL.”X⨵¬ÐŠ5/*Bò­ IP´¢Ò¤of ZBÐ%ªÍ›ÊÈRáh’@„Œ ‘j]"ä…‰×DPN"‚„°}-‚·".²­d³ÅÛ,Ü0²)ã;†Ýl`’#PJ boÐÑ @:¢dJ;›!·® kïœç/Pç0ìåÂmáâkhBÈBDl£VRË óÃ\$I/«UbTI“}È )s™%€‰LU11•Gl4>ä5ÒàÁI 4¢Ù«œ”‡ i­ 7¡gPÙêðBáz‹B(àñT^ÿß™þ ßúÏýv_cÝz[Ý?éȇY¿ÏPAx1;"S]'ŽŒÐRý+%žÜX>èð.š« {XlåÍ<² AL¯˜Cæøf .ÃÁB!°§Ú¸¥ÀÚŸP“y.ñ Cy5‚ÈýKi€s…½hùpâ0„ƒ8Q?t=Tâ<³Ë?ûuÉ5KÀôAHŸÜܲQ¼’–2 bUD€V …–áâºÀ£®…øÂ/²×Ô‘Ú; Ÿ¥ M-¦cΧYþº¬Ç·¨Y3E$!HLk8´*(l÷˜K‰ˆ¤ ¦¹‡XæýÑRß!¯Ýó~ïŸðªŸšæýÏäÿLïÍ·4sb Tr!Ð*c6þîÞÈ´Æ”€€Ð×°2D—¯,@†hd'ÖC"ÁÔL@Î@¦Y¨-Å$ ömk¦çl‡«°Ï$È36þ/eüÿW÷ÿGgý|m{çî u@l[_·"(ˆCßô:±O1ÔÌ9=µT 6‰Ölõhu)íhÖ÷;Ö¨–ˆ§¶‰Ž¶„/ðËý¶´<N †O†˜ì þ.¨ Ë€•eé}O_ÔzNS·ô>Z÷7ïõ\A8ñDqÃa‡¥tׂ’*`F~n=Ïl|_Ùöcüjm5é«^Žšd(+™»$+…U“DOPDJ«D}Ÿæó58w¢²ªÅ ÜP¿ñ%´ÒöŸ{c#‹X+9Ç’¬Hñ×6t¶è[w6|^Ÿ0d ² CЄŠž~'Èu† ©'ÉŠg3H "„"¿­ÔÕ:¡*SEUÛqcÁás>øžOæm3ù]Ï1Ë »¬¹3Žñ¹Ÿï««äÈRZšŽN…µÝùùe2„ƦX*ôËJ/…Rß ¯¢||ƒ †3L à °¦«Õ¨ª.ÔZ'c—½UD…Ü­TÒ–/ÞyP8û"hiMpòìä}i4ß-~ qüõÎ Ýúžöλ*Q¸PqÂÓY¹ßÝ;õÕœ†~Àºìå£+••΂{W½›{Òí½$5§áø66|^ÆÎÑn â(ýÀd¥ÂŽÖÀ°ãНˆ`yœŠ÷Ìõ‘çÖ;ÉÄSýÂâi ¤ÏuÕò_sãû?¿Õw}Ž¡9}Â0< ©4u×Ü]òä쎗4€$Üm“O@5h{—§Úy/µëÛö{ÏÔámý„jéS×v¾¸ý¾äO€½ÐüÑŠùý¨znÇÐ?:šP=ƒÊ;ÿëdØò1ý9ª )@SØ,0ž%Œ·¬ÍT°^y6•:€Ô¨È[;H²­²>‹£ƒsuvÐ ¨þ›¸ Aü‡ªYÁN”ì”Pò¼[ìôáÙtÝÞÐx° ‘`'HI|Y¹¿“×ȵóß*(â‹,*&`Ü÷)X@hîO9}¹ª¢nÙUièÎ2ávÆÌn7<y§î§ûÊ•tÁVr©·“öš¸i5iÏåfOzù¶m ÄÚœù¨}“Ы]ùÔ5ôV¾zt @ÙļèÛËnŒ¯²rÂbZÆÈgKãƒò}þ)üùw›³Éé’©*Oµ8ò ú‹ÀÁii3…Ÿ¯ór•ÁHo¨Œ0¢åàÉÔNƒ£¾Ž³îE5Ð/Ì/eéuÏÍ“¨Û€†`§KVqôœlÈÇe©HiÃê*5@ß-ªœ¬É”Îs¡üvÐZ0‚ÙCB03IÓ@Ì`—ÏW’¾µ•þ?7¦íEA1Ígî[0®fyú¾½iIêVøhëÝ“füžØ ß’ÀÿNfâgµ]sõº>/ø¡òÄc_¼GfQ^-˜äÇm×Ô[ùh:)ˆY”\Ù$oËv³œž™ŠÙ'ÙÅÏ1å "Orã±2\¯«ž{Ñû®œT¦AùCÐ}–·m îú†¿—› z ˜„˜¿Ò#áÆ«]΃Xá„/,˜0‡ajÚ'ßÊ£˜‚NJ‘LüùYœÌ¼þŠÛÖñ×ûŒ5û0¡‹âÛaúí–o.ÞC’û‘Z«§ÆªóÙ¦À!©F½Çc7×PÐJºÙÈ <†TG÷aöÕ¼¼­²1e²9G?g“àr¸ýß œó’ùð°ä¸|ÿ5‹øŠÜámÒÌÞ¬yKÉ·”ïP¶X !;I£Â»BØS‹@©SÝ2kŸ cR‹Þ~ùU ¿}D×~µ=“¦WHíf—8„™K0ƒíUº –SD²Q®xæñþþ¿u›ZF+°ßµG"1ù¨ËFi£úí©Í«.µ¿Ûá¹ùDz—ÝÔå¬!øñ_Àڹܭérû#4[öÃâ)ÝJÉb]ÄíßIsÒ&îêÚåüiѪø¥+EàVa»Éú%ÙJÑ9[;µ›³ Ò2×A:/ÐVn„¯S[q=¼×­-å]š›Úgj;JÇ *Ê@V]ùôâ}®ñª–¿½Õu*Ú:d{ÿuæb?­ë#3óÓ,Ý9ɺSo¾ÚI3¿9ý‹Ý÷Cz=2c‚mt1êþ»ÝFÌ&2î]Áñœ¯­†%iz¯$Í¿÷ucßnà¬÷«ˆ ™o‘k•;Õ®ÕqDÎÓMƒ = '° ®}ûÚ‰ peר]?U—ÜØWDRzzÞD8q…Îm©Zf î·ŒoîUJ6>¹;Ïj¾$#ê¾s ͨŸÞÿæ(+$Êk<ŒŽ€`CŠ_ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü3¹ÁæX‡‰ÞÐQ@GÁò7¬®!ß=¼ò‚ë¶½5îÏN€ô]€€0ûäÝSWÛWp¨gyÔí´ìax Ø•­½$žm†º¡Õ7›u¨}9ôŰ{»}ïXw­ÇÑ÷¾îœßw@³NA0ÐÏ{Óë{㊩ô:Â3á€îÒïyõN¥ônøÞ£Ü»€-öÞ{Æ4Õ][:v2ekMm»ß{íãë½á"NÞßw“Î=ÂoŸ*ÇÏIñ=z®m­µ§Ê­°ÎåN÷=¼ÅÙªÀ ±áÙu¾øt‘*¶çe0Ñ5"Í´·pèï­ñìi­“V]Ÿ|}<|¶…IC¹O‰åàõW¼Šô³ÛÛ®S§]7mî=ÕéIÜß{pI­«³‹–Zª¢íÇÞê®m¦žš9}«v$cTÙ¬û0ñD’öY—{Ï_T>¬ÛKm’°lf–0 &Íõ»º¯¼zQàÚVÖ×»—@{ÝãËd©BÊ«h-‚·ØõçŠQk MEŽŸ{½çkljo¯>o¾îvKÐÎÇ^ö|ùXG\Ƶš_]vó›– z¬ŽÕ² {ë¢EV€…,©íÖ[ç˜ÈöîÐ){Û¶Vz4—k}ã@}Vcï¹íÜlÙ]îÝJ ž×¼àëÛf“pÜëäèWY©%jn™Å²ûÝÏfÕuÏ«ídwÓwÛßz…GÞݺöó½Òßx M˜ €2`F&L™4i¦M4ÓF&FL0š`šdd`!¦™bšbhhÐɈ4LdA( F€M` ‘‰M4i©´Ê˜Ÿ£E1¡©äÓ#HÓÓ$ÓÔ̆SÔõ4zODzŒhÒ ž‘´Ðš šdôžQå= êjh L‚D&Œ’m2©úSðSõ4ž)à©ù§éOSOQú‘åÓÔÑ d£M= h=M ¦€I¤‰Ðhª~i©å„õ1i#ô1õ5SmSG¨7• íQä4ÔmOPõ=CÔõQ£ÊÔhh4 44h4õhÓ = "I hLL&õ0Œ‚aLÄÄÁ42˜hÄÐÐha1O@©ù ˜ ~DÀ*~£ÓM2›ÔcTØ…4 Š"€bLSi‰ ™¨`šzOiOCÔ0&ÔÓÕ=Ÿ¥=&ÔôÔÙ5¦IšOI§¢z™4ÚM¢z˜S&€ÈÓL 4Ò ˜bûü&Ín1=GèJg‰§ûúß³¸Ì´vÜ<ö%VXÕò†,œ ,‡&5õS¸ú‚¬þ],¿Ù’B†f“J¨¬Um¥lr-Eþ1 'ñ$l–ëXÔ?$!iÁúyŠ"[Ï((«ÔQ[V6¨·@ †W ´¬ÂÒŠ¶Ûlª£ŠÆ (±`Å$‘$a$ Ý·§éûOüW¾’#èà?ýôþØÌ›±g§4ˆž+…Ía‡{}­÷%‚¢HÚ‚2ª ZºsPËmáU »ÁÃA›tgš;ðÆQ<ö‰¾™  Œ1Æ!Æ$"TÄíL`IÄ€“)îË S*0š¼ïe'9ÿ9ªHóv›….®_ñ½Y6½þÿŸÁõœsœä|{Qo…¯ÆÞú¸ajTp"–µHÚ%)Oç[Í4¾ÊTkaSÿ ›(j¸àåŸùÝjÃJ—3ع”UnaR¢Ã(å HTÄ®5€².0®DD²DRªA¨±{hH¯¨Š‡£Š¯Yöð@ÇÅ;¸iŠúøŸ wPv"¾¶ þÜø ¢ü:è>»ù©í?‡Î܉_Ãòiþ¸€§ „8t?…ªŒÝòVê×ô²/ÒŸòÚÒIÝáz¹BÊОµrœª¥Zµƒz›š¼ÕkS­jñeº·%a8cQdÎKª–µªv²•2²®²šÌ«ZL®fRÊ' è˜UÖÆù;Y± >¶}Üò>Ôïé?v?ß ¤a¡¢§Ìƒöð,‹°*&ਛ"¢md‹è—ôM`±+2ªscj¢f•©Þk')ÊMB˜Å¢kOƒ.Æ•´††!dš‘Þ¦‰tŠÓš¡EÔºn„¢T'S Kœ²¦!׈äŽò¹¹2K&Ôå+œã“HµJuZ5‹+5QNË%©½ôN±Þ¦nÕë Õ¢åUÓêUM-f7PÆœ!Ë5N®í݉%:%R¹“´ÝL꦳vó‘ ….Cîè^‚Å!p¨”ÐH×BÀ¢Zš+š–Iéõ×ÝËÐø6ü1ÇÓç>¦%ß ÙX±$HD$C‘™Š_ØW¦ñ!¹¡åèÙ‡ùbÐì¾mŠŒ<„,¨„RC ð?¾×N'ýþÓ£¸ùþ2±>Ëì©3Á.OTGàWëBÖ­|zÇê{?‹–‰ð¹rþ6€zuü} Wí+é°Õ™ÉøÆ&ÁÀ ljc´^#‚0“_ß2 4a 0»åÙ¶øþÇû¹ûßSêÏ«ü¥aÂŽÌþ¿þ:û~|›@2Æìbíûèi[¢”bT ãÔôû ÉšW„@wF&^©! žCHÎÆ`0„@ Áãqñ= 3IØŸæ>›pƒ@åËe ­H¹’Ï&`¨¨@m‡ê€Uc„ª1¶È ¡ˆ@EÎ £S“óëçð7(Ž ¹Þþ1ȢΒe¢Šg‹á L¿zÒA\Eä/lN›˜•ü‘Ç)ž˜T¢ÝWݾJ O—Ïk’k€öã^ eµÆXë«QÈTöUÓøÙý*t°åݰx $?‡Þòà¯D€¿Ãþë°—Ò~']év ž3¿Äÿ¿Sýš4>Å®aåuNŽçùH•;íÙ @fbD@Ã@–© fnfÈ´™ùáò¡üØ|?ŸèÄ÷E3G .3ŸX°cÛ{§Šÿ+s$Èükâ¿0÷eòãÕ¦‚&ˆ1ˆCc aÚñfiŸm)c¹^ñ•¸éêQ®¬šsä_2Íb Ý!Ð’H¬z ªCûÞOñ=®­Ýð¿KÑ~Þsü?·êý5ê/œÚö\¤:É#D‡ ´d>‡ñl§&SKw.™s·Ê÷ÏRèš_­i¥>ô®ç—çâ“ïFŸøìéݹÎðÈÆÿõuW¥ÊRXßœbïXæø×çn3¾%kòL‰¤Êƒ$!p±Bjƒ Ä©/IÔéÿõ+ŸCñ¥øí…7Hñàãið¤Vk"?•,xy¤|ÓËZR¦1$;!0UmXn!¼»¨Íc™n4É}é¼Å‰@£è &‚ d×þ1J2x-it˜tì5[æ;µ89½Xå÷½aŸj}Ýz©£ïqT¤vi•òÖì¾þÔ.%ÿØÃ׬W‡Îæ æUaàÔ»Úžw ¤ûüߨeàæü¨Ö 0ü VWžƒ~,Á¨BMzÏ»7Ɔ($“WÑ»>õ é¥òÎÔñµYØh:®b¿y»¾»á±8~º:ÔóUYb¯ý$1>ý>LA6G)[Xc~î§Û5ó·øäŸD`1z„1ƒ;i/^¡Y½ÜÞ¹¯oÞÍæ?|¾¥Ê­Ç±'ÉíýôŒ,\×?,Å×çõé—FŒM¶ýˆDØ£¦ÃÖý–åè }kJ õqUÿyCÕýcáõß÷¢ûcâ:[ÿKOÎý÷ý—£1ýo\æ°TO`ˆÛüëÌnÜË¿øˆ€ø2Ûäò9Oàü}½Î·›—j²ÿ´p¼[™¿±^ve-³h€ @z]…û„ •…Mª2‰§ÛþW¹ý¦'Wȶ†‰%1™GçR:¹v>¨.X8÷›rÞ¨Ÿãýåbõ0U]µÉÛ¨´%ÿMr¯—ìðbÅ»÷Ä,¨‡VšÝÒÈœز]‹’œˆï´<´ÙOêÞ²6A¯\ÿªªœÝM>ï2jÊré^®«¯1#¿ç ¹ëôÔSˆ¢V*(£ö3àóêoUT…ø¹ënÀScˆ¹uõ€!ýèCȧݵʈPòxîÙ©ËưŸ{·ƒ¼lêò[~/™^šÞ­˜€ÔÓýîF^Ö·Ÿ_?O…×˹ÕUQ.Tvó¾{ºͯ¤¤O>ÿ‡¢åÕWþ“1é¥Î#(3]¶º¨½'¡À±ÿ¸W²ÓØ«ßÅ÷.Qëºíy<ÜÂÉ!u™ʪ^²É’jôi¬¥.ƒÃÜqÔu%vÇÒ¬NìY¥;4„ˆj|ò†kÑVkdAÒ‚E;ìæ8ÖÐ"Ú dÑ0øŽyöóürVìC„ $‹¨Àb¡ÒÅD*R ÏŸØ a{’°ŠKèÚ³¶¾‹u <ûªåñ`*ûD4Db@Q#ÈìTÔ±ùÑs^’º|ðêŒÝZMÚPìñ/õxÚ…VÊÊ?äbåM^6î§ÓtÖ½éöºnó³"úso±¨ŠˆÅEcX1 ª‚Ná DmÍà6u'㌤Œ²ÿG¡©‡:Ö¿;ÝÉ£¶®aЧæ»kúo’¦³ªàïü‹äÕ'8Ì.ò›<ëí®RUȺdØŠÝ“D®žo#ÈV·W^$sêìË›TüÞ|2ÏûÝuÛ_=ØéµñÛgÍÛ† ½M-Ò¼ù2YM†Æ™ícçøa×í÷FÕ"ÞïàY¹$$–¹ˆOÎaF "(ý±­]I +#$ž­˜`ͧ{dU2V‰©TT¦ŒŒAE‚„UD`² Eˆ*ˆ€5VFenÿÑã<5u7¿ù9O_.Ú1xSÃCµzÎEYý&gèÇ_¬ª±ŒÔœ¸Gi·iüÊ)Çè[…˲ß&ÄDA8ÿHÝø¢% ¥.óñxZɸ«¶ b>MÕ܆Δ€zÃJÁÒ~_[{¶}|üšj¯‰BïÏ,I3—»~OÑë0EÇ£»3Ð’à ·Â™§ß_£‹8ŠrÊG@à0ìyÓ7ޤhñ÷ ôß®yÀX¡ëýþsˆq©Lø8ÇA^f§‚úVëÿ–bm:/è·33¾p*r°ÛºI‰&ç\ ²Þ½¼›|oo™<Š¥ºîU `XéâGØñøõØHíVæ\ªñTÀt FÆcÆ)ô:>×ÐÍ>Öóc”6'›Z'f­~¨)š|–hÄD¿Kç{|;¦ K’êß?ØödײÄNBb CÏ<Ï’ÖUµ­Àöûç‘•Y™”¢ kw·6³]ë@Æ'O5&òâ-òkvÉ«É6žõw©SÚ¼§Z·§%š¯©ßwÜÝïæŸ|Ì©­‚Ê*¦õñx؇„ÑSã_­æ¹&v ²²¬×ØVQÕF0^*‰~»ý¼+ÔÌ~«Il©Ô¥=Ø?£6:Ïg)Ïê~úˆÒ¥úJå[7ëïHØ£î*5Ë nQ&§‰pQ$ÍïÞ ªcœˆAdGúvúcØýçªÊ”“ ç\Ô„®á0¢ñs¿Ö²%F3`§œWu[+d6Áé·in]ÜNosvµk­í­Ì/ÂøîNV–M½NÅ,(!ò*&C !;â™ÜG¿Ê€MJAÙZ:™r‰×&Âo¶Öç›s¢Îlʹ"ÞäšMBœR‰„ÖC9£ÚѬ†´‡™bÊÑ!CÇéCÇš%Ìt)ÍÉ„’‚ÛUô¿yO<‰moeÁµgÞ¾B±;ýŽ®Ô¶ªÔõ‡ä·³EYETV¼Ö¤óAÕVO.B ó&8k´íðA@‚ü"÷ŠŠˆ*¥¼XŒ—®*QR?êøO•–ß´õ°þ IÊ ?DULeàøàÇ·^W£3T¼Ì0-sËË™©ëyb)ö É~U·Šætï\^T·…òÿþÅŒ$U.£Ü2³2 Ø®Š£û.‡§ÉHœ2°/ÏÔèzðkª­½x/É6Š ¤Ùål¼ððLç[ör…þ?-“m>×ð-T³CפX‚z+÷ù˜‚ȪH{|¹»:{??GCqUˆB¿½ESpá‰C¯åÿk;¿[]è®.kûkœ"ŸŽÿ·Áºs—%ULv"Œí|Çx²—¼ª \§õGSC¹><ÏÑÙòÕw91—\xîdáRr¤OO>»wËsL´ú#t!w<æÏ c$ì3CP+¤W¦EÝWµÅÓ%ÙVÕôtD7n¤dÈ}Ÿ<‡0‰§gœ×Ë$ÍÿdÖÈô\ÖÈuàØYª¥êjÚÂýFD.õ ›Å3^+[ÏÏFú(Úi`¸ß«”X]290Üõáî™I½‹9íÑÜT@ña ®ql¼L}|õ¸2! üÞA£èìùj¾Ô%ž|ºÕ§zwŒù{[¬TUÙŸ °ª•_®©©CÅ¡Vǯ?PÞ>k-ÛŽ kÂë•TëÐêïFóo$C>ßϹéj˜÷%(É®,µƒ˜Œ15Ãf»ß›;i ]÷ÆÒ¹“«~èòª0QpÚèœW5¤Ì[Zóž=êhERÝ;²È]ï“ßç‘-à’s.b„ Vu§^þüÓxºó²ÞÆÕæòñ×l¯Èή¥U 3êÔoßv)Ã$Û§z!·ÌQž »ów¼±j°&”d:¿bó¾Ë†¢¢u¨/i†§we¦…84Pp]Üí¸Yò‹à¨«ÊвsR£øÿ-ÉeÏõº!ŽÃÝs,z:6mÓYÓÉ”ïñ‚Fò´ag<Éuë?èêœú:}µéã#ÉÑ¿V«²ãÆC]-J»Í8zÚêFg§ã8LhE ŸK*†lHødƒtXÖ¸ÅåÀj=ôz³{)ý:ÔëÅYåäZœGæÐós>HÆ]Y5ÑsA›ëæ•Y×ÌÕÆXˆU]A_6rí!zÕ¬0îrÐ~¼jê-Ó_ÛnmОéÁr¼Iw“݆}íGÚ½7ýæñ}n¾ÿƒÒÿÁÚ+ëÒ|0ÝÓ¦¦Ø¨àË” ÍÄ-“ìæ¼é€'€ùª›‹‡äñAuÊo0åËJïdÏñÐ?Ö^Ë\ðzð¶¤m0« ${ÐÓàÌ‘ wÝ> P!¯Ð‘ÐØ]ŠÿŠSYª:gÖ¨‰æÓÜoñâù¹‚OÅæÂ¸iÁ JuÅþTò‰€AÝâ·Óè[-ë<ñX‰‡ª¸û_ŠÏ‚¬ÌV /cæi©üþå‰I „äÃ[©›«ôЙü¹ñ•°h:œ˜¯ùûŽýó#BCsÇ2WWYÕyÅN[æ½00 ˜ÀB°*ïw^S‹ÿîqózGÇ Ö½9¼:<˜~rK¯aY6äckS¢{´å;Iв—ê†órKdv·[˜Ýª‹¥t @·‘Sf éùNnU3‚èÈQý·œ+)ˆzΚZ[„j’¿ž/Ù*ŒùáŸÃl~ÊXî˜Á|á\×3µî=S*O21Ìî~݃^$Cgš5©âª‰tÍoo_« %À¹,eŒC×~`_Ôó=ÅõP|”(~zwý-Þn÷dz8ÚÍò¥zðÍJ­?.éû³D7}=>›ˆØXáWtt,emÕÅ|ç{™\ÏnÖ<^Nk®7Ô¯ÁL¦y«¡›n<Ös¦#Uã=¬’:ýT—.¡ƒQ¨Áñ öY?ÓÈ WyO¤ÏŸíyâ=Ûu¨ÜBwJ+&Ez%”Έ— v>,BL÷tCëò¨gœ=\ÅnƒÿÍ÷#‡Áï°äCžÿ,†¿;q’`ñeË1Å|¬äÁRæ ÷¥i®"-Î@õ³ƒ§hU’³úmrôº[YÞõñ×E•Io¯dÇ~Z¶o2·îßNïë›MT^&È»}°ºä÷'âV¨ÌmÞRSˆ¿Aùòr&ùw§ÈZ6÷òUg¢ X03ç.IÀŸã `!ÈOÚWKÙMöÞ¦ã¾èõ>á¾ô¾ä¯È4jª5S_[_ªý¥ËÓr¥¥áÌ¢ Çã&ÎGJ§á|ûås•Ý"¹¼´*­(ÙïyʾÍÎRJg首 I¨¦ü¯êuCéå¸ù=$0„Xs ÇZ ¶^ïË雹•>G lýçCS–7wá÷pо솜µ”‘01M!~ø(Ë'WjYx¶F{®â‚½#ïÅ=7çJÙ°·¿¥Fr•ª˜»þZNFå©{Ù:•M‡VÿýTk)ÅÊf q„–±Á',–§mGXE;Æ?.ñFìÚã¬S]ò ¯ž ›ÑZõ0“0BÞ[ñ§œ·êßµ4/n˸À‰CÙèütN€^å¹yWYH7†#„§vŸ¤S"áUý†8§)×’¦Cs¼ï\é——(‚€¬É\l»´cò5fÊós“Ù†˜ÓT â;‹§ëQ*&añÜËÀœ•—]Ö>ä£Rr %˜]wþKÏ'c}yþ;ÿ]#t1**Ý,ñc@ ]yÛa— 9c•»æÍ‹3ß7ÚáÂøÞ$o »'úÜÄRŸ[f‹ØÀÇÝuØ{ñ¶$½f*}ÃL¤¦óêï\tæèÛ‡èCÝ9mÕWÖx2G©»dILäx†ËÏdf¦Žb4³t¾œºÿ2Æ®H'кJcÉ‘¹o¡! ˜·Å/ú[6»9-èG£ï¤!øK‚Jþñ‘úoÛ'€Ý÷ÿ ?…’cËÈïÌÌÓ©L“arçˆN,ĸÉD‚—áÛ;h™{2ÚPÒ̓1ÄÛQýÆ·r­ÚΜÏȼéfÒ2š'qœ]k†š©wf}žÓ;¹;xßuJޥשáM €ígÅßñÑÛö=Îu\¯ÆJŒ‚îr¥äþŠ×Ï×ðÀrC¡G„`bD@Jƒ·¿ Ñ[Áòé±7ÌÆ ¦SŒmxM˜Æ‹zÛ*CSëUôè$¾ª¥Í,_³%´“™åùõ¾x'z|¼S»‹´õ¾+ùügÓäý¯…Ìlý/" €UP$Eýx³ÈÏS?ìíòÌ'ä]ä/²aùAø_+ý=mÖÁCý¢¥ÖïC˜£Ý|º!¦Pêù÷Vìs,>DÀ&Ž1Ie2Vä50ü¸ùNr“û`€zOÞ¯²‹Œä¿« 2‚?p*$ENcwzY@AÿêýRüí{詸BnŠî³•· Š‘(æŠÑÄ%BBÜCŽ0Sa"Ñ9  *X@”IPAaƒ0)a“ 3:èÙÑíšù˜Æˆùþ'Ý{3ä)0ñVîÔI(šöŽ‚°ÔdêŸT &_$ø:(ÿÚhžLTaß #!C:g2Mi²`†"Ô-‹ÓVŠ“3/B3$‘¤f°"Œ,ÒÒ§3 H0Ñi,$—ù%è5 ¬+jf0›ø6²‰ Êà`6°ÝPÒ–Ì^ßz¡Lêk@\,Db óxáþ×)Ké$ "´’,Š…Rvà G®"ÊÚ˜Gi<˜a$ñíéÔ9§ ð”pªX‹y"ÍYdä/ÅïJ’ïÐÛ¤ˆðwàiI²–“óÎÏ¥§OSþÖìãT…bÓ¬uf¾Í3RÃHÏ™)ÍZ“ŒU½Ü1WøÆñO¸þ’¹÷ùô.pV/8: âÂ4l+¢ÇodµªÆsfd›³ê`f@‡ÌÜ(¬ N2IŠs¤ÞT¶Ôªí)Oøõõ*È÷IƒJ Í¥Zjb±™¤ò‘“zÌEÅ™dé„Ñ?¡Í~É*"lPˆB‚ <7Hû´ý•)<þÞÕ)}ÍÉ^äüTmeT`¹8x\¿ƒ±‡ªÍ¶Løm»Ò~<øoŽÏ‡Çã æ\{ɸ“kSz€fvŸ¹ÿ %ëú=úúÝàË3Ýæa?½½)ó~¿yy±ï«oqýdÕŸnéŸ92OŸtMpÊ NÈ´Àù¨k|~tSCæÑ4¾É-¹ „•5ðÆA ‚ÀËO&­Þ“Ãn&a^*ÇsBðÄëÐ9Ê+tåòÔ´##&Ä0–!»@òã»qf+“¤­öLZÖep÷Ú86sìcw—ۭľÉ*¯ ê–Œ¥­´!e‚m …¥[,‚2Úƒá’B]fö‡‹#ç9œ=q‚o¿ÝH·HtP Bí¸1PŠ’ŸÁÌë<Ï.óù¿=îv…2 \"1Qˆ°Uât_Ó!Œd"#¡1 ;ÔRéÐ×*ªZ¤"S jFeÍ"¨Â 5ª—4¥S!Ôš]¬×Žö9ï¾_‡C0%–2+PÊÉçå+»|ÄA"6™|5,<>vgÉÕžïo™É#Áþ2’ó´Iª)à‹™|ÖÝZ‡N.|•}-ñ9¼‰vX¾ÛZ=ä8Ÿ™¡ãÃXgâÐÏP:£ !Òb1`Û@‡:ÿP×›à (µdšŠ£êŽÓ2D¶Í(ª€¨€')*b¸+˜3f¥þ†ïŽáD¾?& NŽƒ€ô4arQ¨È%Uk„©£wØ6M¬ÆÅ¡æM†Õp²+bšº»Úó1éRdÐ@p@Èe4üÚx;´òTæ‘©K@³" u¬Þ.…E<îc>4/ïÏý8 iSÌp[s^¶ÑÏNë®§%±'¤?Êû]ìÏc¯·µ…éwÐ&¹XM„¤ƒ’ü6±aœ|Z…XËG»z !ªëŒmž¹ërúë±Øxz=k=%åÿ¢Š¢¡ÌÆ ëⷵ粩+VN*«\òóú.h]‘ N+þ óëôçÑFun×|¼ñàœa%õnþʺb‹†¨šaÞùcLò©߀øG’Þ,qix{@õ•¦Pü˜(‘`¢+b,Œˆ² ŒD@Y*1PPDP`Á`ªŠ‘APX‰ ÈŒD`¬wÀoXLúXi–’åå86I‰EÅK¦{*.µ%’Œ ?']©Š¤±ù£DØUÅùã7µP F!ê¤á8•º‹EœÁàÄwqî‚;®$‰QÅ#¯¦È»qÇÒ† œTÙjþÇEÆ[ž‚f‘u ’,Þg=bAÙªKÝÙÛ%k}<z?bZõ·Iôyxu÷ûúlº»eö¼šûC¸Á¶œCÁ!%7öz|;ÖÛ ð±Ÿ<¶§Án£K1»â9eú;ȉßêïãÿã@®0§Ú8týè{ŸˆØÚ›oF®Ï¡ÍÏιf²O®S÷ÚàNâž²n=Ûù“­ …c–7ïÝ®bùjç¸mG.½Ñ4Ň!árbĮݰ§rìÌŽã~c{N/_Ù'KÏœ^’Uí:¾“¦­¶î{Æîášžß°Ö[¯'O¼sº®Òàæëõ äØË9¢vŠx¨ž4–¨U` 90ìÀKÔf׫¶Ûî4^n‹Å—£Y•ÓçŒaÍó8>„fø™•Dƒ°D”;®éY,ª×îVþ8À­ñ|†šæ¹b½(t¹¸Ö Ïã:tï‘XˆkÓ±½’h,£ §þ]ú„`Ÿ'[Åm<•Øý(w‘â\Ó-–;ήœäg²}e‹—€$Qü@~¿"NF¨‚8:z|9ìßKk²íá=2c¤%]ö8ӌа²8+'BËã•s&Dì2iD:Ð@„Kô,]Ü à’j±ßñ¿ónÐË=DÄ88º ˆ¡RBÏÏô¤wŽòx“X!r‰t¹egÝ/¸&î—Oü^ù:íN“"ß„Nqö¼ÔH…§r·1³³»sY *kqá747¬Nþ)íÉ1_°·Dþ˜ÐE;ðÇ_f` ¦ùž¸Lðxµ¦óoXÖ!‡¥ùºHˆ!vüÍ¿éê*ï»nSŸHLdpÃ#'÷1|vºŸY(&K$¸Úä0G<*l"&—ÖŠHóOEÒÌŒÌ /0Ä6up˜ÔÀþïg#Ÿ±ªàóDnziY'?µF6mÙ -´ƒ=Qºâ•\¢G†bˆ•;H°®3n„Ÿ‡–3ŽM»ñŒ0׿Ÿ™Ä¬é­á!Ñü¿&jôL+Ìt˜K$©³,:|˜YÁ³ç„TÄŠCTò‰¤5>Õ[±e'ŠÄO&‰\¼Óª‰ÔÛŸ¤Ó¿Mý˜˜Ù‡6ÏãÊhŠçs¥È½­yR~A<oêµîïÕ Õ2F_“Ì&(œvyýð‚y9¶¸I‚cÚtõ&¹è“²§(ƒ;z¼•ŽÞˆBæÎf¥Û„LŽS56VÅûƒô¢.<„1/'ÞðÀ¦šõi³”¾Žzf…Äõ›2D+µfr^h¶YÉ-ƒ`èl˜"ß'.=À@£@AN°PFýׇÎmsú÷æ*]^E2t€!×q ¡Ã»o$ãR0ÜÛÏbh÷a)zgæ?´øtbcøa>|ÌÚM¢>¿ÇûK>̳U»: *Es¿}9é|ãtòR¨íCsBGè√ø$ç0˜¨g×—P»‚gâqmѧY©,¡¾tžuë\!<¹›•»5ç­Œó\àSÅkdü^M½Aµ2ìc§tîHI‘v%ïµ÷¼ËNÝu ˆ ¶DÇÕGÙ .ƒš®1rʈ‚¿pyv77ùújŸ“ÕKòø&ˆÕ~ «-þH;°±˜s|]å‹ôu#Ÿõ·ø ˜1çTÈ}ô¯Sc¡ÌxªÍ%/™øšÜ Òæz±r‰Š€?cGÚdÍ_«ܼnl¬­žLdpbñùVR š1ÒàÊh.ñ÷ð b¶]™N5Ù`ùª„SÌo“ÚÕk(§¿ûüúNaù¥3¤3 “áõíM]RÊü𾺙m%¦œšVŽÚÑÏ ™ULù^ác`l‚6áz¢ ªÈôÅÆW64×f~»úWHr1Ê<ºÚ¯¢ Ž:›H\å`kØô˜¹«â è«p1ÙšwZª¨TWk°†÷õ}SDÜUTüûMÑ`òÊþ‡k0€ó?wéE/àù¹êX‘÷URÒÞ¨Ènn›%¹S Næªè¢¨Idà²_U9E½jï¤Ï¹•9kV¦š™ÐÑ;äæáÌQøeëëÏá|â6«j¶ßL»oAêv9ðüL‰©HuK<•«_;umR%1è¼0X“É‚‹­éi0€MP5÷5æ¡‚H§-¦(=¼ï´@G£i$žL¨Eu(ż˜ª‚yc–öogß¡Éá4/ãX`õ)Už®T˜¼›é–Ÿcö ü64p0^Ÿ-9}ztË/n§J*ˆ(€$ý8ÒV's7G•ßÏAùÎþ¨h 2¯:V† Þ–o } »wsG÷ORµcùûµ³É{;Ùìs(l†QhZLè ¬lÜ¥õ\@ð©šÄPĽŸ=zÔaH¯Ì†4Õââúóaª/€÷])ÈݹGÞjÎG‚"²C9Œ´£ ÇÌã‡,ª}/žÂ¯Üé×–$,v^s«½R!p Ú6e·ÐÞ‚"&ÂB‹Q$ƒs(ç^œ~*+ æ˜×⃗ Ö|´}ŽAÛ1Œ]‰'ͲԦ$ º5%­±ñÂÁ¶ø);ùG¼L¾±ugÔÐôáÇIÊ]g9ß%•—&ÍzйH)©ƒjªÉ¼J­F4¥ü¥'wkÐ:Èà­†Z+R-‰w áx…2s›5½ ’~ä³[¥˜“Î8ÈÔóC)¬&ŠŠ¥æÌÓCki ‰µRÐÚåÛAcð¿¥0!84v42}ŠS«=/ø–¦ìéíG%èq“Ó´¦^÷#ž[÷9å«zòCi¯iíwuóŠ$[r@š_,EmñŒ$fΨu9×Û”zqÑî»Öúøãa\ÏÑ`š%2ê¾è jí ®——ÅW¤hÕ¤ o'e¦YDÆhôn+Ÿ†¯_½Ž–•Ä–ú6§è¾rww%);»Æ,ÊØÊR‹ÄÐH‰©‘Kòˆø,U#YA߹ʩÍFSØîù6k“mnÄ:µ6ÅóÁˆl:Ugn®GãC°ÌÄ|ŒÄ lèäWV¦NX[axK—±èØ“œ Y.Áamh àwóÔvDôb øšGlT±×Ú°f¤Œ£¿¶kŒ–[fÙ Œ£(Vt!K¹2ä!¤&ÓKÕ6Lkåg!wÌtqo'ÎÃd ñÐ]ȵÄ.PÉpæPk¦¿fzUQÐñpÝÑ’BõAçÀ N‘È„v/qÊ=žÖTìhDœ)—»Tõmgh(ÍËÑÛ79§$_Z=[c½_:u¹º’’Ùb£e*\G‰y`‡‡Ùa+é¹·[)%ý¼¢kƼ³#©e·hÐX(¢ÜèÈùjÄâ¶ãEZ²-bT…‰®ò$@H-êOé&j¿V«Ž f¶+ã– =Aí«ª‚VXÐuåd4\Å@ð*=ÔxÂ?4èØ•HÛŽl—Ý<°j•܆åßÑΚˤÍo.Ëa* Ñìo{öUŸ—wwf%—)~wŒœø"¾[“¬ù÷£ˆ{íµ›T[Ž wW.&³µ„ù¡M<-qˆÔRýaýG rL'Ø´™FJKTÈ-Œ*²$”"OPΑžã.{Æ#ÈŠ†ðº™©š–¦º7 ð°ES̱”Õ4i}õJjf왨6·™ªo®yxT06t)¬RX±´Öü^UFXª!,ò'b9ꕞ šhùZê}{}šÝ‡-=+WMôüË_52l[Ò äÀëá! î©X2Ú“œË÷_—·+¯XÚêüçødc,jõÇ¿|"®©°¹¾¹†7HÆ©rñŽä—J}‹:ñwÂ"˜uÊBǶ HÅO®¦V Ã2 ãÞ­$𣗰‚4 ^êÇi¦{iõtèœÛ,zä*LóÓ5à3l›l`Α;ev˜SKÖç7dЉ†$ïF;»«¯ÃŠ3Ò/Uz¡²jܼÐã)EÑ2{+—»€ï+}çm6%šÆGZ ŸâúÛå§XÂëý¡ñ- ^Ütày˜€¾«^¨p€wÕ ðýäP©ô ¬Sj""ŒLb-§\¦Ý'¿6<î²¾nñ{YíÃ˪]›Ð§Ì΄ìãÒZFK ²F(ý½NYQ÷÷†ƒ;0ø iàÔu""ÂmjÜiž”Ã;ž’‡Ñb²°Ôupˆ¥ùH´õyg·ÇGNNGWOéÊÂzwÃuJͬ¥ï±ÛËsÎL¡›Ô½CÐs ,¨Ä¬q]`ý­î³“ƒcÌó1\À“^µïó¥±úîw.ÿTìµA¹c¤1RK’õ¼4ÌÝ|\˜¢²¡) èÊ=ÊJ%uó.:[:i§&¶áÁ+p¤Wõ¯ lù\~Çx9¹JÇQ}eWàºk[tŸvAvÏ5åÓ•·rÊá…’Åö`ÅÙGæ{pÛÛo7W yÙyüöÙNMoFž?FÊ“SZù¯Ë9cvwjy*Å `Ó"Wçjáθ–.RÙa!pnSËÓ tTÕVÅu,¢««êªŠ*Hf¦UKü‘y›Úð¸‰XPÕh.4)µ+ß„×ì™ë…å%“Á!ævÕ õ;äSJÎK›Hºù7M䥺™ð¹·ayòÌj´Ÿ`ÚP¡Exw1ò›‚«ø•ÏÈo>™óôYm|ûš¯ŸŸ æTœÑüY#fáA½Z›%½ÜW"*x·1k6*š$=‹|K± DÖ•ê\(ªçaS†=3ƒ èßð„„×ç´ð]­L/ Jý»$«e†÷zDM: lŒ²ùìÙ©¤Ó’¥¢-nÞBMgv¶5.1Õŧ¤š:§GÐræ_2‡;V} Èíwœj†5Ž„Æ’ŠƒQ¦=}É!œÝ×M\_Ùy"'9™r¦Z úþO.Púî™çÙ·×ÛÙ•µZ3mò–´? îû4Ïæ¯Oµ÷9]Ž•úúÜëô˜ ¯{ºýÎÆ»à6ßöý}1ƒ{]÷æ­NñŒ³üÿ¿ÃL¬üüv>þ¼²‡g{HkòH…atÕÐÛÔ7ÒÙÖÓÝϽi”é]¼5vçwƒ†¸o±¯ÕãÝø³ÜOÁ?Lz,Iym¯§ŽóU9)ªã›\£ºí¶ï˜év^iõÆÉf§f½f9,=¨ý»0ì»Ìü´VÑ£÷bðªÅ ¦û“O!3äû·øw6¥9aúüKáÜüÛõwºî:Yƒaó{Q>²¢ª@ú̹úê옷nx7‡Vë§óŸ”.©ß~åýùz;¹éãOGÂ(„ ïÛìýƒc•a“)FÅ”»…×SÐcyH›— âœè‚^:{ÎÅ}Òfí5Êß^HÆP¼²ìÄ“ü †Å6ºIó8ex"‹šƒ*“XªGeô¬}pÉ~+Í(¡Ï­¼‹S‚|Sš%„e‚‰ºr4E¿nšüoäÃI,4Þåž²ŽFh¥Ú9U ÆD™9H¡Y³xv‹á†ñè.6v«^¶ë¡#~ävII»M¤zæq˜T\»îŒì «ÀËêñ îùsÑóz¯ÁéôÃ’/R¯¾‡Ÿ ¹µË‡¸o· z)¹¥š‰×V?”öÁôd%ß"ÙÃx|³ó×Üo†þ†6ü2ËvÂzøCZðÆiÝÛ ºö—Ý©'«!ÁŸ%> NG†Æêv²ª )5CÆ©‡ˆònÃwº>jrÎ,ºs­ø-¸Þ>‰îï3*È@âϾåÒ<15jâèQB˜­iŸ+§·¿khqÑÒìk²Bà¯&“et- %VðC^r’RŽû±¿lï<͈ºg|ô¡‰”Þ ˆL’¦>x êuÓIæöó_vîe^RI¯»ïçw-}:#©=­ßÜî.ØÃbŒ,år‰C‚"`È9jè2¸£µy2ëª[»ÏLLûKø'!³y5ÐÔgŽ’­Ì×A¥fk¢Î²¸°x 5ZN Kõ¢¾¶1÷!GÈÚ¬æ·1¡¾Úµå#+Ê>4¸KÜ­®á©ŽÙ³Ž•2ÜÍL(B{4Ä rs ïhÓλ.“µš¶Â ¥~Úýv’NÌüîK²Ä¿¿Ñ7^¼EëO3CQ¶nNY2C]6zpV’âT赦#4[^Æãb@ "lsV€ÐU»7 tŠt"ŸMP;2ØÜ.åÌ&ÇdŠÐfRq~?#Þ*¶HlׂM‘1ÌÂ<$ÙÁ2Æ7¢Z.¦èâxsÅÍÊ“PZcƒvÞÄ•áŒ_… QwÏ­ê© Óc쪵%£áƒ½¬–J{9$¶0FÒòÁ æ]@(”çd7ëàôíŒÈ!DD É^IEeJÎwk~™ìÛ›y¥q®%$»ÍêkÆ]eÒ••ñûÃ×·{0kZf‘+4²Ô”Ô› ?F$Z&H¤m®ËŠ;ÓY©ðE’,Õ~ò²”‹}Ø ‹UÅLKÚ8Ã{ìÎDšÌg&Ê 7¥œ­ÒÀ‚6ºeJm™šAˆ-T¼¤quæÍªÃ%îÛ%xoÜTORIŸÛ‡ÅÏw‡T>©ô¤*—¤É¤&Í2r=?\:†<’}yþÛ•ñóÇ9JöªcÙoíøŸ#OJ}ý.'të”áB9.OŽ(vô)‹K3õ¨¨„êõ' úüo=ýNúó#ík§Bü2W(’ºÎ]nZ2‘Ò!¥J‘#$r–ÜÊÉúWW»~ÿ¢n©!+ê—P~?N{dÚ^väIëX½|²>›,ñ¨ë}oè• ñÓZ¬õt¾/îOËzžÖ${xy„µj k¢[£È¯çÉÚü)óÕ3¨ˆq(ên^Oê*åÅù¡¨«â…žT©Æ  –±#TTOy_b­(}3Ø“ª€¢¥eôZHH˜Ö‰ViW¿-¹Àj¹_Õ¦¼:ä¸Nâm9c,#i–Ö5/ ÷#-‹Ú×ÖVûð$?tM{úòTÌ“˜•WÔæ•y>)žTsø§]àl9Ù<"íÕ 3XÖbBjºà¦êW¿É0qCaó¯¢ç"íx$¶[¤Æ)±Šòµè¡zÂé= ™Ù‹ÞDùA)2”ªêZoŠ=%vQJÁ);EòÛÕÁÍI'k'+ ^_#,4ÁŠ. ¥F[J(kZ*K1 q>5Õ›*˜lÇ ]±`¦" 2%–Úñ×}}càí."Óõ¼¯(|o.ªç ¯Mÿi¨šÍ¡$hKi‚¤†NdïÉá)C}“–¶îJBÍ}m¶0†“±Kj)†2 S­ £rŒ K”qëè¸À‹Ã•+cʾ˜G®>«?)´7r¿d±³ †Ý[{±jW)>>ÎÌ$· äGÄ\ #\Tj ºbraí;©Åã¾\)øXx¶Öp|Ûg%Ü'2ö:*¥ö‹†±ØÚÚ¾»Of¸ûKÅ#›P½%—Ž}Ì1æ´ñ&br¿…W'\oSµ4áã—*?fÎýhû:³9=OyÉ&è«ï½]§×cCŠ*ÌÜEÚô5àc¸Ël,ö,ÑX²æzÙÏNaàxWÕ§‰Û+ä;`—D¡mBrñE"µ%Bò>Ó—ª E zº2º>Œ,–ã¹W}ºSh¢Ø(S™w¾ŠÚ;mË 7p® \ôëmjU&{¬—ŠˆòF4S¹tt®í‘ß«VèÖ„Í…Y(¬¾ˆ|Þ¨>\ž Cª‹áÇ›f &ÏS€êrS™P‘K­I.`·\ŠðX/ úPßÇwÁÞÝñ†à&Ó šo§rQUU!4ÞNF#kP)Ÿ ERž7HèA±e8Ä!ÐCh¥ÍF˜ÈÙµW…L…ð6¾ñä÷Võ2Ö}„âJrºáƒh”ÕϤ…Te9ûô•×{fª¥ýív—d%Í ÖSœç9N‘U”¥YZRÕÀ¹ëÛ«›>ˆc#’+éÁ•bˆšxŸEèðäß&£ìžÆÍÓõ4n54^*5ïnŠ!Öýl…ðë‘G`¬z£sñtC<ô5i!z½þ›¿ Hò#‰,DÅNÛœßðäŽ,%Xbû8¢$ØÉ Ë ìj‚µ”ب/;{ BÝ šìÚw3B$Q³¢;¢ë£@ãgO‰cÈÄ —1ætDaï˜it‘A\5@ni päP“3DU>MÚ ¢“_L“qãŽ/0¥Ò¬–Å„‡ j—Ãà2(ây¥¢%µ8*@Ü kX âuÙ;—¢il¬­j 7Å8K·&„j¬‰€™©ÅMdeX»{4;Ë=÷ÉéÚ˶aηÆ=§Æ‡hJb&=Xþ&¾•œXÄ[oÞĉ ñq,‚\gï0˧xân×{k¾>¹ÌÞ+ÎS‚5+x,ærù|±!›gµy=ZèzÆ…a:=={WQƒn¶4¶V]Úò7^¿% ùKÀ¨øGx³Sì0é.9ÀvZF pΚñU"-òÁ2´ µ‰ðÚéØQñÃ&Ã)‘}øY×ëèNW÷A°”ö©z…¢Â bQ³r «‘®%•n VÓ¨ÕTÔ×AfŒ%FÎìf`‘ÏÜ}Щ¦½PÜ‚¶Ÿ½yÞ¡žŸ·ŠxÄÞÚ´º¹Š*6ÔVõ0Kh錭q zØlïºLQ ˆ1‰JÓ vÆü0^h#ÝjÎH‰ Š*å¿ÓðI½~ÇÅq(’æË8nTj{›0ûvÂB ®Ìžâ.B&Âó{­X(¾ÎôdÃcDöâ‰á öª¬³5ËR$Þb΀¤fປÇc.ŠZËÝæRQ™áÑ#mHv‚LJ"H<¹ –/9€à̯3Âòvãò²¾‰¹›n¦JOÜ~Zõ>ع‹Jg%žP;s#™Ñ'ÍÛ €2&(ÊÞçJ7tZëâ˜ïâA¦«r»ÜÃb°*Ór/v-£—)•ñIÊç[ÈQ·Îûl'UÁ°aÞ ËEî­÷q©Ü+—ÍŸ5D¤£aOei-¯#ŽPyÃ:®.ºµx_ZüSûçgÌé×qPÍU,V¨VnhVjB«Ï ¿j»é)]MpHM;±¢ã%НCmåÓÊFãÐÞ®u†ÇÞ¾x¸uʤåìt1±w(wUëÝm'£¸R:âüš£±k¼«ë`¹ÜcŠãÛ9Š©5eTС­7¹4$”B´][¢bžásó©¦\sCo—-Õ»3«Hq©Ö°Á‰°ô"j2¬r|4(¾Uœö—#ö’˜Õ¹ZË(-m¸¸U6y§ð_#éÁù¾‚5±Å(@U‹> R’ôÍæ»¢1eX2¨ª©_ ÀžlÑœUÛŸ™™ç-Ûþ?.û÷*…0úø4ضŸZ°ÄêÖÆ‘³’ÂH‰=ˆë¿É/‚¬ë9r„ “7Åaëq¤³¹îzuBЇË2Ò/ÓŸSëLg¬»ŽÏ"ë}µìyF1·]ØEh„3ö}>s‡´kc«‚¿ŒÝ5ÃoW0‚2 †¶dBL\}Å ÃGŽ•í2~úþr‚äÇ+Œ‰8ãPÂFXžŠ’Òú'‚À¨bQ MP–¶T®L7 ÷fjV“ÓD²ÉFrGøµ ñk±&ˆ¸"ŒÀÑÆÿ>ºátyrÍy×TJ¬`Êúê7Ÿ,¸›Ìv€’lxŠMK DŽÆ2 ‚D‚Aù™G éÉÆzZ÷ËÔÉŸ‰¦Êøž×û× xŠõ¢oÄ2¤«èß!ü5ù?zxçn þàkÑ9;ù4[l~²ºóÀ„./ÙK×Ðt8s—±ù®¸®ÅÞwâ@Ÿí|Ö:½y£ÌC`3}¿w6&’þµUL {iJ¸“rÒD¿äÏt1®±¥º_«g0íqÒ2·ÙÛ°·îýwî|ß=ì„ôþ‡Ý©ìÒõPñ "{WŒò’€gdìÚeÞÃì~ËóSìru×.âL’õ…¹Ù€Œ±Žª«Jæ}E«g 0¾µè¸Š’ý¬©ýæùl”ÿ´ZÃnúT”.te|1uf5¾“,Hýø<+kÚSoîi')¹§{[iK§YCo¨Íùx£ßG7¬^ ÎoiŠ€×ÌÑ[ÔŠÏL|Ö”¢*&ŠÚ)J´õH¢èˆ2…TMÐIGôa„r§e³ ñœ‚ùYPZÕú{þ;´)ú›KŽœÏÕSóq=?L}( ì}~UìÐ@ <4éãÙ[Qn}f¬òº½djo®P÷åScê»÷WêÎOï£Ø°·S“à “»0%®«¾ä@Ȩu4mQ—’‘PŠSƒ£ç\áMëe7ªvšKÅ”N¬+¯Ÿq†=ý³Ø/4Òk‹ªa6‚´ØºögVÏ~Ì1“‹]Œ©-Ò§”µÊ|–°×£÷é(\èÊøbê,Ìk|+&X‘ã…m{JmÆ’r›šwµ¶”ºu”1fï³u5â}Þ°Ax+9½¦(€™¢·©ѱ§z6Èš3hÄ*ÓÕ"5‹¢> ÊQ7@a%ïßÜ©ßY_v' kBPB+3S¿¨¯¹™V­w}Ï­ÑìÚkƒ¦Õ;þU;4D0D7õꯩõmK™õš³Êëºé&mõ†Yc¶üªlÕ »÷ãªß¯dHuYÉá³Ó ˜¥Vžÿ ‚B‚?¾ʶÒÅ¡à$B ²ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªÛm¶ÛnäÝð~Ò>wý)xA†Œ?N^wvœ„\ñP^" âíßÎtìAì¹ÿQÞ|aÀçéïøñè3Ñçwð«±Õ£Ë~ÅýZü>¹ü­‡^ïõÁ›>‰k{g{™Ä@ Ê|ªŠ¥i¥'ûµ?òÜë¾×à¯ØØïÑl"Ù#W{bòºž¥ïûG´îló}µkûŸwíP‚Îíód°è@t =×Ç ÎZý½2=Õ'ð{]òܼc OǼ—-Í-^;í[¹[øUÄU,­J­MRw„®Æ1XY©t1¿½î”‹cv¹a zk0½î]KW”Uï´yNëeiÇ8µ¯¯‚ä·ÕH ™²Ú®)ª•y¾7ëÂyÆk7 Mè§.;nÔF­^­“c«<%Êâìõ\@{ø;]Šª©œž| ôS¶©[c*•Ø  d#Þ <®¸~û¤Ö )?sõu¯’iþ¿êÌÌþ/Ö»™§úüå·Íï•UU¬eyÃ9ëçG5m‡#·<ûËðv’¡«®]WôÂr•z°Îè¾/Õ|´™~0„Þ {–kÜž½v/gŠOe¯©ÝÌn—ǶQ4¢ÐeIøž™Vwê·Ç pŒu·?G7kö÷»eÛ)*Ï¿MÏ⪮q·ÎsœåUUs.êø¦÷Äù—çk­l{êùuÖ¦îxÔº·nÝ6-kMnqÝo6Þµ•¾N÷MnVë4N;ÕMîõTïRçZÍrvg'Z›­íVYºK/[ÝÔ?éâ:(ºÍÎúës]U×2yµ§œÈcYpºsh¢sê§8ˆÏú‚…‚%(…¢ÒÒUDªµR‰,•Ue¤J¨´ªª’ $¶-YUHJJµR’RT*Ä’|@éˆHä¤KP挲æt4s¹ÛljÑU Á’Qì{˜P2HŠ6h²Œáa¡Œ±páÂCFŽ’hÙ±š4P3FhfÊ –I¢‰"I6Y²Ê0±2Žh±QÃdˆ£DˆÐŠ,d2H–8l‘Œ¡ŒG¢ÉBà£dpٲÄ’<@p£F„,ÙpЋ$gFŒ$Ù&lãƒ4HŽIÂM–2M›0¢BN±X„8hàp³ †Pl²Ž *J$’͈ ,²N6h‹$’Iƒ40ᆄpl¢ˆ‰,Ù`É6EQ³hT"ÂÆPHŠ7ª¶›[ÛZ8A¸€èˆ ¦÷äI¹¼àââÞ“,\Œ›Ú&ódp’Á#€Xlà 2Ê F¤áÂA a¡–hÀ’ͤ(8 ­[†ªÚ­é“ jïDµœvÝü7ñç]·vª>9Þ¶·k­]ÝÝó®6ùwu\ç9Í-Öµ®rf¸[\»±+ÌÛË6›Y³ia&øŸ4j7ê¡GS0¶à³«:ækW{PåR3š¡jœ)U“„ô…õBוd¾UÜ©9ÝÂÕç£X«Ëñewß>ÖŽû]á" îèíëSvZ»tvÑÂ͆i裆É7ÎQz¡G;*n ÇN¹×ÕÕõ¾¶.çy¡ÌèÖ¼Ö"ºï®;èü}gV €{^¤¥@„òÐPR˜ " }¹]ya Š(‹|‘|_'$–Ù‰†ÚUƒ?ª¡WBX2@ðüÚj/Ÿ"³j¤±Vú aKUwïf s H«DNª! ÁbȦú cPmÞtʼæËuq.RBãR l« @I$ aq©D„-Tû‘Øåïùöîúηàx¿¡oÝùß×äüÿåþMúo`»ÝD™©eÆÔ@ÇñZ9BK¸„1i(¨Ä7Ÿ_SS:Ç©=¦û«X@ Útþ.e«¹%¹Yëù¼ùÙ!iSVB¹6¿×ŸAeÍgŠhyÉCigò?žiëG’]y¯7_?ÚÙCíÄ"n°„‰¤+@T‰±9se_64Èz¾{|âÄ£kƆq ÖhbŸñÿSú¼Mwè•d$¡úý§ïò¯¿…Tèª< ¯ç•$’I$ûŸgé? ûöˆ?Êø~+ø~6ädÄMVQ[þÆÀë '4¤v¥uý±œD‹Z³-V›em9L¢ñ]{Û3.ÝkíWéˆ^T„ ¶mS=‹N‚ÛÚþcuÅbøw ßò%b9ºÝ/ÄFÙ1} Ó¿£ÒO{UÂáØ´:ª-e«}ïª$ÍLû¬8û¥ã°²–å"è€bÄNÌ‚„qöÜcB즸C'èzûpø^×oO+íü–uÚÊÒ‘'²Ï´Ñ›±Âùö„p‹ˆ%”i@b*ï¢ @Và~´mݺÀ! [? ÉC¡`˜ä¾ë/²Z¡†`¯éóó•<-yQ„æqÁMQXçùþºî«¬1äÿ÷z^k«ÍùÙsÏ·×WI'­V v×Ù­+]cþc¬ÖäDÿüÝ“‹×ñðòS¦å×hYd¡‘!…ØÂœâ¯îª¦óeÎá£XU³ú~· UÎèW§_ÿCéô= ÆŒ-ŸÐÔ§HŠQ‚Jƶ³¿t9µÏÃO‰1–‡éÑŠÙ뇾ÏF/'‡i:Ïä?'ݳ¶ÎGBøÄQö>òhD5üx›ã_©=þ|–D`Ï“Sà`ŠGÌÞÐ%ò—6m¸}‡Ö{a!P…­ôìïîQºê×÷ãâ¥õ¥b tOy©¼4Þ·Qš8."#DéèŸ/Èy§c¬ˆÅþþo7cŒ³FLTUMašgó0/³ÎJb†eû¢–T"…n‚ch°‘[R%z¹’vȲ”#W ÖܵO'Žé›)²ý‚ÁP5€¡ ‡ˆ»’Z™Œ“òKS%ˆÏaÐl”n”ÃÕÏÇäûü޽° ÈfYXþ^k;Oë?þëÓÅ`²deêŽØìH*7úš´ò JŸ­ª~Gûîÿy½µ¨¸](@Wh¯ä©€zd?¡ö\<(ÒüHž¡?¾¶ÿÑoXùê³/@béCÛðÿ$ÕÏvxÔ[ÅÇ¿Pz!6Hs“5[ùàÞz˜ºªªç¹© ú"Gï†%ýš’²d…å¥IXÃlÕ@¨ÿS!Ÿœ„ [6NËŒùýsá,èÿ[k­9”UH/¡ ;~-g–ŸüÏ`ëNý€yÿ×?3æÿ¸»CìŽ7w/•ÑJ±Î—÷4˜Kÿ9ÍËÌph’IoܳÅSª/X•²÷Oß ‰ÍOöÔš‹ëüXŠ%Ꜳ]Ò—šËŽI‰ÍÙ+û¦pã—›>°7ÃE/Ù¹ây6ti$”÷Ê «!î,7~TÖS¼k0é„ü¢Šðð€'³=Ò™>¬t ¶mHºs¨Œ«H1% †„Š 9(EWäQN0×>Ф©œýx^’C)®¨…i9´ Ù3¾‹•üå"Ü“‡>¯*RØ. ¯ Ðxi€ó—uòûsÉ5 æsô29ºé(U@øÜ„öþN8Yv6¤ÝKà MN`X¼WàdC C› éHÄ"õ´ ±QVï™X}Q#óÑÂíȺ ŠùûÚS!a±$!Tœ–ºŠFJy ®nÿ_v»ÍòèT)D”d%è§îà¹R‚*Ült¹N6.¬ hñp—g:Ò $‡²216©SaŸ«Ðz¹Ó3>¥@UhýÚ1š/v»2ƒm‚5Ú%°w*Ÿ)»Ù¼ì^4™¹ ` 38ca$I˜˜fש»¾s¡Œ&À ÑeR­ ޝ_£ ýìm,A%cìûGæü$·åøŸìCègŽLæñá;&ŸÚ`x‡+Â4ðþ<Ñ4zÜ-‰½ëvo½!!!$‘b]Ó¡Jhà9 RëO¼DºÚz ¤$lm˜çÓFÁ•…×–áùÙ8ûÄî3{/CFÏ1 NÂ¥"8ê·šó‰Ñ#ô~ã?ú_§ßûÝ[ÂåNpU?pwÿ¯œ,VÇ*ÿ2{¶söž“¤å™¹s;<Ï/‰Ñ¯çv µ¸»G:~˯Ç[þ«N\1$dQUEc¼j<¤"n?4õ~ŒØýO_Ô:Ý™Éý®~k½ŸZ=š7W³ÿu­Ÿù[|þ/Ð÷¿}»B\™ñ+ß‘L;i²­—ªsËøÔ”RÄø7 ï:-\¼Ýïƒf³ýW½ý;ü}Þ?'­0 ×ËkZÖµ¤ˆVi9ÎnNÂEE „añvþ‹º–¢ZFX`[ïK}÷j/•œšrxœ©”µÊž±Í[ª Ê¡w.ÇU¢XAÔ¿cQ»ûoÇß;S{^ñŠE_Ûöòýnâ+ßÔùeîýÝ"eÏ[s§4±›~Ƥ=™Ëüìöò¹ó»ü¶&é½µº3{«ü ÂDÁm®óxm ¶J ‰ˆüKaànx|ºX! †§ÐÝ[‡‚œwÚó0§¨gäFåãÖ˜$”Aø^»Þ 2ÚÍ‹0¡TéCÙ½oD£õ©ba¯Ôú‰³UF#­ó<øzÄ´@“\œÞJéhþÏŸÄìö|=OàÑõõ÷¶"¦´0µ(tú”ô†¸ëcʳßìrôjœx¦»™UDquUOwø¶…«eU>"#:ì7“¡žJ믛92ÙUìv¨¿«Ç+~Ù‘vÁœ­Dœ°ïOD¿˜²-ÁWå?®kêúeÛü÷FÝG¿ERuŽ,pb"ÂXDGqúù÷›x|_ØzÏQýÍÞ+uœm䢀ëôXÏÒ) Öõö›«g6²FÏÄý^zs¸Çgó8¹ûŸñ:}Ÿ|ÚºhõçÜ¿4ø}?‹Ï®ê½|ê´—›B¾^ëµõ®ûýÏÚyŸbáL²‡ö0=™÷&üø.ëõ=~/{‘AU.fÌà2lž1=Û½øpü ª½2‘ö£8ãÕ»¼O×Çsꇛ-ùzÖ$Mk/=ç,}Îô6æíßîïÓÑ»äéñ×äVÃßõÏ{©¿Wë¥&*'GïŽùçæÆ '*ÜsKâ7óí»T¼ÛE‘èçðäÚ¼ëßÙv'ǰXîò·/×uGÏ õzíÍÕ:ôk­ÿAùxꞟœæÕ<=–_?_gOÔ8'#MY›!ëa·Ø=ެïèãO:ïÒ›¼‘Ø2øù·ÄߊÂO àéùyÍO<øÇN»î22Ov¼êe-âø8Œ®±>³¿EKn)¥¹®#Tõöûè}[kñy––™’‚}E:÷õã!}Òã›ÇÝÞpõàdÃ]smßßùÐHé07ø³O {‹³zb»Ôe}šh– u|¾N‰ž õvˆsÔDK?§VþÍ{/_Á™“§ã×/³ð´é‰²u²lôùJ$$!:;O¹¼II5øm&p% )GñYt%)«s(?iþ¤T-d”’$ãjÛAxRZîžÁhB29Šã}E÷Fÿªô¿¿ÏæumMݬðŒ~~‰ÍþÆGæm÷°·q“.;ÀU­Õ¿ý‡ÛX’çWCÖÂxÔÓúg@Q\¸Ã6þ?UÄ6y¼\rÐäY#ÛŸÑív÷ußiÒRyì»ÀΦ^ÁÿçWÿß@‚\và4SÞŽóÙSì899´Â¶>WÊú:CëTqaØ;¢‡’Yž\íN†ù$“ÉhQäv¥ôR°D E€tü·]ûÞ&gOõ?kñr=¿º:Ÿ ßKï„0xÀº¸ŠŒ­|\u¯Ö}Ï_öt(]ø _žÏŒ¡ÿé'×ö•höÖ'ó¯µ[+ú&aÐ6)õôlú9?÷KùùÞ­ÌšøQQLFSGÇÿgk2›~A)s3&•ÊÓú(|ü¡¯‘¢‡+¬Ä®“Hü{ýTàßw^ZE.Îx·8rk%I…ºÂæšã•¸åÖa­9q­êÜÞŽºý\4vdý|Im>…Ó2qLld³qd%<}e]jÕ0×^^êÃþ¹æ¾‡Sê{ßËúº'=û#¼Ùÿ^‘º|1äOPœž=ô{ ßZ§E 棼½“‚°„ á19#ª) %Ñj›ž£›ÙÂûýKuZ‹F<6[W¬æz¾û¾?;}8ºõígŒ=óm1é޸Œ÷~¸?ØKMXØ¢ÁV(|´aé#Œ‚‡Õ- ŸDûÔºþiu¬$þz“—èuÔtSá3àE ¾âñxE›‰P”³„rŠr‡zå‹ËQJ,.Ö58C›Íž¤Éq^ëÞå’£W«¼©üšîy¿ºó=#î5ä?>ó”èYz5Ýj×GqˆÕüm»åníÔÒ‘& –è_ù-!R_¿èïG¾ý'÷?§·sGÏ­Ë’ÿé´¹²_È“ÃëkÿKœâ÷ü^íì’$ œËÞ=¿<ã6V¯ì°~«Ž¶9Tª˜Ò’º9d¬¢åH N‘™SʨyDl¸ÖOl•ŽðSøÝæa¹FZ&6f$1ÁÑA îÃÙÏÞz?ÕôšºÅzª¥ÈŽ|í²ýE,Éßn-_ë»)’føõQM-E1,±'HØ=˜,­:–ã:ìŠu=•F—®îÍ]‘îešBFÿòجökDÎŒc†+Ò”äs3>ëö¨ýf›m¤šý\ÿ£³[Þ«xÃóûÇ´&¤}÷VæcàQÚŽ„{—¹=PæØ?é”çõ®á∛U?ÀãÑ,føãѤÝM°‚þÓèmï'ÝçÜ4t¾wø‡5ü_±“k˜­ÌãQ”µP’èÚºé7ûÌLcÆìzjþWÖéÔ2DÕU5•µ Õ_4ÑlÙ´ãêø½ÌiŸž¶©B=Ý+E>UGm‰ ¿I¥ š³yyµUc§Yœíéô¼¼>#÷ ô_ؼ·^<ݼ=ž&&L *׿LÑO8A˜q74Äв)çwºX=ø»¦8^ÍYÍcy“Œ èUEÑ2ÿrñÁ×_7‘ÿ„p™ÙÒ/äÚÁ?(»³¡%'Ю1¾ÓQ§àrI I›ü%ëþÌ´{çó}ž¸^-Ílµw ^x^}m5œ¯}i=PÂ]-Ao÷ƒïÝy=±8þXÙ"ô9äåB O—~ý·_fwð·9nüyÈø3ù—øï¢÷Ê[¯»æ@ŒØÔ¨úŸf¸ôÞôvªÒ€°ÇSÖ9HmÊ×Eà°“¼®ƒ"Vr–©Ö­Ég«ðÿ7bpo>;°¢ÒÃ3RtbS»îÞ¾ylZÆ;oéëò÷e<µ—£uYxë>ì¹tý唿6ófß,Ù}?ø~}„{ÑM;ÝhªšxwXÙŸO«n:y*ùiǵNšÈ®û•”×ìS|kÛäðÎûh³ºÐŽ ï-Ñèñc¦ÉîÇÅ^|:%â¤÷pì’×ná5×g‘§¦ˆõ}Ú‚8¶*è×S^6iŸ@˰1G´íXcσùÕ®3Üùø#}ÇVÛ&yGö“ÎþN:¬ÊÎ˽¶Bâ;«eÇ ¥uñÒÂ]v‡(sؼ£;†'»ó8â]m<ž(âºzº¬84;ÙÓ~ñIáö§iM·©ĶÏ¥ÌÌn#É¥Û ½ÿh†[iÞx¤Í£ù¤Åh‚ï¿Ú‘( «û/Ü÷gÍkc¿mï òzmŒè›‘ÎU2J¢ Â f¤˜¬–9­–ÒÚ’g?YÆ‘àå™É4ÊfaKeS.¾jix^0]ë,ˆKlõ31 [zÅë¥=w ´Df ÑûÐýîÏñóËŸL|’ˆ«õúþ=驹Ï0_0ƒrÒ(tݘ¤dZÔD´é—ŠÚ§jPTHBQbÞéwNúsköÿ6fñÇJˆZƒœÉ«gRA1Õu,¶Ëª˜¨e|~WÌçæºÖ oϳKQŸ8ÃZºìçÁš´m _ ¤6Â¥]:ÖŸ¨8SmÎY.{Pטº8¶1üÖr1n’ല̙–YyåËšN1üµBhîõørׄ7z&¡Ù–1dz…k1EPŸo7š¨›LÖ´ëW&ù™ûàÕ{ë[9˜RLt€_N:?6þÅQOŠDVænZH%O‡ÕÝúò„ªçµÒª¶‡{'|&,o£Ñ†á6 úÙî‡ømºÊÊW³` Šž_àùûûbbØù}çÿsú½%=}ÈçàðxS¬ùx )þý{/ÏáÿKÝúSOXï\Úþ_QÝíÔ÷yÚ~ÅNî?/ñù²xÕ«å+ôS‚!ï~€^RMÊ7µïŠýÆ õ>’!·¤ ž±µôϾÁ³i$¡Ö}å# ÜÔ„íJ9²}&Îo3åëôMÕ0=Ï^Ý! v(Ë:¥sÞ£ãõ¸¢{]wcYóYÞ¥~ÜU1ÃÄž=YpZHðrÝåøeð-ô8OœúýÏE<—~Éôÿ±ÓqàÕÕÃÄ`½ÝÜÿ6ÿt»½+áN[2š¦ ßOE6Qü˜±áºL+µVwBÝE QSå_uMôï’:L É Ø²Ë2{¨öš¼Ú?CÄ"÷V‚h#µ¼ `Ƕ¬É¨Q¢´0€™ùHZ€ÚK,¬¤± C3'{4téÇå.ÔÍ^¶èoÃgJ ƒjdÎÎqs•r4OT Wä~Ÿ ¸ï|Õ=×ÖÐÜûñô'nWÁ¡ì¬ |N(— áJ#SÎZk5 ´$µ^—] —D #£é|ÿU€¯É(eM -”ÊÔbq T÷¾Oýn#¡ˆ1!&áçiµî’ßbíOzÞº«ÌUœaG]€¶¦…<Ÿáy4½ë þïú^é øR°XŒX,S¾Ø Skã~Ôrû¹1ªøµ3¡Ÿ£ï:t…'ÐÌ„¡ìûH}0Ü~]×dY6-pî]>àÏ"D>£x¾³êCüï™íõ}åÅ9¾]Ù¢G^¹h&a­T"ÚÜ¢=Üò„0?:ùLš^(·ZW®ÈÒ+jX1¸Ç!¶àa£ÜÑÁ“ 64ëç¹qˆ¨?'w'¶ñ‡ƒÕÜ~g¢è°÷_¿çvüŽd÷õ—.ŸV;Àï„'à¿+!“žª.¹̱”Cý=Ïòu¼æ³™¼7¶”ly_8užo‹”ÇÀ9{³2Õþ7ÑÀNIâ÷stò€€{-ä4ÃIúÌ„OÔ;É Dac’ý€…È(›Ëµ\Žƒ‹£Êõ—iuNcg§éC*ß9ÿ» –S‚üå¿Ý÷ú¤.üîû‡»þ×ùÜsÀÍTøƒÙ:ýŸGÎns'Š­v{’-·U5ô¹ñû1ìôûî¯CêaRJ‹N$¹m *4]ùÔò&’gôy¢÷ºnÝu£´–ÉÎuÀ‘ÿ·™èC:V4Á…P𣰏0ç„äa©Q¹*‹¬duО Áp?:Ñy·ª²²oçÁà;¨h¨E@ô` $7”Gj¡O›ô½èÁòÓç¼Y¯ï]ûXMHül^õî„ 7¾Ñ×&h͘´Fo7µ Ot)fÆtòù§ë5×k®ïí¨ÒþÞÁBèJ_+Jéþëà÷mÿŸË^={õÔ«>ØbÐÙLÞ—¥½Êÿ°–fçðþW±ìká–œ ïa¼xL‰¬¢ê‡æ6pÛÛ*j™Wëó·’ ÞÏUü[Ï•7”aW»’E¯ÃoèÌ_ÈÔUÄ`ØÈ,L_¢Ý??ŠrÑÀqØw:3ã±÷]¹;Ctˆ‡×äÈËü¯Ü¸.ãhW˜=çL<ýÈøLÿ8ƒßÂA{ÏZø òO¬•a½G’I:óÔÀ¸(ªBЧªµ¬>[ËÞu70'I?Ó+áfíg@臊î(Ï~¨ µè!ö-»w§3Ü©÷ñ™æ]Ye !#I$»Dâz[R“O&I–ØÆÖç~²®¿:)±õ{X)‹ctS(HHu*B )VîUÖRˆJ(u-D­¼Q j!Åk;<’2÷=öô’s;ç‚MãÊð¿,-‹¡èe6O?íMß–õà.‡ZS1ÔKJ"”A5äó»ã{ÄO¿Twã)*óÜGž3·¦ŽÉsTé….k- GSÕ$ºuÞ¬–ûÜwê#Âç:µ´~/—¹´u¥>yê§÷žy;1R¹MÉYÖ‰‘ºVËÆùOüíGËñ{ÝÁ‡ƒßY§Áòˆ}¶ÛùŸÊÙþŸØy]žÿ™éórOí~ÕÜ@jún·r¦Š@ÝX² žÈùT|-WßÇ’Y·×’âH D4°…BJ!l!P“$… 5D"‘î=ÃÛúž®tíëÑ•kù·úT9T;Ü´¿K&¹JozÎV]ÍéÌ»sU¹»§jU^rM5²Öôï›®íêŽRÖº­fTÝbvîµÅÖõ­g˜ ȇ:4s\†8ê6D„I¢ˆƒf”Fër2IÑÈ2͇02G ŽTl٨т#A¾oq¸Õ›ÀŒÂÊ((£p\YF‰‰ÈÈ×9®dŘI¸˜`Œ6p£ À“AdÄ„›áÎs‘ÎG9PId"#FI$˜hàToDÍA¨žVn (Ù³pn,f Øá4Œ,Ø(Ù²¢I€ÜVÈÀ9ŽQUpѨ(°a£D‘†Ê6häpl±#"ǧãgA³GE—uzç7Îsœç9`Q†98pÙDÆ ³G  ˜`ˆ²Í.8l²ˆÙ†À£GPË"Ê0p@"(³Dœ8YDƒ6a °Ôg7Ün 8DV÷¬™©Î÷ÌãÖµ‘w½QZŠ9¼7¡Œ3…åï"ãwaAÃ2Û2yœ»Ñ½æ†F´rMÁ1¢#9f¯ç7±áˆº Ü5²I²fàåI„`pÂË$ƒ"PÁLTr60Àf¢Í0¢Í‚„p8Ôpá' F ÑfFg7Íð70’â,³fFäÖõ­ó9Îp8päs†s!‘± 耒 …[Ù“Þq8Æßq»†ßqÌ0íø}_nÚ¨k‹u%'(¼Uv#•ºÒHÁ䰌öOH¦Ís^¦³U]qr¹Ï­vòœ(è;$+Š£\6% Ħ˜Nà‘*F"ÜŒ¯–8XÐ'©2?pÜtpãÓÕϦh/ORÌhÉi,ž Jñ­+WªÝšÝò Ю¤åLOÕë‘4rnýÏæ"#íûŸy¿ØÕ v}éäîv¬N?çx7çæR‘Þ„í(+n*«O÷i,ç Ú¥¢ßû¼ Å-`-ä8úó¢ø`Õç9ð@:Ÿá¸Óç>¾(°L}7>A] ¾€Â ¼¤‡ùE*,IGÿ ‡øÊÏûÏWb¤E€ÄçþbŠ–ö3ßÁ/‚yØaò<µö¹ÐE5OÍ—$ãݮΪ«Æ(äJ sÏLþM'ù~.‘çhý(ùìŸn—B ÀÝV¢°R ¹^|@ø@ =8€4âJªœÝD>/àr»y<_yVabʶÇ̰>5‹GÁÏÕc-ÿ3oʺ6Æ>C90Ï—ßwÔÒáÐCNs\}~9þO <Þîÿ§÷ꊤÔÄD;U$$j€û€ÂJ©áÙñõŽßË­#èX’w,DeJ ‹®(›`‡ØhÀrö!ü˜ y‰/È^|èVöQàj=³ö$Í(~Dñ@ýò¤!öqJrï¡®ü›«æèæzÆbîäÐ 'Ë~bbÊŠ•Wì¾çë·r»†Aâ­YÐár ›¸†M¿¥ô>'yßxm?§ýý™ýù¼wêÿïò_ô»‘Q:-}Ÿc;.ÄñVºÔA¡Q([íÃí0à n»k­kèDí?b„÷»ô¡û1G¸ëöÚÁäB£µÒÕÑíï+NÝB¢@‘üþGû‚ž» &¸éƒ:å‚<µ?’—)WÑ–]ÕXBïåúïYÞ|ÍÎ ù¤Ìk#çQbâÅèÉ—¢Îù¨ ‡Å«lëøg÷bËs7jÖ\Ïû92¸Se¹fëîõ›âî}*ÄHHÙœ ëáyü´×ZZ†)ËóªÍ:Þ¹[´pá€Ì4"J6Ib 1œ‘‡ £D"MYFŠ0$²Œ½Þ¹;ÞÙzÓT , ŒjT<°ü'ø?‡Ó¯b˜eÊýÒyfúL\çJøž|ä­¦œå¨'%bC¢TB w¤†Ce“ÉïeýÚ^w9˜±‚(ƒEb"ÁŒ’‡A:azø“Œá6 °>‹ ^VTÐëf´huHmaAEE9Ìr”µw%dÈÜGéŠB-&”ŽHI"Î@•O¼Ü=YÕ ù$@þ+Ï´9„ : ®¤S‹º) ˜ì­žt}Lq"H(HUô”ÎE™ÈäDœä³  ,Šrn/eQ²È8#q9T¹½þ%ú3ÿg~;¢ˆ þ›ÍÖÄ2Ï"(‘’a¢öööªÆŒMŽ"*&+‹¾ ‰ì÷Qbƒ>ÓUQb‚¶Ë+dU‘‚Å`‚¬FÐ¥¥[Ö50%H+;ú¼@ ðÚÈ)¯M!çâ:ëÙùy¶r]X@¨ºÙS÷üûJ@Ú\%Ž6”ØÐDA ²Ø¢ `ã®mδìd’AmjÃ#¤ˆ8ktÂQ(ÞÌQ¬Ç˜H„EÎdÁxa›7؈WU•uP‚M‰(Üaº•® rø­V¹Ž…«Ë’J 1W $Ù¦š$¶ÂÑu ßñ’Ýu¼àΉ::7<‰Ü¨¬ S­ØNò:6páfËÄ1!›W³p„„ Z®8j9­r6s'XhЪ9{ô-k™e­r¾É!ôthƒ ,“F c3®5αúÀ:º—ºúÖÅåÍ}ë…nÔƒÞ·§kÅd¬ª°TFÿB\Ý•6>§mΟQÌpq~/§ë:nël8[Tte©ü°Ññ/ó?iãÿš°·û†\Ñ0¯xáÏ^i}ÚogÎ(xnaü`8¬t<,=X*F¼9]”ÎW¦cëlÜ­öÿÎñÛ[Â:+pR Èâü«óÞÊK'„$ªÒÿEô>¯ú?ÑÏyîß¾!Ü•ãmhvdîgsUl0Ú–ºú¾]…{]?wÖÍ¿×&!¾Fï1¡Ã2ÕYKEe^}Oàò&ƒAJ:Dë9γuTS¯mOÓU¹¿²u°¯1Bp:D’Ò —ÛªQ#m~Çžê¾7í~.`Ôä ÈÙ 4„„#žAñ‘ ™„Ýv Ôµ1Ê>Äî¾0¬wD@ TœÈ€ׯúÀáùü=lÓ×Ük4ª•³!2bK®×/ÀµÿGΫ §rOëÂrAAdbÅVuÏ4bwý(° ¯Ké¼N…<.ËÍñ'Wl™óõvº]»“rÒú±—Y…ñ=hB£"K(²ÉH›$££D˜he› JÈ6YeÜÖ¹€¨Ñ.÷œÉÍ9ÿ?ý'¼|¿ëáOâ>/YÙû AÒ°KË1s|vóœ©$lj”†r°RM¡ƒÈÊÉ%e›F‘ ÒMpRß—æù7Ïù]~~.»%OȼÑ%›íB:)hDPggyÞ„8}Q3äí½}3}<¸î±ýu©•P;àç×ÐÖÛLLà bÆ»*®©c6°³‡×¢Åc¼½= „çM~<˜Æy©Áòë_:òò© sŒ††„µå|Ù*~0˜Œg˜òQ3sºeCˆÊjº¦µ¼ ç<™ÛQ¥"? g‹ päÔmiF¨’j©Ê\ÎMÍ 69ÁòYzbÈuÄÅè>ß·| ÄÚy²<ãßÃöÛÕ1OY5§-†ÏpTÙãmjE@èg}Ÿv¾?š™dªS4Í7e+ªt(i¡mµRH &A<ý(þfó<áçÄîOÌL™àŠ:8Q«ç#bjââÍ BDÑ*3"4ˆR0‹³Ë¥¶ä¨jM¤‡Hˆtp#&ݨÏ}×ÜIáÚÌ=F‹º1~4âp Ëôû›û”pŽ$5ºhczࡈêb¦±DF Ñ pLÄM ™áaùÐ÷o#pK]CXìÝ`wÂÌyp[­HïZó=û22òJ„F”U"¢¾íQQ ÙðåT{tþŸ«éÃ$NßÿG¨À.\–ï0qélã78855’ $Dv"C„Q¹Ó…±¿½¿­`QU7{„4Ìɶ™ç «Íð|>“ŽÓãD8=Ó6hГ֙ªhq’Ëq’Žê;,Ç"P ìˆ3nˆ¼vt"k%KºåÎsõ¿; ñ¶\CB#˜äæé^eA¶¦]™\p&c^ž µ8{<3iRÑBDr¶/ „Õ‘H%‡ST1Š|±í¾G ÀÙZ"jjŽJ'îXQ ya¨zÉ!\jpeš(ÌÌ'$úÁ&“P¤PÚñ¶ÝÈ:y’‰D ýíÛ ‰2óŽÅáÒœ¹ « w4qDCb_ c*Å7nY²QÒ,2ƒqfoáw0%NL6æ„Aõ ŠÕ=í(™Sl.椪”øytÍJÈqêÆ‚ Ý/N ¤²Cc$6€T#Uf30²Åv³ Ù‹Ü”ÍÐy%cr¯s䤰°ŒŒ+g†ðœ€»9÷÷7B– KLwr×QÁj–D8¡Mï¨6(ªªle”‘‚cˆ†bx90F$žLLž(Üš::’ ˆ‚ƒñèôÎÖr øBÜÈgÍ«„ ûM@dšÖý›ì×U„IÏ‚Ücè=G®°`«DJ…Žxdš°Ò˜Db¬!ç$„0 `ÇT£_vÃL "¢{YF> DV/k *Î>·„ßCVÇ JCy7n7«íå0PˆD±2ó3á€×%d)¨ËÑP…ã"ÀÁ1ˆW7e2DëfdÖfŠ…ý0x Zš“^²(&dŸtÔ=¥3Úcšj]´éIÃÕ–jÙ†C„oç »˜›ÕŠdJƒŠ* ™1 „Dˆ „, ¢@\¦“£Ö{IŠLa‚ø;›µÖ€g¡@ÀÈt¥ˆ„F@Þîá)N`¬Œd#,õP<|û˜ˆŒÃ ¢ "ˆš%"—™[C†m6tZ´KºgØÎ,"HÅŠä”10ªÈÒqr–‡›‘€k^Œ!‡\™œD—i@DdQEAÅ¿8T!Hl:v˜‘ÚoÕ»Ee†ëµAO>íZ‚?‚UV–*øÛU$Ä܃ü^0½¾ 0‚k$À‘suBG«ªê£„g„ëv}‡Ê–ŸŠ©Î01eNLB©›'v‡MÆËâ¨Íˆ›lkNI‰3\Y4š ,@a¦’¥a"‹b H‚þX„@3uF¦ª\?ÄÛ*a’ÞãM \ùï ™µW7}Žã±c$ÙNO¹)QÂïß-ý)¼ mfÊ€Ö5 !“À 2¤2B °œžsx¨ó ÍŒ>ç¿öýok«ãþòßöÞï}òj/ØûgÀ?­÷×qJ%ë*‹ÍŸÜXe©›í{ ¯0Ô^ˆ* ˆ˜¢Ôú²Ä0ö–#½Å~— ¥ÍõÙé÷^9Æßb?™þµS‚|È«Vpm}•vžs{T½x”¶ºÚ>„nz¾ßY¿ûÆ?)ø\ª„?)’šŸÀí â¿yD"ë®wg=©áQh|^Aæ°ú¹°{ÖeºçθB1{–VæeèevafŽ4dœ…Ê6l6h²K4I…˜Qˆ,ÂB‰„%½j“¬Ò1z½c$ZN¡YÒS?¾ÿSúQ4>ç8lÿª¡´ÿoÑÃÇöŒÔóÁ„K8Ë:¦Ö?V¢x)ÅÑõ…ºº{ßæjÆžCæ°ˆø0{zØ@K*P|Ç´Ó 0…Úô)ãΕO(‡˜§ãú'K/T5‚Ç/yÙu¶¡˜¼}ÏNŸSä~±­wu•Æ}–3¾—z•Óíyø™¸S³3ß¡‡ÌSÌã‰c¡ÉfÇ]wš7˜ÖQЩ‰§ÍºÁN3kF1s:uêdÅŸ6]5…~?»ÝÓßgPïN¼âvÏ1û¯i¯cÀþÁ0VWŸ"ŒÕÐý+›Ð'²éëûé8E³Š%7i=.“HïﻬŜ™ÔiAԑ͸}¿¯ÎÜœ»¾.XuB–ˆŠ?U±H¾¥¢?<ý?ÒÏÔýJ¿Õ°“õH0gëFô1ÇB’MEë £{ˆÂÍ\räÈÁ 0¢ €J&2g0µH¥\A‚A!ȱZ’=éAn‡òú úyµ©~L¿»½ —å=hùŒڰÙ\„Ø5ùÈ~{ŒwŽÊÙ­áT¢X÷æB¨ªeç¬ /†;ÄrÀ@ X%7A¨JX1óôѺå5*#‚¢†Ý½'Ë·îÿ38"|‘´ÄļÒ$};œÙðpä”|„ŸN€ª‘|ê.} 3[€šÍ ur1<ÉÄ$}T¯ r0*ÊÒ7Ý’›4—<-ã©Ê¹umj²-Ú#gq¡#Ï5ÚÒrKI ²DDÁPšŽBÓbÆ'Ôà­Ä¦ Àº-¢«ú\ˆ¢r•î1½FLi°ÈÉQRˆˆÕUÐ1±R£jÂQµ ,V$‰.X¢¨ò¢:|+Xc¸Më#mâY lᕸÀ’€pPëÖO%IˆS=÷kŠ5µ\A&»(›|R00]º vl9™ç5æÊ „¤ÁÐ`"*:¥5a ó÷lÍJD‚b̲Ô. E¶ó*LJ 4r8lìâ\‰¸¼ ŠտЇÁÑ€`´²´ˆÂ1&Nz#šÑæÙšDÔáQˆ•Ô`›õ!d.»ºIªa•?®DÕG)vfÝÌjRóê5QQ@,×aQë•ÚØÔ˜×‹lÑ…'ï‘w°&5íÂKð»4ãËÛbBÙæŠpYIŒ4ÿùÊT,jSMT-Rª Æ!ªp{ÍG{£¬ÜÜ”.ºz~ëDÒEÌa´Qß-f$SrPΔ5’R‚&wVQ¢f!@6 ¸]­úý|ç r¼}W˜Zú>ñÍ×ñ¨Ç£ã“|§l¹æèþµöý$‰/»{‡Y$±˜•ÁO¢D Èòbá$¡äÒ‰ÌL"4A/ò ªsâ<ÈzþƒK›‰ÜñÃô¯6N%õ·g:\D×ýn§Â^t=Ã\ÛbeáªþÔÑ^Ì:—ìûىרópLM²mHC>Í„çy/³Þ²ìxMv‡¤Ã¿ Þ≜f=”:³õyÏ È›g¶Äð(³»šóeø#+ÑîpÆEÔÝ&›[÷rªj_^ˆg•ÍšÄ\ ;šh§._OÄãpyì/cåê^/í$ëu˜W´Y–Í!Gðw™:ÕÂÊ_£t¾2 b¥®ä$* jRj# Š"ÊZJŸ¹÷þ6Ç?NùÄ3SŰÂ/q1rÍh0ê¶W5ºˆ£ï˜8ƒ„ Õ „ U(F–¬Šº•x)©µ.³Ü…á†fxß’(d)H¬!uë” ‰BfpO¿°ŽÔ!«®Šaµkòïåm\95É %rœÈUëÐw(˜S7i3 RæJˆ!Ö U8ô ¨<ß»6¹ØÉfºœ“¢öM1ׄŒr@ßýsŒ«dž4ss³•¹Ñ£'H³:¤ŠŒ,tÕú²é~µTVÖü`ë®ìÚý 1B„!ãdfS…OTÊýñ’RùK‰ödU8¡~U¡§VÖ¦ iU´ý ׉BLØY0¹Ø5—˜'Ö˜R<m–æ¬CP`«Í ±áüû‹í]e#ù\æo‚sÄ–*€¬À3w eœ©$ò2ÈÄñܦ<ûÍÄןbUdœŒÚi™ÆS\nP˜$‘0ƒ%ûÇÚ3‚P åž8XðÊ0XQ”YS+®Z²– FBâñRÉËêEÈÀiÞHSFó';*ëyâš4阅Œ§³ rÖ¾>xK¢‹ôx.ÍŸF„(PÔ8pÎ¥¡ kJùýVjp±€Ç©ÝQ÷°ŽâÊèiP! L¹K‚‡ ±Âõöùιìû~<ø³O®ËŸâ÷¿¯ðøç9 ÊÊE[}§ôëoÀ‡›ù€îùß/â~GS˜hCnÇ·"ó‰ÎøO@§âþ4ý+ô¦Š’È=WUñ3J]Ëú¿óýÊ–g‡;ðüžØäšE|Å=­AÆA>/“zß/‘é×òéš™ì’Í–aübÂÌ0ᡚ&ÃGG 6ÑE‘³€h’4n•:¬¼¨Ì•æµ+3‹„.ü?Yú=p††îÔ¡lðínE7Ø ’r"'PBã{‘… Ïs`°41ò{¨í¾§øMÎ\Þ5UVŒ†;ƒÔ1z›¶-ãŽ|°€ã¡Êê9iT,®!E0°•YÀø}Þ^ÿºšú_)²‰Á>9†£ðGˆÁPà“ ÇäƒF ’ªº,ztL`^¬¥F£@PË o ›Ýr÷Ÿvý½m>ñ@ny^ÑçÖ¨LòÔGy¿x˜²ÝOöFÉAƒmï× £ÈÁ0ñá»\ÈIUú4…ð.•n/RY¸Á!ˆ þˆ ™"/Š£,fB(QÃÀƒ´s<É FˆÜ¸ÉäÜ’Qôä–ý(rD’#å÷+uà÷CB<ž|¯föÓ%_y7žä¦]k„RùL€¸±šÃ£äò°–ŒS ØÊ"”{õçØ±"k¨Ê4)L‚Hn “¦3w9çÐén ::$ÂŽ‹¿nµfÏb¸Dj»1££lÕôfÁ:¹¹ÏÖë‡U;^ŸŠˆ"ø×}l|[‰¬µÂ‚pà‹t‘C’jÛÒqßùìIÉÿ¼_¥F€|Á°…²D€ÍÄ tHdÈBaL`HBN`íW%uõ•>*Îè¬È;ìßC[wðì9¸½·Rư2b€„ d™>H;EˆGä"ò^$%ü?Åö?¼ÿ{úXv{øh®} ò§ÉÚ‚1ò–ªÇ¶mý<±?#ì?÷s«§€r«ºcù*„X¨3ŸaÛšbßNoF•\öJ$HÑ%XŽ ˆ,à†Y (èàIAd2ÃrPH‰6Vów³q›7®rŠ ó!ZJ”sñ¦µþñ‘æÇ ¦é‰Åµ³´\¨ÍÁUË£÷¾c»à]9¹ªŽA`KKPÔvØ>þÖ©µXÞ&ßÿsys©ñôÙ=|.âUwoï$*ÐÕ†™èôîû~g¾Ý¸;¼äý¸#í‰,Üh#dŸ £•Eš‹!õ\4#DÅÎs››"*ÔY±hÂâƒtn‘…9½ýUpŒKÿD.¬”Ü—Fô€“¹mRöÁsŸó‘$zü–{(ÅØœ/32!žsêùøÝ=#ÜêBN¡4„¡ !/£u$ÇßäéóT#y"p˜®ñÜvô2>6;qdhöbJÄ(d÷S™ðlb,.ð Ñ!¾ ¡F .l‚b†GÒ(4T÷ßhë¯¡Íøk9EF@êbpÉ)D ²"IKòv6TW­P‡2 ßY‡­õ¡ˆÃCÎ,ïw¡›ÅÔY'Qœ1ƤŠŸLé¯Ð¥ u…ݸ[l‘Ý$„5ÚòíI>ðEÏK+;ua×D^g.âÄZ”ŒE‘¨)LØÏ<bª˜ˆQÑÝE¾·˜öÊ‘¼^}ŠÞèòhàQ†l­2w%Ávj*MG¶ã‚Û< TÆ”x,~8èÙ?ZéØàÏs›4X‹¦OžbŽ"<¨“—ÜG.ßžuãÃF à¡,숽²:;7L®kBë|þ½{†9, z¢ÿ·¤>èˆ~ûè}/ÃéüÏîþþ¥Eѱqƒcs‰d9Q´ ¡ ü)¿ ß¾®oG–[š±]Ÿãÿûø¿'¸þ>ïáÿ7WÌx?¹éþ§Ç~ïÄöÉÃæ¤æJœ†Šµ0„é…D²‡¶«à_I1e'œ"¢¼'_Ö7€ª“_d·²8§g–®3ï닇/>/C­†¶Âõ]e×GjŠ’ù!C‰GÓ®/§ä«N›©yNWóéMuÕÈ„p8YÂÊ:ÆX"$›4pÑ"$£ÑG™y›©“6b¨IQšÍoFÎÿnÛˆñÑûŸ*>ò•ðÛ´ïÍ=L0‰Uê|6-›²˜¬ 8]ÓÉl žô 53ÛÅD@VTa•C6Dhp¦¸Cƒ*n7ŠBÄB‰AÉŠE¡À˜ ˆÀ,ḅ¢âM(’‹,c5ŒqË+y«±F¸efÊrŽ.LõÍÕ°EŒø?¬ëG@w¯Ú/ÎHÔ/ÛûC¼’¥Ï&í©éô£²ÆYÆN·뽈@i¾â“Ýó—yk†ÑM©…ês„9ì"ON/$;0\(…BÕ÷Îã®ù;ÃE„/¢ªºŽw Š3¾Ãfu£32I¬É‚Šu“Û«ÐâxâÌ<‘u5¥õAŠ \Qà " ƒz¡ ¢#ôüUiûv¾aœ¤+éx+Ãñ÷~U®{l\68|7h©•#ñ»õ¹ópc:ä¡aÜT2j»ìHÇ¡n²3¸þ¶Qàî¼âç ¿>Z´É6"3\=Ywηå_]7bDÇâ`Eœê ]¸$IÏo$Îî¢xr*Ç ·Ã©èEt¢T™ÉB… bïZG5nÚ~\w“ûŽx±ÁÑTEÃr¿ÍR;XÈà^$ž¦¥ßôáokžVÒ«º«_Þ:)ð„ #êmñÝSlãù=bþŸ¦xÅ êî"{0ehú¥4œ'vŒfJï­ùq;Ç«ð×âñ2zŒ=¹Á? ”äï‚»µ2¯Õûñ0݆åªòÖJ27ÁÈRðÂSÔrEK,6D`#C4"ŽH"Œ(²J,£eJêîT¬Ý×6ê©Ã/¬þvŽñŸ}CâÍ©&7{K¿J¦í$Õ⼕Çß2sËts œ)Jªcà¬B·ø1ÆÄ›ÛÙp'ô—VÆ(ÖX†PUA£g ˜ÕšK@(ß/x]jËGœ FdÅàMj²_.¹‚Ù<ÄQõˆA°Hbf†hƒgA¢!¨ŠQü>hÏ·}lË>ûÈ ¼ŽŠ„ÔS‰©qB.uzÐfçÀy6LKɳf£ƒfÛó¡™3Ù_ƒÁ€‰®êO$îw)ùˆ0ø–~ëfœ¯Ö¿Q9w±Ç’þÜ0raþO®µ]aaÆY4aˆ-ÐK ¨:Ãe×ÚO\3‘XÆo³ÃºVݨ‘-¹Ñ»2Sc Z„#Ó&€‚bÜHãfk^ò³/—]˜eá:íÀÄlävÕ+Iç)ÅÚ&žáÙžœ˜WOO×È[8 ¬@Xe dòÇ?Ì~Ö~ûj¨¿ Ãîú?§ïZúŽ6uÎúó¡Çn–‹$E"0“F³B(’Ë0F‰$ˆ@ÃW½æKØ2˽Ʀò—ÙýV˓䮤]Ÿ^(ÿ­û\Þ{œˆŸg¡ª} •±Y²l~æº{ÇžÒ´e¶Ú6…µ¾­>^ÏO·—éϨÃ_XI'Ž†Ç£lÐÅÃg$qÃfÉ(ᆢÔVÂæ^Ë5ɈàŠ./–ç–iï÷+kò¨:;*ôî‚;ˆ:þwˆ]}¤êGLp’„r}gqÙEÆëqu'‰ŽŽ°ÐTeX2rpÁQ©—÷?cÅKÁŒ ÇFt‰€ÿ”ˆp‚=B0„fmrÆPÊæG€ÉÇ)D¢”]g®—9¸¼KËÑoƈIE(´G;6tX ð3±÷$Ê8jqÁÔ©2acèƒ,ÂÕåãݳëÞ'“ÈŽq$’@¼Xæøcù}ç¸<3®¿3ÅWÁÚC,• ¤t­ñøŠ’/$% "9Qí$ä(BÒ;Ú7âû]žÜóäèÃȆ2¼{ž‘* 1…\UKا¨­Ëj]“VùNs{×—3~ïÑû _®çø?ÓþO+®ÔlVS½8n`eS?êåýïâþU0ãÕÙýL‹ü­¿Òµ¤/Õl»0iû:í|.n~Ô߃ºæ*5ÿO2¡àð8F é@Š$à!Ì@ ·úø¹ü~σù_ìçôÑ4QWʞπù÷¯¼ê?ÃóäNq´‰¼Ïû7•¸€Ñ&Ê4I£ (è°ÂΓƒ!’2Œ 0ÙE˜h“A¡’lÙ ÀFƒEŒ$˧›Ç:Âx‡ÍÇ-NBß6Jø?Ìì‡,¼Þÿ:2ú_'[®UaT‘¶ *ª©•êºþeý¿¢=ϣ΢ME‹cȈ’£ ÁÇ „dÂà8pÐç Š¯SXa&¢ƒdFÌˆÑ RŽ5åÕZÃwÒ˜áPK¯ú€B•/1§ ƒ±¨bB!"Þµw=èôIE˜I¢ŒQ,ìxU¨I¥òê|£È!_ûlçKÎÏKs —éËœ ò1DŒÓ ð»·Ö÷—éÓ‰"„%ë‘É$A©>Ÿyñ|Ï,ìñQv£WÚK•q«·Öß\"†‡¼z»Á ‚€ÄîY 3PYOì ‡ŽÌ,ðDLaý©G01 ÖÏ ï(¥ˆ×Ò%EoNÔê ºœ¬8œø8žäšLŒRF„4 ëuB¨p5¼Ÿ“ö7¼Tõ¬þSóÀ%Ú¤ÌÌ£µo(·á£;tc’@ÀTÎ^ ¼˜= ÿ"}œ’‚ççu)–J¨ÿ‹½¬#Íá‚iÏîÐÄ{÷Öóø×)"C§cQ‰ÝOÁ&k‚"´NÀcËEÖöVð/¢ßWÚ]^j(»Fy!³Ù@=‘ƒóil©³õœýÿ¿üý &¥ Q>/Q¼Ç4ðïÄ:o —_á1fälüƒÊå≚|ÿ ^+q¶’üÆÃ Žî"€ìåçæÁ‚i2Za&JCÍ8Z³Z”bhÄ4(êfÍHŒ$J*å9ûôâÜà3Ѐ¶@TÜÖ]-ͶJa™†]Hé’ (Ü™Qg¹fÈ.É2þl8ÉfÜKc5jfa™*æÜá @F?í}ª»«¨Uʬ‘ráщ)×ú}ç"œÊ"YÈž³Ë ¢3fÄ¢!I…”¢%‰‚XQ£)K0”ÂÕ ”I“ sÉ©¥²‡³efJ$JŠ @ã aKD¤¥ 2{»öiTM‰œað¡¤CÿrñÑ+% ¡†0±Fsß÷ú585—wDÙva½.‡ÿ)½­‰DDJDe(YF#(R£(RR–Sâ¦J2”, Ê1#2®ȇ$ÀÉJvÉ‚#’¬6ü¹!6 ’›,L,¤óY£ 4\TµfN$’Øt»73ëê¬ÑCDÀÂÄ¥–V2X”Är#0b` fVËWˆ“&UŒUßù!Ë ¹¼[‚Ì ;²jc4S²–ª}-MêÛ“&1L2a‚Dg2JY…,ô3®€¤t¶Y)eÝL2r¢…" ¥;¼íÏähøùœŽh̘|Å4P¾QØè¢¢“uTÔ'Šïl®¾mÛ˜óy­baþ³ÉO1;nÿªòÝÿ†åä·ï-‡E2a†L—_uÆ]iÌβJ¬µ¹?C™US[ݪªosfÚ¢±šæ³ŽuÍóS\›Öc¥­ñäñdòô’;9¶ËZFcÒjóúÀ ¢¯}þD!Ð22ÕÖn6¾Ð:×îÌÂ}QP¬ãêó2·ƒÅ&þ½+Wnîõ¨c8ã.dlÓ‘´’(- ‚ÖÁD"H‚*W“‚Ç-X JÅ -…Šˆ!Ð :d*Ü£ÐýNŒ<->§ãs?¯²ux-@ì¿/Ìþ¶Ÿ¡³CÙõx·l/PÖzç_Ÿ¯0˜ÆP³¯¬À05BxbFc ‘Fööȱõ½«çú9B×ëÏÛ˜ ÙRsK[Û“ c›Dh1ï®.ÕS ýÄDs‚/ÙöÛoÃ'–Jç¹ûw (“¯û_Óa åÊý¥Côµ¶ëš0F9•8AY]g¶økè†à†JÙW?Ýf ƒ‘$$›ÒŠ­À4åîpC?ðrüOêóðƒ~6ÏÉoþtÁ ÔwBPA Û\­–&hNÞ®ÑYbpä5QöœJ?còП¨\Wœ 8”MQÉ: ð"áù"@‹QM««öU/«WÎÍbΞCȩЊ¢¥ú†=–åÞí~ÎÓÓÞh-]ÈéZ*_ᾯC”ï³2øgÞ~̉Kõz"æË©Ílp<ñè|ÈžKIìÃ+ ¡™Õ3íOñ]ðA´ »$?;÷Þ+ÆkGV¦$¥Uð¤W̯’ÑŒT ùÀKIJÊL§¯*ñ¸Ê»¯¾Ñ/[á‘"Ùc6›f¤ªÙ(©§Êó/jRÑt[ÁJÞzï‚ëi!% QZ;fÆqÂ/8¦i|Ý…TˆMÄK×ñü@ïÏ}̵q¤¤Ù¢E&Sƒ‹‘(QNxÎb"(ž²­Û’ø¯d¹™³Ãšµ’ù)hrço±ì~ÑàþEÁáÛÖw­¿NXäkÝ|è,ø&û8­<=­ê—0©ÉNÛþîizT]ÐÉáÕˆºêVŸu¹(ðUڨȠXËm<Ñ ƒÈ¸G×üÓdñé`€¨yØFÃW^®p¢JR÷­†xÈf'œÑq‹ w ŸÑ 6Ï“©CŸ«_|Ùz‹#ÞRífž‹¢ASb¦Ì$Æ©S³’ËÑr¨.’M¬p²EŸ"ôö.°ú®Í«URÜ{‹‹ŽbnX(†Õ ò‡ 5ìÒtàƒ Lƒ,,Ñ@4躦ʺ¶Zp¾·ó*ÖlÊK¸<Ëö„“o@qô¹÷óÕÝ›X©âÎö`à Ä0Æ!€#·+ˆ> ’%°#zÄö{>ÿOo±ï>£Ügyoªsë´|Ë5o·w¸¿7*QYiŒnxOò¡1ðÉŤÕðÂxÆõü:Â{ßÑòÜœƒò[EvÒ†ž?ÖÓéQñ]çŽa,-›4?v±q™üÝ -5½uÖ³ÎÐ'6­"jލ¬ ðΫÓÊŠaví[>Ô3ÀUš¨F+íK˜@U&¢f¯1å{ý¼¯­”XítsoäêÝ¿eÙ*Vjua­?š]—$~^æ¬ wÿ!µ|Í#ֳͱ[j0àDx‘Œ‹½–$L:€0ÇNB çÝnrÔîFUùÃ|=Ú;CmÑÄÀTY1©š¯:ÿ/¸Ž»·}Q<=͈½XÜx=èž›2JmáGP¿Qg¶L Äc™$¯«è)¿ÓïGË ÏÏýI„õÔòïiz²NH æR\ã_.]‡#øÚ1µFžî+CRV¢Ø÷=¥æDDMj"tóyº˜Ñ0ܫֵӸŸÃ3í¨¦‘ÛVº;âýnxÌìQM0ÏͶšRЧˆÖVÒ³ÜçÖv K®KÐÝmÞã•0_kC¦=ž-¼Õm2Tš†ã½gŸg5Ý„ KúïW7VÿÙßøú»·ëÜ0¢˜ð<Þxùªòó»ÚçUý5?mòwO!H{úûþ~\.»†štëŸE|7sãÁƒø5¯…¥éÉôÒ­¨µ$),„“O\Aˆ€ôöHX£jú[!¸±-UÉ,UYkááS_¤J±$i 5"@Xa¥²Ûj(*ŠEŠ(ª‰X+*¨ª( «"(¤D‹UTF)‹b‹V,PQb¬UV"  ª(±TE"¬‹ŒPX1V*"Å@TTU€  ¡H²,R"E‘Ab0#m–ÄBQI$ZI‚ÅUE"ÅUDŠ,‰TUPU‹R"EŠªª#ˆÅбE‚+((±V*Š «PUXª ¢‚‘VE$F(,«bŠ ***ÀPPPˆŠ¤Y)"È ±,*¥¶­–ÂBT9Ùw¯Šñ½úÛÁÉ}D‰=ß9Kо=»zíÅBx?H€q7‡æDãÁ8êµÍxî[ôãîHùêOwï=®½’ؼ# OÁÀ—M-^›í[¸ÛÜ®"©ejUjj“¼%v1ŠÂÍK¡Žè甋cv¹a |uŠ˜^÷.¥«Ê*÷Ú?²ÖÊÓ’H) ‘X"ÉØ– ¢¥@$A‹#âhE^J*ÄUî÷×ð³Ÿ-nú‡)¬ XÚ"ÁF0P=# }t˜±CZ¾E E*1D’AX¢}Û+6%EA+%­€‚Žaa2Ò «#а(ª©#5FW-E!•-V¤¸%AŒUƒS- "ÈP@YXV,‘ˆŠ Œ°U¥*Ô¢ÒH•$‘*H'òP½ÉY hU-µm²X«cl@[ Ȳl€[IJd‚Ê&I?ºÿÑø7¨Ä„U„  ¨¬DF*ŠÆ"¨ªUUÅЍÄR,F(ň,"„F@X¼Ò²)$"È`)!# ª1ˆˆ"F5”ƒè¿ÛØt`†9œA\AB*$R(DBÁZбP[ÕT’¬’AR P@X‰Y°Iù<ÿ®ý/ÀÛb 8 "¯Yl"­W‘õ}ß ðº?¬Ðïß­ôùsU?ófRÛ?¤‰óÒȬDŒc€ 㿈ðÙ’l 2 Œ ³lY ÃPb© bv‘¢uP°ˆ‡‹ƒÔA;¸+QT¾H¨ûÿ\GÕ{æ¢'Ȉ H#Ä@~ll‘lXŠ- >Ö ,6dˆþÍBGÎ @T3„€Ø€Ã) *@\’H–$Hüt 3$D%‘Š@Y>´‘Y0€¨õÒ}Ö@Yˆó"ÈA‰$ S4$elT’H±dKQ,¤‹R¬BY`’-B-¶¬Ô‘-’KKD-Iª­Z[%’È ób2l@P!^Äx'€yj±.\O¢Ú¦nü”14>pá B4¦x®ÜS¡œ¾â.»xBXš/:#ƒËGDèÃYŽ7WËžuÄÛ‘è!íõ€½/=>\I ùkÙ&A—ÉfÅrwßò³/@vø‹¹;ŸÊC7ý¥Q0âÌu¶5d Ñ~z§"ªZ~fòæîˆ‡1÷[Ñãq‹Îåwž›®äzÐnr“°–ˆ@ Éê\“>_XÛ`Ô¤F'jiThLCB,YáJ.%¡ …* 4”¿sy¶ˆó÷¾‡Üó\ÎßGÝpµªŽÞ߆9MÜ£˜G[ußÁá÷³â)˜€sñrnÚÜõÔ"`A×5—ÑÚÁ袒 ˆóZ)9ˆƒtŽ'Êî}¿_êmû<ŸÛ~ïß{ïÏñôò“æóÿò¿Só<ŸšýŸ‹õ™=çÙv¾@ •Ö N ‡Ê@],I„$¶--J¶!<( Fh²@TOd†>"r°ýŸÙïµk 4@iábȰDPÍJÁH¥kŠAJ– Vœ+–˜ÜÁT½áúY9ïé¤.ü¬$Ø@sH 9’!#ôVo÷sfÊZE°¨L“œ†HhR(@c"‘b0A"!"‚Àb1"ˆˆÉF Æ ¢$„Y"F(,E¨ÅV PÁUT"$ ŠŒTX©$cA‘ЬXˆ‚ň¢ –t´âÐÙ‚1‹a¦1$…Hʲ5@f@X1 aƒ¢Â³5¢¥Ý-L ¡©¨™4ÀÐ*0DWHHY”¨‡ 7I!¶ „€ddUV1UUUUUUXÅUUUUTEUUUUUUUUUDUUUAUUUUUUUUUUUUUcUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUXÅUUUTEUUUUUDUUDUUUUUUUTEUUUUUcUUUUQUQUUUQUQUUQUU€UUUUUUUddDddUTEUDUUUUTEUUdd`ÁUUUX0UUUUUV QQUUUPAPAUUUUUUŒUUUUUUUUUUUUDUUUUUUUUUUUUUUUUUUT€ dˆXBˆY1Æaôè Ä‚ ,-‚1 89ÍÖº–”edFÞ0»²k! 7¸%{½$k{ –#ÍUÁ#’@ÈŽé¸ÉŒzñÆ÷¤ßK˜[¡˜Ó…Î{ü¯ï?¥ýO?꾇™lB*©¤‚ˆq6ah PY$Ä„, æTîžsS1(ºšYÑ%¶ (§‘`ŒæYÌ:•ZIà²x %bË^Å202ÃÜ, ¬iÈ÷ýû½ì19BidHŒXJf:Ä›8Øá+ÀˆÈ !ˆ˜ˆÈÄðß-j,’2¤„€½‹í–A[\ñ;óÔ1ÞÚÈ&fXà086³Jd¦RmÐÀÞ¨WI]¥I‰²ºQeL&2Œ”q—‹¸â{¸1’Ž[˜$°2ðäD4RQ˜.HA’C¤€=ª*ß{s…ŒhE´’0Q"©¡¥l@ *Öc#B¥LS²Gˆ¨ŒF"d1þ§Å|Ò.hX©-dÄ µTʱ÷íÐìê¯1œ5ú<7ɦBHÔP„9¢HÝ$x MÒi°[Ȉ*¬DH±EÁE‹` (¨Š1bŠˆˆª‚ŒHˆŒY@QI!BÈ €¢ÙE–JAUb ‚EŠ(Æ ,XˆƒQEDQˆ#TDEPTµeJª²Ò$-[lEŠ•@rYª=â*⊻ $š$$ „2—XÈ&ËX.Q';HÛiam*®JJ¹i†\‰)¦£$ \ª7ª¡{•/†AU$ŠE‘ $Ø.v(âÐ…"0H@HÆ*„b‘RB¡ªA™¤K @qDìæG2*çE\EVø’q Hª]ÐþIv§mC€Þ· Y”’fLѧP)™T²ƒ“Ì‹Ž°®cq'o l ðe`ëå3P„ÐÃ.¬rAa4Ò¦k8ØT)\Í‚7S‹»® I8‚Y¹„’‹“X9Ó¿áä:3‚æ0?!&‡PÐJ Á¥¨e¹R…LK2#-)Q¡X–1F‚”b ,UX­…R–5(жÊU¶•ªÃWPj[J…Dl¶"¨å®Í\‚Z-Z–R•³YÿeͶڅj%Œ#V#[V,Å©[¬³#G…þgûmí][K—˜bZ6¨X-E‹8Lp¥´lKQembUŒU­‰…«X˜÷7 ¶£e¶µ¥-*64t•J?à~.ön•îj9}…°Á)A,¤R’¥F¥·øî8[X#DQ@²”©UZAʰRôÈfE‹AahÛJ³0̵eáÈe‚ÅZ e(µzI…‰ƒMslX² .£eZÒË)–`A06*HysÝîrnsñÇËð)‘&ó‘s-=ÿ »(f5Òøw7¾&šñªjú4ßOÊle :étò U…Æß¿o¯ª§'‚àn²©†ùõ G,ÔpHpÌèµ)^SM‘×jáÄúÏg³æxIƒ¤Õ· óë–¸mù#–ÈYþ¯íÈj±Þs¯QøØýú¥T”@@ ôCæ—¹sa³•0yb¡z @ R¬xàѪ$1 @OÙÅâ©Ø€q´6‰6ÈW“ÐhžÀ÷ ž×ÄuPXUM»…¹ìzÿ›!Êæòü¶õˆ©ö˜tPùL•¼9?:ôÁ’ØaÛ®/Ó1³œONvjS »Ks€  Àb B‚˜Q * *%@RD øË®„=m֦ͯYè¿9~¯É'´ò\ˆ…׺Éc80„}´M1÷0¯8¨¨§éXôA¸BDžï¢HN‘'îˆ $ƒ±ô´CæRlìJú´·Üó?ÝÙÿ?0oü,‚¨€X‚!dˆ„©ëJüdAÍÒ ”CôDU_¼\——ˆ °¾y›„[·½2c»'°Òås•úeZàð>&&èp±ïI…Y=ßßòöt9ïô’Å$Ò ý9è7Û•ºÒRð–‘’D%Ñ’}êú&­÷¤jRž¦*²Q÷ÓÛqºþßï¿üÿ÷ä/UÜÂÃ"“=]ÇÇ ¶U6•³:MW ­Ø^¥†XèÄ}eç•zà4‡D„^·äYÌA!3ÿûv²I¬ìø-¿ÈÊNfhOƒìûn¯ÍƒüÝÕ—ñ¿Êð»½_\}oËlŸ!ðñª$ýºÌCéÐçŸ"û×Ç>Ûúþ n@o‰D|°Ü‰¬‚M+Ö~gÿ?æi>Òèm >ûJ!ÉQ Š…J’ª**ª”¨”±m©)ERŠŠ©R¢ªUªJ©J*Š©*¨¥T« µUbv«OÉ£M%³ê©­Ýoý湆î5&Jÿ ºSÖ¿øô—?i* p/÷Æ€cÙy$7ÉÅ3G6xj¾4õ§‡†Oåc^ÔrN^_nX _•£.¿_ØáeõD¨úÏqhC¬ûÖà]Ó¢ e¢‹EþÏð:{‰Ì¯µÖ**žÊ( î2º¸.M9³ÛÉ‚"! ‚Cªª'Üø×öýE(žWé|ÊçáÝÿï´džý ñ3l$&UåzUY# d ˆ1AbA \Ü¢"/«" ‰ðœ?oÀ‰9ž"j|?/¾ª¼¤-D¡T‘Y‰ÜéY^€;ÂÀpB¦ÿvøeü{ ]âà±¾¸ÍŸ‰QºTȰãfûb¥•LÏçÎOÅU©ªöh ÓŽb¿ „œ‚5Ámg‚òþ5=u ›‡5Ž~”ê‚_¢Ÿ;§Œlˆ>áÎûÍ7æåYÆòñÙïúf¸î´çb§!Cwídâu!Ýâ˜.k5Ü/QAh/FÒR…–¥E‘m«,zŸÇ÷}Þ.N¤éùÿN€ì’DH¨ ad…J$T‚X!8öþ"#ÒÝÓo¡ëÀ@›"D‰¨"D>LTL|Ãý5âjTèüà‹Ý-Ȥ‰üÿ?òù €ù(ù~Äà€êæþ£îª8D›:¼Ïak µÙ{~öôN1ñì>Þâé™"÷ BÁãTkH{rœ;Aøý™×㇬©é¤•$„–l¹'ÀÒ~ÿé÷åƒ÷¹sòºàj{ϧѕO-H˜ÝS_¾:.cö²~í6ˆ@ác*¹è¥{i]ÿ”©º}bq+Ÿƒ€øIeóW¦¨¤ÜM „!“ÀÀ7 €@Ì"SjÖ\DÈ”K¾ÚÄH„+ýúÞXæ§¶z¬‡ÝLðÍ–(àˆª°A[äÀŠKت- @¥#T¢‹BU(B‘V‘ TD¼@z)Á9Ð’$úìô´MH'”øûÉ$ó1òxûß!>ñõH fÒˆ#T9rü¬N祒؉D†íõŽá!+i„0Í–ÅÛi¼"|›Ž_KÔbfnu¼G¹¼äü¯;`Éç¾&r+ÇBŸåy#c&öþî=²% iØ|‘p[¢â]¯]ñ8ž´ý_Èú_?å–ÇÞjïý×ÊX‚nðí»“ªrÚ[óN„!€ ,NÃhA' @5bÀ`2|†¢FÜú^,<­ƒÔ`ßÛ{á@<ä¸üɶfÃgÇö;°z3¶ÿ¯«W¾W¼=vèí¨@òT¿Õwàþ¨O¨’ó˜>ò,«÷¾¿Ç - .Çò=¦½ÿ§»;¾`;¹ó†¿§aE--`¯yËý˜å°…UPªª•T«V•)EdEX"AH‘$Dˆ ‚¨‚B#$Uˆ‘•)ITªUEQ)B¨÷o5ÀFNN«gæ.¾÷}T‘·±ãÞ¹çA®BKòüjydEúÿ©¬vq`sÿb"oÿGÕÿ¿ åBs¤l݉ýÿÓ}?¾{ÔÕUVÏè\?QIê×]H"MIOq®ÁýϹõþùàD‘³÷ C8‹®èA?B‡;Î\;4”l(á{ÛØrÞ^UD„oⵊºÌ"䈀DÀ€ #†q+æ5BPr 6ÉO½ öÇiKÇd|yøZKå?_Ïmò}¿öäæÍ›æÏSô¼é ÿ™ø=Ý€°€'âÒ(R(E"Ÿƒ¨ó>r€ýãÊzQÒo‡ê/€ˆþ¦—΀Ü#S_ƒÉøú¿ƒænH{çâ#êeÉ /ç·û½F´è?üúWt  Xû–Ž×5z¯ÜhO¼ ¨Jè‰é›õ¥Í„ ©RuI÷§Vû¢C†O½iÅ~<é4o3Õn7ªãýó{~·˜{O_Ð~GÎðÙý†Iƒ ÂIÛÄ®š€„ì/ƒä˜"Ú#ÿ—õ|E×Äeª‘ˆûú_ÙS½US½;“þ”’OÉB2bt,J@ú>_¹iF* ‘€[ì´¨ :F`íL±<ßïE¿õ踩Úp¸9Ïð~¯%ÌÄèÄÉ‹*ÃÀd­:$‰DzÒIqÿì¼^Ýï+ç=8>°E$D¬ˆ÷ž‘~ÿÞn>2zoxDD=ÃOÐqMˆ– 5ˆæ!wý{fîo¯'amÕÝMÜAàÔ\ó.×ÂÖˆ©˜5Æ,P?!ÿÄþüþxŠÅ?µüŸÈ¶à¥pœßg§ Î –°£aZD) ˆæ*p~T­3$‘ >՜Ɍ3f/FÕ&Òàøf&’€Õ€ŠµbE.##7ˆØ‹*ð;7Ñt¿YÉyëcÙ¡ ofœKÒÄ>û¡N²âʇ ç- Èvu„%ÿ/ òÝ®]2¦AÞúï©ëÿáÏ÷B'³í3i4Ô„œ‰è?£–Ûàï?'ׇ3éOÀÉ8:~éRÕ.åöX‚ˆ}äsE†j=²üîJ›É<ß-²`h } Š`ƒr@úo|ÒÊÿcnQösàÿEöÈþ¸`†v¾ót|‹ÉÑd„ôðñ @Ú®ÜUÅÿû|_þ0;L¾»ÿ«¹üSízOÃÊDr—aCáí|Òþš¬qÙ¤&êžÁATÁ5¾ÚÅ,@¼@½5<ì$‡q]®ç]ôªªŠ­ÏMu±¬Ï¸ðô49on»ë y|åp¼>¿GüŸó¶¯]µYSy@è‚n•¾³ÚEbªÄ‹K( –V†d,"ͬŠöÇ´AAÅQB“Ö„P’@?c? ¥¶XžR¸Ó LêË'@‰""º-³“L^Ñ_bzß÷Ù$>ä<ŸP|M`‡eÀ¨ûy)‚QÛ8F×{øûó¼8|à·Žu…ѵ̾òãê×ÇåšÏ™ÊéÈ9—œ£™‡‰=ºúj5¡p.4ÂÔ–€@   t ?\à) ·iއø©>2R«þk&;<Ϻ‰eßZÞ%rd­Ëºcù&ÀGªŸbbn‚˜†Ö0Á˜C.P>?tѺClŸ–‡ÿ]Õ>óz¤Ù2¯ÎþŸ,?«NÌüÁÛ.PñýºêUzÁðDD:ÔQE~"vÝâ nöþ8á.uÌêqÖïå÷ÕÚìáñ«7Ácßj€ÃÃðÞ¾î` xÄñ•Ã,?Ç9.nŒýp£_*ÌGŠúØ“5ÒŸ§üû;v$äA?«= ü/×úY—5±ÌÃ'¬ÓZaQ/omˆ—.{@Uó¼>ÿêÿO•ù?¹×yO«Ò6ÿíQ îNeRÒ.ZF«zG˺²#«?ã(jjˆg‹¦¡|U™ˆ±‘À ìˆ ¾þñ_“ö~fÉvœö{n½D<½´:<ÇU&QàUWÂvN€MŽøu§xDh@m@RHI*$ß;±kòôˆ¯rç2åW&U¡”„d.?Ú=–š:ù¢ ©ëð;'fgŽ^Íh[ï’Zýºr ¨ZˆÅ* P»¤rÌB]‡¼yãXQîêÔÔò5;{ß³Û—ë ëx•{k|èèÁ¹âͯg1Ã'˜’˜ ðä®'¬£P¢y®÷ûüOœávßkìºoêý»Á ø`ŠCÛuDî>;èGÍŸBí 'ÁÅ`ò€«êÁhD«Q€!+:(±2ìýüèù„6Ô‹ò¹ýO?ú?ýWþŸ'ÛýÚ­ò¾´~EpÑ_VÇ£Q}Ÿûkn«Ÿ- 1?9óh]ÖÞÍÙÜ‹ f¤9ÃýjZ¿¿'Å süÍž ý(YJ¤ˆB€íéÍøÕ­ŸÌÃy(l¸Ä‰1ZÀ <Àɺ°®Z©WR¨ Ù2@ˆ/»EAî* éj8Ücò?³÷„¼»"ù£ñ¿;ãîˆ+øBóB&ƒ?ÛûïwÊê¿×iÈ;Çú’O‹ñ?ƒ±=§t§¨ÇóÁË„œôöù ;ñ¢t#•gçÛø6 °‘/uN”¶Ÿ·ÕKoç ð½ N¹ ÏÆBÄ`e!D ,þ¦#6[åj&ƒI–B^7¨”^¦¿%ºk·qõõЃžPåÄ €%Ç‚0“ñ½Gsq ùxn`å¾ï+Ðc“AþŸé¯†ˆËd4G@f`ª7RC$"bb&TƒÌ¸&sPÇ©~âçP+ k=µh¹Ùžù÷;›Þ"ElðFéšGä—$¨öð¢*Añ¨_’@8jv¨)Az1ûi÷8ú‰9›ÐÀˆ[…éþ—”ês’=I!×CDý¿QÙà·rþ=Ÿƒ.ŸßäN•Gã÷zû4]R"HaP²,@UW×ÈH*X$¨BÈŒ¼{k²ˆ†Ù™TL  ˜ž’y‡fkFï}\滿ÊßÎyÁnàWÈlp„Ë¿=4Ú6r…ºÝ¨m“ÞNNP ðŸ>WiúþBÆN%#設¾kÑÝÀ]xRÑë¨ë5ˆ…òí]_âØ4@ã¹Óx}*å ØYóžÆÛg€%¸ßð¹ôüD^ª«.6ôKŽQkLv†”ÝM®é¢<ì]‘؆1†T¦3Qªc@茂BßqÜ×묗·ú&r|=ȸǗ–Š’xºõ½íçÛ`—ðºcã7ÈmçÊïív¾ú $w§{ãºl.;>õ÷|pØãø¯V ôÔ’ U ƒUBÕPUP´–Ò[d…´-¡m lm l–Ù-²[H´ƒlXJ…Kh[J„¶…¶Kl%¶BÛ KBÚ)-°-¡++$­H[d–Ø[`ж…´–ж…BÛ -¤*6ŠÚBÚÙ l•4°•–ÙX´–Ù-²Kim!m%´ ÉY-²¥e´m’Ú[d¶ÈKh[HV [@-¡m i h[J€ÚÙ-¤*6€¢…´*T’Û[B[@-¡P¬ hI+P–ØØЖØ­H[a$¶+Y i*Ò¡m T‘´–Ь• h–É-¥BÚÙ%¶h  ЩR¶A¥* ¶m’ ª ©!)Ê›G(]¢€U:8ü¨‡ëb©Æv¤DC“Ì^xÎÝÐaR"ŠÙ|g¶xœºËÂ.ÍDîìáúÉvèz|Áîgæ§±1ؘÃl5ÆR*‘e6°€[A¬;Ý‚ªFJ±Ó~¿8F+è$Ux:?€î¡ˆÜb(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢­ZµjÕÄÍŽû$ 'Ú?ƒ¿°¹“Ö‚Uz¹Ð\ú2žá¤kßçØ5ê6L Ä@Åt!R "B?8žLÉJ8ÖðFqV¸ÞôVÜÍÄ6zø€öÒîÆ¯—ý|îQóÞCÂç¹þá‚ õ]݆Mš©ù B ¨«ûÞáÀôåÌj%X¡-F±=1i4=¬üû¦Èü/iÂ?gÃð7íã†ÿDEPBNBŠ  ¿CJy0EŠ£À€f;„´"¯4Š’j€°H#I‰‘,"ĆÔA•(Žˆ>6áMÇ,8¼;dmzs{rrÏÔ€éDãñõÃO}$D&wv=Ž0BFTTDˆ© :µv$Ÿ»rjì†_R¼åqwsˆ¬~ÄéuWº¤@Êqô‡aí.*v´6j1ÓUÓ$J„¤© ÿI’ÇTeQJ–‰TKD”¢` T€ÅE…¶IjÒÏÚLó´O‹YÕk‘õ=1æÈARdy$P·ÉÛ–;QÓÛdã_ÓËÖrŠwÕâ}'Šûÿµø}7êkööÛÚ™A*+®ßC8ó…“&N?ϼ «ºxô@ì¥Ü ‚dÆ /ã•ιJ¬q;þãôzîþ !Þˆ¿`ið<¯‘àˆ[ö[9·²žïýGÔÿcì¿;Ùûü›«åûèd€¿$   2‚ r@"1çð¥þÍYô¦b¶¼{Ïé±5!qøŒŒGVQ~~QÖ)CYd_ÊRVׯ¯ÂÇ.Ì3ŠˆBû91Šôyd•FO;ùu¿yĹUP?pøDkö|_­éCátêé4k„Œ-wN&ëÌzllõë°zs9‘ì»/óÿ/·¼ÑÄË©ñg¹×õ·L“Žm;8B, îb!.üì—ªýIÅ¢ž~ÇÍG´Ô~kSÆ¥üïIÉÃN_»Ò|‹u×Tá z.‰tÿ§×xÑ,蜘ž÷ÄשüÞ’È'yì;k:¤ãP~?Q»~ØB_]Á½`»ð*þÞ‡à—æ°àH€ vŠ$Ë€€{‹äK,ñÉšL"¿âGî©ùõ\ËÞÊb…vqó콿üß?³û·ä°ìºÒõwvgÅ8¾â%k 2X _jŠ™6 £§1&†bPÖ•¥¤ƒ -j-tº¨¸³DêÒéϰù½^žœD<¤ÿK/Uóö¼™þ]ïS9D?å.?§>—øñ7¡ÂÞlŠý<¿›ãФš]¡Û©7ðØ¥ÌóÛ¤5³}/!øDtT•rÇÝd“ãèã–ãÜ V¬BKsèÜãÿc•Ùü½]®×¨äeñ˜€ã¬gxÝ|  #º³VëîŒL–EqóZO~4íyBDÀ»ë~òLÇÖÚkñ€‘ÈaXžöΡ§vöí]ù¤ð,š„H‹@ `À€‚¡ S $„BÃw÷ÝÓÛÍØOsÎõ™ !õ9ý0¨Qâ„ 3£é«ÞÿÛÃÀ* ØÇðs¼ȉ6ãñâ€Úß7 ¶¹_|Èᙦÿ7¿dÔºøü^ãÎoËábûú+LªòÔÕ+Y®ª V”Ô÷Ÿf-ÙNõYRE‡›ðŠ:mö^Å_ïgÜŸ9MF{h_îe¶(4bÓTlØ«Tªm-­­¶×ïôý’!ýÃýÑÿ;ûÍ'÷&øãùÙÁ #²gÈÀR ¤­?¯«ƒÙtuMßy§ås895 T ¨r„X°jSR§o[ “³[°«Ï½†TqzÙ…RÊUÕ/_ëãW@§ïün-Ùò™ûU„$ODöœýÿ‚β§ÏëæUUT=!±ðåK×Þu'ÁÎ’HïPéV9¥ŽWßnŽ‚ @QS:õ½’z>!Õ¾Vzu}çj…}ä5h|1neŸ?1»õÏÚÝŒ9×übææ¹•ÕD»0ਪ(ÚÆÞ¼:&ˆ—_ksâæÙÉz…÷À3"rWTNJœ©*4béÉv nc5LJöûÿE‡)˳‚ØÖ)Í7™˜4¥¤IRª¢›x2pvD๠¯öÊ[~RêÙ‘‰¨Ô þ,q$.k©Rå4XÔJ… “Z-(Æ?Æàr(ÚÄtX”XæíŸÿ2*aŸÉƒù?ðü”«øS«¤ªè>Þz°ÏöÇ4f͆} ®.„™ÏSΔög8|ŸÁ¼É‘Ÿéò>òÞ?k½úN1äøWºDšsO`ìQ™‡GOwþ€nS¢ÂwÇÂEJd˜•&Î0%L†g’€ÿ¾›¥¼êc?Yç'´ÁL»È• %Õhrßãef4è41+böoBeä¡·Ï =…ˆà/- ìBÔoÛ±C-ÆÊî¤X@?[6ªF®êc/ÕvÉ©€ŠŽôgNóg@Ü&á d”݈¯<£Ñ0e<?ƒÇñuÇDÂÿSøM†ßª=lßµ6 ·†Ø;o(-ôÁxó  ~PÃ_êì_¹^ûÑÃt+Ç}Ñý_F~!ë2žKªò>;ù½f·'û$2û_!Žm¦ÄË\ÚT‘ÃÜŒâýásù×ó³ßø‹jO¯®æÜæ6ReUhÎ1ŽPº¿¼]%û¶´¹rkùT?Ð×þ?EÙ‹Ž•!ŠÀÛfœyÖ_Ùÿtôýß;£³ÿö¿ªèÇò<‘­ÞmG­Ãvé{Æá‰¯^ÙÝޔЫ0/)+͸ÇöP%8Sâ ,QpVÙÝH°[ó§sø£‰ƒC(~º”§}b³fJ³3VqdJlƹPæaPò¦ \Q|ç9¬HÎsœç9£œláÁñY)ç7w­o—xÀÇ3 CO0q4ÄÁ¸ÕÑT’œ{Ô½ešÆõ¦Dšno|]m_m,ÕÞUY™‡ÇìÍinè±)B§»Õòêšîå/7êD±ú^®¹¢–²,^i©gV•||\ÝÎ š„¡48T šþâ˶ ‹A‰Ò(b2©ü¯+z òú’²jçwS'ˆ©“•š6N«›9Å‘½Ñ[¸˜Š’•ÅÕ¦f8ݻɭ֊hC •Xe-Ǧ´·P©…µ¢#(ÞvS:sUÄOcSËS‹™z£›H6"êGYr«.i Å+6Kn% °Dªö?C¬ÿ÷Úóßáßü^£3Àè­! UZ®.•jeˆÕ!Z¶¥ ‚Ó*l50ºiçLº·"¤ \=bÕt {tª.ÒoZ¶öÍÿ8`GÁ×Õª¦IýÉu5Ïæûº¬†ô½åm>|Âx(^#xt…ÔTçâ/ϼrXÉ,cbÅv×Ü3êëÃcUa†’Fhß66Ÿ®l6—¬äVuRÙÜŠÖ‡ :¼¨‰ËtRgéÓ_âìp`£J ið¶_ó¨Ò‚ÿÃ[+ S)ÌG¦Â$P&Ïäuþ«]hѯ-°ö/.-|M“Âg& Üs3ÏÊ…È)PÌÒÉ9‡8.®Š($vX™wGfK²ŽRƒ€n鬦†K¿ ÓDÙ-å¨sÕÀy lÎÿ$Ô¸p±p €sßœ›ü¨Ÿ9fê#ÖLzÊÛÓÕ$1/6©\ès}·mm*ŽqBpYUTP²N”~¿ì¾‘'Ÿ÷3ŒÏ[ê}ÔIÓgŸ¸û}BA¦tÊ"}RDØX!=óø‰ñV =Ÿ{o[øóµóýŽÃö£ä!ÚaÁ¸OŸî5ÞvÐ{íÅÊG¿Mba Ë¢VJ¥b«-±•)Ë Š®4j RŠ Â…TY Æ• )DhP£YT¡IDl¡Z…bŠÐôŸoõ~"@¡=ö3ktÎv\æs"™’žþóàfãaRvz+±WBdÀÖ]#ŽL• «=þ—X 7Jtaö4¦Ä€øÛ^Iæè :}zœúuýdõÝ}Ùê·íÑt&C$wHÙMóm£„ƒû%‚a2‚Ppi2Õ ÞvWvh3ÐÐ  Éoâòí%õÝ© žXÆÆZ´¾ºS=¾=j¯4žºj»ß_*»¾ó•[ñ5]§{ÔמÔÊ:ÁÈÒ5µ’ß’x|aíÞ.¾S“ñŸ){¬aƒëÅ™¢B%:;BÙ®Zl4)“é3ã[ªTxK«ùÏb>†çzîºùVû¦x1jR„»ðx:¿zsºë+Éõ_\ýL2þ>tMÇU Þ §¿=c—æûÎáCMUi?âs¹ZÛVͽ•Z·iÅåNÙ§+¹¡JYÂ{Ù7$½]Q”€ÇœÄ@mú?¯_gl*Â^PLÁÍ¥NR$v®©}ŸO‹6ÃÊžôÃçc$NW«ÜO¾”b¼!m$ÈD©è­íŠZªÐà…a†Èbð(/ˆB‰>³Ã<}|n g=Áƒb‡·=•3S­„â^É“àÅuWSŸltï·~?£n)›7søÈÀ#À ¸bƒX18ñ“'Ïœ õŽƒG—ôþÿóN/Þ÷§ 6I!!ÁïlZ¨§aºR>íå¥SÜÁ´P´<ŒÆv4]~Kì\LË6ÐQi’ BoT$¿çê)¿Ðbä4À“XŒ˜Ã„1"«`D“]à ¬îcß™ŒsûÍBš¿ûáÿ[×\Dੌ;L÷Eâþ…!ïåð„1§,±ôy\oɸC˜}®ÝÀ|Ü!Üë8s†GPož›'ºÎ^y®G¬£‡€†Á¦vÄáØ¯ª~ó·`€ G}Ú}+†ÿ÷ú™MM*ž­PزgtuOû?ú6†yÊãóîß ÃtâÍÜž“±á·Ãût/ãäÙñ ÝÓqÀòcOmÜc,n9üâ :>ñ"4€?»cÿ¯y·Ò›ö9³B}ÒÝïIçg.Õ•†©¡ ã*uÙ5¹Ò$“ŽGƒ`ÏŒ¥ïФ6åA¼ˆÂB÷â€ïèÿÆ éB÷(ð_ç~)L ’Ò‰RÂVÐE3²…Ç0†2bJÕþí‹?Ö¡YSðçËzNñ÷±Âaˆ Cñ]{ºBwkÿ†ñÁØ=+5‘?ެâØÏªû„›‚saíIFg¤ß½íÏŽ…%M68) üH‘sœJSg .Ť1µD)"ÃgøQ×3'$Ç|€ÏÔK¶›5“ä0Úuú±ï!ôfFÊ÷e¢%028KA±h[NÔm«³Îü®3ñówzŒðˆçß™¾‹ô¤Ö‰»G_sIãLM8äjH¢£¢¬&Ü@vdÿ×;›¦ë%¢Mµš×¤ÂµõA@DõýäpÌÌœŒÏ5Ö÷»‡à§8dÈÈN“C(“2¸XIT̹«RL¨n (D¨ Õ£ÄÔ|N—,Ø@8 Þa—žh¦˜BÜ­4‹£“UÍ¡RmJ ½XÔØ%õ2r¤¹ES• B9²J&[3žÄ9]nì, ˆÉÆo.²"”¼5 !àóå Z|zÌÉØ¡Å\Zw5¶JÎì2€¶JÎpÌ€»PÇAkrs°09YSˆÀS¦¹Øp’;T8PmNÙ#‹è9›ÜY¬Š’f$¨ÙÅ!ðÙ¡ Ù„Æ¢$qDAQQ¨èˆ2.7¸Œ­ÄŠ˜‘M9)#§MÐÍ~€y>Vzõ÷ÿp%Þ@ä趤ŷÚJkG—UôDg(v.:QÑ»…N웵‰¬±¶ÇBa);)®”Ý£e¸RøZ+ÉŠTqFÎD½YFäEÉ[’raað0ïîðÏC¡5i¡örìjórQAXÈAAXƒ‹#‡gäd«}W†Á´leÖ›GÆ«ƒWàaZéø‘“APAƒ©ŽL\(°Õº` $€Z2B!Š.â¼d Ëë‡Ï¢«ÔÝ‰Ë v ì–ßyòauá¿An”_¹nk„]Jœ„ Çh D”<}èÃhŠa,_—.ŠÔ¼QP­"Î\+eGzƒlÖÊå­$éÒ:!XˆŒ ÃÆ,1*å!‰–Àþ9@¬¢„ÆT7Y•C4–ÅRÙ$µÂÓ¾:'`LDhLçÅ.¼ç ™±IËüML\±d$dB74-â\8Û”›Å³¯&_ÆÌ‡KÀ¦ ºÚÄTNzáâ¡Ïk x†b–ë§B¹IÈT!5GYk£gŸ%šóç49˜Ø‚• KÕ¼‘á³ r\™`Ùe©-0p)ŠœÁxM›­Æ.Z´n~Ï…²G`TH›Ze"¡ FªN,(¿Ê1|®ä2…@UTA«fÆ#)z44ÒKRÝRC1'UMS•·®t6Ø-ŸdÅ@ âb» &ŠA¨'.0´*%Ò&l䤶Ðå[d7pÕ4åÕ#bÁ³Bk⎃ºjXÎ>JÊ&9Phí#¹Kíšõó^µñç<ŒÎ¿3µª¥–þJTõŸ-ò–Š1‘aè{CÖŒ˜†A“Ñg¬Ãr †áªÊ—Ùë8²H?—Ü“èäÍ:*.íü00 ª›’|x“³©íøõ¢.Û0¥Ež½Ð2¥E1 cÕ°Þ#<½'»Þö2Ò 2à¡aB!É å,)X,•–К7}Û+µô\Ó:"‡dw"ÀX‹ 2DPaAm{<`z˜E $[dœhÅ«t'Ð…i'iøœ›«¡·¦ïÓ§"])Òz^üõ󧸉װLÄ(¡Ø¨ÑQØ/EhìÙê«„ýÿ Í]»mùwX;e@ñ|­úH8%ʸ@>ßÒ÷°çº/‘Øö3Mmz†=ÌG./Rñdz d•¢Ó¶‰í¶§'ÛwA‡þûjx ´ˆ G ®£ýþûªø?YÚ™¹·6i¢Íâ Ë‚»Q* ÔwÁþ\×å5‘êò»ï¯uc¦ïö³1S7e¸7;Fçƒú~Ûâí†ÎLû™êÀ TZÈ¡h®óæÜCìèúíÏìÀÞôGíz jšÀÃö}oã'=N€è}ü@n‰ó&Aâ\Ï9Sí}Ä_bÙH°UFÎi¡º(ËéQÑÂ3s.'{þÐQ7â.ˆ!ëc`"ú¾’g¥yÎlÍýÖ `å±öj'ÔÞ¯´vXßxY¾Xü´—;÷1«un–+Ó“’mi95“So.Üù7d»Kúðìãðÿªý@çfá@*0Œ$‰ P °Ua €„Á ª%=Šª^¯'rÈZ!m¯ Þ›)Æ ”Y b7;2lbvç |€þOFNõUiV¹2Y" Lw>Ú=_ç~w8*07 šÅÉ ×®ƒu¦†7èÒÔ£Z0k"D‰;‹Þè14Ú¸(» ñ €Nåñ⨗À{Ö&, űIí ²Ï}ýîGì?'5ÅßÒËËsÊæð’ê‘·M¶•ÑÂqµÑwôMæèÛ>7çïÈ·Q‰aGÇ »(cô¿Çï{¼¿ÞÊU5¥H¶=ºŠoKX ŒQVÙ¦²J©d¬1¥é†‡ö¦eÊc›zI>BÜÜ5ýõÃÉ·«llL­76ü6¸aÆ 2[%ãñ›xY¯î¼ç†êóh6gɶ’Kx›Kf»ÂóÚÑ9ï;xöG¯£ êh+ðoGQqìùüž4½Ì†H‡¥ì¤üZŸÊýßOøXÒZiøßaêX)R•­‘UÖñXj[!sjаZPîb7ÃÙò°Wf&0HL”!RÜF'}rµ°6j Ô{Šþ#š¡óZÔ†²Kªµµ‰F (” Å•ª¦š–JŠ©K# jæ—+m”AXá™X&[S»© AhÓžÍXù®†RصŒeµþWâTû² äwœ£FJV+^ÿ 8Q Ie œ§€ƒè…’¦þÁ¾GÙ ¤Ct‚,:*æ\F/1)© ´ÎY~ѳ_ãîùíZÌ 9gΛ%®ªá:ðuR”çî±t֧݉i–VI%¾j¸ÅÉu¯›Ž(Rê_1«‰pÜåÓÏ‹{,죯nÖª 7Y.¡¬cXÎhÒN€È&Ñ6Ó€ d¹n‚Ô}Ü Á¥¦ÃT´îÄuD$ Œ yR’-Ù–E‰`ÁZÌÇ $9aK§ùò:£®ðÉ|À‚É;_®Å‰þ i¦<èW²°àV‹CJŽk;­q#ИÞRιìâÓ9%%@<¾:L‚s-‡lïÂyÁ ©çêc¡_z˜¥ 鱈…\ËI¸—B¶1ve,fZR´œ+1"f¢0Ðì9I™º£‘dë@\ÖÕœs‹S%;Á̺ÌìRž”ËË{L©yzŠ”¹+º0 ’Æ›…­Ø¬"LÙ1¸º2,ÿ¤Œ‡.¡ÊVD±––æz™2êé u†•§ æ‹ Â:-JèÊÐIp€_Ó ¹>p^Hµˆ|„àœdåŒ8nÚ–±Œ-‡,.‹œA„@ÕG ¾`ö‘2숶ÍÊXH{ÜÚŠ"Å{§Cú\zCÌ !Æ—p1Œ¶†¾Ì”ˆ¢ èÓ£n;@jŒñ]Qæ½ËÙÛÎæˆlÕ‡,ÝÎ8T¶U•-ZrÆšã( Αé0!hԘĊmÜ;¼îµ«V˜ræL–päZ’û6ž§×¶¶ºT*ÃÔoæy{óOª§µñ€·ºÇ¨¡[óÃûâ¸]JcŸj™ÝV¶ŒdÈb¢:`Å^¯gmŒ2Ï[ªm—µðŠEM/ºÆMVL›„.º‹§†?õç¾ÛÃþ7?¦küݼ€š"ˆtmk 5mÝ'qä&ë>æ™WiFfde Z¸Tw}Ð „EU­•7ÎP‚ï4µØaq•øäÙ8øÉa(PÏI_­ÅÍFÓŽþ·ˆû;{^ˆîgÛR–#žˆ3Õ܆iÄ(…&TLà3Ô„‘n$Ùâ‚zø5jÄÆˆÚ"¡N8™ÍññÇ™æ“÷^–7o³HñÓ5nSÓ"uqì™vÅé°A&ÉFòNú®2ê B{UDjD1 ²£ü‘alÉìŽÐÄ`,¨&wˆ×]g(º…@Ž€ŒëBm/…Ø3¤sÄ8òúÞ=¯ëÛ~+ö#®²-‚€­¸%¸†¡%ÐRˆK™rÚùÉź--:„©ê!Àâbx†ËXyu4r’: 3“‘ηâš™k'6k'±¬Kß…m‡Œ€ø^…é«¥¢?¼.øÒˆ¦ün‰üB‚zbéƒ]² <("z[Ñ}LÈy3M‘h È!UºùCáoVдšwN±CEª¥€©5Èhº-XßDÊúß`klïgr²v§CŸ7iëh÷¶mè3‰Ö q,KÕ¦ ±ëø¸ýW]ýJ AHŽ$ÛF0 TK* !zŒÍl/¾øA—R×¹u.”xAÝ÷²4¢” ‰]S<£Ï§ª_)õå”xäkê¸#´éãñ‘J•,u1âãÄêÜDzqZöŽå®à€ž²žããèéxÃsÑ)5SFÅ[œÞº3=ÔWnâ"ug­"{SÑá!bgîi6@uI©s`]IP¥/5.VE‚¡î,·x©ºŽ í;|#(G;ÝT>˜—¡§\ŠŽi´B‡'Ž/SUqìš^È#„ø®ò"#ˆŒAà¾M®Ñí§õ# êÏRkÕ{úÌÁž"$á¼ØòÑ:ÀéßdJ´&6§Su>d…Ó¦”{^‰YÖu¼ø®ø8â7Ý>fÈöLâ;%‘ ©Ê#[˜ƒÏ¤xy>®75 ƒïÍôÙ‡PاKè设xoÔD+7à .¦™}O¥†ñ¶þç¶ñ1…´§+Ó´P¢[öÁéìýxè(§.÷GQcE ÑB$=|ߎïʈ<ìah”Ô W–v3ç㮳UƒV”úäù[KÉ _6/Ad£%Þ?èå‹ñË|F” ך©\î¯íÝ]õt´«cÚȞǔqo¾÷ÎûçíÝÝõu« Øñ¾gÁ¬Ï×;Æ.µÜ“ÕÛ«Òv¬'kBvR”¥Ö¾—EpÿŠè†,«pwçæxu|é<¢úÆe|_LõìÃ,ÅDtŽ%`^Óg‚¤2$IéŒåA„‚ýìß#è>l†©}‚Ò9ùú´Iÿçÿ1#ëÜšðÉr\ú5e"ÊY¤ah°ë­]•¤±¡sÕA%Á7(w©TMõf¨öív¼ ·æ°‰ çsF5²ÒŽÔjDÅj¢~›#XDNAp‚†@€ ˆÉMVo^_¤¦OºóEÖàÄÙbè-ÑR¦YZ ‰bIˆVU´3"–2fX + HÁ0Ô’j2²z)(„‰C!¡Šy+‘!g´¾°åËžW¹5Ôæ³)Í®onîQE]þW9¾îz+ªŠ1Å&öä Æê5¤±tµ†ÆêGÝ&Ó¿[¥M¿W_ˆÔ[ü2ŠÒ†E"¬R$P€lvù[fÇûuÛ ˜¹s;n½‰p[:°]ë·éÜžNAÜ¡ô¿àÙ"Èzù§0†±k1,ÈlÃq$R`fã.osyC!3ñ×TYD¤«XBÂXy†ŒÄÊp‘$2'Ì.)3“ & &+jlAeDJ”Š©: dM¸ÈéJ‹duÜV‹)8,Û* ò§¸| xÀÙd8ždëHb#– )"µ>&­;±&»r™¹•Mˆ†pÁvÑ5}¬i¸Pقل¢xÉ'¨ >Pý„ÃCa__jb7HL…M¸é¼¦3ý 5ËtÖ¤šx“&/Í`‰VL!{$†X{»Ì©õ€fßÕ½­Ž9¢*"¾ñgS—ø<>(5¯Ûщàj‘HÅÅ·êBÚb®œf×UÐ#öRi{ë < 䟔 }ª‹ñ>¨kϦR6®61ئYrÝH#¥L™E5 ÜD¾\j°€ ²£8”¥äíH Sv6+£v,,²ÉUk^ÌþF¯ôm¼7Æë 7Ô錛$oá%ŠZBÈõ¬!Øé:ö±”bÌwepÑc -M2̸Æe 3žFÀû ^ 寲oê¶ÛbËVÛzRd6†¾Úu¸ÕH•vÊ Å«z*˜ ø£Pb§µ×e“)8ÆçKµQçr°v(Õ+ñ.ÎA·cBÊ;\¼|ý:±Õ¡ û¹¨ËŸëwøòݰý‘[²~ sùL…L ìÔĪ´)– x}Öqå—‘¿‚åàÝ'ÁäÌw¡È¹ ûéñx™ÞÇ#¯»ŽÝ­¤ 3F^¥rÌí¥±jZ1ŠÓ”¢'h~rxŠªšW‰K=Š‹ÆvzŒƒ)în™«Pé²ÏgìÆ³:N:T¯~{˜ÕCô¼ïf»êaU·Ï0@îuw *ìp0‰¿—ŠªîŽ;‘lNéf"©­Hb­Zª¥‹,äA†*Ø›¡<êÓ*uÃn+f”(ç ¡Òk¬N>æSJ:£>}KR¡l’­I´»E±ÅD`al #0E"ˆ ‹‘mZ¥ƒ9H0÷<Üs¢{ª’l%qKlò#Oð³“N^Úz\¸Ç%îÀ¡Œ‚š£±{YÀ>R-ɘ@ Ü1´›rÚ•¶'rp±×ÞÉ…§e}ºÕÂð¢-.1{étb$Â%‚fé ÆØ'A‚a·H_.l„Ì­&ù€¨œkòv¼ÇG’²õ§_‚ë¦ÖŨ¶¯XšD\Õ¨ £*NJL˜åÃtÖ7Ï–ÈEê~Gz˜iwáÉ­°µïlñ˜ºå™ñÔÎ}ÇHŒV\³š™·}\î*;ªdè’-u’vENta:'_?»³—îuí¸õ©w~{„¼tx×So1ö«£EåçW'4·2·~uwš”œiæò5çJžÉܨ÷—Øúß'å?)ƒµ¤Lø‰‚mнo9Ù*üjf;›«ô=ÖÒöÄ®G(Eìæ?dT_½Ä'Ö—¾ã\I™ pÄ·6¸‰ŠåÄ'Ö.n5Ä™œ“ÄlËÍoq „P¹²­UÞ›Sn”a˜M*É‹¨ˆ˜ˆ’û’jæt*œ®PÛˆþá™ËÌõœˆ²ô ¨„w.UÌÚ.ë(÷¦ a§n·xüÚ™H æW6¨„&ð5Šey åC…¸ª'0N‡[\„Àäã$ú± éñkx·û{Ql/7aàI x‚!I\œ-nŸ ›9ž£Là\´¢î^9ä9ÐÌgn&-ä J¡gœå‘†æ÷’ù+ÅUåYV@aŠ•„„ 8'åSÎXz?É"X|©ÔP8Ì n:”AÁå”Râ²zSñœÓ»™ ˆwxŒAu}nI¢¢NßW­dz:=ãŠfL× –“Ï­ÿ×ózE¾Ç¹uD}1îž"B;0€ ú#Ó_ÆÑnr³ï(àÊAØ3^ÑwKh[ñ b"yÍzt/·µÉitý¯%ûŸ§Ôô·zÍŽç*m0‘‘Ð~vcJZ–}öY©K%1–%³åY ˆ) ¤FI£)Yb2QŠ!-€T–ØlC `ÈÓI&8 3B`ɉ1%Q„‹†¤–$EQ#”",ud˜Â¡ ÿTY\FØj™“òÙ¡$Ó¦,A À€ ¤•PŠA`Á[E$U •QIP• ÄY*UT$+&!qBd A¢”“RÀÁ? b\K§’"ß=Äø¦ÿuÐ’jÄt]Y#(Ëë#f×;µÞš«c;åd³ònmŒfŒ6¡!u¨ª›Ù‰ÙÓ¬*ª··¯º­ÚT C«È(OdC©ô}¶Ÿ?ÉÐs™áM’:CÓr;Bâ!6Hžgp‘;©€¹v3¬£á×Ô»˜zºHÄl#§™ ;¾[W ^ÏËNhÉ„ƒ¼špu{æÉ¨Y"Óï•úJ' E7mܶü[^9äÐá’IcsѾ­µê{ÏÕ¬w2¾´˜Ÿ6K<Ç:(hwÅŠH’Àú ¦V(ŠÖÏ N7±a ³Å…a„<'ðIíÖûŸ•„&xòF‘¤MÅ3è©LF(„XIOI˜þؾ2zŽ®ö´†l· 1q†ºaÓ„ä7˜E?3›ËúíZª×îP ma&qP)6"$ƒ#›+¼jÙ"Sl™Š˜¿š©Å´€¥ '1æù#e :mbÿº1¸×~.ÌC_éu8¹ÀE—+¡ÓÓdF®íè$Ö"NSk!Ñ»œfòЀ@ Õå1€ìÖ)jÄþ§ÿ¿'1<ÅGÈ_BÛÎXHp¤{vX ”‘…mce|‰7T¨IV ˆ¢‘ü-Nš›a±`‹F dûñ…9^Ùz?vZ6_ïzYÁȼwؽm¬IÇ;/*¡ 2}È)=_UåúÓUR9/4n¸OÕX3S¯çm À…¦²„ý «uä[ÏyÇýÙ÷x)Å÷Õî½Ö²ÛÚTØŠHŒ„"²"€YA y£õ}¨ë×ÂW~¦ÉFÊ|*ZZ[3˽Ïî X²¥ˆ±J[Ñ.-J Dh6ÆÒ_l Ïïålx†Ô˜S•1 öV> Ü£’ A‘6B@æçd°ï¡­Þ¸”å/mì$ˆìêï&×Ç;©•™`ȤÞeF} p­!p` Y¶w(´6 ‹ù–Þhï$ˆéðÄ‚ÂÊ,±;»÷§±Ó¡DQ‚€léÙ.nЦĒ[è­«ò>UŽ”è'é²ÙÂo¦Á±`°–¤»•ur5Ž´¹Œ!¸ ¸`½_.ݵLqe’³#œµ:ŽÌ8óìœe•¡;^- ²ë‚ W1Ãf%î²Ìª~©ÅÂq˜Yu§-½—‰Zq‰Ò€¤:ÿ HsL3ë«(¨ºÈ*©¬NVñ„ %-'Ú«'<Ç“j•ö,'“Os›Ó[ ÙËÛâtlz"È  lAû _{²lp_˜Jš­¶Å].‹+1¨$‰ŒV Eabª$¨}ìª(5*Æ(Â1ˆFЭ¶0TGûm ÿI†ef€óWx,Ïac—BÇПÇùÝÖ)’äíp[âïš'ŸŠÐk<9 æÁ½NßéìmbÓ.mp”T@yx@}-‰ÿVÔÖ‘úßÖeÍÃàÚË®°½KnÞRñ$„ ¢ë¬ ÝlËjC0•PÁâ%˜Y½'ÓY}5„y0ûªîÅ9*žªȲH I*[`–Ál’Ы‘lZ€°‘`Ä‘BDa‘Eb¬d‚!$‹ ˆPa Œ‚Å‹$bHE„,"Š‚XH¤X«$Œ‘$[-‘Ä-H ç7ss Sßš>¸s«î’¤Äl‰5½4¿‰qV-‘û7G‡rèT‚€À} dàŽ¶ª­nÞÁÁï͹S2%ÑãTŒì1ÑÜ: 8”Û.'¶s¾þ®W÷5ŸšÈÚr«´ë¹lƒ| @´öOPÈx”@*¾ÖD\6ÿ×äÁ½“µÜÀ>ì:ÜžÆ)n(B©ü6ø|]eS²›FEêŸ×™7+{âÛeý!.½S•qsê±-vGE ,·ÆtTþoße¶7™#ÓÁûÍÓXø# <(eæ‹Íj}¿ ¹ë}M³RÆ‚»0uÅÉé¿ÜmÝ®­ÏŸ–› ûtÓ íÒ¢@¤×\W½E74B.’/Dúžßcä|.?üs&“AöÜžN¬áLJ!µb£ìæÿ¼áfEØÿ×ÊæÅqüH)ü?×úSÃL~Ì£J£ç9–,¯µ}K#¸êºòë=y‡pùìyYD„óÚ“æk’æE†¬•YÌžz¤ “}•oK‹3n™ƒI­ Z–+[©Ç‚}ÞÒ,"‹($ÊÁ¾+q¨8((‰”\-4gÄæÏ± …¶o±IdÎY9«Ó…UQˆÇm(‰‰Ä7~}{Æþtu;ŸE†¬1pb )H -‘Ç€ (gU¼m»|ãÙÁRlG…χҋ<äe"ÙHñ–xiu“¢yYKјݰ–¦èOUˆD„ÜX™ Å“—-ÈèG<„ÅÇ8cª-@Óì‚ófÓã)Òi Ã‚ dl<˜(e ŠÀOdúh©V–¬®å‘åèô<Óz&« l²To'¶ÈY-°·1H¯ëD*r %ÀšÏø¦œ^x¡”<²>$nyû ãÅ\ãd;·¼£µOâ¨ÍG.LqôXšY:êÉ9ºAgŸž²D}Æè. Æ0Š .ž@À+"Èi(Ê!X\`æ.Mܤî^=Í=²¯â]0@uUè⛢d¥‹l1!ÛÚµwrœxv,¤äi¨î¤¨$M—ï,nOÇšÉÙ•-÷©m²"„ŸH‚Œ¾Õð°¤)‡ J™o?eáX&ÇP2|,õzd÷Ø^T'±ú†!ï&ØŒ8|Ì•ŸA‰•SvÂBïžIõ´r>ºrØi!*™¤‰>vèNø²5{ùUEùºÌ"­Ä Bs1T?I;¥+€'ÔUÕ}÷øÔG~3׌ˆõßåL Òq¨ê`\ò]«‰²|iþ†\ÎÙ4&¦…ñ¥Ö©<ØY͈îuÕôg$4Å!]:&O»©P|žg. ˆíæ¾+°è¬ƒ'–W«eB)øDéÇJb\4¯ïÕ%aP” ™…ð%&àJ5¢.H F‘tÈkÒ3(ÚJâfX*™—<ÔÔ9i’b–H¤+'&@Pá!ÜͰ2)X’—€Èt9k`Sy6œ+'¡[®3a$€ƒ)"²–¬E¥•A„Dk'¥¨.oJÄçbdùy ‹VËmY -H YVŒiïzIz¬U`±c‡Ì-IÁkæ!Õ:ÐÜyý—)1'ŽæVõ5ž§4‘á*¦¦,7]ÖIÇ kÀ¶Óìfa­ÐÇ2dÐ øÛ’¡¹ëÐØbmC™ÇJÔñ?Pã5$Û~ê$¦¨Ìi©ši¢±•† zd¿lç@k24À ŒN–,ƒåV;ðÜ!I……¨±¼‰!s"¬HÏ@Ö'ž”9ÝîÀ=IÙ,îy¹$ûCà‡Ã­Û·Ó¿:2Em‘l*U)KI©ªX1c) $DD‚¨ŒH¨("±d#(ª ¬ŒAIT‹! ˆ¢²(A"+„ÀH"È„•¬,¨UIjKVăB„*E"Š€ ÅF1‘BÐ…¨[VZZ[µe¥¡b‹"Å€ªE„PEH c!"ËÖh[L;™³Ðõ¦¼ê¾P®t9¾†! 8ŽË]¦“{Y#ÐØrLX¶è@2P‚3A`‚ƒ’0Rb@©Y&Xc¢NI(O¹K#»!ú ” ÃE‘a8š¦¢,“AI¡%I˜"RUõn{ÿj³LàéaïÛ0+%ÏÎâL1¥`²°Ñ»—Ìž“‘“›Ð7e†$³÷[c~âï†s;¢oßsIO¹SCI¨Û&S)  ¡‚8Z@¼ÚápoV´¬Š£ŒI9]P‘ ]+oˆº•\-Â[ðs)y@€Y2Fò.ƤÇj­$ùÉ1‡­á=WíÓãëz±%JD+‚á–#†ü´²â›;®ü¾¤Ò’„¤0$`tÉÑbÁì´òÌóèóÙà “’æHW3 ¦H$*bnIÁ*£fù¯†sº/1ÓmŽYÎÙ–ÓÈâL –¥’Ïb§n1 cMFH³UVD¯ˆú 0ü¶CL¹ØNNã²OVV°PÜM0Ÿ‹»j Š•$ ì"£| &Ð\ºh‹Æˆþåʆ,D‘)¨ù>%ô̈kÄÊX4qÌ`¹" %©¨U¨¥ºbĵ@jÔ}õø~o?:þ»ðºöÍÿ?kë Ÿ¾œÓoâë(òoúœ5± Ìa³R[óH†À4b! `hùà/Kxÿà£åÿËPýi'Ká‡wö¼†S±ïº&ß|ö@N°¢€¼ý2PT`–ÁÂÐÜŽÒÌË‘<1Û>>ÞÃF’*GBþ¯,Y?ñë˜W´'+ ö\üf*©‡œÉihTgUÏô¶ºÝ5,9}ù*îÒPFÔ]v0ù×Ö\­@»®š«·Ø<Ýød62ä¿,vI™A$óôü}} ‰°¨‰µ ŒáýW~·Ìþ®ÿôþ¯÷p`ûóJšýx€“m¾ !VUHšÇ`³aú¼ÔÅðEÓ*ys9AáÄÁ˜\áÜ`Ö²¥Ð…ÑÆzòfô‚s¿Û¢<¯ÖB@ä#oMr1+U¿%£„~GF­âcÄ D‰ I.vœèLıžIšiKå”7»_¥/OÊš`õj‡õ‰eû{÷Bþ¦5“þJœÉã½™°/¦€Æ 0! Æ Okóù>¿ãwÚ Œ„ˆI&t@ žxi!WÛ9ºtše¬ùÕîТ¡,¦µw ™’X¨¢¥M°ã^wz$ R‚ªÈ)>â„"ˆ‘ BX`âÆEŒ‚ H3N2NÌ62“I ŠÈim”d‹!b¦¸°†"0ª@¬ŠQPDÔ‘–pšâšE‘` µ hvÔÍX‰¢édš<Xµk›ËÓüÛ›YYýöÎ0ùö™0®Žº³™©„œžM&éÃ!¦bÄbÉûeÂÞB@Û˜-’#˜ $¯­SóùÃÿ¼y8Š9¢ˆi‚±¦ñìôMøI/¯1•2[4Œ€[t`Æ’m–-0ý¯q¨ ö¬ØêÂ,Éðý×2ß(¢/“”X”’Nï·¤Ù“ ¼ ²’ Ȳ–;D%m˱lUïO.ÄO+ñH¹;tÒM²’·kÅ!É*8Ô|D††$0ÂÄ 'vÇ–²fr@BUT)´Î0Éh¼g&Ðýü³åö°ì§ ¶ õ$W¨D*y&(HÍP°¥ ï™IDOí?¡ C<Î'¶ž~¾\°±~lúNÉ‘0­NFÒÕ.œŠÉ *WEæå2JQM¦°Û›µ¨§ĞјéAd#JÉÆÒ.¸ ˜*ŒL×-‹Iƒl•:¼¾é…¨¶¬œÅsŽ Ä¼ÜYq‰ m)[©¤í¤ý €ðë6›‚¤ýÚÆ[àÛ<5ÝÑ 8—žËc}§#G%[f+  `.+Œ+C ÚæTœôNGîÐQ9` Õ,•IPc$! 12 ÷ñ½TŸéçn ¢ëú½0œÈÅ#$V*ªƒTAAAåH0F1"žfÆ›!6ÕE€‰a­¤¤QF,‚tÙ;¤±Ð#NÌÌ5ñçÛV+g{MUãqݵW3ÆÁγélqt1<4Ž)» —³žžwkPß[ìábj’pCß0 8(„PÁ••¥¢Ò5(zíF ccóYIš¥eB,ÆLLƒ\ ÖÔS—b–y—SéÏIltftܽ™:³‡9YÂm„õDªªþÞÞ†¦À¬f ‚@ùšÅQF"|t¨ ÀUEUÀ7ãWºó€àç&o‰nþns2)…"‘0¬’lòÔ0M@7IUIÒI65>‡B`¤Àcã9@½Û4ÆmÃ]VTxÜ ƒ÷ãaqÙ«Q¤)zrGOCR7óæ“Å„Æh6ƒ+u¹qH%0!PÐZåà‚€éÙ®2—ZÇ -åªf€óÀÔ`vÙaäwJ¢ñd¹kXZØ¢"3gK´C…ÚrÕœq „÷™æÿÊ㤟¾Mfxc¼p«b-Zª«$ôÒVzÈÑ ‘ƒ`xœœ»íÀ¹‰tä¨%ø`âM¬P#£yJMW•Ñ@˜˜[‘Ü 5ã!jkŒ¾ n*kj¨Ô|<í¡5hl!S Ä‹RÂ;OW”P×mv}ô”‘)Š€=άøT+v„¤ám†ä{ëνÚó©Ól• ˆ%Fø…D× u¿(µÑ|\rLx)>”ýóhϜرhÎúƒ·3çl<"Ç£i§Ðu'DtD)8õ®ë„€©tD’!lo˘(Ç#EŠ”¤ ©ÁJ*Z¸Åœ¬º5$š™D:‡¾î˜~”‡#‘ÝãµüæJ…>Ñuø»¶æff׿¸ù ;þ‹ÆÁÄcìj÷BB1™’fJS@o”†Ã`A²B"2Åà …)j,ÜX’ÁçnnK-ŽŒ@(wx´¨†!œpËnì¡hßÍx@ƒtÒI`ècª¼¬Ü6çNfÕÉ¥U{ú›lÌ£ U×¢=¦‘85CY”üß±>b¡¼ eV*^ñÚL 7•HfLL"2“Ñpr½‰,¹†z+ »Eª·!õæ9P^Qì˜áõ¢ '·çÙ9ÆIŽBÈTÆ,…Ô"}^q ò/ ÚÈwr@è‘@ÉРŒ÷O²2M3äð¡>“B뇶ժÄâ°såéi‰a™CÇ‘?ìHiB 1%ä”:*æG7'ΫÝ]¨²$6k±Oy*ì¡§ïT)äi!V¿‚Tl˜gn$”|-@l…ÆÊì)t$<†LTŸ ÝÃzÊò³̸‰ ¬?ž ÏbuÕ÷¾—þŸ›Éé|ÿ¿ÿ_Ìõü-ï‰õ:ϯ_ö~wÌ»ÚüŸìâœ8NzP@9øÁbëSuò­ÊiGL.µ”×ÿø™ÿ+þÞþÉÉkÒßßæ‹‘ÉX¢ÑkÙçÒaNë 2¦Üþ3 1Z褖-°R¿™« 5¶…tâ κ (Ʀ’í9?ÈqƒÆØLs–¤(¬„†Ž¢ƒI—cˆã¬éÄ4<ÝŒ†å¦­é­i ­”Ò¢—,¨¬Â J&9S.03eU\jƒ3VÙ’êèDrÑÞ¬•™G6£öYõ™'ÈB° X«¬œÞ"sØóÑtè8Ñc ƺYLKÑ0ÝŹBÇ£37““´×^ š°Û<ÆpºeFÒÎ-Æ•ä—,•‚ÌÊALL­ÞsͰ1›TKøš‡18´ä´Ý¯$ܺNœM¦i¢¢>ÓŽ&ҳŠ3¡Å†Ù´6Í› @)*TÌ¿Éå?[ƒ]zIC ÃÈÉÈP?í¯–,{•Ào‰’•:§Å6üˆêÅŒ‘GÈlcõËGw3œðñGnÙѧ#DZ#戀åiV»7e™£™y.e”€Í©4Í¡ë4ä÷Ôz]®#žœD4}o†Î¥ë„0ƒªˆ7Z•ò˜ YK>ú°.^AÉ>¯CÙÜæ3GÆ3ÄØóPÌ6SRe=ýâ`áÁ×qy’-¥3/È%”±!Ø’l€@Ì3­$°€ЬƒÛVÒ.4àj1’2v°¡„,Òp¢r¡Ü@ë©¥õ¯,àâœÔq¤Í‘t1 ×[ùy} \:²0Ow.I:¡iJ!l±J‚€#$tIJÀ'wɸ9ôÓ`Õ¯""o×Eλ˜ªTn±šed*,¶Ô–¤ø•™%‘3[ªe(Õ•„Ò‰Œ Ĩ ~Ê6-ë1C6%²$,² HQ1 S g×pPQS`h¶a ¼T´Ðš @I†`¥>Y (!*@XššÔ·)MmŒ ­ÏÜW­àJ •þÃ7šr(PUVH ‚²2M@mÕ xÄ€°a“pÎI0E¯¾ÏD`[`µ¢Œg4žsÇ«\+k^ Š€áúF$“HÍKd‰²xÄLÆH…â(˜h¼TH2Ç F&`ð%0zX= y&ýÛ¿C2™ìòw![–¢õl']éI»ôHŒ¢`²J²tPìPµEJ€ b(H"*¬‰"¢Õ’Nz#Q 5³mkD2²' Ñ\`"¢A( h/‹)22ŒHˆ‹KdD¾Æ»÷È7³”’³\q,¤†à“ÙÓy,¥ QaPK¤S€¾EfðŒŒ^Z0’ï11ûáAÞȼ]˜ßPÑ#~¶%¬Ž6l¦V¶¥^A˜èðæÕV TÌÓgkˆó¢\¯<¸¹Sq^+`$P¹ *ÄA€ŒR‘11"£¨YJ¶Xµ[ˆ»Os {ÿ„Zú]IXu–r¥j4¥s•Ãï¢daÙCs–Ck®AË4y¿LœpIîPÎg¿Á;iúþhièCîù jª€4„Ó ¤†EÊ` LAÕÕ1(.R²’#²J’PÞéﲤÆN Ã$)Ñ&ÎFŒÂLÜ ! 2 Y$¹ÜÈP^$È1%!ªm‘F¥‹ cb’•bŠÆ ¥©-B¢E"*ÁARµD2 ZX¨#bбª2@Yl€V’Z–222"¦Z¥JH((-µd•id;Xi *#A:äŒÛì(¥ÆÈ†H¦  ½„f Œ"I™h„Û d`h’ ‚I…$‚$)²d2š±¶(¶­ZQjÅb!TAkF¶B+U, ´ ,£dQ BÔ¬éãÔvlÙ ‹³° ‹g¨‹’d€mÆ ƒ½/ªöÌÞZQÝ¢¿“rëƒó|~hy8yW93 вY^û#I3BÈæHd‹5ß¶GÝ´,7hšQ»ïoS€¥%[çòö5/¬ RW"€…]([¿ÃÍa½þñ´ú<‚„€}k÷³²m+—V@þɦ9 HÔâÓLRiŸI4Í«4íåÒðíàe¶¦ß¹kÍ,h­íG÷}õÑÌBÚËpi‚[‹D%h©8´)éýü ŽÇªJàb…B¡~¯‰þ3bL’iJ’âg ‘b”-y…L¥­ßn×Îòg~_}›mÀìþ~†Êõ»&±°Í‘?£BÛòˆ $}¾'ºúaKKkÅLÅM“Q”N– HÒMrˆ©Æ;" ‰· ‡å'‹ºYRØýb£ú4š4³j8Uê44 È_Hy®"…&‘ñfQ¸*'‘*J’•R‡èº2Òjß7ªÅKjOCo¹åJ¥å‹Ï$l"©7 Ñ*"È‹,H¶|[-‘‹ Q-$aD´–ÈZ´K,‘lER*¤®d˜¶,ù¥H NŸÉîv(Ž,'Z³hu^Ü^øÄ0‰ï:=Ý ?õ"™PAH"ˆÈ2(§ <Ý;C¬¦yÓQZd‘$³¢€Èñ¬޳Æý·C8q—Rc•Ø~ FíÓªênµµXU¶Îoe”lÄ"íê«m’IjRÂXR-Ka„¶–*ü’#µ¿n0žL•„€°ÔS¶Ÿ5V˜zP¾æëîouÃ`ú0Ò²2 ²°>²[B¹ÔDÀÜ9sÅa"I#ršˆId¤ˆ Å€²$E„ 4VE‘ƒ"ÈŒX¤X0HDŒT@`±”æÏl$æÃ*Ï+Ü’¤8,„Æ#dGЗ2E‹'1ñ0æê&ÒOröV¤Bn`Y8ñ²%a`,Žé,C°€ŒDaxFÑ e!Y |Ð;ð„€pí…tH$Æ@ìƒ9W,B˜ÐT®)IÄ+ŠH)¢TE*º4-ïI!š¥Ôð6iE’´gé%õ.ÜÀèå$—Q<ÓéÃÊÜ\ó™r¦E1fc´·½$œ‹Q,Þ›ñ$T‘2)˜@£·-Dì)3BÒh€Û$b˜”“Ì’XŒ’: L:ØúÜ¥UQµèCÚÞYXoÞòo5ÐH©Ñ¢@i#2nX*Õ’Ù/V[ë_ Š4› Ì0Û}FÙ»ißúÆð°)žÄw´–<§# )&5#ç n»ÉÃÛ¸Ù#þÁÒj—½Èî‘N©fÔfœ‰À»jš”¿œƒU˜Ò¼2Ì,¥c Ùšd5it’íºæÑ=E›se0÷hÈŠ£(*†4à¡áq2¢ w”înèoêËÁFA ‰¡-H¹›lÄiÙ®v:` @4Å'´€;nï°S’ÒBƒ331QN—2ìk“ÜTðûJ¦P†ñ ìs¢õÓjZÄ@X›(Ià_NÆjFÔ<Ç"‚|þ&6Ô¯„C t½—£Ê ™Þ4 S:½é¡þ\ûedD" ¤E’€øã]òR|l!Ô=ÃîBÚrȱCÑ >éïîDÃÎ&š(£^d@sòÎÝM(·XÁ‰BT*$øó|êÔçxv €!j¢æ(t”M.+pïÞß_Žmö³Ôî¹ã›¾óÆ`ïØ†‘œØX`¥¯¤žøÃ\B,$P»…ÏÕHqÞcJQ Q„z}AAŸ!¥V+µ;Ué¾îËe«NÿS`‰?!HCy¢¥ÛzÔÄëó*ÖÄZ¥œf™Z*YYÅÆÔfIâäìÜxÑ…6<ÞAëOiòX(¬E+÷¼'œðTA(HT€Ú²@V&Q<Èìw[^¾}¢æ½ó¶I»ŸúsßÐ[ ÎügÛ ;!Œ2+%çóæ2ý”×)Ý4˜Âé\p…³µ}$,Si@èØß. ð?S×zÌÿ?Ò¾Ç2l£*õýž¶AûzãkÒÕri°d¥@’X%ŒBa„Fé¡€FÓÐiz“¨Òu»X'L@<4r7{o‹gsw œ0·H@ýIw¿©ÊŽ”§aW1m—ÕàE0¢*‰Cˆ%/'â]©©fïÞ~-'93€DQýsþÄgÇÚ’â×d[¡z>îoµmËÄSEÝ ¦ìÒïò?~Ñ »•¯!úL±’¬M%üêD]aªÙ"Ê[PˆDP&o^íñiÑè}Ž8ZÐ0äúü»•d²Äô(CD“ìoÀ½lše!û&'p_aB:íT@›µÀMïžñ^Ó¹ÙWªì%÷¬[fsöS{bŽkSÑ|¿½ÜÆðÌú%ðp{Îl~ž£“19Òp8c¤Ž°O,‘¹Á )Ì©d´qÞ›¬mói~)?™V?÷ù úŽmñr×g¼ù[owк«,ýúØôü/ŸÂ/£‰PúØÔ&a·in-¬cℌÜèÂÜ¢ñtoÝý¿aýððuò^›cÝÿž£Qäüò6<„$ø‹¸ Ìl|ÁÅà±=ÒFAm}QŒlDçø¼Ÿûxãï=ÏQ™ª¥IÏQw6’ݘ3û»f,ãˆ4q/¡£DŒ  €ÀCÀ  @ꪮÂÖŽQfg§ÓÿéülDÈ9Håm Š™kZm?‡„d&þaýmm ©áBˆº± C÷7"01+øüî,F(1b Á‰+æe ˆ ›ZX òÃ)¢Ñ"£2Z(Á#l¶€‰·¨Áq«KbÁb2ÂÆ•2•&&9-,˜¸ X“V),UBØoaX« ƒ«(˜/7&R+8RÈTõ)EU’i-Q"(Å‚Æ*±dX‚"*•¨Ši™– Ò…ˆ"vJÄJ•D]Úø;výïù ‡ðEQ Lu)`ÄͺŒ¨jƒ2—µ×ÞÕÃ!ÓüÖ´0‡6¬YÃFW AHðS&I V  _Bèý‘&‰73² …ŒÙ%ˆ¥?glí먶LmCpo\RŸÐaµQ‚"¬8ìËœ²ù0€Ô-¶-Öê‰$Ë0þÆÓ#¤*~)µ—Åüßçr6~Éå~íø{Ο‹³”þŸ+(ÅGi’Óok÷v ]wâµ$¨•`•iRÄ>—¼Ð)|REO %%¡š«Í2²B(„- ©±ÕœÚÄ$'us5uÄA"Ž¿Át ›1ð¥©'[ ¢"Y‚¿\ °U xzwšÑh2+£—̶t˜F“4òeëª €¡ ¼ö[jØ1éÈØ,J"&¬ ,Æ› ŒZ™“ka,¦µóǶBO'dØ¢Š*"Šˆ‚Šª*Š""‚‘d$‹d4#vù¿gám|¹ 89jgLb>þ©ñ ‹ ¨¢« ?ÙHÉP…‰ BQYHÈwð¶š–&(¸ù®j:* ÷n`r¶`o0‹…IßFf‹$£‘*̘`·<\a 1uÝ™ˆrà4+’Õ [ˆG£Té”ÉhÄUP/ÆIlÙXœ5&Ò]9„[L MEŠ?g¶c³‹¦¦>"nó’Alþ;;X›„=²ë(5yWŸ Ç»¡=T3ËÏ'/Ò¬S^oE ÝË,,ù¸ —(±@2‹¢ ô >'k…G¾йÏgÊ’#ò¡+‹ñ²FM7B•lÄ’¬Cux¸åwÆ-*t2c;Ò,³[´Àù-³Íežzqýœ/ºà$ÝÚÆolÞÌ¿@ eÞeRÂB×" TÄŽ3Âã97C¢Å±“FŒRëÉKà @TK(/¬  ­Ê„A9ìøuD‹½w(Â3†ÄtÈK„DÌTDqÙ¶êd=xEÎ5Yn+!øl&3[M&s4˜‹©’Þ±H#“ñXzB6xV!;šBw³8nÑ ­ö g6&gž>Ð Ä Ù…8èœü'Œ0€~w©Öµ¯¥*Ð2Jvä#\+•F‰eŠ$M¤ •*Ù-²+Ƀ±ã@zvj;¸˜E’È"€T'è”&a'QÊè˜A¶O>7ú3‡a<µI" X¨¢Å!b=o|{Dµö ~î ¢ü¨:6lÛ"Ù˜3È;¥1a2ïFë™ SsŒdÈQ[k6“&@"Ud–‰Ñ¦síš'ÏlF#±]Ù˜ÅæëžFnP« ¬ø’‹‚ àņÜ@ M(aOM·3ô~þ¦Ûnæ®o›àßãp ØT¬QW)PÊ[IeK I 5‘â?.ª9êbUi6¨}xC]då8‚›Âá€rœ¸ÁÐOlk¦QàkN¹6¢kC¢µnOÆ@k„ë²QÊÜêÂD›ÈÕ_É„[ÝbÄX1‹ž äÈTUÔ¥$Ä”s!A „H‚CÀ°£ˆ–Cf™wÂì‰ÃVÊ……p‚qí9X q"ÄPŒ…µT²Ê«*)•rªTñ5ƒe2Á.T7º"»8—”œClqám!1´4‹*©lFÄœ¦‰Ý“¢s£w¢âCW» ëaÄ`Bïi9!ò³a”ºººU7•Ã)¸Õ0.Òtv/Ä Ú”©ƒp%í®@•B h€ÜÕ• &ZYT°«miÚÄY*ZµŠi—Ö4ÑB@ëpDVÂCè0 ˜Ð©8„#¶Hs’›Ž#-l*¥VÛ "•{òX$ƒ&F©FÄx ™" Ônˆe–ª1f1 €§‡–¬mï¥ÎþÚeõyµ"Æ XÁ˜É9œ@ •í;-—TÄ83-„K"Ð@Bˆã ’Ó3*\¥E1AIPY", Q%L)C $ùä>|ÚÎyÀ % aŒÑkNÿ#þ¿—½Nãgt_]b­º<²«D€„v©Ã}ý§i:¿{¯×?ç¿Þ4_êÞ¨Þ²­¹£ÏÌOúë …ªãI¯é?ì~æJÉô`-ç¹zÅ–S?i€] i<Ù¤¬ÎòL!ŸÅé÷S.øÁüÕn­C”«.µW‡õ»1MuË7å½×ÎŽÓ  " ùýSþŒ[ò>öºÝòæ²u±É~÷•£<¨h´¥9¨ˆ4ˆÏ(ÝxÏTéËËÃØ¾”ZXÙ;þ/%¼:õuk“K* |žÔû8‚ž Êg§?hš¼úYFHœ]ñ»•ŒÞ¬ Sâ\ž2ìÎÝo†F6’I*2gU0„b5g;§\O]nKÌþzj¡ŠPÍ`ÓÜÉ6I0…„û6Ñ"Ò-ÚÂcé“JRÒÔ.«c©ùª\Ïäl«£rÊ;—0ùóóâ¯jsq/šñå_¤£·|½¤“vûGÏN÷(žýÎ{sO{¬zõõfûÑÒhê*u}ÌÀÜD¸¢w†VÕ€’'t_·Zˆ±ßDœá9PN8’ÜK~/$ÙëZ²Ô-¥R?•Hq¥£Ùb¤¢ù[«Ròe/i¹mnIÖL•-ž¬³šv£¢fT v<»˜5’†ûl‘nY,n•7É£s© «¨‚ü.ñKÑ^5¹[¿š,IðOH-Fí‹ÀÇ­Ü3ÞσUº¶ŽÔžnHBŒn– ÛÅT˜ZìïvNz“`"/4îJ™ÎϾÌàâÖ`¶@«˜É×µÒˆ°F,þ/JbÁEê¦jάΧ³¡°:ŒzÝ(‹bν)¢­ótoÏ­RÚé£)qH©e,Dãµc“Š ˜q:„>IèJšo4Çà?POÒ+ñ\ã‰ùçè|ãb<Îëzj¢ôÕ\´×_.^~ÒŒCàýÆçánLIcY:¸£Øœ¿NŒ,¿®ã/5¿&Q#q5Â×@}+Yt™~hõBü—8±5Ý(IÈ(²<¹º«=µµa!´´‹£f“Î;`ÊöÆU°«´!±2e½w­Wz&+¬2Þ7Éú!Ñ6³–C¢¦]M<:†ÑHàpWÍ`¹½TŒ›és€íÄDJ='¾Ýk•ì®2¦ýk’-oC‰Ïi†þ‡ˆ˜—v2ûÑν ñ³ÿ0jÕX |Z7}ŸØo²á72•ÌÝW­Òl\k#zpdI*TÖŒú“„(.1!,(çnêæqÃÖ³çmÏm5™œÚcáa,Èw<”ye®\¶î¬°àû%øô ïEb¼ð„K¹H*IRZ¡ˆ²úUZ׈¡r:¸þž ²¿N <‰»ùÙð鳺 LÐØsªRjfŒŠfFÏX5 @V p˜‘9ü`P(ŽT¾VKëmËš]æbo6™½ßyyÉ:ŸºzÿqLï³ÆÙž¾¥ü²ª!‡ÚìèäÄö•ݺ)— °f§::/ ~«›iâÝàߥÒ$…ùnÇVm+goâæÕÓˆùÓÄ"½¤Ê§ÌS‹."ŽHÁJ+J*SRÜ»’ªªŠ¤P¦fI¨P„iÏZ.n’a‰½Ë ¬èòçÄ× Ž:L} É"À!‚‡© ¬‘ Í®I ë,ꥮ`èAÆÈÄl㜱[w0¼·–@TäɵGÖ*LÈ’èäN}C»‡e­jmšEÒº–Z$ýK+D3ÞªNö9*Ã3ÆÞâIão[y̼¨UH,Sý¸–H©°²)®é)åëPšZïYDZ(9 ‘32¦Áì8Ãh«Ñt·s<ÉšIiÇŽ#w“™ó”ÍèÁÇÓŸ¦_ÝÌ #ÌY„ãŸXÈYvBðØÀßµOy%~8É*=ðV‡~/ž ´´´µ‰ihµ E²,‹"‚ŠP‘AdR‹PPR,PH QAH¤"ÀFE ¤E( H , ( ² ,Ab‚ÈE"$YE$PR)P"‚Ȥ‘Ad’@"„X@UI€¤‹„X"QHŒH¤)$QI"„D)Š¢È¤,YTX,¢ŠDEH¢"Â(°Š PD‘B AH¤"Å)‘bÂÜ`ª Ú0Õ¤@nHÌÝ©±/•‰Ñ8cÄF! ¡l¸\Qf"`T+ˆcª2 ‰A‡jÓL°´“NyÎDªÒíð( Œí“‘A=Ãö-¨¼òÞ_Sר†ÑAB¸ˆ¨U3J‰ñÀÝö4; £´pY19³~ ,6õ[’z_ì‹”Õ¾>Ï^Â4éÇùà­l…²-–-² ¨È##w½ïýûú–Þ>§?;*\¸˜•* JƒŠ‘2‘t)É®5—gC®ð1ªŠÞ€¶+þn©˜ŒâÕž–.:Ä‚[ Eòª&›py¼b 7SMœ™<–r_ZTHT^‰2eƃ–ÆHÝ$Ù3¢¼'ýØà´,²[ ØŽÌ\À,»ó5íÀ09övz4Í’~b½|Ð&BÉ¿¤&䑆kæ³ sº}3SzÔýIêÜD!jæ.¬ŸesšuB¦ÔjdYLºh3, †¯u¢Ã{˜åºw•Õ5’o­¼oC« ‘g4Ͷ¦ Œ% dÀÀG(Þ( èüPyÎeÝ2c”H@aÓ–sî-­3'<¶ÕvlÐr¤ˆX!^“aC°{ òäóaˆ#ªh®Mþ'å+ø>/6òæN{áX¦áýr÷È“ÄÊQ0jY}Ü×p\\ãÔ/×èåu”.içÍ1BD•%˼²ÕÏe‚ŽeHÀiFM–‹Õd‚i,´-®Ü£Y”^Œò¿s¾axH(‘$$^œ5âQq7‚/(D‚†¥J„‚êïÍÇÅ/|¸5·P§“0Qéo)(?ÿvиß}üXZô½zÔ4ÓTRK‘”XnMy}ÆÂÚ~FRJmÉÚ†´ú|>ßõ¹´5šrêÒÙïî‰Ù›ENø¥i½hÑE“ ä ;¤è€óRsµ»ë÷òmöiæoÓÌw“£Þß¹mðuäˆô¢èA@iu©¯rHLQ”¢Dd("%UŠªˆªÅ}9èÚñÆúpó¶=}½Ç·¯c—n݋赈טþ5Åaâu«¥ÅiN~Nº>ÃùýÁbäCÉ`ñôÖ¢{jÄÎe `ˆëmj0uàˆÐÔŒŽ­¿ûy½?Çæõ]¿7ÎiÚıº––Dd7øSëaõÝüá>’4çbÃ&\0Kf\0fÌ…Õº¹š  Éé'°TSå}µmö…–ÃØo夒‹›@‘`Q ãyNG~Š»b€g]/[2èieDhö˜¶mĘ«ÌÜ2ÕjÈúµ#{§IŒ­Z„ŒXiVîo©K`±IÕ*€ëuÔ’_™!#¥Ôl†H«EI@‘Bde"®Èжæ’ ±ºw\%ò`0µ–N×2ëF*j™b°Ý…Õ-¨Ô)¸…Úe‚†’AK‚Ñb‰a@>ß³Î=¡fÞyûæs±îC—”9"o, Ã-ᚻɑ=Ù$1­Ì’ oJif¡+ó$Æ›J‰ôžC —/§-´ÝëWåº3³' V!yÐŒ‹ÑÌè¹ÝÅÍfÎÂ1¦ýš íxÈA4$ÏEP-„bë³õ¦ED¨ãYÈŠXTT'On2ºÊX j<£¨"#Ð ßÞ%À Üšl®ÙÁ#6MÑLႳ"s:Û–0õYZ”`¸€TP1ÈuõwéYØ@h@í ;Û8ã¦s8p¦g­ðj°ß}ì8ºÀ±îþ$N.ݺ¸sÔ>ÃÙÈ»IF6XX„˜“ˆ«sÎi•”©¿Ž 1&÷ºl‡a#ªÃ6I ¡1$‡á°•Òœd Ö„¬,‘d€(°‚ (“) jE€(@X©²B¤+Œ“ÀY$©`ÀÆC (ÈT¬!Œ¸‘d‰F)‹—c6ÛE°[$zµ'$B„<ÇYèÍ”ºumhSøÈ‰ fS.ÔWÙ÷yüÜøf¼¬ô̜ܨâðh’AÑBÕ£BMyä5IÚDšÂ¶)í) v ÖÑe¸å ‹d‘TÒp H…½]V- ×3-Þäž9€ŒÊ·aApáÇ Ý¹½LÊ´ˆ %oNu Tªw¯]·ØröÂÝ©²–*“š)õ6£´„n3©˜W H)6LŽw«rÛ B8âŒ.vÎQ$ ”¦d$¤ÂιfË­èĵÖaÆ]Y¬©¥ˆ‚ÆÊÆ.`̹—͸[H"¶’ÆÆ¯wwñCvãX^(¢Z4Ql¨TjIJщfˆd€Ëš†¬Šæ«1«˜¹3-µ—ÛM˜ãcuDRL°Æi‚ 0²PA‘j$-‘.C4!œîEb°¹¼:óã@á»xÀ±f<´5ËÆõsN&”y¼ŽZàf¤Å‘cVDWmPUEV­)S‡)Ž!‹Wé /d‡0,ר)!Éäe¬Q!Z ‘¥d¬dÜräI ´•MпAPN1`@ÖpèË£U#‹)@õ"zè$‚ÀQ`²)#*›©›6BÙ9Î~låWâ¹98LјÃ>>8 «Š>|d•§BE¯¡„î?ÐZ­__k"÷­R>‘øÒZ¦ÄÎdÄ­­Ðã´LJ1Liiª¸äÈ‚‚â8··òlÚ‰ÜA’cÖª>E× b‚ºQöeÔE š4†£‘‚Bä5ëdTÝæŠ[Úoˤ!¨û'½ö:¹vÝí©‹- ²ÛmçZŽ´äM¤’Ûañ:6ÇCË+ëþÿÝ®ÁÖÙ{FE(0™—KFÄäIwÛRÀà€®>V%°FC ` ÍË(2@`‚€àc,wç<¼äm¹ŸCCÿó{ío{Í"¶Íe¸yLŽY¡ct` m)aP`PemÓšŠon¬ VËòÛaÕ-`Ò¤@zOC×s`–la$„bb3æVÖ° ˆÅ-´¶Ãù'¾Yô÷âÙÕOÞd½‰ ¬K¨ x±sAìÁ#©,TÇèN†©±ÌÂNznÎ#¡½õ ¢gFãíàêŸË2€Ìsôì >ƒó·si8):Ó±¬Ê'¡ùOúZ|š®ç]Ý1DDUŸ*Õµ$A\š`ã¦tÈ6Û±Fq3€Ü â+ ›÷¤%•‰LŒRŠ™± §¬ÚwãJÒco¹ðÖèjJ*ÿFoÝî0d &!<þpm¶DʺËXæé‰ìhÜ’¹8ÉÔ~ÿ%(o¤‰(D‹ƒ2 v'y/œ`š¸Š(»±Â ÈFxD f'ÆCø‘='ð$ðy}F3µ!QÅXV”ý@›o]¾lÊ# CÃ2ƒÈ'‘­A h„äëŸ5;4­1ú„ÒºaC‹aa. 2¹cp)ÌÈWàÙŠÈÁ/ª"ȲI¤âsãÒ¡‚æ"ˆ@Š TZõøq-Š'¤.!I ؗȲ kAHg[Ÿ»[FFð7«åÊCÌÉìd¢¤*ú ?E„B º²´¸¦xrTÜbNH¨˜]†OòܾoÑ`#mg·.Q"(ÉTERË$ 0¨Â@R­’¶bÓàÅX‰"ˆ@€0ŒXq1±¤ê¦ÊN a›lz ˜ÒÒÓn¬nY#r¢HÖ”[6¾‡æô¯ÃýÿYí9Ÿ§ÜÎÃÿ?»õßÙ~7Ô¾=÷D3}<&{W>SÒÈ€/Œc¸ÈÉ £!ˆ’Á¼ ðÌDXEF·ùsé¿ågûKe Mn`¹¢Š§`<·š»!«ÓxYÒþÆ_ÅïMÌŒˆ˜èñ4†Céô¹öö ÒÆ‹Š4õÝrçÑî›;•¦XUÏñ0°èWÊø»='b̾m>õž¾œi¯ 0àU+TO&IG5–Èbµ™$a©óé$‡$}Ô÷&øä§˜§¡é鲤˜ã”²&6ûâàÔfð,“nkF­2˜ÀHÙ¨¨ÅVÙU™UpŠR0Ž"xæ±Â²½Ѱ]C|3:T]…“:ˆ Z‚À?ehjKšž “ xµ¤À²ŠdÌ9ê@ý¾r’)¯@„°_×&Û!óévÜtâM’:2e<”×4†e.T ºUêÄÉ‘‚ Ù¡ÊB\$>Ÿõ Ä(!ÌÀ‚ÌýFë%™%\º£|7’Äc{rìŸ}Ô¬hÂ@VGš‹ ôcV•ñrû±–ÙlF+%Jºùp2 }¸oµš™¨ò³¡:›|t†Qb GƒÖè!m¿5¹«æ}/ÕÝÛÜM~ãòö,t»XŸ{?bŠ÷'èüÌß5_ãéaFò.éŠXf{䵺ÂÖñéß<•“…†äîÑ¿#«Î•¬%´ö¦gâ.HM¿™Ô'T†$ôòçÿí´ô—£"¢Dd|hT`éƒhÚQIik­6Ê_¸ˆ€ËÛÓ„X¼Ðw»¨ë±¬‰ÉahÙH´F)4Äj-¢š® åï·M/ƒ"E†Ô@\×=F+‡cèeÆY—#šñˆÓ¡¬;·!Oè6¹Ô2j@C¤ç¿K÷ÿ/ü¿ËýÜoï~Wùÿ#&¦™BoÚ…—PÃâã¦=gY±?VRfF¢„ €Fíé±1Ø’$J,-ñþûâlw·‡6§ëàíÖ›m—´g"‚èÚ3Hˆ3,Êi-¾’&lBXÑ„±b–ÓBoúþ${ð_#¹>åhvaû¹F PhTÑéÀÆÀØ£éÕ¢¬Új¤*ìK4jñªi Âp&Be•-c~!BË<õH¤–¸ÎŠÝÌ2í"4,~Çþ¿OëJÇñÌŽ•-®8ãÕ9¸]HªQPÒBüöÜG¿¦Ì}C;*KÒ’ccDŸ•ß!YHò¾•ÙÇ•|EÖ¬ "û‘3À³:Zæfn(†Ø’°Bè¨Vz,º½/óà ṗï$œ‹_\ðH"!%Ŧ~OôÔµJ®ëŸÑ¼žÙ¦>·ùaù‘šÄ*¦5h 4I"‹Îs)F›Mš4vÿ©@Ç$’QqÊÙ¯»«ú·ˆ€v™ôïÉâ:Ð¢Š¼ÉöR*ÞÕÉøÿò7ÐýµNëaÅ·žÞhnZQO†ëUq}Ãò«1„ ¡bÍÑ<­HJD–Ô±l_¤êdjYeJ°¯,#Cð:*ËB1b€ÿžm’Ê`HB,"Å6ïüÚÞòï9S¤›á wvûJQÓ¼pÁæ=ñÿ³ÿ¿÷¿wü/åÿñúØ‚»Ï³hô¤åÞšóÐ^9÷zÜOk-"@$Æ› ÚÆSr !8 Æ0`PwªcªŽzËúXvÆ/‹/Ø#jHŠÍ'&eÿ¯Ó¨š“_ÕgnígèyÝ]Yv#c‹5ˆÉàPA‹=HvZÏÙ^)CÄIŒ*¢ @–¤öWÅ%uÔÖm¥ EMŸKf÷)Ú×’h†Ù¯öjùÐñÆ]è“I+A‚BqRÏéz“Ê¡{!È—6äõrt+_·—ޤyèKi\ms+ÓïamT¦Þ -hâÙº³‹’ó´àF¡î>g«ûÏÊ0ò˜§úçƒRüÄ5ôoct#® í$œwÿRÈ€Þ(¢–‡BÎŽ«Õûúüçó{ÄGSóûrxG)"À¹‰Ôwø†äù=$LA©xñH2.ÄÒ"02'õ÷£^Ô²n„õK EçHÍ÷bs7–o©ËydŽZ—á¾W¬O¢¤±×Å'‡”ñoëæ@{£‹?}Šf#¤>úG åÚ «E%êô´£¬¢¨ëcà 1Z…+Ù&™ËÜÔ!WHÊrü4VUM'SK¶ÿ…:š[ & I‚Pià€©2Ž Ä&!àC€ÉQ%›>çëLz†’eSjÇ?ÃãhnÛÔ“hÀPœŒø]’bo³~Gyf„̪‰—1=?ëœýÍ•gñ‡Q)?y=’ÏÙ}ñß fÃa t|«geúp|’ÖŸÝ„UƒÊ3rY#¢¾wí1ïÉÑÃJsg+èRœ“¨òw×]EêSÇÖteSÐóƒîßíªÚ;ÌHÕXñnµ/zÔ­4®]4Y]…óÀ½Z2ˆI‰vP×øàŸ  üß­,Ô¹P/Ôl¯–¸Ø*­j±›d~ÑÞkû¾CCØÄ$R#!ÒcÉ~J …Q‡ëîùú}JkÏ¿Û!¡«€Œ¸„/Ç3zŠƒ¸lþT¼lÖý Ýü^Êf|!¼J ÷ó0§QbasÀC0"Ã^íªÌ°X@ ƒx€3 g³‘ªø 4 ù7e@ÐÊr`¢ˆr€Tà‡0èH @¨Ï7€³8u¯îIt©{S—IM[÷‰á@ùö;ý÷ú=)#àɉæ~‹x“ÛÀ(ˆ††¯L4Žt¦ù<¥ðY/ü‘èfÐëÄÿ#j`üæ³ùfjÒlX5ÿ§]£6«âŠâtê÷_žØÄ‹$J¡>y™-²ÛP$2 1—!µö#ÏÞvÀ-Ÿæ²„y]p~^<­¶g½ÿ?G§ÄxÎ?z?óÃ7ɤ>Ø<<ž—ˆÁA]Ëõmþ²Ì¹3ôP·Ø~Üì_*o&¿Ì®°ÌS.®¶Ê÷ߘ@xRJN'ܰÒ%ˆnîy&¿^r¥”´µp)îfw'1q ÍÉÖæ©ÌiÐÀzܽ!"G¯m(ÂÅcd©sI/Ê©duWÝ7¸Âèt00N^ù\dË­<{Ó`gµ‚×Ó½lÂû4ŸÊ$!¥žs•þ‰»>å`Îmµùr›ûƒ]uMkÒ €„*š+,¼ ž!Þo £úÃÆVÙCvÀB ö ñã+péµ©ÅøÎŸÈ~»äµx'Sï½9í\‚ø‹O¡GþáL|÷=ix Y>üsŸä…äƒ «üvãôI•Ê7S·¦žâw¹`f{¬¡;µŠ>”^éÇA©´mJfÅ“¿çáRRvø¡ ð§ùGj²O±—‡váÒc¢ø«>—öí~qlêUŠ0Û÷@@ åw¾VUáqí키@ëcë·ÌgOïôßÒ®¥ÁG$?t« ÙOe ^‰éO8ÛOŒ#º…·t•¥6ýf²j‹wÁ­1»ˆguÕK˜pâôt.òÚ¶*þÛ‰}²¼— %÷f¢â½’í«Ð„væXýÓ4Aʶ;‚²h… ׽ݷ¸ßù¢ s£)¾ì74v|‚¿g§tjÁðW9ÛC —}üÙ­VÓ rnËIqçëäÕµËеï>Ʌȧ^HøÐ¸ ²ÕyáÌ:Wv @Êß|xL¡lûÒ³R)qÁ#ÿIü£ßš+¯ÜDªøã_Ȱ6JR eî¹çÑ—ñîÕx°uWðj¼n&žöå[e¶è÷‰Þ›g'yh½»”M3î—ÆEÄö¿ˆÏƒët;C2XÓWRsjN›“¨F ü®d›DpQÛayT Qr[-8¹Û¡Iz¾_kì”}öy{jº–©$û•¤¿saÃZ¡ÌóîùžC ë#1ö—ÔHô£°¨ŒŸ/¨ÁÃþuå’1~!ŸZö̇ù›>ºðnO¾ä=狳X„ Vª&Û¨É{õ ÓúµïD”¼sÛ§¯®Ü´±*¹ïSêðS㽦m«Í¥}ó¬k¾…¤’ ›ŸËébK!ˆ[ÏD^%gÁ:½íÙ‡MC›jeÕv{Y÷ë;ÐêÃØS¯²Æ¼^Ô ‡›xà´¸µqzýö¥Q ÿʼn%ó,ò2¼×Kô½¦Y«Wõ¯m€rºQÂ¥pµñ+òav+ùæO6º<æ½Y-ѶîV_»Cͨ&TB¾D¸6¬ÿ‘{©ß’–Êí¸~6z Ø¿_sžÛèøaL'?]ø¨ë®ñÒðZ°$@„ˆžò3ÿE@½5Ȧ+ÉøÕ^Mb– vÙͦ?ªäjÉ•ó£S©?ò ³Þùù´®°zÿŽ•êô&jGÞû˜ Bon¸;ö˜á4Ìõ”ú©ÉN·`g>ÏÃÃE¿ÆãWï¶C–C—K+ÓÇa¤n`µE”–ö|Ø/Ë.Îߨ×rµ.Ö Í~kùúö&ÜMˆ»v¯GIv‰Ï§êúá@w|1ôSÞ²”·‘ ˜¥Ózµÿ£©£iš!—:{N*Çeâg@…ºf_I¯Ã¸˜ŒO©¬®ÊÞRsöžK¾ clò·“¨sw´sèžö%®œ?¿ ô^dܶÌõÒՉ鑒zTÜ=­ñ}.D7µfè;‡éG©W†ù”vL[…ø´ „Øžï}3Û};›ÄŸõš*Þçý!•ÂOóý`Ú‚î_;¬yuNÉ¦Ò ¦dµÝcyf·,? M¯™Ï;oÜñK_[‘DäÒ…´e–ÊH•â™+žuVùQ[ž-´»äU7·ýw!¾¡ñ2TÞ~±»Þ¿·Ã@»D¶œªóN¦qÝæTãL^ Ø)â¾{üvSs%ú [•ݬ¹AáFMïš&zº Ó´”.±móHXGT99ÿ(Ó9tÖ»ïn‡¢åèð<à*ÎÚñ" V)ù1ìRž®§ùfœ½w”u@diQ—õøa%ˆ>VÉŒ04Žw›É›Ú.OøW`aª.k—Ïœk Sx7?³Èº,.“}úº_ÑÆŽó³môbœKÚO¡cd´GµîbÉmsØR÷ußô¾©#í{žñ¦ò†)QAGYd·ð··ß×v¹ÿAazR-'¨dÛx1öŸï•+ì¯{ºSÓ–Óí=Ýy- ½Ý÷3é%»Wjiâ]­Çg¼ëc\üÕueÝ™ ß>×PÊ[Ç'û"û1©VvÉc2LKÞj#wäèO;»†{¢œHí-ïU$f&§x± M­ú¦Î>·ÇPëWôGæÀ«ÆÐ¿daq•#3Ÿ:;ÕB}•¯Š…KCkv¦/OG“èsEUqóˆ~Úì;Ôaµ}'i÷>¥þBé=ÚžírÖÊDæ Ë°}}mÁÒò™Âò;s-9ä+&©Ç•ká@­A×6ݦ²¢yg];:‰Ú¶¦†#°E(Íû>±F¾Ù3ÂH$;Ödù!¬ëëb¦¶y§?s‘˜v ¿+üP9p¿€N'âCánú%:EÓ@dsDqk£•Èðí.­+ü >Õ?î™À€Ò¡Œsó~ûr 7 |[x¶fæÍdbQé¹–r½™þýë쉴zãEŒc0᲌ÝxoJ~UK\¿†DˆÅNj‰Y–Òë^é[›Ø"™ð@ \®ãÂr°Q ŠíÿSs¯J„Ø­ú¨úûO‰®æb?Å2ÒXŸW’åãhÖÆæþp¤o”nn\r½žþ†+¡CV” §‡ý÷e}p¸h—Wþ¥á]çnÒÞC‰á¸ÉbÖYÚG/B…w¼¹1¯/Y°©!—ÙÀÿ v\Ј¨’–Xüð£ÑØ×Qó{bÍÎ_ðNkï—Õ¶È?Û¥•ñ…]›®7‚ÐI¬r¿]ó^—¸’y%ѬÐùíy}th·wögÆÃ\n®ŒÊ ¿®Ã:þRQ:©ÓD-¹L«PŠ'ç oŒNö¯N}Hïâý`ân;ôÄ>O3„¾â0õ é]©ðZËÓ:]hÑürQÊêQp»sÓ|ÇF<' 9M/c·ñ ßê†ýöE Æ®tô¤G3§`BLj XïMß|áŸÒu¿Nmƒ3;ŸtÚÊ«ÆñŒº•iÓ2îÓÝóx48o¡>ú¸. g¸À½ë~l‘\ÁojU½•ÏFHøäéág°5E—1ã1ú(—k,ÑAoÿ&j¯³…a°ß¸‰4Ì­û$ÆþÜxR³«¶ª^7×.œúJ÷#¿Î×W”OŠóx—¹õ+ ï4c^¢g{›Ó¥âõ‹í›2QõæôÒI]4sH>gÁ›Eú©ªzZ1u}×›{Ž•TŲĺcg>îÙ‹Önóbs:Uê—ÛJŸ`Ôš¼V7uÄ€A¶ˆu¥‘va5š‡§ñ~Ä öÁÌW†Äzèj±×(|¿JÈÏ_¶ûøåÄèÌœF-O®|§"}ýߪÆbšEyÔ’ÊÎe$~gŠVºcRïxK>ì[›Âçç)Â÷{Ζ»;ŽñÌY85#߯©%ÇmOÌçÒ­øqyŸÎ/Šî22µ–mc߸†qPÛh$Duß8Ë›ù:_긲$6{¬Ç%ã¶h½•ŠÅ†cf yâCkgŽYv™y×± ÅrOê}¿‹{±ìH~{:sºÚœh³’ò*óÝã“fºæÑ®“šHëÀ¼ÙDQ#œÇa‡¶¨óI¯k±òñÌ·3ºïœŠsº?aKÿœŒêÞZ‰Õy—¯çmL}ÍI×´˜b½í%²É>÷˜ÉŠñ‘ˆÝlìžÔ|¤¦©liNÁŠ‹Áçµ™ÄüÜÚˆÝxžUÉu9–yà!¡+¯Åu»„õ§Ëåë켫J?ÍýrBm]¯„s›«?COªÛà¡)á•:÷´ð˘‘" Nø>R™æžï(‘¾ÔQg—G{SßÖLJÉAîÆ2ÄàDÎýY)jÇ‘¡§â_4«ËßðH¸ã!ÑÎ|:>UgµF Ügš ô–ÚŽ! Í‚oçœ1®:Ý´Ÿ=ˆ¶‘˜yÌÀÞ'ÇpýxÞŒ(¸Fé¼­/û³¼Xßüä{¸ÚÙ òúŸã7ªWóó2-ý†_MNÊüQo9ÀhIn½;A3KÖ”ÍÉíø<>ŸåjälYñ\ಠΥVû|·€ng/΋´!‘5z5—جáRÓæ†Šp©5yŽcµ‘Î¥ â£Ìùƒ@4S}¬×hä^/”–ãЕuðºiûmýÔæQœÓ Wòü¢}Î@þë©ïQ` Aóxÿº÷ø|MÁ£îîCík@n˜]½ˆBH˜ýÑÇÈ,ìvï’ž«)4úéJ·Y×O6]Ä:¿¾bZ•uŠ0½Gýèõ'7_¡‘è‰_*¥Ry×líØihêíVÕ~¤« 9ëÞ™]„4gfÎ?UbÑê¿ìtÂÄÝy;Ü>fÆàÚ“Õžþ} ¤añv”ý\$­V.Pu(óà9Ø¥÷?9$Ìꎇ |ÿé1æÜJ”3ší¥sxú…ºJ ÂÆQì×Údç”õýÚ3a§]ÞõwL8íX×J}y~‚t?M–ÃæötɧvI¾»é¤z|è‡Cý܆GÅKsåè±åCåÀ8ðífb$!õÛZ²û²›MJÓÀ@c=pXm×±{jÜ툃weßZ§ƒ’Ö*4^÷1^ì?ΊsºzÔõöòŸ‰p†©ºõ/ÀþÖV 8yZIYÞm3ÄLðßþ]·ù޾_&þË[Ko‘²êÉM[e­öí·ñ©3 ³¼ýKÏ#-\ÕÔ2Í"Ê?C\åå¡bUv?&C­‡cõ+í*ϯ1x½Ù_¤„‡ømåše#o31žù;u)¼)»?÷%òÔÂjåËúWbS¶ïí?K‹QGW@ËóÍs¥{'_è(•ý,3ô½ÎêÁk_WÉÙ—¼±-}‘N¨ ±˜îáÈöØN^~s£]ùÔ«n×5éjD½:÷qlÊqͧózß3õÊ Ò'•§Ò×̵¯»QÄ™ùa4:¤PßÍ}°72=~ôñ>ÓW âñaDÀBÝ4Ù|©…lûýã¡@ëù·Û‚hCƒàH'‡û×,ĦYüã T®²dSñ‰ïa)‰*}Ì™œ‰dZéªÚŽÕ!¬ÓòÊÛg’¨ÝsóQÚ¤kw¿üq¼î÷HÄyÚ>üØüxTÄ=bqô2UýU…°ž3«i4§°æ*nã›-õzŵ9¥ÿïºÕ#Õ¬¯à½»AV/ÒGÚh>6¼Þ·ÍË6.:[6|•›¿Ÿc ç»Ôó­jùMz¹š—˜<߇>ëï¼BÃ8ìã!Ué×xQZ&šûþŒ›ffŠJWÛ­-Hî*rÿ["»¾¬âs÷¼­Šmû­Q¨ðh H»á|8…ÿ£-e¿âoz]E²ý®¤“¸ÎõKp¼gÊeª¶ºö|¾Qßy*ˆÖ§¾º“„x;k?XÁiu¨°/½ë´Â+_(U8¡m“Q=øsrà«î¦¹‚>Ã/+2 ÊìÐÆ¥¨{^&–³*çûb—†Àò>‘S¹ˆ÷ký «#þ°ÙvuÑOæž)gÝ>ȲTLžçËàÏת·‡¼åì±|ýxƒ//Xç—ò„èÀâãîøå‹^6Âpr¼t [Þiv*ô¦í¤xµu:Ñåìjí`aÙÎ\¤”ŸN­¨½Ù³Y!Ò©«*ÍäÂW `‰rîÜ=ÄÇ#dWnaÏBiÞp3ÙÒÿ“±Î<8¤_… }‡ü}¥ô¥@22,¦Èœä˜5\´n"ˆ\ýÒ†ŒñhëO)ö¤äP·Ân÷üñi»'‡û^V"}ò Mÿ£Ð‘â˜ÓÉçTè(B¬Iè(ôÍ‹¶Zç•Èz”âù3Ieïm­òøí9Ü-Œ\Vî é÷+5©•—•͎ݾìlåÚ[Ô1oÖïù«Ð÷g—“åÑ!ï•΂ÃÕø:óa©êÖJ¯ZhûïûuÕÞßw Ç÷:sÆ'8v†¸N;ûñÝß47•êí¾4B?Ý\£qødê­®t—Ÿ<òÍ'RÞIÿtÕŒÁªåŽâ‹À6[ÿœhg4¼ÙÄLÄ_¬F(‘¥Üdðg ,ŒúW§eA ˆ–dIR€ ûrf‰ípw°æ¼É~;J®}¯³ÿl ÏUßÍŸ÷<©|#zÁ‡“ϱúIèWŸû¿œæ8ú …Èw#.ªî.°¼¾ä‰®/õ ,ÅÊU›aïË^%÷EgI}ÊeÒ@KdÓøÿ)W«3xv»wdåLÞf|Ê&4uˆç’s¾n¶¦ñžþGáÀ[šæ9 “Y6~Æ/gvß](fŸ—ö)k{b‘¼ê<¯0•’õ,ùg=ð÷Ûd£ú‚UjCAåP ~°Ùé¸Çöò  X¹îɳûŒ5Îu—åô“td]úóåYiµ©Ü5å¬hÿn©Féù‹—Òz{QÀoê–;áì\èZ§Jõ>ÊO,Òg7 p>­3C½ãƒÏ2>ý¶!ÿºÞuìƒ~á5ëÏßc®Ÿ´ø±p¸‘Ëê†ßGž­U»›m‹+ΈLFãÖ÷ÁnÓ”K«*™ŸQµçÓQÙ€@•ìÛZlYœàî »Mõ'3»®ô,¬6åVÏË&FòpçQ·ãYGYïPÙo]ü'›*ê;[9YÇ©f6ê) bÇœýúggþ¯—¾ö¦äÖ³/[Ç/è,IÖÈgáð8gŽÎS™»<˧‰È–‰ðFy+Îíás8¶>gÖèÿFúFú 6ã4Û–}²¼ò=™HƱª@^[°n·È=¶Õ5¼ 2Ê3Õæ{ Z’sª±â•gåG ˜ÔÇZu½.&t÷¯/Õ»ÏÇ×ùã¥$Ïï½QnÇ÷ÐÙiÝá xËû×:%*ÝfjXæû0THß'#´“Á(›RQ6:ÙšöPú[w®Øé­ØZåí\½’6ïÔ´L²ÛÓÃ-&þ„ôW&»µâê%ÓPt7 ýt–T\ÔôºÉªÃå´‘äDEŽæÆ³uÐùüî1ôŠOö‚Ô w€H¶—?Ü„Ÿ7ÿ‚ËÂdH¾zv@ôù‹PýÊ!4P¿¸ùúmÄíÐéEáÌúâ¡ê&•Û½"÷¯Ûæ1ð¬Þ?p]OÕžþκ/÷Œe2é×äÌ•òz ìÞ˜‘í0ýP^Îj)Na»V©½$äa]ƹ¬¢öûuÍ8Ôò|6Þ¡–1Ñçn2zÊ•¶”?„ˆÍæG[£FzÌq ‹SMÆmÚZ^{z½H—Sý§ì3Û­æ9±‹YÐòÉi ×¾/Â9F…¦®øáì¨qŠeñ:ÏþÙ¾"°uÙVgîQ“ÿ>D˜è{H’$ä½~ì9#þÛ~4¬-ûÇÁêUV›fšŸÑgY*“‰Åÿ´®~Ñq(½®&î—ßé5=fF÷£º˜UTä#¬®µ<9².ß'^.ÓÇýîÄ?îÖ/ðá'QÚ˜ÚØ>…}÷Ë›ûý{â7þÎô4߬=d'x×;$˜}—í¢nû§*oØTi‡‚’{íZK3!Ôu heÿ¾ ¥H#îD[E åÇÏ€(mðýH€„(Ù¤˜‘î=lJ™h¯_ÐæÌœB³Öª@~™+,?Vÿ¦ç§~5÷k“ux€uç  Ut­þ÷÷‘ãå.%À“;Wà”…‚þu÷Ùovxœ_%êyÂdU7oû;µ¢eq•¾šêY´éVxê9Èôiüõúèø¤ÿ×'G!#‰¿ì<)|gò â'xÚª†ÛÏó!ÄÇ2}*ÆwÌ›Àê§­TÞ2o§˜T6Úù^ã ÞgjÓºÅ>É=êûÝ^Ôp¦õ›ÂJôû{jC’Ï#Ö¾ï'ÚãÉAnxеßÝg*¾ÙüïÔž®o¶3ò¸ YGÌP§§@km™JÕp÷àS‰¡Uù¸Ô þ¢•úñÜ?}œoÕ9Ÿžše/öàõ[°íË`ÚâŸú¦¾?™®ôfíF9Þ·«ëª±‡c\–ÚÛq€ÝŸ…„˜J¯(Å üÓpEÇËO…Håûßnù6Þ žá;¹»ð1hr5ûszxÔeôÛÌãÞlÅE§#Î^ ¯b‰#×ðn"šRʳJ‘οEPÛœºàSP½ šâ¿¤šxrM; hÇ=Ãò¦¦¢øY@<¡—UÕÎQÙ/,×ÿsÔp(¦ðp0:;ôW)ö+µÔáëai)ÜnaûÜ”‹7¿¡ÔìÛòó|û7“Øø§Ïg‹È€Â\ÛêÇÉÇò^ÚS`µÛói£M%¡"×b’él^Z’·d]~à:‘4øÛkgc“® ËU.®j£ª|Ö%ÇG.Ös£ÕúûádÖ?œœÊ¥Z6ÁÊ[o9ßKýÙ‰šÔÂækœMºNÃ÷jVóõóˆòy´aMw~<ê¿>÷ý”9¼¥×ÕWóþ6 9AqØÂ#ÂÛÏÆòÂs¬¥BSˆ•_¦Jl~ô‚5LdaVI|1ƒTá%>çúÅt=£Û}¤y¡DyÅ”…ùþ÷t †ÿl]®ðžê{¢@ýí‘}Óî$0¹´ÄÊÚÒÚaC@%û¦‘ªîd;zx9³3ÚÄØ³»Ñ’:Pø>Çé¯%¶AÀo{¤µÊºOö})ncÍÏu­LÑY=ú™Y—Œkˈ]Áøà.>n”T/zË–î;M|u$]g%ˆD¦ø^ﮄ¢¢‰ ^žmn(X#ÍY1¯û:¿‰#z&žD`u©:¼Þö_Rÿ?—ûòÛ²/lý/”ŽïbÀhd;èvütþdšš÷¶nDõ>êç„yí¢Ï9Ƽž¹eNj¯±ÔÅÌëh]Rb–¨¡ÝIÕ»¹8åĬø;6*½‰úîWŪ-=uOÏ>q̨9܇jßœ¹?'¥?1ÉìнÏ:™4û»§.© 远¶´:’³oç9nÊåa$ê¶Ra¬uÏYŸzVÛNä2Á×bC»êéyÊL»Ex'°^:™ç^^ÉÀ1×}ƒºó”Ñ…Æl´«ìá|æ&ÕÚò10ñ‰ùŽÕ@ >HæÏ-!—ÍCægCš· gíé3¦œìªÊÇ>¶kíïgÁfÿ‘˜vuˆÀ8äý$’N€:\ô»z™¬ôÏžá3¥êªìÊWluš"®5÷Ù“ò­òvîÚ™-zWQ]®T_'ùÄ€8B7÷UÒ+£#RtÅc¿g ìåv„Y©e˜¸J_i“½„Âã†-Ÿ ïèoq¡Ö.\>T{Ô#À82•Å{UÍÝn¨rÕºRû§%^`7„ïÁf¦º"A6áwi%]¹ }‹–Üž#A…$3úD‡×iàB¦Pâú1v´X³ÑbZNðâÍ(pt Ï*yÿÍçO„Ì0yj±GÙp'ÄÆt0h~ cþ¹“(/è¯!·\€{`¥-«Þ{>Þê›cÐ;ŒÃ½å褥(¡ë‹;ÏiÚ€ žØrºà€Û×¾7߉Qî{Ç é>Ÿp ñÀª’’n;ï>vðŒ÷±sßppXÃl¼îéòõ;ß=îw™ï7z<œ™4ìÔ®Øä´){Ð`@㻼>úæwÝÉóÚ3;9)ç¹uÐ’éóßrøÅ ÷rï}ÎÃÆÂöh‡@ñÀ7Tß^_}ßd¯{¸*€yo6_yï–ö§}ÒAA÷±×k½ß}ν¡×B€Sï}óÍñ¤ =j>÷×ÙçÀ ‰Ð>yïméP >†•D¯Ÿ}@7¾pûŸwT1%÷¨ÄÕ(ªˆGb½°Ò²¨è±Ò%@tÀfÒQ("€€g"20ÌÕ&Üæµ2±Ø(ÖwwYvçJ»†\À+FlÈ HÐë¦v¹8UÛtR]ƒJO!m0´û»Ýuˆ÷·yÞO§Ëî|½wÀs—¾²7ÔRÞ«UÌãZ´ FÚI¦ã3¾Ÿw¾è{ë¾ûšªžsÝçZúå«,”ë:××”q½Ø6ͶSæï™#ë 0á±òtöz[ÝR²Ì¥¯^NóMsÓ{×»¸Zú΀´Ý][6†¥ÌáØZ“[tëVš4i™¶Ö¡»4”2³ZÞuh»[¥²Ð³[mŠm3'·Ç|í|Ê)[&Mkìj趆©¦[5T(UÝß[Õ¶ÖÊÓ3A:7ce½zûìú[C Q¥õVtög«d•¦µ•¶ÊÆ•½ö¾xØlÓZ+bµ®X>j„±b¥Tß^{ãKk|m¼í¶µèÚײ¨:à˹…}ï“îú6–¶hô}íÔR}¥[¸/¶ûaÕÛ®ÞêÖ}@orT¨ûŸuS}óO^€è.v°ùíïl*XÝ÷Žöà"„ €™0M0À&LŒ˜L&CM‚`M2i¦4ÄMO&€Ó £F!¨4Ð „ÀM41)‰Šzi©é¡éSÅ<žšh6L?@£õOQé²&Sõ3R~¤<‚m¤ž˜Õ?)Šh4dÒÕ4zMêµ£Å?Ji¦ha’  &‰$ò&˜jy ‰‘§¤Èi‘¦M ™4Ñ“FŒ£Mh£ 4ÔÐ@4hh 4’@€@˜L¦O@&š4dÕ3ɤô?SiFÔýSÔÚУÅ•ªMG´ÔÒdmOMCÔÓõM4z£Ò“ÔÓÔf¦€òézÔdJ!@@˜š L`4É£&3@Ldddi‘‰¦ ‰‰3FM2jzb4hÐ?J~#ML¨@ˆ†€4S=FD§êŸé¤õOÔѧ¥OSôÚR©½Aê“óT˜ôÒ‡éª{T0 äž§§¨õLM“Õ=O(ÆšŸ©F“i iˆz5=#Ð CC@ÄõA0÷¥´?ýº7ô?H5ÙB/«ÞB×FgÕ‘³8UåœÚa¹t¤àÄ·ÃyûÕü–-Öf >/Ó{½kUàh×XÈ‹Gñw…ÈI5ã¼B`h(á…a@A†UÓ§%c ƒþï$Ì¿’@Ù„‡æ’I””7͇fˆ¯í‰‰‹Æ¥f"¡VÚÅh£m–©RÕ…àÓËijª­VÖ*¶¥ŠÄ(ŠŒTX"îì…b¨1¬…]ÑøáýÏÀOï]Ðþ³'¼šCPCÔDÿˆòýS¨™z¸I$Žp€zCÃö¶6ïãºíí¿ÜR’õŠ Â†yÍéô}fÐöÞwÕq¿3&g¡ôgŽÉØzm†È)ýpQfód{Ýf®u®¹ãGÝ j)™¸à7ߢWDø³‘z:>Åb> !TtŒå‚ˆŒc™I_œë÷H“ Ì©)Óö½_/–M«ôº´‘ ÿF©5$F¢“¯Máx“HJ…v›ºZ‚9K£+8Å#Ÿ!:”f‹±Àžž0 0Š(à !§z³5¤Øf%þ¹¬-¥ýU 1ÒBÆ9h×bÛ$6Õ¹”OÝ2i24M ‰ RÊ9fP«YnQf"å±`–˜ãR å£Š’-¹2Ù™TÆ\²,XÆÖŒ1˜2@ŒÌ˜ZR2°©<¬?Ž˜"}à Å}lAÄËÐ^N ˆpà ¾:/U1Å9ˆ›Iï`‡¦ˆwÐOV(þôEåEùPUn‡æÁÛ@O懾ƒëȧ‹úu4}Ç3íy "ZaŸÐÐþüt@O•ØQ=œ½½ËW‡ý|…GëA@}Œ¢<(od"§ù”æ¿*™` ô½Ü=åw›k"úCÿÅ;4™¹zæ5'/0ÝíŠ̘.Û;‘K[ ²ïD¼‰ƒªÖ¯6ÜL0Í0ã´°îYŠÕ¶l\—k½²ñdÉ»”°´0\ܼ™¸4Ïüzp~ÿùÆ+ö/ëÿ}©í#»Æ›š´rógéÎviÎÆõ!;èur¤ˆy‰›’=€OTôú®½æ\v”5n.æ8n;Ë*Ãİ ±›Ìj}kÚd¼SÆž@–PZ¦­qæ5 š$ĸ‹zŠH·r‚ ©Z¸Ù$ 5Q£Kð!(^PÞ÷ž Dug€îeœ£ºí3·xÕ¸b“uæä34[¬Ë¹šZ©Œé;{7F,³˜Ýá'##sq£¸ê'yjA¨èx2mŒÄ’rnhl‰f7v›Ý:pä±T¯ñþëàÃë~¿î ߇Pªìâ>…û½Ý|q®†øÇ_$‚V¡~ã\7¬*„y¸´‰#Ž>刌öô6cz1í©Iáÿïþ+é'9öt?%®õùÜ]Õ‡ òùÏg÷¬)½æ([É~_'K.øúŸ‡©ÄûÝ}ïú´zîŠÊÿg!¾Ékíy®\ªøè¹ÒÈÿÌÜÅü®ç>©üÔùâ@ü:Êz |Ô=w«Çì,òñÔ‚ ôÐöÔù4úç»Þj§Îêiì?'QîyŠÿg3?kº§’‡O­@ý?ÉO ªÕø6Ûo±jý˜yøÿDC©ö?“6ƒø¢çNס2èe0'vìú‡Gn<çCJ)ϯ[ù¢Üß¾…(â@ó{G". _ü‡—;Éf‡qÙl{}NÞò#ì¦wª œ´~¼óþëÈT£‹ñ g iI Á"œG²*ÂyààÆÅb÷‹÷æ˜ o”\ëa(3÷˜V+,s♌mY b  èùQ„* é‘`”1àñƒŽèÉËU(D¿=ü "øÜØ©ìô9†öVæ×ZYËÆ{òiøÒ§›Å€£}ó0Íp œµå!Ãþ'ÛŸÍI cðecqŽ¿§ª)ˆÓ($>ÅÉ?¾þ²ÔíbªEœÒøIÁkþÞ8¥Ä¾z8˜ðéß93ì‹ñDÖ3zj&Y]7ûÆî•?òø°ªíwÈd`¢†ðLÔ\Q0E ‡^¢± wÔ)wê•·ñQ z_åEûû{žŸƒÃö÷÷~]¼õ»Ý]þ9pŸp¿#À>XØG†Jy "òçaŒÃ4ë´¼>¶o±’ BŸƒXo„…ÔøàI‹è^:ynÐÌ_ò·¢9ÈBšß/ùÑøCп^ØrßÜèùÿ£è°o÷“V¿C¶"ȤŒˆÈ)þÞ¿È||ÏÑáaÿ;ÿ~Éb?댺زÊ禙ýg³ÒGæ¿÷F5šMBbRìø^0¢@DPë æ:C€ÅwžÌ÷ç,œõhí¹Ï34·Íe欴YüËú* ØJÚŒd:'Z›Eİ“z»Ã{óJ!@¨ŸÓ6wù"ººS—b”)KHŽ@^~Ö…©ÄÃqÁÒúŸ—犋 ?vó° NÔá.¥A?yÿâ‹ yt¬¾EÐãó¶D^ÉݺÌÏ¢ÐÝý Ønê?6|_z'«+ã%—Êòä(­ңïû N~Î`Œ(“1]ñÅÉ«0ä•kÆâû#*×ËN£){ô×Ë2éQˆ°|´¦èˆ‘àÓûa³ü&¹d£·¤€¶ŒZÁzЈ!/Ì×û”»ký€³†ÅéOøá0jÆQkî3] ?É™²œÀ)=µÍ×SB)O –Ù_P°ÌG¶âÃA* AW‘ƳzxÚ²·1}2Yz%q?‚õ,ÜD>ºß!üÞÙjWN)’Í”Šví”Oï“ëQ½ÞÈ2òÎaï{Œ‰„“P§VDϪUþý2¾p“;¬cvºÂ"þ,•*{¬¦‹&8(£tLá’P@[æý=®ÆPQox·´Ø'‘¨w¿RŽl?žÃD|ü¾˜º?înQO2go<>?ìú{zc´ôZlŸêÚpÎÕo,Lx­õû-˜¥Ø¹¡õüá ÝÚ1I EŠã,²¨ªE²ˆ¤´÷ˆ óè+}Üuw³¡ñý–ô?£ãw¾N:™70n¿†þíÞŽm5Dûö–Þ!êg¸®ÒÌßùÞdÑÅx¬x²CuA?îûॗѨ6h?®• ôl"=‘ò·¹åþ­‘”~þeÒÂÆ ®²õ¶N'ôúÀ€wæ]õNBÕAï@,²øúý$F–[«d¶& ÝîVY¿œÓágÔéè¿ðú®¨ÚŸYŽ>[¬­Í¿‘Î瞊÷å9´¯F}Gü¾yú78kỲë #¶¡¶åEºý“©0ü¾£·vÃÁöª¯Ò>`€<èn;¿……аùSQX7 %Þæùþ-´aDT` I±K‘VVH¢ˆÂ« [, >³ÞùFÁü—ËÕþZÂ<ª¬*eø)˜ÚCüj=ØõÃ|›ü«Ž±KqŸü®CKÛ~âãÆo`ÑßÞiÐÛ ðÜp¬-;ßèB-]ß1ZâTxFOÃåŽõ|cä·0æTXµj‚U¼¡~ 8»ëŽœs³¾íåÎqsΊ5'DDÍÊ’=‡~$‰šjÚXY"*Éö-^ü¥¹P•<#Ü“Xkz&>-®Ã ĤTŠÎs§çuik7;˜±5˜@TM…:“þ2ÛÊÞ…Ô W©ï¤ >¸~Eúy­Ÿpû›mæ½ÈÙToUA»þW/LŽï¦s‘`£†Ë!Xòuéd)O=®ïÝÇ^øŽ}®W?öÔÿß•lïïÜ‘ê÷:ú玎ÙFçá–uËjá|EƶŠKoÿY±³ÓÍN=`÷ØzasÊžØ|˜TYYø¯Ê вB -’ë× $i‰ â¨[VZ”@Íú öúþ[kÇœÛèÜ|ÄQÇPØü~¥cèøÔ’â +Æïhëo“ëá­æ¸D?¦ÛJ€æ¾Ž‚‰Ù¹0t<ʹ@?oOÏVeUQã©WP Ÿiør¬ƒ|ÕC•H¯«áåp¤Fö¸7;£ÈåG•wç¾èÇæ¯ ì› x$÷gšzþœžÊ`ì0e¹ô¤¹²ÉÅ»O&£±LV¥ ²'ÚÄ'Eõ÷}wy·­ffµ¯èó­»z>ö5­k€œ‚áDÒ•ù=ëTU>•NÔ¡ëì=‡{Ûïw‚Ôç[‹÷x°(H-?,Ì„§7·Ì{+î.+7jž7ÝY' ñ»XUM t‚P"쾿ƒÐÄ]ù¸ñæòj¿¯eîæ 7ÅêçhOnuðá¦hG—åaC #÷“xÿ$§½çZÇÊÿ¿" ÷H •(U’£Õ‘åG4ܪ0 "?NÐüÞpôëX~Åñy4n|” ý'_8ªÄªzYÓ¤z–®…‰}êÏTæG¿·mÑŒ‘DSØ}:ykéâµ5¥@mSºññ·ÍÁŸzïÕIxº¡CJUjô²¸æµÅ“·:LÀg.Î'šý3HåÈUSr~‚>H=i͹ØòåPk_Š”Öõ‹Ï& ‹ñiØT|aSÄØ”(ê2ÈçÒ~„+‰%)Á­~v‡É;Õê%g‚wow–V!:Œˆøp;¼¾“}>J-ÜW*‹•ñeY‰/ÁO3 P‡?¯øONkÜ_ë?ìÿoø?×Äü!êùŸ³/ù¢ûÿð¨õƒ×¿,(UúøÛ—gô²OCìþ·³ŽªUÞ}™æ²lklå‚ €YÊÛŲíÛ} pÞÁEüªœ„âéÐ5¦½ú¯ Eüò¶;6ÑZµeDz߯ õÇßó½>»„wýϻ۰ýþËéæþ¦~–3_ ¡ùZ|Ç'½å1êó»ã:Ùl”Ú(>okî?Äúý ò¼€¿ö÷­ÿNŠ3eØsø’ƒ¯]¡M9åÁÌ7Bù}Ãâ)öAíòª'Þ!Z~G¹)|.ä4ªu¬òa#¾G¦ÑW*yóŸÞñ·jýíc þ2n¯½-âÜ–žÇ£Ïü…·0€ qùNòz¯‰É»º´˜ Û£Eèõ9»ØhA/@ÆmðT×Ρ©Öˆíea¥¸Ù3õn-„Ò¿ÌÀ®}6+Dìu e‰›Zèciéϰö}zñ×_¡ŸX/YÖ-åçý/Gܧ•¯Ý©dAì)÷È@ðÚLé¼­ ë)Ÿ׃¾¯ 8YÉPéf†Ã«]˜`ã( 6QžÅw;ü«êÿŸ·;xWg§O—º•ê{Æÿ´µ¾ p”‚ðÌ`qÅS¶Û° lž•wˆ“®®—¨v‚¿ ¿—¶§åFKaSEA’Ÿô? ¹}j—~ê~Úû]• =î®uÇuJÇS>vCÉ̱N2#£¶ §BM“!aV9‘t°ÊH›{ô7ýi­ÕØêÌéˆÇìÛÛìåB}¦ ù”n_1W<½žxs7¸÷¥ØD/ôÞ^5JNÚⰿܳ¸ðõ¶©Ò—Í<0¨£ð[cÊG_þ½C7‚Èâgxc‰Ã4qOººËÑoœ6®¯ÆŽ—¡Ü.:oÿLÆêà¢ÿ/5ÞÝÿS\–iØëí<åþ»æÑزÿƒ„V¹.¬¹d7´¶­í)“Ùmôø}àk¹ƒÒW‹BXŒÖ)µz>ïÑñ”¡ß±€A Ë$™Å.“'FšÜ‘ò,³üéGÉß««j/§,µ+»Cȟ׷aü9έF­Ë=*f?É,®ñÉ]; oƒ£‡¼vNÕð3Á*kÞH÷2H°¸ ¬]­~8E èí ïx?unö¨`âKwâ}iF/m|~Ã+ç[úËQ£äóxá*IvÕ#O¤|Y …&¹‡ßT Yœåiê1”¯0UZð_sÄ&Z ¤Å}9/ ÎÌJ¦m/ªv#Æ… K½gÞ["”¥·ÈéfrO¶VN¨ñëzÊ%?«°9$Òê rµ_‡„íŽi} W&¤¤`k7d]HÖ¬aòX´É¼—úS½#4)ÒÑ€ GÂî‹ ñz.=Kÿ¡>%ôŒìý¿›èGÛÁfžÜ}ß[Ëo6Ü5cþ6²€5Îê¥Z”JªH\?øøÍ…÷>ïP–cä…ä7ä>,°æ©õ}~doû5=š3#ã|dž'Dܯ1ï:ð¹ì‘.¿³.PsÔrÓ~g3 ½Ï²Õ[ëV:r°’磟¼[¿Ö³<~³Ññ¯)»˜ž[óá1²hù~*`ÍògšÙ^¦{Ø„¾-¸ˆëè–¬Þxì_Ûú¹NëM‚êÃÕæµº=JøcÍífñ"Âý:£« wŠÅ75µàç\,¿}$NEæ2wtæÈ< Üìx?årä£×͸%K|¶”ú‰wq|’ú[Ô—(Z}û~-ñI`"ÏßzŒ÷VziÊ>L>Å÷Çärõ"ZƒÈÁ¿Nw°(aÉ=å=ÁöfïT%-Qú ûݾ¹¿[Ö÷æ–”a¤4qƒÄåñ tSýư©ù½·e¤,Y˜D~œÊÒ¢•‚Ãþ™7ù~´ùÙçÐÜyãÜ 9?#–C}CÃôËÍg+ß’ÒòŒÞÑÅEÎ ×ì­ë5Éùð…Rt´åÕ#•½æ¤^æÝ­›Û³î!Žþ­L3sON=ôþ±ÝÙZ;¾¸u$ŠëéÚ0ŸâuÙé‹VOR/mádhê¤=¯^?I©÷ŽóŽçü|‘Â"†gÆATÄ®ƒ/pJ^.þ˜fÊNýÖ«èó9«*Ò-s¼,®”OçúâcÓN›dò&âfìõtQˆˆð. {?SŒÀ¥ÂÜlÀ3Õ²3WçH+^9_ŽˆI{&çE%Áœ+ uúŇ8íÓZÐÍ;J…ï±õâ+¤›(&Xó«dõ~wŸŽÝ¬z=É÷#ñ´æ½Û9û½³ÕòN4m->ôMáÀajÃ]Ü(Í÷›N©Ëƒ|M¢ÜÝ{—8á¸Ò»öæà£d¤M¬òY„ñÚQuî]Ž%ýÚ£atŸe¹Ï‹Nnz8ç(jÂ!æï¤¯ºÍ@wmn3¤¸Hþ¢<”^‰Ä7{½¿Xzî‰û5 ‹ ¨eÂôÍ÷ŽìäxGi_z‡båKR2ÿñÉ‘¡|¼œÕá¸ÙhÏ_ ´ˆŠëì=ìo2¿úKîr—açÒ÷ ‰r _}‹IÁÃWÙB9­Ž©oÀÙx…ͤøÐ*•þ?”=Æ®‡3„TóÈNdZœØÊÅ~EÏwÄq'_Æá¥äÐÞžqFbc¬÷ÂJöòàPúž‚FEì±ð ‹C.:”߃•°ZA“ð5ïñC=‹;á/6ˆ³ëŽHéʬü!°ÇÓYÊg‰YâÎyß.¾ý½"ÇÍ­¯o³ñ¤íW"Ñ—yÝv¹wÍ‚í,ð‘ʳl/R¦EÔÊÓ®+ïQŒÊ›ÒÛÓþ8/)§¢‚1¡¢ÆV…B|3ô•aS×7dÌÞéö¤,w x´•Ûfth“Ä û W(µºWÀ¢‹.î/e-¯š8fP 0‘š;ĸ Ü.Üñ@|dï~˜´¾\ŠVÇã.Ü'ò>ŒWþ¹¡Åµ4Àñá~Z0} Á¹à–¡X–ijËKÌ1gæËá‹ýFc}‡XôGu%K *ˆÆÐŽ˜Ã#Ï—‘_÷O’ô®6:d~M±Ç¶4ÕB£.©ßÈ ;6›Üês •­<5$‡*ä©>qÌßY½­dÿ‰j³#$1¬š"àê¾L³ÿ6D®~襘$×LP;FsÙn¹ÃÙÝ+£Ûª0µÛÿrÌ«”¾®þžO“¡ª¢h×ñïú°~ùÝ¿»“.;ãŽP)cêÒè’$×Ú1ÏÔ¹~¼\{•wÅä5×8…tC¾Ã‘±r>\E|íÓ4•í٠ظ*¤ôv" ùIVMYRûG£rŒ tñ“¼0=ØÏ^™ù³JÍj˜5Cùë'šJå½1žØ.ÃOÅ—¶ÁñTEíwk6áê%kõtÎþˆw¢’$6YÖ(ñ½™¥r)/ÚcŸ?&ÝF&FíÓŠBG3f_¹uck†Cos>Í>ò‚%zw¿…æãg˜¤+¦“ rì~—Ÿ×/1ï›’<¬x|ée%§\_ü·¶þ-í<’œú^H°°|ÃU‰² 8º øÁ¯ Ì÷Л-áî"ý¤ûMÑüé—ÚÂö{U½®g-êÿäåÈ ñÙè>Úî¶7·–6Ù¥ú8•ieòÉ'‡Šqg<–]#Ÿ—°õíZß;%JŽ­~&v2JŸÆAÐ(VuA±…³©ujÄj¢‚(z»æ},ÉyÎêåœ/ÛTâÀ¯¡ì6|³Zñ#ŸÿKºôÞ^Ë,÷;‘È(åâPÖ0üTA›Ñ/n«e–²!}H«¢L¶ň¾ÿF$Ü]¦[ÌR§ü\Æ¡ú‘îó3Ö=µK–rE|S†tKàeUøvgR¶üÔjœ¢5³ˆÆìö<Ú xŸ·ÙÍ‘yµéü´pþÎ8*iV'¾L¹W™í"9ÿª¦¥QÈ4Xù¤—ˆ†"£„3Ý÷øèê¸<$È‚vE¤Pì×·ºL¢N×YA~o|(·,O(ö?8·‡c˜%Ì…ªÊÅL}SöUÿ”óQv¥¾ ó÷¼Wöq4n{XîñE@O倧ÀõôTOÔ‹éâ ¼?U¯¿÷^óæeß—_÷ÒóÞ¯âñl¾xâ…³uûßívž²R½µ.Ÿå½oœ­ÙoÜ[ …)nâÿ‡ŠV9þ¥÷K%qOoørý½Í-K†H¥â+ È`Ó?²´ŽÆ¥6u¶õì‹×ÿ®‡ÛÓ¤æéå<­~l»ÄqÝ ³ðÇíÞ½_ƒSª–Ý<ïšÓtB=I¨ˆG°ôbD„Jôá ¯ÅxfÜÚ)~M¡L…hí||Z•N:dK.§¶ÒCÔ˜‘ Ëî°s²}ŸV»i¥¶í½Ø€¶ˆ—Š oÉfgþfX™NæÉò¨´‰e3ê A#!6G¡¸Ò´Œ.÷ >î0&AFaaýJ÷q†jÁƒêK’Ä‘ƒÖÅÍúŸªûl¯@~ä{£3ÉGv0éêÆ½¹Ë¶ÿÀ¤Ü€¥©#£Ë:1‘릒#.–›ljeËm eSEH}^Û8MÓ‰éŸê_gï}Þo—޳IH«ÞÄÑÅ.¦é˜é†úÉ™&Ä2TM#ñPêuêÔßxÖÃ'0²(ÖÚáÂk4Ö’í$V³_‘´ÄF#f}å`jrËJÒi¢ËL²‹³«D1Î@²ËHŒRB¥ä|S÷áä,#(",ýý,ØÚX¡X>U±-­ U†˜‡`b1…cH¡2DUPI#IŠ{VTÅ l¶'¯×Ä„õÊ%™¶ H•d+| eH²ƒé½‘OÚÂF?bÙ@vð{¾¿þÏ_šöüߨ€òkÏ?.{6Ãê5ë@ûGvGb‚*©8¹Z¨€½Ú,˜` Í%Dˆ+ B‰æž1²E(ûæÛå ËìÖr¶…`˜­*êÇ‹0™T1˜ôÿŒ@‚Ö­›tÂDYe@)‚†ÄA1ÆLÉ"¶ü~Àç{É[”ÿ¯¸¿o“à÷öŽ ªÀuq+0'µoq²þG9MÝ´ p›€&m»k°ðù»z»K4é[5pS!Ç•? €ÿM;ÙõZy²޾=]GÃõ½ö•èÞ´@ ßÎS ¬S¸£ËúÄ*\z‡žü›Ìcªö_?‰îà{ƒ?‡°àíÓ»§ö¿ËßÔ~ÀïéÉ<°7×u½‰É<ˆ³õ ËŸýÞö§—ð9ü±úrŸRÊ<aÿiüõNœúW¹vô÷sÿ—>ÙÛÖªÉ=›öOëØ†¹Æëœoƒœc:‰Dw¯{­` PéŸiÇÁå ÷(©ª ÛÕ@šÜ‘ :Pë(ˆJL‹Âôñ<îSa} ôΩè7¡Ù*ŸèãtðïLÂå ŽjT¦è|^=ÐÑ s.Ƽ¹¥5éL!VÊëa49!º¯3{g ×ÊAsoº©g •0Ãæë’ß/Nž}²G£:Ð{KzkÛo¦0¸ðÉ‚®V¥«Jí˜ìë{Qêúa­$Oö<+D˽Þîoø>©ÕßÎsssssssý×GjH>• ‘ï´J–YE©JEmQ)ËP?( ÜwGi>WØ O @óƒûÔø]”¼¯ŽkáLNP¢‚,ˆ@ú÷ÐÇÍ)Pg`F$0¢ÅDÔ \´)JÆ&{¥ ¡`PT¦’QYúñåòx‡4]xXðpÌ0µÐÒutó®[â‰|¡ ENè??ÒÊ[¶Õ™€Oð^¼´¢Š¥T‚?ÞìBj…Zí•`³Òß@yÂöuñ!—è;ü<}™¸Û`Ê¥ Ä}ä-¼<Ê<âCJvïJ ûØdÔ w²©¡ÛlŽÛU¬C ä;µ‰@( VËsZ]«EÆüsõk}3·Ÿ:Bz}º=U9ìÅoC_Ùãx|6ËM½(Q³D 3ržÏ¨$ø¾|gIñY4âNW³²  ’WÖU«Û?~,Ôÿ¥ ¶ïl<üMÍì#àRÖNÅÃRÏAýUÔ z•¦®\5!—© â÷;´éìUÛ–ü óã²ÚŠX²ÒÛhHˆŒPQdY" PHˆ""¨ª0X¨‚HÈ‘‚Ä$ƒãÍŽïÍ^àO¢ ͇¬²1êgJ6ÂC|XnàAörw­z xE•20IX¬ª^W;KFárEªÌ‚û+Ê¢ ¾ª„°aBbØÑ‹¿£ˆ#“‘Á@.o(}×Íf{;i>3Û¿:€ãµ Mˆ 5@¾y/àð3øþ?êoïëñ}Ò1ç?Ì4û‡íñûP»dðéòGÏð郲ÑÑÝÂ1ü‚É.Ä¡>!xôº-”àÇ¿ç6f‹Ì+ƒõ=ö­ë(=¾ß©¶Ð;¸–è\{y&3üOvÖû›¸kõÿø{þ Mïß`Aÿ[¤ç°ÿ#ë~g°_Àká#ú¾!¼+ñ¿éþo³Ì*½>¸õv¢Êž¡ZW?Î=G›Rü‡ßo‹¿Óç©t÷½=Ç4zxôeñù¤C}Áû?TvöN9¿L'ŸáÜcèú|[¯³Õv(ðúå›ÿ=óèÎß®} çÀ]ø´G¹3ÄzGã|ùûÈ€¯êù¿M ýøkö?ãwPêßq~èõ~seöÙI&¦e‹íûtª [c£èˆûù÷¤! ŸðR$¨ €‘Èsx±>ˆZgäºÊ¼¡ÍåØÀžû3¯½%¸qNó²½S+3x"[etPPш@x¶ ?[×ôùäz̰ïu›ßãË¿G“Ï㟕Äã]/cÉŽí|HP xÈsçϘD ‘z9Ï+~¿GÏË1J|ÍcÛ¯¯|ݾyô^Ž•¹ï{<Áujó <5 2üzeÛg¥_“×åíóôãé'™ÆÝyož´ šj²2ÈqÇDz.Õÿ¿À ãÕQ0 ~€L÷×ó<ýOw·lVý¤zÕ1½Ã}MýçžF¼É¾ã»—Ö#^o%ãt¨ø´?³ÒúP¾žO¬µÄ{ÞTçˆ#ñ¹é‚ ¼3òe×°Ê^Î;­)›²Ù¸Ï¦†ÍO)«šã»ìhðPWC’/E×8Ts5HLêoq›Iq!~›ˆ{/@9ª¡#¡SÉ´IM wÔ{gÕqhRH£²‚H !vô0Ã2üO¯‘ sEâÌÇ­#x©ÉR[BÕ@ q½äºËVòõ| ÜË@)°SP4µ%/^L=ê Ù„o(µÞv|ÿ¥3æàlEx»øyóø[Oïöj¦\êfæ­Œ?8€‹‘åä=ª†$HIñõíÐÕÒèuú³=ïF$ñ¯6î>v“›½ðeïéëc½Æ<}ºÎ¦žÝ»wõù·@t8òŠ& ‹e @ϸš¨O§Ñ?3/æÙî£×¢”·F€’yч·“¬Ó¬~qð&ÑéÓ©ø ff™€¯•¼{k|älälA#Žê0DH|‡ëÒ©aqøQ¨æ$“‚cÔ¨¨ž òOG™‡Ïôòÿ¿“‹Bùß# Õ¾\xcMÎZ´Ñìù:>O_‘íx¡èD¿@~½!ôá$óöo¹ÓqL^nÙÙäË«¯²á 6ðogক[w|Ì=–ßÊš;iÓæå2ß=[œ‹ìï_±µÇêûG¬y·Õ1ËÙÏtžËÒ(ÉBü)W²úgßäà€Ú¯Ýï Ï…ºñv¥ü—”ŽO¶°3~wßmþçÑO =ÿMùóSòtõañ‘‚G§Å‹·\…§+zOSéü5¡Hïøcï¨ø<ÏŸÿ1}Γµþ.“IROß6($ò¿Û[oÇîxÞãÐËB)®=¯ÆT€÷ý‡ÔÃû7 Ò(r=. #«þ»Ö“$°É^!ˆçÆC_—ÀN=¶Ç…ŠSõ΃øø>¨"G;P¯qGe6É?k€œ© „F=>’ e ”ÛÉg—ÂÉO@n{ÖhzøzÍašäZŸ¤ì!…[ê¿îi{¨ew†³Ü»P´B²© +‘ …U‚á¯W1&9f-]†’ÿJ¾[ЙC‘õ‚âÄ-ʉMÒÞIóÂ'ö, rçð~.u|VkžË>ó箥kMëu±Ñ 1ÙÝ#Ùœ}]çÎz5äxÖ@W^;ï‘T•Ð×—§´ôù|ŽzÞÜðÌ>ô„ðd.“d =¤¢Š@ Ë—ÎÞ3^~ý~«qxçl¶“Ѱ¡ª¡¯½Øù(”'ðe‡‚õ^8ëâvb=Å`€ä{‘Çw|½®ªÕo¾n¾Ïc¾Èi´ïòù³z.bAˆ×ËÇÍ®W‡ß(ú'ÔŸZÏ(¯ênî⣯ºAwùª}îäûBü®8iæ£!Ü|ª‹Ïžðþhâ×à Zšy–¼cÖˆ5¬÷Ñ"ÏA`m6 ;&$‘±?Bþ¡ SŸ~¹)Gº$ÌX¡P4H š”]ö9vÏaNU§R£IN9Æ6ýÚÛ•o<ë¢áG¼Pr"ä{J` Ú1˨oÝþ»—Æ÷QÔò.;ú® 8á¼#ÏèîÚŸ0sü$ù†² :(ôåbm_W½ J òàA~^Tö?ש$’ßv;¸ô­‚ì;¾Ò§‚Bwl@yô">lôÕ¨ŽÛl€Î]ˆS}t¤ÝvmÑqßç®M`ߢ{å@øJwéÂy+ 죺zyŽÖT51goT¿‚¢d5¨£¦Û  ÌúT·Õ‘Ðxqêó`S¸]Eö Ü(|ò+G`ÑçGjÏ;áø¾˜oZŽ¥=ÎÈ÷¢'voQ>9ù¡° µQé©áã+¾g ªé…Ÿ¦ìòŒÊûÝ'DùÌ…@´ZkÐèõñ Ï‹ÕÆ¿;‡o/&¨cÄL3|þë²GÙÙy|(Ö§rš#xzt;?(ª ôWƒøÊ¾Há—ϸ¯±üõèµ0Ô]t%v$w»óˆŸ°”ËñÊoìødXGÁà–q·Fmz8VDS¢Û¹Bè/CSÍõ°Ò¯T†` $Û¿¾)ÞCøô9ƒ°·¬¨;•ly„¹Un¬Ýzzš¢”U%¶¹¶*n ù¨—¡z:Ûüs±/jïLÛµ3´ïàîŒ"V”Ži¿FHØ‹y(]ÖìQ˜¿«œÄÅEzžåX*`‚Ä$ ·æÈ1ÙU©èË«ûÁÊö@]œu¾Z-åÇua¢­Bö¢{O3€qù^Ävr¼ön™ó 'Jf¶§} ¿/’Cy(jüß'Ü­öY¢§xó(yÃk×½(;}tÊ|&%jˆý'v> ,;¨>ìûˆ¼LºÍÂ)ò„MÏ@=„/¹NÜúÒ& üƒxªsò}Å1ǯԽßË`ö·Ñ÷¼‹RŠ}aÖ‰]ÆÆ™™ ýæÍóQÑ.98†tm­­†‘ (C2 'ÏçW H>,‹ÊþŒZ6×JÅGÑ#èþE²ƒ5òçÓ‚$߲ޕ>GHÇÑ`;ÊU9‰òd\9|õæš{lÏ­P È;•/ò]‡eðÀ‘øYÆÆ“æ«ó·Èñ ¯júýß)ìZC½ö{Û¢/Qñë M¼=§SeuÇ'Ãg:™ÂM{»ü5 >ýëùv·Î7±þ¨áp|ãÆ°0@Ý  !2n@j* „çwIP Œ졬cõéöÈ6SÈ} %ê¢éŒ«)@+Üôjì„Qsu¡;ÚE˜ò_·Ëf<×#ò:Gäà(¡–´>þœÙ¾IÕ<øFU»ÅCìÂñ^ûZ{Haô‚üwZÛo; ô§¶Öil~ç YîÂà^ŒÜmÏKH÷{;"¬¿=ÑGÄ©Þu¹¡_||¤J³4õöKó÷§Ýn_œáÏ—×ï·âdÏ%ó}ú±ÏÇx'£ú¥ÚýiFü.­Lr¥Ý‚”»9OT8âð̱Ýy¦ËT§Å§€`B«ùcYTó CEüy[Üú|ãðò–ÎË¿* (¡çB‡æXýgEÑÛbT)Êß…_ÇØ?uús#’ý$'Ç@ΰ ‚½ŽŸ7Øoxs¯µo¿xÀ– B¯ìÈÃÄ¢Ðú»x÷w<*3ëTô^D+€²žw:§!·¹ãÙÇ®]¹ð寷ãôžn¬îteNÞ”M…E™¹Thl+ pÉ6¡K¥zãö 2‚èfœ¬s}y‡w¤yg÷Ÿ½§ê}µýí?3ÛÓ¬ôû¢«öE¶¯Ò7‹_¥†ý‹R|=¸qã[øÛó§º ú_7eß §-ð9»rWù#Î'ìS[l×_„Çä}ný…}éðÌü‰ÐSû/Waáyã¯g–ùw_5x); G†¸ùêÖî_„Ùþå„p6Ÿ¥Ç•>¸°ì=‘èaÕ2âó?‚žð´G£û»þg¿æ=\‚Ž^>šzö·)òxÈ6†.;þTr)ÁE˸yqa+iɆ:ÊÞлk8Œq0þ.!víÿv€=C˜³¾Gäè€Ç\¯‡QãÜñLßñêOà&=Ø})`ûŸ£–ß׿§]þäå,è@¨!Ykê'·ð¨™ÝfÄ=\ ëx †ÖåÅáظܷ: ìã$û¨>¸]¯ïN¡Êˆ>N|Û õÝÌ/*l0É'¨ä\¨Ýn0kξ×áôkì……}‰Ø¨bHu&NkË«*Q(©cô5-éó{Ÿ[ÍL×în1õ€ÙI\üÒü(_›ýCJ_ÔÉLý2›r9gU° ç¢Sëù˜Š£p}BƒB3wó îƒçÎí¾„Ó£'1ºz‚ƒÈ¥JJñÈ{ `‹wiz8Ügñ xNl†ß‘å@€}>4~=~²Å{HNtóÕÄ!»EHÜ}µþé×ÈÞ•}ÅOQ }êqðsofÙuËØ@ô£éÒ äÁøyB ã`GMÕ< ò÷T'o“ÐÙî¸úßC7ö  øÊ¾Pr·>õ&ÃoM"´ {ܽiãÓâB6 ÷oÀA`§ppvO •òôX4ùØ/¡G‚çÉ@¦©ÊÇÓäMêšÛ¾~;Èôñ5]ðíAødùCv𞮬:Ÿ:á§åöéšfÂà§nü/0”&›OŠ?p®m³-Å|áCH=já§o狎ÑÉ6îoxZ“¨=êô ;ì`c_,ó~ ^[Hèöå0(›ºy®®Mˆ ÂóûÕ`vQÞ Ø?“­œ oï©8¤¨nÃ}ï<oÅO=»`{Þi’@!ûÄÀéQHœQበ— £îr+ð.Ètá…RIº}Õi^Æg”Ê]I;*µy]…g‰[C#½Ò2Î3 A»}cQ„  ƒJs×Âb…±c™wä»d;U*-jìcÇŠw…e«<`Ýhæfpb.X«ô4ÉMUš—lQx ³†^dE^ÇzÞ`  v½šò/¥â•¡ÍÒñëy”ÅeÉD y°èÛ¶gìà÷ ôú¼´7ÆÆã¥ÙºBïaë᪼ԟ:’úfoL®npªC2Ï”)9BI%àéîL–(hëÝ“n¿±NW›¦óîg?.é”ñŠ7xjöì]XrY_ÍÓ‡Ãi{'pXGÍ ¹,U5q«~¼o«/£Ùbm¶6oôòë@zý˜ñî:†âü÷òØPË{¯ð‡˜w7³…˪Že_àç¸õè§±Øù»ã•õî|<¼o®•àùfîðÏÇÝT#êu`;ŠfÝ~¾?£ò6©ì5íê þ‚‰£óñ ZcÑtƒøD…:PTøðe2Š©¿“ê£o@ä´ XBO:€èn~ “n½FÕHÉ`œÊFý‘9(Q·>VUÃTrI¸7r`…9¾å»Ç9æ·°F° ÚWµ™HUAѨ»¼P$ªqÈ`z(¶N¼=:~‡aËkò¾Žëߤ~O9L Àw†u¤@õ”’‚¶ëö]9 õª™åÓͳçÃ>:Ï2w¡F„®Š,(ÜøòÜ5PJª€—O–?Fdsæ }ôTðHÄ çÏénþì@×IõçØyÐ,0ý³®Þèm¿nñ‹ Ss~Òé—wF™ š_ú»:ZX³Ž£ª¦tDá^ŸÞlò˜*±^mzxp\q™þÝï^ú™¡ôup=…D øx™!ŠõQîò„ä÷Aßxšv38ô>ögÍóï‡JpœU<Èt¶V‡gÅžg1 Z E2üîÖpÿ”@SÍFÕñù½_ Šé{«À$]N÷«£E}6¸:>žÎŸhaïv__!z÷àSzyNò®^Vòì={ß.ù—ZÔçèñŽŸ¤RƒÔ‹îy¯JÒ™ Aw‚–T†äsGöa.ÖîjåBàï+%ÍR€+¥w,ߊ££èÔ'09'#g ^aBÐmñ¸óò!<ä¸˦ ¼;WoR‘ùÏþ|Ý<äìU ÞÞmȘþŒþsòæ;Ê óîùüw–ÇhDi8Á\uÔ¥š• Ò_†€i’Bh ъØ-œ,ü6O:\Þ‘O[n^”üÄû­æœ–¸=ñ¶‚ôÚ›ÔH¯tÈl¨W‚NEGèÈyÂÀ§°lûÑgËÄ¢ùCŸX§ ŒàñÔZ¬Ñæ û‡Nn’G èºß6?yßÿ%8¨ä>T!<8O‰žÜûuÞ:÷" ÄW—m³Š(õóp=☕Å•EÄÞùí¡dí± † ‘_ Ž«¾üéPšÛCí¯å`úb¿ê¼¹B ®ú|Â¥)ìõX{ÕNÖLGj­Â!{]ÿ ž„ìWïEÜ¡œ@⋟ª9'Ü5öT­éï7;4‰ w5–f™f“€æð%üZ®î9‚Cu¬eÚR/¸ Ý‘Y[8—¹*ÔRc†°ÍÏœ/*yëG¤‹5Ÿè["&Ò Y÷:wßL¥½Ð(1s‹‹Y¬È'4&Î*4·ªÔîS¼ã`FZ؆ãM¾ý˜I'àG«¤{»d€AéÎÏ-¶7—!²áš7°ÖVPs5&Õj]JÆR˱R$š»rû8–}iuÒ–Íg¹ºñ¿(™E€ô@KмÒÎlm…ܸÛc™8£FtÏÃâóÊ+Uzj볬Sjˆqö+І$§Ûk½IŒ7‘Ž^µŒ×”¸P¯/{Š+FÖ¤Öóˆ¢øå…Š ZQZ½žñÒ]¬°l ×l­`Šœºy¯L °ŠµáŽÆCr%7¢ÜÈ•*)•wWB}÷Û\æ«GÆSX'â"g‚Üo»¬ì0º Z¹p&€`ôñý·\°¸EÝŒz/Êl> p1íåè(©.G€nœU‰å†¡Ôb1e Q¦[ ³»x£ÒP8`u7¥Ú·¸5ÂLàÙœ.CV¸Ý^õ­«_ _Ö´}­Ï7Ë©ùŠuw³Ž\·õxrç~LýGv$ôä£Ô~³îÜNâ€4ä©sow~ Lw×VŸÄÃâKòÑ_r§SÃ%im–p¾Oi¯rÜÊ “\3ªzÝ<ìÿŽe‡šYŸ¶õï•þÜQë0=8Ç«ÑN¡~kŠw'‚â \{ž¨çx‘ÈÚøÊ6`q%E¡ßŠŒ)$úï„§¬ › ‘ñà Ñ B%¨H%1ü;zbǪÒÂèÍyÎý‹væ4TbsʾA@ :Ù‘M°€(mÛ>ï`ñ—ÒÁ‘õ× Í"úZ'÷=ƒ@+Òan‚rü_ì'¶ýÌ”(@°ŽM×KÎŒ…èKß¹­Ö·ìÞŸG¤ÇŸ~W$”(¾¾ƒÐ zˆóžéï;ÍÇÓ!hÉjóHã,•{ðì(€_»š$ïøKÒƒ0{Åz‹CøÔNC^èú¼ ŒybûåS—^ö½,£Â‹æà/Õnyªë {ò¨þuÈaÉ›éôÒÀ8pܧÔÞqeke`¸½ƒ° šû|ÿ@¾ÖÛj›"Dø3¹§yÙ~çÚFH¯2?HŒ ¿5¹ÒÛyçU¨ß@«@ð§4}š¿ÅÏ3JgwÅzQÅg•=Çóy·hã ã=˜Ç˜‰UÅqÝóäw¨ðîaíÍø÷z¾:uåØËÖÉìö¦xY"{† oâQú£Ò§€3 ü¿nàú¨5¨n$¿â'£í¿€fåA9nްïºûªð½—¬g/œu•,ò…qÐ'dìˆ  ”ç A, S\±¥”¢Ùj‘ÂÓAúa™þ«û#»x¨ø Jèõâ¨úUÊ{#±óȧ€Í>7¥TJ®æüîü¬»RôÚìO ¿…}=ÍÂáXœ›Œâê÷µU…úsçENÚ n‡žŒÂ½UDw)kH'¯&ŠK÷6œ`u˜±Zí‚ᦲáiÎ\Ç\LvjÓÝÑëÈB…šºÇOÂO€>Ø@ˆ#è ?¯ô²@bŠ d“Ï·Ú÷œö«>Ù÷·‡‘}ÑÓov<þ°zÝÏÝñ÷•¤çذq»_Y÷ ¿¡‹s®eq»1®+ë‹RÃÓa¬ç3Ꮎ׭¾|‹ÖoêénUXö¼ûÞç·‹uÀ]kn}§5%ºýßhö×îýÐAF\¾Í)ºÙ—¿9Ëàû9)Þñlã˜y×±Í)—dk×ÔŸEÜgsC<{¡ðv^¾> ñ>ç¼Î”^ߨÐPÙUõ@ D†)--!jÔ%¤–¤´–‘hKP´ZI,…Ë"BZ²¢ÉR¥±?¾€vHTr¤’Z“›©£©‡c©Ö˱£,²Õ«‡\46hÝÉXW&Ì´pÉ»f®´a»Upªá£“MÚ+ 4häËW&YrpüV5nÃg%pÕ³VŽLµsrlцîMU³†\+’¶dË&í¸pá»F͘hÜ­œ+ «„œšªa»rrl•ÀáÉÉÉ–Zšµ7a5pê$†œ47hÑÍ«v²áÉ«- Ú0ÙÃvîmrV[·a«““Fn݇'náɃvîNFYpÃvJ®NµVÙnÕ» 4r2Ë-šœœŽF††ª®«,9+&®lØäØÃC‡ ’e¸Ñ–ÎL47nÐáɳdhÐre©Â•ªjÙ†Îdò¤mN®Nl2Ù0¦Íslé:Y'$é”ÑÃDÃÃFƒfŽ pe³f† œ&U£CUa³™–® Õ†N ¶jÝ9&éƒ' Á€· Z߇‰MڵūjR”¥)JUõ¹¤%XK­ÿÏd‹jŒ³›_5èÖ aEÅ1 ¿+`=­g9cì~·"€Vwp;ÊfI«ädH µ]å,-EVÕ1«ÐÆ<¨iÁàGÍC·žjÀí!¯JÜp ¦/—éR`«ƒ øþW¸äUT?5* µ‚  „¢ýÿóª¨aüEó3ª—¢  ½%UWD‡‹ü?Sífv—‘8N€‹)jQü|”ˆÆŒÿee²@QPé…¸’Å.1þ$g –-–o„8"VØGå~÷f@#¡Oáà`È‚"1AweR"œÒŒvjª¡QR€ 0£  (±ÃáE óaµ ¦sY÷:ý]h¾]ÞÛ ³©É¼Ô9gìÖÜÌã)ò‘â}†]Ìw÷zþAù¼ª‰Fk˜ëUoý[ûcßZvåzÍü„ CHäŽaç ,Š)¨L¨ ÇY³vÖ„nh‚øVYOSŒ©¥z¦²€„ÇŽ~P¡cyPçˆztN„@ª,1(@»Éþ$>¬ø¿VÞÁ×'úøåj{šþvS©×ËN¿ãW÷w¨Jð›iÚ=µ¥bÈ'/üt=œ}ü¶Bj@î%HobP„!êzJ!ó¾·;鉨’êV'¥Âk£g¡¸^{Pv|_ô_ÄβM-ý6÷‰ ëƒô‡‡jàÇ Ç°ˆ¸Cã˧Òp:g¼ülê1Xú¾Šìï…Pjx<Å£èˆ,óÛåZ¤¼•z‡‘\x lj~%…D«/ü8Yò¨k†_Rb}=KÆì“ð …ÒZ;[ðú[©Œ œV¯jJu*f.ÖŽ¤¾P«ØOÈ´§qʲö&Ž9ËJ¬5¾„]A%,%Dݤ͉†Ðèr(î8ë¤Ç⦠'…Üa§a/ø?NŸëë_äÿ”+kºçGöÃùœ©Ì‚vÛò_njp'?‰—ÅüÙfRô£µ'í_3`5ûÍè©ìyì©ØÙ\ȹ!ÍŸÔE‘uñزŸê~]Ö½Ý]à0€àÌb(OÍò_+wýhàô|=§"}¯«Üø_ôñº<¾Óêyêþç«ù=ýÕ9~rÔK.§9tïË*]ìò"%xú»Ý÷]ä_çÏ®‘s(¾Úäã2’S”ôß"÷;è … 0çQÃÀ¼Bá¤7‘½µ×¬¦S%MÌEÀ0çx£Ê? ? ºº#{ý üö%ùHFaüúoé B‰äA)3£ÂI) D? ³œØ3ã„9BÚëxž®º§ŽÂÃTfˆŽJ\º="?ôÁðaa Îj~ÇZ¢µòË^.8Ö‘hÃeÒ“˜Ì»ëår3³sÅѺ8IGǰ|à Œ”÷ðÂ4‚YBCßÜD¯$ÄR£jhà \--ø¾WÇáC¬Ñ IÑ›‚•é`xؤ”Ó;B¡±ãuüw×Å|è5zÓ`²Õ“%BKŽÛbÛ=Ä¡^ÎCl{röIa¸Òòüžû]HOzƒ^ë쀥ÀÐbK%HÌ#zPnƒ €?UKfþý…ÒÉò' ¬§J ˜-ãÓp²-ÐÕ@ ¬É’Ã\¼? þ/þ°íßnŠªËÌ ï.J"ïf£+Bîy’[‹Ý*?P¢d¤ïL§p]0*áCvíãªUȬ+Éœ%€Ë’×)U=ù¦²FÀYÜ@~glÎÛoºî—ÍD†J?X[Ç>B§›ûGÂ6[·‰E…ÀÑ;Œwî±,Rý’Jh„[nÉD¹V¡B‹õ‹öênt°ÁÜlg>~Ý58¡U¹±„åÝ´Ëkƒ\Cs“†‘¬§.…Õ¶î-)ù˜»%˜,/·ñ5FD¥hŒ23Bo^¤ýÿñìÞ)ý±Vøuä;žëñ°ÈþvÿáÿÉ™™›Ç_Áëÿñ¡±È¯CZ8öñQÿG¿ÙOÓjv½ÿ±Oiß"ÔÚ‡z‚Ó¯Ùô¥|) ÜzZ+ÅžhÛŸ'l®5s¾o`€­G…*s÷n°$ƒq `ÿùµ‚4æG(»CD¯Â>bW냵*.ÞrîFh›èZö*älÔ`.³…y·èFüÄx‡za Û¢ÿ—û|?±Æßfñúp„>¹µ'Ñ忳ÿaDLŸWåñSM`u€€±u ôyÚA^‰ }åˆþ”'¼mæ^e¬‹’7ᱡ³• ñì˽™Üý†(S Œ4+›™z²ñgt¿ ¥Ç6ÃŽ9aït ïïÛ`,ÀãæãÃ$§Þ E ­;0ïǨ T$ Ÿ*a×Ʊ÷=HqxuÇ€~¥¢Àm ÌËÍãFý Oî÷SéYY†Ý¦ޝN;hí \ÍÀÔŽ¬ÔñQôéMµè6m²mäÛ×såµì;¾÷ÃTÿe"·m ýP #Ð鏿—€÷¯¨t£I% ?Ï7öuœucô\ðlóg‘Ó+Eø’™§ÉÓÕR©áªûÀ ù øÁûèP‹ìi™»à:³DBˆ#&ÅCø(&p™˜O‰s_4˜ÅaÀV¾ëÌïŸÚùGÒÈŠvÄËÝú]²í2ÇuÝ4^rÓ]~‚Ç%Iu®ðýþµwwÖ­”±½U[%9Ò/GÚü€ø ÌÇ™/H"ŠÜСÑv´ôÆþ7†(Y:ª–mzrÑlïrÛOÜð¾'´ÃÙvYžJýsû¦zx«qÉ;¼|7ÜèH€}Ÿkò>½ÿ ÍŽï«ñõô{žÓÁôÙ^R†-cƒÇq·ó þ±±¾›;ík-ߘ7”Ôã,ØßÛƒéÓŠkÕô·¾ƒÆ7äò6ß^DÝRuKæ´q>JÖ‹ý´Ÿ‡½S_`"Äv"ÀtP.rv00¢YPo›}–(Ý[àåò¸wÔ¿?3±å»ïÅýÖ×*i2//˜»yˆRSèB傇à*{϶ÃÍæ®>—oåh}Ï„@ˆ=tŸ7ÉïïÁ€3,V-bh(¤ÀÕT{›9œŠü‰pŒx§‡«(`xjt1ô¸Ç‰`0õú£Í%nŒÅÊüòUv¸÷=ßr¢‘·â}OÄ=çÕïΫ÷<ßy9OwN/æú¿iÇ€û=C?Öø¾Ï¾)÷~àòó÷ù¼Üw~zÇ×ûK¸íozïWâù~5—F}“Ó4Ú¿w^°<)Å1ôóåËèt[þ›¿ËN8ðeüf_ÅÞ~—§Ú:‘@1×çÚ¬0NË£Ò¿Ì1ò7ºâÞÐ6' æú.»ìã)ïÂó¿âûÝÿG»žh+×ðÛ£’OÖfïó¥;úønE·Ö£èç>æ>ýǹ;ò§ÅJ|F>¯ËÄÖE®µ>¸Ã´Â«³1¯ªX}ž=½< Ï·éýoo»éךÌ(:ýï÷tà|ÚÆy÷oð‹»ú¼ò»’Ѿ§êkàúÃÓ_ ¿Ž?ýPm€#Óšw#¢ùò}€£Èy-Xe¾¨áñ|Ñð:ý?Mö°ŽŸKÙÓÐrÀkñØ9]-¤”ÝoöM¯³“yüÚ"s€…š|¶Ú¹75§?eð·•ÙÑÙØÁd»•†B¥Ç}ßõ³ñx?}Úm:{¶ßù¹¹º­Æ•3Â~©QQ“ZýD³7ŸW±ËúŸ±VhnoÌeà&(àtAáºÉåü?5ø"¦ @ò%¹µÞ#| ò :8 áLTªMÌ<Î~£>z‚V‘#ƒØP”vîhr7£øÜ§í°Ÿï›Í=Ý–èxÉÃÖáÕýä»ÓÇÞM–ÌhºN6×ï_Äö¥ÓQÑ5bf² ç^¥YK8ãÅð%‡@ip"ùáW·ú÷óÓ¿¿ùº½tC+žLþ¾•j”(V«FiIY)B°ñ}7ÌòžcçqœxySãmúað³Íàþìÿ¡=þÏÏñs)åÛTË—ãÍ¡·ÔÌö|¹Z¹»¯ñ¿­íþÇ÷ÛNVômQ{/¼ þ×nûRûYÏŸ~ó?ý‘¯Ðí:s4U…R’‚'ŠÐîNýé² ?ôÿ†Pþz78yš´¶S^ ŸÎ3 öÛPòr0}xÞñ%E-üÓ Ø¤ È)BRŸ Tl… ™ƒbRÑüüŒþw:?Ð4ïÃæÓðÛ>×ùŠb)À¨,âš“¢N¹¿›Yéš#ú0. •ª.vÇ™Zve£èÝlq­é_8Wðç«y·5JWìvË%dŒÖZ9­œ—¡KÑ@@ .›ªÉÊø¢ƒ¥«Ì+`‰.Ãn¿ÄϺ‘2çøÿ{æé@H£Ú‡®»Úë«v¶Þ§C›Ô–‡\`ö]oOP@ç̆nm!‚?¥¨c·ÕüYGèuòR”*p± ³Ù A21oÖCpf¤DþyÓ|a£ÒâX¶(RÑ´=»Ô!`…N(E›¢ XC6ò@.V¨-£kâÁY™¯,ð¼Œþ›ë§¿=½¹Î¤F¨«ÔBÜ~6.tpic†à$ ˆ9)FÁdz÷»ˆë …(H¼Ž£~e’‚&ÉügÉ8ãty×è‹&_dØTØG1ß¹FcRµ®îØ­i*&BñÂÉ0¥o5ºÄ=Q³E#eð£Âš'âW²…'>róá‹Ý¸šà齦Y¥â5"Ì^xz¸Ë+e«–VÏs²Üzžzù ŽÄ鎙äêR½[œ'8i<ЉËÄ QMJBEšvaHµŸNÚ+èêÝZ^˜ãåýC¤C_“Þc»4ç§(ŠÌAü…©E ôy<+6Xaʸ.P• ¦ïÈ«PÁö[®LQ"ÉŒI´0ª–›ø!{™ŸP ~1°Nô¤Xñ%l8U“’>þd±˜š’ŠŒ‡äÖB|*T‹Ó–»°òn_kC1¦“ ×°¼N¤%4E2.Л4åݧ¥3ô~r÷¨å8þ3®bÂÃ×¾.äwñ®üT<Âà…Q¶`c‘£J~ƒU¨Uv`_šÙÞ:!Ußy;xãñÏ/å»RÔ sd#$Ò“ÀP%`êŽ;mö„4ˆÂ§.Y±l´tÙynηé.û•çz=J[޹òCE’eŽ]/V€f%œC©ßCŠDg:¤$ KŠLB,…kÏhm3‚^]¹ \úÛö(rhN[§‘5mñ"ÃL%oéþ]©ÏUÇÜcèË>Aˆ¯d׿³øŸZV?›ÃÏa¸ä4’¯™ž•¼Â[P–Ë÷•døfàó¾ß>üàÎõ$E¾ûKµ­kga6¦;.Ó¯fÓmÒˆ¨¦ËV–Øçºîb.ã±ñ²Ë¸vWÓü½ú>ú£÷îÿÐü®¨Éq S‘/m )ì)Ÿ±±ÕíÜû®†#''pø©e¥•©v-kæÐ´´íf=›õÃ×][®ÿŠ¿±ç¿Î6¿ÑÚqåš92x¯5ù1Ûn¿Ç× —N»©+{[º8t ¬lÔï çëæb¿!1‹ôÇô¾ÏFšó”ëóLp?+Àvð¬KE¾gÑ©slÁW¥ 1&íå:j‡6JÎ7ÍéPšŠ†m9Ónr¼ô\Ï%æqÁŸ¡Lw iw@ˆE"÷O6µ†moëÜ~ïÿgúßêù~_í"üNÒ;ÚÏÊö<¥ b]îÀµé&q}.`U “ßBe_QªwÁâud7‡æ´ùuÂegÈ ÚDn®y…«¸—]GG¨AËâˆ(¢øÆ<*<*’¬Aϯ‚‚ÑÔܼîîžËö[~¿'ÝWÑ}===*x? CÖÎM¡q $\3óÅD0òýиÉK@sÿ‹ ¥¢Þ¸¶/"¹³Òf+~õëÖ\yýN!ã2–Ï}™{Ãëæs¦}Þ+1T3bµÁn›·6Öî&Ž–<³ƒ2¦.kJÝ™÷¸Ÿ¿Üx?ê6¦›‡eÚθÐç«d›0øs#¶Û|(Ú‘™@:ëžáù…ØU‚à …íkLö_0²È Wøß#ÆA%Âù0·÷ >K6bŠûòÞêwíšÔ÷Ú›7Sé=@âžç®=xÝ©F/õ¤xå GÔå’Ö¨j…§w@Â:fÃë>"ÿ¿ÛÜ~ìøb9w.Öié×èÄBê/MÙ}½öäö¸|…÷ÆáAB ªñ?C^ïo¡à?­½Û¼cnô{û…“÷Üù¿Ù TǬհÍãíö}ÿ/$æ}ßWÚ{ºÿcn?¯íTm¸WQ¿ö§ã÷ügÞÊûҾ.‘_ƒ…Ñá¾v·Ðî cíåÎßpéªÇ¨i¥u9󨶇v~)â|—O‹Iøýûña@ ƒülZçÛL{,Ú|Qª¿%Öƒ>vðåq£®í©ðÆôaíöî•õ®?±Êáä³6=ýHNƒŸ°ôcŠ®ŽÀKuß{::DöïSõ˜/×wèËuø,›K3 †Lx{²Ê¿ÅãÔç¸XpÊwê†?Äïà ,:ñcËR ²„@å– %cËßè›ã^ÛôM;CìÝvé~Ô*Š2†(Að^.’Ì„K3õ9v§ÅJh*£q_°vOc!ºlûï‹»\*§6­ÁãMvÜÑÙVŠa€z<¿ó:]’A• O™n²{³*iÅÏžB ÷ê'C§<Ý6‘¾ü‚Kh+àÞ¬ P,”äºôÁ ,Âê£ûÏ™æïQÏîPhúÇŸýŽ 6a¸9îaçNCœ¦7#|uvØœÒ닦Ä7<¾á™K —ÝШlâAJI”Þóœô’-3´Öí>Wq‹Åô.KÝ–1> ®Ë‹Ÿç7™9ûù·ŒÍM œS´Ü—¯ÐcsÐTL‡Ê‰ú=_‚6œ›‚—Í\¶¥9.ZÃK}­£Ë¢tdãså¹nµÍãˆÑ5¦Þö÷{a»9=î˜å½ƒ4­™ þB®bƒ‚(HSþe=Úÿ‰ò|Cáü¶[“’ÛƒÞPŸWqåØ ß¿‹’nYb;¿ ÇÆÇÛTTDü^T·7îk÷¾®-~kØ+ Mýœ>OФˆ¯ÇíúŸS¯‚}|~”äÞ^?”Ag=¯åUì‡éóžå#áç†øxýv‡Ëù<¿(TS w~ÁÈr±'“ÏëÛ§€Ðçðré¤ü|xãñ—ñ¾O?OâÿÇngpHîäÞH_,y̱ë·E©•\d%….G_µÎsOr Â¯ÅçMyÍ)»a‘Ȳ*yR)$gª*€uªƒJ0}"!@Ûæ †Á]¤€ÐS¹8‰‚ Ö2¤€”& ãw>ë²ô?/ìõ<—Gð<7Œþ·?W—óZ?ŽÞìÅ<±vr.SÌŒø¹á¸,8*ìMÌ6Yws`‰Ô¢Öo£Pw:V$½)«.‹5-Uo&€ŸHPÏò•¯1æh|XX‹xáµ;£×T@ XØ!f&üÌ›`ðÌ-†¯_šŒ{œe kÚ[pa†$Dܚ‘Û Ü†®í„-«ò¹ 0¤xÖñ;èBþŸaÎ4õ$eøCç±àO;¶^¤Hš…Ã7©´‰ßŸ¢»ò™Ÿ+Þ#ëk&CBÄ#zXôSKP1‚íž¾?x3R4t°áà5v,´ÄY,CÃXéÑ$_aþgî—oNÅX^4^²²ÆÆ ¹Ó¨²(QúE˜n(£Š5é© K“rJ«+¥m»>íJo ©çnÈ9kýص;ÅHFÿz{vSê_7}.îöbç hýNáJ<øžûE5"a }&làô?¦0Ø|ežØ`¤áfc±8œ(Ù †jòÛ–OŠ"Iñ‡q Á[Ýí÷”óWvôK/OóRÞңŹ[ÄÄb•çvSµ,穉ù;˜I¥Ûƾ¿­]¬Â¬—&A pWËtY2/*õa Ò\mËjhÅÖ—RP’32Î>¢¬d71â€ó ¼ŠFUv{å\jjËB%µU¨¬³RmdxR ²­lï=¾Sºó¡ÄÕRsÒà±`­H²Î g.˜"ðoŽ[Ö×Ã\a¥ÑÊËÌÌΡ¡y±ósš8`Â/æò+C :þŸ¾Y ⯟_LÄb5•…ñŸp$!AÇ8^MlRDG* *êì½Å#=Ü?hQÐç ïeXJ† Ò`:k£±(ªXw¾ÅÃÞIˆ‰nA6qjø]Ã%Ô±Ž8=t=‹»Ãì`^\Ë ]8ÇÄÕ›RbÓÝNáº,Ì#Ú¾‡ÙroŒ–Þ±Â,ÌQ‹è|㿨V†’•9£^®#ãèëúê Ú[ž_¾Z…Tˆ:w-k2¶Þ©?Þܯ^0G‡Q¼šÈŒ„„ä©Pp€‡(’ ÜøþD8ûÀ³|†Œ:[áÏå¿æÀu¶ÅâÚ¿iú´ü»›OÞ1ú9Ïç×þVkYjuŸ¿¬<~'ce¼ÿÔ±á‘aÌáopü ±nÇðñÓûƒ["%‘ ó‚4«ûÌÛm5 \…?Ð-Ú|NŠíãÏÓ1ü}bWΤ4ã§F OJ åçT¨ã‹ ºøE¹Dsû•üQ!kªÔÚT(5¬3÷½OgÔýŒî[Çúøç6L†y°9ÔÞÐ¶Ý hÓcU¥3-»u°^á[·q7ýŸv½{X)ϳ{]u*9}øÿ3ù1ìÔWú)ûn¡[UÍ›ÛaÔþø¾i.¤xv}³°cCržó¬Ì6~ÍA(_î?Í«ø~‡³Ù"´8è®löˆv°VhÀ"vR«VÂ1ˆý««´#ú€y 4è²RRÉòpÁ¥:f·!„¿Iõ¬|¯}ÖaRùIÝo[S¸,î«l/*¥€ƒ !½Ì3žn€CË9u1W…,ÉF޶€ÐñðI‚¿@Ö¥ðùõÝøÅÐcw}àEô. …­Z„‹\XELJ­±©wK4Š8J”/* UÉEU «,+n&Fׯ´u¦€ÖÛl"6‘+z³0Ø=Pa–µ½¦ÂÆÕÉ‚†²Üà&Äl6µÍÍEuw²#ÅWN²j%Ê¡,¥UC5R©’2/lÞÇw|"ÕJj‰›¨È¥sFú‹®í× £s“%PIBPÇý>*5ámm³PÏËñ•9‘DSïzj]LP½ñ )Û#$ÅïI¾õÄMQ‹H±¬?*ß—‹dÃÿéŽ6Ÿ­´xÞ¼qÜM¦.&Kôå„ä3:ÿ÷lê2ëñ¿ãû~oé¼Cµ‹Ûè§æ¾sÉî7ö¾ò@9 >$7)$(‰’èÈ¢Ôõzzø}óöO¼1 ïÐùG›l;Ëã¾qtw‰ cxµœ: ´…뼇r>ïOo¸ìåóe÷€hÁ˜²w§·÷€A^<…Òkƒƒ)‚ < ¥{›¹™µµ¢˜ðhÐÆŒíA”©mr»Þ Áa…C´6aŽÑ+Gv¬s»R°s™HT q»i\£^XM95q2Ë1•œ›ÅUÄèºcBRpW)†¬ v²£6†œš°ÃvŽVðäÕÉÁ£’cDä­ÜAƒ Æ—]Z Û°†4h†¬*A¼KÃfÎM[´5Š©ZMÍÜ·Y9k2Ê̵Vµ›ìËFüŽCˆäFÃ,·rl‚  A+/3¨o9Þ÷»Þ÷½íAÁµH0+Ž:4hÊ‚UŽ0‰\ enôÑ£'&­Ù7qna³s« ›ªàªì­%`±a«íƒC@"ÖΈhƒ€wR••˜,@˜C‚C蜊Úo¾óTÙÊ]š¹MYŒ2ÚlÝÃg$ÒF\95nÕËXlÙÁ–“FŠÙ´Ëw XÓæVR˜(Õ„ уB®Ž(0+»Z,1bÆŽZ{À·FÀ0AÑŽØ´©q@xŒTíæï¡›oÎÕ×ÿÝÓbÏ1ÇòÖ‹o&Qäë{¾ò¨ÖuŒ+šÇ'çQ•ÌÛÏQ¶Úú­÷´ïR9cÕ^BðÑæªâÿÆÞ9×r³-ÿ`üqÓ=Q¯‡ç¯sTÆ(Kë<Ýäv¦ªµ6åjÐ@Ü3Ž8W'¹íGCºóíÄsj æö±y\ÚúÀµÜ]Û e¬Ù"øq Wm ®‘ŽÚJŕ֪4܆ôžÈ'7¨ó³]:o¼Àš xSýUà;ðõû_³ÍìRžÏ³·öýŸÚkûN¾>wg^+iô9˜íu“"F,•Ûƒ{£˜*ô†h˜Ç+v@rë‚9¼ï]`ÁÞp :ŽK¡wBû6v9¡‹WÝ\´k¶ºcÞÑÚÂxv.$¼˜OÇ÷}&dp˜ŠÞ™ÿ©l6œ•bz‹Þ/[åèþA“è0-½H²ñþKo껥£|›ú¹ÿÏí¼þ|~UgÀóßÓâ= %ü4zøªôz¾ôØç^JëÀì`„ `¤ Ȱå ~’cè³ûy1 ‚‹þúŽ_ÍJ?´°(V~ÙÏÑ¥ŠÃø £[?{±™(ô¿ÒþeÖ¿úã7ÝÇ,±j­²É{ºü´Ä€Çé Ïi[æ)‚gfÓ%Åä@>WéúÝ‚juýq×N¿¯; õð—jѾgY£vѬ±7·$ɸݎ‹çeÞæ¹VÔå¡;ÛÇ}}¾õõ›8÷ J–ã¼ÅÕz2í8HŸ‘ŽsÙÃÞÝÜå†1nŽ,YžXà/©\Þ’‚ÝlЗ²Xï*Í“`—½×ÂHÒòò¦tñ^ÜÕ/`lq»#×Ì@”¸lì:¤q³¾²OfDÐN’Qˆ†ïmÞqu`kˆ»Û‡Ùî•›Þ7Fú%ïy8åÏ‘ÉÜævºdx‚@‚‡{îھݧ}±ðwˆó‰ÞS .kα¼XÒs§ðdâê8—‘1Ñ×&p]t+[DÚSw2Ï—ÔqZ˜Ð) ìâïjð\6Ù#{Ây =…»Q§:¹ŒØ˜ÀfùxsIïxV Þ¸Á¾±Àz ëC¶µÓwç5’8ÒA‡1• üTŽy畬^ÐxyÖÅØ·mFxøƒxa#¶Ê ‡–îqãKƒÍ#‰ ^oRÑÎÀzÉ{ƒ"„uó3Ô„ça{tÃ](æã´¢ãÆa‹9Ñ}' ‹…âpñÙ$ÀwjÁeª˜: ìÞÇ;ªàCF zPE—Þ>MdÈri«]vô¾á]ÃÀé‚{yÒÄB–Üb6Ä£›Ææ÷¯†âÍ…²K2*Q«þ-ìÄ›8ˆ–õ1¸Ïß‹3CGŽ87¸šÍmLDî1jjØÞðs5sd€† fbǽÓ¶x¤7Š–<»±q>TÖnHÞê: ç2ó¼×„.ä²u–à,„ÊÍnéGÍ©±38B+;;š»ÒÄ•Ìî÷9º7¹¯×š $€">wGˆ_m6êø8zÏ‹¢÷ÈegŒ>Mh¬!.ð/ #oJ¦ó‰ŒÛƒš9F‰»ËÌœàÑË==^¨-ò%ÔJ¦kDR²Ìä‚+nNnìW¸‚ Zî/¹~¹Ö{¾2ð¼‰fWq W+R—¦-‰‚BÆ›ð;ã›Þï-Çc‚–ûÎ3¤7dj\c1K"(pw¶z/9Á§¸•®#²i Ð\pRø$Œ4\êBë¹£)Ììâkœq¬×1Ë{ɦüwþ?âÿÜ@$zq‰ "ïÿ…™$ö~é„îž±çÿÓ©>Ö#çeŸG’Üxóãî@~ãyí9~^~ÝžH¨qCzZoùóÒÄ÷ƒ!®d*T.§ m³R[ƒ= ÿ™€]i+³UA@Çu¡æ¼Y1@Æ£´#»RÞÓ8¬.[¦‡Ê]³J ->Wûñâù1£ÛY€ANQï¯íþÝ­~å§Ã|Žl•>ç ™ ¶³¯ã}7mmª^/VЇäý Í@@ë½î`ßòý½+=$+Ÿm]Õ(–õÍ}ÔÑÁ[h`šÐë¡\“ò¿‹Úv½We§µç)Ê|^ t~o'›› CH­…4äý5ï6”©ìÏ¿I©ü]òõœ|”¾Þ¸÷n ­âå}|Fg£ÔßTü<|Œy¶åË–4θ®M7W0ÃfnÙÁï°ÐÕÃ.&íÆ0`°€€Xx·NáÁ¡9ÏéSñóçùÚ¾aÜ{|{/;¸ PR¯ÁÜrYß›ßWú+U^Úõÿ­®ÕiÄ&P±` ³ß~b`ÄIX"OˆŠÉ‘Xy™`£-œ²z¹ùçÔë›;‡ÜÖÛsë)º¬ˆÈÄ ŒTJÖ ˆuÐ#5–vÛÌI§“fi&  Z6Š*ª(¢%J*§c ºm†Æ™2ñ¼9šÍ7`Žë½++§I…zñ`kŸ-…6ãí@:øÊÇ,tD‘4åˆbc—ÞÎŽoMϧϫÃLjÃVÒåçm¹•[7jᆆÎ2˜‡ ؞˓—-˜qÁ¹¡Âpc‚Ðå /GS¼Ú΂/½è×·9 ]ã®/ây„qÏ8ùÕÇ6ì|ãW¥Âë8<ÒÅz9¸.´œÒvÞ‚–XiòoP62„;Î<%ï˳£8ÊÒ”g%À);¼r¯"î*ÎI(õ 8bXlúª]«èè°€ÓrÅŠæÒ¡8aƬÑ4ªêWÔÚ«Yºù›f¥ëq±a´8y¯&󳡓E—¾ðœ£Éˬ®d¦³ótöx ‰žvæ…qš®Þ£²4‹!‘df a^¡JÀš,yqu²Ïg/ƒ ®óƒ†oŽÍ׎˜CXêCF!ƒ³SyÑÞðnf]ó©Ùï_OL2¶ŽÓä7a.Œ­§n¯k¬î¼t´“y0°…‚ÁµÁʆÈ@†ñˆßrã{ƒ5ìœÁØšÅ"Ù™¼ìSÐ\9ç#|òY%ÙºóÎ8ù4iç(f•m¯EëÜë ïH-*ÞçL8à#ÐÅŒKk†«+:î­-ãçèêÂ4ž÷­ŠOÖ«!s½¯,s£Æ°ßBÕ]"nv†Wv–°} ÍÛâs¨ž»È<<çk aÔ Aeíä® îÔ8Bµ–¡¨z@ãïnÈ9yw€Œ¦x@á$iqW-S=ÔÞ±ÛC^‡@îõ躣¢Ç,]ñK(@ÆÅË¡k€:iÚ±ÜpN(®(@EjÈÐÒ# ßiŒ[Þ K1F¯–ºA—ÑŠ«²·µaÏE§-ä}4.s|n "z<ã{†ÚDWx|¼iF3©H|{*¼"ŸrŸíÕð߈æ =%`´|"Ìâ+í›|àCG‚¤ª!WE¢Ô­ îø˜ZdŒ´,ô'uÓëD–9I'‘ <Ü®Àë¢äç'y˜mTpgñ%TÓ^=fª¬)1+$?ü?8ùýÑ쑌Õò±iÐöÌëU²õ–Yo„¨ˆ×òþ\Îã=¦ºù9ÿèßßäötµtõ.ÚšRóSqÃÖ×uÈRCîm;s_Ùÿn~Co˜Êèf¡—áPº[FVX7|/`ck ‚†“f‚ÒH%ÄM þûÌß×|“âûލ:ÑL«!Š~[îuóÿ§ô¿'÷ŸÄðãÒ¾¦îäñÌÏ)Ô Ò²&+=&h¡n;ˆ³,uç9ÞØë!éæg2 ©/­Z°¿Q÷9Ï4ø^4ýz>´¾ôuf•¼¥å0âo¬ä]Ná–Î h½!ñþÊ=lSþ Ý;z‹5ŒÈr¸>Ø{4Ë–‰íVdfí6UÞÜÜCÙŠŽGAÄBt¾ä+âªtÆmtÁ}xQF,ã‡F(ÀBN¯Â}¿áîeæÞ˜{¹1— Ö~“õ¿·~kñßÀ'Èì#ÜÒÉ`vÖÖ¤õYopí/Çõi×äà— ÙJ¯ð¼öH «ïÑÞ´hçÀ4›b ‚A~·ôß•û÷âþ_¯é?¥ÈèeƒÐP{°Œ„“7ÐççÒ !Þÿ–Üò^ÖÿA·«µ ¤2b$ -‰ã ‡±ä¹Óã÷z<ï“À“o„ ú¿ñ¸ÿ³¥ÑãêÞ½â  WefåNþ;ÿ/z¹F•þ—÷ßá{6„ÿ×Þ@6þOè[}Ó©õÅÜú9í€{-uãŽ3Çäcè}->×+•ÒËvZ4h¯e–Z°Ës“ ¹4r*µ957W #ƒ c t 9K¯š–tmk"ïh®šå3ŽO•s¼ì /¦»R&ÐÁJ¡0Àãˆã›ƒH°‹µTVÁ¢QAµd(ÀÔg¡ q}Håwsáø½¿“ñpnrþœöúzôrcmÖ¾ 5¦”–ŠëÃÆ{±ò&˜s÷É„KyÙô¹¼ í¾®¿ÿ„ Ê|Þ!غ—`-»Év¨VîÀê€g«Œmxºÿ9’Î0,†ßI={íŒå09M[­W*FÖQé~nÛL&ëS0›º7à CïklA\·Y–Ø ù¡M±…¾æ°ŒújîÜLZƒÔš ZV© pYBàö§%É›£ujnNš@f9 ‹dËÐôõù]¦¯0klêìæ]­¶%jçR›íѡ¼¦…‹†(k=.eJ]!r‡¢æJØ“‘ïf‚¢ü Sô¾oŸé‡Vôå‡ÔŠÁä@¬8¨¬‰4hâ6m»EáÕ\rÕ4FÊתÃFu`)3Bï6a`TRÔÇÀvµsŒ€µ7ÆÑÔy=Ÿø™½ª/pKÑ닳ÕeÝÚ­Œ^DĽâE¬t·­iuÎq]@˽sÆj­¢âΫYx[ù=hC£$Å…mvüöy–¥ùä]ÁÃè3.íš{\òý Ö½_{V½ó[˜æo2O Xî¶Å$ÐÞ®ÕÀu±°Ã¶8´tüulþ¿—^~¨¡þjqÇ.7}-$7œyá†U%aK¥ä{ÂÜè==$òvú:-Q¥ª[imíÏFŽS`ÿJx¬ …¦ô ^–g3³Ö~û”ö¹Ö¼ð`v ¦ ’ $Ø0ô+HåÍÅ)ăaˆð˜k”P¢=éD‘µÎ0bÒþvš%¶PÉPcJ#[9{bGŒU{ ˜=šèÜbűÀ€Óî«hX¨OÊ6mú›¿?]ø6`¨$$‘”*ͧvÅ‚u]jÒNªrqwpmG‚!Q@¦EjªûÑÀ|W‰\ÖSwÃ,X2JQ]i$ì`yýz6áDEØçuàS¤ÕÞatÝ»³'Kp •`·€¡É@HåÏŒ?ó¾žH[L" =#˽&pyÚʪ̪YAïþê︑n¯xNžae ÜëÙ³vWãMlÏ£šyÿOæóùðáÛÚï‡Wyé9ÜsÉêÖfÍp¥ñs̈§l1Švž¶›¦»hã0À½_6$ç Fk³3µLÍ «†uEʈ¯‹&öÎ…oŠWUy”àÊu›q`¨‚ªw=6¹{g{z]«©×‘Ñ 1½! µA*ÌÂÎØ A% ÙVÙ)«Q% •€Îá3ÃŒq, ãs«œhÚéc¤UG£S²½Æ[Æo¹g K…žÇ5TF(•drºþ9HÝæp11"H4ig¿Ð¨s{ÕÊ@ùâ{ÐX¨f”ŒD¥Þî›N™8ÛŸ²tç›ìÁ:Ù{ê©áB–"·v¥xN”Z7WóªuÀH U_oåà8ô¨L7 ìàvm•…î‘ ÝK[¼@pEl¢÷¿F Aòª ˜ ×I=ÉH… :/ßfÕÕ DÖuFޝ.±µ×)Ìß9±Ñ®0E82ºhsÝÙ®¢md>ì²IŽ0Daй±p£UÊ\Š÷ÁР(GUP9@†Xä[€n¢kÉhä‘IB 8z²nÊtBh²‹\J”(M ²0à¶ÄFÒ»îUPܪ錠C`ä—Ü©MòºÛB™@#lr“à ]fD=ìe’›ïlZÅIR•Å F0Å”o€Ì´f²"&ÖPN„К¦bxv{[&›q47Ú¨2„Õ@[ß!‘´êÅÕ!,K@\@.쪩7Æ/ç¸×’O¦‰<z®ÕÆ«xí›Ã«f;NÖI_)hÞG>V‡µB‡¹°p#Š,ì¯T¥gvt·a^ÈÛ8@UÈ6Êl 1Ö­y¨@–ÑP7TIq7 ìLT¦²£Æ%EÊ Ar¤ÆI8ëWìy—šúwðؽ÷³—7e·Z>Ð+1Ê m¶q˜ÜílR0ô ¼rΉ™ðTèÈàáÂ0½q./…I0ñ•› 'g°Û¨óßF*ÎœéŠøí¶ =“,_•å‡h–¾ïÒºZhÙŠñ›/£±¯£Z·T/™4 e uh”ÙS»ÀD´éâì©ò#¿ºv:¥^ýFCŠ-®žZIðÅdl`§ udTÖ†ka^JÌTºÐh£±°C¶æk¦¶Â]UTqKiš;‰Üf–Í[8F ÑtCÀB5sva*ùi ¬¨µv*Rs»ÎnûФ‹94m±"uL… ™MWp¸`À;>ÁU°Øk 5"EÑÆm€­Q¹ZñWGQŒ×!°¨“jÓȪ²»¹/”$¯PÅ:¢µ³±Ñ0â_!‹÷¿qŽ˜G>›9ÚN¹Û;„™æ Š;”qßïÈ(Æ%DÑ» ÆXS4kÛ¸0¶Hr1T¡hÜQÅðô™¬ÖMòÂv®¨26ÍË¢Øsàhne/Åñ¹P²AÙžŠ­K½i³ »Ã³0ÙSxKN›Ǩ"°2-]Á`(äÁŒFÙç:äá¢ò9kÈ Kh>Û ®˜”§É¥•,Û2^úkÙ¹û[Œy‚âê L •!lU ` ";º'ö/¬N[òíìsjÕÎsõ¼=>oäÉÝ;<}e7~b©u|é†kËmõÞq5âUO1‚"Ê1lsK"ñMU+R^¹€¦À-`DkW#‚‚«B˜MZ…3p£1Ú‹žÖL:‹g0ï™qâµµØETEw´Rnž@JZîéhV2ƒ=î‚“aÈä…AÅ+„ÅvÞ¡‹Q;YÝT›€‚…aª '®v埚nn«ÉÔÑŽY•Ú‰HåªýÝ@ðDbjGÅü;À8+ˆœ‚.ƒ ê#²ÜÙk Åy© ª ªÂY.CÕÓ˜›JÔ[»œ UB…Ô ïV°b¨Ö_m”Ñ·Z”mc½©Äé…NÑ®ý‚q˜µÈÚ d©\‡²I`0Œ8•EA~+m€µÈªïEÅy %HÓØŠZa»ˆº8 ó#Š=x]ÅKB¥÷¯.+NB!¡Ë~W­åÖ½9AAŒ|VXg#™×g;ÓÑé¸8+u µ1.J&rîDn«Øiz„Ø\\(ïïstçQ ,nmÈtR ¡N¥ t¦±akZÜßž8Z‹U‹šÈËÕÑí@©œ‹2] ék‹¾V¡¡Jcº2¶A‘T«¡ek¹vPô"ûÁ¥à^áQ «Îø ®÷ š)YEÙ†k” iº£‡£$eÙ!ÄŒR :Tâê}ËêƒZP›m,îƒY²ŽÛ@O³ŸíWñ~øé½°;P#C7`Ñ…¬ÃLÈCKç½£€‰/6o#æ¹7™yßo8¶p+Ëß¾/\×|b×|é¾y]“›Þì½<<Ò;¢ûm9/»’Ò²»»æ¨ ÕϹ/Æ µÔU Å+åååá)Ì»ˆ¶<Ń‹»½$"Æ&@q!ÃÉŒŠ&Lˆò$Êð#6}HsÕ¾‰ÖÉS¿N) ÂYE?ÃQµ_pÊEýß§Öݹõú6}/ë2~—»îxîwkwŒÌãéC„ÙÆÖ²²•­ Fª„z€À0'áÃÈ Æq!à¦ýÿ¥Ê³Ô*ÎThA’5=HiÒ³H1˶:ÅÃIE­;šl•VkM­YÓÈ “VQ¡eΆA¹S2ì‚I$4¼ÃDîvóÀ ÀIF¿Öµ²$VÁ*À¼•wmkœÚßZ;È;تÊAI£d(PÔ¸½$hâd¢i’Ã.7Fm³DúXc§b4@•Ôí ’ EQœo¾iìK¦é j`›šéèã±a»Ò>ó3[ö:^BჃlË&,„p¶¤Œ UðPìç§INö«ôìoŽÈðóÁjàuU?ÉÝÆÁH+Þ±ɣS.'»æÓúÀƒRL—ݪT4äPÂÇGfo-ÆãÕç±½ö…íwFBýF¦úÂÂJ(E,>]ø=ß{»ž –‰”å¯sZôjªšIDÝ–Ûn®°R¦«^V®åX4¶ëF°Ê@ ¥ˆÈ’\Rз<érë!¬CLçX‡ì¾}Õ…ÏÞÍÚ7 Ÿæ}Ï_Q%õið ´ºÌ1F{û{Ùî;}Þú¦ú}s ϦÙ£†Ó-ßÄjÌäÙª¹'&óvyI³3Fõ¾í£vÍfSCv& \95Š–FF¥‡¶+B(õ5ŸŒK[q*ÑE…y¸¹Î1™ÏOžz»ÂL|ݾëÝÎg¬õxÇ“ËI¸üõžo­œW;œwͲ7«»Ò¦'^@Íð¡Þ¿4)TK\¶¯¯ã¢© Æ¾‡Å¯Pæt€r«¢ÍË:RøÕ¥ý§£þÞ]ã®g•ØHNÂkí,îf­iÀ€? »i% CŠ^¹dÓ n’Ûˆïv‰§…ÎqÍ»§«÷ߥÒäèè­¹»¯Æúåªç.3«­(™Â£mk„ˈ| ÝL.ôRÀƒf¹“pÇkY¯a`‡F©T¥êƒœÑÒ ”LÑ@z»\«}Fr§ Ü³¨|“vr¬îÚ!aÛýÿ¡”š ºß½ä Hìž“P!"‹´'"ƒ¡+¦UV)W`Ý@n—A½ñn»}öDØ<Û]‹ª3Sz Ê,€”AAÚÞ©€¼†3€1…AC$p$ä[°°j`$[”D@à¦-:M€¥i¬£RMîèWA[¦^ÉE3—Ä®LRFX,V˜"à‚HP¤§s/+4ÝžŽà;R(/nŠªw³Œº)¹‚å>£”D²îS¯pf:D#šbxç„=IB€– !¯na¥™Ü›Ô¢m·åd¼@“Êѯ!†¯Vwj]„¢l=ÆôÚ;¼vt;:rN '>]B«M„å ÈÓêŒS9elàA$®;´º(à‹×V¼@ª¥Qe† ¼ [ó,7aªPT|pú1(£—n$IÐ"kzï˜TrŠ„ ÙA,%òÜJÔPH'·aÚô¥BP …Áîô B€HV…`ëNCÔu³‰è ‘@ W˜* ÀΉ ¢†edÈ›³1‚%È$ä‡75EZ`ýj»ª¥×l€ê¢á1qh¹è'…t-L`@kàŠ © C…öV ,ŸE¬,"À&0ôÛARÔÓ ~6–CzŒZ k3ZQŠ)¦ã4›TnŒB›ÊŒåD 8 .7ºç;iN]Š0!Ùް®Äè p‰ *GQI(ªuê Šˆ2)}ø†[f ¨uüךsÉ-È ¬‰ÛžCépB”m² ¥©²½F¤ Ĥ#2£3¦Ì£m«BºÖ-ZEA*7ÜÙú*ϱ@ƒfÅgŠ—Õ’Ó9Sp8×ïU¾¨–º†mèƒd;QˉÝEJF‡…”ÜB1MôÌÃp)»Êl(˜(éØˆŠ`­ðünœFÕgÚ:*Þë…CÄ1”p2]Ù­ØÙ ¨À„¸ŽÑ«å¦àã¨æUpX2%T’p´ !¯n*ü´jœÊÅz… 4°eÙ¤Pk¬‹Õ:j*kæ­›?;ñ„}¸Á²ï( [Îú…iTÂA•{Ykç´$P \Xi9H¦aÅXµa9L‡`±…F f-éD°D;o]+{F”¥€É•Bì" mu[ ªz»4=PÝP†ý Gg.„Áæ‘Ë.±JÕ‚ŽR+²‹‚ØA<° žs27”~Uzô)z^ŵUA&wW$.Ì€P„饱ARˆ€^%;;@[Fa_.×µä<¬‘‡QÀQ¾ê#yÑ ÕáµA]¸¬¸µƒh ¨ÆÏ:p—ÊÅ+I€W Èà¨X!(«N9dÔH‘d笄•%·´Ãµ¸UäB€Û†EÛyÆTÕá”jè"¶Å|åF¯:ePjÍJÐmCc‹ÔIBÌÆé"•ÅïÌb–¸]¬tknl—ͬ ±K‘°lÆ«±«-´.Ô±¦«,UÔÒÍh£ÎxðèˆG1Ué…a¸Km˜$QxáË"•6hä%ëeähCP/%Ž0*(—Öƒ#Þ"­¢š(QˆÓmU°uBÐÑ.ìµ6 ™±aµÁÕÖX+rˆs…•Õ¯”Ì: “W¶gF0ÂÆuŠ4¦ÙT»ó RB‚‡–[á‡E ÔgŽd)äX -a…´â¼ƒÃF”Í’lVSQðnÌêͳ ÝËmFµšYSCáÌR–‹ÒE ˆ:v<φ¼>¥­cA>€ªT»I„R±BiJÓyQœC—͵L,á7Œ¨Í!¤ëC¬òñù"ï|å‹›< ÔûŸ/‹‹ï~Gã|þª?2Ø0ûL +1ÆDÒþmãØËÊ132°g°‚óF1˜‘Xa+ieõ\Åâø³X^RZì!m!ÀQIŠr ,M©ê+ k*ÄXŠ€¢«Z“"ËpÂ)Š ð‘ÕDø¾NŒ“çU)lÖËR°;ïËäÂ…!à¡!{¢YÎÃÎkRĶ ¤`  Sá ”HzÒKZø“›Ëû…¯k$¼•>GýÏ?ˆA·›â9rk&⥙j£§ïþpëÁDïÚm—·ì<†ÍÆ]œí sá·"HÈɱ„Š Œ#QŒÆRÒ°TT-–¶ÊQTFÒÒØµ¥ÛæôèÇE1•–¶ÔjØ[Jµoů}m¿¯Ñê÷]·UF(*1fã*‰Q«KQ–ËemVÑ´ZÛ¿*…¦«i)b¨²±B¢´±²––(¥B±AAEPQ±-¨JȱbÚURÒÑj[Q"–­Š6ÖµZ£,©R–•¢"5"Ô*ÖÊ›6ØRâÖÚäŸV´¸àãk˜eÌ.0bÌ”2·›ñ“~8¨ßœA:Ö÷ß™â)[òŽwóçÒau•¢_Z™R¸e³_0¸¾ï5áǬÉuPkÒÙ-‚ÖåpÍjÑVÁ”ªí»œ3E¦ŽUiZç¸ôŒž4ìC¹€too<æÉ;öÖv¡ÆvpW@ îáªVåÀÑÿ¶BÆ®Õ}0Y” Ê¢8Ì‹Šmtg ¦ÌHfÒÜ'DA„(1”!3( «bŠ¢,TXÅUÛ¼ÌåeXªÅbŠ<ÙTPEEDQÏg¡¨m×—,×FC˜ÀUETQXŠ(ŠïßsnÚš*ÄUQEÄ*AAAQDPQEQE˜Ã-™‰&(¸©nEÈÔ\{<‹Æm¹.V“7¹\ÑgL”Wºçc3ão÷}Wú×¶þý¿öÇÒåyi9>RQ¬äì­K)F•€° –rcõ¡ÞdGÕzhÿ¯ÕŸ·ø£éþo×û…»ÏíÈâˆ@ýrŸÞÿÞ;€Ûï§ß;CôÈÍ“Ÿ7S„€¿ÅÖØÖ¨wÝýî;«ö|? |êsq ¬”޳‹[]¬ÝRü­‡®Ñ†è}¯ËO¿Ø?sò¯ ù=GõZ¿x{0×—7v®ŠÝÉ•lääÙÃF œ7hÑ£F[«QbÂŽ€­Îdu–y´2 Œ/Ý´ÒÙã?ýœï0Q ŠD3á’5Ì¢é»wŒ­ Ò¢™áó;–`)‚fB¡ÒZp!ˆà[Y ‘8@žèo¥)óöàvšð›ÂËn˜y_˜yS÷_„ÃèbõílbBÛI$hÛv‘-S(¶CaA²ï12[K늄ßxïlð:Á4X÷\å‹À¡dEõOa­` 5fÂÅZAëpZÙ‰‚¤Ú ypD"£råʧ½8a†ó ²|nõVY0äqÇ N&®á¾Œ¶aº(0G¥ÃÎqÇcìÝÔóÞŸ…ï]æ™õ\±ËðL¾Z¾*îõkZ¼G~Ê÷\»ÎLõ–dóz¥ê.Ltfòú&®yªý_tõòñÍ™¯òóÅ–RÒ/ƒÑg UëkŒ@}-èã÷|ñœÖzÝœ9ŒâìôØÁ‡Lò÷»‚ÎÖHoÃØ-o9xoÂEwŸüô® ¨ù½u1é@ÃP„rË‘HÎô©vÅ##–\dVê‹7÷o¡d–Ê×ûϪ£ŒÌï±´r¨Và3”±n,£…7]Þ»é1tþ1ã5Kïñ\¶híIdÜWÛ ¾±QA=ÕÔ\TX !*¶KÐßk,ç H?Igv4§ú ‚àùˆ Xl6ŠÈÈ‘¤­1ÂrÜRHæªA Öð°!Ê›°c¥ÕÙî3A{¨)5fÊÐ@4BDÔdREmN´mC7ÂÊ)ƒ 0ˆk¢BnÑ¢)ÄŽ‰m¢€Ô²ß¸i©.¸­¢”M¸jR#əĵ[‰¦dë¾Òç"€h  M×AŽUÔ³ Šg"£l‡PÅfMí@ž#p ‚… ;µ““emœ`ò êü5߆¬à^¢ÓˆåpËU¢ JÝ^ (ÝF™kËÔ>§z‰”…5¹dm†Ðޏ]E0®–8¤iy`b8KçxŒ.6{H°à,‘²˜5’ŠFÞ 9Ú¼@bFí¦gu$B`bÎz€C‹`ÈÃT ¸äay2r d/[íµÁ€óy³LƒR9# 2âù4#yÚÚ¾¹@WÅ\ ì«*ezóÍeñg^,W˜(3‚)GµrÉQÇ~ÒŸ Š T²fϤ±Ú.nõ™i$¡—*—Z±‹aÖ”è))M,Å‘FJ)ƨTV (Uáf»( .,r}´©’„zŒ=s@Û%Þ-6Ú³+°´ÒA›˜¬È„³Î³TÆ–š˜(m›EBà–ÍèÖÅ…ã-.Yœ ­.,a@Žj‚À ÀÜ‚5¥V „Ù¤ëêF5 ƒM¢!ã,"Œï $fÊ€1E\';1·uµ“EsÛlÀèQ¯-æaÎ,GA°`ÂÂQ@å‹å ‹Ø°ÊÈ ·½X^!«ÀÚPT¤à­î6£²ÞÙ,Q‹šæàM;„V¡Eœæâ¡ 2hnù݉^ö#‰† Œ) ÎÐkØ*(,¨ƒ'4ÉF@ÕQ8…@ -ë—6€ƒ`@°ˆ µŠ ÃÖU¨C‰ÞY J2¡T­Ä WZ*Ó«%eÅêýv‘šm¶ØÒ9*…·#ŒbêeLH¥¸¨ÈVõW~õж§¯‡€½­\¡ºbœØgƒ§ ô·Ãm1¢ö,Cb8¬òBöE’pâ˜jÃ»à†­×¾³`5TœEœWj…¬f&”b)US•R»̼6*¢´µ”AsƒRc̱@x¥B¡K(¸ºòÙ8ä«›plȬбy€U+Z½ ÈÌa…HL«]ç¤y•l?lËvø‡F ëŠy]^j`ú€†PÞŽ«~ \ˆ¹¥¡’*q´VÆê°Ô•lbc{%@ &U02NÀPA9a[ns}¦oÚ)x–G¤dÎÀ†MU :ËàA®ÖJU7К1Ù—U•(¥ßzRFï«M RÀº¥ò7p7q1a¨´¤ã7v)Vs˜ag£´²½ ÝùÒ¹#*ƒzÛùXR ÎÜ.Эéé·Ô“)g|w4·RêÆ›ª\q8Ï"ƒá"ˆñ"oOåýî¿›•õ?KŒ~ßEÏkm >Wƒ½³o¹ã7[ºÞ_ßߺaœ¾ö&òÒ´.ˆâ›Û©ÇÄ¡„d ­ süqÊãúƒÆX}G:J!;þ‚xðJÎ<2–ãŽ"ã <º×›64Š´›ó¿±Ò§ª1Qb‹ä´PX1VÐDÑR"Y[ZZªZ©[mö{.:Q(¥¬ceµmÅ¥Û{¼þca6¶;ØÑ²–•©X"Ô¶Õ•¨‚–Õ-[K*6ÊÕJ—)[r¥r6·3[‰™™™©L&90¥m2糟«^O/g“³·)žŽ—ön;ŠÀÂìJ­/i¥`ÀÅ"ñ–ÌÆ×j×3KÕ&iõÜâóJžÞ¦syÝçöaå¤OÉ‚î2Éd Õ¬Y4÷jsA” ÙÍÊÞ ¾ZÔ‹ž£KÕ¯¿Ž}Ä2€€/tüh6¢#Ú]cà ™ka«$¢„P‚@ ¡m[ç6..¹UuœŠCŰ0H$¡"¢1Eß³¯^tß~­ATQQDIh&]ˆ?‘= ¯:e*¡;Z& ©oI=Õ/„å}í –ýh¹sÿ+úé~¯ãÿ+èýOзæ¹f\¹nKj¢HLŠ#‚ΩRrœ¥×^/VVêK/P³íqŸ—¹ÿӸܾ Õ5j½§gkg13 ÉÏgƒ³ôü-nS’Ê\e‘:^Ï8%ZŸåa‚ ¤­³Y(Ÿí¨OÏ÷Ã5ðý¿Ãðñwø'Änt6+-7a³…FX0ÑL76*½àÁT„!Ñ€Rˆ3s ±X9Z6×Úøû½Å:‡ã‹G¥…1Ð3b’)Ú^¥ÁÚÊsÆüÜV‡Ý‘ù}‹×õqû¿Øcï¯(€øVX<³ü*ò¡÷.ı´]ŒôÜú2¹BÅÉ)Ó7_˜R£Ó†¡&BqjÂÒà÷÷@zªÁ«ø~åtðyóŽÞãñ":¯èáQÕU>aþwÏÔ|]EPñãâîX)(¤QÏ{D]áØÃ²%™ÇkH½ÖÅ ¦V$Jµ am©JYÔG%˜u&VŒÒÁ|)Þˆ&BPFV-Ô`µ³á>-_’ßâÛÛv>DMáí2SŒ4ž§)ˆjÞ8&í™q8r“:e«†¦ú1ÐÁϨ9UÁའ¶×-æÒžwxœ xmÈ÷"$Íð=K4i«5r,ÔѲ¦KÅÆ,ù¦0oÖÎ,ée|8{] ±u´[ˆ¾ 5èaY±+JÎ(ñQ6Ë”€ˆH1ú úˆ€âû 48ÈV¦ƒìÂ+e3Q»Mfм\ež‰1pÌÈŦ5LÊÝB)a .Ía$V\n-vŠc6…$M%ÍÁ®’Õ¼ zÈjíS[Ñ/TQ¡ÍD*Ún%‰ÑƒÁÊ6Ôµ0)sZÌYpÔm¢Ïì鯕rnEñLß!-¾æh8qZhKE´0-Àp”dlqeŒ+I8U‘ŒJ*¹ÊäÞ–6lغºŒà…ÔÅ…˜mgb¨h¸´8º¦É¶DSÀjÀ48™E’§vLŽ0ƈ9Joh\Q,qµi]™ÄÎÀ&Á*FÎÌ4QIºFØG $6:ºˆ&F©².Ã`bél‰©Öé¬X.Ö³ÂUr Q©m–‚1j¸5°´yц€Y¢$Ò´.Ü ñ"j>ôg85Íu}m4Y缩Ø)R7ÆÓ삅ڦ܃D¨ ŠŠoׄ@á6éV8Ý´±$)X¨'–©_qpö´Ü)€q¼½¥ï…ÀÃM¢”QVØdYV¡³ô@©”eB -ËíE¥Ö²¼;YÃXb·²_‹«hn³Ó†4ØVª–)Ì+” @£Ò·‰`BBȰyvë·ÝTèâ -©$Zªë;iÎF5‹uZm´î€Nr7hšfvädï¼ÍõÅ*TYìÛ 8j†"ï,ç¹ xâÓ°ËãhubØahQ°Åë8 ‘ZÀÉ@H´1£›†ëÖpÝR˜âX\3p(»Ž º-˜+QŽ\á\Ìå—ž^ƒ£VÕ™‰9K&á*¶€®ôq ˆ¸ÆÂ–6Úc k޶Dâï]¦á…Æ*mEÄÙªŒq±‹EfÖy¡Ž)[maÜbô± b)Wdj à¨4%á.-TTÙ5¹BMq•lXÐÅrßÃP{bˆi±¹i«‰Sp½jÇqC¨k‚ä>W5–­&’À °¥“+"¯¶w$ŠKU¬Œr±]ö"vî–ÔlƒT«2¸ÛO¬2ÊŠ®•‚BJêW"ê3g—‹=Hœâh"ê÷¢LPæëeN¯/A}`õzß ß¡²õ;+Â8ÇÜ `k5ÖÂåùšq:ÛqÅ2ZóþÞ¹2 e½„úmSÚ­/Dš‰½)¸,ôUeµÈI؃ Q‚Šjn ˆHæ)~U½[8<ÖöLÐe8ô …QK,˜`…8ØR¹8˜  %.ÙÝÑRE  ]¦3*My@Ìñ zjÝ¢´ ±%_‡QMÊŒXªÏ,<}oï}ÿ P Q°»0Ý :s­Ò ‡ ‚êînC½p2Ê™ï$wYÖÑâƒ!’íÜ»µYI¾“‹dÛ‡¾!`æÃ0+EVÅcWwÈ}îŒÊÂÖ&³•¥D Ð".U,iEZ0[#g&a²_½n\º›½¶†ëq[m3÷%8Î?Œñ`"g{ s3Ðzo½þ_¥úï%°n·[m¾Þݵ›­wv ˆÈu{uwWö¹2Ya)îˆ ÞõiÆVb×j¹!LDI–ˆ›š³#Õ$¥l!ŽÄ[»ü'Ù~sï?vúß©ûq÷a÷r ’ ZQm,k}^\Ï'>³\a˜––­k\£¦8· 2—Ú5·×·ŸG³<œï^8Ä7g~æ­T(¶¤BÚËjBøaéŠJŸ…ÖÆò_¾Øµo\ ¶ùhó!ës>ZÞè^Eù€úï¯nøÛé»Ü“¾ŽÇLÃ1aóº<áæ ‹”rbw$â…A$@]_\ y†›a˜©YÂÒ¡ÄJ ¢—k­Ð—®Õ‚ÜÀKPQ+£ÅgRÂ<ØÚœVÚ—Ú¿h¯bÌ^Ngõÿ{Óvó‡Áã§%ÆØR²„²µ‘„ª'–ÙÄ…•§!t,½e…,­—v¼wòòüv^[›êëKzö<¯smû.%ÛߥÎþ?yú™÷K¦)ùþb¡¢yn爫ê¦lí•û]îÔ£!5ÁôïŒH[×»kìgwEm\Ž´pÕYeXnÙ–²­Õ£G XláM•†Î  0 lÝÝnŒÅãS~Owï;?htc¡—óí¬ÚÑJ>+¥©Væ¼Õ¥h,» ¹ÌéòŸ{/&ß¡ËÛýÁý‘ÛÃÀë@ÚQ{MéKÚ¬(i?¾QH&K¹^›SŸîqÇAGÊ3Ž}ÿºð<¾åÏÌ î>ƒCžâ?ÿ¥ÇóÿŸÓdÕ·m»ôz†;Û°-ÙŽlæoÇ5ÆÔë˳ÔoÏá}îÈÐAQQ2¥QXE"«>oÑñ¼|Ž>FÛî’žSÙ¼åÊS^IêhÎU‘œFÌ ™jÛ–\¥håL ƒkÀÆ€u€S ‡]3ÌÚíEî=0òö›ÕÍámß5¥¦b·W2)fë¥×xž§­BMá×S;9êûët•çW¦‹‰ ~zåŠ-y Æ0¼HɈe ZÍÛ5¬¤‡;íB`J¥t*ÐŽ9Ë´sÎ`u5’PQ&ù;j÷X P-›…YÓ´ã;Ü „´.ϱyÀË£„ÓŽ/¿Ldm¬S…z&©E0µ¿„¶ R—€_{âqŽVw¸® A®žPÒÃ*ëi…«Œmô˜È[fèÙlˆÕ§™ÚS0âÎ8g­ªãB˜"€ó»Pè6½ÄȦlö/6L‚Ç7Á·«Î$ ½”Ep\H¼¥±à´w£â¹—*vL£Æ¯$³vè” î¡æ¡F‘ŠB`ht± A„‘£+ÖžEBpîv}¥RD&3q)2Š !çôU¨0ˆ¾,Ö|c2¶ØmK [,È”½_n‹Yõ6Œ®‘Ó"W;®ôivµŒ³–¼ï}Ùr®âp®Ib•Ì-¿Çðà`è£t¦ü*‚¡R#À #Åè!QEÚÈ ’[…Plìlñ°qmõQôíË[cTp¢´26eа¥ Rµ¶bj.‚ϰ®•†„¯‹ Ët°Ì l¬ìu{$™ ”5d¼„@Qb´\sE,0VÊ¢Á…]ùfF—rC’¢ÂëŠ% -ø—GÈV··ü6±‘£=(¹Ì›oЄUž^v`Êî,0°ã6&¸ ˜q‹* YÞŠb£&ϱ „=ó¾W›–År4*ª–t!”ÉìUlÔÛUY•»¢nö®Ò,î×mYj[%hkaNˆ,38­i`«ž8½5ª Å%(p#kT<]`Y˜¨Õ&‰ˆ£êéd¼äØX-œS‹:Æ)[Ó Œ5¯ÖÕ“l­E”,Qœ¢•pâÁ(A"Zym¢„Âõ \5Ãu¬V™Ë¡ub„⯜ îï fñ¡™Òú=¯O¬oµv%1KCVn4ˆ"Ñ[­ï“£T.+”J È‘AqPª¯i .4k+H’2¶ÃÅ0àl3Lß DfÉ#&ת‰GËRê›QF F”flí‰HadÒÆ²Ò6 Y“BÂPÞUkf*j'gÎØl’¦·ÆÉ¨m.­g!Í %ˆj˜ P¡Y1㤊ˆ42=L+R:GIQ£$\<ú[Ón^||t)ÖÕÏkrïó·ú°Ù• P¤„÷ø¿Êø¾u6W>_çÿWýŸõyÿ÷_Œ_à—fÿºŸg¿þoÚO›¯Ëµl»enFÄ(ò‡ÜÖÕf­ Èñ›V&ÚÄ=Î š’õ¬½‹Q{Òõ:ÙÞ¶ÅîŎ/š°gcµé"Ò^²A –“ZüáçOv é0ŸxýmŽßyë>ƒ|Ý›~X¼\V·k-èÀÈ¢ÕMwÝñ¡È²Ý®æþûÿÉý/ûß×'hˉÜìIǼa[ŒyV¹LþÏê“]œ¯­Jí`~xñÒÑR’ÆQRQöé8V*€ÅPý”(lýòõƒ%ݦV£k7޲8}­=h‹ôЬ´b\ ð4zˆ`"µë°äÝ;1¨À|+±xY²æ[’äBmâ—º{¾GvîóÖ{¹®rÕ³F̰®°Ñ©É†Å2rW%y€!ˆ:< ǃBîwX2C£œêÿw÷¹ýË1w;R•­–òkÙUÚy æ¦ß­¯OJÉ OzÃÈm¶‘ñe„ØÑF×Ù¨ó™$ˆÚõÛb²Áƒþ"¬zc³¢±Lc âúþ¿s³\kìyƯO Äâpãuœ7nÙÂhÖnâhÜÑì®íF»êÕZ6ᫌÓÅmh…¢`:&Ý„žðo/'K´²¸ÒV›™.(¾§wÉâ›GÎúó†tmNbŒ”öüi­‡ÎC“žýç«V´Žµ„âöŠûí»=½¤ñÈXƒÐà€¶°vªV%O=šÁ©ˆ1gÚȅV½1¨7¾§FIC8øx…Æ-Eˆ•sùù»WlËšZá`-¡È„jkYÖž»pE׆¦FŪºmXJâ+D ›.1HIÔm aðÀ€<߇ ¥vÄk¿m"Ú3,$Fæ¥Öý]ÜuíîíC£XÔª-V­É8"3V@5D¦d­€e- Í]–j(É Íi6®ÀZÔ(ÀŠÚ±q¢(lgmbõ²{ª”5xÃÒë‡ÆG6Íx¤^pFÒìåéû¯Dr×> §sXFŸÃˆ¢€èÑ”b{ð!D´ SäÖQä`½sjáîÃ7 EPR€W2(ÒƒƒÓ6k¸T¸½JÜB“kQSNÕ­é\2 Ú"•˜6Õ3Xi´Å©[4Upi£ˆ8ÔbUTÁ"z?OÔ Q\ Æ·§$àKÒ±˜<Š… Ü)¾rã2ö@¶³ÕL¬¤¼Ö›‡þ6¸7]§4iÑÎ&´-²ßÁV´UØPã £ƒM«.rª ÆâØÆÚìMÊ–yhT;ÄÓÞ×Y9€’%' €Q"9¶Šp 7{­.âû-j¹¢n¨—im]ŽŒà ²8£)\ I©}>­…Aª¥ëk‘À±Lâ˜ÔàhB„@.;ZرJ,´fˆ°; ‘šÅôƒ6/ay^¦Ü+C2;W]ºâ^ÎYs·ù»mà€ðŠ€Çc¡¾:7víÌlÖndÁVæ´Í ðø®àŠAZPDÚ³9c|)xpóŽÓöèÞ¬]^{,íÎØÍ_OÔ•¬!³eê5¬×®Ó¾„Lllãm²¢·JK=ŽÅu¥‹Ä=]VÄh¸.W‚–9€h«HÈtÚífrìšï·‰Êé½8Î×0!¨ 0õg.+mj]NVî!žóz¬P/“qqJ¡ëGž{^ÀÈqAO}\]ó{ç{-ié8ˆ©EY¦12/‹:Õkg 0> аênÔ­ô¸¤ UÌÄÙô¶ÚÍjm 1Œ ¨®Zf[ø?ðWùPƒSœÓ®·5›Yº¬ú^‹$Ká7 ÀO‡.–;hƒ…KO0—ñ¡çMJ|ï—ó¾sm¦´aš§ÎÚ»|ý÷Û[á¶Ó}kòþ¿Ã©c–ÀxCoÌèdͽÜõ?ƒÁ4ŠabÀ½ yÈ9dñ®-òe~÷æëæ®í5Ó;jÙ„ªw·v²ÐÙRnÃ,8jáÈËFpÐÃV¬8rpä¡aP¢”4u¨ZÙìmq9r_f¯î~rþC»ýÊ}áeUïUüS#vµÅP‚{¨ÈßÞ”ÍÈ"÷ Œö+ÝÙ¦ÊLÍN¦šàáÌë‚T +ŸdÖË¡fRÝþ´F:{àE ß â¾Ýôã< @ sÛà=%vM\©”\/a…\jÏ ÐZl1vµh÷¹z&-v›€ªaZb/)¨šeYsWPÉÀv·j½-4Ù¦À©L?o{àÚƒ6°q F)K#@¤l†È¸÷MÒ!t‚dÊeb¢Žtùœk,.F`]„k2&h—ÎYHº:F­Rk«ZËEò£J51r6)=ïøŽ„¡r*EÃ`MœXTX gH ¾ä†Úæ1e‚l6¸yz>*Z+€¨”Z†¢ã +s"ÖiÃ]òsZMìÕA’ò— I¦ò2ïI´Û`á¹ fH½…)(rU¦ãr•Æà‡­æg7" :™Ë4A“5Ì…$\d:R¡0$8«³‹{,.¥àp—¥”ž(Ͱ {ì‘Æñ.»Ð²ƒ´8¤`RÊÕƒSKKR@ÿ‰²bC›\ÚD‹ˆ¨3²D»ˆ-]‹ê”­,‹Œk4ÙXW!®1F­.j)7RN T¤C´Ëج . ;#†FÖC“» —ÕTI•]¹:ci®.$\¾E×zA…µ®ÁÃÙžÇÈÖ²Ðak•³ŒÛÎf*0õ6ÛËÊkˆEä½iœ¥K1 ˆ7aAm‚‰sÙ…ÊÉ´íI VQy¢QïjŽbø ·à  ¬5¢– >^CMòZEòÅ­gãh¢»PDÓYKÛóoZ¯--(¯’F€‚ ¦†PŒ;2H$H–°É¢h/ªn4ÁœŠV^«RƒAíT2€¡&ªÊ@¸®Æ+c¡5*ÒªDȶÊ˛Ŏ×~.ÃÓ;‚+Lm²6ØÆª&Úi°°6½II‹æ».YlÍ ’X©0WY{á¡ ëÍíÿÑöÿÁü?ö?ÅûFßù]|ñÉ{ûKŽø¤_÷=?HPò½þ×ÊšÖ<Êž’6(9PÅ0Å;8³eÞÏÇåC›ÓßɹŠ4µiZ{Ц¤“ýn¾Ò‘ÚÇtöžüííR'¥ñ‰¡s[Àë¾á³/w°xp®/™×ÛK‹YäœÏ'”Q7ggçU)І³eñ†ÌÍåJЇlÃV 6|ËæwÎy»Ì±ö÷³yÎdS˜úﻳǞxYîŒíñ?<@ÁÔü±|šÛžyàoK‘MòNü¿Eßž8y1ùÏ =§Wy†Ðóºåi?“šdOéaä>DZñ+Lr¹'ÿßäãUë™6‚ ¼jS¼:.~Uÿ€é3y%%¸A(q쇹Éí~OyÔòÜ,nF0É$ ´Ë£ rܧ*gF[Å­œ¥¼]£“c“Vêš8L+f®L˜laÉ%0 õ¶Êॴ¼P´³ÏxOIòýVŽ<}vaCFsÏKÙôE0R¢×>ÛÍønó>Ùî¡ØqØr½ÂÁOUïöz³Æfg/Y= wgÖpÖeá7“w7r›ÎMXÞpL9M”áÂJ^N)»^‘¼b8e®4ÎÜŸ%…Ë43 Jï$;Ô«ƒs~†mËSN;dç ñeù£–oˆ»öê:¶ä½óÅÌðªÞê!LL³­`.&ªMOHó KŠÙrT®Ö¨jçeµÉÁ’"ÖÖpð6„³j„‹Úµg¨Œ]VÃÑ…c_ÑLCˆµpú]«bÓM2±€ll)WÐLÒ(–º…7”Žª5¨-q&ئ2·Â¡œÅ(·úLJŠâw‹ -°t]iNΡh0±³Ú™¤ä0™]MK&"ºZ¢Áe]"Å,"h³Õg ´cP„f1|9x–Âé¦bàœ Åv”Pe–À< ÛMºˆb¨¬£UZÅÙAâglƆƒñ”ØMRgtÊ4ŒlV¥Üˆ²¥ÞÃcR“ÃãiE6|Ö)Zš‘Qq4ÃH´µTfŽ+‰`ê&ê€Têƒ*bÒ¯E䱸¼úí¸âÁ”„Üo;ï/ªs@±’8#ëqQDÈ+œçm-!Au–T´./a‹›Ôo-aËO`õY{ØKŒÛŠ1PL0È‘‹éê‚­09Œ º ]¨ÍÜ“©lè[jƒi”еç»ÜØm*¡À–½–G @su\š”bƒ\Tp**(.8ƒdÂe)‡×çuNu£‚Aª‘4h@)}:æÔM£1€ Œ‘°(¡ë,¦éq±˜Ô©¥°<3²‰“ß®‡—æòÐ×ÍÐPøtöýzjŒ¢Ü´‡w*Iâ¹¥¤8!Å"()µøH`¤QjëÔ=K²“×"›Š[ˆ»àE3ŒÞ˜½™Ã¥÷¼ÒÜ€/< ÄP6¸HÎkµ±üáMÝ"&bmG+I·Q4Y¶V…¹¥Äiu‹-©À»Š8W4m,‰ a`á…£¡(A¬) FCÔSL²¡ì°2•U5"õÛNü\dÊÆ‚ µ¶Õ2V«2è!l·¨–jB©­±È8¡ž/ .qUç‡HÞyÚž]¼÷÷ /h®ùéHwegÅŒÃ0l¨[. s¤‹¥)$NÚ•œKÁT¨¶Œ½„ÔMH T"¬êdñ\^•™E­6°¼L_"6 *éŽ2² N}ˆ] ð`À†=öоÍÕ¬Œ w]û`þ>Œ7 ô¢C¥c°:+Œ0*UÁòýÄáØV…ë\Í^Æ(e6lgl.­Þ–®TU/Ešâ) 1ª(–µó9žWËŠÖÆ†žÂkœ¶†ó—[eo‘ŠC± c…sbígZ®¨ÀEZ[ñAPªW*âb›c}â²@Öm Ã~Òˆ ïrò©pçià ×..صW~CRqßqn5)¶q\ÎhÙÆû´ZŒ1kD°°,ÍÚu÷,³ôJ&uø™ ˜!eÅ™¸òÞ´°†ž¦Óþ³¿Øýþ‹‘óŸ°áîõùôéÕߺ;<žèo5|^ËþÞ‘Ïÿ«âr™PÔ¿²abY¼òÐhdÅ+$·Ëì­hiBôµ$I²×˯äÿ‡ô½ŸÓγۧ&ö}‹Àåàô¸è¬öY¢«˜9ñ…*L©c6 U´–µ•»ÅÅ"„-/kMâêïµé{ÌÖT3,7º×¥¹Ö¯ˆÂŒß'k›É’ß5kK4Ê‹UÖ‘LÝé%­GiÍiAB°3‡¬ r\Ó|Z•ÍUl.ÊÔþó|_ù7ãÿvù1BPáåv\iT¾RWMN¡8a …šàóT´*Ó•:r¾¸øk‹Õ?eQÖžÖv»:¢9myXÁ"$—)z%7ƒÏhq·€dl!° FbAŒG^qhï_«ÑËO«¦ÚsÔÒí®¼¬ìµläáXVŒµVÊeÆ86Vî²ÝXUV…Q:וµYµÇ8 ºÁ;?Ÿý½>nL9¢VböýŸ]¸»Ð¹÷°àÐÓ£è°ßwf˜éâÑÓ¦3O¯ åšMÓGf®JËVíc^M\š‘—BFŠ®ÓÐ [] îÐÞ_8†!v¶çÿl{n×´­^+Û&¡L˜l =§.áVoV³K—šAãwªw9—ž//oFþçëÏ<Ýô8§CÎËÛóÞæo—Î, Î>÷9®íw3{Ì~mƒ;ŒîÒïqÞj+Xš^niJg77QVÉšTH»Uî.n¬)ˆ“àŠ#é¿ÆÐ,z8…€c}³«Ð\Z¢öÃ< lí(àÎÞû-&ÃY냡UÌÕuzŒKÁjéžè³ änÁ´ mXŶ·ègj$nwÁ¬ê­KÆ2õŠLª×$D³Êئ~XIH°!@R¬Ä]]s­ÈŠÛŒÄØ…µX`S*3›=èÕ…®õ²Ö¡­@744œX®gl( ,†%ɳÍäaìÛ‡vØÖ¡í˜¶³4ºÓVcJ°—G›iv¬caY[Y^šÃ«+ÓÎ^ì8: € Áƒ•ƒ)€ªÁ@{B#%x/™5]èûQ„Óuhp7ÃÕt1VØ­ ÒÖRh)¨ÁAg8»UEs0^éŠÔRöи¥Å­[`b”Õ¬&l®0!Í«DPøš^Ke–T#0Ê’$‹ÛQ¯ÿº3_AÀ`œR â‡6  ¹e®K!8#{í«'·¾mak KRkªX7DÅUb(ÚËKƒà8R,…€ëjRFõ/$X‰ ¨5ư-‚Ñ›åpÌ•eÈ;°\ZÎãÐØ ÅfHš€Â£EÂѪYX0a¶ú&W ZÏerr.Ûêy=ÎßzÜgsd™ž¢ç¯m”ØÒ4L˜K0fô˜h¦‰ID²Œ÷ð±©Xº‹³%=˜R&D¥‰¡%))C"FZ²Ì«²Lª³F%”iA,à e > =ƒß„Øà±)×'f ”e9‰‡cWQ#‰BÊRÊhB‘`Ì«f ¥,DˆÊ10ÄPðÔÁ4(PD–P¥”¢š0H˜¦˜~„ ¢˜%(¢”¨ÓߘKU‰Ù! 9J&†”,F%6¶Û’†@V`a0)f Fa)„ìJ'ªD˜lY¡Ž…‰…œ°4&ŠR‰DUñm)¥Pš2Påë ›èØDU›–ÛlÔÌ_ž†LQ‰¢Êw¯·hj$سfríçÖÕ¼«6b­v=©¾ßãSú”€)ÅÍõªÝC ¹âˆ() • ƒ‡„àÕFbÌHŽ(Daå()BdGÚ×–çÅ9{½±ÝÕy›®sñ­î=ãkmç;Å.(–áÃ|'¯&Ç¥è[½û@=Â|Ï©ð$)ðìYŽŸ¾ÛG“ cW1••†V„Pu¬M@ Œä’ÌŠ$QŠ” U€ÉX‚1b£FB¶ÄEIII&îRq”¢ÚŒŒDx{ýÙfÿCïùï£ü;­ð€QvwBzÔE& ¢:aG-NÇ ë|"ÛþÏ÷ðar‡!ä¾¼Šˆ»ÿ%ÝÇÃÕÙ+Áä1¯7<72ÑËçM1&ã¹/¹pƒ ÁXò # °H˜jg$ä¿æËý] Ÿÿ_ôõ©œË¢þJ""uo䓪º~ ~ÿ ´ç–ñ{UŠc5×<Ú¯:qètö[Dôùn'ü¿¡JÃ''KÞˆIF# ÚJDêbí#dØÏÅ¥GK4?¶9òÃ9±CB"H6_õü ÷\^Û–bÕ”˜†œ+B.¼GL½ÿ¨Eyó­9ˆBpVð¤NŸ{Ø8}bè¤ÎO;Öò/`‚ i9¨‡=ôµ•d kÇÂA¾ÇÅÐ4ªP`ø1VQEÔóÔ0­ÜÒüÿ`’ô[ãžìSæ 5µì®áæCç¸ LEV(ä"q–JDIu,}\dK°V¯ }£\7QzŸUï¿—?i³{ƒKka6ÕwNÇÍë|8ë.ü€=GÄBßɳ[Õ}µî€€½ <³ QÃ3ó8Û4ïA¸7¦…ýh¥#ãr êÇ…?X}ˆ >·Î¬€h¨-Ü 'ÄGÆ‘çûÆûóttõöfOªŠïñ4‚úCì» Âô×pdM÷eyz }(F‘s@UABö;qد0ñlÖÉKL(ªhoª¯‹ÿ:×{ÛÔ|/ìüŒ_‚Þï.¯“°O3ËÑ:>Ƕ¨—=”SºÍñ_"£ßèO?»¯S>‡ìrÅàÀó®ò2ÛNM©^ë|eÔ®Ÿž"nÑs<öRyñòxêê2^×ý<׸í¡ÄŒˆ€r@ ï¾úþWwJ½dÇE:®ËuÃÕë.@ÃñIØÙ³ìm+m†.¾šD€æª/ú-ùXPcðµÎÏû[×ó¤À°R ¿ìòÕëz&¶̉֩z ¾š«=gl!á!Ð\D7T""NoŸèc\¨RÒ…a@“¡û¸TˆµchÈíËCÂÂÅC»‡»I{6‚jÒ†v}-ä¶(~ѧ$,„˜À.ÈúùvšŠ{Í}M×ЯˆÜk\Ú ¾ºQÂB—Îʤ”ÿCÜòp:rå·Ã Ÿøž«_Þ¿—A½s/^Ë‹)M¥n›Ýµ1ÍîÆ‰±u²··~/0Ýðß,cb¢Í@YÒî@0Ôˆ+ùZ¶…H"ƒûÿ`›­’Hð²A²hTH2@Q`ª¢ÅQEŠ °XŒUˆÁT*Š(¢‚ªŠ,UQVEQV*Å‘b‘EˆŠ,UUX±U@UU‚1EQAEUX«) ÀTQQ ª E‘V H ¢ÁAbÁ`«V*0Š*Å‹RH2@Q`ª¢ÅQEŠ °XŒUˆÁT*Š(¢‚ªŠ,UQVEQV*Å‘b‘EˆŠ,UUX±U@UU‚1EQAEUX«, ÀTQQ ª E‘V H ¢ÁAbÁ`«V*0Š*Å‹PNŸ‚à9bÎu½Í¶[êÖrø+VþPš„ùzõ#ÆÙ¿¿cä>&_¹A&= Ÿƒéüÿ 7nÍ¿a¾£¦·Š¼_iJŦ‹¼Uóëz‘òÓé½*¢Up®7çwàíeÚ—¦×bxUý¥ô÷4# …bsçx!@¨Š,‰!jP¾† ôD‚ăý?öÿƒîÀ7Õ1RÔPŠHE‘""ŒA–¥”UE¥¢ÕU«)iU D@R)Y$Pµ-E*¬E(–P¶J¨´[ RÔJ°Z–Š©-E `#¤‰  JE©h´B*RªÔµe-UUX«R¥XªUR-TФµ-YV‘e%¢ÒZE$Š1B(‚,’1©eIlÄ´ª[$X d„R"A`²Oô——=ÕU¹>nø÷uëâ$Gè‹ecæ<ž*“¾–fÛ‘’È,1áLT‚ÀYÃKh0²8ÒÚ ‘‚1•… ±E$D†$YR( bâY€‘±– }TåÿXÐì6Â¥±)E*ʪ«"•VÛ,-D¶L „,C H#E¶­¶Ø•B2*¬AT‹‚ˆEUˆ¢$"Å^êRE"É ) $ "#`÷ØVI‰$"F6ž·ÊçmT-ŠÛ-¢E¶$[`%¢G@a)imYV•¤[¥ Rª@PJ€¨ @AÁQë‰Hþëûÿñ»ßúý£ ò?ÿÃ÷½d©~» ÿ>ÆQ ÂD›­ÍnÌ…n'Ï7íôÎmPã¥Ù²Ó«ãû¯QÚþUÑþ‡ LcŒˆœÜIé`Ÿ*÷ëíÒf‰7R²Ø}[!ßPådÀ°5©<”ï²qCõßÞ$IúP³! 'aQ~yýô†¤²¢X–ȵ$²"Ô¥“òH I™Ûö‚0@c°@VÈ ‚@”!d²’H–"BÏÖ ,@É”‰$ŠH6P‚ÑøvDƒ(gt—( ?§@^Ò `!ÈÉÁábJ¢"ÒBÔE,J¨¥‚ÒE©Ø€@(£‚"ˆÀF¥,•IhRËRÒZZJ¨ª-JYUQl–RÔª’‘0„Y!F$Y0–Uбd }’)ø5ºÀïõÇOºñ¾/cP;:øŠÙ×ç蟢qJð·û_[€ÐA ÉD|\ÛomÏî´žÆÍÄ4¦(I ¿¢RLáûzdùz¤Òˆ ~WŸ¯ë¾Ö;¸OùŒÏ™1:ïµå¨z ¨€0¸)I—>›ž£½”ÕZiZœ­¥ίm©À£çè1 öS]T°¶.a$Ho-AQO{Íã×âïwŸ¥ä¹»Ç Sîn™þžSAü† ËÎù*œo7¾¯ ¹‡”‰å†H.f[ÁJƒN­ç ùè®SÙð6ü YÆå¦C¤ö¶ò’ÍcBðò»Î[|cé/{ÏÑaéùb™]&¶¶þÝõº‚¹©Á&U¢âÒÔõå²”íF‹RÊÂ\Ì0‹LA! Ý$“IA9Ï3’Òeÿ“ ‡1ÀÓASóƒq^@öh™í(†Æ[Úf2ÐR„aAÓÝÓ¤ât™Ø4®:&†ÿY`˜í­ïOjÖ%°º`Цfê—A/Ù@â}ßOÝyœßðå|çÿÛî‹ÝúÎΜÊôiâD·V—/¡êU›EüdZýol@óg ¡Gè ,‰P>DˆþâT?f€¤’ü”蕼ï¦è D—÷Œ÷*bÂÔ•E¤¶TP"ÊØ©õšÍxÞ?{Ÿ³þB `ã ;Pß$@›è”[´üÉ´F[R¬ZA$U€ ,’,‚2 ±b*ATŠX±"+Å‚‘a¨¢±ZeP´ZZZ—ÂvÃkâi®², `( @$Ea€@Æ`ª­EI)B‰™#dˆžHè@4H b"ªªª±Šªªªª¨Šªªªª¨Šªªªª¬bª"ªªªª"ªªª"ªª¢*¢*ªªªªªªª±Šªªªªªªªªªª¨ ªªªª¬bªªªª¢*ªªªªªªªªªª*"ª*ªªª"ªªªª¢*ªªªªªªªªªªªDŠªªª¨ ªªªªªªª‚ ªªªªªªªªªªªªªªˆÀ@UUUddddUUUUUUUUUUUddUUUUUUDUUUUUUDUUDUUV1XÅUUV1UUUUUUUUQUUUUUUUUUUUUUUUUUUUQUUUm¶ªÛjÀ* *HT©!B'Ë@h„!”Daõ1âÚãü«Ö½2$tëg‘¶Ö-@Ë[®²ÒÈJQ­1Ä yg«÷?—·ÿCq{E4†ò)$륢<,Œ9ÍëïÁ4ÖwOÌ@VÒ$oâÖBi Ýa=ºP{h 0Ä.'»$̓Ùe6ß&·Ô€²(,’CdPT¤eKˆ‚‚Å  È©!!R 9ŒYH…-ƒqíaŒ2) ¦M&7N×WbÒÙ*ÃXÊÚTKldp…`2ŒD¥¢¢8…T)„)*–È釳cZuÚ†ð6©Z,%Š Š<½‡Úµ3Y ŽýÕ”À­I"*Rˆ§†¡Z©ÃXHÄ"­.ñm–ÂÖLž˜Ó6Ñc+€%Pw,ý¿©É~ÞÕýä䇅½$’YADÂ$’a;¤ƒÍ!î%DçÜ€ÚRÛ)mU¶Õ‹l°±b"ÄEUV1TA‰EP"ª1Q(¢¤Im´±m«b«!RBÈ‚±DUF Æ ",DUUcAA‘TU*£bŠ*D"ª [jÒª„E(Na0@{ðƒ¶$Dƒ¾$"@, °¯Ym`ȤThX£DH"C&p*­«bZ’Ø[ VÛΓY:† A‰$Yb ”,,H©°Œ„±%@X&„åxAÊ$âA¼ÿ;yÇiœ¯Qºù·+}»6˃ý«Ê2`kà g=¶Ë­\Çýç” 6Äl¯‰Ìæ„æYÆÆæð¦³Û–ú$†ÖŽî°žÙÑ+Bþ™:I5@8ØczZZÀ¨Îè(hY¼Û3äиQ2±iYmÉZˆTóë1£bRÄ%Œ£hT"DdÒb™ J-¬R1Q*ÆÊ …J¶”-•‚ª‚ FËab4©R…«->êéÃV¢=åþ^¤± ± ±J Å… E瘄ÊV¥¢Š[¤ÁÜÂJVµm²‚¢ ÔJ6ÒÑD[m†S- ”O6ƒ©†„vÕ• cJ¢­”¡F•Õ¨e¬¡m•´l¥ZEÀR2dŒcRŽLJJ,`¢ÿùË„DÛ ”jÖ3¶&œ9s¡ƒf6&\Nšãk´{–Öî£5Ôî‡ûH7:2í*C&+ýë,áÙüÿ¦sp}J“I;+Ìoà¿ÄÁÁ,rþ£ïëpÉýéJU¶‘÷|†Bøy –‡òL¿<ÅFà3ÝÕ`·Ì”Uõ¿·-ßáÔT|l£¾ª*$©ï<ï±ÂÚÓ> ôµ/óc~2v½ÑÆè~#5'Y×5ìr×´ðáå|Æ3 eáA6ï#R£G5^ÓŸwWÍÍÀ~kò]dÙ.9œ{:(2ðÚ¿ò‹ÚĈê)j_¥)«gG¿ÚÞ( 7¾c(ó ¯JÇ*P+´ô3ª‹­Øø·W؆*#§Øó4ç>Ñ΋WA=¤óÅ¥ªçëg*z®‡z ™pÚ?G/£âÌÁ¹cžX¡À¥šL¨õÇA–$›€€UM¨<¿v§ÜI·ý¢Í*ŸqŸ*”TY–s™Ak¹U²\(&CÐWhø]ê­áDIý UbJ€² €±Où4ºb[‹w'Ìð§+ ìs~Î×òðr~¼’­ÎR=>úÄÍYî:š½öJ-ÑòÊ*‚m=÷•ØmâÏæù¡åÈ Õ )~âHò?ÌqgéÙó¿Å}ΰ‰ñ$ ‹$‰©I’{³t>ãH‡µ‡è"BOæ;ñÞïêØ!‰·g >µ±"yoÖ©ž§äiU@ŽPÒP¡>WèÉò+E4íÌùô?§<Ý]#'uð/•磚8¥¹ëÕ@®Céß(ŠhüÿÖ‘ýyd2jãÇ~— ûËt"¶œþ¯‹MJo˜êŠÔ«çÓzy&Yl/­õæ¥oª«ÓNˆ3š´±RÅM˜Sן»æ4eCÑ•ãaãšp@ ÂìÀN{pÂë}gwzÿÎþLSÆrþ벯‘ͼDÎìJÿ̾ûÞQõûr탓ܻžt@=ÞðÏi™”·àÞúÕîLnûÛþÝå@|>‹«¼0÷½·ç¨€ƒöÄì*•*¡JR©UTU)T©*Š”**E)%)Pª¥"¨¥UDª”QTU ý|Ïô¹—öÝ´Ÿá€LPá(#¸$(bª æÒó¿è®òá Û&å¿Ù/ýbäºÙzƒÄÓåšs”ü \ó§ùÎ9Æ­–§Á÷”¤Ä…DÞòó=½í\H>±;ê*€ïë˜‰Ê jþ¹º©Ø@ ¦-Ý)|âêó¿ ù/s’ͯ_y-Iå ~˜€Ó‚䈃z*wê((Z`ÉþïúŸ¥ñ¦èA?_#àÐLü‚~ß̹÷¿ûÝ.h §o‘ˆ¤в¢dE¨"Ù±~RÈ‚4½ö× "Ô2Ð{Øäwš8ƒ¹Âˆ€ÿNäÛó7e¨s#à6Š^ÅE¤2ó¾¯êíR_dŸ¨ž"–>©Ó÷9¼ØÅ­x†ì )íÈ Bk¶.?´ÆP> O­ü¼~d:–€×‘ìËP½¾ÀMÆië)S˜V›$UÏÈž\MJ–Aô ( '掜Óô›6žû«3êV”)J5?7ŠS < kùšªmÿkú›“µDYUPXE"‘dPS÷ßÑû}Ûs˃þ“×ßßV'ŸýŸÎý_[w{Êë@`þ‹â@{ˆH¨Þ˜ IBX‘A*"GýoÇ@ãDëUo ؈‚¡üpÛu€PAOWÖvÈq÷gt,™¢€9 ÀE€‹DD[çz!=Owç?÷܈yÃÆ¨#Œ@ $æà:jgCuº!JP)§ïkTãe–ªu=7gSã(¶õÊùg›y2Ó™?Ç:©Ÿ{¢þŒ¥*R”7®FòÌK}.ßBOSÒ^öS9†y ~VmuU³˜¢Ö´°‡üÑõÇGÂú]_³æ;ü½ßýìžsiOðùŸÓ}üгÍ{ªºÏë¼Ë TUަ«å‡Š—*ImÅ'Ž=âÄw@ìïýÙW—¤-Œ½ýºwôÃõÄ‚yvkþýtHA[«÷˜Æ2’Àq+äÈ;AYüA‘wé˜ R îí~ɹñr? 8°ÜQG9ã¢BK"FÈŠ€²I% ¼U¨$a,a1  ì5Á8£cðµQGú½ùÅQÖ†ˆ(¢¥ñUªÆ‚»}[ÎþòL|Äô¨µ xÑk0þ¦®š ‚Ò,!¬"~fqˆç¯ÿ=¡kÃñe5Ì]8±ãš|ëãŠÅu=cŒ1"@0€ ‚€­zéÕÃ×)Ö2éæž‡Šs «Ô.q“}/€°ðW ¯ Òô8YvGBƒø9˜…D—’Ä \gÔƒ†MRSe''nf@0Šoµ:þ!‘0špD5Œ4 ~0Ó LfaÃ`Ád›®?âîÇŠ!ûùš}¹a÷ý—÷ú‘ 19–𪀑ÖO©šòG_¼5} ùyø`ý®/ùmÝ¥æ·m2‰û¨e@ŠÉ–ÙT¥TR”ª•U%T•b[h¢’ŠªIT‘K lT”¥*U*‘VH¶×÷;¿cð㜢Âз™§ú?â:õ(âöÓ°m[^µÝ¤äu’®œXjµµ ÁØ5×w^ÝqDëÿÃoÜó\ÌÀ˜D8ú%%£ôŸƒÁ]œ8hRù% æøÇz]Éh‚ ´‚ ¯ØîðÙò/~öþ³û²·ï²?»p" ‰ÿ÷ÞþÿUèDézs@C¯óÿkAÌú™¡Öu ôüÕˆ€N¢'ÚtðBÙäˆÙòA:«¯•(ÒT¥õ¸Ÿ ù7_ýÎÿÏgÀãþ§íšõß…òÿv¤²{=ê’‰&]³úÌ— $ üÛ—wäÜ ŽáH€ IÔàLÕ.Í~ÏÜúAÚúîzÿÈý/­µÉƒÀ<¡W±²BÀ°" A€‰‰Eh­¿éxÝ·Ûìö¨+{£úzÿÌ‚däì…Q* (‡r‚¿A´Dåþë©áù›Ÿì1%#øÐÿÁøÃžé{nj”¥–IK/V¢Ö½‰è€ô~e¼9ggßët[ü¾WÌÿÇÁ¢x ÇÅe/™S¡à8púo}_Ö1§é]»…⯗¦=˜ådìZXé´¼¢®Ë:v"¿ŸÈwCÕ@åuVDÜj(ìBˆ¢-Š  “‘„yˆ“fXƒñßµÕK`2ýe'“æ~Ã6MÌ>,bߨcþ¥ÿW»í|í2[c0:Ð |”:³Ø—\Z æm?:kc²—+óá¸>Íý¯žy.;ìõo'äü˜€€q!ëü Ïß9fxCó.ß}û&þש˜ø×ÜÌ“ômQ‡¸þó±zÿ#ð=z‡–@?Øxí’¿ð©†0BxðüÆè PþëµèªÆ$þ NQ’¿·@dHõ'ÙI$g›Íÿî"—U’%© ìh€è\’ñùÏžÖö–¾æt*Ãô+‡ÒúÛêëWÒäÃùŠö¬\µÉöcOäŒ3Ñ )ZS¨Þ6 ´©Íëò•¤ uÃîÁìá¹o|2ªf|C­– Õ{‹^6W‹›Ù_Vs/_Ž ô¿Êc&Cub‡³Ô|l.ydí¨,ƒ×ÿgÃÎá}ïƒö°g@äcØÅé¡!%Ü´§¥;ÞÒæË_5Ô€t<}1À+$IÓÚzº­´SÇþ~Æ1gÛè˜SLÞCî_2´›€?7zCW È©£§xÊÃzp1Š_A2Àd-@aløz¨ ¡ÊXðà8ë`HHs4ﳕCöü¶‡‡¼D/ùŽ›Q“íãý?À@~¯„ôþ²~ö½¾ŽqóÐ6  @*^U`†Ÿß_çùæýÍìˆ1  ±/ðð¿+ÒÐ8[_Áå¬Íê›tlÅ-VÊ‘*Aé)aQRdæíHp‚¿Qx€Ó#&} <-jmSǺZýÆ«‡ß5–hó#îôjqÐÞ:ËÒˆZ¸|GЫ·LÔw•W\31~²Ö›¸òêôdk^ € A9|žáYs/ð‰÷Èê Î@>ùo¹~ D“ñ^è ˆ B¢Š©ÆBú ‚Ÿ\èϧàéܨ=Íà¼Ä ì|n ÿÞèq?û[Ö÷ãp‚ƒz/¡BbË i,ÂÊæzgkk¥¼x© ¨xZµÄËŒDˆ{­¶ 4)9çUÄXëC] ûO'æÔþ®ÍnWó@º6(½Ò§F«#Llg/;ÞyÎOü|7¬çÞÞs¤äŒ:xJ àÖ¿Ôø‰ˆ©) øüj•¬÷6ýš‡Q=§ÝëªWïöþ'}q'ˆDT¯}VàFkt²Oöþ¿ïsôþO”÷îùùÿdßl zšï¯‡±1Ìy%µ›vZÙØ2Ǥ‰ÓWÛ³xi’&gðî«tßW+7«%Ve/l~Oïýˆ9|õ°p€0À( (¢Š <Ò<AËd0 æ1ÝÉ;?WPìxÓîWô‹þûæü<¹žÓÞýÛù|¾{ý$”„„ŒÌ=5O{GÀr|(Î-—›ðÈ>Ã\"ÐP†ÙpJá´ ‹Ï<`ãï²Õ½:²p°÷~ÎKÑi¹H vͯ¸¸«Žxÿ¦®ö`À \lB2’†¸@ßa™Ò+ãæÜ•6s<×uµüßþf¾ècõôãŸöÕŠ ¥â}uŸ‚ØzO„Óþ¾åŸf˜©žÒ¥j»ˆ{hYd¡±î)^ª‡<ßk­S^(ˆl€i£ E•2Š@T×Öž„@´’BDb)_Ùßy›¶$Äy,Š((}ÿåãPD¾t› QD0é4i,ÙÒÀvB¤ ªëª ÛÖ18ãš^àý?ìýóãæûA¡„~Ñæí]Çáú²P¤ã𿚄o´ö,"¡ë–…ó¿ÝNÄ`{’†¶¿¢œ~b೉öÒÐ${ÌÁ¼Þ(-lÑÛýÍŸ ñûîïÉûþÓÑùþ×}Çá󇿲ÕðoÔà Å{L„¼ªÆÚM@ ¤j!%À¼PQ@¸¡ñùQ9Å"ñ&µh¨rÖõuä·üÝ|Lêï˜*qs+Rô~ĺ%=F£†!ëú:úÏqÙ}òÐ R‹JQJR‰JQiJJ„m–жÈÙ i-¡R6ŠIm„¶…´%´’ÚжÉm„¶Ém¶…¶Kl’ÚÙ-²[d¶Ém$¶ÂÚKl–ØKh-¥¶i!m h[BÛ$©m*Ñd–жÉm’ÛÛ%´%´-¤-²[HШÚ,…´…¶Kl-°–Ù-²ж„-¤’Úж…´-¡m hB¤¨[d¶€[BÚжÉmm-¡m’ÚÙ hÐ-° ´m„…´- [`TR°Y*[JȬ m!m [I-¡-°¶-²B¥´¨[I-°–ØKh´ l%eBÛ m -¡m h[B V¶Ém ¿7ÒÔ ~«ù?ÇCô¹¬GcØ…@xÞã Š V4ðÙUr ªÐ®ÍÛ!£á!“ãö4^b¼¤^Ž<ŸSm†ŠÍnR\~raðϯòmTkü†¸D—QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEnRwçùÿöe‘º÷£ì|©iBA N̨Ýy:¾)™¼@2šPÐp‚|=× p<‡w”ZËï@é Vˆ+Ó¯zÔwRÛìÓ Éôq¿º/^ÞãÞžèp,-ܽƒÄ êK|Ò•@(Še € 4Pú˜~@§ñzÎ߬ð‡>V÷Âg[ä>ÅïäÊ{K¢_F‚°Eu"¨}€‰, úB'æþj ø„‚~Lˆ%‰ô?wÑ’7@T„¬"(Jñ¤åó?Âë@îˆâOß±÷MÐ[Bõr"àÓÆoSDÐÂ(‚˜•%BG²„’O>¯ ”Fpí“DZz2ݬUügWönòìN¿óiå¥^VÞù‡c¼ È6TkjZYjŠ”Á¸0R€˜•0ª¯ù¹LÙl]X+÷84ßë˜TeJ’›ü”Ø¿ÝC¢é??WÀÍÜ*¹½¼Ÿz¢SKÊÒXß`oB!Å•ýqb_ï›3òLõåÂCmè×ë|š¨‹Î‹6fëÈ òx üˆ~.WìÔ>·Ä¢{¿_è<ç~y¯â/¶÷§`Øë„?œëS·ëÄöàüžß!®tü‡ÿA[ x/ÉÛïý¼—ië@Ü?Í è PX–*'côIU+;7>cªóÜÇñjû»ÝÈ(ø·¬ÁÙô}Ì™«’HXlqÒ¦¿œÛ=—_rÛ(þ yÜ·†Zä•ç/+¾f—´I0òOó_ýä¹ÏŠbx·»m½®öTód™i™»ÇÞù r½½P>OÚ뼋î<æoWÇ¿eö·óÆûÑ3ƒ¨í¾žgƒºI$„I> rI¢ÿÛ´‹‹ÐŸÌ%»ÑÝb¹¯éüȵÇÁG.ÁiA•‹u¤O鮣°j¤Ö\8MKò8 Å™Jú=%ìšÔàôYGÏN9YYaÀgà Ä>¯«Èyj}/éÏÕí~ ö÷Ö„$ 8~Ì I>ï~ü’4ö6ýÓñ¨C^2ÚoW×ÞæÃó·¦ !S|0+:Rƒœ>D€@ŒÑ.1§ÀÍ“î•ÔhÐÄsÓtÙÚ£ŒèÙÖ¨3Ž ?½“àëäËñò}ži«i’â#ÄÜ¥X;TÕ‰çÑ@ëðH’pœ1ATV¶qˆÔ2Øa@³=·úP¸C\äV‰\ @|\§dÄÿv à,ÿ*½6M…wÚkWVèâØA>]V¼‡Óør£˜ê”KÜŒ*sKC§ìDF2Ê™¤†Ø‘ê¨þ"Ó½D´ lU=œÎ3n´yŸÑï)¹¡"´½§Uµ 븅hoI“GÍøÎSÌ[ïóPüuù_õÉöÿ ¯%óÞ~m \/I€†ª;j ÑŸÜ.† ê¥ÇùѨ×ËŠVŒ}á¸y6òØÊ® ýº1Sµj˜&YNyd{õ?¦/%béŸx’ŠO+ËJ“â@çr¸Îý¤üÿ·"ÀQG€¼¡€aV1…ç¿ùñ¹Å÷RlÙýغÎì8àP§Mÿ_Ó‰—âmûO<æ­k¨Âá„&Ƈ»P…]çàÞŽøÔ)¬DôÝù¿„-Ú>}guAò¦Á•ö(ü»Ë÷÷|3/›<ª¾ñÜWf¡ªÛÈÀ (?¬„0YŒ‰\05‰¶^0Ê‚€êS©½OݼmÉ I$ ðœ_™zºÿ ß«--̆¢ö?§Wåw8v&<»O î1Þm{ ß)«_q) 1W)“SÝ€€9þ™DI7žÜó!=$DZc>„ý éî%|gp<ȉósª0O7ý<¥Àñî_%^.¾3pȽÁ×lZ˜AÃJ³£ƒíkçç´²Ýí-ŸWÒá½!¯˜»3ÄéÙCdv..†–•ׯšúšò¦~¹FEh^³ZÅסF“bìím^þSÝßÜ^×zúScñÞ3Sgge “_Zã­¨P5Hj” 4Ž9«]==,ÜÕÁÇK$NRò# „ ¡Íè$Lrwª9‹ŸùÑÿ#óñÿVßæWéK¼:} aÄD69"KKõÛ 6¬ˆ8TÑAH3VG"$!!'à0F ]=§(nóøšÙ ÆŸv°º°¿ú5ä¹³f“i¡¶INfï߸ÂE+aŠ€¬x ŽÈ+Œ§ÚWoNç§Ç¹Ä>,¡Î¯ÆöyÊ–ß½VO(#šVãº\Û¿øÕã× ‘}©m(g]?Óí¾*t]=ƲŒ Éã̇&DRB›ŒÕªûælö¬SþÃþk×þ½»b–£fÎðÊbÖÍ6ÿÒ¼6ÇQ\ž pôVßïá«N*h-°ÉS½±µÆq€¯†ÎLlâ‘ZÆÕ¶Ô LÖ*°™f°&ÓJ¼1 ìÊ-+C[³Mµzk3gxüß³±KZ>ÄwþÈoâà}T¯Â9„›]Bns_e–½Ä. oñY3 ÒPL"µ¼NÇfÚ%Е õ=Ì—èXg´¤ÚQæO]×…Fãh©ìòwöó>¢˜à\Rø¢ŽØÐ`­AÅÕåÁÇ0M÷ .®l¤Ípû8ú_…O¶<Þ•TÿAÎ^’‰–Å…LMaºÏ ˆø€ô¶IÀqY2„H‡GášxÛ‘Še­k£…†#‹QEi¨Jt‡ýÖOµþQ¼ûÐþÛa~[ò»fïõ_Ë+‚ÏW?EíáËÄkö‹Ëü·aú…b“p?yË^÷äY¹¬Nœ]&ÁµÞ0™+õ’®†%¹š/8C¦4/#°b› .]UbÁN“ˆÉ@‡@…jÚ2¦ÚÖHÄG5šCmhÍŽ6É0Š3W&ÚÀÔ[«Œƒ&¥™LÆßkú¿­ÿCüïö?±åÓœé•+ÿ•V]`fǔܢ߻ߤ•ìÜù©ËóÝâ¾{èi>÷7@¸ÑÀ[”V¬}YŠENŒ»¸RN³,³_+ésâ„”¯Béý,#ÐlJÄ„KõêÃ{ìMáÕ–V]›~÷`1wø»Éýñ´é…>İîêiêG¸#/}I‰Xý³”¿FX9éfbGå~#·æì´(ìQf—¾ÛÙø°ñÚa(åjP¡ÂÕÿœðù¿³|•Þˆ8ðè|áš}&`T!I_‚¬B½OÚN“þå³s~^hî÷ƒž€Á©ö¶9”ñ“@0pïÓ—k¾=ù&)c&wˆ‚aßY¨bîí4Ð4® (çÐ M ´º¡àúÛ÷Ðãš{PCM¢{e¨žxóÐEd C§•˜'cu½†f ¯Pr¨::]=Ÿuˆ4i„¨‘l@!DËS7¨ý3›:õ}/ TËz"|/õM—éíÍgéè`vú>g|…"@ íÂÈQ´¡)‹%AIP` X@ÁH*¬‘?C÷åáßl(nlZ~ß6o”Ý-þã„EÔwâc¡$ I>Â; û²D†®[ I3’Y¿Õ”œä§äµÏÈÿ/«[[aÞSiç·¿ËšEbó:çb|‘¨€Ï»ÙÞíÑ®¿)§C¿kHG»;‚{µ„¤»¿»ßËXt·”ÄGZ2áWrOž·±©å¨ÓÙ\QD³©šß[ý",¤ž ŠÂæ¬Y£³x<-Sª|ô&W2¦èž\æ•üåÆÊ³ÓeUˆ[‚¸“jÿå5&ݾ`gI˜†…ñÎbõ=±=Žu´HqÀ]0€< ]si×¢÷´ÌÅñ¹=/eãú ç79¢Т•­„ÌjPܲ“OUò<ÕýÈ'o+!2Bü^ð!Jä¶óÑ1“š*‘ABra.PàO¾k 0ŸK³‘)²¬’pÅÝ’(s´ ¢­Ä>#eëpã²Ë,³-¸m´„·¥úϬ÷\ƒç<þÆž=Sì'aààüÿƒ2’N`P 'ÚÐOwùÁ•A)œ'įõöCï5ýÿÈþñ¥H’üºý&+²<Üb5y€ÛßõÖŒ QÚ\·w’„ÕàÍ¡•?§>8ê6äþÙäÕ¥¨÷ šI@Baˆ`½Œž”åÉ8eVFvꬰ&eƒÂõëKÀ©:ª±$-Þ°x•˜ ˜‹ %!¥‚”§ëk×Hé0éîºkÀ*ÊÙ w ëkfnŒ4ÿÀCïdÅõѰ~²gZúÖ®äçæ,¿°7ž‘ŸnP‹ϯÚ2ü«§ ⊡–«>•rçÒÊ’êÄ’kç`œqë®4º¢(ÊÝU•™RXD+õçV<•RŒ³íɹoc«Ý¤@Dµ­1mÜylÅm#úYm¿Œ;nD8çÑåÖ‘;Ç6þO$ⶦªì¡ðy²•¥½ùg«¬ÅD+i’—·¬“N7lOù5õÂM¿‘ø»~/”ìo¾”ŸƒýðOêÿ÷Úìèð±nøÐ{÷ÜôãîfqìjÝüéÞÈüˆ¢îtBq•@K¶úYxW2üÇÄÁ(èoøñ½Ô Sd%ù}Ìéf-¬Á VÈÍHgœz«áï•ÞÓ÷džÙ‰>@¾ôø¦ËÌam°ÍL˜˜Ï«ð'Åmžµñœ@a:§‘Ês‘´3üs‡Dê~ûŠË‚I~ËØÊû¸Ë=ù«+n'ÌÏŠ|þÿ òg]BÚGFŬ¿‰Þà«–Ê"ÙŸ€D¼,RE …Yl%„þ"ÌçjÛ3jÙé«Ñó[ €iF¦Ü)\ìã%õÚ*,åjt2˜p௻úÄìGƒ>¶c•î˜ÄùŒ±B°ÝœêTÓùlÞG>µŒŠ0D_×›mî0ˆ1@Iùƒ‘ˆÜªE!˜~ô¨·ž<@Côéì1ñ4Ò¬ž¤žÞÑ #Vl•ß}3 ³Å¦•Y<ü°c yˆÒ*7–mò—™Ò葌êÊ"•TË`zY¤™Æð#KšÓë(Å´¢Œ°)8qÈ\@ö^ÐS$";½·ÑæwDrn5ùKÊí·ßŒyhÔ@ìTó:$‚yÆ–tO//ßyæ$pRA5íðbaQlŽNx&Vk¦Ý-ˆ -H²ø} )_°Ç÷¹œìèXŽÄ>zŸ4ð9G·O†èŸ÷?½Ñ=G‡³èó$·=ìz+!֦ËM©5”»biV,ƒŽ @ ­E…£d²`\) †‚hH$ɦ’-`6†‰u §ª²F•d† ½.ílO’ *>-atÖ=K¯^ű5±I›Û{}Ã{î±>uA<âYŠo·^"tã@qD«õ4&‚&n5 ý­’AŒHH®Ô[B‡§ÑE9¤ž«³‡Ò¾p’´ôzVþZ Œ äó:o}‘â™0 ë`V0PXŒŒö¹g°;>W0(6z*+‘…a öGTþX„¬‘eK|9Zñu{ŸE4­eYϹ: yjH-Dl•,7±ƒ^¤U|Áè÷3íûæÿŸèOPý VDV¶P±¶J ²úÌÁŽ4¤R23CÜÊ6–У=æRÈ™äkA¢m]Ú‘/5M;´vÒ´ÛÛYK´/_ܸ/œ0Û/:=%–||³t-¨i³­6Ö²í…æ’¯9Ñ0Âo!ÖwÈ$ šT=«5TA.Ô¼~±2ßNM÷më¹ x%^+ϱÕ@yeà‰‘£¤UŒ\ ‹¢lãÒl¢‰9bHa&-øf] J¨Y÷XQ•iRIE bb¼&ha½Çã;µ'>·t°d,(Î^o—îз¸›uvŠ#!¢É6±%âjL³¦®…'±ò\› =úz d÷zŒN¼oÚuÒ,ìvvcÔÐc,$•%D5vå• 7ZRPNËåz¿)Ëír~/Éÿû…ØýÔüþÛáßJXc"ÆEF¡À>GÂøÎûN¥V-p+€¨ú D"Íbø"P˜ðÇG_~ßE×è÷Ý™÷Ÿ¹ü=ëGXÎ¥jJRJB~…Aç ( H…"þŸ%âýp`ñ„6*R¤¡:ÑŒ'ýŸÚ{ÜèÉÖ»ã˜ý$Ot×ÝV*ªJ6?è[ç?Ͼ Ò˽øë~ŽÝ]J«Õ‰ŠéÆ+ÀîO®êéëægæüÿš~W°ã~ÎÐS÷ßCíp×4¸Ñç–~³Ç›¨5úF™Cì?&®?e^ÌaŒéOh‰¡¥Qþ]Ûù*($-¦ä3¢Ä%xV{Å.2„š'žØ¢ôiHŒ»í³ôV´lðŽ‘š¼ñà:^IÎûFhF‡éøG²GÃÓqE¯L{%L.ã‹OÐõævÞx쟱(îÊùªåÛFgÏ<\¿ {çy€µg¸C2®ÉIiBô©YJ•ßùï/£›0k(©®@š;®æïó{]Ð!!€Ph|£wÍ–‰–|!ÑàŠxÒfTôƒÑPeTθâ‚2µEºãtø3…ŸK!Ä·bËI1Ù^>ÃŽ²–`¬ÑÙR `†*.îÀ4},b™6j¬T(Î=/jŒ[žœôñŒV1ÓŸ¥BÉÞ;cîtO¡@ýtaû£PÐÃç¡QbÉí¨Å#måøÒ,‚gC𳡧8µº·JÃ˜àƒ¶Š´ï¨4sh—˜Ø 4ΩãlUÎ@ÀYdÃx_ôkK6ƒ’âx°”€2hüvä2VJ•:°<ÌŸ’mIñ‰Af@ÉC¸dª€ðD–)*HÒ}¿ç'ÿàè¹h[ø±eìêƒÂK&$Úqf¡6 ¤¶ÊÀiP –e1ˆÄL3Aû½bÅ"ìÅì¾Y[-1 }RmæÏ˜û9O7`Ÿ´èáüù³K:кkˆ‹–.zù´­Shó-;2%/C¦0˜ê5`ñk’ cœ‚^Œ P%äeÈM˜¡æHÉéÕ"ìÆ,U‚´–[iiX³ÙâÇIÜ@cÌkP›\Y8ØNñS6Kföat`A3 :1b‡]\)eID; a({‚„œÓèz;@Î[ÙP* §(!££µZg¡³yÚ÷I¦faì.,¬FÖ¢)ÅÌ_@©# ­~Šf-–Ĺˆ¡UÎêê@¤0È Ð FÒDaˆÙn ›a0ÒI¤¨@l(DV‘ L`b\©`LžiI çß³þÌîÁ|„ÃNfBošã¨ûxžý¥‡{QCvNHÛQñR£`W|%";}nUY @É„’AVKR!b¿$‰w\DB…*:¡EbV䯔St„£4“a™‰j\—E"±90¢òvµFqJ‰1"Î)BWd…™ÊÉ­ÔC &Å($CC(ÁTc"DÒQbÂ1‹ bI³A6ÚÉŒ éHYšB¤ä•Ôd7qF)ƒ½•Ä(÷?¢N½Þ+²Uƒv]û›Àƒw˜ì`®ÇÙéã¿n&B™×Z£Y’^›ñIÚ¤«Û?cD—8ðå°Àüÿg¡½$nGì}KõràpG÷˜CÄSŸáws³ð~û°ìëEdõ1E‡Õ8:šÙtmÖ,aþ–ÓÞôF¨sm+›ªt¯c{¦7=Ömµ²Ê¶YŠ®Ö²Ù·; I{s´2ËÝçáüÍ©·×UÜÁ °€ë-}Ò¦× llhÛn+›Þxg™Ÿër’'ãûèñøÍî'¢´ÿ\Ï;É_ÎÒ‡Ùì9†ÒïÑżÓæ7[¼vnðy=0®oíí¶š¡BIHQ(”?+å|žŽ¼o ƒÝpx{m:rf¶–r¸uðrÄ¥ûÆIf¦‚:À¸Ó“§lã0fgV5æ)&üÛVØøü5òJÏ0¦¨bù|î¤Åçõªù²QõêrùæpÎ%Ž!zv¼›yCâZS $*@šykî,jDß•„ ÷/f&P„ŠÕ Ä\BDlrïÒÉP‡‚b>Ý5”!q;“ÜÊHn~ÊIÑ °ùèJéï -”xòûfŸsedÝ( V{F_ö\š*Ïœ^IâC§"ï®AÂN›Œ…ˆT‡‘Ê}ž'#à 4¨(MÃzs6Ø••¡YÌÑ´Ì}eoœõ 4‡K$ K—Èq(ê q.0¦š7µ‹ˆ…àó„ëoiGæ¸òï×÷)—‚ðq ·V‡™§ZäÉ㇫¹ïŽñ …¡˜k¦†É¥O%é½…u?jJë@^GLjŽXóÜm ÚéÊ©,ÇPº7¢ØA܉¸2CnÙİç+, ´¡B€ƒËÖæcšÈÈ Ÿ­®þP˜¨÷$þ™Ûhî¹,™åÑ)oÓ®ç/%Ú)¸²_½&ɬH4’û½•TUÇ1Š0pÖÀ ža!Hª{éúÏ´ûýi9oSÔ¡YÚó>é8ÚS‘Öî‡jX™‘ ÍÖ-…Ñ¿eoædÿÞ7qúý>¾G1sfn=¹ QÈÆÂÒ$%«tn¹˜ïk1%š3ýLç»nác·på~WÐ<’œ#Ƙ.ÆÖ¸p%„ À¥/˜î†HÀiØΆÁœ ~±ß¼¾Q¯vK½ëãàzçy…\¼³‹N'%\£²2Y”kш½°›-~ïôÄéÇ’ódQ¨iªK„pƒCw⪠úâ¾#™#Cz5NÐÔ<\éÜÊôpxð°.Pmç9â5Q5#Oì×¶ç}6éO Y:†È˜XiêÃf‰Ú+ÜÞòNÙwÈ*÷¾Ó׈TÈ"¸Y¤OÄ~P¯]U„ä»-ß-¦å†ò ÎÐBmnb–6' Š,=j&D   ”MÍJÅ b(»{ØP­NÔ”PÓL]ÅL\Ñܢʀ G>N -ÅÞÃ&Já›3¢MúÐDíOÌå³_7Ñ©ô9ò¢&øY5!)]#oFGZìèƒT’¤"@"å¾ÎêŠ UQÌõ¨ÀUµ†À”–.’‚/ZŠS•6…xTÞµ £f4—.ºÏ.¼qŠ_¢¥Hn@È &kPÚC ‡ —"†@"P°Ò Rv#”*9@:‡®2FŠqŠYA8Kè%Ph Ø ’D"rä^vIo-¨õ³d19åá „7é{ž®Ï4xh‘¾Nyb¬ðü9Ú€Aè ʼn-¾ ˆ[;>ävgÐÅÌl€½ÕFëÔPKÌlçb «ªêX£ )Án: G6Qb¤­È%ˆ%,Šâ‚Ð xŒ2øêµR•/ýÞ|¨:ã“>•Ãô~l)SQPµ†z+‡«Õ…$ <ù³Ò¶­m;ákz0s¸­Úø£CÚŸ.:]1ΆD ˆÊ™«± EÈ~ù*  #r\VaĪa\úw®²6óx€§ä÷þ³÷Úé· £`G&i#™r1¼‰-ýä„0hE »oWhk³tÇ -Õj €@Œf©†&m G»Ìz¬ç({|·ïd¤ÄgXgåZO&³ª= `¥,¶¥¥¥±•AL¶b(1°¡‘† X‚b r˜‘=WJ2hclLjV\lM‰$jì1A‘T6h8c/XÀqÎ"´C[sjS®/]NÙ\€( $"%HŠAF ¤VËD¹¨äÎØ#“0,öXŠYd)”ËÃßž`Ñ/™Î+#qž?†¡¢&Ži\I/—×H Ø®µÍ¹ÿŸí9ÌÁ÷,ˆH`Iù0éšv<óÌyëÿé£k)gÂ7Ä[d‚R‘µ³*RÙÞY*­Á Ø¢~É-°HF*¡ð¿‡ÃãÎ@ (sÆÎ‚‹Q‘£E¢‰Ö #Éâo „acÄ «8þfjPíjÐ1`C´., æãµZÁ¡èmÀ\á<¹,$ !£b¸¯‡RMÎâËs-†X'Âì"’ÔmÝÑu 9¬n_2ËFá5§›`(ð›¬ül7qY]&Ú ÄĈÉɶrÎ[$¬“1’¢¯¯‡èö Uþ“© .¥&Ä3ÒCph·¯uØ4ûã½(cø4aPaèRÏgNY·yçi7Û}]îãŒrÙ@¼Á` Ú2ø`fáè\X™ L>*DƒÙ¾Ë”~ØQ säÎxê ¡ƒ¦‡Êº$õAÖÈÞ;;üðÝÁIñù‘žÐÅ ˆ(©)T’ÉX2[(Nþ»l14ï:e:{5mGHö*Ûùy 6ÒCØ{‘¢ËÍÒkÕf“œ· ßNä'™"Hüz@w3nñÀ†{ÌÄ¥—ÊHQ3 KôêV(6ZfTÜê6žXOj°7½Õ$Å›t5—UµðÍ & †³þ!2¼/»Éã‡qéšé£4XvåÚjÝ‹´"ʆÉHÍ„Ûmb÷í6“ZÆÃÆŠS"a`R60¡™Õà´Ü­ÍÓШ¹ï[´D¾å²x,·­ùiÜ=‹Ú´Z,ª*É£œ|Jêxš>ïÅÞ“ËË3Ø„ðF0‘‡’Mý¸xºùèWtÚŠìRæ' 8 ³U˃evß]±ÐÈp-“K³b/Nüe¼¶Õ‰pòwÿ>ÛÒr9NTœlMØY´V<Ú<8¹•-2ŠÂ½ˆi²@Ê:«2@Y«£#ø} g’­½dè„͵×W´ÃŸó*:Ƙæµ&lE†…Ö+Au,Ó·®¨Âžç)}XOÞîîé·5޾#ª;5d 4ÕU•,8’€\q-jº tfÙ–zt×F6cñ½ ¹ÖqF­üÌ”/q*I]y@Á5¡)¯   g¦7©.RgÔûø¢Èâ ™9•Ã#d×Ãß·ˆ×ká¾3ÅË8¤cÌŠìl^žV‰ª|šâU¡ ¸¬IÁÜKÉz4»t©zÖ¡ˆ¡¯qi…Ž`Ê`ë¤F/:R"$" dE"21#% V^P,7I ¡:jv *$Ëç÷¥’®çÝ‘òeZ±Wxxâ{ýg¨ž×À@oH'Kiì¾—$A…4Ì΂6†šk(xtO0K‚€l&;*ÁÖŽ¢ÅÏ,u®-—Ê8¶€x‚’:|]ùìxÃÔ°&÷“Ôšß-¯fÝ~½ OBDàgÑà¾ÚðhCçœ30tÜ•²ÚaD3 tlt"ò@;ßÈ,³~ñ­}w %j‰‚ÑPg… `¨Ç(éì_A ÓWÇä½€@X@*”@?=wxÂ)T¢æÈÝÝ+ m ˆø‘ðïX£…jÝÛ€êúy^HN›ÃÚšç;¶ë³|ºqìUŒêšò¡ù”“áéÄtë«-j ˆ¢cB `#ˆiy LjT6mAµ„dÚLqÙ&)J£1ØéÓ¹ šCl¯é}HE ef.ŠIÞ=È&K†Jo™ñ_--»óÐܦD†#TmâA¤Õ÷lˆã̲…3Q‘9BÅ(‰fƨH±Åd4O©|GZzÜ3¢i"(îÄqâŽá—¥ÙÍ “AÈ1Öïùt÷./7[¦¤{n§#gªÍrtzIj§ÏšG¦û>eÃ4¹b-€[m•" èÌÄ@eˆR8’lmA8(Ѹ"\ß°TÚM™eOÉÕÝ¥!À‰‡qÂQ/K`Æ%),ÔsÌâ‡( l4ch š7óôÛùhþm-Tâ/KÜ=ð05òU×zFŠl–qkp˜§X ¾IåêÝÄè@„N2´IB¾öûGØùëoQ¿0Á´0¤2Z¬Pýi0Äó,Ù 2 ‰½«&\0•*bJ$Â!…ÂYV”–Ë?³2J°ÕKP}¢ƒ¸–AfˆÈ`ÀU€¥¶Ÿ¸ÕÏ­a ÁÙ(M$ÑuB“žµ­ d&`£yˆ¤ŠÂV’)ö¬© ˆV(V±É²µµ°© *ÉþáÝÆHVç²kˆ²„„!  ÛÌQÝÅ&{¹ÏYaŠQæ'Z¶ïâ·g<¡ýŽº¦0„!óÿæ›óa¤ hpa% €€OõØ?÷þö‰Ëú¿ÕÑ,1áWªÑÏ×°ÛzœüLp‡… çcþþï±KÇ•*«±JnÎÆwÁñ«ôÛô6õ,ŠpÌbQ±ùw  ѾûQíØÞˆDšAàI Q)£ÇsÃ(..N'ï/𻬠”X¥ªQ(k”M8x69Ä Æa*ìäU×cEÐà`PH ý>/úüNÜ;œœð?'—6ŽÏcdr§QRAµ‘šZ-C„Æzxé 'ˆIbÄ‘÷/©˜k²+m p2Ý2yÑòϯówí;Ä_Ñ ÎÂH «PKbUuè*‚RÉm²XR;Ñö¿Èÿ_gÛ•ù=߫РSï?Ìswù<®Ô]ÅgÁ;£Í!ÑíÕ(8óá¸ìy¾ë…ʽtÀ?{Wìsà€µîªHÃîü?Î÷øù{È<—EJI¡NI‘"€°!õ¬„© $©1!RJ1n‰l²JΊ¨ÍBEm—äá&8ÌJä[ffaø¿ÌßøŸ°oÅ´°S—Ö©‰½’2Î’ºlU“ð+ó~‚N‡1°¬µ-eßVu³ü÷9ćá³f4¶qe³‹–LXèr@~ãó?àúür“›¸ùýþQ´ù^ý« m ìP6äTQL²”-¢­jŒ’vÀ;7àá·2Àf™!“õö[`œ0°5÷ôlýk·OÂ(WÙlDÂØ²”H«¨Û!ÃÇ>Æim’®b&Ä€hˆP†#Ò[;h(a³ì;̬4¨aGhÊY:V+¥ˆñVl¹1Ñz1TÉÑÜKã Y-¿Ñû¨ˆˆÉ¥Ê:]Z¥“š'MˆÖ>™ùh ìû/ÍãîhêXOík·À…Ÿ¢Ä>¶œ¡Â}þýûm‚‹¼M ˜½q·[Ä“ÎY5ß|-6šJÍYA©³yÝŸ6 !ÕŠ0Xðÿí²NlšåL`±d¯~ĨšÕõEHí¥ûèÀ™LîÄ’BNébD@" € ú¥GPèÔp¢†“Ù dTjnÂg.•†ιQ•£­l^Ûݤsà) žÝǯ:7ؼ}àô ˆ "‚±~—tÜ ]Cz^D±ÜADAD;„ ZØŒH£„TDAƒðËfY*ÄDd‘#"ªÈ‘dž¿Ålâµêw>ùJÌXVÉZ…©Å»RÆÈC¢ À¾svÐÐéº{ϲÄP½ƒ 'ìü‹Fé?¶ÚˆæpP~7™£Åê¼MQú0ÄÇíêóü·¿„„œ¾f¤„…áéĺ᳥hà—¾uˆz "õõÀR{Ös'Ö©ii-FÍ«2¡,"’ ²(  AD ,T"„dˆÀR’,‚’ ,Š d@"È "À‹°’Ø…°[Ø’ÒÑTŸÈàbøD/}ÅèøälÅ(J€ Øb† ¬`ý¯„Õ–¢Ê¤ü› Ùh™ÓU £ØdPÈ©ˆ•BõÊ]mëMBû$P€E¼ Eöíó³^†v ¯Ð0`*Û˨·$XñY WAƒùT+òršæýtñgªü¢£Ö±ÙåbmJ¼Í\Zr&+:õ2Æ!sUdvÌä€Ñü>8íhžRZĈ¥EPýP@ SÉù¿Îÿ_5Õ韼»™-åô”=PwÑÊÿês—ãýFÞB‘´)’ÜŽZ~µÍVÎWs£B·*ž÷”^X¯èƒi9O?”¯ÚÇý|8.ÍßØï­„c²¶×~"…7Œ°Ë9ª½¤\»ß†•mv –³*és ¹åiÃú¿%¹lÛ£vSã)#ËÛ‹/þ¦(]ú|/k4禃ú³ÍÂ!æf#Üšéñ  ´ºšØž–Út¼;gÏ¢Ž7nŽð±^~>ïõË]òTzïuÖ<¨I'õ6INÂJ% œ#fЇ€ Ø(–ß Æî>†=šÎ?ïäüбL“QÙ„Uùä)¹š.(œHCHHÖu¿Ó¼x¬‡%£TÆöÏ¿¡³f΢ *’(@(€Ît8o¶”‡¾†´õ6ž«%—±yËŠŸàI;¿ÃíŒMÖ”¦.Yž“ÿ3¬³C;š‘`‹û6åCmÍÃ6vs¥E@ ð¬LìGПÕbÅ|¦e9õ@´’L첑®•l¥<&uÆ[Ò%HfyÏõÿ|ç瞣ÑçúþO;>ìÃ2”aKUûæ½j§³OšßîžDõ¿ëûzS¯f|û A‚Z¯i7x¡êRÈžb8!lFI4à†˜ÚV•”`À@!E A•2A]Û{ LûY&?9PåÊ—lIÊ |ݦìRH•võ~FéÕ¬ÎVêÊ´Ã244)au¬TÉÀþ?f@üNÏo\îÜ£àÖb,¤J@ÐryùÁÍÄ—ÄÍü<;q/€ç%’pÊåpÖ„¡•Ì_º±‹´m&êðã¦!†[ RT§< m*ä /Cá7šØ?¯ÞO£ã-X²ÚÖ”iX¾fT™m‰þ#Qú}ö`ËðYêó"{ Ô4ÑÄWZCZ#ƲÚt΂¥’L²¶¿Ì :ÒzVUzêhézåælé cs³¬PÖŽNè(iÄ¡äal5âÈ0›IÏžÙ6ï-ÛNN  lÉFH(±Qµû¬b=«œ÷xu%š¾fQ£¼MgÂ@+â÷õ5Ëc P’iQ(šŽ~RÝÂõ™ºyeè@ñ|Æ‘»xñ»ságÇztííÑŒavzUC$  .̾<° $b†gg¾ÀSÂmÊÎ͉ÀýZz¤G}œ2J˜Ô¬ lé36o»nÚßA$Ò3&¶‹ß«ð¶ú:6ËÜÜ/}56K®2¢Hx“dÙÙñ:sVN:€ºw Ê8]Ž—‘£äoϸÖvï“(YíÌé©pŸ? HSµøWl‰€H¦™l˜ž‘1Š”ú¤2 ñ@ù£í:» jÒw¾*ØVÖîåµË  ²ÈxØ‚£”-µÃïß–NPõ”ç@tËmbÔ F0øÝ‘ñª"²:Þ © *­©|okÞ÷+¢*W§Ø•j«i˜7ÍÍ›Â!5M¶Øg]sšÛ´Åp$M‰=“'SÇkê|>ȇåP7î·s JF–ŒŠw5+=óxBPÑË“ÓfžÜÖf͵¥Í…±¤ÇRDÑ9*¬¥bÀ‘%çfÖÍΉ!Î`lZµ`%/'&0 ªñÆb¬(~¤‘'@Xî=YÍ‚ÅV!Ýû µÒ³»tÚ²t~.ÿG€€ÄiDhÊ„ù ê‡ʴbyÏ=~ôc΄¨±B0HFAk 2 EŠ"H(ˆ¤RDc"D(²,’b‹X`F1*YRÅ’ÑAR1bÒÒ‘T@D ² (*ÁdEŸ7Dô ÄO_^‡“²Ÿ–ç2O“’ ö}”íx=¸áòû«úþî³ÓSº£‘< „'=,Eb0ž¶¤{’\Ì1O‘f’j@qÇÂŒŒ‰’JH!P`$X"b@"Àc¤ YÍŠ?γZ³LÃ(×S3y£N0_‹PÀn´£š »ÑÒ FUŠ9$$ã´tól…ÖWTª€šÙ2rû|¿ÞÓ˜ÏKˆ3]-®È¨ƒ‚Z׿Æq XÚèÕ¶ø¹ ˜jðÇ(ƒP€®Õ–$(Ö&:¤”»É2½²ÂÛlTò¹æ-G\qÖ7žìtÕw^šÒÎS$sG‰fC´ÔpJÊkTµBà^é(ä÷¶ñöóN‡±‰ìxáÓÁÎxbjGk’b™*ý*ª­Î6¤Ö`E„ˆÈÉ"¿ôP7X‹BuXgKx&–J¦0U{Hù°¡’W5‡Ååû_Åþ×DêŽAWeʶpÅòmãïAÆëÓìWæµ$çË!ÈîÚÞç±ø¦Îb¢|·¥àf/§5 Xˆ‚ˆ¢(·Ó0VÍŽnCÈŠ p\©ÿNÛw?œ8˜…xÀ>’º„9Èo¾vÊ›X¯X £ÚIÇðŽ›C±~¿ÚÍås@Q@N'Ù­(9jE¾p븓Œ7 „W¯^)Ã>²Im_™ßÈF¬æ-W_ê±ô|Èp|]ÿï»è®Q/œÁƒ“°âÂÊF0­#JùYaBïB¿¦ÿ–î­Ûº¦}ãü¢Ôý‡_´çúG<ÑötB¶Ê\ÚY+ŽÞžbNTD•¢=_öø ¯‚Æ‚iÌÍ_Ç ”d´wÝyÓuÿ3÷o†—ùvŒzaÍ} €êmÝ‚´„7Ыẚß0ßÚ焃)Cø,•€zÃrö|¢do¾‡±ÛC´†w~£DzümÊv}NŸØÃó=Q 9ɤN??L£”˜ÿÿRëËbP‰œ:ñ’§œ/\û¯›oÀî|ŸËû‡Ãê8÷Êw<_Úî<ï¸÷Ÿ/Ìú/÷{ÿÇþZö#";øîg)E${­¦Îo¦çîéð Lp“ &VV[ëŠP. SŒk0€«,Dµ 7˜—l7‰µuk?Š d`}`¤XŒše`}BB¡$¬’½ <›Fl„¨E$Á‘M0*ß0ÄmºÊÍ5ç ü>(i›5Ú*@m¬Ò@ƒcY­-sAaž!1üOºù?Û ¨þϱ¬tB|í°b(Тp!?N¨å$ßû¿´þÓuá&8‚V£ë3pèYÁ—dÝD€¸taisŠD¤¤J§…êj(¢ 0'¡ò>_Ùa4£zù|¯ô=Íaü¾Þõ‡­ÐKkè`tD$¼š+‘ ¬+=Ä'çpzû|2>nÈa—2†¹˜óßÅ; #jÓ1§,¹ø7cæ4†é »ä=è(gØ'þü¿ Íz²ÔÞ§£ RÖfM¶â‚ªˆ¬ç-bµ0 cHPàëá6#7 o¸Hk°}öQçe`ÎÀ-@T±tË69\Y®¸ÄmÉdŸ!’KÊÊ0Û …¡µT1U6Õn1Q(ão zp±7—dX^¬aS–Qâáö4x÷Œ&:&µ\MLt£?-F–umUçåîrj¨å+õó_O`AØ[—4ˆ!J ELù?{͸÷ʱ€Ä4aDHS2‰¡úЄ=æqk«™StÜË4ŸÈÄ=ÐIÆå½•Ë=7Œ“ßNIžx³×K¡z2³"d²¤Î6©XE`k¤Å-ƒsFƒ­¸ ‡¤ %¨XÅ%Ê[YñÚ³2ã)„ÎV4o 4¥*×Q5Åíô¶¡ÂRýü”%l úÃJ­Ô,ööäpŸµððêkÜê5m)’ØQôËZ %ÌÈš(šÆ‡=ð>÷î×ÓþW×äxž_ÌÿžËvvyã~T+îÂÜAÔ![E^’±ë”òOÄÅE$D±T@PEQÀœ99Áu¤Ã醵ŽRÌÿWì§±·Ãg#$?G•9ídÙÁ +0û €º`µ\fµa¨ K0ÂÆ}…&$Yø)­RŒæ…a½ƒ©¼3r.ŽRæ­Ä®.bÀÒIí.óS„ߌ%Çd.T0 ‚ÌfÚ4¿[g¿ÙõØå°ÜÞÆÝÒO³fî¦ìnj–Ù­S ½CAvI;† }„1Ó«½¬–fS·F«9m†l`‹-K²™r˜œ fœ“ò°.Æ}…“m‚[8eCOÚ‰¶¨Meœš•0ˤå£LÁÍŠpC™wfñ ûv“FáU´Œ(’RŠ€B)üݦ”Ë|¹œ­õCÊm%‚A¬+×ë¼ýÂdû#zòëž~.ÂbžVÓ-¥þºŽ±<ËÔ."I `Çeu-oÕ”k%’{FìÎñÚ€Æbуûwôµ/üåößSÊb¯cr"2*›H:Ðt#™§[A?&’þ<#|ã§©Þ ^Î7$S¢Í ä"A°[›Å‚POƒt_µ´î7„6Ê)œF¡1³c ¦7ïâHàI °³T¤²¥´c¾ä<¯¸”q- JG¬ßÜUFêBrž0aA1ÆãH @’Iß ìùTδR^Rt¥ÄÂÉ,&Û”ˆÛG%ÚôÞNS€Ï•¸Ú"ÎH`‘A@'ïk8¦Ä)Y‹*iÅ™ AA-RA‚Á­Œ!ƶF,Ò†& 1# ‹)uƒCX ,3,byD ²cQW[µ ¤3ºA„ ¤~ŽÔÞ¤-”ŒÒîZ €(ªÆa*U u,†$™è83šç,ie²Kf»L•³_‡]£^•&Ó©ÎÉÉÔ*~:bÕ« Ô¾( X·S‡Õ¤ ³bûŽ!€–‰œé& LV²…)D¤V@IV"Y$^Ì$1e¥%5T$!‰0Öa”Å‘dÄD"Ûa RþÒÍR@6!±·º$ÁðH‚¤5wÖª @‚OÔÑ’ØÑðãì]É4 óàÌ!®:}aè¼R}þ1aæà€óÓËF¥tXmòÊò<±672º `Ò°Út´í–ÍÚ7cƒ€Å"'l£ VÄH„óÍÀ;ËP÷9ÕO'ì{õ»ýúŠ}r#—<2ŠC”B9TZ´:ÂõôãÕe?¶÷–¬)7ä[â’O$ýE€@ë­EL€T•]$Ó*­%¶®D²&´ÒY"E&Ú” AÀ2IŒˆÀY… 3s)‹™ŒšËaeЬÓX­EŽâd0£Pd©‚b l–*@S’R •/sAdÄDXi»‚Q„)ˆU¬ÌFîvTBm#Ä%’e, C ¬ˆƒl„ÄÚpjbz²À„›K6 $)ªE˜ h¥¶Ò(Œ!F¨ÊZ@`Z4 K VZУ$bÖ-–kË– "  5ËH<,'Xàþ=/¶ÈmC™¢‚p_;îë®Èî‰jÂ…T²š½} ÖÒ•X³óþ¦ÝOþ^¨öE7Ÿ¢‡£Ç˜¶*!¸h›F?[–WBâ3†OÕú?ËsÅåxY,7ß[âùëy;¤ ü4³—)OAnŸÎ•gg*h“ÖXÇ%ÿÞ˜ìŽoøÃC ;_<»bQ‚;º¶xÐ@Ð5@c"ðòfàáö"oµ0LÊGý>¼ÓŸU¾N¶‰àþ÷ë\‡ëP\'õæS7Òvx7 r÷aÍôÚö—”ƒü>s?ãIùóònN8,×ó½tƒ–Ú%1ƒ\Ìc9ƒËó»Îï?¤Õ ‚0Æ/{°ã°±!râVÀŸKJ!³Â€÷ÈXž¡ ä@€¬X–X«"Z’)R¥‚¬…•ç$v{\ºõ5!XI +ñ] ¢›;V˜“c˜"m•Ö‰ãl; ¡¤‘ÆÈ,½Ø~xjN¶lÎâ…,³Îßs“1Tr,ks2BÆ!HÈ®i‘`#Ôa“H²,²Ëj[ )iRVÈ•Ql-YlîøCÅc•ZôB»d°!=¶¾Ëkn%(—ßfodɈ,˜í’RÔH‰éK"V¢òA› µˆ“j[#Ü“¶–©çºh8¦H?^dâÃ’Ýp&Hfj¨†æÁþÂ?¼î(’=Ö†•Û{$g})ô…  é…¥@9¸1×:9ÌO£x^Hç[ðvw9“¶’tHæHê@QµDL .òtTfÇ´XI‚@–f±Hb{sß³ rjžN©ðJE M~4ˆö BÞïSV½Ñ=J0ì©©¯«¯Ÿ­ÃÌÄÃ? 1“ÐÉñyNþß?nþrŽgmÃ1 "d Õ”ER]>Ê1Ø®]Pë¿üøìbsYÎt Ž•kµá$#5”ñ‘Í60v…,cµ’ )«©9Û3Ib‚‚ÉÎ@8Ö  bLpKž¾Ùéå9žyãòh{ú†{ÙÃA–üy™X‰¥'½p°òGKãË¥´3Øs’¸·ÎÄx{M.Ä ôÀmˆ›f+ŽräG,Mˆï+E(0(­¨E*Ħ£"¤„Cj…Ž€&»¨¡ÒTb¤ŒEöË 5÷éï'ÈÓ˜€ó$êšù0«*±»Ñp’M*¨›«o¹™ob $a m ™ýóÝ`ã2h`E\Ö#F5UŒ­­,¼š¬ ¸˜Ë<"ö80Ž$‹`.™]¶ã†7 ¾¹æOQh{§/¤’ÁÈ…1̳˜Ä®†d‰ÇÅí$ Þjô褫Zóœå²Œ ´ƒË§_“eÕtyCÄÎŒëÕR¾ÐÐ5¨Ô'¹" J#[ ^%ÖT(‘©HÏOèò¼~gèúßí?·¯ü7ú×ö¹f®œ­.YûÃöf.3YB½¼ãŒ¿*Öî³¼( (Ȣ€hò i¿óÛí>çy–üãùÿëãv/¡ËgRTþx5­ B:Tkm ^¶BϪatDˆ.©„}ú~¨Áü”üoãà°EÝÝ…L&Î-­?:ËÛt$½Bþ¶ó¿¿æóÿc¦üì½qÕêPçá /šH( ¿Ð_ͽ™]›ò |Béx“üàoú>³£î~gCöSw¯q ¤$„×ôÓª65ðfÍÎ Êú_Üï¥ÆÚ–[.­“ô¿÷ŒÄ(h è*l(Û‘‘v%îãáÛD£k"€, ‘O\ $@DQs<Æ’jOW }šO‹“wº—u™ÛgM=ïÆØn}ûôwÆÛ,ÍÖ~fîãL2„“ÃŽi“¨bÆEyû?dK õÕ ÁÁôƒFïÌ[Û0ýÞV30èŸbGÇú˜I8³æúiVtJæ@~Pö2ÒëÍ9 Ehá…éÓÕWE©Þ)¯–­Ye¥²Ùm´¤_ãÖ¡á§™ºFÓFØY#<+|Ë’m±òZø›y”5I|úì}}Ó„ç“©4K7'׃°‡|oRs±#Ñ•V&$cžÍ¢¬Eu“Û Y¹¡ÓGÀ÷|RC¾@ýºM:µg7Z*>Ä=dÐ%'m†C·ØžÛ ‚(±AUŠCcsÛ‰¨¼¹œ ²á®}9˜lm§})\F bÝî@c”-6¹€±EPSTªH$Õ¢›²Tcƒµ DDT(£RÒ°²0H±Tý·ýÂÈÝßž¨†sZ¢@ü/µMðÕFÖÚ;½à}áöÚãnéÇ“0«’bZ ú™ç–z4ñ6¼þÇ-f´œVnñÈ•š³¿Dò*a¢@ÿp¹ä¶+÷o&û³CaLȽäÔ€vMÃ>bˆ¨ÚoÉþhöFibßÃýkÀ[¬U€FI@1›%¬V1ÇׇÅHÓ˺$ÇÙñjLMÊZ˜UE·þ_DÑ47ú·þ>ŸñÔÚ~Ìîï3ùþ/1ö]Ýó燼g(-*×(³VŽ1Isÿ¿ü™!®úBvÍì=}à%ŠKÊÁ´ßæ»C­¡‡0HÀHPl²PÑ:çÏ›X¥ƒq%e \ Mº”¢ ù…Àí’uù(3–­ö±Ï˜µ2)ð:`ðì<$ýOÔs;o‰½ÚU<ÚàÀ4²ÃD¡©V(ªŠ¢¨BÉ 0ݘxÌþÇÌù~¯DþÕVŽŸšA²@ÓOít°ċpÆÚ4„XYdP’-Z åº[… Êe”%U¦ K™(I1Y†F6µ…–LB‰ç™¬Ta’¡SêŒ0v$ Ÿ¼ž.ô}æ.Ñ´²„Ž…(mýe#é¢@†Ð%q§‡j绺3Œi,Ïk±©ØÚ+|AÎOf^ਥGµVâ Rk¡~ü[Vc(o…P·tèØ#H@‰#¥³Ê\­P/bä™q«‰Ñ™>Ívþc~xE´‡KǾ|ÝÎíèðI,Č٦;&+X¬ 2O-‘ÎÕÏê¨ÅžmÍyg+j{ôÔíy^8Ò{¼µî:U^0@+AŠJrE†ñ¨ ƒb-ŠŒîJ ÕnªY‰g˜x½(qÒÛZåeжÒÈV¥jJÔ!@ù~  €+ÍRà€éˆžÏ÷œ¼¿uE¬Ð%ê=¬m}s,Áè2êÿ(®bìºjm¶@±2Í­3Z+±`5ÙµÁWhi%Ä…jªVh̬Ê6M•Xo¨Fd3,²–±SÈÃmâÆ,cV.6l¶Ž‹"T(†Q‰]‡ÁÓ ´Ó6Õ×½ÍÆåj,3k“–ŒDÊé®c"ø¦§« 1stñð‰ CG¹®“VÝÜnÆM#8Ï=s®p‘¯G9„³h¯* ñcÓ¤’wêñY²&ÕhÆ t}¤a´ÒtÉV°ÒD…‰2…$99ÎzMI¤ª°Ñщ͉\JJV(’!%½ýl‹ 1J”ˆ)K´õHR–¦«áíêI©´Nl!üí%'žDŠ…[J©Z;##ÚCY. [$„a,4EWŒÌtvqŽÁ4 ºE &k‰0UŽbš·ëU͉"À’D„)K3¹O[·ž./vέüÉoÜõ¯°ö¼Ÿ§øÛïs™©s ZQÍÐÒ~áø¬rÛ †ÉhŠ Ðض‡Ý?Ç;µ Ö kiB b|~ùšeÍz~|ÞTç/BH@ý-_ûEÈ—ü×ý‡%«ÕUQŠ›RìI6\Û&éïïLE‚[»¤ÄªÍ“G uÕÛPû–q¥¢ü;k»ìrqÎe;=(S¡.ÉrNÍ´œ£Nb^n8SŒÖ¼ÇY øH3BÁ‹ÄÎ/¸ª}7·T&*©BÐý² $†–N•ª°¡•Z»¢†Õ†˜ØŽ{Ì#C¢P¨ a¸P»¨·Ðš4ðÖˆ»­Z ¡Ý ¸âEœœs¦‹#IE…[ùdB:U£9YŠ“ÕzÖ¡ÞŠ&ØjÒ^íN|µÏR¦Ú§4uC„*ˆ«ò<øñ»;ƒµüÈ6ÓÀUcm¶îTAú7z?' ‹ã ¢¨«[%Å@ ÑhìÏÜ™‘/L0—•QÕB«iÇ;’&VVW–ÓÍòG£@oÊw–8F @ìá(!,1Á*¯ÛoHÑè v£F „iÎÜaB[G-•(ÌÞ›»#µÖôæ’f3|´Y&÷*>–ÕðY‚äg®Õ»ÊbîðôiŽvãZš?^#¼²ÍÜr94a€(Їȯ¸‘ônù,øíŒª&‡PDÙ®1\"P@ Æè 6ŸØG¤húè‚[‹„Ba¬bºD7 4Ú}Ž!H¡µD÷"ªE+e–€;o¹òl+VÍJÄÕÞw+̓&ûX÷˜@#ÃÃèJ_Uù7Ýü\Ì·àýuïÕ-¾N.4·à2&rkKt`QP…Þ:ceõñŽMÕ{T‰ÕÉ¢UÐŒTuHÉ8ÀP`V¾²Âä0Ž„žÁ/¢´–ý·-»ëCùÜûxgqž{ƒ¸óp¾È¤*”äNòÎMò˜rŽtÖ²špÇ/ Š'‘!´IÇŽßÔïãøxéÀ]ö•úr/ïNœüÎë r¸Ì »ÄªVÕ4ØÁÖ÷ú™ëÖ’³`GB{ Çä݇/ÑîUê¿ÓW¢?ålôQÌo¸ Р±Aw+º¯‡0€›ž¹ê‡.+å)ù]°ÓÖÏGxÿ0o>™nH­à ø¡Pÿ¸÷"¸ô¬´·8>ãìl‹Ñ`.¥@ÑöÝõñ1ñs5Vùþb)†*Poš=F@ªÂ;^Õ¸úp錾Xou0îuxÓ 3\h†×}Mråwwx ¢D_ÔƒdÜg‹[úÐõÿ.–Aü$HA'y8&Ça&jYŒIÏÅðæ45˜ó¾«!åwóžÙ`[C·•Æ6îh,5Ðã ÞìÒém8å‚"0PXhåk‘¹ ‚î'êû$>s ½B?>Ôô$)‡dçâ°¼ÊD„†ì‘A×/3oÏÀ°îlìI/Ði†èáVf$|té"wŽ·vç`ÄÌf|R,óv}Y¨k¹¾:öÈÄÿs±˜† š”œ“·Àï šîbn¼I ~€á¢Ö¦¾Ë"àæ–ôèiUr\>†Ècp:ÞBw§îXwžo༒ěæÛø['ðY  °QEE‘dR "’)E²,‹ ¡R E‘dY$X(,‹"È,Š,PQEŠ# ¢‘H "ÀPR)‘` E  *’(¤YAdX( ,‚ÁdRAAAAaŠB,Š¢‘AAdY-…¥²-’«RÙTYY,ŠŒX ‹Ù¤•KV¬Uˆ´-J±b€°0‚ŠDB1ADB(²1("   ¤ˆÅŠH¡’*¨AH±dQEŠH²Z‰jÔ€Ã8 1:ó|¤’fäÝSȲÀ0‰qË8U2ã µ2°#`EXý ¡’})`e‚Emº7ÁÙæh3¨ÍñLÓÁ䯮§%ÉTLÎLÛ¦V¸´áäc!9$5ÍE n?dÑAh¥¶ðµ7áXïÚ}a`¹×YMŒê†å5ä’ ¨mÄ÷“Ũɶ Z·lfë£K뫎^jO%-‘4pČԙœ¤m!$“âµ )ãYdz™Ü†aÙíÄF9½­Ý~L>à€ÿ9Ëõ½Ø,|T,†UQÿùžÙ­$)„˜°uFì©!Õ˜mi LÉÚLuç,Z*¬ä‹‚`é+Ëo¥¹­·I,d"n•TËFfL4 ¬JØ–)YãËÊëXY•Q„d–eÖè§xD;ž+C!ØH¾}Y=¾‹‡o®Äì\/ˆÂדæ×4²÷vöD|)#¢w9m„EKHo†l¡ãè‹‹%'xüSGÄßBÐ`$CÝÉR(¢Nœª˜(/ºÁD̰U6!˰ҠÃɹ…¨kÓOäey1õº!ðd#¦¸©ñš÷肺P°½ožÀɯÐáKÙÖ4‹ö Q6VCñ€¹'…ÀdÁ «„Š)4L(y ¥ÉuÍF´7µ 4]¨ƒs«Æ o¸/Zî|.bDâÌó:E°QóœñqÄî Ö»ž\ÄŽ%™ætðyø¿”…B€{g5Ó›ÉfiPÏ ÌfL²®µ©¡™”@óÿóÿfM¼\ÌßÚmé÷x³¼¿k«¨[eC‘<]ç•”C@ð‡k„¯"Ç$3UàŠCjb˜gªÃ‘#>ÛWÍùüû¥S³<5#­‡Ýà~¹÷4˜(yxp9……% )T(T¨ôJÀÐMóåÛ‘äæ¾ ž]í³g_Lü>WW;£'‹—kn‚‚‚éÈv7^Šâôxþ§ïº§Sºþ»ûŸcËä½]/zöÈ—ºÊÛï~ì‹d×8˜®V@ ¬‘$@X*ÁŠ"F @›<‹’( šÅUB‚£nRL_†ñÓ’ ’²¡‘¨(TÅ_¶G¼@xôvéÜÐiÍó^ÏÈžF^4½‡¯ ¤ð«,‹Kl¡e–Ê€¤©T¶¢b.Ûºt ¢–ÙlU¦švμ½ŠêH8טt!≽g‡ÄÊL¶®«Ý+Æ@|Üzó¥vY™aŽq0Ʊ5+D&}å4‡9¡š¤B¨²,B@# \¥ª€_Š›F’Ÿ-WyÀÙ뉼±¥uîbOXp*f‡ÖЦ­«Ö…ýF=T´j®›(F–ÅSjÛ¡5±Jˆ¼¨j¹\ƒ— Úú36£ÆÞ=brãlb@Æá1bÓ•4Lqœ¢Ø›`5¬…ƒ›£I üŸýºÎtÕ&%K­ju¤ ù>ï©ÏNúv]"ÚUX>Lí:;óçÎ ËÃaÑ ÈóXöxÆKÅÆÜ’Ùð² Ï4°Z‚‚‹#¹Ëzrv5]¬N“nV,zʆN›§@AÀ(&1¦Ïjž¬Ž³äÝ ³¯hÑ–oe"ÕYÙ‚«¤ä±ï1ÍÅ;ºöüƒônœž î;«þúœ·åðCÄCÏäó79˹š\N¼ôU´¤aÔÖž²µI”ƒ B&h›‘@ÉP6醊I·‘˜a€¥HAB¤dÏÂ~/?ZßÑö¦»Iw±´ ! ”ÛM´4Ú†±ˆà”Ì™…ÑDµÒSnµsST.¸ê¿‡ó»6߆×|0TEW2•q qtæ—3kr̵˜ØØÅnRæe²ÖÔ2å\ÅQÄrܳ02c¦£ƒ­]n ™Zµ ¶¹—ÈÚeÌFT©m[Z}æWM&L¥´­µ úmtZRÄk-mbSF‰þÔ¦TiÉÿ9ÜçÛŽ~HvwÅùþY¤‘U KYmáÅTìÖ3!UæW+[Q¨Ý3Á…­]Sö¹5¶®aT¤­¤ÙiQe{! 4oôØZW«½åñ‹<°RD’H)ˆ\Öå*A°Û,2ž¬ë«5³{°â˜ˆ4"¹­³LÌgÁðõò?Kþý/ìü[ÿ‹ë<¨OÕŸoÇ{Ÿ 4¼!êp|:+@P ò±Š%Cb€s†-Új}Ú Œ@¼°^` ‡nE’ £â¹—ÿªNß³Òß³±êéçÃa‡e@l7Y…4°þ'͞ǭ¼„#¸«gíÔ@ňd‹"§ìû±•–ßÜQ6;¬$ë(læB¨",þÎ[H`L°“ ƒ}>«9þFù™˜´ÕÖB†ÅB1€‹ H¬H‘¢¡¥ ™QlZk$έF$ÙÕÚ’EC­Ub¤¬X²HBF&`£áÃÅ“IJŸ·û½ð¨jwŒ$ø3éì'®˜^öÃFü•£©JfÒˆÈ &µÁ<ùy,¿†³Õü,宽hÞ/ÞK+"MïÀ2`"(¨Ém²[c<Öló Ëàâq&´“"%µvm6Ÿ cÖ°êë@$\ùšíê#§ |DŸÇ$q·p|< ’[kY*ÉÚ¬ “T ze‘CˆAX™*¬'u9 >ùlm„‘MÐÀ6~QúŸ¸O¶¦lR”­s&knf áEQJ6ÔµcQ´ûL.Uf‹\Ì-Âåij%³(S JTÈš¶ÈL&Í0ÂlZL’é  D«kijÚÌ®BÖÕû”3ª7XfU–ÓAšhêÑŠ­ÇçÛš¹…¶2”UÆWfàݶ×ÛýÆ}ÆüöϺ賌V<Š@’ð)“qØ¢äÅp²àtôUayÎÿïÅJ½´ì‰lr"ñ ÎýÁì¿«½:ßcÜó!›M¯ÿ•ðÛê'+p :¶øÙ­àxI$C΂"Ï®üϪÓŸ_K•tæjÄm,Ϭà kbI¢U"Ã`´4Ì28cl°ˆl›‘uuO±KÁU5†Ë™«l¶Õui¢\’çÀÔ.Oq¨nÐÙ°¥¥ÂW”j>¶€ŸvÉ(ˆ|š•¾ù|¿3°I,×·2MÀà?ZüôPð¶"Dd€²h;c$ƒq?M¹Ü~#?³Ž±Ä§8x L»š¢ÉâŠymºPQÉWW&2ÒÊ P„8hr&B+ÛC¾ 4sb—ïšB”rƒV:hŒ:S15¶m5;ha¤6þþUßú†óù£9óà=<ŽÔ›G˜Qwଽ§ŽÐÃR^Ž B†_C%L‡}‡â[˺×ýÎwñ¿Äº—Û¸ä†ez ‰„4Ÿ°Ø¹ÉÛ°õò:÷!ôêG¼ßw“‘„DUa¸†’\†¹Ýó¿™Èíçh‹ZÕµŒŠ}_Ô“‚%œS›e™ÙÖ…Ö]'\MÅ·ûò&(ýµà`½¦4§kþ}nPÎ0åx-Îw±ˆ{[Ø’™[œÝ*Øs½)ÐôÐ5ßøfÛ¤‘Ú˜è\ξ£–ÅÑqE(¡dáôÿ¡ilRô;- ÕK841Ö–D¤HUˆðzQ;£÷´vÃb8²:jIŒQ„S@ׇ:Íœ+|NއÑÂVŽO[èpWöh& tÄo¸öªßÍþm,i@ÿ.©ùØ}»¼“†uR2ÝK8ûL?™Þˆ+íÖü¿Dƒ1„ä³ÊF¼BÞçÿßí‡ÚxYî¼ XB 6± q=ŒFJÏôøÌþU“ïØLM!D©ZÔû ¶%Ü–l«Œåu”Ñ×µ‚Þ»cÿ¢¹pùµ†Soð_‰2þÚÃ[•…o0¼nÑ ›7àâìh6pÖ³Hv œC‘ÐïÔño‘“R'ò¿:4‘Nôÿôn$÷ÈPAABɪ…þ݃søö:¥—©èñf5½ß¤¡;ŽÃÙfCSLyÞ›i§Ÿ0ØG:ÝGO;ƒ åýJå=;ú-ǦÀðÚƒþ7©B'%ódž6èo¥¡3%—®ÏÉ×Ü_‚hÑÅIbTÒ)nF–bóËàµ%h±%檓 ®ØÞõÓRx,Ý“?[êzªö8.®¹*õëÊUÙ°Ä¡èõ–`éUÅM (Z)RMé¿Slµ4šŒôº=bò»V9y¤¹Å5GÝfìÌ”¸½ªï«Dº¨÷‰[L«(¸-M³1™{UÚo‡{Yi @ô/.ËŠ½ô3±W&N+Gç!rù‘–Âu´ÄTšn]•E«8c#ªë¥ÄÛWÿ9f´¨qZt¤Pšõm$@ËÌ›ðéLS‚+Rp,'ÙûG­¸ž' Ì] Ï—£—rhÐÕÓ¤’Ú8†“©¾á÷\³É§ÁçÇ;ÑU_õOöï½Áxþ_7ƒNkOLÃ|ðÃG–­[Iöì‹–[KQKSÊø>2MУu±düj’I>…Š{ÈñxTy¼Êf@ã"P gYÈVr…—ô¾ûö {ê»æç“Þ.äîço;Žó½daׯ Ô³Ö3V¥l³C>¾òÚ#qìôµÌ û‹ª}*äTgLk[à¾!Ö1ÈržUÖ‚*ÒÑ"E–áï_}…|Ùµ¦r.ó¶@渖O;‚ßxïÒ7/š™«ÌVZÍÍÍ'M*RÎí`i $ˆfWƒ@·×~¬ã'9Äfi¤Í܃îó œÉ{,]¬výó¶ÝßǤÒ^eä· †ßY݇ñP¨“z_eQ™ÚÛjëµ ¶ù†âòôw …iiY5£s"´®µ€eñŽz>z4 WKô¹o8^—Â=™w{ÝæXõì6è î!÷'S‹ oœo»³½X1´îX»ÉvàÞõwrõõÞ<» “ßÎ`±œžsÇÍnpsVÉÆüÍ/¸m=ëÛž¾\-óÍ!ß'žÝy„û ØLY,!ÛS^Â;ŽÏ{s­ÛãÊ(ºLµÏ¨±UAÖ’‹«y‘ø>†tŒ‘½~Ø·ZM—0s!JÎ3auèI>üçÿç©í¿ç“ê'hìôŽ­˜z°ãè%/o§£¯¦é¯^!S¥™/sµËfYü›6†n.»Ðï¸=œñþû¤Äjø©sDƒ£Ÿ_E`ö9öÛõ·c!"ÈKBJäA¾Ÿö™”·ù²÷°Å #ßìT?›#Û¢øþH¬ ¨ÑZÍŽT7 ?‰«  i$nPÊ„öÙy¯Ñ ÄU†ˆ‚D<×X2aÄA4F:Ý2@%-ÝÊÙݶMé»yxùrâµA_HI©rì&`¤½Ëä¯qF°~GßÁÎ%ë¾9‡mVf9‡üßœ6JLÒ.àöuÞC ÛøŸêÇž_æ #RÆH„ Á¸¡ŒÚiÚËü? ý–ÃØ¤Õ¶6}}7èibª«ž:n~±OlŒ³ M@~” X@)›M>oÓ®Gê›X‡,Š ë/Êql-: Ðì…OiP|l©=kŠÞÑ¡Iám˸›æ£[øh`Ð…e°±D5â-4ßñ&ËÜpê ?à÷±€édÒVç¦ç·õB§¤~è¢Jú]vú›èººGcæ…7€Ä{”8ŸÓX¿©™“d³Œ?={umíPÆ}ïLÂ{|~3×ÜyœxØ( ~ÜŽD n_lð-I£d:ò¤mV³=mJÅIcÔ)G‚u¤rï“ËÐ0Õª$B"²-o¤PVƒ"÷˜¡‹Y+ÖîŒRQñDk”)b‚ÖjclN…Å&50CíZæÒkTæÓ XSr”ñIÒ ”A9®fÄÝÆb¡TŒÝoÍ[Ý^€EK+ÚiTÙÖñ€C´ ʆ(îÇ3 “Ë¢·ö ›ï p­Íùˆ‰uæ.-SjZä",)—42.]ÚËÊÀØP¢‚LáÍâ¼ð÷XÃÖ°ï“÷{È´¥¡‘¦MY¿¶ÕÊ`ŒÜ¡.à\ëÈŠæ›]›Vkí"4UfÖ†‰‡b‹þÑjEî«[™xzÆ;L «±ËntÄo@ôžSE]Q)‘Œ¶÷­ìøÁ5ƒ|V20“n÷g3!ª`¿ÏzÜE‘wÒ”†]ä³tY|`Ai®©ìSká{üÔ1A˕ʑ‘dé*†ô4bz,"På² }S¯«Í³éºÂý>+ÅM0ù¬šŸ[ÎónÛr펧‚8ûÞlò—$€ 4H@. 5¬ä—³çnö…I¦¨šEPŠ2pAVVˆµ©sÀ@7ÿa"E'Ø?<}ÉúKó”ñƒóˆíˆO„¦r<í‚S0Îe›M6i2Œ„’GȽàòïîðzÙEžÕðaH­ÚÁU—žnЭ#Ï ‡ÎÍó‘t‹Ë ’¸­a9Û2N¨¦ƒ×⃙֦b®”³ÁìjU@#¤ÃL×;éåù;7—è÷¹½È½.Dü膇Mxhxüç{žGÛð½àMME"9Â`PydÈ H™2c‰…lš3Ût3§¡^†R{Þù³3儦GñÒ•ÐÆ<øü: Æ’ñŠÚ˜ Þð9Lr°‚¢*¬ B ”œ*yB¡@p-©õhÑqHÂKë|¯“G¤%}GŽð4z zZm[0êK]¹8„ñ5P —û¢ñþ½Á‰WâAâH„WÜ:"8×Ü:¶ªÂº.i~GÁ¿ÅñXoºrËhÓô>î‹<¾]¼5L¹;w,P¡€ßŸ:¸¯XȤ !K×J©B©Qï¼… -0Ú\n˰?!öÇ´UÏwǨ:óGNÒàé)æxÊ:­¢÷î\ÔÍ‘§-mÌÚâ"íE–Z­)„pG"6t3mÖÝm0z4AEUY(!lEû»c—k%Û÷žN;øàÚüí±ä•ãk†é·Ð,|üKº$’ ƒi (‘›¾Ÿy0÷½ã©Ë¦ü¸G†J €ˆ[QPTX6"I$ƒ¥”"¤ îìó³W{Üv ß~üÏËæ°x’Míª„†¨”Kñüq43ärÆ c(”ã&œ9w^ rç® ø5ŒyY…ÙÛ,±n3¨y¼ªž 0$Y—´(ÅÕ A$šZ·Å&³H©½•ïÿ‡qÏ™XÓÄaWYAÁXÖì™)¦¢”F‚ 6©ß|Õj²/Ty~¦dm—‘æ½vdôÙv'š+è Oõ~ß>‘–êJÙŸ¯Ÿ[3ëJÞßøœ=fûý¾ßWñ>ÿ+ézlÁ èfÍ;G@¸¬×¥ï·ßHóÕ÷b?"ÉúÐóL¤¼«8¦(ú óXmÐ.áû-¾ÓèþÿßAñ=åEhˆ•m´¬¥ò5YˆUjÙcEAUFú01‹iVbQTXb±-±_›j´¯½(¯ë¾ñm}éÌå½{…ÑÑ, Í"H$…§Æ%]Y¦kò7ѲÜÖ¶[Þ(öap×ýçkVIKyåØŠ*ˆÆAKNV¦ ÓXˆ¬AS°å]úvnõìv:sÍ΃4¶(ÚV¶”hQ-¨”´aRÚÛÅ[lX TezdQU‘Z÷($’IsaQv°ÉÉö¿eõÙ$<søŸÒþ»ó¹3'Õ ‚ɤfù;MÇn©²áÔ6Ê…ñõµù[ :·;ÎxTþN-ݯÓISÊfñåABÿeµyøh0 $ð u. E׬ƒYÊù÷¼‚à¨DuQxz\A±ÀöýÄûr÷“íĬÒ.lË͹~;-äM#*FKK ÉýðÑú§/®ýœ†t—·äÃ^Ò}dT¿ÑM½8'Ä´Aá@PCÌO7Tw‘¢Ø¡Ðà . á@HQláXà:s'ÄÀ®ãAÖ©a  P/âÝ® Õm²úTÄ_¥Ýô$±šÏ´. ‘LöÕÉ{æÔZr»P~›nr[7ö'+Wêþ{Ú1#¦hŽpr\nc{ýhž}·¦Š Ç·3®Ô[^›çßè˪ãÍ[£ã·MÖXëÞKYPÉ{}:=ŽÕ§õu[Ûd•ep¨²¶ô¯¼ñRì´õ±oG;¦|Õ`ä×ÛlkG)TÃéC¶æ˜jÀ]Óê.°dÂ1u[`8굈?úšo/wÉÇþ*èE? yñª¿¸¿%l’U(Õ7¼¿ó—Ý7}íÚ¯ÌÆ§æáÔÛ7IkxåöÃg©A—.n€Ð”à4~”³_Jp³ojÙ]­9v ÜO,pyq•Ï Sø{ª¦:uSzø, `˸ÆÓ‹Bö5îòY]ŠÞªê¯³žT:œ\Ùâ|G'ç öÝã<í§'¸Eó7Q×:.m½|Ô´tÏ6 ì@”Æèk‹Œ’Zòÿ·‡—q.šo÷¿@ñ óšoSI '}(û,Ø”s]è€ã|¬Ë:JÅ[,W_ÿ6§ªUœoFîán½FLÌ |‚„êNªHõ‚ÂH¥ï„¢ýQÝ}Ð_œé“6qJ˽Õèl²~âX(?†ú_°‡g8?€ oŠÖ•v„÷äÖ+ ëÞ“šÕöK6C÷ZaÖ—WiÕ8E.éÝû¾îK¹$HãP#š®ÙëüuüÄJ6ø›ÛijsßÁÜ×AsÁd2=S·ôx‡;ц=Ï‘¥«âÞûñs«õ"g³â–gÞçß笹´YCÞþZâOuS½³FÝ \6†f3¿÷ÛÏjìñWÃqBë„¶dYJm5†ÁÛ±HÌ1­Á•ñ¥œ¨YRü)]t#<ˆ¨qî«øã¶ªë"U“¥¾ï g+âŸâµõÔMßã|.{×Õògdx)//Å<µë‹˜ºÈG”AÆ ùÉWθ•þʈ&»Ý×*w ‹A½±ß4’gURDœMÝ$½÷;tfßÒÃkë4­Ûñ·ð§/Eç(˜g7ø$Ó>ôÔé¿Н}ó ‚r§r^RíÇýÕRåŠU4…áüÃt™ü—Ã'}r~‹Ü‹=ýå4Í¿ù‡†X‹nO€•8îq[¤õФ÷Áàáøg»¥ÿºo¹Ì{ô§_éñÜÆ0(ÏL)â»@ö±Wy<áv3ñø©˜$xˆ6ü»§2»ê-fÏßÛ‡ã©õwÿºß›zZ)—yŒKŠêcê߯³ Û9ÝÁµÓ›Åšé¸rûë°x\¬ÄÕi/oýÇA¶-¤ôž—pí˜â,P…oÊKð™ZB潑XÔý¾~Ž^Õ´Õ)|y>×Ûý˜¤ÞοÛ!c€rO…ö/qK–;•ô^]¨¥ ß+W‰[gY,ZÍçìD'`—ÕV§Kœø9ØgV½—kf ŽÌs•ÐÏg/é6>òTÉyXi¡ÛñÑ~ݲ9úê ¸†{Œ"ú#®$¼ê7‘#t ®¤cãeÔ_Å“L»Tÿf8ýûJxÄނ«»½éƒó—sÛ9’þ„—íþ7j¤n䨶íðŸ]t+C±ÓP«FŽt a_©»ùv«öxÕų¾‚ĈÃäÞ$åtuËWN+ÑÞ¹¨za´ W/cÎG%æ4Ú@«Š½“¸öó3èÌ–'G¶¡üÀÝ|úO¸þ˜8̘=Ë=Éí$ò…$  œÞ»£šqpDòô¨!³??³+úÙ,¡'¬qIQÖš.ÿJP¹,üg®k3bE'•øD-1­5;S\dù¶¬<§° ¹vŒühèoé¦ß#VÅ5˜"Øv9Ô²@ŽßJ­Ž§Œ²³_w|ÒãJWÄFøIÁ@_¦Ý;µJþ¯ð­¾$úJTúšë#ú×jìfè«´?| lŸ^sè«Öbþæ˜gPú3Yg_u ²X|ÜHO‡R®µ®¯-Xí*¤Ê=^ß+d­™ÐD(±«4ŠÑ¿h›NÐûž¨¢ÑÄ{ˆ8~ã0>¬4‡qØñß—Ãì"«µù{ˆ®#á¸:÷ý~ü;|Õ{tîù~2}ýþÇ•"C™–¹ÒýžÀ­0!ÆôÙÏvÓ¥³ž,X{•&ô~7m~IkFßfÂxÚ«ùúäÜǬZKî<ÆäÖ¾wGÛQ²*°ˆŽ_¯5eÔ¾úVLyŸ{ñÀ|è’á"úÛxPÿŠç= ŸžÓëã¶âõæ8Æ=ÜÏT9Ôuý±Ú¨.8öv˜f%Cçû(ø‡g¹D/¤Ú®:놷'Cæø’Ù!¿€æZ¨,kg”Ó}’w³ŠäꤰL8{Gô¨¨³¿‹ß¾]É4à,oÙÅb¾²ÛWóJ¥'É—z°¹z=¢CßOqRñ¥:6ÿï’W€ZD¡i[ÔÂÓÀíÿh  âãíøðÐñªê¢A—‘·Ìíqþ译so¾–ÁÜÍkLOk¨IØÎ ÕÖF;lÖò_G³µ*w.¯]ái¢\¿ÓÌp9Fš°á3~稹F”ùƘÿ™¨Ó”®*TE (7žwõ›„ÿ DšùðmS•@]8ƒ{ã~ŒUú…l€¦HùÑ5Î+xG°%ÖwV"ɲ«!Ås¦âÒî9aÝ5Ñ<ÚqÝÓ²yêMbÃçuDŸÔ^TûhìJ¥Dgm%ì:Nº3Ií2 û*T€Óóic‘Aå¢V*:äXAÔ¶ò42üÓšÈò},?ç{Ô¯Tëʓߞñë0Õ0Ð#æÍñ>Wt)iž}^7uËA—†jÂèÄ;;‰0¶Þ‚U[ ŽíÿŒÑåÃ\ì¹âJå—,ëx'¸Ý5©ÑèI¤ÝÆÎeM#ÌQÄoazÕAO£í­ñ)ßä}ûE;®‰šŽ‡ô[†ã(Xq†*k|k's›tà€½\zI†Í&a ÎÍ9i÷øwº•ŽGmЮÆx5)s#Ö5˜Ù‰ûm.‰¥??ÂØiíÅ;`ûS–?MšQSà;¡á±";Ž¥;œÙ"w ;àc銌¨AO/“Íù9|ïÇš=¶Ÿ®ÜÂ0€€i<+caÎÃúFä¥äH™råìÓ¥¹¼~ % hR×þî"¯¶¤-hÞ.#¨z ™zw2hH¨wO‹8ÿIœÚü)ºÏaÆ­¹%Îk[õäú¯žîJÙŸýï¶n@@n¥NÑvuÞj1Ÿ ÒRvb„Ê#ýAë)ìñÊ$ÖmN©utò2º¾¯¡FŽ›„•}ÈZ¸2Ÿólç­Í2&}#vÊœäò¼…/ˆš~âxþªJn/(üß‹å…ÞCȵƞ´þ`wë¸DQãÎØ ÜRðè;Ò¨$Ëdï 1W¿©rØÝ‹¢£Kt-¼…ò¾YyVˆ ÔÉ“+§ß/ªßÑÞì¸ö¦sèN[^ TË‹0OjàÀ«­×ýþ»¦,Bø~MYÑÔÇkßY«¤T¶}‡­˜XY‰6쾚Å+‰42ÙòºR°/œhå³ÉÚßv33~DfûÔ/`gÀÐFV0J»Ï¥"{¸n9k»ù…éV"×îš{üÿ<7n¿õ5þ4‹ÎŽÒ¼.”m¨io>¯G#[Äh•!ÃoERîPâÏß“ïÓq ƒV7Ÿö@œåŒ®(‡BÉ[™áæût'5ÿJBšOÊù\üä.³ûj~4Îcš}yX<ጳz‡sì±÷˜¯ïXX€€ÍD>ØÆ<œc´¶Îú´ðµï¬À)¤'@]¹ZÌ¥BT¼ÿ]ö†¸Ï|ºÝåîiÎFÉ”çk''þk·2¨F'ýô-%zßÚ¿ßÉ?a<õ4BdKZâÂU•‹lO-Ž— Ýt¢Ø‚ z(”L¯{âÌÕÈÑÂù3(§G[;Ô¡P’Hχ –E¾µkÁêQD»ìÕÄ‹~ýOR=<ïÏuLûØý8˜^µLòÏ#~r–Eº©ž‹^v´àº<î?®±ˆàDi¯"ÛëàÅ…Äí§7óž—Þ“ã­¹:l˜­*V¯qžX°ŠLWw`íô"©ûO/‘=«.¬‰òP·é«bt¹š‡×Ùmf±›ªVïŸ4¬ªÖHïÚ¤Û0ÛɇRÝ=/q‡Dó‚‘îd¾·~Ú—÷ÿ™ô6°&?€Ø’:C'ÎŽÍxÆùpÝjúŸ®:F±•bžÊš£î¥£¤¡vú™·ò'¡Ê.ö(bíßD˜¬cÆÌXu=›Ìb·U>g"¯?±vGáβ‚ð3<>ál¯ÃÏñêÜöæ×µ<Æ:^v‰õzUntãAâ–o´Éãmu^àÿ‹,‘›­ßª”NŽ;Ý6iÞËîA…‘þ‹ŒW/׿­¬±_J}[èüQ?^“oùpºãÿ|ÿ^%C|ÔòÜz˜/~j´‹<; ‡ýžV[»ž¼~ÃùÝJœ,§Î>y*·™}*‰_û¦v⦋/ªÀ¤‘îómBa$2wyÖVsö”;ê½7§•óÇË:bš?{©ÉÉ,,+¥ëâ_sV}x˸;sõ£5¾ÉOɧ™„ZR™°¹“°5–š!Ël§ÕbÉu*RâÔÕ·Ùô»ÎöxÙ¿dP­p*‚}ÉdÏ’•ÿj˜¾LÆ+w±faãö³üäyôö•§½zmzøì•Ê·Z%>Ês_¥¬ª,¾ûþ®ì¨}Ð> !î¥çùs<Çß´ŠIgŒLã’8ïå&£M êþºáFZó ŒwOÞ¡†,½[ß©4†–#òNÝÚZ¾GÝ‹íê¼u©æ0)§)dpôÙ²gèθc¤EYmoùöa­y;nÑØjŒ¦ _/AW[_¶>…G‹ïÅ’daó¬rÙ@@ }ò»æY?‹÷3åJIJÀ]Åâdò1p¹lftUô#©i—k!ÈLRo*[H–R¥¬¤^œ?7Õ³9ê÷ò7¹H²|Y¹+œQV­î#':¡öF~¸¨û>˜x°âïÈgI„ý…]Úš Þ•*€`11ƒ€P{C%a:3óL³1Æø·]%4ví^ç÷¦ÕŠ"Í¥ïÄ|ê'_g›…æ>Y­û©:\5¤ÿ÷â³Q±ÒФʦIœ!ßjÆÞ¥cNBw“öøÜvZvêO_TÎjž鑵a"^¥ÄôÑå¨sZúù¬‡T;U ëŠÙ¶mU)yp·ÑÁeÁèØ*«˜ðÚP+»Ò$ç»Ï£Íÿ”¦½/?+‚×Ù5OÈâ\C9ôŽY0?´¼qØÒœÆu¯í§ÊnF8‘qï c¦Öû^ƒõþ1Ó´ÿÑìÓ}Æá±Ã¨ó.XíìùNÏ?ÜÀâÑÚ16™kÖíùsm›Á%ÅÒ³P² Ãè×¼^v­÷‘µÙ;ÄêgÕ«sêt¤s“­j†½ H®^ÜZ壋žWùÿ«½Ô³è+!S›–óûü 7!ƒ¹gÞWjêÊr8Ž敷Kž–J?ëÃè7˜(ÂI§ZÈ þîΊš>ó/Ç©côÃ,eøÒxÚa4øCïIW÷æžnêßäú­0‘R†âßÅDÍU·òÒÖa»?8í^´n~+#2óÇòÚ"6 ÌùuœUßC²®¸û¦LO ¹h{iKZOQž†ìÍ”[ɱ<ùÉysõI íÜ}ËÿOK–æÏ.Üýãx©œË}å˜kƒRîF-»Wë’ fÏ1é_¾»…ý£Žß È9|_Èòšs0¤y¿Ab4ù·y89Ö2>¸ÄM3þ_º5ÄõïûoYÈï@ŸÏòå9É¡¥ç±5•\ñGÈ•ôzcù%ègýÂtB/«ªÜ)ÿžÝofdÀÕ‡?U'2’'Û rÇaýMé[¿ŸªÏ×GsÑ °;»vÒ2Ú†,O™ÎÔ‹LÍrÄ9O —ýO¾•ê¨o–Ágê®C©Ä¿”„ávÙnÆd>7c¼è­U.bR;]Öë­ßé63¿ìL&µÇõÜÏÇm¼öžÉÆz.¯:­l}v ™ttkÿ!O¼òƒágm_’öažÖhsn'ë¦Õ¡Ú¡ªhšüæ·¶×xßõ2›kTY)ÃÒó÷íC8Niù%ï„unçVÏ›ãPœ™»¹Tgï¾ëT S?¥‹È<âu‡ô~xšÚ æ¿•¯6?e.«–Ë­\¨rvµolŒg*¥„TxG®¨}UÕ1ØþguÝ ©öLÉo¤û£Þ|ÅþÌ®³3X©Ã‚ïöµ¡}¶ó;¡v]RO"ýfßËšå™wTÖë»ÅV÷ª`u‹-¢èì5r?Ò]½{7‰øèî2å¹ ú‹öU®ˆÇêýÍã¯ÔõyG’çî$ ;ËìÌœï>¯â¢Æ.J­Óªh©] \Õƒÿö?¨•§µõÀU—.³œùªçëý¿ûãvM¬ WËk{²ÿ’\7“®<¥Ý¹ñü Ûgú§Wá…ô·´/D/1=yËELó|>k;<'?Jú»ãœ¬sAsC7 :î[ÓÏ@ók_\ˆ‘oE°Ìþp¬‡‹îrE'Ú9 .úI”1WƒçUåíÕm•}ˆvù?¾§àx:h\ŸŒÆ*_mÆ‹¯2eÙ[‚¦dG#xº=y^ê§ç±ó]Ü·âú¦9‚’K1.Ê×`¦%± .û“âË0q`{èf?ëùõp}½:qË_²ô;æ¯mûÿH²#’N¿óúëê™iQÀÿ‘7¡ü7fyV<‡)N”9_78—Oûúõ£ýEýÀ[sôïx½”Xüβ} ñëþsè¦=µ¤“¤†çTiåøÂ ‚žÛ|qeÑ:ôäe4ÇFõ²]=Òã´ÒF–¼yöalCqŠîÃÐôC§íûðÝæ`¬¬(Ëq¼ #Ä‹ó•ùdûÅš÷4›¤\¼¨ž8+ÿP‹žÍG€¯Ëí3ööd:¢¯pߌ4{eHó ‰`ã*%åYfÞ±ý’ À²ÜQK î›OjZÛ˜¸…b ‚R‹}`pƒÔîlz<‡71°GEÐY+ž#0³ñÍiqÀ²îWh¨ªÿO÷‰°G¡OiJcÑwRÄk»ê"þåãñÅ}%ÞM7ó Lìˆ{AP|K0ñP¹  »^fÈ2#U˜¼û¼ŒxnvƒÌy†¿k óÄ!éÇVVÑÙ×: skÝúÇ “Í5+Â[Ú€º­ï…þt¦.¦:œ}U$ùù“Vt%êÅŠÜé""fÀI¾Ød¾ [÷ÜÁ"×ñWÿ;@"üyôè'QQ-ñ|)þÃá cpîWºüÅóµ_m5¤"©^âã2W]ˆ„ »66pO‹Ó®Ey§2ýGÄý2Í´“ûwPÙ£EQ4òÄ8z™ž)Ž´_;•J «9ÑJýN‘eRôlÖ^‡cßÔ¿õ¼=MóÓçÔ|Îý¯‹œ« äzõ©ÔŒµiµÃ],“°½4Y0ÚSZYgàGo.§ ¦ ,¹têI$Ä8T½•¼uÓÿÚ½g׊Ã{+OnŇ#._<³ûP09oÆ Žcá¨tÕН³=4kN&s/1íÊú'Öw·Úÿ@Àwì-4Ì öß=ýr¸èùú£¤g–$ßï—ƒ• ãcé…gÌÅì·°Ü8ó&¶ƒµ9Üñù9Cè'mcþïŒôåq4™ZÎbÓ°^·ô:°ïýeƒŒÏÒ?¹Ín+õ(Ëÿ'Çqbt}¾j%ž¼ÇMfflÍ/JW¿TÇ܈€ê”î:ÿu8$‰^èáßY¤ºö8hn;t"Z+æá^£¾Š'c·4T¡Í¨Jì7UpUy¶ßGEþ€À¦,~â<~vE™£U.ê Á²Ž+ÿØr¶h¦›ßò¿²Éàúö¶‹U³—ÙPJ·ç\ª“by%ý¯–÷æAeyz÷Ê?mç¨Vn¯û¥båÝùPõìTÿ_J·=qöW/C aJ¡ÀåáªMˆvÊ^!Z ååQõæ rmÃõ3#`™¤Ù ¹¿aßvÌõ²£›=˜£­Q§uíÌÌ|_S>îLïÎ0ìó¸tÆÎtûâµIK•ý#b›æñY)ˆó³·…î¿nà 䉱9 Äv¼Ü·ç¼7æí,s!'+WYóû›¸‘½ø ‡ÚòW®ö·þ^iÞ±Ó¼J÷xºù}>Rí&¹—V|ü­Î¯£à~KŒgö'f£”,šÊyJžo‘ÏáñÿÅÄ}쑇߲í3_ºÿËñæþŸw‹jøš›¿fãGû³>¢4“•R£sÃ0ã.(´ î$޳Òót1/°3F2—£ïò6~µOGMУŸ€1å’þ‹\HÕY ¹/~½t6 ŽÍŽÃNzwi顺`¦D—}15y>ðU‚Õ6 Y?LÚÌùëºCšíÛõp6 O²[ð¹Wó¾Kþôâ—Þð‰›>“îÁ6éîz 9ë,å%׼Ā :ƒ‚ӣğþ2ÎóB€Ñüý6ó¬½Á|´OZ󜀟Üwe…²\vþuºjŸ5fÀ šXw,f•ߟãòêXâv‹IvÉž¯Ãfþ#mÜmÈR–v:'JˆyHqÇÊ‘X_8=BrÕ¹i}™+9lùŽ“]ÿEß›‡(Žc°ùîãþ1%’tïÔ3ÓVöÝÁ NÑDfG û‰ùH¿cºúTµÏ£úèU˜nÌô/¢ôWÝže–èšq¡Ý I´cÒ|t·ð‘2¯nÙ{õÝ\Géy.nb¾q§-RÅ=[^Sã“HìRXâ×)|Õ+a½£qîˆ.Öù-–]ë+½0f^T-=‚ÞÖ»^oÆìœó¦WË¥OWHÆÈ·æi†þšñŽ3~õïòÓ·õHm:ßÿ{=pL¬ö~Öÿù‚UI- ‘wu‡ÅÅ(U‰À–Ù«‹Ùl“”6÷¦Ž@ä|ÊKð~[}¾ s±‘€!ñŠùLÐóõXi”˜Ùläžý°,E³« פΟ¡Eÿ£.¨óm{é1BêϤ¬îÁQÁ}q pv:$zØr—þáÚ1É>ÉEläT,ó«Êv€ÙJQh•ãZºü*M({lý°~r¨À¬ï%`ب×|¢/™÷‹‹¶o뙫#5T³óË­$ô­ùí\3{¬¹-%mÉ?÷ÈåÀºLÙ";ͽZ`N´]ÐË>Û‰ßé^eoW¤êòŽÊêÔÙ8B\€{yˆ~ïžñžñÞÆ¤‹E™¿ÝÿÔ^ß¡­BÝïU×Áu¤cNšèÓ0¶î·ñúå}üÿ¼Ñ‡×Gò‘«ðíåݬ¥×\ÅMÛò£f‹Ì'üK(i¶ ^‘TÇJ¾d¸Ÿ³o“5 åšÿbÖt¼´›%cõxÚá÷1n¬K¦oGJ.FCvÕˆP+>^%”j:µ†›í~Ö·ÌHÞ(ìõïU~Š\®-Ò`Õ¤Ü]#f®©í¨L,wí–<ßÕm×DZïeî½—¾H¢ã4B˜´øüéV=×&¯;u’'ÞEŠt´ÿ­š‹í‘ýõi•[Æù[z§)Ð[`5Bjb¿¡ÙP·NÈô××öÒ+’§ÓUY^V¶}ñW+< <}I£ JD®c×~$ÓÒøtýÜÐ5íAj™›©uK)]3¸ï.ŸÓ¬a{)ž¯NÇ g•ÚÑ*Ï]9¾S’äÕ4Çf»ï ¼Û@Œ%m&‹‚€+—'õdcñGôdwÚ‡ëí[Â,½2Ê6ÿ]¼·›h<ŸnÉvâ´Z—ü˜VÇOËm3Öq¤öì|^þµe`—r•jäÔanä\’Õ‹Û}‡5Ôê8έy}(1 ×ÍìyÖï¬zHI¹|æh[è&[쩌›EJÿÕÈì#•üy—oH d] 1GLmøâÚðQn¹PÀ9’äIw:|rÅ?a££%f‘æW‰*ûÎÂár€,¥çZ.A†@Å Ü‚ÝÒ %‹OØûÇõ[¨Èe]Józy÷7¥ÎI{ÿ¶ÚŸtËQên2X÷b+!øˆzÌ¿Dì,Ùó‘Ó¿g3O|`5ä{98O¿ân'ÊÁö?êFÆÈ­[k?Dœ\òÊüe64Öõl÷Ø|~©þre+ïR3í§U5[ìèßR(‰ò¼Ò‚¼FtêįpZd÷¤©58^~]–™?¾·wŽO¢AWçÐî3µ°åÈZñM¡)nÖ)§a-tÐz˜ñÆZ#wß‚º>Ç@ ÜÆv¼ñÝCD[ìiØÒ¯„1¦ ^¾^ ®ÔïÁ+íØÿ´éáÎà›òAæ|yŒ8”%ÊÔ˜ iÝêBcþ©tì–Œ ’”`g¼È °¸SÆ+â¯TÛõ²YZ^É0/ø‹J†ý.Vì]D£ªk’ «âOò³ñeÔ¥hi_O9†“ {€®Ÿ”dTa}¶ýpg-ÙüJçò:8;¬’ú9WóDSUér²âË·”%%PÑž.œ}¶«~÷¯·‹ò”³âQæBlºŸÈx€Ç×@A¨>Ôiæ(2òǸaª¿ÑéÈG>:íp;»©Íœfˆó,%ΉT×0ÐŒ¬ÒŠJ’=~”/ó:&ÉWv±Ïs‰"_è>w¡f¤+¿Ñjžªö“KÔ)_Pgó7‘eK·U¥$Ó"ò“ 7N3ë¢*}ßTb¹íÏ¢^ru³àâ³Ú wÒJ]ÿš†4OŠšª#Rv«»Ï‚e€]…¨§>´©–6·+†I´yYŠ S\ëv#uJâXç²ÿT3)Éñ¿¾Êˆ¢F2?¦/¼júŒ. åEÛ«××þ³çC´ÛêÖ¨A¼—¥ú8Oêîzþ¾Îtô’#œŠa~ùqs Ìxýë[[&–뎲‡n-€Þa&¶ 4+ŒæÒ}{N4ßnÿú@«Gø7 óMÑËÏõJ·Ê©€}e@î»ß¿Æ{ |VC«(§±Û_^Žð§.ÔòµTi> g…ôzr"Od¶ÁÏýN»â"¾j]E\¿Á¿?^Ô=ò²é÷xš¾¬ÔåbÿbMO4ón㘌y8^Më½FJâžab²½u>rôzÇ/t­û†›þ?oîqæÅ”«ïÚàw  ‚£vñ Í/E®'Ž{ÅýÜc9Çìkþ%žB¯°«’¡«GwÎUÀÄ’°ä»v²jýåk«ò¿FT2 CÏ#6ÝÚï{K±þ:•S·Ôvaúl8–{‘?åOžóùázñÁ®» %¡ÑkrÓ ]ü÷ÿ]“u% Ù?õšï¢{?‡ø4± !=×qä< ‡WΜç¿pà,i}'8ÆÂˆˆËðîùÿ—VÙouìß•c&Y]g¸DTï6Ãü†„T£¦~½C éðIhÃ2okå|øßǽUŠv5åÑïʤÎmŠbŠYf›´Õå±'9Zó¥«qCX§Â=Yœš(#›>”ñ6ÑûÂß×ÂG±ùv²šÎz¶Ùž •ŸÃQܭϤB¸gIï™~êw÷w–5f·8媭WÆþÇøÓ·„lc+ï;š=Ñe|$CéŸì„Rfí ™é»woÅqð+j½âB5<ž×hiO1Ь°Ú”ñÒ0r¥8œ¼2ú~R/Uݘá“V(ǨW0ƒ3Œ cºÄìµØÿŒYÑô‘vl,^t)úÎÚ2Ÿ$£ù­Ž fñ$ÄÒà´îúÆÃb·KNîRŸ€òY±J¥bxã¿uõp¦v¢Ñø ¾oFWyÒNi¸±h]-w"K¯¯9ÿËÜö@Û÷¶Ue `åyÖ<¯]]Œ~–ŽGW'ñvy—»æMwæÁ"£V{c|‰5K° ¾£F›îSzå$Gb.£r%e=àûè´f4›ÚEf}#A·YÈâNMó®™#cÛžüt¶éž\ÏCêz?öuo´†{&Dú‚õy‚¥Òª°ZË0$b¢ë¸ýYn^“Ú×<‘6íÈVYŽºE™½rN~ù DÓfLåJ•³'ä[|ÍŸnd5̳$$7aŽÎj»,ÊVíã:Åã>º×Æ‚]+ýL÷Ìä³`ø]ߨ¯jy t»<²ÔÎÆDñZ/σêÏvÊ)ÓfZAš½ma²Ñj:Ûà$Ïg §‹ãwÕûç»$8$YõÿßN}'ZŠ-WY^©¼ÿ?ÞÁß®š{á4çt z½óèû?ì#nl¨³íµ«Ï·8ežIÊ¥wú¦ºcEÿYÙR®Á¾†²‘Ù·C:!IòG2–œi+:Ö$z}5^ÌL„Hþ‡ÑûʧzÛUÅ$†ªå7æeØõoIkr¹ ëõÞ1Ê”e¾JÉbò¤/ºì©§‹YÇÕÃ0#Ïx3ìxþÏÔ[6Kmn—~;>„_·â!wéØ[BÀjæ´†ñ–lß’ˆÞµÂó#:žñ.a“Çc1CòŸÄ“øìÎ|²Iy!÷ÕoÏ4Âø­w~×œÄ Ñõ§1‰ÞIl™žʹ;"ªíì3Ýȇ åF5¾Žb5‹%wkÊYbÕí£tå µ1+¿_Éê•Çé½4iO÷K>¥SÁeK¼ˆ €:¡¼âÛZŸ^OÏÀ¶EzéÒëú’wÜ!Œd:°CÛæ\ßÑôϻʫè;ÿ4­Gφg€»ÕÎTžVä¦E>ÓÍìd1˜Ÿ;Ý_S»Q?%£/jñ´÷zµÊÊżaj+ívc¡yLÅ•»í£ÔÞ6¡aé÷µþ>ÔKoÃçdûr¼m\ ¿.Òö‘OL&Ì·¶¸õâaL)o©ƒq¶ãœÿy“ÏýqÌobD2Ô@ïT–Â:»“aŠã±Æ¦î·÷ûÛe]Ï„*ÞÇÖœ%™KA{Ø*m÷7Íòš2Wø‡Ïrû¥}NœyªáºZ+9¿«ëçü`|³ÆOw&ãÝ .’2OÝ2aÝrûÝ€rnUÓBÅÁz0=Ôi›Éÿ’=Ni«I;Ù™X ƒ^.ÐÙ N½4Ië#$Ÿ'ÿ1AY&SYÔ éÇ °ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿá­Žf3^.À`8P {ÝY'Úç¾Þô7ºì÷¯{ŽÔo{oè|À{Ë6µV™áÑÝÔëmµÛr³fß¹ôeÙ¶Á}ÕÕR2Ñ»®§ÒJƒÌÏu”íT³éK° :lj•.ŠUz è•(Pzê€Û|>cèûe}{ÀïŽ<Æ"ßÀè§”Õyð¦u”žWÞ¾Ï{ÕmvÛÚöß\ñÈ•è=;7Û¸”ûï½{>xãÖû;€unWC]ç¼é½ò»'µ»¾šaGÐãë4 Â§Þø§Àï[ªá³o»»íÏuõçÓ·Þžï7Œ€2jµ-34{¹{Î 94ѯqË¢}á÷¼÷·1½Îë¹¾Çy—¦§³B"®Ý¨­°¯ŸyÛç·:øÅ³S>™Q¬§YÛ%óœÞ׉·¹€è¢:ÒP¢ØÃm{}Ãà}ƒÄ•D¤¥Púû•B¢¤Šöôy¾ï‘A!UQyóæ*TŠJ„ Ûبª… R”Ÿz<øØè˜7¾ç6·vaéÊÑ ˆ 9»½çdà/`ÚÃbìv-¨y·£ÒRfÚÑ|ÕFÑŽi†ÓsKóÒ›:âè[s´@ÓC… –يҔح´(!4Vàh VÁÐãw@vûî|Ün¾ãÁ¯»>lÃâëá÷.·¾ª(ðô½„ÇVÆîíe±‰•b­™H·3ƒçŽóê\îÚ}WÜ÷z›ëÏO Qm€/»€Ÿ;ï^ØYAo¼ù}4ú ê€:ºÑÛ‰ŸÛcÞîÎgöhÓÞÎ{×\{Âðõäqê&=*ûçÖfÛÜ'fm˜ÓwáOU 6æÅ3{îñ#ØÒšõ®R¬%PËzj—Þ_wÞ}_mí õ—k!vÐIléÓŽöõ×Üêû{±Ò¥kTºúéÄY½š@U- ª¢¥@DZ»—p» k[ »iN׺®Æ­‹{Ü{Ùa­,kA—»PvÉ•¶ÁBi©)ÌmÊIßzôt2û‚½ëÞí»ºÙ6ÚÖl­Ó(ëu÷ÇU{c|ûÞw’{#ÇSK a̪¶ÍÆ2­¶ŒMº8ê®Üê¥Ý¯}ÛœÕg¯½ðÛ]Ð;>õ£ëà½Ài!a˜Á0&#&OCLhÑ  £ š4š2h hhЈ4‚44M4$ÍG©ˆÔôô”ôÙF{$žM¨õO(ÐòGŠx§¨dSiQ¡ dÑô€PÈÓÔÐ=A£C@@¦€šˆB4&*~¦ŒL™ ~TöMõÙ9q`cf@‹0bV£«X"5(ÛfÖŸÍ„$þ\$ÚEß ÐOÔ!lâë?ÅeQq‹AT©E´+E¥¥ebðA.Á­FB°Xª¨‚ÂAº Ddd’ ~×äÿ1õcþø´‰P;,á!ø³íÌÀÖ{žëÃÀ¹PKãQïg¥á{osávØ›ßî|Ið\Ü ìåý‰×7²rœÌ2gׇTÀóŽ$Æ×sEiˆë-®ûé½y„ÃhÛW;þÍ=¦Ö¶&U§‹ÑoÚY ŽA¤ãŒB<ãˆÆ1‚0—TR°…UG)™VÙ ‰U…TDq)™I™l˜‘´*UjQ€A¸Ã°õ¿ea½~Î €b‹ì"»€÷‘|Ô>$TñbÜ_ýã¿6à;P<¾/Àõ"*š0"ð‡âžZÓãÏܱû#W0§½¼ƒÈ(1°À1ä~í#ŸGü`œ¹ k tyÖôP<ƒÍüŽ¿äRßÔÒSD£ó¢ÿ‹…¬PâjR”"ʧƒ*^p¼Êj|Rf,W‹±£-¤ÈÅ+œ‘Kå:‹§+&ò®"_1©±I.ó 1*f—ÿBÓÞ›¿k_Zþb‡ïw\bÂ#GSÎQ`!ð€xó—<ËsÎê–·OEËy¹JÇJÈ.Õªu ÞÞÇ"ýQ’dHO f¢T(§Bu ⦗P„’‡‡TÊ%!L2ˆÒI:Ì6³”§˜lFkô!<—o6åõu *Ê]A’§,¬zD@ªT¢¥ÔžùRˆµ•%½ÛÃÆ'‹§wyšr^¢rEIòëUÌÓÃU•s+½$cúßáwüŠ÷7ýÕO”xìbšaÜJ¥U[ëK‹«ÍÙ2Øø“ÌýX^? |ðÃR~ì¤õ°øÖÇþú.B*¡û”Wû¿–ňE>æì–`ˆS“åþÞÎ()„™¸-öÿê¾ß¹ ÏÑA$}íTНý<õ6!ð°¦ÐBA!ε§¯‡³‡â}¥r£ú=oÈû×¹=D5?éñ*ø¾f ›ÿ “À‰šZó¢rjŸCúÑû;GZÂt+=?£KåÀöóùö:ß6ãà{ÊN¾ Y…ì×c@…¹µ·úm7ýlÁ¨/˜t£T—*éÑŸÍoÙQ=ì7JØœžn»ú÷±\]1 paË6:âS¾¿ …'–ì† ˜“-t×+º G²ïêz‹A€8œuþøwC]ÖFÊÿKªù±>þîK¦ÆÓÖñ-˜ÆÃßYó Ž¿†\_ •¢:é“;6ï Õ¢Ï/ïµO£Qövø}{nñæUB.[m<<6~u_qu†= OéX/‚ýØ*H¡<Äj¢•$÷_ËIÜlý¿×fóŸEÏkÁK.`Ÿîå§«m\IÕJˆˆ©W·~Ÿ“è§­;î«4î97¥³õ[õŒ%ŽÁÉ}¥&ZëÛ¼€0¦cŒh®™ ,´cìÒÇy§úÜiÉÏÝFâeäŸ$îçØf­N „AföxqhÛé°,\¶ÃCwSÑà*êç ÞÌô¤`9yX ²óü6K’:»—u'hÕգÞõ`m[D‡_^îóˆV…W«]Yٚˊï`èŽäô¼U¡°Ýs1ÆÒgM¸7êCw½ˆÝÔ1¿ $ÞŽ$$í×G’Ï$þGª$f&0Æc†-ÇåcÓÛªG;ÆKY!X¤ˆ<º÷2ù®Ôbã/m ‡skú­;ûY›/Z"•“Á—uŽùRÂÎØ6d1ܦvÜ=…ëÕûÙïX¾‡moX²ÌÏ€ÀVœtEò$þeùl&&¾Gvƒu­êÞ¹8Ntá-ë¯|eÊÞ½ÚÓ8Å´ÃC|—õ¥W¾"‚ÌHaƒeMIÉ9À2øÉyyó£Fø0—I.œS&ÒO §ƒ—êžRÆ¿P+'«ïeZnÔ[Ë’[¼ÙÏ*q·Ü[Æÿáp¸ ŠääkðëÔ¯G‹jáÀö¦þܨµ˜ð"¨kèÿzš~åBéBÆ/8e 8îö)0Å/i2ˆr¾s'ãUØh~¿¶ë6ù}¨žx²Æn²íc‹QEާKãÑ+ý5üw•±.rÿùÖØñ{í˜ÐÐð±Y*Õ¶t||Nâì™ja©aªèúnQˆŠV¶Å‹,mI¸{n?y™)_EÎ!~ŠîÏznöËM+¶£öîÖh0¾8ÞÔ£Œ*œ˜;Ì­°Tèè“èk©aŸä·¼<3»cÖKÓýÏQôp)'.&êå-m{ªœÍá$ó(ˆŠØ·½ÂŒˆ a¨Ç5p€nŽâý§àYÿÓõYkû€ªê¶«¿; ´ ®ÃvìÏÆ¥üOø—Ô]ÀUþœÜŸûº‹Ê»ÖÍÀJ ";0¸(9`Å·¥àäÜ>¬™Õfg0Ëßhœ9UÐzºCiVoiNQ@¼¡µƒ!‘Øp2—•.`\Æ0iž?ÚƒïOú¹ë?ö`¿"zÝ}§¦½™ëóÙ>õ6c>{'÷œìèüONwØ©£ VÓwJ¶¦Þ\8Ü. ìI²L¢àQ×M /C\|’²,Q‚ˆ=¸bŠÅ;Ù§£%B¯ìAHÀS¦ emýxq&_Û¼?¯Ý=ÔHnÕ÷y£öS©­ßêDEÏŸ.hjÚŽld7˜ /°Û›dª¸ò\ÅQŒÔÔ« w€5ô„n[ª®ï"ðU{>ªÌ[‰‚Uc¡˜b.ÄVd‘RID pªçÕ::ßÕÓçéãîyç#zó êüÔXFKÊ™öϦb舄c:¤¥ùN-9÷‡Û7÷¢kF©ˆì7‚[!ýgî‰Jƒý¯!oÃ<ÅWÌUuÚ)ïÏæ ¨KPAU@8;2’E9ä1Å»«EØ© ¹Y¹YiÀs%¾M7i —¿yº~X(jAÚ%$Š"ª(°YTU@€):0 (£XA¢Š € H3ι8ÌñœA†ºqÇ£üϿ͌®A¢^G]‹›Ga–Ø!LÈàȑދh\„ÔÏ"ý¨ç)O©µ9¢6üÚw”JÇ”@×y/›DÁ†DÒkZb϶j½pS︞·k.j™1’µãVÕé–B÷†BËínpm¢¬¥7VWÔ™éìïâßsYÜóRÆÉæaÑmíìÔ%ÊU=V[EÀ¦Žï¹V—M"™P”TC¬HpE4Aø(Ä‚EP‘À˜CŸ ~½4”ÆÛúAω‰ûîsÁƒ;áUl*°ERX0ëž¼3ƳìÃN¹x¬Òqo_zv>P7ðA;$õææNç`"Ί]AW›ê笈*#+`,€ÁZWªýTœ›¿ýÝ6ø;aQ(¹ÉjwÍðÇøóÿ*$r0?ÂF6LL2ÚëÄð8:Àç~…ñ×ÒŽ›#ÛV;_ýÑà›%…N‹VetÈ.¥„Xé†Q¯EÃb‰wvÖõç>£æ¼é•FbÚÖ*™…™Q «ë!wºH/¿ˆ5I‘>QbŠ¥®cbÕ— #U@!d$IPФ$Y"Å"€(°$’ÅÁ1‚‰§éoq;/þÏ6/§°ÂølåÛÆ—žú¹~ àä 7ãéŠÔEP €œöxÔ{Æ'lÜ„œBM·ù, $€¢Š(¢Š(ÈñËð}²šžþâvvïÕEQE,xÓxê^ §¨ˆUîêÕù!3J`µ§â9™ÙwæÝ  —äs–Šœ9ÃŽ/4 Ë£ôÔ-:AûÃ߸_P¾ÿ¿¹í–I÷í2ÃÙN {B$:êÜŽ;SX®ó¸êTèïî;Y{¾É}æìãuwåÅÌ=,bÈíë!à0 Ë´Í )H†t)ø±Dü©€Á×UUwÍž–¿ò俊y{_ZqÏou|5âX ÃðxcÏç~¾¬´‡œ Ð×⧪6) #GÇËh tîÇœLÿ5v|Õ5ë§ê»S‹ŽZüÕìˆòçâèzqô=O{÷ƒXxÇTî¬É©à2 T˜#?JkÛ謼33™šbÌ®þsú‘8J¾©äN˜}H~¿J>¾h¢‚Ñö-öîÓ h±SŒôÊ,ÞD–ä`g4mˆÛ:ð@»Sp˜8扒6°a°˜Ä3…2CxÉä ‡¤Ó«ª1 Ͷ9ñÖtmuÊùg›¼s´!”C KÊ÷”©yF÷u½òX„ÃR÷ºÒó¥î׬èr:ªV²…kU­sSÎ÷½ïy^÷KaÖµ­kXƵ:Ö”ª%kZÖ•fAàø7?±t`‡Œ{šÔ²²3}‹âØÂš múí›F&_·vÖ§”6câô½Ne®éa¡x¢{GuÕ”ØÉ€´PpMŽÆò¦í2¦L~v9ºÍÃÆ*i3ÍÇ6slw•4”®#+iÆÙôêìÓAU·Éç™y×$ 'Ó ÏÛ•ÎØžø ”Dóküõ Œƒ™ýüu}€Ýœ#ux>†œx©HÃKDšu9î‚]»T?þ:Ûó‡Ö½ã®0E$÷ÍZ…x‡Q-¼÷š#-”A¹(ìÆ(yåÔ¤EÊ(:Ñ& ŠF» †5>yû¦û5µ™!Ö¤¦Y~tÇaŽy¼Få“U?Å&á„Gú;‹¬ÈŽ å0Ca¡€¦°ßV°bBž”RïêÞðt2C{mN޾\>3)–²åðrqïÞïŠ:»š.©»\éɹ:©^ï…E£Â’†DÆr@Œ°!da°étmóÔ?á »Þ2Oå¼Ó3'çFkçKÂEûwœŽHêf[4d45}Ž6‹@MZMN´ÙjÐÁ¨["wúY¯xÄÄß«|«È@PÏ›Tb+#o²šÌhâYg‹­¶˜`h9"31X.7!1t¸û&~=nªw/ÿg…Ç™4µÆó¨¹*`öóÿ,–°=Úy¾ÿrSz{r}´ÆQ€ýLFBWépGÒǦ¯ªhjeÑVT})­nu þc¿Tð~[{?ù‹÷8ÇÃÙ"T¡í®§½ŠŽ;o¢O»Ü´¢T®êv?w¦á:kzЙå6 è“÷{¤¿éÕKŒð¼+6ý"òš>=iª¾M¾r²ú³{ –gSdlöb[œÝ {_fý²t€öÉ_~ÐTÊ–®®æ‰ŸâÒL‚ÎÇR6”yêµC$í Dï1ûÓÜös}XLû±±= #Ʋ—ì® I6Ž•~ ˲3ü&Šôý×Üš, îµéÂ{‘×0t×ÎS*" Vógh›}µËÖÝÇí9Çg'gõ›þ–8aè^lcG9-oÃrǦŢÊÉŒm´:÷#ï™ 9¦n ,½Ö‰jaçOžô9ãçÒAó2O욊¸HOn_½3Á<Ålµ\yOÄš5ëfWzk/<ÑÀ¨}ÛØ?dà+_ìWãùíÊFº¨Ó}Õ®¶w9¿Í­u8ÚéX^}ÃÖo>!ŽÊSAÉÉIÇN;‹h-W•í·á¢Ï^_´Ìu>§;%úüíáÏŒ×ulà0»X¯¿'Ã9]‘¤‡ÿJvð»kæ Oõr‘tuÕ9¿MçzÌR2–1¿“ëÔt$tÐ×l~q[ÃÉ`¤¶ëÿlÏmEw+)ÅìïõLuOŸ·(üMc'i°ëtéߺß‹Ý%Â×yE·Î£ñg0”ílúKí i†ó7êc”Óa“K:ÓçöAŠwAk¡ö£žÃÌHTÊGÔÅ}¢Ú—]“ñ›Ý¡¯¬ôµ}öô²ˆNvpL8¯józëêë_ cþíî xýæ«§þNÉ]7ÚˆÈboÒ+S_6Õl…ÍoõàwŸ g¯ vrº[ø}—_)ÔYä¯j*)õÝÜfª·Òå˜qâ7(ÍUÁæ¹k{ø_žsNć+ÈóòœÔãöyÎ6E ÂÓ š¼’©,cO+U¤Û(ç½ê˜Æüá÷ký›¯&ùeKîÍÁà¢ø[6ì­so­sܹ×i›f'VŸgãDÒÉŽÍ~÷‹½™yºLïFN0Is¶?bøF25}¬W ÐÕ+<È;ͪÜ>êùÿéÿ‚×Z/zĉáCîýw Œ,P«rîâ§v‘SÞß2zÂÛuæv1TÝîƒ#¤6dáy•ÖuÚ âó5Í„hXô]å¶½M'K/–óéÛSìùi7¯ù&.Ëm3k<³cÉÅ~Òçnë)¥¦”SyN¿ºêV÷qWbxH^`/ää# vKïO\lQ3ÑÕ'_IÁ¥ëMñuŠ” ñ˜ ÞØQð8÷Õ‹¿.¾át‘ôk½*¦Ziö\ó¹LÚîyßùȹÒ~í½º*%¶õíŸ=ð,tUª!ÿì·~¾OI½cê®ëŠ˜êã{;6o¤\îQ›YUðJÛ¯+ÝKœ÷‘³‡[‘ÿjÑÞ,}œô7]¨é±ÝÒjòòLAehµ<¥xη“£Åk³Õã5èÿnmðÚ¬»¸J±û¹y·2;©Z¼ǽےíSè!Oˆáà+–f˜A—(pçânº6°D_-õ3öBýá¹í"):~‹[j÷¿ŠþjJÚ? ÷ˆ5d\knäÿÆøÉ|ðva@õ` ØÄA ¸ F Ÿ.ãÝe@æ©?£×úÚúèHv'ú±Hräì+ú¯/‚#‹ü¼óà|Ê÷uÓý|i;Í¿ õPOî90|ydòH½(~é’2‚J¯º·¤·¹Giéqßõj@Cëç¾…Þ×¾žûÕú|ïü¬¿­Å¾à@€‚ˆ ņò@EáDGô,n< мa£€ñ`ô"üyó¡ŸBËô¿:¯_ßN|JuZFª¡ªÖKEY%4L°a1Ãñ oã¤_ÕÑ Dã·ÿwÕ´>­Z¬`7Ü@¿Vó¯]Bºþß÷?Ølw‚«:æ ðIyöÈ>ŠAFMi-¢Y@Ðt›a³©¡‰4K9ëSÉ$Ì3 þÏû“`Æ£“© þë¶à.0ÌP&äF‚º€hôêæO½¹6¢&;Õ”©ŠH¨55éü~îÛû4¤Š‚D©Àþx§î—‘¡>rJÉ»'1ƒK4ø¡g¡¬FÚ%U2$’ ¡Áñ¿ÄÚ`ïÐ.©ˆü¨ h]09"«B=áa×Ð#:HŽè"\ˆÈDÿ*˜€HŽeÎ ¯$Uq?ËÅ£•:JÔ;«’Òkö(;KW0õbÆ 3t[²ÑFýŒ‘nƒP‘]éd—ÃÒ󮲘¡³O1ØaµÖw>þI²,A7ó$êœõEß¼Á7+óøÜaPL»<«›>õw“àj¿ /"'esX$ƒ5Ó.ÏZ/¼•ü~Ÿ «W:z]¯/©ÈÀt#üßtÁõC—–½Æã¨£¼ùúÁGÈWÌ‚«—g«/ç.ž[ïŸuçý>~^}Å÷ÖµJSÅ–@¾É±S-ºTY¢ÈR„â 9„#3Cjd†Fd Fp$ý×´CÞÊ}j7zß|…û7&¨8p†Ì—˜¿ô(é†UÇ\ÊþñòyÛßáK{“ eÌú@÷¹âýWÙ,xƒÙŽ5.¢Ï0eν;¼Zã!UÑmmø’÷óñpáò(hÇѹÛîïÌ’Iý;µÏ†Ì¿väËès)¹—)¶X¨æªÂ¨8 D2’ƒ]/o6õŽB]Õ£sç^ĘFˆE!´D([oŽÒé‰ëªüIÕÏŽm¸1´±³£Ÿ(†- ëÿç- ·šëÓÛÆ¿ ÿ/”{>>žf"ÀßIïU‡]2gý‹HeîJÌí1énìE]È;Îò†¶2{¡ìž:Ÿ/§~Ù;Žó[ªÛ§áªÄ-öÎÏãñοâ¦þšl&qµùú¿?rªáîë°?KAŽD$ƒ”£»ì³ñãvý†Š+ˆ…USB)kD£HT©jVRYD¬j–ªUb+X($ªRR“QLÀÏ æÌ®@¡!З0vCÑ¿›®ø 5’3ÇÏ}[c´A|Áv$’!•¤ŒzåÖ€0ÞÀ4µû{0îÉ?²ÏN‡„I!$Ð c5ééùvmò|{™ÙYýˆª§4.„ÏkçÓ n3~£ì1å§Â´3]ŸCNž÷ù‚nÀüž¡wÀ€ZǤ¼±Ãˆõy€~‹ÔV„TU (‡ùN¯„‚\(Š„z›{À‘Ê“Ó/pÐC<;f[¤Ü~·$ñ o&7æ³¾Iá‰9ówòž.?r€Hü<8qúžr˜,là1^ÿDH“s3íq®“VÜÉ­›ŸÅ‰«®ÌœðSìNÌUqk›Ú4ú<¥ï>ˤåç/M£÷­(¶…ö‚¤ü>§Ðr¦V>ïÚñwhiz÷c¹É,©’~Ìã¶Olôý§ÐëW²Þ¯„ЗÆÉ·›ìààxd@êèÕJ¶7@:¹àŠ«×Üwýzeíûµ·«evÒC¹Ø®d”·Ž›¯&ŸO½NE¶< bPT¯×î­/¯ËìøÃ_$ë¨Öº–ÚÄÇo´ž 7õ;²éÐ]5çrʤ@ˆ‹§__Ãǃ۵?A*û¹ôõ:;;_Fw|ÇÀ1õð«' lFü!!kIj×x¹èŠ®öÎ-ν4½|ºÝVz»ÎVÇ»ÝÍ3:¸ ¯2ݼw×ÚTECèNèC¶jßÍÆÒ]†;V¿@Ó®sø¸¶®6iŸñüP/óØÂ³ñ ÉaÒ[o_Á¾Ÿy÷¡‘Ñ[ ª2Ö+½–Ž¿ 瘋ƒIæŽI˜ñŽvúü?å¸ ›ÿï'%ê,kÃÅã芲jôÁ™®zÄ8€$»l­!iI]“Åh$m˜¨ŽuJ¬{ÜLN Ê#®U ½¨6¬˜\()Üü´5û¸zêr3Ç—ÂòUªäˆ¤y ª°æÝǤPQP08lZÙàjÕ ©¥ ä’M‡7'jùÈ6†‡-L¾™¶L(yJo¬'ôŸô^{wK¿±Ý*føóªêKï¿Û]_íkóÔ«ó4nD"éå’¯¸NÁ´Ó)œ¯Â²>³mèùW`Гšg‹œ éÍ–YÄÄ48™Ñ¦Ñã^i 0'š e‹ÝÕÒ&ˆaä»¶&âT±‰Q•pÈ%Ç`§_¹xº©ûÔé2P/_œ¯@š‰ -wHšƒ3@ç+î¹Ü£¥ ~-r Ï @ ¼ÑÌmZ¬ygòá­‹Á‹y‹«š‘)¡˜ e_ÉeÇ£‹süŽ»ÇbZƒí†FrŸ@õB$LÏÔ†¦:¿!+ö<|Ä1 ìÒ;Æš×>û·¨ þ-Ö„^NƒÖ™ûôɪA'ϡҽv÷1·O~\)uÏ 6»®Ð­I¨†…¢‘Õº¾.å5О;EÐWr¨@ _šrû™% $3m¸`6å©÷|?CG"ÅvàÔæyocÕÃî¯ÕàüDˆhyÕûOû*ÕçÎ%$ËëYNJìÄÌ\ØjýÃE’™æ_éœ7 ̲Fg®ýøQï‘™.zí¦Id¶™ri,G¿çÛ6Ù(TZ*ìªs¯ Bޤ ù¦î4ÄPŸz)XȨEZ’òâ¡‹”\Ú€n4z˜""#EL}ƒžW‰Ù,z6ÿ>'˜ñ¡¢hqðèH@# Ŧ+ ûBsÞÞð>ÒNZõìj^—Ô+a¶¹ „sl0¸1°ÀòÝ÷l„tv9ÎC3 dÌÐúöbqêSHï€Rài]e\ÓÛ†ðùž²îâÃ;Ì'“›|òYûª•vßQξ6¸áo¶…åÍ\f+V>n‘¸¡ŒÏáÎ4ê¢ÑǘLJ”%×åØ-Ú¢tàP21.®øŽiéäÇÜqÙ€ºsà&Æc“ ¤tåÑÅe°kP, y]ŒÙAªÒ½ö~ƒ¦3ð Ï biƒ[í0»»¦:º8¸«”÷ÞêÖ¼]LË' Édžr/”"Àùº<ýn5jCU¥7€æC]jezYMÎÚµ ­±ÅŸQØÕ› Œ[¨mîYÃàÜRCÕ<ݲ»p‘lø•vCfàž ›¡‡0çˆâzïxx767¹\ÀÏ<ºÚûÐ4†m½‰ÌÚgóÙ ƒS$€îe³m¿¯žn{²àüÂú€!Û€DD[¨0con(¸Á†‡8  ˆømd³p.pÊÛ:P M—‰ê1½EáLda´ÒÎç(Ë”ŠÍ¨™ôFr?]@K¢rÚ‡pØA¸(-ФÜnÚ€ríPò0R¢îNåÛÁ%L¬^ö!W×ß)Dd~C6ûy7£EñôœÓBd(]ºHlAÇDò|ë~žSêaºŸakÄ·ç®Ýª. q¶áÛz‰ËÑMÒ ¼ó1sÌ=ûº´L¡ ¶ÏziP Õwjלé½yœb({Š'š€¾]Ј*Ç|$dd `´äaØ Ùœ{Ïy¥©Û(^4ÿÖ*Îù˜¤ûT``Àcà9üÙÔN‡.O´·½Ë-52NdTHäËZ2)ï`ƒÕÖ"{X(ì×AÉê\è“Å]ü8þNÈI°>S÷hÚ =&kE}ù¡½ó3¢³äÀ›&1*5ŽÁUãyŸ̶™Z?n;`›Æw%²šƒH±6—îìì´E10ã5ì{}f› Nz˜3äè…®©¦±c!²ÚüI‰ÔËœ4Ž={/eÓ«kTÕ‰`a‘´ü³ƒûÞ¥ÌÒ2:S¦}Z’T2œ³²w¾š„F¤n ûv¿¹¯L_¿÷æÕìwͲzï D6âà×]‘-ÏÍÝÖVéî 7=Ìð6 8¼`0gªq52±¤øuçO½G»¨¡û±ùâtƒôõzg³«ŒÐ±Äò¤ôÀzAÄØͤ;½œ9Xõåj¨•™Fªƒ£éA&4ç6®;ô£(vG¼ô Ï‡³Õ‹¾Žg¤5Œ†þ¤ ;íCóéàícñ¹þŽÔü¿~ÐaÝêh¿Ò¼oà;Á~_lœÏy¡qôoð½Ê|÷é”Á†Fç² Ð –½—ÑÐ_Ê*³C.ódfλyCy­Qäó蟰9WJõÏÇúEÎL;ƒŸœÝ³p/†ìSsèçãG7N~bî7—üKqÊüh1²¾³€{öN­Ã…I©ŽÒ3¥ª¬6˜@Ò]¸Cg* ¨A L¢ÝD…… ×”² [¹Ylþ¡81€'ÔbíÖ[xŽ135ÌÑ5F@* `L¨:¤Ó&Ÿ=ÓŽ^<_xá–{–KO0>cA·œ)ÍyÆ‚Ê!ë}[þVQtÐpâµ°?–Jbl´Ò¨€Cñ!{y:óùUs .TÛáØåË}"“.oY^üΆ2ªVÊJ\P‹{‡ÓÍW¹ŸÞÈ6ó!Iiõu£ÇÇÅfoœŒ0Çï<¥±Ä &ªa:LeC™I‹îpêdŸpüÎX÷n¥ùSšˆÁ˜âŽ)°Söa˜oXïí]ûë1c„éSp¾5È*ùûÁ·¼Ì(~bKŸ‹ë^ùN)æâ¤VB€ò›'¥Á€z͉G½ÕØ™yýWÛ‚Ðd~tð°©e*“µp*’#22i5~ž3ƒ½Áº"]áwqÀy%<Àw8Ý9º‰ÀöˆÇ]»½r' ÐP `1®†[DZéç áê¼ÏÐb^ Rœú_Ù¯|­õäô­ÞG@Ùö§ù~xþ­ØêÝïÜ{’IWÛáæ¯Kkpûë³Ì›ë£òéÔ»{‰Dƒiè8¶Æ1^¡ÜÜxÆrš¨!H¬äšeÐiJÉ 1ß»È3ðˆLGYùõuãøÏvTAƒKo”`ÚÕ5”£qX_¿E“ce©,¶{õ 27Q–sü0ë{LñÈ«øåt[‰î‡nvoN´ZŽóô‚÷=ô!¡‘}Ÿq Þ2¥6tÝÑÒŸ …£Õ»J_v¯ð6ßâ͈ž”^êããxòÀÝ Ô]TÆÁ­…N«†´$ª®¡>™”kÏía¾¿ÅŽ3Ë›ŒV1ªhÍ’ÇÓMµ…Oo¾Þƒ9Ïì0Î HÿʲOÌIdC–îÌÃ0«OlQUn8Î@óà€¶™@S–w·ÏNi§J ücÅóû»†¢Z x)R×Áž^D-kyùÅ ´«t}•†f'>úkŸçæ~EßÚÎ3†wæy„p5(eV Œ]*³VÀsça®g}W»…)ŽŒÈc¬P+—y·Èx?޼V3ðPš§Áp2c0c¼Án¢{ï­7N›eΡ±°ç©_$9&3í½ó¿é{sÖ·`¶Ä·_uE%’@aÍÉ‚^Ò«CASÛÙQ ÖÆÊû6C>àP0{!îÚn£üà—?›ÓÏZ<ˆy¿üýõíïëéÛ¿ÃM´V¥aR²TªŸ6\Íž yÜU|Ÿo.á¹9÷ôòªòßc[f>›=ÐjÃ-ƒž·‡]¥Œ¶åG»ñç×´©·|n-· Òvè…TG]KqQYAÓœ²o™º\<³ùP ¨ù3 ¾àÁ³ÜA÷Œê6 ¨5*óîÞªLXU¹< ¼vyw•! PÐøN®IÂí¯>ªøÖ7¤dõãÑZ÷m/pÇ› ï꯷8Ùìç.ã½7ß‘ø½~¿„G¤=åËx=-âŠlÍôÙ!?4…‡J(ðƤE§­¯Xó\h+2ùtÜ'h´{T Êó³øá/2:¡õ@gÁW«‚¨(gëör•-ÆF ¼È˜ý¸ò_ÍÃFøt˶÷éNv+…-éÞ{¼§$¨t$s'«Š‰ãqìÀ&-†^Ò7Iï°+²t!Iáâx;­/ ¦IÃåB…H¦ŠLÏÔ³žPˆÙ¬L#Á–ÝÕÅ&Û$Óõ?u y»‘,Ã·2Ûi¶R˜Á‚=ÈV06¥CÇ‚B߯­A5ÉÜ=&s׌¯¦4gâ-Ûò¶âÔQÛRÚ â2.Õ_FgU2€¯î1DÜøªÎD]t0z§9´7x¡ÍŸ2H'VM¤}ž¦bN:IRÖí«ejË*J=˜1k– 2ìû®~;«9UÑoâòSK;ìËËÈìŽáÝíº“ÂûŽâ“0uîßkpÞ¹úYZÓ™÷Rªì‰ªGOÑ‹óqíx»wO÷Q]Áàü9ç 4ã²P\}õz{<';EôT?"çA+)3HÆJ°Nµ™Ê L,÷ºÎ+e$(w‰@¾çðl9y’¾ëü¤šsò7´O‡%òÆCè$„SYe4š$<¶y HÈ‘C_º¯tqÊý/•îJeHä“›Ê}vÏß)¿öûè©·nš:ž­RО( üºüïøNfîÁ²û"„Fä͇B+ï‚3r1*f -5Ð`Z!+!Ϋ{ÅÓ¹£‰½TS~Šºþ圇U„ ·ð“ÎÎ2Ph©2˦0àh6÷*ƒãLÙH‰¨¦`Jz0¤œÜÁz9Úaî¾vY"6^›îÊÚB¸YèéXÙxE…gæŠÞå4Y2fÈu§˜yçCa=;óŘíÈNƒä›pK;0‹ÔúDúL2ãh˜‚ÝH1ƒ=3PŽÀÛÏÇãø¼p!¯ùþI£¾ÓaŽ.@:–ÃÈq)sí.ÿFß=¢£ßæ"ãz9—j¯‰ñ^ %uåšuS†ž)^ËÉÈòqÈàª÷aïÏ|ËÛʽñ_Vêãf…g;­o'¶ù~ ;³÷Ö›;QÝ(b)ÐûsîáXÍ™4ªB[x¥i“INAùÀöÙrò*“²aº°ìžpŒZ"×-¶Q–äC9ÂÇ¶á–Øn„ q2ˆø…ò¿f8 lé#{± ¦L  R²é ŠäqU˜ñ˜Åõràw󞮸L¨=šÛÝ•Ã`A â@ÓŸ>¢Ú3d /OU¼fgªT` [{Ä`š‰‡@sBÆ|¡жHc-h% Ï*°0yè®Ê0{6n DsÂËAœ&€È6ÚX>°ÚjgÆ$Dð „ÌnëØCåb} ¯]Š–8'f—ÏÛ¸å„îáC‘é¼:IjN1«SÝ%Òj35)‘¿,u:ºÊ6*X@þàN-#ì2‚«°SžqtwLÑFÚB"^úäìFÛñé· â¥Ô’ï4ÎåÃy×*biEŒ÷/Zh·†”!¡“‘Q)”Œ_ªÙ±0‚¶çmèæi¯zh‰ŸŸ–@oâ‚Ñ#0ܶ(æ77€qrßoLKÍIB<ã‚ Á¶Fͯ•7!)»&ï¯ ¯§uAPçk³w…»eûûÞæ;žÎ®­‡å'Lnï‚«_>8c×ÝÖ09œZì<ÄTr?[ä„›®ÂÓ–èbÂb¦7h€Ï¤Áš{$(V2Ï€"ó¨í„h›FIaÉyúK`­÷ϼ7/P0~dòœJ$^*f}:¡;u#æ=²IíDÿ ÝK˜ò¡LÄs £JùB^ÐùR•°Èc‚²:‚""ëÒ`ôc™1Œ¡ÐT#Û%3ŒN‹9m”‘UÝ[™¥6ZT?%ëULé"Ü´˜ß;Ê56€Ìéf/%!ˆ ¨3œäjîÅ;Su…„Ëɪ N{Ç…âÙCץ畈I±P U8éé§íÄÞÑ(2Ó7x“£ÂU;d†f /y£¬/B(Z5£ õ¦“˜2ê1A+0ÈXÑ0 4’3É.Ç•¶¾‘ÐRX ´E¬¾§§9dÒÙ c "$ÑIhJ*õŠ­T<{ÇR?‘/Úƒ#J•™íùŸ?YÅHáÙ.ðža'_Àîñê°òå(ã÷ósUÉi=zë••®úÆ"R:œ4gmYªR)Ô]LÔ?=ÅÝÙ™!/Ú=xwô‡Hµ"q|‹öæ*'êLy™µà‹Sä,ãaŒêʇs°WJDÜà¥$±VR“D ÈôpeGÆpͯ<œ-Ñ[âð+ µå~œ×ãx»¯Xq©9±/.Z&¦Ö|^uNžËÊFÎ L»'ëâߘrÊšÂe#•?,ó p:¥é¨2Z˜SMJ{Ÿfq­g/yõSM""É¡xñj‘‘Î +eìÄÝ6 GO”©¾µÔÙ°X¾¬¼Ž*C‚,ö{HƒåeÓk@¹Ï8 Ël šjyUé¾7Zz#X£r:Ì_Ä*áÄ0r Ѐú4o_VÍß>C¨Á{†:5ÞgŸRlØN3à& óÛÅÚ¡¦ä•ÜP-ÓÛˆÒUOHª@Ë$ÉAà vLˆ„=#ó¨[rÀåàþÑ- Xá„Þ¡EYõ:REzóÒd¬V´ößmú^î.xR{Éð³ÉN¶‰' n°™­qÞ±‡µ¾7ñÊ‹-SÙ+tØ$ ôìùÃx5É‚z‘¼¹‰´ ÷—ýЈ?9·/9ÇÂÖKÂZõi÷ò~׳ÆÒ¦Ûf^©£B'Þ¶™»›" ‡v2{@@3ìeêèí8¢½Úe·ÜwyÏyÒÞ}fïÊfhvü+TÌæØ^µ=Ȇì~nEŠõ*‹EjwŽîgúoò¶»&-f@21´E²¶žôøVK×/ë>ˆspôŸ<0z VÊEt>¹¾H'®ô×Ã7!®pXŸðmʬ۾Tª`ÖIá9j2ð¯±Ï߈ˆ«‘ư;¨ÌáÔËËê÷GxrsN‰p\‡q>³h<Å- ÍŒ¿ào^P‰\ÓãGO<" 6šs­GUu?‹Ÿ ¡’¼†f¿ã.½s19PzR:¾É/ƒ<y˜ÔIQ x*K<€ze~ñ Äx:Ösâ=#¸/h£éÑÈÀNtÄÀótÀšEÕŒ·º!ë zû1s7ëÒá¾¢uÖp!#"Mš#o]§†#Ïå/|ÔÇ4ë´¿~ƒP¸!Œ Ãï2ºì4êªçjà$] ”œ•]20e¥äàÍfUýW^ÞÈ_ƒÄêð9O¿Î¢?°¿°ž¯Ñ³`‹¾jlµœX«,¦ËA¦¡ÕÑñOrux8çyxïÚаÁHǨ%Ñ‚&W &è‘ìÒ€‘#E \Lâ°""-îBj³IÓÛĶIIýÿ‹ùØGèv8 âõuÔÖÍ^B¿!~‘põ*¦\k¾7¯gÊkOD ¨ŒÓTÑñ¶¾0ªûŸÙ÷Ÿ »¾ECÁ>õp€@ñÅWÁö§¢O…Öãý¿ ïy€¼Ñ£Ûè–6EüPd@?m2ªÆ«×ü8d¶|tÖ›ÿ_©±ç§ëþ ’ñiËÝüeÂÿz±lm®!ËàM*'4"¶0üµÔN„‚óìË;½NŠIÃÕmÅW‚øU€iZ^+T“‘åêOH )¼ýòaÆd~½÷?ŬûÎJ$Þ~ëĤÜôñ½%‰`ØÔÐÆ¤yõ6ÇqVáЈ‰A|ßŸÓÆ°µŽ©Kí‰ä"ÛŽWoÙw{ëG§±i7Wú‹e³e¥Ø™í•yÑãk¦wñ~Ʊ­M!DE“S_†Òz»3á×s}˜GR×áÚ—(iµÄ–~ %›·xNî͈bo)Šå@J;óò¦¨—˲?+à×L©·Ë$¾\ÞzuñÙ>­"£Ë»Ê¸^•‹cmqÏ*iP9¡±„‡J¿Zt¤ŸfYÝêtPNί'Ó×KžmÃöÐìÀ'£ãÏrXÖœ/’z@80ÆWê ¨Œu¤'˜òœz1‰—ÇäRnzy^‘‰Eá/-*ËÕ~¬`Û~ï1U²*ùvã]˜ù~{nÏm’—Ú'Xé^^è;å­rœjŤlÝ^[k·KHû3Û*óÖñèšÜÌüýŒY3ZÒ×âÙìEA:ñDT9'F;ðc Q(Ä$$A$“ÓªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªöI)$^"«þc·êêø¨ÝXµ¿©¾/lK̺ˆ1ìÎê„àŠ"dn…è; aœQua—q<&„€×ˆ1q£68ÃA/#F C°‹!üghÏq§B¤eH¦C55#F(Æœ|D[íÐ""÷ÀºE¨t Vœ&ÓCKDÉÝפè„ ×ëyÏé×î|wûo£ÒzÈ›û6,*¹…Vþ'Ȳ(=î{ï1ÅÛ™íBôxTzˆªóNøOó>çÌócÖ䊭…W”*½Ðªõ^‹ÛùøŠ¼Uß"ù¹ùxOƃèçy;¬»ë0œcÅôÊ21Ù¹==* ¿5<ª´‹þa¹/ÏÞ»³üåŸûIYcõaMÓí$Ü’ŽN!%½[ï8¼%ɪS]]Õã ×S’Ÿz³“U;xøŸ:Å|¼‡x»¾˜´×¼¼¸uÈæG?:ÙÖThk¶q¤Q¶¢ Ig9¼öò×iï^~]‡ßÌq”™cÛáyÞVïÅd9N2aý ]ûOÓxõONËÓ¡4ÛK‡4„²¦y6˜íý B¸©ª“-±´‰Ï¼Ê•nŽþøŽs'·g_g)O·¹ûÙ–QçÎ-ŽfeÚÍÇÌ—•Of\`õÈï¥Ë¸îñsI•ÍRóTmÓÜM(ä<'ŒÈ&.kmùй<±Ëá·1~eÕÓîcí¸òMÌmÖ•”ªåd•‹«i©ÒGA&¤g‚E‘á37üãñþ?Çøôü/ãü¾ñ;dPõ^c­ê½/¥ÀT°W¤ ¯M„‚ADHƒ@"„ I"PQ€(A$AIDA "DI"‘PQ"()‘E"‚"‚ B„„€‹"(œUzàUx ªð£ð~Yøƒñ–Aø‰ ƒÀሠüg :4Ä$áÃ…–p£ŽaB8I¢4g 0Â0±Ä`æ”Ad4¢È4³ ‘É4à 8IYÃAÈ0ÓC…H9Y¦ŽI%¢ÄHàÐ4 ’ˆѦQ$¥#¢Ê °³‡‘˜ÂJ(Fa„~BÌ ìèðQ……tQ#Ž,EIAá‚K(q"Š4€ÑÄa‡YŽA9ad”iÃ…œ84!eA£’IFf’" $Ó4D’A Îi†’X" 4Achaƒ˜YƒRá‘b‹†Ð>Ew¨«¨jhAfì“°p°a($Рð@p ;oÒA#œ$±(j ² 8pG ,±°dYŠ ÂAÁË2.CC"ˆ\ØBÁrÈ <UŰuðÍð™¢Nv—Žü]ùêîîîûæ­Ýw}ÝÝxQ»33;º–îÎò¥íð}Âr/rò%*OU\Ýœg4œç9Îpœå)JRDGwwxÆlæáÝç9Í”ëRöyÂÄÀÒ)ABUTŒ€¡Íê£ ¢žã#È92dÓˆÆa¥6C?^N£‹¼qÙr¶d \Ù´oèöÈ€Å&*Ê‚¥GQO>¼žíî Óg°™_DÕG¬ôÜz(@ÒPzé»d¥ @¢r "1A *T?ü3œ[´aÔqÓŽå¾ÕNrÖëÊED!Å>…3};˜â:à³s¼0Lk¶Ù³}™™_3@®èH*½yjT DPð÷¡D±oU’ïúÿ5ž& ¢QAHÄ"$"*°Š«ûP¦|eáf)$€B ¬|º)Œ|r„P¢( -Å1!$ h¢"¨(  ›%bE˜•’H‘ @XŠ#ˆŒ "1Œ A ¯ƒþ™½(éi¿Ú=Ó¶*7¼¸?^΋&_UÏÌvxÊÚŽ£%ƒ:jú DG3öm àYÕC *¤â@ˆ©V?hD ©wU£_ ~´šZöQ}pœž¿hÃÎí][öv9ž>yøãîÈe–ºV7ZG0ŸC/&ð¨å(‚"ÿŒz Â’¢=²D½Òƒ‡–˜­eý]ßÌú<Ù¯_øÿ¿€l¨þŸô²]ª«mýò»í@8ÿ]&‚!c/©‰Qp6ã°h J|ÁÑ[;ße5¹¯ÅnµÌXgb\Âéð¼nf­Ð€Õ8m×5ð¶º9œÎãŠäh•uzJnËs×-Vš‡ÌÂÂ6r‡%•Ãï#¡|kdÓfÑ˶¹ªH|¢tâž›ï>?ÞýÕ°ûߟÆ,Ÿ-õZ„<Üò$KñÂ뼤Ï?ÓØeÖ×Hã>L%μW©ïkÓߊ$ꧬO×OÖJJKÁ'?ÏáhbõaÌÙpË^¯÷9gýGì~öÃhª;‡ÅZT((Ì(… !Dþ5ñ‰Â+µ ìÈ1`°½6”)ÞºÓß•’õ,Ûh—ùx>Tck;ÞE™D«à}•~F܃ú3;%PÝBt0Kƒ R, bÃßÀTædfǬî'éb0éõ8žr¿ñÿmö j_¥þ¼úámoëlK7˜gܣğáã#6ÞMÃWùÿÈšßu–³Y«~ª‰¾oI~`22œp<`Iýüͦ1ˆiæI-ppkÌ:©9>Tà²yÓ;´¨Œo„þ$OÿìwôT«Ã_£yF¸v»¦¦ïðŸaósÌ…X†G 6 5cï1ÕÞª-¾ÿìôìá‹‘ˆÚÕ(¿tÖ'…‘V‚×hLc3 án{OµrX(€]n¤v~8„Ž,~/™•|#³Æýÿï=À¿á§Hú;ÚŒrÇ6*ÝwV6Ó-PÕµµBY}wÝdã^bí¾`Ö»-ÈÓ» îì3»ƒjˆq‹ü×y—‰qþ z§ù&€ù#º Èf4Ù~c>!„÷VœÖÖ<(… wŒ3³c…óŒÄ&ë!}Ÿ?^wœçÆ•ð6 ¸L†ýi©½ˆ€{H6kŸpÓ<ç\óÏâ) ¸ R FBëËÈÒ5‰öôIÏ<ïßßßt,o Âág#¹0‹jý_ý¿R™Í2ËpÈDà‚÷UO4àóžgDŒ/¶†¾¿'v`?Úîë­pûùó™:üýØÓ»$^d1Üý:óP>×sÚm:Ð!c¯årî´Øü\½¾¿½u­ŠóÄ„ aƒ†3ªûBcþ£ÿ/Ätaî…uüË}¥¾ÛÕv¬Ÿ²V8M‚û¸×[½¸ é£âÚ³0£?‰é.»ü…g%Ò=ø³yÎ=søŸÐµà{ˆl( …·LGõ¼ÏÔýý2 ïì¡[î„eøêÙóÖ`nofá¯܇ˆôFÄa<µÄ`?ÎÏäÙÕABHˆhË÷ÿ ]ˆMîôçb­àqé·‚.a$‚=JÿNý}P.ã›õ(šÚ‡ ÁÈX%ñ¨æ†Eeþ9kϺêfÁ2:9€HáPC±Ùƒ¤Œü‚>Õm,zž—b‹Õ!Ø<~ ·ú©¡³ÇÏEL‚Ù4^ãœ${`€¥ô||Ír8Ç=(7( LÑ:Â\†Âý˜ßÕÓ'G»·ü<óðt_Aóc09ßw\E}ÝVÖ¹á3™ÄØw|ÿÌ ±·È•>ˆK|;˜É}ÉÜgŠ ­3”ê†oLºÈîo&hf6¢˜ðD”"*B ’l‡Ä:ˆy–GÎmÑ*i*²߯ÝmŽf—Îö3ŠIL •yH=8@œ#úØ”ÞVwp÷?‰ïNfÙ׋©Éó²f–¦o£Ê½55K©Ñ]/|EÌÚV¾ ^üÀˆˆ Ñ:;È™§°sÎU@d—IÖ·ØŒ œX$1 c)c`1ðç!©ZIY# ƒBô²‘[Ÿòÿ÷;º|Ý›mý³Ý}ÊÚû•¸Úåmas—æck•oƒ0Љ Â™†=»‡½ï}¿6Ý:xèÃcánBvBæšÁ>·¦õÕÝæ{wG³¹/ë«ÌˆÔ™PEvG^+˜£‚ÎY´ÊCšÎùeÝSD¸Ah‚±ÁÀÆlÕæü:ìúÔ¯NÎ.nì­ÙàçÖsšNR”¤ò„!FINs”¥)JR”ã9ï¥)JRœè²”Ñ'9¤å)JP”§)¢N“œç8NsZLÎsœ×§Òtÿ/»íïÌÛãð{¡é¾ŸG ûü¯ê²úx\§Ë“f¶ÞçŠ I»y—w‡Üìåº<ÞŽþÞ@Ç0ÁÞ¼©cä<×óÓšûk pŸK±Ÿƒ¿wåý§_íùöl>îevlå}OÓwfgVŸPm0è„¶þªãgñ>uYÞC<`ÂñgéÊ{lBèæ¯È\£—ˆÅ&+œ=5‡žB=y+ó[÷ ÊÏiIŒ=N*¾æ²ºÇ±“×DÄjk§µ‚’sþ÷‡;ÀèaP B@€ÂÃ6f´»ùý±‰ÄÐâ‹ï2«E™šQffƒ33<¢_×2‘Ñöi£ši¦ši¥›eQ¥Ó 8i¦ša¦Ži¦ši¦Ù°Af–LÔša†a†a§ 4ÓM4ÓM4ÓLù¢r;s·Ëi‘5J±Q^cÒÖ ¢£ fœ¹Ñf'C©±ˆƒ¶Õk*—àCˆ qÉà ðIp‚ sÈã”8æŽ8ú@@!8ä9£Žhãš8æŽ9£ŽhãðqÍá 9„–9aÂI8asÉκú̺ž¹÷™u}Ýrîù¹ww{s3˪ªÉˆ¯OuQ÷:/¾à~Ó®àíÙÅ?ÒåˆqÁÏ ·›ý‚›óÑrÀšp%L¸LhM ¡!¤w$qÉžBDuâ%DÄ)¨ú?ÕíG¡-îÉ/ë:´;¶qòü—OAŽíA—WO$‹ÙGËÚŸ&Óñþòc²x0`Áƒ½Óø¯X<Þ¢: Ýǯ“;õÙñwù?w_œŽþNž_%þøîxOðöŒWM"ïÊÞ'`ÅL 543–ÁqÎ/™7óV3n¹srÏ·–ì¬@àp|_µ5†ºÃC*¹ã$„™fJˆA…X uŸ¦¾I)‰P#wôtùS»½Ñ=õ?›ÓÛIÁLEÐòWÈùmŒ3@!NϧåçÛöû¯æÞ̶âˆÇö‡×Ø:º†Õ`'ä^¾‡N?¯×”ptÂeÕù?Ó÷³ì!¿×—HýîßçêÝÅêô/F}ÆQ¾;!‰'@T×ÞCׯú|POCºŠëo·p~<ÛýôÙò óÎbO¨­4«Ûûzx© {ÇÁ‹ ¾ Ôúº¡îõ}PIî›s&F=-{áDvû‘/Ÿç3ħÛÃã_¸?Ò?wøOÚÌÜÆâ›€‡’üz·ùÍ_| §[§\ôV =Ñäó_ÑO…¾y¦}çÆÌ¼O´ûy†³½;ñ¡Á§Æ~Mrôú£MñòûÃn™W¨pølɦçړݾŒ5ø&ž–—O›Üåm“áöé^½ÿ>~É´DBŽaN²¼â{M»O•Õ{oË+}õoN(€Á§O‡Ï¿1YÆ=‡¡ÇÏì‹n>ÿ——Õë®>ƒ›»¶û»r  ú=œX1¯¿…q¿ÎÌÚzÇ–™g_ü&¹uüž»³nÂ0DW2<ÍÆÓ. Ojür„#Ñ?ÜjÇéQÍ~nã-€T•Ð\\š‚ÛsdâOó“ïÒ6¤3’¥c¢Õ3Ìæ@r% j__ÔöÆÄ#„z(ûÕ>$I$—:Ú"‚Ñhæši§ 4‚>ä´Ji\:DÃúÅÑDG„\8p•“6ôíÜ?¥ðýkZ¶d%FdFF‰DŒ-žxT‡ÉiÅXà¹\Úì²å'ò寧ä;aÑjà¢Y+W¦'¯—°½ï5½Y/Ç|¨z{ÊóšO¢¼ø¾ækÃ'$І‡Pþ›ý¥Æ¼HAö¾_€wºõ¼á×Bú®ï¹«·ë纱Uãïþ;ŽGnaÞ÷‚¿¦èôY‹“¼³Ønœ¼Â²&’"Æ&"…¦«v{jk[V×+Ø©CÔcà1?t{yÿróÓ§,@Öiòûf§ì8)¢ª·­ñ{Á#EÎò†Mîþ8ƒœN›+iHEÎç"7 ’„Z›Ø «ï•Žù9|tÊr[AÕFXY§aÁ´rT,$ã$„³²—ÅQöÅ6ˆï1öÄ‹ŒJçumª×pæKµ¸ý'q¦Š""ÿ½àûÎDß%SÁ˜\7«‰œ_ž#õT1´cMYA³õàam)‡$•ŽñǸš*˜÷îâþ\"\s·Ë›÷ÎFÀ$ÂSM­ùîOsC˜pjâûV­ì ±Î0kÊ/#|%ÈàÀ"Ã9#±Ã80 p˜´¿á|§ãÀ“ùz_‘ó0âyëÃìÕ¹^×ëIŠ”c‹JacF-% #+I¯s‹@[ÍB´µX‹×*1OnUM^I†œCO4\ÒÀâÑdb•TŒugsqkì$@ÿ¡Üýãö|3.!‰"!„ˆDB# Œ‰a„„]Zm›6ÞC­þÛì.ì4¿µô~圞â¥rïîök`ÒÈï·pä]y­ë¼íýweë­ýõõðlA„Jª‡×ó(=_ŸÄì‘Øì†Œ¼péœÄi0Ha¿šÀà#cÁËõžû×;²sª©Ñ±+D&– “_òÝÎ oÐ}ûgyÚfßÜìw¶B Nº²¸9/ëéåW7¢ðf³Ý:;ö—öìW?~*µëmÁÉÉŠmdÍ´M:Û¸®Ñ×V;žGµòû½µ.“Ĥx½ì3zá£è–в8áÓh$¸° À‘χƒÁ/ƒŒ7î¦%aDQD÷ûŒÅ`õ±-7ÏOÉ‚Ùõq\wàÒkZ[³eëèÇ=8 ®Tv¨yòí³3JîÁmŽÕÿäÍ»IÚçÓ>ªe³ò³òtÎ8èñ÷…iqN¼º÷ÈëÉ¢¾wié‡ û¿TºSšq·‡(¿_\r–b{ÿ_\êúæ1Cœ$–$Qð~¯ƒÁÂ÷xÞçÛiœóøw,½oYÖ Ía”%+V‡^þ|g< eÞ¸„Þ»$<$ _M7ŠÒ¯«EMŒ'|…d zå5Ï-%sþ’èAb#3y±•]Vz[gu¾.O¿À2*ËDûžÎŽ'•eÑ ¼Y8|RMÒÈrŒº´’³=ÒkÊ‚ê/mø×£Â±¯`ÅëŒ~ºçÚƘ<{’1¼DŽÅì3–³ÖIœ±1àH¼æãŽ«¦è‰\ùëq©ˆJ _É»ûºZ¡4>úcÒh'²ÒOà]O=µ¨é‡?ƒs´ ˆˆ, ¡V$ÊPD!ÜÑÔD§m¹Ý…ÅzæúÔ , À°, B™^ê© mø†/ø7cË#FÆotmãËuîôf–qèkè fyY¶ŒLUv¹éß1?Ŧ$$’ð¢îE¿4¼ìr–v/Ë‹úÞò‡Òde×hÒXŸDÑäó¹vCg§„rŠéú GeÒß;Ly¬IЂrcc^h s °Plš£˜0ò˜ì|`~Á¯‡ëô.á!‘G¬æ÷i§¢~°n»Ïä%ç;[Ä"­Ø|üþö¸€íbá¤ð=O,¿¢W˜äù²QÅÀ8—öŸkj¼Ü2k@+„Ì"ÄCÈ# ‹¤ÈòØrD¨ ¶ú;RWòÄÓ+}DùüZöí!¼ ×,ü2×”G¸^!´ñóÚ¨-±¾#xõûŠÃýŸÈ<‡ÙÀhk9§Q_ U€‡.£Á;àœî~ßœi¶^÷_žjÍVÕkîÅ \Œnä[D„¡ÇˆÎÞeItûf¾~O¯[ƒ%’€Ê"„ªqž° Œåý›Dç´ƒ8à˜Ô©4Ù¬«_»·ÊŽrF@‰!‚CiHyæ Œûèºn6Èuè; ù ù!£ªéãà77™èNvg¨áÏnpmu`âDDÉ:á ¹¿#"01_ˆ@ bvŸµ„”¿wÖ¼ÚÝ£Õ85¤ÆŠ~ä‹åvòd.‡wC—º:Ѽ1üÿáùb«©iÆXUmãF–Mã¬&n¼ïšfuwÊi2@r‡hªÒŠ3D\¨Á7JéÉIÇ̹ŠkQïßótËtwå‹Ú!ÐÚâåüG,ßÑ™¹çg,@xÝÛå‰ü!ÒpPŽŸI¤]1÷–3‰ª3)™¨H_'ˆys©uü§]sºçÇ3ÓÚष‰¼¹oP:O^£øÐÎÝùþFɪö‹k{¨^êsÞ臜Ø$B˜C^¨ •ÕetfNÏÚÛ~Ð"éÙøö‹§Ò ;8 3 ¶ž›VarÔ"/`ñu, QÏMæW6{ÖbÂܳGŠEè¬Ða;B 771{ ã%1SÈõ浓ž.‚""þ|Wp¥†{¡liƒØÄd¢ áß m’ÄSt&´†Ô”©4¼·B|xÚfŸÂ|ÄЦº•37¼3¤]á ™ÍfsY&g( ‹e“†$IœAÆ ó 0[†ö[ÌUdk5tÝVÄr}u ×L;\Sf¬îén £N0455«ÈØÊdðqHîQ<àâ¦d”X0–Yÿ."0Hª %݆BÞ‰€zŠj;Ç<U¼_]uÑgÏj\æl¼3èqÊ ø¸W–¬ï*ÊôÎÖ°žÂï¼RÐYõùÿG½Þáð@œhÕ,Û³ÕÑOv-1•ûóÿ3ÍàìkxWó¸8öyeúZÇûšxªúßp/ò¨D;¥ÑÄ€!À´øRY³cÉqÀ 7†éß¹êr4¶a¨ ’ 9¡FlØ{xêö=Ž[¦sî°Ÿ„{CÅãõf»b«©Î·_0fþŸà_÷Z`ïë7Ÿ±÷S³«yîýŒ¶±eYŽ©tËa.\ÛEuSýù|Ö 9 ֧׿Ì~Î>€ÝZn^Âѯn=ý~¨ü¿{÷Vz½­n·™æq°*¸æ­PU~˵8XÌ“/}†ý`ÝX^tf]ÃÍðŽ|;û³‘ìÇüû-ЇNBðƒô|Ìüߨ(wF|;1"„ŠàÅV`ؾªßûÃ&¿ÓñÁÔZôÊ|Ä$_kñmlù=ÌLÆY^!+±\`TœÃˆ ¸æ§Ðèú‰K©ââƒÃ0¸""ú¾âŽÏIü£êH…ÖëíV@hìí «9ýth%œÈ¶»ØèÞ¸·í\%> ÙÒuÜÚÌ0=$‡ÌóÉ~®q ¢ò=—(¨HL—­¾P«ºŒ¯²p“ìõeJ”¬¡÷L1ãû¤ŸÈnÈ€¾ÅØÖ”mOÌùóÊɤ‘¿.Ù.péá,œ÷çGÓµè|7Ïzô_2¶SH}¤íú²Œ±ß¶è°Ãm•DPgÛ ¬\*äê}<Ë ñ£Ð‘ 8jaÆßb±ƒóOë˜ÌÆ)ö.çÏ_% §\¡÷WNPû?Ä*—.ÏãIŸé&”û ÛøQ!²¾-:]ÿh’~õ¹Ìú#y ˆ¡á_sÀ’¡î>^}{ÚµA! '…vÄXû¾w#G~noFÚ¡—ÂÉTW5-з+CËo= ÷\¾aér‹›óHQž>ŸÕ?_òv5ñ:ÿ¯›œØÙ¢BB®×ÕQÃßÙ·ž%ý¯=¹Eñc’ò‘{)wÝ›GŠÜÇ4ˆà9€ì¾~Íj>üLŒÏƒ#9è=Rf)Ûííôjì<³Vǜϵ¯ù‡Øíx\b¸ÂëZâŸ4ÞÔº’&>éó¶†\yºÁ8XC™˜d¨ÑV’ª,!Ï$G2aÞ©ˆt¡ÝŽIP@ .Rô¸¸Uôg8ìÌcrßïk›UÓo5aœu™/4ÂX™€áUçŠ-æ]ÎKÄÅ0’fS3Q¾.PÀ’LÍ4¯¿*íS¹½È°¶Ù"ËQǶ‡CDî/%B#r(V÷”…@†&bàÜÈPç$‹\ó„…Yuu˜#·~lB>n<<¢Û®†—Pã±°ûÛ¯Qy­žµÅÅÉ{‡zv"‡[·5ÈMp¬žQÏÓ~†íÔëÓ&éOª=zñÏ2œÌÃ5Ù˜*¢£'‹` ’Y‡aöÔ0ðÀ”»»¿ƒ•5½yz¯/Ô»ˆ}qh!#€ÌÌߺ§'wÛ‹IÓ´ÇS.=¾"ZŸŽø ¸TõNΘÁ dè…I¿¾Ç+”Ó*ÜxοcöžsFðÀâv>ZÂì1ðwWvýÅýÖÉpªäý¬^³½»µÒ{žEÏây­c¹Û:~)à€Î0Øq÷t¨#‚O°ïy„r‘USÓ ;qš §ëgÂW»Wzж‰D€‰`UxÀªÞ¨«@ªòEW#Ðìz[=§¯ìnìloÏè%q¹%q=>=k•;ÎLEG8;äfF8ž‰Tqëssy Þv9¸åqÙÚKºÉ'™ÊŠ•|j^ÐË:8«€ sP4²Á§32dôtq¤¢é™Çð8Ü .›C4t`#L78ØÎ9¬Ð3šY8Òp(£M4pÖYFŒq‚Ë,¢ÓcI³Mk@1¤’ iw‘¡´áF¶×¼åswu·[wwwwwwwwwp¶»¶EšÚh‚šIœr€–ÁÎ B ‚aËhÝœ ¦áÆÃLjËÎl»BjbG8Ü8SZ0ã#KbÀ†ÓI%¹Áªï7›»­Ãp²‡  ¤-1Æm màné›»­ºÛ­ºÚhkafÜ8@PÚY 5h ¢›y»œç7wvZHm4mmÜ07Œn¶›»¯»Ã¨‚Ê)¹|ãdÉ©npvwmÆinÌäãW7y¡D´ YgÁÓ„š46œ$†œ MLMl63W@BŇ333 ³vÛj0r gÑ ¬“ 5¹&³˜ÀVMòöÎcXYÇ °D£[K^‡pÁÍ 8q€Ö4r˜‡¢ÎdÁ¤µ»Ñ¶Æãm¶5‰¬±´†ƒ ,ÒŒ(j$‚Ø«†ùf_¡E]ʈ.n7†Óq¸7¦¦ L ‰‰‚˜ ϰm0y°qþ:î霼k¾>fV‹Ý)Ê I5ŠÇ½ùá!ÖæýÎ1•ŒðyNÝAPÉijâE+RYɾÓ,ñ9Œ– àeN=ûCÌB” 5U*ç˜Äž´ËcÔ-b‘ FרPÅ«"1T“'¯lÇ ·yóädwˆwîéî%l7ö ±W^ÀÝŒêýIÚ‹Ü "/x™›ÅáÌM„še€3]o3ë?Ìö‡Ùü&Ûç­8†b€}_C®'Åöxž³Ø¹B ¬Ù Œ€ªžFöáVæÀ>ÍDºã¡,«Ñö´¹.œ×'x¿- -úÀq÷GD.f#Ãyb«Ö‡.uÝå»›¼×ŒvÝ—Z¨óþê z( F ž‘„•Š«=ßàk AUDKJ:°ÝÍðÛ(,›ÒçíoüíI·ômN£ÉyÙÍø6nÍ UWúö¼“Œ¼ú 5½±õQ(1QQd{¶¾ØU|èªø"«l¸ûàe‘ hHCóý EôO¸¿sîšÖ¶k=¶Ü»k Yv.ØÓ*µÊšª¿£û'äf,«þ"pÝÎ$k³ù[Öá×/ŒjR„'‰à½ãÄáp;ø”¡ßeã ¸«Ò›G§ÆJ÷šë]×\y$æqlBDï䨉ˆx‡Ž'I§2zÌÝiBÂÿ*ê;»„ŽÄâ¢("L›ƒ¼Õ:ˆÔñ5ÞkLrß¾sq ²b%LJx³qî PûÍ~nÄEbäÎØûSÑÿ®ðçßHwvˆgNç9¯×cœ0Êr!Ä%w–ˆ;w\j"`˜ˆ$Ûç5D'P¥ ¡áB•gŽ>YXðrQ4'DÒ‡áD'Jˆ!âaLÄ®të‚\æUõÈ­VºST©C»ÿ-Î÷®ÒÓšÝÀý ¥=æ;ñÒq'„Ü%æI&T(SÉ’^¢&w32°¨wÑpØ„´y„J™wP„žÔvô©ë£&u!ã¦ÙëóÊMÙé YVÛúÆc9é=¾¶3pÈFkAq“!dò÷@VüDL¹lCvŒ°¨¤ Šå]½3,  §4uÓ3ƒîë6ì¯í21»^œ|54Ä ˤìüc?œìx5гÞXJF¯oµRUL~#fc ¨‡( ~¯®ÏÿvJðg¢™|Œ›÷?qóF© $.B¨¡„èHþ!4 Wõq| ù# wýçqwQZGït¾?·ï?Áæøßƒíµhán%møÒj894óMÿmµwdžX2$ñØo@äÇå —™%£ìþ;Çì®d·=ÕÉWÑR"‰€s"áU»“kç;þ.òåž /Uáøêb4¢Î&(8HI¥Q' ᦔp,Á‡I0£‚ “™ÎE‘Ëɬy央^àù¾›F˜ö^}âKû—$K!~Ð;»¿÷Y³ùŸOާû9ÔÉhèè¡Çq!ÁÄ!ÙŒËmbGå™ë^Þátm,?Â;²ûÖ`™"‹=éc=ì\O‹S×BÉÕ Ë:ÞŒ¾k†hÚ˜Š( *£TTˆ´c1¡Å(‘‰G†ƒYULµÊ2íývÙÞ%Œâ-î&@B±Xàz×ÔÅœÀYPMB“JGç?8Ȱ>¶h/”Ã4/³ç÷¢ª]Ü} ,$ážóÃIálæÃ[´šS>‘ci,ܲG0¡¬ ¨Ó†a­ ä±pÜÒ,)UËÇç•JTÓìD žh˜‰%©T=:hsj§úƾ¹1vQØâ(£F@‡%L2=e±F³aSÒAÉšügDÞ>v/ç@$€«Ø*ª+R¢Ê­Ú jX ª)ZŸVÑ…aü4È = uïëAtwòˆ“â4(ˆ!Åû꘭·nUü'>;ËÁ¾(…Ç‹‘$%,e—4Vƒ³;®Hù--Xéƒv·¹ê^2[|!ñ æPt¥±9²–ñ];tÐ8? SôÕÓAÒ’‡Z™’ŒÇ„Åôú%H‚!œµ ʸªÌ93»›Õ§,Õ•…’²" h]ì¼ã¾rKÌh—O/À¨×¸°¸ Š:޵åºë¨`ª'©,ÖàäâÄt^{—‰ñ³’P‹«vWíù¿|oÍûÍãÇœ\ÉlüBDÕP’C2(ýým~_‡ï÷Ëósîìå­klçÛ·j¬NH xí¾ I[Z•½-{²ƒ#2ÿG‰ƒü‡€µHúv¡P¾»ü®ÞÝ´(³šstÃ9ÑCmì1ÅšSÒ N™HXTÉ%$’b¿¬šÊqbjê& QàÏû¿Sê÷Ys÷—csE~Î Fõ_MûŸ¦7™/ýŽ™^ÒP«„¬³/Ì´9Œº¯>!æDõ–2WºgšE•~9u¬Ç:§=”¨;‰Ó¦û"¦OσÆF[Ò“þwëÿ÷ý?Ù)ÏÔÿ&µ‡~Sg_{øù\Ý÷ySeUUUWh…QUUUûßšh7ó°ß¬à8q|­U|©æZ©ùþ&›ÉM(µ åUú+µ‰‡sCÿ}ÿ÷_² fE31$l¹¥Eú”P,1†@”€,+ÐF ŽÛÏLÃÝÓ†€Ãó""ñʂݘý LS_…þ ©šø ·¡ÉPÔÜËíÆügIeµkkÂn%}Žn?O?ï­¸œµûsp¤E»èqê¿©g/R€ÿÂzgRŒéDc¨²¬X AQD!ÊçFˆFa $áIa…˜QÃño·O¶Ü¾T´Á1dÇ1¶×÷Ý’ÄÙÞ÷*•LPA¨§7½±Ò”6K828'd™5%h"1ËöäB~žbÿk´Ç“¿žÆ††HCR`},×qÇ$ÐÀg`0ALS"(`ƒrå òHX\©°ÇÍ,aÇœ¯o\,žãñnñ¦LØ´Z´5Åî ;¾îƒvõÉwˆ598aöØTTg <þ1æþÙ·u*!Ù»w0‡ˆcÔ&ŒF *X%kJ¹@û ÎýƒL=›rk°˜¹q ÖbÉãlͬÿ$Žàý%é)†BÁv]Ó=,M¿Î?L8ÜÂ>™…ørìrºñ¸ÛÙ8þïºlð9lÛ†ìšîãÐ䆒>É÷0öa5Žùb7Ñû‰Q¨H,’š«gÃÚcéχÙ*|¾ŸdÓB¨Õ¡£E4Ï]S#$ãf7:9¢á­öCeÖ3kÓ£¸À¥<÷æ €Ds]»w€z ‡Vðàí¬u"N‘™ ƒ¤ â» :ø¾Õ“S~î€cYïk¨œúALÌuO é– ,¶¸[ZÂÃM)Qk¸®GIJ½:zäxÒOîÙÊfÅ ŠC{IéVàbà†X‹3Û,Þºö•]¹¼é¼"Nc}ÕV@e HËètº¨ÒVÃG@™Éó)ÈhÒz5X9dŒˆDHyñ"Mƒ›Ac{To³s÷'sk _ÉOv;ym7-ÝÓÔ¯«¤wÀÜ¢ymðñÅüzo ÁXijä9¥¤øì(}.‡zéÒŸDŒ€Ý‚•sˆywe¢G8 f@8ï¾¥†!ŽÖ’@ g’FÆËÆD€ÄQÉç±IºÜô~oty|)È7Ö’‡½¹Ú²ˆwÉ  -`¡ï „Ú³ $ –np5œ†Ù °yÜøN¾"ÃÙiSâ[JT!Êö£×Ãç‡k޲ÐlQ:^ÇÆðþ¹ÝÇ„–ëáv¼ Ø ./›ñ˨е¨fy׬*¤´Ì€¶íz‰9ˆ ž;ž„ »›bÜ_E|ý#ÒÚ>ÄNÒÁ€Öa”1háY¹LÈ%P¯jÔf˜r™&lGbG¤D:#4¤$Ò0‚ãtf”y{{4fžÁàâëJÙ¨qv{È_—=Ñð«Žæácà]“Zu¸{úP¤Í·¿Ìê}¶Æ~ ë¢q&pø+€zqöÀaáG3öøûqH'³ÑÞ÷ÃÛs ŒOX:ú=¯±† dÃ8xÍÄ;³òÛµväá ¥êär6·rÔðiZÐP‰<Îr¨íÊ0Í* dAÊJC蘎 -F,X ‘¹† ¶‰¡ÚÑÔVS“˜«¤Ì”Ê¥8V£8ªBY¸)÷€!ÝZê ´dÀ`ë‹Þè,¨AI²¤ècfÁ Nc9! ›…‘geÏ<§l’á;}±XôP$Ð"˜Ý;õXߟ»¸O#ÔŽvymXqª £u/£P&¤†i¤f7„Ï®æF%-]ÉF Bb9ÞŠSfA²Åë~R!0 P¶h¨WÂTÜY†²U’©G6œœ¢–]1ƒ{ìÃë—ÁküI¢÷MÛÎ4Áç¾…°íl‚­ˆHMì&vxG§Évç.kÚ0ÛûlÙÖb؆RÇ3'-(!¼A` ±PÁV™Ê•± ™EDfaêJÑH+q[q ùé˜ •U¥qÅT´|¿¥êváiã¼I~äö½„!׷÷ À0–:̹‡=ªìøZàòç‘Ðê\8€Ôw@ÞœŒK Ô ‚1ˆ—8½˜"ÊqœÃ ÒvG9Æõ½­éÍmGÈÇñðã}¤ÖÖíTí@´nꨩ‰ç,²rS ‹¦YÍP3C’ NJÖµ˜.¢09Q<õQ3ÔÄZÎJ©3¤óK,³¬àí4#‚žÈoi¸¸¦w ‘±”+žj:xŠéÜðç»híéâx¨x§î¿û?Éþ£€nä/™ãçâyögá:õh¬_—R‹ p(TÞ샦I2„0$ ­Í®ŒSœqaÝßz›÷ä¢È(,ð´PÝÙúü«çŠóƒ‰&NÞ-,v˜í/cM%‡æCg3 ¾»‚û~ûC•“”zÃÕÍúwÎצéæäÌ&=!wëÅ”ÁÛƒ‚~£FëÒ”M‘Ê-ixgÅ&ÓÑ7\™íêö]|·ô n+w‡“·Óßçôq;zÔ Ý½¥ ><'.ιšiRüí|ݘëI˜ÆMÎÝ›èˆG”Ýc­-ÄLΈ œÜ"¼ò¹±­Š1!^U,V3üîæö/‡g¹nɧµì_,¥©½vfî¹l̘^Þ®S îÎí>zÔ'Ï䣮Ö峎‹{aG^1¡½‘éR«¬´º¢!Ï0´T­T³>p=¯×<ŒŠ0¾5lÓE ¡ ¢%ïyé‚m`ƒÀ*´˜¤§íø>†ø¼‡ó—åcýVøÄÁÌ'—½Å¿$y–ŠÀÉeavqogh ÍH’#HÉ*,Üaˆ€Ÿ*±@ßæ¿C³»®»Óä𰙪¬“ÀN²Œ€°À˜ŠYXJÈ¢i¤ FK Iý?-ß·Ìë9ùƒh*þ]¨xwRÖæO›N6ÚšÂÛþ³Âo<í8r°¾éÄœ‹­—“Ù}»ómõ=F_Ìô>Wù6­½­µ5êX*k§_]~‹x»¨´¡ Cþ¿ì~çú¿æ}ÏËþáý¢œ]?²òWá<§ HKîñTò6úF QÌÆz΃›„¡„“†äÒ’B1¶|?ç·9ŠðÒPO®_&Ý}/n/êÖI4Y+Jª„D¨õ…• 3âæË6EBE¿¯„äÁŽÙcü²•Õ…ã¥ÂcÍ×Ì•Øüž4xmdySË3¶Ïçz>š,(öšð2?o£gÎb&=r@&³OÙ+pç9ÐFtö#ƒ”íx…”I%pG ,ÑÂàƒ„9%p¶‰œzجåš+ãFqo?Ñþ&>^þïu•ó} ŠDôü&ÖÕõŸƒcÝç}¶ús37¯HÜ+'³ð;÷ù¶øIÔêR”¡JP!‡id4&„ ˆBˆw´ µ? ”o¦Á}?leøe'í¿‡Ã$;mIÄê † Àúu?ÁÆvû™wpÜX ù©¨þÖ.&ëØ÷¼n$fzk [k…#’$|”Ìòf^fK’PÜ>Õ™JœC»âÈ”ÓUR®¹$«Úæ\¢­%@ã€{äg?§D-Ihå¿‹kiM¥lõ‡ÜÜ~ç幎`q8þÙÀ!Æšpoñ»pµ;ÜsæEåýÕ»M›ûÒÏ"€'âï¹¢Jašëg=<ööÖg‰ÎîkXÛçz­×NÞèí÷>Τ/¬'Þn scñ¤‡a$;——Î!|;«­ÊÆŽ²i;JFHßéíFÑY %Ï(E°""jîÎøˆK â7jïçΚN»ü¬ß´ó.z—&thÍÆs20!1ÐÎŽ²9º áBó®Êh•k%ê*3 g„g½8ˆàÄŽ5]•/¬i3‘ªVN èi"Î4«ìMq ãcN„¸ÞÁ3v(ÅtC„ÔÎLf3¸=ñ±ÙÈ4™¡­#“‹£ 9XÒ©n âÄçN‡kOeÙgϧVÚý••µÔ•*! )æfâ {Òq‚5@^n:€÷Cé„!‘ÑÍ:p«Ž œÍ(Gv(2t c];ô¦”ÔÚJÁ™MÖzÌ¢Ð4Šw€/`д{kiÏrätå­XêmUxð^7_Àñž1Ö9¦sÝú‡Õ3Öwyós^îÿWQôp¢Ûe°Þï¬ÿQèh,^iÉ™‘M­›–ªÆ5‡ü®•‡JT «œ@ `FK'Á Ñ­¼Qú/jG]Ê¿¸ik(=Ò¹÷~ZÃÊãÀ‡Wsx]hH°h¢_ÕÂØZØsºxc†TúqÒÕÌ4ø¼Gû˦~3ÒTü>aç($«ù¿PDDÈ» å9 ·çŸºc™+ºÈ'9Ç8Ñþë:RÙmÎ'îŸ÷>ŽŽèýçÅãýÈè!ÃЖ,‹Ñýö{[ët(Ì}¾ ëã¹ëáõøL€¡ä”ŸçËÅù4¡Ú&ôxÁ† @XH@8ƒÀ„@" $“…œ0À( ‡™ã»Î½pÌ‹1µK;ÈJÓü«·ñ>cC#ä‹—NïÓŸ–÷ø³è~ÐË?˜n„XãŽ!ÇŒ£! $(ÈrNoƒèÝ·¦zý~¿¹ñþ¡ÌêþmÖ}Äó¤ñÈgÈÌCÕ<óàóõ-ô¹ÏèÒ}Û5Ÿkèæj9…Èñ¢ëG{­UÚÓ¾ËôéáÉœI7ã“ɨ‰"äDöîC³”R:.@Ø •k³š£´~ìÀÜ`(q?0²ýྠÁÊ;2§Ç9™ü~{g›Â^Îÿ:ë L³YŽT7óë7ÞàïtÌÊXðÔYÇBJɸ/ÁéËoê}¢? G÷&f†“Ó‚ j%Ók¯—å~_“èêòº60D” .Ìûß¶ª$4Óg«àrM8g-ɦãkI¦#G„a9a0 pfçÜcœZÒ•7 ÝJÁá(ÍE¢÷shÖNlô†m¥+JÌJ ÐTZGÚ­UyU3HÔãU3E¯ÞÐJæaqPJË£ \ù_±9ÃYãø>sØ=uo‡OÍ:÷8mº×u û»Ê.Gƒª°7jq„YD¥AlŠN%Z¤’ªIÝcEŽ ìÓ•­ye0n1Iˆ¡‚IÍLb”c–FàZ Ù"’‰2Gœv‹þh!ꌠ$ š¦ðÕÆi´ÅøQõˆ¼†ëŠºI 5´bÖÎYª„‚!"ìÒÝÃ\ðlÝÂ_=—ÙÇl•©¦…  L FN¥ˆ ‘ˆÚnÒx&l/‰QnÖNÆ+)&q|.Û†"©¾J{P¶™ Î@.ÑÐ ísQþžàñò±©½ÆI"¾„¤‘ïéÞWoÇ¿Y4|»ž:få-Ç#ŨƒÃÒg'o=ñºL|쨥ƒµâNtF= ¡Z‚¶*Ö’ …\Elµ6Ù>ý&t}¯ożñ‹òhäˆ'ä,‘Ͳlê‰(Là 3»-)6üãœ!HÀ¥ƒQ¼=^ocÓ@0¼]/KÐ0`WDÒñÈÉ×9Ö`Ldq37K*Õ¼TxUIŒÈÔïCœÃR„@Óeqî¸wDËn\9]ØLóÎåû îÍÌ‚‚! )¥YŒ(Ôm–”E¬âFŒ¶ ,¨Ø;E ñ°iÅ4Ý£ãæÜ^‘c=EšèË=²…Þp~NÕ£ÁOR&E1x¼UJ 3H#VBGH5-²2)Yè46À ×B>Hw5ÊxR{ácϼb÷ÓßÁ3ÊéÓ‹Ëó•x8u®q3»·o°p\®˜CÍȤ÷ívÈÀøÃÒǸÔÂgš…ôíf+ðÃ^,û4÷6®9 8É(Ïìy3wÉçܨúéùwò4Ò(á$“ ?dèáEtYÖtYæŽ D({·Ýzä×G4u É´a­´×U“¿þwÖñ ®”·ŒÌÌ î]™64R”¡JSÚi…(”dš7Ðà2œzu‚syL«.• 5Q™;d}¯Uìv}8€A0v ô:IC•0LœŸ3“%£ß¡v~¾Œwüq½ãõ³v UW‡ #8JßÂüp㪩…ïl²Á‹µ~þØbëøzI3Ò…ùás PZLK-“+fb4Ì!™ci-Ê^ÏsÙïõ}ïwºîÓÚG ÁHÜÆÎ}Þ4´5µ;Ú^1 … D…’ׯ‚ø_'d²‡lXrÇ“ »\š%cóeùúŸ{2^ÎÞ›;w¬üÍžª*Sô±â*ž¦µ_B€í30ñÌÐ$Ær¾äùéÝDOu®.úñ¹àMêX¯~¹Gžá?šÓˆ»Å­Aß—´ /®7,cèèã]¬D½ÁÅç§ Ê4\âã<703«0¤Í‘ 6=AfÂ"¨sY³:Adu(:ÅžQ•m•åçšbE_Çž‹(õxTQð8ûÊ||>qê}‚ÚñâHÓ#¤ äŸïÜ„fRìNôZ%̓©uòº‰LÛ³FEU±ç© lù‰´@ž5HB ä5aXÒDÚœVt½1„ÑØ`„'bï!}]Oh£¥†Ò }wÎK *s¿NÙ…v;îT‰—U8np’•uµvçI»`.«ZäoXð.a¼Ïsám·+Q …ÌBŽpœ[;N (“KÏwŠ"¡€’j$ ÑØo€‘å )4DÌOV„$Ú65Š„ÁŠÒIF™M`Í¡¼"¡/B‹ 2†1°DVb`zìÙm7ï;Ì]¶ýI×Ù©Ë$m¼ÔÞšjÆBŽB©*›Ò’³Hš—›„¥”è˜Lª””w Ä¥ žö§oxwáëÑàê‡Äå.¼ dXšLV¤’‚DÃÔJõžP’Ò¥Wˆ{ÉÞ•ÎAŽæg*+]7(‹Ä]ÆE‘¹ÈÁX¦a€çÊÙçUôdÆ>uïZsâxÜã䢬ª°õ1~/Ö9ÜŸ›Ìõ|?:2lPÇÌ~»óíA¥)DÀ[&ÒÍ õŒ+µ'v“GJ&ÛPAÒAgôUÙF–4—ç«m£Ó9äåJ¥Ó³ƒtaå翈¤3Èœ¾BÀF0rËÞÜìÄŽ"õ¼(]0\ÛñÑçÕz½ä<;bnÙ {;äÑÌ‚¦ÎmnMnÆÝO¶`JQ™«É¿G™ää3+Š¡¨À[HK;)/=°àpßrN½R™8¤lðý¾¿ íé½ù1¨‚êÈÑCK펭?(vä‡DÝD;$”‡0îè5߈õÁÄt‹;6„“òðEu%|¬±™¥‰\ÒRFx™ Â@M k«N%šæb'¼äXØLíEÜ;\1s(ßšoÒùÇ€q¼Ë;½ðŽ›®ª©·dêÜøC¥Þ-™ÎG};µ ]Q}Tyy#ìr¸SÇø¢Rññ·ÄõŸoâ{é33pÂàw!ýzÆï'Ò‘Ç_/µ´ÙÍiaR¥‚K@³µ(v‚^²¬h)@ ‰$8L´²$V¾LÀ`™>(/U˜ŒÉÞPcs„â“Q” m“R5•m³"]ã)’W$²Ö7ëHW«õ·ú<ãû?õ½Ÿ±ñê9†ýÛÏWVáË÷Ü¢d=‰Zǧ¡íiÜÂÞ‚¥ED¨Ôñ žBû6ò­¸¾¥Œ‡Ñ„8D}÷¿o̓%!ÕUZ¸¯–tŸœ™¹X,”$"°u”¥òþçùØÿëòâãØ{Æc~¹D5›Ÿ’ü•‡×õáöbº‡I .‡"dÞÚíäE¦+6ºÞýFÞ~[ž¼ñ zÌèyàéÓ³3¸³ðx3)ǘó<óŒqlvwé7€‡þžµ?OiŸÇàû«úc»Âf_¤Æb—L®)x½÷ZìÞãûá¸×ó8óî ®¯ ²¾)î±!RÛÓtµTvMýH¸335?Íÿr>œp‘Bþª¯õgë…w;%9†ˆ²J0‚Œ,0’pƒ¡YdaC‡ Œ$€€°U™|DQyj8å¹È’\¶9³~4B\¸ˆuìúéØ$Ј‰e)d”¥OÜz?0ÑO¯£›ÀÉÈH¦ÿéûßäòŧ4ûYúÛË›ÓK­µ—l®ÚÉa³1l§Ò|ñ9}ôŸÀåN“§+^{\¦³7¥]ö¸;o½ï=îÝUç õာUUQQU jÜb‘QR,€(¨Š¢¨Ï_¯×uîúÇ8Ä›ž…ÖâdàÉÌ6{ý4,X†¦¹¹—ÐЙ…;chØqŸÆäkr ,2¨Ld¶“#;cQgÑÌŸ·¹×:%Ê:Þ¹™áNõ\ë­5:k½ÛÈ»ØÈ%Ü{Ž›…=5¶ùî u=âNîuÜã_ƒ8Sÿ™›ðlSž‹R}³»(öÙ¬¡¿ -îšög ¬G z*Çoã—“XhæóaŒ!O)2…ŒÉZ‰¸ -ë²áé„+Ô\¢ÍKÀ`À+ÑþÍ.µòXØ¡|SfI@``NÒ*X‰¢V’MaÆ)I `ë2ŸÄÌm0ny!ÕK¸[Orw„I ñãv8²Çò®Ù¢û\Âc¾J×é{M—·œëW}¹‹„!PÕȹE3Õò£«Šš •ÉH¢Gl%癥ˆ€Ãå\ š Hú(ƒ¬ ÁˆàƒdJLZN.íƒkFÅ‘ñ·Îô﫳 )› c ÊcŒb=ÐAˆˆ#]¼,Š"ieŒU\ÿ±ÍòŸÑ^¹»³7G¹‹fæ|.Vo )÷Ú!Q ªÄËU’%Im[]Fµi͇ÕÀ`}ùXó_«ÌæÙuVôû",D˜I’9‡Y…9G ÊPAc–g3ñLRÚ·à–«¦ävâý_Ò5Ow¹™šI†¥(R–A(”(ÈUô³>Ÿ²`nXû÷À{¾Ç»¯¹–ý¬0ök 5䌪j,ffon˜ïuŸ89R㎔JB™í‹Q_Z+/™0_O‡¦í=©aB>ÙmÙÎW´“FÙ§ %¤ãr €½†Ó !pƒI8ÚÀ`ØÅœ0B¡l³©™zžO—ʨYx¤TÏú>ržžÌ9›¬Âj@A9#‹ƒ; +¸ƒ‘m+Bü!éWNz}î¶ü]ðt‚} ‚œ%á…çcÑ+¾Ê‡]U‚ã(!û¢¨R›6uW)yær˜Cgq×:+ÇŽ´v9¥ï+yp¯÷1pòŠw /uDŽ8d9ÌhzhÐOÖÇŸÒž5³½#5ø"Æø·—îü›àŒGº±½9¯ê•xº¡‘§]´j–ÍÌ,ÞcXJx­õ<{hÞO8êú*Slf[{W êËœ‹ˆêzMÝML&¶¾fwí;׋þïïûƃCƒc ðó¤¢a¡ ùˆ`]ŽþÜäǧ˜ÖG²Íî5Öš¯ïïuvŸŸÏ.vöÔ2î·'ž>–×Û2®;'Žs¯3ÎîÓзËäß•ùG‘Ðì ù¸::æó~^ŸÐ`7¤â…ÓšÞÌò%Õ®s¿]{³30\vöÚÉGføz[lˆTܧœˆˆé{ eDyG•=ø½ãÆøbµ@ÞNv@Ç^nT#gƒdÏS|Ën…y6IQä­³¨Ä€¬!;Åc i¤Œ³9"«¼""ÖrC®$­=se¤Aš.¶›Ò FÞ‚î“.BP­ã7ªMîhÉho•ñqƒ"³)@+^ѬJñ ó r9LïFòUÖX­á“)˰´›²CÍm;Eìbk³èAôãO¤^užùâ1ìF6! H»Hš7¬ÖZ,gPª°VÊ— „…è«z¤/yy¸}ºðÂ%D/Y–ºÏ+„–9éòP§®êç“äd{{@aO]NW7<ÍÐ\pœ£•ê$ò.ÌðÇÃÄÝÔím$Z‹¤ÕV2ˆdJRquR<ÿºÄô¼,Ö´@ ðx!«”b—ov(~SŒ„É•ì<×­ýMûèaå; ÈÅ…!K0R‘ΧJÀ8( …£IP‚Û¸G0ˆnÐp+ :Ä"Ám#–™V‡YMGÑñ4¬£³£±<ŒAL‘ã¨V¤T;¯inzÔÙP›G`e×W %¹7æ·WÐ8—\%V*MÊ•™4Mà€ôp°tZŒ¯UZg”D¥ ÞPy|Üïàá¿+ÛþOÓûÞˆ—–»²á&ÑQ´m„`¾Dß½¥:Rt“cČȿä!Ê/*8KFšBÿ–òEUþR"NEÿ\²¿ 5Ïæ‹’>*¼v„]slZž-í¿ÅŒ°%¢ÑT"’n܈Ì3#‚„@Ê€iÑ…BÃfªŸõ Ð}•ÎihW±Ø{VÈd¨g´ð+ÍÌ„Õô#öñ$§˜„À~:ûÒª•ßÒ32hzµ‹ú_÷ßÊÿÍüïÉ€çÇ›OaÏÖà /ý^g'Ðeíô ®mø•’J(­Ùc´>»ö^ÿdòJDG+”¿b²¾Ý¼ÉÇÕvI'`‹;(±Á °8h‡4á%œ$“ 0¢‚CH8kòbÎFMU¥ÄådÓ–Ç*îÿ‡ßÑœû7–ÛhRˆˆ”¥()IâeS P]ŒüO­÷ omü-ëG³_pšþlfŒcáÌ¹É “-Šsíà€2Èz¦‚ Éw÷§všt·_t† !c(å›E+7¼„…嘭­Œä6#ƒðÄIXaÍþ½¥]:®¹O2Y£:¯ÄÕƒÊW‚ÔαEg*¡ÖЂ´”ÜKuÒsYѨjj–vµ«V¡Æ UC”ÎffÐrZоȊ:ѳç¹o{,è@u©~ô輑ŽGšîÂÒ€˜,+exs¶ÖˆO/ÉÏ|Èþ'g¡¼7»ù'ž1‰ÞáüÄ”Q¬<øOŽ_:Nl)E~¦>?é¶ûLEƦ‡€® AIC!RË›¾qwÌovCÕðÈöïvúžã›L‚ï¬j‹I¢{“ Ñw8_ÇryÎ_Q5|7®íj½r·¤ÉLTNFñëy†_dz¶ˆ(ñ¼/}3[IÅcÃÁíUäQóqmyÞ9=dý b/Î=c¼èìˆ÷æÉÂÇ<”çÂõ%1ÛôÐLõäs·¦Hу€‚tÒW¥¥SºèSÎù yØä ™"¨¸¨Rˆ Š Çs ÞS'f$.¡—ÿ[RT¾´KyÊõåy“oEaÑ& yÏ7ˆ&îíKüó‰]z;矋Ï·ôÛh ‡Øæ0÷ôR–*$v~ô ¦Ȱd‘ôóãt¢ø£ ~\z&=ߪ~÷òWMâÞ¸þÜ/Rrù|2É#^3Hè )*BMœôµŽ‚‚ApzŠ‹È¥¡Jh@g¼¤c%ÉÜ#¬…U£ZÃ,Ôª² ­"‹W‰ ¡ âÎ  « FMH´„¡ …ÌΘ“ÒjúÈ€€¤¬¶”¡éSŒcýsÍd±Y†¡‚Dº¤@œF¢" 4ɆµÖBåÙ)•ÄÌÛÖÏeW· õ‡¢£Z¯g-wWW£õÈõÂÜë0·;å½Ü˾¶swƒÎóZc΢¬Ö~¹½{AÑšFœU_%ôèìßî/Ãg¬<’W=b!ÁÉu”jP ZœäÀÖ'+žU Â2†µ€§Ç¶¨¯#ñ«¢¹7LºÊ®óTûÑ0¹°>‡V8pR‰ÇMghTDmVz @‚ k¶!‹AãSŒïTG…[ßÄÙÃÄqq £k¿|„qûÃ^8¥`aÖSL‘§uzÖ­d”( ÄÌÏžtºòî°Á:¸Rtv$2¯åí§š<öd§1ô†/´òᇊñ ¶”Øw±%w\ìG0/œ»/=C‡S ošy——ô¯©¯SÊ…{wxÿ;ø𨌔õQVd=4į†ÍãeZ¬Cà|“\»žë<ÉÍšiŒæ1Nñš]¬Ý Ä➌›£¶‹JÓÑkÂïîeïpÈùÝzö‡)o]0D`€Dqœó‹¿į¤ïOéî^… \*YØë=Âÿ™’|‰¹É í­¬è‘"D­ k~œ—eŽ’vXY… y,˜Œaº÷@ƒ Úâãês‘ÇGïlýE;Ëß¶–¸ù",£‡Y‡F–p‚L8i…”`æA”lÂL~myŒ\~'ç§DA¾¹þ8_Ðÿø„vîîîþA”¥ PD¡D䢿ŠhùžïÁùÓë­ -RJ˜å¢cÝÇ=o­²Nñ‘‘Dw›úªr¿°;ƒ°¹;5¾…ƒ š‹¢šKi1åÃÐÛCf Ü0Ù¡°F”8å0ChØYÁÇ@ç8RQ*çóaAøÑZõÝÔ«¬{ˆˆâèÃ÷ë­®v[Ñøi”? -dÝôL³¹ …‡P§w^rŽ£6ÜHšñÉïÛIÓFr:m±ÕHDœH# )Ih‹óÙÖUS©Ú±‡ò¹&B@XP­^y !aG‹­éhÅ ³Ge¬ÞHÅÓ”‡Â!f¾ÈHŽ¢›3ZÜxwÇBT¤ru˜®øÀZ±8#F‘ºiõ´ƒhq O^àPy)¼¤ÆB…ŠDG“U׺håuƽN£…O ‡:ê¹AðK‡8ú›±»é*˜ß‚;PzEœ¨‚4…ÌE_8‰û´b@ÖëFÞQèö…×71æ6ù§Î>\ºíò©Ð :\ªÜ©¤¶b¶x¬…mBXâ iœbepÎâ!/XÄÀ”¥ I¢f•9!±‚éŨùTuá´of‘ÏM¤ç·Åbi‡€‰rÄò_]|*'¸x ×fà½Òéê‹zírÆž6ú¶¥tbƒyzÉ]˱¸Ùƒâ‰Ê{“¥KP¯¬¨€1PR±±äTCƒËUÅ‹+„‡Gx¯z†Øš=Ý«ËîmÜœõÕøãÛZgjÈßFg\þƒ!ÆfÚ•ÛuÆ®s!áI0–qþS $2e”ìH ¦"VbsHé!ÒИ9µ)I1.Á ÎЄçUjÊ@)¬H¦”³¼iáµð^JM|;óÛù·Qƒ.ÄeüBm)“æoX¨®/tl¬R+0ó”È8S•%Vœ:ʳ¤Öä¼oCÂ৬Ç|èÂÈ•OSÂÃq?‚{Rº«ó ›åx:‹ Êsúhoþ†9éüð“Ó幋µ\žD*î^‹Àª¸‰äcrKeeo§Ä¾?#ðìaò aeRÖ©U¦Zå•£0•Òo¨ ÑAe€FtS0. iBQ”ÑäT9+ÝP¥PąĪèЩÁ‚ÖP3­Dä#sFy”Y$Ík8‹»!QeœYâùýà 3$Ò4­]­ëé/ÈûßÔù¿Óþ-µÌa˜óÑ×Hjò’ïGÙÍIÒµX˜3eÒ-IÀ¤ŽÑ²ÁÕà«ÆÊç'H#8™¬')DãŒãç4—ø›9ƒÏk•½Óm2ÿÔYëö«Nrp—i8¡€dÈÌ_i_ ï ˆ_Ö_.Ðò]ËåN¡ø`÷«µ2ÜÁc{ƒJ ‚xI¯ jP1óÏÂdhgJù)AጌFŒ¥8Á Ýrc)†ffƒ’ŠÓI0á&œ8Fšp’ (ÃD $s +uôÔòùiùA6n¦&³(Áàÿ§úÝ¥óˆ‡x‚ R”R…(JQ±Ï›4h³÷ÿ_¤ßÄØöÃÏ€RÌk¹vnÞm»&ÞŠ{á" ”„ ÄÁq‚Kåé£Y¥ÀIKNf´sX,8``0hhcX5Ì-Ö±8Ö,*ÝâÞR™—äMÛü8Ž¡*æ?smÓoé ò4›eZ3ˆŒ8јXLpâB‰ýàÿ¬Yâ·ëÄ4 £{ ¼ŽÍ¾[Â%P<ïB“Åf±JIŠ+1DƒR„RŒÝŒÚa8 BÅ=–³^¢ 5wf"„è±{8HA ÞýE4†—µÅ”8ÈX Í8À q|Rô"¦+54`(Ïä—.oºe ìé1}­:Q3Y±8é 'uÐQtDlYgT¬²œe!tžBM)dç0§EQñî_ª0ÃMuäôcà:áäeJViߟ‡ÌëiZÎVt˜©ØHÐ`]i#T±c@¸ý½ˆ·ä5ßGLN[v232·–y¿@¼“~‡kÉ&ZŰÏì·áë·cäŽa³ô{0zˆö0°èö·öGg°xnÊœÊﺘ*#®Ûq™Xr»˜æc`û5a5ÎEu¸Zû܇VùéÊ7±£$E°'¼.j…}°€:bq´<'Œê¢¢±åàñw7bdIi¨ ˆœŽó¨¶¬²ø½YágŽÈ;;4ÒH0=UÉ%£ÐÅ êÎ53ûØÞÉKß±Þ·EÉ®M¬Ö“ƒŽLä jMå‹"|Ï6ûN¾[Ü)¾³¸PNKgDÕ*iX×EÒ‰!1Q ‡w Œ Éoǘ«P™ÞñãÝûg,‰~‚+‘Ñ`SîJžŒ–õï½é­Îˆ'£2í;ï1ܯ%ˆLƒNQšD¥&s’VzP>´ TT Ażrå¾b=sˆÓÙôn4õ¸mÜéå«–YÖùÏ—ßg] ã#ËùÂàݵsA*vòßYB!0pšŠ+%YšTŒg¬?cL`\/K4rÝ»0°±À€ðg/"+ÛÓÒg¹[GPïê¡¥jb,NZà+ œ“ݲ=ó›8¯ŠÜ¥vz×Hn‰-ˆø}Vfçm,Ã!;ÉÖ@ÅÅG°/Ó|gZžÈöc¬îËGV{‘¼nÕä•jq§0²ÇKr?Gˆ¤ó.¡Äæ½'†HºAÖÚ‘ÍëD•)'“UéçèÏì~Gå|5¼íÃ5v=¬ !¤6Ke5Ø®fFeûî2“…CS ap„Mÿ­FñqŽHkj©kñämy„÷èø}wyð8 }âAÝëo¾ýÞ¯ëóü:oÕ?|#U²9O:Ïa³8éÜÙùc2 ¤• °ãf/8éó²’$HpF‘Ñ[ôíšï¹QæÜæN¸(ƒ&zÇqèý§˜ÐbÍýÿyýžG²ÐnÛ•”Ø;{ûÙ…Á€"yj ('ï\zÕ˜Ä@ßsÕÐsA0Ÿ§qúŸ;çð°ÒcVºÆhdäaÕE6¦*:ˆ“¢{øM¶"’‘%-(™hÀ*´Q,1 (¦õ'J¼ž¡U¹c[™79hÝNb«ûÚš3„‚B‰Ù¡*"ªÈJlQ’ŠºÝ¼¾˜(>·çkáˆ1BBI$¸õÿËÚ¼1Ž äb>0JhÚhhÊh«ý4Ò1& ,FQš12P¥&ÀÈ…%”e< =›X˜x¦ñ\†¢3 Ã':»5)´V&Û0ËK-ZjPbX­"f*$UB†JL ÊR†Ò|šÙ~dØî§cGâèÉJ$M¢2”¤A‰ÌܤѩϴXY£m—¿*ê5bYFD¥–U±M`¥;u)†ªÒ…2)‘\•054`c¥Ãýx1@Ûa#C)KÕ9E D̃Q9%"$M–”K6†.Lqp*(™93Fµm©À‡ 6›dYfU…žðab`–hÂÄ=½L"MËnJ1 <°0È‘” Û5žÙ–p2²›…”IJ'J1&`˜MFD˜RPÀ³Ägaìë×cŒ‚Ïu¦’ r –öê‰%œ÷fwä_ò ÷öèjèaïöü05ÁÙ{;Ï Å.Óæíч 0ô7Z¼õb»ôUFqê‰äâž\d®U“j ¥5có1s ÞûÇÊ͇ª‡T¯1\nñ ù‚ѱ0q>¼s3Ž>Éí€ç/‚úHaBüÁ™}¯Š“mJ$øPm‚†É3MŠÍ]$»VÙ­T˾Ådd‹ @@YhXT°ˆ0_`4q¬4œ­Šä-J‘k !Pª#ñ3éåE!!X®;ô}ƒ¨@Ô8§ásó‚økÅÖ?G!êhžÏ©eÏd%è1Ùtï­+âÖÎѱfÆ G6Ã0ƸŽD‘th{k#³÷%i!üX½MÅÎÞóþ£³Îgù÷åû\˜ËÃõÉ ‡ñ>¶ ˆøÞÞÊ:¦Ÿ/ãPÙ]{W†Ï©ÞZ•'ÙC½>Ïè`u)>ç—öŸOõ¼µ«ãß˵ðþ+ÝX<8;0ÞªtL6"xìL[Ô߇5GTî>ýÓV»Ä£g%r<í‹E- 7_£Âó—Û¿g”x$ü_còÖQò}¤}{RàÀêü¤Ú‡_Bˆ©‡ Ž_§o]]ËæÎ[”>VPP>©â'‘Ìó'¿êãàö%6ÍGàè€1#CÜÄ6íJžã(Wi/žÊ#ãuèNó™»Ï,Û›ûúp½>÷L3óÄDP3îᣌä±Sb¯òÖK%Ó $èA]8oX''ÔèpÌbú]ÎÈñKÊŠ9T9oÇ !y†{)*{b{sì·_N;uÂbÙ ˆ^>“ ¡­ï|Ÿ®èggÔ¥~Ãí°ÉbešHiœÝß™Ïψq%bÅÙf·:5î±Cb{`õÝ™ódͼ^µÛ§ncœü/1ÆO`Dˆ èJÿ|›0ñMs§c3ïnsÞ§«X} ÆúÁcBPµ²>í3)Á$’—öút¾N3 ® "w]^¯SnðßÏãô´ø×v»û‘­lÉϱAnEíÅÃ|¨oC šwMlFÞ&¼}bÇ¢::k|Ä Tªò ½èÇ 2⸫ŒÕdÖì¸81aQ l\W(ú!ïâÿï×ÝÓÙ@Íìk¼ÃzÆÜNdb5Ê)q¸Ç6®Œ²Ái]~F/AWi9+êj’ÏLîöI°ŠÖýWH¾OÉÇù\-ÀPê?sÿ^Ϧ =ŒC¡WÔý—v—únüì0´¾©·;¨ÜTÉÆ·Ð•äãÁ¾È#¸› $Kï[æÊÛÌ»,6ÌÌm½`ÐÍ÷×H‚œ}ïZ{±òãåµcª»@«"èàŒaӿɽœ˜úÍ|XcÈÿdxuÒþì¦Ï†§Ñý¾R ÌÛìz×|mÛáæûêËä¹f“©Ùë÷¾Ôè ‚,‚ "‹Ï«Ê]B«ä…¯ ’B’{G°ï…uÌôŠà*¸ ¬Y4PŠ’ H‚¬UX¢ÅX*аUˆÁUE‹EQDEX ª±EŠ(¢Š*‹TV(ª(*Š*‚¬DTбUb¨¢‚¢¢Š,X°X ˆ*ªŠAV( ,U‘b‚ÁAbÈ#ȱAH¢’'r}¿#GÙÏË/ò7ù¼{mXËUÒ"µUbˆ’2I# ±V ¢¬Ab0UQbÅQEQAE(*¬QDbŠ(¢Š¢ÅUUŠ*Š ¢Š «U"¬UXª( ¨¨¢‹,€" ª¢UŠ( dX °PX²Å‚2,PR(¡QÛüôn´HüØ‹?«ž{ú½Ø£ŸxØ!³N™˜‘rëØ€ÖCÙáâ´È¢»]/ÍÄøàÏ„³.&Ô7~¦ºL¯9„;$½úîSgwi6]/ ¨|‚ ðN*ÈUZE„~ù¹/ê}+»?BÏëJËæB›§Ù7ÜJ98„–õo‘Äyã=Á'LøÕëÃíZ¾Ðˆ‹¬€‚¢"# .`æÃ`wal8 ä‡ êƒÈv !à;‡€ø!D öÁ¤ã"„xº†Ñ<‚DE ÷ €s¢QŒPBûÓþº;ãÍ퇮$$@bÄIÐBQ¢ sÀWÆ(ESÖ~§çúß•üøƒÂBe€@* H¡#Q‚(ˆ"„R(€"Dˆ’1 " "#‚‹ ²¤X X)ŠA@D‘A‚¤R,E"‘ˆ‘I‘²,Y ¤RF"É"‚‘)"‘bB1„b"Š0Š¡E€¤’I%@" ÈH$ABƒDPA# H A@R(DˆŠˆ‚ŠB, Ä‚’(£AE’IH±@A@b,ŠAFB $PA€±d‘b0¤'²™ÛüNß{R¦‹5õJè"úÙÉî%¨*RÃÁñ|Ùâtß”†òö²!˜\ "° d‹©X•V$”@Œb1Z”‡â8Å‚ãR,"ÅP•[Jš+-ŒüfǠĨÚE‚Y%V0¥,Â¥AZE%* T-¥¿m£»+]B°*@‰ ò¥‘@B ‡@ª–ú«qU¡U°¡"PŠ(ÕJX¨¨Z""¤I#"AU‚),U"¢,bÅ‚ ÅUI¤‘E@X$ФH±AEXƒ"Æ0oê|øBmp’AL¢ LB U¦…V€"ª² I*ȉ ! Ь‚«V(¢QHŠ ¿Ÿ`U}=À£ìáxÀUn"©Vlm¯¸ªÀUß³ÑHa²Kü‹®aËKoÝ¥¬Ùçz̰,[ŸÃOúxmš¦ÙÉœ,ó·}Ç;tç ¹íÉQuæ@:±§äC‰>Þ!íc|&JÍLq pO[Þˆ-ÑZŽ8­_ØúãÍ ÿ*¹•@\Xˆ¨zPU}(à„Œ‚’ Þ‚«ÿ& àªûL‡Ž UªiEZL‚«@Š¥ #U–E=8ªÐ Vˆ#KG7êQ@ÁBáU€y!êX”"‡²V* R ‚ˆD¢" QÉ’@ˆÅ‘dX‚Å„’B(‰ ªDˆ ˆ,‚ §·Vê'¥˜ÅW (ÐͱÄeñ¯¶ö‚®ºïù\bÏìw‘}­² ½Ñïh=ãÌ¥ ú¨ND.Öôccc3®Üiî4~[û¹M'#ë~Ø~àkooåùá¨*¸÷€oýo×ÀCª) ®ÊŸ“¯Îá—0× ›“o_pb¥øîÂ{ÒÐbÛÊm…Œþï­è*¿^ÀÒrÅH_}ì}>t§Ýž[ 7ô· î8·@RâîRnûÚ4tÇ)Óø'´lT¢¬4Y…?ig I–䵺‡§ô`£þ»ÀGOkœ®¹ò|>ë¥c§€÷>û%çÙþõ8¸´­íV¨¯.>’ø¯ Ùkz¦ä~ЉÑåsõgîLÍäðö4ý¶ wž³ÀÛþ? ã¢ÏŒóßX‡°ò?„?„(ÜÝcÞŸ¿ïÐC¦ý-;áߦ˜íþ‰jcQñÛoÅÝ‹ºíòe*§åøÇ)ý]e?vÑôòD Ÿ§°!©\tü ¿X(=}·Ƕ—Ø~¿Úø\ðí>«oŠu|tëÛ8—ÑÖߣ4Þ…Ðdˆ'}¡!óhþÆ’÷übúqY'6þ2îÅ»ŒÄÖE¼""|DEˆŠ€.€‰X«@Y`*w«?´Ì"HÏUiDW¬*¸ÅWºíG³2НMrŠ­ ¾=t"T(¬ˆ‘jÛKõ.* Œ+*Ð$[I<2GPªàæSÏŠ®z&dP E_*ºV ®Â”A\ü´ØBLAaÊó6!ü† ’jß®lB !,X‚*©Aa`2EPE"Àdb¨°ˆˆ X $V,F Â,bH ¤YY=ÊC“žØàl: ÂÈ*ml’B‹$¢«5DÈUl*± šmª.’Jp3k«”Ctª­¦ š‚ `lB„´ 0Ð`UhUz…W]ˆ‰¨ªÝY$XаH""ªª"ªª"ªªªªªª¢*ªª¢*ªªªªª"ª«ªªªª¨Šªªª¨Šªªªªªªªªªªªªªªªªªªªªªˆªªªªªªªªªªªªªªªªªªªªªªªª¬bªªªªªªª¢*ª"ªªªªªªªªª"ªª¢*ªªª¢*ªª"ªª¢*ªªªª«ªªªªªªªªªªªªªˆ©$‘$’*ªªDŠˆ‘"ªª"ªªªªªªDˆŠª¨ŠªªªªªªˆªªªªˆªªªªªªªªªªªªªªÆ1Šˆªªª¬bªªªªªªªª"ª¢*ª"ªªªªI$I$Ub*ÅŠ (#òW(¨ XU`**°E 5Íö ÚÞÑU«¦¦ú R‚åš—/lËrÌìÃ3‹!NË Ñ&÷ä˜ûþÉàm4€‰QY kZ$µ›@1-²P’Ina:ÌœÓbÐÕ ŠþU€‰·K:@CǼ(B%`zêž¹09tA ˆ€¡NAT‰ "qåkº]rU¬…a"©AOAÓbnÉ`EAšÐªÔ;¢Ó!Ö"(lô¸Ç‰`K‰”zŒÊ"0 gBRä!IJ‰€H‡"òAÎÅ ö hïj@v¥Ž »QdÅ`°Ð€ "¤† ²jì¶tÔÊAÙ3Ê4Øh@Ó”5BèÌ%Ü’HÓbÜ×ÜŸûÑTELɱ8I~{¹%*d!0¢"%$ }Ð$™›lSd:Ͳ*ˆB 2É ]êlnï¸ÈÍ÷3Ì,“áÁbí·li™™ BÀ¯Z ç’ù–SÌUož"È’H)L?²q)ZÁ4¾ ‚"ÍßÝD¾‘ÀPóªP:¼i77n"£[–¬*6DDÌU`€ŠÜ‚+—ˆ À!ÁUp&¢«ëŠ« ’„!I!ÁbˆÅPU‹Tbª¨ªªª(£*¢"*‚£‘DDEŒUX@X‰‘,¤l*µVÊHˆˆ‚ª ŒˆŒ`±DbŠ(*ÅŠ*1UTUUUQŒQAQˆÈ¢""ŠÆ*¬ «$‚À€¡³!d€j AdUŒ@ÈBË$TYdUXÀc$$`¢SÒÀ<¨*àªØâ*:®Àì]8šɪ x0`0@(P„AÀ€ # $ u„ cð¡*r¨Ñ¥%T¶JÈ­ÈámÑ$&àHBvÙUAEV°`¢Â$T`‰ww ÀE)J (A`¢E`Xª@  !€ˆED(¡ª$•HšŽ„Wò æ*;7€®ÐöÚº ä“ÃÀÃ&a†fÚèí <á!K0;¸ƒI&&Aœ S(w^ðìÌc¿ü„XC¸)!œ0ÀÖæQ“t$¤—fŠw‘ú†™;f@¼(™çGÃ3…a¨‚di”$ú{‚Åq(IäšÜv¯Ä@~éȘ‡)šI%“ŽÜC3Be',™Ñgt@0vŠ­Ì42 °™äJ»À 2MÍc’H9˜fk ¿ZÑÅ8¾5¶¥¥¶ØÔDI© A¨‹,J5”KÏ—¡©˜óB˜1Q°£°X,F e¢U,eƒb5[jô¹Îº.Z"ÚDµJ$ZƒE]Û8jé”¶Öˆœ¢¢ae™˜" b£?UW&ØËl¯MkM·*Ê”)™a€©k–‰šÃ2-`VØÕieE¡bᎭ´Ê­¥Œä\™(Q+u˜!-hÛ)eƒÕÄÉ•¶ˆµv.‡ô-’+‹BJ4­•¥²ÚV,¡¨™¶Ò•¥•Œ¤¢ÕR’ lFÒ¶ˆ €P´Ù+KEÆ"k&&"T™$“•!Œ+¡Ê2Ñ«(zu‡’3Ž œ€OAõc‚E ͘c·i¼e`qYÎ=g×þ{) @¢lÝÁj~ÿšn˜wÓW=?¼Sж—Õì·ÍdE§ÌÚªûžÏ>ØëÛ÷t¥l´LŠ´Ò;ªÌ'»ð¸v+›õºš²{³ÞНÖòªß^*¾ÏÔk{Í«Ì "8""å¾ß߆^" ¯ñCßý‚ <áU‚ éU‚*˜ÅAUùBˆ¨@P"¢ÅQ€òDF„êã ¿÷s ¯7áâ° fK†ã“ñ@sƒîn_}Ìýoð7''™ âÄUz ªî«é¾~ðRîþ¹j>·˜ü7éL´ÛOíèp£F³üñót÷ŠöêäÓA`êvm“dýp2@)ù!@cf™•¬åWz;î—rͧpà{&÷³:(¶ 󆿙ÁæŽÏewߣv»éÈ9¦Çý³·/<éÜÅÛõHÑ3k¡oíö¹LA‰•]™æ?G ªå÷ qüÇyÛÊA~ªùð$Ü`ê(:‰kŠ®W¾À"j ÐAÃô{Þn¿¸þ"*½ð ™HB $Š  ÄDˆ" D@@H"DB# ªD‚ "0E SÒ|ïÍRäùPÛ­ÿ>G„ž®Øúú ¨°Îö.± . ýD8ð‘5­ǘùœÅ-éðBæ{»÷üqŠ/—å}Þpûnæ76¼¶Žé|SâO»ü?o‘_Mû>Ëúsù¼ÛƒcŒ `Y‰)€†5'“ùƒ‚•Ué„‹›}ñ-gÚŸìVáﳎ»ôý[Õá£üÆNÑÜïåJ"&r0'cLIN8œ03y:ˆ _þ »9`aþŽÆŽB""""zýÏÓúºÌM` ú M« ¬ê ¬`¤D`DˆÃ=BÒñ}œ5»ªŽýe6"ÝÅCiwv67¿Ǩ¿¬hæ„XH}ÓþdŠ¢„ƒ"ÅQDXˆÁH‘X¢EŠŒTç€Äy‡Ÿ9ÔžøÒ("~ äkôLjáUÄ"UüÅ¿~†>wO[k²WÙdÎ<}"™2Ÿ[ÊüOÁ»þóàOíÚº';ìa’ÐcR¿¨Óèͬcy›“ AUyªÆ¼¶ŸˆNõ€a»­ “- p„NˆçTsOìSÅk¬ì·:ûÇR2Óëçó—^êý´¶‚‚ûÞü3A|ÑÙŸWÊ/-ík­ÚI%ÌZ9gÛü=ÿü÷ ¬™w ó~?ý0z`²Ä€vq4e¥U¨ñ%ÁÇ-švR}2÷¯¹~±Ê6ŠÍS]—*©*î#c¥Dä"kÀA„˜Áï ñ|ÈyA×ú‘Uï ‹,:DO´ÍN’ðö–/'êß'òXÙ!ðÅVTöäÄWØ›Ýq ñÜaÏYlf8Âqö»þƒÙÞ´}ž’’ï§òJêÿ׬‡J«Rï½r¢¬h:8+?ÁíDÛv¥žÃºkT¾ÇÙ䢪Œ”Kš»ÕýLa|êíüܶs0 w$>«UÆÅ_[1«-øážý‚ô*»aWl*GõàÒHT¨¤b I¶"9ÃU¸P?çï”@p¼Ö["U{çÌŠ¨«Â/È\ó¦¡*‡oTå_Iù`‚%óæõ\*?íüÙÿÒØ]í{…4˜Éþ~F¾Þ{Ì8emY¦Ç¼²7I<‡Üx zKÜÜàÌÔ>(û³™l¦†ŒÅ~gh\,­Iƒ?¾PªòEW_—ÿö7V,g¾Ôá›eãÃåìøþŸ{þoëúP8·ÝµÙ4Ï­»‚jþÒÁ¹|ðÂb ÆódÀFA„€ù´ãsº|ë¿Q4M˜,ûxq„Ónƨåúcõ5 ûl½†-Õs'ÈPg_@¯qf(¨p…áå{ÅPQ±;áOÊîz=á¶ ºLÛ§ñp¸Sh7!ë|V.&ЪLJ $QÒ6'ºäöð '½ýøñÌÝþÞ"éä@ï£{Äûw%»Ô Uµ2lµ³ëèbD80„yð«Ë`ˆˆºôuí—óÏäã÷xjZWéyÇaýoEwôà—t*¾ WÝ~åã½Çnj—B²P‰àêÀë¹â‰ößÇóÃ)Þ ¢›bÇŽ ¾ï½ûU¼?cpðW¿­z¦œøx@rUâ*°¡PV"íàËÔzº€ ³€¢¡EÖ¨QPŽ~x¸ìƒnGsŽ“‰_¡ÌïÂpq>'íù²þúƒïG>1Pe²ÁtDp˜•¤3Q0_ïkO†³ ð_ßAꣶ·É Õû³áù3ÉóÍ;Rà÷ ¯±ÿuÜ¢z°íÅWú=¸ ¨\ ¯Øz» Dðˆ‹Þ€"»À(´(¨Yf+tšA«ßþ™æ p9Wƒù{¯©—‹Í9©ò‡‡úx~ªãZd=ßyb× ÷"#k¢±© 5,Ó6ñˆ|n×ëÞÆÞ§‰e]FX JœR«PCÛÓÚïdeºç‹hxÔs„ë«øo)ê€ Q€E÷j 9DXERo5ŸÑù]¨ªýíçª{€ÊçüS¯ôÿÍåþgð€3oðRªì~žžíòv»x_}Ü{OêÁãáFÔKZoX¨ü"IŒÌd¶eÇE㊋FÃð|ò»ìX€¬`ˆ#2 b0 `ôD`<ˆˆzòžú_'s"} ¿QÒÔúÇõEÁÒ{[4Ýio?úÌVqz~©ºœê^ÓDzMÀ£A¦LAï>þÄ`:¡ÀÚzáø÷ÀB¥•ÄÀsb$20]Û‰¥‰ ޶‚ÁÓ©ofé'ò}Zö˜é¨¿~"Ǽåv7Ì@\ý'é @Ðb†Ë,ˆ‰` H—UI@HÏ7Õ=$=óçuø}ÅãY\‘†¨§ItNˆ¬Q…hBÍ€ªÀÝt^h  ¨¤UHª»”"RŠ,<¿b(†-°D0(cÉ«Ñk[”'uíÃÒÀkŠ‚¾ŒUuû?#-~…“VñGe''Øû²¸õÛvU‚ƒß;ÏѪÒë}(4Ÿwù,Ç5PÎ9&JÕò¦ÎظF,8¼æ±”™1àÌÝ×ý]OCAÍ¢r`íÈì²ê$A,÷[ÖÞ]äßB"]¹‘Œ` 0#aH‰Hˆ)E" ¤dHˆÄŒ‰‘ŒR2$DbFDˆŒHÈ‘‰"1##F$X($N´…ˆˆ– ‚f“ ŠDCÏô¸çM¿ñþ$¦(ŸöïègÂ'Æ¥H°PR÷iÏèÿ;ð¿“°¼y΢Îs´;¾ï¥ÿ‚“÷¨ ªZªª¡*¨@m l%FÑ@¶À-¡m’[BÚIP*[BÛ$-¤¶…¶Im„¶¶…¶´-¡%´¨²Œµ[H[d¶È[d¶É-¥IP¶…¶Kl’Û%¶J–Ò¤–ЖÙ- [d¶Ém„¶…´ m …I-¡m•‘HT’µ¨-d­`°-°-¤-¡m!m hÑ-´-°…¶%d+XV²BÚÒ[a-¡m$­aZÂ[BÚBÚ©%¶Im h[H[@¶¶¶m¨I$©[@Ðm%je`[E’ÚжÈ[I l Ôm [B¤­J„¶¶’BÛ mm„•¬+Y-°–Ù%´m l h$ˆ…ªm"<”G³ïÄ@x£0CºÿÏMr* ðÃÉó#Â>â¿ÖÀÜM3t² ²ÀFÚI$_šF‹ñú¿³†k{_Wãõ"Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(ÂHI¨ ,*¶\cϹ)@îãHý³hqϰ¹:Cñî"ÎlÔfobÉÈt ýÈê }«€Q=%ñSu|±På7¥È#aöÆ3õ¿..¥¤ˆoAô²ö÷”!jî±ÚŸ UqPPmQ@Þ÷ZçïŽÿíOCžûïµ³˜ºÅªI}4I믱°Wú;ýcÿü”ä02ö'Y°)G|X(ªAKàªù" ½ßØT`*@ aEC]߀÷@ 0QD¼Ubˆ”‚¤U€ˆ¯ qCÆ ½æpXg“”ËdH)ÂÜÀsò/\WC€*»*›‘­@éAlgÄý|¢"‰d@EŠ(»¢ ®ÐšAóî¹£[xU}FñÜK†(«ÓO%|'¾ü‘¶‡ö¿óxŸþw%Iù˜¾ÅµOcm¢5*Š–Z´¥R´¨ÆÔ= 2–•FÕiXÁV^Ùl‡ðþ„¸¼Ê¬KQ*‘Ì_¼¨Uî?±¸©*ŒxpN–}ݾÂÏ#ùÙ²œæÜ{ ÷(h·Ã>Î3¢eÄ9T$×q:ÿ<3‡¶MÙV°r’1 DÅš¼}P$mÒ&0½`3ÎJ#_©J°SD‘";²%d—>Et»F¨.a|V/w04›ÞC<ÆÇ¹t°`7ޏÀ, @ÕŽ {@¸?;õØ6¹üì^—WFÃõvÇ? cI;Ù`Û]üÎ ÜzéÌ8Üî÷j³ýäq MÜHG¥g(D«£LŒ_NsäOêÿÊwýCïñƵßs­UÚ3þ_íS_¿¿ào¥Åýß§ÜÚÃ!õ„ç³@Q| íQÑnŸúÙ¸_Òþãïé&ý_ÖþßíþÊë´Ò_o yÕw0MÌ!ƒÞa ŽÑÆÔNø";úÓ”ègïr#ôbŠc’&+Ò?wök9ÎsYÂsœá=ÜÝ}Õ»»»»ÍÝÝÚÝÝ7wcwwy¸û°nîîÞî­ÝݽÝÙÝÝÞ±¸ÌèL:Ù'\žMFA;Zñg Ý×6Þ•G&«œ›Jd¬Êæß9<ØÊæmÆVåó”I‘1Nï1¢&⨘ØÌ~lXÒ3ƒ@Ð4 @Ð4$Âa0™ Š(Šªˆ Ž­ÍùYT!=@ðèI|à—úWËŸN)%q¾fôùB§ûg”ù1oÙøåé æXÎ(É iÙjÖôÒíES]¸vM718Žé† ˆ@Jll¬Ç)ÎS—œwy$žQ-Tì©:f‡rxˆ.& ¤S"aò„xÍæ[˜F¥Råv’ld“v™Ñ›rOo0l'x«ê/¼¬yî̪‡~‘‚ziªˆ©y™J]Э3â)¸9™TÉB¤‰ÕŒ‚ Dc€Pˆ dÇÀ-¯c_gסT?ÕÏ“ ÷[~+6c0–ÛRù#—HõßúócîF™V‹¡Q„`[ÂA‡Ø0. ‡³;¾èïHËé¢Ub··˜ýí#³Úæ¾O[k_ÛERÿÿQUñ4{O7s}Ҋј²7|ZÆÝÚ˜F&ñB˜KϽTHgâ~˜ø’­þ(v‰®+ÄrÄ‘"ù—uÚ,rP˜1ƒR²±•È,‚ð 8áˆ55ñædsfší–‹£¾úÈd¤0#m³ˆo‹ê³)ÓHFÁAÄSPÀq‹HOfƒüOLEPšEíÜ MЈ ¥Ä@@û&šðP¨wDCüPýàUaó¡J*ÃPüb‡â@;ž¨h \QË öÄ=~$£ˆ0Ψ ±NB/sˆ@TAe–Ú`YXªÂE€Ú[X¨Á[iiUX¢*ˆH¢ƒUj¶Q(*J±„„…”ò6Uô>Q߯[cJœ#]ïö^0;øqÝ Ð“ÿ;¸¥'žsð×Åã»OR{¼¨ˆ-aUt¾ú%¥Ö?Ã÷˜µÁUÞ=›Â6¾)­~ªï(w¥ÀUzíÓ÷¼s§>™ÝšjCû›dÃZ.÷Tð8› e¦ÅKðcšCö’ ÀIl•ªÈÀó„D ÒæVgÖóûV†zJÇÊ£11¶»“άÍsÖš6È!Ж@‘1‹Ótµ ÆŒì72zÙIz×bŒœ1¬rŒ«¹Î­%˜¾ú‰ÕŽ»Ú{2¥~!Fb2cm»Ò÷ÖÙ¥³duXOwx<¡F«gIÖÕï:XW:þò‹~IQÛpÊ Ïië®ôÒ³ž#'µMd»ÈÒp´'#ß)N‚;3dÙŒpñ¢¶»5¬¡ºxÞtq’Å%]&{wMi-m[]§.Ä5¶b žªÈèÎB‘â ;tyOíO÷×ÄÉà*´ì†ß†Ã³’Hß4ðkìë{zɧ0žóRЏÔUŠŠ°vÅ 8ˆÁÄaûž7}óÏ–±p¶ccxÎo/¸÷,l§Hæ0 zzÿ‚@„XÿW%gþŠ kóòr©=´º—%…å[GÀ}g }¢f–¸à(>oÜÀ=Pú?4¨+¢oïµ9É‘àÜÛ4ÈdpL£¬wo}îh®|ÏfpÂð4B±ŠîˆÈG"I“Ž©¹¥)t§˜ âPˆ^&$Ä€6m ®#ü>Ÿøž|Ô½úTìf›žŒ†µú¸~CŸ±eåãÆ‚ëõ¿fÌ__å¼Ý ÚÒƒüTê–¢‡~TØ/ñAU™$C2¤`OïhVðmÝ (³–ƒ`‡zBÕ&1WÔ4¤ùW¶ºš¯ÆKZÛýÕÅÄ4¯[”´0•‰¯ÚåþçèÉ“ -daJ¡F 1 A‰ `ÆûíKsÐ3d3o¾çhü>O_矗ÈêëçGtw1OïDSeƒ¯0|™2^?Æ¿RHC^;¼ÐˆŠ§&šÍøý¿áGƒg‚Z…Ý>…˜•ŒQ*…ÿݦݦ6Ô1IÛ~jùW‘W_×É9N’äD>»¢3•M/[•·6lÖõõ °€¸çñ¿KÁȈ€!úcŒA ¶Ee‘ŠþáíiKýS/©ád?Òžªg›óµ?A^vt‹üôä½—}txü±Ï¶z:áÇ~-©ˆö——„â…ïÕ#ÂI+٣٫ì[,ô.ÖÍTvóSæ]TQïŽy"¬,öè/RìÌZ2¢:EQZŒÐwlrdÏŽEg">S>ôSëÄËrÖ‰žªfåÈéýâáÄ¥óã—uå ’¶xÈ!¢¦V:Žþ<{ŽâNè¨r=zñêꓼÜý/ãêö/â*ó‘µµëˆq~8*¿ÍÝò¸[û?de ýx«È5ôUU%U„EBþÿ3»ƒÙC•tã˽×7±Æ-ݨ« œê«ç;§k,TT‚8Œ)Gs_P—Ÿ³I *¸=óð ¶m×?kpXõ6T‰äÓ´ÀÀ1‘*P,#(Ùµ‹+ÛØÐ ¯¤EV“c1}¯UȹAÞ¼Ï>€~ DÔ«¤Ý 6«"€ZgßµœO©ld7œó4oæžF‹ÔôOÁðФÙR}†°W×áa´»Ù$Ür`í 8‹"D@ÈßWyy$¼•Hs`S±òÇ(Ý¡÷üÀ÷XÑUÓïaÔñ –<ÙÉv 2´{ÍZÖª¢À D¡ü M±YÉÏ{A<^/"ë¾Q¾¥ù·rΑª¡”xu›ŸÁ+mn:…¬D°¨‰ÚvН×ìÔñΓÊÞo¨ñÜwBç³”ˆ‡o¬ær9Œ<îñžRA6•f{/ix\ª)w.3¨3t 8êÁam't¹‡k¢I&la™0rl2‘Þ >J÷æ¶vÞh™$’äÁ#c ˆ€HI2BL†r2AÄ&hÐ\Ó -Èi¦Ú"jZ1‰Po6TD‰¼óæú3c‰TJI§§¤PÅ2 ©¨Œ¶²4†¬–q>BT„Z½¬$ˆ«kYÀªÚÖ3„ŽÔ»ß–HI¯VsÉPQètèaDÒÚÿ[vŠ,´Ø’I°qa P7Ê"ˆk Œ`nJɠѬ†f*¤¶„Òˆ<3GÛ($qúkÚd[À5ª †ù6¶¨‘_š$tШw¡[»ˆ g¾gtHB>6SC$É/›ùÞÄUUF0RáAoÕHæz>±jÄ!ïìcL÷ .±bÖÉŽQCéDZª4;4hC¼žDE„XBeBFiqäEœDyFé©[NAðÛé¶éî"[†ÅûÚó‰àO’#ÎÍ.©ASBăwÉø ‚NDü-Jtú'7à™ gúCâöÊ"Ûo\ßfzÖ7h™HmW+%ÝÙQ1¥ªÉDu"D6Wl<`¶I‚2'º H7’gPÍÊèÐT”ü ¶ö_~á=àªä ^ÝGˆãŠIé¾Éôxј}_eØlN•+F°(ˆÈ)¤+$©•DÞÐø˜R@¤I$dÚ"À@€² cY‰nØ|:龺sØÁ7úK¼P¶<½z˜v ¤„ Ÿ™»`Ä\{þÞˆž& B€Í¸‡Äß  eÎ8̆6ÆàJ€­á]Í£…™›çë`kŽ}!œˆ9æÎ±$$Ëè«Bƒ#»‰»áÄLŸ™Í ÏoAUÝQ6…Vi^¸`„;sºÚç^íÕñ4×u²²Õâm‡T»ÂÏå@l|ìa€CÝó‘"2¦Ô¢ø/“&fkéèÙÛm° é®È @ . T*Xmh-‹Ê@ÙéÚ@äUL„ñ~ö÷¸ÐóØw"-«\6új[c¬==´=ÆÒH³„E(VÙÔXaÈU]n`^ø»údCÀð€´vçìógÎ+!"£.d銯n*¼Œ9˜ƒ,$~.²sñ÷¼ÕŸW'¾zŠÆÙµ*ÆŠ,™K²ûßÃôt €|I<ྱÑh/¦ÔGà¯Ë p–¢†&°½Ãš–)Œ&uxùAõB¡ å‰IЬTXJ a¯ž!êcaá7gž êu9‰íìfflŸO²Ïj–*Åœ0¨!µ¬ SŽJÑãÔž›"5alŸ:Ìz&£€|bˆ ¥Ú¯§C»L3hÔ„ˆõŸzxY”–€ƒlaÌö@,…A=P-é>™!•UxÎZC Ur ¬ËÌ+qçùÝþiî–z,¦%(²¡FBÁŸTrõíÃt3)ˆ)u…‡ÎðÎ_„ünÎ>à¤XI~µž~>¿ p-Ï¿Bÿ±Æ'½èuឦo*Ù×׿ïºVGåyu5æˆ6Bèæž`Ç^R£ “©©UÏàñ?žzyµ BB1NTÆ0º¿ˆä FBc‹ŽU bvh¸« ÏÜÀàŽlÕúý/:<8kéÀáÝ|ª©eëëÙ[ÚN“ ²„Ê™|ŠÄg2™ÈwÚOì?ÚKÇòöåÛÔ©ƒì„üB‚}ßwUûãð}úRI¸Ê__,Âè}r;|’·TU’OxñÍA“9á{›¯½ÂÛu^vãdÏwvÓ=ü|ºô»ÓÊàªäãùŸØüÙ—Wtýþe $öÄ‘“åû„ò<Íï‘éwúîºjì-wß¶}a±D„!ă$XÆ$¡èžv]B¼àá±m„Ê)üü@•^šL!ý•ýXÀêë,<¾_>ݾUmCwŒ˜FÁ:‚&È‘S¼y+‰ÈžMÍäøø²áì0¼nÿjýùC+Fø¢KÉ‚Õ#ÃÌ6‚¶€DM IA™ B¬ˆÁ- Œ @³VÕDD-UôI¬C%Rj Ì”„"úˆ‰º7áQ6nà£ÎŽa¯ŽãG¾$’^¼ûr® {a…‚‹,?`î‚'+¦NŸòw8šçÎçØfd£hV‘B`aúÆ¡yÔ:òwXUqe²{;)ýö6°½Q C¾¬A¨iC(êËI‰8aã¸ÔÀÂ_c¾u¿ïºu›UyÛ>Ñ£m+$ìÍÄËq[}ÿ~›0Ø¡˜° :ê!…tÏ×A„u¸š.þE›IH¬•›¢…¡@*²,üW v]IÈå¸e{ØÑUzζ¾Ì…KU‰ ê‹FGŠl昿'“ JÁÏRt'ëÿ#¾æy¬ð„èx*ÏØ ZÖ)VT]ÖSqÙy(ç“Æ/(ð6´ŸÃ%B=é$Jí:Ëñ(}D8Ä”@á7Ä4ŽãRDÐ}8¸$Ä=PÙÕÙM˜MùcºHª( dFc*²±¨Ê !P‘¨F,‚UAUû¥zË.H&Yw?ªà-$ ±ÄÙe«KSBöÂÙÝÂ“ÃÆ—!{T‘0Á/k"¡b1`Š£FH}€ˆTY )ð!àùÅÒÚ,û, amRbŒ–¦4„`Hœ†?`bn×iÇé¹jçEÄ%ʱvú8q÷"Ãöªvµ"!Û|pV3`˜êÎÀÈVCôtU+¥¶`¡ô>¬¾Ð&£ùúº„¤!áßeˆu`y•ÑäY,›z˜ïa­µkžL  Ÿ5bª· dà§²Ö¾ ÑL#pë ¬ó±üœTât3ìp™s—‚i£sZË«q/uÕÜÉuŒ†Îsnd3€hJƒ 7šÂ2Nãh?xÿa4¬=G2™C÷&ô,¥6AIÍ ƒ¯æ  Ñ€}ôÌV~!†ß›º`‚çßÒ cÖ‡­¼KQy¼ìX<ᘪÎÉÞq¸0Α ¤>3¡èܧ„(MÎÞTkAßA²æÉlù`UtXEÓ% 13Ϙ63Ú«•‰õøP@Ädl ZŸVóVÖä|qpÜEË>V \’Ÿ^–±‰œl› d^Ò@ÀªÀÆ™_Ï Qм]ÂÎw¨—ÆKMO=›tô¤UÇCÄä;ÝRÈI QX P ¨T hwÛ®íèx A°X’Hkñ1Æè{Ü»vOµ¸¥Øp&"¤7~l»lv`@ò‡6ŸyDâHÏHŽˆÀA*DcÄÂáŸét“fkGî”ìÔþWä˜?c"Ðé uÈô‚qöÝŽ¿‰ú—eì5ÓÍHâý÷Áâ`,`qsyJQƒÊ9Åme€cQ©ŠÓ;`"V1†pÑ)” Ø ;äꌄ’Š”b–Ì’ÑBSˆëŒã 0#Ë· s%ÛúÈ=—É4#¡×^Ò¥²Ñ1)ßûiwD³Â¸m¤Î9^Ž:Øç„?N»^#-áú‹¨ÉbTe”óZ8€þ}ó%6»Œ&äùþ³áØôæxáã`õ¾¤nï…ÀHA–oŒò "±ÎI&"!Š¡Jæ€ d¤OìœXÊ»GrØxGÌF©^8ÃÆÃ1 ñÙ­|ŠÅ²Dð¸¢\øôãc)ögnÓBˆy»&Ýv0›Šy]öXW&Øâ1ékRœI] yˆ«v.S¥Ø»ø˜qB=3oË£Röí³—„p:p™ÍÆw¤æÄHcâΕ҈L’X­'vâgãé3´Óž<Á ÷öG}Q„E`{ã :]¥ú lHëa­6êfïÃð÷óãºß‘åZ´èú¥À”ÅÆ7X=!©2]#<8Õòf¬%` HkGhõÕGjÓ0{Kñw^ÐyV/L°~<2Ëãår »LíÁ1âÙ MÜxã*êÅ(«]*ôóãê‹érø¾‚†ï1c¹/…ô¬õÇä‹‘ßÅYÆðö „À8¹›%©´ÁÈØ ÍÈÅMÈwÑýP4åÏÎ{ù|§ìÏcÈÄû©a1þ¢!ááÝÜN —0p¸(bW%ÁdPB‰RPÀ°YPªÑ(Ñ"—,¬*¤1 Û¨B5d-Õ›à*  Ixð¨·Ó ^ûÆ93†E˜ýý뻪|ôSŽσf!óØåyŽÑÚ²¶{+¤ñVüŸ;7g®šöC„_úþ|¯¸ER `¬ER$ŠOË ÿäêÚ|™šq¸ñޝ¬ævÃ?“ ¡|ÛZm²½½e.ÑøÚ@¼…îîÜ` n¦Æ>ëþ]w ãä4ì+ÅJ–ªjÈZ ‚jÎêLé@ÈŽEû6Õ! •EGJÈÓȤ#ù1(b @`’EN*!æXA“‹¸Iì$ oˆwþÑsúüau.„al ¦ t¥c´ÆqûôiA¾!ÅÔ>øÞ3AFDžIN-VdvI0ÂÃéwÏ‘Ÿ#›ÃËù/¾ß§OžM;Á£ÈCé Û§Œ±"YD(’…ïƒ!"…OågdfѵYŪJr1[µbãˆçË#µ l€b’Dts¦ü·õFtï·Ü¬Æ†fΨ¦Zc³>û4_$uÓŽ #ðkÚ=¸äœÇ’zIb×~8$’DDCtáiÒɆ[Ï,øôhSU›pgm§Ø¢ÆT^Dθ^Î$ÏvB”±íïöpå[ÎD§5'ƒôYñîñ_(µ|8ÌÌÌ¢ã^׃‰Ù‡c¨Pð•üŽó²¯ã±!ÌF:Ô¢YÆ :+jó4¤3#Xéš"‚ŠšÙ¨=•YäìfÙa*fêKSå#G€œv›`ð \¤ê°°øÙ;¾Ÿ‡®B!]†62”LÈ€š‘Ê w‡(’Õ‘ˆª °¬¤iKhO„B¤óÂi³]¯u4hêÎó¢©A‡‡·JDh6¨­ ¨™Ðœ$H ”‘_Á¸ÍW8“¹õSRYiè*´»ÔDÓðn è¢)7ƒ<å<€ÀäÅEX°;À4À Â`oßpP°e‚Ë-úbtë?ÐOÅÓ¯`¦ð,m=3ˆ«°êž)ñÈøß¼çî"wnû—X|“Ã+4ºHË\±+¢ÅÕWÉs(\“vHOZt„ù0™=£¸>Š¡Y°£ç’ôÉÎAw.SÕßi<<;Æï£¿q´ÚÇnä#ªxÁ„‘PL‡<÷w³v¾·'¶ý1‡Ã!ßjQ¨…J-Eãü/3âN@h¼-òù„Pn¿º\¶¸æÛ@I%Ö,YjIh•«üòr‰ud!$B˜QÔ³TÚ}<RÅàlÜv}V]7ˆTÎ¥€`ªÂÂddÄc„EDÄÀª*G“Kºe»º>yª˜ 0P½nÒ£¤JÚ°€)PÂò™‡Þ™ìã ù׸G¡=,]7¬5Á^Tí?rOI»ÀUhÖZ{§Æ&±úÏè1”Ï_ácïñ[»´¯”:¹› tH²* ÁUˆÈ®±Ç7“ŸÌ¿•ØôކÎY«Œc$‡3‹N`äò?½ÄÛã: qÓ ö½¢,ˆÂ??Ë<_ubx%LDO /ËIA DH¤ƒÄQ㤠F;b Šâûœ ¡$ÞDÕÌ­âfpI5™BœsÐN!£FÄÿƒ½ «'c6®ýWRÀÜÜôéÒC¢¼n!Ó˜"£1•P:’IlEcP––U––•ΡMmΕÛzê*à&ß8W(¸97”ÈÝ ÖÿÊ+mKâ%nÜî!˜ÀÚ@œè†6ÆÉùú½}ùØn vV.°Ì‚*{ I9¹¡pT%r5«Æ2èû“àƒ„dx1:gc¨MQ41öÓáòª [c‚0¯g<w#EÈ™›é¥s„.¹NÈ€Ha lѼXÁdWpdB¸¥”Z«Îç¯åsx¶ˆóµÛñ¹,á§Œ§ðÀ蹯3G9!M"µ¤¢ÆÏ4Èe— ³ÞeÇq ßð×3ÛRwg¡l…Uˆâ G'¬wd½ºåœ0ßHp¯Wİ€â¶3¡)€Yž[=°“s!°ŽšqˆÿV3ãÎkw]êCé9IÙbMÊY"‚’ ŠŠ(µ) ’,"ÅiZŠ™YËäÔÛ‘ÕR"†&FÐø„Œ`æîWϸ¸>j;5â~>Ÿ¹gJè\w|Æí¡9ìËRúhž0ç Ó¯M„DºNÚÑAI$ŠI$Q¶Ð Æ@ôC.:û(úe…FÒüДLRVX&Uh¸ávvfï1?$HcFQDCö!‚ˆo©"Œ½”¹?Âòµw#ºÓréb20DDH›ÔW ‚ ¥â³£ÓÄþt6ïMö¥Û¹ðåµ³à™xÛkA´_‡þ¯ä³ìã‚q©{áWAm*£!Ù¢«P**{Fù"•AeŒAd¨ÐÀÖY»1$W6³•• ­FÀ4$•“H‰H(MYH¢‚&ÌÔ=ú|¹3pk+' *HÔ̇¾e½}ú‘wŽ. ¼f! ˆ¨Cb<Ò`’ÒZP`ˆ lµ’VaE`¡%¢ÕU˜‰A$TªL]÷BL "¡x*µ”Z²Ÿ÷·ÙÌɸkZ×àIˆ}ôýF­iö•ìvnÊBé&ñ¿Ê÷¦Œ„ê”{+Êáz\ºÓkjÞ‡‡ÞC~boÖˆªÒ—¶~R^‡'ziá>ïè~e¾>\ÁÀB¼ÇïøÁ§mQR°*¶x¼ýâήNsAáßäLâxº ^@׋š¤ÁŠ¿½¨vOÒƒQc€ Ä#—Œ `[é$Oa"½O +a¨¥“•·ÂrÈe˜wîoçu ]q”œ"9…˜.ädÒEr‰îZ)êã›d!“kçÑDó@ØÌÁ}b¤ƒgÙAÉ·¯‰Ÿ\þÓÿo·IÅÇ Y`@N( 0ˆÁpV÷k¤KpCÖL•Iª;ržW"ãcû'ÂPñ[Þë˜ka’;Ð-ï“?4讌?Ï ®yØ'QøË;M4[(<`Q¤§^³B9¯Í×öì\€¢T(UZªh ¯ÈcIu4ë5Û$—3CöÍS¼ T˜¼`DIŒ” 6œ=_zÿê˜Þ*Égãüü»ÃFb@vÙAUݱtN$ýΧäà]ÒŠ¸r%ÐD`i$ñÒÄ`4„݆†‘d i„„Ó7h…¶V+nóç6EwI*³ðùÔoÓ—¸HX)þÕ“ì ƒûòI#õC¾Å 6—ô´­lI!÷ÿ¿K|ÁM'a׆¼£\¼U{{Æñ„ h¥3éjÓuÊÄAKÖaUL%E’SI›0 ¹÷nüZ.g£ÆÀõÄŸ†Á@ÔaÙ,;¬èÌS£Y,²ŒFå†!)DÁ$§ÖÓWmÝùÊi©q~JжףU!ðX‹·.©]Ž"Œ„;~üM±»t¥¨ýé;¥¢ÿ wЋh*» ¨à@ÝÖ¶e;Låž;h:z@z€äDðA@$W(ˆ'³u¬*¹Ù¬YÉdZ6|ä€iˆ†´RÑ*|X<¬‰•‘â¡päY~;‘ècnA)….*ãýéH<£ù ;!Õ~ÙÕ°ïí»gp øÿC§,Ã8E¦šÍÈIq5Ð V™Ýì.iÀÔÐPâék0ßÞ,Fˆvþ{˜ªƒù¥« !ˆ5žô´#xÙ^áU‰×§X@ÃJª/Š Hª² !"BB0ƒx ÕÅï5¢ÊªúK¿ú¼.÷‹ö?«ñ7ÿ÷®ßXÍlRËé·a½³Íç"«^# ¤ÂäyÇ6Njôh]ŽH`L œG°YÒ”PEX;Ð+)öŒ‘Ac¨ÉCîÐ5”A€’T%jTvŸ—…CŽw÷ÿä?/—äòN©¯é´úñ¡3‹Å†KÀ aý Ù¸j}˜¨Ø”ø™@Us¦Ò ­‰óò¶Órý?AJb49(ÄëËþ—u…ïþò­îú·0q1¨úà<ÆMW*€dÇVH9ʼC6¬,ßÊÿ·­ëEâ|ìb÷‘dð’+"$‹"22P ,"É„R(Š‘d‘T„Y,,X@RÁV(H ,bÁEa€¤QAAdXE!€°QTI’)‚È N™ Ú‚ª"y=;vŸ>OúAg$±§ªWK!è üiUAkQ~ètsh› ƒ Å‚œ¤Ê,MfbX Êþƒâ!,€4†üsSa2õÿ¦ñ ±n×&Š´ìOõßüà´g#¯·eY/I…Ft÷$ÖL{‘`ªI‚¤HFdŒÉ~¶âzBFj«!‰ýXê߈ÏW&ÿ«ppÞCÕyüþáâz"za!Žg3”ÕKœš@Í ‚í!bž±¹ÃÁCq!€Ì¬JWpnظ]?‘º9P¼ÁžHñ¤ @Ѩ ©Û‘pDDG÷k75ÓÈó2(õ—zËßïbëu¼²|ª<:™t×ÌŸï¶ì³à-7ø¯ƒfŸY¿‹Ýoí[ëðÜ8-}¬;—ó|ׄMW-˜x¹&º¸)¼aêo[{­‡©Þõ÷;¹Ùeì>kµýµÑà}éþ¾ÜÆ“µ ëã2•ZŠFfM ÷ÓùÁ hâ‡Úy$2nlF4¦Ä__”,)©ÔޤÂkHs¨4ÅCn•MÂÆ{ëýãÑÙå\ø»éþ°É-óòo9ÈìE`Š‹=Œ£-,äþ/öݽ½O@¾Ïí;_ìþ¯^Ý2¤Äð¶¶×»´EöC$<`{&pÞ^„à`Á»„jp«kG²šã¿°°ždf(dæ÷؉äã1e’‰Ñ?½§oknª¨%WTÓ-ÇÊl~F¤ zO=…@Ä6Ë`Vµ'T1‚,@©+ ¤çI³ì*$ 錣•ã@sÀ$6 *YŠ+ò¡Ê"ªX!EIx CblÅ,bˆ @`3wºN! G”¬“®ÁŒw rÜ ¦ªmoå:LqjݤliSRœp§RùÙÈÞÒÇjE„båbK:æC(•#k©r ·Ú‚¹þ`ÛÒã¿0‡Ê,räÑíMt UÈqÍ‹rÁULj]#¼ä?+ìÜzz,ÄòHû Ä^´3 /ßåÒñ3ÜÔ»»¯ÌA÷ÀåÀ\9þ'îó£æÇß[FÍ‘}±ä"‘ 2,"@‹Aö›&˜PAc÷Ò¬Ë*°F+ P)«'çvø²'yJSb£Z~;:¦ì%|ê~W°ùšd‹!XíHy¼Ç”BIßý}e´šE3L=gƒãýr*¸>]þßà{/RÕü)íæá ªÍYÆÝ—¬XŽíV#Ê” %dTdV"0DU‡¡ë’±dâIúGšzGá}Ö,ÄžÓ& 1@P¿Ñ°ÒH³p‚ ™Ök&âZК-çHä6 ——™³ ¶*Ýñp24¾P“´"ª°‚€I*¯µj :ƒ~ˆ3¤£hš¡G•õ0ˆƒ úDuþâÿH¤D w“ÜžsX‡÷F%`Iê=>cÔß±÷ü!Äê çLJ>óÝõV§gÛ@È$98ÕØ/G})ƒýw£¼$„ø}>ÍÍ„›"ª–VÀ^ãà>#ØO€’E ÷O _ºj«e³Cþø*»^¿\˜°™Ãß`7˜øï>3Rª‚p!¨vÜÌ©4È‹»Ø…´U˜±ß‡Ò,B jº/êB– ”õ@D6@øUq‹PndQ0¦DBÆLÈ Mä¶œö3“˜u”DGõiAÛ H5ïFÅ…WÚx]ìì1DdIļCÒNSlšv«’Ú£Hºw,—!Ø‚«Ú¨ Ð \~½ëå!$ù°wà}¶¦ìƒÇ•R4•ø†™;Ø{V²I"Á&o¶)ºLÀ~.‡™’ v‰Åœ+3ç›9.Jrs{Wz« QˆÕ^tÉ»tç;™“íêèy6Ohgxbí4ÚÜYLªÜ,þ›ƒ,H¡ÑŸ%¤T{¶ ’`õZŠbOÅEQT†Óy›Û †ÒB*ˆw¿Š ƒØÝ&ì9û<–ÛkVç†Éæ,žÏx{ˆô½€{ÃX* D€Ád’Dd‚¬"‚ň‚ÀP"* ¤Œ ( ˜VÒ@¨ $‚Eƒ 4 ‰V"V "¢‚Á`ƒ« ôBI# PX( *€FAb‘‹ƒ+Ä$BH …´ù‚ˆIÖzD× {‚×2²‘Uv¾Šõ²\8ÎÄ™“ø\—²ƒ°Öž¯ÄHE†½~ÔäñK+QcÎ’ ¾HCda›$R8ÁƒB‚Ì``I$`T‹XJË… A€ÆV„Ä b0a2 ˆ¢™aQÄ T˜ÊU¾E•‡ÇçÎÃ.À`Ë¢|GãÐæt³L¸XfPÁ Jú;aZ)y£Â· ƒ\ÀzC…¶>‰°p€Ê˜E§Š£cm mI"i½M£Ò+•U܉"¡ð`øapqrIŒ„U ƒ)6—ÛøX/A] úË9ˆd»$¿,G÷&õÞxÏ8Îh’#-›“i‚x’w,T¥}òUUdΊò# «ìƒHäs{o¿TtH”J5¤vBiu~®ÁÚÀC(݈â0Ú­òŒg´‹ Iã¤* ’I.‹á#ÇÀâã”Ô€ð!´a‘íñ­ÅùÝyšâ¨M&'x ¦"s'|pMÅÞxÙî6¡I¡¶ ÛE E¡E•M®¡´Lj´À6FFK Æ0‚ {áþÏŸº‚2™‘ ª‰hVx©ˆ‡ƒyˆÎ1ÄqØ\–·ÙËZÙ.T-ê²wŸ€ƒeÔœ_ŽÛìqÀçó]ï‚b¦HFu¥CDü›QÕ#$šcô<ý:o®û)l·ˆ:<­a;v·æÉ«ÔñΡ›G<(;9çÄí$+ÙùßQìy÷nŠf›Ý>¤óôíä‘pBå»ß…y®ÒR u Ç·¦#0x@Ï…âM&ºvŸågS !•&x%ò&ŸBËK’š³|ÀæÖëAü#®-Ÿ  _úô¯SĦb‹0^ä*‚Ã΄®sîÌfÒŸû|éÑü?)W ¯qÚèҒ霶§Vláû^ó8.ʆø9×׊­}xæC48o7œ‘(‚B@@ד™{è@"ÐtL‚ÂìñŠ­6û._“æñá½–FÚ>Ã@a«v%ž»Ç:àëÉ]ûz¶\±ã6=EŠIˆï¦dB-L亲˜}~Q+sú~&!³¡jƒçBÍÚ.“‚Òs_1(¿ ½_ÇÞ{ïÇù¾ï “’‘^p*µžÁ(Ï}HKÑëYAVâ#P’J2[,q“äMÙÂXÝ·ÈT…I¤£ ª¹m„ˆµ VÑBéJš@ÒAˆŠVM˜l“\ZŒ` F$F"躥s2‰has !TE“d†É–€¦ûCVÉ$ŠkE—‚«D/{µjý2‹¢B†{ &±.·ö‹¸þ\3ö‹J'‘ 5ª‰ýº‘2ßËD(_€ {/R)*P}$A|Ãý±òã ŸfîÏï¶³m’ëÇ}Ò+ I$‹$mûÍê½jÌã·3`ü5kp%MŒ>öb«I¤ ­0&B«×lW÷q<ÄÏi}ÑN^'íÐm³©‹­ggéÞ›mM#ýÇ¢€žOE¤X¥´¥/3Œ›¡ÄOyÖ÷s»EWÛ-ÚŽîr³âåà>Áõn95pÙêÂ* Ê,!Ò(¨˜@ÖYÄ, ¿Ë„ qù? 1Ý$ÞlµšP¢¢M¹Ÿ&[Ì&d"õ™f8 t¿¯ìþ㚃ÙÀoÀz“ºhÞˆöÈQX±JQ Ù„¤¨Oãë3X¨Ãií¾¯ÔOá¢Ñ``–q–[—>–7Y Ë¡ ™,¢I=\a›Òqw¤ÂðëD­¶ÛÈn Í“J”Ma.\ØWN„4a”ˆ6«2¬T„%ŒCíŠ. ŒK…Õ¡PNÀ‡8ð ÂFEâ;=’ŸvAÕœ¼9Öž.Yö‚ˆ: ¯W ¸*¾ãgCp ÎÄßoÖ‡U´QW#»÷oµ¥4ÞuÕ¨.­Ò L¸d‡VB Ç"&žaÀÞ×ÐÐñÆ)“1øI¥!FGÒÅ‹uHnÚhl,°Ý¬²¥2‰ Æ ‰AXªé§åÌÄZ/ñÿ '`¨°"áÆKÜE= °wœÔ!ð€)D9u¾CjÜ΃v!ëÖåĆc!÷P·ó¡ (7ΤS¸,SÖÁ,@Õél™Q©Ê …’2Tì ©}q8EŒ]”î ÔÕóÝøÐ÷ÁCbÑE+dEF¶ ÷U ¸ˆ‘f"«ZVO²‚!Jø•kRiõÒuM IÇg·,óÍ Ò •;ß©M:GàÁz¢ f *2·¸–$‚E$M2Š’ ÅYÆK”{vÊÈ6jÜTÛ–Ñ$¡Éh€™"f"@´"™JŒÄGÞzâëpôFÕ#„†Ñߢ—Dº^QÎh×e÷–¢è;à¤7€ à¡ÙŽ™u‰Î&º·êíí`ˆu[&·Àñ€Ó?ka„OD•U ?ÆcÊ%¸Ö„:uvXÂ`Jo2CÌ$'vÆb(õC}‹²i9ŠD„66x™Ä‘RBBBôÕFT\’ ÒEÉ:Ø8èªí±v¬^eõSøš/ó?ÎPÅ-A/ɵ+ïËŽßg ‹ "pÎ;R&Yý.MÀ­¥Â¦Ó 4ô’iC¸i/‘oOc2WŰùQ‰›FjfÖdÌ6xš[©@l‘’Ó#ì¼óýßðz¯©ü_×ÖàÚöyüáÝ]p>¶åq6{Iö€•˜£XÙQ óÐ\±–ç«#$¡!‚³z'5`Ĥ5¥G ‰¥Ÿ¡TÆR¶‰cü“áH \ÊP@‡ ¥Ûs~rÑ0¨ŸI™˜<ùO­“¢d‡8Ì/ù2èÊþ¾½"hOU9îÕÝ«ûÌ30 {cȸۑ:&NÖÁ™Öí{ŽöÙŒ.7IcÖ×§<>F˜rHOü—t-¦¨¾¸R^Ð~׿®K±âí† +_àÆ¹‘~ú-"tUà*çc0 2`l¹Ü€ÐÿÄß OÇIÁ=s¥™'N‚,)ÿ/©×ÞT¼SÚã€K|w k34¥LÖ²Ýýãòk·ña‰ù3[̠ıûù8S¸±vK-mGkEe¥ h"¬ÓÀ8‘€¤€A`‘àùP‰G&ø*·”H€@ÒØWt÷ëÛbá èNäœÙÍS«?0bšÝðBî ;zô7£WåxàJ{8~ø=UŽó/$¤É<ý2n¿ÆÀ U!¶‡;q©4¼(|öv°£æµ"y’¬X‚ ÈQ1”POP/Ýå§&IÈþŒ‹‰×®Ìëµ=€}‹±¨öCcv"Š^ÐÛè‚‘j‰"Â=¢¯ÄóU³"Hl‰¬Ìl)Œ1U]õ“"šC‹†ˆ2ÙÈídãr”ý~X\Ûšr­ˆZ?=2QTöú^÷½ªxÞÛ *ÃAĉbn›¦²ÖÚ˵‰ áúi¦oÑÅ T¨†P±*]²…h0MpepéeU—ÈÔÍ@ +üHXëÚj §Š0å S­žm’NC¡ ²ãÀ”†zR¶ºKš~óqrÊlIûåUwP bª°¿|u½mY¶XÒ_K‰b”,vÄÀŽÓyú¶è”Ÿ§îì¾qSÏ“`†½”ÕùÓFÉ¿J'HÊ@´xM ëîÎäŸ)ÍO˜H¥¢øV[зדLž) 0ú¯Fiœy3ܤèД[¼±hwð ‡kdDØ7@¨2QCJÆ‘F…„‰šP oêNãÄä ÈÏAQ ß'4zg¦iŒÄRRt á#…Q1ä`|:ÑÏÌi D´·é·ÞÉÐ[DV*sã)82Àñ$üâOõ|.åò€^äbõŽM|ܾB¯ýßLŸr›`j2ùŒÎ&Ó ÀqÓãTE}Ü&~§< ƒÑ)‚ ¥¬¡úCPbH ¡Š¯l**Œ  ¯ÏÜÐiܲÚÁXÍÂŦ)$’‰Rã+˜f&%C#ø¡© tW Ñ‚\Mœ•ÐKŽ™$Ò‡ä8‰›E¡ª¡ÝBƒ”ÿ¹¢­0;© &f`ü÷†‚t-àR+ÙcJ¤þ±h&Pã˜[&‘“J Û§éjf¶^{I €±Rªu8˜<8ƒ´‹ônk—,\¶Úl—1ÁŽÂKJ’2œÓ33fÛæ˜hÐÜh&/™ÄÑ­“A•Ct0T•6ÆbcI* q¦ßv†&DÚ<¡¥ ¥`¦I‡%˜Z „U ívLMZ®’I$ÖªÊÌ×áá¿íîqH­"ºPy~ޤ Dó$¼ËÑÆgæ·—÷96OÎoZãz¿¯n†¶å²øôÐÊ¿QêGé:j¯ öé$G×a3ß;&$ `LíBŽèe¼ÖÔí[…(«¨ZFZÃf¿Ž·Tªüúë!B¡Bu:vhØÛN?õ†b¦+:«ÚÀ # ÉU¤ZœÚ2Mü>‡½un¿£Õâœlx[œ0?Ò¬ÚI I%pyÕ×Iaoš¨$>ñ›Ô`ëÓ=D¸ªÅL˜(@ QæNé6Œi:ІJ~Vt@qô4ËP¡‘GXÄ€ãr ?XT!½ë™<ÈãS™˜\u Äù!P„›´,E%`›’Ȱ±‚nÃSåh²… äÖ7„ÁŒ"Ö°FÍ› /zI­’6Úf—íåÑ$‘Ò³&̘&‚ÁTb¬b…H !tW ɦ`†M¬Cm©¡$Ùš`YÈ¥¢˜Çg EÕ„†ˆ`„eüÍóxj†dÌ(ƒôL§ «ª¬Sc6‚Å&YiÑVL¤ Í»†Ó / ó€ÔŠ˜¢2Xk¡`O€B2NËÒXH¤ï°(@Qd`z? J–ÍC=ôšŒä˜É™Å+pØž‰Ô÷Q |ÅV)VÒn·M”€Y9„<á‹Ã‘|n-\HŽ ˜í­¬¬´¤$XZ#²°z<ŸHòÞ]Nqñ? ôÅÀ×fùú-!yý›æP s2(/Rð@yÀRÑP*’‰ @J"\ˆ¥á"·ˆž¨¥@´$E#!! •‚”IZ• $Gf…&X2+$œ4,$ ÂQB§ËŒ/Á»ø<¸â½eGÌ™… ¥ô¦±Ñ:(yi^Øæ10´ˆ{XÒ<ÔÊØ"1/,Q˜¶ Y-#£” $‚움eéY¹R€—Zh '®"Wx×ñ|ä;Oñ›¯Ç~îÛIæYਊ*ƒdï TF T•ac*A²R "¸A‡(>‹ ƒØØO˜"<Ú·7Zn_xŠOæ@)íYmñÊ'®tk&úb¶»[ÁC0ÖIáÌíèšž¶ï0²2EI p£±Í¾mÛ¤3/ÓÞ£~bxÀñ ;CÿïÓcOq¯‚^ùT¸ßZ"½v ã°Ãॕ˜[›ëZ(…¦Q;`¹„J† ˜;L3R†¡„&+I$˜ã Y‚ÕÃí2`fÞå4å’‹ Ý4È"P¶B–ÄŠ"¢ F¥´±¨°,!D`5"Ê‚"Ñ…¥¨ZI$¡i$“)˜ÜqÈ#!™J\ÀRˆ²U`X2¡c„)*Ic˜Q…Ã1‚2Hƒa‚«¤ÉZ2õRjECF@Š¥ÑjÒ,$™Q E(Ø£I^š¸4/Qt«ì2R™²Æ¡%;ùY`¦ôQI½¢ÊÑ *­Z’Id&é•BI1R´VVT’I+ iT‚ÌDÝ,¨ÜÅ|g¾ D ýúQ´ ãhH6˜G ¹Àƒ $ vfjhòˆ b@°ü?`þÿôÿ›ìÿw“þËý¿ƒÙÉèùT–š7ú¼+œÖ,KÇ:«²£Ž©I_qONК“¦þÒ‡MĆò­ÁCè0âÙY¾© ™†e42gqMàÃq›:·0¾Ì³†»Mª‰¼EØåq3S#Ê!;ŒäqàÓ 1)ÐdUJÄòˆx@‘¸~Ôt#–œ/s‡úK7¼ÞS?“‰³qƒ±Ð1ܱS6¢ù_W+Š|œÅ b9:ôõ6«·ïæ]LÊ|¿¡eøZ}îgžá# ä }à*¶DäâBØmØõcDqŽ)‚Š´PF1„H²üCë«H†èZðRù–ÀЧûׇ{ØEû‘þ°‰fߨ]ÔâWEXŠAš…Hvƒ}¶ÞXl›Fáœ-‚¤P ÐF ‚BEà 8ŒqHÈ0Ø{c n(cÐf]žoX@ìà¨$‚%ñ*"‡õAP¨ "ßA@¨²¤’ $€'1ŸÐ:˨«pèù>R)òAíÐNUººA)ÜêïÞüŸŠÞÿh|âKÞÛäæ2HH^Þ“çqZ¶Èú-£…¹@ù¾ÄöŽâƒ‘W,¨ Œspéý–l^&sâju:ç/+œ€4¹V[xì…€ì5TA$Õé] a‘ƒI®‡N’0V ‚04‡v*¬v邃Å$R›b»h{ü¡¿y"HëOŸ¦ýÊn ŸrÚ£¸ƒ „RHÐ(‘‚ìÊnq6.¹ç$G8•@B+ ²(ÀŠH¤‚Å‚Â+8Cì“t“£ÞÔ•D ÈH @*¤Õ€Ë%jÍðXVH,‡ˆQÍ@É!Œ1¤>KX©6@ † ¡’½Ú "â¿1ª›Uƒ|D («W(¹¢•K‰­!@Á ,`ä ç¢öC{"^Å; êH0Q¡½2íU „€ªÞ Ùâ0šuMÔ¹Ñy”Ö1€xQQÊÜ„TÏ”œMV)Ò$€áˆƒaU†+€2,’0„…È#æ$°¢¬Š*ÝJ¡ ÇßÇh8œàØ;¾Ãuù 'Öm>Ô@öDY¨«emB݆'PxǶcF›ÅC=¿ïò=¨è‘Ù¬)NϨ2õ­EÑJ­ ¥©:UC ZpÈ'b0ÙÚŽsMÜ'ÑòÖÌU4øçDÖ‰$”Qˆ”vɘïPÍá¬ûêN&-l°àê8ÉÉLÇëvkE[3³£Óø$ª`Ôtšlc¼‰Šls¶hG8tíö¢ŽùÆë b.ö3´@0ËIAJ•:ÜÀØâ˜3-¤€ Ì’IÏÛÙŽÄZâeƒµõÆ ša~æsð0âøù$QЙvkn¨™²C \_Aæ½U7;Û1¥ UjRl‚¥¢TBFƒÅp€Õ÷Œ¨BVÍœTârpÚÙà Åz@4öv×Lfw†*¹WÄqƒ`èÂ@"!èÀ’@^l¢óœð:ÎÐ2ˆ· ‰AÆ“r R…¥CÒe§/ú3}Š d%Aù²UϸÐ(”-U!U_>Ðñ¾ãdsÁ£kAø!ã Q$…Ø0Añ¢Î*þ’µ;¬¨»ê²ý3ŽÈÃ>«¹ ü@ßN\ÆÖ‚—-->56±¬X 75)y¾£Ûð„Oµ×JYË4¦åNÀa뀜N&µÜßöBIˆur(ªíoç]úTò”î—•,Dö1ZV$£‘1ÂQ°#AÒNPÒè0ƒ¿HžÕUÖÞžÓéª;àÕ¯[äÚž6%Z¢Š® ¯•>®íAKÆaå™´Í”Æë ?ƹ9åî{<¿p=„330àâÐipvÃÞÀù"Ò‰'.5 É–i•‘¾¢T[ˆ06Û¯¶ûO}Ü|?ÔþçöÏãTÌû†÷៧,âìr\¯ë‡•Á¨Œ`ÒÐgó cïHZÂ(ÈâÒÌHz(`z•ŽØŸ úÿK.Wñaí‡@K£ùú*MýD^".›*Q [×ð³Ìý£s½N'+¶l×ÕÌÓ,Njæ›´>Çwý½þ®ƒ’·wþ1Þ#÷©çCßÎ}»ØìžeƒÔJ¾ß ß§ålDå. ­(«°U^°î;ìd¿ýᤠ7½˜#”U`‘`ª™ÞC+¾Rw ÷­`(x T «Ò$'¬BH’@êxó;^¹âz5¬_6LòµÕAG ±›ÔAAö™‰ñ²Ð¢&üW0qwa»Ø‚¶çǹ‘“¦îã0?ÁüöõHI´;¡GïèØ É;üÓM(á±Ã™ë2)òÄýôøOÞA¹¾´c5VÅ¡A?J HH7æ–:òIàl¡A$hÆ9 XEç)­’n m&ø„Ía*Îë@þS “hj±6ð¡œh1”BRwÏø·þÊ÷#ãÁÇÆI3W6Ôa¶Ê ,‡¨œ¢MÍ;]=1t&Úö¢Q@^¾tˆm»!¥¨µT{ŒÁïËWSœ(V;U]¡²m¹Ž{\=C“ľ¤œtMsQªÙâqSS)(Ó+ )‚ *¬Õ…›”ýV:þ=¶§|8WÇ›ž½CpÈX¦³k¡?•ó?ùþÏÚø^?ðSïÿüÿ�ÿKì÷¿¿üÿn#ù‚BúU•r×ݶ"[ÿùÿÝfßù8!ä›%«‘E,¸.X I$•î4»úšø¡¾ö…œ\ì0ü½l¢àH?Ä\F"Ë`VrhÍZÈg 0ˆ‚Îôì1AGfÆPKf­BҘѓXfH0²j™–¬Š¢Î½&G“úW7Õ9Q9aƒ4Z2I#$£‰0ãul"1“fX€TR)ØÛ!³¤ÓEšŒºµXâBÚ )`"¨±‚È AERÝ6)[iPDc0œí%¡UµˆUID Q_.OIÜžÿ’7@‹`º"ÂõM5(UjOÝËwíÛøñ”úbÃH¦ª *¢ŠO-;ï!» 7J•¶þºyy*}=4ÌÃFnlu“@<ó™Ùا©¾‰³¦}1…:G~‚°œckõ3¦br]²æ‰$˜)–›¡"¼è¨º@*ZÎÀö\Ed[[ ‹‚a„µ!N"4ýå-6>µ€¢%¾¹hpžƒÑü\ì?Áöd=¯Ru;ލVºÊ:ºjcŽâ™cªh֮lj=é{Ž2Ý8F:ÃâܦU³­x5G§<(ä2jB åÛNãzžI^¥p:”Ô“U,•6%šUl6ð ä@¢@õ@¦ýzœIì.Öôx½=W…é}w-n{ÔÞÝ9Íå}"«0˜¶âûeº2,‚>æ!Å8wbšv;رUaËÜd6ºwÔ…„w"Ѩª1Šº° 1" ˆ7>Ìɶe?G7®b™\¤ït߀ªû5U\rvµ¡DD(aB²DXÁÍ"Àh”€Ã3qan­É½,0¢È´4"äB‰_½†&O, Cl…]S&ÜqĨ²T-˜¬1(î‡ÆAÖ‚íR––Ö µ–þzmw$ 6w†Þ)°&úX@OkÂQêƒ(xèw ‚)üUÖ¿ñU“§ßï: ©áçsçgœÑ³%IïŽåM‡‡dóÒÚ8zrc4Êõøt͆|WQ“µî7¥š¤”8a8wö¢N•ˆ¢- Ë%*¢Ì‚Q@–{¡·@ï.MUëK¾•\Ó°:›#¯È¥²3‰™ò p«=7=Å×/.}Þydn•2 ~.zß2h5ÁUÅ 65Ã;­•ߎx­NDvlÑÛhÂ"X™RO§§<)ííßnÝKKél­/kån•·³ŠI½œ£núçòôqtN_qNV¿Æ÷'¿Ó—[ÕÇ–Ä’M®B$’B!¯šqh¨¸4ðÙd}-ËŒÖQâø.Uþ¿ÌÙà ¶Ûún $æ0¿7söN[uùºgµÞ‘a "€‘d'×3ddPzê¨CõÈZü@ÂbìQ íµÑ´aW|ÏÀb(ó å”P>¥r{=øúÛ™VÄ¥±¢BAÍ Õá:@ª×Ÿh–VÛÕW§·oÑËè딨qX=}BÕùõTó!úz4ªú6Ãðê±TwÀªØÉ-L­v$Å‘ k&µÊá‰14d&Š[g>íLfµçÖ¢j•Q*_MÎ9‹ a‰mµC¦YjËPÕ1,]úCËmÃ`3zrC$¢mi•y[-*ÙX "³g †± .ÇÓ㉸°5’R“ápDøl¹;²èiíéêKÕ;j -”ßX®@Y˜”.øB«)ÜŠ8¡-$[ÓJÜN” ã!°^c"¨))F0J]çŸÆàI Ca’V»Òd†cAÆ c’ $£ÀÈ„õ@°Ò…œ€ñz䈗Q̃ê"Îp‚œX¡#²BIÁ"™ÆìˆË¨2c‹xÁÅ0G©žÔûDSÚ`H&f@»üº¬BˆRÂfÛY(æ”/€òàhl”q‹IH’‚ÑE;V1ÍÃÓ´» ê@Üwµ–4€¥¡%dð* š6×™¡GªÀŸ6e*®L‘‰4—VLŠás*9”ÅAƒ13-µ‚÷ÙQĨȲ«z²,¹0 ÂU[^*rq aòí«É*ؤ¶ØÕañ-0Æ&´S™@Rd(•±«eí"V(e­IAjÛŽäCä…ÒÁ ÓIÚs×ËSj$„ÔàV—J›tYhKP",4˜ XTÁ’\¸Å DR(U™’1#€ˆZÒbî@p8Ë ‰b$8^Uxÿwž¤-­¦Vs[õ[bößV€cÛÈÈsoÔN£aálßS² ×éM]¨õ´MêŽ ØÊU ˆþ¬»Ý·»`ägƒ ¯¤Ó㉄X)™Üß7PfÁd•xÉvIÜBUqõ~öãÿ7ý ²…¸˜$3ó™'ºë™åëØ÷‰‡ÿwuI„’˜1L3ý¨ˆ>½q¡jsVØÀöZÚÓ—moÆ–3Ó9Œ^Ø‚«ÀïšåŸw¶Ç:¡ÚI²º­QtL™«¦¡ÔIĦÖpì*i¨STª]8kU{Z½›Ó C¡Ah”¥' 9dÌÅdýÑiµ÷$5 tr·†%ZtWËo©z~G˜"Þ½ªff±™ÍeêwZQZ;A–¦&©‘V<ÒJbÎIžôv®AgyPí,ÕØ$¥#.€ìƒYÚÕ‰éÁþ÷ÔíÉÖ|HJIÝëb-7<8õž ¯×UNYÈm—‡sÒaã)ü’„§=åx)LûÛóŠ*Yö69|‡|f)¹/ó™õ1g—uÕWƒ*¦v[Ó»x˜jt< íܳ˜qk¿ïP|3)pðüR¾¹>DD n?ˆì!¡WÌv+²¾&ûuL¾WöåÙC°’\§` Bd ‘òÂ=ŽüÁÔ1ô€™:¹T¥Æ>cÌŸFN»»P™Ý[<)©$!7U09Ný ˜SxKÌÑÇ(¹O1L£AŽXâ:Rz*°ò(>d“‚géí{Ù^'ßݺãI}»7É%/UÝ"ÝC;BgBÑÛÃÁ Ⱥ~f“ë·šQÉ6§Q"cY¿‘š]AJžlœœxìÍÄçÛ¿¨±TÝ4Ì·Í›ºtŽ3¢f™g}é­‘GlÛuå€wÆ{‚:Fy˜‘JvB/ÚgåòÐ’Þ×󛏨®ûž™/OÝ:RŽ)~<xvS>"q»Qã8È[ÜwJ±+&‡g§q™™ŸègíØ ZþÏ,â!úóï~.Ä#Ø£ÆYÙjïºîkb˵¤’KÙ•%ì°0]¿‡–q ýxñ~/¡™™¢ ØyÚ[(>§=Ñ ‘Š"U[Ö<ñÛº;]®öã×[TîÌ3-j¿jÒëXÚïf×SÞ/ù³},gFz6ì¼ÿ±±’òBdªÚ5ƒ¨g±P‹ ÁðTú Œú xNŠõñ—Bîº?Sª±çIMzÞ ?ÈâT-»xíÂö<; ,С¢A•WI'c.PÞÛç*0¡«!Ì" £Ð}È"ÙrƒŽjµÎÒ`€íK‡Ó„@%"èÇ8·ÏÓß|•ðg…–+h…6DE”ÄØt#Èæ B¡!–N¨ áö) È%‰E‹®.v qUÍç²^wuÜýïrO†?øËø›üËg%’à×a*²¬ŽÌ’óxtLlËÀ€Ø‚¬)`bK£o*ðôÝA®¾«&ȯ?e» ë¼ð{ °-b ˆÅ‘ŒŠB1DDˆA·ãri— ëî›çU©m‰4ɯdít¡6Áì¡.vçããÏ8²Pysáݤ¾ð’ ŽŠ— ®W²~ü’ŸíXñ7çGn«ïyMÈv½ÐÏñ”؇‰òˆŽéUé|[±òÎÏ£}ó¶rd™—¢&%ž"žz·õÀi[õÊþoø1Ûvüƒ'Âh¥Pªrçâ[P61+ç½ÅÿgoÃ4þ}‰h:þMÂ]dØ]•¿,åðd”|.Y„m’I€¸_Ÿ|oJyùZRYÆ­ÖÍ»@.ÁªTMüÇwxYÒ N9lÅ©‰á†ÈídÐé¾kVN_‘Ô:²NÆ}‡…¾ñi÷»»¤ âÖ” Þ½¡æB •ƒõ÷`¤X)ÞÙŒ‘‰ÙK¤ªnæðå5¬ó8Ô<ÝOMìÊ Ì—Q²€A¶©DÏ£›v‚‰ðùNߦ›>[³Ž ñL·àz¤='FîjCèG`ÈÏñÎá¦)E›†Ú±¯P[pó²t5EÇîzEFŠ`У ÒŒ …6†Wb‡Š ;5u6!zöK ÑOXLWnÊB“\¼:H(H ¤RŠ,‘H( AH)  °Š‚‘dE"Y„PR’E²"Q`² AdXE‘RA@R,PÀQEA,@Y‚‚Y "È ¡"Á@‹$‹ (,"‘I‚‚ÉH¤PX PR( I$“Ð0 *(¢ "¤"È¢ÉQEA@QdXADAI"‚‘aPŠ‘`(°IŠAddR‚Â(E„Š’I&Ç’Bú,¢®k\U€lb»’E÷C‘‘¡¬ª'6EU°j–*¨l2\ dræX)P-@`„( rZX”†€k$5 €}©\Û†Ê?‘ùo"1Å1¤Øs9Œ.B(|T(Ô*<ò> ýŸQó<`É¡÷Ûn§«ÌÜ!ç¿€=Ðñ›|óA!‰Œ`ö¾d1È‚"³9'Ãê<%=¤ÐÅännB…VA±!­O:Ò¬ijˆæP„ÔZ4ôœ,IÂŒCn夯*C.&ÄC+¹å^â¢`MÃbú¼›;u¯eƒœ³ŠêUÁÓ˜Y½êÔ„° ÑØ—FwUÙ6»d½ÈÀJ9©(¶P|P³èó yÃsâÖW^¬ Ó:&Ì:{¤šSéâœT$‚drÿN¥‰0ÌÇd&7Y­@Ål7ذÑjiÃ6lf—V{ÜíM.¬ÍZèÙ‰&h¥Ñ €&RL@l^Œ…Ua,&…ž Á²¡Ýé£tNV„ ˜¯Iˆb=>®t<Ãíj'µë0ò¶jëø<½çÏÎÏÆª*.¹¡`õtëHvD+ }ðÜCâëˆk¤¥U˼±‚w!Õ›·¶°Iß`Û›FS·Âƒf÷`€ÚwPÔ4vêCv‚!ŒC0Quõf¹!½6cëÃR’â龊«½ñò¶ñ êÝ4^àÜù¤ž9q£ä)Cˆ+ïf ¡½é„¼¡¼ý¾Øƒ1àtÝ2þàȤ÷Çýúf™pÐúÆkV[Ag±+(•Ð ;ÙŒà.(&$@‰38@€à>ghåk—ªlýrðzî>oS…“Òµ99iìò|(xó i¼âåÓ:Aæ’ˆŠ“è0ÄGÙ«­}¬r’2½âð¬>Çò(PâŸ"$àŠd`Æžjäïv@$xKU!K+˜ªšdÔW¤­ á0¨-jÂa‰>G{xØí‘-© …úc¼Á‹Ÿ=x¬Gì+Þu/ÜWÊAë{>9QívýÛDU>©ŸßßÇyi½”oˆýôtÐ:BôîÈeòB†¿¦Žku\ÙÌ®¯v`¦1ÒGµØ‚áwmj•SË7Š|˜-É;¢… åo=AÝ]uÝò‡=Ķ!"2g³†Š8‹£@ÄNK…SÄèròž'aA±|G„Ó<¿T³sïÀ4Ÿ,(YVx¡õÉêêD¾Eu íÉxœÉžL@ìq'w•(*-RºsÃS–™!ÑœM7q8ôñÈ®)ë0è@&L„‘pì[£DíílLKd›T+v Iž½æRV×]\t˜Î–NÑ$û ÅÒŠr×E áà¹å ^™™¦ÒÄ?ÃÇ••ôÜ’©v¤~O œìÎR„£)‡W™ÞBQ¸‹ H€ E ª…­*§>\òºßzÙD8D;wÝÞAß|íRu“ÓG›YD­è–‘"""8¤ZêªÉ&Ÿ³Ïw‰ör*óooT?xÇ9^™™½— å AŠ¿„{?7£Þû ~Â,ȧ_höØCŸlUÍQ«vûõîàB†-éEBkûhpiá¾ìŽt\³+Z¯í;9NÐßXïÄþ7oˆê݈Ê{·ó Aƒõ%¥!C˜S(pvèó±òÎGÅÉá«e#²8£äŒ˜UÑHÎÆ§<›]ÿ›^iùºGa]@"`…õØ´\íÀºWKÜÒŠWx*¹‚«pUÄ« !7oÒd?“GÖžgpœzóZ=¦;9ôkk—‚«FáOÕ q|ûE£rA\©¤‰X0ƒ*1QÅV#@Fvf}¼“ø»¨#Ã…Ÿr¢dÁeðs“ò¯»—U3ôsëŠÇîÞÔjTí[5Ú ¤átDlaUY(Ѻ4ঠsÓ$KFMüåþ…¦Uˆˆ¦VVaæÎ±EªÌtË®äÍ%!“aÈ4Âó Žƒ4ÒÊS`Ò‹ñ„&`\õ3ûgéC±Œ¡ÕÉs„…¹6aBüî:Û¦¨¥0$(‰kF¶ÄñA¶ §EE\釤ãl5 ç]„ ªÈF PÂä¤Ù†ýæ$/ƒ¾Ê¤e|9s€@êöd@††ÃGB™Ä †YŒd;À`9(‘H ÄdœÄ".1muþ5Ðבqα‰ÝX g€»¢+´›Fý.ø¢m‚$séá`ÖÉ+Ù£*’‰-£”3ÄÔ˜ªÁ†YqZ)€ä¾)‰¦#£*„‹ Ìf¢D&œ|Ïš1ýÏÓ§ÂýC­•pZлQÁíR%Ýaáàa¯j!‘ìÌÌЀ¥´Î:®9 EdËbœ—K LY6–¾1Ud+@Ìä™XY‰meÛîqºw¶&C x Z/ú$VH,ƒP¤V1€írTÚ70RI‚l0\- ´¸2j¨”£®îÔEÙ¤UQAbAW$§bo{Û[rT‹Ûjá ‚vŠ­ ¯XªÛîmÀ(óWfù¬óD‘²µ¥Æ k!PT‘1„Kg½¯˜µ`UwŽs²Á„Uvb¡|*"‚U’y ,YŒ&1E"‡“DdŠPÒT!ŒÄV¤² ¡'ÊâÁ E« Y$¬‚‹$*¤ TrY+†[1€6€°Ü„…d<<;ºÌ%KrY4 «(aê2 Ã¦y}’AÖl€Íˆ,1,hqêþ¥7œ4¨Tdï[t!Ò‡¨ ¦¤L&ÉNÙÆ&]šå³~h:hM”P0Ž^D¨šœ²" ‚ `é7&OböDÄözr'«û¥ƒ³ÞЉ²“Ë¢‡éÒ¤;2õ@ÔÚ$iÈ Nµ12U"ªåÍZešË 0Ѫ¦«¦0.P Ð*neÐÍœTUÚZ 4Œ• ã‚d –» I¥·d¢¶Ü–ŠìÊiÌ,Ç0º$’h’Hàà!%Ø32+«ŒE1šÍd$#K.ŒÅëu”Õp¢(ŠnR"VRI#Á“NÓV‹fÌ(đȔ­¬Á„zI3Z’è›8ªŠŒ•ª¨¨¤U˜Ñ“¯fÄX€A- àÃh5˜š4hœ¡´PX ŒP`#D¾oÜ(˜/‘H5” §¢Š žð)ÈÛ®H° Ë@HMš#i• U¨ÔY ’ª”$^‡"Ž'2ÏQ»Þ¢¯ap±»CV'[d6{Þ1Ðà`\ª*ö  à;Ì.`éÚ6a·Tyè H VDAaMó „QbÇm‹‡ƒÖ#!ªhä |ôúg*½B+Ç^uÜ­À憛–ü ¬ÚäÛ¹«´k9²m” ëWû~ø'Ç©††3Ä'µ8ˆŠI$_~O\—ݡ۴¬‚±X+ 5 ‰I[ÆÜóTCd8Š8v›6co°ŠC'Ð:ñ̺q„šïñ‘0þ\ü L»¸’‡dSܽ;´£ñüæ§>3¾ꟓ’Ç%5Ä’&ãR\zPED3<:L É+DkJãEÜͰùËZµ sErVsgeปYÅ¢ç½Ìè`CÏÀ<ÇFŠÈ?©©¸TL?š9þ‹Ã¶«+ûK<É”Qˆ­“‚ dÃ~ˆ/üˆfì{=__é'µÅ‡2Þ™€9E”b Šíx%¡3Š.SŠEÖˆTx&Ȫˢfˆã?(õµ`F.¼ŒFéßÅ¿Ü*e›þ›íÞaq–K7£Õ5cYYˆ6AãUÏ™äöÖeÕˆ ­‹=°ˆûÑÀàP~=c´+´,V4É•64d™Xgâze fƒÑ™õåÔÆ‹bŽH“&1Z›uÜlîR‡ DDKàö$.@@ERÅY ˆ”þœKÅVvSÎ$VôóOÎñ(ôÂå68`ª¿%Çd8D5„ý-þ=tõýŒÜ`«ÄEA hü©·‰ÉÙô0óù¿ã¹‰²%¦°0}þ±p%õ¹§x%²ºÒãå\k±Ñ¦pè1ÜHOAVÆÊáB«ä~¡›-ÌwÓ|”™3Qåw›ã¹dû±Óz ãÙ €*2*©\&%B6*·ƒh…ܤv0‰)!Óж,Â,™I2¶BÁ¾ééöô{èÌ“mO^ÑwDXEº!ÈB*Œ³ù+¬HYâž¾꟭µz¹t–Ö†|[Áx{ô“Ö‹‘‰"#'iÄ‚CÉ„¥±îI¨wbZµžx*5±;³HhŽ)­Ð ] %Áòù*¼Ü·Ž¾;[X6 šWÕ‚« ÂÆ® Ñ5‹³ûãžXu¥êæ×U`YUgˆÈ*—je2!B¸¥¨ ˆÉ²èŸ åÞ.ô3CæU>6;¢Hú¨ºF)ÖãüÙwî¿Ê(H‡ ×ÙÝk¶3OÇÙJþ8åUB±j&Qˆ–Ïí| ®%»ROs‘=}ì<½-r#içÌË%+m«ôœ¶¢PJ‚ªÊ”FŠV! V'öI/%YaÁ $ÏD‚©4:1,(ZDn¨µ;Œ²V.˜*´Ÿ`ªÿ”SSižª€š‚«$¨H˜Ð7q ™œÞø ·²(ý6ïûüIÄœF7U·Þü?8­'ª÷ÃÙèwª>C£@Û}ãf¡ÚèƒÙÀÀÌ`ÇNÒ%ÁÜô䌞g““)‹†V Ž3­Ë2n|L¸²×/Èææyÿ›Åûa[ßþþ6ÎÁ3ê•ÞkºZšª«îr?ŸóL;ž¦`eEõˆ‘ìûê°ç'VKX©|Iu]I>à'Ûa “œ u@<òŽwhv%2y?Ïsyá•Sñ¬“N29a™kRMÒ¡3Z*#0eWI Q-@Èhè9C³¹”&¦›kmy䆤ýk}¤°Y¸7Ábµ4;¨ô¹][P댰 ¿ eƒe]éÁˆŒ§þÔæÏõ¿Ž~¾ÞtÜŸDUDIÓnDÇy–GT™¡{huÖŽZDâ_¿ôñ³þ_9e}ÒkÈQjçÛ†¶ÉVšûœ™±ö«Cér‹?+.P‰ÚK?î{.¿=­9Ä>6_“ôΑĦ­!ÿu9ä5¶Œ†^̹Œ¨_÷úp¸¶Î3ktñá<,QûUc¡Teû½kuÞsFÉ­¯qc¿Íú^¶/ÆwÕÜÃÝwE€] ýù!$’~j¦ÆÿÖ ¯˜m‰‡»žËnu—ÒR–!Úg 5ehÒdÖ¶8±†1w"§îÿ?çÂç$„uE$Zœà6ƒ¾áC¬W>ÑJÇ8;0vƒÀšî‘mCýïîUÕüðîÿª¼£›µýûäÒƒä~ZfX£»Ñ›”z`eZCZ¡¦L·¡‚LŒ3,&%`9˜Îí!‘‹§¹1~ö¹ÂÆn²¯mÁ5XÀŒùÐ`X7ÙË: ý3‚Z™Û}Ýl+y‰” %Š0Pdó°:tŽUÊSû 6yg›˜ÛŠ ðÀUå"s +×ëG`h´Fè$’_Êï³=)·®“•II²îR ¦ÃýÁëú~½“E‹±© MGóz}Vô˜¼ó‹y@ÊÙÿ—lr?š¬^©ë#©fkhœ¨‡P!ÐZ±u ò™qÒ{î1,»a¾UŸ–8äUP~íÛ¦h¸µ‰H'ÈL¯Qžy 2¶ZªF‡v¶Ê®Kå™M¬BÖ]ñqPU]åèîo¶ûᆑÀà eä% -$¸{ìÃ"\&f%îæbg èåø¾ñ|¶OI‰°ä`¹pL ,¡¼ç­eÌ¡ØJF@‡gÚx ºG™¾^òuü# úÑnÜ£ ÔÍ,rœ¡Êˆtýß·¶Ç?ÉÙ¥ÅWµöW“KM¹»è±õrb¨î  t>Ž-²E2ï'qL1çÖFNõO;)Ýì]æ€ÐÐÉíÕ¯6Šz¢Ýë‡J/…ÑAÀrç ×n{e~ʳ”” ‰PIÐfÑHá¬õ8ä¢|‘¸áÔ£YX£Í@´ZSXUÆ•SÚiÂÓ}M68S+m…‹ƒæ2#T9‹ÑÖGŒ²´Î+9M‚Œ,¬`æPA›Bv©Ä’´zÅqžqº´ ý£Ž·É~¢&[¥žMÒóVÍØÝˈ¢!™Ní¸Ë\¶ËÏŠ p£é$ $ó»:wóë±ÏåGc¯|¨U{þ{_Òõé•¬Ö ¥ý¿— Ÿöýƃší±iÎaåÿ³9ó÷Ni·Ì“±ß,pƒ…Š™×´p_.µªhž^DúE!Dôyí¥*ÕiNÍóÇù¿¾"­É‰;4˺ö2 k8?009t²#“@¢ò¶»?Í ÿca »Eô D±&n8ôü÷9s¢¡ê•‰HÄÄc æ@S0@E„VDóÜ…Œ²1±FaŒ1þ,àZ>ó¥SŠˆ ²ø¾‘¶²*Ȧ ÈüÖ2ŠÅ·°™Æ@M øLGª*£ïθ5 »†îyÂÊ™Ü=ëdTß ˆcµ˜íËI×\…ÆJÏqHÍ0{œ%%  ‡\¢×j+¸3¡êôýOô»€/©øÇþosF¨j5µë‚%»>2ø^°ëíÏ ¤Cøý‘H§Ê„BÙ·Bm·óÛEÍ3S?6ë_ndaò‚L"N<F¥f¤«¹ãv2 Ad%Üp»íÞ«Ymú™›ë§º-8ʹ»Ùlõ3=öaâߎ¦-ÐÈÌè a0qºåæÅz+òq†¯îü_€Lž€™FÜ`ʈ×x-ŠØ8K²b2Ùhuô +`0Þß5Š÷©òvÿÔ]pÕXXê·0÷­„GŽ<0¦Ƈý! Ów­.í òìwŸÔN¯ã:«û¬Îï(,YW 1 FÀ3Ÿ~›9=ÅDG¥‚„ ˰TO€"‚£6ÈJ ˜ !6܆g ¾"Y*ø¡EäÓ·Ð%'—ájK*‘EŽeÖÝï+¢•ù°YZy:¶«¿W13l ®?ü]ß5m=3õ÷ƒ^ûuËÛh±k·\j]Mâ0P[n°.¿µ «Xzµ›~»nZn»ŠÝ…Pé¤Ëó’MôØÚò¬; XZIÆ‹o[ÜßÎï(ô³5ˆÉusqEæå€Ë}øîýzŒûS×crËÃ5hm™úx.7·nçÏǰg=Ñ2äŠ º¸KV }„æ ý}ìaêüËà_¼=…­é£m=–pìv5 þUõh—ÌL f ÏR¬·;zÜyº |Žq³5®V›Êt0sp+Nû÷Õxüßþüì‹E®1v;ôƒ÷pͪn|œŽc­Ô'Øf滃vH÷T~þ—ÛW~|õçàü‘¹6}‹Ëë•/›4×mqæ±ÀïXQ©ÔðIòüÒ±vëWsy­í'W&"túç—ËÃý¥“eÃÓW ý¯ì¼9ÑÉ"uåæs¸L•†ªµó ±Ÿ Ôè8ØQôw„æÇ§²¬R>Ÿ­O¢áŒËßr×µÏý;¸Ý?Ë­aY°v¢\ë ;¢÷?Ey”òpd\1øíþßÐú¿<Á`‰6?õÇ·—à°Bs¦Öy½M—aºÑ-棨ê Òº+Øz׺î°ÔÜ6Œ?Ÿ›ØÖ_;ÝYéNÅëQ-îµfWœª( áQ¦jâгöj›)ÛŸ0¿¯ÜþÌò",NêvD›½;`ÍÓ<= ¹ÛJ¥ˆ+ºå }Ö“oÇbÂeØQ£ßñû÷lÒüÏÂ=™o¯O)¼ââ¬HvA‹Ga«ÌZ"®ó3™&Õuïz¦¨íë[ùmÛ\ÇcÕ¡Ï.ñJß_žo‘o“U¨ÿU÷üN«Eçïu¥+<)÷ž}.!#%5Sïöë¢x±»MÆo_c™'|ÜÍìtYJäRXpÍôå¬vgþ=+}*¶G¼r[Ùíø|}¯Mé†÷_$÷ßñº.s1·>³;”“äÖ© ·Ÿêµ|›k|\vs|ðù‚·úô0žŸsF{xÄëmïøªw-†Saÿfÿ³º}>ã)«ulúÚð3stV­ˆîPièÇÕۿϤsíPPêaÝzQ-=ŸÞ)*ŸÔI£$b—¤*{ïC+ŸÔþyúíüßY(lF‰”ø.›Ö…Puœë}Z/ò}ìjöÞ‰Loñ²õù°ïÔöoA¼;X0OmÛ.›Åê¶?‡a)‰ßu ñº7}½²æ¦vÒv–ñ¢îØáí³»Š{E¿-ÂûÊÖ_4ýôTy~âŠÍÇ‚­~gku¹‹ú­¿çfßvÏ.a³5,¬™g½7¼Ð·jfžgÎß=ù:¬8ÝÜÆ)Ï_áúq¢qÜ ŽúŽqšzãj¥ñV@Wn0™¼4'*3yƒÈþ_´K÷­·{’Ö¯º’â1p/uÞfþ£œùü¹_|k­›U1KO‹:ÝܺÜýæ˜?ù^fxм¾¢ÞÇ­ÅÕë7š6z·{¨“³ñ¨­ÿ]¤Z–˜{M&/ôt[÷Ài𾾎 ¿çâV9ËAšÃ>r×ü²›]šó&/å÷‡Ú=wÕà ûX÷zåŒ$—†ÉÕÖÑT“Ö…kÁ¡‘ÉÆ*×hn³Q[mmÿ¯ À~Ç6DÝ<™Ì¢ô ¹ø^Þ5á‡MÞýo¦³Šž!+t:Ý•ÛáÈí1³]˜Š–S£Üá®ëUêsW«Â<5Æ1˜üEC’„¸kÏÎsrŒa@A5Tùòt`"´0Ýkc—Uè2þf® že“VÇÀõbršIßjæû†ª³ýÎý,ÑSç~U·›Ä\VÞ=«ÒÑ_vÆùººö-~·©wÁe«ùýŽÞvƒî¯=‚YÔÁ,ÖQxxŠÑ—ývúi§P»­—úi~ÊÞÜç_sÕ·ynMaÿ<š¾D–nw߃^©¦EƒÔé¿ç&~¾›‡Kc„µÆ­õ'ºÙÝBÿ›ïÒ5Éu4‹|cü ¦+«;ÍÒ©2&]Á×jïVÏ=°É4ã¼K>%i>ÌÖY!Ú?w“ßÛ›‰þ)r´À¬s£z <ž¢‹ûcP×p„fŠëêãn«wK“FÚîßæÜmåà ¹y Ì$¤Êk¹¹ðäÚ‡J“c¶­bDEÚôr §S­ëmÇ… ˜÷û|ó9È~\`?0p¶—HˆßŒ¥³:æíöœþFƒ*óÙÍê^tøÉ/–ÃTíH—ë師r“—uz>O?5k1_†q‰üüè±:…¹žSæµ”Ûèïl• ŸŽâ£¦7I}uþgmNii:­ÝÂËOÛê7ì2”JÛêW>µ Fûtè±C|iñy]¾’‘“xNmZûìïOG+<¡^C„pŸÈõÝ9k+“Èìàšéy]—ÇÆìöQÛài7T˜äTÚæê‘êíýçšþ–%?GH+úõå4–Ún•‚u~ü> FòûØïU_žp»gµÙKç»龨øàñüíçÛÚä¼Íƒ²Îó÷Ò=MÌ5O«5Øò@i•´9ƒ×÷ýsGotçßy–Š¿r«ËP–¦æ,|÷³ßÛ?ÖöÅ|ƒÖJxsW*¾bûÞ®‡xÌ¢Ñs±-?¹\39ë±'ÏÐô¸v”t<¬—+°Ö‹…“ƒPu2—ŽïÇ~íý–’®ñÊ`úŠ,ÿ^–‡]¤.ïQ'uÅúîhï:Þ¯¦_ѲʿÿPôDIîiûl?ü»–Çð×oÁNnq‚¤êl‚óÒKV7:úDLì{5æÆÚ?FsÙ¾Y€še‘UƒlÜõñˆWeü¿µýNGüÅþ½t—-—{AÇxŒý~šž3Õ] 7ºS©¬—ºý—®3ëOÕÃÖûÙÅܳïû¯Å6rA»Y᯳¢¬åì·W{í3ÞQóÍi¥ñ·?¨¥7ß!ëuO·_vñîàx¾7gÅ™¬`Åïß,²//2L+z˜”“Õ?vi–FÊ •‹Å<ßüã_¹¯öT_öÀíÎǯ=û¢â£õ}÷Ø@’É\î q-°õ<Ü_ÎæËꀸ[ÇmšÚk§uû y¼»Æ¢ùvQòÎD¤lú_ß»,Q”ƒ¡öËDYbŸs)ðñПK“)6ÃÉ÷—ªÑåc®’Lg2P¦¶ÖEǰ±9ePÝQ°²ÆùïÛœU޼,ÄÏPïqþÆrÖùÙÆ;;Z'Å*/ŒšÄŸ;¬¯Øë…úb³'à]YÂt{³Yúþ³_^ü0ÿ~KË•7'méòKÌvæY/Ü)Ù~zÝåÒV2KÛi•Rþ¿Bm­Vá»_¼ÚVÜe•+vÏCLô­mç|±Øä7ü´Ž *žY—µ«Ã#AË:õMGØËåC…Ë=WêÉðÜlä[Ô~W¸øìOC¶¹œã\Fý5bÎ7çïJÞMƨßNm·Ú~U¶í׉çûv|Ì.•›[ç‚«øí÷ï Ø,õRÇžòϰÕë_vêÛÎGy…~bæ²|O¯Å˜È8à=4Ú×î–¥ƒÕ×ç"ĸë🞾É•SÞ|ëQz¶™e®†#/{×0ùd9ŸOvá.°áëdáRËCeä2 ÿ][‹š j—µ»m†Ë¿ÑºEý¾¿ÏíÁ¢êù!ÛÎô¯~þN¥LÍøÅÈÒGávŠ\šººuºý3ôÛ6µíå?¸@gVØ:šÞ_àó„ÎkßV•±M?¯.n2ɼåK&Öex‡f»CloöƇ,óÆõöê(»<^a~^´ÿïšrúõj<÷ÏŒRÏj9/EL&•åÓ˜îã3IæÔD,|~¼Öw|¿é½é$ô‘~ê¦ÖÛ¦®5éÏÛ3㇮Á¨ÙÓ^<šÍ$NʼnƒóJÙÂÞ!žýê}t<<Ô:þßmÎK(ñGyêÞêêÿç}!ÔõE<“vþÙG-îKæÄû-óÌoô¾Æ_ƒcSoÖΞx½†~²ÑÍ_¤|³5VÐõÙM†‡kÁNÿ¾Ê{ãÜ%‡ó:ßx‰}¼Ü¯Í¿´Ù:~[7/¯gÅ3Ùõ”>ø;_7¿ª­Þׯw¿µ>cOdÎHîTL2|‘22²^Ö¼3ÊÆÙcÔ†i¶G ±ÎÂ`óyŠWÌzºÈ]™Ò}z´‘Úý/ËIÚ9ñ¥óá ǘÉ,kµ\=ɵבܿ¥òùí¹P3üÍãRoû+ò{‹ØúoMŽWø ™Ç+´vfj:‡”vÏÉ4µ VÂáo«”Î]x•.±”=ÇÆ‡ Ù¬ÕÛ«Æ»}Rðªß;hygÍòÔA:k?'ÄkÅ—‹çË^vø ]dV¯3ÅûàrÓLÔVì3Q‹¦b8Sæ(+$Êk(›YL@aÑOÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü5­Þ‹/9‡¹¾Ã›¾‰J(W³“×ÙÛ•·®£ÏgDCЭU>0 ¹é³ë8íêuî·8ÚË—¯–HTR” ¡E}hM(@ Q@  ØJ‚a]|FNú@è À÷¾øúop1^<¸ëµ„ìÜæÆšê»Îì·k¡  iô5yí.î׾τóçÝzÃ¥}h@”RTï>ðz46Ê%J…ò0=óßp½`o—ˆ½åîב­7Æõp&lŸ‡¶å“ÄÖ+#{Îæzk÷]Û[ï”s€ÍM¾w>©c"ÌØm·fìÙAZx}·°6dû>‡JT”¦šT÷_N½ë§>uÀiT”’½²«ß,ïAßïc×*•Kª¶¾ovô;vçGR¦Ã}{µJùuÀy۾Ƒ«j•>{w¡Ý…+«hª½îà}÷LŸ @úï–õ¾ó¦&è¡Ï¾ Ò^x×€¥ `Õº¬TS»ÆÀlI¾Џ4Í€T ãJ8:Ç£j Èrh:V¸'B¾ÛÓÈo;ßw‹ÆµÍJ_N€ÛJ‘ôÂ/sè͵®5>¾¾’” AöëP9íôû×CËÓàõðO^‡Óá;x…Âl OX&Ûn]¨.qô÷`so‹o¶û†/Xxî®ú÷!M}†ï»n2»l¾ôˆ•é©z0ÁtèÇÛÞQîzä§-3VyÈî^›Íá”n6Õ6õõ¸‰A[íÓí¾¾šë.Ø*Ö‚šFÛ…O§¼>.]µÜΔ…éAÞ—·.ZЇunf×ÊöÎóî­}ÙÕ CÝ)™íîÁéËï÷›»•kk©×q÷o6ëîz .úr]÷{]½gEkmˆ»¤a»tß\û¯«m‚^»Œ[R«‡Lr¥:7ØúzÐ>¨¾µmZ·Ï]ï|Ó’×UÓ»8C§Ð{·yëÞ®¶Æ–ímÓ¾øjA$©ˆÞsrû[»€vÛí3; ®ºÇß^0’õ˜Cí]3èá8Æ‹‡M۪pæµòÞÃOIÃyxÏOy€Ó>lXN÷°êÔe<èzïÊ‘&€ „ÀFCC “F&Fša4‰ ¦†€h44ÐhÓ 4A=È A( @ @C@ša ˜Ð$ò4ÓM “(ýHý)éPÄõ¡¦Ôôž¦µ ž 41€i hH„"h ¢fŠžÄi&§´›5MéSy¥5?MOI“'ª~©äÒl§ê†5 ê)ê'¨`Aˆ4À@ ŒFš`OSL&™44`L@Iꔢ&!2i©7•==SÉ©µ6P4ÉÉéµP¨h4h¨h’"@ÐhLM2ÓL&€LL&&˜Ó ÓCTó@€b0˜FŒ&Ôò§´É ÔòšmI††“ ¢HL  ShzM¨òšoõTmSG©£MÈŒM i €ƒ!£A ¤ 4È  ÄÇ%Â|wï÷{u´}eæmÑëªeù ¸Y³ÏÌvIs ½ŸNw7¸3×QÉìíkA­!âêÚŸŽý'¥4ÉéܺtïÍw¦µO© ~•PªZgúp,ZÏ—Ûåé3-èëºsº.\Äë®%ì«jï¯.w'uܹs»P(Æ’É£(Ïý?<ÿ£í>“ü’ÑõðAæá'¾ÐŠz z>«ðîeËê%Zˆ"„€m1´ †Cdµ®ƒ¡@l]'tÉ6Ý,Ž}Uâuu^¬QÁ#vÇz¬\¡¹#‚P„<÷›y®Ë/PáÆõ.þ©VãŠÙE/ô°§lmÍJr6úJÌÆ÷¡l[Vò¿ãÍÿ¯OªNªyUSè%'˜®ÎÉQ‘Ë*¡’:ác£I$Ÿ°dÂA‘Ì’VË+”ŠŽX Ö¤pcQ´Ó+ìî¯á"¶ÕÓr+ÅâyÙ ÛWžP]­¥£õ…ɾºþ‚ýØ'¢‚ïbyQ ÛÅT>’l†ÂèàÍøQ¹ý¨&ôDâÄT막:q@?¹õíã_“=œsk¯ëÀé|—¤/Õ·ý¿yH×@û©ò¿NŽÚH(u²ʲGÏ}§JÈwO§Š¬û|‡÷ðþïòÝ¿zAPÿælÑ/ ª=4µ¨ve‰©YÞ³æ=ñ^ÓµñÅÜ1ÒGn¸y^îøººpŒ¹“‹x¹8›Ó¹¬3|xÑÆø—2ï/[ß6À²™?–Ç$Âcþš<)ÎI5øRÁ÷ÑøñÁH/ÙòaªXö pøcßð]µ¶b®k͹¦L-ܶ6<ÈÊI’fF{uš{y¼ÆÝ‘îÄø²=c¶ÖQú½åÏû§êåÂaÞ~ݼœ)ñhý[P‘„ñOßúë¯Q’QüïõÙþü¹Ióöicëh3dò&ÈÌ„ åÛ”ÜJ2¥Øó àm‹Ä ð æM¡õÌ(?hÿ|ÿTÑ‚›5%§1Î ‡°P‚´ÄQU(_õ¯ÜsÐ2;¾Úïôqý,xž+’¡T@›]ð¯r¦¼$­ >û®%²)8¤|©@ôÓÿQˆ‰ú÷±MèσÐ?£í>†Àpëv …¨ó¯Ùª9f äSdp( ‚Z÷æŒ>Øt¡?«r*HNÇ’)b…«ÚÝM£V¦ù¬¢V駤AøiêvUy]Žg”ÛôŠtÓÜ5î“,Ñ`Æê/ù};ÕP ½ÃÂàftÜ D””ßã‹uð¡Gb €©G¨A ¸ˆˆþÕ%—ð¼Õ/˜Ž¸ž«äпóþ[é:=÷øuœc¯¼Ù»Ï÷Ïñ °a<" 8˜-oL€Ò@éóÝ\_Nê—7Û7¾-‹ ÔLOF&î5CËá·$d§…Î}éÖœjû¾„úŒ @bn‡±H4Òn¡JÆäÝ)¤î!8Umxõñ,,Ö4ضØ^Îë9ÕhÜÏñôà¡ê»\ ®‰ÂOh‰®k{Ãùø­#ËÒGê†2ÞÇTt$¼[¶è#ÏV=‚Te‡ˆ£%‹é°(LL‚[‘Je›ÛYEÍL/ïùÁåA€Cpý-þˆÕ·˜¡Š h‚ €!@ É|§ý½ ç…AÏ,CÂ$ìÓæõ{ó¾s´ç³ŠÆ’ø[ƒ¹ÎçQM•] 2.Iµ½lòwý¶\HôM§{Ü}ÍK•Ò ª=5M«‰›$O.Sa¾r„G襩ì V~NecÍÂíþyÛô…H ãï¹sʽ)sg ìþ¶¤?8k×þäúfxL¹ýÓ“‹ ÍL.Y•ÛÂ~ÓØL;œ<ûSyÕøOzª%ÆQa«¢åÓÑŸ)sSs 8m²6ÿë%:g ñ‹°S³ëöÎÐp vfU¼ø£Ãç Zß¾ç7þs^î~Ña‰²âýæãyi‘µì»+jûiÊD‚®ÈžF›„÷ -¶¿`Š^qx¼ë …“çÒ¥"¡,*ÕÛs×e•º¡Qã)kf²‹½ÏéŲx8›ECºÜ‡_fU¡¹ÅÔÏÓ«r¹‚ižJþÝ ÚŠD(F ëÞÛç+͘¼£\÷ôu •wajm˜N×÷¸WS©GiJÝýã.ºHÉmG¾Yª®Ô‡Ž Û·k•ÏÂX.½Mò··Íµ5&r¼v(nÿ žJw,½3ÿÀî/¹ñüi¸|DžC NÞÑ€8Ž` ; I~ä ©°DÑ2ᥴ/ìU…¦Û_¢ü¬%ŒCÙO²¸o€>êo¹¹ÙŸÑ¤÷®­ff«tYÅ=_;d‚Ú^×ý ^½K ðGøßv™w6_O«ŠCYQzŒûÞ¢9§8‡Ñ£ÄÔeÛ”?o•4÷R?¥ ÿOÇÓ¬3©Àé)g)&©?ÙÏ"UNQñ³ýÉÚË~8|Ý@ À€ˆmäj)£s»L·”ø‚OýŠÊ#ù_ØYUD¨ƒ ùrU+úYSM²^÷ìÁÌ݆‘:*‹>)Ԗ¤ü`³;"ÀÑÑÙ R|Ï`Ãä›?t!fßã<ÔúVøþ_?šï9Ö6!p":Oyû9k.m·ñE/ÑÕéÛ·]¿¹œ¿ÖPŸ6{©ÓÛ &V÷.ØLtPùù¿×Q Ã‚Ùeªµ|€øF©íÞõXËlZ·ÝYme©iüu4¶¢Ö®S3âý°çÿ§ÆqðypÞ=aEümñٻŸl‡G¥¦ÄÞéz? ¾×õu–‡(Dzúæíoýw³qaUOÖuV‘ü2iƃ«÷ÕÃ]Û_´ÖÿÍþi¯÷Õc=E÷¿Ž¿ù¨DUÃùcE•APQN•ÇŒ¼çÕN_åyó•€";[Y|ÆyÙäçõ´ˆŒ/ú¾_ŸÓÝïïb5ðnÃF±%£fl!"'o_5ù/×ø;ªú\™zò[ø¹¯ÉåD´Âü»e]³ðz6Ï3ØÊë>ÝM#Òaá,›ò—¿¯4±»*C‚ Ô";áʪ‘{øòˆÿ÷6ààª!’*¢g™j@BÁGÌ`ÖÿZj¼v¥ @R€ªœÆGuGÜÓJ[Uj…3U«Úæ£pѹ¹Z5Á T©F-»¸N»^AëM“\4qÞš…=jåí¢ñB©_æZ¬†ª‰¢Û×ìsí©·›ŸêFÏMxY9ªÆ{»/¢EËDŽÍqŸTáM¹`ß·n]ðÇ{ ¦¨™¢ˆ² e©BR *—Ñl7%Ç<ë|sàÑ¢ ]êÃbÎ%hÍʪ(ù×Óo¢·/]kÝ}WÁ1‘O„»òBm„`D‚¯Jˆ„/˜ó€_TQ<÷ÀÓÆÛê28Æ! ŒPÚ—¹¯-d6s+rüÞÑmÙÜêš©úMd?’Ôû×ü^ w_«òlH±Åî½¢„ ¨*ªª°’›* a^ A¹z±Ç tmV^gõ7íÎÃx¶èž]x¾ëu8°Íׯ£.æJZ³yª¯mW³²3ýE.¦õü•¿ƒuU6Ø‚y¶¼²ÆX=jñ¿“õk[[<ޝ2ëß§+·yÅ Ë‹¯U²¹®í[í®+£ßG¬¸Z v§ÿ5¦õU‘ilâŸ=}½-@¨°~”ß5ÆØÕøír"'Ö¶¥¨´¶¬‘¶"ˆÚÆÑ¢­Z¯d$7Ç·çæ¾®3i'ü7hØê|_[8>SçP8£ Þ茥ŠðôCˆþC|‘«àqÁgêC¢¡óùþè ˆí«³%PóÊCx½ígK­x´vàÈPÐsO©öbG±.k÷±]B¸¦/£9tîm´µÓÐ2¨¬£ ++m­T̽˜-$ÓµÛêËEÕË4[ƒÄ´m–œ"½ñuF9iö tÓvÛÛSÁQ`xÕNýõƒP ûy™µs;rÉæ6ÈœÈÜÒ<}S» §F=„y<ÝàoI ÈAÆ ¸dƒÙÀÜ`9 çFÑœºjNçö5Ý·sÎÔÜÉSàPÇË~ŠªÑÔ_>èÜ**‹½¢ù Œša¾?Âgo¦ô9ž¿{¬2¬A¸K†Å/ŸÃZ ”¡Ñçÿ+îÌ«Jf¨†ŠÑŒ”UFÍ4µDèÒ±mv×ñ•…,ºßåîwvC±N¶!UPÑ™EÝr7íð)£”3Yìñ£Öú kŒÂ]UŒ°Î)S\ÂÍ ÎAÓ£Äݱ<í hcâÀ°è|‹ñ*yR›58+ù}«”1b)“âN tù¾uƒüèŽ>ëýHUc—šÆwúmm)U\·ûí©/éË?Oí½wõøúÜú¾£_N²–9lrefaQW¼&?`ó¥ðpÚžùö¹A‹Øþ¨Ae‡èÿaO“Dzö·Ëîîwõdú™Î ´’ý¯Øî”ÕPa#ŽHÓŒoª}ÑO»öÏò¬cãüÓoéì›ø ½þîÛ3üë§¿c~™>;ØêQE3—„©#ýÃÃ×Ã}ŽºÊÛ/øñj2bÝ ¤×_äóõôü]¸ž«rÕ>Ê¡½þÔêGñ±Êçä ÆŽßýRLŽ#{¾Ýå0öË·e€îü›îAÖ(×þµ:d)z³ô‘ëÍΈsëR±ßn<Ûõa;HÅ1š§nwq°Ê“Ù÷¡5RË?n;ñ«oýòCдw?ó¯Iù¿Zç‡<ŸE,¥ç{×ÒoNêaj\Œ2œÂÕ…pžŠ LsS.ÇÝ%FN¸oßóBü’¿YŽï•©z­±ë–sÈ­è·D禯wn¬Ã*œØëˆ÷P´/¬cǽW`tópBÉܨÍX€_#¡ñ©è\|ÿuüŠyY~›·|ÝÜ|ý0íêp8¢œpCn;ñZƒªe9|Îo&ŒËôè2çë,y>NGåÎ^XlÞÉ)Ö,pîÓ›I¸Œ¼ýËÚ·\gןƒi¶Úgb…Ë~®Q&ªÝœ½Ü4á¶öàœ¤O…ƦÓu`À'ž<@ º$€Œ8ú°ˆü¢›”éjå7ÐJ[¼Ãç\«ªÜ-¹{†9‰O=Ž×½wtí¹JZáõµ”<¯o€ª|lNV½œœÄÞ¼~­.‰ûàg—Î/ö»?f£{ßí:ÔV¬éžÓ®u(É}‰·G mÛßP;bÖÜòçý~êÍþƒ›l™ý•½x{æÕd¥ ?B–[ÒÚtËé: %¯½Ù¾L òê3/Õ"º'÷B¢´ 8Öž6™Øí,·](âs¢z,ÁJ\ëœé¼êùQ½À9X»­|n<_[(׉bòPAÁ(é®"à8.¶’sµìÀÊš™]gýÙ}}œ«ƒÝ—<î¯ {ß»¶^šKO [Çë|¹è¯\ü›%šÄßÛ‹®TIíò7vûE}É„}ê&ÿ)S93€›£ûûìúJYÆK®ªž…N©à<+9í×oıW˜Dâ†ro…m[bènS ¸îYcÇnY>´T z·¬£üÆôÆ:V©O½çå™]é²V%жqÎë×|Ý_~ðßÇÝÑuFtâh°§L뼘šŒ•Ó’éù¾„µ¹ þ¿ñõ¸ãœ¯²Ë|´÷µ MýZ ëå~äo•SgGÞgå߯æï3÷ñkžz¶GQÞ#Ö´wºüÔDÊoý›DzbÄJö±í¹G7s·,Ý~é+fu~ˆ›Ø÷l=sj–ŽLúŒ{X¬½ñuI]Þ s-ÝŸ…Ðm´îÈâô´·*Wõœrµíˆ7ö}¼=ÖnM§1¹ûÂooËÝy /6PÆ dÀuÊi0~7}—‘ ¥¥ø;þò -e×þçÊÔgº  7¶w¢ÞŽå?èôªè'v¥é|£_BH•FÙå‰0·Òh¡ñÏtë²9…eJÄ@…….5Î Ý}1ÁS‚Žé»JØ»ÒhUñÊñ$jŽÂ]|ïÞ1SÿÒ(68ÚE?=ï]®wdVé±#]oYˆ~צ­(ù–vË[‘MëßÕ£õ°¾ %!í©an]Þ´¦¹æÝâWºëÿUZHðîy;ÿb+s‚Œ4 mª0L«'/Ð3@ñÐFžIR›cít1 ÕgW‘«dûoÔ<óR:vŠZ7Hèõ ¥¬¼Ê¦Ÿ‚X‚eþ6Ü o– 5±ëä.òéÉòÜ ­âžöùâmñ“·[ìïßœ>•ÜR.ì´å˜Xi‡ÖÉ™e’HƒÖ¢§mn|Åå¶…\€ñ6x»òy+-‘ýæ÷¥È”Fϵ±B„ (¦UE.íùäe/IÍ{ ª)fzÉS¦9w˜[¿‹9¯ÖŠI$™Õ‘xý‰£^RwÔ™ÊFYž¤Óg¡Í‘C{àꣂ>©˜Î…¢$i‘Póü.ifîS#°Ñ8J=Õ*§Ó4Á¶éGuuýGFÃÛI¢‹ßæjéŒÉEû–áñÎ¥£ Q{a¿Cª¯§ƒíyQ8Žn¹ô˜èk·é;eF_|áúùRM¨6_zp¯Þÿq¥ØìµêZžŠjžnuœ@D§uN œÞw+z§ÑÛaý*l곺–¹<¦k“ Ÿ¥ýy-ù•4Þ´9e¥¥•uµºJ'iþuÛ+£Íúá?Èj®1Ty=LÔvÂÛAq§íŸÝ·tB^½=Ü—>…÷†g³g°‹Æm‰Që{~tjPM·/8j²äÕ¢©f¡JZ»è–Iw.a—ײÛ]:ÀOÓB÷¾Hý,âOvt¸-'°ÒOáÆüÛzq¥kâæëŒ´"ÂTYô /Ëûò~1pt˜ë‚&/ÛèÛçMh¿O'\ÛœqY«IlÉúÉrß ~gÝÎ.l}»d2»Ž‡;:xÿSÁ4Ï”•ÞiŽðšqØ('q⸚+=öÇÑàìããê0ž3ötèn½óÈt è±>ÈkÕe)û)ÿuVao+}¨ñ7,X,ˆj¦uÅÐø·m>6_SÐ2‚Aðô  LZ¶_¨pÆ7×Á?ðýS~åŸ!õ¯ü®Å5ãO¶‡L“á&X#í(Ü(@D;„Ò@ 2–%**wž×°)õp_¦ÂŸYôè‡.(}t>Çë«î F×ü)û°@Oòÿ‹à]Ùäõ'ü„°WÌÔWw}x»•ƒ3VÏù}u¯õ×]«%Óöaž¢?ðÛ¯ênv?·þ4ŸBú " ¨qN €3løoÑNú«|äfù#€DÉе-È¥}ç¬Oƾ—{ß’#³ÎP¶”‘žÒ &²ÃpbšØ¨Ž"Ú0 \¼ïü#«hna™j#·!„’HI ÆK»Œw4Sgg½ÓqÃvbܾ֛¸L-{‘ ³ ë •b‚ÌR†E®â9HLŽÕ˜B°[B.Lú“0c8|c3Ÿ¶Éí+óë6î"3v” 6¬›qd]º¥}lG*¢<#Ž5ò×1Ò5¼ùòû>_AÇ mœ÷„Ã%Iø­ Ø—õ³ÓZN¦5ñ«åúº’×±\ÖÉ]*1¯•m§b¸ h ÷@¸Y®M˜›m6Ób ¤ù‚ïˆÓ9Ùmæ‚ú†(>Má‡Òþ`ÞÓýíQaé ÚXÆ-}ëF©m»²¿üžiúÏ­×Û:ÿ9=>·#› ¿2u^û‚$$RE:2¡v &VÖ°ê~Šzq›çßÝ3ý&n¿„>Ð(¢ªXHªn³¸v§‚–4`€—°Áá3ö÷â×l§UËÞ%¶ö8ñÒH­[|åÌм§5÷.ò[×xêÓÇõuåšü—>z7Ôí“‘ÕÔª½JÝ:á‘ÿ¹M?Œ§£‡Åó[æ_—¼ý­!Ãêiëëö½×»)àÊNc}=n‚/~7º×câxDW›øGÙ7ç­mé]ÍN;„Ka~£rWvwJ_°ÏÎýª ñ2Ó%º_~³~ß>¨€gÉBŒ)ïV8ów劷Y|ÕË Š½­ðV÷«·“¿»Ò*íê|‹óÊçäî­`Ô¾Õû_äÆÙ¿¿ãàK“ƒ°'ø¾öû½O[¸gýµS·µÒBL3úzËxÎWðô¨z²“°–n¬²·æ;“s@®®«Aëê³4÷{à»Ý¿8Òh‹âPëýwB˜/ Í‹îþ®|8Do-¬'´f gÈJód;MD˲î!ËxºTåðR!€àaÏýëîy_ÞÒÖ¯Ê/–ìDF3ò}nF^~*­¨‡>¯±Ñ…PüŽ„)ð,ð þÿ’”¥:ì¬Ô›L“jøwš+ÓôäâØ b(ص6¢ýÌ_ú1ûbŒ¢ô"öpÉ$ºi"öß0¾šz·š0©ù™WLÉÏl¬cmŒlvËk“Ìç?`Bý½ºŒê ôO«ÓñM˪¯ß_û¹nR²Ñ€4ý&Då 'åèÈ÷GýFåË+Gá ɱ"€‚($KBœtÄf}—pKêRlŽ*E2‚ÿ$¶!.UÈMËÛI3ˆž Øå>]õÍ2“Á™$/W°Ÿ®íˆ;Œþ›~œùu–}n¢û_²q/¹s%´§áÊ ˜Y³#„ i®°92ÕHÑ ÿ Í•œËˆïž4oþ/ñ8zùíåëöñO¬Š¡âµQ~Nž‹~åÃcõ!¿Gôßóÿöî6ø'á]ù6šüžO©Q>ÈÙõY"Ä,û9CïØÞSeþ”¶<Î÷ÆÃÈÕŒâ—ô™;>hv„G¯_A ÂBFB1L•,S1©LÚm#e DXÒvc#HYrt{IÉ,v¡º_%ö¯Ó~o¦P­üQËk4Ó|Ÿ>ó<:SP¿7Õèî®k8²˜ˆÅi?¢“G;}SlÓ5õÝ:qbíy.XiŒ\ „OhÝ;UäOåߨ·Ï&‘²ö"P‚ ¡I«[Wò»=ÄKbªG.؈öbs&cÊëkö{œøaX)å’ñWU³¶1½R뮟›ÙoòûŒ¸Æ?¬bÿ ßgûx®?W»«ŸüØû¼ ‡ã’yG“Ï:~=þÿĈûï¥N±ý}|GYê·HêÏ/P·ãÏÙöcÑÝ®éøQ§òkh hÉèuhéä;’ò\y2@ô›†ù½«†…:¾²…*©Sz›/3?>_¦ž÷mà¾pÛcô>ÿ“ÃÔéGàëôoëAJì=ânÝz×&î¿aøßÌuSr‘³ªöäÃ%˜"Âäõ ËxRVr¨4—ºís”Ñfd—ÅÎrÊf£*ŸªìgšªÈÃAáñÒeî/¬kylöKT"m¤Müìüö²Ų́{DOo߯éÝ¡q“9xÚT‰ÍÚw IJªJ²üö‹Á6»]¹mT­8°Ì7*ºÝg”ôI®šaî«ÕY®§;÷{7N—â[6'§Ñ„á©XÏ.ü„ÞlE¿,˜­’¹XI$Tƒ‹À¶RТð>%•.Š»ôïhÝaó_¥ÉGT 3nõ¦ËsÎ8û¨[/! Óåž$#¸Ó ªì2Ãã ÞÉ›êì–v;wF{¡ìX^Ï »Å¶kC°2›Û?ßê~tv'wW<™ô÷NJnä­óßï[¿$·É¢.½¾>¾¾›½!Ü)»×¿õ·ëƒ¿ä9i¸¹(â­ÎÝ|Ÿ•ÐêŽÛßÄs¤±äÖÚ›ëßÇ»(NÙåÏã«K[ͽÍûHè6ÛÍËHK "'­PI]Ý’ö9ä¯áŽŒúSíé}cØnø•aw¨ÎÉx[¦ËÔ©Ïò²aU k¦¾NËíeî\tÛD™Þp]Æî ˜Ís±O®¨Œ½ôÝ›˜ÿ& ØVì•VmjõN‡gö{½ËoXzZ3r¡}7M\¿©½ãæô9ðGOƒL…\?Þ³."NÄŽKÁ¼lp×. ½ëìÛêémß°ÇÓëOˆ6²ëÀAýƒ¬Âji¸ùÿ1°feȲy {Hë½·F;ßßðýmæ×1Ãêü2êd°¨aP!GãÙZ]41Çcq‘¤yö3ü]hc¯“œ¡k#:Œ7‹ Åú6ùaWsRSˆîÊ»/êbŠ’™U§Sð¶”Õ*¦7kL‹n«-y»Ó–å“@qy‰™Õc.WDw-ÍÀí{Böë§:!×ÇÒ::©“rjµ£Úä)öÓƒýd¿ƒ3ïÉá"™XdCëöA<—ùó,¹7u_iQøO qÔ‘Ù•°¤Y€-z/;8š á ™)úRÖd Ê‚(‚ 湩†Yó|~©çc©¾o?E­¦òþ¥UÉÑ£ïî-Æ{íµÏTªµ­ˆEU5o;¦ZÀe}À/‹['Dê0n¢Û§¦«©ÅV·ÜfTè$ªÇÉ”îÌU¦LuNòM¼ËÊü4÷u tƒäS«OV˾énwTâ%¤X²" ~ûOgKÏ™Ûj 󕨏ë\Ÿ–zGù¨¼—B—?´½–㪢­3gJhÎ̧gݴ‡>M «eŒ¨°&ƒ L­¢÷]{"ÞVí³¼*ø ¨Nýð£›Æ:ùá…PÙz%ÔkùQ·šeíK&Ø\˜TFÚ–ÜoÔgçƒN‚˜ÉÓá„h¿ .cy0i§èòúW³O¹åS';§Gäz~oRº[7GÀ§Î¸o´œÌ§©£—×ÑQÇ™«=‘™¤…Z±µ¤‘ÆîÉõ‡UTÐÑW௙ç{oÜ¥¸Çß#vßS¹é¬z…ÔMOZ×Ó1y¿š6"" ›{ûTïêáZsÜÍ× zš ÕÑÀ6o—C±^EL—,D|¢ïóù9B§6Ì_ ìçb1ÝÌßËÛ=ö@dgo‘u^g¨`¿?8OßÀÉ̺²BOW[—4£yãòL uœóÈÒÆÔ±˜¡ƒ‰áfÇlïÑ–ãv1š€zÏ#*§1D=F÷©úã¹ÝÛzƒk›‡‘†­N0›ðÛæå¬uîf{¹o¿CÎ-i­®ÅÓÁaÊhÛ±™¥E'¶zÿæ–1ÅpýJ1–õñïâ’Öud²vô8i©—N¿™³;åq;lÌ££nÏ{HÛð4îé._åê³7M=aöøU1O¢Þ°Ë×Õ×)Ìd«Ú""";òèü±l`«Hÿú¬wyo=‘•CvÆ….2:UNQ›M ˜ÉP¥o®ÁË¢ež¸–÷2¿}‘}:3ã£>¸g{ó8‡‚3Q¾ÚÖ<´ ª¢*Ö\Û°cHH×gG^k.ÇÃ9·È;ַ߆DΛžÁ¦ƒ5Ó5dØ(Þ¨7šÌ¨]iC¯ÓÙ¬»˜Õ@ÈŠwìâ ‚yãEi^ /~æî†J×é×çÏ"­„ÍxhS³·yWµ9Ý9¼½Å=}·à)Å”v±¿UÚ…^cty2gQÛÅ·›È}ÿVÜqÓa¸/†MÛÓjtž–yûWOÂ{ú£Š™lˆÏ¶^·™‚M m½r5^9¡Ýßòè"oT·y¾G>ÞÑ iòp8úþ.\£K †¿ÒÆ0X꣣õNÎíÛØG±‘¬§»°mýL«— Üý݆u¤oÇÆc™Ó¤ê§„š÷<¬KríÒLûô£2i¯Î ñOzåí0LýròÛ¨PO,ž-Ûɻޯk0w¨à¥`?2y¸‡Ó¯ªNiÑ…NMq<Œu¢‡Z'>|°†}—S<¼Þ½þiàŠÛÙÀ3M$êW9¥9çÅÏ‚¯WÓ,βNJ¾K–·œó%ânëfïUîn³O>\vs€ÍׇäW¯Ïß^O†Ž›jÙñ‚VMÞO!×ñ»*vCc×âÎl§gسŸ?{¡¢¥Õ/ìí^®'”ºS2§¿šÓšýU…AšÃ·ÝÇÝ=Ä•¦qáðÖý{nvSÓ+fÆüàæh,{´Í{»½}Fî†Þ†¿³–}{$¶TV4=dªeç?ÎcßaÆTêL˜=£¢vÛ·ó×XÛr³,ŠBîâAÓwEØ·<òàþÓíŒã3¾¹Ù:ÐQNíÛsÓè;?êT<Ÿn«á×ðvBtÒè»Õ•‰_Uõö5t cΧ¹IŸº„ ‰Þã>†[ƒÏÈ| …EUQzëÅ2nÁÒ÷êâoz…ÖñÜ}‚#ó¶Ü{Ö·sÛ¥üñåíâ*[è»÷÷ðÑÍü7ù¶¡Ûß—W/jqôøoì;MûãK[l¼cÀ“š5w n¬úÍ6òàq´ëËÎQå1pq{O'L»ëgÇ»“{Ý‘á7ÔúÄ\ý—ÉHû-óâ~[|¾¯™¾æ>µ¯OgÁÇŸÕ¯«·ßÜe9ìúqêOŽÒãÌM/ÁÝïœS.Mò+ò·›µ{zã¯gÓ†øÓÉ\¶ÞþõþckŽ[·ç§Þ·`xÍ뚬pÆz~n»Žªl¾›|ž½[_ÍìíãÝc?«ö¸y67ϳ¦ívõuìû÷tÐܨ¢ùºóå•P/k6mYw3ÿÐÝÇÔù O¢~¤üÒy"ÿ;Çι .lø{Fy<˜›–Q”x¬@ªê*çqot…šÌ\ ŒóŠÀ°DÓÒ½ñ|…Uöù¿* Ómo~ÿª½yõô‰ððíîúÿ'ÞÎWÍ|‡Ìî„!#Íc͘ì2Nn¹MÌÅDô¾ëgG$ÚÙmY³Áã0H°n_N]Öí⟑rc#½{¬À~câ]x_rݯK½7ÏštYà6›û€ôúìEK]Sˆq<ý±š-bøŒ)ÌëÝø²x:¸Ùztöu}ÚE^,êDèÓ÷Vµ¤$9{ïaŽBÁƒRÑëvnK%l²»[Û´níÓLÇ_½°½l>xÕþTV{¹ës¢ï™N,¿¬¼}KÏø·åÞ§N~ŽˆyúÎÀ¶ãÙÖîªêÊ¡’¯A¸!‘@ÈYVŸ;ØÑwÚÖÝŽÎÝzë«­£óºÓ_…W§/mú*½Û'5¹Ñ‹!QÙ¯6…£no{Ç‹)F^»nØ$;^n}rwª[©õžº4ìMlýÇŒÁ¼‘¬û3(·LzY×~Æ>žÉŠ¡¶_5Óe5ô{5ßá ¿§Ÿ.ùß¼ŽD-Å>}Þ­éá|`QrèãoÃs/‚-½~Ã7¦y7?}´ óÅoÑzªtXSÁz¶žº'vÔ-AÎöñR!Yº×Ìèpê`„7ŠËeUE4ç3©.üL]]l¦¸µƒœßÌË›«(%a‘L†¿AÞ×´ÊÈíëS1]®¼qD—]®š}Û±› ºâ`ˆˆwWËsÜ©šy‰îù=?”&E|ãï¯÷7Ū‚ïôÙu,uÅÞOÒlbt»wü9\Êø±“t3›åä®Ù†ñÏSæOzWÞ2ŽŠ…Šyævq‰ô/>@¨4Ü * eùýÐ9êT÷YŽÁ’SÍê·ñ÷Õ­Æ!˜ó™I¼=‡,øD†iYníקŽG_Ý>õò zú;ײ®1ļ.o§Ì"®ú\×-Ò:X3zïUCC¨ô¢¹u™ËÑk8¯k ç[jª«X4;;—fkP¦Ÿ\É-jz¿$Ys5•˜âÿ‡\$ºÒ«o¸°rf͉Ù7†ÀtSÀ:Òuù^} á;¼Tç!¶M;.Vã­OÌ˩ͮ÷S^¢¯ÕÏ·³*eËϯM´CÅNáQ2³×MUD:Ô7÷À‰?5„ÑC§fVàÊÁ·&>Ä6ŠnèÙ¨Âã®ÒXv7Wzó[w 1žñ9¾ú2ó¢Ãx·Ô(¬2øí0v’‡Cg<›¾WN%˜ðTAûxé'Y÷,ŸB§¢ŠqÙÍ;\WÛ94HkïÈØ‰†»£çu2ZѨŒ(ØÒïÀ ±¢ëE|CÖϦøùÏž›/y¢3°®Ã/g[öSNæÒ {£*n¤'Ï~ß<˜îÕYÏo”ÀÆÝ‚ŒÌБկ¡Þ"%–sêGNõa1N­oÂGà’åú‹ùwWŽÍßäiT/;Ÿ4›*P¡azíí<â$§¯O#î_7±ôä˺öxrb{ôbŽí{JØnÁ}Þ:†o 5îs8f|ò8«{-؉q’½ ‘d‘îíòh'–:pöt'Ìx¯èÛ2nÖ¶ÃÙØ}l¬¾èÕÌés3)-Ý ë=½vóxžÎÝ#È{;.ZÝÙ¹ëÙèóäa'su*L÷ïƒX_:ž—çëq—œ†hê±äR}ïNG-9`œšáãÞžK vÝù·Ž´×Í«ÚÉM׉Ýå՛×?èêžçötQA¼¾IéÉ‚Vïc¯wiæ–8§J㻳nþçí f*éÛ¦Úfsã=ö;9«h‘~4iã»-0n/ãÇCr£¨*§Î¼×©wÊs‹pEÏ^WË—†èÐ_Yßò¯V6N›øàØï`6Žó©“Xðîí;ÛòàÝšÆ=üÙ ¸NÊΫ¶9õ¿wwvîAÇvóA¾_#óö\7èu!ߨãqãÚÒÔ†-{•½…^m|õôu6ysëÐu…_ÑǤøtÀYC%•ùÕÓ§YïŒk¸ÂcÅ91ª·WYŸË ÙßÓ™çÜn3aE®¹¼ÝWòâwñâË#«Ÿ2õ >€æçååâÖ;kfÖÞEíǸ¡m$OTåÝâ½ýØòâV×ÍöüßgÝYy4»í ‚¾…_'‡W.>Þü½øÏÔIƒ·Èw÷Å¡ñ;£/AY ™–ï1Û‚MY´ng•Áµ]‹j8J­*QÔòñ¶v Y Œg¿4^#O†Ý‡©*©Ý𷳎kµ˜[FMΛé;ƒwF7á,¨ksÛÝð\°‚ ×ÅsKû_ƒ±’ÖaQÛƒäÎÖÕzë„fúEoª§†™ÕJß–+¦Ï¬Ñžì`[äºB[<2î™El4,aü"cÐöTí…âÕu×sÛRë‹E÷1…¤¥F¨»´5îÃê²–¤V7Ù„¢n>Ä““¤oËM2”Åòœ¡ÞCH3\ÖÚ5]Œ;ªq&ˆgc½6wHܶ©GÑVm¦S70š+ªÎ¹¾q©]3a¥š'8¼å#'´É6w›5–×nÂìûï”ã/ŒÌ€†eIJÅE¨½†±À\>Û6[6dÚ£|ïØÙf2TMÆ4˜ŒšÙ2d¹›5Ûv{•¶½*ð¡Ê Õ¯µÇ¦ÑÝ_#à}Ø—EË­ò~3Õ®„mYßl¸ÁHª§$òâ®é9^xW[¡·V×¾êuÉUW37nsñ6·ÒÚ8ª[’“#µt,ªÂ«ØUÍMʃ—T¨ÒxMG%Ƶ À×3SÖ5Å]`c±M”%x"ª«n]6ÒwAOët ¥@ú_M63¢ý_'¸ÍY~¯éŸÓÊü¹ðO‡½<èoåÆß„ºÉ†èÌj ‚ZíßÕé¥ûYcêßÏõRúç;Eù04&Jó|ÛíÆV¸>Yù6#-žŒÉÉþ—õé¡ÄŠÞƒNIÂcS~ϳQVõUܼ»ËGcr1~›ªê'qÊ%P2ø<ƒqT•a½}[:™ÿ5œ4nnå7¬è.zp»ºQW|R¯W|°Ü=ÿœ÷Ü çù[7~ßkžœô”޽¶Ënþi±Yfßet,W‚ôÂçÔX]ó¢ê* Š½î2ù6^ÿ¹x4Ü¥&0ûÎ)ÊñÙ\u.¿ü8ý3pÆ1'NŸx@DO(œºóÝ¿¢àðÜÿ£¶¶VLdvÅÖ·¸èª¦½À’ò¹Â`â‡ê®¸Þ¦ÒjÑtàþiäç ØwA;¯Sê'\D?)x{U¾ïûþ^ï.¨¡Ün9qëïéÇ»WÇo“à¸_7K}ÖÏ˯ԫåÛåe¬¦—Á”»\7©Õç>÷O©Ïk Š¢¢°¦ç-´$Æ×ˆIda‰Q{Û·ã°k¹èO£õàÆ¹Š:3£®|Íü’ê!ñž7û™²)™Ô£¢‹uÓ¨ ]Q+÷ùók·W·cÇ%!ÆÜ*™Œ§e”œ»[Í;¼ÿ#œ½À£mMmá»»=üàNyÎ((Œ­ê*Bеª0L0`² E”`…Jø*D†¸Ò~ÚZCcu§Þºg5 õúJôˆ\N2M›Å^¾êÓÞî~½>ºG Möz…L ååÓ2-dz”=nð'»ÁPˆÀ䀿Ñú58DDCYpŒÌè¼ÎÀÂ0öc/[ô€ÉD—GÓ lhŠìÑEhð-] ø$U–,TL»1É…:¥?E·Œb¸ÈðzøT¼t§î å–Uà(%+t¡må?‰‹´÷Vfá_þ;‚<2Áª{åTû$>ú²B •_K–¹'Æ“Âø e¨ÏÀ W9œàª"‰1øù¾6æ?£­oÖh±ý\áãüü6žÙÃäÝgôÎÚ_…ãOñÙÖ¯µ®Æ˜ÏŽ_ÒLÓJ¬›{ºÏ÷²qYê¦{ðVCûþŒH" ¹NŸÁ´ÂãGBé/-µž¡D…ïãN:r:êÜ«‹“ž¿Ý~쥮Ècê¼ã`•}˜Ùqêb/ñÜÆæç\ŸÅ¶ÚÓFSš":ÄGãL˜Që5n}—¡ÕÅ“FsoÑfÃí7Nf¯½çoo®÷öÛ×ÙOœ.ë¾v·?]»TÉz³ã˜‚È{ÔÑDÙÃKÌø`ä¿VV41Æþg B ±²Ynìꪄ/ƒ°°Ê+é\-Îþ«ZÞö›üáã¤6œ'“zg>Òü/vg«m>ûé|øéÜ™¦•Y6÷uŸ~lœVzéžüï}ŒH" ¹Nž6œNŽÈAè^[k=B‰ ߯œtät3Õ¹q³“Ÿ¿ßºR®ÈcÞðg‹E‚UöceǽŠ<¾÷1¹¹×'ñm£v¬Œ\ñA6DOJéélq¿»ßÙµ³¹Ãß”ûùMÞÿ/3¦÷öÛרÙÕ’êíñÛÙÅÐÉÇ üûšoÙ s€Tç_ñŠVAŽw]|ZÕµ·¥k[åú ¾Ö·ZA0 ‚O¥ ž…ô2üpè|‘TÕÜå…³ËÓÙ;Dvú;§Y>hþýàÿ þ÷#}xüÁûqð‡¼ü}xûÑñàûäj?r>¼zÁó£Û²ä{á÷#çG³ {¡ð‡â|?|=ÈþøcàÞ¡–?~ýðüaüøC÷ã÷£ü£è|}S®3Œîº“¹ïþ4ðû¾ÜM–`ËalŽÀÜYA ?tå¶r(S€”Ž’H…ÂÅ–ióOVD (DtÿÇçÍÀOøCÒóàâNy辺ÇÈ!Ì!ÛzÛYàÖ tAÞÀDzáä<"=Ðv!ã÷B#è½GLDz¡¯QÎùÎÅÀðü?¿í“øgãÒ £ýŠþ†ÚBŸ¶W‡ÙUü9=üËJ÷ýº¿ƒmü]Ø‹ýŸñf±f¥ýËy—é¾ãò|%ãñ¶«´ûç«Ë»}aš¾§[Ol6žL£mzÈÓ²·/Vm­¶ßÓ­5ä[öóÞñ¹­;FFùjê鉊׉fÅ±Úø1]ËØïîðòW†ºæ¾ >I¿f…Ô¯7?Ȉˆøâ#P׎òP"=Z¢zýÃømÄýËÿ ù,~áj™™†Ÿ¾Q‰vºZgÆ&^lU±Œc Í…\`µ­ffµ­lcµ­kZØÆ"# %­/6µ±Œ&1ƒ@32c½ñŒcÂbjñ‡‚ô¡{ß´Î.bžÐŠ<‘ЬCÍ­y‹TÕ‡ŠÃM:JZ§¼9kÞÌõˆ,V-g‹Ó^ªlæ’ ˜1v’H\[µ©j­‹âó{ZÅÞ¯ ‹aí|+óññéë÷¯“öbßÅoO”ogŸø>o¡n¹| dz|µÙ¡öTÊr«ùµõßÏ› É»5ÖsÙ4k³Ï½™åûbß±óiòò¾=äßz½^W‡§Óê,ZÖ¶×µ­kZ×µ¬«fª»ö.UŒ›,ŸÂåX½;«Ë»<‹kZñ,‘{ŒM¢¬N/¬LZ­uÇ–”bn¬Øyqrˆ/–±Â_ m&Jˆ<¾‡q×u0ë€wè‹PD,d QŒ¶Ñ!¤SJÙI&¡ YH*‚ÔH–¤Z…$[Z%""––m)$ª(’‹¢¢RØ©**Š¥¢"~0‘>R"wû–HJ¢'‹Ú÷´Ù[Ø÷ô®Í0®ÎÏ{Þå]Îæí*tìÓv9tÓ³†ËŽZrÒœ«f:vlÓ³³…rݦîpÆÊ§LbºvUtìÓ§*lì®›4Ów ìØì­6G.N•±ÂpÇ Žœ\¹84¬cž2wJá³½+•k–êéŠîw)Ó–›)ÞÙÓMœ9pÓgLc†êخ͜«JÑÓcwN\7W*b$$±%ˆ À\¹qË9a…iÒ¸tá±ÃLrÝnv:c¦ÆÎ]1»³±ÀìÓƒ†Ç.òàDOQ<9p¤ÃŽŽö’;Í›¹Jf``¹ƒAC!.`ª(¡ˆ 0HPKr¸pìéŽ:t›˜åɢ“sÄ6Gœ%&i•>qœb¤]Ù g™Œ8ï{gh›Š9qò¶/DÖ+œÐ´Uìîïl_=Ö]®¶ˆÆ!ç«ÚÅ‹Z"KÃPµ8k»­˜¼‹rÉ„º­ï{UæÖkZׯ&ökZÖ¶ veµªjmu½U8ïLµ|Qjª¥Vg³ã ‹4”±&0èTE;»Î/UU{bøÆ138³½™šÖ¬c÷¬…­kV2ÊÖbÖ¹"¬ÄVEU=¢-R³3TÌØÅQ#Úå=ۢë½–« h…Å‹-Œ*ã\*µí3Œ{ÅÈyrí|QV±k^¯×™¤¡Ë1dµ¦Ø©$«£ZجD ¸&-Œ_hgz‡¦µZÃИ¢—½U‘†±k\™œˆ‹ZŒS 1-$Î/xD„T½ñ‹^ø²cL0C €˜w‹`½¯z¬ PÖ§³ZÊ. _ÁƒÁŒ^®‹8ºáœ«¥ä´ Ã"’X‹gy‹%¤¼KÚ^{YËærNUí× «ÃçŽW|pç:ªÉ²¼­Þ£d”ÙZnù*ÙíOˆ½£D¶+bÎ*Æqß *q!hkÜ[ÙfV"pù£b,ø›Ùðå[ fUÉ]W y»âð+;ÄE›òýú¡Yi¤d¨x°ü"”ÃÈàk¿\ùp6pybŒT{bCkºáRð¬ùJa¼³ZÐ÷0_# h\Y‹^–•°‹SvÅ]nCE-—Éq«Æ(y´Í-‹Þ¢eB%ì÷ò¯7Ia¦Ãb…*ñ‰R¡-X¾1fy‹âm{«Þ^±©f*øµÖfdÅï‹^¬”6 rÖ"„E%¢"ÖÔãøá z½dõ|­”²SE^4¼¼Vù¾'+Á*fÑ‹MU³½ò™\ ¸mr«ÞUÞኾ2¼aÖíkኼ¨`³b¤ÅµAkbö,·uµã¢ÏˆÅïi©µTáKÞ± b±6œLéz»2ã x¾0Òö‡Ê×UÅžÅ× Ð_ ‡´TQw†Ã‹‰adhµ=Çq–Íx¥[³âÐË1ŒU-U±|.lg€¯hùWÆ2£VWvˆ’õ$f„$ܶhùBÙj)I›äe`ÆYTJ\Œdò×ÊiòÂФ‘.ZùB¾íxi¥h¾!bÕ•<Š[˜´es„r*,øÃák|°ä>Lb¯8v¥³XÅé1y¶l«lˆË ؈¶Jï$Pë•ï(Ue6íÉñOx½žñh‡v»Ìbï‹â–JVrZˆ' ɉ2YUÅYï”ݪ/7ÃLؽÚÕ‰ª(k*¬<.¦ËV¨Šº/Š•²Þ¡­3jÄN&±XµT¼EKbÕW¼DM¦i¦`-˜^Øß.\f9â÷¢(ø¾*#Q<ÄTRAž7ÑXÛô šˆª*øA¿iOß@A@7sÒ2}Æõj.æŸæò<œQÇ<¦, ŒdOŸ«YQd"2,ŸËkÈÅ„ìŠ#FÜ)’1T`AU ŒUDEe(‰¯Ï®Ç—\Ÿ"ý]æ÷]Þ½Ù_¯º–ȉZc›©dH@«"Uýg匘¿µ™”lÅæst/©$óÚ”»UeÉâp(¾0»ínù¥»NõÍU,$BPkíž`´zc†€¿Ï€±æ)tKkᘠXn×ûq÷uÏÜÛà@aUxîÔ˜|Žpô¦8NJ ”ºV²u‹ýN+*óeTÞ…""e7,R[©VgˆeèK,ýŠ€@P!D cèñ§0Á“D}0ZÄŸ] þ<}÷O odÉ$Õ*å|íïþ¨•$$?½>7ÔÞÀ4d+•þ,²XU›ÂÚÔÉq³2À²õ„µ¹„އ·+ºC£ôܾõû pÞ® Ç÷}£ôòqke%þ\qGFÒ Gfí`º¶fÒº³tjé¼oYìLË“]ñÖ%KI·ÄÚ‚9 ¡¨¹r½Ë²€œ÷Ð'QšRcYˆ´«¡ó6xÙ‡rœ¢!r†-n °~ŽkÎÉüìöËð«×æ?>cì¿£‡ƒÛQ@dŽ;uÉtÔT~mkñ?K¼Ü®¦>šlãä&Œ‚ŸÐ…Bo›§åCŠC•‰’3ï¨?ÄE¿¥ @KˆŒ@3 ¯ Ž›?LNp€>J|'YT!=:[©ïï»HÉnö• RµfÉü¡þé³¼—vÂíóiAJ­ýl©å—ÅÓ­–d§·3,Z`Á°;Ñh=ƒhb¡i‚‚ñ!Hú,³¼Õ ‚¹ ŽÆ‡Ø‚ˆ#Ûµ÷0ˆ ­QO-ÌA \y“Ú9x}-·;½–Ö@êöõQ/É{†W½ „ÏÕ1Œi/àôÓ¥s`ÍäxB¾xá¦#e ƒ¦JL€G„KöðXMiñ|ÐøŸ4(—xõeî Éúwx¯êú<GƒÉíÌþs©—çó"iöÙªBX {ÑÍ”¯éXœþ~CáC-TªÈcÈ®yOŒZOs*ÅG?¤óÿGðÝu1û ¢£è±&ÎÌ£ÝRA°ß_Äsôq×3‹±tets¤£A×àèãq&¸­Ôhmé«ïõý=™ ã)Ûç²¼ƒN¹3] å…]UÕFÑç%9c)áˆllm6—7Ó£Z4ÝGÍCh5é½a—‰•ÖqX3dÙ,hé¹!G±Ùê²s6Ðë}.]:«M © JMÌ›»»¹q2ºe²e¶Øt¹XÊöëV-Ôeªùý[üÕ8-Õ8÷nìá‡-¡½™~÷Ì]‘TU@\ ]ÒEô^õy>UI–1ßú¹»Õ/š»Îvqû½P "”¨}¯×ßæ-àù³žw‰deÝ”ß7ü5¾Ko«í¿£Æ}Ûwä«g­Ù¾ÑgêºÕZ°ú|s«6D®Z«1þp’¡:dzÃz*ÿJìŽ*gXH‚Ú`¸}5«­ä‘ñôßsÏ’õû,åÑš^ÐUQüèOªv2OúË&å¡]ñúžƒ•¤ÉšiÞ3PáK·>ìžó7Ûu1擟¸®Îƒ¸9GgÖüÌÆ‰íOÌcÑ“ú¦}å ]g};)KÖv惦_•öy·2úoKšðÌ>¹ ÎÈÆ•¦gìlÝkØ*R ]»5–6o'fþrØ:¾ÿß¿÷ýó¢÷Ý>êëdÏw!º¹ '¹QÕ”ôŸÀ¨Tóá«NúªeÔÕíÝó@€”Cf¤$åÑù £¥Ìæ`?÷'.ŒûV. ²d‚s¯+p…}¾Ž©u4 Ó%L%ôý“³be|Õ}‡&4ã‘BÞ7ˆ: [ öqïs¹Ï·½ƒõŒþ¨ÝçöÙ;uÑE'gýßEÐü<‹½Q}ò~šösßlãºÿ1 0ƒÛ%çkrSåÜÊͱѦ_ÒH>l€æ@/VÔn+šh|Ã.<—R’Öw –ŠüŒ”v{„BÜ]ÒÏ(g‚¼ˆý™šfï0œ‘TE?ŒpÜFh£%ª#‚()“ƒ÷¿$Ôz­|ï(6ßËô¿‡gŒÓâFäqÉâKz2»Ù®>–ƒ€lÛpnq+ãŠÎ}¾ßæ4v~Ó¥ r¹jÀ®Œ¸0Òx{Œ6Ô@Â&‚"bÔÅŠá EŸÌOjAîõzo»Fý–-äô×Ì"\kmÄôdâyNŸ»ÃO3Ñ;¼PŒFãŽHãr8IXž>waiÁíh¢dg_*Ô@ª“'Áí¦ ð¤ö|™•úÝmè˜WKdŠA”v¢Gbö·†Þ­ºwåcAý9äæî‘æø¨ëâtÓêk‡E8z¶²ý|xg¯õ7}+Çâïåòö|¼º•EtK}u½Õ¢ xþã>àMµÌ޾^hB ì¿)Þù*z¾6IëTaO½W‡U×n1þ {¸äÿðìÃcKÁ¬ø_/}»qUXUfc{Žû·ÿ>MIåÛ¼ …àf‡˜;ïöº 2·ØÙ‘ÖHY[>0õóúŸg;ü/å Òü 6+š@l¤Â¡6ÀÂqy},Â<èÞ=kH¤%3x¤”ç$Ô´³ª0G´nˆJa›š. óŸÕ=›zÿËû~<Ôñ:·[ç·"ñ,9ßWH–É÷tügê[>î8ö¾Û§-|GŸ-oQñ}´º}eî[üÚöļ·½^>úAvþ¿í}¿ƒ?Tð1¦FóãtßÙí¦Í‘»|:¬ïö|þŠõyòÝä’'5êÛ—á¿/#K蛹w~F³èÍŸê§W,²én£†·Ç—_‡v™m»âÕ#Š‘¬wz4È—óWÖòù¶úò5¯×æÏ]þ_nyûú¾›Ïú×l™vOw—¬áî'Õé¿WK"Ž+ ‰V8îãîÇV»Î þ¾ó‹§ŒÎ>sl|[û×á¯#ûªÛÆ_gg·îßr¦åA²ÓV ópù—Ž[ÌÛ\ÆÞªÃtúcæïö9Û]Ž?/·ØÇU¶Ì¿ì¢úû¡|—ÔòÎÛ7Ī©¦‚{}þÓÅPîA‚Š>›õ3vóäƒÒvýÙݘœß÷ÛüÀÛ‡€î6íI ÷ û²¶ Âao~š½ ç¥Zê]psÊâ‡#™ñq#xZYÃ9ÅÅ$ú‰êlÁÍ'ŒŠv¹ö9ãE½&Õß±›‡w¢†æ¦å£º9)rH@ È žcÉ×ãr» hæö|ãóÏÂ=™îpfìv•îí^¶ƒÝë6várþ|ú,|=ÝÓ•ÏŸ1¸N÷6xGœó×ï·!¸ÏL’òÄS÷“[&¼(^eŒö¾xdEEkƒ·ˆºØÎrëåÃŽº*ªñÛ*Y$Óe ÃMÙi xv·ò1ÎàQñk{ÎÆn˜2hùPâ)öÝÓÊáÕÒDM$`)!8RZO7¡ÌûݧH AÚµyÀ‡Ÿ:^o¥Ò:ÍíêÊ3h×Ê-Àu}3Ä©ãõÝnDü¹§@;ÓL[Ï‹ìÁ˜aÏàTHí=^¦íG<ÒØ¶M»ŒÒý ½´¡lEC+H¤C¦pîtzq´ØlÐb²Ká Á ÈYóäÈN¸ñ™Ùš~ŸÅö«ú?è¹!$*iõéœëÿ§œüØÛèt¥DUð$6è¨ù¾âÇpŸa··]Þ\0®<ÝÈ€È;Zs›ùsX#/Æ*;p®^ÏÚðÿåþD¹ÖÇ_T}CÇZì-`¹q¯_&®äFØbK‰g§»ƒÓZý$â¢Ê~òVOÒµò7ð>\6ag8=œ¦l[W*†UUUC¸fY_;›»xïŒ@A4šö|o7€Þ=Td ÷ñäëB”\›:䃤‹Å¿™èÛë~oM&oìú Ö½öÕìëËÁþ—ÛÝûÚå¸Ûu¾בÍ5Û¯Ó¯= qý,—-|N‡Áéß[ú<œöm´rr±›_&yÐÙËæðdBü­¾¥±û]œ¢ÞãËáǯ6e3Ûšî×S§gê<ïÓË£[\öç«k镼´5’¼W4SÓüF|aÌðö;§9óéþ›¦G ò$òÚøuðÓ)x¿qѽã9/†úV#Ÿàwy;‹ynþþ}ž7Û;æ®vñãH¾¯¯ø<»ÍŽÞïìs ´ö|æÞÞuì<7'_gÙëÚ.ê½êÚÛ—~³—m³ÈÚ<ÏÇ\¼US¯Ž¢ÏѲo2DÉy~ܾÂ.{óŸ1ÅÊòµ¹ ‚ùîºèÍõpŽ|Œeˆþ<#Ꭹúã)5ÝÔfX¿Ï®O‚å‰î]ÿ¸<ßÁÛ8Ýöø^#Ñ[¯Î™×›nìõü8¾{û´6Ò·w>»dWWÝkêc^Þ[Yf8Ìæ§Õ_£2Â&ž{?Rqn´ Âù?“·¡.díÅ7zîâÕžc¿2lôùÝ!  ·sRh{ÚƒOR²µ©iŸà~…?Qû2ØÙ9g鹃Âw)`æ”dM(â—¹iS_BÙeSèg Ø~d!ù›´ÿ ´¿_cïu壎šêFÖ0ü£©¡ä=ZÃTj–¢Üƒ=ni‘ç]ë+Ñy¼ë²dÆÁ14ÇÕP~n ¶}XEÇ>ì1¾,åžã]w† îÿEœ1þTJhž.L3—¦ôõ«®=¿?;m¶÷Ê…²¿1£ê9Øò' Í*¬!ñJÛn²61úYbpgí*ìSÖ«cÆ×Óz³¬Í¼Å/ä=¾ÖHg¿ÓéÕrlÃ+dÌÎ+Œ£Ù¨\{üç4R9‚Ua2|.k?dž³Aua`UmÏò®¶8—4L}j¶ä ÌÝ9"™ib¶‹EP(WºGOäQ4¢ ¡f`yMBÐéÀ¹ŠEoôc‹å#rÛ«»”e½m=q¡Ä´ÄÄfw < íæÄN9idclH:" Š«®ÚuÓ“>üÇ]ãßVL÷ŽÔD‘$d$N®Z*¡{ð¯V¸^_7ÛE[ù…0ùu‡y®¾Sêõ„‹ë?›øÏ­ºø›êíøôÝK‡¿îpë4W?œx>Läàä3G®ÞèqsòçüÙÔdê[ÅÞ®NŒ7n{¿+s®±ÌߣspÞ¾ÝÃè¿ß¶ôù^.ÖO€¨ˆ7NÙ—1ù.Ÿ³DgUz¾$è\¨¬Êà#(j-ëÕëÍ-ò$qlSçºÔäÚÜz,…@×µ5‡áªn+ÅW6œ“<ãÄ•7ΙoXÝeá´ÈÃÔÇÞ:•°€üEb õ`Aý.gøíýO©¥óËüŸd”çD)@h)Ú> …k²‰&« ÏÜ«¤,Í4;I~°~xï=>.ÿ3þö?ƒ>üDw(CPĵå­oZ•¦èµ–üä¢*)kü5H÷,‚´DÀÉ"-¹•Pj®~u„GÛ(ÓNÈ<õÊ+¿Áâ€d”¾ÇØúéc½€ðw„ËIChÛëj†f(Ïùvü[á¿wüat8´k¯/ÑQCl oüë¹V„ÁÀa‰¿¸º0ºÖßž¼šOÖR5QSúÛ›ë ±dÓh7v”`‚ÆômøòÊ6WF\:ú,Q6J7é.ywåðªèéš.(¹±#’®N½‘mÖ%·5|ß[ePOÈý?ââãö>Ê<ï·Û·—ØW±!ÈzZèõ¶)ËÖzAÇ(N‚ÿƒba—/Nù?ßí}\FæîÔ_Uî¿Ýq½q2û0ç‘Ùø\ÝG†Ý±°á´Ç:f÷§®6u8>œÏêTب9&€êe5\W·õ;X“?²ÈC£¯ûš×ÕÿPŠ™öùÜrZžnÞà¶çÛ÷‘6Âá‹Ïñù*þùÓÀ<¾Ž~…-×kw4ŸÕìNoAY~à}Ï¿¿ùÅüÔïªçºÛ×£wEXä¹çeø°PGiÞ<¾°í²Ÿ&&¹ÖÅ „rÏs¢»ÿu2ØßyVa×çÐf!Ìy3÷Û¹ÇÝ)¿Q ‚èæ£z²DÄ×)èÝ_?\KÕNçe×ÐÆÔÄwñº21@0dÀx³DN5kjúåφšò ié0ëFEÔäC7U?åÀ­®O¤ßB€m¤Nètrï&e[ÀŒ.NH²%<L@b#Í0Š«çžJÊ MD(ˆüÕÙ]D®jëøð»ëM­ÆË¹çö§“eœ-µÆªgÅ‹—͋䂪;dðb¿Lk¿»Eå­"&h€eŸsÝ-ùú ¹ÿFpVߎ·ŸêF_Z޾sæ@ÕCïvîhÕã™þKóò£®ßÐ瓪‚k›,ɼdØôççêmùpãöúþÔj½^̾|¹×«ÕoQ§6D·%ëãÌû¼7Ënü4U›ý N8|?ç}?·ûÛÏÓùËÿ¡Ë±xrü½Ù¡úÛn‡«³«·Sogð Çxº¿ÉÙðñÇëéÍö^ýŸ¬'ÏåïóúwŸTSÒ¦í5íìúhÓÜy¼/qŸHëÉï®SÛoš/—szýƒ¹ÔˆvèòQyJ ò%uÔœ€#M0#!ŒŒK£+Çžt§û™üˆµîýÏ™þo—†Mù}VßÁQ?Ý”xrÒs+Ÿ, ]aôVT3GØBØ?9UQ>ãQ>sݾe¹¢è¯š¤kHþ¿¿•ýtö¿ÔÛUS«">3PIJf¨†6BШ(D«(©j¥´®:3è(¨Ûl;~àütgªmþ gØ>Û¥7büw¶íõ‚¨ÛÚ¯+z¸Nklãa›ÒèàB€K­SGTí9¬Ï›FÓÚø)Ýu¶£6fÓoX©W¬Ô»á•É\DÚïvù̯X¢Ï„èÖ÷Ûžg: ;1Î`qÎs‘m#ZÙ†M”³šTÇ^‡‚Œ¥!ûŠäEÖq÷Â\¢„Ñð¶s<мªLºÔÒó|#§QÌA`ÑÊ]®>F»mnð»uƒ8×¾¾¿ îö=ÄL9Ý×w¿–§Kr`ÙSW·S‡:ëkÔEÔíÎø;hì6l‰J‚e”I|³Èˆœ"‘YÂÞ³º„æ’¡ËJYÄÆS;õ{L­õ3g¸o]µ¾Ä¦Ú Ñ8i·#ÒÛƒ·{[í®ï“¾·Öû¥ÇtŽX ‘Ä£7$Ci´£üóÛS›{r>ÇVc¨’-M¦ËÁÏ,Ce_"@^ö&âÉvTUU ”³;ØjýȈ_dÆŠõ’n!µ×Ì£-µ$5B[|ãB›)´Eä¸ÛœR©KÚ-‹ ÅöÁm‘§ ežÚ*e:cµ‘ ÌX„%A¢4"`e•²ÙsH•&UU‘~Ã>•žD5Œ&-EmY‘ìÀ1#¹ ‘–OÍó-jÖÏKá‹:#—ÇGó‘™qâéhz2빱䱼º¹`KÕP¹ ¬•y¡õžÐíÏB¾H¹E÷k2€© Y³¸b’(ÅåïDegµK*Ã[åsÀ4½]³žÞhW»ÛáÝEÙŒcËß¼äÃKn> ´Û%´g%Ît+u2wÐÆØ6vƒ#‹;€w†ËÕ¯°ù`Í‹ÔIuÊšÀóY9VWÕ©[ „eRç^ K³k̾DÉ#P[ŒÊbB³#ve«ÉÆ”°ï3!dJ²³< ÈHÊ·Ãa$4ɳ}.>M±–iêUžò´ØioŽ—sƒ‰@4X«VXeÃ+$Ci°ìo¯ÏÿµÅûßü ø¿¿·ø•¼Ð ƦV m˜5D`òG×¶e$JÆ£G…Hh–C±¤9x8ÃòsrLb¿ ´UPÏÙåç/O°ÜÚÊðIº[GÈßäÒa¸AÀDl ÅK *HjŸ´‘x„L‰ù¢&š)ð{·ÇñüR¤ÏÇ.ã×Áu*¬¿.±M {½¬¸0±4¸µBbË{Ôf!U©Ú¦p£ÌaÉ—/yY‹6å•ÀÀÆè6T#¬ 2 ˆ”(2á P¦VKC^×ZÊ‚p÷rÅÖlµ…µ¯y\¹rå– ¦`À\9¯œ6žõ uJ³c¼îðºåñ:å(#“’ƒº&,ÍiœŠHëEXµ‹X¢†’Kb‰0 Q@`§(ÅQrÆ "X±bÃŽQEÌŽ8Ä–,X(±t¤‘0}òŒŠ(’ä™ ‚ÄBI‹\’ÅÉ ˆ‹âåÂÄ"F Å €PS 0’H’’:0¥‰ rI¹„ÀQ!rã—!0—J½Òà^øÀ`ÁrI!È,QÈ$bä’QH,%‡00Æ.Ar—.X,,,`¢HH,BIH,$„!y«ßÆ0‘,–" .Y $’æ ’X$$¹R„–ÃÆ $‘Ê/bå“£¤áÓ´rœÎŽ£§N:tèéÑÓ0`L"LX²Y-ArÈ¥],::Z×I$“8åQƒŠ.!.„„¡!‚Š,L,–J0`bÃa Á& RQF(R ±%†@ptº ‰„ÁdÂc Ì.] $Áe»”Aw —(.JAa €d– Å0`±` Á"˜,:Y-l]/„Æ0˜ÂcÁ‚ÈÆ.IB’AƒI%Ì9& ”\±bÄììtììììæ˜á³lÇ.¥rì¼»M8i¥”â0ìÒrì8ltÞ¶‡S—]9c—)Ë¥o½JÝ£iÙÔÈ×!Ƀ4S¤óˆ¹)ÈÈ3ƒÀÈ$`ÀÄ¢\‚ % !"\±qË—.€QÉÓ£::tÝØì®ÎÎÎÎÎ:tvvpråŽ\ºråÙN]ŽÇG1Ï‹ `±b¤’IÃ’\³Ø±bî9r‹¶jN›:tìê¯.:néÓ§JéÒ«ˆ"lÓNœ››¦òpÙ£N“¦ÆÍ#£—-4ìÙÚGdp쥻^»tÆ¡ˆ C ‚é!„Â`Á L#–²QP]&òA& ¥ï3(¥‹–Úø³±Ã³NÓ‰»©Ó“©Ðèêu:DzÝÄP£Œ`¸ò\À¡ƒ,X±EÂrÓ—.›9Ó³F›4éÔ6nêŒvdèæjCcM»8táMÒn0VÉd0†ÂcL&1Œa1Œc Œ&1„Æ ˆê'fÎ#†88té˧Nœ¹råËxbå\KQQ"P]/„{–0NÆ17¹`‚Š¢Ä˜ aÊ(¹ˆM’Õ‚åä’1tƒ (¤”À㉄¡A‚K…É$ƒ’Q!.U% ŽŽ]Nï¶lžq=Ñsgh´^V«VO[4\¿Û‰é²^”RgP™b×»¤(‚ "$FdáàD›4Æþ½|·àßñ5jü)š%(دº]2lüÙüT)íÈ{ˆ¿JÆ ½CÿT{ÿ ùü\ÏúÍj¬öÆÃ†˜‡®2"6~ Dn8Oåû1ðü—èz’™ 1‡‰9ò©oš†e¦ÆR“/¢ËP2B®[!ó:õûïš!¼p «B#ïh¡ú==ŸV6AG«Ñ-5‡PïqT~U=\o˜D~oeèþ«z9<פñˆ’¥°¹øµ†„ô~›|µXzÝó)îCkâyÿU–õ¹F½¥?͹|4Öî}¼ŠdC›&Ó QR¥Ô¡¼¬Sflû>×/À÷œß_æx;îÑø_wŸðÿR0ŠFk¢;˜=è€Bc¶ò^^AÌJ#Ù`ˆ`«Þ×/àX˜Bc{@A}„\¿ƒñl«ßr«ÛCþ7ôo™û¢¢ô’Ä#~¿´E»,!ÂõT«[ç¥dë Xs|ŒÙ¼»µ–”ÀëwùÖÙ«óÿ7ßZ_Ûä4h75;ÇÖ˾äMòH‡§Ây]͸6‚ž–K {Ñ] *ä:0Ç&l¸BrMÛçJÍ “ª¥¸ø”ýÑ© C· ÄD¼óßòñ­|ÛêÙ¹Ô*µ¢©I5/i¨¨‡»9% àI‚Ã(’A€ÁB˜0Qc†.@,F*‹UÅUwjuºx–DyÅ)i1‹—z…f-j½™ÁV›ÞÅ› ]ê%æ×˜¶®+XiªÍ®^噬Էµž–õu½±kM™hi½ð`-O†0ÊêËF1h§†–¼Ø×yý_â·(foáôÉïü®¢ð’eêXPv` ?k.`Äêü ZIœˆB}¬(‰TkQUóì¼»tí—ªùõîîÍôKó’÷1%(‰${CI£²žËQƒ#œªt!0eajJŽä[zÔ5«pÌtÈ(Ñ%%Ó]ôAº´Ý¢|e y×}´o£m·Ø±¾¿«þ ôR#ËÃ7¥\Ú~ø€s` °ÆÜî<òÜâùo…°Ü?˜RW¥¡Âl6Š(¢K’%ГÊ ±kÓ—$Ä£¥‚G(Â`±a.`0˜R0A$ °3—Áb À\(À`¤L0¤¢dÅÑÉ q‚ÈõrŒ!UZ:LèÙÒàà@Î4âë×­;úAý×B€•DüŸííe²¹c#AÊ08¤’té’R=Ze<}T}Öˆ@ÝÜø_±Ú}ÇæûoÉÕ¨œ'tDblÙÉ·š÷2âG)¦¨v{Æõü g(Á`º@â%Ã@º^ô§ÂH†L[R³$"aUÛ3ô®µ©Ý®â”A ¥0@NQ”/0Nu+tP[b䨦ˆ*lèÁhècØaÐe±m¶ÐÆXDŽÅã7ÖÞ…Ö̽¯PaØk7”y™­5-8QK8JX¢ $¡RK˜ %FP#3{ÆRÖ\X¹”Hî|b^†ª›M¥m‚ÊA‚’F% €‚Ž øµmZ[EIV*¥W8ë}$HU4”9aKYÖóTPLÒÝrꩾˆŒº4l1S€Ð_ÙÂM¡Î!BÀdQAPR²È¾W[Ymå É*æ/URÒ²Êñk-:¤ <ŒPA K…”,!YVqwÁF½ã¸ãËë^¬Ô½;nœîÝ´héÓ™É3·.V;W6jE6=d8Ë­tµ—WŽ%ä…85Àº pØØ&0âG¬Ã¤ù3:šÃTfÍð.ˆ‘ÁÁ“éçQ,¢¨(ª(¥}?gãÆxË?qŸµµòË,´ , FÁ`Á<¦ÄDEWÑ÷GGR—Ñ” 9ˆä ƒ¢Š˜zý-éiÄP(žµ›ƒZI$ÃÒ‘àÏ™T×´ù,§UÙA–s3•]â§ò]½VÁéªoçN˜&¯ÐšŒEm~§ŒòdÙ âŽÏõ oq!ó^RǬƒS^m!’F~lc “Ëï]Z}¹³x;½þýOÉýoþÏÿ_ØmADBø‚ÇaJÝ~¸ÿ ëo³Hä¼ëª ‹‘´Š4‘G?7… «õ!ýO¯ÍúÝ.ν9ŸlÓ¡À›…Ьp[I"’ Dœ|ȇü:ã{©¿M2hg«ûxTÀ„…4¦o»ÕÎßÇ3ƒÇõÒh1=f¦ïá;zQSކz}›S;“»%öh#fd¤rÍÓC¯R&jÀ , Tqlc[„¹<†~Ô•»ÚEQ—ýV8“t†F£ú‡? 4éoŸ°y4‰Øòª`ì7¿Ì"Ï •.*ô|'Ê0ÌŒ¢¨³LÔÂ9W ¶¤X–JVŠæÜFD»®”FÆ|;o®·‹Q3ákXµ¬Ü´T™'«â_J·mJé ¨ß«–#ÇZ @AòF $”QE\±†/YH(PÈKŒ.`0Y,–(” µ‡-ƒ’IŽ)bäŽ)%‡0P@åÉ$”1€.@dHc%Ò Œ€¹AF$ DÊô…%ÊaÈAH P==©`ÿ=¸áÇËØ4½Y ÉúRÒ¤]V"7í¡õºg—gCü·Qω¼:7TtgQÊ•à™mÃ_ù'/áÛÐýýp1 ›º­0õÏ{cŸcCÇÏï#½ê{>fТ¦Ì~r§*¥cIXX=›q¦íäÅÚ1¦¸¦”¨á6Ñ}ËÁ»e8ÆJ«P»1UÑZyÝœ'MŸË]ÔÒª B„ÀlZ!™ùçþ0ïùþ÷ò÷át†Í÷åÿPDÝSÙÝÜãŽwLâ,õÝoiµçÄÉCõgXìåá;›$Úw45ò¼¹`| ò¼ºm7’é$›I—›Ë¯6I"Io·êíˤ—人ô›²WÇæš c|-7¨Ù¦ –¯ÌÆBŠ¢¢ká~ïóÿwiãÇ_O>,À‰¹9s³. HвóÅ¢i#N£U×‡Ïæ âj\3ÔÑ69 oz£cm7=nzZåïSU‹(Í-i5GǺLY&¥Aª†2ðÜâÈl¨ Ùˆ0PÜKâÅZ ѱ¨ÆV66C2Ib“0²•DÚ¡Ëã³E­ªbĪٙ"*H†›$ Âü^ëpr#µS6Íý[,6;m~£¨él䇨™ç ˜@CMà9tÈtC‰s2REœ4Ü•ˆ¨çkŠÎTq:Tqµ¸ßÙÃE‚ªUвZª¬õîÚFË-*Ȩªªð×ÃfÔ¥•Û#’k+ºÝSi^š]‘x·Lª¥X§8Ù¦J”Õ“­(É&úi²m‹)*©žÿÏøuÙhzü4ùÊÌŒÊÖ[" ÌԸČj# Z½¶RÅ…CÉöY‚·ÝÛµeU*©šžyl£M2hÓ6^Jú~–ô¦i”D¯NÕé¥y¦L“iKç]d£ËzYuxÒktÞW*ªª±UZi­E;üû|=߇õÈìöwüN#1‡׉ vø-VRÊ=eÜä™H…z&N­H Â`€)=gïú.oüþ³ó¶ös GƒÝ6ŠÎª—ª""MD‘I# MÞ_­ÏæÏ¿Îy¯Â·‹ËÙ¥ÿ·ñþ¦ï´ý­pz^CO?§¿~€åÝ)³þ0*"=Æÿ»I/o…¤P½0ø@0 ðhÈÌôdÉŽL%aY*çÚz?áð¾ÿ£Õxerl¯ÖÖ=¯œ<ÿ)í.¹ d;þûV‡6/‡=° õºîîÆÐÚÙsé}GÇû¿ ÏïèÊLÛÕ ÚãÑÉÔ½*)x”ÏhÁôŸ+Çõu㺲ˆH ó?7ï~ÓB[üüФ?Ãô²“íµÅ'-*7Häõ}HˆÎqNª6Ùtª²¾6ñCõÿ‹$ßJcæý•èHÕw35¿‡jyúª³8ªËZ2É–/$Üc"L† ÆH¹s‹Páq†$Q,A!aBÁi-{‘ ‰¬bø¾"•ÚcÌTÞäÆ-x.H•8”‰E‚.“Da®TÓÞ¢l×»Úé{ÅU^/0ÐYjfîâÕ±yW‡f{Ú¹A Åæå®–*ÁMwòÑ{¥^1i·Š³[à3þ%@õ*yUsQTO„Ýøà^|È-gƒÁ6ð™‹s¹^ÚÜÞo¦Þ¬­xºJ±%´$ÆÈ(Ú6õ6óeì¦MÛYË»OÓĆ˜ú¡ÝÂÁÃZüýa¡ Å£áÀÑ¢œ)†ŠßÔX–j*B¯š‚ðüŽçò½¯3oÃs·fó `L¥m`X&‘==Aëø>Ï´^¾Ëät¼œ¯‚Oé o!ú~ ä$ŒúÃ<ì>FªH¤Ì¾aì-FRƒÑñ/ÛÝ]ˆã޵èò9ç3}¯?>rLj’9Ø•µÔK˜šð~¾o«ôª*Õèå%®\Û3ñç4!•»Fe&˜QÍÒ*úȬ"hhm‰|sí|·ía÷&³îf™ÖèªàÉ>C"K“(—$0X™$aDœ0Â@äÉ)rÆ —.\¹tBÉ‚¤ ‚É ÁdÚ¦7WfÑÁ¦íÝ8Ù±Ô„G&JºEì|‰Eà2(’á7¤’Š*pFœªrîDS–æÐí½½gNMò¾ËÕeöÕQ—4܈g´ÿ?¿Éù\Oƒ†G1E9O%ÜÛî¿™n ,¶[]òß>ÃDzˆØ²ffPjœàŽŸ»¹7ès=¼þg6;–Èòf—-u˪Ó~~óX²"UzÙÏ$1lgû8c0™ 5†&1ŒÓDÍ;ƒÀøehÒT4ôõ­i1™ó (3pÆ?üŸ¾ÿ¢˜:oÛ½JÐê7v-òìh"!ð#ÀæƒØï8³5Àœ¨BQEï"a‚QP¼`SlÒ "%ÜÔ)‹M"hô¢Zf!hE*[¡†}ú-QǨQ]ÓUŒ¥ÔY©¿ЈqãÀ Ø.•Œ ÔD¦jÖ‹P`DÝÇ|éàö2Æý37Ú#ºO(¶0 ÐieY‰Y¤ìÖ_Wf…®7â8IcZÖ´´ ÀÆe12î­f™S4È,ÅQDÅp…˜Æ¸^l{¨xG—ãd”Ókm*ÛVf'ÃÛ˜¥YMõ0jTª²¬©¡„4²;·Æõ6UQ³Fš5Iµ4›a¬˜Ò­²•e¥ÊÃZ04X«TkXjJ•TªJxuëc”ï ámøëPÃc=|ñ<®Iœµul©ïÞfÖ Ì¸:N&¦±¨ã (Š2Œ,C]Í4R¢ª•Ö&•Uvo†#118’f”ûìƒs #ÙëÎöz^™³I,’”Ó,¢RÕÖÛk[l°”Š”¥*•E«—mvÛ4UJ”UFío‘p®ÀMƒbI.úì‰ßÚy£Ž{vêf{¾ÐÓ%ê–Ðg9·RÂY47™‰ßÙáÙÙØÊOKE•Ûl­E£jU*’¨Ì5…Û1uÒ«P@ؤÁÔ€JÅG˜eÃïåIº™Ua‡y«à]û€½…Öm”j˜,dQ¹Ñwnµë4©ÊªV³†h/|´û@Hä—GÐÍgEßfx8Œxa<¬ÓIä¾PAD雼 ‚äÉdX„%sL•CEËP.V¶Ï,˜‘3ÊÏïlb×Ó™õ@ö¢†ÄHºØÌµÃy{ï,X^l›ÜbýS’¡*%BŸTLª^ fQ‘µ¤ìëÈ^HÈ¿.ðС9žÎ=ïRnÆŽyÛ"Ã…Ò…ï;ŒäÜ¡å†b¸`ØU‹ç oÂ13Åö,f7cj+UÂñZo18Y7,IBS6dtîœyž|+1zW¯ÇM*ÕÙd\oÞ!Á¿¾È‹gœ\~ß~˜û‡øá—{»üß™æùù_O­h2~ïÑnßð _¼}:Cyÿ&\fG™ü¯ÌçéøP>§pcU»÷ÿwú[½¿ávÜÿS—BBuqTå?qÍÂßze‡Íyž®Ÿ/¥ñyÇ[¿¬Cá0ßñÖ u†ÑÄ~¿×fõ fCf‘ìc-¹.Æ™F,;æ[«ÙÐdÁnZ¡1ª¨È@€^š‡r} ä÷‡µäÝØ5?óçèý§ªX45ÐþæÚ³íðE¢†²ˆYF (HX?úD½B¿éZgìg—èûþÓ÷à™ ¢ÚWá¿Î}ûºÿÞ>…í½F ÇÔ]ÌŽÒ-Ÿé¦"Ø!Án8YÅ]tøâQó4Þ¦*âl÷qUi5¨!¶3f» ¨²Gì)nâñ-2#º?tݪªÊ¾«YánUL+-–ãL@P£˜ ,AE‚Š08ÆJ,HQ$°C[]­”¤M±{ÎW¯6eišª.´`’- z bô ó{—ü¼²‹eWœe1<½ˆÀÕj\Krɵh’1wˆl*ÕʨUÆ'gˆ¼5^meÃMaoF ¬V Õ²xŠ>j.¸›#æâpS•½·nfJTÙ8ìJ1É ÐÎÁwÐÛÝyº©}å¬^x*™c$Ù°á³çªÂÁwh©™‘ܤÂÈ‚ Ò³±gºc´T¢a,¼7©¼üG™«%ÁØorÐdûõ}7ì) tÞu¬C/½’É¿¸vzÁŠ8Æ Ž0<èqøËLÈ9‘¸F6ÆÙ#£8ÔrK…Lj»­ÝÐL×kºÜàë·§.ÝÊ¿ ãùµ^<¾{Uã PjF¥$Œ\w±‰0XÂ\±˜0ƒ†ŒI#‰))&  ”á¼ÝÓvÄÇ«£—.X鎚iº‰ ”¹W.Xi$trÖÁI‚æ(¡‘ J¤ (°åÆ,J€ (pp =ªë‡íæ½m{òÈÔ#øäMúÞÛ®ã&)urÕVµÜáá´L¤œLˆ”O!‘•ê5 GUQðïˆi­Œc®ÔN8&¨Dà k„È~Ê"XÛ2nh18}KmMhµ­eìf;–,\ ‘’km›d\Ù%ÒÃ¥ÀD ¤‡ºtÌLM,Ô-c ÔLŠdò1†7ÙE|LŠn!¦\Ø©¥©f…W%Fc.d±&òæó$&JÛ{»8ð”^­‹­„²¢¨W(¾›(Ê8>š±ŒhcÖB‘Äã»’Rê4qáh8«+“À8Ûj,¥­e§D‰7^fQž[í㥼@OL’†+Ž…µUôÀH-T0žÌÀÃÕj2h¡¢R”í¾à$ ĶYÍE˜¢f‡}‹"p¬8”U™©‹êÈ.d•„.` I"µÔo;ëÆ£K:8À³¦ Ú£$“vŒh)#‰“‹N-`®8ΊK)A“ÚûÌŪîhl9`lžÍ­%•æelRQ;Œ„±sqTc%0¢¢Œˆä6Q;A% 2¤Q‡½­ŽÒŠ(9NŽ2£ƒA–wM­uÆ—/­cQÚl¶²3YîDÍ;9¦i:s/EÌ .dK–;ë&b Ý=ú6XÚVD³jõPðŒ(¤ ÜUsuñýâˆl«»^F"·’1ƒ$‘EÅ›çÌ)ÇL‹ ¦ÁCfR¯Ÿ&ì1ž§Nò$cÓPÙH{ÙƒYf \Õ•PUF#ìoH+Óh ÈßÊË&ò‹âµŠ)mJ’d’\’‹‰cú%†QBHˆ0ˆhƒ¸¼R*RA±>ÞZo«É“°(ššëªL^bÆvYG d Š`ƒA .‡ Ä˜ÃÀÏ BBÒª˜âd‹×”¦"ÄÙ2²‡?GíÐØ¿s7`#ŒýÛ®9>v‹"ƒ7•޶˜Ö™ËÂøµ—¸?;ünkÏä=ŒýõëVWG5º)Ò¢ˆÅ3`©¼º´N$ÁHãŽ\Q‚%»M)œ˜š9nÑy64Ô¼™¢n÷¬UUœœ^ÌcµðËwʳ¼Ž_z©´é¥ˆÛ7ÖZ^-Ñyvç³É¦trtsaÛ‘m4¶j ªm,¸¬U•éà›Ëʽ§Ib“V¶"–®îZª±|^›Àø(½DM÷÷‚i×I·$N“À²š¦'‘HæªZâÚN'fÊ0óðô]}‹0ªÑ¯fkpß<2ø€(|˜: ?&ìëð~VDzֳ\ÆI2gwy:ÒXÚ-p±Ü£§B„´-­»PÛLÞ VÁÅ"`ÜÀÍDÃlÊé¾Wë{>W›æ²¹Ààä ûé¡ 2$±r»'<C *IE±‚Å‘ `¸©I$’X'PáaèSL#˜Bá%È(ŰQF0\£BRJA €øG$µÒS$–(.X¢Å$„¡‚Àà‘•ÕègÄtܹdDˆ³W~I–T9™¦JðdùY«*½åT¶åFÌ0\s2Ç^…ÍÊ*Z¼Ó$ $€î(ãP凤1nªX†¢@ݨ Ÿ¬®à¬ŽÌ…ö7oÔ„7þ¾8öáejC5kßj¼Z%¬9s" ›ŠC'¦/7Gê„ =5œèÒÇYl™3Û4·ÈÑFVðã’/<í{› n8Śąô›ZÖ!J~°æ¼=ƒcbÅè ÆüIèåqž¶qB•VVIbx°›>šzr¥ruÖïs~ûK6ÈZ!q*µn<{ØÎô`ȃ’H(`¤7¶óMˆ` ¦\=wÞŽJ:HÆ4ǃ‰ƒj! œ9ìÞÞ³ÆÈp(àmeX­¹{I{6)ñ)8«'ȱäÑ¡)Ýæâ}v㉚ó´c3G˜kEÐæ:Ü--@QÃQM=Lȉ1ójWDR—43¶‚–7$Ú¶¬X½IFø˜°ÊPvX¢Œ‹™Arå¢ç2ˆ(¢A=TV•-”~‘CÀH5BŒ& 4Ö´VˆÆ ôq¡Œäõ]díÉ×rŒ4©¥j³D†¯· ÔHÆñËšj6yœS»X1‰$—›B(&£J÷€NaÀªY½˜­••‹U·]vòqðí¿‡n›žõ6«n¦¢Z×±y‚Ã!CØ¡`Z5ŠAy ºó0Ã^¤Á€Æ0 ÉÓJ 64˜ '^Axff³/k"év¢Æ¤Žj8å%Š“0#"ëªêÊ2°ÐB[ ë)TÐ5[ºÌ®LeòLi®c¸  å­-¥<; %¦jÚšAsfˆl¨äïàääY•@ò„ × ¸t÷ï¤Ë£Ueä®w!Òò^º"³ó?ÙÎýοì:¾°]d¥pV\iÖ4y²ç4 B†Y@E•Ê0C 2P€zå)*¨V{³\½7*VÒssÁ±b¦eã6Ÿdwdm!’d !‚›Ë! !€(AÙØ°4^Bøâ|ÎϺîúÉæc ev°ÀýîÕå1Sˆ#¹àì0Ü‘ê¨ðQ È£pp6ã~ØÚ­6V3¨ß-á5¦³E³‚A°Ãbµ7¾?/WL@‰¿n¡ˆ/6´ÅÊ»Ë1jUB…0\ƒÎåËM•Žœ¸VŽ]6vi¹ØRðPÉF"ï4ø´.ñ‹²—½ï°V œXf£ Ì4YRKÍ9{ÍÉvek´ª.)­N{ª5Ýn¶§½ÙRø‹ˆÀ4%ܘÅ-õ|*‰†-«3^Ui残o‡{E(_ýWâ©+$ÍWrõ®õ«6â¿$U”ÓA±õ¥Q?/ßÄ®Ö/­ŸÏ•¸nš2æm¦¿ÇãhM@!$ !µeM­\¡xóÍPî•æ4£j6ÅFÛ\ì]Ûž’ÞƒÂ4FÁ°e’‰š|ÿKÙõ|ê•™ÒR‰(†HëWKJY [IøŠ:‹"JHææJ\s"„¢ÆB¹2<’…’•rG80è4ÙÉÒát©l¦ÅJ”6pháÙ\›±×'Jé×3y¾äÝË—fRTÑ ’H\’K!‚Á³-Š[OÛâ”ö²ê~‚ —Š¡ÍQÙô‡/UTkMPj)%"Q¥Š_ÐPeÁCÑJ"T*¯`j eù_×ë¹§^Ù·µ|pÔXÈ1ÁZ#z“bŠZšÕÕH€à„— ¹qNŽÜp]Q ôì:P%’6ÈŠI\a…1€Ýƒ„Lg~˜óË'i£¡ªÑL’•¥ž$x´¥­dͳ 2. \’ÁȵÛ^.‡<²#à˜:Å¡Åí†TL…aF‹6 67$_u‡,[Nê›EªÐÙlŒ[=G 61.‚‘ê{h¢¶ÚÞð2a0ÉŽH°¹Iä4%/©V¾Y\ÑÆ½í{M²nædrK@Ì™x[Gmð Ì* 6QÞH&z¡¢÷¥6„K ¶ú@E¾xÜMž$Ü»¶Úfm½•íEÒàÒÒÒÀƒ6TxòðwòÅæˆÔc,¶S¨¨€—ŽÎjçgžÑæl™<„Ê‹1R¬Pl<›#¥Š$RÅË Ì×[¤\¸š…ÅQÏ1Á#»»ÅêÍw»yVHæ5"(”§%ê<üo¼«…‹†®`$Í›5ÙªÏ62·ºYêR°ÉŒaŠ/²ï&Ùn”1¤¡7›Ã\k=¦Q’GŽÇò7ÝÛ¶,LikJTSÇDJJ,B(¡þC8uWvNŽú!“–.Jp¹{ÐQa¢2TE ÍÆ£lPd(ZBmµ~¯ŽÝ’øÏQó}3Éf 9•æÊ4Îmñ×@éùCFˆ´ÐIŠ6ü:ë ÊOµÛÙ€—ÑqDÒäcõ¸ °_ïZž—þUêsÙf›šÙN5´`¢X, ,¡,ÐO¡¥þ–ˆjYšb­b?´ý?§?Ïm2û_Ê?¸³ó¬™ežÏ¾Í Ýtÿ«˜Ï·«$7e%ãRföædˆ#Óq¦¤1ÁƒeÕ*wàûÐÞà[}Ù˜UHž¹»K°Ý¯7²¸¤­žÖ©µæc\áÙ§˜Ç%˜ß—JÆšW š0¸Y,ê’¸ÅðãÓ©‹^¯LÌÑl-ï6[Ñ ‰q" [uL2‹RË•¬òö¾I(ã4e-NhL™F*핪êõe½í&Âð±l15[3¬S[›-bFkÍTMñt_éÿwùèo<4j2·=ŠâtÄî¼\J9X‹¢HL´yí Ç_^äüžÊ³¾Û^ÚeXÖbê¤Ã8ÈFV krÙZ" Ä%îá/¿†æ¬p¾6¨²,‚Hƒ&àUÌ–áá`ÄŒ‰(¨\¹rJ0X±dÁEPâ8Å\°¤˜Ã)\' 9„€Á‚åË$—éZvm;º‡3™¦i\¹ráÉÙ§L..X’ `±( \$’á‚H,a0é$’` *I.8àㄘš©gv\¨É',>"d²9qÄ“ &H,”¤Ÿ—õÍ͇ÉM¶ "o‚–lÙOúøúåÖžßÇ‚ Ù!‚ЃdÙq=K[ª´¥mË;Û›©C‚øèÅp—¹ÅÉ:4njs¦vDb£j¢«v²F0I˜m­¬EQkª]q8¸bòN»„ÑySgcÁ® cK±†&†˜~ä$r×nˆS ç .t÷aÜ䣿Tè§!q-‡x›CmŒzj i¾¬ˆÂŠ¢†i•˜Œ±’³’U’¿I^Ú™!Qæv7׃w £PžPŠA³æe×NÜy<™è‹hfÔ[y;‡‘DÈÈrâjR BbñcË¢!x(CÖÌe™Û²ò«¥âø×‰;lÝe ŒI ŠZ$Lì%Á™ÿ©ö+Kc\õxÓw—ö¿Æ}¯Îâ«€ ×í²3*ÉAÇ1áõm¨€@+¿°|µ§™íF§:uÛ裶HÀÙH{aûŽ»óÝßsÿsýWåçðú°¢C¹êhð –‡Ÿó•h!-JX¿ƒb³ïZÇ’jP÷â_tý7Þá/×&>.Ù{£ÕC1SE¨\Uí*ËQfŒbÀ"ŽX’ ,†0ICš`ƒæ(.@–Ññ,YÓkX¼Þ®ñsZŒb]‡G&¯X%æbªcªÊÊìô˜Xrö¥ûËj!–¬Ù`±e ,0CæGpM‹=åÉ[» 9%2šI´¥UY³OÂ…ÆKš a1ÿcÏAHFFaE«m‹XdÈÂÅÅaŒ˜ÈðûžýxíN›½Ì׃ÞqØóUtr'&†w#hhc"dR~»\. =hëÓ&íµù3±y;†Îa†w]›\#p5J6Úe;óÚé…Ìr#<‡˜¥yœ§S"‡4.)ƒ*ºh(*±¶£`ÀƒcmqÇô‡\°giݺƷØÂ88Wk v ³i¥ÐÆ3² bجMSCÔÕš]‡$d¡‚L*Š ‰€aABÕ`Æ4ªªWÆSNÖ™hÑ!(»—ù'{±UŒ1U˜Çi±:í9îÛ­— Íûr¬v7Í»£žÅ"¬ªªGÓ|¬H%i Q³¶W¾2,A˜ÆbXÈL!bæ`¦I–)Å ”«¢Ó\™Ê`È‚J: ¡Q4äšiýΙ֫¦tê3þa8£Ï&@P.5‰µ5%e—³Ÿ?äg/£#‡Úéô8×ÔôªŽ¬E/uêr£Q¬aÓ§î9æ¸õÜ|`T{Œï·U MtÁ€!ñ!BgL„Â!„ÿ“ÞçÇ[ç»n÷ÞWQûOöó½wØã C— ŠHI5{={|~æç¡ô‡âv-µäÿ%½ÛAˆwrÛ»ã¾qóþÏÁꎨzσ›þ9öϰEú‰Fßc·»'"<-Žžœ¼0C Qîd”Y¤¨‘2Âö$1R Œ‚°lm¿Ï0E L¬l¢c!0«™¡¡…cµ…ªbÖ1Ÿ¾àB6NÙCÏBØ„-ýŠ h]ˆHRBX¨PŠ˜a  X¤°ØÑ O Èíå [ ½ PjFØÈ°]°X3FÕ;©FEƒXÔÌ$ƒ*b È™üf,4E E¨Õi0cHA¦b„ ÁÔ ‡«îbòú_?'”œº©FDÈ0ðÝK̦LºÒíו/-庥!UcQPk”Ô 11A¦B(B(B(`ÊUP¡J˜×àÒljQ1¬!-nªB*4ÆjBG÷L(bbi˜Sèû4ÀÄÛ†—¶‘0é Ö›ÄÅ…A´Æ„*cP Å…mÁ3ރыF&X´h)öu1½Y“Í÷n$˜pâSÙŠ¨! AŒžÌXkMÀ«¨z¾¿o¦cý¿Ç" é^Wîö;ß¿Úò½NIË™9˜v½«ÛaÍ—Ö%1V³©M†{D^^mw½4Åžê¥QyVw˜Åéã2¶lÅÇ—³Sãù4õˆœ=máËÖ!eêâIxôËÓyf^„t#ÕNŒ$Ë1—±qtò„Üšæf06ëM¶q4Š ¦Ò1TîÉråÍu6su›ÆêÑH‡Ž!®j¡¢8Û‚ ŠºÇ«þÐëô?ÞzåA÷k^f!›ù6Y?7·Ÿ°ªûð[¨MµÙrݪõ·ñß_95-jËžÊÙ¢r…ß”¶” ¬å2–ÎY’úGÜûL£Ò£UTü:açî˜õج€ìgþ ÿ…þKï›éL·)OÕŒe°odÕCôÕ¡~‡õRî®î™QÚµ'¦ÜÏ3a ɵ! YCà…ï HÚI$ÕÃ×Yÿ9ü(ŠoBwÔ#µ½‡Òû\ncñ«ƒz…Ûœ¾,˜~^ãÃ&÷öxËôz5Šž…ó’~ƒ£y?cø/Âz—ÓW\“ ÏW1ð´ò÷¬ˆ«â§Ö_ÔOéX¸.õhNNÎÁãÔ®ùÙÙÖÿÕ®>nz22<’ÞÏ0¸ôߌö{§C8\‘·¶q¸‘}|BòhTï#³õus3ÎÉnQó*‚º³ ÆétxaÍþW5P¥ö9p´: B¢YP>EB SHh¬*ÖM¨8Ã.Ëž¶_$Ú÷~GÃúÿ¦Ò ‹²t¹)Ó²¨g><œŸ&H‚dÏzyóD7ge8fì¹·¾‡@ˉÚ0mìN8Јè¿ìß¹µ’Q9¡ÃвÞeÏhÙ鼟á€_~¸a’h0/k5°¦Lt6ýZ‘/ßžv~^yŒ+5ÎÏ•‚ à0w°P}4¥]ê“_ÌÜîÊ)DC $b1T€ EM¾V"û¥5MRuψr×K)œ§Ž‹¦«ér2è–Ÿ}•F³Ï™÷î?0 wk?ºW@j€@'àDD{Ñè~ÿd ‰äÀ$@_§´°ˆõ×ñ~w õÖf³ÿégM³×V2ì¦Ö¹½ü}ë¾™åº'½¹sÑÔS×›¯?÷?Íô5Õ´ËyÝÅÂãί¹tå¯Íß•n^XÝ1~ž=ÑÛºÅýÍ•{—Ýá|úuç»® q–¸¢©}]²uuÖwpœáE#³âßÒÕ¥øáw˘ו¼îé ÓMŒ‰5¦6]º*góÕø}ñ7ø÷,:½‘»àó¿¸SŠœN§o8ù1žœ®P§[æ.Á£$õçEâùJd±¹W­û}…÷¯æÖ0¦ÿ7S¡§™ü~ym³6ùöã¿áÇ=†¹9;ÁçŒç¸QWņUUccÆç§³~ê|[÷hä§”ƒw͸y¶Oñû÷¹F¸Ëßfùë=Øm7l_¶¸©P¥ï´ÁSÎúE¸\f`׿ð–ø©¯¹Ñê>.{áäÓ5ÉmM$à¥|Lf¦4Å{­ždu?»x׎Ü_ gzÚf;×I\þÙKüÚù~6ö+Ïrq¼~«o¦:ye~ŒŸqŠ…Ñ%Ï4µ ëDZ“:Ó c}Œ{~UÅÔ^Zë{ö³NüX½™ê¥—å¿¶²Åמ¹3sÄG$«7ñf>®çEóõå<·kìkoÆÛ™»/®üF«Ò½¬¼ªÆüÛ±¿šíl+oúÚðöMøïù¦Õîßìþ+Õ»¦½8ãüôF]}?ºr«‡VLü«hU|£o¬©*é×wÍ¿§‰®z5²ÛÝÕ7jo§IxË ÖÓË]­‡_+e]«U>ލ5Ímsæc!s ¬ßÌÍ×¥T†ã[|ru[M—V“»{ ŒÆ½lŠhδ«Ñ±Zºdnf率Á®¬Z~O–ËÓÈÝŸ,Úuä¾Hn,òü·ÏBê¯0ëc­ì«Ë!•³)_yަ=6l ËXãG’mo¢¢4êø~ƒo‹Ž:WK1êÒ…C†NÒÉ[tïúè~@>ø‚©‘â‰üe3A3ÛµÉþ­¯Ïà£øßWù\ãÙdüOow/›Õ—j€B2uçÛÓQA Uw>)£Md)éDLYU4tùÖ# ì„nFDV_N ¸d.ïRú¹~÷ÓÃ_vg)þ‡×öcëû~\ßëññÛDÉT÷ªïçÑõSùß£êø¾5#îvgŽÝÔœöu…OîÛ×ïG?íê_@’'»ýžßønd¿OO…PéÔ}ÃÁ;¸Ó?›×ëO;çè]þ•8ú¢»­‡ËÔÝ\UÙ6òWÏêíNìHþÊÓ³«•(§ç|}¦˜ùÀëØÉ"¨Aì:VPþuð|/Àƒ€"8Žðˆó¹½ †:„‰ !ÙĨÔ µO\‡o¥ ‘Õ„|œ"'‰QÚŸ:Ö·j[+[ŒØ ¡(ˆ"   fŒFˆÄE‚„ ˆƒƒ‘c&­c3lZ62lh¨ $`¨¢Æ(¢Š1mVß·ãôµ­éZ£m£‚#A%A€Áƒ ŒFˆÄE‚„ ˆƒƒ‘c&­c3lZ62lh¨ $`¨¢Æ)@$dDéõõ¤ÀÝ–à8hÂçFhÆê~v<¿•«þEú¼[3îhêe°öÀÝý\½)ÐÔcwwWXu¡Õsîm¹ yt_ˆã¾ÅÚÜÝ,šb"+t€(+É΀PÝߪÚvc¿m·hÇ6n³ yÎðey~¾ÚBŸ€¯©Þ«ïÉïñ-+ßÉWô¶ÞmØ‹ú_?̚Ś—ñÛܾ{î=>ñö?“iõÏW—vúÃ5{bvô‚'¥""‹T*1A{ïL0è 6‚p<PÁ˜2€Ú ÆGPy:¨E|9!Æ `oЈðbu`v ¸B†Tü2á þÁ à!P ô=CÐô=CÐô=CÐô=CÐô=CÐô=CÐô=CÐô=CÐô=CÐô=CÐô=CÐô=CÐô=ùÇøGÍxó«TŒ@c$ì"‚”1C¨ ²bBCS÷ßqÆè‰p„1PET–ØŠ5he6±IµTÊÛ%bÖŠ‹E±­EccTkYJ­‹i ©1µ’¢ªJÙ6´U±m±TkXµQXµTZfµ“km‹l¥’¦X¥$¥+&Õ‹d­©¥«kuµ%©$’I)-Id¬µ•[)T””•%iJÚm«”’”k$QX‚,”ÙL–QZTØŠ-’,Zªd™”m²Ub¶‹Y-‹bÔÊ©˜*ɶ¨±mb­$Q&–šª*•‚, ¶ØH2‘¤”´DVŒü?<Ûm½¿‰å^mø5»á X.ÞÕZÞŠ«Ê¼rÚçßþËe­5dª~W!7Ã(Ìbå1v»¿Mš<Þ8î¼^4o˜M‘×W7wu(9¹Ò¹ÌtgršgwuÕÕÝtÑ;®‘ݹ(”î·1bRç,œ®­Ì*2¥¤‰l ?ÊÓP)T)TDjÀ£e dŒÅ(kµ«kgKe­e«U‚¾ ·¢Ø²m£!lÉe‰LA”EC(4€Ð-k%ETU‹jŠ-šfdHM™Ÿ[jëU½†¤ f#$•(YXY)Z¦!¶µ–¶ÙkY”„‰,J‘"BßÅ~«ôÖð"8¨‚x·”°"7æ#V€”Bˆˆ @ $qµÍøg›,¿K}Óôo ¤œ$^ÊÿÚüO‹ö8žÛò{¾W£’,†Ä;( }l¬ I"’>² >Ú)èb&¯iBeËÝT•,¿K¢€6}!ÜiôU4¨#@D¢G€Ä$î`R{ub7;lDK÷ñDÌ.²"YB€ˆËˆ#"ªŠ³ÇŠ6FQTHP ¡h'ˆ(·EÂ#®KÂ#ÈUnŒ0‚±P8ØAÖ÷,mª’¶«UF±¶¬±“(e!RÙI‰iTVµE[ÚбŒhÙŒ!I$EØY= 2ˆŽ`@JáMÏ'0û‹[ßÛŸy\^ß±ø>û¦y&DöÛh)Jžî ž#ÎêûožàóÛŽ3ßBˆnN²6ϧ¡{ûï‰`Dnõ€>\ &»ýðÓ`8§Vê vSßâ`r„Fèà;»7ùÛga‘ÍÓ”¯Á†ž¢Ü¶zêplÚæ…¸hùš3?>PõÝK¨šñ{—C·`H„!$a$'£ÅUç¾üÍ‘DGÀÐEÁlY€Ê˜ ùS² ž}hs 3ÂŽŠÙL=¥i%È £ê÷ú|…É·‡\{>Ó³\@ÚöÞk†ûO·Ý±ÜAî6gí.ØÃ±;e†CÄu3æÇDˆÞ6} ³`žE%ÝükÒ*ŠY´—³)ßCj‹*ÉùÂb¦œý¡Éµ9ÀåA_§édípªˆ=(´"BGáÀíbô`8ù¿ÞÖ÷F‹Õtéêx&H :–tàõ±MP:` (ý¦þNWûû¿oêß[»êh¸Üž‚„cDZó[þB×ÚÀORÌsaŒ€€¹3€€€’L`«ôB#<(#H,‚¤TÅÍ?qþl[ÄY~AÚ5’Ñ$©ùÚæÂñ6„GÌ&ÔžÞéT‘º±ˆ#¹fH ª° ÞC]KR$‹¡Ýà \MYOŠ· Å"A›Ec%±RXÖÆØÂT•LŒe"Y±F¢¤0Ö‰ˆ¦dI)†RQ‰¥˜É$ ™/¶=¡êFÒÔ¨EDNÉ$sI²"i3!ßdÎòˆ‰va–ÅSfQ¬Ö\‘u”_ÑnbdDÄDûHƒÐÄFâªb‘I! € H € €D ! `H€hHH€Zʵ€Hi¦€hI €€¡ &`H I! D¨‰Q¢%@°ÈDíDGB"‹a€ B#AXè 5îoï· 1Ú•Tm(VÁÍ8DGq6c)*hÉP-E^kÍVøoï>GSÊЂï=y"G„¤‰i ¦I# Â)1¥jÙ—1”¾%PñŒIÇÙDL(ºµB“%ƒ¼›Ò‚rˆ1®ih’%“ŠË‰1—S-S¨!! ’!#=½=<]5¤mš¼î­¨‚•:ÛV@j@HC=ý¼7 Š~eÞ pg˜ÃUE ½&,àÙŒy«`<16$а1’ V,M…"’•DfسyN!C‹³[Ó=z=˜ß•”¸æ€ÐÀ`Ò ù3i²^îñnY -²J©jf-Ô±÷ôÊj壎•žúì—wΈ—É]c,µuY®±· ˜Sù›¤é¸ÛçiR²³¤ÏfÃò & ß%!!6Œ#´¦‹>Þä6(ðvÚA¨ÂHBIBFL€L’b1AAI3%“J­TµRÕ¬ÖBADi0bI2Iˆ¢"H)&d ’i¶ÕKo)OÙ-I-ŠÚò»n¨HÒ’@fSdH @ HˆJ ™!&D³e333$™M4¦Rši0ÒÈÓI‘$’J€€ @šQ $$   „À’f`€(A$D )¤32€€fH$I$€4Ð@$ÙR˜$5TÕP0Ó@`,°Ì0 $@` $’@$È3€L‰! $AX(¸$€­ÔöCÓ8ÐS( éñAÚQr ¥Š¥TQJ’”R¦Yi$«&’JÍ›ZRJ–BY)$Ö–m+$µII,¥%$RF ¤¥I$šM)RË&Û)´•’µII¶Êl”–Ù)K0Ce-”•,¤¥Y$¶”Ú”ÒJU%š -l’ÑS-–IKI“)“d’ÓjË,¤­¥–IM£U”¥$¤Ô±jR’¥”­•)µ%5"’”¥«-,”’RU¥,²K)$“"¥*”¥–•+6Ê•*ª‹M˜LJ¬.-"jkM¤JL›l¤’YK¨«! J´¥*"¥©&“d¶’Yl©*jD¥Q2šLÛ2dÄ… 5 šZM2Rm™Qi¥14‘R”Õ%-eAKII)6R”‘E•)IZ*+$¤ÊeHml«Q;Ž#»¨’S²Ü†\V\ÊÁ•s!UKR¢•E-LV©Ö’- ¶EE•jîwOØTm¤bª"¢’**I(j¨I, `’É$’NJ,É…ä‚W³ÉjÆÂ#ö€€™RÚ÷gépcE„¡Nðûú;ç›a”õ´"˜ˆ8së59ë\º“¸røô»Êï‡×Bí¸ánSÌtŸJæúR„C9ðøè{úžŸ±mÎ…i{,^ĵŽ+N³BÝCä.ÒŽ_íÿ,€—A3jYD BiDDD@:$³ TDªˆ–H¨‰AQ£úW& !U>OÈçiíþ—Æ¿¶>ÓÚÔOfÀükj´ a¦ÓÔ´–“ù÷ýGä7{lxZñòé6û°< á{c΂ Ÿv¢0U>è%I$7ý'_ÅèIŸ¨@RŒQTH¯ìõAqBÀ‚€{”T*üaù_ФHGgÛí63‰ì¾øPÔ \"Ù?['BsäzGÕØ…ŠGƒœˆŽ°Dmid>‘l4NT·½6u/í}éTþÄC²†¸f‘ö¯m†:¬äÜ þ£WѨ¬˜¦™m9K6D÷âþ%‚šÊçIꫳžAÈËé¼[ÊE6WxwÑ´ÍÕü¡yIß.ÇËdé¾>º‚N“·3'ñòVr™±™ø1ž=î¸ýÜ€ˆè!, ‹.sÔèà$0éâyÈeô¾ÔÔ ûyàʾûÙ`jÚ“ÒÏÑû3@ÿ§ÖçÎ"7íƒg¡/¾¾Ó[{H éÄGF”äy'†ÿX¸ˆà"9”Q@àNÁãnøÚµ¯ú}iÆ-üÊE2¢#èTÔ0 I,´’R’K-e)eRÓd²¥ZJKi%+%QÇó {E2C±éžIN2Ö«}Î}ôsÇÓ3ÄEß~ËîŽXgøâóÅú8I‰Ø®8¥8[T ¿ãÿú4mÙ®.¯ˆm¥ö&Ly<=n m% `(ix_Ïx ЂÒ<é¨=ß¾û^Óô?ÈÿÏ¡ÐÙäÉ?m’Õmxl0{XÄ}¸ˆÑñ”@všP_œ€«GÐþϪfŒ*¸]ïƒýqPôã~ÿÊ_Ú €–#pŒÒìð{ç9œT ä2mÄGH4¦V;û•Óo!(Ì¢ ™  AHƒT•iÙ0I!õ7?Wþc¹$Ž‹ Dw|o¬ôš8¡:4s…÷» Ü ›Ð÷þŒ¹ ¯%óçùnBA¹‘{²z7Ûc”žY´‘ 惜éêqⱿ•³Œòi‘ºÄý7­-þêìD}8ˆã»dD|Ú":¡óÁNš€DE(È›3tËßþ÷|WÿJªQ¼›¬«Iªì²!j«»÷´×ªÒq7*ɦCyj¢‚uÖ·opÿó¯…‰èò¼p…LÏ=í»ï.h¨Æ±±V#m$‘IZ˜ÍjJ0j£¬jˆÛTmŠ TU  cbª [Aµ¢*¢¨¨Ô’HŒˆ’‰K÷·;x¶ #8H|# ØDpNüDv !Gï<µeŠ€H’K%’ `²$ °“ŠT$$‘@ODŠx`~Ÿs⨀æPÄTTàx¢ˆÃÉQEg¢·“hUBc¤=AT‚©ë°EQWo2FO,DkŸþ>/ÝÚ}©DQ=Â:(!øßq>›ÅôJ²U’¿í5…ü hNdžxD€\·ñtƒ½ˆ|q‘ÛÄ~Í…_ô?žþ¦ˆÚ‰@¤LƒôƒAp·,•õÿ µ?-÷f~>DÕ%¯ö¨ÏÓà6¡úÊ%£Ëá¬bôàä€)Œã‡ÿ6EÉèz~Wÿ3§ýÿ{î|ŸeÊ{†ãúR§cqX'L¶E,ßâ÷¶H™yD3ÚB,öÚçnÂ|b ‰ãˆÃ¤9çÏø…E•|ÌZÈ‚‹ù›·}ç«>–y{<ôߪ`/Ôía6ð½yØílÌ;1;DK MÿÂàˆœÏ!á+Â@ª„ÀË2€™"Jˆ–1HIûY4x¢TDA8=>`³J ªˆ‚‚:|Ìg2‚€CÏA¡ÌúTS`‚Š•ßoká÷Y´¨¢)~‘êŒÞŸF’šÁváîrSé@ó§æ_¤²/’zsÏø}ÈÈ@„Ý2‰b1BÜŽõ'.‘ ‚Ä ú(ü•m·ý¹¹Ppéí3žsïÞòÖ "Žó/[EôPÜéª'1Ð8/­‡mB¿³=m¢šû-hýt*lÛI=pàpCʽUvƒ£ùNë‚ôh ÇŠJ’ª¡ÇÓìõ6ò6hV‚ª£õzÂÏ¥Õ½ÞŸöÇõJñ(Y„ÜÍ¥à“Â) Ù+…üÒz?ª¬ú3Õˆÿ·×i3™o%î|@î(ÑsŽ.eËOu–ʯø/êgœ€ó"­–K%‘KJZ’Ù--–JÙ*¥5JT”•@p›‘€³â Ï,Ý>gÎs3Æã©5ôô–\ÄÅ4ŠNÿr¹2÷çÀLžG^Š~6Ÿž˜'èD÷9Eìlh˜IÛ_ï°yëÁÿ¤ë®BB¾¿Ÿ2Oƒ]I+tQT¢  =Åo„¤ÃCEFCºt@ó`'ö°ôÜ9-!‚ ¢)‘ý¯ïûîÄGöüâ䓵Ý?_mÀ?Á1 øÐ)›Î=·édDzI$âaSΨ´îäåÌúxÔü¹²ß{-ýÝ«mÏúL;Ó°·’X¦ô?…ÓÎ5)æŒÉžZq{³ø#U<ë( €Óaû)’ó%j&Fåí;a!`d²Ã3láÔ·®8šÞ‡ÒâÓ7ñØéP$´Û·txŒk3à³²­)Qñ:•3ô¼Q¼Óò¼Ï™üoî rõóñ.£uŠÄVûß6b»BŽ Êj=ϯ墚G@ˆâ{ϯiöÝÔ‡4Ÿªk2 .(* ­”ô %„Gn¤DqëÿþÜÑ¥„„Üï|O±+ $‡ä}ŸCˆ»„#ù,¯ƒi*ÒX*§JzÆ‚KÆQ‘!Ï a0ÂI;®J,OÞÿ¯÷ÿñ½÷H8,s:éÅKÛXæ¼Ïddë=[mñö˜^)w0MŸó.÷.¸º'4óµ, rôC, #¼NË ›¸/lEHvw’Ä@¸ª…Ø* ƾÊÀ€p¢ŸâÜ¿Ð>§¸ëÞÍ3$rü· åÿéåpüÔþÏÚÂÿáç/5ÆÀ?ðDGÑ 5Wóéô³Ìõ¢Áù{þaïCPøHŠˆ°tõñÁíÍÇÅ<øˆÿ¶ÁtS€ ÍpÜ"b#T}ªLügñm¬àŸ£þ}ÄSÝçôQ@¡""·*/7K§™ïìÏåfý<ùˆfÍÈNú~€Oã2ìǪ G6'†d†sñõI‚dÕTDC„‡  Bž&J(¢’à àŠ>î\ç37õœSlôè)£ó‹R|%öÜŸ‘^h(|M¹„Ya–pÓд€EœÓ`¾ZâTñGç…A®ëÓuÞ—=²xe ¦qTo|P *‰†…PTJ~So#è,øÄ,:»¥ 5èÚG¸€;jýkßúQÐ"=.¸÷¶ÌkïH{ƒ÷Š!ï}äIë!2ODxé –T(À4öד;Ý>Î-/àï=ôéU&®lrL 9 ‰Qçe`+8"" Ä@ §‘ä䤇EkË g±ŠÝ+Z[î|¢Œb×Ðö£Ê<€Q_!a$OMÊôàšESÓ ¨Rä~˜Dgi>/[ùøù;|Äáò‘N¿BzU ëiDx“ùÕÚô{RÜ¿º+À>¿Â•ò¾¿²&+óž¯_Õf} ýÑåöSOé~wçs-¹®©ÝD˜Ã¶ˆH}‰>“)±øÕËžŸ@Ê~zÜÆvÏ1@!|h ’ä4|2&s|Ë’‹¥ ¢œ¯Úó\ÏÔÂT‘Ønµ 2ÍÞ¦®u g…Ëqe«ƒÙe+ë3=kN߯BÈÇÁü²ÈsònÀQ‹êR¹/÷Š|¶ÆÂÓ`–æt¦pQ“vXùx\z•²o)D!B$…Ÿ]Õ4#Ì” ”Û…9¹ àHxâªu{å}_vKíÂäâ+ó¸ŒoŒÞ¨‚Ü@áD_©þÒúÍëØ Y€€€¸€°’2½·mKìaôsõ!øsââÔœ=l½ßíõX<]gÓÅ '„8**­‚Y "1‘ÞuP[RÂ+H*«(ŽòÙ°…„B©S×Y)÷b +¤U PU@4¹¹ ¡çqnMÏ@Š|@ÀUóâ#Óɯ>“® ÿçMÕ{WÝk'¾}ñ\3n*»wûNç™þ;q0 "z#«‡Î…æ*k›/X€Œˆ ’ À€ ¨ґ³3ˆ'M€®!@dgìüé~ÖAƒ¦2!øþG Ûf3Ã?×`ÈHz/ÂAïÿåA#32²’31$ÌÀÌÈ32’ ’ I”dh$‘!)"D##B$ˆDdb ”JÜ®j·.Z×75®\Û—6ÕÒ H$‘¤‰(М FI$Q€FF„) ’Ž1J5ãI’ŒŒ "I)" YPÌÄÌÈŒ¥Ì†VTÊÊC3 Ì‹„¹’eeC3 Ì["9r×.U·w[—+r»º¹ZÜÎD”‘ ‘¤ &Ò$€) I2åIbæI˜Â˜#+*$™"I$¤€” "DhQ­¹¹ss[\åªç6ÕÝÚµÎZH)"B$Š4IF”b IIP¨¡PjˆÔúH&1H‘CÔ¨|Å ãÛ|·àd¤DNo¢3 €¯ë¸;Î.•@u*€á€ø_°FOœÔZЙwÆæ·úŸÜuùæúÏ€Áûõ7Þ~UĘ­Ý—, mP Pw-aò@éù[µU†.2~;۾ɯ/Ìßwvö=­ËVÛæ¹.X’s˜"5!#iG;1FEo»- jŸ¿­¿RÉê žsµ\©$’OÒ÷V´’oµóã0¢î=Óþ SR(+Á•nqö…ôª±µ’·÷&$R‰”¤h’@™Õª’<¿Àø^ƒÜ÷ŸaûÓþ¯¸ÿgâ|clÀwÙÚÌ͘ךԦÆ9__éK2Æ"0S¯û£+¤$80D@T¨ˆ(¹ÇÀ{œßâÕ}öºþë¡éuˆzÞ¯eiµµ–þ->ô‡(GÈDJI$(DqMæSʦ=ð‚ñÐ<…U  èö4Š ˆˆÀ’I´B¢D" dHAO—µƒÉ`®è’„Hó#„Û&VÁa€a,"7:\¡PO¥OEQ2ýöDÊ¢„ ¾MáwEP´Ü ²â#ÔGNí#›½§ÐwdñNðÇ£ôžô(̧’H™4$è•E4ÐõvCšãX»®]×üyÑkCtªOå—6–7'_JÁ`":‹!á´äÖll7œ‘DwŽÀ§VÅ/º¸|kh¬jJ{_"'ÍäÇvWî«t{þbØáŸožÊ&ÙæÜrúÆ ]Ø'õKlPO]Xû“IO5û}¦NÈyæAïÕ芜ñÓá÷‚#Ÿ0à‡~aÔüuô»ä}L =×hPðEä@F¿iíŠn¢3Ê©*Ø÷ä‡þ7¿¡Á?‹ÚzŸÝÿ§Ñþ·S÷¾‰¨¶Û–¯]®ïîɼêF v±|$½Ö[a$×&@s!`I1 Ê;Ç•EþóØ~·âaªù[»Írú‚Ê (÷»½y=ÁϯÏës¢yß§3ÛŸ;Ty°õö&æÕƒ«öiÔh*­€ž ×ðˆ2'©{>´ã]N/aæno‡ùPUãèßß*šÎƒ¨ŽË¦<  $—‹)BÉ„£ð¤Šà _n·¾iDÈxÝL:ô³|R) w…è’°ˆö¿8Âúì ÈvÉóGÈÿNáÕåç{¥ÓÃØMy³Í´ˆ¼íìNõOI—mÎNæûç1P1eïc•Ãì«…$ ¡ŸÑ±BÊs߸¬ÀÆŒÖk}1 Î§ Ф!r|Í„©ALA$ÙD 8€¡S÷Ÿ¨7yÎ € ·÷ˆ,ð¶?ã*qÝSœ\þÎ…Ž®“æ×í¾Há¤B«HÁ€´P H¢Ó§ï8™“+iT`LxæL’ÏÁ“µÔ#Å­À€@@Ofì«n@@@i(„Îáµ.9¿(R€Ú‘ðß°…š1ì&û}û­fqνU@ª¢ß§9÷ºîZ³×ù ùÍÿ¹€3 %-ö‘¨Ð¯h¿4à `-+tQЀˆÉ ’²I` €²¥#ˆÐziµ@²3—3>\Y7½mî©᪡zŠ39ê9¹Á}ÇSÝ*gî×½_²ñ÷ †‰4EÑ=µ‹„äÎdÆFâ/­Æ2BTî/æÎr>xS •(á!‹ÝîT#¢åö–:¸÷~³ývr’Š}%óojTè§Êðóµ“>[í£Çz!xoNvç¹°|ßÍewHíDÐínTùÒ´z97¨æäÌi7Íü‘g-™afmeDáM—™rdÎ1†áAÁFÿnpÒðÁ –ç 7/¨íåüAûCÓ Ï¤™r]D!Vlˆ¯à»øXznvpÉNœú: ÌTN˜nŒÕÀâm<×Ú‘ªn9œÃ›ªéÉFä0d§â)ÂÑ=Z˜ÏAt²f¨e–z d˜ÆKz2l”Ë>™ç|ç ‘v-%•Ty*ÎZž"Ì#MtsÌaäö¡rÃ|¼ ‚Í•U;³ 1¢,d8@ !kUOd_ úÙ“+ pžå+%[#YwnÿÙö'õ‡Ó’Ui¯‹_;¯yå€ U‚Ú/¯ÆÚõs2z÷„šJ†ìÕ7Š¿? ìNä½3Êá«…ņà+U`²$½Œ+ò 6 ŸüÈU… CP&7Aê4x®F7­!õŒ €£¾Rã9p~zµùV0æp)À €S€@ #2 J€›¬Á` f€†€È4Θ!B Cµ€fA´C ]lÄL–Pk¸)gyù{ ¾ŸÑk•Šv™Õen_P¬¸á+¨˜vªƒ‚ü>¿:ä¼ÉQʰӛœUò¡Ò·ÇP$”eq ÿŒ–ÿµ¤“¿ðÿ¿ÖÃ×ê½®^¿wßá¿°7Ýó|;ŒjZ}?ŒN&ñWð°Êpò±ÿî1jdÎ ìŠãyMªÜÙNˆe•î½ö[8ý Íúõ~¯FßÖK›{³1­® Îû]¾ß‹%Ÿ{=‘±ÿZ!rñWü߃þÏ£,V«ëÿë­Tƒ"*ÿ1ÙÕgÍáÜ‘‘ÒFÆ1æeÎÍ󙱞8}óxœ6{­CÏçLGHÞôÀèÆÛHò*K.®ÛÛÄFz®©ŒeÛ=ø¡ƒêjÌ)|>Œ +ØÚÓÖN¶jMNg5i×#f©Úõ®$ç® ÞÇË&Vå„ep¹O+½ê­mŒës­ÃHäáËt\Nµ™u»«t.ṎLÎ7CI§¾wƧ&Ô•àkZб6„Ÿ°}ýš×ÖdëÅ»ßbâNšË§hñÒ™ ‚ !ƒ$:Q’ÀéBÀx¾E(D·=ÙÔpÎò’²­ÊRù;c¼ÎöqûÇÆAF®ÃÏÀ×0¨‚ôÄš7û×"F·Ç¾éXZC¼ßâ@”Y@@l¿ü{ò¢ó»vÝ+¿5Û¯1Fô•ÛL" A¡¶åü\Á-(¿"ž|³”É[™’i¦0ý±¬º’Ü*•o?¢¿} ªê÷Þ ƒÓC6Ȥ’TŠS©N¨1¢ „fò=ºÁMÙFÄVfz¿üí¿Í÷?û_4v¸gÙìDyU×ß!ÝÒÔñÄ~¯;öó°ß^¶CosöÚ£ê·Ýš¥â¬tTU@Z@H@ iUÀÌÄ”ê\~ ô<3“òÞ‹ì>eu³ë}žmO´;)N6Fš}©'àT"#¦çã™ä¿³n¡O™öV‚ ""*"r] wÄ;ƒè ‡Ý‡»DF‡„ƒHˆÁâöÔøà½ÌY‰Bû¢®zPÑó þlP΢,:ÁzBB!>žQ ª*Œw]MÓ»KM»·]Åwiq–jY.ë•Ìwmt1ˆ‹å»èfó{ÉÜþÖÍgcsçAÏ_²ÓD‡Õ“¯7,ö‘!€pÿWtšÁš³FªÒƳýü;Ì7a?­¡@GL°OeôëÛ_ž°¢¯é£›!ÄnNaO%÷±ý„iÏ~Wá©a…c75θ.ÏLËå£NQ‘¤ùP¥¥÷½ÍtÛLµŠË&2ƒlï~ÛV˜‡!t†Û žË\mÒ6Í|·ìnÅ0î5n·4éJ@h×Ö…-,p½Ý«.9V|"‰µí{¹8ªÔl¶×Ž{­Ÿ îlóŒ¸e…ÍxnâæcÖÙ+kW³f¥'ZX­ñj^”o±·,fC?™"B?!zÄ âb½ "PEÎ!‘B¾×É$.ë¾`AJz‹²!û9KpmöV.n´\\Ë’T>AŠÔeI/•Ÿ#»½ï‡Ì”×—Ym¤ }BJY"½Á^ lBi€êÙÒsë‡;N©V%°Z‡’&PŠOh"0FÑl@A*/%7@ C˜íQ wS—õY„13ŠëÈ6 ±bå¥.X…ϯÚçtÑ1{VIì»|ç ]Bˆï=^ý2 † (uõ$HÛ…­¨Ôå¯Ñ3“iy€Å@Lrœ1éÐrUê]Jœð M™X‰¸ +j¾db«ê5rÅi¯¥×¿Ów}oo¾Æ`[£ˆík„3j›aÈ€NÅi^^}LQ\ Q0Z›DÁ4ChØØ¶n–$šÄ7],wœô–‰Ô¢«A C° :0@´—§àÿ§oävßÁû¿¯õ°P­Qÿ¶>„ÕwWcÎî£^´J«Ér½­­@ ¶Ûé¹EÝMýôœŽziÀBsyÛgšöf2((d½ýuo>c/ôhÉ`‡k_‡æòöîài/é¾W²û¯]î8²ëˆ‰ »‘‘¨¡¢5m ´ª›P/jVþ~P X`œO¢›@"ž”‹ùž ü²t?Ë´=†Ð6‡—µÞè¶Ñ/¸¤_®ËîÿGû¦MšùçIzT]«z#ˆžT²œ‘ ÕÝi¨Õ „xȃ„T±¢_=ßÙeN· ç ýÃmzÓ:𢅥ABÜR€áòBÂŽòq.WR!°±ë÷·K!h•¤«Z‚>|D|¿}͘eäÊéÔmÀ9l“‚v æþ]ˆ9q¬2 ¬*'[k!IVÚºêÚÉ]²BÑ[·ºPÁËÃI·³oÏ£:èíÐ¥ÝkѸ,yÐ7ÈMZ¶¤»b!ˆFíê}Ayú˿犪:?ÙÝó ¾oª™F(À.Š´NÍݽ–$ï…Me 6æ1[ÛI”ꃾq€ %ÔæK¢#trØÂµDzn²¸‚EÚ@^˜ê€ë€""ŠN¹ÎÜ‘ØsPL~?ì6ã}YÍ„ö8»€¡OÁÆ„ÁéRëkòm4Îú’|·+‡ì¿hlMÀ,Ppþ&„ HF(¢€ ([ôñ¼mäÔ›}ÊÖñäÖôn%HÊ¡’¤X„O8}4)Bx7<— |¢Ùm.éYü&gŽáÎL­Bé±4k“'íöl|EÄþÃ%2@„;iLÉ9ÀBûÌÁp i!ð Gÿ¶/Ép*ñÉqƒc:_{þÏç׿²ŒYüÊ^ïâ¿{øýûI©ÈÁ!€DwÍ›jp¾¼9Ö[®!HïD,ñ@™‰í=pÒ$lo»$š²;Hh¥h²3ךD¶,²­Eƒb}4´ov~·³ÚlGSßTa38qpÜá•ÙÜHPnꪣ†©”HeªJ¸Ó€­ð×L‹Œ¦â+G8<ד£)¢Âƒû 1) #åcÄZ.:=1¼„ºDCmaÁ ¥“»ci˜ÊU]Ôy$mXG–³ˆÈ5ŠkËÓnºWÝznm½ZŒ§Ni²2šo4’ÂÛ a²forš£,©´šæ×)ªHU®›®ªþßáûLqÞ!Ãhr¡ð±-Nùíù´ôlÑd#Š9A26ËPe›“6F²¬?¥Ø{OûëÁþŸ]ßòºÏìN?A-ý)›d3>T°âÙ¹}\¿ZGåáraZb0!ƒË§äèÛö?ÜÑœ?륬B`ËrKÃY…ЪIJaþEXHcCiÒ¸ÙF¡dM_Ôæ`™ÚÎ)§hÞ66µ)$•%$cnA56J•oÝlƯì˜ÊW ;©P6!±%$„ÖAiä#`Ø>Ò8Q›ÑÕXšCO!˜"¬Õ¡:Î×I$*ráÓ‰¶ÚcC\Â4Ø3MÈDÖØ­‚\œL´ª«.ìbÅ+«0·OÑ÷ëµgG+%;Œœ—Q†§ùožgâþGmz£§ÔὓÔÎ1ž]fŽêcAËz6ãÝõSñúãÿÀyÈ:ÏÍøú´( £¹EÁPu_ÕêCmê~ï³+Œz›ºöeâWœ½=ÝrR:âLŒDQw²˜\–q–,ÄÄ=™€Œ¬–i¿<±r‚ˆxßm˜læ>çQß-Í&/Ôîc}$WY¿O ³pÎÛ#}¼/Fç+ÉåWöÿ#àþ>úi7ö,‹;*ıjµJÖ$ËÑ›fT6ã8‹fä~â,à®N;'5Tje6Ú …¹E>d¹ YªÓ¾J‚Á™!$1ÖäƒJŒ(OÑ¥“I$†¸pÉ-pO¨¡-D["Ñ%,´¥ˆÕ‹eŠ @„"Á$é'ÆAçmeGÎÇâõ‹_eOQuM[i{>[çìÖ å˜±ºí«ï6ö’ÆÛïU|O#m|>7û)E™T´«_¼g¸M"³ŽÃc›©ãá£Â?ÝLÆâXpÁûÛh!PpÎÔ3Í’RUu‰$*6Û •2É×}[çÃq䈕kš}O _¾ÍNäO˹/ÑýkÞØ÷õ.’WrÏfó¿º=××¾cýa&°ÐÆ6¶s‘¢5¼]Õ 8—RËó髦 ÞkHGàtyXxÓÝ$ ÞÇù€8Q¦ðئ‚²Ž}a7Æ@’B@Ò×ÔùñOgrF6Û]šƒäjëè#êªZàwâžé8Á®ÎÍ™Rd«’̉UQ 2—6* "#€ˆÄt¸ÎTËÏH¯"€Ž+ ”ÝêÒÒEBG—†§´à3·7]ªMlŒ¹Êĵ&Z®T*Š"046ÉmòÒí@¼«¶òûBÊöþ§E´¼<5›3Äj1¢Úì( ®#ˆzó©!,ÛûþÄy¬æc)ÿJkû_Îåý-þßîn‹“ÐÇ8ÍrµSª‰à_"ÀNÕ®èh¼ükw¶¦²ô jL`& ÃH!b =˜-T¿ìCzÙ,ú8i‡i€bóœ'Þû¿å?׳˜Ø1“EÚºúiä×”ƒÆiæC»cÖ.=0ÛëË-ÿ•ý ‘ùk~ Áx¦q&ôߺ6ÞÅÙ Q Ü|¸^c/Ð4ÅmžŠ×›ÄL5Ûh³Å× ,$*2ެ¹®xÂ÷=[ʆq«dDÓz¡uj9³Ë¼¼ž8Ùœî Q´ŽçZÔ‡-cœê°k·4íÚóá·ÀäTL q©´ —€¢µ|`M#$pÈ.®5…l–Ì{UŠd² ])“Ú¡ò-(dª¡(]ïší1k&àTJ¸¹è¨Ê)u ]„¶?ße – Ü)S{ü–#F M\6#X.PxôOƒk}µ§*;è;"œ³‘ò>Y}{à¦da_NT0*š=¡R$¥†^9ÅPK*2"˜ÜÁ¹@œïR·´õ{µÙì{HpR73ÕkOŽíJõ0ó«lZ‹7WÙ$z¥‹ÖfyozÜñ®ï±ÛU —¿ƒ3ƒîÎn2®šLîàü h59¾¼vãò÷ß$ûtŽ˜–pÚ"ˆ‚ª†Í³1kÓ,…”Þ²,¨†õUEM±d¦ÙG;½”:±#—Ø`Vý¾ê‹Úg½F4 ‚*™ ÁYm½ë9,»g«=•.ì¸\p½Ç¬òÊ Õ=6Ôl _ƒ¢ÃºÙåT¨#h„½vñ5Þo›ž—W¹Ù[CõÖÛY©¼FŠCLvã–¸ºÈgÏZbLBøh3`Á­¿=1h«ÜÍ?6.™æ˜úœ :aœ¥çRv#míµ×~|޷ߢt•4Ó9òÏ<Þµzs™Ôâµéì…ˆ6¼üN5Å&ýVE8_z¦Ú?²ª$hÈ–fDw&DÏR‚ßh|*(¨)Á™ø×Zuág.j{TÎû˜Ün~—%«œ§¦Mº×u§eÍŠ2|fì·Z±œâ³Ë;^W&Í›¼g“ß³¦Ö½ev¬¥ókÝÁBR²ü_¼Ù&™äÅÔ\k;1(ìß…LYuT“mšÌ“M1•i›˜Œ£ð$h¶ïáµ™™{',–òÍ»î@†ØmÓ™ i5¨œ1HéžßhÏx\½Üv4G1/!öãË©ç¨s\圥ËQqè@I|C {cTo3ã0RÚ6\çœÎëü4ýyœÑǘæèÖ.»©fýO„ÈÕö’H¬ŒmÁ1WXÑS¬J6–ÄR¿’Q±;ƒ1‘¢YŠ«¹ª5‹[­’—Ž);~#s—ììè¥-ú¤‘KojÓ%p³¢¥éˆ˜¥ˆ«M9•°Ú«dÑ9I*ÖÆVÑpÖ4jÒ',¯ÞÐH̰׼SÌ¥è;™³Í%žf,ÌuÔ\Ôys7h¾¬—WÏ(Šk¹­c\Yó<»_Z©…0a‘ÞY©X­(€U/ø*uÆ/;ÆŒø>i$Ôoi÷f£:"óxíÛt’CÀœI(%!‚‹ I ÿƒ¥ÓÓ\Lé“)¬Èm•´Ñ¦`†Ó}OUªÒ›8s'ó]î÷£Oñó›\;Þ 8rÞ5·ÆIë1´Þƒ½»Íª¶™ûOÿt·µŽ'ÍÝz¤ŠÃ™¨…Ì‘z÷Y C]…º&`¬"ÈÈaÒÞå×Rîµ\š“IŒvBFZMx Ý{h¦) šfD†¾–´êl1gÏé$H@f1£Ž%3Ö¡]VëgÂQŒÈzΦ²ù“^×*S„²Ë»%Y8òùpóá=^Ûe´zÞ;_j"cùíû9*”²$"²!# å]ÎG«+|:ó0™·÷à6CLN!‹ D„gm>W£úgÆc]M„ Ãx{4b{».’(F=8H ŒZ,m!™qKg›Ûù5Ãß×fE²9‰Ö»9XYÈ7ÑÉIJ í!z´a¤BÒš®D$Jj¼Óµcã=þSÚDMäH{,Aº¦agiÐÎ~n– Y؂܎wA£>!¯8lÈÃÔæ ·RÝvÖv _8S”:úݨԌS–LF‚ÔŒ¶ ¯Y$‚Uj¬dÓi «Úù> ‚uÛ(„.Bhää¦\ŒFéä=4 ñjßc}ó)œh2ÂÒ¾ÚÆñfÕÌ%êm¦gaž‘³!æroÛÊÆ¡u_4gŒâqF±¤ « ¬*]C+ü1šö±¹RÍs\j¸Û³mÕerK:ÞrÚò>W17‹D­’¯“`ÊYÝÚòîu!,ë<çœnàÁ»çŸõ4­ „’b†(‡* ®©¢Ê–fb„F©(i’b!µ™‹’^_MÁpãbMO¯{ŽáÞªŠ<ãꥪ3³;ì{Ú¹[—jl¤¹vZ4ÔU€§ÚÉ´½_ÅìúqGG ¾Šx¢&Ö&CÚù*Tµim*Ýš£‘Ä!÷$6öºâåò¥ˆon%-ƒ–.¾_ ³iü^&jNYºMŒ6Ï•úùb²;½œá”vƾT$ÒHÃà*– jmbÛgÅMêÓIY&2'Áá§vo¡ @" §#‹‡!@×äC§_ƒ#Lñà ¼Él…ÍIòVê7®w'D`36>‡0¢i}X`¬¤R–ª$5Îá-î×Û## •ÐŒ8Ð |wÈ9hÉÈ´Æ/ªåžC+Å¡Sf‰)\ÈÉ©5Üñr“Ž%äcñäªìÅ1·ÑÆ"½|œèó;‚î˜&.Þ­Xô›]'¾ˆjáÄ*Ê,Ê‚£ŒHæõF­M(’¡‚ËZ‹g¤*oz«Œ—½½äxÎõ±³\Ϫ’ÑÐŽ—h"ßN]­frAÅå¨ñ·b­¢IÈÎ9ë¢î4Þu›luºi–§Ž1¶ì­fµ!'ÛùÏ&Äq““Ž;ͺ°d"FAqb¢b•$ÌtL´±Ø‚X; -”2ÂDa¦t6Ý0¥ÑRB&pÜÝŸZl¨S&ICbi—SZ)Çñ·øÛxÀ¬­*ôñº™»“õ_]6Öo¶Íµ»H¥Z[Um…‰dø¦s¤tpÀŽ…0-b<@┘·å§F’Øç áâv|.¿$,ºÛ^n«väa’ïE›ÐŒrH«‘a¨óÝ3:u,•E‹,°õŒ÷7ð¸¼Ù4ʱ%‡‹‰÷mT³>E:²”„($>€•L픣³ Ô#w;d¦†ÀFì ¤ lۚϿcäÞðÄ“ï×Ù^õ_‘ÛMYÌB*kí² çlÝÏØëGÍ ñRâ"eD…äÁy’uâÆ"naÔVL6ó•V@D\WÔÈ Gò-+µøy,·¶ÿÚ÷1+eÎuÞúì˜IRÀ]aûUk[º[md³I(¦Ê׬Ê6Í&D0`Û bUúäı€¸f؆Ð÷F7ùSì5¦mé¤tÒ#É…G´#Q¶ü?’UŸj)FÚ1«7°ö÷”×£R”k—¥uEKÓ¶ñxÙ4m¹­£%®nk–æ´œÛ;«’×èyâ€MJÕoî}ù& =xÜEgÍüÙÕ5ß²—Ëñ/³Ç¼÷1´Úmµ\c›»Ù4ÏÜúX ’}O˜Sƒ!ˇyÏÓ-ð6Ê&K,Hyµç»¿´óZy]n¾;øüÊKÚ^×°ôq¸lœ´DsÛn'IJäëðóQÔÀÓÏ+üßsœÊ—®«VýÙ°g^`5Öe íÙ øÇÁË£¼Ôþ“èŽÞ]eç2-óØÓå2ßÑ+7 ð •€ ó•gñ¼"éC–[:̰›@ˆø"ÿÏ|ýüº8sö![‚¢D˜Y0Òº|zMFA´FáE)‘;œ›eK!UG@=çaæûÍHlD‹“DydtÅ ‡+ž–^TÂ$‚yO`£È%á¹¹D†­QŠ…-¢ç‰…¨‘˜³y¾ûì²ÁùðÜ»~9[¾²ÌŽ¡“×0!ž 6’ E\"! H ÃøÉ~avŽü¬ÛÍÊQ²6;ðž@èþ%Ö×7]й¶çßæùƒø‰;Öê(¨–UTVL$ù¢#žø$n"4kŠ)¬†Ôo¯êïÐj2­©’°J<úM–"IlbÅ„Gªë¡e02ŽðcÖ#ÎCŒý 9d¸uäQàŒ‚ok1·/øü½¿êþç…ü>Ûûÿ±ÇõqËê³Å!ãÌÄÚ#¤êŽˆ„çݾ¦êðЬ€ NðkyÑUù„~Í>Å“õÎ숾,Ê~j†,SÖ1T´PRAW¬€ÉßÀ®óó{ìç»åäûˆl“=Û¦¤®k÷ϯÉ3åGO:5»ï®×°ù“¸Ù°Â%ÈÄ!¬¼îW¨.ˆxpå¯6&Áñøs?„ÄV_Ì7CO{„bm8t2Vé´URyu¹GúM£ T¹§1,~EîÅþ}‡vŽ%Š *çŠF‘d"“L·¿*×É5­9:óÍß"âäè™Ïe’I$ßà2$Xø1‘ÔMÎ!µÊ¶üÛ'•¶–WÆŒe€ÃÆP†Ú¢X[ >—ʼnˀB EuÍEKõO_Œ>UÝE?'k[¨®•Í¿o±éß»‚¯läOm®¾(XÚ †º´\á ëUMó„ …°Æe…Ä‘7>€åL¥cfTQDƒ¢5½¾ï‰óyÂù°npÐHM~fr÷I¯„AUÆÕ@!zµ7,*;X›Ae€hÑ#Z5ÅC%èdœ•rÇІ Ø"=*·ªôö0ãËj™ %26\³ƒZª û(©D"Î*Û{¥Ë…ÆI'£[ånô#㛡)·½ñ;¯7”™ù{»Ó¨¨âŠp¨fÀ¦`BíT’QLVAÞ[­â}+]À#Eînù§nÅã¯Ýé×½Ýݤæôøºñ €±÷”/£^bïEÑ=×wÿ~Wе¬øL"i‰!³öB…EQ’@Ed YâiLÆ|ôNvâå†Ô‡/k'å~ÿ?À§; ƒ¿dŒ€¤|ûÝ£Iò{g}´Ü†Û„Ií¥E³µ5)-”èQ ’uWÖ`»·sí<÷ÂøN|]P~Î5B `EÈ«]¬‚4™ú›²EQ Kg($ïËÑo'ˆø²Ðè°Øq ½¥oW?Ù×Û<0î$Ç›ÌÀý)ð#Ý1zQ2‡ÎæÇ†Ç ÏÎý Wój72èâål1ªø²ˆZZr^®X¼û«ˆÇàæ\¯Â¿Íá§#÷3é°U5Wxy~F:¤$‡©>Ä. Ÿfo¡J¯«tRÊšr#pá{õ_°-~«ë·Ý{Ÿ{z×çY(-ŠÅb2²[E´)QZÆÚ1­£chØÕ6ÆÔF¢Ö-cFM£TjŠÓYd«mÊØ£I¨£j‹QF±^¾õú×ý %Ë%TÍ·âd1,´µ­‹õO2i²ŸK\I!£½–ËPùFÕbç ÏÂáƒ$Y B"á,³Ôý/Ô—O( ¦g0 Iô“0ôsž_÷w¿úûM?ÃÅÅýÆE'8öY̪ñ4_Û•³ [ÒYlÙÌ’+„é %œ:ˆ0 ´rÿG4Ĺ p™q,Kœe]^r}䟭ÿŸm†v)ø4Àø:|M›²ç·›4o¢¨à9 (‡™¦•t?Š¥e¸ðA?½ñÆÜ+\ÿ‘˜Êîݳ©Ý“ðh_ïc¶Ilüß¿Lº*nþVNvÙøœÐùþÏë{/én¾htA7vãßWŽ! ê\úcví¶hES\¬Æ3F“nWWE«™ŒÌ™‘ –q-*ëÞ§çjAòý¶HæòÊ­„#V-‹D-‚ÑØ•3Ôúã*Õ^õ7qUT²¨…±7‚M¯ÛcŠûž;Î*f¾üábP¬L«?|ð40ã…¶ùÙ fUÁÎö˜¶ƒœ8á±À±F Öô.Š#Uhd‰ky€sÒV©ø6E¦gq¥ÎHqÃfî4[B@ž¬Õ@Óff(ç:{ Db·×4Èâ)[\ÒGŸ“ÍNQy/À¨?ƒ ²íá‡!˜à=±ípvµO\Ü–_àë*é“îvÙ&­»ÌLÚeÝÖÜ?CxÞ ï›êž¬ÏŒz‡k%x¤ÏA¼%f%‰²%¥óó|~ûùãáQ»æ|ñúy˜sü™Æ¼¨sÆw•Ë %@„;øÝxˆîkÀÄ04ÊHŸÛñœkóÐu‘º+½žsWŠŒ5éÇz*èUÂ+ÕnRQóÛoO¥ô¬c}eÊŽl ’â b´s¦zh|xlldרºa0e&ñÓ’0ªøH°0Ýé<Æ;÷Èd³*JŠ*È‘,:fR•,*=ׯT‚:\¢ï¦K†ÙÙè æTPLÏ\j-§ šv*ØeRª•jQò¾“ÏV-‘ôßùÐ#ø‘]°{‡ÆŸËb™ÐÒ@á,«âÝwK,–¤ ‘%QDªXùÊåÉ9Ý•iÓ%I•S© HB/dsó‹¡Ó@JsíIÐ!I­ÕøG‰9wÛÏA®*–‚2›L®á q§~ hléQñ€€‡ìÄL«12PÔB¢q*2N¯jÒ!rÔ`ÚF0VÃÇ¡ø^GI]üVy³30ç,œßéé.!y‰Ì†6½³O94ŒN:Tr$I8ä`ñv:àçµ²¨­ò’àˆùŽÐUGÝ:³¬™°6‡>…i€ñíÓºG™+IJ"›»wXHB(Œ„!Tµf×V93HøÚ=>iìÑôߨq©# †|§p"‚rên÷ozGÈâÉRCÊ݆BRXÄœAöoÔÒHàÒK€×É£ Û*Å»ì±ç ”T`œˆ’YÂjš×…‰?‚ߟ‡¨¶0øTqQ•!~ËzÐjU&Ë! ¼ÏhÝ¥Ö¹HK†!¡ÂÕxœ's`\ÜÕ{õÌå†b}Xïàp» óÙˆÙF½'{:{‘'Y׫ÕÛ|µ02\jbÕÁœnlM10 çèëô˜ÉÂ"P¡(‘ÓNiôñš°9máÁhßMFY6Ô2èÓ4ÍÓ{ª›#ƒZH$’Êj1…\­ÝÎäÝnÓZÖL¯/g§—»>¬$‚”R±QjÙ%JNÜ=ˆú‰óý°ÉwßNÁV7šð××î7Øó¼mâá{÷­}Í¿B.Î妷„¤¤j!¾د<®[m“Éd0£œ™+¹Zjg§ÕkkÍMì¦~!@•)¬$¢ûÛƒ¦8Œh@Öˆ:Èm™d¬‚`¥ªFÛm·[Þˆ—Ví$È™ÎHÊûÊ2ÁUK19)%úG¿­xÓÓ¸.1!²ñuˆÙµ—¡M*ðíÜÜŠ¾æ»§¿ájó3ů\g§Ç×Ýòk——yçz«êo©ôCÒ½f"-ÍøûË´Q½ß}Þ è¹ŠJî|µ|ßõÚ“&´­¬–™¥|nm™­ÕY R²FŠ2T–Ƥ֭™„¨¥–µhÄj‰•¤k,ɬҶ)4ZÚ¾Þµ¬®‘ˆ£mªKcX«DmE,hˆ±£ûN÷{ÝxPð”*œþ˪æ_¤€ ÷:ÇqÈ`yîáÍá5]G,ÜM×{ªh©$œéDá.hÈÑ ƒÄû;LÙ9Ù¶ÝuÖš^æÚZj–ˆ‰YOÚíd[:Ý–ÍmŒU’kso5Š,¯ Q3Hó‰ UåJ‚·¥¦Åuðm }«0‰ò6¢Þ¾ð"û=Ã¾Çżñºî0=·p1Œ!¿S•é9z¸n®áî÷xë5ܤ’I%RoUe[tê#²)¼Þ8Ÿ>ne—©9Ù6×­Fú¤DÀËÙ“VPBÖÊÁŠ ­'-y®ÁÝ`º£2)RÕÕKZ­˜íªð†EÈ¢8dåålCX¹¯^r³Aߌ¼ |ãé¹ô!ðz‚¤ŽiåQñ®ÄIûpåÚ‹dEZü[íÍGt‘*r$êøqpýMW>FA*íò{„+–Ì•)]ÖE6ìÜw>/§Ï?]p|ÙÄv¡£Zˆça3«2êL–/`ÕWÂëñúÞ·—`)ß1×Í~Gç¾O¦÷<ñônã}w}O—_/ÛNÛãÍõÖûe¯¤±Ú¥©”™YFõ2™´Žêˆì©ãå)m£‹²>ÚÚ“´² ¢/4)ó¾# 2X`@´·ƒ»y¸òY7„ÊZŸC½:ux¼A ³EˆÞZÃkÕ¤I_Á—´Éîò}éóŸÔ~ ø™Ÿüß©_Ë‚¡Iùð+é!x¬{ÖEæå×Çà fXÑ¢„!I‹ó'( °!—1£6 P Úcvùûã& €ñ€*ü‘Â8ƃo¹6Y|DéHpÆÉR©¨\¿zw™Œ|Ç€:ûˆ„ˆàž6R…ï_¢ŽõDA{<Æ!×™5®†/Á •ÝuÒÃÅñi‰}¼—â>xÖó®©óþ`ÛüEû?ðûÿžÇ!æ³ÞªW™¾º{;Pù¼i÷÷2ÚHI*!Vÿ· >‡ÐVÊŒ¶þ,ýŽ€Ò d E8YÚ·«¤-M6¦Temhø7þ÷­øÞï{yæhC)Á£àˆQÞ˜z? HDð «ÌÄé|ïÑYÇÚ†!a¶"va0Ï Qä=F âñ÷8!†sÁ ï}íÑNìEG@:ƺ.bµ‡ù¥½ª"Š— N,Ç¢÷ô]?övÜ~§ÚJ`_ÌÔ{•üiœô~Dî›9YòyJù¯Ä¾J+û@+¤ˆ X53A’wÜ£ˆÉ"C6`DjÒZ^‹‡íÆçÖÕ0‰×ŒJ1€²9†Q¡êZ¡×ä-Ö¼Í%­ciZõít£ÆÖ¸[$BÙÅ’1[ÒNµ‚ض Rl¥¬¦,YS ;Rv°iV¤IPMmMHP6пzôÍ7'_G$$ xa%Vp"Ü‚£zñ(Ýq×6fjÿMQïá®Á£ƒ%ó 5'…(CD !"iZ©^ó<÷õùší"'ÙD‘7“ö*¶:ñ7mÿ|n€®È*›òC5…T:]ÞË·-îJ‡5÷°3Œ RäÖU,{ÈŽy0±­Ä¿UËY·˜„À—´­5~•Q 0=×GDo˜Dr‹¢ 8.9[ "&Ñ,@¢.88BÔXmÑO5¹¼^O¦c˜±ŒÆ)k6~?ËÉðª‡1Cè>«ÊGƒšájS£Ì¿7Mz”ñ©ž¥‰²DœêOô¨%T—|WÀ‡¢2ç›íCF1-–åÇáu^áKµ»½•ÓŸl 1”tuf2çï–5éChŠû™OìPÒ)Gŵd¨–“Œ—ƒtÄ^1Zot€L[k¦pZÁ¢ôI8¥^¡óÑ#ì4˜2àó.&UHÍØÓtl„#"„Ç`ä ÿŠek";D{é·öÛ`±‰¾fì5!Ù‚H%刎BÒÕE˜•:ˆ%Ñ,‚‘Q.]QP/E*nœdŒCz©zèV„Sh 6žŠÉ±2Ÿ âÄÍâ ô¢ P‚9:1Ó›8ýk¶49w* A§n’Iy)%Q‹¬ö,ñÖväJlêÝ»~_á}n]o UÉ/˲ƬmQCxHÔϦ¾/Eð½×|Šü²‰1d¡ši¤ÒXÚ"«m•‹P)V¡»ž?5#Ö‹B%¨ž,ÉUnî$BHÙZ¥§Ñ¼·­€wbý~„ä"t†IÊxà;éshÌPB#éØvõÁ«¤Õ†÷{3†=îÒÜ6£iôöx9g²-³™™X¥Â©j¨Àª¢‚÷ümïEŇ´«/°îþŒ tDÚáIAH:¢HvŸ#»²©„Û¥§œäµ¢$vFWÔƒbšÂ™ À+"1ó·3icVI#ešŽø÷.N±ÀX«E1 ¸ªÁ\ýò,“Ÿz³*¿-4È^hO€£|Zà‡6.ÜYE'ER¥6"<ù!ÓÞ±{ŒªÖ‰Ø q2¶¯µo È³ÛÆ¶Ä£NJWªè´*Œ„¼Jyð]49v:e¦3ÂÔÒGs¡7‚½×âÞæU¼®å*àsƒ`&8¦ Š\а!Õgn†¼éÀ¨bZȫҀÝÑ, À|°lË<Í;ǫ̂lÇI[ïÖ#MyílÖ³9{Þ©fÉ\5®4€ÓF‹#­•(¢‹Â‹&EˆŽ+r•GpÎ…" *ihø•Œìu±Çö­”ïº*ô+T)ìÀ@@SÀD!ôñNfQ•¼”_ãþŸ/ýÿÚ…‹a0¼#Óñ}‰ƒÙHÁ*ŸbP¸P­¹Œ¾™BëeÞXøïz&LÜŒ@5•XY¶Õ"©ºÖ»0NqѤàon9âÛsä" ß©´+[˜ÌîûQ÷•Ôvš±æ˜ Aoküg¢9&Š©o=pì¾_ѹ’+縯œ‡o¦Žæqê &;0–…è•Yø¨¶jA,à2ðøhm¶Ûm±¶Ü§†¹ÜíÛŽŒ2\­•+ÁÙ2ËÌj~Õ—º¼Åº¡B˜JÃXÈàlÓ³ïtâMÓÅÑåTª¯µÝ;–2ÑUQ’²’Š?ïrÑͺÏϬðÆAd$dc3ý“! n˜ÌHÚΠ ¥E}þdûüÅ[RÙ¬ÚM{#›(OƒîH‚•ÂŽÀ#£ªÊ ¼×Iܨ²ù×Îò­ªè®c ÄwXýÊ*‡ÝZ.©›3’*ýücðgøí0õUVUÓ~^ßåŽî¹BÛ¦$’àù¼¬TŽC‰ù/ÈZN Ô²E–•MØ­Á“cF=Þ* ðwãNH,—TÎX²Š2«kâçyäkª#¯œVž€‰) äÀ\‰…êòŢؖ#1´X£ŒÁØ2³hCY™U–´ÂâQI“JdñÊ8*cÁ–¤$’!B¤’AÑ’44IË¢qÁìú ;m‰w»yhl¾¥£xzš÷S]âp‘  û2<ÏÝàDMìŠØîŒ$9åcQÖ¬:–çÔûûÜ.À½%°QKÊ¥ 2ÕTi…†êPë‰Ôûòy|Ϩh:Fdׄƒ èzÕær"¢êŠˆöTW42o 8\¾{–FÀЭÑù¸šNM°õ¾1)ò )« c"²ßLË ç Sˆ A}o»ºôzBñµãmê¼W}Õòzýí0ÑŽ4AƒkCF/°xBöJÅy¥ðŒj92@¤wNH¤„åíM½•ò¦wÕò&ï–cei–òTHÇÙVE›AimZ‡&HÂÂ׿ž–‡A°_peB@x5´}˜µˆìÆ}uU^ºÙ%¶sÆÇ5.%‡‹dd!ðp:Áš%ò·}>ûÊnoôY®×Zi£Roɪ#º¥!¤åðÑmä.Åïåöž7uõž»²úOuò&ÞsU«ÈÝq:9càœ±c\£§ 0\€Q …+t‚B3(@y—¿¿_ÿw÷š[z‘Ƹ_[ Xú¤@}Éâ§òÁ_k¦ökÏ‚‡ð¬ƒ‡ Qó æ„LÊ4º—XÉ—R®«ïÍó¬Y7Fß28îG¢¶hj1¿ÓY¥pdÊ©¹ÛÑZñÀ@Á¨ùd²m[2+h*èÓi³šV›=ŒÍACm ‹O¶ªÃDq6jÜ!Å/ÙºíšÛ_É>0™Ë8‹%©(ËüN›±¶(Ã8:Öj­—0ϳVŠH†cÜ ÅÚbIzÚ+,ó’®F£C±Gú™ÌlbÆ'¢ìC¬í¥ü^öUËg‡+lóg¿¶*.·e§¾ÐeÉi—E¤DêÚÍ›{Mº³Ð8XC¶Ê‰,Wàù“F¹ WÕÁ¶zÆÔxŒ ÕWaî}¶³9µÇ+ô¿›ªåÁEäl8â’Ì¢ªªä_3lÿµ‚œ,¬‚fŽf*#x²g…ÄFÅ#[ÓzçpÓ“(}fd2ª°ùeù)ÐC3 I¸±jܘs“2ƆҖ6ˆëÓÕXVãÐ;#MȤV"3ñY”šuòÄV”ú¢J äGÁ:$ùv¤J•)=^’‚Ì_¿£)d3±»†((¬(ã^WYò˜΀=‡ÇÓp‘¹•HÂ.Å"4q#\I˜önÕ¨‰Ù‰l‘•1¹€¶Ö ×ZéìÕù§½Ò¾íéîy4h/ UÑ À.Xà5€.¢@[Ô 6hƒ›]<˜ò q!/;èwÝêTXÈk_a“ŸîíÓ±ÏØêÚ6d-‘ù]bj¡µFн"&½ ìÚ›ØÕ…«dI7™p€ŠÐbbX)9? ~Ïv±Û™´ÍƒT£eFÓ?3JÆ_JDK!ˆ ÅÃ4Fø†ÂI¥0uó}%1®X&! ’Œ¥Ti²¿ž÷‚í}®êòÝnš¦4±is™ llIÚ®¸¡á¦ëb\ º`ÙuEÍ*$Œƒ%D©ƒºX˜ùWpÖ£VG@ˆÄH"1e \]%cÁó v¥¨Ù/^"C—,|³"ãÌ{Ú„6Œ-hz“n¢G™ä­/”µžŽÊJ•'0&¾~3¶ Ï¸˜ÙòÜ‘€@‘Þ‡ùo¥²!®,‚«#«|µ Ë 6bM¨T‚D *¼±¥©«`2²ˆÑE…B@$ØØ’C¼—EQÍU$T4ïXÈe™,£H—%ª¥[|¯©×¿|‹ <Ö!ƒcè%iPtƒÃÁ†Á´H”5Aô´€üdŨY‰è '¿¤ –B"ˆä–Ö{N¾aÆj†“Õ©%}Q¡ÅbÑJ’ª*ŽåÅ™)‹,íµ?(AÈÎ?0s\(Ë´>;Y…¿¸ƒÎ°š—!¬Ê[F\x¢®ÑÒ_¸”]Ë "]F͉J4Z’ÖܵãÊÜP è‚È’$XM*&TŽ,“,€É›# Ò5­ã3fRÖ·TÚµ¼ZòìÝB"Iš c(Š$ÐjjHG¹<õóÒSÍ7nݸEdLв»»]MÖ.ÝÙÖîѵ­éçB’ÑS0‘àl`Ò"tcMÈ#²F ™c°„2¬ÂAÅnU‰¡ŒK¡Œ„Ì¢¥¦Éˆ‰d5"{PÑ…µi=ë$qVÕ’-VÞešFe’YCY)*¢UŒ§ÂvÒFa¾‡ Úš2"ªI,“-§Ãë£z7°75×p’FéËmgtˆÕFR"4„ ½šiˆˆÚM\[L·3ÆÆ¡J…µMš’@‘yh[#NHÀ=þß¹˜€É !ŸKqëëCåNò;ìi^ñ–)VU¤Rª­¶UK{ùŸ†òÇŸ ÚRÛ,0Ì…’)P‘/ºe­z/{êeáüÿäÿ÷°ö_÷ýÿoöË7ÕYù®~ØçÅêÙV¥ÌUˆd^~ÛÞ P‚PAm ˆÊð!cÍDèöôÉ„_g4d¥}ž~öÂwYh˼ìÜÜþM£]IÄÓ[¡Rúg~yýǶptšM@HØÒ9eaã±–±SL{„c›¥àCpY_«,o¸§æ2gþ7\‰ú"VÖ §Ü¿íÞDzYkÖnc’dËV—–Âd‹¤÷´r×û±7OÈûüésÙÊ>ÛpÞѶ±Èeæ„IÊ·Õ‚#uE¥Ç X=l7:ÂFDHcl²SÐKeŒœÙÊE¹´,i“$UŠ-±Rª¾zบÑPiÐçÙJDèw‰ôn1O#õ4¼êÙ[nš›,Hî¾,=Z¨÷vræ®ãºnu]}¯/ªònidßIËDê9Â-‘ab–ÑlÖ,“M¥SJDY¨BØ©ô¡$d=7ãÉêL'Si½ñâ–-Eò!ùK$HZÕPzêKƶcZ¯·UÍk±ªA$‘@ì\‹à%£p7ÍÚ*H‰6ì"oÀ%”7X84ï)„â7ŒÛ¾œ:ÂE#"|ñ@Ò¤àÏ‘GlsæýwÖ*HN\h‚g,0ãvE•¿}”^^ðŽÓ±‹.Í!]i‰¶:…¤“m«Ó5} k鵨Š2RšÀ¢kE¤–ËE„RAd$ƒ!”†‡$EN‰¿GÇà÷QùñÄdºÔš Q\1œp*¾7á´y@Ê–£BŸM¢Œè)ɉž)*Å‚§U‹IEYQ³»»‰ìÛ^jö{M%¨ “i;+³RZ“cb¬–Ô¨QWo~Zýß±°j4kk²­cH‘!/4lEɵbÁäDs‘BEqˆƒXáe Á$IÎ…9 Hˆ®lýREÜ…”— #Jœs›¡¢ƒYSn^5·ÑoFÔš¯L··^ÖúØò°æ¤Z éádv8Œ“Õ)v,0ß(hj©õŒêü$™Á%2êV(§y; É;½žúämmv—¡3äKm{™pŠÑ ÂYæšœ¤DÐ"0ðA`¬‚¶]hŠ6Á½GÑ„D¶"&de¡(bgåw”Õ¾:Nrô b¥³bŸûHµiç´Oº>¯? ¤’Dê8º"&¦€VDC|ñ¸ŽnD.)Η‰"ÓàÒ\ ¡|xV~ôÜ:—àŒJ0Z{’D|,£çþ-QX™’Ѱ² š2ƒu¨ãGÏvk»Ó#`™ ¶ £ŒŒgÍÔUo}a‡œ›¨ÓÂn*5 _=z7NÜo“·O&ö¤»=ïmšõ‘æËOGÚ„+µAPn7$^íY‘Õ %ÁSš»ª@ZÒ•¶÷älh…Z‡QTœ€™M®Õ3T<þ¢žÃ š™X¢4«ÝACK¡Dy…@4ÎT6VèVàt&Sú1Ö¦TáII$9b#°ÙÒDÞ#ìO8|¿BÖ>ç Œ•W&4jÃKªÂ¦’XËjdj‘”Ãî#·Ay ›"‡4xb¼èbAÝX:3fO·p¦ø°ÆVKdúÞS´µO“©TÜ%kësvØCdÕ„œéUË«B¸BÛ8X ´Üœ=y·Ñn¥€Q¨§¬¹øÙVɱ§™òV;[§–2ÀäÈqQJòÑ«Œ&'S&¥qSHŒ`eí^ÊHY@G€â9ó»÷#6‡!BîÕ÷õöPÖÖû:ö¿o±}t4ŠÇVþØ¢4DDa²ªtÜZI ÅÍváCNZ!&N œPøqL‘5SGÅsSŒt<Û6lªç7׆%‹“¥æ,"}EZi¨pð¿Ž[«—ji’Í.© °$&KH¢aÕåу2îÊj*wVæÞ¶ÁAùƒ3pŠ, 4LJšð¾íö•ÓÙžÛë»=}.êþ¦jû.×øÿ±·µ±;À¦Ëe Œ)î{U —Žþ7 I^lÇ%Ѫ 0ˆ’¸!P1ìÇÌØòrÓUFe ¥î*£Í³Çtdø·°R üÝd¥?81¹MÄ*ÎKr-`w©h>†+FÕ‹ ZØ€£@ˆä@Gö¾ž&Ú9«¿—…§û¥½}j0¬oõÿD€ë¤«ñ¶­Ÿ5ôæozßYâúËr*1xÁ%U:Qæ( é°¤f}Z÷Ëðè»uTÃKÚ¡ÅXR•ÑJ‡ž©…î²SRVpšDî“’Bea¦6+¥+G À´%Ëp¨njwÈ7~ h$b’J¶Ki\Ă懹ˆÅqšÔWÔ¹ !ñŸÅyÄÿ® ý÷úÒÚC²ó³¨;dü¢t½™¸‚!Xb¾>vÿƒÅ‹xûŒzc+€ ÓEÛs k®x›Â«tå³ ~Þ©¿÷¨PÁpBQÀ…/ÆþnÁiNR(1š¡"!zàÐPà¨'Þ>øõ&@… À$*^ªëj—y²_í.ùw¬ñ´Ž'XêF¯„x´•»¥§b„¡!B'%5;‚ªÿ¯“óz7âÿ¯ês€¡ŸF†ŠãaE£êÊiðý¬HB¯çbÞöз|iá ¹Kl¨·ò1y$AŒYY¿ç[l‹{ýn¼Ý×2¤‹1}êíT¥yœdîÕ̘½7v-åÕÃ^whoG1èé/gxò.¯_-kyæîì¹o^ÜÆD™ ßܤ´ˆg£r¡´Q0Í[Ç•æR˜“$xºÓLLTyÞ}~ôü/O‹ÓÑ>7M±¦kZÌcÓƒlhHL1¹2ÒÊõVÕ½åÏÒxxllãbE²Zi¥‡g,Ö!i7Q! vï;OÒü•«þKËé°a‹bêGÂ×. ‹‚¸To÷oÁ—·«,˜áP¹P!OЭ"³ä•^mOåþ¶þ@0<¨l„cÖñç0ú¯ìÛ&Èç1[–ãÃ=ä½T© 6ÓrE$?ìR‘6¤p+ŽÆ7AÆœƒ 2OG#…lŽMCšG*±½#_GÁTçÁA 2!ï9GvæÊÊ1V¸˜8i鍨u|•öÖG)•€}'¡­;‘är@6¶ÔϬ^ÿfë¶w.ê¸çqDDúþ}_nD4U÷)÷bI q&æt2÷a2©U2¾†ß”v¼”‘U1Åfw2Ž|Æå‹„”4TMôBÕU"EÑêwÅ@L„pÖâhº»Dbùòßs¨ÒkF"£°2‰¥m³P&0$>âœ/!,“nÕ4ï}‰°j³¦jÜøF».ó²|ë"zW´,Pm[Œ‚6È{êOS3Ý´æ‹uÌcâBÈH£$Y$€"9}ùfÌ PbIƒLb 1OÏ&³%uÊ×N @ƒ0cuÖ CÎ$˜FD2`í 6ʆBÄí)©ôÒÍÈJH´ìŒ f™‰ ީì#®ŒÒ’ ©1)4oœ{¡e6ÎJñê‰b¿"5²0·½†L²Û„„’q{›¥ì‰($˜pĒТ.×S?4%®¦‡s·Èª…D Å¢¹–ª -h ®l!$©LZW¸";Ääýï÷û=¯hzÜ<éô´ü¼]=µn-: (üÑ@ Ñ›cÂY㇔™†¼ƒa´6(#M[4e4A5ÇpƒkŒçËÒ!*™•|yŸ~)¢#ªû6ßåW¦fnµªÆy¾Y²NZÓ§fMd˜ ÃD=%éÛŠH• *b"6{xB ²2©”å‡{J ?´ Ñ „$â Ü9oâv‘â]&ôÆ‘¡`1ìÈÂ#Î6p MúRØgÝ ÀÍÈØl"ÑXõ–ꌓ¦ÅÀŠ–Î2æênšëM-ë—[_sk'Œ˜í³*ÜKdµråZW%I­ƒb17a°K #ÖšAG)º;B±†åqMA4'4UÐa¼#×KÖTÙY…d†?~"ëó2m·¤ÇB‘GF“`OÁ¥ É ‰Häˆ)ž^Íwˆòv5ðùý.î³ä”vkM ñei¦£èÂcƒ3Kp:Äæ^=r¨H)c``n,°®æé×uÔ"d€Á&~i+"MÜO˜’NÊU²ïƒ+qñjð"¢8Ê9@DὈHc#QyUF¶mÕ-In 믚wª¨4ÂcM ŒUlR”0´ ½PÜr6ÇÉI³ˆ´”ŸéðŰžÉÌK«¯¤¨mTÖ”Ò’ÓDGЮ€˜ ‘BB K xÈ-Ò…¤hÞ9à)ØMÔÏ”32enŽÑ„7ºôÃty&²Ñ$!­‹”ΕN¶ü{ø¡¬ˆ©Z¥J[UUgwS¤Ãæðaõã…£q ž?y“J¼ »jÂMÄ î>z\Ç®Eô«C3¦jéölK‹_º2åVIóé 꿼g­ÚÚ"IxþŸú?üëþ¯üíþ  œú¾V5HH5üåIxßÜÜ  \ˆb:=Éi¡Ô¨ùa„¡ëY1Ý5œ.žìe£ˆ šÞå³q— Šnr-Tö|ÚŽÜk5äAz¸†“låË<ÛÞaªb«»‹JS²§rŒpíãºù“ItÅNü¦“LmƒÃ?“ãÈÍ{dÂ_¤x\b;`„/_tŒœs³LÓ1­Æýv\™bóõœ‡^|ìÌ’û˜´6(ÞãmÈG]TIâ¡§!!Ô5fU@D!sRÐrtÛ m¡99 §(kòfÖùCÞ ‡HÞôðÐd±¬ öRêªr23U yÎ%šYˆ”˜,Ü,rvS)~䕨æ&]~ÔgåŠgQì3*i†×6/†âs'Eƒc`Ú4:Í÷}ÖmfsÝïa—”¦)p¹ªkNó♦£¾n®aí u$ÆŠæúPë´8àâ3¶sM24ªtõ‘f‰®6ºöLý¼Î'ko–¯i_nCqK1Á«#ž·u’Ç ÓˆwXV©„'³k1õ#IÇ_/…¨6!xˆ¨$q¤ ¦ùJX2‹ÜQ„ lJ‹z%TÜ;s£}%¦4ÉEL-êŽ:4ªØUE–p«2£†Ž[?PCl<›ÞqÝèØÆÛ|XWËïÛG~ÓMð6ž¥ ³*8hå³± °ÍV¢Ù­ÄMÙcòrÎk'†ø¾å–aݯQu¹Y_jkRÓçH ‚l[‚ã¬Vè§ rÍ`ÈR ÕŽˆõbÊèéºÊÔ¿È„`ûwy¿8ÒĬqF;LzðÔN9!ßlhÛç·R^8P:öEÔÜUèkðžñÄ"n)…qW·«‚K…ò¿8½·¬.ß–Ò›¦<¤MϨßÕ¿µµjš&ôl":9-c2Ó¯GÓ¢’ùËåfܵTã ˜â¤.ýô~š¯ç2yA\ÏÉõ½ néZì%ŠHÒJ£—ZÁܺ–eYOJ«À×ËÉÏÍz°˜ÙˆYÑUTuÑG]`}š Xº¿]£Jœ5Ÿ;0î’ƒÕ<Àú»±hQšùW;ëtWã¨ßÇšs]\Aå ¾{|ÎØ©¶Þvïߣ5Øç$°îÑF6ìÕuQð»DTîÂʲ=ìõºpÓ¥DÙØe²á÷ÈRÎ ]Œ_l¨¼ï ­2ÌŒªªÊlã"Š …, ÙÞ ,³¯ç¹²ªnl—ù_k7ÓÞðÂÎYf—7­Å¼½´AKâ"8ä7HnD)HM)÷Tý~MŸ+v›I‹$>F:háZy&’EÙbR¶ !u顦HžƒÑË[jÛm«›p7üãÊ•=Üvßâõ­FsÇë'-¶ÛuH1¹“@Ö1¶ŸÊB7õÏ378†Y*—{Ñßzf„sYl ]ø#Ö*¢ÔkF­ڊŶ+Qj(¶±¢ÆÅ¬j‹hÛbÖ‹VkÑj,j6´Xª,ZØÖ£mŠ,mEµˆŠ±¶’جVÆÕEETm¨Ö-±bÔZ*-´Qh´lTZ-Ú‹E[UV¢ª*´V5mo·–µ¹[]KZ®ljÚ5¢+F#¨¢Ñ¢¢Ô[%ˆÚѶ-ZÑQ­£ARZ5±FŠÑ«±QcY4UFÛ5¨ØÕdØÖƱ±F¢µk£j6¨kDZ–H#—«›k,–æÑ4™XA-YFéhòJ’Ï|»­”F¶ÝcpæÝ±»_Í MqØ[­’&Ù^ËŠJ²{AE稜BëeDÃ^ê´Òì¯iÆZÍšýï{äï“XW,ˆDM•(p-¬loU¸åËâP¦b…3­ªX¥‚ØÒEƒ5[3E‡¼@B¡K©Rörpxº­Ï½½ÔVo™Ç,5ù¾Ìa¬ëõk”»u®sXqΚÓr¢!U`=¾™eßéfqsGŽ3T49¸/Ú¬Û;šÞ+0]22‹ˆ ˜{+³œ4¶ ìˆ •{«³—ª¹w¼h@’}¾÷ãÑ\qÕßy5;+Í]æ[¾Úrèˆç+ŸŽù™ 4B9j£DË¡­m¥ Û µ§Áž(µ‹:Ñ ú…O½…“«ƒœ¾Ã®xÌ2"¾0)BÕN­ñ×ÂG]í¯-Ó½?²àpØË¼xœz5[~ZekËíc{ì„—’M»Û¿Ý›äù2l@G}ª÷ˆˆñéÒMÏGJl Êñ>¶ç¶ÛS!ÉâÏqÈ}Ö&æÝ@DoËÚ·I»†2Û®XŽÈ­ˆÄc"„„Œ"E!=/Öž2á5bh²ANÈw#»X½>èXD·{Tµñ{M[EWœ(Äè«jÒÙݧ\ò1­ËL3¬B±† v²ÛJµð×FfwÊ/ŒVIw±mnM©oJì2™^kK³‹N3¶n7kÙ²[VQkÝfô;—lžÏ4Í-GU$Ÿö쀉ƒÀlþWо9—:yiڛΊžŠaØÑ5ûID S1ˆQ,bºÝ¶vw8üC†ç|HÆÊ“™flÄ$c$¹cñ(À?zŒ$Íð9,Øèæò@Æ3ኃ3%lxDWSsJØ&ctÑ`ŒÏ ØXâ„–¡µ®ÖëÊIQˆõã3é9Š ëF(xàˆöŽ“HjœV'ÜÌX¨‰j• LöÛ¨‹ºg‰*ªF7Æ,B>¾Ï™b¢–U=ÿKo}Ά̤ÓÞ­òá[zí²g¹cóœÎÍ{;/¬òáí©ë*–Œö¤%J Ãîëi¨ú©!ëI @²¹ê·É|­É†S×XÆI±˜“•±«¸ÒŽE m“)ˆ†6ÆÑ€`Ààë}sÑqrd~Ž$!=N†&5ÚÆÁ)Ä5î×mÎû…uÝŸãÇÇf*Äò¶ó”h Á.¤3É»rêIlZ$Œ©ÐIjyFÒs’vž@#Äå\ùg{7o姇ù01±êµR%ÖðSC¦ü¬ý® F.&ÐiF•13 iTÔd$ÂAØJ‚\(¢@°ÓUÏ(Ü9^goc«ÛÕ¯@¼JMSŠÍ’"<¡˜©›@N YÎ|8”Ðp¼†²Ç2 ž,$"B !Ôƒ!΢ö.U PCp`Ø‘pïf\}9NùÉ…RvêïwŸÒ„5žO4-¶ßo*§¿«k–Ʊ­£¾²H™L̆PÊTMPšÌ’©hI&Tƒ>Ç<××"“ÏÌjšNÁ¢jú¯]µÉ㺠Þ’îºG'=;Ú,òÌ£ojbµ¶¨Èã7`Pm§bCPË;Ç# ¢dàÔ_:cøãçeÖ’ôÎ> ‹omN­MÂÈÛQN©¯8wåš§8éu£çY½‚BªÚ„#Hӆ݈I$,L+ÇLÖ9ÛVš°aÀÑ}/8s¸H(³‘"¦ª-T.qÁ~q¿[°È„ؘmeš Q6Q=OiG3•‹*²IÝÿï¹ßI $$ ܉a8”Æ1é@<ûÊvͧƒ5¶â^êT5ŒEøàæãMZAŽ>,V28UBQð‚ šîÁÝ}=ä¸Á>×#áÂ!ê`õ€‚6ˆ€hF´O§°žŒX !äè;8ø7§ ¬’dž›/#2ç~’…¨$&¾¬¡ÁϪÐ"e¸|±†Yéôí¡· ¢ b,€¯ xæÀ.¥¼g6ÐSò J TȺ¤’B#4ÓNøÍÞ6Û©–ZU›o®’i—gíM|b›;ò”ª‹köä™1ñ€Z2H"´«±ØF"BBÀ— ™ÆXºÓ2G˜6.¤Ãk»¦‘éÄi‰» HÈDLåã"x°?o<äU/Ô±îßµ³ÛLÁ²¢ÕÕó’!8‡yøö~\kÏ#løZ­fÛÑ‹@6%°Í X˜XºûþúþºÐxšˆhz0^iPYEåˆá+}¹EÙ#vÞM`IuDQ­ 6›˜ÄÒ _0d_«©˜ÜÄ™DSŠ—LȤu sž}Í‚H#$‘ˆüØÕÎpäëkÎpUæIɬ ¡ tø}9’²GliÔAü¯b,f­†î'374þ&þ©Ø>«÷ÚI ‡Û÷ÍØ«&ªu<>N¹‘Ð1O~DHfK|ü{­¤e%bDLŠ«$DùñÅûqH‰¤úJfËVÜË$RMs«I…=Žt5Fõ¼­•$Þ¥”GÖ –ꘋŒ$2ŒVÐ2(Qf€D騛Q‘`! 0®|”@ìòóª”,7㟸ˆÓT"4~o¦ˆ«Ýßòc~Ïeõlƒñ»†¥³*ÔOøô™ þÂ5 7 ¾ÎØùsެm¬4ãÞáu‚ê*ÎdU|MAzLRÔÊTQL1e’êYë1O)XµìJÙY«A¬&súm¯ f‘[P±hi‰›öµšÆAaè3o$¦Òí¤ðh¡¦ôE¤A¥l…-×.09ü¨íþ·|œïô좟?‰< ÃG¥Li³Øm‚ŒR}mžÛ›Kß-Û¢Ô1¤&ëO«ðŽÌ’yö eV]aÌãw:x]âÄÖ ‚f’IÌ‚Ð⸮?üõð]yœ92‹ÛŽ¿÷ƒ].™§}É]Oí±=‰Œ‹\vg¨§<9ánÖôš ã">Ü#Rͺæç%¦Œ÷ÛI\í™94¾–z˜„­,Zfë2ùÚ?±hÞ‹ÓG•Ÿ››=ªù2AË– ITT´ïa9R]ùÌ0?å넸ö?[˜r›Ÿ“îùaÓ9I‹g„½,¥ƒb4C€Œ"Ø×]ÿ8ÄøŸ™GËÏ›NB ¦Õàn!~Çoë Þ„XH±÷¹5~v¸o&û·l Œždr–…RAJsKIBxªç* ðnÍ[ªÙµœ9 äª³Üæ ‹èw‰»ÄÊ´´™†é1Bÿ5æ3w«Õ¢(í¨»ê<©³9ºîVމáª*¾ŸŠ‘̈Ÿß.¸KgX \ªF@ xËPÍõgÞëïEF ª×¹ÆÃxM£õãV@­™¤„-*Éš·ƒ½|(šÜ'ˆBÇÝ‘†GŽZÝvéÜýå4ôÏ¿ÿ›Æø9Æä Æ7Ãl6äê8pN³¬^i~º~¹QiK–T±d²T)C%)FÔÑŒåtJç‹\Ê5/gô~1wò´—ŸgŸ®|¦ù×ÈÒÁê±-CJŒ³®k[Û¾cmLomk`ó_ŽÐ´5Ó#I«ù£©s;0í®/ ìð¹áWÜD¾¶Yªy½y¥[os¸§ä\2ÊžP¥Ö)·øŒX]ò2Ž¢YSí-¸ À®Ê«íSÙêú6üÍm'«Ë¿ÖÃß™ë[k*©Ù“7ÌÉòþ<óLŽPÉÏŠCþ‹CId‹æÓÍ‘ÅÔ×òd²knYÆÙ$:)P6ÐîÑ këÿ÷¨2ýa¢ÊÑ]ûÖ5Y¼K4SŽW?W”ïA¢#÷ °hl^ï?›ÝÚhù+„þQÒá]ë1ØáÞŒ’M3cÖá–ln»U´mɬdÿ úÍèÂ'ó?ïÿudLŒórÆ€¨r ƒô<½Ýý^ïëŸÄO•ŸIÑ„e"‰CSXP£ ¡1°£4Zd&\X¤ÁêzÕ Í¹$µE”T©uÑÜàÛ=ðå|±ÁO–~ÿi‰ª‘â¨uë‚}67ǶåŸ`eTØ5ª[ ©?ñK‘ÈâH˜o|Ž#©]õQb’G«þt $ ¤©_ØÖ®’ 4hB–1‹"Hˆ¢hÂ7D1ú¯Øæ'=èt]Ç¥¬nvGfu–ËÊú·“6é¼0ƒŽKÎ׸ÙstpcUÕæ‚S{v…ó:c§†¯«òÿ7\½/pý3Û/·Êæ¢ Êªàœ@0YŒ¡‚‹uUSÎãÎïÿ×üŸá±ª‡0 û?²ýŸµÄÀ iQô~s¶­ÍXD£mzùüC³ˆÐË’¹>>^-à{p«âçoñËC3”–6F>¦QŒ1§u ¡7qóÆfØ2r‘Såÿ$ÕtLSSÂí†×l(=®"{"¯E–̓,MÖJcÿÇû¬žgû¹nLbß*~%e+•íôðå2CÂ÷û[{^%WÕq‡N|"Häàó½õ=áE"‡Áõ_3Ò¼¼x¼:E?ë ºf1×zJpúÈÄ` ½ãËiÌ$\Ò¦)俵ÄvÔôøS ^î1Õ9†©Ì´N÷G_ñYaä.€;ÜH3ïtógHx YJùV€±hðð•Ù÷óz¯»p˜5«sOªû­‚o‚°‰h©ú?êúŸùŸ/Ør¹hjvК íµn‡›¹Óµ}"b‹® 7[%È+7¾žÕwµé{´ä@Ìs›Ài,Œ’ Ãˆ (—€Í€Še !E” ¾(€waduæA $ÃHQàXL£x( 8%ŽKâÒö-¶÷˜þúÔË•=+fÙ8þ:žW©Ö¹4»±‰-ÉóÓÓ~Ì´€»^³€˜á†Ù 7:‚Œ±_[ˆ‹L·iE°žù¡`˜›5[*§÷¹¹^Gþ`e$á3}†fÙ/U~ž6ûL̹~¬ü¶•­ äbniXîͲ;Õ¨åW±}êŠòk3LÙ«=_ºRòç_}´£Í^­Ú¢æw«aü“£˜Æ?/3[–…Ö[XçÜJÛH(-æ³q¢!@gsóæIÀò°/´Ìà8»ÕÚ9xi¶Aœ_ÏÒªˆ…â©9¢aï2·þ%sÿû îŸ`u³¾·fdË0ýxr§U§[tôJ­_,—< Ü·ä1eֻݜ“d›RÁå—Cä½_ƒïbflŽ~¶åÙ‘Þ³˜¯qŸ£?à ¤¯Y«k¨»€jîû¬c¯L€Ý‚¯iñ9»?˜úë¡S-ö{ =¹ÉüÐw Í%¼9Î*y>{&ncN§ ¾ý»iŸ¦Fù"2!uJ3[Þl2°$Ð%m錰 ÙÈ}Vê¤sÙ.[0ÒŸ £dôgrs@D×úÎÝMÎŽŠx÷çúñÕùMZFøÄ¾2Ke÷ßãÆ¥Yþìü¥¡û|²²Ü“ò‘~/wž}+‡í°Éùâµæ5´ï¶l‘©òí;}ìvfד–æºt»Š ITZÉ´)«ãbá¾E9û¼‚µòz²ûè>#ÓxÇÅ@Í©}•¡î×Pæù|š°-6ÞNM:ˆJìõ><¼Žt×í);ŒÊ¶Î±iÛŽ [ú÷_ƒ“=×ÿZ=¸êöMmV×|‘Ðp®}b¨ª’’^9·ü£«Ý²epðÕ]­âÒ2Ξ?5鿵¼ O×;VÐËÑ©>Uåª/{}4­±Àmy÷4¼JöMZ½0’Å”lB“Å5à˜ÎÍw³]ûßku:]Ž=Ÿ´ÓÐΚ—R–ÊÁ„»ñ´êòëb|žëö…î<7¯ÏüËý+¨*ï§ã¨1 ÆùªqvνŸÇÜö¥u'ì¡’›ô‰»Ì]šß£þ•àêô=mõN;oE>ß1ÊørØó¨yÖúN3ÇmÅ-z¹%•¡®îú{÷§…±4LMýaŠÜà ]ª®ýY¡@Ž·>_5¢nM¦~1oy½‘æX°™^uø¼~{å©VºïäÕ>+sü ðü¹‡—Àíés_uCª>l Æ*ÄÉ¿ï²_¹wUQõ•áôòd÷‘ëUú”…QJî½Ôz–Ñßdž?ÇÍ¿¦»Ó´NŽ¡+éöKIäuÔf háúr_Ø¡kÕÇE\—ÓðªgÁ)Ïìƒ6ýkó}éUtTï¨Q?³w 9?ö=¬ ‡ zÙ1Ò}u!Óáë¯üæI¼b³àö}uÝ%¼Ò•¾'Fçê¥Þ¡¯Ëï3.(øÍ}=κš¿YXåìýú=¶Û€%Én"·ÁZ¬E(ø€:•öÒYÞ/Ä(oo@C×e󂽿ázâ4è}ÞMßyÙû4–ðVÁ5›i²À×ÙþÆ«ÐÑ×;9c)AHåàQä 7€’ë" ˆ2)¸Šºšì‰„W¶M?E¾—ÑißTæc ‚§+ÇšÖ³UVÿÔ¾^ˆF¡ªŠ@zQ*žªÆ§åÕŠ!wîøé0ö›X¾¦‘û%žéÊk‡¹™Ï"êO˜|£µÕ"äö9//nÚ/Sˆ¸·Úßß™ VÂc÷ãßàf»o»NÍ‹›\r)®¯O/TT4ºl.¯ÒrË3Ô[vY€±¾»Ï ûg—òb¶ò(· ‘ù9—/Ç2N½Ÿ£ðnÜø±rÎïaF^å‰;´EÂ->¿œÐjõèØtÞLºßg¯¬vžÂøxWÞb«>²¾f”jv÷ÛØ§i³Nõ?h¨#QäãÖ,%Üqš±´iC~¡Î{IŽ\Ç7ó\»Âb+õRÖÓǵßõvË}ºî|ttßb˜{—}¼´Âßæêa•%áGùð“^•fµV”;Ÿï'©Eg°‘=\FÈÃÆd½ó=†y®QqgDGìØäo¹ZæíÆ!È¥{íhh\˜âs¨(ñ3É® š½j£Â^-K$ïÝ}G€u‡úEÏ:³Jš˜—³QqCeçù.[h™Žcts zOïù‘—@gtî[“š‹N›SV©ïhÿ°9ÔpðÎ M™ªÅLÌZ”磴æþ`µé‡ £êÁ‘¿?È”€Áï'A»€8Ü6]„Ä»3 c©·d­VÉ']µŠüåÒß%–¯Vøª0îЖúuНjÍDsTŸZ; ÇUeD«É~µ†Ð "zIŸìÊlƒá=Ê—î²ÉÓï~Ÿó6ç%Ôd kõþgÜÝV¹kMîà%ïhò¥Óç##7‚!ßä!yì½¥Âæ÷®³|·ÔÜi8ؾy¼ë2”&ªÙ-l‰[ë“Þu“Q¸^C·õË®Ë_Ë2ÈHŒ¼O…5CIƒš-Š3™WSªX­Ý-Þüèšë dVwQÏv?–uHÇÝÚi2›ÅsÌùdc–{ÿHæ™™ë6Ó¨ôvà ïùÍÆðDj0Wñfå%QYrŒnïÆûØŽ¦jKñ7„xë´§!†åÇ`ñ}ü1¨v¹Ï!ìf~oÊ+ݾ™ŽÓ¶vuFùË%>MÍÆïåJ½•¶ãø-õŒ Yk•»M›n¹-÷ïÛRThq3ò¶êxGQ•²éÊiô‹UÜî¢;C£7öãüŽ»ÿkdÈ$Å'ópÍ彺f;2•^YÜÙ[¬¼WÃÚ×5® ‰Ã™Ï²¥}“L_ËQ)¡ŸÔ£€…ÔüWçF"V´Ë\ÌXƒi|7 ®G’…eyš7Œ°–T÷cWÅñ`êõ)MájËÝÝÚ8nó·Z6:x–Þ]]çdÊÇêÛÙfÕü¤Ô¼tv1ß/Å0ˆk”\n× éš¿ìÔK gS0êÖ·xc#O¸U⇡æESáH$§[7×é*e`JbÔ;Ü$ù¾ þgG¸>c÷i_3O Œp3ÌN°ƒ°Y½è¬Q»ì99|&»ÆÓÿö£„ãö´Ò*#ò(z»Ùý+÷ЉðéûÍ_k¸{ž*·+«‰U¨8ãÎá^QOïòì””“ T YÆ^IæqzKtŒ»P•,¤ÓôQµÖÓØ`b_;Àþ¹Ëœ•Ô¸cÅëëc”úNsk’k¸œmÆ÷­=[;à­XlRÓ%æà»ù0ºÕ^ålµ+­—¿Õ5ùtûýÛÈÈâ»*=îú«TÄý׫š ¥úÔQŸi4ßÓÄÕ¢f®(5”¼}›O႟D†=¡ÁNŸ½š±bòý²Ý}vL ÎÉY0ÒÔµ<ù}6²‡¤ú߯F‡ü"cT¼<\ÓüšõmUYKâÕtÝßõƒ_+Û‰^Ö(j¼Mû†6Æù"YU¿ªì¯À6ªÙ‰‰.sŽFG“¥.‡w'ûâìàÙšqïeÖòÔðϯ)GïdÔõõÞ;ìP…ëÅþLn›¼*¹¼îé™çðÒü =÷ýwYú™™ñì4r{¸úïöXÊ ­‡;_Ø®jêèÏÞñÕ84{nO&7“½¸äAìÞù1¯V(¨ÆVÝT§Y(4°Ê·ïTFñÚúÿŠŽs‰ë½Àa AÔàA=:³­]ý{ŸŸÄBË"½¢a9±R|Ej’*µ{ÞÍ¥­Ã­êÎ?®¼†*#N=Ÿ+wA;Ír˜bÿBÎy}à˜ÛݱøW@t!¤ a)oúû¥[åoÌCÆRg¤ã³‹{aôâÑ ÍÇó_¥T÷\‘k1õšÉÜÃbrç¥;™ßKeKÉô>¹éF×}D½#ƒjbý ÒÎB«‹|R,5¥¹iÜ5›$}aÊâm–eçjŽNz7 ~‹½OÒkAè°÷x’¦$¶¹œ÷á{Z™ÔÎ~ß<Ìê¶ Î_ò{I¬d– Ð†˜š›W*yj‹ﳞo–ê êfÜlBqê{Ýý?ëþþzLk^_oùâòLsÆÖ»²o*•ŠñçPÍlyXYI%ÇËÜ·¿-ºõCCH(åIļªÇxË8**zQZ~JÀ¡Êü±ä È-=¿ÉéFô¡ätÙmß~ïeÃñè¹»-¼•DËù®—i¶³Ó7¬`»¯k1ä•aÃÖÈŒŠgµþÙ9/š5¸C„ÓDêvŠvÁÁuüJÝm7z ß ¬ü‡¥2ÙÎ¥(0–»;N×™ró·Íôô®v(°÷¥R*cº]þ×Un3ùlÿ“ïÎûgyê-½$~Sr&i9ÆÙñ­ºZB4Á}ûÆ-àX`83¿eDt‰Ã?É=ÖLšÍf6¬ûìçEQ>VW(sã_«Ü|P.ÃÃÔrÜþî`q@ûì¤`=7êÎ*DI(¹@ZîŠã©£3z#ÄxÉÈìÕ¶÷ï™| é]þV—¥Ùz÷¯zŽ¥¹ì©4ëŷбCv¦ºN‚óžÆPß9t­¢-—iJ cTΡ'óGñ;hVêW5Š›´î¼'5¶Nñ Šœè¸x($ö ô¿†[dK˜ß:Ò•òƒìjÏAà+¾š]7;Î:CÙüÚ÷¾­wÙª¹é%xSšåË®·óþ°¾~YnwWû­ë?Îûñ-S_/Zª½úÌö×2vs*ɵcÛ?ÝõwÑ·‹°1îÿñ_ÁËû‘Y”4®L¬ˆ#÷?©Ÿ·SÆñHÓÁb?˲³Ïø­mç¨ñ )ê‚M^Ôö^Þ&Cù2e«­nŠ{´Gb·p<:ª±®TL J/SgÚä÷ão|+Ê3_ñ½æ[/¢­©v0¥ ¶èóçßb¤ÛÛ*¹¼¬s"=VP¶ž¢­á0Eþü¼TÛŒ}®çÔ ›ÃŸ‰aFDÓµ£ïÞ%ê°.héWÖ&~uY}¯…vYëƒ.€3Këõœl+•‡£ëwsíu“ÅoÓç1š1¶ßårÇéù+Y°ðÛPª²®‡}5ÿ±»2¢‘7’‹šÃç)÷Ñé`½ìæ°‘-«r®–­|´þ³C«ÄÕ!1”áTv%¥CWQ̯µ«IE1,ŒÓ5œ¬f×ë>U¯²…¿;Ì<Õ°…‡ß'°‚tØûÛxuOÐGÿ&æ‘SúzÛi¦­«‡Xê¿=ËWý«Ø*DèÑ ñ#ù}bmU†šÃ>ž{cŸ½†Ùo¬3gÙ§4·W>x%mhW7ýûì;u¼´dê*.ãÍ£µ†¾ø­·Ž#|í§ëÙeÔÁ¨Zm|7¯é.ë![¬%é%Ô~Íwï-a¨³ü£sôný|`éø5¿‰w”íös[Tg„À˜ÓºÅDÔdò—Ò– }ˆÂ†Ã3ÈKϨU+y+Ý£n–<ºàúwÎPu•þ3|5tޟ¦Lr´Nü¯E-ǹ±µ*9.—ûg#½®Fé²ÿ—>ż8$æ<3=f¥TægùZ6«ʵ-{9°C*a¿1øþuÖ :U’çeåÿœ B¼'*’ÂíóÉÓô*6ððÈ:OoαšÉ9KMlVpB/^äo.Àg7¥b‹ü¯"ˆ"¼Z£Ž€Õ×iǾº¯ä½Ktå>Ýņ~+¹Nþïåñø"^“õºˆÞÞ~fá­‚kÞ¹‡!êêõ²Œ¬ùýksL~—gRÕþûºÙÿÕ<4£~ŠèjŽÇ¯qúŽý$×A.½TT`Ü¿ÉßCwi®3’ŠW¯ »[(Þ^6j¢‡ÛîYßµm«â<öcp¼~%$qlGÜì”[ä^Âu9‘o—|^w\Ñ ºm"T¢üv¯+—ãk[Üûk^^‡‹lë¯Y‹b¼rÿ®±Ç5§nþÙd~;×'5ïÌq’ôÊ^Nš5IëÆì¼«>£íituÍLÅ}ñèé·˜güK©~ˆdi¹fônt&a/½ @w|÷OÒ„þÂß#XÇ»Ô3à«Ö(Ôs9QÝ—'¶mƒev×:ko«ÝÝh?L©Àw}õ˜’ʽRsµÍM÷­A˜šŒŸ.‡Ÿ³]Ý5`ð6ï=¿æ›c‰¡Ñ°8ô°´ŽÎi_Ž]|«H@JzÚtn›­‹ÏU\ü‚s]Ë žÁˆvcðÙÝA“™Ú@6g ÕY~<¾Ü?[bAž‚WbÁeIþ7±CY¨øé8¸ŽuòEô6…|ù1•JWWÏ»ç´ÚŸ]ú)Н& „ óÓe×ýº?ßz»^5?ê'w#=öW‘ëng£÷ öÌçd1©ë¹óéxÈe(5.ó¥ ´é¨¹ÙåXµz[Yí_àîZ( ¹übUû{zrì¦ÃCÝÔ.W,æüÿ“6i@MwÇá!#çï$þÙƒcÜÿµÕo%£Í'¹#5ÓLi¾¡ÖGÖä®î5ˆÚëØ-R#'±¬ªµK«?;8€€‘8<¿²œM®ÆÍ|ƉFÊÃR`)Ÿ±ÔµŸ³¯ÒÙ%±Œk³Ò·0vÍÑ<óøUº:êåöaböm0ÁÛùü¹znK‡æY_ÒW­ãFȰ߷cəÅèw&$ed:{ŠDÕ%ýv´þÏ}ãæb†?•WŽ…»‡yåïú8u·j™íÂ[1‰lßÁÜfÊFµ)¯Öµï›Úìf$v³ÔIZ =’k‡%cøöÅ\…=?Vñ!Îû?ŽîÉ%wúy~añšÕUëí Ì çê*¸,rñɹ¬äü†7A7‡T¼;b‚Ì€/¡éÿÌPVI”ÖH×c*A§›_ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøkk¾¸Ã…d0p><ŒŸnpçví ±“®ƒê‡»€>à=÷Ú èµ>«×‹³Ïv¤8ŽöIë4õ”Q–ºÛ=(=Žö  €½†€i ÔŽCF@Ó a"!6ÀÐõé v áÆ&òû€ Pcªù_l$¤ùäúÛ|=´vŸ/¼ûoqÀ |xç>«ï¼Ù³}> dˆœÕAß}ï¥=ðm<€ï|PH)%UR÷=¼{. |ûÔ@÷Á÷txÝpç|\‹¾Ãî±q;†Ù»¸ºÁnãºÊH»2:µ÷jçÁÛ툇 îm†ƒ¥»–²ì6ûãïwz÷¾ÝäðR•v­àõ¸=ë— j´Í-–n÷ÛçƒîãpªÔ¶ÅwǸ;{ƒT£mEm÷ßwÁ³¦@û[ï{…¹ƒU*^Žy×½Ú@Ý0Þ|Õ=ß,úxÐäqÀÝ;Âx …z4t ºaT²ÙHƒ@}´ñéÅaÖîpãAÐCD]huÝ”®€4{°P=†zæ` aÒ\MØ©-+Q¾h8ÊÚðúˆï}Þ/¾ùôx›ï¨ |ßKï»ÃÖ¢²ö$­J®lµ¶ËN¸ëH=·©š{ä*Ksݽ­@è2­‡@ÏwÍ­ö÷F“fÚÚo¾÷|Ü|¶ÔY†f+ª]qsŽi‡êÏXPlë;U!Íhµ%0h3TwÙÀwßg^lúîjÔ5£[®UË)>ÎñVO,ϳaš¥E¢W)1R”lT$÷-îú}€kb0Md›¶*Iæûî篹Ýí¤ÓPÆ1¶™¬È÷¶¶eD¨ª*"ª Q¶ßo—iî•¶Y5­* ÑVuíZ«3Ï|÷ßoqœ‚†˜‹çvÜ64¶lCM{n›@0­² )çŸN'§@›¨ EÇ×¢‚†E”ÖP $Ñõï´oÝÇ\Œû5¬*š ”vÕI:×6 ùítL±¶”g{Îxš{Û¯G¾ÍîóåçÏ­‰Ô;vúœ©õÏ™Ê(j"0 &0ši„ÓLÓM2`Ð šahC&ƒF¦F4hh& š €ƒM€ 4C@Œ‰„i¦†š …<š#É=OSÒŸ”Ÿ §¤yOÕ3i¢ŸªjŸ©êš?JhÐyG¨Þ©µ=F™¦“Êh4ÐOI¦Qêd¦€š„HADcI1Oɪ{SÔ~©§•<šždiôž§Šz€ð õQê Ô2£OQ¡é Ñ„Ð! 4€M$HM2d›FI‰‰Má4S< §¦¦2M“ÑOSjiê<5M©£Aêze©´ž¦ƒ 2   4Èõ4PH„ÄÐ@4M¢a0#É„™¦™4ÈdžB`Ò`z‚i“Õ? £L©þ¦§¦L¦OI´§©ãIš2j›Qú¦z$ÛS<š‚$‚ ¦54Â4d†Qš)馨ý4§êŸ¥?E ¨ÛJdýSѤ?TyG©å6¡¡åª~©¦Ô„6 êh?T4›(Ð2 g=Eõ¶}D_¿Ë™_e-Ôìwì¼tæCÂÁ«çö§íT¡mÑì¾êŽÚ4¤µ´0­j˜þr{èÅDþL‡Õà h—TÆ-©$•+YtRU¿û®bƒü¤3ˆ«úpÙб-”‹hÒÅ´Z2–ÅKv‘a!eq*µµ+U¥XˆˆªqeTR9ü½¸ÿïÎs4]ÙýÚAÿOèÆáƒ=.z)±ê<®þÓÀé®»­ÇcJB R Ã°Q•ŽÎhÐÔ½7µ{Ls­ã¤âÔTIHÓgd`¨Ó–)–ȹ0ºèâÕR @RŒa†4”†âòúÜÎjÄñò€à£¹ýã·ûúä¾»“öçÜÄ÷_­nC•y÷Ür¤g¡õx7¬ +ËæB±˜aHaM(4¤0¥0Àe¶ ¤$’¶´Ä¾÷ц° Q†òã\ˆ±G-Œ1¨,Ĭpkh‰S–LpR¬E—-q’¨¦0Ȇ$©¦28°R†3¼•$#ćw^rzH 'S_΀/¯‰ÝÇó ‚¾ª©ãELYé΀_É‚”Uòb~´鈩©Cì»ÿ%²|Xçg‡.†[©bûã¹úñõëù|ý™ýº×YMê_éGþWôÿß aÖÿRÅþ«ú¹ü¥?%2Ö¦ò”¥,ˆÂ²î1Ù<à‡Rírš¬”ë/#/éÜQWƒ–Ê*êaå[«s(—µ8¦ªš"Ó¤©î1<ÜUNNeLqƒëAü¯úã¥ýjþÝMý³·øåúvýcøS›pÀ;Øw_ù¹±Ô@YMD+ê_h¤˜>ÒŸí—¸õXäQ FCÄ=É/RLÑ¢µMj¦5«iËf°º[FrLyqCËe-JíÞfµ—F`Üt˜i¬t©z4`?Ê®˜?ÝécÆèîž)Úw¹’"¥íDIÅ)”î<<‰Eá²ÌWNUªrÇ—™›»§w‡™Œœ©¥mPÒòN˜²Åo”êl|TŸKÑj˜Žt$†?Cù-a.@©„e 7°ã{ê÷Ð0'ýáFëà~’)k¡Õmh²Oóî¨N4?·œ¡ÎÀT9H8¾]#•«‰ä׋Ûõþ¬_uò°ˆ–òœš¹ €b ›9ky¿‹cõî.ù‚Çåü?ƒ‹ÿOFˆj÷6Q ˆõÔ–XDA`ÄdH’#ü_âö}¬ïï‹“?óKØ7rR~å5×̈;2O8`M("EÍ!¤óPªš¼PE ¹€xøÑ€G°ÿ>ç. §(&H <•ƒÂ2‰²²—zYR¯”A*˜Š¹äÞñ|lù£fJ `P'$¤¹ÓJ¸ úƒ˜‹|6ùnQèòÊ”ž2Û”r¼q¸X¿tÙÐOAD3^i¤èÐ5”„ ˆ©¥@‹ÎêPÍ5Þo9u‘ß!3R–yÜÚã 8{;œ—R_JܬaÀ‘T`$1‰f‚’ õ±üäú©âùÑÚíÌËXÿzTs[ÍÎDêT*ƒZqZåÃÇG—9Ì:·pƒHp&ß”€„ ûƒ^Êó¤nP€ÌVô•U^Þ¾ýè½÷ÏQ‹‘‰²Oßî—:³ŠR‹» Wª\‹Ôn“ÀòìŪXÒÈÄ5Ò÷®Y0{O¡×}“®÷Öeï&êÁwpĽ„º’Cùºv}eê£ÿéòÿgPÛ§’T „±t‰4’,HCHa ]º¸c¤X¬J.jïonº†îqWK˜!6 y1K«Ï;ð¾1±f=;tX95„r¡_­ÿªÒÿÖS*n-ûÌö²µ/=ÆPž¸€…é¯iû5º)头o+Ž[ç,Ž·ß°†Oû>B5€…(G´jºyR ji„þ(ss _“¥¬\7M}åáG)X—/!Ç¥)AJB”›JÑl§Y#áS ØÃ$:cŒ‹å!±°Á§6Ûì7{ÅMYaƒxHΩ¯x}¯?Œ':®|Dtkcå[‰:«.ÛïöŒMvPCTüŒZ…Foæ÷–—ekK“ŽÕÐ)90fÚR߆2”æ™Õ¬µ¹ß«ÄùÌþyÊZ¥Šô_úPß-ƒåOI-kêù·×o?þëö©o>ôŠdÄ$.Õ•3“]•ÈßòìU5úB òŸ¼ÆaФ öW¦ûìU+ìÛùÛ#TâSö]~r1ÀBqÈå#ˆœéïÞ…M¥ÞZ‹6ådƒŠú×öOýez‚FïU MÈšÕÊå#ýg¨¨ÞÜTÉÉëkô.(è1~”ÕŽfö¢·‡ò¸W”?¹~ïFR%öIOЇ;V“»ð4 9ÚÞ¢è%ãÓuŸA³Íuªµ^¤/éjFÍÇKxg Ùå“Õ×Û׉“¨Ü¿'ò0ú'í}sã¤6pòg{S^·’”Þ¢b<€ýÿ¥Úîoõ“AæâÔt½ÿÞøX½&ôX¾½ìé¡ö|-Ï)õ/A>+ŽJ_ÊuGïã§8MtÝe³+‡Kˆ7ùhÕVÈ7ç‹gÖ7ç©Ø¿ïä'¶ Ù•,GÞ<ËÏ}Q”Mh©2G×þý«ö.Í$»ÖûkU?[µMŠm2Ù“}cˆñ7Ì0#íÍËx8úÓØ–¼ˆn^õsÏŽTPcÇTw´Üèa[—u¶· IÚ%FYö;8ÃáÖ}fêÜôa=ù&g Ä40=p²_‡v¾eW=à„oÀä)rï¬d$œ‘Á!7pæBU%c»°)g!,_Ý É@ò£û\IMiÄÞ›œõ.áåñŠ5Ê ªL½² …:ÙÄö¸Å‡e«šC)߯HÿªÇ½ë×°êÓš`.>\×=9°¿]`Ç÷dÑ´YS3Åt¨ÇÓì]Õ.–¬eQÒè¨Ië¢uy‰Í¯Ÿ¯­Àعæñ\†õݬN‚Æjº«ù€ê{CöŒæ;–þ¿äè;o)íòˆ/ÎE<§§Çô:þ»"ÃeêÛZÒÈ¥Šj :ýÏ7¤ÿo¥ì?çºô^*)Ÿôàcþ¥~öyôÁ«î~Ñ~µå5mY( ¿ò¯QŸòpüoø°íõÔ"ytKù`£œÝ}{†NÕù™ùtòÚü]<‡î>ïè«îQ±…Nxô½øÂÚ¦!ö•†K´_þ¿é>9ŒíUEŒ<Ü> v4ƒµO‹‡ÛçƒmQR÷FÏ?ï2²Ž¾B¡1(I¿m%XrZ§¥_ÿ)ù/\[U^ƒåç!!>”ÿ ¯‚¯“-µ‹ÎÕU?¿ÐX±H¢È¥ea‹[/Ø @Ÿí @• ºý—šÎ½ŒíÏñímüS(¨|™u‡Üþ¾wÞ“á°ð'‚ÁþžÄƒÇî°îÅ|f ú:—rö›,K‘Ç’ã f½rP]ÚÒøDÌùÜë#ÌèÝl±æ¤Søå*B}/»³Ù’ð¢Hòß±Ê^Øýüv-:Q9¹¥»J·5d¼]A†ºQšDP!!L8†YpÃCÖ>XHrq[¨%tr.rL{J&åä+éïÿ¥ƒŸüŸéØcû­ìÇ–G°ky²ÏüºKš6mŽ;Á×ùðÆ4ÓnSÍ8‚ú„­ÓûÛÝOGÆT!!²+dU 1TyцŒÜf0PQ$”%a4ÀèÊÀa”±FØEP ±YDÐxê}.מ|žåÐ÷ÏÔ±#'Á„eE*µÂ»:]êzÕù°|Ëì_êÁŒ2hêq•ñŽì™&î¼×÷&`wÛG:®#è™:ç˜=CÆtty—úë#dV¢ek¹Á“¨Ãž"ÎWú9i†0ä’Ûóᓟ|'Œ[ Ð›`øPOqTOŽs‘6 ¨ð ‚¿$TDú+/w%ÄB,D„ŸY„XAH¢‚ÈŒU„P" dC‹ÊXN}ÓþðóûXws÷ï°;k‰à&"'/LÜî_C˜˜`ÿãþ…ûøªš @›óPlM8ATX£^ÝaBÈAÝ©í:Ÿð¾ l§¸˜§¥5Œà30vaõܹª¡ ®ê%%+Öæ¦_+7УCï˜ èlÂ\)¢4Ÿ[K{¥W«¯#{^ï!/ ìû‚ˆ"àÚ™n+… ¨ ‘&\á„ÆÖqr„éܵŒª.¬QTݧ»Ò§q‡’ž »ŽUd2˜´gÛg4MŸW®˜›¸Òh–2`2F­ô>€ tï° éùcÍîôï£ë#"Ÿðl='˜9úð×ʻڪϰ퇱4†0ªvoRyLÏuñƒL8†yµÙ ™…Å,½`"·^U0ïܺȴú È÷ˆå(*dTf•¨«ÑüÞ»É*á˜zÀÆ!GÝpÿ#»”¼ åT¼·X Õ_,/@K–P½u§„t(ÑU“O{-€)%l¸=‘Tm·â¥7  ‘GÏ8‰‚ Õ, ÅÁÎr´bü²‹úLÔÔñäU\ëâþšé$’I‰o³Ž¥ö‰´Ùü©Ÿv•lQ‹6I> к|¢Æ%êbñqËœÓj ¾¥BéšåêÑÅFž¯ç}GµÀ/AötQ 0“"âò¿/÷=¿ õ„ Á[Þ--Îo ZS?ç7¹ÔþIV7 êíñØ‘£¤uÿ;éyz½•ò [Û˜ÕëïÂ!ì8b÷[ƒø/7Ò¯m’½T8íó‡¦è.‰a¨„×c2À˜î(Ä JÝn·+¡t¥±™¤=Õú´ƒÅž¦›„Á>›¡;ÖÿIÇ‘H2xÈŒžoã+-»ŸvË9Õ"Bò-;Ù^E¤NµÃ½†þwdéðïÚ‰èHžTþDÄ}3Ë–}{ãöû _ÛG·)Î<ÊÀ vYòÅñB‚Á~«¦ò„ð\‹žY¸ò}G¸ ˆ2 )Ap0Œ"º>üUå‘'úÚ³'ýþK[ØWáé*›¯P12e×ÚéÓr5eËu„XÁG?ýË:6†Ì†|qPø®w¶ü+ÏSqòd¨¤&é%ìTdÂ^]ÇÏ›†ë™ƒ¯­UëaŒXè 9énõ9ÎÓhÚ÷Z "dF›ÔoÚ©uŠ„€Ä%J”é\÷îåÆw~ØØÂʲª×­Är ×YåäP*1×htÔ.ñì(8ߎÓçÄAð¦ ~þÍNÄÇU¶¸™€¦¥ö8MÅÊ%†+”±¯ŽÙV_å[G¼§-±(!“\f xù¦¦‚„`pùñïôv¦ l âή¸ãb»Ø{—ãçpçæ»Jú*vÓpõ-¸ìáº('¨Nbô<‹éèLªË}ŽšŽú$c3Œè¼Å›×ö¯1&/Ø“¥µ=)•¹ã¾ù-ÿ#‡"‚÷Ô›‘G;l•˜. ñŸÜ«íÍQ¹UåÕÃ4u¦t¶ì¼NÚk{í—5}ÝæqS þàãéBŠ¢gå=Á•û?Œ]EÇøYÿ7Õþݨ̖r–•A+Ó°Üøôñ·ü0‘O蟃¯Í$wùßK(b?kã3Æ¿ÙK«‚wœ`w>èÕ$®ëß…ø\ßvϨƒ×Јë²örŽ™/â-ŸñiiYëÙôÄ ‡»9ùKïke–󯵲§WÈÀ•gªÓ^Ù*¥'ø‘¶-Dmh>IXvêxÌŠ™«ü<}z“¾±% ~k¢í¡ÜÏj|RøT*“~Û;áÁusÞ¢·Øàî$Ù$t&åCaÌë¾må®;¿CÿG‚v½HÛct+MÝzälVAÇÞÖH,F4¨@+:Çw¿Æ Ç:¶_g¯ j¾OJºÝ¬ßôa8wq”e|º ‹‹•yŽÂZó¯Ÿ_Œo›Ú«÷gƒýen|€X÷á7ÞŽ¿üb}?'€î—©âá΋öͺӶÖݱÇVîÏìãkÕ9´|jžMwAg»IÕ<Ád1!})×ržª,¢.+R‚®.fOE1÷é Ùò"%²Lx·Ìç²1Åú9DÈŽû®,U6¡ðùhc&iõQz?»‚ã'/ByKîyç%–®½;aÂò•«2íuù2XŸ¶.a jãýɾM¿oñÎSlS‘`Û1UìßódßÔsK+K £?¾ãåÜYú7äS9v~ mý VÚ¿’Ѽ†çu<Ú-Þ¦Àî÷¡1³ÌÍUø¬¿þË‚NêÙ§ÛCu´ÉuS,Ù38èŒW+õ¤ßÔwÉäkv±ô @rßUÙ5Ö—ËììõQe°ò ’…Æ$LC÷7°9‰iXØMt}wª¹®¶#Ë#NJ¦¡yÆNKUÛf”ï|T‘Ï-MÃîVª¤;nJn]‡d®¦A³ ¹úµm¢Ú|ÐLx2¦ˆÍ†CÒÝ™ðäu¸>uQÛû¾ô>3öµé%f¨MÌãä5ÞÝg„­ÝÓzN³Füib¾}¯Ç®Ó{Äéäèf^d9*±Ìª˜õ²Tâ.ob {n°þgIÃÉ|&£ôŽQqêžTž ¥…f¢x³ùo–:[¹*X »ç!®²iUbÁÆÛê˜õÒš^ÝÔóYS.ãô™'žI$×ßÙ-Ò]ƒ¼¥¼P?"_¹M_,dƒçvMv·­w‘©¾M¥av©‡G~h’T¬AH¥qX6Y¹dú’CÜsBÊ:QÊ´”tƒì§¡}܃†ç8P–óé®pc÷O;ºéí®hýIØœ$#µg§5. Ñ6þXn"Th˜ÿ‘ Ý é&^«òÂÚ^ÐŇGˆ—­JH—q ! ½‡ÙÊ7›¶ŸàãžîÜÒÅÝô¦'HÚÝ }Cä?´É®wbm™7ÅîÄÚóòÓ½üŸ»e®Ý\£Þtù*†Í­+!ËÓ· ‚G(¿ ™a#?Ѥ”R®Ås¨²JõvC‡È¼Q—àdû Qµ³S—‘ 's;ºe¾=©§ÁýÌm¼­l¸Ê/F{Àí5ÛY«‘ýv¨¼.; f’žw–µ§ÃL{Ùesß­ÎâÑV⦃tÇžŸzØÛeç£ÞOþõYxyojMÍ«ÂÛêéaŽR,éìI”Ÿ;d=DóŒ¶÷Moªq•ÙS&Û*¦BO1C?ù WŸÃKœí\®ð“8pÀ„?o𽲺PËÔÄíΙM‹û–1t¬n1y|RBuÕ'ƒòø?Éû¾ýÔüïÜ|ß4 ‚wÑwU zȈ»hëDS¯"ª‰ÄæM(ý º›Pýö¸(÷7•ìÄQî{Òû¾F{"fþ&³©•üáíòÔ°á"27Çc5€ÅÐbkþT+÷â‡ØúÔußr¶Ý.ÆÓ‡@W…)DMr5€€©£‘V?^á@µ€ÓI s XZ -1dW¿ò|åKqÓõ-,ªÓÙUlç\`JP$s ¥AÏáÿa>ÿBÓý:êt<ÂRVÏõKùÄøfåÌÇÖàÿ«þ›æ‘èΤo„Û¬-ȶ-3TÇ2ê,;nìKÖµÔÅnPY‚@ 0#Ã,(ó’‘M†ÏbÞÂ.4"J†.Æ ì(‰fÃ+lÍ[(þ‡ñÒœ†JsBÆÃ gýÿÔô¶m¨ÕÞ³ÆmƒžãÁ¡™À†nZ’FöOêI­ݛܔÎ\ÍîTÆ?ú'ÿ!YKM¯‘Ù)QBü 0CCà F¡_ÁCsÕ¬âr„£ÕXEm';D`8¥ ØÈì™&Ñb*±""ɲˆÌˆ ð!>Û ò³HOÌÿã’ðèI1`€úéÍUvŒÈ .ˆ‚êü‰ìWÃûÚô*u¿ã$ÉNÝÞƒQ> Éà¶›ÑeŠó2øûô¡Ch T‡=Ü”l A'¹æ÷õ¨}BðP±‚ Œ–ز¡¶H$4EÍìmѾ¿ÝöÔD¥þwìüáÐø~ÆuöN^Rööû ¦(*‚!WR%Au(£èbÇMÂÕs¢8ógp÷ÏçØÂxÎóxÿë †º‰à~& Á=Þ¾ZkÓKœ´îGÔ è ½¼<Á}8ÃÛrø>v ¨ÎÔâÿ¤š3ÖЖŠÀÿ÷üƒŠß|Ü%äߤ§³­k‹ËmÿÀƒ<ÅÖC…83¹¹6íA sÞ~?QYl··!¤‡Hé Û¨Wžàû­ «ØÿNWé·“s¿Ïã¾ï–ÿcʾj.BÏ|1¾‡ƒÃ ãŸMmÿg[ĵ/zx?ÑÎü¡´¡¼IZ¶ñµfÁD†A¯W6NpeW3œàòUlWþ¹„hß¿1ð+3œéIi•Í×Rmµªç\ì€Õ Æ7À eŸAì®¶œ½çyn eÝëiêã å‘ SDSD»´gÐݰ\|~¼ ?¬—ëÛóu݂蓢(âÿV¶ßŒ›'·åøDqÎ&¼9MßW¤îåÓ[æC (æ|>6#u>ÁiôîîÀyïlн4gd¤éããL’ ØeÍŸ’a6§AÆÌA`ûüÝ¿/ðšBÊ-þrE&®•ø_Û¼Íܶ¨EF™iÏý;ƒ‹¼ P‹n&ÏWFöâíÇÛÑ3„ü‚Ë"UhÊ*ÒQƒhˆÐ)f[hÐÅ‚ÄaJ´eZQ±¡Z‰kj 6Œb‡¾@Úp$—†–ÕÄËC°2_’×ÀuSÚ:ªøñâÖ¸X9åpœ- 6PÁ,°"¢ ^#R‚Åhˆ­4D1–'ÇÝã !Æ×ˆ) °Æ19óïñæãÒþ/–o^÷S°¤xß§qË–æi¡óìwËÞöß&|7 CW»“îî™*ì±5TN=ÜovB0éš‘W÷WȤwâ03aÏ’5´SCŸqëîiRFyàÏ5Qe¾Qr& ÄdEþ9Cj×8Ù'P@½x×=9è_àðå8mäRÒç©‚ƒï¾û,ûÏgžßžÿgC­–£ÌUIPB^_æú¨ƒý‘êZQDFÄ„D܇L Ø" Š +òúÃaO}‡&9pHýÑÓy‰×/Ps…•îÆxí|rpw•~+ÔQ`åw¥­º ®…‹f Ï!¼Ø¸µûÝ·,^[l‚ —E]Esj‚ü‰• M¦¥Ûâ´Pæ5Ý^ºÎm†Q¼¼›×cµ1ë‰{Éîp¢óÃbÇõ¹§³< æP/V¦Å@\|svpx!Î*!GK“z\z7ë)j»A¬omJñU Ó·ZÉÎû¼+†±€À^S‡B( ¹qRXtªÿ/x•?P\8爷¬K²Ð7' AzÎôArž­ìãßsÑÄ~Ñ^׉‘­T„Ç'³«f;uáÎ*6ꔌ˜¦sÝ a ðL¬Ö:þ{Bx®éÛ1#z¿kú×z ÐŽ[:¹â¹kíÈHosLÆ_OË“òì‰ ßl¼ú“ %Ñ­8ºdF]à€”Qd»½¡úôFõZ¿á€Ö$$öè:H@*B pé²`à.ks禷Œ\WˆØlH®)á»=é,iEî 0á;Ñ&Œ9å­:Fà&1¦5ápÔjàwâ9EÉÄD‚â>[ïÆ¾GìýTQ~˜‚ëãÃNÙì¹ñL÷y‹=Ýá‹·¼O¶4µmQbeý¶½ÛãÕ‹ƒáB‡:é…;©ò²¿nR¨³èåÛ ñ·‚Œï›JìþÇ#ÆóyjÒ$Õì¿·\µ Ïý s„ó"z0Vœ^nœK±w óÂŽ„‚×.¢UÀ\7•ýúŒI <šÛF”·x0‡†Œm ‚ŽWÙ³m®±ÙíZÍÇ17…²‹ÚêP ¹µÜ.š*!ei»ÁÂðˆ€ ËÍ}á7ŽåAt#“†ÑßEG*'Dš›2•ë.ݵëYÐ)p‘Ìw¿›pÊcNm,pr:vßxŠÚH<ŽlwlËS¨5q×,D+{ðŽŽAs< ”pô×tŽ™˜Qì–òAgzŸ46LrUA0ãPÀpõ¯bB±MÎ]œvºOõƒÜÍ! >Q(ë‡þ#KÕ7H‹¹³r¤p¬Ò!f Ä FçX5ã–V(@è©tè`y•y‰¬' Œ":àPn€áÈ.Ö0²¸ÀgewÊb”t0Ö¶o{Ú *ü@žÊú‚ÚD}Þžbqáç*/.UTôùò{Ï×¾}}ýCÅh´ˆX;yœ;dºs‚€DNxX wŸ{!¤Ç-€—Hx™ójZŒ@…«s°ÐÔsª/ÊЪ ’£ªÙ­£Þí{¦:˜7Z¸ uö?UŠ$­Ì¼ó(zi§:›pÈ„ =_XòñМ«óÏ>à%~'OkY>8!ï•h||ïÖÑH¢ž¹ëˆA.% HH…¾î}{î-'¬ù€ƒœ8è*IQKn> ¦¡Û8=šõ7퇄¾kÓN7‰3Ä.ƒmê$y;šï @cx^MW²±N²(* PT8b"aÕÄð1òÚEÑÔ•ÃDxqç\ƒG•Bx©m©y°;nŽèauùA ¬fïå®äd¯1(ëËgû¯Ä4û[xwÔ¤ö@^qðáõsÊCø[_‹˜ÚÁ”è±ðô>Ã<±·9sh2†ãžÓ6;²—ü›‘7Žq°ÝǶô×ÕØAʰêÁÝ‘Q@(@bÈ8>Éç§ÉY'ñ ¨Ñôq€yKªªùØÜ¼ÂïJ^7„ú† j7.»T{ÐgÀ¥qDC{¿¸¹í³êÙÅ%He‡=,Ìê\òdÕµ‚Óq3oWʇËGÝÎ^lCìô«¢¬_W§‘k‡«áÅ‘ãªj<‘à1äåÛeAs£©ìÔ3YÐ̰VÛê{—°ægpê臂2òžcaÉ…÷ "ßK¾5õµ ½Ý4§@6¸m…~ŠŽ’ù‰Á'NXt z¼cºZkë5¶Æ+ºŒ!¼[‚¤áN¾»zÃe˜7:€ð$©xw0; s€Í5&¤Ö3eê·5¡äÈ ‡7$¡¶l5׺üc¨Lq«ƒàH@ºû1Þî7Ð^*1èsÒâ8mŒž¡NÜBxú‡Æai~õøy7@aÌ8~Þ•Õ×ìvà€_ÂÞ$f&¨H”qÌ v˜„=c˜ Ç½ÌÚ–]@ÎÀÜøaPF1“gn½™åy»rö½S"¬™ºÒõ‚q¼a²‘ æPâJ¥Sc3ÙΞڹÆþÇÎGÌr^÷%¨;´ÄOo%*R‰´‚'š€»F;,+Ô%Ô5 ½÷Ÿ'ƒ-üâsÆÜ1w3†®p××,,$­ Ï’^ÑHb1öú³ëêéåÖzóçË>q]ê ‘!Vâ‡NùZyõvòeɪÀOgf¹Yl–ƒXÁ×v{÷ÑîäT†GÇþw/ŸPâ:õc¿o%{Ùd4[·°UÔú§šŸI«FÈ}[ÊÏÓØÓ|.tÎÛùx§âš…Ú\w‹ˆòqœwެé¹ã·áÚ;ˆæ)=%² uÄ®îj ydBBmÙÜ•TQJwµÙ £˜©[ñpÚ­ˆµßb߆ß=u™Ýj:È|õ[C»ýpÊÎK&#ÈMdÅ0êÙ€[)' ³ÒÖQÔu¢½ü .«»:µëø/¯!ÉnE–냰õ×^Øëݦ´hcå’1!ÓÙêˆv#eý ñ¥íš¼O"T_•Œ•kÊŽ`‚¬ƒapß-­Rûµæ¹F’ƒŽ0p8^þ  Í¢Àtˆ´`Khur„ŒÁˆuîËÖ2Ž’ÄXkG†½,^&››ˆ/—–Ž …uBUà{>°2d,Òå8žÃëbÊ1½Ò¾ªÀ)Ûj€òòçÖ×<2Å–F™C×v…(i‹УDÕn6¬”¼É‰BŒàùAýq´Óáò<†NáÙê¿ô±”êúz††9»r² D®‰ë.SNØÓQZ@1x{È@/z£ŽjÊ2É `|3AmTawÕá8¿JÌ%žûÖ® ä¢†ÁF»WUж›J6ã¼BX$9ù¸o» ,*h@$¶‹“”€/~„†lAÅã­œÛæéb#JÄc üÞ{û¯i+à¼FA!ˆë±ÁîsîÎßT†ó‰]›¬Œ„É!÷ø…ô“÷½áÜ£’Ì}§ëði>…Ä@¹&½k¹€ï^:Û¶£¶¨nž¸cŸ§žt‡/mñ8˜â³§ ÉøB ú?wÓxsYc9Áà-Ç ö‹È’c%$­a«ÎP@,âÀ&6ˆÏ1æ*·Í¥!wFžK ,H1`ÌP’Jet@sŠ<9B(–Ž"Ü=Ù¾cˆ)pfòB.ÈÍÁMž]{^ð¶m”9õ-A@iñhüöY™D mͬG0½êx¼3OÉeÆQ»o‡Ué¶Ru4–ÌÞ׉ÁWwÕ'bø(G…GQJ¹AŠªÓ]CžVÆ‚ŽuªŒvžOc®Èò$+Èê}x—>šH}å`ê-ÞB¿u‘ ‘òÖÍ`CÈ7¨qR»×¹Â ôÎ.u¦ïÔMÚž¡ÌïºQÉ[F‹¥m¬÷”¾'únèÌVVÒÓ1©e(·EA¦9Ç¿dŠ©˜ëÛß„{ Æ] k÷èä GZÞã†Fž=c²N]äh$ñ«Òáà$½àÍBŒ÷38 Lkr°T{”}U½ÄX‹RhmpRUãàrD‡©å\ÐÀqå€ò}D@¸í¶|6p«ûïsmúÛ)X¯ 1)>§`bð‹9øìv¡j¸ Fнþý‰ñ8ZX8ØÁب ƹi´™|Ý™°ç^ö›¬ôÃÒ'}Ǹd‚ëgïq#É“ØÂžÓí–TÔvjô Yо™íÖï3™½´Æ8vç·Ü—¯«:~—jϪDYÇHåÉŒ›V^À9RÃ_'ÐíÙz¡ÃT/²ËþGÞüfyì…j$ à×ZóG/&”’Éc_ ÓËp—z³§»Õ8úâò¹c¨sZI¿llÝeãPÉr¡Þ2xó=ÚÝ8fª< ´ŠX Déζ£¥wDj)<àJ½úd-2ÆÞl>M‹³å|Ç!AP˜8*î‹Q­V!¥;›j4]G:cE ¡Û\,´t¨±‘A² 5Öƒ¯XÒhc¼r€ÏL öòôôGÊgfɆ‘Éˬ`¾v²Åï >h/¾4QËô8½ß.:éÚنؿeáJ]˜^]mþ%€mªÄÄ”Ù$ÙhÕïÃÏÆ–™X«‘]{_‹ç¨¼‹ÄŠIuòôÅœ:q¥; ëV•q’´yxòJÊÅúÖïyég£(·%uÀ0ù—*®2ï JŠï›¬®ˆÍ‡| Ž¾DЛâe^¥q¾…rôhú3Ð,)¨êiT!SÓ„lùâvæàë0¡Î…ŽK¢çºé'h :3É®evXÀº§‰†6#Uп9'¦ÈÞró”"Ûì¤C=³ï™H Êl,Ú@|×ÔÜa%»Õ ¦80ÒªÒ„M0ip¾¢Â8‡|Óív¸ áÀ—G;××S“µîQX¼6À)Ï,é=yFÆ]ÈL¤~/¿Ãƒ-;üD`¼¢a>Ì9êm;ªõ0fÓÔî¡@HH•Žs({.fG’õ“D‘ä»D< ×ï¾$ëô©½¬éôÇèS'qÿB µÜrÉ‚#Ú >çÇZjâ¿Ïnÿ˜œÜŒø$ç'{ žÆ   ›–°3‘`VK?¡ƒƒâ»ÆŠCÚß8 /˜g+`¹€ê’"Ìaàñ*½™ æj´Ò)&+×c1Åé›Ä¯¸JsñDºhr¸VK‹—íäÖ¹\éÎîÞeß<2¸}ì4š|ɉ‡8ðƲê[]UÃÁbÈæz¨%xG5s#2ÚØ9ÔS5S(/TŽ.ƒ˜üRƒ‹ˆ°Ž.|s kyê:öXû¬ ”Ufµ˜ºˆª,Å–ºÑDµÒ%)")(LBwZZ¥Ç̧]޼Ì@Á… –¸æ3êgÜ ¿§ÐÀ3$—KW¾zãû«àý;†¥êþÊ'×ÙÓçšýLœ(ÉãIÂ{ C,æ[¿{wŽ:Ö¬›¦Âr°˜Z &%§s:=ä_ÎÀ{|Ü_Õu×¼l YŽóŒ±@Äy#v«(·7Dw-î²Nò;tþ¸ÓKålB°QÉb‰Ï_ŠÃâ žë(Ú õ³—w§:>«Ù0¹IÞŽQC ”ô'~øÃ|·¿IOaϹJº.X]”íÞSþ ]8ùZÑg×ëëºý†\ák_i-gŸkË—xVÌY½'s‹ò á‚è­Žx úöárï”F2Ÿ uáXƒ?k±UæÒäüG±jPˆˆÎŽW 8B¨⃞éŒïL Rqí”h2!޳–DjÂÙ ™NøœQq:š°f G8¨ Õ O‹ty?b ³éé´&r9ì{S›‡ LtRÂA—~Ô-‘Р»íWê. ‡Í–Sk^˜8TU öÆ øæ‹Ò7 nßkb,XÅoÙWÊþ ÷¸Ï6`RNbcßÃÍÁR@ÇX!ù; ^õW^Cn •RšõÑMü:”6¼Xi¨±áÀóoç,r<Ú7ÊQÇÚ= j%Í)Ÿx( ªwÕ aDØ@M&Ù¨ ÉËž9Ý”b½÷4]÷ jâØ.É#ñÖ#‚bŒ¶q¹S0Cg›$ß[û@;Èv²à'öò䮈èê;­ÀPŽxŽé¨ï~$ù1÷XL–ºð©ù?aîþV9¨wGÍoS|÷:u¢Ë}ˆ“ÝöEÁ8òà }ã". ²(o+ßÃyuG>> \D/"›é»t¦Á”“n¾„õµ‡¯­po™a³XW]¯gFïn¦§ è"(&¹1ºêG©a6J¤1 CÍÚÌHÕ`+ ƒÔzïyHCR¨‚°pÊŽ¾ûM¶¨ØÕ”ìŒHœCkôÀLJŽå¥w„tuò#1zìíB{[€íííXêìÒò´9Ú9Üêß·P BžY^ Ïk»ˆÃ`Ô÷=›uÅË~j*9Ê t$B‹BŸ"·±àC~pt<ަ/ h¡÷æ8:FãÏoZ) ï{Ë=Ï»º‘$¯uÏ:Ì·ãy\ÈäfÄÍ]õë¯Ç¿+åß]÷У+ÁyswLçNï/3éW¯yÊõÓô.vùO}˹äRÓÁÔ.òª›ÉÓ°ëT„Ò«$…=¿Y!æŸíɺ·Î+çjEMLI‹®¶1‚\nš¤ñpØ‚ëCW19ÖTsÖmE‚Ô1·ÄÁö¨¼"–4ð|.þ=üGÔ€ê5£ÎGM)]:&ÕÍKÊ& ›òç%õuZGêÔy%W»]“ãÏŸ®ø©d;·´Þ1”æÁm)7sOë¾SM«–J×¾¢$JŸÄ?9ðíÚ¢6P¨¶æ¤ ¶ÅÔ¾‹Þ`¶Üï1uó·e$Š/¹âÊÌç¸1¶a‘ÕP·2¯Êá@Qˆ}cƒ¥{«R®m—F°E“š¡B—ÒÂù¾«k9á±sL‡Š"¹9ȈiõæCÝÛAšm‘s÷~È¡ST3ÙôוÐï^¼Žkø÷ÒŠ‰/3ùMPIé”GvþžµjÈâ¦~œø‹ù[ü¤‚ú¨Z,ÏY,æœç|n£‡ç°{xé<ûuj´ø_*I „/Žd=æÒÐà,°Ñ"Ö€€"+Å•¤Þðãƒa+(è¨5QY’-±o0,@´Y¼[È’§$o¢ì0;©Ï7ãiMg}ñ÷þLåÕwŒç××— ÖÃðZ‹œ9¾/¨ø¢’€¯½$°ýœó:‹·áò€R;£Ðáx|Þµ£Ý2aÕÏÝsôì²1¡½‘A“ÞC|¶<@ìÄEÒnÈ#¢óÆ4Nœ·8/^A®w¬ä \FÍÑ\ýœæú(2…ÎuɾT€‘ŒªNèÇ¢•ºu#AksÕäIšªï)ê´\ áax¡'ÈnÙÁÈal¾J‹1ù½Õ…tAËÚƒÔnj ‹„ßêÚƒ-Q¥¤¢H g4 ¹ÛØUÀ<$ƒÓBñÓ OÎ!€±|Ð<¤¹1>ûßõ/0ó]ÎŽšV̲ _¾ÜÎ_®g(Œ[^dÄ¥Ó)ùDD@ƒPêc¤†8…¹ùŠÀUd ÷j›Ü¡H£(’Ù«$DÂäž"V„‘{Ó nû¯ ®o×1œ`™ÀèÇGÆ"ôÕLÖÈŽ¹Ϊ@ÆÃé÷F"’ „µÝÙzéuŽ–Ü®E:ÒÊphù€LG4e]ñ[Íp¿žÆ øšB<hñº‹¿•Úö? (G)L|ŒŠE"B…„•1~¦÷¯é±5GíP™y\)EàFÇ4]Þ½m4x`Þg’ Ré¡ó€€"C¶(üy ¢ ùßv29ÝÑÍfv.˜­â èª‡× g·—d²”àv#>·>RQCªÉ”×ï’b.©ªv˜Á+â÷æòÅêñsÜЇHyáØÇÆÇo d",èÚóàõÄw%ñÞBúù 7‘fÚÞÝö.–§<8ATÑ"ãö㣞ÊB(¡Qˆ?Ô#`1äÿû´s©w¼H ‰$¸[E©¯FVö1HiBQHC±f (‘¥àsÌtŸ"ôFêj~Yâ ÕxG¦‡V¨ä‹&³tO '¾Õ-ƒñ< µÝAÙÙlŸ:§¡þzú?Ôna™¥5ÃÅý´hO÷ŠN{uv›úÍÉ@‹=¾såäR¼µF®Üìoó»Å4“š&$õçÐãúýU׿7Šç)@Vr½*©bà@]CÎ:dáÌÅÀYø1ä ùŒä›\ÄÇ÷=¯³uײͦå’ò«&uÌÉeâ2ÿ£À $Á";^·é¹ÏöcõB Îùðõ~€© E@ë•@åª#UI1´©0W5„ÀÈ÷~›ÏX=½m„]â€úX Ý~<ê¦,™pᜫ»•¿Æ¤)Ï9Cù·ÒQoàÁ¢¿«ýÚÊʤÿJÜ9M'tZ,þ|›¸hOo( ¿±>¾Ûm´•Xÿ_´už\ûr£IRóÁ*Yù¸s®êM’Ô ®Ýna?’öM’×ô¡ÉçðYî8Åòòì6˜>„<“Ïþê.)i”íüÞ8ÂO¸ ’'ñ2…ÚkÓüg{?§}ú¢›+ðkWgL¯»…a³ÍHá`ÐmtÉך•¾³vLùïWî˜@<‰œ¸È^Vw!ƒŠ#ˆVW2[eO‰Ì¸Ê‡CE ëJòI¤‰­uëlO vF&Ôì•y© [„å wÒQnh3E¸é&²©[pì4”a¶ÑfÒø 5ÍXƒ­¨FÒNÃÙ ™Íê¡{ Ä –Ý”IRóÁ*Yù¸v.êM’Ô ®Ýna>ËÙ6K[ Ð “TÚT¡8cPª¡Ì‰Èç â–™NÞÎ8ÂO¸ ’&=—i¯±©«³ªûõ=6G°ëuùǦû¸V;; # 9ƒ3õÓ&ÀÔ­õ›—"çÏ{_±æD@4@E@×vdNRFCè¥ôØ@“¿½UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVL B   ¾ïÁ'Än«>ž"SÊÛÒâÀUÒ¨±\B]…0ÌX.ŵ؈‰²Ûìtø7|pùîò àNР*@ÎLt°3 =XÀàM€æ0Àg€v„@*€†´à+À€NÀ>¤ô €+À¯@m€»Jh'ÀÓD°`À $L–‘ B–M¤„‰@ %xxe@ÛéöN8¡u¿J¤Â“‚߇øöž·<é|Áæ|þ‘ÝôM¯K´Z_3;#ßÍÿòû“ê=ÆTU;÷{Û|ðS[ÍkªÐˆoó»zvSc²ó£®0oɦŒ ¼QíÄÊ/$ß‚ùÁÌ »I–žîrÝ-èùi]ÇwVØsX ‡_ë:Â×¾ÿ ¾\](Û"ÛËþx@¾4íÜéLßbÌfÃ׳|C¡¸9°¿ñ]ç³ÕCË\©t=ëp²ý0ÒZ©»Ò{íÖtÑé~[ÖrÖ÷÷m½ûà%co~M©”µï\^\Ùƒª1Ù›n³x›£±vˆcvÅο\qãõG(@^¬A`" lD¹6!ehRæ Çâ±ùøÿsøRLÿ4ƒï“w1ü.A¦stçb7ww^b7ww7ws!³1,œÝÝÝmÝÝf؈ŒÙÞ'»³vL®s-¦rd{d¥Žl¡9Jsƒ£EðYÌÆ/hƒÉ¦Ÿ®–êàœžH}ïb¿ëu­œßk›!×™¤a0‹ªfØ+_Y³³p‡®þÉŤÌãÞ}›¶J¹Ùù3úB>ÂølˆâDm¢Ï,z§·˜7Aé낯ȉu—RÈò&æ®yœJ¿QoÉËærVæ,ÎWéŒåÎK¹±eW:‡»Úž@÷w0ëšêZ_Ûª‡B 7 ‚ð€U¨DFA AdAŒ!BA!¡" XIB,! §]Ø ºðd@^S‘Ð9“´(й“´±’…Š,¢C ‰:04ƒ‚ £CdÓ 4’…šA¥(‚‰4£ s†šY¦HŠ $ÒÃL$GÁYG ,4 ’L0F’(Æ8I É$g ,À°Óƒ”9C†œ8za€Ô…YØt@tQ„´Q§;0s¢M0²‡$rG ƒMG 44ÁÈ,²Ã„’a¢’ÇsH$ÁI!#–9g 4ЂÍ8p³ ˆ(Á0¢ƒœ$²F aÄXp,²Ë4CYƒ`i…9F‡l0Ú õ`Àð†á!¹H–2p 9áÂO @È𠪋4m $r 89pq¨@9…j740\c¸"5{ pßsNãž8ûýóTÕ՟¢á¹uSÍŠÍI¾ ¶CoUºŽµàâws©,©ëco3—ÉÒË9œ³ckjÊ©E>5U¹¼¨¾qètn‘’Ñ»‘2¶ñMÎfKeÅìLÕqùm:ž=»swœÎswwwwwovgktÝqaµ*%7 Õ¹uÉ­b¹wÍÛ¹mÌ®+™vwÓ3tÝÜæUfDf§NrH9ôBª×wÛÞh¡ßw•vêÕÞæï77\ÝÝÝÚªª­ºªáÊåÑE¾‹"äŒÉh"24©§änÝ:Põ||¼H/–q©¸AŽX;Ön*r ›Æ©Ü£–mQ¹SÉiL·w7›¹»»ºÚkfeÞ­Ù7yqsœæe¾›¿_!¾¢ºç}Rù¢¾ÕRœž£G—¸ØËŒ‚÷V;»ô(K_•ÈÞrž&*gÌf—SÌ4äòq+‡•](|˾]ÕÌß[RëvèO[|ɺ§¸½Ì}ºË»Ú|U»“—pûKn¡â´²:å–í;ÐËâQ ¥¯ZE_T:Üã¸êx@T¬£ ~±6uLÏÕ¾KOG1ùoJ3—Ô¹芭wŽd¶\­ÌÍͪuwË¥¹ÎF„Q´×sqlœÎ›Kƒ×è»–è»Ö‚%¦°ýDw-ùVéuÑ<Ìñ©¯ÂO2ÚüÞ6[SÀQ.QÆSÈæOçOqкvîxë”ûÔõ“%Kˆ‰‚ó¹ä§Œä½ZyäFI5¥œÆŒug/›Ãc„4ÜänÆ«Ü!LLhÛål=¬|7–ÛÊÍeY‰Fñ?"õ<‘D-̦»ÚÎB³›qÉæG'&c²cfç­Ž·«TuŽ@M–ð‰Ô;GJ’åäsªãÜò¹¯UœãÆ^ÜÙcâJi-wŽ-»ÙËcj2éb䫗ʬ½šÚ½½Ëº‰›§Ü»ç&f²ªã“µ\Ê©Oýuer«‘ÙÔ÷ø?]ûØ@ÀÍüéR§K@ Ýë¨PYU¬ª€ú[|òÀ¢ÞÀEYéÅ0þ;r ±Æü7þóôìò2t5A$  Œ$ X$gb…B<ùU‡¬‡‚P\±@´žFSñRœòÉ ¢DAXŸ‡˜ g\Á‹DYïo°a.hYôaÊB€ºFƒJi€ùª]/ ×Y§P· ¡ñø—«ôY«ŸìäŸký#Crÿ‘Ø*NÜñ¥]Y¬þ­XÔW» R)úyL ¦Ö7BPF ,â6N#¸1ý?¸ó(ªcØÿ?¹Tiœ „Q»éŸ‘ÜzÎ[ýS´ˆ5 Úÿâ¬<¢ éìÑ\L.Zq˜ÖÓ{NšÕkýèÌàÖ}5e%)ô=Àvtþ/ìGîܯ…”×(1þõcìÝZúa_·A¹ÐðýŸ«¡úþkëpÃÒv¸O) HHœŸyG]$úÿ~Ö’I4¾Í¬R‚”€¥'´¤0 ¥)ZùIîÜŸ¿ÎÍùŽËp³¦'UC??¾Öqô*|Џ+†Óÿ67wÍÖ‰Žš øw¦ÙüzO? ~»¬´©ç/V+IfÁm‘‹¹ƒaòÏö[äw.éyÊ>_z±ý{‚›ŠÇ¾í¥eÓpÖð~€³¹øFIš&“…¼Õ¶f^ðOÀ¢Ì{}óF]À…ˆS" ‰ÂTCwGcbh QýhÍpt7Tã`"t³žBVwèýØcÃTTê—Ôúaƒ÷”ló;*ÜZŸTÕÅ™n;d*´—'PîÃcà^&™hÛMBÅå ¤ˆÕa‹h ]ƒY4•Îd4ƒ˜`À¡¿YõAå¡ d>¯déÞmIèþ§³À|̓¤’wÓç<©!dÙ2Á‰W/w‘£n«B |Ù,_žo¼å »Óóõ2hš‚Ç-­4 AA­qÏêùL˜×??´¾Ò*ÄÞ<Ø`‡étÁõùäU ”RóÿÉÓ[¢¼ÝßÿhK„¡Ô†}°¯ôzÒ_wï}G0¿Bs£¡AÑ?À0ÓWÿ2ÉâŸÒwôvAù;SÜPcê2ˆ®F#ÖÃÝî·¼0 ìÖì(/¶³'¹V }Üx·A”‡UÐ4­™×l…Ô—=£ÉeÕY Ê;2¿ù0 RÅMè„ú »RÝ´]i¸Œ03Û’³Š¾Ú5–b9PB7. þ?Í,êú?£ Bi 5g9¹Û Éõ¥üŸ—ëj° ‰œÞµÔós Ü×-Åâ–©=Êš¿ÿh&ÿ—òºÀÃПÕËòS;Ã5!„ÏñÈãšárEø+'ïX ”$8³xy¦ã<®¸+)óüXNz‘¥œ‰ùCx\ä|ù–³,˜<2z§±îFeâUP1¢h¾b)Ñ0_ä}|3u.—9µtyþ+7·_Ätó]Îà¡Ë݃”ÌÝ#ˆ!Ö‘Q´}ÈA;5*2åU~Þ€R¨·ª(A {ðéâÄš„w#âõPúWêhäæ8~3R2TÙÅ8 ºüðÍüÏ£Åàz ҀȠ‰s¬ÕÙbæaS°»$ÍŽ'׌ü 4žÂ†º¶7ÉÇ„Ãå5qHˆçD;x•¢»5Ÿe«§Ëj^HpçTO¼û“²ƒÓ›=Í«‹ÄÊ¥,Ÿ"¾ŠÇåñ3˜aŒ>êý%s¾<Üÿbí¾wÀ^ÿ?TúJ£„úvÈ>ÎìQbÎÊZúuÙ4¼­zC‡¨×£ÓÌ2Lô«3øÖ ! kêÃÐ8-õ==ù]¤XIÊiÃñ>Çpx#©ã_&ÁÓ`÷éÃ?îúvã˨_úáÖ yÞþcb5 [h·ü–ûgïÞîaú ¨JäúbÞO¾ÇóÞÆÝÏeŸžC ¾Üÿ#²ûd=}ó¯^XåÏçäß*ÏÖ¼i˜92õSV…'·˜ÿ‹Ž#†¾×õ]t 0˵Ò]˜óúxcí]Ôä¾¢àEûùÆŸØg.ÉkÛî]g0¦ËÂó*Æ=¯»8\.òl8}˜F‡e¼7™õ´ªÒ¿à`ººNSK'´ÆjˆŒUF*¢‚£{ºuÏ¡ß×Ù‡áxßÇÃìsöíZŸË>ä[«„vú^R…¼›m.íòz}É^á['>a¼ÑÎgE±¨g¹åj¬Nc–üc ò^rw•%2uÊÒ!Oš¾Íëé>‰‘¢O(àØò~àÈHÄŠpSŸ]O9»°#’ÊP½2\Êf:sZS2j˜æŠCŒÖk.Ds>ž€ôo[ \èâ5…–~^fe+™:{ÙÁð©É*€€ Äÿ á;æÏ&Àÿö–Þ&áÞܾæÖ[|\¼š7;&¸â¾}½ÿwgW»«g†}ÞþBIñjÕA ëQ;5õÎ:7x'ÇBû¬/r¨g J¡=$"’kj>¡ïUâíÈðò#èõÕôQàUõ×ß?± Šý®Qã)£‰R¥WO&/ȤV9jèØ6;`U:Šò½-®¶Áb[F‡Ž-=çÉC)C÷ß–¡ˆ7¤1Ð"‚ÈàC˜¸¹šÙ¯œó™ƒÊ¥°I° «ËR¿+ÿçæêÜN[?€÷á¿/(”N³ßÄ@;Ïò|Ž¿ª*Îò¹Çãêå×)›ì-!çÜñÑ!Ù§7ƒµb%ÿwÐ:$“}ÿ;)ˆ÷û“|ü]¶k÷½ú°Ö-ƒ¼Ž¬ 3ž¨Ÿ/G’Nxå’‡÷·> û>ZjÁ«´¿FÉéûþ·ß¶[=RŸ¥„û[þly^óðÂ'¦{çu˜:qª®ßg¹^c2ÿr {е¹ÃAÍfñ®ÿt_eœ<,-½V;Z‘›®ÚñàNôÓØ Ç|³Ç—›õq€$gÜÜÑøÛ×ßeš×Y—G/xz£«èö_fåHxD§á{ßEæ}½]ÝÚ³¶ëx/†È@ûïÁ2ï6<׿î^5[ðPnägð¡FL;îÐ=éÄ[[#—;¾f;ñ{ û{õƒñkWpâÔ¥oSóãç<åç^´< º9¡'w†-⇂ÝÉÏô¿»wóH]Ÿ1n´‚õô¸sÚÿx8pg„zUüïØùѰWRvw÷wÜÔA(žà*ºñõ[¾‡&A„€ýAõ¾…‚“Ê7ƒr{_ê~ÿÿ¬÷d>ÇÈ=õîüOW"ž?›5 ¹ 0 åŸ –Úî˜" ÐSJ@ñ€Éи¨ ²1T1¦Ò¸Ñ¿lìV- ‚,ªO5+~ˆó^S½‰ÆxýkÒkè³–{\ØùvbPB0Hƒ™À'§ <…NeÄ36”¦H¡ 0$€âQqgHÛ,ˆ6ùeŽ*HSw!ž:ØÊ&jjwXº ØÕÀð6GŠíÃjêlX– jÍZPËÒÃ6ûµøßóؤÈTé2Ñ3åfŒvÒˆsÕWÔ%B¨ÞÔ4~ß{xç“÷|š;?Äð3¶ómˆDr/ø|ÿ†ö-\S í ê¥KÙK89{`ÁîSÔÖ£@oþÒü{GáyR"!;¬ÚpR€Þ†ôü7~E§3 NE&'æ÷‡Q‘LE` =(Qb%ý¾kÓÝ›ÔÓ­ìãE´ÃÊUL× p²UqîÑd}²G>ŽÖ“åÙåXÇ·á:¥ÖÂ(lýnã‘߸kv¶>²r&h—¬qŽ“Zj@4sâ14"ÐB0X%Ë™¢xêðŒŽ#Ê Úwþ[Ï-òa¬%Ê)¹O µŒu…êˆiÏļÛí~ëGÙ÷4PWŠ ieä(Ñg¯v§ õ%Jp‡ûOÖq¸è a(! ÌH m ¤a(ïþhaâ>ÿœ÷¹Èø«pâÒ‰PhËâ»Qï1óäPùrÂÏÎöZ?5„Å€{ŸZCÖßä,þÁ}‘ó¹šdØË×0ƒüDAŠKE[G¨*1fû€ä3ùÕxÈ †J™š…µ‘„obªx-¨24HC†WlUL‡nzè®e{$‘øŒ`Ȱ ÿâBS‡Ýýcwá9(]ŸºÆ?HCŽ> ‹> šŒò}!ˆá í2AáJaŠ Ë‚Ý!‘+L<n ¨êäQ $eÔs©Ñ¦éÏ·¤ÍýÄ'y/ü —Ìÿ±çr_­6ä»[©àm±Íz=ˆñ0·€#]Úä–¶Z@5ðPÔQò¹ðÊ&ô—H_ÑýãÍ«< q¾ƒB¯œe.<¾¯jŽš :NC^tø˜>|á)Š„ÅÃû,Ðì¾Ú–¹:ä:BäUð y”W¾ üöÄ’@Ôm$ï¡•†9¤æ5˜N‡eèô ðhÈBx}…N„ó(wÞf é„;½ÌÍÖ§î?iáí£jü¯÷¾-¦­ BŠø¿BŒ})²<‚CÓè8ù]œV ìu ’'áûΆšt&—™ô"ç! Â|&Æ‹ÉFùu=¢T= >),Áí[¿«û8»½7š¢k'Dþü¡4é`ò‘—ôÐçÒŸÅd ‰Ã ¤©FT8Ëztº×íh¨ç(2(â>û8PûÀÌw·=4^Ýþ_¸µ’üÀXÆè2!ÄãN¦Ó4yÌv¸3Š÷6(O©ÇyŽåÝй|%Ñv%ÀÌûÙ@>H¤¢Ñ™›õR•¦Ox¶o¢âͧeìkrßw+Âyô@_£Ž{ûú1’6šÜ6B1äÜ6| ï ðþýß9·£ùܼ˜ôWËê¹²?ÞšçÝÛ§6Ïáoj}øŸö†Ë¡Ç û›ÿà4ðÁ0¦É`íiÿaŒ†¨³vTZ_hOoA¤íÆkéNNÊY}svçÛú7wðR wïØ7nÙ'¢9¶ÜÑ^:œìâ>ÞOÖñÈbD_˜±_º±kéêZÎ8làôw*f¾ ½·j§»DGŸâ»o|§]{®{{™o4ð‰×]µŽ¼í¤ƒNwœŽ[2Þ¡Ü(/:ïé£ënó¶ºT½ØûnÖϽÐvÑÙËt£Í%ÑÍlû~oí[ôÊÑv I¸<¯øŠƒðoçwk¿_¦3ÐRß&.ýŸ& £sXZ‹Ýѧx`6x"&‡Ö6‰tÙ×<õe7s×k‘3íUì]+´v Âš«Hf >Vø¶ c£= E]Ôëa`,æ cj\TËKÆO½"bW½yU¿ŸtghÐ÷¥(oþ †Âçåº;t×V§*¿ )Âÿ Úëm¼î¥î„£Y¿ÄÛy‡ˆ4¾ ëØKclv^ü9Rʘü ŽÒwŒ“oyz¯Õ®éž6»Arª4ßTôû×éf®Š²IDµEÊÖ®\#ç•}Wr¨O_>Œî ¾s²*ƒyÙ/_åÒb &÷°ô ȤD4•ý‚Í ~¶§Oêð^w `}Ϻiºedƒ‰Ü±›µ†èjê&ʈ(¤ÍJX”PLZ„!B ,¼ªôÿ}û<ã¯x\ªörë<ï!áž\PXžrÀQñÖaçº=ßAèç²¥züÙ‡±(ÃGÖÌǸÀÄF²”µír {âÄ9²êÈ{ßF»¹ìá*ó\gTÖþ¦ôŽhÅ‹KˆZ«’W""@ñ¯YÃëW±©î(ðÿá¶4øoº‰‚:”ÐŽ“@4b'aÕñ®¿&?/¸«xa«ÓpåŽ÷h€Ñ:;§-^Òoéû”Ø ­qëüÿ}äG+5'¶%Q` /'˜ÿÙˆ¡ß…ó{دƒ¶áÆ :ŠOÏ»;£¥¿Kö'’ }]þ[²ØüÚEyüÞ4ˆÛ†[Fƒ¬! 1Íë¼ïŽ®¬Åñ@vŸ² æ»›¼ÞÝÒ7$°ðŽat¹úlÃh u$qO ùvEBé²]þ7@ñà”¾–MEpà,ª!k†˜ÓCØvÉù{/‰MÎ…AxÀ´/fM,« µÍyCõ ˜Ç(¶8 ë ˆ((HRh4êR‚4§zP[‰|º^?{U´Å™Ø‘²ÚÞ×¶ô_WëùÛ§q—ý .|ÊRÈ'ž DPZÊ‚üÐû»p ”¥* Ò•šÕã—J‘.X´HÊ=v§ÆârJ˜[…þ9ÍÛ—å½q«ë°¸J ´i¬Ö[:’„%‡¡»[&Cù"/ÜL<H}Ç!þ €‚Ð ¤oÈ´_Ôˆ,øAlüé©>ˆgñ¯: º}LXqa yÈå_ªlÛƒ¾èôÚÿ‰³Ó‡ZË«ƒ£‹D„Ÿè*“Ê7Ó^=øÒ·ádà‡ô??dbYâ» ïÏù~mf¢Äál#ªÍ…G6ð'h@‹d©,H2ņ7F¦éþAAQ×'ßm€YÆúÅm›ŠRP Æ(D?‰0ì6o8boS™–áÂź9 ¾ Ph³Mäcw‰[úO« ¥`*7¶9ºÜæÛ¼V#/(ûì`ˆ Óâ+…›2uÞŸ0d¡ó}…Ó¡ÚûÏÈN~7Gÿï”b$ÿýüiÈ- °Žlë¾)-é÷ý¯OÇúƒ/øÖŽ¡Å;XÜ/üýXшåFíáÎC››‚¸êèC¶™‚mC<>jŸ©ƒÇ/èxûÿ_½@_¯±ÇpÓ^\ÓóÃäï;¹ùCfïôsø‚ÿï`ÙûI\½oþûœ(ÓÛíÞ”§›Ö®Õájî?›Ù$Ó¥f€‚ñ3Œþ?­ßwÙtÜxœÆt€6‘#Ø á/'|˜såí8f¬e‘«.;!eËX )kH „(¦6L9epe¥‡ÑÎ?3*¥¡<€ˆæ)dÍ@ T°xâP|ñÓÁH¯Ž+•?Gû§ÆÚi »Ü—ÆH ¬Ù3›4o4‡Ùˆ¡©|®n·ƒ…„j é­¨ÈO˜u„Ø Jrv—‡<Þs¯Þý¯ ñwÕiØ€x&›MÞ×ò¿yïW•¿‘1XXÂÍg!2_T®*+¡úmóü?žÔýEè¯F y_÷x}_“Á~—#;^›#cµ‰«®Â4œ‹àÏj¾t¡Ý¼Ï A<ǪuáômÀONžI< D—üxk…nî<í×>;?¼†÷šïÙÛ´êSÆP1®ÚòÿƒÌÚÈùŒ3°J*ÀWSÔûäS]Öª ç>Ž÷Óu#n}>˜e¦¯.Ͻ†û»Ë ³ÈnWëÚ·¿®6ÏmOF}ëëRÓÇÝuêuw€ÞÅwpPÆÍSi"™°(,Î/jV2øsù?—åoÕ?‰ßÓ—7îœ-óìzôJº0Q즸‚”Ç·÷NÈÖ:Á#¥}¬ ÇíLú¿àOÓMäÜöÙL -–Ó¾sR“iÓ§¯Áû#ô…üDQùlÔAü Oû]ÈÈpŒ¦±›‘½ ø‰üÎGNoì»2ùÙp¡Òå(«ñîBÒ^xG9yã´~¨Î³ÓIÔW=³×‚“Ç,*BAe¼qyJf½í÷qÀãJ9nÔ‡NÉÉ‚Iª˜¥ÏÊz–x—Îüêê|&u4Ô,mÞhÚc³k:lèM"'§ÞqLMÇXTØ;ñ:vtCIÌtõÃËòùgA¶˜˜˜¤ÌÓœvRæ²[Å[šÍAú\`Ô, Í´±¸Ê©ÐçÄ$Ðܺ8ºåÐß8Ek@XJÔDDAb‰Ç ^œÎŸŒ{0Zðg 9®S.&K‹œ\³–ãªÌ&,q›Ážü9·&tŠuí§»kzgL\^#';ˆÌš«ºç-;ó<ÑâùäO^»E»°$Àç„ÿ'Õ5ýÉiuTÄoVD½;0LiÉh—§Q2ͨnžyÙÏ_cæfVì„0«XXìZ¥Õ¬jbdÂÐ-(âñ¬4(•½°¸iîì÷ÎÞÑ}‰æ¾\bdžÄ#­œ!r³ŠUÂ¥unssã8Çy¾Ù…}>ÀéäÝZÑ¢7¯^A¸rxåVÛ…ÌœŠµËaªUº³+[Uy:Šc͹GI^ÂßÒ ëô=Mùê}áIråæ0²®.çÓÊ~?H²½4°TN£´2f·kÖˆÖkªìã8Á)ÆFз30Ì cší!/ìÑ%Ã'ÑÊ÷QDžLZ2æî¦=wÏçl3ŽòVgS{ÔŽÚÊ„NË`¡]¦MRJª¦F4)–…ÇžùØ.uxuÒ-“j©!zãÃzM 'T-°Êq™hÀv Ó.èÔ×$|rÈy¶êP\¯;lð9aÚFùY6š j΢f@®’!ºýí½Ûž&Åçzr[náǨÇH ™e”õ æËæR¶JwÂw<’šâ-³¯MÚs”Ö`Å im;ÿƒÿgé{çÅùþÏW®®äG^]ÒùhŸá‡Å}æo‡Ú»û?Øýl‰ûxyÿ0ìú«Ùö¿îø½‡–Êø[^†þˆAtÃÀ„€ ½1Úˆn?› Ý¦==ð »Ar‚ r ª¤D*¥Ü\‚Ð ¿hA|Þ?ys/™{WÍ傹Ыß¹Ë/3,¥%„g8Æ”C§¸ñ6®ª,œ˜§P‰Ò “œ‰žf¤ç(²žpÇJÞø÷$Yé˜j!Î0èkEcuT:(‰åÐA¶óosÖœ  käåaÃ[[táÈj%TÁ²R½ÓjèåñœÒg™®1[8Ö[9LÐa%c[hfcs›­»­ºÐ"MTÁD(‘Ì0áp²è¢‰8p±©šŒ,³M4²ÄȱÇÓDÚÒØ#I%‚k’ –°¾SSV6p’ ˜‘Í$$sÆ›lÍÝmÝݱÆs„5˜ph8Ô;9Ãà iÆáŠ2Zy“Íç#wwv÷u÷uŽ79|â–Õ8QÂÊ ÐÁ”È<×£pˆ(ÂÍ8a|m‹(¢Š$¢LÃãp£„¥ #˜d–ÚkS4’9ÂŽi¥ši¬Úi¡fQM[¶f‡Ó[[tÓM4ÓM4ÓNb¨£X¢ˆbÙ8æ3a†$ ¢B‚C…-œ’Gi8i¥ˆFHi¥£ (áeµ–AÁøHáÃ48@p†Ð‚æZÓM0³CBÆ,,³Ó‡ +€pÂÈ!£'1·xÖXP!ŠHY"àYFA%iEŽY†XAf[IÁÈ$†’Ø!`›J,sH ³D˜YeœC9bÎ ’Íœ9wf»[Xnïøf6cr©šÆ8IÂŽ b,Ó 0à 4ÓM4ÓM,Ö4Ö ÓL²Ë $ÓL 4A&QŒŠI†cPQd"‡v’ÚA¬²Ê(’I rŠÃÊÓ…°˜£0·  ±Èl 8Á,4ã9ÃNpàÌYÆÃ 0Ã4á†ÞÁ#ëqÜ "Ë)1†ügifŠ8Ó.cpR[Y¦ØÚi¬pÑÚÚi£0i¹LÃLšPÆSnšQ¦†–I4@Ü ZÛo„´’Q§ Œ$ƒ fŠƒ†˜0páF–i§ bí¨ã æ(sƒae3q 4Æ $“¤“†hͤšQFÁ´ÔÚÍ#A AlKiÁ6"Ç Æ±Qhã…ˆ’@ÀÓBM …3p¶n1Ë-¬Ó€Û[‡ $“I8Ãn ‚÷‚ Ä]!B‚""""""""""""!áÃ4á§ 8h„pÑB8iÃN!4B8iÃN!G€«£b&ˆˆˆˆˆˆˆŸkô‡Òÿs|Ã_Ó£MG «ÄvCῘ?‚É Ê9ûöNO°¢eå9…“QmêbÎ0½¢öéug3*ý—tY€Šéu‡>|—g_Ö|sÕ‘–«ìËT³tuEULm Ü4L†*Ù¼A/ *¢ñƒ¡0 šôÕF"Õt¥€”Ó^ !`'j[ñy€dëØ/&î~¾rYzz‡\YgvA»Kà«%½Ì×'aW0prw–:l6p‚Œ™#)VÎFœ!–nXö| D›ùpÀ¾–c  Œ‡À ! B)ždF D YQÙ•Ý 'Y‡™ífvþ›4êíTsªÃØxÓ^êþ~ ¥YÉr` ´?ŽQ8ð!°)T-‚ mç2œÔ;_¢¶þ©óƒ)a‚H" ˆÏÜ%ðT§÷izŸÛ¡‚“ýk!Y$$Œ#ñ·¼Ïñ!¿œ†“™°Ÿ hp°4†ÿ‘üÊdìÃËäá¹ÅÞ²ÂùíAäyd0O9çÃf«"ΜPÃ|©‡$9&EŽ“Ag2щâšN;]›°¦¬]ô½m’f©+¤d߀#7¼#&jÐoQË> A}(ޤC'ÅbÃ6Nƒÿ#©‡o¿_ª·é~7JbW w³DQ"ƒNÌ8AÐÔi$Ç 4BcJ‚AÅ6Ž<'+%ª¶ 5m1OºŒÛÍ™“"¦Úc8l>?*eÌe.-ãG)ÞyÊœÆêA6[a/7*BŸ–çBufnL\ª½døÃïîýNaN1¡$ M$‘l™HN‡fBaûè+®Îo|ˆ:knŽÍ Cu[Ë¥WQ\Cr‹ÛMn7 "Æ¡&HX™Ä’˜MüWç$¢9£h‡r³nÝç2¯ãà ØúéKŽ’ T]SUQhr€Û´¢àª"BŠ=r£„Üh  nì(@ŠNÂ!ânN¬Öå»\VZ]e ÑÀ‚‰èÂ`:!š! eÈì2&Ä“æQ9˜t§“7œz9:‚ 8X9 cŒ1Ÿ°ÂÙ!5»3²dyˆ/©U¦—ãAAFÑâHÈ#DDþ[×faÕêqÏ9Mñƒ¼¹¥39Jfs“h Á`ˆf.„pwyrLü¸í.˜8&Msmyòº¿Ñ¸^[õzè:”ñ­(<¸bà Ž~¹AYJ¸‚))€²RŠ…Iö¸–5+²ÿ¿Mºj÷â’[„s( ¤b ¦‘D‡X” Ývi* Î?úŠ8 m]ee{yÙF(ªFì—kÝ ³ó T³:J^“Ð6ó”ySÿ$gµìVO¨ŸQùcÒÔæùË86µÖ TοÕ u¥­óþOÂçpNæd黇I&?rð”~9þ ýyû¿ò×üþ¦ó†Ÿá¨nëúI-¬c÷ÍW-Öô7EýÙˆaÚ€MÁѓȂgRf+ŽÂîûò8}ö¶~{’b ¶!¸#3$'}ÅÅ.Iö~ƾq¢›'¶CzÀ„xG$DDÒn0ªj:hg: ¢:$˜àŽY­É ¢¤¹4£ÒY¹œ4ALY ŽŒ/z8pnˆ-º,qÚ̜Ӡ¢‡¡òj ÕÕ¿‰BÃpaùnX YÛ6¶íYGùS܈2ŸÅ±"#`]…62ªÙ옹ļÁh—¥<¼K8r>ö!?µ †ü½œM`s¡whè[±¯¾Bƒˆ‚¾î ᢊ1 S› ‚ ŒF"&Ä”=FCsŒÀo½C À¤F°2"1<‚ÊhvKÂÉ@A=iDQ{°÷ù'±¤ë ÛB ¾Û^(`*5 NÔ5KvTy„¥Däzú:"ãŽÇC‰dð0r°·9iŸº–{€U%¿:§cA¹"È’w{>mÐlOnµ0¹@Â0:Q¢JÑÛ í¼ó(û>ÀPÖ<Ü`¹ƒ`(ŠdPîßP,†ÅI€# \ÉXXQžó `¡;¸ÔõêJõÒsê1¢PSÌ&ZR…²ÑŸ$‚Q)M{»M ¸rBA‹r!Dc÷Uüϰ‡y&€ ^9g€  6TXÈËÍ·¶¢9ÜÔбA³ l`(:=ï–‰ë¶1•ƒ¡ÁAIƒ|Ù™j÷›85­ÙUVÚ¥Mûx8 ú^C%GÆØ1|Œå iU‰µ‹Å[8Èa¼Ç"°ŠHd¡‚$N,àà4l!A„¥|3pa£­=Ü8……ÌÔФ0@¼¹{’ÉâD±!^7ñó<<Æü…QUž§axf‰Ã% £'¿| 繆¾mµA¢L4o°ÖnÉŸ²yö0}®8–Lp·¨¢A'šìy2Äœy| pB¼…‡ A0¡DDAA†=†Íá­†gCTÑDº%Ž4ИŽ‘j!\ˆðáÛÏnöÉ¢—Ïó+pH ©+B5 „ÅÄ…Äyá-#)=¤ø»a´5ôx÷0áÏ»Bžú8UÁªhKJ#´Jˆ˜ÙŠZ¦iS4m ÒØQ"$DÓ%ˆlõá`†¹Y@þÜì@õB2Ù) œ`š´HÄA0Ó00AA‚FBàa0:‰Mx{7Ô0®¼ü5+º ,CŒ¦šr£Sºo1‹n€»Œ4p\ ó×Ë'H•¹P„0SÀÌ2(ÍÒ7F”Ô&“–®ÈlÔ,Šˆˆ 6zöl6$DŒº§¡©“w? Í0"Rb7ãWëÙŽßÔî ‚síWÎ680àvAôÄW—Ô|„$åL;D˜X”…"$Öµ fµDC–Ã̘l3”b%å¸K¤¡f%0)("7 Q§OYîœè€qá·DÖ 6(/΃êC<ˆò2#ÀÃ{œ¥¢ßu§hADˆb0Á!‰‚5©„Ñ¢ŒAŒ€˜:¸M!Ad“&0ŒA2a@Ácûñª%é)]À^(·¹˜á@´Cp `1€;˼àâCÈ hÑ£BA"yš š L á†õ {ÝÑ‚qÁC$FFrXÄI˜a€#ˆ”˜ÂÇҦi3ÇDvBŒ—E 2ÃËÕîàkªjÓÕMudþ.Y7¼º5tTqVpæð@1 ڬߞ |Mü¿sÀÈq¹žgEsÅ×ìÿÅ÷^>×·Ñè1ùÝM“³Þ[gL`£Cá@%åi& VB,ñe h+­É8ÎɬG úü¾Uò‡¶™«ƒlë¥iŸ.H/Ežûªn=™Õžª¬S·C• oÅmíëÓüh}N«Ÿ¬96,ÓÈ^+P€0±S `5¹ÊÁJ©ƒãø ¢"âËŒ!Ä:ÿ{ïØëûßö¿‘÷^Ç Tä[äÐ\vWóœýÕ¯±ïÑ dÒ;ØpÇ2tý¶ÅØP$ì0oÀUŒ(åıPUB¹T)ïñ~çõóv^ÂHsC¼M–¶í{®ÃK¼·}Ïbí51ûRp 'œÉĵFUšƒjÃ--¸|¹æWzÎYËë–t:šL:L2Ò®üÆPëõÿT¶œùO³û«ë¸o¿íýÇø¯ç.-JpwŽôá#Ž8Q¦ƒ”a%$0E`aE B ã’iJ0غŠYQY<ç/Ú¢s“OmÕ8Fç#Nh]Ó×$á,Îzj.¦ŽfܽT¬æ^ògœÎZY,QON;ä8‹s•M«L/ß‘®Ld“LEág'JQcùÞ ¢îþ5F §á€P E?U“2§«ÙñŸ\=ÍÝñ³=¸Q&Ä ûÖž>oÄ(å€Ì$RÊ¥Ê ãÈ‹Àˆˆwå0×Ëÿ HÀ^kF(ˆ™µçÛ’•‹ì@?V'5‹zPVék‚{n[9^|é¦ ó 6L¼(¤ÑÍNØ}¼ÒNŒþþËïƒñ-ËoVÜÌþi¹¯/‡—ÆÎk¹x–(*ʬSE‹ÿ­œÙ†ÝÐÄΆÛì0v·í@QU¿ûëDäí$:r ZH(º+¢÷ƒ*¨·‚’T*'c%íI¸õŒ<ܾ¶ïFZo*t ÅŽEpD<åƒ B è%®¸õÔøËwòžïžtßFœ‡- 1ZqêNðóÅ;m` Ê‹(0j4Z"ÒŠÁ?ª¶iº²……JÊ‹"È¢‚Û(¥e´°b „óý¯£ƒÇàg£óIš£óR³–îÍ /‰8ÚæEá#˜a$¦8AF–[8ãÖprÚËjøÜ‘Î"Í,¡Çi 5¬8hÜàõðᄎi¦Kƒ 8@~ |ˆŠ×»õ"šU#m¨]`ÇGƒî™„1¯wŠ‹Œi®ÇÐ@+±~EªŒDƒö°fÿûÈùÛ›Ù(ÐúZXl%Ž,؆JNlŽ;ùq­‚.‹L) a’d•ÊkGd†‡z0þ¯AÄÈã½ár Ç^Îì:;߯øÃ€­€®™–޵.Ç@¼ ]kÛ¯§UpD93©¨zˆ 5Œ¯˜äAô™û† Çäe’H€óèß•’ ûD-ÁÊÏVX…¦AÀ>#n¢sI81b>®žDÀ‰C:HiíLѸvzô\ÃþŒÃ “Ñì¸ ™_YïÇcŒ ÝÄãY‡¨H €™åóñï¾'þ=ø˜×qÞ9Cï£oš±&ð¾×¬ÞWhNÏ—áþpP¿¯§Ëõoö½ïŽ›`8£ä×$}SG~¥)JWgg%€_QÓA£,U ±aÜø1ÝSw¾¦ H®ºص D„P‘R¢%ECiÂÀtïö~avéáXæ3_yÕ¿‘„9[.§<]”åà‰:^Ÿg7.¾È| ÚìÅ¢ŠíúßÚHzÚý}9Õ¯3ZŽw»'°ûÀ†,\´>“á®ûˆb)þC ëÊÁR¥k R  ù¢x¤! Bš;ݬ–‰ƒ¥ñÖÝ}½3LÔñq)á%øíõžïÐw¹»ÏuÝsÚz<û_Ü¥¿•U]±RÅ$ƒ À·œ°(Íæ€ex*[Y_ùßèÖ>z[æeüãæ‚ü¨]ùHÂÑ Î9 …×ó®_± ë¥gâºçØÿ¯èýÎëøp{Á w{é¬PWK'8²X¹ìõáïÊzàÞôZŠHÍ´¥å«Œ¬”‹N-ø)Sû8>qñsø=~œí:Œ¨ÉŠ$¡Á ÀsP‰4rI$sFÓ@ƒüATë“<á{<çZ^òó˜L2O Èz‹¸²«ytL<dLPá.Ë‹b6­MëÉCÌn^Þœ¸xþÇÿoýoæ¿â}_‘ýàñª\A×y[­&¼ˆ ƒ'cyH»Ó:°ö”wRâ'²Ü0qôjÁùG] ˜0zúSì–µÓäãíþ=ì.øÚ3B~ó^NÀξaþ9ðØ7­q¢l  FP9BÐ.JÌï™SƒÎn—ãþ_+‡zÜñ\‰E`§õ ~8;\69FX漈ƒh-*E“úòY@Rlj Š VZêÃ2!¦T"˜$¢+h©ñûxúÜAú¿É+£û¤Ø„R(É$Šˑ¿'ñÉ0 ám‡ 0¢ÚM4D”`‹qÃYÃÎ8`r ¶©3 ÎY¢-œÆsCL bŠ4²K8IŠãõøß}ƒê<þü®¡ºìöĈ CøÇØ‚B§,­}‰†ölç88ØM: ±TYó§#G!”!oŸÁïåØPïèò^¡;$ ŸwÔMYy#-™vf‘¿×ò;>}ØžÛ™Ã4àwÀSc Nü³i£–±cŒRö‡dOi¢Ô)> ïÓÒ,s„óžÛ…Y5\Î? D9–s ,ùg†rdøoÇ_šK„ó=碘Œc1*&­Åëßá<Ç͇½_<ù9%ü²[>•pª’Â>ÂÍðèÁM’'xž8\¥úpÌà‚O[‡R,2”¥4ô¿>ZËð„dä€&; »[öhægÊë«-¾ÌÕfó–ç ª*þŒ…  vø$_ Õ"ýj¥ È ‚å¹Ɗó“ì¥ìÒ¹B4g 9h­÷<àU&á „çF”Å[r¼sHC}""Y0ÏE”Y<¡¼˜ˆ¤;ÌíoÉ^úõéOz¹Ûë—SIÏ>œºôôw‡Ê$‚ç(èäZ(ÂÀ F0˜D82ðÂRYëªMzoO¸çÐïß¾¹G¾ëœ57LA…É¡¹ euMm´î³L†ah‡Xu`I‘ ¬†p„’eϟЙ^ûôaëÕ«=üj¿Œ¯}ðÅ¿>Ç9ÑÆ4ð¢ :oˆ`°ô Lˆßæ½{á½yÖA7êê˜]̶3Ñe)ÜMæ»âñ/A-(%IKim˜b™”É“1 fY–™*gä-éÏàøy{~®ÞÅ]£­°Á}Û;¶ Ÿ›ý»“?7}éMÐA}Ïü¸â ÑaüÞïÝsY—å >e]j86[I@lଅòBI¨yœwÿ¼·ãäǶóþO5¶Ý›Üµ&wƒ _*®µ|¦î.xiBèT¾^LRªr˜%Æ&Ãå>Úöýž_mèüOóÿÅÞöï_ÄþŸ5ÿ§Åá;9µjTMÕU %T‚½ûÁ~÷†f€ù?Söe;â]þõ×rÇùeG¸…aÝëšç¦òÝÏØü7äï©ØDtàB)F¥ Ñ´„÷³l4âG›ISOã`=£Çü¯;­ûõköò”òùË’„9¥`Š4EC88hæY’pE 89@ s„CâØgäUÕV»â¢j¹›Ì{™ãëÅNüª‘ÓKnÇ)ºä¡AU»f±Â#$å‰Þžr'kUlA•[ÍÍ}"cNTDÝôÁûÞÇ<ü÷>ßž ů'm<¢zYù7·çM´’Nüðõ‹Ç*ˆ·Øg#Ãa`ü.ž v³“Gd›J„ÛçIu9e ˆ/:mUÛªQ¢ Œ`\³I¡ °T`ªª•‚ÁX„ÍR µ1bb§yü!§‡¥,u+TC¼ôpjjXÓ0pÔVT â, vj$¢¸cIAMeáу“EHäœ04Û„I( 4³‡î¢FÖ 0rvM iµ//ßᙡ‰ÆšÐÌÏN[xvWxÑ^¡Ò(RVw —,`ÜÅ~Y¾¯5•—¾ÃKv¨%©ÞÀÒ.é+$ÝÓ´âvEdž“LJnxÞ­p#2cÊ»ŽØKŽ˜îØ‚§dÌ¢ãÜ[™`e¨¶˜Ö­®,çcqwál¦»¿ 0à:wÃÜ„jûªñ(N€úœ ³ºÎñ 馤#Q"TnY¦ÇõùqŽç3?™Ã=:Bq°BäÖ‹ üÞþ¨Üj3ºAÐxZ ""h:e0±)ZQ/G–¼ÎÝ»úóys×ÎÁBç¦pȯ2§Žô=A„Q 'ŒoI¼õ˜Ÿ5DD®Ê‘à‹’Hq@Î UŒË7)…”^÷C†0x-׊€\až•)âò¯ÝÍ!Ç€5|zN9¬ÂhGÞz ¡9çÌâ#Ü:³ÐGY0ý´ÙQc¶¦ œLšL“…ànõ…‚€QQDýHJhMûÔšN4ͺAgŸ oyÕ½ROÙ,ÀŠà ö«1eA5oƒ‡,öq´²ŽO:ìã<&s¹p&¨†B"h”°©)ÜaIb ö}<ºÞÅ1åh_™Ì§N%;<ù4H܃© Ñ•/M SH}nG#¯1u6•r•×Îs¿B°$‚~„ƒaÍéd!=Àé/œ™oÁE˜°œéÃS»¸åxÞ€žqö?îýûÄö„È„YJ)PB£».ó#!åMñþ|==ŸâëyW‚BðªQÃ8Y7?7ºsþ|víÅËv”Å xùÝQœ}±ÊÖ§Í·«†R Â¨W“Øw© ÷R¹t?ïuwÙÐöÁíJzk݈Q€@#ò—þ)%YiɹS'#+ƳÊj˜Ía™yÚ:jÌÃ]jណw”€Ī›ú§âöIÁÞÇNY˜QD”Q‡Q„„šAšhpH9BÀ’ +HÝÒµ³„\ÐïEM•1̈ä^¹™vXncÕncÌ= ía¦´0h~ …³¡KérGx:ÑÝrÐŽ,°£I04£F()¸i$™,dÎ["ÎæEp7„´’Ì5–i„³˜[q‡( 0³‡ Ê9òf€¢rÅ0Ã!{ÜC"P°¤¥6hÈc„ŠøvbDÎsúžwîý÷ìà}96þ®ªp† Š!Òɨq…3›KÒP‰¶/*¶réø0 ÐåïUøä¦òå9{Úö’p¿¾¡äx0ö7©Ý|ŽqøÙyíVnp8QDÀ1>úõ¤žKJ‘H!ÁñÝ4Èæwl¥¸9àPã1GC‰ûB^IÛncaDåÔΦ­Ì•ÌL<%µ¤®4J”Îe$:@!M‡D´ „ã\øß¨ F÷g¢G=Å‘é­ày¸ájÉÊ !Ç$%yj³²Q4Zu)*øÚ1±Im¼q¿ÜyÙÂÃb!ƒ¯Sªºðô É«õ* y8«˜a†a†áaàˆcºqŒ@IÔo]ÑÂÌ0‘È-ëÈye弜i0Ó³ “D&¡¨ÖsÆ«fÁJf–Ýäù×}¢Ì4NñÀêf¨ãüÏ;´¤Â!4ÜÜ¢‹˜Þt‡—¬u$„:ï·v,t8`ËÞbq‡y|hà°æs0HöÒ‹Ç”(ÈPÑÛy¹[}ø±~-BSÆÇ#´âÑtпg²ÇhgŽ=yÎõåÉÙ]óø?óÿÑ}ßú_ô8"ÔÁ€˜°F˜¶ÀFNm=:¹/˜ã½y0ß{4ZzOS“Þ¡­çáœRP®^Ýp+²ãþŽwg¼ü_Ôgñ:l÷P×ÊcÊJÇKP’б$a)ȦMP™ƒø{7øÛÓ÷þúñ_ovãË s,r (k¡Ê ² $ÃH·Î£kò%v¬M•±œ¬Ãxü¼ªÜZEÝ\<äk9º¶69èV§ro[œäæFÌݬÇ|7L~{”–Þìý¿±ý£ÿ6Ú¿CðÍÿiïèc,‹"!Þ…@ïE…dïóöóórù÷ŽÒr„šˆ›`ùšaG ,v~Š cu,0‘Ì(ÖÒZ`öIe”ç 0’˜Òq¤ ²ÚK)¤Öq Ç 8YÄKhY¬6al5³Ž`¡€[x‚¥Ži<1ŽDetŒI°‚ hêIO:"¿’%ì~I†XZ”:vòÿ¹ÿOË~)ÀÓǦùR÷ÄÕÝ”#àôÁ4 íÏšºë& '¢JkÄÄÀt& èp >I‡Ð8$}£|ÈðáÙÚeÙÈ$ƒÂŠË£Æ\)¥Ùšxä’«˜íÖÄG}ÆÐÎÅ£·Nv †@C8çYßZä’9 „.þ‚€ˆ7Œ›²NW˜$já…,(Y?Á! (˜¯¤_ziCŽz•ÜÎe?‹ô"Éä9Ô‰~rfñšg;PCéÞ§tq¬j o‚Š,ìÓ 9ctHLt!'û;Ž;8ì×tº4뮇{ᨿ”ë"Í.I m=°Û wàî „!“WG^pƒÀ“®å5Q1ñtÞÏx@l4ú'Ó|ÝÈSAj±¢0ª D£­-F\Ý^_eÐÿgùø,òˆ¥‚!Êóu¯-ÚÖàŒ¸Œ®)\3 €ïãßù» }¢k½öÄÿ¯wƃplÈg,Ú^ÓC÷™ÓÍÐ_y 8ìi ®æšD‚‰—Sñóaòœƒ»2"\_«üȪ…¼/ënvÕrïimŒ5–@åIi¤páb0‚Ê8@ Hqܧµ±‰çgƒ‘k.Ž,iæíCÔ¶Ùt_2nù…»‹˜¬vŽm¤¶9TÜ¡çMÌ¡ÈœŠ¸ )Ǿ^Rþ?úŸôÐwœ»‡ú¿½Ê~wìü<ÿÚ}Rž¡`ª¢1b¨ŒX,ß¿?ªú¼_2ó8š›×©Mjs6`ˆaM_ ™-!‡é“ bI%¥º4“…D8I‡DišpÓj(pŠª‚Š£—Á´f0¹hfŠ/J5¢ ¢Š àÒJ(–icf†8PW Ѝ~«8üÞŠn)¨ë®±°¢Nކ¦³p°é´–ý±!£ƒ¤ VŒ« h—½N;gSºÌåÛíySq„37cp›·P”j­$³gCs€äwI‚ÉÕ!K 00D놞c2;2BF†ƒX€L™0˜CŽ$o\Ó š«®Ç i5´ÑEXЉF )F'Âút9xmWœÌgÇòΠᄵ˜Í¶šH;Ü[`Œ¥“’J=¿ø=;t”êS<3©áx×vq‡c3‘°Î)¸¨*Ãb«1 6þfœÁ'ÇŽþ/!až¹MÞCf´.lè˜9lò Â’Š(a o”:…Øäˆq ôÝ»\öq°ì’ÎõƒNÊ8 q“3CBËùð"ŽÎâ»)Q6ÿsœ˜NóKàÔ—‰ÚÝöfã úçFÀ‚é™ z¡¸¼/˜9Ì5%”:Œ ¥t!MM˜l4<îü (B>“„ Ô&È5lQMu¥³€¢æâ F–(w–là › I–&ÉFl9 ]°^òs»ý,à]"Q™%FGBZMM8 |£€Öô¶ Ýþßü·g@ÔzS†ò7sÖË2hÀ±;Œ4j#YmµY2%,öhÇRÛ­ xÐÜC  €Ä”,Ë(‘0³S2Ëm h[ Ki‘rlÑ HnÌ”¨¡´Ö´¥)JQ D0œµ1q¶Ú¢SRŒ£Ã’úœ;lÉ„¢%ž4³Õ·&S-,H™1R–Q”gVa‡Ô¦DbabÁOg.0›8”)e)e8ÅÉ…<ú(j3@Ê2ÚÒ jPÑeL:hÔÃÿ4’Êb;V‘ dÛ(`‡MjokbFQ˜Ha³BC¶æô¦@J%ž†pa4&Oˆ)ФLˆÄ”³A†)Nï‹Sf“ ë ”ba£%0K<ØY„gR˜dJvL˜waÈ<ôëÛîÁñ¼K£æä5Ã@&ìùCyd‘.Y$< ɽø` y­—mÐÿw_Úö×î:­Öµ«ʸx»c:û_‰«pTüÇ©˜}æ'{œ‰ró1mJ™¬ålòf¹1Ëä,žbºÕ4±îò&îçyÇúÀ¿ª_Qý‡â@ùñˆÇ·Ñ³æt®A•H¯/ ºj[ôð4Ï—Šm“ë\Æ”øÙ´ ãa‹š¹ê„•šdRÑK0`m.$ƸƲ6ϧ’¬b`‹,ˆ $*$E ÕŠô0~Ž!é?Óþ:Þ7ôò¼ÙKÐdÓmzç‚F0Ф¸ ¬>Þn;׃Ê«WŸÐÂmm6j}çjï]Úfùdg6JÊ*  1µDÞt>5"<Út'ƒÛ¡Ä˜a ãÂûN÷ÏæÅGÕ½a|âÜ÷úØÅô»lDœ›Ì$람Ë3™ f~&b$á†Oaþcóý¥ ~Š>Á×âbQ0L¨3C$„sC4Ò€Zm?CÙ>&3cŠ'¾é©G2„&_¹áOé;ðøG±m:ˆ. ¥d¢–§ÛC SV:]MSœ. ChSñ öpÎÙîÿ;·àp6ÃRoMŽè~ɬU[´@BǪÜÜd¬ b¿\öÑ;ru$ôjœdÎý.Ï$ä&Ê•("*F'”€ìÕs)ö\¨±4-ø_¼úÞ/*)/vIóyÈ9WŸÖcŸ‰ðúzgkqZÂÝ®W<+8l„Ÿ7Çn¶cq™ PáãUb²bP¹€­¯·©a2ñR·­X³ }òÝ9–—ê÷rÂoÅ{ÁN©yBX/fÍÛþ£ò"!Ð`†Œ 8xô0àíñ{ ùo1ux·[…ÿñrâCm-5×RùÓàh킜0ø“àM¿m‡×î'W쾦rCçžÜiíø»úˆ¨jý¶Ö”œ«Õ®JÇ*+²±>p7 µ(HŸY¯M8'Õ¡*0À‚û2~øëvz‘ýÝ›F Òkìfyþk€‡ãÚ øÓ`D´æRÙOÆ^ÆÛƒ ¸ü⨉“\˜¨YÑ…b…ÐÜíó‘A¸:AWþÉ„ }ƒ=…GÄðêŽ4Îpۜ޷˜æÙÓ!ñæh®÷ýÃÍ÷=÷Txpø‚Â2„` ¼På?C?‚ Ãç:}‡uÏÛ‚ÛËËp0ÛŸë& ª‘Bény]4ÁÔÎj¡=°Uuæù>ÝŸrsêê½Ëc­º?0ˆøËŸLÝ«+Ål¯àLJ(E M¿&•ÉñÈ$nûZ6ÈE6„ˆˆªÖÝ•²…÷]†§ÝJÖË ¶Ûi?ìì¯ÐäˆûûvRè×£5La ñ’´.?›õNr;ƹ٠7ºT*;s­{ îuYß™r´}õ+8/âÊ8^¿Xýáu‘Ñw¨`åV¾{˜¹Pti2Ò ó.ªÊ$pˆ%5¬KMY·í€’F'£ sÊê4îçÁ°00µ@§ \z®‹:®Z‡êeÙgðû5B94±{j†Y¨¬*zT09|¿YÎ.Æ×]•éo-ÈøÑËM‡ÿi¢÷L­¯\Þ·ißìÕ)Ãfæ•üm¶Ú_Ìæe±žsÉó·TÏÛeÖ÷Ž%4NÔ|†Ó[ÖÑ W–ÇÙø–ˆ«hq‹=4.§6-mô{íÎ÷™CS ´¢M ¸vAÐ t y³ï뜠xÐxÆ—¶P¿È¯¢þ$à(®€fRè5kÊB1ÜQsÇ2"o(Å ÝMù_“· Þ4„ ²ì{¯rç͈º|¦Ó½_tú:žÓÍXbpa"N×`Æ6QBž7†…D(ç¬lª¦Rs;!«äuÌ™Án$Š«ºâðé@=«uÑœŽØÆÊ‰ ³È0&À*¢ Ó©_¹EK­. ÑKë£FG£‹VvŠG²×ˆcÌ'ëC§7ø­Çžd_ÛËáÀdžp ´÷¶¯:©å0Úá"rÕ/¡è5"ªÅQO‡Ñîqñáßdz¹> ¾ZÊ¢RQAïa¶Wò?˜ßáÎ#SÖõÎÀû9F\´ïŒ‡y§( ‘mm}"Dß`s´_ Å~é—íŽn“ñE/% FíÙáÙ9ÝdïæÀ^-+º׆—Ì,'Cº´¹3.xb&¤¨b5ª—3ðË[Æa¯—dÜÔ¿—³?ÀK‚Óx•<5Ó¥r©|Õ0€îˆ«ÔLƒ†·]Å~¡l·Âùß½kK±Uº6ÇýgBYÇzå)‹¤¾«,¦VŸs<,pì|aÇgÞu_ªÝYNxx MÚ†¡þ£’‘+U”ï:"¿ŽÛ²ÊekÊòX›¢%”¢³I !€€…„Ò[Èi²v}ÜòíͦCé ˜» Ùâüyh¿7óçÛ¡¸ÿ-Êév’$_A×õ¾›Ïù=OÍãwÞiÈ!º’ EäŨ‹í") ¥,(’ q諞hÌHðÐÃõŠ@û®pÉD±@pÄ✿tzƒ­æË * ¨ A{Q0)"„€„DðŠzKËÃÚ©@‚Õ Aa ‚Ð(‰B+…‘A¸‚ÀE° °,‚” PYj6à€YZXPD¡†áAa˨ @*ÒŠöÓˆU „€ƒ "HÈ(B* ‚,€Æ Â")"(‰ ÔBAE© ‰""‘bŠ(ƒ# )„#D$QA@[´q.pŠ4:¦ºa †§Q )gËh”¬†:“ ÅO ;¨ð¨Å‡"•ƒ4¬^5·™‰Á›ÙÚ6§ûI~;Ãû_ßkñ[†2 -µ0!g‰‡Ý²t…¸ÛùkŸ~ŠÞrð@]|×0˜kÓC.Z]K´]"¶Á¶Ë—‘Óc-â±¹ñ?÷ÑØ/Ò"Áâœ4@PÞ%È€¡áùœ¦žm‡yÒì5x;ëCg¡òvX¼cmüخךhn9Ξ;þô b#òMÉ›7=ZðÀŽà±®CÉÒ½C÷Ýß¾{zkÓù<žÇæÜž]_›éÃýÞï:{9ìÍýüÙåú[]bæôy6¢ƒ²ðy9Û>s\šHHtôÐØ€v~í¡‡ â0ž”Ädäå _=TyX<ô*Ú IG¹ñ?áò¸ŸcÍôÅþ_ðù~[ùvþöø¿Rñã;ñæ…C؈,€ ¼A`¨‡jCd °D7 Å\B ê„QÄ ¸Y1-Ú=TRGž…dY‘jP%S@ÉûJz.›§÷ 7V Ù^" ±Q*á}_¸ê ‡œšdTE‚‚¢A`ÄB( ÁH $RE  Š«$‹"Áƒ,R0‚¬‚‚¤aA‘AôAÉ$ã]Ò0 •B„‚ÜAi`¥fK*¢ÅÀ`±U†„óC†Â!ÄAp)$  UUUUUUUUUUUUV1UUUUUQUQUUUUUUUUUUUUUUUUUUUUTUUUUUUQUUUQUUUUQUUUUUUQUUUUUUUPAUUUUUUUU€HÀ$UUV€ÀUUUUUUUUUU`0UQUUUUUUUUUUUUŒUUUcUUUŒUTEUTEDUUUDDUUDUUUUTEUUUUUUTDEUTDDEUUV#UQAUUUUŒUUUUUUUcURˆ‚Á‚ (ˆ¦ÌAn X*€°UD„;ˆm ')S€(Bèñï[‘’ £F}¼ÏÎí½ M ä€ £ PÑ@h’¤€~+$ЬXj–i 2ƒBp¤âHÀù„…C6[K+@ˆiDóÅ{½$±bW¥BËúÓ›°C RÒN!YHTƒ šc‘„BAEa=ÒÊ‹„Rò‡¡5‘µž¦²T.í5LLM†”¦‚’ƒ‚6¦RbîÕ@ÀfZbXÃL,%Ök ·YbiÂK”E“I…M³LÐáLÛ›äXH¿˜Þw· ¶2‡øˆJ[µ=¢#MÂÛ6xf!jªb¨Tb&Ã7@Ã5h¥B 3[ŠÁ`æýÒœwd…„ |æƒT=4À†ÅÒ‚H >ö¥¸h ÓB¨Ø]„ª”õˆ ±‰"Cˆ‚ê ¿h‚  $ $#"ˆˆÁQUUTQAF*"ª"ˆˆÁUDŒPb $B‰Š*ŒbˆˆÁQUUTUb¢*¢(ˆŒTA" F2b„D  ÉÉ!0²PUUUQUUªªªªªªª¢"*ªª"¨Šªª**ªªªªªªªªªˆªªˆˆªª*ª*ªª±DUDUTb UUDDcÆ1TEUUŒcF*ª ÅUUF ƒŒcUUUUV""±UUUUŠ ÅUUUUUUUUUUUUUUUQUXÄEF"**¢*ªªª¢(Šªª±ŠªŠ1QDUUUUUUUUUUUUUQQUUŒUUUUTUUQŒUUUQXŠ"ªªª"""ªª"*¬EUTEUTEF"ªª"ª"ªªª¢*¨Š"ªˆªªªªªªªª¢*"*ªªªªÆ*ªÈȪªªˆª"¬EUUTEP`Šªªªªªªª"ªªŒEUUUUUV1UUDUUUUTEŒUUTEUb,EUQƒ !û¡./耠è*;`¨ó €É?‘DDE¤$‚$‰$‘‚A"D@в °D"$DD« ŒŠ‚"# Š! ˆ’D""$ˆ‚"0„DDH‘I"$DDƒŒ"‘b€*F’2 ‚ Š "AŠ DDAA€‚H‚$DDDDƒ$"$EHˆŒd‚A€ˆ"DDA„@@"ŠD$L¤JRƒ ) ’"‚$A$Œ‘B1Á"€ ˆDD‚D‚$  ’ "‚ˆˆ„DQ‚Aˆ"H$@#""$Aˆ " ‚ Áˆ€‘‚DE "Hƒ ÅAD"F"D`“GAæ@±Q;–Т–­U¥-¶¨.(9T“bŒ!I‹! )ƒÐÑAµ+@Œ€ÀŠX$„S(¶DHb‚*AUb¢DQÔ"€½CÚ(;œ„G€ˆú‚Ô6JO{©WH¢M'ž@0Ø Àô`Y ¤ŠN8H²,£+$ i†a åïA¢”t:a¦(Qf ¦J Æ;ÂáÝeð2B1Aü¦`h™y  ïZ¹e¸Ã$€9ݰ¡6yPݨÐAb÷ˆ,5@ƒ `3BX*¦ YR¹$Í’qp ÃXCƒp¡¡üz(¶l4[8IrÒ©lVéœð.ªÖ¨ÊÉ €bÑ„X¤ŠIX’TŒˆ¢Ä`‹²JÂbŽ6Ø,‘dŒ++!J,BÙlª"Ûk-2˜¨ÄÊUiJ#(ØËjÛm¡Kg—øù­XÎVÄrE‹.'UË• ¬Ì“š‘ʃ"”Õ32[‘ÊÊ‚,£û †‚PA†èb Ì´´(Z´EÛ aJrÃ2$R†–.b`Ö…”*Ùl)7h¹ïW[CxaQ0Xc ¨RÍ%´üúY" m  ÌVR›É&$‚dc&2!"‘bÊ„±’°R¤ÒE GMuK5œÈ9 â)-n&9¬ÌÅ0ÄËm-Ã0¶‘¿Þ\{€CPVÞ1]%ce¯qœéÞ;VÁÆ„7I§ª”,ÓC`ÔÀ@ï*ÛBìÞq8A©ÍHéz&Òé“ÍÖÀ>k{í §-Q¼zè·K”vòº¿©íÿ{¤6¥CƒÃÈÚû¼Ú,@mj~Ê{­êŸ êü™Í¢®„„<7ïõÆ;xý¥(åŸÜØï³¿s´îÄ:¹ïF ¼Oít}Ÿ¡1ᢥ.p ¿îù×UÍî-d¶¿|“_w ·w[+nªÔÙ¼!Uâä:zGú‘”‚è4i9øÆÉ(˜$’c$3QÝ×÷Õú¡ñ*˶ƒ'y`Ôfg~w_° >bA P)‚¢ûA‚AAb¤X¨AŠ=ƒÄ"Fú•L”Gúõ9ßúüã¡ æ¿éiõ™½ÿ¥‡Ø ]wñÜ?¯€¤†Ð)!U€èð󮜸œŒYÈYim¶Òi/øº§FOr( I·íVÊŸ­€?mD^-ü †Sn* üúü³õ¾§As©P|€Ab"%zcaPA~2 ¨@‚TO ny" •Pä?¶dL tD3É(\I­¡6?˜ˆe‰Ÿ7>Âúî²'¼çk{plkÕÚàÏ  ¼¨ º@‚û iz†?œÙÖ).>¯–És!ÇÞš%·Z%‹QOÊÇpš0.°gK|@…ìp˻ڒéÔI(œ¯4‚uÛK[,¼üß@¶3`¯ ^- ¿Û`&w³ —Ò–i¬µZ¹Ì*‰'(•˜6Ì/‹Œ[Î~›wQyεÅË0Û=Þ®o\„H°@ô°y¸ðQóå* +“‚œ'š·U}ºxX¾Å×]K9ãÃùŸGÁÀælAþ½ê ÒT:¯1·>9ºÕ{îïTÇÇþkËUUâ €AtPPëÔóÝ]âo4DóV>ßoøgsØœßW‘ù³þH¦0A{d@4À‹ $D‚ˆ‚‚ª"ˆ‚ˆ‚$A"CrÀÏCûüø0=•Min50 ²Ãzvdû80aÀ§lOÏX¹=û}öâüÆìµ·:$¡¯M K6#Aò©‚…R’<‰zw‘TtPû^OMÆsI^åGõôÒGW“Æby>‡ýšf8ž±Ã[^s˜”÷˜€€ˆ QNPÐ]žD–+ÛþßÑéýeò>&ó…¡¢FCm›ØÓÉl8R©¿ô á*ЉqļËlîT'©;¶ÝHŠ%Xn°‚/׸®©¢ÿ´Ug*ˆv¢@ˆ‘X±$Xˆ‚’ƒdAÇRÐĨ9 {—ËhØ‘|š¤ô—Ð <;ª‡¯ñ³¢Õ³ö˜¬õZêæÏÑ%‰©ªCÐ~|]»ÚÓ˜“1UUCöE«ýÇù7O5ªÿ@œàs:SlU"½L?i­+ï!Uþ´n‹æ°2'±²Dí…@”Wbgi_ôn ¿Ä^µ¬=çC…¯Ÿh IØ Ip@Š¢Å{YVE„Y?‚ÔÛM¢ùhÎΪ±aSæ{n¿ý)× s¹t¯ŽšÃdâ`î5y¥—²½îºÊé•íTò„÷-Q°*¢Câ 4¿zý€¦Ÿ¢BªúÕËþÏ¥Ó3<4>ŸÎ€H‘ŠH$"²@P@YdX±H ,£P‚ˆPˆ ,`±E’ À¨( ,PY‘AB,$AHæù˜rK¨žDα\c¡ðüm©~§ Ì‚×J ºõT ‚úÐ)"‘" D(‚nQO“Ç¡P(ˆ—P@@ýoÆ=(({ ÷DDÄtg=JƒJƒe †Óö[àõˆ§ºÆ¨ŒAt‘ŒIH]Ö¶Ä$1 —ñ‡Õ3ÉeÏê’Ð6ä:H¼3¼ßR¾ø»§4iÝx¾âIa+æ3ÐÌyc;CŠènÛÙW—_-ÞIMÄ5KÞ—RKŠMÜFÈC€Ã Bc}«n†³ƒ¼ùž¾Ft !uƒ9XçË5Ï©!XøË®ÙÝÃëYþëç<)!׈-Z}k•@ðˆuaÛèðzîªpÓôšî1Õhd?é½9=^ÊÄ«O“è«¡™B.  ƒË”AwäX¨1@YØ P) ¥ ƒÚÅr‚ c7ƒ¦ª"Ž^ÍT^£€ ½?Iœˆí‘N”AzÁëÑMâ'CNóI_ª" p5hRdžE%§lµŠŒ[>Þém=a Ch(ÒÛB E¡–ZårúÎrµóà„ÏÞ¨"‘°îå2v¡wbÿãü».¯&·sšH’v°¦Í,«jS ¿ŒÌd –ŸùbôË>m±¿'èÄ ùÑ11# ù°ÆýâÁÙÛùRðãW–0¡À a4©¢¬:êX…OXbÎ÷fˆ_íPE˜æIõ »Ï õ(ö@(Ü .ߥ +HMæsÕ® ûblAg®Ârü`ßõñ¾“¥­ÑéRw¬€‚DŒŒˆ0DD‚"$Dˆ±`‘HD‘ *¢@F±UB ÜT„!ŠŠ•,öŸ3KmsÕŠ—Z’ &°jÚ‘NÃ7Äöÿé¶{¼t@@!í#µ‚lïÖÿpÃëXÁà0|Ñ+«…‹ƒÔê¢RkúÓÇ™çˆüƒ3¯ ЯWzª !ìÄЙ»£<£‘ ‰Ó»_ÈóAÑêNlAaÎ_£ÒàÑ­u8â_Cªæü÷•ð0HØ`gLâ%E ΋¡_™j’Ò×?ûú{»n:Þëwñ?’ß«ÿ÷ÒÁáûÿuËn|UÒ*hŒ*aà@•ÎUöì,Üé½ËhàÊÐ1`?ÿš› _2ŠpÈŒI`¬`+ÙÒ…(y·;vò Ûëõz/¤~}ožéÄÒ>Iت©Ù}¢#ªø*Rõš†(0“‡1˜õcšÐò¥âx¤4 lJVÒ‘hHÚ'³çƒ8Óù=mž„ê#ÎDõøêe˜onϺœ°~êØéÿ'ú’ûÂë‘jR²°~"À‚Àòâ  ³Üúz–á÷Óçüo©é»­ÕûÆæìó°.|6]Žroè±¾©¤g¢ÍSwchµsÚ>¬ÝI¤ ï '`ÐÄD‘ BE„N­Ìw>á¢<ʪ !™ö`Ÿ8ã ¨.çhAnŠüP9ô'w“þI÷ïê7:-› ¹áäç ‚g‰™”yOaí†Ç©’‰;C¾’âìyÓ`-ZµŠ" TEgÃÏùøI´Øµ©D¢C¯ôf{ Ë€E‘Ý‚ £á®-¯ô$68U:%Ϥ]Éû²„á5¸ÿmÈ zù‰˜`)+†$ÕÝäžùOièñÂúÖ^Þc$ãï+hxê©W8³A8ÄOörÏ]Í„8U&ósëßhÿ?Öü|8!=ÄGÕ¢gÀ^…rã“ú6^wôøš¹ËüQA}¯¿×w—4+È×{[„7„`@l"ËÜ_úγr%¨0wKxVÝ÷ê3ª‹©•jh ãžñû½­\´ây<áv‘÷*½içlÍôpC¯ð䯀 ¿ú:,ïñLI z±d³§,o_ ¾ ‚ÑéÔ†€kªf¬²D)I0P\qªuåš‘ ö¤©‚Ó«iþ½ºçÖù¨ÓtpÒÑ*§Cþ¯;Øú¯²þ«Åæ¶½—æp2\ð„9UÂìó¡ëO³uóûSð¿ð~ú­KkñýôÊu™)•¦#g¶õ¼o”ZÖ±š¿#”_‰¾''X]grB²”Q@!"88†¸CßøövóLØ…"gˆ cP@@Î=€‚Ø/Jx*ªîC ãõà:ª‹".HA•œ ¾Bª !héÕOlˆ¢hQ¿ô'ˆSíív²C""&B l‚‘P×"™ÿ>‚&æÁ½×Hºq´ºïíööÁ7ˆzfþªIûÝßùíÌXŒÔՀ˟mn>CÀ¦caÜ/`jYÞß¾Ü3Ë<èÀ粇éz®‘/CI*ñâ¤eË[úŒÔEÃ;Û) @U<­__DtPWÒ·+= Ý)Í9å:Ь%ç6'1ÐÎAuËÁ†_aIw-C¡BÒƒ ¼eÄ’ÅyĸïàŸ©ù´ž¶êþ^t(êD ‡Æézs¸íy£¥mÏ_„AèDT â €ƒ €Ôä='ñöˆ™s÷ªƒ”¶“ ¬Þ:ýÏNBN€›ÑÀtlAW`ADNËðÍCk¼GñB Aññnþ1ôdØèeç¿«Øt¼Á5§g°(Òa†¶yŒãèq̆Ç8ލa°Y!®n’ïý]?%åLÑI(™†Ÿ«çáÑÖ†>£÷[@8a*L$p@FΊ‡:ëàçÄ;/ò½Ä€uÝÆõº•Êa­~;É¥<é¹ò—s“ÌÏ< ¼ÙÎ.îuaG8¶–ƒ²•2C~šôW÷}Om£ÊypðTPQ @ÏéöÛȸAýÕ©]z)² ¡…æÑJHöB   ^Œ„D3pbŸŽ\¸|¸þä:œÉë~¸.½® sµö¡Îy~Ç‹H_x¨(@TqO8r'-0öôÑÞíØyñïpkp™÷˜ Ž@æ,„j)î "%%çÿ=˜‚ÒéçSàî×ýÛS)ÿÑßwüqÈá.")£×èžSì, ¾ów½·ËõœOM<ýÝp˜ !ùÁéøñÜ}Z~T“± ÌFú'äènÎh¹ÌœÞ@ZU\¯¼ñ¯–µY»,|ƒÍ&ܱ¦àúœz¹=J㨠† êÏ2tƒ·æ ø\u¿ÔZ“‚9Üb@pŽåN@#„)IñÁõöÒ™‘çyþž_)½ü±|'èh\îwëêéd”Þ|ÏKÏÅŸUý»NÖ0Ho0Y“³cB|„ÅFa 0º„Ç Rˆ P`Ý&ÚR¶€wU4gñÈdМ¡¥`„eã¡<£ˆUŽÜj’Ð:8ódŠ@Â#÷ §·ðf$•sXÞúSúuæ¦ÇYͯÖ<ø ²Ð/tOSGŸÜmƒ·ñë¢üÐÁ ãò¡Ð˜¨ }Êx2˼£¢d­^°´ÅÞXi£—}ÐÉCùCu(µ)( ¿Tè¬H€±@H º!BÐ( û2òt‚ 8*‚†Qrærgü!øØîÍ󈦀ª ó„c¦^w¼øn×½¹&†RÁ²’5>æ•—G¾Ò|ðÒ“f¾ŸÀf0Î c ì·äÁ63Œ!ù>t.L­¼«*C¬…gQUUíæE) >Ïðï8¾¹®¹2X€iÀEJ„NúP.P¥4ÁðQŒ3EK¥ŠßÊ+ê%f´ž”¦ã¤ìåÇúx\½z3w ÖZ"*yWMÅȼ-jP6UÑ>Õ±ˆ7ó1 µ÷Ë/"óßf·2k¯æ½Á,âõÕX4&ï} &9vc ~~<g}çñjt/Ç$0òdoa!%ú½wKÒhÝh&³A†{óúØùßæ¬ hЬ¬­BKh[IR²-¤’Ú[d–Ø´-¡m ÊZÀ–Ø[I*T%ed*VKi$¶ÈÙ$©Y%´!R¤©ÑHÚKl’[d•+T¬ØØ $¶É¥d„¶’´„*T •’[BÚØBÚm[`BÛ-¤%­*(¶@*TZ*T ØB[a-²Ð-°%KiP¶…´…¶J’T+%¶$­B¶É l%¶Im’µm…jJÖHIZ„ –Ò¡-¡ÚH[a lÛ$…¶¶’ÚKlmV Ò[@*[JÂÒÒJÖ@¶É- Kh[BÒÒm…m¥HKl ©Á8^v 6ðèÆ)»Ö›l*jèãõZë¯Èª ‘TaG u]¦ý¬Ù7zë³Í^²êÇÊÐw* (¿/SúàÄÕ?JÐTçJ¬XêS<ý÷ÚèJV¨â-V[™§ÀÏ7ÖÄ{œ4=PåÅÜÔ„’}B¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢JŠ@‘)~¨¨ž»ûƒ<ÉŠyÃÍøÒeÕTèÕUU@WíÊà”/Û Ô>ÏqxÙµH“¦þ}5sÝäYýIz±8J÷™Ð«Á¨ByRiKŸÁвQkëu$Ùu_]iþ¦G¬oÁ½Äƒ¡ùR½j:0èX ŠF—åC£¢ª .¿µÈ&3a‡Ì\qË›p«·"p7ÝÕ‡ºÊ!GáÃèóUb¡A²#T\, ¢'«ÅB PuJÑPŽØE@ê:‘H"?Ÿp ±@P[(‚¡P †~ÐS*°?2)è=0Ȉä(dÞÊ[/@À‚ꀢdS΂†ECA@ ( ÔUôøc³¶ˆ§×Ç?ýú·úÒ¾®d°Ýg$£å?ªÀ‚ô“ :N£bUt6%ç+·HÅ„øé?nWòµ<¹Ý“èÍ(é…kBµ‹ Z1…h‚Ú RŸÍ´Àª¨Äm"ÈX5jÒØ¤¨µ…20ª”jžë§,]}d4Rƒr/0¬„ê"y¨PñC-óì 7|½¡0‘kØVu¶æ·2C(`´¢QHiV±¥~ù6T¤?6O©^…fcžéÖ' Í«º'®ùº…ˆcœ¶\XG¡0l¤# z7s›ÝáVŸ*ÏQl¥¸3sÓË¥Þþº!¾ás^·çðÏ. ½¿¡<Xîÿ3bu‰¤C™êÄ(§Tù &™±Òí:>çŸ>&ü\$æv–ˆ!†¤DYÉ¢ïðïKöí¾ýÚ¼49_½©î^Ì6ñqþOÏoùùÜñ}*Sžë½+"bš´K-ƒvX#´ù•šâŸ¡‹‹®Ž—ò¸™ç3ÈÚêè^sE_èÌÁŸ¨EE@„{чâ'Õe€}S„ð¡ “0’„‚ (T‚¡ ÀÄÝÌ¢gç㫊:âØÓø{˜áÎ{ê6˜KœTMl«åîCY ì0½ÜÃŽÀyxg$Bb²q‚ >7ö µÜ7Pª³*ªzðæd”è¡ê‹38¢û㻠΄].oýÿŸêÿ£ã?âõ¿Ÿò7úŒ ŽX‹Ý®2Ô͵wÂS6Å“Ï.7©Gý8물ÔH Íÿµ ³e2-T{Lÿéò?f¯›ñÛ*áègiqWð öíB¡Ò D‰Š FWM©Æñd*,¿Ž€ ‘FíØü¡GqKé11®ÊEÝÌÚ•–êìÔ×'Ž»:àŒ×sïJ|ë <ŽG!'<Þ•¶o„Ò¼¨¾• àÑ\COÜ_f‚°bÍËèìÛ»nϹŒýùÐA—o{Õô„û«3i `TÐÿÞòdtÖìÔ–ù†}jÔ´ÖyRÖš"p3[sÇÍ*°(û1úó½Þg·¼áwˆ —ukø3Í|9j(›êòü0 äT‚\ùd6«n[¦^'•ŠŸ¸9|+¼Äw¾¿ÔŠY/³õÌ¢°½Îg(Ü}ó¥e›gi»ø\Ǽú\´£cÂwºî31ö˪ŸWö±aø¨HHH=±LŠ2_u)ç¯íq\ëÊ(1÷ ¸Ãó4g˜Sc !ÞÃù"üΜ¶-¾ÆôÁ°û; ¼ô$-à‹PEú¸ór|´ úü,mçÑÜ¢§àÒ°ûÂíÊî&ÐÒ=û‚äD!öí·¢Àpߢðz@¿‡ »@(B$4 8ö¥—"K©çó8øfoúútKææÔ¹s¦ä¢ÆÜM¸mŵÚUNßTm(y9FÖÄ'U¯*„ä!„й_ÃÇÕÆM5÷·;xÐP܃p‚0݈ÜY6M€ˆ(/:ž›wCo"ô¼5Ժˬ¹è.,3ám¢Ð½‘¶ªŽ­E–¿„+GRd{ÕÎ{ !{:`à?N»Åþ÷žðGWŒ’(Ú¯ð߸7yÇÏûNDþBù }ÿçÏ®üD=.Èr9ŒÃòǯëJR(©ŒÃ­EÑÍœÅÀ¥¦½k÷o[ö~Ñö¼vØšôçeŽnžJ3ýþ…nü~tÇ;>ùöÈ0λ6Õó?ïw5Äí7ƒ‡ÉägÉyFc‚\Úæ¡(¸ZC÷1ÝuÙÇùŠÒòëžBýµj(?2Ý÷Ïü \z@úÎõ[X·öä`p¨ÕêaRN”ªæ¦ŠG¤Â§Âîiøº5¬ÚH ’ŠŠbŠ¢€.Úr¯02r‚J«ƒ€€W˜Ýü4LUK àoÕßýgŸ\'Êÿßö׎84akušÂº×Ïõ#õþ~]9ô¹”«V”–\¼éfhè&:lÑ€ƒÈ”¢h0¡€ÙU FÓ 7sÊÒ'-·;ŸBmæsC^ÀΔRõ=úõ·ÎCB¸‰žâóoyº4ñ¥Ë§•)²ì¨ãy&ƒZ Ô‰º(¹œË¼v×kã“Q²ETSË'ghh!Ð@9³®íÎaÇqD^ÆÞîÆØ’@˜Yœç9»»»»´aÎ;ì“2LŠ©”¼ˆNDÂÃeɰنurá½\cK¼5sHèÞî¶Ü·l«2g “WXÙpÇ?¡þ‹ú¿¾+ÙÇ(¾÷^®™«C¨Wâÿ{Ö󿉮8ã/†¯·Ý *!TÀR–n=7Ï‘€…Íóÿh¬Púô¥–ƒcéÏq¦}¬ã>H+éã„ @tú¾÷˜Ý{”ýNçÀèDìf”Œ€f=%I“5×˼ïØâÝËLV¥ôÎ ƒï>ó–ÛåÓ–ÎXÓN•(©4A Òˆ½| øÚ¯4/2 œKÜ9¡Ö\‚+?JŒ÷ŽKœ¤Ýo{qÖ2™Ùûb ëáPèHágõ 3÷iã»vƒö€.d£DH‡?oó£ÊÍ%úó§¢ò„~óŽò,•'<»ñ¥‰Û–a´Ÿš{üóE òýŸ2N?/ü^}PÕëÍÓ¹[ù§¿ˆ¿†­ÁŠ0"â.K\Ü5Ô?‘.Â#*†­-”¥)AJ R•o…™ÿª³ûìÏá笕ºèuXwÛtòž¶6¯_íºß«ü¯$úø} wé÷ åIèN>ˆ8¡è›Âû뉹0`-ÄK6£§‰Ì‘0·*ƒŒŠ Ž¡©f¡ö#î9)ÈŠ+{é,¢4EPТ°ÉÑ‚ €‚ÀÆ@Ö u°ïÑ:‘äѬYœ €*ÀþÈð]纈æ{ò‚‡ûPD ÃFAŠˆªè´4"šHÄ.1°Q)p¶D²ÊdT‹&B˜d£@Q/#ûh y¾Ø‚ Ò0ø«Nº oMé¡ê=HîRv8ó‹&Mjξ‹´o3ÎÄ«ªªømgÏw¦yýOÐÇø† ‚èspr8&O‚10€`fþ‹è^Nï"ûƒ²nOô=Ø{é¤Étƾò˜ !7½X+ôÔ· ‰ä”GÙ¥'&œÃKlìé&Ý3»ÄÔòœ÷‡\ê Óxçvû¬-°_[]޾x;oÖ¹O,knKU’ÒÑ{žìÞöœ°zQ™±œ_„§›29$ëpp [^ŠªÎ{¤õÄRZfØ_kÜЄ ¬ ¶*CÜ×K+í}V.³ °«£| 2}Õ¥µÆ÷9 *0©¡†Œ\¡²ªèQM¯›îýoÚhÇR??ÇS1bj”D¶c`ÍžMÊ[HO,a¶ …Ð¥ÐMy­TQ±Åùå›ãK002Îë2ÊY:8lÙ«PÙ|iQù$.[ðA =si5âHkÀÁ¡Ë¤ï^}ÈnðpSä\9™å'¥Éè¸/³õ¥¼õµ vQ9‡#°ÛÈ&™ÑÝ{A A-€‚Çôb–Yó¬€DÒèk6{èáÆËµ¿ªðdù÷iÉfsKW Ï ¨ÌD%ÉHOiHI— 1Hä!ºÄÙBÁ=ÔßìØ‚¢Ô/"Wò³dÙV;2V€(Q8G$rܰé1ëí ÖËíÅýªŒ}±§[8è Æâ.Ëu•@‘³ŽlLËà, ¾JÕ‡üñ*uª~ú3ü,²+f+Á–6:$m2gbŸí)Óðbd(Ä/ƒ+.tØc )AdŒAûìžWç|®óòÓÍžTÊxæyøÖ¢åú6@Oiù-0þëGaïƒÁÞ.¨ò|°éùûÿuÒËÔ·ú™ïëø¼©cË#§r—’uÿ ÙȇÙo'áD@€ügˆÊÌUÅ?` Å¿=Ù];Å8[ÒdüJÂlÌž²Í­]=àAmül?G‘AŃøÿ·c“ðg_>«$vH]iaOàÑ»_êøà »8 ´ ð, † ­As¾gÄÓ1ÝbùÄÏʳÌ݇¹Ùà!bI'V-;Ó:âнQ §EàéÏ2/I”íMÙzFe€eòš„”ª48Q!ô¢ÍÅ ‡¬ö<Ðÿa)л Ó1…²^‡òæDåüÏÊÔì¹HÁƒ\¤H@}žón4ÍXˆ>ömBK/@z°^çô+ó²hÈ'*4§]c‰˜nјàL ‘€ÍeRÎNdÞ`Ì'J\®¢J¶sP –+C I–Òš’/ «ƒ"Å ÅWÞ£ó9Pí:t3™„,³V˜D³"罌#™£žQuK³ÖLC]PÞÆ†‹F`òC0éh9IוV%¢‹Fª14‘ 0pt< P‚ (MN5Àé…•”ÐÌðÖ§q7L]íÁ¥¹€T3qšmpiL¼$×1Ó®bQÀ˜n\Í™½³—ca:!3uîL¢›:æÐÏJõ㚣Cóå¢T¨dA204Üàpì’ 2Nœð6ihPÌ3™›m é53ÀÐJ Dº„ÊÂÖlݤ«Õºn£ªÖݺ‚9Þ–nùÙ xžƒžû` !ï@|VÃ$ŸñP¡0D$„<žÀÙ^)»Ú<¹0èP…ì ÉjÅeT’wHlCoµ¬g§ dtÈY F„G‰c aOfÕ*çŒNú!äÐñ)ýð‡C{Ë<öÁV,Y°)ÆŽ?CABêÿ\ˆQ¸g vÀbíz…¤°w&v ÷M@G #žgÀw@X{ÝQ[jjib2! 0%l<HOtÝ%a Ña‰²åè«ð |­+̈.©ûÏPzCTñ>jª9t^™NõA¢ ÔEZˆŸ#´Œ‚ ÿ " 5• ¡b(D‘Y¨M(Mã™TÕÏÙËwølÈy¤‡§éy¿šÁztbÁc"‚¤æ`/©ò2$’&¨qQª|Ôï‹y œi¨P™¤´]yבÚÂE3Ó…ˆ{ÃÕù ôosÎZÀÄemšaZ?™Cž^ç®F £$ì^¶sÖ$=ðujÝ(AÉîèÉO|÷l$R’CF`DÁ¿O[ß¿‘ÁÀ1>1,CÝñ“gJ§©‘fYðçqÏUÄ©¤1&ðà0¨m ®2X0ÔéÎÏ„òŸi ¨J„#¬>Ó†ŠlA ‚"²d¥U×zÏ1:kË Y@Ȱ)*BB$€ùGœ ºœŸ„FQB-¢ÝÓ‰&'&à‚ü±ö0(qæó‘·ÑŸK=à ±äjÖʳp¶Tb(GL¨‚¥Âý§»‰CT=',È‘ïŒ+3/ðY5îòÀHÁ=§CÙßiá£_qŽÍ†@¤B¿6{¾7a 6ƒ×T!‹¢™ ‡ ³™Ì\Á4‚KT¥fÁÊÀríD Éì,6’Ëd„ED½Â€»7‚ª`jB44„¯î«sWìFMnÍEíÂÈÁT8 *G– pYoÚÊyuÇ|ªìmŠ^A…ß”N+§$$%V\qZ0†úÐÆ8ÑÈyŒ9Ë’( sP®V& ÜË ¦Mo dK‘±|›¹F£Ð€HjjW_o½æ'Lü§*’0‘8€V*29 =ÐV0SXXˆ‰©!³ë°DEP~9MNÃv17²H!Ñ|‚ÞÎÓØ ù…Þ×õ1$/á_,Otr=žjy”S‡ìFc«E{Í‘ª6SãR»cHÜ;Ã:7M¦DO BS )¤! ÂiR¿=Ï9àpjõŸöÇ?9=ÞéZ÷ç^ñÚ‹ö9M ¯¯¯,ˆ€ŸožÛglìè!5íé¨àJa )J!§z%‹Î¼½ÅÈ.»½¯;‡ åu–G9Oì9¤™ÏôœÎ.WT£¾º¬‡£ø˜ô: Ï‚¡"TU:øƒhƒP­UZ ´Jbš›?6 ÷â(ÁT?—s´ƒ÷½÷ù\wß»ÿ á¼ÒÒ‘Dô»¡5ðyðw«à” OžÅLW·éIÊB£] H¯(B¨’=lGw[¡»rg<{ ½ÃP¤sEBè¢dˆ³ˆp¥‚:´‡€t£œÖ.î²½Wæ7w ¿á­†á[ÂÍG¡ŸÆ_¿ø=€ö™Ûzj~ocÊ>G.Y Àr4zÄÒ“Ð138ª.¼ÀäÖ2¨©É °°#JªEªÃdQlD¿Šµ®Ø¾­n3Ü„ÀÝ ¥éÊõ€‚ÞÂIGgÒd¿G/m§§ÍæpÅÃOÂïÃÃU¹?{Í”¬Ô€I|æMü¶MOÅ´ólYr$?G×HeÛÏÿ†íÈ7ùÞ»l°:2Dâþ ?üƒûg!±P¨”uXr‚H„€ÂI"@€?¯æ9§_”ª„’02è¬3l’Ì‘…’`Âb“æ@ªªÈ~4­InÈ!é1K‡bA7ƒæ41CÎ21›™ò~^½$ý#œ:Ÿ¢åL²ƒÜK¡ H‹mD¶RËbCM­‰E˜‹XY† 4@“3”Ðà V²˜4±aaa,1Š݉?³Kç7°}M^â*ÛË ¬ Uyÿ`Ç™û`þaKÁß)áYàÔp· ¤vàì" b†AñG<@—6¿$ØitT•R [Õ3c±Ühcžã?”‚@“ŸEU檪ªªªªª¯+b½-UTý9'}r©äÕCÚÉ?eª"$¬X¢½ä9ŠÎ¢wªC£UzèÛ56ª ˆù‰Õò&»à൤’€Au:·Õ(®P)7^‡K`t{ƒt ¡d. ]Ü—0§ÉÆÈXÑO šuXOý}' ‹‰ W‘XH zY/r‘Ê(üÄÐXo¹r¶Ú%£Z"*œñ Å[…>ˆ2%ò|3~àá™”kî7Ð~Ô†oº#àGµápè•÷•]b(ƒëdQqaî\ÎÓìé¸uÙ/ª©Ú ò~$ŸGêKÌB0`¤Y>š½"säfÆAX¡–­T € VC ˆ© H*$¢-e­ÅT#DR%ù¨ Í[èS¢9¢R_à Eœç•†?*œ\ŠÁó–ŠÀ9²T962ö ÀP€ªª¨ŸJª¡ý­øbÎÖ©9R¨ ˆ°çãC5m²TUV £áh½Ä$'Òð5¯M’C:iG4`?d3@@7+˜¿”Bªª«"4ä¾~Fæ#Ÿ 0DÍœ-ùÊIâVb¬þ]ó½1º¸ŠR™Šv!5ŠøþÎ7ß‚²‚b}ÊÁ"I)‘l{ å¥'« ¤ AÒ3Øc[VµÎýÎíôÈáœh=: ùÊý^T@1B ¨°€`mØÿÜ£×’zúÑ–O.\ENSÑî¹Ë•L,å½`®y»fÁEï+· Óüå |ZwR ‡ï“õ¾‰Æ~ÞÇ¥,„c²a)`ÄÒŠÃrëüý=>Çc¯C–¯o!™Æä©U}úWâz-–å·K¸4ƒGKuzw™ÙP0ÕÇLæë’[ã8gþmT( (Û[s‡…ÅÀçõÀd¡<&±±€E̲ÁDLŸ‚GÆ_"$€2 ¤XH"Š   $ÁÉeÔV JW¬ u(ç’%-Ä$HHNùÒ{ÌBüt5}šºµÌ“ÀîaÑDgÎRT}‹Î¶u`vµd&ÒfqjŒ&‡¿sx(OÑý£Æ^–ÞÍkL\ƒæˆ8‡àF ÂòŸ_ŸûÝ-Cß¾ïxÐw¦C¬_ñÄК6")¢–l¢X‘‚ŠÈËëï-õr:€i;'N¼LAµè\C‚!“Op÷¸ÃÄNÎü7ç3ºÎÓF i¼Bza÷Ô ’@°.0˜MKãk Šƒs‘b‡’›3Á;ý08êNBVÈâ§¾Yfõœá¹é€xþ˜Éâ ¼NÒ‚ðð3Ë] oÍ.ÃH àà e3‘é;['¯öY[e*ä‚dÛB[hÑKhi )ìt6‚ÝJvÇÀXwÇŒ-² ‚Ëà›xÔ´’D0<Ëó|#ñºç²P{_”ÌïdÛñ8Æ&{s× /z¶P]n;G%äÁ„6çñÐ]8:‘fP Œ–†¯À»qE.(±¶Rì8÷e8ÂB` ¡C’\LI„8óú}§Òè}Ý<ÊŽz—y¤ÌÃôÛœìuXýånZñpŸW¢ê® DÇ=¡Hc‹cY s„o€:gèÖŒŒà¡¸ òÉë«ùç&V‡çÉûD??o']úoÏ÷ÿ®Îܺ—†'¡1€ºf­S([CÏkX—X³4Êt§ÇÃæòõºùÙúŸ jŽÎ+PE2ÝoþÜw?Ê‹ƒ”ñ e@ZºQp|°§½Èbè&»˜d` ‡›)¶Ë!u—Fl!È+hŠ$¢j%®v†NœL驼Þü$Þ›†b#cYÉÅtF+J„–@C!ÎÜrÀÒZNzDG®¤ðE«¹%>!úÈ'¾£R/ÊÙ¬§ŽvÕM÷‘’ !3¤5äÔ ÍS^mwë¥àh½œB6Ô›uœfö«„ß3-Ä á£/2ó~@V­£¼8^nØ­©ß m\5zà8DãÆ:Ÿ‘Ø—Ñü B8dÌákû#çðg72cªg¡ôtàå®Ìêv¡Ü‰ˆ#ŒÂLÔ ™µµ/¾èCëÀ¤¾l÷Aj%Oh“Ÿ8šXïêWNû×âW«#Žòüäß»¯Åçžç©ÞõßOMB#Íë×~fWqÂvŸqt?êù~žXµràis|CCKñ‚¨ãŽ"ˆœ„0#F(‰BD$5?©Mœœ‹œN ƒ(\Ô r’nȈa2j†‡`; ,ìsTE]°9œ žht†Í>Âa¢hD5G\íèr8‘ÔÜ`Ї&9l$?¤~.¨awÓòØðìLØå ʤ*r;‡" e2þŸøðs4©X1Ä B)áÃ¥5‰B@ŒA 0 ‰!¨ç˜)€ô°A.P?CC×4½0â pf)(ª_³—²w@.ª ˆC.¸j "'ÍŒ´¤K *ª‚müô –ŠQÇå0sîüú|NÁ×@ÔñAä^’¨SÅxÐ"È£Ñ2(°Š?ïÍeê“p!à7?b<±ÖÆB&îºØ–*ë˜ÀÇpýR!a[í b€˜M%”w°öQ"YBØ8bfáNW©jÇ­Â/X¸U B<Ó©»çY0"ª„‚:,«³¤[zÉ ;Ç„ÍQËÆ—*3³|$ptø&ußO%S|cÙàNT;0V`@•KèœP95tiWU–4ÃÌÍ;®¼u IdäXî(K¯ Íʳª&¢™Ž;×p_×\v{“&©½ÐRù2±˜^—ËÓ¿|]ˈݟySÖ‘ž†ûôÒ¤qögMè&÷©õæ¾aÔÜ {Úb ø9?HõÓÀÑ÷±^ýÁ‹D;À ™‡ U<(*'qï!fÄXÊ%s…Ì4ÀÅ _³Câ†_(HS¨q-”‹àC! öàsOðß«AÒ†—w)}SY‘2^09¼Â¾çäÍ ùÂw?Y‚géÙlÌ.û³kÛ ^NLê?;Ž^Æ$Øšöu£8Âî yø ŸeãûäRå¶,:}óy}”A)U<,T‰Æšõi¦Ã©šÕÄÚªµ(´·^TjuP×¯ŽŽ„:÷tãó¨Íqd=øÝ;žzýls乄œ¬©cß›ÓÄt É åÌ_8{=Ü¥ÓCÀ°¹³¡Ô$,º€žv:ÄU‘f‚Wš”ª$i`/2C :Ú‰ÞCTè F—çjH³©Üà½çN`HÁ‚„E‚‘*Åb*ÁAH¢ ÁdŠÁ:A~ÎSÁaxëVŒ‡µ›иx'Ð áèxˆ½ ¢®Áã]H6=!¨‚óÚb ){쯗ª˜Äv‹]$e^º0Bµ½PCµE¡d€+÷±} „ðñ¾„øi+¸€e–+q²òFâ$6}|­=sR÷%"Z~sïÌfk5÷ÙÏ"ã‘\šŸÇñðy6a%åü?¥|¨úÕ÷–ÅäéàìᣇªÛ?MD¨ãó]õ|Öóò`†æœø:.tËoh®;u%Aór#¶ Æ;MÄõò/bï±5Ïpý«S|¹ê#Ix8yOjÝÙgž –òÝ,†s¤Ò¡У´žóI—À‡39YþANœ¥çn!:™D—Ûy²zw” ™„‹!Å/ŒoÕ7uÕÌEÕ¼.£på‰×Ï–þß¿€AÛóË黑ûwä=]GÁÕÌ+ù»í@o£<ãÞÄ zø¶>D|yƒ]d4KŨ€ò âa¼Pµt±ºžº),,,Õ=÷wîÂS$ “—`d˜™K ;CÏ€Ø4äq0=ð]I$GH s ¥kÂÖ,ókò£(znM9!Ç—FX1"A§°±B ƒîŽTA#v¯ÏÛÈ ±+ñ0º½õr+'Ú\Ú”§§DÈý+(H€2!êÔš/h8"܇*¶Ó½l©hò_“(Ü_¼Ðóèž«Q¸ÈŠh7b…Ñ®Œ$ µýã´¶Èx ™N"oÙÖÉ NnfND8†}>øU´Å‹}<¡{ Íb‡´–¡ì´%´%j<¢"¶µªš€ÀY8x!òD Dû²V–@ÐlR|„[‚ÜhœP)ùLVÄû¨|ÄÄ ›(À‘~cqzÙ2Àv³^¦#2¼ÊŽÌ§g¬ ½OØÆjxþ‡ÐÿÛßûæõ¿9ÒzüËçµ4ûDÎ{³¦#Xü‚ƒ˜Ž}€ E0gØsNð 6þmØ3{}J¨ŸnV þu5üFIŸH ´¢-BA´ Ù©1  Æ(€µ„™Ä0\d&ÒiX鿀oUg†YŒ*-'$Œ@Ä‚ˆ•8LEƒmGç‰)£[4W˜ ²~#¨e•ú bHŒRc8œd mº°£ 2JÖ[HE$m€Û¬²R”“ Œ *“ ÑAa(šÉBn-DåCÈõ¾“Œª£Š"d 8žÏ~…e™Ñç÷=ÿ{Ü)' C H#ÖÝ/ëƒÀrï¼Mæð¼;»éH€¿Ó~ c98Þ~ùÙlïô£ÎÐû µ –δ¡u­u®£±1l~N%uå̆è~—òûÿlËùŸµ¯3±›ž¦ïôáàþI³†è&uƒrSºvMÆWæm0˜@Ø"ÈR¡ú¹)PÏœ/ Ÿ È`DÜöPa‰€Óñ÷)¤ˆ/.¦m0ÃL aDO„Ûä”á0èBCÀ`CèÜ‚·º½Ô¹ ãBâ:üî†N6A3À†΂‘;³evé´§$5Š)›:Z&ƒ¨…B … ™œQ%‹€^÷$W0òéõJ=Ò&›;“H¼÷ Exâ{Ñ "¯OÐÝ,r´a ÀŒƒ`§xÈ­[I€¨mìÇ»‘8˜(Hp~ øx`lq,C„$ûñÜÜÂ0êsí¹“ï ’£Î“~`ÃE€RO‚˜kãÝDAa”FðÛ¢Ø?âasƒv†Ä¤ßÈCdGNH‰¥©Ÿ|$T}G@uß™ñµßÕîÿgÝ÷ûÌ–‹ë‚Ñ[Ÿ^©¥¥í~×ÈA…™ÿrZ؈@}¬  Îa»™7ð:^Ö$ˆ T¥¹º ƒˆ'¦)òÄr$‘Ä\ÄÁd9$1^”°U´­1·—æ üínœ3©s”a÷”Lk¤ÎµçùÆ@¾#Ç0”‹âÄÆZwÙ)$`e“ÛÓœe¡ýaâÈz’N†PR³ÆvÊZ&ª¢ù‚àVÁ€þë?Ñr‡“¬‡;Ö2€EÜçE07­4”Ñ!HŠ÷ÞT Øôæk/Ú‘ÊæÛõ–y;ó @ õ$@9ƒörRC7NÒ2"‘Yèô…*ªJ¦Š Š¾‡X!a.{W‘ “Ê5­G»P~&í†=¾ç[…,I6•>ØGíîôx^Ä2´Øvõl•2ÙŠÐõšÔÞP¡2Ìf*.‘<2WiN>HL«ˆ²0PWI‹ÈC~ ˆ… .¡Ð(ÕTð‚úøZÃ¬å“ ¢œˆPšHN&£2`0þßìì6–€ ,H—’þÖÖM’ ƒüZMÌ“¼b0X@‘E*ª ¤bÁ‚Š*› šˆNÁ3FªŒAÈ €Úà£R.å 7xy¨Ý$Vádñ‰ÒõÌ‘®’ËÐ{Ø'Q©/ah Q;˜P§å‡„º »šŸNë#r ¢ò‚€ªóÀ‚â^k¢ý/1ÀÅò{>Û¿ìúg߸!ç5ØPUî3[U+Í º_‹•Õ×Õ9/µY¼¸NëvW¿F²=­›(Ûü‹ÇÝiæ×8ë[ –bC~É^¯a~Û•;OAÈêQKLob¸õÔ¸zݵQ^8²>8hÍ›ç­Cim”Ýomß%8º=ó¦¥n?ÀÙ|¨£³ìx/®œ]: WkOkµ×ì`«1ò ë¤úLiçOÂôç£@A{õüƒÇïŒÊ nÜ=‘빌ipwçËÎ:8'³î=rã.âÝ-/­ÆëzX|—˜ .¯³ŸýÞk­-¤5kBkjê•zw=Ä¡ÄcHg-àü>%üV½v;Ï^7ç0@¸ X°X€[XCÑeø/ÞÀoþÉÚÛš)í!˜ÔHE+óú Œa QÛÇsÖtEÕtú•( ‘'ò¸þÉÑ7¼þËÇ~<ÙrÔ­?Å4â&<àˆxóÚgœH¿€žï_”öâ & ‡¤Õë`&±CäÒˆ@O«=GDÁ’R$ "1@©(¥  4‰`(Œ0…¢ÅZ¥d‘’c.DïÄ‚¦â XÐ0€©q "?¢EA  A—åUAdl2Ũ+ûÇ*©  ­i\jò¤ ™YôÏ~î&SxFNíwè¨%ãí¨ii©œ°uª9ÄFh>(Þ¤mM#Ì€8;ÎöΘÉÑ^¬Ñ@æÔÀº{ðHE4$Ç`úùS@ù刜(âC‡køêô ù9ÚQqçm*”ô€IöNü÷úý§;øû("ˆ >¤DPR5(‚Õm+X1ýÄXª2E¡ÉåýÔú&„Òqgèýx'Í¢ Ÿ–t{ã<öó$2G¦§JÖCã Zý¦„êEM¬9i5Þ=òžRª"Š,Hƒ!hm<€ý6m¼’š D4— µP]DE e‘"È ¬b¨¢ŒSć—‘"À÷e²6Ň­&  ˆ¢!ÓÞSƒ?±—jÑeêÅBôþu‘=þÆno•4ê¥SD‘KÜ«kuÜ+ô;pÔ!R©€‚ÂF ‚‹ÃžÏˆWa]E>ob¿«H¨˜oÛ M}vÛ+dH±}Á>Ÿ.ä?7Äú©ôŠA©â×¶·ðú>/Šô3Üöj½‘4t2˜|Äò€ÐCè|•í»I† ª!¤0Ä6 äé26"r»Íå®¶{dª=¤²H’hä9üm›a@È@GÞ# ÂHÅ’,bIDਠ¤¸¥9.‰¹C<6»EÊji4i1Ôƒ`ÃrF®5ÊDýkÒøOw¥Vr3qj:?¤ BAJ#S”ÏãhŸN#^~ÈjEôiôò¼2W«JS¤ÄŠD`Å9hŸ'~~ŽÁïëÃÓ¦±¹&ëxv‹ ѨíJ#%4D ŸMó§¢SÍ:΄ðdäv?b<âø—t ì/­EΖ5Pï6³ä]žL%)hJv­µúÚÒH|² î¹R­IXÔSÝàÃT»2²ö‡ëŽ §½îë_|Û*þ{6·}8šD>œ3¦ž{Ú*^Uô-£á„3‹AáLéÆów“ŸnܶÂ"Kû³¡¤®éä™ú¡ñÙ‰©†ˆ·ü3Ù]_Qú˜ö ‡‰F4J„*LÁKë$v+»ƒ{™Õ8]Rб{“9Ë¥=&Œ„“„$CpÚn#å]4¾2˜H¢“<¾ .•Ñ$*Æ—I‰ýŸŽÒt;£̳H÷¯ô‘æ^AaBÚE!œ¬ž¬ËIÍtãÌ«L2¹Ý¶†t! ïÖôBĈ@ÙdÀˆÁ ¥ŠÁIN‡>(¡ aš‚# {ŠŒ-8]-ìÕÈA;à¿)ŠOTdP7  è^Áè%àH¦ÌÈ‚ÚÄ_I£öty@"Ežý=l<*0íjô2 Ìñhlîw’°Xuu1c°ÔÌ@_£¢BŸ3‚@@â@°è±9ˆŒ5µ¨X‡m² ‘1í™W HÊÆWT§#gxsNó>;+´ñævIàÀëØ“N^Œ&'mc«¡ËA–«9kËÍðÕQG$åækø÷rOaǘqˆô^Ê[AJ$ƒè…á"6~ý€¦D|¯©†Øõã $õõ„óûQù0ê@U4±DéܘäŒ@¸…©VÛÚJ!e7G ¥›–߆×_A#\áTç>wgr +L `¤}(ÖšZ®¬kD$JçÚÀR4 ³°ŵÐü0èÆc€~ƒµƒ`ãÞ4h p;òÕÿþl4¹CgC“¯"sPR€²¼¡ÆL½e¨‡Y¯œuKîÎú¹ïf§²¹újäûÜYÀc3¯¿lºŽ’@Cê~eêe§Õû¿ðµx›1‡ñ 3Žéù™j »¢á'„o2šÌ`þüyþYuýÿü(â ¾Ç9z/泸öµÎpvx1hé<Ò*%¨OÆ:k‚ç©ä¤}AWª2++Qæ¢[©‘?·ÅC¿.¿æ¸0ÓWùwi.‚c  ‚âM€…HÝåPÁè6uª2©uÁÒb¥<õXC5l ¸‚ÒááÜhà<üØ3ùÉù¨§Â€‹¹ì!¢{œÉ­×±¬àQ#@QFѹ(ïvº[ÁžusÓ®çq¿ë¼K‡ä÷þ“ïznoæîüOàÿí©Á„ÝQ"†ò6$áÑ##î3~/¹Îø_Ýó>~PÈŒ™Bg‚ E‰²¸ñ¡p`„ÛÛôr‚ " z*(’HÔDÀ0 2bˆF!!øI`Œ}F E€³IY"2˜ÂIB ²HÄY1‘«4À…dÄè ˆl®žJ†¤"hŠP¥q%·l VZ¯,ÂW3„‹m+l?*éDGíhÅþi9 ÝäÐíà`á ùhoR•„S=¬æí˜@“ŸÍ„™²#"Â. º1 “Ï]GáÌ6…‡Vuûógú¼×GHz}4^Œ1¹`£”×:! ˆ-&gv¸&ôJv¾¢ „L@H¤w€É`iêÿ €õ ÷9ŸlÞÛvÇk}÷6–çêém¯Ìغ‡H~,õ±$RE„dÕdÕ @ñ^ï²Äl¾»ZtЇ>" 䟄Ž;lªä¸üæH¢`F€Éî¨E¨N2Ð7€Rrª\ö#·g¢Š•(I㸚‘\‡”da6t¡ Å'uˆQT_9"QŠ“ƒAÑàXtÅ¥‹¢¬hâa1„ÆAÝÃVêúìÔº2bKn„¶œ& , ªƒŠ™|ü(¤ÔŽ®­L±BÚ,*É$…  @Ÿ•‹Ü¯€U — ’I@9t"¸ù)À4#˜ZáA¨¨OTišëa'H.¸€‚áÎqÖ!$ õ Ñ w!ÂÏejˆ.™|}H¾º »Ó¢b5©dš a(]˜5Y(Ø«'&DÝ Ns„K ß^p„wJiJÊ"{`ƒôý?sÛ¦Úc»SˆTžƒÍB¼,"ÆÈ"V*?¤ý9[˜Ð„‘’@a ZC-UUUUUUQQAછ\„ÃAn"¦5 ráŸK ±Ÿ“Ð5»×± ‘£hú'ƒìSâ Ø¥¢Hèf4ªPàúõ¶²CÕÇ®sdß¿rLbØŒD¶,g™R±#ÈUÀ©òu*­'E*݈Œ};dÐ RDÃÏ›o“™#ËÄhìb$ZèÀ„˜¢O–Ô2%B øtP0A± #‰•l'´ Ä51 ‰$%±¦EKB, 醊`^Z>ý`€+ìOi¸xD=Ø$Šv¢Ä{I‹ØÂ{SÌ8P=E<¼’¡Æ ÞÑ’À¨ž¨)ÜÃÜAÐÍ%Ë_sBù"óc÷¤åpÐ}!£§[£zKkùBC0€Ñÿn“¼D2pˆÞ…Ý!ŒG2ËV×Qís –Œ¶H'díî„lŸÀDD€@@²Äæ–NÞ<ƒÜ–K¢Q×ÑßUa×NYAÁØí Z@Ÿ}z¹iÒ¡ŠWê”ßkˆ–”Íö_äÒ­½OPÓh"h9U[8Ô±1c¼8¾ã’&ã¶W+® E kÅç¬ÐL"ÉÊ0‘HRöÎÖQÊQ¹^G7LÀm­6Ãp~œ¼ÿ4ç3Açäýµd«6ì@€Ü Ë}þ‰Ã¿òªo¸-Êè~ÿÂ÷¿Wçdâ˜ëƒ?>­ŸEå÷`rŠzƒ¹,¬§dB=Ô~ýËå4¨º+ óÜк|c*mâXb¨ÉÈ·$’©øáý&k³q¸Þ¦=ÑÖ½R ®¶îÌ ^2¯W,ÿ^ä<ï‡tä•<d1Þ&Ýâﱈ³}êŒO…œSá ï­*)˜ ðûva-JÞö»ÑÕ#\<§x\IIâiéÙ†mÛ`Õ¹äÁ”é¨é»î®»~G²B›üç;Uë‡Öu¦hE°q¿­ö|?¾õdÔí)Ð: ¨QëNIÇžzòÜѳԥ #=t/ìéˆvþÐäA@ õV4/[ÂfO&81¬bF0еçÑÕ Ax)¨ˆ¸aÖ©O΂d ‘ÍèbK¸rƒ÷Ñ%P7ö€œÈ.*¥3ñ³Ç©kdø~Æ©Q;€ôì ª‰Ã‚’$‚I‘|$‡’¬AEQAT-,{‹Œ‡ñêý›Ã'«ÓcÛÍî×T×Á9d‰¦üjjD¨?Ü&s¹‘c©š€úa†HBk0Ç V e´ÌÇE–]ÌÌEE*ŒWS]™sYm¦Ñ‹è‘{íı‘ ç;`·ï#¬‚*+ÙÒÀ‡‹òbÔß¶““ Í85\ÖÔ>ì1­ ‡Ø°â!P´bÈ0Éɲs‚X Š±”Qlsíõ(¡¡ i>0,ѳÝ֖ ¿½¤7ƒ7v»´|ØS~F¨5Ê:’@nHâˆH§¦ÇEú¦‰lA¤x†ø,ç™°4_»ûPvPÏUÏ€‚Áßo6Àä!6š¬ T.#jFá°-È7¹½„åßlnºÔøZ~óÇÉítëBÂXÀð3„™Î ~Ñ…ëå>)ÎTOzÍfdª,ãY€le™Ce*žy÷þ,DŽڈˆlê²Ú=ûPMË– HÇÈ<”òD/a¥¯ý 4S`¤dXÐÆ+Óýç´° âÉ´_о"oØQÒh u[0m‚öÁhVßÓÚBÄW.BБ‘E&Qgá²$L Q„HyÓL ©×²a$Üä ̹àd-õã$Db§•¢,zÞ¸i/¾`éê}‰ó¬(èô³é'›Â‚ÿ!…Ü–iˆ`PT«ÜñÙÀ.[á‚ œ^#Újðaà|ßúyÿ­ì=g{ä¯ë>Ï‹ü]/åÿ·»ê3µ5îüÚTÕ(¨Z6®´©Qª …Y±cûïÙþgþ å×úEŸl¯¸YÎi¯šå‘å0Ð_eU&äY‹Âù\íÙÌ)†! $çdê2¸×ø©Œ‚¤ÔV7¿tÖ:y Êï Uq%Ã)¢Ü¹‘I&\j‘\œÞÎjM0¦SqG,1†'à'è°ÄwºsÞõ!´KX¢ÅÞc: (c>¾¨ l5O@é¡Gì»ú=Ú!²/𻘓tN 7Ô’½àØf'^Ç3™•\ÆÉÇ‘v2ô·5x7N¨ktÁF ÅŠm Le*v7$åËX [q4ÌU)˜ª5®†mÔmÞYæ!•¨ÑŸ¹Iø¹G?7œ——³—•“bmu¼]Ù IK@XffJœŸ‰„†ÐÈo8ÉŒ÷(CØÜÈAûQùQµÌ Q:”7£T,Ô ª/î"'t33³G¨gPZÉÜr »Î³JŠšH’@Âá1+Ù÷^²” H¯F7ö9ö^[y•ö|”íÝWo«+Ÿ©K‚Ýs.]æµJìui?¿;¾tBw|@)ý5À\¯ù;yï1§²çޝæNâîÇE¯ÆÞd5Ä[ úRçyÛÙ4uÎÙÍÒ\àDç:—àmQz~ÆoüïŽÙ•$ šRávà–PX#x±Q@ å3pûó’ˆQ‚vÉ’óƒÔ³·ÜVä a™h.âmÕ,9nñPBŸálj§$‡¦ ÕìsnX ‡f©tµˆÙ±#@`²ÀÎâbçÇ©«®CkdÔ†!Ó–‡” îYD¨t·•…X ,£ HÈ™‘‚+"/lð [Ä?(Z! °5xJ¸؉” ™«ôS•.fÎ9›º1T‚" ¨»Kö¢õ–H, "±S ¢ñ,ªÅ’ØOÒ_+q4J ¡†-€ƒZ-ÖŽc–ÈVhª#JØ FEiXIëÊÕ@Å`~º"YDè>}Ýóh4f‚¢½,–ˆDDè„ Eg /MäÎÇô H•„¶ú°!àEê?pãBâŠDº¹•û"ü9ODîdúßl'ô,ÈÎ5„R+Ä€’ƒ" ¢,Ž€‚ú,`š†jnïai wýÝŇ̨ù¡CÍì–T£‡¿ €w iE` 1ŒH=ÊÊ BÖ‘° Æ"Ã"‰Ñà@Øæ"‘,Ÿshul>0öš”ë.ŒÄ AÌì'8ÀãY5 'Ͳ`º… Ú0‰`Ú4Çß:²+ÚxëX¨+€D4Ƀ­Y¡Š{êöÆí-K¨-¢ÔTdĹ´Fè@€h‰9h@ÍBÄ`(4 ´² _5›Ä#™Â F a»(ÄA b2UJ…J6R–ÑcPJ,eeX%I(5PR”H"@‘”B¤„¥¢¤ªà9ŠT H‘VÜvë-Ó†CNOò0É’1I̦ũ9B  LÀ¸˜‚ä‚%y:*ˆ˜[°$HFQ‘H ›†øA‰ÅÐÅ 07 ¢!|¶P†ò‰­”,Eª‚ÔU Ø%€±,”H5È1$F$¥X5¶QÕÌ ¶ÚYR!"«yYp¢ƒCæ3Ý&ÿ\RéÊ„ˆHÔ;"ÚÔ§tÑØòÜäò"RR@±“މ¨O‰½‘E'Œ‚¢CÖ-¨d€s8 Á°9ÔÐýoÖu±¦×SRw3xÄ,Ì+GS‹Ó¨C{×úP¡iØÃb馸.õ怼Vb‡„‘O›TÇïŒ4Â~ü×­Ý 4ÅKÄßÒyX€Ív&]—²QÄ!ˆ»†)*ŠƒS?$¿ÏvÿÆjp´Æ Kp˜˜˜S…F@YŒá€2Ð4u°á'Xa‚T*T ¯äÄd¶ZÏ2š§µç¤£!™3ò'Óó'ð$ÊÁù¿ãþ¬U=¿ßþIïé_ô(ŸýœoÑAôm ö‚i D$B@  Œd„HʈŒU‚Â1$AF$b0ˆ¨Cö?b+Äéü3{Ð"Ë´)H+$l÷Ù :Pœ™û:k½õ°-²q”…E/S ˆ@1»CÆ `±‘„`’ ‚d Ô…)@‚Ämp  ‚á‹QµË¶5 ÆI¹­@1YÎÑ6èOPER!:G’Ø(LœiEÒ’D#h`è„„¦Ö*£gÊ}k au9üðéÆÂ;ʇgaGôÁvÍûvÑ€H(b!!CnùÌ”Ab- ‚ ,6Jˆ‘‰@*!î„J )DMD½RF*Ä!NJ€ðu{Ìyާ#ß\§Oå߀‡uM“Š9å eÅqTÉÀ¨±hZ¨@ “XÓ¼øÈù SÏ ƒÖáÑ,œ—½­¬ø÷) Rm"™Bd´ƒîPôçŸÚ@“QñB°ò[Wq-•¢µ“í¤¢ µpo“‘4• xJ×¹(oÓñÙ®X'·?ˆíe¼‰ L¤(¾LÄ+fàŽÆI$ä!oÌAx`¼IJ(ß`˜„ƒ¤± Ù°E"tGm½×â<Àº'°PYñÀGœ<ÓÊHÔ‘tC° ´û‡.Tý$ÁÝÚf¡ÔÆ–ßIƒ_ÇD\9M€‚Çñ¹ Ã…Gœ’!62Š””%dl’0c% –‰‘˜?t{‘§‡šåVi!¶LT l}Ðùõ7U%DDÝA® ºs;D¨!ôÞ~'Lõö’Å·XÈHˆÉ_¨|!†æÕL× —×Éî,ôZ§ É]t*F"% ´¨”õÈr @" >N‘Ù…ÐwiÄ£—›Ï1eŒ(n8‹d Ièž²Oàxûå¸4ÁÂ$Ê©E"Û™ñ¡CEßa9ÍÄ`"î6,;t ÄsÍ‚õò A~—@ ”w|`½-CÑN‚#> !b“Õ¥!˜$Å‹¿éί©ÓêÒÎb[£_N¹Ì9ŒòvÛÐPm—LaI €>IÐ윊B ¦ne=€pB@±|ՋƒR7²¤Ooº’=„õ5¢MTí$v÷£Æ™fIî–û€5!úPç*²øœ Gé‘-úÔFEXBE„ˆ‚wz9 ÄF@=' x‡Ag-7:ûsCÙÈkâöh=“…«`„7á¹wñr\-îMsÜÂÇ}è—éèÔ¿vH“ÐF®F½œ¹öåƒÈÐìæ@4‡}Â’_¨Û¸0Ð’ÃF¨Î&ñ€(.’ŒÐ—.ÐÂeôaPCÎ"0){õ×0 ñàwbÔE`„#¡qC{ð‰¬P÷a:»[Ñ mPd;cOn«Gi'²=$gM6 sÏ—>ñ„¢ŒŒb ¤Aõ… ÈNNˆœ™;´þÎê9NC(ÉX=L BhIè󒎄Ѐ˜ƒhÀÍ>š¯.ò;F¨£™wçÇh¦±Êà÷(ò(‘ÛùÖ·Â\1}n0ÀPt8½¬‡—šž¿f°Yô|ÂŒUDŠu$€Yp:»˜ž"vÑWgqìŽÛkîãRÚ= 7ÏEÅõî]G·ÆtLÙe3ˆ½'Žl2Ï.Ý´0ÊŒdLFèu7jg"Ý”¯çQΜ‰Ô˜ÔÄÀt€Z¡°ö^Ìñ>†êÆ4ì25ªq4B‚Úg²åKŽ€£ŒW’º.«à¦/I˜Á‰ßýÉT1!A¡4Ò Ê× 2톢Á}ûôú®œºÊ8Q €˜ÀP R2i Ã%U©‘±þ¿×Èô_»«óñc@Xû©q.K­-RJ¡BÕh$ª&HOºþÀOòðØm"¨ƒ8$…FD5jÆÙUV$‹>˜X~çƒZa EÓu,¬I` ÆPDÆÚQ‹²Ú!DV(ÖTYFYA JÔ1  ¨‘DIi,V)™%" f ]8ŽMв('A'çåE‘ˆªÆ "¤š ty«0þõºt¬ÃM HŽ6Ñ­¦4ëþÃúsGbN'èæŒ$™…Œ„–"@“íaoŠëò7àœ#ý=ÚMÛäí&6Õ­J¬¢JóA'\ÀÚn@$ÈR)Þ}íwy®ï,Åuš3—á…IÛ¸ãÏ!…yùŠèLØ£w$½ËæŠ÷¿âôMä˜îÛNÖqòî)-x¥‹è¸":U¦Þ牂1 ÜÀ²í02ÓcŽ û–@[[-i*  ¶@ŒqÝnìÄ*0‚£C’ýX‡‰ Ê@ ˜+•©]HjŸÙÙ±1ÐÀAýP»¨ÞŽ`"îJašL,óß'‡ö1~¡þ-qÁ"E8ñл â±y›Ë7¬pºÃ7B¨‹<$ÒMR’!HE%¬rä¿]Ì,þ&môÇÚ; rNø¿$ —’@cîÄâ»ñé¤f¾7 \2Y0ÈÆAÉe„bI4Õ"Ü6™ä|óeÂû¢tåÊ$ƒg¯"pC’‚ÄQxCV‡d±D`êj Ul–IȹTÆ'BÂÍÔ6(¨ª¨ (Á!$IÍœl_JCoƒ ’9º5wÆd»lEú±Hƒ$Ãûv© $‘H‘bÄO@AA°¨(ºåËè¨ãjfEIXe­JTŠíµ‹šHÒÄc™\£jP£"¡Zã(5Çlöƒ¡ÒˆÚåÊêZ¢Í-52o)ƒ­ßF70à.T‘`¦wHO@Røñ(4‹‰=¹HV²zü€dó_æÄ Il<›ú~\'— Žu󠂦—MÃ#èuÅ3F­]ù9ΣpîÂÆþxDjTpƒÒF#¹ìè ª ©„„d}ò±`P)º€½Éqêt.£Íµ,-A•‰dÐ?Æï%“Èc¥GÂ,ŒcÄX:œÕ@I9${Ob{úÆÆbC}‰A<¿CäöÞG|}ìMû©-ífõH^ö¶¥n|Ϲày¯6P ¹Â‹‰Ýðq†ŽÖÂ#‚ª“³—±Ü4¶¾Üe¸Ù*åßÀÐËìffIvaŒ¬Í†ŒÐçÇeâ]4Ó©ˆ°p§~ŒÉåd)¶ˆèñ¡\u•b‚.RŠQÏåÓ$9´\*ÕcXÇ æ´hq¼·¦!…¤EQ”–Šu·+eào º¡Y1V!£nŒúT¨±Nœ:þ‹&´>“B‘io;V(°EGë¡D„Œ!.¾¼õ€ ˆï¡Q{l"tÓäÁމܤµÂÂ…ÿÙ‘ ‚ÆÒ_wq+d¨ŒDò”ÁA}ÓK!$`0‚i¡ñR¢^á+%¢Š"Ȳ›³ "¨É‚U"D(eðÉš¦yVÂ*°ê'X\‹r_ïiTr Ät  €‚XR)5)⑈aó8Š$Y‹—¼(„“* î€/Í;¶s`>yáá¦9.xxQ.ûÉÈu?w êŽä'™Q`ˆƒI@9Ä=øŸV ÁŒ`x\,yÃdx(O2‹óVãusïxCg1XBXÂHIFsYp·Ž30WvÂÖV°¢‹³ReE’*,Š`4ÆS$Ì&+wI!XBˆA-¤Ñh’TDL)°‘5E!³¦LÔR_dZBåED,À, ŠYÈ”‚aBÚXT_@z~~˜H?1|ÒY<·5€"²q Bè ´ÚTçì HÒH !€Å2è´Q¤¨2X‹lITX%ÊFÓ !A˜!ùC“¿w­ß¡ªÛëš.h`ásþ?»W!‹-óѵ4+.;O[ßEUÅ2"i$5´Æç“†Öb1Ô ñ'ÏO#šÚiéSVÓ)ÊÙºÕ'á8*®3©ÎëžÔ‘IßÓû†•u¡üü™Å=KÓÏþïßsÿ.35ŸãÙŸìÏÏ~âé`U€õuá NP›Þñ­Ô-"HK…`ð$3„ÏØ îÆ¶2AlÕÚŸé§©¤RÑü(çn›ªˆ¿ž~¤zuJ ~ò‘|S•“´5DNF««´ØÃNœÕÍi¦EÏ6ðšJÅ »+97Ÿ@Í®»X`»{<¹Øi6ÊÁy^ˆa‰4˜™tø>w–š>%ža h€ÍÓ0H߯~ù'§ýÕÇ‘Ð?A$gSpäÕÄPG¸‰˜7Û=Mt9*P8¼ù¹Özþõ,¯¨-Ny[7/5em¿?ݦ¿*ãÀ”p›PYY•‰[÷‰ˆ!|㯜LÎy¬V2‰y›âL—‘ -¹Ì€/Š#צ„ÓÊúDXØŽ`éÉRÃ6“) Rª…‘0µ¬•€MÐ+íÃÓuÓ”©7ÆfL uSSoÜO«w“öSTʵRÿTa9ˆ;·‰ðqÞ>¸–„ÓsCd’‚WÔŽÉš±û’çëÉùSŸ>Â…]ü¢”›“íû¹bOÄd>&Ucù¦š"¼#çTE °ŠTÍèÀ|%¯¡EÁ;Êëw–Ôø¦yµÉ"fÑž ’ЈòjxéêaãµMcÊÁL@¼‘ߎÀN»3>íwÛ÷Œ‰Eàô8äLýË«Ò<3×÷1»2—tS"wr|»PŽ)^³bD#–?r±ìÍì—VòNZz3h´C»Ù)Ú?Êß]öÝ èð¢{$Qñ”03*ym2Ñ 2çU7 òÎ-Iù„OÂÔBuöÅé'dNñ·î|­{ÊôýZÕq~ëæxûé÷†¢e4mÐŽhá*~.úÛZÑ’H ±0•sT¬æ…ß2Ü|¿'9xSk9!V'7ݺç;Ê*¤ NÈMæ©YÍ—˜ñnÙ˵ö03#ÒQÃz®”/¨S2èçÓí¾ž÷”%ƹIÑ|Ø1YX϶Ç*ˆ™0&﫵Ïràro®~äý×ã\9Ù2‘%uù¥—avUÐvwõ¿Ëèz¯‡×ìØ¨« ò`ÛJ Q9cD˜”ÐQ’Ç•f„K}#jº0ZIóâùE?¡5K:ÆþÁ«¤u‡Ó£ˆìhnµø…¿6Ã^¬£Ñ æB(¬ªÑÊ…Ä«ÙC9¡˜t§E*s‰Õ>Á„Gœž‘ø±vŽ—ÝØe÷Üo¹¯6AUÓóéΑÀ}+¨(¹I.uºœ”q^ÍÀMè€"DòÆQÌð°!^!óÕ»{MÄ)!ÓUßPû`ªaDQúFŽá«ã˜Ù³y;–Qü¡Ï B¾Ýksa­SG¢ÚF®¥GS´sˆ€€"mzà0­Y<©€fkFÒÕ¶À·W¢Yƒ–h£µ@´¥…”ŒãhTá8¿¾ZxJ`õ›—sÀ^e‹FUCÙQW•ϻ窣­‡êkì»OçñÚ¥Ç×õO+Å*üo×ýt¼Ô™ìNÜ9`i¨Øu ™I.Ür!ì%äP?¸rOhçº;àrgÞÓ·:õd—͘À‚VÅVV’¹ ½ª¸ô@ùºÖ‘Zûç;ñœ¦“œ´½ïP߇ö_½ê"=Û-gö÷ ›?8rÜêXü£ïpÜÁ D C°¢Aÿ^æ® 7®Oñ=×à÷ãÕÊ‡ÓØ ,ù‡g¿»„’<ßÍØ¦BWѺ¥Xþ!®3×HrµG‡{ïÚ±zov¯‚U‰|Sˆ£#Ïáý¾ÿ§X“?T¸ªª<¿Ñ¬‡Ç†6l@Ðÿ~k”„¾Ö^wèSF*„çŃæÁNÕ$ª Ø'œ‚U¸’Éë—"OôÔS$DZ;Gè ÝÊw…y hŃ.ò0´£Ö0ºÓ|/=ËxÂLÕàyk";å½Ûhµ6Ny©š¸ZåŒ +‚(Ý%’nOا£ÂðH"ª§ÝôS2ÔUy =Žóµ¾ËJâJ„ 8,–ÂŒu  ­±QŠÛ(ÂGšó6Nç]Mf+óGG˜º¾Þñ¸¬F/vƒ‰L<БPŽ#!¼¨jwît•WSŠ‚,AbÐôêP`U›|¼RÚ„ tHBÜjmúªÕÐjx¹’Z¬Kj)âÑY”ª"®¦Ã0p׳5Ïï ½ ¦ˆ¤bŸÂJ€±:[¨ÅŠAOLô“ܼ³Â¶Êo§@£ˆ7Ž%Ò«Ø÷‚øiJ‡Ë $3èžûÄ´;u%Q ½èÙ˜åš9GCéoäÎ;í¤„¾†Â .ƒ$ƒ ùRˆ"§&ý>D;ÆM@aÎ!NUiàI!>ùÛç8ÒÀøŸYª¬|›)*+Q­Ö\€Ûv–—ÔÜ*ÐQÖS1_Pª\AŠ‚%¢ˆâ_¸yf(,ªª£QQUUUUBDd€’±Eg?½^_ –|t ¥q:¿ ˜^„>-_`7ÕQ¾Ã¹ì—c¿Ã†Û¯<ÇÈF‚ýWë}_ÑÃën“x\iú7ÍGì|ßÂðø!GîúçÙÃšŠ­îUR¡zø/Û³ûy$h³lA”Æ ˆxh,G¼îÞ¿×u–ûJýQ–áT)‡HPB#ÓËMÑ!ƒ›k€rÉ/ŒÉÒÓˆ]äÍw#sËG95åÉX—ð<¦ß;½—!VŒ¿• Heqãw×uª”ó¼¹–#¤ùEÁÒÎ:c]B“…»¤Œ©íÿm4®{MÙEüTL‚z–”î±?ª†Ÿ„rÔ!ä‡É˜,ôDlîÝZØJ£·’}ÔBàžöZùÅðtÜéRì74ÙBŽçH:álÛÏHñky­ìîr¨šT‡?Eî¡5(¾T¨Nª^=8ÁeÕ‘òO®?)ZåyšŸK›p‡: ÕÎ<»ÔÀ¥ªm4»³;gy›Ô_¡pÄdvè:˜ˆ—ge+{b"ëM¦@03~‡]HéíêTºn’::&Æ.cÁ7yµÈŸ‘Ô>G÷UI8‘\.²PÀÖ°DŽ$R“¤¡ß}DDÈz=~5ðÎ Ã~ËÛ‡måbøÆrrÎxóì¡ü“‡”y—®Ò~þ'Ikñ¤é/DðãWÓ`y„¹´ÉrɈQ”£¬sûOª{”ùôd~¼%7®ï ¸¾gìþø‹°´­ ØŠ»r®Æ !bùE¾çàãñ{N—"fDΡ—°á¼¡`qôöœf yè¼Î(;ê‚ ìÀ‚þ ³& „ñ·£Ò~¯@¯‹›·ázãiŽ=œAÖŽW)û„™<Þ{& &!P*F ¬FF !(EF"ȰÈ'v³Ë°7<¦Å¥^­n[%öå‹é‰~¦â¶-”qrN^òúXÂRêw’Ê6"9ÔßNÖ%Çw‡“–¶yŸ}–C÷ ¹‘£}ÊÌräÊ33n¹òyz„ ¥E¥jìˆô?jANÌ 'Xˆ.W䬌ßI5¤¡¡In]£¤dÍTY=x ä¥Æ!©4~k C †¶y…mM1a@X¢¢‚0X7A„&jFÓÏi89`Hu2Ñ“´:ˆS# ÂB ”":"£ÁÖKˆhPt9P>…Tô*¤D"\úਜ†«a#cZÇÈJg`ºfµJ8ÅÆ(…–ƒ*)‚)$¤ÃU•-2°-SÃ4+M³hÔ1µ]âWBÀµ`áKŽ\ÑMHh]jãÔ²ZšÕ˜ 5ƒ˜·W2ºs,f°Öh ,”Ö¬ËfV¸\`4 8@’§4¢n¶¡« Y¼ ˜"ȸÃ1Ìè@‘5¡ªÈ(1Pb©*³0ƤÄm¶ÊîÕ0´¬µS%‚ÛÝöGqÕ1+»J¤”–ØÛF…¯ÊÕSdGkô¡U{n€ÚHŒÎ†AQM-€åáõ¤ + 1* Ò¾ò2$óE¨È;‚¿^È{À‚ÆåÃdð(*~hjY:eæ“`A|À)©à„é˜+ÁA€Å„DTFHHȰPF `¨ÐÂP”ˆ£‚‘ŽÒƒä‚¹;¸!…~~´T}¢£Jyq2zhøqCÌb ©=hz`‚l-·5lU'9ßÔ»i»¾É]qlpÆG,- w§Ìø"6lÒkDEDXº:P}äøömáí­czá‰$ QäºAqõ,ë"I@ >pŠ\]ã’Ž0Ô±›Õñc Ó¿Ï8úã§›qL¦ƒŠ`­”†°Kd0è! & |¦c͵'ØÀF‹¸jûjò|Å Ó’CY k¡UU$JLmÄ{߇?eCª -ñBÈ 81“@>¿Új îf‚ÐØ! ’ØÐH‡:çD"I!Ä/+?*~yÜ×ËNx²™ã1Dµ/ÐØä¦õË‘Iu-".ƒB ÕxøT±„(<ªCÑqÃQ覓¦ˆˆrb "ÔUiB-˜Ö˜[ÄÒô©1ê‘ô…ˆsìÏH±IARS½ˆ d@DA‚3DùÏÌ÷uÔ⇷í'ñnU„–±kbš0ˆà„(W´NÑDH—ÜpvÙÔ"ò ³~bËJ¤TY ¢Á!ÒI ÷/]Sj ‹¥å0ŠwìЕ¦PôÚîÀÉÏÃ2`Ÿ3Ð!·VLw^ q²É¿‰ûQ²ë£cØS UŽº¯è6‰NÑ0wìáãN¸ ºÉAˆá~,KAª¥ùÆlY„)´† %#€ˆ¸B|gÚú¼¤ä"—‘§„àâÃxÊQö¤$B0 °ôîŸOÆžðùÔw"Á†S9]ͪSºa¯>…庖×\q“ÏÌ>Ò PS¯ƒ¾† D×`ÂÈëP¿Ç‚S§oW¸«ß-ùL* I1±B–[QØ„ /íÌÌÀ;Ò(A!7蜛 ÀÀŽƒ24[Ú‰P jQ¹öy,tΨT‘r ±"Ó…8“Åô?òá¶§ô½Áõ·[Yß/;¥Õ©yogÂöœŠâo!››¡ØÖ>9yÀJ >TEà)_H“$¿wôxð?b [¡ËJ‚ˆ?yý=Ÿ¾ýýs¤ßÐïMUM^%²[ó} _‚¨:DÎú÷‡/”D‡}îw6æc ÿBc¢iW¨—¯/6e§8jD¬è>º–ÿ’D%~YëËâ7=ßÀ:ëÄ›n3!Œ‰?ÎŽÊs`ñŒæÈ$P:Дdöÿ¿æh‡OÇñåëü¯^hdFâ`ÊLÕ ­†k%™Œ”“WJ‰•Šêʪh¤Ä5M ¸Œ"P$ª=¡þ—¡:0…MàîË P)G5Z#d8DB¢H“ÌÓ2…ÛÄ$U‘‘!2jѦƒb yãL¦ÙðqA,²ŽbH¶™Ý0Ì8»F ’Mjð·Ô@u<:üüÝv:‡qü~:rœ™lþ&9í¢¿f÷>Twû¶BñPsÎH$~*¿úÜû&ç®®½ZMAÅMu Ú¨ãàáAœÿ}áËÞú_2ü©FñMŠƒš1,m*±‚Ÿxü¶qZºëæ¦Ýn¼&憄$ôýPßqþëq ètª°;ÍKûT)ýgõ*~ K ÷ÿ­ü\äÈGHr}ÕÄAuÇ'8#ë¡ ¾ÿ£ƒ qîÀ22òæÓPÍ—, )bºÈ9ÜwLkR”ae= ß^Æ€R ‡2€I¹™OVYÒƒµž )lÂÅ‘A@¡Éœ…(ŒQ@!œ,/b’°ÆÈJ JnÃúª4ù-kµ¿Wˆ“¸àª¢T$‡~ÿŸÛËÉȯGôr“±Ÿ7(sè¢\í7‘cYaÛZ˘HA£-nx¼À£ð„zoŒê²]ðÁÓ(ë×ÊH+ßn›­¤ïæIï׿êh}E…u^(Ó~]sÖZJaþ.}_0"¿Iâ6áÓ;z6Уht•©üÎøù ¶=éíæ HuÐòb–ï(ûݸӂvš¥ø.xHnСpW³öxàÐ'=ó¬û^B–6éÕBƒ > ú2*³ ¨¡ê2ì’ ¨"€ÂH0! ,#,xÙñ¾_н麡ÝÎãÎpµ9c4ãQ18@ÈDt`HèP šFÄ›ZÕ´ª”USZÜØa."3©ÜI‡GòÎeœÑì¹dé—¡rÄs¦/öa' _> ®²!‚‚®ob’W©p5¨)'MZ:d€t@xùóAà$/‚lQŠ=Œ>ýz•Ïö‡E;]íÝèç<òÕ|–?-­ªŸÃ‰š…ó‰ ºwz¹òƒåœ¤)N˜ VqŠ€ áÁ-(À kräQ†ÈWyþû8üYg狳sÔ¾˜¸`Ѷ_ªaú¿æÿSýW¾b çù®¾?c©¦NŸmü›ðÉ3ÑBLÁZAzËú}œIûù¶LëÏÂÃq8¨LU²µÚ`¤K?蟽ڕ”®DÌ„&ƒ9ìÊf?B ÁמÄDàÌ#÷èí7GùÄ¿£?w^•ŒÜ­ÝmÃÄ¥ÒmÏ]¼ùÙ’÷tÃ{$¨yíAbjâL?â¹ZrƒåÑuÃYÈ@’%QP‚ †(ªÎnªjøÌ·ZãœÉ%pÑÛ'FÌ-0æeÎÆz#ÿ'õ\¥væÙ€—1EÌ̯îþ+¹ÓéþI}çŸ6ì‹ 3f¯Õ!¾(JÈpâ2 !h BjÞ~F¸µ^ß%õóe}È’u4Þ¸vÔÜ-w$kÙéÔ,`œ ¡§êÿmýº¼FîñÞï ûãé¹Z ?(©ŠˆÊ¨Š.ЧôâØpÑz{oRè âKõ± *Tµtšj~ï‡?àcÎÛEK»Ê/ª‚FU«LDŠy°ž„}楡`^ceDã$Ã:$t 0TéNùT(ªƒT-Mo{boÍÆñ±Ò”Ä$¸C2"u.-;ª¡¨Å…*)Iß[—üeiâkZïaAið õ˜1FsÔ­ÌŽp½gXB*™N>Ô_Ìçà:tp­ëý>RùüÕ™FM;õ.oƒúÖçÝô‘Eù _À$ »Î¾å|¯ÁõŸ/‡kºiøÏŽææ>âvšÔO¸ÖÑííé¤Ràñ(.?¥©tR_ö¿¹ýGå|’cèÓç4ëYÞT(©TTª(ŒK^sÂü!Àù;y$ lðsŠøF`Û'?ÀC20hÈbô(äU>ð<ƒ@î´ ©÷^¨h™@ V˨ú ˆ!"HÁbT5ÂèŽQÆ.ð7HÆ!!B(²*‹ql=¶ÛGðh-ÛCyÍÙ]aøÄÖ3 ¢$vózߣ}®…ƒ„®»{W."Œ6°A1vݯk«üÚíîë÷#x‡î"–—Ø¥cÈÙÚççåU¥öƒa¡È.0€…+Ö(¡hˆÆ5ø¼öïýùùù‘j<½dx÷Ô†úŒ¤q*eT¦€…ñyõ'9&áȯ®ÐÖ—úÙýt¬ýÃäyå4~å@ØþçÄ£ÕýСûë[9Cþ§f þÏâ%+ d„‘ûÇX7h“‰q+Ù÷®Ý0÷n!ùœ[ÜŠ„}º¢>kW TŠU˜Üøý’º­îð÷ÝËÞ½%Ö«K“ô¸Sh?Öýþ<Ó~ÏX”Ò­ôúSŒÿ9®z ݽZ”aÖ7€€o2ÇcÙÍNüL4“ÛºBÅ~=jǼ²÷qÛàåùÊY¸|¾çîÀð§U˱ÙO‹ß†RV”¶ö¾=¯ûEùbáîÌÝüºîrqlQÿoO+’…‘'Ÿ!¥xSÔÚKêR2\Úµ¿t>³I³C<³ËTÍž™¥Hä\9ËîÖ;³ý4ý!Ö›ïnƧWz—²Üji<{×Ë#”vÔìcƒù2ã#«y¿–½ÝÆ/Œn‘ýÒ‡÷H “mxŒ±Ù`G‘²F`,vz¶%I"F3ÛGÑZLä[ñÚUª¬u€í]m°·,®ß(é €¡±x‚´~_€…ó+cвÖÐä©Q½Ý‹ÿsù•ÄË{í±\Z¯Ãf·™ôúå㯷0Úþ×ç­×çkìímcêã´hþÞâSR¦¼KØl.%©íµ¶)L¸Ç?ûwŒ„n:Ë)2çŠ:ª¯qvýVâ†íg;ú‰òýÑïuIˆå= OíÓ|n0ÞSMemFor@B ³4SMg¿"â×Y,»š Fý#©¸C|‡#ØT´àt”È}‘YO5¬LÑ&Lí££·lä’2LYN^Ž·AöFêdö3”óv]{¥]¦xZÞ%(Z`Tåÿ°«²}-—–2µñŠF­•#­±gF–Öû3­§@ØrRAÛ®•3äKÇ•`„ ‹š,Åô„¿‡w_‹.~­l< §Yw‡¶×wœ¹\¥Vgd'?<*ŽÈHû«Ÿé;½Š×wå˜ä¶>¯Y_d”œn(Óïr¦©ÒIj^/9»bÔöå|-¬ÙÔª§½¨!#N®CøÛ:œ…,jWÊCÕÊOë'LyërŒÃÉÚlSòžŠÊièæ}²¢¹Ÿ’/:Û‹Ì›sG;ñóÔ<ßç·ùÿÓµYwœ ,§[/ŸÐWHÓ]hLLåîiõ½4}͇Áõ–R§öÏSüo¬K˜¿sßù6h»\Iöi^+ÕëÓnʺ3'©hØm5ic Rø˜Ò~?¿9˜Ûxö;´Õì¿›‹ò¢’Ðç6}=îoO%û±†´eô¶ïï}úe‡}g&yj»µ]v±ùÙ3F×}/ëÝy÷9§ßk˜ ]â¡éÌ þaÓ¡Ùá:ÊQ¨k<³Qøÿe †Ž«ÇZÖ?¾ëß7B|]ÒàŸ,òLD¬ë´´B3Ê•$MFôö?{’OÏÿ= þf¨Zÿm“9]9ïSæÁñ)»VvõÚÉŠ›´ Y¶tâN(éÚÅ„ŠÞz;­N/­øêFpùÈwJû‘Þ8 1Y÷$o´!ç?cZëÖvu±û·›‘‹e”–aužÑí¸ªi|TÜß/CÖè¶î¹îñÉ:]½ÌoÉæ¦½'ÐŽÒ¤¡ƒ—¶K!ßÃ>÷ûõòt^@A±²i7÷Öã¼\-P©ef<ë›?~/þùìí1¾Vuç*¿v’Z÷SFÈNM˜@?I{í¾†¯ÁèÞ¢ÕIS_˜ŸäöLwvή[|Ö÷ýÙ·ÓM{5>ØìçQU=u’Éæ‡o¦Ÿa:_2ŸÛ‘˜Oðîw[\¦©ºY:8ÖnðúV÷%P"ìëß4ð5Ø^8ý1?W›êly)žÚþÇàÊ>|!}^h|Ë-b,Þ¦'+ºÒližY¥}m¾¯-‰“#m–ÂÌS*°]8'vK÷T^tÃÛir˜üŽ­¥Ëö‡Â™î^ÿ.çX_2=}µžâ¦õý©3Êßy`‚ûhÏï)ê¾N†4DZè1Lûçmã½z^Kã£ÖFq:?[½6¿‹¶j¹˜ú5å4:»ÿ¿ê/ÏSO9ŠüwÎ}au&Ñõ$,0yh[_$ÑÛ/VVµ?íia®ãµ¿^ªKÚ~åd «æu‹¨:p¨+Œ›–xQ´ãN uÚ… qïn`aÜ£G†ƒÏSO”‹é\Þ§Ï?eÍ“â²ë¶Ïé ¦'‰¸Ã¹"nJy³¡©xೕW¾¹É̦I©5­ VÛ"àfLü]µ|ìR<üGã²wïälwçgíåc-÷~5ÞàÀ@Aé/™ÉN•†éõØ)q²Ÿºþ÷jÝmÃ1ߎ_þñq¶3ížU—,5e¬bewñðRéµ_5s´LüDˆ ×*ÊF²úK¬CâÙráêä¯,°z¹9h>fzb¦K×_Âõ¬'¶|ªýÑ2ÙvÅmvv=E¡&®™Kg+ÉÀ¿ð>Àûd/Ö+±y½ÎÕEK?Ò/ÏË1;…€¼s„§t•–ƾY¼º¿àà)OññyñÈÿWgÇßÛó =¬¶ÞçO_Ôæx™9ûËžš?OÝ•¦¥^“²ÞµbÔõ-W¬7«5:å¾ïÝg;‘²Lt\üë«£×ð“eÔ6ßDÖOæ¨j µÙT€¢•g]/—ðäq´=ÚDkíæEÏÄûÍÍîóY%m‘öÄÏ…§³Š¡éÚ7rÒ_§ñ’4øjî7wÖ´©ñw͹PÖ//#ìÏmÊÊdöµ†­S„ÍF­tk„­Ae#èÑ…è¾ôÔ¾4K%º`)T§©[åCk®¹c»îµÖüÙÒ“ùÙI#¥Ì[ù¶º†®¯~íeÛ+šßÒeYåS“%8¹.K÷§U´A¹ù;Ž|ßïŽßç·lRš; §÷³Gq7àѾîãU\vu]îðÑoqIŸ‰UÛœâa»ÔÒmB×p—ÇûFB+O=>ÉÎù7K¤])Õòý3ZJJ/²·ž;ô\¶º[aÔîé=ïüþnõøâ¨t]‰H–Ïèê € jjÊsG æ²›  ºÖ:Ù¾_UmÚ }«Ä‘äå„ËÛêpÜ>ŠÐüýLêc«1œèר¬·U¨ !2ŸíÔUï3S>èd¸5pðOÌŒÝæœEU¦Iÿ ¶ü4Yµ²} ó´ ÿÁÕù£A}…ÑÎϨÒ/di½OéV~¬ænË’‡†v™;|Û÷£Ð~[øT5À°:£ÐÍMo=Ðgú¶”÷)]-A´XF31‡î/±ÿFçÏ/{¬î¹v™y×Í7•_”F=I£ƒå{5> ^-Œ#ún+#}—M;WÒ¸PªjFôbA©TêGË}_9KsgrųÕ;Çe𭳬ØÚë!óêt º¸Í׉/àjÏ}¬_`ü^zgc8Ó1–·¶ì̲ìÙ÷Œnv‚¿oê]Êp5z ññùJ«‹ý,Üä8÷‡Y‘ÿhÑJmHúoÌetb^6ó–õ•úF6ߥ¶øÿ{†ûó;D:ëtŒÞÆO-ã–®Z¾Y98swm~~²(œêweþ¿úöýTÄ«N2Ÿ}.gÓýÚ(ö¬±Xn¿\O±™u†ÙeÝ•tEýÄ)Ó{û9㙊½eÏEñ¯…¹wÑžÄÒ#'²­ÌKJÛ™Î7j™SržÞŽ­5?ȧnsx4%ëaé«¶º§]"1:þ„?‹õz7pŸYçb¼»¬´y8œg[˜ÔÃ1¥eúÚ:Nyiõ nU¿Ñ¦¢9>+¥xç]îcÕô/oÝv8u—V¬Ëy•w¹ùm©sûE¶ŽâWE2‡ÃÑ^9ÈYkt;KÜMRŒÕÔy˜„Ÿg¢3_’ÇT²Jä¦>Z$wË[©¾R>Úûn<)Žûl‹ÍŸäSöÛÕ7üÛóüX¶õø )¿®ÅK Ú]sí?·Ë’þp2ÿ´ÉŽv­•vÍAõCÚæE˜ìV¼K«ÚìçxÅ@¾¯`ÛÏ=Ë«§óyhú{å:×)i ï"äßS,qöRµÛ|fq¶v!ã"Ë÷c=ÌÚjw)ߨžE\¤… Ê;¢’õãå²›„sEB' Ò—7Õ¥gÃÆ@²ñé[r›&«èH]AÎ[Vq㉩e„p¯ë)o ;-z“—OsºXË—ÿ¾V¿J…M6YWãÓðQóúŤÉýã7Í%-'BïÝ©`ÐÆ\þQÙntpŸÖIëõݧ@Íø½^Û´1ö“Ÿº7F·uóœË8cˆia}ßí½©~!a½º ·ÊUS‡åd«lT½ù‡™Ÿ»UÓ«IÎËÝre-´:«–›ýt/3'ý oª mSH\RšB ±d4ý 6Úƒá_©’ï¬Mæ5¿45¤þç¶Š^Ÿ½µ†â: C¦Ô—1ª´Ù·ëç®YñA\q¶Ä ¢ˆŸ¸øða¿ÈUï]ØTø|¼Ë”º£×Ìó—d’¥eÿ——“üýßGÆ•Áþ±9¸MòÀó"{V›ê÷´7Fº%em ÿ[&»%-ðèu¹~*ä›kqÀ¦¬è´î/ª`x kü½­ûn•HøŸë\h©ÎoùYìÎZY-'?g¸5­67ÙÐJÀaW²5&yçžæ'rZ]C=A‘dΉ_ÒÍv§ã§÷׫±ÿÂxySØ‹}›Ê¦6¦ Ìæ_G¢×¨a%SëŽÝ¶&¿¥xùøÏ„>glã¤ÑÐN•Àöeógä5v“¬¦ÿ–UE ¯÷ÍbÕ¹Z¨ik çíùŒïë(ÖîcÎuØÌŽåû$ÅŽÄÈÃ^¸?ÔU¢zÄn¥vKhëðWxWÿ=ŽØÎ->¦!kMÕÈîóùÌ‚g¯ÒliËÓçs¹Lšû¤ÊÛjJ=S7Á"¢ÎÚÍÕ²ÇÅü?›ù%Hû›:½? åép6ŸøÕøµÎRpLXÔi5=¼åùí +O¬¡Ä¥¥ÀÖïeˆ@H{#Âç¾îôK…Ê §3йewËÃä Q“Ë:ú-žë  þd*ãšm¨êÃëNõk/¢E ¯íŒÍbR®ªÎ*ý‚“¾y–=#´Ç•›R`ñRF©+ÿÓ p/Ð›ßæ'èÿ»Õ€g2+‹æë\x‘³Fkï+ö¹º™‚ŽK›úä+7RgåÜ–çŸoµkFähØî?“­öN•·ý†FM\&kU=ÐÒxéyN? êÆ]õîƒr縕¯ÃxäLiŒXVÄ=üÍ µŒÐMpgç¼ûÙw6qú‰˜/¯“dÞ?¡6¶¤t²œèm|Žõ}w"ÃÒée)Ùäø=T>E™³¶ä®’>ð?ƒ{ŠØç‰iÌÿE¼^ñfá•ö߯Ýêºg¨R™zÝìö¡“±\¼æœ³éÁÆ+{]*ØŒáVˆ³ãm ÎZ`U…¸òž«ä¥óú“øÇdŒÜ”:\)#Ë{ úï7’îZÞ¾†ë‹óººî,DÁÂy¦”§ù˜m^zž»ûwÿ$¤ºv§ïÃXz@Øi@~R/Y]Â3rx祔Æÿ«?•Æ‹o¼Ašó(èp´>›+E–¾'-Rm²û Ä¿÷G÷ûdµš+J› ‰|ŠtkÐüΞ˶ïºg…¦¾§ö÷ØU;Ýö']Öîr—3ò÷c±¯1s[}Š®- 6—­”ZÚï¯"sÿ?ƒ6©kÛ¥±ât4}ÖŸøêgÅÃaC !•u2™"M3Ô{mµ£›ÜF9¡VÓfÍæÄWÏÏéóÓ°ý+º·»‰…zZLÜÖ3”šeDåÖÊõ9ž»#+cT¶c+6²F#—|ÿ£vz•UVI;³²ÙÓ°µ§±¹¿yS%¤)w:7KèŽ yÇ>•tKTG6£5ƒèÄLcVV•ö!ðérµj“ª¡}½3&½I€û¨öüTùº‡$æ<û|È…Œ¼Èðö¦iøŒk›Ød¾ïèÿ@ ¤Ã- ¯mªœÿNæ×'žx]”ÚåüÊÅf¢ñÚOs9-‘ÊNíù:×­;„Wº”ݭѥá…Ýïwñm¯x|ÆAÙgzÝ™eb笭0ìøMæF …îm§ëèü÷Ù:8y4—ž¶ú‡Ðz-B«n»¬àËc÷øœ Öå%÷Å2¤­µí®¥²¥Bv'Ýj¨ U¼=\™¬¥½o½QßbÕºæ-ëcu :|*x(Û7ˆŒ6ûÒýÄš>3‚ߘOÉŸé.)$Þ9økÐquÞ÷uÈ›/·$’¨GÒÎõ©š(쥒ñišW”lm°zÚoŽÛÁf¢«ºNËÚj?¨ó·¦5 ©Mu]ƒX”œ<Žr+©kï±H¤{IýAA+j|º%Üü”® $¥?[˜¹8»™÷Ø÷hV_´ý6küvý GË_oéèЫ9ê6›ù(Ü´äËÓ•6î¡sŸJ¿ÒØIÁ´Œîß™ò¸Žƒ‰îí=z.·>¤¤¶Vnòl1!ðñÔð9ÉXŠê˜úºöïŸh{ì³@Ø«B·ài|ëwpjäó>öºŠ&Ù7íŒËk£¿øíñÿ}Ÿº5îÉ¿ïG¿ëÜØÎY^ÊHæ SÒãiä&Œm{ÿ}˜{‡µ†¥vð­;­”¤žVoç!¡L³ûysÞ…ÙÀ@¿÷sùâ%_BÆw°ƒáÔL¾]YÒ¡þôªi©? 0ò»Þ¡-+(ÛxôŸ­f !Ü 3'žG¿Ç¹ðp™wy{Å6Ep§·É/ªm¥»¹™nãOõ–ONAõnú~3VI“üM-þõxöhh0üJ–ÕU—ÎN£9i‘o™³2—Ç+öõìº|åþŸO.†Ùß䎷Ëúéý¿~„î=³SÉβÇi×§Üõ<;è¥,l£&oùŸÅJO°ªðê5ZMÂu,›ú)ÿ‚M?Žng9/ñFÔ6›ÿU9-b·ëžÛ?ÒZž—3üÉð¶Ü·¬ÆÒ ±lÊêO~xNz‚|ÃáÛx˜æ^åšÜ¾Æ¢ —ÇÆ3ÑRK`hlõp·å‚î6g »ÿ‰=†¿`ŵÔ:».={£¾ËñV9ø›.ž·ò‘¸ÎFÈÎð“39u«¡'•®÷|üDf: ÕAÓQ5Æ¡»œ÷$Ùõ×1U~7¼[~ëK3 êê,dx~F½ŸßŸîq7]sçkѳûåç8M6~?ö†#ÒÉŠkïí¬°­ °5–tUŸ‰ŠLQ/V¬|êq;e«óÚ5–V%–òÊ+=|®Ÿ5þµ,öa[¢{9Æñ/å³N£}c7‹…kq{£Ð3)ÔÄdOÞs_Y·õè0VZ,ÓùfsvÕûµõL—lÆû%žü¿Bpß½·wN<¤Þ->øÞO‡þã[„ͱý¡ú{Ö•ñ¡SÁ¯UH›öÚÇü4ÏÅ‹}®žn’Á#+ùK¤ÍdS3¾ž{ã ¦ÖHþ+ /Ï„×û|~Úó2ç+ÔOÊ(ë#Ö»OÛ\]ÝgrêïŸTÞÛ(µHmÛ{ÂÇ!kðýÜ¢é©ç>;ëÆD¨múnF⧻ΌãóP܆XW®mOUpæ9‚¥OõžKoùÇõj#±w• öO ž®ò þÃa{‰FéK,ê²ô¼/ÆW‚¹ÎVós0(™ñÖþmŽ–m¡s‘óïeÛq¾Ù‡nD‘×҉Z˜ ÕM´ÞZÒžMI_ûÂ[¢á/¿xúQx ú¼ºc%ðʽ[4£'õ‡N^UÖb»¶vê Í}G­JöwnûÄÝd5½å†œÇޓޯÐó&zšVTÎ/-òîýÆ…¥JÂŽ „Û¼t³`­aÄøn&-VyüíìßÓc“¶ËTor‘v9ÿÙÎǽçuønó8Üá°kšÙù6h1ïÿ» –Ñí²ê´úw<šŽ®óIq^v ÷›*ùf™Ø˜Éb(ÿ!ÏÛ×­tlqŸÔ„OÝfò—¾í§—— nФÍwóy¹äè¦ ¦(9Ž÷ô÷±ã¶Ž–k'#Õÿ5Ó·Æ/Cèàý˜~)i¿Jþiú;5{Eç„Zrró¥[Þpx\ì”’]/w8Þá±Óo{‘Õº R¿­‚­î¤|ûõ̯Y!ÑuFk¡wàßÁcŒãdšß7-1^Mòw¢NOùk²ƒÁMë¨ôoj×?¾¾7•áC…¯Žj°ËÇBÑ~o*ÿnÇÊ.¡ ± ¿ùŠ É2šÍã›Ò(4Þ{ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@\<ÝppÊñ}õ*}Zhb@†_{q»}Î]Îum¸»Ñêöòox8]2øð÷gÇDaŽÆ=zÍÛ®öîóM]tªÓq€Ü·ZjvÛ=:NØÓ®åt¹{Øè =‡®]2J@¯6¶ M€tÑжÀ6À( aP[ãCç×Ϫ» w¹ÃèLР׸E ›àWÛž°³ Q·žCäqN²We¾.%:o0÷ܰà¾û¸&ç%$.—Ͼ‡×݇'s㌀=ó‚€D}ë®ÞËØñóâíéëê AÙÝÓ¤O>&»ç;ÜôÁ\ݱٓ1«l͵R‹¾û×r¾ëë›FHÛ$´jñMñŽàñ«§¡A]òúàøØ­Sß}“Þ«0U  S¼}n ˜¾šÈ|Gp¼À¢ïØ0}úU ÷‰ç¼WÐoF=ð÷wÏ‚ÑÞú7ß@5­ï€»½ÝÜ'€v-”—DÃQ‘Þk®p÷³P ¾ûµ³@Œ°|Å¡ËrÃè7Âô¼ZæÄÇŽ7Aˆ!g»ƒÉî*ƒ"Nœc@éˆ"»„ŽÐÜ]ÀM`#‹£ÐדÇa‹17ntÐm<ÔêK‡}¸ðùèTÎ÷‡rM>¼t ¤ûå¾ú·±ë­³•CE¬ës0u‰ETIÚ±¦éñ…tÅÅß=Á9}°¡% _ûÏ@û®Þ쫽)M±¯v§¾>iá òÈ™€hùŒî¼ÙGy µ‘¤„ª›€s«¦¸4÷ÇÞâÓØÛfñŽB£«'Îû=pM6x½“{îwÞ^¬bIA:nš²ÂH%TkCçÁh;rïx5|™*)kE¦Žo};‰¾q}”4 -{ñ¾¾€·ÉÝë»mBHôÅTe@HG¾\íæ]¬`iT ÖQKa¯ßo–ßu­Zb‰|^K/æúÜ÷:EA(P¤ ÖƒX¦òúûÜP ’í»ëÞ{cc@ '­4Ôé´Ð÷ÏhÐÙ÷WqžÞð{ctк AØÕÕdSµ0ï‡Þ禣mŠ¥7ßGx{|kÉâêéì]÷»·>O¸¦–SëïNžù}9ÆË±€"¤@& €LÂ` €˜0&ÉÉ‘£#D @L ÈÀÓ4Ñ¡ dhd4Ð4Ѐ4ša¤õ0`™'¦Ñ0Jh 4ši„Å6i4òbje=M11µ4Ô𞧪y21OSO#&›ALÓFš‡©¦S˜z¦›SFi4=FLêze=O)£M4M$H @@4˜Òai ´MSÞ§èSÁªzOÒŸª~M)úšè†ˆÓÉ´§éª¨ÚhÚ¤üÔ‘¼¨òfTýOR~¤y'©é¡ê~©êz@õ6™OzOQê ž iêa=A„È@CFÀŒ`ODÀL&É€hCdÈi¦CÀh™…6™44d¦À’ @ &€F†€DôšmFJzžÐ©þ”ÈÙ51=š§ú’o ž‰ú“ôÚTÞÐÒ¦ÚiOQê{ЩäÚSô{Jl(õ=TòžÔiú§¢cB{SIå44i±Oj˜=Q TD@dãþM›“úUð ¾õ–daË­©Ç$_xŽç•þ[Ì$u1ªk®5³óÑ ŽRøXV*NÏË~³ý+lUÏtxI* uŸRävõÁE𶀈gû‘ëÿ6˜ õº™q”¸H ¯ßd2H‰ûæ6»©÷D„áo$Ç#F"±JÔjÚ)Dl¢V¬jr$ [(2µ­m°¨ÿðhŒ *4‰ I6ž¾bj"ö©ÎZ\¤Co޽¡þaªCÿ£ý9¿þê+o‰ø[^j¡ÞçAJsù†½U‘ç5Ywañˆ:CP0@ˆ©lyìv‹[[ýt|­V¢º‹ÑuÞ¯)³æáŠé^j×(ÈÇ-$¢ R@4ðp½f².b!)M¿ç¯«‰ae|ýÃ…³æ­£ónòœuÍø6U*a6~"–\A‹-! Yy„%"Ì""”„@1!V¥·03ö´„­Zé ªÏŒÂ¦|72ÔSl˜•ƒöù„Qq©.¨e¹– ! (Ö¥lE©‰‰2$YˆÈ~ù'»ÅœYFŠU•’Ó°¢~Ç·øýnêjÊÞ0ïCšIÁN7( §{¼Ý¢L:˜™h\êN*"#­C¿ŠîÑUÄEC¶ˆ¦ž ‡Û£¢À€)~p}ÜyH9‚&,òfäpT4‘3–ªå¨VïàƒåýJj9*e-èáJv•SŽ égçœÔÓñ¨/Æ;Ãÿö “ޤ.5•=‚Y»?ì^‹Mü6t—½0*Œ^|ëQ^TŽÀ™†ƒ‚Ó—UÁ¸`ý®ív Òz¼îº³Ò™ vûcç_{ßèa\?Gµ›«¨×Ã"j.ur»_Õ¨²¡#ØwâºäýäRßZ<6«ð­`ÁÓÃã,“Á@%vÈ ^_ËŽ|ÓµNxˆ ßü'S2¿s"û¨šu¢.U'н©ê¦Õ{‘.ŠТ¢ênEЦ"ײ‚¦Hw‰±j©r^LSÚªÖ"/aM'y{D¸•e°ü÷ÉæÞ„~Bw17+Þ1sϬI}ßfÃl´™; Zw›Å¬(~Í&-¢0IÃÃZíü2~«OÓîÓùQRQDYSW§,*{k»÷¡Âå+´7#>_秤{»ž!JíÉ>%EF×eG$på +>Œêù=š¦Ú'0é”`Èñ>Åjô½rxO¼<À­x{@Ç´èŒúÔ{gl­æÏ]ãÕð«ÅF³n¥XÔòj½Üú;ŤÖgàû79êï§mJ÷x;ÿ%PžÑY¼%M:MÇð{O‰¯Qqí~F‚Sg|:³%n6J|ÇŸ…Ìcû&;rŸ±Ó5ù©5æ<ŒÂAƒÄ>dú¦RÇKPÐpÍ«Ü0ž*ÿÈÌûðNéxžã~›ÏÂ3 ùÓI(zDàºf(sc„ìñkXäÓúxç«…=ÿÙb¼ŸÑb qí×@q.Êat_ó×V€NeÔ=T;MÛ5[»•îdD@ŒÁž}H`»\"pËJ|B‰IPØ Z¤åPw;O¿ÉïÛ÷ßïDýï=îÂ÷·ô^zÍ\!ë}–•Ò™!õ;…¯TÀ„6·Õ(ô‚½tÕ®»õ@®qôL |6ÃÊ_æa³‡ÓÜâ8†PÀ?î‰Ö¢~(6ܚŽ"% º“´Lá°Äüõác·ƒO*õ@€,áoho™Ï¨¼?½rî§B6:hñtÝ&N¹Ñ÷X6¡¸éUÇòWëÚl³MúwÍ„<ŸÚÓku&~öÜt÷N†u!¿ÌñÜÞÆÇ’cÕù¸L'·ëEÞEA°½“îZìhÊQYÃõÄãŠ*¸î$5²¾ù1q2ˆa§Ñ÷z7FÁIJ$+žQ8¬Òzc#©a`¡1Xƒ^¡–ÍžžÈˆ¯6ï¾Â`ò6ç&.ÞOßý³z'ÃE0β4i ÊlNzz[øª÷l+^9­h¯ ~ïµ’z·‰ÞU.ÆJ<ê Áƒ•ñn#íx”½:–G¸Z”hcšÿ·-bû&„ŸÉ;ó¦ÛÉÛñÞ¨bLÀ0¥ŸÜ'…9^@ðÀ¦„‡`²¨ärø‡1n™i¡AQ@(¦Ðt}Îíß™ÙÝî>NI9®‚&öŠ÷´R‡SG¾¨)Éþn;WÑd´<ÿ¯_ó¼¢ pè€ÄÑJ_蔦EÛÃüâýö*~Žo»§ç¦ÅÂ쀫ؚ €ô3ûp †ØÏC×.¼à(‘T(¹Þ¾™¤â—Èuøg®P©½ÞUUÁÄþÈ1x—U ~È‚_z\"ïÇ»ã2üºóoÔž®Iç?>õ#=’59ó’÷ ã á˘ÒÑñ®ß@n3ýQ®……ŠY;÷--G¸¥4ý¥÷ð¥ä$&¯òÓŒ‡¦C^!aì§§Ó»Öë÷¦®oÁÎä!ÿ›ðÃ2f˜Ìk±Ëk1¨ó˜;†^žÍtü c¾lW7fcbc9ä«·Úc¹ìÓC)}¿ƒ÷e¹g°š‡a¬XØèL ]!XpiO,߬ïù<ßÐñªewÍå ™h< ËcSwÎsÕ>|˜š“…‚qÕPÀu”ÏØ¿Ãèýkι»wo­éd‰!oé”'¯m !ê¹§t5.#.çs­(@áÐp‚ÿoønLë}ý­uÊܰWÇùæí õÜ‘êϘA®öU¸x”|µW»°—2ž˜,ã;|?ȳçjÇO­ûÁç&«~o ¸R`2׆¯×ܺà-à«W1Xïx“+ K&šFò¾tÔk‰ÅF(šóNà|[,,‚Îm ¢eàä ºÀó0áÀFmD=«(oID¹ ` @ò»0NMåt¹|î_µ¤@åXŠõ¶[73•ñ;n[¬ø+mùËZx¼vZw›Òæ¹£ÌZ|­ÌDW¼ËeE µÐä¹íJö\ù¼ß1ýs¹®'S®ÿTó¸ò9q-I‡µré ‡ÈÁëûàÆ/˜™ °Ï:v9gç4Šx'üFˆÆ €%7ÌžÓáŠçê—:² nT™,rÇ9þ¬Ä¶“†–b LpŽ(Õî’ €‹£WDí&n ¿ù—û̆tÂ0üFc•~?Åÿ.L†Híw†à¹tÇוÒWÇø$ æ[øÙüV–ãor¹_xtZB‰‹»üCX”þv&>ªÓ0¾†µ7?]ó–3WÚT}aż$óQÔ®kË ’ˆ´H苽ר©@e¡© øi¤U¤OÇ7®`À‰l¿¿^^ KäLØÉ…ŽJ2o—: gQ8Z@á †i¨Ãæaªî*þLI GYŒ5ËÐzGí¿å"™(ÿøŸVb—ØÓéÑŒZˆ¯û]èU+w5Qê¼d7ÙäK³øÐúêMQÔ‰õ÷¡oƒÍ(×-"Ê‘oï{òÂf!x±Úg·ùÏuì×§ÚÈEÖƒFTe77e•¬aš'`(‚¥ª§Ž|)pвeƒH¦Öl3°‹ðM‡Þ=$Ù¼b#›­mÙ¹ŸªýÉ-´Œz¸ÒÇöÕèÅêÈo;LÊE»Ýh}ÓÛ–túzb®TIÝ|‰pÿ(~:êJBp@ Û°Ø`Ç!1„÷5Z € ‚O6 ǪÓ],²²Ÿã×’u(ŸT^ƒ3S  +{§Xëkè¶C;Ú ¾ò3³Øtô€¢Ü¤D|½(Ì_Ê·‘5"sh©ØŸ\g¸Â\¹R¾~Œ )TíÄŠnr$y!Šï£ßìÚƒÍï²³+1ð‡âETÖÎi•wT…úÚÕ39ÆÝIJ¡¬n¦ˆ°ÁOM–ûÆ}@t£æp‹|9æî·²Œ<ލ§×â÷rW(s°~«õm”åúlDà % (H,‘ÍÙgø~"é:¼dϼ@N{á‚[/î©óãó•KñwÍv¸"C” æa3Ðu9¬*×&3"Õtï£ @®Ìz©œ$¯½~gò¯µ£ý«ç¼ØóA”¬8iO£ÌóyVö/¡TinÒ]:´$ø°ª9MVì¯ç?m­ïAsüÔ0£°„ha£5Ù«¾å±»Åc*yõ¢=…ýU˯V¯‹¡îÙ»x` €À˜:ùüöw\Ÿs€Ë]@^Z ìÝ?!J„°â畽ôŸËìÿoÉæ6Ü÷—Ûùº^ÊéÅÛöx~R×ÝøÓ3KµÛ.yh¦@Š:4|´S^bžA,QA£bÁF…#h•E 1”@¯HU ¸Æ*‡Ü ¡PQÕLü¹”æñýï¿ÍýÞ.üT}]··S¹h9z©êAµŸ!Á^)ªë°î¦dBì,Ä:*©ÞI¾^ݤˣ´¿B Õ¸Á\­Ó%ÂPP»¹m…RþÒ…TYj ŠÕßú(ÁöÈP×bñ„d–+óP³7<4MkߥW^µîÞ™&°zœÏ -ÍáTBª ŒÎ=6ø•ã‡eÑö]ûö.ï7›ÍpÎá¸è©}©Â£ocÇÏçžï–SÝOC׋µ‚‘E1ÈùÓ£Ùì8ß{¾{CëzÐçŒÌ9-ÂÓ^'ß½šÉ¸DCy»oî§~¹éïÿJÞôq+º{tžÂÏ*déôúaÕäO1ß\w«_²è·óýÝ*W¿æåñMu‰Ò<ûÏŸÅvcȨNšz4˜#š¨RC¼¢–ÆBÞåJ%L£0³)†êU‡Álácåo*{,øàÂ#!)z£¿×E„DÎ   ç€0Š,’HtÜuÀ±üˆyz§-ú°áXÏ~ǪĹ>øÓ~’TÿÍÀ~æµGï®*tqκ»øˆP)压¼½—¨ÝzŸÝwšuBÐH!0èߎÞ}êÚ·@´Ÿ…õЋ£á%›éîÁ²H#gùˆã½ÀÓ’;wì\«¤ŽÑɽÔYµF™>L“NkbÔkQ,ò‡ë—æÃ‚GCÁÎõìúN7Ö,nwlèìÞ n;¾Û4ÇÁÞìíÉZ5±$QkÓÈë»GsÙY.uô‘èso6ÛôÞw¿àñ$¹jŸ¸—óuˆ"fI¾·qr M¿Ÿ•·ºÏ—ÎMÓD8„YßøÎÿºþVßSܨˆ-y„Ó±hùW>•{qÿ~ÍÍ¥ÇIÜt>Ïñüà ¾Å~Ã㿹† ÑºO÷P9)Ï÷ÿcéÏ¿mÛAr­,™™†½¿%^©¢þ¯¶¢ØajTÿ£ýøq¿¨k¯ƒÔã€× ˵HA©’’R„ƒ$ÈÎýÏ;Ch´I´Š?½_&ßú·œ;á€FD#¼@ÐÐ(â  çô›Õï÷5si¡@íe)¶ÑLÝpÜKV­¥UZ´Øtҽȸcd”àkvr„àz9£ÑÉqDWª:L wM×0µÆ~3„]añk—z@qé& Ȥ:æ÷Ù{zî]*Fþc¢*€ÄCÒ )Œ!‘J­–Üš“›(“P;o,n(+–P‹¶Fû­XE­§%ÁlÉBf”ôj¦ˆî* 8cwóýíµþËXfÕü4ŸÀAª<“] ºNJHªÏsÝ4ú‹ §º <òS sòǾ¬ßò~7·i?ÄìýÔ}¶^ç‚Áì]üÿËÛ–<~Sœµ6®ãp¸L¸E!¸LÚ;°OØëã·ß½¿?·¼F¢gWG¯W=›ˆ÷{{¤’Ð@uVwUëS ~q…Ðyɪ¾ÔyÚO!ÊžìŠL%FB1ˆZ©Êãž^†Êá´Æ}½w»(ß<ð-;x÷ôõµ9&[ ,™ŠÔƒPÞ¦åq–€²-ÝCÍÅ?êþí¾êôñ¥ÀêIá×D˜ƒb›G““ò™“aÃã™svóѳúЂ° ¡nÇ“ RÅ U¹¢¹8ò~û]ð¥™û)k9r‹Âk»eîN»P¨×מ°…ó÷Ú”)ýgÀ¥Hp꘾HÙ¢p«±ô„0y’Vz‹8¬J_½w×N~Í7«˜§R#¥ù¶#_"10Ô "8YK‰Þäe¸%hÉ”'‘ˆl7*ä‹"€$ tÈHÀ$Xóí„ö³ÕóôCN}F½ ÷L(Ê}L…½Ÿ1ºZlë…HªÙ&©á)cxØ µà-¯ÔÕ’Ì\‹4€@΄$Èäp”½]°³¼kô!Öo¡ááÅ*’ú¼[Ïb(c×­ºÁÝåQ!‹¦Ø€ù†<ðˆm%ý!7½µ~ƒ™8þÒåá–ïÕÙå’&/G¤?K'G¥,@Ÿ\Dâ˜D ÃÂä:âTÖÑ5;0#ƒ‡‘ß+‘ñUؽղç/léê—bO»;3Õ$`l{A™ã éHÖ¢­–¾uhH¬ìUEuvA*îrãoö¨¯|Ø÷B Ÿ¨‘ÁÆŸT­ý§P±uM"~æ›Ý†È‚2ñ{SGö e0xðÕ;lxC‚R„ï&$ßqRq‚Æ?9ø¸€¢e©ñÝ«”ø27‰ÏÑÆw–‰qHƒ„ÿ†ùˆ|ôLƒeš½ñ”xuà¸ðD˜’\gDŠŠ¤ßŠÙ‰{–O¨Â™½[Ô™˜f/ ðÀ=UÁeŠßôLñ•'LÓ¶Wfa‚”c&'ØÅƒïçúhzC)€øÓ}|]T$$ÍÖVanÿuzÑt\3y'cšÑ¶P%©Éq"Œ^¨KR[ªs’Õ@Æ??cn9:AŽöT-Üø’h=;«å–¾YÝñ‚ žŸŽR¼4…¾~@Ëãë¹çR ÄÀ9Ä…€§×u¨€h&· l?Y1Ùé°³ñ¼"þ¡ñÌþñ‰ïúµ?£w´ïñ 1jÆQ¡‰ ËF˜â6üÍ<ÚÆÕªgèy)!:íVê“á¢f±þn_x¶K£uy;Ï¢÷wŠWùJ^œÕÆU;R§ìU¿ù ïÕ…’êb2ŠƒDv¿vY»é!gIŒ`c{VKFÕBÛf! FÜfg9Äç.7'1äZ³Ž&óöë¡ì‘òPíéáÑŽZF$ÜCÔbñëwÄäõÞ ÿÿ֣‚^L½ËacdOúH„ám€žw)Akf.W)€™-‹à"›¤4üÀ!Šû@?>3i\%&q/¿¹Áahx1pÒFƺ ­©Õ˜‡ðÞÝ£‹°mväXOt1Ú¸²ÙÑ—ƒdíWõü¨ŸØhÌFäCßÝ fÂRý É:»Ž}(µ»¢…]€ø¹ýªÇù½ç½h*«äê*_vÂ'¬Xê¥Ôÿæ\zH_cº¯á»ït æš™An¹WŠ9IìœßBf‡€Ò{lC¥Üö%ÖÒF3&€´7¡Ñ7Ì¿8O¥Šøù­*!€Ð™ÃL'cˆ^èá†X ¹"….øME ÿ+mg¦)8©[¶^®iÞΪôOˆÓ‚µ²ìZK,Á+¬-k"ŒZ²ÛxŒ€¥f Añbø‰ÚAš0!%i]ÁÝNøÏ/Ï:I-|®­ç¯Êé>ÌÝDB™? „ôÚ~<¹t¦Ì¿¨×Xd©_dF' @Qõ eç—õ“Ú¢ƒÖ¼ÇuYƒ†1ÖpcM]žÝÿ¼ÃHI±™E/7 Pè­Û¥â‹ÏÑ&Ëdú=œP³.yY÷#V1³åO •n§µÄõ¦lÓà­7"²Þ²¼d‰wôêxa• ¾ì«I¸!y[†]ì[ þšö×z£w«ë:W^sKÈ6Á»w}^&b¯‹&\ýxïöjÉgAÙžp@þ›ê. ûùB±_˜!÷à°Ø}{ÀÁwÇyN‚[gf‚Åf–ÍèÞà±æŒ%Ö'ÄFéO{ Q =øþ889å 6´<ˆe(MЦ¥ß™/kâÏ2ê>$iÊxí‡Ï®EØsÅ8@óÎË àŽ¬YüÆ©Œöˆá˜¯–sø¬¤ÃºÈY±_zð»0Ð2sÎëù?…9tIð¨ñiô¿µ¼'ñQ4«zïd웫An+üïY®Üˆ‡À>–w4lG¶G¤ZÝ}¬J¾éÔKäb·IRun#¹çÿQütöŽo¼6ïüüL„O¹M¾ÚJ/²–{Dê«¿U)¸·+µ°Ä’ì€ ×> 8 6~¸ŸÅ[#Öá9w»ï{DÔIlD!ÿhîõÀ|ã…³Z½×î¦ÈåNM8˜e2Ïn§ iãÝÖb\…9jáHL‹wÔëiA¸Z…T˜›=ïö'fÈZ:&¿¯½whÍ´¤hñLTÏîsŒn ½¬®èª¡”´îÃ)±­+!ѵ3.Ì ;¼º:RßbÌ·ªìHß;Ê™ ¡‰…=õyÊkødÏùÞ6–æûs?/èk…ÑrEª­s¥éR·Ï(qëÂ&óÿ ÇEÅ †ýìÜ߉~d&ØRs` • ÿ ¸Þ*!""ÕNgOkälv-6>³¶þ—*;yv'×ó‚i\O.š1<¨‰Ø*ŸI ÖiÆ?>~• :²ãÕã’Pä·ùj³{‡Ýz—­=íø—D-Ч[–á*ØCaoÑ5à-e/z󎓤q¤BƒýˆWH‰Ü·aŸòVÙã ^˜ñT/â»Pô8°Š;,æ­¹%‘ƒÙ˜à—óOn½û^5{þH kJÔfñ8úçÙ*‹‰÷˜ Ä†èúÕ¾l`Yqcî¢Ñ@d®ÓñÏKÌŽO)åù?“Å/¹÷…RÚ:C‹(}ùxJ{ÛK;L~ÜŽOŒ³Â¨2…ýoùi Š{C›Óß’“ü8ÐêÝP+wA{ªZWi9оÒú"C³;iS9nw¦­VÚ`ÌÝú=r(Yõ{ÓXUƒ™ ¦ÞÆ‚£Ç Ò¥Bþ*ÏB» ì La6ë/Ӝ̒¢þú\Øžô u§¨ù>m»Å៌ì^ña•C(ÐÏÞ)þå íŸÇúÆÚöˆÓ&pUD‘S`éqTÑ€ûví-:z\U`€²y$o:Dï–ª¸–µ‹‘>/a1’”ä·*¬(­ÒŒ2 tÒ}Äô<ãXøQæ?ŒtÊR–„Kò¾ûnxû\þ^Ìæ” }_áw¯ïí|€ðëBÆDäííVÝù-:)¤ €¢¢)h8…_ÙÍì5ûëêRézŽÝ9áŸÔDˆ]`)þ›•ù ½·AÇ£ZÌÈ~}Do(mªéƺr ?hª–ס֮,Œì«•É’´¿{(ïž}Éâ;©;X—Õós1Ñ`—H‹tvñ¥bk…&âÖáDO|ñXÙ$ÄŸÒ(D—̤ϼŽÔ!ÉH?J VÝTÛŒ]ÿ‘y7ÝQœ5ךuØ¿¾ìB9ÄM¦Ð»òî[9è¤×+vÐÎnc[$E( #ì0ŠEþ:­³~¿äxßèˆð¢UÛ¦T5M=3ç°ŽZNá-¯þ¯ï5MØ÷+goKG”¡°ÉU>rš/­Rþ{1´âvãÛ¼#„ÐX¼lž®K~£°tÄ{ûÞš†ºÅE¦ïDžö™£eÉÌfQ½Ö„¯r'Ö÷ßCÉPóܾ+Pò8å!Dè‘*ÛÒ[Ý1èžð¢›l´ 8!ÎÇQòñÛ¬‹óFí„@Wyç¤!,%–núüD@Íæ"yÄhïá*éÚ%A£QîJ÷~ïè±GiŸP–Éñí;Ãl>¸ÆdœÜ"[<¼P°ÕY&%îåH×#|ëªVo O˜i„ŽÕˆ#‰ïì—4!áâ|LõÇu|Úq,%ϸ¾ÂÄýßúÞeYºîM4ª‰ó‘=”õä›·ÎÀ%$Edyg÷ÙÄ–µÈWàäÓüëù¡f*Yr_×#Å0>Ô^kc¬ Çè}?‡ß°“â¿„¢óñ¿Ð`ò]ËÙ>*ø8M_`!üúvyˆã‹ms7&õÑ?íâavWÕ¾bQ)—R´Ñ2c|úKë3œòû?Âm#uhLN¶vF¹ŒÌ)ÌÖš¢¬7´­ôÐàWäM”ùÄ,1Z9©çZ€³t_^8äÙ2Æ–÷þ^Õà{DÌ:ƒ¤œLWSv(4=è°®'?Ïr°’’LgU¶dr2¾©wç¤ÐOE¦ùÜ}tâ™æÈóº ‰ %þ÷%ºˆ¥³\¼0I&p¸9¿?|äâBÌF^x¼'1€ÏˆY_^~ˆýÿL7©—ýò²÷FÝ© ´g@])òs·Ž¥í%ê²z`GâÀ‹N!EÛ”A+E7I²i‰¡qÌ÷ÜDråd¡éýÄ;Ø„”“•隇ú{öñÖgþs€ °ÿâjïwèj|gâéKJÌÚÄŽ ”îMiäÅøÔãá¼EƸQøìJ1в~<ÿ;%Z‹,$~Sb‚Úƒ±v*ÄmNªHdX=Ÿ¡Ü•ùçêIȺæHJ~Æ›XRe½T'WÇ A9WlýÛÿr$ß ƒ0ÿ²x1—]’Ä/äÇà¶6dâûþ3ÃNoÑL—µ±¶NÅ;}c_d9œôGÉgB{ãß±?‡aK¿ýz$ Ú‹æÀXÓ.¢TSÏk.Þ¬)s8r¬íÿ}&Ê®°=ðÄ,â’?xÒøfï—¥GÔ2¤ªJHM¾­[íóÉ¥ÔÎH®ÏÞOvªìSíy¾øå„ŽíTTH®¢[•±'V¼¤äß,?Txé‹£ù—ã„’ú†]µ?5íl¨5Ô°ÿ^¼ß¹{Tu {£!&sälZÏð©Ô+U‡I2•û¥à†8€÷#ÔF=Ûäã°úöä;í¾â?µO”ðȾp`‚Kœ¡U’ïvi¼±lÎÖš‹¦„Ž(ƒH>íßXñ¨–½‚å›þú?9• ñžB‡Roè¥m ø®Wg’ÓxÂ0š‰U¼¼`‡’!ML2.òÞ.ÎpëÁ/âþ•ÔSwV[̬}štá²’®9ös»5é&>Š@ jmGÐ²Ï !÷vhV@¡wé$<™„êx»*ÀrÁáI6Ãép$IðãH÷ÕÁ—¿U à¿gËGÝýC ÆyÓþ…5 ­|þ”fñ;ûEtÆ…“ª8£»G›¾= ESèÝ$0F©ƒcÙ$Š9½-íœ ôT@j“¬rB¡X­,Ùs‰Q‡‡ö'KÖ€m~7á5.?MÏúE`³|š,;-‰J‹žsSS)=û°Yx'‘ ˆŠº¾†|‡â¾]÷½sUÒ¦µ÷ÿL“–W‡tZ_Ì Äžâzs(zB¿3­=ö;#qUŒK§®E‘g÷-ÉBºßÎÍØFQýŸÇ9voÕf¸¤¼ì›¬){3ó…•\êü˜³A²Èz-.]r }´ç¯6áf;Æ«"k8®ãá”÷šz6$„ ‹†ÿëØ;Â&focöF29…÷ ëÛi Kï7 ‚c ×§»%Ä<DvˆâÓØR¶)œ%škªª÷ÎZøÿ%7tÜ©ã»ëÙh?Õ$¿pjnq¶äRÐxk©];¶êÌûôžßÏ=‘TéÖW5ÔËRWºyØþuAjù[y5IøC)SánN;æ?,? ˜Ô˜ö#ÎIyˆ×°xõndY »Z«•Ú‚ˆŽ•³çˆ€ÑæÅJ•´­ ¸ö1U Õ"ûÙIQ™ w‚iŒ@6Éφ’EŒ‚â šÔ‹@Î_Õ ÙŸ÷wÒFÎÂÈ€†/Š5Zzè«ùs3wþXEǨwÙ†ª8‚_VrÉr ƒøÚ’•àÅúF¶Ói¢Z}cB>¥:ª‡¬µ” =^¤™RQð)/”y)\0©õrMXå¼l©|¢TE¶Í«hΪ]ŸSyq²'¹ˆ`F™Eô=O~j¥˜ÈtXéÏ{@µU(ô ’ÄQQv»kŽp†ÀQ´ÈžCÅË«ýoËeϱ}9ÿ­ôx.¿Å¿áw;¡ô`kðE ®s±„O^¢nqP^ƪ ±Áži;J ¡ü}Š ‡ûßh¯¹A:8âÆþ«°;³±ÙçùTÛí”?¥UUB…‚(î–f”Ëq\=•ù—åRÕ»ä:iƒ>±ÜÝh=/ù),FÍÊjª‚öo%6áË—×à×.‹"3ëѺÿÅ*™p€“Öö¹eŒKW™|ŠeÎ&宋Íå³NÚxZÁ‚qX^-ú_|¯Ríïí¬mËiº ¦B**¨ ¨î_~ªº­PW¾ÒMú°Öltºd ’,‘ ŠpÁUEDDDϬŒ£ ­ŠK<½•™þÚ_Ðeè? ’4R01Æ£$Ì^PÚk…µ–÷1jnäeCD„„$~- D ?áР€3(Kä°£#´¢"Á„L6då®8.‹%¥,¢SÍq4tð=„w†£äâW7WQ¬ÀØX£ã`:ÑQæJCá°tb ‰Õ€%š ˆjò[XDæ] ÆØ¡0h2T6kãÓàÅpèBY„FHA!9¾ lp^”ÈÈÈ#q?ï!º× K”;`vÀ®hÃ/,Åäv²d˜9éjvÏ—ïèʱH,#'•”\ªx@^z23d”ªÍ"¡!é{ÿ&Ø”Dd‘bÁ`,P|¤–C^f6ÌÊ"DUC\üœq,À™˜r°b,’a@›!b„$>¿QmŒVG8»`å0ÍàuÁdq‡ùÐlDË髦j€â}E‚âjMp Š(çF¢îcýUµÏƒ\×»_/-fÛÇðظxwïÝñ*l#›'vÉ §È THÏYáßKr.ÚKš™ñ‰º«ç´E¥ý”?þ_[]SÆC¤q0Âf“E¸gi†L5Ç)ïq$OzÔ‡ ä1ÈÝ`òù)\›,—‚ÈÞ.tÑ~ÚölÜ’)V1ôj¥Î²nþ >þ}ç§ÛùÛ=@@oþÿ¢*=ÿ_K»ÑÏÓJ§‡ÏE@?Jâsø üü…~Z‰C½iók(ØÈ®±ÂlCR¤‚Š< üÖài`=U«ÝÝsŠ> øAQÿ ]½sw]l×cìløfX¢-Φ½–¸‰ðç¡ú?+»ÿ<Ë;Ž‘ÍÙØù¼ ÷[°öUÏãåÇ£'ÓüãÖPŸéF¢›xà=§]½ðREªs‘Ü’ãÚÉEc 4¹2‘§žmàuÍ>ÌTE»rë° Â#µf Ä»6ö,n¶R)áeÛ,‚ÝhäŠgg‚n4¨$Ö¦ÈðÉrín‡?íöÉ|EæªÔ30ßÅÓmÜûtji™¶Ï‰ªñ¾08ÙÆ9RÚoŠòFʘž»Ëêš2¬m0Úiy+8 ¹‹ž“WdÔõ1”»'ÑW»†YM”étEæ€Zô/Wzž¨«Å@úð-èåâ¯ÛlY8ÚÍ¢ŽìÄg Ð|F;Þ×Ô´²± ‚½ºI&LŠhp¾‰B@!ÉÿS#oƒÑõÐ` }‰'ot3Á˜þÑ¥öû/m•ã˜w½A„`oVõ°k1èÚ ºk{±žÄrR’+›ëÂl@W±¹ƒ,2àuã5!ÜXl‚‰c†’ªGœTb)…›ôîµ€’ÕíÍÔµ‰½Qï'BJ»<Ù¥èÆçÂ~sG¸Ý|[ëËDgáì™™™é ç!H‚D ¥)Q±±Z1…´—ÝsϨ\EÖ£@¨ÿà?Iö9¿TLãyðOBâvàTþQ5,ß»UÓf(t_/±Úu/)I¾;ô(ƒ¯Ò\HÌÌÉK(Ö‡di¨H’J TŠÙm‰ã¡XùÞV\Ç3 `e¨=“P3NŽ1„ÁϽôúîÎGÚwY<‰Õix°çÜÙ¶–”ê\sNNµu€faœyØÇ¶²©døÇ.«‰sß2ˆÈÏ"7G5$QÁ¬mË¡3cz±4Y̺èÅ™‚>Á6ýž˜ìax»šÂCù´¦û3™ŠskÌ;Jw'#!"(ÄQµsÂÆu–•}™Uœ$fÎZÉš9ævÅ"[—ÁhcdjN§ç®×ô“¡„aîžìßîd~ßF4”VÕvI¹°±ò°3¦J¾×³†lZ¬èvAÈTuý7ÝŠŽ–ÎYï¶ü.뽎½½¾tÝÕ ­:$´ì£J/ 3 ¡r"_÷nb‚“¢¿âÜ}qí÷{…ƒÞ·¹AfI €Q…ëÒ<¾º‹ÇåŸwër¹‰ ÔîÇ’Ò¤!cÔæl{yô‚F –!UZ,…AHYU󳞈Õòr›Isä(Â!Z33Waø}¯¤úò^«i“Xô¿kŸ§ãé|z+= El›sºéè}NÉÖÄÉ4F“™ûJ÷g5Ž=uèvÏ׫§Ÿ áŽZ·ópߟÆò\ÝèyÇaAdFBE¤Z=߆^ÒHNþ'¹ÊÖ1 ÄPDUTV Œ`$Œ –‘VF ¬ ‚0Eˆ¨©îïÇÛç>×Îö¯~.´ðù¶Ó –ã¹åé¾as¡±qʰn×ñ@^ÎÌ狳‡.ÅÎv3MжµsІ‚úÒ16n 6‘æ›cLÁ4p†M ÐðÐaÉΑ„\YNbó%=µƒ\Y°;&߯(ÁÔlc!™†Ù´ZªáÞÑ ;ÚT–­-­Œ¹‡Žê¦3âkm¥±²nïC3 ƒsL3 >øAQ TwŠ©èYs™›?3[-qÝÂ*ªë¦`¹2ŠÒ f¬E²²® æƒ\¥È¬‘|·¶Ÿ$Pxô·u•®RGHñ%ècw9¨ŒÕ¶cž£•ÿ™¹n£È`¨Rjvk7Y6À>SEˆ‘cTøéß©¿‰qæ²1Ý{'ã(ë× ÁX9wvÒ¤‰v²e5&ø$HÀ¬Æ)1ëaP¤òSN4ñ•vþÇ&_ݼzV’=D‘¾a$Ã|5ëìøIF'*Éu·‹ %r.|@1‚|f›<õS¦Ò¥;ñ¹=}ð…‘!V)„ E"„hg ?ª E&ËÜñçÙƒ,Œ³µªÅR^i©¡¬vB9ßU:pußÚj'Õañ‘ÀBtvhŠ|‚(PQM¸>µ €ÞÃÊtš£õ§ˆã‘‚Ã0Ý#½Äuð[}ì—¿›Oyë§Ó¶½²È?]üª¦;ùá~ž¨_vêÃùŸ­¬Fùb=ˆ€y€‹°(£•ÅÀÊ‚£‰¬gðoÍÃ+J­f/ ¨×…ÅÙ×|z¹`{9Ý þ¼éË\£ÒáݦüºÅG¬*?${Qø¨ù‡êAaݼ£W{‡ í÷ü‹w¯(Šû'l5ÒÔÆ/áÿj´¨ŒßÇÇdû¦^=yŠqõ!¬ÈšŸ×ŠËì£f{îwZb9sQ€ znû:÷Ǿƒt¶Ç‹oø¥ƒ¿sÙݦd´ÃüßR•‰ìb¼_îÿ›ïö+¯ØûÝõúäîxD†gÓ:ˆ¾4CO€"8Ùf„‹ ö1À–OåÔL—ò⦈—o>Û™æôx–9º¹uyàq˃}ä-25-²Ç,9¹ƒó†çéè»oÁñ¼Ë½Â8o>¦öu­8DÞËÈ ×cc„•‹2•&!*˜Æ—>\á‡ecŽDi.Ž™]Y;ž¼9‡µ(‡²*†`tha®‹Ç@m튎ú†í!¦¼7W ǯìð7C°¬©í„=†ïK–l¹Ý·ß½Üšs‹{3Ûß<9é˜`vi¿Ÿž²¹‹ÐüZ¼ ¢‹ñ¶ôzÞ÷œ¾.F¦@©Êåèèêì}8DÍÒƒ§« HŸZ(ø½¡œÜ§órmÎ’oÿpÖÁ>ÜÌ{ïÓ³—C´/ã;0yæ³~ã[{¦&¿.x§ñÅG§—Ü{\J%¹=n?-˜Ù:<Œè<Õ°3õ(Tqw•Õý=¡·n\02Àã¼¥{•–>\ÚFSßçf¿²úÚçʳC%ó ÑîöðÀ3¡}½wµdöcAÿ”yts²Oƒë¯õª‹˜[jÎôvE¨ F[j¢ªiÒ>¬K¦(Ñ„vW¯‡Ùᇇošc튈=ím²ßÑgÑ5õ™ÃÕÀóÚý†!µµZÔÞ‹1+îüÆuÀ Ù×ÒCëÂ>iÝþo„z:[ÑÏœ»nEå%-¥´¬÷·- !»uÛ3 Öw0Ý Ó±,zîÚî½þ>/~˜ì.>™€îü_¾´œ‘ÉË,vð×ÄIÊ´mú©LX"]÷Çßv;£™@O ¶9T]G¨ܶ߳ÓWI6 :ìÒ³T’Ziv1·áŸéœuÖ×µþNŒe¬|>?Y‚Çęϓ]3n'Ü÷øÜxõsv”ûÌq“®.{ùÈ`lâtÌ—Ž'« †ï±኎&×ö +ë ¡‰žß|wí;º6s>ßOV=­¡“]¥®uXžxXíñÑÈäLË* ³ß;NAteÝ´çö›_ì³IkÀ{ˆïMÉ©»ø^ýyWËݼÌwÜ=©½S¯Ásoä¹×O•Ь?Ú†fbsëæï¾OÔ–`ç§åÇýTÛ•±-2æ2•¥É[yº®-jV;P|˜çÍØÕCœ¾è%üÃ3 '=¿¨£öÙ +´?Ne9Qa„HTʈ¨ETÚ¼ØAˆ7žJxüÍðòZÜ>§Šs’*¬¢R(§©çèæê9Iäóíè>˜ÓYc×C½Ïê| ù€y #Ï¥_Zexmpº¢ñ²äœ)63ÁœyØF9£Ø1~ÀuÛw{wÏÅ_¨ØwÑO»I VÛÕ‡w×àoÀwaá`H ÙièVú9ìñü˜|ùS°¦$#e²}acö¼OŽlGq‰éd›ÃPj©,~„2}Ω,s¼ÇA°óœ ÆÀ>s öÌÈï44k}ˆÏ­dœêhî«dS™X¿ 0ïÑ6àp«íÙšWÕ¾º+Dc/°ÛRçú>ÁôoxÒ‰áýƧæ°õôjßÙX´[–(Èïôkœmmï¤ß[½_ßžkK9¿IÄ”ÜòÜåöåÅc µÝÒ–ØË$P—€Ö‹_{µSáÄì¡Á*×$c›Ä»´dù\å¶‘9Hæ7¶šú¼gæ8áùdÓwÞzÅ·œŠ_+TT¿ö{¼”ßRÑ¿G4Øzy¾üY­É>-Ê6ïÔ¤ÜR,ï[I+DTk»tÚ3ãQŽ[ð)9c*Ï´R7'²fô|-æ#ûWÀàNþ~ÊÒNíƒÍlv†<¸×Âï\Úæùì¹yØó}>Ï«ÓKä¿Ùõâ®X6^AÔ@ù§wL›‡ežø"‡z„ämsBÖ@9åÛɨÂ%k^+úõÒ7±cÀãO)5A¼´Íß¹zLµFѪŒÏ%¦ßg"Q±DD‹´Óé·ÈðÅ¾Âøcâ’i Ô•:I»mPLQœJj)8 4 2…ùîáâØj `aX¤sWb4¾¢ÈW¦ö'T‡22ª™*bR Z¶¹¸HÎ(ÞžF©DJiÌM6g(Å©"E~÷k[+<[á£Õgö7s—i÷#’ô!Ó1˶û(/\¹9õô¶¹ãíëæ½£x[mß;/‘÷=‡‰¬‘ÊN¯ÜUœÅDcο,£œÆß‡ÖƒPä%‡:£!fÚ»\y»Œ–‚°Õ"z²õ鱬=Øö,n#–kYd¨Ï3ŒÚ(’1(JkTÅFîm­ÿvDf¬š±ƒ2½1$ÂÌ·§a"ȦGR…èÜ‘_uK[¸ÿ%õ|üŒZ×p¼{·Å?—Ö;GÅò`{Zˆû†iFØó±¸ÌÃu£J]{cs粬JêwŸWI‚޽bt9ýÇÝPÓÝx)Ô ë˜ Þgt¾bgE¹öñÛÙ¦¡21¿!½ç*ó£Ç<.M!ÏAgžñ©5—V‘reäÒoÌæ •¬í•ó»MôÒŽãÔÝùíã‚ë¿æ?Ÿjö¶.VÒ¼Ò¬ùk¿çóô¹sïøEùûvpæ­4ìÉ:‹¾¥ÅFº´“hsxµ÷÷´³j4΄f»7•îC¶j&8ÏÌŒ›Z4¤3:Sö;ØøÕÏαòÐ 3Ù!!Fíõ»zÍVZ`¨ÁQùš.C7ƒoþ¯¼)IÎB± ôÀÄ¡dèÜÀª2·›rÕ ƒAh—©¨ Z¢ðcô^¯óЗb„µù‡—_—fÞûb~S¸6‰qw÷»!|BòoIæ ùÄ˜Óæ¦tyI÷‰®þs]òÞÉhÛ¡K«–ÇV ¦Cà_Gå}w>;óÛã·@>>U˧CF›" ‹6ã˜û6å¯ó½+«˜úçBךüu«[މ,? ãCê÷âØL³Œ.îV~½¯î“ÍuÏÕ±ºL×âóö=ÞV“ÜÚ#AÛW°ƒê4ONÍ»¤ï# InØuuö^Mή—Ÿ®ÌU ºH÷I¨póû>ró}ÇœÑøïñóÛ™ÚxœÓ®Z¶•Þ̘X! ²€ù Ë}§vߺ8¹²lŸ\ù<Îé¿:úa³O+—Ê#;“éûN% }Ÿ°™îð^ëQçåÑ1ì^½Š.|I‡Æå–Ò<;”:kâïú¼øàyôå~KÕÃyãâ—â)Çf¿j“¦5“1ÉwËBoGÏ:+m½FÁØp½ï…è:6µ^ô³ZY7<É]5’sn“)Þ=¹üñ]§ÀxᆩœÇ’ýöˆš oÙîOÝÜøÃç)Óùˆ'¼øùy­ìÏòÖÈímºìrܲ׳i†Ç#F÷¹_Íf4º:ì›]¯ã'=[C¯îã;´1ÔùÎÚ› sXzŽQÓ»Iø8÷áf¼ñµNp?sXÞ:œG.þû÷¶º‡ˆ‘ñ;rsóõðÛ|²fÝøÜå-GŽÎP žHnÞ|iEvùüÞ¾|¬Ëx1Ö´ŽÅ¹/æÊ^;ö} ‚Ì+ù>ÍõîþmQÉóxô~G±úã}xSç)€î]ûpi¢ó¦å=®‰=Þ<ÿ?ÑB¿—jÓQ¸êW"zwx,'ìùÝÛÈê_häwäÒNñ:„nˆWr¶[÷œŽÍå;¶µ|ãfÎÖ,8í«Y¤tD{·™ø‹3ÇÈcc$w‘¼q?’°o¤Ê‡‰2v:W>Ý!\g½õÙý)Ž_\qï¼í¦ãË!†¶Ö€[;3ÞÐæôgË×LR%sÛÔ¡–§ˆi¬žÎÛ{þšïXÞ#+¿_3n»¤ùRÚ{=È!m®Ý9Â"’áLîZi™ùük'§oŽõ´Õ¾¾‚èŒaýnÌŸÌívÝ£^ü¾é&ñ lßêû‡3 GŠCnLJ›ã-¥žR>ìô©Z.©{ñ èÇ«Öybûo§eôd©|ç㞺C­ŽŽ´q.ÒG”ÓÙ šØNêîÞtÇ>³3aóçû¿‚ZîeÍ8vaNœr]WKÁÎN환 lw_Huµ­—Í¢(MÔ›† =–Ž\ÙæëËÌzç§µþéÐÑ”ZˆPëŒS‡¦/5 CŒdç1ư3æ•0ň¨+%ª‰4bS‰.Ä¢*`˜¢Ÿ°”`5.¤ëä¶ãQPCœ™™é {⯷»Œ|ŒîŒ|Ç(b_g}—ÁëéðÓ6y%¿½Ð°Xo¸ øé¡í ìöm°Š ò\ŽrÛêç­0z@J:ˆïõNö<é°"5s–4oyàÆ­;¹ž{ü—­±Ú7N›éZ÷he|oèµco»óçz»Á‹êéù¿×‹ž¿‰úª¶ƒÅv6¬y #³|Uû/"m>mÔÎAÂÅñ.ç³”QÚÅGBb9‡ñ3›x¶_èÁEì{yÀŽð>žÌŒÓtN&È8šŒXæq ƒ‚ rc±D6ŒŠq‘#ÛdTNÙˆR±dZ´âƒû‰×¯ZÃOޝ„M»`ŒŠÐAh‚ǵݬ?K³{gh¶Ý€š±ÖÍj„vYb""Í3Þ3_ºNôí´9nè©îé¢CH;çŽß‡·ÓGØóÖ¹ó~_‹vë¾å­máìÅðçL¼œ´T´Y;æ4íäý™ŒÝB^ô‘¾z7*~Éùµ g3kæG µ|AÂ,¢ñª«¿\NÑFÖû˜FqûþãÏE/?>8Ðt¬Š9ŠºÄ!LI+;»IGUh.4 «(…?"1…Hq£3&ã6¬}þ.e÷#MŠ{[ÌöëçÓ¬&ºîß`ö¦±ªÇÊM(ÖÛ_ Ó¿æ<ŽäP=÷áðøH‡À’²7”;Mþ§‡Ðö¸Û¦o.æøç9|¾À£ºšƒÎ.Ms½7Dy¸<zð«ÈßCÛv>½1oª‚ë2Gœ;6ì·‡}.["е7'ùDR˜µi¢lƒÎÊ7Ö‘nƒ%ÍI”¢²´¬Ÿ8W4dÜ‘_s [LebRiDY%Z*rѩƨ(Kœ•Ä» ×çiOÏXôÕ×ß9<¹m¾úv|¶5ñ‹“]ÚÉÎÇ=Åè¿z6}zož~öž´Ûu<»ù¶ÿ‡Ï‰×]Ç!uô[­JÇ܆b©>ÓôDÛ±;(p¸‚LñG‹Gju+U¤z âÃð£ 8M ©VG 1JJ…¶Ñæê Ð20ª¤x¯ÆF>zè` *1F;½û³×oV_»¦ø:c«×}ît]êËÏÄ1ݹòu7º„™¾•á0D’Füh‘i­ë@Å Žåè: Ìù §m›ž(E´žÔ‹Ã/"Ú‰²*Bp ìií`•TÌ-JO†ŠeO5ØB%Heù­ך+=‘â}8ôêÖÁ ¸'juø»VèÕ­ÐÞ2ÿX&;v/¦9úù–VûKsÒü£—™{Sf5ÛjcÄïMî¢=ÎÖ“‹«x¦ÓŒžôæu˜½;^ y·›Çî²ñNžŽøÄ5{ìÌ>èF¬‘ôyðr=ÇjÑ•oÏ$w\/Ö[æýoÖ»¼ºÙû_ë_RœñâzK=†cÏpOnð]ª^0œL&>‚‰^µ6§Ë± ÃpZ—‘IŽ'9@UËM-%­¼Œ ¬»‚QÐì-騿º9ß«¶»=z£¢[=O˜Û埇{ôî(ñÐ×G–æ_ ÷t·ÉîÃÀu?$1ˆX‰rª¦! ªcÛ·´Tk?aB£o[ÓÝä˾c¼Ä½Î^J5±é±`Ôèt ©T^‹òÅ—BÍU,ŒJR ¤»Ñ;'Ží¡w¨válvtìÛ·— ;žOš{Ž6¼ äHxT¡ñ[¡CB®­‰ÈÕ#(óf !ù§’áùq‚a…võúDêéÜxº; N[Þ†¡à[a=Æ>ÙÙ4ŽYÏ»ÞxyŽÏ?•Rô\BÞœíPæuNÏ­ÄšÎtÇŸo‡ÓÈçéÓypwy©(;»¼ça Žä;={.—ÖÁÓÆ´½ ¬‡?%o8æÇ¯ªß%ng´=ÍLó+íÏ.Îéïrù»qÃÃûFo¥^Í ÷õéoAî^˜‰=ņàõúªů—Ó×_?±?¦cÑ“Îeúlá±ëálzâ tQùÑjë“I³Ä¥g7P1$­ Zˆâ7*16É’ÜÔԣёeè“ÊËhS|ã±Ï".Sx×»ÆK­H’ˆÌ |ê·)UNd‰RDêBMjU xâ^mJ€äµ?2‘$·-ËqZ&A'4± ™ªƒïD¡LE}ß-¨WË”%E"ñstnS¯Í‹ãâv#‹Îjà(ÖjóWue‰í¿¢:cKÂGÏÊ  §~ÌÏ=9€û[.Å6†óë¸YÒªM·.:Ÿ"†î—lÝÇÐr3;i{6¢[«.õŠçMG?í¥üÉŽËð°íì²çk¹ïÞ }%ËEÙÁÐ:Uëæ=ì-ü˼ìûnðÕWÖ¾2TW‰££Wc‘ÑOÌG¦úQn´œª¿aÖêÌ/+ÐI©«>”Ô¬zk]ª±q;•V*|ÅÙÙ†a¢T;©¨‰uI)}œGbùb×¾Ú6#ÏWÕMåqÊšVb ÓHµSÜ´Jƒ£Û-¶G^«¸°m—­Måqê×juÌ{‹Ã”¼˜ýÊ0åÚ8X f}­™Ú›œ,‘qœH9X¥0 oh›ÚFQTï¦Ó²ªYwݧ¾‡Jû*wì·)¹g›H‡†N”3²4‚ $…Íöx«YΩ¤Ë’±öñµ0çgxÅZ%-TZ¡ä:DD7Ñ÷qT’Tpñ×köùÞz¾8Ì7sû)ì_e÷4ÏØní\5§¶5‚;9p½o·mᙘnš}©µôÑ¥q}n4ÚÍ_}1ë§ ¿ÕÏ»£ãÛ6S«§¹3dRÊL!Å·-ÒE°É9:ñ€¤*×"Ê#”i6|xÈÓTÖ¤TÛ6K§WnÞçr89|ÏNß,4cÆ ¾(„vy@AÛ§MŽ5ùd}?§?§ðzÝcm÷;—Šñð:ÒݸO ™}¯V^:¥èÐÓÝYÚ/¯™ƒA "4zÙ¶ö9²ë8cjÛN.aMa×FîÚ˘T}œ§«ÏÑÊhO+.ÇDâ‹w‡à±;׺_ŸÛU[‹{o°èóóö ÓD]ê ÿ!OiÙ}+61õœpiÙÿ®3ªlž^+ …óù¹ÓWç xtžšõÚ‹›¹îÛ'%²I–Ç©¯n|ÌvŠx ÕùÄQíésQ7TØpúzbmÞÝúÏaŸ‡JÉñü:~s÷{§!»úœ.ªÛ<žâ².É<ù7‚Éå?âû_yù{É ¡ü½Âêy Á Êí=¡ßôú›vKú_†PÆ¢\”vG>ì!üu÷}{7Mx®ËmL]öÆèö©áüÿcólxk}¾.lZ¼ô_Žvu‡ä{O34ç¹Ø:jâÆž1Gy5•m–íj¥ÉW­sµ›úùe—^7¸S¯É¹vwZMf ã~]f¹•Ï»_·çLp‚£³`~ÓÀl Î+Àéh󭨍€ K1)$ÚNx: Ó}D££ äuiH™[ÉG«,àmïpééëÁÝf´§ÌG‚ßQwGXôNþÑø’_D.Ý7f³V£×ñvé}E󻤃ÚÈúäÞê'ØsäÕ=§´n¶m³ë‡ %å¾á%Ï yׯ¦Êûgˤ7ûÎo•BôóäÍÚ|>×kÕGroBR-Tóí:6ß}9“ø„á„FÖð¶ïñ“âG£»Ú`u}ò¹×’ï£óŸ äfa§¿{çÒÞ;–õ¿‡5ƒ×èïk´úuõý|è*×Y®Õ¸;$Ó±UD<¹Cù{[Ì…_—¨ètK1ÔDï%¡ÆÿÂö;z±/ ör×íKçÎíè]BÚýŸ |kMÅ+ÕÀÌÃir—±/Gs5£ˆVv¨S=üS×|ËÞÞek»ã·/ qšõ)ùãÆòUŸuxÒ 4ÄFš›1k­}ÍØ&óQ®+â³éâ> Ç2íD‰W£—I㘜TÃb4g{ô½Ž>´Î1cÕñüɬØ;´pè‡\#Z‹÷Q¾ŽsË•—Û<Ò´ÇlÛÃ}õÅr­±]ˆm¯Ÿ—¤æÑù+Pçv×Á6õÇå:oZ“~¯Œ?ƒâêpB…¦¯Ë/‡{óË«S¯qV•ÆC4󕢃—(œQ²ß‡KEÉufÛKB•ÙÜ %1rk)ž+z ZÙâÛyâÖj±Änµ‡³÷§¿½æ×ò€ôk¥É}£2çÃbb•}ö¯Ð.ûÝæ¯*Âã=!ÌfšægÂl¢Üí­íÆ O§h¶h²²Û—o¶{üùj¹ÃÇŠÌŠö˜&ÛN”ÜÔÞݶ®¾4ÐgQEÖ1ç¿}œÆ;áîâÅA+xñ9_]5\µêlhï<è7uH«ÞtâÎy¯›kÌžx¥×´m¼[–Ãé—hB¾:Åáê)ôó9Ï[à8¬Ö5“D×3xhãG6ÝöÓ"Æ4y¢Ÿ3ª¤÷¼Zîp¯áéñ¾2CI Nú7¿zÆ5iF®ÕƒÓ ²h-sX~=ºki®|Ÿš,¶é¾™\íDç·,Ã0×Væ¬éS´d‰=êmÓË}W*m~yóSomöÄQ°u•Ëwð~ÞÚ·¹áaÚã3 Ú^N°øµ•²¢ ˆ§Nh̽¢3—”½SïwsV¶–é¿·²¾=ž•Ó`9ÛØ/¤ñ2'ˆ%æVº½b­?rïkbýGò§°^*q¬5|Ÿ€Ça®oózb7UÁ“Þ÷ù¥úÚöÂAbÁ“M“×lhóè~êJeûø¹‚¼ã#´ëŒšpa´øœEU¥CËÇÝ ûJ°ßn>myŒrí^ÚÞÏ)âyš?§w,ê騹‡'×_fܪðñ¾¨#Zð&DÂ;A”›‹ØÆŠ÷n_M‹ûˆnóáø—/S¨ðË’¯©|Ìp“uƒn¬w¿KîcÙËßpñã×éäñ'œå&{k·[éÛ™uÙ$*s°`õÔ/Tsù; 2Úûoåé0[¿åï/?>F uåtÜ­½ëzú‰ n$y0)Œ8+ÁyMÑvÿ$?6c‘Í E])eèQú¹såfÍB"ÀB–eBŠ!Ì1jC2í”h·Å9:³&}IQnÁ»ƒf¹ Ä£š¨‚!Ñb¬•AŠdê¨Ç“^ Ú)§T` 1&ÂÆ¨Ö#¶à’´ñà)uÖ³leÍx]£SÂ!Šã' -Ç[ráG«gß¼£?'«Ùh–;äó×Å~l}&a˜gk#½@¨DzᩯB⧸ÛSCcbìèNˆêï F§Îóõ –G×?Þ_žu¤Ðî?aò×a(ïw;þw/Í[N¦«0ÙôKeêÚAó7'=)ÒZfli˸ôsøèë•ïŸÿC°\–æÒòôžïÃþgϳxã.ÈÙfÝȵì@ˆ§îvtd!»Íö§`|û@>Ð’tãâN=¦«ÀæØïT|ÆF%(¸¬°£l!(—]ãcÉèÁ,öŒ?ÍHc8·-1å©4èL=RŒ…(¹ãmæMWŠmf4¿Ðè0›MÈÛ¿Ñy¢Ý+ü^^œ÷MK‹ø?¿ápK¨ðÓEîýUUz}&5G€á POPoŸB-Çgôè$?ø5Køfcб·ì ¨³_ü¬M_mb©ã¦nŸÖ>iÛ¡ßÇ€$7wÄ¥f£”LOÜ„€ €Ï*b¶:ÀÚŒÂÐåõcͱØ•×};<€’eñÿµKç ¾]ÈÕõq)—9„+¯JìQ蕆ùÉOW®öäEÌÂ’˜;vDg±õ¢¦“xͲOD q*ÌÆ»!N~ÜßëW Ri>ÓÓGsÎê‘zm-q7çP¸xÍßàà"hUåŸd-ÚúÞ@ °¨Ê‰ÊÕ]ÔQ b=¯½ŠŠ¡Pþœn©Çêt¿ÛÏÎûyÏyÏíŸ-”î®þ.—³æG^ó&ãÚ!F¼x€ r"  |­'h±‰Å” ,Á©SðZ˜ÂR+ªFNÙ|=wÎ6‰£ðh‡É T-Úÿ²Ã³ÀÕûú5C§I/·š…šèíþLãï«ýv± éh„&Z¸ïzSFuÏùªjÍYû#±ñ¥±Ù´dâ~ÂŒâ¨þ$ù»ôס¯eŒæãnj­˜Tß bÂLjá ª²ú}-1'χŒ÷Hj·úÿ.éogêúð¸m®9]8ÃrvÎPß…pÂÖ1Æu¢Ž¤Qô'Wn?ƒ¯+¿NNï³ð?I~[-»ïíŽÙ×limÅ3/YŸüñi³=ßùòå1ß­TtÓ\¦$„! kžõÓ®'{Vwó,Xw¡¶9ABfËçf…vœØa¼!Ó¤•æÐ±Côߊ™Ç²±-b:ÒÐÐ WïJhιíSVjϲÞÎ-ŽÍ †K©Úæ7±{43‡Ñùmv½/ÕßjuÉLÂLÑÂUeôÍý’z%Áç=Ò­ü}ÒÞÏO^r½ºK¹7NÙ'(pưÂÖ1ÆuŠŽ¡Qæ9x¼ZúLwqÞ¥öŽé/Ë…ßÅýÛ:ï-³¸¦g/iQì{ídzªØW´@€qP<ŒV !AŒXFdPD@õßaÝMÎ÷ðáShará~@’s !=/:ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªøA¡QÞ*>mi¨ôžÕ6Ë<†ʼ¢›Z ¦Sß›æ3-†Èíxª×rVslbös]–-‡„ï›VS˜TÔ»ŒeTY=u†Lƒ˜ør͇ß(5@׃å‡Ä®HwAчrø|@ôÃj6 ûa¤L>àsAöèì6pÖCdôPwÓÈXzê‡ZxufÚpá‡Ê;ôÓ@<ÐÝöõ~âÿÇJ'óŠ€lzŒ0=Zǽ\nÏÓõýŒöüÖF`ÏïÿÛ˜¾òø¿÷FThFH¾¬,h³:XˆRIBˆc°¨çEGÞ\œ'“Úÿ›@¢¢cq4Nû  ¢‡ýÅè m1 <ýɃA¤SŽä9AG™Žhuªo)ãwýï*:ø¨ðÜH¨îB£GBŽÈŽàŠ9AQÑ*Ž}Ü÷ öªá£áuÍqvçþ‡[ WlƒRʪçs‹ŠnA"Ú†O/ Ô:¦Ð:ôE:f톡‹\V›iIÕªüt·÷Ù\:£ËyÇ×´FÄ—>2f¸ÏwUx‹ e8xêŽÎ.¼;<£s¬írw­®EmQ>]ö+üª5å©"$ónùž¾ u¶Üëó |'ƒŸ†o¡È8ÓNXòôñßæãÑꙫÝtMã "ÑV•ŒFeó’‹5c37WªSU˜©ŒÌf*زŒ,«ÔeTͬ÷í›9…´Jé8,hCèø|¥_²¢]¹}s.ª": oÑg›4&2Š: F P€D ˆŒHH B "¢¬ˆ**9%xìŠ#"(î(äs$9Xè‚ÁÎ\s¸±D—$qËwh\s’I’K—2X±$™09’ÆDdrå‹…‹A‚æˆ(¹‚‰.@Œ™.PŠqX±$ dÁƒ&L`µÌ„  È㈰ásŽ6r‚á†Fsq€ ”Ðd±’!†H2X±—$Ë#% ¹&$Á5É$#ˈqÇ2\É"0d’`ƒK’"LŽH‹0`,bÔ@Œ”9$A’H ‚ † dÁY²d°I–ræ!˜@ÀÈÖ bŠ<QÀ±A°Á±°lX±¡˜x(À\Ø Ž6Áa®#&„Ž42PP\g „(k˜A8á!ƒ…„Hàâ É αw(£ŽœvVz¶£'Q–kc 6r®öÔml\Ó_9|ç9Îslç1œç9Íg9É&sœ™'&L™Íg9ÌffdYE=êg9™¾+"¶"Š.d‚ Áš˜ÍËÍêá{ÄDg3/’ÙE¢¢"j£9¾+9ÅóŒaŒD_6º/ô¯›™/|d¾rùÎ]ß9Îfe¤“&LZŒÃc›> ¶o ï6µæjªGÎ ³Ð ˜!¯|=ózµÖ"PÁƒ †È^×/|;ÑŒ>ÌL>¹z¼©Ó™í¬Kê" VY{9„RµõšuX‡Àö´X¢¥ç3WÒ×üù¬FRÆ—|Äi5Zßõ )Y®Ds³T¶R)9¤ÓZ'TÖ*tX»˜¼&s¹ÛV¢ÍY“ÕÑÚJÓxß}m©Œ|E\U¬â1˜ÌVúµšší£^,Ö´]±œg ›ZÖL¢ÓŒÄÙÝUVj'²î„i—ÐfÀë ©s/5,ä¦5δØÁ¬ÌÖs«ÍñV»º|TÁ$VµkůF!퇽­˜Á…zÎ_»Ó“{Vr•ò¬ZöVÍê×™Å}F¿j†`ð∽´1 ¨úÿ’¨Øâ¨ì~—X‚»§àÞº¹ƒÑÛEGÄÏQóC£ë9½¾µTJLiêqT@]Ȉ¨À¾ùO)Ðl}ÝÄfºê½6ÇöþÍ´EÑc4‰|,Rªµ6~¦ŽUe¦$®¹J N{¹¥BÅ‚£a>67¹ï+0i» 7Ÿ¶”ß‚ 2„‡š€ó7R€-âþ<“í$‡O×Óqæšf*/äþþÀðÃ?¤ëZóõÚ±ï3ÛI¦äÛ×!“k›÷»Àa°²ã)A”¦÷4¨ÐטzpHz—Mf7OD;lÔ`UskD¸Ýý©÷&M'§s®ù#®±éG$îUNYó¦( z>7º~äŽKdèR©b¨à‚DÄa7@›€¢ÔбùËÑÃ@ÃEýÁßÊAAÑýØe׬‹qÝz,»–½;ß÷Ä©-.ÊQ¢þÌ €ùQSicøK‹ €vª¥ÿHbý;s¡ '­<@ á+­ádwOÉúA øÞ¸~™ò„žGå%”à+*|Rš—ä?–=0‡%‚ÿŸKJIì}ä 蓟®½ ’ G¼§=¾˜¨ÀvlÝÿÔ¨ï2ïëF¥Ky«.‘Hï°ãNsÈ<ÂȾÓÖ`È+¿|Å©ÒÝ£­OÇ…Ýõ€úPcvvš Šß}…1?»N4°`ÚFM:²fé£íãv9}‰kä/[9!á€ý,Ûaà_–‰À ¬"Þ"©ûeÏA1ãX *d&g8Ø(Â0¬úÅ“äZ®9†Í¦×Ù¯jÐq_áâA!¸Ú8ŽÁrúÕ¾QåvÑŒäñõ=ÍOröòÔ$Ž»ýoøÞ¿¸ñã¶ût|V‘(|xPˆl^„`D¤ˆŒi’\¼ÉÏeõÖ•–˜\$ÍÝ!_âȤÕ(ËÕ;Ȍŭø½î±ÜDÈ’' Mv”‘ë·OÓRNÃ@mI*Ų¯³ "g54Ý8½G^ .FE‘,ܪªI:Ïè|Ý~Í¿Çáï«!$UQUb QQUýGÁÿSîEîý×Úôþ¿ÇÃï+ïfy8”‡{(A:ÿOJŒ)d’rœ]UMaêz?Bb?\Åqþm >ö¶-·ã˜É&ÄKé°§&µu ‡+Ú;¬Ná;üpàéµ®s»È=¥Ô±ùð=ËbÖ$ ‹Î°mâNL|†â¿û¹ÖïNJV@}A1Ê=d[F1Þq'$‘üuï¶t±ùeù+4ËÞ ›ÑG˜ãüOsúW6ಬ¤»SËé±VŠ‹«Øÿ& ´~ˆ·ö¬î–¸²U $cñ^‘±!vËáÝ@«É VÐÈÇ¥•æ‘$O¯BÄšXOÅHðÈXÓj*£5žÅHò9”S®ÁÌEts§ÇùkûYiVø¸ñ.µ0¾_ÔW}&<¾õ v? E£ôfÓ´ÖŠXÖúHû¢¢¤çJqì@ráLC2«©¸ä•[Äö\_~8:ˆ\*SK©1ÖËæ&ÞÑa‹ ý•¨hcfKbRÈFÖƒ>jd‰RŸ×®e –øKü“îAZ–צ—Ã;Øk›CrNÜ)C7Á¦”P꜅[.yR“c,lQ*•æ/˜/ÚcŒMýraìÈùÊ,éÜK2þ¿ ‘¦ÄÅY@HþÅ[ÞV¦C:“êHë­- `}†:V–kMÅüîÜ+;±lÑsz)š.¼°\'ùè8_s´ÒxNú}r¶ÀÈyYF–н2`Ηž§{ m—5cÏèºE³zg4tæÁP‡ åSêÏÇŒPk³+Rù6e#ë~nþЊ;¨¨ÁbQKJ)§ÒëÀrÉüzJi‡1uíê1;VX‡¶‚Å%\vìééfÝ…<|¦ü|)Á×½^ção±&Cå£5‰öËâPu¡ »åø.¬¨ðÏ'Ð:·Œ‹¢9ÏT*º`-£ÒÁUãéÚvt†ùâLnŠüãðsS†‰~Ù†Ï7—í#Kp¨{lsë¼”ÕÏÙ-*dÕ )OP[ð¯P/Ç$êuv²oèáB2¡§^q·ZCÔž>$r¸r¡Y@8DP´`e@Ün©É±îï¤ÐÌmè?ˆÑU“¢Æ]Snº€ÏDGèXf³ÚÞâã—á¯5›Ë 'n#‰FÑtü—õVs*[¨«#Ûרß$â8&±šÑâ1tóóÇræ@Ä `§ânÖoXI­G‹Ï&Ú×Îd öÆ Wä$33ñÓöÊŒÆ%0ýrŒÂš` ®`<]:ßY7êëÂÔürXÞQ/§× ÛVXÉ÷óºfÔVÐÍQÈñô{Íg¼ 4í‚:!šÅã ôrK%P;W>&Ks(á…1ɹ#®ábËÑ{ ùÚ8iÛbÒ‰X~üpÈ›¼¨ØŸk[äõ:u°N9Jˆp$R©ˆÌlJt¦K&Òm]}ïÐ ‡kÍSÝ`¡¨òŽB¢Áá7Îd:«Ö6‰Ÿ#SMS=+ãóùÏr#`ý—­ÖåbKZøIÜÎÔÁ·ÓÞþD4Â$‡œTòh‹p5Ëmcg˜ !LOñzi»?ŠÇáqÞá©"ÒKžãoÛȱ„±ïzÎ! ´?ŸÎëþWâŸfjr;;0I8ÍµÛ ,ƒ;¤(¼Ñ@´ðË2&H9CU %¢!Wy«ûq-t #*š8‡ÞçïÀ:øþ§Ÿ·öšÐç9ÍÁmHvC-Ƽ±!6,u‚i;!¹CÖM®'-Hq²Ð8ÍUD©=ãÛ6³÷\Ú?Ÿû8-E(¿ðü£=vVTA@½•ùf÷Ý?]5™tW›.§_÷Qé¬8€È4ÎÆZÓ²ÁÂønô-QrâÊSsm¢Y‡ì´µãýÙÑQÓ¯Ð=˜ˆÊS&)UHŽ®ˆØà‰Ç˜S!„ôW¸JLˆä¦Ð]í. îÆH2åׂi lÕˆšHË\c)5†! ôØÜÕ˜¿-ë‚vÕ°‡6ó_?´ú?ûqGÐÉËEŸE÷8£læ"Ý]¼š°›¢W”O0cÔ©Þ',,G¶2†ù‰Kâ¹[7¡ì>'f3 %†Å{_K£SÞYʸ£ž‚a1|&Eä{^O”¨‚vñ¹ž½Š|d>ß­~™¿¬3jøh*û`êÌ2͵ºtŠÚCÞ%˜ 0|®gC(4>º ƒ§Aº|Æàóõ%L¼÷Á¼™ÝÝäìŠõ=“gTÆ‘ö_gC“A1᳊:ÙjÒùAæR-ùßÁ¥&µmÕïÌ,±ÇmÀ†øƒ°ÓZ1b€‚8ÂæÑEÁE Â(¦f'™× &ã íömE{›¬ìÂjS>¯/Yâ»QýjÀ£¶'¸ýŸùÝÞ!“PHBL\üÞv+) ¾ú£(ìBD[(بdÛ®P¨ö÷~² ` \éÓK*S/Eé{\÷¡ìá<_ßèºQó¿ÓÖï“d|¯߃ÓϵŽÖ×áõWæp?–V{p˜aÐÌÌ·"±_äá»!šü oM©ªBnØý44ä¿°'þOþ'ô×'[ýÍü¾¾ÏuèÆãðº[yÁ"¡ÞTذ0¾±#ûüù^}†ùøgñ¤}uwñuÏ«ÿÊ‚;ÌñÒ&Ä´„ž¸mäµåÅ^Ã"‡mBpM—­0C2¾Adm¦dZäåêýco¤'ŸSÓWìOÔB*ÀM~„>²¹¤š rrQº¢„(ªËóQÎw¨62“q@ €X(1R¢B<‹xa1F͆9 ZÇGÚäú³‰¯Žðz Ë­kói"BNjÔr±V™ y>†1½ÓPÜy‘È‘0j8 *VÑIypÇèÐoÚì3Âëýñ8Q‘Îå¤yùþÀ–&\qç’‘nÂzšº… ¡ÊS#ºØƒ_oúQºÓË^?¯ûŸ]ïowŸ8ûûQÉêçÿØÜõ…~çœæ1Ù.ŸÕÂÿ tâ·¥i×ßï­ÃØ82˜«U«bÐ.½@¬ 4L 0†,† â@”¸¶õa‚(™p'ÁÉjÇ_*þÁ+è`ï8ƒæžÃÄ¿ÐúºF `Á‚±‹Nžo»=ÃÜ;–ÃÈc€‘2Ó<ý–äÎÝJ5ÒÝ­ ‹ÆÌF ¦ðQÊ]µ\˜ƒJëŠà ø¶¢²t~–gEå§Dð‰F†NHUm\•Hr®RÅEŸ¥o.Jx` Â?@k>ŽîZ¼ÓÍâí©RÙcžHݸu,%ž^œ~ÄpNÊ­ÅѶ¯-6Œ}#Žåç³M<ÑUŠÛ¿°XY`WXƬmiÕ»U„À½Ìpãq—¯y ©B‚6Ra”ôŒêikÅ|Ý |ío-ÆÓoüª,AÐÑþÑ’,æ:¯<t×Ý~¹O‡CšYi(Š0E¦7êáEûC)·È\b8ÛèÃ/³Ÿf\ÚëimJßì¡L)KªX`ƒeN ÐÇ>Ú~Û‹¦ˆg‡.ñ9½½”é—üÎóîµý_'G]…„{é÷\mE^)¤š¼…í­†—N› [l«õ\ºµÜÞÕ;ŠUd!Ù*Â*`‹bƒQ„JMsÏãijRAž®€êW1£3#31XåŒé±·1‘Ô¢‹o±–æTETˆ³pVÒq "™˜d•ŤM`¸êCAÿ›¤%|/èŽ:N’:éä"=|—{Üès¹|ëÎ|4ïßÐwAÜíÑ‹ôýÞAÉÚP¡A’”°¥D”ˆ%/«ËÒÃGÁða‡!2À*šáô]j:âƒn"Ê£KnœÏ'×rã’Ò”kP5ÐnÊ5qP®]•Tê nñåV6 #Ry³\{+ãÓÃUí6£šÖ¹q–ý®Jƒö ÌÌ6+ý3#õö¦åPÝ*”‚iò’®êœÊ$·jrÞÞ²µl‰Tw\ïFôæêZXØAho£ÀÉÎZÆ}AÁ(ΩNv–²¥æ‹Ó_*†§NüªÈŽ©õ? 6=•ACK)\IJXnkìáÖMA„}*Sqwh©G%1RA•qº ”ügà¶›~eX9_;!k Cø%:%c(KR``ZëX/hÊ©ZЕV6QX+&¡ZÈÖV" ¶\€¡Ù!¨²‚U®¶®,ˆù\ è“屩L”ÀJšì{‘JVfÞ£Ú?6ÁÚÊÐð‘Ù¨líeCqei%˜Zûöì‰:ÂBÎÚ—å|e9’bÌŠËuÍ}“îFDä:'J~\eJ|ã™›fNøjiL¥¬G½¢"ÍbJÄ{ ›ý ¨õ– =]Îá×Ú¢¼äöYßÐ_Œ¦HL‘V)ä«*«ŽíÈŽd@b€4eO.Ø,At#ÂM]Š›v€¨d»À#@k±¾JÆ}+Ø6ÄWµŸÇñÚžE½EjzÕÅñRö{-¿\?Æ€§ßcÓ—©Ÿ[5Žg¶l>ǰšzk&âmmûvÎo—0=ï (TßÂD œ¨ ?a~ÝSF‘)Dæ¬Å4?©ÂýÓXš Ê"J…©[Yx—5šë›û¾as‘ÄUA„ J,j£vº5ËpªÝ ÈoùSõyžû†÷Y¾Ãà$þp-¥ýíÿ¢ŸŸ¨XÐܼû&p¡„ˆ…ÿ®n¸Xè´V1»úQ|’ ÍÚ—ˆW—æØ^åÀføÒ©jA˺bðÉÏ$R÷°»ˆ©÷ç~+f¥óV "=ϧ).‚îŸçº_g»ùI^ÎèåòÜÑ?Õ^+Œº^;M<ƒ:Îõþ¡[ׄDx¶1žOˆÌ©ÕùVhK÷éQªî_ Wäw»~¼ö$£™«!°:¢Vµ°äñQ–G9Ñ>¥u­³à̱ÇΚ̶!\àËš¨læîö׵ߔó6@—±»ÜãvD9Úù{¯§{îês@o8‡ºë­ßyÅ–w?fÞ `Ï3Â%ZƒDbÚU²¬…*P5³‰«ýf Ñvû£êÚ칎3çç¦ö@8OÍ8~G¿þ.³~©Üdª˜¾%p0й¢0‹3f€Á„ÓsMáÌÈ6âCËã6Žw{®ë(ñy`Œ–·>@ÉÍÍm¾Ïlyðø˜Ãck'MFC4&YM1í?Àùô¡Ème¹Ð×ïI4ŒÌHJ•ÆU% ¦˜âê–Úœqfë*Âè<Ô&ÏèO*»ßš›£,ß©ÑÁ0 9ÌL¬8û›’X¡×0µ5FrŽC@ë™D2’$¾™šk[a! Ä ¢ LÌÁ™B‰ºhì ™µá6`–¥FéºMj”9˜&˜b@"K!”Ò÷™xqÐÖeþ½Œd–B¼³—’Â"÷µ¹Ú¨°°’ ˜t™£Á´ÉCAsî“Gc¯8šÑ¢|`J |·Òªþ‚XÎ>¤¼¢4³œ*Ñý—"RøÞ†½ÄQoßmß§óÒ:mŸYôðã›Ëfº¨iöˆ„9ò+Ùˆ¦ˆc¢×ÿÜУ•óPB·Mv3_ñm!áãÇæä^~*åŠZ:ÉéŽÂzE—”v[' 3TxŽN­Ím¢®ˆÌ¿ˆ“˜±Üùú]©|¾»€ÊT¸ëð>0+¢Ç…Ï›¦ø>=êdß´«Á¬$+"×-Hˆ > mõ_¬M"ò0Îl5Ùà!Mj®P‚šBæ¹TRùEúߟ¥áÁ}|þ>iYëæ~]?›xÛo°rN7‚FBnV‡G,Àoc!ÀqôHÓ>ѽ²1Îß„6eŒˆCL‡lÄ Ž¸ìòìÐk—G\èíÿ [X"€iä$ ê2ðͦɿÝX~*ËÁ¾§@h{ “åŸÓ¶ç,i ÇÃõ–W\r©MÓt'A ãÿÊ=±ba)KgÄ9ãdŽv×7–‘AviA¸x@ç c€äpu3w„0²>‡Ýˆ0 ’}=ÓŽP|42?} 9?ËÀ¦&Î'wÐo¡®¶ªÿ–Èb)–,¼=ªJÞÐú-NúòÚ#Î+1OËØÄñ²qÑË¢X‡†„Ì„~&åãñ/Å—×1 të?ž±©ù럢ޮd†­™!ÐЄ´ÑÍSJKé Æ09;&6ûqóÈöYÙ¢s>úEl\¸Nß7pïvKݳHÏpMLm½ê U@óÃê)OUÎØî«gÎ-\û$ÇëšSÚ˜žb,aZ ¾8°ƒê)7éü„®Ê&I䵟ù=Xl¯k*²ö£g†ßA0g˜Û1ñÅú¯{¹aÏ#CNê³xïý ;Y†a­ðsá¨ÄØC# ŸI;ç_]h£5øú"€ÜPñÓÐ’0¬¬äšš·èCaì²v9¢<ÒéOuF+.(ÎSM8ñ<µðöqk&Æ‚ °P #Γ$:ç Èâº?ìGc¾±_9N*¨ìvÒ` Á+°ŸjL3ÐBÈ M;X”k¤Ç•ÂB¨,««é¸@Î"M„¦… 3—\Û“9޼¶‹ f‘ðýœðÛâ#%d·6¬Çvn\¸Z0†€ŽÊK¡> rãáo x>nžHÄB0¦˜rÆbC·KU)Ë\Ç•|…Øj©N…Øô¢œ” ÈŠé”R/Åòh@³Id`óÔIbQ 1",l P ¶E—>d¨‚$2 (…Ãjæ¶›#L–ó¹$Z›µ –ÉÍÉ|.<˜ñ_†½¡C= e ÷#»¤G… ¡@‚H qN4ak“–>Û“kÛ31ÅxçjìãÚÌúßþ-u_>™df %Žxóñ ¾xñúv=^v_ÁË<%Ò wm[ÞÓ]qÎÏ9>Ž&d2©ú’[`åDuÊ-^,Â…sŽAÙ E`*–º»êÕ>}ë×rdÌKcWÃR§F–¨’NŽuds”ÐŽP}ýå‡öÄ€*‰È–?kù5ëõÉó 9M#»5øºl%à20›d£ ù?ÞŸ+þ.s¾ãõ¨úhz«3ëzOèkÌÎ~÷zg½Ù3`êƒVjèb!3ü@ß ¿AúÝÂÞ`çÄDÿOæÓoÛ%4ˆC_§žüÛÏC¤}U·Îy@û§KŽËÉáuD²s¦8a]°+³W“*iS]nÙ¡s–Dˉp°¸Úš¸4ýÊþ!ÔàîI G]AÃ>ZšN’*Ò _ãðü³¤YÙß«Í &÷Çóüö3ƒš¢t¶za‚ 9iJ#<î3ccŠeg\.5+=In÷-hì¡þ_Íé|¤ß7°Þ8)œ‰å|d:ì~!S²LìãŒèIñá ÈÎ…y÷¹Õ°iávŒ[„X—ßðÈrÖÒî›Bî“4Ùâàî8»ÌEöÊ~gìõ“«9"ƒ×^Lì7Ôw*,f¾Óéq†×‡;O¿óû½¼¹òçGNZ£#–˜[‡é.´{2˜‚ÄcÈsÏáÆÞ!HñÇ–gÌ)«{ôT»X7þLvn­Q–MRñðÌUœrÖ³»†Ã‘HÌÊþ.%Õ‚ŸX&×_ÝxC%mþÜ€¯* htÞzý‡‰+"IXÕ)ƲºÙѼõŒÏØóffFmÜÎÚÀ /ãÒ*ÌTV GóàgólÅM97ëî°] !‰ƒ­®ó1õî|`°Ñp‘¨»hÇ’Ì R¤¤8Ù«2l3!Ý =4]ªBA×Q@Ùdà £^üž-8Æ ¸§ZÈòÑ¥O 40Ñ^ÿ{ѦÊ6ÑéÕ% MˆbÆŠÕc 1©e%É66ÏØ˜Ë˜',QOŸ„·M¨ç"@pW”ødH‘!–†X™/ÙVâ4QkE]Vîu9£ßH³ “‚Qƒ´:ÙjX:¼ ˆYÍšE«—Yë¹ØÀ)œ·æ!®U_Ô“HÈ ¬DÈ.'‡Õ)•FõCüÊeŒˆoŠ`ŽLÀ²‹rñ8×z¿¿ß}̘ÇR™Øôj+!÷v z^3Ö]¯.ŠBÒ#`Æ–ÆÀ$“µÒQе’,ŒÐÌW«5Òp9vÛþ>ÏÏ£æî»ÞM˜jû”ï~æ7uªÄ`nþZŒ(÷'M\¼+î>X;bš©¦ÝÛ÷Q–-ùúzš>èÁ a3]Ìdöl÷­/pïGÑÀÍÃ3´½å¡4ƒ+WÈ|k£/,ßÁø u@@ 8P‰,*TÂ,0z±üïfy ËxÖ÷=?-ý·M½Û±_ÿ¼¬]¬äÀά"’ # ²/[B!˜ú§ä€,À#`Œ„”2+¶•ÒH%´#wÛ uþÏ9tµ«Ò„o˱šŒïOò½à‡Èbê$Ç ŠD`ÐKka¬²?$Œd]Þ|"Þ(bŠJ(Œº*¸¹/{ÕŠV*<%³2~»;¼AýAL¿…ø4q×<9úC&~ 6¨í«_]«&öáßÁÎÔPÀ‡:tGE’®á2EçëÅ-¡Š_ÿgq¼ ´8/îá¶“'îÛ-i's‘¶t€sÞö'Gø[8Átš»à_ŽÎO6U¾A>ž¹aÏ~݈1å{\Èî9þã9å~å“ñBó×_'×ï4ñóÚÿßÈkõñ ÍÀà„4v°Ì7Nóz88q}fqœÿ×!g:¦7xžë\þêNƒ1‡~ƒøŸ êlÍ®osG ƒªfüÔz!Ùw~S+žò“­i¥š ÒZ/ Á0‰ˆ±yþ-¯õ/@ @ ý°„D6Må1̸o¡EÒ{¼oÄè+Záu½!G/¡ ,f‚‰Eí(¢YÇMèötñ@÷ý&£½W[$bBøy…]­Ø¸$ŠÜ6×»•XpþôŠèJXû÷ý݃VÅn% Ñ‹J`“¸Ij‹0 Ååv¹¥; ×YL jô¦×¹ó㣋N;wãʦÄ*·Nϸãm^ƒ„Á Íz46ÚwÆDÀ÷4˜=ÅzöXì'ÏÑŽME-R…7\ü`@€"º763•ËÞ—O~íp›õèº5à`ø&»í3jD?íÆÃ97zÙT ´½Q‰bÿ‚nx&¦duÓ±+Ã@Â!G?7¢y8 ޽¦þf¾Emúþ:ßËî=|´¢BCÉ3ó^PÌ8# ü=˜ÎîØ#Ÿà×%©©kÎÖÿO]Rd¬‡K‡"ßFRÿ£©ƒ|¼'O&-&†v¡8û‰[h¶®õ <$¤“$L™×Õ‹#½ãÅ)Ô”[y’T®‘ØääÊ6©ê¯#>ÚàèÔ?âaõ¶¼q›C¸fN}gK¥Wm­(ð+×Gí¡§ZwÚ +C ϵŒGz™ X#%ÆÏµèÞ £ úˆ@1‰2¬Ž€,Y*ó«»’xì¡è1‰†ˆ€:¸Z˨<8­S£(ÑŽ‹±s2Ä ‡G+3H¸U5Æë*Ÿâ .ÒTE*6[R0k¸x¥VNiæ iÆ=;ˆclˆ«4 SÚzQ·]¿ˆ¼ fqônD{ZÅÙ£õgDÜ}QWEµSSÊ  ®¶ºÚÞ}fÞÛñ²¶‰žœ¤±ªYø½qº-þ¬BöúùgÃäç}ÿ®ÒóYêmfÆ?¹¼u‹û7Ó} ú<]~Gxíòÿiç«ËâlÇñõ¯´õkkãØÉ+”lz„ WË ”PÜ©n+@¥¢#¯:àŽè³”€ˆlbFlR­~©§ `\W k¨­ÜmFŠ[p»TšñÒ¶z‰\G™ý1V—™ ó³îùƒæÐ؉@éJ£_aá9PÇ:ãAYsvfj¾^5x Å©ŒéVl5:íòV’˽RIDÀäW,ª è|FDZÈÜEö\OIk†Ÿ(¤¡Ó6DÃLvlXf늰°bHÂù‘g ²IÜ$9–èÇ‘™%a˜‘;9ÊÅïEqþþÖex†t¤œzS¡19¬s˜×e˜”sqùFHŸFšÉÇMö8ÔDfæZœ2iª}ö+Ï<,2M_ÔA²FWFÜ$m`˜¢Z«”±ÙóöV÷O@ h™Û˜ ¦½¯»Jd˜>k#%‘èåûmo µ¥¥$"RöŠ¡.÷¥‹# «$ûχèlâOÈö0™ 0Õ§÷~÷¥ÅUV}Οp¡d¬ÅúS&#ŸÒhѬý,É4‡‘ ó“}Xûl7ÆTßm# —Ü¥1¦xÖnX›ý¼ªükÖ~ïÜRgMvF(X­æø¬z Vw™SgédÀ$Âûµ0ëÞ»”šS1t_ïQ Æl&møE‹\#Y¬mmƒæð‰rÌèWc]piVXÒµ5kX»VöDçmzîh89´^E¶[a¶É; Þ×Vl64£]Kš¤c ‹ë­J :Î&ÙwwMMœä4¸²¨ÑƒFa®€k;³™›Fl霊Æ]CÝ!Œ`iªÖã²iªy@µ¡²Í¢c­ïV»œ¤’Y¹iw âŠ#T!áî÷ŒìN¿t>š- [júZˆ ÝìƒM&4ÆŽ6Ì\&*ÖbÄÕÎ…ÃÓ«Ä ï:¬l†ªášBIvô‹ÌÚbÏD<»»ÌýO=FæŽv |:<ë¨öSO0Ñ¿B˜´«¿Nw¬8œü%³›F;ër÷hHÈmÁçÒðÈnÝnÈ)"€ÞY«TÜëiG®\\¥cŠÑ½`œpt‘1˜Îs›ÞØÎsœæòa¬ãY .P$À†¡Ø³S\±ƒ&L’4Ž8Œ¹\–f°ä”I“—bÖmsm33œéœ¶[9Î[9Îsši0e±Ar –Ç1™ÃÆÌSÂÅ3`ÉE ˜A“&Gø™kL†(vÁih0IrØ¢d†2\¢åÛ(¢ZZÄ™ ÈâÔ9‚Å‹ˆÃ'¹€½e¨ÈQb bŠ,QC°Ð;Ìd2Å‚æ ppÃ_;\¾[$K–i ±‚ÍcÚ„"Œ—%5‰,"H2a É†2d‡M s&³Q“#a³%Œ–dX© ä‚™Ìb‰h “$´4çcÎk9Îs–Îsœ¶rÙÎsœç9Îsœç9ÎrÙlç9l¶[-–Îsœç9‘¤ƒ$@ã9rÆLŽ;¤“–`ƒ!F $±EÄ8팈ZZpØl]¯†ÎSœå°×  Ý®×c82Ö.\ ¹FQ†°@"K3Ž@ã˜2`ƒÆ¢Œ˜0\ÁK“%,d ÌI$’d±MQ–Ã6B HX(¡Œ.X±AL30Ô` ¸åÌ06 É$˜$`†DµÇ––«“bÀã™$¹ƒ&C&L¶ vj±b‹ŽÎ9c0Ø0I&K6 —2ds&F Xs%Á!‚ÆJª2\É’\»\‚Ã`£ rL”XÈÅÄY‡b‰(A[Xk29b˜qŒ$¹È(ÀY  ,`.@Ù22dÉ“!ÉÉÈd2 ™2\òÐcËXc%‹IrÂ(2AD`“%9r‡±Øg±˜¢n\ ÀIv£C&!q¯rÄ™1bŠ Á¹Eª(íT2„!BDDDDDDDDDDDDD9±s&ÆÆÆÆ ˜2`Ƀ"ƒ"„`Ƀ& ˆF ˆF ˜2`È„!2 º6"h؈ˆˆˆˆˆ‰ú3Ôð{´¶Gˆ•/²ƒ&½CT]‡OQm× Ž *šG¡Ó…9aE4ãSëâ k‹ñí½ Ž¹Úùs•¢±íÖèëÏ|S«cEÙ«¢íËX1‹s4-mŽÖwvã‹í®Ým pæÛs¯KkÕ±B,W`´½¬ÝçÏnV230ßæÁo?»ìöúýåí˜G½kÕå{Î÷»—º‰÷³XÎ.ö{Lá16vÅ !²0–21÷Íݱ.å3˜bgÌTâ×½¢÷›^2½¢ôó´DMÙÉM͘–kÛ)ß*ӌ塆sÃÜ*,õC¸ù\yé¾Ó/[›Å¯Ì:‚å“üîç¦P8ß×R´´Û» í1Á$ùÅ ²¶7hD~!  S ·ÚÖ=s»2¾j¹†‚D`ú¶9`îo³£|N"£Œ¼°¡‡9ÛI3¯’S$Fâd­n•e,YÑôÖÖcì­= r+ïÈCo3´Á ­!Ÿ¹ à@€ TøJÆ­ðÍ{{ñsBVñ²ÚÒõ?S¯~|ay¤dT}Ÿ‘ºp^¾iÖw¹²‡gKç|?ñÜõ‹’ *´Š‘‚@ CåÍÔÁb¥–?¸É?ÞhºMå´³ö·øœþ é‚Äb6ÑÉ ?ÒûÎgþÌÖðÒa‰´Ÿx˜~RXŸ¦ÿ…C94{©Ý’ˆ) ‘NìTz¡Q ö£1q¬")bNnåEF—½žN“ZÐo(¢¨ý(*«Ÿˆ G”ˆ APqÍÊ€¨›çwÔB¨ñš×êÎ!Z¢t¿ã#îv%‚ =±xå ”<"(ÄEDEíö‰i›ÐX¥GÀ6ŸoÇõ³VÔQÅ‚(û½9Ž^¤;£‡ìör·'<«eÈ\<‹Ö¶™óCk:Whu­—{µ}h Á)jØ … ¶€#˜²óƒ±6ÕMfË’æµ%Ãýx»N¹¾ds[Ö¡%:ßÎ;¦«àÐc’u¼¡ÎcnnûÜqÚ¿É Ì6G$y~’¢ySÐÝbõۡbä…É#8äD3¦¢ª6‰ûΜõMF² X¶7’eô–Ô!Çθ%@’L ˜O¦ ÙÿÅþEË‚2h8\{Ö…‘Pðjž¿ µGó:a90Pv“xXŒc’óáÜqÁ™yÄ<Ì*.$„!ˆr„SItì¨qÉ’‰(HÁz›€®0“1èFI(°œ×éAúÍçCa‡8»Èb'>zä;DzÓfÎ@Ä„3CJ”š‡:MBrd¥÷>ç]›6"ôlëf M¡©c€vf.60ÖjIub" [ò•]îdÁ‚Ä,XB4N& ØþOÞ{Oòk–™Ú"á‚ȬLÀ†Pè¶î®¾ ãÏ¢aæïš˜,$_Pó7mü{ŸuµW÷æ|vüO–ûÎz}‚´0"ìûCzí{$2¹ ›``PVAEúˆ¼Û7§{EæeÎÇ\õ‰×Ý}ƒ%‹ûÿvQ2• ÁÃMz¸ÇܺD`à ü/×gÉß^гƒ82·»œ—ï+Ný¨$i‘ûjIÛ°æ>vº.1ÆÇ œe <œ”<^Ï® JÔk¸aÏ^V_ð£˜ýûÕ,jª‰W>ÕÅ[uuå³B[ì~`6õUŸ'M ¡„Èo9œ« ãšNXQl–jD X œæ˜ÀÙššþý};=]ˆèøþ4FPà2kk¸høå1µ´KIKq¦R°` 8¬Q Ägì™ žÚm/«^r mÚžÁ.$H øR˜´GNë÷Om;o°ü\oEÍý\wáÁÞq”3•µ½.[µ§ÂRAUëIî†&cd0`ˆ#Í”¢"”¨R2P*2QN0‹zÑC@öúÏ·ª.ŠÑ-áö¾5FgQö©“Ñü\Þ®(£„:aQÓP¼a 3—1Ê)~ÂÞõh3‹—&â$×C¦¯¤D)þä~Ÿýy¥¹¦bÑ}®ÐÕôÞûžÂÌßK#Uÿ+žßVÜíOÈfa¶-Ž®÷ÒÑ.öÊ}1XJ­F X£°¢Á 2X°XAˆ°Ö Y\‡ÄÕ°IpÅæ…6 ÞsRÔ÷EIzЬDLÞZ÷aT–®b_*ØU‰(Ë∽³döË*…«©×Nøôx•åO¿@v^ˆÕ‰‹Ç•mŽN…I@Å´g =mš2ÏæZ¨ô’šYi Ü$=é’„Ñl!YÛªW€HÃá C±‹®µŠN}‡§i“÷È{GÇ-Çô¾" 1ݳ‘ÁÄ3]3QQ¥(x,OÑpÏ™LÑè9'ÒÁ[Æ ÂðRCµµA…gÕÿ ×·Ñç̽¯O­îkÆgêU‰vùoMëŸÑü›íÐkãˆó} `B$wb x@f\#FŸÊÔ²)È8,ÄØ{t2"Áf7}ÎC™Ì6j³^B³p͆eiKUäb\¡ä–)àOR¬Œ£I•PŸ¾ÉVJ¹Œ%B€6åvÏGtžšM!3çŠ`£YUþχÚèÒìèB%gK¢t^qï}ú7·(¸„¢õ‚‹¬…Áa¨ƒ$¶ ,`.6ív“¤³bíŒe°\±f–rH$ÁP.PXÆm‹ !¬`‚Ø2Ã`’H,0"Å‹,\ÀÎcÅñ›´ÚgšÏ$¼=}²ðí¨Žˆ,"­«†1·8ÍjÙÁqs·ÃÕýO“å~¾Vó'ÙjÌìÐGM]ùœÆdK˜K'–€µ\.¿ Þö,kªÞ¡Ë“Èî:[¼ÅÃä`tyþšn†¬@Ø0‹Õd¸Æ7.\…®'Á¿Ç,‰A<š&„ÚC™²ëš.[Ù I™„š ÔæªÄy“ÅæÕ×ãJ TД ÉNM¬\ íµ;›øuøzü|û· ›¶÷Ø>#á8šruž‚(‰ì%!ˆQ9´UŒëå73L“&S aôòÌaDDh´²*báh%*2Ùd›3 ‚¨“§²z;ŽW®~!ÙÔï;¦) zØ éå©©Þjñ{ÃÃ_Ëãõ»wWw7 ³°í†ÑÜmèN³¶ªBúC¼È8¸”¬"49XBÖSBCAÀÀÝ q™ ÁšÑx”ÑéY,ÉM™í¡Ø&qßן2Î pZÄ–jØ“¸ÑäBÔL1ªÄpL—Åħ¥$À«^å6¢"B! 'WOq8÷x=NàÔ)z¸<ç§éAÑ35¸ÇçS=I<½Mê=ZêÌÇ–ž7¦âŽgäeº)Ì9ç„WigeI¬Ì‰h‰šÑPø‰´ÙP.ÓqѨOFôw6R”|ûJ‘çÝÈ›g!â @X@lyI¡Ð°$bL¸\28J'1,iÒÆ´H!3Z^pÎÚXB!Ç¢ƒÃ}úû8(c†ÁŽ®c¼Ä?‹g#O%fîɹ©ÜF÷:öv4ÚC8Nû„’a ¦Lµ9î>¡`ù¶+%)S#@šÀ†ïÌÑ(Hèɵ½m6BBCCáÕ á´šÒBÛú?ŸÎ–º´næÞl9ãEª„Ú‰·=;5p0.h©M»Û¹½>ŒÏ— Æ›iªÝœ’O*(èr:ÐnÅ9!ÓÒf–-Ëj6p!EÚ\»¡+X!‹&‰½ˆ,Ŭ4Z¨–`hÌ0s¨7ÀÊp"ÃA ±Šs°Z%Ñ1¶—,7ÖìÔ`ŽÙ×¡È u"Œ`in½šsçFmµ±bÔ­^­Ã,3 åÇ5´ÝÒcÃCccsÀ¢«=†lÐàá L„GH!„O5,Ÿ¥Þ &† zl ("=_R‚ìP½ß@ÈógŒLy0£Ê¥wa³«¤}5ôzG‘¨CM½'—ï:©[ãËB0hs;-rý4ùÂa×<¤£ƒ&¥‹yy(¡æŒ`á¤À gKc£@zl E8vÀã"ÅA8¬AB‘æ¤ñzÍœ ¡s-2YÎ`¨‘$DI¯K¹¿Ìòíí Î]{ÓQÜ­DFL—æ¹.Ú6‡qÔåãóy@ÎêhFFˆ iK(Y JÒF‚[ !àe=Fjd”¢ ™ ³ûÂüú¦ñ¡ƒŸ^05C;ÎØµ5$°sâ!;³0}BÌFLld•(« J2vXd@AV3ćš)‘¡;ÓÞ·Ô²ãÝ…Å(ªqÇx ü|-©ë4מ9óâcë°{Úó¾”ýä”É’#8–¼º±÷!ì£xè ;³ˆŠX«|bƒ†TEü_…ÆBSŽ €/±BSý<~sù3$‘ÝKt›l*[`Û}†±‚”,瘨g»&ûÔm!Òk#Ò6]o)B­)*”€) ÅX ˆ( ‹QAŒ`ÄF% £Ca¢R!"7ËÛ@µ16MƒÜåÿŸ –üÛO w™Üªÿ3¸ý²ÿ‡µÛ3XÓÚðúÛö2±€IϺ Ì﫽}¿žóÿ‡Ï[&‰á ì7·Ê7¬Cö$y3ójQ ;K v窯ñˆ@tAö¿›×W#@fí1¨»œAu)„ÐÂHU­Äsël°Þ¨<+ýM¹Œ¶Þ4ßœ›“Õ~è‹Âú •]·µ‹Së?Ó{ù·—öe±šžh haH®i-±ñÆ@ ðÝÜ0â–Ž› jDWÛ„í½Îë ×~ÞÛUz¾w-Öu\D¹œP²Ü=[³ET`6 ã”>š  Ê€ËcåRÑP†ïß›åÑÑrèóß” åÆ6·ÅK=íØrÈÜ”Ëìû­7Æç—¨ê:ެ/éÂ{–~ïgÏ_©Dû(QR‡h}¬h8µ÷j²³æ6ûU€±h]‚x_" !¾]·e2Û£_g¦É óŽÃóýÛ¦:V/Â‚Õ ¬¾3`:~´¬!¤Á÷y€¥ à}~íÈoù½}ü%†cìÌÑ»ýí¹òÅs.Uâ]íÏ\Þª¢ÚÚ,dÍ09’K0\¹s 09B ˆ(C$™†S›Í¯¡X—††¦yE“µÂo˜•{@ï#«Zp°b®Óekˆ²›Uó‰œâ<ÿê~v?køïäyާõ;ÊÓ÷À !|–LìuLÔKŸ°†÷¿‰é¼š’§—\q°Q…)h®¼(.æT}%QõzP‰r,‰»µê®ÿîã®êÓKNføÖ"¥¸‰ÈêjƆ Õ`Q÷3ÜÀ36ö3i¦Q’X£}k‹ç"hÚN e€e‚ìK²–1 È4Z†ð¡S çþáot @Ý+å»3}âx'à¨v¡@îµ=}u?9÷ó?.Úc׎ÆÍS/—·nÇnÞã^<ß[+¼7[ºLÐ}§œ„þýÔ¦bÎ9Ømšž?g9¥ã(bª¶©bÅŸWÌg×§Õ“§Oß·77WU2å‚>œÿ×Þ\§¹g;m¤øX}8`y À¬#¡¤å1ÃÏñ}O£ïvïÖùRhŒDX²Ešµ`²¢ŠaX6É>3 PøPBÄ$&BBa #nçC_‘·ÇðÇÔ7«¹ò¦æÁµ³Âã\Á–¸‚d\Àâ0ØÉc½í–“ eÁ­A& ,A#³ ÃI%̵Ç,XÁ’åȹ  #aŒ’I-r¬!˜.\‚ñ›úpZæUá¦týû¼P„|"ùm£7 ¸6‘ÐoÓ W^Wë”[#qÏb³Ïm8; ©8$.:”avŸ'ãÞãËK}mP‰_ž» “ìôSåX#¬ìlΔ·´¸ªs*I°‰G|Y‚ŒˆÌ24‚Æ˜ÓØf…‰š¦»!Mër19‹0ÁQ‘2Ò¤jS ŒK÷?cý>ã÷Ÿ3Ô'Qƒ¹wòòm‘éžg˜£Èô»ÎSë}};lÌbÙÉ€ÌH†í4=bæ–ô—ï<øpmPÒ8Ö‚0²†¤±FM1ˆÅl‘e2@2ybé&ˆ°Ù0Ô Ë@„Ìۆ¼èàß“bÝ)X¾6µÖrÆðNB sи5‹š.\Ào€k¦7gL0Ȧ2Âá aCEXŒ‘Œ²MB˜±2˜K0°1)Ü05<؈2k3Bi‰ Q #8M{­æØê3WÛ½à6Ó„ï0V>vºOJ~ms#55$ÀIq¤GaÌãS Ã "uɆDE°¨ù;ðá (ÆnQ‘"$L‘îN4Se¢$Aø‡ònÛ`cÒ#n¡nÂìÝŠñÉ£­¤­3š0ÝXÁƒ¯a$\kõ~£åÁÁ!Ù0“Z÷)…ÑD ÆO6 w‚uÑ„‡È@ DH¥Ä<ÈDB€‚I¢$))d¬røþ¯MVœ¹ÌÈdOS¦ÔïUU¦vùQ¤êa‡¸v¡ƒPÏ,€wBvæ!!a ŒF"I Hxöf³@Þð•„ ÍmMíü»Öƒ?‘©En: ]}yIØ#¸ÁÈ9ör;¸ìíÈØì ctá¶ÇÜ1ß™VAD$á‰EªEÇjÏýí´L™ulâzêq“BfŽYÁC)Z6 œƒY Þ"#Rå°§åìJˆrì_l}¥Î\‡ÈÁ®­¹ƒ!œbqBc‡¡°pk¡Ç!Šö YÄ<§Úk¨¦Ë))z7)þ§3¾ƒ0VÈÜZ¬u‰]ÙŽ,tý²ÈäòE<´F# ÁîaçI4!·Yä `ÙD:È’áynƼ^³%{“n¨"¶uø+@cŽPÎ fø‘Ûº5š”µ3:骒.Ö×ènŒA,]ð$tþ7ÿGþ1x ÿ&6 ðÝl³ÝGy–þØ=ßÞÆJò«px Éâ=ß2C³0.Œ¦F ’ªˆ,€²Hv2Cè“ܤ‹}núg`g[¶\v@Ó…Ÿ þ lƒcœ…·?¥Ú€ÎöÍb0L 0¿€ˆüÅŽ8u?† siŽF_âðÉ #@ö#ÏöiÍ“Xg¾YåSá5•üÞïÉfî_×od}׋Žû츫Ù›é_4¦A‚ $ x '‹e pµª_I™æí~^£ç¬LÍuá-mš7cb_ÚçhÉV¾KÛ<ÄÇVº,Tv`ãÀžÏ\!+ÁÖí‚XÑ%™*Ó‘û1o¾ãÏÀÆæjäšHÄaóþý5úŸÖîí•V©]¶¾ßu0N5£EŠOÚ‰ñ+ûú?^[Œ'+“78rÀáÔˆÚ”k2"X.Mtk&,):žW6ÏZFJË£ÎEàÇ ŒL&“#¶_Q.SÌ  o`]Þ ¢l¡ `›&ãE†£Rއg‹ØJ9žÇ-ÇàøŸV…·e_ýçn;MóõéóU•`vC˜¯­¶ç­V ÈëN̽Ù÷~É÷=Ï“ÎÓÁ”ËSáu—ÉLÀÒ‰ X›üwgèL3õ]é¼åG̸õ)‘ô¾>XÅõ§§'x«ÍÂóÊÙx½ãE±X¶!`0\É%2Qbå‚ —$‚Š(°ãAÉ œ(¬r MSˆ)¢ø§€ŒTiª’ ¨hN:¶Æ]òf)¬©é³N"ÖÅžiYb ÿ—û¿³þg÷{Ï÷3ýïàÇ£¿ WûpíŽW[ÇL1¿’¾%þ.Å 2Š:C>ê Gшa$W´—5åäòqÄücãí²o€îˆõB‚y¯Åá äæÐÿ®Š&ÁÌC)L…þž%K5šÌ@ç:¯Ù¬jºþ4P¼eꊣŸªNj÷ò¿¥Ãj(ñ»'{U}hu'å?YëÙæS„9eŠ­VT¼õNdàà.`S’I>“!h¬ €¹8Ødñ! ÔãdÕôéY]©GÇ"2jÙ!ù¨¨ÖUU’š L¸‰~‘¿æøù|ûGhwÈeœ/f¾K(¢È¢ “™2`28ဩka¯%ÇMrŠ,9bâ.A’Ê0\ƒ 8ìI!MrK†L–rÄ Î$ÅdÇ…4½þËøÚçÚ{<îÿŸrg8úmÈ:%ünó(…c©ÈÔêÐÃɤÕëW9ðîil°Újkü&(Ó¯ÔÆÅñÜaÄÂ.;Ðë°gjþÍAáÏ ±×èøØi“CyàhaQN‘a;Ó?—q "tdOÞˆ“¥jÄÈ]õÜv5z7;ÃNzõ42,•g~e¤ê\£Øä¸Ý7Ø£õ«RçnÓ$ŽèqލpsH @!¿"|O¬þ§C§o>;{?\„r2@–óžmÞɺ’0ÿs”BØ3]uŠ!Ù`À1‹b†¡D9¢æÇ6ÖÜëCÌË„&Š•ä» ‡ Ø¢%3Afrt‚e Þ2 ñ’!œt2¼}gl7r¥ÊÏï³LòxL;`Á<:xÝI£4/%˜Ô8.ÖÝ9/ „ÏÚãö!ÚŒëŸéquÔ® ”AƒŽVj– °Û3Ë KˆL:H—( wx$v—$‰‡”éE¹òþ'69Û[¬D@:œºs–›ÄÏI˜é %ù¡$ì㳺‰¨,(¦­²SÇi‚;Wž{Ÿ¥½ü«ŠT-ʸ=€¸X² rŽæñ{›ò”¥'W¾a¢EÁP>ìtÀ ³«Ëï|o©õ…G^ÎwÞ1ÔWÜhùÿKqØ_“ò9b½PÞfÎir7eJE„D„DC;/·PÒÆB}=úÙ®•è7Ï—äl칬’ãñóâÄ– …áöðeïãoˆ|;*ÚZ€†?Ÿô› ¯wÛµ¾Æ*ÅÛà šæ5 ÀV§ø^*i8!vVNÜñFz utádµzƒD°:ËoQú¾¢^Ã=m¦ëñþÃn~ÝwÈ{›ò´¸¾ÖÈíììéøœ}Éð¼j”`ÔˆcJƒ2 `ˆÂ)kQƒä3KcJR‘z.)ºùîFëÔž/;ž“šæ´:$*¹¡£ƒ^aÐÔfñìq²4E”œØB€Ö†ŸëYöw™.¿ìÙ}ÖZGÇêt[½×Éø¨UsB˜œ3\Ç#Û_*àdM¥õE¹ó]æƒopÃÕîv|éó°áyî5ï9þ£#Öþù,蚃;Lº¹¡+{Þ.oW”±œoœU¯|A¡s@£™™˘0I‚ ÀŒ”6FpÌæ‰½°bpRy|]LÕ#˜™¸X"*Ö/lÍŠdÒ]³³ÕÕ³wš‡³æØ\¬JÎ\xzÆ,fo‘}ñøïý_Ôý—Þ|¯"XnÊpÚ]6,žä\¿Éø,:j=ߺç÷t³¬"^2kÀ‘'½ôßàíáù¼;ýx~.°ÙþÞ“t*Y‹¤j ”–‡g¡«QÔjãÇø!Wa¿§·>ñ7AQ¢ËùDªÁŠ ÁHÃ#2,a…EÄ©JJ’”ëÙåæ'݇ ”©Qí¼¸]ªíbF¢ˆ%©ˆ!Šg.HKArbä”]Þ¬Ö¢ ô{¢0Îd°X³a›K.I%Ʊ›A$„ {»ÄÅ­sò=,PZÃ0ÁuÿKô\þälZãŽI¶Ðv>Ûü|9õÁƒìÀA,cÏ5ƒ€e~&{ƒí#þþzÚm çxÑVoƇ¬oA· k˜t#@„ÓD8ߨ|ï7Ýz÷ÙýŸmúÕWö6?i€ á·à6× ÌƒÂEJP:j Í=>ÇsÍSÐÝn4|ï“û?W[Œ=ÝN¼O$xg^¶ô ƒÏûìÉ/H…âž±ç`òùspË>Ϥ4?~ç,Hf5?v¹k25ªí!‰?„u¥³ª½:Q° è4YÓ\^ ÝÕ_â8”ÐÍ ì0€`ÁÊò§¾©@؆Ã6‘|Â%Ç?Ï7ýyÇt/Tgª ±8ÍW `ùu¹;Ý%o…ý¶}®¯¥ò¼ b&щFvˆRAÂÅxj' y¥¹>"|mæ¿ÖÆ~=(3·‚çÈ FQÇòݘ?Ú>öúÝ&fa©KèÖØÔ˜µ£laZeã‹<ÕAƒ-”`rÄ.\±s%(É%,\@åÃXs"ä† "åSâ+5bÙÅ‚g¾B/œ!E&UæÑ‹¥›5YÝRŒ•‡Ã^ùOJbñ%ª¼æÕšËçSúÓègøD#º ÍAçe/ó¬>{ÿ—ÀtHäbÍò—à§o–Ñû¿Fºøé;ó-Ã’%:™NÿƒñìþŽþîß¾oÍèáÍÓÆÖ–„Kÿ#$ƒB T­€µ…&DR °kD´A(ª ±ô½¾ïkÔãnÇgOm˜p:@â*e°I2LlK@‰. Ár‡eU™¾D"åšÖ¶Á$’Ä6K–’ãØ‚ ’I‚ &K@ဒC!J¤©ÌBÏøC}•z‡cdQ¸å„Õ:—?}Èýó0Ì6ƒQÕÔÛÑ%ޱÐêV°9žŽâ ¶3áa¢ÁOíá‚Aˆ’:1ÛæcœÙ l£TÃÌÈç)iÚE›ˆÙIqšÕŒt!U¢2‚ñ`’(qÜv?Uþ É׃ƒl7ˆ:7.F´6Å >ú&¾‚Drš‰H €&˜Ú.ä4¦ë¿‘<›//x9&s$#¸´ï@û§;S9#ŽIá#é Òæ®‡ €ñ2”¤¥~O^SáX¨Ü€Þ'`Ã×ivpÝ©؇€êò1%Ðr¥†H@¹¿ æ°´T`fWm×<ïÛ;dÁÌk^ÖN 4N¥…’l#@áÒÀ+½Ó3 öâ8(›i¹¹s‡Å5ÇvÆ581ˆ!SX“3¦e.³;3Œã€ùb+9‚kC;ÎáS{éLT'±U&éÛS;ÀGÉa!1(Ñp†• íœmüÏ÷= ç–sÍÃC˜q{âÆ%† x+á7‚ˆÄRÑ_@ؼ¨«ÁL  À€xóh×Á…lÓã†ýhAÄ¥]ùô¡Öï6¾îκ·mk]\:žÓµQ 20D@¯ˆW†.ÎòZ }HËL`¸÷Іs:À½­o–ÖúÓõÏÁt¼T»ÄÂQ:G-"o7Õ_Œ`‡k—5’åÌ™0ArŒ" ¢Ãˆ£!q3–(’äÃ8¦fصÌÝÊX˜½òù™Â•{Ép»ZÕgtb¢1Q‡³„Pá"UðêÏik½íˆšºlÚëu‰{yÙh÷¾º0‘«2ÀC)ä`”ˆU²óŠ.·0ÌÖÂd€* ¨Úª³Œ¸¬ìz<ò(ÞÌâW\L(²Úý —Äs9ë×sZ\¨U d‚Iäþx”{ËÏïo´7¼Uï2Õu%²ÌÎX½Xv.bÀ[$±zÌ”SbÍjµ˜É’G³E6¢Gr `¹{’eŠ(Épƒ”ÈZLµð$CC,°Qjb!íl»ÍømŸÛ¥²#Q´’G—Ú$Ô‹1‚¢à-lþÂŒæ~Gp©‡jþWé/•nÚç^ h&+Ê-gcÊrPïLîßpæQdÈL1 UÃ!¿±Ñ65±0”7)RÈ‘ÏexmfÁ !Þ­|ͦÐQF&»›qp]ZŠ•@î\†‡´5Ü ‘Hnàì!»[õنƛï’I5;ZTI¾æI7.0E§dÅK®,DåáÀà˵ííüÿ9®¯{ÖóœÈ5 ÷3óSWϺTÀ,;6yK3š•o«C ‰½‹ÍÄ0eè‚B¨ÄQ µB03ÓÞöóúáQ… iÌtšÎrMÈ!ínûEWk3÷I{v]Ìöv*– „ÑúGÎå‹íË–ûfç.Eé>'0l×4 ¢KŽ;ÁÅ&C®ôC ¡âçkÆÕùi¡–³Åè]GÞûÜÁƒH¯ˆžf^‡bæÙÛ·aî=“Ytöš3Q³»tÄ1cz7*¶ØÁñ(@(ycc…úùã~ 6Ä”­ EÇ$$Lq‚èÛ¥Ä;#w! !$&8¿9x¶sÓDQ¢¡6Ͷ©Ë ´¾ªNh]™Ç×h õ¼àjU~™\%}Ýç¡è£¯&Áûʳo©lv‡j‹?2˦Ê7¤®E³X³¸D-r¦X}ØÍP«ÀÐ`ËÁÚ­;$ùÄPµEÔ>Ž4Z7–»ˆ¥&$•Ý qVÓ9˜žq÷Mbd|."ÖÇØd@KA –g8*;Æ ò¹Rÿ,‘o³ô¾«ì¬õšÜ)o1k?gY¥ÿÒøø~7ÞÔpÞ—KØzŸÓõ¢ïçæbõ<¾»~=2Z’@¥)AFj 0@,ö54Ò”ÓM-£ VÅR¿cüõ;Î3NøŠ.¬sš> Èúüê·Øþíc»ßWÿ}¿nç­ê|KʺCÒæ¦"OŒ³ªê«··4 hUKGòó¢O^4²ú~¯åšg‘€µígrö›o{Wί횢õk_<ð/ŠŠ‹@‰$¹z +& 9s—$¢æD\ƒ¹DMfø¹X‡Œf/‡±gµ®ˆïic4–n×uXF]RŒy«aë#Õ«åcÃú?è~‹ø_Ä4ù­Aó¿~¨ìŸ}wÜ÷ká5£”Ñ„ªÖg‰ú}¹×†ÑTYþlƒ¦ 00n& *\R,bE ±X¨fOÆôz=žßG±ÏÙí¼‹Îr(ÔX´9& b™¢®Å8FÚÆcÕf,Ö©µÚ ™kZÍrDHìÖ X¢nQ¢ZKHæ ’Xf Ž`€™§b훪µ$Çñ||“}¦¹ýÿoÄpX¼qkÁ5ŦÜ|DœðjY²&úš3z“~ŠÛì;äŽÉ„k&g:ÄPI´%eÄÑv›%7›•º ä°U¬g7DÚˆî;![ò¿Ùÿ‡J7}´êd±`(~Q iždÒ’™1cL£`B Üs›Ž«8]ŒF½:-M‹™1h,ñ¶øz‚ .\±¡ » 9âÄÖ’–iÇùÿÙÄ,Ôm#›‘®f&ÉQÊBú;ŽpÃŽ1ÍËï(ÕYî8æ›ÅZý'‹,^iÓÐ8âNý± œ Äa‡aЄ&@/ÞmÄ_WÚœ¹!'<í$¤ l^ÖƒRj :ƒ¹0δyƒéÒÁ”°DDuÒAÞÞ<³b‚C EÜ% ÑˆgÓ4²n»¸3Ñ5×lÉ«± å°d,Â’K.d¦h†$¡2Æo˜ÐpÌš.ŽÊ:„ìà Ëf3,im¥µÅ]ÎS²ÎD cìg¨®)¸•••uÎmÅðÌÛÌÞ}U¿N‚Óýp¦´…™V=t‰ú_:>CÛÏ܉ÌàA† V¤úgþ#p%Š~g·­6¥±Vìéµ´0¾†úÿhrK³õ\O;ÏûÂ3W¾ãºÜ`§cµ†¯eõÌ×ûB&†·p2ΤÚ08P%Ç33‘&³5‰îübèÀ准k©ü5Ò]åïê;ýDìþ Ô41$^ ÆLf&óô}ßç~âÃÍ`sí^¯ÏûäŽÄ~­7¹šË<xßíã8Û¿~çó2N˜t yxG‰|/*ÃÄ4yPäbðÐà‹4ŸÛ¦°ˆ(ŠbǘÁËUfÍj(¦Úš˜vq°3ˆ “† 5ËCHí’ãP2E‰  ±‚Œ’dh¨Œ]˜Wº|ÄÃoËîÿ ù¬gmfOm Š„p•“€·G e> lµ¬Ú…Õ¢ cSbãìÌÙdlâqЇ Óûši‹’!QZžrõ£a¬kй¹ú´$ÉÝ ¸¡P¿fr®7Ûg¸o[ĺ´¥4[j æ`±’X‚³Çu$8œ¦!ÄÒK²pâsþúΛ§Ž ™6;i^ükËFÐgdPãÇ qÇ4a3¡øÒø6¢ Íæ^Õ¾÷6¾¬÷7± Òd“Ta·vø#08jqÆñ¬k H‚‡¾íivÙ<ªð;PÐQh1tÂ’[b1¦¹Š¢‡¼Åi«’Îij qì˜X·f¶3zq¬@¦fE&dËh!¨ ÍjYˆÈŽ ;;›2% gý}ö ’üñ½©ÞbÑ1Cl9»`“‚ÓlBÜG‚ ´4JlYkSôzqÕ}6íÙ6ìôî|ÃèI<ŸÉðüüCІT@ ÁĨo/ì÷Úš¯ÒKÒ™‚qm;#Â^pCý7÷^£HøR¤Ö!¦åx«±Ρp©qßrª¬¦((àqQpEhÈºØØ¢²MÃ3‰ ÜÚåó$'ßÙjcçƒ=ó&=c|•“Cˆ‚((Æ*‚jö;»»ŽÞ}Ë›k¾QNÛ«c™r®A5ç¹™ÆaŠŒ£¥´J4c×~S¿¯j"J,#M¶•"•ØoDXƒ!I&K…³Àã$ÈCk³CŒ#%³˜—ÚðLÕšQc2ÎK2¼°ü „jÆt´ˆrŒæÆvÌŠ#ЗXº_ôoØn{¦îÁ¸‹)n…GPUÃàC·µNΓ]Ÿ€5<.,¾’ákγì!V¿»Ñ‘MCíP؃ŸV­eÙQAQnÐ'Qˆl ä¿Üo‡ÿ·¾cþ|™ ´\ÏwmX-6>Ïb…»wö#H¤}@-8í%äLƒmŸÞ¼*rCÛFûÉÃ;Í-ßÌã:åÆŸ‘œ¿¯ó|/y»] üÆ£+‰Z)6,tñ @ß“ ŸnÛ /OgÌÐ/ã…ðu[•ÕÏÐó&”t’-xŠ%2—ǬêQ Ã0ß“|¤ÔÂADA)hˆˆyæ Z¤¢d네À¼á!’™0¥–Ã3 gÈ$„ìàÒpÅâf‹0$v’ Ì7ð¾I%P&q ±&`Ûùÿ‹v±tqif1`$!%˜ Ã丹;FaÒAG>~y[9õe™FŽ  ¡£›î³¿¼t!Ãô5:;))D³`v4j$Ò¸dJYJdr!‚ê‚94L,I£ dB–s=›3K±2RPBÉ2\–Ùe¶[lXQ PÂa`ªYD˜RR%%˜aß’˜RhÂÌoÛ¡“dØ…”e1"S ˜aâìù?]³”ä°”e(Œ±R  Ä(YNF™)K)„L"1(…”‰2®J"dïçÿÒCF‘œ”)DJ(ª¡ÞS§9³A (Íí|Ù0f€Ù²™4zÉ0Â&„K)OªŸ8ÔÙ„ñº–3‘îlgä°ÔÃBY…0)“ K)ñ“X¾Å(›5bae)gŸ a.–ÌJsÑÉi,ˆ)Ça‘ÐÖí%‡duƒ™-ƒößqöÀCʷܳ°¹ÎÐîó6_àãÆÑ€EZ.:hмÏß篰å¹éwç¾—îcju{+’ùø«Zž&î¿ Ôî“ÂvWµ­egOiÃ’N Äâ#3‰œ+ÕóJ¯C͈cª»} ñøkô[ðjû¨Ob‰™ß?²l ühõαZëõ‡*Lg¿M¿‰—ÓUäæè5jo´Tm¸°^>õ%¡¶N÷-×ÙøÉ'¯Dùå:ŒŸfÏSœûKäa¾ãì¼5ÍWùâøÀÖ4?L:!Y°öúæ|Ý¢/ˆÀ—/ùí~\gå¡ïùïægÊ"à` +òa /wïÇÚ‘±ú£'v¦™|ÀlPXöƒkTŒ@úÐÁÊV;¯/ÿ7>Öë!Ømm¸U{ÔÁ€6}„ 1±ƒÍfb¬(e&ß. Å¡ €=Jd"…–ð|ØGÍ"ã0YS3kçú}`é-Óùë »8F~ïvĺw¶vþÿ=]Oåø?î:2Jc¾#7JÂdÔ¬Ã÷J˜ÏÌ<Žç ÈŒû*Z·–Ò=ÑÁ×€8ˆ„XævËMËÖs¯lØz¾4èƒÏñÞh—&8=qˆpèÿ¹v~Æ’FL¶$SœmoÂà:Šÿ(ã‰$’ „HHAV ÒføîG²Þàµf‚£ùŒ ÆðÕŠ ø)m…¼Œ D6]×sð:™/…"¼û}IÁÓCß"ÈéCÓ._QùG*¡ËGbßeLc‹çŸïf²ÿâWl—áß_ bþ9ùgñtÕŽ›a¶÷ï*ˆ«]W1Ý{IÓ8.ÏÏu½éè¹(ôaüt}|o¤étâ»æ¡o9ÿ*›ôÿìmÄÞµ0¦Ú[UèíçþF=x×û…ýo+vÍûj+›aKH¬í]£ˆ¦/Âçñ±U¥eóR¿Y³ÂÓnJdO»ç:–ZÆ–ìιý7mµ¶ïË¿ŽÍØ5™YwJDø*·£ÙÎê(‰ßþ4bGÒß—‹hº½–­ü ÞÊÏšñã¾íªG^u©çâ3~_¿U.WÛuÁ\owK¯’z›?Gø/`¤]Êù~"ÕrØœ*¯_ŸÕ\“óÏð–†æÈàô¹oy8´Z{_ÝG¨^÷ÃÜ£¤¹æG½qøðrý ©hâ#°‡ê8î•âD;¤8x¹O~³Õú{]Ô±‡6‰üÖž=Ÿ8˜ë3žGÁ¶k¡­Ì#Ÿ!e(v%Ðä0¦ß¿³¥ø9‚ò]ó¶xøb £–×AŽGKx^Ýx‡Ó¾5Òû½ï<ÞárZV·½-œÓ.N=ƒÓe›œð¦ú›y·=ÏwÝ÷¾‡×„¼ßaóœÚ—N6_èo]æ{GìGbÀËøßÆú§;cÝҒܧ·¨Ñ*šù¿bÕ›ñ*¡rÂ*MNåbï‘mµObhÑ{¼­o6ç0Ë þ|þêˆp[™ÆnH2ký8„p½¼çi)_¤¿7‘ ²öŸ<¾+Ȉdž™€$n$<º=Øn P¬fÄ›êTŠÐd¢¡ù ™>V€%$Âôÿõ5ÎâÀæ‹z œ‹ØÉ¤!Ädd;øÍìÂ/cǯ"ÈóšjqæîçàýôDù &º•ËËÕ}X…áæõF6´÷Nèý—‡•ú{À[ÐGʲT"T÷¿‘J+`TuŠh¨íú[æ …2@¢Ê©B*}=öÕ;{ô ˜¢Ž"£F‚„AB",Š * ª(*ªÅPUbŠ(«E(±±EbÀQŠ«UHªª (±QXª¤U‘E$„QdUUETE"©H¤U в*ÁbÁbÁbÁV*„# ’*‚Šˆ*Š ª±TEX¢Š*ÁEŠ,F,QEX°EbªÅUR*ª‚‚Š,TAV*©dQdŠ,€ª¢Š¨ª€(¤U" )Š¢Áb‘VEX,X(,X,X*ÅVf/îð½~B;}0ëB¾Ø"ÑbÿfŽÃN/ûmf&1ðê9èlx^üï–ÙŽNxå%lðÛK<´‚":U€€Že6°‘d€(€8­¤Îåcˆc’—h¥˜•:MÊà9tB0åW5.“ ºećqKŠnA"Ú† (Ò~/^bîgN#)gëþ¥LòµÎÏgfÙ˜ù+ãW×ó½¿*:wiwá¶ø³QEŠ)H(#)¢À×+RÅvÓ›‘¿žðîÍ|º}Ã^:Ã\€ƒäeGp5Ã>!™Q«1Ý PÁ  Í‹Ñr2c½#†á‘±z2Ã*<уðË ˆÉ Ë‹Áx/༂ð^ Áx/༂ð^ Áx/༂ð^ Áx/༂ð^ Áx/༂ð^ Áx/༂ð^ Áx/ìn@ÿÀzv$DW ÄI$DRTÕAw ޵ßeu¼·ôÈë.sñ¼î/qÕ(*8’â² ! ‘ˆÈȠ„R(D@‚’, ¤H¢0()ˆÂ(ˆE#Š(E1$Y"ÁI‚"‘bÈ AA@Q"„R€‰ $R HFDQAEPŒHE "H"1’ @D’€‰HTQAPF@B()##$X¡‘  ¤"‚Ȱb AH,F"DH’""""# 1PPb 1 °DHˆ")"ˆ€– ¨¤‚H€?Š  6ýÆØçz˜%Mì}_ÖZè#p`iüÏ‘tÓëäiR=íÔ! H!‘B) T-)%%‘VÊÐõ†Ä`KbÀ*AIXý‹Y&%"Bʃ ¡a’¢6² .¨ª ûx*6â *%¡óG=þ- b£`§}ª*ÄŒ`ŒV¬DDEQ‚ ER#Hª+!@*PQZ`¨ÁAÇûßáç´‡ ,@P ""Š$HÁV ÁX‚¢¤DE±Šª ¢$Y!"2A`A@‡¶ÂVEUUªˆ'}(©KQ‚Æ 2Fx~?ÆùpúëKD€$Yîê&$Tb(  E!(ÄQ€ªDQ‚£V*"¤@Z‰"—ûŽÛ÷ÿGÈâ:ìöÝyEGU¡Ž|j”Q°8Û”wÞwÁQãn±2’@Pk 9~g{ÔÚß8Œ¾ÛÎæ}­Þr6?õí~å÷w¯¹ÕvÝø¼óòó »ëåP“ü¬ÛýõHðµ®7q>Žöü0‘³IÚ ñW‰dϼ¿Ð©Rw{O£ñÃOŽëûËW"™d,{ ïm£{½@ 0Ô8@â &C iÄN6·ï¨e KíoÎߺ' ºù¾§Úíý•ô{÷åæq±˜SRt2CŸ‰Ä°Àˆû*8‰ <Ñ;") ÞÊ®ÞQQ@ YÜ øüxh·ÐîCµ@CR*8j(#Ô¨£ªÒ¤(@V@‚"‚ @$IÂQF-HAL±FÊ(ý¸‰Qµ# QF9 (ÑQŠ€Elˆˆ+Gæ ŒÀ¨Â‚‰(QFElD}s¥AEn€­…Fø¡(TbqÀ <5h¨-ࢠ*«ŒPT‘DB@Vƒ!‘ŠH¡€¤Š  ,$€² ‰R)„DŠX@€¡*Y‚ˆH¤*IH€ˆ‘I © )„H ‚$F ŠIH(D‘FAˆ A"‚/ÅQF¤ÎÃ!pTo„Q£ÔË3ß Ðþwƒ¡Ó™ã%–£èúã¼à2v»þßC²e¬K#”¡|ßÕ˜Š{‘ÀÅcOÑߎ23瑯?ž­ëS]zϳ/y¸a°ÁEPsËÅg«oÏöøñ7Ì»O×RTòÁ4Ü*7õ…³ÇfÐé]Ú‡ÆÆ“šÎåÄžG]N·{ß„?·JdK"Ch¢ËP‰³’zØ/R ªÄXˆ) ŒŠ%`ª)ÂWÓ]7­»Ú{ñÍ­Ú9-¼öüã£Ì@Ló!…â4yРºDÀŠ!Qø”óxHñäGU™pÛöý²h À!¦5ì[¨°Ë\ÕG¢·w}ß4Õé-j™ÐF_hÞõ.ÃjÎŽý¨ˆæW‡¹Äg”#Mn^óXÓ¹åeÿÊ=1ûH«oñ¬¦ºŠ-½?L0òX‡µˆ€lÀë 4nŒ˜`¾"¸‘¾`{}ôÐ~ü¯Í[ËÉØèz/Ög óþGbîíbÂês=)Û(œaôq{kÃ>)T`Á¸PëökÉŸþ, ÛåtK[o¬Ðõt v*w–…©mNtòŸ¼ø†ã½Ôñ%ÌbÒâ Œ$NMÁC>lÍú.g¤^×ÊõÜ€¨û÷Ÿòb£F*1 „X¬d I"1!ΊŒÛÑ– /"*0@+G™ä…FøTjU⬠ê„Q€ÐTmÖÇ“{¼*6I?¿ûDCí Å’¶îd¢6cx¨àŽœ6©ð Œ/Ô€£Ì¢ˆ£G D( AQX\±H5séÀ£@J "@‚ŠPŠ(ÀŠF ƒEER,‚£P"ÃÇ â;4$ áH$T*;t‰ $ˆ¬€¨ØTb) PE° ¥Ä¨5¡UVÑ'zÔ5E¸4 E»™¢ kE $"DˆŠª¬bªªªªªªªªª¢*ªªªªªªª"ªªªªªªªªªªªª±Šªªªªªªªªªªªªªªªªªªªª¬b±Šªªªªªªªªª¬bªªªª ‚ªªª«ªÆ*ªªª¢*ªª"ªªªªªªª""ªª¢*ªªª¡!HEUUV€ÀUUUUUUUUUUUU`0UUQUUQUQUUXÅUUV1UUUXÅUUTETEUTDDEUTDEDUTEUU"ªªªªªªªªªª"ªªÉF ŒE*1"DŠ¢v¢Ž¤DV£R…Fh fqCnÝòŸI‹· –‡"`t"Á4 Aˆú-ý³6öª[V÷¸þ©_ÿÌY|ßýÍýÝÞï‡ûð<Ä$QC»¨¡C°‹x B 22ÞÞE²¸(£ ·ˆÐ‘¨— 0“¼}ð¨Ý<† ˆ*‡¤D'¤ˆ„ ¤ôÁ°b/ˆÕå×lUˆ°"#Q‰È³ “ VK}ërv[)Œ4ÉR0“M4:¤.¦Œ°ˆrJ&{¹§ 2V˜ßÈdaŒ[”(ór¤ÛNøPFMœ¬Å&å&S¢Y¢Ãp— ßMqÄ8eDZI©Ý“*væ•Ô&0A ¡PBöÜXqx hÒhI4)#™ÓSŒØr«V<ùJñ50 4Ä 2ŒÁ4ëZs$äI ™‚$Gžô ¸~pY@¬ xµ­À8›Ê)Ô‚;ì_Ö˜R¬!Šø:¡‰’ÃH|PÐQØL,‰Dµ4„B*þN¶È0¼W¬’\– d±"Õ5a°óPË×Xqô/õ¯Ó÷ø—Ý]vî…ú€`P;ë("ŒPÞ*1Dn=åÐÜ yG0ð5"QG!EF*ª"ªªª±Š*Š*Šª°PQ`¬`‚ dTDbÅ„BH$„@F$QDbª¢*ªª«¢¨¢¨ª« Æ ÆEDF,RQ’@hlš@P)‹$Àj¨Š¢*ªªª¨ˆªÆ"ˆ¨Šªˆª¨ÄUTEUUUUUUUUUUTEDUUUUEEUUV(Äcˆ ÁDAQŠªªªª¢*ªªªª¢"*¢*ªªªªªªªˆªªªªªª""*""ªªª"""*ªªªªªªª±Šª‚ ªªª¨¨ªªªªªª¢*‘"ª¨Šªªªª«ŒUUUUUUUUcUUUUUUUUQUUUUUUUUUUUUUUUUUQUUUUUU‚ˆÅUV Šªª¬„ƒüẊ?`è=€#¸1’ž@@D$A"FTV*„DDDQ‰FDU"$H‘‘$$‚D ˆ‚D$H‘""£`Œ$AH‘Hˆ‚$D‘F DA‘"‚DB$Hˆƒ$@Eb¢Š(©$D"Db2 ŠED"1H"ˆ" ‘‚ Éb" ˆD‰"‚ ˆ‚ ’ÈHL¤‰DR‚ 2 Œˆ€ˆ D‚@B D"$ƒ@A‚1‰ˆDDˆŒ‘‘D‘F@BDH£" H"0‰$Aˆ‘‚D‚HHMtíæ‡RvÅDƒSбk°r€âc F+€ 0d‘Fèë7•˜­0 JÄJ€Jb„8 ÙE" @EŠŠ¬ A¢ƒ1s¢ãÄFÐAÖ>`¬sö¸—ýLìäݸ°q½ªýa’M†ÿ•˜ Œœ]¹ó’HØ}-Á~ ©Š ´X˜€™™yŽOA?‹MàH|lAan8œ¢ä“?Úv>Á总¸S0Á®—Ù…oËOCzp²J@€üÍolŒ1ÍþîA‰wFÁBg.ˆþn ñ¦"@Ë)1 È«ZáWp7ŠaJ£¬TpÂ"}ý°MHd™e{Z¥˜?&–ŽIÁ 4†ö–…6Ès„D”0ÂüÄ'ó3ã0ßUE^Y…@QHÅ,Žvæ´ ¬±V£½ÐÁ$Ò6ÐFõ¹’Q4•2„«¿OëiËT.é‚R”¥* ¥ªcf¦!f ³0à R–…cZ" þŸ=x½k ÎYÕ3.03$—2˜U¢´,¶`ãâåk[ë˜a»ÍÌ Ä(VÒPX % RÄF+v“ÆI‚JÌ€ÂVJ€¡¶!1’VCýþøLDDDG@”Må$>mÍ]8‹iVÚZX4‘¦Z""1UË+D-9uÍèèðš…qG-±/kq-ZP°NYŽU©JP¢[Qµf‰!)TG‚ÊÛpºŒÏÿ6{©+€h‚*€©„†D2R” Ù‘ s†›dÀÄ|·[­òkÿóãe/ý_þù¹-ÿ«ã¨™`öÑ\:ê©.¥]?FÑNÇÚ•ÿ3YVIOÖQ–I–ô%‘ԭlj¿>@gðuóŸNêš­xÿ²èWƒêûÌ„ÁÊà0!CÞg4@¶áW%ç¨X9ö¨»ø$[ž1u{¡¸7 A Br>(ÓÒÈ„‚*ÿ0à|ÎùþØiü¤[i¬v'~ ×s×;WN<؇Ø6AÑê¯2¥d®÷¸FDŠ<Ë>]oŠ_}ë¿eÑ#ôâ=í¾ÄíÏ-3ëCÙŸM„4ÿ^Áæ!ê2]p6&[,Z§ÏÉ.§ AL7RÏ·¿Ý®éÞ ç·X5ì™’ÌÛ$k­€u2cžÄdø­V…‚ Õ=…§ÑUåm%®åíwôØ›PIî~놩O÷cêcÙ3ÙÄW;fgK¸BÎùS–(">d¿|Æ+“×)tJ­úƒÃ*küö¥ €@ßÑ‘™÷¾³ç°3íK¯•³ ݤӈ`S˜Ç®ë+šÑ ‚CÒ%à €vÏK?M|¤ð¿›³ '€" [ vóª¥&g7È*§t—‘l;¿_òÀÍC&×õ·JðŒ¨¬  Væ¡ï–5«Í.ŒÓ«A– € _4v__9°œ™_”%Çͼ=žOÐI3¦™ü­ú)FÜ¡˜…½]°•dèöv-‘\ùÏëZ¢Z—,¥` ‰lAÏl¡xQC%?ßûBiumø—+þÛKg‹®ï’U7Ñ% j½‚ºâ«Å~PôQ§ÓÜ—æÇäÿÆ?ãíçÄâòÁýü-I×Ubˆ 8£‚£*0 ŒT‚£9ÿ7ê[mFQ”„m\öã™ûÉ&—Åw¼Qê¦æ± uÚ|»Ó,-bXŸì, Ó£ Q´ˆFf~ÕÏóºGÃc’>QQKàZ¶ÝGé’ǵ˘¡ó´ž¦·fx‡–ŸqQk5ø¬>$”@ó\ߪ‚m¢£oN5«â‚£AM~ÃóîWu9®6ólU®*@ $Râ5ƒ@Q>-°Ô¤* ét]·/Š/B*8ëé&ƒÞ¿Bâ@Œ@‚,Y™»ûÚîÌCG$ó`ÒH³áR¾5J(íª(ä(£M1Æ} ¥^iÙal›çÿZ „nDÀª]FÙGP2ÔÚ†ÐN²%ªÞèJZ?¥†ôä">¢@¯ ÜryÊÀÊfÌò’¬Yצ ¤ìÈ‚¼q í¬ËgISüпÙmKàѬ'ƒ­œ,ÌÞ¯ çxßï‹ÕÞüZfa0(Z æ”CŒ¶mŸ«˜ ÖË‘=×?ö4ý.ÂÚ‡+Q…NãŒéú*ÁÀà#PWDU~Ö 'áë¶éó>æ ù>߆jn?>sÒ¨U @7PsंýŽãþ[k˜é¿ß†f£j ïKOÙéú°>hý¥—Ê Ô å°t~U‡6 ¡Q Š1ímV#}Üò¼F[ÿ¾ 5­Eì÷•Íô½ŸÂÙm츂…QìDÉ„ƒB`‘D$DDD$DD‘$@H!!"@”šÌÇÈ“/´„¦¿ â- .Aoñëxö~-¾úú™Y!ކÔ,ÇaoÄð‹!§9º f' þôûA¿å=á˜Üh Ôû³-xŒÏø»þvòÆÎ¨ÜŠ/×ÍŠ£'Ü“7ø á£ðÔ>­úá¡aþìˆ/äœYŸ–w"˜Ø |7“ÐïÓÊÄ©üY óÏ;n¦„’Ü®pUÖ|°C) ~†E?G¼–©ÓX[•¹,ÁÿŸŒ¹?>ßGÓãøœÔ<à" ]ÎÓN|[\ÚŒýç-mñé8ñ é¹Ï«\:Ò×ç–ß;^gËàUcÊŠŽëàŠ€<—!cÍÖ" ò1Cdˆ#öà †ÉÉ{&‚]à ¹ "íö¡³DÈÕW©ñ5|>â¿/ƒ…ùŽ2ˆ('6޲ß6Š dò ¤iÕ¶îmUG®Š"¤QÄy@Aõó>Â… ˜y­÷ÛÞm‚ÂÉ¡î¯vº÷u‡†aFI>‡òììúÿO3~Š‚bjåÑs~®û­ôVD?•(P’PÞ6pûܯ ¯èDƒÿ¸´x Äîê …²<‰T&î”ñJ¢HM- ´ß¶O¯ÔµǨTw!QîÊ(£º(£’QFŠ`gS®T*8A6)gÒÒkì¼öëêb35Œï°èªÓ„³¨58l†ŸŒèñ÷Ì,î…•ì¨O»ðž2´¶è@Ÿ¶äY=bâÆvÅ•,Öª²%ÜíVh§Ð€S;æ6cAqz¶D’ƒcñÿ²ƒµûM‘òfõ^e;Ýb†fA„‹š>\ºlˆ/F$W²*BŽSB|ÿê}àîtI@_þ›VJ0ƬÙ:ÊÖë’ý O\&{LÊoïõ£;¿X¡”Ïlbá;ÿ“|vûþWKw‰PADhñ¡Óg3’ïŹ9î×·ò× ûïÚÞã{(ôýû÷pPQdŠˆÅ€² °‹"ÁXÁb0QdUŒ`¤Œ€)(,Q,c ±T‚€ ¢ŠHˆ É$Äú•rÿSœ÷–‹â©°q«•æùßÝŒu¸ÁÊŠŽÐôû£ãDAB ŒÞBU÷ñ(!ETV0"ª¿-¾™ý¬µÁñਔí8LK@" ì°u}*«ñ€PãnõY0‚`£Ú£­ö;)U€ƒ` Úײȧ±ñv1QÕöCüc ¨˜"£—CÑÙ|½ƒÁ¯. íâ¸ý†Ù4Å# c±Í½­cúHlÛ; à²]6ûlàÈ·Hœß:ú 5xn7Ä*„=~š–úLŸÊ&-Óh 3ëM'áN‰ÿ?g¸l³q øŠûÔHXC…°£o„<—ZÕ‰ádC8„E(‘€o”<°ùÚݽ²Ü³~?;/Šã»‡LyëJok²¸÷.çÌî [^j´Ix{ÙºOÀ rŸѲ'Eu÷Q^„”zå « ™®·hçžkÞŒ+HFµ–`:ÁÛ1Â]÷u˜Ò €yø_ú­UËD.>½óë¦Ä­ÿÛŸeå^øŽ«Å§/BþSnW£ïõ”‡îÁàå5}hå{`Єì6ì„ÀïljóvÏy…_6Ýc°²Ä4ƒ¼ ÜzÛÓàøÑܘ%ýµ–€ßüÔU"·ˆ¬5&E6ˆQÊAÃÅô2ÅRúlíˆHŸˆ|†í,ý­@ 'Ô§v?FÂÕû°=óN*o´°S øÀ‘5Òº3*a‚Óß«ûÑX÷7À~ñú»ÒÔ!—méG'ô[‡£ÆZ-¶ ½1[µ,Ùã¸Ö±~Š÷Ú~îÐu߯ñîf¿½ÏAþ£nko“xÐ6|)£ä7j€[i~'Ÿd×Ïø:8ßõcUùR ô" îŸþ¼œªˆŠ?’÷ø=—ÚÆÕ<}6[£×y}¿åþ/&ÚzÚ¾ãÿé#"øZ†×Fx¢ÅÔëSsï8‹Ÿ¢®Czøÿ.¯vç¶[ê±Í[¸ J–8ÜσÇe{OàëzÿÝóð “!BÂΨ‘_ˆkAã Ý"H‘b( ÄA D‚"„@‰ˆ ‰$?¹œŸà”Y/Œ0@TÈ)ͺß»ÒÖ#ܼ(î®íïñ|pßÔFÌîü‹FXGy’½_c*Œæ‚æØpТt&± !¡åº>\b >Ø~:ÕuÏR爿œ¿óôŽ3™¨~l­íî@ FG¡šðYE¶šJþ¶óž|AüŒ×Šˆ³‰ÐA–Ó(­Ñ…Lãu9-Ë%»w9Êa˜Š +öÊ›:rV$Úÿ·/7· ƒ0cNˆ„‰ü÷1`¹Å ÝÅ”|5¶*³ó8È@²Ò*8Pú[öÞ³sCŠá…PÑõV·^¦‡35Œ÷| "x|×Ä~{ïDT}ᙸ®]mîΓöéþŽ5ÓƒÓ5×µØzŸä/ÌÎú~×ax½ 4CÕkEF…"IRW:N—{ů‡‡Þwé¹½ŠÐöÛÇð¨\X¸¦çUX0’Žjj­PMʪH§˜uÅ?'éÞ6ËòÚo‹Å7.kÿ¤u£3(]Õ1âŽç78¶ùØó0Ëkø¿RV<ÜtŇ÷fq±ˆwh~ßjâZP`ª®Y\hi4à “z ¼ÿ°ý²œNXK/ë×Ë÷s…[õ»þ?C”䎬§t5Ih|dðq†N p?G‰Æ¯B†û¡]K`Ñ@'÷ ‹Öú*+jž»†Å‡‘×!Ш9:1REn½—ü/‡}á©»{=õCÉCôê?Ïe÷û^s†1Ò0@‚¹DP¢(@`<_‰ú67¾øü0i³â"nžŸ_×àòÝÇ*(~¾—jÉŠŽLTsb¨r›G^Î’À<ÎB‹œ'³ôx£¦ƒiPÒD÷9œïÓBÁQÇb£w¡í~®ÏÛ~LŽOñà'ƒ5Ÿ‡ëM´v+RÌฯP@&¶'ßÑAœ `Á s€7ÿyÊ.©ùl…œÀ0üé›B°RèÜmtz÷ðp¼g+½‘å·×óÓËF¡Hbñ ­ó¾Øò¸µúAýp“}ÅoTÑQZ•?iýeÉÌ™}C(Ád7:+ùCÃGǘqEKÒxìû¾8ßà½SŽ”p²µ¢P—¬¾Ä¿›s–³¨Y ÅÕDăìßêRìö¿c•ù6Ñ{¾ߟžAÔ@`i†ݤì´]54<¼ËEB…ñS׈zq=)ÈqÓ‡QýÊö¾ŽÃlº\£(41£éúާüéܹî}FRL’Åa …!!ó|¦udh4¶q¦@€«L‚‚³,k@3 RŠGÙŠS…Íìþ‹œÏ±Ëï”Ä>¶'‰<Áâ°{¦ Œð Œ|ò…Fc:)ŸøH €&P€."üÌ„YJÝe|˜Rò¾iAQ×Hü±ÌÂWÿ¦¦êÁدOªkù¾7î~Ïg&"ýEPÒ"ð0’E`HI$„$_‚(nà}CÁú\U \Dú\OÛ:?[C¹U€®œÁNsa@D G T£çƒî†üÜH}*cöà¨ý9Ò_#n#¯w[Žó•ÁPÜnnR”žÄ-kû¿¯÷ŸWöúÄSþ°ßg÷¿Ùý ¹ªÛýS4af8l2˜ë4Iü#Â[¯´cþúƒT*Z¢6×ýÿúæ}ï®t × ý Åu'b•"£¯¨£‘d~Xã¡B©’„„Ÿ@/ÂË%”‚C!zñAÁ÷&dF*A5G÷ù;ÞËŽ÷3BAÂ)ÆBù£)[^?“׿yKO¾û)—‚– ~š»›]€ ×5 ùØðk ¶ö+×…sù„cÄd‰¦¬wÜÓ¨èb†8Òª'š'ò‚ñŠ_–B„—ZÂy¨.o¡J½í߈´€ö™çstq¬¥ÛkO›ù¶H4^¢œ¡˜1Ö¯lM·]êm.£|cn'†Q«GáH›]d¶5 Ჯ™ð' Á¯23³êw q°ú[Öß!ªðëÄC3è©Âx>JÆVÕžÀЀ ¿‡ âýaeËëhÃxà}rðý%óL²Ñ F'Ÿ¿ÈZP oï÷PMÐXv‘7þª•Á#0-s{¬FßfD  Îÿ¾o?~ÁfïýÏó.@üöI„Á*`]C‰ ±¬¡Æïc¹YæžËôˆ{›Ñ †Öº£Zòù'lX~V†VåšÌƒ¥‡…k×âÙ´ZÒ#|“Éœxvœ©î_)F”èW©¯r7f¿ÉÆýokÀÊEªy§'¯«ÊFò9Ô‡¾«ªnýLÆCš›øÿ)8nV XÆ^¯w›ž¸H5C¨'ÃijÀ»«iÆ7¬g§Xô€bÞ´l|ܚД,âm/ñHó®`L@Ð øD%W¿ÖöÂEçïFÌÔF œ4 º€÷ƒpï¦c'` €n§oô¶>3Ù¾Üü{ÆU€iöšw|!Q™—sÅð`{ïù¬î!›áùO­¼ô]öá9¼Zâløu?" l¯±ñ[ý†Ñÿþ·¬×Äp Zjve§'Xî¡òî7Tºóú­CíÑ#‹hp;å-"¥ÇMÿ ± C&üh¯6$Ùÿ?+ܬì¡ä ZÛ ÷ºQ!Z¤f3PXÂWÅéçqV³ùþËÇPÊy9øÅº¦F^ø.ÃkŽKw¬8ëÄüQþÄ‚x ç=˜¢Ž µLÿˆti²VÉOÎ%‘¼µÎtP ”8 Aà( ÕÈk¹ªˆjèÿNëšýÇ“Ùï¥Ó£ a¦'Åß­W^x{Í_"Zöq¿g‡ûx{‹Ã-ëż½3AóñS:*;òÒìB`‰I"€B).ƒÊöÿ¶à¨ØªâkBÏüúôÇ ÿ½èADÁëF¤*=Š=ˆŠ:0è¾—¼Ô€¹…ldtT¦$Ö*=ðQB€Ôu÷걑»PtDßEPMƒ¨Pðò¼>:!K6ï‘V'KEPMTuÏ=ˆ †©‚(@Äöºm>‘“ôÔ ˆ2,—Éöylå@°ø2Ür÷ŒèEMwþòóöñÓ\'ÈÁ¦g†@À÷dNóÿ³üË•âå͇DÁOÌÓ`¨ìB£`,½õPÙxŸÃñ&|má Ê9 òóózéÞŸùÿw_ŸæfkæL>A¸Ør*B¥þ’JÑÛs‰³VÿDzIŸ ;L®D7*¾ÉQGR¥ hSß?Õùïù¤ð·®b¿Œ’)Ñ2mýÂáOFÀÑ; S½ƒ¤Òiöþ[êõåÐÉÂI!!GZç2?üó³I‹3EõØHÎÓ¿’]*¯ã SˆUmס-née (—CAXÊèH~½Š˜÷³·þÂçÄm›mšÀ¨¥%´Q•Ù ŸógÇúŒiåÜGQG§(i®“mô>o !ÂïBoβ:Qpn~%—2XûšÏWŒ…¿ö‚Å NAÿ&¾¨‡¾q‘ƒYùE‚u’·5³ò“,Ïbö 2äß,î6Vî/±i÷Šz¼áÀÊJ4«‚«‡º=@ÙÁ·¶LÕ˜€Þ&ÌÖѲbsö˜Þ·Ü•Ž@ß0èwZ!Q¡ÜFÙVšPr2 „»¥¬®CȦŒš%ôýªºYó‹ßç¾Õâ9À2Ë’ u½¨ˆ!£O;AQðbßåöEG6(g„퀰2ðúÀP¡X*8B£TzÀF vTaÇÎ×û*½ñ÷{áÌdƒKƒÁ}  ¡œÅ(( PTˆœw5Ôï_ë¹_Åw(a85ËaO cW ÷ÞM¦à"àeë²?C†×¹¾î0ùPÚ°yƒ¿M4t™w±…ʃ%EJ_±:Lm„/‡² ¥–âuØ$$’Ÿý¶f­­¯ìYçe³ÞßÀq¼p•äÊXKkЇ…HÉN9}õg_¸ÄG2 ’§!ßù_5²æ³ããÿVÙ£ÿé ýÚLÄÍÊv IÉ ¢u2Œ¨½{‚8¾G„€ò–ËèŠD±k~ƒyCa×ãæ\9mãÿè¾®i—ƒ†”²XËRÍcôùiæ ˆpB_‰¸¼–E’+® ±n3·mývÿÁæ\àz½Žúr*=– ³|·ÍU|ðT~¦écümƒí¯»íîAOD€ƒ§êÀQöÁP` ˜ªÅADÑ¥îý|Š[òö[?g¯ë¡ÜƒÖ]1Gîó¿Ã–å»ý[(l¨a_¥ôïΣš[Íâ¨Þ$ Kµì!e‰.Œµk{«®Æ²¢ewî¬EBÍ#bZ–x‘©n]Y(ëüe»cBw! UOíÆ®qLhÊ£Ï{ɤ趿HûÅšïè8196Hé•VÇÒ!šRáSÿ•£Å,ŠM•o¾¥ŠeO=âüĹq@£s?Œ6&}ùÅì5ÊÁµ]›SÔpfâ÷·…ý9Ú>Æ÷1¿ îò. ò“@ œ=ž‚1pžJ%&ƒ¸[1Ÿ9!ÃðX˜gàîj·ÇXQ‹¦œ?'[ï¿ózÒòß7ËǺqûv ay08A°Åd Eè|ÿ¶ª‚vàƒÜˆ‚P[™ÈÔËÃÌñuOŸÅžÈ¨Ú¦éÃÞ­Ýw¼?Óîò ªÍåŽ`úÞ'5ôzaCÝfòÎ;ù9ì^«‰Ì­þî ŽÆ=^åòº¿FѤ‡œcøZwI“‡a­³zˆCÑ?Q°ŸÛ–±=ãCNGýkÙÚ‹ãëÿ®[ÿ¬qÍGÄ(rŠdªÖËEÂÝU$ÏŽ…kŒþ¿î$œµö{ yºUhOÚÆª®¨±bˆgÌF#«1އx #‚7¼;½w»žkYgß`±ŠþœÝÏSÛøÆb`Õ/­'¬dßÏß²ÙÚ§  Ÿ‰ 4Ù”vº+Ƹ ßáC(6>lDWª±Ë¤RTûøqJíuºDtKz쯽ÞÉ㊕Õ;¯îIz^Üãû/§ò(ð„JÚTË•kQ:¡?­àÃx,)Ìa6ÜuupfÁsÝbø<%É–ÈKû~ØØ@¼XBةɩü´;p”,’¥i`ìs`¸]…ÁÀ{&%°¬{4f&B¶]I°6Ÿbª8•h§†Å9Àc~CŸûÁGÏn%äLæ:ŒR‹…ë}¯p«!΄^1¡…µØ]çïÛ…à@,ÇAµ™‘Îí»]p;V¾Cöðýÿµ˜N:§‰§£¼ùw ^<É„ÿW _ëÝÿÞñ9S„ôЕ¯Õ ”‘|5Ž)ÝsF÷•[Nc=1lE3‚“ïs!é“ 2ó¥ Ðq“ËoÊz‡Æ´d–“|›±ˆþ+ºÂq¢/Éõí´šÂylŸn7%ªPÓ x—"A•2+> W5”%\@ÓÛåG‹iõþ”hjoŽÝÑaÉ^ˆyÔh1  €ˆëó¢`eѱèEGå€(…e¹ZÉzø]/TCz@œÕ¾ÿ¢ü×éhs¯/å\Œr?Ò¦>´õôü¢ô¬³3מ´Û¾†‹|ìþ¿…ŸÝ2ù[ÉÍ“714©jäÚnª¨b4 Å"Š3C :€°1 â (UÃó®¡Ããt\_b€ˆ®€"† >óÑ•ÓyåªþÞuªð¬÷‚†Høº ¨ñ%†o o,]š& ”þ[Çãç½÷É𯇆ÔýªÓ„SI ’h@Äë½jÞÜýj èʳ‡¬yOõñ´û½³åÇ š !ÝÊ¡ª“Àé 'BZ ÑFE러ä‘ý¹ü¯ö?¹éìç—ӹw6ï28õUø¾J„&p¡‚( }´ù|§ÐMæ7­Î;uú7æðÝ&S™ûÓ¿¼IÛåú±{ÿQIE|ßê‡7N÷~“þê$—Ì0*‘ìÖZɬ¯¹aÎãa`Ÿ¥Ã&oŒS,îÿØU®<Á»êg54X’ŽÀ@©‚¥!~öñ€bÿ>¿ !`Ò7̶q³õ^|”¡[vq&ó`È?·‚"P€ªyÚÓÅêØU4¼f4¾t{&µèµäòÿ·¬íï´Aú~Ï”‹.IméµsÀÁƒé®=_§œõµ·YŠC~¿éââ„^'wÝ*ÎòÇòª_Ïc}Sž{ü” R”Ym!-¤¶ÈKi h[aZ hBÚBÚÙ%B¤–ÙÛ!m$-¡ZÉ- KhIm’[BÛ$¶È[d–ØIXT¨T¶Â¶B6„-¤…¶BÛÛ¶mÛ$¶À-¤–Ð++ +RT…@ l’ÚJ• h+ ©%¶J•­BKhTm h²Ò´…´¶’[@µ¤*©P l’Úm¥Bªªª­%¶I-¡ m%´–ØÙ Z’[H[BÛ%´Ki%´-°%ª«BÕ[$+RB¢ÖmFÑ´©m’[H „•¬­HÛ lm„¶À*J„-¤…´-U[Õ[‡õ7'ò –â*…½¿ùý‡“×H7 6BO#øî|¨&ØNÚ í=ÖS»ÂTDˆ‰DxëÞÛüe:×î-cäc”ѬÐ(Æ(Ç(ø®BÉiàò<¢ƒ¦,‚Z¹ü â¢Ò’`JT©^1X¨ôlu<É-ÏÛ³ï&[¢së@$˜TQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE$%  •Lé±Q#¿•}^¸@ø€_Nƒ°µCK¹w[M€bG4ÀL®Oh’„Œ’Icšf >jçshÈwcÄÓ19BáUGÆduË6º4g˜B‚8`€:¦ÞÕ­ÅTšì1—¹Ïö'ø·ùa})R[’nºååJ›¡–ýcõe>+&×t û\;žéÌŒA†Šû$rLÒØ}g¸÷í7wYÄm¾[gr’³Qkt‚-jï#%-NFdEôQ¾ß¬¶O·vW#Mˆ×2¸~´4òJJSyvÕfðTYðhþÁ¼!e0*óT:\.·ƒ°éƒmQGmÕxN´}ª¡@Ç G^ÈãkåhCTÏñP©%«oÒûó> {ð>ÇYY4€d®ÚÂN€‡&*„EUK`¨ÁT‚v²¡Qîf˨pÁQ(TCýÖõ®O¿»p‚·"sŠ €@Aø~ÿmÀT`‚*”ˆ‚„Q"ª üŽ(\e&(]ó4"Ü áT/Š×YïjÅGëeó¿ŸÓê¶PT~®{[5ù)¢üûˆDàÃÿÝûD+PDX "nà(Ž€ Þ¦À°*æ 5Êñ½ç?VCðªD ;7£Aj¥S#¾î$°‰f0Æ¢4)@Íi€¢Š<:¿.MkˆÜ·Û çA¸uFO1B©ú ¶ˆ¶)£‘Q9™ ”ÅÄ[ ²Ò¡b£jÖUB¶"¯Ù}ņ†W$%) Hbe_Kz¬:â¸ï'tS,¢Žþ¨,QFõE1L©V$ ¯ióþíù;÷¾ú˜Ki0AÁivúl‘ï‘<®jr\T`^®r0ij÷»Œ×_)vç?~¾ÄQ.¸Hè1qO›!˜<„üõïÃfûAµ…æø‘õt/)ö†:8zr®d¯ òh´$Q\Œg>ì/>ï–´ÃiMˆ²‚¡¡Kš+y¾g¨ÏûñoiÍEòsiƒ ó¡ÜceõLÒÃHiüÆ|ŸWèø=×ð}ŽÇ—!‹¾S‰ÑGèq±g‚|þ5ãBV`¼6,Õµþvo¿äzX["tÇ*=^7ùìõŒýí|Ïàå}Éþ=ÞÏ©S¡Ss@Ãu"£Ìè{_;¯÷Ý«§¾Ìá÷<.3”D;éæùù'êëF­9®øw½n«ß‡wã7fÃüÓDø‘À5½±Eª×©N—ñê á$\Sg¥[…G#B‡BŸgÃê~Îûµê:ýO÷<a4©úkëÖ?_!ÅuPªÒÏöCo¶ÏMŒbÊ—)“JkGðck­öB­¥«¨j.[¤Ò>:÷þ!Wy,ØF‡j~t™go‡•Œ¥Š•›Tí,…&ó­P¼ä¥þÚt!ŸÚo‚’dšàÝ4Žî­»áxS(ù«eÝåÓsîb‘ÕT®Ð}zñŸä¯3N¦²Æîµ( RŸþÎ"WÒæÊÏDÜýyÅlÜÁèå9Ä?tOµÁ×?®7¹“úeý‘{ÐŒ­ÖëÖ""Bç£!ñí3ù*³ÇÊ÷W’ü½ïÖñsÝ®k°Û77ß„] p‹Ÿ Du—ÏP;öƒF˜pvC‡ºŸ®â\P =ÑmÓ}+쥲ÎôýYæ¬E]þFÝ ¨2í·«}~)æ7ŸWQ¥g ’£ºï½F’¾_¾u˜á\©ß0„¦öçDjÆKiððÖZÃãIWãhÁöxE°ndm–¯°±cBûîM¾¥³”,$¡Ì8EjþÝ,oØ*©ðW³û¼—LÑT0͘ö¯óµ\Ý?{Ì›ò^ðÂCÞ70Á½ìïÁÕ~5¾¶qñôñø ßõÁἯwÇ÷œ‘˜o%ßsœ÷SŽÜ:ˆ€Ûzq4Ûg:˜´N»·ºò¸ßUá@úóTz¿Ý½©|ÏùÒJNš°=VG¡’¯¹w­Œorìפ£v#õò¸r›çZ$BÓõ2QÁofª¿¬„Àüs/dñ¦ZûR/‹Ñᆱ#÷[£ †÷öêQÙÍt¾f3S_xÆéûas¡Çõ {ܯV]$vVB;Ho¦*óðÆHÁÚÀ%ÄFUH—Bø#œehªû‹w~üˆ†Ü”upóP—d:ÍÃÞÚÞP¢ª‰=…‰Pë@Ø+ñÀâ»TOŽØ˜Âc@à÷Ït¼ï„ ¶›$è3½ ’¬ðs’Ÿbºë*“ÈýSãMG–¿8ö{mU¸¦®é«Á*…(€˜ @vCj$Dmßd*&­|³Y©¦o*RrßÎìZàß@Í›EEA2ær­Úb‘DÎÄ~V!r[¥©ZCÜ0-Øèwú¦A}z^އ?zÀÂj<@>$ñjÕZw‹Owìý¡ßî®è³¿Gìò(z¼ë O×d$\r¥;ñ|Yé¸Üx38  ”_²4YòéŠhè **‚ ·€¥K‚Z›Ihïix¤q;aÞ:øªŠÙôü» Ë%Å£Àƒ¡#šŒDˆÄ¥!›¿'ûG8;ñDT"‡Ú§(í8B&‘¦˜Ã6ŒÐäKô€ý38Mýfpë^‹³—F#Ê,ŒxJ$[¡‘©R ¾™ä…¢¸ƒ~[~X` vnÈ"¶ƒA°{º ÉM°”-Wìa™tA?&æDª¦›§Þz°oú{>W[–= qÂm à ÿCl€¨Á³ÞŒËuYÅBa°C;GË9qúxŽ3¾Õïý‰±S‰„’I$’BI ˜¬ ŒùÛP÷ÝbPM„ÐzEA¤Söñ^Õä-åTÖ€áŒ$$‰’€RÉBJRžÇÙüÓwxÒn€Ã¸8ÖÑæýž7 ¸Žk€Po„!¡äžÑž@¸;ˆ?©ûŸîz×2Ä£ùa Á÷ÞÂë!ºõÎàõ°øddƒPð,®îüã…cùã™qbû~?™Ûü Íða‰±°1 _ƒL:¹W]URº$ 5“•+f#ˆéŽþïô®`/Š®*<}ÒýÖBœ?Ÿ^‚›÷Í@Ôe¹­¹~㬽‡³ ÌL€isBùRq²±éR_—Ÿ“{œL´3GùG0ƒ5¹?¸‹É"žyùË3ac®z÷ÊAÃ7ç~8¤¬xk¡×€ÅãpÁ„%&ÀG艰sWí=T?.›.uEòå4c[’¦°`äm.ëNj[ØtÐÀóMn!«RWñó|?F]½×1ÂøüËî–ê=9WÓáýx< ú÷È÷J3¤ªc1ìC"``b!’‘3ÖÊØ(–ˆU#iJZhЉ¬Vh2âŽZQ¥VQD’IPIE¤¢ÂE“²¨´´‰¥ÙÁ)Z3F\p²¾‹ãÓ­ã£Í¢«ìA4†sìþvqüPþ‡×sðâu‰¥Q”¥;[-1ˆÜ¸Öª‰)-¹•Ë\0 È™,¥)Yˆf3|7½èØ5 ®a‚?ux"¨OcH‰³À!Åÿr&%â"ðó7—‘<ÔJš¨Ü5¢7E”Íae¹¬†õ°êì4Tâ­V" ´¡ÂÛúmX[ºÎ]DCÀ™Äɳ ’ɶ!áïïk™œc-™¡´!­Lid´(,×Òùý°vÝ…·¬Ésç¦òúëË󹻿Ko ó½¯ýý'ŠgH0]2Ck –ª¤ P·Uf**Á­ÈpB`º:/Þ?æ1d‚]V „Éýø™¯ºÊ½ÆjÃBo„ùW°¿Uz'å™Å¤kt^•œÿg¨^3Õ€ÓÞÙRб„\AŸ«‹BIÜ¿—.Ök*‹J‡J¸±i?êò¸}Õ)nº"ˆÛ8ÏÖp …ÿÂwDD×tôžUž" ÈY© }ŽÂkf*#R=ÉZ¥÷cÿ(jª€ÒRMÝÒªJ@60Œ2ÒÛ>^0Îø¡ $T0ÁÜq"¡¹ñyöO±BÜ\  &îE+ ¨”Dê{Ñç¾ýߘe`Òs{Ã!a(ØSNÛfг`ÿà †jLÁ”@ƒ2Á}Isõ¦FK†Í{"‡C‰ž 2Û^1ØøHó³˜ÑŽ_Ы!¹¦ÜÙÛsh L,^Öf¹±Ø_¯s98¸I(9L·ò2bQîDCaCÀ€MÈ@©f¥Ënj‰zD\NÖ üzÇXxŸ9ºŒ‚ð;E\êCå9Íð=—•™€RÖÀ®W½ê°m[V¯ä;ȽjÕ«ÛiÚ… ®²VFY‡ðÙÊ3<ã¬:ÛØ8˜Fõ–¬0Âøº>ó«ú¾ß+á}w™çP{&'9º†ý°~źŸR «grò¥?æùûO²(¡Ÿ@âŒu¦7Q•ÀQD㧘}ÃëMÃô —ô¦w‘ðYx@÷¹Ç+õ•i^&¬qÂÖ÷xÉEù[9.Uä·i@8Ò@ ú•TÇë v:¨¿)ÑpUÆ@Ù÷r“`zw✋IŠP©*üõ´Ë†àñÐ6`庈`WënGMpµÂN¦­tf”03>ñ‚Ÿˆ$éÔêu-–v-`Æ‚ûþ‚ˆ­•Âáx¨Ï°cV ðÙA„R%GĈƒÒ}ëë8´»âQFWMau¹`ê[@¿¸‡í03ptUÜ‚¶à·ø¸aö_¨= *D£Wù:†¢Ž%õÍ\qI…•%‰¼-Ê%S"Á>sÇàQx%¥á€e‚ÁB¹ nä4Ñ®Ê\£˜fJ’±)eQ‹ ‚àz°®™åuXt¡ÝurÅ-jÙ°¨6;e™´›¿¸ÿÚÿ«þi†o¾n Ôq‡Ò “è'€¡œEJ!C€@ÿÃÇUÏÄß³ûøf΢ŽgóuåñM.7Íü¹c¼'Ž>Çð@¬'q<¦P+†¨d{ˆ¸| ÇØvr¦a˜n›V*ëRƒ`ç‘Ë*ÞZÉ%p*ߣôÆ"Š8_é{:3ÆúYæ†oÃG÷ä–ú¢äËÏžFü2%ÒßîÐÜ»oµ`Ú»šaFUúb:cikNˆpE çŒszÒu™‡ã6iµ«]yM.šâ7å2úGJÛ‹n*wŒã9éÆzg¬M·Q}ú®ÍNº¶ˆÌçŸ*Œo]˜¿-õÎ…jéº;ÇövÎ.هɻÕó€@”ž÷l¬ZÛ-¶â Ú]TÙcwc®µ¥ð^ÁƵÿ{©ô=+Ò€¼‰Í€`-„`ߦA X2ÞwþÿaºÏV„$i•*nŠ(ážOÉû~ ^„mîÒ@ç¤B<{%B,*k_—ù¼Ý–(£õ8¿¼_¡"Š6(£l/ð©EG*wUâŸÛý¾ó÷KAlΆZ@P2Ô(X¨w„e¤’IXe†…²ÙŒ_‡À€iÎÑý2|^½ÿ¾¿ÌÝ’·‘8›wª©c+´µå‘S¯‚ ¾•ìˆØz@b¤öpõΪÍ)³6ÇM(÷s„2oÒrˆ8C±öM99¸ð“›þºõóàçJZ'¼Äð*$8BÑ7LL kÙV¬K&ýŸñ¾ü‹ àGwæz/WfW‘á2Êî—å»îÝÞEuø4§êÉäp¥Pȶìt“0b=ÒŠ:ÿµ¹óW@¶>ÿ]~s†ã²»Æè¾EPMŸ^’®¡ ÄÕLœÒ‡xèvý:Š6(£¨ÚX,(£ñ0!1,(£XD9þ‡X»‡£ÚåJq·§‰z°2dj È\* }E•vì°¬ (Â(£=ÔnÅ¥íîª(ׇ‰Þ8{% æ²uÇüiúfrD_+LŠ ƒh%†îÌ!†{òB¯&Ä4¨ÅG­G /Ü µÅ.(£²w\ÑØôòŽÉÞ4·(…ÀÔ+gëÉ ÊFWÇæpïCðN¹è'Öü¢®UéÜø¶Ä ·Ÿ}@ Lõq²)$€cÀ>Zü,se›¼Ä3øê^X*8XKÛÑN7?×Ù ÃÎAÝRR K@7êûÐÞô·âl‹ñõ`Ä8úz>N«ä‡þf‚Àè)šTõ`(T*4ÓeïÉf0=i凙²H¼z“ŽãHˆî†Ý›Iérì1ðx¡bH…z½¤DrìRH^¡]áԡߪX•"„$›Uj" „¬APÈC3 b&„­ih`‹ž3fד£€:çBHNzÈ àN‰ †¯%·¤­¡€œË†•›JX"%[Û …7W,ã˜)¤Á@„É2HO$QÁKQ-™'˜SG¢6ñ(Æ+{Ý,bb¤QC¹k:²{ iv†x7„ÍRHK£W¡$%2q§33 sŠtšJ“ÉšÔ¤Þk ƒ§¦BŒ²@fí„pªp×3oñ†L8$„ÈoúûçÔ„uâpîóÉzvòÑr&fØËŠpÀ ÞˆHÂà rÔ|órW-Ã)˜¯ô[•-Ã1Áw1TúýCùânlø‡ŸÒ|ƒÞvÉÎMÌ""d;߃ä˜.j"Vd!Ç;‰*ˆÁX/ý²BCÔµ@|f£fÅ #G!Ý8œÍ„¼dRs¿I&ÐRRõúÓ!’ ƒÙ¸R„ ã|CöN=¤ßÍ{ù€I©C!<¦s“ÉdÛŽy9Ê~ ')å›TGIY줱€‚±Pc«°ö$`„—‚ß×Àu]EÕ"4$F}í–™Þ˜6Bë èI"0)X…JžÒ@§³ã‡oõõ>qh(KëÙ¾t´@AªRCžÂ7ñv[V5M ûBŠ?”×®áK€ünÎwS(%6ʹÂ"‹%ôÚ‘"ŽZоÚ¸Rö¯JzšÃã •Çæ&† è* €õ |™vòiëo[ù—Y‘ .ɱÔÞÆf61ì —ÂLÐÒª.Wj*o¸¨Ï E}21ékcÎ>ŽC”ø¦O×ÜÝ„u„PD„;ÕbÀ‰€DDPD×n jŸÒ8¥GÉv‚néÜäÙŒÙm » ïxÖ“( Ã†ã ©³’oU^B›ÀÆ x™l’—S.C3\žXÒ”)‰˜aŸžåª0^¡â‹"^ª/Bwt÷Oq¼µ†åJ# á8 bVñÔžNP9ƒöЈœ§RùNg×ny=ƒP€LHÁ ‹@‘$T./dÀÁ* ‡ÖHÊ—LÐ`ÑÃè_(.ßåÐÈÕà”=>5¿>ˬÁåç–$àÅZ-Ž«ƒPªm Li{_ãX:B=îßW…ó¤“ÿ½ð*+rÉ€QpÁ‚FeæüÙz<abn½EƒÓ ZnÕ¯³‡«Î½Þo,jÁ¸„PÜ'-~ómQc .€Þjƒ3V/7’oFìTE’­fÛ+ä3ïqxÌ´‡Go2f±IëÊB=neõÓŽ[Q®ÝÈfU›œc5­ D7iÝÂUd;äÓè> ‚‹uS2t¾umwM²üokvÜ:~Ã÷õ}ÖK• äóÕ8iX¨s1Td@9ˆ¢y<Ì^“…þ[Öëo•èCöoæ‚˽×o1d mv>¶dîV”>+â¿ ¤ú½7ºØ/ï®ß÷|ǃ_Þä·O7ÉÍ㡚‚¡¢ îßuÖe¿ÝÍ‚¸b(Àè lPD7Þ?ˆ&}rĶjð"pñ@5Ei„„ªRBCÀ»ôbNÆ"H ›ˆ`ƒíÜ -†=[Ü>âûm  ŒPÜhª¹¥©ëÞ=iØõù.ôª²ªPjˆlñ梣er‹nm¬«o1{ÎßcÝqmî¶ôrñMÒЧ»µjË7 EÄ ¡"© àÁz!ôC2-ÅC™ia°§ÕAaïgKòî4ÝÊQ:±Q÷5@0¶ìà€[ ľBéy;"Ó«Bê@¶8©XPöóÆVpPu𳽺/í!º×~Þ!RP HÄF*°²…’X(n–6Vñ”°9+Â\¸0!BEëâ¡uÕ”Q†bx% ¡@A"yUÕõá´T3€@xª-û[yÂüMeÀ#FàP°>[¨£t?WÄ¡2DÐ<'Š@ù~Ðô ªçàÈÈ’.­QÃÙ¹ {þy¾Žÿãð]>¯×ãoÚ¦¾sŸ÷ønÏþˆQU³$çºTlIV8Ê>¿žEj3ýÁfŸ¤do)b8á‘^3‘ÏÍ1-n9•žešªø@ÉzÕë ú‰öÀß!QÍQ®ÕO™¶0gÇÎx×<›Î”&jšAô>}~U›KªÅFÊ+mÏ3††8lx/ÎB!‚k€ÄDãzüÒÂw)…õãÔíÈÎjÕ ¿k¾Ó“äï¿.'fŒÀ²”™B©ÿ|ˆY!­ƒHØ‚ ”• ±‘A¿ö?©ùÜï·óò¼ÛQ7î!èâZhɲ‹0HZÍš^† ³lDPWÍÅ´±’xX¯vExƒ´±w?~'£©¸ñ@I!’" ¿>€4lrc£Elÿœlþ†Í!…UTöÍ׿ã{Óôvo°ú¯îåôš¦[ÂÁÊп‰J¥:Õvâõ£³¶0Ï/iãz§Éú;Ö™ ÇÞçtØ/Ãås˜™[£D;[Ö¨;-˜ ML;òø[OÌÅÌbz߯Ž[C”.Jk!øù.´{pï}E’ûÂ>)ž5qõÞòšmÅD D’@`E4Á ek+ Ô¥ 1(×&ø¨ú¶¶·¦.X‹q©Š½ KE+Ð; OêþÇ7ù>ö<ÙêìÉѹ7/ò]{šõM“|Ї@±GÛ%|Ø–áK :f2É–iÑ¡Š %Šº$„²©%¶ˆûi¹SÇ#5ËØ"jC¿øôkÓòÅF¬gFž;–,Uämlnæ>~47sO¾äƒxÑfÖ—T9A¹*.í°”)£ôðõ;"ªÈþáÚ®Èsk5›n°aKŒ'¤4"=p¨fã‚Zû÷ À¾Ýƒ¶®lphcmá•ó©TxÖâ®vÕk"”k|–´lm§ç®½¡À`ªÚÑÃKܼSb\i‰P‚€³üßôxh ˆ6YUR (¬"G:üHsùØ ¤x!@—±Dyr¢T ‘êªMÜZ½é(œüßsöDŸí\®ñìjðXY=8Sä(6@›ix`WƒÓùÐÞµ 5C‘3#­Ü•1TCÀ¸ ÷§4„©¨VcRX±b‹(¨ÉRr¶) DŒª¢F%D¾å}•lã8f±NËQòà HzâRň>‚`É ›dïB¡uE‰*D7*ˆÚ&‚(úEˆ;Ê Ýç¬û}éH Ð$ o8½­V'¨#"]ˆ¨3ÅÍÔÃJx§¡>¯ûþJr„>‘÷Ú¸²¢[Jç`Z® oF ?°{ÙÁ87â5$—´­DkjX"î4L0¹rhf‰¢™ ¤ŒaDATX->{¨ i”UGA,È’Ld‰¥H2r`Œ"Ɇ,?««¿èøÐÍD³ïsÚÏ‚ k!ƒ¸e˜Ž>ƒà8»Yž‰$‡'‘ÿ[Ÿ†4R/f¿~Ë‹F€M…")ÀA^æûeÞ§—%ÏÇ1üÔlë·ë'z„_ŸŸÈTQÀ+1_óV‡1ËÓZú¡è­xPÂT=(ŸŸ) Õ ñ0Ì|}ßv/»ý ,UÙ#œhªcó•àžøQl+ȶWëF­@m2ýýZ‰Y6ª6{ÝØ¯f8âí¬¸S˜Ž×*‘„$eÞO#¨òwÌî7³ù·ÏƒÞ¿ÖÇ£Úç¢ýÓf‘œÓ0`™Ô¢@¦ª©þf³‰¬$öEË K˜A(X¬Õ±"‘ÒN—`s.„JÊF!–þ¥å“•¥00 ½ÇHf…ñUа"  >æÂºUy5ŠÁz!P"qZŸw3¡j¢ ÇVCfvõ¹«9ÞY7"ct¼Ð„Ÿ—Áv2¦¹jLç›71Íí‘U’ÒˆÅvZh¥H²ó…§PM0±ˆ’B,€(tIQ„Qb¬Šle(ÓL ˆüÏç}8Ò¯¶”üs‰Š‹Þ/j{^&*„UTÙTUESLcJi¥Xè>HÀºkû¢ß;–´B`ˆ" ‚Í ¤±„€¶Ã(LÝÎ&|Á‚¢'ÒÓwÏ÷ÿ¤Âþ•ØÞj½’i$M=éŽ2Û1M¿ƒAó¹Ó¡å±ü/Ãþ÷ œ c(+)J+DÀÉ,6Ö³Z×[ÁŒÕxæ„Ïu³žôç›!í¯ˆ‡Gªj†É‰Š èR ‹’_[tÙ±k2>E.^½Uª%S|QN—u‹AV—¨^‚)Ãþ²æ1‹Ùõ{hÀsÖår¶8ÇÀò2ÿ"„%1ÃÝüº®êî¨<@ ¯ írÔÂÇÝâÒ "¯0à-Qh´üCCÂÙÒÃizK(°¡w¯¿÷üJfûïçþsÀô pùÜ(ïwpwˆˆprÇ8„ÑPEÇ7u~lýlà/¢ZÅHDI„ˆ­ºÁ!WínÅÿÉù&¿+îÒJx †ñØ‚—Ó÷ŒYÙŽ^H6nH¼yX•aK}¿åæðªHæ‰ñã E’”’‘‚1ŒI#H!Å”?^~Õ6C8”Þ_(Š9-Þ9n€oˆZ¡yî‘ü·”s¸©4Iùy1ðCÊù k†-PûvÄFA‰z‹C²n»Ñ¹-gž½Û:}W{$„¦ü \ÐîêI ÿÛf"Ý¥¼hC—„8ùÁ,¢½ôu¶ç7µ¥Ô5‰ 6¦®à€ÑÕ|àÑ·øÔX7é­Ä0Â@õî(¼„ȶG±ˆïAÍæV~?·Ìv`ôˆ7ÑPäÄNpÅúŠÉlmä;`¢Ÿ,ô™Md4¾¹&¢:C•,S¹€°½4lÖ…Ä1Ê8Ð6‚VNO+™=vk¦»± '\ ‰ÎÙŽ´Þv§+` ·ƒÈñƺ÷”æj²ó{dzFóî…ƒ7¶¨mn®àþ1gå'ô”—Øf7EÊmt[b[4ìt@:H­ºm!¢ÂÍ¥'d25-IžœàLÚÆúΆk¢‡ft¸§mA0Úp"ÃmH(ŠE(MeAlÞC¥8¬æ£&Ê4M(UT­—Pª|¾[ý3•1KË$Ä ±Ée@r`†fÀ½n[[ :y)#ŽºLÙ«J[åN!A ¥:G| V¬ïXꇖgy°ÅmÆ€´xż ÈTOMÎŒ¶ÞÜÁ´Ú&#$v$Æ 3óAdÚ¡Íȱ@îð%€vœîù—,¡«˜uCLÅȧ‚^µo.Ê#äÎëÍ ;NÖ`"÷b L¶+9.k“0Ì4ãhÆÊ^_œÑʤx4§YÞ×ã4éõm‡ÕF1‰WÒfvänWqo¶A«°ds–^š,Î6èãáÝÛ™ûïFw3†uu9YÚ›fnãÉ&w^Ñ Êí:•Úm4Í&]Ø»‚fmM Ýß5¶(H;&¸9à› hM-©²»¢µÍJa9ÀÛ5i–†ýmAÊ]´NÆvrv´1I–ã‡ãéÍ‚Á,ÐC·¶\m–À„C„8hé°­‡¬í´/.: ¹0ó™çCCÙ’WUVsޏéÆE–Êz­Û‹l÷¦UÐâ}Ÿ[(§¼?XxÉ£°’ræüñ†ƒ7#E+ , ë;A—ƒIØÌÚ "8ΑÆ4‡'¨Ði!Í–Gû›ÿ[7X¾‡mo3¹Öõ¹ÏžL_Meg[ZLêbõ©®¹1}.30ÚviEåMÕ UQÍì%k>¹u°Ã0Ñê‘× ØsCû{”ë.÷Ö ¾è(X“¢ÏÉ?V&ºÁɹk烾ôE®¿5Ôÿ'Ó×[èüY#ð¸cii`ú_°[C`ítÎsg¢ë£Âu Å4*æ-ÎÖ¶ÿ§ùÝšôé½M¿cÏ–ã3 ݋Ü¿}iµæ&¿sÑ–±L¾)-¨)¡m2C(*7/°‰ûù½¿ÝòƧf͘uÐÉœ·ý@ë ~ïÇÔ`ãG$RdÊEÈ¥d®”•úƒ”YE±K,bZà Jåf!‚˜†“S‹\IŠ•ƒW&:’¨„5¤öt"ªÁb Pî \ÿ“ûŸn>Cé‰r5õÃ|ÅjÄ¿ƒØu–À´XßV0©¢o‚tK_–ºi´k‘±{²ÚW¬@Ù dÆîÒa/¤áú•˜ª8ÿC~ñM€%¥ Cs¢ˆQR'Éÿvµ‹„nXçInÑù<íM§]‰ ñ?·c¥§ˆú·.C`ýö­x ×è®|…`ªò'²à(°B’„°RAý¼S€€!š½€dF0o~o£ÞðŽEÍÜb'õ¸JÛå>èXºø@Á¾/ƒà ñ$$»}-¢KF^Âãl5§VüÖß+¸£·])BLö¡i¼Š!Q-4,€]w·PáôHÜM2J):,ª¾ñ«ÇÂç»äF¸æi•P{˜TÆ¢ ‰A8w8ftc †<Ћ` „zJV‹ô ØEÁ?x_•Ps˜ÙµA¢6½Ä†6 è'çÉh»ÓÄk8'¨ß•Ýò½}¦Øc^‘ÍYvó´gævÆ<0jÌã{W‘’v!{N‘ì²ì¬Ò‘T¨®Ge¼8aDGr3ÀIz´Øï¦¹ÐÝ@mn-Kc ]Í–!œ}Ïo„] Ì5ÚHª:Ϊö9É+~* w rÂ…' °±Xäm©4TˆHÅŸA4-ëliEZÂPPn‹-#e!“åkCc† ¸%Òuð Î;¿dsØÍL@ð‡Ž½ÉoOMH„×ñüÞ‚,Ú °XK­Dh­<çúä’ð¨0î5ðÂH߯b ›þéLù,QF!ž‚Ú¶¶(îµ E‘fÜ’\.[ˆ¨ô§ŠH€ IøÞƒ”䨤X‡!+ lé0äø…}j<âo"Â:…µÛÏOœÐÖh|>7š/ܨ8Kgƒr VÀàó8 •˜ ÁÒ'`[Ø0oÿ®w~Ínù ¾3B£k+j™™ªÒTilT|¥°ÄX@˜Ì{™^èzýÿœXOü„òÛ½´Mž`þòQ‘ïaùå°/ˆÄÝ <°ñ,Hƒ, ÂÅÁSÈcT›¸_g°ÃsAãê%"Ë– bAâY:ã‚`0vB°.¢)³Ma£êÅb ,mÚŒ¹^{n7tËשCl’ÍÚ³‡Û!„š…ËgLÖ7Z1^m52†+”ŠGŸ3Z8nI¡7ˆ¹ÞärÊ“(J©¼¯Ìȹ—ôôƸà<µ0zŠÛ`*ƒTuo^úö=ã¤Tpv¡ÑwMG»Cßî÷2lðÄ I‘$H°!uåì€êÀÁ‰×¼<”·iã=p ªH3匟,sÛñ|=„ÈŒÊÚî›`b:°;Rþ-î()º3Ʋ*3Uª@Y¼X¢ŒFÁ !Ì$F",ú>¤dQ^6“}\ýÙÊÏ6D’Ò‰ðâšl’@Ò’hÌW,£E[pí„„Ä’-KË(£bÁˆoý­¹¸¨£JˆuÈ%,A Šk€þ5î_ÀR´Ä“H)"®Lã{«¦ÒÞâäeLQ‚.‰Få"J=í[ÚïßàQvLdçÐ:z´.ÈBMñN3©eRƬ/<–“ÃC¸$Õ«Ÿ.Ó£µCT 1^¯‚͵µìm¯l¨x"ò30Ï(J×´–5 ˜!ß„3AM¡vhWæo¨_}±4ѼÚu‰‡—ÑTÜh ÛжÞÑ*ftÍÞÃÄE­mÊÝc–š 0¡Œ]YõS²Mgwª†Ë)´68 ºàåƒ:™v#EË:Ç.,'tƒš &ܶ4ά30Òo¡ ÒÃV˜gx°ÜÄGdë8@Y¥¡ ö8 @‘TX¬‹ÇœóÙ’ø8bBIOJ Íž%¼˜šÝˆsƒ¼Ð×`‚';P# ‚* ¤’fh£dý`âõ¸Ï;,k(t`PHC<*41ºŽX¯”ÄI2êáÁ}¦³PÄ5Á ï¾Ü4¾ÝiÑÙZG¹ÙVïí-¶õUS2­ IÏZY°¨ðÇ S¤ˆàf€Yˆ$X0 pI@Ôf(ÆÏ Ye7’€#˜: v !žì~E¬{Z¯‹á0Ý–}XC1,ªÕÔî…oâûeÅf|òï¬éS&#¬º1%µ6¶©äy`‡—Ò’xËßZåkÃçS |ékil&Úábƶ ÃŽ]^ñy¤ŸMÛX¦Y×N64Õ­×-2hì·Äh¯£°ö\¶WUŸÁ1G¡ÁÑdé‡{?)WÛ–]WÔ2n6N9\½ìµH”Îaj1L Ÿ6ÕMœd]\bì ž®®†z%nžÏº9C¥DD<.pêÊZ2£Šx¨ÖoWŽ"Ð$H¶ZA³¡ Ž—™³?Zš ·Éqãjm„r° ˜kK” TD5;EÐÞ…°@ ¶¡6ëi„sv=´Õ¬2ÇÄaWØ!€]ë×fÀ‰sçÍ«JªE-|¸ÖÛŠ—prH¿Zü_n‚¶•¢>Ùš}mͲ¾¾¬ÌôÎ/ŒK„1RzS> ÖyØnb‘¶AHvJA"kJ°§ˆî 4熤:nH'PŽšû.HÂDàœÄñÌÀ8)Ö a„’]w/Ö_“êy«¡¹¢M‰ÍÁÔ¯N÷™Ðu|šøþ¯¬p’&°½VGa±'{Çk€ÁQ‘TaPKZ&àº7´„—v+÷<Ô%*C >•ÀTi»ï“ƒ1¢BS´a$ÍÒSí"uÓPd*•hCW³ˆÒŠ9ÜøÙ’^Ö™\p¯\½zgM„¦ƒÏ½~ÆQ‘0+yà[œpX=oaÑ\ýßÛæ<;&Óô“S)äá=ˆÝ×¥ÔN²ùYDéª}nT\Té7†/k¼çq䨏ªÖš°KEð>ÏòûŸùJD×þ*.Y†ª¿ºo§[1ÊR†7𸳂Ù.c œåsbyýn[—±K?ؤ:Ë_/!‹è\0A &ºH†saÀ-¯!…WÜx«þ‚C•j®ÌU¼iú²c©f1Û›¿¿q@E”@ ÜDT´ŠªT ŒUF ‚¤D˜î¿Ée²OhËaXJÆDÕ ÄNq© ÌfœØp‘†!PЫ»&3$¹@ÐãLŸ¿ü<:ï“ĶU$bA¼ŒÆ,ŽR£`râÈiM¢46ªÃ•²¦TŠE’*ÖABE–Ê7ÑBPb1a )0Q ’°…BKo`|^$¬  ö=ÿGú®j—0 >gްˆRkB€¶¦›÷xŠœ„¥¨ C'·œï~ólçp\öôÒŽ‰Ð(¿> F ÆÆ4 ¥‡JÈ Ùó¾óCyñá[2(¢s‰í L°0Öi2&ï+×ìÏù¡öùzôÉu9lÅüù<ŧ—Ëqs\±Í§ø0ðÿ~ɬ;NÐ|Ÿ%­ > žÿßwA¹®–Ù#Î)„OÌf'Â#)ôŠT;„Ÿ½"ª&bEaFþ´¦uÀ¾âŠ8Û ÓÖ´—ÆZììü:v;%‹RRÚehå‡Þ˜öü wª³} åÐûÈ%ÒϨûÍÛ®ø*Žÿ×gæ?êÇÂîz#otd”=OS'ö“äþ´bÏ寨¢¨¬=ôøìñw°M'bLÙ|¢ »»6C{ؤï()*qiÝŸŸŸãÃÜ=]rœÁ9Z`û^½NDo¿â÷Ìk¸öпƒ|Õ"ˆq¼“¦,€Ôd f[̧$º¸OŒÁIˆz‡ÁMºï³Yf]ØŸ¹ËÜMÞSlß»Üá Ç'v—œ Ш‚£SÃÌ8¦¥™H¬Œ(¤!"ª1"±Î†•£*ß0ÑçüxàÜdKÅ;b0 ’dDã×Oç<¦Î×t°"€ƒ nÙà\UË–3C=Ìè__¼·þ2h{rw畲ÊÁŽûSШÞý×H—››üX›:˜}‹©ü:YŽš¬6;¨ÿìNŽëDâ]yVò’;ÎXçûcjÌ’:„MÄÕzë8zc®V݃٫·èìœUÓ6šeÑÞù“sÅ4% €#å~¾“òœOmßçpw…oáÔE•1NóY?óÖíuo;Òù[^­èç6\èaÌSœƒ@NžþþÏg§Ûjp-cRŸïtUýˆ!×R*4êd )„ÍžÞH5þÐ-ô¿×ȸm•(ä¡2tåêR)Q*¥ TR¨¥&-–ì3à[o³Ô~¹þï¹”¬ã"·â¡ÎZh6þ×%öŒl˜jíÃcë~G}‘kT/„¡|Š0ê'ªÏ@ÂĨ¥Œ­[@RÒl$(ibŠ1±ÆMŠÃ·a¸al[~íú«ðÛþ]>;"˜aÈ(-T x€$ÃL;FCþ¸sñÆ¿\çñÄàxJkNHbgè¹_˜ƒO•ª"ª$„d(¨tDN¨á-;LÓwX_í……—Zqç Â‚M…§ùQÞDØœ2wÎÉ]IX¹Ùp»³¢_ðBHŠpPå³%ɱ"ª`ÝpÌ ‚> Bàa@Ç€",Ž$†ªªqðúîe ¯T†^(n‰Ø*8Ñáñº!þ†OÃÿk5GóuP¦¢Pû$ìï ÒÀ7¯þäèDÜæŽbIŽÍ $B„&jvI ±^eÊBÐÒaÊÓ3”Èb ³Ž0L‘≟»!`“²^TX3ÙInÝ×u-À0…FA|wðÅ ÁÛªÛâ€!¢,€‚Á‹"$ ˜ }¿Y”<Òø¤€A…Êfz¯ ³Ðì?gÊò:ßçÞykEö™³~ç/?š¬Ú±&'Í:‡¯ówÚ!ñ—FÖVÌí×*8¸×Á—dL¸JÇ[±‹W£P’õiÊ;²]õ0ÛVˆÿ«óþ“ —#š"V0)‰¹©@‡çsjlˆnvƒÙi¶_[OÎÃ=¯ïÚ‡…çÁÂ\BH'Ęò²   ŒrÔˆ¤bˆ®ánÊU€£H°nò‚~ë,1„EQH’!‘IPm »içþ ‡è!6 kÇø-ñ´”n8–= ÐºRÛ lDß<)vч„wÇØú­Ý4{péi—w£J…F£áéµöžïŒ¯ù½WQ‹îNãèÓíöôêˆe´†O„²®RxÛÔ Z nG fB9|aD-a=ÀŠ‘þe–•¦”3øÐ‡©|xÈšj¦Ÿ_ô^à•­õ7šÌpd$,‚1bÂ,X "°$V €¢Â(AB A‘",’(  Ä#Y@‹V²A@RHˆ,Y"¬@H¢’E’*Å’,P‹"€²£b¨±H²ȤˆÁ` «$"Â#ª,Â3;9¼¶vIDÄ{1Š(ÓdŠ"’ævGž‡Î…K•IP ‹ @`Ê`å$7"i-£aRt/XbªÂ‹(i 囘Ÿ÷ìfLC±ßó¿}FαʱXÛ™’j_Ä ´ââeÅÁ,& UFH‘„Dµi wÓÎö6€tQð”QñR„ÛÔ²B? Ÿè|Âé‘û²ŒIÕæäMH™n¢œž‰²>ñogÓ‡e¶ÛR&æŠû@ u=c¶I D(>¬ÈPýæõƒDc3‘3!Ñm—¶¢åÌ59ÍZ­âèÄ-‘VL誂;h*7EøgaÛ|ö"^ÉE«¶xü‘ŸÜ¾åÛ4HU:åW–“ ¿8Š¿Üp‚ö—5{ÛžfkÓH¿e–½JB<~Ýppñ¬—¨£äøšBëý=/jdà¶Kc[Aå0÷Yið¬qÒº¶‹¯ZÛµØn«;‹Žô9oÒÿ&ìË 5bg0v?ež^ee q¤Æ¥œ­¡Ó6Õ­6Æ_ƒçpÜž®{àTv  F „7¥Q¥)KE\:PÖ¾NáiÁdÃ{ƒáµ@‰ümX_–×S'ŸÊqœfÓ ð_þ—)½ÜÛèáxþ,OÓ,µö“\ý98 ºp¢q ÄUÊD$Ìû³¸,þ´ü±Ž?¨$Afƒß9HÂ9 Éníu›‘ÊÏäâwn³ª^ Ì¿å7Úbb Óþ=ãφc1®¬ [²1eüÌëL„1Ñÿ´¥0¡ŠŸ ÕüDÆ€ Ö„DY(´ÆÕÊ¥ $@l ‘©ŒÜö,Xl-»øX ;SíPŒÍˆCöa)Ç¡óa,(eÈB¹ÂÚ¯ãß“WÊÁ¹Êÿ ù™ Ž+¡®ùrùv¿î27te‡êî¶íx¹”uëôüÄj„½Ä:_¶‘~aßV¯‹O~7=øÿÔD@¿m?Ÿ»üüq³s–ñbÎ÷Ï=J9ö—M*h: Q‚Dƒî‡ó³_ ,ä½êf‹ÅêñZ~²Ìqýí¦ ¹ÖITŒ(AwHAû5l“]ï¾—+Ò‰¹ Xˆgâ#­# F‘^žåˆ€,"2 “ ` Œ†¢H&È)û[ Z*Rܯ¥š èÜU~*2 ¤…¹R ÔdëA›‰ÍY_ÁÜ8‚„X0lÍmS óŸ•26à‰yµ2{‰JdR‰À”e”)›Ì9 ÔãƒSDÜF]áþÀD‘(pÜ;D…i³Œâx ë–) Áq>î—šKåhZÊÚÖ0ͱ 'à€†Ÿúµy¬¦¤6ÆŸëx“âXã3Ã=˜?Á–ža?§YÌK×¥n'pªë׫î:ob¬å;¹y:yªÄ[ÓôJÈuE;¿8ª‘‘f³1Õª"¤Œ_ ±X‰ ‰5 õ)™K²T.Qaæ ÎË!åö#äµÔ Ñm­ˆª¢*¨£Ê?SïW7# ä$a…ð…èB¡‘$O~¢øT0 ß:ÍSâË;¸Š¼óØš…O܈õJ D Œó²i'}õð®†W®â1领@åès\¹x­E6ÅÓ§@éþ1®ß|{z}"tgH`iBv­ßÄtUC•´¨‘Ö% ×`5äzG-ˆMàA¼bŠ=ñ_Y®°ºâCÞ^ƒñóÇÙÙÎóÑOZÊcðÌ&d8O)$"1X¤:— ÕÁÑêT:z#¶!ðή3¯ÑÀøy{lãSÆç6Ͳ8Öåë@_˜±™zq˜äçÏìÈËØ40‘QD²±4ðÝv™µŒo{w¡ qÃ3Ó‡`U‘ÇŸMœ1œYY®Ýgvò`Ú ÉA–Ç“ºÎµeÇVؘ̽ƒˆ€¤J~H²ÚSn÷ÃÕµÌúæVü-5`â;m^Ò—©}?\Ê9UDV²ƒÂDòR§TìaŒã¯LèÂX;T¡n€aÑàF1Ò¬¦K¹v2RÒ‚!ZÛIB–BBt 8&Ÿ+—àÒ†¸#Îz ªX* H#cLhž"ǰ„‹fƒy‰]â !Glñ7C+ž`C¿¼"FLŽ´ïõnÁÈñPÐ01V’Ûi•2xˆ(R‹XSÉ_›Zq Ô‹«,=Û,“Û™5½@Îæb\ÙÇ-§ÝBlΖòÅTU&aôG§M¤ÄâHF}EvK! ÎöNe²³vÍYd9CˆNš5Ë 2‰ôD3 ò¡Å94  u¶ÅYà,ò¡YØxblԦȟâž§böZ©*U\r€u@xN¸Ñ4˜GWgt$$R1ŒI!@Š" ŒˆŒX# QE`¤ŠEŠ bÁŒ=Ä ¬Œˆ21`¢#A„ˆŠ(Š+` ŒPŒëV1b‹„„URH(Fb`…H²RBD넌•$‚¨¢€²H±V,UQdX¤X±AdÜ'9âï¾ùv>èx(òŸ@uDÚ_o5 Ïòùd™àQ’teùO®p ¾©ï0kâ=/—V´|b‡¬QO­ûgÁèaZâË#ðYETh@¨K[” ‰ !!†8¢T€¤R &Z Â)E 0DA…Œ Ž,4 V|602žÓ8m}vSßÓ…º=;ÔìßÜÁð›»Ç¾t‡yÂ:Ç"ݺ †„PÙ±sê8nÄ| B«Z¥òª”IäVÈ)' i•;˹ˆ†!uQ±ØÅŒ g¾CèíîCàgö­šâRå:SRè‚aÇ~Œ¸0‰×BzÒjìÌÌTÈ-1°  éP€“äHs=ueTz‘ÁÀžsø§2"‹)eDL’+–Ò–g‰á4ø¬Ç_KDESÀrØfa“Aîð;4탃rÔΑNw0ÖüÞ¸V]r”œ :Úd²Tž>³žxÓý'Êî6õÁA¹ŠóÁQ6Z‰„Y!43𬀅`ïÏ ªˆŠ¨ª„Ï–z¾\â@æ !:I ãKo~Ý&0¢DH‚!Þæ,É`'Çë€m¡Æ'L«þÆ?:Ì :#± QX¢É¯¨0JvðÔȱWäN‰ª vÿäÉŸG%Ç#ÏûæfƒŽk_Øt§U¦øÔýŒ‹£!6%Ä~ŒuÌ\2Á•.Í{Õ«ËQyéÕL‰gn‰öÕŒ_e¹ýòñ=LI?/¯“ಾ~ÃÔßoGösBÅ畱 -†½aÍ"q€Öhü{½Ý©qÝ?Ïœçö?^$%1[.d£ßá2`°Iµ˜áè k• ‹ÍRú6Z·›,ŽáUX^•æ±;9£²È>#+ˆPœr€ÑÄÕZ[G<\7G¦ 96fmÀ© ˆdw a¿Ož{ò0öÆIz+!‘´ÕóX¥÷X\¿û°B@ÅÁЙx `}{KS~·ç¥ø}î4€·` P€€4!»7Ée{ÜþôªÖãè¤?â\Æ­ëàãÀÔ„?ݪAE¥ñ MF?žöªíÖ…V8µJn)Ñàn÷Â>OÐôÁçâwáyÌ—KÄbÔNð'òÕùØûýÆÒÛñd«år~¤"A1בpnióÓáî×4ZsGq[éÿžüý_“Ýt{‰EÌf¨9œ•¤°£"úÝwÓ®ä’H`ÎÂn?Èoœç|´p• ˜@Òä·;Æ”ß:H†N¼¤u`(&NÉ·CVDôþ=?æÛ¨ÛÏ衇†  *£¬"ºèR F¡Qf'9Ûï?ØÐ{íO­às§ãóØšv”>V!á¤"d²‹–óÒâ_gásã ”2.jD¬ÏÁ@3-ØR›ˆÓ1UñU f*9z¿Nz€ÿµ{°Ø°H^Ûgi=àwŽ<ê°¦¾Í@ЦŸ¿æP?ç!9U!Oq|:ù—îúëÐ-%uHxÀc’H-âý Ax4.”GHi{îÆ÷¬‡”¶æ{? ‘èûÃÄü{ú}ä<ãÅŶunæ/ýÙ÷™:éÅ›°ÚS“Ò{áðWû†Ö(I}(éÿ…®Òi 0ÌÃižÞÇ/8¡>møÐ»;ÇŠ1¸E¿µæVÑͽŒ)©)Ä]àÀUþ\ó4_dI– cøƒ0CŠ@“5ïõVœ§‹¡ç5½wßÛÜt½oa#[¤Ûó’ÏFé˼¸*?Æ 5òVÚµ$Û!_2*1¢¨Ä0`DS1Q¢OP™Qš1¶4¡F!¦É¦›j?t’V@†UYÍ%‹ˆVdœ’¡8´hv0Û! °EV*@DÇdZÌedY P?öþŸRk[ËÅ$„Ƶ™ud˜ÌýlM "jƒ+½ùu[…‡3q¢ H¡äAy³–0£R¡ã¯ÆN¡hCÈp&£º€½ŸÎ¿É!;?@¹ep D¤P\TD$ì°Ï™ði©‰›: ™þãó¼æR׬u€b7 †aƒôÿü,AðªÃÊèÀS÷/˜äm—&íC×…xPöv¼»M­rY²-ÅQDL+ò…ñŠJ²°>÷·ÞV*6]ÖŠü/< ÝîïÌÖ‰ðη™©iò(uqê€ÏrzjÜÖ§ÜÃï´^òrCáÿ?ØöþUO®KþáÎS 4µ( ?ßÿ?£ðÖ¸ |”;R¡X²µ$ñîM§ØÜô·`²ó¨ë‰ƒbg"†p<`™Sáà(xÐV|)Z CZ‚î‘B°Ü¬=Q=Z2Al*ÓJ i”±cŠž"DÅyP™³ -ñk/Œd%ùÊE ZS#RžIPÖ‘ŠIäèr–ýå1E†0ϤY ÒÊr¡†s'-à[2NT,ä–Aœ- )I Dã.ɸ$q…&£öÄʬդ QXIˆ9’Ù$„ÂFÀBÄ‚R Ï)YÐÈÃpgBnó.'šiÈ(§¦ßå(£Î1EÑ7.°xÅ‹‘4mΔAežrËÍû^˜`s¾<±äª ¨ !6¡!h„iJ|~“nƒnBàKÓö)ü…Pà hC– ÆíÚK¡ô4ýHÚâfñY) ² Š ˆ ŠH#„VÓÇô€ÉË „€’y‚–ªªªŠª( …¡I`Þ¨œ $t<#ØÃ?÷ !¼Ypæ±ONaGcwæú‚;Ù?Ý.ÃÕ×­ÈŒ•TaU°{1•Â_¹º‡q횆â1žû€9J‘BDT Ì06ʤ¬"û½K TÄÐÇ-›°FÔ­O¡”¹±œµC5j¢ê{¥‚½"á_m^«­­ÃEÊ_µŠsÅõÊOñ¿äÐý—„›A¬%V¼ÌJ&6$VEr0¯ÆM%šœ5 VDA&Ùš!1H],‘R;Ðèê\B\0G /p •GhsÊ,Ú}1è {lõz“á1ÀÇ,É»õ¬aêÅpm¢Òq!b™ sdŠ(p„ ®÷CÔþ6@ô$‡°€ìòÔYP€F\U" «Å¸@®÷0R§Z‡¿Î9$cBæ]äÏ ÙòùWúp >%{ý‡ž….çg)¼½vâ©*µMTÕ|È™fa½H(§kÙÂÔÂwˆ˜³„¨&˜¼¼¦õNèãd«nÎÐãYtÞy`Ÿ°BlHu‚ Ã(pN•“Ÿ2ŽÈÌ÷ûO‹¿åö¿ÞÅ\„§%v]×­ìÏðyÿB- |éiKŒÀžB +³ºW™zQsüM7lŸã|ªþmÆé¿ÊÏT¡24ÚrRV<>¦6ÿ•ÕÜõ}¶¿ÆjêÆ¢žX,P"ñIý;¯³ÿEÌ»kB)AŒWÑêà7x]M‡úÄt˜ß;ákSÚy¼nZ}ìѧtéË!b”jZ”C‡PGí*¢Õz¿(0Î ?62 yÊv*BbƒÐÚq™ÉÔØ8Öî¥KJÆñJ‹¦lC ìÔW*Ÿ¡W•*Ú+܇Y†k+¿ŽI@žŽ6pC‘ɘa’ý÷…fj?¶D’pÇßó\6ŽšPÏú«ã—×ôZ|VÈäY¿—ùŸøÿ—àsLtùɧljÒÖr#¹áž^T†fh£Cˆ"˜dWXjlyZ5‚hÂ{ö|Û—´éZõ㉿Ï)Ý|Þ« ݯŒ[3Ý—TæŽÓü ¯³9IL¹ÒR½$$ή Лµë¹ÔçÊE½­UTŠ:Ù{éˆ%0lÉçPcèAHå´+Kï[÷÷9Þ¿½vù¢V²Yº>ݱ1.°ÁË)–ŒÌ«QpÈÛ™­.†¹JyN ó؈î@?}Î{ó¡KKEµŒ:úz·y RHG%Is^½Òq­Œ˜§#®NKvÊ Æ••cê·‘?Þ2Ôõº¾ VÚ³¶CŸŠòɉ€Ú6@i!˜Áž#QR€Ñ…"JQ4¿ïþû{ª¨û8¥ÀD1-/Y~Þ>(rétž»Qè1UUUž0µTzrÃZNmU]ÏäÔÒ,Y6Ö|F³¬Qc}2l'w¥®½&²U|Ü.÷Ý|°B«Ê· ª7?L/0B¶aÊ E Ÿmußçƒùo¶Òœd $ÊÔ­GZ¶@õp1\¶*ªv-A¬bŠ‚?%•Tb Ž**ãî1õî…XŠ¿-;D‡-Þ8•X)!Ö AVêvÊ">(I£2z dX¤í´HH"ˆv%E{Ò‚Š(GærÅ!œä¬Ÿ6çœ)5/ÊóürBâá!àëIEU+Þ-, ãU(`0xA©!È_·a€?«ï}n:R«^”Æxæ…iKKåúÀ&ð½¶üË f{U¥UÜP¨ªv5N”ªÅUªZŠª€ÅIEŠéúÖå…‹eMBBÉKt)Ž „/:¢ ÆxxŸC* BªàN8"‰n,—DA§šÔ¼wþbÇŽ@[ûðfÁñ»GÎä¤eµ«-í A%°NŸ/ª¾i´¿ÝâÎǼŽ8Ã¥ž¹#·×FNz+sÆ Ì·•©àEpê~ë0?è“ö2wn?ðà¢ùãžÏSUéCÞùüð˜F·RÏ—` ñÝ íqÝ(ùùÇ\—mÄ#çШ(ý}ÎYÁ4•«Ì´XßøøgŸ÷þœÌ'¿ý9ìVíïîÒñ=§õÏÿ»ío+ÑPàhÑŒ€³Qs À ` !‘(ÁÇjÉ!0Eôs¡ù !Ânè$„ÔÇÏ ~'ô>Œ±ÓHZU~\,¥Z¶^ˆŠ;è±Þж(š²Ù£*)üÖ\j*Œ"Ÿ¨:”Áˆœ™^cKÌ\— 33Á“ç³pÍRe·²ôÉ 0$™H›r'*%×ë$ÖðäÒ#[,ßVšA5¥ƒGeÖ¥NŒÀ‚Nš ÆœÈN¦ˆóºMI¦UrÄVµË™‰0n'TÕ„6„*¬t¼èsÊò\^º3½®ø¨¦°ÉmÌÂcs1)P5y¥3–B¸Ø«mfÚâ‘s–± ¥çfÄXeV”®šsf±áÅâL©Ù«”ì(pÒ¡`iñC·üN0߯ ÕÚiÞa™í6í4í !ósÈozr¦˜–Nðßâ3ãô­´åsWââa0 V±ZáT‘„LŽß€[_¿÷µGåL¸øO }ãº2>fzÍ ›hä„ä‹«lý`y³±Í™rœ 0™Á%–ãòÿŸŽl~™W ´ã} Ùßwpq07TXÆ#»{•ªÐXQ°TbŠ0wÑ'äUIþéRú«GãEïþ—­dÛ·h€XEå½k?؇<¼Ê©=„À)KâðÞG›óå|:<£C?ÛàÉÕwÿÛØZÕ~Ïú©ò¯Í~¢lÿ›k¬Ä ^,’„mE5E0°}Ÿ»üž¡ÿX Ç-Eh¦"£:‚D¨I%%%•ý_åÀª>öt´Ø96íîm@›ì»] Ô(ð1j­o" kâ™´? 6”0Ó‚ép3Õ‚R…ØÈäp ²Mð!â dÀ,qáq3ÌÌ33‚ÄJæÈ9Œ_ÎØRðI `ÅSˆ"Ö *´¼a I 1†¦XM0 tÆI¸†Ñ%¸‰¨o[™$Ê‹ŒCPK%¢þ,²RjYõÃI‚‘DX8à JVÄB`ÃhùTpC ää5z(2‰…›l*2÷ LÌ‘EªÅl¨>¼e2"ÉX1bÛ! êûƒ˜“dÙÿBÂZኂ€šV8Ò¢©ig«™·‚ǘÀ©år<ЕP’ªÏB;ö<Ì" €Á"ÁPŒ‚ŒXˆ*ÄDRS”µ˜7y‘k^–¦³äa”¡HH—Š“5ú AãJ©ð3™†Á8§(‡´èfØL6Â}àø:I):îX·Üâ¾Ëö—.=ÐñI¿èX=swÚ~'Æí$ŠÈ¢wâ¢çÏmÑov«tT-iHc ,•p]-ââ. (@6È@Ø Ý˜Ò†T5a+"D‘‹±H‚¨‚B’É!,ƒ$„—Z$)à ™0‘¶AŠ¿ËâfF ´A Qb,‰I+mAjEIEX)P¨Ö¢2¢Ö%ˆ²HF"À$£K) ²4õäB¡ˆªlÆÉ$&µQ²B±"sÑ%\dŽä¢£ |6C2à ŒXÅ:òA.a’á $3F«Æ¡H° BXZ1†I –Ù âàIø ]äQtœ9WæÇdø*잗ßý4Y †³¾â6 üc^½N­îG±;ÿÝ3ž»>ë”3¹¡‹Ö¼ /ß^B°ëS² TÓªéXØ«³Pš£ùî›Àë}†=üOõF¥ìЉ¢~ª“~Ô?H(äÆóç ]…Ô$à7†[ @Ç/CÔ±ÒmÖoìoÅúýwqàHÅëħ ‚Œ\¤´SnÙ,H¦ñfíÓ õaƒ4‚íº—é3¦‹#8³÷1N§;œYÔF'ü¶Ä1ÎŒœ©²DdP2ˆã óø¸ý­c€8úˆ€£÷t:î¯×ÒDp:QbJ°@šl—ù:LèžýÍSa€6íù¾ «ÝØq8E§£ñsù-«Ùá}Ÿ?¬5¾ù7ž#&½ÖŽ:û?Ë}Ão)®Mi‡\†¼ J«ïØSÌaapû bÔ2Æè|oÎÇ6u"F4ïQFš…õ"Q&ªs0\]‚«´©†KÚň ¼?ƒTí!ª4! %D¥ë˜Èߨ`$C{]O“ΰùÈJ9C„{kÂ)¨¥‘@`Á$d‚" D‚ ÈMÀ©¶o$µ½bY/ƒhÂ+ EƯe EdQ$Yd‘@Þ% H"fg=1ç3ŒïÅEøn w»yþʃþÇ{”–Cv$Fµ€ØáMÔ鼑>¥üܼ¤'‹š¯”Š^ITʤd5¦®Œ†6øðÒBÄô¿Xtžtª¦0O¿­F 9>Hã¸7nÖÇMOa†µp?A’ËG '×$A$‹„HD$»îCŸ>€¾)J¤ÊJ" ˜Šƒ ê´š) Æ?Í!k¹’'Bh‚‡N£ØÉ:ˆ-0EgøžÑƒÒçÈ "¬`ÉFA+€,Á1Š(²ž·È>['zd ‹e‹ ¬@YZB1$ÃÊK$¨‘JÂCÆ@ÆGHeKƒ'°€ BE! ¡Ø$±}<§<$cÈZkQF RŠ0 ÉÀ&Ð Ã0 ¡Œ?NÐ鼉„dà 6è…u°yBf+5;”®ÚùèO‚ÊŸ,xÃ+ ©¤½0E·³RZ*:)±GÂq2KÝv…Œs9íZ㱕„ü³ù}{:s@<éH°ETUF(›]¢ˆ¨Á@PBä ŒÈBˆ>€EL«HØB) ² iÈ:ýgõµs3cS"EaÔc3ÙŠf¢(£L¥TF¤ˆtrNˆTôÈHƒÈп†qJ5ž±ËÃu—˜Þ€”‰™ ™œlpÿÍc.c[TvÙú6×-ƒM*:ÊÛ_ Á*3bÂ[ƒ‰”¥¹ÃâK$ºë†Ì-q%™dÓ(4f +‰nœ+»‡›xL\ª]©m©…3%Ni¦B¡Sª^l¼-ÙJag&z¶¬¶$¶ÈˆzÄD1:!ƒŸXPäqf™Ê…ì­ZLÌ#£°÷­ˆØhsñµJrG ÚGDØ?c÷çÖ6¡çL•ç“ÑEF•;ñÏTˆ>Q7AQ„ô!ÍCGaÞt˜˜Ïã€/×pÈë7tŠŒ±è t½?µÀæ @‘bŠ|‘òV@F4´˜23 09vqW¸i.'’kÁÂ-JzšzÜÆÞ\X½b-¸s—pbèîx¢Œë´×É¢Ðlûù8ž÷1%è„#7øØ–„ÎFTURÀ³hÎÂ{9$›>¾óAC¶sô©«ò;Úh{§híˆñH•ƒÞ¡lö ­…éÎHñ¹`sïDÈK™2*ªÀƒåÜ’{]­OFňžó/"ÈQÁ¸ä¦`FHŒr12§5ÚŸù!ØŠŽz»åB.’|¤l¯IÏ$²HàP§ŸŸ¸ôÑ4|· ‘Ý·+–…µ¢£z QFÛšQF½Í˜€¶òH¡æ ÷Èžf­+CÁ©â/«>to´–L$9’+ÍÌø¦.$Ê¥ŒpÉ€¸Y)ñýÉ+@%QIo|º¸åv‰ò 9ÚPÌ#O1H¼ÁèrœdT8vhÃ=AŽF“o‹~Kä”–Þ½7WDÒ…ÆHÞl6ÜYJö˯DCÙ‡÷ƒYS 7› ž«—J›>º'Íù‚Èô£;6ä ÖízY }•³©Ø£óK ï@L çq$÷âÄò-lÒÈÎE( €Øsf¨¥Ó_¤žû Ãÿ¤Œ˜€È# €ÀÀvrk˜ÂÕ»T¥ñÁmàeú¦&®Ì±{ôÒL@=¿Ž¯£_ÇwU4¢iÝ&2#ÒlåU£=äò=Ö>= /†ãú¾ÆÓéc¾ƒ“E0Tb€œ€ ä.zd#¨K|ÈPÈ2aÅAQ®Š@þ¿Õuma¹§Â‚‚–¥ÑpBµZ¬»'@èyËIëuCê?”Ž4/…`=3:rÆ\¾:ëúuo¼ØlØfrÙ+e !WY°5\Ø5‡·ô³:Ihª¨ó! k¡Îïœ0!V¹ü_;‰Ã Êæ€=‚˜À5»Cê´.þè¸ê~;9ùÉ ÏÞ'GüšRÛ9Û |Ù ÍU©¹:¸mÛ¡4ØA~¢f°E²¨>¢r~Èg3$>gª}:ûå¤V#IIA Œ)#b;:.tQGõŽ vu’mÃxQê¨ßÏd‚±ƒ¨ùÓÀÁ¥×cå}†Ýqaï‹€sKøXFƒ”¤<Çff{?ök0à¤&Ú;Yüt½žž«—Ä2×D1¡Ê€§ kB5¢’É C¦>/!G`ÿWA&½l)ûnýͼÀ€õ„ìB}©ßß‚ÀY®ØïhODT+â$Œ…T)aaãº0áÁžùÆMë|æ`ïËÙÙmËš“H)òç)âruE;ç# *mŠœm6DnÁ´Tͪ! Å3É`áêO¿àÃ\¤ õ)±æoˆ¢¯Nû“GË@ä0è{à°OÞ÷ëZ„i9béhØa>B‘‡Á&NùQtCõ¿:Ïî;àƒjww]„}h¤{I_½M‚BFAIÔ¸*'Mƒµ†9T glô'0VÜfCã2 óaÙâÑÅ:I‚b#!R” "É­UÔ¥×ÄD q líüC ¤“”êRô%ê™:÷ß×uïp” s`3+?¶sPO„ZB ŒGØ@‰(q‰j¦ä.#oýò÷?ÃKê9œF$„ŒbJ!zRP`I‰„ÇFS“ɦ%>¡щÆ~”üßòc¸ÉÞHƒROÏ>§—ÀoÐù ¯Ú2ÍOÂ?\Ɔ»‡<»Ï2ldvîþ~g˜-ªX}¬AéçÂX³§"HMëÎtißÔ‡ý:=ë^ù»ÓЪ7dp„ÏÛæ…#§ØËu﹡¸rȃšÌŒ~}é—ZcGÂ!ßÙ´\ŸCb×¥!„6noQö¿oŸkô—ÿîﱚö6/›¾H[dçùS¡2š Ós©ç-5ý.uŒ%Cþü?3(åBT %͈"}H?ù¬7 áu<ïOÁü¬ó=~‹»ÕbWÏÖÐ0uÆ€ @sTô°€ÒReC 0ýSrèî‡G³CäãuÕVM¶ÁÃ××Ë)ýf÷ªsÑׯñ‰à9¯µ-ÚthFêåªCHÈ)Èõ¾†%°Ïº—‡½m=6¤×ÿ9©WfwèõæA¹à5þ ƒÞÙ£ÖÆ¾|³×DL š.)4…®á ¬jÚwÐ]g3¾O}üý³ßK¾ï«z¹²,°IîÞ@#åXùÉL7ˆQ”/þ¹\N»ú“¤8'±`?šÂ†Z=€Å#ñ,® äà ?Ü"3Òš.P kr¾æÒ'”:;YÏóP\yJÒu\9ð×yý#Ó$ _`ÈåþøË4( šÁÄÈ•ŒmŒD@ÈŒ§®k,vÁÌ0ien2Ø€Z1aDÕ6S"1ˆÂÚ¤š¶ZÐ ,Š|Rç¿I!†Z )D*•¥Ð áf!j”¢ª[T®bÖ "án!FÄ6†& ™a+VDXj)D´K+ ¸&)hYõmq¡FÅE€ŒXÅbªÁDJ²(Ëkü‡¥¥DµÈÌÊZTKXâI rÒÛ-±¶±)Uð¿w€þXÜXÍËõBƒ¥ÖŒ!ð†¤©` ¨ª>ˆIø÷¯Ð+ìlIŒ¿ÇÉÞd´F‘Õ$© ä|ksé‘2ŸâûŸ¡«¹š‘Qª'äBXú¿Ä7šõñŽe>ÁÁšF#ã“$èDþšó:tÈ/Ö}ΗM:¦_)z#x4´Ã´ÕL´bšŒ.¨ËGS.QƒTmU£¥¡j¢1E•„N¬kðø¦V0€#rÙ¿Ðo‹ÁëÅl`Z,(†çúûK?â\.Á2˜ÙÖ™vÓXÔ'oJÙõ,Á®çtÙ,¾©¬ä1Ë /C a›Æ6¹È«a¿Û×X‰ªÆï9j²<ýç˜ÂzÃP® pÌk68¹qž°ÁC5À|b¡!´…`l C¾|›q\®ý"Â,PÏÏ>ó\ÀˆÏW=ÿdúM¹9|;é…)J¥”¥”CPeU0†³¤9È+ ÖÓñÐþÖMjk&íÄ;"Ô£ñYRH‘Žß ÏѨŠrÿÄ' Ç\5ñ)æ^Q€ ê †2Hâ†<ðJƒåT’VU¬EI/gÈgyntXŒTV*ª„‚lÕËŠZúýêŠ;P8À,’AÔÀ'똩+HEbª*Iß#û6@P„Ä'ÐKÓ™„¦'%ÅÕé„Ä1‘JÍO¨2MŠ”S-Šf— 0J8ýñ\j*¢ÝÊ"& K.cK2’qÀ@&¼pò!ýÃÚôÊ,‡ïGŒ ;’9oK@ݹ$6˰²Jœ«¥Þ[=="šÙã°Ÿ;*ÒF8ä‡Iã|&3*jëTÖ”Ån¨\SZÔÉŽ‰!!ÕÊ(ïxÜÖÿÙ]NÍÀ”Ke‘J¾!‡mÞ‚ãœ8KxfÐ*sFA„dÖ¢Œ¢á«¬<‹EAÌ"G½M’¤¿‘sðùäæ{ÑðI>Ç–“<­UXÄ!Òb[FÃñZ9 è$+õ ’BaŒD!t9EDÌäbõDLâiï¹ÞŠ>O V í^åãcå|^ "Ãé@AQÑ¢\%¿Ï ú«¿{*I‰Ð)dt! p‚+v@aHRwà==¿ˆI ßÐÛ“ ¥h´*ˆ <¡ó¨£¨ôõÓÚ>©w€/7ó›NtSqà6àì uQó2¹mõÀµ1¬m„9_?쉮RÈPâsªŠsÎJ¡Þ"²Sª˜nÖÃ`UWl*yvªÑÈ¥b þÄù¥ÂÂ"Ôhù‡ec_ïd&Z§G$å’TšÂl¤pº-bÌ6Ñõ¦‘7÷q0²ª]?{¶k;ò™–W„v`&ï^’„ÕÙÔ¼Œ8ÌÃX`éßo¶2©ƒ úýfûÚ¬í‡à4Óc\¹bÌ9l^%¨3(Þ c)ÖUÐmkÚy£NN“°‰›jŽ‹6|³jC8=ŒìI$&<»;0&¸µÕ¨®¯sÕü=tÆ’Ÿ„*âµÝÛf¹FUã‹mfèk¡¡ÞòÏÚ91XÃß—W—¹ñ„U%TÛ+M˜xrÐó&Š!Ät;(ØÖ×§ÏW„ó´Æ^C✙|ôtSÐ*Q›ºÒ©©¥Ú\zQõŽq¡YÒŠd;]J‘Þ%ÕD›$ÉéÑ«õ™aÔÄ‚MŠsgéwSu RNâ¸Éë¬Õʼne²g‰Æ©Ê|ÂÚsáæduQ xQ˜ˆx™€Œ%U¨§tï#ÓÓÍ•#–-n0îØ&ù”â0!Êk¤Pën¹’]ØÝ[m£¦\0ëk¸î§H…0ê˜d¥L²×iÎÒhÓm07½ìÆ’³Ó婜›–íË»riŠ(&éáãÂHJmãjvüí™ÝÊùeÆ99ÓjM;CŸ}rnÛfpÁ‘omÈSOÃ’ŒïL5˜H#W¬¶äšQhÊ…!*ÀÆõ°8étí8Ë=oW6» ²1Žvg^ÉÔÀâi8ÎN9 V7²Àã²éÚY(vÕõ§[ŒÌ77¶)ãl´íÕãD©é^¬¯8‡ mN4†ŒˆW_kȧõ¼à¤baÉ€®,Pn9ÔpoáÚ}¤KöMºnS ã´ôý²ú§d;8¯°R¾à“zm¿àïô}–)ÎÓß|kG\Q†ÐN_Áð¢ü´±ÏàÛþ?xhdÿc]’÷þ+sKÞ:õª¿¾îEDv4‰!ǩį›ù·Ò,»¿i˜5Ó‡×4%IÈ}Ô.1Uv(¥UÜíÞq—Ž¿“Üí¤íÄž6[íòß•…Oõ<èÖÏ'cæ’*6V´{ Ì5âÝò%òø ´fu«üʤºwÛSŠ[¸’C—˜nü98ûêx~¿ÔØ¿ g&äÌi4Ô /ªdFde.”f0‚˜SL–…=¥ 7õ°ËÂRtHᦥÒH=í—Ãô¾?ëð5{’o”TÈJ~µá(˜Ä¹{—uÉ_ÁÌ+á©a|ÜÚêêaÀ£E{ÕáÂï"íö;mY Û¬èqM²+ˆgÔ‚ë„p‚Åã’ {[H4¬U<ü[¶ŠÀóTÇt–ûh©ä!Ïͯ.@ èÁ<ˆïÅkþòqƒeñ06‡“(¤S@»t ™’zÍo/’rØ8K¬è8ÿŘm. [ã¤Ôa6@Œ-ŠÝÑÎ\PË—<^ „MŠWRÄÙIt…»ª,0Š}‰öæ°v{òâ4kVËãÌ<³ÏÄÏ1e;H@ÔîÿÚ{šó÷)°û±@¡Þ˜Ž£ŒFáêÿ‹Ì`Åá´NsÝ;v#5EøOÚóua„ñž…(‰–wDÁUPêa"¬ŠšZ–…IQ@£ Ì¸° †yŠMìÞçqx=¤dSó£Ë}7çÈ=Ð@ª£a Ðq2Š ãœ˜s†ë êš¡’²–›Ý„etëð”ÐeÞtÚƒWU{‰­¸ € &£TßÊÃО$†ŽÍf,Ðaãú„Þ Cò?µWV  þ¬§¥ÏP¬ò@!êöé‚NØ:ià3<oÙéÈÙµ¨ei?lÿ‹õCÉßvµÕ iwD/îß„`˜V³\è :mV²zÇ;"<­}l ëyO1Üa&zÁ0d<êaÍ'; üvE!A`²P"‚€ ¤ ,XE‹X(‚Â,’(É‘a)„B"B,‘` ,‚È(,  °E’(RAA`,RR@XH°Š E$‚Â( RÂ)H AE$R(RAH ( Ȳ ØD¨¢Ñ  E‘AdRR( (AAE‹R,‘dPRE°‚‚É ²È HŠˆXH EX, ²DB)   Ab€ °PA@D  ¤$@IEÈÏÆ-ÔQ¶Ù‰egó€ÂN ÈEFUfƒ $ˆÑİpTĪ”l’–V-[Q¨,DY0S,\p$Àf@¶ •ED5 ›£ÍÀa€nA°¨ÆgbÙ6:Èí}Ožô_ mÚŸÓÕú“÷®—OA~öFL1BÛ€e_ãV tH8i¤«þm•éteŒX’yÀí #ÌELE.bs¼ï}FÚ1€H" ‘F AX#=tŠö6¨{„$ò&«d[Þ¢‚)¤að>]§wÁò‘,I$Û¨ 8 Œ/'rTÔ"AEƒØ röŠ«†–Ú7¯P¿QF툔¦cfmALOǸAÔ c2:@9jªž†ÿÅs([ÔQì?›¯„á‘DïÛíI™g¨”v› 1–8‚ED¦t9¤‘CÙÞ´jqZNc$3øtl§™f ¬Iëq‹0\iÔ5È¡¡$27)V0LÌTÝ‘΂ž„ÐŽû“ÔõMØ¡þãw"³æFïU$Šq¾,Î2«=£3ó±ÝXӼد}Œ¯C œÆÿ7ŠuÍ,»ÎŠÆN3äKb‹Ü o¿œÉËÅ—çsÀ ‚úÌßÏõ1Û°ô<€ü¸õ» ;Á¹»ð¿ÏÆ_v¢?Hÿ‡úÝᬄ#"I>Gs —öêчeº8^ex33Ã#˜M2ŸYšHzN'™ ôû¦×´Ë\qLÏØ·{ú?éÉÙä®yz´þðÖ²Éç­ê–·­e‡.œF™fõ©LÊPŒú³I%*?^KÖF„ ^ÐE•àVµPŠ!“¡bÑU7äÖÖ—»:–!N9Âw!$‡çTɇԺÑî‰jîk.“L8K †gÕ@[w²!‰c.€Ò“4ígšÜ›E;¸îóA‡Ë>bTX-“!(k¼d.CµàÐIÜ ±yªPèt=£ek&›0ÎŒ0ÂxDBk¬eïgÀ´0~¾ªš…¶$j[DûîLÞŒ9BèîŽ(ÄÍœ/kF &:ÞMJÖäxéӖɦóP] MâL+P+@›û‡nB-M"¾\ŠwLù¢õ4Û˜‰ACÑ"œ|Eé^¯ÕÎ2cI#rVäé1¬ÒbW¾¢¶lÒ˜y· pªÉ£Be˜fœ| B¥Œ¥QÂf‹ÑiXŠ €s7{Õ”¦}mM–ùšË ÃawŒâ­­Gm‰•5ht30ÉiÒ´½F3¦&Õ¡äf‡þèýA±HC3 ‹cÅmJ!UZmFÕz«à¢Édý?ôù:‹Oúöà ‡Ì'~"Þ{5âÉãsШþ!HÙÉ‚5»³_Èë© —ë.á½×Ä›§¨ÑA§Áù_é}ü›3·ðÇkù’ЦæuõÌu먽â¼L=šéêIIe¶³æ8@ÑaFø4^bcìcjÅ/‹á”ã9lÔd|žùŽ7»Ó-ê(ïQG~rŠ7ÿ^hvûøÿ 8Z a˜ÃQRÛ ýª›®Ç§åÐ~ˆçÏ׳šÝ½Øt¢£ræD!H’F Œ##1Š”6ž±å5¬ãŒÂ‡Ïn¾if¨´=åäË*¾Ñ39œN!H±$½¥ñUq°"ÃÌ_/’QB‡+ꉉq¡!$ÇAÁöyÒñ_*bM²u“lÉô?î.Ú3 ÃÇSÀ…B ›1 TQÁȺkçÓñ:\GagXë &Å,ä{/³ÿ·þ~"‡2ìÑÐ'_œ@ü@Åå¶ZfŠ€ãBÐøi6"UÕçmï¾óä;Ï© Ìúú(Ù%ÕDŸÌñ¤0Y âi#´B 6dýA3j(Þ+0 Q¯`Ñ…’B"*$RÃAèÈ©ÁÈ`rÅ;A$Dc¬³½DRB+ õ‡ bE HtÙïöa ìÆ(‹¨Á`(¢Äbt¥bE4ÖBÆyÓP”î@³¸ì?UÙàùBÖ øsé5Y¨|t0ahµ#$& ƒÒ0 Øÿh^I’AL’ A €>繊â@‘¾Šv™KjÆg˜ÌKÕÈ× àˆd¢ºUM»À °.‘p»0kÀè Á§ÌÏIõ”MIš31iß…Q—’ŒÈ°¸f˜©ªVü*£LÑ &˜$¶–ˆˆ »D»m ) b™´f:âÃ. T–-Ú ñ,*~ºììÇN.¸™Ýµ“ŠuöÑ~|iÔìg4­¾ä¼¹ o ðq¹{­SÈùrS„¨”ko½Z¸@ÝÎÇ[ŠiÔm)]z ¸U;ÙQR–––AŒa@nç7‡1ÆÒÀöoG³ f™« Ž£ˆ¨öЬ"Œáÿûãí,~M&É"ñ•ÇߪGi8ÆA²KŸa†$ñ`Rlf„ŒbwƒD®É‡@Ѩ£w8Ÿ\a×Ë–¨™"#“`,‹$"”B’HbJ€`„Ä #YY ƒl¨Eþ²šI‰*B±E€ E„¢µ4¬%TRJ„ •$ °*ÈJÖJ‚„‹¤ d«$ÄÓ!T¨ùzн›8½§™ì‡T-¹”º€ÐÑK6¥j\mræDAs )%AÇ3F-0Jé© ÖÓLݳi";eÁ‚‡cÖ›­åkZI ¢HLÍVšÈdÀªPÓ˜fá˜gáÂbBB;’ïeÁ’VPÖkSPÒJ`ÁÉuA.’ØI[(ÄÌ$„Àãz#€†Û…̪à4¤´¥–E²¶æÜmÖˆ«+–Pr®©]cŽ2aM&‰!‰¨ ² 0c- lB‰´,©ˆfP¬µ)ˆ3t¨«a#(”ÞˆnE,¹¡s(-|R…r’”%"J‰eU¶\×ø~CÇö§“úêþ'0c&Ìh³ PGË@7:ƒ8†a6"%Óî{ëâì@ ™Ø5Ka G1KÂKE¨‰ª h©b-EÖÒ|–—XQFåfe¢Y—u#’Ã$êŠ>0FÞØÃ@„P±‘a í-’Iµ ¥hÖBˆÄ»ÏiÀFE«t4{ºèØ×y½åp ô0 ÜØëé,ôD ºÃH ÊþVÀ(¶dþ16Ô`H`qbVÅÉ,φGä0G#ïBÔ<_.c[¦óyzÎâÛŽý´}¦Ž®T€ôöXíÞ¿šrÓ’àð=wT ¦W`ˆ @ ýydB½ùö®Ø„„Bþ?ÈÀ¨\fúÑ»õåÛTs;Ýj0bŒÐîU(Êᣈï;†ØZ¡T„bE’#ýgä‡#“'ÍèÒˤ¯¸°D!?”*!µ–y›¦‚£ 1öz¡Qù×Ô®TË2BO¯v³ÙèxÜŒÀ^'›¢KÔƒU‚@ + H±`*¢Œ `A7sÄÊí¢‡C~…K™™{BÝÆ" ‘<%…eû…UA†,VB°…`HÀÐN¼ú™}¾O:íÿ™C„\©D8ÞöwtæTR„˜X‘ñ ÄèrAŠBt+,{É#ˆÖµ F£Qÿ0®ÚÅ'ãÜw"L[3DXÁ 0` Š#ÀHJ¤)þÛʶ›õ{@€·×øØÕ¬4Ô³j%Ö­e诺CÚø˜ô˜€PÔQ¦Ÿ +NÇ\·Ùchbúñò½ññùn½^µŠ`¡Q²-mlù0›¤ÁNðgÚ>ÑPu€:ˉá;XEÃádŒˆÁP?07ãò|p³'³ª55ÃÐ pìs)0NY§ì§¦O²‚ŠÚ ^&¶Àk@éŸt(†Ýf\^&’(¨H›”e`k0Å VBTµµc!!H*Œf&,ÔEb jU±æbÉÕ´¡|Ý……GñS<1CVtF"È#i±¿ÛfFG{XËŠ³øHlDà_ÁÐ$ª'¾go5ÍŠä–t6ÝímS3šÉ-@¯C ø«¸ë36[¢j˜NKxúIJ‹ƒÍÁíS2ÙGJ©YG‚éµÜvÃ!ÿMŸ4úÁ>GuwùçûÑpä×ùi< 0üw•õUÝ)á„Sðý+ÿ_KøÞõ¢ciz†ÆÀ-±c`æ (Ž Ëo{ŸÇ¿«ÒdeÝNò.u\µÙï{ôòÖ™!Ó¯Pût—¬f[×qfN³’}zù@ß$ê•Î8!º“âBëÈ¿óºx˜ w9×FØØèª˜‘ùx|´¶«a–^{Wý "±é<k͆ó[.gåŽ\î;CCí‹KRèd6Rz§¯'âŸ\Ьüf0/´¶Üƪ:ð×Áüòðãä锨–dÅGrbÏ€dÌÊ 8ƒkàvIãJ00x«¢5x¬µøú>ÛÆ¼®bHŒ@Ì3â¾E2‘Ña ÃÌ—{kZª¨jÕ J )e2ÌË('Ž:P”ÿÈ v@CJ‚¿1f•4²-yæhZԇﵫƒ7‘ 1‚/å2›O‚k Qð;t¦#êžžÙâ£$XÏŸk>“,!j&c÷X ^Lè«;_t6í t*²+þ–‡i6}i„ÊgZ‚FH\NQÃ-µ³2 ÚíÐB¢#†RaŒu»­§†Îl.>Õ›ÌBú¸Å€JàfÙ¿]‚œû1yÿøà@ ÎÀ‡Ê¨/P"Úu\Z3ɉA ß%Cì+_ÿZNŸI,E@&Ä—S•[Êì)»„óß2§ÈjîӈܻÂ1Žüý÷ ¨ív0 ðc¤íŠý}D_=Ç!âDÏàqÞÏ Œ"@Àx`ƒ“ÕŠ–J2ˆ""²"~7ËíÑ¡þ¯ùã}%°Èˆ†7ìøð>=…=ÙöKp›³ì8çE«ZP®B7Ô  /ó¿µ…ëÚá¶^«?Ìe]·ŪO†.”'ØwÓ®âúŸÃæ]½ìÕÆþ¯7oâÁñtê°¦±L $’;_{#"FSY½Êž ¨¨£s«µ} %ÙHäá6šoÔ7ÛÒKŠ¢Ïâ{㘰HÈ*$EâŸÃËiÑJ{ê¤ÅÂð r»ºÂrJåx4ªl[Ñ‘ñìq‹”]P´D!jBˆ¶„í¡t„Vœ÷ê÷cšõš†¨ëˆ$ŠÈ¡®Tvb½'æþ¸˜ äM3ÖŠŒ.¥DÍÿäõUÄk’H—ÅÂT|¸{ºÔ±³ô B¢’@!±P £ÔR D,Ya—aª1^o¢<Ö„{>Ö„{ÒU2ýzDðÿAúÈ›µÎÆ BzóEcþjøüÓ׆;\&ØçÒ_Æñ.ž2Qã{¿ÙÎ*Û1ô˜›„Ò¯Y:Yñ^ƒƒ¶7[F·è #Ѐ ÕÁ„‚@@¢sšžOËðÞ?¡Ó~?Ƕx_ÓUáÿ—ëÆ>5$=ùÀш*„ýŽ­´4ÃÑ—Q±ý•…`j_Üá^)ÂÙéVª°se…Z9ì}‹ÚÑhC Œ¢Ö‘D´“ZP2hV€È‚ÁQƒoÇBŒ À2”…Hm v~5ÃðàN@¶È •€ l2†Òƒ Ž©ˆaE¦•ÊÈV¡6PDˆnšÊHÄÁ hʸ‰ªeMMŒ,.$·°ü¶ç=;D:z–fƒ_ÝèfDT‡MvòrÛÚþj?´ÿ¢~,I1~˜±qåÙåc]‹„”èþ²žìO;•%5_Œ›Ù|bvåc…O ŸN{rÉ£s’užÉvÍóKdÞÝâÖê &eŽVÆuSîµpÃmñ¶[¿¦hÅT,ÿV±Ãèâm’x²E6±êP›d åধ¿^z“zÀ¹m}E¢Ým…žü¾—[@=ŸRÓÄÅWþù²ø«BËMçu¼9þÖ/Ršåï›æÆ­…þötß`zœCtùYÂ_ü¶´üêwvÃ]ò?cGìïOwjˆ¼çm‘9ž~zÃùÿõg˜æBF”¡H¯_äÛËh5³f¸Åñ¢SåÖVLÕ†Õôÿžk7áÚ/ÛKͬ%ËÆÆpW U•IÀXQPC$Š´D1bÛA¥°€1Ïz“_³ …?Ay„ó°ì¨¬„y¾L)Cë` ÂÐ @î¶jJ£æQ×*Êz´QQ­¨ˆ=€ McÉþîƒÃìíœãV" ňŠ,D#ã$mê{êY`2"ºîqqë>9ø\RC †¬BÑ«3S–a²-N©åYÝ9–q­ æµ³è¤D eÃp úZé²,=ÍæâÉåTˆþyvÿ;Âß"rV?gŒ”͹ټ¬1]™È‘^îÐnj(íÚ¦&~ZQŒEX)ýƮ͖ø—ý:Œ Ã?ˆyy¡ Ïͤq;œ¾2B~ξÿúÿmÖ<ÿåkËýýF¬ÁçSνòíf¸'{¹23ƒëMÄ>:(¸GXãJg;…»¸ßðš*ßJûŠÇ±Sa ˆ€€ßãK›Ã)°rŽb›q‰ÉÒE0ˆ/Õ!Ä0fa­;G‡­Ílí¬Íç¤þâ¥$‚ÇŸç#?uµÔ×)×G)Êœ„¬TN+˜aq9o3-íyñÃÉ ¡@Öé(ÍÜÉÉÝ»ß\œ.)› ôgñqÉw2”D†bšD*9&{û @S!il&‡¿ÛiÕÎÂHKDÌÑ£´Õ¶o7½jiC$œòß ¤QbÈ)‰j4à¿Tm¡+»‚+í)ŒFc3ïŠÐdzülúè» %™ûqòüº~å›õ–*’PÒi²×–gžš2%ËV‚1j©àlâxx¾þo§¿g‘òÙ$ãhûØUŠÏ’ óN!†‹Ä×´k꾎´L(üÈïìffãWÂå ˜‘Bý«r}Lšj.‰¿7¾ˆ_e£µ‰ç äb½~m\î ³ãÇ0ëŒwèíBÜ·:h¤#j¬Ó]¶Ynlûj½|˜±©?)¤b…&ïª ¸yS°›”y5êÏû*¿£/rGÚ>ô™ßóU¦\»«–Ö.Û;ÿ›b Ë¼*teO.Ÿkñ.Y½’ÿ´~¼¶x¼€¨÷ƒÄxØ0ùý'¢ú\-¿²ÖùŸ¸Ó^ÓÑó¿¹C¡Q,Õ5N éš’‚+𦹇æ~¶ÇÁü߇Óý Û_Õy}±·`ŠÃù}¬^“ÿCÏp¦Wò½/އíÚ0 I±r™ðØþ<>>—ù¨È)†lÄ\}Œ8Oчn;²ò@@ÐÕ²~'|*6𭝄óÎü>NÞ ð— )¶Ýã­‡¯íw€aTpÙâ@7—ŒB@'ÿ-^ÝÇ4s ‹b›n(âÞ’,X)&\ã/~ !zÝýU*ù59ªXl˜b£êü­P‡”·£h/ej À±‰Á0ŽËí¿ÜèñÍ –Uû¾ÏùîðVf½¨ÜÑü÷X:'3*ݸ˜²NÉ–4üÿŒý)Y)ÿ“Q?|b†R/ðNsõC ÝäíÎ lØkž r6;ö'¬å%uì@A7Ý›ü}üd‹hÒÌ-S!ê2`yªú ‚îñº½TáÇö üòÏ~t\¶ïmg~[âÔç¡0Ö dÚ)î;žÈåõxضóS ʈ¼FÏxÛ*/áÒFêüÊ/Ùùl8r¶í÷³æßüµÅN÷ÖÚËÄ ‡‰;n.ÔÔ-BËò¥Ë£€ü€ °WoÕs>ÿî{Ž ø|žÇÈ‹¬qeçt=BQ4wÜ—æ¡@ $‡õú”ü?3zå?Ùöñ;ôó9ÀÀvö€¯‘¸<ŽOòÑèÐb3*}ý†r°Ø%ã„õÿ¾‹¾¬ÿ®Ç=-Ðͼ^ò(ˆ,gkÆt±†øx,Þ_¡ø¹ÿÏaß»ðãöÝû[÷šÀBv³Êoñ9¤Ï4h†rRüó·®ÈK!±[9S|ÆÖ ˜(è, –Ÿ…'»±z‰± ³P½@&?þâµ()¬}Ü HÈ ¹§´Ô­+NL7€É †RKÖ³Ê÷gÊØm++ÐM0œ>”|!°,EçR¤óŠ€Hè÷?š;Å€K±¸ãM0£!μ*ïZjVÉý;Î4“ôü2M}ØÌÙjÇY€ªÂÿ%’R°p\JðDUžG gzüD7lñ«oöî–p6OGC£êù¡늼Ïb¼,ÇÉËúì¯Ûîì}K¯6RÈV ‡J •2ùŠèŽ^jõº1¸aþþ“ª^®7êâ2nqf¼öKðFx¬¯5 sÝsÛVa}Võm«Ñæ:Éž†òq“Ø6˜p €AguÍÕ<„¾tOº¹ €` `…£­H]>…ó_«ûn…ó¯‡DnùïŠþx[ÈsÿœÑµ P`”ÕÂP‹ÙÁáÅß½^Æ}!ͼù™™Ÿ¨FfcöàáàzºŸ9µ×ñS½œ”º€5RA¤~¿ã©þ—²·Ÿ¿ÝÈ÷_oÍ/Òá0.ç·5ÞŸ¹ìZ4o#´°lZÀÅŠÐ<^xlôÀ*á?€ `>ô È€ŸÐèY€¥ÔHðP6+Ø~{ Víÿƒ=.ôЫU—z;nl¾|ð|h(övt³Cš²D*·ožäœ,<‹•j,ËBÿö *ñàÓä¤öRõI_šHqC;ÎÆ’½(¥&kØŽšîõ£ç"Ì¡¶Uëå¼Pšô€ËÝBä§zhØCh†}øbXIú¡óµy’ð/ñ<«•½°›9H/H¹ØµÃ éNøM|‘™Ò{i3lÆA‘’q= º¡XC`l9õ”FŸ3¯xDvé*ѳÝ$4^áWZD­>™Œ#)Z¬^)›GªêÚìôÅÓ©ñ*%"O,“Úú =“!ÙÈ â?Ûo¹"±RãQUX¢¶^ ¥˜ÿt§#SÕÏaòà«ÖuT“ÇΦú¤Aájå@T. QW)ý¤¡™ wÒô(¢:–uŒõ• FmÁ9•Ó0®n6öM\üµ ù&X ÎØ&~¤ìZ6‰Iä?u%ãjº÷߈Ê-£ÛD™šIx›(øËŠ«³bPV7³¢0ò%ƒðêþ¢^ªïðçìƒã‡a.¹³)^Xá…öUÜ ÞkÏSO Ù,•Åà…¸‘8»­›éý†ûzŠ^~-™b=ì¿—“NÁÝÙ ·‚³©¬v»”´ Sx\ºKÂs;¼Â?'™¬¯ªîÞÏ8ÎIH‰]ÏS‚C_ñ¦m$«÷hêÿ4 æÉzvЉ|ì‰,zgHbºAÿžQú~ÊWç{W…÷²q/8+ >9üîÉwv™Ì²Ñ¯%u®¾²í÷»?OõÎàs’K I—O²hÊMJ1ûHÈ?H²%1Y£iäõJ_#HhŽ?#Ä……aÑoÙþù±“чسÜÚF+‘aé[µJ";õ0ñý¬~NÐiœÞkSžV`€Q_Ää»È´d»Ub•¸þÃû!™=„Ì©uI9Ç9_ÅPb/.ƒ6w2æ9‡óߦ7bÕñÅ;˜:–}ÉŽ1êäÑLwB‰vuöŸ}š÷µWòù×Ý$Ð(ò­ Ì5X@“Źþb °äë—£éþ¤2!„Ä< ôM^ƒ³°D=\©Ð•ÞÕŸô±ÐÿpÊîtˆÕÝ%W_úH㬒}6¡/ÁЭ¶¯í!™1gtw`§Ûiüï[Ùiö lª‰;Y8ŬwÇ€4í,<ª8U¿<Ï?÷_@°À¤ñ)$E0û ˆ6vr¿æXv··%ÊôÀ^‘mC]™E~~—’XZ•T3>Æ£YŠâ,¤¿íºb´M ½ß1MRÌGLW¤D¤„Rað†Ú.Ãy­åþð2ïW¢4¿¾­N1'†Y%¾Ær„<Ž˜¢'©OJN”Qb-x@šþ9S¡uC+¢0†t4uèØ‘%&èWBýã¦õÿkíÿØÊüI1H–Tï+[ò]4ÊÊ] ^v˜-áÈqõ'M!ÎÄò”Jû‚·¼èêïò*†|¿¾”ËùŒln‚ Ø“ }ÃAÑÕŽ\Ô ÞõK.AòÕ¦u´LsjíšÏ¤üºRi¨÷üòj]<„æ›8«j£(·ö¼Ñ™‡mG¿—á—û•âàZ Ï(¹¦yFñá—@¢yªÇí)‚vh¹ójqk9ÈŸKVài¿ûcÚïÝQ°PKJ!Þ˜ˆ~—ªk¿Wö1–Á![Ã/Oæ.—àt2Î_O/ûÎóŽËŽ` n¨¿×ü&®ÄX„¶TQ^œ¾«àÈäø3öó£N²×ã°íúëdeÅé?Irwœ´ ®:¡Ùi$WË‹ýv_”99´8†áíâ÷±äLŒühÔF£bîî®<ëB¶jhδÄ0¤<}¹HÏPq~žuœS¥ m_æ½oŸÕ}TÍ®~¶íM> xꣿ•®øè{¤ÿÝiô‹«}Û³ C,i‡#ÚûÏ­agþ{º7ÊïneóÙ|Ù¯^_AõÂ#W*‹|ïùÿ×ÿa°¹bKÃW˜€Ïωñ3ÉN}jøGÕ  àxÑù~¤Yàt_™[B‘ÈbdÈ&Ã.ú"PškÞµTAnFôøæ°ÔïÙÚ:8kɺ¡jë¾&&zl’L_øûj9ºë"ï²I,íÊ(ôLQA´u—§ºÜÆéÇü X o¿2Ÿ)yÂð*(<Ðý ƒ•g& ÿÉÐq l¨2<¾<û$Å^$¬ ƒðyÌ~]åËÓ+’=t,Îc¢{ý|p6tûÇãd*¦ÙžÛ)SvVgųØ\пÖ诳â‰|ßÄ›ÀïÌž©Õ· ñó8ô »ÞŒÎ>d½UG¥›w/‰õú88žn î¹P+ʪ«º—¸ó ô² “–c§ij}Y¹Fr¥q´4CheÔŽZdÅ_±³¹ÑÊ[ZÎ1 'Š n£®ªÌ—S¿Àf{È’‰N9x…5Žô¢_çÊWÏkH›}~ Ys™ BzjAÈkêÙQ ç7$”09jmм< öê°ŽùF¶ycØÌU:­)Wÿ/¡ JFdPÆ‘vtö ˜À?üË~yƒuʼn”ƒbÙIÔ#û”ä8C©m÷¢"íÁŸÚ+5ÊÒLý›ß>ÐÒ™öåR‡ç±7Qüys‹¸æ¼?APÝ_5ßjã9´¶DŽ÷<îÀì¿´ÓN³ÐÞ¾„FîšgΞíp[à.ñN±ÍñaH¢5™¢`Vˆ¿²X[²ÆFŠ=È©žº®ê{øh¤¾|>8fpRO=Hä°d¹e¦ßäopîêX>чæîøºûBï½^ÞK’¡DE ï)âkß’*ÑÕ“4L`_=‰}šµP·j ¼ÒÊ96šŽ\ǦMJXT;¸L~®‘ÂQ› ;Ü‘]Æþ叨UŒ«ZþÕÕü-`ñn<­Ïωq«":Îõƒ>ù¤Ö–mv½Ã>ÏT»Åö¼›M—;TÛPÕéÙ¿¥ºzÈ]¹²ÚWÍm€Ü¹õþz!†C€ø®4Ä­ïùX%”:é®­Ç´bè \—w ‰«Ô’¶Q=,É+¤œdü¸OÍL­®Ùov”ì—Ô¯§£ œ;ëvp¾"×o›S'ËV;:{÷¾7û£¶lÇc-ˆ(Zŧ òf†ô=!ïÅ3/½yž{Æ–ö^>ögí0~ÎÃjOÐn¤©RgwXÚ$À£Ò&®ƒ6ØDjÎëÒ©ñ²ïkGb4(ñˆ ‚šTUR°&m’„ùpîºKå#SŠÑÄ0»Xì¦ÄÐrÏŠykä.-Öš‰ëU[@ ·?üéN-Ææפ̸ŸÝU!ì%³é0>Û¼Q} Ë<˜e"¡‘žåèÞ× ×¾Xz5׈ó¬º^Çc~g; ÖK ‘ÍöÙv»bÐrb#úš/0¨t Cm䯓¤s_Ñ,B#œ@ßþp8¤‚­!Gxþ,.=[ÿi„¨¿Ù¼sÁNv2=°è#õ~gy‚ÈÏ’~å—¿;E¸S˜ëy›§sý×+×iÓ{¢©çN›£ÃæÇƒ€·€é€ª$¥©ûóÜš\!Uù-ˆ$œëè.ç»æè½µHY{t”[l65>K_¼Þñä<ÑV“ € Ö©ò¨ÄÊEùéÃO¥‹«ÑÞ"·cŒf:îì:Þ7Xî»ùçk„güã¦úµ£†‡‹Z`Û]Î/07Šèg.VšÇìLZ!š%sÃ0÷°qÙ“G¡¯–މ`9¿%`@v-ô÷oÎßeøñŽ÷Ò@Q¸V`¾WX— Û«FW5¸”?]~†ZÖïÚ¢ÂzÿRÿÖ“2–õéiØÉ1êÿxÔÊÒ7_2èÐŽÝay¿ñ™hïì½;­¸J“al _8Œ=_ÊŠ+](Íü6×;"÷•ŠCœ$ŒSpÃ!áš_XòÒœ(™ù-úQ™ òRki_XÔÆ¹ÈªùQî/ƦI˜Úuß=ŽÄýAoæA˜²„{=êigDœ™çéN½õžÂÈ«Ôs5êÚ'y0xvüÆiïtxÄÚãQçÄþ̱ˆùí|Øm•ôá1¥ËãXÅh¬Ó âEGàŠI˜¿™nßÛK([ߦ±^Úð*ÀM—¶€h   |(%FL™R¤¹åz Bìñ8÷4™ržŽ"Cƒƒ“KÙ¯DãÇÝð²F¹f^ÎÒŸÎ/èIQ‹ÊÅJ_ö—È;¨¤}æÃQcMé¿F#·Ñ”!YÐ4ª§ÿÅb‰‹U)k19¬ ðRãÏfw¯êo£Š‡â&}˜wü+HGj!%ÅD±°2çš„ ž¸É€Q.H²òÓÐÉ[õh‘Þ sV®pú!ì4ˆ¸’b›ðèW–FÄ.ÏAö×?ó_Ó’þ w7zH U¤ 1XùÜw“aÒš#^Ö¬ñöÉq4<é~b‹_½!‹o›Ò´N|EØ]¦5ç¡¶£ç¨ÉVµr/›/$ ïÔÛô\¥Ù`nû@½J[ÍméQ*[$9}¸œÀAO»KYÄ•{X:”BÒò­jûƒÑ@œÎ…Ÿ‹!3Gís ÁèÀR‹ÃÁd´ƒC¤E ˆš„ÿ¡2 Ëáûƒ¶„!ÞlLlãZinMѳÓÇÓr†P˜?¾Á?ÆøÃåG§—ü=„ërÝv?7/@[z3 vƒñš_ìÅ3bD¹y4¢ê\$Àá[Ûåøº®‡ý?¤|~‚k¼¥‰ôE&ÿ-ø¥²©ˆ=ï6HhqŸ6Á û&3ìf‘A3ƒCTÍ^¬ê˜p•1¾{A¶LOœq}åÁ‡òZlþÊLNþ=ëÑßçf£¾¥ éâ±2Á•{Èbvž~sl‡×ù €!¬¼;ïJÁJÝ>(d0 E°?8žÛqqTÍàr‰ÄxOô)&!á~>DFR.±Iî¨4fDCzÊ‘9†ï+ƒ/Ê£I’´yŒö¦¹ªÄÉ=„ìªùºHª'“`ÏÜ@vû»\±IwÒbÇ‹`ú‹ÊnzÖ-õ9x½lnTÖhÇ6ÃgmUj‰…7ùÖ*_ܯÍ3Bqòž˜z0Ù·ž Oâ Bj¢c¦ÿAò_Jq§—/‰R©§Â¼RkåNÄG¡ŸZS²S´¤5³ÓæŽö9üÈw¹¯>mö[飃î ÍNd´ÜEÀ ®IvôÊz$`«ôiÝŒl†°,½|wñ „d5¤~¢Áu“ÍÌÅR]á°Þ¹"«Öœ<1?ñ$XôyPƸ" 3ßiQü²¾]™ÈИž§Ñ#!X¼ÀûB8? w:fÙ<»fíò2}o,q¥iL' }»´l“ÙÝÍ3øŽ7º¸£cg+ò!”ÞJ{œ® T"”ð-O¢k¬²ŠŠa«h/‰èw›ª'R˜n"^“ ÌïÅèµ…Óg×§Ý 9ú³¢<ÿ%O0z<ß^#·&’]Æf?‡6ìÕEá,Üg+•Á˜g\ÇAÝÒ 9à1ŸßŒ’Ì’di‹yíÌÞP{¤Qgy Þ§eöó—¢0¾ÀóÀÂ.³–!l®/r›¤u$…Óއ¬ª,à3jE@¯»³c¦+Ì®Ø4Ê6AS$òÇ#噆§ª£Èªüì;®!-s?·ÓšC)ø*?+—ö@ÑXÿžb£”vkPÎKü»ÞÉßû#y§÷ZgE}OÆT/ëù\ÑÝæÄ_Œjç›{‘v·r”Ë"`žû‡2‹ö‹>)ëfWô‰ì’^ùq'OŸÎN ¥fªX¢»û˜Î(6 Ò$Ú}ܸ¨øÓăf«äèšSfx#Ãç:T¾ö¸ÒeÙš€Ü,·„ÚÿHC"^ K{V!×Ï¢%Ê ürƒñÚc{³×ƒÃ0·!ä'Õ i,”}L§lT4ã š‚ίàÀ܉êé$íO¤DcÕ>̆4‰—VßM9ø'Ýšº=¼¯hê¿ÿr-ãGþ$ýɶÞ4ÎÇ&|Ëz„†æ ¨/yJ¬ËÝ?jÂÆ÷5ØÈÞíãì‹Qñ ósP<Å1;Ö[ªë\]±=ú¬›¢[¢=bÓŠ¡P­h ŠTä œ–¿}¤_åRŠ^éÓ핟«ôc›Ñ‹¸P$“º'\q q…eC¥•!½7-· sp㩳húòôð¹îú÷XÝ^íýT”ã¯A&CÜÛØOgÖ‹3q ù#úö5ê1€Ù­Gg‚)lçEÉá{6ìÀÔiépú]¢ee!¿yääŒ9$*_È 7Yc¤Œm±ÞPEG=²ƒÀÔÊ:µ¤žÓõXãcÈÛ¦jAΔÛGW¢Ç8ì:×{eÕû<›¿èƒ°9:}Ÿ ÕÓ§vQPËÚ«¥~.?¡zŒ¶ ”a˜ß•¦Ü©°T›ŽW(”!÷YQFùôiŠÁž cG¦wŒ¾{C''þ±õài»Í%ªûj&à|r™r…ò}[Fâá[½<³°ö>;7‰êGcñç@Ï•~K>¸I¾›•œåQéÙßfé™ ,É?Ì¡ò{œ7´çÿºù7Sˆ #j¡ÅUlŠÞvb˜²…}’OhpM?UžÐ‚}p¦QÄ×Y„ô®´K>Ž éTZö¯zº–èïèõ‹+Ø›‚ï¤ù6ÇÀï'7û>CdP]¤‡ó§,èXù)ÝýÝÝ-…˜^nL>ꞇö|URQðàÛð?Žñ@êèóEvi«3ô“;7•ÿ­ý4ÙÉÂ.4ªí7Sã9¦lR£ó?“Q\îd¹´ïž6t."Ñ8ËíïßÈ‹ ök_è/ Ž¥›Š~² }ͽÿY8‚¯mê ûßÅ4‰¬þOØâ·™‰ø@¯Â?y¿¡xÖMÞ€·³Ï……¤3GâË[¢ÀþÄ–v÷y!}J `þ´O5²Àì2»9¶.® õzT׺IS“CÝøÏM)ÏëýƒoÚˆ­EÌO„‘P8ènuöÃ1º–eïóØ HÇöúÖeœÉv\)‘Ô4ù%ù½éoJ4éÖ¹¬¾žSïšéSæÁá–zcŽIȪ¾[‰nZA”> ÿ•fŽHÑaÛ<6‹þ%Ë„ÔÒ‹˜ÿ=‚BBIŽ0Âé-ð!hG]Ûµ)ÕÅ÷¸K²Ý¾K®¯æD†ceqÏð&ÏN¿;Äý+Ã2²°é5 LÓ"ëcÓi_tÿ‹MQlºü‡Ñê¾JY ý…ù¢–Lëà!ôo”ð ì^žGDïе}옹 ¿îO±wªîSÔBÖHùÒÕ¬L2e©8©0Ò*ý~[ðÝ”ÓÏÑ6ZôpÕ×zž‰qUÙ\1/³!‘hú™£rËÏ XèÉdÕ ¿Ë§=¿Á•-7„~|ò⊺9gwNa£N8#±¶]ûïîïŠòÒ ÿê ‹ÈH‡ùDý7_µ‚dB`ÊÔ`W Q>TÅÙ"¨Cÿ2Ï5Ò3W7úEÌ¿N;tÈ‚¾&Ù± –i`%UËò3â,?ÿ·æv\WêE,ˆ„^Fu½ÌÓ0’g/ÿ_^lŸÑ#nQ;*.ÆŽtBlm`„Ô™Osè±ib(ßf†™³P¼±~ëËÉßÿP¯ˆ­ha¨I¥éæ'ôšRvºÒ°,ä ú•«YyYÄÍ Î`h$¼±¦ôPJºò˜Ó–~NÉuÜ‚ÝÅy#bAB±4Ê.ÓWÕx_ÕýèeȤ"62ñŸÜ\¯Úû,òüšbý¦ þvæ‰èElÄ€a­ZUØól„Åø]uðÊ÷Š¡K”L#ÇÿÓV戔Þtƒ1-M¯mvë‚­öUÁüÏ˱bCñ`¬™Ñ ?Áuùé5ÇaMˆûÛ*²¸ycJ8}W±fSŸ3ŒÏÊw.Fëaе²†ktyPj¢¾áå‡Ò‘éê N3ò%Íð®2J²ôN ¼>×,kŒ‹í˜‚_mR³è/ºD¤L1©î6FáB×ìôýŒêë¾M|š#Hí¬SÕ×›'&o–Â…—ììCûííü÷ÿÐÅ#xd5?A[éÜ­\%JŽ®cÜæº¤‰s ofÝtc[@£Ž÷¬ê£1mÚÿõº/Á"G´}ÙÎf3Ìs4¥#OL…a‘~—£´ä”¿ïh3ô["„ÌÒ›Éf¬¬R|û6˜ooh›ýµ}8LöþÛ52Gˆä¬\p€?2ú…ä)F¾BÅ»$ƒ3µ*)0êàÞ_¡µi|m]TNW=?%GD+I-”4n&–HîäˆÉ±®gånص,sµ#à £¿SºEÞ$«K\ŸO¾iÌpgèš=б§ÁKdÂJpˆ¡´E¥Ä¶U—¨o‹)ˆá†/4†7Œó[4¿É…¼­#;$±îF–s“ÔcK¨^¹ÄÜ.édÞ*OgBî¤ÿÛL{r šŸù~ÉUknÔ £Ú·y¸H%yUY0>¦´Õ[Gµ _SÓÀG… `R†ï5¨½œU[„1ßÑt’`jލRÞ0ñ£žàÅÚp/éé…û¢bV›ÏÌ{LÿgäÓÓüM_y¥šoÌâ¿]ªáÀ>Ø’£yZSìðhK´C¡ÐLJ2à‰@¶õLL €W£‘V‰»©]ðõ  €FñÒ) ±xÌÐ 1Û,_2°žýã±°¨ƒK§p¡ŒÍç£8Ó>2¹ÕlC^ßéújª ÝŠØè1bîÉC&›ëkbP[«ï[ÍØØ]Ë.¿h /ÔN¬ ±”ŽóZ^¸3 ’•˜u|É–×S)ǃŠc¢a8›ØÒ$À޶|u—‹æ±?ÓQÍ—î$ñ±05œKz-iÁ££yçßÜKÀ×ÊÅ©Æm³÷•´€µ»ß+ Xœfb¶€?åw¹JjŽäÂðaB¼äçßæÁ?xз蒱ê2|QìFEþ¼iaS®Ëö+y]µ¨EÖV¼z·×ÆŠVP ³’xë?å+SfÎIÍihRó§C©Ã;ÜtžÏ~è§Ñ / SìA êÏõÖ0ùT¯@±ØW W/À}§Åü듌^óFê+>A  (o»èùÓúa´ýËaª ;gæó»—ÍèÈGm5øÒßj†-Ep½ÂØëñÙ¥ùÿø¥Â‘h%U« ¢U®‡j…5ÓðXij•ûÿgÑT™¬ª)iÔ•£ç`6jñÐ뮳#Ay‡=ƒßÙ×W×\ÏcqáW;`³|ó_ì¸ þÎR Ö˜|áúŽaòÛmv„‡ò¼ŸÄÄÆÌÞœö3Qƒò<ú J;©m›îEÊ8)?k‹¸¬$žmÿâùkwb,¢«yïÆèl0ôÞBÓ– 5²F,‚+*Óp£¢ðù!7BDn¸ŸöÚúm4óIbc»ª¾³4æ¥@¡÷ w—|´Nr›ó˜¬kÞº…Š-§à]ëü¹+=Fè³~Žo\ Zi­Gô Œ £ÒO†F[èUk(œ5üqi40 >qÉvyº£%#Ò‰Hr®2Æ¢Y?(ÌØæmÜíÉ‹tϕԖjš†¬ðÎ’?z¦â¼tÆ‚2áBe.ÃªÜØ¡_~_Òør×ÌZãÀT¦û´vØ/ $9yíÓdI÷$®jiÖW/}s³Šö©ÇõÆ®‚4‡Z©ExR®½?ñ3EÀЧ@?°Óù›J)UŸ&7«ßMN­4›É·«þJ9 ®)gÙò]ZØ„Ð4Ô£ëtš¹öþ„RæC¾z 2§]r ©—wU¡O &=σ;dWÏ:Zg¨¬© „òhIEv>¾¿Öº $‚¦7OË(î6íµÀm«©Éšh>ûý>‘•M[h+Ä æº TÃÑö#GÆ–x¸÷ªðÃ.pÇ©luÈÍ4¦‰ôû.‡n Ëêæ³FfêVdIðý~Öò¿ÑõSëOFÞNôÄ!Žãý¹Vù+ÕaÌŸ†YæÌ˜ÕE¾ '¾Çn[óӜۺ¯ã¶iªAÒ*6 gÕÓ¹ü/ûÁÕTY’—ç?aºŸåÄŽx1ðæ·ú‹¨øIcÿÞö¿Ñ}óÓÔŠiÓj£·ˆÏ!Bz‚;Ý)3Áê~1œïBVØväø omæu£0èöÙ¼¨77 ›&† ©ù«Ç=®*7tF׸«{?êºÆÅ4µßÉEª†% rRyÁ™gòmýø!ó(oè³Äíßé,Õî|ðt‡6+±…ˆR²ŸAFâÉ4kž†¦Gä§Ý?ê‘>.Q.[ì¡°‡JT{ŸáïÓüú !ðQ« úI@@ã–hlqëb(HÔ¿Kby@êæ¦"#´#""G15ÌMÈЩ"'„¶HQ¡‚Œj¨dèÜMšXÎûXˆ¸”¨¡'´ÇYùÝŸ·9zéyK9‹¸°ÂK,ù‰_BðÆ™4>j|‚%`é²_Ýo¡äÆ(Ô‹„h÷„u~¼ (Y‡²I}¹Ç6ŽtßVó]IÒ{{艴ÔÎöŽô`UÿÓí*ÛD“íôŸëFt»2ì””¢ò´G–¯5UZã–3¢ÑØ`©Ã ‚ãcÖ®z“ûÅùü i»=þ㎶Ze$FÚ4Äà g™éú“ÚY %ÏÙùàã¬øXâ¶æ°ä²ph}£2Ÿ_òfë„߉€áûüOƒª³òf“x⯔cUUz®—0á¬ÅÚ§’¯6£;_Ãûhï+ïWÉîî›»ÝÁ¼r—;`T1øD–:§˜Dÿ™G{ þ‡õL7CÀõ6u Š ~â>§§'É_‡™ÌlŸ£Á­Øþÿì{¼qºlaî$Û’ã×”˜HaX+ê6²<ˆª¡ì¤ZIf4¦m•¥âGˆòÝã¥ecåú IdÁïÄÃzö¥#0Tw¯²Òþö¡G¾§ìù‰ËÚÜÆ9Ý*iî͇Yþá¼eÙå·y¹ F>¦œ,]‘Ÿ·Àö×´ë.ØÄOìXíÊœâíÍ%øû%H—!6îÐÎä5už¤„‘¢—Þó5” wDi)1ÄСµµ¾ N:ÒZ´•®Š¿1¯¤40Ñ€·^ tV‘™Im‡ëå}¢úöUûþ4Á~s;µ¡K-ƃÕ-ª´­ØÐó}—Ä&xnm±Y­ð=žðÒätï›ò„5Ýèõ UcfNéu’ޱlJ;$êën9¤Í(ö>#þ²¥TsžÊ§·g’°Ö<”[Ý£H·~åeó7"2Ú¿LY«ÏûUßR[Ðà^£½`UËg³îÞ-¬e;Pó:äøYÊ;Î>^ÐO1èrÁEq|>n!ˆ pã?¾jH!ÚÏÄ´+‘G©ƒ {xQƒ‹Õ,c“Fbíq³º[z}Êð”ÁÅð>‘YËUŒõcYµJÛ¿ÃøÓ¹ /F*u‡0·<üJ@[îÈ=ŸÒ'n9ëù8íçjp[ø§|m2†haتÞd;å‡&aÇBÑúFÒÂñ³ÌγYô:Š­0’ÍÝcÏ®úÊr ݦ~W4‘cèm“ËX­äÑ|ÿ©˜W¥µã<ñ9ŠËãp>¨ÃphyzΙYNöçI³Í.êÍŽŒx[¥…õ÷µÝZ… ÷þȨ¼¥~œÂL’’i ?t]5z`ދ÷d÷š¹ zÁÒå(˜%6”˜ûSƒ³æ ‹ß¤ýÄéÈjb†C¼hPòšïc„²ü@†ƒ)sïaÜä&aœ¤6õ0ºûÇ×[N¡VTã2ä–çLv2¬ i?}%êM§ó_ï‡ÖªÉ´ð{/Z¿Â‡bÿ{/([ʰ»Æ'nSìh-Kk€ò{õ2n‚ÃQ‡"{sZúØ7$U‚Œ]rÝX&,”½QÖ…kòëqa,öÿ—Ò …“®î,·î ­É± D6É#kç-xŽîŸãWø!É‚±y½¯ãbyê–L;`Âͱ“©ï­©Fóž¡üºÿÉ šcðâ ­$[º‘M1ÍäKÈÕ·<¬‹M†`öÀº°Ñ´¨÷|•e>þ Š»Åà½ÖBcˆ¬æÄäÊoô ÕÆw°}„3¥W‚Ñtÿ Á² ß;òÀ˜w]ÉÞ\öLr”ìàÊ©‹¡+¨¥¡c„ƒöÃŽ$•œëaãAíÕX÷ò¬ÚåÏ^tç±¶6.;UŽáŒÛ£8L Ñ#å~G¦»N :a s¿‘ëyFÛWâKÒIyÍ[²Â•ú.x>ÃAˆÎg¥d}µ-á37¿tKC¬¯h’¯·îžËæÕµ%Öy&®zH•Áâg6 ×Ç#åúWx89õASaŠÐ0»õ­$‡¥|†ËRZ7»Ñ0qËVÿýöY¢r(‹hœUÁßâ«X*¿ÝSÆ»¬[èZôõlôÇý»U9g×?ìû‚±Wª?ÔL©ú‡øÌj{þ‡2úoðËÿlïãGûá¹±îîæ<4¹ZÓ`tÓøµ‚þµ×¦ÂÖß$9¿zöÜFù…V•†U<-žÝÉNÎÔgf­wƒ ƒB/xgš Ë€á¯‡Ø½õ´zï27wì!qаj¥ØP.‚Š+n è„øLYAxoc "ÝNˆOfUDÅÈføê¬4xª:n,‡PËø(|!{«ë~jG:ªe²å~-°ÝÃ]š°Õàh;éÕÙªs°1²4‚à–7ˆ£vh iq~Þe"‡ €E™)wÈë¥zÆÜcáê¤x«y}G5¸]•o>¢æså@­Ú –ÇüŽB8Î…Äõ/[ä˳Ƭƒwínôjt€ ‚€yJ]¿–·ò=-ïSf0ø[÷_úoÓz§ý¿òuµ+ƒôB^ãcQ†§wò»WÂ"U²øÇÇ,k›ø¿4n‚<_þ—&‚K_À³6š$+¦ϽÑàé4ó\IUìµ Õ¥+ü³Ú* x» ÜçOÇõ׸M^‚"¬C\Ëò=½†šúi 7sϟ“!1yÔ~ .r«2:âfDLÕG¢ú+žß®ÅDö››]¾ÔæRbÝxlžóçê§:º›_”BKáQÖ *ÌËS|¬J«v²›–E¼tY͉›HÆd#\1lxèØXM÷¿áØúJWá˜a+þqÇ ^‚¡öùbêËžäû™pôJÈ}JgÄU<ª!ƒÑ5¹·í°ÿÜ)R%“ǫςù{Ë. zåïy(¿0Ç·ðRê}s,ªÙK\¢ÃZ§þ¤;¯iâ$RJ3_£ø¹Î%Þ«ÂûuumeU{6” ¥ÑK馎òJ=Ü}mv²wåÔoˆâ¬F0Ÿ}a³SP0…÷ü‚m¯± K¸`Â5…»;Š*¯züýÿÇ™Ü3¯ñjáö&téÇØÖüæ§7pÇ}&WƒÞËiügPw›À)eDV`’ó¢µÿ$Œ¼ä®m?»'q„O5?8 ä¡÷Ó(ï+_s!:…6q#[–(½=­Ó׎bÙFBÇBúGp\ó\V¬‚of³ëM-Þ-ý`‰ê°’À¾iQäJY_ørŠïóžœq!#µ’A›6ªÓ,pÐÙˆ@ªo^pÞgΔ`Æ£®üïÁKzÉEEøf¡%,»I#ïs™!:N_² ÈlïŃ_áøÕ2Tå‡wƒÁ{Î,jÔõ’Â13=Ä&©çM 5s'Å&_ú©ÒE w°í˜±2›õýNØG“ß땪)WUA +?)ÄjhEަèQe©`æP§IŠëG´8LB‹e8Üœ:îÁ¡.UW_Çñx\J# S5ôn|«¦³û ä·ÎÝJî«j B»±}³Yþ¡ˆ?Ó‚›Ú|XÌ÷¨ðýË9@ëØä¦~Y°û ݦàšnr«Ô,Î- §?œHYÔÆÎûùeYª~;>‡·ojÒ¥ž¥\häÖ1}®_wØ’Ò|'+õ]ùkÇÛißÊyzIlØsDjÅÅ÷|b}¡Ô…•j=²+Eº%c)¨‘ÿ.õ:‰õ2•1*;ïæm Äë(•u5šÞk99˜S×ÅʆjG;“íê•Eñ~âB%&ÒµÕ›ƒo–|— ƒÐ\ÿVÙi«û¾мº·¨´ï¶f2¿_Ò¤y‘þÛÃuáÜO2gN@9(὚åžÿ‚47ŽïA[-.ë×ïN²M ±°Ã+ÏDï k)fÌyµö%µñ„Æ“-€”Ïj;ý‰¼‘±ü“1òú¶¹=dÚ¿3‘$Ö¦øÐ3fúŽ’Ø{‰dR6Ñ2³è·Ï£oi¨?Jz¤úebB)ÿeÓº†æšÌŠÑ1IãZÃdâàIàãûwl.qßÓgSóMÜ“•keÃ6Çã,ü@ì~/¶²íoE½¿6¨"éÌ 8ñ1Ð,çjŽ GöOíSŽr^ð6'»ÉAb±¼Kê®(§~d…YîoôákÁð•e_®}z³Þ ü·ÊJlô—}~¿ÓôÑ ƒ,ýÊ„?¯p 9õ(.ë”?_›¢d+¥3ZŠþÕÅ=6~Ç‚ÉäÑ¥;—è5!) ¯Ü×"Q¿kÅ„Ày¡ÿáV/Ùù¸tÞÉ»uyÇÕ©v|º²¬ïÌ 5øÇ²µÁýjD}¨ã0å™ß”t<Ú¬¯іݸ~(n{ˆ7 ß-½íq€€‡Þ1•ú77O1íºc.µ©OôÉûC¢1Œè™Áüƒª™0(ÇUß5ž÷ųJ_E›å¹äÂÏÒ¡eÆîò"‚?º@CnAß¼Œ‹ @oÜç7ô·L?TPExˆœÌ÷ªŽÙ}cž,?Ñ„·_èÿ®Q­Ž›ªiBNèþµ·ËÛn*Al9÷æ8Êä2Æ~ÕîÆÆ¥üRlÝuxÁzµÆºzˆ/ xñ㨤šîWëÇÒôT7Š>¦2Vî¤ÑöäHrnèÒ8Ýgä"Ùtô;†Ñr•ßMK ˜—$ç㈼\ò„2ȯ ÑŽùuòªe;§°SðãF•rt& _K·-㣖"Ã~¶´foK$z‚:䀸Ãù‰{fŸÍM­…ËVqº}?ˆ·–vulŸxK£ëY1 ×Ã÷ó÷LzÕ^‡’!Ã¥èò®¾'¨mú¯†jìÌYª¯ËBG=¦rÇkTý4ìnùe0[ë½t_σ– 5žtñíj ©<;ržÇ†F¦XqäݮЎ  $ª1ž4-<æˆcÚæ¬úŸ7¬Õ™EC•S1ìy‘Ã3æ7ÊùÝxk4€£õ¾wª•+wæïü<æ4Aö¡KÚ;^’`paþƒž Åþë/8':dÝÓL™=ÕäÄ©g·±-´N«B)µ‚îÜc±÷¶Ò®ä°ØÞ”pëõ~Œ0¼'Nøè9æ}–£Žë3ÆÀû‰Á­“!5U|ÑBĪ­·'…0å,†o}î×ÛÀ0)f‰±ö»Úñ3ÚP|`hV¾²% Ê µü)g„84aôd0*ÄfËUŠÕDÀN ‚2hº„{LÀ@#º5:…±±msgX–S÷$–¨Å\&Ý¢¿µ}:¬o%uö"ŽÌÒÑ2£œÿfóvgÆ1jbÎz>‰Øìc𷝦£Û¥$að·ŽF^[Xà b“iÏIH.qƒá6T<þ›qâgéíèÙYà¼ Ø ¨06d„áNÄ=¦›‡ÆÖ× 2¬¢tµ!Äjvb½ý8e BAögk8|™Ä—ìrqUô|“ÚþëD¤7ÏUâ¹=$Ûž¨Ùq0…WÍ•£›ÉíΜƒÉÔØÔŸ«%®D–zHè:ëlÿc•Ÿƒ^î”,²‘zKå÷£×òÖ? *Î P±ïœ@抹ÂA½,ñ·i iÜ€‹Öy·÷+DÃ|Ê©òÖü³Þµ¾j­óäÓX<T&ô°.Z‰ÀóÜÂbÀÕsr<0;.×¢ãÀåƒ14¨%øF1çDZþ¥¢V†Q3鈫±°DØÿ›Iãâ–¢c½ß˜³Â"I÷õÃÉãlÌ©Ÿ'833F¤ý›²,)‹Â[PQ%ÃHÏq27ð³ºI Ù­äæÔaæI¤¯°ÀË›Wªüp¤´.Œ^å+ý hü­‹«68è‰Õï£98›¡#½ô&õÍ ,nøC¸ãü\›+Žgò× å(5ûæ@ÔóÞ?Ñ­¬{!]0q_p³uƒÿÂã›D]3;u4¦à¿ÎôæH6Ûå©Ê@ j”J;/>Èémó!žpqü”¹ûl Yל3ƒqžî¬&S£Ô)ÍA@Zò z‡ºš£=dM²K,{šÔ„Ժ΅…Gópß»’H0æ.IØã^^cÒÈ66HœSs _$ lgJ—ÞR@„a!Yšæ‡ynUßnNC(zËñ¢ÈQD¬A®È¶ªVóµÔë4±óöúñçñ©*˜æð>mhÚfÉʇ@kü1Z–í”0¿f·‡hpO%±jV´ëdKC,#ç „ìÒ»\?Zy¨ÛÕG™#ԺёڟX›qkŠð©”óê šÃÅôùz\%™“w¤ø 'µ±Hà\¹È™Q ]Ÿò*JC:´Ö4à÷»ÛŽ ùæ§…pè,÷˜,0o‰s+9·n¹òeH%I³ Àw¹ðÓ=‡u7«3a/Ý=…³l dô‹¢<å!+Ö†Äo¿ŸÿŠ}MÉäf¾ƒþh¹ó79•bÉRôyÍ3r¨Ç¿Ð%ÓnÜòˆ¦àd«tN÷:LÔkÿüÄCAm“çÚO‘äK5<³—€øv/:ÿÇËnæãOF]Kмµ>迳‰8xÏ¥±Ÿ‚@÷ìv*ÙJŵ7ÁBbVBgÓ€¢Ô˜0´ÇùeÉ7àÛ”'. /UO¦ù48ÑÏu™s6*T¨%w<¼§ÃŒB õà!”þ‘]ÝvЧ°ò×C êÁ˜Iá‰û\òGxì./ôs°ÉÎÀ¬Sºô(hWÅÉ‚–¥—;Œíy#*YØ6 §õìÎÙu6¥¶oÓ[©Õ¶Ðšk»±¡Ò÷ßY=œPèµ´³?»Z§!›7¿Öõt&)öæYú” RÔ" Ù+]q?w¿úZ7:¦ë,Ý~í,ŸLQ”›j*7“5'—<½;/lŒýß aè‘x©Þ¼õ…™¦éî"sˆËôyZ¯[o¼E2f†úl>ù§Ìd_$’ð >´LcpG5¨ÞvzPã·ƒKým} <,ËÝòþ“‘¨mÝCÒ?Cìÿ U—é¥7ñ–hš:ë.]ÄOúî%<¢ÜïÖšØüЍg»Û9b¹÷ôýã°Úµ¶#zÒ(¡zWã)dkþ’­/ Læf\µfÔ^ä[M‚÷§\É<(õùl"?…=“¢™S6° Ë’ЊÁò-GsïrÄq_Ì‹^9¼¤vþžPtß»n9¹FH¸¸Æ{™Os—E¥YšlBâ{_ð›WÍùPh@ nU¡u(ùl+â#AÞkA`|ÍÙöë>ª Nsb#ç"û?ç0¢UÔ| %'’›,Xz$¸ ¯2ÄJ,2¥}­%¤íÔuÁ’ƒÃC˜K yèW_‹}ÔØà­\_Ô`³ªD íT?¿U·ÖÑ.㯺ëKa嚣D`Ö§¾.W–›¡©óô_‹ØS‘,¦w´á˜h‹KþíË8‹ HÇîè*ä+™$>*­ž3–³^Ù`y8î¨óý[„‡ÞRæ´}×ĵ-ÞŸ(¾ÒÿaVE¾ãÓSA~ à‹/BèÜ¢«dÇ?ëú zŠÛo¿Úc7:¦» œHÚ)V|¬Y“•oÉ7Óô¥œÝz`÷D†g¶hôØ4{É‹®øå°ÒzÎ_Õ--iÈa}T\¢óU~t´Z01)¶)|êTŠÆ~× ô½ŽûO+ÆëmW† Ë[­Ó'e§ïäNÁ70ëju®=&§°¦”òÑ °©<š'íë¨fÀ)Z1Êðp=ðØ6î%n¿¯ò4O´Î̓Q¦”ùh=.Ù=;~4£’—Ì¿Ö[<£cd“U¼Þhk¡N ÜÁ4«±÷k Ðg¯«ÀzyÐ9÷€ñEϬĮ|´GsýÞERãKü²_ Ø©ø1ò§Õéž>Â_6„ßêi\9Ž÷W¢2U"ð7å1$JÆ7]î/ütâ^Œž Ãaõy¹ŠGŠ›2‚ª­b'ôÿ™®! Ø ¼K+/Ó?ìÍÆ¦ª?®™ñ˜ï‹'žË‘K QÝùÏ {ð!¿¿Á38sÁ¥o.¯±q¾_ÖÇþ“еᑋífR´;’׆1ª@*“tÌªŠ“±D4—u€˜â/Š1Ó]9ìƒ¯ÈÆÏßúåºß¦=v¿hö—{YZ†’gá9ž:˜C\µé5ÁÞ¯e¬ûlj³ëuIú$4§rõÍâæ¶Tn˜Ä€A'ßvNæSÔ-°ÂMÜ!p·JM»LUZwÇlåëñz|¾ÀI\3¯Ëv‘âÓ“étj&ÖqåÎT8Ϭž öü¢^šïŠÀ@ªŸ¼õd…1&›Ä#5¡;˜Õ6§ Î{IzZöe='œÖí˜TÛ<Õr‹êÓÖ.¾{ÜòyN‘a/É’hŒ*Ð.ŸïÏQ©g179cù¬Ó®Í,Jà¹Ýûoëο7kwåDžÀgò*ùV ÃU#®û¾óüϺ„ÉšeÒ m˜7Õ?ÓŒ›h¿w#°ŠO¿ ‰;£ˆ;lgÍçý:HD“€ûè›vúFžsô'¯¥ω Ô Ç0‰xJŸøÌÍÄü*Ÿüp÷ÅñU~“XUÝßgbç~½§{È"_dÔÝ¥*˜Î²©½ý«û27²»…S|Œ$u#C°Þ‰¶®ûvŸGH?×®#9)6ðÔ´”Có³}p1KêrqézÆÄ%ª¿ç·æ”§÷†—åMõ®oÛĸޢ•Ÿcë4€l;¼e2o€{¾ê ìŽ&/o\†í¾}?ª&»¬ÃaÖUJ_SøÚ i•:@ŒÏ<{U,^ÃÁÄçð‹è‚±¶6ÐþÛEׄí5>OxÅ!ÍÎBa;Ðüúã-&æg„’²?ÍñUâJ¶ø™ñaê6N@²ßx û«È¤²%ÌÔ} íšU™Ð<µYþÈ/§yzˆ£3•‹«9ý˜hÙrÉ3ìí}9½Ì”ÑŸf/ª ßÃG…Ýî V½%ÙÖ­z$Õñêí¸”uòjYØnùð­bÞ+tøj`yðóußîQZïtµïdÄ*`oÌž]!_ÈBRûDfz6{_ íjý2W™ôdDmMõLH›å0U Eˆb¯[Ê©3ÄDÖë_xÜ­—™“ \×%¾o¸×éÀÔ™:WdrˆÛ6´kì)´Y®¢Rµ™‘h7ÿ“áX_Ô6Ë^܃zkz“b.Yg«K•“¿í¸Ó–Ã618C…tÛöM‹¨J7Æ HUí%í@Ý;ýÔ:ûD–ÃH†u»þµò·˜†¯©|ùàç`”¶ÚŒR*¬|}…xPu·?ò¶›/è£ÿâ¥À8¿¿%*§›å?7oëížOSßþœªÑäó$’ÄuëÕ ãÊK?ï¯T÷¡¬g-Gý÷dšÒ’ƒžÏvWé ­§ù¤‘YZå_Õ3—’ç¬inxàoÁ$P!ŠH–š/–õ‘cºo÷üà|ï´ÖÙ ³—îßQ`KÒÍ?¸áq5É•’jˆ³¢æóþ‡û?”gÿé(ârËÆIÁZ8¯ðŒQ*Cê|Ytÿ…0ÄÚ!ÛÙ4ø—à55 hòzÊzøæ+ÑNõtÛØÈ‹ÑS•?´=œwT`‘r1¶¸ÏpÌg4x÷-ß¿ ÔÏIÕÆ<ã’„,¬ôèÉÚ.Çpcœ¨î2ñ|Ñ ê¡êx¤´a›C…‡%ùê™Í. ¹†È„ÑÙzTÕÿ‡2õýl¥ýq ¯Ï„=½*ØpÑ0#P5|‘É!ÉéšqÝ›{jsK™JÔk0HSïÕ’ò+˜DÓ0î+øê“ÿ½3v›”ŸgùÑD0èŸzæAðµÕªìÁŽíN†Vì3**õ)‘w³_Ýúh@CÑùÏ-öÔ íz«ýõb"öYüÆátÌoT„ŒÂÅhoÇB7%ªÿÌ£Þ~ôËÂý’_Eb]ÞÐvîyÇÿÁû¦½5Q¡…Õ´Kz|@8wâ“¢¢}eÜ| Nùú©œVà¢ÿÀà“a[DDÁQ‘ÎŽ0t p(mìDIÄ×óv}³U1_¡çt0š%Ò_Ü‹/̱~W= ‚ƒ*ýL £/ŠOýï <Ç[¬×­Žß³³†GË×\j–kR»)ƒW “ú>­ Ký Îï@Q‹‰ŠU±•«9õ+iÿî-1AµU'ÂYu¼F¶É¹ö Ô芒/vŠˆ9ÕQ÷ö©§`¢,Š1HÁC“GØ1¾}LÅ®ŠÜsÆÇb)œ>úrä!Ùxm]P*50õë˜úÇqÏt¶s îeJGM`üõåèjí¼c”ΟCg>o0ÑpóBÿ"E&f˜íNøƒGÙØƒÂ0ADe®ŒÉ¡èžâªñQ‡­ž5æ4QׄJ‘¤•¡´­\Þ3ÏŽkÙ“:;ÔЬcÒ:f,ëic„ßôyäc*9»ˆeç?JiÚ«ÅÇðµiþý‹Ó0Ö¶”q¡Ž1ñZöŸå-¦_|K/vØ[i%·!Å”Ì7*É¿»5£úܸ÷’ÝÞR8ÊÐÊm¢  óé'py·¢§9b¢Ï¦‘©³vÒÒŒs™*å’·x,Y‘¢¢MvÙÒŒ¥/•"‘rý†¸TéJÝCõC ºà/›Pí¹÷J7ìKrä*±Ü²/¥þç<ç"F·}’’žâðîã,rÛù¾s/ÄãþRˆòΟXe¡q[7±K9sƒˆÊ ž„]hf· Ÿ™s+cW©ZÍîQí¯‚Ç–L·ßƒ_åë6èè­‚Ì8ÏH¥‚>-Öô-Ù€ÃV¾ê–&6™§ò~Þçç««kŸ²À‚³±¤Ô„oûañº¼· ‘]뮼qc+ ,ÔÐí „C%£§ÖÉ¥\ ’6ŠøQv˜sÜ8ñT>ï øsNŠ*Ï<ždÂGó.:hF°)D5ú䇯„ ŒZ6 ˆUê °îðž2³ ¬<6•9v‹N0gØ©âbÒÌÔâPhrÎhè£LÅ<â´LÙH±R"çWô$[¸kÈì"sËÓh;¢ƒ†º6úßùµž½Q×ó•îEd~ éŒ tH}ÍÕ'ý’=Ý\µ£Ï´@„`Þ!SŽoY,,(ÿÉ”ŒéŒÕ{à8‹_•J*1˜ýR5¤“áü"åŽ(¶¬“æäïož_Ó¤Tt¹;Å)Û´,‘²½ ·”§žÑo­¦Ô ÝŸt4ß@ÒhÃ]-Ýg†ÕäÔÛ1«¿´ÝÃ>éÁ¥,Ó‘xÃÉÈÌEÞoHY„‡é ÂüøòQ²’KÒda~Ô‚%Põ=(údg“lj ¾ØL5$t |áE)uS¶“„ë íÅ|VŽÎ]DpÑPÊm9{yå ß—R;TßÏÉ©sè¼å¿‘]úÿ!×ý§‘ðeŽ•·‰ø£¥:õ?Y‚WäÛv«w0¿6àä¨&Â}3ÓñS픵‡@W§¨³Fëú ×qW §Ñf± ¿Ÿ:{9xçbxÿßçì5÷¨½XmtsüŽÖ.3Ç3ïäÄó¶šÎ`q,e(:5¹~‹}Y)\ãá¡ûb¼<zå®ÇXʈÆMჽUk±ü,¬˜æÙ¼ûïèjM,Îwõy²ÿ^ëá3´s» ¼4m¼Xw^Êþ%ÏÜ…_gL›ÿ¬HoËÏ0ŽÐqSøGÙr´×÷ ÈÜÖj·½õx½OŠ×ö©” jî˜9d÷ýºÑ.nÅìwÖ•^š¢«Ñˆ´ô[ób§¬|iÍY ÍÚ[þÝúÃÔØZ¼7^˶ýS™lô6»»d¦ß1Æ÷nkE‹¥8ðæÁÜø¿­ƒÅ‘¤˜‡f…œ˜?zD6¸ý\ «€Í™+¹o´oŽ[MÏ9=QOŒç2WÇóÎÁ—SBž!æz5[ލÎjGíó3—*yQ‘ßõçâó:ñíX¥nx?¶`fJœ|“¬)K„„F9Þñ~Z•BKŸu%díŽäö;>§‚hU`ÑÆ–ß³ÙM{÷’tqù‘í¢tlήµx‚ Ÿ,h¿J!Ø.1]ZPN÷•/f¿ˆm>óIa²I’üy˜i£bHâ8ÙùqZ´GC2¢‰>š¯À!ž#V–ÿŒ7}jx©÷é_„ûË¢bÔ‘õü¯ ¢ôÈq|P ýy„¦–C>9þNC$£AÕüiË»!)XùY Á4B¿·ôÿpÔt9»ûÕš"ïQ0GIe<ÍéxøCÊÌÈúõ×5Çs؉ã­Þ®XÌ>͘N&h½IërìM­R€”Jšnë«æJ>z€¦g— Zÿ;Hƒô"{zá@I…RxØ'œC—å9xS’á6Ýý´vô¾< „¦”Ä÷»Ú¸,îxù]fÈÁ¯Q­…%;>O¥k½Ù¤©8¯€@7Þ¡"ÁçPl±T‹‡û`íû#ý3œ8ŸxjBò7“\;É6?`z^Ï© ¯ÄA™í²7¸ýªNÿ‰g °9¡Ñ¼µØˆšY§­Ì‰LKµ®j›=€~‹Ý¸÷ý„ï(<Ü!—°tôLµœ£ Å’ÙˆáçRcçZõ­“}³¨ÈÆÅׯහ{n‡ÕusñB£™’›œ·£ä!R;ÍZBÇ“íö&K,‘~Õ3: %õDij‹]g,ªèû¤é•ôT‡‘ Ô)ˆôD><'FnŽ[|ë‡J™³_nŠe‹³™`ÎiptŸrü|HBÝÊ©ñ¥@ÔÖÂú«?ßm·»ë’Ë3rEw·\5;úáj,ŠNâþ Ó·~Ù/s¥™"[[­ÆmMñƒvÜüÊ)Suü‘üN'ƒbÉWûÕ€¨>Á¤HLr­Zÿ%™wûcQxÔ3C.boÅeüÉñ;šj§êÆù½w’»'ÕWj&ø9u“ÖþÈEEåCß­˜ªfôÑŸÀDŽñ†­k‰Sîú*¨ÙîB&›ëÍr^÷ý/8Ð#9VÝ’…v&v¤îÀÑùrm]B6ˆ ¯y E¿ @}¤̹$ÜÌkí¬JEß5÷r|Øï}zÈ¿1MÄ¿êÜ‘°ö¦ñ?à‹çI ád»êÐ_“ R,þ :y•-¡{o‰Q¾5$·îɉRmŸI»fhšAÒÈå\ñXœâžè.vë±2‚¡;+þ‹ˆíƒgePö:síägÆVgà±´|C86ë#’ÔŽ¿, o"¾MÉþŒok׸”or{NöÕkÑAe-û•÷<:[OЬ ànÿAgÃq¯„俨#Ìì %h‚¨4¶ ¢{ÀCZ3?;Å…s8û™¾º.¢üA¿}.¾úºT‡¯ÃákµñûÙQC9úF³Á2Y©X±emž³yâß·®‹/ÃØì©%VÍ¿3QôŠTåêQüf‘Í #ÄZƒÂxŸSt•kMYQ7ä ‰5äõ˜að2Y ëÚs;ü®·>¨¾ä_í0óêëi$»¹É“Aým¨Ê`z´€:ŒÛV®þf»¸Ióp‡¨†ÙCð~†o¢4ñ›@ì2© ¨~áPj8‰‚W‚V‘)—YÔ½é’ÿÅw÷Ó¬qÿ ì¹d¤$h­|âFxZ{Žä–{"Rg'c›c¶2¯ÿ‹¾×O€ÐÚáoéyr•7Ý’×ÔµÉq6ýl¼š™˜ùñTSX™Á«ýrð¹¶ì4ÂW‹Çž€ÆSÜõwù’ÿ¥¡Ö?êOÏâ"@SÐ{¼c.è5´^§<ÝBÊx~Ú~×ç ŽùD³6ÕDZrÓW¿‰—Š«»>/j]¶ sIÁUüÔ'úzÓhjÐ&>uà‡/b×ýaù´‡]ôb:4 ¯(ÑËõg’ÑíÜÀuȱLbñ™z^FÊ0ãô*ŸÎ´>³Oª¶݉Ÿ³ŠòÖtñ¸Ê·W}1䦖ø©„e…—]ÃJ#r¯Sêò<†îÚàòï|ŒÛá ‡éþ,©ÿ1ÏWD¸JaäZðŽš§©””hµº)6’È>оg§ÐßiÞ‚~T·5°ðyÈB³îùé¤äÀ—)ý£˜ºõF8&àj/Ö­öw¾{£\¼2&”{SØbÀz6ejx”«¦rP…©N¬-‚#³§â%ŠŸE+U‰/¹à§ÑRæ&Üž¤õ+Çìõ’±ŒQ—+ qY Iò:ˆ‡´;À3µ{‘÷ðëÒôEkKûæ ¿¹LÖ  ‰‡C¥M¹jmr0ç`¿Ï¶¬íëî3X©.Ζh›½ç~ÓD¼ÉoÕò!¯–Iö7DË›õŸÃIÙ5"YßI!BŠún ®5yÃ[y=¶_ ë¿ÚE…¶¿·þ4HÙ@…A?Uq3Ëq¸fDˆ´"Râsÿmï“°ÏÝ©Ù8'XzŸ•r„Ý… ]GJ¤›qÌ:q ¸ïjÑo‘wçáÿâ‚<» ²6ènÅ{Qvœ¼Áåkì!„¤ßyYÑ'V»(ùåXOA‹Ñ)gsˆHK¶Z ü|•¡öOéŠÇ v…†òxß8ðN$éXÇOV;‰|L œýµë³^Ë?=PŠà4lLµT“Òû^…¿Ïý½läÁ¯¬w¿jÞ4„9”IM3œ‹j×fÍò‹M#^åð|Úc£hȾñtORÑÜ/{F è^M“!â½ßv]ʘïú[k;ÏõŽZ,ßéa*øZbõQPA„^ÒÊ ÷XÉ{§,Ÿ'ØAÙñ²'äûIfóɯ ?tõÒ¶O~qŸhòXÕ¬1ø쎜à´nx`_¾-é Y2^ªz«éTÇ«èŸLŽ'^ÃÄ?F[$®Î‘þô~9¡²>úìAÞÚœ2‰1l ·ê>¾ƒþ3zvŽªŠ [â+rÔ,›2SúûæýJ>z#Jd"–*ªñèý´ØTIä®â¯y¾Î@¹¹gÌIÛî=ÝúOR}“W¾Ö‰%–‡¾`Dc˜ØIý@?ù~<½¼ˆ™Yø»®²ö¤^ Yï²À7øÊä5#­å¹)öoÙ±×É:ˆqþÞSÝr"ŒÇ9)ânzßä­ÑLJÙ"MÇÝÉ¡]¢ULÌr{NáÿEñW}Èî•8!‘sÕÐ÷¼Zú¥qëð˜d–ñ«+W£|»þ,ØÔÍXô+êåBöçöwÜ)P.0fÆ8–(øïQÑ%Òh«RPU$ØJoÿO¤ƒâ5EÌ[ÕÂéçèj;”åý‚G-ÕsÙ^Þ¿ŠôØß0{K\{.9õ²‹¬¾3NгÙ&1ôÌ#õª5þÔI<\>RecÞÛÙú1\º¬Ñª±ì¯ŒõJòØtÚliøk¼±ã¢{€7ÄB‘ßçõiÏõ€ ‚ Me —þöóÌ= $Ô¦ÂîTÙt$?12é(¤CwNC*¯}úÿeÿ­I ÿ9ã?ß¡5ÞÚÞYú¿U3é°r}¿úÞè%1HÏ´wúÂ|äÇUýM{Ù/@ñÞÐ k]ó¢ÙK²rœŠa¹õä I¬O©ÖwOYû¡½v+éÆgïvË 8ökççn5»S†ÂB~EçÐ÷íóκm¤“{hk€§^#Å@.œïÝöè„Ûì•R?©ßñÕI«¨¥¥3Üa³-. œ0€c#ÎPÀ< nlz¨È€öÇüçÿQï›6°Õ($ÑUª¼#°šÝDþ&¾÷†‡CìÙ­±ZŠ|†ýç­tñ KÑ·î˜3K‹ÃúA½7,n“—ŠR¬˜¹„áN°?®È5!êLiò¤«p`ãÓÐT;PpÌס9è#Eþeàïõn¿§ÝÞ˜C>3-¾é—Ì÷ág„^¤Âþú¦Üì!üÁß¹Ãûx¶¬ÒˆfcïØ¯Ä?MÚ¨~B¿Œf"Á…¼cWíG ²b²‡ëo"-é÷ûtÔÞlËpe~Ç٫Г+ÐÇ8ŒŠ]ŦQq45Íê*ÈßU¡<ÜÄû…óŽïÇ3dk‰—Óäà”ÇYö¡2úEB>oFI9íÿ_ô—Š!ª=ÅËØá …Ù)¡¦à¼ðè¼n„žCOÓTº•«Ï mðîçÚ>-cåÁt`€ȘãN QÊÖG›"ËÈ­ãÇþæ(Ühû”ĵ˜=ަ¨}ƒçÖÖÔK¤’wù”ªJŸ%OûOr6SF¡c®xƒ,0?¬·ŒÚ¨ˆ³:)ÌeKø=š•Go-=g6~´5Ú¨–bü°œªÄD¯hH2¦i½ý²³®} ¨g®°íÐáÛ‰wA“¯Ä»G™B·“9xL‡_ûo‰åu…1&W®c—ùmoÝ‘:á~H'µu ÏÖý÷)qK£"ƽC3³œ®Pf£;•VvWë"¡ZŸëƒ!9ܘ4fgþýô®f2íN_áމ÷ïäî#Ž€iÜ3 =V*A­úîq§Î£-)`ôK&Ýâ¶JêMß„N@w–Ç [ÐŽ¼v ‡ç;yÑOý"a½Î½äRÄ|F!ôâG{ îx.tîZk±ýÖHãä(~‹³“ûÍ'“Ñz—¡"»69¯¢r?6í5“½Q"¼È›uG˜;1’/òɼmSO_Éx—87Bì¹õ`£‘ß{ZkÈSú¹œRݨW}h¦®,ˆ›æDšƒO¬^7{êf>¹Ô¿SiVèà44¯õZ¡u‰õ,lÒö‘}ÙýJƒÛà=½vo‹ˆŽ'á ûü¹‹Þó2°bVðk7&Ï®4ôZ–Ú/æá’]b w²ý",Ý{ÂH÷ªy‡$ çϸ¸Òf½¿>DXÅ*ïõ(?½mä·?ö´á_×?³ÇÓÜ|oI~6£ en™m¿`ïû¼â‘ôÒ²Ãúr¾¿¹Ê[ @'°ý)§Þ›I ”döbŸgê@;éáæÁsŸHý:C¡ ==-¡Ö§ºó%þ×"K7šRn´Ð;Gg¤F)EÙ¤ºVjd… aš^;ZV0H#R›-s­™?Ÿ%2Õg'1Éæ?š+=­˜ƒ÷¹0Æu—v ø359m×ïß £1‡°°=ð»¥ÝØ?Šo‰ãY‹Þ̸=¯A¼ïGÐËT÷¹½ ‘ÿqn–?ØË#ÙEF82ÿõ#÷ÖOgeÖég\sÂu š;ßÁì;@ÖûòõŠõ+ÇfŠ!†ïŸæS¤#¤ŒkXpo]Â¥i«hün”öjJ¶=Z}⯯3 Nl÷H¬$¢r;þŒÈ‚ÍÞó’ ,ÙÄ*M}/U9ýÄ?µ°Ç¡m^LãÛóûÀ´\U¼8öW,=€©½½9<8ªWù ¤EC1Tò+›IUò›qCö¶,ÒòHaÞcþÂÛéx›œ²¢ _)^§³ë3Œ¢—`»†o' BlÈdpAy ½Ûü sžê‘A9óå‹Û?Ôt• XŸŠ\¶ÌXhíhíŸ+{íü2z¯çè{à ¥ŠŠ÷þË 3jÙïPeXÍïhÏÌJÉô ™GoÑÅ6˜s¥%­«ðî1ðGRm/DiÉ&™·îz,¯ð Izƒenãt‡äoÐÊL?Á{S×=0¡<Àrølíþ\•õ:åjø­¯M*ž\&k·Ã@,䢛¾L£7­ËÙó•ѳü.« mìüâ|PÎvªêcÙ·pÑŸ»îÄ™Þ!¹Ñ;yrÁ 2·« `T“zp=ÁNT+Bæ}¯_Ê7¤ ßÒeçøÐVÿ1w*FS®¿Xè²k^ßk™ñÐÆ 2EþRC‡&ªÐ#Û‡…pÑv”²Ýz”—JÓÀÆúwû¶ÐÉÉe"¿Nx.¦åÎïTO'N9F?C É ¬‚‚­´‘Eÿ¥bèÌ”ºì<ôÇ2þ‡çFË’/Ò]~P͈±ë<°Œ(Î…ÏÙÍ'Zêž4ˆè ã|¼Y˜Ióö§žØÇøH‡ïò%?kŸÑ(kVR¹£e»¼r®§–Ð51¿` ô¢hvõ~üú„h†Þ±J[ñù/œp5(îrGîC`Nq¹ØÀ•ãV@ëp1=q»¾p‰pŠ 9â¤E;H[kHM¿±ÏîÿùÏeœ‰8‘Ri:FÞK¬„!¬óýx?Æ¿Bµ*¯®a2«óŸ âW_K›&|r[$\5Ç._£ˆõŸûCÝ"-—ì£H¼¬;8òãž—æá}§ ¿ÑƒPñÞ3î+劢sw%¾÷ÒæHü£ˆÔQ€÷WÝ&EìÿœžhCˆ†Ã*?I*¶ÕÅtS¤qÝ3 Ö3݉:é½?þ‡¹CÃõuqÇO*ÞŸ­ ê‰1µ!¾{øÕ¬‡;ê‡TzêÉáX6Zâ–[ÇíüþÑo $¥ž„äÐx°Œéf\-?`/¶^#Cål•H·úóú [ZMaLÔ•§‹úM%íé/Ô‡•¶ü>&Ìêݺ–Ym26%ú5×éOð”lß}«ˆg;5FPh:ã ªPM%HÓLMo}Ïpin.JºÕIŒìÒÂð Ðoóu4#C%Yé´€þV…ÎC¹)àv‚žm2A*#Š AS¿ãç±W.:ä æp@½Á¿Grö¾‡*Î,…RQÍLC#¼š3-ïÚ.3ÐkKL"#ÐäUdTÛÛvcï*í(ýy[yPˆ)›¨8Hl¿ݨˆ¾7ú8!õ7äó±¿ú=Ú}/õèqEý†,Ž>¼O·ÃÌ?æLúÞ5N?{Ÿ; ú¦¬ÅÈ“WØó«õH×÷Xÿ»˜¬ò ïÅý—l Ì Fèt?Ù;ß…E¸È |“ED_åÈÏŽäWË“þ—~óVt·)ŒN5Owu¢}ÂûÃ'+ ÉwEÝi™hZ©o*Ù.¼u«·ù=DÊ2Ô,ùo’ü/´“Ic-Ó—›á…²4\RÒÞaGpÝ.ú³©#;á²æÆ–=¶ðU êàuÖi0Ïû<¡ÀW+—Ÿ¼!‘ãÏ+mü}Äs…èý9ø¯Ÿ@L3҇ˎ]EÒÁkä£;T²IA¸ëTe¯±l˜PϬÆ:;ZZ*\È·q'5®¼óŸzV•r…·ìög™½:Üuw/¾v?š…%,9sn¬"a1G"ÅMÄvSŠ¡ŽBc»^Ÿ±KpË ·Ùâæ…°¦xë÷½£‡Ú&÷¦Hú¤§ ¿ª„å6ƒù˜Š?BÿùZWZ¢†ý+‚§æ|!ik 爴o…]''BÂvÁ-‘bËÔœ*§ÒšjLC£Œ:UÃ&àÖåê¿ ð]—×4} œ¡;UjÆÜ2•ËøÀiFÊØ¹¤¬[óù„k Ú· þ vÅbðý‘º#¶ùó_·æð§)¯’à~LâäÔ[‚:N8²CöDëMq¾iΠβ?Ë0ð^Õ©Pƒ§||¥ÃïD]H\;Kô è\Ù „LvKž™Æ“Ýc¹—ÞœÚlÄÂë‚À 7l~8œ;‘¾d¾¦7æê+€™ë¹µÀ 9GÚù°œ»^JUW™Ð=´ êç{Þº#žw[Ð91DO{}íô5>Ø4Çך)EXúà4ànúú.á×pú:½5ªì3cwͨê,|º·vão²÷\ÉîÝ»½w»ÛÜíkY½™ãäwxs­ºÐìû{yz÷n²ök­ë:½^æÛk}ï; íÙÛ‡5V6¾íÙ¼êúëÁdÀû`ºßMݽŸ}½‡ÚŒ>UÕÝÍKw¾›ÆûUm¨{«¸y˜m´w½áG×Ðu_}pzОc•@NXr}ßOso|÷€YõÔ¾ú í(-¤³]h=Šu¦Hª^©¢"б¢€4úvÆÞCtç: qÖæ&wp ­mºx7JV´h(ƒÝ°VºŽ.J‚ŠZz¯§‹ìûçÕ› ︳í[×Àïƒ>½° ^Ö>]n6Eµ†62¢¬9Ï.³YÌÇXÚÚ¶Ä•°±Ð>ž}õ‚ÖF´ûï¨W’™± Š+ç÷IJæ÷«¯{ hÄTµï÷¶•{´yçlúÜ ·¸£ÉÝ—™JÕzÇßqÀ¤¯§Ázw–d˜VÆÛk¾öã жÂUC[ål 0”RvXÚi³ 6¢·¯wqón¯­*Ø­.¾æ=´¶Ö†Õ±PkSlcNÛÙêì+MScCi1Ó ”5ï™Öè}ÞêE­óc6*¢WÓI°zÐ%LÚÖ4eï\eªFËZ÷wo¯F²µš¥HÍk5ogÛïŸuAAõt;˜ 'ÖR[™º:»1»•¹¯“ªrʶn®î‰}Þïg]_|ri^÷ß=ìøøó®¥ºë¼o{"@ƒ@ €™4i“LÀLL˜#L˜MdÓ&M&M42i‰¦¦`M4 hddÓM †„h@  ¦€M&˜@Œd”ýSñ©½M<˜ž©ê=FŸª¨oQ=56)„ÓÓSÚ¦žHõCÚ¡éh=@iú§©¦A¦€%4D$S42z)ê4ɓɢ ÔÐÓÔ?J3dÚ€h4Ó@€ I¤‰@ƒI‰¢1¦)¦˜ §èjm'„¦ÔòŸ©?TòÕ1êh›Òi©ú£'¨ôDlPò¦††êh =!¡‘ê4z€ÐÚ†šdhz"H„@ÐdF˜šhÁF†€ˆ™“F˜‰šhÓBi0i0&º'oéf_—îô¨‹T•” dpÅÚ®æ+`h„ þ*æÁ²‚²OôýÕ®…Hÿj7*ð˾T„ ~ñ…6!CäŒóòD »Á!ÁÏ#í^jxžU.ù„‘O— v7×òø0Y­\Hñ€N~ì‘?Ú᱃ª‰©› PÃ\ÄèíGèvßÿXúUýxˆ|YùP÷_A\¨§Kewþ/Ý¡v;d¼cñ7„UÇW’€„Ãm¶dœFc§Ìs"?ìåöëší62¨¶†¢õFFPÄn@` e>A=žó ¬Òñ@€—ÿty”&°vÅIuŒ$Øz…@‰8Û2¥1A¡è>q¥Ö-Åà}°ã  ¤Û[´Kù=&ÝÜÂ5}‘]ZŽ/À,tJøð›YŠçòͳïöÆUjm‘tMÿojÿñÐS (0ù^^ì­îJ±/·›¼˜ÞŸ!€€#ñ€°„†! w„)4ãB  \ÐÛnöÜ@¦I’áÇ_ÒQæùpÈB„°fªOô`ð‰92Oý÷ÓNkß¡êûÌÃÕ[@šcÜBßÚHïáPœO³°Ð'é¹¹{ZxGK(>«ÓYî^ã~*€Ô`1€ÍÈú2ÀUPW0"~šO@YÐÚâÀôþö»‚}Ÿõ~÷Úßøû:Ü=,OÈyˆë’FH‘'æÃÇo("½(Méã °Ì  òësÙŠ ‡ƒkP%i DŠRÍ’ ›@`„|œ5>˜5ïO=#©ÎGNe+ÎCÝØÍ+yþ´Ì&‹±(çù_mʃÔnN9¶Ÿµ#·PëÒwSÙª8Òl•ý Ü0íÜ0C €ÅÌ'x0@*I00%ûä¼”ý„‚¶åt–úlçÍ'6¡^ݨ@î1ÐÆu!nã¶ë…EþÏØÔ•)ÑY¿å^R:šÅ4¼v¤ €!çtû[é’õQà›¤81Ñï½]„êw•Çš|Iío&ôÚD³aéW`Љ»f“îpyÐ]'$OÚ š•‘(ŽÂwµ›$SDNŠÈ XtÈ·W;tÀèËNCÒèÖ}z^3 Ñþ<$Ho@¨1€ÄU~<*FZtï]½õr«k¾£‘qÔ‚±DRmcy›mŸ‘£oN9ò7¬t0ê4;mñtNµÍ¶wöIÁ.yúWy•ÝÌ&BrÇoÏëÁK°IIB/>ª*$3ÞÛƒ…eg }èb0[_)1Ô¯mœð£ú½ŽÀãebF$8U]¸U`æ/“Fn°Gùðë—E5~íò¢ðÊñ2ã‚\*(”ÿs࣢è†ÅyÍ ã+¥2úîÙKG\(ÔŒlõlÚ›låQÑ'¤ÄÉœðnQÄör£4@ÔRHõ…$UÓ œâѹB‰¥*(«Õ! Ȭ€È¤""P3ý©·¿Ô©“Õí̼7¹ÛÀ¿˜ÍS3°S´H‚F „þ7ûÌ\бAb1öú|µ ×·¶’«Ùá_•¹wq$#zŸbZ½¢ÌL+Y¦R¨8è4Ó?Ã÷ Û•1À¾VÛï#ŰSÐ 2’JR˨¤H”ç4ÅH%T*ÄW)JQ *Éa¿J{þûÉ%Ÿ\3¯ éÉûÔ̾—g½ÿæ+7:ƒ""¤>÷;¢) YDEy-9í“ÆÊþ )`"ŸU&èÞ0!§”|ÐÂDP MŦà ^àûªsøé~Ú@'s=¾cZ 'íGÞüñ&ÜIX#U:!ÇZ4•HÈ,UE“ŸÞËð³Ù”.íS"o¤6¬m¨FðÙw¢%†%Ny¢ŽØîícglZ÷!T^nËzi8Bé–à÷ðàBjª b&RXç™Ô<¼~=$ Ý>‰ÚH¯; D¤sñ®úäÖ[“'\QòEb&“½Áý3Ú¦ût^! #0GÓI ­'ÊæùíWsã¿'¿‡åW]gB”‘\’ë}¯{Ízƒ""]ç·Ÿ!¸ö}xI€­Â*ò0©F÷jcÊ—ª!%SP5PJ|jƒÕ÷‡7—×)ÇÉüO0¯G¤£Õ¢õÛöy¨"¡>—/&W~¼d;ï’[ARQã®Æ3¼ú È€""îÁÜŽUV}(){ÿºÖ¬pKÀE|Ôó×ÀÂkµ[ç¥2jæLÌ £Í2§ÏIðÃ=ùüï{­õl¡ç¹êgdÚ|~¿hV6¸S¼-=ñ›mî¤å þ³;±Qqœ4Q SW§|¶Ç%ì…Р’§zÍÂ@FýË_uÛzVµp¡EtUà÷ur`‚ü³¢l¤s‚ÃúËhxÚ¦¦d®×À—h½D«EÔ"ýÒ‰˜Õ@í$ˆÈsgnEÂÜ‹é˹˜äØœZJLa¢ 6¬ŽÒ3>ms5r³‡BÂDÕŠèsâ(ÆÑBñ½ËØêÉÌQ8\  ÎFÂJ0#C‘Ñ%rT9nf NTcyºw›ŽR)•8$dÌ­!3 åAÌWûœ‚ÓUŠ%m +ó7'Tgì“ÛËNäüÉDLˆщ—_3—ÊÀáûáŸS+ò üÒ¼~­éEd‡&š¦yâ~žfÅwlvbÒÿÂÕ¶ó@Öw½UˆÏSY½#ä$Ö3÷ìølãOê¡ ø{'v~Bÿ¦#?íaÝä9šû¯fátµÄ¡íÅ»oôØ—ŸÇrî5[Ö§—diÛà¯s¨jû9 ª›¶,#^—ßÔ A—ÞUu‚výüÒÔ¾*¾º©L¾1—ʶa»,ù´ °/8}€>p£–\ëaÓð2Vñ÷ñ¦¯ñii©ˆ…åÖí0ݹ‚,‘ Æ4œ…þ`(š$JýŸ½Çâ@û ùå‰Hݯ懡óbö·œ>Lvð4U¶»÷…¤N‡oz˜GË›Cþ{¤ü-ÉéÝÎ1É¥±Q×M‚¨Ð;g· -t¬«ÑëŽ+~"U¯¾Ç-<¤57Ñô{¯ønxÊ.r m¿9ULŲ@“ ñ:ßt¥o@棾søÌhx•{±wç™”üÏ2¿+éÒïñ`zWq ye<.6¹.Ž?â¾ç½GVa¿›¶€ŒÖžx’[EðBcÆÖRž;^_1Ë gâs]u”K¹Jn’W¾? ‡^Úš§Su¿ÄG3Iî«L?=/ïÂNª1N×'gËfdæE„eF'!@Çú§çô¼èÎM<•¸sòîL#qm¥<´Ô(¯*xÒ^že7›Åûç8ÚiHéïÜoÐ3)ÚJ˜–4^‹‚2ÏëŽëÂ5]åÍ<Ÿîgus¯h‹­åô ù¸ßÙ †KÓå‰çEêQëçÆ\XC{ßïO¾?ßgðäϘSûëç—µyöpnÞ(íÀ+ç¦é6f58êNØk¦9\[†ÿ‚èí§fGC®-ÌãÍOÛR ç2õ6µŒá˜þ%=döEt ÝæÃužX¸§–Œ®¼J Ï/ÖxÀ#e<¨ÛÒV©½òïéÓËñ“¶XaÍ”¶‚Ý Hô`ýwh5Œ òûØ™Ùþ~ÇÎW×Ç2ãÐëä!RO p÷ßNO«ÍfÅ n(¦>Å5;.Y;"?vÚ<Ú,-KeÅsOO;BçÑÃk»õlÛ¤m#uT„Kï4Õ·uÆú}a£¹½F޾ÆþGáä"]/B€'‘‹{ˆhÓ—O/Êm6tm¾§ëX‹@ó—q3=öMŸofÞOüfAýÞë´\y«i~~TýüZÝÛùwõ±Ãnk樋Úl²ÝŸ}[˯Ý*iðÖ™ÏA@Nú°USôÞþæ×ÃC—ÙN&ˆ!Á¬€†ê¶GÜ\Óœ™ æüj[íƒ#mß[÷]œíÄÆ$¦Bqˆð•*ÿ¢ƒS÷[‘ï>Qnׄ.çB¥Þp³zg\û‡®ýÖül©•Îý>ÝC:G;3›Ç¡”³!V·¼ó #±/¯²4 ¯+FNLîx`칸S—Ü^b`OTõœïÝidá7ÒÌÿ“8 NE*~HC¼Í¿~®/¢°ÏhlÁÁ#YóØ(1¶Sîù°Ê²¹›÷-F1ºl©|ŽAÎ,‚ìœW%P·Y’ü\øÓn8/3ÞÏÇÛAb~ëØhŸ3ö𙦹ø†`Ú=–Š%·BGj¥óVÈàéîÙ…>iÏ”¾7~ºŒ¦¶‰á8A„šZʹÕÎõHçöc$ТfZ‡TG̰‚ªg¿rûϧƒà*à»@z·|Ãeh­²#äº|Ûmž–fäÍ w÷œ#']ùÑâodÍRqF?‘Ñ1íû²¡Í•d5·( [_.¼G;k«é†9º'ŽI¿bÒiQîSÉÄñJ?Pþôìcë­FߺÐIÓ<)½]´Ûä^ä8ú5ï[?í¿$ãàƒfÏM+åëpP&—¤Ýúù…N"F¡¨ÿƨÃQÒצ¨˜/‚‘—’¼üœ­~ëg¡«~ß¼*…_6”Gsz«qî“·C£ôþ{}”Ú— ¹>D0¦µHÏGùý·²Êz—¹Â…(Vßù7ŠVö|¶§9¶¸†—ž@éôyÞÿÍFÝ{Õ뱋¬Ÿ^Ú(¬¤H €B_ !€*⩚*žŽü8õV„ùï‡B¢›ð/ëkÊ>äüŠ¢ÿÍo¤¿…j•N =Óÿo§ôVó®*eš|4KŸù5ÿtÈéþA/íTÔA?X‰ÜyÉTm:þËtoÃöÿ7Ê·e‚+ý0?R?êÆ——¤Æú«rçÕäítý%è"À,Pp®ë ·à6`° ­Àˆ+ÍqÑ•¦Ö÷JÔÜåò¯†ÊIx§|ñŒá”GOòº¤žø… ÍþÉ!ȱwUÓ³Ó ù%§ÎáêÀ '¬nÊ”õß»ˆÒÏŸÓ h/—ì}OÓ·†ûP½×êÞ¹ç#žYÊíÓ‰þ±º›N M¤9Ý&n­áüž=·Dé÷ÖȦˆ"Kžz®ÉÔ*«.ÁyŠXĆWÃ_y»‹+3{s“Ë÷Íñ=¼I6À’¡ û¹öþrðÖG(¡Æ¥äËå¾ÿƒxuÃs€9ò4“!ý±Ð:àÜ¿{Ú8æHhëc—x+Œ‡m` ðãsEÍ®ñLÛÝÑØ÷öèúNâ[ós&êm¡<Ä\2ØîñNîVÛß<Ï‚þ¡ûcòÄÕ^~ÃÑ„“¹ZxÓÇ ¤BC »˜KÉÕçeùj*‚Õ-åÝÃø‚)à rÌ744Ã%È2z®m8q{ìè ÝÄdžÚ– R… g¹ÁGe²Ú´Ã×’H`öh¾/k>Òg9;«„5óyµp‚ ËAÇÙˆóÑiZJdk?±9š†¬ Ý„ÓP™@ÈÄK6´dܧ¢s-®Å ³-”Ŧ,g1ØîoÃŽ³âã iÆþ.°C| x~­I?lì7¸9çÃÊ: ’õZM¡1"–•YûmÞ~²„ÉÜÚφëgV«U™ jà ŸI}­¬³Ô.ßÍýO°°h6kÕt¤máïp4æÂú°²îÈТ·[!",DYÖ€7‰0 {¿º¢üÍF°®ÍðL€x®#$ç£ÙÈùó*‡ˆúDÿ›EQŸg£À{ÓºO!s‰ýüÜ[3êÍ•1ÚÓl#ˆ¢îP9Ùã–­»¢¶\ënÊI(+±(;ð‘…^›åP¨éñÄP"UÉó2ðÕâéaUG»Œa PbH¢ƒîèvãÿM|î ní‡ÑƘI>Ž#Ùþ¬;èóBè|žî®àø ¬7b(aˆçƒòv”`5uÝãºBåŒÚäú~xÙá£+á½ÑËéÒè+ݽP B1‚B DQDŠÄ‘‹‘Œ‚¬DˆDH¿xÂÉl”b¤,f—§„Ǩ']ÛÑ1àÃ…¦{.kRiØÍM¤‰LøFbª:+(îP´'Ö òðQ¸ážñþ*¼ýEoÁ áÆÄC;ŒÙr{‘"&A°ç“™“œ÷õq†DÆòî=P^¸ô‰AÞuÙ.{ÓB;KË·TÎÛU ïª3ˆzG%Ýê6“ß<³ÀÌ×}g˜ó“Gºú†9W†ÃÔÝÌ-X7ÙV+kK«NH+¤áÎ ®Ò ž@žM…îS".ÏèËÿ°ÇéVÒxΞ˜Á@PIDĨ:Ô*k•ÂW ‘Æè4­ô4 °ú¿¹Ï~öÙó~ %çc—wëèÖ?éŸõ}N“·d·‘²o{„·r” †ž¿««W_¿!÷ÐL mìëì\0oF€hxÑ”Chʱ}¾ÖyËÑꩼXaô€ú;%ý‘Jµ+Ù×§÷çá?KŸ¶nƒ°øý¿oÂ;é!áý¿Üý<£³Ñ³ØéV#ß ;_h¸‘.ºÀý4=G?bËpurÕŸ Ï¦Î—剿’TIè•`EÎÀTK ª!‹¤ÝgœPWTÞ£³áÌoïVÍìæøop³hÁµŒo¨œ”àìwÄ@ð¥uçWzÕŸIgÑì×ÒË`ŒE9 ôü5u¬³PLøxÝnÃ@du »â Äóàn÷E¹ªwª£Š*!³^ÕluóëW+st/áÑY½-ŽÛ†Ž#‰l¸&­F¾š ÜÌs]®¦Í¬ugK’Ãn—hV˜@oêÿ¿GBó­Ðeaâ€p˜¦@ ük$7ïÑ1ìvvJ[8_®ø>Ña¦J0újŒê.Ü;ÅŽ ½<|ÓxÅ´ß›-ÇilNg9Q%˜‡r»ÁPTz(+Ç`ëí<u×4nᮬÔã€GM©Õ©£qõ¦¥2€6£º_´ @˜ö­xª3(…ûW\T9N /FÂk4ØÀ4C>Ì·§ôl3îNa¸ˆ´OÕ¹ž÷Ž¿#Fù£5së‘ËÓ†OŒ‚»Á[Øé&¡€M‚Ž}£7êb8êD‰ü R#Œñ:rZß¾ÈåÌ¡(B9]N±QCn‡›¢›niÊì_†[]+–ºóÇм{B"@—jÙ_5œnZ²‰ ƒ+±aËœZv«qoÙ¼ÞÎoÀ×¼‚¸[°)vbÿÂä¼#Ë„&ÝHá±ÛÁÝk¯â gwPÂß§ÏfýÙAè÷ÚÛm·ó ÌÀð84š$A“©Ò lUÞgˆÇ‡ÜÄQÜÓè·4v4Ã`Ü œ¹jç„÷鈷k¯ tú=eÂÒ;‚ ,tôyÐ|Dñ”@@óJ‰–ßs»½×ÙÔÝä€uÐw×ð˸nßäp€µC5ˆ‘Hˆ‹5Þ æ|xò®VTlÎÏ«~ݧSèpÒ‚¹úÓé>¼§z{TkyL¥‹äß?¡éSPàGd¨¡œé ­­a¼fé|ÇþºõX8ß©ÜÌ‚¼“håXåùØò1ÖmCa{öbªˆuT̈¡gYŸfìꨘîêÄâ†|Æí×z¾îЦÁ”`©ÆÇ0žÒH‚äòü±ùl.‹Gɳd@¡ÓÇràïWŠ¼È Jêv¼¼umäj®V¯4sÌI—®ß6m›g±'L®YØùÌyåÎÈ;’Æ_³Ó5nȈ!'g·Å n'ž‘ ÓÚ¢|z#sˆûZñöÖá}D?—´Úˆ'•ö¤ô¨óQýçƒrªD´ûðf«Wcòb·ÝôJ|Š’)`X Þ8@W(1k;øÖ•UŠFPV‡’+sás±I1¨¯í­Äásk”$Ââ“„˜…va $ØÞ¯0²…Ò« .À0y˜j¼ ½þ‹Ø?§˜­1Uˆóhj…ŠÌ±Šág±À¥HBÓKµNLºer`\À{KyšˆÌíŒ"öO°2WCÒÒ6Sê.Ëf- Œ¯u×,ÖQ (Û¥!‹4TLmŽç¶D$¢†ò>þåÓ¯éu+oׄ¼ëœcF0ÃE÷–f`¯Iuû—L_Eà_§žèù˜wuu_[QäZ‘Þìëá…|›}úx½pâÓ5ö^âÖG¦Ÿœ}žÏ[ µ÷ê·Šy›Sií®Ý;·Þ:k$ |ñ 0‹ÛöbEšŠ>ûl`7ܨ.o ˜”5õÒ/Mþužø'ßÏoŠvÓ=–Ú/If·Ø@/…TÃA¹PL¡é„J£îù²ûù °¦Fç\™@ÉÔ ¢ã‰ËMɰbXC¡DN­£nr ~œÛLjŒå ®6¿°¬²€ÛíPÙ';%;ú}Ô;q†røûÕ@¼d–ª¶AZÒh £­Fæ«gÜ„c@›ç<5¶k.‰Â@ƒL1Æ­LT}Šnràë*¢®„‘¡q¹ÆcШÙq•ã]ÛëjœôŽm¬Ž~tÑ19±êÚÝ­˜†Ôwu;,iD"k¼°!ÓáLõÁ-Ûn÷â~ˆ†‹«$'”ŒjÊB™f.1$ •ÑJË|ºK Ep(ÝiÅRíì¸ZsÆ{àõ¤æò¡Ç§º”9e6Ôª,¾ƒS‘ÅRÿ=ONðW<¯-n¼|òcú{øg‚n|€â¨©! çìÝ/–õùÆgiÓÙÕe,Ùi¬üöú¬kw£píÏÎwÀŒr©æ£–^¶*FÂeÊñÓ ð+€‹rYXL î€^dˆ"B SŠ^×2”y¬¿˜E7>l:Ób(P§ÿÀ3)êï¿>UÛ‚Šk”¨ö‚êL8‚ ÝØ*³#æöcÞ6ºme›—ﬤ¡(W5é ãšt!O°7°Ò0Ôêî PaÆg^Ý~œ<Ü*j{DiºðM¸MJ$©¨^ͼù4e~µ ËY×™9]p•ª­¦ÑÚÈ·êÃ( ŠÜ#êœ.^~4JÓh]ó¹ A¯^*Å5RÃÌPBEw6ߟ 5û÷h H°¥†®PlÕo:À#2:ÈÞ0Ù©D]”ç_ à’2xn(›  o Kµ÷ —•Qí{²²õg)°Àb§8¬yÙÜÐCÍs5…y½”B·kݲúOhDMÙɤwV,–ÑU”woÔ ÙT°Ñ¯i2ãd½~É ë(›|DScÍ·mœT¦¹é‚Œ{T †ˆ"¡ÄYP6À¥ã@þ#TY¥…R/­œ4*…=ª"ûgwHÑwÍS¿ÁQ© Ç}ž7°íݾc´¥¶¨AýÃzÙ€Ù4[°*2'¦žÈ©ßÙr Ê“Ün Hk3ƒÄ°eò¾„?â–eå@tÙ’xŠ&˜\†‹Gy¤J.¢—KV‚aöóÆˆ•L¯§3ÍDC/tXRÕ÷\ÑI9-Ûq ÷Y‡ŒIñ‹‰¿ŠÚkh­õ;„t vf•XÃAD¢ ŽÂ†›ÀçiGTô¥|…ØQØ(tgÂAÉ2v¸4ô¬5eiF)ˆƒÙL¡"B1ÛDº3ÏŽô€æ¥ô®½‚l¿h¿>K®ÝnMx‘N%BÞ«²L5äƒcÆÓþ*tÍÚS¹Y+¯e, †N²ÀÏ]>ƦOWy{©;›ë¡«j6¥O(yHc×ÅäÕ“+àƒJ ÒA´·%N>M**… ;Ô£Q8”Õ»œ—¦oêÅ$/öC®µêßòkáµú"7ñ]vŒD©Ï´r÷U=힟µ¿Úýý¾fl|áãÖŠ%øˆ'¤Ä„3Ç>«½÷å†` dˆ"x®ùD¿¦ wÌZ¼¯fºò¡zÂ;cÚt!YB‘ÚÐAšG;äâ+À qQƒ ½†…ý°øæÞaÐb *Èk в‚˜8ÉYèá°úÏijÁ1”ib#p"湄ÔÛ¼î ¹q2,›³Jóv{¡ŒûfÍ _Z,Å<Í̯„}©Ý¤ó­GfÃâ¢^Söôa .ãI]Žo„9UrÊÿÂô£Ë[]GȨ€f ’ânÅDO¤_­lï;J>Z|è»UweV…0äš3‰Æ±w0c)Ô!u?KÚ/[Œ+¨y6¸¹¬Ü‹²ì-œäì—®X0×`)#àba\ž`áE¡‚¨ƒ(…ÿ)pà NRìýg»¶2•íÛlñÝí¥BòÆòN”îAQØ ä¨2Ö½)+}ƒ8‚˜é推 ‰ [€‚“ÕÈ_ PÛ!|Ä®>JO†ËçÔ?„“Ü=[¢;—©¸f“ˆù©êrqâœgæa‹uYdŸ`¼\=]SSîímÞq ² ód:nÙÚ:6zX¾×ÜÿOZôÏ."•᩽G— ½øßw5W`•$ º¾˜? ã™}©Uïßw¹Ýô8çéê•þuK±ó/u4¾BOwÇîùÑ>?sádOŽ<;q¸íŠ)³ :`áº;½”­‡»t&Ön«…c²±¹HÀ|¥û`aÁ¤(µ÷Ì2ãÅßä=“ :ö®<`>$)ô5b„0ŒýàzœdrÏb5…u)ÃŽÍ!>*¤KwwóFcç{÷°™†:bwx¹UaÀbOÚÀl#ov»ä¼ÄkDD¸=º•{"øÍâ!%ÇÛ!Ò:×O€B‚tWõ÷»f›äróiõØÉšÙŠÕØ™XÚý8Áõi±Ýí­«8°b¤\>% ŸZZdð GEÄÝìé šabx#^°'}0:ˆ¢ õ÷ŽÀ5‘à*Û@¬<òöh57ÐPó!EÓÅä¸*÷Dsy½©êêëìˆòžail”i†WŽœ§¤z:M}ý9š¼ûõw(Šzª%g»Ã(KÇ.("rè0Jiæ¶~9q½È£óº»ìºZ¢9š4|º–tA*Í Ã Ò!ø¥s§–>]ãÌSÃãïíõ.·¯™·ðÅ¢þS»ÛõEÆÈ‘Wߨw”ÆðÊÝè мHyAÔ;72_ìmÆñË­m0àpP¦Ž1¸¸~*‹ ƒ¢iìÍŠ#ÞÍ6¸Ç,ØÈ1` ×åhŽEoIEEþ.N-·ª=Óp©Ïæìœ9¢˜a°%}:Å(]`0eì‚UÓX–0k€¨7¶¯€@ä'`ÔºµÍ݉±pheñí”G’øSÄË~ÉÑU Kª ¯Í“VG4el˜/RM»s@jðXÓ"+ˆTBy !Lˆ ÀPgá¡J‹ª7¢˜:*®«ÓPdÁ• Pl Pˆ¬|^9Á–…b/IvUÀ;Má!UR»¸\¾ËןwVtá³fJÄ– 솻‡Ÿ|4déÛ›ñn\JN $)ªF+±çt»ÍL›;‹$åK034Ë÷0Ö“Y/îúÞW“–§b\ Äàà9¾tsESôú±…„”MùäöÉEÂ!eø"›mˆUן|“‘4‘‰Uª£Ü¿‰º˜Uð’eüzs5s ŸdíµNÁ‚ WfM+jÊdb³Š]Dj´ƒª\k©ç¡·˜A×Rü. Á¾Ö‰Y?2ó8ÛŸ/\G6¾”ÕÉý ðºI%ìÎϘdÏnåÜCS%×ÈY º‹iÕíOÝŒŠm"@£Y–®ä^Ñg(‡Œ•  Ì¢(R$™ܱe ±-‡¼ÉJõÏ8·Zn`¨Á—ÇsßtqFƒÀAîa[Mè"_œ¥d j1š“!HÕÚ:ÚVƒ Þª¢ñ=‚­‚±ä[YÙ…T¬ÄYg 9Óø(Ò*™^±íÚP)É2ð4$#wdd}"Ä”"åQy4Á›é=Óê쀟Z›[Œùž—ìâwÊŒÕa!—(: tÃ`ÈXÞ¸¦Oˆw*‘YÙ¨`R¤Y (W@êé\ê"œJ ƒÊFn¾VÉG(„Ž$Ý@`ÂpµÜ–%¿t•8åŽ)t& #³J°Â\l3ñŸVr€ê(‚<†ëk°»rðÙɬ<úl}¼T.iYBÚÍ j§Ï”Ç1#<{œzÌ¡(‚¨"Iª¹ë’"±,É4——­Ô±¡™èU9}@{šÆ·À xÒº š½uDé!1Œ–„f Éz jmM,ÙB0z=ZÔÍŸ ¹I¦„ª5ófƒ†\OjÄåv=Ï tPnà0ŽÞxó çÞújæd×ÑõtAÖCb(Ú1æÌZ!Õ²QÈj Ø;¬) ötDV뇃„â!­™újœÉp°:ˆäßÒ¨D®1ä°íðF vCÉ×éaÎõ u8Ý¿Pû Ùó3b¼è#Wz ;¥^B:¢)±Pt‚‘ÛánÛ^Äœ5ìެ¸gÍ«D¿P]»áAxqéîÓ˜Ž¡Ï~ 9ÏY›¨S‰×û b½ò;òLï@¦î ðNQ7‚ÎÛ&.ð•Ç™xõuñ×÷³”æ_U³x®ìªeê=†P“™6&oa’µÖ1Hì7²iU$ÏÎ'tÏEf¼Ý˜˜IžVƒN2–¶±…¨¬MÀʪR¬.VÔ¸4 Óvsµn‰ &´kŽO12“ãJEÓ\ìïm\.¤²z¤ÅÂÀ«“¸C”ñuÄëä:Õ ¨ÀP4T×vвQq² ˆº,RÎѬSÒ4¤d ‹ê#â°6œUFÒeÜ©ÊZ¿›-†JE– è"6'1­±õ÷Qå9yµƒ„c3&‡‚ÒÊ™SôÓü¼ñsËõéÊšññX“¾)Ç;Ù´Ä›ƒÊRlµ-£V•aòt$#¿ßÕ'z ùŽÉßvܺڶ¬À¡Eûš¹]ŒÎK|i…wC±XèüÓPÒ.!‰F¦ãê%ydg;Qð"|;è>€K°Ì|ê|# ^3P0©ÖÛÔú÷ *¿6㯠î*ZMËÉ|ŠÈ’©(Rð m£Â³OçŸøÖ¹…üLÔ?²6üÐ" ¨©©“ ÿ*c²ñ>5s¬íÌñî}ãx" Nw/·+âû¯àbÅÀ¾î#´Vá3;굇tóFǽg_<ºxß[^°TÞžY6’ˆ—ë¦ñ)¸1ö0\Õ9æ=Üep‘Õ°xTsá~5¤f‹Œ<ÞqM)ŠŒx+» »õG¢^lð)P—ø0½K÷¨Ñ–\NÎr4X²Ì{Ûáe× G—Í›‹ ÔÉ{tEÓÜD3›Qh@û 0wƒý/ O ŽC=N V»W\‹8|©r)Dˆƒ›¯˜/j¥Óa6§[ù!Pâ.PöŸ•ºŽÕ¸RÊ =qïéuý}\†vHûÝ#Üîô¥¥ã×|‚üÑë€Àrö*‚ƒÎ£)U³q¨‚Q;°pJ0*J º‘äPzƒà¬„w{b9 b @£Pý ƒ‚óÄeŸ1ØÄ¯•ô5"€ÁÇ®Wj2¯8æBŽIºi;PÄÚåí»pCì/Ê8<w1Û„¢¨‡oECœJ³…rÙP0S³¢£.èCÏ·Ñú{£úŸÔõ)Ó³Çø¾ÏåQ¿Ç¿ï ¡Ú—îoXŸTžïåç ¾ËRnSoGøÿR¬<ÿ\ÍRzm&ýE­½e™©æ ÃÒ_%Šª“Æòƒi,mã B‚T@„ö?ñaBܼÃSÖºèëðÖt趈«rI¨%ê÷†µãn¢”ƒ‘õy³¶‘P„(A@ „ ÓùŸêÃô9ùÇù:WäŸ,öŠHÂÚØ>ª¢ë©í¤}Ì«$¬oš×¬%‚ÔSxs¨–í×_ïÏ/+䱸Ÿ!ÍõÂþõ(­˜^åJ+ûn´‹~Ïåö ?5cqù¦YlKOL Üñ”%‘b_•(Ûô0‹/èyOâiŽ‚výFL¦ð“©ßü¹ A'f™þ4Vf­¬»¢gW¶& ª™Emä‰ý%òŠâEÆÕ‹ LJ?\ )zŠA^æPÌ…xÃEs+'PZÎ\>A"@ DOåÂÙ?Óeª|[2é¤LA˜çµÂX 9­4h>Õlû#Z1ߺèþ¦TŽ3/õZ;aoNö~i¨K´|["Àã¯~OÑM0äâ(ï°Æ)â•’|›¤ÆJ•> /Ò­UõºÎ-á³!rÆã¬ÏZØ–ž˜A¼ñ”%‘’á(Ûòòë]9ôÇIÛ­“)¼$êwøH6XÊ"xhëe¢Ù™‘3«ÛUH¢‚6òHDø('”W.6…Y<9ü#8KÔR ÷2†`´+ÀŽ+˜é¸]Ak9pðÔ€"$D ¼ú¦¿ ºk#C…f\åv¸B '5¦¶)ײ­ïÝtqð…2Ú'VÅJϪ=SÒŠ'TŠ"B"'šdCÓ{*K"– d*ȶ«ºDOWrªª"ªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªÉ$šVWb õÎϵí;7©CË¢’Ö"Jf?OÌǼñ7[ú|r›/·šãðÊÕ¯r0Éþ¿Cß_l}pù£üÁøóã€ýûqóÚ§l?8?$?:?$?ÂØùñô#à|?F?F?T>püˆÿ${cߎ?J>˜|±ñĤh>ð{céGÒÀž`?†>ÈÔèø`{0=øߟPW®'YQ3óÝ÷}ýaᮆÀ«06:C`{íŠûI˜œö&® I˜Pe²6ÓÈŒ‹ÀÀäÁì yHaêvŠÐy{)yh+«ÕÂÀŠzäòÒ²©T<˜ˆ­1:Ñ]cÃú‘ 5ãÖòìÞ»ÓȆáЯÊõH+Ù ¯-|â ÷‚+ÐA^4ã=o‘ß÷†Î†ÆNµ?]¢Ì°ÿ} }¹@ïæ °ñ¯9œ|‘ÿzëŒé–‹ãP:ÖñÑWêÏdÇ+õ¶ØLRs_$­iYãæ?:Ÿ7ø]Kr¯§µsæ.ú·i²3ç ì¤à6soðå·Plæ±à±ÈrºPᤠ3Ö ¿›ÌbÒ£bœü£sÀ²EXÒÐj‘Îùfǃ,øðLMœ¾G.n ¯-` (v¨+ÍEDü€pëËíéöé÷í¼~ääîáÞr”éJRR–a™ Kœç9ÍÝÝ£—2õÀ§œç9Íçœç1ÖXÏÃŽû és›•íFÎÖfó›¦îènÕç2Îf1ÎE]éòh"oqrIž‹º¤Bs‘VÞ<ÛS£vþ©D˜… ëÎÝ|¡,ž´n²±Œ3Q÷¦Qkׯ1éÊWóØ\ÀfUµ/‰ÞO‘ú·DÂìZ&cv2xrçéèèvn£Ë¥Ï<\t¼£œ¾G32c#&‰¾D¬-ù¦ÒxkÅ8õ/ wœãÆÎ]ϼˆs™Ê事éÔÇjtyÊÓ,ŒÚ3zdæz¯Õ0Dê‚o¨+Õ@1%UI H–ª *’Ñ-%¢ÔµEUUUZ´ˆPŠƒPPbE¢2%¡•EQR’Dª„²PW«ß ¯!A]½òD‘Aa$ñ€ô-^?Aãhà ™nù­Þ‚ªœá@æ†i…:‘,ÒK °C‚,’B H‡0 ,°àŠ Ë á“(ÑÇsJ$áCŽad†AGI0‚ ,š ±È$%šPPÐa§Y'³0Ãa%CL8vi£’“º$ I&pDŽ"Š”AEŽAa¥I…p£ ²Ê0“€Œ DŽašYÀ€EA¤a¤–I„#†”a&–Y’v8Í¥s¢ $ ƒ M98ªeÁ†î ã"#ÞHI;ä$œ[§4œÜ™`ËY& œT­›ˆÃ¡©–XnÁÁ¡¡¹¢hØÃ,›Œ¦Ž Õ¹» l¬¸52Á«Jܬ44jô‚Dë’nå¦Ûqñtá.ŽJíNxßøžT=L=ª|)ÇI,ƒ”o2Üs®Œ.båGH%"ëh""3:ã@p盆=Põ|åÝV8÷weÇT›·G"8©E臨¨Œ—S…ÝóœÎnîîïi°¶ìå”UT,WÂdÇÉ8æKÌdÅi\8PùœÂ,³foL%߉Í#gcxZUÊlÎs’¹\7l’ˆÃ‹tê§™4½áw$ô„˜tCõÇëo*zîM™«&pãj1 ®gÆË8p³àvQ9ª:¿£:†T¶¶U·Jã/9Η5ËÉx·æÆ‘¹1EÖiòò¹ÎÔñš•x²‹Û]Šc¦zÐOÐOEy1Qvd’p±Ì8G‰ kú¸OD–ìX—8xð=‹˜iŸç<˜în¶·G~w%³2d-ñ\ZÝé¢ ë¯Ð9ÉWwÔŠ›áÇÚ»…X³×Þqßm<î8Œ~o7bç—CÊLý+å—¹‹6­ó‹¢ŠŒåG+Žp᪷„ݾiDÆÔÎF®mÖËqÖ†<ñUÜOCõ¦O/,Ò‡ÊËJœÜ~¦Úæò­O/8Ók›·8¨ÙŽTªßGL:p³;r-9×[GËì²ésï{µ{®UUðmêþêâ+¯¥S‚³Öþ¿¨º¨ãAA<ôPVCìŸÙùø@ÂH¨"¸ÏN¥E‘†RÍRBIHÀ’9k`&Dˆˆ'\Š+FÈT$#ÉÍ¡³qØ¡$Æq˜±`,¡BÛSmE2•…þòâ~ß÷¶’—‹3“,@$"§èµ5eDHBêR˜€óJ%H–$çF±†bʺ7Û²RäU¡5Iôb·É‘ó´¡»Æñ,;Ú´"ªï {¥_É÷ v>oÛ~'³ïºÞ8 §¾ åvº=ŒßJ…˜êâ +ý¯Y@½7ÍrB&›¡Åäîœú»‰F4‡¤‰vž Y.´%D’9“'Iÿâ}ïàû€ ~:|¦×bqþx~wâìa(,)u[éüµ~qüùšÙ2S€òÉ/û €¬é¶¼8ÇékžÃù8ˆ6¾—Býy,gý÷ëýç¥ùœÿôü?æ÷þ“ë}¿éÚЖ#&£$މQ‘‘ðµé’1Œ`Æ11 cá¿^“Ñ“—á/=‚¢õ>V!9‚¯Ó*šËüæz’Áã¹QÔgoåûthRàæÌ’™ÕQÐ} ÿÞbø&w3LëäÔ僑Xåòôô> K{rM$–%§Ú¿‡t²+þÉŽ—±úÐÀÚÆ5ï|~š¹šäùù¤êìEçDUS6]JÁDL4Úš£NÎL°Œ9à0 â@ m¥ïHl‡‘£©çýÎ97F³«Oໟ;mÝ yæÑð|¼Gê=>÷õˈ(Ýb ¡¥7ÑBzê0 å…“mZ».ïƒ&ƒm‰ÝÀ>//üóÔp£]Q.”šâçOì× ™·WuÅdwx6]bo§ jP‚g€©7…ÕF1Œ'̲ ¶;26°Í ÀVKÙU]2 wÃÕBŒ£ÓS¡iÉG¯TT63ð@À0•ºã9‘8`ß¾2is-—.SŸ7dûé› mÿ˼;>I|mÞ¨¹»¨Áñ·{•ÄÏîþ:Áéü£Ó~G¸÷ݶXÅÙh|ð÷yòó–Ɖ€cý»ØawûXϧO§Èп]ki>ZgïC!Mý?zboð€ÄJ“ó²QU‰wqÄû¼!ù€Ÿ×ñò?‡åù8QDúLÅzKè‡òrr÷è'…ÇÓøóø+V‰%a€û³`ûO[t4’Bá|m¾)²yßC}!s8ÊJèdÅjäXó™ndBB%œfF0Lâ5N“[Uu8^ÿΦaIáwÖ¾ˆwÄí} TÁ_êK]Qˆ)‚A@rì/ ¢dE"éY/èO·Ú;uÀèí{åÛ׬#VÝ1¢‚sóК/ž¿#´0“4}Í|ûã›ëŒèD3`˜/¬)ýÏ»­…Àà<áݼ ]ZaEÌŸ.§…Çõ}'Lr«º°€Ÿüÿä~]ßMÀÿ-»€0˜¶Ná:+µýqˆ”%xî¾v³Õ¬Gø¡TÏ1*Î&´þƒ¯±'·ò:v{Yêûûvi;~U< Ý.åËo§ØáôÚƒ…àt‹ý:}9…Sè`Á*{Ñë…æ a@@›Ý?ÈùÃêÜØ‡©ÁBâ?ÚøS¿ú¿»ú€ÕÍì"€5àžÌûüq›ö´ÁA7‡P°„I#âåc_Íç#Úå8& ¨â@õ€ìD.™ ¦¯oTº¶ÄЪ•!I þ˜ˆ€#I.DŸÿÞ…Å/ü|mQ6ä°Á ü(¢èúÿÿ—æ¿§Ì/¡Øoéù:¥Bd ßÖLÙ€ÀHf>êÇçjÎf>›/'ƒÜ?ƒf‹®®ŒhSHÓ¬O"`ë+H¶AƒUÁzëòL@„ù…\Û•/›G½0¤‚ ¶cŒ¾¢Ý}€uá „ª~ÞYæF¯ƒõ ‡L†SmK \§‹ß}•ˆƒ•܇Dp;â_I¹Yïܦ“Y€éã5¶OÖÍAųg/r)£{ûÜT]\8ÝÎÊ@ÖÖ O~‚?T#¨7Â-‚¼i̽‰w­æÎޝ;߇ø@·®7WüfÄ$@ ‹”¾S ¥•ÙÑ´oLýÇ@ê+ÕÕ¾™+Ç…lºRãçòTêzß^ç¹éo:))ÿÉò^0`ØB@#(d%q:Ñ1˜˜˜µ3âÙ>wúð¾=øýÜ~¿~¡8~ þÕŸS¾KóïûKŸâý?_î~Õ?6ßéêÇc‚~Èü2Z>_äпZÛ­šGevfURi9ÄÆ5sVHÐ u2HH ?ç|[_¸³è¶üá_‰üO÷?ær÷ò—W~¬ÎzÌ@%J†Ø?@äèQ§j#¯0¢ Ì•0íµ§ñîêËÞý,û¾øgßÏôïÚ!ý=Ù{ú¬W_–R‡àœ3ÛÑL! ew7àÎüí@Vƒ‡£ÑA³~™Í~ÛnÄiþFÊy®lºÖô°Ëˆð@`ãûÍâüdzÿâÎí¶4;úµÇò<[Š´cFqýy~bÌó"KÝšëßîrñÿtæ¿£w’}æMïOÎ2Ž´5'ÌqŠ#‘ïÌEÿ”‡`ó«ûË–V ”¢L&}­Zù¬(`l-ÍùËžÍéUfï«¡%•Uf¥–ßû^h|’4Q±+ù)sC¶ $}ÈŸV.¤‚í.Ü‹bQ_¤v|‘ È¿±åÖ<_ ÑË“Pú¤ŸmPJK&ëè÷¢çï½/×nޝ¬—çÊ<)w?E‚Aïîìñôøúÿrs”G‚åä?½³ÏÑ«`ß=ûßU}„ýÿwŒ§"ûo·ó­ãÐúmî{§ùßGX¶¬)O¡ée-¹Šb#Ô<ÂB»;‡ÅŸU#îäbt(yGf=ÞÆšÃ[oµ¡»ùüC\$a[möDoñÿ†Üàa]¡ÃxíÝ×îþ¥ŽüéÈÇÉêåžÞË_~G ®ï€K¦½z¤ÆÈyH@&N2uEü›}K ñ*yÕ‰%U' ™ÞÀÌeV:©_xö¼£ûß©þ—ðcÑwõ>Ïì³ö÷Ô=ÞÁÎkPõ˜|l`¾ æáZPVe$’ÄÏš›NÚQ 3Ñxá ûÌü¯Ïñƒ÷å«S–á´yž§î~Òù>âí‚Å)?¶‹XA·ý0²…ËÛÐ[výÛ+¥BÂÀ"ÀÇcÏá•à~;rY=\î+R8¹‚úœÞB…;¹¿ÿo+Æîœ\ GÕ,‡Â=ZÞrг:A;²À@ð€àÑü¹ÁC?Ù …F0GìA$-Ââ¥S_›$R"I½ØfÎì3üÌ1Ž'µ=?•ï3ƒ´RÒ­,ïfae$~&Önt_µz6y)ù‘#ðâ4¿Â!1:ðõ>»½Â¶•ûà˃¼C,È&2*ªž ±UÇfžOmò–ǸãÍ=Á»¨Å£©[°×-xg2 ØàPjùhÆ@ ŠgTùO%;ÇÑŠnñ[^UÉŽÇØúL%ÛïqÚQD)å_ÓàíϹ‚dÁÉßö]‡b{¾·hx^óºÕ3Áœ í\Ù¬²Qà¥Ð¹O£ˆ qaOjCÔüé] >÷§õyµR šnKâÁÕºmé£ôĘêÏ›E¥Üù¤ƒ¦wBk¨ÐKßf·¨(«ÆO.cðEïA}…ç% ‚ \(UPw— ]0½d‹ +@|r“\zå,oRÊNü=1™‰²¯Ìàø_üóõ?nú_ÐçcôñÐsŸW–Óþòažî `b<§÷~¢ÎÜ™Êÿ™AâÒ)4—úÍùú×·ÇTM)àR#™X#/zgäÀ1u‰ _MþH9÷A×¼Lu™mÌ”1·”æ1Bdvã©ÐFC2A*‹>éÚNî(—ëñÒŽ¦d4² MA<€D_¡1òÔ£,¬ÇM¨ Ä"2bù­ŠªøÑÇ›¾Bå±J㶨!N.Gîn¬¢#¦ä“x¨¬ˆ9~QÆê Pí@…²8.bb*®ÀÀPD C`Z!t’Œ F€jÄ B‰tëá:Ÿ¯Ã²ç‚cŒ¨ªì  µ3)ž<Žîíìf“õüÛ*ôl¤˜ 8Í?ˆüír¥ÝM(?š‹˜˜_ù4ÖÐüÉ6Ý`^B€” H…a«x1‹õ4gvý/ºõXdr¹wäðãZŽ.Þ>ëz{¯®ü¥õ¾7+¡³Š€×NOBû78ŒŒ‚ªË*3M@f˜’r>Û'Ñ)÷“EíÉqe„ézbë=*´ý&©A5Vº¸Ã2G޲ ?M„€²Œ-Ó<»ÞèöÍIŽÍ…¹¯;A¡L5ûT ßãᬭ/ˆ¿ü×»îÖSê¿·õš²êQÃ\ÓÔÐ}ùÏ-½¦Þaç˪ή0§8¢3__×Zæe"ã×#k¼³œF¹._וKA’µÝâJ –ºOw*ȼ7âúB·z]U‘j…ñï§r Ò¶Õ6¾ ÔÝ&cÙ€ýjz:ã]ß«ü_{>AþÈ cŸ‘ñó¶i~úyfJx¶mìK®¬Åˆ¤¶Â*™?wD_òŸNÀzÎcï~fi"&BC³×Eìñâ%H‡:´#>ÇÝQr@>WPk£(¸ öÞÓÄ™8~>vºø…ÂíEí(Žñ¯¯Û›e=Uq[ÔúgÂÀ«Œ=\_ŒÖ¨aº¯v1¶7öå~׳ã}¯÷¯¤±n-GõféiG-þwu¶Úk¢µOU6NP{Q;!A&âHfžÛÈB=­‚OúÑ®ÖÂŽE©ƒ$ µUUKûô˜¯p%2å¹÷6}ú¿Êå¾…*J0ûèü®þCÆ,gÃþËP—i,u'x5$e {Ñý¿Ãñ7ïíÆ%¨S«R7»÷%؛믞ÅÒ>_˃BÀT iA`§±õ¦3ÐÎö=ܰÛ::pGËÊà±å^ì:&–C“Z…`µ„ª&6t¥`–<©³)Œ*ÄvÞ¶ò­£l¨1EE‹ETUA"ÁV,D‚!¦JÅb"¥Nœê„æíT`¢ ¨¬QE‘â“„11’ú©Œ¡¤•‹  ¢ÃÅ(ÁG,8Â혉™[Öúá;üCfh§+m¶VZౕiD¡K—›Ãð¾÷Ïëg–|üs&t©×µ0ÙLB£‚ÒT}æÉ´×&¨pØÅQb ȾvS®4I³z32åYJ’ª(>ëH‹„V ‘ÁÞ0Àx  ðmátœ_éÚB«®G€Êhø³«Îh@‚U *ì­äïThº"­C±-rç-}¦zú@ã=_Ëöo}•ñôjL6TfÑQÞêeˆ¢,Yv\öjœ¹nz;Þyú;uò; ¦dº]8îþðE}Þ q«­ã½K†Mkºšk„æ6lgμçP:VÎr\ž¢*ÝxïNñ9®ÄÉ8õ[ê|ÅæZðDˆÁszι„£MÚ«9< ø´ƒƒ0b‘œcUf¬?­ˆù=TAžÎ=«ðàC þçº×ÍùÜË‘/S'Pùž—øž­±óªûÁ„ÿ=÷éZýœ<>~·ûv°ß(—;ç&¯Ôó~Pö¿ý÷:Tì` yY@´…‡ ´'ï{Ÿ9ý__ôãØííQ){!ËÁqãòè{WK;Pî¶ËË—_Ý— of×m6ÏÑÚîñc$DqŠs;îÃ{Fâ›g ¯Ýk e<†u+ÐynM^­ßËO×µ·mï&Ý×¥»ÜOÿvnyÄfñ D’QÅ¿é±õ‡£§9Óœ“–w|s—à`:O‹º,8ÃYíÐvÛò©ICMæl½¥Xyaº}C¯ïŽìçaÛñ§ÖèÔÚ2úœÚ À\ËØœÇh* Mßd¯±˜‘šh(¹'»¶Ìü&ô%ÍZÝÄB¯M5B6€jK¡m汸ÜFek&òÙ£ø¿wüÝ3û/ÙúÏÃy×M¿sý¦¶½Å½tθwmu×FBÆéHÛ•ž€@,’5H`$ \ü5ù§êñ¢Œ(%^Òhñ;Ìÿ}qÎ8^Á3P§Æú 5¥|µ©žAZ !b›eQu ¥ÐÄ¿:]þá I>ª•Wð„àAZ QÐ(»­¼”îPWíýï?½ú}é·r·wô˜ÎN¤Ò>r°KëC¾ySÐÃ0›˜–×nEªm“îŸ%åu/«*î–~!9S{_È?h{Íð¹à™7ÙŸ 9tábC—Ž«h¶õÕFæ‰s¿}¶ß˜Ó¦%,yÎgÌüA¼r®¯&ÓŸMS%ò†ÀÀ°ûd\Ëf#_ÝÝ^›´DI ¼5 $õh‚.vÐÌm;,™Ãv«-…¬V' â9`_^–%ŽÎ7îqkãu™DûË =ŽIsîÌ$4×j<`g6XÆÓ]ƒ½éÖTšrôÓ²ñØÚæ¹?#¡Ý'[¬z(óŽ5ßп©3¡›VýohãÄë–ÃÅ=sJׇN¹“‡ çñxó3—Øz“ìzçÚÑÓ\ {}‹Ë› púŽF×#´àØ ®!ÎéŠðÛŸì»ÞQ¼o bJ™3 CÙ‡ øÃíž_µØ:ÀPÀ ëå†ËœzÏ0sÜ2©:ÛúöäÇÚåÁ¿Ý`Y¯`‚¿&*|5ûyf€'¿žíûÆîÖÛ0¤Ii CBF óŸ¶í-Ò, l/÷A–;Æ+œd"¢¥Â‰PLÑ…~P©™±¨ÉÉC2ÄhT¢ A?¨ÿTñÇ>Ÿ&ƒ~˜Ç¶Ð]x´½Êæý›D à4›>gú}ºáÜŸsÚø•æ²A_²îs^u©Â¡çf›Ôò~g6¨ß5™(Ͷœ"ÃÒ>ƒF‹‘1ðîZüYc{2ê‡êÊ~ÌglÃË!ëí†Z¶ª›¾2{.¡‰ŒÄ®ûé]sÇÞõ›!м·çÍ‹ýýÚõle@X@ˆ-É§Í ë& ú °ùvã†U¥ôàËú¦=·®?A»•ÝÓHvs Iîð§|wÙCÆ‹©DH.åV8Žæk£Ãs‰ IØô6s"ø? êülé§™[ÔdvXÕÔàðŠœ’dXƒÄ ¼BˆåU†’BÄñSSIR†(Q÷vpR`§Æu¹ÛõÿéCêËš¿„Ûu^3žyìÃG•ykq‡ëÿ>?†ú¦·î4r!ì®[矧 @³·Í¸"}÷_]œ2ì˜ÀÚ5|+¥¢á¹†å·ˆüþUñþX ˘wÕÊõ´{¤Š¾ÚÁ¬ëÎŒ±Í…zðGêã"°€ߨ7Bޏ}µ¸í|ƒ$ˆ×º¯Y6°£?Êg·ýù„,PIl”;°Âd¥,¶¿:hÁúŸyËè·aØQŸ°lZ=b޶Fh™e€Z|˨¬¶Íl 0~îG4~ã·ÀšãÕ“ÔøƒZç û#ß'Ã4»Wm—î¸9ù"Lˆ¥Ó@„ ˆ]ïAˆ¯!»¼bâæaË©tc»$Â^Ê'®ÈC«ÇjòÞ×&+X;ä÷=§ .Œ™µ†÷1]õ·êÝ=n¡†kåõ{ÑaÈI‘&îBç äðƒŒc7t9\€MÁ R`q3ËÜæ$Û®Úp²‰Ì$™·vQÔZc<ÃÄxǹٗ}vyƒ‚瀈‹;‹C׆ӷ8g ª1Gç9T4áo¸y8™‰¾¦P$+˜!ã-ý‹.%Ÿò‚“©"L–šíáÛÒ„îôqäÌ<û9S>¤:¬ï%š#"XC$P& ™‚'NþQG»¦or ;7©¤Spî㠞׋®{3†!×e›IÊw:%ܶe•7”ófsiio=öž½ qÉ3•g†¨/‚ž§yœ’l£8uŠÃj®¢›â¬¨%#ÃŽ[Éá2d¸Çè"B\åÚ[zêñ®ÝÛ4”ëÄÃ{/r[*µ™Yº‚iD!‰óÛ§m=õôB‚¾Ô Ž„–ýÈÒL6z‰ŸT(™%Çd!›Ffò¼úò¼p¡o*¼AR&¼ÞqØÌì(*¤I%`rÌÀ¬†¯<t“vn­šãåR$wWk*z5¡¡1‚T,"–yÑ¢õîäuÝx^âëŸuÑÚb`jÌ[jh¨àZ›CS£QÐí:Íž'¾íªÐ {éæ{£²í¯z;Í]åçhe{¯Þü ~/O{o½Ã»ðgÄ‚¾°ážTTüïl‡!93ÀW” ®…u1 …‘D2,’Då!AZPW‚¼ìÜÞ‡DéõoÒÊŠêâc9S*Ì«uþÆTÄ—U±ûÅõs(žC½E#œ’æ·ª›‘ö`Ü}Ù7V¨Ê2òøî£bs/6W7 II…žÌÀÌÎHÌts¨Úd‰Þ+ë3•rDw¥æsœç5TlÑÁ_*µÞ¥˜å1TpÁ àæ!¤à„H†¦mk)jåóyÎsœãp9ÎsÎ ÚQ' $ÆŽ¨8`æU¢i8iafš8Ðȳ„²$¡Œ! Öh(€+FÆ0± ›…µ,°àpáfAÁ 99s­M&6q ¬rô°Ò‰(4vFÈÓYe]5œkjb²Ni æIF† f«f˜i¥–7+(39Îsˆãn°hhag –ã5”A¤²$–ÐÇgs,°Ó ‘ ˜qÉ4,²ÂÉt¡Ç n`“W•†p¬™,â¬bhɈàYÅŢƂ›…ÁcŽq˜,ÒBG8p’BÉ$²‰$rÙœ“šI ÖQ†åCfò÷œã78Ç8Üã78Úi¦Ži£#C  Ö²L (¢øÍÀ³ niDð$m./†1ÃÀÖÖÒ"‡%ƒZ FaDŽ npá&A¤· B ´3„œ ÒØ,²Í,¡ÃJ8i›$–ia¥3 3p(Ó„šaeq¬ jÛÜÎo9Î7ÒŠ j®`ÖY$˜3pK,pÃ0à qøm4i…™c…rˆ ½Ê`¢Ë4à 4Ó‡áǵµµ±›‘Á˜áÃ"ÈPÜg4àXäe–QF–pÓ‡8pæÜpÓL0Â0Š(²Èbœ,²Ëc„(£ŒpE1¥,dÃm)Çh,8S1e³UU$)œàæ’SPhY¬i@ãœ(áÀáaMDÉ9ÂÈ$ÑÍn„g¦ôÌOVBIÑÔäR”¥)JR”¥)JR”¥)JR”¥)JR”¦ÇÈâr: Î&çs‰¹Jq7)JS‰¹ÄÜânRœMÊS‰¹ÄÜânR”§rÛUv4)MM R”¥)JR”¥=^»çŽ#‡w p Õ»l¦í½¸(þ?ÌäÕ >ÉQ…ÔÍYbéùƒê‡Ú׎™<Úsë:™q«JkŠaulÐOÛ~«<-<á•àI¤«,v½mll"¢s\¯}3Ûˆq‚,‚ŒÅÚBëܘ,!<ð˶:(ˆ¢P4ÅÎ3i#S 6Î[.C®˜­³ÛkõîŒDÏPãÏÑÎzú‚ô»±ë•í(õÅfð“4ÚNYÞl(Ði¼BQÆKœ5Ö¼äbÞjaÞAfÔ l³’kKÕò/Ÿï|ýÄÝyÛ½ ‚¯*¹äãÎãÉçôÓUŠ ä 2f;Ì´¬<WÍþ†[îÂ¹Ú²ÅØÔUŸëýÞ줻¦ð/‚z8 þþ0‡d‚¿ÿ}g²úßOí½7¼ü¢ô'²7I$B¼ýŒ"ÄÄ÷¡Q@OíR{iOmU„k³¢ˆ9PQ?µWñ‹ž²8²C¥+54CøeO–Q•©-$YìWÅAZ´øˆ+)=´ô2¥‰¹V_›ò¼™!zFKF3Ú `þgô½ü´m“wû­gpË À¯ÕH4~?CÇÃïðë;àóZîˆý—Ò`ÿßüq†˜^´E"‚°_‚S×}ðyua{o|Që?³_܈£ÙúK" û: ä×d A¨yòÁò¯ë–|öSlò?"rMàÓíþF™–õëÚm¢-õûžËYǤŽFôò£)®žPàš75ÌÔ–S!Ò`p60QYB¸0aj”Y)Z.Yà6ÛÄÜC°ndf8:r%˜NúK'HSQ¢ ’†³CJq!jCrQ”àˆ ‚!ÙÇã’> „4 ˜âfñ ÜÐ&@ƒ‰dèÉîeù#ɤ¶ŽÚ¶Fue&íHí’šHg½ VÞ’,w6dš: s”@Rª€Ålâta‰¼³vŒæp'¸7-²ÚU*ìÄᬮ?B„˶‹K3nÃRL–§C iÙ2BB¥Ü]ÖèåÀåÓQBבšvˆ9§ÆÐé2HL0UB0Š‚1ç3ᯩ~œëÝÔêÚÓð3ôN‡N:e¡xT·jÓì¼ÏWU~sµ÷¾ëñò;>wú­§=,¨…‹÷^’H:àBBA€!£Œ2Ч`e55š”T™é'&¤%‘ ª+´CÀ)]éiãŒ%d†Uˆ­9Ö]žóv¾õÓ-ˆcRÝŸöxj•[|QiSÑû;ûNeÚºnQlV5„2ïcy¿MÎ5˪ª¶XýÇçýoeôµß w<»saièe`Qå›ÝÆ=јÃ*å/xû‹¨Ã҆˟,ý÷Iï½.žÿç¹^ÄØ‚¼“¯4pv¾¢×½«eí0Žx_-ϲ˜}=Š(q¤‘É(‘Ê8!`i…Ë,TVØð­â wv ×¼  ²âÉʈ®>qIRðVÌr!ñ¨ëðÒ˜­ú+?¢§´Ü®PC › ä%}U[’c¼ê4†êR,[Q±¡¼5Yp(‚§ê]ç59ïßóýM¹ú½ž—û~½|ÒèæÊ¨Š${jšµ†Ê^ñðWÀú¿U$ìZÒgÖ[¿ú3teêù没¡pA<*_x§ü—mž`ÂVmAÞ¨1¼;’æ,CbQˆ Í>ŠWvî:Bm“N5W,Ç È@™/j“RãÏÓÊ„ók`Õ—pˆ¢§}*†,´k¬Ós–õ=>PõhéÉÍéœâì(zWNPã§ËÝò 8¾<ƺ*¯ ÚRë¡Zx/PêÝ´üñ 6Ú®›Åéǃ³HÎwV±ŒÂó‘‘Ûj± ŽÅÌqv¥ÑQª„©PŠ´Ibª, ‡àxa1°€"!DR€‘éóôù¼Þgf`Â\V Ù²’@ \ÄÇ Ö×0ÀÒõ°Â[’Lƒ£‡°Ül9{&Žp A€\ Fi²O ’NO 4Ó[‚†ÃÌb¨°˜¿^ pù‰)êønlGy‚Šƒ2})IHï— ËÓŸí½©}Τ#¼¦°äi†ˆUÒ¬1K´·å€ùªP`Ûy'ß'døô]Y;Eïñèôîìáïýl‡½‘D‰è¥"I d¢j•FqÊMÄdÃBŒBÙñÙ›§ã*e•7Ë l¥VÛ>ÍÉ;³32º†"ˆB ´ UÀœ¾-á·ÿ®¥qä¡ÀC€<€¾zonj„ApP9‚ë Àä]ÚÄ àÞÓ–ç'ŠžAJkÔ›-"Ü—XdÝÐ)“î`mtxykKÀp˜aÆÞ¦—AIÖjèu²ˆ1=hƒ!¾™ÃÁ[òæ-téAɆ©è¢#š]¬1Kö\0 œÖ”©%‚5üA1ËN9DB.M¡Œ‡!Î’ß0vðO‹%¦é„èAaÈ# !a­u$Ô“hB¤+$Œ6h7½rñ§%’šùÜ-6…ºL†ùÄff`P„‰’·ÆZƒ0ÛUC‰«άFÙp¤É‹ß¼ õ8X‚νþ>ãÚŠ(N¼ªr¾$f4Lq2¦°À0m¦Ý !8ݘ<ÊyG/›ÁÃ/¿ºŽþÙ®1h æAnAÁ¤ß’¢þa3Ž;K((j•ô)ôY{u‡vƒ“›þÎæ´Røæ‰MúÌØp-•B¨”°Å†¹Y´‹$c$ D”Ë*–Ãà%Æ’Q¿W 8 slµ¢âêW—7¹ÑÁavÀwräpè$—݃1ÎH¸qßÒ× A¿ˆÀh…X0ÄR &ü²«…UE)×ɃF“±Œ*­•Ôî=F´P؇dÀñlëÓ†4Ì6’ïpÀÚ š02˜%¡¢s¦ÃÕÄÀâÍ0ø©.Y‚ÃEˆ0g(6ÌÞš»^æ3„ßz4Ì vnÀ7aev؜ç…÷œ Wáyuf!Ã$ø.‡Ž¡…Ð {;ÍO‡¸÷ŒÍ¥ &Œa„­ðrAô­Ò~=õè#™Tíx¿ÿÛîÿð}ׯúÿ=þN§7‡¦nÁdN;T[Á/ˤÐHÂ@èÎŒ„VJˆ'm.± ¾t’\rcûïfæÌB»ÙöÝ·Þï¯Àûr66òXÀ€`´¥X­÷‡2]«ŒêýE”M†_¯äaÔ¿(ª1ƒY $ I!J€ÊaRË …¢®äƒ‡IOÇï}v+êj¢Œ$€c<ù'C$¼Ý[ÍÙ‰ŒlwÆf\*N“œ¢'—¬ÎšrÄ…´èéçú¯þ?ÎüÏó~Ÿ®ÛÙ£×Mv‰ëˆzðÝÀM¹Ž4ÜyÝ“šòެs{ŽO¨4.óÃ4g«öžm}§?2†¼hÂSõæŽkôxÿ4þéÛ÷÷†`œ–㘅dcª¯Ø ‰}ÒUX¥={ýl5R„ßL-襮„„®Œý œ§Žr ’K(G 0ÑÇá¡æ’@„I„Y¦aB4­ä›µ±Ž·JÂó"¥ó"K±ô¬­ÙºæÜœxÕ3’"[u¹™;™U¬é¡TÖFY§âþú—ìþ¿÷õÎÐ8ßy£io§¾7õ=Å[“L È…z™…Ž\2Á‚@ª7 Ó±„ RO({=ÛÖa—lóêQ9Ëoý¿0?týOuà̶æp£×ÌɆ“‹[¾^û‰…%ëRCÖG"!$àÑdÞmñÛF(S£û¡CÂAÒr~jq}¯˜nM„ÇäNæa©ST -)S fL”—Ø:ùTŸÉmÿ• €Ø—!_á!«)XûŸ¡Bà4ùvÀÂg¦Ì(›@ºAº|åûâ~«,ˆ©e~ú ŒË%ÊU`ª,RV‘aŠDdR,UPîûT‡i‡7¸â•…Æ»ÚÊÁ¨Èä1.]ÄÈ€AH;#ƒ¹C‹[G5˜Ð†Ì(qYºÍƒp’Ù†œ4’‡s†µØÔàÕ»]—c‹ 58·$0jdÈä_{l5ÔÏ_ƒÇÒ Äåäó+¬ÿG+y6FnoL¶Í²Â"!EÑGºmLº³hVÉP @&)hk u{Š7t‹¬†Tîå— 5¶Ä¢ÅDId™j% ³•…‚"ˆ:¡KïÑ„@pÕ³V…b¬ÉºJFDÔÕ—&’fÌ¢©?ŒHU‰E–«^Ï]÷}Fö(÷+wöúò,ùñâÒ_ç2¨œ/¡»f¸šŽVv»UdŽê”TIJ Ú„ ²‘(!9d{üù¬â©¿! ×0Ò1 7Ú¦‹Þì˜0,‘f¬-Š­µb%Mß{âu¼ ˾Ü^}œ0èìDü‡{½fœ@ßA-ƒw,“S¾±Ï°³9#¥Áߨ֖.M“D’°¡)ÌE„½Á¨K¡›ÜÉ"1&Êh͘QX‹,¢Xzð)r´Ð™“2ÕŠªvÎIód1×Së ñ‘š)M¨%›ÐÐ*Ô(gš%  ¢&)AÞwš4vžGmgDE‰áaR`™„Æz°¤×¥™ð`hÉhz©½MNSÑ€a EbÑ¢™J˜•i¥ïO‰…Mî°¢“©‡ æú®½N "E/žz¯ çàúcࢋ¯Ó,úYð`obÄT5¼’Ç» d©°ÂÑ0²L Ì% tÍ2¥)Tªa„ÍI-#m»¶CeÜá¬ãÜÔ‰¨ÝräÚÚM%¬`k“.\=Eóæ;ds:Ø0çÉ#“žÎÁ&ϋΈSD„Ê´Ì9å)¢ä’%>LO›ÏÙ¢R’P……å|¾>Ó¼÷ KsÛ£í $p¢Hô‰ û½ƒpÊ:3°èÇ~^íSÀè%3=·MBZPC®Xc£ã2$¤qìÏö:+Ìû˳Ǫòtb! VqA$I†£†˜iäン "˜æŠì’q ƒOÞ¦…Üv7›G°ïG Š yŒF$« !mûñÄctÅ…ƒ†@Œ ÝZînÍÎ;EŠ]£ƒz·5omd`U͇†hº^ZÞqÁÛÓÞlA]–Ê g¹2Êyx#´j>t“~`ÓÝåõ'?Äß¿Ÿ“•-\–^›ÝwåŽ^MóÇÝ;:_÷=·{CýÇ­ìŒüì°UUT%­Üó»¹ÁÙtñoÕƒíöw±ã8Î×ÄgCÌD9”O°5âÐ>1g®É¶U@Æ„”>á%?—£4ý+éð¢0:œ©ÐÁP7ëÄ×tjÿ ²ÐªÊ·Iøcª"_pWܺfƒÿ˜||4y»9 ]>ÐÿµòÙ—R&§rGÖéõb:7¶âúîd¬;@ŸÍþëm†ÎÐ÷ i€tgÙCíž“²‘`/F €(Ü |ꔤŸIÀÝ¿%tÿHh–ïåMñ•еÙ]$»0¸ÔÐ—á ™ 11ø/eß-ELeÜs–øþþaÎ{>©×tñ;yåúp7÷,“A;iAêõjíôš¬bqÿWÄý?1£nzéám‰§Õ»ÉÁS~$ác€°7äº0ÒÂÔiAJ¹™üƒÁÃSéÂ>Õÿ=ë–Qùï¯çŸoÔ}}ÄψºÇ‹O̧}ç#”A&šA¥œ8I¤–Aˆ„ ƒB—“ÍœæYÅ[{™—4â8£B&›1ñ•›{̼­­×Q³4¯ ò~;ï_ó€× 6êWwÛ‡.º•\x€7x˜'$ÍÐ ÔÍ3R(#¼‹ˆ%#ß` H(“ˆábþ½&3AÌR;¯&aV$’TJÉ0 Z¯ñ®ï2­»M÷'"Ä9eÚæ§ä|–fÖéÏSZºr;’âa‘ ±v¨{¥ƒ @ˆ¿-ª[`Ý&`¹O­LÙ]B@åSY\©,FmX©æ´ØR§Tix]w`⇀7÷ž  `9µb&VË QMý ùAÁUBÏűB„É”ª±,H¢Ô}ýøÈõöó÷f92"Ì‹'u´á ÀH¶€s ˆE’q¤Ð¦0(C˜iŒØ8Xƒ…–pFÆ®p2¸qªÏ®p’É`ÒF€ãô@A„–æÓ"rf^ã€QÀ8+΄5ëÂtÀ"ýIs½f2/bêî)&"¨w‹ê0DÜ(Ó@?C(!“/y”M #g2#"ƒý‹ É$‚˜Ù°Z~" °€/pŃrÅ’ ÝÁÊuÿ`…;ä’hñ¶,õp`' ÝóøÖ©c›^nFV¸KÔJn5eø·„aä†7`É“,ïVàíÁBk3 5Cÿw‰ç7Ô íàî8óòÙD‡qÕzL´SËŸnÌÌÁÜ„ Ï]{QMô(환ÔopÙñšÎŠwûãØg °íƒKh6þ:7K¿NÒ¸+t'ªÁÔ+ «jÒœÃ!•Ð2Œ¦VÐT5˜ŒÀâØd…Ï=xÌ”Jyõ%@3ÐÒ`D¸jÀZŠ€IFk¯H¢ÂºH9m3¥Û:úúœ…Xp ’ÄiÚý‰ êÀC»§!7k||÷—øb=º×Ô4¬cçÊõ?ö|ß³Xœ³MäöÄ‚ +î,(šôJ\¨âiÃßöé‡ól9 Ðí¨õPqþÉõ§âwø<Øup ¸¨âQ<Ži—Bà9¥ ('$‘ÊrÎ4ƒN`ÍÃG°¢ ÉdkªÙ ‡w3ŠyÌ/‚ˆ1ªM´Õ•|¶‚y¶s \–6õÑlîóo“>P3Ðx9ûÇKø^ZÒ³ÒYú™øüµ~‡Så-1Ô){Íè A*(Uzñ‹ˆ‚DOSe¨‡buÐ 5SöÉìŸÛ¸GñÁ"!LÖe#ø8çˆÜ€"!c ]„=^«8äsa`I?CÈ{"솭b‚‘"™5”Šª5F’R±¶$´™vb9"˜>·/Ýõ~¿ÖÚúø³øp€² ‡dëA¡³Xp2ŒÆ$ä°i&Ë`á°AÆ– Á¤²ÈfÐnQ¥(£ŒQepr&ƒ€o6„šA¤`h¸Q£¹¡¡À$‡ÑòýãþäÜff`Î{‡~W'¦Ø˜^I4üéì͇Öüñ૆PÆfF•fa†–Jùûã#™þ_~?£íÙ¦ÎG€ùáïuãfû¬MŠø´zÚ)}$½fD¹$(…<öåŸW埉ñ8aD7·‰=xH·öÐ! ›«* f!:HP`ð$@î |õéVò»Åcâ’Ž¼Màü9¬ÌÌÃxU¡Cž …ðäï1»\ö:ïÎëŽȵyr2Lw7 —@É›z󼦸Öš#gè2xàl‘Ø)7]ôòÕ LEf1`\ZLj"2 .IŠ xh)åV#A(nI fé6yc§  Ä¥Pä Û’® <…Á f4µtцÖZ°¢B(‹ˆ\RG < MÜ%BDÀ¬ƒáCiÐÓŽÇÍ[ˆ`ᇑièò@ÞS+AÊCŒ0L!èÊE})§NL¡^6ÀTd_Dh‚X*:D`0ˆQµÑ®`á‰dšxö_^½j"ØÄÐI®¥c̾ ÈõC´ÄðC¼ñ.&L(ja…)JŒÚŒ²ÑŒ¦U‚aHŽu“,×—ác¿•ðѳ›½¿Sšzù³±õ¨çÜþ_7ÿZ½`'^%@àƒ BøñþéÜéxºñ(+â%Fçmª/\/;¢j"K0ŠÅµh_©õ»þ®³:û:ëcéä_‰éÞà²ÊÒØ(-"0Ä"R¿­W$eäÅÄ<~'Ö?{û^¿S:ŸÛœt“ q„• Øv½ØXÙ›ùr·çr.Áãò7ÐWiÒÄ!é * ?ao{í΂ª.©îoìPå„ ï›[ Í÷ùùh§Ù¶Ñ¶q×Ñ8Fa¹_Eª0æÂG(‚Ê$’I0rŠ8Y¦X‹ bÎ En¬@«szÌ‘zæQT¥»™iñª}~‰m³3պΜ¤êó¦¨$©$‘ÈW,BYÕ8€ðtV »qâ È×fÀ=/šdéÝòÛ^ %g‹.°Â¨¨-º¹Í÷Óv¼#÷yÅTH0"æ±0êf«¤¼$çÞ”DéçÓÓÍΊºýÄ i-%FQµªZÜÁTƒi¬£­LG"kZÖ¦SN"È"ŠŠ 1$Pð<„Âuô¾•c0o§Ri¬[a£ÌŠ <– Ó†„7,À²Ë(¦ãpƒÎp€²é«J$f'Kƒ„`äÃ1µ‡A€'%in{ý}Xyèïž¿˜šöv:0v[ž§®íÊSSƒv#ÜÓ”ín§_¦Ã*o⬲i•¹díË,›ëƒ¾‰…5ïÑãGÄHŸ£ÍÈI Qè’D2(øyîÁIâ¨b«¯íx¹rÙµÏ[y¶î§>ŒÙãǯè´¢$(0^\ÐXÉÁ DÚ¹BÊ5†ýŒE™pѰ€QRF;Å€€€ È;{1î±zègA â yJE!SîNê0 d¶Í¢  ͘l—k‹"¬g:N ©Ó«€— ƒ”Ì3rIVJÍs‘ס¦NR"M·¼g>ÅeM:'ŠnÚJ€õÐ4yrxã“0C1ó9Ès•`w½ÌÌÀ°÷‘ÊkgµäòXXAE¬pGqFš3¶ÝeÇ´ÚtÝhàÀ¨ógƒÌîTö‡ w¦+­ia<4o¯C‰dÛ¤g[QþËÛ<'eÌÂáÆ‹6IN…3º”‡w§tÅx6_þa“ÀÎ7°y ÓSSžš¸8§u³B‹ èT ¦­!!@OöɧÐÙ%”ý ϺQ”Žæi•;§0X`0 “ 89ÃH$ÂD2,D„374TUldÒ~ sZ›cäAO›¼‚×w›9³WoÈŒˆå"¹ ~´‰úï?,¢ƒ‡¼!#Èí<ƒä»ÜüÞ{vÈ‹êt—ŒïlZÕ'W½Î¿‰îüðòñ1þ7ÊO/ÉÒŒ?=E^wwCÔ…×ÉPOŸú¿]­6à÷mf“ë”Ú&¶p‚¶‚Éh¹ÒƒIi40’ 4ΚrH8cͅ醥Ž!¬vƒL ÂW \ 'ð~<Õ×v°¬s°ƒ2Š.QÓ=´Ökvoæ¾Ú´wL"àüÓ!TE)hî%JFmõø.ç‚ÂÇ“ÈI^7ÖyÓ–ËÐäÉëÌ?7 ÏaâáÈxdd@¥ÆtÅC4ul9%#}yh;‚„½IÜM@ôAÙ,à Öpq˜c!˜€ñgxF1%-'C3%)bŒ®¯'¶ž1 û Œ˜«çp[ €’  ¢M[KGu:¡™eŒ¬Ûâ/^];éÕ’d‡wÛ¿YTšÞ $ ~šªr–×Vš™15”]U h¹š“,Í•ãÑIæÀ’gwzòW²4åçÇ>,ï|oßõ7¥r{‹êf Ƕ°ÂÄ­H\%ª~ïèpïSû/•WÏH>Óí•‘17,i%†aà‘Í4ÓƒŽ3Pc`Èá`á"$€á\P]Aȉx®D9zv”ÕÇ„YÎQm„6Ñ &•È(z.øÄðÉ”SáøH}Ÿü?x‰C™ßzß÷CÓì{åQJ~÷ Hk:…“ >ÔL_vßš:ÜK±ñ°ԈÔ6aü‹o˜!$¢ ùÒ NPÄCRLJLX$‚€¤ÃÏá³åõtïzáè5ïÔ6aÓ”Ô 0°ã~h²M h ² [57F±'£€äšpÒÁøÜ ²À€Ž B¯$šÚpã‡0‡ÀÑÀÎû“¨˜žSx!ì‚\8¤èÑYù± ŠCæ}&€e@ŠpWÓWø¿kà¾áL@aš¦,:!Í‹ªOÔÏH„ÃÌCˆnÖQ5—¨ëóßfà‡^£"HjÐ혡^ösä8î„;º=³œ¾—ZpÉŒ!M¹c€¼]pZr@¨È Pd LÇhv_9ûËú#\¢Oax‚j.¼QäðGFtMlÏðÒ>éý‡"!Åhv¸‚‡ó±ãË”@!Ï>©t»=Þ ž{ìL¿j=3ú½õ^>]ç‹z9¯f‹Î 4¢Šo5­ÆÆ<û©©¶é Êr•ÆKLHÿ"Ó ì¡#S0g^2î˾}7“²É!ÙÊy“Á'€¢ËŠ((;&@™;†³¾âXöº™ks+änw⚇AŠ¢<)ÙyŽ— 4ùI,‚Àï‚ ÜÕ  h`  S6{H\JÞ1ã_Kú¿æÿëõ£Ñã ˆ‹'¾û^QtÚó½Ÿñïî°p‡*p±°Ür3ó?íöÿ ©éŒÄ7pÑΫ1ưëZ©Ûîûp½¨IK¥Y„#C3èõÐPtØOÖÍ‚ ÀD ¨þ×Ü¿z›«mR*Õ›úóëæ:×'i÷7é²=qnVo\§¡@8å–!i†–A¦ˆ²p¢PŠ C4aÆ‚ÇËå>V7)h=>c-”ð±×#C›<âäðÛÂè·u²æÔ̇ôßåÿÑôVùs´Ëê~?ïÏœúïü•Ò9êôž£ƒòfùbý å…êt<½³³ (,I†/ŸÏ‡¿baT„=³Óüã’SÎÀ®—GM™&gX\Ѧø3—­Zti¥ƒiE £‰Î]œ¸a#hællàÙ†²e¼MYj¸5$7624¯x©ß§Çè²>*ä:y«vnÉ$à‹ °_Œ NúT'È@ýÝÃæT^(1 ”Ê…²ßh ¢¬=7!:˜q(^Þ_©¾Ö˜@xf*«ÉcÅ0 žŸ¶i44sFܦÐôÓ»$YGüCÁšýy™×©N éº9™wß84Òá¸Rw 'u(ªÅ†³oqMìeößj˜æ€ñߺ7ÀkGÄ$Ö㟒=޷Є֎yž/ÀÃxr'‰³rnv8$L¡Þ{|¬2ÁÝôHäëî{ŸË&0]ku"¡áe;Vˆ ¢£0;xõãw¤¬3ÖÖÌva–¿õ›±yN¿ÙüN÷ìúÁ„<3‘7£$›Ž×¿üoú&ØŸgýþÔ÷ˆAÍöÐd%uê¸,jއ9Þn–?)·ÕæŽÑØ1®$ª6xQúßãñ¼Ïþ¿ööÞ'K`w³¶‹ I"æ!ÜFÇitã ŸŒ:¿¿•H.!WÈïW•úŽrÆ\³ 3YÂA$’ !¥a„ši†8p± @ÜÆÞžN) ɸ›™ä½šlé ̱Té'w¸å½4ˆãa|¨ÎpºœŒv·sHÞñ¦[†Åuø=#é·ë¡ßÒo ò†¿5\Ø`Ï–\¹q‰¸a´%å$@Jb͵øßËXzÛÂà÷V9ÆÝ¸\HÖÚc<³–pqÈ,°¢„L[6…I#m6°oI˜ÙÀ .„iÎÃŒi¥ˆÁËB@€g”§_Ýø1ïû#ž|øDt9`D:¾¾;ãðõ èÓÜ9¹úÚ&äŽÊv˜Û毵ѡjŠ›êÙäÊ8D'<ôÌ„$ÈB÷ ÒæÛû»]=Ùo]Þý-Fö3_@ !mgÔ¨Êçà«§€„e! EO kwß2I0ƒtð5n?+‡)?Ž£’ö¤“ “ê#…GTµævÀÄÌÒnC9I†:N.¦œ5÷™û¼~I Åúó‹œ[2¥º,¿˜·ºk÷C/N L¥é`vñlâæGɤֿŒG÷´ßó[ðø}{DíTãFj¼˜%Z€‘7àÿ¶ã¥ôŬ¾PÿÊŸ´üjv¸hÊÔ±3Uæv.0ü§ðˆN⚈7\£2syOÔá¶cÑAõ²¨áxÕkp£I:¬¯Qö¾Êù¡ö¿£}÷ê×8C¼bÈ>ÎTÒpֱبŸþÉÙWõ¾ ëU\v!#Lس“°Ï©½èÂý·T›3äüŸÅïŒ}뜻ÃÛoX+«P‰ŽènoZI¤ùÌmß©Ófê%Å1(tÓ7D6émÓP*äCuZfSQž¥™Aëª P`Qú©YÙë“2±P߉Á„sxqìOß¼ù³~¬×ü¯ûWçt⣖mÈåó<Äíùz®x·­Cšr¯¥¦mE%NttcÕ±¡3BµÙÓZeÐî¶t#(0`Ýí¯ßç=#u"üµc¸8Z­  ÁHúÊzŒú9+?D*°Çùþœ„…„{5ïÕ¯‹;ñµê¸]"CQb#ã׃îøƒo½8]•t©obý"_ßf@sïúÀºnȃFqúÝâ·R=ê×S´´ÕÀ²P°JÝ'ä9ÿyPÀ [ÀŒ`1Œc€+àä÷â¼p_˜ð©g;¼£ÇGÀ‹õ â=IKïbß¾‡)Ý»úá~å¿øìù}¬åccÔiô¾ÏÚÎéË@Z«“}6úñøÛߨ”7ì…uÃl¾ª„åyýÉ쀨ýð˜Ö1ÏU†A4.à8éPEØHk#’DÕ~EHŽm–y²P™®00ðŒFzâpëR¸ki– ¬c¹a„’]¾YÊË£H€¦?aöÊ L+LâÂ!Kt;P_±ä)‰Y<,¢/¢˜Àpz2­Ý¤P@v±=Æa@uhÚ¦@D{ÕI°#ò$î'÷*WbúáëÐHÀS y+¸š‹KÕX†»;VÝ™,ÿ–Ý5yàÈ_ ]Nè§íµ©Ðc+O­ Dﺔ£ÛlÞ4´fìôPº˜³â½–1drœ \©Á†¢&nìòÂ2h7VlÒhØþ$ådð©YÀhòwìU÷ôêlf¶c®ø_™*ÿm‹Ø S¡Æ”ë>‚6÷@D\!~Þ7B[^ƒ=÷0¯-p»ñK-3Z…ÅFd w·ƒŽñ˸c€¦4Ùz€UB@’äÁ€ì†K´‰\@P ÓQYvˆÐ˪k¯Æ €˜ƒ©ÛˆvÆÝÕL®$ZÁÈ[Äì ÂáßQPÃÂRV"Ò‚/¿TRé3Û5׊áuæÊä"­W Eï„lì/”œLÁÁ1u{@F bäÖê=æ]ïá  ýs–P”x]„à aáÍÈ,[IvÿG‰;ç´›cCƒŽšÑõ)É@Q#Ó5¤ÁE3Ê´”c ÝxO}ùe¸ÃÛ[¬µ‘‡;xøäl‚½¯ºw¿cþ|`H{.#8š™»~ÒÈòy»Ö(¿!ÙiÖ; þ-pòèÜ×üÙlèª$ ’­$Pèn‰Ý>(¼«N^Õa …;|d] ?Ç6=×ÜßÏ­¹ïÏö’Güm[õßZ몂¤‹ˆR}AþƒMBú„&v¨K{ ³õÏ÷±Hé µW$äi€7iåÙiG†Ïšý¦ð5+\Þpôšú, ‡éÎ@?é_”öe*Œz1Ÿ“\½ŒB€Ü}z½Øw/.m¶všîŽ^Qê¢Q (À>ó\°ÜA\PW˜‚¼¾Eó‚ X²¬+%Q!пø€ˆ·[ ¬D¬I@U,UbŠ¢ÅQEPUX ¨Åb¬QEX1‘EFEUUбUb¨ ŒUˆÅбV)EŠ «EHª )Y"ªªªÈ("E‚łȌ‹  ²,@UQV,D’@„‘U,UbŠ¢ÅQEPUX ¨Åb¬QEX1‘EFEUUбUb¨ ŒUŠ,UбHˆª,UXª,‘TR(²EUUUPDŠ ‹‘(,AdX*€ª¤’20ˆ<¬þbß+  pwWäå›"²8z%ÞIÙž­ªg=#*"'‡3œÅ÷ñy’#ž‹·{‚¥„AxÓïÑæœœÊÙ`s¶°†2mѽÉÚµ–XKl {÷NXb¾áœ}øÝq2Ñs¼oηr>æ3Õž8ÉŽWëm°˜LRs_$­iYãÚ}j~¶7ðº–ë¯~ÕϘ ¯@"AV ®byvPWŒ}‰ûC÷Gú‡É>ˆì?`~ÐýIø“Ú=£èÙŸÚ€ä þº†ðH@Ü2¾øâî}¹ôçÅ>qõçÀ>AõÕŸøçÂ>œø§ýÇÖŸ~|ƒÀð<Àð<Àð<Àð<Àð<Àð<Àð<Àð<Àð<Àð<Àð<Àð<Àð<¬$záD• %I=ôD} о{üŸ‡Þàïd‚¹ì‚LP„#Q*€1ˆ¢‚RYU*ÊZ*­Š¨U,«V Å‹ˆA@RH )#Q D2 X*0AB (¤E!²-µih²‘j-[±V X•b*ÁlIl´*¡ijÑV%«RØZPªªªªª•`«”KR*ÂYQÀ‚ÒJ¡TU" ¤…QBT¢U"¡1U`¡ ¤Y(DQÆDª…©¤–X…²Ij E¢R¬¥ª«Pµ©-¡jIhª (Ò˜¤ª’ªHªYV¥²I™ J¢Ù b[ RYS,ýoƒžšJ ˜JÄj±Í}¿Øæe»ÈåšBG¤«>ªíÁEæé¥†2 U#L'Fft€ Te,%- F+$XJi%F±hÀURÉ+"„J2 ±éjÐ¢Š­ÕFŠYOz‚¶AZA\#‘Q€±ƒ¢"µe¥KX‘¶Ë0°’X’!üÖHd„dV "ª*ÅDU‹QT[bÅ:±‚Ú‚U"ÒKE¢Ôµ¬H¶$¶(¶-*­(ˆ±DUd@þÊdÂB ‚‘X@µ¤ "в!$ È B «‚+V(‚ RDú\HI2$‰õûô ¯Áº ý¤VÈ‹÷°ÌBARD!b'Dx¹_ìO¹—¿IøÓ+²¸ôÃóoüªÌK¦~ñÖ˜)+þ›¤É!Dy'üü®‡«S2oA=Ô O9Jûˆ­”uXÿ*¤ÌE‹aùª•<*‡d-óµB}„´àG<Öè•Ô ¯£Ux ¬UD=H‚¾¤\E‹I! ¯¨‚‚¹`‚²…dPV¡–@@'«AX¨¶VYQ(PV¢‚¶£¶ç(€J AXžˆ`R ÄÓž"³æ¡HQ!A$‰ÁdAVR¢ •"KHH¶B$Ťµ´‰‰%Y’ÒÛ(-H’Yb•eX*ÙJ©©!<„“)ò·„“ˆ"dOî+ôfãú,JN̈{ª~t²YI°(Ì¢¡ ®~[Û0èéË+|Æ¥Q¥vâ¹PΙïO³ÍÕ2ÜÂ9ÆŽQ$$Ò?¯<0PVÁÐþß9Ùgnˆ+\|;þ.î_vu¾s‹vØ>~>Ãçéí°QXº%5~OwWßñ¥¬6sr¢Åxv¿ñl‚*Ž‚ïQ* Czp˜W·•EÑœçÙ¹®¾•hƒö½6Ϊó%Vñ<ÔI!cà …ÐB².!`û{ A©U?¦iUÕ €Ôc:LôÈà zÒ †bœ@#†ÂÅv}.¶^_Äî‡é])û sãD/OO{’»§¿¯Ž‚óù#ã÷‡JÞƒÅuâ¾>~|{ýÁô<ëüà„wÍ>ãKû3ñ3ã³æôªÞ¡Ó·C]g<ÿÕè8ù Êì7ñZéC«¼3ÄíüŠ-Ïù/*üvÝ4`îQˆÕ@€:ŒÏB펊ÑÃü¤SuÁ\øX£=m•™ÓõÑ;~u¢_(넯wß ¯~‚´ 2‚°ˆ‹BG³AX( ÑAX¨Îº â‚´öüÐÉlik¯ë‡±€,*, €  EþšA/„vh4Eaœ@(/›[ˆ¬A]±Eëà„fbK…TRã iQab„U Â)"ÈŠ€(RDT„H‚ H¤  ¢Š*ÄH€±UŒbI|êa$ŠDˆ+°EpBI`I#“y£G¦M–°À‘‚‰tÁ|Ê î†uHu!$Ô$$DEUDUUDUUUDUUUUDUUUUUTEUUUUUUUUDUUUUUcUUUUUUUUUUUUUUUUUŒUUUUUUUUUV UUUUQUQUUUUUUQUUUQQTUUUUUUUUUUUUQUXÅUUUUUUT‘„$UUUUUTUUUddVFEUUUUUUTFFEUTEUTEUUUUUUUUUUUUcXÅDUUV1UUUUUUUUUUUUUUUUUUUUUUUUQUUUUUUU!$`IF‘$ ¢$! ƒà®@² ÐŒBII!)dë6bNP‘ÊûÐW $$$’Ä.U $ýÏÒöÜ~cú}P»ˆC¶Ä"Ø'WnTI™Y±3 V™¤tù¤Ö ”aàŠ‚œ®IP³‰9JWÐâ' ‚™îêÑrdÃ=¯R,  (H°&®Y$ È‚A'¼)X±$„P§L‚/­÷¹"šQ숙‹ ÍX@ÖjèÔ’3YT0µÂ‘­´¬ÆIˆªš8Ô0Ü’kZ“I.Ê!yf˜v¥Rr²å ŠšK–hk®p$—b³I°‘þëý~4ü€À™¡aÇ”H{‘~G:j5ÏM-!$!4²ÀRw!|8¦w¡/žŽq59vÄUy0üHL:DXÀda# òj Ì´P¥ûN,虑ǫ¡öÖD‘¬V£$f`I(ÆJ$„™HIæ'¨XSŒ$›¢IñÕNÕU[UmR¨ˆªª#cUQUF0QcˆˆÅDD`ƒDc$’DDAUI "Å¡"*K%ªª¶ªÚª¨ˆªª#cUQUF0QcˆˆÅQ‚ ‰$’"" ªHIhE2X09ÙU bU P d–Š"ªª""ªŠ¨ªª¢*ª¢"*ªªª¢*"ª¢*ªŠªŠˆˆÄETEDDUUDF**ª#Šª1UUQQˆªªªªªªˆªˆˆ‚ ªˆª¢(Æ1UDQUUÄV1Šª¨Šª±Šªªªª"Šˆ¨Šª¨ŠÄQEETEUQQUUF"ª¬b±Šª¬ªªªª¢*ª«#"ªªªª¢*ªªªªªªª±Uˆ"ªªŠ QXÅUUUUUTb*¨ŠÆ"*ª¨Šª«DTUUUXH>Hˆ‚7PWÚ´ª9"®tEßI$ë ým¶ U)J”¢¢•%J•VBŠ¥%U(T©R¤U)RJ²QD@HÄUˆÄa"1€‰ *Š•JŠJ%IPª«iR¥«TЍªªŠªR•K"ªª©Vieª‹DV*ÁŠ#A$@H…‘T«BªªRÉ*ÊYV%*R”U„«$«EUdª‹m"…Z¶U¥$I’Á…C0ªª*Id«aRª¥RªU([$[ UIm"ÅZ±QjÔ¢ªETT¢©*’•J*Õ•J¨ªT*¤U-Z’ª*•R¬ªER¬”´ª”©*ªª”T¥*R[lªU­J¨« 2j ÊBN„ìR¨"‚±K«©$&‚;ŽªàÁŠ@UŒ‚ªP`ë8¶bF%Š ’¢E‰Id–"(á1!a% RA%$„ÞJS$Ü$MÀŠ úQìG@jD](‹Î¥›cÁ::&Ec.òúŒ?öºÕ°<·y)¨Ï ®ùg,ç0h4‡¤‹ ,ð±˜ý$Làxê`i3fÛ6c„8bÛmz§}±üÑÉÓ!ßw¹‚õ­V:j˜D^®wgW öœÊ8Øs‚,LGØ­.K"µnøϺêÞJ}k7<œ’ÕB…Ô³r+ub„¸šê"e€´Ñ"„`…ßú”.¯Úó¡_m³ÁøØÎ'IGrO/P;@ Q é9í%ù²§ñç{ëÈ/*„^gÈMõªOÂ'à™‰âbw?×û}ç™Ûêü×oÃÛêù}ãAí|*Ü|QT~" Ä" Æ ¬Uˆ+‚±ÏÀŠHÈžøàÚ÷¿D!^ÌB@ÕÂBh¡’~ëûÎEŒÑG‰þTQtÞûÀ‚†!ÖTìÐV*Ž ¬Q·Âàö9øÂªˆAP"¢*A> ø.À(¨lTQЧÉ9ÐWö;_i`CñüaÓ †j]LOñscûQA]¥~•AZ}'6ºßkë½%ÈJ0Ë£P°ßÏÀxb€*X ò{“á‹Zl„âò^|ÇSyôÝë%ÜCwe¬õy ­–£kª×HbSo¼~RFÓúe„ ä€a2ÀP  ‚ €‰ ü_Lø¦FbÎ=í®KÜóÜößíð0;I´m~!ëh»¢nPý2ž±N,PWÖgäròM@‚‚¸ ÙI!ìŽgݘ ®(+ QNØMÅýËúó( ¯¢&C„‚A‘PDˆ‚ dŠÒª¥%X‰mŠIVÛIT‘y"‚{ÏÒKü-U¬ #?êÚüç;ˆž2Rz 掄ènö#gæZ¿ïx.D1¿"¥u–§ fRMeR‘Äáìù‡Y6ŠUcèìsh‘˜}φÕÕ>f¾5å´€B˜H[ @¼ŸQ ¹g n†3#neÆŸÄ=åŒØn‚¿Ëó‚¢/²‚¨} xÙ·˜ >p@T^oÞ‹éD=. ¨§Üõý¿8ûÜ2’>¹ˆI> ~Ëø›ò‚'ʤ¤¥#¤‰ c²‚gTE=çÏ׭Ъ:VÜ=…ŠÔx>ˆKì”´=DTõ©égzÀÿ€µVþûÕžÈÀÁŒBGi`àõ¹¾} k0t¿@å,]„‡°N¡þ‹ ¯ùV*+ب+í¡ÓûôRŠÚ´è5¢ä¥î(¾Ú4=³‡»*¬ŒüŠ!Nó„ïÆZþt“Rœÿš4V^Ç:î3­@ Gï!ö肪ˆN—mç*à*mi;;þ‡ßþ?Êßå[‡éÚy>G‘QŠ«QX, ±QŒ‚¨±DAˆÁAX±„R *Õ‘jØ´ZR–…°UX‚¨¤"ÀFAEo·Ëî~ËÌóæ\Ûfä ®ò ‘~Q}Å‘Bª Ò‹ŠŠÁOe×þoòjŸå*èQ° ‡IQ¯f(ˆ'À溔E6fUÌ=H¨ÜCóW­þÿñ(­3*ä‚»J‰ú]‡òYwDét:‘úÎ?&'”Rtú#^“Á$;v/\ ~?å}N㑯É}Ú­ZZ[¸¸•§§y;}¯ò{M§›Ap¾êlßj¿ûüeãf@d€/ÍÏTb¢B¡2fÛ¹+|`ñÑpèN{ꟙž€Aª]RòLSïšD @|¼&ˆBp*X@TUQ¿"«Ð(€û˜~ï7ú~ŠÝéÚã#åü÷{y¥Ûôrà} ØTQÏJ£tˆ+Øî ¯¨"¾Á¥¡h)$Q b‹@R"Ò)VЀ‰ÝÏP ¯Þ*ÝhÇÖÞ|ÌGB*‚¼9Q3*¢õH+ü“Ô(ˆ¨„}7ôr^'æwE§’Šˆnoåј׸ø^»Ò÷=ŸG¡ú¥u£ð,@ÿŸ–‡¯,|®HËé@@@lNO@èÏmù”Ýcþá¢ìkT„ ±Ø´ ö±fOÏ0<¼Æï7¨—¾Ë:.OÍßzŠ¢u½áª(/€'ŒHÆH"Iµ4ì L ³š* Œ:^ß÷ñ~h_@.Hª ØËÜáóücßò2(+…üïÀ]ûÕõkj’F[ÝÙTñ!‡‰"Hª¥R–ÛQU*ªªX*’©*¢–$µ`*‘"¬@"$ˆ€ 0S2)P6ÓŒ0/Г¯ZÐïWCNõªê™\¨Aï]ßx}Oaí¶zoèÙÇÐöЉÜ(w¶ÙÙõC%#áð<ÃhTÙçú±;9ÿ›ÛËÄò¹ž‡7ÀQžØ\DEîÏ ü8ŸIþO@¨·”øxžsU¼Ò ë)v§¬ŠïÑÙÀó†=Åâ‡DІ>$N‡%V®Oܯo«A:…¤íæ®ûÏOtû,JµD³­€€9¬lsÒÅ@”*ù\¿×öéæ×Âð‰ÙSw·è|ïÈ ÁH)B*„R)ó]Î÷™"Ñö H+’ ì@1æ¨8Îîyïw8 …AQùó½éª%WZ à‚¾xð¾6_Íë3xˆ@ÿ¯íþÞÿËø¾#G#>R¬O“è¹Ü/!"öB Z®É5œ÷¾ÏðþÖþoïû! öO¨‚F lÁ^X÷*8Ÿâ[‚MQÞž©™;Îýµ:**R„Rk·sì¦ q{XNت2òùÇÞ’IpÖYwÍX²Ûø?áë:/òmU_ò˜x'7ÀÀ{3B ûàñPV$A_?JƒÏˆ+ãü_²Úûĉ~ˆÚy<Õͪ„m»ßvãÛ…ÎSæéñV¾™f•ñà ÔB< ~4AX @ˆ°F,ˆ¢'r ~+ß½‹í•±@>“ûŠ?ì_uïÐIþHI4"H¨I<ÒŒ z‰Þ!) ïöŸ\›Òm¸+ñ¾¤LÈŒë{^wá‰P(¯¸ó5U{îfÇ·ð ÀºQ!ITNg¯øü¼º!ˆ@“Ý– gÌEzP¨Ò‚°*+ÞMÁ(|û à`ÖéjF tJOKˆ·äªª b,¿â*.7§/é_ T¯R|ÿ†rbíÍ ©Á.·ó˜j¾ŽÑÚ@á~‘";Ì áMIL0 `2a7¥@|[éÅè¹€;°!¦NQ«Q!"ô²ZŽ@ðÂK¼ÃÒkí:å^Õ±s0¿lÇÓ5<}C;-$Â=¿Æh‡]·º{“6f #b Õ$ ­îµO¤À:©úÊk€|¹CBfÓ ÿ„!ÜUJ —S vϼx¸ðx 7GMkÓ“±úÉ:ÇKÒ²Ëð ×yËÐOW˯‚ª1îI›@˜âv½ö&éê!òW«N¾ÿƒÿæÓ§aÙÎÂÕÜ„“Sìÿ—‰jbÀžˆ>'¯ý¿Í΂¹ôÞá¸}"¢¦A¤AZEˆ+ð‘øÀjË/ äZ„[°f¢©¼$ŸWŽêŸðÕQK€YDRðS}JDECåÔøðÿSúwÍ„5…$"HóÿÇÏ>âçÒú†}×­ñ•i_^Õü¿xjô£C€ýÇ_½îþlñ7±öBñl‚½Ãd„#Qøã‘Ÿ;îÃýŸêãò6¿v¿gÐÿF¯?àñKÅ7ñCbå¿üýÈðòPíNÅT/<9 ,1( À†ø­ß}G.Ióüß µäÙ¦Mˆ|­ø¾ÜÞ°‡ŠÿãÂ<™I'À‰" ’{íˆB|„å½ ˆ¦uQÝÖÇ‚Px4ïj¥WžA^Hà*(tLe¸øá(#™Â7eó£½Ú ¶ªJïÊý Ú4¸šŒ¬Hh±<ñ°~å¼ð€GFuü"À|ƒ±BôÑ̤bËøSzîÞÉöO•·k5;+< @¨³A_8A^ϤsSCÕÿ¾nÙ3t<ÑþÊèÄ@NñHJ¢îö¹°}Ê Ò¼†ûÛ1×£ä D΂±Ẅˆ°ÑÿÚP.ç<îÙ`v"¢µü¼“ÿ_{åù³çq 3•Çøß#ès<=Ãg6yç:0"Òwù¤~>Dù¦ÈxM…F»þ`hzø›FƒÃB8_wô7 ¿,t˜~>í_z[Ôej‚Ø­ãC&sâ¾0oK vÐNk t8ô¾Ï#0>£â}Ñ ¯+‰QÌ ¯é{-Ë©íÀ}*ØxÂ"/5öà·ED5fÃ2¢*wÍ¢ÂkDÉ€6A]]>gæ:|×wÿ_åæ—ûTÌ‚¿!ÍÛ5h>P>ËÁÀ|cØ‹q8áÁ:ýW6 õœñ§ƒÊŸœÏíöÀÝÒI:q¸¹†td0¿îñ üêf*OÚç…$ –P@üú­‡çûÚ3”àÛäûÔÕ‡hûr@óሯõx½"§ÅU)DR”óú;ä?Gá ¯3ñÝó›cáç¯OÉ<¯5öà/ºÆ~ïÚÿ*£Aæ;û ¯éÿGækçõ³Ëý_Ù}íÓм_L?ð}žãü?¶<ÞÏ•þŒ üﮓa›®B@!1}BbB¶ÆÇ­±$õùõÉ©0Ÿå À‰ €DH€@ƒïâ³#“¦ÙDû'ž^Æ”íÂýÙ²2ŽyަÙe./õûê¼GãÒÿ)Ô<ÐI$>žƒ—ž0ÿf1$×E]‘•¬örØõšž^ÓW‚Ï;?8¨ÄAÄ”1@> Þq¶Ø«cˆ„"CŒs€ cA 8ÅyJ»N©SËå_¯0úɇ‡ƒî%Û{_ nð쯥Û`âˆ@F’àêÍUVCd1ˆ„-ˆ€B2¼÷0\>ë¥ãz%a@–pîÌ­W …¬'Õx=û:†1®µ"DC1öØE’@íº5'E µU`¤EP¢1w¡hP‚¯‰ÿí„9ß4 *±DA3vYÅAQÙî½÷ȨD_ùïºWæó¨÷7OÁñï¼vT•꺱>È"—&ü{ó¼(¨aÕª÷tx‚FÄŒ‡† ¥ÿ *¤Ò¯q×2ƒ_á%ÅVs)¾;nil¯)‚†€ˆ€F%@m„7hT˴ȉtÈË4ãÏÄšþ˼€‘ å³Û¿ûýgƒÌì>®»²>çIG¢O·ÂÒ>CûTw]nÆ¿x'ôïÛBж¶…´…´…Kl*V¤–Ð-¤ Ël¨Û$ hKi%d¬ i Ô%k%´ l l’VJm„¶-²BÚIm-²­Im-²AaYm•€[`[I-²[H¶Ø¥d–ØKi%J’V)m hQ€[I-¡-°!m!m%´-¤¶Â[am¶…¶ Xkµ-¡ h[d–ÒKhVÛ%@–ز VVI-°+R[@*[J…J…¶Kl!m l’ÚжÉJ’Û$-°%¶• %¶+ Ô i-°–Ù+RI l¥k*BKl-²jI-°- Kl…JÖVIm m¶’´UJÔ*"UP‚©ŸÓæF¢H€1÷ß<rŽÔš ’ ""M"¿Áô799ßeÝÙ"÷Œ×´)$¯þLÂIä™Ö}+釯ìT·é¿ÑG¬ï—+ÞiQEEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE ¿®$gýÔþ;·°œ¿ öï†ù…Û¦\¾WúlLÔPûWsî—‡Áp¨r~&Ûyt ÁDOÖØ…<ý‹Þ‡Mã¿Ç‚ç °™Yó"KÝgsß4nó¨P9e„ãK ìÀE÷K@¯$툭Ȣ¢/sFCŠžKîÿ*êw®båØèت$D¡b )E0‚¾ÑTv¥,ª>J  ‚ǪED;åEN˜ ¤E0AX(¢ * U` ’>Ì8D‘RÁîCaxIÀÌ‘K/æï´Ùn‚¶WiDSP‚¨Š™°EPLQVª‘ÝIÞˆ¿ãÀÀÛÜÖÈ+úÚ>×õ¸(+à“û/õ4?4þ»üOÏJROVÇ÷VŠ6+Z‹*¶[l´[h¥–ú\qJÐIHS÷yEUÃê\™m¶ª[Ý÷óÓþOñâóü§¢5A^Ì@(+§t.ZÅ ®Óê ƒTre6… Ĩ .äì‡'(šˆÝT&‰nÔÿ‡#¯&µç߃Д€Ùáéð¹Ìé ÷åXV'lÌ ÃÊ €UµEP‚ôü.@G"„äþæ‡àçÑwÿ`yH+½¨z>ÓÊM¡ÉP0¤øCèMÍζ_^`û¯|už<Åñ¹Õûüв"_Ö–AZ Ä@@nFœah<¾üâéCôÞ\Â/ͺÛw¨ÒgkëÜÔ9“gÅn©Q}ÙÀ–U÷¾¡Å5í4Èó |çF½Ñp+ýq_¸øû®‚ÊôwÏb˜€ô+I Ø‚>|A¸±#=0( $‘Š’væQƒšr‡5>½álø.ù!f0R­+l¢¼°°Y6å´™[NÏÏѵpï*¿ià Æ¥7‹7±„(§òÀÝ1Ý5„ ERÆ÷³åªC “•éÀ±Qˆ‘`…¸ž/¿šàÇ/5½ì:œ_mÚ —­Æeï~aÇ•Gîsnä6Ú<}â`ªáŸ¶p±LgÃHõe}M!+ ÄÜ@c&Ò¡jU¸ô¨‘ “ö@¡ñ`õÐOüD¿6&|?+é½¥ÌÓó¿±í8ÔÀËåB&ì9 @yƒóWM¦JêpÌ–ÌûíÉnœ‹„¬Eø†¾†CùŸXïއǩƒJÛ:øT/´ÕXD! (Š¶æµ³†Œ†B„ºkF–žG¥h@”Ϊ›ã%wœàÆ“Än=‰%ÿ7ç~ßÛ×ðk15Ñ@z¿¿öè;Õ ±¤ËˆÐ`V¹`€H®¹|Ûd}C·KØ›G䔽Ý$ lúˆ¯¼®EÓZC!Ù˜lR‚_Ä2@ý[&¬·†8‚oô+å þ÷žÿ–Çe³6ÉöÕøþé>7ñK?…V•_v@ŽYÓ”y ·öV bÊ•(«ü‡ÃÙ_ê¬Ïï8ß“=ð-Y|8ó^Õ>Ë7½æŸY†_—ˆã£ïGìÿ{^Ãña¼¼OAA@{èñ{ÔðíèÇö¾šÿ¼”ÿ)µ£zƒÛ ÕГÐm½‚mã)<ýúcÕ5,z…N sÑç?o6n¸ìn†óCT¦ä9°O¦çínÎ×Oi>Xë)/éÜäeC8jJ¢¹ÚÒj•*°Q´Dß…ü¹âïw»ð‹:Ý[»[¨î…_i›&@{ûëo›p‘hÈ>ûh5ô)ØÙ0ü‘RIÓFþãOÂP×—w#qbUv¿ûù{møãôöhM>${~ˆ¸„fa{"ð5ýNJ©Çqi@Œg"˜%B`M‘ŠŸð>µúë4âÇ©ùU.xsîH!Ã{Ñ„SçÉØ:33¤,^EMC¨DÖfbLã§už@T½ä]ì0Þî÷v6ÕbR’”j·5½Õ)Gfˆž«QÆÚ>–¾úµÿ;ÇË·¼-£3sS^W2H×ܘ‰ºÈæß5:}QkŠóŠ––NdUD&•âd$¡¥<'™²o7œÛãòyÎs•Î<3ÂAÇäs“6å›­%Üñã²—Ë< šÖ­¹§!©¤Siƒˆâsš%UÕ³sìüõ}g†ÌÉf†ýæ¬PÆ Ê…Bô, ç¨oÓlôÓ&eéi¶¾»ŸÂ6(#ó6jˆý1Z±#‚ûþŸ@/°5oþ·éx.ùÉû¶í;B–0 bDõÆÑØí ÿ§˜Ôïüÿ~òûLÖCËåqœ”;XÔBKF~d‚:³8ˆc®F8Öü¢Ï5§·à¾ï¿Ý»Šè£ÝLçå]­š™®Ѐ˜²Îãh/B¡j/…e…1”x |ßÓý¾Ñó¿ë÷´:u‚˜þWPÞ „(àEñ%ŒH—I TPÜ€’Cf# € Ú§ÙîwÉÑžû£|M÷–;טÌ6y›ÔµsO(V3œÄhóÍ5gÜ:è%x <µD~ÖiûWÚ|#?¹`ùÿöiáŸsŽ=ÅáõØ|'æŠ4q z:}èjÇ ]₆CüXÈÙG¶T‚Ožà£Ý}Ö4vý„“¯"­”|fd$˜&}>ö´l?;†Pvn€Pür’{?@þ¶Lb¨±TP<)TQˆ)-* ÁD#H–UZ[-‹bÙik#ÊQ>î¾ùg‚¾?ã= »¹!-ãy¦sÔRuŽ—!Ã>Œë´ã»ÄaŠŒPŠ·Nýÿ.‘ášO²ýoØ?í o•AY; Å”Ûü‰ÚØíäD° ®ãMôž^š>^D &$™ó 8²d½!¤=AÃ!æþÓÿ  ²š_ÄS, œ#Ž|e]fÑ®ÛvR½i~X%YU°XÂÕ†xC;¥ Α¾Îô¾“;&3Óµ¹ìÛ|ÌFqÓL*g¶½ë–Ÿl}“Õ¥kaG‹†´WL¡sVYÍÝ6Ãl«-‹k]E‚U‘•ZåŒ!-¸å„3ºPª«ÒažzJT†3¥i(¶C^:iéa…Æå× ®Vié­…Ö²±XìÙ ’Q+Zí¬±µ3®v”vgyÒÕ˜€9ï®p¹)Œ2‰“–ÊXRp™ …Óc–ÜÄÃŒ4Ý\Ñ ÕF$,$'t1…¤æ1ºªé۠ʰÎv¢×ÎüpÌEDæ¹^÷ã§ 1ª=/g¨fc¸Ó§{YS”AÝDÝjïØtŒÜ&m£bÝѶAýóÆ!Ê.:!ŸB®bèhíoƒfîÏ*¤# ,êSbä ® Åpì6Ì„“CcXçéͽ?hårǾØA÷YTf|¬X÷­Šg[]µÔò#Ýd‹p“¤£²åyºqªY¬®Tõ](Ö@¥Ö†÷ 4¹tÚ¢°›ëÇæ÷¹é0£³¸Ù…WX]áØ6ê}§>¹ZŠç/ÌoµÕÐdˆó€dË$¨.;(DJq"3(@Z ‘ˆ ¸íÆR$B„´#†! »DÊ…¬kÅS(}‰#Tª7î­+*…1Ù† ";Í …¿YÖá·ÅÝíÒ'H1sÿÞ=N±Åò»€ b®ø0$øjñ4æ¶–7]331†ŸI×?«µž®Èˆ^{X^x/ñ4û’ÍÀ„[0{È&ˆ$ÖzëÄÿš‚°Ù®Æ*áŒ@¶1„—,`–Fsa¦}Ù¬! øõœ…½ß™ÙÏÀ1(üóÜøõjL8IE´'èqáS§»6KP($‹êµ?Éo»²—O‡ñ{›üâð™¢÷åS– ^F¹ñý/ÒÿÚ|ûï÷ùžÄeuë1A^wÀÈ)?އ+ñÿrw×0=‘½“Ô=¸v{s|ÇþZYA\"‚½H(+õN¶c…¶8 Ú ¢žËÇÙÕLŒJ:~½_§‡%É•T}^z±PVQ€a4]Ê!pHx«tzš<Ê‚ºÎ# |⿪vŽ|Íöúp‰RŽ)`²PI(-T°0}D$úÎñÕ`6+íT¥6ãLe‘ —!À‡Í^ÍÀúÎ*Í"&îë'Rc€ü±-Šœ½ý¯¿*ì$dÑõå·„Aåï(¢6Nþò• 1cF0Ÿ00=rs®mU$ˆp¸—M#0Ò\²ðˆ+AÒ qØ„ƒóözu³Ø(ÃØæÒBÀu’éƒc„„Ä-‡ÆìåGªßÕóW¼÷ÌmHA²¶[ dUÑ$*@jÐWµ>{ѶÆ/¶|ŽUÞukÈ hì{ëâfÒØ} eS¯»–óÒñYÂ{Pä‰ê–ÇHIÉDä’–Î0’IM“\ŒÖ¹K S Ý[&¥åI~]ÕØò׫„ŒÓEKP9$™5Ï!`;L¤è.ˆ±Ù#ˆk)eMgÄeB4 ”<3)1JT¼Ê™šç½3FöäÓg9) %¹ËRkRÀVª÷£: Ľïm04=é\ñP‡ŒAGTå£\©Kg(M†žGIHSˆÞáZp8*/+¶º6**¨‹ÀšDE‚†vk%¬þUŽ™ÚŒ km†šÒÑ áæS0Ãɲ2u ç‡Ê"PG‘>R¿½ªC¸ŒŠ±Ga¿µbxÕ÷•”—üET(WhÞwS9!®·(A³z4˜^ý»ÏrBkËkçÙ†l®¬Ñ­ŒQS\“lLXd[xNI´ÓÝkNŠµÑ¶òXüØdbMqÕs‹:Ù–ÕI‚i,fàI’N 'à8;O™‰´_\‡5„!Φ£ù‚<è¦eçX€jî€Áö¯„vj‚òn_†3Ð\„g@LºÇÕJÀyáu®\I =ls˜:̓¢§$©Jà’k •»÷òuîîâ|ßË„}­ØÎ¹+Z0PÔÁå±KÀë?ê‚°ò!ÍåiÎG…‚òÁ3cIf9BÆ•qÔ#©Hì9ä Š¨ *Å#,A’)'ÊGjj[ + ¯â#ƺÉ=•ÄIwdiUC l5?(ѰÞÚMƒœ(*[w2BhèQnmPÂF§·¾Ê(Íf"ƒP+R¡#HÈ0ƒÛÂnä¼É K(eK•{6Þq !º¶ÜæðS%*-ñX  ¹Ø-Rv‚µ¨ëšópîE”õßwÝëÜ‚©Øx4X`¦S0RŽ&ŒŸ,·®LŽ(m˜ˆ‘ÍxžðŸñ‰ê´‚|^ë/†«ž­÷ `Î-Ö{µ¹ò†‹(“Y‘$f¨¢ävfž †œÊí†ÆË~3nÀß?":¥&ØÙRönPØES ú辑ºÈûñ1Žyª=PÑ$:s x&b‡pÒk0®kt¶ŠnónHJ‹æ‹ mxã:êñ«æéTQYyË3†AaY®Ê²*©[¬ hĦ½]yýˆú BHª±EPPQE! v¬ e¤[Ô,Ë×byyNoJ’Š©t•¿±g)æ+ËSIÜrÀsWd™WŽÌ]Î&…Z…ÏsŸ¨üæÑÈàkv¬dÈ ×N”“-t˪݈ÉP1¤ëµ…cÍ.'.wCH·±}–»W“êë3äôáU¶²Øê,AujX5M¼»/µ'i°70é¸îQK˜ƒ„AÉѤP L@€¼ðb * Ž9P’© BñŸ!ƒ{wtˆçôä¬Ö§›_ïÀñäÑë|ÿÞƒ¿6Уµ±¡=㡱T|‘ø˜|¹ÌÔQW(¨ûïqgV~{h)‰Sr ²È ´EKAÁj\<ÿÍ€¯Ì€(Àùðäô{›‡ùòÛ6/¼ÛðÙóüZ!¤® ûŸæP3uÇz„¥ªDÏc{òiîÿ¬¯d êÚ’T ‘ÓˆŒˆ)ç¨ OÓ:ªªª®%ì I<<~oë õÏTÎzž8U}Šª¬}xg¦h¤l”(ÎÄýäËPÕ†þ¢Ö9 Õ@°~l?’Óàýž½y³–äÅTU‘$–Ò¥¶‹{ÂÅHBˆ•,¢¼_½)$’f뜫ö‡ns÷І[:$UTT©mµUþö@’!òúªÁTÒÛ Ÿa~™?î@‘"ÉŸeZ¼g`4Ò\Ißœ§;Š;¡¬ÅsØÜëJ,`œÊÂwÓÂ@° ¯K¥Õ×ÊæÀÁÓ§l EY´È´"¿ï¢ýj¯GN0'h€'‘M„B8 X®äÛ,§ ÞŽ@úáýö× 9M ÏìýçÖ›Þ_+H¬Å••qÁ¥¹+§­}PÊ´®‰{ÈÌ `I ëý¶éc10˜”ˆbi²¨h)+AlˆŸ¹@¢,).î[M‰Oë?¾Þ¤ ìñü}3HÆ‚Êk„Û,ytP"²}.»Ù¥m^Õâê·2Õáû5ˆüÕQbªCFÖÍÛ„Ü•mÿP ¯¢ÜÉÉ3-½ÌYÙ  Þ3‹98Ì?GâžÀ©UO¿žÅ}܉ÅVÛ,µa>äêuzÈÕ«2E‚ŠKÀ‘BÐ_Gj}²n{AÝ”Ž|î*¤ã~œŸœþzUå'8OƃÑ7vS ¥ø:H䩪5¥QXÅm `ÀiaFVÝZ¶ÔQQ„c&j‘±Ó©%ÎYÁc²Ä¸Aÿ¼eÀóÞ]SÆ7‹&tÊ ã ­Ù}¢Úš[QfZHKâèÍ\ȳ¯±gbÌ÷>gn«ÅU¬6ÀĬáÓ‰Kz%fÈ2Œ5õ[÷GKžA]´f‰·½+z1fÈÞ Ê€à@Ò&35~²À·Èî”Æûá§ãèpp ÜC€,¤A^ !”î(Ý\!l5 †…x¥ˆû«ÈÖXÜËTâÒF`Ò¡À‘‘UE´„$”)k$ ,*´-Qc°®´ˆ‹í‡hó ´\9”U‡³£t!»¤ÎGX6ÞØâœ·Y§m\ +¼‰ÅqÆ mêh-–sÊt^€„Í+Sn‹&%bû¸=¡5½Ò˜•¬X,Š„R*‚¬PbJ¨¡E’I´(+Ä ®Ós88 D7¢aèÍÌmì£6ŠÈ®ÛD5Ù5ÇTÚ‘›seÖ»j]Ú$œ€$&z=–Š*Å´Éåû1€Èˆ¦ŸwM¤èW~&¸ËE¡*Š¡$ë»k'~jõ’`›YÊCD3á­ØûÊO–™1¨#&%Hg¡•?ºãBÍ~»Jf•2úï\[CÏD¤Q¶úk8a§ÎÙèh{¿rhÓÖÚqšÉ s ÈþÊNô(ÏŠôÚ«:§ M³‡€3†lDI¤;ýÅ)û¾Ëd˜“"¤hC¾3š{ǽHq©šå‚v›ÖA¬E)E§ÓdÁ$Œ;PÒC†ç\†æuÚAXOYåÌ‹É2ÓVw'1§`nÞö ·Dì98Wò’ËÞï}o³vœç>ŒbÅáå¬h¹»M.1Æ$*°H›§Å3óªwÅÏó1ÓŸÚ–J”0æKwúä÷ñŠZаÝ'>¢,}ä¾FY<è´…–K ¯Ì ¨Áã“Pg)PØp•hÆ 4…[ìÈ~~ñ¬3Þ—pz¶ÑŸA"ÕQ"YÞ÷%ÎEР䂱 áEžêÆ9{£’”êHI8¼»q•£Í´X@dI‘IšÎË““ÄnŽ6³GnSL}Ö‡¯ÇŸ3Y¶¬DÜ #Û »ëH+– dÛs,Ác&‹9ëÍ×™(+è¶ý~;ank´j€#Qƒ=(-/@@ÀMÀ¨‚`"%B*¾¾F•þW ³RüëÔÁUXÆïyIk¬Žß³ï?«æ¤N–J"R^écgr>­%I0‘ùŸÜSé)‡îœoP䯸p~éˆGrÿ~ﲚ6MNï‚›;Ãôþç÷~—îþähô؇Àþž¸c¯î¥ ­i¨*¢>= ø‰Þ¶­5xˆ ÛsÃSª<¸ïÔO+º§SçUu¯Uѵ⟛/ "“B‰t½ LI2Z7ƒÅ|ÆLC½®Ü”÷²b£§;¿;íâ2Šïf|xˆîsŽxÇ7 Gá•x-×ÝkY¬£ºÞèp÷ØVúa™6öõ2ûÕ 8+=0ã83¶¶8=wÒ:“¿y+œ 63Ë8îÐ=/ñÝ>–;°•+¦v*psÍAMwxk5½wS!žŠ ŒðE"Ž˜UîkHgkçžwˆ¹M Â<¤¹QÃJ¤øíÕNDL¨Lµñ¥ÍD&d…ÂüÛšÉ׿®µz·½%I ëåߣ¤S¬ ‰D&âtzD[¶¡ø¶¤<*Ü[mé åhž&7ÙºÕw÷èuáéÈ—â]ž[Þ†yÌ*¡rlýaXŲ¤$ÅÛ,' ±˜›¯P2Æçpƒ)(. 2IJÚÂÈá&Ê*ʂ뭄î`máyN˜O:ö»aã–9;ü,׊p³3¤¼Òv‡ÍöñÞË037DÆÍõqsàó2“o1ûK§]\g™àŠ—õé±qc¸Øì–ؼ¤ˆéÌF!ƒ¦ÏMÓ±8þ‘‰“"„™4¥|S ©tßšiž ³Iã ‹@ŠŒÞì™)@ç…æe;Öv»y“Â'€¬‡DÓ:½E£0*hdêt®X¯N\¹7"”ÀU#ye+at0²Ò2D‘D 8"&ÏHt©r‰ª‚ã…wÎT„ ÙxGŽêÙÇöw”Õ9UY}C@»wªq¯ÈíÚ#Á''¯W1X7…½äV ½%á‡éÇg5ÙºG–LþÑ ogQ¨˜„x˪;¾Œ07€½>¯ñð¾ìÒ{°“Ř]§"YUWèE«HFzë&⯭ġÝß«`fm¤ IÄî;;¤øëôÌ7òpeœÎKNç”O--øqMó5ÔkdB(ƒï?\ÿv>ÅŸ„O¥ôí‹>ÿãþ#ZQÇ0£ut×ÊW<#´ÞPÔŒ$Å”†‹Ûæó>033ì/;> ‚)?KÌù:1Kñ @ÈÑÏ¥]òÓÞ,U¼á$áâ×,.ÑÆŸæ½dÂf™ÈûlÆ”ÈëqZç¾#§Ž—8•óº2ƒ”mI²Ê .@,˜2Ê7@Á`T [ éÆÚ[V ,. –6›’É«!lÉU‚+%òî~9|”üƒÐô¶Ú}ë;½Jr-K3c…DÖ-û‚>i¾±ŸÇÕë›Ý=h÷µòÔÍc§%mAEU³.M"DE‚ÔH¤–.ѹì:9Mõ:ލU[2ý–O3¡ÛLºZ€Ð|ɱx9¬ÎÝÿ&:Çi˜‘ÉÐY\£}±ƒÒëÓ$X@øÅÔ¿ÑêŽÕÍÁ6 WYT™æÌëÆáŒZh‘Ñ0ôl5‡šg]üÞíêWÃñRq*W #.(È )‚¤R2H ,©µ†)OC®;²’Y5u4FZâEŠá‚Ÿ0>4GŽHh ƈ£øD±„ Hˆù½fPp“DxÈâg ÂÄë&½¹H‘9²«YèIæ€öžx‹º·òúè={ñIˆh—-yh*Ñ»ªÂçú@tKŒßFÎèOö  ˆFÂq Ïå;EC~.zùðµž,D#ˆœ©XšÂ÷óÐS«Ã…0ˆ[`‘V!JY?šóEÙJva™°[;扟5ôц/sØ Gš€nJkBã\bKP, d¢ ™Éâ+ÝÂId0ÌÉg&»}l¿®^ËJVìÐ4 Ä’;õÄÕ²úò΀ðÑçÔõ!äk¶å<¾å‡S¨çÉÏ>:UB:×y)?™ÅdãÄ;0@Ç’#,¹ë'.ŽÎ¬Ýâe¾†óݬ¢‰T\èrµaJEJZ*Ò@d3ÇUCÖ¼Ä³ÒX|HÇAkÚî*roEUW¥ìæW¼† ü—ïV¬¥°9Zˆ2 ݼSj¤¤!¾‚¸ò‘Pù Š‚»ß£|˜0 éÐáÁÑÆF@v :´X±vDÎÎ~ØYÓÃà&F}wD°8¨íÞX]ÈyF÷/ý¶ã H+…·oz½6m¸^è+3„Á± —*¬«)'J,”¶8ÄaC¬9=MÛÑNìÌ2á¯c•ä Ŷ \ÀÃ8k’+½4 Í ŒëdÊb’1¶´XKS9]ÏVŽváx ÖIë °±¤äÎè&êœé¦ÎêœÕvi”@ij2 Ël "’ÈT!C˜8Y¨†w~‡‚¶À³C|?¸›`Ò!”^KRSØÞÔ!#HXÁåØvع’wÀ’yÏÏß@Ë‹‡E¸)­®¨+fÒØa¾©d(Æ7sWɓݒâ–zerC :CƒA{@§˜òˆˆ€/+›”ÝÁ•Þ{} ÂR 9€µm€dˆ1&\u=ª“^{2>ÓטÆÓì·Rwפ9hu‘M펼ëö¦<®¹íx$!߯ô«ÔM55&t³§òˆèoaW ÃDýùéž{¢a¯¥ÞÒGJq¼Æ+Mì•?’©*â‡O3o€¤¾ãÁËšYĉ5¿ íè.Ø}AjD˜:ÞàÎbY¨.” PE,‘dijPX 0Ftm¥EÊ®"˜¨W]Ú¸ÐÞ(…îx^é|*¡Ñ*ö"^NY,˜žÌò1!$°é5BrRg:—ý6Eæ2k–d“z›7¶»ªOÌŠnÓöoã ÓŒ’’Äà”Cc°ZoM$’Ñ´Æ(Y±ajUHÝdHsQ6Îp¯Jžkȉc1k4 ºÝ ¼§¬ÔFD!H+gSµéGºæEà]çùûu™˜R!ä|÷cº[=ªI>`ôüŽDgc©¯¯Áº–Å_›_=&FîÃÑà˜,T²›‡• Õ¤¤1B+„£›*Øn‡Q£žÀ07—•$T–6^$›–ÀâK«ZÓsAB ©4ó‘N·4rÂF¾Œ)âÍžU¾íP¹EYVä°Œ,*HH¨hT$ÇBíûl•I™›œÆ!ÛaÝŒ8’z­LÇ[æØaÆŽdYÙ1R&}8¢¤„€Et€(åÖÁ»Œ 8“1ÕÕÛ¯,¦8ÐWx0ó?¿£Š~1É>E „Ô«X(@1Ór¸–P+v-A3 ×M N€ÄtD}ÿå}çÞÿ'šÄÍ;‰ƒh”-f€çj¨Kžò´£ÙöˆI)Šlf…%D 0>ÌüžSZ$ˆÂîÃÁT9²ƒPY05a9¥d4}ÊfŸ²Àá!‘?d$•†¬nÁRDB<•R©Å1Å‚ ðÈ\A¤ÔË$P” RAI*#!XE±’²ˆÔ!PŠV¤‹  *“„­êíwqô£VTUCA§–†Ô>×õùýî~._FêÏ;â"Õ-‘»ƒU† +E4ã¥}G´Þ~Oô;ú£&çïpÉ>úòÜ:nXokµ.Ïßíc¤3{$¦M4ÒÏ«Ì8§ýÿ¬ÿFü&ÿVljhx5» ŠPVŸj‡œO¹ì<¼¼¥9Ú0×ÌCIÏ<2Ù³9‡Ýú›½>]OHÓ\  Y:„d?±9BAÍ–ÏBÛIE€v¶”ô`÷1ÚéÖÞgÏC@H²,Šèr»00íá@(FÉŸñôòƒGÒY3†¥”íÁi黯ҴäÔÖ1upÐXª}%Q#/F鱈]=È,¼4\ Ö…r~Œˆf_×O·Üm]úÌh$ìb:Ô ô¨˜‹¯XXO¦i¹™ø²» Åwt1•'/ ®Jö@ùD;B³Lj¾s^Á%ÐVb‚ôø 8Cgu3l.@)‹Pƒ ‘AXA]þx}³†×»]E9½2ÀnC•@„HÀcFŒDƒq¬Æ-vtGqŸ!˨ު5Æõì1Í©´÷)Œ¹½-÷Ý…}{U‚s²!aaPB„H€èb7 B[+¿a©×€ƒÞÄ¥ ¥Ew(Zyè-  u"• ³XÆ^÷±xZ×à_™0  – °ûÇvš„ξ»GˆÔpñúpœ&ÌŸÄgT ŒO¹H÷ì)Z©ŠJcúúOŲ7‰ÝA$]©™[Zyä¹– â§ó÷nDƒáÑ^Š( œÎQeF©m(«QªU¶‰ZÖHûŽÅ꥽L‡ç?­“é©’Æ,ZYc¶’sÂS{šd­Y>}Ö']I¢xÞšCÏÆˆI·* Ï´ø}ï³èP|O ïWÔa‚˜¤wãf2Ýå&²Ã`¢ 0ŠEŠ? YH¨"((˜—lü7.d0@R "Aá IM¥ŒâþEµò~¥üc–'ÛI(A'å¸cáòyˆ_ÌñÝ~‹dµÀ\â¿ίºµ d%vìøçÆ!¿ ”RšzÿÃèõÆ&àÃ3È+@}±õ¶ÂëDNöNù dÙý2MƒŽÄ—WJª¡y¤P„<NØ\¿º§‡*aR ¨üLNwˆ?UD"ÀXФ‘AA` E‘$H² ¤‹ ¤TTD ¨ ,"‹$E‚ÅX,€°9!UÆ ‚‚£‹E‚*Œ ¤D‚É ²‹‚‚$ŠHªE‹AT6b싇~\5ùsEw6ób*©™ýºlÊ"ÁC»¥ª¢„{ÐÃ$6j®Ò4ü<îÇ$ £ìYÚñûœ é˜Aù½ÖI!<+½PNc ©sæÖèz;mB@5íÈ@b UˆŠ¨±b,H*ñaî`‰0Dì”°ðêÖm±c yci´“Z¿‚Ó °cLÊão»1Û]Ò‹ ƒr f”uí—K‚+;–£Y=!•lÜ3)Ê<ø (½at ˆD4pþ:ɨÖ®1]ž´CˆØñÒ¤þ×m¹lü›T¼G^;[K&¬§±¸‡s©¯Ppó.EõÐ<0Ï5ÌôÒØz¾§ Þ{/õM@v½ì;@ØÈ|àz‹àåŒý¶?êþ ‰µ±Öc]ѱîg­´ûÜ0"Ùÿ )Îo£†W¼Ü—û~tš†?ý¥¦,¥Ú0ÕÍòß#%:Ž}ZTáô4V¼ÜVìÿ'¬¶ç(…*!J¶B€BÂÀ˜à–ñˆ"‚(1p.`ˆ³ÚMªß 0ĺ: ´Ço=ó£öçW §RG§]³A¼úÿQýs¦OëÏT®`·/ëo°æ_ìÚÖµ+ålh|(¸; Hüc4É&˜üÁ×ñûGŠ,þZ^î;ƒ‚ÝEmúèa½·O.BƒüQ\ä~0 ¯Ð}ǜDŽÊ?4pžñ0v­CÙúÝëÿ“›Âpm“¿Ä9(a ¶N×–­-ª·õž#²Ÿò!¤fÂNõ‘ÛØÁpf}Ù?BrlH 2Èm¬“!,¤²fK€ ëzí²’X~ ÈÁ±8îqà„šXjI A~¥Š£QH>w 2ˆ¨\C €Äæ¦"+ö¸£«–¼ÇØ‘ð£9a§E sgÍ¿Îͳ_D݆WÝ>3DòÕïEœIe9hDâý>: wPɼ>Þ »U H ƒÃJ‰"æÊËB;E•lÏD}¸– AÚ(+¼:.™D'~wzü¾,l¶s3C[å>d葚6¯í¾øn÷Ç»±èž·Ðr¼º¬{¾öÀÆV ,V±´(½ªM2²Q ‹ö›º¼›‹TWeƒüûÊÿ~çïXsͺHuvʧÅvÜ0·X‰‰&(âp¼Aæ”Ë’óËD£ì¬>5NÜ0^†(+³XÆ0½³2§?L—He(¯&¢Š ¢¥¥X¨?I*ÍjÌ"* ¶ŠªªEéª4¢@ô!>cÓ àâzáíöÓäTÄ”´0@©R¡‚)`j(ª†aè´AvÎôs¦Ô¶õz»$$ª•¢VÇ[f“œL–r'Æ_«;{cÒ>óŽ–åH’R–È%‘$ÔN‘¼ibpEíÊ bè4WÝó¶TϹö`ì€n Ù5Êp´ ç4 ÇY™´ç‹ý˜p!d%e]ì×Hô !¯L‚jCÈö‚£úÁ"$¬=ƒP£S®,?ž˜_Ïg†ªVEZ³yKj4YBI#,“ý* éÊGF(à :ϯÖúEÎ:8z’<éÂÌþí ñ2¡>–ýgHt2ú-}Œ¢Db’,Ÿ:T‹ Vw'\ E÷x–æ;ù:@¼Tbã…X,° ôv¯)¡'; œ’Äzî¦i#Èvâk] bûs q"+Ú¢*ðf@.æ¢ÖãbC‘HѦ25'TE"CÕ;¸Í´hœ7§0=éÛ©oš±ÂÏ¡äå–¾£Yøv…(¢…úÔ­aNw‘K&&4’lIJ1EÁs]dLÐÔévÏgãQeC‘ Q A'ÍáH˜ c„a7‰äÉDbq—šü¡BœLåË܃™³rú«eñTf .Kj¬Ûq’fäsµö+ ¬M˜'ÌBéÚ”!Ÿ‡RšÃZ!ß ¯uÅçápö㟗˜°1qíé[Á÷œ±.¾ À>LÇd*Tªª¢€¨hÈ€{ŸWî,W8˜‘«™Ž¥Y7N¨†ÆÎèÙ+aþ. .b (HHÀü¸Èª2ÜM¦l¢uUòÖÑîî;Û-ë½âÿ¸sêôèàº@éÀ ËA’?þ?gü˜beGа /p ¬mžêXÁ£®‚±² ÁC˜ˆm `IA$S-Ž0(‚ )$ÂM01Ÿ‚…ŒŠmZŠY4‡ÛqY"²]YQ@â5#¤Ý Œ…Ü!I„û˜d4Ép’H™U«d.Ïé쪹 —½ì*·”AY¢Š• Gq¶ŸñþžMó‰ÎH‘ •û#Úã üàô鸱g ¨9Èy&z°Gq²:A_> +c f%IE2TA]¢BOîù§Tí¿ëgÈcÅŒa‰g?Ób§ÏY5EE;øŠš6sÙƒN~7 ÏÙüg\‘/<Å%B‰¾¤ 3 ­‡DoË£ü,5âUÈsV³ ®õ?"€zp×ò;/ôb/÷`Ç8?å£`}¤ž kWäÖ™Šñ'ÀßÔ±AVZX±-ªÄj±µ?…î³ðWààH~¹&{«Ì„“Óvêa0ù;/Šë7’}é€åst(ÜØ¢(­÷‹(–_NA¾·Õ`à< NÐ%Ôl -Œô›W Û›1x ýM‘7Û9“gLôµs KVªÊb_¤8ÇA5ê&ÀþfƒÛêVØ¢_¼qOª’±BŒÀü½kCBFðóºÇH`“­¼Pö(¬Ég A8鉩E!.(0 ’VBŠ1ꤢ&gÔÁ3$Dv»bó²=×Zq¨b XxB@Õ ÙßByB‚¸ÝJbÚHB.C‰¾(+ˆ›2-xÛ«VkEËBQ Œ;&á“UDü¿¯Ï¯(“ÒšK%Æ*ÓQ¼TCÒE1Ui»{)¾Lð Mã*TüOiJ’)‘²Ù!¢U{÷t;÷õ$òUЍH@ˆ¤°„…TEUEEE¨ˆªªŠŠBCà…‚xüÊ2Œ†Î$Ü,Á²Í·5•°­÷Á6H táÔPrÛ¹À7/VÖÑ*·ìÞ°˜ø´rb~öËó èiE¬*‚ *["‘`>v¤PÈ(#9LDf}hÙmç)£"Ñ Òp&šÏo1ó깆'@C—¨’÷B‰¶@Ÿá~e’ÉЖ%A>”LÆæ©Šã$ -… =öI¹©¦™"'ød͉’\B¡µdv?õ³W MM¡³-ª³«Í(ì0•£€¥w·hqÔ½W’\0ˆr@ã„)étbkc™KdÎSƒ2ÇlwXFäⳚG's&ö„ ”ÃýkYA[ hÒ!ÂpfK‹ÍÍY@Ȇµ¨t¬ ŠQK°Ã= œF9PW¦˜#Ӿ䝨ŸÏûÐüÈzƒ¶…¢Øþ4@SBˆ ,´¢X]”C€ˆn³àšõä‡We,ËûL!Ú!­t r¥Gfc~ëñÐØ˜¶—²Œ=LÁ0ÉÇq(­¥hñ›¹°&ÓFŠBr'l@Ü‚€–¼\Í÷a vÑQºVˆú»(ãìõ9Öð;·Þ[ùÊnM ¹ h+ÎUCWýòßÞb­P·SÚýµû(©Ûжž÷<´ˆMÃîÈ~›#ˆîK–So æŽAHs†~¾jl$‡÷XršÖôA,£œ¾ÍÀÕM^Hót˜r³6\Ù½Íáå˜9²ª"ÜõH@'õü¹èå^_0­D0hèeoš'ÎC ×ã—Í"Œð`ië7,Ÿ]®5+r…™OÎuD³K“Ëœ¶àBhPk ‚‹—ª±RéýÓ$¢ ùó+Â)'ý~g¡¿^Æôx|Ðtȱß³ºxè÷xöý4¦ý–ïérÒ\¦di,q¶Ž¹N@l8ü³Œ‹Ÿ9±J­Øs’©Gß@© ŸQŸ6TÙ,çã ÀDA9b‹ÈW”-·5ÁK¨+Û“y"Iºþ²Ãòhˆq«Iñ>Mfi×U Ïå€*j]æ*dè"`Õ‰­“Ô ‚ bÁDOh”5š2‚%Ä€@€bƒ¦rp T N“üÒ㽪~´8&ï\Øúc>?ê?ÝûÏÂûNPv“¯:2¥TµªZHê¢Çü|?žüþç¬è,™âõºº¬Š¹V“F&W,Â=Qsô™½œ „Ž`àY‹ LÉ/Þ°¨þɯf³Úç- º´eÎbÛªe0JšÔ*%ª„RêàM3L’Ia³6:îÔ5³x<­šjœ`dT½SV—“fÌÓ¦ 5gu+š‰˜Mâ!5ªcŒÒA‚ÍSQy)—1ƒµÝÛ¢ÜÔÌs`å€G‹dáøç‘ÖáÖCÑ@.µC˰0KÇøØ œÝ ë9Œ“š õOÒø£0šö¡,ë)i–ÖÚfb‚€Dý‹{â"‰Èô®‹œÄ7À=Wd™7(`lŽŠ«h´±îõ§vËøe€q¤‡Õ-£ÇRéNæÅY¨I"8@Ad d Ž tà—(á ʲűb[e-`H+AU½Ôn\Dh( ÞòV¢‹’¬­(2•BŠ­´¬µ(Á­8ÀÈ…A¥ŠBH°$ˆÀ’2ÆPPe#QÊ’P¬¨Ê–­£J5²°BQ *b¥•ä D²Eæ‹”ÀTºÕ£HJ E‚¶©ãk")[f…Ô2ÓAQI‚h¡‰€C¸5f…«kjFÔiV*[ «%¤EŒ„‘+) "UU²‘(‘(EI[¥´(ÞOóúÍöê(Ã]£¶@$S†*6‡¥VE›ëï­ÓîÑ€švͶ 7¨a¸ª—„ƒ £Â:™XˆY "Œ‘c"£"Œ‹"ÉUCsž‰!K¬$‚+$k TžªfUQÔÐÝšÀÌeAÅ"2ß'Üb¥ˆ4A„Ñ41€F*ò÷P+p¨:©‹ÒZ…«Rªõd|¡µ‡$*{â„Y$°Y#Þ2¤šJ†%âÀº m€³¶t2„ŸJÈ\ÌêÓ­P *°Â `óÀ)AXY PW=*¨×ºÁ@­%IÖFNH tr”ÀtiaXLHÀU€¤œvz™(OJL àdî2O-Ÿ+ÎqbWMZÑÊ®À$"X2t I9@Þ´);*ú’ò©×ºzîQÄwÙlmÉ4| ï±SE t€ TD\bYh‘’¨ŸA|©d„‰Ê,‘`ßÇãxÞìžœ–#AßÃzœöb‰ì)b€Ë¤b"¬TΠ­(+A(¥ˆê/•,`<¦.›Uùù{¾{0[imª%¥d­=óÇP$œ÷ šhcdùèµò÷f:Ô©ng-is\Ct‰«ÁaL¶•i¦| iô˜ŒC˜In3¨aìýãxÕkPÎ \¬*hœÛ)Im7ªÒê†ë8äØ5¦ˆIÚÙi˜TÛIibi-IiyQ©¬–q¥Ä ˆ¥ Ì`óßÀ£Ø‡#NÂms‚ßÿo´ïÄ8Õ‰Ãy+’ ͬû{8ÂÄ—á!Î:f*¾Ñuˆ`ò:àMˆ+:( ëšÓŒ›"ÑBÓç,Á¹ÕUQD`É„d„,À<؆ÃpCšÓ¡€1xÉ1 Zư*²È|Ñ ³ä(¸"ig”Øu$ #Ǩ-Ûè/ÇýïwÅ«o¬zùY|îÓ Ûm–a1‰ÐÁÇ`eÂ]ðþûÖtÒcêè €ÚªP„’Z‰-T[b:…ë£på*8•°°é»ÝÒ­‡Mµ'BÊ––IÝ]Ï„„0ÄPW€8T9<ݲä*£A £§ a‘‰¸vràçyâ aØf茻AGa޾⫝̸V½ÄEpp´¡²‚µO_cËÅöq2ë yaG¬Ä:û*ìCÿgÅå2ßĦF‘¥:¦­3æš´¨É>G¤XLøÇxÃ;…ç-D´¤ƒ¶Ñ½ïþ¿»Ì÷Ÿ¡õ5/‹¿{]é¡ÿ6n>N•Ñfq)L ¶ i,©Db«•Fà½ñ¡Ú·Ôd‰ðSUö2o`çýO„üÏ}X³Gk5 DDúÿ3ö0ý1û_ûkuê")ÿFº“gø»y“ÝæQòüᄚ›±E™°Õ@ÕÔØ ­(+Ë>£fàí:õÏ(Øy³…ðP‰´"±b Ázüñ’OG¤œû³ä  °y%ABªˆB¢n(È*ŠMúE z,¾–вÖİgû¨ÏÔáß—x(q˜>KÇûQäüïâÙÝÐñ}F;^‰Qéù<1$I`8:3"ä›ÔzE™GÔÎHæ9àºn˜f¢Dã*’ÔѶ‘^˃ Ú†YÔÍW²ѹ="ÇÑ0ç×f:9H4ü'?9aµ<ÃxŒŒŒ#0$B!ÜR4<.ïpÁ#ê¾6ÖHÛ1€vdØpÁSè:ÌU†‚PFÅ%K"Ìrpäç“­æl•¤%ëlå' åö„æì{o6°àâ­‰ÀB×L}Å/KÍäC–:˜‚Ž4¼PM—¥MxÂQtK$!lÀ;ùÚN É@u9³F]Üý Ä"·t鯟‡Öj"jç³-l¯NBу‰W,An|ëÍs÷Jªª§Çi9ò|Wä‘w¢¸2‘º|º”X2\6bLia‚… ¨øg:èkcóš“2ȳ¿Î|¸ Í›0;­Cš˜°ˆF÷¤T&1¢m¯p¸õ gÅjß]Ãuõû'yÎF/ u:zh¼‚S1¬­¾ "CŸÐvGŸb§h4­%®¶òå¢,ULèöA“Ê(6±¬ìçߪ@žsËI>ü=Y‚€°õ* ³ :Dì}×ÃS•6XÀd±6\'«èÓqžYDã<¾“s¹ Ch@¨06Eà Dà†]è™ó”äì8à›|`5„îNP{ü [¶°¡ÑÊEØ€V6„‘n°„u0Á7±Î¦÷L"¨1DI–"†áa³‡w¢Yé@D @xP‚@e¨È8>P¼Ûù«Æ ñ°öi÷<3vþŸ'`Áqì9]^Ò¶hÌF¨õ¯÷ظž>Iäo7’¥·’‡&-õ޼ äxe×F1Ðz—Cïî`œ‹ ¼ÞcÐífÇhñþÏ“ç>?àmŽÛºÃ>4MRÌølæ‡à?ŒÕþÎy™›J(¯Ö–ÿÖÿápUWö$j¨Š/è}Ì9ºz Xg´?RLdq6åW[)HC?lñ‡¥Ã£¬ F„1ŒbÆ0…OçãîZQL]öÐËK&íaùy6Ü|Ùf¹;› ¿öÞ‡ñ¥™ å†éíb-–¼å h*¨Æ ¤ (’1A “2F1°‘M»±øÿ9är>‹ù}Î¥T4»4:‹¿}bÌ´«…,ƳT™ (ÊZ41¨ëd‡ã~5?S[!Â1k ¡–UVŸÝ¡A?‚œ¸ÔÆ"² °DB–2Õ­«™Q DDPQ ËcʘëUÓ‰‹Y‰BI(ØÂ¢íHTIP Ödm²ÙiDh¤Y”³V¸$­GN ˆ*’**¢F‰Rm)VßÖÙ™*—X2ʥ̄’~ûZÒhQL£BˆÜÉo÷ã~`ws9ó@ìHQ!9!‚¢êP(˜Ì€¸XG÷k¿^/¿+ºÜËßDÓMz­`žŽ5¦TÓµ«Å¶œÉ““z¦+ü"ŸÊßí\ó.syL¹˜fëîˆ «œýˆ¾ªß• ~rz8ç)›¼ÜØ]ãÆˆc -*¹vÀMk2©Qiºhº$±Ò`¤…¾" k᢬Џ™pp»së>?kí25jÈЬ0ÃBëʇTóga¥0WRÜ·ÁX‡B“Æ}lõƒ2iç<:M{ŽÔnõsY¼ÖîÆ—f‹ªèÝ—0£rfg¶á†÷7í×w¨œ÷N6ãÉQaôÃÝËÄÉöپвUðˆu¹#¯p%Ü$Š­é'X,_ÇøÞy2e˜  e*ª­ê„ÏSc+APÞ&êr:¢‡äµ¯á\¥®ÔÖÏgÕ¬5w•T ¥­G¥}’ú?‹MàZyg™=P‚*æÛú½´Ûˆà&ÊB*³LÜÐ/¨™:&ÏPr#qTè!,ÔäsIòYbªšáŠÄQUEU’BBAA*ÕÜuºq1Ò{ï Ö‡°PV\EtUMeÉHÏqH ‚®ERAÔÂ02X„1,$Ÿ~¿—SLÌã3 m–ŒÌЩ…¤mÅ«BŠc)–#l¤¢ˆµ!cì’ÐÆiŹIí†5<²¼S^TœÂ‰pÀÔ4/Û¿‡ÆûäêMÈdgÐù. Š*"ª*+íþ0c?€ À’>¿a²¢C¿À܈õ'-€(ІÔXww´‰KQˆugdÌ¥NZBã²r¡ü ‡ÏV©‡Ïb±ƒÓc}Ä8ð_y 'ÙiUcäz‹Š¾ò…ÐSaê7¿… Šà[õÍäÄùÚϱ×R bÎ #|ã…döZIÜl÷œŽàúÙ{°ÚAqOŽX¬kv[ICä¦jñÏ:ûÅ(}'ƒ·}8ë¿[›·}ÝÔôplQñ„–¬EQ[¿Wö!f¶(*ª‹CUŒ`Š‚/ÍΘ¢Ù %”ˆ‹×P'¼ëMsœU€#9RŽ£T; 2sJÛRIÔ*§$àSsiÇÁà„"H!7PW&‹P±‹Žãÿβ¹Ä3"´¥»yu 0`ªâ°ÆEª¨:„Ä,Iíåô~Œ '?ªN9œr»Ö“3 2(¦fe+XÁ¥qÉ1ì@BP)=HHÏ9$’I(<ÁÌ¢¹!À*tˆ‰œJ¬^ƒ¡ÙÏÂf€ëš®løšØ1uR0£.Z´™îɰt·7 ܾ>Y¨iTú‰^kNƒfèJéˆô\­¦MKh]ôËÒ…ì|¹±ÑF0¨¥Y÷š0Ö®_©éîãw8¬óä;,Ñlœ¶®W‹i.. ¬Kƒ§” ½ \eÐë¤' ‚…Ü ­áˆq¹ÄW"3n P‚©ô'tî߆ä‡DÆ)­ª´’ !V(®µ©„CP’D!Q ¤ÓJµs ¦áØŒHÖDžh®DRLBE¶¥-KV(d¼åVMj)C "— R€ üj‹Íc} >»ös<ÙdùÛŒ€¿Tø†YŠZRFMÐ3¦"»ŠôÃq Ó’®·%þ;9¹}GF le Ðbô ëgñ¿ÏÿÒò³_leh§È`’]V÷{$˜d|më¹{Ãï1÷Èt¡wLHmfYÎ  E‹–~ Ú¥„ž·ÁDL~”Ed/ñ¸stwõÌíß§{ØTšËFT½ög;Çi]¥fíÍeþF«–Pݹ:g<ë&Àí»JSvys¹µöqÐ;fï˜~gQãRL ÃŽî9i¦'2(äj‡rßݱ2Þbž5}ÔTÙo½CU±%²iü$ƒÙq‘¾¾›g‡ŽýBMÒÎZÖ>m‰Êê9» ’‘*O´_¬Oajñdz—ÜržN«a© H´=Í)¨©ö~•iК ~s`ÊNèOõœêÄìWµJÞð:§A „“+EòT.âoI­n¾%ÁUDç^Ø1…ƒ‰v'Ç´\iBYÚ¼ê0Da—/']¹ÒñuIu˜LdìŠTÚ¢•7ÊË ZLm31ø¨#}gqqR¼Å‹ƒ´#qE;òó¯]ùÈ^u'VòÌ Í÷¶Á_Oýßwd³sNþÞˆ IaüŒˆ1Û”òl?åÏŠ"_/Þ×ô(ç@¤c²\süOú®Ò`Pª¼ùêæ<“]æõ·ãÝ1¨w=Mk~Íó7wË GTÉëm‹€p>xà¶=CÑYFVѯeŒ!ÂDS’œU?S>=Êùä¾tí`ÿXzÇk°räa™µ“õM§8¼ ¾DÿøÍ9\?ÑÕ¯„†´.DŠÒ˜K}(+ÅÝfˆp3×6:c´C­lµOÉÑ(Ù/'‡LŇ _‡…îð½9ã†[̹fZuùn /ÝË2‹„© Q ĤÞç˜õlFçTÅ0#U`IB©­šÂ (Éš¤áÚ^u¤œ¸¾.8í~‡ º1"ê ®l Pãe™¢ÊÃÂC²d8Ð|¼k‰ '0áó/Á«¬îôRqN Þf³RëZ2^ÛÖ®ÖÌÇ+–;ÞmJlÊRˆ ËtÕ©¬ÉƵ!h¶­¼ŸQQ˪“0ZŠ©ÇuêY:e“~Äa$;ÛÎÙ]>¥Zž¨yóÀQÐ:À´A—4iÖ\Î쨭Q)RÐjúÍćPq;†=(; MsJ½½œ–™iˆwÅòûª³¶¥âwÍäã‹-Ü H]7°p-S$!KÙÊ—*D¾''ÓáùžŒÁܾé<;;¿ê3‡ad;%‹_-£à9ú&$hJÕ‚Ý÷>nÃÇ9±Øl§‘¡á/irM.ã´õ#/ŶOk2'Ê©©Ñ:<ŒËûL‘@RÅ’ ( $R ¢Ñl[ ¶Il‘l‘jJ°+E‘@PŠ ,XH° E© Ka- b[$µ EŠ„X¡H¤PPYPPQd‘H,P‚ƒd–…¥¶À´‹RZKHZ€Œ€¢‘dP„YH)Z‘jI$ú"É"1`[!h´0T$ÅKH-‹dª¶À ª(² @U‚‘@‹E€(¡ (É"€²E$€¢‹"À‹X,Š,€¤‹$R`,‘H (²ER)H,  ¤ˆ‘I‚‹ojí $™<õÞ (+¤l ”^„›H+Zd U¨k/rc(CY+(Ò•‘ÖÖA óIa$±šï›éˬ¼N.CÚv¥´Xò ßMø;8öA²iœJ£&P:HŸ¯ÉêÄ@˜Tà À ®³œ:äôØ‘½"Ë*ùñlÍ-#'Ó‚¨{aJyþcù%›8äÇÕ9Y†dË„ô«[:F¤ë,“Ò¥ «5›Ù̆ q)ýn¢ ¥Ý,:‚±ÍÁ®ª)’E´¹Eb%GÄ ·àÎYgËáÍÓz™“šJžðк6 晹à—ÇN¢‚µ£·ÒqmPT$ŒCr Ž[i!%’sJ ý (Jœ¤,!4¹)¯±,ÔšaåVÚ²ízx„Óž°ÎÃkÿT‰™€Š[OTCV<"“H„XÒ’ÊÍa0ƒ­po[@: Ðã¦U7eE-¸¿A¦Ý<ÑpL˜(+M ˆÚX‹mG„n$†pªd°•P¥é³9–+œ›[s- ÛÚ©V2Àî!ås4'ÅØX¡Ó»v¨Ö#» ¯Q±¿¡X3@bÇBrg[†Ùq˜×‡=+7tƒ»Í¸^­j‰ ʧûAm ’I* ¿BŠ=þÿÏàêÀ9d]NªyžÐ¢åèjB *öÖ‰p+Ô¡Þ¾”Šox¹ñeßÂu̺·Ã¿Ô‰Ã:W¶ª‡9EÂôd ¤6’}iý®dSè°X@ Ä Ä#°@A*Õʾó>6æ»Gnñ®,Ó§¥ìâî¿ãœ«"χGzOˆõùCW±{š0H—!I(=I¾r„)ö½æOüŸõ¿›ÿ"ÙNSLTª5ïP¤•â˜YC€lwa{éLÞûZ¿ ­{ßQ ¿ïªZ$±×PEîÆ# óÉ‚"˜´b˜ê §§ˆÔçLõ…T|:óêbѤ4zhß4Îgâ¡Ã8M^·;Ó»#z¥]Nµo, 9ÙèŠÂM/bf%IÞŸìåôý^FxCú˜¥áoµ_KÄÎäDÓ-ûÃ+~¤¶Mèóšd:ΠàK™7 yÊÞ_*b%c°ýÓæ ·™—SÎHË¡7ŽæòNŠ7ÅC>tãâ„­ÉHBV­cK;6ÍJðÃ9XmÇd{²Lš7DV¹ßÈš—óÝì÷i¬hÁ|þ^î!.Ké.–N*èwšÒÜtj•*©é9½F—Ñ<zu¼é棤ãçó¦“î!õsA\(ý–Θ +˜ô\4×[ÁøÅÌ¥ÍA M Àݰù ÷Ñ™œÃ¾i4'z‰T¿ÉáR‰È±ÌãÚL@¹ÚXtÂDáÈ•L¥Ú ­)¸!e„`@ƒq™^a=(ª|@"®•tçæMoê”UR Æ*X'!7è£iÙ¡˘£hH+”rh„UC±£t±ŒMCšÛB>)é•¶"E€±€/ÇGˆÀ<9›è‹5$ ‘}`hM˜R퓦€!DŠ"jq‰Û» ´·Çƒ•ÖfQm+ÆhR’¤dtk4ê É3È$I©Üx;Ø*ò“MxvÜw±‹\°Âç4²Ejûì×+Hë0Ÿ›Ñ¢Î^f®µ=–)b66’Æù¢RƒE”d6`9lÇSk]0w*ûºbví‰QL3¹ZªZ³Z¯¬Ó9Ùpt±It°CeNäŸ%†MÜMÓ:Ù2 wGT5šì–‘ aÝÔ”mÊ-]ŒƒdàA\W‰hBv°åÌ—£oõ³ì05h¤†ÓY¬'­“E¤ÐÁ‚It”Ó¡(wp÷Wæn8ñœŒ¤j¾S/o‰æTçuúf.…áw` îêV¤<ÖBÙ a-$bËFTÄ$©ÇHQ„0J„ÒT¤+!PR@*JªÈJ„c©+(P©&0†1U  A-´]*Šj fÍ:5[í´â̈uµ€AÌ!$þÔI©9ü(sš=qe 2GjѨ¸ Ä4U¹v©äÑÎSæ(§ ;t•)c˜éNl#¼³,å”Ï×é“0á.+ŠHÝhãjw’g“KÙb­¢[i7“d›îF~ð;æ“ «=·l—Ìœù¡ÙøµÓµà½ú8áÑPÒS@Y·°“ H^p—ÕÕJàÍ7D¢¥Œ ¢J:—2-`£—LdÓLiA–Òå̦6ÜÊa &@’eRÔ † ËrØšµš !.²™†!mqËŒ-’æTI”,à “ ÀLÆ ÊØŒMP3!Q$J`&ˆÐc4S W 3Mts0pz@’\2ÀX¤(‹XiâÞ5VX‚ÔQEQw”ÄSIQE8r˜nl2µV*¨( ©Õ–0ÚhæŠ[õB!#ðH0Mq¸ª©–W¼‘&TðA´Â-H†b€Âcg’JšI8ƒ¬N· Üo® ­†Íã<.mÖ;£Ïí¤$Ÿž„õGt[d–±„a$žL¨¢°b‹Æ\&ñ2ùõMÇ„UEUYY4xoSaq-yY;b«ÿÆòd€^‰’*õQVfžÆ‡86 éØ(+Ú<wBvnrÎK sUæ!¨îæxh‡gúì•Ô‚¹Ðå­ °.dX¶¢¬N¶Îí„“Si‚€/¾°ZKñcè|fpÖPÅýGê5@6ü¬9} Åæ…âÍ&Ý ÍÝjª£êxH`é+³ ¶–¶Ö¼¸³wöó"¯ŽÕ.ßmnG]\õôÝ™™š 00³@𜻩©wd:ïrpÉ 'MÓ³ÓVi4°«"£xÚHf#=#¶º5‘S$t*SªZÔÕZEVë§TÒhºÜ…È’HÈŒAäÌ"º™•ÄÌŸ EÍíó¡ÞjI§ëv“H>«'†9!«H11Œ! MJŠ;™–G Ö‘–Šo¬+ñ.2æg†¦õî‘ÓZdõ i¼°9}«·ÓÙ0q7؈ʀ!ŒÆ*æVa­¹$!%(b%ýÊ/.18 ï‡%èä À @àÜó›¨+»f‘E… ]ìà7DX÷àÇÒwãŒ=O”wï ¯Ð\WP¡•¸/3Ht+él«-–’`öÍ?KžÍ¶É.ÅÔMäauùíÿW¸:VaW•™+d"Y®yc|†¿>®¡ß²;ªBªÊIÁ ! QZ бb‰Co7^)°G|ˆºOJ–SYB„H«°?ÀÉCYl U Dp’OOIц1ІŒ+”5°dóãÉbY ŠÜŠ‚ƒHÛShR$ˆ—S—¢ƒó€°w÷Øí1À 9á~¨‹$ ";æú!XÒ& „䞀j:¢³'Ñ’Ü®µìv«“4ëÇÎ=Ù*Õ‘nžÅÑVœîŠ Mo.`ÖËÛ¯×ã»úœŒžÐs#™9€p…ka$`Ñ›E† ×M0ÑUƒ"›!> å˜C­ÍÈpˆ”çQ"b øyÖ>,YbˆÉá³éOŸâ=zDá8xÊi3Ñm«©8.ü§d3Ç“ÏèÁ$$Y÷òNzGå™$=î;:ƒ­ËÉÝìå…•KKLضT…µ*-d &S„„‘-‹ IáR˜Âv’e“O¹$Ú-d1¨‰RºÐWèà ²bªb‚± B`*!$€Hf`x-Cé~.7P6\{[H5t–‡­>ëô'®Ì_´ù«eÖª'3Qò „ï^A(È¢P¾ :ü±+ŒÌruè bJ€ Îd#qÄŒˆ¹s 0 mëaí‚ñkðîw4&Hü6fi|ºä믉±Ÿ¥·PsåÈwsš;/.IüôV#ôtvGÀ²WŸ ¡^!8* )¶ˆB–C"§ôøJ>³Á^JVѤ¶sÉ)–Tƒ!”˜*5U[AJ­2ÇK2E ½Í…Öa©„ 2 ‡ 2\L¨È±#¿5¤S1“œ†…Ö¤P‹›„DÂ(œ,Ã^dFqi·\ªBÀ’":¼N×À$5³²X‚˜ª&3–®˜óÄ„zªÞ–ªòf‡b :lé’gfŽêcÍö[~Wï>,%I‘Ç÷Ô‹J¯¹íFò;ofOpUT«Hit´U‰e¥;Å·çˆúÃ2éC ë’‰>“Iúx~ý&q¿^©Yƒ ̺¯V ¼íïUÌLÁ¸¢»ü+Oæóý®¯éI{ÉR‰'z›ár×ÀÃǒײ›ÙgÜ\PWãã¶÷åumJæ•à› <ù+xŸPDØEÌ;p(ˆýOéìãí|Sñy“Þùê”bɨ IiTøYß ôkÉзžØ‹âX9Y©²GWJa!ÆE'ž=“qÔpú¨È6NÑfä,Àš¡ž¨-°Š>š‡Ò¨0Q 0ÌBƒuMÎ>š|ßNÉpé.p/eñëm_7ˆ]Ò ŒñTÓçq–1ýŸõØm“¹ÇüYTŸY×ùŸºúß•ýËÐíxúN¬7/I`ˆW¸£¿¥`'Í¡ÊrÑL80³†P±7ªXÍ¡ßBË‚«ŒEYç|Õ‹L^ŒÜFõè­HÇÚbÑöYÊØc\xâËç:ͯœ,V“†Ì %¤W =)¡:èèé,ðƖ19š½ìI\†àšŠ„¼ã†…›Þðú~!rÔ?xf%ûñÛ ñ 2׆?ðí€Ö¿D(dnrqÖ£aG#™P¼„ )ž;÷B’Ñtç´úŠ$Á Ûƒ»,Ä$Õ§abñFų„);†w<ÔYÜ%¤DTFp óÿ_ý×!éÐHô¢€îáá<&:û!©‹Š¢5OO,P wâÙ©³šjG¥ÁHJ$¦¥Œ`’}?Àц 43þöúS㯺qºº:˜}òÓÀÉöꔄ¨IK"r<ÏHÎYS“p~òÈ"´H~5AùHȘdÈeäCør[åb$þŒAko Q…'U]]¡˜¦ãº1 v.6’ÕÎ;vuqÔ §FlÅ:Aúö…Kèd!Âm+9ò¦“NÈI̼Äç«¶h07—3‘³Z$Ûä”ENSoúåaû~4s¥A Kæ­Ê_çþ?áÍ&$(ˆÙ?£ðLz†Ú䄇À!qã4Püh¡C¨E+.¢”Œ5# •­óV'2Ü«”ŒšéÛÐg`_n” &9JLw6“á'ª±‰½³ûì‡9 3 @ÚPb˜PŠâá…ì w•b9ÁõFa8ì/Ï™ pMùÆSÎ7ÍŸ48º¿>UˆüQ%Ž(“V@Db7 Šœr¡K«šP.D(‹÷ûII§¯~Dö<„uî·í2Jv¨Du¿·q‹µì:^6,ê8a‡ž“/0Bà3<±äa‰ 3Å¡Q´k¸_?—cY 3äcÊøš ¯ç$›=žíòëNäÕ#ò4`¢¡¬šßît§êŽÒ^½©åþ ¯£ÐQ´bC—£I#ÇæzoÌ]¹Ò眃8§'2‚É Íh!ŒŽÒvæí8·J“™Óð=Š ÜCÀþÊŸ_«…&ç3³sýÝ '˜ WE‹&Ç!Ô‘ÞvýÙ+:˜¢€d©¡N±¥_k@ˆ!¥!ýÍ¢Hè„XÅ‘@ìÊÅÙÈVÒ Ç™Î®Vù{=‘{رW³GjbBÓiOƒŸœÈTk¸Ê´KÐL(êX©qà #!#ªæ“ÓÝh~ßTía6T?MÖ6+³jLj½Ê#P.‚ADóàÿ›ü¿ãõþüs†cå¬ww:XjìîÔ1a…ÃÄÆEUˆ ’PFšãçUPƒEˆ§«­„#Q!YýàZí”L†A¯Ÿ‘ö¼ä:ü)™sÙÏNÄ ×U²"¼Lú‹û‰²¸°Möx‹âÊ´õ÷½ý¶Wã_ï”ù—&2$z]K¬§TéL>|?¯rë=zN‹øÿÄû?×~ ü:oÉëçt=s‹`™n¯ ŠŸÃ»½¡G¶‡¬!â«eêh³ö§÷4ÁŠ ¹û9†D¼d0''‚;J›¦qãœlÞî/6 =¨U´žâÅŸÇãïÔø~/Ýü‡®þ<¿‡¡ÿÈOóÌÅ×캢ÁFÐü2†®`6û.Ø á×öÁçþH¹ùi£j䉱鰷Æ÷Q÷ÙÖó&•~þ^›_FÓŸ¼Ž›ÀÚo­ -ò°kÞø¨¢ÞX!@¦äª87“:Žs< }rl÷wÇtñ¿]TG¯Ç‹ØSîÚ*ôõÐ1ÿUIô9ñž]« ìíÞ¦³ÁŸÕëÝ«{ôŽà_Ë$a &;.FMT… (ÈU«çßÈÀ1ü(ÑEbÃï Ë ˆŒæƒÒú½À0Öl9>ØÎ{ž6×§ 쑌2¢Î.'ÿ§#XCëÿü/›ùŸÊ²n7³õ àÀ¤Ôò(×,Ko¸ïûZ±ñ“—$+Xº,`»týø×̇yì‚ý<¿A¢ûï'h.Ž+ù+‘OF‘-) y´Õ–1£»Àù nôåU+h&øXËÚÿ6 Ÿ[þ·µ)ÙÕI4ͧŠýýüv®]ŽùŽÿjž}¯sï…b/:Ÿããší(æ§u¶MÚ;†³öÉөŦSñ_bÀ¯@j̨TÎÏgR…Qj被Êן¯øØbtaÕ„ Gíšr¹°J(»êoÓÁ?º#ÅEÿ2.n¨¼\OG¯éØ»ÿ¿Îó÷÷\(ò³¦¹=þ.vKeFÊK]‡# {…i|þ–°eéŸÈ~ù¢–ð©M,V#ÿÀÅû0AU -ú6òêèüž&î`çÐá(„Fc§§½Ó,ú8•Äïp<Òzôˆô3O&žþǃ9IßËîîa9UÊmÓ]¨zvùÔ6Ô&öJ=§˜&}ij¨(’<åðÀ@Ô¢¨‡•¥÷Ο[àä{ofï9×µq¡y 챿*³j~ôÑ`Ž‹&BÀýûHfkºä&³=ÚîÝ[æ”s72ŸÀæ˜9ØMW(—èúÏ‘5ÏÈ ®c¥ ÅåÜpøXŸ-!·ÛéÆ(ÏSØ“A‡)Oÿ#5úÔºJ,=%ÓÆD¬xXG °|v`]:±Úì&úûÔ~`=-¤¼ çÒÙ£oŽ$Ly°üI ŠUƒž\2xžØ©ì4·o¶¼È°l|ìÓj1­J?áÝDêÁ¸IùJs4gM$ü°ñzôµÞ‰g ½•ú^B™â¢‰,êýüK²ùJm ­´³ßQFkóÁ½½i0ÿ`=û1ÏÿêHz¿:lÑNò˜šx< ·ó˜÷-Åóliý°Š¼å5ÆÇß_>I~è³ì‘_FEœF¾OÓºÃþ¶¾á2¬¦@–õ<½|t$)ºRW"më8:üý­7f!Õ W£õ¬ÈXWViÔ¼ÔmÖõ>Vkn¤öo#³åîñÐÎòô¼Hÿ„ˆ#é­ª8|~ãÜ|¨îÝl¿]?À„ žSEÑA"7©äêwhìôJ3añV™Ê†3Vÿ?¦¤€§HeÃ;{t¯©~óÔ­lÿ˜×ÁÄÓFÍ0Îæ.³ŸcóÐãè(ry»9âûUß[>¦Z¥‹BTáÞø–Cg×­¥W’²ºIà÷:Hõ¥ö¼õ›‰S+œQ»=zâœ9oÔŽáøB¿±³ê"Få¶³RãóBÊóïíΟqùXsdÈ~Y(ɈÝÿNÓÔ¾;\—úC„5Þ»¯ãþ»>¾©~m£­„Œ 1‡D½áKÄ;³Ö\yßêú:À·j±‘Љ#²ŠÛÉœ¯8¹,Ò¦(ý—ì}ôìü@çÑ¡ÌÁ ,ËX ?(Ô¾ñ°ï„»»bŸŠ†*dêe½Û/¾ùéê^úÝóijænç«ÒÐÖu½¥¨[ÝÍøÆèqÉQ¾ødFzŸÎûaÐJ4@‚;íóвI!Í¿g|äï]‹ï?í«ÇÏÑ[¤ k¿!Èaò3œÙ%:¿-ĆÑ. U%#+*G˜Brì­FÉ ê£Ü±·/Õc ¾™ì9ïûog?ÄCã*âOßJŽÆbÂ|æ`Lázø¸ý(êå¸9OøpxzŽ*ö(íˆ;7Öu¾ÉÝ~ÅÜ@Ä ^ëþŒ_úQm_xü]{?’‰ÀÿIݯw{ÁÜÈxÜÚ'Í›Gø< v–¼†¸¾½oŽÚ;ê©)Ì<ÌQÁîÛî½g Ûº¾ãl„ôB ZÞêïOÂù7[¨¯¯âƒfqŸð~”áù’ ‘üÒcüqÿÎ[¿tÍ»PÀéú‚èÓ¦ýÕù°À¢vwô:_l¤}åoñe3¦éá/wFÓ¥?´ôXI7®6ý.0 ¸rç@Y³uþæ¯Üõ¹‘¿ õY$ÄÕ7ô,ˆ—ÙW£]KÎ"7rý‡º¾Rèn¹-§výžЂMôðiªkH³qûo÷+2+BÇa_¹åt¶ÿDŸRÖ;NãScrOÃEœ²!ö1^ÛKx„tåsL\8½—`BÝm /·[¹&~ÓÍ2¥C‰Ù6¼/¾_Ëoo‚á¢ÄŸXì.þP®Ì> H•î·Ù¢@’íYpúxÏ]ÃÕn‚Ë g3Óï-}_æ§4{dô¢‘ÝfIÇ|åɶ×Gg´÷ßm+zDw§Ò$¬|õñ}uw&`à~h·ë‹ÿ?é¥ N’‘¬Ri¿·.S§–ï2Ò㳦G¥Ç@¨|ì^œa•c<æ¡Q¸oÊÀD%b÷Ñ%žêƒÖºsIx¾Ït]‡ºÌÿ{Ú ™EÄ.‘m›³åºè0îìäà\a¬§¾þ¶ž\¬=Q±Ýþg„ç‚>¯?Ûe¤§©,9mJ2¿E_q~7/UÒúgã¸ðÐÓ³‰îbôT5¥ŒNƒBBN=[ðý)Õ8_¶mõk<œZ^?R·PÊž/o鿵·EJ‚eØ©DêÙs)þ©jŽX69Ô|? õO>öÓ§Ëöq´%¥'‚Wháàc‰2B?Rºýaÿ‡®n™^Çwh|C_™%ö 3ÏÄaÅ:4ød×7«õ[œ]Íuƒ«ë·!q7Ž+\}¬·Ïí]áCŸ+W˾bA^%v[ž†„ycQEmºÙ3¸àbµš×_x,gØžÖ—ÏY.ú†­nÊüÚÏçb'œÒgÝA¾žÐ2g bf ex(ˆ=úl¦×Fkø¨÷à{æºï8äÃûÑû‘uà 4ëRrºÑBD˜}_0v•& šÝjTnçÚ;óaŠsÈiOFd¸ç±8gzSQ*¾&›¬ü+ÖïC ‰¯$›tû튇š{ƒþ‘ Á…'¦çÍ¥ši»æÙÑR\«Ú>÷Ü–•c9LThŽ(úêÝ–¥¤EØ£®—™zäÝÉz·¿©1ÑŸR猪´Èu3t¼>Þä¡í’¬wu ã?—#Èð×¥„Ïj“”×û4©¶NhÙB¿øK²ÇlmûÑÍ‘ËRdOZ6ì]ˆi‹|H£àEqÔ5½ßšˆµ¬¼ ûÅUS+šžü2óm‘ä#<# :åÛy¤LygŠHm¶ݳ!†¶} /Z¦HÅP”7ï_~î2cm•î]¾žÚ&Há.ÎTû§_('Xq7úæ¨Ð 7L5ZJ<×´dôI=S´«o¤·¹Pî°l©Àïž4Î/Í'y·Æ÷4YAÖãñ—ωMsä7s·9huŸyú'2În‘s8+Õ´ÒÞç¾+îßÞP=OÏÚ+<~¡×ãð&d—-Úâ*qxºø6«µÜ»E½CÇÎfÐzqÑi´þž\V„×Óëý Lþõ[?”hX¹Jx‘´Ý;Ÿ®·îé»iéŠá@táßmÚÑQžóUc “Q˜7Ø ®&úÑYu¶ìÎ;6ÿ·F£‹Ú€Â›‚½2ö×CG¦ÑB=ZpW^iäí&žeí$tä%Ë_¾ØâêoØW „†·“Ç:ét`j%,©Ÿ:ÕÔ°LÑ{/yk>Jõäå¯ÞÚÿ97« ÃÝÍu¸ß+5am|âdjÒ×›mº÷øLB0`ØNy”ÿX9CÖ`ÉO¶«õ™©F3]WsR•¯o› Õh²àJu“Þ:/II¯ž·Â¥,¯V«yƒe—b!9Ê1…çK§F¹æòÿü—»-£÷Ìç==éN|X¬Óo Jù«zÝ Ï«Í²Ùð5ÇæXÊ»gg8ŸGcÕºòrŒÒxÈ™ýïd"¿OóÀkãÑø„ Y¹žÉŸ¯Uˆ±êÑxmÖ½–0 >%úv—Ëz<ï~éß²…/eàk,]Lú’ÌÉÁØ^!Q®5°9fvÞÙ­#ÃþË‹»Õ@:ð0½€Þb¹<e{C)äs‹.•̵-3f©Liû†OÞI†ißIw­ýüÊâ7g)ër¶í jÄ\¿u¦Œ(7ü­Þùm*17ÞŸõ{\ySЬäò¶§w¾v…ÆK ™Î5z‹2Ã÷“‡£EFÿ^o™·æãÕSlL#ãr¹ÚÙ{Nº+LÜý æ±×îjéš¾—Úú$÷n öˆJì*>U¥ˆÚÚI|IsݽQl§• ïðÒ½,—IüÍh¨gŠWų^/ûú騠ìÇÛåá.ÌËQõ7Ê%Ö¿Û' s¸ëM×V.àñcÀ–X+¤mwߺ’ا“›4>e„*×îl+ì/¬•Íô÷‡%‡çç©ãfE6<5°z[Qzµ·±Ëï‹ î¡IÈÞ¤Yøsð\=>¹÷tn_±q¥oC¸¨ëF®Í=¯šÌŠZ|šÞÜÔzÙ«cz6þé\¯®Û†æÍ~sÂT¢ðFªºãjðÖrÏyÜF~¿e°ã›*ÀÝ™¶Cÿ¬R­TŠ€–»«—šË±œÙaI€|!Y >gϽÕRyìÊ™7œfyóçí³rnËsv½ú8ûû€=³ FÞ”Ý÷»nç®d¬¾4v]ÜúÓñuxË„´—/«¹Æ)÷Üÿ[töÿ»5Co#ê{•U?#Í YŽèe㇑쭺í+ö\ Ö³“>Uq±ãæÎeá‚â×z¬µðõ×ϯû{·{¹)’ë‡?3qêzËóœâýÏÞWYºgñ™µÏipP1™#ö’}n(ߨvâ›·Æ#_c1àzƇcŽËpŒÎô²'»Úé†ÑbÿƳ81ÿ¦îï(øÿs;d§ÁÅr_¹ÛõXš(èɤF ¶Ý§/1›§{Òwœk°“QF¼A¾Á­–üäèK%zÚb·Ž®5ð×1Zõ´«P á—g5«ôΪdv‘_QÓÎQ[÷”j&3Ê…’—Aµ¾gÃ4E`¿ïuíøæÏ”g¾Þ¡ÝØ?ºüæ¸óA‰ççéJ\Ì4§óo~‰hË9ÙÀÿ³ÛÞko'ʤ}MX¾,µçgP|jR·Ý‡µù\®>§½YýaŠi O‹¯üƘHög/ÂG‘À/q_G†Doj‡T“ñÏSù2I_^mN7:¥2äî“£Íë½?ZÂÙÆÛ¬ÞÐ¥Ûe²y6Ä—Ìà§^h¿›ÿqšJñVÛ»‹>é1Xm†·²~7®Â ?ìÆ‡Hˆ_9Hè,6—‹#1L³FÙ¯K›^•ü™/mJCÆÕ/áu÷ïÔ;àÙz\Bm=yH2Ÿ`îïS|è›n R¤KyÛ§?Œs„ÍN½QׂȦÇèȵåÊLL÷”Ôœ‘*NüGÉIÃ?MŸtóqØlŽ2PPePþu—áé{³Õ¶%A¬e }ùZ¿Tä" ¼ ¸Óž®™ÇhÝú_š…ÉÿBa;ÁÎûÒÝfý‡†~+þ¾$4ç dÿž‘q¤ñöº ,U~qŠT7÷Û.™ô®êq7µF‘ŽDÍ.µ'ió6ßB#9œ'­Ô¾x]ŽOõŠ–äTy5n¤½–&»_.ÅtÐ+Y½Ð“´–2÷å§/º©¹ês&zSÒ±J{ÏO¹:aZÙËQEJT¶%uN.£Ûú~åßžD·¡àóG‰s´iä´!Å&V¤¤ÒWjí`]ûQŒ¹}ÏMWÓƒõ£Þoß:¯Ÿ/É6r*ñ³÷Þ…øé®÷ÿ« ‹¾[öó+[•õž¿ù£Ñ׿aóV½‚'o¶r¿/âOÁ]H‹„fJ´ˆ9sÇÀvæf1£Þê%¹|ÑçcO®xšŒE¸²ØÆs6'‹u´ÂÛn&Jò ä¦#}&ûÿ-šÏrÏðŸÄ–bdàþ—ä*Ÿíñú™0=ÚMŸÖ zóÞy‚dsc8Oázüµën©…ý„ÌQ=l´Õä¢Ý¸sQû’ÓË®ØõŸ¬Î‡¤ø‰iõ¹–aÄé<òÔ]•RrÊßïtj³é«^-ªvÆ×–ÐÂéäD“š×Û4¯lVÏõþÕ 'Òÿª®ïj“í×µq†Ò†>žüã#?–¬§}ñÕKtìÚÒ€z¼–]€¬G‰ÔŽ©ÎM¸³»OôáäÖ7LÖ}Õ€sÆÚ÷’eÝ1® ú:ŒŒJþ]NFy¦àÒãü›Q4žÔ‘2‘£²PXæ-rß}jÐí’‡&8@á;9eåý¶q’±]nÇ6ìÕÅø¥Óý¿!µô⫴ﳨüð'91‘‡:üËUÚ¯×Si 5O›‹ñwåȼBðÀ>¿ìžãq`¦ÎYž˜=’Ü_™ä—€>ùïwCkÁª‰ˆÏ67R¥ÐÚÆÕlà_è9ªs¬¾Ùãv¯Þ·ÒîK–§žáeüN“èf³:®ÀÑcE?ªq:BÖ§î?®½k´én¹Œ‹êМM—iÃíËÿXLLŸ˜@¦ùLZÒ'ò Ry-Î+þTYíZNr£ÒwgÉÿ^›3m?[˜MžÏgúP²¾ˆ¸Ü@YXÙ=ɕͿëÖtÈ.Uh»Ê×njvªDŽJÆÝ¿Œ¾ZŸµ@ì5ôÊf§Ðy{ŠÝnÇ16Æ þ]ù³ÆØs“©~Œ;-ú·©NñæØ&÷¹éxþ»ÿ¯½õ­nóEШmô§¨s*þGf(•ÛTÈ9õîLS,TQ¥Ì‚jÔ×Åè×+ ½òÄo†¼¡äs,¤Þ¸ZåŸÚ?².+‡«¹fT7˜4<è?ObÍ»ÊXt¦² }t;¾vp­æpåóö#3U¶Ymcg-(¯Œì®%9Ø»þÙÅúâÇîî„âÚ—e›Üxš-—ÒÓÎ\³øËœà;Eò©}&2ú_7¿Ô7 â￟»”À¸ãDËî0Û]ôœy 6î¶|JÌ–îÓ}gpá‘{¾›ÃÊüo»Ž-Ý3aÎRgÆ6ÜͲ·‰Š‘qWÈÇÊïNÑ÷o짃…ŽíÃLsÚÔœeÃ"/røÜ6o?Ù³œýˆÄ…°žŠ{r‡vG¬ÑsáT`øW×`:o¸zO^ÎAAÚNg] g¥›3Gõ÷6ZLì²6S.õæ™ì*ÎÙBs%ÑUÈ·;ª¤•¸ð°®ýb•bf•ý§ŠçiÜeÇkiXÉǽbÿ%¦Í/ž™«ÝH,ûà§åú(ë>¿hçÞ¼Vråv'âÔ펹„¡Þ:×?™Õ~}¬[²+þI³ç°”t;qðzØÊ}ý79ÖXc‡åïR;,^ÅÒ]œž²>=–¶S„q¬åw2+f|Ÿå#©ÞöêÅï~[hÉæ4µ¦Ó¶—ò±Š:m8Üu¾Ã‹ŸqÒ÷/u²áé öåoY}1zõþgÄ5U yI’P¨Ôг4áR`â=½åÜODƒvÞŸqYß& ëSö‹÷geˆ«¦Î¢ÄdŠÈçÅÃõ×zéVLØ~ݳ¬)OÊã GGå«Þü¶ð„jvþ,H´qf=/&Ü««¾Ežf𰳆ßýÉÓnãÉïÖ­U&lWÎ845ŸœJñƒ·I«¤~ʯä¦p9H{YßZyµxŸfvÞ_ÃKÂó@äÑðŽ¥ðø» &{\æúí Úß:ÊL¿¢×ñzÊiÆ¿­íÒïL}ÿ©L_² Í›7†ÊTI½–•œç<£û…lc¿ì!ÁXGþ« ¾­´}ÿªÿ‹ö+×»Ú²,vf×d9ROÒV>è•4ô{iz²ÑhΟ¼µ¸†­_͸¯/§Õ¿ëtCGÙ Åýq#­WÑwÞ_ŸôTîÕ[øóÝå~ï®”†~ÙÊÊlkj·ù7ˮ쮕·D™Óbã íöøÖŽýD.Ѿ#G¨L‡–ÿ›KiÛ4æAÎsíüfßC§¹Ÿ™çÛ>Ûù°w͇©Ò§C ¦dÿ™É¼Öw“ã:Ó Çúø^ø¨Ob5,êÐÌ¡ôâv;­ì®:æ·É¼®•ë»Ý§#¨»>…÷“ïbúê. LSUsÀ-¬W$¦ûýÙ¥ÔTìözßó¥5†ÑÉtdå¾^45&· }£Ö|¼2ó|+2b, ²ˆèy¸E-›©÷¹ÿy»RÈ£äM„ÿwý¶ÿ>ïU'q>ïüéNÝFº°Æ Ñßá牷3­µ]®þX¬Í:t0%ßh¾)Ô²Ëa£MT¿åÙgß©¾ÇÞÓˆÿ“ìX+Ò!³ýè>œ oOÅ­F×RG½¼ø`4Ë”.ÀŽ{li‚ÿ×åàä.4rbÒódPÐ<¨ÙTptœé;M…J5”WÑvrÊï™þÜi‘zJrûù´þÜŠÎâðéu¸Aid¨Ú=úUþÒ\{’ß^R2¤-k%·û‹-(½ g`¬V’Æ5wF—ú¼Ú} z£ál¬HÚVÇø;pÝxÓOâ–ö³—L° e>j*†‰1èlççXôzX§äÿ?åà¸Z\z¸±ö$®Y¸þ÷Ä:p‡;W ¼ÎÜí}ÿzÌ7Sa䇶…¤’@@á•¿úÐvìb8ÕaÏ.^ ®ÞÓN¦î©?¾½nàox/GŒî§õ±Ö=&ë‡èä/ä”^¸ÞõSú~¸òvIËÛ{}΂[¾+-ÙœcWCÝøþYm?L/Û¿*ÿ:wttiKõÀÄ®’¨ÕÙÚk;#<®{$VÜŸp1>;bGsÆ·üvX¦5«³§Íÿj“Ÿ+ÝÿæYSÝdü‘~ë™èör}¶z ¦µýNá·Ù ¥ÌòyÞÊ›³çÒ.@Pøm§:µšGÍ®¦ ƈÿGƒÞ5˜ˆ±fˆLÉXa|XoªHy„£¿×¿9¶Á&B¶¶WÕÓ; ‰>oiyâ¤ìËS+@µt7‚AMž<âztÙòímŸ“qk±YQ¨²›@€‹?^@‘1)Ή‹áȦwüÓÖ†ÎÝë¬ÏÕÀÉ~÷A37 á§Äi­ÄÌ‚f^ž©AÄŽ¿‘ Ý¶]ã%´l•r~iºôþÌ_¡“²Xi—Ó©puøI.(:æÛY¨… ªï,çJ»¿%0y\ÆbäÅÄü"¼Ý¡¼j‚äËV×õoߨ¾èÓœ¬T ®#­%¯ÑÆ[†»Ʋ£Âô˜5žu-ïw·…íG‡ÍÎ{Zd²ôV2dã>d裵{‡N<®JBô8h/O¯$Ù‚+%â%ƒ}7n÷ëN“]¼Ëe^ñ¤ê>[w ¶žFn|uÿòUvÒ7¥Á]N•ñ}ïÛ0YxÎF+ǯë1œ1ümÌjÄ”:Œ ÙÛk!]šñ™Î;4ª=迹ñ…X—yÕ2:ç–Ò›+xû‹ôú^oöæ…/wðÏñŽÿáÂÉOÁ7Þ‡uL¢šãªS†~M‰mš‰¦â7ë¯G„Ïö¶™ÅŸAØì2öìŒ4ÝöOv;W(¿-/«Ùêl·ÍŒÎ žNcFÌÚ£ö±2›¡i²€[†º>x6`ë‰ûaĪïÎé(Î~[+ûª¼F´“½% é—Iéñ?£éséCývVØ΋òÆLÙLÞI?‡–(¹3´š«¥™×'‘eºÛ+þUͰ^Š–0¶ÉƒØÒÇ”pU­'þºµg Ïih ï´þ¬ªŠü>ÎLóÏÙÓ¡H{¢¼:·Hrí}O/ê¶GÇhû'Ä-öCÿ1AY&SYMýpy Úÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿá£.2Â5âíCî9z@û­¬¶y˜o®:ÙÞ÷;ãkaêØ iðLj¥m3—º¼Ô§ xqíçÁ¶T¤ÉT ¢ÛS6ÙÊ^´7¬m€@k½€è==Ðô4ª½´€hÛuC¨Q ëá÷\ú;ì×^àæ…¼8›¼œtÍ9ö“c]ï§`§»[íßF@7¦û­7sëÜÏ«–z÷·`6¾^öÞóÐ{Ì5·¦ƒï}3@ (^NkÜw±pÏ}xû×¾÷UöàÀl Ök@¡÷ÇÝßrúðowëÞÎs“{qi—{ƒÛ"'½»ØÑÞËèoƒÏ®¶«‚ëÎÞZÖ‚›oMÙÏk}Ž|-ô`-4º54»½ô÷|{ÇTŠ]µnû·Ûà}î8RUëwß}ïƒkCZËZ5÷ßox6`úôt ¾ox}Ø }ª/žà÷ØÕP+羞¬w¾eéôï¯v}>åÛA ¡Ã€¾—È{Àh ¨U ކEÃ7­îfy ©cFÚË€ `Œ›ì0ãÒ탓C¡lá91»Èn;ºsw +­Jvéª:è4äÓX‡,@vn  éNN’¤g_ò,=óë)y±÷^O_4àø<ùÕ3mFZO¡N´îb•U„(5ˆì77˜ͪgn}ì$IkD ÷»©O®¯¹uãPU¡}÷Ã×»:]š¥Ñãqßmèä×h[‘m³):e{ƒw¶ln 3 é­÷hóuY4Fm‚­š°à©ÛeŠš9¦’'Y™[lØäíÌiA¦Ø¥­¶½Ëc­Û¸6¶mf ¶D š<ï³mïWµ´Rª³`¾Æyi­÷gJ¾ÍI!¶ÖÑ ‰O»;îÝ­ªÑ–°RÍRÛ[osÜ÷3 D æ[ )I:V² ­jÙ0 Š”Š%Þ7ÞØGXSgsŠÑ†}ëb,€ 6«B/M.ûÍð>\Ï›ŽU{*›hJÝÎUÛŽ:Í|ð×mHmî)ÁLöà“O9ã}®Þ×ÞïŠ_}ï-È>¸ûpP""@0š`M2i€É€L&&Œ&M 0&MM #C †€ ƒ@€@š4ÐÓM “É OI„š'¨Ôôõ4È é ÔÁ©æ“F§¡ šzšb0š6¦‡©‚¦¦&4ÐzƒM  ÈL€šj „5MЧ¤ý4ðÑOQéêQ‡©éOÕPõ4õèÒ‡¨ h¦†€=@€ 4’@ L€h™=M'©„õ04j2i‚&Õ<ɨš ==Põ4óT7©è„ö“SÚ§éò™='”ÐýPÓOSO(z†€Ié 44õ@h @hI"€h  DÙ¦b˜4Í„ÄôM˜†!¦)èȘÈOSšiè›S#2›BdͦM4È114Èž ‰ „h ‰©·ªLTýM¦šj§‡‘Mƒ%OM“*?A©Š=ê§éOÔ?UžSj{*6†§©äôš úPOÚžÔAê~¡G©‘‘‚h§¤ÀÒz€ ŒÉÍÙŠgÌ_ B…Òùjã¬%áR <ÜÏQS˽­ÜļEA÷×u¯ß6„-g«£òlËÿ÷?ÿ}Ýúv½à>µ†":µamƒmDK “û þâÐþæ7¥&aFªŒüà áN3TÊVYJ2Ò¶ÒÒ‰EªT¶©¼’° k‚U­YlUcXÅXˆ" ¯mƒRA’@Ç×ióÿG¹·ë|Oif§º‡Ôh‰üÛuÿMTî#'’ˆ ñ8\.–Î- *¨ª?Ùjô>{Õ÷á œ”ŽÐ韔"je‰[ǺhíÕ‚BVËshgmCÐ~Ù…E2€ïA4„d(Û1ÞP÷áÅ[îQ) …‡èµIr¼ÜÈn³ûZÎT€hûŸÇÝìêÿ¯3Øúoê·ü^Ãþº­kåËXÖ…°QWUDå©p°ÆR´…Ê–˜àÏß%tʆ°¸á˜b[0Ê)‰[B±+‚\‰QTZ ¦$+Ž[-¡X¥Dh„ ÐÁ†@#SåÕö≠¨â( š'ðÁ|äD>TQ¯´§ÉŠ›QõñQpú÷{ú÷>â#ð'àA÷QçD9_¡Jú1E?h@öˆ0ÿjWÿÅÛöÁq( ã|¡í)Œ_)üèK¼=ÑBðY„iý^gò<×m…@O?ÕÔîhdäAÈôû~’S>]¾]\T¢'ü…ÿo{š&ë*ÕÆLVI¸õ pSÁ“/&:w—$µW"˜uIòò\x›¼’!Ó“5W‘1bSržßdÌETÔ(¼² Î ÿxMÿ5~Úzøýð,q1mþ?Sü¿›Å¼ãm*«û” õ$&ý7èÙ,L{å(F¢Ñ#hù ×rÒW"Jƒ?x…ïQ‹L6ñ§ù?ŠþQþ8©Åí(÷ðõ0Oýu€'ÇŸÏ“ȧö'àE>9¼ß†ççÏIûÔî>Ò‡èOÀ·Š þØóýï¶ñ¯Öåï¡RûœÒDQ"~oÆ\éµ4#Æ@µ2T0€ #@! !Œ¸À&¡ˆ[ubÍè'2ò^²€ƒxU÷î?'êzýÊe)´ó¨ ?ÄF ¿ÅYŸ5D¡÷ áQO³¹£ˆˆAïø/1½¯Zºÿj'q¯‡ÅPDˆþ|Ùˆ¤ºÈ—Ó8«2pgkÄÃè=ÕÔŸ]R‚ŠwRW#Iá'°õAÎUÃcÿc{ߥ"¢ÖSPyÕÍvú”¿©¿~d7$snÊ›óþ2TÂþÜð6#½€aBÀb WÑä†Äe˜mõ¥y){6—þÚDu¿Z³XÏó=v0„ á€'ÕŠ1&„a™@¥N:g*ëé%¦Î?F¸éog€Îö­}}^öçþßu¬µL9.‰Û˜4¦ÿ‡’-¢‚³5ß·A¼9¯ñ€yÀBÀB ؘb ¹Uô–‰”˜1€Ó'ñxB°‹+ÏéO;‚ÏH×k~W¹¨z À@¼! ¯ ¤Ê‘Âj(ÿËIH“Ð78gw÷ä¸]sÀ@Ë€VHv7Wã~* GA|™»V"´âÀ$%­Su”¨px9ÊYJm¶JrËW¼¥kUˆW‰)ªöïdu öú¾…häþ­¬w®_Óòy¼mnuë±[ç{víÑæìØó<ü· ¶Ÿ¤åŸø’š€€FH Àb 0,@A$ è‚~<~Ý¿¦f‹G5Û”V7ŠÚ¨"‚ @Át‘ÐÀ@*±ˆÕ¼™ú¥. ]YpøÔVQ¡€Ô~t]Û´w©9¼:yiiêZ¦›FÈ¥wZI;Ìñ,~#Œ¬“˜²ŽÐÁÔ,¬Ôʃ&vµŸÑð+ÿªk;8 v­]Ô%Ÿ®„µ×£d’Aûø†h¿Áå= ±Oqûƒj;BFŒoLÃŒ6Oœ×s‘’Z5[W˜ÖxêzòªÒœ‰{ÖyŠê“nÅW-™i¶oƒ¾ Ú')£˜5HÃRý³ì_ÙM“ª3à@h3Ä»”ª)ìëÛ!ùf Ú• ™ãbe `<õä;€mG5¹˜V¼ÂÙÑ„ŒåíÐçÿݳ“R~ÞµÞ¸±à³ÈvÊ;äÐÕA³_­Õ/š@”ŽB%¯? ±·¨U—â·áß;á%ûK,/v—˜„kòƒåÞÀÌ'V“Ýè°y[ºS2ë2Ú˜EƒEB$¢žyÍð}-gÇ…¤"toÇØ×ð«l·agi"Á 椟59Ëþ¤›W¹‹CÌÔiO[†MUÎ TFû§yšìEÏò´ÉUöSVð:Zk÷Š`À„ ííO'ïÄ.€TV6ÌŒÚEMúQë+±jƒ¿z§-Uœêá{Ö¦á§vœÏúž:~Ó©[:•®Ðj']ìÛL_Þé´hZu…PóÚ6àõŠ÷-úMïeç1Ð]QŒ0þÆ!ŒÁp` £/Œü“W©®Â[Ø5®„]'¼¤îyª4²ÐïÝ@‹žz±&}¿NûíðÄè['9ÒVIÜØsOéÛ¼º©]»ƒÄ´tèBHŠþH€@jB«ÅÎÜÈæþ¿Ú@©2Ÿ¶x‡×q¯ž´Wù5)þïôív¾ÀygùÙí—à™müÿä÷¹;ì?c‰uÁQõ^òïa}´O`Ýä¡wø5!`Ž˜@x[[|/õW:ßh³tõï݈ú®$.OátРi÷ÿÃÿ6ÿæÔÙ}?_•ùÊ™ý;=öaºßâºg‘àeýï7ZÇî’£+ÏQô!«óÇjÛe;O0ñ‘×¶KøÙ% nËF¶Ñ¹™½ˆ¯1Ä;1]ÞÊç`2 AV «~:ɘ‘a‚"T©dµ›tÀ| âg3˜Lü<|#[æI B£Ócƶõø–ôv!‡ä7zÉÿçýè " U‹Æìm2¨x{Y° ÓùJ§ÌäèÑÒíJ¦¢1£x]ý¥!hòÓ«¾('ÿ¦·aIõ¾5ÏICÎŽØ*:U¢t»>« IO|’~ÀÌ$H¢À()˜î"§Žµ'–oÿ3k½q>33©}|J'b¤ÅÎwåoÕt_ý÷¡,ÏJÓ›û¡ÔÞšdqg¨ÚukGiI©Ê¹t^ÞAQ쟚ª-¥F{¾ð–$F耫r³j%§Iôïõ,3€)’ È 檨¥‹ d”T!R6ÔŠ•’£Ä„@Œƒ‹œÃÈ‘ö¼‰Ñ1f·DŽs)}åÉáª4«Ù6ÞÞëZÃÚ`, ¹Z¤O:ÞsùÔ”œT–µq’üLîïy`µÚĈÆøûzHˆZ{¤W ®ž,³W:€%(`{]ßs·FyÎ(5&(w¬Tæ÷01£"¼D1îáFwß²âl DŒHAÏGhëHáûX7ï‰ñyÖDôƨÇfn“ òbA€ŽÝ3Û°˜HˆxÒTDTP:SÚ³$’B|(zТÄV0Dô•ß3Ê×-‡Nßzò}8ù³ÅöRóóÜÜA*½öNÑæÓk§¦«Ù7JI ±$" hDÁÈu™\‘þF"׊n4¯¾~fŸ÷×”TÝokWÛÛÕ­{Ýn}«ïøÐìå}B{ì((EX,"=x1- Wµï¾ÕîM´ökËŽÝ5«ºÐë9rQ»\>C t~ZŽÙcJÄßx¤tC3æ~T›¥ë'#ï‹òˆJëUÉTÛùM€ƒàx^Ë>òLë¾åHµ4'P©¡S\‘øÝ‹ù.dÊî=~ºóïËCû^ N€?h™ƒA48Ū\@  * Iò«RAbÅŠa’éÁƒó,´öÁ€~†oä†>/ᢛ¨?–10ç²ÙxßÆÐ Ÿ©E’4LÊÔ£PÔA /ˆüq–¹úhfoÚ~«_öpOä<Ú‚‘½A³'$háÒwõø>´¦Ñãh™f.„‚C½‹ÐU4í¢”$”“äËl®ÂVVN[B@ü>‚Š(¢ŠxOΞsЦÂc®óÀ $dý£-ŸXÂ. 1ˆŽ­´jÅz5÷‚_M¡êôŒ¼åC#2‰‚Eï‰ç¤ÒCnÝðŒlû°=¨û›¼v|›«_mxoÎBÇ(Ÿ‹çÛ‡ÏÍŸ\ÔÓ5±éƒúâ?úÐrMc9ÒS,Pí'¶dýÕ¼_=êŽ=¼é¡ƒÅÁi’BC»Úæ7ƒ%î{ÓÖœz§‚xëºu¤Ð•ç| <ê†z†^¿SV`ÌÆ"ÇØ9B—OEº48( ¦³ç[vLøêû}CßçÇœ6ØïÞ!)±cAA÷订jÚMjËV£é=^²Tztâq»nv\rÞ*3º­ öÞ›bçË>ó¦®]w½„Œd—”ô˜±h3ïEG5íšgð,¨:žï 5áò6£ï¤ã%¹Ùùë\œ<é‰ÿ:/a°äp'wWS½Ó<>xÎ` ˜@ ÏÊl>Ì i‹O°È^ci¸ÌÀ®£2 Xæ‚*’êHt`ƒEæc’ËåTíHšƒ BÏÐ:ï†9s:ˆU íäPóŸ]Ò…oó‘ÕØƒºG‰‹Œ“J±—G>îÖ½—¦w÷ƒsä• ^€« Ûfr!7é­Ø‡bëùy0øoÓ*8S•†ÆKE#î׋Ùþ¶þÛ˜þ¸ýC«h×£oCÊG•Cá¨Ð`¤hOi¡7Ébš×Íg¢/d7co/vfµÆ{óÑ$sr:Âsù†1ŸkqÀYÛˆÂþüá« W„Á±‘T`‹•6ÕÄÜ=ãÃØ|§€PÊOØŒdeÜNf¨`2yjoÅ«v÷¸ê¨Ëçï²ï®Å55hZž,n)Žê80V}NfÃÿ!(Æä&#\e=ÎåææöZ°½¬Nš\}„,Ïàw`]F˜ôÀ/a»1´ÅøPUuöƒÎÿÁ0È$Œâ8ʈ†Œöu6á$ÒXÀ ጠC­`¸:Um«Í£×]Ímþ÷ÒG´•ƒ¦Gœž ;ã¸oÊèçYÑŒÅÜYâVs b2iò3ml¯i¸¿81}©vKzOÆ—¬÷ ŽØ™iòø¿×IÒå·Í¸-À¤"¦¤êpMj¢5øÖfkâ €¹X‘YÅÑÆÈþmÊduý–/Æ®ø$Jûüªe ˆ©Ðù+Ýð°¾}iOÔݹwù©€DM‡êÇFœØ2½ŽŠoÈäfsyó 4ÇH’–Ò§˜5`AŽÓOÉ ^Ó¡;ä O6ld½3žðs®º´"þ9Ýò*9ìü%EÉMűv.$–#ñò•ö.&Ýø€M Ý Þ4j;Æ®#ÒÏ(ã€]ç3ß¶ƒRÅÁÑo)­;åÖ~ *xì¼QÚמwâ·]áÒ¯/Ñx÷|0ÿO·³óQÅþ]+ŒŸ ï“ïvi»5Wg×L÷¿­’|]ë&NÏ­RB n?ÀålŒÙ`è­]öï±§ÈD5=•»GYëÙrÏ̽Ôx¨¨Öz£º©ÂÚþØÃmȨ)SÞ+Þú–çÍÏA3NØíré [(쟹t­Q}•éN,"R™vm‚pÕwëý©9ƒJ¹'HÍn™ü—(Ýíoñ¸ˆÿ ]=Ç»±3CßÇš‚crZt•QIW\_‡`Ðe;V©šŠ³Z÷©ˆ¸Ì²ÇrO¶Ñ u³žö¡×íþQ=ÝY“ݽûÿ xOK:\Ù¾NFßÝ®{à¶0ת=šo¹LŒ¸±i±eÔ 6ñ%¡rc0qú+^G¸ç[BïšŸÐØÛòñ4¿—9×»a…¶‚7ÂósM$åAÐØ+2ô;˜ì¹^ß2 dFÿú›LØ‘"ê´u·]¹o5ïSuóÖ]hìψ@ׄO~yì¢TŒB¯9ãîèÒ¬b\T›åº{ªn@P ÉpXØ3Wsuwrï<Ãÿ¬Ô"¤×¶ÛõøÇ©S!8Ä)ш:2„€“ tðv8ô‰ø°0Dñÿçì½2ûž²Ø-O˾­uà€žãú?¾ÿŠøœ¿3þ|ÈhÃþYÏÅ.ºë +´i͓֬SÿǶ_+±©À¤_wýø¿q¡ãáL??âN÷øîQ7`@AÅ6˜¢€†Ü;ÿñÆO[¡°BЅͰ"ùxÂ(üÍÆo[ÜOþ_ü¿zïÝëÈ1†'€ÜØ*/W &]:6oWxƒ©–Ìl,ô¥Êz86pá½è\ Ά³ÐéÈùNûÁì¤Gާ6,uC¡“ùßɽ®·¼’QxHI ¦„Œ¢’#9rH¡Ùl|‰DAY ¬‘IÍŠd$á °°XªDdˆÂF$ H®§khI}¢=šc‡¬³§V/*ö-LjÚë½Ó6½ kXkp\r=ag{Öè¼Ã«· .WE!"|"-r ‚f ›„ ¾)† M³QuªB©¶/B’‚¦AxÑxÈ^‘æô8ièzèz‡Äìôv‡ âØä4ÿMèÝ‚[†öh:Âl 0˜ˆj„²œ G'jXÚ†Qß:žÕunu‰£D ñA-i:ä"ƒÙmî¢7 Ìsºv+ã€`Ȳ#-¢#-hØyšDSÙ,÷½ÉDÂ<þÍ›NÔƒÞÁ9¤ï¾“Cc€p–oçÐè>`¡5–‡;mµÀ㑤t`âŽÉJëz 8J»½(LóéÞZ "¡h…E pj#'ÓŠ›ø†ÙaÖÖGä~~ÛyFs) ÔòÀ¡ò„‰rÖ òÿ½Ô©ÑppÍcbGÛÝVœ<ÿ«Ù¾ýëa’1 ‡_2köy‡Öt¬9#÷&w$5…òaãŠ,ùýøûë×ï„~çÔÚÃ]Ã?OˆIœ)u&ö.ó3þØ5LPÜB ¿æjçÄð’Xì÷w_·IƒiÝœ]ÅÚ%<šZ@€œÀÁQØÍ½Å‡«LÚÍ[­0IͦTG$3ÛEqé‰d+Ó3D‰¢ˆ˜c34D0Œ.œ.®ÁGYãúÊ<¾ºˆÄiä¨eËúÕ‡çJ[$ðžÿK^q=¢f9ºö úEýßÝÚØŸÅ8ÿ·ÇÙꨰ/Du ‰¼{4ÀžÞ ÷g–CÖ}É~Ïí§ñyô|ëÀŠ{Ð:aÖ5Ãù'ãÚgiÆg =AÈ+À3—^6©7³Ùcù÷}ë‚î®xY÷Oú–m6»¬ç õ*1äš[ûdKî¦ß[ÁMÊã `QAP”ZÑ¿Ñ)phÖĪD°âØ¢"e(‚0Dm£Bʉ´!æðGßÔOŸòQÔ=»ƒñÞ^LÙïÍäàHC·iÛÑæw›WÏåƒê‡k¬zÁÀ˜Á<ºñ”ÞØ\rÀ-˜d )µ£‡]džƒÏ¢lòšAùÕO\háÕ|੎“®ÈØ7WÇ+}]±T'.'êfd»ÂP”X¯Ý¾oX;%‚$Ø–«¦í\[ÛŸ¯£Æ Ž«g³¯}¢Vi‘œxkƒÚ#1A Î6Cà3Cš9ZkíN(j˜„GßÝÊ¡þÖáÛëÃM;7Q-_Ç×7–žgSêÉœ †Œ&¤]¨Jþ.ÃŽ @æùç[XÓ'I@vp@êÈsã˜U¡0{’Œ¶p}g§PÎD¯§@ÖâH{…C—=¯¾àlœ‡¢ ÿ}Ã/^ ¨ä?T*6©Ó׎ Èù¯3ÅE­g#o5ûô£× éP[„ kÊ͆]jÐ6Sî Û¸ÎWºà3(5ÿÇ!~À[ÁYb÷•Mñ½ö ð¦H *»Äଦ:G:ÿãùúKÑî Ãv<šn ÞöÂDÓ™s"¬Tçˆ3ºP'xâ±d $sö»¿öŸxö5'à¤]#óäÝzYs•gÏ!Dkîœ3:!.@ÒξC³ègÃIú"t$„÷¶|b{–H‚+T`ˆ¢(°UX¨ Œ#iF,QHªˆ¨"„UQ!Ä„H±Œ B8¹|îÅmöÅÿk½ÜCL3B2ŽèÜ©’Dç™®ñI(±²G›ãŒÔÄ—âî×ÙÞ͈n+LWÖ*[ÜÞª•ûß*”‘ã¿|žz×îûèsÒ;wPáIBŸTß4ìqÓº°»d§nv±Ž-Xƒiz[¤*9=®Î¸µÅGKˆ‚t£:EG‰Þ†aíéÎ6ÿÊßc:ݲgî°Á™¢õ3“.Ã¢ÙÆåÜé^ü*·üM‚R4NàñÙ¼ôòôóƒÞ‡öE_Ûþ¹qá´c»È×"cô^§ð—¯ùb bCܦVM«¤š¶…U5»ã¶ÿ—÷ Í¡"*×™ë~.áuÓíIñs£^˨ìyÓgptü­ 4ÞæŒŒÌàÎåJçý^ð¿±hõgѯœdÑÞòåw)ù¼C£¾nñÃhß«Ä4·H¬|Þðô;ÔGÑêä8ËÖà€yÎãîÊñÀ>ÿCBß+3”£'Ò1¯ª§Ñ> ThTŠ¢«@¨ù‘íE[  ¡¥¢»Låߨgì ¦ð@~aÚlÓßŧٸ 0l ùPV$-•¹FèÇÒ W»LuÕ\Dc˜" ZÁ¶ ª½r¢í£ÓgÓ “'éeGMÙÜH=Õ*<ÆÔ3#+‰†ÔìÙ‰òê TÝ-0£÷¼>ß.¹;s>äO¨VÎaØÌhï¶ÅGl*=²€¨òû3½xªaܘ…Â|¹ßḵ òÓÚ@ð×ÍüìCo @dFÊÁIToŽ!Óð…F㺎¿po¨6:Kô³QƒC(ëp´l–¾²[¥/Espóf-¡/6 N!!7Aœ8ñËÝr;qXÙMïžG½×¤'2¹3 z$€Æë –¬ðÏõ5w§Çˆ´m°s†f0@ÊíêL¢4(3€04˜|žÙ^õÀñU.N^¶\„›u¢×§Ü×·³Ù”ø[±T«’Ïl_ÏÔ|¾t:Fò"¸õhú˜÷ãÂÅ`€ªr¸¢-!> Gªš LmÀŒä…¶BĈ ¨É‘š½;xVÉLʱO3.hì]>4R¤5S9±ðjÆ;O$ñÁüöV‡ŸBn„8zÒB‡â`ïôîSÀŒ‰œÍd›9Ìë˜ZÄ_Vì›çUµ†â³*:ÇÔçcZŒIHˆ!Û¢£wŸM‚–¤Üc’.Aå©gy­µ+|—£rðGа@ ñä´šç©Fmür];lûtíÆ¾•D‹ào(Ož-­Ë¢Áïé^¨1‘êD¾ ø›9´ü÷µkÀ!b„BîW*¹à§Ó¸#ÏÏcÔV9"¤ØÔà v݆æd-õìR""$Ö&®š‰;A¨&¨Ÿ]»]Ú1wb˜=è’DpF3ûZûƒ4¯]ÛªÒ"Æú:¡á2uÔ·Uê“Çà€œ™É{+xUÞÕ¦c%H½ƒtrH6…BqÄ/ë|ìS’@ºS'obl|×?o¹Õë{]^ß åžS"­ABÔ}[ß‹®O7žœàºëœÌ9{lñ±ìˆÑp‚0Ö¤¬‡X‘al-”÷øtÀTˆxFÿFsÌ+ë°6UÕý4¤ÍeÿsÜ-›™Ó¥–"Îù—p}¤ÒrÙì!؉}e^5¨­SCû ÛÃMm†ýÉ÷6¬ztÍ´¶»Mk7uK ˵ڲaƒ›~ó 5×ví²ëÁŒÌ"&•Ü[žÛn×mÛ¼%[l!Ü@`¬Oµhäߪ•ÜŠUe?EíRhÔãÛRÙp¬V/튮ÒÌl´k¬j¸…îA»nìÛ-`ˆ{‰ {¸ ,mÊ@¯= /¾Lêxœ¯×¥ýShm6½&}ÒåySǼÖq¶ñåAH¤+|óðP¶ê¹ƒPî€ " Oû1„ðõ>&-8Úc°ÈV|x=@Ò¢4ê¹qu¹ŒÏÔ{¾dpò_æ1|¬ ¤ŠÊõ— ˆ2><½2«WGZ£éÚG`1o+˜ëÞAp ¢@ÂÞ½gî ûÙ40’‚Ž”sá­EC+@ t%ª2PŽA¾ ãÀøšFSR½ÉUÉpkV±§áwØ”ËA ‚* ¯Ök&x -8©‘4¤Ùíƒ(@"66W¡ÁùXwFb£€Ñ{HP×J À™ QRyâHpó#¤Šì”®z=¨ýd X‹UäÅžd ä ãv‘©;u æ¸Ø@NZãà̦.¸Tôð47 …B;²´î~¼W®x½Ÿ B®ëLºµä GLÃiÏd¤L´ŠI€e ×6 ´¹‡àð˜Ó|j…èðdCQ•`Ü``ɵ•à4EµNI¯TI©pQC„·[¯E¡äç^©ã§Ê­Õ}}Á1µÃă°‘wv  `UKŠŽ«ã£ ˜ÀÊ4ÒÊj­L#ŽWä:ÀqÝQ`/¦lC’»ó#“nnUZ>ûÉÓ3— -”ð­ )’6ìb¨Æ›1|xã³: ÖðfXlAÌt;ç›!#Rʸï,†ù4 A‡©]yh! ;Ô è}Ì 7V9³µikÇtÃÅY§0LNñ`§8 ‰§–Œ$†Í’ÄØ\9Iw `@´ðkêÁ¡ïs TãW6S©.¤ÍAƒ.}m;¹*¾n áðÌ…`ØÅÇsj1¨S€ç(lS˜3åÌeL‹\‡Dp¦• §æzÌû*²BñÇ*`}®F  "ËV­]FøS$ –à·TV¹+l™y‘qÝ£Ùø;'‚8¸¹öüñ½ZZüÿN˜ð˜ƒ.pÙÉÂÅh q3Vµ[c0¨ãâö=nˆbÕˆ }(;Ü ) ÔÅ-ÛH]ª ÆXŸ[÷ùzâçrRÄšî:è3”0pÊ8’P† WíRÞ; 4Œ“[íX*òÃ< ñfÌhüâñPÓX3(ÃÐÓ-GâX-os}€åªi8‡«ÚòO/MŸ˜óæØ[c-­ ~!®ƒ>™“ƺ-p=×.aØŒ…€f8Ë,óOLPxkÔW%ò¸ZQ䃵%`‡&pÔ EáÎà7L…*BÓ9¨ªuW¢ªë5“•ö3ÐBf0Ú,Põ%9LŒŒù&¾ÉÔt¦zøÎ§ :’èÁjUwŠ$vàéa Üuèoz…(Ö…]f„„`Ö)« Ò ƒåÞ>ÿ y”ú™©ß+,Q vVr´ K¡š&‚š"#¯ç¨w–AßãM EZ»×Ý\7Ä:ÀÇVéŒô!Œ =!È5ivzz§u´ß­·gçB¿4@`aáÈ Ha‹½±Wº?¨á£`îƒÇ©Üôž:ª}Íýb£ÂÊ£‘ìÁå•&M„»; q‘7ÛETç÷·F‚‚)) ©ª ù+AÄâåvŽ™·wîYësÇKœì-ç—eJ”ÛÆ†ùd]¥³I¥Žž;UÂê«ñwø.lu7þâZBÐP)+«Œ t¹ÍK# †Ó¤9«žÆvTñ¢•]Ÿï]<¬±Éöþљ餌±‰Ö,C¹3d£þ_¼ZÐÒ}ÕêÆjþ´A忍]ЇZ ëð/‚uƒÁÃz¢!èZŒÍÞ(8ò ÈÃ|'÷ïäž:wH –eyŸAãm$]UÝ–YÕ0Eó >\{•Eà““n.ÖòKlܤEYí««­¬0f ÊR12Üœ‘)ÏŽîš›‚bÎD <œ@aìö¦@Tt2b_(>n¶‘Š·'¤¸Ì±ö0/@9q  'ÑG¡ÑÏ’r;¹@¬ÖY›{|âxwO”C7 cˆDÝÙ¶®D}8p볇TnÝÓy6Š`/܃Y"GfñΜŸuuÝ÷í;õ‰`àÕ‹Ã æüÌ•ƒøwú¤7†B°UØúÅ95´ëxp’³@g¯êE›UªU)i°Xá˜[„õÚ+¥ÂòÜT6Þ0ˆ7wé0àfPQÛ¬´`¹ÄÞ¦ò á„0ôðŒ5 X¦D4òA¶**‡ ËŸJ«œɃ¤úˆ6ªt³*Ð÷ sY¼+ÈÛ®zª¨?07ß  úykààg~Êú“ t¹B&c„ŸCŽÛ¸õa£1(:æ˜×¡§l\Ï» ¦ð·Î˜]ÑU¯›ì”®Ï;µÉ¢êEׄ3³uÃtïF†ªc2…Щ¶Âá¸ß0Dl‘ †y"ƒpÃ0—UÕ@Y'u7Í€S†f„ä¨ÜãK-#m{Pk«ˆqÂtçÛÖ Ï’E \¾ÍXõya?%‚ÙŽÖN]©Ýæø{smÄy—ÊæÂ™‹•ªÒí±ämë}™‡Ï6(£ˆyšlúHHJêÔé†1®ÔÜp7O¢dç ƒ@„1"EûHFÇe„ðS:Å«-u4`â=†y¼N]Jðã: ‡Fêâì°­¿;Ù,J&ÞÞ$’"Ãv ¨ÅùËóèuŠ9‡¬ñ}Û¾|ß“ôëwØ·ÏæÆMW—^Ýp<­zRâ`Š1øºÓXåB>A**’ °Ã¾´£Üˆ*ý§Ü^P}Ùv—¹éC€„»˜ó!¬àSÕÓ˜"¦ z Uè%CV¿«»8Äâ;CÍX¦øc½àOÃB¨Ú-8­ÍNÙH)—!TÅ2ÔöyéÝ™ŸH†‹›*vÜ(e‰Ü9ƒ 2':¹á)ð·ËšyUÝ©Ògו–ZƠƨi–C­BðDi¬lצ–ã¦)_+RÛEû #6fÕ²‹º&½‹ÇB7ÿbOy‡f—.ºÁ=°àñ‰Œ7ETvóûw)²íûf¯E>Ú¼Œ@õc·Ñ!P=ÙB…«Á<Žç l÷ xŽ0ˆS9AaA|À^ðÀ ý§^RµÇ>ŒövðèΙÖÖ÷ÊÆÁQÒ1u¨&D°»p±¯.ë‡tãZ³‚³±0V«¥¢_¥‘æ.¦|VËsn£ý//?»(ÛCÉfðM‚ G˜ Ó€+aPp¼bU¼× Ç»«\€àclòP^603ïü“d„r.þçy™r™ 3€Ø+'»A¡.žT]¡–)›ƒµºunƒ£fï!LÊLõaàå[á^ªD‹8Ì & 0 )8¬8EîuŠ®:¾s¿y&Ìgà­e׌%ãíæÕKâµ]—íáxzŸ[…t7¥¬UÎÒ¨Î4¹ÓŒêe–¥®|Mä¤ëÊ«ç‹Ë}G>ÀGê.H·õ@¦#¥.½OÙ|iuþ÷Ìb¿OÌŸˆ²¶‹ÓŽÖ„¾äRŽùç_c¤wÓŸ,:æ<¹9ê»SLç ë¨Ÿ”Ž*ìsÊ9?UXO¨º[^·âŽ,a»]~ î'Ë*s¦kR‰¥`ô:øÎRS+ ¯9N0ªí•PŽ/59(Ê1SÓª_·ûªGLó^¤Ÿ/ì‹ÕÔ?áåÇØûn§»rI%Å|¹ó£x>gÖq§WèŠ{ºwÞžyÏÀ¢Ä·t}̵9I}}¾Ñí{Lqý‘72šR‰]¬Mê$a kŸØ„ìtUeeÊû+ȃ9,ל-›j’ÖÁpŠJ§UA[ÑöúÞMÝè"â<;7ÕÛ>I⽚AGòàæCxS¨+”IP´¼eT;Ï'™°âÐU6aß½¨óºF ºr¯ŠEï®Ì©'N=Aq<9 {˜Ž_ ?pèEÎ|R³`W 1Úá°€ªä !DŽÐ¸laÀÒ"Ê @2¼X·ÑÑÖ‹7t¿ÈX*¢5(Ð A•ŒÙßG€ôÚîå:s¡k½/¶šC”ÚYÖ Øp#ä1HÀf•ÐR´DÙL›!X )ƒ!m€‚¢!ïγ޽˜ÓqyI 8EÒ1{"sÁj¥¥fùˆwµ]ö€p=:F½Ó=Ýš–/yÞãªæD ন¨³0!rB0Wv(å“­t—0â!á°Qf¹ 0’*©…É@€lÃÝá8$G©Ü3ÏÐCÂîAÜ2ï\“7³OGÃòÌ»æC3½VùŸÐ6Ý÷l×ñ·cËî¹wœKC‰hßhì2ˆCº$¦eÙLO¢z§É?q3Ý3Ist;–ÑpÑÕÝ)…›µR©"vˆÆÏú„ët¹ðãšÚi3¤ÐD0O7‘µi,šÞë¡0P‡LÝα >Q˜¶tº¤‚À®>Vap!„“îÀ.úx>›J íÀ„ü.èϼ`jøòiédëñóï2n–o_ b¨¢µppö1Þ:WÖk/yÛë­çi¨]º¯¯’ƒ„^ï Ùë|çÚõþðTw»çÓ( yà=C¨ÿù‡÷'È™¦™¶ÌÜ¡c‚¿”I ú?˜zý ¬¼Ç=ƒe¯³Ææ«;exDo.¾ã¸¶R{¿ð‡Ø·è+­jˆ’Z¿‹÷ì>ˆ§Êý)Õóÿk:!ý;ÿiG¹ØÑý|šz¡ø§½øœÁänU2ƒÈ…^°€l0@~®7 ïn´ëêåt/ÓUûÞúõÝq@õ •±~fÿ ñÀÀªm¢UL¯á\À1é0.0O;Wg©…`ØÀåT™Šæ&¸EÑØˆ`ˆY/çOáRúêâ nícØÊü¤3·ì¥©b!Ç=:±¨ŽÞ˹1¶¸ëãÌ’Ç~ήšõ¾÷£SÛté¢ó¥d^äªôFt~DÚ ´Ò˜)J>÷o9U3å(øAõì7]V-qJׯ& iå:ºúà'D=–1õÑ[ºÞÝrѳÜñ‰ÌFåS(0 hb½aØ`䵯ãAˆGèöyôvT ãoÃí_‡P6ACá4$CUÛ{úÜòàe\Ú< F™*˜#N»˜=&Æ ó[ý×8’ð=v­Ðã¸Ýn­q¯TxŠŽ¼¾US§®ú쯈;׆=r¹ íë–¥ˆ‡ôêÆ pŽôh%É…°»9¾Ðä‚‹¼A“îµ$zHS$@‚'€I!$Ø$„éÞªªªªªªªªªªªˆªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª½„hTz…GÆíìù>M¾GØTÉli‹9½Ú¶•žt\± b‹ã䆶!‚ÙÒc¼ÿëü¿¶²?ÂÑìGÒJ>8ùC|A÷£ß»H>Púaõ#ÓZ=xó‡Œ=8öƒÚ`?j<ÑëG’<±æl=¸öƒë‡»¼à}ûAîîäÀå}xüô÷cúƒÕœàT{ƒÔò\£öwï¹ûo»éü×?½;Èu¿þ}<úUÞŒÃî<ßšªÓÍáky¬j£Ûç}xöTTSq¡A—™ñÍÇ)à‰b$ޝ&”ľ1s‡³þŽøTx‚£œT{QëNˆëG¢à¨îüMÇÑäwWâ{~·ÑsˆYPû´¦Ì®÷=ãªä¨øÊ¨1dpv=ÖW©ü9†ÐÞêÏÇUO)}óÁ¯”Y&°_dÓè²å[“(þñ,Î8m£ [QïÏ›ä•ÂOÎÖª™Õ ø ø%·½V˜O‹‘vœ±ñ ¹„U”A*Ÿf£·Vz³õ³Ý©uÎÞßpiŠ ŒTuÂQŸ°zÓÅøõé4¿ì¨ü›gÙÈü’´­«\ír_5³#6³y»¹œ|ÌÉÛ|Û½ÌÌÌÅe¼3dÎfnîëèÑ»»»ºnèó¯´Ë^êgwœææVëMÚª+‹¢«–G.󙦕ÄÂ~VÏ9[Êxf®[­šÛãéwwkhË.bâF­š„^øòîÇO¬/6»vmù³•s’Ý.UÇ—ÒÝÔàÊ w$ñ„­HW‹Ñ :/U:MH6TØ«©ëS)™<_Zûôô4Ó‡ûù8ñUUÆR”¥)J0{'J.t^÷J}¼@ëâ( ­ÐAd<˜‚*6°Ð Ž`ª0‰üˆy\PªŠÂÉ ùVH“¡* *ÕL”ƈ°'ôÕ}cT€°ôô¸:šDºOí‚£L$„L¥"ÁQ‚œ Rƒ'‹U$„bûí¨HHI"¿-•@!ŒÊ ƒDøÉ#$´»gÊÂNŸe%0¼ÊBå Bº_¨ëA„¶Â/7«_Z¨y2C¤ûUÇô#ýœ,¾ö* þ<@GÑ$ìH€@X>2]$Âå±’çS_­,²š‚5 ý7œÏ>•æw@Œ uµ€Å&Œ4ÄÇC(°Ôh±Ð¸râk]QO¡Œée±°ZM±¹,z}œ;Š¹ì§®Ñ£l:íL·ƒ^'®ýK· ŸÍoð{ÜŸq‹¬ÿO,m–OÌœ›q†à>×+ö çßx4B,UUUTúñïóY¤SÍô{´jv²‚1¬²º¡Q•”³rÅ¿ & ½(n%6¼MýªÒ^užï)ËÞ£¥]b}¤ÖÀ[‰\rà(Ãc<Ó¬2€°RmC}Ëò­<܃>n5ŸóÅÝý`\9ØrRât1}ôóÿâé>’‰ï†©p¥šQShã?¦×˜_/;(¼¤WäXÏ’œÓSqŠ[X֙ơñ-ðþN<¯Ë—ªÒL;G³!̬çø`qÏS…O½)^kC}£TøÿHÅ­êÊ&­Ö×»—`÷æÉfÞ@€Ÿ T`(´*;Q€#¿âÿãö[õ@ðýŸ¿ðú¿,Ó×]ÛQ-ÖÑ$D{¶ <FßRên·”IŒ$#v[…›ApgÞš]Іg4Ê^ˆzÿ¶(X²•;¶ì¨*4Ód ^Ò9¤¾\`:±¬¨öUq7삵ö¯'ñè}åÀÃò\%8b᱊úTC c*õƒˆÝ¦lPâ?öfÛrX“jP[Àg·»×˜Q5\'Õù‹¿s¸4 ¸ÏZO"Ø,€ÜÉsÜO€‰`-8Fä¿Ã–ªpñ×ø@•(o¥ß.ÒT%„$BM^_#, ‘€ fZ›M#£¡Ë€TCØþ‹µã^`‡‡†ì%Þ Iyßi\§q­’ XvÁCû¾§·›8d‡ØüÛë#¬dêgÑé3è†÷d"eÚ‘'ÒIøôd²bsþ×íé±ð8¡þ….1T‹ob|Güsý½²¶ÐV°c ¸ÍàÆ!ӔɘAññùòD–×ܹ}>äKK‚p"¤dçSEL}1D7öàLcŒ"ßè›îÿSϤÅònÏV~0>¯Ùø;Ó¥×™Ù ~Gûœ)ãÔîÜæû´’y3û媪«}„?ZLb C «ñ€+]VÓ!לdÚ,AHÉi÷84fúʈ?¤äýxú@ÌðÜ¿Ã}ÙÛ[hP#YÖ6l Ž=ЈOBÐmèz·ÊÓtú¡§ôƒ1´lq GŠ8ÍMá&oº³g\È]üpu»³'õ³Ž¿¹ `À.¾* yXmZÙXB,ñ3ˆ&ýû´`ƒg䈂˜;`´†}(ð ÑõÕn´Ìrâ_0AøÆ$+Hõc«Œ4Ÿ'¥pƒƒ†«±|@Z¨?œo|xôãNâ 0a‘ç¦E†²˜x-Pb?jˆLÂOÕÜ 1‘ŽØQ.0…¨Ø3î%C{€ç·Qz¬8Úãr)üŽX"힠΋C;> ‘´É01&Òf¶êÞÖ$…7È…4Ô8„!0¾/e«Å}âÌ;‚X˜:ÑÄ¡n¡ÕýŠÆ3ê¯vi.mÀ{1'÷aG¼Ï o«±Û¿ÑÏ"EI$2U$€H¡ºøž­Ù89KÎ!–O°î±g¿JUDëEc¼o諘@^cC¦6ÔƒúÖ H< ¸ìsNo .„ÂA¼”o»>óW^`ÄÒ:…IJŽJŠx[nï.×£ Þ³¡»b!øß©ÿ9ï‘Ðf]ç·nñ¼Rh]^4™•–Õœ¥_ÝĶÙcÕ ÓÛF¤n“ø>em2ÒÛi.¨ô/-èoóž 0Ÿ{oEkŽÝËl˜/;Ïyùø+?/ÄÒ»•~€S@ñø F3öîv«ÅÿÍõõè·Z÷Ì Áƒ5­Ëõ\n§?`üí+À{xL¢²InÉŸ_Çoè¯?»|½ùȳq«BÌÑOÑÿ?æþ³øÏN¤úŸœ׫ë±Ç—æ!ãOû»khj(˜˜üµÇ(|m§ûë>Ùýœ‡šaÆyC¸ðßeˆž0>ÉßkûnféïãÍÇ¿>Huõ°²M‰ÐÝš£AÆ{Tl©ôpûNZDô›åo&l:Û¼]6CRofÿÃuÞCbÅ‹emø†Ùðr ä@@ü@æ{åŽKÅV ^wj€sÄn˜‰&üÿßRšh?ä–Δ²é;00ÁÑë~š¸æþ/U$ï†Këùv6Ê {l|«K§Xý8ô}<ª|M;«…øá×%ÕØ/w(àÏæñåŽ!Ãí\´qðWÈLo¡ÖBFßîÍ~ž1A£ì‚Œ:AkRÜG*ö¶3f0cO.¹Õ„6òV+8–«ŽU–Æz[°©Ê’ˆÝíW 5ÙlF»õà992Ý®¼´vÈXb™ÂGÜÐ1ü ö ƒú0èÑ `Tþ…H&¬t z˜¡˜ØP€”‹¡¤f›œ•„"¬ë,•23õùrˆñê±i”9\áÅXµ¡¼6ŽW«‡L­|ê<^Ͽ˹½XèåÒ=·ô ¬6Þ%·fϽw÷,Ùùáâ×AÜøiír(õýcá3ðrøîØù<`áØ¿…â·©~ëzî?wvÏ»Š<a+^º÷WBoÃ#LêA½=wãߌ<þ}û&{ütÝá³*­žëX°XqcôuñÇ[!»£ºGE«Ù|ƒLrqåËÍ^ò«gkZK7ݶ¾NiY! ÇôYØ-üT™ÇÊÜ ´úzÆŸŠ2ý?6ÌðD=ú!ÖÊ4Hï]U@ŒÌ¤ovœ|E~çuʇÍ8Ö # ûéæiNÛ´ º«õ¹ùôêïBÆ9?œ0±:§Åס„â• ùÉÜnïÙ];c;.´?7ŠòíjíÝ':W]G‚˜°w»}uêçõíÐYQNrÊŽO>:[×êÉy=yÇ>ÏÒóLÓ¿wiÚîôù{\§ÆZuvSgnåõÅê@‡1ÄÈezõ@ÌŽmûµÀùéÙÇ#„bl Df\'1`.UÒ|lOñ¿óø¿{Óº¾ìWYñíçŠ0, Ö#G¸1;οàdê£!‰…¦Ì•¸¢×WlqYDˆ ³*HŠ'¹ ©‚ägX ëÈ4ìÏ ³c^ïþË¡©íEÆ@®éÞ/¹÷ÚÞŸ•Ò|Ÿ‰¥y$ô‹íÀÇüŸK¶ô8‘12 zŽ»!)ÐÜn¼ðüoEÒvaà–éü½ Õ ½ MASëûŸÈ?ü/ïrzd_8z`ý?¨IW0‰‹ƒƒ˜‘È+Á™Á«šÑfnle3·N±?>,GûüΧùe?[ùŽÀ˜\¬`F«ˆ¢aÀ°ÔLƒéd=i cU‡*òò†ŒTð' ‚¯ $ÐOx¥,v)-D˜ %3\{¥øGƒý¬s€#iþ9ø~©Ç—)‰ E£çìFˆ@†  ÕB¯å½‡o3’± ™Ë&4ÙÕn…§³÷¿•¾æÌÞ''õÖ[Y¢´¹>‘ߣ®çfN0övüþK4ƒk¥Æþ®öõ¸£©®)gÞùÁÈêÌ,žXcCJ¯yòV!¹öhZ>»¤$xoœj*gµ=9æ -€ÁÊÃGOw&o1äÓ+—Íípz-ë‹&01ä€E/Y8˜Qo¤…†u•Æp13~!½óA¾pbM0‰žõ Àðý §ð;ä‘4?gîwJ»ø?ù|’ÌnOéY8é?á©ýò?ðDæd=Qqeʈ(‰Wýˆƒ3ñ3Ž3áܰƒèEœ“Ú\>ëì ÞžfØI‰~»¢NÃ/wÅus1%bë¥3YšsŽ3÷Zõ¬4Xm€8Ub⪩õ_Üþ÷ÕÍóÿ#W‚Š~ÿ_¾ý_AÌçòþ·ó´Þð·û»u®¯yÒu†ã¬§,d#ÃÔSÃíŒÚ'‰ã:L;ÁÜeô /Âv~ž¶«0K~ì²ïØŒ†£r„4¦*®@ã333ÛßÞÌ Á¼ëÕæªÛJ–X¤¿>Ž}XïóÛ¤’É H È(m‰Ó>µêKMU§æ|ÿëù þ/•ò~&ï¸×·V¾^Wvv_ÀËyƒP|T$UG&ˆí¦3’ýÉö¡2‡›oáâÿv~Ì­ëðuôôÛ¯ oÆÝßÛñ“¡µD|Â˯¢ÝrKô _HpvƸݼ©b#gwÒÃZï³ñëO›·}Ç€ûøäµa…§;d³€Á»ÈUîÛ²ÄH¼%ÿ;þFˆ÷KÂËxüÀÞïpr¤cÏˈpås"Ò9Á8 ´6š¶‡óøtnçêàÄz_Kº ï(9Äælœ›‹Æ›!®ó—|œÊʪl¼» ¬¥SvÙò…]#Ó3¬lËù¸Hç’Ì÷$#\ªçÔ?Ñ®6\/wàÏ›\nܧQ•âcËj¢‡‚“úQNÞ”WvºÊ4ç]—:Þm1Q9œTÌÁB¨(¨Õ¨JÅqýBØävÓò•xÊ×U4c†•`ÖÔçÆ¯¯6¤ÓtÆoÓ©4üpGÀ(ZcCUf߯FÙˆ¾½òtÎ'_€äéMD /~CÒ¶ðûXº"·[nè}ãçÉ{©ïññ«æÁëc·:†Í,š÷iÃî¨ö9Ö«§R‰xÜmÙ¦ü¾´àö–Ö‹òœëUk{Bë¤äæ_Ö¡lc1õ»}ËÇ`¸/fZ ­Þ+Ný–óû;_Nš¸˜à¿Ãìâ3¼75éѲ̷®‘·AäòëÇÇy¶û½ÆkúPITHHÑQj±E'{1ÄñLóo÷6Hžq£ÇÜQ˜"#;̾“üê6cˆ¦•vÄ ´%neL~š¯ÁøyüÍqŒÎH~íR$;º™ƒ×±ÊLmJd,£¤H$Õ ª‚ÇfÁTX°d]ÚÆhŒUDbù©bœ5ufRù&;ºÉ0Âo¿æi1¸ße½¿kß­÷´8àÃ)H¥´•©E-ž–W/êç×ÊjEóÞÐÜ,­ÃÍןí=óÖjxù¨szƪX5Œ`²µmžGý^û;÷ie¤;ÆO»ÊgÀlf¯L êÓOWÀŠLgBâŠ59E†bIsg£ *H@Ïe–‹—I©OÐÈ&êª!Sú h3 ùþp™Ît‹”D¤AÚD€ŠÄ¨,ßÓî ·mQüÿ~Z|ÝóìjAÅ$ƒ} áûTóí’ººø¶GQT† } 7–Gô.“fU% è“ÀÀ¢4°uðaÆÊ Î]M®² ›8©Óë"‰ÄaéZQbOß;7¨=*ÕïzÔècE2VcVDUö¡¹ÀQd—Ø*ë]Vnµ]f­½ Çj[†eë:ŸÚè*|Î gîgnu>ÙòáOMßÔ'ÝycÀ©9±a ÌÈËÜäÎ`çàØ;Økï,q|m'ô;O¡÷ºùcàöcÞ0¤/1àŽF§Àž@m2ÜaÄ<æ/˵^íÈü%Ъ>J½Qʇ<¿\®¹{¡²ÝÏîñò艋v¯oÕO­èÇÉ“ øŒ Øñì|Quú<ý]»ëMæÛ>¨¼>^O€¡é·¯UàTYëP@Ìp@„CUþ-ZÖ\•T×21Š!»<¢JÒ¶( %ƒÿ~P‹@ew(ÑIØ@60]¸g7‹J×®b[¤Áˆœi1wÀr¥L—P$b$lB»wOŽ_°•×wbåâV-Uñn7ÍךÔs¯ûÒ:/wŸèøÁÝ|¿y] ]‹b„ `w¥¹$Y,Še!P)|Õ¡ ʦ1GVO£áJi¢Gdsð¿Ó“2)éûê9ð> *7ˆv'27K?`Âú˜PüÑsŠ Ð Ü¸„ôsŠZ*??aÄü޼Úû¢Ç/—v )çuK¹îQð-Ûd¿™ßø‡M¤MtÑ–‰¡$®°ÿ1œ¾ÐoòÎâÀq†žtL$f= ¢Àðºéƒx:›˜àXi(cGü»ÁL6Ž¢4P8¾Ä€óþ„ŠÂy7È…6á1Äf³çįÜØ ~/§' ]gýß|»g+ Vú»w¸¶,–ç–éjh~+pÕ÷Gx¨§®8ž/â¸t7ø]‚n‰ó­dÙãz{gúšë÷W 콟ÖéúG›ð¼ïqÇCÙ>ÈJ9fï:?cÔ;ܤßuÆô×@óØŒ§[  »=­zž‹빎€‚ézó(ý5»WpvZ`¨ñ(EGÑ߯3^`+’nMnç:Z\ïSÓny2Ó=ž†ïCC/7£È&!ƒŸhxw­9Mäd`Æ™¨D a1ŠŽÙ¬K·ü.«bšà¸#‡TèQW›!ØX˜·Öï/§dí‡pÌï;ç˜ê£|Ìï0ÕnãpÖPí¡eDâ¨ÄfÓ0¦a€>ƒjâ¯1¤‡ÁÑõyuA2ÉÆ²³.<ËD=G‘­²JïŒFª2SHöñË”–Ôݲ.ƒ (€„ (( ÷vxC½VpSK’MñêU©ìªÔ‹{ïKÛ_;½–£øF‰ê´`ÈóÀß°±|¿¨JJõ†3ÕØUý…Êp,U%3õ(é½ût>|>úgjÅui}6üª–àÌoÏßÒ¥I¥8Æ"§*Ó)xPvô»¤ì÷¾õª¸|ºl1òFŸga„íÊ~ÖÖD Ü.Yrgóì÷žñ¿mÊS¿Öçé?3½Hᦖ’»½£0.Œ˜Ú©ôù“µ }xø:GˆÄ*Ãç” ¿ÊÊ+ö3çáÕU²´<úºíÕ߆ ©Óò¸þ™ÖÛiß™}P ‘Œ£¢ë—ÅŽ:(ø7ÜW·ÏÚŸcÍ%Ä)‚´&þÏ¥'PRQ/û|zÀ[‡ñØ™¸žqÞ1âKºŸL=7#`ßIú½NÔqòØ>A,èrutYxI$õ/òSóˆ‘ù¨^ôù‡÷hk âtKoãcÞŽœ7¾+” C[£n_ÆUÄ$ÃXÝÈd‹hÒD¦ð÷œË`«Ë»W ,”Äb—`*”ã3 ʹxš&ŒoÞÃeÕI¼géΦÑhÂòš‹§F&ëaˆ1Û )\í|íNwÊBêL¥´UzçZo»µ¥µUMvhuµIr¨º¦n,¥LÄÓ¼Ö˺-"í5ŽÕåñR¬'¹G`€A î2`´ÀnãSlì4õ¶ˆ¾%Ôâ$.ŒD@ãºMl#…ÍA[\‘]™º2ì79nÛ;4×-Fưm0’HvqV§ãÜ6¶žÌ‹*´ f46 ¢½ãE¢k„âàE$ˆ’d¸ÔdRP‡ ˜Ãت¨ºÇgI ©¢Ç¼w„A¢%G%©ˆCc ¹‚®$‡²¯®ÝäÓ›É ³—"Q,?aw“~l‰ü8læð—51ªÊ¼¦ÃD³7î¼n޽×$ïÛw >‰xˆf"S´ž9)£½í®º÷˜5”wïצí &jìá£>Š‹BL$$$ÐÝ9Nä#—#2)kG¬ô‹hÚwbž•3ˆ’›0.4ÆK·-µ¤Ð.š)ÙšpáÜ;6¢Jæ…"T]½ÌTMò™÷”r9ÅsÖm‚”Î’‹(º}·ér×Oàijq $6!Ìm»`«JœI'§$+w›hö‡¨©˜"ÕÏ”%/0(;DC³c\Gj··WŒå/Ê‚Nª‹rÛC[‘#Ð3ygBˆSÌÄUL€ÞO2‹Tî×òÄI ̄̔Zâ<òÝÛøä4DŽz’ý>fäÛÉÚçlì¯Õ¡ºN™8@˜‰pi„á"g*6Þ/ÇSS0h× £»Ë Œ;g.Z5·^»u5h# ŠªreÄXtM‡´a]é¶©ÃGhÚP£AqÙ›±™˜nvsŽåñÅÄyË.ªÜ«£Êbs7âì%÷o@¸Ué Á…+ŒP¸—Å;@*(ç6¹JÂîßTpñW:øH‡‹¼ès8pUÓ‘Î&ïi£¨$×ÒB"£˜ãÌu”h˜XQ$2‰hàß»Þ/£›k¨»ÙgÇ»>äTÑnw˜÷£ú>—aûxÍR©Ÿ˜ó_Ù9TUõTvEÀvýIö™—ÍæF£°*: -Å ,£¤ à*4 (TqŸ»¤ðº1æáÒ­Û^—Aý§³F)Õ‹ƒ+ƒ:($–(Ò–U§ä‹3›±2LîVA‹FÄrâmñ梸ö.WEð’K$“ä Ì6u’úΙ7H1Gñˆ ©Ž0‚/©©åVœcrhæf_&c2&…ESr·…ÝífstÝ8r§*$M†±›“[»ÎnîîìDnÖóœç/œæîîîîì³å¬Š.Pܨ³³Y­®îÛy»¼ M¬i­ºÛ»¡­Æãa†]îeÓ Ó‡ÒÄcœ1¤EŒä"ÂÉi8gÅ–ÃX[ÍÉ$n5 Æ8Æ–Q' $áF’`Ø`æaE ã>”9MPq¤c[^¶5†ÓSa4Üà ce"NH³pÒÚŠ1á””i#”!ÁhÜ`¶¦Dš466A¥–7(*†ÑǶ®Q¥8Q6’aŠÔÄŽ6¶ðœLAg ZÚÚówwMѸll3BËj r´s9¬†¡Ìna $Ó…ši¦ŽXã`QÂGf¢Í44ãYc@˜¶Ó 4ÖÒæœ0G8qƒFCœ8páà -š1-,YeÐl,{$¡I ÂI4£Â %¤‚Ë,r†4’ȶ±Ì(áE†p’‰icÌ4Ó¤ši¦†ši¦†šÓ3»‘Ã…´±DChæšØÕ¼Þqµµµµ·u·Y´ÐÓM4ÓYµ·wwYmmcXÓŒqŽ8páÂÍ8A¦šhi'8IÀáÆšià ÁÈ0s…HŽ8dÒILQFši†,“¨8PSammËàP EPÇÍc[[x5Aà ,“ƒI' 0ÖÓN8pàã3ŒÜn\•-´6šÚpÓXÐÐÓIs^sMl²Ì¶á]ÔÒÆÛk1M­e†i­¦†é”ï†`caãi²pÒ f² e5 %š-‚Im$‘œÓH 4ášŠÍæÕeµ–×…é¼áÃÆ4ÀÂÍ(b›cgyÆÖÝÝÝÖaÇ5™mÝÝÖÖÝ mÖÝmÖÝmÐݰ²Ì²‰,Ói)†Ó…Q˜Ìhi†Ó2Ö †E1¦K „ fŠ(²Il °†,’Np³((PÅ’pà&(( ¢JТŠ(У……hQF–pcÃM 5,»“[ íð Œ"ØÐ!!!DADAD‚Œ‡aáÀðàiÀÓ§4à!iÀÓ§4à!œ 8p4à$ÉY „ADAD>øü£òÜõ]·ëðѨM Ø-k(îàÁ§öw!¶ùËå¾ ;¾`ÁÙKaî›ð‹1Û3YÚØ#Ǻ䱴å9¶)NpÖÛáYÙ…êñtm;-™V¢Jøˆ›³,†Tô6¶¼n@:1s³;Ã<°!ÊÀ§Ì•?ǨL'måàÿ™ÿCó–¯òþoÌžÌÝ̨KœUqåm×&&wÏQX<Œ¶-‹#’.L>Åsf9˳!¹Âg \ Ó¿¡QÛw†ˆ¹Í.aQ‚ ˜°ƒF?SNÌã¡Û¤ô½¾^ôÒGjvÔ§ Ùð` \B€N¾£XîX®¡ÄôÔAÞ¥Ñ#æQöD, ô¯ó’cŒÚ”X‹ï²‚ÿ?ça®LþÿßgG„†qצÂŰx¥ÿéÆbŸ-výK™—‰ó¿ÔfOÉIÛúÔÔAþ:€2…ûQîþH¨ÌÃ^í?€^B¹ý»\{.Ç}½"X§kÚ`«®…Тê«ïß/²ý€E qQT2€Ä5 "fó4 <öÇoÒ¥;Žoº1½$Tæ* ôæCËâ1—Š¢ý¾ËØö‹Š‹ž~†€¨â{úœ‹Ÿ~DǤ8š–±M`>¸þm'óŸ¨ÄŒ8|ë@‘ˆü߇f4åÊ€#ÄÜ`Þª…Ö˜£ø5få/µÚTÑ)p=4Ý…ÆF¾{ªÛf;ã@ µÜ'‰"$d‡ ‚„  ñœaÀjh&¢¿ §™¿ßFXñŒÀ37õNà£ó žÊžö«¤ŸmŸÈ,ر]±œµ(Uõ'Ò†Òò¡÷þÐX—Ê~µ0—"…ŠAw;œê.\—Â]Šâe)µ d—L_a¸øÞOÉû_‡wq¹Ó#™ÞÉôwg,s“ð ð( 7aÞ4÷†7¶iÆäc1 Yµ/ì-Ý—(¤2˜‰6ó]k­/+ rþ?ÔÚòÆÇn*Xä–§ÏhªÎhuýöQó€ÄTCÕëØ\Tk¨ìì0DùøœŽBꯩ‡Øºú]J{•­‚,“N‡4ƒ qÈ4Ó„“dP9'†–QE¨æÑbso— /y6ôF•¼D«U5ÙŒ´EÞUqV¶j¦#DëoLÃMˆ%íL˪±øªT†F‡*ÙÏäÿEú¿ÔÿûóMãÿOÐDAòG·ü”¶UãX~ÿÏ3G¶sÞTÌQR²¨ÅŠ›í¨{ A`~›´ ¸Â¦Î”SÞÇ»©ïh×Ns³y‘UH¬Š,aȜ߈ͷÛm1W½¢H°|[‹(,PT…÷&1m¤ýóMÊS€²w¥%‰ºo¾Ø»‰{˳ë.Ç~ä°Œ6‚ÎÖ†a*‰Ç»ù¤Ž§î–@PÕTÒ8 ¥ç›Ó:eoÆ.ï=«÷_)›ç윲I)†rL0††‚Œ+’hQ%” L¢ ,4 å”kCaÂÉ Ö%¹[iF3‡¦ƒH9Æ+œ3DÖrÎUKEîœfSa¡FI¡€bË—‹ê1žr˜‡I¶çhrÀºˆb!J·?Âu qÊnÚ80À143]_HCù’õô좋`¨¨ª cA µ¢)?G Y£P$Y¼""ë¡@&´l—"‰×»F‚"Â"xZ £>L³&7«þ­E/ŸÍ¸fa‘§sï ؇0Šôê‹àð;Y„±ÓaaYx!6;ˆPårUB©Å¬…¢¨È¢2Irù.fÕ%:êÔŽY8ðò;ã;]‡Xl‘‹Q&ÌPšÇ!Ä5œÃbä”Ð ‰ßõûÈš˜ fãUQæ~ì7ãñëñ»*ÿ GÅÝ‹ç®om4ç=>t°Â a¢8QD¡È‚Çf M ±’iÀB4qòˆÑÓΗ¶Ï2ׯÚ.¢H‚ÁÓ;­£R&¹g'q¯™9Ú«­‰:]u0\HïJæK½uÊ¡ß2ˆê™Ñ¡uÈ®s—²i´puýèŸ?éO¥6‡¡‡£Ñ9û=ŸˆNª‡Ïm¤°q3{M À Pa©Ç•ßRyÕWÒø6¢V Ó¥·HâïãvÿuÂÞþÙiï“»ˆzhÍ^#h0`Q.!ÛÀ(¸ 9ÁsÈ0 ÏŒtNœ.9»Ýkîþ6«¢f„ ä×ɪZ¤fÙž¬Q(ÄM²“DJ4eÚ˜™çÊçÍ}Ëv”ºœ†s ·¢u#~¦ño)Î2Øì±1pS‰60×*jsËÅú^÷9òõuoˆàffdff˜9rŽIonÚ"v—jQƬ¶‡ÍËZbKØiõ„;‹»DqÒ‘±1å52S„à3D2A"ZFY(1|¬°ðÖ`¡ªQc ­ß‚é„'N42ßV! ‘ÈÕîRtaS\”ĆšdÐÇKÕ¤¸apßqAl¾hÝm†—yâêü-*ÆÑTÑЛ8Méz | d‹ mØ¡-bD) $cPqƒÎ@rd°äoæn9r$`½Ãj,İÄdLÉpF ÚjD@Í‚±"šÖÚ&€ «G(–OÚ¦âm´ØÐš,H!¬¢$˜1Ò° a ±hB‹ ÂÜ{¶îxqÆ…étí:˜¼â[‹)å^@Â` 5áÎG$&6ƒ"öBÀ]´ç¸ ¹À¹Í-½éhÖ;œD-þŸ^ ÏÚûo@ô^€l@YZM €ã.lƒ(³}ÑÐb+JTl¡¹LÉKh…HRÒQ2S в–ÉÛÚCù&ᬄ|@SF¸ÅŽEîX;ÿ:ƒ ¸¢He£rî´È“O`C<[j_$ÛvMðÁÒ‡á<äG×ïûÀô Û áb9 †¼Ñ‚uôÏ8« ´ Â$9R†Sð-¸`ër†Ó¿É¡„ò6¤Í rÌ ¥˜•—Ša±¸ÆD;tQ4È(B'¯‘°œÍùŒÃd…†(´ ‚Ó)Ž R" ˆÎìqM3 ò²´€0+«é'ã},€ ÃÌ&éõLÚØƒ34w,ìç4áßbaºø“°âO y^f ÒÄX`›0›$Ô©è´S„4 bMŒ,”±"a¦2–…ËJwA`kD£iÁ’š‘(É,)Pb¼û:vïÓÝówƒÌÉõkÊ6`øßm.:ŽCãä¬pí8&§IcBÓ$ ÑaØL¥ÜOY††¡À˜CÎQòå5QѦ˜E,DD1„ÉFWÀ)L0!6BÁ-£ɱè±u1×.+   ŽÞÓÜíê 莇£¤`õÜêÖpº×R[7µàÍû"r³Ö`¢ÎN½æLfCÌw…˜vÓ–’fÃrš3 ÃL,Ôd¤D bå0…ˆj”c3E-¦1NäÃBB0„*-{q­¬u‰ê´L ëìë©DAY8²ŒÓV·:nŒØ2 @ÓÁFN)ÏÐjLÔ‚=¨hÃR‰3T²$ÁaÒ‹!èÈP±‚Z‡ø)‡‚œ±Ü,çPÌ}§É†8½ø_AÆ$Ò&”öÿž>Xlwž&t4 FNñ,c†„0546@t%É‘Á²2ŒÃ @DÁÀÈH8P!.øšp`¡0àuq>‡èsS‘Õ Ç#ï×ÝÙgϹão@é6¡¯ƒEQñ Þf …A èfpÂÌ"*$F*$É‹AL 2V‘‚S¥Á< R܇1éåb¼0Ó†[±à^¯´‚Ž@0DxDgî®o¾«K«ë 3¦7WZö¹ûsK´ÐÿUÀæçnN^×ÃêC¢CÒˆÛI}ªE‚5ÆtO[IfÔ›¡Œ‚3VJ0!‘²ÃÃùŸ‡Ñc46 Å-Óc4eªŒþ¯OÞåò{ßIÅçùú¶µ*Ùhí9³ÖfÙã ƒN eµ’ë:u± € ’  °]V+ÙI!FÃ_üß~7Ñù™z/›4ûzm\®‹“Ò[ªòá‰mÑN¿ãq ÞãZ!vTh´æW7G>© x#Hèig¬Ÿ‰úßÃëýwè¹U¦ä2BÄvÇ@ÑÜêfìð Ú°›'¢ÜwÚ»a£é ú/EZxèdzB˜r YeÝ=µÛ©ñ³„6ÞãdÄK,‰YqåþŽùÕÿoýbòžƒ£úÝ‹÷_ÄŸŠÂ'õ2ýMŠîó":‡Å2«J$pr‡QA$ƒˆáÐçG qÈ ÂL"¨Šâ ÖÅÃ_Î7‘4Œ(­œ•9—)öwx\œvÚXW“YÆgÚòy®?±r£x‹Šã‘#ÃÌEñDQ!ægú™ï¯/’ ƒ>ÿÛ†|³Ö`¾ÁN^8=㣷éQˆÌˆ@Ê'ð(P&§¥::<î‘ÉùD~l!Pæg”žçN°¦=žÏgпÂL›£Ý$mš* 0 ÂxûÈP5ÓP¥¨&z˜ v´ƒ¦á¶ ¤‡úáØU‘Y…Ô ºú÷ߦhïüŒ–ÚF~gÌE‘MÕUT³í§Œ‹l¤÷)ëÎnX„%2‘˜2¼‹bÖ§E£x…ÂÇ^.ë÷œûnNØ"Çíý ð*úsÍJˆgº¢!Ñöz= Ø^Ó–ã!7mÌòš=žÚ»@<•R*·"·E¿o1Ò‰Pª©m¬fRÅATŠF) 2H’I È ˆÈÃÃÀùŸ'†4ù3™»nŠ$ËvæïŸÌ× få–ci$@k¹!cK±§pá í ;H‹“ŒYv+gf¶,°³xAÜ0×!'8%CaÇ á5¼8 ¦0pbÉ40¶‘˜0(Ѐªäóom&t}?øZ02hÂS xŒ4…ƒÈ¿Ô Ø—µÛs¬7ñrˆ•e"P Ö(‰å:P3€fBHž‚ °1¥è0cº”AQ„Š ðر472À=l_9n¾ˆžvša B–:Zh1fÇ×ñtíÓ~Îà. % {»¶?Ì:øÂÄI>ÂEC”5ñ€ÂƒyÐj÷–î&dMHÈÊHA"B¤¢üd,0–”¤ ŸFI£T¦‚dÀÜÈM a(=¸ÖÀ‚#6 †B¢Ý?¡ÛÔr ê›ù¡µŽœa$SëáÔòw›sœ[½0IHè{4*¶:Í\stAÌiœ"…5â”YRƒ¢ÉE¤˜™ˆÒ(J†@DFf(NI,äÐRìa  § nèöÞ”æîW¦>csÛ_V#¢Š<%焔䚨¿³¦j$ÆáÁÒmÚlSâHx¸x•'Rvꂆ Œ R$F#’%)PDˆÉ8Ž0 °D%RXx¡ †" # f‚ … R""fÞ{ùèÓÁ‡KØ×òi(ÂObwø^4ý4*OG'´Â€¥" Œè´‡vF †¬›æ `sÉјHzKÊ&£ŒÐŒtI¡„¬0 S„ œjŒL4$˜°H"˜Œ¦‰A°pɆ ˆ¢DBv÷÷“°ïwŸ ßˈ@t{ž'SlÞICžŒ1œfáٱ¸Òv‰ŒIˆˆDDœjéh’ÌÈ+IZFÐMØ,8¦ŸCniR9„)¡xcÞñOsÔŒz-áÂÏ]ÏSq“tÐI§Úzî9!Åñ°±PM,—fJZz©`f­ƒƒ& ­‘XO4ºà²¶)uÑ[^иéBðÔ»<IÁ‡y—†Û)¬™ŠdîóZY-”):znhiÄ,\ a†JRù³¶Ìv=Ù!™ úÉñöï× Žþ¾òÒÓçéhƒ0öj\Ó»©æí `qn½ˆÐpäÚäK…ŠZ(¥.ÍL#š³¢œ÷ù:÷x‡# ðN÷ ÆxÐt)‡tãböE6é)ˆ‰A.ÝØ `"@`‰Á ^Cyó·VoS Ùý<¦œÝѰu;Q÷¢"-ÎT—E=6Yè…þWé½ãúŠª¾nu¼|/@\¨6ho6WÌ{~ˆx_¯ø_“÷ú\É!ÊEߑ跔2›±ƒÒÅFhþGëýÿ᯲¿uíÉÑ]8D7¥áÀã”XÞœ nû5ºÎØõ*XËÚógñq3û‹EÔŽY;îsöGtoP pP<ª‘€òÉ3€ª öï|'×ÏŸ/»Lܽ½ÍP~;:• ÒI°Å™úyÜô髞Ûÿ;ùÛÏ£1xÒÖ§ÍË¡Eš„'‡âx˜.º`Á}üÿwM¤Cª«Õž)ɶòë'×ÕΟ£W\XF»ÛÜ9¥"r‡¥˜X‰A#’#$G " (8EOó­¼ãÑ]Tdq‡n‡é®'KÒg5Mœ95à ŒÊ‘T,ÅPÿÆÉÞo]WK®YÒ9Â'™ÌK†)·«h˜—Ê·+_Cœä?,¼Pé§KË»|™%kŒÍ ëúÕ÷P?kM¢z» ;&ž)_«ƒ~â…•Uꛡ¡ßéÉ|ã…ßTxWŸ—ët0¼ªSH—áùS„oðâT¸Ïˆ§’oãøkçý¡¤@Ba`œ݆çQáwÉò¾QŠA;TD~•®¨®!!Ŭ&áí…SÒåH‚|[¬­`£nZ‹²"fZÛs*¬F,DW(ŒÝ ™,X²€¢‚ƒJ,$GQŸÇðü_ ~:æ½ÀÚÕÔLþ`ç*Š8pà bƱ1g…–AƒXÔXã¶8P"Œ5‘¥A¤A%°8+Záeši’@q¬ÖÝ 0’Zp³ ½i%Œæ´S)›¥œ (aØàAaxœ¸†ü­JáÏìó¶Ò]®Ï»$cá»(è=ÖT¹Ëª-¾gìwA#š@ÞÅðÝ@÷úDýËÉý² ±:%ì#õbÔ\"/É«±­†|Z6GCvpð?™Þv˜ùà@Øh%÷Œ‚9Y¦Ú»‹[‚ ÞV ¯¼PÌ„kýävņÆÙY‚"Ó´†ba¢âˆŽ¸Kœš h¸4há½Ì*h¸˜"kúo^…•×Ôy -©ù’I #øÅ·] XY±åÚ|£bX'¾ìqyòy²†½y­Æ›ÜÖ¦e¨¸ÇÙ—)´gnµ–µ´¶›»¥MüðiGÌ€‚[èuøkìQUŒ`ä˜~I,°à`Ó¤Ntð8Œ+K<È^ý<ôÂ_å F&ºz |ÉN„ qσ¤ÍÐÇŸ>˜ÃŠ~=œ8|0äÌŸŸøpLÞŽ‚0³@á%µˆo—ß/Q•ˉ$Çzvr Y 2ÂÆ së{NQMvvxÂo®ÞE0bõ9Íg¨v-fÞÎÈ¿^²Ge#°•b—¡ý7o Bø^xÁb0PX† c¡‹rÞœw>7n‘ß¿S£‹A ,Q_wòx³|eÉ-™ áÃEé°)‰¤0:fj@'b ¹IHÁ=œ¢B|Q©ÉrÜÂIbpÓ×Óà 3¾¢#NÚW-”\_Ä´±ÓÀA‚:³Óå¥CMÁ Ç#!ÏÉø‘ᓌ„ÞGÁß;rBËz÷D“Ü´{p{G²Š¬0¼ @Ð" W$d€È dHÉ$’ÍEŠNžþAº¨ê.«ðÕ%ß¿øù¼ßÏàõS8ÐŽø­Nç¤×1_Òâ?Õ÷¿æü­ËÈåírÂÏ3›&‚]€B°÷_4AOu€Òˆ•¢ ²‹ï´‡ž-劢¸U‡²RÃ^¯UÎ8 [^8“† éN4„ד>_FnæmJ¥9Åæh㈣ 0ÂJ$C…8Ib3HŠ0àMÝ o/ÂÈź&6xMl¤æå“&ò±dæhÊãð™ËyYqÁÕD^Ô³…Ñ—ºÜ©,²b³‚•¼žBQå5Ýñ›¿Ôâ=¶f àd€‹ETˆ?|}#•É´ÿŸÍc7ÞB0ؤ÷v]]î )râYáå (^*8«Bǃ àŽ9DˆXÏ]44×%´b£q¦R¢£ 2@¢ŽQ@tÂÂÖØL±JԚƓÁ€i€c‚yzÏ^Ç³Ûæ¿_ŸwƒH8TeÇfÎPä°å9”Yi2ÖnÀIÀ†‚à `rŽ1%Û# *ªŽpáÂÄAÆÃ²È4ÆÖbKÚÐ5ªò͸`ìØYd’6iƒa" DOóøOHýœ àèÝ0¿Xº£ƒŽ?ƒõ”³2Ãí9(ƒÂH9™?ÞæMeÙaù=L‘ïÕÄ¥©AJY”I‚LɃL(Q½ß±ûß ßæåÙÓ¼cä××1)»¯“ç"ÎPýƒ€¾kÂgÎÝhÙ.ÒÚ%Æå¸Ü9Äü½¶Ñ´ë¬Š¹®7¶õë;°³ª„]{ºÄ,’fË5¯Ø ÏÉ£:fõÙÁ(¤@ÍC¯Åë¾Üò=Wœå•Îö0ç©èÁǬèð9”:<ê"<“$%7·©qFˆ1±Ž³Õ:y¯–ÜøÅç°ôQD’5žð‰³»å(ÙªÀ~/Àèè“n›ÐP~&<áÆGÅþçäã9ïÁždĘ€‘®þ~ý ò>’7»ùg!iÐ@;gk‘X_¦Ì}ÏËÿë>>­$ƒÆ>GÓ}ÖP¬˜ övö›Í¦Çp Û4–áBY ƒ@C6žt¾Fžv]¶œ GÊ áj”4Ng3ÊoF0p²I)1¸r}iè1¼s ¤À0Ða„âqe–I¶„Ñ)i¿•™¡,Ù˜e¤DG´ÔþÊçïàîoàEì%M<{¨‹#¡è‹ŽÝ”Ú6VÉH§8;à QQ(…:³¼vÛh˜L;ô„]ÃO¶¼U]-x€Ah[˜\æ'E^çÝ’8Œ@ƒ€ˆ‰G cðS_ÉS§j>r¢D"OxfPJ5`¡«”°Á‚zn£ Üv0Ý! ×HðXç’Ö9L[ ®2ÓÖÂÇ–S ˸š ©]®`‹(H† ò8ªµ¤©Yœã]n‰ÁeÛñ;šiÉfQ ÿhû.ó¤ÑîÄÄ@skPC\8Ì&³ÕSÍU\•ޤh˥͗ jgB‹ÞŽ 8:ñ>¥­ÎT¹U[µ½Ë‚ëkl% 4i”m»ò:´çØ ³ ×Ïפtv}:³¦æ£ã_èÍÑ8QmI vu<*oeÂŒ¥Ù˜o›³DD7»ìˆØ=N±" µç­s•GŽ¸ÞŸ}QE_d4L8CÒÔ_s’Guëg¿¶’òs åaÄ™C³z]u½?·e³¤°É{¾îVl MŠŸgZIfÌQ¾æ'Œéš@@^Pã¹)wÁ9¾Cõå·Žþ©²óŽCãédðØ07ÃyØ’Ke a(•9'8@áœuÜÔ–ðA†5˜Y ‡­Ç@ÄZìørÛ.~Ó•÷¾ÏÙ÷Ÿw·ÙeåìL±E÷_O9wéÏ{ŒeCEÌ;áý„ÝÆÞÿiŸùª8 ›7.…Y­™¦¤êáÊt“v+'YúÇ“3KØÐ1 ÞƒÐ7‘îUSGÁù¼UëF>à_oïýÏ×~?[¬ç: ž™y¡¡ÅV´>º I6i&¥}i1f­‰O”3%ˆžÑøYžÞµÏkϧ¶ss7j‹™ÜÍÞY®^Á´‹ $¢ÉEI!,«œ¸ž1¥lDëË—™¡È²æ·-X®œ 9Îx×XˆËÌ™—…Í{x7•³ÌæÆ§Œˆæ‘MrI±C¹ÉÕCÌYÎrê–mS·BÑ7Â:ñ¿Y›÷L¿;ÀûÏèú˜‹®b6#Ž:F.3ç Ü]x*TÇ%%@;˜X0€¨ÆkA…b‹Œ ( E ()ðóy÷0ëœüçÛ—rŠï“™ÝÆ*IøS=µ41e6ÎöÖ3˜[Rda„’41c˜8‹œ 9f¶ƒa$n9¥ÒcIœ$g..m˜ Ûk4sJ Àp³ Ò3)c‹^k&zûÆ}ù̽Þ»žàåU ­Û%}s&Ͷ2féváužýnG—×ѱ îZÛoç©j(sÆìˈˆ’E'݆žÆ€# $AHH0ÓßÏ !TBM…AN—£™U`3Èheµ´„…p‰¦˜ß$D…8çeþ»ðM'ÚcÌL<¹)Jê6φ4–5˜Iêoµí:íÌ&"’šºõÔj”ÜC‚š&ð´Dì74PØé:U£Z陓í!:›„•ˆ]N¹Õ;…ËÛ.¨¨ªôñ ŽÄ„–kˆo“ÂP|ª% | Üt“¸—}wç¼å_9‡€úåG ô®÷!ü5¡ {ÒÆ§¡!,qÔ.\úìë¾³­ãÊù=G6îðëšé j,‰±¢Žî®¿ì–2™é‘¼–ñî¯_¡ 4CaÙÚ?v‰*O£òO$ °]“îž?Hz†=eU/¢I\sæÏš·Â“ßÉéªB°‚Hç ,‚ á€kp4Ó„I…ŽhÌæ6O.o63ÜEâEiÍj&*+f RÏO¼æEÍO& £c™‘›—mÊæÌë¼¢óZlrk1ÑDÚ¾M¿!<ñÕg+# °_Ó¹é³dòÙÎßKNwUÏ¥®PûÜø‡Vk„ H£mX°ËÅÛÑ߯m|ÇŸ ßF6ç)Ç;¶ûá<8×C9¥“%mƒ·àœ8ÆpÖk‹’LY†œ è’I,¢‹ b4°™mm/ÐáÁÓŠƒM(fÓGpÒZ`D31Èká†8Y† f 44hÌmá›sŒ~÷…‡fh¤ê¥]içd5H Æ!Yèé„/æÓ·RJ'žÂ¼…¯ÜIž]‰¤¦¸K4©Às…-ZÁF `ˆ›&®Ô†Èëû²¼gLݘp’H`àSƒŽ[ŸÈñóG;Ë©…5g^‡³£ƒ‡¹ QŸhn)J)[ 7sî›±¾Ã¿aJ†®»^z>G²BC²› Ñc7lÝ;! 'vÇdsÓçœìÎÀìK˜ÔÆÎÛäñ¬£¶†áÑÑÂBHaº7Ò=Š+“ cCþ’ä'~üs)Üý¨÷z¨•SfñdX{nIl[XÍfuíÝûƒ`†L¦9 ¨8àÊ”Ècƒh„@.s¨2•2ÏÔKŽÔkÖ W§KakgRæÃ,)¤Í.e0ÑþyßF’Ý»ºššìjSàÇÈ––ÃÓQl`S33}x!1~‡Š%9C»@€ç8d9°m½ÚíTº«Yç˜i¤Q†3[I­ÐŒê¥’­HVCzŽ)J H$¹c›,®)­,ëê©'Ñú¨*î ¢,ÊE@z#÷‡]¾Š†2rß„ •åUÔDS$+’+£×›[yÛR´oËl×Çx/.ýËGÈO’6Ò²_£í>—[¦îcÔ89c»ç ¹ $…@*¬¡PÿÍD3~¬|ï8Ÿ‹!ÔÛ7ó_«Fri÷—iòÔon Ã…ˆr„p‚ (ÂŽÂ0à €C˜`åo`®«›v¦È[‘EΙ34W1ø¹¥SîÒP÷”Bl»Ú#/+KŠã³m¹¼nqÓ‡é¬ëzÔ:ӛ̢\ët±¦f”BÚM35ÎOöð}ùúïÕ¿™äûþÀªP®àæö%¦_Ð2" bì°~(ظd¹2<"2 '«€ˆ%(5P`Ø;X8Ž}`À “Gl ¡‘¥¢$r4›ln3–Ìa¡Ãa`Íf±Ã$s ÂZÔq†Àá‡68Ya}åãf¯[ þ¿íÏç¹Òs£×e$ˆ¨ˆwb«ÃùâHöx[)rxk©$.BtÁÙ‡ï$€ÑÏ]É\“#&ï+ Ös³¶Ž7iGf°Î&!È„"¹G*n©©4¢Xè$’'œ.¹ ŽŒv9äßm,UåMÌ"Dß yMi«µ"Ø{š¹z¶((“†„’vpDã5 rëÐéÙ† XÊRÊQ³ÙÊ×;:² džàšbL;ÎE ׇÌÈ«œfjMR¨ÂÄ(– gaÓ'jÛÓ¦éCH#‚ íµ'TðáÇ›Vï§¢hk8kx$#bbñÇØÈʃ‘#q\ hBnO³ƒ ÑÇ qÈG˛ѣ4Løs{˜§ðOaÛ?„ötÒZ8àç®ûM£6y1äÄ=WŸä¡#AF?©ÖN«îªº»XÚg¾GƒýÔ_wØÌõ¼ >ÂEêyÓãú~³ÛÔäª_jŸÆ1³/U€_Mƒ1óÆÌ1ëÂ¥§Ãø÷ü(|\ôÅ=`‰(tõÄÌÍÌÓåä·îöÿe’óØ­|—6ÿ­&ë—Fþ_*š¨Ž¬æoº,:Çq~c F_jL±\‘ Ì8Û‹“n´"F|æD†)~{Q~K}"_Kòá­Ãë$Á0­Å™Äî3ÑÏÈY?Z9:i ˆuA>ÃïßìÜö¢…ЮïSºŸµbÚ6Cù:'Ï=qãöüàs¹bX˜@ ±1Œ6a®y‚IÊr`ÅôÔŠ*GL† ÌqC{C);š£¯Ñè.ÞÕ£ŽÇ£ôœâbîâuü´aï@@¯d1SÑ i6‘•j8¨I&šû뎴ýyΤ,ŒgPàbæýY«“.ÝÈ‚T}=¦Î&@¨À-&VœtêÖ* ¡‡5 ¢¡æ±wÿOQð;œÙÁ0¥M´<“IŽRϵõm<ž7%Q‡WÍëØêHÅ• #—-î£z× Ís¼…æ–S»‚t Êi9m¯UÄÖuùNdçqꇤ¯Àùt[˜¨îí ëN¯Ikj #bqõÜá›R¡ G²)Œ”>׺ƄJ–ë/³¶Q6¼Éûº·¤,"ÿ«ï¨?ŽŸIÂ*iÅ NÁ+ÏvÞ¥Z{jA#.¤™¯mÌÎI-HŒÇÔ\1k>^R­ª”Ðõ=5ävK™Î¶îSwÁÎwÚ]Fb%YŽ.Cr_kTu2ŠIÍ ’Èe'Å•š€Û(¢ãT*œ#~¶0f¦>Y‡^iz ÐhµÈÉ8Ô Jô¶ä&3zJäÈÀyͦöàÒ›³d¹.R8 y”x¹¬r½#¼U^û¿¬~Z=÷A70vŠE¿Y'ÍrNõ.•UË8Ž[e u‹‘”o÷—éÕNN·as°3®Ã;lKR×?@Œ7Írº¤š”9j%[ Ü- öqvW\«¨êý±J¶ÀàÖÙÜî›0n(%« v„†hÆû-œàÕz#»ÌýFNƒÜéœX3DG(ÚÈ3`hf¤×6UjA¡ÕÕ+tAœAÖIŒT35³Ðî§Ø½Ô7ΘÕÌõ÷ZNˬûÙ °@%íÒß%{þw¯Í¹²ø<†}N¸,<þªºàæ&-`­„Yc…Aˆ@“0R_¢uUÑN ˆñÄÃoªþÚfn²êë`ƒ¾}ńş~‹({1ªÅ°Íæò:¤ŒjÌb2Ô䮕5L¢ÇZq4|Š6¸1ÙŠéE^Ò3늿}3Ÿ É—–}ÐQ0À÷1Ü—ž&(ë#K%«é ¸T4DF‹ÜÒÕz&]»' –—Æi:¤œ÷Ç¿É÷MžÅÒ¸9ÕöÊjÇ>ñÿ á†dJÛZ»q–¥H™• ŒóZ=ó pA .´IÆh·s"[¤/.*‚o² t¨úŸgÀàûÁ™Dû}\{v ó ,>êrUtOíi^ÃìÝ˧šuœwG7tXø 2²Fô*‘D ‡§žø>ª*‘‹)”c Ó7ØÁ¨ž  ã ^PD@¦#V}í‰ù¤ ~ÔÓ£:˜ ²ŠÞÁ 6s‡ú"–˶7·xr~×’õ¿¥­Ç“èÿ…:8}%gˆ *t„ÅÿGø'ó×Çl¥ˆ ÁáéÕÇ¡;ؼU·¤ˆ#ë[Ü€Ô‚Û&–u¼¾ÔÆ©kƒ)ô÷«ÑÄlÈ]!?ñ ЙŠÞ°·¡à8ÆóÏgwWÒÎ&€^ÒÓÖÁƒq—\ÌLÍßÅxt¡}{}0Û_…ïZ³¿éiò*I!Bu#Ú»:ý}•FàTpŠŽèTiÄ‘„!Ç©€•A„bÞÆßUDóȘ·4ˆEG¨Á‚£Y€‹$$‚‚"‹U‚¬QE‹PUQE(¢Š(¢¬X*ªªÅX ¢1V*È«VQ"ŠAVHÄXªªHŠÈ °X*Ȳ*¬Š² ˆ²,‘AbÈŒ PXH’B0„Š ª("(±EX*ÅQA±EUQbŠ(¢Š(((°UUUŠ(¢Š #b¬Š°a!(¤dŒEŠª¤ˆ¬Š ‚¬‹"ªÈ« ¨‹"Á,ˆÁ`°QE!OO£Æ§Òø¬~ÛÑ×wWϕ˞ռú°ê2¿ÏÙ ¢ËÏ¿H"ÖëfŸ±‰Š1ïrZ~.‰¥qïëÝ945œõË×~éoÏÁØ‚*|"£­ãêýﯱª]ÏNìíÓ±'Ux¹Ä;•² Jv¸Ü÷—%GŒªƒñÐÊõ=¨9†ÐÜ‹>åU>4¥÷ϾQdšÁ8iØË—Wf¿R½€¨ú‚¨¬@D`ŠÀD H 0?àÚ‡ü@Ê ! д0µ \(Qk¸Œ-Aø,Ô7aÄyÀj 7ƒ`<ƒ07¤ÜAÄA˜Áض~)ö°x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€x€xò‡÷Cî*>‘’O…h@ ÇðhTyÐ}5€•PA‰#XÅ`ˆ ˆÆ)‰DŠABAE¤0"0DR"@Š@RE‚2‚„ F©’((E‚ŠEYPP@R ,Y(A` $P$d@dDXE‘@  ‚’ "€ˆ@D"! ("ˆÂ)ƒH ÁˆÄA2F"Š@Y*D`Šˆ‚ª@FEŠBDd * „`,€)„IBA@ˆ$Š@€Á €ÄP’,€)$ŒEF@„FD‘BDIDU@IE’E$@ïO³¯™ËûÍæ qgTü~å»pjšˆ@7ˆ«@:c#̵ ÷"„‰*Kmˆò¤Ç im€Àý£U0j*ÈŒ­@Y" 0`¢¢±b‹`ƒXT+îp•."ʲ¨#JÑIb*+,„„/¤*Ô*4 1—õÅF£I!?­ÐSéY²(*Å A$E``Šà2  Œ<£N BEŒQŠ"(ŠŠ0F#(Æ"ÅUV*,A’ÈA¤FB€ÁŠ0X" PX0TT¤û¿Ûý ëÜÆPH EƒQÚ…F€‚ÈÀ` F‹‚£F¨¬B*ªñì „A?óüÿ§‡ux*>oˆ'ýl5ìBÕ  „€BøyþÝðƒ¥:AæEäiTZÊmÇÀÞ³·ñ·wþ~•þWÚþ_âGI¿<&’>ã“æ{5ƒˆx°$ùqS™{Roï,bNÚw‘ø«‚LC‰O6<΀«Üx"£Þ`T` à£à#‘"Æ)Ÿ·F\ÍÁQû @TaT Œ2*0 D ‰Q…„Ag4T`*ØaD D­ŽNàElª-…FÝ (Tg×O {°Tb´ ¸ÁQˆ R‘QŒPc„$…IJ„¨R*E! «„‚0V#` ( ¢‚Š,P‹ DR)AAˆF2H, ,EîQ³ßC¨ã¥þûJv1î÷úºóÈ­Xf¿Ô^{#Ô››^i GÀŠ·ö΄®ñÕåB¿2ª?;ðé´‘õUiíiðð2 Ž_Z B¤)Uw¿!Ú_ÔœŠº'Þ$ÿǰîÊS1³£g]ÔF;æaìƒð@ÄìÝßÁÍcÃúŸ·¾ì»ÅåìÀ÷ ª‰¢ ¨›ÿãÞãô~DËÞëì ˆà"ÆÙTâ ¯´Fa lºÞ ¡Ñ‚ ääõ$•H ˆBbJ ¡Îý¶<@ž÷KÃO5×<C½€R!#8z4ãç° xDwêßß=éøoM]W~ß3öT'guu?õÖŒ>%ÿgÊÍ5.NSƒÚÝ¡¶ œÜ›ô+ƒŸ?ØÜ'/‡²z8¹ÈIY¨¿Fô´‘ä}ÊÚkBø+ÎúÙ(–È'¶ß ’]ñY¾šÞ¶×åºÓ-„ ŠðB-€„  @Tb¬D°P€¬`>¨ÁE~ȉæF'NrÅG¨õš@€˜ b£€¢qˆB1Q¸TmfŽ å")"‘B,Ÿ:ÒÛ•’Œþ¾ ž£ƒrûEGdl¢>QQâ*0Tz@D›Œº"H«öGö%“’ š„ª‘¤Y"$X(`,€¢‘AEŠ1(‚E€ÄPQEQbE€À@P¢*1HªÁEQQX D1DV ŒO1ã ³çÛ•‘¤*Tx€˜ˆ,ŽF£pÓ[¨Ü±a¼hŒ”†¥êË $a ÐpY@.*4*?PTus° o‚AQƒIUUUUXÅUUUUDUUUUUUUUUUUUUUUUTEUUUUUUUDUUUUUUUUUUUUUUUUUUVªªªªª¨ ªªªªªªªªªªª±UUUUUUUUUUUUQUUUUUUQUUU"EUVFFFEUUUUUUUUddcÅUUV1UUUUUUUUUUPAUQÅUUUTDUTTDUUUUAUUUUUUUUUTEDUTDDEUTEUUUUUUUUUUTET’$„I!HFAb‹X‚'¤…Q[ Œ€*F[6„w‚¤‡\Tg[….ñ $ueÅŠcT2O•·ê»ü ½$P^˜Èˆ²"„Ö”m œêà¨ÐÈòÁL_òF€BÊéoDQ56èvÊeX‘…Ü``y¼Žpû÷yÍò :§4*9„ŠH°&†Š4Ò(DŒRT„©KED´¡PöL¡$E"*÷1QÐ œhÙf!ß`Ä/(¼ ›7Y¢fÍCQv$d „6Œ¤RjZPInÙ3VfaK6ɰ‚-ªII€ÜÉ]¦‹VlI ¶b%íâ0~°`‡ð|«„6Gªų-‘áF ÚqQo!BH`nU „ÂäK³{1&Z„fáº0ܘWÒ*5ªi$TŒÑ= }¡¾ÏŽ¨Ê¸ùb*õ‘UpŽTV‚PŠaQ€ˆ£‰ È”mà$V&QQÔT ‚£$c$#$„‚‹QUbªªªªÅTQUEŠ" ,D d$BHFEV1QŠ¢Š,UDQTDUŠªªª±EUX ±D@„‰P «f!B ¹¢ "Œ€I @À¤  Æ*ª¢*(ÅUUUUUUUUUUUTª*"*"(ÅDEUUUUUUETTEUQUUUŠªª±‹bŒEEQUTUUUUUUUUUUTEˆ1UUTEDb""¢*""¢*ª¢*ªªªªªªªªªˆªªˆªªªªª±UUUUUUUUUUUUUUUUP`Šªªªªª±Š‘‚ª¨Šªªˆªªˆ¨Šªª¨¢¨ªªªª1QUUUT"ˆˆˆŒcÄUUUTEUUDUUUDUUUUF"ªªªª¢"*ªª"ªªªª#¨Šªªªªªªªªªªªˆ¢*¬ŒŠªªªªª¬ŒŠ¢"*¨ˆ ¨Šªªªªªªˆªª¨ ÁQU#"*¬"ªªª¬""¢*ªˆª¢)*ªªªDŠªªªªªªªªªªªªªªªÁ"F ¢*ªªªªª¢*ª£UQUUQXŒa $’I!*1E|ûKQüòˆ‚£°öŠ!ʽ¢Á@@Hˆ‰" ˆ"A""‚DB(‰H’DHˆ"AD"$H‘  ÁH€‚ŒDA$D((Ä@A‘#a ‘A‘" ˆŠˆ‘" ‰"€ˆ 0ˆˆ1D$QX±EQbÅQbÅ‹AˆÁIQE@EPQEEEˆÈÀD "HA"‚‚ È‚$Aƒb" ‚Qˆ¢!(R ˆ#+ ‰d‚ ‰Q@D$D‚D‰‰Eb( @@dT"$„H"AQX#$ˆDDA "!B " ‚ˆ€‚ I ADA" ˆˆ " "" ‚$U"¨«XBD€ª7Ø"rݲ AáAL%0”T ½©.&d¦!qµ˜1LÆÉ8›„;¥EQI‰1P‘¹ÁÕÈŒ‚Ú•¡BDX@‚"ØT`€ÄE€ŠM‚1¦ƒP@LCQìGŠ 9à#”x(â¢>žæî΄0Ž•›«Zˆ£P<[„08‹ †‚ÄÂUCL ¹±ÅL¤N»Ð8y]kEÎæ\kq².04Ê•+ÂS)>· šÒª#Õ:Lg!`Û?pÙ#Ge´ ½°Àug G¦Ìî(p q¡»¡4˜ `uÆMdHF!Lý;”6D K †X7f·]TmB£‘ î̤hÒh(šd¦\Bh4€µî2 4?—B àþmXÀŸä¡?Où[tNÄà–õ‚ã_©K6ÔÛ5™—+3ü­¿c4o¼•cX­¶Ë ¢0ŠÄ[¶°ˆ‘¡Ckrÿ—«¡&˜¨¡²²Œ°m ‰$Æ!<±žU&‹FÆÒª‰oÜVe-ZÕñ™¬Ò‚L–€²¤Z…E„•¡ÂT‡à]E“F¾Ó‡øúãA,æÃ`æ ­´ü2[ QDX‹°¥­DFµØ¥r[A¶Ö%"Èpæ41Ìem*Ñ0lrÑDeÕ1`¨1ÈT”¨¥&œ0üFc€°ŸÞêY B²E© „âÙ7f¢H¡1"• ²È -¢É`œÜd‚ L‚ÛV‰A´¶ò-†Ù6Ž]e£FÆÕ¦é™DQjY#±+hÔAƒQÙ³ FÛk …Šº2[D’Ý·VêU h­J_ÍÚÍ´¨”¢ât×qŸôý!>˜!~OZfGó´ä¸ªÔð\é³ê}ô:$Ü¥%yퟜsv…„67€È¯]Vµ¿\.²7Áùü¶¿¼ÅäºîÁp´© AlržQ‹_äÕ´¬#v{ÞÍŠþÚ“‡ß¼úÜ›e矹é)#æ¡™£i³¤ê²Ém_Ú¨‡µLÛo‘woPR!$“êÑw{^WòýîôÞÛáŠéEGºÿkòpKÅG䣥ë¸ß½êZKH‘¿|˜þÞÛê¬ Å@ð~È@ªêüË‚‰ ÷¤g_ø9qpâ#Éÿ}Å|în;ì.Ÿ3%”&”j¦ÙåbœÑ°ñ|Èb)3@±ïpé† ì¾}s[» Tz0TnF·Áæ‚p Ÿz÷PÁ?€{ÇŒ¾Å[/>)f Èœ’7½]~©?g…FB%ˆ ‰›Ç+ÊæïÖ’s;Þk¹å…”Ïþ"ÉžMC'í;pö˜núÓÒôÞ—YP1kÀåNœÂÝ)]·Ë«¤êÇþ§îäÉázlкÖ+›s´…¢¿§þ‹cЯñuºDÓ¾dîAQëNgØì¿3©˜_ŸÎ"ÐÓïPóˆ}Þt Þ×7þŒ"£ˆTtUAç©Ï÷— +p솺›“bçùùEw( Gž(¹‚ D‘ ª°H’" ‘!‚$ !„E=«½¸O©'N–&©@¼ÞÑì&Áu3_E qî£tCâ-å€LGƒ  ?Á5(wáÀy[Š#"SfG/£ôâ5¶ sMwêQ„ £³U/SÆþü6àŠŽäô¹o.ˆißP»hïm7£ôEG7X"¢¾TTã}Å*€x°U!Æê¼y2Sx*ªþVO»þÈyw–|O t‡–ÙEA;3Ö•¼: ‚%ˆ*?BóË}?PsÀP{¤H!ŠÉAU ²*£×ȹRŒ‚£¡þ¼Â7A·æq Ÿ7üx\8k}ÀòÄI.Kù/øs¾À¿¤®kˆðÏr¡]Б¢ÐïW) 8>EÀD3¤FiŽ_R¨ªìKD¼T,TxkH¨ïQÜ m5Š£_¦N.Ü$˜4útju).d^‘úï¥ëÿÞFu×H³ÌvKäPâÆ":öÙž”ø¨þ¿B¥ÑÄ›P@°uS´'¼$’áT­qðzq¸ŸÕÌì®@ÆvNì*Î6-ÊRIa„ƒ"ÅVEX @"A‘b‚‚ÄVÀ"+ª(±IR*Å*ÅDH«‚X() ( `°ûû ü…V:ŸÂ» /Å â¸Tm¬*:ÀŠˆAQé’…FA@A‚„D¨ÿã@s·³ïv ÎETsØè}ePD<þC'Oœ§<ûßǰªvíÊ©…P3ù"£ðP$`€8…GL4ûH QÉëì€Äb°I<‡ÙëÆj¨¨³ñ$¨¯öQsU‡áµÚçË÷iŸ·þ7ûZ¥X«ø¦ #ýq¼0~ÁûŒT_Î-îãu`vü™ñ§ãîÑM3 ²w×óÔ:¡QCôahˆ“H0˜Ø÷*ŸgHˆ¸ù†1™qÐrVî-O¬ñõå ¤. qœ^ü?a÷#_â‡4î|o—ø?÷ý)ÚB("s±ÚÎìT~·ú¬‚{䥷 ¢·ùž¬¼4¿ÙWG¬$^±ì=¯›Ò~ç&ª´Üƒp¨õ €ŒG¨÷¡F:°JF- P¤$b R4«F&Ð*8Æâ»Ç]UM3qñK –sùAZ?Ó„TE\¢€¨óG PNÿÀò£B£ã²€öŠ(-ÿßèÆN=ª ˆPëâ ÃHp( kâ!Ñ~7íá¼ÿßuýÝÖ>ð ×y÷Uß<¾\–pž‚eÔŸûöW&x3e±Q9™"‹’@` 1Býûªs³åºRÆëp=¤®ˆ°æºn°öIxOYn^Üz¥òg1?ÎÕB¬rZ c… ®#fÄ\õ”$c«¼Tt¡ÛSµ‡­ÄB¡ƒú¨-g³÷uÝaÀ}ªˆŠµéaêÀゥînÀ|o·<0p€#ïïGüV Æ!!š!EA¢µ?à‡vBŽf¸w0Ú÷ÎóàÉV!hQ=ÕÖ’­TaQØþÍŸM›!Óä2Ÿ¢¼‘!<1izxœÍE‘AEX@`ª((‘B"H€¢‰"1EYªF ©EUXª@>ÜØþÄ@°F ‘ò]5›}Z÷wN…pk&­“eíÅšxÕÊIˆÝO‹ºa€Ekl=f"ŽØn'˰aê÷ò$=ž “+Ÿl¯”p¹¦²ø¬þàЬUWçî>¶íOWéNÐC¶¿Á’O÷Okz¨(!Wú¿r*=GZ—ß&°'ýÿ‚®Œ‘¢¨‘ЇÝ5_QJá$'¨Ï¹ÑU_ñ~±™ÿzÀ½Äþ®LüXMNg16ú-¨,›šXé¤*B0‚’/¹„¾‡ØÒJç8ÿ÷ßñÿÍÙýŸÿÏâî½ý*œê¶N çøJ€!¨X }ö«¸~B[H.*@ B€°P  Db>/õç<-.(ÅPüoÓáóxÈ ù…G0¨ìîýO$ÀUè‹DUî@ ŽQ°¨ö~€óýgªÆyI·ÃÊð´$àNç¼ë[>¢¯-GØ/r_ë-oìÑËîµcCÆÒÆõçt…NÃáÓ¤IEïN9öIyY’ oÁåigäa±9A*ÞºuNÖWS®êKäÐÑØ`.KF ™"5q ;t®?]›—Â`øŸÇÊêÛ¶±b3é}à ¨ Œ´,æú½ß8ó¦úÞHz^`uJ  ‡Ú|´A1zÀ>™¶ ª»FÏa`JÞP2\sIÛ]ú´^cx¸ŠÇ^{\Ð4 €¨Ðá FaU Oçúƒ/orw#ë øu' —ì/ó $)¢BJ5¿K=kQµ‰lbH²,ø‚HHÖ?À´õ…ÁkhY¡>£ÞLA*מÂã6Ääí‡rޱo1EâÇáǧ«¿¡å›JVÔ–H—>@$€INZ@\áˆ0zÿùÙäW£Oþµt&,Î0>T;ãw 'á!]±  ¨@#±„ À¨fVe/þ:Ö"ª?ºŠN— ÄG3›AЯ߭åhn ®íCZ«S·Qä¨þ6y`,‡€Uä¬1‹EYkÑs #‡ñûˆ¾tT{(!­•ÌDë~7Ÿl§VLì O©cø@B¸W@"uåT áë #›»±D1B_w¿åônKCðAµT¯\Iâ·ÄÁ†Ÿ4XÊ€¼ Ü£µú5~ûO&ÝB`´„H‘?ŸOàC'êÇ´¯îNÝ>uI¢c'³wädËN gqÚk_W“«¦ZÖÕÞB°PÀ0ë‚£¬æsÈ¡-µ‰¨Ù(ç>—óƒ‘$À*ŒPÕ $4óP‡”(‰•P¾ÈTl*£G¸9À¨õ£€È{¥@Ü#h’ŠoŠT&áQäj  …˜HPâ!/ò„A-2XB~÷?ÉÑDB("u­Î½0ŠôXŽ} „p±! jÒÄðËéô²¢Sô7W{Ž÷Ÿ ŸT×]ìp®ÛõÃÜÆãP¤Æâ·¼º& ù$ú&B£Àã+Ýt_B¥­Fç_§*Š Ð€ ‚@$»s~˜·QSgäð‡&«¤V£1 ú¼ÁqéþN6ŸcG,œ ‚ÍÛçò½¥áÑDé£×Ìd³S¶Nýÿ.ùÙ@ÃË 2eYRà¥Ù(Ÿìþ£ïðµÀR}“á „@ì@û«=ˆ x*ªã;U@ÇÏõ;B©„™„2}jÑóx5¯2)ê»AQ¢‚ Š Ô[?jB0Îa-/ ™Ï8<ï1þÛûµäS‹žÒNGÜ—ï1©¤œÐ±Àpþ4”I;¬«j†C2@@|¿Ä2:@B mO[|“iÍNØ]X÷¹¸-kÓÞç•Ùè­ü/Û×ÕÜößþó‡dp;??ø¿ö胇¢ÑÔw£Gv4*5ü]£Ûy4Fž¯H€©÷¿ÑÍÅÕvdãõã´‚ eÜ­Ÿ‘p@Gï q“í &ˆyãxmö, Ž¢£hT€kßàÀ÷¾w­@n¹€æ ¢©üþf²;pîy•Ã÷½?Ðp(9Ó¬‡u´òíÔ„›ñ%Ð@1ˆ@"^„%,n4—.á?$ºÿ£‘­õ7ÜowP`ðp<Ü_YaƒfÂØ|?s˜‡oÅDOð=Ï}Ïü½h…£ÈÜ"ª>«Õ‚£î‹uÆ{×[âR*§OÙPv`n[ßÜP@Ó §ëŽJ ˆcåu|v®UÝȆ.æe#äs¾Û)»ìeOÛÐ=Q‘ü¿|*8@,™ââä +TÀ`¾Ñ¿FÇk体ù'™j¾7¥Ë„ð`èUùhŒÌ¢!w¾Ú™M†…™©(](”à@€  " HB0@/N³Çò6*ÁÕ\3Lœ,X È)||/¢µ&Ïe˜ Fä‚C«‘yµS Š«ÈH$~è ‰ˆU0ˆ‚RIÿŒ_hìe-$Œúõ?óõFûä„™Ã.sª>OIéú£¿ÿט)-?éŸ<Ý ?;Úx'©Á·lu+s;áÛï¹óªúªê!öSN>fQÓQRb{8ò:ÅDÿÕØú²çê§ï9Ö–@ç(UEF:ú"f:ª©ØÕxKÞ TŒKQQd‰å‹dû§¾ïºŸææ|OÐý‡è>G÷#ïú¿÷sŸÚúíEE)}‡íÉçÒ¨²ÝXÁ›jùVQ$ÑÎ=tU§Á,`Ô €"AÀQ–ä– †Ž  r£ˆÄ]¬X˜Ú‹=qPŸˆØž¿Ýuy]Cœÿôäß¶иí¶Ö"}§A` à«@€V „ûöðéxt’މãÂdGáà ú”Pô·”f.?GÄúæÐñ ~޹Â/R˜ˆ ^R`*3P†ººÀ"Áª ±*:ëB4¢ ÅÚ™k+bIõŒÖ|8V0 ª¶ÒUCÈà¢"¯(ô†B~¯Ôôïšâ ÍñÅGi~-o¬`4M7£Ìú Ù“oþ({b〰Ýî tã@ºœØ6—lP€VAúÇæ ~ÌÿäýúD5â5lš'zl£ÃÆd @€,´ØkK¹¤ªûìÐúèLGW·ê¿*hr¨UC°W¢•ô7`nƒAAwY0ª­†ï.¹½ǫPîoi&ï¸ Ðnn€:Ñ:±&í†Ü7¨ÓX+¥‡» Ð4¤”T¤žà+üAßÜÐß,óyrf~ÜvV@€wQEQEQEQEQEPDQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQ„„„¢A’% ŒOC¤b4C«æ°˜Ï(ÐzNèÊà‹Ì7Ê4k7š†ž\xæ+àJ `" ²næ.Û7E“K]ä2aCá½y` î{ ^vÝp7]é!¾´û1Ü Ž""#öÿ‡yÔÉ¢¡¬O,hö}–™{(¾ÿÙv‚{¸aýÚÓiè-äi)qµÓëtÛéPt…_ îÁQ‚ˆ$ÄlP¨àM¶„ž©L¸;‘DL¢ˆvÝÏäu÷*¨è*0E\‚*!Qªª†íC —Ó&Ьaˆ&&ÁKÄ:飰ŒÂ*8…FàTu„A6Þ§ÝŠ §"*!¢ DÈ*à5SIM³àÿN‰TtÔ ŒLY5‚À¨÷ˆ‡ñw=·8íjªX•Ht)ºéW)e­†ÿñýÜ=¯ÒÚ|ÃceöðǶíj)‚”«ز !ëÂär×-Hi[€[hì¨qŽ]>]Ø¥JÐ 1Ç*<¤`*9´ÈkÞSGKTÖ9«ð¿'ÊÛÿQù½¢ÄvÕ™2cñé{ªsËOXÇz™»0Ú\-~Iz¥--€–äJkì Ä røfÝ ÒùOX*=×Ýyë—ž\rë°TrˆtŸ+¼ ?TÓ6^ÞžYÚocˆ©¾Fµ;kРÀÄ !ŠÉ0c1ãQo7z H}ï ~žç¥Âh=µ›O€Hy`X@”0(™é×ÊUXgÆ+Š ‡Ç¡Q}‹§£ä}ßqÍ÷½ù;ï‡Âóš;žO¸öµ*KºÒäô2Lâ.„ÈpÖrJI¥”Ãä=Zò.ŸU(¯0‹–¾:¿ž6 —ºû¿°ùûFÏ‚tßÓ=ÀïÏ÷‚£îÿ*üœ¯Eêè@4/Ù†üá[ÏF—%Ì&ŽYŠô´t§É²91'¥8I¥â!…Û*IQq!@"H «®6÷R©0™>ÿá5 ²Iq}™ÕIi³ÓQ­B¥¿Ò&ëö1Û ÍùãHÃñ¡ªôt L B¼Cˆƒ|ÁxHä[=º`0é**„ˆËñ¥‡D@Ozf0[Q öy_—k“Ü7X¿ã%qò#£tÿI#­'µÊ×3‘k^¤Nò'ÒЀKtÌú÷°È,€D%SB n;ݦ €×3…«½ú£.d´ÃNû¦„aÙþç×ê~JÚ~ Yy©h¡Kï)†ÀÅí+@1™_d£Ö „!mЇpæéû8à©5bûZP ±·q+÷M‹º<ýO²J“…I¢cR…Vmrtî­¾iѳKÕ„×S4“šÂÐ^ÍQ%¤òH“^ö5À$‘wÈ¼È _èPüøÂå0Ì´þiýß»þÓßý§,Ëmªªªzÿ:2Ç—n*ˆ|ÏbVÙ=p|~eƒJb4ëÀ=Ò–/ЙCB^¶áWóîSëˆã†¸+Oq¿j…· ョçѯTé­¬ue|²›‰>Þéms,‘ª«¾&mÍnƒ¬ »jm¡¶¥±æ™qné2Bî0*„¶.£vÄA‚¬À2%Î zìܯ«\\/ýÝ÷x]»ð0Ö L¡¼Á¬€ÖCYWbgbgˆfBSC94£ñ0Yƒ-Z“3*´8´9Sò?¹ÙpÓÄÐ A A\Y[ŽXŒUa–; y3®ð` À¼…äAm®û…3œ'2"”„«ŒHDˆF{33+7Ñ~•åö»ÇãþoýðïCí|dÃáó‡F—mêÖD5¸'ã¸0û, Uw/Í͇ ¯ñ6ÎäòJÏÜ—‹Aqxg\~pB) 5hìÿñ€/<"ã\vI$S™‹&*ªMà^P¿àÛ(Õûî?·óý¯ÉÒûÌ­ú?}ÇãÿÜ0‘:êÏûã<–f­º·æÂQÂ1Ð4Z)}F“Væ 2òæÊÑ cžN÷¤ï‹ÈCó@z¸Õ’­t©¢o2ÃPïM>û¸a:{ÿ5ßm ß]¯©÷YÅGÄúr`ùc3s¬÷|±TÜ=ÄçGÔ¿<ðÊFCõöÙ¿ñ¥ìö ÷‹ðJ„§öulŇoÚ-¬<™’¡Ø„­Ä«š¢ÈYÉF¬y¨5B¬6³%q0´Ë¬¯¹ü[7Õ·w2ŒÞÌÔÉ­!$ÎL¤ýJQ™GÌÉ›®7ü®UDP…IÓÌDUæo5o8ð¢4Q¦HB$âbÁ`ÂaÙË0böµí´d-X¥²–BÈ[1LÖ1cŠª ²âh‘ ¨ùÌÂÑNКLG*ßâ|Ç‘òžñ„×üKÆZTjÄ­ñ³ ¬Z6$¥Jxwë/~M‘ãÃLü¨¢œ—Nôï¦bRË>J9Íãh… "›RÅEDV‰±˜e™pÌoóa ¨”w«@C}0¶aiÁ†›4 —y¼Ìþ“ý§úoêþ½jñˆOâpNïB‘Ñ8(l`XEJ 4JÕžš­31íÌ [¬1ÎMî=¬q³2pÎÎ`w¬ýunè} ïÖ+Üåú/*àÞ&-¡‚ì P!€7 ÀI.}_Â×ÝaÄ™¸o¯öpµJYE~ĶÍhMKÊvÚÅsq(Gè»÷ú‘?Ý8sR;é –þ]‚±®SËÃŽ’NH6 PŠ?³dÆ’¨ó”Çù¿þTw[d&Õc=.‘ÿ'ùÁ¿ÎÈÛYp!ûú»&XLúææ^à £«<÷ßa6 ‹öô A˜·èdàêÕï÷ßhìk&¥ié½É ^2¼¹m©h< ÞÚ3Š /+P€CÊ ‡W=¡=oâÿû{Ë깈;ȉ}‹°\øËîÔU_‡c!eÿŸ ‘>®ˆ?"b0‚ Œ¸ËCåËQ¥ÿ°‘ÿidCÐ@zÃÞ”’Eô{¨sì ¡øet`;F¹uîH0ƒìפ„û(2  …i*R…I¢!P•Ca÷Pêø†èàuh:‚e=¢VÍT$ Tq Á(á@¸²×Ö—ê|_—Îí³®KII‡0‡¬€?áxa_Â?–dn ò0Ûuqº¾ƒEM†ËEQÎŽ3 ü>€@D@°¾ÚD_ðžÝà›Ý >&Ö“®8.õg®EÊ]ô©™¾ÚÚvXâÌT¬´ç\é\£[”˜úx póÝëþØïî=ë×J;•ž¹x$þ¬‹F¹ßát.:¤ú™íJÍÖº5^å¶Tð[®Àíª¹Ý ™I€A;€€UkïED“Â$†˜L238ÒpH¢ÈWuêVÓkßb®ÔøT°…t•t\ Ya3漏¾-ƒª£— Y}˜WZ¸ß"Y‡Î"ÖŠûÛa\¤ih•BFgbã2vì”^Æ/}àî*NŠÕÞÕC§¼—ŸÎ{RŸ’ôë3ÜSTÝ¢æeóå}L¤T,š8Ĭ•WÆ;­±¬Kïjí¹ge÷«ÅÑ´ì¹ÒÇý&‡á>aêuî$x‰Ùü/22å:t*Ã4 Eô³‘!‚»OÞwI$—¸ßÑ›¯‹yÜÇI ’·nÁ{ZÅôl@íé¡‘î,@BtÞCãÔ'(DThY½ TlœK›¸†¤, Ð€È9®y™ZZˆäTÊŒ*4µ^tÜâ8Â×C VóÈÕKÚ¹ó>£‚ºÏJH&ƒð PâLï=ùI4!¡ß?€¬”ßg¢ý³ðLg¦Ð¶— ëWLuÂ(O)K¯§?ph1«PÅ”‚ÅÀ‡*7òn¬\b@AÀ™wÑ£ÁXVmSPej’y'v‰¦…a)gO×ЈB”?dú`8Ìïîxˆ6‡¾Ð6!=!ö‘<--ÏÜIœMD¡ï«÷1 x6‹Ø‹czfé—ŸÉÉ«…Ìö¿ é|ÿìt?§ö1ã™höŽjðIf(*7%£‘\‰eÆŸ¡$ŒˆÌFEÑu`ù^Qy"A„,bF0‹:ú5ƒHÒˆIóo£ñê*У¿–êIPÎL9£ÐÿhíDÇ †¤ Í‹§ú,ع{ï„à—nQ½§y ¾ @Îù}Ã袔î–Ùh®@ªA;Ìô¤ØÛ”å àsÑ8!ï¨Ã ‹*²Tqg6‰pùï|HÜßÜ95ôRŒÐ¨ªÑ;×P¼"I eYO>Ž×&YTºÊãŸ$ ¸š0ñ²1râÛv¦q§HK¶ƒwS}‹pD‰æDD¼ýÖu!´óbvã"G– nmnä˜rfg Õ¬€âhRáb†ï†Óo'ÙR]ákN Ëi¶ú)ËV:( á9t¦¥´œCB­U¢ Š-߀áßž™63)CTiIbl­ÌYs öüâB¨—«ª2\‘¥33 œY1’Bf<B]µmÖmšˆÃVîmµ5Ê› A“f ê†Ô§¤Jíw÷j÷½¬dT`Ü–&íA ÀD»;"œÄ©êغÖμó“ ES'…rY‹gtH8çDh!ˆn@™£vña™q‘·8,SFMN'96=ÿ•íÚ'ãŸ˸†ƒÝNôì"|J,iÖjCø‰ÒA„sEt]4€ ©¼ëNê,×E-7&zƒ4Óo8&ݱSR'î#F…zw‹Y0³e¢ýBÿ&BóW·p~¯ô“™<9<ÒŒCÅ9刊¢¨åAªƒ°d `çSÀùÌÙ¨ UZm¿¯Â‘Qbþ°ˆåp>"‘4?Ík€T:z€-S®Ið'­ ’ù&˜r†Ë¶ÉvÀ‚ÄÚÈÊ—9Ÿ>Ò ²o€á‘•›QºÑsòò!{ þW Æí†½ÞM$õ0˜,wˆ@ÁÄ&ZE’ ”@}`¨Ãðâ€"' }¨JDÂPÝ”>èÖÕw,ÒC•F&ì~¿)‹C\ˆkÌl Ä&¤°%à[àó9"D8“ØêX¼AQ <;OET!P*@$ˆB!º4¡Xôà; *2 ‹~þýTÈ„%ôµ„8*B²‚uÀ#¼¶‚£¦ÂØ äS ÐƒÚ ¥Óô)ô@ëìÓä.b/È„Öyx€ >)\ì€H¡ž‹PX‚0‹J¨KýI!?ßpket'a “ãDËeÀ¸ÿƒL’BsHkSlPf’- ä%¤ #"ÈÆA‹¶@Â$_w^p;AÚóBDŽ… ûúUÚ ‚^‚çÇ@ZÈù!˜ Žýù <…9‘|B11ưv\·ÌýШýШêû³nÞ`áÚèy¡Þ=Ä™¦ˆIÕA’ˆ'*VûV»ÚCHÁQQBÄH^a¯Ì\7gÇØ(ö¹^ôZ2Ÿjôa½xîÄ…–7c¿i†^wËÀd‘ï짪îlÔ~¶9y.L¤& Ø*%–y& joáj[d/tªPáES?QÁ{¸’Î/C’+˜¢f€¥’BŽ«XˆQ‹(–`D 5^? )’D È.ˆ¨ñ^q$]w\©AóT~U\èrr)¯!-`PQd–”¬•€ÒÚ Qì¦)í G`c*?K•©†\®ŸQÙê3à ÏVaæŒ)ç»ÏtxÞˆb9íjMC*bùÆ,Ȫ25–§92¬ÅW¾ jgôŽð.žo;Ñа’*‚Z]á@ˆšœ7ýá“}´짉 ­Böž'PÜeÓÈ™z¬šŒ¾s¶äN^æ¶yI»17·N“œ E‚ø2ŠÁÖ Ð:g>®Ú ï®NúÝÌ­Û ŒÞlÙ½˜äËŽ÷–Ø›«f¶Ä eÆæ\Ôô¾@ì`«ï‡6REdJrøDØvƒh@E×–¶…­‹€TEx¤II8D/0ÅäK÷vç ÛÀuëdH†Q2bUs 膓˜¤¡LGo¢â¡: #ïz®±¶Ä¸BC @€¥ÈL~·^êºÈm?». a±)ż»˜õNǼ·™¥Ñ­àw´´m5;ŸNû$”ßfª+m²Ïf×>eî¦ô-@1Æ ¬¤ eNVÔ Xyµ4h@lU;Ù^ž® DBDP‘<8­Dü¿-yw{y,ø]^Ŷ£vSëˆOU§“ &'Ï<÷ç–Ñq<¿aŸ>ûß4Âw˜)5 HŠ ÉBµD)4«SÉO: Eö?×®}?Þþþ7pçëÿ禃¦%ßWô=Ú©À°*7ŽÄ) ¬ðéçh¨‡ÖD$ 1LA*=ÔT.ˆ¸x\Œ™H|Q>A~ZUQŽÒ7cœ4„:0'˜d“e¡îiþ3½‡¡¨<¡B‘òšùsR D´dO¶*;߉¿©$ XËÑÜd8,ì/ÑOÊ,fG4&1í·ºè_*Q$EF "T)ZDVÚ‘)JnA@¤â—TòtmÇÃl9ÐFýΛ˜²°„ˆ°ŒDêžðIÏhŠ ±OTÌC:w ˆ$_BƒÏ'H:B.€C@iMÝ\¸×RX;á¸B‰ôn ŸÛcMÈ‘wC£¦ž"‹ ûRž˜ ²æ+Q_TZƒ "ª%O³-¼$KIÏ2Þ³4L6]šFëeâÛþ&]¶!€ýóÎpóo•Vä–S•H[ ;Yk{¿iº¸~ ,œˆÝù5’6‰^ÅŒ#|°´¦ ~¢0Mé  Â0[—ë Ì-¡ÿ»©Ÿ˜×÷_ošÕþœDIÀf<ð—½û?±pE•ͪõ…ˆfÁa`)~”åì;7‚£¸ßJ…O娶ízÌœíyу¿ŸŸwϯǛќ÷;MvÐQm*§YëýÈI ËŽ>Îq˜Xwd£ ø¹†“»ð {6 EU"vÁ|°>óÿì?1Oý§þøÌ+Ié~ÚÑdc`‰F$Yú=§_jóª:2h%’ðlOz˜`&„̱ÆM*‘£»¯LõÜ>ûA4ó~¿‡œ´'¢®CòB”Û]qÞî+`÷ã ·1* Á`ä–¡1 ±B‡fÄ›f®¶hªº³ÆÜš%)°cÜæŒþ.áÐR=p÷ƒUÃóEFçhp‰ˆ‘"‚¨üë™ ŒÂÕP‹ïJµS‚”†m†™£h;.'Ð,ÊI ‡0ô ¹ç‰âàÁaBj‡6¦›$Œ„¦–ˆtˆyX;߃'.xö}‰ÞdÀ ŽoÔ“{C ä‰Õ”Û¯¹&ÝrL¡ÍP-R\ £u7À!¬ÈãLd¬Ž`Ba’$`Srh,\ü<— aï×F F¦¶z`å. wˆý»îâTCJ”:ÓwâØ•lå£QµŒ•Ov%èòyTðíNÃàh’ƈŒ=åyv¾$ÁA=#IaÒ Ùá±°7k¦n w2¬MÂÃd BXª6ÒÚ5ª¤ki`¤•QLH¨ô£â6Èl&@†ÄmÍÂ$ÈŸ!ñO²zN÷¸šFO2é‹OJ"Ÿâa™lî¥Pøí’‰Q$W @OYí3D1ìZ0'úB k$d­/Òt–-©·2ňHÜ0(œ±°`(œ_IßRQè.u-ŸÎüÿŸÆÂÕA©Q„îfþæ¹ÛwØn®IZ["Ê‚e®"àŠ ƒ”¦ñ™[*-´ÂÙÒüöeÖM µ˜A‚)U•*Q5´ÍBÁ’ÚêFÁPk E e(¬D +C hlà T‡¸zA›‚sS¿£»pÝØÉˆü±çãwF€/¤¾½O7ßyÅTg"½,ä’`k Q;­†Ú®¥¯»pÿ¡ÒìNSôý;,ÃZT¢z’Óy$ŒO D†ŒƒÈ ½žï©Öç(‚’˜Šœ/ÿËî¾þ¿‡Ž¼$ŪߕýS¸ê'[Ùàtoâî²üÈŸ8Å&ÈE)Hp’V(Ž2Y³Åš²›»ï¬† ¾J_f«h P¾F !*¬/v̇4¨r¼fùEðI^L ÉÃf@H&“Œ•NLªÂ%é®âÒŒÌÀ¶[QJ£z4‹iX*Ò`Æ&É!7VYH•¬©]©¤\´Æ@“"H À`( %lŠ !0“0›ø®<ªåG¸î-\ÜYãTHžu‹þWÒþ&µ9Öv‡9gC¡¶ ÇvTw7(OÓøƒâèÆëÀùF:žXÐ/®÷­ža@F^•^#Á·˜ÑÊÝ*gm"šf%† ¾cÚ8JàŠ¨Rþ²–Go«^6¹ù9=ô‚OÞ‰jxwæ÷c€ÇEFÐEaé|=Íúó—cLÅ´d&!×9ù×­™8ùeÃË×**ùø‰œÞF¼ÜïU8÷Âß’°–eø]÷Óÿ«ó¿Ù£ `þ§üÿÀ~ü~RˆCÛP™¯@¤*MÈÝ`5KRäëÏÃlƒ1•eÌèȉÈß¡À~Ÿð/Ùò‡Ás — ‰Ó@ãËvp¥„Ô1žw¤ F¨é®¼¡MÃОõ±œ“œJ¯{:Ã\|>q¸Tv0…‚} u sá$‘„£#®êPd‘ÊüD4’û•¶ ZúN**¾„¢‚«Ì¡G¾ ÕÖnC•¢Pxç«¢ãˆæŠo‚‘?¶ub’[0˜âÑï±_¡þƒ§µt+’w àò›Ýاlb ¢¢€ªü'/| á­5k’>&CAˆ»Œ¢(¨¢«<Š>=4òšÙ`d“@4P;^ÄÙ½67Tâ²y9–±dh $ˆ’¦rDý”ÃzÇdäÕ‘é$„|cÌb¢ªÄ`?;¶•Å €p/<ßgWù@Aÿ:í$‘/ª;%]nö‰ÕÔÑQ%€Éþm¡Nêpç¤èÄC?_“½ro ¢‚»Bo3b¥&#IaÙè<çÕ2óÓ¶Œ JPJJo™"È^DèÅè%Qe¨ ý"'‹¥Š«;_XeÔv$„öHisSÖ6Ê¢:§Ï­»¾¯W˜Ûna¹­f ò!À‡”‰4mÙáUadZYB ‘*$–”ŽBžd<ˆ!$&F=S0?yª >Ð…öìDéV•WBNÓ‚k^ÝA­È( K?ÖyäñŸvN7W‘±Îö>Ë]¶3uJ‡,ÔÅÖ[k$„ëwÎ[]I!1Úh«‘Ðmœ¬IO+·AÒ¡¿°µUtNÄ‘NŒ TŒ3zf²d Öï¤n=óöIb „lÇ€-w­†ŠMŸ/3îÍP66yE4à'©’¼¬7è;à¯D‘HöÙàsàÁ[A¸ÅÎ3øÇ©Wn¢¬\¼ëœ^Hÿòä‘ã¡2ˆ¥òúa’Å|%±Ø¿ºÿ6ðˆ@ ãëôØ=—ýy†ï„Þ>yo±oŸ#¡O"ê;¯DAD„Îü֜κ}uÕÏTñ*äûvÿJ½Ï@|jfv,›î—šqÝNI¤Ý¬ñL8%DéË5Û(âú" óãÑ ÜY2×Èè´í˼2dsÝM¡ºõ»t‰üŒÊwîwÙ¡Žv•¬Ú«mEŒ­•®©£¥_»p™”)_zBf.þ,ˆ€i‚<Æ “޾GžÏ.zcêKÙQ ŒÊÔ3…-Gi˜à¾IúéÔ|—Lv‰™;´DÀêrî;;.ïYpf.‚¨xG¦£â‰²2x¾> !ŒM€„îZc-½eÐêÜxO.š_íë•TÓŸraÛ/aC›$‰N¾F»Iµú‡n] ¬À•G(œ!|žˆà°@â(ß]h#¤íh¾òjÜåý“œgw1 ùè • ˜ysŠúöÓòE·Ê¸¯—Í!W*ª Î‡¯›¬³œq;˜˜ù“ä|ž‘)”i!.Ç¥Ãçäürõ~ÚÀPƒ VûCÐ)š\8\K|ñÓLè˜Æ!؇«‘œ ÇÜuŠí­;ðY°¸§š9Šø30ßÇKKݸ©·ª±ïSìuKMœŸTÝwK»ï½K€æ–¡'‚“£ÅÆE,AjhŽ|”e0ïDH*<¼˜Y=æTêÞPèÐ×™£§§“‚vBvÏ£Þw`úòjp±üïâ÷ózvî°öleYꄊpK¸Æ ÄÆ˜0A3%ÆL—1ªåµa–¸ÖT¨Û\C-U Rc‰ ‹™+nÁÐÉ!ìDR 6¥cϦk½¦ý›]º ªˆÅcžó¥¡ó±maQº6Ààn ¼*Ÿ9P\ÜãóÓÐﻳ×Yâ‰ékÙ·GÛª¿T_œÀ~²Ñ¯^»á‘0O³Ä–ñÊè^½ú?‚þ¹X–w"S’Y¾¦cxºªá\P]o$DÿÕiÛ¯!H‘X1HˆBYþwÃþkÓ1ãç1PÎišúÍ.‚Óõq̃ ød’L (ýk’ƶã˜q ëý{Ósƒ@ìãdÆÀ~™Ôâi"{DA¦òaòúOÉ˰N@À½,¢Vµ©R&[‚‹Òxò9L‰ù?ó?ðuuÜ!»“ñA¡1°Ñ¦"XiøõT DT{ÂÖ‘È+Ýpîˆö¾Ã3pÌR€øXç(ŽÒ(`÷îÒå’ !e‹$£å_˜1üRëΘ€äv  ˆ¡ $:šûÙqâ­èPŠþEùP™:m½/yºfiYª,¦a£SP8Û¿GE[cqÂqTPcp/ÚbH‚î àu®õ{çŒLê³(úKŸc‘ר`j vGÇ.‰±Y$"€²pÂüof²HMÃÔ1Š“š›T¯QK§ffç_X¸éÉHöš‰IÙß|†%uú_)˜mâ¼ÏUE4@™w×^®ýsÜ,7Ñ5‰|ñUM±J=¸ìy×D’}áðþù­ÒR'cº„'ojzô‹—î¾\Û¸C¥Gkí6Ûm®bSÉá3Ã2å<ÒXt`ÜŽ^lLÃ=m Àâçl‰»±z Gç™WyÖrµ¤ µ$1ª‹(ª‰ž(“wJŽx…¯`c¤*@Ž ‚uú BŒCÃÞ¦Ì%ÁQ‘;Zž€Îæ*rpÈzÈÂ(iƇ¾8#$/Ü*6µëˆ,b Œ­irmRG[A¢H±Ma\‰’„²)„‚ZÙŽ¨Õ:ðÅ×K®k™Mpâó雑ÂÂ{Ü:h†tߘŸúûÅGÝ:оÞZ³ï‰òK ޳Q¸º !q.Á²!ÔHŠ6²§¡^ •O^;Œ¿»RIž&›Blk ÅÒ{‚láC:q•A#±²d6#gñÈ /Gp›äøUFw“¸â(r¢È°‡»ybPY* …°wR‚'=ìøÊ:÷Ù6˜ãIȵ€!A 2î1µŸHá”ñòéЩÃÛ(”z\´ÇIHMJú a—Ñ„Ç`Õ˜àˆ;ë‡àCm5w½ä€mK8„L=ε™f­¦z‹¾wŒã¼ñJž¾Ð¹D#ɰž=ç¸Ts¹á(‚´’°ûÂ{è‘F$„A Œ„@G8'ÁG»Ü$ËÍXpÚŽÎjïc© ŒéÔksÜ-Ð6æó„¬øžÙËY¹R ¢j\…(áµÛPR(7„ºÖÚ› ¤!Ê­´U.c‚fØzÇ"\›ê°ãZAPÎ$™,AÈ?é¨ ÷l¡¿³!ב¶O}øÒž}¸RÝ%2±HQŠÈJœ…FAQŒF5,FÀ¨Á± oÊÝÜ è‹ã@N&ªªÔ*uŒ“Ù%aîÕ¼ |BÂWö¡KÀÔúgI×È)=‘ÂGË'n¼êÊ ÌäÇh7*€ÒšAKœ4ì½î—!;›ãFR^MÝ"£ƒ¸†¦#+I*®£J“¢ ¯Ï)ÌÉçÔ¸°îØî.ޤNf¦Zâ`¤;{]=åÝñé~µ6×À1úÚ¼ŸêáÌÃÑ‚3Å·\*<žó¿Obyr„ŒTŸîï×-QïãÞìß4çL­wÐeI‚!}ûä)ô3ô»û ˆO™-9è^:s‹ÎMäw'C"YóÝוiÉœ”^Rq™XÜ!íÇ¿<ÎÎK|ð„(ëâ7®áé ¨ýÔ´ªDù¹sϦB&Ÿ‰¾Õsߨ²úéºXNÞïω6žÄ½D>L4,Ї1䉂ïYdãñ‹›jFK&ðUâ›EÝ.ì@¥A6Šºo¤©Aº½× bÆä€¨BŸ5¹J~I!?l.ÃÈÈxO§Ìù²<¾‡Ð{4œ<… ÷-˜%B[ªùö@]TÉ£äp)Q¡#¸säžÛ°r¼VºÒÑrü¨-px ,§¤‡9‹*Ð!Ô¯¥3ít×x ö¬=¶k¥ÞÀ€„=)ã1Žº„ñ Àâ´Š=J÷J0ÄØ ‘´ Ù‰j'Y Á$ q¥Û4N •, Œb€‰y "µ.TƒVlì>ôDº€Ç-.XEFêOjçÈ7®+äNÀQ›ÃµûUgž°NƱ¶X á§ÌÅî }KcBÚU,!¨{Dp›N":¥bnw£äîÊÛæ[_èèüÞ‡îø“ä|sÃû{zXÕµè;ÝPÀŒ}B[æòØ .1 B DH…È$-·íäd¿œÃ?S‹ÜG!†¤M P#ÐF•¨)P*Ú%F«P%´ûg}@•¸’É…²LŒ>ÓZÈMe’qª¤‡¨’¥H‰ ˜JƒH(Kó%0]+7¾Y*Cæw 7(^Tm¬P @P(€=l•‰1¨IP*[(Qd‚Á-+mKA™”P )-;Ìí2™à^-ÌWX…_ µý×}xúxFÂÚø˜b„Îb Äå1óh¡‹³ó.ƒyÄ«3ÇÒÚb÷*«#‰Æ¶… iQmŠ1þÒ‡Ñ÷A÷š>ó1šó!ßnÑfƒdÂZ-mý•â^bÕ§R©›Cë¤4®Â#†o’ ~ìXÀ昔ÉO€˜dÔf2{‘Q€üwÞ l@퉼Gš½¼6MB>„R ÎGå!¸Š"ï¦P¡gþmÐßþ8ûÿ§÷ÆúY>—ü=·óü/5¼@x¼Ùøcn¸Àð¢áþWúþ…è@8ÌCÔ@éE ŠÞ%ARËO*Ÿ0ˆ¦ ˆ ~šåEX¦¬RÕd²Tè2AÛæÇÚ k¶Ü_›'¾2óÓJ0D£ñ?öX½½›ä•ìd«2ß®PÖ¬Ò¢"$•kBu7Ø;‰!=<Z7˜höÐz¯J¨‚é‰R…U5$M€/Ü\ÜÞÞX’I$ò †0~‰Š„ÕÕkUÜ?@ñ¢žI­k,‚ÁV\À,ØH!“ýoÝ„DöR€Ï­×Á %êÇ-GÂCëdÅœùÒ‹ù-a±$"É hLd~À¶«Ùƪýƒžg‰Þ¤‡Ùq¿aܺvÒ534bì† Q(` u$„â»Ú±QUUTñ¥W#RI˜mt'hê‹ÊAW‡'SJTttóš0ŽèÀîîcÞÊ,Q±‡ŠKeµy¢¿µÂj!D–WIQQ$TÌRÎÜFç#!€’IÔjU¤$„Q+È*N@oÀ¬!¿]ÃŒu!pMËUOkm@“bm²ªª¨Š+åkà*ª¨«ý(Y:û«tÅUUUUUUUTE‹ÒCÒIÉ ~€£qTWp-,ðé!ƒØ€.üÙîAÑ &§ðМOeýÐѽt¾Ž[<=YÅ0$` >ââƒ$æ]Î?µõþéþ¯ävrIûñº2°1q)1,D…J1Aü+@SÕIEH"褪1dDˆ20Ÿp’V. /®Ñnù2®_Åü^Y·ùæ<¯ëþÌ:=„µù¶ Å6&Éqs¼Ò°fŸü¼þ§bC;Û™Œ§f\×·?¬ûNq‡CKfBFTÕànn.o`*4*0uÅÿ[ÜÃ8~4$Ö2Õ¦ÕÙ0 ˜=ê8Òð²ÕˆKXåB—›ÍÜÞcž@ìbÃèá äè ûìØÂ@d‘b c‚2b¨Eb$ˆ0в*ȉ ¬! Ȉ¡H¤‚„P2‘°DQAHa"ÁAH²@ÏwD‘íeH20(ø'-ŒIèAQpa("D`dŽŒ*k=Zœn›l$ w–R‰Yo32Ã0Àk 5{›ßñûŽý™+ª, ys‰¿^¿¬×@Þ†ÕíšVHªEAв.æàì ?CÒmÙFеòuÊù’•e\“õž“dr\ç£SÝÇ‹u5/¿b£±x°7d‚ Úêld{å/»œ°?ú. Ž‚yü…î/gÛ"‚¯D” ŽQ®ót0-¿¹ÑÓ+oóo0S»ëŠ™ã —vçM”gÕ³’‡ùJÍ"mR§T®¼žûí³ ;—ƒOÙ{¨´lµÆŠPˆú¢«ŽÂ<äÝºí½µÃjr„Åò^®M£®åèxƒ1ˈ¦/=¡èos¢mwÜͺ/—ÒdŽ„\ c,ŽÙffý[Jƣˣ„ ,ÍÂA©ñ³}oUѽœ/WG>k³ÞzŸèù¾Ç¯Þz¿X Ž7Ù)TjO!ð p%¿MRŸxαÖöP(ÙÒⱓr8c’†ÄÙŠí˧IȬ5z²äÕ+2_,rçq<u00éÌ·¾‰;O}\v0õ]5ÅØh¶‰wà˃ýWÿ.£„ÁZ ÷VT$$ddÏÑês~Iô‚ßÃW§©Ÿ÷/}·ÇÆ/±Õuìï¹}5GQ4 »ªjHdqûrQþÖ±ï€T}NáqI–7èl&ÿFûôAÙÛô9 HÕ }ÿx_Sö?ÛÕüÁöúý>'ÛC´z"Ÿ‹O¼SŽmÁÛtZ ‹Â¬°b$F,bi€.Æ#0h °‹þŒ×¸IôûóüV„ݱ©ºSc(˜=©Ja÷ÌÆJ ”ÿÕýþT4 HĆ‚‹ìŽ¥¢:ñ¿ABóRQÑ¥& §D0uéžØé9Vø7Ë,àX¬r:°þ«BtÒi`ÊD1J›¯pžÃ© &poC„„.B£¶Æ»I$„þª,bȆ$QWb•›ÂDÿXq(„œBUDês(øý Tv6 ¥½îĽQÕø¯¾àçÕYÛÄ ·“”Î è£Ã^÷¢«På<'ÃàñD¤¨$aÕ–#‚ª,ѲPÞZÆ,ÝÊHZÒWtOTaxI³ZÌ´´û’“WšÓ¨U‚ˆ¹`'$xp@å¿xeȘ{§úQ *1±}|F÷ÉÙÉtvãé·‹”ß”`§qº.8ðDÉ¢P*p ]¢Ío{Yë< |6aÂI¤äÄð¦Â©ÄÐY¬ ÄF `á7@eP@ЮL,EFÂz­×ß1ô\¼…êä$Ošy;‚Œû$ušqÒߥÖÓ í£ÄDØ '\÷D䤯‡žÆÕ™iî–HŒ6 êÀ­ZZI­aDe¡Äî÷JÏãâ‹<ÌŸHq>{^ÝžÆbã³Xœ›¾8B fCÇñrX“|@õ/ÒŽ¾Ì]pËvÅ ¾õCÇkˆ+ísQ#Ì4ަ`‡©µ[o,Î6˘\ìT ¸ugü–i!¤úÏM佞ž21^Ôg  Î´ÀÈžß[†·µ¥Ú»B¢(­¬“%îdqFièÓu[ÔÄ$Wås;~ä²ÏѰ"Œ™gÕ:«F¥*!ÚÈtñ k{!ŒìØ¥Jr ²?ÒÎi³9&ù¬Ì*Ú% kE…f5 nN&ˆ«daQƒv’ÐkX€g¨PÆ" ,¶oÚ€`¾#º7L#&Ä¢Í+À"8]`ÄY\àlï²gY:Ù'‰gÆÈ$,SÛžÓYµ3F©¯Ž×"7íµ­Ú7kvªÛwÔÅ)û6r-)¯†Íˆ¡ÂoºèI/Åd ?UúD3f$!UFSp$…Ζl(ªF ´ NĺJH³yÐa3>fM™×WEE'–ºœÓgiÃÀÜ/MÉ "â22|¨Æ;âò Pò@ˆ‘!$FAŒTEb¬abˆˆ "H¨È ¡X¨*±D‰"ˆU„‹ÀŒUQUDb¾’ $F2,‚ ŒdV!XHdFIŒ ‘%H±`¢‘bȨÉ"Â*Y ² F$‚ȰP‹D°{Hù=Îãó ™HçqçAºØ8†F×PðNãhÜqtwg]0x;…NÄ£5ÜØ¥±KVˆ#=‰ÂÉ1¨±2•‘rB§ (IäeNý³!³Y" D@6‚£D ŒA‚ƒhLBŒ.ìÂ|r˜$D‡·ðY9&0ä!X>2³Z–[1if>G8 '˯…õ–£ûžÁ<Àlpò>6-Íû…’“¨n¨ÜODCÔœôÀPí‚¥^BP‰$D(!Qh†O‹½ôñší ÀÐÓj&(¡„êÛÞ‚Îþú~XšK;9´øPn~7:—€º‡lV…€ð–!½ˆÑukÖØ2¢E0e oèj©¢Ð·Ó¬Ø×R’µL)$%ÅÊI4Ä‹„a.L¹TÑ4WHháÍÛ¡Ý“¬Pí$ï¡O7ˆaçtà*QÑâun÷·4þ_3fÞ3FÏÞÁšUa†tȹ)šÁFrEŠ®´ÄA!-Œÿb2¶¨hn$'pÄD€gÎ.ª¾“ÇKâØ§µ @Œí J‘!;`- Th$« eF1i6О9—)7û»}^To õÞ¶zó©•å!qÐn*žäsªÛ]˜qâ.@î0F!‚Š)ë‹ ÑŽûŽô¸ýëÿêtø|·g×v2dâ…Ñýÿåù6¸„$&>L4“ö}&ß‘ lãç0$9ÕIU½ù~»X¾n Ávøâ1Ø; A}«Æ@.µ“šw¶˜m¥Zžñ¬ÞS ,üò«Ë{¿¯Ççý?Í$/«™ïS3âÚéÒƒHŸ9bƒ j’¡Öt¿Yk‹Ëßj8 àmã0õ¹kÀ°(%WÓôj¥÷¨ûìk’a[© -b[³²þÅ_ÏÎ>Ÿ²£ð#Ûgk¼áQ¼Ü§+nz³«£D%RP¥D^×!Ùg竺ˆÙ2\.Ÿ ¨Àãd7N?i2HÅ Yõ†L§@}PŠŽPÀEïH;åï»MhE’¤°id¤ý¼qÔR\™]yí4…P?ðµLÅåѽ"p¡ö=,/ ìfñ=T%!¤â“jÀô“»é½_˜ð{³_ª€™Q°Žè§Bº¹[|ÁQ Œéˆo¨¨¶ §ñ$$Ó(¨D#  "b(%b‚€°EàBg+42C†CfeµJÔŠŒ‘•%dF:$Aq@dAQ¤¦©>Õ8I!1‰‰$&&ˆˆµ¯¶õ·¦<5zÀ™;c$¸µÂ„†é`-®¡ŠÍ ­‹UK÷UˆEFꎔj¨At`ÅT#aŸeÊ/õÿ^€B=z›®ok5é)Ø?´ÒchšxÚHÞ e\>Ml*7È vá´ŸSÙ¡|‚£¨¨ê ÞR,W’ˆHÁ@‡èAÿ'÷åÜÿ âRhËCïú©Ýî ô;XV¤- ¬EŸýÿ?ù~Pû&ÞíëÁQÞ N žèƒd4ÀÄ((r!´Ý *-CàDÉš°P¨Æ“EƒÍ×R´¼¢I²dO443MA‡C›1 ¨‰9éÌYX8j “S4›~eœÒåý³x)`¼©Y&â–Xƒ³)Žˆ›™ £3Dß6ÐI f× ÿH„ve`šjÚý,.9†.Sl(*ïªeŒJÛ Yec$%‚‡4Tõˆ‚@BâÆF‚‚‹ °ÑâîÀ #-4D\K¤¯rV¼&Œ|Ðl^dbdFx@*8t\c¥ÝB‚°.ÊÐ*;?½9g‚('ŠCÒ™Ð,Kd¥¯*YY@Adü~œANÎLÁ|5 Çûˆ~HÌÊ,¬Ó$M}”µ¼ñŸ…Ùã(P÷H£$ŠŠH)”÷ã¹&ʈ¬„å)IKjŠŠª¨ˆŠŠÅTEUETEUVH :¼€ ©_,CIS ,$5¯) ÂËx*j— äØgÕ&ÙN[#CC#º3ÀÐo4¨Q±[×Gd7åÀYPôö>ÞÊOk²ÚcŒ>)*H¶Ê¥¦ƒ¬¢‚„)³52ÒÙû¯¸õoJ 4Oǹ®[NuiÉ4Ñø}?¶qœ\ÍÜòM CÎ¥Da> 'ɃM:Õ"h²¡ ¢á¢Û¬$d¥ÀžøæÐ£KY!C D‡ôû¨pOBM½x†fNA„_g!02öÞúêp¨zŽ3ÑdÖT8’„áI ªES·pj@°£¸d( ¼²&ß¶k£rÃAt,ú9UŸ$ë ÓÁÔ¡‡Ð¥ŒѺØ3vÄ7bÅ HH˜(OI="¿ÄAc³ +*(H%Õë ÃÓA°‚™´)×K›ªÁyV¥ÄOMþ5]*{pûÝå‡Qw3ýd›‚Ð3Ä@H^dB*“4¨VÈ|!Æc&a¤LÁ†¸ˆ 7ò1ýžüŸµÜw¿üèóêj Žˆ—ý ×wÈüùéþüŸgÝxÚB4O…JÙ¹U¨VPÀt¥&raÉ%ÿÓF½&fYˆi®ñÞX½§‡Ç†cÄÖ3CnYúŠÈØ%I3ž<¼LÝV Q°ò}^- i‹)#yNW9NC³ãB0D¼Â8›Ëö‚*_ÉÆÅ`bEúãžf+° Ìð¡Á¹œô¾þ?õiûœl_r컩(ˆq§·"£.µn;d—}·ßnÇ1Âé˜j4ø¯/jë—³ÄþφMÅ ~Œ,¡E /²‚Çë6O<þBMÑ‘E­Pï´VÕ¸œ`wR¡úÀº¦0q! üø24B(Lb@HÂH¦¯0‚N°*9D$„Þ$û¤ô¡Éª›®ß Ö™™¯ypbÏ€W"p• tT=fkUU¸g¢rA:€ëÞ²‚tp"B$I"¡žãPGï¼aPY(¨Ìó[!ö? ÃÑ ßZ*~ºk6›¤‡IÌ·µÓ$qN°¬œ‡w¼`>é†Ú2kôoôˆ{BH‚A€·îL6ÿ@…ùnôSs¼áFo&éI(¡Fó0c†Y™lL¶TÄDFSðl'IõˆU f5»΄̸!ëõ›­²Ý‚òâ~QúTî<šáÛ4­Ö"¡s "R îv\Ð`t@ß \ Ø"æ{'‰AQv@ ·bJÎïÝÖ|›Óªè©79´Q½í'î Ø1TRCÜx ô¨P‘þšÌÃÌ_´¡åžÖ$1Q„¦–vŽÁj$!ÈŠDbá –‚ ÃÀŒ"PFŠ7( ÛmB_I®XÍX2È ]Γˆ`õjÀ-b§^Ò~­Q7âvZdC ("O¯…}Ô•ñÞP€'(ªVtõp“ŠyNžÉĹÇ}»yÒDõ'¤*#‚âH #(Hr„ÇçÕÀÕ¼•øßcëÿDÎÇ×ã¶ÖÄ^ö¢â¨¼AQÁîSÆIó¢>àÛqUÒQÓ†‚˜.Ýy,6Bж*êDøæ kGÔò>[­¬íó Z-hhÜ:ºͱ֎ɽ5±iP rVHHÓ¢9/uãí5ºõ}·‰fC¨Š‘zR‚D1ï«ëŽÅ!¬÷3sª‘ê]C8ã43Ž»‚eOpÂHdÉCü ¶b3-/nøî„I¬ÿr:we‰x+˜ŠTV¢héeÀï½¥î^%ØÖêÍ¥˜ Ã-ÙÙÅDÕ›c¶i1 ž¦Œ]$†É+Ž5œ4IÂUJÈ‹—L—ɵÚïÖL ®ÝÓQ¦ Êk×5OÍûÝø:)ÊÊŠ–ÊÂHD@U‹¸t}z3rG`S,@&^»¥Šßf‚%¶¤rc(¦ï:”HAyˆ@ÉË¢°ˆ_ÂA-Ú>QŸˆâ©gR’%” ©ÊßþË÷´}¿]Ðpdj‘P]ÐÖ ¹'@¨èÐ*>I™z¦ª¯ûŸàì\2Ž‘A±`@M7ÒbÔêÅß p±´J“F80cTÁ=UDŸ—Ö9"µóür¤<à ©€Tw:žÞ¥€‡çB®Ä!cìÝlBÔÂï[Ö=áC·¾{†áÊ ž/›)¤Á13.KYjB @ÞP§÷¿Lâ .rr§vÆëŒ„¡D ŠÂR[|úŒUYï 0 Qy `W\ñ¨ÔJOD “#õ0nla±D„K…!L m’\½íreÁ÷´fLšz«TÛCaÔ %—­\h7æÈAdYgä J •&ÔàT`Ô´_6û–n2¢RIK,’I6q@\¶¤*AJËmaÁLD] †©ö›Ýj·–fppM,´!  …›ýb6øXÀT` ‰‚d )„2a{*øæ!1FÛšPÉI!º™ aD-ƒ#+ïF@ªFl‹!,ž 4X^,µ+B2B†å=ØYçM±˜§¨µ¢È„ª„LƒÂÇa`  ŒH `uB'@}eDIJ*&{x ¿dƒ|ƨaç>.ŵ°¤Þ’eCFÀNñ¤t"„C<‰$&$’a ±B*+ ¨^"’ ôÀ  m²ª”,KYH1VA²°‘_ïaø>4U"`Ùœ m¢6ÚÏÓVb Cpg…K,ˆ O(ÁÛväÄP¹(µÅCsóT€yHg¦ž,Ô:IJ ìn£ABz™èrW¼ÒüpÔðZX¨ Ä€"H!3AA–*Š¢ªÅ``oî°‹Áü €C¡†¹¸°ôËtó¢Â}6@÷Ó©80È~T1.æ$Ÿ&Åùé£_}¦H€I·5QŒªDÓ b’±`²¢kS±!©CfCÖÌ@Ó Áyð`ˆhÄ"¬F(ŠIe’BY Ú#e¤ˆE· °°BADR14ÊVˆ¬¥£"‚£¶Ô©QE2*FвT…Œ¶„Y$"‰$%JÉ!+"ÂȈDEƒf‰p„˜ÁQJ6­––©D¨Y `R ]‚£, ؃³ KÐ Œ* —VƒF#DM7™ÎÀD)$"%¸xppÀ‘Xesî£QäÒ*5T`[Ù<ÒW±ìÒ‚W©õÂñ“ÐçÀ~öö${'>¦f¦`ÔÆPù žè·Î €¨‰€Z„¬Eä¼EtP}ß}þ­õŸçï¤Ø•+ô>§îŸ*YIåGäÁ²ÙÈó­>T½þ`4@0ÆUºäE=z,øcùš›™ÿ+•”¹QúÛZϯ%‰ZçÕ/ Ý>ò÷¯§@}Øç³‚Å­c@þ“üîX“Þˆ ûâÒ§êþ§ž­Õœí/ßT€ÕŠÏ@‰%õŒõÿƒÎ´BÉÁ!ˆó;‡>cáˆ(zÀZñN»Â ­‰et½÷XÖ [$9—èɈÝ0*+â‰m÷ÝÐQˆ·k¸ƒÖ@’aò(XL…S~H³úwÛ2¢ªùõË—6Šz¹rãÌx@$ÃOt´PUDú¶î!}¼˜¸¨­¢1B±E½·\{þ9¾×äùrÆtÚûÅ*ž 9æa‰f¢ëÌPä*àó œgìœ(Ø(aO ¨°X Hw$„¬­g4"@Æ©D<ŒQQ >wi¾í®üHÁ émkeÕÂp@èãÊÎ<-E9ÖÕU_HIÑ<è($7q¦ªÂQdsäÅPó ™ÀF %tO’±<›UUJ×´öÏ×ÍaTV(« °ÁGÍÞÂÁ£½ÙUX*ªªªªªïær¸*ªª¶ªQ¥@UUX¹J )<¨ßÙ&3Me¥}0´z‡Áûé‘>çÎL ˜4-…Û}jÕ)É1U-•@÷>¯5ʨ©z„1Åp•’,‰–µY(¾%©ˆÆb=ÇÅ„6`ibŠ¢rßÌšÐù¥&Ä|„*>Î=þ=G›°ã”ìµuÙx殈àL  RE’Q˜$RWãtÐjC~J‚ˆª2,ƒÐ÷ÀbȲi‚£\‰jª‹¡î—c¿|Ðýè°ïä.²òå|Ë)~%LV>w -5¦î|¯3Q̘úÄ0Téö>ß®ö%{´Šç ØT # Ú±Ô@]$N#%Ì`È3Âx6… ç „qâ†=Ëx]Ú0C(!¡äSQîs5ƒ 7>Æ7ßD¬! ¶º@‰/J_é.ʉd´ø{ÿC»äÿÏÞz¬}¶Î•E ‚ÇôOÎ7Ó¥KK†)cÆ!Œ @3 € D°h~þ3UÎ& îŠfTGÚ*Œ!&*ðBÌ%F£J ìÜTˆ‚¨‹ ŒF(1Æ‚(#B!m”Vss*4¤,­dRZZ• ¢(Š¡kFípÁ‚,¿&F ’ B`›q˜ˆ °Q 1AØl¥²Ò–Ží‹…hU*aj#"DŠÈZUlƒ%‚$­‰jÕÿ&×ï{ŠîKâØƒkZØ–œ) Ãó#Hw[rܱû@À’DHhâ¦^dåÇÓg¤t,;OBQf`bäS0Œ c%!ͱ&P5B'^ád®Êdíösñoù=7þ¢sÍ(gZÌõBÌž<±ÌΜ¸ø»û‡”„µ!U†¿´v6t­B£g¤Œ€gÄ<¡¤  Yî ë€pÉÏ•ýtu²,ØðÄön_fØœ4Îë$$ Ç\‰Fù¤X.µ‹ö B.ÆdW‰ ûÔ]DáÖu©W0B”À” ¤¤‘Nò‚ºJ).OVpEGI¸ÇEŠÉ 8Žû`Tp G"¨ïøæ<2*Å€¥²yÎ]ÙUSSÙu«¡-´ ÑL ê…¹5ihà"…-¥MvÚf™U!ïmf´H¦ÙQ‘؉i(ȰGè2ÛÆv'½¼à!ŽÜf‚‘`°K <5,0 –Ò¨²Š­´F)QËD÷ÍŒ‡Ss<ß–ñ›ãxrêŸÂÐd9 ˜r5~$àDUf5aTY†ŽX±šÝ³§€tÄS! ΓȀ¾¬ ÷Øív"èÅ [û`„ZÈ`\‰¨Fi°”¬£„ŸHÜÉ¢ŠÇõ‹H‚ Š)$EMáH!CC) ’a@$ Å=d°àÄ1вhH¼Œ!l` Dˆ€Æ0,ƒb|í!# E`´ Æ0ˆÜS°P}!—¨à†ÑCÎñOA± îú&©ÄõÁˆ0»Î£:I€{F‰æAaÜ1`] ŽäáîÉO¼z£~MÊ÷qˆGÄ ð !u! :ØÄã#ƒ"C€“œIÁ7¤› ãR«ÔË–6ÁAb!Kc«H‰0b¢Á@‘QŒø6Ñ­¶.5q€W.$¸†ITŠ%ÍJCa–2 rÁÀ%Éaí¸‚¦¤²¥h5T¢?Ë#” °A¥’Œ«+*ÍŒ$ä4C §Ðd ¡Ê7ìxN£xX;ȆH²!ÑÁ‰Nª70šïê‚"^mL‰* X„„©`Á¶¶²„€ 0‚BݯS˜UÖêR¯;µ² ÍËße Ë ²Jòytâ ÞÂé%Tü”q@áÎÒ“±  r䣂¹ÉüKOá¿Ù2w²+x“ŽßÄgGª7‹„€ÎA6óB£ X/±E_#ýÿ™ù^çäþ'Ûá«Ó¨W©aÖüBdlÎRq¨ŒìÚ ˆÅReuu­yîÙ§oš~ÖîÐ~tñnëF?CÌ"ß2*¿ù–%šFGô‚„º´â£ÝÀ¶†>Æ+0Óu™`ßV û¯é>÷¯¦b†MKKJ4šLfr³µ“Î틦õÑÝò~>°ù•jþº¡àôž0C;Ì“øü¬îÊ,}žüy—ö9#3 C55v¿+;³÷ªÎK«‹¬ü%þÓäÿíf:q49®;´”ã#êå÷ôŽ‹v>Iƒ‹xä6ƒ±jõx<’lâäÝPñ¦³µüëÄ+k£¶•“¿·|ìêã†!ÒFjõNÔÓ!Ø"vtâèö“ƒWD8Ÿ'[ÛÒ‡[Ú¥Ær1ÏRfÆÙQ6…UL@ì´Ô£ VrkO3J³4ëKj“V5¿3v¥V‰Ì¯ƒ`àU^NjœàY´$ö¡ãð}_ª-[øã&§eêÜ¢hrÇqü³ÛæïØPä\̽>@MˆI0"Ù6Ô‰"PÎ:DGÒ wôaMO÷¾ecÛÅo<=ÓJ>Ê™=2h슙M ¢ÎCP&âÓƒ.××tf­6§qi›% 2öåÑ¿-b·%Þ‰˜ä’Á÷C…)w¸yõê>–íC3 ÛS)ã8•Æ“BSCuéëÆHô˜ofÈ+‚:_Â~«RŠhå\Ð[R Á‡9ÆBÅ5"jÊùø³¿Wvö>t™Í³`!.90›ùòNydÒ ´¦žÔ êm/W`ríj‚é¯Yœ­¬ãüe9´³aã­—uRÞ)œ•é ÓÚàÌÃkågNÿf^bzš’rãÔ¼õ$u/qÔïwG‹Å܃3 Û~OÎgA\J¬N¥˜ Ø6‡¹L8XDk,q”ºýsâPsWÈÒyžµS3’fyÏ“…Ïûqô |a:¡}Bñz[ñ ûß&Û9Ho,!Rê5«)DÑæšMÁ—OçOù¢»D›JLãÁ©¡IåÜû~ãî>F4¼QÖµqa…QçË5:#^k„‡i7¨"FvX®ùrÎgŸR7ÚûíWjû Žû[&MáXFG;,ù‚)öù½7ÅÆÍ6e·†ÞÇPÓ*¼3D@¶"ƒ bË9\ø]Œ·Öñ)W½Ífpfzq4L ÌäD72®ýõEñ.ÜX‰‹”û\<[Š-­Þcáßâ{Ço"Ê=Ç­ÆŽîÁÚñêÓ³ÚI^Æeê\ ËC]$†@×Õ (@47³ƒÈA¬õQæéP´Ý!Sµ~ÿçüŸò?úý„£}~ë%Ö"LS‰¼Žèúøfü¡UJ'SâЬõqÆ·Ø¡Å!ÄÕÔaÌ]Éßø=ˆâ/’Lò¦xfs­ÍD”‚@“´ÚCý`˜+âä—Qûâ2>— Çz49ü¦y?§˜?‘²Âq ¬9Ð#ž»>6óHvD2DÀä{÷ÔÌç1„tÎÐõ’a¯ÊN䈊ò_K"ÂÊÁÿ_ª/ ø÷$Žˆ¤=9^ª3͉µØ½|UÞºPžùÇ÷QÇÈw¨¸×)ÆtÌ wf‘:Päß¡ýYÇQÁ6Ô×§øÌ…Ü@ýÁ,"ÛÓñw2AnÎ&b¾!¨ÊyRÎùó¢äP<”ˆ––t–^¶ãTËC`Œºj—% 2Vž¶É^ÅTóÃÓ;L‡±W]õ¼÷MÿØ_¨|Þ3 *LÚPå ôC³ªÉgøÃõpº¿“võ/ð‰ð’_BžY™†â§95ÕžAy7ç_÷Έë¥ÐÌÃR‡;î²Ì‚òo¾ûç|èë€ÌÃ~·ð<˜n¸ü^÷«¿EæüЧ¾f*åm¾™¼6µ[^ ¨ÇŽ~dÄ8ÂàÛybÅ©ª¹xÜßöj.!­Ä¥w“FG]µÎpš`ŠrC:ýùÑN}ÏDø}ì/à®B@ðh‚ õUlÅ% T Îáq½r4Òl®Ž ãäVÖÕèÀlÄ}÷Hέ@‚Öšæa+E OsêùÀwuØÐTl ÎG]m;¥nôz¨2-@ê¶n·‡W¢¯4Ç™Ÿåc•öû+Œ`ÈFÁ=ÿÍœ»6À¦ìÄTF,ô°±e(,(©* ,c8ÄgÃVètµ(òr, Çp”æŒòr>5yšBflë]QzQð¡zõÉÞdv§<¼¡zˆôºôê1Ž§Ë¾«•Ã;RîuäÁzK ›µzžºIp˜Nç}NTE?Tóq¸~œÉRˆJ¼Éïk~w7lgM/îtý^í°rqyÏnHdÅ &’3ÕCqTx\€KáËm€Áû]:1D…þT¢ÞoqcR×nÂä;”0帖C!`4! ‡ÊÍ!ÓXØ*oòÉ#¨y*þðlQdUb£$I!HƒбV"EœÒ{¿^‡9…Ä(š»NF$ŠÆ (jÛªo¶åvCjưqð¨ðG†1 ä  ·5ɶ ަÅÅ¡ $ÑãoTÞÃS¡ß. ½*½ŠfÉ}CI1’ "HÃfƒì&Új"æ(„TwíåÝb²nß4ê/°²?åLFGÓhœ'úÞÙ)Übêê‰.r'ìáɈLÜÁÇEœyWI&Hâu‘ÂùËw˜n[þDÌÌ5¥u|»ffÒ»»(QSx¸G¥ âó¦^l$„Ü´å̸‘)D®$S.í%½ ˆ0>˜èüÁaEgDY†Š ¥ÙQl‹pòØ$n¡âd:¢î’ }Õ§q°#ó2!¼ña»,A‚!‚"aÔD=d쟒Eî&è'x¨Å±D –³Ío—Úw´[y×%nùõÃÌ“îÔвô8Š”oE@H¥Ô¢#£Dߦü(’­Ø"€\ ÎÃÁ‚´Œ „ Vˆ,GG>ñcÞþj·çü ©[¾ÉTgr\\K\2",‚£(‚JRÐ`ÒT¾ÁpÇœ¬˜v΃#ت f„„BcA¢¡ÜÁõ7)Û’E$ H$ Š›Íèfxœ,/æÕ—[Ô L̬dÜl!Fv Ãïk1,ž`9Ä„ >¼çšnޏ)<ö@*)Y!m”@(OÅí¸¨FÊóñª¦i)‰  Õ(h/{ûîPšÐvK ¾²H¡Ïnä<A B\L¿q¬Ð<úü!ààÓŒT5EŒXÉ¡ª ðÇkqlá(¨å:\'†Aé:NMžW˜÷;٘ϿµuGu`3`ó‚£ø"úP„ñ¹ŽUD_2 fȋرöUU7€¡KfÁq…à¹b׫–¢ —”²,Vñå÷²-ò—b¥—D<€þ SÌyÊÁÈißÌP ñaðv!í;f±Xk6’;‰¯8pHEy°-$RÓ@ˆyüFüÇ€ˆ|‡Ò‘_¼!®GÉÐ9Å_Zm¨¸ Q´³Ó˜I! B"B"Šœè"À0€âøY!êd°j+4DL±D¥äAÁ 5+ÁÀ0faä.u¡2&²ð$J¢A$É¡ðEdM¯õ}kãšÔÓ»ðuû5‡è{kõw>ûœ~W—ú>Oæuœ®«®í¿ûƺés?wù=GÞfêqtäwñ8²î²¹P|ô:óu‚&=”Ô—‡ ¡Âr¾Ë&BÒ¿–…ôô_§~vQ­+b ŒÀ¥h?r_²0Âà“ãÞYw˜AH¶CÒ¤³«&:/#Î T½d=PP[™/Üï±’Öõ‚_dD0‰Ü¤ âeˆu¤* Wy wÀ»ˆ îq6™"tò<ªÛ6„ûư5aT£¢…dŠi*Lƒ¬šÖ‰ª´µh(ªcLX·2¶´mj£%ª‚˽'·ÙÏ'ᳩ:{z iÐÀätçÒ5è;‘R)e¼cQD$Bõ²‹ Lç,ä`¶!ÆIÈAXøIøº°ô[‰Déd–öCRw¥:`'³¯aÜÍ!Aa¹ÇuÂ’™bȆníÑd-Át9nwl^ ¹N\‚‚¥¾·óõ_?ö\4åîäv?µÿíŸ[á§ ¿p{•Èþ³¥|[nå¢UÀ4,ý¦ÖmýæåëÊë“ok]ˆ ¢ý,´Ò¾µ"H t @(‡d•q ÁäÔ)h%Ì -%‘?[ô©õÞ`øbÌtp ÌàVC™[н 0 ”hzï¹Ïw…êëhßó3B5ÿGÜÞYaªc\fPI”ñ¢¡ëC^Æ€~Nò¶9Ú’½T*¯*T,¾DQ’_˜¸9³Z‚jrÜI¯Ba*ÒI& *ê®-”3¾AA–>?vY3å ÁHФ/p@ ;NÓò á€t€x0œƒx $8!!û´‰ÊÒQR Šîq†þõù?Àx£ÃÑ4H:2LLÆ©7ÏU8`‹ÁÖ\Þºà¯vw÷ëŸÓ³“å roœ³÷6hÆ0‡!ŒKÀÌBXP ‚‰@œ`D|~Ûè¼×ózŽ›kÄ4³4¤‡ +ª©¨ÆâT³¦\C‘Ð5F*0‚£÷œÞÏRó<ÙóCð}Ð/Ü7îc÷)Ä÷˜:m‚øÖÎü5Yˆ?“C¼ò^Éj¦„ðƒ$‡’”&x Ћ KD¬ë³?±Äí¸ö×i°açzv”y‰KWÕ;Í©,™€uénû†‡k´™¶û=(új‡# ßE±¡­ Üþçô}ü¿ôäö|ýt‘^=TWŸ¾¬&b)#åê51AÖgþ„&<^£ºŽ.¶-©pÇxD’I¯ñÇêä=W[*Xl~"üVÿ†IüäÓZ3§• 5ßÓÿL§ n|¢q22ª s#¸=êò}ü%ž€ê.vkŽC0Ñ„*¿/í3¿'Ëø?ìì~¦(ï Ãùu£quµýÐ1«ÑFQ ó‰ÄŒy€R 0N§È'èøAð+,äJ?‚H@@`¬ªzœPúâhÂçKJ´˜bðl§®òùx½?e]Œ‚ŠHwl™ŠT"а‘¡°m^rKW oˆK}ÎéêÜÓ]Ô·<½¶+§àì  DäîŸÖÅ–kó>ÿÝÏIÅž-aò€Ùi‘W”ÔŠiH(¬V,ÀjÆ8ÒTÆ0’óH™Òˆ­WäZŒ~þܺ­À* ª†éžÕÖ´ "DA$•—õ<´òq‹—>Âÿ˜Ì?‰p?€_¼ÿOs¢E¯˜ àéÒ¸DC;¡g_$§ëÑø×àOzPaQ”(zÓ9<†Þ¼I·µ9iM¥ie  á=}z½›™/õ }c­ý/áî³—6sKDw7j_-UŸLt_×ù~¿±Æ`ˆØb^ò#ˆˆ ÍA’CH‡/p”† C‹×ÜÖÓð‡c}Šq<Ï>‰ýöP¤3¼‰í¾ó×0ȼx.d(<ÿ·ïê‘ö˜oA`‘W^„JÚ<‚#!¿Üsœ@3ꘔ3#.ò]ë›êÖÝæ D–.{|çêG“ôý.báüè~·qùƒ C¼òü]Á^'»Ål·¿¬·Èb‰"`ЕZWpÆo( ’2ÏýQ°xW#§/ dÔC§ã®1‹ØÒü=ÉScW™ŒDãª$‹€T°\ ŸhŒ1&E¹/†Ø7bÑ}^AdUX!ÜžBP6†À&ñÆ#4=·79 1ò:*2c®°iŠéê¼5±ôæúJ(ˆÆ¸6–tlF€2UP E@bVÏKõ)Ú´÷,ó?n¦Í|‚#`Æ Œ#À$ †KO×Íòýÿµöÿ+¹Þe Õ™±G©Ïvü½KÞÅZ¼è¢“ˆôÈ$>ñjù5×_¥dÜr§Èù<(#B-ˆùç¹õ”î½@ëp‹çXPåPwÉ©‰A@ÃÕB¼ ´’™á%{Ü'û¬í{Ö«ö?ÎaõL‡Ë =ß—æG÷¹ì—î<º˜ÇÒ>ìö:3giu^)›gö^e­È¸ƒQ´I;’«TózhL¡cÅ Ha©Ô=œðŠé² ªÓ‚A@’ŠÊ™9BóR4¬úd3§4¼Žþ©im$5…À)ãüá¯ó °-“µ A@c’Æâ]Ý6!3²R‹]¤oUhØh Pl¶ÈÁïÿ 5ëÎÚŠsþËQêïEÂM4^µOô¿ÝÅyåæyÜ‹þ–Ûxy׋‚T‡ÔúÐ U© ©}ntÀHAÖŸÛ¹ŠŠ ¦Bä¯ÀìPÙ"½oísà䂺0â€=Ñ’àR’_O²U­‹Îc¬Ý§ì|‹_ýñGìÿá(öLj¨¼ Ÿ8ß»C #TȈ¦Ä 8zóûpfaÏê¥1 6n¶Z]?ÛªÖÿóí|3\fp¼‹`/Þµâñ\äáã{°/Û¤_/JóÕ¯¦Ç}Gy"}ïcM {—óyföD¤|œÓx\)ìøi&.ªT)½Í¿ÚH¥¬véŸñ'ô³MÏã÷`&~½ì4+•5×–åþôcp¹›mÔÛçΩ×cxeFØb~`¶ÚMûiÿ$œJýýŒ~yœHß}$ö4k ‘mçz5LžÕø¦¯/ÛjÁG¥…¨òjeV3€¢¢ÁI..~ºúN§:R9î—œúúQUåW›¶±”Æ¢q=Ѭ¿W5Yïa þÎsônúÁ¯Ð£Ùis1ïöfߤ²ó|¯Aú.X08Û¶E|ÞÒÝ¡‘ +]0m2ÒbÅêp]¦.ý™óqõÞÃ{›S¨¼1‹¿5²ï!ŸŠhÊnáÎz›5ñ,¼T“HQ´±Uª™G£Êï$º¼î7&¾>}>Ⱦ2_Vý‡«øà "ã£PïùöS§¾o“)#™m¶7…c”˜„ËäšhRƒÈqîúT¥¡0êZ^oYôÒž¦A¢OvÕ$é÷¸mŠ«1ÖºŸ²{\,¦å3ÕÎçØ¢ß–V´¦Æjó±šW¼ß—+sÉ,Ì:xž“ž÷±ø”³56›mÝüœgRqjµ Ó3º8H÷8Û:ØÈuÝ5O½"sFðñV— +·—à5r¸ŽÕ©¯§+8µ«§yÍAÉåwÒ_=f3› ²Pe¾H'ß~?ÙG}åyv\èWéXê›F>OGysÁ‡Ø¬¶%v_<­pýÝR¼¬bw/kI‘à=€- ÿrŃ@l­œöz>'~^HãW§-w¹îhmTïp L›«BÛÞÍZ/é¼ ÈIÙ´J±[Єèaj|÷]$hë?󷼓áÃKû”Çðú”BÜC´ü]ÍD­³ T.äìn{¯å}ïZ¾‡­ºcW^Ñô’¾Qÿ„ûXÌI=ÜÝÉ~|YmýR×ÊùÞ9¯[¶…IB1gŒz·‹÷ªD‚½§Í¾PiNú‘±{[Hu¢Âî¬Cæ9ØFIÿ`þþE¦Ù~Bí*äÖãEÍ©íUk¬—”²ºZÃ;mz’Øjy_¤dÍÕðÀéQˆ®PáCPîm:w¦û˜ÓîÌé¨Jš»üçÀìvlš­?ãå&— …ž ó-µýÊï:U)Q6ÎϬ¼ùC¼T/K6#@âzvÈ ÷r³ŽñÊ|§Îh °FýÚ6ëõ®\ê/¸mö;ð_óz”‰¾éW|Ü9z!,ÌÑ:S1*,Ÿ¯²½Jü8$TïäGâîD=7î¦l‹tª-äç^ÕŸµþž@téæÇÏdá3z]n‡ïþê†P\-_¦Eã¾±r-o…?Ëf¢¿¢äÿs /mðÿy¼¾»Îö‰Lío߯¦Ÿ¬r`…J£Ú.åh”•°l{ëI³r_CÖp“úö ”ãÍd—…¯cØÝZrŸSƒéëæùð± ª¼õ^:ÅGSÓ3 t Öû†MÌ» Xq^§PØß¦u ÈH®@ Ë*øgëAÆ{Ä_@—ƒ,ñôq3¹àêSm]!Ë“¦ñã úJ†²"…וú³.KKt6¡Ü8tÛ …Ζ7™Mܡſ+H4DU%Šû 9^!9‰Ð‘=²Ë\ùª¤T¤¶Eº¥é¬;+MOmž–®Çwаë÷cMÓG°Voëíª$Ï‘f•c_‰Æ‡w+9ã’Ô¥éä*{ÀÕËú-öªvŽuRyâ ‡·Hùˆs«9Ê÷n×ï80?]›¯‚’_6ÆÂÓåÚ¾g¡ÇÞ«î¾h4 .qåÒe ÔY´þ5˜ÓHÞ6Ýcì„/1KG€L”³÷ßóŸ‘,æÃ—oÙap·MÙ›„ 6Š8ï %\òß_30@'ÚÃ¥kÖšÖ%ú¬H ‹µ£z”F]tuzÄ?#Îç;Ù:æb‹íÏ×#é*8^ÂvÓi¢é¢ßDÆ ˆxž´—Ce?yIV.ç=pÝõåm²/V["æG—o¶L¿6«Pý¿ñ"˜·¾çNRÕÂΩŀçN–˜ðä‰àXN¾AXnâr6dÊ4Î9ƒªÇù¥K¥©Ý"Ü'T²ogRÝq›ŠHÐøœÔÊChm¯U< Û|/×û­ÇÎÙWvþÀ"̨’½‹\M›R‡A~©gã£\“aÆþf³¹/ŽÃç1ÊØÞÏaªÆÞcÙlþ(¹ÎSœ Öò/¶åþmÙñbã1·½Gx]”Zk÷eû`P¥%« ?‚b%âícaÂñôãfBÞ½/k=’û¸3lZ ÓÖ“Žê‘Æ^ß `¢ ‹!oÄÁ R%†ÓªíŶÓ§6C‰RªÝÙ ^NFÖù‡æ/¡Xë#Ʊv7TÒ½Y„IÙϲ¬·QÔ¢†Ä“ì±î)C. »ÅÉÜ ˜·iBU¥Ž¿÷Ot•¢öÞ$R[Óõ±l×Ûh¿s5¼}~Zy¬}NßIÄ8„Z¶™B‹õåûëG¬~ëì#–räZw…q<°í¦»[¹Õ ÂäÏ;P(¨ 4…Ãk ö^òdî sv^‡Ís¿›Lý@úÕ½<7vª=›î‰ ‰ŽZ1ýW`°ã  Ô¥?bJ¶»ïÄÝÌ Ž33$ùàÑfþų5ªa*¼ª¿*mÅ^AÑ8¥ÜEµvÖ&òÑT‡¥–XLº-n{“ åP¸ªü›¼_ˆ^³bo¶¿9¸rÞ;4ì¿Ýóôi›×][QåŸ0R3n9=½ëKá ËÖ¯÷´þ)—×Üß$êœ4¬‘>zì~õæÂÑ‘/%Ÿß—QE¼ÞqŽJx³íþÖð5˜œVTíßgíòÎåüíµÉ—p ´sdñ5ÇìÉÞmäj½…ÄÑêÜ=n™"Qi£³3”jp‹ØOîPy¢uWh-¾ßy‡ÞÏúÕ~oÇ.ÍãñÊtúª¡JUß2ùû J–|ܳ¨vAMˆžWŒ¨„!WC¼jÇOò‰_¡ Á¸¡»\ÎŽÓrpO’c¼6Äzc©¼‚µÙ;šR3ÞBg‘9‚Eé²É u®_²&{Ê Þ B8RœRR´šD~Î"² YÃ\)â”<£÷Õïh¶¾g,¨X-Ãn*¿÷šßâ«Úcö}8p½4‡PŸn:ñïÌ~ÞÔŸÖ@*Un<½M„g5—£îXKŠÖþ!2ù6.ž%žñõòeíÒÇC0è×zÇ4ÇK”Ë©¢¼ ÏGªåŠúzþso—S\Ù8¡BÅǾ3gÕЙ#*q€}ŠÄôÄÇVzù—C{0¢`ñø}ÇJ¹ª½7ä^'‰õ"ÆzêÿìvzÂãyTÕ•³Ãí£@ûó Ï sשô´ëlÛv‘1z3×°/‹Ù¹`à³ö5RŒPL~]áè¢Þ žíŸòiOçÎ%¾ÊÏQôÒÕÜbV"k~¦¿i<ªmâÁŽWoì…ŽËãoéÔ$;U}ž?kÏàâ×,Æù`ÝñŒ¤þ3®ë’®o8ð\¿à1Ê/-0aµYÔo%nôýðàF³¾†ââöÓ߇Éû¤?1D/eÙÒQüÊ&«’–“»*„LS³h’¥/™i£»žXiU6Χ‡yÕw§£fVP³Üù¤¥» ßÛ=?Á7ÀÇú6T¸Ý÷‰ÕîØæm)þ¼ ¶l–&AÀà5¼®ý#¨ù“~+ƒ›f®DSKŸŽí5fš†³uƒm|ȯOxP¼oŸ8®Ø„!ºFóñ²ÍÏõ H€@ƒ!v³•{d½3®„/e‡PùKm_o†Ÿ Ç~¤#ššã³®ö,-æKx­rö½ÑñÅÛ²øÐ¦;÷ÌXr+ËJ¿Iu¿Ÿ¾Öí½_ ñ5™l¿ë§íü¢øû²®Dš§Óâpv1¨§ºdâñkŠ{5~4h½:±¶Þaêj/ b"²g{³í=Á¸q|‚…ôºß÷W yg;ÚÕ¯ûµ·öÈÖœúã3kh²ÒîÜ#tž×y¶»t”.vêåùxÖˆgiöC°Kn‡Í”òÂöÙ CüûwÇRøãøém6K½¥ "MÿF§#ÏUè9tfÚW×Í‹[Æìj×5Grz».§%u—ÃA‹ ¿öݳâ¤Âsºñ#;ô1Q´%/…¤–'YÜò¶Éh½õ_´Ï·×Sn¹åµ-âpñù¹8½î,ëÈO—X ¢Jw=&zµ„œ/RÕ‹.“­ÄÒù=ºø5Š4Ã{¤_J—:iE6þľ×ç°‘”Úí}­ílûÿë®O¾U^f—ËÛî±o[Ñ—:—FÜ.ì’gÄ Ž *·˜Þí¢e ¶’Œœ,—èW< ÒÝ'À5pãèjõ­>Ÿ—ÇûýFúÿßñ9 ”k(* gîù~¸Í äëi½åS¿|¶ÃrlZñ.¾ö'·×( vT¾aô†6¥¤—´Ò«‡U¯¬xöJVº“ËRU0Ý…`ƒ´L]!¿ FôÕœ½ÚÑ-ç¯A“…ÉöpÓëfL½Ãýÿ 2¯lYš¢?oö«†wiwëQÞ¢üwxüÝ«Šââ$_ò·“{ IÈ—óGc«Á£TÄ®ûšyðºÈß'1pŒ èN«ï©uF´þ›d²ÙíJÚÃí£ª©Pýügg.‰‚¥Ïµ’NþÃs³m¸1H㘧¶ïÏ_ãç9 &m½®sè•&ºð$û“uÉÌP¢µ åqÓbóÔ—½þ“}y¼ìe ‡GøÜlÈü÷Ó¦3ð¶ÞÒ4Ñ’gö¬f<µjmŸ”Kä.òFîNäWI“xnhŸ‚¯_ê 0¨Þß›²­ñ ™£bÅ^ô—È{kÕ[ÚÇ2¿þKí¡™íèjÒùl®ügúS¿4¿^ZŸËN†€ÄíyûKœÕ«Îh#»Ý¹?›N?9…UC{[ãJ7—Þ–À:ˆ9tÔ»S‚$"¬gdû=ØÁjýfû‰·Þ:©µû‡ÏÊzÖk6Ê Âlǯ_Ù¤¸È!£ÿYûhÔ®ÿµµg¯v]»PÕ¼'ë;§ð©zI<Ö%$\4Å(°7ñØû‘+XP‘¥·Ýö¿‹R£L¡HÒ±Jö9ìûGüÓ;u{³†”úñ¿‹ù;.¦ƒ¤g‹p¾sw·8J|ð¥¿[3c†{’w§ÆúÍl懋5µ(ÁŸŸ‚Qi4+{ÅSÊ2ËOÉþÖÏ…m]–õönÙt_nmY?GáÝu4ýí7]Uð _òÂ÷×»]Å>îVEå«åêaåRÜýh¡(ÜÓ¬©} ­†·òŸØèù¨ ˜´Ú4;’ìä˜hn8¯‘•ÀÔë 'p¾[8 ¶i÷vßQÄïöeMDÝÏFrcŸÃ@bÖ9Ü9}[vË{UdóOÕd!òò{èÜŠŒØ’x½òž-"¹„¡gö¤èÿ²¼í£Æµ¿.º&f‹™´BL§ô~w îc{‘/ýÒ@Wìñë­<ðì¼f»S΋yD›±ØÀãÀÔ|¿»|û”¦yºY˜%.ƒ¹Mû¬’zôäöí­wU³¢o9²C¤Àðz:4ú\sêŽ.º¯gç¾ @'tÝD}>–2ï™ýÕõ¹8p›¸‡]¡SÓ!+1,Ý-Ç»ã–eÏZõñ;iÏpNÛ'ºÎ…2¹ÿ„Åoëgã7K-ÍYÄáVÁ1å§[‘‡ÑÊDàU7dcØ3•+äÛ¬¨íw^Mæ›á¤u°@¼“çj(: …´oVA³cCZØ…oÖgœr‡¢‹M²à¨ ¢¨\ñå"=ÍJH´’ìÏê/ë忦VkÄâDQBöÊÒ/ð«óž›w0USËËå”éµyœŽîR÷2w6 ¬ó§;Å÷I\i.·ð6ió«ŒU '57TnòîÒ´*°îuw´Zå4«£'»ã¡ÅÙ<û)…Ášäºµ˜ÚËÎF{Ó-oûž¦¨› ñÁq§¼ë Ah·'Þ…¿pecr}Yʯï¨;–©nfSÑŸCåÀz>$¹7éµ§àé#Qõ(Û_£û:Ïd#ôÓ.¾»$ö ÿc©†+×óˆ=X‹µ÷Ñ,€ïCÄÌúZvy¸ZHº^YäDgõsªZ{KõG/rT,ÙØ,¿7?™&eÂï5ÚM™ñZ 9>éý[\£_rH±ÚÍšy”ßåÔjÚt§Z©/ßó1W(ÞmW)ÑhxUÞ³geþõi®|ɇI ÖÓÊÂ'sîeå`ö£Ý©GL;Xãæè©ÊåùÛâš›PÔχ;íSjáuìlaáÄVtýÑ´Qí/ES“ëc|YLm‡×ÞÙÎzÜ¿·ãÿ:W/`0b~Ž"@?6PªƒÄÞÿ:ŠŸ© #†ò~ßkIÆä³v’’yÙtqÿV|‡ Hk[Úëe±i"süs„ÝÁj¹Ô_.h¼ÃÃ,›éÙÒv[Æ+÷[ŒœXÕÇãpL(U»nL;Jï!?±çÉgQ}ö§Qw-Ç•¯ZÕÑÅ_Wí‡ÊD‰¢3ï‡?BÝДèㆭe?=3sýJ@â;5ì`rk¯x:,Ù|~ƒ¼_IÒ<×ÊeucŽD”QR¹ÞžC±™|ó«Ë@øh]x›<¤’ã=B3ã&'"÷!÷ƽ…èÁûMÙ*÷0×½ÁÆt´nD´ Ì<&Ùþk¼lbºÖÁÇý¸ß˜¼à|ÏJÍû`UèK¿ LÙš5|­uÎ:s†±ØÜÌáânP3•xyÐÖ)÷Y)x<ò’¦Æa/*»/úÑæ¾×¸Î=ô³%$?ÄíKîšVSÔÿ?FŽæäúN‡ž^1Í/uÉ¡Á¬ßèè:õo¶tvŸí—üÉ‹uÕì½ë°*oVq?s³wÞYת­ò„ u¢˜’àwzqØÜH!¶Áâ8¸"&ÏÓ©8'qHJqh׺:ÈŸMzN¥øtoÿ®GYù™‡·ýF?¡Bz~S[ýléD_ú ã=ôÔå—sùJš9éÆÓ•‹©oׯnâ.öÓ}êįè¢Yè»yŒ–ø]xºÿŸí?¶¡¨£´ìÛ}x÷á^©•ºoKÅ ë´ò,»ŽüÍâs‹-ácÂôð(¶Öo÷¬Û/Õ¹CÂþ”õÿ˜ ¬“)¬ÊB4P-ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðüW¼ZÄמÞá÷(‰(M}}6ÖnëŒíµŒ_l2ÐÓ6(ø>|ïxKMKv`z8ëlöu5ní8*ÐqR€µšuÐU¬@öº‘¬Rš ßŽ l>îŒWÀŠà€_)A-Œø(ër°{Ì{¦™í«U@Í2ïmoº\;1¥}[¾½pû¼ñ¡|šjµµUÁÔò {…½JO·Avm¶­¶éÞuÍ¥ @=™ƒ½ôñ{ÀÃÏj|õ € ûqñ½·¡¡¥ï¾æ_^Õê}â÷»{œÝׇxžè‹ÖªŽNî÷µ&º§]Üç¶ôôvÍlÆfÑ ž/ݾß;ïCt€ˆáÌnVš2Ö„[Üc™éMÛl÷HÞ«¼7x;p_yCWCA§l¹¤:מá¼Ï}ðÜô=O2ʇF@îÝÝÀ§™ãåÝŸGÝ{å %&MW—sÜw|{µ;³aÕØ¶ÐùówÑŸ9 P‰öÃ>Þ}pr˜:šÑ×®|ÛÑï½ïHwdZë¹­×E}ð|>ûß\wÎj]ŽNô óฎcµ1)¬2VcéªN«òzéëbT*hd³€0 ›-AFÐ # d1…eÅÑG#Aîn‚%;ŽŠ@Ó— ©3€A9 N*hê¨tâ@¥zmÝp8:añåKÞ]ÜwÐto Ïyðœºñ)¹‚ë©öÕO@šDÒÁ³E°íƒ¬>¾.ŠCÛl<í^š¨¥å‘5k^vt®ßaÞDöäí¶ù÷ÇĨ[VÛlÌ«Î8ëïuîÃ;ÚÍy½’ìÛŽC¬ç©ç^·¹{Z)çwƒ®Õ¾ÐÞœUÙµå¥.Í*ѹ˜; +cƒ ã©of@„í’Qô¸Õ@ 9í¶ÁØøä÷¯xcZ ˜R„÷Þùܾùww|Æ ¶ÄÚÎï—ú}rƒ2…5m°É4¦ ªko\ù›Ù¥ •µ³c0˜[ ËMë^›ÝÃQu°³‡Îíz›4ªXÌm»Üy{i›B%õ¾¾‚‘ïG³R[I¼÷:TQ(_sôÏ w[—<‘õ ¨íöq¨ûwÁ뢲€ÝÖ§yìÁó¸9T<Ì©x€$„&&04a'4Â0!¦CLÀFM204Ñ„a2 ™14i¦‚P@Ð @!2dbmOCJcª~)ìÒ›%?B5<ž‰ F›€¾Å‰!=¬–lQkTüK Ê-éÁSÃV$2±1Uý/?®§LÔ† ÛFÖ©Fœ„ ™d“&8XVÊE[Pµ)QTŠæ°£ :ãñÿü?è<8ÜgñRV1^n¹Þ†ûCÀ„Š€IG½«x)ܽ«‘ËÞ48hi:òr¤Q® †O-¾1ðÂÊ›^p•‚7½ß'r´gå'$®1—íúî×ý¾¯ý]Ýn?·añÐÜÃiÃÓV*ª¤?0ж`Z*OäÙ J†8Á0¡r‘G3%*)•¡Œ +1Šå1‹bÌBµ"Ÿ·i l’Q"”ÌGwì›È*u‘T²‡ r“âÄwGÏ@CÍDAì=&Ûà}ïU€ïgIæejŒ4NO㈈öäDÃ_Tïo^ådЀ%@9¦€8U=B}€B$ÿìÖuüÁœEI½éÊyˆùÔ¡>·ÖúÞÚÕAþ»úyŸëjfêj¬‚¿®ÄrS¤ìÈVÝbrÊ©ºÄÝÊXRZjniåÌ^K’b‰Q”"³ˆ±e”f¤ ¬ÿ·±dSyñÿm¤?ÊoÂÿ»ó·øóâ>ð·? XÄŸÇMETÔPd €óßî©YfºÍiÍkás4;Ìøoz×+¡ÌÁ"&“³,€œXlËR”€q J3€l2R–’$"f‡@ˆà".xƒouÙ‚òhØ•SA”ݺH*P+·4$»°æ²¦ÚV•ªÃ(ÓºRÑ+2dÓ *l^si¼ñÅqÔâ@X²¼Jô\qs¤(’ëQX¨·w„@õZ—ý˸ìM|X=$ñ.õÖ¤gi²*þí!ö³©@ ¥ô?n·‘ù“àLú¹ì(´„¯óÿg˜2@ÝÄ.0ýuŒ×»KúßÅ^²({Öz:Úîí"ÞcDN²‹ì=LCçϱ8Oé©ü>·'öÝPä§ÿ¯ë·×üL/ï]³…¡äù~.Áýrù'­ªüHžK×WÍÏÁ¿¹üÿUqÖ˽žÅ6àè=$>¬O½ÿvÞçý=ö\¼Ìã ü:˜ŸvúãzÚ:¨õ!'ÉèGõãæ¿¶—¼O¡ í¡ï`«ø¿áG‘ÍÉl»É_u§ñÃNÜuý~µÆÏÒ×™aÜ~¡SÎÅÛ{¾ëŸ§ô-öüÎ,}Ç%“¸ÚÞñqõ±ñ )xGþ •=¬ÜDó‘ý!€;c •zbÍá1DÅ)J÷”wè ˆIu>%OVžc"TŠ! ´œØ¢hß:O;¡ß_5¥1Ûûº»®%ÝAm'iZaTúï<+½Góð?]ØöEQq¶¤{u¦ÉÇL–‘ðD·Z=–NÅn™kÍeÁ‚‰ _æÞO܇åYeô§ð£!8Œ¼Sï}ÊAT#$š1Éû¿Ÿþžÿüy,~ü¾ÏÒg‡¾ã:Yþ×§êö~Áÿ0ûø?Ÿeö­Ëòª½ ãawóV’À§$¢Ñ d¹=ë’ÊZ;ÊVj´ë‘2øüÄ3ºµ£ÄÇ¢ºE/Á¸¶Jôâ™! Ô`–ÚI“kÉ˼yœã„ÑŠ£Òìr%~”ŠéaE©Õå_l?$‰Aí/ÅÔÏâ?6ËßÁ°ŒŒÀŒÈÈ!ìbnF tG¾FDØž†ùOp(ÝuÙø¿Â¹ã„øæö½üG×ê†RJ“Xh¥¨†¢ñ–:©–ñaÏuQE7˜A¾jì¼£7®Q)Õ*ýù»fb>*L@³OÜÒ×Ui}Ê?tg¡@¦jMw¡š¯(£ÆGaÈëØ‡L=–ÚXx H!& @T°ê p£{÷º=8/œ¹29lße±M£“J8C†« ðð@ ߿ŸEv‡?ª³[)3¯¡ºZ6ö¢Y¿)«Šs¾ýt ]±ŒVÁ=‰‹õðï l¼ÏH¿ËHι•tóÕsÜ@C<¾-'Ó35—AôÆéÍôxÙ¿G˜„à Äa¹å딸öö@‹¶J;×LmÞ¾@‰Ê%«ÑíAY]ÝšÞìB{i€¢YÇ^òñG†<¶Á³æ‘‹—7½3®øWý÷ifÐçâ"›žíП³T¨Ùýtà ñáŒ0ê²Ò·Òz§Ývì¼Þ~]]ÖëiB§Ñ¸Ç«þ0¿}8ïÆÐØòÔô{|vÒéÿ¿²Šr |÷ׯe¨‚~€`îãÇãö-³=­‘<êËz‰b¡ Î0>ý"øút–—nºH¤aÿWè×K£ÖQÀXHÀ¼4Ï„ºi)ïrSG… ó¯äªñBZO‘´aWËÚ,õOb Íœ¸Ô… 0# x¿j8[+ùî=Ò§s—3‚”z ™7~8ʤ_©ÓýJ’î¬ñýôœM%£*¿°ˆ.´OÜ• N=Þÿ|N좂¬ÅôÄo8ã÷¶P¤­– ,²ö~?µ~íj ‚*oE‹›îæú;ɉ¡¢Íš°‹Ñt™‹VÿKý‹¶[m´:W¢&NœŸ= õPwY¡ ŸÕÈÁÆ-Z'iPÖ ÜR,þí ÷ë‘jÕ Ëæ”†À ÌDô9 nȪèˆ[ü¡£Î¼ã>üÒ6Ë w#'ÅW0çÝ×`i{w¿Ý§ÒÏÙ­èÜê$Í>&ÿ”ʇ—¾~c2q®Tmÿ|Eãé½QÝj‡žŠ¬â0×.Œ5š½~áíÞí¿~„TÀ¨­- îA"T}'IÇ–¢ûÞ4•kì.[Ù­7ZÒ"|3œû³ÿz¯Lïßç}‚Ópo¥Ð3aúM°{>zr²ÈQfƒ-§jý4V‹ÀQ@!o«›d`€C ŸíÕÆÍñRȃÁEUG³€éEA¶öØ ò íÄý|!±°{½Ö×VâÍŸÄRü¶ÉŽI¾}ÈñJ:´`›#nnnßø¥}Z~ƒZlÐÅÞvóÓþ¸UJ«>«ç»îëÆsÛð}Ú÷ý© b§Î’ñôPAHFK®Œ„‘’D‘ñ:ÏzN(]©eŸ(@žŠú`Ž”`,A‰"¨ª äÓü½ÕÌÝþOL¶[$$è8É[,!_—|iá+" §z5ž9ƒ â4ܺ+VªÕQ“9Æj—ÕK¶™ß*ýéÿ[ô{ýÿW[ËÏÕ>mÖ,²EõÒŠ*Š€ª(ª‰”»Ÿïž{GRn›iãªäRy£Õ¯§Cå·t)ÞËÁ²Ç¿ÃÇBüOýNjüÍï›7?&¾²Ž×ç]{³zI¼=~nw„%|z"r5Ö&N[½Ã]û/<˜j[Næ}%oàÕÕ-©6ºÚ· ‘"ÀœÒ‹¢!¾ UR¨E+"ÈŒ‹$ŠI" €ZÐ!)9=§ÒÞãž§e‹³¢aáÏó,×¼ýÝÔ€}Ò ¨ˆ ×ô¢úÍUUQD[ßâÇÔSAØ"ªþÿë(LÞ,Dš‹ŸšT‰4$™!2 ]’œF wàd4àlÝÒKùLœ¢¡œ–µQ™b¯w&ÐãU¤JüòæañD!U[ìxaµ‘‡ÜzߊcÁ]£D0A•³@ÌUB¡AÍêTDíÇŽ¤Ë³¶1iYΰ„¥)J”®kZZó¶I{Îxã qÇRð…©BRµ©9Îsœå.fUeYÎs+]PðVTÒ–Jì2:€ªÆœËjÛo­¸Û\ž½`ûŒ5ñÅ÷ûþü÷ïÏÝéhžÊ¾x^ý²¤>ÏBE}˜Úpb¥Ž'lŽ¥(©þ¢•RbŒºêÕuºrç<ê ËåE= å¸8eÅRljÁJ…¢Ã–†¤äˤë"•·”ò°¨O¯nJ˹s¼³¶ÇI ¿mÇ#fÛZ.¸Ð‚D…uÿ”,J’öc暀ȇ†,™§õ3ô?rúø';>¯iôß§"ñ=Ì ’)/­ÆɉҤ¾Ãò„–k@1 Ù²2WØW¨Â­ “U9¥î,$©Ù(ÒR$›bЄïÃÒ;¨ìÉ,‰?öM§èÎI+FDò(:ÞǾ½¹GøxC×5‚®4‘-VyAƤëIJl²YÅ£važºžþIÔ±`oæAdsͰ’ «q¾«°÷”YÔ"\ÅÔ"kûŽW7:{ß2qò`Þð5¥¯ýÇ¿ö^}‡Ä×¾q¹ÔVATÍ^‹a¿ úÛç#™GEQ‘™U“Ž×=æGÏîGír¹í-ù°ìËÖÇí¨{DD> æÿ"Ï,škn„“_èóü\?m¸UT€OÖý/Ó{} 8ðy­l±¶Ú(ÚĵüºÛøÿïì}ÓÎìxÎ1¡\/uÎÃ\AÀ•²6Z¶äâ`›Ü™8ŸY¡àŽ]Ť7ŽSÊYöB”°¤Åšìú ñb’Ócå£ãöå8…Œbèˆ]>f麼§ÆX^ˆŽ+ªMr_€¼ËðÔÚ¢I|¿QÇoŸƒôôç¶\Qæ˜îù|Ъý3sêtsÿTÒïØ)ƒa¶³\¡%>aÏ1L8qÆh{zçÆ ÷sa3^¥WÓÜÂ~Z€Êë“ú_GÅÁ§â†¿uÄ—ÈšžG­=éj§Ð\4ê·=Nèñ£|ÆDç!Ú*&ºy±>w‚¯FöâzžŽ‹}ßõuØw.¼{0¹v*xÔ ©ôÔÈæo O4|Q<ÔV³t²ê¨AC?#õxº%–}ª.zy¹»ñ z~‹u*'rï×~vdõz?§íÜïÔ7Îv䦙´|ݲ9unj÷ÚNÊ*ˆÁ*ÙÉèøÈ^¹ w*XSßú0OŸ ~шV©ä‡dX!‡Nèd°ê8¼z<¼ªLÙ’œuÅÇ!uSËI‡Èê[ŒŸ°z«‹Ú_»‚îÝÕN>&¢ôÁ’&Ïåh™eÀ„#LyÊÄyûÞïÑ&Šª˜-›ë?|Vf85×cy`Î4'º–ë±¶9¯#C•hóß—ëÖGG«#Ò¥/²›=25u2H‰ìÿ§þó?¡ùLoøQïÚq¥îîä·ÖtrÙxjKüZ£X£A8^ù9\QlŸ~…Ó ÆP½'ÛÔ€—õacGÐóo»ýVSWØ©o2|ŸÈßÉìÿ¡‹¬ÿ?탸çQ4fòÇÔ|UT9Ý.’R¥šR§Ý2Ý쿊ÏvKÁUÜFᕺ,*8ÀhIJ×Å„Ð-?¯¿o;ï ycágƽ¥õ-L/øÜÿ%Ü£ì”_3j6ðƒ{ûLñ¾ùÏe ¬4©ù[Ÿà|ÍB»\fT½µÊ£3…:‚SÏêNs Œ <ÍåRǹ ÈWž³5&<ÈÕ£úÜ×Q›sšé©ÐÒÓ4Iª½(1]½œïkS¨XÀöWq>fåÅä\u¢N¦âw/Ä~‚…ÉXA¦êâ• Õ„$šf"ÞÙ#ï¦ÓÒ€ÞÇÊÖñéÙç¹±‡Ïñï¬fs_%íª `?„*Æ'4ÖP"9ØBÃböõ ¶ÛÖñúS•ÅÉÖ Ûþüƒ_‚‰¥3o¯ž)¿Yä/ý.ùŽ!`ò¸yÜ4œÎ‰ž{@e’«w³}~IŽÇUänDr| ÷ÐùûÛ‹@Vè½ÜŸnñù¼ì ÏÇøÙ;žÏg„ÐiW§“zÚe¥þùïüŽ+6a/‹¦òm¶n•Í´ÜÊyÊ£š¢ù±Ý…Cègf¯·¬Þ@áo«]¡F|GýóÑž¾µÉé8Ba(È@E¥ù{Ç8Ô΂'Õï‘mp¬-t’ƒy¥ÞäžÙÚäQ‰WÙâü²Ãó ¿óZw8”÷Ë™6uÙñ0pî¨t½•7«´J¦ô¸µ±%GÄfú¥ áµrP:Íå¶d÷©3lÿªXå’®ò\4}"¨Â«iÊÆˆßµKlÌ¢ï¬ñ×ó”þÊ8•ïpÉýR´î7Ðø»Μ̵VÃXö%'j*†«©;_­ŒêÓß‹¥µSî›o{ëX™,}w› Î^Î2Rº›5C8ç²QãðÕo=»}SÚ¹u‚<Þåò]¹7»bGÍ?1™û0›­Mo­[Ȥ7ÜCg67¼q”Â[È)üÌ6 nSk°È7Qm»€V~¥ä_M¬ÌG®îM £w”6»|ƒ6ý4}¤YéÏAüÁÕ/5kN©%;càéXsþ<ÝW™Ïn|SÉR>éYœ5Ô=•%ªÑ‰#¿eZ?¶ÿUÓiuwß›?"‹õ9·ezß3‰@ÉD»r®MëÍ~§¡§kÝ= ϦÓ냮lŒ›¡Ñ´Å„äî­ý)ÜRŸacÑå{q{ÌšRêãý‡N’>ÁŸºý‰r2ð"xGäѯ¦ÛßåMš¢–G™Ç4âòqÔð‹~#ÉèF•¾%6L΢aÓ Å,‡ $O±˜Ï§ØS}ÞóÌÙ'¹#5…ŸhîÌ”)FC'•‘(UXÈÉIn |ûH¨ÿVÞi÷ftÄÂøš¡lÌEGüf½M¼¼lå]«¤8Œ¢¾ßW¨foJEiÙówÚá¾Ñ²¾–œuGÛ*K±ZáNŒ#sò"¯$Ÿ5"¦[»ãªÝ ?{‹õ€p*ÜÂâH1à6î ,ÄBvþ:,ýµD¼ã$êñØPÇ}RŽ×òvÂåÄׯðƒî¶"ÖÏo™—ìþWVàYnùvùpjù\ªCïÒø8*òY麅E9&÷§>г ¸±uŠ+%öÍq¿X ¹½„Re¤ÊÐÞ­Ï ÷åIô®ƒíp…ÌSéç'Xt¬Z:t~ïÏOzƒ†ÄÑonwµÌj(´É‚Z¼¤;Þ†Û<–Äúq•¼t* „ i6Í>Ç {nÂFCZácwØä‹ç%7°c`«*³}¾¾DJÿÁj³ÉeGtÓ‰-Â3Ì®ÏÌ$R¼-ß”÷®ÃœÒCïÓ4T¢$&r®hmð¿R×}[òž¯–×=øÔ‘ÿ`–:¥Z ™ú!8£NQÜ1NCOkÉ„Î.döÿÛßRº'ƒƒúG?þé’ Òá¼Õ“—Bý;2|y¦‰£ÝZÿ±D[7S}-Ë©wþYÏß}|é>Icã•–Æ7Z{¨Ò؃¦lRá0Sùniq?©iø3Õ*ÙÄñ;-ú{þZóûá½±m£uª úíSzY2¤T§“ÊYÿsîÿZþE¢×`d¿êëïWH9žñí‹Nf´ñ*丿/<½ú?7(þ“¤×µÑÿ¼ˆõV²w[îx!šL×y‡„£´ë¨x¹UgL>ó§Ôœj8VÑ,¹Ã7ëô›„D\±Açýù¡©?S4¦êFò¼uº@Íò¢Ó Cˆ)ã*«†ÓÁÏÅcaLÙ'àÕýô躻…àKøÔÖ‚rkMF+­3ýbkºõïò}ûèÞ8WVWûñˆ¼wUCUÁ¾¬{4’ÍO’ÎóÛ©v³÷œMµß‹^éçwþcwi\{WÎy¬)({ÿ‡&ÎI$üìOßȸmûXU¯ø@:P¦¸æfhAÜÇ%çìm}.dµ©I¯OI6mºLR ¦žvî¾Í§Ñ=Qþöå>¨åzzkžŒY#¿U¯ý2KÄ^}>M„̳©4Qæ_ažd'áä]Æå—Ýf%‘Tù ªH®{»•iEÞž¢ˆ /òàæk¤ý’§–ᙉ™ìŒš™ž‚ØàŒ&3|;e=*ÿi({?#ƒÜ¹ø¹Y9Dv¬¯U·]÷˜=·RÎ.Voä¡ÞßÂLLq‹KÖqÊu"É~›àví©Pbq98ÀOOˆ¸å¡ÇêO/ö=Rî %óÄ~TeÞ¨$¸ñ€BA€@#¶Šˆr)›qÍX^2 ¾•ˆm 'Êöµù\×Ù*Þó]b1’=‘G÷@¯éýÿÙ:ØbC¡úz–Ã˶pRÿ‰÷12é¿‚ÄÂÕNÏÂÒ»¤–-io@Nº=&Ò—±Žt¿O›±ù=‰HˆŸ-@ Š3Ôú}ƒõn—¢"¤Q|Ëòo¼\F úÒ;¶(—`v’Id ap Tž#8ýhKö, IHΌÄ†mÞo `Zd[O‡nø9áùÿãßï¾ ç8È)èŸV ‚*?Äéú9÷›ê,Ý }ZH²AdMiï9ƒ,SæÔ»NJÉ ‰ &@üb&M0Dœty†J *Õ¤•,‘*Ád°äå‘7òbQS,uñ¸W¼`ýçÌÏÕÁ‹4‹ÃI‹€añ)ò>ŽÏ¿lBÀÆG P4á äïb¢+  ‹#!d"†¶Ë!ùÐJzyð3ΆèXA<ÒRŒTë2æjLxÇÔoŒ‰xE•"‚ÉLÓv ²2É$HŠªª©É#k!¿öñ!òI”˜sG ‰)ÊÉ'ÉRñ7éå^i$qõé(µŽ0y‰Mwa ’†Ãw~t#±²–;ˆ„[÷²ÆmÞÙ}< â!ß°V¢oàž²e( ]×ñGûŸ_àFÇ|—Œ@aÒ¢©w"sênë·Ì§­ê u–A Û43Z-ã=Ni¯Ñp‹£ Ü&ˆ3附D†m›Ö‰8@ý"Èqè”]ÞYÆŠUdsîúHlXÇ✞ž÷ƒ þAx{°Üa‰ïpÝwó9›JNXÀRî£tRÑ6-B}(䎀¢é·æpÖY5 Tb¼0‚€Á>©ab ”´‰"FEUþ­c=¨»³.l‹ë‡´{>IKh&ñYÌc*õWÜb"älà‰åNäÕ=¥ç<ÓS§#!ŽV(Ñ—ˆ¢LŒ<[<§¶§M ÿP£* »¼N:ÐR¾ øp†ÅؘÒTXÊåEI6õñhà<Ý7z¸O„=LHÏŠ{ïo/ó¿Ú¶èÞü £ Ð cÎÅåÏÂ^§ŸÍk õ´FÏwö¡Äl—vn ì]G«[n*•ES3¬çÕÛ?›ùaÜÕ§sçz´¼/"ªF5ôG§j4ÉåŠêU w) ÇŠdíŒ ¼bF(ˆ“cÿ€áaˆë…cŽ]øš£&~Þ?⨇b6±Þ¾·C´õP žë#ŠŽž²|€4®ÅÃØ¦…| ç[|øðµè6¼Žÿà .)!Œ™ãz˜5ñëèéJµ´Ú1úÀÁÊl a!¤ï3Ä”P¢í.n*7P4 ûãAÊn²Ø0ºã†¥†C(gêéC Í_½þÔ´Iø„/ÙÚÄCe±Îò×]¿½âõKÀ½N¤N¤H"LO žQ=6K,X°ã»ÚÖ´cÆÝÆRBOƒÔhŒ…lTF6¤d*š’AŒ”Q»â¶~e@ ê)X8Âí=Mt66ÙØ2F‰ÍÈîF$‰*;|R°æŽa\Œ"‹(nx_N¼²ÝgaÄe=Z›Hq¼ž¢ h+(1`Œ‚œ¸0©$EJÅ’ÖB HDa,‘d`ª«E"1•„R EÅ›¸úüqõ±×T-$Ü‘Ïàݬ`Ä‘b•UEU`ˆ*ɤˆP"ÜÁÏÃðÉ£Qv:ôõ}mIÌ€{döDz*«©;¬«ØÀ„ÒL©q¾WÆÖA1TET˜'!¢f.íõvÊnÑTUµòTÒÉ~_³Žì€IÂÉ=¿ŠÉu€¤$z¸ñrK}yЉ¨¥ÑAŇà Ü–ʇÂÈÃ1†‹²~ô&à ’H$’N!gwJa­ºøÂóª}30aOJ¢ºÕ.‚ÐÃÒóÞHš»®L¢ùCìó¬Òbyýû– OÌC©;c§Ï¯·o:—Ç ‘á”<=×øqŽÚá"Ñ~"ªže»zò¨™® y³oknÿkaýœáêÆÙÖ¤ ½%ð£¥ÚÑׇá(ðo5/Hpø±Áa×·O~¿»ÁŸƒüPù¥D´°j)Aª5‰K Ê0±)mŒ¬Š*}r×ìÍQ­mT²ª‹Fˆ•ªZ•¡e2˜`ÚÕDµ¶ãTЫ#*[‡à}â¤ô`sñž~¿£ÔvÿDŒ:ÖqèvQUën¨º š7Ø?ÀôÂ7îeŒàÐG¤8ù@ïaß–JÏŸ¥×(SnŒ žœ3ÑHLŒ‰ê)³®ñ)fųu[áhÉcHŠNDÆxa³[öÈë”ÇñÏb ì ŸÂTdÀ@࡟tJÌØmï{{WÁ­8ç?Ùçë¾Í3Cüu9.Š*¯£AÕ~3ÙÌ0ù§YݼMœ[d/ûrïPÎ?¼\ø.Ï wÄ:têÔ¸_æfŸ·Vþßô|ÿDýym^¡ŸØîøg,º­ôk¯ØK·§ÝŸØéËÔí›ý.ÇŽXϧéG×è¦}¾ŠÞÙÅíâÇñ¿3B-âM¼þ3çyûjwºWlÛŽÓ?ñ'^íqßÓµÒ-²^hC½ñ¨wP—¯Îò†Hºa¯½µÛ> ¹™Íò—–¶ «QГWÎ[˜:ضMNj³r@œ0 1QMªAQ¡P9a9ÐF¨+—]$Ï™t×ëIdw¢h°ã€× ÿíÁ>G·kM'î—ÂR|QÁq±-Ÿ±£ˆÎ+ójŠ€/:"7¨]Ž € ¾àsM[c´Êyhõ]óíµ¸ ·¸ÄÃÞÒ˜ˆ7hÜtÛŽ°>‹¼º ¼|-ÓËáÓnv €ÁçØi¯ nÔ∢tv*ä½¹ïì±Ö¨bñ÷Ÿž%ÁOœ˜Œ+siåÒD]´Fd€ “Ì©N÷ÏÄïˆwÆÃ—ñm£wÇ8´CA;;sGÄÙˆ*îPE[©Ø¨cÍS†? íÊ¡}†¾ËUp’Û'c¿ ör\‡LÂý‰Œå¬½î·ã<"ç$c¬ËxåvÈ<ø]W½Ù ª«;}m¡Ð¢$TCy·16\ïY%cêÇËp¬)‘ºó®°^”P ›Â9z=n„ÖǃqÆ,]Wja³ÊòBª(#"«   ‚Z H‰-‘-HH¶¨€² H +È~¾– šytI¾¬-̉¡X>G8µ'ÔŽ¨Wù•ƒ,pgíò£¼™}R6†JQԲ˜dèPÑEn±KÄ‚œ¦¤Q’ëÇZ5V1ûît3å=¾­ú´÷§Ì>õ¤’4Þ¦ýÉ ûi^÷Ÿ0´8}?ÕR™øÑ› ‰)e )¹†Cù¢‘²&ôèñ*pÃ:⯙&çŒAy¥Ô/zÆ}Ý´ñC›¹8õOµOÙK«FI?gg^ñIqÐWM¡Ç­wí²Šo)eó„»ðÝðD  `Ú" ˆ‰)‘ªšG³² is46(¬4a: É lÐ&6Ž4¼ˆˆˆ"戫ÏÉÊ)³Rdæ*Ô%í:³Eȉ4/ŽIåx"ÆSÎyóÈî»t4T,;úuc"ÞQE$âtb:#ÔV¢—Ó†T’d§F‹’w%\ï ²ª‰M!Iæ;(ìw%v”LUµ<„ÊPB´ÝiœJQ²DÞÛÌÌ&fa32Ûo9zŸDû}W¿PRçOq lDZ6¦& !µO“­Ðeäç­Õd¬±ºwiÜ7™²lñg¸ †å¿ÜÖ°‚œh€ó"(ˆ'º$C®Ç†ü;¼:¡C„v¦Í;ÁIÄŸ$Ü¢º‚wcžÇ|ò@¿#ɼ¡ŽJþF„Þ¹¤£C=#á¥ÒÖÝls0LûÆ;bw»]5ÑiÖÈvŒÅ û(é õ&£›µ2g7@Ú*x¾DÝ8,V§§U/UdÐSløˆ0KDz”Áµ™½x\ßpÄó*‚»ôãE@Ôǹӭö¯|à&fœéÃÂq ÞTïZ‡GÒ^ƒÿ†ß³ÿï¡ë§›“­´N߯¼iÎóÒÚæ-|{{Œj$Šƒ–Œ}öÞѤtÀád¥°«J€±)d ‘%[§ϓ0”­:ƒ(Ø9ƒ™5öýI¤jj ­2E ‚Œ¨ ø1ÙÜé—þc ñO¥[×·ç7¿±Pç-oðC?AÐuñ¯´)UU ˆÍÌuAá¶ø*ÃǬÜwé¯KPV—¨ÛŒôY™ê«*e‚ÉÇû|~f:U0ÙÕd(Õd¾<+KG|ȬjB"ê9²HÂt6kU"L2Rûš7wc'wƒS+ËéÞ9]Š<,™+&ßb&5!MÐÎpÃ%¶ÈÍÔÉUF.;w.9롾|j‰<Ý0\¾ÍæÈùW-NòÁäò§±0ª¬`ðØlÜÍ8îHB è°uÊmÞ4AaÇ}_ZU"¯‚±˜ñ¼óý>ûÏW_mÇÐlí¢ª ³}sG…‡~Ök*¬Où¯(,…}i)òi(OäZwÖ::Ui{/'Œñ´Ú” Â$R-Ý|!~ ¯‘Å®¢#a†B‹Žâ½1„é«Z«G~™”„Þ©(}¼"¢R ì{.S#»(µ|#âÑbúçÉçlã´÷£»ŒyCÎMèÁÇTÏÀÖ§_°…Ó¼Ó ­—³l"oêî£*?™$„í\Î_©ŽNaÔx9çÕ5–™qÍ’´Hž¾„D&¨CÝl¦„/hé› –”›¼ Ð ù<ÝÃ"¦¹“§!=¼ð5ÑÇ-%..›#ŠÖ)XC¿ÃÅß­·Ýƒá*h¿d»xx_J5”Uí~G7‘ßY/Vîyâǚýê|/J*Ÿбµg‚»3oW{˜uGÚRŠ»CÐ^õ{KO©ª7*h^ŠO¹œò³¡u"‡•¸Ù=L¢•¤Åç‰xaá]þC‡¶«á¼ÓŸ‘íí}m‚|ŽÒç7WäíÞõYuOB¢s)ÍlõÁ[Ó~ÝocgÅeô,±ÓuMcZTöû;b6ÔÿAM¤Ýü6¢U  á©2ɉ.’H‘qώò“´) !FK¿Ãy}ºî—~'8t Ü*¾ÝÛ0ÈŽtèxz ­xW§T‰<8VDEReQP&™í‘ ¡ÕOh Ùé×L/å_~åõË*RŸM Üz-Ï\)xÒQ·pñoNð´·¦î{}xO ¢« Š”S$Æ €'õVñŒ @NH£㥗fìa¨•MP¬Íž¿'UõŒ!ï3æÉ=_y¾0Ó©uÖ1ßÒŽé×°­tëhŠ ¬m¾ ÁPð/ãB*/¨ƒìžØ£È‚›`Jûü‘<¼ñV¼ÖWÜ3ÅE„”¦ºC§V‘ÍüN»¶@kÖcî!ð_ Õ¯WJÍ—&»­ |)M4e0ŸÐ[]¶.>Ï«Çq ìeó< 0bîþ×»<†Lݯ½•yzo"÷ݺ66^á<žã¡#êV]ª˜[³â@‘ÓÙNŸ3 UrÊÚÄ£ƒÙÜ×» øóÃ<“PË!³s",¾VpOˆÃÞõðËil1¤ë¢²¶ Hƾ׽€’#~ [i£eЈCõöTŽïí\Ú*ü.ÔØÌòôZ.¢\ïo7'7¡ÆË=¡~ ¤ÓÝÙÑOS7ÈßäÙ z_Ò»ªÌ+J£¥šç ÒˆcLs¤¤${UžR¹#Jð‡“«½ééz™p_ ?AçõÇëôZ§¿”º½n˜äeó}]Ü|-„澌°žy}Én3öð[”—ÊÝê…Z؃{¶~ÎW„zð1Uý¤¨Nr_„Ø"Áv{¾p¶ö#??7>E8ðê÷tÑk=¿>¯ÛÞ6oÎÛ»r|ñ#=ýr‰ZGÁÌäÎ'.jvøqòÃÃáÊIîÎTÕvtíåÀžÂ›Òq~í¾Yk<¼_Bìºog‡uwÛð»ÕÄÛè…DöÅÚTRS˱ŒU¾Âú¹R¼2¤GÓݫϾÍéÜò·ñh>Lw’œ‚j{¢Œ Š)ÈïŒñãªÝ~»|u4fŸ«(ÿ“ÌÇg1ðÍš[ ›O÷ÏÚÑQYyÙƒà­Õ›gg§r`Qoæ%â»Åµ£Ö2Õyç;,%TíQÞ¥àÀí_ÉÎ EèœCÞŒË\ç—8»ny:¼[Yj·]ýîÜybuìqÞ„à§MšKœæÄ7ñ)ì±­l¸C»¾X^½ƒâŠ*ªŠ¢¡il;ô¥'AW=QF4O.íý¾ž“íÌe£7±$ß§¨qHô"œÂ•ä©^Ÿ Ts=ðæ‡„ÒÐê;ðs¼[2ìÕfí‘<±cK!ºuƒ4Zpw&8Àh.Ùa‘ïº1a‰é(‡¨³S§Ã™Ú/-ø&*TíS½òžÅ+“tù“_ƒ€ç\6àèá‚'§> «1Z‡Clä ó»Í‘UIœìyìE¼üýz"þ²ÐÛSeŽH{béR˜m#Û~¼9wf“¦ðÚ|hc[(™‡Ì#O ±QTÓ¼7ݼÚjÔF €ìù»ž6ÁDp¥³e(C:Ä_š|³ý¢vÌ£ZâÇ6vÐë)"i M²XJ t@™% ð‚ Ÿ ŠëbDà ùB†Ei~ÎkG¿¹ÙÊß^Û€I»¨’ÚôÁTLL’ƒ ~° ÀÖÌÊ‹oÑŽóý,”?ŸaK+Ø{îÑ“f%pWÍõï[øoÔú¸ØöÖm³§[´š_± $ò•ÆM&?jÝnyˆ—õÔ|“Æ¢ŽZe•üweSÔ©aÊóœ-ÕNË:R¥neZ©k©³.j‘qŸÖꇨ’\.ñX$! ²†uU#™ƒøü‚ÕõQÑgñþƒ¼Ûèm`x|ÖëU/’Þ (3æÛxZH„ó¦`«yÝåЈBƒ6ˆãT–'4Lœ‹ÌeU5Æn5Ôgàt±YEÝÞC,‚ˆß9.šJôê~z‰ÖüÃï*º`êˆû˜Ào´ñþ¹¼¤ëåàsÂñi¢ª½„‚ìn¶IjÉ’î:¹·ðZ_€ù2ô_G%7y ;k‡wËÌ(RG‹Å¶óŸÅªW ­Xî ¾îB¹I»™“ÿr™_MâÚÓë9ï²tgéfwïC²¯|˜¾­LüT‚ú‰ PÎ* (®¬¼ƒÅËÍ.þY7†u(Üû6òå Š»ÔU—(ypèØÝì碹¢”磔Ϯ9¦<û lõuÑNÚcÏø´²™¡| 9³Û·{óø¤sòV¹¦ÄÄ–=Ùá#<¸pÀ¹AÃbøñö3s0Ê!Ò§~ ÀõJvŽs×]ùi˲&<ÛNèoÇ~Îw©!x`sa¡¬R\¸Œ¼üô­–øT2L¿ ý³a8i]û¥Ë—,Ü”îÅŽÞÍûhÜÜX]u%(4Pœ§ôÖS-|³[U`iÝCn‰*fjÖäCœõðËÔ/…PNíºmݨ`í (ˆ ‰GæåŶÓ½6|z;;š@•[ëàEßÛÇ;pðqëçΰ/õìmê: xhDg<\§¶=îxö’5Ì[ó&Ó)á¥(«4Dñl'jˆ‚QçßLŠñïÁ“dýPSž@ºí§2sîßùé9PÜ(c¡Z´ñ²nÄÝRrqG1T«ÿ·:ñ1e×É8e ")*7–5³á6¤òFpÅeމ„¡“R“ Rò¤r£”{Õ‡SÈÓYtÍaüELV²r÷Æ0~ïYT{¾¾1€L‹öÍ|óÃáñÇ›¶RL"‹âÖ™%Âó…kL4ʉBKŠ#7Q"ËäøGЊÏGŽœ¿¤Q3>Ô8!Rã®X"ÇHWl× 2„’lY{y.걄³ï´$Q©ƒöØŒñP /¦|ÐÀÁ«$3~¬;—¾ÃTZ~ ‰øæ<ØùõõªØ«Åꦄò H{Y]÷¼¢ïª+lò“Úºá&ʱ®hÒm㺆 ‹3ª5aD‚C:|ÌöWgÛšß`l`²lT†Ì’ëU+)Lßš’˜ Ê›Éö.D;×RT>–Ùìû!Ï‹$ÖnÛLøãÃ\+‹×c³šµ-g”vȪúMêz××2S7ŽÞ];0·ž7.ÜØŸ€½Ž` €"³C%Ç(J[™ÛÀ¨ä¶+âGxú‰§šÇPc•7OÛuX¸×^ˆL@z!¦^ßÒÙ)ðiÜÖÍvBJªò¡aàfcHàãñï»Ú›Ÿ2µL|7äԉϸÕ%'É2šJý{í:Jªå"€Å`H&=q¡Pã=Õ ;‰¨(âŠy"ûí¤ ¯BꢯV]OÜYÔóÝão”ñÛ=j©šOUœœzÎ’C¸zw-àºnRj’ã–8BªÆçV!’Â%–g;ÎÕ,ój¤¥ ºG¡QŠ'±¢,(wŸ¯5×·ÅšÛŒBTÚ¥¡}ñ%Ead‚°}˜ˆ€‚' íä+dî¸lÝæã)r© ¾K:жJIÅÚœTT=.IÒúœ#AMMȼ–\9¼ °%›@UU Ĥ|ƒ‡8€%:t§"\ûê`«Ï±6„¹™‚záøÚx}þcÉ>ur;ò‡¿ÃC‰ò¬vörkâÓ­_vpxLõ§í:vm™¸‚:àWÔØðU‚Óʼnè2H𷈢K^>,åÍkÜÛ/›Þ“Û¯?ˆo§¬/<„NŸR o I¨»Ê ΰ†ƒo' È,*”ý^¯>’‰š¢H5úØ+¹½žßS3Õð;÷"¼f ÈýÛL†Ó!´éI™—û¹hÑ’I$  !BrB#}8ÖÃÐó»ï&»íÅiû°•:*·Ò¯iqf JÌ2óU8åZþ I Û ù;q}öYw:·dùšPß€î½ ºÂ¸­ÐLÞOÏær=ŒeZÁ@ðÚ"Qìâ[ÕYqÖ_@ ~úÒ¹E­§UÑ;,Ä©³€€F˜%æ@Ø€Ñþ/³º¯@±oWõX[nÎjòrj( ¿Ÿž& ïÓÅô~ÃMU…´ä^uÏnÜÂYƧusôä ø¶\_MƲä‘Ü!¥õ˜F3uöþw å¹±èrû%Ôîûìô†Ì@·'ãzQöÔ'²U}øª õýü<’W©¶9(LF3©èN77húºë%þ$c¾ñ-…ÞÀÄ"¡qtŽ/cÚßõX¼e4ñ¯ïí/vQÛ µ‰ú¥ÅUãL%£ÈÊ_^ô?S¿Z§î^7é9qƒ:Â.ƒrýä9Š"" _Û¾(F?{¶xã™*š²Šê&|ÍÔWÞƒ…Õ'­÷d©þêæ¶Y2}Äo(iÎçLzVx)E‘E‹ë&€Ðueܼê-Ú:P@÷Ûmûæüÿ›=䝿S—zØNY)Äß cÙ “¤·÷­¬åXo°€$ÕSdðTœ:ñ™‘…ô}ÌšÑb e¾T넯‡Ì˜ž, 'ÓÏ—†ïD³øWÃin”vÃJÄê\U^4ÂZ#)t^‡5ü*œž7é9pƒ:Æ.‹ƒrðÑ8¢"!á—‡t<4cö}0†Y> …&¬¢º‰Ÿ3uïÁª“¾»²TðÃW0ŲɓÃG[Ëž:¹Ó•ž MdMbúÉ 4C™w/:‹vŽ‚”§w‡w‡Ãžòwð©Ë½ ì'”Ó‰¾Æ’}‘:KqjÒ+93×ã‚"<¸ª ë;à`É ÕEv說ªªª¨ŠªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªÞÐL žH'Ñöýìbó÷Ô}ÄÑWO¸ÏÜoPhÎ*ª³BIú•šÊ¡ÈD@>~^7јt®ß¡Õ¡êôHrÈcCÝ¡ù(vH{”<$9ä4Pó¨v¨yô>²9¢Ib‡4‡\‡V‡6‡‡>‡<‡.‡½CžCÿHshy$;΍‡‘Cè!Ù¡Õ¡ïPÿÄ:ä=‚Ž9ð@{Þ<ˆ8nýÿ“óìôzHCªÍÊuñ×q8:"Þ0ë1ä2u5ﮋoÕuÜ·[h~K¯”•¹€ù¢ ¤ÉÏůѦĒAïãù×û»$?gB#÷ £“ÇÖÒÒÑÚ×cjvòI8.¢Nó´Îʘ68<ÒD<–´@s„«MØ€Áç˜Ø€éˆe¼ìg Á× Îð-ÒóævîëðÖIiÄøÚè}fîû¶Ø}WÛú8aßYâzßW‘ ߢ…o>õë*7<ÔÇǾÏ>Û`«ÒÅR3xÝéGŽÕÙ£^ e½lÓ´±ÝHiëf±p¤Lºe0Œ/=¸ïÂXÊ;Û}0œ•ÛIxo2âù. 9±l¯ÖÁ± ¶ØÚí¶â³ª ùAÜ›¤p@X9"y{ߣɾª}RÒ„!/O« 9F©IhneÎÖ îºÇ݆$pá#ƒ 0ÆEª¬¬©Ìì– > øÈ™©™áÙ»»bîúffl@ÆÓÎîîèîîáÔ+fgwwwwwGŠª¦ß囑›h`¹Ù$å_ÞcÞª«62âà]Q4X#ºç«0wlu5›Ž0¹Ç‚ÖdØlnÊÛËÎÍÝî8®ºµ¤Ö‹HÒQEÙ׊ö¾ ?oŽ>²2ï(uðF’v†NV•§g„­ªEVr¬¹£ôåß„çÛâ" ‘äJíË Dða‚»mà¯SŇ*m:iƒÉ8dáÑ—NJÑ[páÁ§I–œ¸<2® «nݲå–ÞL½sì’zˆ'ÅpóØ÷U^¬ûCÞcæFDIA_7™—uTµf–”‚7}ÓXj(TgFonÞõôêæ ØÃKoFô6²êÝßtÙAãâw¡¹zs338îYŠªE¨ÞíÛÛ5JOcªr&Vw58x;t&z©>]™UU½ÐîÜÏff©Êº™Î ¾½5UÍ·rèÙ8pLÇž%ä>±Í”8Þ2¤ãnŠ—V3t¥af)’íœ @=†y·¬m¦Ìöà!Í7WjT’}‰PΠ ò¥Å7]Î:Í;(0$ [ßaýR?2Ù$êÔ¬±A¦îÿÐN¥Yj;”Æ@"ÿ,$oºˆ_TOÍ¢”Aôа'&½'û¥ãò ‹˜Ä¹ïyGbI?/Zàï­«£`¼ÝF€ŠÀ‹d‘-åãoWøý.%ë‚<„IÌK¯÷Œ¤œî´s€B:¸7Lj á—ÔtPß²~ ‚§¬ûèyïïãÿ+³E;èêý'£Ä€‚õrÇ‹ü½ßK„W[2˜k“ xÉœƒº„©@€ÙÍÞ,$ý|’æ\}³X¤œ³)y¿ÕÎ Óyo)›»©ÒR—½?]ý„ ô´Cˆ'\‘€3Š.ó“Ú–ìx?ä@oLbš<ïµ ÷½t›¨€2"xÔSZ3ÞX¿‚WQ:bOe‘+ÈŸˆC" !àÀ Edˆá ‚0" ˆV¢‰ÂIÂp–Õþóð¾uÔßv§Ä~iƒ×ú^Ï6+ðÊx¼Aìꥪôíàîÿ§ËàOon*íÆ f¸ù’ââæù|}À"¸(*ÍPƒÄ¨D €€X¶ vß,¿_ÀUz»³<0••ŽÕö|)#îuXnÓbÊç_²>tÞß’¾kÎÑ6ËçB»çÍ6W/Š–(;;ìÛ°"cq¬3¶ûwM«bðÑ› ŒŠ;UëµOòA ÏÙ`CÌ”‰µØ@|²ƒDE[’ ñ“‘ã=£ŽJ\ OŒ=ꜟöñf0ØlHЧ§Ôyd¡»Û c£áEubz³ã=OðÐyÆ_ ÎÐBŸ}>7#üWØü8ô.9À‡3ò>6ÇúßO<üíä†XH¡£[ët‘ÞzK½ö[jâÄWfUtÚxv†‡¨£—6sª§î.ýŒô«]1Y#–÷Oè•À¡Þ cv?o?íò’ŠT»©rx5˜ü75М]$îÛ>Ö "¨"¨‹˜n¥Xª†/µòJˆñÁ °T$RF :¿iE¤k-¸Ì†•†dqR†.¯lˆ˜åÑÀ€8Ué¿:µI•ký²æc™ýŠS<•“µ%¯ê:¨&žy¦FÒ"m€˜úÿ”„ˆœ)ý(Þ7¼%¬63´\I•Õ)†Å¶¼¯€:D#û}'o{ƒÒü6Ë“"iNQ®žx4cfè£SãÅèÿÐS¸Ä”™™Iâ#uøc³ãþ”—¸ù–0Y°£]bæ·)|<¥mw2>³ ¿Ÿ²¢|™'W¢6cº*pù15ÔV>²úQˆ=ÇÂæb»!op“ýǽûî“ø>B_àÙ–8éB!±ÆT^ ¹=Ù‰ö’=gAÎs}z•VŸû@ßô<éßUDE_†lçìÉÏ:x°ßF¨I!¸‰JŠŽœ›ýçìî`ä£ÌaEÈ]*ÉöœL ÉãuÓ§&޵¶`y7ùê#êÓðäÉï“òl‡¼¦ßÉnmgü!@²”&`rSÒ^jª‘®²Tµ%(â®F߈Í*þÞSHq‚¬žç™Ý/™ âƒI)®×0ÿ?säXù{ð0Xõ2'å¼LAE´ØÎk3êqãë-¿O“S¹“}Ž»¦ÉÞÈH¢ KÒþŸÏÑh¤˜üë^Äå•\W§„F‰_Ãþë{)óØìJôövx¨ñyæîaã/¢úGmY šÕÜaÃlþdDcÀIå"<¡L;"5=T&*)&Xgú³ çÔò«^éý­‹õ¡ækM>|¥}R0jUSj ëvÉúU?zèÏ.ü„k°4Â>u˜€@'Fú@Iâ>CÇŽt ¡¢·kžëz/ª˜$Õ+YÆyWBÖªÿ ·V¹bܸ•‰ ¡à‘Â=M¼˜´£ÀZ ‡ xVý7Ž`вÈÅÅ@Úu¦‡cŠH€Í‚]ÇôÿUÛõ¨qÊž§w¡´<™ÝÚ¾/c¿»ëGð3× ¼|½|¢åm=>]Ãs©+¯- ר¨HÑœ?U òõ§ÃoÖS}öSEyç­JÁD6}OË@“@M ±S¯¼H§ûÎi“‚”9¾lyr‡áÕosÜgC¸ñx»½OÑhw~®qÓàC 5#êyv9UTÃvJǃ¸°7þ®¿‘ùº}Z^”oÏ—«ìõá®è”eʯØÍ9;þõ™äóm$ÒOóY0ßÿ90/Ú6÷ùƒñÇõYÀ³·¥‹Š*)I¯»ö|º<Þ>_QåÖo•)EòÉSZõêû kÒk ,–Z­~ÿð>üñ”–pÞ—#| » /a½¨ñt¹¥ü¼{ï½fXJñwÙ ?%=öçôO÷>’]^¶:û—õ¾×‘Ϻõ-£›PUè•;ûôðxp `мOo Oe|LÕ*fQƉ9&ªSŲGZÑ&Ç´§:ê½j]Q`£0G² ¢´;1 _|à³Ã +Á>âûqƒ;s¾1Œ¤«fc'îRR>âcºCü~V§ƒ»wbó>èÑÐDI|ÈPXSyâÅ{(ëà¤ÿÞü¿ù?³Ýþç̱Ëw£Lþ÷åx%Ïò}Î>adlÊ<ŸõÞ¢ú“ïÓUáúöʹ»Gòöüncì}ûpü\z9z™QrÕ>øb¿ÛÝîKWôÏ?‡…%Ï:Çä¬wî&±xA¢«Û›v°'VåSº–¹×ŸoÍÞ<‰Lë¶žî]7ivÂܾ^Q]ÇÚÎx_ì+æÉmÞ«a‡£Üñx¹k.ÞcPÀÇŠô ÛÓñ †x¥ÅH o·»Dœ›#{×'tTµg›¹…ú-àžÃ³\ºSO=öÔôõù¶Ö¼Å;}åpê뵫,ÊZ< C缓§åØßUO¿£%ö+ãðcò9ª…}~£Õ”æd|—´Û¾YÝòÅö7Ãöýœ$-ý—f®züNÎ;´jãñjáò»Õ8ÜZÿÜ_ã³¶†×èò ±y Š“WF¾&·AUÃåÄ\  52Ôч‚Ì—^SÔm oÈ×]æóèf\Œù (š¨% G n9™”e£»™P¤ÍŽÛSë3ò¸×<óÄ_¨¤wŸŽGõ׉´²@`C 0ñJN™ü¼?Rsg·2OŠ`¥Ë=R·æÎÞAÑI(x/G þõŒÅkߪdKCìÌ¿:ö×[2å‡ ßÇÑmFw”üxœ½'0ܱáx#p/v§ŽMGö±«Ô]ªs¾ÿ=¯Î·œd6}'˜,ú=·Èø¿sÖu2g5'Zg•Ïç yã4Á{“O. "yÛ‰óþÝÜfãÆkú¯Üî:_0'’ÿæ÷Rw›=jÜ$-(Û T”Õqѵ‚•[‰hClûÞ_iàyú•%T­[»Þ€ecè+ªutüêøýïît8 pêt§¾¸Ø‹mKèš¶µªÛcÖ‹ìüL½Î_5Ég´˜é6ýáUí·$„0r|ÖÂë­*­Q>¢û[+ƒ ‹ä¾êán‰D”¨ ¡óXG‹ªªu¼9)(Á\§räîé•IϘ‚g ¸!žøÜ(Þã¿Í—­·ùõóîÏÿ/Ÿ$í±ÒN¥‡:ï¿ÎeTòlŸ~Ø‹WÁ\xçÒë‘Uè ÊDÒD¢A`a†%§ÉzÅŸç|'ɾãçv›qÿŸ/²_²¹Äû?×ý®^ç=.qö“?˜Tù²þ¨çŒrõÉ#Òü£åÓ„áцM°ŒñþCkÜ]˜ÎWò±m³®1ç*6‚ƒ"»ìzØ; ì¿Ë†“ãêó³ž6–ž6ŸÛn±ýÏÁû/Oò~ç1; ¨`ÆGIѹà¢y§Öa‰áª14éX²@>• uÚÓ"¹ÑU-×áò‘C¼’ÒÊ)Ë%ÏVGHÂ"ÝžQžA¸Û›Ïq5míMl!Š HpÑÙA*JxVÔ“t™¡‹©-‰l‹P ,‹w"‚ÁdPŠd‹Š‘‹'6f†×e‰»&é» Ì¤´f¦hbÄý-A…CU©«»1_qüÞhT”rÙí®½øâI&µ’Hª¯‘_ÃN0ÐDD @è7ªc¦\ø 9- ÛýZ4=¢]>?5d²Ÿ¼)0ËØëì×}Ióz5òk§í{“Ö¼Ï8¤×fçá¦\øú:*“·­ºÿÎÓ>ž¿æ:ÿu|×éµt®Èã¾á1KR•¥gL84£IÁªn“¤=¨æÞÓsJ}Ïþ¦‚W í¥1Jb£;çîqò/ä| 9~¢™Zúiš¹ÝÚ/ÄbKàÔêŠéI–XtÇi‘7ÙÇYk\"J#(Å>£÷IÏ?óü-‰ŽÃ!Èu°JßÂõ ‰ÏyxÖþO½Ž^ç7[ut[ò!ݾLÉÿÔŸ/5<Þ8/6agîéÓ0<[ùsc,' %ó1å-a ø kN÷&8n1ÿnXc^Ÿ/šžBó'‚+EÅì7¢*ïsiínnù±ˆsݧ6™æCƒÒS×Ñ>ʶõÿrÕŒ)£nÙ.ö=3Xk-—ðq2>>[¤Ø%6k¿HFÁÔ£úmh:¡×Â~߸i\%ÃW8tG.H®­ëB³Z*éu@ös®¢$WÌÒÁ"„Ô…ÐaV&÷B› ãç æ¾öŽïjpfãkËy½õü~ƒë}¯,ŒŒŒOÒYó²`œ3i´>£½ÞY*"¡ˆª—üL9Ø øö~AÑÔØ>´G‚Hò™ñ¥CŽD”U\nŸî¤ÂRD:Ž‚³îFmC1ÐÌ^ˆÜxÇ,vëD¢¢ªQ™T[+«ÕŽø¼Þîõg ªõm_j„”UD“1E%pÞ˜ç#WNч´ûežâsÖÝ1š·„» ïBɦ¶âjdÒ›@ÖwãŠj‰£ÓþÀ¨¦–œ¸«L`rć(x@£!Ū{©{ý¶N©:°: u`zU†pÉÃ@ͳl›a´LLd1©P`)XV(Ä ¡B° ¢,1•Šˆ¢"‘b©ãêà çáz襩 §dš9xvq„/eœô¡Rª¬mT×Ò®wK¢O^?¨B½^¾Ï ÙÛå³ÄñJŠ«P÷RŠETOkQxOfR9ÞÑù:ïÓ|³Ûî=œEQVª*ª®3¥8Nq“¾3b‡»ÝúYŒc½/ ù'v¬øFW79š§ŽîИý4´ùŸy¿9¿\f?\a÷-ÕP‘Ò‡óE)°OO,ïuÑ‚ þO0DzÙi«Ý壄vª€©$ ¯ö¶ú‚¦Ü[þÓ¶&#íSý|ŒßšBl¨ÓÍæÓŒvÉŒ•#)ÎNÖÒÃÿo¾ Æû›ñò˜ðοÖójsWøË—xp§=Êó[î8å«‹¿žã/3‡R±}G…âÎ^üO««§`ɤŠHìJðŒT&GɈE@‚ªCÆ„0ô’@ÍjëfçÄ0Ù Br ™3ó«%Çûg ™‚Ñtñ¯úq¾g'¨é9}Ÿ7­›Ž è=çÁ‰3ÔkÝ÷vs’¨„›`*¬“ùs‡:W’œF—•ȽwôÝ{ÓÖS>Ó£lx}pþGFl",Úñ ™³™s[Ï/¾P¢ú=Sésâ}2”¥>tÿ[:"2¦bê¿hn·±/F1Zwf3B(ðާ.ÿ¯/Ѝt_2¯Ù¡†ÓgŽ‚${¨£•²ü“å²mìÅwŒh)UE÷·dñ›qO¥’<4ƒ%e<ÌÈRîªÌÓ¬5r²s˜CKîðmÇ›© f±Î½yqœÙðQYŽzÞ¾_Ìš|ã± X„1Å@!À<ôb’Ò%" \û§ÍD4^¿íWtħGw˦Êá½òòÆf1ß>E}ç3Èä31ó²ûK ØÊ“d9nñã¼6±àv0… „â&Χø<·õ}~‡é~žÊwHRùHšv(øÄEŠ–Bëºê¹ _Qj½ *#è9Mª[è0aôO¨éúŽœÑ?×…Óà}ϧ™ >8€Òë­¶€Ôš d5ÉÛóè“áD‘FEHA!M(rõJúâa¥ TKw™FãÔùqëÞ”DvWÿ^³mA¯ßêº?Œ„u’†k-“(0µ|Lñ ¶o†`¶v¦ƒ†î,ºŒeг$„Kо)Ÿ¹üyÏ?ν''è{sw‚·6o_£PàoŠRf ¿€¦~ù¤£[5úŸ©7K,¹–Ò’IrPWÙÎR'I” HöêMReU dÑm 5'Ò¦$j›±^¿oLÑ'J¹ÖÌÌAJ0AWR‚Ð*—lM A$HVå™RD‚§Ñ©4˜iã‰É`’ÕŒƒ&eÑC {öOǪwÃ%êu‰‚iIn\Õ!DúOº£aKá…%[U ªz%tqNeE@àãçåÒtŒnãú-Á¿Ó.IÓ†‰pɇëaTêSqŸ=©Ë'NS|véìßneC>vj<ë¿.“¦X£TVŒŽ–  Ñw=þÈÅq³o6†EzƒNqWˆˆˆrÀÞQTÙ™“™îbcœ&£¬ Ä*,`0R¤KH’Ö£)2\ŠH^æ†MÌ¿°ý1"[Î Ø_ þ!àš0Ø^O'&ºg¤itËâÌ·a¶‘D•rÃI,aÈ— ‘Px4¼L€ÀĶÝ{+­Yî@a]£Kãn·GfQ5q¦µ«]E(ÚR÷÷Õ DÁ¬šâ¥n¨Ä ²ŠcaŒI4G_²Fi4H·äÏÛ›6ªn¤‚aŠ ÊöCÅ!ãßÝó±‡\ïtwÝa™G ºÖ‘¦”,²ãþELÁ"ßÛ%¥E×Õº“*úqßšÝÑžšñ™Ä¾dôdô›±èõuí¢­SÚ:gÏÂu‹ãebu, ’‘*¶%!'âQ OþŸOžGÅIÏnµ­iÞyÝ>ž¦ï‰JŒÓQã4‰¦Yx²¦(å1ñcúŸØþX€@MÇåmw"í°îJà¥wžy§°Cˆâ;Þ&³ô¨èÿ¹Ù9]5|­,ǨªÕ'úý‘©àke6ž×ÏøA½øº¸ßHi†þsywØ3º3rpqØ‚ÜôœeóùK¢¤û‰?µ~‡“Üæ­ªt ò=q}¿‰Ý,‰¾"s$[BBháïäM3XÙGe–ÀoKrT-ËÅ*ðEWg1—»t Á·b@²¹_žÉv)%LÙÕþ“/¬¸\ÀUCjud€p#ÿé¼¾SÖŽô†F½—[ÆeØpW5QXsÞƒm˜‚A“£œ“ˆ-Âh_Då²Òä8hÉKCø“b賓à„xZÏíQF—¼\6p'2&“i§b Äxf°@’—áÃÖW[3o­+W”YI-L°YÕ¹RÞÇðZ En²Ÿðî–0'7ý/‹ÛlôàÒô>X}‹kaè¸da5ƒE«Œbä›7ۜߪȪ§/áþEˆ‹üèãú®<Ü„Mf‰÷îû³‰­9C‡NþX*_½³ï{d±Íy_9e²}Åvtò<#H®V¬ Ø<„"£cÇ)ugÂ¥ë÷0³³ãù¼Ž2ÁJGï’ùv‚€Id8ØÐûŒIG lMÆ:æ”% ‘0ˆ×Þ¿.]ÆÃ¿Á7ï¶vü,Ó¿mu-»tsó¶sËÇeè5ãxÿJ˜rèÈÙêt"~v?nŠ¿%ä÷U4â̺Ïw;Bì2õ{m}}÷”òZ0Ÿ:nšÊº¦e„”² VC1¼!uÄ=RcÉüí×c²ô¼§÷t\ü[ê’Åž-ð :ѦÀïu¦¡#²Úø|㉠n £Ä zD;48Zà+$²Ùh ^4¡¥µ -PÐÁƒ ÙŒ0Äz»ñqgÆùhZìÙM~7?Á̦¸›:`"±6p¼lãaÄ"P@,ù`è JUbx8¶T·²)‚”ôÒ}`±Ã V1÷Cù /b€¹˜AV_^Îtdd°ó´í§¼^e%9©l 2(ˆ€Y›J¡Z! °¤V¿X§hX®h€…L²â >Ñ÷Ezø¥±µ½IÉ´rfýƒš1h“wDfIˆ—.V1γ‰BÂ`F›Y‰ÓÈõàŒD7èz"úì&Ç Ÿž1+ÖÝŽ¿R%° $¢IbW¡èy^… ¥Ç[]„`ô° P —ä2©V[ÉV°¨¨„dì«0D ,ak/…î=ç­4smCº‘Š.yï¦{ÚøóM[ÏÝC‘•£z2âTV(Ó®le@ÄÄäSŒdd‡‡p…ñéÁÞéžm|5‡n!—{_?@crÂ2Å»´Ø¡BêFEOvÎn—vw|B€.¶°^_ÌúAKô…M@¢0}MgŸw‡¬ÛôbÈDKöãŸ{¼óÈ,Á#sÏ"(yHîŽûé–LO\å-¾³µ‚å{ˆq(GÀl • …,q¡ËBÌÌ:Û7» êÀ©w­f…Äz0#’ˆ/§G ‡ŽtA»ÃbŸ¡ÜO4M(RÙaŠXŒE‘ƒ“V‹â™ÁP‰‚F€Ìd¹“1DʈM§H0øj@¡‹ßq´ÅÕ’Ø“Í=*zx8ns|{ÅÝñdZ™øf "h:М¨ !©¤̦%¢Â†DÁK"=zèˆÑïÙÇ›0<ŠT&ª÷¨¯Ðèx/7Âk% × èÍ´$I b7\‰¼äåw›íí·÷áã2y½„@Ë‚ÓÛhú\œÿy˜ÞpÿSGÐÁÌh€ÿ/¨þ¨å9¬|Ð ?Áü„‘8"*H”ˆÊê¼PÛÿ„Þp[ó„Õ·L3‚¹©ÌÕ®ò~Õ}Ó,,r»5¼5ÝwŠ\ò»«§=cfÏbÉ#2•Ô¿Ë¿'o&¦·DŠ8f<zN8_w#H™XÜå9ß …Êó]8‡,!“•—ÆgnÖThWÅÄ‹ŠÇÀpèØUBH-SîB&*aeÍäKˆnEŒ¡ P¡¡@( 6m· šWnõÄaÛ¦:téÛ†šiÓ½»m™Èêîu&çNœ9m¶ÔÂàªÙ:qš˜G;ŽÙu:rÛ'&ÎLFædáÓ·,,á§m6s;œœm¦\΢£oXaË!Åw#$P0H"f§s¾¶É:œÍ±ñ©©¦£N¹pË¥®[áÄᣖœ»rwÁÛ.ºe˜ÖŠÐÑ¢ƒ‚ÅÝîÆôPÁcG щ(#B‡N8m¶ÝÎ9dtí§m¶2Œ»8»œç™¾Ü6ÓR²Ã·.MµÛNa¶]¶³£n›w²ËˆåÌvNÎÎÝ»víÛ·nÝ»w:˜jnVÛvèéÇ\öWNÜÉXvíÛ·.£l›6váÓ”®ØvÛM2íÌí\F²ìå۸˳—.fÎW.Ü8tpÛ†œ§nšu…6ærÛr4àÛiÞQ˜Ë]k½Î¬åÓ·N\ºË§Spa´êi§N7™ï¾;õwß}ë´åSgnݺrᦚm—nZtË,»b2íÒn2¦Ý»ví©µ77¹¾§.Ý:u0íÜáÃl»v³n“m´Ó†Ùni¡b@áB68`ÑQ£…Ž»±³­8q·'æeÓ–§‰ÃS.6pÚ¶îm¶Î›m§SnjNYde‚¶å·,w ¹aÇ,9a“‡.L¸0¬¶äÓ'máÄéÛztË—Za§I#N+—2›e¤È¬6ÄÜfpåÛ¨åÓ££ˆœ886ÜM¶íÇ2Ndw×NÒκÝw3 w[ X»À`PÀ4 (ltpàÇ::8\pŽ€ 4hÝ6*¨P¡Qcccx6 ev™w(tXáƒGGNÒÇqÙÜî@îwß.yç™ÁÖ´“]6à ¹0tuÔu»iË.]Ž£‰ÜݲÎÇŽ™f²Ëšttã¶Ûm·3“„íÄq5“¦Ûs'.8píÓ— «ƒm¸‰³,¸rÓ§kC¶vîi·N†[têN¹råÉ˳§nݶÛm£NÎŽœ¹rré˶äìæcNÓ˜rÌã\×.dá“§.øpíÓ¦œ»ŽÝ4éÁ¸êbvË ÉÛš:c·'3“–ܹvÁ†6ÑÛM9hÖ´àté¹¹ÑUædñH'”DL϶& 10Rʲ…,¡K(Rʲ…,¡K(Rʲ…,¡K(Rʲ…d`biPré`ré€9‚TªT¬ì˹ٗs³,Lw;2ÄÁ†& ;™w;2îve‰ƒçfX˜0îveÜì0ë:†P¥”)Öu KK]͇”)Äà0²…,¡K(Rʲ…,`a‘•ù?øþOOìý½Un~c·ã Ï"I]²÷>‡z£Ù±—^n8 Ñ´(·ù#îîuîüR?'¿¥ašVÆf¬Ðc6Xí뜩¦Ð¤6EpRxø»L2ÒzVXmž2„Õ7BØ;Ú8fY*©e,w˜šéX¥ ÌY%¡–ãm^[çÀÖþwÅÛˆ€'æ}|èñxï¨ùØUî!ÇÁU?'ÓnçDÜß¿äùÎc ðd#;¹Šï‡Ý:LB*, ‘HìW¨¯³bîJ¿âxÇJ)ýU(³óJ¦òÒëûÌ…6Z'ùö¹ûOø¿«ÔòÞßÃt¡Þß¶9Ï]è}7Ý­Aˆe±^-ð-î¸ÿeÏíðíχøzå<jõ´ñKéš²L²øÀóÅKLÞ€@{‘£êLî¤@e0þ@ '£«ê}U>«ŠëÕ÷¿ä¿{1Õ£÷ÊðU_¬Îózà9[±`¶Š-n^‘V 2˜5¯^Î-T™,;Ó7Nû;Ú\iWuæÞ¬U—s—z¬,Ò £Ãd©¨VÙÕÅtÒ«2:eep@Öæ!ªîÆ)¡OŽÉªG]"zyÓJU<›%Má²HXQzTÏgSÌ«0Ê@]îá"ò ÀC]T:w­:¼$1³­b䘂‹iÕã½¢XL[[2ºkn’¹¦B;‰f¥ReY#¹Ím!|îf©*©ÜÏDÙ *=Ê$‚4æ𭦯¹5E–Š8Q°r®‰‹Ì³ÙFCëݨ#-Ë¡rÙLhV·$Tÿå¤_…dÊç\ÎÕÕ$–O“gË ¦ÞML¢„éÅTY±VòFN¢ZºÚ,·"M#­Œ¢7ÕÎÈÎÎ"ö‰ÌuuáY2šdó®Y4,Ñ¥ËHÛ9q€jÙ­W,Z±º= ±t.ÍÓΛží‘ÎÚÖ_8±{×|7.k(‘Y9¦ªÆ©Ãµ–Gíþ/Ï­óÊô.‚ÏNH!Vœ»·]fZjÅÝV*»Fžº\Tö‡rS×ÅÚ*­jÕ=(…Ns'¦»±tJ2ðs'HCAîX iåÛwxMeÖvŠ åoMšV'¨îdË:Á'7¯ˆÉ$àÉV0ÔºcfÎÏVæ9œOVq§¼¥[ÙµÛ•}†ïÁÀä~ÆaTØŠ‚µýõ° ¯‹ì¼¯*â½ä·¶,¢ý¼‡áBÀ"ª· >{˜úÁÀ_Vdpîý `Ùf;ãÍü-GÍcë|Cðc»ÑÿŽÎÚÀ‰ÚóxK€ÒoT@À F „’¡F ­dÍ­âY•»õ<ßÖs%ÃìƒJÄÕOÔúû×Å_j17Ñ@æRú-Psé“ÑìÝe'šP§Ïúƒ¼;ú b¢ÊÎãÀLdÓ d ÕÛ½eÕí4ÔÅW£ñrdüÒ“Š®ßÃ`ùYõÊÎò&0à|¼J.¦úŠ((¢Š (¢›aÔLI a0U¨º yñ>Oºý¾sÆâÊw°ñžjåæÈ„¸…éÈÚÎt‡œ‚½(Á‰"E5=çVövß[‰ï7†–Åx×ZÁ©ú»?V¹ëôYîè³^KoÍŒç+ÞÛ3÷¤òÒ!9`=‘~X±®Ÿê!½ÏPÇÆw_F¶vŽðë=®8ßNYiÓ¶\:V8)—F˜vpÛ`XÀ… Ó$ã·nSšg2Gfwm$TåR£E‡4àÁJ³Fjò›Ù¹+põLÒqpv¹Ûášn¥i<Õçl·Tb,lnäȹ¤ÖÖw¿Ö›ý‡Ì@ýP)BªKRÊ©*ÄU’U„`ŒOWøŸÒtãû¸|‘ó‡®ùaåùZNzõºvü¸ÑëC½]uIoâ”köMI‘‰E‹’*D@e=˜–³%³üJQH¢ ¤X N©bM E!J$ ¢21B* UD@ ²*À‹#"‚ÀŠŒR@V I# È  D`ª(€€ ª‚ ªª*‘‘:ÿÙ’óþålÁIøÝ¯d‚0R+%µU± Šb‚ÈÊCÇ⡎2ŠÁ ½l°‚Ò%¢ØK «bËl•ab+"‹¬)E‚€ +EmD• ±A¥Ke)dA £J,^æ!ˆE&·Iò§pëtˆõUæ‹–±rî[J3òW†A¶¤Hi u¬‘aKéqÈ„hÔ¥¬á `€Œ_­@œJ%T?´©‡_\tè^ˆ³t JG E²†ŒŽ¨°P±@È ˜Ã†4`±ƒ—.a‰Ól£8u´ÂeËS™ÃMÌœ5­b¶Úff2äåÔç]Íõ¸éØæu+©¶Úm§Hé˜s&;0æiM9Jà9öUŸÂúÈ™õé©ß윛bfïÉÊT^ ÚtIÑ9˜ýsˆº³ ÊÜá`X"ö²‰á"nøPÁ½:Œ‡wPƒKÂ^ŠPáÁŠX³¬(õ‡ãO¯20X+D¨ÄTQQŠ*±EŒ´¢?o2ä?¥ÌÆ ?7§2úÈÿ1¯¶ÿ1Ö éúÙ¸óª]ŸâQ﮲ïmHÇßÚJž«¯û©+)€Ã•B†„L@aÁ¹› µ.¬ÑCÿ'ôß§ý›óÿ³ÇÏÊSûßå"„êæÍñú)8xðLÍ,þ‡‘ã÷ãÂ`toûÅî>GÅVŽÃúxþôÇaß,Ç‚iëþ·µŸ¥ä?£<4“)°C:Q.!fÔ3;>¥k– F(+'ï`Õˆ4D¤¸{{ÈY,E »¯Â‡îàóÆãoÛ˜ X,Y¨@'°ññ"£ °UT;~Ô7¼&U?ANþrNÅûبª¬bWÆ=—íÙ"£Cõ±ç;ÜiUž¤©‚ ö‘Õ‚Îòóa˜€£¯ô¦ Ÿ¬ã#í ŸÂ¯ „:ˆ"}ÊGV˜ûwmÃcB Õ(;Õ²¤!Zµžp+¶˜8@P®8m—GšråZaËXF ´Ú€#Ž#d]ØUÉ<6oˆÄì­o—-è».8Hî!=½ZÝìôoSб¹ ^ îêZ¸ÅFÃÍ£ÀîsÔ9ÝíSµc¬ÅÅï¾µÏ?Ì}Óú/Z=É_C J¸F"°ÀÀ’fënöÆß +Àª ¼£g:¹P›Z0þ•¼N€ÆO6ÌKJªèd¬¥ù¦tNæL@sL]X]úô'þGòßæú‰E{>¿Ã´×øjc}·‚>ëj\X“û¾WÎØØ4MPZO#»Ît6Yî-¥^j PÑ(Ê*«®M½¯ ?[²„‘ÕÇð°XöiÛt? àôôé&»/Nº 2]6hKÓ*ÐñÅ‹1Zß-Ù6k÷O ãÌxÁÝ&l¢.T0A3AM i@À%öyûï"´qP‰¸‘ä¸&‡†÷m̓`xâzŸ\2§d¿l'ìS¿ÍíÌüµÊÝ?õ¹Ï×L™³¯›FuƒªŒßÔ|ÖßÃ/Ýhl¡‚›äœ¢ÜŽÛ”apÄX@!€¨©¨J‚AŸžP°Š,P0 ‚N?’˜9.JØLæI\—'t½¾Ø° ß0åÄÙù·Sfe™\eß 6áàÓM59sÇ ²u†AÓ®vÎç.]ºW 0˃6ê2uÃ}N8;x3<]¹œîpÃpÓm8V¦$ð¸…n ¯Yûœ|™íùwlíŒ9ò‚éÊQhR‹<àCE³Y!i®Ž·Å¨¤ç»Ê…êú«© >/ɲ{§ß«}´,?_? ,rÕ-·ñCÜ’H~½MÕîHuªñõ:ß’ýÚG´YcoÊñ.w¦dó\z2}?â~À| ØUVuÜš( 1¤qbxCE“¯•ò1Å£ü^ŒÂZž–Þ؈‰ïM†Ô℉¼(R%k[òõ²Ã¿õ>]Î4L<ìÍsvb(š<äç£Í³|Û-[kéùtí7XUUwx;š$Üè¦ÊÙA5ª7žÌôëÁÖsȨÄG¤ VJt„âpg ‚ðVKtÓs½'BòúL0:&ɪ¶Â|¶†j—§5­E¹n9TÃEaÄá³[qV,«oŸ-M9zS×fû·ˆã©¤¼]UpvŒ¹›sVÅU¶ð–»ï®†hû ìß[ËÛ‰{®—Ë }Z:yI=E‚R“Ÿ_Eomµ¦ÃW)‹$™ …ÆyEÈ^%i™òB*Ç’•ô4zÄÖ‘7¢‡w²’zƒ—ƒ˜štéŹ[1UW\;²xæG=:œÌ{»pÍÕ¥ðëÎúÅ'2z0USrh¦& á‚©†òɧ–ôËS<ÂiÃMîUxÙîâžÎLg('¯ºœÎåàîåTQGS,30ÄÚM·§ šq*«ø]d™åaÊ3\(ÁÉÅçÛâ™Ó‡ðL†§Éêº2$H!AÖÙYx!a†hEUÃÛã­# à‡o«>ãæé¾[~*X§«Ó=IÕ²ZñbÒeXÄ•6ª"©2Tä8&1Œ ˜ÀÐx,®p†g2f !lULŠ!°qQ*n˜Â¥¾ùà¾]MíÙð̘bhÕ –†WÄåþ› /'<ª¬QVôÜêô&Ȇ€ÑÃr¶Œ*…¢´pårÁ1.(sáV»Û8‰…‚¨U†Ýxïlt”ؤ‰£Vˆ- ŸrØ‚;0³!-·®Ê]VS Ç€Ò„ìiï|(pÔ¹}é ©1à”kVhf'Pš2dÐe¥»p×Ç McôBNªp1 £°Á¹^êÃQ’âŒÀòH!1Š»XbGÝ|¹§j6hó=vÈhInìsœJn›(·‚ŽëÅXnfƒlaâ‚j`ÙÁ9B1„6ÆM²HN¼Âs%єˌHT¸”Ãǃa²“ÐöÁ=)Q­’­§¾ QÙï߃yãf"Za§ÏRhÒh÷Á¿$œp6-qú{î@ádk@/– …y^¾ã×!C˜Sž¢Òuž\GFL-—.ÎÇ«¶Ï®ú„e`ë N—8.W &³×¿MÕª¥ß}kYÒ÷ßN6X ¢²`RBÂÔ/HŽj© ¤ • 9Jï#ºV‘ È ¥†ÔuH<6C;ˆ:œPEäéNtŒ,)eߟ:0t4JNP”¡‚˜Hˆ¡rÉéíø¡ðè½vÐ&½)Dѽ]\zóNVíÓ6ÛrƒAvËîBCV]°êšÓ8;a‚05‡æêœeš‚2qJ¦¬ß“@"uvÇ¥*½a£ãbLñƒ¾ƒ˜T* 2”4YÉ…bjÑJ”Ò)‰‰åé†")2ÍoDÃ84dq<6#4 Q3ÇÝñC:)ÕôöY30ötø³$E]Ùˆ†h„œ‰rœÆör €ï8Jk8aâ’G¾y!ñoNØäÖ3.Óz¯RûjûZéPaâÊAM]¨a˜S‹!A!Y aƒöP²o«† ¢sJ2"']"(¡’ˆÊYI…˜0cxZbÌÅ‚J“ …‰ Q†„&g~MÍÃA’ˆÍሧ\wáÑÄàzY™Â¥ë *™ãd·„á¿ФÔܨëBñ$»Í舳7.ñŠ&«ccÅöJ¦ô²! PZ P‰!M±4TÕU£KmªÖœ3S»Ú{$çâÙ‘ÀYÎ'«­ 8B³q æÉhØ("ˆ^÷?ïø¾¿šþ?£Ô{ù¦qÊhA7riÐp\IR¥@ZŒˆŒ…Ä‘(‚;#8ŸüÍÆ>+…+Àæu;¿!×OÍÿ£õž`ÇÝõÛ3˜ÓÝecI}µ‹žóQfÞõlð¥cZ:ÅZlH})mÍï2Å×#‚ók¢òG ¡‰››Å=’kµØÙç{<ð™Ë7ˆ)še¡yUReȪW¥ íx¸Æä•rÞašµ(ŸÈ´¦Z’eR£Æ ÃZ.3ÏÔ¿±Q·üOö?kô;¿ìüêo”ÀÒÝ~MVãi™óþùVy[]3þ&¾5ÒUÉ[®Æ_#£îpï||·Ê^r2Û2ù²’²Ÿ'j±J—N[‡¿­þŸ'ßóg1Òæ±ÉÎ`ä-o;ÚËÐæ‹û“Ã7 kL ØûÊÑþ÷ 2`½-•®¿¥»~YS6ýGØvý÷“ý {æ¬WüwÊÑÅ$–žž˜aU쇵P¸Ú!´&ÄÀ~/¢ô½Þ=è|¯¦éç™éÓ=4$ m$<í³?yrQ¼8)À—ïxÖgÏ}é÷ɨ°DSö~”v®ìÎLLûS&ZU<‹—êqA÷db{:`\ýªv‰2F÷†öÖͱéï¯3'Óg=ÖX°÷Oà}#Ðû3æ)*È Š(² GæŒbµ!l%dX¡ 0XˆÄTæHÀ`‡ÔhªŠ Šˆ,}¿aü^wõ2Œ•–G²{^ÚP‰I²!"‡&ã+54å†X¶Ë´tí¶Ü¹mÛM9w:54æ759rêmÓnšœ¸›m¤àÔÂÊ­«˜’F;Ù—.~>æÝÅpi¦£ÁÖÛvᇃ.OmÃÛl "L4HûZÌ×gÿ¿U|¾³Ç×>¯y:“*sìÝÛ)ôÖ;4‡K¨¾]ì³”ö-+,Ÿ©t@Y%v¥þ#| "O<Þæ&¢Áò‘ùrŒá¢ãͳÕE|ñŸ Ét3¨ÊÊ͵3¢N‘\TtEù`ÕCfÛâÖ±@Q@W*Í{œðÖžœUg­]Í6ªªžxX3ÌѾNœš,£<éä‡vç5R›Ã)`f»°6]àœhgJ’`Û²Œ×ɇ%뎽ÈÕ’—za3Xya’ë€Ø`ˆš>YÉ}wÃð5äPÇÍOI¨JW§Žk´ 蛊’­)]‘- ‘„FñòK„dX¨q:C¨xìæw}J(•#}³Ë¶ý³EJH‰iD¾îu6pq0`‘%ç -XÞYeçdÝpÓlj¨|JâÃ-¼³÷Ý Ý’N¼Òx°œL§)¡³ íßd“ÛѦËÒÎ䓽‡é¹£¢X0òIg4î4qƦ:sáßîjRí•øš‹á»=Mc·c\‘d·"n3…Šgrƒî‰²m3ÁépâH èd8T1K>Š«£22ˆ†-M¨f&Ù)'³ÄÑ®G!HŠÄé˜eÆb“Çl7à×'Ÿ8pb«‹ÎM†ð™F$<3¬Ñ¯À²Œ""CË}î‰mµfE3«ÉUtZ’0 wlp“±šÒükÕ®5ÇuÆÍæu™<Éç6'­Q£jVSÖzÓ Æo®dg¹–jê'?%Ð"04wïA©éa“ÏÒ˜m’_,œä4C„ðÙ¡7ÉØ"J+ã„߸pS&’X¶ío–0I;8é;ÁâÌ¢©e؃| †É K-¨6ák†¤ÌaÌðÛT”2,@¶¢–И—¶Jˆ×6T!±ñ{(Ĥˆ3ÍÍÔ!GŒÔß4Nå–ЇdÛ;¹' N5y°ë3 2ÜÞ“CÃL²óóÓŠn6¤UÁ ø.G¢¸"eÊZùt†J˜ÀŒE#Z¸ˆ…ã— Ö*n5Á¡…š/¬a•&½ µ³[jÆc$÷›ZW²U ˜†$І#˜“Øj¬ªÃu++³KH_m;J¥)iT²–¢Ê‰*‰š—ÃÃzn…Tžî3’YQUu£Œê6¡¬%ï†8íÃ&r˾^UçSu$SŽL9;g‡0¼pfR ä©£¶C¢Ô‘*­çR3ƒšy¢©Õ…Øûš"Œa±¨õ6c•é+Ž4 2ì€è@ ¦fEƱ––eaKäŒ(¨Ql©’š@…Ÿ|úåa/• ”…’²(o{ÊF,jÍgÂÑtÓGy­!‚5BF¤4JÃaAã,íÜa1.L1MF05ÕUUE[¦!!Ie™¬F‚P°ÂsÞ??`v ½kðp % 2&ªï¥W=4{F3#Ø&ˆ“Ö´lèÏv„£†Û¤‚‰2Lª“F&]2M‚ê”.31D»ºÁ£5ûŠá«oÁóÍõŒŠIRñ$Ù”¢#‚Å‘@çœYïöñ8x›Ï@»føå?«ÐÏþ+Ò~5Ž6ŸfÎǤãÿ&­ãyÞ1 ´’8Áç!òz>—Õ,Y`±T`("‰’Ò¥AŠˆÅX¢Š[T+hŠ‹KVÔm-ÛhÖ2¶”ZV©j• U¥k[ôa~ÇM†´ÑT b–ÑŒUµkUbªÖÛ[DV¥¶—ò˜ºiX,ÙTDbѬˆÔ¬TQ"5ŠV(¢•h*¢Å* KGYpEJ¨µÅ J£”¢c)j–¥(–Ø¥b ÛV+L¸\µË–S¦fUq‰\j¹™r‹n;«»³f?ùø•-åùúe‹”ˆ·£ß¤+f”H©­×÷Šýç{ÞÚ>fTÍù‹Ï›Í¾}ú˜úv:Ì vRžR¤ØŠJ3¢Î!j F!¨"^ºRP ­¯(*1 Þh5åæqt’jˆ cÓ%z=X0‰\Y8º ŒôÁD  ,XŠ‚ÄTò¯LÄNëDQT1`ÈÄQ|wšÑGvŽ»úä4‹,Db¢¢*¢¢ÄUQ#´§wZÒAAE !€a€a JŠ\‚VC€aCÖlX#æ6ÖÈÌD®üÞ,ºß‹âš¥Ï{î_ít?«§Ùnû?åßÏŸäûÿ{àó¿·ç¹“äxÂÕÇÑ9KȤJä­Ui}ªù%½Wäð|Èr|W14nåyjæpòï1Ø»NÿŸ§VHóy§ÆçxÙ}Ö¬o±¡Øé=OÙø>ÃÓðÕÊ}ìÎШI)Dt´MUÖ%åˆwþƒ®âða›ø‡pB@‘7Û ³ªjZw°Ÿd‚ý–¡ÙíJˆ'Ô³H`A„UbÌ7†T²³LIM|þ­ë>KÏnæéØ[Ixìn”(³ªÀ!Š81bG±Ã `°‚BÀ ‚ÿf¼¥…ÞèIÇŽ|Æ<«éY5x2†åÇ+À2vú¸`ç·/U=$ávÁwg8N‰wSØ'G;¡‡]¾ãJ´QËÕ"‚—Ù×Ãmò_çל÷ï¢~ß~º±ÎšºÔí¶-a aÓ6vÅ Ç\,1^ÉXGdë·[ÆJIüËÇÑÃϦ»ó#àÝAÖ©ô¬_’ë=êx~Å£¯©©2%J,æË•h¶¶ã2Ýjé*(©Å£'êûusRû̸Þnm¦­m±F.ZŠ :©4ÑT¶ëho‚"÷óaÑ×UöüÏ2I 3gcCr’¼¸ q¾ o²h,ÿð‚?“"tŠª!óJ“i,Síþçï]ÿ{š%«³2¨ªs¯%A݇-¸ÊGãË•«PÌ34çf†©b»¸u8ÌÝŠcQÊ,lZ-F–m¢»DTÒW)^,•'=,Ù:ÿý¨¾ïˆïjÑ›´iÈE‹T‚"!ˆå ÀÓQ`³@XбDQSûŒCÕô¯«Ûܤ}RG¨’=$⌙L©…Q áÔeéNZŽÚã‰Ó‡»ÆÛŒhbÃ01¢$1B:G A‰ÖDÄ‹4hàA pèáŽ,X¼¸±Ð:¿dcbdðpí‡FYŒ°àðœ6W ¶âtaá("@—"ßà»üÉ™ÞCfuõr‘ò|¤Ÿ;ô-æõöÉõ‹=<õVVÊ W›V õå‘– ä;RÊB[šÑnýí÷®Ã¯ÎíœG'͙µx·§h›Sç’=Wž³C`?ƒ°?:k×±‘@[Ñz3,šµ ËsÁJPz Eˆõò<µìCLÊaáQ•7"‡Ü8Bâ´ 0YR‘*ySb×F ²ËÍÅ\ l ƒV' yõÞ´)¬Ð^ìGc§¡â1PT}94ZRd”‚UVY«AQ°ûéA.Í2F¶ÊW]™b;Õ1ó6Ñ”EÅ_UÛ+HÂZH†CÁÚr‘%ˆç1$H‰3`i¢¨¹£¡-é¢-«†Ú2­m‹Bjld3&ØsB55† D€°{DÌS“22óïA>}½T’Ÿ¼(þ©Í}Pœ`šC(“ªÂc"h1™¸ºf‡ócUØÌ1ªä, zÏò é4ŒóRªA[²8´²ÍÈ$pqÄWÉÁ´Ûi0¢Úvr š´õXD é´¦Ó6Ç4Âð…âA %)¬ð›Rl9…a0’¡âM3$ ¢¢” ½×Æ”ß; HçÃ^#³Óƒ^ò,Úx9âÐÐÉS äÕšòò£Š±E(óTα„*¸iœö´ØÖlÐAñ6º‘‹Z¤cAg8ÍF”U³YŒjI40”I™šŽ¼Þ>8xaÝGZöY½NªGVjKn•,á‚nw¥4' ôy;òhÖüMHÆN‘F)Œ´.¸fÆj‹#$[GÁrÁ…"V†')FJÏ{‘(9(H‰‰‘šª©Á‚X¢ŠI4¸"3ó|N½/ ÞÓÕLè$çÌãpÑÛˆŽ~…)K`@xG¯¦ ö£rëÛ¶®J5ãO]½"þ~¡ŸúLúúmã¡î£~Ø~<­ö’Ê©9ŒžDáÕ³"ˆ‘$¤CUUæ#éô$}î3÷ÝäÕAX™yÏÝÓ„C-¦Ù/ÇÈh' >Ør´¦@ß–ðA†‹Œ®Ò¶™*IPS&%²NEPu‡º·Ö–[ÀÀí¦IYÀTÄbdI‘ŠËUQAKú¸²¨¤êã’“¨›Ub’˜Å…"**«r›¡ äa$«s\Xú{ò¶¡gÃÍ ßpÑ[™cq¡CõP>„}ˆ³>:½ûöß»ÌYßO~Íß—Òf‡¥vx¾Êœ  D¡ž¬š7y@ASîýè+´Z§œ* ˆˆÅDX\ÛwÝǽíèk©×]<;u·®ÅQQQW8æœ:د<ኪ Š ±;t?ûyÏoâçùŸ_êÿ óÿÃ<én]–{·ØoY ® N>Ž ·[1\—w+CÔDd‘ÆÂù’c8´Ÿ)ôíÀZkŠc–TÐÔŽ’ŸQ’³øgnOø?âðt4YÔúŽfÑÀùsðŽ^Fié&TYøXÁšRÁgB[A£c¶Zváàí‡N°åÛ–WmM§MÃê s[8œ³¯9ÎE!yW9%·›1OL‰WJâL…4my¤+­v`ç–pQüÀ»r³ê€óvDÝkº.¬Ö62«w³—!ðÚnnþÏcöãò¿ ub4üÁûæ<Å9¢ªŒ±9Ó7<‰ôo÷ÿd}”\fgýMoZùvkúœ3tã)ûº´”ÛrZ"w—"¦“5ž¤êD×L2yyø4óÁCÉ8»¬i—SÜtÛ‹I£ÚW_ÜiuÙ„GW¤_k©µ¢Û+ìqÛ¼µÖ¾½7ÛïÖù}ù^] ŒR̼¸!Ow®w„ûC˜eµ\qH²¥Sª¢ ¸˜˜Y™ HÚ\Ÿ0´uJ‰‹TP1 ÕKK)YV2#£W-‚ZÆ´š² ‹1=¿Oäúß[«vGÞ¦<û ºã\8tû²ä©¦{'c‰·Nfrë·Û5L¶Ëgn™ï㇠ƒbÃCŠBÁC"hÀ;n£N›SM:0ážÝ0âe±Äàé¤#dØ„ÍOYýYNg?XüóË•³Ï½Ow®¡]ÝRäua/hoÓ±ªË§µªNMÕåJë9“„!*=®ÅŠXTÕ½½’JeX‘sÂáIÂ~)JJ¤»nöLË— yÌ(h*‹äÉs¡9êóÖͽG ‚Ǧ3©j<°´ÁzÜ7KŸ @id ²eãÆõ7׆´ñÝÓºãíëoN±EI”!³Kxëyç¤V¤Çˆâ†¤!Ð7^í]áC ,0TCïð  |ª7"¼ýJûCy£Ñw#lÍmo=Þìâ¶(0¥f HO)±±šç)hÎìÙª«Å»}#F¥ÔN:•hUZU’Ñ¿[ø˜Ÿy A´ƒíª*/ô'öÒÆ¿¼ÿÝ~Èe¿ÊõþjîëY³z ÇmÓ›–ÿ¥è²ñÙ…¼¡÷x Ñ>.ú4"®ËEûõeýOáé³bÄWUЂýmˆØ"wýžùšZþä4É Â”ÔŠµT@‹ ÀÁ ŒŠ XF²‹î¢ÌY…´¢’²¨­ÓLUPM%B$bˆ1bÄTú§Ø>£¬pY~Æ›½FCFÜ8jL™œ8}¦¬Óƒ‡N›˜›­¶¬2Óˆå£èaó:›q‡,»iˇncl÷4áÓ· É—dêtÛ©Ô넚Šá8Œºvá¶Úve3Ôn2É‚8dXˆ ËüËGõ«©.ôwªÇu?Ï÷TYÙ§GÏ:ó=Oz“|³¹L·¯¼²{±7•5£Ã<2~§l‡›¶KéžGËÑZ¥S< óº™Q§E9^êÀ€ef~ÃE`DZyH*‘ç{—Aƒm0TQ3g1‚õ2ÁP^Þ<ëBJ%(9áÔÜÁ ¸e!–÷h”Cµ4 I¾í醊šI¥Ð$Uçê$•òc(>ŘæöWŒãÚI4 &‚2db¨¢÷NÆÈ(Gù'‘Öa‚LÓM`hÂJ'ôü]è¡9{&µIÛÒDí»1E(£†u“ÙõJ)eŠ“XæÒ "ûböØDÌ;²4ÑÞ2QH$˜) ¢f(@ž/L5ˆenJl$a'*Š…&ZV¤T%$( Q’*9v¢Öš•\U‹µã6ÁöêFZó¥¢Hw4s )FsørMŽL¹ ¤$‰©ÛCUTU &IˆD†Q‘KÚ,¸:nt,™ï³^hŽ‘3t2†0 AóÌVKÉЦå&„àä „k:nÕEQ5Sh(Aµ½a:IŒM›9qcÉR ¹‘’¢Èʵ«S bâ…»óÉÙº,ÜÃ:ާY Ô-ÅŽÿ!£aÒ³i±Ùöi‚vO 97$’ׇ8ß<×ÂÊcµÙÉ•*i”®í`µÈRi4D€ä’„È!cB€ùæª(ª/dõo˜£»º °í×zÑÁ{Îã­Ù¢‚&ħdÑWEñÂÅp||7³D/—>‹âµN$3^%§2…Q¡8¼W™B„Òc’"12ÅLq¢gתO‚ABŽò .‘pœSeÖìtCÃ1ÂYIÀõÜÒ`–ão4  K!†1Ó<™—KèõŠóõð‡<IÚ…ÇÕ£lƒD” (0 A(TÇDU$`‹H"L_Ì(Ÿ~ª…ŸrŒÞ‚Ü í1 ·¡‰5H#`~«Ý°ú0‚]m‰ÀuaºM(¸1‘R®ã&$g9Ia .0hEæ)¡Bâ–yÍðŒ…2 ŒX°Ò¼XHßO H÷æ³4S}$ ^²Š³Áîý/9ãèmðò¦k-?ãjÄ´ˆ¡fGTiÉ Æs Lt;'C|È3ÏÅAUg”ôâˆk»Ð³tѱܕ酈*ÐA”¨D‹xªª1¤gމЗ’fÅšäÎð.Ç£%bÇÃî1sçÀïúOsÿ:¾gÝ|_ÑØÞñÉàè”ȲrUE<;m¶[›Âmæ R½?°û>ûé}ÞD÷œ±­Ÿ43ë;àÈU_ý¿%*ª2”WëW‚/­æÂk9Î^j­iC¶R‹Ëé­-¯G×sšƒ¹Ÿ)å¿[>‘ž+k´îÎìÛ5æm"¨Q3”¿s¼9^>’Ñy×èφ¡¿T$yâ ðYà|ë9çiÙ«ñÑÏýÿÎÿ÷ýÇø Ú;ÎEÜæxúQŠ'i2Rd=Ÿ:Kù…}5{. ßùÒ5D‘,ËHâÆ–âÆ+œ\S÷KQ“‹ä'  ‘ä?×ßt§‘òž‰ößÍÔ:êÜõÀu}mŒînÏ—>ÇÂàv¹zX BW0e‚F€6#®,‚OuÌ>4>?ÕlôÐ^%Œ´Æˆ)›³¬&!íf¢ò«ð?k õêJÒá ´'’¹ãµ=§­†$1#E„ÀE 8cB8pC@±C…¢Žíˆ×Jì`ÎC¤bì72áÏUA±Ü”ÈãNÛ”íÊìQˆ±•ƒ<:G<˜2&f›ËZçJ[ⵆú’Ú»šÞ½ñD} Y·Êý°PAðÿ|>–Qêÿ«ìN³Ø]Ô…pc"""Lœ`ÑL~ü‘úIM+aÚu†aÍÛõ1†…´ ê{}šGdSŸZ­"Œ¶ ¸ÚÔR O—çù–ù­ú5â¤59kz3)>³†Ú}i¶ã¦Ùc†ztifœ®L°Ë†gOs)Û†\8tÛ¦aÇ1žÌº“.ݰÞ2Ûn6œº›u®M¶Û|pê@êuÓ—.úšw&ÚeÃN9h°ӓgLÎS¾iÏî×'É7È}ûõß™ë°mö;ªÂœŸtUŒ¡sa/Rm¯+ÖÓ9¦ó=eÞØ^Lž‘™ŠeCIK €å ‘h²’L¢&ïõ¼ yugap:$S¤½³³×tPvÑ­6xá­çFO‹_?=eÜÌ××ì7Ü:ÐETÉæ$Õ4 HѳGC Sþ*&µáÐáÒy£×ÓË ~PAñ€¨È8çÅFHhî·'ÛÅŽ0x˜ß’}cÙþž~¢±ý>dHáB ™HFýlá¦lóç9ÖÛeË.\3Há90D‰ˆèˆ‰ŽJ²J†r¹x—­è“6hó?À`ÅÄhݹÝ ’Çݠס™p*Á¥6ãé=åïÒ~àÌ)ÚxÈû‹­áb@Cê}:W“Eæ7|üWžç3¦]Œ·©—'2'œõÕ®Ë^»ˆØ”H—.97­«†¢ÁB²ÂøHuBª[<X1,²54Xª –µ0 ØÀQ1Œ`êÒ Sª8,„&¬@rB`’D‚i¨)ø€ƒbÎ 7ñ‹£]«œ-(ÅAb!²Ï¡Ñå ’–˜`èLèf‘¾ØwzªkL㈠Ï4Sèί„g’Í"š„CFÇ0èqO# <¿œ^8Gß¿^»dufõxg›TG¯V=ß¿›F³…Îù¡Ïª£üï‘—¢•ø|öÏ)¿CÞöLSÜQefWŒ+„±†\b×fjÞgO߇ÿ Èý¼ÿ¥êÛ³îÿGô¾¿­Òy˜Õ‘m«}“ÌnŸˆ18ú.þó;Oh@! åšÓ"ñªþ\Åb=µ¿Þ±{ך8ùJ¶Ø@º›“ܽ˜֞wyö¾c V9”Cá⇯dig 0â@££JÕŠ÷Õì/qŸð3¬þoyŸóüÏÀó~híýC¿%‚©À "¢Úâ‡ìØ/‰#¹ŽÚÞê6úÛµï03¸`©f‚*²ª4ăÀJw@¯…¸¹y `šsN½¼íáa>¤9îP@„6ÛE9Em†YmÃF˜e¦šeËj, ®5Jí‡Xż`X¼—`Ž3Ä>žäå ÙÐÀÌDPξÁô¤¬Híê/°v]Ç)6s²ê¨s®¬´'G ™§¤TœŠWáN ´!cæËÔÆl&¼XÜ"ª*/yp>ðûÑ3˜pärýÎ2¬ó_Ö4å瑉þ t6—×.@ Ì‚3(°ËDŽXUrÀ±aX‘$ÄY‘`Œ‘H¤PZIñüß3×39ù/«âãbóž\Lå¶Ü¶ÑÃsê¶ÛmíÆÜÍE|lœœm¼ÎFQ8‡N' Í»“gF]´ÔìíÙÏw''4îaƒSGm¸hÛ.œaÖ]¹m·1Äâq;nm¶ÎÝ´Ë–›9i—nçnZpÊC“·e°…÷Ç;žû2†O íŽ"ìñY'½#åÒÀ´ïvIk4/=/yÅeëÁë‹Ú jœÙ[–*Auwæùâq—[“,ðé‡S{k×?kóÏoß¹6»š™•èM  ãØ,’¤Å¯€,þ:"²ÚR¤>ºn×#,²i¦Uc¶(>TÆ2N hõ]VøË(«Gcë*1bÅ F•Ø‘j =»Jб#@q#@a‰1ÀÀ?RµLUýH‚G¾Ç÷QøÚuIHæå-HëŽæ’.3¢•dÄž†Y1›ÅuWUP޶•(ÕR„È™%©"!â+¼ç¤JKL-ªÂ㢠“*\¹€‘H”"Dd{gž¢Ë¯n™8@‹2FÃÁ`H‰l.Ѳ4vId1ITr’¡ËU*ïËEÁq’­”×÷BÊñYì"8¥Ýžå†!F#Ïb!¤H‘db™è¢*è^¬Å"‡Øˆõ* C„ 9º>Äl€É@ú¹dõ-4D\ Ê“Œ“AuRK%ÿ›xYÉšÙåvbÚÀuÔÒÑ¢jh* ½;È ŠdÈØÆ®ŽÕhŠ@µE†+ e–5#œ·­¢<Ý.¨—D[Mk´"ª¤1Ù1­xÀ¨¦¬JQI2½g)Æ43$<ˆ”$9Q0MQff ä°r胥 Ê‹ŒŠæ)tÏ*1uÖ uŽ—Íò+K=Y¦<¤b¡rŒh ™¦“Dà i*ÈvŽ3 gq¯G Œs|Yïe>z:JcC’”Í$ñYQiJôé(Œ Œ•*)R)MUIƒI“r)S«øq™;Ú´Ùli‘M£['E}â4iË¿zÝ[ Â!/«@"G‚ƒÑ S!EÓ{Ï ˜¢°]R»„bÊ«I…m_kçž3žŠªÿ±,é!BdÒ ‘ã(êG±2C"H&dPLñT\®1š £˜¡Žàå8`³ê~2îÈÀ ŠðƧ¿‰æ}ûûÑF ¢ÏÁøkHe‘d{Ù«Õ¾OU:š ûëÿiÿsúì?¢ÿýÆŸT¨Ï°89Âa€‡ ƒoä¹@À<€¿G­ë8™ƒ¶ÏŒ ËFùÉäñ<|d¥l-jÂ…¼¶ß#oh-’V„pœF3£žªš¿^›æ½KÄ‚!¾z+RŒÛÎuk§ª*‡‚oÌìôÞ Ús{2ÿpߓȾ õíùS¬ú]œ&¢vETª[^jðùs’S<=þq€ÔûßÇ·íÕ¯nôØ÷¼4d÷Ã'JLKdÀz‚ú½…yt¬ûöõºÛhXJuxWÔ´¬ëú=@œ0b,XD(¢$•PFåÏÅN~&ÈÆR^G0ŽH"PµT«nc· :FÛ3Âõ8eÜtÊÍörèÛ3NtrÛ¶]¸k†\ë¶VdËIËm8œ;hmÙ¼¦]É70–aÏwÉñ­i§QÛ·Q5:;eÜÇYe¶òHeħmÃC!]ëžvݘçŸZq‘:9äçx/¼Ú:»­¯ÏºéMï‚vÙÞšŸWƒÑeFfzö:ü}d‡ìPy2 I+‡èc±9F¼<íèÝ8õ&y·ÃÌs&–H‘ï× #ÏLOàB‡xéë Vq=£ÏUúL•Íý6ª¿£úÜÑö$§™j—±£.mZ(Ht¨äP„ Ã!R!2Y¢+’Ñ„ˆN| }“YT7Ô}1b˜Ev²¥tÍÙQ§³ô¹R·`a@Ãc,FÛŠµ&ŒÐÄœç&ujhƒ¤ŒHØ¡sj`Qƒ²U4,8ê…jÀée/Icrµ¨JLZ—p€¤‰áK¬Û¦ƒ7ø_›‚ü`1ƒ|‘É¡ÞcˆoÖüAáÌÊ‚t51ÏI ƒÏ&„J´HÔ–J÷‹L¢@š@™¯‚Š*b RŠVxa26f&л!P›ƒ‘z˜Ä…2K(ꦗXäÁ€·W1ÈŠ^‹ád%Bƒ–1(^E‰(S4ÐÞ͉®Ï,$H“YÌdÓÊ-^†1"U]óT†·S;锊 /¥FÐô8 œÌ b«ð0ÀàhÁ ™èªŠd\Qåk³_Bd¨ÎFƒ˜Â@ÊôL… íó[L@Ðf _} —*±Šç–3¦OB"ˆ¤EAÕ-•¡$‰(™8šñ<EñàgD§ ÖÞN8¹ãÓGhº˜ã9ª­¿‹žJˆª‡ ç+&“ÈÈañXDV›rëžµ¯Q¹‡®vîF[ÛúKž+X1‚M.8å.ĵçfL‹·ìs‰<ЖJ4T~ž±Á hhV1ÏÄ0þ&6,lX86l×抙ÃÏkýùà½çC^Bf®ÙMudð·®gw˜x >-›iþ'ŸžøËJˆXh<Ø•è4¤È¨A‰àbѱau|ü™že.9Îk]8怴ëa‰Ò¾¼D?*{èàyèdú \ä‘n~7/¡éËNm·3óž‹cÑâòòÖSJÇÏŽlç†7ÍànrĘ`#~GÐÓÅïÉQUôQåo#*¶1Üÿ×ù¾ÿüÿ×ÿ'_½3U>ïvkÃïU_³Ûü?Ú?7G+çLOÍÕóþ‡æ`îìü’'ò>+Ó¸÷;†‡ŽQ¡™Ùã éºí»¬ ·³ýä¯ðyÎOOž3^³iñžïH›óÂÚ o—äjRVy5{˜ÏKÚ[̲9yÕ¥;/'ªð½£_B l(ñxÊ/ƒQV}×õ2ŽEð§$¾=ü|{ÞK1œŽª¸'noSÍñð7à󴌌rpSâîíÌòcg Ú÷9Ûã÷;Þ=ßRê]º’ò3í» ï–g$´RÑ`œZ1µ®ôý£ÿŸÙOúîÁõ­±y’>³¾ÐÁ~,}–Ú;u?·“ˆ«(yå<<¿îgäÿ×Uè¯Ïð½„ÅÇx_kÝm5u •èk”t=>n“¡èº>“ Ý>wO7º[€¤ œ7iÆiÛ—ÿÜ š»î Álþ¾kJá¿—*£Ú*1QŠŽ¡œwš ÞMÕ¸Ãf¡PdY†ð@vBg™ä4J¤aX0³Ù3,·%”K¨åY`Œ) ׈š›Â€K)’‘¢Ø”²–+0œ a ÐnS,Ð3C5¥±4l€Mâê%6 ‡â#MVØÃ¼eÁ©¦à‰¥4Ô¨ €,U`Œy£#¿l&• ]],E„b%é“]Ř Þam&QK;óK¨ˆ‚M”5 0ÔÑë³F‚Í Êe¥¤2S,ñÂÄÔТTQ Šd£)D‰“˜ B«…QL”Ì¥³"Je¶ÙÆБ&âl³o>~Æç'ÍÅ'ÅML¸)‘0±)²Œ)‚8¹(a†ŠQ&¢RÊwa@ɱ˜a,£b¤FR˜OÊ ©£A¥YVÿ=50ÐYìòÃ÷74Y82&*“ÅÒ¸³Q0ˆ–RˆYjâ­–ÙrS ž“S%%,¦‹ˆ–8¸P<Á4L(h¥ >ãš–4S#0J”P\4رNrXÏü>û¹Cƒþ_Yü(#ž'Šó+ üo£Ûþÿ±ìûQÝ|P«û>ϳ‹Ê2€ªäÚI‹ÚmÈ×37ùyÒù¦ä±&èÈ}Vp£5<¥ LyU”j;Ä—WÄ:PO@Çc( ÿOÒzâŸY ŸU Ë(›¶M0ÒK”è™…ÄP¬¬X-eZSi€c>ñ®Y*1r…#ZšBIþ’ØŽö"ç!Áëìº^Ò7ÿFF¾Ń›ðß3 ‘€ ~Xp‰Í€@!q QŒjo@¼­ ¨ÛPã4Ȧ½"¶ª©GÐûÍ4fw’²{p˜©™“˜¬?$·:óØY{ýzÅDnÑp3™Ÿ3)‘ŽJñÆI+óU>Ë­þÓÝûjýZGòßAdeöØÁk:­TüòŒ†ZcçD@õö„þ<0õ‘†\2Ý8]¤¨û˜5T­50ÿ³ó½è ¬b¢qJ2*‚Dw;0‚þÏ’åflÓc˜Ù°‚ý²ê¥TÑPNåh Š-²›¥ÿVÈ<:Üøê ™lÈ›Õ2S«.‚Ø1MÕ ¡ÑZ —GØÂ]õ5Q×KÓð/xO‚¶]´œá’)8üo–*ôÄÂOfû¦o­¶s¼RJ0u©’Ûç«õsFj”coƒÀÛà™.7lñÖ}ez7‘]“î¡ùSšSÂð,©9K8ýÕkÞŒí ©‡,#Õ й«Óï-’ŠªÖ«;"¡„¸íõ!i*ŒOûn^;â«“²ù¦>±¯±“·¾Ç-<ªïDEP5«ypoÍz Zm$Ñ¢bÞØÝC :4é~gðð¸s€A&}ðÝ/«xµZ;Š›¶4Nɽ”fi³Ê a£g×&úˇ­ômæ¥eU¹ÌC3´¨7ðÞÍa˜¡»¤RiЀPEN²(\ãã—¯½,¤rP=UOXó }°˜Ðd îÒªÉÍÄä¨Ò»äÜ›¤/€Îoá{o'ÿ‹©¤6äL1±8I–^Díб¦Xt;(ô1Âf“žç빿™¶M£~Bõ@½›{Ð>´±8)ΡøŸ/˜O9èìõWœí}ÿôÉ¥W-ë×Òðw¸°'Ä8¾0+ó‹ Q|´=œ–hÿ}ÇœÖ2óžPæØâ+¥ýõ¢ú wÓCÛøüݺoïrUÛ²UkE ¹þ?ÄõßÃ]ipzjéº0d#¿tþòd„•@OˆaZ# Ê¡æïÛé~†ëàûÿüëDQc¸ê{è÷pé皢öì(Û͈Ý_^ú²`ôÙ|ÌòUwalãÍàÇ tÀe%и˺™¬T#‹gAVš•šô! ¿~ý=øþÞÿ•4Ïê/ô¾;äoñ?Rkœ™M>Þt\)"""!½á+l¡õï"sÛ]Ý¥¿†úç†Vº™¦oŠ´Å¿iY ]ôwLF3Je¿JáU¥ Ýê\vNfhG£ ÊÓ˜ª¯5¿ÝÃt¿ÂüxFñš¯9¤­®:åúÙWEdÑzå7j64¡, ¬Ñ\¿å«Ÿ­Í¥^>ÏêÛ½Cuð—QNJ&ýSô˜×’îœí³@“0Æ£½7uEh%ÑT:†š¿&wðæÒ(’ü¬#oo 3ÊÓɨ÷ê6ë¤fl3bñhÕ‘W a·6Sx©õ!˜¾87JáÙjô¯%•áM-·}µe&¾ 4gñ?)Çž.®HìT)"¡-™¿FyÎÍN¯M‹æÃu¹ês)nÊd¥UO:—Á‡X-(ÈQzãIBÆ¡GVzi,c5©úö´D’ê!FðK=w_^¶Ã}¯›6ÊkA×”;{#3(7…»]©Ul½9vFšéãŒåݤ6Í÷.ü÷ã¿ek§¢D-Ï¿ë>ržck²Îù3f ­å}2Tè¥R*òâðêòØs}™—>¸ä±È^ M°ìŒ•j£[6UÚ¯^üþ ¶un‘E¡5㓯sfíÓ¯{g:Û, +Ã,‡QÔUJÉÈ/3`ä]á"3ߢë“K½yÉ`tµUPUEÁsf‚”!²‹–Vƒ nûû3l±¥:ÕTЧ-»µ]g†v*­6œV=˜u¼…7îb»sÙÃImYë^jÒZœrB»šR.Ýs唫:UUOiã( þ]9õ7ÅVÛ9ù2Õc|vŽÍ©„ :“nŽ×‚Æ”Ý1÷žÊ YjÈ•›UQ[.ð„”X¸i“Qf²]?cƒüš_×÷sˆ«0DOä¡,=Ž·–ܹŒº#µñfÛ8¯ù¿PÁN  ¿ÊýFþž¸ÊH¬›zøcèÕvÑ˭²0N…0RÜ<î›$bÇÛ óÙ3Éìô‡N{[­ŸåïŽ?ûþýº/¢¿ŽaÐð¶[í±“u¸Ç›%[[€<"X §Hì œrÜÅÀ©€UŒ@s„ÎDˆH2²«ð,ZÁù£ÁK_ƒ"Aê°“h&ÐJ’%A,‰-[Th!EQdUX¢Š(¢ÅV(*ÄAEU‚ªÅXª¢Š(*¨(ŒAb*E‘Qªª‹dŠªª ,Q` ¤PU‘`ª (EŠ«X,Š ¢’"@","‚¨¢Š,Š«QEX ŠÅXˆ(¢Š¢ÁUb¬UQETF  ±"ȨÈUPX«$UUUb‹"‚¬‹PQB,UX*ÁdPPPY T-7ÑG¡·+i±¯Þh`»|eÈ íÕTA<ˆpê8åËö¾ºÎÞÅòhÞÇÃÕís ¡µ•×½ï·ÊÞÝ­Ðm}¼!‡ÀYâsü¾’¿¦…o?ë*7<ÔÇÞßgŸu°Uéb©¼nô£ÇoxíTAUŠ#Þ!Á¿®ÿKܾÑä]7xçx—Žx—‰zÇ—tŸÄyGò­å_"ÿ;à½SçäÞmæÞèž¡ðžQçqæÞçiç^¥çžyéŸ4ùÅz§48ÐãC48ÐãOð>Àøà|ð>Àøà|ð>Àøà|ð>ÐúCè}¡ô>‡ÐúCè}¡ô>‡Ðøà}—Ù|´ûO´ûO´ûO´ûO´ømð>ß¾Àûø÷_à|Ã~à|qÜw‡y¼Ün6› MMLÌϪ~…ñ< ‡ÀPRBTH„@á¦B‘Sƒñzoøþ¿ÐqÛÿWÐLÈ$´Õ‘l‚ªÄZȵl«ÕªPµ V%¡e–ŵm–Å , ¡X ¤‹$ƒUd0YVD  D ²H²Y„Š „"„•H•P,¡j%¶‹bU UIeD¶д–¬…«E”[ª‹b,¢¬!<`XAX@a°aŒT ¡…JB”J¢• T’ĨªRJ¢T«VÛ,«ˆ‘‚$H¡E‹ ¢ÁI"##‚Åa ˆÀTR,"ÈÄb*¬"(‚Ih–ÂÔ‹a…²J¨[‰T–­Ô%RȶH,ÀREHE„E€5-’ ©¤X²Z‰ijH&$[$"Éah´?€¤ƒ1ia8óžµF@“Çr´Ú£iÏéV$ABÔBÞ\á~¶³!Q%µ`¸&|ÿËýËØr ‡-D#"6ÊÛ%+DTE‰Q¥"‚*"[#l‚ÂÛhÖ…¥6ÕÀ’H !àJPP¹O† 6P(Hȃ¢ŽëìXÉ9¨µD”‰T mA(²HJ[VZ±"Ø–[H%„…A* DQF )óýËÚe¯ýxѰ 7( ÐMi„$ˆ X@` üÏ·´þÿÚó¾—Ü÷Þý«åãÓx|ç¯ÛrÝoèmú5ž²O‡üwSMB·Ë¡¡üd"xÕHÚº3©ª±{<ö:h S@0ë0<ñˆC/`ó놿?íþGgæÊ#ÕU¡‚k… ÑÄSâ@/‚Õ"íù´:ÞÐ¸î„ úÙJ"Iú úÉÂÅZ$Aƒ"È‘<° 1(H;zºP'JA,á¸H!POÙTJ\* #Þ ;ØŠ7¹UD!B „ô»ÑQ¿‘¸&ÐK²°‚_¿ÓLDDÄ"v’ 0IÒ¡Ù"‹" ˆ"E’ ,$-[$I-’$µ h,A((¢BbˆÁP`¢ˆ[dKd ?:A3ô«”¡L?sÅÙçëkì¨õ?OGÚ[ªåß©^·V´À=\õY=qâP;¹¦âyíÔ×Ùð& ðëmmbÜޏZ¦<ðž.¿Tñ\¶øÆœ(Y]x÷$n»SRà§c3pñ\EI»™Iâ™Lö™OçעąÏZA<>€ôÃú^¼ýßöªš{›G6ä_×?aû±ý/÷¬[ w*ØöÃìOäþ.}}_cÈo°¿æf!‰Ô€!˜²¯Å‘ï‡8¨ˆ¼åŸ¼üȆ>ÇiKƒö x\ÉÒïcIøñ÷:t!…о!tJ«$×øzÙ÷ÏœùXðgvÚE½ªíﻉ_‚ˆè „ëÛ'QšÌ@ %Î|Qj¡dý?Ž™Í{7† K¶èPº`@{>œ@l úA€0U±dUª²Ú –‚XBà‹Œ@nJy1Ä 8“ÊŠò¸Ða„‡ç „½xޝ˜±Pj)PJ•€\C1¡–Ìgõ’ ñ ¹N”@f@rÒ*mÄ„“C††0NÇòžœDàJ™`ƒ1D‘‘H±V*ȈE€ªB)"Ä`¤U ²(F²)"1`" ªÁAUdDb°¶U•mÌö’¥±Q ‚z›¤¥Bʱ@Ò ”ÉíJN›¦†]ŽŽ»Ì FÀɃrYm•KD›A6‚v‚s’NÄh $2$DUTEUUUUUUUUUTEUUUUUUUUUUUUUUcUUUUUUUUUUUUUUUTUUUUUUUQUUUUUUUŒUUUUUUUUTEUV1UUUUUUQQUUQRI’AUUŠª«ªª¨Šªª¬"0`ªªªªªªªÁ‚ªªªªªªªªªªª¢*ª¢*ªª""ªª¢*ª¢*ªª«ˆªªªªªªªªªªªªªª¨ŠˆªªªªªªªˆªªªªÉª1Qˆ(y¡ÆŠ(Ø@`ˆP€ÅA$]$Ó(’Bd2ÕP2wIë Zšgzdž ,x¹zæ:BIlßsùû‘3€Š(ñBC„2…´‡k½™],³ïHBI†¤d$!äÀð}=³CïV]JD5š×É#qäC¸í&âj.11/ RÒG}hÐÉ Àâ•“vÖˆVBû=°Ìs›$$ŠÏ §2àt1%Ç+ë»5EŽË¬³*“4k „Ä*¬Ë+¬*´*“Zº´\Ý5DÍÒ\]Qåîóè`i ÐÐ!I¤¨1pw¡•À@„Ub °ÀþÞà0ï­‹ ’œtäâ&’xðA‰"EU0Ô ïlÜ~™Œ0¡Ù@ÐÁÔõ›,ìÆd:Oþܨ]r£åO|H%ˆØî|I>Ì]ZÁíA<OùE5%*­¶«AUUUF2*1EUX¢1ª¬`ª¨Œd$‘¡$‘’$AUV‚ªªªŒdTbŠª«F#UŒU‰ $F(I$d„R`ER•rET!E‘ ArK%UUUUQªªªªªªª¢"(Šªª¨ˆˆˆŠªªªª¢*ªªª#Aˆ¨ªªª"ª£UŠªªªªªªªˆªªˆˆ«Æ*ªª¢ª"ª¢*ª‚ªªªªŒEU‰X‘ƒTEUUDUHÁˆ1ƒ1Aªªªª¨1ŒUÄEQUTb*ª"ª¢*¢ QUUUUUUUUUQUUUUUUUQQQŒEUQUUUUY*"ª¨ ¢*"ªªªªªªªªªª¨Šªªªªªª¨ ªªª¢*ª¨ ªªª¨ªª¨ŒEEQTQQUUUUUUUUUUUUUDTEQUUUUUUUTEUUDUˆˆŠªªªªªªªÆ"1Šªªª« „EUUUUUV1UT€ UUUUUŒUV1UUUUUUUUUUDDT`ÁV1ªªªªªª²2*ªª"ª±Šª1UUUUUUUUUUUUUDTEDTEDUUUUUXÅV1UTEDTEUUUTEUD#"*"ª(ƒUUUTb*ªª¢*Éd$?{HBM'ü8|áÄ‘ÙòÄ‘é""~™T±Pµ-–XŠTªª¥Hª¥UURª–ÙR©HYHYe,UU*ª…UŠBª©V[!VU«Ù*¢¥Xµb”ER•Ue*ªªU% (HUIb¤•J$(,P"‘Q# ªŠUXKd•U*R¥RÚXª-"©UB©T¥´THЍ£ ’"$ˆˆ‚*ªª¥-¶¤Š– °Rª…)RÉK$ªªª²R¥EUUJUURŠ”°ªŠªR©jÒÈYVŠ¥P&e0±KU)Tª(Á„`°°ªŠ(”•U"U•eJ‘–’¤ªª«JEZZJ¥P¨«*É,¨´µ-"U"¥©RªªQR¥K!T«$¢Êª¢¬U*Z´¥%°²ªR©JU-YVDA‘ÈŒcAH‚,P²Å”RYJQU*©R¨¥BÉDR•UUUVTT¥»à ®JÐÈ"Ù##š¨% ”9¤Ì-I4™®À!ÿ«€’@“ÆlÕÊDXA`#"LJ† „ÎMÂ) ˜©H$‚ÄVabTIG0æ¢MIBĉB ¬Tr¬H””¸€EnBå>ÀGê"½p< ÃV™©ÞöÒø?OýŽGÏ”ý‘SŠºø×ygJÝøR;sž’³<…Cs½ <‘eÙ\ÚÃ~ŸFÑ:ëBÿ”¼‚eáTPL^J'áV€L«Ü+r^OÑ  ½÷$ñY{f šnõ³ÝB÷yã<¸ƒL`]ú´6¨¿Ú[¹ækóeR­ÿïA(ù ,ì#û¥Òeöý ï1¦×4¸•ü€¨nÅ·ÙÉñž Áš´·W<ÉõÚ¼/aÆgEÕ¼WÏþßÕ䨀ý~t\½Æþ®Ôëæ ’–©«ë¾zΧ¨ ¨…r6_S®žœÅ’zÇFyE¨û|ÍO2ƒtâîLF€„*G¢,l¡!ˆüäbQw¿pœúªBš8úòQ¬†àtø_³ÃøïEë3ž¢ PEÄ 1DH 2 @‚`€Å 8¶œ!£GÀÿJ8„>ɱýŸ ¦Îƒþ˜ 3ëPI®í·0Ç ýbo÷9öBHÛëûÓÞTCÖ TN$(!‡ì}1¶÷_­• " €ü!T‚*£TB¡åÿ”F”WÚª¢—ær”hˆ ù8û"^?{ƒgú`”"ç}—ï~‡ÎøóµÃ‹íõÚÆLãá€ë¢1ÉSŽÉRÈ'Ž2(s?lKqõGok .•Å^ Ô¥õ,O—­-“Ý|hýk•¤ÿ¨õ•ß}òÖÚ`^“=!ó^RÀõ¦ì2a£ù¥À!„8%}ž­ %É÷ÿÆ®/ö^aå-W'Ó ’ú¾»cáà:üßKc‘v„–÷}³ày¯$nþ0q¸1寂¢w"Ï@ )íLÀ|ßw“³6ÇÓê vAÊ 4  ¨$>æýNo ·ù^ñ-gËl ð{=þü…` ŸÌ¤‰ë)Tª’ÁVKlUTR¥Tª*T”R• ©%T*ª¥U)JªªUUˆÇÞ}¹Gé…í ÄË¿!#Ü¿Øüöûï«ûk‹~ßÒû¸Ì†Y‘"€ÂsðÖ–›ã€9Í›¤ÞÓV8Ëwó}ýëŒ0ý @§i·×/¿„ΫNÿŽÓ⸣ÂÏõ]Ogç|¯Sùü/cÄÖV‡›ÙY´|ŽÕDÉ=æ÷-/ò£œF ^˜»0Ìeù“¢ÅGü¢DK¹BÚôð#—X|/·Ë‰å¹¿ïøœø€ôSeÀ‡l‡^ËWêY;sèl|>ïêØ.èê'èÚŸ·ø H€²¢2(^T¢²*"H£ã •EUróÔˆ’ˆ‰tT¦ R‚Téö^Iä3)ƒ7´X[cô:ñ[¼Ë Ñ…pLé ˆu0@spºN_­ƈýAKKX,E‰m´+" À ‡è`qÙ‡ïÿ¯ž3Õ<@|ï¤×é<×ùû–‘à¢HB«™7þïT<‚ˆêl8O¹ÿÞÆä8Å;¨@Ð.MÍoìœ{%)hu=ÿ¾·yàz/Ëð焚Üi†ëFÐlÉ£!4äÆBá û¤Çâã ,Ïá#¼ÍëA?‚kB@÷Ÿc—¶î(ô†—/ï´ ý0„Œ ÂŒ$އŸæZÇÅw'ëw¤44¢þ˜¦¡xy¿- øoÝŠsrŸÝ&ÂRÛH™À•_Á=κÔîsAUÕ—è…K‹ÂŒ¦ÿ„€@ —Æ +â!_ t‡ósÌD16¢Jí~3yáßAÓó€TURdY*É"‘dEˆAQ‘`" IH²AH(@X)@R"A@ŠAH,`€’Š ‰#"HHœ÷é¿ïôpy8s" Ÿ¦A=¨$ ‚|© H¨¬ ªÀ@wçEvŽî0Š\‚/¡Ý€ªœH*€Ÿ Óv¡¸Ïòù•’85D¸“Öø Ÿ”’~Û˜"8A>$‰Yë¡´!Tq0´aè÷˦>ÚõOæ=ÙÑy0ã$ƒ~ú‡lt‘Nǃ§TáaÛ’‡ÉüìÆ?i½NSÙýÍíuþkø%çmïÉ¥¨ÆËëIDª$Îr˱ļß3ò`üjúû}úa‚"0Æã„ àµùÖÏùS(~Nì¿?ìókK öЇðªÚºšä¾]hS–JÿQ¦®Š'Œ>~4îAçä‚ˬÔW/®ÛòJ#µ]R?ƒ²úæ¸{o¥Úöº^ççñ>[C²PPîDŠA^Ø€f„E¡ñ>iÒt91öò›½ItO[Ùq½žlrzÏBQTcCä ꨤS¬Ô±àP€ÕAH`‚V’ Á*$ÀÁ…顤E}¶Ì—t(|h¹ÝÅ\*ˆvÜÇEÌ¢ ï9A÷TÇå¾È®¨ˆ¬ßLç; U0…Æ?u8ۊ膓ô>n ü†Bï•Âoî6½_{Á?iÃs¾“ÅäÍ® <ãÅ÷å“‚ŸÇ´æÃH7|ö¿#e’\ŤÀwü!XJ[.÷Ù1ÖxËa¯΄À—¤¨ß˜b§ýúÞ¨0€B¶Ðwëç`¸d÷ã'éYv {%¼õÕù±?áéµs‘Õ  Äcµþkˆ<ž°t˜ÈCÈùz ³Ÿª‡´§ÖZȦ‹÷&ëoéº- (cò~üEÝ[ÕðÞ8±âÿ_Ðåÿùï; '²òÞ°ANðAL]·[µuTTñ˜>¶˜~SñkK£’úã³&îãÞàòÄkwÐ^|Ø Ï]çwÿþí £xrƒûi Ã:ЍÌíBʬ`Ê…O â,I ä %–EJ)EYÚ…ª¥UJ©JJ²Km)dK!$FIRýÃÕbÇÄ*å‡ùÿïCoïÇý¸ÈÅn¶½~ùû,‚Œm?Á:#-^ƒ2_xÉý¿‡:tñV‰˜´ß­¼Õ{êÔKÑŠïyœ[µÅýn™ 8àÊ"Š?±r¯×!íyoܬ'ÝõÞ»Ýyž4aœÏEê¬\\syGDÚU°¢|Ž€L.ÚúÇ•<·1ðúa½¸ø¾¨Îû_ÈfÀ‚ OéáÈ:ŸûØð9~¿ïäÙǺþ›O$Î@}±ŸÒl¸l=Q’Œ§öm©4Pžà7áa¾;-ÇaÑþçÁ÷=oQøþ;êzêõÚšüòï6Eá%lÅdhyÝž'ˆ5©GCSRª§Ç¤€9}gÏôʶíÏÑþŽL3 øý‚÷ñ¿O•úýxgÉJÁ ,ˆŒDb‘OÕùÝÿ:†x#×À¹ô4üˆ¯fÂp#úç›ô´Ÿ°ú~ƒ¡ê¹ÿñéz²xþ«ÅῚ(鈢€{¹x‹„]p ¼þï½âyðû¹:·¬–!=˜Üõö*ûÆÅã²ý®Ïüq_ÎÒšÕl%În$ìKXù?/šþûÁ¡Â¢nª½©3ŸÊ!ÏíÌœåý¶Ëý>g,‹?%°´Õq(kϧüoØÕ˜;Ÿæ˜Ù 2ƒæJô¯±s Sðâþ-fj×·fÚ|ÛØà{…èº+~‹Òˆ)9©Tý:__½±,‚üúaH«;¦ÆŒc™ñcß!Œô^ÏëjùLœãòt‡ÉµšP©tÞjãKeXŒèõu/Ë,tÆ~D.xdË"í!€@%!À :]e"|h/Ày ª¯SYê'ŠsNF©Ÿc7ˆ ÍÅcÐAñÁˆ÷A! $B$’DA „7Á¥Ã êö~ÿ±ÇöG õ ‚ x¢¾×w1GÀûþß¿»ÆŠ€/Ÿ·x€øb¢ Mð“†vÝÙ¼É×{]žÆ@y~×êrÆx"¾®Ó™üéF¶ÿÄy£Ìÿl’ÒO}'c<}g3õGˆw¿AElªÚ6©jÿ]ø¶þú.C…á¨XÚ­-¿ÕžâCpÐ"“Ð ”ÂÂÙ-OØ’¿öuoGÞ5ÏÒoÁÃfÆ-ÀðˆP¾ž“0 %ŒP[~?üílüGÆö7§9õ2rß¿ßg¿¶†n•ËùË’^#l#Œ¯õ¿®7›ír±GË÷O†Õ±c¶«iÏüç‹S0_r£ù°ÅVØä¿F~ç%æøŠ9ƒAÛ2n[ÍL&"dp †¸ãNéŠtÁ(„Òœ•T<ÿïô"¸Œ# !yÓz¾ëC´èþ-ý¯¢ípóº°ùYúB(oÍ3Á‘õú£‰†"o*.©ñ,s±3”¼H,ïä "3]as>óU\dƒÞ[¤¤;ÉŽÅe5Æs:²LƬÌW|‰Î–„]u¬íÿR£wôíAiñhí¼ÓM3”DóçÚYaÀAà@ÅvFmmÒÚªûJà| >­ò¶€€õ}vnŸåùÎDZù¿ÍCâêjI$’‡'pv\Ol ?"ìR{}l8aÙÞ!ç¥æ‹¥ 8~S÷VôÂq.zÑ32K rªùà…9ëJ'ék˜”zS-PNåPæ;õ(X*yÊS?}µÂÂúVåvLÉ5ëoŸgL_0T„©EÕö]øb ÅTMõ9$waE_Õ•TR ¯…Ãt×øÄ?&‰3¥Ø¥x}m½¶ë0d¿JÞ ý*%÷^K®/”ùhà”Uø÷oÐì­VÒë>%lb#A"mëÁÚ~3U0J… ¨ nˆ>`¿”ü«¶N¡Kñ”2€ ‹ª 4(Î (Ó y£y¨­KOçùzx¼¬ú˜ñ–B‚«û¸êÿ¬´ê!+eüôßÁÒ‡r÷’'ƳeTS´‡©ò  žt‚/+óüA –}½TN HOÚÿ±ËâßAÔè·EŽ p¬Ýø•Û˜‚° ¯m¥! ° $ahàaRaP;“ý ×ÓêÐ1TièU 0@ É_b½åçÈçvFÌð«?Œ†ÝÝiƒÜ í䋾5¨Þ§Ëñ·PÈÌ#SDÌœ³ DÀ

Ɉ„Ûû(c5›É @‘Õ>¯Ëø¿ï½½qôû3¼½Ê¢,Xê”þ|?¤Âgõ¿toôm}?Œ"‚<ÎT *²Pý‡ò>Sïÿ°ûã‰Ó¾Õ^è8ÀF,Í•ó› G<ÕO˜9w°À¯ïîîÔhÌþýš\YæÖ}‹å­/Š\7.kN[‡¢^”£° Ac<4’:$!=öª-$svïí_Èú5Ðß„/¥ !(»™âMïþÄÅÅæ¶#Ë*¾êà¿£B¾·|ðsâ$@aï½Ø ©„‹]ã»§¼ø~½Ý¹ÐЉæõ„DN9ã.á.Àª¢ÑPsÊqÚÞlCÍàÿB¶ýëŽ+ÃÍùz½Ü‡,|døß•ÜúaÈ =×h{ìN¯˜Þ¯ qC£;á 4ÝâFp(#!ÓKÇs¡€f¡A¬Ÿ/†ªÉ£C#Ö   ~z!èÂÜê9A‡»£ÍÌ‚h]ŽþüSEÙˆMŠÌTîu®å$± j±"¦~ôCåúz~{Ïk‚ Ú–·&b­û¦†RBÞS!Ҵé°ÂLȶ{ÙsßYD0Æã€¨´u»¡Ï@P [›ªXIù²bBy/mp#É_Ìó׿È`lCÈò¿ó¥”À{ÙFˆšˆeT[˜LK·éä{B%D± P÷HÄ’ {û…øŸåC- ûPó[@U2¢€fuˆu0ø´Ýèšoíh¸½ˆ®léˆDDó'÷ÄJðÚlÃïüÛ›8_½þ¿Žò¸ºÀ‡ =q«´ñ·‡HcÎy‰û¬y}œ—)ÍœIFÙö•ì„Z;( Œ4š2%£{2Ä!Æ „FpÐ €sŸG&Õë¦jI~àü>â.n©{aŒU÷ž£®Ø½¢Äƒû9%Ýþ³^a¦Iâchsi”Ïšµ€žJm¢|@ °º(¾ßû¸käÁ{·QùC›—á;ï½³Es$ Ïf#¡D 8/¹§‘¹en 3ÞJÂxQÛæùŸmÚ« %ØpaØo(N*D'Q ÛøÝ¢& ç¶îÕNÊ$ª•*¨¨%@°*T…d…JÈ[JÉ À-° •€[H[d’+ R°%JÂB¥I%´„-°-¡-¤„¶ÂÐ…KiY-¡$–Ò%`KiRm!-²B[d-°%¶@ l%-„HÐ…J¡+%´…JÈ[d€[aÛ$+RBÚ@©P-²E*VKiÚÐ…¶Kh[@%¶KhI RÚ[Kim-i!*T l’Ú¶Im$’µ l„…¶J•$-¡XBÚÒ  Û$©P•%JZжÁ´¤+!Z’I-¤…´-°­H¶IZÀ-¡%´Û i%¶T+$•T UPª DDoù "å=g"è#¥ûh*¼á„Tw?s¾}O£Êˆ‰•¢á]®ý/kôëîrœ6ž9$’„ªÉ\$·zL’IéJª>-“|ÔQHù¢Ð«~c¶á0ÛÍÑRv=ïq²‘/Ó`àžeΣƒ—Eõ„„„EQEQAEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEiaAÕÁÆ J& kà'¬úÿ~ípÀQçy¡ó¤„[ïøE£ðöùŸÕ±úrkÿnªŠªª¬UQû'ÒõI \ä!Pïv[n]»KS÷Q*®08·ž »4†ƒ©$fSkIñÕù_'òÿ“ä~ïåý—§ï5>‡’üûN~Þ<ï2UÔ»+H§£2ZJG£÷_ñsbÞmÓ”Âî/ÂÇ|NÜ(/û§­—$«ê%Ú4Kà ;Pè!Ø¡z€<àè]ݸTññ/Š–lÚú-j%Ä¢ ›6*›X¦˜æ{ƒ«ŸÃø–N:…g¹è:ß'k[ Cµn`""l¨„*B¿ÿaâHŽ0ûH”˜{Ñ^ÕACˈ(@Dí¢*ŽJH’$Ê É¨’* ©·Ä"+®ºJ 9ŒII™=¶aÊ ÷_·íÁó‡öuH抪!Ùxy*¢PP4+çôî ·§þ:ýEû;1ÚßÓãÙtónl²‰ÁÝu×0Ñ z¯.O(~Ïkûþ_^Ø·ø$âXÞ\¯ö' Bù¨’ZI eˆ#YF"–Z)à& ’20¨‘¢Š•MUU ëì­Úô=Æ‘ÔãÅbØÀÌ.ˆŒ6ÂÛ¿—…@uÈšàz3¦þ+ôuDBBÀ<0x*Ó{ÉÙgy¨‘¼šÏ-¿]–•¶Ú7Äë(œò)Ú® Šî¬Ÿ=æS±­0ÖäÝ%:¶EV•³gø™{““0ç4rþ$÷¿Å[ˉ@ LÞ öá„   H±ÏØš›ÇÏæ©sM„*`HÁ”€<€À)æÉÔ†& ÂXp]§Èo^Èž‡ˆ¨ìƒo£ã©-§6ɰ>°{´}œš åûHÎA0û&i‚õjž;Y='üVu·æÄ|mg@Õt™uùxO¤§x¶ò%Öð½Å~BáÆäÄèz"ìÑK>$ÁÙ¥“²H?*«ÊqÁË^ý?}Õiûßüô?£ÎúžÿÇvZ~>CAõ/ÌZ¾Ž( þ÷¹¿´­(&elq€AÏO"š¶×x8DÌ«ÑÝrõúgP)ì|°žóvTÓI§Ï2'ΞÕß3èÑWÛðx{ˈY«ÉË0ËûR£Ês´’OEÕ¡ì?_Âú·ðSꨥÅ»¨¢†í뎙IÒã?™ò3‹ÒûKë¶€T£Û“ËÁƒIQÂ8/@ˆ7`Üy ‚jî!yÐ¥«5¬ÐªÁiEZV§üoÿÇ/Þ?åîáý¿Ï|^¿öÿÅþ?é0ŠVåbºþýÛ±f|úg©ôïœzm˜bÔâ? â‡ÍQ(Ç£¹Ô«ì3lazÞ/ä¾·(TòKÞbþüyß?”ëS3ÂèzÕÞ¥Üñ¨"Æ"Ðf¢C‡Œ-]EUѸš‡àŸŸúø8nÀ¿P@ëåû ¿¹ý/ÆÓâýG >ïk‡õùS?ÔFçQ£õ>¡÷e$´˜ôTbsüª%*Ve*¤jLJ+>÷âDvÏ.¶µíRo‘ˆ“ÌÓë=‘ëNÙ¿d÷¾üþÝö)õ’Âä€ô~So­Õ¼ãSÜ» Në'Óñ[¬h,Mx‘±þéúŒ‡‰×ܤݖ¦'Qï¬-RV»Œ¯§þPyá7÷¡)Zù€ÆøÎö˜àË!%Ý-6…Dn&C€aG 8t"Žw˜)GΨuéƒð2wÚGÅ·þÖ~‡Jid} lù…±µÚo¨Â@ïø…/ìð‚S6é/h¼®Ê«œGݯÆïTYåæw¯[íz0¶ :ºŸõõ3ŽtIóð€o•Ç'üšhxÌc ž@9Ï1$AÓusJÑ¢_‚ôИЮ8eúÕÊè?©âÚÙKe-–Ùm–رYb¹Ú:s™µ¯×mìlQlbD^ÿ’ï§›/즇íyö€}?eÚO£‹þ4ŸtÉ´áø3³ ûtkÌÒVæjDRx²mPÓMä œ„ä„ùYya l Êœ¶rt†\JRk¾¬ÉJ¢þwì¿»w茲‡Qð2ééB BpÜ1΂sˆœüÓMÒÕÃ~îLB¢Ãn¸îŠ'¦¢‰%.Ö°S‚’Û~ë‚p¶æpD8@†9 æÍ˜ÄtØÌ†’ã³Ô4&æ™a3)™¤Ä™40ÿ.sƒ—H$zÈ[žÜŸŠ9¤&ÑElŒiq‰è†)‹“~@Ü̦ƒµQÎ gbS3 ‚òƒ#ÔèÞ9ñP'_¨édJsñ•Lµ°¬î¸çÎ&çƒxÅFj½Ñ‰ÒDJ0FS­¡ —ô»Mð;Iû<¶ò]¯ukhÿõ>NúÃ÷–gûßãëJ·ËÊþÖ_ªuŠEM—nÃþ=Ìè|46OD»€˜«îæúi~Z¸F€! ƒ™Ìu¤Àxµ‡#¾ øuí'gn"#åCbÀXYâØ÷¯„x€?• ãwÔ ^ ÷]UÀHGr‡»÷þ[EóXŠ_}ÛSû>/ötœ¦%ððW}Üz\ªàU‰€7_‡B9Ý|Aä‘C€–§§ýšä0pU(ÅÉr×.|i3ˆžUjTu×’õe‘ÒùÄôÇ4e®K§²"9¤jhÓ{yB {eÕÿÏÔA ÇÃößo—ºsY/è™Y¹/톛ƒF-mÿ°Æ0=¦:Žž°…e!æóÇt»õÿŒUQúDYdY%L#‹Ãì èå¹\@ªpW…B ‚õÑA^„QÖô‡™(@@rRÿæ4…Ä>fäÿ»"{®¶âÂTC™‚lÎc¶²2kÙxb“¤*§jJ°”BôD` Ýrð!ŒgΓú E†5«4Bæ\p(Q€ÅŒÂÒÄà ÒRÐ…X²•jA‘oE6€€õ‡¯†‹Þ‹uƒis {P×… :^ܹL& 5ŽªÜTºàÀd+×þ¶³à2Ï` ÉÀÔáƒ<6f!ôtA:eÛ÷–Õ©à¯(v}ºû®š{ð‹;×;áç Nó¡dš4[SlO¬c? '~¥!^ræÓœ‡â±Ö;,P›L¢:Ë‹–1ËÂ4ÆO¬r×GÕ› Y—:ç²›wJÔ\vå\qÙ5×3v1Ól"¯9Ûß>þGKè:¿u:}ú©4KO9Üùô6/p.›u¡iíÒ˜I©±Zk²OŒ]¹Ïi »5‰Kmk®´ŽÉ>ì¥g¦{¶í½¦Öˆ¡85¡ u» ävÈÁ6¾$PÕ,QpÊÇ’‹FH,3ÄÛª& øX¾k{ž“!”6ÜbÖ[-Ö¬»È¶ù«^‚Áá-³«á)ìeöÎWÓ0¤/ؤôÚµÌËd¶Bû%„a&„$ñkÎÚ[=Å~Óz~ÿ’Hž]ÛÏĵâÓrëÉçÊO¤§±ú»Ÿ y‡œ÷;döIÁpmópv<ŒDW7}îa0Àìh@%< @~ÄÞF÷„ÒC(if¤«6±hÔõð-Ç#ª½ÉH{È!ñúϵÙyãùZ·}ô½_™ÅÝû¯ñƒ–iÒ™µŸµ#ôýMêŒûô"=UQKé4)Å]tõ†É(JbŒ¢UÙã(«†ôÁ¨Ä Då&»Ÿ2–ô“¼•±OtÊ"º¶‘_;¨—°¼<0²à‘p›Æ gû.—.@BB ¶Ì{˜°…N¬I´ê‘×…5ù°€0káxb¼hAñ‡àå’¿DÇ:F›*Ã&çU¸©´ j( ö*'¾ò5aÓéFòZü þïIðÛè‹9OF~L4üƒ1“ZšI©ÿ?ÁÕîÝ÷ùîo¼¿æeÂN›B¶…¥“€Aõ]aˆk_@}3¾Êº‹òò#Nhž6&j嬿Äe]XÕOßKÌç·ë·6$f¤kZnÄN6á;¢[¥IŠ§Ê—ÇÕ]H4‚GÊýÛƒ $}.˜4¯õoû¼-£öu¥ÍU Ä·Õ²ÿO@Èšâ›d­B]¾>ÎÚ²Kçmjxœ˜ _½ÄéÜdÑàLâQ’º]ä·Pe²Š¶Ç ³-Ý±Š¶>%ŽàDA °þŸç‰Û/Á\wši5ö+çZÆUµ£YŒÐW_þ‘ër ¤Äne]LñþÿÏæåâü†çƒ-~l¹º×èjQ"±„H@"¢yvõЉ‡†Ê™œeÆÛí~˜ ;žçÀÎ3Œptø_›ûØ¡z”‡Úó—ëÌÄÚêÂG•Õò‡«®HÏÇ!;° qQFDO›åóy/éê¶þãÍý…ûêA» é#‡<áŽGº*pqø ×»µÓ"ˆ„U1‰§JyŸÍz,âÇ BoAyœBXª)g®Ùü@dÔÓ¤ŒLÆC –(¤HÉû׿VÚóîHëËy¾¢ û „x`>ÓÊfujý²ÌŠR¢xGO“xNÄCK¡Ž|)Á…ÁdY¶s¦aÜxKHÇm¤“™Î¹8k[D̈â!Í2 ¦vFã)Õ°0[éß[„Ú‚rát Г††¬ hïB“=>î³K: $hE¸¡¥À9…ÎÒ:)í–z˜I§”©j aöž‚K*j•C(%|„ÿ/ê_Áð ¢ MY*.娢(ìß\‹?’{ÃÆE¤¥mYÌʵbø2Öt%4Í Ë¬ÝjÃV IÖpoI+L݆hÍn¯m›5o‡ieSYíË‹u¼æ-^`ÓÕT,4‰„iRÚ”éK“NùMñÀÙ: ÉM2 TTÒ£ èœÒ):F!I ¸¹sA¡´Ððdâ­áS‹¹,¢%•®Nù¶²ßVó©©6’”Ìêqt&@ªÉ'—âœY–p™_mo˯Ç&Øvò’$e`Bi%‡êôÊ̵ ]]eEë]Æï}8’‰Â«M!û»'nìq3Æ/ ¹ræd5ºŽ€}?›Àts;ç( "ì‡Ô|ÑpÁd,:t¿+­Ò[˜`šIô2âž*€Kˆ!"»p¸ÎTD\îþÞ)÷묰ó ’QTP¦å¯™ª{ÂO?¬x"M³‘ôØOØù™n¡^ 9!ÅSÌ7'—Šxûñtgwçö;N’pÅ_P¢ÁÈT¬‹Ë© Ô^‚~©Œ`aÓ¼ñ>šDô²{ÍŠ1ˆ*"Oî„…‘'gÂ’X¨ª¶ƒÃk¦ß—ŽläüðE8‘E(3äÕÒɆó5Q‰hà%¤¡‰ÁË6§^+[ü¸›“\7¦}zñN}­:ÃYαŸ ‰¡”Y#ƒmqp2ôÇ4IªQè…@dm•KA|@`6ŽÞ ­ÄVÐ{¨õç}ër[Øö2ópÁQõ ~êo…«k†-–eN?wÆðax{¡í8™<þü³ÛS†ºaOÜ}Šù']ÖzêPÒÇ7)¨­ü5‹@` ̦uø$ ˆ{¨ <2¢¯*˜ƒhK„þÃül$ãÅ­jÂÖ­/™âÔ˰٣vAÙÍ¥÷Xs¯¢J–tL·“U@­ÄTUØ1„b°Œ‰ÂaTN ‡¡HàB†íÆfõŸßëy½])¶A6œ֦\›i¬2“:9›m–YºÓlêF$‚§)bª*ÙIôŠM*Â+ÏÒ{$u/ç. J´ócCªKKg®˜²L0ñI_‰ é6O9ÔT'­H=ò•wyðC„š g“`#Lj" 8ó|ɘ¸+i¾Û ¥<>3ßé!Y=ˆ¤@µa øÃŒTÀÚX)+hÏt$ž¤ø“>Vsõìí$‹F•>}¬nXÅ’Õ£ÒÙ>Ü´_FTôi=o!‡˜|ƒÔ%(z©aÂÂüªÀ°ÆÅƵ²À†& Tª0‚ÐD’0,–ÕKÛñÎåW„©_Ï1÷î¦l8œÒÅPUTˆ€:ïMïX -˜r²“¹¨ ¤Ûˆ\%I°B©² ŠPÐü$PûÄ•+=@Ÿ>€’|ÖPø¾hx$<º{°#‡Í½íÖÖÒž” ¶JP·g¡m&÷ËI 4  ±~mÐC\ Vªdá(µÃz¥2(ˆlÛŒ¶Ò ˆaÍlÌìšôÖú_ éö;fR”[xeP®¥ß6´Ã0Ì»¡l¸âh©­LªiØ’4¥Å¦ f‹$Î-PÖquu`tH(aSÙ-PSŒÞTÒµ˜Ô 5˜)¤ž>\ÃÍ“D«"Xê|ÿøíã*YU¶*[bBVH÷„ž¤’(H¨¬‚,Uƒ†*T„P7ÆCíVH¬$da³†”š±Xç‡'œn5À¹±mž€ò, Aü}Í‘ÃÅVuÑHp[3/ÊÓØ$„ PçFŽÖn°ª¡>V¥zßÝúÚŸG©î¿Kó»ïìÿ˜útx¸ÿ‰M¦ÂÄRsƒË#?ýí^?ý8/&Ðú«`ðô·Ä]‰ÆB~Q-e•^ÁôyÎÏ9!E×öÚ_ƒ¤Æ y?Í’w=Nb‰º‰B¢u» €|o—ªŸÜñ±µš”T¾tzÊÁc=5O“¸YØüoÈæü?q¤Zu*×e 1û¨güÍ,è‘õªÉ¾ãóßèv)·O¿ñE7Çñ8ôÿƒöøT¤¿&ÁŽ8¸60Íê®ÕĩÆ\ZÛ<ÉûúÚÚý$«{ßEv±$S|´hHè$‰$ ªI6ɱߤïBXXn¤VÅ«s ûe ¥ÆÏÌ™w_‡ñUð@Eb¦.9õ¸C6÷ßïS´ñÿ›ˆÿ¦Û^hI$?k?“áMº»dô½_&ò&Má“e@€ÒÕŽV mMéaýÙd[ªJIDĈ(Q'é%Dy(V¡ÁlL®W*w|7]… òb å€HÛ5 6ŒˆÝu#ÁÂøá@ë´#`Ò®¤'”!÷ O ÕÁóüƒÔ\Šn*ªª¨Áòê €O”ôùDQ÷g°>?èx=ê‚‘`bTQej +X) ª~úyáW×'žb¯6ˆ{ ÛûÉâ!åR8Û‡}^+Ë"ȲàBR ÀTp4­Œææàß `ÂlTUyŸsßtÿùâtèŠù‹d-¾Ó1«zA1øTͶÕõŸø‰S瞦~¡Æ§…ŒôÈäaKTBaT.Ú뤑¼”ÂlB‚F$Ûs&wG !6b»%U²–µÎXÂ;ñÖHg+G`–‰ ";ª¶g“÷›Sª` ì¢H8 `~xz·}…¶¢”öNd'×ì§w1¤{é½Ïµ!ÐÀиz7ñð¥)ÈsÛ—d?‘O@dØXò4õUÁD`GQ†6“á"«ë½SÂXl}r»²3~Ò±€C'šyç§«P1D}v4)ü½²,,ˆ© YJ ‘£çò>뎩Äá’Þâ­ œ‹š©Ÿªü Rš:ÏØ?Ô·G«Ö¬{¸Ò y½7Åä!!!¿¸á®Àô^Ȩ㺜¡±§Y3˜dÖë5 ¯¼Œ^# úgÞH²/T©Dÿ2¬çà'¾çåùo'ú;kú|Έu&ˆá7ùå„4N¯š§Ñk¾WiÕü>Ç8‘ÿ ÙÂIéxr{àOàu0ÝDÄœô;÷0yq‚XÌEˆ ÅŠ,2 ‚ $ˆD=sÁ—ÏZó0“ ·—p´H\2&¥’D"àð¯ÉüâØöÄ!ãÄâ@b¨¤éò˜´VÈÞ=æÐóŠdÉÈÊÊ'ôJ‰ÆÑD$L…ž$@ÀËaeºaFd5™2­µ[-”A~] ûýlسƒ,ŦL’fQ µÆÒÁ„L) ™½O? !C‘×xQçK—Ó½ÎW0HBeF¡LU‰ Š6‡ÉD)å÷súŽùÇëÑ^c-•bQè~šêh§ÑÉøÜj â¨KÏçÅr¹ˆ_»öF†¥ët!¨+$ˆ­S|5‘ãé,Lq}µÍq¸zŸ%XÖææÏIÅ÷4w£º žœCÁÇq<-LPyíšš¡ž„Ayn¢©ÈhÜ]K²C«š™@A„ˆ®Š, ú5`ìÑ¿hjB yøú\?]Ké%1ÒÜG>5 [M’€Ñ 8 SÛ†¸M¢eÕóÒUâ\šÈþ`˜ËÓ4oÛÖ@‹•çÕ ¥x1ŒÆŠGP«Ä…¡~Ëá `i‡@©#º(,–¥,Q”€”AU´´µ-Š –˜b1-¸9yO8‚e8F½K0 Ÿë˜‡aé“­Ji'„}½ÃLØy…úØy–LØŽØŒOMûY›³t˜Ëy<ÄHÍ¡<" ‡-ÀT›ÀuLp!l-BØ‘jõHÛíÉ"aÞbÙñ@„öÍx/CÈàÃóþPù ÷ûM‰ÎŠC k!A!P“i4ï$L"TŒ–H ;ˆ­­±Ä•/Ó®3”æXÓ3v$›°b4,¢7…¹ 5’È4±B5kE)b²°1ŒT>Éâáó%xÂ!ñƯ3 S‚“ì¼–zOI¢1Ä:Bå‡nD.aP #brqíÍ =M?‰Þxz#ÁÞóåD“Ä'hÃîWþš‹¸¸ÝßÏšœZ쎰”î¨ëf‡Ó9]|ñ°Å7»{çtl;ìÿJF¥6à9€p‡,j+£ç|i€eø:¼%›LÖ(™.èì]%¨;ÝçýØèˆÎ:U;2x8žW@à$N ÐÁÒB°U'‹N-F Ý«˜”âÔ‘âGJ›þ ɶÐJ‘%,„–Ç­À„8Þ›ü×FŠÆ:KƒQLVÌň!ÝJÅ’ALiZH÷RŠŠ(¤^áîÃ¥Í"©ˆ $zs“!Óo)Ë‘­Ð@›ƒÊJ ]®*j9¢†¤H ¨0¢‚Æ"º°â”“%Š÷¥.¥Ù@ÿÃþçŽc ¤ï˜ÀSíh™D#ø¨ßM ¹þ7ÂæûÌqÒ…Š¬ëƒ ER$/ösóŒ'·š÷ ŠôV{Äë£2|3Öz¥«7deâ-¢` ¶…9L“["ˆ5\sA?¼ L¦iÌ¡{2C$ºÁ—,ŽÒ„':Î;T±I]cmUª;¶.†H$GƒÏú×"!èúÌŽ2ô3(üŽóü‡Gg %ÇÖ²þT0c)0—®Òdddd$5f·³gGÍÜ!ŸˆÆäahJ•(±MªÒ³W›pŸËóøs@8÷O2æÌHÒ£ŒÓÊÌ-‹8KÌâ•Df¤¸4r‡Ôû#¾Rk¾.°ÙŒ Hvå®6D‡Ðµe©ÄZ«bÕ•R1!ôÕÕR;xúËDI4ñò‘{%È{KI ÷fGzëªor`t'pÈ Õ!÷ ƒÃ&í‡wyHphoq¨Dx¥³÷/x™CryŒ¸(>Ü”ü „LEÕC•Bgl]|[õ»æ~¿Žü_Š2|f1ê/4ò·ÿ¿sæGByUUGc‚÷´­–ÂH.„Q•Èâ2 ¦§¨ÜÖá¸Ä"4~?ÀÖÓ±¾3A©ùŒ\ªd„މ6cy›;hXÄn/,›IMÄiGÁ‘s¡š&Ð `%„ßf•Q¼7K¸_H³åU:Úц¾.ØzQ°çt|¨¶XÇñ!íó§²Dßn½ˆ¤¥)¶Š ãÒøþ/É™ œ –n­;”_¬õ@¶ F¯æcÛk£L=<-W@¸ðCÃ;кÚPH²ëûU¯ÑH)ðU^Q2ÍLG˜ÿAà’.{ËŠ.œ& ¹A¯7“*ü¼~ägQМp|æoð}Ÿû?Çþÿâÿ;ùØýx鵑M¼vþDZQ’Ï™yøp¯"N3æ„IÃïEû ‹ ¦1¡z°N1±’¶K„f•I2ÍUG™¢ÖEä~n N;øÀçVâ…Cµ’Κà×0u!Îñ8ëry iQÚyéìõì7­µuq·)‚qÆ}Mê(wõêÚ~¹:²½µŠÄ ´Q°%[ã¤RXJZt°ëF›2lØ·õë [F¢ QwE¢îŇ\m‚‚—ÉÓUqL M'‡Nüœjv‚ =2Ž©ÐŒ;Ý".ÖL,âñeRNJ¼n†¶XBª\˜«m.‰ô†ÂÇÎÎz\EÏ=S›aÚ+êqߣGu‡)8CwKÎ÷©»ÜÞl<ñDz·qN<.©G:™ c&¼û÷Žçu¼êG${èwñçL‡w‰'¬½/L%„‰Þ&*ª‚:–T.ÆËUâ!E$£)]}< ˆ‰Ó¨Þ¼ö£”C!12~¨†„å£{ðÏ‚ZâÄÝ¢èúîQô)m(ªG>d˜¶DÀº3Tí?zZ“"¥#³6Ö@¤`\¶²Î]åC‰ Wl”âïqbŠä"PCç8ášâ†'n¨ñN#pÖõìu$ ˆ¡ð¾y^ãÀ?f €Ëd*€ †Ø‹YÂW"tK0‘`€Â_>gÜœùÎg5 F˜åËv ü<‘DF1d‹@T^…ø/žòoØÚÛ œk©1ú Mí¯!Ûë94@qª° œ›Œ‹h›zMlCQa[²(^Iª¹@¼5 «t™é€(ŠŠÔ;ùƒ±5ͳè'‡ŠLÙ7]ëÆâ¡u £²M7,(À…¤-Py:h}B‰ø$2»ó}3G2%™þl{±²8R¢\Å­ ,ˆ%ĉUµ#3 ìx.EB¡s-·CL|~·‡|€Œ„L"U±UÞ½ôCWö¿ñŸüò½ùòoˆÌîÍÎÃòçÀÎ! âx½Pôf8{ÞÕÃcÔR«. çajDžă²˜Š¢#RU€79Õœ0É© +•<'{9ññ§²˜¶Å”*¥–X¡A ¨ˆŠˆ€Ne` Qù©)<ãÈiÖ«Z dÏß(hb5Mù#!$[”ÎCŠúÀcŠªƒ1Mƒ§:T@xöVVeæËbºC‰QÄÞãƒd÷x^ytëF±¨Í’R/à«I®ÝМœmć·( Æ{%„ÙoŽ‚^ÅEÄDtM À€å›oJµ¢ÈôÒWŠœÀ˜/ÆÍô°I£D}d“3ê•‹R>•ž×À±„ä4S]»îf¸/ Ñ÷Ó“€§Bçbx¿ÉlxÈù4'æØo.¹@è1Ìq"bœ6èW²¥×ÎØ1“Â9MI,*¨:Ôшœ5êwߨGƒIWÈXÁ!è‚ ©cO½þj¢l…¬ˆ" –4îïÖüŸ -¡^yÒ* „BˆLKoÆOëjÒ»lá¢+ó¨\´nO(ÁR%œÍàf¨ª…í}D°©[Åa ¥èéf(üßê÷³em{®ð’"jC‰ zl8òg†ŽÜ$„U†|ö½õ$A^ý3àßoJ¶]`vžÉ6ƒ¾\ñî>*‹Eª îK$*“«M<¾5~=À„;‘ó=w½GⲪ1" ó $EA'qú_]®—p!¹5„Ç7Üvã!(¢Å’×°M(!":ÈnVàÎKŒå°M+a™›I6¦)-¹:9CH—ˆtS`ÚíŒÆÆxÑ ‘«1k`ŠQ¼`9ØS\†’íÕ ¼sÑân5×…š¡ˆÚÚî,¢:© |ç=f ½ê fºà! ‘£_h‰­©~r“òJ¥ î¿+çmøì5‰]5Ön¨D„ «÷ëJ/¦‚úo¡*À€Æ È" б°YŠ*Á‹ ‰á»$Û CTÍIsU„üEb‘ÅCW•Õ!ˆþcqŽ™@P*B¦Zj …¤U”Œ†ã†(,!”¥@ŠD’Ú«$ªÈ²¡FJ2I£(AnQÐrȲ’HORDø=øë.(ÔŸ·Üð ×ôØÜöÍÖ-ÐõºxJs¹ÌX¦Ì¿Y}û>x~ï–œˆ=ÚqPüü>ƒ´YÙ¡GÚ²ÚÀ€ÑˆöüO_¹T»ÎyÎãÚCißig.jî[ðø¸ÏwÁzîØv`Ã~è–íüàvÚÂÔ#‰wC$8Ù¸Åä¢U±&TÅUžGØŒ:;Á•T! dÒOqOÑé)ÄF!LIùϺ}[ÕWgôó BŸ®©m²0ÌLä:,Äçøæ2¢IUûšfDÑQ‰„åkZ>fÇåOºWå2žœ~×ÏÆ'­$Óó2±Ë†ŠŠo Ú!¶†(uNHoLµ<ìà.õùÆyk’â íºI$Û$ÆCŠ,Š@ľÏԹ׌xîÏ^úOàTp®qdуz{jså„¿ý6}3DsÒâq_øN™f´„ш®‘Û– ퟿ٴH.« J1ÁXBü´’T€?HŒZ`€0ÞocG/qCÓéݘá±(LDyz¡À]P!! ÍÚ½¼Ï¡êˆsLž;½¥SYŸkÉ %-ÜŽÞ~ö…2¥|ŒWõ39$2¯2£+ÐÜ ëóW×)qƒ•ó2W hŒet`Ëú ~×Nðy˜¯;¥ÖìùÛ„@ë7t."+¤š`2! ?^Â`®ïTgþð1è°{ë PÃU%Aô<”4#Ôe¥¢îÿ›Ã†6ÀjA;"0&Ð@c1ÈÉUD žæŠ ×ÊÂd‡~Û¤>&zÓè;¨ zð¡¤6Ãéeœ àŠZ} ¶\˜„­ñÚ†-”öÙG·áþRü½ÏÞô÷s;ƒsʨ*ç“:T*ªU2D•©R¶„=ðûãì&Ò¤Ÿî÷²?xh²ŸB•gdÑü\Ò¿ˆý.ÞvÚ§Ô|ØeRDV¡ 誅¤-F–¼š”Ô^ ¨†äà@å.--¨R%¢ðÓ•Ç X8öžïÀÑñöÄ4…aQhÐø©=ݑנ½q9™è&ñŸ€¿ÉlÔÐÎÅîåHþ3qáîF8€z èfj OÆ’Òã=ìýïÇa d†ØT訅ˆ@_YX"ˆ·ŒÒû4%‡È=äôœÏa$¼0ðBô¥´•Ñe|…š´ŠGHçSÇ1:ëKž&sq6Ôe¯®ã (ž†ƒ {bF úîŒ`Œr3iP¿ÛS¾&µGºO$Ÿ¢Gå²LXvCBH—÷D„ÂDh¾ ±#!`{ŽýWNCø½OèúOìá=·÷}¤Î_‡Bˆß­{ã÷ò½†>H«‚ňeíjhRÞÊ;?3«tIŽ2œtaA»ÀE;Z;ÍŒ¦8 ƾ8þÃêŒè”´b>-a2ßÞÖþ ÖS#1„¼0ÀH1„鬃‚V@b  ¨ÀT‚Í4AÕ’Ÿº¤¢‚)Œ…r)Pýn®ÖÁ¿ñçAÅ\^Q€£ $]³L{8é |ìZÝc4ö©Z• â»(OÔ¸@l†wÈò¹Ÿì½.#»ó¹Ïu¢‡ôî®oõ¬|¾ë§û<×tãÔ’0#'ðü|šæÜ£â=”5-Ä›r¬È;  ÖPK‰º £s¾€ùNË8Ê#Ù—Ž=?=Œ8ÓöUl%©*¢Z-K,…«BŒU‘‚’(dHŒ€°XV,в*ȨÉ"0R ŒP‚€,VE€  *ȱ`((Å)’-E¥²Y-’‰çž‚£:Òyb¯¼‚dI "ÏȽ\[b­X7Þ}žu­Š„E‡rI &¨6k.X¸Y׉{€ë"F$ ;‹pUß#`èÁ,µí÷¦±‰ÇOŽºíP?_ú<ûó=@‡­ÎèwC¼¢ˆvÞá"3`„ü¢ ü"€€S¦ÐW86ý­o»~š7WÎ|”_¨»EO«ôù•)}<½RD»®úõK®ºB,ÿ<Àf%ººÿd'¿'Œšj¤ÌLYò)âý#Z+ùżÎ0îJ,7_ ZkäôY+õÎÂz0ö+2=5‡vAü¢y$½y¬,"’v/—G/.‚å°éô@'áðC€€]Ð<5hupâ"¶ñå´ÝQý$zÿ}}ˇïÖÓïb9VB{÷Þ%áV*&e·äí{M3Ï™‘ãFû ʃMÃëpðJÉÛ˜þLÝãO–"ú¯U?Éøðíܼ±ãpúväkád[Ž£´Ý—î´9eÇzãÚúý3àOb ¦ëR³âHT6y<ßk›6ÿÙiâóµn»>I)¬ü\¸aø~Óˆ-~+RÁ”'‰·‡«ËŒû€¯÷¾îšéðZ¹ ¾K6öû¯¢ë±à±¿2i;ó‚µ€86PÉ»8€§Ån+\È4ŒG‡¸`‰‹ÊY U@¡é Æè£@LÄg¿ÿ?Óö‘ ;$ÎÀd‰hÐÌ)ó¤A” `B£¨NÝÅ%ã¦:!9˜ÓP€¾êÉVHÈH@I …¼qöª_¿Âåa17(«lUc„D÷ùrò¤“wîý5:‰üŸ;êj‰NŒ»*¯ž!ÀÓŒ¸]S1Ûb\Ýçs0¢TÃð;ïI™ôõ´xÌj]i¢bXg+=n[éqL‰¨)?¾Œ€² (±ˆL!ÎÅO)î± èœY”W:Þ4$ ©®ÀÁ b‚ç§P/°Ýž·B ¿’®ÎmÁ»©fÂ[È()'ï~0Fx°XˆÆ,в,“L¨ó}©Ç‘bK´üeóVÇE4¡µ´(œ‹£¢è|ˆ› Ö4ðŒ†6¦ðèd6„’B*~¬? ²!¸¢x,Q$Ü”|!.¢‚$vYõÁÁŽYX¡P©Fƃ-…MµEƒIÁ`DÊÝ<0ö%Z¨žü¸† •ÇH:½4}(}ÒCìëÚ>zFûË<çÖE¶È´I89åÊ0¡c™îú_ñ ïÀê†ß­w& @@ah”ˆ7¨˜"!£Á&vdEŠ9ê™QÒOo¯R|þ# _A‚z{ÐD3µ‰Ò5ixSn¡ K»“O„Í´äŠÌµIµ„ o!K­ˆ­LÎU.^ÿl;mJR«Iñ{î«m.¡3±C's¼ÚÄmŸ…ªŒ;ÃåOZIÓåCÖÉUU;ÊÚÐé캈Áb" sQê²E² ,‡¾“ÛV¥°Ïç(/‚çh-•hÎ"fa‰¼wÑ$Déíl F -2Yµª)(C3Q%Wf*5! Í6$nk‡ôœWÉÿ¯o›Õpÿƒðî×–z›h|wíÍ5×Ýà ŽRá´MEô—B&ý1„õÈ@ ;µ´{ T,tùÎ|fuÿC|—g+,ù¸"\IÖÁéÕê¸ôÆ'`|ûDÀOÀÚ"1¸¥ð@Xc„RT÷Òšìó-[À¬”z©•˜ô$`Š‘À8I6óí.ÄÁh‹€œœÀ‰÷¶Qˆ¤ôÿJ@ŸƒôtŠ.+P¡ŠºÄ99?Ú³û?Éÿ7?#`t:ˆˆ0r9™|Ó‚ÒRRQ†hñ üa†®Ý$öÒ9{ V a3k~½ƒM­H]9æßA%EvóüéÝ$¸˜]3Òڒ⩉)2.ð9µ=Bî„»÷ôËÔ¤Ê2þ“€Úp~V÷>sq“!QH?æ&äT÷ÿç_ƒGww?¡Wšª!“Á-ÊUøü„:ë²Cû²8@D?ÐùÎâôïÎß¶ú›Ñ^;f*©¡ŸC±umhÓ¹”]*](˜5m}/½××þoòÿ3+Ÿ•ô¿ë_‘—} ;\o~ :]ôª‡¹;ê±*ê–p=²6ŽÓ} ®.<\åú4\b—ÆS~(í”öÀvϽ¸ÑhªIŠI$ò¾ÆÒìû'ïøž(®ðD¨é’;ã Ö²9XÐÒ eÐY†MfKeÀ¶èɃÂi]Ù¨çëhc0»çDÃH‚*{hÆ­Ä‚ŠÀJH Ÿ~òö°*;ÃÊêjI$v‘©&ˆÐWHsÚ §²±kûÿ¨ë»>ªH>H“ un'I=s±î¯ÊbÅW>K×Ê9ˆ'`=ì00S”#eYh²5K´©PmµU$J øûqÇhq&¿B9ÜS Œ4’-=˜ïz·­03ÂÓ¬çüF"¬R T„RIR À"2Eïë磄Þ[Ðnˆã=)æbYU_ˆ´Srt! 5ðõdC€áWà2‚"“âñ¡AÅî´ˆ³÷UX/5¢z½®W†¤F@ÑùôiŠmA`‚ÙBŒ)ZÛ+RÒ‚€ŒYV”ªO¨|Ã/öE°Ú~˜©ïÉ9uë‡`ŠCgÏ"¦tZ‰$€ý«tL4 %U/ÎXO•†Ñ ²c7{×áæçMÒÚgFp'ÆM„p…×vÖæñ½…RZvši³Âe\V˜¦Žc2΀‚${ÌÓ &òYXU?¨ø‘EHý ªm›ç®¬W×-à Xyûý‰¹!q„¡MÐ%å¢ñld?Xø˜3æ½3£3Ÿq?ç 8)!ô§ *±pYªª«zíQbž¶ªªúŽüÌ”,°©Ê±I¤@ì–•" 6šgxœu^uÎãlŠ5#d'Þñ;RÑÍ÷!k¶ŠžHP&d"ã!„ÝRZ⛄Âá×l bÙ”Ö@ %³îBö"§Çê¨.¢A>ë/ù|1 ÏDuPÍC¥ýAI²³/¶M"Lr“¼˜ \Bpä‰4b!‘€šÝa˜äçtPabÍÎ$‘øŸs÷?úž…E¤\xénœãÑ&tÍ£r·©Ýp\½rë)î]ÎD¯GÞÍ0vgô )Jbêô?(¨ýŒ5 x„g° Ž!c2/U€ °qêP/:´ÒÖF×HO?ü‘þ‡ýß•ýŸÉþõÿsýÛç–h(âí}"4O›)Cl‰€8è¿Ó)Ûâ ¾"e!µUøT“ú&@ˆ‹šG€ ´EÅ@ŒÄסýgò:õG=zâé‹Å]á`ÍhAÕûAø¿ÞÿW<½û{[îÎø¥ ©n¹ÑPóãöÿíOwòèƒQ} «†‚¯c:m•±c„†~s3QPÝd¸?s·dîü¾uÍ÷ÿ†R×\`Á`·…è}¿wýýÏ%±³ggçíô9ÈŹÚ·§ËÝóž9Áòij«¦™C+ÓI¹Æ¶C‚-ˆòA€:ЭÝzëEF\Íñ±¤‚Bµ&óxû¬þŸ˜ “þ[ïf0) HÈú dj=Ѥ\^gïô»Òf0¿ùžòw•çí4…ÐW¢È4µÄÌ3-§ÑÞÄYýYÛ÷ 'ÿ^‘ˆ°³»¬ñõÝJ’Ÿ°¬û‡%[%H«$,– dG×"?+æ ž‚q‚ ñË@sDŒ ˜éðI"gQ\0L2ÆLs¢ˆHw·f·¢–«®¹0žŽ?ä!ؤD häæf´ Ì4b謄 F0’@†„°18™°Í°˜Î§°ð L“Ü÷àµcZ@£lb(¾rl €­Ö倎rBLEH‚1e=’|á£Öü“T—ŒÉn8Q­LqË[L0£”X—ü¬ M5+˜#±„êAÞè¡ÇÜôSúè7ýOZÄ>Z RtØ\DHé°¨VCM› €J®fJ7E"3¯D‡'a.,º¬„wy ˜(c x2¨ƒqáh ’'¥wÚcPðX—mIç—1;”§!‡Í£¸òCœ8òH2³ßÝCàÕ‘áÛ FBûŒc[ëœk•J- _ tz¡]àˆŽX Üõ¾Ór~dLŽ3g@6 Dl4¨ðøÒ¢^S?ñ P†¬ð #A²ÙU’1‘gO*UWDÛ8 ±ø%aD£÷ćT(Íýå›MD"ðÏ{D©öǼ~hõ†~å«VÚž?7Y5v¬¯‘+ˆB&›“sbèæÈ¡Ëa\—–Íz7—z¢}mס1#Ú±Ìe•)ç0Æ,‚Ïš [’2A`Ìd:Ïãv@Ôw¤™ ~G‘ÇDèq£ì–ß· K(ˆºª·¶BXè#P¯‘©o'žwt¢2‡j ¨ÈÃ&~Ê„1ŽÐÄX-”OѧÜîõ“ÁTì¿_Ýÿ’GŽ„¯{cÓÕêFÀÌø~ÌÙ0žOQ ²©S¸ÓeA·ƒõn¢¯ÞïïÞ¹Q•6¯uFxP€|cißôažêv½o^~jšËC6 Ä!€ã7 @x 0ñÃØûú¹Ïý}…Ãæô=}g<އ¸jÂ7Pé–¨Aeª«ëkœMnQ31$Z…‚+ý›M5_jæï±6‚êqí5tºé@Ò©šej2°„˜ ó€3\ëYfÙƒ$xÖhXŠÉªRˆäË’¨LD´jRÓù¦åawb¹fÙ ØÙ·™#xµ“LR”XÎ0 dmâoìêb’~òã 7K°¨]çYˆ3RíÖÔ×V›Õ›-dÛ¤ëi?ì±a €¥¼ý0¥ ˜e¦êPd"9½¦…%ë/]…HnҮꅭªIŠª¨ˆ‡Êlþqÿêð@ªU‹S~ö}‡ýùeÿ¿ÝmïëŠõ]-·Åtç4¿ºýNõÐà… <ØtFwØ'VFÔ^%])ÉD‘†Q ›yÿ®éÿ/ôùŒu•Q Y§FóK=²_c¥Ó*à’¡y}#·¼é‚Í¢2œñÉšT+615eI8å¦UÈ8d’jäTD[õ0‚EØÏùñ«VŽÛðxË!ÅeËù:¦A.»ôºwƒ\zðÈ¿½É`p†Ô}\³KK‚ãœýî/ˆ¼1†!M 4T©TUF¥Q––KB˜MÑE•=vQ5Qšš’IŒæñ5/‹!"¤X(1XŒtç‘üé÷§‹ËzµtßฌyP·òÓÊOçÖ3¯ £ŠžR¦Ý†'‘¾w¿à$’B:u5µV~# hñJ)ý3{„<ÜÐ,{M °X/u° L…9ÙÀ(ì ¦¯³±Û“[®“¦ÍkªÁjòåÚIÖÅrDz!ÃÀ(É$n „ H~[tKŒ•P$˜2m$¬ h°Y­ŒQ¦k?ýö°Ã/¤²pdË (!:õ¦¶m-“ ‡LÐß– H%‰"DIgvnÎ&›GŽ'¨Ö´“vÓvêĤP²B68£X$i (‹*J X(DTVBF@”§.Y, d€ñW§¨Á‹$ çzàU–•…8!à¢qu\6Ú­&q˜@p„áÒ­ƒ1 |/ÕqQ-umnH jÈ âÎmªš?+¶ÃZîÃp²æ³ù*yX‹TPÇ”ðO¢Vˆßƒ=j‚¬¨ *EhÍHKQ‹ ,Iª*¢Ø†H–HÍ‘ÂØÒÅ¡¢Éš„‰$ˆLÁî\«M&š¬”щ,*–É–áøÛ9à„RBŽÞÞéœÈLO[%k zÎÅŸ¶d%˜0¥jÒd&vÔ#›Ê–¥,«sò3•°Ô‡ËƒÓÏó9Ÿ8å™w,Ìs‹"ý“'¨š~¼ìÚ¶‰]NèHž+,ŠÈ€³µ¢•+AŒTe–’ÊŒÀN>40Á$“¼`¬¬Àm"Ër‰˜‹l2,>®gÁ¶Êªª‹;éVuµSsú¼)•C* Æ.ÆTé$H|Bb Rè¶M2ö>I©s¤xoíÝÉ&pk±ÜO£ý¯*êZQ*/n`#“í? $@#2q pߪ¡¶]fE†n¬e¬ ž•"7uaj[&•± Ù"‰BÉ×Znf{uXÅÔk|#ÊÉ*¤˜L ˜¤42Œ<ºlÑ>ZlƒÂÚÚØ¥hlQ°¨Û V ¨Áj*¶B¤F0¨@”¶Œ€D¶ŠÈJ$$ª‘Aeaˆ  Ë2¢â&c”IXNz]ɶR°O©“ 9Ä(ÙˆFàˆk Tê2’0Mi§Í6LH<62l„VA5r2´/ŒîI¦îe–ZÃA¬…Å©XŒ€Kl€JÁa–D)JDd€F©h6•)&<„«®p‘7?Ïr¢‰ch˜‘Å$ƒ<¬ÿÆÂb*1V,‚Ê”Qî oÜ™“¯Ízd·0ôXU¥YOÂù¯në„4°a„)Dh„‚>EDoô_KÖý,~74½ƒ;ûû¹ÝU·™0-ë붺ÍùñÏ®–Q«±TåºÉ1yêé ƒ†HáÀ!ÞéOAÓûm…ÃènÃÒ@„å(d`–…Ð0Obð’*¹¦ÎRœÃ¦·s‘C£!¶ŸÊÙÉBèoR*$ÎMæ•ýÑ’,P*ì;$¼ Y™¿<©aáú×=x2ag…H!TÀÄ)ù¿ÜÿǪ $6 ¥¡fо¹üïà}•ø¾åCOÈŸîû?øÿç£é>7wÅr[]Ú–Àø„t†Çí`QûÅ•8L&³×&ÄBU%0BI–n,–Nà€N§wWY!( ‚"Æ «Gß)ÌØ'“Ðê9ÞØe!žc$X@„ùîa‡žJq&­$,ïÌ÷—F@æËU°RR•ªcl!"Ä@F@` Q#"E‚"¢,¼pÁ„‘^/@БL`ñlXFrƒÓÄU X ˆ²*²È¡ÌF¢‚°¬€VR,'Á‚¬$Y"pNœ’œ™¤"‘ùz÷&ºT(‹Âã¶³ª&¢7Ò\uF!Á”Sµ ãâÕ°d ˆ…X„!"¸±¢åË ¹J¥}2H_º´–hc.+_UM"b2:fáJ'’y|Rtótà©û÷±™,=%¨´H¢ÅE€‘BChE,Ic<`@òAV*É"ŠYY!jÚª´¡ô¤‘õ¬ŸZÂGYÞú[”¦oFɱ$Ù7¹ì÷O|6wÏ,ëÔöVÌP\È\F!‰¨C²ÏLŒ)lJ²ç1âNIň*ÄYc1–yP0?嘊hÁTR,crÈr˜š·êƒ<‡ûÄ6ÈZF©å¶!#U.fU8“8š…}|v®h¶"Iãö£Ê–’¥S€)‚•E|¼1Ø­¼nh°ÆBT† Ó!Á€Pe;€ÆSx¬#8H)"À$XÄç¨ÃdHvC¼°)èæJ[ø`_èÄ,ÉB •<°Ã4èÅàD“WY3écÀ‚o´“©÷ úÚõ¸¯âA “l!´[t*Às´!#åÝ¥"O€Ð` ­úéjL‰‚8‘e*Ú©‰L"ÛTS ‰h´ÄFWï`ùÞ§²Cêâ%ñ-éVÔˆÊ!b±(ÒÍ}ŸX0U‹&RÙK3ïrNã¼ ÷uëAdb ýÿà|ït¿å%úØd¤` ZÐŒaÈ>݆Ïá~´צ =‚…egÞ”û­ ±|¦¢"Ÿ/¤/ò‰ñ°¡BSÊîNÌá0Ó$$€£T_…u&l6ÌR9èDw|›2òðlDM¼x:72ØbŸY\…U‘.à2¯WÚïú? F&þ“jUqåá1,A- ŸJO1>ÛþŸ=¨ ƒ‚¼6ûÁâೇ»Š|gm'2}Úx{‡äVYJ@ùb(ÃêÅ1· Â’FüKŠ.´) ãA¦í<ïö¹¾ùþ÷“þþCàÿ×é`ˆÐ":¯ža"¹´Ú? ‹?È;¾Átð…XFEZ•6OÓ/yjiÈïÙSõݺoã=ãù_–íš%Í?ù½7Ñ{=¦Û¾ÐÏÒ)hÐ óÉÀ±wFäüÓÿfôôÝŒû§¯Mdt>¿ó´Ð"F‹AÿŸáæûžÇýú/‘ù?çœpº›³Ë¼¡ßÓ0šæ#Üiüͧvõ¥ÛÍ÷=r-‡eòŒä?#õXw#d¾GQÀ€ QrЇêØè<ÇåèWùÍÌ-³C8í¾–;ä9¯eæ:L{}מ kˆ  1àovó÷DÛR iT¶••Ÿ’1QO• І$DÊ‚a €Cš¸«gr08Q?MMJ(êÔr…)>U¬ïö{EkøýÞ´à_E•Hþ P± ®y Xö±ölfÿÆÙÿ2PÿÖc­Åù|>ÉwðQÎÖ2“Ql‡ùJ>7bíØyȰ#mÄÆYóˆeK‰hÜîÆÆ°ñdBŸFd¡$à¦Sƒ)wÐ.ð<ÅQ:‘âA<úõ&¾ü¼9ë1‡Œ¯{“|°p ²$XA‘‘ˆ‹u¯aB['²ƒÜÚí¶5dõÏJÍw®e>«Æa]ÉÊ•ësäWZUTêÿ[æy'Ðê|ë”=r?’¿Œò$ÛÉñgÁ¡Òrbc *ä걌6ZANÊ!±‰0ê&E``Š¢gDäéB`š©Û"Ð&“‰;Ó\ic3CMUè²ãT'“L™±«æÉ"Œö'ÄÏ]½Ö‡Î0Ý.ȰX{ YúͬRyàvôzçÏçÝÑÇ3NpŠñ¹²s½"À§•ÈÈŠ'á²C½!÷RF!75`¿GROt'tYGÙ”P,¥?àëÄ'®HÒØhàaè¯Íîã#} †Ð-±žWõ܆a˜ü•!‚C*¢yeqB8zU×áxHGÌDP=ù>ä‹=ÕiõjX°¼`gÄÂ,ŠC`¿8’A‰™à{ÑÌ]XC9´øé.5*tL÷Þõfذ‡vìêÈNOˆdÚz»–œ&0¦þcÝb eYõD+ˆJÉ´HÇ$2í'°ç´ú>«# •D ÂHËý>þc'£'£T` ´aEŒp€ôz§>59¥-Ó/gP9˜˜äóÏÚ þ¹†3^zÒZŠ•Ú?ùh•ó›îŽK5˜Ö•e+Þ4]Iˆ@À ]b+F)÷¦%P#( ø7ñáì—ö^=ÉD€Oòã^±yUýõ {§±^tZÖí`:r8êaw+û¬÷œJd°uäIó¿¤ 7`’ð;2¬§cN 0„LLDP0Â0Ãv<ÈGãðúo‡|í{þö-OÕïpÀ­ A¯“•w«PgÙ‘ó,}ç÷þ"îG³u 4›#ÿ‘ûßH¼˜þ·6:`ø§9ÍÔ$H0êc]Ì/íõŸÛz€k MC¹£ba¢d1‘ËLÊ@%HÆ› 0Ÿ©w‰ýîØþbt7H‚ñ$$‘l¢Æ °XY)R‰Eñ-X1b ”¤±¢­ˆ"y6&RšaX8•€«¦™”Ȫ,V+0@%iA bbˆ±dCIX"²PtK͸ LµÝ.÷˜0T#ŠŠˆo.!D©e¤«Ŧ+Ü]& ¸\B\Ê9Lpcÿ¯Fµxy5?ÉpjˆU n]sÅïñüÙý¯pEÄ:&õ{M4;ߢ»E0W©ÃìKôá| úÿÕW]I´·ÎÍuæ•ôÚѵ†Ôý|& {õëK¢Õ3é\Û|ïó)ŸÓò9b§ó}Ú±ßS‹ï߈†néâëRÑ-ÈãPiŽ|wXjæ([JÕAÒ\”RÒÙ¡\tÖ'ìé7 5ª4 ‰$HìÀ.EH‘>Ïòb0„!¨†- ™r› ,¢N€™Á¥'b›ï ¾S?6:)Õ &L™ÿ<ÄH ŠŠ¤q¿³ÙúK –'V"…Ã5 º¦Á)cªd?Ýù„Ú±M¡U„`ÉùVù²Vk 8®À|â@4tp7ô *êî3²ãÈHÆ#Š0ˆ!Ù¨EX:IÕ¦IÈÊG˜Ä˜T¼ö4wÄ•Ø$õ¤%ó ef0öZE9—€ÀDq#> R|ÐÛdK»ú¹ó9,H˜Ã ŸÛ4™š¶‡Tž@BIž‹³Ÿ€ÀuÂ"ª**£F*¢Š¨ªª¬UD$•PõÎäm¯í;a~/ÔNÞ0‰¥»³0AOµbªŠK$‹åb 2 (½ÁJñ†RÈ`Ú-2Ó\f Že©BHË–‡4œ“ ÉY][Š}œ0ÍO³sÓÃ~š¸Ö´¯W‰Ûè£N˜˜~K‡’϶ý¤ù!™ª¦ž„O0€"š(¢út’îc ]¦Ä² »»ˆpü0¼Ná¬ñ)ïâzã1ò‡ÑÙ"Ò‚¬¢(¿À²BOVHÕù@o!uVÜLèUy}çTÓ4ÆÆÚSÌ%øÆa$÷œ¹I?3D¹¿#sõ<>:ú¯€#ÓDýáÐè†"TR£gIèJ€®¢*ˆ¹tb@)ÒÄç?™¢BŒ¤mƒÃue…Ù³”Ñ"…Ô‚2 ‚lâû‹®Ã¶/-t‚QñËikÛSbžè{iÌ}/4!ê=Ü™>Ÿf÷ŒÕ£ÈY¶‹ H"ðY/.!qˆ· l.Ǥa·Î ±1XñÄÓ@sˈ¥eãïwpoTh®¥áˆ\G}Gp¥H!("·¤Møá¢ÅQ£D¢PX¢4Y-‹9ƒÁú/K]{P'*<"‰Ø^nl(å 4ÔŒÚÙ­V“¦…®¦ª’Éq`îëÜ.ª™ýƵ“„²‚Zàí“h`e*6ÉDÁI”Ð$ÌBƒ¬+=m »eØ–Æ–fÌ LFÙ,µæU4… Êvóç41…œ &#ñçaİŠú—wAæe˜/-“U¦?PãË' –âXXtæ•è&ÍSc>ü¾Ø„b¨lJ‚’–Û)%>NÁ!:lw=Y FPôEˆBÏ œ:bvö`€Ð¦ïBC‘Gue•¿ŸÁ zÆhU‚¤„²¥sE°‹¬CÄ"0`²Œ¬™sÀöîf¤–ȃ’adÝ’acmî&HÓ ý2a Dw@èìÍØŒ $XŠÁŒa‘! cèXŠ˜4°¨Y#ç‚?©‚è˜L$HJsÐâ`›òcÉ‘ ì"Ä/q¼¸}6aë±ßÓÂu-†NӜϿ=‘þÇ€åÕP‚ɪeZ W›ˆÓ·–•`|é¼Pûò7§XNóS Ê‹¶ˆÒ¬a»E#)A,¶# PiFg&€ƒÚRÔ¥$J1”FR:x n )(¦ °nZÔ´€º§|Ò¦rnå"G ŒU‘dƦ!@+v…²j Ò’H¼ Š£D Í:ÔÌ #I$.µ¬ZZÍ6K6DÝ«ØzÿûÿÛý?­Ì~Ÿèþ¦ýckÃß›eû8QÕ~ñhÒˆx9ÌÑyŸŸ/FÖù#|©þ¾Éà4BX¡ë(@þ>Ÿæÿ§ó¾_Äøÿ­óâ|e„Idã}Gûi_•õ+o~Í50‹z$ÿKl¥ kÔûþœc<ßm-úØ“£ùAçôVìUØ‹ªâìþ'Åöß'Äæ¾‡Åæõ²£¯GDÖî&iÓ³¾°J"| †:â^8ÙÓZÁ·˜ˆÅDUQÞï·EéÛz’ôب¿ézLÔ¨‰ÕŸ\øûœNㄠ¯|P½Š_’‡ãy=ùdQ*ŸÏ!Õ5í{òZXQ²–8»Ìf™¬‰Â\ððÃ]«ÞQ5Ò=´N0ж˜u¿Ÿ¬ ¿Yïæ3ë;„#ÜD+ô’u3¥ZǤ<•“Ɖ†¹nÍ‘ñèe“NãÏ_Òä€4‹âõõêbjy!Ü‹àž€õ|Ðè:I˜0Áá£Û˜áãsQ4/u==7ÚèMõ<Ô‹¼ï¨Zðä…+ˆ``IÂ*ýýq—î†™Ò LL„@‚Úpÿ&˜:}/¡ÓF¸½÷Fw8:´{»Ñ=5]ß<g¡®»-MæÌåß2éVNç¸Êš<÷œwà6:ТÆ( ©¡&&~Ô&j¦f¦]ÌÇIWdŠT®gÛBY_c BUz `Ø=Q>}fÌ‚xý¹} @]Ú‰< 1é|¡ôhÆ(oà¢ICëPʦ%Y@¹ïÞƒJÄX‹«´ê%f‹ás²î‹-Î…T,³fÚrXGŸ  G"hXú‰ K*3ôÁᯂà@ûÓ“p¶F}yΈ3*El<%oò!u¬làõL[°È«ú– Ó a'¥*ÒI l­¥aÑ'‚]J«ŽœtfMS5ä»&²ŒÓ+Ú‡nÝ»k‡¥*ÒI l­¥aÑ'dº•W8èÌš¦k²ô iyx÷WÚ–ãð)1ö\[¤M͘cžöPæŽ<÷6".f‚?3fgÇ|éëý¯îÿ¬ÏÐÃP𠮨¢Ìyà¶ÈŽÚŸVHg8fÌ+"@EÂõÇÛøãZ¢u±è™U.#ñ²I9ÿ,~ÿôþ>žçÿ¦Fm‹2j§(È$¤UÔ¹³ ïC²T}îÏf…š²V(¼.ÃÎFäíßÿ>vLuk`œíœâæÔaæ%_KÔÍç±ß›6fôæ NiÉœfòi­/vsÝx&²êÓÔ@'æø_èu¯–ßÆÞ´“2 ð½jA•;ßÖÝm~/fÃ>žÇ’ïd¢'{Œ "*tÁR.y*ZjˆfŠ’œÍÌÁêð½2ˆi.iÆÓœÇx¦*ÌC`£0¤>T¥7lÙÙR,΂âAÁ¢9ÕAˆ”µÈd²'vuÕg¸°åæµ5ƒ­Œ]]ÁUÕ&(ôfQï–ŠÙ×=i*÷ZÆ\ÞšÄ<ìï3Ö§põíÓ/§ Áð|Y{é^ìÎW½8ó×O=ޏ$}®O|äHÙCÏ–+Ÿ–<²£çãù.'îç2E¯’gªÞþ™‡…°Iä¬n<<·ãÇî¦s†üìêѾ²f¶WGj…$í¹?©÷°ˆ± A8á˳3‹‰¿½×LJSØ~e°òúÅŒ™ SXÈÞgšÔá/~#+pð)o…FÆÊYë÷ü–ŽWyj+…£«è½¯k¾O¾ð÷ªß¢Í ڌ͡Ä_?“„ЄE„:TbK9°Š*ϨC| $ÿO›j¸JUç8 ꪨß?É!" UùT­ò¶ö2cUËi£1ƒ÷¥òݰ5~¼îµÌÏc|}؃ƒw³©\ÖÍMbw¡´á€Žø¡P×çF°ª(Š 4Ñ…‚«ÆIL BâĶ¥›˜dNÒ}êwŠªª«€T‡'@ó`T:õ´0bXúdêÉ!Ñ‘"ÕëÔïqWÝ<õ¡v¯¯Àn¨½Æ¡‡”õC¶Ù/.½vêO[Π–~ åóïÇÁÂB»ã…}}Ç'Lb¨ xuêƒø6w™}O{UUUY–¨4µôˆòU¸iûc².êuˉ<|‹þ5÷Ãö¿×aÏ ¨¯‹UU©EŽK/Ôó4pïºX ª¦fb*¢üö®EFœÙøø÷çâÝñ—•U\–ˆÝTï¥U^úOëþ ^‘ŽœÃÖ‡ïØH ‚Ø-"Ø–Á%²Ka-!H AaŠYEKRD´´‰jÙ$[!l„¶%¨–’‹RE¡j––‹Qj-ˆ-–’[$ZP‚ÉAd€¤"„ŠH¥¥¤ZKRKaj["Ð'äÊ‘¤-H–¥ ÁI!‹Yj(2!"H,‰""¡#-D‹a$[¶-%¡lJÀP’,Qa"’AE’AR[Õ¡iij[$‹HZA`AAV` E’E„ª%©*Â[$–ÈŠ¤´‹`["Ù"ÔBzœ8¼EÆöA33cÑrA<OLÇ•â–%…g«m_`‰Hl'®Ñ€À¨b°%2²d[1¥E –±Q ¥Ià“ì¡ )pÝž% Jq!¹Nk1Óܶ†iUá°k_^{àÛÃÇ|Kioæ<`‹¤5%K†Öß¡B;Ð4‚Å‘³—X3Ìföˆr HœRõþI>_çWÛçwóÜxéiz8ðšî:qµã•\èºmÐP>G¸’wŸC6pÚª*«`nI$Y&1Ø@%•UUDQ@º‡ãº&‘ƒ=媼É5˜ªª¨¯ªa' †•Ux-U_;Q`¯ØòÌ^”{`e-bá‚V%*ÚK„2C TyC’ÇÚu‹®~R³¤…‹Ú µ'ŒCަy¾{òùÃT$A Á‡6@¶õ˜lQ6íÈî›ðhè² ý¢’VM¼ñ†&¨Á…ÝS¬3¶¥H*¼ôwçC}Ï ¦Ñ "D4BÎÄ&°%W§‡«'¤«T¡„<$,ÅJ•‹=ŧqí¢ Ÿ#3w‡òžª)鯶ëbìõÑfF1–ù´¨ÑT-`Rr¯mZ­QÒ¡uo…D¤¸3ƯD $Õ`¦Ú¡uøàk8ÉÏÚÕ«B,ðÕÝäìàBñ<82eê¨÷w3F˜;<ÜbàÔÞžLYŒŸ–~f;J"!ûéÍ&zü>¼O7Ž’xü|Øy+5ÕUVÍMÍ„“Î}²Î‚JÅVµˆ²O5f&$|ýÀø{BûŽ+õ<2*ª¥ù#Z•j*=$«_ñíQbnßOÛf}ñk<íXªˆ±EDUYUUEö³%'ùºÁ’ Š *Ѝ3Š©–ͶU¦™—o«ê×¼Ãú™äû¯QØÿìì#aZ/_ý‰/¨íªõškÛ„…êa’oü…×òC)n ZÔ ¨˜ÖS–‡W8&¡~Ù„\þØ~Ý¿Þjq¢µ´PýÞÙªJ‚ïæýÖÿ«þçþ?ÉÄÃ%2ÇgØÃl“í…ƒBs‹îf†×b¯ô"oYÇñBŸ”ñíÙåMëJcT¨x3É)B>Ý‘„U`8aÖÜ+VÃR‰÷ôò!Q+²-q…ú% [Ó÷nHW"„² <&K%U)$> QqsÌ8#³Y‹&ÒA¼’ ßNć¾M”Zø©µÙ’D˜Tˆ·»FtÌXRbGˆ¡ *£1mM!D"JàbÜQ~{øé¸& H_0º^lR/1ø‡ÃÍ–ÎHž‚dQ(›6h–§¨àØx}ÑŸåÿ¦sDbÀ–X[K-BžÜxPPÛ¡;t@q®vµj&ðèë ]ÆÍm,¤ènžåL‹<DáM½ï^ZÅÆ-±e ~œ)gXÞ Ç­¢+‚ 'ŒŒ¤&ƒ(Û&;6=„EîÚBÚ±VZ“G²$‹ DlõØÒ?¤"g‚$*:¦Xg™ñ¢’ª$'“2e•¥¶h˜\¬ ©[R‚ “&E@Ñ©V°,˜„¦—9’ÉXIGoмX+”ætsñwÙúÛí¬ÝúÃWE´§4€LÉ[B¢õ2΢I xY›Ã3É ‰®—£Î¥Û;¬®ÚµÛ$öRLÒc1é½´ˆ‹˜ÁÄ’>HrÉ7ÐÈ vž‡H4·ò ]N¯^4æÞ¿dÿ…F <\2TÁU8á4õO”E‰B{=5™ ˆ ¡Á`— ÃZ;¼þ#áúÿ-žïu<~·nÖņÿŽáåÊ ò —1õba†„Ò46ž¯Õü 8óض x¼Y©#h*+ù% qÐÒC V¬z­ÔHG™x…&½  œEsâ’&´j*• …I*–M@Æ(eIFHE *IR a*E•&.VD*¤n÷$HTަoƒ ô¥S¶CQÎd„ýMZ²³#ßc»Ã¦ÝÍ"Dñ²h ‡„ù$>ð„Þé?a µy@µw¨äÄØMQ Í éFç%v´XE€’Qã tN³ÍYuRaǃÂÄf­HìÞw §F0€‚Û™ØMâü!T_ñ…Ø,Áƒ”Ï7cù_&„×Ð;úÐê¸ñÉÁ„bDä À‰0`‹ÉJŠ(‰ém²o]Ób0WNYŒÆ¸àÞª3$ƹ„¤‰¢„Ö­M,2YªYˆ •*WdehÍ30[ª%¶ÒÛ+P!$®A¶Œ][™Mh1 ÓDbA± a¹™0‰1jdš¶¤,Š"R.¥Í%ušrÉFi3fI5ãh§B7™®. *( ¥ÌŠ( ¦f´iZÌP¹CP°R¢‘´Y™*,Q´¨¢‘CŒ§¤’rÔ âèØÂ,Eƒ"2Û 1R„$i (3Ž)²ap‚Þ½P@¸E0… Š'Ôöø²à0ÂEvec gÇa!îvA†ì$Xz‡› ÷äã÷K¹¯gºr¿¦#sè; vólªeÎÁ$ ‘„ E` ª« ‚ÅðB‹I°¬à°´HA‰’e– Î ˜ 陯}g±Êªl‘S|Š”‡+\=Š4£?MѳçGSÔê~ Ãé+Ýîö»ê§Ëñ£”Óˆ9’f3›>v|l8„°Z±Q*G¾–ÚÅU0dD0L›ä!!`e‘2.û|ÔÛHÚbQè©€¸Š`¢œb—z¯ƒ¥õ9;q« Òx¦&²éæ­Õ°4Zm6éû†ï/"1 ómÌ‚´ÞE·äßÞòçGèd=7†2ÌX ÝÓ ‚VÁÎK^Œ})Ã&2°éR”—’Î: aÕ.@\*4@‚,* àA²oÿÞ7C¥¢á.„ÐΠ²ŒGï”ã=w™»ùy»}{’RR¯3ÁC}ñË——ã9»ÒbÐ)³™‘Âø‘3ü/ìk]©1!¾I-l,ë^Êaú?genk™CÉÏsüSßëy¶ÕS“ª Z™P•.…ZÕgóÜtk-7™¥YsM¦W4ÒºsVgûéüÓî¬}÷@¥àéú% 8vCé ’Wˆø6+O ?"ÍMM;£«¤U¶SCr.ÃMZ(²ÃNfZ(²%Hs,:ÿMýo™¯¼2Ík(ëW-.­=J:ÑjdS£2eÀßxk&[r®V ¶Ñ®òŠb31¡G)§1EhÚhÁʸ—1-à ٖÔm°Er¨#VÚ-ðf •Ö Ö®›¤ÒeqC- R’QÿI.A!" ÿÚË?áõ^]ÔçjvênöAÃ+†ts/}¦ÐYt×ÝÝ 0SM¶ê¹ )2Ö¶Òt%!0Ò#Ö·HŠAS*ÚÕùuGnâöªÍhÌ´Ÿ(pÊ”`¨aQCš)L°t÷¹õï¸a÷˜½‹š¿U“…yàíß9çŒy„z¼“ptÜ'ììiÓLމÁ‡R&0È{J Çvp ÁÀ¸$ **Ù²7QxA/IÝŒŒó›‡,Ħp~p•ª‰™BƒÿQÚ¶B~—·w$dRH¡ìqùóEqAÀ`¤„Ò#øG°?†{“ '£Û}ÐÆ?•çI”ú* ð}†KG+û¥øìït„&Ä’G›Ö¶%@˜®Ö @F†Ï4Í5 ´Mt(Ø3 _.KdÌe,–"QŸ! ‘ÆDH`¡˜×âú3eU-c¼àIJ.u¤ÔÓüÏCS$žò½‰å…7!ºja>,tXûp˜¬º9`òÿ ‹‘!¸‚ì$¬"EŒ¶Ø–‡ŒŽ(b“ªÎ³=¼§òÈÕ0£ßAÑz¬âØÐ•ø›‘ ‚à&VR@ìäŠD†ºe…ìÕ„øx5Èî: À]–}0+„D¼-‹bI[\T>eal[IKSòZ<¤ù$oëŸzÚ:DMú¡láͶۖˆ"Œ@ƒ šWÖŒ>ùµ=±áœÃ?¦Us=»àÍòèñ¨Ö³ó½Žòxá hðO‰¦¢v'édÛÔõsÔöûÓ ›3*Q}Ú™7ö÷ªfa˜³-ÈAJ$ IL·)0ƒ"†„Í,ËF™rd’œ¹…)å9mƒ(2Ée*¦5R\°¤T(–“’8d¶ZÛ«EpÖ˼»wååö©?Ùwxx‡–ox¿‰ ¢e|0 ¦Ô·(J@–Úp˜534ÔX™©US)”šh̉aAA©¥3*€e´`¢Ë$*s2IÑ-ƒj!­8—CÆŠÍhK\Òш¹)‡ ÃNA—.#UW29š³­5[a„C T”Ä ¥A¶ÍSÍS‡!Kt[–ñ2æ‘\¦%µ´f´bé)ª•FTn73õzÖbm5‘µ­šËS&“™›ÞæöWyLµ¥]5]bd”¹™–«™n&ð[šËQt¨ÜMíå±"ˆ’š—¤KbSS/ûrS$²¿hlüñö´»ý­‹SæqÔøúþ“™??þŸxˆŠ{>Qv}Å?öþn>î‘úÖCaÆœx…€ÓTD^àÔ¹ç¡tgnG°ƒfqe?¼òAƒ4'+‚ÅP]g #–}h²¢›‹ ß$)Ñ9Hh*tþíy›C’0?¢p¢+ Nkù]ÞylŠ‘Æ+'à “§Ùiö«ÅÖ(É'Zr|»–…à補ÿnÇÙôŸ;äî;ßÜ[9ö9û»[¯9~t«4F|Z BÄJ¡GȸnÛœçnv -ŠÙ÷>/ÎÄñ†ŒÂâ竲òÝÇdbh4 >óql¤™åU%þà}ý—ÇÓ1ùî÷ïÜýý~Ÿßu­âjæ1A¸ ·ŽÓºÕÝnÜíþ÷‡“°åü"'i릊~%þÊóœQ?&Ç–€€>ä—†±Ü=§’¹î³˜e”DÄ)CÃû~÷{yôðï¡$ƒÝJ†Y$Ÿ5’ÙŒàªZÿñH'É`êãëPS=ØÈr“¢@©Ù *L¶bxwöd®„Ñù”Œf¾ÅÛçäÏص 4D¨$~*e°|!ZãÁ•ÚXC¸Ã†aÃ1•y,ï’\馈yþ=KÈÉHÕJg†©46>,‘îüuã†|r2© •µÒeÓZt£y`V½b!àF=ÌâÃÌ Èɦêp°œ—ËÌò¹.Ò¡æóÌw\Þ@t/GŸªÁ‚­ $ ‚YÄÄÁ„+º D G÷iBnª­Ïáäרìtò”׎ôi]4xœ™Áz{úiŒ¼=øRÖY3Oè}á1’ b 0¼ð Š ¶ -Ö~â1_Ü6´Måƒ)‚c|¯¢ÒŠá¿Øþ¯ZŒø¬%}ÿ–ÊNô5Ô-ÂèÎÈxìøa¨²NöâĤ© ‰f“Ä7¤`ªÇT ö¶í‰Ðåá<& Üþ‹CílmU@@ZCvlÅT”ÍTŠ*2¶û“t3™z£=Y¡*}[YÎJ‚¬fß._ã«nk•ß„ˆ@ G]‡¯»î(}ßSü2îŸäÍq¼¬a)1ÃC“¤lž›¢Ö‘ƒk–fl¼ªÆX•ÊìÓƒc’¬Gy+Õ©”hË.häÏ{ð¶Ï.ÝבÒ&¦Éò·%Ærçx»›&í}Õ·Ò¦Wj,JdoWÊ–|"§ÀtÞ´H’‡(ËóŽç*tw\Õ—.‹½ˆä½bÝëφ§jäm©¬—SáÚÓ©\«UviNlF”«JYJµÌ¹Š½¯2۵؛k 1ˆ¾×?½úü}Ùßq?o•÷aǸnë.ŸÚ¥Ý=Öêy*·²ä·XB4ß•¯Ö¸ÛÉŠb¢ÚmWUŠÄeßž4{~;ÝïEIåM€|ò_/3¹kÓv,½cJ<ìÓf›ße¯ c³9¾ÌŒJÒ4Æ5¬r‚ÅËÚBÒØ:†Ë™¸YaŒ%FìƒYÊr›ÑU—‰ÈANò"V6šõÝ9”DnÕ¨-%¤»¡v<µëN³Äöß„éµs±°Ôÿß{sçô·»ä²ØMK}öªüÔ_Õ)¸¼A‡ýt\aÖ¾`à•1^O/Æ®­ª“ö;‡QdB„T¡8³ˆ³ˆÑ5™–©äÜ×´˜ÃŒ°¢ —y“¾é+Šòçoé0—ªò,‘9˜ QEN§³ê7±ì´×ö_2k7„ÈÅàïX9" <ðöT|^qiΓ"°¬™ëjJpœÝ\xÝÃætø¾ì'‹ëyÄÞu1EƒO vTºRïñmÃ6ÐÜí µ û·Å¢R‡¼*Mõ𤥿âÃGÚ̯Àו<Ü)ØòüDmìnÙ¦ÍO”Ýxú©£Õç“~^ÞÝzw|ñšÛrG‹ÎL÷ž¨úô}œÖ.õIÊ)£!û²<“ÂizmºK dŠ4C÷¼ùö·ˆµáÁöÁ– >ý÷ŒvêËr ¦Ý‘”a5v¥÷£ëSìÍ™ ïeÒyZcÎ6í)/Á§ ¨Œ¤¬­”ÈÊs-ØæÛ—Œ³X†9DV–&J—¶ú÷r´!sF¶úþK>~ÊÛ¨y&³Ì½±½¦ÍIWaÛ˜îWQr¸‚•=»²…Œts-3w/354wX³þõàDþù÷¿ùþß¹üÜßçÂñ?ÑÞìe˜TþÆ×sÖj˜åqð?¦m¬®q¾&)Ú~}™»+WK×dÛµqòæ0‹žóõª|ˆû¬¿çu²ý&é|ô>}â¶>…ÔvòŸ9˜¤'lEÿwµN§¦~?£ô¿¿à|/ƒ¶îò^q´PçB¬T^zWr@¬!„kZ/Ê¢`?½`ižÇl§ð{SG-÷íºq&úÞ7 ´îÏÞµu ?m•TüæM Å3ëS»[;é©À™qOßk }³ÆÓ¡½w̧yÄO,ÀÚ‹d8ÔM¼o|ß& ʲ^®5ÖIŠ€êÏÚý²ö9§Iîü¿GhvÍ(ļP[òŸè×ï>ñ’˜ýM©÷‘g ¿pûœOz~RIW¦í3÷™3ž"χJã;Ó»t‚[*|Y\ч€„ 8äô;{ºžz=ú®7Qìf¯]ý¬TôO°ªÿƿҦü t€;£‡ìßàËy}õ·ÃmZu#¬£õ~=ŸóùÇ¡¸vìf±~­ðȲ'‹ aE3ç‰'dMP™úý^KQ3ŸÆ;Š !)‘ȶ²_NäE‘¦‚ –w4 ®ïŸÕù|÷>=»ÁF´TFbo,y¼sßÇ&õ{¼:é–OgÅ9Ú&¸¤<íaו›]9è_‘¾(„H5鎓$šª«¼ƒ<©â¢ÍáPLjUÃÓ¥W.wòIù§ð5˜º^Ÿ‘ü0Á>9óWˆ,ˆùÔÕ|7ôúT¯>wrkW•ªÍÉ™ºŠ"ËËZ¾jâ¶³=0w "_'¿UiúÅ"V ËŸ5xmÓÅØ+mlª¹Ýô2p 5?jœ‘¿o—ã½||zúL.ÑwOé:íå‘î¨ÙWjlªo¢µVXAqÙj³|å6h¼)dú®™Ôs‚‘ôõ½ø 06Á7$XOs~”Þ“?—ÃŽ JÊCˆÞ›;ôq…l»Ç ¶ë{Äur×(”¤kôQþ˜÷À|ìqúšfCØúðÅ ‰„¼ã¯ýþ³y½Ý›C»Ì§™@ó*w£.ÂJÊ"ÀEaS¿6€Ch@ÔŒ’0ÝK‡~¿Š 6BþYÜaåÑ6†øq„euŒü§6¿ê9 ªAEo8m÷©‘ ™Ae0ŒTÙŒ0ŠÜ‚+\B=~’??ùŠ,* –¬’˜‹DM}F bW!„„$Y„@BáþêPЧýÝû¾†„8ÙUU4EaøHþ¿K¯·›0OÆç[Þmã*ç‹Ìßé‘ZÝC·{ÝØf- ‰ ¡”…üú3+iß›åøú $rDDÐ$v±Æ ´wˆþ>qI|cÎ̪­%\Kvz™Ð…0yÑFžEÞMËzvãî'ÀO¹Ó² ù:üŸÉ¦Õ|h¾LçLj YTRÛï}Èû}woªU?ŽÉÜû߈ç¨Tï‰Ìq$˜"ïõ[^—ª¾OÌâ _“^ªu7I¹B³M_`É›ðw:g&'÷È0H#߆"AGZ#H@À+vƒ÷l‰’¥~Û›”¯Ö<ˆÃ¤’©:åìùÖTÄñ* •ILYDØËR$÷^z)„ky½ùôî.š¹jì«ñKnßïTÕõgSÙÛ(ßµÆmìÃ7X“(ó8êÐ&HUŒ¹f?¦â¥áÃã×ÁX`VyR$]ÔÉÂ|˜ G5+WôþËøÙÇøý¿KSì1 o¿Üýþ>yr­¾ÑE$²lÜMë»q7¯Ö'ë;YØâŠ¿ê»_ßø§µ?[j¡×SÃx”›~¤ßªœ áꬾ¯í˜n.ÌÌ·1·;Žœ~Ïä'÷?WÏË¿þ£ÝÞÒÊ"Öø2àÛBŠWÎÌ¥ÏI…›]xó¬ÑkZÊuí¿ò=8z6Þ™*ÔVÊ¢(¢Ãþj È%H& ,ú?£ú^<šldý,ëË®dvÔýn¼Ð@¤=0R("‚‚R ÅK”äÛ¾™£¦)RÅ‚ˆÆ–•»V"ÐdV•$0\ ”±T&\î_w¯žã¹U q¼¹\¥2–5,´GštCIP·×³¾÷^?™Uº¯Ý_¯$yäù’j²ÀPC‚ŠD‚ |&Ýß‘™ƒ[Š %A¿–É6¢È½MÐÎôyÞµç©OÏ/ ÷”pÕx=êþóü_»ÌÎÍò~=,¿Có)F/î÷ujËö»>ç RU&i¯ùÖû>ŸàY_Ûÿ §£>¯ÇÔÔÓÝÙ¦¥jÈD‡ÿõûw»ß0vÅÿ[}O7Ñý¾ó}±½¥î\L©bñ3)t…Å¥«)öém¢¸¶¢­¶Q¶Å&²©÷Iù“ 0REùIOì'캎ÿc3&8¢@JJŸ†e-ý”ô¢}.B|ã&÷kff¨T™ÞÝÃ쓼Úm‡5…­R¢ZW-B’AB!B>ÈmjÅs´¬0g+¸×s§•­Z"–Ò¾3 ŠÝe¹r¥(ʪ² ²ª+ZenaŠÓ)†´H‡E‚Ñ$øm‚t:S~ê|ßÉýÁÈáÅN´Ž.–—yåË®WÕˆ/þì´r~ÿ¬úÈ̃K-¶f“ž¨ï#áGvû÷kZÓ50|“z"€iu&‹¯ Lˆÿïóñ)È…Ë€!ÒãÀ]Ù ԱÀÊ9°@¶&ecókj5…—°¼ÿ–8 â…{ïtÕ€í4`œ—Åú%Øœ<ÙÃã‘^kR ¶\\¬nÖÌùò"†«9¼|ùFá@½ÈhåS˜õe;­]¬ö–¥Î¥£E‡œŠx8ߎÔKÁºà€?>=ÛˆFa€@ó;b8ñÔól7›y³µ2ˆÂB9$¶|òB/ôhkéI+–K£TúpGç^ãö K)*#£>ý’x«<ÏngÃßæ«“U½ˆ€0ˆ}ÆòÛâÛ6¡'PqÅ|E­EßäøÀüó†^›þÿšÀOû9Ï}çOÚï>7°3ý.RV„>¾Å%aáz%6ãÈÉ(„8pĵt Û ÇFþ\è1[r`x®lvÞ6ñŽÎ§¯WIB9Q€áøáLjFisy²¹í?)@$ÜNuœ”èº\ûõý)ÝË=i· ÿNÍm&\pƒìbìÅðGbt;g~O}¢ŸRMÛ”’ø«Pî ªò¦Q} ÿß6£O\ŠZ¡Ê”ö«Þg3±5øä+Ó&î%ÄM8ZH}•·5`m¹¾ˆs”¢±U1ÿCüeÙ"á£Õr+ú¿ºÿ|rŸ·Öü³:±§ˆ”Ž'n³ŸeÖ)kÔÐQÂiíD8R7«ÜQ23ÝW=’úÄêœßûÛuö.âá7Zÿ,1h•}%‹Y´°±Ï¯©®):ù¸•'°ÂuÉŸ‡ßÞ¤j.èyPšUs8ÐÛÑ“ý÷ÉjSó÷›ùk"š´äS¯™§ü÷&½.›'ÏïjÅ7;þI¶Æ? :.WèÇßâIÐ&ÿ/u(²»¶5´¾¼Ûi.ÏaýûÇÑéógÞ*U6è+:‰jkþã/ñLΗˮ‚‘ñóÌíû9Ñ¥æi!+²ÀNŒBIé›Pωä@ ÂÇ@þ>J‘|º¯êÃÜ]•}ÑÙ€Bº›$3>hÿ‰´"Bãïíú8œštŠ>ÏÐ÷ »_·§,ɯÏ$°Â®6•vŠgX³™Î¡LG>¤ðõ½ ! …%¿3¯nA!ŠÕË#¡ë:ihíòŽáKŸþoßO£ ×UªÅêиÚüfÄ_û°»Óaç¦ÄaÔÄùöà ̬ñj1ji§WˆÁ0Ûð­ô ÁJACibǤ6±GÛØEW¹ÃûçÇ:cK»‹Žâ^#aÛÓùr:yç” öƒEWbvgç³¶]_,N<­ãþáÁ>Tñ®ÆbíT²¨Þ¡íºIgHîBAªtY×D˜Á…0¡û-ƒÚMeQa3vFƒöÇ]uÜ€$LlRòëóý[þ¢*œB?IƒjèÙ™Ho7_Äö‚ÞŸ¼ñ¬½«Ç|މK­êüê§gÅoìZI%‘ ÀÎ=›«Æ×4üŸ*5bɽÏ×À¼]€¸ÌÌÕÕ8ãZ6‘n#¨2v|X°Ù›j—68ÒäêíÛS†¶SùŽæfCÑ ¿3îÊCråxÛÖ&Ôý-†ôrº Öd¨Ç³ š\s·ô?ÙÃtBø>®àÌÂnÂM0;*s•ÿ^×[í÷È~ÄºŠ–ì†›êªÉó)Õ©#§û×#ÑúÎ20upJ×CŸm×NßfÜT"°Íû+ŒÆicOz3d™]âqò)•ùŽñõÚ‡Øü¶¿?ÅÛ:cÙÄ]Ê0êïÅBÄ_¬C¶×Jÿ»Y®„;Ø¥?=Hf}Q™_AÄ_twáîÛ™%ʧ\VŸúsnKÖßݨQ8!-ªLñÿO’äáÈc"3/ç^Õî âÓ·\hUµ§1f‡ /ϵ°³ÕÌ­¹÷—x“©¦?JÒ=¬u_›™öN:÷aõì&ï_ûõ6DßìýQù_‡¥Š:tõ _…OŸÕ£ÍÍe©¹¿–#m•¶’š®:rQPÕ”Àk$?â:™,ì¼ß…9ãsšëôo3=4hºQ'Î.C,ÎjFðçÏXå*,9y¾î²nz]Aû™ÓÞ־į±#;¹ƒç^?ES4­Ïé­H¯›™ˆï”þïÉï…‡c‚s+¡sív‡U̺”òØ}[Ì—e;¼×îõÁY2/Ô!gÇÇø_Ò,ÔÓ¶–ná 1"=¶¦¤-çG*Wmë S‰'‰ZbQe(¾¼ŽS‰9[–¢Y‘®µUÍ•OD‹!ò?F'àÍ/KÞÇíć/c¶gy{Ðgæ‡Æ±3TÍq’Ê×6¨;¦ýEfK0@]¥h7AãÓäÖsᬒ>ßìîNïÜçÛ‹ÆœV^ÿ+'îM)—ω[ÄÔÙ(`Ÿco2 °!ÛÈá4Š”’ðÓõw6¥¼¼—±Vœ^s­¹’és/ðsþ·Iæµm¡Êå£àæýü•îgÈ„Ò_tmK–Ä xÍ ”“z|„¨2`÷çs~kjíVéX²ìЊ-Úlu¢•Ï{FÖ5ý"‹U›ö¶2I/4™öÛ ìü˜vé±ðÜÆÿ‰»dh^¯¦BZ¹Ü"\…íWâ4*T[ÉßJdo>Hž³¢GN±µ qoèó>ï)¤Ž€Ø ¨|í‘&¾*·Äd …þÔV#ÔÁ¿Tá×Òrµßœ-zè8ut©I¦ cø¹Žœj7Ù};ô…œOqв}«zøLÆcηs v££8ÿ9™çÏô´®h=š2&þ›eQDMÔÈ`Idžï]»^dPÈÃ&Ȉ§µ©ëz°(£EÏÿ½zÙºè2="C 8žÿb%óàÿ½ËÝ‚LTÖâ\²«‹=+e~ÉWóÜxÜV¶{Ëk…¹µç-Mz××&­ŒÆ™î)±x—Õâ7}}î(ZµK1ß–NuÖvÊ“?…þ'ÅEUþï6~‹ûký݆^S„¼UÞ¢l頻uŠ@nt,ýÆ ÒrìE¾¢nY[ÆFÆjçC(ˆðµê™¸õ8Ò„Ó¾¯Ÿ†Ô?Ê. ’‚6^^Ÿ×yœÎiÎê^tŸŽÞÙ¼¹›æçu}; À#«úñ{™‹óçHûëžrʼóA»³|JÂ{÷¤'ñQý‚‡ƒÑa[:V>nç8Ãõø:½Êö¿ª|ïæ˜éL¶\I7Íî¿n3>îs‚ mÑy‚;…a UýçfG¹Ò–á¬a5oèû¹Dx¯pÝ yã\¾ßþ}D«1GðzT•¥+D…ƒM²½æ–ó£ûw¿Ÿö!ÓÝ'o©JsîÔ©çp`/ê·ýOùׇk¹ò(ÿY¤ÊÓ™iK¸¢¥ ìÓõ|{Sü™Vo4Ügu.39K¬ûyyB·pm¬™Ê4 w®Hùz„… ýdÙ4/B‰ìw{¥-‚n´¡ÑìMGºùöååãÏ©òž£y{¦.Õmá½w’…±Æ‹fÄÉSß躓m:œ¢~סÏÍF/ƽX%`²ùŽRþ#ÃÑ+®ü2¨¬í Ϩú›Øúöˆ/»%ìâÿ?õ°ä:t°Û»×™ÿp|eg6RïrR‰™y³E¨wøR-ïÆw#²ûÆ=óÝ/–"ëŠËœÑcF0–*€{u9qaIJÈÔòiäÚð:û4IåÑž¹W”bʆγWxdo÷ÚòÛÏÐÜ*'uæoIZ¤eE#/Å7-v—‘Q–›$C—ÚT°>ë59,Æü[5›{¾‹C×–Q‹¹>cOÏ©ùNÇÄÄí6h$ö%êk\÷QNMXÞõO%——³ëŸ ̾LÄãt=ã$*’ÀœÌSb-¸/ü½µ‹ |eè‚dŸ}æ‰>Á|§ž juD‹ÇUÆ—PûÅdY¦ ©M.pâËô³¯—ÍåÓÔ ù—”¡ p§-¾Õª÷ÑpÀ! <!È¿96”WÇæsŸŸRI‘üæXBÏop¾‡â'ƒÖW|eë×”fé%:ËØCMÖ27úä—^3Ùïb¢|í;t5!½;ÛƒmõݽÉs‡å éÉÈQÀ·î·¿ãË8¤ÆÒòø[ÓqõyYOwÞƒI2Mß›zo½‹u ‘î}GÚžÓeU‰Uj¾ÅDÏ´¬¾lý-Ÿëó„&êÙó/õl7ñépŠ!%¿wz›Z(‘”­HþY»²½µI ºC9Mç¨%´ÒÐÜNò»¤ûË?®Æ—lŠWò­£FMJºQ2ËÆ…ÚœløZot×{di?÷'½ ÷©i““zç3Ã~™Í¼hH‡¥÷ýÛ2Êÿß¢ç •<÷ÚÛˆOÅ–kÍ_é–Uèg‡åX}ú °|G¶ØÊ÷ k>éϾ “?rx¼Ä³èsíìºò k8T|hüÙÜ&3vÇä;lF´n¥Ï_{Sš¼Ý¿…²«÷íØ_Ùï{áý‡WX¾5¨¿Xéh3®uõ5Ý·íF;Õë½àÊ^Xñ£GÃÕ¼] ]´nãÂÏy–Ã^mgm6S‹VE9W8ë«x˜Owíg™”ïI~>%ýdlῪ^bºô—ßv¾‹›Œµc÷Iš’{Û±ôïÌ÷W¹t=î®#çÑç]‰µ,B³mlJå9»’ñPÇk\ã° 7åsÞ\¸Rõüy=gŠïµµkÞM^M+¡ˆáçY…@^¾·ä»Ï/øõºëÛ·¨û"[/ã'úO–Cþ»üñÔ!Å÷ó'™eð ê=ÂÚȶFjÓ$73¥2øŠv“¥Ñ‡cßæ`³<ù y;󨃘wWOÄ·ÛŒÌ[ÌmÄÄéýðùË)/\mM­ü|¸s6E,LŽ.'ÈÎ÷â51[ûgÛêÔF]À¯þ¼ù)që<'Wöºþ'«|ê5žI® ß7 ^ÑYUçF²d}ჵîløþVn¼­wòƒRþÕ|¯Ë,È[þx)À^º-fžq<;S®£=ÿ¿æho‘ \>‰OOò³ÝÈ’B£Õº vøî`qóLÒ”±¼ÞÛ]ƒ~ì¶äÑ› 5ÿpèfmÑfèúÞ¥ð! ~‰|³„‡>SF¼Nl–ñ#_ ?¹{É­{ÉuË,’÷2-µg±Ï|¬3½m´i¸Èxú­7¯YÇ÷Û³£õû`q¼OÆžª(få9˜ˆ€ g”t¡“öä¾P/AóŽ|Ô©\kï×áÂÇcÐ.?}ÿñ+ÖÞ‚i—ð ö³qg¿§E’¿›"©wºcù:/_È+bŽ<ĺ6¢ËþŽ4ã¬=½ã'F ûõ«)€…&0€`kzVϾÅçߗ삈é=Ä[Íú¾B×ò¿…ö×à°-096Z‘×¾9î>þ_°À!n%Õp[Iº”-Û¢ÉMa÷O?>ýË,¿õ¶fbƒ*\ ݵç¡9¸”¡9Í,ˆqü¾ôo/+HˆÚŠáÑ×ìàwñ½òg§}lÊ };óg)!ê°ËÓûA—ž¡Ós¥Ç2ªÃu‰òw#?L¿^ÿ×ý©l! <Œ_olòta çHÉ}ì^©éÙ_×zÒpËžÉë3ïFüøS s •ñÊÏ­Øíxä½³­Û 5ãN<2¹ƒ™®§¿ôvK®ï¿s¤ƒh/7CºîU¶‚œL“oM]ã©i®WisðíèçDpáz§ ˆS¸ÌrÙl޽¸œ¶ÿ¢e —¹)}åUšâû*ÛÄï±} ù‹æš¡ùÑisn‹e»î+P¸°[ˆÚ÷§Ûã%úñj¾»u¯YSëß=Ǫ׫t×6~s+‰ Îý ?ÆóË™á*²q2ŽäÍDL5¨X—Wù¤‹¶ o}±ŸT»n¯fHµ˜ÕškKÞ…Hœ¯nÛXêùW–ë¡yÍyM"ýòQ£S*Ó+ƒr”‰ÔÏ‹½â‚?‹½•fšû yøö~c‘¨;1Ͳ˜=Ù¬64cÑðH¡me ”ÃæÒ Cg©¥8øl1gI¿ÙT¹GW+6Ïó¸!ð6vg«Ù1’çÃXS/9ö‘Þ¥Œ%½k•¤õ®KTE„ªU¼·Ò !³ú"%Šœ=9i'&m3¿î¯Á(©j´gb§_9É}ËÊ1s [‘Q2¹A½ú-1Ùl­A¥Q§ú´¯•*Q0ý>%½E÷w¼ž×âñ –WÛVXƒL[õ{‘Ôtã¶Z¼tÞÄ=ì97Ãà°û:»(èû2°Þë’“>Ãßz0¿CÂq€Â7øs1šgD“bcéëÕîñ’h”{i͆\Ÿ=:÷]óœÃȼÇ˨*•G«~3Š{¤†Cîoè3^­ÛAþjþU¯£cö%×:åxë º(¯&Zm^%L ‡}…/#{x€:¥7 ‘ñùuŒž,oÌ®ó×y´ÿåÑÒaX#TÍòñ·'ˆ\ÎÝLy\¨ÆÚžÇÚ]­ú¡è/òj9=?Ï…ŠžÌå¾{Ã\ËSq®-Œ4œ9ùhYGZ7>%îmV”‡iB;FG‹‡ìßkIfãÔ]ºÊs-‡s×w›Í«naÞB±CFúÂ~Ú¡$ËLi9ÍZ-f:m/œ¤¡ãpÄ”=™e}äÀ+PÒ$ÅBìdÖòúmiaý7p §Úª¦œ3RIŽ+ A&OäžÁ“é®§p¦Ó¡0v­8(ŽySEk- º ÿÈð¦Í¦Õ½äúŸésîçkŒ·'Ç<{;® |Ò¹Eøòðîsåxø^¶Âug‘o¸©ùìàj^ò%¯n-F¢Û2,îʤåþ¯í(L)¸åÜ9BÅߌw Ñb‹Ïß´cÊP7Iê@ùR¸þylÙßV†GG(Ôç³ßÉòÕCã4É’¼edyi:4æ{S꺕Û}ù•–ÕÜÎÿx!t‹³$­?Õ)œº… øñ[¦&Æ—/¹6bO*¤žz4ˆGÇZâUzËyjK¼=G8Dt‰mIWgÇ1UcoiÑ[^7yÆÈíËuéɉçÊ¡’òù1=ß~aªo“äig‘dF…$ÖžbHL‰ª 3¾÷J™‡ä·ÞK¥E’øc|œ²t¾ÿµŒ„Íý–±¹¿=†•…ù/󚤵ÒEZ–A“zKQ1*ë-o]x¸ãöº¤§-iþ5H_O¤MÈÊý󠬯‡KCääßý®ÒãY`B÷âpÌ:âíÞ{Y—c½‘xò[ÙË"„À]<&ܺݜÓföe§ò4³v½fž¯ÂýbLÃ[CÆÔ}év¿±uL&e¿ÏéÐB€¯Dš™œ‹‹.l¶7¿´ÄMCÙȃŠL¢‰Hq˜šª«8Õ6ûA¨ì;,h¨ð}šl_#̪èy{Ù^®Zé¹,½×'ieîóDǯpÚ°_ö|¿[„ÐÑ.²6 Ç»DÿG½×¤Öf'éúÏdrwÇ™Øsþ'´Ép÷æTìbâÎÔÙ4ê»·sÐ:ËYy¬94ŒiKnǽˆü×Õc#±ö‰ŽôTñÑp Ó¹¶yËU o§ZžŒoòKÏagç õúµôÖ¼Rô×+þó™ß.K³V:Cý¼« 0YôãF&Õ¡Öž«ªEÕû(ôº,ÔÆÚŸËVx>_¡¹ë·UlüCÊ}Ç´éj Cpmy9 ®Eç/Z\­”ß©å$]rÍöQ†,<‹ºgp¡·½®ïQüÉéËFOÂÃ÷ì£ù¶þK}]óX¥Ïû¾á+@ è§äóM¢–¤å’ðNt÷›ÕT¯ì},©˜€ðùSùXc¨¥ýü¤ii¬¼®§^9¯h›>­ñ²sT‹»§Añæ!߬yØùž%[Ä’׎Ëv9t#öþe3‡6E¶Ö—¾…Æ„ÿK7Ô÷ÛRZœÿ,ÕM‹Ž[C«a¾wÑÖG³™êÐ*Ô8°™~²÷æé³Õ¾\‰Ç<úV^ñö¬7#Îw‚ÚÃ*¥@Ma“gËrdªjSö¼ûg¬¾Òü®ÑEìÜ7èA°Š¥iSSÙW 垤_ádÆ-¼\5]íû'½vU¡µ¹Ÿÿ}ä˜Ô,´´&]%k·bÕ*Ò¶6}½b¯É:WSºéîR-#õ¦™ù<›‚îÄéõ<]cöeU˜^OôUq0=<õ­;ú#i‚nTw™°äŠ’‰U㢑©Üð½-TDß{¤ÞŸ<ß?œ ñeD2–*ˆÍÈþÅ įí@ŸÕë)nOQôÞÐ@hUu²N’)’åU‚³™wö£ª¢³8ò{ËnK%„þ2ÞUäîvbIðvÿÌsP|sÏ7‹g|ÙJ)Z&¹ƒ.QiL‚+.gý„¹.nÜŽÚ ó=vŽ»B¿;§žo]ÌáÉ?%ÒØ‹Ÿ–ççE²«Tçêi»©ÿ8êz˜4÷lEQGªV^Yöš {O¥Ý×M´ q¹}ÝÓû>{c˜€ ^.¹›fË=$Š—«b:µô~F´Â¢Ááún¶";·ûØ È5néP{õûö•jÔÞ&þÙÚäžMÕWõ»Ií[ôtªÀB̵Âk5=œ÷NVú­éãÜúHýìÅÀUåHö>Mº2[å”/mq p.¡ fnëŽt¼!à˜2-§·' ªZ4䳊՞s.<ËY6ìt*eן¼‚—ÆZ—,ßöhâV—dúvåonXà»Ò w¸-¾Z T¢Î{ÛÄzºÌüYàŽ§îLÛtÝä¹&s# žçAu5{¸”íÒ9ƒ@å9‚Ñôïq¸»§aF:=2üöâ­*u^dªßKª‡i¨‡@ú鯩w°H?ö-Ör^ xòœ¸•sôç(v²‹áŽiï{` ^gÌêΓŠx—ýĘK²Ý øh‰iöšŽøTSô¸Åžœò'­ij& ¬÷HD¨+´æU4ÆûfÌÙ9¥4›ˆ½B’0ãñJ² Ùâ—îM(É$f%ú=&˜üµ8lOl´O®8±¯Hb;î•Rá‰.Ç Íå|íg ˆXŒZÛãQ½ûû™ZR74¹qɳuõTˆœß òd5#Z]Lüht¹zhêçôά-¡.$Þ1ÿg{’Mð¼Ó-R¯1²v”Çv-–gnK•ºÂGXwyÍÑZãÜWµÂóP»ež¥”=×j(G1ÑoýD¯éø”[¸ÇeýáM5Wóä-Й{ JÓ:&pir3dWþdÄgc%tn\ûUv÷òR±&6¹_ŽIÇ7Læ5%Ó6iÎ’úúûÓê‘tÉvü,µöŠå<»¸W¬my ^Mþg—·7Šüû×Ú>gH™ú),OÕþ_±üÎ`º¸‰!Ú}û*¤+mB?£'ºCı¬’G׎ÔÕŸ’é»=\þ9Ë3ªüŸ-Ûr ž]o1F;øè·—®JïÅb¾BНÀŽù—'í’Zò")zT¬/Q3-š´wòÒòžæÊ<çu‘´f LÜxX ä‰B£BàB10–#L¥AGºv)ïðçg”2~|ƉqlVC=@ĩѦœ£Ìò˜œ/ý„ÌáÞv¦VHÂp]aPüpW-®j e¦ÅIÞL“ææ=êg ‚o§8ͦ釉[ð™ï‚·Ò¬Bð¹Ñé3ÑYª¬Í'G8šÑ¤À6ço×ë„ÈÃpI…€øk”x%d"í¾¡a›0Ä•ðÅ Â÷y•ôfÔL&õ½ÐÛ®0/Êu™¹ÿc¯Iï_LªõcéX„K1§™ýîB+ê yj¿iÓï…ø`È•Až£ª¼hÜþ—k™è›æsîУ 4 z&$s«Wh)EßÜ‘ZÅŽ5|§êÇ•d•€³%0æôþ¬Þo­>.ÓÌ·Ñdç¤d‚áÖ"ßíÜÌ%ÿfгMiU«Ú,@K}He­6ž‡Z}G…Úÿ§ø}¢òˆϤB +ÆSÚ÷R4JUœ¬&À×!Ü«b×Çn@£®.kÒoØVë³ÙóŸo:ÌäÞWxO5œW½í!Ä ˜ùáÆ¬9Gï÷”ù·Ýf?:5É:G47==‡8¾çg)ü+fû*C˜©Íþ©ýÔ0DyÓ ¾ûèíãä=ˆž¿ùšB,Ȫc–6é"¯#‘èoA¦Q­OqçÉéWõtNã¹ef'¦´ˆKTSH\í5;µÜf_Ùßãê”ûù.Àèà`#½ðˆ!²ëE#õ/ÝKÜY"°ò¤™R’û!5–žZ‰ÿ]Xì~+ƒg'bDV=g²„n^‹òÃr,8_›XÈãY)דÝ÷‘ýe§ý~Å“aW^WB}=SóåtI0V`F·ôM¸ò¦hÜPþÆö5w®TFh€(mvP°õLb0ésðP"²·tUðbú²x=Ì­dµÿ’o- Ó\£Ýodû­˜á¼'ú Šqë×ÉDÎ2f¡mqÄÙ¾/þQP2þÛôãL_Ìýcùˆõ:^_ËßÞ&ºƒ™ØA<ž!EœÈž¾Ã»ÎßiÚ:—Ï—¬ñðT¬>5A&ôg8§#ãBæVQ»E»'}:°iþÿZÀ€):Z½^»Zž ÞUãûÚ‡33?-1â©8ˆ¯¯cÓwáóˆ¦ñð÷ú`ØX(ͳ!ºã—N£Z]m[ |s²;hë ä^µ—´C3‰óé/û}Ã9¡ÇiÍ ±IòJA2hœ“¦dUl3Ò„­WàÍâ éšäÁ^{ao¹Û'|w¬áÔWÍU”‘gMÑ£nïmHƒ¥v2\§„îtDÞÆkçédÑ*!ã}):Ÿî¯Ç‚ŒúùÑ{þ1÷f{Uù¦‡œ¦Bˆý»GI¸¼¨öϵ=ÌÖÏ$ô½àoÕç–£éªUî\ù ͨXÿÞ‡>¢G¹w|ÕÛǘf8öÚ‚2ñÎ÷„¡] Óáê?ˆ6qÅ› „ܯÇ$_{Ÿl@° §~µ©·µêö˜Êª“ùó£œP˜ª3•¿ž-k\J/SÛ)¯5Kk¿ÖË=qi{á=Àù4k·è …®.[W5ÚS_mÙPÒÃÕsËtw¹¼oÓ'Yá葆Çï½æå<ëÓÀjöS›Š‚7ÃXEQÎÐî“·/{4êv‰BñŸ§'9:¥ã²M36…¦"ä.eo3Ùýn*Ôà·J‰¿6…r‹[ ðnëÝMC?C^ÝÖåëçû?ËÞh¦[j:Çú4¸£ÏL?­Çáß[àÀB‰`a½ç}ýw÷+x8ômzĹ%Þ¡}ì¨â Îß%=˺O:oöaòïT«KøTBåÆ8^ ¸êy™a«š£JòÊ\n™jÝ›tð¬:¬}¹J|Wt#Ì,¢óc׿¡°DtNÏìâjI_EuÍTI_“m4oFdÊÆÈ¾¥‹ªLñîê Å;½.(…¤µMê2fcºf߯|–ÍÞ’‘c>žd©CÊÚ®Ï2UAs¡N=%XÒÛxÂÝÈýxƒÃù1ñ¨Q9Ð*@kµ}ÕC6¬UͤtÚˆ™þªÏvhÑeûRµ0b)]µ´Üæp—tí¯'¼Ý.žEõ›â#NL–¡%öIˆ€ Ä“]3éIúÒÙÖø’¯Ì0ÿ‰­Á‰ =-/žÇOB4ÿX§ŽWoêÒ{ËÈ-Ä$öv er"Hzž6­}«VÞ߇J¦U4žÛ™±KYÈÇðh®iA¡‘…á^Kø_r´Ï~ÔáþwNSH´¸æÉ2ÿV%®~T¥‡ª\4Dqiùû²†¼ìÿåccöOúF襽ÛÙ{¥ðJK3ôǬmäÅkw& ´=Þ:½*wÈþœøz¼†ÆmÏÊ‚à'¹OùÁ“{ž½'óc w…ܸÊm>IƒŽNª!‚¡FY¼MØŒð“üîX2ÖcmšW±gÉøç!›B1[‘a? {\ÁæGþE{Ô (ÛßsUQ‘S•¹ìÉÿʨè’ä‡'.;ßL•â*“ÙßlAÞè’ÙÿíJ0:µ¹“Ðy!4ˆ¥°7áöüþ)É{Ή¹‡M|:ŽØ+*5^vͯòqt>ŸCä»é–vDÏ¥d–Éøµ>õwoUfš¤˜êÍŸôܘ5;øSr|hé¹µžW›:˜@…fþ˵:Ã~Oî?÷ä±5þ5uÿ«³¦zä“#X2OÿÞY€’þtFçéM§úkcwî¡/¯}R«ôŸ¦ÄoýâaêHu°¥a‡ûui9Ù2[S$p8bq`ûÄÏ«OAežvË_ä3¦ ”ô=ƒð(U|]/¼G 6ÅÅÞ'x‰i ~ck~Œ¾ão+·fBvnÜý[øê”]£äöÛ1löÊln;·°ÙÛ=ï|ƒVÿ*)$¼níþLém}Ÿ³5#Ã*£D™©˜¸:ðq"ý¸>ûöô³²ªaÖukÌwºZùíè‘’I åJœîÞSl2ž¶ÆtÕý÷óöÏ:?#öQ~×G¢âJi&ØèÌ—´+”]vTMJ•ÃêWÒ.¾w•eyÉ;_ãUÌ,ƒäЬ£ZçÆ¹xÿmaàî‘áòüI7™È cݰñÑmH§¦…KÏì ï­\»^Õ«ªKhÉ—Ÿ(…¶ê†Jfw•3•ÇýìíþËÞÊtnD*jRŸd¥Ê BoŸýîÕIlHF˜Ã@FX¥˜d\D¶Ò¬<»§ò*a@B“2Fw. M*ï@[ÄmGt?“ê}¸–§39h¹)“€.RðéYPȽºµÝÿ‰ô¶½)SÀI {ã;Kÿ‰KP ¿î]5 vïn¹ÇŸþý Ù±»àèÙõÈ&ö»±ñ¸j=5úç+q£Ôð8Oîf x§?=Èü‚zïçHìÏĪsɵ1Dl·6#kë,¹ÿp'vb),Òì¥_è´ <|ãn‡ñÑù×ùvüKÇ=+6Úr×qô¸â)¦'ÒðjÞ©ØóÚ¹n{hrÄBh«zwn]Õl̯”}G?½Þ 7t)òØ&ÚòÒ­¾ïì»Íÿ’–Kû›Ú·²Š]Õ¶a¦5Ô‘é>’šÕ©®wÏï¸AßòÖbóH‡úÐ>ÚõK qü…¹‡©µóOßEõÀ-Þ÷ÍRíÈ$VÐD¥øFפÒfñê¦N]‘'¼¹w¦@Ô›®ç´J ¯¿¢Rêe öOËŸyÝ­MN'C‰RkoÞ}et{;g8&=9©­ÛdÀÓ ï èýéÛûé¾›šðÏn?˜?¤œÙ}´ùîÞöZ z‹ZKŽ?(‹ÅLÖË.­z„[F•'õŽÁBá;¦Pq™²óƒY!Å®fu¿ØlÓ¡f4¹ø™=äÿܹÿ±Iî¾…sÅu{Q1c¿ám)ÞŽ‡½6LV¸ow¥\¢ŽØÎQqòy['q·ø—òˆ},S•èï(ÐmV½Þã/o,Òÿ¬ˆ¼ëðÍJiääè“óÌV)yF™æ9^Ú/¹'šhî?„ÒGÙ22ç†Ý-3Ò•íÚZé‰1gèÑïàšüî¿£GÊЧŸªô6“ÇÄ\þÝ9/)Ÿ¯£ä·›´§!ö·°dþå|¢OÍ··ûº;Óq:ª_¦(æl6?îæqJÃe×ÁäòZßÿ»ŠjÍÒµ¶“†¯3œ;‘¦¼‡éQjŒb‡¥X½Í'éíä~Úò\Žç¾P9;™³´é‡`CìS SÑm«òËüÕì {•ß]™åÕ½w™Ÿ¬ao¿ù¶Œ „z¿s¨GrYÔÄ‚·ßåßOÅK¡…÷þàâ^¥ä¯a0S±HÐ4TŽØÒÉòÆã_$ι{@n:yGÈØC¸·è›Wáý&3Y#éöÑ·k³Ü7¹²±ªÿăì|ïñÍ_ª.»ªÇñ ?¦lü^ÖŒ^êÏ5©ìëËpl¨cé—³Ä[öÿÄ/acüô=õÿƯ¤Åð½0DÅ2´d»æõÿ(fŸËË‚v×Cùi²gûÑé !ô]ŸwŸ'h6˜Ü11ºk¥ô§¹ó)üy*Ix<‰\ÛÄpŸnîñ¹ªaqëF.ˆéúÓ®Õ¬Éÿ,eNzúËÏÛ´uºÜ†ídy;§(þÕå«d¦O|)DßN¯Ú솞¬§¾oÏÓ5¼ÖŸª óÑã'‡ÄOíÃJ°âô~L¥ñ z´ á°ÚÀB†}îÿPºµÄ¼‘Ò—[©ð(•‚üý’šqïå餻ÊúmíRÄm‹bÆÏT‰Ê÷Mß%Îòyñèîáy*ãed­°’¥ZŸàœæ/úÏ|Óž½á²­ ðY«bÞI®;ë‘U«žN¥¶5Dë~bî1Qõ>ýï³É`ç÷±‚IÙu3W/'Ž•Òû›[§ýyÛnÖO%uç››„Å]ë}d ¢øs,5´•liÌÓÈWÔØ1j‘Øâþ(ýÎkGñôŒdüË-Z¢Ã߉»ç- 20ûÄg9ºˆYÍIrðozÕ'µíå00øô¤ô~ªU’Xle^0€&*ÚÏ/GU¦îëaRòõ–\Ž Éüæê&0Þˆ|¯ »Öº=3‘<ëb$Ò_Hz™——÷GCë¹(Q½@YŸlɺ2ñÝð–T{¾–edpÝ&ŽŽE'8§Yoü¨x¤^ÅQôa`ðáuMrÌ×¾.GÃ;ÉLtŸ™4‰>f ½›‘èsP:ìš bmÜò|ù{í¿±åtJ³]Þ $ãÛäáè]‚÷¯y›Ÿ÷M$кdãû »ï<>ŽèöÖ­hÐÉÙŒØðŒ±ÿ¦Õtî^•_ÇŒƒÕÀxñ›~ ¦j§¿">ÞÎâ…;kÉ&¹'Qi';¡ñ)^Ûþ\rbÛÝ©á¿,kS[}‡rªÙ·ê ÛŠ$=eï³Äžáò]Z‹r7^ ”‘ðÂï_ÛŸÓâMĮڸúõvNmH凷vGœ~Z¥nUÒÂý<ƒ£:.æ÷Ë‹þåÉÃ9õÖö›%ˆ²´ÅùWlbæÞ³úÉyøQܼîŠÔ‘…±#ªoã÷ŒÀ¨ªèSGÌ_¡å0|h)v“_2å&‹OXQ.²V–»ë׬ŒêbxâeD‡mãªh*5Úù£Ky®ÚsžSêeï+KÎI4Íߨ£Ù:±bëšvrY¯Rž ÉÜÆµûiB¼ÓÚãa\›b£¤N²dxâz ÔÚ¾ž»J¨É[IÅ•"£[Áƒ>&4® 9¡C{ÇöÇÓ„“Óúö|§yÛFÕÜe/[Ýá$õ‘Xý¯Ã‹å¬U4õ3¹¥Ýü­ ö—®pn².‡'æ™xªÛXµó“p‘ºé{ÞâÞÒV“159¾ï…’ŽŸ¿þÊ]êlFÏ¿ùÕ*äuRç̹”UǺv¯›œ¦œ®¤}kdƒÍ$Lu§(¦r,w~ájN}G8ÌÇ f à­ñ‘ȹÆZ7Dw›ÏÞóÉ )å6Iନ¾ûøÍ÷­eD#RÛÉ+<߯ ÂaŸÄ?¥z3`ÂsQâ-&¾9Z[¿&쥕0yù„Œ^M¸ÎŒÔ¬ê~b‹¦/Æ^vÿ낌¿î–|?·äf02„õ¼ÅáÓS¯°!Á¥«ËuÓ°Wjy?8ï{†á9÷âõ?ÙÁÓ¸U7µ‘½)Uöõĺö¾½Ï¦"›a•”¿ºÜßúåCFa¥__Ù“ÿ1zm¦½4m(Ä;8<Ž©z–Mí‰#eöÏåsÓycñp?ÓtªÌKÐó({¯ìó¸ZûT^2VˆÞ¿Ñpøâ§ÓÊѹ´úSXà©5[즛My´WûŒZÈÿÄŒo,ovz×ä·aß›h.­OÅln×Ù€íÚm úäo–>TðÍ×tô_LJàï}aÙ^½‘VØlÏ'©ŠL¥ôŸÐúˆžÕr9ß=ܙ§|@ ©ÆŸÖZnŠ»ÔÏï¨X˜¹‚å+â·dQéíi9N^ª6*┊'‘iwgb‡,ÖL‰ I8µhLØ~Æ%áj VJ·«ô¡®qóMwCwEùø9—¯ç›S»–Lý¿¼î±ÿ¾Ñ5ÇT"ëÇÁ1°€B‚Çö£ñìr„µŸÊïŸÃ‚9®_ôæý)ÙÉ^Еû<¤-{Ⱦôrÿ³¬y´îÌ”elb úŒ±á¢£¼bVòSÏe†ä¤8Ǭ”è?òKÆ—Ma÷ýQÈ™êºõùtwÑ63A…ìh/Ä:–Ýgk숬ìI«ÂÐ@ì«ó˜TÿðDÎæ©¶•÷%ˆ(cØD%e¦Úlg›U_åè»7'n„mòÄëÀšY¾çwT\EÒë™ áßMœ6ŸhdQÒÏÁô«ÃéU-­+V>¡÷ójCèNO=Š®ø½¸“5åôý]<¾ÿŒ3H€û»*ÿ…Æ^Ö@Þ~– ›üq‡¥!“£¸[ïgûˆ‘ô:x˜¶~æ?–Ójy‹g¹óñÓœK ᪌+X½×WȈ‹'šI2^…ßÛ;Ú:dT“ÁêmQœTrɼ ½H¼lC(N>®¯í1¿¯µ±6†šù-·ñ¹ï’IQèµjèäóTM¤–ßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿá˜ï¼>ë|om¢H  ß9»fu–•´6ºîÛãnët¡îÀÓà>¼ùÛ$´[îstÒå³ÖH÷5çp=µY…]b¨U·®SÛÁ*…õž1 h›`lÀPNภhh€ ”JtŸšç¯¯ Õî îà±‰Þ ÷QöO›®"R}ò½|U–žû»ë§N¼Ù ž÷N§¼ö«ØîúèÕÐ4:ÙçÇßooCìÞG(}±ÂîÎðÍôòPû³×¾ûÚÁŒÀÔ»ß<ÞÙí÷Žs»c+vÓZ›j‘.™²ØË{_[½ÙñuxÕ5ÝÛZRRµ9âï·vñõ´íÃknºåSZï>û¯¾vU3Ÿ}ÛïÆ­Z ¾|ðí÷ WÖ+ß|Ü>úÀ4ù÷ è¾ûï¾û€;çÛçÂ@;çqwß>ï]Åõåãé€ .^.ô<M6ÚŽƒ¢8ÊÓ¼îèò‡*mFص P MiP“AÑÑÅ·\ 9Ž- :Év%„ ë‹ ((; ݨݘ@.ìj#‰ÑJ” Ôôw‘7ÞYJ5ïXûr;ݾtªÇ|ÇÏ·}4Z%OmIK–›hQ;™NúÐìôîÚ½Ç][i¤KF¢A»ç=ço¸¼í´;jä>÷¾b±=5¦]Î1÷HW:¨Á®ƒtÔ2µt×Zª)w×p©› ×.šÅ n᪗[n*wØÏm¾ÍT‰Ñ&UW •E $"R¡óËï;Òµéºʱ‚¥TPú4£³·±ï›Ýñ²šF´&ûtT;VJ‰( ˆ«­ï9vdÒfhÀE°Þw¾Ï‘(CéWÏ,uÔVÒPUT*ˆ†„)'}õ€ “ÑÕU±µÙÙ‚ % }0žŽºûzøg1¹÷QÄG2²“¬!Ø„ŠšÖÆwÑÔå͸7[».›vêõ{éØosg¾}ß{ì÷U;»<¯»ï·¼¡@‘ÀF4É‚bi¦L0L™110 Á4ÓA“MA¦MŒ ˆ4Ñ2 4@ @4hdÑ¡¦“&SÑŠzd˜§èL˜#IŒˆÚhôš™oPÑi©é6 ”<£Ä#ѤôM4ÙFŒ¤Éé14i“ £@Jh ¨„A©€™5OSö¦GªO2£Þ¢Š=OÒzFS'åCÔyA£ÑÄÓM=CGêP =@ 4Ð$ÒHBhMdÐÑ &2žšdÈjcU?5aOSmRMO*ªdôÕ<¦&=OTɓŦž©š™£ÔdÒ~”zhÔzÃHÀ@Fz¡“F ÓM4ˆA˜Œ£@OL††šL1 &†&ƒ&LFšh™¤Æ†$Í 2`™4Æ‘‚ ƒQ0˜š›Tó ‚$„šDÐ?j˜$õ#iSô¦ñSüªoh&šSýMMM‘ùDý(ýQ§éFCÚ§©ê~ ŒPõSõMê ¡éêš=#ô§¨ÓFÐb3Pz„î…â?ëlãˆøoå¢íÌÎÈX¥¹G2/w'{(¿orÇ««>¡K6ûLJ È€(ŒÕTžÀ!ñZ€™ZÕ-S¾ÔŸ­…­úêŒÐ”³{¾ÛAü@YŠÖªˆ ÖªÚÛIGë²å/&Q™j<¸Ã*Ú$U¶(Š*‹E6´P"ÄE™·ûÐìBÿ?•¯Ö)F¼ n+ÉXy¸• ”$¿æ÷¿£öœ¯VñrÖù£îe]ijøÖU19ÉŽ4Ü ÐÁ©€ˆWÊõ8m:~ªÓ½?SÚk~—ªüØ8ŸU·Þx}F‡¿ÿŸ¬uîî5ZˆÊ5V”šò TÅî¡ýŠCZºe-„´¸ÌKB‹Yn`T%pj +ƒRUưY–ÃE+!ü¯ÂÖȪZN¦ µ£; Dú YÁ±€€'@´€zSDïcÊκ'~Šþ8€'¤Šö@r ¶ê=Æ}€/I­¡Úß§;‘‘tÐýä'Ó óîOÅ¢øõô`æºyþ³çXr2Õê§ã™q²=產wm¶5iða´’lbÿ²!ƒüùoÙü³û?È?b]ê⌲«d*«¬uOqm”Y9sWjbªr/&Ê|z»Qw"‡È«”¦é FI2¥Ú.U”βs È•ddMéÛY†Ü&ü¿ó¼ÏèýAéÐÿÚ§ïÓ@žo-É Ð7 ÈNU·ÑjÅê÷£‘9UÅï(‰˜gt¦E=B(WoŠ”©©«m­i½áÛ\f× -q1vºÌÛl͉z©©qæ`—"¥) Š4fmåì¦Wö£fñ¢fQ”žîiòjªœËU—o6è„Ò’h«r¡^R´ñ“(³'˜÷q8*˜Ëˆ¸›¹U˜ït¨z»¨Ì—¥Š&f¢@8õ/¤cç'ó$vå»¶²‡Sæ*8:Ë(L= ÚÕî%/C³¦“÷øöóv”9üZtSèõ”UBéÛʦ>ïí«ïáa(s²‚Gýj€T@I9Ùà×¥ël«5sâT¡‚YB‰ÊÃÀ†ÞŠ+K8=]¼-B`žëÀ²¡BbÆÅ…0Q)ëàt8ÔžÚsz•ü~9CÓGðGÃÛLœÍ"CÆò¶à¶·* +ÁúUdiÙ:$ÆxÆ…8ŸW\›JBsç¹¥Mü~ÇKebD¥?ÛÖPù½]ña䡤¡9(s°ÞÂé!2wԯħŸ®'…Ût6q¦› ¿?ÅÂ$ê÷õ §g ¯”;>ÓS½³µÖ]^Öøž}N¾é'²±†(HºÂDe'/*Èþnü„/K´íûþùsË;æ +ñ„]¨â H Š4P aöYruIŒ™XRõ¹0Zúõ©d²!=t·9Ьçd2ØÀ cTµHB†”ð‚PÉ EÄøqÇû/—ê@À÷¥¤;á—0øœBõv¹ñÇ„‡gs|eÀ…YÃãØ*®O`^ì,BÈŽ)S•F )/9\_ðæìýœ„q?[ÒýÃs3ê{ŸKÇá  ø´ (y¾+ãá3©”¸$~Èšöz_OüV]:”b …$0@ãHÄDF /Ðáô2Nô¤°vçÊrŒ&Ð7¨kø”ÔeÜDr0ä»ç°¨ÙŽY®Ñ 餸{<£H_d_Xˆ—@ü2QˆÚ¼eý1Át/Ó9.`X …#šY¿èég%‘ëxý'M¡ÅSÑýÊ}E[BB„ À€è¸*‡‰û¨ù¨“Ïõ}–“7ÌøW×üù þƒü}·ÿ«xÁûôAøRÆ9T\gþ+så ª<”‹ßw•«»ß´ £¢Œ‹ /Ó€ˆÃ !††D`Fèh€·å‡Ÿ¹Q |ì9enqeK¾Uú1η»òíØÍîuŸé{_I”éâè:¢í©²˜™è?ýÇyròŒ†ÊÈÀ ¦Æ„–—Ý4š£GÐÁáðxÒ¸þšÎkAߌËÙ,xkëÈu²jØì%Á?á$% &[éo‰êÈã`.nˆhð¯_”d,î\í‚»F³XT•í^O×îÄà!ÍMwÙYV&)$ —é\LCÀjॻ'¡#=Æ_O3ÀJÄüxó¬WZÞ ÓPxÆWhšð t·-Ô$¿'µº“±ÅE&aÏΙêuVȇa$/)Ê¥*Ûõq`®Ú3LþVÊ-à°`ÛÖ/6$È06\Ư0$L9ñø>U®?-N @Ð@!`cÒc¼YÐ FáŽPüp%9æþõfÜÚÔx¥èØsŽ13ÿÚÃo?ŽÜ¿Ûÿ7ð¶Ð!Kjë RÿÆ}ıÐàà¨Íß03R¾‘9Åá‹°½•ý>ééÛ4ì±ù‰¹ÑLÑ(ØóàM–ÓÄváäŒÙýf(¬©&ƒ·üŸ½é,ꙟdŽ/næ×ƒÃRÝö£˜þ÷*#¬ö Qã]žêô²P‹QÍ$x(gYpãc*Oçh»©ó·}´<…ù샎öY½-Ê‚ŒžÇ­4Ÿ5cº¶»á·Çä-í0òÍÝçj¯/ ñ}wÜrKžT¬°¥ Ñ2VØ-ø§…³º‹d! ÿοVñ‡¤U£Ý Žà 4pãÃ,V×g\´)šøÔZöo"øûþžj½yQ˜­¶?M»EÖœ¿ô,½¡Ÿu^¾î×ôQ®!nfKªÐÏ<+ìèÿݻˬ#Ÿ™ú¢©…|!ÍÄÝüOYîþeõú°?Þ»Qôóèx=qg£ßÿ2Çþ.¯N¥µ•<ÙeH"½()$Ÿ’EP ²ŠB,QB@ EQ[r«{ßG®VôÜ{·&Gac"ÛLÙ+O¡x•¶nëdÍÁ‰+’'¿ò_ÕWˆƒ˜ES`f|»¿ÇÇËnÀ`š2Úi¥ôЧF#|‰ËG‰ìa[ëx”  }‚I´*by‰ ß©°{>?ä×û|$&Á:‡²‚x'n¼í¼9-;Žã‚‚Þž²¨¶ÈŒµ–¬à‚þô(à€Šê‹ÓEs¦»4®¥Ò¸,Ök5šÍf¤L‘2F¤I{³0Ãi‘‡RI&›Ì7™ÉÑEÍfssÄI“Æîîï[»»»»Ñ¦Žï»Ó̉Äòý±ö./^Âãy¾ ¯Û";÷•ûÐ+ÇŽ“ÏÇO‘Ézîåûà HÈ"xV.võ¯ ‘ÉÐ*ðõ}o vëcn·-´I ¨.!90xéÆÜ»pþã4s²Úí8¿½ÿ 'bŽ™+U1„ o¼V}Ûò©› òWã)«ô]œÃùŽB2SÀ9àaºWSÄ…QÇæµÀøŸÜóÜ9Br¨¾WLJ² Ä*ïHû\]pˆ}²`ö»Õk\Æúæ ïbSd¼ç²—èì\´=;¥mì•[V".¾+Ë5ÈI…g7}˜*äì”C†‚ D=©HM¨ÃÛ¯„¿9u1(Ž$Z·xCšÛšñÚVšqÂd^`-0ÁAF‡}ƒ»´­¼[?|G¿'Ø”F™89K8hWXýžYh o(àÀÚDN>``È^=8Sunuä“1!èú>’»ÓÝ”¹•‚„(J’UUM; ¬V+pôx´M:}JýW#•Õ;­ïoÿ æWMÛE®”‹EH%T’@PbÿoÔ®YFÆÅ¨˜œ×Já²n þM•–ùשÀ§   TIÊ„’Q­±V²©JÙëÏý?¹Ðbü2OÔIãì¿¥”à?¡u½^Ññ!àÛ°‰ÏWÑ Ø@Œ¬”Ä ,=O¢Íܺ±Æ«ãh¯ è"$Iþê¼D,¹Ýsªr_PÛÕŠV¿ŸI`ê©›ì|†^r“îp`ÊINæ Ê50L²ë­Ãp¹š\ÛP…̾‘ˆ@ˆ”rwæWÄGª”Ã^PsÛ¢Ÿ0gAÀ¦ªÕNf¨3 e£–9&øÈhT¬ r¦iAjØ¢‚gå6­ *Û„%VŠ¥&±U»õr†ãs8$Ȥ×× Š ø„ ¡«ÈäirdãP8ú›¶ªk"ò‘)N}•»YÛ‡­ê…xÈOe“ïoÅ´ø ªö#—xØÉskhÐ.2¡(=šq¦èyv£¹vՂйî%p¼“¡æ£‹ñîAÞÁãD9ñ´>Ë}UJ! (æD`¿ˆ ¢Ntˆ{ hp½­&î–(„ç÷ø/ñÌô¯'7 ¿€è^+ë Ñ¡”²Þw;§jº¸EØZ¹þ®ªå§\÷L ¡ g4ï|!Tà 㢟©ù5Ÿn>xeÀ'óÕ_j=†ÜžM êLŠ®õF׆‘ÉúD1,æDï>U½) t|Üm=ªSd?Á2¢Æh“çÎó¿¬G™Ê˜È¬ð~ýqz©²Ö:‹øÕeå0Pî|–Úf¼Ïš†²ÇÏÇ¿{´¢20>ÁðæA¥5½3‚C®TOÞ<ÀnZËÚcñ=vÇútL%OíN`r”ÉÞ¾õéÜñáÊ&Ðyyf•ùæ&UŸ¨¢> Š¢âiRrR=Ÿ£mÐZÕ > ”uZØN×å ßeùöøðÂpä÷÷à4<à¢I!§×v7+ñe"3ñŸON0þþÂÐ÷Œt­³Eœ"jÉ.}RFï•3܆Õ7‰¼Ô’ÂÖMfÓí|I/Ž$±‘ôvãßpŸz =Á6NÓØ°¾é¶©„ÌŸÛ^L{¸ òÑ+¦»——ˆùÆbZ]øZÖjM )úð"rŽ“k ?ZÔ™ôÒv}9\uOa5h¸¬%îck^Etžg›Ø‹#“Þ¿W¶×wi b?¾µzÞ÷̯HTïp$úì‹NÀäÄÒœ>‰¾¿7,æÆu´[An&Å6íTôø”Í<ŸÃïÛ¥E“å‹,IóÛÑÌùruËÍ–Š½¾&{ûìJí¨‹ôš”f3K´lŠ€¸}:ʼºÂåžÞº~V¼:×q×ÁÓ©oVªJøpW¿Ÿ¯ Ñ÷A#}:¡„‘·q¡íô›RC´*0Y=#ªŒ4Ðý9Eö¬3dB~¦ï‚]aiÃ!Å;‡·‰ KÝÙ0”-ñ•ØÐl|Ä’íÍ%n77 þË]_ͭݹœð5\æ«^ü#ý*¬i¸}„ |Fž1õj~T“±—ÝR@¶uŸÃˆÉu»E»mó5•„†“q¼ÑvÓ[k-õÍ5’¿¥AãWc?ÅäÂë\ìïˆÍ.ä}¹½çº­½´ö1T§‡Ç¿Ô#Ö™­ˆà-(ÇÓÍÆü»|ûs)Ï…’ƒ;cÊÿC¶ *¾ò eýVAkKœ¸M&`˜op”•?*ói8ùn^29¹+sK¦Ú˜_Oï7ym{€—†…FâÕÄšT€O„Ra›Ñ×BÜfâÌ9vVŽAûi1ƒ¡UwôåµÐ>+RÜr²½ÄJq“¯>yTÂóÆSÆx¦=ÅTyV@êM¯oP ¤{ù†%—¨l~sI«“s$a‹ÐåÙŠ™vVê tÉò#lð”(ɦ7’Äž¥íwZóO»-?•ôÏyªÐ»z¬y‘?öÕBÖÙ}}Ùl¼/.*Àµ_Ÿ¤µë³€\IeÚò W¦­©ë:ñdð&X´"›!O˜Zt×½çà3ùÊS,₩ŸoŠ1z¦‹  ˜/5'Ê’5¡fÅòåŒ7npÀ‰Ä?kxŠóÇ¥¸UŽT·÷Ց݃òÅæš7Á _÷5ZÐØõ`¦•¯Sm¿ù(”ç^v+z…ý/J š$ÚbBÌ,ùGæ^ýs/4Ã'M€Ë+üø½âŒü–ñ7)ýkUñÄmÙ¹ÔÓ ÈWR¬ºŽ˜S€”]teý"ÄÌÉBÔ¿õõÒ2q4 æGŸG΢T¬'N<#‚[K‰¾úàœŸFÛ÷íçI¿ûÐPùéägx^c2ΧÒ&‹½¦ù‰ìPÄþ…Ño»}³IK>Š9öì¸ð‹f;§&û½ÌsfŸ<ôý°"¢wpì–qA>çgAÈ€Ž>º,|]døa(±á {]ßô¿WþDûÕµ÷²È·P¹Ý %ÀÚRàvöw„k½þèùE¢ò쎼S„¨¡e¿¬95É0™ïG™qÄÄn„’§gMKëÀcZ:~Þ‡qkÜ›®Î SÈXAÑdî@€`Åý-a휤›rºÛWVÉ&ªŠqpņ©)$$5mi÷!ð6äôz=oÿGfî¯Gã›ò¿0cE6äúß¹îz·öNÊOÙ"¤’ É"Œ‘ˆEUX‡²¬‚1E‘ ˆ ˆHˆ±d ’¤‘B°¨‰ˆÀ¤‰("0¶Y"È(¢2A`ÄKdXTˆ‚Ä`-±!,"¨Š XˆŠ RDb,‚" 1¡%A*AJ‘Ê‚£X¶ÛR»MòI5¬DYŠ©#AQ$ˆTPYŠ 6&I‘Xˆ‘E‚ ‹D` Á‘Q ’Tˆ"ÂV@Šˆ1Ô'Ù’äŒ`®Ç/@Ä 7o%'2»§ÐüÌ7 ,å"Â6£»ÀÉí( Ä ˆ‚$‘D AAB`@E„P’ „ ˆEˆ @ˆ°"H¨0ÈiÆIÆ!# "˜íAEŒ$FDDŠªª¢ªŠ‘A†Él$ )  ‚P²E¬‹b  %eˆùœáÐ F1#†¤"ðç‹ÄüÊÄa¯ šßQŠjZ^ÅâNß( ˼ÍQjì"¶›–÷A^0XüŠx92 ù;ù7éQ´nêZaj ‘pСáæìïÕMüј@ˆŸµTÛUÄkpR¤) ˜‘Kê*¬þ.Î/O£¦û8¼ý÷¼¥$9ðV I Œ‡(6gR±<–I„3°œÿ£„ÍP)Ÿ©Ò ªDEbó;I“ÌÝÚv}Kß^ùT˜{²Æ%C§ÕÝgËÀâ3¡€n¥ú¨]œ†ÕA O(† …Âa3ö¹ .TX@@ɤ°P¬ƒlžxZ8 ØˆÕ`Ñ%ƒ.ŠÇ,_’o÷>¿Ÿõ`;ƒævB`î%<øL‘I¨¦’\ˆ¤o2g•^.ì‰Á[ '¾Äîì ÍÌ!&JI¥›À”i P¯/t<›ø½×Ü]tæ-’¢Á0ˆ1™mPùØX¯¯ð-ƒm†oxñêÙ› ÷üQîûÉc<®³™ßž_C±yˆ¬­-B0–éŠäx‚+žZW¿¨|EëL¤ØU¡¯¢f|Gùš9D‡w³¥·çßß.qÁº*Ž0fIe”Ë?þ“ó÷§ÖæÔÅò5½ÌÊŸ0Çíy»°kV ®a•¡j!ß/n³¡ºçF˜èg\«aŠœa¦T`õÉ•»rÝbN?ÎÌê†Î雚Šÿ§ZjxþÃuC€)ªZ,´€ócމîÙ$"'†¶_¾¾M¿}ß»äãŒüñ |ŽÎ˜$AIP$ H?ÄÍ{§õUŸÑ­=P3Xcë<št€˜?„*?ƒÆ=6NœWã¨úB ó(Ž?eó÷Ó(Jä…wD,&cåPá³#³Æ¾t;ZS}V}ò¯|WÚ±ü‡ÖŠÔo‘ňoØÚ#„öÏ‚…gžii›ôóY—ÃëqqœË¸†ì¢+°7‚À„2GsK*"ŠÁ‚ÈÁA$dŠADŠˆª‹"Œ} ¿}¨b﯃éËž¹žˆ¶3Å* RƒQR4ƒVM³ß¯†$ìé Ûd»ñ¼‡0“YÏmÞËæä*Ï¢8¥Ó±ÚÄ7<«øŽ4 „‰v>áòa 34Fù߇~:ª燃à"©ì˜CïQ-º¢+Ï^Ø`¨¥Å]šçèò±ô˜ÚñÀŠå1ŸPÄ —WðÒ0(åQPB«x±xg< 7e…~¾Ï=‡»±GxË‹^êºáf¾]´œ£Žs£õº}П©ÂÕqÚ¾%þwŸU/=}Õ9ÞKо;n÷ž¯F<ãÆ.AÖŽaWl÷Ì5ö¬ÛG üþªíøAèîUqëGôaŒàÄ¢î*ÑXvf.éÖ<ÝvϼS®¬Çst«Ÿ•º¿2Gh\µ‡Ôz ,ËÍì"ÿ'á€éçK ­éÇé³uûÎàïyæh¯¿õÄÒ¤…lç÷™·×l38\¦¨ÏäîçËaôþ—á¨|¡ò(+@‚ê"¨áNa©píPÓÆ½þìBk;©˜PÙÄkìQUUÒð¨ŸH"#j¸±ÞÕ@6Y£Üu}7ck­äÒhG)B"<„Zc_"åèññ=l:ƒ]оàÏ#ËS}îãÑ踊ã¦|gÖÁµÔõ Ëh#‘6³ ¦åq@{}Ø ‚V퓵ñAªHžEÔd^~Ñù„=[‚Þ`ECáêóöòÍqs*fRª\î~LîK¬åÆc{ä;Åõ¦¢ÒžG%L:[ô¸<>oêõÕ—‹² °àNìd"%‚àñÕ¢äð\æNûmÞ\â3 DaéèâàoMF/©ÞxWšÄ ЩӥEO˜*˨/AyCaŒC ÜZ‡vÿìÀ{;G§yÔr.|cÖ–¨ÉoÒªº2µýSÑ¥ÌÅÛÚµÆ5 ‚¦ËE‚¤Pöx€ ôÄWð…@@ù‚#˜æxštåAðÇ<úù|:€ ÎàH…ñú5ì'¯¸¡°ÿUÛxœ,K:$‚âÝ£ß0øƒ ;áâÁ³ÇÑäòADÝêë =o×Ïì°ûo~Í×™AøMQ_´K<þQuEÔ(7Edxµ[mTT¿¸ï£²,"%0¢ (z¼ßw¯µïob¯ÇÛ»a ŠôÚ;+áÁôÄPõ¨'Ôü 'ÝÑðø=\9ösÚmòíʾù æ@i%°0ñ2‚=­£~¢aŠôëPˆ7½ …Ôol|2è¾òÈ[å * ‹ÏÚ{vüçݦ¡ _ÏjëÊCú°=â?ì9×èyÎ{Ûœˆf‡c±Î YÌA€Å,)®“¿Á¢D@HŸŸ‹…B`{9p¤'Ÿ/5³ k)ß_}éŒw»¬äÃôä¯u_œ‹èÜ8ÉñžÝo8]’·øsÅI”ؾ_©Ü~?o¿n]÷Šú‘gÓ6³ÚàøAŸµ¯s·ÌYñ÷»Lÿ7qY^ê95åçÃŽ ä&Q©T xéÔ>py_¤úŽÓJ+DÚ‹é÷·'=þ^”ÞòŽÐðy…u×Ý^í­k‘6Ø%ï5C îàAÀ:®,™ÇuàRon«x¬OJ©ƒé½âŽPDJ`+0 íhp6b Nß‘ÁÝ1i˜±_ÚùGw*]ÿM}qzb­¨:U0­R3“øŸ+¥Ãj”qõfMëJļ9çσßéøNòœû¨r{_¦O¨ Úk÷Sß㙨çxè Eþ6pÎKÑ—Ê1«?ÇèsÞ C_ƒÙ½‰W†9ôI¹¨ ?'˜z)Úy>>?,vöo©·QEO‹Ç.4Õ|ϯ_(r_ÇÉ´z·_%Fá‹^aÞQÉ'A·½+îîuv‰ÅÞºÕŠåPa}ã¥Î €­£§¯lúôŽð¾ªîÒ·¶ßR˼„ÏŒzÏ¿_*qê&e·,ùp~Óš®d`å÷»W¬,Ü+'žÞ¿<¬ŠÏföîôU5Q"ÈÆá°2yË’m—¿’N{•ô;ßÉÂ>Ë eHÝ•zFh=0GIJtŒ=Å<Š  rÄc¥º]ÒË¥`/%} å¤Bš‘P‰âÞÈ>ùùquD ÷° *+?™P›á kïWï,9Q2ÔBD¯~yÆ0<.—Nšê•WÚç>ÌEÒ(H"v\¥|5¤³‚<ÞaÝò,ï{“IºKÙÀE0ITkUA Jò­\ê†$áR6«ßO9†ƒÎùIH{äIã© ;µ¯Šæ‚\y’ Š™Ÿ"˜˜‡jN¼¯‚ï $ý¿yïóð>±õèðÄ}Ž|lyL¶ùñ|yý»ë-ªH‡/7}[fõÚ"°ìz£”öcݹEA>”×z¸±©<`c2:ÏÀGà"ˆ×dMÆê3¯ùÖÔïÙô5¿_gÏs2ytâ"èÈFañeOoÌæåó-<²¨­ zzvW7Ê ;Ñi_-©/8VÁÀ«‰å¼½µ® ÕJ&ÀŒ‚§êaãñúž²Øõåá¿’¾÷.¬ùð}ƒ‘¥Ï€to¸û¨™÷ó1ƒò‘òLIŒ{o~|Zúx%(©ÍA ØzA™èh|®è i®{óòñNÒœ‘–[¬”"5àí ÅG‰é BQâÓˆó³ Î¦G‡s^îrÿšL-¨Úl,Î-q²Vo}¦ðBgr±ØHƒšeÃ1á#†(û¤1$\u; ѩڪ¡6=§3°}άC"I+9¤h 4P9sfôÄdB^ävŠ‹Ä÷ºV¬g|F°ùÖ0z`\S€2øzJ ÆÍöÕÏ8‹ Ê–…Åœ1Åžs\gºÍ9Êâúî¬(;ÒšX6@½xï]\Ñzy×ׯŽß£)¨ˆEIí…H‘§a ‡³XƒÃÅâ5rrm€U%ZÒUÎí’ß rÿ+µ9› ‹o°IõuM˜¹¼å§E;ñ´ZiÀâC·»xqFûô;\BðaÍåÝ%´éÚ%\Ôm(<ðC´›!SeY†Ö˜s<^,ÙS8’ÉÚjâx( *V¯¢fZEõ §¬ëÀ@œu³«Aa^ ®£!î©d •H®(Y4«¨éJËÃ}Z˜rÈÑ"ÁjÕ¨XÁÁÀ‹È"Â@€Q‘¾ßÍÑÒþ½Þ=ö<#ˆTøa›á4Þ×€h-ýÈ™C¾#Û ÆGÀólÁ¤]‡o™¯ól¶^2’Ùü;7Ê ÉË+æý¦)q''ñWјç|w« ù±¶¹$[F. sûî ƒ2ŸiC2Éz34hWF>umq@홊g’ˆh®7é~Sȱ@‚_=™;>“Ž6hß½"&Êi(ʽŸCEÝó\»‹0øuÛ6¢…Œ²Ul²„DËA“ v«ˆ´ZÏ ÑÅ•PFǨƒ.¾æ×׫7NŸv$FmW¤Zw•¸ŽZ†ÁÉÁwYS9ak­Á²UIõÀf [Ãú ËâB‘ DRÂ-ä¦THE“hÖè]p߿ʩÅ.V¢\ç%cÈ¡qÜ Ö=ÞaqA;õz\ïÚQØ(ˆäÒ5;¦X®ÿiáÍÝ£•ÈÿZþGðÁg)góØ-íÃ9iß}:5“á϶&ëkâëKû=]ºe_”p)€†)¢h"¿DE|æ[|ÿäÉf¬û+랢øùµßÓ—nXKW3®1ƒÙ}ÏE`,v¹ÁáWb-p‚yJ n˜¬»y!í∀©|ºô7(†4R!°hv`=.®µ ¼1‹nŒ † ä5쬄Å5.¶l»É­ñŽz„5º)•¡‡”å­}48ëÜúïš .’SzçØäpvMNÙ!à2—$(×­¹{ž5Ð3ï­{š¨B«‰¸÷^²1ÊžÛ*g@Xr#Sê¥’Ûæp¨â|jò˜›R‘/ˆb¯WfªzÍI„œpƒ:—0›Ô:KÛèÉŽC€8 ‘ß5}t¼ï»æÇ‹ à >i#%#Ã’÷¤ˆ¡_RcqÕõWhåX$:ÏuêôJ/Z¨UE íEÌ;­y.ÝÚoT]ø†Œ`$uCÖðR#Ñ3!-"*&áR×h‹ ðݧÍ]&/Xtšxz¬±ðtYòêŽí¨£Áb m½í/vQùÀ:Ë`¢¦Oêè솾ÂòyìÖE•x†¹lÚºfÚ¯.Íê+­Ãâ&¯›üîæ¯!ÕïxÝá…Xdpk±®ŸÙ¨‹ìÖ%Ë`1«Y~Λqw5jg%·»ŽkdË ì ßÞ ázÚ8Å(DwŠì7è×PÓ $ÈôÕ®‡u·b©7òŸ„op³jðo,½µÕ@þB>KÎúYÌü¸Þ2ð¶½¢öÇ=H¬HÍO¬_l¼}Q¬tƒ¢Ü¯Þý{l¼òN–x|~wp%Ðí ‡…—­Ìâб|d4»˜>%´iô'Û€”aåqmàª?(\¹á PˆB{‹UZu}×õªËExâì8lÆ#o ´z7qÓMúÀSn™ãèû \G¤Fïg…VùN¹ÂÓÿ³^í¸F)Ǹ¸c§{ú@ï z …7Ø©†@‚£Œ$".A¾}v¸o¦5Ð:Rd&2téÂ;”pE\EÊ%=#{Èßró‡‡Ï2qlú½Â¢9*ó:uso@^¡I ¨1Ý º Š†L13Ó¥Ïѯ…•Àa!¬$-ˈRÛjØAŠØÙµc¿Ÿ ÙáçÔÙäãÇHÆ•WΚ¨‚Ñ©U‚ùœåR]Ò<]’Wm¼„ôXjà0¿6Š&©tëä3ÖÊ”"sP1-‚ºdb Ë"›–ñÈ Hb5j rT-‡§4YZøù—Èz÷¥6ò¶v8m†›qÙÕ7d¾žµ¦¦·)pž"¨*N˜Í.ÁÂx!w^ë%ç0"‚+éQ~„#`æ|-l§<‚2:#ÁOŸ†‡¿x)Jøª!ÏZósÝÔ{9?¼yê ég¶u«â®p•·! åßM¼ü*3‚+}O¶÷÷(zs®™I öèíûø>bŸ»õ¢:;r£¡–r‘§+5ÙËH›†Y%CB¨¾ñòxg ij1¹ÁÙ/.®À@¨\¢áÛ[K:Å1°lißc¢aˆè#@ÀRéÀQj¡7šâ83µu8(q\*PÐ}§û<[‘;”ƒäŠUÃõŸ;“×µu0Ìߟì(ëèSàüýîÐÂV Òuð™úz¨,”÷+×°oÑlês"Ô%Vë’LvFêòôîÁ<Û‘ãuó9ÆÜpu°{³ŽhžSyM£[ê/?v Q"±¼£„c kp‚ž' EîÖîq­Ã©k¦9Õ7ðÙÒôÆ1¼!\t2©Rõ ”œ„„Ÿva^ö±)BÄ‚9jPñ„ÁâE® ÈÕ Y*TÂý©ÍŒ±p–!jˆ­Hè*˜"6Ç^‡ˆÖö`(yêe¾Î’æ¶1´¼Xn^Iì ­ÉÖ”…V_jËTcãÝj: ªMðMo¤4G-CñFa®PÄ3¼N¸qF&z”{â±âHN£»CÚí]ys>pxX©7ù]K¬€á–‡Ï7Á 3ÞF‚Õ?‹áàé‡Ûjß®ƒ§.(ƒŸ~ \S‚DoË>11ôžÝð:†o¨B{"¬: ~pÏ f!KJ( +vô³Åj1(2d#¨Úà׳‚˜Btv6÷‹ ë ¯3n+kÁ÷m’^E®ë:¢ qïIw”rŠAà*¤ûvd‹ß‹¶‰ˆ TF¦I¿Q|C›&Ë òg·5AÎ.P ¨ÀÞäŒÁ)…^fåÏ@íjû@Êk[Õ0t,¸V'3À=`×it]¼±(í—Ô‰sÃ]5IŽÿL; ǽ+­nÍéÜm_?+Žb0PjÖ6 ßä£|ÑÜ PEå¦MÕB†¦ˆºg@}êí6?…œ¢êåAZi L=léцDÚ äÐî,-x""hˆŠ c†­Ç-)§—d9^Máþº3Y%9`­#­\íÑt'¼q8HÎ 8«-Ñþ[ž-|¯^h:ç×l.y2©ÊèΡ°IDÅXÀirå9 >ÕF}âl(rípxyU¶¹Ö;¤.òtÒæ.§{X% Ýã×Z]ó×/i²´xn“ãÍLÛª?5V¨V;Ó{ò”qg°M<]^êo'e‹µògßúã¾±ðŠÖ±Ý’ÃU©öJ.´ˆ€K§"=×§Ïëý·§öâ+ɾ\ôlbOTGµQ„@+ÜÚô…$¢ÝD(4¶Ò­¶WNeOT '¿áû¿Ð¡üùø´kޏôTï€Çq*!SÓL¬½Žiçíp†Ó/'Ì!8.U­™£ô7ËåÃIÓZ‰S B‹a >ä¾õ5’m349] j Lj†/¶68|øPÿ¯—EDKÿ‰t«:Ö¬m?=Œjß[ÉŸò]{.û›a”9(´ÜûAêŸÝ¼ª<4(”¤Â£_ S3¬Ü©'ªj½m4/­C …J¾¤(ç¥ìp‰4¾u~ñA]¨+æòëÆ[ô­=õÚd-ÂnxŸìÝWõóÃõ2 öfž-"Ïòãé¯?tرV¾W\ÖÜÿ‡ýyìwzx’x{½Ë¸«D¬ñ5…qPS«Wº•ž·~ë¦;k&1Q©|O‹  ‚3(¤‚€¼\fæ5Z.=½³¢ë¬u7­ÔU­™£ÉË.Xv5¨•0´(¶³´ÂÜÁ¬“i˜Á¡Øè[Pf=¤1}±±Ãš=QÙtPDç=±*®úÕ±¯E™Û(¹Ý´¸ÕGAPâ R\`3)zÞ–œø”JRaQНiLÌd³r¤ž©ªõ´Ð¾µ X2iŠ(ç¥ìp‰-¦rü!æ]¢+<÷øzòÎûý¼{s-Á ñ*5;r¿l‚öšvèv¿N¬Zñ¯· V¾W+Üùü>ÙÝþkoœ !Ö †ÿƒ!$€Dƒ"¤#µ¡"2V°T A$½êªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªªª«Þ"´"¼ÄWÚy'öП?¯çṑ`ÊÕYr´¿vVoË÷‡79V.6mÁ¼ÂéÙ¬Ž;BâÒñ)d®`&>fŸÖzÌ®Åö¯þ§÷<»Á¾Ö½£äßbã=û×½kÌ>åêöϵv/öϪvïÁ|ãÅ<#Ê>QåÃÇ;·”|W–w/ŠûÓt÷/høoÇ}îdü×Þ½›¼åAÙÛÙ yÂöÊõC˜Þø?ÏÿÙü8ÆàçyÓAZq\¡Ïhæ6<7YÙO)ÐP&?GP­Î€ÞW4<‰ˆ"¹Â+åèPN¶ ¦Šz¶hLÍ<}ÜåŠ^¥€gð¡ j*e°Ø^Ö˜µéÊgé/iùW¡]Šô+¾ãÄWpqˆ+±]pŠë±æ6þÿKS¦–Ï{FøN H·•psn‹ô?¿þîÚ†êm…é/%’ª'曩ñ—ßlG/³„wÛôÑ7Wƒ¢6º.©ŸõUEކtê}VA|°›[ªT#5q\Ù×Å¥ž˜RÍôÂbÓ|[U¯Û´‰:²0Æ YÄ=ùi]0Æ û©­B³ÎÉW¨UHi\D#P‹F:œý{š)²›÷®Ä1ÔÔywp"'Á…TCÊ®µh¬5¨D˜Æ'O¯§JñüãØÝÔ]Ü[»øˆˆ¿º×ww¹Înîîîîî¶šL¾ænÄ´DšÅãìVN<'}xÆXï¾g9ÉæÏ34Ó„iÃNsw¾ro­¯Çå÷GâÐîyâÕ{•loŽd½Æ´ws‰ÝñgÕN÷#º3 `çìùdó:2Áð|!õ[Ãg¶ó—téK_eh,—isvêœFé¾ìí©áW¼CÃ¥!Ì:y¹ºz¹:e¶йÆA_%Y¨ŒƒAï‹6/TÛéÈâÄ÷¯|¼¸âFo*éæõW5]«œÉç+H{ø—¤¨ÉQ·<“c¨¥R²Ù1 µÒÞJ"‹øÞŸŠÊÐ:Á° ¢R(AEQ$DFHAB0 ‚HFb"1QˆAE¢(Œ$!EPDRI$R)ˆAA_oÞ¯Z‚ºòYW‘EˆçÀùáD†â#DiB>Fpáˆ(â àpàäœ8!p£†˜a¡E9Áá¥9¤°á…aC`‹8A ˆ8ç 0Ó…ˆ“…a†4–X0ƒK(Dˆƒ8PHIG 4ÒÁÇ$гC˜pÓ¡Î"ÂÈØYg :0F”9¤v9ÃKe"‹4ÃHD#Yf–Pa‚ áfH„hYÁà ÁÈ4²K$£(r‡8Hæ`‰,¢ÂÄp³ƒ…ƒa…–H9h" $ $á¢,€F ŒÌPíPWš‚¶ ¡©%CDHãPŠ$-˜<ÂÄxD!b8@Ð9d–A`I…HADšhY¦† šY¤`ãŒYÃ샆fø×‚®5õ–æ Ÿº0&éüoÄAÒU\ç]Q[͈W±djÌ׫ ŒžfæffíÎî†*æ¬]OSÒu•×¢ú½¨•›ys·Ä¨ÎV^»¿&ŒÞ+“™ÍÝÍ×ÝÓwv÷wwwwGgãäìügÉÎ&MÎnîífhïàîöÚ>íÜÄ«ÜÝÝÜÞsœç9¦óœÌÍçªw3•™»›»»»º…ʬÕËÛ/v¹—vZz‘Æši¤öÍð\âë¾×:—:w¸ï¹œ˜úP¸^<Ôdfü´ë¶wåá½­íâo—Ëäåë_'¼ÒšØâë¡LÑœóAã>:;ðÓãÁLMìËT¸ÁÄLjp*‡Ühðº,î¹½ËÂ[iCƒò»Œlqã±øÎ²zµ¯Bë:4æ—ë8äËIOoÕÕNÐàŠ(Ù¾Ct³­Yer#«§½êfÃ7r"«¨ŒÕ·†ÌÌIÖjêÆkÆE-£¬:âÉ3 ¸¹æñO æÖ8Ÿ-+‰­è­zÍ~¸Ó&dWÜÃ[£ª':t!ºêÞ —MtërÁ¼K‰5”ˆh È|¨½ŽŽª1ŠÇ¬É/œw®JÒyÕäìíõ¶åÍß9ÔuËÊ©žºë™ÊæTÚë-ñøýÉé÷7zë˜j/8•Ýݳڭ¬èØkÊQ!ž˜Æzl2´†Ÿ*Š©ÿ3÷)@êÀQ‹E)ë(+ )!Tüœ˜iC°fY!#D‚«X ’n™H¢±’0в,„’O§F—éo3ôÝ€”`ƒMŠ£ûGëÿgpÈIG¥ mH Déø_õ:›lìV\ßFµ*«Ój€€DIˆ€ˆQ¦÷¥óO ’Ìl9 ͼZÖ˜z$Z|« šu'Ëçþ¤ö¼_“ï| ‡Çþ­ÞÃàð`9 †ÖÑìY´gx[Cƒ|N»Šýœï[ƒx¢}Ýññ±œhÜé½_õßYÌE `µü­lîÊýî城Â^9êAg„ˇ­žÜÏ«qËÔì}iÛ&|Ì åü™—ˆâM B<[{€•Sp§ÊÉ hA·ç/¶ñó;ÿ'Ý´Eæ Êvo¨?o÷N_Øêh”uäF[?^öжû·»ŒrˆKïyjý|álÄÆ‡WŸ(·øµÂϹN3GVmR‹\r=CýiÁËØØÙÏü_œñ!ãCðûÿÛü °»ån+WâÊA$d=|>+>\ ±H¬‘¤(B yŠœý:>ËîqýO®ÿ³ñqm‘ßwü—¦ï:N÷Üh¿J?uÿ§j¸{ñ+ ÛJÕe9q—ŠHÜß9dÖåͯJ3ìiÙ-àJ•5ª­oØ*^6°:ÕG”1oksc˜YM[Òû¼-؉­|»ÉoÏ»ãpVçÝ&²(i{¶bºÿ{óëm³±é¼Üª€ ‚?„Í6¡;’x£$®Ÿà(〦:Ød€Šà"b„WŽJÞ+Æí'ÀĶd^¼žf=0JÃxãEOjìßôll¯=èóìÊ™ÞÎÜÒö@\€~u óÿÊ‚ ¥Xˆ(@ÌÇ GìfùŸ®|{é?<ä‡F¦¼fœyš‡^a¡˜§à°^„p±ãüLúrY«ÿ‹hlym²ÿnRS)ž©ºÙáôk ú‘;$ÿ¦Yc 7ŽÆ'Á—犻äÇ«k q²eâ,0l6…•Æå{¿kó»ÿ§{®Ê¿ÌÄÞö{ꇘâ{yï"çÑæßÐÅ–@û0º a†ü-€p=y" O’øÐÐn|8sdôoÙÍöŸ9œ‰³Ô¢hÆ®ï>§’e#ÉÀE…¤ÐÿC—¢I¢ObRî»'^Pm*©†YÐÅ-¾†9!;åYgÐ= uow²´·š¯;h¯8äÜÉÉS?KNÀLŸé¾’u/>ýîËŽ—ÛGå\Ýu†²lLî^Û¯Óã Ðd:èÿšÈ´Ö„…ùì¸FPg]缬ÌÞgF•.›úË=Ár†^‡ðþ½Âð;»Ðê5qo¦ÆöëÉØv2(êêg‘,‡þs„{Éô¦Ã`g:úÉ$üàìq5ä³À›\ü»ì äX!góx¿©?Ïœ¾­öÙ×Ñø¼»BÊöBÏ‘åðh åÞ#<Ìá7:¤´ÜÛ ô« :iÒäåãºã½ŽP“³V[»Ó¥æb'$i¢ÝÈ>«ÕsД¾I1r|ý*•&Üð ˆÁßTq „Ø^þÀt±•©‡ÖV+Œ%)½»NŽû˜A#;*ºðzÝû&±ÞŽLTYü©‡¹z9ƒ¸J¾Ê{¥õùú˜ì‚CŒCX·ö³ÙеɇØ?wü›ZG±ï.K.J«)ÅÄ£P®)D.!|Û4ÌÕôô©Êà«û¼‘g~.3oûÄÇÑ~Ö‚ìQq‹µ»-’z ÿOê5‡K”4ÀñVS RYz—Q@Ûïü›SCmôJã¼·%28b£`H턦Ö~l%À`…÷'ôiúIhB>°Ø!cXSç^Ò÷…Ý‹« J@i³Àº÷ŽÈÎd¸8‹Û 9ƒ[³5wCa{¯­çbb¬K !^õ »ùL¦xxÞPñI¦áX,OIQm{ÕC•5FEا”lûéâo8},Œø}C¥¥àQ0z-ȱåÁªû§eëÔ!Õ¿y÷ÓÐÌyÀ?ÈÖÖEVã9›#ÓÔ8‡Êí"<™øzíŒqlÑSaHh ÙšR…ÅÂj ˆVj©i­ú[L ÷ʨ·À2("Õ¡T®`•à/pÞæm›ã¯= Î*I3ù$³à@ O®Ýâlm(˜½Þ­s ãBB ô7ܶ,I™äç›sM>Œ»tÜGóŸqý|ù\pŽRåѨ¥´–÷ˆ „éãÌöŸrg:—YX{æBg…Ô’ó\ÝOI:þSÌ~Ï?¾=7Ñä|Þé3ÈlÄW ©½²o3–ë-n»?“Ë´Ãl_àû^ïßûwxF´æõa©¾?Î×vôÚ>§ãYt¢¯£eLæp÷¨ýé«¡=žR•C§÷³Ø»N=_xA÷¶„"1"·~åƒËžÏrà¶îú7à ÄqºU|ïoïö7é ÖI ”ÜþĶ©øì¸á|á8èárbà>¦ XŒœå… ߦ—ŒV9—ˆ ‚ß")8Ë ;€€óy»yçÙçY¯Â wwû%W›'âc+pÇ?7¸ï†:Nœ@0ó·^Ð’ºvoÛ¥Ÿ Ý{¯óöpãÕ¬s‚w~-¨hHîà«øôúPõÙ\‘£°-ã36{ü¾:æ¦nÞ”¥<ÜÔçpU¨oÐumøÑúj¯h“ò4õû¹C;p¼zçàŸuì,‹«È„$•êY·~½ÞrTχ·hW9C?ê|¡Ï‚CÖ Ê`_ °žÿÍ÷0ÂÄVEQ6(Ò I¬&×4í…Y½ó‹!PÃçx3~©úR îçpðþßcï}Ì̯qÿÈüaL¼ñçeg\˜1g3cw]æR»‹¼ÕÙ­Tu|ª¹Û Åµ™PL»´T~Ü÷ó·òd1;¼þofuë;:¼Ü¯Œ­Hª£/N^ƒþó·'-W×éÝÉá϶Z=?Ê“´-éˆØÔ’sùüÐ:µ•ç<7øˆxp½œÁYSÐ4~Ó÷”ÞÁù/†…9Ó¼­½ñ%„?Ó|ï(.šãŸ”ñ{}ŒdÏr8õ+cÓŸƒŒaqua‡Td ëà¡õ鋊 îçðPõ}î÷ñùþ ª¾è Gmáþ]ÃÔße‹‡µcÔ,nzÜg+œ¾ûˆ…=øRü8±ËÍÝ›ëØóÊ픢÷Úv#í,ÈT§ÒÃIÛ·|n†;RÙhˆÑ£’žÍkö:ê§Ž¹Ûò®'Ès`¾êLØržéì|H»ªß#z'?+ì¹ÜÂ\þ^œ€ª>Âw¡_ n9Žñ /‡Ÿ²æ ÷··El3ú3éôN’+Êýd)t€æŽ»žR~3„ oUê öoïù«cáôaà[úå³LüKkWiøññÜ4F¼sâ³ÅG“ÃΕלˆ¯*¸eѾ¯ y×K\ÕkõJ†}Š]ûò‡yTs¾´×M{£ß¨ {l!×Û£¢×ËÙ¶ê‚úª£%¬å£“Ÿ—Ïw4lÄ Ê5zSg®ñg4ùËÈÛ¢žú~¡Öò§Rª¼yŠ, Hö=_ËŸ”ÿïëq|kSí½[|bõ ô»ö_\1aÙwß '£º QNÆP§Ûç«A^ý¬Ãî…ï-ʈƒ«³ ZÊ emŽQƒ™%°ÚÚ° +C 8ëkÄ ˆ»×p€%êO±ÛçŒëôí@Ÿ*É› 5û¶•·éˆb ëÞ¿ž°ï’Ab€øœ=">Xîð}wŸ]WëùòæÿˆGèÚcíïI¤¸V¶ß¡Ä΀†_mžÐÍoaS ÕOƒA L[s¹¶ˆ¶åË)Gçã­øzõÂølRË¡xSû†YqµµÑ»<£”ø-—ð}Éèolj~v¦ñX› ED–Ç7Oó¹îµß÷õ=–Ó\cß«ˆ_™§U½±¼•&´Š`€Ið)Êã±VóC–Ñø¨ù\Á»Îœ»’ÄðÂ}pÊèvטîÂHRç œ˜) {))7àNU BDæ²Ä~…ŽÏ%éšP˜7ÉïV­ö²Pм£kéÁÚ~çÀ~ ‡ƒùƬ4ó]šŸzüŠ•NYŒ-L3¹ú?OÈG”øO£æûA`d$§Þñ(‡Æ¯ê¾[XÏýd=пC(øö«ï§âMãî1úÝTj@ù`H}æ(m:àb$ñEŠoÌitÉñªAþ³žÿ” í“½x4âað Vj8¼=ÍS;GWõ}fÜ-~;ÍK‹’óÛGŒöõU¡3«ÞÀg´š´lÔðû " MÕ‡ì€ù8³§ºù~¿ø¼üÀö¿ÇîòÛ·a@HDÛµXŽ¡÷lÀ_òÚ,íRŽnR,‘/(À„~ÕJ‚6'Ì?®_¥æú:Tfþ|MºQY‡™” !"B8„ƒ8/G0Æ  ÎÝ‚®h ®@Sý¬ZwFþ‚®¬ˆ(5Ûó_Ôßûý9'§ÐWväÍ~g‹Ž}wYÏæÿRÝög.®O*qÉøÊUùß9~÷~í½ƒçWݺ›vIÊ1€í~u8g1Ô¿!£y³Ò· kôb޶|;—¯~M-½|™ ßÏœ¬º1êgôI– 1ß{´‘\ÂVÕÎDVkgý¯ ¦)wl½mYm#¬òœÇ”MS•ÊÓN"æ¬ê§’êhvÎt×}ýêðÃËAU•­"‹8ü¸ Ðhm±˜ë6¯Ì ä‘ê¸û'½l*å…]°éhòuÚ鈪;p^zã>H‚2sFvì®!ãŽ*¢}ùÕ„æ)©‰¸TãkíAuÓú¹ÛJTë7ð^ A²‹Éw'ZåSřٞr½Â±ëi<÷âñ#~- íº Ï«Ø^]’˜ÙïÓ8uçG-—a Œ…îºÄºö²nô¸ö¦ÿ ˆ#*\ÂîG6´Dx> bäCê9¼ûÎJ¬œlVr5k2TUoÊ>ôÖ¶»;%g™’¦Ì¬J_Äuž½,$H½4[Å€sèA“ˆ*QaBx™"U¢šf'Úa†üü»Ÿ½ö÷Ä8µ‚'[OJ‚rª$‘z ziF¦51fðÄ$ˆ‹Êüö <lúZ§-8b9l&5¬…VÁ` ±AF"$D$²( Â*‚Ä,T21‹@Uá‘hˆ¢²DTQU‚EÅEU+ÄEEXÒY]ÆhCI]v\Žô.ÈPX9¹‹ò|D‡gêù£ :uƒè×Q‡vƒI(€1"¢€‹dDV0c!”iAUE0Ab¨Š3†‚ƒdDEFÜŠ.-ù9ïüïNûÔ÷§“{g-Ì^7Rä_ÓŸ‰â8÷7”EH¾Îuø¸ßS§%ܼœÇLÃ-ŒE2¤¸òÛHmï]µ¯l.·×ëH¥Ý›X8EgÌÔU ‚—øûÞk'Ûçõû»:ìŸÉW˜ëá1]ÏW=,šwà˜˜â¢“»’¦þ¿å̬ûßèðå\pÐf>ÇØ›F~–;#Ùp#Ïõd ^9ý< ›·‚:¾9¦ ~Žúü?îõ9/¯ìjÌí½öK ù#!•¬‹öûSñ»ÓDO{“¯··¶ÿ[ÑKî />eÙäþ€_kÍï=ˆrÖ˜çùþn[®áf%Ú×î0p†ëô×ò ˆD”«!T\c„-{–ßmÕ¤®ê²öñòžÛžO"ù…GÑ\¶f³Õ©­t -´`=Õ¬øIÐ9:nµÝ<|›@åï?6‚.ÃJ!ðk WeFS9쯘(ŒO•MÈÙöoÛº’ù,Õñ-#ý׈§ê…^\ù|¿­Ô–Ïþðs¼éãÙjn<ø4 ;ƒl«‹S«ËÛSX ?Á›Ã<¬"l”„ݪ|§_ÝÂNޏ¼÷OE)Úü]·¾' n:P1;Îò Å1Ê ^’)$ €Î’ ö+™^}¶›zSÐQ Ð=à<h%”%²À°=)2(€€À½O‚¶ÇÞj]õóCéâú÷”4†µ9š4 £¡ûN,Ú(S÷ã ÍÇo_Õ87D£®@ý-éÚ{cÞ£—^{SÊ¢f³bµÎrã‰æàŽ0㈈xØBÉ?å?WvH“$‘ˆ3”+v¨&¤À¥¥»¹&f ¬¹¬ÀnvÝöu›öYŸVܨ<áÎyýÕk;„îÎ&!¬y-Ï8ôu¯àŸ!9rìE ð‚Rd!Ó¤ÇaÛFõG\ê¥è(¦"Й&iàq£’ÜpsÆT:êãCHã+ìÉÆNƃœ~F­aŽ’@™Ý`éaÐSã듃,0<œ\á¸Ìî;œáÀ™·›ŽQ%yσSøìåKçŽüDÊsÊóQY ‰zÅžZ-U<ñ¸Iáœ?gÏ8î8î'äF tÜ¿~æ—=‘"aÃËÀ˜…°9~|GtE]I|ˆ!Üö¢kÉ÷‚Í»¿2`Q.ð(r wMÓÄ$¥×u3#£ûOönÓ1|Ö÷=¥¼ W™¯kõU+ðõÛi[Öé3Ã-ç1l:.µ±Øí6UM^2Û-Z\áºÖ\×<[ˆð'IÙ|ü°zLëX¾ø9æîšKJ/Åe™}ð烡½\QߦwqІ1C¹ÔŒÔü]ÇžÆ 3»ñ§”ÕB®®‘&œ<øfjòxqA ˜„0óÁÆW|º$ß ü-©m7kµ ›©kHÖA5+½¨¡š¨¬ëxËÕ™z†B—¡hE¢„¦xó…;BkL k ÛCâ¥ÝÍVØê\’;°/\pÅÓ.'Rž0p:`+¾QDvó;jt'½ïêg0L¡¥ óҔ•Á@ÆàõÆÛþqJ†|Ûí+«×êö5âñòc¯šð¬ÿ¬¯3ú·þ§˜ãsÛ}ÎË“âôj+”2€¢¼Èi9ìe7Úfÿ…A^8\EnBáˆA¨"¸T´PV€ŠÜ"ºý­¦Ï_¶~e›_µ\ªÏÛU¾î«£VTäC×ê²¶9•¶¹[Íxš©—#“·qNTbJµÔU`úœ›Äí—»Ì#–yšu ­ª  ä“2éSïY•9œ‹:§zà8÷rµùζ–ÒhÖi¤š!ÈУ–hîúaC@Š+Aƒ’3e1¼ Þ6óœÃÀllmn7ºÛ»ºÛºnîî¶ëknîîî³@æéhç æq¬ ¢Š(¶)¡ÉdQƧ)¬ ²Ë8Çbp‡m0h(áÃXƈ×8i¬Qe”XäŽY-ÆáÂË(³˜6 Àç/™ÍÛ5œEÞ—Ti†±‚C’KLò³7šÛ»»»»»¦ëq¹Îsœç7wwwwwCM4Ó’#‡(ãieK¥hvÓH(£…há¥a¥’YL[4á†4áAeÙ AMšÚÜmmmmmmmÝm8@@ÐÆ“­ºn¶šn³Q%–YM¡0Á¸Ù˜ àí"ƒ4°E†œÖ@ÔI!Âiáà 00²Ê4³†a¦ˆ²I8QlCò(Öpjj!5™e"šŽfœl7ÖÐáÃgЂ $ÂA €ÓL4(Âqƒf†alã‚á†665ã5ˆƒ5¸páÈkÌØpD„XA Å€ÎQ%Ðê°á4A㜠$²ÛXƒ[XÓM4³FÐÐqplf²tÓ\•d„’ÔpáfƒŽDAÆ4$0²Ë,°àí¡e@l8ç9¼ 05šXž1Î`Ƴ9„…–8Y¤’h ÖY¸QÁ¬¡ Ò,áÃNi¤’HHKkknën¶¶¶î¶îî³q®B°•&šs9ÊÒ™¨j ­fàŽ7c†ÒGm c 8ÔI¦ ›Kg8IÀÒCL0$€Â™Žpp³¤šII&®¦C‘‚—3.nPW­A]€ÜDQEQEQEQEHïÁãÁ߃ǃšsNiÍ9¢BG4æœÑ#š$sNiÍ9 ‘4$M Ffglss²¶S?AÍjpnÍ"º8ŠX0¦Ee‚cÞït$¦uE¦¾Ðp½!-ø¿Ÿ·xеØðë™Ö¾"Ý/ §•åÒœŠÓ&Ñ4¾D©Õ©+Ë+&‡Eð e¦!“)€üfªa 6¢×´£ †7Y§OGXM@¢ @x¨ DFäüË>^nv‹çt”H´Ÿ'WßÈâ3˜¬ŒÌSæ]1¡’ö¸QXW,‡Ão‹Y)lç!ÖB³™¼Æ½$’.„`º[fgÕÖóès:³*¢+• s mºD„ CYª¢"À€° ‹Q–Ó:Ô¡aÈnÚð’ Žd}uÛ§¨µÙMÚðvh–вª<Üÿ“Ì}yáë0~~Üö>òž'âá|/EÊ\¨ Ö°Þ¯ò8 t3’yV¼CKþÿ6§ʬH¬H zè´„„€ Æ,Š0`1‹ À¤Š'ü»AÚ4€…`í(ÛàU HA„‘¤+ZÁKåë'R"»á·h"»ƒÁ½fk@ÃpS2çCZzZùpŠáþ΄93{¥Ó”j!î 0ïþp‹>…Ðm)³8-ª•… ~;~ĸÞî÷ôÞtA½A (ŠùŽ›þª"¶ ‚wL "¾ú¹Ô5Ó£• 8zÊ¢ÌòazL—ñµ¾âèÑÚX“y}-qa«ì)Ìw÷þ{ó5Ûœ) ˜d5s¤€Lê4µš “p„‡fø Ëû{þdà 2dD€q?ÜÌŸSÂ/‹ÜÈ»þ‰GIF‘cF GI12Q(_ÍÁ ¢ ™þ¾¥å™jï>k™ÂçTÝgw¿}8å‚ ²Ê4²„" 0áEšpÁÎ …”P@„A$0®w7 ½¾i´D¤©Íœu2Øcjñò,žr Ž6Ñ[™svî‡àü¾G5ŸïüÓºzü?[ä4¾¦ÕUªOð"Nú÷öBø°ãÅFQ3÷_íÿ¥ÛÛó),dU„ñši­`Á¨4d1¢zi*#Hq°6ÑCŸŠûYÂj”ŸÀä¬"°`³–ÁÑÀdòDp”$`"„?Üd”a(E“E¼ÜH‚¯‰¾²b*® ŠV ¤* ;PÄÈŠ ºnÒÀ(ÃIWB±HrE*vošvB«éu…iùz®:Õ¡Œ™ÓˆÙtcYTÿÁQZk:=h›cld-¿¿Ñã]Ó3£P1-¦¬‘š!³) #‡Ä¾ÜŒËƲYÛÒÊ0¦~ †D6ëNY4œŠ  Q§[[–ÍÃÑÎaFhJP®´Þr¸üݤ ûûÞ2ïQÑEÌ--!Ý”öÒQmþJÐ@|ÀñîSòØQPF,Šª*¬UX«ýÓEˆ‚ÅTm(Çæ%"±QD aü4>í ƒ~ëœïëä àØFÔ:BÐÁãËÙoÕËñó5\lì.l6%vå•ñy‹[ ×6°Zå;U¸ ¡M5 NãÖÎç?£…j\vÈh!‹0³©i@$+½œ®;‹48#HSI†ìÍoÂ>²çF!Hq!“½ÝVá}œ$uTêzhã )d® Y¿Ç«¶/®œ$±BG‚ç0Cöµ9 XÌâbtî5x²‰q¶ø? iƶÐÒ'€†dÄæ”cQ1 ˆ"”å7ا3A€ä,Ä9†¶˜pC ,ÃS¤€B#Œá”AË\çÛ¼ )¹®g)4@ç¸p1ˆŒˆ¢Š!Ç>|a…Žâ|v fÁkÁ¤á•F8Î @¡ ‚‰/×ñõ¡æJì®4›ì²¹4&"G3r(,9Ø#êÙÁ{Ú‚Y£¾N„Æÿžƒ7† P ]™µÙìå5[öàÌZjèç£i¸y{LÛÉŠìµØã,ͶžåÓrvÜŸ ‚r/Q¾ŠÒ›­†ÄUÆÅ¨˜?Öã±$)¤â>^g bš²²®Ž86Ž0ä#ˆlÖB–Ý]QþkZ˽Ö];i»kFïû_õ¾‡à}ø!Ãø_¿:kö¿¯wóï˜{£­À̹¤Y‰*&…}»@–A—böç0‘dmIˆ8 „Æ•1Ÿ9-áݧÈ#ÃCúèm™#{1 ,;+ŠJƒh]øÀ†jÂ)öS‘”œã T Ê•La Waª/¯ ÷d”Rv~<ãŽ)"¨Ê ¾ë˜ããø#ˆmLÀÓNn¡Ðï6uÂüGRÒ¼yùõm—òø½ ûÉü~œ‰¯ÒøÇ<ä°ž@½¿?ݵ­±¬”m°PR ª#Œ£ ˆ²,TbȲ’) #%H âü_‹óÿ ‹£ïõ…FñÄœutÑmÄ#N‰³¢rŠç8!–QMGÐÂÆ“N"ˆƒJ'ƒQƱ`ö`ç0ÂÙ ƒIkÓƒ–9fØWÓåðÊi>×îÏÞ?í›í3¤#àÏ ñ‡$_v`DPURdÄÿ7OãÇ­Öyþ¸Z\éÖhn×s—N Å[3äpd)ùá; ïkÁèv—ä[»{¼á±ðËîÀ‚à¦Gº`w bC˜˜oêèpDÔ1ÝM0ýY|]Z…ðk†§c< b ÂÔ@)l‚BȘ† "“Ååíþ{âVYýðÈ jß·?T¡MŽåeQbfÉpUEaiaÂR0Á÷Y³l&¥1” Ð7‘³@ˆ lS`ˆ. ÇH ÊpUX2¾=¯Þ¯u¶T+aF¤.Þº^Ô×Y,õì""mªL„¢6Æ$Jzl )²X“B,“pÓOSa‰ J,a¯bÄ„a:voA6÷ôÔÌÔë8©[×4Ê´tꈸ1I‡ƒ}aûF3H†FF>! L"FYa(ÀaÇÈš )²#”l(ƒLÌ‚±‹&–`È!fÊ•ÏgbpW~[ÌŒÍqSV®O'S“ƒ# Ôб¨ZÎå\éCQ – 0%;<”5EstÑž~ßbx–ý÷²ae-[‹ V±P§œ»ƒŠ ˆLÞ'¿Ñî$O„g—nçšñ8lšÎû(ÎôÙ” †‚(%Ʊ$›û™lR2ÛËÙÓužT¶šHyT±‡ŸÐi²ÏðnÙ*tÃ1HÅaï{ÿ³ûÈ©¼­ßüW¢ÚŠ¢VAaè•´EDT@R,%¿1~Ðü0߸ý½ÊˆìEQVæ°¡´ä8AzÆ’mVï 4FÔÜ4¢‰(hC€ÖÐaÃ…0 Íb)éFÁÂbŒ›¨'F‚Ùˆ0Ƴ®ˆ?EŒÕËÅÁN»Fÿ¼ñ„QÚçñ¯÷m­¿0(šÀ d HLhŸš•÷Ú§ÒgÉô7¦7TóÌ?Ö—ß_i–p3,]\]„Ä?Hrï¡G(`°Mð0È)`df!‚DC…AOµÖ4"Z*‚×`îÒU‘œ+j{3ZÓS°{Bxð•¼t3;S`uLû®öÅÒ=¢ˆ¤Hž6ȃC Œ’¢¿çÒdÐÁbÆ¡b)Bk¥†â“"`ˆŒ¶eP³P%)ÁV²Q P…uö»¬ — 9;ôã‘©D#>mÏ›-…ŸvIëá#áìé  K @½‹œéo 4‚çu ‘Ô‘i’!¬ÈC Y‚ÿð†ç¬êM®@:q6GiÀ eAYWG¡¦‡<:CyÅÖŠ#!—¡,B{BdOB𦒦´M&´BÌ;©2Cì F!` ÝR‚Q'Õº¿?~ôÝŽ97Žî®O Ùß;MvŽÛå© âò9\Ò:@£Á55¨ƒ A¤€0cYå`T& h<¹ù;º6#8ߢv—36M½ôoÓе¨:ìÙÝâ7Üg °ÃjÐÛæVg ØAÑBÿUÐýx>ÿëPÓdJ ÙÄ1Lú•@éѹëñê"F#ùÒë4wUvÑцÄ`pp 0äÒù~O» 3âå`±ƒƒgå뻿âo‘¹5ˆ@$«cÅïná8=Ñq‹ÑzUÆð·&>Ýè1—/"–V ž)øÇçxþó‰8¡È´Æ­õµ&)[K"…ÜöR¸{°¾½¼ l$Ž€rØúÍ)e7üºJ9³¹ÓòyìA$Äq´áiÁÊ hÔeN®NA’â®:Lœ‡‹Ýy´òsPp:ç)O'I‹©}ÎIËšÕ´3¹{U¿ØÿKÜàŸwg߬`¢yÛ"bœü´/Šw7Á3QÇ`Î2ûVÿb§« TàHŽ}vëT}iåIg±`¤p#Þû/© ½Õ8B82Í©©êqþÆžDÓ0·CåVë’YðARÏw€Atð#Ü>C‘Fe`@3RT€*U ÓÏàë†7??S#Ÿ}”öºlâm Ž\8‚¥€ÌB D¢,úæ` (,¬…c$6ehÑX ˆÀ‡½íöû~{KÏËÚ_Òg¾g©ƒY»w<Ä°æ ¬º®¡²x`‚Ê)©¨ÝãA£˜a&hYEˆáš@;œÀà@‹n5Ø;PY¡d™DèÐÁÈ€º&ª3Ÿ[íÇæð±w'»~¡ß¡N/.ê||jdv )îþQø{^º‘c……2à˜fb&çÀpè™Ö[ çÌçÏŒøé.)Üvlkj18ŠÓDT’Ú0Ô/{Èm†e”@ˆoggÇü÷ã³Ùd?°mgàæÿ±ß‰FÓTÁÄ»6˜/ïp;bHa¼$À<¬[  À‹˜ŒJŒ$ÉJm¸NOÈXŽÈàQÈèjtÊb×Ãxäo,OеK %F= ‰äØÛFÊY½*BQvBÀWKÈÏ#ec•Ça‚Ë‘¸Ì£qÃi 1Ä!!ïgµ@âq¯G¦ò7{à£N((:AY5t›è7”Ö#C\.†[ËeªðåİÝ*÷¡X–jEJ¢wBaÁOÖËkÀé´š;*X…K¥5TbÑ4»¿ŸÌ¯UØC,@²è:Ý”jQÏ¥3ðëÇð|—XF`QLÌEb,…(°R!Ï™æ6Õ »Ökßw ž/y⻾õÚ PŸ“xçyE4èüOx‘íÈàýóáø‹¼ö;øQ`\ô¦´ EOf¸ˆvô¿ƒôܰ&e ûo}Aü¬0ᄪûX¶õæ9È·Æ?„p‚N‚Ç$ƒ‚à Y‡8AÑÑe‰ti&’QèÙ.äQ}aÕH’hEQE?ZågÙ}Þ%q›¸Éó—/Tgä]ßÙ}¯áý¦\F¡ÜÁ÷ˆ"©AŠ÷r‹L͇ø­GÆêǰ¼À?’V–½D»!¿ö?&dO“ç™ ·£ç _"ßÔn°}×}F Ñ \uOG§y}ÒØ¢¶çÓ¡ä\¨CqSË1àqŠTŸX ,É,â%”“˜ «[sͶþfz¶ÛYš eT«î}t55‹Ø¶‹pÆ0ácKr+‡Ü6¶¸YC8&&[Z™±³Â8"Nãe¶Qg `‹fw ±Í9÷Ä6»“ f¬:4i\¹kë–«›öJXàÇ^ŒýcÀþ(sÉàyç1Ê.¢ (S2Òp;bY”þ²fö¨rþøBh ˆ‹˜”SPAÕ[e<.÷Ò&Ùyø{¯$ë–IEÙøAi„™†ìâz›ÎO¯ë¾W·~ªÏcÉO0šT:©‡ £Èált.x8÷îB¦¹b®3z¾«N9„(. ni£º!–t”g=ìÐâtÊ"£ »¨RúsøFðw‡žI=z'‘Sñáë (áGêI̽Ú:°Dè4De2µ)ßg‹%G¢t‹¡’wû<ÂÕížíM¼¢„Oµjó=¸YCAÐǃØ®šÄŠ3&Aä‡DN{^áƒP8ÑÚ>Íé7\§>½¦5ë9ß7@ŽÃ>XàbÜ’ùÜË7^Ed ¬Ãaˆ¯4ïâ],h*‡LÎ*s³«Ù×ΦŒ6 îV]®DœøÛ;)eÔ¨× ¹“&xÔ*hÑCÌ:æfd™32gK›÷Ç]Y]<^V/“”Dƒz:aÑGGå'w²Õ^–›öæ"›¤Æ^›s×&äIÈMŒ %Ï>`œrŒ_]ùä ѼÉ;4¡Átt™Ç½µ?0æ¼ßŠùgñ¿ˆþËø_’ýÿÃÅð‡ó×ýFìmC ix Lý.ŒÖé¼?ÝÓàÅœ6¿nP‘d@8´Bå @ @¯šèñÛfö.àÓ<½þmt½-âYÎÔÅ7x÷Jz—ÍþçÿoÃúÿ‘õÀù¿TÇíÒäq¥ ŸWæa¶n\˧.¾¯ãs<1/q£Í’3ºâݵSÈàs²ƒŠq‹øü.XŠã‹ þOÊdL4Jæ±”(¡F€"ÅŽ‚&ÂE¡½p:³÷©~±ÀÃ3<Ñà¼Êµã”\?ëfÚÚ}4¢Žy: ,c’8ˆ’Ž’É Hp£11ÀQàüØ[pwNé8¦eäšç3g‹bˆ¹¾}ãËVT˜ë"´ÉTT¦>çŸ\vŸ—ó>ß¼õi/‚-‚íÊ$],a*¦éÂ| §×{Ì7 jš½ÿÃh¿GŽü #çõ{^lC¿ËÃêðC²24•¬Å‚PÀÁФVÈ*)†€ˆ)FY`±DEWÙö¼|½®y|G$ùìÄüíóŒX! ±¯. ‚ ga1„Yq rÍD’Ò×ÀÊ,ƒ\k qCi¦DÈ &áÁŽC™Ì–k$áŒÒHq˜áB Ó•œ\¼á\3ÇÑöÑý,ô¹×÷ a™¼½wÜIè0‡0Ñ«èôœ£S.761¦_¾üAÏo­û •%¡BÇ_K¦ø^ç£ç?÷‹Ï‰Džü"d&eÉ;82hÖvoC„åÌi׿¾²vv f=iM', µ˜ÌsŠa—I‰Bæ»0—s yS^¡LÌO‡(°µ«¢ÝÄ'æñæÞÞ“ŸÒu›ÏlÀ|c´{”!ú^ÞºÈö€è繃xC$Åü\Ó ]LPià c èB{B´“$’vtÀGK´×܈èò@ýž"¦(š5®Xpr‡bNIP½n8ÊÊÝÌÅ ”BcRÙHR5˜W ÉÅÐlÿóàþÇ÷ýÖÿµûͽ½ þ$Äñy:r/åAçÙižêŒc 2º€'‡u­—(ÃöÍÁk—ÙþEyë5ç‡Æ‘Ü~¢T´ZÐÍ+p3=±väHÖ1³gIÞ41šG$ÇÇ" Um¥¶ÙJï6öKn¬Ûûïîï>¯.ññ!L:’3—·om.³²ÚðØÖ–ò¸ˆtžR‰ŒB¬$̺™–YS:9×}k•cÊ„ÑõÜ‹qØyþ/Õü^ûfÞw\›UjœÓ†šQe‡8Œ?ŠQ†šp èD ³€æ˜Pä‡ bH‹Ã_ +‚"*.kEÝZwçIÌMoñ£«[GC8¹H.WAò˜ü®ŠL*¨ò/Ùòtáj¶a꤄µ9ÍÕ!*I¡é¿ï+]¥ÚR‘¤d$U FC"5EIß×àOÎyV+Ìø&eehá3Ç,³-Fa„5ƒ—†dÌÉà °Š m 0B$)¬ ’Gl ¬$“’ÐÆ’Òk4q¦Ã(j,¶±Ì0­eÌRTQ”ÓÅp°‘ê6¦&+ëOLR±º4ªa—f¦ò9×ΚT˜•l¥sÝùIj38k{¬ñW>ZA!%šDtI™?b rH €ˆw)àƒû«Ÿð Þ¼9 ºŠ]±ãC‰wTs0jo.‰6!x^%@ÊÊàãuÔëç-¥MäæU±Ë$8[sÞS;m.ieG$]¾Nrå|o.’9‡ C äEŠ”SÉÈH=¨Áµˆ-­ng¿Þ##"ЙSPl:s›á†›)³„L§‹|]èˆ'„Ñ&žº¶H´Ètß}˜¡%ß%×oåtÔ9DŒñtôU×q>Aà¾$“†¶–?f7»Ž‹ ”¢f&æaeíÂÚTS[tí3·~š<Ç}¯ -ÓuF–ÐaSÎÎ;ˆâoKÒ=*Ü숀ë×Ç®É,òþÅÖwè‚`ÒG0:ÁŒF#Íé–Qie–Ïg··~‰¸ö?~bO+Øì†£,ALFC‰ u÷¡JŒ®j¢÷×>Ž'}uñû¢"~·Ëù_BÁÒ9M#Ñp?Ÿþô‚,Û::ê%•§1qO³Ð”I€zßs9|·ü׿tëµD=Ë2+¬¤²@€+l­ QFRÍÄ„¤‡.;¯U¨æ)ÉuŸC”9 ɤŒ§+g ÷¶o§ü>·Ð…ðÚc!Mí rB;HhÊÐÑCE[Ŷ£·°AíÌ ‚Eâ.Ef¡¤è=ÈÆ ŸÄ¢&ûÍÚÔiF‡,pÂD#€Åˆ²É$²L A‰€"‰#$z¬¼ƒ“vñw¸æÛÄÜÞ:¦àžÈt›\æ1ÄJz4ܹ¦Œ\Éä¿3–èè·äT‰$ÇüoãýñÖùÎ?Šç(þ¼ØíülšÅý»vnñ´<7Å]‰¶,5€˜"ÅF*‚$X,€2„má1á]~Ájï¹COv\jhÎØ;B̬8ßTa…´· ,ÓM8@IF”ÜD!Î cXE ÜÈaaÁ˜@<Á¬d•}s”ü0s÷'Erº°ã÷Ü8å–SfúÁùˆ¤î–ëáæ¿‰'u$ É”xGÚëŒácpàwmáÿ|ˆa Ò:ê¦S‰&HHHH£›ãü7~ÇÇ•fr<™RGÇú9‘à÷ÂO‡mØÔ{@¿X8ð“ŽâLé&N$)ñç¯eÕp:]óÏ*Nrrm¬Ceì°‚“°P9ܘK<)m ar:ëÇÍëÏMd?]—4D5žfÊ%¨òÞkË5K@ˆ9.œÊþ¦šºviñž>>Þ,²Ç""ûS.ûögÐÊOk“ǰ6náû˜qÙ«¿ÇEΈ‹äôÃA'zí‡lt礘kD²aß~š8Q‡i§Á~)Ï7^.ÙäÂmi?Bt$!¤Ç©=(wõêŽøÇ‡òx¦ó éö¯™ìÑl½Ý/>Üö vt!ÜM,JÂ…¢0àïœÊšë Ôé:½lJ°ÀäÓ ÎÁˆÁ–‹P‚2H™Yâ²±‹#ÖÇd·Ô‰ÎSNtoèçnŠpjŠ\?¯8ª èä0ŽË€„[$[ü·{/Y‰mìòœ½-QüKÍÖwcŸîïÂßs©‡¹·š6é„!5Âã¿Ñp’0’Éjf¶lÀ³ŒQ…“¤4"íšJ¯Ô?›àÏ×Á×~tòT'Šóäáæn¡«”AÂÂŒn„É“&dÁúâö<‘Ñ$˜½õ‚rfTvÒ\`9„eãp“GOøÏ™šˆ@ã¦gõ°\ê¨x¹ºë¿^Z¡ÎkcWCúî&»¹Iã*ò $ÓÃ%¼22f;K)hR”)ϱS)Ó²˜'dN½ŽÆh+2&YÁþ‚Oð¬fðJI$šFq;/.;/#¿ŽˆòTD}^Þgž‘禓!aêK<Ñèx‚G’ù¬À"D½»ãvv!„AãÇ…3E ³Ø’B›1 à;ˆgv@€A&ãô#‚nb¦ØÇ!®Âí¸ a0‚‘å3&A³oú?8ï§àŒ0<ö”cGŒŽQ'Ń, ioô&qÝ8ã$$ r;ýï¹~gœ@æ3ô×táîÍ"å‡yÈÞ‰D*4F ’V%5 çJ…k­Hרó>¯ùŸèpçý'Ïÿ×Oæˆh&­œ¨­‚—§9ZIà€®nEK}â‚{,é¢ùj€ÞgY¬"a 2áå¬xÝîüãô^ÏÑ~ï¾ì;m‰»ÙªHÊׂœø~¿É÷y,_ÞÑ0ÅÍ¥ŸV}þ.VÖQiõ-6ÉõDÚS‡îÏÁ›^F*ÒKkÇ"j0šþf¢L>%’Qg᥄„Y%˜HŠ‚ËÂÁ@S7&äËz9Vr ½l~ ¦–írTräT<­1ÙÝ–j*TÜn¶Îá4É·2ZŠÚ4Œ]'–ÿ¿§±IÑC/}­£íØ ®yWñä*ùþ÷d¤#²¶ QÄ G»¯[÷sµë¶µ¶eÎàØKk]3;"" ( ³ó0Aab¢L0§nšÍdGDŽÍd88Ü8Ü9vpÀÀÃFÒt(¼ãÕÜaæ8çCµÕMqËÒDÖUŸÃøˆÚ% ZwXSˆ¬.Þ}ºNÑcŽyHwÆÏ%Ñd`òW `B;q¹$»  ¶Òy˜62;&a2‰žùWŽé«±Ë è©õ'faXÐYᡬðÐ&BΠκçNÚDÒµÜVÞIå¹Fã5v#±ÜqÙÎ2HLoóÞOÙÙb!Öx ðÎs±­pLr4s€âØ„»æÙÒ2Rw' èÛ1ìo^KðÇ^A‡4 <¢à<ÞóÄóÁd7^KeZ çú^»è$@Lj~xj;ï„3Aß`€„‰R( $øª•ªk`(’ @2Xúµ›J%d‡Ä5éW×ÎF󯘭äî<Œã4:9FX÷µ–!‚€É`!†=c=¡kò,l¤Vª MkWÍmÈwÔk%Ê€˜I¸¾iá€{ƒˆL~QcØWó¨ QÚlù›ËxáÀô¥ “¾jo^L‹°Mž^_€!ýÏ?ü»z½xÖI@ ât“R©#SÁ›NÉ""$öD‹Î…Œ¯»Îî×]À!B „A ÝŽý»÷õ”;ø·KÊcÿr¶Úm4PVß¿q57[gßJR„ÉJ`°†D‚0e{¸Yƒ)ñj@’hº,¥6Ei­Jh³ÜÀÙZBIMƒj¼®ÙmI¼å£|š2#ÙqÝ ŠÐà. ÖeËå PQF# Ã’‚´X5óìÈÁ€þ׳ø¶.lR–Sû.N£6 ,JRv€ÄÂÊ §û]v0D5b‘«†JRÄ¢`”($ÉLdÃÄ”0¡“áÓDЂ*(j'š(yð”74HŒJ ÎTØÒ»L«e1\2S2Q˜FS 0¤³ <Ú ¢3z´š”Á2S|VÛlÈ”²”Ê´ÉJXŒ£Õe…4PȘ–R…(… Ì1[…2%,å…š>¸QGVÛ©˜)1¬¢S"m†MUҳ̉±7’nPÉ ¡b2œ+†L% Ja…«˜a†LÅ–z~Ð’ùlØ67tÞ,Б¢1)¢‰’³@Ò‰£S a’˜z af)DÒ½MMh¦N´Ñ‘J'‚ljQ—YmÉL,˜ÚjP`h”,ÑÎÌ>Ïu Jo‹ßÓaÐy7O‡ÉíÐWCáßòsÛïêî½›CÑô%)¨+)ƒ©É—÷¿ Ê¯îfÄíV\Q4O/y‘¸fÁ»·J³n'1qq>-[œz[“Þ)É{‡ä;Ò½xºœõ©Ÿ|@êä§­Í$óW×ùÏvÅò .V[8AÑ`¶oAM®mâä ‹ ¦²ÁI/Ž_—•0‘*m„–+–ˆ[R%JÅ*VJ‚ H‰ †‘"‡iv¾€ÞçÀP6G÷ôûín¹v¸·:×ȼÂ!¢ÿJx ƒB€À$ À8¶W$ïãbšÿÔä{½´O1dã‘·“VÎZ§Öô1[h×üCû®aéŽà9ý¯Y¶ü%ôÊaW£ `C‹f“ýx)Ÿ±6 îªþ‘ábPðà¥9~C+õåúÍÕˆ7M5íÎä³IFBcљޙ^ê]t0”Ø›úè9ÇÆp}¾hž˜ÉØ\¡éz^WèØ`½¸²¶PÄ‚ï±ùm9bÞ‚ûÉ(cT]öæ-ÞX¼^ÀÅ»÷ɇ# @(A ý2‹«&Ïû .µåÂ=¯u¿–ëíç_Dý ÜXÈIÁ8¾©p¤ÜçpÌ~’÷ó×àLØŠÑßˉL_o>\Gæ+£á èÕ6èû¨þon¨;ŸÎG[u÷æ°âüR…I|Q7íÃ/(ò‹Rl“ðŽºðªtƒUŒ–Jæb‰¬±ê‹Bü udËa1…`T·äà_ÒŠ°Qá¸Ä U0]ÞOêÿ—Ë0±F «Ûö9q3·æ¢…t¾¾Êt±R©Ÿ>ö·•nÑÕþIq²^„¨ÜEz°÷1¦–ò²dv¾Œ\|¾Ï“‹Ùa Бy”òÆDw‡‚P^„4T¸Òt.uÎ6Œ¼‹FÛATÃOÁúqTÒÇ*ܺ§I?,p…»Š”£ÃаJ±Ti[ø~¿ßØ=¯ƒâù½&öà=|Ìž'ÿ5g 3%%%)KdOÑC\U8Žº‹ñbq±Èðé«‹Ò—EˤNvà0*wzäu84ëýq=IÆ<Ó†åΞaµ“ºì JC:õ HX !¶9€¥@Uåž[ôWøýÏÅô\/ÎåTTz š¯×?{ýÁC­±äÊõvœß’ØR`—Áÿ9ÃÇ9|µX¯Ë“Ù¯Žé¹*¯¢}ÇCàºß¦¾¤¨{¬¿ChtDp¯ój¾R7hû—ýTïž ^2¦{Oì°³«øÐÆþ4@"gnT ƒ²F½XIÐá=ʸF0¥ ­¨3t!] ´”È®SZ-r¯ÝNr¡Œƒ“¶žX>©«l‹OjÔcŰgdÊ~¶­=~:½Ùp¸Ï¢o㽡+?Dì¥Ù·lµb øØï»e:‰aÍRæÛãi¯ csغ„\¬ëÎ3Œñ—çèùWXÝ8htA› Æ×éÁëVº‘XE^ŠáôOÓKº]mõUkqY`ƒI˜Ê3ŒÝ”MË‹‘,)G¡ÁÚHʵñ©ÿarý›Ù£ØävÚBp†‹Þ+XFýw¬j|Ùç8Ñî’ãMû­ª`ØeDp:ÁºÄ`C©D›TVí÷:Zd%:Xu ïŽ&j—ß$L\öÆ)[†3:n¸rÖ+¤nÖ)lV9/åäž랃ɯVÌ•êu»G>V‡EOØDê8KYÆåÈ9Ëšé $8¹£ôßžh·›™gKk˜Ås!ŒpÐàè ŠÒê©–/‚¨™¡µ›äð+sO*.dWÛ]"ed]Kð,RµÀ™V£S:5ÔÇ„˜ëY·%¼ÕsS2¶ªÍи3XðæhÀ$–ÕcáÆÚ6_Mè1"*ˆ6JY pXN˜¹–þöêÅÚåU4ëöâ—+”o[u8—4svÿü íãÝ]/54\‹˜’Ú­Úš–ÀDÇZñÛ¾ùÔƒ„w‹e+d0ƽ÷ñ¤Mвª¨14Î6²äDóÈâ `íä‹h¬™Vci,zèb<œs#ZSÕû5E(q !¡¤Ï?îu×Ѻðã€zEèuö~͵”Pþç†P"åýÓüüOH ªƒÅÁn‹TÒÑ7L_Äü½Þʇ’œP£Ý%õ,•P1>üÝN5¥÷ÛÅîð~Þx›«ÁÑ]TÏñÕ:6ÓÝÆÝùWÕË[pîÓd:êó/A_ZDŠ«Wl¥AóÄz.íñXw^ßâv½fã+îÿ_Åñüç«ûÐ;+ìKê«Mm­¬LlŠ­ßWfÆxÆ{–£*˜)‚˜)‚˜)‚˜)‚˜)‚˜)†ØÛclm±¶6ÆØÛclm±¶6ÆØÛclm±¶6ÆØÛclm±¶6ÆØÛclm±¶;sÕ¿Q× LU"I$$1bª<ÛAì¿÷ýt?ÿj´ºû®êþ¶**ØŠ ’Š’2BFD‘"‹ AE‘@X‚(¤R(EH¤PŠ B IQ$X€)ˆ€ˆ)""À‹$RB(DDE‘T’"XˆÈ)D„bDA@A (¢ŒH¢""„A!ƒI$FAdW€"HŒH"„BBˆ("(1„ŠŠ !‚Š 1"HH#²*Ȳ# ÆH¢Ä„Q@DŠHŒ "A‰ ,EXA@  ,ŠÈ  *À$UŒ$U‘h²DP6Á»áùÏ’…Í“ŽK…òÝ}-`*}lãhBpŠM†R# ÊÄZÈV~¥0ì(Y$‰&ÍAdb,–ÙFÑ£Œ ² •!V5(¡F Õ%!)V¡$Š °P`¨¥刭DV‚+RA$F0XŒcFLBˆ° jT¢ €´¤l"°@Pþ”  ±‚ ;R‚ƒ"Š ±QU"ŠÆ,b±EU`(H d‚„¤‚ÂP…%R1dXŠ,Mw|yï Š˜$D€ Š‚Á2D€»QAA„ˆÄ!"A‚+@@Š(¡TºR}?aûõkÚP]ÖA?£Õíj¯“õw„W¢ò´WÛ\ª6C* `ŠÄ\­h¼Eïç–¨•5þÜá}gïÖ?qî{{h>êÕB‘þuþbkê(À0B™O#”ú^/yÏ{®­ãÇÅ6pq±@`º /;„‚Þ‚†Žö`ŠH’ oá¨Ù<ø ö]®üEq„—V 8"½:—„BaH1` 0¬¤EºÐª‚µùj¬ iAYŠÆ”QH $PVPVEAu+V ŠÊ€ª QJ„˜êE@@µ¢+ß!‚+©E_Æ+âV€€dÔ"¡et€°ŠŠ È‚,ˆÀŠ‚2B ²"T@*F"DDŒI$RDd °DŒƒ ‘`«U ¡0bI`¤d!ÜZ¡¿ +„JkÀY%t°JæÎÏ"ëØÐîµ:¹»·èÜvù"ƒBrüFüœøØxÀ¦Þ ý/kãgßq½y¹<0k¯èc¸¿ªW´ÑÔ¾¥€"ºng"ÑèÕ£²?ýú«.Oà"¶=9…u[íέ˜ˆvdÆ¿X¿ÝlRöÇçæ]Üê112u³o£'Dª:M¸¢‡U!!Ï‚*  Šƒ˜p9º<Žßbj¾÷ÔÚ~]*‰VSTŠ rЦ’H”¤@ ‘Àª`%w‡ Œ•ˆ@[rÝ8¢¦8¿wì§ˆŠ ®rÃØ~¹Ôÿ;¤iä>ô{<ŸªèŸÁÜ{ޝV;À{†`t4¼û©îN§ôǶëêÙÜ«êïù?‰,øÇøkÅ(ˆ>­s9Otº()õüḊx?B:Av/””¥2‚TŽê¯÷R~"dT`ÛEB°¬€°d¯÷aQEX…ï!$Ø;úH§öd$N €_l"µAX"¹B )c]DH(°åPþrC÷± 2HU"ÀUXFÈE" Š)@D‘H,@X±@0DˆÉPQ,‚‘¢±d æ¡´¹ˆÄ‚+¹Ö%ÄVÂ+ç/bàW[äê1¨ÚÛ´#­FÂdUŠ,Ø) Z_õ"+®ÀPÜ‚·E‚20 ªªªª¨Šªª‚ ªªªªªªªªªªªªªªªªªªªªªªªÆ*ªªªªªªªªªªªªªª¢*ªªªªªªªªªªªª¢*ªª¢*ª"ªª"ªªªªªª"ª«ªªªªª¨ ªªªªªªªˆªª‚ ªªªªªÆ*ªªªªªªªªª I "±T‚A UUUUUUUUUUUUUT‚AUUQUUUUUUUUUQÅUUDDUUTEUUUUUUTEUUUUUDUUUUUUUUUDDUUDDDUUDUUUUUUUTEUUUUUU`IFX"±"@ŠßÛˆ¬ ¬B„V" HòÝSô(¨ÉŠŠ¢ãcg­·KѶº’Ãë}wy“Íw~'äËúàëV Žg)BÎÊ@ÐAÐg͉/a‘)[(åI÷"9Xw¬U Y¢ f¨,ˆ vÀ|~Ù`8úâä(D3Ö±d]Crš…嬖wÈgŒ°+%a ,ÉÉ“dc ,P`ƒŠË°žÕ£U  äsôÛ³¶Úê4h5 sZ…JÒš†YJk)rwdº ‰MhÌÔ% Ù‚¦°Á/âí$(jVG ‚Ðy£|A‰7u¸S º@lÞ‚6*XpS¹ka’aX!özÇçö­€¿F‘aš'Zª3%¿ÎíØ©Ä·V×­ï½Á¬ç˜Š ØÄçK?þÒLJtX2,Pdi,ÔÊÏx„“Œq­åI2. $8¦,Foô³#ýNÕMWæ ½¬?d51f Q@ QPK* pX¢(¼Ý_WÒ!¯B! ÁÀ‚½qzˆ+’0Œ‹UTUŒ`¢ÅŠ"(±bˆ‚0X¢ÄF ¨0X*+±E « $BHÈ+ˆ$X(ªª¢¬c,QE‹D‚Å"1A‚ÁPAXÅŠ) ’IT"ˆXƒJˆò‚‹"¢ä¥ˆÄUUUTEˆ¢¢¢"ªªª£ЍˆŠª"ª¨ˆªŠªªˆˆ¬b*ª*ª¢ª(Šªªªªªªªªªªª¨Šªª¨Šªªªª*¢ªªªˆªªª« ªªªªªªªªªÄQUUEUUUQUDUUUUQUUUUUUV1Q#AUUUUUUUUUQ‰ Šª¨ ¨Šªªªªªªªªªªªªªˆ¢*ªª"ªÄb ªªªˆªªª ‡Þ²@RàŠþ£Ü(9ˆ.ª£à ¼\…?8#R1DD` ,X„F*ÀH’$DˆH„`Œ@I!‘# ¢(+"@H‘„U`‹F ‘DH‘„ˆˆŒ"*(¢Š(¢Š„A@ˆ!DA‘"‚ ‚Dˆˆˆ DFDPD! $ˆˆ$Š)DˆÈ’b%D‘F(‚2€‚D‚1€(ˆ¤@@DŠ1 ’ ˆ‰(D‚!`Š  "Hˆ2EEEUEEP„DFAˆAB" ƒ Œˆ$F@bŒ„ÀŒ(+¡ƒV< ƒa[éÛe¥UEhZŠª´M¸´%!$¢I€w`ŠEBE`0Pp´3,R´ À€$V„Vˆ3Q°Qª±Qˆ‚˜)F_û÷(ma½Tvª¾Çj¨èÀâ‡ÚÚa$23« <©•ÓLŒß&£´Xæ„0Ë\Änõ´Š—,Ü*œ6½^í:y6s0fÆbŽyÖMT:žË¶KƳc$@XĤ‚I¾Ñ¢–=‹¶ÒÓ‚Ö6h½†•Ħƒ% ˆ¯Y &ümÄ€Ó—)aÄ4ÒSue9P©ˆñ ’¡°Iå„Ù¡˜Y`üË?–Švæ31­Fà£/¼†wýþûÜ~¯Ýcñ~0Šÿ§ïÄW§ø§©6_½¹í)ŠÐ@! êŠJ5&.œÈý2¯ºÆÖŒ žÙ–&-;W»Ê­úâL éjõ™çEœBO!®Š ˜G[ˇLæÀ=sºÃ•CÐ?¨-žAÄX ¤YVÁ‚°EbC> „$$‘_¥}O¸ù2î“]Èý™Sñ1Ÿç$X¡¾¾GýFúѲSn8É#$=mh`IßNS¥ê½f9| FR¢pUNo#h”E< ñØÂIˆªžŠÀQð‚¢˜£ácÒMÞaEEvb(DP  ÁKÃptÂ!PQT!Œ ¨âýaÄJc®Ÿ…@¥ÿÑÐ?–›"Æ) Ðÿ‘•%“òЖûÿ› Ú¨+±PW-AZþ6ÍG·:B•n¿x¯‰á]ö7>_#Y/ÀÙSæìèõ’J2bB÷Î¥“O ZÖµœÆh—Vàå,¨ž‹y›¥î>Ç]è¿›ð÷ß/ŸðyOþô¿c³wÉ<ƒ¾Œä`HE3µ¤c"ó’]¥Ò\~ÓGveÍãDØ wAŒCqG¸³IxÓØsRmCäÙ»â@»Úr<Çðî ‹¤/0ÕMWåtFÐËQwB+y[Êä0Eh"·Ñå”2,Q¿£šòûoMoÍ·ÄýꀌŸT!¬VˆªF+"$B A"D ‰’ ‚DDrÔÏíM>a@“½“àèVÒôQYœt?ìÀÀ"€„~>#0å£ e"¶`Œ—†Ý-Ù§ºÞ£Ük)÷>ŸáÄ *Ú@`Fþci»R`l¼ †4CÒËM]à!š…17!@\"ce6¶ØV…7Ý,8s„^,Uz™@QKm{`P(mÊtÈ–æÃøŒð õSvWY¤/…Ȫ” Šôâ·ƒˆ$)à‡ðCœçÄBƒˆÈA„Ud@@dE±uDD?ÃUî¹}8(ÃEo&«âöõ´PVØ(¤¯GÍWíXê'? %h”¥$  g8i_’ øiDäþÞ3õû¯S¥áüŸƒ÷»Ùhu^õ£ïQ‰?9— ¥á×&ôE5Kyüþ³ÎÆ¿³%E­ŒÂØ@!cÈ ˆ)kiüúþö§`8iéûìn€û·ÓÊ’D$#bÁ`*‘dˆ‚Å‚ 1TUEb ¤X°UX±aPAbÁHŒTD`ÉcA`¬RA‹$F(p‰±á˜…¼µÕ*X:Þÿä yo%CAØ"µ]‡4"ºdEA Šòýú•U¢AP‚  ÿŒ"¥ñQKT?n¤QøPˆ¨'ðÂbŠŠa (ÀQ¢€ …zb‡ù¨®“òöþÅ@Ú| PELQÌÓÖÑTsA³a59¢þŸcÑ%¶qzºÆ¾>¼·^–¿ì…¬Ôñ5ç+e•²ÃN”éŒgÀÅ#ÔÂÿþ~L1·èã€ê?O²Ûß…ã:”êLjâulXrpe×Lì¶xtÌ}ÿt L?³@„rð„¯øG%øPPݘd0Xú»8½4ŸÏó»,nö>º½"*¥'¥Ðˆ­}£ ¢(]ggJRª ϶Y`¨?ÈÌÁ»ñªv]°æ²ûlQÈÝLˆR”vL ÓïDWÙ‚ª0P}Ô[â+½ˆ+ùÃB£@ŠÐÈ*JÂU¥iTi"°EOÉWQרχÔ‚!M @QR€* ß-DPWÝà…Säì„W\€i‚oe‚*@ QÎU𙉰m®ÌÇŸw¼â­³Û†·Mñ·q‘ÀGEÇ—°;£jiDGÏ)Þ”kh¢ Ìt˜}°Šñáü>Ë>¾Ã'7 Ó{.‚I&bòfï“\–Æì¾î¥aØuôTçbYDPv<®pkþ<šªTLû“R߇8–¨x†;ÞóÝšúƒsÅ}åëH\æN–0Å:÷« F¢ +÷ÔGq¤ß0ÝÃÆ°R§4‘[¹ô¬¨„0aP @@€À|^WîÿNnw.ŒDqõøÝŒ"¸Â+pˆð?g[Ò–šOA¤Ñû¯i׌ªº€¨ƒ°D`ŠðA[¬üN‡“ý”2oœgw­Ýe–œåêa¥.µ -d…)íód©BÞRa*€Ä› ¢ 0´0__V>^<rvl&§{s]3Í*joyw£O`ÍÉüuw‹¹^T7lÍÉ<h‘ÂÛ?ŠH”‡À­UHŒî!‡"¼6Ò¸&’í<”F—.¨Õ™ò„ç)ý''þ «·;:ŽåŽQéjbPÏ1©ˆ|¡:E L‡a†3û+Îí^OòisYM+@ÇٜʒoÇóuYé|“d÷þ2~üí´“‰ó6a¬ˆ®‡Xîyå@$@q†Æ$B1HEë"‹€d p¨Y•ʤxÛŒ1Y„´ «0Ûm¸QøÃŒ0aÑêÁôiÌDK~žO3Ýæ?裎y“'Ÿ­ÅW™S»°öuTûi àCò'´6M²`¢*)ÂàŽ{³^óëò—æyk¹™2I$wjWˆÐ‰@§ú­¾-I JG°”ëòói)g3-ú´ì¸ì¯åà¿1µú¾ûF Òs ìÙØù¾]®± UåÀûÚÜ'“L¼ö,ÏžŽMTh’{L°BêFHH‡ô 9j@õ¡ ×ê·pê9Qý¶O³Æa°°âä­Z3ñyžDÇî‹Ô2Â𙪠æ§Ú?„%­áþ„n[Iç}¸ª¥õA ‡Ùˆ­QE`Šï”PPW@`LxIø|iTR@BøŠêÀDáС;Nt"ÿ)DTï¯`–kËÊ"¦z_C@Î.æ<—·þËÜêMЯ¶ T/š˜Ìþ>Ö§äôî=f N~/Ô>5ÜÿÔ=@ Åîl± "‡òõÇî!¨U {]Áý¸~Žû"²EQî:Ü`н R ëDV­+8 lkUö’£\¹í+Höþ7s ü]ßMÏö8+{»¨·UÝ2³H´«J.  K Ÿ¾×‹œtv[;ü2’¹q’†8ÌBˆÂiÈ(nZÔ“LV»†•Eþë².– ÇRƳÎФgY^:'ö©ÃxÔ¿$’CCùþGY¡v5_Ñõþˆj>3p ãîÏ䀪" (KÀ* c›µA ÞÛáé„ÏÒs⢟ ½p£Œ8ÇéÐÜ×çöþÃ<¸KÙ‡ŸúÖn÷Äo­C€ˆ¨rçŸ)«›ë$(T€NjŽ›„*’x¨—Œ¥ù¾ïù˜½øc•1áfäTµY˜sô{ûˆH9Õw_ñŠæ!‰ zÓBèÌ5Ì)ÈÉ—‘/Suå·æ8eiùi?Wuró†éòÊöï ŸN ÜÍ‘8‹öÚ~gžÜ\v]ð}#i<–×̈®]ùȵZûMÓ~_‰ø‘ãÕêI÷øã|à ¢ Ì$:ʪúõ¶ñí:áÊP2^hy°òÎI¸{µËAÄX¨«@Fœ4ûØž[I¤ËÞvJïCl¨´Ì( ÀÅ!âX>~s7¨‡znŤlKuéÄT%<£ox隥THéfz' ¼¸``Œ³Vw“Jg•ÝÇ•IMËŠ<ÔRmØER,§`¬¯@‘NGh™¥é#Ê–¨Ãƒ„ç¾b%åpî“ÈÕPHT¨ `‘c˜¬²„)°BœsçEOJ¯¼8PÊ S¸P€ Ê *;¿d QB¶(ªEA+–cnyœà­å +o²äû‹¢ä©ÃÁ¦ûZ1´AE߈„r{pp‚LAìMâó>)qª‹~o4îo·|çè+úøX.†Jôf<6‹ãé¶\G–³¹ø?o²?ãüæ,=n—Øì| 8ªˆqçÐEGõù_B1µç‚¸|¯ƒÆ%*œ<¥Ùõ\S`sˆ¼db‘Tó>Ñ| 9⢔KŽ#ÙuB+Ùö[ÔpÎîKpmt 6‚¯7›âý»@\C¢úµ;€‹ÏÊŽ›”ï?-]gÀ(>Ë5iãt5Ï¢Ò8í§8|…Àä^°dœ~²óû_™Y"C@Àëc¬!§p,€˜‰2$ž€˜€Tä@ðlÝL²¾dªtV28®é^ÅköoQãXö¼^³ªÈÿ›’ébÒw÷üUØËWäy7Îp²Žš–."È@nÁ!>€ ü¸8‡ý²Ã’ØO¨Â3œD).¤btÖIŠxLR>c*»„âT©<޹YùêÐ=Ü¿÷Ü·aqÍ‚3Z²é-Jáªõ‡Ö¯cygsüÙ>À0ÎÁáo»OÏï}Z÷øïà}Y©Ãø4íïø ï_‡}ãgÒCÚˆ®é C`È >‡Ó:N€—îi+?ýøª½ybo–¿ô,à¿øôó/IüXû>j8GO!“k`‚¢…UhÀEbÝœ¦h ( AX"½‰B”Dø´oÖã ë€U@ÊÆDTÓšªâ¨ƒÀâp£F |{]pŠæ#ó²t-Ù¡’?G×ß”˜-ô6¨=47]Fg¦¥)R-ô¾@j°ðšËÓúçZOlì0„IùsŠ©¸ìÄýí?bBm­4ñZ¾™˜Gî*Hn˾õ{¢ÕŠW˜šÀëTíIßì¬u D ?‡e÷iN/ñu»7vûÿ­®îµåÓsö¸,{78³7Qù­æñR‘]ÅF ܼ ªNÕ…,%k‡Ù秤ªú͵˜Gò …'/ý A±í9o¿ï=§uÖzœ/öû@gИà®,²G¥@"0Dv+QH*)|¥¯¸ :“l T­7ÁðzÑC¨TêEU" ‰ ŠÀP@iPH E÷v £Á@è(df"9ÓîËa2."¸[‚+ÐTRú‡2¨9Eýoæð ¨&TΊ4) 2ûÐGïsK÷îG9Bñç1ÓÎdˆ®hÑÔYÖk ¬©$È( ¯–œúô>S¢ëinÙa†~×ZnÌCÔþ£é’oÕUV1ùá•X~TBÔ)J6–­SÇKËLbÖ¶ÊYhV6ÈX ,*þ¿ÉíXZIár°¾@¶F,×+®Äh ­L¢ÚI1†u>£¼­ø º#@{¸$¢¯ÿßzÁ$ä¡ÀÙ®öŸãºÍÖú 0P}³2n?/ª‡®åI­ÕýÁQ§AÉJ—ˆëx’ðïcÓn-Uß¼ÿ=ø;+Íæ7:]³W–‡GýÂ+ð6|ëÉ»ÐS×<èŠàþ__„çG›ü?Ð@é‰û>çÉæ“_¿#Z ®‰(ж ²°M3¦¡IÅp^'Ðâôžc -v÷&uõOwÖœœš¹„®––;%$Ü2I}ÄϙѡñìÇ©\ˆ Ê?¸Àjy?L Z¿áÃWÝ~¼ŠUUï{qÆ9ÌcËsÜ—îd.JNAó†.¾ PÉ PÄäxžSòÿ¶³›³Ëõ_ƒ;™ü™Nßhÿ‡^ûœÄ©”xŸšhlÕ;N(ä½mÊfåÉü¤1ÓLXH@ …Hž&¾ oÏÐa¶ÿÔsVo~?BU1ŽE‘öÖsÅ£|#ó:ÿ…]•Z‘‹y×›yUjè=ߺ"F«±s¬rÂR’c‡Ñ‹+PÄåyÊáñ—µ™N;ßvÊ$LêcW’)ž:áîâ+bBìï :ˆ†ÄmRŒúŠMfA€Æ§c‹½«\È'ʈœ}¾‹ªÀòO»ç#‚6ž¥;ÃóÆ1 ÄgÓ`®óŸRä P z^úzŽ€ëõM‰ æÁÀà¶øø­ –ÍškvmòŠœþzU‰‰ÜHIªázÜmU`‡@_„&eYe•,Y² LÀ¸7~Õ$@! ˜ÄÔÜ%IºMÆÛåhÎza»^&})ö[¢¿+Uû‚ýßüû—Ýb†wùùP“¼$¯2U>R}›¾é=à/fÆåAÆYuiÀ üäaÀ@!ƒ±áƒ¯X¶0ûr¹$ψÐà¸I¹4«+.' a>bkËoypýÞ·õ±Ïí’K÷"½îÈÝyjj>‰êC/¢À¸$ò€m±„C±Rž)B¬næq‘WÁ/ÏZù¯O·|ã1£F=X4cÎ?uë[csCífp ü0t‡ï£÷n >¨üy•‹€ûÀBšIíô¼®âcMF]Ú‰¯V—ÃýñŸ ìtT¶»­«èõ)ÑùTÖ¢?ÿE@ìúFOûãm-T‚«œ8iP{Ä¡ˆ>éB¡þdÆ¿¹"®kt—0ôÏŒ*qÁB˜: A/o+sþ6ž¬ñë>­kƒÏmÊ>ÅØ5®øe2&“мD6 œ¼c™“›™Q5 Œ”ró*µyŸ«ÊáÎìCñ§nk;訜†ÕxD0@7¢"oEzF Töîg#´ëݱûˆÜ@Y(Þ\@iŸ.Ýj? ±Ž£ž¥G¢ A*íšnuÚF:sˆJ<³H}ö…·¸°ô*‹©UŠD V宺T´?~ЪҔϗAÙŽúùFe——™–Oí?r߆ÛüAÿôþý„ÿ[Ùj/ÛÑêj™Ù÷x¶gŽ€Î‘1N£ýº]V&/ØúY<8bÀ:{9@„‚pˆF %’ ñö9OtË?~Uµ­®eÞ/”q–ÙÙåÊa¥.¼ŸëŒõìLòpŒUæ’¼lø—P²j•!»‰FqXM›»+œžê½›˜‡œðýŸgãÚaÊÔ7¯Ìí?/ë´xjzoE@OÝh`TãŒ,Ø„ãx¸{r¦÷8 ÅÖÔ¥$éwž„‚v&@d|pôvó²@1÷ð¼HÔíˆèéÍ J†`@"+ˆ«BÎFÀ°`;7쿪½_‘;É-2îõ¤Ðî)ŸýbzÁ»ŽI‹Ý8åñûušÙ](_†Þ¤€Ãé(ˆñDžHá½§I¾n›¾õ˜îþ¯¼øNè·þv4¤„Îÿöÿ®÷?‘<¿—&bÚÔræ~×èþÚúOùXo—§æ\æ^îíl¨ö·ÓýN±ÀJNç†6å9o§ÍO¶ƒ¾˜2ÎU”+ìèØú‰Ð¨ß±úÖ‹±Ûò¿ÕÝf¶%Gá°=7A^U^4»7F‰¹â{ƒxõ5­érÔc(¶%¦ŒÌv—,Ç4UÉôUá/‘•P©Q5sœûœÕhNÎÎ'Ô3&dÏìDLDmO.ùqË8'årã[§+e­o„a2¢bUNã¡:qÐqâxôŽ(•S÷ú%÷xì¹Îs·óm˜¡qùQî$!Zƒ×íráNHðî}MúïÚM¼6åÀiÂ1‘D‚ˆ—0ɈצÄÌy$©&²õ3iÈrfªÞ`¢èPó ÝÓ°„8ö| š§‚Ë&šŒĢɮ4²ï+Nå‘ÄÎ$O/)ó'#=™s˜"ÁÁƒÕïsYåý>ÿíç—ðþ›ï¿£N‹òö>ßÅáR9 Ôॢ¨RHðóUaKc,¢Â%Õ½RÐÔiCðE7úwÖú¾ åünÓù>é…?öA®ú;äÕ˜[Éêv—[Ïwæ·4dÚOÏꚥ[¡GŒˆUÇtºÒʨg>;„‡Èýý½l/'AÛ”@¡°æª´èk!g?xºçƶ&D…_¾L?ã§ŒüxðCð*¨r½”™-aVÈ©|TõkäŽ*g3MJ¤Éÿ}¤…³ ៟ٻ0çôbr};4uÉ 3J ÂТƒž3,bÕI#?NÅÜû_gøÁ§ßêT>ŸØ©‡¸ËÐ̈´Léz% BFs^6= càŒ´DÀða­€ Hý€À …Vùé·S‰Ú™:Š¿ÚÛ5×ö]6>q¥c>èÏ\»WôçË—ÚÇ+Ý_ÓÍR¿AOKMÙ{Cê® ÐCÍ4Á2D0Sùw{“ òô@CŽ ‡Î‚ " £Š¼­Dãb!… ëë(*‚°xRŠ ýº½™ˆQ²:(Ô f’?âQ‹ËòʾŸŸ£q>0éG rx€'˜gö¬‡îÏšÿÄ"0DEZzQ,”˜‹ ­«LLKŒŠŒŠB(WóCÅA^o ëò’áÔHÁ÷ä·ÑüiúIþˆtÚt<¾“ùßïš">üÔÍ –Þ»›/^ ý>ß;,¥zLï®4 /óÉ'±T~7§Cz‚¿Wæç—ȇ¨†ÃÄÿùp^?™ß•ŽvϬ»'·ón Ÿ¡¨ ’º„›0Ì)/7-ÀCU[u·×«æ˜ççQV2Òür‡ $ûCî®YÓáG Ö±² ôsép;¿ƒû®yöç”kÆÚêÎå–œ¡,qÒê´¸NÙ]}’Ñfpv4}ŒïÙVßGÈ«–£×{t%^¯ÞûÁÕ0òÿ~êSb³ƒ@Ag«pZÛjkôÁÒ•‚êò“Šÿzλ{=;CCÑGX‡~‹™ ¯ÕB0ŸÀVkÜi$ÔŽ0ñTÑì~Ÿw5å%­Œx™³ýÎÕy’‚´ ¯´ò)AZ™Cë{L¢¯cf jKŠÏ­ƒç>çQý?{òú'½àTÊ8ßwjfW9þ‡Óz||V§„›ÓÕ¯ þþaÈÈ£"ü%n~&ÉU½Â_z ¥vº/¬Û(2FɳLmªB?Eg£}ÒB ¾›çȽ‘—Žâ ãcÔÄœ¶Jç~M-/W[ó¦TDbcQšLZòÍí|Ë'õÎFilˆ"_®S Ã67J>ÉI3AlS—>î±ÕÞä J@¬ñï§1Óïµ¶Iwßc´’hùJ~.Åm ÿ"…꨻ùæÑ9X•;MƒÈLâÑ…I™yËq á÷eðÀ9° S0°&]Lèî¹*òða¢Ï~YVùu.€\CÞn 2A=¶nóBK×fèì@“vÄ'ï…Øq¬ÁùØI7V¥I`J„©}³œÎQݪ%d•þ~7çotÑпê’L¤N tçö~ÕbÞ&þü«û(ÿ"Nk_®àø,1B7âGúö–õ«Åq¨„Ä€qÞª2ûˆ€4Þáýâøbòb¨ÂìÉ èAœãZtW2K­ÕUU|·ÕáWÏò?¢ò{;•ØW7>´˜y°Epv¾K×uÚÀÃ…Ø‹ï;-žny¡QѺÆPE¦”j5íÿWÚ{Et+ÅÁ@PîùíAÿzÏŒ`ÀmsÐð”ÓÒKiD’K@E"«TÓ‘1ºž…PWÔêþ®uYw€N„õ}ŲV,ª¬•DoË…–A©`§HQ3ß‚+@½v&ÖÞ–[B¥àZÚA¥@„$û'¨hÀd_²Ô(XØ>Ü€I$ˆí­Éi¼% °GÎþ'X íKµp26Ëuædy\Ä!bX"° 0ô Ãý¿t“`g/ûŸÂ¾k+˜Pø6YêM(¬]†¶ ]FÛ99‡yô»C¹É'SîàÏy=,Àù.¢U”ƒLRÂ+×ÚÙ ŸÍþ˜0#JÎ…wÕŠéÙ)’ëE2×÷yã îµ{.g1{M™u”Ao’ñÎÎF$$›Éu19frº5°)»ª¾Í—¶ŽÈܨm ŠÍP޹¤ ª€†CN€É¦ …B˜/+8sj]´Êf‡ `¬u¬WfX¨Òʼ¦àdPéÇ­ÓKŠÇr¥¨‘ùˇª%軩|hiG"îH^¬‚H¢±À‹0ÌF J4²ÆrÝåXE!ɺ ˜b!²PKk]zé‡BÒ˜Û1È(Ôv Œ3tá]¸ÖµmlÙÛWjTâ! À),‘ ¡°Yš‰mJPKxÅÄ&ÁÔ­##$iÙÊèµ)ûÿM)ˆ§è€ FÄPR¾ÉÇr¼ƒ|“ŠÞPЕEñGÄeµòŸð Æ>£º,Øù,KRˆÑáy;pkæï&l§Í3I´5T¼9Ì ®TôIci?š |ܳ!$"0aÂBTݨ[mª¢êl<úHžñ oc&Jêݶ)¢IH„Èc@6У‰}ËCÃÆ‹ñ´›Dl3-Ú £Ï|ænæú5›º>{O‹å¾ÚMö¾Ù$ØõâÙqX,m%±suQY¢‹0ó¢+ „—§ý/i†ÌPõ2T©%d*HT‚,¶ Ct …1þ "AaÌljtÈ2(V4Yþª¥½Àl $!Ú¾s0²ø(v*fZóê „I*Ø $‘ˆ_ñn©tl¯lã8¦Ð ŸƒŠîv¨w#¡H*›ÐáE$$wçºIeˆ¬BE$YE>š ì-» ¢0Ebê;,¡™¸£uÐ_3ûs)­vàD±„õ‡WûNÞ@K{Ô¨tºÛ­4Ë!FF +®OD¶>*eŠÍ09¤0B9C†mÁ$0Ü‘»X‘#6PÝÆAâ€Q€cfÍÒñìÓá¡H@´j)ii%”Ö–ëó¬®aÁÃq˜ ÓŠ‚ÈC¤$dO?*6žþ¢TBçg‰$爯Ò[âŸ5ât.Á®×Þk¸ú>¯µ,ÇS}M’¥´ˆ¬ ؆4’!á§'¸¾N¢øZX ä@(žâhi`k; ¾E¨ ûÃÓæôÀPÄ$ðaw×E $ 0áÇ{'VAbÃßÕ'°“Óç°ÝïM“6¤ÓK¾Jâ¡[†b‚Äå¶£–?{ y-bض…´,ŸE¶`€,„ÄídÁFfÍž&h¥%` Ø”ˆ‚Á_‹ã@R$b°œŽbƒ$„ó jp–"Žëóš÷%XùˆòLŒ}N]ÄPè•ù¤Xb JR _=.$¢ß^fNnþâ7ÄQkѤÅõý>çÚ=m}=}f‚L.>é“à¡CÆæ2)¡U8Qk´W•Z:Úâ«vo…2Ì‚+,%›<ëÞ5ÌË""ÚS±È]C†à¥ *¤• ËD|€*šé|Ù†éoôÑ—êb.ˆûuÔ¢^;Áîä÷¯R÷ƒÉÅG½Xš:‚ YGŠŠ :BÁÚ•Ó¥ŠQ.åWßù>–W)‹þN{m¼÷”VÞ’¨µaµfnÛ JA‘{Ðú]?š"J:J(Àd6é˦¾i}€V0„Z9` 9.. ¬aòP¨É¡Õi?KYX题–“ñéX¬OÓH7q!@û¯Ò ÒÞW2œŸ>†+ò_}Oße®—ÖµokV`cƒøAŒŒÔ¤jRÍðÜþÊšç¹kQ®%§öZý€BIÊ^&øä8fãû.ûv&(pØÏæï8·Õõuh¼y4™3 Úa°ÒÊ5h³ü#ùû‚¾ØÊ3pýð0ñdE’,’1BSÔž—‰õù•;ÐÉ\ĺz 8EË“•@rO³,=Æ TD7Ž€8FÏ:…i0.&ø×ðú甡ƒjh”¬R2B1,*R‡rkVÛ[e*a #¡Á¥Ó(ÌÆYŠ˜RÁ>^l:¢À:†äÐäDOíÝOÇ\èýÞTKu”—0)2µ9ž‰×¶¨ž×‡èöœáËŸÉÉ+ìµ ¼¦Øsr;IMØÏUûñÔètém°?­` #çÅ< »x4…ñ+çL¶&G–X&It³e’€Ezî[¼œtÈ>*²|Óƒ¨€;H5WɆ8ȦþžØƒF1›–h€,‹!¿ñK3ÎŒQÁ¸3$ݼkÑ ¥JÈI/`kaÂvÞ†ö1 ôNaû/%ç›D_‚TÎ~ú¬üõ8— B\I ”VE ضvÊ“ØVÀQˆ’Pý "¤òxôœ*P!ŠëÂ)Zó$þµá–ÁåÀ:’ø,…z£­2Å­€ ë¯Ø,ÓðFQR|Ÿ—Cȇø4ñøxÍ÷“¶0nD9Á¼Õ®X.R/Ò…1ä>BPÙ+›ýÍXïéó}ì_;’”‰ã(l‰s;Ñy”Š­@Dºo³á†M7CxŠÀ3‡¹.– äa~Êv‰BôþŽ£õ|™8Ç]Ó ÅÐÌ«ð”)þ±~‰ÂÚƒù mx†°E|²qïo72¯›Í˜ÛØÀ¦ã–bgìàýVô(r!˜ŠÎթ듳ôºñŒäÏhÊU=³Ø0R¬›ïYÿËiéXõ¼;ÿ_ iJ(!(¢‚s˜÷—º½" Ü ­ñ¥Q±¦¬1„ 3`!Ä æ5PVÄ-aÌQ ’Œd‹ ‡Õä5©‘♇>¦ö0…™êËÉ‹œË)ŠØÝë¦â+­ÒH^€ÉÂlÏÂÏoÞiÀQ]بÞ¦èê”ÀcJ"ÔN”îØïÏ‘˜éÛó1&—Z®:­…ãZO€Ì ÿWôOØK*›ì¦¥سÍÿrû°p6îÿ÷k^óu²¨Ã¡:Øp¬ I¢ •°e"„†*Ö;È,Dþáÿ7û·|Þ¢ýN7•+¬$+Á–?k¾ÖahUNe¼uìÍ"œ•ä“:S_2ÌJáÛòÿÎýè¿Ï¢“Å2p^,vC˜ÇüÞ!ã4„hÂ@d|ê‹ße•‚l³ûT³Us”–"ÐT1YYo†þÐ{vÑÏàÑØÝ;3 |qîT;ñÚ¨Bp=Á4 &©MÛ'ç¶í¿£´_¬ %ê²5mL~œv˜aÐÃÊgí z@[&éÊÖš Ì=:˜–ZQÃÀÁ2XÖZS=gC3wàp„¹¸Í!õ^R›þcxÿu­b”­'6pâR ã`v8´Lè6ˆ’l(t‘¾$èÊvõè`ŒìrÙœª^ï']¡¤x*ã×¥6dêÍ•&éÈ¢¦PL§$éÉM)¼/Nàå1öàjMì"S0&m¹†cš Á½Û5týû˜ º Ú‰<ÉlfsÚg¶oÔ¥¨nŠÈ5² é}_ïëLµ¯“.&¿ÆŽ‹ùÙóDóÖº“<²Ïèå¨o§åP‚ÝË=W{˜ðåÛ<%“¢CfäBŬá‡R¢Ù „߳Ɋa1éãƒöý&íB¿nC™è䱩“HÖ¶³H„á5ns+¨+Mƒû$·¯ ßÙãC Þy}šç}õ‡òFèÄ^ž-üYêä†åŽÆ¡,ß~J îЦ]DA³´¹;Qí9áºQì›ÝvPÌ¥y‚58î›_‡N{SÚëÃNKžxDˆƒÀp;s¥óE«Çhí<7õã) P˜ñÇC…G%æÝפ xsh¯#ƒ#ÁpÃth« ú9W·Õ¨=;Ât̵¼í0@tæ3(M5fǬô»©/ÚmI?úƒdž[;—Sæ““.õ~ÐóËw=·ƒrC•ç‡qæ³[¸È¦ì°:!zV=vç»#!Ä›mÆÄÒþÙÎ$yΣØä:ŠòKÀa窂×:ô2‹¯rÈ´²¯ 9_t$]r®¶Q]%ø£›ßަ+Åö0ÌÓ3oÙÒùGYQ6ù²º˜¾ºî–ƒÍÑ× sÃ'ÂGsªݘU)g t‘ºä8öиíñÌâóðŽJ¯äzÔ¶ØÅ–¶kCo¡8BOYÊü(ÏÂ]…łҲ³CïmÄýxÞ 37áÞü/:êUûÏg,U·ß©§ûx³°ûÝÀ€ëàC6o[› ®Ðý÷ooöõŸ¿ûyï¾{ûÇ+ÊRž¹ b<ìU\ª`KF˜eY0XQ®1XˆÔS bÞâɦi1*Œ•V5Ä— ÕšØ$ Kd›`ⱊ±‘6:O'ûÙ¹¡ tKêñFÖe‡~Ô§¾Ç>¢¢ ‡1ą̃â]A=È××*QÀè¨íx¿ŽO——¯%$¼LwàŸЏë‹Ãùë:<òySOg•Ükë Ã"pfaKà6(ÅQˆ"@ˆ’DžÏÞ¦òês4]¸,hÞæA‡³23C¡Wû/eÉúÿ®ãÍd´ÌÅ0–qD£Œd˜·Æ1’æ ¢t@`?%˜Â5¼^3ÊpXó¨ñÏ4_ ¨à32‘=gV™r„ÐL”:ÒÀ`Ù¿°õƒ™—òîíÐM¡ë$3i4¤É#h_~è×EDY]"‡‚Z‘2„7„.Î ø–mc8•›œ0…´Õ»äG0. ±CÏÂ@ Ê¦,CWéiÉÝÏ…5Ò˜ g JDÒNð‚!ÐýÙÓtVÉŒ¹â8ÉÙ£ ±–²ÛÿU3mø_Ôç JI yPÀ>°Ó=2ú¼|ü}Ø·$?P~I…œÉAXì}­u÷yv–qv3˜ãT„“Êüt4rS$TC ÍãÔ8c·!ð½cÁgÆâ5° &¶Ö»Ý+šÁ³–«ª¶Òà¯ã 7Á†f@ LŒGô?^\à’;›0Ôþ=9 „Ħ¶EïPÞs:açëø¯”Ù½7¦*’½ªuÔå?JÅc´xOШ{ùUC¿1²èPÛäÊèñ³>B‚l{C¯MÌ[Ç©+z$ a©ˆ”¡P‰àq‡4l/0SÈúQl(­„<ä(Þ_¤d¸ âb!"j%4¼DWüG¸„$’ wMäÜö§xNX´´¥ ØÛ °Ø$hÒDp'ÛJ­àɹ3ƒ¶ä ±³8ÙCB¦j"¼]h5 1)Eb@"BhSzw±L@…¬ê‰çŸ¢ö€u7ã(ʬ;N†Îc‘ùP¾{Ή©ÖÄEd ÃãLÚ¡º!Œ¯dTÔoUWdëÈÍPðÍÆâî»7%­(Á ° ºÁ?Êàž}®¢çíÚ-_åû/¾>ÁÝ|(õkðè1®7L‰ #c«/ÂnRê¶Û|5rж´šYŒò‚ð˜c¼fædý8RžOYã3Ë}90×a–—û}gHzGà]m7•ß`ë—êÝm¢+Ÿç’uª%bB ¨E`î¢`ÕSÓñCÐ|n;üÁ/rvL5 ¤X0DH‹ì$—Æ÷yùκW=27? Ô×ÕÐä˜9àEk-&xŽÀŠI%bZÚAtq|̦+êéʳ™Ï>2j$Иv„$Þ¼­šèŽéLã´Qx–|0ÒB­é†5ØïÆÄ_SJEÕ·uB;•ÛdëúéáD>9Hó}û¶"+®yœM®…á±xËÉfËp‚<∔‡)d i ÕÑ{ D!pØé'Ž«Dy‡±€ÍÍÑ! +1‚±ŒdY`ê«°¤îýÛ‡ÄLá ˆÒØë°Ü¿PŠÑ@cÍÖ$Œ„‘/™[E{àŒp.œaʨ±u;“Q«p “¶Ç…ñ‚ׇ~2Æ1vѵrZ,€ÐP> Ã,Ç`™4Mà( h(¥ˆHMS3ó¯¥Õºêﳪ¶~ ·…0¦Ÿ)^*åë°Ó ߌ/9ëžÏâl‰WI¿./êp®™ï·)O~ no–ŠKÞã+™ÈëáÝÇåmæM¿Òí4vS ׫ë0ÖI«åÈ7Ç–"s –¿=´LCŸ ñk~}ž=¿V¡›¿"s‹Ù$uOéß]“8çw¡â©¼ä•‹ÄRšñrY¢ŒE&òç$ÇtŒÉ‹MŽaJ^nŒ|kÅq'äG¦©…ꇋO—=*`ý©YŸ!…ŒÅÎûQ Öät‡"|]{љ昊P{/PþÞŽÊ(5™½™€ lá`A,‰É‰5" žØ’rçN. Ô *ˆ0€8vžF°=âE0g™Ï¨En»H…Ôê’IÏMXˆ^»E.ë]`ƒ;Â’nrù‰ÓÖéÐ ®V§ m`ówÀ’e „ê›o B|Q'y©à ˆÁŠ/aé½êD¡!"K/€/ièrÌsùöëv䊕ÔÕžËìåîí±ÀàHÎt…TJ£jgÄ[þŸZð!2 ¯Ö±$¤E‰E‚–BĀ딑y Ž"AAùôú J"·Ê ž’âh aÜ1E iÕ0±Y Ãù®ˆ² ÉÀÏÜ¡-í´ hiAÿ§EŽ™ôÇšL{GŠRá× ¤P¦›+ÔìÈ¡<úʰaî j-1=]ž+Té¥ÕfY¸{5Ä Þ¥‡Étq€oK²¨_²‹Îê±ö}gÆþ.û¬î?°Å8´!@2(Ñ2©@”£E©_®Hf­,ŠŠÔVHCÀ8¸P*˜’‘”¤²8Ñ‚*)ò„£!¤&âT¬Š`ÀÜ5«жAËPEÝÇÁB,gÐÛ©P8C0£q縬8"¦P š%-F$Ó1¨¥`  I*,d¬––FØBÙd•!+$ŒíL³m¤€¸²ÍÀš²­BêßÃÄrAa÷ƒ¬+ZÊùž×¦9>L»!è¦\)(y#ÊÀEh»Nÿñiv?iÐóž“uÕr˜ÆŠmó4ÁèŒ%x]Ç¿>Èjè½Çanˆ‚Ãa´Ø›ä,4ðjH4Û  ë!åcŽ)™˜ª Ý·#ý!bÄ ¹ßˆW9Bý¨.«§Ä^&FÐX»yÆp¤ÜD\`Jž3{%Tñ7ñϯgó°ÐlŠ ;bÂ÷C¤I<ªš ‚€†¤Ñ£ # 0Ä 7ç9@mƒ2(nï”#‹A-Bu¯Ïç/sëâš^¹NoxÈ(”KßÅ(wbù$B2€C€Fw?ýû¿Õþ¹w~Hf@¡]¤$w`À?“üzBtŸaó?X¬5«œ¶Å›2íBÇÁtPÁ…-¦!–ýþ_Ó¡Êö,DíÔVœ~= ”¥2€t–G«Šy¹’«€ó–†Q:¢¦°Ä´ì¸Šÿ{€3?íä/ßó<“Ózÿ[yLÜ1”)JQ¥P£!®!¾)±º¦ê „¶j‡·°hAÞ!Ï"mózÈãûŸfqéOÂCt4Qf²¶0@,,)¸0“`Á;ÒH%kLª™ˆ‘?ÔT˜œ„VÈŨ¿šC38›•,uù€ÊÇ~Õ2ðM Fb#ÕÑ™PMDW¦ðŽáâämê戭GðŠýbXª^C¡vbª¨X*µ˜2²Š @8‡ ¢E$ùñQå(%@Ð^+IŠËKUÚ‡#œ¨E?J'(¤Ï$ D ¹Ñ£¾&Î 574ÐÇò\Ó›®ðyŽ6O9pûŸÍ(É&Nvƒ7DØ )xÍÍ,Ô.ï9¬Áe°ôçca>9xT–$ Z¥èfZ$‹Õ½Ñ‹¬@ÜÄÏ(1'8(ª(dIàAü3¾(x0‚·JîW…°„ÓÁòËáóœ,ñ\u½S·v¦\~¼Œ1o÷…G)lóH£ÿ—çCæ¿,ý?§íf˜R%Gî)D#(1$F¬Pb±_º XÃïé@X "2$l²±b‹§ðZº¥á»¼ûƾúmóiòÐÙ'Ÿ`#ï\q¹°€Šßÿœ+WWüwõòú\Öß9öpñ=n)Ž cýÜç§¿SdZ2¶„ÝÓïÃi¤þ“êo¼<@"^nl4Õ²@©®‹‡ 'º‡5J Šìö¾°Ý’ E‚©’F ‘VP’ (EX ±d"$AddRXD X¤Š’ H,QdAaY" AA,X#)`±Hª¤‹!"ÀP °$=‡A7?‹è q`Bè%ÁeÁÌ(+*‚`@q ,ò%IØ4Ñ´íÔ›"Ä*I Ú ²bQIh}\ÔÈhÃõÂu9Bì(ÛP¸ ×Uö~ã0¬BåB.N¾ìÍòôÖ~3Gâõò8Ã{!&ša 4PrŒ""²„ F‰ŒâcZ‰`À"°'' tuä¡ g‰ó6¯© õù,"†¹Þ‹x YØàÚµk¿©Jà`· ¸"¶™iVr Ѩˆ£å¸DB²ñ´ÑBïq¡‘¹z¯¨%íE[ l–¾V•ž4>ß­O¬é~‰åÊ~rÊýµ.®v¬¾~Uëò3‚Za6|F»YþÖ—@ Sh[ãYbnxƒ…±=­¥öÁú—³Âßãå˜ÿ¼cPä*\·«@l1-<‚\@³Wè!êJå˜hÑB”§ì®½?è–‘~’€üÈü2·ë¾üþX ùƒãì`,óÉy¥Ðxh/)÷ ‹x] `‡p!òu˜·‹Úe2ˆ4‰ÚŠùëØék­Õ™Wû-\âЦÓ0ÒT;O‰¦Æ⿃ÕhÏèì¼ÏO“—ˆåš—I5ÛL]¬„}1£CÕTÞ^HH*X DYÖp!æU8I3,!AD ( [6`) V( •*¡C¥êº}J`ˆüűPAdR!«¢"R2!ãÀE*"€ƒÆãü7Ž®ÙiMç!‘P‘$#"‘3@ÎkY-Ï{j¶óW¥@¨Ü&v–Dˆtcñ§ÈA§-3#HD… òcd²}yªòL†jj(f nŒ®B~ È%ˆ‚©%Bd …:Ëê¿¶ E!¥<Ö¾€BIÜ’m¯ò>!öÛ£Zl'ŒÊ64_]º8<è+I•Ê1_[îµL#áN©ÔlîCÆ£"룑V¥`ÎØÈ~±2?a Lè–Ý_9÷{\~ÕmŒ‡»(€è¨ƒÈœ‘ãÒ””ÈîëO@¢·õ¦r>”žT{IùêÃç|ƒÆä$«ÕJ–ˆ‹.©ŽB,8@HLMá¡ ‘g™LBT*BŠŠ*(* Š"DI$dæƒú˜;úüÿoø¥¹ßMEd µ‚Ð2UCT9{9%ì¥øé@ŒÏ"]u᩽wþCDkLоˆ¬bаH´ª¾d Vâ ¤‡ ^2æÔÕî[ŸÜÀo6P ¤N_0j‚·UÀ{ïæmÀ'²DŠ‚#aÏPED$‘T‰ÖZ“œ®Í¿€yî<ÐqªÕ©jOœ2zY«¬§ Æ,„/¦øsÖËeÑÓUQS(%Ñp?± Qõâàïää-ápÃH„†HÅ€åÃ=Áˈ—_œò¾¤8s#8ãÒüÐUÝ \uÄ3bçç¿·ŠÅÛ™#ŒJ-Ý//ÔÌcƒìö:<½(<êçZ<É{y²ãq‹+´a+LÞÈ,Ù4œöì¸)¢L!w›Y ¶:¦`c‘¼ÒJ ŠFgRQ*P"¾Õ*‹RÜŠeHz *ŠE€Á#燻îÞ’z½Bˆ("¤î°ú‘P“`Ø%!ÈUÈ/âwצl»c´¡sDê]ñg ¶C‡NŒöeÂ1‡ ¶±$‘²¦ä=ƒl‚Íè–Áq¢²í¡´EuÀ]à6¬é@j;a¶9þÚh†åŠë´øöe$[Fš!õ%íJæ¦pP¼Æ9'bV$E‡?œl`”M‰R ߬Pr‡ruÌ:»Ã”$! ƒ¡~Ýü …ï@ÿÅ<ïC$†å:€÷ø§œ’2 ‰Œ$‹ Å ¤Y€ŠŠDAH EÞaYdD‚"¬‘HŒŠHIAb‘dD ²(‚AB¨,U"‚‚ȱ‚@X,$QŒ€ÅI)b¢’ŰQE’*Š)E#²H²2 rO‚ jUȯ•=Ì„Yz“%Úÿ}>ö>þ6MæÝÈwùrú³P<˜O}’!N[A}L•’­(bC- &JE C$ "b¸¬%f dJTA€cl lŒË`ÄU¥4Ši5n+‰€N_H(,ŸÊäÁÀèkF|jçxh=çSóìHóX÷°‡Šè·q´À®ÑúL@6üÎãÜÚ¥Š)Q9@S9àí·^Ei &úv1‡Î>ÇyãH¿!%·£ð]#£ÉN™|ÿ‡PA±Ü!DÊ4!ÖS¡ ó7E3ŒˆH-DiŠÈPF“õ€YåpH ÄæHaáÛØ\¥µõ0î݃ïRª¥&JBI•îÃLê(£ŽþU³Šó‡Ý˳ýd8Ä6›×uãzËep¥-õ%Œ˜ä˜\®O"äçqà{=IRBF|>ì|Òµ‡ù”äzÏe|Ó ô¨ä^¸ƒéç 42‚D¨¥–!~° ´¹y £“Í´É9@7–S8;;y÷!ˆ""n‘•%† "‡ÃEÆÆæÂ)•Æ”‹'½ånÿ€;O³³½”„©ã§Eûn(|³ŠhjÇì»æ¤ø¾Ò캕O]UÐ_°˜ˆð.FÄ82Ž0Ã9¥ŽD0?ýäØ_º‹âêùJ“ ’ykêõúkÇq´îøÁö7…þ\Ë4‹»´Þ’&ëÛç¹äàùž7èCÔ§bbó.5$“ïRIQd0µ”è«-:û0gˆ×@ìÀ‡â¤¢Š"ŒaTI„‘xý®GìS`À” $|'\$ÅUTEUF $ Y ü×v ˆOgÀ„;JhÙׯR3BŠ«ª’%\?SpS}ÞΧÝ™Ào°™Ûl‘žxQ! xÎtÅ‹Ÿ”5U´µ;|Ô E‚Œª1…@ôÃi#M ø~,2|/ϼ†$FJ¢È"XÒÏCH²ÚÃUE‘ùWÅHcr±•¢:ùùù}˜ˆ‰ë¤žª§Áú^ 9.›¤’@*›mCÊÀë³k:·4ÜuJ\m¹GÏ!?yÛ¹´üÉÀˆb U”€¨§ÔŠYýOæþn¥x~‘ÜŽŠÊø£ügÑå©Oí ƒøßçü‡¸@ªc`>Þ(>ŽI¼½£È EbȄͥ1ŠÞ|c†Ñ ïÄð{éç¯OÀ‚¢‚ÊØfå ‚* òWÓÀ1°"» å3,ÑGµ 6úèݯlLX­uÝvA°<òGI’[÷8|¸Û¯ì†Žê ˆ œÙLÐ t TȾŠT41= ¨¤Hƒ{Ru‰ˆ;±âj»"1¤Š”¯+¯š¹<ÌŸª ‰ –˜½;üÖn¥üJ–~Ý@í45b!F(ÊyÉwާ£¿Ø’n0ÕØµ’++(‹ ¸%2…K’Cˆä]:]Í´ebïåžkè‹›¤µ?>ÉD!?DQKR‹iv–V IèaV:@iQX`[PQ.ÁÒ3Zg i×Iñ¹uLX+Aµ$ –¶gÜÈ_€€eôMŠRí‚>ü°}½’Ðñ…Ýya'¯Ê¦Ol µÐ¨8rʃÎQèµ/¡ WÛö†%ô=×zD€†ØérÍA—BÒh ¸R&Þ'Ô>‚…ŠCº¦+lhžØö"Œ‰>"`|^Êhdü#Š!ÊDÅöî>C’‰QSÍ•ƒ¨Ê%k 8øRø“D 0ì¬î¥N4ѳþØî`lOÙ{à½JÄÓXÚ ƒz"R]RÖ62Yˆ›¶Ü—×EÈO„98÷kt-0)`Úû­jß•›gWeiñ¡7 ûóôóÒ|NRÚlyw²–гç*ÐÂÏfÓö/°zÊ [Äj€F{êhƒÕ»QïÿG÷6_'ìñ»/#©ì¹/òyüÅÚ8l׎YÌR»%]·Ž¦çÝ&HË m GR ƒDaÄ8À$ဠÀ!|ËÖ•Þ;Rßá}_±ó÷†ü1¨¡~ßü_»Ñ» 1d Š+“£/ Å[ÂÅJ¸"³¸­›&¶e Çl %•ÆAfJ”ˆ2,@Ý3ïó¿ Žã¶dÛF ÆÙ†Ø†6U[G2@Úè&˜ G¶çÉßFã,¼ ~»QɲTHÔ.¶d5 o&b˜m–ªQXæ¢ x§èíL~æÂpšäo:ÁÒ1‰4u3 ›µ.X|¶BEÝ€b}Óv5&$·¶†7}uÖót¸¹p)“ ¦™’ŠÊÊÊ’ &ô"’£…XºÂéU Q ¹u®ä¸1Ö\”¢¨± †?Møi³¨„Ù•1± Œ¨BIºèZ8µT-(ÅòôúóõŸï稆®±I,v=ÆÄÓèWìNç[™õõ¢òÍóFg¤î»´‡}Rk6BÛ\Í4¿îéøF{­±CRÆ€Së•ÛCÀEx­N|(µ­oýŸŸ¥€óLÑ mûɯÜädÚ’£§©­a!¬ 㜾¼X¹Â߆Р3k¨"±/—öÑÅBÜ[ †A`ÿ—•ý—ÖâzŸi¥Ä1¢Ûæ>î_|PKo3.0m33“ò9Ô€!ñÎG›ÒP4wð^„QX¦$!D²Ø@ H…nXìnó)=¤>èwBçÏk¤@´Ì ¨ùäˆo&ÛÓï„öté=¡Ë¯[ŒØ/S±BؘBN­ÎdI E¢dˆ`sÎ͆´k•i$±¨¿F×”8Y’Š[\Ѽ@‘@œ2nÉ &A+‚FÃcn®¢E £”‚쀶RfÕÊc¦© Ie4‚ÉAË 6lE Y‰†PÐÜ 0õÈ ¬EPÃFbFM}Ä iHI04a™" Ëkc#R¤aTŒ;hlÂÑ!T„I E(Q×Ì“ÓçбåJ1BI1† ‚Q™l؆ÿ°Ñ!Æfj"º X/æiaR鹑ˆñÅwåDš8QP¸—LØÉtO_~fÑáäÇä|½6e Ø #H )D: ) A„’0BCÊŠ)AV ÈQkX"&"©tº¨¨HŠ«UƒqR‹œºZÐïŠ)ÈË'tJ\¤A9(ÿ-¢…£]ÙaBID1zE¦ÎŠ–?8ʈ6æ?¼ÈY"ÆD²8¤Q!!=´5;€;¼Ž„¯Ì6;”aéèÚÀ¨  ”ˆ’ÕŠ- ÔF(±Pˆ œuTþh@‡RþÌOû%¡<_D,8Cí‚{Ÿ™À†Ù½º„õ=ÖÈÌœ™‰ß \¿—cÊÿ `ì˜ ¦s^<òûø‡¨É ‰PB\¡Ûf"&’`¬:¡$ƤXE!²@Xm!@IÓS B(²¢Š! B4"µr JªÓf á“‚äf1Q†ÖQ ˆ$ª"Å‘‹1" ƒYÛÌÈ VШ!`’¢Š-HÖRF²’1d‚Š –¢7P,!£J`Ö,B$Ãy u BIn¨ø¨Z‘„„ )eRŠÄ¢1K@Ðd”˜H]X@£ AÜÄKd²à ”þ3½F%˜±RÚ Q)Rª Ee ±‰YQ`IBIZ©YIH€°P¬„’V¶‰´«V…EÐoÍꊕè)Û>©Be55üGdM¹#Ê”!AŠkËD ‚+"*äƒÜ„(‚Š@—õÅk‚Æ ~œ ÕøÿìzØ1Cu˜·3_·äS4Cøš¡îR*­+Ô…"‚€ÑÉ £ñÇê-† †êâg@k2{gt¨>ˆh>cŒc»éC6’§*_o\a %4ZëøÖÛ êa ´:€êãƒ1†î£RÅÇ2Q›š¢‚ã¬.ýûMÐä)¾ìa¡1Ó ²n“šÕÂЩ0z²›ˆ‰ '­£[SÎBIË™ª©¤†¡¢‰ä­®[Ç&`ìD=£p;Â;ù>YU×Ñð5L1–KCioËCÜ@ó"+1 $:@ïÝ*Ë¿jŠØûÏ.•"BIÒ½û{oè€@Nö# ÞB+9ÃΈw’ùIòPšÄó¤~L AQ²"¤ÄK€Bw'SÑÈ¡IIER°ô%T#Òˆžú]€H`Ø;iîM”Ð¥ý£¡ý®àÙ³ÑVò¤ô Ta •*áArGã‰Kû[·KÌÄç¼£#±?ëßšÅMñ=C Dȹz(«‘%L¦WÊ{ …5ì„‚QIëžÝAû“[\1¹WkB¸¡ ‹C`fŸTÉj&J‚¾î±öD97ò‚1HÉ Ÿ%VÚØ{<=ÀU£Ð{/ÙRPëˆVÍçB•pÅe‹? PùþŽƒªƒ™¬aœ|ÆŸ [3èU|PÏÁÏas'Pèn'‡KtáCŒ¦©á0a¸zdáÒÈ»j`ðûÚÀ*€bCŽ0ä¨)>à‡\þYU÷¡raÞs=ˆ4d<éüר*y‰uØ¥ºt„žÜ˼¤½/ ùV nï_› íÑ­Pj5TÐUò!tä cYÁ·B¬“Ï!Õqä¡]f·ÖùLêÐ,£[æim-¸äº íX±è>i¿ŸðÝ÷8„»+Ì:uc ÌÍŸ¯E}A`Y«Š IpW‰=/¹Ô"`I!õ¬Ð_Çaô¶_gÆi-Šò˜Š Ü ­Ê Üb„ÐFòÙÌÆúÏêôÊ…`E` èਗ਼ð; Ñ®}Í”ÁÉq•”ÂÐKN .ª ôZáîëVz¿˜Æ1Ë)膼2‰†¥ü­°¹êÿHT†0÷˜õ6pr¾¿ùhæDéð zͬÉóÄã5Ôl×G€4ª†•€‹aåtÆŒ"FiËAûÝ–â‚3 zXè ¶ ¾u€çœkæWé "°·ûÒÁò¹q‰×”(¶à ®›|o» íz‘Õ@aØ$VBñu+$1i¤"ÕpÃr¹ aÈ6ÕÿåR5c6!ÖL¡Ýj^ßw—¤.%_ø{ÌœÝÕÄ¿lþôÙÐÕ+´þüIdçïô¶{úÔçs–¿“ÅÊ!¾91 ¤Ÿ ¥Àï‘ÇsaÙ-Êîð‚Pñ‚ âñçkqÊlµ†˜d±£1$›ÐfÃSލ\däÐ_¤Ö™¯sq$Aí˜1ÃäXàÜb 1ý»çG<"·x2Abkjøl*ä´Â R†¤£Þê¢@„V@8–4]FŒØà¦YÙc,”OITP;@ì ûŠ×rØN\wÞ‡»Õ?ø¸í…¡ Zn]µëÍ Â+UÊ ½ì‰ÁTmOŠ>L#ãEÐ<·<Ói…XSÌ!täÞ~:E7ÙAEQXª@Áõ@fÇ_¼ˆ}ø"¾àl%ò[ÁP°EÐÀ*ÅDR$HÉH›–X I$ Ä’IªìÁ³g5£+1Ióó J•©©m¸ÚcB@ µÁ˜åd°)i,@cï@º0iKA¤ó‰šÖd¬¦‹v„!0¨‡â±ßÞÁÿ—‚qªv½TíO¨?Èb½”"´wE+iÚxAKj"2YÓ°§õý7¥ß©‚ϳ6}}]N݇¢`Ÿ×±Ð& õbüÃÐ>èB¥aû¥• ¼%8P€’„$ŸÝ›ÏÔ»­é!'$‡§²Àebï÷Ó8÷Áˆ]ƒ×õ.döÿ«Ä '¹îî1:U§|@±POe”qVÔìä¹gþØ€y¢Þúýgôì/ª ûÖ/d}rU¥ë±ÑØ1ؾX#°t½HHõC(~\ iÃ×Zžr:­Ÿ\!hS"=È ‡FýÐÊH:p¢xfXÅúa#B£Ÿl}˜OYÙê`uQ$²ÍR)eMå]—.{ö«;È”€”ì""%  y€`lm Pk$ˆ¯®dY«€ûžàŠì1‰:Ø›# RHÒÔAª ‰>D‚4§/t\ت¹9yŽ„©£؆­µÏ2VcY&Hú8Ðn“k½†êd cMJFJj䙦*¼FÄÓtÈÞy]«2 ÒUŒØ`É=œ™XÄc›;&LŒ¸åN9³î5­-¾ý'y´.à+[m ŒRÞ¾Îjã[ÿY›[¾ðç«®:]çœNÇqQVÖÂUv­B¤6aTâ1ÎäÀ¶ŸrŠù¼ni È”vÔ†x±H4}Ü"°kU"Ç%ÂyDÁ¸*†¡ #„DV_U~:¸]¨¬ À€H€”¤„1H5¡E’©b DAˆÀJl\= Wœt '8 )‹ ‘D"±V@cü« ¤ÈŽ@œùÔÞ8=&H„‚%Çpp×Öð ÄqâEÕ67ù¥¼R[~ëË];½ËïÇ`ûׂw Ùè‹Dl=ââXÀ1C@`|lcHdSi `„‘ÕT¶Ä²[ ë1b¢ŠÚT¬PÌÆÚUL´¯fSL$“S[ìdÕ)¶WVh)•€bˆ!@È …R\€`ôQÔæQ‚ Eˆ[*Š"µ–´cb$B€’ؤc²ÆÀâAÆJj”m[Ôs@4‹"½YWM V0Ì%¸Hx7K\jhŠ+“¼‰óÎçh‹-U$€ƒÜÔ6L&¢Û#$¥H¥cRÒŠ…•²_L“?oíý,Ü{„1:ÈZÚÄãׯá_K×CŽc4Ðl>"‚hI ÔTa™G  ‚Þ]~g„zuE\bчkÞÎf#åŸ]ñg±$/ÈU‚¿Ã¸Ôe¬ïWr¿'B:OµåQ5ÉjŠüÍüïBcJ{~}U ?Ü›<¦Ë_¡,¨ }aP™–äŽÅÍ3Mê⽞~_G·Š„tgq ¨!7Sp‰fgò¡5¦ Sðï‰} (äýèÏ{¹ìþ¿ôþ%QÛyã’ßD8„„ÍyIËl,fÔÔ2¨6Ø øS¨œ¸ÜÛƒ‹q®™‹ko~áß»nMÏ 'ŒÉHI4 ?Åtš½ú„µx¾¼U D®ãÌ­\?KÇ8uh§ÏU8-9rióA؃¿ª Q}Éô”ôŠL?CÊkÞ -_s\ö¹ð˜a™žßÙ6 Y—2P9Îýz¥t™K—”eWº8íæ¨:CêÕá׆ ±_ˆÄRŠL?)*PðÉ“ïVP¸†¾ž¹0jùÖ@„¡üçˆ/âw¼²(t‰þßâ<&×~;ü{Ù”¹«ñåëÁ™H Œ7ç—&sœö8wë߃»ò]Ù=Ñ©­ã·Ç^÷{ðs…k$yNÔéÅñûÕÔ½êÍh&‰mX¡$»®pUÐLR.Þì„­{3¹3ÙnR-Tò¾uÈ g÷çvrÔ\T“T1_ ´:wKÈïí.”+Zô í󼇪w0JYÔ8ü~ðªì•ص|ZÌ9‰³»±†Ø ¨p˽YT\¡±”Æ]fjàêêÈI5½5Óqîåú§HuB w~Þ:§× ô.£Ó®Óç½ò{õ¯(8 ·î-/Ô:íúã‰&Å ЧzwÐe0pÔá¶\¨Y`–Ö‘É“m ¼Ûµ—PG‰×œy„’E:N$™1áœÓ¯ GD 32vÙ/*vñnÖ]A'^qý†š§Lj…åVx×7÷sr‚’a”ÕŸ\dÉUmc¨ö“¦ˆ"f=¿çQÞÆÚ±wþ^Åÿ3ßéú>_J‡SÄ«–€í©þ¢C¦ÉÂ"Š>b x4jIíZŒûC§ëUj´ÂÚN2^F,Gš=uM%×&iÈÞG+ªµáN} d¤ õ¢püðýÃçÞo(áRØE—½õ+ðP¤GšKá³2÷É©#¬)Îí 36ü(ÓÞ¼}ïÆÌü …Ö… 0üϹÅ6G[ÐÍ5(A>ã»1Eo Ã+)¸škfÖÿ3²úcѮ샺n»éÌíx%JgäfZÒå¿«£®Ô:ž°‹û%‡„ì-(NlP Nà,žåÊÖ>‰x…ß§°0¢œ©”ø¾i ÏŸ:üŒ\΀N4 pT((zèGµ>1í¹j%Êà »¬ Œè.°Š÷­îÝ·{Kÿ¸å¶J*u$ؘ031¤BA?§ù ϰB9ƒïO¤DÌ.-Ega±ÛX¸Ð6Dv) ýAE ^Ì¢ŠùðŃ] ¯ 4©‘²³ò»ê:gåZgEöUüeü$ÙìÄvßgR[÷ú¯¡&œC®W¢BGÌFÑϲ*Uÿ'vHäç©ïÜðˆ_£á[4.£(g=9 áò¶U]mµ ™ Ä)"27(cÒpÇ (%‹ËÞ¸sé8ñåuørrSG¡?†ˆ¤Ãº{UÅ!~ †gPŠZv}uwÙwR(OŠS6t×nΦû?N¾8±í¹êm1ä\ñvÍ-ÐŽ!І‘ÑÑ„SÌuvHU_™vˉ zóDTUÕEÁ*IfI¤[¯'uróê^:Ûn²ðãÖd1ì>¿o‘ÅæØI¡ë`æ¶»M“[šÜ²»6–nÖbu¦CôuÜ“Næ¸óî.¤‘Óâv@ŒÊqžw'N­ÜfEDHNàJk<Ü©…rŒ™Âòæ¨M×—Ô$ûLÀÌÒQ ê|<˵'Á?ŽØƒ'D_N4øP2*΋°»´œþv~™`fn6OXW„O“¾X„¦½Üˆt0ÌÎÛej6–òÄ%5®D?¸1û¯Æýé(0"¸ËqIT¶”U¦Ûl/[TÛÇé÷óãŽÏÈë´5¦TVJTph2•bƒH°|ƒg(ßžk(Ö~v€ôzdÖÁß4øÈÕø ~Ú¯sð+y¬…àq,TkÅ \EîÞÁC”öV¾ v_ˆk¬AŽÅ5˜‘lÇábîR`EuVÀŠþ‚»gÏÿµ‡Ìøõ¿Åöaå” vf]%}w'G¿W´þ¦SÜÇ\ºnìR‚²‰í×új(€ÈÈHÉ$P„‚ Æ‘‘"A` Oúß^ã¤ÿ<øÇ˜ûI*¦â¥è¢ªRŒ•/ñd©¸üSñË+`Qí<±ÚPíìb3®ìVPn%âýþWù—8¼Ýt’IŽXišfáÜÄ"c¸vÆý´iÞ„ tu6+°( QoÏ™ÍP/ýþ„óº‹wæO)èŠ!BÔô5ºÄyt5¡ë8–ì:ý#'¼d…;P;Ì( #²HÕJwù{ˆ)ü¶ ø(+ÇÈ·Ç Â˜"°Š<ÍmõÔIL¡¹ ÞmßÄHâiXa·m¤@z½à,“ÒrŸ$èÏœYdF.Á¸ÍÃ̪Á+Œ"DÊ1“m×i’uƸiF2}¢wËcºª£AI ²!$¥QíXÅQÓ9$“ œDÚ=ÂÐ@`‚2rH-KBŒ)JäsÌ®™Œ "¸d)š¸t• ÂT©0Ö¬5h¤%¤;;éí±á¼ñ8ôf†DÓ‘EwÝ vˆw%«„Z%F'xŸ×pffÅ®ê_‘ŸK¼Œ‘ 9ÕIT9VtWx´¾U‘v¦(ÌÊ&פD ð8 1@ ô† 9üLЄŠ)¡‘®ÒÑø{º€ð½”•Ï7RÒZ´(yh=2ЄÁª÷y‘K¦€æfC¡°—]C;!£Q†7°¾<¬Œ¬A(Œ}žÎ½¦IJª«´ñ€Š‡3íœ ¶Î»5šUUd˜Z¢HH¢½â+B+Ü"²Ò (¢†o´p8âaëd#ö‘€(…¶H(Œ (0 RþT{G¿?¸l9Œ eó5˜A0'#ÏdÈ Tz+×´,@´’DMŒRÈ+""V-â{‘¼DBñÑ ’ *-@Ä‹rȰ…@ŠHT¬"†$†3¤+©H (¤d€ Âc%HÜú"Ñ/–ÌØS)E˜É©90ÃD’OÞ‰’sâaœmwH‚¯‰¡|ƒÄ Üc¶™ðæç_¨)=/_(eb±ë(ºybëh2ðbµ(ÐT¸™H½tVÑr.z¥€U"[“ÃŒ„‘šÆìç -&ËÂfG†²fn&Bò²}ï)Ó3b@‘àbØçÍèó-¢⢳0Ǻ™…ÐÉR%´l¥ Y§JÁ`,…K ¡rU®°ÖX ”c¡Fjæd·0p$“D$™¤Ê6ZP­d–Ë!­\t3 ![1±¬ ÕS)U2âbè–Í Pk)c„$”.‚N”!˜SkµmŽÛS ò!$vMÉ:¤•IZÊ!²J¨¢Åî ºÉÇ)3s}!Z6ÊB²V – µ°•Çwÿ¾þFŠç¥UF«ÝQGÿ5…m®²Ç!È@ìOèM³]@âA5 H '| "Ÿr¨H@uI …àQgYAÐèYÛï¨+€ézT˜ê,Û>ïp[ê±ÕA_¼E Ãóf¹CÞÉÇ„D~È$ EAaD XI°n§rUÀšUE!1–KP„œ¨¨ò^/  ^!Þ ¿‚ì 5’`>l«u–#† \.Gp"³tùÍNûb3¸¢§†Áôo™jÄu-XvKUUUQ_ ± 'Ž’GÉB¡ìƈÂ!!|´ 2ug(Ô¾a =¨ªªF ¤Ç|mNÞîÇ&Žv*t`ã!ù(±3u%ñ× LETã“R“¨‹©’1Ù1Ö4Lì°1ˆÉÉ…bŒj3£:µ²fD1¦gžâ+líeµ¨Ê;âæI &üSd6ŒË@ïx.øà\hZod‚Ð D¦å<‰MÛ{-ón?þóE,*@¦Mç.#ô8†ŸÏÌÌyîÔ`¨©¾gEÍЉ×ÿ]ÏBsÕln€ƒ"øUCgng¡(…GJ$”…j ˆ’° ¬¬‡HHCrp3ƒà÷X"ÏrËDVRŒÈ8Sã:ßáøzßÇôÿÞ—§øœ÷­ÎÖõßkóÄDF7QZàBqx³”F·WéQƒ¹¦Ü×Èé»3htyT-Í@"õ'î;€€`æðx}·]ÎæîÏWì2~.Z'Ûa®æƒ#:´7ÚšÀ ŠÊ4TT(4 ôAQmAXé™ Ä(JJs¤HLuAZ4D„GóýL*œU‹ÎUõ„üHƒ Á-Âo38®/!›ŠX .éB®Pfþ‹WF^o+ÐC `æx_Žx²á´4¨ˆ¨I?"”EjRín`DØ«öµ$¤ëë„’FE‡/á¨Êe1#"°+]Éž# NP``ʨþBBDb*¬“ùŸkØaàÉR1"&NÓE/‡%5Ž=l J™ˆ•W j+ã ĉ2Br„KXy”; E\²ÁérŽž²´m ùXžOÂItÅÀ`s¤uPWôh»ÏÖ—úqì–=þô-W¸.X¥¢4=å„´!z FE ºŸ£tyÐïCj|µØ" ->ò ûzÐwÐQx‚*ŒDŠ/ è2ù©P˜2ˆz¶\1Ž1M³ªoK†çy¨yþ¬4Œt•‘´kI)R„$ŠsIl–X‘E„`ŠöàìÉ7QˆÌÚÌjðéxŠA¤$ŸœBÈbÀÑ´A „VQ³ëó‚B`<¬)CÐÁ×®GãÇ?]ÓNû¼´Y‘DPŽ×õËNEÅôj ~_oüý]ó8ŽÿS¼øß7Šë8Ì©ÿ?žãƒ"h Sµ*¾ÁYaÉòœ¡$k ?O‘wS†…Ò_¿`V¤' +„ÂPã·ûKW‹Ä³”¿/Ð (í/{ÏH€\¡?ëðW “ÛåâhÖ¡Ž7bòIÍfX6¢‚”BN,H¹•Zä+à™<³ZL—H= ´#a–K c€´˜ žQoÈ È‘‚Ám°:'Á¾¿=yy7ÍK"”` uK2ØÚ Œ%VA@¢J™b\ü1F ´E”ÌU`( %fIdÐf”–C’¢fæ„^UBHHœàÆ%@q®³I`Ö©ìAàD¦Ä*2b­ˆ °QHZQ¶Éx0ØÍ¤å·xÈI3°-ˆoCúÑdXT*™ÿ*w¨‘¬7êíHc(™r ¥ìg#––T=Î"a:Z%æ+n )hÙ]!à~n—ûûOŸóû®«ät¿ ¤és´j÷ž¦/¶wmߣ±Q˜‰"Cá#Á|)âSOàIP`E¨ƒr==ÊU üÐ;Ë'P}{½íŸ ø{¬`¦4$XÉ’!‹dbDî³³½‡èõ¹¥¤fu’’õŽŒá $E·çþw")Ê…(?½ªh²ÐÿÉ¥ ЭD€äìÓ)¸FÜÕßW¯:+s¿ä[Ú·ç<`-uü;ÉÇXÅT# Uý^+$šV‘ºiyg#ÃÏùÃïT·Ô Ä$ 1!q++$¨ î88p+69K Iû¿€îŸäßÙA@ `.GæÏ߆°µ¤à("´¯_ï¡l(n)pBÜc¯¯©ŠV’ë­çLhs°PÆeß#‚'ÔgSÃsz€¤î;?§ž;Óˆ§q&S6ü²•Í̧,…]–ÇÚ†NÖßǾ& Û]Eiµ¨¨Ñ v9ÙnnTÛëñ˜BI£†Öosi´5rgc'b‚l ¢‰A–~ôY£“°K(V!uz¿³wí¬XœˆÃìßá1bAJ†öù8×s—%JQàÿcÂH›>]Áí?ìCÏxËÇ>U0T!¿Ê}»ðO‡„ã®I/}ŽžaåˆuÂ!§#+uîÌ¢/ÇÃ%j.2ßI€žó£¤ý^çÊ&hD@+(<ëÈ€x?[û¿ÂÙ¸h@{:Ô7¹ƒËzZv'`x@Ýç(¬°MÎ~ÿsæ8÷'©Õ@øË™pÿ'E4E1úaȃ¬¾ˆX*ÕCÜ!£„$†ûèÊ%YН<®©q±##Š”˜ HF@a„ <|¹¯ÔíôOiêø‰ùcݯŽt}Az«ÖUªV•(ã²Ì…º¦r7cóþŽV›é·Íç?Àúz‹Çå}­áí=ÐäXÓ/gÆp”ÒŽšif}LI1)Tˆ&–’( M3²¾ûÒsi, ËD¾0ëOµxF(¬¾×'Þ>à¿ã‘™ÎaUC4n,§â×BõKeG—†0ؾ‡F{žZ¦ß·Ã¢K‡—¬9ë\/.J²›S“RÕ6Àÿwy˜¥?­é¤a8´Ôµ…ß‘êþ¯÷ÿ¶ûÿ£J€ý×ÈÙóþ’íÆóŽ•G6oí¡yX€I ráh„ û¸KuãÍÓV}Tð"ÚˆC™¸Ž9àâÁ0êPäSÚò/÷;rçÞ3ø²~4‹V`£s¿“mÃGĈNk]ÛÙ×6Ö¸¥ŒÕ"†D¨`n…võO“œê¼¯'´Þ¼¿¸;4,ðýÍÈÞR‡’*nƒÊ0À 6%€!€@ " ±Ï>D·U‹//÷ÁÔ‘ýKzQ]FEÝ‘$·Çy(7cáÒçWgÇ0AO6W]¤Ç©îÈâí (•~¼VÌh4÷Ë"mèÞHÂ7Д]@•âs_éz›LŸ Åb¡¤kdT_£çÖX䦟ÏÃ囘A=Ïc@o•'м½Û°¾$ÛqÌ4Züv=¼SŠïW{ \ÊJÇ»Ýí»gÉ.öGÌ…Ê4}¦;T~ùÌD:³ø´#ØŒ6Ù·lÏä Ý©õ­.1).ôxKçšÓw9hð¾8váÄÊ“˜Œ-äƒWö×ïw±Þ;-™eô¸rÉÆEv½oÓ-´«i„÷àx¸/)8è‰ #¯ï¡ƒÃañ77¿T~ÉÔ¡¦¿ßk|>ï÷•è—çÜçgbgº\~\:ùh9Ø,eˆ NgØó„gàB±3^Xsmj‹«-eôq:¨X]<2ð|Znh¹×sÍv™‰¼Ž…?ák õΞ¡«²àQcIöc{Cc<ñáú ³_1”$²2~Ž:4ë^ EûNNøð·<Úk^=ϰˆîî!ñFP!ö_n ­üœ/€ìY¦‘ýsSÓæò5y.{½[¥oLÚµ"VBÖ/³ g‘‚Uçó­ÒI”( T”DÎÑq;ùQ'Ü‘hZzóÏ>›ë·ˆç²ÿÏK2M„hNi,é>”žû£0gYÔ.]źðAœe-x›<ÞØÍC"ôÞKÊ´#ÉG¢ýRïÈæÃt,8¤¿ãú3yÂG0L8?§hñ©Ðˆí lÄrÖZ(-ʆH^Ùö}ÿ^æyû63–„õu½r(œ¾U£|ŸLuË?g·@ú@.þ80yìÝ2òî¬éÇíä!X6ml`R·AA<Ñ£Æwø’á¦>Ü;r³.*í–JLó*D•þ;Ù§0ð»Ë…¢Ž‹ØþÍ¡yýÿ†KKª'$D<ù]—öØ¿²tú­Oñ ßÇ UùI(qÓLxñSŠ<ÒËj®E7|«ò+)Œ¥øQHIØ!UÚ‰i#Â_ïˆ!Ñ:¦··Då94Žm:•$¾ñ4ü››ºOÑ>Wí=Ì÷uPt™»3êíæÏÉ-1§!KH>c ÅVè½fÀÉBSÑ¡ü—ò¤ÙzLøñå͇‰Ó/µlÏ5Geh‘¿DsS[ãÌþWêm5¿#òcsr§#5ÇC6Ooæ*áÌYÅu9„?¶ýê;xH «Î®A & ÝѪ²»Ð]N£ââÍœêõ?»ÀÛ6pÍëþ?M#Ú·l:u¡Õíù&1{ßVŠ\ëLçXÞÆ–)Çõç>i&-³þü™tJ°, &Xð…Jl×ËÇŽaV¤7è°õ`Ž)6‹åŽŸÑÌÒˆpq<÷‹U\ <ô¥'³yG|èn„§Ú}#ÀSmwž¶€ÉiåsÊxÅPGÓ£®chß½Ñ-ljJ¤|â‹—„û]—//gÑU³~º† öÒðµ]Ý\è_æVyÞœ lÄݹMOŸnÕ-¼P¾‡Eå<Ã7R3  –<~rj¶²-¬m­šæ‹‘³>io)ïí¾á&£òß·‡šäþªy|2Ò-ŒÜç5îãÚ V›1‹±‹Æ{¨G»ý4ûy€ ‚ƒ° ‹®ÎâŒüëà~92:"lwz†-§ Ø ê·øl.j¦¯ÿ]ùÖÉ„ŸÏhÏy«ŠhlÓU¾UÔš9 ɇËP߉ôþd¤öµyj\º±88Û¨Ÿß/ ªƒq¨ lFà3(j‘ÈæÎ¡ð" :´RW“²MML‘’–:NLnÂ!D{¿¬ñ“ŸÁŽR{¿4³[p‘ÑÝÜ9f¤ßÓþ».‚˜¿»@þ½è2¾aöBgÚS;Ýpô„!bÔõV·¹Óôïcýôtëvýˆ^üW«ûƒîûÎ uþ”}ŸŒ)f<5v‚ηƒÓѽsæ¡C¯ÚBT“É#wµ*[ÿûb£KµéC"³!÷†qº›Òôï?ƒ¡Mû·ý åpc<ØÝªÅÔŽïÛV­u>ârÚŽ—*gÚÕÿ~·Îxø|¦™!ÐÒË(«V²g 9T†ë~Y ëõ$ØoÆ%TM9ÞãÝ»V,û CEb¹ßʬÊu¼Hù02„×­»—ª‹‘ñ2“…Š*µÁ ü–|ý´¹‰FŠèÅu,ØcäÊ!ã?û!uAeøhm“èîd,yKâz‚|–T7žC•8&ÞŒ~&oõ¨8eþ·Ýnöcão#ÂSñ'ÂTŠDb«GLö?vôYK0¨dØüï„MC!˜‡_wV¤¬•¹Ø“Á;+…¿ë–£*ïçËÒð`Ö!só¸È/ÓfOû²Ç¶¦ÞöV}=ÔDþw_ÇUþ~~%<è)UYµg\K‚õè¶A\S¦> ø]HA«2÷·'»ã<3f€€ðv¯s+\ÛŸvη†2ža¦¥­ó÷زÒFîççÄ[WwüFUû*ei_FÜŸˆÇ[²Œi{·ýa¹TûÞ¶x0¾·Ó¼G «ßÕY4–-XwÑ|k04°ˆò¸iݿهrv2ì±ùƒÏÊ·;þ>}ân ƒ¯¹Õè¼ãsC¯-D|ñx¹‰™ÂTç¶(z0SÔ Øï³ ÐçltäÙÒ1vtmÍ$­Û¤JÌ/’Š®IŸ§z§í»þ·tACñÌt?[’o1ªõØ æ‚œrbP²žï,Øïp©jh”.²ý&ø7R7âGxUBi¸™¬úÙ|X¸>Ãø1»VlG6GȜՄS£ÚßË-ówŸ.b³³¤Û†e“§™c®÷æGÕ#ÿo˜(ïÇÁ¸ü:-;!X›=ù—KqñÐZý½ ÜöAéæî`^<ÍPG¬>*¹ÕLÝý?à~Þ‰ÕÁh³<ýù%(z4s%W0g ð×ìÆ­LŸÏ¯‘Ò­½ ­àNSލö.}šÎJ÷`ìôͯtÛIp‘TƒX*ZÕ±L$Un’—ê ÚùƒVój_­HmÜ®çLáüëócÏ÷ y…ý™²Ê(XÛ)K—ÓïÏl3®y¢Çün}n~¿¼ã“ã–£#¬´:E· ( ãëÌf$÷{¶í,…ãr…o¾ês¼Âg¯Þˆ¦ι·ÿ×\Våü½¬J –ž¯4Ù! ßkGNBG‡ Ô¯ìµTÁÞ»3åVd8¬teÕz{9Y©t¿¥§‡ÇL(Þµg—ßpЉªäHÑáå”hÆZ9X_ãä¿Ò<ìŸÁ… R¿’FiIõž•øoxdÄu2]ãï2o™{BuÏQÓÝæ¶‹×îyQzÍ\)ƒc(Z|ꮳiÊ/è=ò^Ø7Ÿ’ }oéÁf}ã)ξeY ÷-µ_®T~DŸÀz¿Vªbh3cIgsì—â<(¾²¦‡è„FCíª* -!}ÍNƒGû}8,[2iÔ—¿bÚÃns7¶§ºÓÒJ<,ùrMLjÆéÀyÁk’ÆW¿P-GFŠË¡åÊ›ýÙ´øþ®rÉgK: “òÏ«¡7ms«-9±´G?5&ü˜r'‹¸ S÷¨ïS2‘UÉY[Ô^ÒßUækVŒz¨yÞQ€i‰®{ž&‰Œ­ÉE…ŽÙþ jG™í.3É‚¯Åkòx¹—ÙFx|>"Wä‡ñ)ŠÈüSµÇäA î[ªk&÷è»êTò_E[¬d«zæˆÏ¹. ß”m÷j“¡ö†¥ÂCI[Ó¢½›RVDÛHƒ¥¯ið«R„ú¯/º¾‘y¼ŒßHÎ¥õmœ`Xiøévišú£ã?·.U§–G¶PìÉið¦zç×ÿ¾ñ—ÂGJO’’iÈÁÌïç°k&Çþ»d+®w^‡N²7î«<Ï…öJØKïïQ« ,”ßZ.†‡šÓ…!)gI°o·æõN¥kr›.Ì4:ÉÈ·Ò1vðü‹õÉpôý{«Ê¼ÖZ$›:« É,nðq6}Ÿž,­+´L1&Uû{-Ffwˆ‡nÐK¿V^MñUûCß3ôžçÿj|^žÞÐrÛ;= áðÖ´Ë{*<µm«ÆGŽáêß]Q΢µ–U¡ù~bíÀ¯U16[]÷£—Û…±i9ÒÌâ ¨ö¨[w;SôùÓ6M`ÄôݲÄq!V_ì}ˆçñ¸f×kS´gÊæÝs,ë5™Ó²Ëß}"Ò.ç˜}Íž“ú:Hhl|âäiwéÌæìçä`l¿œ˜îPh_YpúÇW,ÜËF¤iü—egƺ¢µKs[t»Î²Ç©‘Ë´÷\‹¶vÈ!Œ·¿ïóù4ž¿’]ØBÕ-ƒÇ;6ßæ6”daÞ“VÿÙÅ‹–ø’b×éÍó(e©zÿD<,íû?£Ù¾€Úåî]ËnÃùUÞúƸ'é~2?>â•XÛµÍ|jÏS¼߆…ýÄúÙÜÕÅï÷ÎÌÚHgûåÌ¿/Ë}d¥+e_ß53ÇѼ4;ÞEùÂEæÉ—Zðλ_3‰àÆêu\íØ?\!äîuõjöVõÇu|¡Ýc’ãäˆ@îKãßI5ºÚL—- «X•ÕdP9†Ì°Û& ,gºgò.,¼Ù¯éÆ\¯‘ p«ï~÷`Ãir²|¡ò†Àñ¼uœ6¤{nöªÿŸŸQ·›èå<-*_Åò¹ G¬QÆ0¬îŒB&èöþªž  ØÁ¯ã¨œ"I¹1/úHVv+%ûŸ]ÔÍO/Q\¸»Ö¤ŸÜÔë[ü²!¶n¼iÇþ¡®‡¢™ˆÕ¯*)Å?N½óïiÈu°QѨF&ñáïÁÊB´X>¬zz‹u9]b!2¾§ƒ¤ÌU즭>pBÍ`§OlBvˆ6€ÝÕàq+;¦Ä£|åVØ «^«Ö?‹/Oö’˜š¾ŠüíQ‚ÔÇøoåPàÓ”úðýhõì53ˆ.’3×+wk€šîÑÛÈMÒ©—M͡˭Ãy&á7¯º‹<‘° íÞ_”(B0¢^P{d“¿[L¾A…¡WËö®.äN{Æ–û÷ÍŽ@OîeªþŸÑhÌ·³¶æç˜Ó£ ÁQ·Æâ¾³èjiöU½g¹T«›„úCÕ›*uI¾CŸtküÌÙ:¯ÄW÷ÇM©Ü°únÓ=ÚÕ¸“!„Iç'±îæ<±xúˆÝf³v6Û¼.ï«JÍaŽís×¥¦pD;ßXÎíËÜã9û;&ýoÎ*R'8ÕµPJñ<ÿè•f²ÎõÖÚRXr–¥YåŠ|Ï~ê†òyä€Tæç–¯ýËŽúrsµÝ…ÚŽç7®>W›¸]‹ƒÖߟs×Oeï~9÷7‚½_óòöée¡™øX½\ôéúÇꨶԵg­TýsCî£í-ªiÏé¯Ï¾-Ýzi¤Ö$ R·4ÂÇ*Ùiµ>t^´ûÑ„âi¾Š¡•èáú×*Oód}¿3½uiš;¿,ä @t¢<áò8ÎwóI SKÝv>kµÏ4EBðtæ-°àJ'!™&7{åÈHÉ r¹Ÿ_= ³þ=Óâ¦ø”ú—eqw¸píLU®Û÷ÔÜѲ_‚YÉL¾Û•[ç«TÌÉSb$tÖ ×a|¯¬_ƒN 9Ø ÌKu#m²œÒ%ýÃì>œ^ÔCD×2Õt½ƒæwÃŽíO{WXÕÒ‹-‹ˆœ±bù½y¼žÜl7ë¹÷ Ÿaù’ŒºKšÈä’âVµEéª[O¹ËÜþþóýÞÓBuQŸ3¦Sg‚qAÀtïBüw§ûÿu}IO¢4~Þ+Jk÷N¾›îáð vßÀ¼ójºÍVM¾#âÇÜ•I…M¦7ðîx9Ô[mª8Þ(SYíͤ¼›«§}ñœóÂ]䛌¹,nß î²n³ö¡¾÷ÐG÷Oà }Lü˜†ÞÙß]¡«²ß!H¥^Z A eá€ÙðòI:_”C1¿×*ýدZ%)JáA˜ïüÏGuœàü&üE (ùMÂåw/¼=ïE.w7Æäóô£U¯¿¬TçdÐþ¼°ï¢Õµ9Þìô#ì† i·Ý‘’0ÑJû'üÛÜ1oå4ÂL{V'S·=¹ë‹;uœ«Ç½6½!›!É-Róƒ¯[r@‡·åÇúÁ•ôOªû0ÅuZˆLj[ŠHjó­¾ùæÏùú R‡žR×þá·Î÷ðyãôb"°»ðsð˜y¿CF”â(¼–M4* }B»žúŸÇkéÇùO÷EŒÑêLŒMk“áP×ñq¦Ëüª:\=A¯7kFgÆáTUŒ{ݳÔ!’—c!½ZMr×ùôy=:Jõœ]ÔY_?Ô±,ÖMC2÷hzïaZ]|R ý‹“8œ£ýùsY„÷÷g‘0l®X®¹ßZ&!gaÞW)-h(âŽýq0®”Ã×NNr­™R¥Òž«Âèx†çŒ ß§©ÐB ™S¶¿¡T¬·»uí)úlpY‹hï\WáÈçèà“.!“EÃVˆj‹¾ë9ž.%îñŸñx‰³õ¯‹ìHÒÙOÈÓb©×ìhlî=f+š¾Áëõø^aËGù‰:çâ»B²~"Œ Τ”šVÏl7ËÙuQõöÜMWn?2N,Ù±³£‡òÝÛ¶9œüXk´ª›;z ¾XU ’’áósVOâÑ>R¯Õ¤<³ë†£I)Q©¿¼d­ö©b{ÿ›²øÈã.54ò/<—‰c‘pp¨ƒ •›ßÔÇ6©Åôê)p»ÞÕDwö:¢V›r×g'D9½³‡ÈínDþoŠåW„]bÌ—JßÍœ©Û¤õ:šMV ·óçGl•Îö}ª¿ê/¹;×Ùn@úÇšÓncðg0TïA1õî;ã·+òîù¯4*žÔáÇRNøËkq-å)«E°ãzÞÈ]胮'ŸüWƒ¶¼S„Ðßõ·7Ô¦›ˆiZ Ö—Æy¤]Çi±léO²³ºyÿ^ÈuSOÜoâ$¹Oµžžˆ€_ÀEÔ>½š`o¨öGg}Jðyëh7èĽßyjÛ9r]&ä5=¦#s¾3/~ß8™›"2!?¦ÿ€¦jEý_KzžW·[Qg„„ÃôáâF²¹è;y3æ. {„ŽÞíÀ»Æ+Êðf2Ð@)z ÜfóiÍJÙoqÆë¶\ÈŠ]ëzZ1üÀ§çaÚpšŸš^à. ˜+3¼Ð¿ì¨¿ ·FBý^TÔç1>{‰i‰¬ç(× ë±A±a^½–Õx¨Ü¨¤›Œ KOš—G%lʶóQiÜ©²·‰ÿIßµÿMÛüò‡R-*$âÐ¥lÖ>++ˆ ‡¾˜¾·›ò5½V¶Úÿ¨¶ÆŒÿ„Ü'Ñæk<…¤few–³·¸«ÄîÛŠ-Ëoäò ©Ê&+"`¶‹Ðq¹,S¸³½æ<ÈçýTŒ¢¶åbœ‹m/yZ”Ç úŸq›sæ·éïrß(õùë«~Û㇃y½|i×2¥¨F¿§y²­ðùz“’0 ¢òþå꺾ÅWý»s%#݈ÈÛ=/ƒé_xµXŒ´õ⸰tÓEëí]#{¹D¶¹Óš§ˆ[©û½Ê"\ëûùr¯#¤Àtäëj…_Ô¿'>×¼üÀ—:»Ò_ÏHar¬‘9^É7ðB»hf"_;.oi:žÙ•1&Y«@ÈBJ/éŽKŠX^·e¸ú·»¾„¾AyÏÚ]KÒÉXIêÛHš8?\ª¦=IF—úªö†ûêçòócŠXÜk¥ÝÚÝÃ+Ž´‘·™Þ—|>„]k5:‘p8ÚP(ZýÿG*Ge0¢Éþv¦_'>çþ±ã³ù稥û—Ü‘œèTâ¶’¼š±X:¿$'O‚¶®4×UæŸù;Èð™;™“QUí£ù~3Ôyi½E2ã© æ{>–nobo¿.[›Y»¶~ÞGn«V-ŽÝÀл8À€Ã=І“ݜڸ¶ü{(ª#nþi=nQ”dš­ ~ó!®öfò‹Íâïjo‹·Fóf{~çÎÓ‡7+;ÀÀ$ºûJ}Ó¶l½Êù|½:ãììÝ–—žügн]rÒæÖNQ%Áüê¶-^PýqíènªÇÿ¼ùp¥ ýI1ðÞU ö´m­yi{¡Þí íkªúoèÄfSGjé¥8¤Ï ÉöáP­ý(0UPýjŸž$7#ò`Ãøú¡f°©::Ia6{Ÿkså©‘tõùé?¥7Ä(·as: ½ÙÓ‚ŸWr·\©¸È©e‰b<Üå µq“y™’r$æx=jÈXšó¾ i3Ûä#:_F‹;7ö–‰g—Z5ZÓ`ðîvš‹g¯›“ºÌ͉µRµ–.y½]ÙU‚I§MgOjì…üpXô|,¿zd¢Üe¼Ñg¼G¯`»å¼r9„?t~´„okÅ[h˜â©Qc×óü¿Ç}“¾wR½ †W¥½j³‚(ö.¾$õBü_w¹“‰ ˆ˜uïÞN`ôŽùQÞûv]q&Æþ»íg ¥œU½Õ?pPÙ½›_mÞÝ‘ï!I,¯Í¦^/ÇN•')rŠq%§U½³{ölÛȇg|5WšFƈ¸Ð25 óåyš{¡r Ý¼­.ïiâK*2Š®Fk5_w3‚¼u×cÛÏíO8´«Åв;Fº~éôüÛë½-È®o€AæïìzqÊóùU ç´\æ!št}?õ뫯?¾Ç‘'[´öÕWÌøqZ,=iTÉ€ZÃ6ɬ*+áó¦ñEkËT47ýƒ½z™o´†—TÌi -Ì^v§/ò€|[·ÍùwŒtÓ··óˆ¼Œ4ôL¡-ëýÍ»[Ò·ŸjÊÜ’HÅÜ©¦¤W—7f·D÷, ¬ ¹V]Cº¶^óïSz}›Í¦OCêÚ-x:,å†n r­n'Ƀ¥Íª:tr˜ÖÆ¾óœ´ fÌ’ÃCª'Ëu(šËÄÆçö9çÂý0õ`›3™ü·1ÃYižKÆÁÄ3¾»(×\üvÜw•nq…t ©qåûG{]!Ñ^Ÿ½È±—+Òóè‡hžå®1¿£ö}Ù"9l7È „«Yå›~Pìî2ÞéFä+˜¨›ïFwújü8g2<¾î*LÍeÛv LíG(ù_þ†àÊì`º|àÙm ­\\…ºInÝT Î1% »ê„ò/ºþŸLå•|mýÃûÇòE¤Û GQžjéìÊ0n5Mqówùr€ôB»Ü 18~ï¢r,î¾·—ŠrOw©®á{ÀJ-Šê´¥§ýh þ®’Š•Œ‡¿O—RˆŒWu“‘Ò´ƒkIZ½ç3sïç/'ÒÓáM¶{þº=†éFA*å>ªÙu©¯±íUrþ â»@äkŠvT^ìnx½üT.'(|_@»Ž[{ Þrÿçì^{pL;R;äb-Ç3+µC/Ú'd+}K²Ìý=¨bh‡f5eW]Îý†ã·‰ÌOI<þ#…]p<éÁß+¬¥põŒRgþ)<*l}*õÉ—ÎÇ—yò™=3Gÿr”U6]\î!`{úÉwm2Æ?Öã.ÍžGÚ€ÉÅ ’õ|ßJ¶ÈÌ* üÚýïŽÿ ø®Ä<‘¾ª¬ŒëQê—v¥ñú‘¹#`Çï̸&v¼YÜ+IÿU}wj®<ì† ÖºaÌ­Þ2öæ¹YÏıIAïÀ»}h—9l¹.…IÒ‹'ÌaÌG÷x!Ë 3ù«sE}LÊ xþnÜ® Ó$ÄýšH­>µÉìø£‹ãOðèÊ?¦0`/ƒåß!Ñ4꽺¿ho^¶{,©;t•tâã+.Ÿ<ç~5Sïªßx'®§sõ–çüçõ–:žy"û’ô¯K÷&æßk­š…I˘/ðÐaTùµÌ[hâÇÄÔ}`­ó2™é½í™hÂkBtú ©0ä,)‘×!ì{%Ø-œèúu›äŸ3w¦{= üía'؃M M <»6Ñ×£{ÍíxÿvL«“. â®Þ@ñÖ'þ¯,¦$‡ÀfXÄ{šk™ŸƒëÚQêt[qýÏíå“Á3w²Œ™øŠCÏ\ܸÙdE€Ö´2Oö‰sÇow¸àò@Ï{õÏ0ì#µ½Ui2¾©aŸÈ…UñK,G϶œ#t|?滟ñfMéš:r•\ô)ýPÈÓìÕ\w>ÇWM±¾çßÒ騵SøÁ1Ûi†ê}Ù(J*dâœ,µIFÂä¶%õ[yZj^Žw–­ÍIø<(¨>gè¦>r³o%2ñÁÖîÍt­ŽÇU;ƒû¹š-÷$¿é.u•µ²¼E°4¶¢Î—·gs\n4·îçL¯dâ9šÛäF¾Ý^DÐâ•òçÆé(¾³lv˜|ørä¯j(kGJkVÝÿ}s=e])o‰s+aES‰]ªYþ¶Ó³ ðÄ÷‹»`”S‚FQÃØ§Üš´`7‘æR5´±$?#¦vÿ«µ„âÆuù/CÑYÿ† L9”—K֜ՃøA^Óíå8üO»›±{ÝCOÍvnžöûiß×Ñï.‰ÜÉ÷èä°u•Š…ƒÍøßèÍ:{®½›§=I“É:Nâ&Úvç=hâÃø•Æfýé°º}Œ°éŽºBÅiäL@þºÄý×&ýèä_T2½2„m— G{üóY0Lö¶ÌäŠô‘+³‰ý§ŽªXÔðxFÞÊ·x]9.¿iÁ¾NDV1akÀ¯S_,3k²Uû¼8u§.‘û—ý낲/ää³èO¤ånΙÑ]F›º¬9òõ öibùÂéêÁÒ@œç»Y-i×b—òŽ¢™ŽtHô8)Fíh–j±=^ÇÈ¿7‘Ã!áæIl5°G2û]^ýüöÎÿå JŸ¥îmÐI úWﲟMå]ø¨ÚMí3|ç÷'ß{p\jÛ¢ü[®´o”økéÂÇ HÑíõ[s½‰Ð2²ØÍý›ß@¶«)^ ñ3ÿ§k‘·’ˆ/<]¥>#Çæ¯ï-þgjÝÂû“ѳ=rÁÆyéèKœ$îš0RvgN¯¾) 3šÒ¿Ôºÿ…¢(7??Âëmf¦æ“®¶e»øbù¸ç“ÉÌ̆ «³hDÑ>GUS™1Í0r/*pëÜüŽè\ûÏ•Fñ @@OÏ?\nºŸ>+¨×çþÔ÷¨×Óä] êYˆ¦Y×{Ê:R]{T‘C§Ê“a¶’ÖcÊŠKR§ÜžÍòI_~3V\<-¿Q6^’å÷àŠ@Ó<⦢éÜ[”á]í>êàôêƒáÿDÏW¶é•³ýæÓOß[Ñhyƒ¨—›$ñΙVà~ÍØÞz®ï~ÉØåk¥õ똧k{3ѰµÛÿŒ¸þ x|Åä?Y߇#êøâõîÁDçíÎù³8Þ8YÏï¸æÑLÅè¯ â›(s­fÑÔx‡¿º?ögë§÷óuо&õŽ<û“Lª¬m¢Z2:ºkÎ÷êíôWe˜ô$¡x2е¾=ó<Ç|eÚ?AýÅfº9«w$ÁB3çÍjYkÏñ~:~x7ïíô}Mù­d.jjÁl;ä‰ ?ý—‡³ÅèÀðr±8¶NËÒÇ{˘¾#{o‘‰S£ïV¦á"º\œ¦Z.¹W­yâæø>fL‚ë'c_ÝûßWÓ pž7ϾÎ6Ëý ‡Â&ÂNC¹A+Èÿ#GhõûU[úC{ýG"Ê“c•/ì·ßËŠëòwƒ]§–m°¸.ó$¢äª7 ~ØíæTx2ùŠ É2šÎ…ƒxð-ÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ}çÜÆ-‡·[À Sïzï»Ý½ë^Þöt‹ÜpøKïxï‹Ý]xÚän;¸‹ÈÐ,º)Ѫ4ÖÌ: « €€ØE*|{×/®ãÞûÃç¯K¾½À Z»áõ£¡¾µï¸>€÷¯½»¾·>|>p}ñ„Û£¾àAîX6Õﯠúo‡­›Núõôó·Ý#n[k¬TÛ«.óï[^ùŽZÛR•Fîóî|}¾áÖ»tå}òûƒÈ}5ï¾áèïXèIô=ö^÷}ö}2Ï} 7³ß=z}Þ»ÔGÛ>zÓx î@QC±ôiv“] r¨µa°À(K[æÀÝ'sê›»·¾žU÷Åîø_}oiºŒ®k ‘åÔƒ3ݼ`ÚÆ{°{κ§AÞî€=õ­›¾M]-ÐkZÞæŒ6%O¾à¾¼èîÜÙ¦žîåls_w=©¶Q¶’:3MÓIU^Ûn'»S’¤Mƒß}ëãèêµM>ìz[ÈuAm¥@Oow¢ t°‘ë®”ji·VàzñulÅÖ;Àb»€iHŽˆÛ2€#饯/ov®T$ +X û]Y(íÇ;™}K‹ÞùÓßvõqi =ˆ‘42002dÀ#12b2hÓ&“b4Á0š4É¡¦ÓL†Œ‚4@h Ð@M€!¦€ „Ñ *~F ‚M¡¤Ú'´„Á0'‘”mÊ=FL =#£#5 €dhPb4dš HBdÐLDÀ4hM&m&4O&#MOj5§©´ƒ&MCz¦ž¦OHõ=COPõCÓSG¨diê=MFš4zšF44dÚ€ 4M$ˆ&&Ié©OÂdiOjzdÐÊž6©”yM¢zSÔhÚ€ôƒ õ=DOSj¨ ¤Qêi h¦€=@€JI &€# M4`!£M44i  ´b=“Lñ&©úiˆhjx†šdC5='©=‘£ LOQ£4™3)Œ“ ÓA¢h"H4¦š¦Á4ÅOÈ©ù£IOaSòaOTñOÊŸ©2Se?*z›SÚ55ÒšzåFe&©åêjSj=LžP=ê4xQêz€z‡¤Ðõ =G¢°ä¿“þžocLéNE:øÏËÇ´3M@ùt¼õøŠw]ÿu7¥wéÔKý¤Ÿ~F”ñÙ?‡%åïj­. ~®ïÑoAIwmMè}èÍ¿Z·E°ºË”´Z­8Ç £°µ`ŒH)ÒÈQZ¿ÔLñ𴙟å&-ÅmÕ[Ùç:»p¶0ãŒ!Æ0ã;¦ =»±BŽ÷èr•…#5 $tf8ÁIwwÎ5ènHohÈáÒ©Á ‘å곚=«r2v׈›)³¹Á¢£à¿•Îk5R1dÐŒþ—ÚŒý E„ƒl! ÈTUÙ–áþ³.˜1˜ûŽhªi“F¶å1Ș…ej­¤’V@.Q̉*ZÒÒ… €Qì_ºáÑ‚S™ÅøÕ‹ÚB¸B'·nv€(~Øh¢(ùS¹¡@⢤Ҋ¿û@êâ{(¤ç¢#“1 }o¥Cœ÷þ…_CÿzOW[[ø¾ý?÷Q@ÞA‘è¦ÊZØü´@×ð)ðRýwÔÌLÌÞ/Ó}ßÇÛïþ4þ;þE©{µ3J‘vWä\ÑmÒ‹œ(©rên&Œb#QO#Ü—V'SRUIfÕÇÒŸYC¢Ö÷qõŠ™»¥'9åÕÐÎzWüò’?ËNêªòÙ˜XüK'ˆ<€ô€ôz=VÝ©™uuOPþuq7ç§yy$§g¥žxqåEJtòöîøs ="^%æ%Ý9°Ìßa°Vµ­j%é-±@ˆ.æÞ±t> y*Þî ªH§Ub1Y‡•ŒbÍaÙÖ!C¦XDΰ6ʆ>r wíXmîòñ1¯X¯zϬÜÑÕÓ±F¥T‹UO¶»8íkù²|\ŸkÎþó?ã£æý×çëJîÉ«æU×ÕH«ð©@CJ! FéBIè_óœDÓ–þs ¡ó-?øµ "Àý綯w/$‡½ùUä—ž/¾ü+Ä÷_Õª4ßQGê~}[_J@ù|þò£Êí訿RZŒ ÂùTÔUI =$ñ}Jh~6qÎélUàÏÏ›ÅõUz00úÿ­èÓߦ‰Ñ:'BÚW3¤ÃÏÚ8¹ò&iÍyŠfÊ” ›sg,?6¼ß>e>ŒËûùœ­Mg©5zÊòçiöh¾Ð£ÒMä"+éOç½™×8çã›k{ëöñf5û /yíòöx Ç¡„Õý6j 1øzób ³„NãÏ.Î yÞÓG“ 媎v^*dëg¿e£ú-SU(g*6ˆmZæG‡FþŽÉV±•ŠJ®èH¯­‡J‡Ö]XsÀ¨ÊDp 2$H 1ÐGë­N‡U–Š‹XϨ’Ä;Tμç»_臡G±ÆÐÓîšrP×)è¶ùò±~äç…°UØï‹Ðá³Îþô ¡ÛàÕ‡š’×¼%¤'±$=¬…ni`67HÎjv5æ9ŸšÙÞÒÀÉM6Öz„›Ø—1¹%VBœŒO.E¯¸ODÉ%³5%½SÎQ]ʶÊ ZÚ×']ãç¨áµ6É™›ÛÄG“ ²ëñ(Cv$éL*ï´ûò‰cf­o _‚° xYQ:4±QЛIÉj”Ǻ»>Ó|Ç£ùy¹¤‰zê~1}¤q+)æVâ’AõpÜAáØJ•]‘ cåç@J=áò¼×Æz½Ä°ÈIÊÖí%ýbâˆÙ5òmÛ­/Oúü&+º;½}[ØG¯ZÆ'q,èüw»ã·ÒzÂý íì“U$j<|ŠÅz‹LÞø©Âó5ÄÞD„¤Fƒ;®ë‘°Ü‡×]‚4 ¹EQä·^ëß,µ&~ÊKüÒSê¢a½)ÌQÚ\2Mè\¯àqt#M.›Ì¼;Ê„}MŽ ÁD`Ù¿ã´ënú  €BEØÛÉÛ¬Uâ¢Y§ç¨%¦<+¾øØi}c.Ž·")<ùá\M;Iz=™rˆ9sØT{¾Ýiòìÿ'yÐùSéz8™ï·ñº‡U6iAÕ}Â$d5Yl,]“Ÿ«éÐqr91Žlý§I M¬C)KŸ3AY–‚£¸½Ï10Ö×Ïø ßílH€BýÊAIÖØÒâg>f»©¸ ˆk Ð|>WÇéüÏ-@ê·îC©ù ‹ñÕKü?o²é¹ÚÔ\qE·WÐ9CwÏŸ —6ìá;z|(CW²ý“¸þ+ͶÁ?ò…YD7õ>5Ðk–»çÍ5b°p0ü¾÷N]÷Z¡¿åsϦñ=yBW5i?3ÿ;=JÏë8ɦ®Ý¸ÏqAþ:;¢TxŠ©Ù²ø!X±b-´~☑c•V3Dˆ.f«'­¾ Ó7O«žÆ¾Y÷_ë§QtšCÓÍíàÝýw{u߯ù4q.þëš­QÊI‰ Š vŠ«Uù=½e™€Š÷ä‚È#¨)‡Q[TòËïÓÝ7›øó¸8ù|ªªhƒ—Ýø£¢ Íÿ¿Ù #Á Vò ˽20à&P6ævû”7 }—Çèôr¶ÜóG¸²$[áHpM§Œ]1u&uW¶SŸŒáAUÓ×ç;€ÆÑ Ò´……/±òFÙ÷Œ6"œ°Ö <^xí+4SµÈú§ÍP6´f1+…k¡X7só¦&1¤¹»¡‚Ô‰PUûÂ5œÀ«$JÏ\L¤À§7id „háË8Oq g_ýÿù{EÈ')ò#nÿ[&R’Œ‡Sèa¿Ÿå•äßkÜôîkvÀÎËš¹¹!Ö2ùi˜ö4àd¡µ´GŸšfüå<]q†¤¯×€Š—øo2øLm–õ›Óøý­¢Ý?|zèÛ”.ØÎä&)Øu-æÙÿ%ÀãϽ6¥l›Gva×&±S‡lKK|o8bi)‘è?ÆøØc…í{ nd€í*àS°ÒßÁõþIòvûÿ4KØ¿kÒªµø7è}¤ÒüUƒô5ø¯¡…B3*ª¨XêKÍÕ騥Ç?ý?VƯãðÅÂIÌùV)¢ÈHû¹ù{Sceªß¿ï Þñ"Ëhžíà8Œt„òÇ×?–‰G4Ü.éõÎâvóé7.Ë[kÃúÿÚ„ÍÌeZ 4³Î€=Q9¼ê7-›¬š×(˜ä`(Zxs³‘þ©k¡‡!X¥ Nr‘˜±,R¼u°3PòèæX™**ªoª1³§‹‡LÀkÞ¤ÖyŠD2—JMJ gBS­T ¡ˆyíâgäîNW˜ÀÜ©àÿ‹‚Ûã¹û©¯\sl›3"aí@Ç¡f¿ÌÙË$ÄX˜+ŒXÖ "y¨Ïví&fên k¡–sGyÍ”ÎÃnsA* [(D,,P§ŠïÚÕWµòYLZ¥bi¶.ΑÛIá{L68ëŸq.µm½]K(h™À¹êá+þ¹ÇD¤7ò^•žd¢~?ù¾ŽD®È®,iÖç{s6ÞÛ©éZ„D„oI3Ìö½?Ïi<çÔ?h8:ÚJGS‘jûnŒ$ʤóèCü< Ñ,Sžt›¯pÁ^— 6a|­!EÔõêÎY´I­LÛsÿ°'{x§Lt‡mcS‘¼‡‚$ð0!æ!^¯±äP5DÅ“,NÁzŒóG홚†nkK¿1˜OêÇÍ5~õIB3ˆ@­ü·#pm*¡#}u¥«ÝSÙÉ[i§œŽz!’)/Ðùˆã ,àAÔ¢˜’q7üÉ3ØîQ*Š µIÜôš¼%ío^1Ëç°Ú,ö lNƒÏËP?T „Odv9·ÌÿS2§ó»ûÖø¹ÎÒ'º„;­Þ¤ùó#»IGý‡`oÃ`ÓªQ2Õ^ 'Õ牻z«ÜÕ‰Nùåß>Fqó3Ù“ÀÅŽGÌ8)—òDÎ;f•Ê<Ïcc¿ŒÊ?m®°i[ØW;V2¿úq0œ¨³ˆ¶šR"=¡`y”%à2nß™éµ0Z½_ÖyZs-Ç‘VŸb¡}³•éò‘A=Ž1ÕO"3(kã”DŽÕGÍiÝâ!>MröCÓkãïõs¥¾Ì=%z*ûXê—*Ï;Ûpo–œ ñ4¾³¼>ÔÕìÆNÞ½„½t`Á7ÉM³ÅnŸ3Žàª‡ŽËÒë:ÄÛž¡3¸[Ì!œz[‹(­WîÖ ´‘BQÚI•'¥kŒãÒàjÁpð+ÚÌÃBŠˆ`ó|ËÅA@þã|%$kö8Î~ª^ãQÕ³åm‘ºÞ©áÐ7aŽœ Bë¡F?î8ñ,ïßê[6c“þi•Ƥ,< §WÅຠW•ØE×ÔÁêýôÖÛv150 ¦”GÞÕ‡¹ÛwËTkUó ßÜ®òûyÆB7ò&/öÛóü' #±£¯’|D^¢Íím´P;²H}Ã?„†g˜ºß•RŒÞïG0±pc{E —‘Ã÷3{/óoŽ‹èq¢vm“êvf£­wÙ¦‘Ϧïþ.†FååXœSìµÂT9Ã1Ñ8NGšg>°Õ\ГûiYävrC8Œ¦I‚ä{Æ,N1Dˆ,Ú´°oâéÝë]øu®»:<“ÿ¢A½ñyŒ¾b%Qxí—èoiZ!ðÙØë!5LAƒ#heÜjVxYé$‰·ªˆêÂr¯H¿†d;h¦ND ÉoüFgæß³äi†ôc[†§.Nìô«[ Q7¾Š›ýxCH—¯k6ÍBÃJ³ADËßpôJ$gÉ­ÎF¿¢€Yó£ò™äÖŸ#„ {íʤl|^ íJÂ9^sâùˆN>I‹ÕVþèशÿfÏ?åÜEúðÖp¾Îý@8‡Á󨨥Éç¾/§J£ÃzüqQ«ñíÿŽÄêè>pù|Ya Á“ \RÁÔý,o×ù±Åߪ6'“Q?ws˜±ÎùÖ*@RÈÅECAQ_yÁü]|þωÉoþNw6üëe3 ô ÷A@†ˆ 8 "ôi” %ô’¼ ¦ òùYéé.5^ä+(~ñä6½Šü<=68­¯K´FS¿Æ0!âà€ ‘²åÅ™»ãvåkµtÅùý:Ô®J€BAù?ý¿ÚÀerôþó°ÿ;)ƇìƒeÆmÉÅÕf–mIe¡eã,Éͼ™¨ÇÓ½UbÐxÙ˜fFE¸™€”ÌU§b¾Ã„ÝRŒB¤À(JCéu¬„21›¿ßïÔñßSM4ÑŒ!Bš1ŒaB„!Æ1„!B„cæš1ŒcÔBcE †[Q ƒ Á‘˜3 aAMUU×]uT÷½ï|+ŒcB˜€8¿^ù`P4€¼pHh(˜Š‹û”\ÿ¾ª‹ÔlvP~-ÔQîíÄÛ,áCçÆñkÓÌ  £;çìÖ¨¡ÄËR‚ü„ÕcÂô`¹DdêekhùúÕ.nÞh{+žA¿êsó·V¶Öª³TrÅ +ÖßÒ–ïê³0Ġ绣Ý˵W‡€ž•Œ&”E:l|3Ö³×õæ‰}ZY¶ž3w[z›^Á©ª¡Ü>¯ÖøžIÏÍSs?&T;CÐ]Ñ„Hƒ6}Ýͧ§‘ãÇÔ‡MêSÊo=;ª>?cë6û'%:ÔŽY¶óE•RøIŠñý{z.<"Îv¬»Ý |µÔ÷«ÕœþóÐÜ|,w@öj,Tñž¶>³¾‘8!„#a %áŒ3ð$oË~SﮯBæàˆˆû¡YEJ”A-)`ÔE•ÙX*ÅFˆWøÐw#h|O£Õ=«)çØŠqŒãZÖ-Hý‰Ôw|O=÷ãë Û[gœ…ð‹ ÏY,yô»¸1zb<‘ GQ€ˆ”=ßTnaç­QLÐ6jù§v3±<&ˆŽéÇKö…§ow¿Cœ* žT^‹Qx[›ÙùœÁŒžTƒÓ5ÝÞ{Ñe…ü;ÒÃ2f´öiJø…ï#”/7ËõÈê„*Ðo¹NØ)” ˜ì NZÕ‘ú|v4Ö þz‹ ¬‡oÈ·°6m¢·é®ÊiÍîdM³Ç|Ò$!°úvõöºì˜¬‡ùœ)EöA3\3;d,ÉÇ$û˜ï7!Žyô·fTÓ½;&oEì ôQ¼ ºÈáÌXIÈïBlâ~ÿòaÁéßÕ÷\¾I$ø(Dbˆ1Š Y‘PŠ,ù©(Å ‰·Çäs=P¨ú¬“³Ïó²g¢Ÿ!“v'¤]›3^(@z¨—²¤¸Nýö°SâÉkøN½Xp"mä]Æúal \LòÒo©RòŒÑ^Q5 ±"^°[·wwÜ&i:ÑAI*ï0xœí­|+Nt\Ìïm[ïg¢} fï=tÌŸuç]Ôgf¥EÐÆª0ŸMiÙ™4"³“ Xøüû‡d$ø7«÷s‚c…æR ü²r÷c0SQÅäXc§.~–yéÈ¢åÕ(ºAÉT]y¢8ÛePC5/fS(„61ÓdC·²¢Ø3+7 -üÞ ²î@+n&X7äNcÅ^ {nQ_ËHnæ'fè!u¡BS½.f›Û9¦$«Ó/¦Òs E¼D1[…k©£ ‹¬ϼÀÅ?ËaUتwXo ò^GazhUwî”Ï+_VÝÀ{]ν ߨÔ:!ù+EƧé*Eå€úMV3<ŒeJDdDDsdC¤ Kð‹g1:Œ%0>@@o™zÈyà9ipó¢ ‰jkN{¶2$Öy…9ªÃ½Fè¸eÉU¹xA)¤„ì„¡Œ'a&›DûèDHL«ñõÍ«Y"y%ˆª’¤ŽpÁncÛÊ[ùwÎÈøŽySš Ä, –’膊DFý•° ËPjà 0fC!V3ŒöÕÎ<ÐÈF,ïDˆ.ÈùˆŠîRp†Fé·Ãw„\¼ðÉ£.À†4'¬.<è6ƒÖ2–0jê4Í4Û‘À"šú,n£•šK̘n¼—µÈ3^ìŠÈ¢ä?±¡Ý眕Ջ¬ï½8~ˆ(ˆw…@OH/¦:u€4kÅÃÒÔD_À%ºýh#…¡Îc·ä ",ÎZ*Ð)½C>°ÇJB´- k @Y¨¬Â,zÙ$“;%)LS™**9 Ï˜x¹Œ€ñoéy¢½Ì†Þ&tÚ׿Ið5 FÃ.X·g‡¡CƒÐPªpg9PÈ—Ö8ü¸?.бϖ8Ú •øŸ]uRÙ7g¤AOË|ÖÏc籉ÉÐó[Ô‚T¯•ËX© œóÕ;ÖaŠ‘0½ôq¨¼x‘RíèiôìNòRS¥i‹ðáÂ÷R$vöO“õ]_£(rW†4 ³L;+¹Žü¬3->²÷ðp–Yú)PR‹šÊ„ÄÚûŠlíÝÀÜô”iÑ ®ÄH2bCÁHˆ€™wÕ'·]{vÅ¢ÑÔ˜F;0d×,^.0† %g Q†)2S…ÊHUÚ íD¸_£uÜ&š*'“™ÚŒ¡z‘Æ(Ð3ºk•Bíl(Šs%$@ˆóß.f囀Á™%8§2Æù6 Â]3 !mŠ+S´3ORôTËÉ áû>ÅN3˜‰ç….lâ‡3®û†Cs_[*Í%iàA˜3"=P@åäµû¤I¸bÉŠÕÜy"fY­'c€DY:=Õ'p C3„‚¦Pí{w@S^Så,¢ÅÜáÛߪÁ5öe @ÄæKMï ¯ £Í¯,ï:¢A áÁ'Ljx¡)Bb 'x@4ÉGE„54€µ>õÎ#¦H7hضn¤ZlïÝ-³e\ÀO`©Ö"&PYLRËí¼^c™ønß©Ëåë†2Q2vc±wCl€v1K4É’Ç…¶¤í›œÁ2ÉÃëx3§ç[#ÍSö™Õ|k³}žÏHu²²¼^hÞüMÞ†”ÁÇ« ìÈ:¤í²CF™Ò†¨ˆaÃDE Çœ³!œód¡½fdã\HXÆÍ0´1Ê+UaÊÅC)üa]DuãU¹ä/;¨‰áy³# ¶ÒCf 3†s‡±ÂÛnànå€+‚ôzÓ£K˜CœrfeŽá쳎¦èÚ0;zÓÑc*ÕÔï›Eo ¼³c¦#p×6âé¹1•ŠÔX#XÈâ 02>v‹•›Raµ=WR’K„Uá;¼ °Þqéšâþ¿»Ð1î`9£Pd6Ò:JÐT\C!¸2ôbZdA žŸ­Æƒ¿Ÿ7kŠC:4 æ¸Rz1´m¸N](ÕŽú¶ÌÊZQ×–.|OùÈÒñ­,;Úof=ô…wrMju­GWc¨ô$wÊë}¼æñä™ÈÌÕ3K¹î§Ò{ˆº>E‚zÅRÓq8šÓ„Âã͔魇0œS1ƒ°×®°½ ÕFæÜ¼l´­1dáý æ`0naÌt˜MðÁ‡‰ÙÌ2È0çªéuˆ‰  ¸~ݦ›ØÖÖOXÖeB ý¶ÞT DYÆâΓü—Xâ"ç.ºåo;Ù˜1ƒç§æ¼ýæÇÖ¯K{ÞyŽö zÕì®x¹°Þq¡‘˜åVøLB”Ö»LäçTº´æ`tÓs·Ãº†‘dªp»Cúõ¥ƒ*š&b"fܸðQe3tM‹º×’ !+_¥{ÎW>ÉѤ/é"öزfÓֈ˥ä3‹“Ã&_~ë¢N1àÛ¸¨f\F)þ+Çm(G¼‡hõ\ܤJu_z–yX¿OÍÞˆàrn¨¹zí›m&I‹» Ýýøuº]n×m£­E…ÜÆD3ƒCmTþ€W©Eò|ÞMû5îX…üû-lzÐv?€Á€” û'"§&¾# ÕF‘9rºê,›l¤ë°ÂyèŒØTàÌ'ž#t(ž"w^ܬ´54KvÕqƨä´<Ä.Llɤ2Ù Ý:²ÎÎYóÇ8ü4­ú¯ÄY†\ZÓÌ(eéËA”X¨ØDgçÑFVƒ€AB É0„jaU®,­ ÐbOvÍn ñ FqªêODãaUŸZ4Mžì¡j‚‡ší3²Ì-™Y>4F@Îbá~k$v:§h¿˜Û²RZHՆƉÖÖaáF0A=¬9‚µùŒæ¤”c Ÿêñl°>#kßœ¸Cœýd÷› ãP›´-ô½ÄFÂÙ¹;ŽÉ éŠcÄŠ!®„´Å9M­ÂkM   Êíú+Uó±¨ šl ®3¶5”PÅð̆C+ ‡ Ó\a‚¸-WƒA¾cjâ[× "cWÙ½ÌI˜­,e5_aÌæ‰àrY rP Ùƒ–œ§€S ¦"agŠ™»5[wó|7»á±s ÚéÕTB¨ãï`ãÃlΉä˜J}ˆ½Ÿ{ÊyœaœêA%(ý—‚iñêMcÁÆ·g2epŠ´ÏšiØõ÷J\•Ÿ²©£*ÌsÚ!ßdB¨‡´Æ‡¹š†'à\1]gÂ$§Ç¢U4‡díç/0ÜrüæÊ<¯qöTnôì¾þê9T— RtÜ™ôâ}Òì—zYG¬æ>$T[Sì7Ç—\l ÌïBú5évÚœ"ËFF¨tÁÜ‚f)Ý—:™àaµå©ŽÌªŠ˜ýkš¤ƒº*ÏÑtüm„ì9²ä±UëÊBc̃Í­X˜Ës…—P‘¬ÅPÅ 4¤ˆiÍÐ *³±‘8ú©ÂM^“˜Á`…ºOhJ+7(ºñ¨b{ŽˆbJc6I{H5pâGD€½îXVp/4%§°ØvçB¢ Ueàó˜r›¦V0‰p†P!šýÇuãfæz9hàÞEE'TâÊÞ2¬Æ±j €b™L¶ ¦ï¿6œ¬¦V˜ºz):™œœ(³¥™ts˜õ…5A´#VWV2*Ì«0ó3,ɧZê´¯]),—^'*QèUPô# ^ÅØ Œ3†:zíÐÅYˆõŠž4“LqmH ;”ש×QBô”©ª,DÀ[lHl2‘ÚûUàŠ-VCLwš¦Á=•¶ 9®~Ëò¬ž2_å!%†‚ˆºãŸGi¤¯+,gTž,ÀØgˆ¾ËXtg#rÏ< ó¯¡ïÕCùTd†çv_Í Y<Ù麤þ1kÈ€Ø6š,{XÉÅpª·IeŠ2ë1¸¥xšM)Ì„ó¼Ê›BÊTãs£B¼SŽ Í­ Žeçs êE*ÊhÀtãˆ@5Àãj0E‘·„iØ“¥¡p“ŠN*AÃ|ÄæÁäÐ0@WˆÔ9ä«] azôßÅzþ\ ó"Z `—ëͤHÓà, éA˜ëz±ˆôàï2à¸Û–T¤ÝÓ$Ë§Š–á€ÍÔ@8ÈË5=˜ÈS;@0ꈡ‚Þ]V1ˆ‚NB5æÅwÄž’@ÚzâE’n Ä]>š(x’0Õ—'tÈY¨àó ½TY¬wÌÞÎ:~¶©ÝVÊ<…»Ôª,žp±®JAh56òd¹âx%š ѬBI# “ YÖ|XtòNØñ÷j+ÇAuCûõ\Â)<«†;‘ž-v0:ë/†ñï¾f”»m•c¾4c¨‹˜xÛGš÷³䥌ïÆ<‹)xko‰½Îøß3MÞ°}:‰9Æ{gœfˆ‘€Ê×6,îš—Hï1MÉ1Š¢úojðæ¡Ô•q/æ~xs}¹hNñ¬Ö¸œG Q¨ôgU§Žå¹/ºó\»ñ[aÅ9Ž Ýû¸x8;ù™±»E“àÔŠÐæBìÓ çktÄ@Š!ø^#[¥»Çvï°ïD2Ÿ>äRÌ\÷º¥‹ßíêqƒž"}Ï3ú«®ÝŽÛ ˜yÒO†ÒÌ$ ›6h 9Ù‡ÊsÈ EíW&®¨}Ìšó*”ºE9‚šsÒA:È‚rËrÄX)(`0ÜÓ8 ó kWd²‹ô7Æ¡`IÁ^un)¾m(™Ñ é†#–äkZn¡Œ‹2HȘ b‚ʬsk²'NAï%ü3bBh¬ÐŠÁ-t¦6cÃ!ˆ2p¶©æ… ’;@ßYš={.YÍÜG“®‘ªì É_…XôÞW¨í™uHˆ[À»!Žx×ÕEõÀÀ÷\G«töŠ/u˜P!"ö`ˆ‡Ñ܇³æ%X%5DI ˜è•žÏ¨ÜT§K{¢®Ã¾ì …*†Lªts¨½b£˜”™…ïuý“œ:çè»è!T¯KgwÑÄß^d/¥À˜ t:éÖÖ#H­ì3`ÁÉ2!âfM@‰{LÙ¼¹âé˜FnbÙ’Ú…Ù§œ"˜:G=”+(lðµ]½ž[_!Æî¡$ÑÏt¤PSÉvδÄUTõZy­:¶ÌNöâw8ø¾®ýìS=>­÷Ï9‹2©X—ÎìboŽ&Bú\ï’¦ÛѱG ¼””šWo»»1¥åI©Ç%%>”zZÛάsL—T(ºØhœ"˜h|çE´«)m¹N.|íL t®rJ Œ "Y›`A‘ƒ!ER"ÇšbBO7‚ªªªªªªªªªªªªªªªªªªªªªªªªªªª«$ÑE¥¥EÅï‡Ýù>‰ý®xŒ¶vc†˜`••¬3¾sœ™§¥Szyð˜ó{t`|3éŸÈÑ`Rô&Bh&v€úa¡aJÀœaÁ °a } V5Ç€lŽpÛà÷'p{óÚœñÜ›CúÏîŽ|êÑàÑî0â•K®ÒŠ»ÑxÙðœ7RW´Ùwo·«ÜRš¾=EÃw?‚¡*Ah| ©_ûù¼«ÞØ(ÄdÄÓÑj‚ó/2g™áçZ”\è+¯Qu†öjÁ\¥4¢÷*öw±Üù—ŸÚŸø½,õ-ÓËÒ“Œ* =3ö.õ÷Ò¢§zëä~æÙ–ÈÕRBüYCœ!f+#ÁÉ<Qh¶ËêrÀñí\øî¾Ü9òÃÕ–ŸVu(¾º‹*/Ø5…" D„KÙû>Â&ò¨P¡ƒÓövK‚1ŒcUŽ1…yÍUœçZÖµ­µ­kZÖjI¬ç:Æ"îÕñŒ#¹Îj8Ø×Äâ¢bÚëñ;õŽ4%fórC¯­‡¸øjj ¶ˆ¢»JêÑDîePz°õ°2Ê•r >*˜·2Ì]×£éFLÕâbùág7‘â=*‰˜«ýÀ í¢‚çTÎ ‹B¦„‚H(2"ˆŠ"("FDQA‚ ªH© H * ô®Íá¶ 5T"ë9n!sëå(Ìä±7B(Cˆ$ÑD8å#b0`²62"ÌI‘Ê(0@",rÇ‘Ê0AbQË6 I³›`s&ÆÆK$Ü&H$Àä…† 6 ²‹”AB,£$ŽI&,’H ¡ "J (ƒ% ÐQC`Üa›Æ¼WCX5™(À!Feƒb‹2pdàÁ¡’I CšAÞ1™†ìÌÃ6Üac‰mŠÕ¥2ž+êîaMN ã1&‹4A·ÉSšÈcÑ¢âç.>±ŠÖkXVÖ³‹ÂE>´T”ØÓbéµ +9Îaܳ*õw8ÌêÝÖ3xh5:R=ÃÝêÄbla^®jñLÀFŒç:Õâð«À6ïru¾1++[Â&7ÄÓî"3BÙ„£B+³îØÃíh|µmWŒmÇÀM^—ŸŒüà68SoÚN³ÌØŒf±ÇE™2`ÄYw3¬ë&®îÒ‹œäÎI·«WzÄN¦b±oƒU£¼ÆkK**ÍgŠVåÄCÞ1©Â/Õ,ÂÅ>ÄìY¦ÌN_çm®ß6ùÔÓâð^c:‡£3‹O8€™‰•šÒaFoQ *q¢'TØÆZ3eçW7JÉ…¥$UU>1Z¦ÒË‹1x’cm“U˜Võ“ìûC–ÃCÓlLòÈϰÖ}Oh û¨ þÔTÖE§±DËÑAN:¢½¤AX|ÊîCTP X0¨ÈAIfU M™("½ìVÁ],D# =þÂàÈH½vˆŠ§ðò”„$AV* ƒ‚0@!‚i4 ÔW¾Û‘…¡@¹>y_øÇ"9³âeL% 3ŽœnÿZF¡®J0B¡8€‚÷œúIÅ`'Û„ §¬~ÙjÄ€! tnÀà!¦ydú§Ju·/‰î3ÁüKnVîuàuÏÏ|vÏFÇz0<ÈŽî2|á™1†ˆÜH§¨s”žL÷ûsÀôÐêYØüðôpAiè4Èæ}êê›Ôé³Ü¹s€ö±JÃ}é>˜{ë7½í‹Û¾Ù÷ÜŒÌÍ”/ÿ­=B_'ÄbÍBRÇ€îD£‡ƒÃ}ÆCa†¼šÑÕÚ1UúŸf+ÌÿZ‡±«öLªŠ²þؾߡW’XÕþÝy1a~î™ÄÛRâs\’A–‘¡â‚´òƒ]Ú]m9Þ›—A㾯)D‚ÿ&þü4uk0y¼ÆÕÖt©ëkG¾[Ù¯Ë9îýâ'.©£Ìhþžâ~<öfÖ²¹ºÈJˆ¹ê¯1u«‰~g\dt½ã Ë!u‰ød+ÖÙ4ôvÙ-Ž(B$:¦'ƒâúßeÞ;Ê©cÜ^«a_wkÕý»kÊaÀæX*!œ€€„BÝñ–›ë€„(\Tmì§– Ã®8Íóê +Ô¥»qdÿe¥¨§©™+i÷ ©ŠúØ•:Nxb ž¸~GÜ© ˆrŽð)÷ŠG™PãñÍŠŸZ÷sÓ)Øø> †çØ"JðØóüǘ]ÒžÜ2M½Ì—P62ÂfÃD™»$±a„ÊÑå=€Ð`÷¶AÍLO€8A‡ À AK$ƒ¬NRð¡?óö0ƒ âe‚Sì³VÏÍý©fu^|ÿµRI!w~êrÃi²Ž!ã¸î­mÅáû®A L$Ó¯“!'›6À­Ã¾OÌήð’N‡Ÿß(èç›âœÈ˜LØ‚!È!qÔÉIŽÿGükºý÷Fêœ< Ô7&1¿¹‰t‘^®trÃ21ï·‘÷;ædœ¬qù_d&eC¿óžò¯•O˜¥îù§“vë[ý›fÉVH-‰ÇƒÚ Ÿñ¨Ü?ÐuP øÚl»Â 0~!Às)³Ý@ ½J‡öØ}ïUØüáÿ¯øšê[1R ÅÔ^4ël?–eðÀí`œ¾ÜÿóTÒ¶;s¢È‚kKŒ(ç~¡0ìqå㮞ã÷?[½âD&nlð± lXþ°˜È”Î=3#ÔÀ”’ÜÕ½öË …ËÆû6%éK°2ie†H¢þ~¾”¾Êò" Ý„†N¸i0®BBÜCH\³‰B -«%˘³Äþ’ðÿO+éx~ï ÛùÕátœB˜$–Þ> ¶è‰"HË `¸Šì¸1"‰©DÆ ŠY`Âq#·hxâiùß+áhqçã'ë ΜZ#—æÕ™*QªŠ¶Uc,ík""3 Ù!‹ZÐmxgkÀp›IU°Â6æ·÷¶²çˆDÏàÏ…XÆ&z2*Ë Æ1ë|¤ŒcÆ,cÎŒÓ8yE;~ÓMûÞòæðáåôý_IÜb¶ü‰hÛ¥h8×`¶ðm¿ë[K$ÿWÞDñµæGö âSnzT~Y…V+Àÿ`\žWÞ×´º—¹vs“¾žïWí›'™˜¬iJfL€h¨ˆ`ÊÁ•­¥O‹Ÿümlm*Õ¯­µÕìçìt*Ïàôül7_[Às:ÈG†…S ‰¨Æö& b¡)PEy¿˜~ :ˆ£Íèà=‹¢£GC‚a¸B›Gòºì·m|Dņ™B¦0ÇoŽÆoõø(š.xæ+ Ëü‹v2®Ü™ä¹.cxºk’Ž5É–@~f(qu·®äÍþƒÑÕªvf­)d4ñp±°ž‚æÞ,c<ÿ/ Qâ®Ó²µý 619r:s³BÁûŽ›“ŸÒ¶õy£üC~‡f×É=Öé³:pI(¼aFfÀ8’ÓNÌZ¯EÊDEÄdE€´õM@{‡BÖŠrxwñô.~ѡ˵ɬ°´¨¡)I Q”¥)Ê~_O‹û8˜û]w­ðûÈ ÅHKšG>ûîáZSÈsö½"ý–e&q¹¿g4’.Œ”„àïeà€@5é¯Åü[é^Zwõ;Gâõ³Süݽãcð°75ó|4šÂKU4¤ªÜ¤ŸT9IÇ‘éã$}¡ÿñf>ÑùÕ-Ó¿(¤bF‡öýzF”EÙªb[U¤„HCs…`,R—ª)],7ÕÄø¿Ÿð5|ÿ¹êüWÜø‚ýk⤀R—I}žrž~ÝÝŸEJd¦‹û)ž¿¥š07½sY_VQx [`åî\„4Ò‘ i·ú—MT–2iÚãO¶âŒ€³¨@1à ›ŽÃnøÞã†ÈÈÍee¨Â9"_ž¤Ì4Iõ¯§÷»Ò“µÃßM¯W‚oÕ÷þ'ŽÝ—¨iþ`uÙ}ÖW‡œÜ‡u4äðä|Iç0xŸÀ£ˆÑfº·Vkú ]4Ö"2)œEÜÝJq­^i&¨•Œ½câçÝC`Ó?'™E^ö<}wð+®§®®ëËjl’õßTfT>3ó> ¯¨ó9PÐT-uì*¬Í™­Ý9ô ž|VÓ«NóµþÆ X;T}¿räÔ‡í¥FD>oÓúþ»³ÇIæx9»×çÍݳO/øŽj1dýQŸ« ƒx5YH±V  ª "±-1µ±b"ųoM#«QG†gO7>®ôna‰ý—˽:PØX ²;¥¥Hù 툮G0òí‹ eH÷{¾,; Ä!„ýÈÿ>×ñ%ŧ1®~Ú,ÉÖ`ÉÅ<Û¹5ä?]‚Ê‘%²EüýÒ ÷Æ¥}Ÿ <\ìû¦vÿ—_¢7 3¯çÀÆŽwÁòm÷öî[8ìp ל2¼ü÷v¹YS¹ú]QÀó‚S`Á`Íø>g*áÏGdzÅÃò3k<”¶²Ý™ŸÆâ©–.?Nž.·}»„ŒÁ”&º®:ž3. ÓJ‡(©îDL̈°¾ACé”Ô±À¨0A¿“ûíøÜUå¯ë­Ýç* n m:ªæ™-Fh§>In‡Ëïkt^#@’6!À·‡|`óà\´]ƒm‰u'y¿÷ö+ŽIWT¢ÅðŠ(µÀ•'è~Ý©ºH0UlÎP÷˜®NÚY…y¼8pÐæA‰¶„=3a ˜2„nä¢Ðï¨Ö"«=EÝ45ãr IMÔ÷Æå¡Ý›6rteßE^4 ˆo^9ΖÖÝÙŒæÌ};¶¬îH\è¤ÛÇmôÈa„’enØR²Ö^&À.^ù£h²:7>ä´+™[Ãe.+µœèµÌø>üÎ÷|1”JI!|;xi@Ɔa› ×3o´Þ Ë-‰)ÁÝ臑2ÑF§NÚƒ8 ¾Z0ÈK—аFÄ‚ß|Þ®%ÉÕ"_ð?齯G÷Ý]tÃzoQ}cŽôh-ê/K_¥EÀl‚ÜU‚,l¨¾  à­*%Y"îÛ^ÝUnͪå%cØæƒÜW©›Uad95ë-¨|˜"sÙ™†gÛ.Û^FÕ1s¨Áwª3“#í§ÖµyºªÖ4SiÜ0Ȳ£Rd£&MËMe´Œ‡Egg5$ˆŒ2C^Š5FÉ, $,¦ZkÎ_U³ga°Æ c”ÆMÅ ŒÁ#‹*H3ªÈÚ* DÅg%®K£$ÓkI2 ²ç,sMm¤Æ²ÒhÃeµ¬¶€ËXí¡£Z£RhÉa:l3`¶$Éd³DØ,ƒ@`s‹08ìIF´9yY4¨–e‚ ’ 4IE4hÉ–É“&Ih ‘0…9j™dÙÐJª¦¦Ëa¤ÐÔKCCQš´h°±dqÌ D9¢ `²Ë-¤À挚4(¢Š,À°Ø¡˜fÑ â29£FXFI 4 IEd’G,Ö¤ÆËt"ˆ 0[[44h4hÄ.È4ÐE•ˆƒµ0Ù(f0"Ê(Á ÌQª¦É£&ˆsFˆÕ‚4dƒ0Éœ¦€ r†±Û$šj!²hÐdÐhѦѣF6›M¦ÓhÑ£†Ð9–ÉŒ5G2Yƒ!F$ ȉ0`°ÀPFŒ–hŽ€foäÀW`*êÄPØj6ÍF³0Ø: ˆˆ(‚x $ d/ ,ÉY¹{aSÓT^ÖTÐcFñ;Ú[æ—ù^÷1—{áøÔÅnæ9kƒ“¬]?`}½ž09Ȇ›òitæÐ§K‡«Â£Üæ½Ïkµ¬ {10žÞu¢48Uf^qŠrfËÖX¬–îZ¹])„`ép¨*ÔëòÙÀÅÙÔ*ç¶ù^¦ä÷ÖÑyŠæ'öý2Î÷¸^t¤ª‰À ¸T{pyÄÀ@æ0„„!rg ú:£‡Bm•BÜCAB#B†c=9þNwI`‘@Üv¹1DÍ–Àûˆs…M$€YµB ã”^ E¦W$¢÷ýYã¹#p¡P~NÃ`9#µ  Q¿C’7À.DLÒ‹ßEUR‚ùšJ()Ñëá@Ê8FÔ8b÷Ai¶Aydrå¼pK(*Ü·]'eaQp ¨î¸ÜKY[@2IQœ¸Móîî¹îúGÆ8‡¾5Ñ>–}±ÿ™ÐÆîñTòIYj¾O£, )š"‹±®É-ãgýNðþ7/ð·™¾sÂõÚ½§úx™í€ãk÷D4ÜzU@ 䨥½vj³jÕV:ˆ¢& _—äçOž(Âo°/À P‘¬„&L®À·æu¼O=ædõ}ÿu‚`øybr6&uóA‹t“ÓW¸ïã-™d‹ð@.¾ë§Ì–ò 0cðh¬(o²«†ËbJµ/’¢üp¹Ø~þç;vJÙ†jïç/¼»ó­“Ûœ˜0Q& –dD’`’Í`¢ƒ¢³ŒÜâ8X—‹šÎ+åŒ^ŒMë8›P¬U¡V&!ÓÆ3øšç‘/G„òèì«gÒûÉÿ¿©µ°$3 DFùT:Jq$Š´Õ^qݼ’ma6 ¨2˜²¡Ü3àb Ügg(^i`¼~ÓÓúðWnï• ‹Ñ~~^L;U?8j™°Ä‹l†‹’ ØÇ!‹q Ã-’ˆrüÄ´jÚ[&(D’õ¬,€ í0~ ¶EˆÉ¶Âxô¯êõýtŸÛ'ÆB Å‹lª[V 6ÕE’²|v%0UdÖÀáÏ®Û(!9}?×ù¾ë†=µ= ±ÍRµQÄIžÕT¥E‘¶pª®&$2¶Â4÷}±—=¥ÓES¡„+ÃÄÞU;Îe&ð7œeÑML€15ZÁäKÐÆ0ÒØ$£Æ‘‚[þŸÝo!.;`6 èr66S‡72`†  ‹ë®Q¢mÂáÎÝh""/oõpÈ‹"~4Àv}¿÷¾¯±õ;öœÉú¤Òø§Ðé29õ0©‡EhóU…SB£.EI ’Bî&6Š ÕQŸëÏüš>LÝK+•ݾO7éuÇIö{\öÚ4›™&¹®øÿ/ÛwÀÖ`Î'Í÷BKÕCÕ穯†¸tq±Žpd`ÌÇõ=W¨“œ ÖP€”þçŸöwèÿM®üIí§Z-_ ϬD¶|1ÇÏ«ÅQ/sûfrŒ!J–!½ƒi!cËØ<#oÃ/É÷¼‡íN]°'€3ÞPTUX¢È*¨ÛÈ‘¦B²>ç¹î›gÃÃë&Ç-½é½ÉlI,’ÌžøÃ¶L0`²Ë$ÄæÚÁ$Ñ‚ƒB$Í9:,1 X1·_¯¾=Ó¯SЃû3ºf#%w–ü¾<À‰â±‰^@L1”áôüý~p´\¤Çf´(kS5 bc#Ù­nM£cµ˜Bà f^ì´(.µÊvW7G&Ýüµ½ ¶Ö\fSÏ)~19ŒKù‹›¼ÜWKPqÌYç”HšiXV1.#¤™p2”#QoA»¦Þ•_0À1Å‚ª(oØåˆ€E;ŠÌÑÚgÍÄæ…³µ¤ Öb¦– )hFC·}̓FÀ0I"2JQ¹§ Q‡—Æ)dðè³b ×0¤Ã ˜$pi!S³ù¨´&AbaS‡˜dÆ!éõ,“C)HAM°Ó¨ê@c·IÌ&Ó9d0òžIå(r;÷wçM3!–”u˜€–“·m¦ƒÊÃj”O54,1:ö2lêB “wtv–h°ÐÒ šVˆC‰ÅÐMøê” Ør³ÅɆd8™žCÌwv‡zr<<2'rQuJM슰©jaºí ^%†rýÜpë¨Ëµ)l-`èqû>¯XÞªˆ¢ê¹yzÂÕ`EI(ô|‡ÈØï¾Vw=ªÃ4!¾9‰ ‰"yœ…PªH$‚®«|Ïj;×Dyz·@Íp¡†½æÇzÆñ}çÓì7Õ/…MîÛ›ÍH3U’?ô¹9*¶§`,Q/_î\èÓ”ÄÌ8„&’„Fxš½ëŒêO¹ñþç÷>gûŸUÿB®¢+ê{–çßbÅIñêö¿5¸`È „0V @A~£Ðâjܶ7° Š8@ÚJKêKÓëñdÓ#ÃÔ} qìá³üßc¡e»ò‰ÅȦ$`FLik-8Jñë«n?â˜óo·î¹ó×]Äæbë/ÝW|–`’ÁÆMIhÑ“&È|éñ˜®]5WzÔÓáùY¢TÜš16MEÄê±|Ÿ®L_çº=pä †L$”åy–¥Ãäyû0Ýñüûj,vÏ“yáÔì.þ'?C\ïI'³Ýdsø¼–,¦1!>F7ã˜%r'@â BCý<û‡[ïüÚ,¢d 6' ò¨ÁWEtÑ¢ì0¬!0§øG“Hao¾Ø ½Y6ÛzçgÖŒBXÊ‹/ÁjŠÔ³íРš¡b-*(ûßÑîè÷.ßœ÷ãB"ä–2AïÇ ÃhÑ“$6®Ä 3I†Ö 4I%9 fCEI$f³•-øÿ¿øøl{mÉúV/ƒszñ¦;0çf†°†ý)¡äóJqhùx*-6‰Â”V,HB{ð°Þ+‰À±M‹!Ôýÿäç¸ÌW>¹ÎïkÁãJüNDûãm±%xÈ5Ÿ¹YÞÌ8((@ÆHP<–I4Y`ÄC‹dfô0u½\ˆ°pàíOƒ-gbŒÅY†Õ€PMÔ-‚JhHŒH%Ì%TГ$8fL JÐê„ÂVy-Ohàq§Ý|,ì‹0ìv!á·BêõË(˜$D¢1,˜#’J40„· Êø¶55¸*ôöŒˆÈ‡î8>÷~¼õÙ¶4ÆIÚž‡ì3°X€ã%%&S!³)‚‘ïäfè“O°*}=²S[ªãÎú(¿#†2Æ×óáàjidô« deR¯P‹%œZU߇j[kBž_‰Ýj<¯·Ö}£6¯!e‰Ú{öÊ Ècþ“/DãhÆK]¹ßuÓwmÉÅÈa5 "@Ê80ã`ˆÈ5Šß1ܯkMÍó ÿÅøEûe;}§Òr²oK­­¤\Ñ¥@À‡Xíù†LžG°õ?./Ò»6m=w—u¹,¼Àóü_` Ô yÐd H)&L˜[£¥d´ÑÖzÕeîÞ6½f È`(pƒ%”P‡/ŠÆf³­\b¬­<>®Œ'¥âVLͪz2¢¼¿)˜7Jl‚›àïí¨Y‘ë_Ýj´ëR‚‚\+–éˆ E65¬* ŒÁ{OY4þþPõƒÃ:šƒèºF/ˆq`b ü¦ªÀ¹d²úþ®ü=G¯LzDCúP™Ø¶³#ž™&Š È„Q‘Mx у" (¦ÁË0Cg3Ÿ£bŒÎ1ëy›xàä¢Dq—ˆ^9®FàŠ!R‰ü)8úþ ôÉ0Å5>¹$æN9MfF–ʤ£0ªj5óáD7‡;hkçñr6xGvˆõ‹‰;ÚÎò:6>HGz 2Îw‘KcE‚£éôù g‡O xÝB¸S¡Ê„cÑ×µ;€ ÛµoLJ4’МB@¤|žÓ{MåmèVF¥ÂÛ@¡P€ˆŠ80ô“ˆ‘‚ÂXm 0Kb"2´‡S×Íøìx­ºœ}o¬Ù›5ζâóCL’8·I‰P´&!&—Ò£‚›Ë“ ý©G\ yçz¬`©%äs£„’PŠ$’‡08`‚Á‰ AÌÖµ¤Fg8(­NŒtT”à‰µP:ZÆTÑW6Ÿº÷ÁºH9ìã{hùžŸW–ôÛå¤QHÏ›ÌÕ¾3½4$aôÛ`¡E`‚ˆ °†È¤0rÙ ®V9R²W0ÌãÝØ÷wÝÞúMlÅe„Qpf†ñËSÙa6‡“-¦‚(Ñ£F ”9$–LIƒDˆÐãtôj0Umñþ^ôÌÀeϱÖ 9|'Œ=ÁþäAÉ £õ® !KŽã·lñÇo\?t.M‰ ÿS§ $vBgˆB&F÷Ï7ÛË89\®­ñU}ôI',GwI÷Gb†b‚!îg»»¿Ü±Å'Š®šA¹À@ɲ&JíGD›"’¡ÛXÉ®8‚Ã{Å2qA9^ÁŸ~àé)¡2›`QÓwïã'‰ciÉ›–Û#EÁ³;@xÝÚ„ÝB¯K¡®á³YUªr™æí)¹¶œÁ]µ &1k®-¸+.CÅî#†­Ø}›¬ÐRq4·i6á-÷Ò)œ£sLHŽG!ˆr"AJ$§k¡‰ƒ:º»ƒ]s:=ÏY¢šƒžìòšS®DΆÂcõ©u­ëþï/‹Ùø)/6W&*ùÞ7½û¼¦<NÑÈÍyD÷SG¤ßrÖ 44¸3aÏVƒ\ä ö•åÌô Ssן«§oyX¨zˆŠ8ã‚ȈÀ0„9Ò#©2DI ôƒÝnw5La>Oß?âyË=uÕOg³Ü¾ðâ Eqvˆˆ@̰゠nÌãØAq ÜvánÂÐS@{ò¿Q×’p×N]‘ƺry ÃE/yÔW"h™ŒpqÙnàa™4Æs‹xŠ(rÍ ‘‚]U Ù1¹ÍìKiÇ8qÙÆA(iŽ< š6ãÀx‰r™;8yN ˜"7$åÜñ&C¹M§'r`¢Ná¸áß™MÈÎËaÙ÷ #šgß}t-¶Æâm ИÙÁÁÁ¹¶ô9Á±¾ë‰š‘ÍË àÈ1¹[ˆáʰ_¥¬ \¹wE™Ír§&xß»Àö¿Ù‚âöÞÃz„„xЖ£L¸„HV+&yìØø¼zˆžæ[œóe'Nr H Š0Ê¢€jU7êªñó¥S=_²Ôì§a‹où3˜Xv0÷Ý~»ÛZ̘¤Ä¶)E&™í175²Ì9y‚c”8Œ’ŒxÂ"ÍÃÕ,¶¼êó“&Q©'$N‹Œ>#SâæÔ.;ìåÏ—Ñ[|ž7å‡ÿ4„Ÿï"’ Céì1áÕIááßVwÌD÷ø^FƒMF›CdÄÁ¨hiÐ`’`Ñ¡ÚFM5d “,äÁh¡Çi+A ¡ž3ªXÔÚ±ÿ•ñømõ¸›(™‹í±ë!ô/˜AMå÷³b!ÁȆhá/í, KJs,YÉäÍZu™€ÈƒÐ±.‡gù®4S—ž ã’ˆ8’8»ˆ\PÑ,D3œï¤àM®32mÅÉ&ã17EÔÜæÓÐQN¶‹oUJM›7gw0œú°¾|ø Ã4®rdÅAØÐtI–nÉk¿ˆ)¤sxZî7ÜNQƒl‡\8cwÁ°áÉ= È7–Û ¬þÓf÷ “=ìl:ƒƒd;ø59€ñºŒdÒ i“NOF¼Óüô•ú?—éü° L|/êüä`ÛÆ<ÂgÇ’ôSNT´ €@émyÃw=ò¯YÂSñ”a€e^EÖÀd@É„a«¾ùۙǣÙ^çï}O¥_séw,«eÕö:Øáqfùl:ò¦¸x[m&éV·Þ5q/eQ.ˆ ÜÈŒƒ2(48ˆ¼(QЦ—z­`ª¢Õ­`z5Qâôy²ïjEßwÓm:2v<ìä€9±´YóÈ!PªyŒ\ÂPPÌgVsÀäN­V‹TSÜËÐôl{ߥöÊìÈmùêy~¢7(㞌CŽhɈ,ÁB-¤¢  £E †sCŽY¬hc%2hÁ†4µ¬ÎLs¾hœÆï<3,“­…¹l›éqqÆ6àmá£sƒvàÜ7f’æûñ¶åðjž)maešI&Øqäo¼o®Žfƒ—.ëqÎBH©¾õ½„m¿“Æ<ŽC1Ù1[qÇHSdF#;˜ ²ÛfpÉ‘nãgys‚ðâuÁ¹!Ö „ÈBÝ ´@1ÖÉÞ63†lð`Œá÷Œ²*L€™&f?Fk¶86•‰Ü‚c‘o ÈL Óñt±þ§â{þ˜UsP}n•M6ß´ùZNdÜL¡®{åg6%ÖR~Íe‹ó–mú¹MmBÞÌô, QžM›ÓjT¦‚£3¿kj}ÌÜü”ñ¾=?aä×\vø{µí~·+†l8Œ 1ËÆ2_EëAb,E¶`˜¼hx[²F@ æ}nXǘP’ Š,ˆX!JL‰$$ŠK`—F¦ ¥5¨·ïbbÚ8;¶qQl\þYHÉ%Œ ­‹@Võà8;hü¹ý;æèk3a…,£4a;ÓD@@ÃRŒ£–S2Ûr`ÊJ¬²†øhÃQ(a’ƒ(ÄÌ\ŸFžD”É€P±#D,ØôM ©JYM(`"YF`|¯õòa±6”íà4A‰D,Md¡‚"#Á ™Š˜SÈRšˆÊhIÃF¦ŠhɇäNÄôìlMÀOÏpd*!F·'ðykר¿¿4a‘¤ðtYîc˜ß×+IUYYë,Y¢+:2µŒN-íñ›·'9αP\ƒ0Í·o­ðß…>·¾×¹e`(`„¨ »ÓdTQ`ªÆÛ$› ª2öÞ2ž @!TË2E¬C.€D–ã[&¾{ydž¸ÔCÎþg÷Œ”…M”æ³kõÇÔùüÝÎM/ñª§HaÙûqâ)uNÙBÚjsùU1Ô+Š48”±õh]»š=ßøiv?3–fNeqàb³ dÀ(RüB6cÉ]˜–«ºV;H¶‰jõ<á“;ê;&4Q%¿=V¹/Ai‡˜`xAŸ’­ÈïÒD ú±¹×ÿ¿­ˆ=gð‡÷\̦}¸qôá=ó´ËK˜‰£T”µHÂE… Ì‚™`0ÂÐwÉ>?âz>Ûõ¿ó¸+D õJѬ%F+ÇÚüÆÅ[ü]Þ(–ÓïÚi`@€žVÌlœ%C³»¶ÜM (˜óPZ2:¿ ZðÏËni3ÍE Ur$UÀT]6Ñ jõ%™` „DB{Ï;pDBI0`cðó¾v3WÿC‹Ì¨ÆäÕ#_»Ú»«ÝòñÓwÕðUW¦‰$’®øj[Ä À]Õùÿ¸üºünô!F @DV¹ij¿2USz0<0Æx&I’ëß;&y¸°ú¨\Ì7ßÏ·3U£…3æíÛêW§Ö³?Qzœß‹KÅ“‰Á>©¯§ïXûn¤ÚV‡[Ô²VñÅx×ÁP_“H€+€+°‘R*²20Œ’AEPX±DbŠ(¤PUQEc*ÅŠ)$ŠUUXª¢"’,PY‚‘`°‘ #$‘b‹аQT,Q¢Š)TQEXÄŠ±bŠI"‚ ª«TDRE‚‚‚Š "‚0R*Hˆ§†çŸ-¯är[Òô«¹);™×—rM÷+¿<¿±ßš‡h‚І–Õ†9lÕ‡²ðyx˜Ok<î|ºþ{™ç<­“Œ* 7°ì÷Ò¢§pß#íÛ2Ùµ€‹1€(Eˆ­ÉI$T^ÒüäOÊlAˆ}Ãçi§>¡¾3ÙóßNÜÍ8ÓÆ>ÁØ›ƒØS‹7&ÄÚÀíMYÜÄ?̤ÚCxxgæ<ƒË;³äŸ˜ÞM|iÊ* Ž™Û”QuUý;+aHQ"Š( ,"Â1P‘EIcI$B0€ªˆ¤Š(  B1$ŠAH(ˆ¤D$P‘$%€¤"(ŠAEPQŒ‘AB#$b($E‚‚$R ¢Â, ¡X ¤"QEY ˆ DA  ()!$•$dCU¹ØÝ®µR‘ÐaX mÊ*ŸJ€°ùã¢hûK“( 1EKiK-¶KT"ÕJJ•!A‚"” IŠ2‘Q€¯÷EE¨øê/õV Ô Ø(²)‹X(¨°„€ @,„Œ$ Q„$TAÄQDTUX„‘a ‹ ÁdQb²+õ}pÖˆ "ÂB €+T¢ÐÅ„Y„@‚)X ÄE‚¨,AD t^oÚj=_y·¸¨¿–¿€½WâT¨¹«j/gÿ[/aYLX¶XŠ÷ýïe!ìû°‘-¶ªËq‰E·¢¯6HçÀEÒðK¼ ¼ÁÄ?&„À  ÖÒ„ƒËÁ*ˆÐåN UÜ»D@â¢Å@QvBV°ˆÁ‘FH©ê`¨vÈ‘Qr¢P â¢Õ @€+a Ê‹P+P¢Ê•J*‹B­T¡¶á‘ U©EƒÑ“’©E¥XþíQhiUÌ"¨R 8 ¤X(E‘b2DdQ@‘aADB20X± "!¢Œd "((²( H )‚Á`,D’ € AW¤TZƒ–”[b£Dâú1´Ëdýl6™x—UÊ7t@2¹<¡Ù\A¯EOc‡»®Ê¢áÝT[óëùØ´®®5Ž”ôh;¥Ÿ·€Uìrx@™@ب"4PDl¶Ì~«ž0JÑÞF 9pz<(d‚ è!Ê^ ûì@.X ÒFƒT0l2JÙªj¤Éé©yÕ}«Â¾¨ä„A <ÕJÙ‚t0C17ù‘ƒ@3Ô ¸r_ú5 ˆ=Yæ"Ôe¼Ï§äó7Îï}/íã;_½ø¬ü\ßsë÷ù¾‚¹åJ éy X¢q*,]á‰Q` ­Qm(¹Ð’NQ`¢ÁATUU`¬bªˆÁDd @BD # ,EQUV Æ*¨ŒD AI ÆK$ l&5Tb*ªª¨ˆªÆ"ˆ¨Šªˆª¨ÄUTEUUUUUUUUUDUAUEEUV"ˆªª"¢"*ˆÄUUUUUUUUUUUUQUUQEUUUUUV1UPAUUUUUUUUUDUUUUUQŒUEEUUUUUUUUUUUUUUUUUUUUUUUUUUV1DUˆ"ªªªþ „€¯Ç:Õ”]^•qˆ*û‚@D „EH (",ˆÅŒAŒPHˆ‘F(*!`"Œ‚Š0F¨B"$Dˆ‚ ‚"@IDH‰ƒ‘DDB‘"H! DLBQÉIHˆA"€ˆDH‚ŠDˆ0ˆ‚0HˆH" DdE‚ƒ ºa(i­‘‘$€–ªÂ,TF9!&Ò :¡ˆ‘b‘ ÜÂ9öpXe’XDb±€FJ6"Xˆ¨@A rR–ÅFÙ¹4jŽ­ˆ.´È!­̆àáÏ×Ün08Ú$ÈahæUBa˜æ3!!¬éBÇG®® ñP`ñˆ9é™™Y‹Ë¿X´Ä¦‚"‰.\ª¦ &¥H3D.a’— W ÊÐÄb`ÜÊÁ¢¨è²¦“oÒÓn ø»Ÿ'Í81ÒS.9)E¤3&EÂÄV²VÒ- Z+þøZ0¸UO[ ‚5“1-2“"ª±Aš†.JƒOš…‘€È;™!Y¨±’%F1¥§Spµ¢Aµ$¶V´pÀëBªµ£eA-*+h[{IPÂKQ‚ƒËM:—:¦z”‡ý5¬mˆî™"Âc VvZ÷·$¾Š´ÆÀ! [½.g„jp{»sxÕÁÈÚÛe,k»4ÚÞ§LýÿEÊßtð66|›Ï$É|þ^yNÆ@au•WåL“G\½­‡jÚ­»ÿ4ŸŒÀ@{´ú¸™'ò-¢z8¹=] šq.rô²‹¼ø>—™¾V¢ÁEðºîÌŸ<Óþo½ø}Ça³ù½Wøõÿ»/ñ-—y¨a$€Ê=oy þ¿äÓrÍü¯b¨uj‡8f¨!&övhçM6Ý&Nšz#­ê|žWÃÿ¬Žç úЍ‹Ü(±"‹"‹Š,F(°CYS©›)HR}ÎÈû|qÞK¹"{hÿû5x鬯›†Wòx»µX!öW†”Ô䢈ô#£ žZ‹¢Á>ïæÛôGnÞU]X(ˆAT@Š‚¤Máq–~XZ¼²~h€Žàà¢ÛÝP:…Äñ†¯ÄÇP )ï¼ë>¨üÿÉìÐ"è0¨€+¾€®8 Óöp|ãæXaõ´7¹º,T‡ŠzRŽžñ:XÕµ¾ºŸ —r.§ý;ÜÄÏ©šèÅ쀬êLq¸/¾UkúÚIÛXj7éînUe­ž5ªøãj*ÚêШ?òû›^gtZ4ZÛj/çÑÝå¬s~ÓS’qiaGQy!çbxtQjn¢ˆ'‰œÏV¨8¼ÿ0 PQ|¤Ø" ‘"0DAH$AIA ‰$ð§Ÿò¾ñwùÃþ.Ô„,Á„-ƒ# œ $ðÔo%¹j!H487Í•Ì Î=z(õ/·É/Û¤“ô«™UR³/ñÉ $qŽ»¹Fý´ÑtB t˜QG`8˜kŽHìqÍÏeßi,C?R¿EEør€ŠüHНŽ‰…’ÿRˆ¨އgÐæ"®¤åpø 0E8™éÀÎ9ˆb¥1Eú`äy‡ú†S×ÞŠ!Àd"ȱ@ˆDQl‚9öˆr}Žõ€ å7Ô\û¾ïvE8›¦õÐõ Õy|“– °0øíÕ.wüÃa  ¨è)Ô]ÈÀº‹üå@Ê[€+ALX Ïí8NŸØø–|¿‘¶«¯üÝ~3µ§oû½w3Àr› Ψú]w‹œ¦»9þ{çpE/(P•èëÿ7ò}'Ü£yTŠ¢ŠB*„‚ÁF0„‹,PU„RAY$I=¾õÙüül3˜¶w*-Ó„Qq(½ÅHEPˆ„ ¨ºë©q(DC_ë{¡èûtQí›!$ޱ5ž¹ Ј EýšX •¨¸ ßÓΩU¾¨¿å‰2䌌dUÈ™66Âá´:À:Ò²…§FvumR "Ð4Ï;îgoìqŸùdŽOcT€ :ÖÍõŽŸêÃj¸Ãçôœ%ï‰©à‡‚wž§ Ôãi›Þâ÷»×„‚¦eEö” " œ9¾÷Ú¾¸ Æ×ŽÓp¿”›Ëe@­± ¸ .^»j@”H !EˆA¢ @"‹ç÷ŸñÇ .Ö"¨ŸjÀQNÅEÓEßøË`’")˨¼r‹Ç(j‚ &ÒÆ¤QîÑt¸ìŠ ‡^ãõ>OéxufŸ¡Áú¦õãøÛ/bM÷åHLÙút½0g¬[†zâ)dž&–¿\ò8]gí,àóñ_û°±[2꤈@6r½ «Â"ÿìY´J°YI'¬reŠ·„,ˆàx[N†Ï ³âsßhYÖŠ"íåb º%©Q¢ðý>œN¢BMj¨½µ~vÜ.«º‰T•Qêç‚IÉTIH ˆ!‚T*’Ÿ_pq§ìR;s~ùãÉ'¯Ÿ4ꟲáÎv›{þ[<†Ú(ˆ@ú¬“h](  ×— þÓÿ½å‡J_@uÕC‡¥­ø«ñT"Š¡õ^kNAì%·‡_0‚ V‡‡—¥Ì/ÃP-€ÅF†N@x€%r;6Í2¿˜\ɽ×÷¡?æ’ó—EÝäïçüåÝ®—ÀCsâ  ÕÞ=$ì¼ÝçvÕràÌ’F@Ë©YWÞ‡F _@8 b¯[Fíiåá‚ûW’ ZQh¢Ú _×nùn01=ÕÁVâŠ"Û´s×ZÔ]ÕÏä ëŒFùsÌñîaï}>дê `çè5O¥ãd½‚hÆ{+' )E¢·jÉaØîˆÂÐ¥@t8ö˜¯·DÔÕöÇy½ÓRF0³½ õíAUaÀP(Ã9ò³&Œ®ì™oÙ Â5…Hw0»øÕå|Úûi–| ªó¯¤´ïFÖžuÁ¹„–Ø&¶g5a,Œ~³Ö ø¬÷óôùÍwçÞ„¼:íà pÄñ‘ $Õ¨´â“,î€@"Š¡Îs*ŒC³þ?M›§DT ÚêžÄÅEÐH¨·Ï aE¤7 ä‡âŸ¤ýˆ‹?^[ó:t‚1KU¿(LÆÔmiúÁ¸BIêH×ÿA4P9ŸÂ#¸X Ž0"C€ÂX•åB”ƒS†ÐÙýâ”k}}Y?;XøÔp.ùê‹ú– wUN{àPûœyÇn‘nËQ*ijVöO§ßøv‚ÿQJ%K:{-„ø= ™ª›V¨Èˆ*,p Dq„#á)Àsýv:V›Š$^¦Îo[=3˜ëòMßÇ4Õç¼Ptü>,öî¥S¼÷EŽ–GMZ'ñ\é½\ sW]DO…1±ÃÕ¹ý8ýÙN¶þÍ”v' AIPBÂ" k„@ÈP8€E8K„ý,’èŸRÆIªÈ,ZÕÝQiÁ•¢4>‡Öº£ù‡Ø&b±Þ”}Aù”ÄEUë­OèÏǽc­FÅ_òõ[Œy¿ÖVp4LctQ-uÆõ³¼Š½…Ú(?©N~ig.¡ÒͶ:ø%IE\~J_KëT»¥”¤âJ”[W(rþU¢Ú­9î€QT1V #ºQo(Ék·Í¨â‹¬ÎôV³ù rõ}z«Ä¼ ¸J‚E-•ènQÉñø&¢õtÎÀfí£ " Àôˆ€ˆ„@)ÊeíÁÕ<¡;ü Ašü|“xCãX§þ—¬çúî?çèõ‡{ë3¶ùóÏàìƒÖ(»Ap¨¿žç]Ïé,œò'Bu ¨?hPZ*XT:ÈÞEMCVÄ‘-(¿óàýßgozŽhÅá@!Bƒ€C ¡;ËgÏyGéÊ(%¬Pc·÷‰qÿã}ïœÿæýÆôZü¸™š´ÛDC\E)¶ëg#¨¸†âétÕŠ‹«`ÄB¾ÀULÀƒÀ)@ÕwQñ:µÅ×—^i¹æó_hW‰=ªÂæ¸l¸«Çr´2dõ‡`tyÿß÷­Åóv=ÓÚvBF‡Æ%—?yà¸ýV¸Ÿ'Þ}T¤)$„’I %¢°_§Ú™.ócÒ{ÞïUø¾‡Âý_G‹Ýè;Γ÷|)=ê›!næhíšÁežÅ;ÃTœ/_8ã|¨Š“ ˜s½×Eè+}^ Ð2] CÐ…4[P¢ 7ÔåËÜV¸«‹Ã–ýÓ¸’Õ#!GU'×c§·þYLîT©âþJü¯CÝ„Š0€Bùnß_cD¶‚àm”u#B\©ðÁ(à¤E@Mì±\À?£ÙðÆ¸­´@ÞàžO·ÑÛ,¯&ÄÔ¢A¹i¹Ux1Qˆ„pÊ*A‚œnÒ"*{™EN ¸¢ˆ¼~ìŠakîÊÞÏšP1P…E¨Çå0Ÿiàd¸+œ‡ŠPmž³eÔG×8=¦Mãõ¹zu(Ãø—5€ ù‡úé_|nlÒÒÛ'íþÃÍ1sˆÜÔt¯·»=¨Ôþ¥Kžéûwk¹ÅYÁYì|»8„¦$A ÆÆb«Š`1ƒÔý §mÜrIØðèV×ôèþþ7õê>½f#-”¡‹À”áü¡<~ëàž¸‡ñ}ªûï¨Vª€*¨ ªD¶É hÒ¡+YR[aÛ!m’¬-¤P¶•$X[I …d¶-°–ÒÛ m…´mR°–ЖØBT¶•m[IR°’ÚJ©$Ú¥d¶%jж’µ…¶BV¡%¶IYm*Kl€[`BÛ m mm$ ÔŠÕP U"ÔT*rklU߇» Èò`*BRÖˆ¨‘PlŠƒùøÌL¹’I $3²ú¸cñ”㔑ÆR”zÇò`}={(m½„’q*(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(Ùû'˜jÕ[?–5-~/ÙØÊ^Dm<ƒQ¡cÈÒyw#›3gú÷ÈZ³°.­*'*{ýçñ;l|}÷,tSý$Hh•Oð3˜¼ôÊ)ðÝw¹ì"‰`HÝ‘ŒÑWKZq€(ôæ`¾„…úÆþßÓ×öÃùD¶”ZÒUñÚ¯y$ —å_(ü|¼Öây8ØÓTqb¯,Ë ,Aˆ \€¯ äQQöŠŠRm8Ô8U" ÔïW; ÚQ`"¨ÙH ‰^ð:D>ÇrÜ ŒÀ:‡Án?\™7QpQl(¼ Šh‰í•N/." &@p ƒcz%kLT]H}îtö»GÚ—½¯/{á†SÙö}ÏQé‡í(OÙýŸÔ} ó“²Ùìåp¥J6¶­²‰,¶B×ɇoÕ»;}é@õ䄟` àÆùZ+¦…vÀ(SÙgàÕçlÕÊk~×Êö÷ P1|/-nlYÍÔ”x’´¥’GHCäD ª¢ÀŠÉŒãšÐE°„éÉÀ ”`ð€ö/ ¢ÛÜÜ~®á@â{ß´7´ íÌÀwÿ‹ßYã¹Ô£\ÁL=Y'Ù~>ž†Ï¥óºþ7åyþ9µ&…CÚù¢'úøŠp‡F\[M§“âm”[~…+«¹FA†Pâˆ@á’Sჟ›ïmÍjKBùóîX‹Dÿ ‘ˆæ6xÞŸœ}²¿øÂÒ,ƒ(Xàdݳ ^@Z3|6ãò2¶èÖˆªÍ ÑŽo®}):«tXÕH™X@R…ÆçíW ú»'SšKÁæ¡e$ØHéæ³5…¼‘‘ÕÑÆaÆ ˆÂˆügÒ"Jw*£WìŸøVéQÆòã¬/©øSºè$nk©VÏW¶Ôt÷4*îC‰f*,WXw¾·¾>–kÆèùG‚ðT ,[ÓñŠtâP.|•gÆÏÎðA‘Á3c¡‘„êx7Ì g/.8òZ‘õ¨Š¢ZièèÀ< næËœùKðê+×—Á^?“óôj/¬]ëÒÿÐé¯dzžŽûgszä©Á¯·ùö`ÀŸeïp¤Eak¿ˆ…ú4(¦%PFF˜P @D9 ‰Ùû¿›oµ“{7uüUÔÕápf}n©Ô`>S¿í·…¢]qˆîІÝõ¦Ó:.«Q‹åê8®"ª¤Ù¹Kb¨w•£€©1Ä0àŒR”)$‘§Bj8_­ï®ˆb#Î\+$-Rï?AÒ!Ï0_ìgÏÛDcK!ðFð¸= p '†?ŠŽ E Ü00pxÆÓ{w¢¶t°é{ÒõÂçÂe –&=!S¤Â« b1{g¦$CX³iuŒ[ 1:Ì4`° q´1ÕÇëÂGîoØEa  cižÝ:ñäÙ¶aëdÆa-k&Xͱœ¾P­Ø¥UR•P¦ÁösÈ«s–Î`ŸkígÓƒ0²u?S?ÿ)˜áÂùX €E´€ÅCqd`DB  *ÊEWý?€¥ƒ; -jÔCði¥mü;î¨t•B­t€;+'å}þáôÿ“é÷/3ßɤ¡Û6ÁÅHXp<%ÊÄæ·âƒ¿à¸Tl(]6EAÓV=¼ô´LP }Qº ¡† €äŠø<nþô“dOÙ©ë¿ÔÓÅd¾Çõ\n›rd«5ÐVaIݶn©Úp5 P „Ô—Eõ[„á`¤Ú;1‡I¥Ä[vbùÂû f”ÿ7)Í¡©çÇïþsèý0úù‘ƒõ7ÿžêAÔ4)*ÄJžˆDLýäÕU4‰ ”¥PáAAR &ª©Ç!%HNRˆI椙gô>íõ®­u·í‹UѬÌ)R–œš ±I ¡éË(¸cXÁO5‚“Âý“˜ºõ2zù­ŸJ¼hˆÝo£ub‰K^ÏseWmj̉:§xtŠ"‰"3x¹d•5†€•°‡ ]TÎ^ ™ª6LL>c^uF [‰ôÚKÚ2í¨ (c‘B¨ˆƒ‡Þ}¥ ¿kÞ}O×UÜöŸ{ñN©ê©¨ÔèTyœó½µãè?/…j1µ³oæý:>®uM NÉ»£*u´“¡ZÂtCþÏä|¯§«ýU+åj~ýú½¾ÌÒÈX ºîe¦4~ñÈe$¿îçöAôLI?øÈüéÿ§Ü}°ßŸý_>Õò‚œQàP@ÁoZC?¶2 æÐm“Êé¯ûPÖQ=R±=‡¤ÁT ΰàc@ì Ÿ#­Ó†\‡b£NTT@ Y,‡‹2Æ!x„@£%Dæ%((©ðòÍ[ã¾ X ò´‚Ô´6*P öPÛ@Ãb=# C¨(\Xãê*?\(Ÿ°N¿¶bOtü¼=Ñ›F…e(e1]¶0†Â‹E5ªh Z%º@ÁP!²'kÎå¯Ç66]‘D6üÙ aÞíÝJ»Úµœ2ì鯤ß:œf·øy™—¸äeRB„–('ÂA[†'UÅ¿ É.г»¶¾ñ¼øwÒTD•ÜÒ„†Ñä¹YåzÄä×<C¡ a.Èòmc޹+UÔ©Áº~vÞ:Ú¶®¥ÙaÌ""v~8áAŽ#FržŸ„²Ü¬õœnš°ýä>¿kÖèB×ëH"óÓ›ê]o7œÁdjT៞îìý§òØiÂ÷ûxJ’d„â°J E`¦2ÁÄ@-c„'ê;µƒ’î”Û^ñ2|Lkºó5¡€ëí®'Ö;Õú†Œæ&5P4^Ý(SeÕ¥n²WjN–Pj‰®T\Љ«© ºæ®@úñ$è›*¦à ¿Ñt?ÈqÿŸsþ2šÿ/öóR8‘³¢cÁN6W qÞ 3áZ;½KÒ^UëÒX»J¡²T\ƒ'9¨1Œ©~…ñ{ÜÖdp  ¥ýsEDCÆì9î;îN\Ås8 ÐÏÇ=~hŠEVpù ÙĘû@ÞêœñIüWZE ˆÏ¶¢…Kú€¶9¬ø8"‹Ì -It·Š[¬TZY—ŠX#Àz€4ž(?H¡Ó ‡>ð,W“º“U½Œƒ c‡úQx\J…ykh£j`›|Í“3ñ¸GåÜRÝžÖœõT%0@¤¨U‘)N*/KúÊÜK‘E/N|vÀ’“¾µå¢UèLÎZ@ÄÏ VÖsÎí&xØKf•yix°fhfi,„‡h (y˜«ÍnfèE‘`02¦¬Þñظ¢m· nÅ„`¨†£ÔÈ36ʪ™f¬úLÃ4ÃCœæÆ<¥Öbܦ“98‚oÇ -ÆŒ9¡ 8‘6 Ï ¤6’n""»M*£nÐñÚÀÂ'2g¢„@<ÿ>“}@–ˆÈœ¦ÄåQ7ròȆå9!\9ŽÐ9Ãb"Îä*>6öÒ‚žaœÁ ´Xr2H;±{ÎÎ9­>=²ãD’1š£Jq%F$.Öp‘>» FöV Na’)»Œp #ƒcÂ6g¦>PÑí-ÂÇ®p ”ôÆ€Èãr‰a…¨2y­šg±RNÜ‘!$ˆ8ÚÖ@öê,mñ•„¨Û8a_ƒ“Îd÷Î}£— ðMÙwM뢢÷¦€á9wÍ'áÙÖîERºÌNݨkw¢ˆ~(‹‘e{Ó²m  ðØóÃ’';¥k"ï<¼ýÀï[ €óÅŽXwSÎ’níÁ¥ äe2I-2Åb¥–€s|H òrp¨/@$LàS´ó»e€VÁsk:@Ú8DçŒ+Å&‡¢êyª.•E¬4—›F #‡%Ti*lÈ÷– ˜ ÊDŸ…$2'‚Ýù[Y§]Àwhø' „ŒÈóEøyØáÍÍ‹ìg®‚ðÕPQ‘6,'¨ÐpO aFOX˜Œ´ h\Ú[„w¼¤@×ÜÙ°¹¡¬ñ*‹w¦Î½Ç3¡ )c"4tÅõ Ê…>Ñ4ròxyˆ²lç¼.÷0Ä8!Ëž5;ˆË(¸Úõ^{käk°WFÍàEU(ˆw PR8n´ÛkØQ†Sö\ ÁtһˋŽétY¶Ã¹›©$&·up…5`[ÁÆ!2(€b˜g`7,adzís“a¨3Œ„’¹‘ț،ŠÂH«lÒ.A“ÉרÇižq’«Ò$ö°÷›&ò(0ÙÃ'8\ú~ÃÄY½R½E×2„Sx;î„^\Ý“6昇{jùÝÖÈœŽéõ¤²ßíõU:Õ³\å„P ¶ŒÃ&HBLcA€ ÎfDhøŸóîúä…ó?j²0C;}·õp6Åø±ðµB¾¸T`v?ó ópp!-ÕG¦¥s– có€¯I>cõÎR¨(úÒUáÄÌ‘¿Ën‹©Ww…ÇU› ›ŠðaìsÀ† Ç¥/v¼ †ˆ†*‹ëT\ƒëberÜÒsîC’|Syב|n|DÔê Sï`HÂ3íì¹h`ŠÂšå´*±Š ©—æ€uœÅ…$oˆëmÿœ¨°Ãù+ ±×—tòL”0hf)&Þê¡k­¯Š+ÞXðƒ×€È„ !„p «a¸q¾rÔ*JÓ’ÜÒÙ‡…nOw¨{Hp8„m ǨDeJˆŒIm\¹‹r®Œqb'³!% ‰ÇY0;9ÂݳðëgŠ~“(¤rG÷k騵¿nêÝ,[} GþT%ñʪ9BÑHQTq‡×¨º€Ý7@ßýhÒ½PÙ²í‰ÎsæX°Cbµ(¼ërK¦ó£ l k¢Ð —ŒÈé£nÝ 24 e@@EcT6,#qWäì¤79±4.ªéw² "Õë”Ì”(•L`&Q*HZaëŽã‚i¢ž) +1‘†0 ö€+Z•f!\,Œ\èCt45HM¥v‚ ·»èXñ¼Á7Š˜ NÔ 4ƒs’çÀü?Ÿß‚&¸ ÷8í!$ÍÔä1¶aí))|!)r–´RÛm””´ å’`ÉD@i€ X),T€”ºö`{$BD`aGCPÃÐЀ 1A«á*†eÄŒ›ìô{Q¹sôJô mon¼K¯æÎèòPÐÓz Š”¡œä1w]·æîó:-­ãc‚j¡VFÄC0>5²ˆ ºn3N@e0™‹ "B¾¼ .&©@{íáªB`ÀR3iðß|œoøÚ %&ì^=3A$Ò›¦Ø‹Á(*`Ñ“’©¤*¤V1bi%EX$È@ü¿7þXJl³ñ¤ý§`®Éœ9Ì|³ÜÛ~üa’=¾÷ q¤Ö—+'»Ì>óæc¦õQu¨¿}LfUbip«ÚL¶áÿ®*¢qÄòø.mGyÙ4ãV\S±¥ƒ§‡ƒ¶ÊÅBBAì1®–¡"ߟŸÙºÇ Ý_¿{õusjóuQñw•-°¸}ÖÃ`I=Ñ$ˆ‹AE" »`Ô½q# Ž¢´T~hk2'DmošpRË“ßç¶IôX{ì¾Òªë°gÎkƒ€w¥!…é Mñ)ƒn¡‰Y·ÅkK à(pÚ™=ª’±ËCä }#DIȺÖÌ$Âñ,!‹„vòPw ýp2/¹EùÂæÞ|Là}Wa17sÌr bŠ-®å+ÏÛöá¬[ì^ñ2ÛX:ßE! …ÄÀÚ°Ö†–R—¢uSAH­ì êZ/‘c"Š‹æêQÂfE¤„¢*®¦¤GÆ€±ž¡d.IFåp};¡¥ÃßûŽo½Áýïòêù=güy‘¥ˆÚaN²òÜ,©ïø\‡&¯&E/2VkÁ±à»‚€êCe[€e6J&¾lbޝ§ö³`ØY‰Ô½ÀB*ú‡>¬{—¹¤×õóðk›óýÕ1Ïât͘NbçäbÂBxMÒ¢™NN²â‚ø;¯µk­Aä4-ÂÓm‡‚€ÐŒ¦JY `7g`[;¾'ˆ—g­¶N®eH¢(fvÆÍ·Ãv@p†Ò©I¸4OR`Å¿ ­!ôŠXPéÁ&mwÌ1H­;]n’d‚*8‚gH;Õñ¶Ò[†âgy “DsÐj^¡CÀ£®.§w‡Nhwã»;ñ†-3,u1.ÁÒI·]•\Õ‰B%øpTëJ‹-”áõBÆFp²”唦”&f·"Ù†o ð·,N¡c5ÂÞJ‘™†ùû%ù&Žòz Äç£QUu–SŠî3ÅñÕRpÛèë¡T¢¾Ë·‰LàxW¾]¶ú_OYÉ„™†m÷Óá®3wÑä:x_sÐë-Í>dµÓgÀúKo4dÚHãz!÷r®¶5 )­[D($U€Ä>¿åî²Ü¡Ïæ`”á R€áýaÇf·ÌU#xh µ¦£©Â·e,÷øF¨B¨•ƒÐ h¢ÔE„MŠPP%û¡tîèãŠ4*×Äë(àóÁÂCD"1û,îtØb‚OT*4Ð0A”1n2;t+ï`\b9eiû­^åñ²¯`Ÿ‹¼š`çMõéûÍã”—9hš”ÚÕFpß0d$ܳ‘Ι (m¶ÚÎw¢ûl|‰f¼µŽÒd[õßEGG8R»°F`6(Ôâç»RWo&òÔ[t?t1ø–Í,¢€mO,‡",„É)"VJ6òÍÖQpóøÈñua'mù*ÐÙwLUÇrª«?©`–"S)E¼"žÞ «„oöt03„„3 ¼«g¨^)¥ ÏòðôÎ…ñb·:ÓagŸÈMª,€¬·$QíBB3°ƒy<ß+¹PeT’üš¹]à'O(p#`UðÚuÒØ·–œ¨cbÊ»êƒL 8(©–%lSÈX .}Œ-ÝÕYóê¡«Øä–BMÜOm¸c­öͳ%ÉuÒ@›!¼¾X*ÇÀžÛbªC…!b·0Ñ5LÇ.0ò“`J*Lbɪf0ã)2*ÕÌ·+ˆÍîšâ9µÕn•·³ëÞçj`C ·´M ”j”ðªrηjÂÆË5ß|ã¿O†µ8/7:«Êš¡pf y$N,0ÚrÐØD¼ThœùÀ݈ó¨º"ÛÌÕ‡ˆÜu&È M¶PtFØ_nmƒwC„ØŽ$êó‰¸Ù0 ÐVç©“ E‰IÞ`˜Ór,…ƒ©î¹ÎSÑÄ¥í½P;Æ7e÷[8œÑü(…§/˜õìP- +$€‚3B*1Ò»cˆ¨¶Ô^=äB@"7U¦~<@œNˆ`[³á#pC @œ{»‰ŒŽž ¾’ߥзÍä°M?çj b{«}óÝ¿±®Ç·×ÜÅ Å.õïíØ Þˆpú­ ù OßÉ )¶ÅIFH(fYY‚ˆí“d:BQ¡ À1(Éö¼,›:Vm=ôÖm€ »&!¬´´P°˜…eí¦& ˆeJ’+ˆŠH²[Ó@¢!`ˆ­_è{ºÎ'õYä(X˜õ_‰ƒÉ`ß2-úÍ…å\F’‚’ÒZIžÄ¾{áõgoìÎÒ<—åhD@‰@èWÉo÷}¯ôðæjáËL»‚Ÿ ÉÎ&/±¡´f|ªƒÍFË$Oá¬: +^ìö;xc'aÒx¯«ÍKm俍6Xò_%ÕÊÔ:€gL5pJóŠÎ?ì'×&È6 g¥O–+¶µ‚=(nÀ}pܱ¾Í€™‘Y.G·’WÒJ™ÀëµT]e|«cø“¹¶“n=…ÑE²‹H§%§åÉW ˆwƒ>k왿Á fD+)ÿoÏÒ6•e·éÏsÎ1ºOûÏÎöL)Ÿ×Îñ?ª¯¹‘ÒUçnh_o·Ûíö¼•k¤T\ÝJpž£òtÄya "§“j# ƒ"úQˆ‰úrÉÓ,"?"ÚÉR‰ËVøÿ‰ïHIŸjxñàÇ>„¸*um~#G-ħ|¦ÚAY·†²óAö¿ €o·Fðˆ(ÚŒ‰ ß *ú‡Ôh¾Šwj±øc˜\$N^”*ÑÒû„;Ð â’ „ˆM+ªQ½YêuQì,?{ #¢Š¤8$9Ÿ<•Àv$/z©º*Qne1k:Ôzµ­†ðãöˆ¯•Aœ@ÏÜxPEBÀ®Ó…0:Rò‰q¡1Ä0Ô[¶=X°*Q*!UPôDØ ›—ãu ıöA À£É(Îs¨±WøÂUG8 Ç¢`hvvy=Ö¼qÐæé$3éà:LïÖ4t®Z.Tùé€ðò;÷>oÆý¯ÿ{}Pˆ0DW‰KUŒ9‚Ò$B! SÓiËËÓMfΫ½¯‚­ûÝ(9ƒÊÇXCKW«÷Ïy4X¢Ãéz>ëÑÀ󤄉Šæy¼çë0œçO®{ ›©ë© €’ˆ%I°";š5. ÅNrTØÔœaþ&ÀzP‚¨DV ²,„X²’ R‚ÈH(¤ŠŒ" )( E€¤‘eЄؾÕn}ð™±l ¦7©!úÔ¨¿n6D!ç‰; ©‹d)XtP@"±ª5ÖÕc4…Lñ…2‹æÓ¼nÒ˜DÙV$d’Ùî_rÙQ˜ÒÓß«pn‡d¢5*º™°YÌùn–Ʊ,YQtŽòŠÉ–Qb¨„îDD ‡þÕ+xº“Úþ®ãúga.hÚ¼–÷C >3nZ ²3•îè¸l8,Ão¦Þ˜R;ng½×R“&³=è¢_-ñ⯿ÎSÃ#µÒ“®È&tbå-QÕÖ¯ŠÓÐ÷]½7|ïmÂZÂíz¯?ý´<{·T^@9äWs'&æ9ÃXM$nUrÞù<7S Ggpç}34K#ÝÝ6ůQÑø¤R²qQcnd€Sc=¶ +%#T·åB¸®"¨d~¬iÐ[àþ[´Ìüx‡Ï‰„?x ­ß}æÛ<ÐÝôeÌ ±¤ÀE«ô>¶BY²å‰åÔma—ˆnrB‚bõjäØ!ÇãÁ[:ü4ò‡ºY„aB =Ä‚!»U’*ˆÀ˜Û›úk #uß_€DÈ, 1U„I Ò&PQªÝOëX¤ ¦À±±¦5°ÑÙc³¶oÅÊ9b”ž½‡ÆBÅ4´È4K ‘ŽŠ›Œ@ÄàX¦]ªÏ÷´pQaÃÎA‹oMš:I21$"|dõõLa¦(¤ŸlÐKKkZlšHxåÜ0°rùò˦DhF÷ ×­ŽËYh¿pûåE®q}5/W*‹»›BJJ`Å ÁÝ»D}^¢é†‘FURD{ »š4^R2T*Tê‚¡‰ÔÎWYD×¶D´Æ]î§ C™~Û%0» ˆ‚a¢&\§W1ˆxuçš‚šwú‹wËäÂhñ % ðÍÛmš6èüfÎ5.Ûcèóî‘+/€x ìò,b)窒®x>pÔ«ÆIM‘‰JZ €°“®Œ ÀéèèkÏD‚Â~ ûWR,#|¯-‹ –#Ú,îd+uû}]5R¯ð†t81“ð‚½¿®ŠP9ŽcvÍú'wVaŠ;¼ëPW°öj3?|ØëLÐXOpe1Na$«m ôl:Ðõ¯š"{à€zÂBôÏ]}.Áö žâk—ÃÈÏo­ÑywÜ;ýziÒuœs)e‡4×]ª ÉØÆ¬´ É–Õ4Äu Q§²qèíÚe‹¶ªÚ7a!¥I¬¤6I϶Ú9š%Ñ cVÖ­µX$¡Ú CHIì’B*A„P€â€‰®©$‰b‡‰ß¢{[ë,NûÀKC:]0R-Ã,wü%GÀR>¥ê2mãÆ`Sb•ð‘ùT >Xy3&ÒìjÝC¿}ª-•¼DÃ]:b† %y¥.dqKÔƒæcT’w†(2FA‚¬€ ER,‹ È$ˆ EY ŠÐ I`UE„„PP¤Š  ,Š,›žÐ|Qþ©±°Â{El`+IØœ¹UØörr'/S`[ Í9â: ˆ70ˆF)æ¡T,Õ¢ ÅŠIƒ `¤Ä‹&ÈLOwk”4àa+Ëë)/r·ÝSkÊKø\ûŽÀ TÕ–&z^°PX)‘„…1iANÊ¿b Zý’Ä*¤¢5ÿµ¾ô?ûû›ð¾æð}ûùÎQEÓá9êv¼yÔ •$2äQMFd™Zß Eƒ‰¬ìÊLNtùÊÐ@W¬AtЧ´ˆÓaÀÀ  !q„1«â—ÊÅU4¼\öo”Æ;kÚúú|æó .gækAEí"×÷sWäóìó³ÛVE¾(´¤¿Bï–Uá'”¢Äº‹-Š‹ üâoóñ±„X@0Y« &’ˆ¡€ ÅŠ¤•&’±d9¤H(M!RLf1´áí~›?™a¸…`“ÝÒ¬‰h1ƒš‹ë +B‘œ"ªnÈ=*þl³ýü€¹{ÂÇ­ €"ƒ–”ìÅÎW¶Žõ?'P]9ª¸kÊò<2fA”Ó®:€´¢ÚQ~WúÛ² ú&Ç×Ñ÷Þ-a¶/Ádö\¿LÙÜú‚‹ð®-ÃèœÎ"ŠA Š [ ‘]Ø™°V )K Å7üEÇl€û,làäSt43bQHØà-×áÜÚ'«·0Ûôé3Œ … löèkm(EwcnøC# R»a•5*I$°±´mÛÛ[ ÝQ€…Ð=€” »ÏèÚmx<Âu´qOz¨¸o•4úC7'¬³»’oÛ•S- ­2*Á B£€] hÔJZ@ €\L:rÂ#TAQ’IV|žS§£Ø{`H2HG‡¢“„üsȺªªªI!",&ó¨dA;¾ ›ÆY|à ÁÊ…06òŸ„G¨ˆuÁNöˆéÌSͰ:¶BãÂ@¸À:ð;ŽAYUBUaJ@÷’WÒ„ñëX;ª>¾d1@õØ:¥a4ÀÃÍ+!´@Œ¡SH%UBu„&~«*Y×ÛP̦"‹ÞÍÁÍÌ¡Nã[¨·ˆЇtNSg2ŒP©u„ÏŒðó”åÂVÉ ‘8ËÁ±yRñ®”Åp‚”K›¢"îlP.ß ßùý<¶Àw|½ºuwuð+¾:¯üß:|˜žØ•á}ühœ‹‘EUUUUTQEUQSé5TUV(*ªªª¾èpŒFA"§b‹^GH¢ò žÑ,)'ÁÂNlS£PX¡÷ * ¬Æ½jˆË™”´ª/d¡U›¡é#ŽÒÌ4ëøTmÖ—í-öŒ€HfwáÖ¢¥Õ+®7ÆIBHI"aB*µë2ÁWßµ5ªqo.¶´ˆ¨÷’ÕËJI I#$C´Í(áDfAÄÅî»Ü–¹ÞÁø/®â¢êÚ ÎÓ N!Þg,Ds°¦_WKR1„aYo"÷Ó$³RR^þO&µ:I´F$Õ’…#¨ #.l3 ¤4  ó^‹H"ÕUUUUàpdYDFp iUWA³Ë5äUF(ª¨ªýÑÆšý¯d€fQ@{üTÉF”@«Evu¨*|&¢ÅWÐZŠ*1EWŠ…-¥Š* `«äS˜ª¬÷Õª¢ªeŠ+¨QPölª""=$9‹˜y9š‹:š‰‘ê-Vt+j¢ÅøFøq·nð§i·ŸÓå9L„D€mµÂi¦´"ó \5¡GÄõSÓ܈q(7¨6Ùuk =‹…W¥/Ò¥EUEUUUUPcäA¦›èeŠíK¨yÃŒÂG´&È£Ö…|çûš\ËßÊ/§ËÝsÙq—žZ1},)¿¹!JCŒ!ÆB !Àц Gö½]ÙâwÂDÎ%D@¨‚hú‚‹ŽÑ mB…,,‹À¼4²PoÑÃZÐU 'Pfh¦Œ™ €µU øúÑÇXÍ«†{º59ÃŽÖc1Óº„áâ&œfmìA5 ”Á3oI‘p¦ÎµMéæ˜†µ™S4¹‘ QÏlèòEHœðú_ôõý-Π ²DAgè{&„Kìü]gXÙßÉ(A,€’£–õÝØh6ÿÚ¹pX*9~58g ”ª¢‘ ð$U³®)ñk¬Qbµ0†ã$¨ÅíïBûÖ`žGš22ß«ãb„^<ÑTKºä5.ÛàÜˆÈ t‚YûPˆµ01>ÑP±ïgÕúþêÄÝFy°’*jŒT¦Œ¯‰°£<4Í`DMÑÑ¢°Qj¢H8,µÊKE¬Ö²BB” 2Caч­|éu  &üTV袑EcŽ2”MË,7BIpà …1…KEHE £È($üuÜ6L!Š‹x¢È&`f‘uü  ÙEJ4! ÈÍ(.\¥ÎWÁP(Z1©hˆ"BX  !(·FõR LR Ž@Ù¡Cÿl¶ I7ðØ¸…d¼)÷[‰I¬°á ‚D©ñÂ…¬‚7(»êZ©–6ØNF]¥ÃEEÈ’ GßÂ鿯Žb¦w$­XÄ€ˆÎ%$bJÁFA9…Àìêç¡_'ð´,K MÅ?Juü3ÖŒ–„3`rñí$ÐTäiìíp;ÄW„xž{çTVB.<«k€„“S%Qo „ — ˆÓ©"`%–È1,„– I0áaš`Q™ª Å‚¶%¶ÅYR‰[h€$‘€̰…ŒØ²M`Q@X„ØŽCP­‘ÑÎÃÖu ÐM€„†`b¸æš˜ ×€Q’FHΉ 'à§YÁ©‘e´P’(II°RÅY*¢‡U(Ðf¯7CÓ&é$—‚^/>:¢›B,Œ/âÈÝvµVe _F A¼ªxtA ‹;YMtSr\CÏ:cƒ´ÁB€åtÜk7ß»tÆpé4ã#þ×ÛÆÑó$Ä ‰4Ž «ÿh’nÛ‡eH!n=E´ØhK4|÷¢Q~-`ej ˜(s-oÇß4ëZÖ¹®µŸ6@’s<§ ŠÃWBgÞCC °ÐöÀ¥\Wp æ»@¶Ò¥¶ì½}4‡æØ.‚°€¬xÂîÙBz±ÌT{PDR$D ¹ìlC•Œ'.z¶‚ÐËþÏüó>Û¾^êŸì:ÌÈyætÏ* ¬CÖËÆÅ"Fq]öÚÛ‚}…%b]}õìÄûÊ.›??àˆtNàEÛ¼É;°eŠ˜Õ/Šo¸§Ü“s `¯óq Ÿ]ÑGœÝúâÞŽˆ“}ܤ|(€)húïo’‡KàÁH!9!Qk4€ª¸Cx©ŽËb¹@{ ^Œê‚¬TÎjd×/Bß‘ Øaø©'ÆÊUa@A²wª'u~ø/PH›ˆ# úRCöÛË!±úãž@Р°¸áp†zÖd™öx±Cñ­˜»Q|€{©g²Ï(©Â…ˆ²VÝõÊ7ŽÎnZ ¨Ý,§\Š®€âÀ’0(®}Ì‚èâfÐÀE ‹œ?ôñzŸ?ìõÿ;’ìý§¤ö^ªãÍ“Øß2{ÿ¹µR7iûw3lÄk–Ñ›„¥'þMÞ>œˆ#Æ t;†r Æ?«Ûpž×ùú[!²%(M÷ÿVoÜ@C`l6LV‡²Ö?Þvúv~rU.]Iì~4¾“{¨À€!†AÀ:èú̼ïÙÌmÞÏB^Žý¬hW¥k*³”^,BË%Uè5ü %Tt••ªÌLH,Ìd’f ÇEÄŒ ±H:h©¦XŠ•”2àÌEV³k*±EqšLûíQÉLÊä²/xék­³?iÄ®VŸ7ŽhâÿM=ïÂú“!Ãv6ëù=]~ÅÑ 'm ¿ÌÈŒÌú˜I'ÔåËpsß&>ÅyCçý~ÿG^Žw!rJTÁ©Œ¥Q†œŒ15u2Ð’>kC…TX–£ Ò[/qE‘EöýþN=µ¹xšiÊÇ*ùôª´G›ßýws&@ÛzJ%3¹Û¦HP¥*¡JˆUUªañö²Ë …K½'»>9 ÞZS_Vdúbdí.²’B⎉¢àd‡QPNùö9×Ý–Z‹VæÓDð$hoÔä™ÙðÍÍ•TdU„‘’I$’@A¸öoœ¨ººcT–šr(Hª,BQ”’ R"ÎCm¦á•©Im,’2Æ0rŽbVR›¿XkN˥ŋ™r€ÎÏ´¾œ'hŠiÉÃðÔZÔáµÇl­•!jåØ!íÝÁkIÕ&Ž…;»(¢Ò‰J-^ꋞãjnîžËÞï²pß,j7Á$—!ÁPòuþ'ZÞ^pŸHl™”†$JHE })Íw©3ŒvÖÆÄW}˻ܭ»ÏµÏ#ÊIú„Ì}ÏEì42ð &`ꨃÙ¨r’ÒÂ!ŒHCl3Áæ Àmp<¯oÐ$ƒ©E̤‚©w‡ºÄºI$<‚)Z@Nê‹›w)Ψ‘›Ê‹¢8FA@¶ ׄõÐ`uŒ¤æus~[Têó&a ™”Âå_5+2^vŒvošÜ[]¤Ìµó&%°¬Y…®Š ÊÚž›s.rÞã<íœ.øá4C@ýÁÔŠA¦w€Ý!ŒH¸17¢¹÷È€¿Z¢Ú”9S#‘"äOyˆ™"²*°.H0‚‘UŠR$ª ªÅX²¹&\\ÜñXŒ$‰Z¨!å ÒB÷pQŠ`)ÚE<“࣠‰ÎsÑ*PUY[ëyö©‘D›ì Šh÷EJ8ýýóÍÀ$±Å3fZâ¥*·[ T‚"† V`…d¶i˜™H²É@€š 5[@iW¢ÒÛFˆ, ZSc cÀ8 =¸*ã·$h &[[Zµ!¡Do˜`Ž¡$ ¥[¶HjÅþû÷YùŸ·ÏzwâzWûK Ïx—þ¯äì~^´·ÀC;*0)¯ª•æég5¡ÍPÞæ¥i(ºÄÑH^êcï¿ëú»I÷ ‡ë´tLjt¢B@¡Ç&H¶*hÂÁ÷nù'm*™fª>²MC›S²láÇ©‰@ïJ“ÚˆeSî’N»®!¦£Â 5â©ÃÑ|<&;¢{x™†kaˆÍö²—Ñ‚ß]¯}NÛ™Úõ™ÞL·‹™XO§6:O˜~ha™±ðS²@C>;»ðVÎZ¤=»NT=psQ–ÖËqw5Æ(­ÜÊûªHIÇ+#ÖóLE‹s2œÌãæéÅK—{kÎgy¸´Ò @“´Jv’Ã-R@žÞ‘‡ * ìDTÓõbÛ ma M Ú)J›{ØÝòÝˬ¨®Ö›]ð(¼-:ZlÇ{—†aǼų Ù責u³Â—{ÙÖhl“µ±[]Ëòm%D<çe!Ó0‘»™HÀÛ:ÜL!%²I¿:C¢½O_ w°±PTæ¥YÍÄÂQ«!Í7çHsW›ÀWŸ) -åÏmâ]kXjW0ÓŠË@37é8€ÙÑðf$¨gö§?/Š;ç‰ïðäz7ÓÚñ´ááó=áy ÉYo"¡Žõã1‚­ ‘ªÕj+«Mˆ¡¼ZNd¢À V¨Eú>ú,ä>£OýŒÈ˘Ÿ@®áîF$D PÄëOžü{L¾Ô7C7ç ´ïëD÷ÒévðÂ'T|Y4SCôn¯zp$“ÕE4œ`›r„É“p¦ìS@=0úvJéöJ‹Õ°í›5÷¨,d]ú`D…ÇGQ÷@h$Ä„´ j-ìxmsg%ˆ$RX%ùì4èÖÚ¦­)"Ö³*‚*‹„i-§ ¨3ôrÕ/+ãBbp*Ä’&­C³Ú‚·Çpl¢õy£€r'ðÊ9óQi虌áj°­*¡#!-àT½}ü‚ 7Èä"^²µPs’ÝÐ`x€Øµáó¹.¼ºè‘SìòëiT’oÃ\ ¸_÷ÓsÞ'¡Ôÿ°ã´¿7èê²3ê R©"Sfjh¾GÇ_#8?‘ý?ñ?ó{ï£L'ÝþÂJÓ]Ë×~ÖØ@¡Îèë)bÜ— †s¾š£Q;Ú)íWƧ‰ r3$nêß)š1/R|MY¯ˆÄÕQ÷‘Ô?Ùp‹ƒgŽbgе»iÙ)7 ^¯Cã¡A£•IJÓÀ@ÒúQUÞÓaßrLÕ¡Ò­>Â`Ä«žvvmkˆ+–,˜MplßCYjuKé3ºÚ«ú8¸ºUQ•ƒ"·oUEì'öÞU”]raˆx" Oœ€ÌÙñQHh® <™dÁ×tÕS}QÍë9€Ä®Pf¾1j«*ãÒòÇ<)ÄÐ+F¸U¼ʨ¼ª‹J‹é€®½æñ¯¨wæøþŒìedÒJˆ¤†³…£œ½6eÕDyǧ§¼ÌFíaÕF*ÆÀ¤‡0åm]_t˜àgzrþFj‹‘¡‚Ø~6Nl̇wب¥Ë·íáôÁÛþ!‹ìÌs-6@*,!ÁåÞ½°6É®P’«O\ˆûPÒé&½uƽ¸%ÓPýl:Lä$G(›qì«Ë€ ûÁ Þ€0 @Ã^µ±Ý. HGdd±‚tC«,€9ÞßiËý=](,औArTXD´ÑÇV¥ÃUåb ]{Tä:-jœj­.ÞÁVlQB®™€Û1 S‡N¥œ63Ë|Vé %NHjÒ¿½$&Àì„“¨fÈá]iB8ZÆÂȇWÅŒ}ZºsÂMÿ>7(ˆf´]t5Ø‘‚ME,Zêa°v7ª›Ú (3î‡!J/ˆ+ТÊ|«ÎCÈùõSÆDß÷ËV%¥AÝ„¡,ÂcCZÉAxpïGËT]á© à‡‚'~HÊ@¢ ² H$’ÈbI‰%d‹Y"Ô""„+$*#VN2BÙ†è¢ÈHkªãàB¬ üèH]p=|Ë*®©¤¨èJ+bЄÄ‹ÖDGòQ †ìŠ\NèÎÊuŒŽôLúóyš”40Ž‘AJ­Æá;žºSÏÍ[ù«Vé·’86V¸fóɸniØòƒY‚†e€ÚW»¿lM‚ˆÈµ ‘Q–ذ­´MHI© ̦²­T’ AÃÀÖkZÖf²a„ÑÞM¤$M”A‰jœd$L„PFAŒb)ºTQEV0Pï’<æÜxm½]ÈQ¬,R•P¨Ïêõ  ^!PUë¡ ˆ ¢€õ™/U'1•$<8Iˆ,™ið;Icà€­uañÆ–¢°à„A È^1/‰ ‡ H´+KI‡ édÃhªW´ÃØaê=B­á¼4j±EÀ@É ç0 âõ'’8h¥Ô^àÊSG] bx˸&7²ò quRל³IAÝ ³­SO±•öôÞâ­Äç¡âÑ`[LeËÔ•1È(Ej ­—ZyW ×1Î ŠÚI& ¬z){jÚŠèjˆ±ŠBlZÁ°.°Ö`ØJ9Þ‚d€ÜÂÛT%Ñ|} BäIH„ $$;+ˆàî¶—¦!֢ƈ‡2Õ”ÚQeÍ{…ŠazIéñ÷>ÖóÛÚ›Ü\æ\¯ºVU[ÁÎCššøÃ °Œ0ãoÕU¿«?Àì8Ö|ùÿSCäzwƒìv@mÜ_ÆeUTŠ!‚,†+«…3…­d "dˆ+D °„ýl)¢‚HˆÈæu8!Ó*®)RaiEÛ* Äs˜b¢£;™ %aD’ETQ ¼ ˆ'S ±‘7hÒ†ÔÊ&ª'Q$ŒpHŒÄ $XÀŠ>ËW)Ѐíj‚"’Ùß_ã› FÒAÝ‚± H0 …LþA´@WÃÇçèlÈq¥ÊBe6ßÞÖV¨ õA*â€V-­'/;oB2PoH©, ¢7 íÿp^è\¤Š@¤Åøç;Æ(.gm$µ™(¡Q«C/Çm …P2%Ø–£›ªÑš šöG¦H)¶&³Cââfž8íÇg+ÑTñĢŬ¹S$Ū”‘$ M_s4,b†øä¢Ä0ÍDL`MF ½7h^òl îˆ|¼ýJÅ£2,³¾¹+ žvkZ2T2)ŽúÅ’ÎõÁS€ú6@ ®_´7VÌçÂÒé›ê „#­‚}ŸüYöù˜DÙ‘a‘;Ä=÷ðÝ$ѹ ÒDaE}až^ª¤¶ÇL²d"ªÅÊbe´}×È? t ßàÍ!Pdš%Öæ48T lÚTÃ)$Ýf\–˜ØÏêdZªÀi¾kÌË‘`r`”7(H¨‰ pp â©ÄÏ#LŸ=“„§/ˆ"xבø|ÿ9%Ÿ‡Ä÷ìôzì𢒠"öT¡žÿç,h øó‚®×£þûVIÔo*24¼ à)GY#ªPVG´] `mùjÃÓ‡°ÈÊt_aŸÙÔâªX©ÔAÉÜ4åûŒTÜ »J.ª²_"†Ý@Ì€[¬Þ¿;QÇÞæþ·w×þO™ò¾OÞÓÿ% êhD´;Øün_ì|ÌßÇÐ_Ð_a ¨Pƒ"gj¨*]¡E¢Öûj2±Œ€¬ï54 6Λ¶«(øQ$ÑÍ âËjr$“AQ d‚ †L&dûsÉøC‡É кÿëMÂ@Œ¤‡;L0"…üd¿x~ñ|ÒŸbNRd í‡…Í tÄRæS —ýLïx:çÒØò³ 3 „~W mµ‚s!—¸¢–ýÕpi@]b1¢f9K°Ižºd dLÁ²BJ™áò)x÷w‘"Òdó-˜“Ìžfflîþº.ÏËýT¦“åqûØjnþ:±Ä:éÎ ücÅ(£P3- CE‚Ž@ùlHŠEGüˆ¶ÇY¡ } ‡ÛÓ’]\ß2Q~}Áq.í’5”€?~ad°¨Ü&eÏ›øœçA=p÷VCúõï}]ûÕŒ…>z„ÄFÎ/Í—%K¡øb[p­.nü ý)_\Wõý1’ÿÂà5ó?dèOЈ†9‰°D€Ü C­Ã¥V•U;ý©\-]š~jÙ¼¦„ë: (½ÀBÁS–NP’w¾]:ÈS}öpfÓ)ÑÖ˜ ah^œ,Úmhá’§ãê gªÐœ–ašV;jÞÖ56™†l¢ØLa£— <5›ËòMn¢¨ûÿwN|hÛû?óù¬<¿²êÂ(k.3Îâ æŽifoö»·×@íÓSèQ²X+d´:ìëHeœ~·}ko¤IHƒ]\Ek!;Óö¥,Ô"ü~³Y)`(CRRgw„N0äÒTS—”~,J¥óàñþÅÏÿ½þ¸sŠ/Áßæ:7nÆç1–—¨K—[Úåꎫh{̬+…cd9SQ`L΋awlI  úõpŽùEü?‡øþgÉé <<ÉûWÊ.|‰Ç# àtHĺò©)’Z±¢ÀÁÑË€ölر 9*—:| —D»Éƒ·Ó\QwzüèX4åÑ […E€«(˜XYËî³~W'ÃqPAñIýDÈ"|VKÞ÷D´“çópD‘X”‰ ca 1B"  ÷~‡u²ø‡õú™ÕÄxSŒ~ýÞ†´ã€ëMðæN „Û÷ø€!Ž€uh›GÂ"uÊtu)çŠE–j®„(îJ}C'þIôÛšÈÓÇè•O?"†9µläß?Ä®IÏ’÷/¢—bsDÚaü9ïÒ®•?ö#ÍÒ+9Uæ#O Paĸ~7òãºN| þt ’f~÷WÖùFÿŒ¬$€àø&†À ‘çÊ‘B¨5{xâàO‡áâT\zùéÔìòù¼2îý¥TsMˆµ|­²Ó5¨ê ÈÝ4£”ðXšNÒm–A9Aü‡ÓEGHïbÃÃtSžu3@áÇ·ìófª›úÞºº5æ:L䮉^î‡NtäþçòžhW›¼Ðÿ0#]uØÚu)Ç`feBä7Ípx®3OÌÛŽM×Ò–Pùå3¶|Œ•þÒdGÏi¥ñ˺€¨{€Sxå…óêš™Û *îîH,ѧÞ4XÊ»GÍ „ŠÝçˆâÔÖñ ~肬??ÎÉê-UÎÚŠ%0¦¥ïË…@úƒ9ý°«ŠÊ‰N—'?‡Œû‘êy[ðsý^3§ÞîÓz˜âlÇ÷×§ü›ýpzoÅX鋜ç¤ÉWhùØTõw‡ë©ºâpÃý¹hOCû© ‚­Ç‹ÎàË™ôT9˜çËsÛW»òöî+åc;õ›$‰«ubE7³–’ÚO¬M›:Ç’ºp­ª€1»ªþ4 ÔÇ,ð“[&!™fà›`YÏRm S¡“ˆŠvðTá/£•dù×Ox€ÇþЇ* ˆØ’ƼâÓ 1=¾2ÙÞoyö¼SÇ_òvù.üDp¢ëby‘îÔTpÕ[JÖx1§É*C´ã®ÍElÖÐC«²z×ËYh%<ºFZO~DÕá£ýýHiáuêßly ªxŒöçNÆ}.›q¦Óûçšãm £5rxæþ°2uÚÙ“FZP_°š¸¼ºÒIŸÒ{âßcç#åÍf4ö/“yT˜n3 ¬^Þ[¸uÅöx™Ç»DÜOs!yŸÇF»xëÔô{ô\QŽ2ô˜¹¥jæNîAñÈmú² ÄZ[´ÉQÎéѧ$=ÐGú66ÔìÞ|ÎÜ:,§„;ØS…°ð8uÛž!>Ιœþ[òe‹©Âué;>®ó Óg¾ê‘5éZÖñ!VµßŽû®A´—VÆ£ßú>œÎbÚ¢¦´øÌ–óVχ+O"`×bas5½pi¹,X:º³‚ͤ=ÄgTK6ÉeT¥#=¯÷zãÎR–r.kXjÃ3”ÞzCœõ¿âYݾŸ7h˜û°„èæuÊÊMr™žö¬”mú0WE‡9J ¸ý;,¾´WÛðèJÄÓE€fQò#µjÌЪFú!·}Ð/gû–é¬ç3æÿÝ=ðû‹wãhc„YÞ nÁ£n“&”Ž<²ß‰òSþö¹ÈÑ›$N·R÷ó§ÊÅgc8òÙ6î¿î^s`Ûü ^lw?0Õâ‰þ;8ÚˆIí<ÝUç&Õ³:Íò]‰T‡çy~6«÷=ó«ÈPa5Á|ý}­?¾îñ–¯ZºÎÕ‘±¿#FûêäÜåd:gv‰&­‚i9šIÿVö~Èì1ÿÒ¥¸Zß%å‡è‘ê‡yjBSžB'~¼»òÊÛÕF¼×–4†²©úiØŸf"YÓòNî¨i< 3ˆaÁ×V!NˆE–éomÇÂÝâš©ð¨>=íÃg ÷Öžï=ùþÚå=[f·¨MR'#ÖƒÝÒiŒ\ÇûÒ=@¼uÓUQø“ ©þã/'N-Ín–6mõ–pŒíi&dÑ\Ô¿C}yE"ìXÍãGýôË87üI¯B|e” =¼á­Ø^°J¬/vÑ÷k9 ë0^@¼oÚ(,sRD «˜Ä„š²çãQÎðn* ø¯lùÿ½Œ´Yi¯¼·ÕúÛ kãŒ2cƒõ­os{&x?U··’uÚüWfn7ögƒ­Mî,º´51-­W¯_òN' ®™K9÷ùVMèÏýº@äáØÛ­Mê3a²¬»rZ]nµöyû3ÙØ-îa[q26°ŠB}~¦™VƒŸÒÀl#aÀŒ‘·4×AŽ\ýºÁT>¬•%û~´(Ƨ %N‰«c:û„ÎA±–oj·-»œËÇ×_Q„õtó7wT„lå/v‰²ÛæRòž8wnåIxÇZ.¿á¾ê/¥íJ÷#@fO÷¾È…äÚùH3óî;· ¤a.«¶>.o1 ‰ °ùa¿\ìC$Iþ^}S5´1•°ƒNô¢àdät5tèUZ8wß„Åáö#£/÷þ¿'{ú«3ySŠ‹¬t{ƒÎû~ø^Ê»YKk—m 4ç ˆ 3,Úλ…sãŸsæ¦é'œ·÷ÿåüìø~ÕE$ôœÚ]2Žgëú´­Õ7áï°þHÑ‹9÷øßÞ{Ü@P@yµò¬ßk#ª¡;3sEšÌ—`ÔHP ¿è?Wölš•0ûŠ‘Ö2ýòkêÒË›y‹8ò6|EC¨Î>-Ä©!OäÚ@Ñ6GÝc8£Õ1Æà‡•`…G«Îèm!IvŸð6f©êø/Œ»šºŽ::h8¾ø/gb’•‘xóÄüUx%û\è¹ú~ÒWÔS.rR[2ìˆ;̵!r"TÑ—wÓM:±÷Bü}׈úØÏì‰OõûKí¶Ýmìmæçê«Ä]×wÓf¹°éd[äÙV}^Wyqzï2 rJ½—%*yDñ–×";ZOÃ…>žÈjK%xÑF~4¿ÕÃàSAUÉû©Zx}tý &È-\¼fÑP:Q~ÏÍ|´Ì<Þ•kenoÞa½œ½nýòû›b²u¯aгjûÑoöi$“ä}-cý(߮Ң¹ÎéðõKžúb/¬sqãýZ}ø¼©² ê×ܬ·iæçëáòªM vÞúñm“&M{»²w9Èwþ³²"K:J̧—·õªãZÒÿjmû'دߙòĺÌñI··oé4°Øîþ¹J«$Öä.{N}S~Ëg­)2n1¡QqöVOÙ•ža öšÍj‡ eÔòpoÔ†P¨*Úÿõ€’ÿ„ '´ÇEv9àž±Øh@íT¹»òwúË6úI¦¯Ž*­[M”ý×eYò;_Õ±Az¯™„qïºDá_"n —vD! $j}( j÷nî"×O¥û€3 zÔTö÷¶ÛÞ§É]ˆÑËÖíjZC¥Ž£Ùîùêס´cñAÇa–<î¡Æ¹¼§ÿ!%N¡•]ÿ|ÆXÌþ6S/1^¯sŽÈ!¿#Z îP¯LÓ.Yõ¹¿(㎬¯©ññüzzPºwj&|ÕïÍþ£k¼ÖçU×~YÚÿéÖD2¡Cu'DÇêIOãìù#¶„)j0:s•N”FKHV]i»IîÅûZÒäK­Çµ`åmJ ±š¨™Æb€‹¿ãƒ›Lÿ]gM'~Û}C¼Hº€æqPžÑ̹2<3J‹Jr÷¨*žO$) ïöO—ahJNIJ¿/úQMÁSŠ=W9ûÜÂéÔ'ËäÑÀƒÎ:ÿO³T÷Q8ý>Ûc*eGÓÞïÏWÎms]ü xÙ©±Ë]3õtºãìæb»[T.ÊÔsºÎ×™aðÚ¿?üü´¹½-¯õ;Æ“¥ÈµÒK~ëK<Ñø1ú_é2žŸÑrû¼OgMo°› ¶s#Q´ÌHk‹_”özr,xI‘~tÇ…¥ÌïZCKîûëÐêþ­¥0êX÷úÏÌ>d¿>aoF.m×Ò-{k•GÑ}\‰Fà9ùŠfä$xµ¶ ¦¦ÍºÔXu 'uòNOxñÌ=5­Çu»@ò5¹.Jiпeáyî,B{Í×YQ4˜„Ú#ÞdðÅ£¥ÛÛ‘oöPjL–6Y|im•¿1áyÁÿþZ®é µÊeHIpyáéµùšø Øò{~ËcÓPm6TYÎKZ¦õÇü§Ï'ìûþCQ:÷-±ºá®DëêÁ~|…ëpØ»j½›'ËGO²š™ü,rÏÚ¯3ÔÏ¿ Š@Þ`™îΕՑg±¤çv/¦¢¼Gëò¶œ«ý¯#š‹Ø:þvâûFÎ èrúß­ó/üo-'-Çà]ŽEÔEv׹ƊšG+y¸á!>|ðúÜ›<[Óü¨žK9^ç7{ßpãi¥-ù*µÕ,bäòd“TÕ÷YÈ/Ù8´ÃÈþVmñÕWãÐw0¹qÉ—]€öÂtº{¦®g` t,æ»QÝ]´?†÷#ßBB63ºlî¯Ý?¸s»£0yµ¸]ÿ‘õÙýèÐõO>_µo¾r¹˜ê'Ï%]÷áɰÌöÝÜÏ\Ów˜W³FŠ5èÝþ_»éŸ̧.2ÈË ŽO×–Nò^ý)=mL¯EeÄØ¶% 5Ûì¾'íÄÛ_"Ð*{ç¡OQêv=}0íeu}þ%i-R  ÇŒ²¬‹)ÑÝoÙŒŽM˜Hµà¿ìŸÿ·M½ãgBÆå õ½Gði™nÝ¿a§”È9Ã¥îLB ɟÈV6Pµ¢ôž'“”¥ÔòIYi˜  õðØÚ~;|ž“a§QjðD×S£ï*„¡SIMõ?c-΄Ôíoޝ–ôè>ç¼J«cùäÖ¢db17&Æ$x”¸³løQ¼›¨,î?:?âÇÐX×Rá@ÅŠ¿×ÏÊr¥=HÑækå…³×G^£šdß7adVfå¹ÿzêý%?’˜ÒÒÌÖ[ëN›ç“ÍcR[á~š‚³,ýÃ]Á‹ ~òõ7­ö±ãË3ÂçÞ5÷:ŠUt3y<²q©úI«nzÔˆ_b£™¼ñ/ä~W8´SèÚ±A³ùQ_ùø%+¯Hül³'ì92ö7Ë鳩Ù>>ZýÌ >ü{Ýî]»YðùïAq%GCÑ똢҅õÅTR|5–u|ž¹õ¹÷¿îßßiWblÜúãT+æþùòß ˆ¾|Í~±½K“H¯ØÝ2*ÓñÏϸ«{dTr}‡Ã~ºd·œýí>­Nå3Å(~Ù_¬•ßdôfJõÒ&Êö>õlüálÖg^¯¾ ˆŸ¨_4øÛ _Söµ±žÜ£_)}ǾrgD§! ¨å¹U]UUmüóõ¾ïÊ ÌÄYÔcÄX¢°>²Z)(žµ”Ø<ú;N¥ã¥oNðGb*#qˆ”9âX,™DB yÊ#þ“qÿê®+Šâ¸­zo‘ûz/7Ür¶”Óçrß*Á†á¸n†×è—üܵxØxÙóÿ]8SP86p"$ö÷»{#ÎÛvóH¨Dj#Q¡ Mþ+ßg ÇÑ·‹×ïÈZÉNr·_y“’ë±+fuy½S7dß_AÅiû{ÔÕyäxÕäB\í7#<à Ök™í-|#¸Ì‰¾ìÒT¦ÅÚjÓ ð}A¾µ¥ë»*Æ Á#—ú~lÚµñ­¥£¯|g~0¨QÀÏX@oq×ó*jD˜­¿ ‹C´§ú`ED¸{°ë«ÚÞ—7óçOË[È"Û6:OºtÖ^ÃdÓŽü«š$½^Qï^Öþé¿%å…$‹NþwºŸ»7ááÎsªMÔÛ©»ýºwîöͬüGv¤‹4×Klœ2W/›ôÃb½¡”ž_;bгvâ'âèëÚïà¥äžÛÖ+*w;¯Ž±‘åd¥¤º‚ºã‰Y'÷Í`8ÞܣߡMålÙ(ù~}ò­½-ÚÁŠ˜{sÓr^ßçZ”9Â_%¬ã§Í9ç›Z¿ûèд[ßmÌf˧²‰«g€û¦Ý÷m¹U?Ì{#ÌË:{vï{¯ƒ¥k£kͰf¿œºÁ„3nä±Îw¿ŒRðhónÿŠ¿±žù½““÷oÔ¸³þÇû/WâQu[¾ñKªØµ~,¼“jÊPØÈºO”f™ÞŸG‰õµ´foÖlâIü¼°‡:=ÛÕÕŠxâø<Ùžl#ª,tÏFåèÝ}иªÄ¿Iì¦sškef´Íÿ_‚º„£ÀØêYuçLùÞ›g¸CL‰ë5KýãçûÔFI¦™SªÞ×GlñšR*Ñ‘¹Mki’Š•ƒÖI8ÅXšaÓ«ÓÀ<‡rõpWwçÖÝüLL”˜<;·¤7-Ò“ŸÏσ©7`ˆ­:ø~¤Ýk´£û&É«æ-¦‡¿;ë%Ú‡Âܯlöæ%©¹oöŸ%Ne©w¤¶íÞWæ–[<ž{&Ür–OS¶jŸ´å1£Tþ7¨®?³€jxÖjPì€Ú²Ÿì:D{1ÿ—2½V^Ÿófé!†ƒŽw$’C=oË¢1úuµ·×G¯5·2t£Bú¸Ä^ñ§<%èìü4ÀW=¹˜fî3¯.’VšNiíSkHÚó÷›ËÌ`Òn«£ö´§ræ¸^`÷ÈÌÍv ¦jXìÐÌ(C,î;.eîøÎLm~Ÿg)Úo7…ÚN„ý›9åjÜâ)épÐÎmäü]t ª>«K\Pùž}RE®ç{[G3Ðf9_üw@Õç‚árI¦‘ŒaE‘`™ÅKÙ§2'éCäaiŒ¨*ð<•PþßÓò™äTŒ[VÆï$æüe~ʸWàÂ8Ðaˆ¶³àÖm’ðÿÊEÕ:‘ÓlÖùvÖ3Y³~³óà¥v…¿Æ¦Õjúî+æOTÒÔr+ûsZIÝÿ‘¸L0êdžFð¶:Ï¿ÕÔ¾üBµ7ùsŒè›×¥Ø\½³—Æ&rîÐÏúäÝ|ëcÆžÛ}5К0ê„ÂÖŸ*öIâ?’ ¼o†_î]Æó€÷bXæ²kë¨Kýgë®sî¸u1Ï+Ø|Uf^ÿ§¼ÚF‰üv¨Ä«3ú³ç!{“¢ßSƒ;¨SĆ ®n¯‹OiÌßVÌTõÿ’¬QYçËÔ>ã%3§ò^+z„VóXÃ>®a—‘¥+èûµ7kFÞ!aXK÷¹U•?–¸÷uIöOÁý=Ì~ý ÝÈWt§\N’©ZžÂ2‡&-;®ú*¶ŸO)3cŠí¬_ûU¯^ª«‹!¶×¿Æ1·I‰ñö8èÝä§:L_ñ´~jç±ôÒ#‰ïúñ%ãyþ^Åù8X-„^Úò7î¢é e’Ñœ:7•GVqÇÃÁw¤üP¦6üƒsPíŠ÷¬ˆNJØúƒY°¾½º¹SÙo… tþÛ'’÷A¨ãÓ¡·þ(fcÍ-ì\ïÅFU17€±Kœ¯•BÄd …I¯ìòàö½<“ä–LcÔ¢÷3*æ¿§jÊ4¨4#ƒ^¿“ã­S¥Ê÷×x«Ù³™C”®4M…Ê77ØÒZ3U¬‘üSëP–¨´‡¾€†‡­«LpÚûéŸmÙŸÞâòºæÝ‰×Ļȯ ÇGÑí0êr¥0oìÐðîìv=}þeÓ—ÈP£ Š„‚gøGø?*S.ž‰±Ha¡©/Ó uoKpª…å¢HmkòRÄ ;ì>ƒÕ±‚@šM?T?Çû ( oè|Nwç{Éy¼Þo7Šù¾s_câ²å!sʅۺР'ê:¿ÿ‹¹"œ(H" ¦n€singular-4.0.3+ds/doc/singular.idx000066400000000000000000004354771266270727000171000ustar00rootroot00000000000000! sing_36.htm#IDX102 != sing_36.htm#IDX96 != sing_95.htm#SEC134 " sing_36.htm#IDX105 # sing_36.htm#IDX119 $ sing_36.htm#IDX120 % sing_36.htm#IDX92 % sing_76.htm#SEC115 % sing_93.htm#SEC132 % sing_105.htm#SEC144 && sing_36.htm#IDX103 && sing_96.htm#SEC135 ( sing_36.htm#IDX81 ) sing_36.htm#IDX82 * bigintmat operations sing_36.htm#IDX90 * sing_76.htm#SEC115 * sing_82.htm#SEC121 * sing_88.htm#SEC127 * sing_93.htm#SEC132 * sing_101.htm#SEC140 * sing_105.htm#SEC144 ** sing_36.htm#IDX94 + bigintmat operations sing_36.htm#IDX86 + sing_76.htm#SEC115 + sing_82.htm#SEC121 + sing_88.htm#SEC127 + sing_93.htm#SEC132 + sing_101.htm#SEC140 + sing_105.htm#SEC144 ++ sing_36.htm#IDX87 - bigintmat operations sing_36.htm#IDX88 - sing_76.htm#SEC115 - sing_82.htm#SEC121 - sing_93.htm#SEC132 - sing_101.htm#SEC140 - sing_105.htm#SEC144 -- sing_36.htm#IDX89 --MPhost sing_19.htm#IDX67 --MPport sing_19.htm#IDX66 --allow-net sing_19.htm#IDX39 --batch sing_19.htm#IDX65 --browser sing_19.htm#IDX43 --echo sing_19.htm#IDX35 --emacs sing_19.htm#IDX68 --emacs-dir sing_19.htm#IDX69 --emacs-load sing_19.htm#IDX70 --execute sing_19.htm#IDX57 --help sing_19.htm#IDX37 --min-time sing_19.htm#IDX62 --no-out sing_19.htm#IDX49 --no-rc sing_19.htm#IDX45 --no-shell sing_19.htm#IDX50 --no-stdlib sing_19.htm#IDX47 --no-tty sing_19.htm#IDX51 --no-warn sing_19.htm#IDX48 --quiet sing_19.htm#IDX53 --random sing_19.htm#IDX61 --sdb sing_19.htm#IDX32 --singular sing_19.htm#IDX71 --ticks-per-sec sing_19.htm#IDX63 --user-option sing_19.htm#IDX59 --verbose sing_19.htm#IDX54 -> sing_154.htm#SEC193 -MPhost Command line options -MPport Command line options -allow-net Command line options -b Command line options sing_19.htm#IDX64 -batch Command line options -browser Command line options -c Command line options sing_19.htm#IDX56 -d Command line options sing_19.htm#IDX31 -e Command line options sing_19.htm#IDX34 -echo Command line options -emacs Command line options -emacs-dir Command line options -emacs-load Command line options -execute Command line options -h Command line options sing_19.htm#IDX36 -help Command line options -min-time Command line options -no-out Command line options -no-rc Command line options -no-shell Command line options -no-stdlib Command line options -no-tty Command line options -no-warn Command line options -q Command line options sing_19.htm#IDX52 -quiet Command line options -r Command line options sing_19.htm#IDX60 -random Command line options -sdb Command line options -singular Command line options -ticks-per-sec Command line options -u Command line options sing_19.htm#IDX58 -user-option Command line options -v Command line options sing_19.htm#IDX55 -verbose Command line options .. sing_36.htm#IDX114 .singularrc file sing_20.htm#IDX73 .singularrc file, no loading Command line options sing_19.htm#IDX46 / sing_36.htm#IDX91 / sing_105.htm#SEC144 // sing_36.htm#IDX108 // sing_36.htm#IDX110 // sing_36.htm#IDX111 : sing_36.htm#IDX115 : sing_105.htm#SEC144 :: sing_36.htm#IDX116 :: sing_144.htm#SEC183 ; sing_36.htm#IDX112 < sing_36.htm#IDX101 < sing_298.htm#SEC337 <= sing_36.htm#IDX100 <= sing_95.htm#SEC134 <> sing_36.htm#IDX97 <> sing_95.htm#SEC134 = sing_36.htm#IDX78 == sing_36.htm#IDX95 == sing_95.htm#SEC134 > sing_36.htm#IDX99 >= sing_36.htm#IDX98 >= sing_95.htm#SEC134 ? sing_36.htm#IDX107 ? sing_308.htm#IDX144 AG codes sing_887.htm#SEC938 AGcode_L sing_1826.htm#SEC1901 AGcode_Omega sing_1827.htm#SEC1902 ASCII sing_936.htm#SEC1011 ASCII links sing_112.htm#SEC151 ASSUME sing_64.htm#SEC100 A_L sing_1525.htm#SEC1600 A_Z sing_935.htm#SEC1010 Access to elements of a user defined type Access to elements of a user defined type sing_180.htm#SEC219 Adj_div sing_1821.htm#SEC1896 Adjoint ideal sing_1402.htm#IDX535 Alexander polynomial sing_1496.htm#IDX559 Algebraic Geometry codes sing_1820.htm#IDX707 Algebraic dependence Algebraic dependence sing_868.htm#SEC919 Algebraic geometry sing_1377.htm#SEC1452 AltVarEnd sing_781.htm#SEC832 AltVarStart sing_780.htm#SEC831 Ann sing_1316.htm#SEC1391 Appel function sing_611.htm#IDX340 Appel hypergeometric function sing_611.htm#IDX341 Applications sing_885.htm#SEC936 ArnoldAction sing_1618.htm#SEC1693 Assignments for user defined types Assignments for user defined types sing_182.htm#SEC221 Atkin sing_1909.htm#SEC1984 Authors sing_1.htm#IDX16 BINresol sing_1415.htm#SEC1490 Background sing_3.htm#SEC5 Basic programming sing_843.htm#SEC894 Basic programming sing_843.htm#SEC894 BelongSemig sing_2225.htm#SEC2300 Bern sing_2203.htm#SEC2278 Bernstein operator sing_588.htm#IDX322 Bernstein-Sato polynomial sing_553.htm#IDX303 Bernstein-Sato polynomial sing_588.htm#IDX319 Bernstein-Sato polynomial sing_1559.htm#IDX590 Bernstein-Sato polynomial sing_1563.htm#IDX607 Bernstein-Sato polynomial for variety sing_644.htm#IDX344 Betti number Syzygies and resolutions sing_902.htm#SEC958 Bigatti-La Scala-Robbiano algorithm Bigatti and La Scala and Robbiano sing_912.htm#SEC968 BlowingUp sing_1538.htm#SEC1613 Blowupcenter sing_1418.htm#SEC1493 BorelCheck sing_1493.htm#SEC1568 Branches of space curve singularities Branches of space curve singularities sing_876.htm#SEC927 Briancon-Maisonobe algorithm sing_588.htm#IDX328 Brieskorn lattice sing_1559.htm#IDX586 Brieskorn lattice sing_1560.htm#IDX597 Brieskorn lattice sing_1561.htm#IDX600 Brieskorn lattice sing_1562.htm#IDX603 Brieskorn lattice sing_1563.htm#IDX606 Brieskorn lattice sing_1564.htm#IDX610 Brieskorn lattice sing_1565.htm#IDX614 Brieskorn lattice sing_1566.htm#IDX620 Brieskorn lattice sing_1567.htm#IDX628 Brieskorn lattice sing_1568.htm#IDX634 Brieskorn lattice sing_1569.htm#IDX642 Brieskorn lattice sing_1570.htm#IDX652 Brieskorn lattice sing_1581.htm#IDX658 Brieskorn lattice sing_1583.htm#IDX669 Brieskorn lattice sing_1611.htm#IDX696 Brill-Noether algorithm sing_1820.htm#IDX708 BrillNoether sing_1823.htm#SEC1898 Buchberger algorithm for toric ideals Buchberger algorithm sing_913.htm#SEC969 Budur-Mustata-Saito approach sing_644.htm#IDX348 Building Singular sing_2456.htm#SEC2543 C programming language Major differences to the C programming language sing_457.htm#SEC496 C, module ordering sing_895.htm#IDX402 CGS, disjoint, reduced, Comprehensive Groebner System cgsdr sing_957.htm#IDX412 CM_regularity sing_1480.htm#SEC1555 33865 CMtype sing_1649.htm#SEC1724 CRHT-ideal sing_919.htm#SEC982 Castelnuovo-Mumford regularity sing_1480.htm#IDX551 Category string sing_51.htm#SEC87 CenCharDec sing_738.htm#SEC789 Center sing_1457.htm#SEC1532 CenterBO sing_1464.htm#SEC1539 CentralQuot sing_736.htm#SEC787 CentralSaturation sing_737.htm#SEC788 Change of rings sing_9.htm#SEC15 Characteristic sets sing_903.htm#SEC959 CharacteristicExponents CharacteristicExponents sing_1544.htm#SEC1619 ChernRootsDual sing_2184.htm#SEC2259 ChernRootsHom sing_2191.htm#SEC2266 ChernRootsProd sing_2186.htm#SEC2261 ChernRootsSum sing_2182.htm#SEC2257 ChernRootsSymm sing_2193.htm#SEC2268 ChernRootsWedge sing_2194.htm#SEC2269 Chevalley-Rosenlicht theorem sing_1396.htm#IDX520 Chevalley-Rosenlicht theorem sing_1397.htm#IDX523 Classification of hypersurface singularities Classification of hypersurface singularities sing_877.htm#SEC928 Classification of singularities sing_2393.htm#IDX891 Code Codes and the decoding problem sing_918.htm#SEC975 Codes and the decoding problem Codes and the decoding problem sing_918.htm#SEC974 Coding theory sing_1819.htm#SEC1894 Coefficient rings Notes for Singular users sing_2454.htm#SEC2535 Command line options Command line options sing_19.htm#SEC26 Commands Functions and system variables sing_258.htm#SEC297 Commands for user defined types Commands for user defined types sing_181.htm#SEC220 Commutative Algebra sing_856.htm#SEC907 Commutative algebra sing_1135.htm#SEC1210 CompDecomp sing_550.htm#SEC601 CompInt sing_2227.htm#SEC2302 CompleteHomog sing_2172.htm#SEC2247 ComplexValue sing_2267.htm#SEC2342 Computing Groebner and Standard Bases Computing Groebner and Standard Bases sing_852.htm#SEC903 ConsLevels sing_964.htm#SEC1039 ContactMatrix sing_1546.htm#SEC1621 Conti-Traverso algorithm sing_908.htm#SEC964 Contributors sing_1.htm#IDX15 Control structures sing_425.htm#SEC464 Control theory System and Control theory sing_1853.htm#SEC1928 Cooper philosophy sing_919.htm#SEC980 Cornacchia sing_1899.htm#SEC1974 CornacchiaModified sing_1900.htm#SEC1975 Crep sing_960.htm#SEC1035 Critical points sing_871.htm#SEC922 CurveParam sing_1540.htm#SEC1615 CurveRes sing_1539.htm#SEC1614 Curves sing_1402.htm#IDX532 Customization of the Emacs interface Customization of the Emacs interface sing_25.htm#SEC35 Cyclic code sing_1834.htm#IDX715 Cyclic roots sing_849.htm#SEC900 D-integration sing_611.htm#IDX337 D-localization sing_611.htm#IDX333 D-localization sing_815.htm#IDX371 D-module purityfiltration_lib sing_553.htm#IDX301 D-module sing_588.htm#IDX316 D-module sing_611.htm#IDX330 D-module sing_644.htm#IDX342 D-module sing_793.htm#IDX356 D-module sing_815.htm#IDX368 D-module structure sing_588.htm#IDX317 D-module structure sing_644.htm#IDX343 D-restriction sing_611.htm#IDX335 DBM links sing_117.htm#SEC156 DISPLAY environment variable The online help system sing_16.htm#IDX28 DLoc sing_614.htm#SEC665 DLoc0 sing_616.htm#SEC667 Data types sing_72.htm#SEC111 Data types (plural) sing_470.htm#IDX287 Debugging tools sing_63.htm#SEC99 Decker, Wolfram sing_1.htm#IDX17 Declaration of objects of a user defined type Declaration of objects of a user defined type sing_179.htm#SEC218 Decoding sing_1834.htm#IDX717 Decoding codes with Groebner bases Decoding codes with Groebner bases sing_917.htm#SEC973 Decoding method based on quadratic equations Decoding method based on quadratic equations sing_922.htm#SEC991 Definition of a user defined type Definition of a user defined type sing_178.htm#SEC217 Deformations sing_874.htm#SEC925 Deformations, T1 and T2 sing_873.htm#SEC924 Degree sing_1381.htm#SEC1456 Delta sing_1465.htm#SEC1540 DeltaList sing_1466.htm#SEC1541 Demo mode sing_24.htm#SEC34 Depth sing_863.htm#SEC914 Determinacy sing_2396.htm#IDX895 Di Biase-Urbanke algorithm Di Biase and Urbanke sing_911.htm#SEC967 Distributed computing sing_980.htm#IDX426 Dlocalization sing_816.htm#SEC867 Documentation Tool sing_60.htm#SEC96 Dp, global ordering sing_893.htm#IDX385 Ds, local ordering sing_894.htm#IDX395 DsingularLocus sing_820.htm#SEC871 Dynamic loading sing_71.htm#SEC110 Dynamic modules sing_851.htm#SEC902 ECPP sing_1943.htm#SEC2018 ECoef sing_1424.htm#SEC1499 EOrdlist sing_1422.htm#SEC1497 ERROR sing_287.htm#SEC326 Edatalist sing_1421.htm#SEC1496 Edelman-Reiner sing_2150.htm#IDX826 Editing SINGULAR input files with Emacs Editing SINGULAR input files with Emacs sing_26.htm#SEC36 Editing input sing_18.htm#SEC25 Elimination sing_859.htm#SEC910 Emacs Emacs user interface sing_21.htm#SEC28 Emacs, Singular demo mode sing_24.htm#SEC34 Emacs, a quick guide A quick guide to Emacs sing_22.htm#SEC29 Emacs, customization of Singular mode Customization of the Emacs interface sing_25.htm#SEC35 Emacs, editing Singular input files Editing SINGULAR input files with Emacs sing_26.htm#SEC36 Emacs, important commands Top 20 Emacs commands sing_27.htm#SEC37 Emacs, overview A quick guide to Emacs sing_22.htm#SEC29 Emacs, running Singular under Running SINGULAR under Emacs sing_23.htm#SEC30 Emacs, user interface Emacs user interface sing_21.htm#SEC28 Emaxcont sing_1426.htm#SEC1501 Equal sing_1380.htm#SEC1455 Eresol sing_1416.htm#SEC1491 Evaluation of logical expressions Evaluation of logical expressions sing_459.htm#SEC498 Examples sing_841.htm#SEC892 Examples of ring declarations Examples of ring declarations sing_29.htm#SEC39 Exp for matrices sing_1398.htm#IDX524 Experimental libraries Experimental libraries sing_2121.htm#SEC2196 Ext sing_1195.htm#SEC1270 Ext, computation of sing_862.htm#SEC913 Ext_R sing_1194.htm#SEC1269 Exterior sing_767.htm#SEC818 Extra weight vector sing_898.htm#SEC949 Factorization sing_864.htm#SEC915 Feynman graph sing_1171.htm#IDX461 Finite fields sing_858.htm#SEC909 First steps sing_6.htm#SEC12 Fitzgerald-Lax method Fitzgerald-Lax method sing_921.htm#SEC988 Flow control sing_40.htm#SEC69 Formal Checker sing_59.htm#SEC95 Formatting output sing_848.htm#SEC899 Free resolution sing_860.htm#SEC911 Free resolution, graded Handling graded modules sing_861.htm#SEC912 Functions sing_259.htm#SEC298 Future benefits of Singular 4 Notes for Singular users sing_2454.htm#SEC2541 G-algebra sing_534.htm#SEC573 G-algebra sing_534.htm#SEC575 G-algebra, setup sing_534.htm#SEC577 GBWeight sing_617.htm#SEC668 GBsolve sing_1733.htm#SEC1808 GIT sing_2279.htm#IDX877 GKZsystem sing_734.htm#SEC785 GKdim sing_707.htm#SEC758 GMP sing_1.htm#IDX3 GND.lib sing_2286.htm#SEC2361 GND_lib sing_2286.htm#SEC2361 GTZmod sing_1243.htm#SEC1318 GTZopt sing_1250.htm#SEC1325 G_a -Invariants sing_880.htm#SEC931 Gamma sing_1431.htm#SEC1506 Gauss-Manin connection Gauss-Manin connection sing_904.htm#SEC960 Gauss-Manin connection sing_1611.htm#IDX695 Gauss-Manin connection sing_1658.htm#IDX698 Gauss-Manin system sing_1559.htm#IDX585 Gauss-Manin system sing_1560.htm#IDX596 Gauss-Manin system sing_1561.htm#IDX599 Gauss-Manin system sing_1562.htm#IDX602 Gauss-Manin system sing_1563.htm#IDX605 Gauss-Manin system sing_1564.htm#IDX609 Gauss-Manin system sing_1565.htm#IDX613 Gauss-Manin system sing_1566.htm#IDX619 Gauss-Manin system sing_1567.htm#IDX627 Gauss-Manin system sing_1568.htm#IDX633 Gauss-Manin system sing_1569.htm#IDX641 Gauss-Manin system sing_1570.htm#IDX651 Gauss-Manin system sing_1581.htm#IDX657 Gauss-Manin system sing_1583.htm#IDX668 General command syntax General command syntax sing_35.htm#SEC58 General concepts sing_12.htm#SEC18 General purpose sing_929.htm#SEC1004 General syntax of a ring declaration General syntax of a ring declaration sing_30.htm#SEC40 Generalized Hilbert Syzygy Theorem Syzygies and resolutions (plural) sing_536.htm#SEC585 Generalized Newton identities Generalized Newton identities sing_920.htm#SEC985 Geometric genus sing_1402.htm#IDX536 German Umlaute sing_455.htm#IDX274 Getting started sing_5.htm#SEC11 Global orderings sing_893.htm#SEC944 Graded commutative algebras Graded commutative algebras (SCA) sing_538.htm#SEC589 Greuel, Gert-Martin sing_1.htm#IDX18 Groebner Bases Computing Groebner and Standard Bases sing_852.htm#SEC903 Groebner bases in G-algebras Groebner bases in G-algebras sing_535.htm#SEC578 Groebner bases in free associative algebras Groebner bases for two-sided ideals in free associative algebras sing_541.htm#SEC592 Groebner bases, decodeGB sing_1834.htm#IDX719 Groebner bases, slim sing_855.htm#SEC906 Groebner basis conversion Groebner basis conversion sing_854.htm#SEC905 Groebner cover, parametric ideal, canonical, discussion of extend sing_956.htm#IDX411 Groebner cover, parametric ideal, canonical, discussion of sing_963.htm#IDX415 Groebner fan sing_2038.htm#IDX736 Groebner walk sing_1186.htm#IDX480 Groebner walk sing_1188.htm#IDX482 Groebner walk sing_2386.htm#IDX888 Groebner walk sing_2387.htm#IDX889 Gromov-Witten invariants sing_1171.htm#IDX458 Gromov-Witten invariants sing_1177.htm#IDX467 Gromov-Witten invariants sing_1178.htm#IDX471 Gweights sing_761.htm#SEC812 H2basis sing_1616.htm#SEC1691 Hamburger-Noether expansion sing_1496.htm#IDX555 Hamburger-Noether expansion sing_1584.htm#IDX677 Hamburger-Noether expansions sing_1821.htm#IDX709 Handling graded modules Handling graded modules sing_861.htm#SEC912 Hcode sing_1518.htm#SEC1593 Help string sing_45.htm#SEC81 Hensel sing_292.htm#SEC331 Hilbert function sing_404.htm#IDX184 Hilbert function sing_901.htm#SEC954 Hilbert series sing_901.htm#SEC954 Hilbert-driven GB algorithm Groebner basis conversion sing_854.htm#SEC905 HilbertClassPoly sing_1906.htm#SEC1981 HilbertSeries sing_1711.htm#SEC1786 HilbertWeights sing_1712.htm#SEC1787 Hom sing_1198.htm#SEC1273 HomJJ sing_1273.htm#SEC1348 Hosten-Sturmfels algorithm Hosten and Sturmfels sing_910.htm#SEC966 How to enter and exit How to enter and exit sing_14.htm#SEC20 How to use this manual How to use this manual sing_4.htm#SEC6 Hurwitz numbers sing_1177.htm#IDX470 Hurwitz numbers sing_1178.htm#IDX474 Hypersurface singularities, classification of Classification of hypersurface singularities sing_877.htm#SEC928 IN sing_329.htm#IDX145 Ideal membership sing_900.htm#IDX407 Identifiers, syntax of sing_37.htm#SEC64 ImageGroup sing_1714.htm#SEC1789 ImageVariety sing_1713.htm#SEC1788 Imap, option sing_364.htm#IDX171 Implemented algorithms Implemented algorithms sing_33.htm#SEC46 Incl sing_1379.htm#SEC1454 Index sing_2462.htm#SEC2549 Info string sing_52.htm#SEC88 InterDiv sing_1447.htm#SEC1522 Interactive use sing_13.htm#SEC19 Interrupting SINGULAR Interrupting SINGULAR sing_17.htm#SEC24 IntersectWithSub sing_739.htm#SEC790 IntersectionMatrix sing_1545.htm#SEC1620 Introduction sing_2.htm#SEC4 Invariant Theory sing_879.htm#SEC930 Invariant theory sing_1663.htm#SEC1738 InvariantQ sing_1716.htm#SEC1791 InvariantRing sing_1715.htm#SEC1790 Invariants of a finite group Invariants of a finite group sing_881.htm#SEC932 Invariants of plane curve singularities Invariants of plane curve singularities sing_875.htm#SEC926 IsSCA sing_782.htm#SEC833 J-marked schemes sing_1487.htm#IDX553 J-marked schemes, Borel ideals sing_1492.htm#IDX554 JMBTest.lib sing_1487.htm#SEC1562 JMBTest_lib sing_1487.htm#SEC1562 JMSConst.lib sing_1492.htm#SEC1567 JMSConst_lib sing_1492.htm#SEC1567 JMarkedScheme sing_1494.htm#SEC1569 Jacobi sing_1916.htm#SEC1991 Jacobson form sing_1871.htm#IDX720 Jacobson normal form sing_1871.htm#IDX721 JuReTopDim sing_1389.htm#SEC1464 JuReZeroDim sing_1390.htm#SEC1465 KScoef sing_1609.htm#SEC1684 KSconvert sing_1607.htm#SEC1682 KSker sing_1606.htm#SEC1681 KSlinear sing_1608.htm#SEC1683 KSpencerKernel sing_1656.htm#SEC1731 KeneshlouMatrixPresentation KeneshlouMatrixPresentation sing_2305.htm#SEC2380 Kernel of module homomorphisms Kernel of module homomorphisms sing_867.htm#SEC918 KoszulHomology sing_1207.htm#SEC1282 LETTERPLACE sing_539.htm#SEC590 LIB sing_333.htm#SEC372 LIB commands sing_53.htm#SEC89 LIBs sing_925.htm#SEC1000 LLL sing_406.htm#IDX214 LOT algorithm sing_588.htm#IDX329 LU-decomposition of a matrix of numbers sing_338.htm#SEC377 Laurent series sing_1175.htm#IDX466 Left and two-sided Groebner bases Left and two-sided Groebner bases sing_883.htm#SEC934 Left ideal membership Groebner bases in G-algebras sing_535.htm#SEC581 Left normal form Groebner bases in G-algebras sing_535.htm#SEC580 LengthSym sing_792.htm#SEC843 LengthSymElement sing_791.htm#SEC842 Letterplace sing_539.htm#SEC590 Lexicographic Groebner bases, computation of Groebner basis conversion sing_854.htm#SEC905 Libraries Writing procedures and libraries sing_48.htm#SEC84 Libraries sing_844.htm#SEC895 Libraries in the SINGULAR Documentation Libraries in the SINGULAR Documentation sing_49.htm#SEC85 Library versioning Notes for Singular users sing_2454.htm#SEC2539 Lie algebra sing_1397.htm#IDX521 Lie group sing_1400.htm#IDX526 Lie group sing_1401.htm#IDX529 Limitations sing_455.htm#SEC494 Linear algebra sing_1075.htm#SEC1150 Linear code sing_1834.htm#IDX716 LinearActionQ sing_1718.htm#SEC1793 LinearCombinationQ sing_1719.htm#SEC1794 LinearizeAction sing_1717.htm#SEC1792 Loading a library sing_62.htm#SEC98 Local orderings sing_894.htm#SEC945 Log for matrices sing_1399.htm#IDX525 Long coefficients sing_846.htm#SEC897 M, ordering sing_896.htm#SEC947 MVComplex sing_2399.htm#SEC2474 Macintosh installation Macintosh installation instructions sing_2461.htm#SEC2548 Mathematical background Mathematical background sing_899.htm#SEC950 Mathematical background (plural) Mathematical background (plural) sing_533.htm#SEC572 Matrix orderings sing_896.htm#SEC947 Max sing_1625.htm#SEC1700 Maximus sing_1489.htm#SEC1564 Maxord sing_1430.htm#SEC1505 MillerRabin sing_1926.htm#SEC2001 Milnor number Milnor and Tjurina number sing_870.htm#SEC921 Milnor number sing_2395.htm#IDX894 Min sing_1626.htm#SEC1701 MinMult sing_2226.htm#SEC2301 MinimalDecomposition MinimalDecomposition sing_1720.htm#SEC1795 Minimum distance sing_1834.htm#IDX718 Minimus sing_1488.htm#SEC1563 Miscellaneous libraries Miscellaneous libraries sing_2096.htm#SEC2171 ModEqn sing_1619.htm#SEC1694 Modular techniques sing_980.htm#IDX423 Module orderings sing_895.htm#SEC946 Modules and and their annihilator Modules and their annihilator sing_10.htm#SEC16 Monodromy sing_1611.htm#IDX693 Monomial orderings sing_890.htm#SEC941 Monomial orderings, Term orderings sing_31.htm#SEC43 Morse lemma sing_2394.htm#IDX892 MultiplicitySequence MultiplicitySequence sing_1543.htm#SEC1618 NF sing_383.htm#SEC422 NF sing_525.htm#SEC564 NFMora sing_1992.htm#SEC2067 NPos sing_1263.htm#SEC1338 NPos_test sing_1261.htm#SEC1336 NSplaces sing_1822.htm#SEC1897 NTL sing_1.htm#IDX4 Names sing_37.htm#SEC64 Names in procedures sing_46.htm#SEC82 Names, indexed sing_37.htm#SEC64 New libraries depending on Singular 4 Notes for Singular users sing_2454.htm#SEC2537 New orderings for modules Notes for Singular users sing_2454.htm#SEC2540 Newton non-degenerate sing_1598.htm#IDX691 Newton polygon sing_1597.htm#IDX690 Newton polygon sing_1598.htm#IDX692 Newton polytope sing_2038.htm#IDX735 NoetherPosition sing_1257.htm#SEC1332 Non-commutative LIBs Non-commutative libraries sing_545.htm#SEC596 Non-commutative algebra Non-commutative algebra sing_882.htm#SEC933 Non-commutative algebra sing_916.htm#SEC972 Non-commutative libraries Non-commutative libraries sing_545.htm#SEC596 Non-commutative subsystem Non-commutative subsystem sing_468.htm#SEC507 Nonhyp sing_1419.htm#SEC1494 Normal form sing_900.htm#IDX406 Normalization sing_866.htm#SEC917 Notes for Singular users Notes for Singular users sing_2454.htm#SEC2534 Notes for developers Notes for developers sing_2455.htm#SEC2542 NullCone sing_1721.htm#SEC1796 NumIrrDecom sing_1393.htm#SEC1468 NumLocalDim sing_1382.htm#SEC1457 NumPrimDecom sing_1395.htm#SEC1470 Oaku-Takayama algorithm sing_588.htm#IDX327 Objects sing_38.htm#SEC65 Orlik-Solomon sing_2151.htm#IDX827 Output, formatting of sing_848.htm#SEC899 PBW sing_567.htm#IDX315 PBW basis sing_534.htm#SEC574 PBW_eqDeg sing_585.htm#SEC636 PBW_maxDeg sing_586.htm#SEC637 PBW_maxMonom sing_587.htm#SEC638 PEsolve sing_1731.htm#SEC1806 PH_ais sing_2100.htm#SEC2175 PH_nais sing_2101.htm#SEC2176 PLURAL sing_469.htm#SEC508 PLURAL LIBs Non-commutative libraries sing_545.htm#SEC596 ParToVar sing_2269.htm#SEC2344 Parallelization Parallelization with ssi links sing_850.htm#SEC901 Parallelization sing_980.htm#IDX424 Parameter list sing_44.htm#SEC80 Parameters sing_847.htm#SEC898 Parametrization sing_1402.htm#IDX533 Parametrization, image. sing_1412.htm#IDX545 PartC sing_2221.htm#SEC2296 PartitionVar sing_2266.htm#SEC2341 Path names Notes for Singular users sing_2454.htm#SEC2538 PerfectPowerTest sing_1889.htm#SEC1964 Perturbation walk sing_1187.htm#IDX481 Pfister, Gerhard sing_1.htm#IDX19 Pipe links sing_116.htm#SEC155 PocklingtonLehmer sing_1928.htm#SEC2003 Poincare polynomial sing_2163.htm#IDX851 Polar curves sing_872.htm#SEC923 PollardRho sing_1929.htm#SEC2004 PolyBoRi, Boolean Groebner Basis recursive_from_boolean_poly sing_2103.htm#IDX752 PolyBoRi, Boolean Groebner Basis sing_2105.htm#IDX753 PolyBoRi, Boolean Groebner Basis sing_2106.htm#IDX754 PolyBoRi, Boolean Groebner Basis sing_2107.htm#IDX755 PolyBoRi, Boolean Groebner Basis sing_2108.htm#IDX756 PolyBoRi, Boolean Groebner Basis sing_2109.htm#IDX757 PolyBoRi, Boolean Groebner Basis sing_2110.htm#IDX758 PolyBoRi, Boolean Groebner Basis sing_2111.htm#IDX759 PolyBoRi, Boolean Groebner Basis sing_2112.htm#IDX760 PolyBoRi, Boolean Groebner Basis sing_2113.htm#IDX761 PolyBoRi, Boolean Groebner Basis sing_2114.htm#IDX762 PolyBoRi, Boolean Groebner Basis sing_2115.htm#IDX763 PolyBoRi, Boolean Groebner Basis sing_2116.htm#IDX764 PolyBoRi, Boolean Groebner Basis sing_2117.htm#IDX765 PolyBoRi, Boolean Groebner Basis sing_2119.htm#IDX767 PolyBoRi, zero-supressed decision diagram sing_2118.htm#IDX766 Polybori, Boolean Groebner Basis sing_2120.htm#IDX768 Polynomial data sing_888.htm#SEC939 Pottier algorithm sing_909.htm#SEC965 Preface sing_1.htm#SEC1 Prep sing_961.htm#SEC1036 Primary decomposition Primary decomposition sing_865.htm#SEC916 PrimdecA sing_1239.htm#SEC1314 PrimdecB sing_1240.htm#SEC1315 Procedure definition Procedure definition sing_43.htm#SEC77 Procedure-specific commands Procedure-specific commands sing_47.htm#SEC83 Procedures sing_42.htm#SEC76 Procedures and libraries Writing procedures and libraries sing_8.htm#SEC14 Procedures and libraries sing_844.htm#SEC895 Procedures in a library Procedures in a library sing_54.htm#SEC90 Product orderings sing_897.htm#SEC948 Programming sing_842.htm#SEC893 PtoCrep sing_962.htm#SEC1037 Puiseux expansion sing_1496.htm#IDX556 Puiseux expansion sing_1584.htm#IDX678 Puiseux pairs Invariants of plane curve singularities sing_875.htm#SEC926 Puiseux pairs sing_1590.htm#IDX683 Qso3Casimir sing_733.htm#SEC784 Quotient sing_1773.htm#SEC1848 QuotientEquations sing_1620.htm#SEC1695 Rational curves sing_1402.htm#IDX534 ReJunkUseHomo sing_1388.htm#SEC1463 ReesAlgebra sing_1355.htm#SEC1430 References sing_924.htm#SEC997 References (plural) sing_537.htm#SEC586 Release Notes sing_2450.htm#SEC2525 ResTree sing_1448.htm#SEC1523 Resolution sing_11.htm#SEC17 Resolution of singularities Resolution of singularities sing_878.htm#SEC929 Resolution, free sing_860.htm#SEC911 ReynoldsImage sing_1722.htm#SEC1797 ReynoldsOperator sing_1723.htm#SEC1798 RiemannRochBN sing_2168.htm#SEC2243 RiemannRochHess sing_2324.htm#SEC2399 Right Groebner bases and syzygies Right Groebner bases and syzygies sing_884.htm#SEC935 Ring-dependent options Notes for Singular users sing_2454.htm#SEC2536 Rings and orderings sing_28.htm#SEC38 Rings and standard bases Rings and standard bases sing_7.htm#SEC13 Running SINGULAR under Emacs Running SINGULAR under Emacs sing_23.htm#SEC30 SCA Graded commutative algebras (SCA) sing_538.htm#SEC589 SDB breakpoint Source code debugger sing_66.htm#SEC105 SDB debugger Source code debugger sing_66.htm#SEC105 SDLoc sing_615.htm#SEC666 SINGULAR libraries sing_925.htm#SEC1000 SINGULARHIST sing_18.htm#SEC25 SV-decoding algorithm sing_1829.htm#IDX712 SV-decoding algorithm, preprocessing sing_1828.htm#IDX711 Sannfs sing_591.htm#SEC642 SannfsBFCT sing_600.htm#SEC651 SannfsVar sing_647.htm#SEC698 Sannfslog sing_592.htm#SEC643 Saturation sing_857.htm#SEC908 Sch@"onemann, Hans sing_1.htm#IDX20 Schoof sing_1940.htm#SEC2015 Schreyer ordering sing_1055.htm#IDX440 Schreyer resolution sing_1055.htm#IDX441 SchurCh sing_2218.htm#SEC2293 SchurS sing_2217.htm#SEC2292 Scontinue sing_1059.htm#SEC1134 Semigroup sing_1536.htm#SEC1611 Setting up a G-algebra sing_534.htm#SEC577 ShanksMestre sing_1939.htm#SEC2014 SimplifyIdeal sing_1724.htm#SEC1799 Singular sing_406.htm#IDX246 Singular 3 and Singular 4 Singular 3 and Singular 4 sing_2452.htm#SEC2532 Singular, customization of Emacs user interface Customization of the Emacs interface sing_25.htm#SEC35 Singular, demo mode sing_24.htm#SEC34 Singular, editing input files with Emacs Editing SINGULAR input files with Emacs sing_26.htm#SEC36 Singular, important commands of Emacs interface Top 20 Emacs commands sing_27.htm#SEC37 Singular, running within Emacs Running SINGULAR under Emacs sing_23.htm#SEC30 Singular2bertini sing_1386.htm#SEC1461 SingularLib sing_406.htm#IDX248 Singularities sing_1495.htm#SEC1570 Singularity Theory sing_869.htm#SEC920 Skeletons for parallelization sing_980.htm#IDX425 Smith form sing_1871.htm#IDX722 Smith normal form sing_1871.htm#IDX723 SolowayStrassen sing_1927.htm#SEC2002 Solving systems of polynomial equations Solving systems of polynomial equations sing_886.htm#SEC937 Source code debugger, invocation Command line options sing_19.htm#IDX33 Space curve singularities, branches of Branches of space curve singularities sing_876.htm#SEC927 Special characters sing_36.htm#SEC63 Splitting lemma sing_2394.htm#IDX893 Sres sing_1057.htm#SEC1132 Ssi file links sing_114.htm#SEC153 Ssi links sing_113.htm#SEC152 Ssi tcp links sing_115.htm#SEC154 Ssyz sing_1058.htm#SEC1133 StabEqn sing_1621.htm#SEC1696 StabEqnId sing_1622.htm#SEC1697 StabOrder sing_1623.htm#SEC1698 Standard Bases Computing Groebner and Standard Bases sing_852.htm#SEC903 Standard bases sing_900.htm#SEC951 StartOrderingV sing_1490.htm#SEC1565 Startup sequence sing_20.htm#SEC27 StringF sing_1610.htm#SEC1685 SymGroup sing_790.htm#SEC841 Symbolic-numerical solving Symbolic-numerical solving sing_886.htm#SEC937 Symbolic-numerical solving sing_1728.htm#SEC1803 System and Control theory System and Control theory sing_1853.htm#SEC1928 System dependent limitations System dependent limitations sing_456.htm#SEC495 System variables sing_442.htm#SEC481 Syzygies and resolutions Syzygies and resolutions sing_902.htm#SEC955 Syzygies and resolutions (plural) Syzygies and resolutions (plural) sing_536.htm#SEC582 T1 sing_873.htm#SEC924 T2 sing_873.htm#SEC924 TRACE Tracing of procedures sing_65.htm#SEC101 TRACE sing_451.htm#SEC490 T_1 sing_1643.htm#SEC1718 T_12 sing_1645.htm#SEC1720 T_2 sing_1644.htm#SEC1719 Teaching sing_1885.htm#SEC1960 Template for writing a library sing_55.htm#SEC91 TestGRRes sing_2304.htm#SEC2379 TestJMark sing_1491.htm#SEC1566 The SINGULAR language The SINGULAR language sing_34.htm#SEC55 The Tran algorithm sing_1184.htm#IDX478 The fractal walk algorithm sing_1183.htm#IDX477 The fractal walk algorithm sing_2388.htm#IDX890 The online help system The online help system sing_16.htm#SEC22 Tjurina sing_1641.htm#SEC1716 Tjurina number Milnor and Tjurina number sing_870.htm#SEC921 Tjurina number sing_1278.htm#IDX505 Top 20 Emacs commands Top 20 Emacs commands sing_27.htm#SEC37 Tor sing_1209.htm#SEC1284 Toric ideals and integer programming Toric ideals and integer programming sing_905.htm#SEC961 Tricks and pitfalls sing_454.htm#SEC493 Tropical Geometry sing_2037.htm#SEC2112 Type casting Type conversion and casting sing_39.htm#SEC68 Type conversion Type conversion and casting sing_39.htm#SEC67 Typesetting of help and info strings Typesetting of help and info strings sing_61.htm#SEC97 U_D_O sing_1124.htm#SEC1199 Unix installation Unix installation instructions sing_2459.htm#SEC2546 UpOneMatrix sing_779.htm#SEC830 UpperMonomials sing_1624.htm#SEC1699 UseBertini sing_1385.htm#SEC1460 User defined types sing_177.htm#SEC216 V-filtration sing_1559.htm#IDX588 V-filtration sing_1565.htm#IDX616 V-filtration sing_1566.htm#IDX622 V-filtration sing_1567.htm#IDX630 V-filtration sing_1568.htm#IDX636 V-filtration sing_1569.htm#IDX644 V-filtration sing_1570.htm#IDX654 V-filtration sing_1581.htm#IDX660 V-filtration sing_1583.htm#IDX671 VarToPar sing_2268.htm#SEC2343 Variables, indexed sing_37.htm#SEC64 Version number Version schema for Singular sing_2453.htm#SEC2533 Version schema for Singular Version schema for Singular sing_2453.htm#SEC2533 Version string sing_50.htm#SEC86 Visualization sing_1791.htm#SEC1866 WP, global ordering sing_893.htm#IDX389 WSemigroup sing_1541.htm#SEC1616 Weierstrass sing_1824.htm#SEC1899 Weierstrass semigroup sing_1820.htm#IDX706 Weyl sing_764.htm#SEC815 Weyl algebra sing_588.htm#IDX321 Weyl algebra sing_644.htm#IDX346 Weyl closure sing_815.htm#IDX374 WeylClosure sing_817.htm#SEC868 WeylClosure1 sing_818.htm#SEC869 Windows installation Windows installation instructions sing_2460.htm#SEC2547 WitSet sing_1392.htm#SEC1467 WitSupSet sing_1391.htm#SEC1466 Ws, local ordering sing_894.htm#IDX401 XLsolve sing_1734.htm#SEC1809 ZZsolve sing_1735.htm#SEC1810 [ sing_36.htm#IDX84 \ sing_36.htm#IDX113 ] sing_36.htm#IDX85 ^ sing_36.htm#IDX93 ^ sing_76.htm#SEC115 ^ sing_88.htm#SEC127 _ sing_36.htm#IDX117 ` sing_36.htm#IDX106 a, ordering sing_898.htm#SEC949 absFactorize sing_1137.htm#SEC1212 absFactorizeBCG sing_1138.htm#SEC1213 absPrimdecGTZ sing_1335.htm#SEC1410 absPrimdecGTZE sing_1336.htm#SEC1411 absValue sing_937.htm#SEC1012 absfact.lib sing_1136.htm#SEC1211 absfact_lib sing_1136.htm#SEC1211 absolute factorization. sing_1136.htm#IDX452 abstractR sing_1474.htm#SEC1549 actionIsProper sing_1704.htm#SEC1779 addNvarsTo sing_1054.htm#SEC1129 addRat sing_836.htm#SEC887 addcol sing_1093.htm#SEC1168 addcores sing_1023.htm#SEC1098 addrow sing_1094.htm#SEC1169 addvarsTo sing_1053.htm#SEC1128 ademRelations sing_697.htm#SEC748 adjoint sing_1118.htm#SEC1193 adjointIdeal sing_1403.htm#SEC1478 adjunction divisor sing_1821.htm#IDX710 admissibleSub sing_755.htm#SEC806 afaces sing_2280.htm#SEC2355 affine code Fitzgerald-Lax method sing_921.htm#SEC989 ainvar.lib sing_1701.htm#SEC1776 ainvar_lib sing_1701.htm#SEC1776 aksaka.lib sing_1886.htm#SEC1961 aksaka_lib sing_1886.htm#SEC1961 alexanderpolynomial sing_1499.htm#SEC1574 alexpoly.lib sing_1496.htm#SEC1571 alexpoly_lib sing_1496.htm#SEC1571 algDependent sing_1143.htm#SEC1218 alg_kernel sing_1144.htm#SEC1219 algebra.lib sing_1139.htm#SEC1214 algebra_containment sing_1140.htm#SEC1215 algebra_lib sing_1139.htm#SEC1214 algebraic dependence sing_785.htm#IDX352 algebraic field extension sing_1349.htm#IDX510 algebraicDependence sing_1362.htm#SEC1437 algorithm of Bigatti, La Scala and Robbiano Bigatti and La Scala and Robbiano sing_912.htm#SEC968 algorithm of Conti and Traverso sing_908.htm#SEC964 algorithm of Di Biase and Urbanke Di Biase and Urbanke sing_911.htm#SEC967 algorithm of Hosten and Sturmfels Hosten and Sturmfels sing_910.htm#SEC966 algorithm of Pottier sing_909.htm#SEC965 align sing_260.htm#SEC299 all.lib sing_930.htm#SEC1005 allDoubleExt sing_802.htm#SEC853 allExtOfLeft sing_799.htm#SEC850 allExtOfRight sing_800.htm#SEC851 allPositive sing_564.htm#SEC615 all_lib sing_930.htm#SEC1005 allowing net access Command line options sing_19.htm#IDX41 allprint sing_971.htm#SEC1046 allreal sing_2029.htm#SEC2104 allrealst sing_2027.htm#SEC2102 allsquarefree sing_1603.htm#SEC1678 ambientDimension sing_187.htm#SEC226 and Evaluation of logical expressions sing_96.htm#SEC135 and sing_459.htm#SEC498 annPoly sing_612.htm#SEC663 annRat sing_613.htm#SEC664 annRatSyz sing_825.htm#SEC876 annfs sing_589.htm#SEC640 annfs0 sing_601.htm#SEC652 annfs2 sing_602.htm#SEC653 annfsBMI sing_598.htm#SEC649 annfsParamBM sing_597.htm#SEC648 annfsRB sing_603.htm#SEC654 annfspecial sing_590.htm#SEC641 annihilator of polynomial sing_611.htm#IDX331 annihilator of rational function sing_611.htm#IDX332 annihilator of rational function sing_815.htm#IDX377 annil sing_1245.htm#SEC1320 appelF1 sing_630.htm#SEC681 appelF2 sing_631.htm#SEC682 appelF4 sing_632.htm#SEC683 appendWeight2Ord sing_757.htm#SEC808 apply sing_426.htm#SEC465 applyAdF sing_580.htm#SEC631 arcpoint.lib sing_1509.htm#SEC1584 arcpoint_lib sing_1509.htm#SEC1584 areZeroElements sing_2366.htm#SEC2441 argument, default sing_44.htm#SEC80 argument, optional sing_44.htm#SEC80 arr.lib sing_2122.htm#SEC2197 arr2multarr sing_2155.htm#SEC2230 arrBoolean sing_2144.htm#SEC2219 arrBoundedChambers sing_2165.htm#SEC2240 arrBraid sing_2145.htm#SEC2220 arrCenter sing_2132.htm#SEC2207 arrCentered sing_2134.htm#SEC2209 arrCentral sing_2133.htm#SEC2208 arrCentralize sing_2135.htm#SEC2210 arrChambers sing_2164.htm#SEC2239 arrCharPoly sing_2162.htm#SEC2237 arrCone sing_2138.htm#SEC2213 arrCoordChange sing_2136.htm#SEC2211 arrCoordNormalize sing_2137.htm#SEC2212 arrDecone sing_2139.htm#SEC2214 arrDer sing_2152.htm#SEC2227 arrEdelmanReiner sing_2150.htm#SEC2225 arrEssentialize sing_2143.htm#SEC2218 arrExponents sing_2154.htm#SEC2229 arrFlats sing_2159.htm#SEC2234 arrIsEssential sing_2142.htm#SEC2217 arrIsFree sing_2153.htm#SEC2228 arrLastVar sing_2131.htm#SEC2206 arrLattice sing_2160.htm#SEC2235 arrLocalize sing_2140.htm#SEC2215 arrOrlikSolomon sing_2151.htm#SEC2226 arrPoincare sing_2163.htm#SEC2238 arrPrintMatrix sing_2127.htm#SEC2202 arrRandom sing_2148.htm#SEC2223 arrRandomCentral sing_2149.htm#SEC2224 arrRestrict sing_2141.htm#SEC2216 arrSet sing_2123.htm#SEC2198 arrSwapVar sing_2130.htm#SEC2205 arrTypeB sing_2146.htm#SEC2221 arrTypeD sing_2147.htm#SEC2222 arr_lib sing_2122.htm#SEC2197 arrange sing_605.htm#SEC656 arrangement sing_2123.htm#IDX769 arrangement sing_2124.htm#IDX774 arrangement sing_2155.htm#IDX836 arrangement sing_2156.htm#IDX839 ask sing_1894.htm#SEC1969 assPrimes sing_1154.htm#SEC1229 assign sing_2123.htm#IDX771 assignment,custom Assignments for user defined types sing_182.htm#SEC221 assprimeszerodim.lib assprimeszerodim_lib sing_1152.htm#SEC1227 assprimeszerodim_lib assprimeszerodim_lib sing_1152.htm#SEC1227 atkins.lib sing_1895.htm#SEC1970 atkins_lib sing_1895.htm#SEC1970 attrib sing_261.htm#SEC300 autonom sing_1858.htm#SEC1933 autonomDim sing_1859.htm#SEC1934 awalk1 sing_1185.htm#SEC1260 awalk2 sing_1186.htm#SEC1261 b-function sing_553.htm#IDX304 bFactor sing_635.htm#SEC686 babyGiant sing_1924.htm#SEC1999 backward sing_2255.htm#SEC2330 bareiss sing_262.htm#SEC301 base2str sing_933.htm#SEC1008 basering sing_28.htm#IDX77 basering sing_83.htm#SEC122 basicinvariants sing_1515.htm#SEC1590 belongSemigroup sing_1157.htm#SEC1232 bernstein sing_1563.htm#SEC1638 bernsteinBM sing_593.htm#SEC644 bernsteinLift sing_594.htm#SEC645 bertini2Singular sing_1387.htm#SEC1462 betti sing_263.htm#SEC302 betti (plural) sing_503.htm#SEC542 bfct sing_554.htm#SEC605 bfctAnn sing_556.htm#SEC607 bfctBound sing_824.htm#SEC875 bfctIdeal sing_558.htm#SEC609 bfctOneGB sing_557.htm#SEC608 bfctSyz sing_555.htm#SEC606 bfctVarAnn sing_646.htm#SEC697 bfctVarIn sing_645.htm#SEC696 bfun.lib sing_553.htm#SEC604 bfun_lib sing_553.htm#SEC604 bigint sing_73.htm#SEC112 bigint declarations sing_74.htm#SEC113 bigint expressions sing_75.htm#SEC114 bigint operations sing_76.htm#SEC115 bigint related functions bigint related functions sing_77.htm#SEC116 bigintmat sing_78.htm#SEC117 bigintmat declarations bigintmat declarations sing_79.htm#SEC118 bigintmat expressions bigintmat expressions sing_80.htm#SEC119 bigintmat operations bigintmat operations sing_82.htm#SEC121 bigintmat type cast sing_81.htm#SEC120 bimodules sing_546.htm#IDX292 bimodules.lib sing_546.htm#SEC597 bimodules_lib sing_546.htm#SEC597 binary_add sing_1947.htm#SEC2022 binomial sing_938.htm#SEC1013 binomials2intmat sing_1310.htm#SEC1385 58804 birational map, image, inverse. sing_1404.htm#IDX539 bistd sing_547.htm#SEC598 bisyzygies sing_546.htm#IDX293 bitrinity sing_548.htm#SEC599 blackbox sing_243.htm#SEC282 blackbox sing_251.htm#SEC290 block sing_40.htm#SEC69 block sing_425.htm#SEC464 blowUp sing_1455.htm#SEC1530 blowUp2 sing_1456.htm#SEC1531 blowUpBO sing_1462.htm#SEC1537 blowup0 sing_1162.htm#SEC1237 boolean sing_2144.htm#IDX813 boolean expressions sing_95.htm#SEC134 boolean operations sing_96.htm#SEC135 boolean_constant sing_2105.htm#SEC2180 52873 boolean_ideal sing_2109.htm#SEC2184 53515 boolean_poly sing_2106.htm#SEC2181 41652 boolean_poly_ring sing_2104.htm#SEC2179 sprintf boolean_set sing_2110.htm#SEC2185 58235 boolean_std sing_2103.htm#SEC2178 5921 boundBuFou sing_2024.htm#SEC2099 boundDes sing_2026.htm#SEC2101 boundaryLatticePoints boundaryLatticePoints sing_2411.htm#SEC2486 boundposDes sing_2025.htm#SEC2100 bracket sing_406.htm#IDX192 bracket sing_462.htm#SEC501 bracket sing_504.htm#SEC543 braid sing_2145.htm#IDX815 branchTo procs with different argument types sing_155.htm#SEC194 break sing_427.htm#SEC466 break point sing_441.htm#SEC480 breakpoint sing_428.htm#SEC467 brillnoether.lib sing_2167.htm#SEC2242 brillnoether_lib sing_2167.htm#SEC2242 brnoeth.lib sing_1820.htm#SEC1895 brnoeth_lib sing_1820.htm#SEC1895 browser, command line option Command line options sing_19.htm#IDX44 browser, setting the sing_406.htm#IDX188 browsers The online help system sing_16.htm#IDX21 browsers, setting the sing_406.htm#IDX187 bubblesort sing_1897.htm#SEC1972 busadj sing_1116.htm#SEC1191 bvar sing_2117.htm#SEC2192 52773 c, module ordering sing_895.htm#IDX404 cProj sing_2207.htm#SEC2282 calculateI sing_1429.htm#SEC1504 calculate_max_sum sing_1966.htm#SEC2041 calculate_ordering sing_1944.htm#SEC2019 cancelunit, option sing_364.htm#IDX167 canonMap sing_1190.htm#SEC1265 canonicalizeCone sing_188.htm#SEC227 canonize sing_1866.htm#SEC1941 cantoradd sing_1980.htm#SEC2055 cantormult sing_1983.htm#SEC2058 cantorred sing_1981.htm#SEC2056 cardGroup sing_1159.htm#SEC1234 case No case or switch statement sing_460.htm#SEC499 cdd sing_1.htm#IDX10 cddlib sing_1.htm#IDX11 center sing_567.htm#IDX311 center sing_573.htm#SEC624 center sing_2132.htm#IDX795 center sing_2133.htm#IDX796 center sing_2134.htm#IDX798 center sing_2135.htm#IDX800 centerRed sing_572.htm#SEC623 centerVS sing_571.htm#SEC622 central sing_2126.htm#IDX781 central sing_2133.htm#IDX797 central sing_2135.htm#IDX799 central sing_2149.htm#IDX824 central.lib sing_567.htm#SEC618 central1st sing_2256.htm#SEC2331 central2nd sing_2257.htm#SEC2332 central_lib sing_567.htm#SEC618 centralize sing_567.htm#IDX314 centralizeSet sing_568.htm#SEC619 centralizer sing_567.htm#IDX312 centralizer sing_574.htm#SEC625 centralizerRed sing_570.htm#SEC621 centralizerVS sing_569.htm#SEC620 cgs sing_932.htm#SEC1007 cgsdr sing_957.htm#SEC1032 chAll sing_2179.htm#SEC2254 chAllInv sing_2180.htm#SEC2255 chDual sing_2185.htm#SEC2260 chHE sing_2181.htm#SEC2256 chHom sing_2192.htm#SEC2267 chNum sing_2175.htm#SEC2250 chNumbers sing_2176.htm#SEC2251 chNumbersProj sing_2211.htm#SEC2286 chProd sing_2187.htm#SEC2262 chProdE sing_2188.htm#SEC2263 chProdL sing_2189.htm#SEC2264 chProdLP sing_2190.htm#SEC2265 chProj sing_2208.htm#SEC2283 chSum sing_2183.htm#SEC2258 chSymm sing_2195.htm#SEC2270 chSymm2L sing_2196.htm#SEC2271 chSymm2LP sing_2197.htm#SEC2272 chWedge sing_2198.htm#SEC2273 chWedge2L sing_2199.htm#SEC2274 chWedge2LP sing_2200.htm#SEC2275 chaincrit sing_1994.htm#SEC2069 chambers sing_2164.htm#IDX852 chambers sing_2165.htm#IDX853 changeDenominator sing_1283.htm#SEC1358 changechar sing_1028.htm#SEC1103 changeord sing_1029.htm#SEC1104 changeordTo sing_1052.htm#SEC1127 changes sing_2451.htm#SEC2526 changevar sing_1030.htm#SEC1105 char sing_264.htm#SEC303 charInfo sing_628.htm#SEC679 charVariety sing_627.htm#SEC678 char_series sing_265.htm#SEC304 characteristic exponents sing_1503.htm#IDX563 characteristic exponents sing_1504.htm#IDX568 characteristic exponents sing_1505.htm#IDX571 characteristic exponents sing_1506.htm#IDX575 characteristic exponents sing_1590.htm#IDX681 characteristic polynomial sing_2162.htm#IDX850 characteristic variety sing_611.htm#IDX339 characteristic variety sing_815.htm#IDX373 charexp2conductor sing_1506.htm#SEC1581 charexp2generators sing_1504.htm#SEC1579 charexp2inter sing_1505.htm#SEC1580 charexp2multseq sing_1503.htm#SEC1578 charexp2poly sing_1507.htm#SEC1582 charpoly sing_1117.htm#SEC1192 charstr sing_266.htm#SEC305 checkFactor sing_604.htm#SEC655 checkRoot sing_599.htm#SEC650 chern sing_2174.htm#SEC2249 chern.lib sing_2169.htm#SEC2244 chernCharPoly sing_2214.htm#SEC2289 chernPoly sing_2213.htm#SEC2288 chern_lib sing_2169.htm#SEC2244 chineseRem sing_1915.htm#SEC1990 chinrem sing_267.htm#SEC306 chinrempoly sing_2383.htm#SEC2458 chinrestp sing_1974.htm#SEC2049 cimonom.lib sing_2224.htm#SEC2299 cimonom_lib sing_2224.htm#SEC2299 cisimplicial.lib sing_1155.htm#SEC1230 cisimplicial_lib sing_1155.htm#SEC1230 classify sing_1516.htm#SEC1591 classify.lib sing_1514.htm#SEC1589 classifyCeq sing_1533.htm#SEC1608 classify_lib sing_1514.htm#SEC1589 classifyceq.lib sing_1532.htm#IDX578 classifyceq_lib sing_1532.htm#IDX579 classifyci.lib sing_1534.htm#IDX580 classifyci_lib sing_1534.htm#IDX581 classifyicis sing_1535.htm#SEC1610 classpoly sing_2212.htm#SEC2287 cleanTmp sing_2095.htm#SEC2170 cleanunit sing_1427.htm#SEC1502 cleardenom sing_268.htm#SEC307 close sing_269.htm#SEC308 closed_points sing_1830.htm#SEC1905 closetex sing_1797.htm#SEC1872 closureFrac sing_1276.htm#SEC1351 coHom sing_808.htm#SEC859 codim sing_1628.htm#SEC1703 codimension sing_189.htm#SEC228 coding theory sing_887.htm#SEC938 coef sing_270.htm#SEC309 coefficient sing_2125.htm#IDX777 coefficient sing_2126.htm#IDX780 coefficient sing_2127.htm#IDX784 coefficient field sing_139.htm#SEC178 coefficient rings, ring of integers, zero divisors, p-adic numbers Coefficient rings sing_32.htm#SEC44 coefficients, long sing_846.htm#SEC897 coeffmod sing_1892.htm#SEC1967 coeffs sing_271.htm#SEC310 collectDiv sing_1472.htm#SEC1547 colrank sing_1864.htm#SEC1939 colred sing_1100.htm#SEC1175 commRing sing_839.htm#SEC890 comma sing_461.htm#SEC500 command,custom Commands for user defined types sing_181.htm#SEC220 command-line option, setting value of sing_406.htm#IDX270 command-line option, value of sing_406.htm#IDX268 command-line options, print all values of sing_406.htm#IDX267 command-line options, short help Command line options sing_19.htm#IDX38 commands (plural) sing_502.htm#IDX291 comment sing_36.htm#IDX109 compareTasks sing_1064.htm#SEC1139 completeReduction sing_1706.htm#SEC1781 complex sing_28.htm#IDX76 complexSingType sing_1530.htm#SEC1605 compregb.lib sing_931.htm#SEC1006 compregb_lib sing_931.htm#SEC1006 comprehensive Groebner system sing_931.htm#IDX410 compress sing_1077.htm#SEC1152 computeConstant sing_1175.htm#SEC1250 computeGromovWitten sing_1178.htm#SEC1253 computeN sing_1476.htm#SEC1551 computeV sing_1475.htm#SEC1550 computemcm sing_1434.htm#SEC1509 concat sing_1078.htm#SEC1153 conductor sing_1506.htm#IDX574 conductor, degree sing_1590.htm#IDX684 cone sing_183.htm#SEC222 cone sing_2138.htm#IDX804 cone sing_2139.htm#IDX806 cone related functions cone related functions sing_186.htm#SEC225 coneLink sing_190.htm#SEC229 coneViaInequalities sing_185.htm#SEC224 coneViaPoints sing_184.htm#SEC223 conic, parametrization, rational point. sing_1411.htm#IDX544 conicWithTangents sing_2071.htm#SEC2146 constructH sing_1435.htm#SEC1510 constructblwup sing_1436.htm#SEC1511 constructlastblwup sing_1437.htm#SEC1512 constructor sing_2155.htm#IDX837 constructor sing_2156.htm#IDX840 contact matrix sing_1505.htm#IDX570 containedQ sing_1785.htm#SEC1860 containsAsFace sing_191.htm#SEC230 containsInCollection containsInCollection sing_223.htm#SEC262 containsInSupport sing_192.htm#SEC231 containsPositiveVector containsPositiveVector sing_193.htm#SEC232 containsRelatively sing_194.htm#SEC233 content sing_1002.htm#SEC1077 contentSB, option sing_364.htm#IDX168 continue Behavior of continue sing_429.htm#SEC468 continue sing_463.htm#SEC502 contraHom sing_809.htm#SEC860 contract sing_272.htm#SEC311 contributors sing_406.htm#IDX195 control sing_1856.htm#SEC1931 control.lib sing_1855.htm#SEC1930 controlDim sing_1857.htm#SEC1932 controlExample sing_1869.htm#SEC1944 control_Matrix sing_1558.htm#SEC1633 control_lib sing_1855.htm#SEC1930 convertdata sing_1432.htm#SEC1507 convex geometry sing_2400.htm#SEC2475 convexHull sing_195.htm#SEC234 convexIntersection sing_196.htm#SEC235 convloc sing_608.htm#SEC659 coordinate change sing_2135.htm#IDX801 coordinate change sing_2136.htm#IDX802 coordinate change sing_2137.htm#IDX803 coordinates sing_2012.htm#IDX726 coords sing_2012.htm#SEC2087 copyTask sing_1063.htm#SEC1138 copyright sing_1.htm#IDX1 corank sing_1517.htm#SEC1592 cornerMonomials sing_1313.htm#SEC1388 countPoints sing_1937.htm#SEC2012 coverings sing_1177.htm#IDX469 coverings sing_1178.htm#IDX473 cpu sing_406.htm#IDX197 cpu sing_406.htm#IDX264 createBO sing_1463.htm#SEC1538 createGradedRingHomomorphism createGradedRingHomomorphism sing_2342.htm#SEC2417 createGroup sing_2335.htm#SEC2410 createQuotientGroup sing_2336.htm#SEC2411 createTask sing_1061.htm#SEC1136 createTorsionFreeGroup createTorsionFreeGroup sing_2337.htm#SEC2412 createlist sing_1445.htm#SEC1520 crypto.lib sing_1910.htm#SEC1985 crypto_lib sing_1910.htm#SEC1985 cup sing_1191.htm#SEC1266 cupproduct sing_1192.htm#SEC1267 curve singularities sing_1496.htm#IDX557 curve singularities sing_1584.htm#IDX679 curvepar.lib sing_1537.htm#SEC1612 curvepar_lib sing_1537.htm#SEC1612 custom assignment Assignments for user defined types sing_182.htm#SEC221 custom command Commands for user defined types sing_181.htm#SEC220 custom type Definition of a user defined type sing_178.htm#SEC217 cycleLength sing_2047.htm#SEC2122 cyclePoints sing_2051.htm#SEC2126 cyclic sing_989.htm#SEC1064 cyclic code Codes and the decoding problem sing_918.htm#SEC976 cyclotomic sing_1671.htm#SEC1746 datetime sing_273.htm#SEC312 dbprint sing_274.htm#SEC313 deRham.lib sing_2397.htm#IDX896 deRhamCohom sing_625.htm#SEC676 deRhamCohomIdeal sing_626.htm#SEC677 deRhamCohomology sing_2398.htm#SEC2473 deRham_lib sing_2397.htm#IDX897 debugLib, option sing_364.htm#IDX172 debug_log sing_1527.htm#SEC1602 debugger Source code debugger sing_66.htm#SEC102 debugging library code Source code debugger sing_66.htm#SEC102 dec1var sing_1244.htm#SEC1319 decimal sing_1911.htm#SEC1986 decode sing_1847.htm#SEC1922 decodeCode sing_1849.htm#SEC1924 decodeRandom sing_1848.htm#SEC1923 decodeRandomFL sing_1852.htm#SEC1927 decodeSV sing_1829.htm#SEC1904 decodegb.lib sing_1834.htm#SEC1909 decodegb_lib sing_1834.htm#SEC1909 decoding, decoding problem Codes and the decoding problem sing_918.htm#SEC977 decoef sing_1877.htm#SEC1952 decone sing_2138.htm#IDX805 decone sing_2139.htm#IDX807 def sing_83.htm#SEC122 def declarations sing_84.htm#SEC123 defRes, option sing_364.htm#IDX173 default argument sing_44.htm#SEC80 defineHomogeneous sing_2375.htm#SEC2450 defined sing_275.htm#SEC314 defl sing_1394.htm#SEC1469 deform sing_1629.htm#SEC1704 deform.lib sing_1548.htm#SEC1623 deform_lib sing_1548.htm#SEC1623 defring sing_1031.htm#SEC1106 defringp sing_1033.htm#SEC1108 defrings sing_1032.htm#SEC1107 deg sing_276.htm#SEC315 degBound sing_443.htm#SEC482 degree Miscellaneous oddities sing_277.htm#SEC316 degree sing_466.htm#IDX281 degree lexicographical ordering sing_893.htm#IDX384 degree of a polynomial Miscellaneous oddities sing_466.htm#IDX285 degree reverse lexicographical ordering sing_893.htm#IDX382 degreeDivisor sing_2236.htm#SEC2311 degreeFormalDivisor sing_2244.htm#SEC2319 degreepart sing_1737.htm#SEC1812 delete sing_278.htm#SEC317 delete sing_325.htm#SEC364 deleteGenerator sing_640.htm#SEC691 deleteSublist sing_939.htm#SEC1014 delta sing_1596.htm#SEC1671 delta invariant sing_1278.htm#IDX504 delta invariant sing_1596.htm#IDX689 delta invariant. sing_1270.htm#IDX497 delta invariant. sing_1271.htm#IDX500 delta invariant. sing_1272.htm#IDX503 deltaLoc sing_1278.htm#SEC1353 denom_list sing_406.htm#IDX199 denominator sing_279.htm#SEC318 depth sing_1193.htm#SEC1268 depthIdeal sing_1254.htm#SEC1329 derivate sing_1703.htm#SEC1778 derivation sing_2152.htm#IDX828 desingularization sing_2286.htm#IDX880 desingularization sing_2287.htm#SEC2362 det sing_280.htm#SEC319 det_B sing_1119.htm#SEC1194 detadj sing_1612.htm#SEC1687 determinacy sing_2396.htm#SEC2471 determinecenter sing_1417.htm#SEC1492 detropicalise sing_2089.htm#SEC2164 develop sing_1586.htm#SEC1661 diag sing_1079.htm#SEC1154 diagInvariants sing_1292.htm#SEC1367 62096 diag_test sing_1115.htm#SEC1190 diff sing_281.htm#SEC320 diffRat sing_838.htm#SEC889 difpoly2tex sing_1878.htm#SEC1953 dim sing_282.htm#SEC321 dim (plural) sing_505.htm#SEC544 dimGradedPart sing_1485.htm#SEC1560 11262 dimH sing_1484.htm#SEC1559 38534 dimMon sing_1234.htm#SEC1309 dim_slocus sing_1630.htm#SEC1705 dimension sing_197.htm#SEC236 dimensionOfLocalization dimensionOfLocalization sing_2274.htm#SEC2349 direct_boolean_poly sing_2107.htm#SEC2182 49893 direct_from_boolean_poly direct_from_boolean_poly sing_2113.htm#SEC2188 36941 disc sing_1898.htm#SEC1973 discr sing_1652.htm#SEC1727 discrepancy sing_1470.htm#SEC1545 disp_zdd sing_2120.htm#SEC2195 41439 displayCohom sing_1486.htm#SEC1561 22633 displayHNE sing_1589.htm#SEC1664 displayInvariants sing_1591.htm#SEC1666 displayMultsequence sing_1593.htm#SEC1668 displayPuiseuxExpansion displayPuiseuxExpansion sing_2064.htm#SEC2139 displayTropicalLifting displayTropicalLifting sing_2062.htm#SEC2137 distributed computing sing_982.htm#IDX429 distributed computing sing_1022.htm#IDX431 distributed computing sing_1060.htm#IDX444 div Miscellaneous oddities sing_76.htm#SEC115 div sing_93.htm#SEC132 div sing_466.htm#IDX278 divideUnits sing_1874.htm#SEC1949 dividelist sing_1444.htm#SEC1519 division sing_283.htm#SEC322 division (plural) sing_506.htm#SEC545 division, pdivi, reduce sing_959.htm#IDX414 division, reduce sing_958.htm#IDX413 divisor sing_1977.htm#SEC2052 divisorplus sing_2230.htm#SEC2305 divisors negativeformaldivisor sing_2229.htm#IDX854 divisors sing_2230.htm#IDX855 divisors sing_2231.htm#IDX856 divisors sing_2232.htm#IDX857 divisors sing_2233.htm#IDX858 divisors sing_2234.htm#IDX859 divisors sing_2235.htm#IDX860 divisors sing_2236.htm#IDX861 divisors sing_2237.htm#IDX862 divisors sing_2238.htm#IDX863 divisors sing_2239.htm#IDX864 divisors sing_2240.htm#IDX865 divisors sing_2241.htm#IDX866 divisors sing_2242.htm#IDX867 divisors sing_2243.htm#IDX868 divisors sing_2244.htm#IDX869 divisors, polyhedra sing_2245.htm#IDX870 divisors, polyhedra sing_2246.htm#IDX871 divisors, polyhedra sing_2247.htm#IDX872 divisors.lib sing_2228.htm#SEC2303 divisors_lib sing_2228.htm#SEC2303 dmod.lib sing_588.htm#SEC639 dmodAction sing_833.htm#SEC884 dmodActionRat sing_834.htm#SEC885 dmodGeneralAssumptionCheck dmodGeneralAssumptionCheck sing_826.htm#SEC877 dmod_lib sing_588.htm#SEC639 dmodapp.lib sing_611.htm#SEC662 dmodapp_lib sing_611.htm#SEC662 dmodloc.lib sing_815.htm#IDX366 dmodloc_lib sing_815.htm#IDX367 dmodoublext sing_810.htm#SEC861 dmodvar.lib sing_644.htm#SEC695 dmodvar_lib sing_644.htm#SEC695 double sing_1982.htm#SEC2057 doubleExt sing_801.htm#SEC852 downloading Download instructions sing_2458.htm#SEC2545 dp, global ordering sing_893.htm#IDX383 drawNewtonSubdivision drawNewtonSubdivision sing_2067.htm#SEC2142 drawTropicalCurve sing_2066.htm#SEC2141 ds, local ordering sing_894.htm#IDX393 dsum sing_1080.htm#SEC1155 dualCone sing_198.htm#SEC237 dualConic sing_2091.htm#SEC2166 dualPart sing_2220.htm#SEC2295 dualPolytope sing_240.htm#SEC279 dual_code sing_1831.htm#SEC1906 dump sing_284.htm#SEC323 ecart sing_1985.htm#SEC2060 echo sing_444.htm#SEC483 eexgcdN sing_1912.htm#SEC1987 effective sing_2238.htm#SEC2313 egcdMain sing_1778.htm#SEC1853 ehrhartPolynomialCoeff ehrhartPolynomialCoeff sing_2412.htm#SEC2487 ehrhartRing sing_1288.htm#SEC1363 16966 eigenvals sing_1127.htm#SEC1202 eigenvalue sing_377.htm#SEC416 eigenvalue sing_1127.htm#IDX450 eigenvalues sing_1371.htm#SEC1446 elemSymmId sing_990.htm#SEC1065 elim sing_1164.htm#SEC1239 elim.lib sing_1161.htm#SEC1236 elim1 sing_1165.htm#SEC1240 elim2 sing_1166.htm#SEC1241 elimRing sing_1163.htm#SEC1238 elimWeight sing_758.htm#SEC809 elim_lib sing_1161.htm#SEC1236 eliminate sing_285.htm#SEC324 eliminate (plural) sing_507.htm#SEC546 eliminateNC sing_753.htm#SEC804 elimination sing_752.htm#IDX351 elimlinearpart sing_1738.htm#SEC1813 elimpart sing_1739.htm#SEC1814 elimpartanyr sing_1740.htm#SEC1815 elimrep sing_1425.htm#SEC1500 elliptic curve sing_1174.htm#IDX465 elliptic curves sing_1171.htm#IDX459 elliptic curves sing_1177.htm#IDX468 elliptic curves sing_1178.htm#IDX472 ellipticAdd sing_1933.htm#SEC2008 ellipticAllPoints sing_1938.htm#SEC2013 ellipticMult sing_1934.htm#SEC2009 ellipticNF sing_2054.htm#SEC2129 ellipticNFDB sing_2055.htm#SEC2130 ellipticRandomCurve sing_1935.htm#SEC2010 ellipticRandomPoint sing_1936.htm#SEC2011 ellipticcovers.lib sing_1171.htm#IDX453 ellipticcovers_lib sing_1171.htm#IDX454 else sing_434.htm#SEC473 embedMat sing_784.htm#SEC835 emptyFan sing_224.htm#SEC263 encode sing_1839.htm#SEC1914 endomorphism filtration sing_1570.htm#IDX655 endvfilt sing_1570.htm#SEC1645 engine sing_641.htm#SEC692 envelop sing_967.htm#SEC1042 envelopdg sing_968.htm#SEC1043 envelope sing_508.htm#SEC547 enveloping algebra sing_406.htm#IDX203 enveloping algebra sing_546.htm#IDX295 environment variable, DISPLAY The online help system sing_16.htm#IDX29 equalJinI sing_1513.htm#SEC1588 equalMultiDeg sing_2368.htm#SEC2443 equations sing_199.htm#SEC238 equiRadical sing_1329.htm#SEC1404 equidim sing_1331.htm#SEC1406 equidimMax sing_1332.htm#SEC1407 equidimMaxEHV sing_1333.htm#SEC1408 equidimZ sing_1344.htm#SEC1419 equising.lib sing_1553.htm#SEC1628 equising_lib sing_1553.htm#SEC1628 equisingular Tjurina number sing_1496.htm#IDX562 equisingularity ideal sing_1555.htm#IDX582 equisingularity stratum sing_1556.htm#IDX583 error recovery sing_15.htm#SEC21 errorInsert sing_1842.htm#SEC1917 errorRand sing_1843.htm#SEC1918 errormap sing_2262.htm#SEC2337 esIdeal sing_1555.htm#SEC1630 esStratum sing_1556.htm#SEC1631 essential sing_2142.htm#IDX810 essential sing_2143.htm#IDX811 eta sing_2049.htm#SEC2124 euler sing_1891.htm#SEC1966 eulerChProj sing_2210.htm#SEC2285 eval sing_286.htm#SEC325 evaluateFormalDivisor evaluateFormalDivisor sing_2240.htm#SEC2315 evaluatePDivisor sing_2246.htm#SEC2321 evaluate_reynolds sing_1676.htm#SEC1751 evalutateIntegral sing_1176.htm#SEC1251 example sing_288.htm#SEC327 example sing_2144.htm#IDX812 example sing_2145.htm#IDX814 example sing_2146.htm#IDX816 example sing_2147.htm#IDX818 example sing_2148.htm#IDX820 example sing_2149.htm#IDX822 example sing_2150.htm#IDX825 execute sing_289.htm#SEC328 exit sing_438.htm#SEC477 exp2pt sing_1879.htm#SEC1954 expo sing_1903.htm#SEC1978 exponents sing_2154.htm#IDX833 export sing_431.htm#SEC470 exportNuminvs sing_1296.htm#SEC1371 10423 exportto sing_432.htm#SEC471 expression list sing_72.htm#IDX129 expression list sing_470.htm#IDX288 ext-module purityfiltration_lib sing_793.htm#IDX357 extcurve sing_1825.htm#SEC1900 extdevelop sing_1587.htm#SEC1662 extend sing_963.htm#SEC1038 extendWeyl sing_827.htm#SEC878 extendedTensor sing_759.htm#SEC810 extendring sing_1034.htm#SEC1109 extension of rings sing_1349.htm#IDX511 exterior basis sing_1106.htm#IDX447 exterior power sing_1108.htm#IDX449 exteriorBasis sing_1106.htm#SEC1181 exteriorPower sing_1108.htm#SEC1183 extgcd sing_290.htm#SEC329 fVector sing_227.htm#SEC266 fVector sing_2416.htm#SEC2491 fVectorP(polymake) sing_2416.htm#SEC2491 facFirstShift sing_746.htm#SEC797 facFirstWeyl sing_742.htm#SEC793 facGBIdeal sing_1314.htm#SEC1389 facShift sing_745.htm#SEC796 facSubWeyl sing_744.htm#SEC795 facWeyl sing_741.htm#SEC792 facetVertexLatticeDistances facetVertexLatticeDistances sing_2413.htm#SEC2488 facetWidth sing_2414.htm#SEC2489 facetWidths sing_2415.htm#SEC2490 facets sing_200.htm#SEC239 facstd sing_291.htm#SEC330 factmodd sing_292.htm#SEC331 factorH sing_954.htm#SEC1029 factorLenstraECM sing_1942.htm#SEC2017 factorMain sing_1779.htm#SEC1854 factorgroup sing_2358.htm#SEC2433 factorial sing_940.htm#SEC1015 factorization sing_1136.htm#IDX451 factorize sing_293.htm#SEC332 factory sing_1.htm#IDX2 fan sing_221.htm#SEC260 fan sing_2038.htm#IDX731 fan related functions fan related functions sing_222.htm#SEC261 fanViaCones sing_225.htm#SEC264 farey sing_294.htm#SEC333 fastExpt sing_1887.htm#SEC1962 fastHC, option sing_364.htm#IDX149 fastelim sing_1741.htm#SEC1816 fetch sing_295.htm#SEC334 fetch (plural) sing_509.htm#SEC548 fetchall sing_1035.htm#SEC1110 ffsolve sing_1730.htm#SEC1805 ffsolve.lib sing_1729.htm#SEC1804 ffsolve_lib sing_1729.htm#SEC1804 fglm sing_296.htm#SEC335 fglm sing_403.htm#IDX183 fglm_solve sing_1757.htm#SEC1832 fglmquot sing_297.htm#SEC336 fibonacci sing_941.htm#SEC1016 field sing_139.htm#SEC178 file, .singularrc sing_20.htm#IDX72 filecmd sing_298.htm#SEC337 filtration purityfiltration_lib sing_793.htm#IDX358 finalCharts sing_1449.htm#SEC1524 find sing_299.htm#SEC338 findAuto sing_701.htm#SEC752 findInvo sing_699.htm#SEC750 findInvoDiag sing_700.htm#SEC751 findOrientedBoundary findOrientedBoundary sing_2050.htm#SEC2125 findTorsion sing_1868.htm#SEC1943 find_first_primitive_root find_first_primitive_root sing_1946.htm#SEC2021 find_index sing_1950.htm#SEC2025 findifs.lib sing_1875.htm#SEC1950 findifs_example sing_1876.htm#SEC1951 findifs_lib sing_1875.htm#SEC1950 findimAlgebra sing_768.htm#SEC819 finduni sing_300.htm#SEC339 findvars sing_1742.htm#SEC1817 finite field sing_139.htm#SEC178 finite field sing_1729.htm#IDX704 finiteDiagInvariants finiteDiagInvariants sing_1291.htm#SEC1366 3508 finitediff.lib sing_2248.htm#IDX873 finitediff_lib sing_2248.htm#IDX874 finitenessTest sing_1150.htm#SEC1225 finvar.lib sing_1664.htm#SEC1739 finvar_lib sing_1664.htm#SEC1739 first index is 1 sing_465.htm#SEC504 firstoct sing_1790.htm#SEC1865 fitting sing_1196.htm#SEC1271 fl2poly sing_638.htm#SEC689 flatten sing_1081.htm#SEC1156 flatteningStrat sing_1197.htm#SEC1272 floating point sing_1044.htm#IDX434 for sing_433.htm#SEC472 formaldivisorplus sing_2241.htm#SEC2316 forward sing_2254.htm#SEC2329 fourier sing_633.htm#SEC684 fouriersystem sing_2265.htm#SEC2340 fpadim.lib sing_649.htm#SEC700 fpadim_lib sing_649.htm#SEC700 fprintf sing_301.htm#SEC340 frandwalk sing_2388.htm#SEC2463 free sing_2153.htm#IDX830 free sing_2154.htm#IDX832 free associative algebra, tensor algebra Free associative algebras sing_540.htm#SEC591 freeGBasis sing_684.htm#SEC735 freegb.lib sing_680.htm#SEC731 freegb_lib sing_680.htm#SEC731 freemodule sing_302.htm#SEC341 freerank sing_992.htm#SEC1067 from_boolean_constant from_boolean_constant sing_2111.htm#SEC2186 44881 from_boolean_ideal sing_2115.htm#SEC2190 62698 from_boolean_poly sing_2112.htm#SEC2187 27864 from_boolean_set sing_2116.htm#SEC2191 60615 frwalk sing_303.htm#SEC342 fullFan sing_226.htm#SEC265 fullSerreRelations sing_695.htm#SEC746 furtherInvar sing_1708.htm#SEC1783 further_hn_proc sing_1604.htm#SEC1679 fwalk sing_1183.htm#SEC1258 galois field sing_139.htm#SEC178 gauss_col sing_1091.htm#SEC1166 gauss_nf sing_1122.htm#SEC1197 gauss_row sing_1092.htm#SEC1167 gaussred sing_1120.htm#SEC1195 gaussred_pivot sing_1121.htm#SEC1196 gcd sing_304.htm#SEC343 gcdMon sing_1223.htm#SEC1298 gcddivisor sing_1978.htm#SEC2053 gen sing_305.htm#SEC344 genMDSMat sing_1845.htm#SEC1920 genSymId sing_1368.htm#SEC1443 general error-locator polynomial sing_919.htm#SEC983 general neron. sing_2286.htm#IDX881 general weighted lexicographical ordering sing_894.htm#IDX399 general weighted reverse lexicographical ordering Local orderings sing_894.htm#IDX396 general.lib sing_934.htm#SEC1009 generalOrder sing_2003.htm#SEC2078 general_lib sing_934.htm#SEC1009 generateG sing_1941.htm#SEC2016 generators sing_1504.htm#IDX566 generatorsOfLinealitySpace generatorsOfLinealitySpace sing_201.htm#SEC240 generatorsOfSpan sing_202.htm#SEC241 genericid sing_1010.htm#SEC1085 genericity sing_1865.htm#SEC1940 genericmat sing_1082.htm#SEC1157 genoutput sing_1438.htm#SEC1513 genus sing_1274.htm#SEC1349 geometric invariant theory sing_2279.htm#IDX878 geometrical locus, locus, loci, dynamic geometry sing_966.htm#IDX418 geometrical locus, locus, loci, envelop sing_967.htm#IDX419 geometrical locus, locus, loci, envelop. sing_968.htm#IDX420 geometrical locus, locus, loci. sing_965.htm#IDX417 geometrical locus, locus, loci. sing_969.htm#IDX421 getArguments sing_1072.htm#SEC1147 getCommand sing_1071.htm#SEC1146 getCone sing_228.htm#SEC267 getGradingGroup sing_2333.htm#SEC2408 getLattice sing_2334.htm#SEC2409 getLinearForms sing_203.htm#SEC242 getModuleGrading sing_2344.htm#SEC2419 getMultiplicity sing_204.htm#SEC243 getOneVar sing_1282.htm#SEC1357 getResult sing_1073.htm#SEC1148 getSmallest sing_1281.htm#SEC1356 getState sing_1074.htm#SEC1149 getVariableWeights sing_2332.htm#SEC2407 getcores sing_1025.htm#SEC1100 getdump sing_306.htm#SEC345 getenv sing_406.htm#IDX205 gfanlib sing_1.htm#IDX9 gfanlib_so sing_2401.htm#IDX898 gitCone sing_2281.htm#SEC2356 gitFan sing_2282.htm#SEC2357 gitfan sing_2279.htm#IDX876 gitfan.lib sing_2279.htm#SEC2354 gitfan_lib sing_2279.htm#SEC2354 gkdim.lib sing_706.htm#SEC757 gkdim_lib sing_706.htm#SEC757 gkzFan sing_2283.htm#SEC2358 global Bernstein-Sato polynomial sing_553.htm#IDX302 global Bernstein-Sato polynomial sing_588.htm#IDX320 global Bernstein-Sato polynomial for variety sing_644.htm#IDX345 globalSections sing_2235.htm#SEC2310 gmscoeffs sing_1562.htm#SEC1637 gmsnf sing_1561.htm#SEC1636 gmspoly.lib sing_1581.htm#SEC1656 gmspoly_lib sing_1581.htm#SEC1656 gmsring sing_1560.htm#SEC1635 gmssing.lib sing_1559.htm#SEC1634 gmssing_lib sing_1559.htm#SEC1634 good basis sing_1559.htm#IDX594 good basis sing_1569.htm#IDX649 good basis sing_1581.htm#IDX665 good basis sing_1583.htm#IDX676 goodBasis sing_1583.htm#SEC1658 gorensteinIndex sing_2417.htm#SEC2492 gorensteinVector sing_2418.htm#SEC2493 graal.lib sing_2272.htm#SEC2347 graalMixed sing_2273.htm#SEC2348 graal_lib sing_2272.htm#SEC2347 gradeNumber sing_797.htm#SEC848 graded Weyl algebra sing_553.htm#IDX305 graded module, graded piece sing_1485.htm#IDX552 graded modules, graded homomorphisms, syzygies gradedModules_lib sing_2288.htm#IDX882 graded modules, handling of Handling graded modules sing_861.htm#SEC912 gradedModules.lib sing_2288.htm#SEC2363 gradedModules_lib sing_2288.htm#SEC2363 gradiator sing_2377.htm#SEC2452 graph sing_1172.htm#IDX463 graph sing_1173.htm#IDX464 graphics.lib sing_1792.htm#SEC1867 graphics_lib sing_1792.htm#SEC1867 graphviz sing_1.htm#IDX13 graver4ti2 sing_1366.htm#SEC1441 39635 grconcat sing_2311.htm#SEC2386 grdeg sing_2291.htm#SEC2366 grgens sing_2300.htm#SEC2375 grgroebner sing_2310.htm#SEC2385 grlift sing_2308.htm#SEC2383 grlifting sing_2315.htm#SEC2390 grlifting2 sing_2316.htm#SEC2391 grlifting3 sing_2318.htm#SEC2393 grneg sing_2321.htm#SEC2396 grobcov sing_956.htm#SEC1031 grobcov.lib sing_955.htm#SEC1030 grobcov_lib sing_955.htm#SEC1030 grobj sing_2289.htm#SEC2364 groebner sing_307.htm#SEC346 groebner sing_853.htm#SEC904 groebner basis computations sing_307.htm#IDX143 groebnerComplex sing_2408.htm#SEC2483 groebnerCone sing_2404.htm#SEC2479 groebnerFan sing_2406.htm#SEC2481 groebnerFanP sing_2043.htm#SEC2118 gromovWitten sing_1177.htm#SEC1252 grorder sing_2302.htm#SEC2377 ground field sing_139.htm#SEC178 group_reynolds sing_1672.htm#SEC1747 grpower sing_2298.htm#SEC2373 grpres sing_2301.htm#SEC2376 grprod sing_2309.htm#SEC2384 grrange sing_2320.htm#SEC2395 grres sing_2307.htm#SEC2382 grrndmap sing_2313.htm#SEC2388 grrndmap2 sing_2314.htm#SEC2389 grrndmat sing_2312.htm#SEC2387 grshift sing_2293.htm#SEC2368 grsum sing_2297.htm#SEC2372 grsyz sing_2306.htm#SEC2381 grtest sing_2290.htm#SEC2365 grtranspose sing_2299.htm#SEC2374 grtranspose1 sing_2303.htm#SEC2378 grtwist sing_2295.htm#SEC2370 grtwists sing_2296.htm#SEC2371 grview sing_2292.htm#SEC2367 grwalk.lib sing_1182.htm#SEC1257 grwalk_lib sing_1182.htm#SEC1257 grzero sing_2294.htm#SEC2369 gwalk sing_1188.htm#SEC1263 hStarVector sing_2420.htm#SEC2495 hVector sing_2421.htm#SEC2496 h_increasing_knapsack h_increasing_knapsack sing_1964.htm#SEC2039 hardware platform sing_406.htm#IDX260 hasAlgExtensionCoefficient hasAlgExtensionCoefficient sing_1049.htm#SEC1124 hasCommutativeVars sing_1045.htm#SEC1120 hasFieldCoefficient sing_1048.htm#SEC1123 hasGlobalOrdering sing_1046.htm#SEC1121 hasMixedOrdering sing_1047.htm#SEC1122 hasNumericCoeffs sing_1044.htm#SEC1119 headStand sing_1104.htm#SEC1179 heightZ sing_1343.htm#SEC1418 help sing_308.htm#SEC347 help browsers The online help system sing_16.htm#IDX22 help browsers, dummy The online help system sing_16.htm#IDX25 help browsers, dummy sing_16.htm#IDX27 help browsers, emacs The online help system sing_16.htm#IDX26 help browsers, html The online help system sing_16.htm#IDX23 help browsers, setting command to use The online help system sing_16.htm#IDX30 help browsers, setting the sing_406.htm#IDX189 help, accessing over the net Command line options sing_19.htm#IDX42 help, online help system The online help system sing_16.htm#SEC22 hermiteNormalForm sing_2378.htm#SEC2453 hess.lib sing_2323.htm#SEC2398 hess_lib sing_2323.htm#SEC2398 hessenberg sing_406.htm#IDX211 hessenberg sing_1126.htm#SEC1201 highcorner sing_309.htm#SEC348 hilb sing_310.htm#SEC349 hilbPoly sing_1008.htm#SEC1083 hilbert4ti2 sing_1365.htm#SEC1440 13993 hilbertBasis sing_2419.htm#SEC2494 hilbertSeries sing_2380.htm#SEC2455 hilbvec sing_1743.htm#SEC1818 hnexpansion sing_1585.htm#SEC1660 hnoether.lib sing_1584.htm#SEC1659 hnoether_lib sing_1584.htm#SEC1659 holonomic rank sing_815.htm#IDX369 holonomicRank sing_819.htm#SEC870 hom_kernel sing_1204.htm#SEC1279 homog sing_311.htm#SEC350 homogeneitySpace sing_2403.htm#SEC2478 homogfacFirstQWeyl sing_748.htm#SEC799 homogfacFirstQWeyl_all homogfacFirstQWeyl_all sing_750.htm#SEC801 homogfacNthQWeyl sing_747.htm#SEC798 homogfacNthQWeyl_all homogfacNthQWeyl_all sing_749.htm#SEC800 homolog.lib sing_1189.htm#SEC1264 homolog_lib sing_1189.htm#SEC1264 homology sing_1199.htm#SEC1274 howto, download Download instructions sing_2458.htm#SEC2545 howto, install on Macintosh Macintosh installation instructions sing_2461.htm#SEC2548 howto, install on Unix Unix installation instructions sing_2459.htm#SEC2546 howto, install on Windows Windows installation instructions sing_2460.htm#SEC2547 hres sing_312.htm#SEC351 html, default help The online help system sing_16.htm#IDX24 hyperel.lib sing_1971.htm#SEC2046 hyperel_lib sing_1971.htm#SEC2046 hyperplane sing_2123.htm#IDX770 hyperplane arrangement sing_588.htm#IDX326 hypersurface singularity sing_1611.htm#IDX694 iMult sing_1277.htm#SEC1352 id2mod sing_1004.htm#SEC1079 ideal sing_85.htm#SEC124 ideal declarations sing_86.htm#SEC125 ideal declarations (plural) ideal declarations (plural) sing_472.htm#SEC511 ideal expressions sing_87.htm#SEC126 ideal expressions (plural) ideal expressions (plural) sing_473.htm#SEC512 ideal operations sing_88.htm#SEC127 ideal operations (plural) ideal operations (plural) sing_474.htm#SEC513 ideal related functions ideal related functions sing_89.htm#SEC128 ideal related functions (plural) ideal related functions (plural) sing_475.htm#SEC514 ideal, toric sing_906.htm#SEC962 idealSplit sing_1750.htm#SEC1825 ideals Miscellaneous oddities sing_466.htm#IDX282 idealsimplify sing_1512.htm#SEC1587 identifier Identifier resolution sing_467.htm#SEC506 identifyvar sing_1420.htm#SEC1495 if sing_434.htm#SEC473 imageLattice sing_2346.htm#SEC2421 image_of_variety sing_1700.htm#SEC1775 imap sing_313.htm#SEC352 imap (plural) sing_510.htm#SEC549 imapall sing_1036.htm#SEC1111 impart sing_314.htm#SEC353 importfrom sing_435.htm#SEC474 inCenter sing_577.htm#SEC628 inCentralizer sing_578.htm#SEC629 inForm sing_620.htm#SEC671 inSubring sing_1142.htm#SEC1217 indSet sing_1249.htm#SEC1324 indepSet sing_315.htm#SEC354 indexed names sing_36.htm#IDX83 indexed names sing_37.htm#SEC64 inequalities sing_205.htm#SEC244 infRedTail, option sing_364.htm#IDX150 info The online help system sing_16.htm#SEC23 iniD sing_1440.htm#SEC1515 init_debug sing_1519.htm#SEC1594 initial sing_2402.htm#SEC2477 initial form sing_553.htm#IDX307 initial ideal sing_553.htm#IDX306 initial ideal approach sing_553.htm#IDX310 initial ideal approach sing_644.htm#IDX349 initialForm sing_2076.htm#SEC2151 initialIdeal sing_2077.htm#SEC2152 initialIdealW sing_619.htm#SEC670 initialMalgrange sing_618.htm#SEC669 injective_knapsack sing_1965.htm#SEC2040 inout.lib sing_970.htm#SEC1045 inout_lib sing_970.htm#SEC1045 input sing_41.htm#SEC70 insert sing_316.htm#SEC355 insertCone sing_229.htm#SEC268 insertGenerator sing_639.htm#SEC690 instructions, Macintosh installation Macintosh installation instructions sing_2461.htm#SEC2548 instructions, Unix installation Unix installation instructions sing_2459.htm#SEC2546 instructions, Windows installation Windows installation instructions sing_2460.htm#SEC2547 instructions, downloading Download instructions sing_2458.htm#SEC2545 int sing_90.htm#SEC129 int declarations sing_91.htm#SEC130 int expressions sing_92.htm#SEC131 int operations sing_93.htm#SEC132 int related functions int related functions sing_94.htm#SEC133 intInverse sing_2355.htm#SEC2430 intPart sing_1919.htm#SEC1994 intRank sing_2347.htm#SEC2422 intRoot sing_1920.htm#SEC1995 intRoots sing_636.htm#SEC687 intStrategy, option sing_364.htm#IDX151 intclMonIdeal sing_1289.htm#SEC1364 22338 intclToricRing sing_1285.htm#SEC1360 62143 integer division Miscellaneous oddities sing_466.htm#IDX277 integer programming sing_914.htm#SEC970 integral basis sing_1211.htm#IDX483 integral basis sing_1403.htm#IDX537 integral closure sing_1270.htm#IDX496 integral closure sing_1271.htm#IDX499 integral closure sing_1272.htm#IDX502 integral closure sing_1284.htm#IDX506 integralBasis sing_1211.htm#SEC1286 integralIdeal sing_623.htm#SEC674 integralModule sing_624.htm#SEC675 integralSection sing_2356.htm#SEC2431 integralbasis.lib sing_1210.htm#SEC1285 integralbasis_lib sing_1210.htm#SEC1285 integration of D-module sing_611.htm#IDX338 interface, Emacs Emacs user interface sing_21.htm#SEC28 interiorLatticePoints interiorLatticePoints sing_2422.htm#SEC2497 internalfunctions sing_1520.htm#SEC1595 interpolate sing_1756.htm#SEC1831 interpolation sing_317.htm#SEC356 interred sing_318.htm#SEC357 intersect sing_319.htm#SEC358 intersect (plural) sing_511.htm#SEC550 intersectElim, option sing_364.htm#IDX169 intersectLattices sing_2352.htm#SEC2427 intersectMon sing_1226.htm#SEC1301 intersectSyz, option sing_364.htm#IDX170 intersectZ sing_1345.htm#SEC1420 intersection sing_1594.htm#SEC1669 intersection lattice sing_2159.htm#IDX845 intersection lattice sing_2160.htm#IDX846 intersection multiplicity sing_1505.htm#IDX572 intersection multiplicity sing_1594.htm#IDX687 intersectionDiv sing_1468.htm#SEC1543 intersectionValRingIdeals intersectionValRingIdeals sing_1294.htm#SEC1369 38773 intersectionValRings intersectionValRings sing_1293.htm#SEC1368 35761 intmat sing_97.htm#SEC136 intmat declarations sing_98.htm#SEC137 intmat expressions sing_99.htm#SEC138 intmat operations sing_101.htm#SEC140 intmat related functions intmat related functions sing_102.htm#SEC141 intmat type cast sing_100.htm#SEC139 intmat2mons sing_1309.htm#SEC1384 21150 intprog.lib sing_1212.htm#SEC1287 intprog_lib sing_1212.htm#SEC1287 intvec sing_103.htm#SEC142 intvec declarations sing_104.htm#SEC143 intvec expressions sing_105.htm#SEC144 intvec operations sing_106.htm#SEC145 intvec related functions intvec related functions sing_107.htm#SEC146 invariant ring minimal generating set matrix group invariant_algebra_reynolds sing_1669.htm#IDX700 invariant ring minimal generating set permutation group invariant_algebra_perm sing_1670.htm#IDX701 invariantRing sing_1702.htm#SEC1777 invariant_algebra_perm invariant_algebra_perm sing_1670.htm#SEC1745 invariant_algebra_reynolds invariant_algebra_reynolds sing_1669.htm#SEC1744 invariant_basis sing_1677.htm#SEC1752 invariant_basis_reynolds invariant_basis_reynolds sing_1678.htm#SEC1753 invariant_ring sing_1665.htm#SEC1740 invariant_ring_random invariant_ring_random sing_1666.htm#SEC1741 invariants sing_1590.htm#SEC1665 inverse sing_1110.htm#SEC1185 inverse of a matrix via its LU-decomposition sing_339.htm#SEC378 inverseFourier sing_634.htm#SEC685 inverse_B sing_1111.htm#SEC1186 inverse_L sing_1112.htm#SEC1187 inverse_modulus sing_1948.htm#SEC2023 invertBirMap sing_1404.htm#SEC1479 invertNumberMain sing_1780.htm#SEC1855 involut.lib sing_698.htm#SEC749 involut_lib sing_698.htm#SEC749 involution sing_703.htm#SEC754 invunit sing_1613.htm#SEC1688 iostruct sing_1867.htm#SEC1942 irrRealizationDim sing_2058.htm#SEC2133 irred_secondary_char0 irred_secondary_char0 sing_1691.htm#SEC1766 irred_secondary_no_molien irred_secondary_no_molien sing_1694.htm#SEC1769 irreddecMon sing_1235.htm#SEC1310 irreducible power series sing_1595.htm#IDX688 irreducible secondary invariant irred_secondary_char0 sing_1691.htm#IDX702 isAface sing_2284.htm#SEC2359 isAntiEndo sing_705.htm#SEC756 isBounded sing_2423.htm#SEC2498 isCI sing_261.htm#IDX136 isCI sing_1160.htm#SEC1235 isCM sing_261.htm#IDX137 isCM sing_1200.htm#SEC1275 isCMcod2 sing_1648.htm#SEC1723 isCanonical sing_2424.htm#SEC2499 isCartan sing_579.htm#SEC630 isCentral sing_775.htm#SEC826 isCommutative sing_777.htm#SEC828 isCompatible sing_230.htm#SEC269 isCompressed sing_2425.htm#SEC2500 isEqualDivisor sing_2234.htm#SEC2309 isEquising sing_1557.htm#SEC1632 isFlat sing_1201.htm#SEC1276 isFsat sing_629.htm#SEC680 isFullSpace sing_206.htm#SEC245 isGorenstein sing_2426.htm#SEC2501 isGradedRingHomomorphism isGradedRingHomomorphism sing_2341.htm#SEC2416 isGroup sing_2339.htm#SEC2414 isGroupHomomorphism sing_2340.htm#SEC2415 isHolonomic sing_607.htm#SEC658 isHomg sing_261.htm#IDX133 isHomogeneous sing_2367.htm#SEC2442 isInt sing_642.htm#SEC693 isIntegralSurjective isIntegralSurjective sing_2353.htm#SEC2428 isInvolution sing_704.htm#SEC755 isLatticeEmpty sing_2427.htm#SEC2502 isLocalizationRegular isLocalizationRegular sing_2276.htm#SEC2351 isLocallyFree sing_1202.htm#SEC1277 isMonomial sing_1221.htm#SEC1296 isNC sing_776.htm#SEC827 isNormal sing_2428.htm#SEC2503 isOnCurve sing_1932.htm#SEC2007 isOrigin sing_207.htm#SEC246 isPositive sing_2364.htm#SEC2439 isPrimitiveSublattice isPrimitiveSublattice sing_2354.htm#SEC2429 isPure sing_231.htm#SEC270 isPureTensor sing_551.htm#SEC602 isQuotientRing sing_1050.htm#SEC1125 isRational sing_610.htm#SEC661 isReflexive sing_2429.htm#SEC2504 isReg sing_1203.htm#SEC1278 isSB sing_261.htm#IDX132 isSimplicial sing_208.htm#SEC247 isSmooth sing_2430.htm#SEC2505 isSubModule sing_1051.htm#SEC1126 isSublattice sing_2345.htm#SEC2420 isSymmetric sing_1369.htm#SEC1444 isTame sing_1582.htm#SEC1657 isTerminal sing_2431.htm#SEC2506 isTorsionFree sing_2363.htm#SEC2438 isTwoSidedGB sing_552.htm#SEC603 isUpperTriangular sing_756.htm#SEC807 isVar sing_696.htm#SEC747 isVeryAmple sing_2432.htm#SEC2507 isWeyl sing_778.htm#SEC829 isZeroElement sing_2365.htm#SEC2440 is_NND sing_1598.htm#SEC1673 is_NP sing_1258.htm#SEC1333 is_active sing_1631.htm#SEC1706 is_bijective sing_1147.htm#SEC1222 is_cenBimodule sing_811.htm#SEC862 is_cenSubbimodule sing_812.htm#SEC863 is_ci sing_1632.htm#SEC1707 is_complex sing_1083.htm#SEC1158 is_fix_injective sing_1969.htm#SEC2044 is_h_injective sing_1968.htm#SEC2043 is_injective sing_1145.htm#SEC1220 is_irred sing_1595.htm#SEC1670 is_is sing_1633.htm#SEC1708 is_nested sing_1259.htm#SEC1334 is_prime sing_1949.htm#SEC2024 is_primitive_root sing_1945.htm#SEC2020 is_pure sing_803.htm#SEC854 is_reg sing_1634.htm#SEC1709 is_regs sing_1635.htm#SEC1710 is_surjective sing_1146.htm#SEC1221 is_zero sing_993.htm#SEC1068 isartinianMon sing_1232.htm#SEC1307 isgenericMon sing_1233.htm#SEC1308 ishyper sing_1972.htm#SEC2047 isirreducibleMon sing_1231.htm#SEC1306 isoncurve sing_1973.htm#SEC2048 isparam sing_2036.htm#SEC2111 isprimaryMon sing_1230.htm#SEC1305 isprimeMon sing_1229.htm#SEC1304 isuni sing_2021.htm#SEC2096 iv2lp sing_674.htm#SEC725 iv2lpList sing_675.htm#SEC726 iv2lpMat sing_676.htm#SEC727 ivDHilbert sing_650.htm#SEC701 ivDHilbertSickle sing_651.htm#SEC702 ivDimCheck sing_652.htm#SEC703 ivHilbert sing_653.htm#SEC704 ivKDim sing_654.htm#SEC705 ivL2lpI sing_673.htm#SEC724 ivMis2Base sing_655.htm#SEC706 ivMis2Dim sing_656.htm#SEC707 ivOrdMisLex sing_657.htm#SEC708 ivSickle sing_658.htm#SEC709 ivSickleDim sing_660.htm#SEC711 ivSickleHil sing_659.htm#SEC710 jInvariant sing_2070.htm#SEC2145 jOft sing_1904.htm#SEC1979 jacob sing_320.htm#SEC359 jacoblift sing_1614.htm#SEC1689 jacobson sing_1873.htm#SEC1948 jacobson.lib sing_1871.htm#SEC1946 jacobson_lib sing_1871.htm#SEC1946 janet sing_321.htm#SEC360 jet sing_322.htm#SEC361 jordan sing_1131.htm#SEC1206 jordanbasis sing_1132.htm#SEC1207 jordanmatrix sing_1133.htm#SEC1208 jordannf sing_1134.htm#SEC1209 jungfib sing_1453.htm#SEC1528 jungnormal sing_1452.htm#SEC1527 jungresolve sing_1451.htm#SEC1526 katsura sing_991.htm#SEC1066 kbase sing_323.htm#SEC362 kbase (plural) sing_512.htm#SEC551 keepring sing_436.htm#SEC475 kernel sing_324.htm#SEC363 kernelLattice sing_2348.htm#SEC2423 kill sing_325.htm#SEC364 killTask sing_1062.htm#SEC1137 killall sing_943.htm#SEC1018 killattrib sing_326.htm#SEC365 kmemory sing_942.htm#SEC1017 kohom sing_1205.htm#SEC1280 kontrahom sing_1206.htm#SEC1281 koszul sing_327.htm#SEC366 kskernel.lib sing_1605.htm#SEC1680 kskernel_lib sing_1605.htm#SEC1680 l-adic numbers sing_32.htm#SEC45 laguerre sing_328.htm#SEC367 laguerre_solve sing_1752.htm#SEC1827 lastvarGeneral sing_2002.htm#SEC2077 latex.lib sing_1796.htm#SEC1871 latex_lib sing_1796.htm#SEC1871 lattice sing_2160.htm#IDX848 latticeArea sing_2052.htm#SEC2127 latticeBasis sing_2349.htm#SEC2424 latticeCodegree sing_2433.htm#SEC2508 latticeDegree sing_2434.htm#SEC2509 latticePoints sing_2435.htm#SEC2510 latticeVolume sing_2436.htm#SEC2511 laxfrT sing_2252.htm#SEC2327 laxfrX sing_2253.htm#SEC2328 lazy, option sing_364.htm#IDX152 lcm sing_994.htm#SEC1069 lcmMon sing_1224.htm#SEC1299 lcmN sing_1913.htm#SEC1988 lcmofall sing_1433.htm#SEC1508 lead sing_329.htm#SEC368 leadcoef sing_330.htm#SEC369 leadexp sing_331.htm#SEC370 leadmonom sing_332.htm#SEC371 leadmonomial sing_1988.htm#SEC2063 left annihilator ideal sing_588.htm#IDX318 leftInverse sing_1862.htm#SEC1937 leftKernel sing_1860.htm#SEC1935 length, option sing_364.htm#IDX153 letplaceGBasis sing_682.htm#SEC733 letterplace correspondence Letterplace correspondence sing_542.htm#SEC593 lex_solve sing_1758.htm#SEC1833 lexicographical ordering sing_893.htm#IDX379 lib2doc sing_60.htm#SEC96 libcdd sing_1.htm#IDX12 libfac sing_1.htm#IDX6 libparse sing_69.htm#SEC108 library sing_2102.htm#IDX748 library sing_2279.htm#IDX875 library, info string sing_55.htm#IDX125 library, polybori.lib sing_2102.htm#IDX745 library, template sing_55.htm#SEC91 library, template.lib sing_55.htm#IDX123 lieBracket sing_693.htm#SEC744 lift sing_334.htm#SEC373 lift sing_546.htm#IDX294 lift (plural) sing_513.htm#SEC552 lift_kbase sing_1551.htm#SEC1626 lift_rel_kb sing_1552.htm#SEC1627 liftenvelope sing_549.htm#SEC600 liftstd sing_335.htm#SEC374 liftstd (plural) sing_514.htm#SEC553 linReduce sing_561.htm#SEC612 linReduceIdeal sing_562.htm#SEC613 linSyzSolve sing_563.htm#SEC614 linalg.lib sing_1109.htm#SEC1184 linalg_lib sing_1109.htm#SEC1184 linealityDimension sing_209.htm#SEC248 linealitySpace sing_210.htm#SEC249 linear algebra sing_262.htm#SEC301 linear algebra sing_338.htm#SEC377 linear algebra sing_339.htm#SEC378 linear algebra sing_340.htm#SEC379 linear code, dual sing_1831.htm#IDX713 linear code, systematic sing_1832.htm#IDX714 linear interreduction sing_553.htm#IDX309 linearCombinations sing_582.htm#SEC633 linearMapKernel sing_581.htm#SEC632 linear_relations sing_1101.htm#SEC1176 linearlyEquivalent sing_2237.htm#SEC2312 linearpart sing_1744.htm#SEC1819 link Parallelization with ssi links sing_108.htm#SEC147 link sing_850.htm#SEC901 link declarations sing_109.htm#SEC148 link expressions sing_110.htm#SEC149 link related functions link related functions sing_111.htm#SEC150 list sing_118.htm#SEC157 list declarations sing_119.htm#SEC158 list expressions sing_120.htm#SEC159 list operations sing_121.htm#SEC160 list related functions list related functions sing_122.htm#SEC161 listvar sing_336.htm#SEC375 lll sing_2381.htm#SEC2456 load sing_437.htm#SEC476 loadLib, option sing_364.htm#IDX174 loadProc, option sing_364.htm#IDX175 locAtZero sing_1279.htm#SEC1354 locNormal sing_1215.htm#SEC1290 local methods sing_1214.htm#IDX486 local methods sing_1215.htm#IDX489 local names sing_46.htm#SEC82 local rings, computing in Rings associated to monomial orderings sing_845.htm#SEC896 local weighted lexicographical ordering sing_894.htm#IDX400 local weighted reverse lexicographical ordering Local orderings sing_894.htm#IDX397 localInvar sing_1707.htm#SEC1782 localization Rings associated to monomial orderings sing_845.htm#SEC896 localization sing_2140.htm#IDX808 localization of D-module sing_611.htm#IDX334 localization of D-module sing_815.htm#IDX372 locally closed set, constructible set sing_964.htm#IDX416 localstd sing_1998.htm#SEC2073 locnormal.lib sing_1214.htm#SEC1289 locnormal_lib sing_1214.htm#SEC1289 locstd sing_1636.htm#SEC1711 locus sing_965.htm#SEC1040 locusdg sing_966.htm#SEC1041 locusto sing_969.htm#SEC1044 log2 sing_1888.htm#SEC1963 logarithmic annihilator ideal sing_588.htm#IDX323 lowerHomogeneitySpace lowerHomogeneitySpace sing_2407.htm#SEC2482 lp, global ordering sing_893.htm#IDX378 lp2iv sing_677.htm#SEC728 lp2ivId sing_678.htm#SEC729 lp2lstr sing_689.htm#SEC740 lpDHilbert sing_661.htm#SEC712 lpDHilbertSickle sing_662.htm#SEC713 lpDimCheck sing_664.htm#SEC715 lpHilbert sing_663.htm#SEC714 lpId2ivLi sing_679.htm#SEC730 lpKDim sing_665.htm#SEC716 lpMis2Base sing_666.htm#SEC717 lpMis2Dim sing_667.htm#SEC718 lpMult sing_686.htm#SEC737 lpNF sing_683.htm#SEC734 lpOrdMisLex sing_668.htm#SEC719 lpPower sing_688.htm#SEC739 lpSickle sing_669.htm#SEC720 lpSickleDim sing_671.htm#SEC722 lpSickleHil sing_670.htm#SEC721 lprint sing_972.htm#SEC1047 lres sing_337.htm#SEC376 ls, local ordering sing_894.htm#IDX391 lst2str sing_690.htm#SEC741 lsum sing_1181.htm#SEC1256 ludecomp sing_338.htm#SEC377 luinverse sing_339.htm#SEC378 lusolve sing_340.htm#SEC379 m_merkle_hellman_decryption m_merkle_hellman_decryption sing_1960.htm#SEC2035 m_merkle_hellman_encryption m_merkle_hellman_encryption sing_1959.htm#SEC2034 m_merkle_hellman_transformation m_merkle_hellman_transformation sing_1958.htm#SEC2033 magnitude sing_1882.htm#SEC1957 makeDivisor sing_2229.htm#SEC2304 makeFormalDivisor sing_2239.htm#SEC2314 makeGraph sing_1172.htm#SEC1247 makeHeisenberg sing_766.htm#SEC817 makeLetterplaceRing sing_681.htm#SEC732 makeMalgrange sing_648.htm#SEC699 makeModElimRing sing_783.htm#SEC834 makePDivisor sing_2245.htm#SEC2320 makeQsl2 sing_731.htm#SEC782 makeQsl3 sing_732.htm#SEC783 makeQso3 sing_730.htm#SEC781 makeUe6 sing_727.htm#SEC778 makeUe7 sing_728.htm#SEC779 makeUe8 sing_729.htm#SEC780 makeUf4 sing_726.htm#SEC777 makeUg2 sing_725.htm#SEC776 makeUgl sing_711.htm#SEC762 makeUsl sing_710.htm#SEC761 makeUsl2 sing_709.htm#SEC760 makeUso10 sing_717.htm#SEC768 makeUso11 sing_718.htm#SEC769 makeUso12 sing_719.htm#SEC770 makeUso5 sing_712.htm#SEC763 makeUso6 sing_713.htm#SEC764 makeUso7 sing_714.htm#SEC765 makeUso8 sing_715.htm#SEC766 makeUso9 sing_716.htm#SEC767 makeUsp1 sing_720.htm#SEC771 makeUsp2 sing_721.htm#SEC772 makeUsp3 sing_722.htm#SEC773 makeUsp4 sing_723.htm#SEC774 makeUsp5 sing_724.htm#SEC775 makeWeyl sing_765.htm#SEC816 map sing_123.htm#SEC162 map (plural) sing_476.htm#SEC515 map declarations sing_124.htm#SEC163 map declarations (plural) map declarations (plural) sing_477.htm#SEC516 map expressions sing_125.htm#SEC164 map expressions (plural) map expressions (plural) sing_478.htm#SEC517 map operations sing_126.htm#IDX130 map operations (plural) map operations (plural) sing_479.htm#IDX289 map related functions map related functions sing_127.htm#IDX131 map related functions (plural) map related functions (plural) sing_480.htm#IDX290 mapIsFinite sing_1149.htm#SEC1224 mapToRatNormCurve sing_1408.htm#SEC1483 mapall sing_1037.htm#SEC1112 mappingcone sing_2317.htm#SEC2392 mappingcone3 sing_2319.htm#SEC2394 markov4ti2 sing_1364.htm#SEC1439 9163 mat2arr sing_2125.htm#SEC2200 mat2carr sing_2126.htm#SEC2201 mat_rk sing_1123.htm#SEC1198 matbil sing_2009.htm#SEC2084 mathematical objects Representation of mathematical objects sing_889.htm#SEC940 mathinit sing_1794.htm#SEC1869 matmult sing_2010.htm#SEC2085 matrix sing_128.htm#SEC167 matrix sing_2125.htm#IDX776 matrix sing_2126.htm#IDX779 matrix sing_2127.htm#IDX783 matrix declarations sing_129.htm#SEC168 matrix diagonalization sing_1871.htm#IDX724 matrix expressions sing_130.htm#SEC169 matrix operations sing_132.htm#SEC171 matrix related functions matrix related functions sing_133.htm#SEC172 matrix type cast sing_131.htm#SEC170 matrix.lib sing_1076.htm#SEC1151 matrixExp sing_1398.htm#SEC1473 matrixLog sing_1399.htm#SEC1474 matrixT1 sing_1650.htm#SEC1725 matrix_lib sing_1076.htm#SEC1151 matrixpres sing_2322.htm#SEC2397 matrixsystem sing_2263.htm#SEC2338 max sing_341.htm#SEC380 maxEord sing_1423.htm#SEC1498 maxIntRoot sing_832.htm#SEC883 maxZeros sing_1401.htm#SEC1476 maxabs sing_2028.htm#SEC2103 maxcoef sing_995.htm#SEC1070 maxdeg sing_996.htm#SEC1071 maxdeg1 sing_997.htm#SEC1072 maxideal sing_342.htm#SEC381 maximalFace sing_2437.htm#SEC2512 maximalGroebnerCone sing_2405.htm#SEC2480 maximalValue sing_2438.htm#SEC2513 maximum sing_1901.htm#SEC1976 maximum number of zeroes sing_1401.htm#IDX531 mdouble sing_56.htm#SEC92 mem, option sing_364.htm#IDX176 membershipMon sing_1225.htm#SEC1300 memory sing_343.htm#SEC382 memory managment sing_343.htm#SEC382 merkle_hellman_decryption merkle_hellman_decryption sing_1962.htm#SEC2037 merkle_hellman_encryption merkle_hellman_encryption sing_1961.htm#SEC2036 midpoint sing_2259.htm#SEC2334 milnor sing_1637.htm#SEC1712 milnorcode sing_1521.htm#SEC1596 milnornumber sing_2395.htm#SEC2470 min sing_344.htm#SEC383 minAssChar sing_1323.htm#SEC1398 minAssCharE sing_1324.htm#SEC1399 minAssGTZ sing_1321.htm#SEC1396 minAssGTZE sing_1322.htm#SEC1397 minAssZ sing_1341.htm#SEC1416 minEcart sing_1991.htm#SEC2066 minIntRoot sing_609.htm#SEC660 minIntRoot2 sing_831.htm#SEC882 minMult sing_1156.htm#SEC1231 minbase sing_345.htm#SEC384 minbaseMon sing_1222.htm#SEC1297 mindeg sing_998.htm#SEC1073 mindeg1 sing_999.htm#SEC1074 mindist sing_1846.htm#SEC1921 minimal display time, setting the sing_406.htm#IDX273 minimalFace sing_2439.htm#SEC2514 minimalValue sing_2440.htm#SEC2515 minipoly sing_1128.htm#SEC1203 minkowskiSum sing_2441.htm#SEC2516 minor sing_346.htm#SEC385 minpoly sing_445.htm#SEC484 minres sing_347.htm#SEC386 minres (plural) sing_515.htm#SEC554 mirror symmetry sing_1171.htm#IDX456 mixed Hodge structure sing_1559.htm#IDX587 mixed Hodge structure sing_1565.htm#IDX615 mixed Hodge structure sing_1566.htm#IDX621 mixed Hodge structure sing_1567.htm#IDX629 mixed Hodge structure sing_1568.htm#IDX635 mixed Hodge structure sing_1569.htm#IDX643 mixed Hodge structure sing_1570.htm#IDX653 mixed Hodge structure sing_1581.htm#IDX659 mixed Hodge structure sing_1583.htm#IDX670 mod sing_76.htm#SEC115 mod sing_93.htm#SEC132 mod sing_142.htm#SEC181 mod2id sing_1003.htm#SEC1078 mod2str sing_691.htm#SEC742 modDec sing_1241.htm#SEC1316 modNPos sing_1264.htm#SEC1339 modNormal sing_1217.htm#SEC1292 modNpos_test sing_1262.htm#SEC1337 modStd sing_1219.htm#SEC1294 modWalk sing_2326.htm#SEC2401 mod_versal sing_1550.htm#SEC1625 modality sing_1529.htm#SEC1604 modfWalk sing_2328.htm#SEC2403 modfrWalk sing_2329.htm#SEC2404 modnormal.lib sing_1216.htm#SEC1291 modnormal_lib sing_1216.htm#SEC1291 modrWalk sing_2327.htm#SEC2402 modregCM sing_1268.htm#SEC1343 modsatiety sing_1266.htm#SEC1341 modstd.lib sing_1218.htm#SEC1293 modstd_lib sing_1218.htm#SEC1293 modular sing_981.htm#SEC1056 modular methods sing_1214.htm#IDX487 modular methods sing_1216.htm#IDX492 modular methods. sing_1215.htm#IDX490 modular techniques. sing_1217.htm#IDX494 modular.lib sing_980.htm#SEC1055 modular_lib sing_980.htm#SEC1055 modular_lib sing_980.htm#IDX422 module sing_134.htm#SEC173 module (plural) sing_481.htm#SEC520 module declarations sing_135.htm#SEC174 module declarations (plural) module declarations (plural) sing_482.htm#SEC521 module expressions sing_136.htm#SEC175 module expressions (plural) module expressions (plural) sing_483.htm#SEC522 module operations sing_137.htm#SEC176 module operations (plural) module operations (plural) sing_484.htm#SEC523 module ordering C sing_895.htm#IDX403 module ordering c sing_895.htm#IDX405 module related functions module related functions sing_138.htm#SEC177 module related functions (plural) module related functions (plural) sing_485.htm#SEC524 module_containment sing_1141.htm#SEC1216 modulo sing_348.htm#SEC387 modulo (plural) sing_516.htm#SEC555 moduloSlim sing_773.htm#SEC824 modwalk.lib sing_2325.htm#IDX883 modwalk_lib sing_2325.htm#IDX884 moebius sing_2161.htm#SEC2236 moebius function sing_2161.htm#IDX849 molien sing_1673.htm#SEC1748 mondromy.lib sing_1611.htm#SEC1686 mondromy_lib sing_1611.htm#SEC1686 monitor sing_349.htm#SEC388 monodromy sing_1559.htm#IDX591 monodromy sing_1564.htm#SEC1639 monodromy sing_1564.htm#IDX611 monodromy sing_1569.htm#IDX646 monodromy sing_1581.htm#IDX662 monodromy sing_1583.htm#IDX673 monodromyB sing_1615.htm#SEC1690 monomial sing_350.htm#SEC389 monomial ordering sing_1046.htm#IDX436 monomial orderings General definitions for orderings sing_845.htm#SEC896 monomial orderings sing_892.htm#SEC943 monomial orderings introduction Introduction to orderings sing_891.htm#SEC942 monomialInIdeal sing_829.htm#SEC880 monomialLcm sing_1989.htm#SEC2064 monomialideal.lib sing_1220.htm#SEC1295 monomialideal_lib sing_1220.htm#SEC1295 monomials and precedence Miscellaneous oddities sing_466.htm#IDX279 mons2intmat sing_1308.htm#SEC1383 15555 morsesplit sing_1522.htm#SEC1597 mp_res_mat sing_1755.htm#SEC1830 mplot sing_1795.htm#SEC1870 mpresmat sing_351.htm#SEC390 mprimdec.lib sing_1237.htm#SEC1312 mprimdec_lib sing_1237.htm#SEC1312 mregular.lib sing_1252.htm#SEC1327 mregular_lib sing_1252.htm#SEC1327 mres sing_352.htm#SEC391 mres (plural) sing_517.htm#SEC556 mstd sing_353.htm#SEC392 msum sing_58.htm#SEC94 mtriple sing_57.htm#SEC93 mult Miscellaneous oddities sing_354.htm#SEC393 mult sing_466.htm#IDX280 multBound sing_446.htm#SEC485 multRat sing_837.htm#SEC888 multarr2arr sing_2156.htm#SEC2231 multarrMultRestrict sing_2158.htm#SEC2233 multarrRestrict sing_2157.htm#SEC2232 multcol sing_1095.htm#SEC1170 multdivisor sing_2231.htm#SEC2306 multformaldivisor sing_2243.htm#SEC2318 multi sing_1976.htm#SEC2051 multi indices sing_37.htm#SEC64 multiDeg sing_2360.htm#SEC2435 multiDegBasis sing_2361.htm#SEC2436 multiDegGroebner sing_2369.htm#SEC2444 multiDegModulo sing_2371.htm#SEC2446 multiDegPartition sing_2362.htm#SEC2437 multiDegResolution sing_2372.htm#SEC2447 multiDegSyzygy sing_2370.htm#SEC2445 multiDegTensor sing_2373.htm#SEC2448 multiDegTor sing_2374.htm#SEC2449 multiarrangement sing_2152.htm#IDX829 multiarrangement sing_2153.htm#IDX831 multiarrangement sing_2154.htm#IDX834 multiarrangement sing_2155.htm#IDX835 multiarrangement sing_2156.htm#IDX838 multiarrangement sing_2157.htm#IDX841 multiarrangement sing_2158.htm#IDX843 multidimensional_knapsack multidimensional_knapsack sing_1954.htm#SEC2029 multigrading, multidegree, multiweights, multigraded-homogeneous, integral linear algebra multigrading_lib sing_2330.htm#IDX887 multigrading.lib sing_2330.htm#IDX885 multigrading_lib sing_2330.htm#IDX886 multiplicities, sequence of sing_1590.htm#IDX685 multiplicity sequence sing_1503.htm#IDX564 multiplicity sequence sing_1506.htm#IDX576 multiplicity sequence sing_1592.htm#IDX686 multiplylist sing_1443.htm#SEC1518 multivariate equations sing_1729.htm#IDX703 multrow sing_1096.htm#SEC1171 multseq2charexp sing_1502.htm#SEC1577 multsequence sing_1592.htm#SEC1667 nBoundaryLatticePoints nBoundaryLatticePoints sing_2442.htm#SEC2517 nHilbertBasis sing_2443.htm#SEC2518 nInteriorLatticePoints nInteriorLatticePoints sing_2444.htm#SEC2519 nLatticePoints sing_2445.htm#SEC2520 naccache_stern_decryption naccache_stern_decryption sing_1957.htm#SEC2032 naccache_stern_encryption naccache_stern_encryption sing_1956.htm#SEC2031 naccache_stern_generation naccache_stern_generation sing_1955.htm#SEC2030 nameof sing_355.htm#SEC394 names sing_356.htm#SEC395 nashmult sing_1510.htm#SEC1585 nblocks sing_406.htm#IDX215 ncExt_R sing_806.htm#SEC857 ncHom sing_807.htm#SEC858 ncRelations sing_774.htm#SEC825 nc_algebra sing_518.htm#SEC557 ncalg.lib sing_708.htm#SEC759 ncalg_lib sing_708.htm#SEC759 ncalgebra sing_519.htm#SEC558 ncdecomp.lib sing_735.htm#SEC786 ncdecomp_lib sing_735.htm#SEC786 ncdetection sing_702.htm#SEC753 ncfactor.lib sing_740.htm#SEC791 ncfactor_lib sing_740.htm#SEC791 nchomolog.lib sing_805.htm#IDX362 nchomolog_lib sing_805.htm#IDX363 ncols sing_357.htm#SEC396 ncones sing_233.htm#SEC272 ncpreim.lib sing_752.htm#SEC803 ncpreim_lib sing_752.htm#SEC803 nctools.lib sing_760.htm#SEC811 nctools_lib sing_760.htm#SEC811 ndcond sing_763.htm#SEC814 negatedCone sing_211.htm#SEC250 negative degree lexicographical ordering sing_894.htm#IDX394 negative degree reverse lexicographical ordering Local orderings sing_894.htm#IDX392 negative lexicographical ordering sing_894.htm#IDX390 negativedivisor sing_2232.htm#SEC2307 negativeformaldivisor negativeformaldivisor sing_2242.htm#SEC2317 net access Command line options sing_19.htm#IDX40 newTest sing_1896.htm#SEC1971 newline sing_166.htm#SEC205 news sing_2451.htm#SEC2526 newstruct sing_177.htm#SEC216 newstruct sing_2102.htm#IDX750 newtonDiag sing_1007.htm#SEC1082 newtonPolytope sing_241.htm#SEC280 newtonPolytopeLP sing_2041.htm#SEC2116 newtonPolytopeP sing_2040.htm#SEC2115 newtonpoly sing_1597.htm#SEC1672 nf_icis sing_1638.htm#SEC1713 nfmodStd sing_2384.htm#SEC2459 nfmodstd.lib sing_2382.htm#SEC2457 nfmodstd_lib sing_2382.htm#SEC2457 nilpotent Lie algebras sing_1396.htm#IDX516 nmaxcones sing_232.htm#SEC271 noether sing_447.htm#SEC486 noether.lib sing_1260.htm#SEC1335 noetherNormal sing_1148.htm#SEC1223 noether_lib sing_1260.htm#SEC1335 non-english special characters sing_455.htm#IDX275 nonMonomials sing_1312.htm#SEC1387 nonZeroEntry sing_1151.htm#SEC1226 none, option sing_364.htm#IDX146 norTest sing_1280.htm#SEC1355 norm sing_1975.htm#SEC2050 normal sing_1270.htm#SEC1345 normal.lib sing_1269.htm#SEC1344 normalC sing_1272.htm#SEC1347 normalFan sing_2446.htm#SEC2521 normalFanL sing_2042.htm#SEC2117 normalForm sing_2233.htm#SEC2308 normalI sing_1356.htm#SEC1431 normalP sing_1271.htm#SEC1346 normalToricRing sing_1286.htm#SEC1361 29638 normalToricRingFromBinomials normalToricRingFromBinomials sing_1287.htm#SEC1362 2301 normal_lib sing_1269.htm#SEC1344 normalform sing_1526.htm#SEC1601 normaliz sing_1.htm#IDX14 18426 normaliz sing_1299.htm#SEC1374 normaliz.lib sing_1284.htm#SEC1359 normaliz_lib sing_1284.htm#SEC1359 normalization sing_1214.htm#IDX485 normalization sing_1215.htm#IDX488 normalization sing_1216.htm#IDX491 normalization sing_1217.htm#IDX493 normalization sing_1270.htm#IDX495 normalization sing_1271.htm#IDX498 normalization sing_1272.htm#IDX501 normalization sing_1284.htm#IDX507 normalization. sing_1211.htm#IDX484 normalization. sing_1403.htm#IDX538 normalize sing_1000.htm#SEC1075 not sing_96.htm#SEC135 notBuckets, option sing_364.htm#IDX156 notRegularity, option sing_364.htm#IDX154 notSugar, option sing_364.htm#IDX155 notWarnSB, option sing_364.htm#IDX177 npar sing_1881.htm#SEC1956 npars sing_358.htm#SEC397 nrRootsDeterm sing_2006.htm#SEC2081 nrRootsProbab sing_2005.htm#SEC2080 nres sing_359.htm#SEC398 nres (plural) sing_520.htm#SEC559 nrows sing_360.htm#SEC399 nrroots sing_2035.htm#SEC2110 nsatiety sing_1265.htm#SEC1340 nselect sing_1167.htm#SEC1242 nt_solve sing_1770.htm#SEC1845 ntsolve.lib sing_1769.htm#SEC1844 ntsolve_lib sing_1769.htm#SEC1844 number sing_139.htm#SEC178 number sing_2129.htm#IDX789 number declarations sing_140.htm#SEC179 number expressions sing_141.htm#SEC180 number operations sing_142.htm#SEC181 number related functions number related functions sing_143.htm#SEC182 numberOfConesOfDimension numberOfConesOfDimension sing_234.htm#SEC273 number_e sing_944.htm#SEC1019 number_pi sing_945.htm#SEC1020 numerAlg.lib sing_1378.htm#IDX512 numerAlg_lib sing_1378.htm#IDX513 numerDecom.lib sing_1383.htm#IDX514 numerDecom_lib sing_1383.htm#IDX515 numerator sing_361.htm#SEC400 nvars sing_362.htm#SEC401 oneDimBelongSemigroup oneDimBelongSemigroup sing_1158.htm#SEC1233 online help The online help system sing_16.htm#SEC22 open sing_363.htm#SEC402 opentex sing_1798.htm#SEC1873 operatorBM sing_595.htm#SEC646 operatorModulo sing_596.htm#SEC647 oppose sing_521.htm#SEC560 opposite sing_522.htm#SEC561 opposite polynomial sing_406.htm#IDX222 opposite ring sing_406.htm#IDX219 option sing_364.htm#SEC403 option(warn) sing_70.htm#SEC109 optionIsSet sing_1043.htm#SEC1118 or Evaluation of logical expressions sing_96.htm#SEC135 or sing_459.htm#SEC498 orbit sing_1396.htm#IDX518 orbit sing_1397.htm#IDX522 orbit sing_1400.htm#IDX527 orbit sing_1401.htm#IDX530 orbitCones sing_2285.htm#SEC2360 orbit_variety sing_1697.htm#SEC1772 orbitparam.lib sing_1396.htm#SEC1471 orbitparam_lib sing_1396.htm#SEC1471 ord sing_365.htm#SEC404 ord_test sing_1038.htm#SEC1113 orderings General definitions for orderings sing_892.htm#SEC943 orderings introduction Introduction to orderings sing_891.htm#SEC942 orderings, M sing_896.htm#SEC947 orderings, a sing_898.htm#SEC949 orderings, global sing_893.htm#SEC944 orderings, local sing_894.htm#SEC945 orderings, product sing_897.htm#SEC948 ordstr sing_366.htm#SEC405 orthogonalize sing_1114.htm#SEC1189 outer sing_1084.htm#SEC1159 output sing_41.htm#SEC70 p-adic numbers sing_32.htm#SEC45 pFactor sing_1930.htm#SEC2005 pIntersect sing_559.htm#SEC610 pIntersectSyz sing_560.htm#SEC611 package sing_144.htm#SEC183 package declarations package declarations sing_145.htm#SEC184 package related functions package related functions sing_146.htm#SEC185 pairset sing_1995.htm#SEC2070 par sing_367.htm#SEC406 par2varRing sing_928.htm#SEC1003 paraConic sing_1411.htm#SEC1486 paraPlaneCurve sing_1405.htm#SEC1480 parallel skeletons sing_982.htm#IDX428 parallel.lib sing_982.htm#SEC1057 parallelTestAND sing_986.htm#SEC1061 parallelTestOR sing_987.htm#SEC1062 parallelWaitAll sing_985.htm#SEC1060 parallelWaitFirst sing_984.htm#SEC1059 parallelWaitN sing_983.htm#SEC1058 parallel_lib sing_982.htm#SEC1057 parallelization sing_982.htm#IDX427 parallelization sing_1022.htm#IDX430 parallelization sing_1060.htm#IDX443 param sing_1588.htm#SEC1663 parameter, as numbers sing_139.htm#SEC178 parameterSubstitute sing_2092.htm#SEC2167 parametric annihilator sing_588.htm#IDX324 parametric annihilator for variety sing_644.htm#IDX347 parametrization sing_1396.htm#IDX519 parametrization sing_1400.htm#IDX528 parametrization sing_1588.htm#IDX680 parametrizeOrbit sing_1400.htm#SEC1475 paraplanecurves.lib sing_1402.htm#SEC1477 paraplanecurves_lib sing_1402.htm#SEC1477 pardeg sing_368.htm#SEC407 parstr sing_369.htm#SEC408 part sing_2219.htm#SEC2294 partOver sing_2222.htm#SEC2297 partUnder sing_2223.htm#SEC2298 partial_molien sing_1675.htm#SEC1750 partitions sing_1179.htm#SEC1254 partitions sing_1179.htm#IDX475 path integral sing_1171.htm#IDX462 pause sing_979.htm#SEC1054 pdivi sing_958.htm#SEC1033 pdivisorplus sing_2247.htm#SEC2322 permcol sing_1097.htm#SEC1172 permrow sing_1098.htm#SEC1173 permutations sing_1180.htm#IDX476 permute sing_1180.htm#SEC1255 permute_L sing_1833.htm#SEC1908 perron sing_786.htm#SEC837 perron.lib sing_785.htm#SEC836 perron_lib sing_785.htm#SEC836 phindex.lib sing_2097.htm#IDX741 phindex_lib sing_2097.htm#IDX742 picksFormula sing_2053.htm#SEC2128 pid sing_406.htm#IDX231 plainInvariants sing_1547.htm#SEC1622 plot sing_1811.htm#SEC1886 plotRot sing_1815.htm#SEC1890 plotRotated sing_1814.htm#SEC1889 plotRotatedDirect sing_1817.htm#SEC1892 plotRotatedList sing_1816.htm#SEC1891 plotRotatedListFromSpecifyList plotRotatedListFromSpecifyList sing_1818.htm#SEC1893 plural sing_1045.htm#IDX435 pmat sing_973.htm#SEC1048 pnormalf sing_959.htm#SEC1034 pointid.lib sing_1311.htm#SEC1386 pointid_lib sing_1311.htm#SEC1386 polSol sing_821.htm#SEC872 polSolFiniteRank sing_822.htm#SEC873 pollTask sing_1070.htm#SEC1145 poly sing_147.htm#SEC186 poly (plural) sing_486.htm#SEC525 poly declarations sing_148.htm#SEC187 poly declarations (plural) poly declarations (plural) sing_487.htm#SEC526 poly expressions sing_149.htm#SEC188 poly expressions (plural) poly expressions (plural) sing_488.htm#SEC527 poly operations sing_150.htm#SEC189 poly operations (plural) poly operations (plural) sing_489.htm#SEC528 poly related functions poly related functions sing_151.htm#SEC190 poly related functions (plural) poly related functions (plural) sing_490.htm#SEC529 poly.lib sing_988.htm#SEC1063 poly2list sing_637.htm#SEC688 poly2zdd sing_2118.htm#SEC2193 61839 polyVars sing_828.htm#SEC879 poly_lib sing_988.htm#SEC1063 polybori sing_2102.htm#IDX746 polybori.lib sing_2102.htm#IDX743 polybori.lib sing_2102.htm#IDX747 polybori_lib sing_2102.htm#IDX744 polymake sing_2038.htm#IDX734 polymake.lib sing_2038.htm#SEC2113 polymakePolytope sing_2039.htm#SEC2114 polymake_lib sing_2038.htm#SEC2113 polymake_so sing_2410.htm#IDX899 polynomial solutions sing_815.htm#IDX375 polynomial, opposite sing_406.htm#IDX223 polytope sing_236.htm#SEC275 polytope sing_2038.htm#IDX730 polytope related functions polytope related functions sing_239.htm#SEC278 polytopeViaInequalities polytopeViaInequalities sing_238.htm#SEC277 polytopeViaPoints sing_237.htm#SEC276 pos_def sing_1125.htm#SEC1200 poset sing_2160.htm#IDX847 posweight sing_1655.htm#SEC1730 powSumSym sing_2178.htm#SEC2253 power sing_1085.htm#SEC1160 powerN sing_1914.htm#SEC1989 powerX sing_1923.htm#SEC1998 power_products sing_1689.htm#SEC1764 powerpolyX sing_1893.htm#SEC1968 powersums sing_2016.htm#SEC2091 preComp sing_1248.htm#SEC1323 preimage sing_370.htm#SEC409 preimage sing_752.htm#IDX350 preimage (plural) sing_523.htm#SEC562 preimage under a map between local rings, map between local rings, map between local and global rings preimageLoc sing_1041.htm#IDX433 preimageLattice sing_2350.htm#SEC2425 preimageLoc sing_1041.htm#SEC1116 preimageNC sing_754.htm#SEC805 prepEmbDiv sing_1473.htm#SEC1548 prepMat sing_1726.htm#SEC1801 prepRealclassify sing_1531.htm#SEC1606 prepSV sing_1828.htm#SEC1903 prepareAss sing_1330.htm#SEC1405 presentTree sing_1460.htm#SEC1535 presolve.lib sing_1736.htm#SEC1811 presolve_lib sing_1736.htm#SEC1811 primL sing_1918.htm#SEC1993 primList sing_1917.htm#SEC1992 primRoot sing_1370.htm#SEC1445 primTest sing_1247.htm#SEC1322 primary_char0 sing_1679.htm#SEC1754 primary_char0_no_molien primary_char0_no_molien sing_1681.htm#SEC1756 primary_char0_no_molien_random primary_char0_no_molien_random sing_1686.htm#SEC1761 primary_char0_random primary_char0_random sing_1684.htm#SEC1759 primary_charp sing_1680.htm#SEC1755 primary_charp_no_molien primary_charp_no_molien sing_1682.htm#SEC1757 primary_charp_no_molien_random primary_charp_no_molien_random sing_1687.htm#SEC1762 primary_charp_random primary_charp_random sing_1685.htm#SEC1760 primary_charp_without primary_charp_without sing_1683.htm#SEC1758 primary_charp_without_random primary_charp_without_random sing_1688.htm#SEC1763 primary_invariants sing_1667.htm#SEC1742 primary_invariants_random primary_invariants_random sing_1668.htm#SEC1743 primdec.lib sing_1315.htm#SEC1390 primdecGTZ sing_1317.htm#SEC1392 primdecGTZE sing_1318.htm#SEC1393 primdecMon sing_1236.htm#SEC1311 primdecSY sing_1319.htm#SEC1394 primdecSYE sing_1320.htm#SEC1395 primdecZ sing_1339.htm#SEC1414 primdecZM sing_1340.htm#SEC1415 primdec_lib sing_1315.htm#SEC1390 primdecint.lib sing_1338.htm#SEC1413 primdecint_lib sing_1338.htm#SEC1413 prime sing_371.htm#SEC410 primeClosure sing_1275.htm#SEC1350 primecoeffs sing_951.htm#SEC1026 primefactors sing_372.htm#SEC411 primes sing_946.htm#SEC1021 primitiv.lib sing_1346.htm#SEC1421 primitiv_lib sing_1346.htm#SEC1421 primitive sing_1347.htm#SEC1422 primitive element sing_1347.htm#IDX509 primitiveSpan sing_2357.htm#SEC2432 primitive_extra sing_1348.htm#SEC1423 primparam sing_1542.htm#SEC1617 principal intersection sing_553.htm#IDX308 print sing_373.htm#SEC412 print sing_2127.htm#IDX782 printGraph sing_1173.htm#SEC1248 printGroup sing_2338.htm#SEC2413 printMoebius sing_2166.htm#SEC2241 printTask sing_1065.htm#SEC1140 printf sing_374.htm#SEC413 printlevel sing_448.htm#SEC487 proc sing_152.htm#SEC191 proc declaration sing_153.htm#SEC192 proc expression sing_154.htm#SEC193 procedure, ASCII help sing_56.htm#IDX126 procedure, ASCII/Texinfo help sing_58.htm#IDX128 procedure, texinfo help sing_57.htm#IDX127 procedures, help string sing_45.htm#SEC81 procedures, static Procedure definition sing_43.htm#SEC77 procs with different argument types procs with different argument types sing_155.htm#SEC194 prodcrit sing_1993.htm#SEC2068 product sing_947.htm#SEC1022 productgroup sing_2359.htm#SEC2434 progress watch sing_364.htm#IDX159 projectLattice sing_2351.htm#SEC2426 projective dimension purityfiltration_lib sing_793.htm#IDX359 projective limes sing_32.htm#SEC45 projectiveDimension sing_794.htm#SEC845 prompt sing_15.htm#SEC21 prompt, option sing_364.htm#IDX178 propagator sing_1171.htm#IDX460 propagator sing_1174.htm#SEC1249 prot, option sing_364.htm#IDX157 protocol of computations sing_364.htm#IDX158 proximitymatrix sing_1501.htm#SEC1576 prune sing_375.htm#SEC414 prwalk sing_2386.htm#SEC2461 psigncnd sing_1789.htm#SEC1864 puiseux2generators sing_1600.htm#SEC1675 puiseuxExpansion sing_2063.htm#SEC2138 pure tensor sing_546.htm#IDX296 purelist sing_804.htm#SEC855 purity purityfiltration_lib sing_793.htm#IDX361 purityFiltration sing_795.htm#SEC846 purityTriang sing_796.htm#SEC847 purityfiltration.lib purityfiltration_lib sing_793.htm#IDX354 purityfiltration_lib purityfiltration_lib sing_793.htm#IDX355 pushForward sing_2376.htm#SEC2451 pwalk sing_1187.htm#SEC1262 pyobject sing_243.htm#SEC282 pyobject sing_2102.htm#IDX749 pyobject declarations pyobject declarations sing_244.htm#SEC283 pyobject expressions pyobject expressions sing_245.htm#SEC284 pyobject operations sing_246.htm#SEC285 pyobject related functions pyobject related functions sing_247.htm#SEC286 pyramid sing_2260.htm#SEC2335 python_eval sing_248.htm#SEC287 python_import sing_249.htm#SEC288 python_run sing_250.htm#SEC289 qbase sing_2019.htm#SEC2094 qepcad sing_2270.htm#SEC2345 qepcadsystem sing_2271.htm#SEC2346 qhmatrix sing_1653.htm#SEC1728 qhmoduli.lib sing_1617.htm#SEC1692 qhmoduli_lib sing_1617.htm#SEC1692 qhspectrum sing_1640.htm#SEC1715 qhweight sing_376.htm#SEC415 qmatrix.lib sing_787.htm#SEC838 qmatrix_lib sing_787.htm#SEC838 qminor sing_789.htm#SEC840 qrds sing_377.htm#SEC416 qring Miscellaneous oddities sing_161.htm#SEC200 qring sing_466.htm#IDX284 qring (plural) sing_491.htm#SEC530 qring declaration sing_165.htm#SEC204 qring declaration (plural) qring declaration (plural) sing_492.htm#SEC531 qring related functions (plural) qring related functions (plural) sing_493.htm#SEC532 qring ring ideal 'factor ring' sing_1050.htm#IDX439 qringNF, option sing_364.htm#IDX160 qslimgb sing_927.htm#SEC1002 quadraticSieve sing_1931.htm#SEC2006 quantMat sing_788.htm#SEC839 quickclass sing_1523.htm#SEC1598 quit sing_438.htm#SEC477 quote sing_378.htm#SEC417 quotient sing_379.htm#SEC418 quotient (plural) sing_524.htm#SEC563 quotientLatticeBasis quotientLatticeBasis sing_212.htm#SEC251 quotientMain sing_1781.htm#SEC1856 quotientMon sing_1227.htm#SEC1302 quotients sing_2279.htm#IDX879 rHRR sing_2216.htm#SEC2291 rMacaulay sing_974.htm#SEC1049 rad_con sing_1001.htm#SEC1076 radical sing_1327.htm#SEC1402 radicalEHV sing_1328.htm#SEC1403 radicalMemberShip sing_2085.htm#SEC2160 radicalMon sing_1228.htm#SEC1303 radicalZ sing_1342.htm#SEC1417 randcharpoly sing_2013.htm#SEC2088 randlinpoly sing_2015.htm#SEC2090 random sing_380.htm#SEC419 random sing_406.htm#IDX235 random sing_2148.htm#IDX821 random sing_2149.htm#IDX823 random number generator, seed sing_406.htm#IDX233 random.lib sing_1009.htm#SEC1084 randomBinomial sing_1021.htm#SEC1096 randomCheck sing_1844.htm#SEC1919 randomLast sing_1020.htm#SEC1095 randomPoint sing_213.htm#SEC252 randomPolyInT sing_2094.htm#SEC2169 random_lib sing_1009.htm#SEC1084 randomid sing_1011.htm#SEC1086 randommat sing_1012.htm#SEC1087 rank sing_261.htm#IDX134 rank sing_381.htm#SEC420 ratSol sing_823.htm#SEC874 ratgb.lib sing_813.htm#IDX364 ratgb_lib sing_813.htm#IDX365 rational curves, rational parametrization of rational curves. paraPlaneCurve sing_1405.htm#IDX540 rational normal curve, projection. sing_1406.htm#IDX541 rational normal curve, projection. sing_1409.htm#IDX542 rational normal curve, projection. sing_1410.htm#IDX543 rational solutions sing_815.htm#IDX376 rational univariate projection sing_2013.htm#IDX727 rationalPointConic sing_1407.htm#SEC1482 ratstd sing_814.htm#SEC865 rays sing_214.htm#SEC253 re2squ sing_1384.htm#SEC1459 read sing_382.htm#SEC421 readNmzData sing_1302.htm#SEC1377 18957 reading, option sing_364.htm#IDX179 readline sing_1.htm#IDX5 real sing_28.htm#IDX75 real roots, univariate polynomial sing_2020.htm#IDX729 real roots, univariate projection sing_2004.htm#IDX725 real roots,sign conditions sing_1787.htm#IDX705 realclassify sing_2393.htm#SEC2468 realclassify.lib sing_2392.htm#SEC2467 realclassify_lib sing_2392.htm#SEC2467 realizationDim sing_2057.htm#SEC2132 realizationDimPoly sing_2059.htm#SEC2134 realizationMatroids.lib realizationMatroids_lib sing_2056.htm#SEC2131 realizationMatroids_lib realizationMatroids_lib sing_2056.htm#SEC2131 realmorsesplit sing_2394.htm#SEC2469 realpoly sing_1351.htm#SEC1426 realrad sing_1353.htm#SEC1428 realrad.lib sing_1350.htm#SEC1425 realrad_lib sing_1350.htm#SEC1425 realzero sing_1352.htm#SEC1427 recursive_boolean_poly recursive_boolean_poly sing_2108.htm#SEC2183 17045 recursive_from_boolean_poly recursive_from_boolean_poly sing_2114.htm#SEC2189 37794 redSB, option sing_364.htm#IDX161 redTail, option sing_364.htm#IDX163 redThrough, option sing_364.htm#IDX164 redefine, option sing_364.htm#IDX180 reduce sing_383.htm#SEC422 reduce sing_567.htm#IDX313 reduce (plural) sing_525.htm#SEC564 reduced standard basis sing_364.htm#IDX162 reduction sing_1705.htm#SEC1780 reesclos.lib sing_1354.htm#SEC1429 reesclos_lib sing_1354.htm#SEC1429 reference sing_251.htm#SEC290 reference declarations reference declarations sing_252.htm#SEC291 reference expressions reference expressions sing_253.htm#SEC292 reference operations reference and shared operations sing_256.htm#SEC295 reference related functions reference and shared related functions sing_257.htm#SEC296 regCM sing_1267.htm#SEC1342 regIdeal sing_1253.htm#SEC1328 regMonCurve sing_1256.htm#SEC1331 regularity Syzygies and resolutions sing_384.htm#SEC423 regularity sing_902.htm#SEC958 reiffen sing_606.htm#SEC657 rel_orbit_variety sing_1698.htm#SEC1773 relations sing_785.htm#IDX353 relativeInteriorPoint relativeInteriorPoint sing_215.htm#SEC254 relative_orbit_variety relative_orbit_variety sing_1699.htm#SEC1774 relweight sing_1654.htm#SEC1729 remainder sing_1774.htm#SEC1849 remainderMain sing_1782.htm#SEC1857 removeCone sing_235.htm#SEC274 removepower sing_1511.htm#SEC1586 repart sing_385.htm#SEC424 replace sing_1883.htm#SEC1958 representation, math objects Representation of mathematical objects sing_889.htm#SEC940 res sing_386.htm#SEC425 resbinomial.lib sing_1414.htm#IDX546 resbinomial_lib sing_1414.htm#IDX547 reservedName sing_387.htm#SEC426 resfunction sing_1428.htm#SEC1503 resgraph.lib sing_1446.htm#SEC1521 resgraph_lib sing_1446.htm#SEC1521 resjung.lib sing_1450.htm#SEC1525 resjung_lib sing_1450.htm#SEC1525 reslist sing_1442.htm#SEC1517 resolution purityfiltration_lib sing_156.htm#SEC195 resolution sing_793.htm#IDX360 resolution (plural) sing_494.htm#SEC533 resolution declarations resolution declarations sing_157.htm#SEC196 resolution declarations (plural) resolution declarations (plural) sing_495.htm#SEC534 resolution expressions resolution expressions sing_158.htm#SEC197 resolution expressions (plural) resolution expressions (plural) sing_496.htm#SEC535 resolution graph sing_1496.htm#IDX560 resolution related functions resolution related functions sing_159.htm#SEC198 resolution related functions (plural) resolution related functions (plural) sing_497.htm#SEC536 resolution, La Scala's method sing_337.htm#SEC376 resolution, computation of sing_386.htm#IDX182 resolution, hilbert-driven sing_312.htm#SEC351 resolutionInLocalization resolutionInLocalization sing_2278.htm#SEC2353 resolutiongraph sing_1497.htm#SEC1572 resolve sing_1458.htm#SEC1533 resolve.lib sing_1454.htm#SEC1529 resolve_lib sing_1454.htm#SEC1529 resources.lib sing_1022.htm#SEC1097 resources_lib sing_1022.htm#SEC1097 restriction sing_2141.htm#IDX809 restriction sing_2157.htm#IDX842 restriction sing_2158.htm#IDX844 restriction of sing_611.htm#IDX336 restrictionIdeal sing_621.htm#SEC672 restrictionModule sing_622.htm#SEC673 resultant sing_351.htm#SEC390 resultant sing_388.htm#SEC427 reszeta.lib sing_1467.htm#SEC1542 reszeta_lib sing_1467.htm#SEC1542 return sing_439.htm#SEC478 return type of procedures Return type of procedures sing_464.htm#SEC503 returnSB, option sing_364.htm#IDX148 reverse sing_2034.htm#SEC2109 reverse lexicographical ordering sing_893.htm#IDX381 reynolds_molien sing_1674.htm#SEC1749 rho sing_1925.htm#SEC2000 rightInverse sing_1863.htm#SEC1938 rightKernel sing_1861.htm#SEC1936 rightModulo sing_772.htm#SEC823 rightNF sing_771.htm#SEC822 rightNFWeyl sing_840.htm#SEC891 rightStd sing_770.htm#SEC821 ring sing_160.htm#SEC199 ring (plural) sing_498.htm#SEC537 ring coefficients hasAlgExtensionCoefficient sing_1048.htm#IDX437 ring coefficients sing_1049.htm#IDX438 ring declarations sing_162.htm#SEC201 ring declarations (plural) ring declarations (plural) sing_499.htm#SEC538 ring operations sing_164.htm#SEC203 ring operations (plural) ring operations (plural) sing_500.htm#SEC539 ring related functions ring related functions sing_163.htm#SEC202 ring related functions (plural) ring related functions (plural) sing_501.htm#SEC540 ring, opposite sing_406.htm#IDX220 ring.lib sing_1027.htm#SEC1102 ring_cf sing_261.htm#IDX135 ring_lib sing_1027.htm#SEC1102 ring_variable sing_2128.htm#IDX786 ring_variable sing_2129.htm#IDX788 ring_variable sing_2130.htm#IDX792 ring_variable sing_2131.htm#IDX794 ringlist sing_389.htm#SEC428 ringlist (plural) sing_526.htm#SEC565 ringtensor sing_1039.htm#SEC1114 ringweights sing_1040.htm#SEC1115 rinvar.lib sing_1710.htm#SEC1785 rinvar_lib sing_1710.htm#SEC1785 rmNmzFiles sing_1307.htm#SEC1382 32601 rm_unitcol sing_1103.htm#SEC1178 rm_unitrow sing_1102.htm#SEC1177 rmx sing_1808.htm#SEC1883 rncAntiCanonicalMap sing_1406.htm#SEC1481 rncItProjEven sing_1410.htm#SEC1485 rncItProjOdd sing_1409.htm#SEC1484 root of Bernstein-Sato polynomial sing_588.htm#IDX325 rootofUnity sing_1042.htm#SEC1117 roots sing_1775.htm#SEC1850 rootsMain sing_1783.htm#SEC1858 rootsModp sing_1907.htm#SEC1982 rootsmr.lib sing_2004.htm#SEC2079 rootsmr_lib sing_2004.htm#SEC2079 rootsur.lib sing_2020.htm#SEC2095 rootsur_lib sing_2020.htm#SEC2095 round sing_1905.htm#SEC1980 rowred sing_1099.htm#SEC1174 rp, global ordering sing_893.htm#IDX380 rswalk sing_2391.htm#SEC2466 rtimer sing_452.htm#SEC491 rvalue No rvalue of increments and assignments sing_458.htm#SEC497 rvar sing_390.htm#SEC429 rwalk sing_2387.htm#SEC2462 rwalk.lib sing_2385.htm#SEC2460 rwalk_lib sing_2385.htm#SEC2460 s_res sing_1056.htm#SEC1131 sa_poly_reduce sing_576.htm#SEC627 sa_reduce sing_575.htm#SEC626 sagbi sing_1360.htm#SEC1435 sagbi.lib sing_1357.htm#SEC1432 sagbiPart sing_1361.htm#SEC1436 sagbiReduce sing_1359.htm#SEC1434 sagbiSPoly sing_1358.htm#SEC1433 sagbi_lib sing_1357.htm#SEC1432 salida sing_1439.htm#SEC1514 sameComponent sing_1987.htm#SEC2062 sameQ sing_1786.htm#SEC1861 sat sing_1168.htm#SEC1243 satiety sing_1255.htm#SEC1330 sba sing_391.htm#SEC430 scalarProd sing_565.htm#SEC616 scheme sing_2251.htm#SEC2326 schreyer.lib sing_1055.htm#SEC1130 schreyer_lib sing_1055.htm#SEC1130 sdb, source code debugger Source code debugger sing_66.htm#SEC102 secondary fan sing_2038.htm#IDX732 secondary polytope sing_2038.htm#IDX733 secondaryFan sing_2046.htm#SEC2121 secondaryPolytope sing_2045.htm#SEC2120 secondary_and_irreducibles_no_molien secondary_and_irreducibles_no_molien sing_1695.htm#SEC1770 secondary_char0 sing_1690.htm#SEC1765 secondary_charp sing_1692.htm#SEC1767 secondary_no_molien sing_1693.htm#SEC1768 secondary_not_cohen_macaulay secondary_not_cohen_macaulay sing_1696.htm#SEC1771 segre sing_2173.htm#SEC2248 select sing_1169.htm#SEC1244 select1 sing_1170.htm#SEC1245 semaphore sing_406.htm#IDX238 semaphore sing_1026.htm#SEC1101 semaphores sing_1022.htm#IDX432 semiCMcod2 sing_1651.htm#SEC1726 semidiv sing_1979.htm#SEC2054 semigroup sing_1500.htm#SEC1575 semigroup sing_1504.htm#IDX567 semigroup of values sing_1590.htm#IDX682 semigroupGenerator sing_216.htm#SEC255 sep sing_1337.htm#SEC1412 separateHNE sing_1601.htm#SEC1676 separator sing_1238.htm#SEC1313 serreRelations sing_694.htm#SEC745 set sing_2123.htm#IDX772 setBaseMultigrading sing_2331.htm#SEC2406 setLetterplaceAttributes setLetterplaceAttributes sing_685.htm#SEC736 setLinearForms sing_217.htm#SEC256 setModuleGrading sing_2343.htm#SEC2418 setMultiplicity sing_218.htm#SEC257 setNmzDataPath sing_1304.htm#SEC1379 18123 setNmzExecPath sing_1300.htm#SEC1375 38993 setNmzFilename sing_1303.htm#SEC1378 20206 setNmzOption sing_1297.htm#SEC1372 9012 set_is_injective sing_1967.htm#SEC2042 setcores sing_1024.htm#SEC1099 setenv sing_406.htm#IDX241 setinitials sing_2261.htm#SEC2336 setring sing_392.htm#SEC431 sh sing_406.htm#IDX243 shared sing_251.htm#SEC290 shared declarations sing_254.htm#SEC293 shared expressions sing_255.htm#SEC294 shared operations reference and shared operations sing_256.htm#SEC295 shared related functions reference and shared related functions sing_257.htm#SEC296 sheaf cohomology sing_1477.htm#IDX548 sheafCoh sing_1483.htm#SEC1558 64501 sheafCohBGG sing_1481.htm#SEC1556 13439 sheafCohBGG2 sing_1482.htm#SEC1557 3338 sheafcoh.lib sing_1477.htm#SEC1552 sheafcoh_lib sing_1477.htm#SEC1552 shiftPoly sing_687.htm#SEC738 short sing_449.htm#SEC488 show sing_975.htm#SEC1050 showBO sing_1459.htm#SEC1534 showDataTypes sing_1461.htm#SEC1536 showNmzOptions sing_1298.htm#SEC1373 64955 showNuminvs sing_1295.htm#SEC1370 18934 showgrades sing_798.htm#SEC849 showrecursive sing_976.htm#SEC1051 sickle sing_672.htm#SEC723 signatureBrieskorn sing_1660.htm#SEC1735 signatureL sing_2098.htm#SEC2173 signatureLqf sing_2099.htm#SEC2174 signatureNemethi sing_1662.htm#SEC1737 signaturePuiseux sing_1661.htm#SEC1736 signcnd sing_1788.htm#SEC1863 signcond.lib sing_1787.htm#SEC1862 signcond_lib sing_1787.htm#SEC1862 simplesolver sing_1732.htm#SEC1807 simplex sing_393.htm#SEC432 simplexOut sing_1759.htm#SEC1834 simplify sing_394.htm#SEC433 simplifyRat sing_835.htm#SEC886 sing.lib sing_1627.htm#SEC1702 sing4ti2.lib sing_1363.htm#SEC1438 sing4ti2_lib sing_1363.htm#SEC1438 sing_lib sing_1627.htm#SEC1702 singular locus of D-module sing_815.htm#IDX370 singularities sing_1559.htm#IDX584 singularities sing_1560.htm#IDX595 singularities sing_1561.htm#IDX598 singularities sing_1562.htm#IDX601 singularities sing_1563.htm#IDX604 singularities sing_1564.htm#IDX608 singularities sing_1565.htm#IDX612 singularities sing_1566.htm#IDX618 singularities sing_1567.htm#IDX626 singularities sing_1568.htm#IDX632 singularities sing_1569.htm#IDX640 singularities sing_1570.htm#IDX650 singularities sing_1658.htm#IDX697 singularities, resolution of Resolution of singularities sing_878.htm#SEC929 singularity sing_1524.htm#SEC1599 singularrc sing_20.htm#IDX74 size Miscellaneous oddities sing_395.htm#SEC434 size sing_466.htm#IDX283 skewmat sing_1086.htm#SEC1161 sleep sing_401.htm#SEC440 slimgb sing_396.htm#SEC435 slimgb sing_855.htm#SEC906 slimgb (plural) sing_527.htm#SEC566 slocus sing_1639.htm#SEC1714 smith sing_1872.htm#SEC1947 smithNormalForm sing_2379.htm#SEC2454 solutionsMod2 sing_1922.htm#SEC1997 solve sing_1753.htm#SEC1828 solve a linear equation system A*x = b via the LU-decomposition of A lusolve sing_340.htm#SEC379 solve.lib sing_1751.htm#SEC1826 solveTInitialFormPar solveTInitialFormPar sing_2088.htm#SEC2163 solve_IP sing_1213.htm#SEC1288 solve_lib sing_1751.htm#SEC1826 solvelinearpart sing_1746.htm#SEC1821 sort sing_948.htm#SEC1023 sortIntvec sing_643.htm#SEC694 sortandmap sing_1747.htm#SEC1822 sortier sing_1709.htm#SEC1784 sortvars sing_1748.htm#SEC1823 sortvec sing_397.htm#SEC436 source code debugger, sdb Source code debugger sing_66.htm#SEC102 spadd sing_1573.htm#SEC1648 span sing_219.htm#SEC258 sparseHomogIdeal sing_1018.htm#SEC1093 sparseid sing_1013.htm#SEC1088 sparsemat sing_1015.htm#SEC1090 sparsematrix sing_1014.htm#SEC1089 sparsepoly sing_1016.htm#SEC1091 sparsetriag sing_1017.htm#SEC1092 spcurve.lib sing_1647.htm#SEC1722 spcurve_lib sing_1647.htm#SEC1722 special characters, non-english sing_455.htm#IDX276 spectral pairs sing_1559.htm#IDX593 spectral pairs sing_1566.htm#IDX625 spectral pairs sing_1568.htm#IDX639 spectral pairs sing_1569.htm#IDX648 spectral pairs sing_1581.htm#IDX664 spectral pairs sing_1583.htm#IDX675 spectralNeg sing_1469.htm#SEC1544 spectrum sing_1559.htm#IDX592 spectrum sing_1565.htm#SEC1640 spectrum sing_1565.htm#IDX617 spectrum sing_1566.htm#IDX624 spectrum sing_1567.htm#IDX631 spectrum sing_1568.htm#IDX638 spectrum sing_1569.htm#IDX647 spectrum sing_1581.htm#IDX663 spectrum sing_1583.htm#IDX674 spectrum sing_1658.htm#IDX699 spectrum.lib sing_1657.htm#SEC1732 spectrum_lib sing_1657.htm#SEC1732 spectrumnd sing_1658.htm#SEC1733 spgamma sing_1580.htm#SEC1655 spgeomgenus sing_1579.htm#SEC1654 spissemicont sing_1576.htm#SEC1651 split sing_977.htm#SEC1052 splitPolygon sing_2048.htm#SEC2123 splitring sing_1349.htm#SEC1424 splitting sing_1246.htm#SEC1321 spmilnor sing_1578.htm#SEC1653 spmul sing_1575.htm#SEC1650 spnf sing_1129.htm#SEC1204 spoly sing_1990.htm#SEC2065 sppairs sing_1566.htm#SEC1641 sppnf sing_1571.htm#SEC1646 sppprint sing_1572.htm#SEC1647 spprint sing_1130.htm#SEC1205 sprintf sing_399.htm#SEC438 spsemicont sing_1577.htm#SEC1652 spsub sing_1574.htm#SEC1649 sqfrNorm sing_1776.htm#SEC1851 sqfrNormMain sing_1784.htm#SEC1859 sqr sing_1902.htm#SEC1977 sqrfree sing_398.htm#SEC437 squareRoot sing_1921.htm#SEC1996 squarefree sing_1602.htm#SEC1677 sres sing_400.htm#SEC439 ssi Parallelization with ssi links sing_850.htm#SEC901 staircase sing_1793.htm#SEC1868 standard sing_1997.htm#SEC2072 standard.lib sing_926.htm#IDX408 standard_lib sing_926.htm#IDX409 startNmz sing_1306.htm#SEC1381 21925 startTasks sing_1066.htm#SEC1141 static procedures Procedure definition sing_43.htm#SEC77 status sing_401.htm#SEC440 std sing_402.htm#SEC441 std sing_853.htm#SEC904 std (plural) sing_528.htm#SEC567 stdfglm sing_403.htm#SEC442 stdhilb sing_404.htm#SEC443 stopTask sing_1067.htm#SEC1142 stratify sing_1727.htm#SEC1802 stratify.lib sing_1725.htm#SEC1800 stratify_lib sing_1725.htm#SEC1800 string Miscellaneous oddities sing_166.htm#SEC205 string sing_466.htm#IDX286 string declarations sing_167.htm#SEC206 string expressions sing_168.htm#SEC207 string operations sing_170.htm#SEC209 string related functions string related functions sing_171.htm#SEC210 string type cast sing_169.htm#SEC208 stripHNE sing_1599.htm#SEC1674 sturm sing_2030.htm#SEC2105 sturmha sing_2032.htm#SEC2107 sturmhaseq sing_2033.htm#SEC2108 sturmquery sing_2008.htm#SEC2083 sturmseq sing_2031.htm#SEC2106 submat sing_1087.htm#SEC1162 subrInterred sing_1006.htm#SEC1081 subset_sum01 sing_1951.htm#SEC2026 subset_sum02 sing_1952.htm#SEC2027 subst sing_405.htm#SEC444 subst (plural) sing_529.htm#SEC568 substitute sing_1005.htm#SEC1080 sugarCrit, option sing_364.htm#IDX165 sum sing_949.htm#SEC1024 sum_of_powers sing_2177.htm#SEC2252 sumlist sing_1441.htm#SEC1516 super-commutative algebras Graded commutative algebras (SCA) sing_538.htm#SEC589 superCommutative sing_769.htm#SEC820 super_increasing_knapsack super_increasing_knapsack sing_1963.htm#SEC2038 surf.lib sing_1810.htm#SEC1885 surf_lib sing_1810.htm#SEC1885 surfacesignature.lib surfacesignature_lib sing_1659.htm#SEC1734 surfacesignature_lib surfacesignature_lib sing_1659.htm#SEC1734 surfer sing_1.htm#IDX8 surfer sing_1812.htm#SEC1887 surfex sing_1.htm#IDX7 surfex.lib sing_1813.htm#SEC1888 surfex_lib sing_1813.htm#SEC1888 suspend sing_401.htm#SEC440 swalk sing_2390.htm#SEC2465 swalk.lib sing_2389.htm#SEC2464 swalk_lib sing_2389.htm#SEC2464 swap sing_1528.htm#SEC1603 swap sing_2130.htm#IDX790 switch No case or switch statement sing_460.htm#SEC499 syModStd sing_1373.htm#SEC1448 symNsym sing_2171.htm#SEC2246 sym_gauss sing_1113.htm#SEC1188 symm sing_2170.htm#SEC2245 symmStd sing_1372.htm#SEC1447 symmat sing_1088.htm#SEC1163 symmetric basis sing_1105.htm#IDX446 symmetric power sing_1107.htm#IDX448 symmetricBasis sing_1105.htm#SEC1180 symmetricPower sing_1107.htm#SEC1182 symmfunc sing_2017.htm#SEC2092 symodstd.lib sing_1367.htm#SEC1442 symodstd_lib sing_1367.htm#SEC1442 symsignature sing_2007.htm#SEC2082 syndrome sing_1840.htm#SEC1915 sysBin sing_1838.htm#SEC1913 sysCRHT sing_1835.htm#SEC1910 sysCRHTMindist sing_1836.htm#SEC1911 sysFL sing_1851.htm#SEC1926 sysNewton sing_1837.htm#SEC1912 sysQE sing_1841.htm#SEC1916 sys_code sing_1832.htm#SEC1907 system sing_406.htm#SEC445 system, -- sing_406.htm#IDX266 system, --long_option_name sing_406.htm#IDX269 system, --long_option_name=value sing_406.htm#IDX271 system, HC sing_406.htm#IDX209 system, LLL sing_406.htm#IDX213 system, Singular sing_406.htm#IDX247 system, SingularLib sing_406.htm#IDX249 system, absFact sing_406.htm#IDX185 system, blackbox sing_406.htm#IDX186 system, bracket sing_406.htm#IDX191 system, browsers sing_406.htm#IDX190 system, btest sing_406.htm#IDX193 system, complexNearZero sing_406.htm#IDX194 system, contributors sing_406.htm#IDX196 system, cpu sing_406.htm#IDX198 system, cpu sing_406.htm#IDX265 system, denom_list sing_406.htm#IDX200 system, eigenvals sing_406.htm#IDX201 system, env sing_406.htm#IDX202 system, freegb sing_406.htm#IDX204 system, getPrecDigits sing_406.htm#IDX207 system, getenv sing_406.htm#IDX206 system, gmsnf sing_406.htm#IDX208 system, hessenberg sing_406.htm#IDX210 system, install sing_406.htm#IDX212 system, nblocks sing_406.htm#IDX216 system, newstruct sing_406.htm#IDX217 system, opp sing_406.htm#IDX218 system, oppose sing_406.htm#IDX221 system, pcvBasis sing_406.htm#IDX230 system, pcvCV2P sing_406.htm#IDX228 system, pcvDim sing_406.htm#IDX229 system, pcvLAddL sing_406.htm#IDX224 system, pcvMinDeg sing_406.htm#IDX226 system, pcvP2CV sing_406.htm#IDX227 system, pcvPMulL sing_406.htm#IDX225 system, pid sing_406.htm#IDX232 system, random sing_406.htm#IDX234 system, reserve sing_406.htm#IDX236 system, reservedLink sing_406.htm#IDX237 system, semaphore sing_406.htm#IDX239 system, semic sing_406.htm#IDX240 system, setenv sing_406.htm#IDX242 system, sh sing_406.htm#IDX244 system, shrinktest sing_406.htm#IDX245 system, spadd sing_406.htm#IDX250 system, spectrum sing_406.htm#IDX251 system, spmul sing_406.htm#IDX252 system, std_syz sing_406.htm#IDX253 system, stest sing_406.htm#IDX254 system, tensorModuleMult sing_406.htm#IDX255 system, twostd sing_406.htm#IDX256 system, uname sing_406.htm#IDX259 system, version sing_406.htm#IDX262 system, with sing_406.htm#IDX263 systemOfParametersOfLocalization systemOfParametersOfLocalization sing_2275.htm#SEC2350 syz sing_407.htm#SEC446 syz (plural) sing_530.htm#SEC569 syzygy sing_1055.htm#IDX442 tDetropicalise sing_2090.htm#SEC2165 tInitialForm sing_2074.htm#SEC2149 tInitialFormPar sing_2086.htm#SEC2161 tInitialFormParMax sing_2087.htm#SEC2162 tInitialIdeal sing_2075.htm#SEC2150 tab sing_978.htm#SEC1053 tail sing_1986.htm#SEC2061 tame polynomial sing_1581.htm#IDX656 tame polynomial sing_1582.htm#IDX666 tame polynomial sing_1583.htm#IDX667 tangentGens sing_1397.htm#SEC1472 tangentcone sing_1646.htm#SEC1721 task sing_1060.htm#IDX445 tasks.lib sing_1060.htm#SEC1135 tasks_lib sing_1060.htm#SEC1135 tau_es sing_1554.htm#SEC1629 tau_es2 sing_1508.htm#SEC1583 tdCf sing_2204.htm#SEC2279 tdFactor sing_2206.htm#SEC2281 tdProj sing_2209.htm#SEC2284 tdTerms sing_2205.htm#SEC2280 teachstd.lib sing_1984.htm#SEC2059 teachstd_lib sing_1984.htm#SEC2059 template.lib sing_55.htm#IDX121 template.lib sing_55.htm#IDX124 template_lib sing_55.htm#SEC91 template_lib sing_55.htm#IDX122 tensor sing_546.htm#IDX300 tensor sing_1089.htm#SEC1164 tensorMod sing_1208.htm#SEC1283 term orderings General definitions for orderings sing_892.htm#SEC943 term orderings introduction Introduction to orderings sing_891.htm#SEC942 testNCfac sing_743.htm#SEC794 testParametrization sing_1412.htm#SEC1487 testPointConic sing_1413.htm#SEC1488 testPrimary sing_1325.htm#SEC1400 testPrimaryE sing_1326.htm#SEC1401 tex sing_1799.htm#SEC1874 texDrawBasic sing_2081.htm#SEC2156 texDrawNewtonSubdivision texDrawNewtonSubdivision sing_2083.htm#SEC2158 texDrawTriangulation texDrawTriangulation sing_2084.htm#SEC2159 texDrawTropical sing_2082.htm#SEC2157 texMatrix sing_2080.htm#SEC2155 texNumber sing_2078.htm#SEC2153 texPolynomial sing_2079.htm#SEC2154 texcoef sing_1880.htm#SEC1955 texdemo sing_1800.htm#SEC1875 texfactorize sing_1801.htm#SEC1876 texmap sing_1802.htm#SEC1877 texname sing_1803.htm#SEC1878 texobj sing_1804.htm#SEC1879 texpoly sing_1805.htm#SEC1880 texproc sing_1806.htm#SEC1881 texring sing_1807.htm#SEC1882 the first alternative algorithm sing_1185.htm#IDX479 three_elements sing_1970.htm#SEC2045 timeFactorize sing_953.htm#SEC1028 timeStd sing_952.htm#SEC1027 timer sing_450.htm#SEC489 timer resolution, setting the sing_406.htm#IDX272 timestep sing_2264.htm#SEC2339 tjurina sing_1642.htm#SEC1717 tmatrix sing_1569.htm#SEC1644 todd sing_2201.htm#SEC2276 toddE sing_2202.htm#SEC2277 toddPoly sing_2215.htm#SEC2290 tolessvars sing_1745.htm#SEC1820 topological invariants sing_1496.htm#IDX558 topological invariants sing_1503.htm#IDX565 topological invariants sing_1504.htm#IDX569 topological invariants sing_1505.htm#IDX573 topological invariants sing_1506.htm#IDX577 toric ideals sing_906.htm#SEC962 toric ring sing_1284.htm#IDX508 toric.lib sing_1374.htm#SEC1449 toric_ideal sing_1375.htm#SEC1450 toric_lib sing_1374.htm#SEC1449 toric_std sing_1376.htm#SEC1451 torusInvariants sing_1290.htm#SEC1365 911 total divisors sing_546.htm#IDX297 total multiplicities sing_1496.htm#IDX561 totalmultiplicities sing_1498.htm#SEC1573 trace sing_408.htm#SEC447 tracemult sing_2011.htm#SEC2086 transpose sing_409.htm#SEC448 trapezoid sing_2258.htm#SEC2333 triMNewton sing_1771.htm#SEC1846 triagmatrix sing_1019.htm#SEC1094 triang.lib sing_1764.htm#SEC1839 triangL sing_1765.htm#SEC1840 triangL_solve sing_1762.htm#SEC1837 triangLf_solve sing_1760.htm#SEC1835 triangLfak sing_1766.htm#SEC1841 triangM sing_1767.htm#SEC1842 triangMH sing_1768.htm#SEC1843 triangM_solve sing_1761.htm#SEC1836 triang_lib sing_1764.htm#SEC1839 triang_solve sing_1763.htm#SEC1838 triangulations sing_2044.htm#SEC2119 tropical curves sing_2060.htm#IDX739 tropical geometry sing_1171.htm#IDX455 tropical mirror symmetry sing_1171.htm#IDX457 tropical polynomials sing_2060.htm#IDX740 tropical.lib sing_2060.htm#IDX737 tropicalCurve sing_2065.htm#SEC2140 tropicalJInvariant sing_2068.htm#SEC2143 tropicalLifting sing_2061.htm#SEC2136 tropicalSubst sing_2093.htm#SEC2168 tropicalVariety sing_2409.htm#SEC2484 tropical_lib sing_2060.htm#IDX738 tropicalise sing_2072.htm#SEC2147 tropicaliseSet sing_2073.htm#SEC2148 truncate sing_1478.htm#SEC1553 13545 truncateFast sing_1479.htm#SEC1554 5124 truncated module sing_1478.htm#IDX549 truncated module sing_1479.htm#IDX550 tst_ncfactor sing_751.htm#SEC802 twalk sing_1184.htm#SEC1259 two-sided sing_546.htm#IDX298 two-sided Groebner basis sing_546.htm#IDX299 twostd sing_406.htm#IDX257 twostd sing_531.htm#SEC570 type sing_410.htm#SEC449 type B sing_2146.htm#IDX817 type D sing_2147.htm#IDX819 type,custom Definition of a user defined type sing_178.htm#SEC217 type2arr sing_2124.htm#SEC2199 typecasting sing_2124.htm#IDX773 typecasting sing_2125.htm#IDX775 typecasting sing_2126.htm#IDX778 typeof sing_411.htm#SEC450 u sing_2250.htm#SEC2325 uname sing_406.htm#IDX258 unbounded_knapsack sing_1953.htm#SEC2028 unipotent groups sing_1396.htm#IDX517 uniquePoint sing_220.htm#SEC259 unitmat sing_1090.htm#SEC1165 univariate sing_412.htm#SEC451 univarpoly sing_2018.htm#SEC2093 unknown syndrome Decoding method based on quadratic equations sing_922.htm#SEC992 unset sing_325.htm#SEC364 untyped definitions sing_83.htm#SEC122 untyped definitions sing_471.htm#SEC510 updatePairs sing_1996.htm#SEC2071 ures_solve sing_1754.htm#SEC1829 uressolve sing_413.htm#SEC452 usage, option sing_364.htm#IDX181 user interface, Emacs Emacs user interface sing_21.htm#SEC28 valvars sing_1749.htm#SEC1824 vandermonde sing_414.htm#SEC453 vanishId sing_1850.htm#SEC1925 var sing_415.htm#SEC454 varMat sing_2128.htm#SEC2203 varNum sing_2129.htm#SEC2204 variables sing_416.htm#SEC455 variables sing_2128.htm#IDX785 variables sing_2129.htm#IDX787 variables sing_2130.htm#IDX791 variables sing_2131.htm#IDX793 variablesSorted sing_584.htm#SEC635 variablesStandard sing_583.htm#SEC634 vars2pars sing_830.htm#SEC881 varsigns sing_2023.htm#SEC2098 varstr sing_417.htm#SEC456 vct2str sing_692.htm#SEC743 vdim sing_418.htm#SEC457 vdim (plural) sing_532.htm#SEC571 vec2poly sing_566.htm#SEC617 vector sing_172.htm#SEC211 vector declarations sing_173.htm#SEC212 vector expressions sing_174.htm#SEC213 vector operations sing_175.htm#SEC214 vector related functions vector related functions sing_176.htm#SEC215 verify sing_2014.htm#SEC2089 versal sing_1549.htm#SEC1624 version sing_406.htm#IDX261 vertexAdjacencyGraph vertexAdjacencyGraph sing_2447.htm#SEC2522 vertexEdgeGraph sing_2448.htm#SEC2523 vertices sing_242.htm#SEC281 vfilt sing_1567.htm#SEC1642 view sing_1870.htm#SEC1945 visual sing_2449.htm#SEC2524 visualize sing_2249.htm#SEC2324 voice sing_453.htm#SEC492 vwfilt sing_1568.htm#SEC1643 wUnit sing_1908.htm#SEC1983 waitAllTasks sing_1069.htm#SEC1144 waitTasks sing_1068.htm#SEC1143 waitall sing_419.htm#SEC458 waitfirst sing_420.htm#SEC459 warkedPreimageStd sing_2277.htm#SEC2352 warn, option sing_70.htm#SEC109 warn, option sing_364.htm#IDX147 watchdog sing_950.htm#SEC1025 wedge sing_421.htm#SEC460 weierstr.lib sing_1999.htm#SEC2074 weierstrDiv sing_2000.htm#SEC2075 weierstrPrep sing_2001.htm#SEC2076 weierstr_lib sing_1999.htm#SEC2074 weierstrassForm sing_2069.htm#SEC2144 weight sing_422.htm#SEC461 weight filtration sing_1559.htm#IDX589 weight filtration sing_1566.htm#IDX623 weight filtration sing_1568.htm#IDX637 weight filtration sing_1569.htm#IDX645 weight filtration sing_1581.htm#IDX661 weight filtration sing_1583.htm#IDX672 weightKB sing_423.htm#SEC462 weightM, option sing_364.htm#IDX166 weighted lexicographical ordering sing_893.htm#IDX388 weighted reverse lexicographical ordering Global orderings sing_893.htm#IDX386 weightedRing sing_762.htm#SEC813 whichvariable sing_2022.htm#SEC2097 while sing_440.htm#SEC479 withDim sing_261.htm#IDX141 withHilb sing_261.htm#IDX139 withMult sing_261.htm#IDX142 withRes sing_261.htm#IDX140 withSB sing_261.htm#IDX138 wp, global ordering sing_893.htm#IDX387 write sing_424.htm#SEC463 writeNmzData sing_1301.htm#SEC1376 38467 writeNmzPaths sing_1305.htm#SEC1380 sprintf ws, local ordering sing_894.htm#IDX398 wurzel sing_1890.htm#SEC1965 xchange sing_1884.htm#SEC1959 xdvi sing_1809.htm#SEC1884 zdd sing_2102.htm#IDX751 zdd2poly sing_2119.htm#SEC2194 55047 zero-dimensional sing_2019.htm#IDX728 zeroMod sing_1242.htm#SEC1317 zeroOpt sing_1251.htm#SEC1326 zeroRadical sing_1153.htm#SEC1228 zeroSet sing_1777.htm#SEC1852 zerodec sing_1334.htm#SEC1409 zeroset.lib sing_1772.htm#SEC1847 zeroset_lib sing_1772.htm#SEC1847 zetaDL sing_1471.htm#SEC1546 { sing_36.htm#IDX79 || sing_36.htm#IDX104 || sing_96.htm#SEC135 } sing_36.htm#IDX80 ~ sing_36.htm#IDX118 ~ sing_441.htm#SEC480 singular-4.0.3+ds/dox/000077500000000000000000000000001266270727000145475ustar00rootroot00000000000000singular-4.0.3+ds/dox/Doxyfile.in000066400000000000000000003125311266270727000166670ustar00rootroot00000000000000# Doxyfile 1.8.7 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER =$(git_version) # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = $(abs_top_srcdir)/dox/logo.png # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = $(abs_top_srcdir) $(abs_top_builddir) # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = YES # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = YES # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = YES # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = YES # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = YES # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = YES # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = NO # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = NO # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= NO # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = $(abs_top_srcdir)/dox/DoxygenLayout.xml # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = html_dox.log #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = \ $(abs_top_srcdir)/README.md \ $(abs_top_srcdir)/main.dox \ $(abs_top_srcdir)/doc/ \ $(abs_top_srcdir)/omalloc/ \ $(abs_top_srcdir)/resources/ \ $(abs_top_srcdir)/kernel/ \ $(abs_top_srcdir)/libpolys/ \ $(abs_top_srcdir)/Singular/ \ $(abs_top_srcdir)/templates/ \ $(abs_top_srcdir)/factory/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = *.h \ *.cc \ *.c \ *.cpp \ *.cxx \ *.dox \ *.md # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = $(abs_top_srcdir)/factory/examples \ $(abs_top_srcdir)/kernel/old \ $(abs_top_srcdir)/omalloc/Misc # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = YES # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = \ */test.cc \ *[Cc]onfig.h \ # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = $(abs_top_srcdir) # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = $(abs_top_srcdir) # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = YES # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = NO # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = $(abs_top_srcdir)/dox/header.html # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = $(abs_top_srcdir)/dox/footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = $(abs_top_srcdir)/dox/stylesheet.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 200 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 0 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 190 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = YES # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /

singular-4.0.3+ds/dox/header.html000066400000000000000000000037111266270727000166670ustar00rootroot00000000000000 $projectname: $title $title $treeview $search $mathjax $extrastylesheet
$projectname  $projectnumber
$projectbrief
$projectbrief
$searchbox
singular-4.0.3+ds/dox/logo.png000066400000000000000000000253251266270727000162240ustar00rootroot00000000000000‰PNG  IHDRZPX½½¤sRGB®ÎébKGDÿÿÿ ½§“ pHYs3”3”²ŽtIMEÚ 'I•' IDATxÚí]wœœUÕ~ÎÙšdJDŠAJ !Ä$ "Á PšD%H E>Š âb¥" QñS5€AD$B ! ’l6[fwgæ<ßsÞpy™>³»Qßç÷›ß–™¹ï-çž{ú"Dˆ!B„"Dˆ!B„"Dˆ!B„"Dˆ!B„"Dˆ!B„"Dˆ!B„"Dˆ!B„"Dˆ!B„Þ ‰&!B„Ä*}9çb=ô€ªŽUÕHŽÌó·ÍΆªýY’ÛòÛ+¥í"Dcýúõqã=¯‘ìùío{Ho>/^ÍÆHBDÆY£ªƒ|TD>` €í왬'ùy„d3ÉQ¿Î¹€Á.p¦sniD*"D(—O͘1C[ZZ¶'Yà…éÓ§¿þoÑqï÷HÎRÕÅ$ÓÌ ­ª=$»Hö¨j’dÊÞ£ª¾Fòûªz”ª6ø’kжª~LUªzPD*"D¨”_¥R©óI®&ù½É“'Çÿm ª¨êJUíTÕN’öÚÊTI¶¨êFïï$ÉN’ UݬªËH^¤ªu¡Éù-É’‹H%B„•0Ú5kÖ4¨êI¾¡ªg“tÛt‡ígÉ{TµKUÛI¶“ìPÕvUmVÕKIîåûUõ’+I¶Ãm'ÙCr³ªÎWÕ“H.°ÿo yhD*"D¨@ ÉãH®%ù*ɨĉk¶u&;’äc&vL–dRU¿Ar@ø{açÉz’§’|ÚL í!I8i·<2"•ÛÚ>ÿaÛEOOTõ«ªºAUï´µ«Û–‰l°ª>A2a̱]U;Ì&{|1'‹A`íÝ«ªik«Ý3?tÜLrFD*ÿRÃÑXã“ý÷8‡Ú@2Nr½ª¶‚ I¹5ªÚ|¾¦¦&Þï›HU…äuªÚåI f›ýªºRˆ/$\ê·é½ZI~z–î#j~·Š’ÿÑŒ—ähµÿ-èQH:Uªªm$Ÿ¿ï¾ûbþû¶žËI>°aÆš×_½ÿ6uf’I²ï`†ªú&ÉUÀÀƒöÏ KµªÚVŒ¤Ip•¡ã1ë|GC©‡Ñ¶:¯^4Œó•Û®4K2`¤O™vü1ÞgjTu'’Ï| &NœØï†dWX½WÕ$ªôŒkÌNÛîÙ?»­ž–ÿ ª½1G©#ò™wˆ‚¤˘HÖ™Ãu[”ªÎ`#†Ý{èîo\LrW5¡õü2ÉuÉdòTñx<Þ›SUPÕTõþŸU–µ(„àYŸï"Î÷=Ÿ”ÚF>†Wn¿ÃL®é3'óÈåô >ë­WÕÆá}§±Üã·˜Vo0ØÐ|J” Yù´ƒÞÙß‹H¾¦ª×t$ãÞg›H.$¹aݺuñ εÆ%ÅŽÙZ"rŠˆôÈ&ùÄü¤ƒJ¢ˆœ `“=K²õ¹”ÉÆàÛIÖäb‚t—¯àD¹V¨(…ˆ¼KZ ¾›«ŸþßÅŽÓÿ¬—U·#Éq$Ç©êUõ’ÓTu’M"çœsÌ6ks/’»†ß'¹Kð¿ðx²£Tf)"Å0šàÙ$cÅ>¯Î\¬&¬]@ç\ ÍôÆVÉõ_g>‘€vÐ/€Y¸÷Þ{‹ˆ¤¼×8œä¯FŒ‘0`@Õbkã¥vÚ Æ`ŽÅ("à'ªú5£m}¥XÆÈ Ñ9’ "2;˜‹Ð¡ãDDUµàš—Áé ûˆÈ< Ö"˜÷RŸmß=”ät£gÍ!,Cc$׉ÈZdÒé_tε÷ÅaTÆá"¶†ãìLrƒsî&åïä)"‘ëÔ}ôÑiÿ©dãeœ;hÊó‘&’Ÿðd¥³…"Éûœ `Pž Ž.mvð~’ï7f•s l‚7x™äË"òa™`gÛ™{ØUD¶ ¶¹Â„³¾Î‘›Š$²vÙ`¼ˆìkL_=¡ ÀKVH;ç6æ[ìÐójHNp‰ˆL1FÖ F2%"oCÝD¤À{’¼GDî$ù3;l^Ð¥ª§ŠÈ~$ÿ/,9Û³Wˆcø`hL´ç©'m;YMòï6ÿ Ó’²ÑAÀŽ$'ˆÈžŒ™ÃÆõŠˆ¼`£w¾`cÄcý9Î%”‰ÈrSOe“íÑÞ`&æ°ÙªU¨ê‘>Hò0ù·ÆÉržm5EÒ†“œdóé &IŸgˆHMX[°uÝàQwx À:ÿ îg48^DÒéô‰qÄO<ñDlÅŠ:zôh‘ËmßµL˜0A[[[ÝàÁƒ‘N§áœÓ¾>!ö2‡WG¶—ªÑÇø6’*<÷YUíQÕ¯R‰ÌpV¦Œ‚väê+ÉTu2É¡ÞwªÆH&¹Éó­ÂOG6›´ç ìRÕS ©h¾ê§ª1+ÓöŠ¥ ·“|“äŪd¡8äC,y$mýé°ñ“äfƒŠy6@§ªqUm4u/U ¾ßc¯’\jcO‘üZöäÃTu]žyï ùOU_¤{{UÝËL<§[âJ»%ÅÜç¯_àÔkY$燫ïZGU]ÍV×ÃéáUÞ_Mþlý$—eñ_Td: Y§ªwX§gIAò£$§‘ü8ÉãUõ*’ωJF»¦¥I.SÕÓ«ÉÊÁ>ûì#DU÷UÕVU]D}Ûm·ÝDUo"Ù¬ªç‘ŒûÛßvóæÍ‹Ùgú>=WUÇ“\•ga|Æszµì>ªz… ùj1ŒLUëTõµPÍÿÕCò€¨IÆü¸OóŠ;cHGlËôƒ1¯&¹1ÆùP_÷UÕ îŠ"™ÿû$o3fvAÉ’³ó9È‚°:/:`’mšYw˜´F[£ª÷äš/kó{þ³ Iy$Øgã$ÿ`m­WÕ1¶^ñl‘Þß{‡OŽ5lSÕ 10’ ªëÅýå<Æ~Iõhlzµm¡ª:ÑbásÍËU˜ÇÉt:ÉVFÚ½5îQÕÿíO1¶««+8°–«êZ’G!y0lذ£¯‡ìàkü øÞoªÁhKn@DºBªÄ»>b?S"2äUª:¨\ƒ¼§*ÿÜž__¤Ã.-"ÿÊcœs$_ ì¦"’vÎmUsD„MTD^"y™ˆ4óö$o¤’lc œNžm–‹ÈJ3åüªc,0!¨jÉñ"r3€ÏH[¿©‘‹EäÏä±Õ>ë;Ì‚IXÊ=¬_[mX¹¦2‹Ã+¯ZkóÛã?»ÀšRD:ìó)ÿ°þ¿""«­½T¸´fHµí63Q>¬Ègg·µêrÎ¥{ѱT@HîàZÞÞ™E²Îó_TÃY´ª€‰­Ð>û‰íÀä!þ‹È$Ïï g\6 ¤¾¾ž$§™Yè]¼x±ÛgŸ}ëׯWÓ w°RD–‰ˆwóÍ7ÇEd·õ9£%¹Å_ü 7 àyˆäá!æR*Ã}äýs,r²“yWD$QAÀë"²¦ˆÇ¦Í>y{±c5†@’o˜d¶¬˜ÃÇl_»“¼‘äGÍF-Óo y·ˆÌËLÏÀv–¼¶×8œ}ÂÒwIÎ3ÎÚê,¶¡ \mhÐQd3éBvÍ:—3Iü¹ë¤¾rT €)«2Óê,›yØz8çnðBà¯ÈÂæ¨êȾt€‘t;í´Sn{’ˆÄI>àÍÛo¿=ýè£ÆV¬X!&­m¶üYÇ{lÐoΞ={ €¾Ùíz›KtÀ‹HÞ«ªƒ}"-%ÎÓ9w¼snQ1DnÄZÈa,òÙ)’žs ßáÒ`:Éëb ì¡y6$L HKä$¯‘ƒMò~Ǧ$¹HDfÙ¼ùŒ!îKÕ^[u>C3GÏ™aL³`p~È ,À°Xê†öÐbcì&™*v =3QD_´™œsÝ$Góî­+ &y4É݃± HU‰id}–ýAd­§—+d•s$ ·fÍšÔ²eË&‰ÈAêÍÙÅ ¸áÇËèÑ£ˆ4ˆÈgH>."«çÎëÖ®]«C† a[[ÛtÛ™ƒ´ï­çeýsÀõ‹k¯ý1Òt ɱ¾U¬ªRªzS "2FUk>„LÈP,ÇøÅ—/ü¤×—Æ<}Ñ\÷‰Ï$óÝ+g¾Ï“Ü”Å>^ z™MJ·C'–g¾+BØ´Cò"L˜ÅêÒ$"3=Zˆ÷wè”ù ºH®Í¶æÐÛ«J&—†¥K—Ñ¢ª²eË–¸’D[[[zìØ±’ü¢ˆ¬pÝi§;ùä“ñàƒê˜1cHr¸ˆœà×|ðò††LžUKKK™0Ѹ´Rx96ZˆÈ¿‰•+5ÌE<;Ôv"rŒˆ¼lžöºr7b¾C!W[ÅJ»a¬ö¤ÏÛDä«&æRƒ•äv7ycø@ §²"BïN¶£INÀÛñ©>b–™—ú]&‚Bªy¸žƒðû$7— âm-F3 >ÛŒÅÚ¬Ía¢©3“‹ö†ôhsì$“!"25›IÄ“]¦-œ€ý‘å9w[rÍ­ÍïÐJŸµ|ùòÔå—_>ÀËþsMMM)Çš¶‘¸™à®3Ö="’¸í¶ÛðòË/§Ž9æ¾ôÒK àVc΋GÝm|I“É$¬|b À«Õp>Vâmœ#"oU Q¦!ùu¯˜CrD6'Mo¨ƒ¥ª¯F0ÏÚŸˆÈ"S©s ¶ià~îÅI–›})€®‹_KòaçÜ[Õ2þÎ̪ô,–9ô…ØÆÏî‘î^JP~("j™q]ãÍÑÇz’3¼0¤l Y›o^EdS¥Ï¸÷Þ{c·ÜrKàÀ:Àg“Éä(?[¼xqÍG>ò‘Z’)U=Àh‹æ¹™,8“&MÂòåË?`"ɸëïÿ{GŸi¹À¢W_}uó;ûˆÑzêÔ’—˜:Å ˜-tÜÀ7fj̧ïŽñ̆dÈDSªDWcœÏ=\Dö±gÞ%"?·bB±l'”%î̲µ¨·1ö[M’_·ƒJÂR2±º?®Òsn!ÙàèX,v­ˆ ª—Ù³îp®ˆÜ€LÝ“IÆÖ¬Y“¾îºëjÎ;ï¼nd\|À…3gÎŒ{šE·=ãTd’}6Wk~\%›ÅK%IòÛ"«ÀŒF—îWø™¹KŠ»-`:²‰Eö'`nÞ\ιgDäËÈ$ d“샂* ."¹[(_}'XU•‹©˜,ž'5Freon¨*näÆ<™v…Ö6¸_¤ND˜K’óhe$2fj ÐKÒ¾·5)¡g]œdÑR¥wØ:¼í¯˜àyÊ>v%2™b|—ŠDö8TU§Øÿz¼tõ>“fm¼Ç8ïŽú½À3Õè—ˆ ‘wß}÷e$cGuTlåÊ•óDäD3©\n’éU"òÏåË—ó—¿ü%}ôÑô-·Ü2™ä‰Y?wäÈ‘©ÖÖÖ®,‡óx£ô;£ ™ºœs¸™LÉÁpʱßBDŽ$ù ÉáŪqŘürtE –ë°±My?ÉωH,‡düoŒ9}Bm îãÏVÀÊ J˼ˆÈjlã°ùn1©£œÍöžêí²M‰Ùø€V’ïA$ «¨óZ£D³R* ©"j‚ý3uû KŒ™eÈàœû­åßg£½€|O±HˆH¼Êe¥€I°ÁŠÍÜlλðžs$—˜%"Z­~‘ÜÒÜÜœ\¸p¡>ðÀØc=ÒþjZÀ@Ë®¼›$ß÷¾÷á´ÓN êúþ^DF’œ-"Y»ví¦'žxbëbM™2%è`=É?o3Œ6Ëé|#€!“¯_oí³ ‹Ý-";xLU÷¨–æçe—0W~.·_«"r7É[‘?eµÀ¹$Oð2°:¬Þ*Ddc¶ n×pŠ—Á¶ÍÂ˃/WúÚÞÚ "4G9à ®·Õlë…h±ÇÚM–bªòJ²§&Ì¡™$yÉü@sèûß ê"g!ß9ÚþPIU1c,`° "2FUǨê’$ù)U#"÷ø?Ùo×3kt‘¼NDqÎU-,Îæmð¬Y³âãǯE&逾àX‹l àjá 7Ü{î¹ç SD>à-™OòáË/¿¼u?Mš4)¼R$÷ÜÖ%• Ñ¡VÍ*Y  [Q¯  ›ª>TÚ*@ü1’f»@Ò^IUýJ¡kR¼1í ªTÕÛ²m´Ð}Xñ®`ÏUék³ªHd$° ^ùÆôE»½3×<¥UuÎ6B wXËË*PY²êb¿,ö~3’£,é$_õ®ý4WÏÛeGe¡«]I¾œ‹–Tu3É•ø)Tµ'_ÉS’oÚ¥«o’|‹dKèÒÔà÷Éuªz•ª÷*`UÓ\ñ°íý¼ÿýÄBºÞTÕ±$7šn–-[êmOÆH"‘˜lï½@r§AƒmÝÿ7ÝtSÌ„•å$_)AÛí‰6,=Úéú{Ù™ä7¬±gImvÎCœ]ÈV„é@Dä•BפxŠo4oK›^1˜à [ÜlöZ¬±“uDP†­ˆ«p:ŠÈ×/–ñ šRF_ÚyCß—*Ò¯ô“n6úUþ˜…®V!… 9º\ `¶ª¨¶³Ø¤ôNd<ûÏ™]¸@­?Wòv…þfû:ç¾æœ[H UŽÚ¸Žä`¼AU—ˆÈiV$“ÉcsˉÄÈ„UþnРA©‹/¾ØY¤L¬¡¡áoÈ8ÉÆ’¼¾­­mkQ¹sçÖ™ùçnƒBûÛa´Y˜œsWøÉ+,}µ…¯›É‡N7Xá‚§ež\ l„ùö—×~ ’¿‘Ëæ1Û„©1ó¤é™R„ ‚ù*ârÇöóFTÂ&‚ªN$9‘ä~$'û25r?UݱTþTÐ0ɲJ ¯O¬mü8€cIpGžCÿä®­A°w/Ýöð2ÉCs‡¸0ŸïEDF[_ÎJ¬"‘¯ “Iz¾ˆL²gYWW÷§žžžØ\ð{ŠÈ®X¿~½sÎÅE$þÖ[oÅ,}ý.9QU§‚OWWWÂÆñzzz¦-X°Uˆ¦êbò%¨VÉ\sÝXPÄ+0!ü°ÓUÿH æÁ¦Ú_VHòÆ|ªõ7Ÿ ¡Ën?XXÈt@r¼©˜¹Tò¤ÙˆKY£Å$W˜Š¸YU[Ì9—õ¥ª-¦®vܨªÇõƒéàÓf:øEµL6þA}¹?H75·µÃWÕ'ŒV²™’vÝS9·.ä4d+üMòÞЭÔï2_‘<¯·/»•¤ŽdÓSO=Õ4oÞ¼¡<òH½ªÆCŸÛÓæeÝóÏ?ÿCƒ¸t: ’û“|ä ðæ›o6„æe ÉsªÕoW*ã,E ðã-͈Ýîœ;™Kó~` 2)£% ÌfB8@U‡—k:(öô÷>W[¾ï˜d{;€Z®|XØZ ÀÇI~¢ˆ>½”¯, IÉ;—r:禉ÈhÙo;1ks¼jÌ#ÿ’»‰ÈιûûÁt0Òìl©"L)¥ôI+`šÁ¼Öùü HÏg#S,þ²Bscჵ9ÌÝŽ#¹K•aïÚûæPZa¦4f[À·TuRoeÒ577§×®]Û>yòäÄÌ™37|ðÁ=…!^©ÏW,$9lܸqŸ¶{ägžy&Dä™®®®_“|/É/î·ß~Ú›8Óß¾½aÁq’w¨ê¾¥L¤wí5Dä59ÀQ$("5y2«²Î·¥ìŽ.wS÷¶ªèÙ«Ï‘Û=f›m,idb`ónN‹ûý[žŒª42×rÁMvüßóÐ…ðŒˆÌqνzéÓAƒÍm²Z›Ù4®TÖ}©Ð…LkȤew!“ºzY®—ª^FòãÈÜœ«ÿÝ®ï-zö8ÉSLâ“tOù®ªª6ÓO§ÓxñÅÇ2¾jO˜:u*ÄÒéô,i!y®ñ—Ô¾ûîë~ô£aÑ¢Eëëë/°ýwÆêÕ«wùL~of²íûë*›Á$‘c+]0Yêœ;ÀGl*%áÁn¦‡ðúÕl2¢ÏE&cKòÙKó1 Ïñ©ËU1 À{K-~êëãÈ};r 2·›nÍbË#ÙÊkWÀw𤧪Œ•|_U? à äqÐyë8×RoUDεôÛ¬/™ à»þ<Çã%Mò’ïë­”á`ï:çžB&Ó+›¯%ˆ¡Ÿ à‚j§“L766¦†š²å´1Üt@O>ù$vÛm7$‰’ß‘F™'"ìîîvµµµ±ýöÛ¯ÓÂãæ‰ÈÔ“N:é8uõÕW³¶¶vèüùóì ?PDWÚïx n8À×Ê]0_%‘'IŽp ÉÓ‚`ìB^`VÈ4‹éô…ƒÙ“j7< ÀƒC”ræÌ9÷ ’«DdX–v‚y; ÀïÊd4› ˜mZ‹œ¿Àq—Mꩨ┈Œ°±nÀ6€€ÆÌI³ÉÆžïPkBÆó݆L©¾õEDœ€d=É™¶öÙæu0€O!S°×˜­áR‹‡ìEã»Där»¹àáj%RÔÔÔ ^sss¼¦¦&¸Ó쳎ïèèøÖ€^àÆ×`õe$O¾ûî»gßsÏ=ß_¹reMOOO˘1cgŸ}ö¬pÔ‚>g´ž´²»ªîæœk®Æ)iÁl¯ønp_쀞ç|¦ƒ¾Šæ±g=Kò3¶\õ²ìdFXWø2ÅeÂŒ0Iò¿+gŒdP€Ùƒ5¤ºrÓo· t7o ŒÖhw2a}¯XtH>‰LA£çEä²Çÿ_ÈAóÀñ$¿‡L€~¯Œ×èPIÎ ù‚ˆÔ…}c¶"òcU=Ø9·¢/×ãúë¯ï9ýôÓã .|ä|¾¶¶ö2Ÿ[²d‰<ûì³­­­¼ñÆyå•WÎð5»µäéæææAþà VKº³">W “‘#«yJšè €¯YìE‹)–ݪb9fù€Ù–ßÎræÉlR¿&¹4[¨©CŸ ÙXîõ?U:\–ûv³,¦’Úr68€áÈTx£ˆüs[f g"rÔ‘ï6 K=™2™×–aæún®}kÂI$§öæý\žp´ZD¾ˆì1òbt¿½ˆüªÖ÷åºÌ™3‡ .L’T›³X,{?É1S¦LÑÙ³g§›ššpå•W*ÉÇ Ûü©ˆðÚk¯uW^yåæÅ‹?'"í"r^ŸÛh½Eu$?®ªõÕZP/žô›)BzjÍç@Ë'ÑU¡C9R̶uŸÅP²œv¬¨÷å¦Y„%zA&rà„~æA°U3eÑ Íä=쎼iÌb IIDATL@ú_ªÜç†2÷Â`»àOlñë g±ÍN‘£¬‘_•r¸s{™Ä†š,‡,-áú|ju)äVˆÙ"©ò@¾C•ä§Dädï°ìõÃÏ+m(v‹Ë/¼À人:±1èI'DçÜât:½ÀÈt:=îâ‹/N_xá…Ã9ä×,A&:ªï­Wë Ù­ÚÆwçE䳨ÆaóEsžgK÷Õ»\KX[Á¸‚¼ü/xÆ$ rkø>l1È~Í™v…NoHoÅŒu€¿y…ÒÃíŒ0¨Ôjlæ’""÷;ç%Œ/o’ŒÊ%]ÍäÕb=‡ä¾ÖN¡kéo5aâºRçÔó;\€Œwü]R¤…¼MTÕã«ÀØXˆÙZ­†sÍޙ͌GdjH|‡äþ½~V@+k ù+øt]2wî\p±Xì»zêüüç?¿ÙL«3áÒïSFÐÐHòâ^š¤¿ Sá)—–Ô àõr%ë)ê»ØÏe¨{aÉ,i ºÚBGXN;V­è”àVT¯˜`®V× \¨çgc^&y&yR¡þùW «ê\’ÓEd€/+µYq¸ã®X ;Ô§OŠÈÕz'¹hÒ“ì&ˆH—ˆ25Ao°B9ÈÅp­ßH~CD¾!"­Î‘D‰‡#9 Í^DdB. >T$Uõ«"rÞNφˆ¼‘­ Uà*‹wm-@Û…„œ4€ûr­…Ñü.«ž¯ˆ< DþDíìÒȼô,"KH^‹û¬O#”c—®H;¶¹Nø±…lÝ@üñXkkkÂÊc¶‘Ã?üðx»Tß2ZUOrU–I¼MUkªÕ)UÝQUWdÙ $·„½˜$H6‘Lòã$×ç" ˆ:TõÛæ˜¬ªY;’MVñx’«C4AòǪ:Êj 4”3fÏAò]cn¬tîHgakhüªª/“¼ÈjŠŽ2Â{/ÉO“üžª®±ZœþX7ZNø­$w*÷p!ùÕ,uÆÛiÏM[÷gI®³ùHÚg^#¹±Ï·µl²1δ¼÷Bu4:­´Ã¯Íæq³ÕÆ d=VB0üý.UÝÍcJuðW+a>¸ÎSÕÝUuûBf £ÉÁF§I>Y€Ñv¨jÉfU=0æUµžä›—3Uucs²‘ä᪺½Ñ{}ž~è­i®6Iò;$G¨j¬ÙWͦM›¾¯ª]ªz—Õ>ˆ{43ŒäϬöÃÀSO=5^-+å0ZdŠýîšàZ×;ç. 6C%¶U= ™ûØë³Ø]O‘…¡›QÏE&Ãl8€ít¯jÙ6 o"û9 À{\ƒL–U£©÷áKçêÍöô2ñvóʱåcPÕEfç’ clƒ[> àPSEd䈙Îb'Lxä‹–Žû$2“Úr|¾(‡‘©˜{’<[D¦ØËèOCªkÌ£ËNO’üˆÜ*"mÅ>_U¿c71ìd4ÓYìwƒÏù×LûìqG&äëKfZÈF6ÞÍæ‹ÈÝyú´ Éù7Œd¢Hzs\""çø €ÓÍ?1ÀúVLéͦ^·ZÔ¹häùNÌg±ýScð—õ¡T»=€uvqãtY aïÅI$ù±™©¾‘J¥ÇûžÑZ©w0Z#ÂàŽùEι“+˜ˆ`À÷8Ê+Bdî˺CDÎðŽÀz’AužRKÖ÷ÀA¶Å®Fhãa{«sê,ç` ˆSUwp‰ˆœ[I,kèð‰l^úñö¶Cd;uXß‚LøÊdè›IöXíÛÎlŒ¼BB‹­`2€½HŽ0@DRÆtÖ“ü+€eVƒ¡½Œç òêü²/T?ÿ:;`ê­Æ ÑŸù;ºòЉÐdca)uR½‚9íÆàê<»i)mjts.‘ç€r11èà k¯†³©XÚ³Ÿ÷ŠÈq>µråÊß=:`´ ëÖ­2bĈ§I¾áœ›ŠþBÓo?]¤ª#J±Ãøê ÉÏ™zá«— Uý‹ªnÿ0„ç§Ê¹á%3þÞ¿)Ç&!B¥8ãŒ3j ÔØÙÙ9ÆøË+þûõõõ¶"ùÖc=vªXX¾dFë9Ãr½{àY~È\÷:y·w:’—Z½KßaB’¿QÕ£Í!B„2øɆ3fÔ“|Æœ»ûÀ¨Q£0bĈñD"qœª>gæš~ëìxU]e^òv+Fœœ>ƒTÕ6c¸3 U)WÕCH>¥ªíž'7hÿVU–|#Dˆ¡m­««+îβ¢_ÛÛ±À ßÖÖŠW-뵉o;Ã:ÜàGÈT𙆌f4€¡x;S$(:ñɧüËìq;Úg?`¤øé}o-€ëDä™Dˆ¡H¥RˆÅbðsdœÄ{;ç‘\µ- ãUµÙâÌ!õî­ª_4u?a"zRU“ªšÒÌ?Ô$á¤I­=^øÌ£$Ï"¹cpªD’l„ª¤•@c{{û’m©Tê"”YM®7í¾ªºYU¿™M4 (®ªCH~žäÏUõ ‹—Lƒ ~_£ª¿"yŽªŽ YãfG”!B„ª!ˆ H§Ó3,fö’·©NÚ½<ÞÉ×&’£UÝ!W)ÄÈÙ!B„Þ”hÏ:ë¬:ãQI’o\tÑEÞÖDî²bÄ@#DˆÐߨÿýqôÑG7 sOß"’L$ŸŒf&B„ªˆ)S¦Ä‰DŒähUý=É!ѬDˆ!Bkì"Dˆ!B„"Dˆ!B„"Dˆ!B„"Dˆ!B„"Dˆ!B„"Dˆ!B„"Dˆá¿ÿK,CàËBzIEND®B`‚singular-4.0.3+ds/dox/stylesheet.css000066400000000000000000000613301266270727000174550ustar00rootroot00000000000000/* The standard CSS for doxygen 1.8.7 */ body, table, div, p, dl { font: 400 14px/22px Roboto,sans-serif; } /* @group Heading Levels */ h1.groupheader { font-size: 150%; } .title { font: 400 14px/28px Roboto,sans-serif; font-size: 150%; font-weight: bold; margin: 10px 2px; } h2.groupheader { border-bottom: 1px solid #879ECB; color: #354C7B; font-size: 150%; font-weight: normal; margin-top: 1.75em; padding-top: 8px; padding-bottom: 4px; width: 100%; } h3.groupheader { font-size: 100%; } h1, h2, h3, h4, h5, h6 { -webkit-transition: text-shadow 0.5s linear; -moz-transition: text-shadow 0.5s linear; -ms-transition: text-shadow 0.5s linear; -o-transition: text-shadow 0.5s linear; transition: text-shadow 0.5s linear; margin-right: 15px; } h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { text-shadow: 0 0 15px cyan; } dt { font-weight: bold; } div.multicol { -moz-column-gap: 1em; -webkit-column-gap: 1em; -moz-column-count: 3; -webkit-column-count: 3; } p.startli, p.startdd { margin-top: 2px; } p.starttd { margin-top: 0px; } p.endli { margin-bottom: 0px; } p.enddd { margin-bottom: 4px; } p.endtd { margin-bottom: 2px; } /* @end */ caption { font-weight: bold; } span.legend { font-size: 70%; text-align: center; } h3.version { font-size: 90%; text-align: center; } div.qindex, div.navtab{ background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; } div.qindex, div.navpath { width: 100%; line-height: 140%; } div.navtab { margin-right: 15px; } /* @group Link Styling */ a { color: #3D578C; font-weight: normal; text-decoration: none; } .contents a:visited { color: #4665A2; } a:hover { text-decoration: underline; } a.qindex { font-weight: bold; } a.qindexHL { font-weight: bold; background-color: #9CAFD4; color: #ffffff; border: 1px double #869DCA; } .contents a.qindexHL:visited { color: #ffffff; } a.el { font-weight: bold; } a.elRef { } a.code, a.code:visited, a.line, a.line:visited { color: #4665A2; } a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { color: #4665A2; } /* @end */ dl.el { margin-left: -1cm; } pre.fragment { border: 1px solid #C4CFE5; background-color: #FBFCFD; padding: 4px 6px; margin: 4px 8px 4px 2px; overflow: auto; word-wrap: break-word; font-size: 9pt; line-height: 125%; font-family: monospace, fixed; font-size: 105%; } div.fragment { padding: 4px 6px; margin: 4px 8px 4px 2px; background-color: #FBFCFD; border: 1px solid #C4CFE5; } div.line { font-family: monospace, fixed; font-size: 13px; min-height: 13px; line-height: 1.0; text-wrap: unrestricted; white-space: -moz-pre-wrap; /* Moz */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ white-space: pre-wrap; /* CSS3 */ word-wrap: break-word; /* IE 5.5+ */ text-indent: -53px; padding-left: 53px; padding-bottom: 0px; margin: 0px; -webkit-transition-property: background-color, box-shadow; -webkit-transition-duration: 0.5s; -moz-transition-property: background-color, box-shadow; -moz-transition-duration: 0.5s; -ms-transition-property: background-color, box-shadow; -ms-transition-duration: 0.5s; -o-transition-property: background-color, box-shadow; -o-transition-duration: 0.5s; transition-property: background-color, box-shadow; transition-duration: 0.5s; } div.line.glow { background-color: cyan; box-shadow: 0 0 10px cyan; } span.lineno { padding-right: 4px; text-align: right; border-right: 2px solid #0F0; background-color: #E8E8E8; white-space: pre; } span.lineno a { background-color: #D8D8D8; } span.lineno a:hover { background-color: #C8C8C8; } div.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px; padding: 0.2em; border: solid thin #333; border-radius: 0.5em; -webkit-border-radius: .5em; -moz-border-radius: .5em; box-shadow: 2px 2px 3px #999; -webkit-box-shadow: 2px 2px 3px #999; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); } div.groupHeader { margin-left: 16px; margin-top: 12px; font-weight: bold; } div.groupText { margin-left: 16px; font-style: italic; } body { background-color: white; color: black; margin: 0; } div.contents { margin-top: 10px; margin-left: 12px; margin-right: 8px; } td.indexkey { background-color: #EBEFF6; font-weight: bold; border: 1px solid #C4CFE5; margin: 2px 0px 2px 0; padding: 2px 10px; white-space: nowrap; vertical-align: top; } td.indexvalue { background-color: #EBEFF6; border: 1px solid #C4CFE5; padding: 2px 10px; margin: 2px 0px; } tr.memlist { background-color: #EEF1F7; } p.formulaDsp { text-align: center; } img.formulaDsp { } img.formulaInl { vertical-align: middle; } div.center { text-align: center; margin-top: 0px; margin-bottom: 0px; padding: 0px; } div.center img { border: 0px; } address.footer { text-align: right; padding-right: 12px; } img.footer { border: 0px; vertical-align: middle; } /* @group Code Colorization */ span.keyword { color: #008000 } span.keywordtype { color: #604020 } span.keywordflow { color: #e08000 } span.comment { color: #800000 } span.preprocessor { color: #806020 } span.stringliteral { color: #002080 } span.charliteral { color: #008080 } span.vhdldigit { color: #ff00ff } span.vhdlchar { color: #000000 } span.vhdlkeyword { color: #700070 } span.vhdllogic { color: #ff0000 } blockquote { background-color: #F7F8FB; border-left: 2px solid #9CAFD4; margin: 0 24px 0 4px; padding: 0 12px 0 16px; } /* @end */ /* .search { color: #003399; font-weight: bold; } form.search { margin-bottom: 0px; margin-top: 0px; } input.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #e8eef2; } */ td.tiny { font-size: 75%; } .dirtab { padding: 4px; border-collapse: collapse; border: 1px solid #A3B4D7; } th.dirtab { background: #EBEFF6; font-weight: bold; } hr { height: 0px; border: none; border-top: 1px solid #4A6AAA; } hr.footer { height: 1px; } /* @group Member Descriptions */ table.memberdecls { border-spacing: 0px; padding: 0px; } .memberdecls td, .fieldtable tr { -webkit-transition-property: background-color, box-shadow; -webkit-transition-duration: 0.5s; -moz-transition-property: background-color, box-shadow; -moz-transition-duration: 0.5s; -ms-transition-property: background-color, box-shadow; -ms-transition-duration: 0.5s; -o-transition-property: background-color, box-shadow; -o-transition-duration: 0.5s; transition-property: background-color, box-shadow; transition-duration: 0.5s; } .memberdecls td.glow, .fieldtable tr.glow { background-color: cyan; box-shadow: 0 0 15px cyan; } .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams { background-color: #F9FAFC; border: none; margin: 4px; padding: 1px 0 0 8px; } .mdescLeft, .mdescRight { padding: 0px 8px 4px 8px; color: #555; } .memSeparator { border-bottom: 1px solid #DEE4F0; line-height: 1px; margin: 0px; padding: 0px; } .memItemLeft, .memTemplItemLeft { white-space: nowrap; } .memItemRight { width: 100%; } .memTemplParams { color: #4665A2; white-space: nowrap; font-size: 80%; } /* @end */ /* @group Member Details */ /* Styles for detailed member documentation */ .memtemplate { font-size: 80%; color: #4665A2; font-weight: normal; margin-left: 9px; } .memnav { background-color: #EBEFF6; border: 1px solid #A3B4D7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } .mempage { width: 100%; } .memitem { padding: 0; margin-bottom: 10px; margin-right: 5px; -webkit-transition: box-shadow 0.5s linear; -moz-transition: box-shadow 0.5s linear; -ms-transition: box-shadow 0.5s linear; -o-transition: box-shadow 0.5s linear; transition: box-shadow 0.5s linear; display: table !important; width: 100%; } .memitem.glow { box-shadow: 0 0 15px cyan; } .memname { font-weight: bold; margin-left: 6px; } .memname td { vertical-align: bottom; } .memproto, dl.reflist dt { border-top: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; padding: 6px 0px 6px 0px; color: #253555; font-weight: bold; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); background-image:url('nav_f.png'); background-repeat:repeat-x; background-color: #E2E8F2; /* opera specific markup */ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); border-top-right-radius: 4px; border-top-left-radius: 4px; /* firefox specific markup */ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -moz-border-radius-topright: 4px; -moz-border-radius-topleft: 4px; /* webkit specific markup */ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -webkit-border-top-right-radius: 4px; -webkit-border-top-left-radius: 4px; } .memdoc, dl.reflist dd { border-bottom: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; border-right: 1px solid #A8B8D9; padding: 6px 10px 2px 10px; background-color: #FBFCFD; border-top-width: 0; background-image:url('nav_g.png'); background-repeat:repeat-x; background-color: #FFFFFF; /* opera specific markup */ border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); /* firefox specific markup */ -moz-border-radius-bottomleft: 4px; -moz-border-radius-bottomright: 4px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; /* webkit specific markup */ -webkit-border-bottom-left-radius: 4px; -webkit-border-bottom-right-radius: 4px; -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); } dl.reflist dt { padding: 5px; } dl.reflist dd { margin: 0px 0px 10px 0px; padding: 5px; } .paramkey { text-align: right; } .paramtype { white-space: nowrap; } .paramname { color: #602020; white-space: nowrap; } .paramname em { font-style: normal; } .paramname code { line-height: 14px; } .params, .retval, .exception, .tparams { margin-left: 0px; padding-left: 0px; } .params .paramname, .retval .paramname { font-weight: bold; vertical-align: top; } .params .paramtype { font-style: italic; vertical-align: top; } .params .paramdir { font-family: "courier new",courier,monospace; vertical-align: top; } table.mlabels { border-spacing: 0px; } td.mlabels-left { width: 100%; padding: 0px; } td.mlabels-right { vertical-align: bottom; padding: 0px; white-space: nowrap; } span.mlabels { margin-left: 8px; } span.mlabel { background-color: #728DC1; border-top:1px solid #5373B4; border-left:1px solid #5373B4; border-right:1px solid #C4CFE5; border-bottom:1px solid #C4CFE5; text-shadow: none; color: white; margin-right: 4px; padding: 2px 3px; border-radius: 3px; font-size: 7pt; white-space: nowrap; vertical-align: middle; } /* @end */ /* these are for tree view inside a (index) page */ div.directory { margin: 10px 0px; border-top: 1px solid #9CAFD4; border-bottom: 1px solid #9CAFD4; width: 100%; } .directory table { border-collapse:collapse; } .directory td { margin: 0px; padding: 0px; vertical-align: top; } .directory td.entry { white-space: nowrap; padding-right: 6px; padding-top: 3px; } .directory td.entry a { outline:none; } .directory td.entry a img { border: none; } .directory td.desc { width: 100%; padding-left: 6px; padding-right: 6px; padding-top: 3px; border-left: 1px solid rgba(0,0,0,0.05); } .directory tr.even { padding-left: 6px; background-color: #F7F8FB; } .directory img { vertical-align: -30%; } .directory .levels { white-space: nowrap; width: 100%; text-align: right; font-size: 9pt; } .directory .levels span { cursor: pointer; padding-left: 2px; padding-right: 2px; color: #3D578C; } .arrow { color: #9CAFD4; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; cursor: pointer; font-size: 80%; display: inline-block; width: 16px; height: 22px; } .icon { font-family: Arial, Helvetica; font-weight: bold; font-size: 12px; height: 14px; width: 16px; display: inline-block; background-color: #728DC1; color: white; text-align: center; border-radius: 4px; margin-left: 2px; margin-right: 2px; } .icona { width: 24px; height: 22px; display: inline-block; } .iconfopen { width: 24px; height: 18px; margin-bottom: 4px; background-image:url('ftv2folderopen.png'); background-position: 0px -4px; background-repeat: repeat-y; vertical-align:top; display: inline-block; } .iconfclosed { width: 24px; height: 18px; margin-bottom: 4px; background-image:url('ftv2folderclosed.png'); background-position: 0px -4px; background-repeat: repeat-y; vertical-align:top; display: inline-block; } .icondoc { width: 24px; height: 18px; margin-bottom: 4px; background-image:url('ftv2doc.png'); background-position: 0px -4px; background-repeat: repeat-y; vertical-align:top; display: inline-block; } table.directory { font: 400 14px Roboto,sans-serif; } /* @end */ div.dynheader { margin-top: 8px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } address { font-style: normal; color: #2A3D61; } table.doxtable { border-collapse:collapse; margin-top: 4px; margin-bottom: 4px; } table.doxtable td, table.doxtable th { border: 1px solid #2D4068; padding: 3px 7px 2px; } table.doxtable th { background-color: #374F7F; color: #FFFFFF; font-size: 110%; padding-bottom: 4px; padding-top: 5px; } table.fieldtable { /*width: 100%;*/ margin-bottom: 10px; border: 1px solid #A8B8D9; border-spacing: 0px; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); } .fieldtable td, .fieldtable th { padding: 3px 7px 2px; } .fieldtable td.fieldtype, .fieldtable td.fieldname { white-space: nowrap; border-right: 1px solid #A8B8D9; border-bottom: 1px solid #A8B8D9; vertical-align: top; } .fieldtable td.fieldname { padding-top: 3px; } .fieldtable td.fielddoc { border-bottom: 1px solid #A8B8D9; /*width: 100%;*/ } .fieldtable td.fielddoc p:first-child { margin-top: 0px; } .fieldtable td.fielddoc p:last-child { margin-bottom: 2px; } .fieldtable tr:last-child td { border-bottom: none; } .fieldtable th { background-image:url('nav_f.png'); background-repeat:repeat-x; background-color: #E2E8F2; font-size: 90%; color: #253555; padding-bottom: 4px; padding-top: 5px; text-align:left; -moz-border-radius-topleft: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-left-radius: 4px; -webkit-border-top-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom: 1px solid #A8B8D9; } .tabsearch { top: 0px; left: 10px; height: 36px; background-image: url('tab_b.png'); z-index: 101; overflow: hidden; font-size: 13px; } .navpath ul { font-size: 11px; background-image:url('tab_b.png'); background-repeat:repeat-x; background-position: 0 -5px; height:30px; line-height:30px; color:#8AA0CC; border:solid 1px #C2CDE4; overflow:hidden; margin:0px; padding:0px; } .navpath li { list-style-type:none; float:left; padding-left:10px; padding-right:15px; background-image:url('bc_s.png'); background-repeat:no-repeat; background-position:right; color:#364D7C; } .navpath li.navelem a { height:32px; display:block; text-decoration: none; outline: none; color: #283A5D; font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); text-decoration: none; } .navpath li.navelem a:hover { color:#6884BD; } .navpath li.footer { list-style-type:none; float:right; padding-left:10px; padding-right:15px; background-image:none; background-repeat:no-repeat; background-position:right; color:#364D7C; font-size: 8pt; } div.summary { float: right; font-size: 8pt; padding-right: 5px; width: 50%; text-align: right; } div.summary a { white-space: nowrap; } div.ingroups { font-size: 8pt; width: 50%; text-align: left; } div.ingroups a { white-space: nowrap; } div.header { background-image:url('nav_h.png'); background-repeat:repeat-x; background-color: #F9FAFC; margin: 0px; border-bottom: 1px solid #C4CFE5; } div.headertitle { padding: 5px 5px 5px 10px; } dl { padding: 0 0 0 10px; } /* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ dl.section { margin-left: 0px; padding-left: 0px; } dl.note { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #D0C000; } dl.warning, dl.attention { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #FF0000; } dl.pre, dl.post, dl.invariant { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #00D000; } dl.deprecated { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #505050; } dl.todo { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #00C0E0; } dl.test { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #3030E0; } dl.bug { margin-left:-7px; padding-left: 3px; border-left:4px solid; border-color: #C08050; } dl.section dd { margin-bottom: 6px; } #projectlogo { text-align: center; vertical-align: bottom; border-collapse: separate; } #projectlogo img { border: 0px none; } #projectname { font: 300% Tahoma, Arial,sans-serif; margin: 0px; padding: 2px 0px; } #projectbrief { font: 120% Tahoma, Arial,sans-serif; margin: 0px; padding: 0px; } #projectnumber { font: 50% Tahoma, Arial,sans-serif; margin: 0px; padding: 0px; } #titlearea { padding: 0px; margin: 0px; width: 100%; border-bottom: 1px solid #5373B4; color: #FFFFFF; background: #006699; } .image { text-align: center; } .dotgraph { text-align: center; } .mscgraph { text-align: center; } .diagraph { text-align: center; } .caption { font-weight: bold; } div.zoom { border: 1px solid #90A5CE; } dl.citelist { margin-bottom:50px; } dl.citelist dt { color:#334975; float:left; font-weight:bold; margin-right:10px; padding:5px; } dl.citelist dd { margin:2px 0; padding:5px 0; } div.toc { padding: 14px 25px; background-color: #F4F6FA; border: 1px solid #D8DFEE; border-radius: 7px 7px 7px 7px; float: right; height: auto; margin: 0 20px 10px 10px; width: 200px; } div.toc li { background: url("bdwn.png") no-repeat scroll 0 5px transparent; font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; margin-top: 5px; padding-left: 10px; padding-top: 2px; } div.toc h3 { font: bold 12px/1.2 Arial,FreeSans,sans-serif; color: #4665A2; border-bottom: 0 none; margin: 0; } div.toc ul { list-style: none outside none; border: medium none; padding: 0px; } div.toc li.level1 { margin-left: 0px; } div.toc li.level2 { margin-left: 15px; } div.toc li.level3 { margin-left: 30px; } div.toc li.level4 { margin-left: 45px; } .inherit_header { font-weight: bold; color: gray; cursor: pointer; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .inherit_header td { padding: 6px 0px 2px 5px; } .inherit { display: none; } tr.heading h2 { margin-top: 12px; margin-bottom: 4px; } /* tooltip related style info */ .ttc { position: absolute; display: none; } #powerTip { cursor: default; white-space: nowrap; background-color: white; border: 1px solid gray; border-radius: 4px 4px 4px 4px; box-shadow: 1px 1px 7px gray; display: none; font-size: smaller; max-width: 80%; opacity: 0.9; padding: 1ex 1em 1em; position: absolute; z-index: 2147483647; } #powerTip div.ttdoc { color: grey; font-style: italic; } #powerTip div.ttname a { font-weight: bold; } #powerTip div.ttname { font-weight: bold; } #powerTip div.ttdeci { color: #006318; } #powerTip div { margin: 0px; padding: 0px; font: 12px/16px Roboto,sans-serif; } #powerTip:before, #powerTip:after { content: ""; position: absolute; margin: 0px; } #powerTip.n:after, #powerTip.n:before, #powerTip.s:after, #powerTip.s:before, #powerTip.w:after, #powerTip.w:before, #powerTip.e:after, #powerTip.e:before, #powerTip.ne:after, #powerTip.ne:before, #powerTip.se:after, #powerTip.se:before, #powerTip.nw:after, #powerTip.nw:before, #powerTip.sw:after, #powerTip.sw:before { border: solid transparent; content: " "; height: 0; width: 0; position: absolute; } #powerTip.n:after, #powerTip.s:after, #powerTip.w:after, #powerTip.e:after, #powerTip.nw:after, #powerTip.ne:after, #powerTip.sw:after, #powerTip.se:after { border-color: rgba(255, 255, 255, 0); } #powerTip.n:before, #powerTip.s:before, #powerTip.w:before, #powerTip.e:before, #powerTip.nw:before, #powerTip.ne:before, #powerTip.sw:before, #powerTip.se:before { border-color: rgba(128, 128, 128, 0); } #powerTip.n:after, #powerTip.n:before, #powerTip.ne:after, #powerTip.ne:before, #powerTip.nw:after, #powerTip.nw:before { top: 100%; } #powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { border-top-color: #ffffff; border-width: 10px; margin: 0px -10px; } #powerTip.n:before { border-top-color: #808080; border-width: 11px; margin: 0px -11px; } #powerTip.n:after, #powerTip.n:before { left: 50%; } #powerTip.nw:after, #powerTip.nw:before { right: 14px; } #powerTip.ne:after, #powerTip.ne:before { left: 14px; } #powerTip.s:after, #powerTip.s:before, #powerTip.se:after, #powerTip.se:before, #powerTip.sw:after, #powerTip.sw:before { bottom: 100%; } #powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { border-bottom-color: #ffffff; border-width: 10px; margin: 0px -10px; } #powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { border-bottom-color: #808080; border-width: 11px; margin: 0px -11px; } #powerTip.s:after, #powerTip.s:before { left: 50%; } #powerTip.sw:after, #powerTip.sw:before { right: 14px; } #powerTip.se:after, #powerTip.se:before { left: 14px; } #powerTip.e:after, #powerTip.e:before { left: 100%; } #powerTip.e:after { border-left-color: #ffffff; border-width: 10px; top: 50%; margin-top: -10px; } #powerTip.e:before { border-left-color: #808080; border-width: 11px; top: 50%; margin-top: -11px; } #powerTip.w:after, #powerTip.w:before { right: 100%; } #powerTip.w:after { border-right-color: #ffffff; border-width: 10px; top: 50%; margin-top: -10px; } #powerTip.w:before { border-right-color: #808080; border-width: 11px; top: 50%; margin-top: -11px; } @media print { #top { display: none; } #side-nav { display: none; } #nav-path { display: none; } body { overflow:visible; } h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } .summary { display: none; } .memitem { page-break-inside: avoid; } #doc-content { margin-left:0 !important; height:auto !important; width:auto !important; overflow:inherit; display:inline; } } singular-4.0.3+ds/doxy000077500000000000000000000034061266270727000146710ustar00rootroot00000000000000#!/usr/bin/env bash #!/bin/sh if [ "$#" -le 0 ]; then echo "Usage: $0 input_file(s)" >&2 exit 1 fi INPUT="$@" P=`pwd` # basename $0 C="$0" C=`dirname "$C"` C=`ls -d1 "$C"` TARGET_FILE="$C" cd `dirname "$TARGET_FILE"` TARGET_FILE=`basename "$TARGET_FILE"` # Iterate down a (possible) chain of symlinks while [ -L "$TARGET_FILE" ] do TARGET_FILE=`readlink "$TARGET_FILE"` cd `dirname "$TARGET_FILE"` TARGET_FILE=`basename "$TARGET_FILE"` done SRCDIR=`pwd -P` SRCDIR="$SRCDIR/$TARGET_FILE" # echo $SRCDIR if [ -z "$DOXYGEN" ]; then DOXYGEN=`which doxygen` if [ $? -ne 0 ]; then echo Please add 'doxygen' to your PATH exit 1 fi export DOXYGEN fi if [ ! -x "$DOXYGEN" ]; then echo Please make "$DOXYGEN" - executable!; exit 1; fi if [ -z "$DOXYGEN_CONFIG" ]; then export DOXYGEN_CONFIG="$SRCDIR/dox/Doxyfile.in1" fi if [ ! -r "$DOXYGEN_CONFIG" ]; then echo Please make the doxygen configuration readable: "$DOXYGEN_CONFIG"!; exit 1; fi cd "$P" INPUTTXT=`echo "$INPUT" | sed -e 's@[ :]@_@g' -e 's@[\\\/]@__@g'` OUTPUT="./DOXY.$INPUTTXT" # `mktemp -d -q "./DOXY.$INPUTTXT.XXX"` #if [ $? -ne 0 ]; then # echo "$0: Can't create temp dir name, exiting..." # exit 1 #fi if [ -d "$OUTPUT" ]; then echo "Directory '$OUTPUT' exists! Deleting..." rm -Rf "$OUTPUT/*" else mkdir -p "$OUTPUT/" fi export OUTPUT export INPUT export GENERATE_HTML=YES GENERATE_LATEX=YES GENERATE_RTF=YES GENERATE_MAN=YES GENERATE_XML=YES \ HTML_OUTPUT=htm LATEX_OUTPUT=tex RTF_OUTPUT=rtf MAN_OUTPUT=man XML_OUTPUT=xml export abs_top_srcdir="$SRCDIR" abs_top_builddir="$SRCDIR" echo Running "$DOXYGEN" "$DOXYGEN_CONFIG" with a bunch of exported variables $DOXYGEN $DOXYGEN_CONFIG echo Result for "$INPUT" is in "[$OUTPUT/]", under "[$P/]"... singular-4.0.3+ds/emacs/000077500000000000000000000000001266270727000150455ustar00rootroot00000000000000singular-4.0.3+ds/emacs/.emacs-general000066400000000000000000000141311266270727000175510ustar00rootroot00000000000000;;; Emacs edit mode for this file is -*- Emacs-Lisp -*- ;;; ;;; .emacs-general - Emacs initialization file for general emacs ;;; settings which have nothing to do with the ;;; singular-emacs mode, but which we recommend ;;; nevertheless, so that your emacs is more useful. ;;; ;;; This file is loaded by .emacs-singular, if it exists in your home directory ;;; or in the singular-emacs directory. ;;; ;;; If you have your own .emacs file, you might consider copying ;;; this file to your home directory and then load it from your .emacs ;;; file with: (load-file "~/.emacs-general") ;;; ;;; ;; a handy function for customizing the face of point (defun customize-face-at-point () "Customize face which point is at." (interactive) (let ((face (get-text-property (point) 'face))) (if face (customize-face face) (message "No face defined at point")))) ;; I love font-lock mode (add-hook 'emacs-lisp-mode-hook 'turn-on-font-lock) (add-hook 'lisp-mode-hook 'turn-on-font-lock) (add-hook 'c-mode-hook 'turn-on-font-lock) (add-hook 'c++-mode-hook 'turn-on-font-lock) (add-hook 'perl-mode-hook 'turn-on-font-lock) (add-hook 'tex-mode-hook 'turn-on-font-lock) (add-hook 'texinfo-mode-hook 'turn-on-font-lock) (add-hook 'postscript-mode-hook 'turn-on-font-lock) (add-hook 'dired-mode-hook 'turn-on-font-lock) (add-hook 'ada-mode-hook 'turn-on-font-lock) (add-hook 'TeX-mode-hook 'turn-on-font-lock) (add-hook 'shell-mode-hook 'turn-on-font-lock) ;;; ;;; settings for both Emacs and XEmacs ;;; (custom-set-variables '(next-line-add-newlines nil) '(require-final-newline nil) '(line-number-mode t) '(kill-whole-line t) '(truncate-lines t) ; I like unique buffer names based on dirs '(uniquify-buffer-name-style 'post-forward-angle-brackets)) (require 'uniquify) (cond ((string-match "XEmacs\\|Lucid" emacs-version) ;; ;; XEmacs specific stuff ;; ;; I like some more keybindings for better moving (define-key global-map '(control up) '(lambda () (interactive) (scroll-up -1))) ;; control-, scrolls up (define-key global-map '(control down) '(lambda () (interactive) (scroll-up 1))) ;; a function which on C-= reload a file automatically without ;; asking for confirmation got it from From: Richard Mlynarik ;; on 1/18/95 ;; find-alternate-file (C-x C-v) is almost equivalent (global-set-key [(control =)] '(lambda () (interactive) (or (verify-visited-file-modtime (current-buffer)) (revert-buffer t t)))) ;; turn on auto-compression of gz files (toggle-auto-compression 1) ;; Use the "Describe Variable..." option on the "Help" menu ;; or C-h v to find out what these variables mean. (custom-set-variables '(complex-buffers-menu-p t) '(kill-whole-line t)) (setq minibuffer-confirm-incomplete t) ;; show matching parantheses (paren-set-mode 'paren) ;; func-menu is a package that scans your source file for function ;; definitions and makes a menubar entry that lets you jump to any ;; particular function definition by selecting it from the menu. The ;; following code turns this on for all of the recognized languages. (require 'func-menu) (define-key global-map 'f8 'function-menu) (add-hook 'find-file-hooks 'fume-add-menubar-entry) (define-key global-map "\C-cl" 'fume-list-functions) (define-key global-map "\C-cg" 'fume-prompt-function-goto) ;; The Hyperbole information manager package uses (shift button2) and ;; (shift button3) to provide context-sensitive mouse keys. If you ;; use this next binding, it will conflict with Hyperbole's setup. ;; Choose another mouse key if you use Hyperbole. (define-key global-map '(shift button3) 'mouse-function-menu) ;; For descriptions of the following user-customizable variables, ;; type C-h v (setq fume-max-items 25 fume-fn-window-position 3 fume-auto-position-popup t fume-display-in-modeline-p t fume-menubar-menu-location "File" fume-buffer-name "*Function List*" fume-no-prompt-on-valid-default nil) ;; end Xemacs stuff ) (t ;; ;; Emcas stuff ;; ;; show matching parantheses (show-paren-mode t) ;; turn on auto (de)compression of files (auto-compression-mode t) ;; End Emcas stuff ) ) ;; use auctex as default mode for editing latex stuff (let ((auctex-filename (locate-library "tex-site"))) (if auctex-filename (require 'tex-site auctex-filename))) ;; put stuff here which should not be/only be executed under ;; mswindows/unix (cond ((or (eq system-type 'cygwin32) (eq system-type 'windows-nt)) ;;; mswindows stuff ;; Let shell be /bin/bash, if it exists (cond ((file-exists-p "/bin/bash") (setq explicit-shell-filename "/bin/bash") (setq explicit-bash-args (list "--login" "-i")))) ; patch these function so that they do not use ~ for backup under ; mswindows (defun make-backup-file-name (file) "Create the non-numeric backup file name for FILE. This is a separate function so you can redefine it for customization." (if (eq system-type 'ms-dos) (let ((fn (file-name-nondirectory file))) (concat (file-name-directory file) (if (string-match "\\([^.]*\\)\\(\\..*\\)?" fn) (substring fn 0 (match-end 1))) ".bak")) (if (or (eq system-type 'cygwin32) (eq system-type 'windows-nt)) (concat file ".bak") (concat file "~")))) (defun backup-file-name-p (file) "Return non-nil if FILE is a backup file name (numeric or not). This is a separate function so you can redefine it for customization. You may need to redefine `file-name-sans-versions' as well." (if (or (eq system-type 'ms-dos) (eq system-type 'cygwin32) (eq system-type 'windows-nt)) (string-match "\\.bak\\'" file) (string-match "~\\'" file))) ;;; end mswindows stuff ) (t ;;; stuff for unix only ;;; end stuff for unix only )) singular-4.0.3+ds/emacs/.emacs-singular000066400000000000000000000220701266270727000177610ustar00rootroot00000000000000;;; Emacs edit mode for this file is -*- Emacs-Lisp -*- ;;; ;;; .emacs-singular - Emacs initialization file to use for ;;; Singular interactive mode. ;;; ;;; If you run ESingular, then this file is loaded instead of the ;;; default ~/.emacs initialization file. ;;; ;;; How you use this file very much depends on your attitude ;;; towards Emacs: ;;; ;;; 1) If you are going to use Emacs solely as frontend to ;;; Singular you do not have to worry at all about this file. ;;; 2) If you are already an experienced Emacs user you may ;;; want to copy this file's contents to your .emacs file. ;;; 3) If you are planning to become an experienced Emacs user ;;; you may use this file as starting point for your .emacs ;;; file, that is, for your Emacs initialization file. Simply ;;; copy it to your home directory and rename it to ".emacs" ;;; (without the quotes, of course). Then edit it as ;;; described below. ;;; ;;; In cases 2) and 3) you should be careful what exactly to copy ;;; to your .emacs file. In general, you need the following: ;;; ;;; o the hook-customizations with `add-hook'; ;;; o the pre-customized settings with `custom-set-variables' and ;;; `custom-set-faces'; ;;; o the code which creates menus for starting Singular; ;;; o the code which loads singular.el (located at the end of ;;; this file) you have to replace by something else, for ;;; example, an `autoload'. ;;; o the code which is in .emacs-general ;;; ;;; Here is how the Singular customization in your .emacs may ;;; look like: ;;; ;;; ;; extra key bindings ;;; (add-hook 'singular-interactive-mode-hook ;;; <... code omitted, see below for details ...>) ;;; ;;; ;; other, "non-customizable" settings ;;; (add-hook 'singular-interactive-mode-hook ;;; <... code omitted, see below for details ...>) ;;; ;;; ;; pre-customized settings ;;; (custom-set-variables ;;; <... code omitted, see below for details ...>) ;;; (custom-set-faces ;;; <... code omitted, see below for details ...>) ;;; ;;; ;; add global menus for Singular ;;; <... choose your version for either Emacs or XEmacs, see below ...> ;;; ;;; ;; add Singular toolbar for XEmacs ;;; <... insert the code below if you are running XEmacs ...> ;;; ;;; ;; add Singular Emacs home directory to `load-path' ;;; (setq load-path (cons "" load-path)) ;;; (autoload 'singular "singular" ;;; "Start Singular using default values." t) ;;; (autoload 'singular-other "singular" ;;; "Ask for arguments and start Singular." t) ;;; ;; extra key bindings (add-hook 'singular-interactive-mode-hook (function (lambda () ;; control cursor keys (cond ;; Emacs ((eq singular-emacs-flavor 'emacs) (local-set-key [C-prior] 'singular-scroll-right) (local-set-key [C-next] 'singular-scroll-left) (local-set-key [C-up] 'comint-previous-prompt) (local-set-key [C-down] 'comint-next-prompt)) ;; XEmacs (t (local-set-key [(control prior)] 'singular-scroll-right) (local-set-key [(control next)] 'singular-scroll-left) (local-set-key [(control up)] 'comint-previous-prompt) (local-set-key [(control down)] 'comint-next-prompt)))))) ;; other, "non-customizable" settings ;; put stuff here which should not be/only be executed under ;; mswindows/unix (cond ((or (eq system-type 'cygwin32) (eq system-type 'windows-nt)) ;; mswindows stuff ) (t ;; unix stuff ;; lazy-lock seems to be broken under mswindows: ;; causes delay of input (only reacts after mouse click), or even total ;; hang ;(add-hook 'font-lock-mode-hook 'lazy-lock-mode) ;(setq font-lock-support-mode 'lazy-lock-mode) ;; somewhat nicer scrolling This causes a core dump with 21.1.9 ;; under cygwin, when a file is opened with a button ;; Fixed it with a simmple patch, by working around the ;; assertion in file indent.c line 517 (or so). This was ;; officially fixed in 21.1.10 -- still sometimes ;; interactive windows disappeared. Hence, do not set it under ;; Windows (setq scroll-step 10) ) ) (add-hook 'singular-interactive-mode-hook (function (lambda () (font-lock-mode 1)))) ;; turn on c++-mode for files ending in ".sing" and ".lib" (setq auto-mode-alist (cons '("\\.sing\\'" . c++-mode) auto-mode-alist)) (setq auto-mode-alist (cons '("\\.lib\\'" . c++-mode) auto-mode-alist)) (add-hook 'c++-mode-hook (function (lambda () (font-lock-mode 1)))) ;; this is a work-around for early version of Font Lock mode ;; which do not use `defface' to define faces. It forces ;; `custom-set-faces' to define the faces immediately. (make-face 'font-lock-comment-face) (make-face 'font-lock-string-face) ;; tricky stuff: these customization settings are not used any ;; longer as soon as user saved her own to ~/.emacs-singular-cust (setq custom-file "~/.emacs-singular-cust") (if (file-exists-p custom-file) (load-file custom-file) ;; pre-customized settings (custom-set-variables '(mouse-yank-at-point t) '(font-lock-maximum-decoration t t) '(next-line-add-newlines nil) '(paren-mode (quote paren) nil (paren)) '(show-paren-mode t nil (paren)) '(singular-help-same-window t) '(singular-cursor-key-model (quote terminal)) '(transient-mark-mode t) '(Info-button1-follows-hyperlink t) '(singular-section-face-alist (quote ((input . singular-section-input-face) (output))))) (custom-set-faces '(info-xref ((t (:foreground "blue" :bold t)))) '(info-node ((t (:foreground "blue" :bold t :italic t)))) '(show-paren-match-face ((((class color)) (:foreground "Red")))) '(font-lock-variable-name-face ((t (:foreground "black"))) t) '(paren-match ((t (:foreground "Red"))) t) '(singular-section-input-face ((t (:bold t)))) '(font-lock-string-face ((((class color) (background light)) (:foreground "green4")))) '(font-lock-doc-string-face ((((class color) (background light)) (:foreground "green4")))) '(font-lock-keyword-face ((t (:bold t :foreground "violet"))) t) '(singular-section-output-face ((t (:bold nil)))) '(font-lock-type-face ((t (:bold t :foreground "violet"))) t) '(font-lock-comment-face ((t (:bold nil :foreground "Red"))) t) '(font-lock-function-name-face ((t (:bold t :foreground "blue3"))) t)) '(info-xref ((t (:foreground "blue" :bold t)))) '(info-node ((t (:foreground "blue" :bold t :italic nil)))) ;; obachman: played around a little bit, found this better ;; '(singular-section-input-face ((t (:bold t)))) ;; '(singular-section-output-face ((t (:bold nil)))) ;; '(font-lock-comment-face ((t (:bold nil :foreground "Grey30"))) t) ;; '(font-lock-string-face ((((class color) (background light)) (:foreground "Blue")) (((class color) (background dark)) (:foreground "LightSkyBlue"))) t) ;; '(paren-match ((t (:foreground "Red"))) t) ;; '(show-paren-match-face ((((class color)) (:foreground "Red"))))) ) ;; update singular-emacs-home-directory (setq singular-emacs-home-directory (concat singular-emacs-home-directory ;; we check for trailing slash and backslash ;; but unconditionally insert a slash. ;; Hopefully that works on NT, too. (if (memq (aref singular-emacs-home-directory (1- (length singular-emacs-home-directory))) '(?/ ?\\)) "" "/"))) ;; add global menus for Singular, Emacs version (unless (fboundp 'add-submenu) (setq singular-start-map (make-sparse-keymap)) (define-key singular-start-map [menu-bar singular] (cons "Singular" (make-sparse-keymap "Singular"))) (define-key singular-start-map [menu-bar singular restart] '("Start..." . singular-other)) (define-key singular-start-map [menu-bar singular start-default] '("Start default" . singular)) (setq menu-bar-final-item (append '(singular) menu-bar-final-items)) (use-local-map singular-start-map)) ;; add global menus for Singular, XEmacs version (when (fboundp 'add-submenu) (add-submenu nil '("Singular" ["Start default" singular t] ["Start..." singular-other t])) (setq-default current-menubar current-menubar)) ;; add Singular button to toolbar for XEmacs ;(if (fboundp 'toolbar-add-item) ; (toolbar-add-item ; (vector ; (toolbar-make-button-list (concat singular-emacs-home-directory ; "singular.xpm")) ; 'singular t "Start Singular") ; (length (specifier-instance default-toolbar)))) ; ;;; ;;; - load singular.el and .emacs-general ;;; ; get rid of superfluous "Load .emacs" menu entry on XEmacs (when (fboundp 'delete-menu-item) (delete-menu-item '("Load .emacs")) ; that is for the current buffer (let ((current-menubar (default-value 'current-menubar))) (delete-menu-item '("Load .emacs")) ; that is for all other buffers (set-default 'current-menubar current-menubar))) ; load singular.el from `singular-emacs-home-directory' (load-file (concat singular-emacs-home-directory "singular.el")) ; load .emacs-general from home or `singular-emacs-home-directory' (if (file-exists-p "~/.emacs-general") (load-file "~/.emacs-general") (if (file-exists-p (concat singular-emacs-home-directory ".emacs-general")) (load-file (concat singular-emacs-home-directory ".emacs-general")))) singular-4.0.3+ds/emacs/COPYING000066400000000000000000000027131266270727000161030ustar00rootroot00000000000000 SINGULAR version 4-0 Singular-ESingular University of Kaiserslautern Department of Mathematics and Centre for Computer Algebra Authors: G.-M. Greuel, G. Pfister, H. Schoenemann Copyright (C) 1986-2016 *NOTICE* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation ( version 2 or version 3 of the License ); with the following additional remarks: This package is part of the software SINGULAR. The GPL is valid for this package, other packages may have other copyrights. Their copyrights and licences can be found in the accompanying files which are distributed along with these packages. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA (see GPL) Please send any comments or bug reports to . Availability ============ The latest information about SINGULAR is always available from `http://www.singular.uni-kl.de'. singular-4.0.3+ds/emacs/ChangeLog000066400000000000000000001067471266270727000166360ustar00rootroot000000000000002000-05-19 T. Wichmann * singular.el (singular-exec): Remove empty strings from SWITCHES 1999-12-06 T. Wichmann * singular.el (singular-internal): Removed bug: Adding of trailing slash crashed if directory was nil (singular-completion-do): Added completion of examples (singular-example): Added (including key-binding and menu item) 1999-09-14 T. Wichmann * singular.el (singular-exit-singular): New strategy for the communication between `singular-exit-singular' and `singular-exit-sentinel'. Some new functions and variables introduced. (singular-restart): now deletes a running singular process (singular-exit-sentinel): On demand inserts a string indicating that the process was killed 1999-09-08 T. Wichmann * singular.el (singular-interactive-mode-menu-init): Also remove "Singular"-start menu (singular-interactive-mode-map): corrected key for singular-exit-singular (singular-help): added new version of Jens * .emacs-singular Singular start menu for XEmacs appears now in every buffer 1999-09-01 T. Wichmann * singular.el (singular-interactive-mode): added (singular-exec-init) and (singular-comint-init) 1999-08-31 T. Wichmann * .emacs-singular added template for Singular button in toolbar * singular.el (singular-dynamic-complete): regexp singular-prompt-regexp now is obsolete. Used (singular-prompt-skip-forward) instead key pattern for "C-c $" and "C-c <" changed (did not work for emacs20) (singular-interactive-mode-menu-1/2): updated (singular-expand-emacs-file-name): conditionally append "/" to singular-emacs-home-directory 1999-08-30 T. Wichmann * singular.el (singular, singular-restart, singular-other): Doc strings rewritten 1999-08-25 T. Wichmann * singular.el (singular-other) now has 4 arguments * singular.el Added "-t" to singular-switches-magic 1999-08-23 T. Wichmann * singular.el (singular-interactive-mode-menu-init): Any menu installed by comint-mode is removed * singular.el (singular-exit-sentinel): remove libraries menu only if buffer is existent * singular.el Added a "*" to some variables` doc string 1999-08-27 Jens Schmidt * .bashrc (STARTUP): load `cmpl-hlp.el' now * singular.el: `Online help' folding finished 1999-08-26 Jens Schmidt * singular.el (singular-error): new function * .bashrc: adapted to new Singular version * .emacs-singular: code removed that starts Singular * .emacs-singular: code added to add global menus for Emacs and XEmacs * .emacs-singular: settings for `singular-help-same-window' added. Settings for `singular-history-keys' and `singular-cursor-keys' removed. 1999-08-24 Jens Schmidt * singular.el (singular-same-window): new defcustom (singular): uses the above variable to pop to buffer * singular.el: Folding `Starting Singular' renamed to `Starting and stopping Singular' (singular-exit-singular): moved to that folding * singular.el (singular-move-on-send): marked as user option * singular.el (singular-demo-last-directory): new variable (singular-demo-mode-init): makes the above variable buffer-local (singular-demo-load): uses and sets the above variable in interactive specifier * singular.el (singular-demo-print-messages, singular-demo-exit-on-load): default values changed * singular.el (singular-demo-chunk-regexp, singular-demo-print-messages, singular-demo-exit-on-load, singular-demo-load-directory): marked as user options * singular.el: Lots of changes to `Online help' folding. Is still quiet experimental. * singular.el (singular-history-ignoredups, singular-history-size, singular-history-filter-regexp, singular-history-explicit-file-name): marked as user options * singular.el (singular-beginning-of-line): new function * singular.el (singular-toggle-truncate-lines): bug fix. Does frame refresh now after toggling value. * singular.el (singular-pop-to-buffer): new function. Used in `singular-help' and `singular'. * singular.el (singular-cursor-key-model): new defcustom replacing former `singular-history-keys' and `singular-cursor-keys' (singular-cursor-key-model-set): new function replacing former `singular-history-cursor-keys-set' and `singular-history-cursor-key-set' static initialization removed * singular.el (singular-interactive-mode-map): key bindings added for: `singular-help' `singular-beginning-of-line' `singular-toggle-truncate-lines' `singular-demo-load' `singular-load-library' `singular-load-file' `singular-restart' `singular-exit-singular' * singular.el (singular): new customizing group (singular-interactive): made a subgroup of the above group 1999-08-20 Jens Schmidt * singular.el (singular-move-on-send): new defcustom (singular-get-old-input, singular-send-or-copy-input): slightly rewritten * singular.el (singular-demo-chunk-regexp, singular-demo-print-messages, singular-demo-exit-on-load, singular-demo-load-directory): `:initialize' tags added * singular.el: folding `Skipping and stripping prompts and newlines ...' completely rewritten. Almost all variables and constants removed. Functions and variables renamed: singular-skip-prompt-forward to singular-prompt-skip-forward singular-skip-prompt-backward to singular-prompt-skip-backward singular-strip-leading-prompt to singular-prompt-remove-string singular-remove-prompt to singular-prompt-remove-region singular-remove-prompt-filter to singular-prompt-remove-filter singular-strip-white-space to singular-white-space-strip singular-prompt-regexp to singular-comint-prompt-regexp All references changed. New function `singular-prompt-init' added which is called in `singular-interactive-mode' * .emacs-singular: loads customization from ~/.emacs-singular-cust if present * .emacs-singular: loads singular.el from `singular-emacs-home-directory' * .emacs-singular: code added to remove "Load .emacs" menu entry on XEmacs * .emacs-singular: doc fixes * .bashrc: variables `singular-emacs-home-directory' and `singular-help-file-name' added to commandlines 1999-08-18 T. Wichmann * singular.el singular-help-file-name variable introduced added section for singular-*-alists some defvars changed to defconsts (singular-scan-header-exit) introduced fancier calculation of singular-scan-header-scan-for (singular-scan-header-got-emacs-home) introduced singular-executable-default, ... are now defcustom (singular-exit-sentinel) now call (singular-scan-header-exit) * singular.el: added (singular-comint-init) improved dynamical generation of library menu scan header functionality improved scan header now gets initialized on every start of Singular singular-completion-* variables renamed (singular) renamed to (singular-internal) new functions (singular), (singular-restart), (singular-other) new variables for last singular arguments incl. history 1999-08-15 Jens Schmidt * singular.el: new folding `Sending input interactive'. Functions `singular-get-old-input' and `singular-send-or-copy-input' moved to that folding. * singular.el: folding `Skipping and stripping prompts and newlines ...' renamed to `Skipping and stripping prompts and whitespace ...' * singular.el (singular-interactive-mode): slightly re-organized * singular.el (singular-demo-show-next-chunk): bug fix * singular.el (singular-section-kill): new function (singular-interactive-mode-map): key binding added for the aforementioned function * singular.el (singular-section-to-string): renamed from `singular-input-section-to-string'. Optional argument END removed. All callers changed. * singular.el (singular-section-check): new function singular.el (singular-folding-fold, singular-folding-unfold): use `singular-section-check' 1999-08-11 T. Wichmann * singular.el: code for menu support rewritten scanning of singular header implemented dynamic completion implemented 1999-08-10 Jens Schmidt * singular.el (singular-history-insert): does not check `singular-demo-insert-into-history' any longer (singular-demo-insert-into-history): variable removed 1999-08-09 Jens Schmidt * singular.el: doc fixes 1999-08-08 Jens Schmidt * .emacs (singular-interactive-mode-hook): key bindings for scrolling commands changed * singular.el (singular-current-output-section): bug fix. `save-restriction' added. * singular.el (singular-folding-toggle-fold-latest-output): completely rewritten (singular-folding-toggle-fold-at-point, singular-folding-toggle-fold-all-output): removed (singular-folding-toggle-fold-at-point-or-all): new function * singular.el (singular-folding-fold): checks that section is unfolded before folding (singular-folding-unfold): checks that section is folded before unfolding. Uses optional argument INVISIBILITY-OVERLAY-OR-EXTENT. * singular.el (singular-xemacs-folding-unfold-internal): assumes that section is folded and uses optional argument INVISIBILITY-EXTENT (singular-xemacs-folding-fold-internal): assumes that section is unfolded (singular-emacs-folding-fold-internal, singular-emacs-folding-unfold-internal): same changes as for XEmacs * singular.el (singular-xemacs-folding-foldedp-internal, singular-emacs-folding-foldedp-internal): cosmetical changes * singular.el (singular-font-lock-singular-types): initialization moved out of `defconst' for Byte Compiler to recognize * singular.el (singular-keep-region-active): new function (singular-section-goto-beginning, singular-section-goto-end, singular-section-backward, singular-section-forward): calls to that function added * singular.el: new folding `Miscellaneous' in folding `Code common to both modes' added * singular.el: Folding `Simple section stuff ...' and `Section stuff' renamed to `Simple section API ...' and `Section API', respectively. New foldings `Section miscellaneous' and `Section miscellaneous interactive'. Folding `Getting section contents' removed, contents moved to `Section miscellaneous'. Folding `Input and output filters' removed, contents moved to `Skipping and stripping ...'. * singular.el.decl: changed accordingly * singular.el.decl: docu on access specifiers and types added, declarations re-checked and updated. 1999-08-07 Jens Schmidt * singular.el: preliminary and experimental version of online help stuff added * singular.el: doc fixes. I almost forgot about them. * singular.el (singular-time-stamp-difference): new function * singular.el (singular-interactive-mode-map): bindings added for `singular-folding-toggle-fold-at-point', `singular-folding-toggle-fold-latest-output', and `singular-folding-toggle-fold-all-output' * singular.el (singular-folding-unfold): new function (singular-folding-toggle-fold-at-point, singular-folding-toggle-fold-latest-output, singular-folding-toggle-fold-all-output): new functions * singular.el (singular-interactive-mode-map): bindings added for `comint-previous-matching-input' and `comint-next-matching-input' 1999-08-01 Jens Schmidt * .emacs (singular-interactive-mode-hook): Font Lock mode turned on for Singular interactive mode * .emacs (singular-interactive-mode-hook): key-bindings added 1999-07-31 Jens Schmidt * singular.el: `Skipping and stripping prompts and newlines and other things' moved * singular.el (singular-exit-sentinel): bug fix. * singular.el (singular-prompt-skip-forward): renamed from `singular-prompt-skip-forward'. All references replaced. * singular.el (singular-history-ignoredups, singular-history-size, singular-history-filter-regexp, singular-history-explicit-file-name): new defcustoms (singular-history-read, singular-history-write, singular-history-insert, singular-history-init): new functions. Calls added to the necessary functions. * singular.el: new folding `Miscellaneous interactive' introduced * singular.el (singular-recenter, singular-reposition-point-and-window): new functions (singular-toggle-truncate-lines): uses `singular-reposition-point-and-window' instead of recenter (singular-scroll-previous-amount): new variable (singular-scroll-right, singular-scroll-left): new variables * singular.el (singular-process, singular-process-mark): accept optional argument NO-ERROR now and throw an error if Singular is not alive (singular-load-file, singular-load-library): rely on errors from `singular-process' to catch dead processes * singular.el (singular-buffer-name-to-process-name, singular-process-name-to-buffer-name, singular-run-hook-with-arg-and-value, singular-process, singular-process-mark): declared as `defsubst' * singular.el: almost all key bindings thrown out. Needs to be re-designed. * singular.el: more doc fixes * singular.el: doc fixes and cosmetical changes 1999-07-29 Jens Schmidt * singular.el: Folding `Last input and output section' moved * singular.el.decl: changes from singular.el included * singular.el (singular-demo-load): uses `singular-demo-load-directory' to load files (singular-demo-load): behaviour on running new demo if there is old one made customizable (singular-demo-load): bug fix for Emacs which moves pointers on file insertion * singular.el (singular-demo-command-on-enter, singular-demo-command-on-leave): variables removed. Instead, hooks are run now in `singular-demo-exit-internal' and `singular-demo-load'. * singular.el (singular-demo-mode): function disolved to a number of smaller functions. See below. (singular-demo-exit-internal): new function (singular-demo-exit): completely rewritten * singular.el (singular-demo-show-next-chunk): bug fix in white space stripping at end of demo * singular.el (singular-demo-mode-init): new function. Call added to `singular-interactive-mode'. * singular.el (singular-demo-chunk-regexp): made a defcustom (singular-demo-insert-into-history): new custom (singular-demo-print-messages): made a defcustom (singular-demo-exit-on-load): new custom (singular-demo-load-directory): new custom * singular.el (singular-interactive-mode): sets `comint-mode-hook' to nil before calling `comint-mode' (singular-exec): does not run hooks on `comint-exec-hook' any longer * singular.el: new folding for Comint stuff folding `Customizing variables of comint' removed folding `History' added * singular.el (singular-demo-mode): new group * singular.el: doc fixes 1999-07-25 Jens Schmidt * .emacs (transient-mark-mode): switched on * singular.el.decl: all foldings updated to revision 1.38. Section stuff and Key map revised. * singular.el: doc fixes and cosmetical changes 1999-07-25-b Jens Schmidt * singular.el: Key binding stuff almost completely rewritten. Features now: new customs `singular-history-keys', `singular-cursor-keys' and back-end functions `singular-history-cursor-keys-set' and `singular-history-cursor-key-set'. New function `singular-interactive-mode-map-init' added and call to that function in `singular-interactive-mode'. Key map does not inherit keymap from `comint-mode' any longer. New prefix maps used. * singular.el (singular-demo-load): uses `insert-file-contents-literally' now * singular.el (singular-section-goto-beginning, singular-section-goto-end, singular-section-backward, singular-section-forward: new functions * singular.el (singular-section-face-alist, singular-folding-ellipsis, singular-folding-line-move-ignore-folding): cosmetical changes * singular.el: menu and logo stuff moved to respective folding (singular-interactive-mode-menu-init): new function (singular-interactive-mode): call to that function added * singular.el (singular-interactive-font-lock-defaults): SYNTAX-BEGIN set to `singular-section-goto-beginning' * singular.el (singular-interactive-miscellaneous): new group * singular.el (singular-map-buffer): moved to Customization folding * singular.el: doc fixes * .emacs (singular-cursor-keys, singular-history-keys): settings added * .emacs: work around for face problems on XEmacs added 1999-07-25-a Jens Schmidt * singular.el (singular-section-face-alist, singular-section-input-face, singular-section-output-face): new customs * singular.el (singular-emacs-simple-sec-in, singular-section-mapsection): rewritten. Much more beautiful now * singular.el: doc fixes 1999-07-24 Jens Schmidt * singular.el (singular-debug-pre-input-filter, singular-debug-post-input-filter, singular-debug-pre-output-filter, singular-debug-post-output-filter): cosmetical changes (singular-debug-filter-init): new function. (singular-interactive-mode): calls that function instead of initializing the filters on itself * .bashrc: new file * .emacs (custom-file): set * .emacs: loads and starts Singular interactive mode * .emacs-customize: renamed to .emacs 1999-07-24-b Jens Schmidt * singular.el: Font Lock mode support completely re-written: Faces defined with `defface', regular expressions simplified, call to `regexp-opt' added, `eval-when-compile' hack included, doc strings re-written to official wording, function `singular-interactive-font-lock-init' added, everything (except faces) renamed to prefix "singular-interactive-font-lock", etc. * singular.el (singular-simple-sec-lookup-face): new subst. Calls added in `singular-emacs-simple-sec-create' and `singular-xemacs-simple-sec-create' (singular-section-face-alist): new custom (singular-section-input-face, singular-section-input-face): new faces * singular.el: doc fixes * .emacs-customize (show-paren-mode): new file 1999-07-24-a Jens Schmidt * singular.el (singular-xemacs-simple-sec-create): slightly rewritten (singular-xemacs-simple-sec-start-at): Handles imagenary clear simple section at eob correctly now (singular-xemacs-simple-sec-end-at, singular-xemacs-simple-sec-at): cosmetical changes (singular-xemacs-simple-sec-in): completely rewritten * singular.el (singular-faces, singular-sections-and-foldings): new groups * singular.el (singular-folding-ellipsis, singular-folding-line-move-ignore-folding): moved to group `singular-sections-and-foldings' * singular.el: doc fixes, of course 1999-07-23 Jens Schmidt * singular.el (singular-folding-fold-at-point, singular-folding-unfold-at-point, singular-folding-fold-latest-output, singular-folding-unfold-latest-output, singular-folding-fold-all-output, singular-folding-unfold-all-output): (re-)new functions * singular.el (singular-folding-fold): accepts optional argument NO-ERROR * singular.el (singular-folding-line-move-ignore-folding): new defcustom * singular.el (singular-section-mapsection): new function * singular.el (singular-map-buffer): new function * singular.el (singular-folding-init): adapted to XEmacs (singular-xemacs-folding-fold-internal, singular-xemacs-folding-foldedp-internal, singular-xemacs-folding-unfold-internal): new functions * singular.el: doc fixes (what else?) 1999-07-22 Jens Schmidt * singular.el-07-22 (singular-emacs-folding-fold-internal): bug fix * singular.el-07-22 (singular-folding-ellipsis): sets ellipsis in already running Singulars (singular-folding-set-ellipsis-in-singular-buffers, singular-folding-set-ellipsis): new functions * singular.el-07-22 (singular-section-in): restriction algorithm changed. Restricts to whole sections now. (singular-section-in-internal): new function used by `singular-section-in' * singular.el-07-22 (singular-emacs-simple-sec-in): bug fix * singular.el-07-22: doc fixes, of course 1999-07-19 Jens Schmidt * singular.el: Folding stuff completely rewritten. (singular-interactive-mode): Folding stuff initialization moved to new function `singular-folding-init' * singular.el (singular-process, singular-process-mark, singular-simple-sec-last-end-position): bug fixes * singular.el (singular-interactive): new group * singular.el: face initialization for XEmacs slightly re-organized * singular.el (singular-mode-syntax-table-init): new function. Called from `singular-interactive-mode'. * singular.el: doc fixes, of course. 1999-07-18-a Jens Schmidt * singular.el (singular-section-in): completely rewritten. Handles restrictions now. * singular.el (singular-section-at): handles degenerate restriction cases correctly now * singular.el (singular-section-simple-sec, singular-section-type, singular-section-start, singular-section-end): defined as subst * singular.el (singular-section-create): new subst. Used in all instances where new sections are generated. * singular.el: A number of changes in the XEmacs simple section stuff. However, there are still some changes from the Emacs simple section stuff that have to be re-done for the XEmacs stuff, too. * singular.el (singular-emacs-simple-sec-in): implemented * singular.el (singular-simple-sec-end, singular-simple-sec-start, singular-simple-sec-type, singular-simple-sec-before): defined as subst * singular.el (singular-emacs-simple-sec-create): slightly rewritten. Should be a little bit faster now. * singular.el (singular-simple-sec-reset-last, singular-xemacs-simple-sec-reset-last, singular-emacs-simple-sec-reset-last): removed * singular.el (singular-simple-sec-last-end-position): new macro. Used whenever position of last simple section is accessed. * singular.el (singular-input-section-to-string): cosmetical changes * singular.el (singular-mode-syntax-table): (my own) bug fixed in initialization * singular.el: doc fixes. A *lot* of doc fixes. 1999-07-17 Jens Schmidt * singular.el (singular-load-file, singular-load-library): checks added whether process is running * singular.el (singular-interactive-mode-map): settings for singular-demo-exit uncommented. Does not work on Emacs. * singular.el (font-lock-singular-prompt-face): bug fix. Was font-lock-singular-warn-face. * singular.el (singular-interactive-mode-syntax-table, singular-mode-syntax-table): renamed and moved to common code section, same for initialization of syntax table (singular-mode-syntax-table): back tics added as strings * singular.el (singular-fset): support for Emacs 19 removed (singular-set-version): ditto * singular.el: doc fixes 1998-08-14 T. Wichmann * singular.el : commented code for singular-logo on startup in XEmacs. This code needs some rethinking... 1998-08-10 T. Wichmann * singular.el (singular-toggle-truncate-lines): Added (recenter) according to function definition in XEmacs. (singular-other): Added check on unique buffer name. Added comments to functions and variables. 1998-08-07 T. Wichmann *singular (singular-send-or-copy-input): Print message if demo mode is active Added variable singular-demo-mode-print-messages * singular.el (singular-demo-mode): changed message text (singular-other): if singular options are read from minibuffer, do not display the "-t" option. Add it automatically. (singular-other): Changed minibuffer text (singular-exit-singular): Added (kill-buffer) * singular.el (singular-do-folding): Added (recenter) to prevent error in subst-char-in-region. Temporary? * singular.el (singular-other): Added 1998-08-06 T. Wichmann * singular.el: added key-bindings Introduced new variable singular-start-menu (temporary) Updated submenu "load library" * singular.el: set-face for new font-lock faces now uses argument 'append for XEmacs Changed (get-buffer-process (cur...)) to (singular-process) (singular-demo-mode): added message on enter * singular.el (singular-emacs-simple-sec-start-at): Removed error: (point) was used instead of pos (singular-emacs-simple-sec-end-at): Removed error: (point) was used instead of pos * singular.el (singular-interactive-mode-syntax-table): Added additional entries * singular.el (singular-font-lock-keywords-1): Added new regexps (font-lock-singular-error-face): Added new face (font-lock-singular-warn-face): Added new face (font-lock-singular-prompt-face): Added new face *singular.el: set-face for section faces put in comments * singular.el (singular-xemacs-simple-sec-in): Written (singular-section-in): Written (singular-do-folding): Finished Thu Jul 30 11:45:28 1998 Jens Schmidt * singular.el (singular-process): new macro * singular.el (singular-demo-command-on-enter, singular-demo-command-on-exit): new variables (singular-demo-mode): sends commands on entering and exiting * singular.el (singular-demo-mode-init): function removed. Functionality moved to `singular-demo-mode'. (singular-demo-mode): more versatile. Knows how to enter and to exit, too. All callers adapted. (singular-demo-exit): new function (singular-demo-show-next-chunk): leaves demo mode after showing last chunk (singular-demo-load): does not show first chunk on startup * singular.el (singular-remove-prompt-regexp): new variable (singular-remove-prompt): new function * singular.el (singular-string-start-anchored-prompt-regexp): renamed to `singular-strip-leading-prompt-regexp' (singular-strip-prompts): renamed to `singular-strip-leading-prompt' (singular-prompt-sequence-regexp): renamed to `singular-skip-prompt-forward-regexp' * singular.el (singular-fold-internal): bug fix. Keeping undo information not up-to-date leads to a corrupt undo list. (singular-demo-show-next-chunk): ditto (singular-exit-sentinel): switches off demo mode on exit 1998-07-31 T. Wichmann * singular.el: simple-secs for XEmacs, second version 1998-07-29 T. Wichmann * singular.el : simple-secs for XEmacs partially implemented Wed Jul 29 10:50:47 1998 Jens Schmidt * singular.el (singular-extended-prompt-regexp, singular-string-start-anchored-prompt-regexp, singular-prompt-sequence-regexp): new constants (singular-strip-white-space, singular-strip-prompts, singular-skip-prompt-forward): new functions * singular.el (singular-emacs-simple-sec-end-at): bug fix (singular-fold-internal, singular-demo-show-next-chunk): do not save buffer-modified flag and do not switch off read only state (singular-output-filter): does not switch off read only state (singular-input-section-to-string): new function * singular.el (singular-send-input): sends old input sections (singular-send-input): renamed to `singular-send-or-copy-input'. All references changed. (singular-get-old-input): new function * singular.el (singular-demo-end): new variable (singular-demo-mode-init, singular-interactive-mode): new function. Call added in mode initialization. (singular-demo-load): sets `singular-demo-end' (singular-demo-show-next-chunk): is smarter concerning end of demo file * singular.el (singular-demo-chunk-regexp): new variable (singular-demo-mode, singular-demo-old-mode-name, singular-interactive-mode): new local variables. Localization added. (singular-demo-mode, singular-demo-show-next-chunk, singular-demo-load): new function (singular-send-input): supports demo mode * singular.el (singular-fold-internal, singular-fold-section): again takes only a single region instead of a list. All callers changed. * singular.el (singular-fold-section): doc fix (singular-exec): takes care about undo information when retrieving start file (singular-emacs-simple-sec-before): doc fix (singular-exec): cosmetic changes (singular-output-filter): cosmetic changes (singular-simple-sec-last-end): doc fix (singular-send-input): argument STRING changed to SEND-FULL-SECTION. Semantics not implemented yet. * singular.el (singular-section-before): new function Tue Jul 28 08:49:05 1998 Jens Schmidt * singular.el (singular-emacs-simple-sec-start-at, singular-emacs-simple-sec-end-at): assume that buffer is already widened (singular-section-at): widens buffer before determining start and end of clear simple sections * singular.el (singular-fold-section): doc fix (singular-emacs-simple-sec-create): doc fix (singular-simple-sec-last-end): doc fix explanations for sections and simple sections added * singular.el (singular-fold-internal, singular-fold-section): uses a list of regions instead of one region. All callers changed. * singular.el (singular-fold-internal): doc fix (singular-section-foldedp): doc fix (singular-fold-section): saves restrictions before folding * singular.el (singular-section-at): argument `raw-section' renamed to `restricted' and its semantic inverted * singular.el (singular-emacs-simple-sec-start-at, singular-emacs-simple-sec-end-at): new functions. `fset's for the flavor-independent functions added. * singular.el (singular-emacs-simple-sec-reset-last): new argument `pos'. Resets `singular-simple-sec-last-end', too. (singular-output-filter): does not set `singular-simple-sec-last-end' * singular.el (singular-simple-sec-last-end): new variable (singular-debug-format): wrapped by a `save-match-data' (singular-simple-sec-clear-type): doc fix (singular-emacs-simple-sec-create): doc fix (singular-emacs-simple-sec-create): cosmetic changes (singular-fold-internal): cosmetic changes (singular-fold-internal): bug fix. Order of `delete-char' and `subst-char-in-region' exchanged. * singular.el (singular-section-at): new function (singular-section-simple-sec, singular-section-start, singular-section-end, singular-section-type): new macros * singular.el (singular-fold-internal, singular-fold-section, singular-section-foldedp): new functions * singular.el (singular-output-filter): sets `inhibit-read-only' instead of `buffer-read-only' * singular.el (singular-simple-sec-clear-type): new variable (singular-simple-sec-init): new function (singular-emacs-simple-sec-create, singular-emacs-simple-sec-reset-last, singular-emacs-simple-sec-start, singular-emacs-simple-sec-end, singular-emacs-simple-sec-type, singular-emacs-simple-sec-at, singular-emacs-simple-sec-before, singular-emacs-simple-sec-in ): new functions. `fset's for the flavor-independent functions added. Mon Jul 27 12:39:04 1998 Jens Schmidt * singular.el (singular-output-filter): new function (singular-send-input): new function (singular-interactive-mode-map): `singular-send-input' bound to `"\C-m"' * singular.el (singular-debug-input-filter, singular-debug-output-filter): completely rewritten. Bogus call counting removed. Debug checks added. (singular-debug-bogus-output-filter-cnt): variable removed * singular.el (singular): code for creation of new singular process moved to `singular-exec' (singular-exec): new function * singular.el (singular-process-mark): new macro (singular-exit-sentinel): debug message fix (singular): arguments names changed (singular-set-version): message fix (singular-bogus-output-filter-calls): variable removed (singular-debug): optional argument `else-form' added (singular-debug-format): uses `replace-match' to replace newlines * singular.el (singular-folding-ellipsis): new variable (singular-interactive-mode): selective display stuff added * singular.el (singular-input-face, singular-output-face): new variables (singular-lookup-face): new function Thu Jul 23 10:28:53 1998 Jens Schmidt * singular.el (singular): initializes the markers `comint-last-input-start', `comint-last-input-end', and `comint-last-output-start' (singular): goes to point max after Singular startup * singular.el (singular-interactive-mode): `comint-truncate-buffer' is not longer added unconditionally to `comint-output-filter-functions' (singular): runs `comint-exec' instead of `make-comint' * singular.el (comint-mode): advice removed (singular-interactive-mode): `comint-mode' is called now in a more regular way * singular.el (singular-debug-output-filter): doc fix * singular.el (singular-bogus-output-filter-calls): new variable * singular.el (singular-interactive-mode-map): code for XEmacs added * singular.el (singular-emacs-flavor, singular-emacs-major-version, singular-emacs-minor-version): new variables (singular-set-version, singular-fset): new functions * singular.el (singular-debug-format): new function (singular-debug-bogus-output-filter-cnt): new variable (singular-debug-input-filter, singular-debug-output-filter): new variables (singular-interactive-mode): conditionally adds debugging filters * singular.el: style and coding conventions added Wed Jul 22 11:45:56 1998 Jens Schmidt * singular.el (singular-interactive-mode): `comint-truncate-buffer' is added to `comint-truncate-buffer' via a local `add-hook' (singular-interactive-mode): doc fix (singular-interactive-mode): `mode-name' fixed (singular): doc fix * singular.el (comint-mode): new advice `singular-interactive-mode' (singular-interactive-mode): call to `comint-mode' re-added (singular-interactive-mode): call to `comint-read-input-ring' moved to `singular' (singular): almost completely rewritten. Runs `singular-interactive-mode' only on creation of a new buffer. Runs hooks on `singular-exec-hook'. Reads input ring on creation of a new process. * singular.el (singular-prompt-regexp): doc fix (singular-input-ignoredups, singular-maximum-buffer-size): unmade customizable * singular.el (singular-history-filter-regexp): new variable (singular-history-filter): new variable (singular-interactive-mode): sets `comint-input-filter' to `singular-history-filter' * singular.el (singular-interactive-mode): adds `comint-truncate-buffer' to `comint-output-filter-functions'. `singular-buffer-maximum-size' unmade buffer local. * singular.el (singular-interactive-mode): does not run `comint-mode'. Mode name changed to `"Singular Interactive". * singular.el (singular-debug): doc fix (singular-debug): recognition of mode `all' added (singular-interactive-mode): `singular-debug' unmade buffer local * singular.el (singular-exit-sentinel): debug messages added * singular.el (singular-start-file): doc fix (singular-default-executable, singular-default-name, singular-default-switches): doc fix (singular, singular-interactive-mode): doc fix (singular-delimiter-argument-list, singular-input-ignoredups, singular-buffer-maximum-size, singular-input-ring-size): doc fix singular-4.0.3+ds/emacs/Makefile.am000066400000000000000000000010431266270727000170770ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../m4 emacsdir=$(datadir)/singular/emacs EMACS = \ ChangeLog \ COPYING \ NEWS \ singular.el \ singular.xpm .emacs-general .emacs-singular \ cmd-cmpl.el ex-cmpl.el hlp-cmpl.el lib-cmpl.el #++ hlp-cmpl.el lib-cmpl.el ex-cmpl.el cmd-cmpl.el: for now from Master Singular #-- BUGS cmpl.pl ESingular.emacs21 lib.pl Makefile.in singular.el.decl dist_emacs_DATA = $(EMACS) # TODO: remove this! #all-local: # [ -d ${builddir} ] || ln -s ${srcdir} ${builddir} EXTRA_DIST = $(EMACS) singular-4.0.3+ds/emacs/NEWS000066400000000000000000000020421266270727000155420ustar00rootroot00000000000000 News up to revision 1.30 ======================== * Customizing added. There are the groups - singular-faces * Section folding completely redesigned. Uses overlays now. Code splitted up into Emacs and XEmacs specific foldings. * Comint interface documented. Old folding concerning customizing of Comint's variables completely removed. History stuff simplified, modularized, moved to its own folding. Chunks of a demo file are not inserted into history unless user explicitly requests so. General news ------------ * Key map and menu folding splitted. Logo stuff (mostly commented) moved to menu folding. * Faces and Font Lock mode foldings moved to Singular interactive mode specific code. Syntax table folding moved to code common to both modes. * Most of the foldings modularized. That is, everything that belongs logically to a folding moved into it. In particular, much code moved from Singular interactive mode initialization to foldings. * Emacs 19 de-supported. * Some new style and coding conventions added. singular-4.0.3+ds/emacs/cmd-cmpl.el000066400000000000000000000070741266270727000170730ustar00rootroot00000000000000; Do not edit this file: It was automatically generated by cmpl.pl (setq singular-commands-alist '( ("ERROR") ("insert") ("parstr") ("GCD") ("int") ("poly") ("IN") ("interpolation") ("preimage") ("LIB") ("interred") ("prime") ("NF") ("intersect") ("primefactors") ("RETURN") ("intmat") ("print") ("TRACE") ("intvec") ("printlevel") ("alias") ("jacob") ("proc") ("and") ("janet") ("prune") ("attrib") ("jet") ("qhweight") ("bareiss") ("kbase") ("qrds") ("betti") ("keepring") ("qring") ("bigint") ("kernel") ("quote") ("bigintmat") ("kill") ("quotient") ("bracket") ("killattrib") ("random") ("break") ("koszul") ("rank") ("breakpoint") ("kres") ("read") ("char") ("laguerre") ("reduce") ("char_series") ("lead") ("regularity") ("charstr") ("leadcoef") ("repart") ("chinrem") ("leadexp") ("reservedName") ("cleardenom") ("leadmonom") ("resolution") ("close") ("lift") ("resultant") ("coef") ("liftstd") ("return") ("coeffs") ("link") ("ring") ("continue") ("list") ("ringlist") ("contract") ("listvar") ("rtimer") ("convhull") ("load") ("rvar") ("dbprint") ("lres") ("setring") ("def") ("ludecomp") ("short") ("defined") ("luinverse") ("simplex") ("deg") ("lusolve") ("simplify") ("degBound") ("map") ("size") ("degree") ("matrix") ("slimgb") ("delete") ("maxideal") ("sortvec") ("det") ("memory") ("sqrfree") ("diff") ("minbase") ("sres") ("dim") ("minor") ("status") ("div") ("minpoly") ("std") ("division") ("minres") ("string") ("dump") ("mod") ("subst") ("echo") ("module") ("system") ("eliminate") ("modulo") ("syz") ("else") ("monitor") ("test") ("envelope") ("monomial") ("timer") ("eval") ("mpresmat") ("trace") ("example") ("mres") ("transpose") ("execute") ("mstd") ("twostd") ("export") ("mult") ("type") ("exportto") ("multBound") ("typeof") ("extgcd") ("multiplicity") ("univariate") ("facstd") ("nameof") ("uressolve") ("factmodd") ("names") ("vandermonde") ("factorize") ("nc_algebra") ("var") ("farey") ("ncalgebra") ("variables") ("fetch") ("ncols") ("varstr") ("fglm") ("newstruct") ("vdim") ("fglmquot") ("noether") ("vector") ("find") ("not") ("verbose") ("finduni") ("npars") ("voice") ("forif") ("nres") ("waitall") ("freemodule") ("nrows") ("waitfirst") ("frwalk") ("number") ("wedge") ("gcd") ("nvars") ("weight") ("gen") ("open") ("whileif") ("getdump") ("oppose") ("write") ("highcorner") ("opposite") ("exit") ("hilb") ("option") ("for") ("homog") ("or") ("help") ("hres") ("ord") ("newline") ("ideal") ("ordstr") ("pause") ("if") ("package") ("quit") ("imap") ("pagewidth") ("while") ("impart") ("par") ("importfrom") ("parameter") ("indepSet") ("pardeg") ("type") ("3:") ("fan") ("type") ("2:") ("polytope") ("type") ("1:") ("cone") ("type") ("0:") ("pyobject") )) singular-4.0.3+ds/emacs/ex-cmpl.el000066400000000000000000001017361266270727000167440ustar00rootroot00000000000000; Do not edit this file: It was automatically generated by cmpl.pl (setq singular-examples-alist '( ("A_L") ("A_Z") ("absFactorize") ("absPrimdecGTZ") ("abstractR") ("absValue") ("Access_to_elements_of_a_user_defined_type") ("actionIsProper") ("addcol") ("addRat") ("addrow") ("ademRelations") ("Adj_div") ("adjoint") ("adjointIdeal") ("admissibleSub") ("afaces") ("AG_codes") ("AGcode_L") ("AGcode_Omega") ("alexanderpolynomial") ("alg_kernel") ("algDependent") ("algebra_containment") ("Algebraic_dependence") ("algebraicDependence") ("all_lib") ("allDoubleExt") ("allExtOfLeft") ("allExtOfRight") ("allPositive") ("allprint") ("allreal") ("allrealst") ("allsquarefree") ("AltVarEnd") ("AltVarStart") ("ambientDimension") ("Ann") ("annfs") ("annfs0") ("annfs2") ("annfsBMI") ("annfsParamBM") ("annfspecial") ("annfsRB") ("annil") ("annPoly") ("annRat") ("annRatSyz") ("appelF1") ("appelF2") ("appelF4") ("appendWeight2Ord") ("applyAdF") ("areZeroElements") ("ArnoldAction") ("arrange") ("ASCII") ("ASCII_links") ("ask") ("Assignments_for_user_defined_types") ("assPrimes") ("Atkin") ("attrib") ("attrib_1") ("attrib_2") ("autonom") ("autonomDim") ("awalk1") ("awalk2") ("babyGiant") ("backward") ("bareiss") ("Basic_programming") ("basicinvariants") ("belongSemigroup") ("bernstein") ("bernsteinBM") ("bernsteinLift") ("betti") ("betti_BR_PLURAL_BR") ("Betti_numbers_and_regularity") ("bFactor") ("bfct") ("bfctAnn") ("bfctBound") ("bfctIdeal") ("bfctOneGB") ("bfctSyz") ("bfctVarAnn") ("bfctVarIn") ("bigint_declarations") ("bigint_expressions") ("bigint_operations") ("bigintmat_declarations") ("bigintmat_expressions") ("bigintmat_operations") ("bigintmat_type_cast") ("binomial") ("binomials2intmat") ("BINresol") ("bistd") ("bitrinity") ("BlowingUp") ("blowUp") ("blowup0") ("blowUp2") ("blowUpBO") ("Blowupcenter") ("boolean_constant") ("boolean_ideal") ("boolean_operations") ("boolean_poly") ("boolean_set") ("boolean_std") ("BorelCheck") ("boundBuFou") ("boundDes") ("boundposDes") ("bracket") ("Branches_of_space_curve_singularities") ("breakpoint") ("BrillNoether") ("bubblesort") ("busadj") ("bvar") ("calculateI") ("canonicalizeCone") ("canonize") ("canonMap") ("cantoradd") ("cantormult") ("cantorred") ("cardGroup") ("CenCharDec") ("Center") ("center") ("CenterBO") ("centerRed") ("centerVS") ("central1st") ("central2nd") ("centralizer") ("centralizerRed") ("centralizerVS") ("centralizeSet") ("CentralQuot") ("CentralSaturation") ("cgs") ("cgsdr") ("chaincrit") ("changechar") ("changeDenominator") ("changeord") ("changevar") ("char") ("char_series") ("Characteristic_sets") ("CharacteristicExponents") ("charexp2conductor") ("charexp2generators") ("charexp2inter") ("charexp2multseq") ("charexp2poly") ("charInfo") ("charpoly") ("charstr") ("charVariety") ("checkFactor") ("checkRoot") ("chineseRem") ("chinrem") ("chinrestp") ("Classification_of_hypersurface_singularities") ("classify") ("classifyCeq") ("cleanunit") ("cleardenom") ("closed_points") ("closetex") ("closureFrac") ("CM_regularity") ("CMtype") ("codim") ("codimension") ("coef") ("coeffmod") ("coeffs") ("coeffs_1") ("coHom") ("collectDiv") ("colrank") ("colred") ("Command_line_options") ("Commands_for_user_defined_types") ("commRing") ("CompDecomp") ("completeReduction") ("complexSingType") ("ComplexValue") ("compress") ("Computation_of_Ext") ("computemcm") ("concat") ("coneLink") ("coneViaInequalities") ("coneViaPoints") ("constructblwup") ("constructH") ("constructlastblwup") ("ContactMatrix") ("containsAsFace") ("containsInCollection") ("containsInSupport") ("containsPositiveVector") ("containsRelatively") ("content") ("contract") ("contraHom") ("control") ("controlDim") ("controlExample") ("convertdata") ("convexHull") ("convexIntersection") ("convloc") ("coords") ("corank") ("Cornacchia") ("CornacchiaModified") ("cornerMonomials") ("countPoints") ("createBO") ("createGradedRingHomomorphism") ("createGroup") ("createlist") ("createQuotientGroup") ("createTorsionFreeGroup") ("Critical_points") ("cup") ("cupproduct") ("CurveParam") ("CurveRes") ("cyclic") ("cyclotomic") ("datetime") ("DBM_links") ("dbprint") ("debug_log") ("dec1var") ("decimal") ("Declaration_of_objects_of_a_user_defined_type") ("decode") ("decodeCode") ("decodeRandom") ("decodeRandomFL") ("decodeSV") ("decoef") ("def") ("def_declarations") ("defined") ("defineHomogeneous") ("Definition_of_a_user_defined_type") ("deform") ("Deformations") ("defring") ("defringp") ("defrings") ("deg") ("degree") ("degreeDivisor") ("degreeFormalDivisor") ("degreepart") ("delete") ("deleteGenerator") ("deleteSublist") ("Delta") ("delta") ("DeltaList") ("deltaLoc") ("denominator") ("Depth") ("depth") ("depthIdeal") ("deRhamCohom") ("deRhamCohomIdeal") ("derivate") ("det") ("det_B") ("detadj") ("determinacy") ("determinecenter") ("develop") ("diag") ("diag_test") ("diagInvariants") ("diff") ("diffRat") ("difpoly2tex") ("dim") ("dim_BR_PLURAL_BR") ("dim_slocus") ("dimension") ("dimGradedPart") ("dimH") ("dimMon") ("direct_boolean_poly") ("direct_from_boolean_poly") ("disc") ("discr") ("discrepancy") ("disp_zdd") ("displayHNE") ("displayInvariants") ("displayMultsequence") ("dividelist") ("divideUnits") ("division") ("division_BR_PLURAL_BR") ("divisor") ("divisorplus") ("DLoc") ("DLoc0") ("Dlocalization") ("dmodAction") ("dmodActionRat") ("dmodGeneralAssumptionCheck") ("dmodoublext") ("double") ("doubleExt") ("DsingularLocus") ("dsum") ("dual_code") ("dualCone") ("dualPolytope") ("dump") ("Dynamic_modules") ("ecart") ("ECoef") ("ECPP") ("Edatalist") ("eexgcdN") ("effective") ("ehrhartRing") ("eigenvals") ("eigenvalues") ("elemSymmId") ("elim") ("elim1") ("elim2") ("eliminate") ("eliminate_BR_PLURAL_BR") ("eliminateNC") ("Elimination") ("elimlinearpart") ("elimpart") ("elimpartanyr") ("elimrep") ("elimRing") ("elimWeight") ("ellipticAdd") ("ellipticAllPoints") ("ellipticMult") ("ellipticRandomCurve") ("ellipticRandomPoint") ("Emaxcont") ("embedMat") ("emptyFan") ("encode") ("endvfilt") ("engine") ("envelope") ("EOrdlist") ("equalJinI") ("equalMultiDeg") ("equations") ("equidim") ("equidimMax") ("equidimMaxEHV") ("equidimZ") ("equiRadical") ("Eresol") ("ERROR") ("errorInsert") ("errormap") ("errorRand") ("esIdeal") ("esStratum") ("euler") ("eval") ("evaluate_reynolds") ("evaluateFormalDivisor") ("evaluatePDivisor") ("Example_of_a_procedure_definition_in_a_library:") ("Example_of_an_interactive_procedure_definition_and_its_execution:") ("Example_of_use_of_@sc{Letterplace}") ("execute") ("exgcdN") ("exp2pt") ("expo") ("exportNuminvs") ("exportto") ("Ext") ("Ext_R") ("extcurve") ("extdevelop") ("extend") ("extendedTensor") ("extendring") ("extendWeyl") ("Exterior") ("exteriorBasis") ("exteriorPower") ("extgcd") ("facets") ("facFirstShift") ("facFirstWeyl") ("facGBIdeal") ("facstd") ("facSubWeyl") ("factmodd") ("factorgroup") ("factorH") ("factorial") ("Factorization") ("factorize") ("factorLenstraECM") ("fanViaCones") ("farey") ("fastelim") ("fastExpt") ("fetch") ("fetch_BR_PLURAL_BR") ("fetchall") ("ffsolve") ("fglm") ("fglm_solve") ("fglmquot") ("fibonacci") ("find") ("findAuto") ("findifs_example") ("findimAlgebra") ("findInvo") ("findInvoDiag") ("findTorsion") ("finduni") ("findvars") ("Finite_fields") ("finiteDiagInvariants") ("finitenessTest") ("First_index_is_1") ("firstoct") ("fitting") ("fl2poly") ("flatten") ("flatteningStrat") ("formaldivisorplus") ("Formatting_output") ("forward") ("fourier") ("fouriersystem") ("fprintf") ("Free_resolution") ("Free_resolutions") ("freeGBasis") ("freemodule") ("freerank") ("from_boolean_constant") ("from_boolean_ideal") ("from_boolean_poly") ("from_boolean_set") ("frwalk") ("fullFan") ("fullFan_1") ("fullSerreRelations") ("Function_without_return_value") ("further_hn_proc") ("furtherInvar") ("fwalk") ("G_a_-Invariants") ("Gamma") ("Gauss-Manin_connection") ("Gauss-Manin_connection_1") ("Gauss-Manin_connection_2") ("gauss_col") ("gauss_nf") ("gauss_row") ("gaussred") ("gaussred_pivot") ("GBsolve") ("GBWeight") ("gcd") ("gcddivisor") ("gcdMon") ("gcdN") ("gen") ("Generalized_Hilbert_Syzygy_Theorem") ("generalOrder") ("generateG") ("generatorsOfLinealitySpace") ("generatorsOfSpan") ("genericid") ("genericity") ("genericmat") ("genMDSMat") ("genoutput") ("genSymId") ("genus") ("getCone") ("getdump") ("getGradingGroup") ("getLattice") ("getLinearForms") ("getModuleGrading") ("getMultiplicity") ("getOneVar") ("getSmallest") ("getVariableWeights") ("gitCone") ("gitFan") ("GKdim") ("gkzFan") ("GKZsystem") ("globalSections") ("gmscoeffs") ("gmsnf") ("gmsring") ("goodBasis") ("Graded_commutative_algebras__SCA_") ("gradeNumber") ("gradiator") ("graver4ti2") ("grobcov") ("groebner") ("groebner_and_std") ("Groebner_basis_conversion") ("group_reynolds") ("GTZmod") ("GTZopt") ("gwalk") ("Gweights") ("H2basis") ("Handling_graded_modules") ("Hcode") ("headStand") ("heightZ") ("hermiteNormalForm") ("hessenberg") ("highcorner") ("hilb") ("hilbert4ti2") ("HilbertClassPoly") ("hilbertSeries") ("hilbPoly") ("hilbvec") ("hnexpansion") ("holonomicRank") ("Hom") ("hom_kernel") ("HomJJ") ("homog") ("homogfacFirstQWeyl") ("homogfacFirstQWeyl_all") ("homology") ("How_to_use_links") ("How_to_use_links_1") ("hres") ("id2mod") ("ideal_declarations") ("ideal_declarations_BR_PLURAL_BR") ("ideal_expressions") ("ideal_expressions_BR_PLURAL_BR") ("ideal_operations") ("ideal_operations_BR_PLURAL_BR") ("idealsimplify") ("idealSplit") ("Identifier_resolution") ("Identifier_resolution_1") ("identifyvar") ("image_of_variety") ("ImageGroup") ("imageLattice") ("ImageVariety") ("imap") ("imap_BR_PLURAL_BR") ("imapall") ("impart") ("importfrom") ("iMult") ("inCenter") ("inCentralizer") ("indepSet") ("indSet") ("inequalities") ("inForm") ("iniD") ("init_debug") ("initialIdealW") ("initialMalgrange") ("insert") ("insertCone") ("insertGenerator") ("inSubring") ("int_declarations") ("int_expressions") ("int_operations") ("intclMonIdeal") ("intclToricRing") ("integralBasis") ("integralIdeal") ("integralModule") ("integralSection") ("internalfunctions") ("interpolate") ("interpolation") ("interred") ("intersect") ("intersect_BR_PLURAL_BR") ("intersection") ("intersectionDiv") ("IntersectionMatrix") ("intersectionValRingIdeals") ("intersectionValRings") ("intersectLattices") ("intersectMon") ("IntersectWithSub") ("intersectZ") ("intInverse") ("intmat2mons") ("intmat_declarations") ("intmat_expressions") ("intmat_operations") ("intmat_type_cast") ("intPart") ("intRank") ("intRoot") ("intRoots") ("intvec_declarations") ("intvec_expressions") ("intvec_operations") ("invariant_algebra_perm") ("invariant_algebra_reynolds") ("invariant_basis") ("invariant_basis_reynolds") ("invariant_ring") ("invariant_ring_random") ("InvariantRing") ("invariantRing") ("invariants") ("Invariants_of_a_finite_group") ("Invariants_of_plane_curve_singularities") ("inverse") ("inverse_B") ("inverse_L") ("inverseFourier") ("invertBirMap") ("involution") ("invunit") ("iostruct") ("irred_secondary_char0") ("irred_secondary_no_molien") ("irreddecMon") ("irrRealizationDim") ("is_active") ("is_bijective") ("is_cenBimodule") ("is_cenSubbimodule") ("is_ci") ("is_complex") ("is_injective") ("is_irred") ("is_is") ("is_nested") ("is_NND") ("is_NP") ("is_pure") ("is_reg") ("is_regs") ("is_surjective") ("is_zero") ("isAface") ("isAntiEndo") ("isartinianMon") ("isCartan") ("isCentral") ("isCI") ("isCM") ("isCMcod2") ("isCommutative") ("isCompatible") ("isEqualDivisor") ("isEquising") ("isFlat") ("isFsat") ("isFullSpace") ("isgenericMon") ("isGradedRingHomomorphism") ("isGroup") ("isGroupHomomorphism") ("isHolonomic") ("isHomogeneous") ("ishyper") ("isInt") ("isIntegralSurjective") ("isInvolution") ("isirreducibleMon") ("isLocallyFree") ("isMonomial") ("isNC") ("isOnCurve") ("isoncurve") ("isOrigin") ("isparam") ("isPositive") ("isprimaryMon") ("isprimeMon") ("isPrimitiveSublattice") ("isPure") ("isPureTensor") ("isRational") ("isReg") ("IsSCA") ("isSimplicial") ("isSublattice") ("isSymmetric") ("isTame") ("isTorsionFree") ("isTwoSidedGB") ("isuni") ("isUpperTriangular") ("isVar") ("isWeyl") ("isZeroElement") ("iv2lp") ("iv2lpList") ("iv2lpMat") ("ivDHilbert") ("ivDHilbertSickle") ("ivDimCheck") ("ivHilbert") ("ivKDim") ("ivL2lpI") ("ivMis2Base") ("ivMis2Dim") ("ivOrdMisLex") ("ivSickle") ("ivSickleDim") ("ivSickleHil") ("jacob") ("Jacobi") ("jacoblift") ("jacobson") ("janet") ("jet") ("JMarkedScheme") ("jOft") ("jordan") ("jordanbasis") ("jordanmatrix") ("jordannf") ("jungfib") ("jungnormal") ("jungresolve") ("katsura") ("kbase") ("kbase_BR_PLURAL_BR") ("kernel") ("Kernel_of_module_homomorphisms") ("kernelLattice") ("kill") ("killall") ("killattrib") ("kmemory") ("kohom") ("kontrahom") ("koszul") ("KoszulHomology") ("KScoef") ("KSconvert") ("KSker") ("KSlinear") ("KSpencerKernel") ("laguerre") ("laguerre_solve") ("lastvarGeneral") ("latticeBasis") ("laxfrT") ("laxfrX") ("lcm") ("lcmMon") ("lcmN") ("lcmofall") ("lead") ("leadcoef") ("leadexp") ("leadmonom") ("leadmonomial") ("Left_and_two-sided_Groebner_bases") ("leftInverse") ("leftKernel") ("LengthSym") ("LengthSymElement") ("letplaceGBasis") ("lex_solve") ("LIB") ("lieBracket") ("lift") ("lift_BR_PLURAL_BR") ("lift_kbase") ("lift_rel_kb") ("liftenvelope") ("liftstd") ("liftstd_BR_PLURAL_BR") ("linealityDimension") ("linealitySpace") ("linear_relations") ("LinearActionQ") ("linearCombinations") ("LinearizeAction") ("linearlyEquivalent") ("linearMapKernel") ("linearpart") ("link_declarations") ("linReduce") ("linReduceIdeal") ("linSyzSolve") ("list_declarations") ("list_expressions") ("list_operations") ("listvar") ("LLL") ("lll") ("load") ("load_1") ("Loading_a_library") ("localInvar") ("localstd") ("locAtZero") ("locNormal") ("locstd") ("log2") ("Long_coefficients") ("lp2iv") ("lp2ivId") ("lp2lstr") ("lpDHilbert") ("lpDHilbertSickle") ("lpDimCheck") ("lpHilbert") ("lpId2ivLi") ("lpKDim") ("lpMis2Base") ("lpMis2Dim") ("lpMult") ("lpNF") ("lpOrdMisLex") ("lpPower") ("lprint") ("lpSickle") ("lpSickleDim") ("lpSickleHil") ("lres") ("lst2str") ("ludecomp") ("luinverse") ("lusolve") ("magnitude") ("makeDivisor") ("makeFormalDivisor") ("makeHeisenberg") ("makeLetterplaceRing") ("makeMalgrange") ("makeModElimRing") ("makePDivisor") ("makeQsl2") ("makeQsl3") ("makeQso3") ("makeUe6") ("makeUe7") ("makeUe8") ("makeUf4") ("makeUg2") ("makeUgl") ("makeUsl") ("makeUsl2") ("makeUso10") ("makeUso11") ("makeUso12") ("makeUso5") ("makeUso6") ("makeUso7") ("makeUso8") ("makeUso9") ("makeUsp1") ("makeUsp2") ("makeUsp3") ("makeUsp4") ("makeUsp5") ("makeWeyl") ("map_BR_PLURAL_BR_operations") ("map_declarations") ("map_declarations_BR_PLURAL_BR") ("map_operations") ("mapall") ("mapIsFinite") ("mapToRatNormCurve") ("markov4ti2") ("mat_rk") ("matbil") ("matmult") ("matrix_declarations") ("matrix_expressions") ("matrix_operations") ("Matrix_orderings") ("Matrix_orderings_1") ("matrix_type_cast") ("matrixExp") ("matrixLog") ("matrixsystem") ("matrixT1") ("Max") ("maxabs") ("maxcoef") ("maxdeg") ("maxdeg1") ("maxEord") ("maxideal") ("maximum") ("Maximus") ("maxIntRoot") ("Maxord") ("maxZeros") ("mdouble") ("membershipMon") ("memory") ("midpoint") ("MillerRabin") ("milnor") ("Milnor_and_Tjurina_number") ("milnorcode") ("milnornumber") ("Min") ("minAssChar") ("minAssGTZ") ("minAssZ") ("minbase") ("minbaseMon") ("mindeg") ("mindeg1") ("mindist") ("minEcart") ("MinimalDecomposition") ("Minimus") ("minIntRoot") ("minIntRoot2") ("minipoly") ("minMult") ("minor") ("minpoly") ("minres") ("minres_BR_PLURAL_BR") ("Miscellaneous_oddities") ("Miscellaneous_oddities_1") ("Miscellaneous_oddities_2") ("Miscellaneous_oddities_3") ("Miscellaneous_oddities_4") ("mod2id") ("mod2str") ("mod_versal") ("modality") ("modDec") ("ModEqn") ("modHenselStd") ("modNormal") ("modS") ("modStd") ("module_containment") ("module_declarations") ("module_declarations_BR_PLURAL_BR") ("module_operations") ("module_operations_BR_PLURAL_BR") ("Module_orderings") ("Module_orderings_1") ("Module_orderings_2") ("Module_orderings_3") ("modulo") ("modulo_BR_PLURAL_BR") ("moduloSlim") ("molien") ("monodromy") ("monodromyB") ("monomial") ("monomialInIdeal") ("monomialLcm") ("mons2intmat") ("morsesplit") ("mp_res_mat") ("MPfile_links") ("mpresmat") ("MPtcp_links") ("mres") ("mres_BR_PLURAL_BR") ("mstd") ("msum") ("mtriple") ("mult") ("multBound") ("multcol") ("multdivisor") ("multformaldivisor") ("multi") ("multiDeg") ("multiDegBasis") ("multiDegGroebner") ("multiDegModulo") ("multiDegPartition") ("multiDegResolution") ("multiDegSyzygy") ("multiDegTensor") ("MultiplicitySequence") ("multiplylist") ("multRat") ("multrow") ("multseq2charexp") ("multsequence") ("nameof") ("Names") ("names") ("Names_1") ("Names_2") ("Names_3") ("Names_in_procedures") ("nashmult") ("nc_algebra") ("ncdetection") ("ncExt_R") ("ncHom") ("ncols") ("ncones") ("ncRelations") ("ndcond") ("negatedCone") ("negativedivisor") ("negativeformaldivisor") ("newTest") ("newtonDiag") ("newtonpoly") ("newtonPolytope") ("nf_icis") ("NFMora") ("nmaxcones") ("noether") ("noetherNormal") ("NoetherPosition") ("Nonhyp") ("nonMonomials") ("nonZeroEntry") ("norm") ("normal") ("normalC") ("normalForm") ("normalform") ("normalI") ("normaliz") ("Normalization") ("normalize") ("normalP") ("normalToricRing") ("normalToricRingFromBinomials") ("norTest") ("npar") ("npars") ("nres") ("nres_BR_PLURAL_BR") ("nrows") ("nrroots") ("nrRootsDeterm") ("nrRootsProbab") ("nselect") ("NSplaces") ("nt_solve") ("NullCone") ("number_declarations") ("number_e") ("number_expressions") ("number_operations") ("number_pi") ("numberOfConesOfDimension") ("numerator") ("nvars") ("Objects") ("oneDimBelongSemigroup") ("opentex") ("operatorBM") ("operatorModulo") ("oppose") ("opposite") ("option") ("orbit_variety") ("orbitCones") ("ord") ("ord_test") ("ordstr") ("orthogonalize") ("outer") ("package_declarations") ("pairset") ("par") ("par2varRing") ("paraConic") ("Parallelization_with_MPtcp_links") ("parallelWaitAll") ("parallelWaitFirst") ("parallelWaitN") ("param") ("Parameters") ("parametrizeOrbit") ("paraPlaneCurve") ("pardeg") ("parstr") ("partial_molien") ("PartitionVar") ("ParToVar") ("pause") ("PBW_eqDeg") ("PBW_maxDeg") ("PBW_maxMonom") ("pdivi") ("pdivisorplus") ("PerfectPowerTest") ("permcol") ("permrow") ("permute_L") ("perron") ("PEsolve") ("pFactor") ("PH_ais") ("PH_nais") ("pIntersect") ("pIntersectSyz") ("Pipe_links") ("plainInvariants") ("pmat") ("pnormalf") ("PocklingtonLehmer") ("Polar_curves") ("PollardRho") ("polSol") ("polSolFiniteRank") ("poly") ("poly2list") ("poly2zdd") ("poly_BR_PLURAL_BR") ("poly_declarations") ("poly_declarations_BR_PLURAL_BR") ("poly_expressions") ("poly_expressions_BR_PLURAL_BR") ("poly_operations") ("polytopeViaInequalities") ("polytopeViaPoints") ("polyVars") ("pos_def") ("posweight") ("power") ("power_products") ("powerN") ("powerpolyX") ("powersums") ("powerX") ("preComp") ("preimage") ("preimage_BR_PLURAL_BR") ("preimageLattice") ("preimageLoc") ("preimageNC") ("prepareAss") ("prepEmbDiv") ("prepRealclassify") ("prepSV") ("primary_char0") ("primary_char0_no_molien") ("primary_char0_no_molien_random") ("primary_char0_random") ("primary_charp") ("primary_charp_no_molien") ("primary_charp_no_molien_random") ("primary_charp_random") ("primary_charp_without") ("primary_charp_without_random") ("Primary_decomposition") ("primary_invariants") ("primary_invariants_random") ("PrimdecA") ("PrimdecB") ("primdecGTZ") ("primdecMon") ("primdecSY") ("primdecZ") ("prime") ("primeClosure") ("primecoeffs") ("primefactors") ("primes") ("primitive") ("primitive_extra") ("primitiveSpan") ("primL") ("primList") ("primparam") ("primRoot") ("primTest") ("print") ("Print_command") ("printf") ("printGroup") ("printlevel") ("proc_declaration") ("prodcrit") ("product") ("productgroup") ("projectiveDimension") ("projectLattice") ("proximitymatrix") ("prune") ("psigncnd") ("puiseux2generators") ("purelist") ("purityFiltration") ("purityTriang") ("pushForward") ("pwalk") ("pyobject") ("pyobject_declarations") ("pyobject_expressions") ("pyobject_operations") ("pyobject_related_functions") ("pyobject_related_functions_1") ("pyramid") ("python_eval") ("python_import") ("python_run") ("qbase") ("qepcad") ("qepcadsystem") ("qhmatrix") ("qhspectrum") ("qhweight") ("qminor") ("qrds") ("qring_declaration") ("qring_declaration_BR_PLURAL_BR") ("qslimgb") ("Qso3Casimir") ("quadraticSieve") ("quantMat") ("quickclass") ("quote") ("Quotient") ("quotient") ("quotient_BR_PLURAL_BR") ("Quotient_rings") ("quotientLatticeBasis") ("quotientMon") ("rad_con") ("radical") ("radicalEHV") ("radicalMon") ("radicalZ") ("randcharpoly") ("randlinpoly") ("random") ("randomBinomial") ("randomCheck") ("randomid") ("randomLast") ("randommat") ("randomPoint") ("rank") ("rationalPointConic") ("ratSol") ("ratstd") ("rays") ("read") ("readNmzData") ("realclassify") ("realizationDim") ("realizationDimPoly") ("realmorsesplit") ("realpoly") ("realrad") ("realzero") ("recursive_boolean_poly") ("recursive_from_boolean_poly") ("reduce") ("reduce_BR_PLURAL_BR") ("reduction") ("ReesAlgebra") ("reference_and_shared__experimental_") ("reference_and_shared__experimental__1") ("reference_and_shared__experimental__2") ("reference_and_shared__experimental__3") ("reference_and_shared_operations") ("reference_and_shared_operations_1") ("reference_and_shared_operations_2") ("reference_and_shared_related_functions") ("reference_and_shared_related_functions_1") ("reference_and_shared_related_functions_2") ("reference_declarations") ("reference_expressions") ("regIdeal") ("regMonCurve") ("regularity") ("reiffen") ("rel_orbit_variety") ("relative_orbit_variety") ("relativeInteriorPoint") ("relweight") ("remainder") ("removeCone") ("removepower") ("repart") ("replace") ("res") ("reservedName") ("resfunction") ("reslist") ("resolution_declarations") ("resolution_declarations_BR_PLURAL_BR") ("Resolution_of_singularities") ("resolutiongraph") ("resolve") ("restrictionIdeal") ("restrictionModule") ("resultant") ("Return_type_of_procedures") ("Return_type_of_procedures_1") ("reverse") ("reynolds_molien") ("rho") ("Right_Groebner_bases_and_syzygies") ("rightInverse") ("rightKernel") ("rightModulo") ("rightNF") ("rightNFWeyl") ("rightStd") ("ring_operations") ("ring_operations_BR_PLURAL_BR") ("ringlist") ("ringlist_BR_PLURAL_BR") ("Rings_and_standard_bases") ("Rings_associated_to_monomial_orderings") ("ringtensor") ("ringweights") ("rm_unitcol") ("rm_unitrow") ("rMacaulay") ("rmNmzFiles") ("rmx") ("rncAntiCanonicalMap") ("rncItProjEven") ("rncItProjOdd") ("rootofUnity") ("roots") ("rootsModp") ("round") ("rowred") ("rvar") ("sa_poly_reduce") ("sa_reduce") ("safeVarName") ("sagbi") ("sagbiPart") ("sagbiReduce") ("sagbiSPoly") ("salida") ("sameComponent") ("Sannfs") ("SannfsBFCT") ("Sannfslog") ("SannfsVar") ("sat") ("satiety") ("Saturation") ("scalarProd") ("scheme") ("Schoof") ("SDLoc") ("secondary_and_irreducibles_no_molien") ("secondary_char0") ("secondary_charp") ("secondary_no_molien") ("secondary_not_cohen_macaulay") ("select") ("select1") ("semiCMcod2") ("semidiv") ("semigroup") ("semigroupGenerator") ("separateHNE") ("separator") ("serreRelations") ("setBaseMultigrading") ("setglobalrings") ("setinitials") ("setLetterplaceAttributes") ("setLinearForms") ("setModuleGrading") ("setMultiplicity") ("setNmzDataPath") ("setNmzExecPath") ("setNmzFilename") ("setNmzOption") ("setring") ("ShanksMestre") ("shared_declarations") ("shared_expressions") ("sheafCoh") ("sheafCohBGG") ("sheafCohBGG2") ("shiftPoly") ("short") ("show") ("showgrades") ("showNmzOptions") ("showNuminvs") ("showrecursive") ("sickle") ("signatureBrieskorn") ("signatureL") ("signatureLqf") ("signatureNemethi") ("signaturePuiseux") ("signcnd") ("simplesolver") ("simplex") ("simplexOut") ("simplify") ("simplifyRat") ("singularity") ("size") ("skewmat") ("slim_Groebner_bases") ("slimgb") ("slimgb_BR_PLURAL_BR") ("slocus") ("smith") ("smithNormalForm") ("SolowayStrassen") ("solutionsMod2") ("solve") ("solve_IP") ("solvelinearpart") ("Solving_systems_of_polynomial_equations") ("sort") ("sortandmap") ("sortier") ("sortIntvec") ("sortvars") ("sortvec") ("spadd") ("span") ("sparseHomogIdeal") ("sparseid") ("sparsemat") ("sparsematrix") ("sparsepoly") ("sparsetriag") ("spectralNeg") ("spectrum") ("spectrumnd") ("spgamma") ("spgeomgenus") ("spissemicont") ("split") ("splitring") ("splitting") ("spmilnor") ("spmul") ("spnf") ("spoly") ("sppairs") ("sppnf") ("sppprint") ("spprint") ("sprintf") ("spsemicont") ("spsub") ("sqfrNorm") ("sqr") ("sqrfree") ("squarefree") ("squareRoot") ("sres") ("Ssi_file_links") ("Ssi_tcp_links") ("StabEqn") ("StabEqnId") ("standard") ("startNmz") ("StartOrderingV") ("status") ("std") ("std_BR_PLURAL_BR") ("stdfglm") ("stdhilb") ("string") ("string_declarations") ("string_expressions") ("string_operations") ("string_type_cast") ("StringF") ("stripHNE") ("sturm") ("sturmha") ("sturmhaseq") ("sturmquery") ("sturmseq") ("submat") ("subrInterred") ("subst") ("subst_BR_PLURAL_BR") ("substitute") ("sum") ("sumlist") ("superCommutative") ("swap") ("sym_gauss") ("SymGroup") ("symmat") ("symmetricBasis") ("symmetricPower") ("symmfunc") ("symmStd") ("syModStd") ("symsignature") ("syndrome") ("sys_code") ("sysBin") ("sysCRHT") ("sysCRHTMindist") ("sysFL") ("sysNewton") ("sysQE") ("system") ("syz") ("syz_BR_PLURAL_BR") ("Syzygies") ("T1_and_T2") ("T_1") ("T_12") ("T_2") ("tab") ("tail") ("tangentcone") ("tangentGens") ("tau_es") ("tau_es2") ("tensor") ("tensorMod") ("TestJMark") ("testNCfac") ("testParametrization") ("testPointConic") ("testPrimary") ("tex") ("texcoef") ("texfactorize") ("texmap") ("texname") ("texobj") ("texpoly") ("texproc") ("texring") ("timeFactorize") ("timer") ("timeStd") ("timestep") ("Tjurina") ("tjurina") ("tmatrix") ("tolessvars") ("Tor") ("toric_ideal") ("toric_std") ("torusInvariants") ("totalmultiplicities") ("TRACE") ("trace") ("tracemult") ("Tracing_of_procedures") ("transpose") ("trapezoid") ("triagmatrix") ("triang_solve") ("triangL_solve") ("triangLf_solve") ("triangM_solve") ("triMNewton") ("truncate") ("truncateFast") ("tst_ncfactor") ("twalk") ("twostd") ("type") ("Type_casting") ("typeof") ("u") ("U_D_O") ("uniquePoint") ("unitmat") ("univariate") ("univarpoly") ("updatePairs") ("UpOneMatrix") ("UpperMonomials") ("ures_solve") ("valvars") ("vandermonde") ("vanishId") ("var") ("variables") ("variablesSorted") ("variablesStandard") ("varNum") ("vars2pars") ("varsigns") ("varstr") ("VarToPar") ("vct2str") ("vdim") ("vdim_BR_PLURAL_BR") ("vec2poly") ("vector_declarations") ("vector_expressions") ("vector_operations") ("verify") ("versal") ("vertices") ("vfilt") ("view") ("visualize") ("voice") ("vwfilt") ("waitall") ("waitfirst") ("watchdog") ("wedge") ("Weierstrass") ("weierstrDiv") ("weierstrPrep") ("weight") ("weightedRing") ("weightKB") ("Weyl") ("WeylClosure") ("WeylClosure1") ("whichvariable") ("writeNmzData") ("writeNmzPaths") ("Writing_procedures_and_libraries") ("WSemigroup") ("wUnit") ("wurzel") ("xchange") ("xdvi") ("XLsolve") ("zdd2poly") ("zerodec") ("zeroMod") ("zeroOpt") ("zeroRadical") ("zeroSet") ("zetaDL") ("ZZsolve") )) singular-4.0.3+ds/emacs/hlp-cmpl.el000066400000000000000000005522721266270727000171200ustar00rootroot00000000000000; Do not edit this file: It was automatically generated by emacs/cmpl.pl (setq singular-help-topics-alist '( ("!" . "Special characters. (line 68") ("!=" . "boolean expressions. (line 6") ("\"" . "Special characters. (line 77") ("\#" . "Special characters. (line 122") ("$" . "Special characters. (line 125") ("%" . "intvec expressions. (line 6") ("&&" . "boolean operations. (line 6") ("(" . "Special characters. (line 14") (")" . "Special characters. (line 14") ("*" . "intvec expressions. (line 6") ("**" . "Special characters. (line 46") ("+" . "intvec expressions. (line 6") ("++" . "Special characters. (line 26") ("-" . "intvec expressions. (line 6") ("->" . "proc expression. (line 6") ("-allow-net" . "Command line options") ("-b" . "Command line options") ("-batch" . "Command line options") ("-browser" . "Command line options") ("-c" . "Command line options") ("-d" . "Command line options") ("-e" . "Command line options") ("-echo" . "Command line options") ("-emacs" . "Command line options") ("-emacs-dir" . "Command line options") ("-emacs-load" . "Command line options") ("-execute" . "Command line options") ("-h" . "Command line options") ("-help" . "Command line options") ("-min-time" . "Command line options") ("-MPhost" . "Command line options") ("-MPport" . "Command line options") ("-no-out" . "Command line options") ("-no-rc" . "Command line options") ("-no-shell" . "Command line options") ("-no-stdlib" . "Command line options") ("-no-tty" . "Command line options") ("-no-warn" . "Command line options") ("-q" . "Command line options") ("-quiet" . "Command line options") ("-r" . "Command line options") ("-random" . "Command line options") ("-sdb" . "Command line options") ("-singular" . "Command line options") ("-ticks-per-sec" . "Command line options") ("-u" . "Command line options") ("-user-option" . "Command line options") ("-v" . "Command line options") ("-verbose" . "Command line options") (".." . "Special characters. (line 104") (".singularrc file" . "Startup sequence. (line 10") (".singularrc file, no loading" . "Command line options") ("/" . "intvec expressions. (line 6") ("//" . "Special characters. (line 86") (":" . "intvec expressions. (line 6") ("::" . "package. (line 6") (";" . "Special characters. (line 95") ("<" . "filecmd. (line 6") ("<=" . "boolean expressions. (line 6") ("<>" . "boolean expressions. (line 6") ("=" . "Special characters. (line 8") ("==" . "boolean expressions. (line 6") (">" . "Special characters. (line 58") (">=" . "boolean expressions. (line 6") ("?" . "help. (line 19") ("[" . "Special characters. (line 17") ("\\" . "Special characters. (line 101") ("]" . "Special characters. (line 17") ("^" . "ideal operations. (line 6") ("_" . "Special characters. (line 116") ("`" . "Special characters. (line 80") ("a, ordering" . "Extra weight vector. (line 6") ("A_L" . "A_L. (line 6") ("A_Z" . "A_Z. (line 6") ("absfact.lib" . "absfact_lib. (line 6") ("absfact_lib" . "absfact_lib. (line 6") ("absFactorize" . "absFactorize. (line 6") ("absFactorizeBCG" . "absFactorizeBCG. (line 6") ("absolute factorization." . "absfact_lib. (line 37") ("absPrimdecGTZ" . "absPrimdecGTZ. (line 6") ("absPrimdecGTZE" . "absPrimdecGTZE. (line 6") ("abstractR" . "abstractR. (line 6") ("absValue" . "absValue. (line 6") ("Access to elements of a user defined type" . "Access to elements of a user defined type") ("actionIsProper" . "actionIsProper. (line 6") ("addcol" . "addcol. (line 6") ("addcores" . "addcores. (line 6") ("addNvarsTo" . "addNvarsTo. (line 6") ("addRat" . "addRat. (line 6") ("addrow" . "addrow. (line 6") ("addvarsTo" . "addvarsTo. (line 6") ("ademRelations" . "ademRelations. (line 6") ("Adj_div" . "Adj_div. (line 6") ("adjoint" . "adjoint. (line 6") ("Adjoint ideal" . "paraplanecurves_lib. (line 73") ("adjointIdeal" . "adjointIdeal. (line 6") ("adjunction divisor" . "Adj_div. (line 64") ("admissibleSub" . "admissibleSub. (line 6") ("afaces" . "afaces. (line 6") ("affine code" . "Fitzgerald-Lax method") ("AG codes" . "AG codes. (line 6") ("AGcode_L" . "AGcode_L. (line 6") ("AGcode_Omega" . "AGcode_Omega. (line 6") ("ainvar.lib" . "ainvar_lib. (line 6") ("ainvar_lib" . "ainvar_lib. (line 6") ("aksaka.lib" . "aksaka_lib. (line 6") ("aksaka_lib" . "aksaka_lib. (line 6") ("Alexander polynomial" . "alexpoly_lib. (line 40") ("alexanderpolynomial" . "alexanderpolynomial. (line 6") ("alexpoly.lib" . "alexpoly_lib. (line 6") ("alexpoly_lib" . "alexpoly_lib. (line 6") ("alg_kernel" . "alg_kernel. (line 6") ("algDependent" . "algDependent. (line 6") ("algebra.lib" . "algebra_lib. (line 6") ("algebra_containment" . "algebra_containment. (line 6") ("algebra_lib" . "algebra_lib. (line 6") ("Algebraic dependence" . "Algebraic dependence") ("algebraic dependence" . "perron_lib. (line 21") ("algebraic field extension" . "splitring. (line 32") ("Algebraic geometry" . "Algebraic geometry. (line 6") ("Algebraic Geometry codes" . "brnoeth_lib. (line 43") ("algebraicDependence" . "algebraicDependence. (line 6") ("algorithm of Bigatti, La Scala and Robbiano" . "Bigatti and La Scala and Robbiano") ("algorithm of Conti and Traverso" . "Conti and Traverso. (line 6") ("algorithm of Di Biase and Urbanke" . "Di Biase and Urbanke") ("algorithm of Hosten and Sturmfels" . "Hosten and Sturmfels") ("algorithm of Pottier" . "Pottier. (line 6") ("align" . "align. (line 6") ("all.lib" . "all_lib. (line 6") ("all_lib" . "all_lib. (line 6") ("allDoubleExt" . "allDoubleExt. (line 6") ("allExtOfLeft" . "allExtOfLeft. (line 6") ("allExtOfRight" . "allExtOfRight. (line 6") ("allowing net access" . "Command line options") ("allPositive" . "allPositive. (line 6") ("allprint" . "allprint. (line 6") ("allreal" . "allreal. (line 6") ("allrealst" . "allrealst. (line 6") ("allsquarefree" . "allsquarefree. (line 6") ("AltVarEnd" . "AltVarEnd. (line 6") ("AltVarStart" . "AltVarStart. (line 6") ("ambientDimension" . "ambientDimension. (line 6") ("and" . "Evaluation of logical expressions") ("Ann" . "Ann. (line 6") ("annfs" . "annfs. (line 6") ("annfs0" . "annfs0. (line 6") ("annfs2" . "annfs2. (line 6") ("annfsBMI" . "annfsBMI. (line 6") ("annfsParamBM" . "annfsParamBM. (line 6") ("annfspecial" . "annfspecial. (line 6") ("annfsRB" . "annfsRB. (line 6") ("annihilator of polynomial" . "dmodapp_lib. (line 104") ("annihilator of rational function" . "dmodloc_lib. (line 93") ("annil" . "annil. (line 6") ("annPoly" . "annPoly. (line 6") ("annRat" . "annRat. (line 6") ("annRatSyz" . "annRatSyz. (line 6") ("Appel function" . "dmodapp_lib. (line 104") ("Appel hypergeometric function" . "dmodapp_lib. (line 104") ("appelF1" . "appelF1. (line 6") ("appelF2" . "appelF2. (line 6") ("appelF4" . "appelF4. (line 6") ("appendWeight2Ord" . "appendWeight2Ord. (line 6") ("Applications" . "Applications. (line 6") ("apply" . "apply. (line 6") ("applyAdF" . "applyAdF. (line 6") ("arcpoint.lib" . "arcpoint_lib. (line 6") ("arcpoint_lib" . "arcpoint_lib. (line 6") ("areZeroElements" . "areZeroElements. (line 6") ("argument, default" . "Parameter list. (line 6") ("argument, optional" . "Parameter list. (line 6") ("ArnoldAction" . "ArnoldAction. (line 6") ("arr.lib" . "arr_lib. (line 6") ("arr2multarr" . "arr2multarr. (line 6") ("arr_lib" . "arr_lib. (line 6") ("arrange" . "arrange. (line 6") ("arrangement" . "multarr2arr. (line 14") ("arrBoolean" . "arrBoolean. (line 6") ("arrBoundedChambers" . "arrBoundedChambers. (line 6") ("arrBraid" . "arrBraid. (line 6") ("arrCenter" . "arrCenter. (line 6") ("arrCentered" . "arrCentered. (line 6") ("arrCentral" . "arrCentral. (line 6") ("arrCentralize" . "arrCentralize. (line 6") ("arrChambers" . "arrChambers. (line 6") ("arrCharPoly" . "arrCharPoly. (line 6") ("arrCone" . "arrCone. (line 6") ("arrCoordChange" . "arrCoordChange. (line 6") ("arrCoordNormalize" . "arrCoordNormalize. (line 6") ("arrDecone" . "arrDecone. (line 6") ("arrDer" . "arrDer. (line 6") ("arrEdelmanReiner" . "arrEdelmanReiner. (line 6") ("arrEssentialize" . "arrEssentialize. (line 6") ("arrExponents" . "arrExponents. (line 6") ("arrFlats" . "arrFlats. (line 6") ("arrIsEssential" . "arrIsEssential. (line 6") ("arrIsFree" . "arrIsFree. (line 6") ("arrLastVar" . "arrLastVar. (line 6") ("arrLattice" . "arrLattice. (line 6") ("arrLocalize" . "arrLocalize. (line 6") ("arrOrlikSolomon" . "arrOrlikSolomon. (line 6") ("arrPoincare" . "arrPoincare. (line 6") ("arrPrintMatrix" . "arrPrintMatrix. (line 6") ("arrRandom" . "arrRandom. (line 6") ("arrRandomCentral" . "arrRandomCentral. (line 6") ("arrRestrict" . "arrRestrict. (line 6") ("arrSet" . "arrSet. (line 6") ("arrSwapVar" . "arrSwapVar. (line 6") ("arrTypeB" . "arrTypeB. (line 6") ("arrTypeD" . "arrTypeD. (line 6") ("ASCII" . "ASCII. (line 6") ("ASCII links" . "ASCII links. (line 6") ("ask" . "ask. (line 6") ("assign" . "arrSet. (line 17") ("assignment,custom" . "Assignments for user defined types") ("Assignments for user defined types" . "Assignments for user defined types") ("assPrimes" . "assPrimes. (line 6") ("assprimeszerodim.lib" . "assprimeszerodim_lib") ("assprimeszerodim_lib" . "assprimeszerodim_lib") ("ASSUME" . "ASSUME. (line 6") ("Atkin" . "Atkin. (line 6") ("atkins.lib" . "atkins_lib. (line 6") ("atkins_lib" . "atkins_lib. (line 6") ("attrib" . "attrib. (line 6") ("Authors" . "Preface. (line 144") ("autonom" . "autonom. (line 6") ("autonomDim" . "autonomDim. (line 6") ("awalk1" . "awalk1. (line 6") ("awalk2" . "awalk2. (line 6") ("b-function" . "bfun_lib. (line 68") ("babyGiant" . "babyGiant. (line 6") ("Background" . "Background. (line 6") ("backward" . "backward. (line 6") ("bareiss" . "bareiss. (line 6") ("base2str" . "base2str. (line 6") ("basering" . "def. (line 6") ("Basic programming" . "Basic programming. (line 6") ("basicinvariants" . "basicinvariants. (line 6") ("BelongSemig" . "BelongSemig. (line 6") ("belongSemigroup" . "belongSemigroup. (line 6") ("Bern" . "Bern. (line 6") ("bernstein" . "bernstein. (line 6") ("Bernstein operator" . "dmod_lib. (line 108") ("Bernstein-Sato polynomial" . "bernstein. (line 22") ("Bernstein-Sato polynomial for variety" . "dmodvar_lib. (line 59") ("bernsteinBM" . "bernsteinBM. (line 6") ("bernsteinLift" . "bernsteinLift. (line 6") ("bertini2Singular" . "bertini2Singular. (line 6") ("betti" . "betti. (line 6") ("betti (plural)" . "betti (plural). (line 6") ("Betti number" . "Syzygies and resolutions") ("bFactor" . "bFactor. (line 6") ("bfct" . "bfct. (line 6") ("bfctAnn" . "bfctAnn. (line 6") ("bfctBound" . "bfctBound. (line 6") ("bfctIdeal" . "bfctIdeal. (line 6") ("bfctOneGB" . "bfctOneGB. (line 6") ("bfctSyz" . "bfctSyz. (line 6") ("bfctVarAnn" . "bfctVarAnn. (line 6") ("bfctVarIn" . "bfctVarIn. (line 6") ("bfun.lib" . "bfun_lib. (line 6") ("bfun_lib" . "bfun_lib. (line 6") ("Bigatti-La Scala-Robbiano algorithm" . "Bigatti and La Scala and Robbiano") ("bigint" . "bigint. (line 6") ("bigint declarations" . "bigint declarations. (line 6") ("bigint expressions" . "bigint expressions. (line 6") ("bigint operations" . "bigint operations. (line 6") ("bigint related functions" . "bigint related functions") ("bigintmat" . "bigintmat. (line 6") ("bigintmat declarations" . "bigintmat declarations") ("bigintmat expressions" . "bigintmat expressions") ("bigintmat operations" . "bigintmat operations") ("bigintmat type cast" . "bigintmat type cast. (line 6") ("bimodules" . "bimodules_lib. (line 71") ("bimodules.lib" . "bimodules_lib. (line 6") ("bimodules_lib" . "bimodules_lib. (line 6") ("binary_add" . "binary_add. (line 6") ("binomial" . "binomial. (line 6") ("binomials2intmat" . "binomials2intmat. (line 6") ("BINresol" . "BINresol. (line 6") ("birational map, image, inverse." . "invertBirMap. (line 33") ("bistd" . "bistd. (line 6") ("bisyzygies" . "bimodules_lib. (line 71") ("bitrinity" . "bitrinity. (line 6") ("blackbox" . "countedref. (line 6") ("block" . "Control structures. (line 6") ("BlowingUp" . "BlowingUp. (line 6") ("blowUp" . "blowUp. (line 6") ("blowup0" . "blowup0. (line 6") ("blowUp2" . "blowUp2. (line 6") ("blowUpBO" . "blowUpBO. (line 6") ("Blowupcenter" . "Blowupcenter. (line 6") ("boolean" . "arrBoolean. (line 15") ("boolean expressions" . "boolean expressions. (line 6") ("boolean operations" . "boolean operations. (line 6") ("boolean_constant" . "boolean_constant. (line 6") ("boolean_ideal" . "boolean_ideal. (line 6") ("boolean_poly" . "boolean_poly. (line 6") ("boolean_poly_ring" . "boolean_poly_ring. (line 6") ("boolean_set" . "boolean_set. (line 6") ("boolean_std" . "boolean_std. (line 6") ("BorelCheck" . "BorelCheck. (line 6") ("boundaryLatticePoints" . "boundaryLatticePoints") ("boundBuFou" . "boundBuFou. (line 6") ("boundDes" . "boundDes. (line 6") ("boundposDes" . "boundposDes. (line 6") ("bracket" . "bracket. (line 6") ("braid" . "arrBraid. (line 14") ("Branches of space curve singularities" . "Branches of space curve singularities") ("branchTo" . "procs with different argument types") ("break" . "break. (line 6") ("break point" . "~. (line 6") ("breakpoint" . "breakpoint. (line 6") ("Briancon-Maisonobe algorithm" . "dmod_lib. (line 108") ("Brieskorn lattice" . "mondromy_lib. (line 34") ("Brill-Noether algorithm" . "brnoeth_lib. (line 43") ("BrillNoether" . "BrillNoether. (line 6") ("brillnoether.lib" . "brillnoether_lib. (line 6") ("brillnoether_lib" . "brillnoether_lib. (line 6") ("brnoeth.lib" . "brnoeth_lib. (line 6") ("brnoeth_lib" . "brnoeth_lib. (line 6") ("browser, command line option" . "Command line options") ("browser, setting the" . "system. (line 35") ("browsers" . "The online help system") ("browsers, setting the" . "system. (line 35") ("bubblesort" . "bubblesort. (line 6") ("Buchberger algorithm for toric ideals" . "Buchberger algorithm") ("Budur-Mustata-Saito approach" . "dmodvar_lib. (line 59") ("Building Singular" . "Building Singular. (line 6") ("busadj" . "busadj. (line 6") ("bvar" . "bvar. (line 6") ("C programming language" . "Major differences to the C programming language") ("c, module ordering" . "Module orderings. (line 49") ("C, module ordering" . "Module orderings. (line 19") ("calculate_max_sum" . "calculate_max_sum. (line 6") ("calculate_ordering" . "calculate_ordering. (line 6") ("calculateI" . "calculateI. (line 6") ("cancelunit, option" . "option. (line 145") ("canonicalizeCone" . "canonicalizeCone. (line 6") ("canonize" . "canonize. (line 6") ("canonMap" . "canonMap. (line 6") ("cantoradd" . "cantoradd. (line 6") ("cantormult" . "cantormult. (line 6") ("cantorred" . "cantorred. (line 6") ("cardGroup" . "cardGroup. (line 6") ("case" . "No case or switch statement") ("Castelnuovo-Mumford regularity" . "CM_regularity. (line 21") ("Category string" . "Category string. (line 6") ("cdd" . "Preface. (line 6") ("cddlib" . "Preface. (line 6") ("CenCharDec" . "CenCharDec. (line 6") ("center" . "arrCentralize. (line 18") ("Center" . "Center. (line 6") ("center" . "center. (line 6") ("CenterBO" . "CenterBO. (line 6") ("centerRed" . "centerRed. (line 6") ("centerVS" . "centerVS. (line 6") ("central" . "arrRandomCentral. (line 16") ("central.lib" . "central_lib. (line 6") ("central1st" . "central1st. (line 6") ("central2nd" . "central2nd. (line 6") ("central_lib" . "central_lib. (line 6") ("centralize" . "central_lib. (line 19") ("centralizer" . "centralizer. (line 6") ("centralizerRed" . "centralizerRed. (line 6") ("centralizerVS" . "centralizerVS. (line 6") ("centralizeSet" . "centralizeSet. (line 6") ("CentralQuot" . "CentralQuot. (line 6") ("CentralSaturation" . "CentralSaturation. (line 6") ("cgs" . "cgs. (line 6") ("CGS, disjoint, reduced, Comprehensive Groebner System" . "cgsdr") ("cgsdr" . "cgsdr. (line 6") ("chaincrit" . "chaincrit. (line 6") ("chAll" . "chAll. (line 6") ("chAllInv" . "chAllInv. (line 6") ("chambers" . "arrBoundedChambers. (line 15") ("Change of rings" . "Change of rings. (line 6") ("changechar" . "changechar. (line 6") ("changeDenominator" . "changeDenominator. (line 6") ("changeord" . "changeord. (line 6") ("changeordTo" . "changeordTo. (line 6") ("changes" . "News and changes. (line 6") ("changevar" . "changevar. (line 6") ("char" . "char. (line 6") ("char_series" . "char_series. (line 6") ("characteristic exponents" . "invariants. (line 47") ("characteristic polynomial" . "arrCharPoly. (line 20") ("Characteristic sets" . "Characteristic sets. (line 6") ("characteristic variety" . "dmodloc_lib. (line 93") ("CharacteristicExponents" . "CharacteristicExponents") ("charexp2conductor" . "charexp2conductor. (line 6") ("charexp2generators" . "charexp2generators. (line 6") ("charexp2inter" . "charexp2inter. (line 6") ("charexp2multseq" . "charexp2multseq. (line 6") ("charexp2poly" . "charexp2poly. (line 6") ("charInfo" . "charInfo. (line 6") ("charpoly" . "charpoly. (line 6") ("charstr" . "charstr. (line 6") ("charVariety" . "charVariety. (line 6") ("chDual" . "chDual. (line 6") ("checkFactor" . "checkFactor. (line 6") ("checkRoot" . "checkRoot. (line 6") ("chern" . "chern. (line 6") ("chern.lib" . "chern_lib. (line 6") ("chern_lib" . "chern_lib. (line 6") ("chernCharPoly" . "chernCharPoly. (line 6") ("chernPoly" . "chernPoly. (line 6") ("ChernRootsDual" . "ChernRootsDual. (line 6") ("ChernRootsHom" . "ChernRootsHom. (line 6") ("ChernRootsProd" . "ChernRootsProd. (line 6") ("ChernRootsSum" . "ChernRootsSum. (line 6") ("ChernRootsSymm" . "ChernRootsSymm. (line 6") ("ChernRootsWedge" . "ChernRootsWedge. (line 6") ("Chevalley-Rosenlicht theorem" . "tangentGens. (line 34") ("chHE" . "chHE. (line 6") ("chHom" . "chHom. (line 6") ("chineseRem" . "chineseRem. (line 6") ("chinrem" . "chinrem. (line 6") ("chinrempoly" . "chinrempoly. (line 6") ("chinrestp" . "chinrestp. (line 6") ("chNum" . "chNum. (line 6") ("chNumbers" . "chNumbers. (line 6") ("chNumbersProj" . "chNumbersProj. (line 6") ("chProd" . "chProd. (line 6") ("chProdE" . "chProdE. (line 6") ("chProdL" . "chProdL. (line 6") ("chProdLP" . "chProdLP. (line 6") ("chProj" . "chProj. (line 6") ("chSum" . "chSum. (line 6") ("chSymm" . "chSymm. (line 6") ("chSymm2L" . "chSymm2L. (line 6") ("chSymm2LP" . "chSymm2LP. (line 6") ("chWedge" . "chWedge. (line 6") ("chWedge2L" . "chWedge2L. (line 6") ("chWedge2LP" . "chWedge2LP. (line 6") ("cimonom.lib" . "cimonom_lib. (line 6") ("cimonom_lib" . "cimonom_lib. (line 6") ("cisimplicial.lib" . "cisimplicial_lib. (line 6") ("cisimplicial_lib" . "cisimplicial_lib. (line 6") ("Classification of hypersurface singularities" . "Classification of hypersurface singularities") ("Classification of singularities" . "realclassify. (line 38") ("classify" . "classify. (line 6") ("classify.lib" . "classify_lib. (line 6") ("classify_lib" . "classify_lib. (line 6") ("classifyCeq" . "classifyCeq. (line 6") ("classifyceq.lib" . "classifyceq_lib. (line 6") ("classifyceq_lib" . "classifyceq_lib. (line 6") ("classifyci.lib" . "classifyci_lib. (line 6") ("classifyci_lib" . "classifyci_lib. (line 6") ("classifyicis" . "classifyicis. (line 6") ("classpoly" . "classpoly. (line 6") ("cleanTmp" . "cleanTmp. (line 6") ("cleanunit" . "cleanunit. (line 6") ("cleardenom" . "cleardenom. (line 6") ("close" . "close. (line 6") ("closed_points" . "closed_points. (line 6") ("closetex" . "closetex. (line 6") ("closureFrac" . "closureFrac. (line 6") ("CM_regularity" . "CM_regularity. (line 6") ("CMtype" . "CMtype. (line 6") ("Code" . "Codes and the decoding problem") ("Codes and the decoding problem" . "Codes and the decoding problem") ("codim" . "codim. (line 6") ("codimension" . "codimension. (line 6") ("Coding theory" . "Coding theory. (line 6") ("coding theory" . "AG codes. (line 6") ("coef" . "coef. (line 6") ("coefficient" . "arrPrintMatrix. (line 17") ("coefficient field" . "number. (line 6") ("Coefficient rings" . "Notes for Singular users") ("coefficient rings, ring of integers, zero divisors, p-adic numbers" . "Coefficient rings") ("coefficients, long" . "Long coefficients. (line 6") ("coeffmod" . "coeffmod. (line 6") ("coeffs" . "coeffs. (line 6") ("coHom" . "coHom. (line 6") ("collectDiv" . "collectDiv. (line 6") ("colrank" . "colrank. (line 6") ("colred" . "colred. (line 6") ("comma" . "Usage of commas. (line 6") ("Command line options" . "Command line options") ("command,custom" . "Commands for user defined types") ("command-line option, setting value of" . "system. (line 231") ("command-line option, value of" . "system. (line 226") ("command-line options, print all values of" . "system. (line 223") ("command-line options, short help" . "Command line options") ("Commands" . "Functions and system variables") ("commands (plural)" . "Functions (plural). (line 6") ("Commands for user defined types" . "Commands for user defined types") ("comment" . "Special characters. (line 86") ("commRing" . "commRing. (line 6") ("Commutative algebra" . "Commutative algebra. (line 6") ("Commutative Algebra" . "Commutative Algebra. (line 6") ("compareTasks" . "compareTasks. (line 6") ("CompDecomp" . "CompDecomp. (line 6") ("CompInt" . "CompInt. (line 6") ("CompleteHomog" . "CompleteHomog. (line 6") ("completeReduction" . "completeReduction. (line 6") ("complex" . "Rings and orderings. (line 26") ("complexSingType" . "complexSingType. (line 6") ("ComplexValue" . "ComplexValue. (line 6") ("compregb.lib" . "compregb_lib. (line 6") ("compregb_lib" . "compregb_lib. (line 6") ("comprehensive Groebner system" . "compregb_lib. (line 27") ("compress" . "compress. (line 6") ("computeConstant" . "computeConstant. (line 6") ("computeGromovWitten" . "computeGromovWitten. (line 6") ("computemcm" . "computemcm. (line 6") ("computeN" . "computeN. (line 6") ("computeV" . "computeV. (line 6") ("Computing Groebner and Standard Bases" . "Computing Groebner and Standard Bases") ("concat" . "concat. (line 6") ("conductor" . "charexp2conductor. (line 18") ("conductor, degree" . "invariants. (line 47") ("cone" . "arrDecone. (line 22") ("cone related functions" . "cone related functions") ("coneLink" . "coneLink. (line 6") ("coneViaInequalities" . "coneViaInequalities. (line 6") ("coneViaPoints" . "coneViaPoints. (line 6") ("conic, parametrization, rational point." . "paraConic. (line 31") ("conicWithTangents" . "conicWithTangents. (line 6") ("ConsLevels" . "ConsLevels. (line 6") ("constructblwup" . "constructblwup. (line 6") ("constructH" . "constructH. (line 6") ("constructlastblwup" . "constructlastblwup. (line 6") ("constructor" . "multarr2arr. (line 14") ("contact matrix" . "charexp2inter. (line 19") ("ContactMatrix" . "ContactMatrix. (line 6") ("containedQ" . "containedQ. (line 6") ("containsAsFace" . "containsAsFace. (line 6") ("containsInCollection" . "containsInCollection") ("containsInSupport" . "containsInSupport. (line 6") ("containsPositiveVector" . "containsPositiveVector") ("containsRelatively" . "containsRelatively. (line 6") ("content" . "content. (line 6") ("contentSB, option" . "option. (line 149") ("Conti-Traverso algorithm" . "Conti and Traverso. (line 6") ("continue" . "Behavior of continue") ("contract" . "contract. (line 6") ("contraHom" . "contraHom. (line 6") ("contributors" . "system. (line 49") ("Contributors" . "Preface. (line 144") ("control" . "control. (line 6") ("Control structures" . "Control structures. (line 6") ("Control theory" . "System and Control theory") ("control.lib" . "control_lib. (line 6") ("control_lib" . "control_lib. (line 6") ("control_Matrix" . "control_Matrix. (line 6") ("controlDim" . "controlDim. (line 6") ("controlExample" . "controlExample. (line 6") ("convertdata" . "convertdata. (line 6") ("convex geometry" . "convex geometry. (line 6") ("convexHull" . "convexHull. (line 6") ("convexIntersection" . "convexIntersection. (line 6") ("convloc" . "convloc. (line 6") ("Cooper philosophy" . "Cooper philosophy. (line 6") ("coordinate change" . "arrCoordNormalize. (line 23") ("coordinates" . "coords. (line 19") ("coords" . "coords. (line 6") ("copyright" . "Preface. (line 6") ("copyTask" . "copyTask. (line 6") ("corank" . "corank. (line 6") ("Cornacchia" . "Cornacchia. (line 6") ("CornacchiaModified" . "CornacchiaModified. (line 6") ("cornerMonomials" . "cornerMonomials. (line 6") ("countPoints" . "countPoints. (line 6") ("coverings" . "computeGromovWitten. (line 27") ("cProj" . "cProj. (line 6") ("cpu" . "system. (line 53") ("createBO" . "createBO. (line 6") ("createGradedRingHomomorphism" . "createGradedRingHomomorphism") ("createGroup" . "createGroup. (line 6") ("createlist" . "createlist. (line 6") ("createQuotientGroup" . "createQuotientGroup. (line 6") ("createTask" . "createTask. (line 6") ("createTorsionFreeGroup" . "createTorsionFreeGroup") ("Crep" . "Crep. (line 6") ("CRHT-ideal" . "Cooper philosophy. (line 25") ("Critical points" . "Critical points. (line 6") ("crypto.lib" . "crypto_lib. (line 6") ("crypto_lib" . "crypto_lib. (line 6") ("cup" . "cup. (line 6") ("cupproduct" . "cupproduct. (line 6") ("curve singularities" . "hnoether_lib. (line 49") ("curvepar.lib" . "curvepar_lib. (line 6") ("curvepar_lib" . "curvepar_lib. (line 6") ("CurveParam" . "CurveParam. (line 6") ("CurveRes" . "CurveRes. (line 6") ("Curves" . "paraplanecurves_lib. (line 73") ("custom assignment" . "Assignments for user defined types") ("custom command" . "Commands for user defined types") ("custom type" . "Definition of a user defined type") ("Customization of the Emacs interface" . "Customization of the Emacs interface") ("cycleLength" . "cycleLength. (line 6") ("cyclePoints" . "cyclePoints. (line 6") ("cyclic" . "cyclic. (line 6") ("Cyclic code" . "decodegb_lib. (line 50") ("cyclic code" . "Codes and the decoding problem") ("Cyclic roots" . "Cyclic roots. (line 6") ("cyclotomic" . "cyclotomic. (line 6") ("D-integration" . "dmodapp_lib. (line 104") ("D-localization" . "dmodloc_lib. (line 93") ("D-module" . "dmodloc_lib. (line 93") ("D-module structure" . "dmodvar_lib. (line 59") ("D-restriction" . "dmodapp_lib. (line 104") ("Data types" . "Data types. (line 6") ("Data types (plural)" . "Data types (plural). (line 6") ("datetime" . "datetime. (line 6") ("DBM links" . "DBM links. (line 6") ("dbprint" . "dbprint. (line 6") ("debug_log" . "debug_log. (line 6") ("debugger" . "Source code debugger") ("debugging library code" . "Source code debugger") ("Debugging tools" . "Debugging tools. (line 6") ("debugLib, option" . "option. (line 180") ("dec1var" . "dec1var. (line 6") ("decimal" . "decimal. (line 6") ("Decker, Wolfram" . "Preface. (line 144") ("Declaration of objects of a user defined type" . "Declaration of objects of a user defined type") ("decode" . "decode. (line 6") ("decodeCode" . "decodeCode. (line 6") ("decodegb.lib" . "decodegb_lib. (line 6") ("decodegb_lib" . "decodegb_lib. (line 6") ("decodeRandom" . "decodeRandom. (line 6") ("decodeRandomFL" . "decodeRandomFL. (line 6") ("decodeSV" . "decodeSV. (line 6") ("Decoding" . "decodegb_lib. (line 50") ("Decoding codes with Groebner bases" . "Decoding codes with Groebner bases") ("Decoding method based on quadratic equations" . "Decoding method based on quadratic equations") ("decoding, decoding problem" . "Codes and the decoding problem") ("decoef" . "decoef. (line 6") ("decone" . "arrDecone. (line 22") ("def" . "def. (line 6") ("def declarations" . "def declarations. (line 6") ("default argument" . "Parameter list. (line 6") ("defined" . "defined. (line 6") ("defineHomogeneous" . "defineHomogeneous. (line 6") ("Definition of a user defined type" . "Definition of a user defined type") ("defl" . "defl. (line 6") ("deform" . "deform. (line 6") ("deform.lib" . "deform_lib. (line 6") ("deform_lib" . "deform_lib. (line 6") ("Deformations" . "Deformations. (line 6") ("Deformations, T1 and T2" . "T1 and T2. (line 6") ("defRes, option" . "option. (line 183") ("defring" . "defring. (line 6") ("defringp" . "defringp. (line 6") ("defrings" . "defrings. (line 6") ("deg" . "deg. (line 6") ("degBound" . "degBound. (line 6") ("Degree" . "Degree. (line 6") ("degree" . "Miscellaneous oddities") ("degree lexicographical ordering" . "Global orderings. (line 28") ("degree of a polynomial" . "Miscellaneous oddities") ("degree reverse lexicographical ordering" . "Global orderings. (line 19") ("degreeDivisor" . "degreeDivisor. (line 6") ("degreeFormalDivisor" . "degreeFormalDivisor. (line 6") ("degreepart" . "degreepart. (line 6") ("delete" . "kill. (line 6") ("deleteGenerator" . "deleteGenerator. (line 6") ("deleteSublist" . "deleteSublist. (line 6") ("delta" . "delta. (line 6") ("Delta" . "Delta. (line 6") ("delta invariant" . "delta. (line 25") ("delta invariant." . "normalC. (line 99") ("DeltaList" . "DeltaList. (line 6") ("deltaLoc" . "deltaLoc. (line 6") ("Demo mode" . "Demo mode. (line 6") ("denom_list" . "system. (line 57") ("denominator" . "denominator. (line 6") ("depth" . "depth. (line 6") ("Depth" . "Depth. (line 6") ("depthIdeal" . "depthIdeal. (line 6") ("deRham.lib" . "deRham_lib. (line 6") ("deRham_lib" . "deRham_lib. (line 6") ("deRhamCohom" . "deRhamCohom. (line 6") ("deRhamCohomIdeal" . "deRhamCohomIdeal. (line 6") ("deRhamCohomology" . "deRhamCohomology. (line 6") ("derivate" . "derivate. (line 6") ("derivation" . "arrDer. (line 19") ("desingularization" . "desingularization. (line 6") ("det" . "det. (line 6") ("det_B" . "det_B. (line 6") ("detadj" . "detadj. (line 6") ("Determinacy" . "determinacy. (line 21") ("determinacy" . "determinacy. (line 6") ("determinecenter" . "determinecenter. (line 6") ("detropicalise" . "detropicalise. (line 6") ("develop" . "develop. (line 6") ("Di Biase-Urbanke algorithm" . "Di Biase and Urbanke") ("diag" . "diag. (line 6") ("diag_test" . "diag_test. (line 6") ("diagInvariants" . "diagInvariants. (line 6") ("diff" . "diff. (line 6") ("diffRat" . "diffRat. (line 6") ("difpoly2tex" . "difpoly2tex. (line 6") ("dim" . "dim. (line 6") ("dim (plural)" . "dim (plural). (line 6") ("dim_slocus" . "dim_slocus. (line 6") ("dimension" . "dimension. (line 6") ("dimensionOfLocalization" . "dimensionOfLocalization") ("dimGradedPart" . "dimGradedPart. (line 6") ("dimH" . "dimH. (line 6") ("dimMon" . "dimMon. (line 6") ("direct_boolean_poly" . "direct_boolean_poly. (line 6") ("direct_from_boolean_poly" . "direct_from_boolean_poly") ("disc" . "disc. (line 6") ("discr" . "discr. (line 6") ("discrepancy" . "discrepancy. (line 6") ("disp_zdd" . "disp_zdd. (line 6") ("DISPLAY environment variable" . "The online help system") ("displayCohom" . "displayCohom. (line 6") ("displayHNE" . "displayHNE. (line 6") ("displayInvariants" . "displayInvariants. (line 6") ("displayMultsequence" . "displayMultsequence. (line 6") ("displayPuiseuxExpansion" . "displayPuiseuxExpansion") ("displayTropicalLifting" . "displayTropicalLifting") ("distributed computing" . "tasks_lib. (line 31") ("Distributed computing" . "modular_lib. (line 43") ("div" . "Miscellaneous oddities") ("dividelist" . "dividelist. (line 6") ("divideUnits" . "divideUnits. (line 6") ("division" . "division. (line 6") ("division (plural)" . "division (plural). (line 6") ("division, pdivi, reduce" . "pnormalf. (line 23") ("division, reduce" . "pdivi. (line 23") ("divisor" . "divisor. (line 6") ("divisorplus" . "divisorplus. (line 6") ("divisors" . "degreeFormalDivisor. (line 19") ("divisors, polyhedra" . "pdivisorplus. (line 20") ("divisors.lib" . "divisors_lib. (line 6") ("divisors_lib" . "divisors_lib. (line 6") ("DLoc" . "DLoc. (line 6") ("DLoc0" . "DLoc0. (line 6") ("Dlocalization" . "Dlocalization. (line 6") ("dmod.lib" . "dmod_lib. (line 6") ("dmod_lib" . "dmod_lib. (line 6") ("dmodAction" . "dmodAction. (line 6") ("dmodActionRat" . "dmodActionRat. (line 6") ("dmodapp.lib" . "dmodapp_lib. (line 6") ("dmodapp_lib" . "dmodapp_lib. (line 6") ("dmodGeneralAssumptionCheck" . "dmodGeneralAssumptionCheck") ("dmodloc.lib" . "dmodloc_lib. (line 6") ("dmodloc_lib" . "dmodloc_lib. (line 6") ("dmodoublext" . "dmodoublext. (line 6") ("dmodvar.lib" . "dmodvar_lib. (line 6") ("dmodvar_lib" . "dmodvar_lib. (line 6") ("Documentation Tool" . "Documentation Tool. (line 6") ("double" . "double. (line 6") ("doubleExt" . "doubleExt. (line 6") ("downloading" . "Download instructions") ("Dp, global ordering" . "Global orderings. (line 28") ("dp, global ordering" . "Global orderings. (line 19") ("drawNewtonSubdivision" . "drawNewtonSubdivision") ("drawTropicalCurve" . "drawTropicalCurve. (line 6") ("Ds, local ordering" . "Local orderings. (line 25") ("ds, local ordering" . "Local orderings. (line 16") ("DsingularLocus" . "DsingularLocus. (line 6") ("dsum" . "dsum. (line 6") ("dual_code" . "dual_code. (line 6") ("dualCone" . "dualCone. (line 6") ("dualConic" . "dualConic. (line 6") ("dualPart" . "dualPart. (line 6") ("dualPolytope" . "dualPolytope. (line 6") ("dump" . "dump. (line 6") ("Dynamic loading" . "Dynamic loading. (line 6") ("Dynamic modules" . "Dynamic modules. (line 6") ("ecart" . "ecart. (line 6") ("echo" . "echo. (line 6") ("ECoef" . "ECoef. (line 6") ("ECPP" . "ECPP. (line 6") ("Edatalist" . "Edatalist. (line 6") ("Edelman-Reiner" . "arrEdelmanReiner. (line 19") ("Editing input" . "Editing input. (line 6") ("Editing SINGULAR input files with Emacs" . "Editing SINGULAR input files with Emacs") ("eexgcdN" . "eexgcdN. (line 6") ("effective" . "effective. (line 6") ("egcdMain" . "egcdMain. (line 6") ("ehrhartPolynomialCoeff" . "ehrhartPolynomialCoeff") ("ehrhartRing" . "ehrhartRing. (line 6") ("eigenvals" . "eigenvals. (line 6") ("eigenvalue" . "eigenvals. (line 21") ("eigenvalues" . "eigenvalues. (line 6") ("elemSymmId" . "elemSymmId. (line 6") ("elim" . "elim. (line 6") ("elim.lib" . "elim_lib. (line 6") ("elim1" . "elim1. (line 6") ("elim2" . "elim2. (line 6") ("elim_lib" . "elim_lib. (line 6") ("eliminate" . "eliminate. (line 6") ("eliminate (plural)" . "eliminate (plural). (line 6") ("eliminateNC" . "eliminateNC. (line 6") ("Elimination" . "Elimination. (line 6") ("elimination" . "ncpreim_lib. (line 62") ("elimlinearpart" . "elimlinearpart. (line 6") ("elimpart" . "elimpart. (line 6") ("elimpartanyr" . "elimpartanyr. (line 6") ("elimrep" . "elimrep. (line 6") ("elimRing" . "elimRing. (line 6") ("elimWeight" . "elimWeight. (line 6") ("elliptic curve" . "propagator. (line 40") ("elliptic curves" . "computeGromovWitten. (line 27") ("ellipticAdd" . "ellipticAdd. (line 6") ("ellipticAllPoints" . "ellipticAllPoints. (line 6") ("ellipticcovers.lib" . "ellipticcovers_lib. (line 6") ("ellipticcovers_lib" . "ellipticcovers_lib. (line 6") ("ellipticMult" . "ellipticMult. (line 6") ("ellipticNF" . "ellipticNF. (line 6") ("ellipticNFDB" . "ellipticNFDB. (line 6") ("ellipticRandomCurve" . "ellipticRandomCurve. (line 6") ("ellipticRandomPoint" . "ellipticRandomPoint. (line 6") ("else" . "if. (line 6") ("Emacs" . "Emacs user interface") ("Emacs, a quick guide" . "A quick guide to Emacs") ("Emacs, customization of Singular mode" . "Customization of the Emacs interface") ("Emacs, editing Singular input files" . "Editing SINGULAR input files with Emacs") ("Emacs, important commands" . "Top 20 Emacs commands") ("Emacs, overview" . "A quick guide to Emacs") ("Emacs, running Singular under" . "Running SINGULAR under Emacs") ("Emacs, Singular demo mode" . "Demo mode. (line 6") ("Emacs, user interface" . "Emacs user interface") ("Emaxcont" . "Emaxcont. (line 6") ("embedMat" . "embedMat. (line 6") ("emptyFan" . "emptyFan. (line 6") ("encode" . "encode. (line 6") ("endomorphism filtration" . "endvfilt. (line 25") ("endvfilt" . "endvfilt. (line 6") ("engine" . "engine. (line 6") ("envelop" . "envelop. (line 6") ("envelopdg" . "envelopdg. (line 6") ("envelope" . "envelope. (line 6") ("enveloping algebra" . "bimodules_lib. (line 71") ("environment variable, DISPLAY" . "The online help system") ("EOrdlist" . "EOrdlist. (line 6") ("Equal" . "Equal. (line 6") ("equalJinI" . "equalJinI. (line 6") ("equalMultiDeg" . "equalMultiDeg. (line 6") ("equations" . "equations. (line 6") ("equidim" . "equidim. (line 6") ("equidimMax" . "equidimMax. (line 6") ("equidimMaxEHV" . "equidimMaxEHV. (line 6") ("equidimZ" . "equidimZ. (line 6") ("equiRadical" . "equiRadical. (line 6") ("equising.lib" . "equising_lib. (line 6") ("equising_lib" . "equising_lib. (line 6") ("equisingular Tjurina number" . "alexpoly_lib. (line 40") ("equisingularity ideal" . "esIdeal. (line 33") ("equisingularity stratum" . "esStratum. (line 43") ("Eresol" . "Eresol. (line 6") ("ERROR" . "ERROR. (line 6") ("error recovery" . "The SINGULAR prompt. (line 6") ("errorInsert" . "errorInsert. (line 6") ("errormap" . "errormap. (line 6") ("errorRand" . "errorRand. (line 6") ("esIdeal" . "esIdeal. (line 6") ("essential" . "arrEssentialize. (line 17") ("esStratum" . "esStratum. (line 6") ("eta" . "eta. (line 6") ("euler" . "euler. (line 6") ("eulerChProj" . "eulerChProj. (line 6") ("eval" . "eval. (line 6") ("evaluate_reynolds" . "evaluate_reynolds. (line 6") ("evaluateFormalDivisor" . "evaluateFormalDivisor") ("evaluatePDivisor" . "evaluatePDivisor. (line 6") ("Evaluation of logical expressions" . "Evaluation of logical expressions") ("evalutateIntegral" . "evalutateIntegral. (line 6") ("example" . "arrEdelmanReiner. (line 19") ("Examples" . "Examples. (line 6") ("Examples of ring declarations" . "Examples of ring declarations") ("execute" . "execute. (line 6") ("exit" . "quit. (line 6") ("Exp for matrices" . "matrixExp. (line 22") ("exp2pt" . "exp2pt. (line 6") ("Experimental libraries" . "Experimental libraries") ("expo" . "expo. (line 6") ("exponents" . "arrExponents. (line 18") ("export" . "export. (line 6") ("exportNuminvs" . "exportNuminvs. (line 6") ("exportto" . "exportto. (line 6") ("expression list" . "Data types (plural). (line 6") ("Ext" . "Ext. (line 6") ("Ext, computation of" . "Computation of Ext. (line 6") ("ext-module" . "purityfiltration_lib") ("Ext_R" . "Ext_R. (line 6") ("extcurve" . "extcurve. (line 6") ("extdevelop" . "extdevelop. (line 6") ("extend" . "extend. (line 6") ("extendedTensor" . "extendedTensor. (line 6") ("extendring" . "extendring. (line 6") ("extendWeyl" . "extendWeyl. (line 6") ("extension of rings" . "splitring. (line 32") ("Exterior" . "Exterior. (line 6") ("exterior basis" . "exteriorBasis. (line 18") ("exterior power" . "exteriorPower. (line 18") ("exteriorBasis" . "exteriorBasis. (line 6") ("exteriorPower" . "exteriorPower. (line 6") ("extgcd" . "extgcd. (line 6") ("Extra weight vector" . "Extra weight vector. (line 6") ("facets" . "facets. (line 6") ("facetVertexLatticeDistances" . "facetVertexLatticeDistances") ("facetWidth" . "facetWidth. (line 6") ("facetWidths" . "facetWidths. (line 6") ("facFirstShift" . "facFirstShift. (line 6") ("facFirstWeyl" . "facFirstWeyl. (line 6") ("facGBIdeal" . "facGBIdeal. (line 6") ("facShift" . "facShift. (line 6") ("facstd" . "facstd. (line 6") ("facSubWeyl" . "facSubWeyl. (line 6") ("factmodd" . "factmodd. (line 6") ("factorgroup" . "factorgroup. (line 6") ("factorH" . "factorH. (line 6") ("factorial" . "factorial. (line 6") ("factorization" . "absfact_lib. (line 37") ("Factorization" . "Factorization. (line 6") ("factorize" . "factorize. (line 6") ("factorLenstraECM" . "factorLenstraECM. (line 6") ("factorMain" . "factorMain. (line 6") ("factory" . "Preface. (line 6") ("facWeyl" . "facWeyl. (line 6") ("fan" . "polymake_lib. (line 83") ("fan related functions" . "fan related functions") ("fanViaCones" . "fanViaCones. (line 6") ("farey" . "farey. (line 6") ("fastelim" . "fastelim. (line 6") ("fastExpt" . "fastExpt. (line 6") ("fastHC, option" . "option. (line 60") ("fetch" . "fetch. (line 6") ("fetch (plural)" . "fetch (plural). (line 6") ("fetchall" . "fetchall. (line 6") ("Feynman graph" . "ellipticcovers_lib. (line 49") ("ffsolve" . "ffsolve. (line 6") ("ffsolve.lib" . "ffsolve_lib. (line 6") ("ffsolve_lib" . "ffsolve_lib. (line 6") ("fglm" . "stdfglm. (line 23") ("fglm_solve" . "fglm_solve. (line 6") ("fglmquot" . "fglmquot. (line 6") ("fibonacci" . "fibonacci. (line 6") ("field" . "number. (line 6") ("file, .singularrc" . "Startup sequence. (line 10") ("filecmd" . "filecmd. (line 6") ("filtration" . "purityfiltration_lib") ("finalCharts" . "finalCharts. (line 6") ("find" . "find. (line 6") ("find_first_primitive_root" . "find_first_primitive_root") ("find_index" . "find_index. (line 6") ("findAuto" . "findAuto. (line 6") ("findifs.lib" . "findifs_lib. (line 6") ("findifs_example" . "findifs_example. (line 6") ("findifs_lib" . "findifs_lib. (line 6") ("findimAlgebra" . "findimAlgebra. (line 6") ("findInvo" . "findInvo. (line 6") ("findInvoDiag" . "findInvoDiag. (line 6") ("findOrientedBoundary" . "findOrientedBoundary") ("findTorsion" . "findTorsion. (line 6") ("finduni" . "finduni. (line 6") ("findvars" . "findvars. (line 6") ("finite field" . "ffsolve_lib. (line 15") ("Finite fields" . "Finite fields. (line 6") ("finiteDiagInvariants" . "finiteDiagInvariants") ("finitediff.lib" . "finitediff_lib. (line 22") ("finitediff_lib" . "finitediff_lib. (line 22") ("finitenessTest" . "finitenessTest. (line 6") ("finvar.lib" . "finvar_lib. (line 6") ("finvar_lib" . "finvar_lib. (line 6") ("first index is 1" . "First index is 1. (line 6") ("First steps" . "First steps. (line 6") ("firstoct" . "firstoct. (line 6") ("fitting" . "fitting. (line 6") ("Fitzgerald-Lax method" . "Fitzgerald-Lax method") ("fl2poly" . "fl2poly. (line 6") ("flatten" . "flatten. (line 6") ("flatteningStrat" . "flatteningStrat. (line 6") ("floating point" . "hasNumericCoeffs. (line 14") ("Flow control" . "Flow control. (line 6") ("for" . "for. (line 6") ("Formal Checker" . "Formal Checker. (line 6") ("formaldivisorplus" . "formaldivisorplus. (line 6") ("Formatting output" . "Formatting output. (line 6") ("forward" . "forward. (line 6") ("fourier" . "fourier. (line 6") ("fouriersystem" . "fouriersystem. (line 6") ("fpadim.lib" . "fpadim_lib. (line 6") ("fpadim_lib" . "fpadim_lib. (line 6") ("fprintf" . "fprintf. (line 6") ("frandwalk" . "frandwalk. (line 6") ("free" . "arrExponents. (line 18") ("free associative algebra, tensor algebra" . "Free associative algebras") ("Free resolution" . "Free resolution. (line 6") ("Free resolution, graded" . "Handling graded modules") ("freegb.lib" . "freegb_lib. (line 6") ("freegb_lib" . "freegb_lib. (line 6") ("freeGBasis" . "freeGBasis. (line 6") ("freemodule" . "freemodule. (line 6") ("freerank" . "freerank. (line 6") ("from_boolean_constant" . "from_boolean_constant") ("from_boolean_ideal" . "from_boolean_ideal. (line 6") ("from_boolean_poly" . "from_boolean_poly. (line 6") ("from_boolean_set" . "from_boolean_set. (line 6") ("frwalk" . "frwalk. (line 6") ("fullFan" . "fullFan. (line 6") ("fullSerreRelations" . "fullSerreRelations. (line 6") ("Functions" . "Functions. (line 6") ("further_hn_proc" . "further_hn_proc. (line 6") ("furtherInvar" . "furtherInvar. (line 6") ("Future benefits of Singular 4" . "Notes for Singular users") ("fVector" . "fVectorP(polymake). (line 6") ("fVectorP(polymake)" . "fVectorP(polymake). (line 6") ("fwalk" . "fwalk. (line 6") ("G-algebra" . "G-algebras. (line 6") ("G-algebra, setup" . "G-algebras. (line 51") ("G_a -Invariants" . "G_a -Invariants. (line 6") ("galois field" . "number. (line 6") ("Gamma" . "Gamma. (line 6") ("Gauss-Manin connection" . "spectrumnd. (line 26") ("Gauss-Manin system" . "goodBasis. (line 22") ("gauss_col" . "gauss_col. (line 6") ("gauss_nf" . "gauss_nf. (line 6") ("gauss_row" . "gauss_row. (line 6") ("gaussred" . "gaussred. (line 6") ("gaussred_pivot" . "gaussred_pivot. (line 6") ("GBsolve" . "GBsolve. (line 6") ("GBWeight" . "GBWeight. (line 6") ("gcd" . "gcd. (line 6") ("gcddivisor" . "gcddivisor. (line 6") ("gcdMon" . "gcdMon. (line 6") ("gen" . "gen. (line 6") ("General command syntax" . "General command syntax") ("General concepts" . "General concepts. (line 6") ("general error-locator polynomial" . "Cooper philosophy. (line 46") ("general neron." . "GND_lib. (line 21") ("General purpose" . "General purpose. (line 6") ("General syntax of a ring declaration" . "General syntax of a ring declaration") ("general weighted lexicographical ordering" . "Local orderings. (line 39") ("general weighted reverse lexicographical ordering" . "Local orderings") ("general.lib" . "general_lib. (line 6") ("general_lib" . "general_lib. (line 6") ("Generalized Hilbert Syzygy Theorem" . "Syzygies and resolutions (plural)") ("Generalized Newton identities" . "Generalized Newton identities") ("generalOrder" . "generalOrder. (line 6") ("generateG" . "generateG. (line 6") ("generators" . "charexp2generators. (line 19") ("generatorsOfLinealitySpace" . "generatorsOfLinealitySpace") ("generatorsOfSpan" . "generatorsOfSpan. (line 6") ("genericid" . "genericid. (line 6") ("genericity" . "genericity. (line 6") ("genericmat" . "genericmat. (line 6") ("genMDSMat" . "genMDSMat. (line 6") ("genoutput" . "genoutput. (line 6") ("genSymId" . "genSymId. (line 6") ("genus" . "genus. (line 6") ("Geometric genus" . "paraplanecurves_lib. (line 73") ("geometric invariant theory" . "gitfan_lib. (line 24") ("geometrical locus, locus, loci, dynamic geometry" . "locusdg. (line 22") ("geometrical locus, locus, loci, envelop" . "envelop. (line 32") ("geometrical locus, locus, loci, envelop." . "envelopdg. (line 26") ("geometrical locus, locus, loci." . "locusto. (line 25") ("German Umlaute" . "Limitations. (line 53") ("getArguments" . "getArguments. (line 6") ("getCommand" . "getCommand. (line 6") ("getCone" . "getCone. (line 6") ("getcores" . "getcores. (line 6") ("getdump" . "getdump. (line 6") ("getenv" . "system. (line 74") ("getGradingGroup" . "getGradingGroup. (line 6") ("getLattice" . "getLattice. (line 6") ("getLinearForms" . "getLinearForms. (line 6") ("getModuleGrading" . "getModuleGrading. (line 6") ("getMultiplicity" . "getMultiplicity. (line 6") ("getOneVar" . "getOneVar. (line 6") ("getResult" . "getResult. (line 6") ("getSmallest" . "getSmallest. (line 6") ("getState" . "getState. (line 6") ("Getting started" . "Getting started. (line 6") ("getVariableWeights" . "getVariableWeights. (line 6") ("gfanlib" . "Preface. (line 6") ("gfanlib_so" . "gfanlib_so. (line 6") ("GIT" . "gitfan_lib. (line 24") ("gitCone" . "gitCone. (line 6") ("gitFan" . "gitFan. (line 6") ("gitfan" . "gitfan_lib. (line 24") ("gitfan.lib" . "gitfan_lib. (line 6") ("gitfan_lib" . "gitfan_lib. (line 6") ("GKdim" . "GKdim. (line 6") ("gkdim.lib" . "gkdim_lib. (line 6") ("gkdim_lib" . "gkdim_lib. (line 6") ("gkzFan" . "gkzFan. (line 6") ("GKZsystem" . "GKZsystem. (line 6") ("global Bernstein-Sato polynomial" . "dmod_lib. (line 108") ("global Bernstein-Sato polynomial for variety" . "dmodvar_lib. (line 59") ("Global orderings" . "Global orderings. (line 6") ("globalSections" . "globalSections. (line 6") ("GMP" . "Preface. (line 6") ("gmscoeffs" . "gmscoeffs. (line 6") ("gmsnf" . "gmsnf. (line 6") ("gmspoly.lib" . "gmspoly_lib. (line 6") ("gmspoly_lib" . "gmspoly_lib. (line 6") ("gmsring" . "gmsring. (line 6") ("gmssing.lib" . "gmssing_lib. (line 6") ("gmssing_lib" . "gmssing_lib. (line 6") ("GND.lib" . "GND_lib. (line 6") ("GND_lib" . "GND_lib. (line 6") ("good basis" . "goodBasis. (line 22") ("goodBasis" . "goodBasis. (line 6") ("gorensteinIndex" . "gorensteinIndex. (line 6") ("gorensteinVector" . "gorensteinVector. (line 6") ("graal.lib" . "graal_lib. (line 6") ("graal_lib" . "graal_lib. (line 6") ("graalMixed" . "graalMixed. (line 6") ("Graded commutative algebras" . "Graded commutative algebras (SCA)") ("graded module, graded piece" . "dimGradedPart. (line 22") ("graded modules, graded homomorphisms, syzygies" . "gradedModules_lib") ("graded modules, handling of" . "Handling graded modules") ("graded Weyl algebra" . "bfun_lib. (line 68") ("gradedModules.lib" . "gradedModules_lib. (line 6") ("gradedModules_lib" . "gradedModules_lib. (line 6") ("gradeNumber" . "gradeNumber. (line 6") ("gradiator" . "gradiator. (line 6") ("graph" . "printGraph. (line 17") ("graphics.lib" . "graphics_lib. (line 6") ("graphics_lib" . "graphics_lib. (line 6") ("graphviz" . "Preface. (line 6") ("graver4ti2" . "graver4ti2. (line 6") ("grconcat" . "grconcat. (line 6") ("grdeg" . "grdeg. (line 6") ("Greuel, Gert-Martin" . "Preface. (line 144") ("grgens" . "grgens. (line 6") ("grgroebner" . "grgroebner. (line 6") ("grlift" . "grlift. (line 6") ("grlifting" . "grlifting. (line 6") ("grlifting2" . "grlifting2. (line 6") ("grlifting3" . "grlifting3. (line 6") ("grneg" . "grneg. (line 6") ("grobcov" . "grobcov. (line 6") ("grobcov.lib" . "grobcov_lib. (line 6") ("grobcov_lib" . "grobcov_lib. (line 6") ("grobj" . "grobj. (line 6") ("groebner" . "groebner and std. (line 6") ("Groebner Bases" . "Computing Groebner and Standard Bases") ("Groebner bases in free associative algebras" . "Groebner bases for two-sided ideals in free associative algebras") ("Groebner bases in G-algebras" . "Groebner bases in G-algebras") ("Groebner bases, decodeGB" . "decodegb_lib. (line 50") ("Groebner bases, slim" . "slim Groebner bases. (line 6") ("groebner basis computations" . "groebner. (line 41") ("Groebner basis conversion" . "Groebner basis conversion") ("Groebner cover, parametric ideal, canonical, discussion of" . "extend") ("Groebner fan" . "polymake_lib. (line 83") ("Groebner walk" . "rwalk. (line 22") ("groebnerComplex" . "groebnerComplex. (line 6") ("groebnerCone" . "groebnerCone. (line 6") ("groebnerFan" . "groebnerFan. (line 6") ("groebnerFanP" . "groebnerFanP. (line 6") ("Gromov-Witten invariants" . "computeGromovWitten. (line 27") ("gromovWitten" . "gromovWitten. (line 6") ("grorder" . "grorder. (line 6") ("ground field" . "number. (line 6") ("group_reynolds" . "group_reynolds. (line 6") ("grpower" . "grpower. (line 6") ("grpres" . "grpres. (line 6") ("grprod" . "grprod. (line 6") ("grrange" . "grrange. (line 6") ("grres" . "grres. (line 6") ("grrndmap" . "grrndmap. (line 6") ("grrndmap2" . "grrndmap2. (line 6") ("grrndmat" . "grrndmat. (line 6") ("grshift" . "grshift. (line 6") ("grsum" . "grsum. (line 6") ("grsyz" . "grsyz. (line 6") ("grtest" . "grtest. (line 6") ("grtranspose" . "grtranspose. (line 6") ("grtranspose1" . "grtranspose1. (line 6") ("grtwist" . "grtwist. (line 6") ("grtwists" . "grtwists. (line 6") ("grview" . "grview. (line 6") ("grwalk.lib" . "grwalk_lib. (line 6") ("grwalk_lib" . "grwalk_lib. (line 6") ("grzero" . "grzero. (line 6") ("GTZmod" . "GTZmod. (line 6") ("GTZopt" . "GTZopt. (line 6") ("gwalk" . "gwalk. (line 6") ("Gweights" . "Gweights. (line 6") ("H2basis" . "H2basis. (line 6") ("h_increasing_knapsack" . "h_increasing_knapsack") ("Hamburger-Noether expansion" . "hnoether_lib. (line 49") ("Hamburger-Noether expansions" . "Adj_div. (line 64") ("Handling graded modules" . "Handling graded modules") ("hardware platform" . "system. (line 204") ("hasAlgExtensionCoefficient" . "hasAlgExtensionCoefficient") ("hasCommutativeVars" . "hasCommutativeVars. (line 6") ("hasFieldCoefficient" . "hasFieldCoefficient. (line 6") ("hasGlobalOrdering" . "hasGlobalOrdering. (line 6") ("hasMixedOrdering" . "hasMixedOrdering. (line 6") ("hasNumericCoeffs" . "hasNumericCoeffs. (line 6") ("Hcode" . "Hcode. (line 6") ("headStand" . "headStand. (line 6") ("heightZ" . "heightZ. (line 6") ("help" . "help. (line 6") ("help browsers" . "The online help system") ("help browsers, dummy" . "The online help system") ("help browsers, emacs" . "The online help system") ("help browsers, html" . "The online help system") ("help browsers, setting command to use" . "The online help system") ("help browsers, setting the" . "system. (line 35") ("Help string" . "Help string. (line 6") ("help, accessing over the net" . "Command line options") ("help, online help system" . "The online help system") ("Hensel" . "factmodd. (line 6") ("hermiteNormalForm" . "hermiteNormalForm. (line 6") ("hess.lib" . "hess_lib. (line 6") ("hess_lib" . "hess_lib. (line 6") ("hessenberg" . "hessenberg. (line 6") ("highcorner" . "highcorner. (line 6") ("hilb" . "hilb. (line 6") ("Hilbert function" . "Hilbert function. (line 6") ("Hilbert series" . "Hilbert function. (line 6") ("Hilbert-driven GB algorithm" . "Groebner basis conversion") ("hilbert4ti2" . "hilbert4ti2. (line 6") ("hilbertBasis" . "hilbertBasis. (line 6") ("HilbertClassPoly" . "HilbertClassPoly. (line 6") ("hilbertSeries" . "hilbertSeries. (line 6") ("HilbertSeries" . "HilbertSeries. (line 6") ("HilbertWeights" . "HilbertWeights. (line 6") ("hilbPoly" . "hilbPoly. (line 6") ("hilbvec" . "hilbvec. (line 6") ("hnexpansion" . "hnexpansion. (line 6") ("hnoether.lib" . "hnoether_lib. (line 6") ("hnoether_lib" . "hnoether_lib. (line 6") ("holonomic rank" . "dmodloc_lib. (line 93") ("holonomicRank" . "holonomicRank. (line 6") ("Hom" . "Hom. (line 6") ("hom_kernel" . "hom_kernel. (line 6") ("HomJJ" . "HomJJ. (line 6") ("homog" . "homog. (line 6") ("homogeneitySpace" . "homogeneitySpace. (line 6") ("homogfacFirstQWeyl" . "homogfacFirstQWeyl. (line 6") ("homogfacFirstQWeyl_all" . "homogfacFirstQWeyl_all") ("homogfacNthQWeyl" . "homogfacNthQWeyl. (line 6") ("homogfacNthQWeyl_all" . "homogfacNthQWeyl_all") ("homolog.lib" . "homolog_lib. (line 6") ("homolog_lib" . "homolog_lib. (line 6") ("homology" . "homology. (line 6") ("Hosten-Sturmfels algorithm" . "Hosten and Sturmfels") ("How to enter and exit" . "How to enter and exit") ("How to use this manual" . "How to use this manual") ("howto, download" . "Download instructions") ("howto, install on Macintosh" . "Macintosh installation instructions") ("howto, install on Unix" . "Unix installation instructions") ("howto, install on Windows" . "Windows installation instructions") ("hres" . "hres. (line 6") ("hStarVector" . "hStarVector. (line 6") ("html, default help" . "The online help system") ("Hurwitz numbers" . "computeGromovWitten. (line 27") ("hVector" . "hVector. (line 6") ("hyperel.lib" . "hyperel_lib. (line 6") ("hyperel_lib" . "hyperel_lib. (line 6") ("hyperplane" . "arrSet. (line 17") ("hyperplane arrangement" . "dmod_lib. (line 108") ("Hypersurface singularities, classification of" . "Classification of hypersurface singularities") ("hypersurface singularity" . "mondromy_lib. (line 34") ("id2mod" . "id2mod. (line 6") ("ideal" . "ideal. (line 6") ("ideal declarations" . "ideal declarations. (line 6") ("ideal declarations (plural)" . "ideal declarations (plural)") ("ideal expressions" . "ideal expressions. (line 6") ("ideal expressions (plural)" . "ideal expressions (plural)") ("Ideal membership" . "Standard bases. (line 26") ("ideal operations" . "ideal operations. (line 6") ("ideal operations (plural)" . "ideal operations (plural)") ("ideal related functions" . "ideal related functions") ("ideal related functions (plural)" . "ideal related functions (plural)") ("ideal, toric" . "Toric ideals. (line 6") ("ideals" . "Miscellaneous oddities") ("idealsimplify" . "idealsimplify. (line 6") ("idealSplit" . "idealSplit. (line 6") ("identifier" . "Identifier resolution") ("Identifiers, syntax of" . "Names. (line 6") ("identifyvar" . "identifyvar. (line 6") ("if" . "if. (line 6") ("image_of_variety" . "image_of_variety. (line 6") ("ImageGroup" . "ImageGroup. (line 6") ("imageLattice" . "imageLattice. (line 6") ("ImageVariety" . "ImageVariety. (line 6") ("imap" . "imap. (line 6") ("imap (plural)" . "imap (plural). (line 6") ("Imap, option" . "option. (line 176") ("imapall" . "imapall. (line 6") ("impart" . "impart. (line 6") ("Implemented algorithms" . "Implemented algorithms") ("importfrom" . "importfrom. (line 6") ("iMult" . "iMult. (line 6") ("IN" . "lead. (line 18") ("inCenter" . "inCenter. (line 6") ("inCentralizer" . "inCentralizer. (line 6") ("Incl" . "Incl. (line 6") ("indepSet" . "indepSet. (line 6") ("Index" . "Index. (line 6") ("indexed names" . "Names. (line 6") ("indSet" . "indSet. (line 6") ("inequalities" . "inequalities. (line 6") ("info" . "The online help system") ("Info string" . "Info string. (line 6") ("inForm" . "inForm. (line 6") ("infRedTail, option" . "option. (line 65") ("iniD" . "iniD. (line 6") ("init_debug" . "init_debug. (line 6") ("initial" . "initial. (line 6") ("initial form" . "bfun_lib. (line 68") ("initial ideal" . "bfun_lib. (line 68") ("initial ideal approach" . "dmodvar_lib. (line 59") ("initialForm" . "initialForm. (line 6") ("initialIdeal" . "initialIdeal. (line 6") ("initialIdealW" . "initialIdealW. (line 6") ("initialMalgrange" . "initialMalgrange. (line 6") ("injective_knapsack" . "injective_knapsack. (line 6") ("inout.lib" . "inout_lib. (line 6") ("inout_lib" . "inout_lib. (line 6") ("input" . "Input and output. (line 6") ("insert" . "insert. (line 6") ("insertCone" . "insertCone. (line 6") ("insertGenerator" . "insertGenerator. (line 6") ("instructions, downloading" . "Download instructions") ("instructions, Macintosh installation" . "Macintosh installation instructions") ("instructions, Unix installation" . "Unix installation instructions") ("instructions, Windows installation" . "Windows installation instructions") ("inSubring" . "inSubring. (line 6") ("int" . "int. (line 6") ("int declarations" . "int declarations. (line 6") ("int expressions" . "int expressions. (line 6") ("int operations" . "int operations. (line 6") ("int related functions" . "int related functions") ("intclMonIdeal" . "intclMonIdeal. (line 6") ("intclToricRing" . "intclToricRing. (line 6") ("integer division" . "Miscellaneous oddities") ("integer programming" . "Integer programming. (line 6") ("integral basis" . "adjointIdeal. (line 50") ("integral closure" . "normaliz_lib. (line 52") ("integralBasis" . "integralBasis. (line 6") ("integralbasis.lib" . "integralbasis_lib. (line 6") ("integralbasis_lib" . "integralbasis_lib. (line 6") ("integralIdeal" . "integralIdeal. (line 6") ("integralModule" . "integralModule. (line 6") ("integralSection" . "integralSection. (line 6") ("integration of D-module" . "dmodapp_lib. (line 104") ("Interactive use" . "Interactive use. (line 6") ("InterDiv" . "InterDiv. (line 6") ("interface, Emacs" . "Emacs user interface") ("interiorLatticePoints" . "interiorLatticePoints") ("internalfunctions" . "internalfunctions. (line 6") ("interpolate" . "interpolate. (line 6") ("interpolation" . "interpolation. (line 6") ("interred" . "interred. (line 6") ("Interrupting SINGULAR" . "Interrupting SINGULAR") ("intersect" . "intersect. (line 6") ("intersect (plural)" . "intersect (plural). (line 6") ("intersectElim, option" . "option. (line 153") ("intersection" . "intersection. (line 6") ("intersection lattice" . "arrLattice. (line 17") ("intersection multiplicity" . "intersection. (line 21") ("intersectionDiv" . "intersectionDiv. (line 6") ("IntersectionMatrix" . "IntersectionMatrix. (line 6") ("intersectionValRingIdeals" . "intersectionValRingIdeals") ("intersectionValRings" . "intersectionValRings") ("intersectLattices" . "intersectLattices. (line 6") ("intersectMon" . "intersectMon. (line 6") ("intersectSyz, option" . "option. (line 158") ("IntersectWithSub" . "IntersectWithSub. (line 6") ("intersectZ" . "intersectZ. (line 6") ("intInverse" . "intInverse. (line 6") ("intmat" . "intmat. (line 6") ("intmat declarations" . "intmat declarations. (line 6") ("intmat expressions" . "intmat expressions. (line 6") ("intmat operations" . "intmat operations. (line 6") ("intmat related functions" . "intmat related functions") ("intmat type cast" . "intmat type cast. (line 6") ("intmat2mons" . "intmat2mons. (line 6") ("intPart" . "intPart. (line 6") ("intprog.lib" . "intprog_lib. (line 6") ("intprog_lib" . "intprog_lib. (line 6") ("intRank" . "intRank. (line 6") ("Introduction" . "Introduction. (line 6") ("intRoot" . "intRoot. (line 6") ("intRoots" . "intRoots. (line 6") ("intStrategy, option" . "option. (line 72") ("intvec" . "intvec. (line 6") ("intvec declarations" . "intvec declarations. (line 6") ("intvec expressions" . "intvec expressions. (line 6") ("intvec operations" . "intvec operations. (line 6") ("intvec related functions" . "intvec related functions") ("invariant ring minimal generating set matrix group" . "invariant_algebra_reynolds") ("invariant ring minimal generating set permutation group" . "invariant_algebra_perm") ("Invariant theory" . "Invariant theory. (line 6") ("Invariant Theory" . "Invariant Theory. (line 6") ("invariant_algebra_perm" . "invariant_algebra_perm") ("invariant_algebra_reynolds" . "invariant_algebra_reynolds") ("invariant_basis" . "invariant_basis. (line 6") ("invariant_basis_reynolds" . "invariant_basis_reynolds") ("invariant_ring" . "invariant_ring. (line 6") ("invariant_ring_random" . "invariant_ring_random") ("InvariantQ" . "InvariantQ. (line 6") ("InvariantRing" . "InvariantRing. (line 6") ("invariantRing" . "invariantRing. (line 6") ("invariants" . "invariants. (line 6") ("Invariants of a finite group" . "Invariants of a finite group") ("Invariants of plane curve singularities" . "Invariants of plane curve singularities") ("inverse" . "inverse. (line 6") ("inverse of a matrix via its LU-decomposition" . "luinverse. (line 6") ("inverse_B" . "inverse_B. (line 6") ("inverse_L" . "inverse_L. (line 6") ("inverse_modulus" . "inverse_modulus. (line 6") ("inverseFourier" . "inverseFourier. (line 6") ("invertBirMap" . "invertBirMap. (line 6") ("invertNumberMain" . "invertNumberMain. (line 6") ("involut.lib" . "involut_lib. (line 6") ("involut_lib" . "involut_lib. (line 6") ("involution" . "involution. (line 6") ("invunit" . "invunit. (line 6") ("iostruct" . "iostruct. (line 6") ("irred_secondary_char0" . "irred_secondary_char0") ("irred_secondary_no_molien" . "irred_secondary_no_molien") ("irreddecMon" . "irreddecMon. (line 6") ("irreducible power series" . "is_irred. (line 26") ("irreducible secondary invariant" . "irred_secondary_char0") ("irrRealizationDim" . "irrRealizationDim. (line 6") ("is_active" . "is_active. (line 6") ("is_bijective" . "is_bijective. (line 6") ("is_cenBimodule" . "is_cenBimodule. (line 6") ("is_cenSubbimodule" . "is_cenSubbimodule. (line 6") ("is_ci" . "is_ci. (line 6") ("is_complex" . "is_complex. (line 6") ("is_fix_injective" . "is_fix_injective. (line 6") ("is_h_injective" . "is_h_injective. (line 6") ("is_injective" . "is_injective. (line 6") ("is_irred" . "is_irred. (line 6") ("is_is" . "is_is. (line 6") ("is_nested" . "is_nested. (line 6") ("is_NND" . "is_NND. (line 6") ("is_NP" . "is_NP. (line 6") ("is_prime" . "is_prime. (line 6") ("is_primitive_root" . "is_primitive_root. (line 6") ("is_pure" . "is_pure. (line 6") ("is_reg" . "is_reg. (line 6") ("is_regs" . "is_regs. (line 6") ("is_surjective" . "is_surjective. (line 6") ("is_zero" . "is_zero. (line 6") ("isAface" . "isAface. (line 6") ("isAntiEndo" . "isAntiEndo. (line 6") ("isartinianMon" . "isartinianMon. (line 6") ("isBounded" . "isBounded. (line 6") ("isCanonical" . "isCanonical. (line 6") ("isCartan" . "isCartan. (line 6") ("isCentral" . "isCentral. (line 6") ("isCI" . "isCI. (line 6") ("isCM" . "isCM. (line 6") ("isCMcod2" . "isCMcod2. (line 6") ("isCommutative" . "isCommutative. (line 6") ("isCompatible" . "isCompatible. (line 6") ("isCompressed" . "isCompressed. (line 6") ("isEqualDivisor" . "isEqualDivisor. (line 6") ("isEquising" . "isEquising. (line 6") ("isFlat" . "isFlat. (line 6") ("isFsat" . "isFsat. (line 6") ("isFullSpace" . "isFullSpace. (line 6") ("isgenericMon" . "isgenericMon. (line 6") ("isGorenstein" . "isGorenstein. (line 6") ("isGradedRingHomomorphism" . "isGradedRingHomomorphism") ("isGroup" . "isGroup. (line 6") ("isGroupHomomorphism" . "isGroupHomomorphism. (line 6") ("isHolonomic" . "isHolonomic. (line 6") ("isHomg" . "attrib. (line 69") ("isHomogeneous" . "isHomogeneous. (line 6") ("ishyper" . "ishyper. (line 6") ("isInt" . "isInt. (line 6") ("isIntegralSurjective" . "isIntegralSurjective") ("isInvolution" . "isInvolution. (line 6") ("isirreducibleMon" . "isirreducibleMon. (line 6") ("isLatticeEmpty" . "isLatticeEmpty. (line 6") ("isLocalizationRegular" . "isLocalizationRegular") ("isLocallyFree" . "isLocallyFree. (line 6") ("isMonomial" . "isMonomial. (line 6") ("isNC" . "isNC. (line 6") ("isNormal" . "isNormal. (line 6") ("isoncurve" . "isoncurve. (line 6") ("isOnCurve" . "isOnCurve. (line 6") ("isOrigin" . "isOrigin. (line 6") ("isparam" . "isparam. (line 6") ("isPositive" . "isPositive. (line 6") ("isprimaryMon" . "isprimaryMon. (line 6") ("isprimeMon" . "isprimeMon. (line 6") ("isPrimitiveSublattice" . "isPrimitiveSublattice") ("isPure" . "isPure. (line 6") ("isPureTensor" . "isPureTensor. (line 6") ("isQuotientRing" . "isQuotientRing. (line 6") ("isRational" . "isRational. (line 6") ("isReflexive" . "isReflexive. (line 6") ("isReg" . "isReg. (line 6") ("isSB" . "attrib. (line 69") ("IsSCA" . "IsSCA. (line 6") ("isSimplicial" . "isSimplicial. (line 6") ("isSmooth" . "isSmooth. (line 6") ("isSublattice" . "isSublattice. (line 6") ("isSubModule" . "isSubModule. (line 6") ("isSymmetric" . "isSymmetric. (line 6") ("isTame" . "isTame. (line 6") ("isTerminal" . "isTerminal. (line 6") ("isTorsionFree" . "isTorsionFree. (line 6") ("isTwoSidedGB" . "isTwoSidedGB. (line 6") ("isuni" . "isuni. (line 6") ("isUpperTriangular" . "isUpperTriangular. (line 6") ("isVar" . "isVar. (line 6") ("isVeryAmple" . "isVeryAmple. (line 6") ("isWeyl" . "isWeyl. (line 6") ("isZeroElement" . "isZeroElement. (line 6") ("iv2lp" . "iv2lp. (line 6") ("iv2lpList" . "iv2lpList. (line 6") ("iv2lpMat" . "iv2lpMat. (line 6") ("ivDHilbert" . "ivDHilbert. (line 6") ("ivDHilbertSickle" . "ivDHilbertSickle. (line 6") ("ivDimCheck" . "ivDimCheck. (line 6") ("ivHilbert" . "ivHilbert. (line 6") ("ivKDim" . "ivKDim. (line 6") ("ivL2lpI" . "ivL2lpI. (line 6") ("ivMis2Base" . "ivMis2Base. (line 6") ("ivMis2Dim" . "ivMis2Dim. (line 6") ("ivOrdMisLex" . "ivOrdMisLex. (line 6") ("ivSickle" . "ivSickle. (line 6") ("ivSickleDim" . "ivSickleDim. (line 6") ("ivSickleHil" . "ivSickleHil. (line 6") ("J-marked schemes" . "JMBTest_lib. (line 15") ("J-marked schemes, Borel ideals" . "JMSConst_lib. (line 15") ("jacob" . "jacob. (line 6") ("Jacobi" . "Jacobi. (line 6") ("jacoblift" . "jacoblift. (line 6") ("jacobson" . "jacobson. (line 6") ("Jacobson form" . "jacobson_lib. (line 58") ("Jacobson normal form" . "jacobson_lib. (line 58") ("jacobson.lib" . "jacobson_lib. (line 6") ("jacobson_lib" . "jacobson_lib. (line 6") ("janet" . "janet. (line 6") ("jet" . "jet. (line 6") ("jInvariant" . "jInvariant. (line 6") ("JMarkedScheme" . "JMarkedScheme. (line 6") ("JMBTest.lib" . "JMBTest_lib. (line 6") ("JMBTest_lib" . "JMBTest_lib. (line 6") ("JMSConst.lib" . "JMSConst_lib. (line 6") ("JMSConst_lib" . "JMSConst_lib. (line 6") ("jOft" . "jOft. (line 6") ("jordan" . "jordan. (line 6") ("jordanbasis" . "jordanbasis. (line 6") ("jordanmatrix" . "jordanmatrix. (line 6") ("jordannf" . "jordannf. (line 6") ("jungfib" . "jungfib. (line 6") ("jungnormal" . "jungnormal. (line 6") ("jungresolve" . "jungresolve. (line 6") ("JuReTopDim" . "JuReTopDim. (line 6") ("JuReZeroDim" . "JuReZeroDim. (line 6") ("katsura" . "katsura. (line 6") ("kbase" . "kbase. (line 6") ("kbase (plural)" . "kbase (plural). (line 6") ("keepring" . "keepring. (line 6") ("KeneshlouMatrixPresentation" . "KeneshlouMatrixPresentation") ("kernel" . "kernel. (line 6") ("Kernel of module homomorphisms" . "Kernel of module homomorphisms") ("kernelLattice" . "kernelLattice. (line 6") ("kill" . "kill. (line 6") ("killall" . "killall. (line 6") ("killattrib" . "killattrib. (line 6") ("killTask" . "killTask. (line 6") ("kmemory" . "kmemory. (line 6") ("kohom" . "kohom. (line 6") ("kontrahom" . "kontrahom. (line 6") ("koszul" . "koszul. (line 6") ("KoszulHomology" . "KoszulHomology. (line 6") ("KScoef" . "KScoef. (line 6") ("KSconvert" . "KSconvert. (line 6") ("KSker" . "KSker. (line 6") ("kskernel.lib" . "kskernel_lib. (line 6") ("kskernel_lib" . "kskernel_lib. (line 6") ("KSlinear" . "KSlinear. (line 6") ("KSpencerKernel" . "KSpencerKernel. (line 6") ("l-adic numbers" . "Coefficient rings. (line 14") ("laguerre" . "laguerre. (line 6") ("laguerre_solve" . "laguerre_solve. (line 6") ("lastvarGeneral" . "lastvarGeneral. (line 6") ("latex.lib" . "latex_lib. (line 6") ("latex_lib" . "latex_lib. (line 6") ("lattice" . "arrLattice. (line 17") ("latticeArea" . "latticeArea. (line 6") ("latticeBasis" . "latticeBasis. (line 6") ("latticeCodegree" . "latticeCodegree. (line 6") ("latticeDegree" . "latticeDegree. (line 6") ("latticePoints" . "latticePoints. (line 6") ("latticeVolume" . "latticeVolume. (line 6") ("Laurent series" . "computeConstant. (line 22") ("laxfrT" . "laxfrT. (line 6") ("laxfrX" . "laxfrX. (line 6") ("lazy, option" . "option. (line 78") ("lcm" . "lcm. (line 6") ("lcmMon" . "lcmMon. (line 6") ("lcmN" . "lcmN. (line 6") ("lcmofall" . "lcmofall. (line 6") ("lead" . "lead. (line 6") ("leadcoef" . "leadcoef. (line 6") ("leadexp" . "leadexp. (line 6") ("leadmonom" . "leadmonom. (line 6") ("leadmonomial" . "leadmonomial. (line 6") ("Left and two-sided Groebner bases" . "Left and two-sided Groebner bases") ("left annihilator ideal" . "dmod_lib. (line 108") ("Left ideal membership" . "Groebner bases in G-algebras") ("Left normal form" . "Groebner bases in G-algebras") ("leftInverse" . "leftInverse. (line 6") ("leftKernel" . "leftKernel. (line 6") ("length, option" . "option. (line 83") ("LengthSym" . "LengthSym. (line 6") ("LengthSymElement" . "LengthSymElement. (line 6") ("letplaceGBasis" . "letplaceGBasis. (line 6") ("Letterplace" . "LETTERPLACE. (line 6") ("LETTERPLACE" . "LETTERPLACE. (line 6") ("letterplace correspondence" . "Letterplace correspondence") ("lex_solve" . "lex_solve. (line 6") ("Lexicographic Groebner bases, computation of" . "Groebner basis conversion") ("lexicographical ordering" . "Global orderings. (line 9") ("LIB" . "LIB. (line 6") ("LIB commands" . "LIB commands. (line 6") ("lib2doc" . "Documentation Tool. (line 6") ("libcdd" . "Preface. (line 6") ("libfac" . "Preface. (line 6") ("libparse" . "libparse. (line 6") ("Libraries" . "Writing procedures and libraries") ("Libraries in the SINGULAR Documentation" . "Libraries in the SINGULAR Documentation") ("library" . "gitfan_lib. (line 24") ("Library versioning" . "Notes for Singular users") ("library, info string" . "template_lib. (line 137") ("library, polybori.lib" . "polybori_lib. (line 94") ("library, template" . "template_lib. (line 6") ("library, template.lib" . "template_lib. (line 137") ("LIBs" . "SINGULAR libraries. (line 6") ("Lie algebra" . "tangentGens. (line 34") ("Lie group" . "maxZeros. (line 33") ("lieBracket" . "lieBracket. (line 6") ("lift" . "bimodules_lib. (line 71") ("lift (plural)" . "lift (plural). (line 6") ("lift_kbase" . "lift_kbase. (line 6") ("lift_rel_kb" . "lift_rel_kb. (line 6") ("liftenvelope" . "liftenvelope. (line 6") ("liftstd" . "liftstd. (line 6") ("liftstd (plural)" . "liftstd (plural). (line 6") ("Limitations" . "Limitations. (line 6") ("linalg.lib" . "linalg_lib. (line 6") ("linalg_lib" . "linalg_lib. (line 6") ("linealityDimension" . "linealityDimension. (line 6") ("linealitySpace" . "linealitySpace. (line 6") ("Linear algebra" . "Linear algebra. (line 6") ("linear algebra" . "lusolve. (line 6") ("Linear code" . "decodegb_lib. (line 50") ("linear code, dual" . "dual_code. (line 18") ("linear code, systematic" . "sys_code. (line 27") ("linear interreduction" . "bfun_lib. (line 68") ("linear_relations" . "linear_relations. (line 6") ("LinearActionQ" . "LinearActionQ. (line 6") ("LinearCombinationQ" . "LinearCombinationQ. (line 6") ("linearCombinations" . "linearCombinations. (line 6") ("LinearizeAction" . "LinearizeAction. (line 6") ("linearlyEquivalent" . "linearlyEquivalent. (line 6") ("linearMapKernel" . "linearMapKernel. (line 6") ("linearpart" . "linearpart. (line 6") ("link" . "Parallelization with ssi links") ("link declarations" . "link declarations. (line 6") ("link expressions" . "link expressions. (line 6") ("link related functions" . "link related functions") ("linReduce" . "linReduce. (line 6") ("linReduceIdeal" . "linReduceIdeal. (line 6") ("linSyzSolve" . "linSyzSolve. (line 6") ("list" . "list. (line 6") ("list declarations" . "list declarations. (line 6") ("list expressions" . "list expressions. (line 6") ("list operations" . "list operations. (line 6") ("list related functions" . "list related functions") ("listvar" . "listvar. (line 6") ("lll" . "lll. (line 6") ("LLL" . "system. (line 97") ("load" . "load. (line 6") ("Loading a library" . "Loading a library. (line 6") ("loadLib, option" . "option. (line 187") ("loadProc, option" . "option. (line 190") ("local methods" . "locNormal. (line 49") ("local names" . "Names in procedures. (line 6") ("Local orderings" . "Local orderings. (line 6") ("local rings, computing in" . "Rings associated to monomial orderings") ("local weighted lexicographical ordering" . "Local orderings. (line 39") ("local weighted reverse lexicographical ordering" . "Local orderings") ("localInvar" . "localInvar. (line 6") ("localization" . "arrLocalize. (line 16") ("localization of D-module" . "dmodloc_lib. (line 93") ("locally closed set, constructible set" . "ConsLevels. (line 26") ("localstd" . "localstd. (line 6") ("locAtZero" . "locAtZero. (line 6") ("locNormal" . "locNormal. (line 6") ("locnormal.lib" . "locnormal_lib. (line 6") ("locnormal_lib" . "locnormal_lib. (line 6") ("locstd" . "locstd. (line 6") ("locus" . "locus. (line 6") ("locusdg" . "locusdg. (line 6") ("locusto" . "locusto. (line 6") ("Log for matrices" . "matrixLog. (line 23") ("log2" . "log2. (line 6") ("logarithmic annihilator ideal" . "dmod_lib. (line 108") ("Long coefficients" . "Long coefficients. (line 6") ("LOT algorithm" . "dmod_lib. (line 108") ("lowerHomogeneitySpace" . "lowerHomogeneitySpace") ("lp, global ordering" . "Global orderings. (line 9") ("lp2iv" . "lp2iv. (line 6") ("lp2ivId" . "lp2ivId. (line 6") ("lp2lstr" . "lp2lstr. (line 6") ("lpDHilbert" . "lpDHilbert. (line 6") ("lpDHilbertSickle" . "lpDHilbertSickle. (line 6") ("lpDimCheck" . "lpDimCheck. (line 6") ("lpHilbert" . "lpHilbert. (line 6") ("lpId2ivLi" . "lpId2ivLi. (line 6") ("lpKDim" . "lpKDim. (line 6") ("lpMis2Base" . "lpMis2Base. (line 6") ("lpMis2Dim" . "lpMis2Dim. (line 6") ("lpMult" . "lpMult. (line 6") ("lpNF" . "lpNF. (line 6") ("lpOrdMisLex" . "lpOrdMisLex. (line 6") ("lpPower" . "lpPower. (line 6") ("lprint" . "lprint. (line 6") ("lpSickle" . "lpSickle. (line 6") ("lpSickleDim" . "lpSickleDim. (line 6") ("lpSickleHil" . "lpSickleHil. (line 6") ("lres" . "lres. (line 6") ("ls, local ordering" . "Local orderings. (line 11") ("lst2str" . "lst2str. (line 6") ("lsum" . "lsum. (line 6") ("LU-decomposition of a matrix of numbers" . "ludecomp. (line 6") ("ludecomp" . "ludecomp. (line 6") ("luinverse" . "luinverse. (line 6") ("lusolve" . "lusolve. (line 6") ("M, ordering" . "Matrix orderings. (line 6") ("m_merkle_hellman_decryption" . "m_merkle_hellman_decryption") ("m_merkle_hellman_encryption" . "m_merkle_hellman_encryption") ("m_merkle_hellman_transformation" . "m_merkle_hellman_transformation") ("Macintosh installation" . "Macintosh installation instructions") ("magnitude" . "magnitude. (line 6") ("makeDivisor" . "makeDivisor. (line 6") ("makeFormalDivisor" . "makeFormalDivisor. (line 6") ("makeGraph" . "makeGraph. (line 6") ("makeHeisenberg" . "makeHeisenberg. (line 6") ("makeLetterplaceRing" . "makeLetterplaceRing. (line 6") ("makeMalgrange" . "makeMalgrange. (line 6") ("makeModElimRing" . "makeModElimRing. (line 6") ("makePDivisor" . "makePDivisor. (line 6") ("makeQsl2" . "makeQsl2. (line 6") ("makeQsl3" . "makeQsl3. (line 6") ("makeQso3" . "makeQso3. (line 6") ("makeUe6" . "makeUe6. (line 6") ("makeUe7" . "makeUe7. (line 6") ("makeUe8" . "makeUe8. (line 6") ("makeUf4" . "makeUf4. (line 6") ("makeUg2" . "makeUg2. (line 6") ("makeUgl" . "makeUgl. (line 6") ("makeUsl" . "makeUsl. (line 6") ("makeUsl2" . "makeUsl2. (line 6") ("makeUso10" . "makeUso10. (line 6") ("makeUso11" . "makeUso11. (line 6") ("makeUso12" . "makeUso12. (line 6") ("makeUso5" . "makeUso5. (line 6") ("makeUso6" . "makeUso6. (line 6") ("makeUso7" . "makeUso7. (line 6") ("makeUso8" . "makeUso8. (line 6") ("makeUso9" . "makeUso9. (line 6") ("makeUsp1" . "makeUsp1. (line 6") ("makeUsp2" . "makeUsp2. (line 6") ("makeUsp3" . "makeUsp3. (line 6") ("makeUsp4" . "makeUsp4. (line 6") ("makeUsp5" . "makeUsp5. (line 6") ("makeWeyl" . "makeWeyl. (line 6") ("map" . "map. (line 6") ("map (plural)" . "map (plural). (line 6") ("map declarations" . "map declarations. (line 6") ("map declarations (plural)" . "map declarations (plural)") ("map expressions" . "map expressions. (line 6") ("map expressions (plural)" . "map expressions (plural)") ("map operations" . "map operations. (line 6") ("map operations (plural)" . "map operations (plural)") ("map related functions" . "map related functions") ("map related functions (plural)" . "map related functions (plural)") ("mapall" . "mapall. (line 6") ("mapIsFinite" . "mapIsFinite. (line 6") ("mappingcone" . "mappingcone. (line 6") ("mappingcone3" . "mappingcone3. (line 6") ("mapToRatNormCurve" . "mapToRatNormCurve. (line 6") ("markov4ti2" . "markov4ti2. (line 6") ("mat2arr" . "mat2arr. (line 6") ("mat2carr" . "mat2carr. (line 6") ("mat_rk" . "mat_rk. (line 6") ("matbil" . "matbil. (line 6") ("Mathematical background" . "Mathematical background") ("Mathematical background (plural)" . "Mathematical background (plural)") ("mathematical objects" . "Representation of mathematical objects") ("mathinit" . "mathinit. (line 6") ("matmult" . "matmult. (line 6") ("matrix" . "arrPrintMatrix. (line 17") ("matrix declarations" . "matrix declarations. (line 6") ("matrix diagonalization" . "jacobson_lib. (line 58") ("matrix expressions" . "matrix expressions. (line 6") ("matrix operations" . "matrix operations. (line 6") ("Matrix orderings" . "Matrix orderings. (line 6") ("matrix related functions" . "matrix related functions") ("matrix type cast" . "matrix type cast. (line 6") ("matrix.lib" . "matrix_lib. (line 6") ("matrix_lib" . "matrix_lib. (line 6") ("matrixExp" . "matrixExp. (line 6") ("matrixLog" . "matrixLog. (line 6") ("matrixpres" . "matrixpres. (line 6") ("matrixsystem" . "matrixsystem. (line 6") ("matrixT1" . "matrixT1. (line 6") ("Max" . "Max. (line 6") ("max" . "max. (line 6") ("maxabs" . "maxabs. (line 6") ("maxcoef" . "maxcoef. (line 6") ("maxdeg" . "maxdeg. (line 6") ("maxdeg1" . "maxdeg1. (line 6") ("maxEord" . "maxEord. (line 6") ("maxideal" . "maxideal. (line 6") ("maximalFace" . "maximalFace. (line 6") ("maximalGroebnerCone" . "maximalGroebnerCone. (line 6") ("maximalValue" . "maximalValue. (line 6") ("maximum" . "maximum. (line 6") ("maximum number of zeroes" . "maxZeros. (line 33") ("Maximus" . "Maximus. (line 6") ("maxIntRoot" . "maxIntRoot. (line 6") ("Maxord" . "Maxord. (line 6") ("maxZeros" . "maxZeros. (line 6") ("mdouble" . "mdouble. (line 6") ("mem, option" . "option. (line 193") ("membershipMon" . "membershipMon. (line 6") ("memory" . "memory. (line 6") ("memory managment" . "memory. (line 6") ("merkle_hellman_decryption" . "merkle_hellman_decryption") ("merkle_hellman_encryption" . "merkle_hellman_encryption") ("midpoint" . "midpoint. (line 6") ("MillerRabin" . "MillerRabin. (line 6") ("milnor" . "milnor. (line 6") ("Milnor number" . "milnornumber. (line 14") ("milnorcode" . "milnorcode. (line 6") ("milnornumber" . "milnornumber. (line 6") ("Min" . "Min. (line 6") ("min" . "min. (line 6") ("minAssChar" . "minAssChar. (line 6") ("minAssCharE" . "minAssCharE. (line 6") ("minAssGTZ" . "minAssGTZ. (line 6") ("minAssGTZE" . "minAssGTZE. (line 6") ("minAssZ" . "minAssZ. (line 6") ("minbase" . "minbase. (line 6") ("minbaseMon" . "minbaseMon. (line 6") ("mindeg" . "mindeg. (line 6") ("mindeg1" . "mindeg1. (line 6") ("mindist" . "mindist. (line 6") ("minEcart" . "minEcart. (line 6") ("minimal display time, setting the" . "system. (line 231") ("MinimalDecomposition" . "MinimalDecomposition") ("minimalFace" . "minimalFace. (line 6") ("minimalValue" . "minimalValue. (line 6") ("Minimum distance" . "decodegb_lib. (line 50") ("Minimus" . "Minimus. (line 6") ("minIntRoot" . "minIntRoot. (line 6") ("minIntRoot2" . "minIntRoot2. (line 6") ("minipoly" . "minipoly. (line 6") ("minkowskiSum" . "minkowskiSum. (line 6") ("MinMult" . "MinMult. (line 6") ("minMult" . "minMult. (line 6") ("minor" . "minor. (line 6") ("minpoly" . "minpoly. (line 6") ("minres" . "minres. (line 6") ("minres (plural)" . "minres (plural). (line 6") ("mirror symmetry" . "ellipticcovers_lib. (line 49") ("Miscellaneous libraries" . "Miscellaneous libraries") ("mixed Hodge structure" . "goodBasis. (line 22") ("mod" . "number operations. (line 6") ("mod2id" . "mod2id. (line 6") ("mod2str" . "mod2str. (line 6") ("mod_versal" . "mod_versal. (line 6") ("modality" . "modality. (line 6") ("modDec" . "modDec. (line 6") ("ModEqn" . "ModEqn. (line 6") ("modfrWalk" . "modfrWalk. (line 6") ("modfWalk" . "modfWalk. (line 6") ("modNormal" . "modNormal. (line 6") ("modnormal.lib" . "modnormal_lib. (line 6") ("modnormal_lib" . "modnormal_lib. (line 6") ("modNPos" . "modNPos. (line 6") ("modNpos_test" . "modNpos_test. (line 6") ("modregCM" . "modregCM. (line 6") ("modrWalk" . "modrWalk. (line 6") ("modsatiety" . "modsatiety. (line 6") ("modStd" . "modStd. (line 6") ("modstd.lib" . "modstd_lib. (line 6") ("modstd_lib" . "modstd_lib. (line 6") ("modular" . "modular. (line 6") ("modular methods" . "modnormal_lib. (line 41") ("modular methods." . "locNormal. (line 49") ("Modular techniques" . "modular_lib. (line 43") ("modular techniques." . "modNormal. (line 37") ("modular.lib" . "modular_lib. (line 6") ("modular_lib" . "modular_lib. (line 6") ("module" . "module. (line 6") ("module (plural)" . "module (plural). (line 6") ("module declarations" . "module declarations. (line 6") ("module declarations (plural)" . "module declarations (plural)") ("module expressions" . "module expressions. (line 6") ("module expressions (plural)" . "module expressions (plural)") ("module operations" . "module operations. (line 6") ("module operations (plural)" . "module operations (plural)") ("module ordering c" . "Module orderings. (line 49") ("module ordering C" . "Module orderings. (line 19") ("Module orderings" . "Module orderings. (line 6") ("module related functions" . "module related functions") ("module related functions (plural)" . "module related functions (plural)") ("module_containment" . "module_containment. (line 6") ("Modules and and their annihilator" . "Modules and their annihilator") ("modulo" . "modulo. (line 6") ("modulo (plural)" . "modulo (plural). (line 6") ("moduloSlim" . "moduloSlim. (line 6") ("modWalk" . "modWalk. (line 6") ("modwalk.lib" . "modwalk_lib. (line 6") ("modwalk_lib" . "modwalk_lib. (line 6") ("moebius" . "moebius. (line 6") ("moebius function" . "moebius. (line 14") ("molien" . "molien. (line 6") ("mondromy.lib" . "mondromy_lib. (line 6") ("mondromy_lib" . "mondromy_lib. (line 6") ("monitor" . "monitor. (line 6") ("Monodromy" . "mondromy_lib. (line 34") ("monodromy" . "goodBasis. (line 22") ("monodromyB" . "monodromyB. (line 6") ("monomial" . "monomial. (line 6") ("monomial ordering" . "hasGlobalOrdering. (line 14") ("monomial orderings" . "General definitions for orderings") ("Monomial orderings" . "Monomial orderings. (line 6") ("monomial orderings" . "Rings associated to monomial orderings") ("monomial orderings introduction" . "Introduction to orderings") ("Monomial orderings, Term orderings" . "Term orderings. (line 6") ("monomialideal.lib" . "monomialideal_lib. (line 6") ("monomialideal_lib" . "monomialideal_lib. (line 6") ("monomialInIdeal" . "monomialInIdeal. (line 6") ("monomialLcm" . "monomialLcm. (line 6") ("monomials and precedence" . "Miscellaneous oddities") ("mons2intmat" . "mons2intmat. (line 6") ("Morse lemma" . "realmorsesplit. (line 22") ("morsesplit" . "morsesplit. (line 6") ("mp_res_mat" . "mp_res_mat. (line 6") ("mplot" . "mplot. (line 6") ("mpresmat" . "mpresmat. (line 6") ("mprimdec.lib" . "mprimdec_lib. (line 6") ("mprimdec_lib" . "mprimdec_lib. (line 6") ("mregular.lib" . "mregular_lib. (line 6") ("mregular_lib" . "mregular_lib. (line 6") ("mres" . "mres. (line 6") ("mres (plural)" . "mres (plural). (line 6") ("mstd" . "mstd. (line 6") ("msum" . "msum. (line 6") ("mtriple" . "mtriple. (line 6") ("mult" . "Miscellaneous oddities") ("multarr2arr" . "multarr2arr. (line 6") ("multarrMultRestrict" . "multarrMultRestrict. (line 6") ("multarrRestrict" . "multarrRestrict. (line 6") ("multBound" . "multBound. (line 6") ("multcol" . "multcol. (line 6") ("multdivisor" . "multdivisor. (line 6") ("multformaldivisor" . "multformaldivisor. (line 6") ("multi" . "multi. (line 6") ("multi indices" . "Names. (line 6") ("multiarrangement" . "multarrMultRestrict. (line 28") ("multiDeg" . "multiDeg. (line 6") ("multiDegBasis" . "multiDegBasis. (line 6") ("multiDegGroebner" . "multiDegGroebner. (line 6") ("multiDegModulo" . "multiDegModulo. (line 6") ("multiDegPartition" . "multiDegPartition. (line 6") ("multiDegResolution" . "multiDegResolution. (line 6") ("multiDegSyzygy" . "multiDegSyzygy. (line 6") ("multiDegTensor" . "multiDegTensor. (line 6") ("multiDegTor" . "multiDegTor. (line 6") ("multidimensional_knapsack" . "multidimensional_knapsack") ("multigrading, multidegree, multiweights, multigraded-homogeneous, integral linear algebra" . "multigrading_lib") ("multigrading.lib" . "multigrading_lib. (line 9") ("multigrading_lib" . "multigrading_lib. (line 9") ("multiplicities, sequence of" . "invariants. (line 47") ("multiplicity sequence" . "multsequence. (line 57") ("MultiplicitySequence" . "MultiplicitySequence") ("multiplylist" . "multiplylist. (line 6") ("multivariate equations" . "ffsolve_lib. (line 15") ("multRat" . "multRat. (line 6") ("multrow" . "multrow. (line 6") ("multseq2charexp" . "multseq2charexp. (line 6") ("multsequence" . "multsequence. (line 6") ("MVComplex" . "MVComplex. (line 6") ("naccache_stern_decryption" . "naccache_stern_decryption") ("naccache_stern_encryption" . "naccache_stern_encryption") ("naccache_stern_generation" . "naccache_stern_generation") ("nameof" . "nameof. (line 6") ("names" . "names. (line 6") ("Names" . "Names. (line 6") ("Names in procedures" . "Names in procedures. (line 6") ("Names, indexed" . "Names. (line 6") ("nashmult" . "nashmult. (line 6") ("nblocks" . "system. (line 110") ("nBoundaryLatticePoints" . "nBoundaryLatticePoints") ("nc_algebra" . "nc_algebra. (line 6") ("ncalg.lib" . "ncalg_lib. (line 6") ("ncalg_lib" . "ncalg_lib. (line 6") ("ncalgebra" . "ncalgebra. (line 6") ("ncdecomp.lib" . "ncdecomp_lib. (line 6") ("ncdecomp_lib" . "ncdecomp_lib. (line 6") ("ncdetection" . "ncdetection. (line 6") ("ncExt_R" . "ncExt_R. (line 6") ("ncfactor.lib" . "ncfactor_lib. (line 6") ("ncfactor_lib" . "ncfactor_lib. (line 6") ("ncHom" . "ncHom. (line 6") ("nchomolog.lib" . "nchomolog_lib. (line 6") ("nchomolog_lib" . "nchomolog_lib. (line 6") ("ncols" . "ncols. (line 6") ("ncones" . "ncones. (line 6") ("ncpreim.lib" . "ncpreim_lib. (line 6") ("ncpreim_lib" . "ncpreim_lib. (line 6") ("ncRelations" . "ncRelations. (line 6") ("nctools.lib" . "nctools_lib. (line 6") ("nctools_lib" . "nctools_lib. (line 6") ("ndcond" . "ndcond. (line 6") ("negatedCone" . "negatedCone. (line 6") ("negative degree lexicographical ordering" . "Local orderings. (line 25") ("negative degree reverse lexicographical ordering" . "Local orderings") ("negative lexicographical ordering" . "Local orderings. (line 11") ("negativedivisor" . "negativedivisor. (line 6") ("negativeformaldivisor" . "negativeformaldivisor") ("net access" . "Command line options") ("New libraries depending on Singular 4" . "Notes for Singular users") ("New orderings for modules" . "Notes for Singular users") ("newline" . "string. (line 6") ("news" . "News and changes. (line 6") ("newstruct" . "polybori_lib. (line 94") ("newTest" . "newTest. (line 6") ("Newton non-degenerate" . "is_NND. (line 19") ("Newton polygon" . "is_NND. (line 19") ("Newton polytope" . "polymake_lib. (line 83") ("newtonDiag" . "newtonDiag. (line 6") ("newtonpoly" . "newtonpoly. (line 6") ("newtonPolytope" . "newtonPolytope. (line 6") ("newtonPolytopeLP" . "newtonPolytopeLP. (line 6") ("newtonPolytopeP" . "newtonPolytopeP. (line 6") ("NF" . "reduce (plural). (line 6") ("nf_icis" . "nf_icis. (line 6") ("nfmodStd" . "nfmodStd. (line 6") ("nfmodstd.lib" . "nfmodstd_lib. (line 6") ("nfmodstd_lib" . "nfmodstd_lib. (line 6") ("NFMora" . "NFMora. (line 6") ("nHilbertBasis" . "nHilbertBasis. (line 6") ("nilpotent Lie algebras" . "orbitparam_lib. (line 49") ("nInteriorLatticePoints" . "nInteriorLatticePoints") ("nLatticePoints" . "nLatticePoints. (line 6") ("nmaxcones" . "nmaxcones. (line 6") ("noether" . "noether. (line 6") ("noether.lib" . "noether_lib. (line 6") ("noether_lib" . "noether_lib. (line 6") ("noetherNormal" . "noetherNormal. (line 6") ("NoetherPosition" . "NoetherPosition. (line 6") ("Non-commutative algebra" . "Non-commutative algebra") ("Non-commutative libraries" . "Non-commutative libraries") ("Non-commutative LIBs" . "Non-commutative libraries") ("Non-commutative subsystem" . "Non-commutative subsystem") ("non-english special characters" . "Limitations. (line 53") ("none, option" . "option. (line 49") ("Nonhyp" . "Nonhyp. (line 6") ("nonMonomials" . "nonMonomials. (line 6") ("nonZeroEntry" . "nonZeroEntry. (line 6") ("norm" . "norm. (line 6") ("normal" . "normal. (line 6") ("Normal form" . "Standard bases. (line 18") ("normal.lib" . "normal_lib. (line 6") ("normal_lib" . "normal_lib. (line 6") ("normalC" . "normalC. (line 6") ("normalFan" . "normalFan(polymake). (line 6") ("normalFanL" . "normalFanL. (line 6") ("normalForm" . "normalForm. (line 6") ("normalform" . "normalform. (line 6") ("normalI" . "normalI. (line 6") ("normaliz" . "normaliz. (line 6") ("normaliz.lib" . "normaliz_lib. (line 6") ("normaliz_lib" . "normaliz_lib. (line 6") ("normalization" . "normaliz_lib. (line 52") ("Normalization" . "Normalization. (line 6") ("normalization." . "adjointIdeal. (line 50") ("normalize" . "normalize. (line 6") ("normalP" . "normalP. (line 6") ("normalToricRing" . "normalToricRing. (line 6") ("normalToricRingFromBinomials" . "normalToricRingFromBinomials") ("norTest" . "norTest. (line 6") ("not" . "boolean operations. (line 6") ("notBuckets, option" . "option. (line 94") ("Notes for developers" . "Notes for developers") ("Notes for Singular users" . "Notes for Singular users") ("notRegularity, option" . "option. (line 86") ("notSugar, option" . "option. (line 90") ("notWarnSB, option" . "option. (line 196") ("npar" . "npar. (line 6") ("npars" . "npars. (line 6") ("NPos" . "NPos. (line 6") ("NPos_test" . "NPos_test. (line 6") ("nres" . "nres. (line 6") ("nres (plural)" . "nres (plural). (line 6") ("nrows" . "nrows. (line 6") ("nrroots" . "nrroots. (line 6") ("nrRootsDeterm" . "nrRootsDeterm. (line 6") ("nrRootsProbab" . "nrRootsProbab. (line 6") ("nsatiety" . "nsatiety. (line 6") ("nselect" . "nselect. (line 6") ("NSplaces" . "NSplaces. (line 6") ("nt_solve" . "nt_solve. (line 6") ("NTL" . "Preface. (line 6") ("ntsolve.lib" . "ntsolve_lib. (line 6") ("ntsolve_lib" . "ntsolve_lib. (line 6") ("NullCone" . "NullCone. (line 6") ("number" . "varNum. (line 19") ("number declarations" . "number declarations. (line 6") ("number expressions" . "number expressions. (line 6") ("number operations" . "number operations. (line 6") ("number related functions" . "number related functions") ("number_e" . "number_e. (line 6") ("number_pi" . "number_pi. (line 6") ("numberOfConesOfDimension" . "numberOfConesOfDimension") ("numerAlg.lib" . "numerAlg_lib. (line 13") ("numerAlg_lib" . "numerAlg_lib. (line 13") ("numerator" . "numerator. (line 6") ("numerDecom.lib" . "numerDecom_lib. (line 13") ("numerDecom_lib" . "numerDecom_lib. (line 13") ("NumIrrDecom" . "NumIrrDecom. (line 6") ("NumLocalDim" . "NumLocalDim. (line 6") ("NumPrimDecom" . "NumPrimDecom. (line 6") ("nvars" . "nvars. (line 6") ("Oaku-Takayama algorithm" . "dmod_lib. (line 108") ("Objects" . "Objects. (line 6") ("oneDimBelongSemigroup" . "oneDimBelongSemigroup") ("online help" . "The online help system") ("open" . "open. (line 6") ("opentex" . "opentex. (line 6") ("operatorBM" . "operatorBM. (line 6") ("operatorModulo" . "operatorModulo. (line 6") ("oppose" . "oppose. (line 6") ("opposite" . "opposite. (line 6") ("opposite polynomial" . "system. (line 121") ("opposite ring" . "system. (line 118") ("option" . "option. (line 6") ("option(warn)" . "option(warn). (line 6") ("optionIsSet" . "optionIsSet. (line 6") ("or" . "Evaluation of logical expressions") ("orbit" . "maxZeros. (line 33") ("orbit_variety" . "orbit_variety. (line 6") ("orbitCones" . "orbitCones. (line 6") ("orbitparam.lib" . "orbitparam_lib. (line 6") ("orbitparam_lib" . "orbitparam_lib. (line 6") ("ord" . "ord. (line 6") ("ord_test" . "ord_test. (line 6") ("orderings" . "General definitions for orderings") ("orderings introduction" . "Introduction to orderings") ("orderings, a" . "Extra weight vector. (line 6") ("orderings, global" . "Global orderings. (line 6") ("orderings, local" . "Local orderings. (line 6") ("orderings, M" . "Matrix orderings. (line 6") ("orderings, product" . "Product orderings. (line 6") ("ordstr" . "ordstr. (line 6") ("Orlik-Solomon" . "arrOrlikSolomon. (line 22") ("orthogonalize" . "orthogonalize. (line 6") ("outer" . "outer. (line 6") ("output" . "Input and output. (line 6") ("Output, formatting of" . "Formatting output. (line 6") ("p-adic numbers" . "Coefficient rings. (line 14") ("package" . "package. (line 6") ("package declarations" . "package declarations") ("package related functions" . "package related functions") ("pairset" . "pairset. (line 6") ("par" . "par. (line 6") ("par2varRing" . "par2varRing. (line 6") ("paraConic" . "paraConic. (line 6") ("parallel skeletons" . "parallel_lib. (line 22") ("parallel.lib" . "parallel_lib. (line 6") ("parallel_lib" . "parallel_lib. (line 6") ("parallelization" . "tasks_lib. (line 31") ("Parallelization" . "modular_lib. (line 43") ("parallelTestAND" . "parallelTestAND. (line 6") ("parallelTestOR" . "parallelTestOR. (line 6") ("parallelWaitAll" . "parallelWaitAll. (line 6") ("parallelWaitFirst" . "parallelWaitFirst. (line 6") ("parallelWaitN" . "parallelWaitN. (line 6") ("param" . "param. (line 6") ("Parameter list" . "Parameter list. (line 6") ("parameter, as numbers" . "number. (line 6") ("Parameters" . "Parameters. (line 6") ("parameterSubstitute" . "parameterSubstitute. (line 6") ("parametric annihilator" . "dmod_lib. (line 108") ("parametric annihilator for variety" . "dmodvar_lib. (line 59") ("parametrization" . "param. (line 36") ("Parametrization" . "paraplanecurves_lib. (line 73") ("parametrization" . "parametrizeOrbit. (line 34") ("Parametrization, image." . "testParametrization. (line 26") ("parametrizeOrbit" . "parametrizeOrbit. (line 6") ("paraPlaneCurve" . "paraPlaneCurve. (line 6") ("paraplanecurves.lib" . "paraplanecurves_lib. (line 6") ("paraplanecurves_lib" . "paraplanecurves_lib. (line 6") ("pardeg" . "pardeg. (line 6") ("parstr" . "parstr. (line 6") ("part" . "part. (line 6") ("PartC" . "PartC. (line 6") ("partial_molien" . "partial_molien. (line 6") ("partitions" . "partitions. (line 6") ("PartitionVar" . "PartitionVar. (line 6") ("ParToVar" . "ParToVar. (line 6") ("partOver" . "partOver. (line 6") ("partUnder" . "partUnder. (line 6") ("path integral" . "ellipticcovers_lib. (line 49") ("Path names" . "Notes for Singular users") ("pause" . "pause. (line 6") ("PBW" . "central_lib. (line 19") ("PBW basis" . "G-algebras. (line 9") ("PBW_eqDeg" . "PBW_eqDeg. (line 6") ("PBW_maxDeg" . "PBW_maxDeg. (line 6") ("PBW_maxMonom" . "PBW_maxMonom. (line 6") ("pdivi" . "pdivi. (line 6") ("pdivisorplus" . "pdivisorplus. (line 6") ("PerfectPowerTest" . "PerfectPowerTest. (line 6") ("permcol" . "permcol. (line 6") ("permrow" . "permrow. (line 6") ("permutations" . "permute. (line 22") ("permute" . "permute. (line 6") ("permute_L" . "permute_L. (line 6") ("perron" . "perron. (line 6") ("perron.lib" . "perron_lib. (line 6") ("perron_lib" . "perron_lib. (line 6") ("Perturbation walk" . "pwalk. (line 22") ("PEsolve" . "PEsolve. (line 6") ("pFactor" . "pFactor. (line 6") ("Pfister, Gerhard" . "Preface. (line 144") ("PH_ais" . "PH_ais. (line 6") ("PH_nais" . "PH_nais. (line 6") ("phindex.lib" . "phindex_lib. (line 6") ("phindex_lib" . "phindex_lib. (line 6") ("picksFormula" . "picksFormula. (line 6") ("pid" . "system. (line 132") ("pIntersect" . "pIntersect. (line 6") ("pIntersectSyz" . "pIntersectSyz. (line 6") ("Pipe links" . "Pipe links. (line 6") ("plainInvariants" . "plainInvariants. (line 6") ("plot" . "plot. (line 6") ("plotRot" . "plotRot. (line 6") ("plotRotated" . "plotRotated. (line 6") ("plotRotatedDirect" . "plotRotatedDirect. (line 6") ("plotRotatedList" . "plotRotatedList. (line 6") ("plotRotatedListFromSpecifyList" . "plotRotatedListFromSpecifyList") ("plural" . "hasCommutativeVars. (line 14") ("PLURAL" . "PLURAL. (line 6") ("PLURAL LIBs" . "Non-commutative libraries") ("pmat" . "pmat. (line 6") ("pnormalf" . "pnormalf. (line 6") ("PocklingtonLehmer" . "PocklingtonLehmer. (line 6") ("Poincare polynomial" . "arrPoincare. (line 16") ("pointid.lib" . "pointid_lib. (line 6") ("pointid_lib" . "pointid_lib. (line 6") ("Polar curves" . "Polar curves. (line 6") ("PollardRho" . "PollardRho. (line 6") ("pollTask" . "pollTask. (line 6") ("polSol" . "polSol. (line 6") ("polSolFiniteRank" . "polSolFiniteRank. (line 6") ("poly" . "poly. (line 6") ("poly (plural)" . "poly (plural). (line 6") ("poly declarations" . "poly declarations. (line 6") ("poly declarations (plural)" . "poly declarations (plural)") ("poly expressions" . "poly expressions. (line 6") ("poly expressions (plural)" . "poly expressions (plural)") ("poly operations" . "poly operations. (line 6") ("poly operations (plural)" . "poly operations (plural)") ("poly related functions" . "poly related functions") ("poly related functions (plural)" . "poly related functions (plural)") ("poly.lib" . "poly_lib. (line 6") ("poly2list" . "poly2list. (line 6") ("poly2zdd" . "poly2zdd. (line 6") ("poly_lib" . "poly_lib. (line 6") ("polybori" . "polybori_lib. (line 94") ("Polybori, Boolean Groebner Basis" . "disp_zdd. (line 20") ("PolyBoRi, Boolean Groebner Basis" . "zdd2poly. (line 14") ("PolyBoRi, zero-supressed decision diagram" . "poly2zdd. (line 14") ("polybori.lib" . "polybori_lib. (line 6") ("polybori_lib" . "polybori_lib. (line 6") ("polymake" . "polymake_lib. (line 83") ("polymake.lib" . "polymake_lib. (line 6") ("polymake_lib" . "polymake_lib. (line 6") ("polymake_so" . "polymake_so. (line 6") ("polymakePolytope" . "polymakePolytope. (line 6") ("Polynomial data" . "Polynomial data. (line 6") ("polynomial solutions" . "dmodloc_lib. (line 93") ("polynomial, opposite" . "system. (line 121") ("polytope" . "polymake_lib. (line 83") ("polytope related functions" . "polytope related functions") ("polytopeViaInequalities" . "polytopeViaInequalities") ("polytopeViaPoints" . "polytopeViaPoints. (line 6") ("polyVars" . "polyVars. (line 6") ("pos_def" . "pos_def. (line 6") ("poset" . "arrLattice. (line 17") ("posweight" . "posweight. (line 6") ("Pottier algorithm" . "Pottier. (line 6") ("power" . "power. (line 6") ("power_products" . "power_products. (line 6") ("powerN" . "powerN. (line 6") ("powerpolyX" . "powerpolyX. (line 6") ("powersums" . "powersums. (line 6") ("powerX" . "powerX. (line 6") ("powSumSym" . "powSumSym. (line 6") ("preComp" . "preComp. (line 6") ("Preface" . "Preface. (line 6") ("preimage" . "ncpreim_lib. (line 62") ("preimage (plural)" . "preimage (plural). (line 6") ("preimage under a map between local rings, map between local rings, map between local and global rings" . "preimageLoc") ("preimageLattice" . "preimageLattice. (line 6") ("preimageLoc" . "preimageLoc. (line 6") ("preimageNC" . "preimageNC. (line 6") ("Prep" . "Prep. (line 6") ("prepareAss" . "prepareAss. (line 6") ("prepEmbDiv" . "prepEmbDiv. (line 6") ("prepMat" . "prepMat. (line 6") ("prepRealclassify" . "prepRealclassify. (line 6") ("prepSV" . "prepSV. (line 6") ("presentTree" . "presentTree. (line 6") ("presolve.lib" . "presolve_lib. (line 6") ("presolve_lib" . "presolve_lib. (line 6") ("Primary decomposition" . "Primary decomposition") ("primary_char0" . "primary_char0. (line 6") ("primary_char0_no_molien" . "primary_char0_no_molien") ("primary_char0_no_molien_random" . "primary_char0_no_molien_random") ("primary_char0_random" . "primary_char0_random") ("primary_charp" . "primary_charp. (line 6") ("primary_charp_no_molien" . "primary_charp_no_molien") ("primary_charp_no_molien_random" . "primary_charp_no_molien_random") ("primary_charp_random" . "primary_charp_random") ("primary_charp_without" . "primary_charp_without") ("primary_charp_without_random" . "primary_charp_without_random") ("primary_invariants" . "primary_invariants. (line 6") ("primary_invariants_random" . "primary_invariants_random") ("primdec.lib" . "primdec_lib. (line 6") ("primdec_lib" . "primdec_lib. (line 6") ("PrimdecA" . "PrimdecA. (line 6") ("PrimdecB" . "PrimdecB. (line 6") ("primdecGTZ" . "primdecGTZ. (line 6") ("primdecGTZE" . "primdecGTZE. (line 6") ("primdecint.lib" . "primdecint_lib. (line 6") ("primdecint_lib" . "primdecint_lib. (line 6") ("primdecMon" . "primdecMon. (line 6") ("primdecSY" . "primdecSY. (line 6") ("primdecSYE" . "primdecSYE. (line 6") ("primdecZ" . "primdecZ. (line 6") ("primdecZM" . "primdecZM. (line 6") ("prime" . "prime. (line 6") ("primeClosure" . "primeClosure. (line 6") ("primecoeffs" . "primecoeffs. (line 6") ("primefactors" . "primefactors. (line 6") ("primes" . "primes. (line 6") ("primitiv.lib" . "primitiv_lib. (line 6") ("primitiv_lib" . "primitiv_lib. (line 6") ("primitive" . "primitive. (line 6") ("primitive element" . "primitive. (line 34") ("primitive_extra" . "primitive_extra. (line 6") ("primitiveSpan" . "primitiveSpan. (line 6") ("primL" . "primL. (line 6") ("primList" . "primList. (line 6") ("primparam" . "primparam. (line 6") ("primRoot" . "primRoot. (line 6") ("primTest" . "primTest. (line 6") ("principal intersection" . "bfun_lib. (line 68") ("print" . "arrPrintMatrix. (line 17") ("printf" . "printf. (line 6") ("printGraph" . "printGraph. (line 6") ("printGroup" . "printGroup. (line 6") ("printlevel" . "printlevel. (line 6") ("printMoebius" . "printMoebius. (line 6") ("printTask" . "printTask. (line 6") ("proc" . "proc. (line 6") ("proc declaration" . "proc declaration. (line 6") ("proc expression" . "proc expression. (line 6") ("Procedure definition" . "Procedure definition") ("procedure, ASCII help" . "mdouble. (line 19") ("procedure, ASCII/Texinfo help" . "msum. (line 32") ("procedure, texinfo help" . "mtriple. (line 21") ("Procedure-specific commands" . "Procedure-specific commands") ("Procedures" . "Procedures. (line 6") ("Procedures and libraries" . "Writing procedures and libraries") ("Procedures in a library" . "Procedures in a library") ("procedures, help string" . "Help string. (line 6") ("procedures, static" . "Procedure definition") ("procs with different argument types" . "procs with different argument types") ("prodcrit" . "prodcrit. (line 6") ("product" . "product. (line 6") ("Product orderings" . "Product orderings. (line 6") ("productgroup" . "productgroup. (line 6") ("Programming" . "Programming. (line 6") ("progress watch" . "option. (line 101") ("projective dimension" . "purityfiltration_lib") ("projective limes" . "Coefficient rings. (line 14") ("projectiveDimension" . "projectiveDimension. (line 6") ("projectLattice" . "projectLattice. (line 6") ("prompt" . "The SINGULAR prompt. (line 6") ("prompt, option" . "option. (line 200") ("propagator" . "propagator. (line 6") ("prot, option" . "option. (line 101") ("protocol of computations" . "option. (line 101") ("proximitymatrix" . "proximitymatrix. (line 6") ("prune" . "prune. (line 6") ("prwalk" . "prwalk. (line 6") ("psigncnd" . "psigncnd. (line 6") ("PtoCrep" . "PtoCrep. (line 6") ("Puiseux expansion" . "hnoether_lib. (line 49") ("Puiseux pairs" . "invariants. (line 47") ("puiseux2generators" . "puiseux2generators. (line 6") ("puiseuxExpansion" . "puiseuxExpansion. (line 6") ("pure tensor" . "bimodules_lib. (line 71") ("purelist" . "purelist. (line 6") ("purity" . "purityfiltration_lib") ("purityFiltration" . "purityFiltration. (line 6") ("purityfiltration.lib" . "purityfiltration_lib") ("purityfiltration_lib" . "purityfiltration_lib") ("purityTriang" . "purityTriang. (line 6") ("pushForward" . "pushForward. (line 6") ("pwalk" . "pwalk. (line 6") ("pyobject" . "polybori_lib. (line 94") ("pyobject declarations" . "pyobject declarations") ("pyobject expressions" . "pyobject expressions") ("pyobject operations" . "pyobject operations. (line 6") ("pyobject related functions" . "pyobject related functions") ("pyramid" . "pyramid. (line 6") ("python_eval" . "python_eval. (line 6") ("python_import" . "python_import. (line 6") ("python_run" . "python_run. (line 6") ("qbase" . "qbase. (line 6") ("qepcad" . "qepcad. (line 6") ("qepcadsystem" . "qepcadsystem. (line 6") ("qhmatrix" . "qhmatrix. (line 6") ("qhmoduli.lib" . "qhmoduli_lib. (line 6") ("qhmoduli_lib" . "qhmoduli_lib. (line 6") ("qhspectrum" . "qhspectrum. (line 6") ("qhweight" . "qhweight. (line 6") ("qmatrix.lib" . "qmatrix_lib. (line 6") ("qmatrix_lib" . "qmatrix_lib. (line 6") ("qminor" . "qminor. (line 6") ("qrds" . "qrds. (line 6") ("qring" . "Miscellaneous oddities") ("qring (plural)" . "qring (plural). (line 6") ("qring declaration" . "qring declaration. (line 6") ("qring declaration (plural)" . "qring declaration (plural)") ("qring related functions (plural)" . "qring related functions (plural)") ("qring ring ideal 'factor ring'" . "isQuotientRing. (line 14") ("qringNF, option" . "option. (line 108") ("qslimgb" . "qslimgb. (line 6") ("Qso3Casimir" . "Qso3Casimir. (line 6") ("quadraticSieve" . "quadraticSieve. (line 6") ("quantMat" . "quantMat. (line 6") ("quickclass" . "quickclass. (line 6") ("quit" . "quit. (line 6") ("quote" . "quote. (line 6") ("Quotient" . "Quotient. (line 6") ("quotient" . "quotient. (line 6") ("quotient (plural)" . "quotient (plural). (line 6") ("QuotientEquations" . "QuotientEquations. (line 6") ("quotientLatticeBasis" . "quotientLatticeBasis") ("quotientMain" . "quotientMain. (line 6") ("quotientMon" . "quotientMon. (line 6") ("quotients" . "gitfan_lib. (line 24") ("rad_con" . "rad_con. (line 6") ("radical" . "radical. (line 6") ("radicalEHV" . "radicalEHV. (line 6") ("radicalMemberShip" . "radicalMemberShip. (line 6") ("radicalMon" . "radicalMon. (line 6") ("radicalZ" . "radicalZ. (line 6") ("randcharpoly" . "randcharpoly. (line 6") ("randlinpoly" . "randlinpoly. (line 6") ("random" . "arrRandomCentral. (line 16") ("random number generator, seed" . "system. (line 135") ("random.lib" . "random_lib. (line 6") ("random_lib" . "random_lib. (line 6") ("randomBinomial" . "randomBinomial. (line 6") ("randomCheck" . "randomCheck. (line 6") ("randomid" . "randomid. (line 6") ("randomLast" . "randomLast. (line 6") ("randommat" . "randommat. (line 6") ("randomPoint" . "randomPoint. (line 6") ("randomPolyInT" . "randomPolyInT. (line 6") ("rank" . "rank. (line 6") ("ratgb.lib" . "ratgb_lib. (line 6") ("ratgb_lib" . "ratgb_lib. (line 6") ("Rational curves" . "paraplanecurves_lib. (line 73") ("rational curves, rational parametrization of rational curves." . "paraPlaneCurve") ("rational normal curve, projection." . "rncItProjEven. (line 30") ("rational solutions" . "dmodloc_lib. (line 93") ("rational univariate projection" . "randcharpoly. (line 24") ("rationalPointConic" . "rationalPointConic. (line 6") ("ratSol" . "ratSol. (line 6") ("ratstd" . "ratstd. (line 6") ("rays" . "rays. (line 6") ("re2squ" . "re2squ. (line 6") ("read" . "read. (line 6") ("reading, option" . "option. (line 203") ("readline" . "Preface. (line 6") ("readNmzData" . "readNmzData. (line 6") ("real" . "Rings and orderings. (line 26") ("real roots, univariate polynomial" . "rootsur_lib. (line 50") ("real roots, univariate projection" . "rootsmr_lib. (line 48") ("real roots,sign conditions" . "signcond_lib. (line 31") ("realclassify" . "realclassify. (line 6") ("realclassify.lib" . "realclassify_lib. (line 6") ("realclassify_lib" . "realclassify_lib. (line 6") ("realizationDim" . "realizationDim. (line 6") ("realizationDimPoly" . "realizationDimPoly. (line 6") ("realizationMatroids.lib" . "realizationMatroids_lib") ("realizationMatroids_lib" . "realizationMatroids_lib") ("realmorsesplit" . "realmorsesplit. (line 6") ("realpoly" . "realpoly. (line 6") ("realrad" . "realrad. (line 6") ("realrad.lib" . "realrad_lib. (line 6") ("realrad_lib" . "realrad_lib. (line 6") ("realzero" . "realzero. (line 6") ("recursive_boolean_poly" . "recursive_boolean_poly") ("recursive_from_boolean_poly" . "recursive_from_boolean_poly") ("redefine, option" . "option. (line 206") ("redSB, option" . "option. (line 111") ("redTail, option" . "option. (line 117") ("redThrough, option" . "option. (line 126") ("reduce" . "central_lib. (line 19") ("reduce (plural)" . "reduce (plural). (line 6") ("reduced standard basis" . "option. (line 111") ("reduction" . "reduction. (line 6") ("ReesAlgebra" . "ReesAlgebra. (line 6") ("reesclos.lib" . "reesclos_lib. (line 6") ("reesclos_lib" . "reesclos_lib. (line 6") ("reference" . "countedref. (line 6") ("reference declarations" . "reference declarations") ("reference expressions" . "reference expressions") ("reference operations" . "reference and shared operations") ("reference related functions" . "reference and shared related functions") ("References" . "References. (line 6") ("References (plural)" . "References (plural). (line 6") ("regCM" . "regCM. (line 6") ("regIdeal" . "regIdeal. (line 6") ("regMonCurve" . "regMonCurve. (line 6") ("regularity" . "Syzygies and resolutions") ("reiffen" . "reiffen. (line 6") ("ReJunkUseHomo" . "ReJunkUseHomo. (line 6") ("rel_orbit_variety" . "rel_orbit_variety. (line 6") ("relations" . "perron_lib. (line 21") ("relative_orbit_variety" . "relative_orbit_variety") ("relativeInteriorPoint" . "relativeInteriorPoint") ("Release Notes" . "Release Notes. (line 6") ("relweight" . "relweight. (line 6") ("remainder" . "remainder. (line 6") ("remainderMain" . "remainderMain. (line 6") ("removeCone" . "removeCone. (line 6") ("removepower" . "removepower. (line 6") ("repart" . "repart. (line 6") ("replace" . "replace. (line 6") ("representation, math objects" . "Representation of mathematical objects") ("res" . "res. (line 6") ("resbinomial.lib" . "resbinomial_lib. (line 15") ("resbinomial_lib" . "resbinomial_lib. (line 15") ("reservedName" . "reservedName. (line 6") ("resfunction" . "resfunction. (line 6") ("resgraph.lib" . "resgraph_lib. (line 6") ("resgraph_lib" . "resgraph_lib. (line 6") ("resjung.lib" . "resjung_lib. (line 6") ("resjung_lib" . "resjung_lib. (line 6") ("reslist" . "reslist. (line 6") ("resolution" . "purityfiltration_lib") ("Resolution" . "Resolution. (line 6") ("resolution (plural)" . "resolution (plural). (line 6") ("resolution declarations" . "resolution declarations") ("resolution declarations (plural)" . "resolution declarations (plural)") ("resolution expressions" . "resolution expressions") ("resolution expressions (plural)" . "resolution expressions (plural)") ("resolution graph" . "alexpoly_lib. (line 40") ("Resolution of singularities" . "Resolution of singularities") ("resolution related functions" . "resolution related functions") ("resolution related functions (plural)" . "resolution related functions (plural)") ("resolution, computation of" . "res. (line 8") ("Resolution, free" . "Free resolution. (line 6") ("resolution, hilbert-driven" . "hres. (line 6") ("resolution, La Scala's method" . "lres. (line 6") ("resolutiongraph" . "resolutiongraph. (line 6") ("resolutionInLocalization" . "resolutionInLocalization") ("resolve" . "resolve. (line 6") ("resolve.lib" . "resolve_lib. (line 6") ("resolve_lib" . "resolve_lib. (line 6") ("resources.lib" . "resources_lib. (line 6") ("resources_lib" . "resources_lib. (line 6") ("ResTree" . "ResTree. (line 6") ("restriction" . "multarrMultRestrict. (line 28") ("restriction of" . "dmodapp_lib. (line 104") ("restrictionIdeal" . "restrictionIdeal. (line 6") ("restrictionModule" . "restrictionModule. (line 6") ("resultant" . "resultant. (line 6") ("reszeta.lib" . "reszeta_lib. (line 6") ("reszeta_lib" . "reszeta_lib. (line 6") ("return" . "return. (line 6") ("return type of procedures" . "Return type of procedures") ("returnSB, option" . "option. (line 55") ("reverse" . "reverse. (line 6") ("reverse lexicographical ordering" . "Global orderings. (line 14") ("reynolds_molien" . "reynolds_molien. (line 6") ("ReynoldsImage" . "ReynoldsImage. (line 6") ("ReynoldsOperator" . "ReynoldsOperator. (line 6") ("rho" . "rho. (line 6") ("rHRR" . "rHRR. (line 6") ("RiemannRochBN" . "RiemannRochBN. (line 6") ("RiemannRochHess" . "RiemannRochHess. (line 6") ("Right Groebner bases and syzygies" . "Right Groebner bases and syzygies") ("rightInverse" . "rightInverse. (line 6") ("rightKernel" . "rightKernel. (line 6") ("rightModulo" . "rightModulo. (line 6") ("rightNF" . "rightNF. (line 6") ("rightNFWeyl" . "rightNFWeyl. (line 6") ("rightStd" . "rightStd. (line 6") ("ring" . "ring. (line 6") ("ring (plural)" . "ring (plural). (line 6") ("ring coefficients" . "hasAlgExtensionCoefficient") ("ring declarations" . "ring declarations. (line 6") ("ring declarations (plural)" . "ring declarations (plural)") ("ring operations" . "ring operations. (line 6") ("ring operations (plural)" . "ring operations (plural)") ("ring related functions" . "ring related functions") ("ring related functions (plural)" . "ring related functions (plural)") ("ring, opposite" . "system. (line 118") ("Ring-dependent options" . "Notes for Singular users") ("ring.lib" . "ring_lib. (line 6") ("ring_cf" . "attrib. (line 69") ("ring_lib" . "ring_lib. (line 6") ("ring_variable" . "arrLastVar. (line 18") ("ringlist" . "ringlist. (line 6") ("ringlist (plural)" . "ringlist (plural). (line 6") ("Rings and orderings" . "Rings and orderings. (line 6") ("Rings and standard bases" . "Rings and standard bases") ("ringtensor" . "ringtensor. (line 6") ("ringweights" . "ringweights. (line 6") ("rinvar.lib" . "rinvar_lib. (line 6") ("rinvar_lib" . "rinvar_lib. (line 6") ("rm_unitcol" . "rm_unitcol. (line 6") ("rm_unitrow" . "rm_unitrow. (line 6") ("rMacaulay" . "rMacaulay. (line 6") ("rmNmzFiles" . "rmNmzFiles. (line 6") ("rmx" . "rmx. (line 6") ("rncAntiCanonicalMap" . "rncAntiCanonicalMap. (line 6") ("rncItProjEven" . "rncItProjEven. (line 6") ("rncItProjOdd" . "rncItProjOdd. (line 6") ("root of Bernstein-Sato polynomial" . "dmod_lib. (line 108") ("rootofUnity" . "rootofUnity. (line 6") ("roots" . "roots. (line 6") ("rootsMain" . "rootsMain. (line 6") ("rootsModp" . "rootsModp. (line 6") ("rootsmr.lib" . "rootsmr_lib. (line 6") ("rootsmr_lib" . "rootsmr_lib. (line 6") ("rootsur.lib" . "rootsur_lib. (line 6") ("rootsur_lib" . "rootsur_lib. (line 6") ("round" . "round. (line 6") ("rowred" . "rowred. (line 6") ("rp, global ordering" . "Global orderings. (line 14") ("rswalk" . "rswalk. (line 6") ("rtimer" . "rtimer. (line 6") ("Running SINGULAR under Emacs" . "Running SINGULAR under Emacs") ("rvalue" . "No rvalue of increments and assignments") ("rvar" . "rvar. (line 6") ("rwalk" . "rwalk. (line 6") ("rwalk.lib" . "rwalk_lib. (line 6") ("rwalk_lib" . "rwalk_lib. (line 6") ("s_res" . "s_res. (line 6") ("sa_poly_reduce" . "sa_poly_reduce. (line 6") ("sa_reduce" . "sa_reduce. (line 6") ("sagbi" . "sagbi. (line 6") ("sagbi.lib" . "sagbi_lib. (line 6") ("sagbi_lib" . "sagbi_lib. (line 6") ("sagbiPart" . "sagbiPart. (line 6") ("sagbiReduce" . "sagbiReduce. (line 6") ("sagbiSPoly" . "sagbiSPoly. (line 6") ("salida" . "salida. (line 6") ("sameComponent" . "sameComponent. (line 6") ("sameQ" . "sameQ. (line 6") ("Sannfs" . "Sannfs. (line 6") ("SannfsBFCT" . "SannfsBFCT. (line 6") ("Sannfslog" . "Sannfslog. (line 6") ("SannfsVar" . "SannfsVar. (line 6") ("sat" . "sat. (line 6") ("satiety" . "satiety. (line 6") ("Saturation" . "Saturation. (line 6") ("sba" . "sba. (line 6") ("SCA" . "Graded commutative algebras (SCA)") ("scalarProd" . "scalarProd. (line 6") ("scheme" . "scheme. (line 6") ("Scho\"nemann, Hans" . "Preface. (line 144") ("Schoof" . "Schoof. (line 6") ("Schreyer ordering" . "schreyer_lib. (line 15") ("Schreyer resolution" . "schreyer_lib. (line 15") ("schreyer.lib" . "schreyer_lib. (line 6") ("schreyer_lib" . "schreyer_lib. (line 6") ("SchurCh" . "SchurCh. (line 6") ("SchurS" . "SchurS. (line 6") ("Scontinue" . "Scontinue. (line 6") ("SDB breakpoint" . "Source code debugger") ("SDB debugger" . "Source code debugger") ("sdb, source code debugger" . "Source code debugger") ("SDLoc" . "SDLoc. (line 6") ("secondary fan" . "polymake_lib. (line 83") ("secondary polytope" . "polymake_lib. (line 83") ("secondary_and_irreducibles_no_molien" . "secondary_and_irreducibles_no_molien") ("secondary_char0" . "secondary_char0. (line 6") ("secondary_charp" . "secondary_charp. (line 6") ("secondary_no_molien" . "secondary_no_molien. (line 6") ("secondary_not_cohen_macaulay" . "secondary_not_cohen_macaulay") ("secondaryFan" . "secondaryFan. (line 6") ("secondaryPolytope" . "secondaryPolytope. (line 6") ("segre" . "segre. (line 6") ("select" . "select. (line 6") ("select1" . "select1. (line 6") ("semaphore" . "semaphore. (line 6") ("semaphores" . "resources_lib. (line 26") ("semiCMcod2" . "semiCMcod2. (line 6") ("semidiv" . "semidiv. (line 6") ("Semigroup" . "Semigroup. (line 6") ("semigroup" . "charexp2generators. (line 19") ("semigroup of values" . "invariants. (line 47") ("semigroupGenerator" . "semigroupGenerator. (line 6") ("sep" . "sep. (line 6") ("separateHNE" . "separateHNE. (line 6") ("separator" . "separator. (line 6") ("serreRelations" . "serreRelations. (line 6") ("set" . "arrSet. (line 17") ("set_is_injective" . "set_is_injective. (line 6") ("setBaseMultigrading" . "setBaseMultigrading. (line 6") ("setcores" . "setcores. (line 6") ("setenv" . "system. (line 157") ("setinitials" . "setinitials. (line 6") ("setLetterplaceAttributes" . "setLetterplaceAttributes") ("setLinearForms" . "setLinearForms. (line 6") ("setModuleGrading" . "setModuleGrading. (line 6") ("setMultiplicity" . "setMultiplicity. (line 6") ("setNmzDataPath" . "setNmzDataPath. (line 6") ("setNmzExecPath" . "setNmzExecPath. (line 6") ("setNmzFilename" . "setNmzFilename. (line 6") ("setNmzOption" . "setNmzOption. (line 6") ("setring" . "setring. (line 6") ("Setting up a G-algebra" . "G-algebras. (line 51") ("sh" . "system. (line 162") ("ShanksMestre" . "ShanksMestre. (line 6") ("shared" . "countedref. (line 6") ("shared declarations" . "shared declarations. (line 6") ("shared expressions" . "shared expressions. (line 6") ("shared operations" . "reference and shared operations") ("shared related functions" . "reference and shared related functions") ("sheaf cohomology" . "sheafcoh_lib. (line 32") ("sheafCoh" . "sheafCoh. (line 6") ("sheafcoh.lib" . "sheafcoh_lib. (line 6") ("sheafcoh_lib" . "sheafcoh_lib. (line 6") ("sheafCohBGG" . "sheafCohBGG. (line 6") ("sheafCohBGG2" . "sheafCohBGG2. (line 6") ("shiftPoly" . "shiftPoly. (line 6") ("short" . "short. (line 6") ("show" . "show. (line 6") ("showBO" . "showBO. (line 6") ("showDataTypes" . "showDataTypes. (line 6") ("showgrades" . "showgrades. (line 6") ("showNmzOptions" . "showNmzOptions. (line 6") ("showNuminvs" . "showNuminvs. (line 6") ("showrecursive" . "showrecursive. (line 6") ("sickle" . "sickle. (line 6") ("signatureBrieskorn" . "signatureBrieskorn. (line 6") ("signatureL" . "signatureL. (line 6") ("signatureLqf" . "signatureLqf. (line 6") ("signatureNemethi" . "signatureNemethi. (line 6") ("signaturePuiseux" . "signaturePuiseux. (line 6") ("signcnd" . "signcnd. (line 6") ("signcond.lib" . "signcond_lib. (line 6") ("signcond_lib" . "signcond_lib. (line 6") ("simplesolver" . "simplesolver. (line 6") ("simplex" . "simplex. (line 6") ("simplexOut" . "simplexOut. (line 6") ("simplify" . "simplify. (line 6") ("SimplifyIdeal" . "SimplifyIdeal. (line 6") ("simplifyRat" . "simplifyRat. (line 6") ("sing.lib" . "sing_lib. (line 6") ("sing4ti2.lib" . "sing4ti2_lib. (line 6") ("sing4ti2_lib" . "sing4ti2_lib. (line 6") ("sing_lib" . "sing_lib. (line 6") ("Singular" . "system. (line 170") ("Singular 3 and Singular 4" . "Singular 3 and Singular 4") ("SINGULAR libraries" . "SINGULAR libraries. (line 6") ("singular locus of D-module" . "dmodloc_lib. (line 93") ("Singular, customization of Emacs user interface" . "Customization of the Emacs interface") ("Singular, demo mode" . "Demo mode. (line 6") ("Singular, editing input files with Emacs" . "Editing SINGULAR input files with Emacs") ("Singular, important commands of Emacs interface" . "Top 20 Emacs commands") ("Singular, running within Emacs" . "Running SINGULAR under Emacs") ("Singular2bertini" . "Singular2bertini. (line 6") ("SINGULARHIST" . "Editing input. (line 6") ("singularities" . "spectrumnd. (line 26") ("Singularities" . "Singularities. (line 6") ("singularities, resolution of" . "Resolution of singularities") ("singularity" . "singularity. (line 6") ("Singularity Theory" . "Singularity Theory. (line 6") ("SingularLib" . "system. (line 174") ("singularrc" . "Startup sequence. (line 10") ("size" . "Miscellaneous oddities") ("Skeletons for parallelization" . "modular_lib. (line 43") ("skewmat" . "skewmat. (line 6") ("sleep" . "status. (line 6") ("slimgb" . "slim Groebner bases. (line 6") ("slimgb (plural)" . "slimgb (plural). (line 6") ("slocus" . "slocus. (line 6") ("smith" . "smith. (line 6") ("Smith form" . "jacobson_lib. (line 58") ("Smith normal form" . "jacobson_lib. (line 58") ("smithNormalForm" . "smithNormalForm. (line 6") ("SolowayStrassen" . "SolowayStrassen. (line 6") ("solutionsMod2" . "solutionsMod2. (line 6") ("solve" . "solve. (line 6") ("solve a linear equation system A*x = b via the LU-decomposition of A" . "lusolve") ("solve.lib" . "solve_lib. (line 6") ("solve_IP" . "solve_IP. (line 6") ("solve_lib" . "solve_lib. (line 6") ("solvelinearpart" . "solvelinearpart. (line 6") ("solveTInitialFormPar" . "solveTInitialFormPar") ("Solving systems of polynomial equations" . "Solving systems of polynomial equations") ("sort" . "sort. (line 6") ("sortandmap" . "sortandmap. (line 6") ("sortier" . "sortier. (line 6") ("sortIntvec" . "sortIntvec. (line 6") ("sortvars" . "sortvars. (line 6") ("sortvec" . "sortvec. (line 6") ("Source code debugger, invocation" . "Command line options") ("source code debugger, sdb" . "Source code debugger") ("Space curve singularities, branches of" . "Branches of space curve singularities") ("spadd" . "spadd. (line 6") ("span" . "span. (line 6") ("sparseHomogIdeal" . "sparseHomogIdeal. (line 6") ("sparseid" . "sparseid. (line 6") ("sparsemat" . "sparsemat. (line 6") ("sparsematrix" . "sparsematrix. (line 6") ("sparsepoly" . "sparsepoly. (line 6") ("sparsetriag" . "sparsetriag. (line 6") ("spcurve.lib" . "spcurve_lib. (line 6") ("spcurve_lib" . "spcurve_lib. (line 6") ("Special characters" . "Special characters. (line 6") ("special characters, non-english" . "Limitations. (line 53") ("spectral pairs" . "goodBasis. (line 22") ("spectralNeg" . "spectralNeg. (line 6") ("spectrum" . "spectrumnd. (line 26") ("spectrum.lib" . "spectrum_lib. (line 6") ("spectrum_lib" . "spectrum_lib. (line 6") ("spectrumnd" . "spectrumnd. (line 6") ("spgamma" . "spgamma. (line 6") ("spgeomgenus" . "spgeomgenus. (line 6") ("spissemicont" . "spissemicont. (line 6") ("split" . "split. (line 6") ("splitPolygon" . "splitPolygon. (line 6") ("splitring" . "splitring. (line 6") ("splitting" . "splitting. (line 6") ("Splitting lemma" . "realmorsesplit. (line 22") ("spmilnor" . "spmilnor. (line 6") ("spmul" . "spmul. (line 6") ("spnf" . "spnf. (line 6") ("spoly" . "spoly. (line 6") ("sppairs" . "sppairs. (line 6") ("sppnf" . "sppnf. (line 6") ("sppprint" . "sppprint. (line 6") ("spprint" . "spprint. (line 6") ("sprintf" . "sprintf. (line 6") ("spsemicont" . "spsemicont. (line 6") ("spsub" . "spsub. (line 6") ("sqfrNorm" . "sqfrNorm. (line 6") ("sqfrNormMain" . "sqfrNormMain. (line 6") ("sqr" . "sqr. (line 6") ("sqrfree" . "sqrfree. (line 6") ("squarefree" . "squarefree. (line 6") ("squareRoot" . "squareRoot. (line 6") ("Sres" . "Sres. (line 6") ("sres" . "sres. (line 6") ("ssi" . "Parallelization with ssi links") ("Ssi file links" . "Ssi file links. (line 6") ("Ssi links" . "Ssi links. (line 6") ("Ssi tcp links" . "Ssi tcp links. (line 6") ("Ssyz" . "Ssyz. (line 6") ("StabEqn" . "StabEqn. (line 6") ("StabEqnId" . "StabEqnId. (line 6") ("StabOrder" . "StabOrder. (line 6") ("staircase" . "staircase. (line 6") ("standard" . "standard. (line 6") ("Standard bases" . "Standard bases. (line 6") ("Standard Bases" . "Computing Groebner and Standard Bases") ("standard.lib" . "standard_lib. (line 11") ("standard_lib" . "standard_lib. (line 11") ("startNmz" . "startNmz. (line 6") ("StartOrderingV" . "StartOrderingV. (line 6") ("startTasks" . "startTasks. (line 6") ("Startup sequence" . "Startup sequence. (line 6") ("static procedures" . "Procedure definition") ("status" . "status. (line 6") ("std" . "groebner and std. (line 6") ("std (plural)" . "std (plural). (line 6") ("stdfglm" . "stdfglm. (line 6") ("stdhilb" . "stdhilb. (line 6") ("stopTask" . "stopTask. (line 6") ("stratify" . "stratify. (line 6") ("stratify.lib" . "stratify_lib. (line 6") ("stratify_lib" . "stratify_lib. (line 6") ("string" . "Miscellaneous oddities") ("string declarations" . "string declarations. (line 6") ("string expressions" . "string expressions. (line 6") ("string operations" . "string operations. (line 6") ("string related functions" . "string related functions") ("string type cast" . "string type cast. (line 6") ("StringF" . "StringF. (line 6") ("stripHNE" . "stripHNE. (line 6") ("sturm" . "sturm. (line 6") ("sturmha" . "sturmha. (line 6") ("sturmhaseq" . "sturmhaseq. (line 6") ("sturmquery" . "sturmquery. (line 6") ("sturmseq" . "sturmseq. (line 6") ("submat" . "submat. (line 6") ("subrInterred" . "subrInterred. (line 6") ("subset_sum01" . "subset_sum01. (line 6") ("subset_sum02" . "subset_sum02. (line 6") ("subst" . "subst. (line 6") ("subst (plural)" . "subst (plural). (line 6") ("substitute" . "substitute. (line 6") ("sugarCrit, option" . "option. (line 134") ("sum" . "sum. (line 6") ("sum_of_powers" . "sum_of_powers. (line 6") ("sumlist" . "sumlist. (line 6") ("super-commutative algebras" . "Graded commutative algebras (SCA)") ("super_increasing_knapsack" . "super_increasing_knapsack") ("superCommutative" . "superCommutative. (line 6") ("surf.lib" . "surf_lib. (line 6") ("surf_lib" . "surf_lib. (line 6") ("surfacesignature.lib" . "surfacesignature_lib") ("surfacesignature_lib" . "surfacesignature_lib") ("surfer" . "surfer. (line 6") ("surfex" . "Preface. (line 6") ("surfex.lib" . "surfex_lib. (line 6") ("surfex_lib" . "surfex_lib. (line 6") ("suspend" . "status. (line 6") ("SV-decoding algorithm" . "decodeSV. (line 25") ("SV-decoding algorithm, preprocessing" . "prepSV. (line 51") ("swalk" . "swalk. (line 6") ("swalk.lib" . "swalk_lib. (line 6") ("swalk_lib" . "swalk_lib. (line 6") ("swap" . "arrSwapVar. (line 18") ("switch" . "No case or switch statement") ("sym_gauss" . "sym_gauss. (line 6") ("Symbolic-numerical solving" . "Symbolic-numerical solving") ("SymGroup" . "SymGroup. (line 6") ("symm" . "symm. (line 6") ("symmat" . "symmat. (line 6") ("symmetric basis" . "symmetricBasis. (line 18") ("symmetric power" . "symmetricPower. (line 18") ("symmetricBasis" . "symmetricBasis. (line 6") ("symmetricPower" . "symmetricPower. (line 6") ("symmfunc" . "symmfunc. (line 6") ("symmStd" . "symmStd. (line 6") ("symNsym" . "symNsym. (line 6") ("syModStd" . "syModStd. (line 6") ("symodstd.lib" . "symodstd_lib. (line 6") ("symodstd_lib" . "symodstd_lib. (line 6") ("symsignature" . "symsignature. (line 6") ("syndrome" . "syndrome. (line 6") ("sys_code" . "sys_code. (line 6") ("sysBin" . "sysBin. (line 6") ("sysCRHT" . "sysCRHT. (line 6") ("sysCRHTMindist" . "sysCRHTMindist. (line 6") ("sysFL" . "sysFL. (line 6") ("sysNewton" . "sysNewton. (line 6") ("sysQE" . "sysQE. (line 6") ("system" . "system. (line 6") ("System and Control theory" . "System and Control theory") ("System dependent limitations" . "System dependent limitations") ("System variables" . "System variables. (line 6") ("system, -" . "system. (line 223") ("system, -long_option_name" . "system. (line 226") ("system, -long_option_name=value" . "system. (line 231") ("system, absFact" . "system. (line 26") ("system, blackbox" . "system. (line 32") ("system, bracket" . "system. (line 39") ("system, browsers" . "system. (line 35") ("system, btest" . "system. (line 42") ("system, complexNearZero" . "system. (line 46") ("system, contributors" . "system. (line 49") ("system, cpu" . "system. (line 53") ("system, denom_list" . "system. (line 57") ("system, eigenvals" . "system. (line 62") ("system, env" . "system. (line 66") ("system, freegb" . "system. (line 70") ("system, getenv" . "system. (line 74") ("system, getPrecDigits" . "system. (line 78") ("system, gmsnf" . "system. (line 81") ("system, HC" . "system. (line 84") ("system, hessenberg" . "system. (line 88") ("system, install" . "system. (line 91") ("system, LLL" . "system. (line 97") ("system, nblocks" . "system. (line 110") ("system, newstruct" . "system. (line 115") ("system, opp" . "system. (line 118") ("system, oppose" . "system. (line 121") ("system, pcvBasis" . "system. (line 129") ("system, pcvCV2P" . "system. (line 127") ("system, pcvDim" . "system. (line 128") ("system, pcvLAddL" . "system. (line 124") ("system, pcvMinDeg" . "system. (line 125") ("system, pcvP2CV" . "system. (line 126") ("system, pcvPMulL" . "system. (line 124") ("system, pid" . "system. (line 132") ("system, random" . "system. (line 135") ("system, reserve" . "system. (line 138") ("system, reservedLink" . "system. (line 142") ("system, semaphore" . "system. (line 146") ("system, semic" . "system. (line 152") ("system, setenv" . "system. (line 157") ("system, sh" . "system. (line 162") ("system, shrinktest" . "system. (line 166") ("system, Singular" . "system. (line 170") ("system, SingularLib" . "system. (line 174") ("system, spadd" . "system. (line 178") ("system, spectrum" . "system. (line 183") ("system, spmul" . "system. (line 186") ("system, std_syz" . "system. (line 190") ("system, stest" . "system. (line 194") ("system, tensorModuleMult" . "system. (line 198") ("system, twostd" . "system. (line 201") ("system, uname" . "system. (line 204") ("system, version" . "system. (line 208") ("system, with" . "system. (line 212") ("systemOfParametersOfLocalization" . "systemOfParametersOfLocalization") ("syz" . "syz. (line 6") ("syz (plural)" . "syz (plural). (line 6") ("Syzygies and resolutions" . "Syzygies and resolutions") ("Syzygies and resolutions (plural)" . "Syzygies and resolutions (plural)") ("syzygy" . "schreyer_lib. (line 15") ("T1" . "T1 and T2. (line 6") ("T2" . "T1 and T2. (line 6") ("T_1" . "T_1. (line 6") ("T_12" . "T_12. (line 6") ("T_2" . "T_2. (line 6") ("tab" . "tab. (line 6") ("tail" . "tail. (line 6") ("tame polynomial" . "goodBasis. (line 22") ("tangentcone" . "tangentcone. (line 6") ("tangentGens" . "tangentGens. (line 6") ("task" . "tasks_lib. (line 31") ("tasks.lib" . "tasks_lib. (line 6") ("tasks_lib" . "tasks_lib. (line 6") ("tau_es" . "tau_es. (line 6") ("tau_es2" . "tau_es2. (line 6") ("tdCf" . "tdCf. (line 6") ("tDetropicalise" . "tDetropicalise. (line 6") ("tdFactor" . "tdFactor. (line 6") ("tdProj" . "tdProj. (line 6") ("tdTerms" . "tdTerms. (line 6") ("Teaching" . "Teaching. (line 6") ("teachstd.lib" . "teachstd_lib. (line 6") ("teachstd_lib" . "teachstd_lib. (line 6") ("Template for writing a library" . "template_lib. (line 6") ("template.lib" . "template_lib. (line 128") ("template_lib" . "template_lib. (line 6") ("tensor" . "tensor. (line 6") ("tensorMod" . "tensorMod. (line 6") ("term orderings" . "General definitions for orderings") ("term orderings introduction" . "Introduction to orderings") ("TestGRRes" . "TestGRRes. (line 6") ("TestJMark" . "TestJMark. (line 6") ("testNCfac" . "testNCfac. (line 6") ("testParametrization" . "testParametrization. (line 6") ("testPointConic" . "testPointConic. (line 6") ("testPrimary" . "testPrimary. (line 6") ("testPrimaryE" . "testPrimaryE. (line 6") ("tex" . "tex. (line 6") ("texcoef" . "texcoef. (line 6") ("texdemo" . "texdemo. (line 6") ("texDrawBasic" . "texDrawBasic. (line 6") ("texDrawNewtonSubdivision" . "texDrawNewtonSubdivision") ("texDrawTriangulation" . "texDrawTriangulation") ("texDrawTropical" . "texDrawTropical. (line 6") ("texfactorize" . "texfactorize. (line 6") ("texmap" . "texmap. (line 6") ("texMatrix" . "texMatrix. (line 6") ("texname" . "texname. (line 6") ("texNumber" . "texNumber. (line 6") ("texobj" . "texobj. (line 6") ("texpoly" . "texpoly. (line 6") ("texPolynomial" . "texPolynomial. (line 6") ("texproc" . "texproc. (line 6") ("texring" . "texring. (line 6") ("the first alternative algorithm" . "awalk1. (line 24") ("The fractal walk algorithm" . "frandwalk. (line 20") ("The online help system" . "The online help system") ("The SINGULAR language" . "The SINGULAR language") ("The Tran algorithm" . "twalk. (line 20") ("three_elements" . "three_elements. (line 6") ("timeFactorize" . "timeFactorize. (line 6") ("timer" . "timer. (line 6") ("timer resolution, setting the" . "system. (line 231") ("timeStd" . "timeStd. (line 6") ("timestep" . "timestep. (line 6") ("tInitialForm" . "tInitialForm. (line 6") ("tInitialFormPar" . "tInitialFormPar. (line 6") ("tInitialFormParMax" . "tInitialFormParMax. (line 6") ("tInitialIdeal" . "tInitialIdeal. (line 6") ("tjurina" . "tjurina. (line 6") ("Tjurina" . "Tjurina. (line 6") ("Tjurina number" . "deltaLoc. (line 36") ("tmatrix" . "tmatrix. (line 6") ("todd" . "todd. (line 6") ("toddE" . "toddE. (line 6") ("toddPoly" . "toddPoly. (line 6") ("tolessvars" . "tolessvars. (line 6") ("Top 20 Emacs commands" . "Top 20 Emacs commands") ("topological invariants" . "charexp2conductor. (line 18") ("Tor" . "Tor. (line 6") ("toric ideals" . "Toric ideals. (line 6") ("Toric ideals and integer programming" . "Toric ideals and integer programming") ("toric ring" . "normaliz_lib. (line 52") ("toric.lib" . "toric_lib. (line 6") ("toric_ideal" . "toric_ideal. (line 6") ("toric_lib" . "toric_lib. (line 6") ("toric_std" . "toric_std. (line 6") ("torusInvariants" . "torusInvariants. (line 6") ("total divisors" . "bimodules_lib. (line 71") ("total multiplicities" . "alexpoly_lib. (line 40") ("totalmultiplicities" . "totalmultiplicities. (line 6") ("TRACE" . "TRACE var. (line 6") ("trace" . "trace. (line 6") ("TRACE" . "Tracing of procedures") ("tracemult" . "tracemult. (line 6") ("transpose" . "transpose. (line 6") ("trapezoid" . "trapezoid. (line 6") ("triagmatrix" . "triagmatrix. (line 6") ("triang.lib" . "triang_lib. (line 6") ("triang_lib" . "triang_lib. (line 6") ("triang_solve" . "triang_solve. (line 6") ("triangL" . "triangL. (line 6") ("triangL_solve" . "triangL_solve. (line 6") ("triangLf_solve" . "triangLf_solve. (line 6") ("triangLfak" . "triangLfak. (line 6") ("triangM" . "triangM. (line 6") ("triangM_solve" . "triangM_solve. (line 6") ("triangMH" . "triangMH. (line 6") ("triangulations" . "triangulations. (line 6") ("Tricks and pitfalls" . "Tricks and pitfalls. (line 6") ("triMNewton" . "triMNewton. (line 6") ("tropical curves" . "tropical_lib. (line 165") ("Tropical Geometry" . "Tropical Geometry. (line 6") ("tropical geometry" . "ellipticcovers_lib. (line 49") ("tropical mirror symmetry" . "ellipticcovers_lib. (line 49") ("tropical polynomials" . "tropical_lib. (line 165") ("tropical.lib" . "tropical_lib. (line 6") ("tropical_lib" . "tropical_lib. (line 6") ("tropicalCurve" . "tropicalCurve. (line 6") ("tropicalise" . "tropicalise. (line 6") ("tropicaliseSet" . "tropicaliseSet. (line 6") ("tropicalJInvariant" . "tropicalJInvariant. (line 6") ("tropicalLifting" . "tropicalLifting. (line 6") ("tropicalSubst" . "tropicalSubst. (line 6") ("tropicalVariety" . "tropicalVariety. (line 6") ("truncate" . "truncate. (line 6") ("truncated module" . "truncateFast. (line 28") ("truncateFast" . "truncateFast. (line 6") ("tst_ncfactor" . "tst_ncfactor. (line 6") ("twalk" . "twalk. (line 6") ("two-sided" . "bimodules_lib. (line 71") ("two-sided Groebner basis" . "bimodules_lib. (line 71") ("twostd" . "twostd. (line 6") ("type" . "type. (line 6") ("type B" . "arrTypeB. (line 15") ("Type casting" . "Type conversion and casting") ("Type conversion" . "Type conversion and casting") ("type D" . "arrTypeD. (line 15") ("type,custom" . "Definition of a user defined type") ("type2arr" . "type2arr. (line 6") ("typecasting" . "mat2carr. (line 17") ("typeof" . "typeof. (line 6") ("Typesetting of help and info strings" . "Typesetting of help and info strings") ("u" . "u. (line 6") ("U_D_O" . "U_D_O. (line 6") ("uname" . "system. (line 204") ("unbounded_knapsack" . "unbounded_knapsack. (line 6") ("unipotent groups" . "orbitparam_lib. (line 49") ("uniquePoint" . "uniquePoint. (line 6") ("unitmat" . "unitmat. (line 6") ("univariate" . "univariate. (line 6") ("univarpoly" . "univarpoly. (line 6") ("Unix installation" . "Unix installation instructions") ("unknown syndrome" . "Decoding method based on quadratic equations") ("unset" . "kill. (line 6") ("untyped definitions" . "ideal (plural). (line 6") ("updatePairs" . "updatePairs. (line 6") ("UpOneMatrix" . "UpOneMatrix. (line 6") ("UpperMonomials" . "UpperMonomials. (line 6") ("ures_solve" . "ures_solve. (line 6") ("uressolve" . "uressolve. (line 6") ("usage, option" . "option. (line 209") ("UseBertini" . "UseBertini. (line 6") ("User defined types" . "User defined types. (line 6") ("user interface, Emacs" . "Emacs user interface") ("V-filtration" . "goodBasis. (line 22") ("valvars" . "valvars. (line 6") ("vandermonde" . "vandermonde. (line 6") ("vanishId" . "vanishId. (line 6") ("var" . "var. (line 6") ("variables" . "arrLastVar. (line 18") ("Variables, indexed" . "Names. (line 6") ("variablesSorted" . "variablesSorted. (line 6") ("variablesStandard" . "variablesStandard. (line 6") ("varMat" . "varMat. (line 6") ("varNum" . "varNum. (line 6") ("vars2pars" . "vars2pars. (line 6") ("varsigns" . "varsigns. (line 6") ("varstr" . "varstr. (line 6") ("VarToPar" . "VarToPar. (line 6") ("vct2str" . "vct2str. (line 6") ("vdim" . "vdim. (line 6") ("vdim (plural)" . "vdim (plural). (line 6") ("vec2poly" . "vec2poly. (line 6") ("vector" . "vector. (line 6") ("vector declarations" . "vector declarations. (line 6") ("vector expressions" . "vector expressions. (line 6") ("vector operations" . "vector operations. (line 6") ("vector related functions" . "vector related functions") ("verify" . "verify. (line 6") ("versal" . "versal. (line 6") ("version" . "system. (line 208") ("Version number" . "Version schema for Singular") ("Version schema for Singular" . "Version schema for Singular") ("Version string" . "Version string. (line 6") ("vertexAdjacencyGraph" . "vertexAdjacencyGraph") ("vertexEdgeGraph" . "vertexEdgeGraph. (line 6") ("vertices" . "vertices. (line 6") ("vfilt" . "vfilt. (line 6") ("view" . "view. (line 6") ("visual" . "visual. (line 6") ("Visualization" . "Visualization. (line 6") ("visualize" . "visualize. (line 6") ("voice" . "voice. (line 6") ("vwfilt" . "vwfilt. (line 6") ("waitall" . "waitall. (line 6") ("waitAllTasks" . "waitAllTasks. (line 6") ("waitfirst" . "waitfirst. (line 6") ("waitTasks" . "waitTasks. (line 6") ("warkedPreimageStd" . "warkedPreimageStd. (line 6") ("warn, option" . "option. (line 52") ("watchdog" . "watchdog. (line 6") ("wedge" . "wedge. (line 6") ("weierstr.lib" . "weierstr_lib. (line 6") ("weierstr_lib" . "weierstr_lib. (line 6") ("Weierstrass" . "Weierstrass. (line 6") ("Weierstrass semigroup" . "brnoeth_lib. (line 43") ("weierstrassForm" . "weierstrassForm. (line 6") ("weierstrDiv" . "weierstrDiv. (line 6") ("weierstrPrep" . "weierstrPrep. (line 6") ("weight" . "weight. (line 6") ("weight filtration" . "goodBasis. (line 22") ("weighted lexicographical ordering" . "Global orderings. (line 42") ("weighted reverse lexicographical ordering" . "Global orderings") ("weightedRing" . "weightedRing. (line 6") ("weightKB" . "weightKB. (line 6") ("weightM, option" . "option. (line 141") ("Weyl" . "Weyl. (line 6") ("Weyl algebra" . "dmodvar_lib. (line 59") ("Weyl closure" . "dmodloc_lib. (line 93") ("WeylClosure" . "WeylClosure. (line 6") ("WeylClosure1" . "WeylClosure1. (line 6") ("whichvariable" . "whichvariable. (line 6") ("while" . "while. (line 6") ("Windows installation" . "Windows installation instructions") ("withDim" . "attrib. (line 69") ("withHilb" . "attrib. (line 69") ("withMult" . "attrib. (line 69") ("withRes" . "attrib. (line 69") ("withSB" . "attrib. (line 69") ("WitSet" . "WitSet. (line 6") ("WitSupSet" . "WitSupSet. (line 6") ("WP, global ordering" . "Global orderings. (line 42") ("wp, global ordering" . "Global orderings. (line 37") ("write" . "write. (line 6") ("writeNmzData" . "writeNmzData. (line 6") ("writeNmzPaths" . "writeNmzPaths. (line 6") ("Ws, local ordering" . "Local orderings. (line 39") ("ws, local ordering" . "Local orderings. (line 33") ("WSemigroup" . "WSemigroup. (line 6") ("wUnit" . "wUnit. (line 6") ("wurzel" . "wurzel. (line 6") ("xchange" . "xchange. (line 6") ("xdvi" . "xdvi. (line 6") ("XLsolve" . "XLsolve. (line 6") ("zdd" . "polybori_lib. (line 94") ("zdd2poly" . "zdd2poly. (line 6") ("zero-dimensional" . "qbase. (line 15") ("zerodec" . "zerodec. (line 6") ("zeroMod" . "zeroMod. (line 6") ("zeroOpt" . "zeroOpt. (line 6") ("zeroRadical" . "zeroRadical. (line 6") ("zeroSet" . "zeroSet. (line 6") ("zeroset.lib" . "zeroset_lib. (line 6") ("zeroset_lib" . "zeroset_lib. (line 6") ("zetaDL" . "zetaDL. (line 6") ("ZZsolve" . "ZZsolve. (line 6") ("{" . "Special characters. (line 11") ("||" . "boolean operations. (line 6") ("}" . "Special characters. (line 11") ("~" . "~. (line 6") )) singular-4.0.3+ds/emacs/lib-cmpl.el000066400000000000000000000074541266270727000171000ustar00rootroot00000000000000(setq singular-standard-libraries-with-categories '( ("real algebra" ("realrad.lib") ) ("general" ("decomp.lib") ) ("Visualization" ("surfex.lib") ("surf.lib") ("resgraph.lib") ("latex.lib") ("graphics.lib") ) ("Tropical Geometry" ("tropical.lib") ("realizationMatroids.lib") ("oldpolymake.lib") ) ("Teaching" ("weierstr.lib") ("teachstd.lib") ("rootsur.lib") ("rootsmr.lib") ("hyperel.lib") ("finitediff.lib") ("crypto.lib") ("atkins.lib") ("aksaka.lib") ) ("System and Control Theory" ("jacobson.lib") ("control.lib") ) ("Symbolic-numerical solving" ("zeroset.lib") ("triang.lib") ("solve.lib") ("signcond.lib") ("presolve.lib") ("ntsolve.lib") ("ffsolve.lib") ) ("Singularity Theory" ("curvepar.lib") ) ("Singularities" ("surfacesignature.lib") ("spectrum.lib") ("spcurve.lib") ("sing.lib") ("realclassify.lib") ("qhmoduli.lib") ("mondromy.lib") ("hnoether.lib") ("gmssing.lib") ("gmspoly.lib") ("equising.lib") ("deform.lib") ("classifyceq.lib") ("classify.lib") ("arcpoint.lib") ("alexpoly.lib") ) ("Resolution of singularities" ("resbinomial.lib") ) ("Noncommutative" ("ratgb.lib") ("qmatrix.lib") ("purityfiltration.lib") ("perron.lib") ("nctools.lib") ("ncpreim.lib") ("nchomolog.lib") ("ncfactor.lib") ("ncdecomp.lib") ("ncalg.lib") ("involut.lib") ("gkdim.lib") ("freegb.lib") ("fpadim.lib") ("dmodvar.lib") ("dmodloc.lib") ("dmodapp.lib") ("dmod.lib") ("central.lib") ("bfun.lib") ) ("Miscellaneous" ("standard.lib") ("ringgb.lib") ("polybori.lib") ("makedbm.lib") ("help.cnf") ("COPYING") ) ("Linear Algebra" ("matrix.lib") ("linalg.lib") ) ("Invariant theory" ("stratify.lib") ("rinvar.lib") ("finvar.lib") ("ainvar.lib") ) ("General purpose" ("ring.lib") ("random.lib") ("poly.lib") ("parallel.lib") ("kskernel.lib") ("inout.lib") ("grobcov.lib") ("general.lib") ("compregb.lib") ("all.lib") ) ("Factorization" ("absfact.lib") ) ("Commutative Algebra" ("pointid.lib") ("normaliz.lib") ("monomialideal.lib") ("toric.lib") ("symodstd.lib") ("sing4ti2.lib") ("sheafcoh.lib") ("sagbi.lib") ("resjung.lib") ("reesclos.lib") ("primitiv.lib") ("primdecint.lib") ("primdec.lib") ("normal.lib") ("noether.lib") ("mregular.lib") ("mprimdec.lib") ("modstd.lib") ("modnormal.lib") ("locnormal.lib") ("lll.lib") ("intprog.lib") ("integralbasis.lib") ("homolog.lib") ("grwalk.lib") ("elim.lib") ("divisors.lib") ("cisimplicial.lib") ("assprimeszerodim.lib") ("algebra.lib") ) ("Combinatorial Commutative Algebra" ("multigrading.lib") ) ("Coding theory" ("decodegb.lib") ("brnoeth.lib") ) ("Applications" ("groups.lib") ("findifs.lib") ) ("Algebraic Geometry" ("reszeta.lib") ("resolve.lib") ("paraplanecurves.lib") ("orbitparam.lib") ("numerDecom.lib") ("numerAlg.lib") ("JMSConst.lib") ("JMBTest.lib") ) (" " ("phindex.lib") ) )) singular-4.0.3+ds/emacs/singular.el000066400000000000000000005262531266270727000172300ustar00rootroot00000000000000;;; singular.el --- Emacs support for Computer Algebra System Singular ;;; Commentary: ;;; Code: ;;{{{ Style and coding conventions ;; Style and coding conventions: ;; ;; - "Singular" is written with an upper-case `S' in comments, doc ;; strings, and messages. As part of symbols, it is written with ;; a lower-case `s'. ;; - When referring to the Singular interactive mode, do it in that ;; wording. Use the notation `singular-interactive-mode' only when ;; really referring to the lisp object. ;; - use a `fill-column' of 75 for doc strings and comments ;; - mark incomplete doc strings or code with `NOT READY' optionally ;; followed by an explanation what exactly is missing ;; ;; - use foldings to structure the source code but try not to exceed a ;; maximum depth of two foldings ;; - use lowercase folding titles except for first word ;; - folding-marks are `;;{{{' and `;;}}}' resp., for sake of standard ;; conformity ;; - use the foldings to modularize code. That is, each folding should be, ;; as far as possible, self-content. Define a function `singular-*-init' ;; in the folding to do the initialization of the module contained in ;; that folding. Call that function from `singular-interactive-mode', ;; for example, instead of initializing the module directly from ;; `singular-interactive-mode'. Look at the code how it is done for the ;; simple section or for the folding stuff. ;; ;; - use `singular' as prefix for all global symbols ;; - use `singular-debug' as prefix for all global symbols concerning ;; debugging. ;; - use, whenever possible without names becoming too clumsy, some unique ;; prefix inside a folding ;; ;; - mark dependencies on Emacs flavor/version with a comment of the form ;; `;; Emacs[ ]' resp. ;; `;; XEmacs[ ][ ]' ;; specified in that order, if possible ;; - use a `cond' statement to execute Emacs flavor/version-dependent code, ;; not `if'. This is to make such checks more extensible. ;; - try to define different functions for different flavors/version and ;; use `singular-fset' at library-loading time to set the function you ;; really need. If the function is named `singular-', the ;; flavor/version-dependent functions should be named ;; `singular-[-]-'. ;; ;; - use `singular-debug' for debugging output/actions ;; - to switch between buffer and process names, use the functions ;; `singular-process-name-to-buffer-name' and ;; `singular-buffer-name-to-process-name' ;; - call the function `singular-keep-region-active' as last statement in ;; an interactive function that should keep the region active (for ;; example, in functions that move the point). This is necessary to keep ;; XEmacs' zmacs regions active. ;; - to get the process of the current buffer, use `singular-process'. To ;; get the current process mark, use `singular-process-mark'. Both ;; functions check whether Singular is alive and throw an error if not, ;; so you do not have to care about that yourself. If you do not want an ;; error specify non-nil argument NO-ERROR. But use them anyway. ;; - we assume that the buffer is *not* read-only ;; - use `=' instead of `eq' when comparing buffer locations. Even if you ;; are sure that both operands are integers. ;;}}} ;;{{{ Code common to both modes ;;{{{ Customizing (defgroup singular nil "Emacs interface to Singular. By now, the Emacs interface to Singular consists of Singular interactive mode only. Singular interactive mode provides a convenient front end to interactive Singular sessions running inside Emacs. In far future maybe there will be a mode for editing Singular source code such as libraries or procedures." :group 'external) (defgroup singular-faces nil "Faces in Singular mode and Singular interactive mode." :group 'faces :group 'singular-interactive) ;;}}} ;;{{{ Debugging stuff (defvar singular-debug nil "List of modes to debug or t to debug all modes. Currently, the following modes are supported: `interactive', `interactive-filter'.") (defun singular-debug-format (string) "Return STRING in a nicer format." (save-match-data (while (string-match "\n" string) (setq string (replace-match "^J" nil nil string))) (if (> (length string) 16) (concat "<" (substring string 0 7) ">...<" (substring string -8) ">") (concat "<" string ">")))) (defmacro singular-debug (mode form &optional else-form) "Major debugging hook for singular.el. Evaluates FORM if `singular-debug' equals t or if MODE is an element of `singular-debug', othwerwise ELSE-FORM." `(if (or (eq singular-debug t) (memq ,mode singular-debug)) ,form ,else-form)) ;;}}} ;;{{{ Determining version (defvar singular-emacs-flavor nil "A symbol describing the current Emacs. Currently, only Emacs \(`emacs') and XEmacs \(`xemacs') are supported.") (defvar singular-emacs-major-version nil "An integer describing the major version of the current emacs.") (defvar singular-emacs-minor-version nil "An integer describing the minor version of the current emacs.") (defun singular-fset (real-function emacs-function xemacs-function) "Set REAL-FUNCTION to one of the functions, in dependency on Emacs flavor and version. Sets REAL-FUNCTION to XEMACS-FUNCTION if `singular-emacs-flavor' is `xemacs', otherwise sets REAL-FUNCTION to EMACS-FUNCTION. This is not as common as it would be desirable. But it is sufficient so far." (cond ;; XEmacs ((eq singular-emacs-flavor 'xemacs) (fset real-function xemacs-function)) ;; Emacs (t (fset real-function emacs-function)))) (defun singular-set-version () "Determine flavor, major version, and minor version of current emacs. singular.el is guaranteed to run on Emacs 20.3 and XEmacs 20.3. It should run on newer version and on slightly older ones, too. This function is called exactly once when singular.el is loaded." ;; get major and minor versions first (if (and (boundp 'emacs-major-version) (boundp 'emacs-minor-version)) (setq singular-emacs-major-version emacs-major-version singular-emacs-minor-version emacs-minor-version) (with-output-to-temp-buffer "*singular warnings*" (princ "You seem to have quite an old Emacs or XEmacs version. Some of the features from singular.el will not work properly. Consider upgrading to a more recent version of Emacs or XEmacs. singular.el is guaranteed to run on Emacs 20.3 and XEmacs 20.3.")) ;; assume the oldest version we support (setq singular-emacs-major-version 20 singular-emacs-minor-version 3)) ;; get flavor (if (string-match "XEmacs\\|Lucid" emacs-version) (setq singular-emacs-flavor 'xemacs) (setq singular-emacs-flavor 'emacs))) (singular-set-version) ;;}}} ;;{{{ Syntax table (defvar singular-mode-syntax-table nil "Syntax table for `singular-interactive-mode' resp. `singular-mode'.") (if singular-mode-syntax-table () (setq singular-mode-syntax-table (make-syntax-table)) ;; stolen from cc-mode.el except for back-tics which are special to Singular (modify-syntax-entry ?_ "_" singular-mode-syntax-table) (modify-syntax-entry ?\\ "\\" singular-mode-syntax-table) (modify-syntax-entry ?+ "." singular-mode-syntax-table) (modify-syntax-entry ?- "." singular-mode-syntax-table) (modify-syntax-entry ?= "." singular-mode-syntax-table) (modify-syntax-entry ?% "." singular-mode-syntax-table) (modify-syntax-entry ?< "." singular-mode-syntax-table) (modify-syntax-entry ?> "." singular-mode-syntax-table) (modify-syntax-entry ?& "." singular-mode-syntax-table) (modify-syntax-entry ?| "." singular-mode-syntax-table) (modify-syntax-entry ?\' "\"" singular-mode-syntax-table) (modify-syntax-entry ?\` "\"" singular-mode-syntax-table) ;; block and line-oriented comments (cond ;; Emacs ((eq singular-emacs-flavor 'emacs) (modify-syntax-entry ?/ ". 124b" singular-mode-syntax-table) (modify-syntax-entry ?* ". 23" singular-mode-syntax-table)) ;; XEmacs (t (modify-syntax-entry ?/ ". 1456" singular-mode-syntax-table) (modify-syntax-entry ?* ". 23" singular-mode-syntax-table))) (modify-syntax-entry ?\n "> b" singular-mode-syntax-table) (modify-syntax-entry ?\^m "> b" singular-mode-syntax-table)) (defun singular-mode-syntax-table-init () "Initialize syntax table of current buffer. This function is called at mode initialization time." (set-syntax-table singular-mode-syntax-table)) ;;}}} ;;{{{ Miscellaneous (defsubst singular-keep-region-active () "Do whatever is necessary to keep the region active in XEmacs. Ignore byte-compiler warnings you might see. This is not needed for Emacs." ;; XEmacs. We do not use the standard way here to test for flavor ;; because it is presumably faster with that test on `boundp'. (and (boundp 'zmacs-region-stays) (setq zmacs-region-stays t))) ;;}}} ;;}}} ;;{{{ Singular interactive mode ;;{{{ Customizing ;; Note: ;; ;; Some notes on Customize: ;; ;; - The documentation states that for the `:initialize' option of ;; `defcustom' the default value is `custom-initialize-set'. However, in ;; the source code of Customize `custom-initialize-reset' is used. So ;; better always specify the `:initialize' option explicitly. ;; - Customize is bad at setting buffer-local variables or properties. ;; This is quite natural since Customize itself uses its own buffer. So ;; changing buffer-local variables and properties with Customize is ;; possible only at a "Singular-global" level. That is, for all buffers ;; currently having Singular interactive mode as major mode. The function ;; `singular-map-buffer' helps to do such customization. ;; - Important note: Customizable variables are not automatically marked as ;; user options. This has to be done as usual by marking them with a '*' ;; as first character of the documentation string. Without that, the ;; variables are not accessible to, for example, `set-variable'. ;; ;; Some common customizing patterns: ;; ;; - How to customize buffer-local properties? ;; First, the `defcustom' itself must not set anything buffer-local since ;; at time of its definition (most likely) no Singular buffers will be ;; around. If there are Singular buffers we do not care about them. But ;; anyhow, at definition of the `defcustom' the global default has to be ;; set. Hence, the `:initialize' option should be set to ;; `custom-initialize-default'. ;; The buffer-local initialization has to be done at mode initialization ;; time. The global default value should then be used to set the local ;; properties. ;; At last, the function specified with the `:set' option should set the ;; local properties in all Singular buffers to the new, customized value. ;; Most likely, the function `singular-map-buffer' may be used for that. ;; In addition, the function should, of course, set the global value via ;; `set-default'. ;; For an example, see `singular-folding-line-move-ignore-folding'. ;; ;; - How to encapsulate other mode's global variables into Singular ;; interactive mode variables? ;; Set them always. That is, set them if the `defcustom' is evaluated ;; (use `custom-initialize-reset' as `:initial' function) and set them ;; when the Singular interactive mode variable is customized (by means ;; of an appropriate `:set' function). ;; For an example, see `singular-section-face-alist' (which does not ;; encapsulate another mode's variable, but Singular interactive mode's ;; own variable `singular-simple-sec-clear-type'). (defgroup singular-interactive nil "Running interactive Singular sessions inside Emacs." :group 'singular :group 'processes) (defgroup singular-sections-and-foldings nil "Sections and foldings in Singular interactive mode." :group 'singular-interactive) (defgroup singular-interactive-miscellaneous nil "Miscellaneous settings for Singular interactive mode." :group 'singular-interactive) (defgroup singular-demo-mode nil "Settings concerning Singular demo mode." :group 'singular-interactive) (defun singular-map-buffer (func &rest args) "Apply FUNC to ARGS in all existing Singular buffers. That is, in all buffers having Singular interactive major mode. The function is executed in the context of the buffer. This is a must-have for the customizing stuff to change buffer-local properties." (save-excursion (mapcar (function (lambda (buffer) (set-buffer buffer) (if (eq major-mode 'singular-interactive-mode) (apply func args)))) (buffer-list)))) ;;}}} ;;{{{ Comint ;; Note: ;; ;; We require Comint, but we really do not use it too much. One may argue ;; that this is bad since Comint is a standardized way to communicate with ;; external processes. One may argue further that many experienced Emacs ;; users are forced now to re-do their Comint customization for Singular ;; interactive mode. However, we believe that the intersection between ;; experienced Emacs users and users of Singular interactive mode is almost ;; empty. ;; ;; In fact, we used Comint really much in the beginning of this project. ;; Later during development it turned at that using Comint's input and ;; output processing is to inflexible and not appropriate for Singular ;; interactive mode with its input and output sections. So we begun to ;; rewrite large portions of Comint to adapt it to our needs. At some ;; point it came clear that it would be best to throw out Comint ;; alltogether, would not have been there some auxilliary functions which ;; are really useful but annoying to rewrite. These are, for example, the ;; command line history functions or the completion stuff offered by ;; Comint. ;; ;; Our policy with regard to these remainders of Comint is: Use the ;; functions to bind them to keys, but do not use them internally. ;; Encapsulate Comint customization into Singular interactive mode ;; customization. In particular, do not take care about Comint settings ;; which already may be present, overwrite them. Hide Comint from the ;; user. ;; ;; Here is how exactly we use Comint: ;; ;; - All variables necessary to use Comint's input ring are properly ;; initialized. One may find this in the `History' folding. ;; - `comint-prompt-regexp' is initialized since it is used in some ;; of the functions regarding input ring handling. Furthermore, its ;; initialization enables us to use functions as `comint-bol', etc. ;; Initialization is done in the `Skipping and stripping prompts ...' ;; folding. ;; - We call `comint-mode' as first step in `singular-interactive-mode'. ;; Most of the work done there is to initialize the local variables as ;; necessary. Besides that, the function does nothing that interferes ;; with Singular interactive mode. To be consequent we set ;; `comint-mode-hook' temporarily to nil when calling `comint-mode'. ;; - In `singular-exec', we use `comint-exec-1' to fire up the process. ;; Furthermore, we set `comint-ptyp' there as it is used in the signal ;; sending commands of Comint. All that `comint-exec-1' does is that it ;; sets up the process environment (it adds or modifies the setting of ;; the 'TERM' variable), sets the execution directory, and does some ;; magic with the process coding stuff. ;; - One more time the most important point: we do *not* use Comint's ;; output and input processing. In particular, we do not run any of ;; Comint's hooks on input or output. Anyway, we do better, don't we? (require 'comint) (defun singular-comint-init () "Initialize comint stuff for Singular interactive mode. This function is called at mode initialization time." (setq comint-completion-addsuffix '("/" . ""))) ;;}}} ;;{{{ Font-locking (defvar singular-font-lock-error-face 'singular-font-lock-error-face "Face name to use for Singular errors.") (defvar singular-font-lock-warning-face 'singular-font-lock-warning-face "Face name to use for Singular warnings.") (defvar singular-font-lock-prompt-face 'singular-font-lock-prompt-face "Face name to use for Singular prompts.") (defface singular-font-lock-error-face '((((class color)) (:foreground "Red" :bold t)) (t (:inverse-video t :bold t))) "*Font Lock mode face used to highlight Singular errors." :group 'singular-faces) (defface singular-font-lock-warning-face '((((class color)) (:foreground "OrangeRed" :bold nil)) (t (:inverse-video t :bold t))) "*Font Lock mode face used to highlight Singular warnings." :group 'singular-faces) (defface singular-font-lock-prompt-face '((((class color) (background light)) (:foreground "Blue" :bold t)) (((class color) (background dark)) (:foreground "LightSkyBlue" :bold t)) (t (:inverse-video t :bold t))) "*Font Lock mode face used to highlight Singular prompts." :group 'singular-faces) (defconst singular-font-lock-singular-types nil "List of Singular types.") (eval-when-compile (setq singular-font-lock-singular-types '("def" "bigint" "ideal" "int" "intmat" "intvec" "link" "list" "map" "matrix" "module" "number" "poly" "proc" "qring" "resolution" "ring" "string" "vector"))) (defconst singular-interactive-font-lock-keywords-1 '( ("^\\([>.]\\) " 1 singular-font-lock-prompt-face t) ("^ [\\?].*" 0 singular-font-lock-error-face t) ("^// \\*\\*.*" 0 singular-font-lock-warning-face t) ) "Subdued level highlighting for Singular interactive mode") (defconst singular-interactive-font-lock-keywords-2 (append singular-interactive-font-lock-keywords-1 (eval-when-compile (list (cons (concat "\\<" (regexp-opt singular-font-lock-singular-types t) "\\>") 'font-lock-type-face)))) "Medium level highlighting for Singular interactive mode") (defconst singular-interactive-font-lock-keywords-3 (append singular-interactive-font-lock-keywords-2 '( ;; note: we use font-lock-reference-face here even Emacs says that ;; this face is obsolete and suggests to use font-lock-constant-face, ;; since XEmacs20/21 does not know the constant-face but the ;; reference-face. ("^ [\\?].*`\\(\\sw\\sw+;?\\)`" 1 font-lock-reference-face t) )) "Gaudy level highlighting for Singular interactive mode.") (defconst singular-interactive-font-lock-keywords singular-interactive-font-lock-keywords-1 "Default highlighting for Singular interactive mode.") (defconst singular-interactive-font-lock-defaults '((singular-interactive-font-lock-keywords singular-interactive-font-lock-keywords-1 singular-interactive-font-lock-keywords-2 singular-interactive-font-lock-keywords-3) ;; KEYWORDS-ONLY (do not fontify strings & comments if non-nil) nil ;; CASE-FOLD (ignore case if non-nil) nil ;; SYNTAX-ALIST (add this to Font Lock's syntax table) ((?_ . "w")) ;; SYNTAX-BEGIN singular-section-goto-beginning) "Default expressions to highlight in Singular interactive mode.") (defun singular-interactive-font-lock-init () "Initialize Font Lock mode for Singular interactive mode. For XEmacs, this function is called exactly once when singular.el is loaded. For Emacs, this function is called at mode initialization time." (cond ;; Emacs ((eq singular-emacs-flavor 'emacs) (singular-debug 'interactive (message "Setting up Font Lock mode for Emacs")) (set (make-local-variable 'font-lock-defaults) singular-interactive-font-lock-defaults)) ;; XEmacs ((eq singular-emacs-flavor 'xemacs) (singular-debug 'interactive (message "Setting up Font Lock mode for XEmacs")) (put 'singular-interactive-mode 'font-lock-defaults singular-interactive-font-lock-defaults)))) ;; XEmacs Font Lock mode initialization (cond ;; XEmacs ((eq singular-emacs-flavor 'xemacs) (singular-interactive-font-lock-init))) ;;}}} ;;{{{ Key map (defvar singular-interactive-mode-map nil "Key map to use in Singular interactive mode.") (if singular-interactive-mode-map () ;; create empty keymap first (cond ;; Emacs ((eq singular-emacs-flavor 'emacs) (setq singular-interactive-mode-map (make-sparse-keymap))) ;; XEmacs (t (setq singular-interactive-mode-map (make-keymap)) (set-keymap-name singular-interactive-mode-map 'singular-interactive-mode-map))) ;; global settings (define-key help-map [?\C-s] 'singular-help) ;; settings for `singular-interactive-map' (substitute-key-definition 'beginning-of-line 'singular-beginning-of-line singular-interactive-mode-map global-map) (define-key singular-interactive-mode-map "\t" 'singular-dynamic-complete) (define-key singular-interactive-mode-map [?\C-m] 'singular-send-or-copy-input) (define-key singular-interactive-mode-map [?\C-l] 'singular-recenter) ;; Comint functions (define-key singular-interactive-mode-map [?\M-r] 'comint-previous-matching-input) (define-key singular-interactive-mode-map [?\M-s] 'comint-next-matching-input) ;; C-c prefix (define-key singular-interactive-mode-map [?\C-c ?\C-e] 'singular-example) (define-key singular-interactive-mode-map [?\C-c ?\C-t] 'singular-toggle-truncate-lines) (define-key singular-interactive-mode-map [?\C-c ?\C-f] 'singular-folding-toggle-fold-at-point-or-all) (define-key singular-interactive-mode-map [?\C-c ?\C-o] 'singular-folding-toggle-fold-latest-output) (define-key singular-interactive-mode-map [?\C-c ?\C-w] 'singular-section-kill) (define-key singular-interactive-mode-map [?\C-c ?\C-d] 'singular-demo-load) (define-key singular-interactive-mode-map [?\C-c ?\C-l] 'singular-load-library) (define-key singular-interactive-mode-map [(control c) (<)] 'singular-load-file) (define-key singular-interactive-mode-map [?\C-c ?\C-r] 'singular-restart) (define-key singular-interactive-mode-map [?\C-c ?\$] 'singular-exit-singular) (define-key singular-interactive-mode-map [?\C-c ?\C-c] 'singular-control-c)) (defun singular-cursor-key-model-set (key-model) "Set keys according to KEY-MODEL. KEY-MODEL should be one of the valid values of `singular-cursor-key-model'." ;; convert symbols to list (cond ((eq key-model 'emacs) (setq key-model '(cursor cursor history))) ((eq key-model 'terminal) (setq key-model '(history history cursor)))) ;; work through list (mapcar (function (lambda (spec) (let ((key-description (nth 0 spec)) (prev-key (nth 1 spec)) (next-key (nth 2 spec))) (cond ((eq key-description 'cursor) (define-key singular-interactive-mode-map prev-key 'previous-line) (define-key singular-interactive-mode-map next-key 'next-line)) ((eq key-description 'history) (define-key singular-interactive-mode-map prev-key 'comint-previous-input) (define-key singular-interactive-mode-map next-key 'comint-next-input)) (t (define-key singular-interactive-mode-map prev-key nil) (define-key singular-interactive-mode-map next-key nil)))))) ;; here is where list position are mapped to keys (list (list (nth 0 key-model) [up] [down]) (list (nth 1 key-model) [?\C-p] [?\C-n]) (list (nth 2 key-model) [?\M-p] [?\M-n])))) (defcustom singular-cursor-key-model 'emacs "*Keys to use for cursor movement and history access, respectively. An experienced Emacs user would prefer setting `singular-cursor-key-model' to `emacs'. This means that C-p, C-n, and the cursor keys move the cursor, whereas M-p and M-n scroll through the history of Singular commands. On the other hand, an user used to running Singular in a, say, xterm, would prefer setting `singular-cursor-key-model' to `terminal'. This means that C-p, C-n, and the cursor keys scroll through the history of Singular commands, whereas M-p and M-n move the cursor. For those who do not like neither standard setting, there is the possibility to set this variable to a list of three elements where - the first element specifies the key bindings for the cursor keys, - the second element specifies the key bindings for C-p and C-n, and - the third element specifies the key bindings for M-p and M-n. Each list element should be one of - `cursor', meaning that the corresponding keys are bound to cursor movement, - `history', meaning that the corresponding keys are bound to history access, or - nil, meaning that the corresponding keys are not bound at all. Changing this variable has an immediate effect only if one uses \\[customize] to do so." :type '(choice (const :tag "Emacs-like" emacs) (const :tag "Terminal-like" terminal) (list :tag "User-defined" (choice :format "Cursor keys: %[Value Menu%] %v" :value cursor (const :tag "Cursor movement" cursor) (const :tag "History access" history) (const :tag "No binding" nil)) (choice :format "C-p, C-n: %[Value Menu%] %v" :value cursor (const :tag "Cursor movement" cursor) (const :tag "History access" history) (const :tag "No binding" nil)) (choice :format "M-p, M-n: %[Value Menu%] %v" :value history (const :tag "Cursor movement" cursor) (const :tag "History access" history) (const :tag "No binding" nil)))) :initialize 'custom-initialize-reset :set (function (lambda (var value) (singular-cursor-key-model-set value) (set-default var value))) :group 'singular-interactive-miscellaneous) (defun singular-interactive-mode-map-init () "Initialize key map for Singular interactive mode. This function is called at mode initialization time." (use-local-map singular-interactive-mode-map)) ;;}}} ;;{{{ Menus and logos (defvar singular-interactive-mode-menu-1 nil "NOT READY [docu]") (defvar singular-interactive-mode-menu-2 nil "NOT READY [docu]") (defconst singular-menu-initial-library-menu '(["other..." (singular-load-library t) t]) "Menu definition for the inital library sub menu. This should be a list of vectors.") (defun singular-menu-build-libraries-menu (definition) "Given a description of the libraries and their categories, builds up a menu definition including submenus which can be given to `easy-menu-change'. By side effect sets the variable `singular-standard-libraries-alist' to the alist of all library names. This alist can be used for completion." (let ((menudef ()) (libs definition) elem) (while libs (setq elem (car libs)) (if (> (length elem) 1) (setq menudef (append (list (append (list (car elem)) (singular-menu-build-libraries-menu (cdr elem)))) menudef)) (setq menudef (append (list (vector (car elem) (list 'singular-load-library nil (car elem)) t)) menudef)) (setq singular-standard-libraries-alist (append (list elem) singular-standard-libraries-alist))) (setq libs (cdr libs))) menudef)) (defun singular-menu-install-libraries () "Update the singular command menu with libraries. Scans the variable `singular-standard-libraries-with-categories' and builds up a menu with submenues for each category in the submenu (\"Commands\" \"Libraries\")." (singular-debug 'interactive (message "Installing library menu")) ;; To be compatible with older versions of singular.el (resp. of lib-cmpl.el) ;; we check whether the variable ;; `singular-standard-libraries-with-categories' is set. If not, we use the ;; value of `singular-standard-libraries-alist' instead. (if (not singular-standard-libraries-with-categories) (setq singular-standard-libraries-with-categories singular-standard-libraries-alist)) (easy-menu-change '("Commands") "Libraries" (append (singular-menu-build-libraries-menu singular-standard-libraries-with-categories) (append '("---") singular-menu-initial-library-menu)))) (defun singular-menu-init () "Initialize menu stuff for Singular interactive mode. This function is called by `singular-exec'." (singular-debug 'interactive (message "Initializing menue stuff")) (make-local-variable 'singular-standard-libraries-alist) (make-local-variable 'singular-standard-libraries-with-categories)) (defun singular-menu-deinstall-libraries () "Initialize library submenu from singular command menu. Sets the submenu (\"Commands\" \"Libraries\") to the value of `singular-menu-initial-library-menu'." (singular-debug 'interactive (message "Removing libraries from menu")) (easy-menu-change '("Commands") "Libraries" singular-menu-initial-library-menu)) ;; For some reasons emacs inserts new menus in the oppsite order. ;; Defining menu-2 prior to menu-1 will result in the follwoing menu: ;; Singular Commands ;; That's what we want. So DO NOT exchange both (or ..) statements! (or singular-interactive-mode-menu-2 (easy-menu-define singular-interactive-mode-menu-2 singular-interactive-mode-map "" (list "Commands" ["Fold/Unfold Latest Output" singular-folding-toggle-fold-latest-output t] ["Fold/Unfold At Point" singular-folding-toggle-fold-at-point-or-all t] ["Fold All Output" singular-folding-fold-all-output t] ["Unfold All Output" singular-folding-unfold-all-output t] "---" ["Truncate Lines" singular-toggle-truncate-lines :style toggle :selected truncate-lines] "--" (append '("Libraries") singular-menu-initial-library-menu) ["Load File..." singular-load-file t] "---" ["Load Demo..." singular-demo-load (or singular-demo-exit-on-load (not singular-demo-mode))] ["Exit Demo" singular-demo-exit singular-demo-mode] ))) (or singular-interactive-mode-menu-1 (easy-menu-define singular-interactive-mode-menu-1 singular-interactive-mode-map "" '("Singular" ["Start Default" singular t] ["Start..." singular-other t] ["Restart" singular-restart t] "---" ["Interrupt" singular-control-c t] ["Exit" singular-exit-singular t] "---" ["Preferences" (customize-group 'singular-interactive) t] ["Singular Example" singular-example t] ["Singular Help" singular-help t]))) (defun customize-singular-interactive () (interactive) (customize-group 'singular-interactive)) (defun singular-interactive-mode-menu-init () "Initialize menus for Singular interactive mode. This function is called at mode initialization time." ;; Remove any potential menu which comint-mode might has added. (cond ;; Emacs ((eq singular-emacs-flavor 'emacs) ;; Note that easy-menu-remove is a nop in emacs. (define-key comint-mode-map [menu-bar signals] nil) (define-key comint-mode-map [menu-bar inout] nil) (define-key comint-mode-map [menu-bar completion] nil)) ;;Xemacs (t (easy-menu-remove '("Singular")) (easy-menu-remove '("Comint1")) ; XEmacs 20 (easy-menu-remove '("Comint2")) ; XEmacs 20 (easy-menu-remove '("History")) ; XEmacs 20 (easy-menu-remove '("Complete")) ; XEmacs 21 (easy-menu-remove '("In/Out")) ; XEmacs 21 (easy-menu-remove '("Signals")))) ; XEmacs 21 ;; Note: easy-menu-add is not necessary in emacs, since the menu ;; is added automatically with the keymap. ;; See help on `easy-menu-add' (easy-menu-add singular-interactive-mode-menu-1) (easy-menu-add singular-interactive-mode-menu-2)) ;;}}} ;;{{{ Skipping and stripping prompts and whitespace and other things ;; Note: ;; ;; Most of these functions handle prompt recognition, prompt skipping, ;; prompt stripping, and so on. It turned out that it would be very ;; inefficient to use one generic regular expression to do so. Hence, we ;; decided to hardcode the prompt skipping and stripping in an API. If one ;; decides to use some other prompt the whole API has to be changed. ;; Hopefully, the Singular prompt does not change in near future ... ;; ;; In addition to the API, the Comint mode variable `comint-mode-regexp' is ;; set on initialization of Singular interactive mode. Singular ;; interactive mode seems to do quite well without that, but for safety the ;; variable is set nonetheless. (defsubst singular-prompt-skip-forward () "Skip forward over prompts." (if (looking-at "\\([>.] \\)+") (goto-char (match-end 0)))) (defsubst singular-prompt-skip-backward () "Skip backward over prompts." ;; is that really the simplest and fastest method? The problem is that ;; `re-search-backward' is not greedy so on an regexp as "\\([>.] \\)+" ;; it stops right after the first occurence of the sub-expression. ;; Anyway, the `(- (point) 2)' expression is OK, even at bob. (while (re-search-backward "[>.] " (- (point) 2) t))) (defun singular-prompt-remove-string (string) "Remove all prompts from STRING." (while (string-match "^\\([>.] \\)+" string) (setq string (replace-match "" t t string))) string) (defun singular-prompt-remove-region (beg end) "Remove all superfluous prompts from region between BEG and END. Removes only sequences of prompts that start at beginning of line. Removes all but the last prompt of a sequence if that sequence ends at END, otherwise removes all prompts. The region between BEG and END should be accessible. BEG should be less than or equal to END. Leaves point at the position of the last sequence of prompts which has been deleted or at BEG if nothing has been deleted." ;; we cannot exclude this case, I think (if (/= beg end) ;; that's a nice trick to keep the last prompt if it ends at END: we ;; set `(1- END)' as search limit. Since BEG /= END there can be no ;; problems with the `1-'. (let ((end (copy-marker (1- end)))) (goto-char beg) (while (re-search-forward "^\\([>.] \\)+" end t) (delete-region (match-beginning 0) (match-end 0))) (set-marker end nil)))) (defun singular-prompt-remove-filter (beg end simple-sec-start) "Remove all superfluous prompts from text inserted into buffer." (cond (;; if a new simple section has been created remove all ;; prompts from that simple section simple-sec-start (singular-prompt-remove-region simple-sec-start end)) (;; if no simple section has been created check whether maybe the ;; region between beg and end consists of prompts only. This in ;; case that the user issued a command that did not output any ;; text. (and (goto-char beg) (re-search-forward "\\([>.] \\)+" end t) (= (match-end 0) end)) (singular-prompt-remove-region (progn (beginning-of-line) (point)) end)))) (defun singular-white-space-strip (string &optional trailing leading) "Strip off trailing or leading whitespace from STRING. Strips off trailing whitespace if optional argument TRAILING is non-nil. Strips off leading whitespace if optional argument LEADING is non-nil." (let (beg end) (and leading (string-match "\\`[ \t\n\r\f]+" string) (setq beg (match-end 0))) (and trailing (string-match "[ \t\n\r\f]+\\'" string) (setq end (match-beginning 0))) (if (or beg end) (substring string (or beg 0) (or end (length string))) string))) (defconst singular-comint-prompt-regexp "^\\([>.] \\)+" "Regexp to match prompt patterns in Singular. This variable is used to initialize `comint-prompt-regexp' when Singular interactive mode starts up. It is not used in Singular interactive mode itself! One should refer to the source code for more information on how to adapt Singular interactive mode to some other prompt.") (defun singular-prompt-init () "Initialize prompt skipping and stripping for Singular interactive mode. This function is called at mode initialization time." ;; remove superfluous prompts in singular output (add-hook 'singular-post-output-filter-functions 'singular-prompt-remove-filter nil t) ;; some relict from Comint mode (setq comint-prompt-regexp singular-comint-prompt-regexp)) ;; required to use prompt-regexp (setq comint-use-prompt-regexp t) ;;}}} ;;{{{ Miscellaneous ;; Note: ;; ;; We assume a one-to-one correspondence between Singular buffers and ;; Singular processes. We always have (equal buffer-name (concat "*" ;; process-name "*")). (defsubst singular-buffer-name-to-process-name (buffer-name) "Create the process name for BUFFER-NAME. The process name is the buffer name with surrounding `*' stripped off." (substring buffer-name 1 -1)) (defsubst singular-process-name-to-buffer-name (process-name) "Create the buffer name for PROCESS-NAME. The buffer name is the process name with surrounding `*'." (concat "*" process-name "*")) (defsubst singular-run-hook-with-arg-and-value (hook value) "Call functions on HOOK. Provides argument VALUE to the functions. If a function returns a non-nil value it replaces VALUE as new argument to the remaining functions. Returns final VALUE." (while hook (setq value (or (funcall (car hook) value) value) hook (cdr hook))) value) (defsubst singular-process (&optional no-error) "Return process of current buffer. If no process is active this function silently returns nil if optional argument NO-ERROR is non-nil, otherwise it throws an error." (cond ((get-buffer-process (current-buffer))) (no-error nil) (t (error "No Singular running in this buffer")))) (defsubst singular-process-mark (&optional no-error) "Return process mark of current buffer. If no process is active this function silently returns nil if optional argument NO-ERROR is non-nil, otherwise it throws an error." (let ((process (singular-process no-error))) (and process (process-mark process)))) (defun singular-time-stamp-difference (new-time-stamp old-time-stamp) "Return the number of seconds between NEW-TIME-STAMP and OLD-TIME-STAMP. Both NEW-TIME-STAMP and OLD-TIME-STAMP should be in the format that is returned, for example, by `current-time'. Does not return a difference larger than 2^17 seconds." (let ((high-difference (min 1 (- (car new-time-stamp) (car old-time-stamp)))) (low-difference (- (cadr new-time-stamp) (cadr old-time-stamp)))) (+ (* high-difference 131072) low-difference))) (defun singular-error (&rest message-args) "Apply `message' on MESSAGE-ARGS and do a `ding'. This function should be used instead of `error' in hooks where calling `error' is not a good idea." (apply 'message message-args) (ding)) (defun singular-pop-to-buffer (same-window &rest pop-to-buffer-args) "Pop to buffer in same or other window. Pops to buffer in same window if SAME-WINDOW equals t. Pops to buffer in other window if SAME-WINDOW equals nil. If SAME-WINDOW equals neither t nor nil the default behaviour of `pop-to-buffer' is used. The rest of the arguments is passed unchanged to `pop-to-buffer'." (let ((same-window-buffer-names (cond ((null same-window) nil) ((eq same-window t) (let* ((buffer-or-name (car pop-to-buffer-args)) (buffer-name (if (bufferp buffer-or-name) (buffer-name buffer-or-name) buffer-or-name))) (list buffer-name))) (t same-window-buffer-names)))) (apply 'pop-to-buffer pop-to-buffer-args))) ;;}}} ;;{{{ Miscellaneous interactive (defun singular-recenter (&optional arg) "Center point in window and redisplay frame. With ARG, put point on line ARG. The desired position of point is always relative to the current window. Just C-u as prefix means put point in the center of the window. If ARG is omitted or nil, erases the entire frame and then redraws with point in the center of the current window. Scrolls window to the left margin and moves point to beginning of line." (interactive "P") (singular-reposition-point-and-window) (recenter arg)) (defun singular-reposition-point-and-window () "Scroll window to the left margin and move point to beginning of line." (interactive) (set-window-hscroll (selected-window) 0) (move-to-column 0) ;; be careful where to place point (singular-prompt-skip-forward)) (defun singular-toggle-truncate-lines () "Toggle `truncate-lines'. A non-nil value of `truncate-lines' means do not display continuation lines\; give each line of text one screen line. Repositions window and point after toggling `truncate-lines'." (interactive) (setq truncate-lines (not truncate-lines)) ;; reposition so that user does not get confused (singular-reposition-point-and-window) ;; avoid calling `recenter' since it changes window layout more than ;; necessary (redraw-frame (selected-frame))) ;; this is not a buffer-local variable even if at first glance it seems ;; that it should be one. But if one changes buffer the contents of this ;; variable becomes irrelevant since the last command is no longer a ;; horizontal scroll command. The same is true for the initial value, so ;; we set it to nil. (defvar singular-scroll-previous-amount nil "Amount of previous horizontal scroll command.") (defun singular-scroll-right (&optional scroll-amount) "Scroll selected window SCROLL-AMOUNT columns right. SCROLL-AMOUNT defaults to amount of previous horizontal scroll command. If the command immediately preceding this command has not been a horizontal scroll command SCROLL-AMOUNT defaults to window width minus 2. Moves point to leftmost visible column." (interactive "P") ;; get amount to scroll (setq singular-scroll-previous-amount (cond (scroll-amount (prefix-numeric-value scroll-amount)) ((eq last-command 'singular-scroll-horizontal) singular-scroll-previous-amount) (t (- (frame-width) 2))) this-command 'singular-scroll-horizontal) ;; scroll (scroll-right singular-scroll-previous-amount) (move-to-column (window-hscroll)) ;; be careful where to place point. But what if `(current-column)' ;; equals, say, one? Well, we simply do not care about that case. ;; Should not happen to often. (if (eq (current-column) 0) (singular-prompt-skip-forward))) (defun singular-scroll-left (&optional scroll-amount) "Scroll selected window SCROLL-AMOUNT columns left. SCROLL-AMOUNT defaults to amount of previous horizontal scroll command. If the command immediately preceding this command has not been a horizontal scroll command SCROLL-AMOUNT defaults to window width minus 2. Moves point to leftmost visible column." (interactive "P") ;; get amount to scroll (setq singular-scroll-previous-amount (cond (scroll-amount (prefix-numeric-value scroll-amount)) ((eq last-command 'singular-scroll-horizontal) singular-scroll-previous-amount) (t (- (frame-width) 2))) this-command 'singular-scroll-horizontal) ;; scroll (scroll-left singular-scroll-previous-amount) (move-to-column (window-hscroll)) ;; be careful where to place point. But what if `(current-column)' ;; equals, say, one? Well, we simply do not care about that case. ;; Should not happen to often. (if (eq (current-column) 0) (singular-prompt-skip-forward))) (defun singular-beginning-of-line (arg) "Move point to the beginning of line, then skip past prompt, if any. If prefix argument is given the prompt is not skipped." (interactive "P") (beginning-of-line) (if (not arg) (singular-prompt-skip-forward))) (defun singular-load-file (file &optional noexpand) "Read a file into Singular (via '< \"FILE\";'). If optional argument NOEXPAND is non-nil, FILE is left as it is entered by the user, otherwise it is expanded using `expand-file-name'." (interactive "fLoad file: ") (let* ((filename (if noexpand file (expand-file-name file))) (string (concat "< \"" filename "\";")) (process (singular-process))) (singular-input-filter process string) (singular-send-string process string))) (defvar singular-load-library-history nil "History list for loading of Singular libraries. Is used by `singular-load-library'.") (defun singular-load-library (nonstdlib &optional file) "Read a Singular library (via 'LIB \"FILE\";'). If called interactively asks for the name of a standard Singular library. If called interactively with a prefix argument asks for a file name of a Singular library." (interactive "P") (let ((string (or file (if nonstdlib (read-file-name "Library file: ") (completing-read "Library: " singular-standard-libraries-alist nil nil nil 'singular-load-library-history)))) (process (singular-process))) (setq string (concat "LIB \"" string "\";")) (singular-input-filter process string) (singular-send-string process string))) ;;}}} ;;{{{ History (defcustom singular-history-ignoredups t "*If non-nil, do not add input matching the last on the input history." :type 'boolean :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) ;; this variable is used to set Comint's `comint-input-ring-size' (defcustom singular-history-size 64 "*Size of the input history. Changing this variable has no immediate effect even if one uses \\[customize] to do so. The new value will be used only in new Singular interactive mode buffers." :type 'integer :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) (defcustom singular-history-filter-regexp "\\`\\(..?\\|\\s *\\)\\'" "*Regular expression to filter strings *not* to insert in the input history. By default, input consisting of less than three characters and input consisting of white-space only is not inserted into the input history." :type 'regexp :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) (defcustom singular-history-explicit-file-name nil "*If non-nil, use this as file name to load and save the input history. If this variable equals nil, the `SINGULARHIST' environment variable is used to determine the file name. One should note that the input history is saved to file only on regular termination of Singular; that is, if one leaves Singular using the commands `quit\;' or `exit\;'." :type '(choice (const nil) file) :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) (defun singular-history-read () "Read the input history from file. If `singular-history-explicit-file-name' is non-nil, uses that as file name, otherwise tries environment variable `SINGULARHIST'. This function is called from `singular-exec' every time a new Singular process is started." (singular-debug 'interactive (message "Reading input ring")) (let ((comint-input-ring-file-name (or singular-history-explicit-file-name (getenv "SINGULARHIST")))) ;; `comint-read-input-ring' does nothing if ;; `comint-input-ring-file-name' equals nil (comint-read-input-ring t))) (defun singular-history-write () "Write back the input history to file. If `singular-history-explicit-file-name' is non-nil, uses that as file name, otherwise tries environment variable `SINGULARHIST'. This function is called either by `singular-exit-singular' or by `singular-exit-sentinel' every time a Singular process terminates regularly." (singular-debug 'interactive (message "Writing input ring back")) (let ((comint-input-ring-file-name (or singular-history-explicit-file-name (getenv "SINGULARHIST")))) ;; `comint-write-input-ring' does nothing if ;; `comint-input-ring-file-name' equals nil (comint-write-input-ring))) (defun singular-history-insert (input) "Insert string INPUT into the input history if necessary." (if (and (not (string-match singular-history-filter-regexp input)) (or (not singular-history-ignoredups) (not (ring-p comint-input-ring)) (ring-empty-p comint-input-ring) (not (string-equal (ring-ref comint-input-ring 0) input)))) (ring-insert comint-input-ring input)) (setq comint-input-ring-index nil)) (defun singular-history-init () "Initialize variables concerning the input history. This function is called at mode initialization time." (setq comint-input-ring-size singular-history-size)) ;;}}} ;;{{{ Simple section API for both Emacs and XEmacs ;; Note: ;; ;; Sections and simple sections are used to mark Singular's input and ;; output for further access. Here are some general notes on simple ;; sections. Sections are explained in the respective folding. ;; ;; In general, simple sections are more or less Emacs' overlays or XEmacs ;; extents, resp. But they are more than simply an interface to overlays ;; or extents. ;; ;; - Simple sections are non-empty portions of text. They are interpreted ;; as left-closed, right-opened intervals, i.e., the start point of a ;; simple sections belongs to it whereas the end point does not. ;; - Simple sections start and end at line borders only. ;; - Simple sections do not overlap. Thus, any point in the buffer may be ;; covered by at most one simple section. ;; - Besides from their start and their end, simple sections have some type ;; associated. ;; - Simple sections are realized using overlays (extents for XEmacs) ;; which define the start and, end, and type (via properties) of the ;; simple section. Actually, as a lisp object a simple section is ;; nothing else but the underlying overlay. ;; - There may be so-called clear simple sections. Clear simple sections ;; have not an underlying overlay. Instead, they start at the end of the ;; preceding non-clear simple section, end at the beginning of the next ;; non-clear simple section, and have the type defined by ;; `singular-simple-sec-clear-type'. Clear simple sections are ;; represented by nil. ;; - Buffer narrowing does not restrict the extent of completely or ;; partially inaccessible simple sections. But one should note that ;; some of the functions assume that there is no narrowing in ;; effect. ;; - After creation, simple sections are not modified any further. ;; - There is one nasty little corner case: what if a non-clear simple ;; section spans up to end of buffer? By definition, eob is not included ;; in that section since they are right-opened intervals. Most of the ;; functions react as if there is an imagenary empty clear simple section ;; at eob. ;; - Even though by now there are only two types of different simple ;; sections there may be an arbitrary number of them. Furthermore, ;; simple sections of different types may appear in arbitrary order. ;; ;; - In `singular-interactive-mode', the whole buffer is covered with ;; simple sections from the very beginning of the file up to the ;; beginning of the line containing the last input or output. The ;; remaining text up to `(point-max)' may be interpreted as covered by ;; one clear simple section. Thus, it is most reasonable to define ;; `input' to be the type of clear simple sections. (defvar singular-simple-sec-clear-type 'input "Type of clear simple sections. If nil no clear simple sections are used. One should not set this variable directly. Rather, one should customize `singular-section-face-alist'.") (defvar singular-simple-sec-last-end nil "Marker at the end of the last simple section. Should be initialized by `singular-simple-sec-init' before any calls to `singular-simple-sec-create' are done. Instead of accessing this variable directly one should use the macro `singular-simple-sec-last-end-position'. This variable is buffer-local.") (defun singular-simple-sec-init (pos) "Initialize variables belonging to simple section management. Creates the buffer-local marker `singular-simple-sec-last-end' and initializes it to POS. POS should be at beginning of a line. This function is called every time a new Singular session is started." (make-local-variable 'singular-simple-sec-last-end) (if (not (markerp singular-simple-sec-last-end)) (setq singular-simple-sec-last-end (make-marker))) (set-marker singular-simple-sec-last-end pos)) (defmacro singular-simple-sec-last-end-position () "Return the marker position of `singular-simple-sec-last-end'. This macro exists more or less for purposes of information hiding only." '(marker-position singular-simple-sec-last-end)) (defsubst singular-simple-sec-lookup-face (type) "Return the face to use for simple sections of type TYPE. This accesses the `singular-section-type-alist'. It does not harm if nil is associated with TYPE in that alist: In this case, this function will never be called for that TYPE." (cdr (assq type singular-section-face-alist))) ;; Note: ;; ;; The rest of the folding is either marked as ;; Emacs ;; or ;; XEmacs (singular-fset 'singular-simple-sec-create 'singular-emacs-simple-sec-create 'singular-xemacs-simple-sec-create) (singular-fset 'singular-simple-sec-at 'singular-emacs-simple-sec-at 'singular-xemacs-simple-sec-at) (singular-fset 'singular-simple-sec-start 'singular-emacs-simple-sec-start 'singular-xemacs-simple-sec-start) (singular-fset 'singular-simple-sec-end 'singular-emacs-simple-sec-end 'singular-xemacs-simple-sec-end) (singular-fset 'singular-simple-sec-type 'singular-emacs-simple-sec-type 'singular-xemacs-simple-sec-type) (singular-fset 'singular-simple-sec-before 'singular-emacs-simple-sec-before 'singular-xemacs-simple-sec-before) (singular-fset 'singular-simple-sec-start-at 'singular-emacs-simple-sec-start-at 'singular-xemacs-simple-sec-start-at) (singular-fset 'singular-simple-sec-end-at 'singular-emacs-simple-sec-end-at 'singular-xemacs-simple-sec-end-at) (singular-fset 'singular-simple-sec-in 'singular-emacs-simple-sec-in 'singular-xemacs-simple-sec-in) ;;}}} ;;{{{ Simple section API for Emacs (defsubst singular-emacs-simple-sec-start (simple-sec) "Return start of non-clear simple section SIMPLE-SEC. Narrowing has no effect on this function." (overlay-start simple-sec)) (defsubst singular-emacs-simple-sec-end (simple-sec) "Return end of non-clear simple section SIMPLE-SEC. Narrowing has no effect on this function." (overlay-end simple-sec)) (defsubst singular-emacs-simple-sec-type (simple-sec) "Return type of SIMPLE-SEC. Returns nil if SIMPLE-SEC happens to be an overlay but not a simple section. Narrowing has no effect on this function." (if simple-sec (overlay-get simple-sec 'singular-type) singular-simple-sec-clear-type)) (defsubst singular-emacs-simple-sec-before (pos) "Return simple section before buffer position POS. This is the same as `singular-simple-sec-at' except if POS falls on a section border. In this case `singular-simple-section-before' returns the previous simple section instead of the current one. If POS falls on beginning of buffer, the simple section at beginning of buffer is returned. Narrowing has no effect on this function." (singular-emacs-simple-sec-at (max 1 (1- pos)))) (defun singular-emacs-simple-sec-create (type end) "Create a new simple section of type TYPE. Creates the section from end of previous simple section up to the first beginning of line before END. That position should be larger than or equal to `singular-simple-sec-last-end'. Updates `singular-simple-sec-last-end'. Returns the new simple section or `empty' if no simple section has been created. Assumes that no narrowing is in effect." (let ((last-end (singular-simple-sec-last-end-position)) ;; `simple-sec' is the new simple section or `empty' simple-sec) ;; get beginning of line before END. At this point we need that there ;; are no restrictions. (setq end (let ((old-point (point))) (goto-char end) (beginning-of-line) (prog1 (point) (goto-char old-point)))) (cond ;; do not create empty sections ((eq end last-end) 'empty) ;; non-clear simple sections ((not (eq type singular-simple-sec-clear-type)) ;; if type has not changed we only have to extend the previous simple ;; section. If `last-end' happens to be 1 (meaning that we are ;; creating the first non-clear simple section in the buffer), then ;; `singular-simple-sec-before' returns nil, ;; `singular-simple-sec-type' returns the type of clear simple ;; sections that definitely does not equal TYPE, and a new simple ;; section is created as necessary. (setq simple-sec (singular-emacs-simple-sec-before last-end)) (if (eq type (singular-emacs-simple-sec-type simple-sec)) ;; move existing overlay (setq simple-sec (move-overlay simple-sec (overlay-start simple-sec) end)) ;; create new overlay (setq simple-sec (make-overlay last-end end)) ;; set type property (overlay-put simple-sec 'singular-type type) ;; set face (overlay-put simple-sec 'face (singular-simple-sec-lookup-face type)) ;; evaporate empty sections (overlay-put simple-sec 'evaporate t)) ;; update `singular-simple-sec-last-end' and return new simple ;; section (set-marker singular-simple-sec-last-end end) simple-sec) ;; clear simple sections (t ;; update `singular-simple-sec-last-end' and return nil (set-marker singular-simple-sec-last-end end) nil)))) (defun singular-emacs-simple-sec-start-at (pos) "Return start of clear simple section at position POS. Assumes the existence of an imagenary empty clear simple section if POS is at end of buffer and there is non-clear simple section immediately ending at POS. Assumes that no narrowing is in effect (since `previous-overlay-change' imlicitly does so)." ;; yes, this `(1+ pos)' is OK at eob for ;; `singular-emacs-simple-sec-before' as well as ;; `previous-overlay-change' (let ((previous-overlay-change-pos (1+ pos))) ;; this `while' loop at last will run into the end of the next ;; non-clear simple section or stop at bob. Since POS may be right at ;; the end of a previous non-clear location, we have to search at least ;; one time from POS+1 backwards. (while (not (or (singular-emacs-simple-sec-before previous-overlay-change-pos) (eq previous-overlay-change-pos 1))) (setq previous-overlay-change-pos (previous-overlay-change previous-overlay-change-pos))) previous-overlay-change-pos)) (defun singular-emacs-simple-sec-end-at (pos) "Return end of clear simple section at position POS. Assumes the existence of an imagenary empty clear simple section if POS is at end of buffer and there is non-clear simple section immediately ending at POS. Assumes that no narrowing is in effect (since `next-overlay-change' imlicitly does so)." (let ((next-overlay-change-pos (next-overlay-change pos))) ;; this `while' loop at last will run into the beginning of the next ;; non-clear simple section or stop at eob. Since POS may not be at ;; the beginning of a non-clear simple section we may start searching ;; immediately. (while (not (or (singular-emacs-simple-sec-at next-overlay-change-pos) (eq next-overlay-change-pos (point-max)))) (setq next-overlay-change-pos (next-overlay-change next-overlay-change-pos))) next-overlay-change-pos)) (defun singular-emacs-simple-sec-at (pos) "Return simple section at buffer position POS. Assumes the existence of an imagenary empty clear simple section if POS is at end of buffer and there is non-clear simple section immediately ending at POS. Narrowing has no effect on this function." ;; at eob, `overlays-at' always returns nil so everything is OK for this ;; case, too (let ((overlays (overlays-at pos)) simple-sec) ;; be careful, there may be other overlays! (while (and overlays (not simple-sec)) (if (singular-emacs-simple-sec-type (car overlays)) (setq simple-sec (car overlays))) (setq overlays (cdr overlays))) simple-sec)) (defun singular-emacs-simple-sec-in (beg end) "Return a list of all simple sections intersecting with the region from BEG to END. A simple section intersects the region if the section and the region have at least one character in common. The sections are returned with startpoints in increasing order and clear simple sections (that is, nil's) inserted as necessary. BEG is assumed to be less than or equal to END. The imagenary empty clear simple section at end of buffer is never included in the result. Narrowing has no effect on this function." (let (overlays overlay-cursor) (if (= beg end) ;; `overlays-in' seems not be correct with respect to this case nil ;; go to END since chances are good that the overlays come in correct ;; order, then (setq overlays (let ((old-point (point))) (goto-char end) (prog1 (overlays-in beg end) (goto-char old-point))) ;; now, turn overlays that are not simple sections into nils overlays (mapcar (function (lambda (overlay) (and (singular-emacs-simple-sec-type overlay) overlay))) overlays) ;; then, remove nils from list overlays (delq nil overlays) ;; now, we have to sort the list since documentation of `overlays-in' ;; does not state anything about the order the overlays are returned in overlays (sort overlays (function (lambda (a b) (< (overlay-start a) (overlay-start b)))))) ;; at last, we have the list of non-clear simple sections. Now, go and ;; insert clear simple sections as necessary. (if (null overlays) ;; if there are no non-clear simple sections at all there can be ;; only one large clear simple section '(nil) ;; we care about inside clear simple section first (setq overlay-cursor overlays) (while (cdr overlay-cursor) (if (eq (overlay-end (car overlay-cursor)) (overlay-start (cadr overlay-cursor))) (setq overlay-cursor (cdr overlay-cursor)) ;; insert nil (setcdr overlay-cursor (cons nil (cdr overlay-cursor))) (setq overlay-cursor (cddr overlay-cursor)))) ;; now, check BEG and END for clear simple sections (if (> (overlay-start (car overlays)) beg) (setq overlays (cons nil overlays))) ;; `overlay-cursor' still points to the end (if (< (overlay-end (car overlay-cursor)) end) (setcdr overlay-cursor (cons nil nil))) overlays)))) ;;}}} ;;{{{ Simple section API for XEmacs (defsubst singular-xemacs-simple-sec-start (simple-sec) "Return start of non-clear simple section SIMPLE-SEC. Narrowing has no effect on this function." (extent-start-position simple-sec)) (defsubst singular-xemacs-simple-sec-end (simple-sec) "Return end of non-clear simple section SIMPLE-SEC. Narrowing has no effect on this function." (extent-end-position simple-sec)) (defsubst singular-xemacs-simple-sec-type (simple-sec) "Return type of SIMPLE-SEC. Returns nil if SIMPLE-SEC happens to be an extent but not a simple section. Narrowing has no effect on this function." (if simple-sec (extent-property simple-sec 'singular-type) singular-simple-sec-clear-type)) (defsubst singular-xemacs-simple-sec-before (pos) "Return simple section before buffer position POS. This is the same as `singular-simple-sec-at' except if POS falls on a section border. In this case `singular-simple-section-before' returns the previous simple section instead of the current one. If POS falls on beginning of buffer, the simple section at beginning of buffer is returned. Narrowing has no effect on this function." (singular-xemacs-simple-sec-at (max 1 (1- pos)))) (defun singular-xemacs-simple-sec-create (type end) "Create a new simple section of type TYPE. Creates the section from end of previous simple section up to the first beginning of line before END. That position should be larger than or equal to `singular-simple-sec-last-end'. Updates `singular-simple-sec-last-end'. Returns the new simple section or `empty' if no simple section has been created. Assumes that no narrowing is in effect." (let ((last-end (singular-simple-sec-last-end-position)) ;; `simple-sec' is the new simple section or `empty' simple-sec) ;; get beginning of line before END. At this point we need that there ;; are no restrictions. (setq end (let ((old-point (point))) (goto-char end) (beginning-of-line) (prog1 (point) (goto-char old-point)))) (cond ;; do not create empty sections ((eq end last-end) 'empty) ;; non-clear simple sections ((not (eq type singular-simple-sec-clear-type)) ;; if type has not changed we only have to extend the previous simple ;; section. If `last-end' happens to be 1 (meaning that we are ;; creating the first non-clear simple section in the buffer), then ;; `singular-simple-sec-before' returns nil, ;; `singular-simple-sec-type' returns the type of clear simple ;; sections that definitely does not equal TYPE, and a new simple ;; section is created as necessary. (setq simple-sec (singular-xemacs-simple-sec-before last-end)) (if (eq type (singular-xemacs-simple-sec-type simple-sec)) ;; move existing extent (setq simple-sec (set-extent-endpoints simple-sec (extent-start-position simple-sec) end)) ;; create new extent (setq simple-sec (make-extent last-end end)) ;; set type property (set-extent-property simple-sec 'singular-type type) ;; set face. In contrast to Emacs, we do not need to set somethin ;; like `evaporate'. `detachable' is set by XEmacs by default. (set-extent-property simple-sec 'face (singular-simple-sec-lookup-face type))) ;; update `singular-simple-sec-last-end' and return new simple ;; section (set-marker singular-simple-sec-last-end end) simple-sec) ;; clear simple sections (t ;; update `singular-simple-sec-last-end' and return nil (set-marker singular-simple-sec-last-end end) nil)))) (defun singular-xemacs-simple-sec-start-at (pos) "Return start of clear simple section at position POS. Assumes the existence of an imagenary empty clear simple section if POS is at end of buffer and there is non-clear simple section immediately ending at POS. Assumes that no narrowing is in effect (since `previous-extent-change' imlicitly does so)." ;; get into some hairy details at end of buffer. Look if there is a ;; non-clear simple section immediately ending at end of buffer and ;; return the start of the imagenary empty clear simple section in that ;; case. If buffer is empty this test fails since ;; `singular-xemacs-simple-sec-before' (corretly) returns nil. But in ;; that case the following loop returns the correct result. (if (and (eq pos (point-max)) (singular-xemacs-simple-sec-before pos)) pos (let ((previous-extent-change-pos (min (1+ pos) (point-max)))) ;; this `while' loop at last will run into the end of the next ;; non-clear simple section or stop at bob. Since POS may be right at ;; the end of a previous non-clear location, we have to search at least ;; one time from POS+1 backwards. (while (not (or (singular-xemacs-simple-sec-before previous-extent-change-pos) (eq previous-extent-change-pos 1))) (setq previous-extent-change-pos (previous-extent-change previous-extent-change-pos))) previous-extent-change-pos))) (defun singular-xemacs-simple-sec-end-at (pos) "Return end of clear simple section at position POS. Assumes the existence of an imagenary empty clear simple section if POS is at end of buffer and there is non-clear simple section immediately ending at POS. Assumes that no narrowing is in effect (since `next-extent-change' imlicitly does so)." (let ((next-extent-change-pos (next-extent-change pos))) ;; this `while' loop at last will run into the beginning of the next ;; non-clear simple section or stop at eob. Since POS may not be at ;; the beginning of a non-clear simple section we may start searching ;; immediately. (while (not (or (singular-xemacs-simple-sec-at next-extent-change-pos) (eq next-extent-change-pos (point-max)))) (setq next-extent-change-pos (next-extent-change next-extent-change-pos))) next-extent-change-pos)) (defun singular-xemacs-simple-sec-at (pos) "Return simple section at buffer position POS. Assumes the existence of an imagenary empty clear simple section if POS is at end of buffer and there is non-clear simple section immediately ending at POS. Narrowing has no effect on this function." ;; at eob, `map-extent' always returns nil so everything is OK for this ;; case, too. Do not try to use `extent-at' at this point. `extent-at' ;; does not return extents outside narrowed text. (map-extents (function (lambda (ext args) ext)) nil pos pos nil nil 'singular-type)) (defun singular-xemacs-simple-sec-in (beg end) "Return a list of all simple sections intersecting with the region from BEG to END. A simple section intersects the region if the section and the region have at least one character in common. The sections are returned with startpoints in increasing order and clear simple sections (that is, nil's) inserted as necessary. BEG is assumed to be less than or equal to END. The imagenary empty clear simple section at end of buffer is never included in the result. Narrowing has no effect on this function." (let (extents extent-cursor) (if (= beg end) ;; `mapcar-extents' may return some extents in this case, so ;; exclude it nil ;; OK, that's a little bit easier than for Emacs ... (setq extents (mapcar-extents 'identity nil nil beg end nil 'singular-type)) ;; now we have the list of non-clear simple sections. Go and ;; insert clear simple sections as necessary. (if (null extents) ;; if there are no non-clear simple sections at all there can be ;; only one large clear simple section '(nil) ;; we care about inside clear simple section first (setq extent-cursor extents) (while (cdr extent-cursor) (if (eq (extent-end-position (car extent-cursor)) (extent-start-position (cadr extent-cursor))) (setq extent-cursor (cdr extent-cursor)) ;; insert nil (setcdr extent-cursor (cons nil (cdr extent-cursor))) (setq extent-cursor (cddr extent-cursor)))) ;; now, check BEG and END for clear simple sections (if (> (extent-start-position (car extents)) beg) (setq extents (cons nil extents))) ;; `extent-cursor' still points to the end (if (< (extent-end-position (car extent-cursor)) end) (setcdr extent-cursor (cons nil nil))) extents)))) ;;}}} ;;{{{ Section API ;; Note: ;; ;; Sections are built on simple sections. Their purpose is to cover the ;; difference between clear and non-clear simple sections. ;; ;; - Sections consist of a simple section, its type, and its start and end ;; points. This is redundant information only in the case of non-clear ;; simple section. ;; - Sections are read-only objects, neither are they modified nor are they ;; created. ;; - Buffer narrowing does not restrict the extent of completely or ;; partially inaccessible sections. In contrast to simple sections the ;; functions concerning sections do not assume that there is no narrowing ;; in effect. However, most functions provide an optional argument ;; RESTRICTED that restricts the start and end point of the returned ;; sections to the currently active restrictions. Of course, that does ;; not affect the range of the underlying simple sections, only the ;; additional start and end points being returned. One should note that ;; by restricting sections one may get empty sections, that is, sections ;; for which the additional start and end point are equal. ;; - In many cases it is not desirable that the user operates on sections ;; which are not completely accessible. To check that a section is ;; completely accessible the `singular-section-check' function should be ;; used. ;; - Sections are independent from implementation dependencies. There are ;; no different versions of the functions for Emacs and XEmacs. ;; - Whenever possible, one should not access simple section directly. ;; Instead, one should use the section API. (defcustom singular-section-face-alist '((input . nil) (output . singular-section-output-face)) "*Alist that maps section types to faces. Should be a list consisting of elements (SECTION-TYPE . FACE-OR-NIL), where SECTION-TYPE is either `input' or `output'. At any time, the Singular interactive mode buffer is completely covered by sections of two different types: input sections and output sections. This variable determines which faces are used to display the different sections. If for type SECTION-TYPE the value FACE-OR-NIL is a face it is used to display the contents of all sections of that particular type. If instead FACE-OR-NIL equals nil sections of that type become so-called clear sections. The content of clear sections is displayed as regular text, with no faces at all attached to them. Some notes and restrictions on this variable (believe them or not): o Changing this variable during a Singular session may cause unexpected results (but not too serious ones, though). o There may be only one clear section type defined at a time. o Choosing clear input sections is a good idea. o Choosing clear output sections is a bad idea. o Consequence: Not to change this variable is a good idea." ;; to add new section types, simply extend the `list' widget. ;; The rest should work unchanged. Do not forget to update docu. :type '(list (cons :tag "Input sections" (const :format "" input) (choice :format "Choose either clear or non-clear input sections. For non-clear sections, select or modify a face (preferably `singular-section-input-face') used to display the sections. %[Choice%] %v " (const :tag "Clear sections" nil) (face :tag "Non-clear sections"))) (cons :tag "Output sections" (const :format "" output) (choice :format "Choose either clear or non-clear ouput sections. For non-clear sections, select or modify a face (preferably `singular-section-output-face') used to display the sections. %[Choice%] %v " (const :tag "Clear sections" nil) (face :tag "Non-clear sections")))) :initialize 'custom-initialize-reset ;; this function checks for validity (only one clear section ;; type) and sets `singular-simple-sec-clear-type' accordingly. ;; In case of an error, nothing is set or modified. :set (function (lambda (var value) (let* ((cdrs-with-nils (mapcar 'cdr value)) (cdrs-without-nils (delq nil (copy-sequence cdrs-with-nils)))) (if (> (- (length cdrs-with-nils) (length cdrs-without-nils)) 1) (error "Only one clear section type allowed (see `singular-section-face-alist')") (set-default var value) (setq singular-simple-sec-clear-type (car (rassq nil value))))))) :group 'singular-faces :group 'singular-sections-and-foldings) (defface singular-section-input-face '((t nil)) "*Face to use for input sections. It may be not sufficient to modify this face to change the appearance of input sections. See `singular-section-face-alist' for more information." :group 'singular-faces :group 'singular-sections-and-foldings) (defface singular-section-output-face '((t (:bold t))) "*Face to use for output sections. It may be not sufficient to modify this face to change the appearance of output sections. See `singular-section-face-alist' for more information." :group 'singular-faces :group 'singular-sections-and-foldings) (defsubst singular-section-create (simple-sec type start end) "Create and return a new section." (vector simple-sec type start end)) (defsubst singular-section-simple-sec (section) "Return underlying simple section of SECTION." (aref section 0)) (defsubst singular-section-type (section) "Return type of SECTION." (aref section 1)) (defsubst singular-section-start (section) "Return start of SECTION." (aref section 2)) (defsubst singular-section-end (section) "Return end of SECTION." (aref section 3)) (defun singular-section-at (pos &optional restricted) "Return section at position POS. Returns section intersected with current restriction if RESTRICTED is non-nil." (let* ((simple-sec (singular-simple-sec-at pos)) (type (singular-simple-sec-type simple-sec)) start end) (if simple-sec (setq start (singular-simple-sec-start simple-sec) end (singular-simple-sec-end simple-sec)) (save-restriction (widen) (setq start (singular-simple-sec-start-at pos) end (singular-simple-sec-end-at pos)))) (cond ;; not restricted first ((not restricted) (singular-section-create simple-sec type start end)) ;; restricted and degenerated ((and restricted (< end (point-min))) (singular-section-create simple-sec type (point-min) (point-min))) ;; restricted and degenerated ((and restricted (> start (point-max))) (singular-section-create simple-sec type (point-max) (point-max))) ;; restricted but not degenrated (t (singular-section-create simple-sec type (max start (point-min)) (min end (point-max))))))) (defun singular-section-before (pos &optional restricted) "Return section before position POS. This is the same as `singular-section-at' except if POS falls on a section border. In this case `singular-section-before' returns the previous section instead of the current one. If POS falls on beginning of buffer, the section at beginning of buffer is returned. Returns section intersected with current restriction if RESTRICTED is non-nil." (singular-section-at (max 1 (1- pos)) restricted)) (defun singular-section-in (beg end &optional restricted) "Return a list of all sections intersecting with the region from BEG to END. A section intersects with the region if the section and the region have at least one character in common. The sections are returned in increasing order. If optional argument RESTRICTED is non-nil only sections which are completely in the intersection of the region and the current restriction are returned." ;; exchange BEG and END if necessary as a special service to our users (let* ((reg-beg (min beg end)) (reg-end (max beg end)) ;; we need these since we widen the buffer later on (point-min (point-min)) (point-max (point-max)) simple-sections) (if (and restricted (or (> reg-beg point-max) (< reg-end point-min))) ;; degenerate restrictions nil ;; do the intersection if necessary and get simple sections (setq reg-beg (if restricted (max reg-beg point-min) reg-beg) reg-end (if restricted (min reg-end point-max) reg-end) simple-sections (singular-simple-sec-in reg-beg reg-end)) ;; we still have REG-BEG <= REG-END in any case. SIMPLE-SECTIONS ;; contains the list of simple sections intersecting with the region ;; from REG-BEG and REG-END. (if (null simple-sections) nil ;; and here we even have REG-BEG < REG-END (save-restriction (widen) ;; get sections intersecting with the region from REG-BEG to ;; REG-END (let* ((sections (singular-section-in-internal simple-sections reg-beg reg-end)) first-section-start last-section-end) (if (not restricted) sections (setq first-section-start (singular-section-start (car sections)) last-section-end (singular-section-end (car (last sections)))) ;; popping off first element is easy ... (if (< first-section-start point-min) (setq sections (cdr sections))) ;; ... but last element is harder to pop off (cond (;; no elements left (null sections) nil) (;; one element left (null (cdr sections)) (if (> last-section-end point-max) nil sections)) (;; more than one element left t (if (> last-section-end point-max) (setcdr (last sections 2) nil)) sections))))))))) (defun singular-section-in-internal (simple-sections reg-beg reg-end) "Create a list of sections from SIMPLE-SECTIONS. This is the back-end for `singular-section-in'. First simple section should be such that it contains REG-BEG, last simple section should be such that it contains or ends at REG-END. These arguments are used to find the start resp. end of clear simple sections of terminal clear simple sections in SIMPLE-SECTIONS. Assumes that REG-BEG < REG-END. Assumes that SIMPLE-SECTIONS is not empty. Assumes that no narrowing is in effect." (let* (;; we pop off the extra nil at the end of the loop (sections (cons nil nil)) (sections-end sections) (simple-section (car simple-sections)) type start end) ;; first, get unrestricted start (setq start (if simple-section (singular-simple-sec-start simple-section) ;; here we need that no narrowing is in effect (singular-simple-sec-start-at reg-beg))) ;; loop through all simple sections but last (while (cdr simple-sections) (setq simple-section (car simple-sections) type (singular-simple-sec-type simple-section) end (if simple-section (singular-simple-sec-end simple-section) (singular-simple-sec-start (cadr simple-sections))) ;; append the new section to `sections-end' sections-end (setcdr sections-end (cons (singular-section-create simple-section type start end) nil)) ;; get next simple section and its start simple-sections (cdr simple-sections) start end)) ;; care about last simple section (setq simple-section (car simple-sections) type (singular-simple-sec-type simple-section) end (if simple-section (singular-simple-sec-end simple-section) ;; the `1-' is OK since REG-BEG < REG-END. ;; here we need that no narrowing is in effect (singular-simple-sec-end-at (1- reg-end)))) (setcdr sections-end (cons (singular-section-create simple-section type start end) nil)) ;; we should not forget to pop off our auxilliary cons-cell (cdr sections))) (defun singular-section-mapsection (func sections &optional type-filter negate-filter) "Apply FUNC to each section in SECTIONS, and make a list of the results. If optional argument TYPE-FILTER is non-nil it should be a list of section types. FUNC is then applied only to those sections with type occuring in TYPE-FILTER. If in addition optional argument NEGATE-FILTER is non-nil FUNC is applied only to those sections with type not occuring in TYPE-FILTER. In any case the length of the list this function returns equals the number of sections actually processed." (if (not type-filter) (mapcar func sections) ;; copy the list first (let ((sections (copy-sequence sections))) ;; filter elements and turn them to t's (setq sections (mapcar (function (lambda (section) ;; that strange expression evaluates to t iff the ;; section should be removed. The `not' is to ;; canonize boolean values to t or nil, resp. (or (eq (not (memq (singular-section-type section) type-filter)) (not negate-filter)) section))) sections) ;; remove t's now sections (delq t sections)) ;; call function for remaining sections (mapcar func sections)))) ;;}}} ;;{{{ Section miscellaneous (defun singular-section-check (section &optional no-error) "Check whether SECTION is completely accessible and return t if so. If otherwise SECTION is restricted either in part or as a whole, this function fails with an error or returns nil if optional argument NO-ERROR is non-nil." (cond ((and (>= (singular-section-start section) (point-min)) (<= (singular-section-end section) (point-max))) t) (no-error nil) (t (error "section is restricted either in part or as a whole")))) (defun singular-section-to-string (section &optional raw) "Get contents of SECTION as a string. Returns text between start and end of SECTION. Removes prompts from section contents unless optional argument RAW is non-nil. Narrowing has no effect on this function." (save-restriction (widen) (let ((string (buffer-substring (singular-section-start section) (singular-section-end section)))) (if raw string (singular-prompt-remove-string string))))) ;;}}} ;;{{{ Section miscellaneous interactive (defun singular-section-goto-beginning () "Move point to beginning of current section." (interactive) (goto-char (singular-section-start (singular-section-at (point)))) (singular-keep-region-active)) (defun singular-section-goto-end () "Move point to end of current section." (interactive) (goto-char (singular-section-end (singular-section-at (point)))) (singular-keep-region-active)) (defun singular-section-backward (n) "Move backward until encountering the beginning of a section. With argument, do this that many times. With N less than zero, call `singular-section-forward' with argument -N." (interactive "p") (while (> n 0) (goto-char (singular-section-start (singular-section-before (point)))) (setq n (1- n))) (if (< n 0) (singular-section-forward (- n)) (singular-keep-region-active))) (defun singular-section-forward (n) "Move forward until encountering the end of a section. With argument, do this that many times. With N less than zero, call `singular-section-backward' with argument -N." (interactive "p") (while (> n 0) (goto-char (singular-section-end (singular-section-at (point)))) (setq n (1- n))) (if (< n 0) (singular-section-backward (- n)) (singular-keep-region-active))) (defun singular-section-kill (section &optional raw no-error) "Kill SECTION. Puts the contents of SECTION into the kill ring. Removes prompts from contents unless optional argument RAW is non-nil. If called interactively, kills section point currently is in. Does a raw section kill if called with a prefix argument, otherwise strips prompts. Does not kill sections that are restricted either in part or as a whole. Rather fails with an error in such cases or silently fails if optional argument NO-ERROR is non-nil." (interactive (list (singular-section-at (point)) current-prefix-arg nil)) (when (singular-section-check section no-error) (kill-new (singular-section-to-string section raw)) (delete-region (singular-section-start section) (singular-section-end section)))) ;;}}} ;;{{{ Folding sections for both Emacs and XEmacs (defcustom singular-folding-ellipsis "Singular I/O ..." "*Ellipsis to show for folded input or output. Changing this variable has an immediate effect only if one uses \\[customize] to do so. However, even then it may be necessary to refresh display completely (using \\[recenter], for example) for the new settings to be visible." :type 'string :initialize 'custom-initialize-default :set (function (lambda (var value) ;; set in all singular buffers (singular-map-buffer 'singular-folding-set-ellipsis value) (set-default var value))) :group 'singular-sections-and-foldings) (defcustom singular-folding-line-move-ignore-folding t "*If non-nil, ignore folded sections when moving point up or down. This variable is used to initialize `line-move-ignore-invisible'. However, documentation states that setting `line-move-ignore-invisible' to a non-nil value may result in a slow-down when moving the point up or down. One should try to set this variable to nil if point motion seems too slow. Changing this variable has an immediate effect only if one uses \\[customize] to do so." :type 'boolean :initialize 'custom-initialize-default :set (function (lambda (var value) ;; set in all singular buffers (singular-map-buffer 'set 'line-move-ignore-invisible value) (set-default var value))) :group 'singular-sections-and-foldings) (defun singular-folding-set-ellipsis (ellipsis) "Set ellipsis to show for folded input or output in current buffer." (cond ;; Emacs ((eq singular-emacs-flavor 'emacs) (setq buffer-display-table (or (copy-sequence standard-display-table) (make-display-table))) (set-display-table-slot buffer-display-table 'selective-display (vconcat ellipsis))) ;; XEmacs (t (set-glyph-image invisible-text-glyph ellipsis (current-buffer))))) (defun singular-folding-init () "Initializes folding of sections for the current buffer. That includes setting `buffer-invisibility-spec' and the ellipsis to show for hidden text. This function is called at mode initialization time." ;; initialize `buffer-invisibility-spec' first (let ((singular-invisibility-spec (cons 'singular-interactive-mode t))) (if (and (listp buffer-invisibility-spec) (not (member singular-invisibility-spec buffer-invisibility-spec))) (setq buffer-invisibility-spec (cons singular-invisibility-spec buffer-invisibility-spec)) (setq buffer-invisibility-spec (list singular-invisibility-spec)))) ;; ignore invisible lines on movements (set (make-local-variable 'line-move-ignore-invisible) singular-folding-line-move-ignore-folding) ;; now for the ellipsis (singular-folding-set-ellipsis singular-folding-ellipsis)) (defun singular-folding-fold (section &optional no-error) "Fold section SECTION if it is not already folded. Does not fold sections that do not end in a newline or that are restricted either in part or as a whole. Rather fails with an error in such cases or silently fails if optional argument NO-ERROR is non-nil. This is for safety only: In both cases the result may be confusing to the user." (let* ((start (singular-section-start section)) (end (singular-section-end section))) (cond ((not (singular-section-check section no-error)) nil) ((not (eq (char-before end) ?\n)) (unless no-error (error "Section does not end in a newline"))) ((not (singular-folding-foldedp section)) ;; fold but only if not already folded (singular-folding-fold-internal section))))) (defun singular-folding-unfold (section &optional no-error invisibility-overlay-or-extent) "Unfold section SECTION if it is not already unfolded. Does not unfold sections that are restricted either in part or as a whole. Rather fails with an error in such cases or silently fails if optional argument NO-ERROR is non-nil. This is for safety only: The result may be confusing to the user. If optional argument INVISIBILITY-OVERLAY-OR-EXTENT is non-nil it should be the invisibility overlay or extent, respectively, of the section to unfold." (let* ((start (singular-section-start section)) (end (singular-section-end section))) (cond ((not (singular-section-check section no-error)) nil) ((or invisibility-overlay-or-extent (setq invisibility-overlay-or-extent (singular-folding-foldedp section))) ;; unfold but only if not already unfolded (singular-folding-unfold-internal section invisibility-overlay-or-extent))))) (defun singular-folding-fold-at-point () "Fold section point currently is in. Does not fold sections that do not end in a newline or that are restricted either in part or as a whole. Rather fails with an error in such cases." (interactive) (singular-folding-fold (singular-section-at (point)))) (defun singular-folding-unfold-at-point () "Unfold section point currently is in. Does not unfold sections that are restricted either in part or as a whole. Rather fails with an error in such cases." (interactive) (singular-folding-unfold (singular-section-at (point)))) (defun singular-folding-fold-latest-output () "Fold latest output section. Does not fold sections that do not end in a newline or that are restricted either in part or as a whole. Rather fails with an error in such cases." (interactive) (singular-folding-fold (singular-latest-output-section))) (defun singular-folding-unfold-latest-output () "Unfolds latest output section. Does not unfold sections that are restricted either in part or as a whole. Rather fails with an error in such cases." (interactive) (singular-folding-unfold (singular-latest-output-section))) (defun singular-folding-fold-all-output () "Fold all complete, unfolded output sections. That is, all output sections that are not restricted in part or as a whole and that end in a newline." (interactive) (singular-section-mapsection (function (lambda (section) (singular-folding-fold section t))) (singular-section-in (point-min) (point-max) t) '(output))) (defun singular-folding-unfold-all-output () "Unfold all complete, folded output sections. That is, all output sections that are not restricted in part or as a whole." (interactive) (singular-section-mapsection (function (lambda (section) (singular-folding-unfold section t))) (singular-section-in (point-min) (point-max) t) '(output))) (defun singular-folding-toggle-fold-at-point-or-all (&optional arg) "Fold or unfold section point currently is in or all output sections. Without prefix argument, folds unfolded sections and unfolds folded sections. With prefix argument, folds all output sections if argument is positive, otherwise unfolds all output sections. Does neither fold nor unfold sections that do not end in a newline or that are restricted either in part or as a whole. Rather fails with an error in such cases." (interactive "P") (cond ((not arg) ;; fold or unfold section at point (let* ((section (singular-section-at (point))) (invisibility-overlay-or-extent (singular-folding-foldedp section))) (if invisibility-overlay-or-extent (singular-folding-unfold section nil invisibility-overlay-or-extent) (singular-folding-fold section)))) ((> (prefix-numeric-value arg) 0) (singular-folding-fold-all-output)) (t (singular-folding-unfold-all-output)))) (defun singular-folding-toggle-fold-latest-output (&optional arg) "Fold or unfold latest output section. Folds unfolded sections and unfolds folded sections. Does neither fold nor unfold sections that do not end in a newline or that are restricted either in part or as a whole. Rather fails with an error in such cases." (interactive) (let* ((section (singular-latest-output-section)) (invisibility-overlay-or-extent (singular-folding-foldedp section))) (if invisibility-overlay-or-extent (singular-folding-unfold section nil invisibility-overlay-or-extent) (singular-folding-fold section)))) ;; Note: ;; ;; The rest of the folding is either marked as ;; Emacs ;; or ;; XEmacs (singular-fset 'singular-folding-fold-internal 'singular-emacs-folding-fold-internal 'singular-xemacs-folding-fold-internal) (singular-fset 'singular-folding-unfold-internal 'singular-emacs-folding-unfold-internal 'singular-xemacs-folding-unfold-internal) (singular-fset 'singular-folding-foldedp 'singular-emacs-folding-foldedp-internal 'singular-xemacs-folding-foldedp-internal) ;;}}} ;;{{{ Folding sections for Emacs ;; Note: ;; ;; For Emacs, we use overlays to hide text (so-called "invisibility ;; overlays"). In addition to their `invisible' property, they have the ;; `singular-invisible' property set. Setting the intangible property does ;; not work very well for Emacs. We use the variable ;; `line-move-ignore-invisible' which works quite well. (defun singular-emacs-folding-fold-internal (section) "Fold section SECTION. SECTION should end in a newline. That terminal newline is not folded or otherwise ellipsis does not appear. SECTION should be unfolded." (let* ((start (singular-section-start section)) ;; do not make trailing newline invisible (end (1- (singular-section-end section))) invisibility-overlay) ;; create new overlay and add properties (setq invisibility-overlay (make-overlay start end)) ;; mark them as invisibility overlays (overlay-put invisibility-overlay 'singular-invisible t) ;; set invisible properties (overlay-put invisibility-overlay 'invisible 'singular-interactive-mode) ;; evaporate empty invisibility overlays (overlay-put invisibility-overlay 'evaporate t))) (defun singular-emacs-folding-unfold-internal (section &optional invisibility-overlay) "Unfold section SECTION. SECTION should be folded. If optional argument INVISIBILITY-OVERLAY is non-nil it should be the invisibility overlay of the section to unfold." (let ((invisibility-overlay (or invisibility-overlay (singular-emacs-folding-foldedp-internal section)))) ;; to keep number of overlays low we delete it (delete-overlay invisibility-overlay))) (defun singular-emacs-folding-foldedp-internal (section) "Returns non-nil iff SECTION is folded. More specifically, returns the invisibility overlay if there is one. Narrowing has no effect on this function." (let* ((start (singular-section-start section)) (overlays (overlays-at start)) invisibility-overlay) ;; check for invisibility overlay (while (and overlays (not invisibility-overlay)) (if (overlay-get (car overlays) 'singular-invisible) (setq invisibility-overlay (car overlays)) (setq overlays (cdr overlays)))) invisibility-overlay)) ;;}}} ;;{{{ Folding sections for XEmacs ;; Note: ;; ;; For XEmacs, we use extents to hide text (so-called "invisibility ;; extents"). In addition to their `invisible' property, they have the ;; `singular-invisible' property set. To ignore invisible text we use the ;; variable `line-move-ignore-invisible' which works quite well. (defun singular-xemacs-folding-fold-internal (section) "Fold section SECTION. SECTION should end in a newline. That terminal newline is not folded or otherwise ellipsis does not appear. SECTION should be unfolded." (let* ((start (singular-section-start section)) ;; do not make trailing newline invisible (end (1- (singular-section-end section))) invisibility-extent) ;; create new extent and add properties (setq invisibility-extent (make-extent start end)) ;; mark them as invisibility extents (set-extent-property invisibility-extent 'singular-invisible t) ;; set invisible properties (set-extent-property invisibility-extent 'invisible 'singular-interactive-mode))) (defun singular-xemacs-folding-unfold-internal (section &optional invisibility-extent) "Unfold section SECTION. SECTION should be folded. If optional argument INVISIBILITY-EXTENT is non-nil it should be the invisibility extent of the section to unfold." (let ((invisibility-extent (or invisibility-extent (singular-xemacs-folding-foldedp-internal section)))) ;; to keep number of extents low we delete it (delete-extent invisibility-extent))) (defun singular-xemacs-folding-foldedp-internal (section) "Returns non-nil iff SECTION is folded. More specifically, returns the invisibility extent if there is one. Narrowing has no effect on this function." ;; do not try to use `extent-at' at this point. `extent-at' does not ;; return extents outside narrowed text. (let* ((start (singular-section-start section)) (invisibility-extent (map-extents (function (lambda (ext args) ext)) nil start start nil nil 'singular-invisible))) invisibility-extent)) ;;}}} ;;{{{ Online help ;; Note: ;; ;; Catching user's help commands to Singular and translating them to calls ;; to `info' is quite a difficult task due to the asynchronous nature of ;; communication with Singular. We use an heuristic approach which should ;; work in most cases: ;; ;; - `singular-help-pre-input-filter' scans user's input for help commands. ;; If user issues a help command the filter sets a time stamp and passes ;; the input unchanged to Singular. ;; - Singular receives the help command and barfs that it could not process ;; it. We call that error message "Singular's response". That response ;; in particular contains the help topic the user requested. If the ;; response for some reasons is not recognized and filtered in the later ;; steps the user gets some reasonable response on her command that way. ;; - `singular-help-pre-output-filter' on each output from Singular checks ;; (using the time stamp set by `singular-help-pre-input-filter') whether ;; the user issued a help command at most one second ago. If so, ;; `singular-help-pre-output-filter' starts checking Singular's output ;; for the response on the help command. If it finds one it remembers ;; the help topic in `singular-help-topic' and removes the response from ;; Singular's output. ;; There is some extra magic built into the filter to handle responses ;; from Singular which are received by emacs not in one string but in ;; more than one piece (we call that pending output). ;; - As the last step step of this procedure, `singular-post-output-filter' ;; fires up an Info buffer using `singular-help' if the variable ;; `singular-help-topic' is non-nil. This step is separated from the ;; previous one since joining both leads to some trouble in point ;; management. This is mainly due to the fact that `singular-help' opens ;; a new window. ;; ;; To show some online help, the online help manual has to be available, of ;; course. There is a number of possibilites for the user to set the file ;; name of the manual explicitly, as described in the documentation string ;; to `singular-help'. But in general the file name should be recognized ;; automatically by Singular interactive mode. For that to work, Singular ;; prints the file name when it comes up and option `--emacs' is specified. ;; This is recognized by `singular-scan-header-pre-output-filter' which ;; sets the variable `singular-help-file-name' accordingly. For more ;; information one should refer to the `Header scanning ...' folding. ;; ;; Another variable which needs to be set for proper operation is ;; `singular-help-topics-alist' for completion of help topics and for ;; recognition of help topics around point. It is no error for this ;; variable not to be set: simply the features do not work then. ;; this `require' is necessary since we use functions from the Info package ;; which are not declared as `autoload' (require 'info) (defcustom singular-help-same-window 'default "*Specifies how to open the window for Singular online help. If this variable equals t, Singular online help comes up in the selected window. If this variable equals nil, Singular online help comes up in another window. If this variable equals neither t nor nil, the standard Emacs behaviour to open the Info buffer is adopted (which very much depends on the settings of `same-window-buffer-names')." :initialize 'custom-initialize-default :type '(choice (const :tag "This window" t) (const :tag "Other window" nil) (const :tag "Default" default)) :group 'singular-interactive-miscellaneous) (defcustom singular-help-explicit-file-name nil "*Specifies the file name of the Singular online manual. If non-nil, used as file name of the Singular online manual. This variable should be customized only if all other attempts of Singular interactive mode fail to determine the file name of the Singular online manual. For more information one should refer to the `singular-help' function." :initialize 'custom-initialize-default :type '(choice (const nil) file) :group 'singular-interactive-miscellaneous) (defvar singular-help-file-name nil "File name of the Singular online manual. This variable should not be modified by the user. This variable is buffer-local.") (defconst singular-help-fall-back-file-name "singular.hlp" "Fall-back file name of the Singular online manual. This variable is used if the file name of the Singular online manual cannot be determined otherwise.") (defvar singular-help-time-stamp '(0 0) "The time stamp that is set when the user issues a help command. This variable is buffer-local.") (defvar singular-help-response-pending nil "If non-nil, Singular's response has not been completely received. This variable is buffer-local.") (defvar singular-help-topic nil "If non-nil, contains help topic to show in post output filter. This variable is buffer-local.") (defconst singular-help-command-regexp "^\\s-*\\(help\\|\?\\)" "Regular expression to match Singular help commands.") (defconst singular-help-response-line-1 "^// \\*\\* Your help command could not be executed\\. Use\n" "Regular expression that matches the first line of Singular's response.") (defconst singular-help-response-line-2 "^// \\*\\* C-h C-s \\(.*\\)\n" "Regular expression that matches the second line of Singular's response. First subexpression matches help topic.") (defconst singular-help-response-line-3 "^// \\*\\* to enter the Singular online help\\. For general\n" "Regular expression that matches the third line of Singular's response.") (defconst singular-help-response-line-4 "^// \\*\\* information on Singular running under Emacs, type C-h m\\.\n" "Regular expression that matches the fourth line of Singular's response.") (defun singular-help-pre-input-filter (input) "Check user's input for help commands. Sets time stamp if one is found. Passes user's input on to Singular unchanged." (if (string-match singular-help-command-regexp input) (setq singular-help-time-stamp (current-time))) ;; return nil so that input passes unchanged nil) (defun singular-help-pre-output-filter (output) "Check for Singular's response on a help command. Removes it and sets `singular-help-topic' accordingly." ;; check first ;; - whether a help statement has been issued at most one second ago, or ;; - whether there is a pending response. ;; Only if one of these conditions is met we go on and check text for a ;; response on a help command. Checking uncoditionally every piece of ;; output would be far too expensive. ;; If check fails nil is returned, what is exactly what we need for the ;; filter. (if (or (= (cadr (current-time)) (cadr singular-help-time-stamp)) singular-help-response-pending) ;; if response is pending for more than five seconds, give up (if (and singular-help-response-pending (> (singular-time-stamp-difference (current-time) singular-help-time-stamp) 5)) ;; this command returns nil, what is exactly what we need for the filter (setq singular-help-response-pending nil) ;; go through output, removing the response. If there is a ;; pending response we nevertheless check for all lines, not only ;; for the pending one. At last, pending responses should not ;; occur to often. (when (string-match singular-help-response-line-1 output) (setq output (replace-match "" t t output)) (setq singular-help-response-pending t)) (when (string-match singular-help-response-line-2 output) ;; after all, we found what we are looking for (setq singular-help-topic (substring output (match-beginning 1) (match-end 1))) (setq output (replace-match "" t t output)) (setq singular-help-response-pending t)) (when (string-match singular-help-response-line-3 output) (setq output (replace-match "" t t output)) (setq singular-help-response-pending t)) (when (string-match singular-help-response-line-4 output) (setq output (replace-match "" t t output)) ;; we completely removed the help from output! (setq singular-help-response-pending nil)) ;; return modified OUTPUT output))) (defun singular-help-post-output-filter (&rest ignore) "Call `singular-help' if `singular-help-topic' is non-nil." (when singular-help-topic (save-excursion (singular-help singular-help-topic)) (setq singular-help-topic nil))) (defvar singular-help-topic-history nil "History of help topics used as arguments to `singular-help'.") (defun singular-help (&optional help-topic) "Show help on HELP-TOPIC in Singular online manual. The file name of the Singular online manual is determined in the following manner: o if the \(customizable) variable `singular-help-explicit-file-name' is non-nil, it is used as file name; o otherwise, if the variable `singular-help-file-name' is non-nil, is is used as file name. This variable should be set by Singular interactive mode itself, but there may be instances where this fails. Anyway, it should be not set by the user. o otherwise, if the environment variable SINGULAR_INFO_FILE is set, it is used as file name; o otherwise, the constant `singular-help-fall-back-file-name' is used as file name." (interactive (list (completing-read "Help topic: " singular-help-topics-alist nil nil nil 'singular-help-topic-history))) ;; get help file and topic (let ((help-file-name (or singular-help-explicit-file-name singular-help-file-name (getenv "SINGULAR_INFO_FILE") singular-help-fall-back-file-name)) (help-topic (cond ((or (null help-topic) (string= help-topic "")) "Top") ;; try to get the real topic from the alist. ;; It's OK if the alist is empty. ((cdr (assoc help-topic singular-help-topics-alist))) (t help-topic))) (continue t)) ;; pop to Info buffer (singular-pop-to-buffer singular-help-same-window "*info*") ;; test whether we are already in Singular's online manual (unless (and (boundp 'Info-current-file) (equal Info-current-file help-file-name)) ;; jump to Singular's top node (condition-case signal (Info-find-node help-file-name "Top") ;; in case of an error jump to info directory (error (Info-directory) ;; if we have been called interactively we pass the error down, ;; otherwise we assumes that we have been called from a hook and ;; call `singular-error' (if (interactive-p) (signal (car signal) (cdr signal)) (singular-error "Singular online manual %s not found" help-file-name)) ;; do not continue (setq continue nil)))) (when continue ;; jump to desired node (condition-case signal (Info-goto-node help-topic) ;; in case of an error jump to Singular's top node (error (Info-goto-node "Top") ;; if we have been called interactively we pass the error down, ;; otherwise we assumes that we have been called from a hook and ;; call `singular-error' (if (interactive-p) (signal (car signal) (cdr signal)) (singular-error "Singular help topic %s not found" help-topic))))))) ;; This might not be the best place for singular-example, but this function ;; is some kind of singular help, so the place is not too bad. ;; Note: We use singular-help-topic-history for singular-example, too (defun singular-example (&optional command) "Show Singular example on COMMAND." (interactive (list (completing-read "Example for: " singular-examples-alist nil nil nil 'singular-help-topic-history))) (let ((process (singular-process)) (string (concat "example " command ";"))) (singular-input-filter process string) (singular-send-string process string))) (defun singular-help-init () "Initialize online help support for Singular interactive mode. This function is called at mode initialization time." (make-local-variable 'singular-help-file-name) (make-local-variable 'singular-help-time-stamp) (make-local-variable 'singular-help-response-pending) (make-local-variable 'singular-help-topic) (add-hook 'singular-pre-input-filter-functions 'singular-help-pre-input-filter) (add-hook 'singular-pre-output-filter-functions 'singular-help-pre-output-filter) (add-hook 'singular-post-output-filter-functions 'singular-help-post-output-filter)) ;;}}} ;;{{{ Singular commands, help topics and standard libraries alists (defvar singular-commands-alist nil "An alist containing all Singular commands to complete. This variable is buffer-local.") (defvar singular-help-topics-alist nil "An alist containg all Singular help topics to complete. This variable is buffer-local.") (defvar singular-standard-libraries-with-categories nil "A list containing all Singular standard library names and their category. This variable is buffer-local.") (defvar singular-standard-libraries-alist nil "An alist containing all Singular standard library names. This variable is set automatically by `singular-menu-install-libraries' using the value of `singular-standard-libraries-with-categories'. This variable is buffer-local.") ;;}}} ;;{{{ Scanning of header and handling of emacs home directory ;; ;; Scanning of header ;; (defconst singular-scan-header-emacs-home-regexp "^// \\*\\* EmacsDir: \\(.+\\)\n" "Regular expression matching the location of emacs home in Singular header.") (defconst singular-scan-header-info-file-regexp "^// \\*\\* InfoFile: \\(.+\\)\n" "Regular expression matching the location of Singular info file in Singular header.") (defconst singular-scan-header-time-stamp 0 "A time stamp set by singular-scan-header. This variable is buffer-local.") (defvar singular-scan-header-scan-for '() "List of things to scan for in Singular header. If `singular-scan-header-pre-output-filter' finds one thing in the current output, it removes the corresponding value from the list. If this variable gets nil, `singular-scan-header-pre-output-filter' is removed from the pre-output-filter. This variable is initialized in `singular-scan-header-init'. Possible values of this list are up to now `help-file' and `emacs-home'. This variable is buffer-local.") (defun singular-scan-header-got-emacs-home () "Load Singular completion and libraries files. Assumes that `singular-emacs-home-directory' is set to the appropriate value and loads the files \"cmd-cmpl.el\", \"hlp-cmpl.el\", \"ex-cmpl.el\", and \"lib-cmpl.el\". On success calls `singular-menu-install-libraries'." (or (load (singular-expand-emacs-file-name "cmd-cmpl.el" t) t t t) (message "Can't find command completion file! Command completion disabled.")) (or (load (singular-expand-emacs-file-name "hlp-cmpl.el" t) t t t) (message "Can't find help topic completion file! Help completion disabled.")) (or (load (singular-expand-emacs-file-name "ex-cmpl.el" t) t t t) (message "Can't find examples completion file! Examples completion disabled.")) (if (load (singular-expand-emacs-file-name "lib-cmpl.el" t) t t t) (singular-menu-install-libraries) (message "Can't find library index file!"))) (defun singular-scan-header-pre-output-filter (output) "Filter function for hook `singular-pro-output-filter-functions'. Scans the Singular header for special markers using the regexps `singular-scan-header-info-file-regexp' and `singular-scan-header-emacs-home-regexp', removes them, loads the completion files, the library-list file, calls `singular-menu-install-libraries' and sets `singular-help-file-name'. Removes itself from the hook if all special markers were found or if it has been searching for more than 20 seconds." (singular-debug 'interactive (message "scanning header")) (let ((changed nil)) ;; Search for emacs home directory (when (string-match singular-scan-header-emacs-home-regexp output) (let ((emacs-home (substring output (match-beginning 1) (match-end 1)))) (singular-debug 'interactive (message "scan header: emacs home path found")) ;; in any case, remove marker from output (setq output (replace-match "" t t output)) (setq changed t) ;; if not already done, do action an singular-emacs-home (when (memq 'emacs-home singular-scan-header-scan-for) (singular-debug 'interactive (message "scan header: initializing emacs-home-directory")) (setq singular-scan-header-scan-for (delq 'emacs-home singular-scan-header-scan-for)) (setq singular-emacs-home-directory emacs-home) (singular-scan-header-got-emacs-home)))) ;; Search for Singular info file (when (string-match singular-scan-header-info-file-regexp output) (let ((file-name (substring output (match-beginning 1) (match-end 1)))) (singular-debug 'interactive (message "scan header: singular.hlp path found")) ;; in any case, remove marker from output (setq output (replace-match "" t t output)) (setq changed t) ;; if not already done, do action on help-file-name (when (memq 'info-file singular-scan-header-scan-for) (singular-debug 'interactive (message "scan header: initializing help-file-name")) (setq singular-scan-header-scan-for (delq 'info-file singular-scan-header-scan-for)) (setq singular-help-file-name file-name)))) ;; Remove from hook if everything is found or if we already waited ;; too long. (if (or (eq singular-scan-header-scan-for nil) (> (singular-time-stamp-difference (current-time) singular-scan-header-time-stamp) 20)) (remove-hook 'singular-pre-output-filter-functions 'singular-scan-header-pre-output-filter)) ;; Return new output string if we changed it, nil otherwise (and changed output))) (defun singular-scan-header-init () "Initialize scanning of header for Singular interactive mode. This function is called by `singular-exec'." (singular-debug 'interactive (message "Initializing scan-header")) (set (make-local-variable 'singular-scan-header-time-stamp) (current-time)) (set (make-local-variable 'singular-scan-header-scan-for) '()) (make-local-variable 'singular-emacs-home-directory) ;; if singular-emacs-home is set try to load the completion files. ;; Otherwise set marker that we still have to search for it. (if singular-emacs-home-directory (singular-scan-header-got-emacs-home) (setq singular-scan-header-scan-for (append singular-scan-header-scan-for '(emacs-home)))) ;; Up to now this seems to be the best place to initialize ;; `singular-help-file-name' since singular-help gets initialized ;; only on mode start-up, not on Singular start-up ;; ;; if singular-help-file-name is not set, mark, that we have to scan for it (make-local-variable 'singular-help-file-name) (or singular-help-file-name (setq singular-scan-header-scan-for (append singular-scan-header-scan-for '(info-file)))) (add-hook 'singular-pre-output-filter-functions 'singular-scan-header-pre-output-filter)) (defun singular-scan-header-exit () "Reinitialize scanning of header for Singular interactive mode. This function is called by `singular-exit-sentinel'." ;; unset variables so that all subsequent calls of Singular will ;; scan the header. (singular-debug 'interactive (message "Deinitializing scan-header")) (setq singular-emacs-home-directory nil) (setq singular-help-file-name nil)) ;; ;; handling of emacs home directory ;; ;; A note on `singular-emacs-home-directory': If this variable is set ;; before singular.el is evaluated, the header of the first Singular ;; started is NOT searched for the singular-emacs-home-directory. ;; Anyhow, all subsequent calls of Singular will scan the header ;; regardless of the initial state of this variable. (The exit-sentinel ;; will set this variable back to nil.) ;; See also `singular-scan-header-exit'. (defvar singular-emacs-home-directory nil "Path to the emacs sub-directory of Singular as string. `singular-scan-header-pre-output-filter' searches the Singular header for the path and sets this variable to the corresponding value. Its value is redifined on every start of Singular. This variable is buffer-local.") (defun singular-expand-emacs-file-name (file &optional noerror) "Add absolute path of emacs home directory. Adds the content of `singular-emacs-home-directory' to the string FILE. If `singular-emacs-home-directory' is nil, return nil and signal an error unless optional argument NOERROR is not nil." (if singular-emacs-home-directory (concat singular-emacs-home-directory (if (memq (aref singular-emacs-home-directory (1- (length singular-emacs-home-directory))) '(?/ ?\\)) "" "/") file) (if noerror nil (error "Variable singular-emacs-home-directory not set")))) ;;}}} ;;{{{ Filename, Command, and Help Completion (defun singular-completion-init () "Initialize completion for Singular interactive mode. Initializes completion of file names, commands, examples, and help topics. This function is called by `singular-exec'." (singular-debug 'interactive (message "Initializing completion")) (set (make-local-variable 'singular-commands-alist) nil) (set (make-local-variable 'singular-examples-alist) nil) (set (make-local-variable 'singular-help-topics-alist) nil)) (defun singular-completion-do (pattern beg end completion-alist) "Try completion on string PATTERN using alist COMPLETION-ALIST. Inserts completed version of PATTERN as new text between BEG and END. Assumes the COMPLETION-ALIST is not nil." (let ((completion (try-completion pattern completion-alist))) (cond ((eq completion t) (message "[Sole completion]")) ;; nothing to complete ((null completion) ;; no completion found (message "Can't find completion for \"%s\"" pattern) (ding)) ((not (string= pattern completion)) (delete-region beg end) (insert completion)) (t (message "Making completion list...") (let ((list (all-completions pattern completion-alist))) (with-output-to-temp-buffer "*Completions*" (display-completion-list list))) (message "Making completion list...%s" "done"))))) (defun singular-dynamic-complete () "Dynamic complete word before point. Performs file name completion if point is inside a string. Performs completion of Singular help topics if point is at the end of a help command (\"help\" or \"?\"). Performs completion of Singular examples if point is at the end of an example command (\"example\"). Otherwise performs completion of Singular commands." (interactive) ;; Check if we are inside a string. The search is done back to the ;; process-mark which should be the beginning of the current input. ;; No check at this point whether there is a process! (if (save-excursion (nth 3 (parse-partial-sexp (singular-process-mark) (point)))) ;; then: inside string, thus expand filename (comint-dynamic-complete-as-filename) ;; else: expand command or help (let ((end (point)) (post-prompt (save-excursion (beginning-of-line) (singular-prompt-skip-forward))) beg) (cond ((save-excursion (goto-char post-prompt) (looking-at "[ \t]*\\([\\?]\\|help \\)[ \t]*\\(.*\\)")) ;; then: help completion (if singular-help-topics-alist (singular-completion-do (match-string 2) (match-beginning 2) end singular-help-topics-alist) (message "Completion of Singular help topics disabled.") (ding))) ((save-excursion (goto-char post-prompt) (looking-at "[ \t]*\\(example \\)[ \t]*\\(.*\\)")) ;; then: example completion (if singular-examples-alist (singular-completion-do (match-string 2) (match-beginning 2) end singular-examples-alist) (message "Completion of Singular examples disabled.") (ding))) (t ;; else: command completion (save-excursion (skip-chars-backward "a-zA-Z0-9") (setq beg (point))) (if singular-commands-alist (singular-completion-do (buffer-substring beg end) beg end singular-commands-alist) (message "Completion of Singular commands disabled.") (ding))))))) ;;}}} ;;{{{ Debugging filters (defun singular-debug-pre-input-filter (string) "Display STRING and some markers in mini-buffer." (singular-debug 'interactive-filter (message "Pre-input filter: %s (li %S ci %S lo %S co %S)" (singular-debug-format string) (marker-position singular-last-input-section-start) (marker-position singular-current-input-section-start) (marker-position singular-last-output-section-start) (marker-position singular-current-output-section-start))) nil) (defun singular-debug-post-input-filter (beg end) "Display BEG, END, and some markers in mini-buffer." (singular-debug 'interactive-filter (message "Post-input filter: (beg %S end %S) (li %S ci %S lo %S co %S)" beg end (marker-position singular-last-input-section-start) (marker-position singular-current-input-section-start) (marker-position singular-last-output-section-start) (marker-position singular-current-output-section-start)))) (defun singular-debug-pre-output-filter (string) "Display STRING and some markers in mini-buffer." (singular-debug 'interactive-filter (message "Pre-output filter: %s (li %S ci %S lo %S co %S)" (singular-debug-format string) (marker-position singular-last-input-section-start) (marker-position singular-current-input-section-start) (marker-position singular-last-output-section-start) (marker-position singular-current-output-section-start))) nil) (defun singular-debug-post-output-filter (beg end simple-sec-start) "Display BEG, END, SIMPLE-SEC-START, and some markers in mini-buffer." (singular-debug 'interactive-filter (message "Post-output filter: (beg %S end %S sss %S) (li %S ci %S lo %S co %S)" beg end simple-sec-start (marker-position singular-last-input-section-start) (marker-position singular-current-input-section-start) (marker-position singular-last-output-section-start) (marker-position singular-current-output-section-start)))) (defun singular-debug-filter-init () "Add debug filters to the necessary hooks. This function is called at mode initialization time." (add-hook 'singular-pre-input-filter-functions 'singular-debug-pre-input-filter nil t) (add-hook 'singular-post-input-filter-functions 'singular-debug-post-input-filter nil t) (add-hook 'singular-pre-output-filter-functions 'singular-debug-pre-output-filter nil t) (add-hook 'singular-post-output-filter-functions 'singular-debug-post-output-filter nil t)) ;;}}} ;;{{{ Demo mode ;; Note: ;; ;; For documentation on Singular demo mode one should refer to the doc ;; string of `singular-demo-load'. ;; Singular demo mode should have been implemented as a minor mode but it ;; did not seem worth it. (defcustom singular-demo-chunk-regexp "\\(\n\\s *\n\\)" "*Regular expressions to recognize chunks of a demo file. If there is a subexpression specified its contents is removed after the chunk has been displayed. The default value is \"\\\\(\\n\\\\s *\\n\\\\)\" which means that chunks are separated by one blank line which is removed after the chunks have been displayed." :type 'regexp :initialize 'custom-initialize-default :group 'singular-demo-mode) (defcustom singular-demo-print-messages t "*If non-nil, print message on how to continue demo mode." :type 'boolean :initialize 'custom-initialize-default :group 'singular-demo-mode) (defcustom singular-demo-exit-on-load t "*If non-nil, an active demo is automatically discarded when a new one is loaded. Otherwise, the load is aborted with an error." :type 'boolean :initialize 'custom-initialize-default :group 'singular-demo-mode) (defcustom singular-demo-load-directory nil "*Directory where demo files usually reside. If non-nil, this directory is offered as a starting point to search for demo files when `singular-demo-load' is called interactively for the first time. (In further calls, `singular-demo-load' offers the directory where the last demo file has been loaded from as starting point). If this variable equals nil whatever Emacs offers by default is used as first-time starting point. In general, this is the directory where Singular has been started in." :type '(choice (const nil) (file)) :initialize 'custom-initialize-default :group 'singular-demo-mode) (defvar singular-demo-mode nil "Non-nil if Singular demo mode is on. This variable is buffer-local.") (defvar singular-demo-old-mode-name nil "Used to store previous `mode-name' before switching to demo mode. This variable is buffer-local.") (defvar singular-demo-end nil "Marker pointing to end of demo file. This variable is buffer-local.") (defvar singular-demo-last-directory nil "If non-nil, directory from which the last demo file has been loaded. This variable is buffer-local.") (defun singular-demo-load (demo-file) "Load demo file DEMO-FILE and enter Singular demo mode. The Singular demo mode allows to step conveniently through a prepared demo file. The contents of the demo file is made visible and executed in portions called chunks. How the chunks have to be marked in the demo file is described below. After loading the demo file with this function, \\[singular-send-or-copy-input] displays the first chunk of the demo file at the Singular prompt. This chunk may be modified \(or even deleted) and then sent to Singular entering \\[singular-send-or-copy-input] as any command would have been sent to Singular. The next time \\[singular-send-or-copy-input] is entered, the next chunk of the demo file is displayed, and so on. One may interrupt this sequence and enter commands at the Singular input prompt as usual. As soon as \\[singular-send-or-copy-input] is entered directly after the input prompt, the next chunk of the demo file is displayed. Here is the exact algorithm how this magic works: If point is located at the very end of the buffer *and* immediately after Singular's last input prompt, the next chunk of the demo file is displayed. In particular, if there is any text after the last input prompt that text is sent to Singular as usual and no new chunks are displayed. After displaying the last chunk of DEMO-FILE, Singular demo mode automatically terminates and normal operation is resumed. To prematurely exit Singular demo mode \\[singular-demo-exit] may be used. DEMO-FILE should consist of regular Singular commands. Portions of text separated by a blank line are taken to be the chunks of the demo file. There is a number of variables to configure Singular demo mode. Refer to the `singular-demo-mode' customization group for more information. Important note: The unprocessed contents of DEMO-FILE is hidden using buffer narrowing. Emacs gets terribly confused when during demo mode the buffer is either narrowed to some other region or if the buffer is widened. The safest thing to do if that happens by accident is to explicitly exit the demo by means of \\[singular-demo-exit] and to try to resume somehow normal operation. `singular-demo-load' runs the functions on `singular-demo-mode-enter-hook' just after demo mode has been entered. The functions on `singular-demo-mode-exit-hook' are executed after Singular demo mode has been exited, either prematurely or due to the end of the demo file. However, it its important to note that in the latter case the last chunk of the demo file is still waiting to be sent to Singular." (interactive (list (let ((demo-file-name (cond ;; Emacs ((eq singular-emacs-flavor 'emacs) (read-file-name "Load demo file: " (or singular-demo-last-directory singular-demo-load-directory) nil t)) ;; XEmacs (t ;; there are some problems with the window being popped up when this ;; function is called from a menu. It does not display the contents ;; of `singular-demo-load-directory' but of `default-directory'. (let ((default-directory (or singular-demo-last-directory singular-demo-load-directory default-directory))) (read-file-name "Load demo file: " (or singular-demo-last-directory singular-demo-load-directory) nil t)))))) (setq singular-demo-last-directory (file-name-directory demo-file-name)) demo-file-name))) ;; check for running demo (if singular-demo-mode (if singular-demo-exit-on-load ;; silently exit running demo (singular-demo-exit t) (error "There already is a demo running, exit with `singular-demo-exit' first"))) ;; load new demo (let ((old-point-min (point-min))) (unwind-protect (progn (goto-char (point-max)) (widen) (cond ;; XEmacs ((eq singular-emacs-flavor 'xemacs) ;; load file and remember its end (set-marker singular-demo-end (+ (point) (nth 1 (insert-file-contents-literally demo-file))))) ;; Emacs (t ;; Emacs does something like an `insert-before-markers' so ;; save all essential markers (let ((pmark-pos (marker-position (singular-process-mark))) (sliss-pos (marker-position singular-last-input-section-start)) (sciss-pos (marker-position singular-current-input-section-start)) (sloss-pos (marker-position singular-last-output-section-start)) (scoss-pos (marker-position singular-current-output-section-start))) (unwind-protect ;; load file and remember its end (set-marker singular-demo-end (+ (point) (nth 1 (insert-file-contents-literally demo-file)))) ;; restore markers. ;; This is unwind-protected. (set-marker (singular-process-mark) pmark-pos) (set-marker singular-last-input-section-start sliss-pos) (set-marker singular-current-input-section-start sciss-pos) (set-marker singular-last-output-section-start sloss-pos) (set-marker singular-current-output-section-start scoss-pos)))))) ;; completely hide demo file. ;; This is unwind-protected. (narrow-to-region old-point-min (point)))) ;; switch demo mode on (setq singular-demo-old-mode-name mode-name mode-name "Singular Demo" singular-demo-mode t) (run-hooks 'singular-demo-mode-enter-hook) (if singular-demo-print-messages (message "Hit RET to start demo")) (force-mode-line-update)) (defun singular-demo-exit-internal () "Exit Singular demo mode. Recovers the old mode name, sets `singular-demo-mode' to nil, runs the hooks on `singular-demo-mode-exit-hook'." (setq mode-name singular-demo-old-mode-name singular-demo-mode nil) (run-hooks 'singular-demo-mode-exit-hook) (force-mode-line-update)) (defun singular-demo-exit (&optional no-message) "Prematurely exit Singular demo mode. Cleans up everything that is left from the demo. Runs the hooks on `singular-demo-mode-exit-hook'. Does nothing when Singular demo mode is not active." (interactive) (when singular-demo-mode ;; clean up hidden rest of demo file (let ((old-point-min (point-min)) (old-point-max (point-max))) (unwind-protect (progn (widen) (delete-region old-point-max singular-demo-end)) ;; this is unwind-protected (narrow-to-region old-point-min old-point-max))) (singular-demo-exit-internal) (or no-message (if singular-demo-print-messages (message "Demo exited"))))) (defun singular-demo-show-next-chunk () "Show next chunk of demo file at input prompt. Assumes that Singular demo mode is active. Moves point to end of buffer and widenes the buffer such that the next chunk of the demo file becomes visible. Finds and removes chunk separators as specified by `singular-demo-chunk-regexp'. Leaves demo mode after showing last chunk. In that case runs hooks on `singular-demo-mode-exit-hook'." (let ((old-point-min (point-min))) (unwind-protect (progn (goto-char (point-max)) (widen) (if (re-search-forward singular-demo-chunk-regexp singular-demo-end 'limit) (if (match-beginning 1) (delete-region (match-beginning 1) (match-end 1))) ;; remove trailing white-space. We may not use ;; `(skip-syntax-backward "-")' since newline is has no white ;; space syntax. The solution down below should suffice in ;; almost all cases ... (skip-chars-backward " \t\n\r\f") (delete-region (point) singular-demo-end) (singular-demo-exit-internal))) ;; this is unwind-protected (narrow-to-region old-point-min (point))))) (defun singular-demo-mode-init () "Initialize variables belonging to Singular demo mode. Creates some buffer-local variables and the buffer-local marker `singular-demo-end'. This function is called at mode initialization time." (make-local-variable 'singular-demo-mode) (make-local-variable 'singular-demo-mode-old-name) (make-local-variable 'singular-demo-mode-end) (if (not (and (boundp 'singular-demo-end) singular-demo-end)) (setq singular-demo-end (make-marker))) (make-local-variable 'singular-demo-last-directory)) ;;}}} ;;{{{ Some lengthy notes on input and output ;; NOT READY[so sorry]! ;;}}} ;;{{{ Last input and output section (defun singular-last-input-section (&optional no-error) "Return last input section. Returns nil if optional argument NO-ERROR is non-nil and there is no last input section defined, throws an error otherwise." (let ((last-input-start (marker-position singular-last-input-section-start)) (last-input-end (marker-position singular-current-output-section-start))) (cond ((and last-input-start last-input-end) (singular-section-create (singular-simple-sec-at last-input-start) 'input last-input-start last-input-end)) (no-error nil) (t (error "No last input section defined"))))) (defun singular-current-output-section (&optional no-error) "Return current output section. Returns nil if optional argument NO-ERROR is non-nil and there is no current output section defined, throws an error otherwise." (let ((current-output-start (marker-position singular-current-output-section-start)) (current-output-end (save-excursion (save-restriction (widen) (goto-char (singular-process-mark)) (singular-prompt-skip-backward) (and (bolp) (point)))))) (cond ((and current-output-start current-output-end) (singular-section-create (singular-simple-sec-at current-output-start) 'output current-output-start current-output-end)) (no-error nil) (t (error "No current output section defined"))))) (defun singular-last-output-section (&optional no-error) "Return last output section. Returns nil if optional argument NO-ERROR is non-nil and there is no last output section defined, throws an error otherwise." (let ((last-output-start (marker-position singular-last-output-section-start)) (last-output-end (marker-position singular-last-input-section-start))) (cond ((and last-output-start last-output-end) (singular-section-create (singular-simple-sec-at last-output-start) 'output last-output-start last-output-end)) (no-error nil) (t (error "No last output section defined"))))) (defun singular-latest-output-section (&optional no-error) "Return latest output section. This is the current output section if it is defined, otherwise the last output section. Returns nil if optional argument NO-ERROR is non-nil and there is no latest output section defined, throws an error otherwise." (or (singular-current-output-section t) (singular-last-output-section t) (if no-error nil (error "No latest output section defined")))) ;;}}} ;;{{{ Sending input (defvar singular-pre-input-filter-functions nil "Functions to call before input is sent to process. These functions get one argument, a string containing the text which is to be sent to process. The functions should return either nil or a string. In the latter case the returned string replaces the string to be sent to process. This is a buffer-local variable, not a buffer-local hook! `singular-run-hook-with-arg-and-value' is used to run the functions in the list.") (defvar singular-post-input-filter-functions nil "Functions to call after input is sent to process. These functions get two arguments BEG and END. If `singular-input-filter' has been called with a string as argument BEG and END gives the position of this string after insertion into the buffer. If `singular-input-filter' has been called with a position as argument BEG and END equal process mark and that position, resp. The functions may assume that no narrowing is in effect and may change point at will. This hook is buffer-local.") (defvar singular-current-input-section-start nil "Marker to the start of the current input section. This marker points nowhere on startup or if there is no current input section. This variable is buffer-local.") (defvar singular-last-input-section-start nil "Marker to the start of the last input section. This marker points nowhere on startup. This variable is buffer-local.") (defun singular-input-filter-init (pos) "Initialize all variables concerning input. POS is the position of the process mark." ;; localize variables not yet localized in `singular-interactive-mode' (make-local-variable 'singular-current-input-section-start) (make-local-variable 'singular-last-input-section-start) ;; initialize markers (if (not (markerp singular-current-input-section-start)) (setq singular-current-input-section-start (make-marker))) (if (not (markerp singular-last-input-section-start)) (setq singular-last-input-section-start (make-marker)))) (defun singular-send-string (process string) "Send newline terminated STRING to to process PROCESS. Runs the hooks on `singular-pre-input-filter-functions' in the buffer associated to PROCESS. The functions get the non-terminated string." (let ((process-buffer (process-buffer process))) ;; check whether buffer is still alive (if (and process-buffer (buffer-name process-buffer)) (save-excursion (set-buffer process-buffer) (process-send-string process (concat (singular-run-hook-with-arg-and-value singular-pre-input-filter-functions string) "\n")))))) (defun singular-input-filter (process string-or-pos) "Insert/update input from user in buffer associated to PROCESS. Inserts STRING-OR-POS followed by a newline at process mark if it is a string. Assumes that the input is already inserted and that it is placed between process mark and STRING-OR-POS if the latter is a position. Inserts a newline after STRING-OR-POS. Takes care off: - current buffer as well as point and restriction in buffer associated with process, even against non-local exits. Updates: - process mark; - current and last sections; - simple sections; - mode line. Runs the hooks on `singular-pre-input-filter-functions' and `singular-post-input-filter-functions'. For a more detailed descriptions of the input filter, the markers it sets, and input filter functions refer to the section \"Some lengthy notes on input and output\" in singular.el." (let ((process-buffer (process-buffer process))) ;; check whether buffer is still alive (if (and process-buffer (buffer-name process-buffer)) (let ((old-buffer (current-buffer)) (old-pmark (marker-position (process-mark process))) old-point old-point-min old-point-max) (unwind-protect (let (simple-sec-start) (set-buffer process-buffer) ;; the following lines are not protected since the ;; unwind-forms refer the variables being set here (setq old-point (point-marker) old-point-min (point-min-marker) old-point-max (point-max-marker) ;; get end of last simple section (equals start of ;; current) simple-sec-start (singular-simple-sec-last-end-position)) ;; prepare for insertion (widen) (set-marker-insertion-type old-point t) (set-marker-insertion-type old-point-max t) ;; insert string at process mark and advance process ;; mark after insertion. If it not a string simply ;; jump to desired position and insrt a newline. (if (stringp string-or-pos) (progn (goto-char old-pmark) (insert string-or-pos)) (goto-char string-or-pos)) (insert ?\n) (set-marker (process-mark process) (point)) ;; create new simple section and update section markers (cond ((eq (singular-simple-sec-create 'input (point)) 'empty) nil) ;; a new simple section has been created ... ((null (marker-position singular-current-input-section-start)) ;; ... and even a new input section has been created! (set-marker singular-current-input-section-start simple-sec-start) (set-marker singular-last-output-section-start singular-current-output-section-start) (set-marker singular-current-output-section-start nil))) ;; run post-output hooks and force mode-line update (run-hook-with-args 'singular-post-input-filter-functions old-pmark (point))) ;; restore buffer, restrictions and point (narrow-to-region old-point-min old-point-max) (set-marker old-point-min nil) (set-marker old-point-max nil) (goto-char old-point) (set-marker old-point nil) (set-buffer old-buffer)))))) ;;}}} ;;{{{ Sending input interactive (defcustom singular-move-on-send 'eob "*Where to move point before sending input to Singular. Should be one of: `eob' which means to move point to end of buffer, `eol' which means to move point to end of line, or nil which means to not move point at all." :type '(choice (const :tag "End of buffer" eob) (const :tag "End of line" eol) (const :tag "Do not move" nil)) :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) (defun singular-get-old-input (get-section) "Get and return old input. Retrivies on a per-section base if GET-SECTION is non-nil, otherwise on a per-line base." (if get-section ;; get input from input section (let ((section (singular-section-at (point)))) (if (eq (singular-section-type section) 'input) (singular-white-space-strip (singular-section-to-string section) t) (error "Not on an input section"))) ;; get input from line (save-excursion (beginning-of-line) (singular-prompt-skip-forward) (let ((old-point (point))) (end-of-line) (buffer-substring old-point (point)))))) (defun singular-send-or-copy-input (get-section) "Send input to Singular. The behavior of this function very much depends on the current position of point relative to the process mark, that is, the position, where Singular expects next input. If point is located before process mark, old input is copied to the process mark. With prefix argument, the whole input section point currently is in is copied, without prefix argument only the current line. One should note that the input is *not* sent to Singular, it is only copied to the process mark. Another time entering \\[singular-send-or-copy-input] sends it to Singular. If point is located after process mark, point is moved as determined by the `singular-move-on-send' variable: either it is moved to the end of the current line, or to the end of the buffer, or it is not moved at all. The default is to move point to the end of the buffer which most closely resembles regular terminal behaviour. At last, the text of the region between process mark and point is sent to Singular. Any input to Singular is stored in an input history where it may be retrieved with \\[comint-previous-input] or \\[comint-next-input], respectively. For more information on the input history one should refer to the documentation of `singular-interactive-mode'. If Singular demo mode is active and point is at process mark and if that position is at the end of the buffer the next chunk of the demo file is displayed. One should refer to the documentation of `singular-demo-load' for more information on Singular demo mode. The Singular process should be running." (interactive "P") (let ((process (singular-process)) (pmark (singular-process-mark))) (cond (;; check for demo mode and show next chunk if necessary (and singular-demo-mode (= (point) pmark) (= pmark (point-max))) (singular-demo-show-next-chunk)) (;; get old input (< (point) pmark) (let ((old-input (singular-get-old-input get-section))) (goto-char pmark) (insert old-input))) (;; send input from pmark to point t ;; print message if demo mode is active. We print it before we do ;; anything else so that the message will not hide any further ;; (error) messages. (and singular-demo-mode singular-demo-print-messages (message "Hit RET to continue demo")) ;; go to desired position (cond ((eq singular-move-on-send 'eol) (end-of-line)) ((eq singular-move-on-send 'eob) (goto-char (point-max)))) (let* ((input (buffer-substring pmark (point)))) ;; insert string into history (singular-history-insert input) ;; send string to process (singular-send-string process input) ;; "insert" it into buffer (singular-input-filter process (point))))))) ;;}}} ;;{{{ Receiving output (defvar singular-pre-output-filter-functions nil "Functions to call before output is inserted into the buffer. These functions get one argument, a string containing the text sent from process. The functions should return either nil or a string. In the latter case the returned string replaces the string sent from process. This is a buffer-local variable, not a buffer-local hook! `singular-run-hook-with-arg-and-value' is used to run the functions in this list.") (defvar singular-post-output-filter-functions nil "Functions to call after output is inserted into the buffer. These functions get three arguments BEG, END, and SIMPLE-SEC-START. The region between BEG and END is what has been inserted into the buffer. SIMPLE-SEC-START is the start of the simple section which has been created on insertion or nil if no simple section has been created. The functions may assume that no narrowing is in effect and may change point at will. This hook is buffer-local.") (defvar singular-current-output-section-start nil "Marker to the start of the current output section. This marker points nowhere on startup or if there is no current output section. This variable is buffer-local.") (defvar singular-last-output-section-start nil "Marker to the start of the last output section. This marker points nowhere on startup. This variable is buffer-local.") (defun singular-output-filter-init (pos) "Initialize all variables concerning output including process mark. Set process mark to POS." ;; localize variables not yet localized in `singular-interactive-mode' (make-local-variable 'singular-current-output-section-start) (make-local-variable 'singular-last-output-section-start) ;; initialize markers (if (not (markerp singular-current-output-section-start)) (setq singular-current-output-section-start (make-marker))) (if (not (markerp singular-last-output-section-start)) (setq singular-last-output-section-start (make-marker))) (set-marker (singular-process-mark) pos)) (defun singular-output-filter (process string) "Insert STRING containing output from PROCESS into its associated buffer. Takes care off: - current buffer as well as point and restriction in buffer associated with process, even against non-local exits. Updates: - process mark; - current and last sections; - simple sections; - mode line. Runs the hooks on `singular-pre-output-filter-functions' and `singular-post-output-filter-functions'. For a more detailed descriptions of the output filter, the markers it sets, and output filter functions refer to the section \"Some lengthy notes on input and output\" in singular.el." (let ((process-buffer (process-buffer process))) ;; check whether buffer is still alive (if (and process-buffer (buffer-name process-buffer)) (let ((old-buffer (current-buffer)) (old-pmark (marker-position (process-mark process))) old-point old-point-min old-point-max) (unwind-protect (let (simple-sec-start) (set-buffer process-buffer) ;; the following lines are not protected since the ;; unwind-forms refer the variables being set here (setq old-point (point-marker) old-point-min (point-min-marker) old-point-max (point-max-marker) ;; get end of last simple section (equals start of ;; current) simple-sec-start (singular-simple-sec-last-end-position) ;; get string to insert string (singular-run-hook-with-arg-and-value singular-pre-output-filter-functions string)) ;; prepare for insertion (widen) (set-marker-insertion-type old-point t) (set-marker-insertion-type old-point-max t) ;; insert string at process mark and advance process ;; mark after insertion (goto-char old-pmark) (insert string) (set-marker (process-mark process) (point)) ;; create new simple section and update section markers (cond ((eq (singular-simple-sec-create 'output (point)) 'empty) (setq simple-sec-start nil)) ;; a new simple section has been created ... ((null (marker-position singular-current-output-section-start)) ;; ... and even a new output section has been created! (set-marker singular-current-output-section-start simple-sec-start) (set-marker singular-last-input-section-start singular-current-input-section-start) (set-marker singular-current-input-section-start nil))) ;; run post-output hooks and force mode-line update (run-hook-with-args 'singular-post-output-filter-functions old-pmark (point) simple-sec-start) (force-mode-line-update)) ;; restore buffer, restrictions and point (narrow-to-region old-point-min old-point-max) (set-marker old-point-min nil) (set-marker old-point-max nil) (goto-char old-point) (set-marker old-point nil) (set-buffer old-buffer)))))) ;;}}} ;;{{{ Singular interactive mode (defun singular-interactive-mode () "Major mode for interacting with Singular. NOT READY [how to send input]! NOT READY [in particular: input history!] NOT READY [multiple Singulars]! \\{singular-interactive-mode-map} For \"backward compatibility\" with the terminal version of Singular there is some extra magic built into Singular interactive mode which catches help commands issued at the command prompt and executes this function instead. However, this magic is really not too magic and easily may be fooled. If this magic if fooled Singular prints some error message starting like this: // ** Your help command could not be executed. ... However, the most common case should be recognized: If one issues a help command to a non-busy Singular, where the help command comes on one line and is properly terminated with a semicolon. Like that: help ring; Customization: Entry to this mode runs the hooks on `singular-interactive-mode-hook'. NOT READY [much more to come. See shell.el.]!" (interactive) ;; uh-oh, we have to set `comint-input-ring-size' before we call ;; `comint-mode' (singular-history-init) ;; run comint mode and do basic mode setup (let (comint-mode-hook) (comint-mode) (singular-comint-init)) (setq major-mode 'singular-interactive-mode) (setq mode-name "Singular Interaction") ;; some other initialization found in no folding (setq comment-start "// ") (setq comment-start-skip "// *") (setq comment-end "") ;; initialize singular input and output filters. This should be done ;; first as the filters are accessed in the following initialization ;; functions. NOT READY [should be moved to the respective foldings] (make-local-variable 'singular-pre-input-filter-functions) ;;make-local-hook is obsolete in emcas >=21.1 ;;(make-local-hook 'singular-post-input-filter-functions) (make-local-variable 'singular-pre-output-filter-functions) ;;(make-local-hook 'singular-post-output-filter-functions) (singular-interactive-mode-map-init) (singular-mode-syntax-table-init) (singular-interactive-mode-menu-init) (singular-demo-mode-init) (singular-folding-init) (singular-help-init) (singular-prompt-init) (singular-exec-init) ;; Font Lock mode initialization for Emacs. For XEmacs, it is done at ;; singular.el loading time. (cond ;; Emacs ((eq singular-emacs-flavor 'emacs) (singular-interactive-font-lock-init))) ;; debugging filter initialization (singular-debug 'interactive-filter (singular-debug-filter-init)) (run-hooks 'singular-interactive-mode-hook)) ;;}}} ;;{{{ Starting singular (defcustom singular-same-window t "*Specifies how to open the window for Singular sessions. If this variable equals t, Singular comes up in the selected window. If this variable equals nil, Singular comes up in another window. If this variable equals neither t nor nil, the standard Emacs behaviour to open the window is adopted (which very much depends on the settings of `same-window-buffer-names')." :initialize 'custom-initialize-default :type '(choice (const :tag "This window" t) (const :tag "Other window" nil) (const :tag "Default" default)) :group 'singular-interactive-miscellaneous) (defcustom singular-start-file "~/.emacs_singularrc" "*Name of start-up file to pass to Singular. If the file named by this variable exists it is given as initial input to any Singular process being started. Note that this may lose due to a timing error if Singular discards input when it starts up." :type 'file :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) (defcustom singular-executable-default "Singular" "*Default name of Singular executable. Used by `singular' when new Singular processes are started. If the name is given without path the executable is searched using the `PATH' environment variable." :type 'file :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) (defvar singular-executable-last singular-executable-default "Singular executable name of the last Singular command used. This variable is buffer-local.") (defcustom singular-directory-default nil "*Default working directory of Singular buffer. Should be either nil (which means do not set the default directory) or an existing directory." :type '(choice (const nil) (directory :value "~/")) :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) (defvar singular-directory-last singular-directory-default "Working directory of last Singular command used. This variable is buffer-local.") ;; no singular-directory-history here. Usual file history is used. (defcustom singular-switches-default '() "*List of default switches for Singular processes. Should be a list of strings, one string for each switch. Used by `singular' when new Singular processes are started." :type '(repeat string) :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) (defvar singular-switches-last singular-switches-default "Switches of last Singular command used. This variable is buffer-local.") (defvar singular-switches-history nil "History list of Singular switches.") ; (defvar singular-switches-magic '("-t" "--exec" "if (system(\"version\") > 1304){system(\"--emacs\", 1);};") (defvar singular-switches-magic '("-t" "--emacs") "Additional magic switches for Singular process. List of switch-strings which are automagically added when new Singular processes are started, one string for each command line argument. This list should at least contain the options \"--emacs\" and \"-t\". If you are running a Singular with version < 1.2 , remove option \"--exec\" from the list.") (defcustom singular-name-default "singular" "*Default process name for Singular process. Used by `singular' when new Singular processes are started. This string surrounded by \"*\" will also be the buffer name." :type 'string :initialize 'custom-initialize-default :group 'singular-interactive-miscellaneous) (defvar singular-name-last singular-name-default "process name of the last Singular command used. This variable is buffer-local.") (defvar singular-name-history nil "History list of Singular process names.") (defun singular-exec-init () "Initialize defaults for starting Singular. This function is called at mode initialization time." (singular-debug 'interactive (message "Initializing exec")) (set (make-local-variable 'singular-executable-last) singular-executable-default) (set (make-local-variable 'singular-directory-last) singular-directory-default) (set (make-local-variable 'singular-name-last) singular-name-default) (set (make-local-variable 'singular-switches-last) singular-switches-default) (set (make-local-variable 'singular-exit-insert-killed-marker) nil) (set (make-local-variable 'singular-exit-cleanup-done) nil)) (defvar singular-exit-cleanup-done nil "Switch indicating if cleanup after Singular exit is already done. Initial value is nil. Is set to t by `singular-exit-cleanup' and to nil by `singular-exit-sentinel'. This variable is buffer-local.") (defun singular-exit-cleanup () "Clean up after termination of Singular. Writes back input ring after regular termination of Singular if process buffer is still alive, deinstalls the library menu und calls several other exit procedures. Assumes that the current buffer is a Singular buffer. Sets the variable `singular-exit-cleanup-done' to t. This function is called by `singular-kill-singular' or by `singular-exit-sentinel'." (singular-debug 'interactive (message "exit-cleanup called")) (singular-demo-exit t) (singular-scan-header-exit) (singular-menu-deinstall-libraries) (singular-history-write) (setq singular-exit-cleanup-done t)) (defun singular-exit-sentinel (process message) "Clean up after termination of Singular. Calls `singular-exit-cleanup' if `singular-exit-cleanup-done' is nil." (save-excursion (singular-debug 'interactive (message "Sentinel: %s" (substring message 0 -1))) (if (string-match "finished\\|exited\\|killed" message) (let ((process-buffer (process-buffer process))) (if (and (not singular-exit-cleanup-done) process-buffer (buffer-name process-buffer) (set-buffer process-buffer)) (singular-exit-cleanup)))) (setq singular-exit-cleanup-done nil))) (defun singular-kill-singular () "Delete the Singular process running in the current buffer. Calls `singular-exit-cleanup' and deletes the Singular process. Inserts a string indicating that the Singular process is killed." (let* ((process (singular-process)) (mark (marker-position (process-mark process)))) (singular-exit-cleanup) (delete-process process) (save-excursion ;; Because of timing problems it would be better if ;; singular-exit-sentinel would insert this string (see Version 1.41) ;; but this is not possible for XEmacs: The function (process-mark) ;; called within singular-exit-sentinel returns a mark with no ;; associated buffer! (goto-char mark) (insert "// ** Singular process killed **\n")))) (defun singular-control-c (mode) "Interrupt the Singular process running in the current buffer. If called interactiveley, asks whether to (a)bort the current Singular command, (q)uit or (r) restart the current Singular process, or (c)ontinue without doing anything (default). If called non-interactiveley, MODE should be one of 'abort, 'quit, 'restart, or 'continue." (interactive (let (answer) (while (not answer) (setq answer (read-from-minibuffer "(a)bort current command, (q)uit, (r)estart Singular or (c)ontinue? ")) (setq answer (cond ((equal answer "a") 'abort) ((equal answer "c") 'continue) ((equal answer "r") 'restart) ((equal answer "q") 'quit) ((equal answer "") 'continue) ; default: continue (t nil)))) (list answer))) (cond ((eq mode 'quit) (singular-kill-singular)) ((eq mode 'restart) (singular-restart)) ((eq mode 'abort) (interrupt-process (singular-process))))) (defun singular-exec (buffer name executable start-file switches) "Start a new Singular process NAME in BUFFER, running EXECUTABLE. EXECUTABLE should be a string denoting an executable program. SWITCHES should be a list of strings that are passed as command line switches. START-FILE should be the name of a file which contents is sent to the process. Deletes any old processes running in that buffer. Removes any empty string in SWITCHES befor passing to Singular. Moves point to the end of BUFFER. Initializes all important markers and the simple sections. Runs the hooks on `singular-exec-hook'. Returns BUFFER." (let ((old-buffer (current-buffer))) (unwind-protect (progn (set-buffer buffer) ;; delete any old processes (let ((process (get-buffer-process buffer))) (if process (delete-process process))) ;; create new process (singular-debug 'interactive (message "Starting new Singular: %s %s" executable switches)) ;; before passing SWITCHES to Singuar we remove any empty strings ;; because otherwise Singular tries to open a file with an empty ;; file name. (let ((process (comint-exec-1 name buffer executable (delete "" switches)))) ;; set process filter and sentinel (set-process-filter process 'singular-output-filter) (set-process-sentinel process 'singular-exit-sentinel) (make-local-variable 'comint-ptyp) (setq comint-ptyp process-connection-type) ; T if pty, NIL if pipe. ;; go to the end of the buffer, initialize I/O and simple ;; sections (goto-char (point-max)) (singular-input-filter-init (point)) (singular-output-filter-init (point)) (singular-simple-sec-init (point)) ;; completion should be initialized before scan header! (singular-completion-init) (singular-scan-header-init) (singular-menu-init) ;; feed process with start file and read input ring. Take ;; care about the undo information. (if start-file (let ((buffer-undo-list t) start-string) (singular-debug 'interactive (message "Feeding start file")) (sleep-for 1) ; try to avoid timing errors (insert-file-contents start-file) (setq start-string (buffer-substring (point) (point-max))) (delete-region (point) (point-max)) (process-send-string process start-string))) ;; read history if present (singular-history-read) ;; execute hooks (run-hooks 'singular-exec-hook)) buffer) ;; this code is unwide-protected (set-buffer old-buffer)))) ;; TODO: Documentation! ;; Note: ;; ;; In contrast to shell.el, `singular' does not run ;; `singular-interactive-mode' every time a new Singular process is ;; started, but only when a new buffer is created. This behaviour seems ;; more intuitive w.r.t. local variables and hooks. (defun singular-internal (executable directory switches name) "Run an inferior Singular process, with I/O through an Emacs buffer. Appends `singular-switches-magic' to switches. Sets default-directory if directory is not-nil. Sets singular-*-last values." (singular-debug 'interactive (message "singular-internal: %s %s %s %s" executable directory name switches)) (let* ((buffer-name (singular-process-name-to-buffer-name name)) ;; buffer associated with Singular, nil if there is none (buffer (get-buffer buffer-name))) ;; If directory is set, make sure that it ends in a "/" at the end. ;; The check is done on both slash and backslash, but we unconditionally ;; insert a slash. Hopefully that works on NT, too. (and directory (not (memq (aref directory (1- (length directory))) '(?/ ?\\))) (setq directory (concat directory "/"))) (if (not buffer) (progn ;; create new buffer and call `singular-interactive-mode' (singular-debug 'interactive (message "Creating new buffer")) (setq buffer (get-buffer-create buffer-name)) (set-buffer buffer) (and directory (setq default-directory directory)) (singular-debug 'interactive (message "Calling `singular-interactive-mode'")) (singular-interactive-mode))) (if (not (comint-check-proc buffer)) ;; create new process if there is none (singular-exec buffer name executable (if (file-exists-p singular-start-file) singular-start-file) (append switches singular-switches-magic))) ;; pop to buffer (singular-debug 'interactive (message "Calling `pop-to-buffer'")) (singular-pop-to-buffer singular-same-window buffer)) ;; Set buffer local singular-*-last-values (setq singular-executable-last executable) (setq singular-directory-last directory) (setq singular-switches-last switches) (setq singular-name-last name) ;; Set global values, too (set-default 'singular-executable-last executable) (set-default 'singular-directory-last directory) (set-default 'singular-switches-last switches) (set-default 'singular-name-last name)) (defun singular-generate-new-buffer-name (name) "Generate a unique buffer name for a singular interactive buffer. The string NAME is the desired name for the singular interactive buffer, without surrounding stars. The string returned is surrounded by stars. If no buffer with name \"*NAME*\" exists, return \"*NAME*\". Otherwise check for buffer called \"*NAME*\" where n is a increasing number and return \"*NAME*\" if no such buffer exists." (let ((new-name (singular-process-name-to-buffer-name name)) (count 2)) (while (get-buffer new-name) (setq new-name (singular-process-name-to-buffer-name (concat name "<" (format "%d" count) ">"))) (setq count (1+ count))) new-name)) (defun singular () "Run an inferior Singular process using default arguments. Starts a Singular process, with I/O through an Emacs buffer, using the values of `singular-executable-default', `singular-directory-default', `singular-switches-default', and `singular-name-default'. For more information on starting a Singular process and on the arguments see the documentation of `singular-other'. To restart a previously started Singular process use `singular-restart'. Every time `singular' starts a new Singular process it runs the hooks on `singular-exec-hook'. Type \\[describe-mode] in the Singular buffer for a list of commands." (interactive) (singular-internal singular-executable-default singular-directory-default singular-switches-default singular-name-default)) (defun singular-restart () "Run an inferior Singular process using the last arguments used. Starts a Singular process, with I/O through an Emacs buffer, using the previously used arguments. If called within a Singular buffer, uses the arguments of the most recent Singular process started in this buffer. If there is a Singular process running in this buffer, it is deleted without warning! If called outside a Singular buffer, uses the arguments of the most recent Singular process started in any Singular buffer (and does not delete any Singular process). If no last values are available, uses the default values (see documentation of `singular'). For more information on starting a Singular process and on the arguments see the documentation of `singular-other'. Every time `singular-restarts' starts a new Singular process it runs the hooks on `singular-exec-hook'. Type \\[describe-mode] in the Singular buffer for a list of commands." (interactive) (if (singular-process t) (singular-kill-singular)) (singular-internal singular-executable-last singular-directory-last singular-switches-last singular-name-last)) (defun singular-other (executable directory switches name) "Run an inferior Singular process. Starts a Singular process, with I/O through an Emacs buffer. If called interactively, the user is asked in the minibuffer area for an existing executable (with or without path), an exisiting directory or nil (if non-nil, sets the buffers default directory to this directory), the complete command line arguments to be passed to Singular (as a single string) and the buffer name of the singular buffer, which is surrounded by \"*\", if not already. (The process name of the singular process is then given by the buffer name with the surrounding stars stripped.) If called non-interactiveley, EXECUTABLE is the name of an existing Singular executable (with or without path), DIRECTORY is the name of an existing directory or nil. If non-nil, sets the buffers default directory to DIRECTORY. SWITCHES is a list of strings where each string contains one command line argument which is passed to Singular, and NAME is the process name of the Singular process (that is, the singular buffer name is given by NAME surrounded by \"*\"). If buffer exists but Singular is not running, starts new Singular. If buffer exists and Singular is running, just switches to buffer. If a file `~/.emacs_singularrc' exists, it is given as initial input. Note that this may lose due to a timing error if Singular discards input when it starts up. If a new buffer is created it is put in Singular interactive mode, giving commands for sending input and handling output of Singular. See `singular-interactive-mode'. Every time `singular-other' starts a new Singular process it runs the hooks on `singular-exec-hook'. Type \\[describe-mode] in the Singular buffer for a list of commands." (interactive (let* ((exec (read-file-name "Singular executable: ")) ;; Remark: Do NOT call `expand-file-name' after the ;; above read-file-name! It has to be possible to enter a command ;; without path which should be searched for in $PATH. ;; `start-process' is intelligent enough to start commands with ;; not-expanded name. (dir (file-name-directory (read-file-name "Default directory: " nil (or singular-directory-default default-directory) t))) (switch "") (bufname (singular-generate-new-buffer-name (downcase (file-name-nondirectory exec))))) ;; Get command line arguments and append magic switches ;; TODO: Think about default value: Up to now: ;; Use singular-switches-default as init value for read-from-minibuffer (let ((switches-default singular-switches-default)) (while switches-default (setq switch (concat switch (car switches-default) " ")) (setq switches-default (cdr switches-default)))) ;; note: magic switches are appended by `singular-internal' (setq switch (split-string (read-from-minibuffer "Singular options: " switch nil nil singular-switches-history) " ")) ;; Generate new buffer name (let (done) (while (not done) (setq bufname (read-from-minibuffer "Singular buffer name: " bufname)) (setq done (or (not (get-buffer bufname)) (y-or-n-p "Buffer exists. Switch to that buffer? "))))) (if (string-match "^\\*\\(.*\\)\\*$" bufname) (setq bufname (substring bufname (match-beginning 1) (match-end 1)))) (list exec dir switch bufname))) (singular-internal executable directory switches name)) (defun singular-exit-singular (&optional kill-singular-buffer) "Delete Singular process and kill Singular buffer. Deletes the buffers Singular process without warning and writes back the input history to file. If called with prefix argument, kills the Singular buffer." (interactive "P") (singular-debug 'interactive (message "exit singular called")) (singular-kill-singular) (if kill-singular-buffer (kill-buffer (current-buffer)))) ;;}}} ;;}}} (provide 'singular) ;;; Local Variables: ;;; fill-column: 75 ;;; End: ;;; singular.el ends here. singular-4.0.3+ds/emacs/singular.xpm000066400000000000000000000024711266270727000174230ustar00rootroot00000000000000/* XPM */ static char * sing_xpm[] = { "33 33 3 1", " c #BDBDBEBEBDBD", ". c #000000000000", "X c #FFFFFFFFFFFF", " ", " .. ", " ..XX ", " ..XX ", " ..XX ", " ..XX ", " ..XX ", " ..XX ", " ..XX ", " .... ..XX ", " ..XX... ..XX ", " ..XX X ... ..X ", " .X .. ..X ", " .X .... ", " .X ..XXX.. ", " .XX ...X XX.. ", " .....XX XX.. ", " X XX.. ", " XX.. ", " XX.. ", " XX.. ", " XX.. ", " XX.. ", " XX.. ", " XX.. ", " XXX. ", " XX ", " ", " ", " ", " ", " ", " "}; singular-4.0.3+ds/factory/000077500000000000000000000000001266270727000154245ustar00rootroot00000000000000singular-4.0.3+ds/factory/AUTHORS000066400000000000000000000000001266270727000164620ustar00rootroot00000000000000singular-4.0.3+ds/factory/COPYING000066400000000000000000000034431266270727000164630ustar00rootroot00000000000000 SINGULAR version 4-0 Singular-Factory University of Kaiserslautern Department of Mathematics and Centre for Computer Algebra Authors: G.-M. Greuel, R. Stobbe, J. Schmidt, M. Lee, G. Pfister, H. Schoenemann Copyright (C) 1991-2016 Characteristic sets and factorization over algebraic function fields: Michael Messollen Copyright (C) 1996-2010 *NOTICE* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation ( version 2 or version 3 of the License ); with the following additional remarks: This package is part of the software SINGULAR. The GPL is valid for this package, other packages may have other copyrights. Their copyrights and licences can be found in the accompanying files which are distributed along with these packages. Files which contain code written by M. Messollen or contain code derived from code written by M. Messollen contain respective details. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA (see GPL) Please send any comments or bug reports to . Availability ============ The latest information about SINGULAR is always available from `http://www.singular.uni-kl.de'. singular-4.0.3+ds/factory/ChangeLog000066400000000000000000001656251266270727000172150ustar00rootroot00000000000000Mi 13. Okt 15:52:56 CEST 2010 - release 3-1-2 - removed macos 9 stuff - factorize for Z/p, Z/p(a) improved - windows port improved (.h files instead of .inc) Fri Feb 14 16:53:42 CET 2003 * hannes: bugfix could not factorize x2+xy+y2 in Fp(a)[x,y], a2+a+1=0 added tests in factorize(f,a) (isPurePoly(f,a)) added sort option to FpFactorizeUnivariateCZ and to NTL factor routines (NTLconvert.cc cf_factor.cc fac_cantzass.cc) Thu Nov 7 11:29:33 MET 2002 Hans Schoenemann * interface to NTL * many fixes Wed Aug 22 16:25:16 MET DST 2001 Hans Schoenemann * Version 1.3c: some utility functions for libfac * search for main var in factorize (experimental) 2000-09-02 Olaf Bachmann * configure.in, etc: support for omalloc 2000-08-04 Olaf Bachmann * ffops.cc: initialize ff_prime to 0, so that first call to ff_setprime always initializes ff_invtab. Tue Feb 16 19:00:03 1999 Jens Schmidt * GNUmakefile.in (basefactorysrc): `imm.cc' added (ftestm4src): `divrem.m4' added (distfiles): `factory.cfg' added * factory.cfg: new file * GNUmakefile.in (.PHONY): dependencies `doxy', `doxyclean' added (doxy, doxyclean): new targets (mostlyclean): dependency `doxyclean' added * GNUmakefile.in (doxysrc, doxyincl): new variables (doxyfiles): new variable * GNUmakefile.in (ftestm4src): `sqrfree.m4' added * GNUmakefile.in (ftestsrc, ftestincl): ntl-stuff added (ftestm4src): `gcd.ntl.m4', `revert.m4' added Wed Sep 23 19:05:47 1998 Jens Schmidt * fac_ezgcd.cc (ezgcd_specialcase): bug fix (???). See comments in the file for more information. Tue Jul 7 18:34:39 1998 Jens Schmidt * GNUmakefile.in (ftestm4src): `extgcd.m4' added to distribution Wed Jul 1 10:57:53 1998 * int_intdiv.cc (modulocoeff): extra call added for `mpz_mod_ui()' with void return value. Wrapped by #define `__MWERKS__'. Tue Jun 30 16:38:41 1998 Jens Schmidt * cf_algorithm.cc: doc fixes * cf_algorithm.cc (divides): bug fix. Works for zero f and g. More heuristic added. * cf_algorithm.cc (psr, psq, psqr): bug fix. Work for `x' with level lower than `level(f)' or `level(g)'. * cf_algorithm.h: doc fixes * ftmpl_inst.cc (tmax, tmin(Var, Var)): instantiations added * GNUmakefile.in (ftestm4src): `divides.m4' added to distribution Mon Jun 29 12:41:40 1998 Jens Schmidt * templates/ftmpl_functions.h: doc fixes * GNUmakefile.in (basefactorysrc): `cf_inline.cc' and `cf_iter_inline.cc' added to distribution * canonicalform.h (class CanonicalForm): friend declarations for `operator -', `operator +', `operator *', `operator /', `operator %', `div', `mod' replaced by ordinary declarations * canonicalform.cc, canonicalform.h (CanonicalForm, ~CanonicalForm, isOne, isZero, operator =): definitions of methods moved to `cf_inline.cc'. Declarations marked as `CF_INLINE' or `CF_NO_INLINE', resp. (operator -, operator +, operator *, operator /, operator %, div, mod): definitions of operators moved to `cf_inline.cc'. Declarations marked as `CF_INLINE' or `CF_NO_INLINE', resp. * canonicalform.h (CF_INLINE, CF_NO_INLINE): new #defines. `cf_iter_inline.cc' (conditionally) #included. * cf_iter.cc, cf_iter.h (operator++, coeff, hasTerms, exp): definitions moved to `cf_iter_inline.cc'. Declarations marked as `CF_INLINE' or `CF_NO_INLINE', resp. * cf_iter.h (CF_INLINE, CF_NO_INLINE): new #defines. `cf_iter_inline.cc' (conditionally) #included. * configure.in (enable_cf_inline): new `--enable'-option * config.h.in (CF_USE_INLINE): new #define * cf_inline.cc (CanonicalForm(Variable, int))): assertion added * cf_inline.cc (isOne, isZero, operator -(CF)): order of immediate checks changed * cf_inline.cc: new file * cf_iter_inline.cc (operator ++, coeff, exp): assertions fixed * cf_iter_inline.cc: new file Fri Jun 26 12:24:34 1998 Jens Schmidt * int_cf.cc, int_cf.h (isOne, isZero): pure virtual methods implemented. Declarations adapted. * int_rat.cc, int_int.cc, int_rat.h, int_int.h, int_poly.h (isZero, isOne): methods removed. Declarations adapted. * int_pp.cc (isOne, isZero): slightly speeded up. Doc fixes. * imm.h (imm_isone, imm_isone_p, imm_isone_gf): doc fixes * imm.h (imm_iszero, imm_iszero_p, imm_iszero_gf): doc fixes * int_poly.cc, int_pp.cc, int_rat.cc (neg): doc fixes * int_int.cc (neg): doc fixes. Slightly speeded up. * imm.h (imm_neg, imm_neg_p, imm_neg_gf): doc fixes Mon Jun 15 16:04:26 1998 Jens Schmidt * configure.in: doc fixes * configure.in: explicit path name generated slightly rewritten to work on HP's. Absolute path names are generated already by Makefile to keep `configure.in' more readable. Fri Jun 12 16:28:48 1998 Jens Schmidt * int_intdiv.cc: `canonicalform.h' included * gfops.cc, int_int.cc, readcf.y: order of includes fixed * timing.h: bug fix. Test on `WINNT' negated. Tue Jun 9 11:52:45 1998 Jens Schmidt * configure.in (ac_save_path): renamed to `$save_path'. All references changed (expl_datadir, expl_gftabledir): renamed to `$explicit_datadir', `$explicit_gftabledir', resp. All references changed. * configure.in: checks for gmp.h and libgmp.a search in `$includedir' and `$libdir', resp. * configure.in: new section added to get a safer explicit path expansion * configure.in: `$gftabledir' is not longer handled in a special way for Singular Mon Jun 8 17:26:55 1998 Jens Schmidt * singext.h: doc fix * gfops.cc, singext.h (cf_get_table): use `feFopen()' to load GF(q) tables if built with Singular. Declaration added to `singext.h' (by Hannes). * configure.in: calls to `AC_PATH_PROG' ``fixed''. Necessary because of some old autoconf version (by Olaf) * ftmpl_inst.cc: test on `WINNT' disabled with gcc Wed Jun 03 16:47:54 1998 * ftmpl_factor.h (template class Factor): `operator == ( const Factor &, const Factor &)' removed as friend and added as extra operator Wed Jun 03 14:47:41 1998 * timing.h, readcf.y, int_poly.cc, imm.h: test on WINNT disabled with gcc Mon May 11 11:36:22 1998 Jens Schmidt * config.h.in (FACTORY_INT64): unused declarations for MetroWerks removed * imm.cc (imm_mul): wrapped by `#ifdef __MWERKS__' * ffops.h (ff_bignorm): definition of `ff_bignorm' removed for MetroWerks (ff_mul): made a declaration for MetroWerks. Defined in `ffops.cc'. * imm.cc (imm_mul): new file for MetroWerks * imm.h (MINIMMEDIATELL, MAXIMMEDIATELL): definition of long long constants removed for mac (imm_mul): made a declaration for MetroWerks. Defined in `imm.cc'. * fac_cantzass.cc (CantorZassenhausFactorFFGF, CantorZassenhausFactorExt): new local variables `firstFactor', `secondFactor' introduced to fix order of evaluation of recursive factorizations Mon Apr 20 16:34:14 1998 Jens Schmidt * .cvsignore (stamp-h): entry re-added. After all, its necessary. * configure.in (MKINSTALLDIRS, MAKEHEADER): instead of using an absolute path, use relativ path and our own variables `FACTORY_MKINSTALLDIRS' and `FACTORY_MAKEHEADER'. Do not use cache to get the variables' values. * GNUmakefile.in (MKINSTALLDIRS, MAKEHEADER): use the values from `FACTORY_MKINSTALLDIRS' and `FACTORY_MAKEHEADER', resp. Tue Apr 14 14:05:47 1998 Wilfred Pohl * fac_univar.cc (UnivariateQuadraticLift): type for `log()' must be float, hence constant `2' replaced by `2.0' * config.h.in (FACTORY_INT64): new typedef for Metroworks compiler Mon Apr 6 14:06:49 MET DST 1998 Jens Schmidt * int_intdiv.cc: ***** merge from branch `factory-gcd' to main trunk * ftmpl_inst.cc: instantiations for `tabs( int )' added * fac_univar.cc (UnivariateQuadraticLift, UnivariateLinearLift): call to `div( CF, CF )' replaced by call to `operator / ( CF, CF )' Mon Mar 23 17:00:00 1998 Jens Schmidt * GNUmakefile.in (ftestm4src): references `$(ftestm4develsrc)' instead of `$(ftestm4src)' from development `GNUmakefile' to avoid problems when building distributions Tue Mar 17 16:57:10 MET 1998 Jens Schmidt * int_int.cc, int_int.h, int_poly.cc, int_poly.h, int_intdiv.cc, * ChangeLog: ***** merge from branch `factory-gcd' to main trunk * GNUmakefile.in: ***** merge from branch `factory-gcd' to main trunk * timing.h, examples/application.cc: ***** merge from branch `factory-gcd' to main trunk Tue Mar 17 14:22:56 1998 Jens Schmidt **************** <<< changes in branch `factory-gcd' **************** * int_poly.cc (dividecoeff, divremcoeff): use `divideTermList()' to do their work (divideTermList): new function copied from former `divTermList()'. Declaration added. * int_poly.cc (divTermList): uses `div()' to divide coefficients * int_int.cc (dividesame, dividecoeff, divsame, divcoeff, modulosame, modulocoeff, modsame, modcoeff, divremsame, divremcoeff, divremsamet, divremcoefft): methods moved to int_intdiv.cc. Slightly speeded up. * int_int.h (normalizeMPI, uiNormalizeMPI, normalizeMyself, uiNormalizeMyself): new `InternalIntger' methods. Declarations added. * int_int.h (class InternalInteger): static member `initialized' removed * int_intdiv.cc: new file * GNUmakefile.in (basefactorysrc): int_intdiv.cc added to distribution * timing.h (TIMING_END_AND_PRINT): added for windows (TIMING_DEFINE_PRINTPROTO, TIMING_PRINT): macros common to all platforms extracted from `#ifdef' directive * timing.h (TIMING_RESET): new macro Fri Mar 13 17:05:10 1998 Jens Schmidt * examples/application.cc (main): cosmetic changes * canonicalform.cc, canonicalform.h, cf_algorithm.cc, cf_factor.cc, * cf_map.cc, cf_map.h, fac_ezgcd.cc, fac_multivar.cc, * fac_univar.cc, fac_util.cc, fac_util.h, ffops.cc, ftmpl_array.h, * ftmpl_factor.h, ftmpl_functions.h, ftmpl_list.h, ftmpl_matrix.h, * sm_sparsemod.cc, sm_util.cc, sm_util.h, ftest/ChangeLog, * ftest/commonden.m4, ftest/norm.m4, templates/ftmpl_array.cc, * templates/ftmpl_factor.cc, templates/ftmpl_functions.h, * templates/ftmpl_list.cc, templates/ftmpl_matrix.cc, ChangeLog, * GNUmakefile.in, cf_algorithm.h, cf_gcd.cc, factory.template, * ftmpl_inst.cc: ***** merge from main trunk to branch `factory-gcd' **************** >>> changes in branch `factory-gcd' **************** Thu Mar 12 12:21:33 1998 Jens Schmidt * cf_gcd.cc (maxnorm): function removed. All references replaced by `maxNorm()'. * fac_univar.cc (norm): function removed. All references replaced by `euclideanNorm()'. * fac_util.cc (maxCoeff): function removed. Declarations adapted. All references replaced by `maxNorm()'. * cf_algorithm.cc (divides): slightly speeded up. * canonicalform.h (sign): new function * canonicalform.cc (blcm): new function. Declaration added. Wed Mar 11 10:39:33 1998 Jens Schmidt * cf_algorithm.cc (cden, common_den): renamed to `internalBCommonDen()' and `bCommonDen()', resp. Declarations adapted. All references changed. * cf_algorithm.h (abs): function `abs()' moved from `canonicalform.h' to `cf_algorithm.h'. All referring files include `cf_algorithm.h'. * cf_algorithm.cc (maxNorm, euclideanNorm): new functions. Declarations added. * cf_algorithm.cc (internalBCommonDen): uses `blcm()' instead of `lcm()' * GNUmakefile.in (ftestm4src): `norm.m4' and `commonden.m4' added to distribution * templates/ftmpl_functions.h (tabs): new function * ffops.cc (ff_setprime): uses `memset()' to clear inversion table * ftest/ChangeLog, ftest/ftest_io.cc, ftest/ftest_io.h, * ftest/ftest_util.cc, ftest/ftest_util.h, ftest/ftest_util.m4, * ftest/gcd.fex, ftest/runfex: ***** merge from branch `factory-gcd' to main trunk Tue Mar 10 15:44:06 1998 Jens Schmidt * factory.template, ftmpl_inst.cc, templates/ftmpl_array.cc, templates/ftmpl_factor.cc, templates/ftmpl_list.cc, templates/ftmp_matrix.cc: #include directives for mac fixed * ftmpl_array.h, ftmpl_factor.h, ftmpl_functions.h, ftmpl_list.h, ftmpl_matrix.h: new files. #include of `templates/ftmpl_xxx.h' changed to include of `ftmpl_xxx.h'. * GNUmakefile.in (basefactoryincl): new header files added to distribution Fri Feb 27 10:24:22 1998 Jens Schmidt **************** <<< changes in branch `factory-gcd' **************** * var_intglobal.cc, var_intglobal.h: files removed (do not belong to this branch!) * cf_primetab.h: file removed * cf_defs.h (SW_QUOTIENT, SW_FAC_USE_BIG_PRIMES): switches removed * cf_linsys.cc (linearSystemSolve, solve, bound determinant2): incorrect respective unused code removed * cf_char.cc (setCharacteristic): adapted to new prime generation scheme * cf_char.cc (setCharacteristic): previous adaption slightly changed. The largest small prime is now looked up only once. * cf_gcd.cc (gcd_poly_univar0): adapted to new prime generation scheme * fac_ezgcd.cc (findBound): adapted to new prime generation scheme * cf_linsys.cc (determinant): adapted to prime generation scheme * sm_sparsemod.cc (internalSparsemod): adapted to new prime generation scheme * fac_univar.cc (choosePrimes): adapted to new prime generation scheme * sm_sparsemod.cc (sparsemod): debug output added * fac_univar.cc (cf2double): function removed * fac_univar.cc (UnivariateQuadraticLift, UnivariateLinearLift): argument `Gamma' removed. All callers changed. * fac_univar.cc (UnivariateQuadraticLift, UnivariateLinearLift): call to `div( CF, CF )' replaced by call to `operator / ( CF, CF )' Thu Feb 26 17:58:31 1998 Jens Schmidt * gcd_pmultiv.h (class CFPrimitiveMultivariateGCD): renamed to `CFPrimitiveMultivariateGcd'. All references changed. (class CFSubResGCD): renamed to `CFSubResGcd'. All references changed. * gcd_pmultiv.h (class CFPrimitiveMultivariateGCD): does no longer inherit virtual from `CFPrimitiveGcd' (class CFSubResGcd): does no longer inherit from `CFPrimitiveUnivariateGCD' * gcd_pmultiv.h (class CFSubResGcd): new method `clone()' * gcd_pmultiv.h: new file * gcd_pmultiv.cc (CFSubResGcd::execute): bug fix. Superfluous break removed. (execute): bug fix. Assertion fixed. * gcd_pmultiv.cc: new file **************** >>> changes in branch `factory-gcd' **************** Fri Feb 20 17:41:23 1998 Jens Schmidt * GNUmakefile.in (installcf, installmem): `ranlib' libraries after installing them for SUN machines Tue Feb 10 10:47:04 1998 Jens Schmidt * cf_switches.h: doc fix Mon Feb 9 15:57:07 1998 Ruediger Stobbe * cf_factor.cc (factorize): factorize now handles characteristic 0 correct, e.g. rational coefficients and SW_RATIONAL = ON. Mon Feb 9 11:40:41 1998 Jens Schmidt * cf_primetab.cc: new file Thu Feb 5 16:53:21 1998 Jens Schmidt * configure.in (enable_timing, enable_debugoutput): extra timing and debugoutput magic removed * GNUmakefile.in (@timingtargets@, @debouttargets@, @debtimingtargets@): extra timing and debugoutput magic removed Tue Feb 3 14:03:00 1998 Jens Schmidt * GNUmakefile.in (ftestm4src): `bextgcd.m4' and `bgcd.m4' removed. References variable `ftestm4src' instead. Mon Feb 2 09:55:16 1998 Jens Schmidt * cf_chinese.cc (chineseRemainder( const CanonicalForm & ...)): completely rewritten Fri Jan 30 15:06:26 1998 Jens Schmidt * cf_chinese.cc (chineseRemainder): debug output added * cf_chinese.cc (chineseRemainder( const CFArray & ...)): slightly speeded up * cf_gcd.cc (iextgcd, igcd): functions removed. All references replaced by `bextgcd()' and `bgcd()', resp. * canonicalform.h (iextgcd): declaration removed Thu Jan 22 10:38:34 1998 Jens Schmidt * int_cf.cc, int_int.cc int_rat.cc (bgcdsame, bgcdcoeff, bextgcdsame, bextgcdcoeff): new methods. Declarations added. * GNUmakefile.in (ftestm4src): `bgcd.m4' and `bextgcd.m4' added to distribution * canonicalform.h (mvar): bug fix. Declared as `Variable mvar (...)'. * canonicalform.cc (bgcd, bextgcd): new functions. Declarations added. Fri Jan 16 09:08:17 1998 Jens Schmidt * cf_switches.h: doc fix * cf_algorithm.h (divides): declaration moved from canonicalform.h to cf_algorithm.h * cf_switches.cc: doc fix Tue Jan 13 14:56:42 1998 Olaf Bachmann * configure.in: changed order of library checks (-lm before -lgmp); check for atof in -lm check, to work around a bug on some linux machines. Tue Jan 6 11:01:23 1998 Jens Schmidt * .cvsignore (stamp-h): entry removed Wed Dec 17 09:56:25 1997 Jens Schmidt * canonicalform.cc (operator ==, operator !=): rewritten and speeded up (operator >): slightly speeded up * int_cf.h (class InternalCF): `sign()' declared as const * int_poly.cc (comparesame): doc and assertion fix * int_int.cc (sqrt, ilog2): assertion fixes * int_pp.cc (comparecoeff): assertion fix * int_rat.cc (comparesame): doc fix * int_cf.cc (InternalCF::sign): method made pure virtual. Declaration adapted. * int_cf.cc (taildegree): bug fix. Did not check whether CO is zero. * imm.h (imm_cmp): doc fix * canonicalform.cc (CanonicalForm::gcd): method removed. Declaration adapted. * canonicalform.cc (degree, taildegree): one more time slightly speeded up. Hopefully for the last time. Fri Dec 12 10:06:33 1997 Jens Schmidt * imm.h (imm_cmp_p, imm_cmp_gf): comparisons fulfill law of trichitomy * readcf.y (yylex): parser reads generator from GF(q) correctly Tue Dec 9 10:03:07 1997 Jens Schmidt * GNUmakefile.in (.PHONY): dependencies `$(srcdir)/winnt/factory.h' and `$(srcdir)/winnt/factoryconf.h' added * winnt/factory.h: automatically created from `factory.template' using `makeheader' * winnt/factoryconf.h: automatically created from `factoryconf.template' using `makeheader' * GNUmakefile.in (dist): dependencies `$(srcdir)/winnt/factory.h' and `$(srcdir)/winnt/factoryconf.h' added ($(srcdir)/winnt/factory.h): new target ($(srcdir)/winnt/factoryconf.h): new target * GNUmakefile.in (distntfile): new variable (distfiles): `$distntfiles' added to distribution (dist): creates directory `winnt/' (distfiles): `bin/makeheader.pl' added to distribution * config.h.in (FACTORY_INT64): new define * bin/makeheader.pl: new file * int_poly.cc (comparecoeff): unused argument `acoeff' removed Mon Dec 8 18:56:39 1997 Jens Schmidt * INSTALL, README: doc fixes for the Windows NT port Thu Nov 27 21:00:00 1997 Ruediger Stobbe * winnt: new directory containing configuration files for Microsoft Windows NT port using MS Visual C++ 5.0 * winnt/INSTALL.nt: new file that describes the make process on Windows NT * winnt/nt.mak: Makefile for Windoes NT * winnt/config.h: preconfigured file for Windows NT * winnt/factoryconf.h: for the first time this file is a hand-made version of factoryconf.h for Windows NT * winnt/factory.h: for the first time this file is a hand-made version of factory.h for Windows NT * config.h.in: new typedef FACTORY_INT64 for 64 bit integer type of various platforms (currently 'long long int' for gcc and '__int64' for MS VC++) * readcf.y: malloc.h and memory.h are included in the case of WINNT to have prototypes for alloca and memcpy * ffops.h: now uses FACTORY_INT64 instead of long long int * ffops.cc: now uses FACTORY_INT64 instead of long long int * imm.h: now uses FACTORY_INT64 instead of long long int * int_poly.cc: includes strstrea.h instead of strstream.h in the case of WINNT (a typical Microsoft 8.3 problem - its a pity) * cf_random.cc: the way const data members were used was not conforming to the C++ standard. Now there is a version of RandomGenerator that should run the same way on gcc as well as on CodeWarrior (mac) and MS VC++ (nt) and every other compiler conforming to the C++ standard * fac_iterfor.cc: fixed assertion that refers to a variable that was not in the scope. Wondering why gcc compiled it * fac_sqrfree.cc: isSqrFreeZ now returns a bool, as declared in the prototype. Again wondering about gcc's behaviour * sm_sparsemod.cc: array declaration of varf, varg and schnitt on on the heap instead on the stack because the array size is not a constant. delete [] is called at a suitable place * fac_cantzass.h: MS VC++ does not like a default value for a parameter that is a reference (in some sense this is good behaviour) Therefore there are now no default values for the parameter list of FpFactorizeUnivariateCZ * fac_cantzass.cc: No reference parameters for FpFactorizeUnivariateCZ * cf_factor.cc: FpFactorizeUnivariateCZ is called with full parameter list * fac_univar.cc: FpFactorizeUnivariateCZ is called with full parameter list * ftmpl_inst.cc: MS VC++ does not like to explicitly instantiate template functions - tmax and tmin are therefore not instatiated in the case of WINNT Anyway it is not clear if this file is needed when using MS VC++ since the handling of templates in MS VC++ done in the spirit of AT&T's Cfront compilers which do a more automatic job * templates/ftmpl_list.h: MS VC++ wants a forward declaration of template class List and template class ListIterator. This should be no problem for gcc * timing.h: changes in the case of WINNT Fri Nov 21 15:25:27 1997 Jens Schmidt * canonicalform.h (class CanonicalForm): inline method hasGcd() removed. * int_poly.cc (coeff): explicit cast to CanonicalForm added (coeff): cosmetic change * int_rat.cc (comparecoeff): bug fix. Did not calculate dummy correctly. (comparecoeff): assertion moved into `if' branch * int_pp.cc (comparesame): assertion added * int_int.cc (comparesame): assertion added * int_cf.cc (coeff): explicit cast to CanonicalForm added * int_cf.cc (comparecoeff): function made pure virtual. Declarations adapted. * int_cf.h (class InternalCF): new pure virtual function comparecoeff() * imm.h: doc fix * GNUmakefile.in (ftestm4src): fbinops.m4 added to distribution Thu Nov 20 16:21:51 1997 Jens Schmidt * imm.h: functions rereordered Wed Nov 19 12:21:27 1997 Jens Schmidt * gfops.h: functions reordered * imm.h (imm_sign): doc fix * imm.h: functions reordered Thu Nov 13 09:10:53 1997 Jens Schmidt * cf_chinese.cc (chineseRemainder): `const CF' in arguments changed to `const CF &'. Declaration adapted. * configure.in: doc fix * GNUmakefile.in (ftestall): new target (.PHONY): dependencies `ftestall' `ftestclean' `ftestdistclean' added * GNUmakefile.in (%.d): dependency generation uses temporary files (clean): removes these temporary files * GNUmakefile.in ($(ftestexec)): dependecy `factoryconf.h' added Wed Nov 12 18:08:51 1997 Jens Schmidt * configure.in: check for `GetOpt.h' removed Thu Nov 6 16:43:17 1997 Jens Schmidt * configure.in: check for `libg++.a' commented out Wed Nov 5 14:48:46 1997 Jens Schmidt * GNUmakefile.in (conftest): new target ($(ftestexec), gengftables.o): dependency `conftest' added * GNUmakefile.in (gengftables.o): some dependencies removed (gengftables): dependencies slightly changed * configure.in: exits with error on absence of libgmp.a or libm.a * configure.in: check for `unistd.h' added * configure.in: check for `libg++.a' added Wed Oct 29 12:41:04 1997 Jens Schmidt * configure.in: check for `ln -s' added * configure.in: checks for header files necessary for the FTE added * GNUmakefile.in (LN_S): new variable * GNUmakefile.in ($(ftestexec)): new target * GNUmakefile.in (ftestsrc, ftestincl, ftestm4src, ftestdistfiles, ftestexec): new variables (distsrc, distincl, distfiles, dist): FTE added to distribution (ftestclean, ftestdistclean): new targets (clean, distclean): dependencies ftestclean and ftestdistclean, resp., added * GNUmakefile.in (ftest/GNUmakefile): new target * GNUmakefile.in (gengftables): rule slightly simplified * test_install.cc (main): calls to `operator<<()' replaced by calls to `printf()' * configure.in (M4FLAGS): new output variable * configure.in (M4): check for `m4' added * configure.in: creates `ftest/GNUmakefile' Tue Oct 28 14:46:08 1997 Jens Schmidt **************** Factory Version 1.3b released **************** * NEWS: updated to 1.3b * README: doc fix. Updated to 1.3b. * INSTALL: doc fix. Updated to 1.3b. * configure.in (factory_version): updated to 1.3b * examples/GNUmakefile: doc fix * configure.in (factory_configuration): new variable * config.h.in (FACTORYCONFIGURATION): new #define * configure.in (ac_cv_shift): set to `yes' in case of cross compiling * examples/application.cc (main): check on existence of GF(q) tables removed Mon Oct 27 15:14:19 1997 Jens Schmidt * examples, examples/GNUmakefile, examples/application.cc, examples/gcd.cc, examples/factorize.cc: new files * GNUmakefile.in (distfiles, dist): `examples/' and `examples/*' added to distribution * canonicalform.cc (operator >, operator <): bug fix. Calls `comparecoeff()' in the right way. Fri Oct 24 18:44:37 1997 Jens Schmidt * GNUmakefile.in (TMPLCXXFLAGS): set to `$(LIBCXXFLAGS)' * cf_gcd.cc (gcd): bug fix. Handles polynomials with rational coefficients correctly Thu Oct 23 14:13:42 1997 Jens Schmidt * ftmpl_inst.cc: implicit instantiations of `ListItem' changed to explicit instantiations * factory.template, factoryconf.template, gengftables.cc, ftmpl_inst.cc: doc fix * cf_globals.cc (factoryConfiguration): new external variable. Declaration added. * test_install.cc (main): prints factoryConfiguration Wed Oct 22 15:41:30 1997 Jens Schmidt * configure.in: doc fixes * canonicalform.cc (operator ()): speeded up * cf_random.cc (factoryrandom): returns a random number without calculating any remainder if n equals zero * ffops.cc (ff_setprime): does not clear table of primes if the prime number used last time equals new one Tue Oct 21 13:24:48 1997 Jens Schmidt * test_install.cc: new file * GNUmakefile.in (distsrc): distribution file test_install.cc added (installtest, test_install, iftmpl_inst.o, test_install.o): new targets (clean): removes test_install (.PHONY): phony target installtest added Wed Oct 15 16:31:53 1997 Jens Schmidt * canonicalform.cc (taildegree): slightly speeded up * canonicalform.cc (operator []): assertion added. Bug fix (did not work for immediates). * canonicalform.cc (den, deriv, operator []): explicit casts to CanonicalForm added (sqrt): explicit calls to CFFactory::basic removed Tue Oct 14 16:47:28 1997 Jens Schmidt * canonicalform.cc (mvar, degree): slightly speeded up Fri Oct 10 10:19:07 1997 Jens Schmidt * gfops.cc (gf_get_table): casts to 'char *' added to avoid warnings * int_pp.cc: superfluous arguments removed * int_int.cc: doc fix * int_cf.cc: doc fix * int_rat.cc: doc fix * int_cf.cc (den): returns 'CFFactory::basic( 1 )' instead of 'genOne()' * canonicalform.cc (LC, degree( v ), tailcoeff, deriv): slightly speeded up * canonicalform.cc (Lc): new method. Declaration added. * int_cf.cc (Lc): new method. Declaration added. * int_poly.cc (Lc): new method. Declaration added. Thu Oct 9 10:20:56 1997 Jens Schmidt * cf_algorithm.cc (divides): moved from canonicalform.cc to cf_algorithm.cc. Declaration moved, too. In all files which refer to this function #include of cf_algorithm.h added. (divides): doc fix * canonicalform.cc (divides): moved to cf_algorithm.cc. Declaration moved, too. * canonicalform.h (Lc): new function Wed Oct 1 14:21:53 1997 Jens Schmidt * cf_random.h: (factoryrandom): n defaults to zero * cf_random.cc (factoryrandom): checks for n = zero added Tue Sep 30 10:22:43 1997 Jens Schmidt * GNUmakefile.in (%.d): order of dependencies changed Mon Sep 29 08:11:42 1997 Jens Schmidt * GNUmakefile.in (%.d): `factoryconf.h' added as dependency * canonicalform.h: doc fix * cf_ops.cc (size( CF ), size( CF, Var )): new functions. Declarations added. * fac_univar.cc: doc fix * cf_chinese.cc: doc fix * cf_resultant.cc: doc fix * cf_gcd.cc (maxnorm): spurious variable `h' removed * cf_gcd.cc (balance): slightly speeded up Fri Sep 26 12:54:41 1997 Jens Schmidt * cf_assert.h: prints the function now where the assrtion occured if we are translating with gcc Thu Sep 25 13:51:01 1997 Jens Schmidt * cf_gcd.cc (chinesePoly): function removed (gcd_poly_univar0): slightly speeded up * cf_gcd.cc (lcm): bug fix. Returns zero now if f or g equals zero. * cf_gcd.cc (gcd_poly): does not call sparsemod on univariate polynomials an longer * cf_gcd.cc (vcontent): assertion added. * cf_gcd.cc (content( CF, Variable )): slightly speeded up. Assertion added. Wed Sep 24 12:35:40 1997 Jens Schmidt * canonicalform.cc (deriv): speeded up Tue Sep 23 17:24:24 1997 Jens Schmidt * int_int.cc: doc fix * canonicalform.cc: doc fix Fri Sep 12 17:25:14 1997 Jens Schmidt * cf_gcd.cc (isqrt): function removed * canonicalform.cc: doc fix Wed Sep 10 15:36:15 1997 Jens Schmidt * int_cf.cc (InternalCF::sign): assertion added * int_rat.cc (InternalRational::sign): call to mpz_cmp_si() replaced by call to mpz_sgn() * int_pp.cc (InternalPrimePower::sign): call to mpz_cmp_si() replaced by call to mpz_sgn() * int_int.cc (InternalInteger::sign): call to mpz_cmp_si() replaced by call to mpz_sgn() * int_pp.cc, int_int.cc, int_rat.cc, int_poly.cc, int_cf.cc, canonicalform.cc (sign): doc fix * imm.h (imm_sign): bug fix. imm_sign() returned 0 for sign(1) when calculating in GF(q). * imm.h (imm_sign): bug bug fix * gfops.h (gf_sign): doc fix * configure.in (expl_datadir): initialization fixed. If $expl_datadir is relative we prepend the current working directory now. * cf_gcd.cc (isqrt): function removed Tue Sep 9 09:06:17 1997 Jens Schmidt * README: doc fix * INSTALL: doc fix * cf_globals.h: doc fix * cf_globals.cc: #include fix, doc fix * cf_primes.cc, fac_cantzass.cc, int_pp.cc, int_rat.cc: #include fix * cf_factor.cc: #include fix (factorize): cf_glob_switches.isOn() replaced by isOn() for sake of uniformity * cf_ops.cc (swapvar_between): arguments to operator * swapped * cf_ops.cc (swapvar_between, swapvar_rec): functions reordered and declarations removed * cf_ops.cc (swapvar_between1, swapvar_rec1, swapvar1): new experimental functions, to be removed in future * cf_chinese.cc: doc fix * fac_multihensel.cc: #include fix * fac_berlekamp.cc: #include fix * cf_util.cc: #include fix * ffops.h: #include fix Mon Sep 8 12:39:09 1997 Jens Schmidt * cf_algorithm.cc (psr, psq, psqr): assertions added * cf_algorithm.cc (psq, psqr): return correct values now if deg(f) < deg(g) (psr, psq, psqr): return correct values now if f = 0 * cf_algorithm.cc (cden): recursion terminates now for f in base domain instead for f in coefficient domain * cf_map.h: doc fix * cf_map.cc: doc fix * cf_algorithm.h: doc fix * cf_switches.h: doc fix * cf_switches.cc: doc fix Thu Sep 4 10:19:25 1997 Jens Schmidt * cf_ops.cc: (replacevar, replacevar_between): new functions * canonicalform.h (replacevar): new declaration * cf_algorithm.cc: doc fix * cf_resultant.cc: doc fix * cf_algorithm.cc: new file (psr, psq, psqr, cden, common_den): functions moved from cf_ops.cc to cf_algorithm.cc * cf_ops.cc (psr, psq, psqr, cden, common_den): functions moved to cf_algorithm.cc * cf_algorithm.h: declarations of functions from cf_algorithm.cc moved from canonicalform.h to cf_algorithm.h * canonicalform.h: declarations of functions from cf_algorithm.cc moved to cf_algorithm.h. In all files which refer to these functions #include of cf_algorithm.h added. * GNUmakefile.in (basefactorysrc): cf_algorithm.cc added to distribution * cf_ops.cc (apply): bug fix. In case f.inCoeffDomain() result is now initialized to f. Mon Sep 1 10:47:41 1997 Jens Schmidt * canonicalform.h (resultant): declaration moved to cf_algorithm.h * cf_algorithm.h (resultant): declaration moved from canonicalform.h to cf_algorithm.h * cf_ops.cc (resultant): function moved to cf_resultant.cc * cf_resultant.cc (trivialResultant): new function * cf_resultant.cc (resultant): moved from cf_ops.cc to cf_resultant.cc. Completely rewritten. * cf_ops.cc (psr): returns f now if deg(f) < deg(g) * cf_resultant.cc (subResChain): new function * cf_algorithm.h (subResChain): new declaration * cf_factor.cc (factorize( CanonicalFormn, bool ), sqrFree): default argument initializer from definition removed Fri Aug 29 09:10:28 1997 Jens Schmidt * canonicalform.cc (degree( Variable )): slightly speeded up (deriv( Variable )): slightly speeded up * canonicalform.h (deriv): doc fix * canonicalform.cc (deriv( Variable )): assertion added (deriv( Variable )): bug fix * cf_algorithm.h: declarations of functions from cf_linsys.cc moved from canonicalform.h to cf_algorithm.h * canonicalform.h: declarations of functions from cf_linsys.cc moved to cf_algorithm.h * cf_factor.cc (sqrFree( CF )): removed (sqrFree( CF, bool )): default argument initializer added (factorize( CF, bool )): default argument initializer added * cf_algorithm.h (sqrFree( CF )): declaration removed (sqrFree( CF, bool )): default argument initializer added to declaration (factorize( CF, bool )): default argument initializer added to declaration * GNUmakefile.in (basefactorysrc): cf_resultant.cc added to distribution * cf_algorithm.h: declarations from cf_factor.h moved to cf_algorithm.h * cf_factor.h: declarations moved to cf_algorithm.h. cf_factor.h removed. All #include statements changed. * GNUmakefile.in (basefactoryincl): cf_factor.h removed from distribution * canonicalform.h: declarations of functions from cf_factor.cc removed. In all files which refer to these functions #include of cf_algorithm.h added. * cf_algorithm.h: new file * cf_algorithm.h: declarations from cf_chinese.h moved to cf_algorithm.h * cf_chinese.h: declarations moved to cf_algorithm.h. cf_chinese.h removed. All #include statements changed. * GNUmakefile.in (basefactoryincl): cf_chinese.h removed from distribution. cf_algorithm.h added to distribution. Thu Aug 28 09:21:15 1997 Jens Schmidt * cf_map.h: superfluous '#include "templates/ftmpl_functions.h"' removed Mon Aug 4 16:57:27 1997 Jens Schmidt * canonicalform.cc (sqrt): doc fix Fri Aug 1 11:06:58 1997 Jens Schmidt * cf_map.cc (operator << ( ostream& s, const CFMap & m )): rewritten * configure.in: checks for compiler characteristic are done with C instead of C++ Thu Jul 31 14:59:07 1997 Jens Schmidt * fac_univar.cc (kBound): bound fixed * canonicalform.h (sqrt): doc fix * canonicalform.cc (sqrt): immediate case completely rewritten Wed Jul 30 09:40:08 1997 Jens Schmidt * cf_linsys.cc (bound): off by one errors fixed (linearSystemSolve): off by one errors fixed * cf_linsys.cc (bound): debug output added * cf_linsys.cc (bound): returns now bound + 1 * canonicalform.cc (sqrt): sqrt(0) works now (sqrt): assertion added (sqrt): 'int h' changed to 'long long h'. Casts added. * cf_defs.h (SW_RATIONAL, SW_QUOTIENT, SW_SYMMETRIC_FF, SW_BERLEKAMP, SW_FAC_USE_BIG_PRIMES, SW_FAC_QUADRATICLIFT, SW_USE_EZGCD, SW_USE_SPARSEMOD): #defines replaced by 'const int's * canonicalform.cc (fillVarsRec, getNumVars, getVars): moved to cf_ops.cc * cf_ops.cc (fillVarsRec, getNumVars, getVars): moved from canonicalform.cc to cf_ops.cc * cf_ops.cc: doc fix Thu Jul 24 12:44:46 1997 Jens Schmidt * GNUmakefile.in (distfiles): bin/folding.el and bin/fold-docu.el added Wed Jul 23 09:45:35 1997 Jens Schmidt * cf_map.h (class CFMap): references to List replaced by CFList * cf_map.cc (CFMap( CFList )): 'P.append()' replaced by 'P.insert()' * cf_chinese.cc (chineseRemainder( CF, ... )): operator % replaced by function mod() * README: doc fix Tue Jul 22 11:04:30 1997 Jens Schmidt * cf_map.cc (CFList, CFListIterator, MPListIterator): references to List, ListIterator, and ListIterator replaced by their respective typedefs * canonicalform.cc (initCanonicalForm): initialization of switches removed since they are initialized by constructor * bin/folding.el: new file * bin/fold-docu.el: new file * bin/fold-docu.el (fold-docu): works now for all fold marks * README: doc fix * cf_switches.h (CFSwitchesMax): new constant * cf_switches.h (class CFSwitches): number of switches replaced by references to 'const int CFSwitchesMax' * cf_switches.cc (CFSwitches): number of switches replaced by references to 'const int CFSwitchesMax' **************** Factory Version 1.3a released **************** * configure.in: doc fix * INSTALL: doc fix * NEWS: doc fix * README: doc fix Mon Jul 21 12:58:04 1997 Jens Schmidt * sm_sparsemod.cc (internalSparsemod): sparsemod() renamed to internalSparsemod() (sparsemod): new function which is a simple wrapper around internalSparsemod() * GNUmakefile.in (distfiles): NEWS and INSTALL added to distribution * configure.in (factory_version): version number incremented * INSTALL: version number incremented * README: version number incremented * configure.in: doc fix * GNUmakefile.in (dist): changed suffix of distribution suffix (distclean): changed suffix of distribution suffix * NEWS: doc fix * INSTALL: doc fix * INSTALL: new file * README: doc fix * GNUmakefile.in (installgftables): bug fixes undone (installgftables): completely rewritten Sat Jul 19 08:57:34 1997 Jens Schmidt * GNUmakefile.in (installgftables): bug fix * GNUmakefile.in (dist): output is more beautyful now * cf_gcd.cc (gcd_poly): call to sparsemod() added * cf_ops.cc (resultant): assertion added (resultant): new variable flipFactor (resultant): handling of trivial cases fixed (resultant): some other minor bug fixes * cf_ops.cc (resultant): doc fix * README: doc fix * NEWS: doc fix * GNUmakefile.in (uninstallgftables): brute force ('rm -rf') replaced by a safer variant Thu Jul 17 11:05:04 1997 Jens Schmidt * sm_util.cc: doc fix (interpol): doc fix * sm_util.h (REArray): bug fix * sm_sparsemod.cc: new file * GNUmakefile.in (basefactoryincl): files sm_util.h and sm_sparsemod.h added (basefactorysrc): files sm_util.cc and sm_sparsemod.cc added * NEWS: new file Wed Jul 16 11:35:06 1997 Jens Schmidt * .cvsignore (config.cache): new entry * canonicalform.cc (CanonicalForm::ilog2): new method * canonicalform.h (class CanonicalForm): new declaration of ilog2 (ilog2): new function * int_cf.cc (InternalCF::ilog2): new method * int_cf.h (class InternalCF): new declaration of ilog2 * int_int.cc (InternalInteger::ilog2): new method * int_int.h (class InternalInteger): new declaration of ilog2 * fac_univar.cc (norm, dnorm): function dnorm replaced by norm (kBound): uses ilog2() and norm() now Tue Jul 15 14:47:53 1997 Jens Schmidt * sm_util.h (REArray): new typedef. All references to Array changed to REArray. * sm_sparsemod.h: new file Mon Jul 14 10:00:59 1997 Jens Schmidt * sm_util.h: doc fix * sm_util.h (dinterpol): bug fix of declaration * sm_util.cc: doc fix * sm_util.cc: new file * sm_util.h: new file * int_cf.h (OBJDEL): spurious macro OBJDEL removed * README: new file * GNUmakefile.in (distfiles): README added to distribution * canonicalform.cc (initCanonicalForm): initialization of SW_USE_SPARSEMOD added * canonicalform.cc (CanonicalForm::degree( Variable )): doc fix * configure.in: doc fix * configure.in (libmem, headerfactory, factoryconf): output variables removed * configure.in (templatedir): initialization fixed Fri Jul 11 09:48:26 1997 Jens Schmidt * canonicalform.cc (CanonicalForm::degree): doc fix * GNUmakefile.in: dependencies checked * GNUmakefile.in: doc fix * GNUmakefile.in (.PHONY): phony targets updated * GNUmakefile.in (clean): core and *~ will not be removed any longer * GNUmakefile.in (depend): dependencies config.h and factoryconf.h removed * GNUmakefile.in (dist): 'chmod 777' removed * GNUmakefile.in (gengftables): dependency on 'all' replaced by dependency on $(libfactory) and libcfmem.a * GNUmakefile.in (gengftables.o): dependency cf_util.h removed (gengftables.o): dependencies factoryconf.h and config.h added * GNUmakefile.in (installcf, installgftables): bug fix (uninstallcf): bug fix * GNUmakefile.in (libmem, headerfactory, factoryconf): variables removed. All references changed (to 'libcfmem.a', 'factory.h', and 'factoryconf.h', resp.). * GNUmakefile.in (realmaintainer-clean): target removed * GNUmakefile.in (templatesrc, templateincl): file ftmpl_functions.h moved from $(templateincl) to $(templatesrc) * GNUmakefile.in (TESTLDFLAGS): flag '-L.' moved to target gengftables (gengftables): '-L.' moved from $(TESTLDFLAGS) to command * GNUmakefile.in (TESTCXXFLAGS): new variable (gengftables.o): references to $(LIBCXXFLAGS) replaced by references to $(TESTCXXFLAGS) Tue Jul 1 14:26:29 1997 Jens Schmidt * GNUmakefile.in (dist): use ln instead of cp to build distribution * canonicalform.cc (initCanonicalForm, mmInit): initialize memory managment if compiled with Singular. New declaration of mmInit(). * cf_random.cc (RandomGenerator): definitions of 'const long int' in class for mac removed. Instead, they are initialized in the constructor. * cf_random.h (factoryrandom, factoryseed): declarations marked as public Mon Jun 30 15:38:08 1997 Jens Schmidt * GNUmakefile.in (LIBCFLAGS, LIBCXXFLAGS, TMPLCXXFLAGS): option -Wall replaced by references to $(WARNFLAGS) (WARNFLAGS): new variable * imm.h (MINIMMEDIATELL, MAXIMMEDIATELL): initialization for mac added which does not like a 'LL' suffix * templates/ftmpl_matrix.cc: include paths for mac added * templates/ftmpl_list.cc: include paths for mac added * templates/ftmpl_factor.cc: include paths for mac added * templates/ftmpl_array.cc: include paths for mac added * factory.template: include paths for mac added * canonicalform.h: include paths for mac added * ftmpl_inst.cc: include paths for mac added * cf_gcd.cc: include paths for mac added * cf_map.cc: include paths for mac added * cf_map.h: include paths for mac added * fac_ezgcd.cc: include paths for mac added * configure: checked into RCS * readcf.cc: checked into RCS Fri Jun 27 10:33:29 1997 Jens Schmidt * bin/makeheader: checked into RCS * bin/install-sh: checked into RCS * bin/mkinstalldirs: checked into RCS Thu Jun 26 16:06:39 1997 Jens Schmidt * GNUmakefile.in: doc fix Wed Jun 25 10:02:51 1997 Jens Schmidt * configure.in (enable_gmp): bug fix (CPPFLAGS, LDFLAGS): bug fix Tue Jun 24 11:15:25 1997 Jens Schmidt * configure.in (with_builtingmp): command line option --with-builtingmp removed. All references to with_builtingmp and some additional code to deal with the command line options --with-gmp and --with-builtin-gmp removed, too. * configure.in (enable_assertions): disabled by default * configure.in (enable_gmp): with_gmp and with_builtin_gmp are set to '$(includedir)' if command line option --enable-gmp is given * configure.in: fixes in configure's messages * configure.in: doc fix Mon Jun 23 12:44:50 1997 Jens Schmidt * config.h.in: doc fix * factory.template: doc fix * factoryconf.template: doc fix Fri Jun 20 12:09:00 1997 Jens Schmidt * templates/: all files prefixed with 'ftmpl_'. All #include statements changed. * GNUmakefile.in (templatesrc, templateincl): all files prefixed with 'ftmpl_' * ftmpl_inst.cc, tmpl_inst.cc: tmpl_inst.cc renamed to ftmpl_inst.cc * GNUmakefile.in: all references to tmpl_inst replaced by references to ftmpl_inst Thu Jun 19 14:33:17 1997 Jens Schmidt * config.h.in: doc fix * factoryconf.template: doc fix * headers of almost all source files fixed Thu Jun 12 13:12:49 1997 Jens Schmidt * cf_globals.cc: doc fix Fri Jun 6 09:38:05 1997 Jens Schmidt * configure.in: some stupid warnings removed if "dangerous" combinations of with's/enable's are specified on commandline. Some other fixes in configure's messages. * configure.in (enable_memdebug): code removed which sets enable_memdebug to 'normal' since this is really never tested * configure.in (with_gmp, with_builtingmp): new command line options. Rest of configure.in adapted to new scheme of specifying where gmp lives. * configure.in: doc fix * GNUmakefile.in (distsrc, clean): gengftables added to distribution (distfiles): ChangeLog added to distribution Thu Jun 5 15:03:48 1997 Jens Schmidt * configure.in (enable_debugoutput, enable_timing): dependency on with_Singular removed so '--with-Singular --enable-debugoutput' and '--with-Singular --enable-timing' are possible * GNUmakefile.in (gengftables.o): check added which makes make complain if factory was not configured in the right way * configure.in: checks on sizeof(int) == sizeof(void *) == 4 removed * debug.h: dependency on #define SING_NDEBUG removed * factoryconf.template: doc fix * config.h.in: added to distribution as source file. config.h.in is not created from acconfig.h any longer. * acconfig.h: removed from distribution * GNUmakefile.in: ($(srcdir)/config.h.in, $(srcdir)/stamp-h.in, realmaintainerclean, dist, distfiles): changed to reflect the changes described above * config.h.in (INCL_CONFIG_H): new #define to prevent multiple inclusion of config.h * GNUmakefile.in ($(srcdir)/configure): make will not complain about a missing autoconf any longer * canonicalform.cc (operator>>): returns 0 again if #define SINGULAR and #define NOSTREAMIO are switched on Before Mon Jun 4 1997 Jens Schmidt This is a list of most of the changes I made after I took the responsibility for factory development and before I started to update the ChangeLog regularily. It is unlikely to be complete. Besides minor changes at "source code level" (bug fixes, new features) which are not really visible to the user in general there are quite a lot of changes at "organization level" (aka preprocessor level) and at "distribution level" (configure, Makefile). First, the changes at distribution level: * bin: some useful/necessary scripts added to distribution * install-sh: moved to bin * ChangeLog: added to distribution * configure.in: totally rewritten * config.h.in, conf.h.in: conf.h.in replaced by a totally rewritten config.h.in. Furthermore, config.h is now explicitly included in allmost every source file of the distribution. * factoryconf.template: new file. factoyconf.h is included instead of config.h in all source files which are not translated but installed (e.g. templates). * factory.template, factory.h: factory.h replaced by factory.template since makeheader is now included in the distribution * factory.template: rewritten to new makeheader syntax * factory.template, singfactory.h: Singular stuff moved from singfactory.h to factory.template. Wrapped by #ifdef SINGULAR. * singfactory.h: removed from distribution * gengftables.cc: code for generating gftables added to distribution * GNUmakefile.in, Makefile.in: Makefile.in replaced by a totally rewritten GNUmakefile.in * INSTALL: removed from distribution since not up to date * memman.h, mmalloc.c, mmallocs.c, mmheap.c, mmprivate.h, mmutil.c, mmallocb.c, mmblock.c, mminit.c, mmspec.c: new memory manager added to distribution * mpext.cc, mpext.h, mpfactory.h: removed from distribution. No more MP support. * config.h.in (MULTIPROTOCOL): #define MULTIPROTOCOL removed * int_int.h (class InternalInteger): declarations dependent on #define MULTIPROTOCOL removed * int_rat.h (class InternalRational): declarations dependent on #define MULTIPROTOCOL removed * readcf.cc: added to distribution since not all users have bison available Now for the changes at organization level: If we refer to the "DEBOUT macros", the "ASSERT macros", or the "TIMING macros" we mean one (or more) of the macros defined in debug.h, cf_assert.h, and timing.h, resp. * cf_assert.h (NOASSERT, SING_NDEBUG): #define SING_NDEBUG to switch off assertions replaced by #define NOASSERT. For sake of backward compatibility SING_NDEBUG works, too. * cf_assert.h (DEBINCLEVEL, DEBDECLEVEL, DEBOUTSL, DEBOUT, DEBOUTLN): DEBOUT macros moved to debug.h * assert.cc: renamed to debug.cc * debug.h, debug.cc: new files. DEBOUT macros moved from cf_assert.h/assert.cc to debug.h/debug.cc. All source files which need these macros include debug.h. * cf_assert.h (PVIRT_VOID, PVIRT_INTCF, PVIRT_BOOL, PVIRT_INT, PVIRT_CHARCC): PVIRT_*-macros moved from int_cf.h to cf_assert.h * int_cf.h (PVIRT_VOID, PVIRT_INTCF, PVIRT_BOOL, PVIRT_INT, PVIRT_CHARCC): PVIRT_*-macros moved to cf_assert.h * cf_assert.h (__ASSERT, __STICKYASSERT): the preprocessor instead of fprintf() pastes the message into the format string now * cf_assert.h (__ASSERT1, ASSERT1, STICKYASSERT1): new macros * cf_assert.h (__WARN, WARN, STICKYWARN): new macros * canonicalform.cc (operator>>): dependency on #define SINGULAR removed * cf_defs.h (INCL_CF_DEFS_H, incl_cf_defs_H): #define incl_cf_defs_H renamed to #define INCL_CF_DEFS_H so cf_defs.h is included only once * cf_factor.cc (factorize): dependency on #define MULTIFACTOR removed * cf_factory.cc (CFFactory::basic( int, int )): error message changed to call of ASSERT macros * fac_util.cc: (crossprod): error message changed to call of ASSERT macros * int_cf.cc: several error messages changed to calls of ASSERT macros * int_cf.h (InternalCF::InternalCF( InternalCF& )): error message changed to call of ASSERT macros * int_poly.cc (InternalPoly::InternalPoly( InternalPoly& )): error message changed to call of ASSERT macros * templates/array.cc (Array::operator[], Array::operator+=): error messages changed to calls of ASSERT macros * templates/list.cc (List::getFirst, List::getLast, ListIterator::getItem): error messages changed to calls of ASSERT macros * cf_gcd.cc: debug output changed to calls of DEBOUT macros * cf_linsys.cc: debug output rewritten and changed to calls of DEBOUT macros * fac_berlekamp.cc (QPrintFF, QPrintGF): definition and calls of QPrintFF(), QPrintGF() wrapped by #ifdef DEBUGOUTPUT * fac_univar.cc: debug output rewritten (hprint): calls to hprint() wrapped by calls to #define DEBOUTHPRINT, which definition depends on #define DEBUGOUTPUT (instead of SING_NDEBUG, as before). All callers changed. * cf_linsys.cc: superfluous #define TIMING removed * fac_distrib.cc: superfluous #undef DEBUGOUTPUT removed * fac_ezgcd.cc: some superfluous #defines (DEBUGOUTPUT, TIMING) and #includes removed * fac_multihensel.cc: some superfluous #defines (DEBUGOUTPUT, TIMING) removed * fac_multivar.cc: some superfluous #defines (DEBUGOUTPUT, TIMING) removed * fac_univar.cc: some superfluous #defines (DEBUGOUTPUT, TIMING) and #includes removed * config.h.in (GFTABLEDIR): new #define * gfops.cc (gf_get_table): uses #define GFTABLEDIR to get path to the GF(q) tables * config.h.in (MDEBUG, NOASSERT, TIMING, DEBUGOUTPUT): new #defines * config.h.in (NOSTREAMIO): new #define NOSTREAMIO to switch off stream IO. Operators <<, >>, and related stuff wrapped by #ifndef NOSTREAMIO. * debug.cc (deb_level, level_msg, deb_inc_level): deb_inc_level()'s output made more pretty at time of first call * debug.h (DEBOUT, DEBOUTLN): slightly modified so they print "objects" instead of only one "msg" and one "object". All callers changed. * debug.h (DEBUGOUTPUT): #define DEBUGOUTPUT is switched off now if #define SING_NDEBUG is switched on * fac_univar.cc (ZFactorizeUnivariate): timing stuff changed to calls of TIMING macros * gmpext.h: references to #define INCL_GCDEXT_H replaced by references to #define INCL_GMPEXT_H * initgmp.cc (initializeGMP): dependency on #define SINGULAR removed * mmallocb.c (MM_TEST, TEST): references to #define TEST replaced by references to #define MM_TEST * readcf.h: '#include ' replaced by '#include ' * readcf.y: dependency on #define COMEAU removed * templates/matrix.cc (ASSERT): definition of ASSERT macros replaced by inclusion of factoryconf.h * timing.h (HZ): new #define to calculate ticks per second in a more portable way. All references changed. * timing.h (TIMING_DEFINE_PRINT, TIMING_END_AND_PRINT): stream IO changed to std IO * timing.h (TIMING_END_AND_PRINT): new macro Last not least, changes at source code level: * canonicalform.cc (mapinto): fixed mapping from int to GF(q) * cf_factor.cc (sqrFree( CanonicalForm, boolean )): new function which sorts output if desired * cf_factor.cc (sqrFree( CanonicalForm )): changed to call new sqrFree() * canonicalform.h, cf_factor.h (sqrFree( CanonicalForm, boolean )): new declaration * fac_sqrfree.cc (compareFactors, sortCFFList): new functions used by new sqrFree() * fac_sqrfee.h (sortCFFList): new declaration * cf_defs.h (SW_USE_SPARSEMOD): new switch * cf_globals.cc (factoryVersion): new external * cf_globals.h (factoryVersion): new declaration * config.h.in (FACTORYVERSION): new #define * factory.template: '#include cf_globals.h' added because of version string * cf_linsys.cc (linearSystemSolve, determinant, determinant2): typedef int_ptr added (linearSystemSolve, determinant, determinant2): 'new (int*)[..]' replaced by 'new int_ptr[..]' * templates/matrix.h (Matrix::T_ptr): new typedef * templates/matrix.cc (Matrix::Matrix( int, int ), Matrix::Matrix( Matrix ), Matrix::operator=): 'new (T*)[..]' replaced by 'new T_ptr[..]' * cf_iter.h: superfluous '#include ' removed * cf_factor.h: superfluous '#include ' removed * cf_reval.h: superfluous '#include ' removed * memutil.c: superfluous '#include ' removed * mmalloc.c: superfluous '#include ' removed * cf_random.cc (RandomGenerator): new class (RanGen): new static (factoryrandom, factoryseed): calls to stdlib random generator replaced by methods of class RandomGenerator * cf_switches.h (RATIONAL): superfluous #define RATIONAL removed * int_int.cc (IntInt): superfluous #define IntInt removed * int_pp.cc (IntPP): superfluous #define IntPP removed * fac_univar.cc (initHG, ZFactorizeUnivariate): STICKYWARNings added because of some strange errors which occur in these functions * fac_univar.cc (kBound): cast to double added in calculation of the bound (UnivariateQuadraticLift): cast to double added in calculation of no_iter * fac_univar.cc (max_fp_fac, MAX_FP_FAC): '#define MAX_FP_FAC' replaced by 'const int max_fp_fac'. All references changed. * fac_univar.cc (ZFactorizeUnivariate): superfluous declaration of 'CFFList G' removed. Some trivial structural changes. Test on 'D != 0' (before deleting D) removed. * gfops.h (gf_gf2ff, gf_isff): declarations marked as public for Singular * factory.template: '#include "gfops.h"' added * gfops.cc (gf_get_table): gf_table[gf_q] is guaranteed to be 0 * gfops.cc (gf_get_table): rewritten. Major changes: copies Singulars tables if these are present instead of reading from disk. Uses standard IO instead of stream IO to read the tables. * singext.h (nfCharQ, nfM1, nfMinPoly, nfPlus1Table): declarations of Singular objects added to copy Singulars GF(q) tables * gfops.cc (gf_get_table): length of temporary buffer replaced by 'const int gf_maxbuffer' * gfops.cc (gf_isff): rewritten * gfops.cc (gf_maxtable, MAXTABLE): '#define MAXTABLE' replaced by 'const int gf_maxtable'. All references changed. * gfops.cc (gf_valid_combination): 'int m' replaced by references to gf_maxtable * gfops.cc (intVec2CF): new function * gfops.h (gf_mipo): new declaration * imm.h (class InternalCF): superfluous declaration of class InternalCF removed * imm.h (imm_intval): convertion from GF(q) to integer added * int_int.cc (InternalInteger::genOne): Ruedigers last fryday afternoon fix * variable.cc (Variable::name): casts to int added * variable.cc (Variable::Variable( char ), Variable::Variable( int, char ), rootOf): 'delete ...' changed to 'delete [] ...' where necessary singular-4.0.3+ds/factory/DegreePattern.cc000066400000000000000000000053041266270727000204660ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file DegreePattern.cc * * This file provides functions for manipulating DegreePatterns * * @author Martin Lee * **/ /*****************************************************************************/ #include "config.h" #include "DegreePattern.h" #include "cf_iter.h" #include "templates/ftmpl_functions.h" #include "gfops.h" #include "cf_factory.h" DegreePattern::DegreePattern (const CFList& l) { m_data = NULL; if (l.length() == 0) m_data = new Pattern(); else { Variable x= Variable (1); int p= getCharacteristic(); int d= 0; char cGFName= 'Z'; if (CFFactory::gettype() == GaloisFieldDomain) { d= getGFDegree(); cGFName= gf_name; } setCharacteristic(0); CanonicalForm buf= 1; CFListIterator k= l; for (int i= 0; i < l.length(); i++, k++) buf *= (power (x, degree (k.getItem(), x)) + 1); int j= 0; for (CFIterator i= buf; i.hasTerms(); i++, j++) ; ASSERT ( j > 1, "j > 1 expected" ); m_data = new Pattern( j - 1 ); int i= 0; for (CFIterator m = buf; i < getLength(); i++, m++) (*this) [i]= m.exp(); if (d > 1) setCharacteristic (p, d, cGFName); else setCharacteristic (p); } } void DegreePattern::intersect (const DegreePattern& degPat) { if (degPat.getLength() < getLength()) { DegreePattern bufDeg= *this; *this= degPat; return (*this).intersect (bufDeg); } int count= 0; int length= tmin (getLength(), degPat.getLength()); int* buf= new int [length]; for (int i= 0; i < length; i++) { if (degPat.find ((*this)[i])) { buf[i]= (*this)[i]; count++; } else buf[i]= -1; } ASSERT ( count > 0, "count > 0 expected" ); init (count); count= 0; for (int i= 0; i < length; i++) { if (buf[i] != -1) { (*this) [count]= buf[i]; count++; } } delete[] buf; } void DegreePattern::refine () { if (getLength() <= 1) return; int count= 0; int* buf= new int [getLength()]; int d= (*this) [0]; int pos; for (int i= 0; i < getLength(); i++) buf[i]= -1; for (int i= 1; i < getLength(); i++) { pos= (*this).find (d - (*this)[i]); if (pos) { buf[i]= (*this)[i]; count++; } } buf[0]= d; count++; if (count == getLength()) { delete [] buf; return; } int length= getLength(); ASSERT ( count > 0, "count > 0 expected" ); init (count); count= 0; for (int i= 0; i < length; i++) { if (buf[i] != -1) { (*this)[count]= buf[i]; count++; } } delete[] buf; return; } singular-4.0.3+ds/factory/DegreePattern.h000066400000000000000000000116631266270727000203350ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file DegreePattern.h * * This file provides a class to handle degree patterns. * * @author Martin Lee * **/ /*****************************************************************************/ #ifndef DEGREE_PATTERN_H #define DEGREE_PATTERN_H // #include "config.h" #include "cf_assert.h" #include "canonicalform.h" #include "cf_iter.h" #include "templates/ftmpl_functions.h" #include "gfops.h" /** @class DegreePattern DegreePattern.h "factory/DegreePattern.h" * * DegreePattern provides a functionality to create, intersect and refine * degree patterns. * * */ class DegreePattern { private: struct Pattern { int m_refCounter; ///< reference counter int m_length; ///< length of m_pattern int* m_pattern; ///< some array containing the degree pattern /// construct a Pattern from an int Pattern(int n): m_refCounter(1), m_length(n), m_pattern( new int[n]) {}; /// default constructor Pattern(): m_refCounter(1), m_length(0), m_pattern(NULL) {}; }* m_data; /// clear m_data void release() { ASSERT ( m_data != NULL, "non-null pointer expected"); ASSERT ( m_data->m_refCounter == 0, "ref count of 0 expected"); if( m_data->m_pattern != NULL ) delete[] m_data->m_pattern; m_data->m_pattern = NULL; delete m_data; m_data = NULL; } /// initialise a DegreePattern void init( int n ) { ASSERT ( m_data != NULL, "non-null pointer expected" ); ASSERT( m_data->m_refCounter > 0, "ref count > 0 expected" ); if( (--m_data->m_refCounter) < 1 ) release(); m_data = new Pattern(n); } /// getter /// /// @return @a getPattern returns a degree pattern inline int* getPattern() const { ASSERT( m_data != NULL, "non-null pointer expected" ); ASSERT( m_data->m_pattern != NULL, "non-null pointer expected" ); return m_data->m_pattern; } public: /// getter /// /// @return @a getLength returns the length of the degree pattern inline int getLength() const { ASSERT( m_data != NULL, "non-null pointer expected" ); return m_data->m_length; } /// operator [] /// /// @return @a operator[] returns the element at @a index inline int operator[] (const int index ///< [in] some int >= 0, < getLength() ) const { ASSERT( m_data != NULL, "non-null pointer expected" ); ASSERT( index >= 0 && index < getLength(), "bad index" ); ASSERT( getPattern() != NULL, "non-null pointer expected" ); return getPattern()[index]; } /// operator [] /// /// @return @a operator[] sets the element at @a index inline int& operator[] (const int index ///< [in] some int >= 0, < getLength() ) { ASSERT( m_data != NULL, "non-null pointer expected" ); ASSERT( index >= 0 && index < getLength(), "bad index" ); ASSERT( getPattern() != NULL, "non-null pointer expected" ); return getPattern()[index]; } /// default constructor DegreePattern(): m_data( new Pattern() ){} /// copy constructor DegreePattern (const DegreePattern& degPat ///< [in] some degree pattern ): m_data( degPat.m_data ) { ASSERT( degPat.m_data != NULL, "non-null pointer expected" ); m_data->m_refCounter++; }; /// construct a degree pattern from a list of (univariate) polys DegreePattern (const CFList& l ///< [in] some list of (univariate) polys ); /// assignment DegreePattern& operator= (const DegreePattern& degPat ///< [in] some degree ///< pattern ) { ASSERT( m_data != NULL, "non-null pointer expected" ); ASSERT( degPat.m_data != NULL, "non-null pointer expected" ); if( m_data != degPat.m_data ) { m_data = degPat.m_data; m_data->m_refCounter++; } return *this; } /// destructor ~DegreePattern () { ASSERT( m_data != NULL, "non-null pointer expected" ); if( (--m_data->m_refCounter) < 1 ) release(); } /// find an element @a x /// /// @return @a find returns the index + 1 of @a x, if @a x is an element of /// the degree pattern, 0 otherwise int find (const int x ///< [in] some int ) const { if (getLength() == 0) return 0; for (int i= 0; i < getLength(); i++) if ((*this)[i] == x) return i + 1; return 0; }; /// intersect two degree patterns void intersect (const DegreePattern& degPat ///< [in] some degree pattern ); /// Refine a degree pattern. Assumes that (*this)[0]:= @a d is the degree /// of the poly to be factored. Now for every other entry @a a there should be /// some entry @a b such that @a a+b= d. Elements which do not satisfy this /// relation are removed. void refine (); }; #endif /* DEGREE_PATTERN_H */ singular-4.0.3+ds/factory/ExtensionInfo.cc000066400000000000000000000042111266270727000205210ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file ExtensionInfo.cc * * This file provides member functions for ExtensionInfo * * @author Martin Lee * **/ /*****************************************************************************/ #include "config.h" #include "ExtensionInfo.h" ExtensionInfo::ExtensionInfo (const bool extension) { m_alpha= Variable (1); m_beta= Variable (1); m_gamma= CanonicalForm (); m_delta= CanonicalForm (); m_GFDegree= 1; m_GFName= 'Z'; m_extension= extension; } ExtensionInfo::ExtensionInfo (const Variable& alpha, const Variable& beta, const CanonicalForm& gamma, const CanonicalForm& delta, const int nGFDegree, const char cGFName, const bool extension) { m_alpha= alpha; m_beta= beta; m_gamma= gamma; m_delta= delta; m_GFDegree= nGFDegree; m_GFName= cGFName; m_extension= extension; } ExtensionInfo::ExtensionInfo (const Variable& alpha, const Variable& beta, const CanonicalForm& gamma, const CanonicalForm& delta) { m_alpha= alpha; m_beta= beta; m_gamma= gamma; m_delta= delta; m_GFDegree= 0; m_GFName= 'Z'; m_extension= true; } ExtensionInfo::ExtensionInfo (const Variable& alpha, const bool extension) { m_alpha= alpha; m_beta= Variable (1); m_gamma= CanonicalForm (); m_delta= CanonicalForm (); m_GFDegree= 0; m_GFName= 'Z'; m_extension= extension; } ExtensionInfo::ExtensionInfo (const Variable& alpha) { m_alpha= alpha; m_beta= Variable (1); m_gamma= CanonicalForm (); m_delta= CanonicalForm (); m_GFDegree= 1; m_GFName= 'Z'; m_extension= true; } ExtensionInfo::ExtensionInfo (const int nGFDegree, const char cGFName, const bool extension) { m_alpha= Variable (1); m_beta= Variable (1); m_gamma= CanonicalForm (); m_delta= CanonicalForm (); m_GFDegree= nGFDegree; m_GFName= cGFName; m_extension= extension; } singular-4.0.3+ds/factory/ExtensionInfo.h000066400000000000000000000134571266270727000203770ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file ExtensionInfo.h * * This file provides a class to store information about finite fields and * extensions thereof. * * * @author Martin Lee * **/ /*****************************************************************************/ #ifndef EXTENSION_INFO_H #define EXTENSION_INFO_H // #include "config.h" #include "canonicalform.h" /** @class ExtensionInfo ExtensionInfo.h "factory/ExtensionInfo.h" * ExtensionInfo contains information about extension. * If @a m_extension is true we are in an extension of some initial field. * If the initial field is \f$ F_p \f$ and we pass to \f$ F_p (\alpha) \f$ * then @a m_alpha is an algebraic variable, @a m_beta= Variable(1), * @a m_gamma= @a m_delta= 1, @a m_GFDegree= 0, @a m_GFName= 'Z'. If we pass * to some GF (p^k) then @a m_alpha= Variable (1), @a m_beta= Variable(1), * @a m_gamma= @a m_delta= 1, @a m_GFDegree= 1, @a m_GFName= 'Z'. * @n If the initial field is \f$ F_p (\epsilon) \f$, then @a m_beta= * \f$ \epsilon \f$, @a m_alpha an algebraic variable defining an extension of * \f$ F_p (\epsilon) \f$, @a m_gamma is a primitive element of * \f$ F_p (\alpha) \f$, @a m_delta is a primitive element of * \f$ F_p (\beta) \f$, @a m_GFDegree= 0, @a m_GFName= 'Z'. * @n If the initial field is GF(p^k), then @a m_alpha= Variable (1), * @a m_beta= Variable (1), @a m_gamma= 1, @a m_delta= 1, @a m_GFDegree()= k, * @a m_GFName= gf_name of the initial field. * @n If @a m_extension is false and the current field is \f$ F_p \f$ then * @a m_alpha= Variable (1), @a m_beta= Variable (1), @a m_gamma= 1, * @a m_delta= 1, @a m_GFDegree= 1, @a m_GFName= 'Z'. * @n If the current field is \f$ F_p (\alpha) \f$ then * @a m_alpha is some algebraic variable, @a m_beta= Variable (1), * @a m_gamma= 1, @a m_delta= 1, @a m_GFDegree= 0, @a m_GFName= 'Z'. * @n If the current field is GF then @a m_alpha= Variable (1), * @a m_beta= Variable (1), @a m_gamma= 1, @a m_delta= 1, * @a m_GFDegree= getGFDegree(), @a m_GFName= gf_name. * * @sa facFqBivar.h, facFqFactorize.h */ class ExtensionInfo { private: /// an algebraic variable or Variable (1) Variable m_alpha; /// an algebraic variable or Variable (1) Variable m_beta; /// a primitive element of \f$ F_p (\alpha) \f$ or 1 CanonicalForm m_gamma; /// a primitive element of \f$ F_p (\beta) \f$ or 1 CanonicalForm m_delta; /// GF degree or 1 int m_GFDegree; /// name of GF variable char m_GFName; /// indicates if we are in an extension of some initial field bool m_extension; public: /// \f$ F_p \f$ as initial field, if @a extension is true we are in some GF ExtensionInfo (const bool extension ///< [in] some bool ); /// Construct an @a ExtensionInfo ExtensionInfo (const Variable& alpha, ///< [in] some algebraic variable const Variable& beta, ///< [in] some algebraic variable const CanonicalForm& gamma, ///< [in] some primitive element ///< of \f$ F_p (\alpha) \f$ const CanonicalForm& delta, ///< [in] some primitive element ///< of \f$ F_p (\beta) \f$ const int nGFDegree, ///< [in] GFDegree of initial field const char cGFName, ///< [in] name of GF variable of ///< initial field const bool extension ///< [in] some bool ); /// \f$ F_p (\beta) \f$ as initial field and switch to an extension given by /// @a alpha, needs primitive elements @a gamma and @a delta for maps /// between \f$ F_p (\alpha) \subset F_p (\beta) \f$ ExtensionInfo (const Variable& alpha, ///< [in] some algebraic variable const Variable& beta, ///< [in] some algebraic variable const CanonicalForm& gamma, ///< [in] some primitive element ///< of \f$ F_p (\alpha) \f$ const CanonicalForm& delta ///< [in] some primitive element ///< of \f$ F_p (\beta) \f$ ); /// \f$ F_p (\alpha) \f$ as initial field, if @a extension is false. /// Else initial field is \f$ F_p \f$ ExtensionInfo (const Variable& alpha, ///< [in] some algebraic variable const bool extension ///< [in] some bool ); ExtensionInfo (const Variable& alpha ///< [in] some algebraic variable ); /// GF as initial field ExtensionInfo (const int nGFDegree, ///< [in] GF degree of initial field const char cGFName, ///< [in] name of GF variable const bool extension ///< [in] some bool ); /// getter /// /// @return @a getAlpha() returns @a m_alpha Variable getAlpha () const { return m_alpha; } /// getter /// /// @return @a getBeta() returns @a m_beta Variable getBeta () const { return m_beta; } /// getter /// /// @return @a getGamma() returns @a m_gamma CanonicalForm getGamma() const { return m_gamma; } /// getter /// /// @return @a getDelta() returns @a m_delta CanonicalForm getDelta() const { return m_delta; } /// getter /// /// @return @a getGFDegree() returns @a m_GFDegree int getGFDegree() const { return m_GFDegree; } /// getter /// /// @return @a getGFName() returns @a m_GFName char getGFName() const { return m_GFName; } /// getter /// /// @return @a isInextension() returns @a m_extension bool isInExtension() const { return m_extension; } }; #endif /* EXTENSION_INFO_H */ singular-4.0.3+ds/factory/FLINTconvert.cc000066400000000000000000000333211266270727000202120ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file FLINTconvert.cc * * This file implements functions for conversion to FLINT (www.flintlib.org) * and back. * * @author Martin Lee * **/ /*****************************************************************************/ #include #include "canonicalform.h" #include "fac_util.h" #include "cf_iter.h" #include "cf_factory.h" #include "gmpext.h" #include "singext.h" #include "cf_algorithm.h" #ifdef HAVE_FLINT #ifdef HAVE_CSTDIO #include #else #include #endif #ifdef __cplusplus extern "C" { #endif #ifndef __GMP_BITS_PER_MP_LIMB #define __GMP_BITS_PER_MP_LIMB GMP_LIMB_BITS #endif #include #include #include #include #include #include #include #include #if ( __FLINT_RELEASE >= 20400) #include #include #include #include #include #endif #ifdef __cplusplus } #endif #include "FLINTconvert.h" void convertCF2Fmpz (fmpz_t result, const CanonicalForm& f) { if (f.isImm()) fmpz_set_si (result, f.intval()); else { mpz_t gmp_val; f.mpzval(gmp_val); fmpz_set_mpz (result, gmp_val); mpz_clear (gmp_val); } } void convertFacCF2Fmpz_poly_t (fmpz_poly_t result, const CanonicalForm& f) { fmpz_poly_init2 (result, degree (f)+1); _fmpz_poly_set_length(result, degree(f)+1); for (CFIterator i= f; i.hasTerms(); i++) convertCF2Fmpz (fmpz_poly_get_coeff_ptr(result, i.exp()), i.coeff()); } CanonicalForm convertFmpz2CF (const fmpz_t coefficient) { if (fmpz_cmp_si (coefficient, MINIMMEDIATE) >= 0 && fmpz_cmp_si (coefficient, MAXIMMEDIATE) <= 0) { long coeff= fmpz_get_si (coefficient); return CanonicalForm (coeff); } else { mpz_t gmp_val; mpz_init (gmp_val); fmpz_get_mpz (gmp_val, coefficient); CanonicalForm result= CanonicalForm (CFFactory::basic (gmp_val)); return result; } } CanonicalForm convertFmpz_poly_t2FacCF (const fmpz_poly_t poly, const Variable& x) { CanonicalForm result= 0; fmpz* coeff; for (int i= 0; i < fmpz_poly_length (poly); i++) { coeff= fmpz_poly_get_coeff_ptr (poly, i); if (!fmpz_is_zero (coeff)) result += convertFmpz2CF (coeff)*power (x,i); } return result; } void convertFacCF2nmod_poly_t (nmod_poly_t result, const CanonicalForm& f) { bool save_sym_ff= isOn (SW_SYMMETRIC_FF); if (save_sym_ff) Off (SW_SYMMETRIC_FF); nmod_poly_init2 (result, getCharacteristic(), degree (f)+1); for (CFIterator i= f; i.hasTerms(); i++) { CanonicalForm c= i.coeff(); if (!c.isImm()) c=c.mapinto(); //c%= getCharacteristic(); if (!c.isImm()) { //This case will never happen if the characteristic is in fact a prime // number, since all coefficients are represented as immediates printf("convertCF2nmod_poly_t: coefficient not immediate!, char=%d\n", getCharacteristic()); } else nmod_poly_set_coeff_ui (result, i.exp(), c.intval()); } if (save_sym_ff) On (SW_SYMMETRIC_FF); } CanonicalForm convertnmod_poly_t2FacCF (const nmod_poly_t poly, const Variable& x) { CanonicalForm result= 0; for (int i= 0; i < nmod_poly_length (poly); i++) { ulong coeff= nmod_poly_get_coeff_ui (poly, i); if (coeff != 0) result += CanonicalForm ((long)coeff)*power (x,i); } return result; } void convertCF2Fmpq (fmpq_t result, const CanonicalForm& f) { //ASSERT (isOn (SW_RATIONAL), "expected rational"); fmpz_t tmp1, tmp2; fmpz_init (tmp1); fmpz_init (tmp2); if (f.isImm ()) { fmpz_set_si (tmp1, f.num().intval()); fmpz_set_si (tmp2, f.den().intval()); } else { mpz_t gmp_val; gmp_numerator (f, gmp_val); fmpz_set_mpz (tmp1, gmp_val); mpz_clear (gmp_val); gmp_denominator (f, gmp_val); fmpz_set_mpz (tmp2, gmp_val); mpz_clear (gmp_val); } fmpz_set (fmpq_numref (result), tmp1); fmpz_set (fmpq_denref (result), tmp2); fmpz_clear (tmp1); fmpz_clear (tmp2); } CanonicalForm convertFmpq_t2CF (const fmpq_t q) { bool isRat= isOn (SW_RATIONAL); if (!isRat) On (SW_RATIONAL); CanonicalForm num, den; mpz_t nnum, nden; mpz_init (nnum); mpz_init (nden); fmpz_get_mpz (nnum, fmpq_numref (q)); fmpz_get_mpz (nden, fmpq_denref (q)); CanonicalForm result; if (mpz_is_imm (nnum) && mpz_is_imm (nden)) { num= CanonicalForm (mpz_get_si(nnum)); den= CanonicalForm (mpz_get_si(nden)); mpz_clear (nnum); mpz_clear (nden); result= num/den; if (!isRat) Off (SW_RATIONAL); return result; } else { result= make_cf (nnum, nden, false); if (!isRat) Off (SW_RATIONAL); return result; } } CanonicalForm convertFmpq_poly_t2FacCF (const fmpq_poly_t p, const Variable& x) { CanonicalForm result= 0; fmpq_t coeff; long n= p->length; for (long i= 0; i < n; i++) { fmpq_init (coeff); fmpq_poly_get_coeff_fmpq (coeff, p, i); if (fmpq_is_zero (coeff)) { fmpq_clear (coeff); continue; } result += convertFmpq_t2CF (coeff)*power (x, i); fmpq_clear (coeff); } return result; } void convertFacCF2Fmpz_array (fmpz* result, const CanonicalForm& f) { for (CFIterator i= f; i.hasTerms(); i++) convertCF2Fmpz (&result[i.exp()], i.coeff()); } void convertFacCF2Fmpq_poly_t (fmpq_poly_t result, const CanonicalForm& f) { bool isRat= isOn (SW_RATIONAL); if (!isRat) On (SW_RATIONAL); fmpq_poly_init2 (result, degree (f)+1); _fmpq_poly_set_length (result, degree (f) + 1); CanonicalForm den= bCommonDen (f); convertFacCF2Fmpz_array (fmpq_poly_numref (result), f*den); convertCF2Fmpz (fmpq_poly_denref (result), den); if (!isRat) Off (SW_RATIONAL); } CFFList convertFLINTnmod_poly_factor2FacCFFList (const nmod_poly_factor_t fac, const mp_limb_t leadingCoeff, const Variable& x ) { CFFList result; if (leadingCoeff != 1) result.insert (CFFactor (CanonicalForm ((long) leadingCoeff), 1)); long i; for (i = 0; i < fac->num; i++) result.append (CFFactor (convertnmod_poly_t2FacCF ( (nmod_poly_t &)fac->p[i],x), fac->exp[i])); return result; } #if __FLINT_RELEASE >= 20400 CFFList convertFLINTFq_nmod_poly_factor2FacCFFList (const fq_nmod_poly_factor_t fac, const Variable& x, const Variable& alpha, const fq_nmod_ctx_t fq_con ) { CFFList result; long i; for (i = 0; i < fac->num; i++) result.append (CFFactor (convertFq_nmod_poly_t2FacCF ( (fq_nmod_poly_t &)fac->poly[i], x, alpha, fq_con), fac->exp[i])); return result; } #endif void convertFacCF2Fmpz_mod_poly_t (fmpz_mod_poly_t result, const CanonicalForm& f, const fmpz_t p) { fmpz_mod_poly_init2 (result, p, degree (f) + 1); fmpz_poly_t buf; convertFacCF2Fmpz_poly_t (buf, f); fmpz_mod_poly_set_fmpz_poly (result, buf); fmpz_poly_clear (buf); } CanonicalForm convertFmpz_mod_poly_t2FacCF (const fmpz_mod_poly_t poly, const Variable& x, const modpk& b) { fmpz_poly_t buf; fmpz_poly_init (buf); fmpz_mod_poly_get_fmpz_poly (buf, poly); CanonicalForm result= convertFmpz_poly_t2FacCF (buf, x); fmpz_poly_clear (buf); return b (result); } #if __FLINT_RELEASE >= 20400 void convertFacCF2Fq_nmod_t (fq_nmod_t result, const CanonicalForm& f, const fq_nmod_ctx_t ctx) { bool save_sym_ff= isOn (SW_SYMMETRIC_FF); if (save_sym_ff) Off (SW_SYMMETRIC_FF); for (CFIterator i= f; i.hasTerms(); i++) { CanonicalForm c= i.coeff(); if (!c.isImm()) c=c.mapinto(); //c%= getCharacteristic(); if (!c.isImm()) { //This case will never happen if the characteristic is in fact a prime // number, since all coefficients are represented as immediates printf("convertFacCF2Fq_nmod_t: coefficient not immediate!, char=%d\n", getCharacteristic()); } else { STICKYASSERT (i.exp() <= fq_nmod_ctx_degree(ctx), "convertFacCF2Fq_nmod_t: element is not reduced"); nmod_poly_set_coeff_ui (result, i.exp(), c.intval()); } } if (save_sym_ff) On (SW_SYMMETRIC_FF); } CanonicalForm convertFq_nmod_t2FacCF (const fq_nmod_t poly, const Variable& alpha) { return convertnmod_poly_t2FacCF (poly, alpha); } void convertFacCF2Fq_t (fq_t result, const CanonicalForm& f, const fq_ctx_t ctx) { fmpz_poly_init2 (result, fq_ctx_degree(ctx)); ASSERT (degree (f) < fq_ctx_degree (ctx), "input is not reduced"); _fmpz_poly_set_length(result, degree(f)+1); for (CFIterator i= f; i.hasTerms(); i++) convertCF2Fmpz (fmpz_poly_get_coeff_ptr(result, i.exp()), i.coeff()); _fmpz_vec_scalar_mod_fmpz (result->coeffs, result->coeffs, degree (f) + 1, &ctx->p); _fmpz_poly_normalise (result); } CanonicalForm convertFq_t2FacCF (const fq_t poly, const Variable& alpha) { return convertFmpz_poly_t2FacCF (poly, alpha); } void convertFacCF2Fq_poly_t (fq_poly_t result, const CanonicalForm& f, const fq_ctx_t ctx) { fq_poly_init2 (result, degree (f)+1, ctx); _fq_poly_set_length (result, degree (f) + 1, ctx); fmpz_poly_t buf; for (CFIterator i= f; i.hasTerms(); i++) { convertFacCF2Fmpz_poly_t (buf, i.coeff()); _fmpz_vec_scalar_mod_fmpz (buf->coeffs, buf->coeffs, degree (i.coeff()) + 1, &ctx->p); _fmpz_poly_normalise (buf); fq_poly_set_coeff (result, i.exp(), buf, ctx); fmpz_poly_clear (buf); } } void convertFacCF2Fq_nmod_poly_t (fq_nmod_poly_t result, const CanonicalForm& f, const fq_nmod_ctx_t ctx) { fq_nmod_poly_init2 (result, degree (f)+1, ctx); _fq_nmod_poly_set_length (result, degree (f) + 1, ctx); fq_nmod_t buf; fq_nmod_init2 (buf, ctx); for (CFIterator i= f; i.hasTerms(); i++) { convertFacCF2Fq_nmod_t (buf, i.coeff(), ctx); fq_nmod_poly_set_coeff (result, i.exp(), buf, ctx); fq_nmod_zero (buf, ctx); } fq_nmod_clear (buf, ctx); } CanonicalForm convertFq_poly_t2FacCF (const fq_poly_t p, const Variable& x, const Variable& alpha, const fq_ctx_t ctx) { CanonicalForm result= 0; fq_t coeff; long n= fq_poly_length (p, ctx); fq_init2 (coeff, ctx); for (long i= 0; i < n; i++) { fq_poly_get_coeff (coeff, p, i, ctx); if (fq_is_zero (coeff, ctx)) continue; result += convertFq_t2FacCF (coeff, alpha)*power (x, i); fq_zero (coeff, ctx); } fq_clear (coeff, ctx); return result; } CanonicalForm convertFq_nmod_poly_t2FacCF (const fq_nmod_poly_t p, const Variable& x, const Variable& alpha, const fq_nmod_ctx_t ctx) { CanonicalForm result= 0; fq_nmod_t coeff; long n= fq_nmod_poly_length (p, ctx); fq_nmod_init2 (coeff, ctx); for (long i= 0; i < n; i++) { fq_nmod_poly_get_coeff (coeff, p, i, ctx); if (fq_nmod_is_zero (coeff, ctx)) continue; result += convertFq_nmod_t2FacCF (coeff, alpha)*power (x, i); fq_nmod_zero (coeff, ctx); } fq_nmod_clear (coeff, ctx); return result; } #endif void convertFacCFMatrix2Fmpz_mat_t (fmpz_mat_t M, const CFMatrix &m) { fmpz_mat_init (M, (long) m.rows(), (long) m.columns()); int i,j; for(i=m.rows();i>0;i--) { for(j=m.columns();j>0;j--) { convertCF2Fmpz (fmpz_mat_entry (M,i-1,j-1), m(i,j)); } } } CFMatrix* convertFmpz_mat_t2FacCFMatrix(const fmpz_mat_t m) { CFMatrix *res=new CFMatrix(fmpz_mat_nrows (m),fmpz_mat_ncols (m)); int i,j; for(i=res->rows();i>0;i--) { for(j=res->columns();j>0;j--) { (*res)(i,j)=convertFmpz2CF(fmpz_mat_entry (m,i-1,j-1)); } } return res; } void convertFacCFMatrix2nmod_mat_t (nmod_mat_t M, const CFMatrix &m) { nmod_mat_init (M, (long) m.rows(), (long) m.columns(), getCharacteristic()); bool save_sym_ff= isOn (SW_SYMMETRIC_FF); if (save_sym_ff) Off (SW_SYMMETRIC_FF); int i,j; for(i=m.rows();i>0;i--) { for(j=m.columns();j>0;j--) { if(!(m(i,j)).isImm()) printf("convertFacCFMatrix2FLINTmat_zz_p: not imm.\n"); nmod_mat_entry (M,i-1,j-1)= (m(i,j)).intval(); } } if (save_sym_ff) On (SW_SYMMETRIC_FF); } CFMatrix* convertNmod_mat_t2FacCFMatrix(const nmod_mat_t m) { CFMatrix *res=new CFMatrix(nmod_mat_nrows (m), nmod_mat_ncols (m)); int i,j; for(i=res->rows();i>0;i--) { for(j=res->columns();j>0;j--) { (*res)(i,j)=CanonicalForm((long) nmod_mat_entry (m, i-1, j-1)); } } return res; } #if __FLINT_RELEASE >= 20400 void convertFacCFMatrix2Fq_nmod_mat_t (fq_nmod_mat_t M, const fq_nmod_ctx_t fq_con, const CFMatrix &m) { fq_nmod_mat_init (M, (long) m.rows(), (long) m.columns(), fq_con); int i,j; for(i=m.rows();i>0;i--) { for(j=m.columns();j>0;j--) { convertFacCF2nmod_poly_t (M->rows[i-1]+j-1, m (i,j)); } } } CFMatrix* convertFq_nmod_mat_t2FacCFMatrix(const fq_nmod_mat_t m, const fq_nmod_ctx_t& fq_con, const Variable& alpha) { CFMatrix *res=new CFMatrix(fq_nmod_mat_nrows (m, fq_con), fq_nmod_mat_ncols (m, fq_con)); int i,j; for(i=res->rows();i>0;i--) { for(j=res->columns();j>0;j--) { (*res)(i,j)=convertFq_nmod_t2FacCF (fq_nmod_mat_entry (m, i-1, j-1), alpha); } } return res; } #endif #endif singular-4.0.3+ds/factory/FLINTconvert.h000066400000000000000000000241331266270727000200550ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file FLINTconvert.h * * This file defines functions for conversion to FLINT (www.flintlib.org) * and back. * * @author Martin Lee * **/ /*****************************************************************************/ #ifndef FLINT_CONVERT_H #define FLINT_CONVERT_H // #include "config.h" #include "canonicalform.h" #include "fac_util.h" #ifdef HAVE_FLINT #ifdef __cplusplus extern "C" { #endif #ifndef __GMP_BITS_PER_MP_LIMB #define __GMP_BITS_PER_MP_LIMB GMP_LIMB_BITS #endif #include #include #include #include #include #include #include #include #if ( __FLINT_RELEASE >= 20400) #include #include #include #include #include #endif #ifdef __cplusplus } #endif #include /// conversion of a factory integer to fmpz_t void convertCF2Fmpz (fmpz_t result, ///< [in,out] an fmpz_t const CanonicalForm& f ///< [in] a CanonicalForm wrapping an ///< integer ); /// conversion of a factory univariate polynomial over Z to a fmpz_poly_t void convertFacCF2Fmpz_poly_t (fmpz_poly_t result, ///< [in,out] an fmpz_poly_t const CanonicalForm& f ///< [in] univariate poly over ///< Z ); /// conversion of a FLINT integer to CanonicalForm CanonicalForm convertFmpz2CF (const fmpz_t coefficient ///< [in] a FLINT integer ); /// conversion of a FLINT poly over Z to CanonicalForm CanonicalForm convertFmpz_poly_t2FacCF (const fmpz_poly_t poly, ///< [in] an fmpz_poly_t const Variable& x ///< [in] variable the result should ///< have ); /// conversion of a factory univariate polynomials over Z/p (for word size p) /// to nmod_poly_t void convertFacCF2nmod_poly_t (nmod_poly_t result, ///< [in, out] a nmod_poly_t const CanonicalForm& f ///< [in] univariate poly over ///< Z/p ); /// conversion of a FLINT poly over Z/p to CanonicalForm CanonicalForm convertnmod_poly_t2FacCF (const nmod_poly_t poly, ///< [in] a nmod_poly_t const Variable& x ///< [in] variable the result should ///< have ); /// conversion of a factory rationals to fmpq_t void convertCF2Fmpq (fmpq_t result, ///< [in,out] an fmpq_t const CanonicalForm& f ///< [in] a CanonicalForm wrapping a ///< rational ); /// conversion of a factory univariate polynomials over Q to fmpq_poly_t void convertFacCF2Fmpq_poly_t (fmpq_poly_t result, ///< [in,out] an fmpq_poly_t const CanonicalForm& f ///< [in] univariate poly over ///< Q ); /// conversion of a FLINT poly over Q to CanonicalForm CanonicalForm convertFmpq_poly_t2FacCF (const fmpq_poly_t p, ///< [in] an fmpq_poly_t const Variable& x ///< [in] variable the result should ///< have ); /// conversion of a FLINT factorization over Z/p (for word size p) to a /// CFFList CFFList convertFLINTnmod_poly_factor2FacCFFList ( const nmod_poly_factor_t fac, ///< [in] a nmod_poly_factor_t const mp_limb_t leadingCoeff, ///< [in] leading coefficient const Variable& x ///< [in] variable the result should ///< have ); /// conversion of a factory univariate poly over Z to a FLINT poly over /// Z/p (for non word size p) void convertFacCF2Fmpz_mod_poly_t ( fmpz_mod_poly_t result, ///< [in,out] fmpz_mod_poly_t const CanonicalForm& f, ///< [in] univariate poly over ///< Z const fmpz_t p ///< [in] some integer p ); /// conversion of a FLINT poly over Z/p (for non word size p) to a CanonicalForm /// over Z CanonicalForm convertFmpz_mod_poly_t2FacCF ( const fmpz_mod_poly_t poly, ///< [in] fmpz_mod_poly_t const Variable& x, ///< [in] variable the result ///< should have const modpk& b ///< [in] coeff bound to map ///< coeffs in (-p/2,p/2) ); #if __FLINT_RELEASE >= 20400 /// conversion of a FLINT element of F_q to a CanonicalForm with alg. variable /// alpha CanonicalForm convertFq_nmod_t2FacCF (const fq_nmod_t poly, ///< [in] fq_nmod_t const Variable& alpha ///< [in] algebraic variable ); /// conversion of a FLINT element of F_q with non-word size p to a CanonicalForm /// with alg. variable alpha CanonicalForm convertFq_t2FacCF (const fq_t poly, ///< [in] fq_t const Variable& alpha ///< [in] algebraic variable ); /// conversion of a factory element of F_q to a FLINT fq_nmod_t, does not do any /// memory allocation for poly void convertFacCF2Fq_nmod_t (fq_nmod_t result, ///< [in,out] fq_nmod_t const CanonicalForm& f, ///< [in] element of Fq const fq_nmod_ctx_t ctx ///< [in] Fq context ); /// conversion of a factory element of F_q (for non-word size p) to a FLINT fq_t void convertFacCF2Fq_t (fq_t result, ///< [in,out] fq_t const CanonicalForm& f, ///< [in] element of Fq const fq_ctx_t ctx ///< [in] Fq context ); /// conversion of a factory univariate poly over F_q (for non-word size p) to a /// FLINT fq_poly_t void convertFacCF2Fq_poly_t (fq_poly_t result, ///< [in,out] fq_poly_t const CanonicalForm& f,///< [in] univariate poly over Fq const fq_ctx_t ctx ///< [in] Fq context ); /// conversion of a factory univariate poly over F_q to a FLINT fq_nmod_poly_t void convertFacCF2Fq_nmod_poly_t (fq_nmod_poly_t result, ///< [in,out] fq_nmod_poly_t const CanonicalForm& f,///< [in] univariate poly ///< over Fq const fq_nmod_ctx_t ctx///< [in] Fq context ); /// conversion of a FLINT poly over Fq (for non-word size p) to a CanonicalForm /// with alg. variable alpha and polynomial variable x CanonicalForm convertFq_poly_t2FacCF (const fq_poly_t p, ///< [in] fq_poly_t const Variable& x, ///< [in] polynomial variable const Variable& alpha, ///< [in] algebraic variable const fq_ctx_t ctx ///< [in] Fq context ); /// conversion of a FLINT poly over Fq to a CanonicalForm with alg. variable /// alpha and polynomial variable x CanonicalForm convertFq_nmod_poly_t2FacCF (const fq_nmod_poly_t p, ///< [in] fq_nmod_poly_t const Variable& x, ///< [in] polynomial var. const Variable& alpha, ///< [in] algebraic var. const fq_nmod_ctx_t ctx ///< [in] Fq context ); #endif /// conversion of a factory matrix over Z to a fmpz_mat_t void convertFacCFMatrix2Fmpz_mat_t (fmpz_mat_t M, ///<[in,out] fmpz_mat_t const CFMatrix &m ///<[in] matrix over Z ); /// conversion of a FLINT matrix over Z to a factory matrix CFMatrix* convertFmpz_mat_t2FacCFMatrix(const fmpz_mat_t m ///<[in] fmpz_mat_t ); /// conversion of a factory matrix over Z/p to a nmod_mat_t void convertFacCFMatrix2nmod_mat_t (nmod_mat_t M, ///<[in,out] nmod_mat_t const CFMatrix &m ///<[in] matrix over Z/p ); /// conversion of a FLINT matrix over Z/p to a factory matrix CFMatrix* convertNmod_mat_t2FacCFMatrix(const nmod_mat_t m ///<[in] nmod_mat_t ); #if __FLINT_RELEASE >= 20400 /// conversion of a FLINT matrix over F_q to a factory matrix CFMatrix* convertFq_nmod_mat_t2FacCFMatrix(const fq_nmod_mat_t m, ///< [in] fq_nmod_mat_t const fq_nmod_ctx_t& fq_con, ///< [in] Fq context const Variable& alpha ///< [in] algebraic variable ); /// conversion of a factory matrix over F_q to a fq_nmod_mat_t void convertFacCFMatrix2Fq_nmod_mat_t (fq_nmod_mat_t M, ///< [in, out] fq_nmod_mat_t const fq_nmod_ctx_t fq_con, ///< [in] Fq context const CFMatrix &m ///< [in] matrix over Fq ); /// conversion of a FLINT factorization over Fq (for word size p) to a /// CFFList CFFList convertFLINTFq_nmod_poly_factor2FacCFFList (const fq_nmod_poly_factor_t fac, ///< [in] fq_nmod_poly_factor_t const Variable& x, ///< [in] polynomial variable const Variable& alpha, ///< [in] algebraic variable const fq_nmod_ctx_t fq_con ///< [in] Fq context ); #endif #endif #endif singular-4.0.3+ds/factory/Makefile.am000066400000000000000000000156741266270727000174750ustar00rootroot00000000000000ACLOCAL_AMFLAGS = -I ../m4 SUBDIRS=include/factory AM_CPPFLAGS = -I${builddir}/include -I${srcdir}/include -I${srcdir} \ $(OMALLOC_INCLUDES) $(RESOURCES_INCLUDES) \ $(FLINT_CFLAGS) $(NTL_CFLAGS) $(GMP_CFLAGS) lib_LTLIBRARIES = libfactory.la libfactory_la_LIBADD =$(RESOURCES_LIBS) $(OMALLOC_LIBS) \ $(FLINT_LIBS) $(NTL_LIBS) $(GMP_LIBS) libfactory_la_LDFLAGS = -release ${PACKAGE_VERSION} # factory source files SOURCES = \ canonicalform.cc \ cf_algorithm.cc \ cf_char.cc \ cfCharSets.cc \ cfCharSetsUtil.cc \ cf_chinese.cc \ cf_cyclo.cc \ cf_eval.cc \ cfEzgcd.cc \ cf_factor.cc \ cf_factory.cc \ cf_gcd.cc \ cfGcdAlgExt.cc \ cfGcdUtil.cc \ cf_generator.cc \ cf_globals.cc \ cf_hnf.cc \ cf_inline.cc \ cf_irred.cc \ cf_iter.cc \ cf_iter_inline.cc \ cf_linsys.cc \ cf_map.cc \ cf_map_ext.cc \ cfModGcd.cc \ cfNewtonPolygon.cc \ cfNTLzzpEXGCD.cc \ cfModResultant.cc \ cf_ops.cc \ cf_primes.cc \ cf_random.cc \ cf_resultant.cc \ cf_reval.cc \ cfSubResGcd.cc \ cf_switches.cc \ cf_util.cc \ cfUnivarGcd.cc \ debug.cc \ DegreePattern.cc \ ExtensionInfo.cc \ facAbsBiFact.cc \ facAbsFact.cc \ facAlgExt.cc \ facAlgFunc.cc \ facAlgFuncUtil.cc \ facBivar.cc \ facFactorize.cc \ fac_sqrfree.cc \ fac_util.cc \ facFqBivar.cc \ facFqBivarUtil.cc \ facFqFactorize.cc \ facFqFactorizeUtil.cc \ facFqSquarefree.cc \ facHensel.cc \ facIrredTest.cc \ facMul.cc \ facSparseHensel.cc \ ffops.cc \ FLINTconvert.cc \ gf_tabutil.cc \ gfops.cc \ imm.cc \ int_cf.cc \ int_int.cc \ int_intdiv.cc \ int_poly.cc \ int_rat.cc \ variable.cc \ NTLconvert.cc \ singext.cc \ parseutil.cc \ ftmpl_inst.cc if WITH_PARSER_FOR_CANONICAL_FORM SOURCES += readcf.yy endif libfactory_la_SOURCES = $(SOURCES) nodist_libfactory_la_SOURCES = cplusplus.h factory.h factoryconf.h # factory header files factory_headers = \ cf_assert.h \ canonicalform.h \ cf_algorithm.h \ cfCharSets.h \ cfCharSetsUtil.h \ cf_cyclo.h \ cf_defs.h \ cf_eval.h \ cfEzgcd.h \ cf_factory.h \ cf_generator.h \ cf_globals.h \ cfGcdAlgExt.h \ cfGcdUtil.h \ cf_hnf.h \ cf_irred.h \ cf_iter.h \ cf_map.h \ cf_map_ext.h \ cfModGcd.h \ cfNewtonPolygon.h \ cfNTLzzpEXGCD.h \ cfModResultant.h \ cf_primes.h \ cf_primetab.h \ cf_random.h \ cf_reval.h \ cfSubResGcd.h \ cf_switches.h \ cf_util.h \ cfUnivarGcd.h \ debug.h \ DegreePattern.h \ ExtensionInfo.h \ facAbsBiFact.h \ facAbsFact.h \ facAlgExt.h \ facAlgFunc.h \ facAlgFuncUtil.h \ facBivar.h \ facFactorize.h \ fac_sqrfree.h \ fac_util.h \ facFqBivar.h \ facFqBivarUtil.h \ facFqFactorize.h \ facFqFactorizeUtil.h \ facFqSquarefree.h \ facHensel.h \ facIrredTest.h \ facMul.h \ facSparseHensel.h \ ffops.h \ FLINTconvert.h \ gf_tabutil.h \ gfops.h \ gmpext.h \ imm.h \ int_cf.h \ int_int.h \ int_poly.h \ int_rat.h \ timing.h \ variable.h \ NTLconvert.h \ singext.h \ parseutil.h noinst_HEADERS = $(factory_headers) libfactory_includedir = ${includedir}/factory nodist_libfactory_include_HEADERS = cplusplus.h factory.h factoryconf.h #################################################### # Documentation include $(srcdir)/aminclude.am #################################################### # the precomputed GF(q)-tables gftablesdir=$(datadir)/factory/gftables dist_gftables_DATA = gftables/10201 gftables/1024 gftables/10609 gftables/11449 \ gftables/11881 gftables/121 gftables/12167 gftables/125 gftables/12769 \ gftables/128 gftables/1331 gftables/1369 gftables/14641 \ gftables/15625 gftables/16 gftables/16129 gftables/16384 \ gftables/16807 gftables/1681 gftables/169 gftables/17161 gftables/1849 \ gftables/18769 gftables/19321 gftables/19683 gftables/2048 \ gftables/2187 gftables/2197 gftables/2209 gftables/22201 \ gftables/22801 gftables/2401 gftables/243 gftables/24389 \ gftables/24649 gftables/25 gftables/256 gftables/26569 gftables/27 \ gftables/27889 gftables/2809 gftables/28561 gftables/289 \ gftables/29791 gftables/29929 gftables/3125 gftables/32 gftables/32041 \ gftables/32761 gftables/32768 gftables/343 gftables/3481 gftables/361 \ gftables/36481 gftables/3721 gftables/37249 gftables/38809 \ gftables/39601 gftables/4 gftables/4096 gftables/44521 gftables/4489 \ gftables/49 gftables/4913 gftables/49729 gftables/5041 \ gftables/50653 gftables/512 gftables/51529 gftables/52441 gftables/529 \ gftables/5329 gftables/54289 gftables/57121 gftables/58081 \ gftables/59049 gftables/6241 gftables/625 gftables/63001 \ gftables/64 gftables/6561 gftables/6859 gftables/6889 gftables/729 \ gftables/7921 gftables/8 gftables/81 gftables/8192 gftables/841 \ gftables/9 gftables/9409 gftables/961 #################################################### # Support for building GF(q)-tables # # gengftables needs libfactory.la and factory.h AND is needed for # generating gftable but the tables are not necessarily needed to # compile and use libfactory (though it will be a lot slower). EXTRA_PROGRAMS = gengftables gengftables_SOURCES = gengftables-conway.cc gengftables_LDADD = libfactory.la $(FLINT_LIBS) $(GMP_LIBS) $(NTL_LIBS) #################################################### # These files listed below are not used anywhere but are included in # the distribution. So they will be tacked on to EXTRA_DIST. templatesrc = templates/ftmpl_array.cc \ templates/ftmpl_afactor.cc \ templates/ftmpl_factor.cc \ templates/ftmpl_functions.h \ templates/ftmpl_list.cc \ templates/ftmpl_matrix.cc # header templates hdrtemplsrc = factoryconf.template \ factory.template EXTRA_DIST = test_install.cc \ $(templatesrc) $(hdrtemplsrc) \ doxygen.cfg \ examples/application.cc \ examples/factorize.cc examples/gcd.cc \ bin/folding.el bin/fold-docu.el \ bin/makeheader bin/gen-readcf readcf.yy \ make_factory_dist ################################################## # autogenerated sources noinst_PROGRAMS = cplusplus BUILT_SOURCES = cplusplus.h factory.h factoryconf.h CLEANFILES = $(BUILT_SOURCES) include/factory/factory.h include/factory/factoryconf.h include/factory/cplusplus.h DISTCLEANFILES = config.h readcf.cc #distclean-local: # -rm -f readcf.cc cplusplus_SOURCES = cplusplus.cc cplusplus.h: cplusplus$(EXEEXT) ./cplusplus$(EXEEXT) >$@ cp $@ include/factory/ .template.h: ${srcdir}/bin/makeheader $< $@ cp $@ include/factory/ # factory/gfops.cc has the gftables path hardcoded in, so we create a # symlink. Remove this rule once gfopts.cc has been fixed. Note that # check-local would run in parallel with check, so we can't use it # here! all-local: [ -d ${builddir}/gftables ] || ln -s ${srcdir}/gftables ${builddir} #################################################### ## Test program ## TESTS = test check_PROGRAMS = $(TESTS) test_SOURCES = test.cc test_LDADD = libfactory.la $(libfactory_la_LIBADD) #################################################### ## PKG config ## pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = factory.pc singular-4.0.3+ds/factory/NEWS000066400000000000000000000137031266270727000161270ustar00rootroot00000000000000Thu Nov 7 11:31:58 MET 2002 Hans Schoenemann interface to NTL (optional, recommended): tested with NTL 5.2, 5.3 bug fixes for multivariate factorization Tue Apr 10 15:24:49 CEST 2001 Hans Schoenemann several small bugs fixed (mostly memory leaks) changed copyright to GPL Tue Oct 28 14:46:08 1997 Jens Schmidt New features in Factory, version 1.3b: ====================================== Distribution and organization level: ------------------------------------ o The new external variable `factoryConfiguration' describes the configuration Factory has been translated with. o If configuring for cross compiling `configure' assumes that the target machine has arithmetic shift. o Parts of Factory are written using `folding-mode' for GNU Emacs. Since this is a really useful feature `folding.el' has been added to the distribution. o The new `make' target `installtest' in the top level `GNUmakefile' tests whether the installation has been successful. o The new directory `examples/' contains some example applications for Factory and a `GNUmakefile' to build them. Source code level: ------------------ o The main interface to Factory, the class `CanonicalForm' has been (almost completely) revised. During this process, a number of smaller bugs has been fixed (most of the bugs concerning some more or less exceptional cases). Furthermore, many of the methods became a little bit faster, some of them became a lot faster (e.g., the evaluation-`operator() ()' uses Horner's rule now, `degree( const & Variable )' and `deriv( const & Variable)' do not use expensive calls to `swapvar()' any longer). o In the same way, I have begun to revise the gcd calculations, but there is still is a lot of work to do. As a first result, gcd calculations over Z became faster (up to a factor of two for large examples). Other bug fixes: o A serious bug in `resultant()' has been fixed. o `gcd()' works correctly now for polynomials with rational coefficients. However, `factorize()' still does not, and you have to multiply with the common denominator before factorizing. o `psr( CF f, CF g, Var x )', `psq()', `psrq()' work correctly now if degree(f) < degree(g). However, they still do not work correctly if either in divisor or dividend occur variables with level higher than x's level. o A bug in `CanonicalForm::sqrt()' has been fixed which in some cases made `factorize()' crash. Changes: o If CO has not a denominator `CanonicalForm::den()' returns now the unity from the current domain, not the unity from the domain of CO. o `chineseRemainder()' works now for polynomials over Z instead for elements of Z only. o `cden()' computes the common denominator with respect to algebraic variables, too, so multiplying with `cden()' in any case results in an object with integral coefficients New features: o The new function `subResChain()' returns the extended subresultant chain of two polynomials. o The new function `replacevar()' replaces one variable with another. In contrast to `swapvar()', this works for algebraic variables, too. o The new function `size()' returns the number of monomials occuring in a `CanonicalForm'. o The new method `CanonicalForm::Lc()' returns the leading coefficient of CO, where elements from an algebraic extension are considered coefficients, and not polynomials. Thu Jul 17 10:15:59 1997 Jens Schmidt New features in Factory, version 1.3a: ====================================== Besides minor changes at "source code level" (bug fixes, new features) which are not really visible to the user in general there are quite a lot of changes at "organization level" (aka "preprocessor level") and at "distribution level" (`configure', `GNUmakefile'). Source code level: ------------------ o Serious bug in univariate factorization in characterstic 0 fixed (by Ruediger Stobbe). o New gcd algorithm (sparse modular), not fully tested by now (contributed by Marion Bruder). Switch on with `SW_USE_SPARSEMOD'. o Various minor bug fixes. Organization level: ------------------- o Factory translates now on Macintosh with Metroworks CodeWarrior Academic Pro 11 (changes by Wilfred Pohl) o So called "new" memory manager (written by Ruediger Stobbe) added to distribution. So far no timigs available which memory manager is faster. o "ASSERT", "DEBOUT", "TIMING macros" streamlined o Factory's IO completely re-organized (that was a mess!). It is now possible to switch off everything which is related to stream IO (use `--disbale-streamio' option to `configure'). This way it is possible to link Factory without `libg++.a' or `libiostream.a'. Changes include: - everything related to stream IO wrapped by `#ifndef NOSTREAMIO' - all error messages/debug output messages rewritten so that they use the "ASSERT" and "DEBOUT macros" - furthermore, it was necessary to change the way the GF(q) tables are read. As a consequence, the format of the GF(q) tables slightly changed, too. You have to generate/get them from net by new. Distribution level: ------------------- o The organization of the distribution as well as the compile/install procedure totally changed. It is now more GNU-like. See the `INSTALL' file and the `README' file for more information. o The file names of the template sources changed. To make them less canonical, all names are prefixed with `ftmpl_' ("Factory template") now. o The installation target directories and their structure changed a little bit. See the `INSTALL' file for more information. Before May 3 1997 Jens Schmidt New features in Factory, version 1.2c: ====================================== Version 1.2c is a more or less inofficial version distributed with Singular 1.0. I hope it does not distribute too far... The description of new features to version 1.3a cope the description of new features to this version. singular-4.0.3+ds/factory/NTLconvert.cc000066400000000000000000001052761266270727000200040ustar00rootroot00000000000000 #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "canonicalform.h" #include "cf_iter.h" #include "fac_sqrfree.h" #include "cf_algorithm.h" #include #ifdef HAVE_NTL #ifndef NOSTREAMIO #ifdef HAVE_CSTDIO #include #else #include #endif #endif #include #include #include #include #include #include #include #include #include #include #include #include "int_int.h" #include #include "NTLconvert.h" #define Alloc(L) malloc(L) #define Free(A,L) free(A) void out_cf(const char *s1,const CanonicalForm &f,const char *s2); long fac_NTL_char = -1; // the current characterstic for NTL calls // -1: undefined #ifdef NTL_CLIENT // in : using of name space NTL NTL_CLIENT #endif //////////////////////////////////////////////////////////////////////////////// /// NAME: convertFacCF2NTLZZpX /// /// DESCRIPTION: /// Conversion routine for Factory-type canonicalform into ZZpX of NTL, /// i.e. polynomials over F_p. As a precondition for correct execution, /// the characteristic has to a a prime number. /// /// INPUT: A canonicalform f /// OUTPUT: The converted NTL-polynomial over F_p of type ZZpX //////////////////////////////////////////////////////////////////////////////// ZZ_pX convertFacCF2NTLZZpX(const CanonicalForm & f) { ZZ_pX ntl_poly; CFIterator i; i=f; int NTLcurrentExp=i.exp(); int largestExp=i.exp(); int k; // we now build up the NTL-polynomial ntl_poly.SetMaxLength(largestExp+1); for (;i.hasTerms();i++) { for (k=NTLcurrentExp;k>i.exp();k--) { SetCoeff(ntl_poly,k,0); } NTLcurrentExp=i.exp(); SetCoeff(ntl_poly,NTLcurrentExp,to_ZZ_p (convertFacCF2NTLZZ (i.coeff()))); NTLcurrentExp--; } //Set the remaining coefficients of ntl_poly to zero. // This is necessary, because NTL internally // also stores powers with zero coefficient, // whereas factory stores tuples of degree and coefficient //leaving out tuples if the coefficient equals zero for (k=NTLcurrentExp;k>=0;k--) { SetCoeff(ntl_poly,k,0); } //normalize the polynomial and return it ntl_poly.normalize(); return ntl_poly; } zz_pX convertFacCF2NTLzzpX(const CanonicalForm & f) { zz_pX ntl_poly; CFIterator i; i=f; int NTLcurrentExp=i.exp(); int largestExp=i.exp(); int k; // we now build up the NTL-polynomial ntl_poly.SetMaxLength(largestExp+1); for (;i.hasTerms();i++) { for (k=NTLcurrentExp;k>i.exp();k--) { SetCoeff(ntl_poly,k,0); } NTLcurrentExp=i.exp(); CanonicalForm c=i.coeff(); if (!c.isImm()) c=c.mapinto(); //c%= getCharacteristic(); if (!c.isImm()) { //This case will never happen if the characteristic is in fact a prime // number, since all coefficients are represented as immediates #ifndef NOSTREAMIO cout<<"convertFacCF2NTLzz_pX: coefficient not immediate! : "<=0;k--) { SetCoeff(ntl_poly,k,0); } //normalize the polynomial and return it ntl_poly.normalize(); return ntl_poly; } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertFacCF2NTLGF2X /// /// DESCRIPTION: /// Conversion routine for Factory-type canonicalform into GF2X of NTL, /// i.e. polynomials over F_2. As precondition for correct execution, /// the characteristic must equal two. /// This is a special case of the more general conversion routine for /// canonicalform to ZZpX. It is included because NTL provides additional /// support and faster algorithms over F_2, moreover the conversion code /// can be optimized, because certain steps are either completely obsolent /// (like normalizing the polynomial) or they can be made significantly /// faster (like building up the NTL-polynomial). /// /// INPUT: A canonicalform f /// OUTPUT: The converted NTL-polynomial over F_2 of type GF2X //////////////////////////////////////////////////////////////////////////////// GF2X convertFacCF2NTLGF2X(const CanonicalForm & f) { //printf("convertFacCF2NTLGF2X\n"); GF2X ntl_poly; CFIterator i; i=f; int NTLcurrentExp=i.exp(); int largestExp=i.exp(); int k; //building the NTL-polynomial ntl_poly.SetMaxLength(largestExp+1); for (;i.hasTerms();i++) { for (k=NTLcurrentExp;k>i.exp();k--) { SetCoeff(ntl_poly,k,0); } NTLcurrentExp=i.exp(); if (!i.coeff().isImm()) i.coeff()=i.coeff().mapinto(); if (!i.coeff().isImm()) { #ifndef NOSTREAMIO cout<<"convertFacCF2NTLGF2X: coefficient not immidiate! : " << f << "\n"; #else //NTL_SNS printf("convertFacCF2NTLGF2X: coefficient not immidiate!"); #endif NTL_SNS exit(1); } else { SetCoeff(ntl_poly,NTLcurrentExp,i.coeff().intval()); } NTLcurrentExp--; } for (k=NTLcurrentExp;k>=0;k--) { SetCoeff(ntl_poly,k,0); } //normalization is not necessary of F_2 return ntl_poly; } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertNTLZZpX2CF /// /// DESCRIPTION: /// Conversion routine for NTL-Type ZZpX to Factory-Type canonicalform. /// Additionally a variable x is needed as a parameter indicating the /// main variable of the computed canonicalform. To guarantee the correct /// execution of the algorithm, the characteristic has a be an arbitrary /// prime number. /// /// INPUT: A canonicalform f, a variable x /// OUTPUT: The converted Factory-polynomial of type canonicalform, /// built by the main variable x //////////////////////////////////////////////////////////////////////////////// CanonicalForm convertNTLZZpX2CF(const ZZ_pX & poly,const Variable & x) { return convertNTLZZX2CF (to_ZZX (poly), x); } CanonicalForm convertNTLzzpX2CF(const zz_pX & poly,const Variable & x) { //printf("convertNTLzzpX2CF\n"); CanonicalForm bigone; if (deg(poly)>0) { // poly is non-constant bigone=0; bigone.mapinto(); // Compute the canonicalform coefficient by coefficient, // bigone summarizes the result. for (int j=0;j<=deg(poly);j++) { if (coeff(poly,j)!=0) { bigone+=(power(x,j)*CanonicalForm(to_long(rep(coeff(poly,j))))); } } } else { // poly is immediate bigone=CanonicalForm(to_long(rep(coeff(poly,0)))); bigone.mapinto(); } return bigone; } CanonicalForm convertNTLZZX2CF(const ZZX & polynom,const Variable & x) { //printf("convertNTLZZX2CF\n"); CanonicalForm bigone; // Go through the vector e and build up the CFFList // As usual bigone summarizes the result bigone=0; ZZ coefficient; for (int j=0;j<=deg(polynom);j++) { coefficient=coeff(polynom,j); if (!IsZero(coefficient)) { bigone += (power(x,j)*convertZZ2CF(coefficient)); } } return bigone; } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertNTLGF2X2CF /// /// DESCRIPTION: /// Conversion routine for NTL-Type GF2X to Factory-Type canonicalform, /// the routine is again an optimized special case of the more general /// conversion to ZZpX. Additionally a variable x is needed as a /// parameter indicating the main variable of the computed canonicalform. /// To guarantee the correct execution of the algorithm the characteristic /// has a be an arbitrary prime number. /// /// INPUT: A canonicalform f, a variable x /// OUTPUT: The converted Factory-polynomial of type canonicalform, /// built by the main variable x //////////////////////////////////////////////////////////////////////////////// CanonicalForm convertNTLGF2X2CF(const GF2X & poly,const Variable & x) { //printf("convertNTLGF2X2CF\n"); CanonicalForm bigone; if (deg(poly)>0) { // poly is non-constant bigone=0; bigone.mapinto(); // Compute the canonicalform coefficient by coefficient, // bigone summarizes the result. // In constrast to the more general conversion to ZZpX // the only possible coefficients are zero // and one yielding the following simplified loop for (int j=0;j<=deg(poly);j++) { if (coeff(poly,j)!=0) bigone+=power(x,j); // *CanonicalForm(to_long(rep(coeff(poly,j))))) is not necessary any more; } } else { // poly is immediate bigone=CanonicalForm(to_long(rep(coeff(poly,0)))); bigone.mapinto(); } return bigone; } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertNTLvec_pair_ZZpX_long2FacCFFList /// /// DESCRIPTION: /// Routine for converting a vector of polynomials from ZZpX to /// a CFFList of Factory. This routine will be used after a successful /// factorization of NTL to convert the result back to Factory. /// /// Additionally a variable x and the computed multiplicity, as a type ZZp /// of NTL, is needed as parameters indicating the main variable of the /// computed canonicalform and the multiplicity of the original polynomial. /// To guarantee the correct execution of the algorithm the characteristic /// has a be an arbitrary prime number. /// /// INPUT: A vector of polynomials over ZZp of type vec_pair_ZZ_pX_long and /// a variable x and a multiplicity of type ZZp /// OUTPUT: The converted list of polynomials of type CFFList, all polynomials /// have x as their main variable //////////////////////////////////////////////////////////////////////////////// CFFList convertNTLvec_pair_ZZpX_long2FacCFFList (const vec_pair_ZZ_pX_long & e,const ZZ_p & multi,const Variable & x) { //printf("convertNTLvec_pair_ZZpX_long2FacCFFList\n"); CFFList result; ZZ_pX polynom; CanonicalForm bigone; // Maybe, e may additionally be sorted with respect to increasing degree of x // but this is not //important for the factorization, but nevertheless would take computing time, // so it is omitted // Go through the vector e and compute the CFFList // again bigone summarizes the result for (int i=e.length()-1;i>=0;i--) { result.append(CFFactor(convertNTLZZpX2CF(e[i].a,x),e[i].b)); } // the multiplicity at pos 1 if (!IsOne(multi)) result.insert(CFFactor(CanonicalForm(to_long(rep(multi))),1)); return result; } CFFList convertNTLvec_pair_zzpX_long2FacCFFList (const vec_pair_zz_pX_long & e,const zz_p multi,const Variable & x) { //printf("convertNTLvec_pair_zzpX_long2FacCFFList\n"); CFFList result; zz_pX polynom; CanonicalForm bigone; // Maybe, e may additionally be sorted with respect to increasing degree of x // but this is not //important for the factorization, but nevertheless would take computing time, // so it is omitted // Go through the vector e and compute the CFFList // again bigone summarizes the result for (int i=e.length()-1;i>=0;i--) { result.append(CFFactor(convertNTLzzpX2CF(e[i].a,x),e[i].b)); } // the multiplicity at pos 1 if (!IsOne(multi)) result.insert(CFFactor(CanonicalForm(to_long(rep(multi))),1)); return result; } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertNTLvec_pair_GF2X_long2FacCFFList /// /// DESCRIPTION: /// Routine for converting a vector of polynomials of type GF2X from /// NTL to a list CFFList of Factory. This routine will be used after a /// successful factorization of NTL to convert the result back to Factory. /// As usual this is simply a special case of the more general conversion /// routine but again speeded up by leaving out unnecessary steps. /// Additionally a variable x and the computed multiplicity, as type /// GF2 of NTL, are needed as parameters indicating the main variable of the /// computed canonicalform and the multiplicity of the original polynomial. /// To guarantee the correct execution of the algorithm the characteristic /// has a be an arbitrary prime number. /// /// INPUT: A vector of polynomials over GF2 of type vec_pair_GF2X_long and /// a variable x and a multiplicity of type GF2 /// OUTPUT: The converted list of polynomials of type CFFList, all /// polynomials have x as their main variable //////////////////////////////////////////////////////////////////////////////// CFFList convertNTLvec_pair_GF2X_long2FacCFFList (const vec_pair_GF2X_long& e, GF2 /*multi*/, const Variable & x) { //printf("convertNTLvec_pair_GF2X_long2FacCFFList\n"); CFFList result; GF2X polynom; long exponent; CanonicalForm bigone; // Maybe, e may additionally be sorted with respect to increasing degree of x // but this is not //important for the factorization, but nevertheless would take computing time // so it is omitted. //We do not have to worry about the multiplicity in GF2 since it equals one. // Go through the vector e and compute the CFFList // bigone summarizes the result again for (int i=e.length()-1;i>=0;i--) { bigone=0; polynom=e[i].a; exponent=e[i].b; for (int j=0;j<=deg(polynom);j++) { if (coeff(polynom,j)!=0) bigone += (power(x,j)*CanonicalForm(to_long(rep(coeff(polynom,j))))); } //append the converted polynomial to the CFFList result.append(CFFactor(bigone,exponent)); } return result; } static unsigned char *cf_stringtemp; static unsigned long cf_stringtemp_l=0L; //////////////////////////////////////////////////////////////////////////////// /// NAME: convertZZ2CF /// /// DESCRIPTION: /// Routine for conversion of integers represented in NTL as Type ZZ to /// integers in Factory represented as canonicalform. /// To guarantee the correct execution of the algorithm the characteristic /// has to equal zero. /// /// INPUT: The value coefficient of type ZZ that has to be converted /// OUTPUT: The converted Factory-integer of type canonicalform //////////////////////////////////////////////////////////////////////////////// CanonicalForm convertZZ2CF (const ZZ & a) { long coeff_long=to_long(a); CanonicalForm result; if ( (NumBits(a)<((long)NTL_ZZ_NBITS)) && (coeff_long>((long)MINIMMEDIATE)) && (coeff_long<((long)MAXIMMEDIATE))) { return CanonicalForm(coeff_long); } else { const long * rep = #if NTL_MAJOR_VERSION <= 6 static_cast( a.rep ); #else static_cast( a.rep.rep ); // what about NTL7? #endif long sizeofrep= rep[1]; bool lessZero= false; if (sizeofrep < 0) { lessZero= true; sizeofrep= -sizeofrep; } if (cf_stringtemp_l == 0) { cf_stringtemp_l= sizeofrep*sizeof(mp_limb_t)*2; cf_stringtemp= (unsigned char*) Alloc (cf_stringtemp_l); } else if (cf_stringtemp_l < sizeofrep*sizeof(mp_limb_t)*2) { Free (cf_stringtemp, cf_stringtemp_l); cf_stringtemp_l= sizeofrep*sizeof(mp_limb_t)*2; cf_stringtemp= (unsigned char*) Alloc (cf_stringtemp_l); } int cc= mpn_get_str (cf_stringtemp, 16, (mp_limb_t *) ((rep) + 2), sizeofrep); char* cf_stringtemp2; if (lessZero) { cf_stringtemp2= new char [cc + 2]; cf_stringtemp2[0]='-'; for (int j= 1; j <= cc; j++) cf_stringtemp2[j]= IntValToChar ((int) cf_stringtemp [j-1]); cf_stringtemp2[cc+1]='\0'; } else { cf_stringtemp2= new char [cc + 1]; for (int j= 0; j < cc; j++) cf_stringtemp2[j]= IntValToChar ((int) cf_stringtemp [j]); cf_stringtemp2[cc]='\0'; } result= CanonicalForm (cf_stringtemp2, 16); delete [] cf_stringtemp2; return result; } return result; } /*static char *cf_stringtemp; static char *cf_stringtemp2; static int cf_stringtemp_l=0; CanonicalForm convertZZ2CF(const ZZ & coefficient) { long coeff_long; //CanonicalForm tmp=0; char dummy[2]; int minusremainder=0; char numbers[]="0123456789abcdef"; coeff_long=to_long(coefficient); //Test whether coefficient can be represented as an immediate integer in Factory if ( (NumBits(coefficient)<((long)NTL_ZZ_NBITS)) && (coeff_long>((long)MINIMMEDIATE)) && (coeff_long<((long)MAXIMMEDIATE))) { // coefficient is immediate --> return the coefficient as canonicalform return CanonicalForm(coeff_long); } else { // coefficient is not immediate (gmp-number) if (cf_stringtemp_l==0) { cf_stringtemp=(char *)Alloc(1023); cf_stringtemp2=(char *)Alloc(1023); cf_stringtemp[0]='\0'; cf_stringtemp2[0]='\0'; cf_stringtemp_l=1023; } // convert coefficient to char* (input for gmp) dummy[1]='\0'; if (coefficient<0) { // negate coefficient, but store the sign in minusremainder minusremainder=1; coefficient=-coefficient; } int l=0; while (coefficient>15) { ZZ quotient,remaind; ZZ ten;ten=16; DivRem(quotient,remaind,coefficient,ten); dummy[0]=numbers[to_long(remaind)]; //tmp*=10; tmp+=to_long(remaind); l++; if (l>=cf_stringtemp_l-2) { Free(cf_stringtemp2,cf_stringtemp_l); char *p=(char *)Alloc(cf_stringtemp_l*2); //NTL_SNS memcpy(p,cf_stringtemp,cf_stringtemp_l); Free(cf_stringtemp,cf_stringtemp_l); cf_stringtemp_l*=2; cf_stringtemp=p; cf_stringtemp2=(char *)Alloc(cf_stringtemp_l); } cf_stringtemp[l-1]=dummy[0]; cf_stringtemp[l]='\0'; //strcat(stringtemp,dummy); coefficient=quotient; } //built up the string in dummy[0] dummy[0]=numbers[to_long(coefficient)]; //NTL_SNS l++; cf_stringtemp[l-1]=dummy[0]; cf_stringtemp[l]='\0'; //tmp*=10; tmp+=to_long(coefficient); if (minusremainder==1) { //Check whether coefficient has been negative at the start of the procedure cf_stringtemp2[0]='-'; //tmp*=(-1); } //reverse the list to obtain the correct string //NTL_SNS for (int i=l-1;i>=0;i--) // l ist the position of \0 { cf_stringtemp2[l-i-1+minusremainder]=cf_stringtemp[i]; } cf_stringtemp2[l+minusremainder]='\0'; } //convert the string to canonicalform using the char*-Constructor return CanonicalForm(cf_stringtemp2,16); //return tmp; }*/ //////////////////////////////////////////////////////////////////////////////// /// NAME: convertFacCF2NTLZZX /// /// DESCRIPTION: /// Routine for conversion of canonicalforms in Factory to polynomials /// of type ZZX of NTL. To guarantee the correct execution of the /// algorithm the characteristic has to equal zero. /// /// INPUT: The canonicalform that has to be converted /// OUTPUT: The converted NTL-polynom of type ZZX //////////////////////////////////////////////////////////////////////////////// ZZ convertFacCF2NTLZZ(const CanonicalForm & f) { ZZ temp; if (f.isImm()) temp=f.intval(); else { //Coefficient is a gmp-number mpz_t gmp_val; char* stringtemp; f.mpzval (gmp_val); int l=mpz_sizeinbase(gmp_val,10)+2; stringtemp=(char*)Alloc(l); stringtemp=mpz_get_str(stringtemp,10,gmp_val); mpz_clear(gmp_val); conv(temp,stringtemp); Free(stringtemp,l); } return temp; } ZZX convertFacCF2NTLZZX(const CanonicalForm & f) { ZZX ntl_poly; CFIterator i; i=f; int NTLcurrentExp=i.exp(); int largestExp=i.exp(); int k; //set the length of the NTL-polynomial ntl_poly.SetMaxLength(largestExp+1); //Go through the coefficients of the canonicalform and build up the NTL-polynomial for (;i.hasTerms();i++) { for (k=NTLcurrentExp;k>i.exp();k--) { SetCoeff(ntl_poly,k,0); } NTLcurrentExp=i.exp(); //Coefficient is a gmp-number ZZ temp=convertFacCF2NTLZZ(i.coeff()); //set the computed coefficient SetCoeff(ntl_poly,NTLcurrentExp,temp); NTLcurrentExp--; } for (k=NTLcurrentExp;k>=0;k--) { SetCoeff(ntl_poly,k,0); } //normalize the polynomial ntl_poly.normalize(); return ntl_poly; } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertNTLvec_pair_ZZX_long2FacCFFList /// /// DESCRIPTION: /// Routine for converting a vector of polynomials from ZZ to a list /// CFFList of Factory. This routine will be used after a successful /// factorization of NTL to convert the result back to Factory. /// Additionally a variable x and the computed multiplicity, as a type /// ZZ of NTL, is needed as parameters indicating the main variable of the /// computed canonicalform and the multiplicity of the original polynomial. /// To guarantee the correct execution of the algorithm the characteristic /// has to equal zero. /// /// INPUT: A vector of polynomials over ZZ of type vec_pair_ZZX_long and /// a variable x and a multiplicity of type ZZ /// OUTPUT: The converted list of polynomials of type CFFList, all /// have x as their main variable //////////////////////////////////////////////////////////////////////////////// CFFList convertNTLvec_pair_ZZX_long2FacCFFList (const vec_pair_ZZX_long & e,const ZZ & multi,const Variable & x) { CFFList result; ZZX polynom; long exponent; CanonicalForm bigone; // Go through the vector e and build up the CFFList // As usual bigone summarizes the result for (int i=e.length()-1;i>=0;i--) { ZZ coefficient; polynom=e[i].a; exponent=e[i].b; bigone=convertNTLZZX2CF(polynom,x); //append the converted polynomial to the list result.append(CFFactor(bigone,exponent)); } // the multiplicity at pos 1 //if (!IsOne(multi)) result.insert(CFFactor(convertZZ2CF(multi),1)); //return the converted list return result; } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertNTLZZpX2CF /// /// DESCRIPTION: /// Routine for conversion of elements of arbitrary extensions of ZZp, /// having type ZZpE, of NTL to their corresponding values of type /// canonicalform in Factory. /// To guarantee the correct execution of the algorithm the characteristic /// has to be an arbitrary prime number and Factory has to compute in an /// extension of F_p. /// /// INPUT: The coefficient of type ZZpE and the variable x indicating the main// /// variable of the computed canonicalform /// OUTPUT: The converted value of coefficient as type canonicalform //////////////////////////////////////////////////////////////////////////////// CanonicalForm convertNTLZZpE2CF(const ZZ_pE & coefficient,const Variable & x) { return convertNTLZZpX2CF(rep(coefficient),x); } CanonicalForm convertNTLzzpE2CF(const zz_pE & coefficient,const Variable & x) { return convertNTLzzpX2CF(rep(coefficient),x); } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertNTLvec_pair_ZZpEX_long2FacCFFList /// /// DESCRIPTION: /// Routine for converting a vector of polynomials from ZZpEX to a CFFList /// of Factory. This routine will be used after a successful factorization /// of NTL to convert the result back to Factory. /// Additionally a variable x and the computed multiplicity, as a type /// ZZpE of NTL, is needed as parameters indicating the main variable of the /// computed canonicalform and the multiplicity of the original polynomial. /// To guarantee the correct execution of the algorithm the characteristic /// has a be an arbitrary prime number p and computations have to be done /// in an extention of F_p. /// /// INPUT: A vector of polynomials over ZZpE of type vec_pair_ZZ_pEX_long and /// a variable x and a multiplicity of type ZZpE /// OUTPUT: The converted list of polynomials of type CFFList, all polynomials /// have x as their main variable //////////////////////////////////////////////////////////////////////////////// CFFList convertNTLvec_pair_ZZpEX_long2FacCFFList(const vec_pair_ZZ_pEX_long & e,const ZZ_pE & multi,const Variable & x,const Variable & alpha) { CFFList result; ZZ_pEX polynom; long exponent; CanonicalForm bigone; // Maybe, e may additionally be sorted with respect to increasing degree of x, but this is not //important for the factorization, but nevertheless would take computing time, so it is omitted // Go through the vector e and build up the CFFList // As usual bigone summarizes the result during every loop for (int i=e.length()-1;i>=0;i--) { bigone=0; polynom=e[i].a; exponent=e[i].b; for (int j=0;j<=deg(polynom);j++) { if (IsOne(coeff(polynom,j))) { bigone+=power(x,j); } else { CanonicalForm coefficient=convertNTLZZpE2CF(coeff(polynom,j),alpha); if (coeff(polynom,j)!=0) { bigone += (power(x,j)*coefficient); } } } //append the computed polynomials together with its exponent to the CFFList result.append(CFFactor(bigone,exponent)); } // Start by appending the multiplicity if (!IsOne(multi)) result.insert(CFFactor(convertNTLZZpE2CF(multi,alpha),1)); //return the computed CFFList return result; } CFFList convertNTLvec_pair_zzpEX_long2FacCFFList(const vec_pair_zz_pEX_long & e,const zz_pE & multi,const Variable & x,const Variable & alpha) { CFFList result; zz_pEX polynom; long exponent; CanonicalForm bigone; // Maybe, e may additionally be sorted with respect to increasing degree of x, but this is not //important for the factorization, but nevertheless would take computing time, so it is omitted // Go through the vector e and build up the CFFList // As usual bigone summarizes the result during every loop for (int i=e.length()-1;i>=0;i--) { bigone=0; polynom=e[i].a; exponent=e[i].b; for (int j=0;j<=deg(polynom);j++) { if (IsOne(coeff(polynom,j))) { bigone+=power(x,j); } else { CanonicalForm coefficient=convertNTLzzpE2CF(coeff(polynom,j),alpha); if (coeff(polynom,j)!=0) { bigone += (power(x,j)*coefficient); } } } //append the computed polynomials together with its exponent to the CFFList result.append(CFFactor(bigone,exponent)); } // Start by appending the multiplicity if (!IsOne(multi)) result.insert(CFFactor(convertNTLzzpE2CF(multi,alpha),1)); //return the computed CFFList return result; } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertNTLGF2E2CF /// /// DESCRIPTION: /// Routine for conversion of elements of extensions of GF2, having type /// GF2E, of NTL to their corresponding values of type canonicalform in /// Factory. /// To guarantee the correct execution of the algorithm, the characteristic /// must equal two and Factory has to compute in an extension of F_2. /// As usual this is an optimized special case of the more general conversion /// routine from ZZpE to Factory. /// /// INPUT: The coefficient of type GF2E and the variable x indicating the /// main variable of the computed canonicalform /// OUTPUT: The converted value of coefficient as type canonicalform //////////////////////////////////////////////////////////////////////////////// CanonicalForm convertNTLGF2E2CF(const GF2E & coefficient,const Variable & x) { return convertNTLGF2X2CF(rep(coefficient),x); } //////////////////////////////////////////////////////////////////////////////// /// NAME: convertNTLvec_pair_GF2EX_long2FacCFFList /// /// DESCRIPTION: /// Routine for converting a vector of polynomials from GF2EX to a CFFList /// of Factory. This routine will be used after a successful factorization /// of NTL to convert the result back to Factory. /// This is a special, but optimized case of the more general conversion /// from ZZpE to canonicalform. /// Additionally a variable x and the computed multiplicity, as a type GF2E /// of NTL, is needed as parameters indicating the main variable of the /// computed canonicalform and the multiplicity of the original polynomial. /// To guarantee the correct execution of the algorithm the characteristic /// has to equal two and computations have to be done in an extention of F_2. /// /// INPUT: A vector of polynomials over GF2E of type vec_pair_GF2EX_long and /// a variable x and a multiplicity of type GF2E /// OUTPUT: The converted list of polynomials of type CFFList, all polynomials /// have x as their main variable //////////////////////////////////////////////////////////////////////////////// CFFList convertNTLvec_pair_GF2EX_long2FacCFFList (const vec_pair_GF2EX_long & e, const GF2E & multi, const Variable & x, const Variable & alpha) { CFFList result; GF2EX polynom; long exponent; CanonicalForm bigone; // Maybe, e may additionally be sorted with respect to increasing degree of x, but this is not //important for the factorization, but nevertheless would take computing time, so it is omitted // multiplicity is always one, so we do not have to worry about that // Go through the vector e and build up the CFFList // As usual bigone summarizes the result during every loop for (int i=e.length()-1;i>=0;i--) { bigone=0; polynom=e[i].a; exponent=e[i].b; for (int j=0;j<=deg(polynom);j++) { if (IsOne(coeff(polynom,j))) { bigone+=power(x,j); } else { CanonicalForm coefficient=convertNTLGF2E2CF(coeff(polynom,j),alpha); if (coeff(polynom,j)!=0) { bigone += (power(x,j)*coefficient); } } } // append the computed polynomial together with its multiplicity result.append(CFFactor(bigone,exponent)); } if (!IsOne(multi)) result.insert(CFFactor(convertNTLGF2E2CF(multi,alpha),1)); // return the computed CFFList return result; } //////////////////////////////////////////////////// /// CanonicalForm in Z_2(a)[X] to NTL GF2EX //////////////////////////////////////////////////// GF2EX convertFacCF2NTLGF2EX(const CanonicalForm & f,const GF2X & mipo) { GF2E::init(mipo); GF2EX result; CFIterator i; i=f; int NTLcurrentExp=i.exp(); int largestExp=i.exp(); int k; result.SetMaxLength(largestExp+1); for(;i.hasTerms();i++) { for(k=NTLcurrentExp;k>i.exp();k--) SetCoeff(result,k,0); NTLcurrentExp=i.exp(); CanonicalForm c=i.coeff(); GF2X cc=convertFacCF2NTLGF2X(c); //ZZ_pE ccc; //conv(ccc,cc); SetCoeff(result,NTLcurrentExp,to_GF2E(cc)); NTLcurrentExp--; } for(k=NTLcurrentExp;k>=0;k--) SetCoeff(result,k,0); result.normalize(); return result; } //////////////////////////////////////////////////// /// CanonicalForm in Z_p(a)[X] to NTL ZZ_pEX //////////////////////////////////////////////////// ZZ_pEX convertFacCF2NTLZZ_pEX(const CanonicalForm & f, const ZZ_pX & mipo) { ZZ_pE::init(mipo); ZZ_pEX result; CFIterator i; i=f; int NTLcurrentExp=i.exp(); int largestExp=i.exp(); int k; result.SetMaxLength(largestExp+1); for(;i.hasTerms();i++) { for(k=NTLcurrentExp;k>i.exp();k--) SetCoeff(result,k,0); NTLcurrentExp=i.exp(); CanonicalForm c=i.coeff(); ZZ_pX cc=convertFacCF2NTLZZpX(c); //ZZ_pE ccc; //conv(ccc,cc); SetCoeff(result,NTLcurrentExp,to_ZZ_pE(cc)); NTLcurrentExp--; } for(k=NTLcurrentExp;k>=0;k--) SetCoeff(result,k,0); result.normalize(); return result; } zz_pEX convertFacCF2NTLzz_pEX(const CanonicalForm & f, const zz_pX & mipo) { zz_pE::init(mipo); zz_pEX result; CFIterator i; i=f; int NTLcurrentExp=i.exp(); int largestExp=i.exp(); int k; result.SetMaxLength(largestExp+1); for(;i.hasTerms();i++) { for(k=NTLcurrentExp;k>i.exp();k--) SetCoeff(result,k,0); NTLcurrentExp=i.exp(); CanonicalForm c=i.coeff(); zz_pX cc=convertFacCF2NTLzzpX(c); //ZZ_pE ccc; //conv(ccc,cc); SetCoeff(result,NTLcurrentExp,to_zz_pE(cc)); NTLcurrentExp--; } for(k=NTLcurrentExp;k>=0;k--) SetCoeff(result,k,0); result.normalize(); return result; } CanonicalForm convertNTLzz_pEX2CF (const zz_pEX& f, const Variable & x, const Variable & alpha) { CanonicalForm bigone; if (deg (f) > 0) { bigone= 0; bigone.mapinto(); for (int j=0;j 0) { bigone= 0; bigone.mapinto(); for (int j=0;jSetDims(m.rows(),m.columns()); int i,j; for(i=m.rows();i>0;i--) { for(j=m.columns();j>0;j--) { (*res)(i,j)=convertFacCF2NTLZZ(m(i,j)); } } return res; } CFMatrix* convertNTLmat_ZZ2FacCFMatrix(const mat_ZZ &m) { CFMatrix *res=new CFMatrix(m.NumRows(),m.NumCols()); int i,j; for(i=res->rows();i>0;i--) { for(j=res->columns();j>0;j--) { (*res)(i,j)=convertZZ2CF(m(i,j)); } } return res; } mat_zz_p* convertFacCFMatrix2NTLmat_zz_p(const CFMatrix &m) { mat_zz_p *res=new mat_zz_p; res->SetDims(m.rows(),m.columns()); int i,j; for(i=m.rows();i>0;i--) { for(j=m.columns();j>0;j--) { if(!(m(i,j)).isImm()) printf("convertFacCFMatrix2NTLmat_zz_p: not imm.\n"); (*res)(i,j)=(m(i,j)).intval(); } } return res; } CFMatrix* convertNTLmat_zz_p2FacCFMatrix(const mat_zz_p &m) { CFMatrix *res=new CFMatrix(m.NumRows(),m.NumCols()); int i,j; for(i=res->rows();i>0;i--) { for(j=res->columns();j>0;j--) { (*res)(i,j)=CanonicalForm(to_long(rep(m(i,j)))); } } return res; } mat_zz_pE* convertFacCFMatrix2NTLmat_zz_pE(const CFMatrix &m) { mat_zz_pE *res=new mat_zz_pE; res->SetDims(m.rows(),m.columns()); int i,j; for(i=m.rows();i>0;i--) { for(j=m.columns();j>0;j--) { zz_pX cc=convertFacCF2NTLzzpX(m(i,j)); (*res)(i,j)=to_zz_pE(cc); } } return res; } CFMatrix* convertNTLmat_zz_pE2FacCFMatrix(const mat_zz_pE &m, const Variable & alpha) { CFMatrix *res=new CFMatrix(m.NumRows(),m.NumCols()); int i,j; for(i=res->rows();i>0;i--) { for(j=res->columns();j>0;j--) { (*res)(i,j)=convertNTLzzpE2CF(m(i,j), alpha); } } return res; } #endif singular-4.0.3+ds/factory/NTLconvert.h000066400000000000000000000070501266270727000176350ustar00rootroot00000000000000/** * @file NTLconvert.h * * Conversion to and from NTL **/ #ifndef INCL_NTLCONVERT_H #define INCL_NTLCONVERT_H #ifdef HAVE_NTL // #include #include "cf_defs.h" #include "canonicalform.h" #include "cf_iter.h" #include "fac_sqrfree.h" #include "cf_algorithm.h" #include #ifdef NTL_STD_CXX #ifdef NOSTREAMIO # ifdef HAVE_IOSTREAM # include # define OSTREAM std::ostream # define ISTREAM std::istream # elif defined(HAVE_IOSTREAM_H) # include # define OSTREAM ostream # define ISTREAM istream # endif #endif /* ! NOSTREAMIO */ #endif #include #include #include #include #include #include #include #include #include #include #ifdef NTL_CLIENT // in : using of name space NTL NTL_CLIENT #endif #include "int_int.h" #include "cf_assert.h" ZZ_pX convertFacCF2NTLZZpX(const CanonicalForm & f); zz_pX convertFacCF2NTLzzpX(const CanonicalForm & f); GF2X convertFacCF2NTLGF2X(const CanonicalForm & f); CanonicalForm convertNTLZZpX2CF(const ZZ_pX & poly,const Variable & x); CanonicalForm convertNTLzzpX2CF(const zz_pX & poly,const Variable & x); CanonicalForm convertNTLGF2X2CF(const GF2X & poly,const Variable & x); CanonicalForm convertNTLZZX2CF(const ZZX & polynom,const Variable & x); CFFList convertNTLvec_pair_ZZpX_long2FacCFFList(const vec_pair_ZZ_pX_long& e,const ZZ_p & multi,const Variable & x); CFFList convertNTLvec_pair_zzpX_long2FacCFFList(const vec_pair_zz_pX_long& e,const zz_p multi,const Variable & x); CFFList convertNTLvec_pair_GF2X_long2FacCFFList(const vec_pair_GF2X_long& e,const GF2 multi,const Variable & x); CanonicalForm convertZZ2CF(const ZZ & coefficient); ZZ convertFacCF2NTLZZ(const CanonicalForm & f); ZZX convertFacCF2NTLZZX(const CanonicalForm & f); CFFList convertNTLvec_pair_ZZX_long2FacCFFList(const vec_pair_ZZX_long& e,const ZZ & multi,const Variable & x); CanonicalForm convertNTLZZpE2CF(const ZZ_pE & coefficient,const Variable & x); CFFList convertNTLvec_pair_ZZpEX_long2FacCFFList(const vec_pair_ZZ_pEX_long & e,const ZZ_pE & multi,const Variable & x,const Variable & alpha); CanonicalForm convertNTLGF2E2CF(const GF2E & coefficient,const Variable & x); CFFList convertNTLvec_pair_GF2EX_long2FacCFFList(const vec_pair_GF2EX_long& e,const GF2E & multi,const Variable & x,const Variable & alpha); GF2EX convertFacCF2NTLGF2EX(const CanonicalForm & f,const GF2X & mipo); ZZ_pEX convertFacCF2NTLZZ_pEX(const CanonicalForm & f,const ZZ_pX & mipo); zz_pEX convertFacCF2NTLzz_pEX(const CanonicalForm & f,const zz_pX & mipo); CanonicalForm convertNTLzzpE2CF(const zz_pE & f, const Variable & x); CFFList convertNTLvec_pair_zzpEX_long2FacCFFList(const vec_pair_zz_pEX_long & e,const zz_pE & multi,const Variable & x,const Variable & alpha); CanonicalForm convertNTLzz_pEX2CF(const zz_pEX & f, const Variable & x, const Variable & alpha); CanonicalForm convertNTLZZ_pEX2CF(const ZZ_pEX & f, const Variable & x, const Variable & alpha); mat_ZZ* convertFacCFMatrix2NTLmat_ZZ(const CFMatrix &m); CFMatrix* convertNTLmat_ZZ2FacCFMatrix(const mat_ZZ &m); mat_zz_p* convertFacCFMatrix2NTLmat_zz_p(const CFMatrix &m); CFMatrix* convertNTLmat_zz_p2FacCFMatrix(const mat_zz_p &m); mat_zz_pE* convertFacCFMatrix2NTLmat_zz_pE(const CFMatrix &m); CFMatrix* convertNTLmat_zz_pE2FacCFMatrix(const mat_zz_pE &m, const Variable & alpha); extern long fac_NTL_char; #endif #endif singular-4.0.3+ds/factory/README000066400000000000000000000221311266270727000163030ustar00rootroot00000000000000 --- This `README' file corresponds to Singular-Factory version 4.0 --- README file for Singular-Factory ================================ NOTE: The copyright of Singular-Factory is described in the file COPYING Overview ======== 1. What is Factory? 2. Comments, Questions, Bug Reports 3. Installation 4. Distribution 5. Prerequisites 6. Stream IO 7. Diagnostic Messages 8. GF(q) Tables 9. A Note on Singular 10. Factory Template Instantiation 11. Documentation 12. Examples and Tests 13. Remark on Characteristic Sets 14. Adding new code 15. Nomenclature 16. Limitations 1. What is Factory? =================== Factory is a C++ class library that implements a recursive representation of multivariate polynomial data. It was developed by Ruediger Stobbe and Jens Schmidt at the University of Kaiserslautern as an independent and self-contained part of the computer algebra system Singular (developed by G.-M. Greuel, G. Pfister and H. Schoenemann) and is now developed by Martin Lee. Factory handles sparse multivariate polynomials over different coefficient domains, such as Z, Q and GF(q), as well as algebraic extensions over Q and GF(q) in an efficient way. Factory includes algorithms for computing univariate and multivariate gcds, resultants, chinese remainders, and algorithms to factorize multivariate polynomials and to compute the absolute factorization of multivariate polynomials with integer coefficients. The interface to the polynomial system of Factory is provided by a single class `CanonicalForm' which can deal with elements of the coefficient domain as well as polynomials. Using operator overloading, you can handle polynomial data similarly to built-in types such as the machine integers. For example, to add two polynomials one simply uses the `+' operator. Because of this, Factory is easy to use even if you are not familiar with C++ programming. There are a couple of utility classes provided by Factory such as lists, arrays, polynomial maps, etc. These make the usage more comfortable. 2. Comments, Questions, Bug Reports ==================================== Factory is a project in evolution. That means there is no guarantee that Factory is bug free. I am sure that there are bugs or at least features. If you find bugs or if you find a strange behavior of the library, please let me know (e-mail: singular@mathematik.uni-kl.de>). Comments and questions are welcome, too. Factory version 1.2c and newer define an external variable `factoryVersion' describing the version of the library. The external variable `factoryConfiguration' (not present in versions 1.2c and 1.3a) describes the options Factory has been configured with. Please include the version number and the configuration options in your bug reports. You may either use the UNIX utility `what' to get this information (`what libcf.a') or compile and run something similar to this: #include main() { cout << factoryVersion << "; " << factoryConfiguration << endl; } 3. Installation =============== NOTE: If you have received this Factory distribution together with Singular you do not have to worry about compilation or installation at all. The installation procedure for Singular should do everything for you. For more information, see the section "A Note on Singular". For further information on factory's configure options see also ./configure --help. The installation procedure on UNIX platforms conforms more or less to the GNU standard: ./configure --without-Singular; make; make check; make install; In general, this `README' as well as the `INSTALL' file are written for UNIX platforms. However, you may find less specific information on the configuration and installation process which is useful for other platforms, too. 4. Distribution =============== The latest stable version of Factory is always available from www.singular.uni-kl.de For the latest development version visit www.github.com/Singular 5. Prerequisites ================ You need GNU make to build and install Factory. Furthermore, I strongly recommend to build Factory with GNU CC. To build Factory and to link your programs with Factory you need the GNU Multiple Precision Library (GMP). Configure options: ------------------ --with-gmp= enabled by default For full functionality NTL (www.shoup.net/ntl) is required. Configure options: ------------------ --with-ntl= enabled by default For optimal preformance we recommend to use FLINT (www.flintlib.org) and to use Singular's memory manager omalloc Configure options: ------------------ --with-flint= enabled by default --with-omalloc disabled by default --with-omalloc-dir= 6. Stream IO ============ For use with other systems which have their own IO routines to print polynomials it is possible to switch off Factory's stream IO. Configure options: ------------------ --disable-streamio build Factory without stream IO 7. Diagnostic Messages ====================== Factory has three types of diagnostic messages: o Assertions (implemented by the "ASSERT macros" in `cf_assert.h') are used to ensure preconditions before running some algorithm. A typical example is to test f != 0 before dividing by f. o Debug output (implemented by the "DEBOUT macros" in `debug.h'/`debug.cc') is used to trace complex algorithms, e.g. factorization. o Timing information may be accumulated and printed using the "TIMING macros" in `timing.h'. Since all diagnostic messages are implemented using preprocessor macros, they will completely cease when disabled, thus avoiding any impact on speed. By default, all diagnostic messages are disabled. Configure options: ------------------ --enable-assertions build Factory with assertions activated --enable-timing build Factory so it will print timing information --enable-debugoutput build Factory so it will print debugging information 8. GF(q) Tables =============== Factory uses addition tables to calculate in GF(p^n) in an efficient way. They can be created with `make gengftables'. Building the tables takes quite a while! 9. A Note on Singular ===================== If you have received this Factory distribution together with Singular you do not have to worry about compilation or installation at all. The installation procedure for Singular should do everything for you. 10. Factory Template Instantiation ================================== There are a couple of classes provided by Factory such as lists, arrays, etc, which may be used to derive new abstract data types from already existing ones. Factory uses them itself, e.g. to return the result of a factorization (a list of factors), and you may use them to create new derived abstract data types. These classes are realized using C++ templates, which are instantiated in one single file namely ftmpl_inst.cc . 11. Documentation ================= So far there are only preliminary versions of a user/reference manual and a tutorial ("A quick start into Factory"). Please do not expect them to be error-free or even complete. For this reason, the documentation is not included in the source code archive (`factory-.tgz'). Instead, the sources and compiled DVI files reside in `factory-doc-prelim.tgz'. They will unpack into a directory `factory-doc-prelim/'. 12. Examples and Tests ====================== The directory `examples/' in the Factory source directory contains some example applications for Factory. 'make check' will run some simple test as well. 13. Remark on Characteristic Sets ================================= Algorithms for manipulation of polynomial ideals via the characteristic set methods (e.g., calculating the characteristic set and the irreducible characteristic series) are now incorpareted into factory. If you want to learn about characteristic sets, the next is a good point to start with: Dongming Wang: An Implementation of the Characteristic Set Method in Maple. In: Automated Practical Reasoning: Algebraic Approaches (J. Pfalzgraf and D. Wang, eds.), Springer-Verlag, Wien-New York, 1995, pp. 187-201. 14. Adding new code =================== If you like to add new code 'foo.cc/foo.h' add 'foo.cc' to 'Makefile.am' under 'SOURCES' and 'foo.h' under 'factory_headers'. If your new functions should be available via factory's global interface 'factory.h' add /*MAKEHEADER PUBLIC ONLY*/ foo.h to 'factory.template' and enclose the functions in 'foo.h', that you like to add, by '/*BEGINPUBLIC*/' and '/*ENDPUBLIC*/'. 15. Nomenclature ================ Factorization related functions are contained in files with the prefix 'fac'. Functions operating on CanonicalForm's are contained in files with the prefix 'cf'. Functions operating on the internal structures of a CanonicalForm are contained in files with the prefix 'int'. Exceptions are gfops.cc/.h, ffops.cc/.h, imm.cc/.h as they use intrinsic data types. 16. Limitations =============== The largest characteristic of a finite field is limited to 536870909. The number of elements of a finite fields represented by Conway polynomials has to be < 2^16 (see gfops.cc). singular-4.0.3+ds/factory/aminclude.am000066400000000000000000000111751266270727000177110ustar00rootroot00000000000000# Copyright (C) 2004 Oren Ben-Kiki # This file is distributed under the same terms as the Automake macro files. # Generate automatic documentation using Doxygen. Goals and variables values # are controlled by the various DX_COND_??? conditionals set by autoconf. # # The provided goals are: # doxygen-doc: Generate all doxygen documentation. # doxygen-run: Run doxygen, which will generate some of the documentation # (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post # processing required for the rest of it (PS, PDF, and some MAN). # doxygen-man: Rename some doxygen generated man pages. # doxygen-ps: Generate doxygen PostScript documentation. # doxygen-pdf: Generate doxygen PDF documentation. # # Note that by default these are not integrated into the automake goals. If # doxygen is used to generate man pages, you can achieve this integration by # setting man3_MANS to the list of man pages generated and then adding the # dependency: # # $(man3_MANS): doxygen-doc # # This will cause make to run doxygen and generate all the documentation. # # The following variable is intended for use in Makefile.am: # # DX_CLEANFILES = everything to clean. # # This is usually added to MOSTLYCLEANFILES. ## --------------------------------- ## ## Format-independent Doxygen rules. ## ## --------------------------------- ## if DX_COND_doc ## ------------------------------- ## ## Rules specific for HTML output. ## ## ------------------------------- ## if DX_COND_html DX_CLEAN_HTML = @DX_DOCDIR@/html endif DX_COND_html ## ------------------------------ ## ## Rules specific for CHM output. ## ## ------------------------------ ## if DX_COND_chm DX_CLEAN_CHM = @DX_DOCDIR@/chm if DX_COND_chi DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE@.chi endif DX_COND_chi endif DX_COND_chm ## ------------------------------ ## ## Rules specific for MAN output. ## ## ------------------------------ ## if DX_COND_man DX_CLEAN_MAN = @DX_DOCDIR@/man endif DX_COND_man ## ------------------------------ ## ## Rules specific for RTF output. ## ## ------------------------------ ## if DX_COND_rtf DX_CLEAN_RTF = @DX_DOCDIR@/rtf endif DX_COND_rtf ## ------------------------------ ## ## Rules specific for XML output. ## ## ------------------------------ ## if DX_COND_xml DX_CLEAN_XML = @DX_DOCDIR@/xml endif DX_COND_xml ## ----------------------------- ## ## Rules specific for PS output. ## ## ----------------------------- ## if DX_COND_ps DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE@.ps DX_PS_GOAL = doxygen-ps doxygen-ps: @DX_DOCDIR@/@PACKAGE@.ps @DX_DOCDIR@/@PACKAGE@.ps: @DX_DOCDIR@/@PACKAGE@.tag cd @DX_DOCDIR@/latex; \ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ $(DX_LATEX) refman.tex; \ $(MAKEINDEX_PATH) refman.idx; \ $(DX_LATEX) refman.tex; \ countdown=5; \ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ refman.log > /dev/null 2>&1 \ && test $$countdown -gt 0; do \ $(DX_LATEX) refman.tex; \ countdown=`expr $$countdown - 1`; \ done; \ $(DX_DVIPS) -o ../@PACKAGE@.ps refman.dvi endif DX_COND_ps ## ------------------------------ ## ## Rules specific for PDF output. ## ## ------------------------------ ## if DX_COND_pdf DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE@.pdf DX_PDF_GOAL = doxygen-pdf doxygen-pdf: @DX_DOCDIR@/@PACKAGE@.pdf @DX_DOCDIR@/@PACKAGE@.pdf: @DX_DOCDIR@/@PACKAGE@.tag cd @DX_DOCDIR@/latex; \ rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \ $(DX_PDFLATEX) refman.tex; \ $(DX_MAKEINDEX) refman.idx; \ $(DX_PDFLATEX) refman.tex; \ countdown=5; \ while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \ refman.log > /dev/null 2>&1 \ && test $$countdown -gt 0; do \ $(DX_PDFLATEX) refman.tex; \ countdown=`expr $$countdown - 1`; \ done; \ mv refman.pdf ../@PACKAGE@.pdf endif DX_COND_pdf ## ------------------------------------------------- ## ## Rules specific for LaTeX (shared for PS and PDF). ## ## ------------------------------------------------- ## if DX_COND_latex DX_CLEAN_LATEX = @DX_DOCDIR@/latex endif DX_COND_latex .PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL) .INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) doxygen-run: @DX_DOCDIR@/@PACKAGE@.tag doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL) @DX_DOCDIR@/@PACKAGE@.tag: $(DX_CONFIG) $(pkginclude_HEADERS) rm -rf @DX_DOCDIR@ $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG) DX_CLEANFILES = \ @DX_DOCDIR@/@PACKAGE@.tag \ -r \ $(DX_CLEAN_HTML) \ $(DX_CLEAN_CHM) \ $(DX_CLEAN_CHI) \ $(DX_CLEAN_MAN) \ $(DX_CLEAN_RTF) \ $(DX_CLEAN_XML) \ $(DX_CLEAN_PS) \ $(DX_CLEAN_PDF) \ $(DX_CLEAN_LATEX) endif DX_COND_doc singular-4.0.3+ds/factory/bin/000077500000000000000000000000001266270727000161745ustar00rootroot00000000000000singular-4.0.3+ds/factory/bin/fold-docu.el000066400000000000000000000006701266270727000203750ustar00rootroot00000000000000;; emacs edit mode for this file is -*- Emacs-Lisp -*- ;;{{{ docu ;; ;; fold-docu.el - fold all documentation foldings in a file. ;; ;; To unfold all documentation, call fold-open-buffer. ;; ;;}}} (require 'folding) (defun fold-docu () "Fold all documentation foldings in a file." (interactive) (goto-char (point-min)) (save-excursion (while (re-search-forward "{{{ .*docu$" nil t) (fold-hide)))) (provide 'fold-docu) singular-4.0.3+ds/factory/bin/folding.el000066400000000000000000001741231266270727000201500ustar00rootroot00000000000000;; @(#) folding.el -- A folding-editor-like minor mode 1.7 ;; Copyright (C) 1992, 1993, Jamie Lokier. All rights reserved. ;; This file is intended to be used with GNU Emacs. ;; This program is free software; you can redistribute 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 GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ;; --------------------------------------------------------------------- ;; This is version 1.7 of Folding mode, under development. ;; This file has been edited with a folding editor (itself! :-). ;; Send suggestions and/or bug fixes to "u90jl@ecs.ox.ac.uk". ;; If you can, please check the most recent version of Folding mode ;; before reporting bugs. If you can't, don't be afraid of reporting ;; bugs anyway. ;;{{{ Information ;; ----------------------- Archive information -------------------------- ;; LCD Archive Entry: ;; folding|Jamie Lokier|u90jl@ecs.ox.ac.uk| ;; A folding-editor-like minor mode| ;; 06-Jul-1993|1.7|~/modes/folding.el.Z| ;; -------------------------- Installation ------------------------------ ;; To install Folding mode, put this file (folding.el) on you Emacs-Lisp ;; load path, and put the following in your .emacs: ;; ;; (autoload 'folding-mode "folding" ;; "Minor mode that simulates a folding editor" t) ;; ;; To have Folding mode start automatically when opening folded files, ;; add the following to your .emacs as well: ;; ;; (defun folding-mode-find-file-hook () ;; "One of the hooks called whenever a `find-file' is successful." ;; (and (assq 'folded-file (buffer-local-variables)) ;; folded-file ;; (folding-mode 1) ;; (kill-local-variable 'folded-file))) ;; ;; (or (memq 'folding-mode-find-file-hook find-file-hooks) ;; (setq find-file-hooks (append find-file-hooks ;; '(folding-mode-find-file-hook)))) ;; ;; If you load folding.el all the time during startup, none of the above ;; is necessary; it can be replaced with this after loading folding.el: ;; ;; (folding-mode-add-find-file-hook) ;; ;; Brief documentation for Folding mode (what it is, how you use it) is ;; provided with the definition of the function `folding-mode'. ;; ;; The best way to learn how to use Folding mode after installing it is ;; to find-file the source, M-x eval-current-buffer, M-x folding-mode, ;; and move in and out of the folds. Keys are documented under the ;; function `folding-mode', though you might want to customize them. ;; Keys in folding mode are bound in the keymap `folding-mode-map'. ;; --------------------------- And the rest ----------------------------- ;; There are is no real documentation yet; I haven't had time. I intend ;; to write some one day, but I will refrain from predicting when. Read ;; the documentation for the function `folding-mode' for the most useful ;; tips. ;; Emacs 18: ;; Folding mode has been tested with versions 18.55 and 18.58 of Emacs. ;; Epoch: ;; Folding mode has been tested on Epoch 4.0p2. ;; Lucid Emacs: ;; There is code in here to handle some aspects of Lucid Emacs. ;; However, up to version 19.6, there appears to be no way to display ;; folds. Selective-display does not work, and neither do invisible ;; extents, so Folding mode has no chance of working. This is likely to ;; change in future versions of Lucid Emacs. ;; Emacs 19: ;; Tested on version 19.8, appears to be fine. ;; Minor bug: display the buffer in several different frames, then move ;; in and out of folds in the buffer. The frames are automatically ;; moved to the top of the stacking order. ;; Some of the code is quite horrible, generally in order to avoid some ;; Emacs display "features". Some of it is specific to certain versions ;; of Emacs. By the time Emacs 19 is around and everyone is using it, ;; hopefully most of it won't be necessary. ;; ------------------------ More known bugs ----------------------------- ;; *** Needs fold-fold-region to be more intelligent about ;; finding a good region. Check folding a whole current fold. ;; *** Now works with 19! But check out what happens when you exit a ;; fold with the file displayed in two frames. Both windows get ;; fronted. Better fix that sometime. ;; ------------------------- Future features ---------------------------- ;; *** I will add a `fold-next-error' sometime. It will only work with ;; Emacs versions later than 18.58, because compile.el in earlier ;; versions does not count line-numbers in the right way, when selective ;; display is active. ;; *** Fold titles should be optionally allowed on the closing fold ;; marks, and `fold-tidy-inside' should check that the opening title ;; matches the closing title. ;; *** `folded-file' set in the local variables at the end of a file ;; could encode the type of fold marks used in that file, and other ;; things, like the margins inside folds. ;; *** I can see a lot of use for the newer features of Emacs 19: ;; ;; Using invisible text-properties (I hope they are intended to ;; make text invisible; it isn't implemented like that yet), it ;; will be possible to hide folded text without affecting the ;; text of the buffer. At the moment, Folding mode uses ;; selective display to hide text, which involves substituting ;; carriage-returns for line-feeds in the buffer. This isn't ;; such a good way. It may also be possible to display ;; different folds in different windows in Emacs 19. ;; ;; Using even more text-properties, it may be possible to track ;; pointer movements in and out of folds, and have Folding mode ;; automatically enter or exit folds as necessary to maintain a ;; sensible display. Because the text itself is not modified ;; (if overlays are used to hide text), this is quite safe. It ;; would make it unnecessary to provide functions like ;; `fold-forward-char', `fold-goto-line' or `fold-next-error', ;; and things like I-search would automatically move in and out ;; of folds as necessary. ;; ;; Yet more text-properties/overlays might make it possible to ;; avoid using narrowing. This might allow some major modes to ;; indent text properly, e.g., C++ mode. ;; ------------------------- History ------------------------------------ ;; Dec 1 1994 Jari Aalto , ;; - Only minor change. Made the folding mode string user configurable. ;; Added these variables: ;; o folding-mode-v-str , fold-v-inside-in-str,fold-v-inside-in-fold-str ;; - Changed revision number from 1.6.2 to 1.7 , so that people know ;; this el has changed. ;; - Advertise: I made couple of extra functions for this module, please ;; look at the goodies in tinyfold.el. ;;}}} ;;{{{ Declare `folding' as a feature (provide 'folding) ;;}}} ;;{{{ Check Emacs version and set some constants. ;; Sets `fold-emacs-version' to `epoch, `lucid, or the numbers 18 or 19, ;; as appropriate, and sets a few related variables. (setq fold-epoch-screens-p nil fold-lucid-screens-p nil fold-lucid-keymaps-p nil fold-emacs-frames-p nil) (let ((case-fold-search t)) (cond ((boundp 'epoch::version) ;; Epoch (setq fold-epoch-screens-p t)) ((string-match "lucid" emacs-version) ;; Lucid Emacs (setq fold-lucid-screens-p t fold-lucid-keymaps-p t)) ((string< emacs-version "19")) ;; Emacs 18.x (or less) (t ;; Emacs 19+ (setq fold-emacs-frames-p t)))) ;;}}} ;;{{{ Start Folding mode, and related items. Documentation is here ;;{{{ folding-mode the variable (defvar folding-mode nil "Non-nil means Folding mode is active in the current buffer.") (make-variable-buffer-local 'folding-mode) (set-default 'folding-mode nil) (defvar folding-mode-v-str "Fld" "*The minor mode string displayed when it's on.") ;;}}} ;;{{{ folding-mode the function (defun folding-mode (&optional arg inter) "Turns Folding mode (a minor mode) on and off. These are the basic commands that Folding mode provides: \\ fold-enter: `\\[fold-enter]' Enters the fold that the point is on. fold-exit: `\\[fold-exit]' Exits the current fold. fold-fold-region: `\\[fold-fold-region]' Surrounds the region with a new fold. fold-top-level: `\\[fold-top-level]' Exits all folds. fold-show: `\\[fold-show]' Opens the fold that the point is on, but does not enter it. fold-hide: `\\[fold-hide]' Closes the fold that the point is in, exiting it if necessary. fold-whole-buffer: `\\[fold-whole-buffer]' Folds the whole buffer. fold-open-buffer: `\\[fold-open-buffer]' Unfolds the whole buffer; good to do just before a search. fold-remove-folds: `\\[fold-remove-folds]' Makes a ready-to-print, formatted, unfolded copy in another buffer. Read the documentation for the above functions for more information. Folds are a way of hierarchically organising the text in a file, so that the text can be viewed and edited at different levels. It is similar to Outline mode in that parts of the text can be hidden from view. A fold is a region of text, surrounded by special \"fold marks\", which act like brackets, grouping the text. Fold mark pairs can be nested, and they can have titles. When a fold is folded, the text is hidden from view, except for the first line, which acts like a title for the fold. Folding mode is a minor mode, designed to cooperate with many other major modes, so that many types of text can be folded while they are being edited (eg., plain text, program source code, Texinfo, etc.). For most types of folded file, lines representing folds have \"{{{\" near the beginning. To enter a fold, move the point to the folded line and type `\\[fold-enter]'. You should no longer be able to see the rest of the file, just the contents of the fold, which you couldn't see before. You can use `\\[fold-exit]' to leave a fold, and you can enter and exit folds to move around the structure of the file. All of the text is present in a folded file all of the time. It is just hidden. Folded text shows up as a line (the top fold mark) with \"...\" at the end. If you are in a fold, the mode line displays \"inside n folds Narrow\", and because the buffer is narrowed you can't see outside of the current fold's text. By arranging sections of a large file in folds, and maybe subsections in sub-folds, you can move around a file quickly and easily, and only have to scroll through a couple of pages at a time. If you pick the titles for the folds carefully, they can be a useful form of documentation, and make moving though the file a lot easier. In general, searching through a folded file for a particular item is much easier than without folds. To make a new fold, set the mark at one end of the text you want in the new fold, and move the point to the other end. Then type `\\[fold-fold-region]'. The text you selected will be made into a fold, and the fold will be entered. If you just want a new, empty fold, set the mark where you want the fold, and then create a new fold there without moving the point. Don't worry if the point is in the middle of a line of text, `fold-fold-region' will not break text in the middle of a line. After making a fold, the fold is entered and the point is positioned ready to enter a title for the fold. Do not delete the fold marks, which are usually something like \"{{{\" and \"}}}\". There may also be a bit of fold mark which goes after the fold title. If the fold markers get messed up, or you just want to see the whole unfolded file, use `\\[fold-open-buffer]' to unfolded the whole file, so you can see all the text and all the marks. This is useful for checking/correcting unbalanced fold markers, and for searching for things. Use `\\[fold-whole-file]' to fold the buffer again. `fold-exit' will attempt to tidy the current fold just before exiting it. It will remove any extra blank lines at the top and bottom, \(outside the fold marks). It will then ensure that fold marks exists, and if they are not, will add them (after asking). Finally, the number of blank lines between the fold marks and the contents of the fold is set to 1 (by default). You can make folded files start Folding mode automatically when they are visited by setting `folded-file' to t in the file's local variables. For example, having the following at the end of an Emacs-Lisp file causes it to be folded when visited: ;; Local variables: ;; folded-file: t ;; end: This only works if you have the appropriate hook set up. Look up the function `folding-mode-add-find-file-hook' for details. If the fold marks are not set on entry to Folding mode, they are set to a default for current major mode, as defined by `fold-mode-marks-alist' or to \"{{{ \" and \"}}}\" if none are specified. To bind different commands to keys in Folding mode, set the bindings in the keymap `folding-mode-map'. The hooks `folding-mode-hook' and `-folding-hook' are called before folding the buffer and applying the key bindings in `folding-mode-map'. This is a good hook to set extra or different key bindings in `folding-mode-map'. Note that key bindings in `folding-mode-map' are only examined just after calling these hooks; new bindings in those maps only take effect when Folding mode is being started. If Folding mode is not called interactively (`(interactive-p)' is nil), and it is called with two or less arguments, all of which are nil, then the point will not be altered if `fold-fold-on-startup' is set and `fold-whole-buffer' is called. This is generally not a good thing, as it can leave the point inside a hidden region of a fold, but it is required if the local variables set \"mode: folding\" when the file is first read (see `hack-local-variables'). Not that you should ever want to, but to call Folding mode from a program with the default behaviour (toggling the mode), call it with something like `(folding-mode nil t)'. Here is the full list of keys bound in Folding mode: \\{folding-mode-map}" (interactive) (let ((new-folding-mode (if (not arg) (not folding-mode) (> (prefix-numeric-value arg) 0)))) (or (eq new-folding-mode folding-mode) (if folding-mode (progn (setq selective-display nil) (fold-clear-stack) (widen) (fold-subst-regions (list 1 (point-max)) ?\r ?\n) (and (boundp 'fold-saved-local-keymap) (progn (use-local-map fold-saved-local-keymap) (kill-local-variable 'fold-saved-local-keymap) (makunbound 'fold-saved-local-keymap)))) (make-local-variable 'fold-saved-local-keymap) (setq fold-saved-local-keymap (current-local-map)) (setq selective-display t) (setq selective-display-ellipses t) (widen) (set (make-local-variable 'fold-stack) nil) (make-local-variable 'fold-top-mark) (make-local-variable 'fold-secondary-top-mark) (make-local-variable 'fold-top-regexp) (make-local-variable 'fold-bottom-mark) (make-local-variable 'fold-bottom-regexp) (make-local-variable 'fold-regexp) (or (and (boundp 'fold-top-regexp) fold-top-regexp (boundp 'fold-bottom-regexp) fold-bottom-regexp) (let ((fold-marks (assq major-mode fold-mode-marks-alist))) (if fold-marks (setq fold-marks (cdr fold-marks)) (setq fold-marks '("{{{ " "}}}"))) (apply 'fold-set-marks fold-marks))) (unwind-protect (let ((hook-symbol (intern-soft (concat (symbol-name major-mode) "-folding-hook")))) (run-hooks 'folding-mode-hook) (and hook-symbol (run-hooks hook-symbol))) (fold-set-mode-line) (use-local-map (fold-merge-keymaps (current-local-map) folding-mode-map))) (and fold-fold-on-startup (if (or (interactive-p) arg inter) (fold-whole-buffer) (save-excursion (fold-whole-buffer)))) (fold-narrow-to-region nil nil t))) (setq folding-mode new-folding-mode))) ;;}}} ;;{{{ keys: folding-mode-map (defvar folding-mode-map nil "Keymap used in Folding mode (a minor mode).") (and fold-lucid-keymaps-p (set-keymap-name folding-mode-map 'folding-mode-map)) (if folding-mode-map nil (setq folding-mode-map (make-sparse-keymap)) (define-key folding-mode-map "\M-g" 'fold-goto-line) (define-key folding-mode-map "\C-c>" 'fold-enter) (define-key folding-mode-map "\C-c<" 'fold-exit) (define-key folding-mode-map "\C-c\C-t" 'fold-top-level) (define-key folding-mode-map "\C-c\C-f" 'fold-fold-region) (define-key folding-mode-map "\C-c\C-s" 'fold-show) (define-key folding-mode-map "\C-c\C-x" 'fold-hide) (define-key folding-mode-map "\C-c\C-o" 'fold-open-buffer) (define-key folding-mode-map "\C-c\C-w" 'fold-whole-buffer) (define-key folding-mode-map "\C-c\C-r" 'fold-remove-folds) (define-key folding-mode-map "\C-f" 'fold-forward-char) (define-key folding-mode-map "\C-b" 'fold-backward-char) (define-key folding-mode-map "\C-e" 'fold-end-of-line)) ;;}}} ;;{{{ fold-stack ;; This is a list of structures which keep track of folds being entered ;; and exited. It is a list of (MARKER . MARKER) pairs, followed by the ;; symbol `folded'. The first of these represents the fold containing ;; the current one. If the view is currently outside all folds, this ;; variable has value nil. (defvar fold-stack nil "A list of marker pairs representing folds entered so far.") ;;}}} ;;{{{ fold-clear-stack ;; Clear the fold stack, and release all the markers it refers to. (defun fold-clear-stack () (let ((stack fold-stack)) (setq fold-stack nil) (while (and stack (not (eq 'folded (car stack)))) (set-marker (car (car stack)) nil) (set-marker (cdr (car stack)) nil) (setq stack (cdr stack))))) ;;}}} ;;{{{ fold-mode-string (defvar fold-mode-string nil "Buffer-local variable that holds the fold depth description.") (set-default 'fold-mode-string " Fld") ; to save space... ;;}}} ;;{{{ fold-set-mode-line ;; Sets `fold-mode-string' appropriately. This allows the Folding mode ;; description in the mode line to reflect the current fold depth." (defconst fold-v-inside-in-str " " ; normally ' inside ', but save space.. "*Mode line addition to show 'inside' levels of fold.") (defconst fold-v-inside-in-fold-str "Fld" ; normally 'fold', but save space.. "*Mode line addition to show inside levels of 'fold' .") (defun fold-set-mode-line () (if (null fold-stack) (kill-local-variable 'fold-mode-string) (make-local-variable 'fold-mode-string) (setq fold-mode-string (if (eq 'folded (car fold-stack)) (concat fold-v-inside-in-str "1" fold-v-inside-in-fold-str) (concat fold-v-inside-in-str (length fold-stack) fold-v-inside-in-fold-str) )))) ;;}}} ;;{{{ Update minor-mode-alist (or (assq 'folding-mode minor-mode-alist) (setq minor-mode-alist (cons '(folding-mode fold-mode-string) minor-mode-alist))) ;;}}} ;;}}} ;;{{{ Hooks and variables ;;{{{ folding-mode-hook (defvar folding-mode-hook nil "Hook called when Folding mode is entered. A hook named `-folding-hook' is also called, if it exists. Eg., `c-mode-folding-hook' is called whenever Folding mode is started in C mode.") ;;}}} ;;{{{ fold-fold-on-startup (defvar fold-fold-on-startup t "*If non-nil, buffers are folded when starting Folding mode.") ;;}}} ;;{{{ fold-internal-margins (defvar fold-internal-margins 1 "*Number of blank lines left next to fold marks when tidying folds. This variable is local to each buffer. To set the default value for all buffers, use `set-default'. When exiting a fold, and at other times, `fold-tidy-inside' is invoked to ensure that the fold is in the correct form before leaving it. This variable specifies the number of blank lines to leave between the enclosing fold marks and the enclosed text. If this value is nil or negative, no blank lines are added or removed inside the fold marks. A value of 0 (zero) is valid, meaning leave no blank lines. See also `fold-tidy-inside'.") (make-variable-buffer-local 'fold-internal-margins) ;;}}} ;;{{{ fold-mode-marks-alist (defvar fold-mode-marks-alist nil "List of (major-mode . fold marks) default combinations to use. When Folding mode is started, the major mode is checked, and if there are fold marks for that major mode stored in `fold-mode-marks-alist', those marks are used by default. If none are found, the default values of \"{{{ \" and \"}}}\" are used.") ;;}}} ;;}}} ;;{{{ Regular expressions for matching fold marks ;;{{{ fold-set-marks ;; You think those "\\(\\)" pairs are peculiar? Me too. Emacs regexp ;; stuff has a bug; sometimes "\\(.*\\)" fails when ".*" succeeds, but ;; only in a folded file! Strange bug! Must check it out sometime. (defun fold-set-marks (top bottom &optional secondary) "Sets the folding top and bottom marks for the current buffer. The fold top mark is set to TOP, and the fold bottom mark is set to BOTTOM. And optional SECONDARY top mark can also be specified -- this is inserted by `fold-fold-region' after the fold top mark, and is presumed to be put after the title of the fold. This is not necessary with the bottom mark because it has no title. Various regular expressions are set with this function, so don't set the mark variables directly." (set (make-local-variable 'fold-top-mark) top) (set (make-local-variable 'fold-bottom-mark) bottom) (set (make-local-variable 'fold-secondary-top-mark) secondary) (set (make-local-variable 'fold-top-regexp) (concat "\\(^\\|\r+\\)[ \t]*" (regexp-quote fold-top-mark))) (set (make-local-variable 'fold-bottom-regexp) (concat "\\(^\\|\r+\\)[ \t]*" (regexp-quote fold-bottom-mark))) (set (make-local-variable 'fold-regexp) (concat "\\(^\\|\r\\)\\([ \t]*\\)\\(\\(" (regexp-quote fold-top-mark) "\\)\\|\\(" (regexp-quote fold-bottom-mark) "[ \t]*\\(\\)\\($\\|\r\\)\\)\\)"))) ;;}}} ;;}}} ;;{{{ Cursor movement that skips folded regions ;;{{{ fold-forward-char (defun fold-forward-char (&optional arg) "Move point right ARG characters, skipping hidden folded regions. Moves left if ARG is negative. On reaching end of buffer, stop and signal error." (interactive "p") (if (eq arg 1) ;; Do it a faster way for arg = 1. (if (eq (following-char) ?\r) (let ((saved (point)) (inhibit-quit t)) (end-of-line) (if (not (eobp)) (forward-char) (goto-char saved) (error "End of buffer"))) ;; `forward-char' here will do its own error if (eobp). (forward-char)) (if (> 0 (or arg (setq arg 1))) (fold-backward-char (- arg)) (let (goal saved) (while (< 0 arg) (skip-chars-forward "^\r" (setq goal (+ (point) arg))) (if (eq goal (point)) (setq arg 0) (if (eobp) (error "End of buffer") (setq arg (- goal 1 (point)) saved (point)) (let ((inhibit-quit t)) (end-of-line) (if (not (eobp)) (forward-char) (goto-char saved) (error "End of buffer")))))))))) ;;}}} ;;{{{ fold-backward-char (defun fold-backward-char (&optional arg) "Move point left ARG characters, skipping hidden folded regions. Moves right if ARG is negative. On reaching beginning of buffer, stop and signal error." (interactive "p") (if (eq arg 1) ;; Do it a faster way for arg = 1. ;; Catch the case where we are in a hidden region, and bump into a \r. (if (or (eq (preceding-char) ?\n) (eq (preceding-char) ?\r)) (let ((pos (1- (point))) (inhibit-quit t)) (forward-char -1) (beginning-of-line) (skip-chars-forward "^\r" pos)) (forward-char -1)) (if (> 0 (or arg (setq arg 1))) (fold-forward-char (- arg)) (let (goal) (while (< 0 arg) (skip-chars-backward "^\r\n" (max (point-min) (setq goal (- (point) arg)))) (if (eq goal (point)) (setq arg 0) (if (bobp) (error "Beginning of buffer") (setq arg (- (point) 1 goal) goal (point)) (let ((inhibit-quit t)) (forward-char -1) (beginning-of-line) (skip-chars-forward "^\r" goal))))))))) ;;}}} ;;{{{ fold-end-of-line (defun fold-end-of-line (&optional arg) "Move point to end of current line, but before hidden folded region. Has the same behavior as `end-of-line', except that if the current line ends with some hidden folded text (represented by an ellipsis), the point is positioned just before it. This prevents the point from being placed inside the folded text, which is not normally useful." (interactive "p") (if (or (eq arg 1) (not arg)) (beginning-of-line) ;; `forward-line' also moves point to beginning of line. (forward-line (1- arg))) (skip-chars-forward "^\r\n")) ;;}}} ;;{{{ fold-skip-ellipsis-backward (defun fold-skip-ellipsis-backward () "Moves the point backwards out of folded text. If the point is inside a folded region, the cursor is displayed at the end of the ellipsis representing the folded part. This function checks to see if this is the case, and if so, moves the point backwards until it is just outside the hidden region, and just before the ellipsis. Returns t if the point was moved, nil otherwise." (interactive) (let ((pos (point)) result) (save-excursion (beginning-of-line) (skip-chars-forward "^\r" pos) (or (eq pos (point)) (setq pos (point) result t))) (goto-char pos) result)) ;;}}} ;;}}} ;;{{{ Moving in and out of folds ;;{{{ fold-enter (defun fold-enter (&optional noerror) "Open and enter the fold at or around the point. Enters the fold that the point is inside, wherever the point is inside the fold, provided it is a valid fold with balanced top and bottom marks. Returns nil if the fold entered contains no sub-folds, t otherwise. If an optional argument NOERROR is non-nil, returns nil if there are no folds to enter, instead of causing an error. If the point is inside a folded, hidden region (as represented by an ellipsis), the position of the point in the buffer is preserved, and as many folds as necessary are entered to make the surrounding text visible. This is useful after some commands eg., search commands." (interactive) (let ((goal (point))) (if (fold-skip-ellipsis-backward) (while (prog2 (beginning-of-line) (fold-enter t) (goto-char goal))) (let ((data (fold-show noerror t))) (and data (progn (setq fold-stack (if fold-stack (cons (cons (point-min-marker) (point-max-marker)) fold-stack) '(folded))) (fold-set-mode-line) (fold-narrow-to-region (car data) (nth 1 data)) (nth 2 data))))))) ;;}}} ;;{{{ fold-exit (defun fold-exit () "Exits the current fold." (interactive) (if fold-stack (progn (fold-tidy-inside) (fold-subst-regions (list (point-min) (point-max)) ?\n ?\r) (goto-char (point-min)) ;; So point is correct in other windows. (if (eq (car fold-stack) 'folded) (fold-narrow-to-region nil nil t) (fold-narrow-to-region (marker-position (car (car fold-stack))) (marker-position (cdr (car fold-stack))) t)) (and (consp (car fold-stack)) (set-marker (car (car fold-stack)) nil) (set-marker (cdr (car fold-stack)) nil)) (setq fold-stack (cdr fold-stack))) (error "Outside all folds")) (fold-set-mode-line)) ;;}}} ;;{{{ fold-show (defun fold-show (&optional noerror noskip) "Opens the fold that the point is on, but does not enter it. Optional arg NOERROR means don't signal an error if there is no fold, just return nil. NOSKIP means don't jump out of a hidden region first. Returns ((START END SUBFOLDS-P). START and END indicate the extents of the fold that was shown. If SUBFOLDS-P is non-nil, the fold contains subfolds." (interactive "p") (or noskip (fold-skip-ellipsis-backward)) (let ((point (point)) backward forward start end subfolds-not-p) (unwind-protect (or (and (integerp (car-safe (setq backward (fold-skip-folds t)))) (integerp (car-safe (setq forward (fold-skip-folds nil)))) (progn (goto-char (car forward)) (skip-chars-forward "^\r\n") (setq end (point)) (skip-chars-forward "\r\n") (not (and fold-stack (eobp)))) (progn (goto-char (car backward)) (skip-chars-backward "^\r\n") (setq start (point)) (skip-chars-backward "\r\n") (not (and fold-stack (bobp)))) (progn (setq point start) (setq subfolds-not-p ; Avoid holding the list through a GC. (not (or (cdr backward) (cdr forward)))) (fold-subst-regions (append backward (nreverse forward)) ?\r ?\n) (list start end (not subfolds-not-p)))) (if noerror nil (error "Not on a fold"))) (goto-char point)))) ;;}}} ;;{{{ fold-hide (defun fold-hide () "Close the fold around the point, undoes effect of `fold-show'." (interactive) (fold-skip-ellipsis-backward) (if (and (integerp (setq start (car-safe (fold-skip-folds t)))) (integerp (setq end (car-safe (fold-skip-folds nil))))) (if (and fold-stack (or (eq start (point-min)) (eq end (point-max)))) (error "Cannot hide current fold") (goto-char start) (skip-chars-backward "^\r\n") (fold-subst-regions (list start end) ?\n ?\r)) (error "Not on a fold"))) ;;}}} ;;{{{ fold-top-level (defun fold-top-level () "Exits all folds, to the top level." (interactive) (while fold-stack (fold-exit))) ;;}}} ;;{{{ fold-goto-line (defun fold-goto-line (line) "Go to line ARG, entering as many folds as possible." (interactive "nGoto line: ") (fold-top-level) (goto-char 1) (and (< 1 line) (re-search-forward "[\n\C-m]" nil 0 (1- line))) (let ((goal (point))) (while (prog2 (beginning-of-line) (fold-enter t) (goto-char goal)))) (fold-narrow-to-region (point-min) (point-max) t)) ;;}}} ;;}}} ;;{{{ Searching for fold boundaries ;;{{{ fold-skip-folds ;; Skips forward through the buffer (backward if BACKWARD is non-nil) ;; until it finds a closing fold mark or the end of the buffer. The ;; point is not moved. Jumps over balanced fold-mark pairs on the way. ;; Returns t if the end of buffer was found in an unmatched fold-mark ;; pair, otherwise a list. ;; If the point is actually on an fold start mark, the mark is ignored; ;; if it is on an end mark, the mark is noted. This decision is ;; reversed if BACKWARD is non-nil. If optional OUTSIDE is non-nil and ;; BACKWARD is nil, either mark is noted. ;; The first element of the list is a position in the end of the closing ;; fold mark if one was found, or nil. It is followed by (END START) ;; pairs (flattened, not a list of pairs). The pairs indicating the ;; positions of folds skipped over; they are positions in the fold ;; marks, not necessarily at the ends of the fold marks. They are in ;; the opposite order to that in which they were skipped. The point is ;; left in a meaningless place. If going backwards, the pairs are ;; (START END) pairs, as the fold marks are scanned in the opposite ;; order. ;; Works by maintaining the position of the top and bottom marks found ;; so far. They are found separately using a normal string search for ;; the fixed part of a fold mark (because it is faster than a regexp ;; search if the string does not occur often outside of fold marks), ;; checking that it really is a proper fold mark, then considering the ;; earliest one found. The position of the other (if found) is ;; maintained to avoid an unnecessary search at the next iteration. (defun fold-skip-folds (backward &optional outside) (save-excursion (let ((depth 0) pairs point temp start first last (first-mark (if backward fold-bottom-mark fold-top-mark)) (last-mark (if backward fold-top-mark fold-bottom-mark)) (search (if backward 'search-backward 'search-forward))) (skip-chars-backward "^\r\n") (if outside nil (and (eq (preceding-char) ?\r) (forward-char -1)) (if (looking-at fold-top-regexp) (if backward (setq last (match-end 1)) (skip-chars-forward "^\r\n")))) (while (progn ;; Find last first, prevents unnecessary searching for first. (setq point (point)) (or last (while (and (funcall search last-mark first t) (progn (setq temp (point)) (goto-char (match-beginning 0)) (skip-chars-backward " \t") (and (not (setq last (if (eq (preceding-char) ?\r) temp (and (bolp) temp)))) (goto-char temp))))) (goto-char point)) (or first (while (and (funcall search first-mark last t) (progn (setq temp (point)) (goto-char (match-beginning 0)) (skip-chars-backward " \t") (and (not (setq first (if (eq (preceding-char) ?\r) temp (and (bolp) temp)))) (goto-char temp)))))) ;; Return value of conditional says whether to iterate again. (if (not last) ;; Return from this with the result. (not (setq pairs (if first t (cons nil pairs)))) (if (and first (if backward (> first last) (< first last))) (progn (goto-char first) (if (eq 0 depth) (setq start first first nil depth 1) ;; non-nil value, loop again. (setq first nil depth (1+ depth)))) ;; non-nil value, loop again (goto-char last) (if (eq 0 depth) (not (setq pairs (cons last pairs))) (or (< 0 (setq depth (1- depth))) (setq pairs (cons last (cons start pairs)))) (setq last nil) t))))) pairs))) ;;}}} ;;}}} ;;{{{ Functions that actually modify the buffer ;;{{{ fold-fold-region (defun fold-fold-region (start end) "Places fold marks at the beginning and end of a specified region. The region is specified by two arguments START and END. The point is left at a suitable place ready to insert the title of the fold." (interactive "r") (and (< end start) (setq start (prog1 end (setq end start)))) (setq end (set-marker (make-marker) end)) (goto-char start) (beginning-of-line) (setq start (point)) (insert-before-markers fold-top-mark) (let ((saved-point (point))) (and fold-secondary-top-mark (insert-before-markers fold-secondary-top-mark)) (insert-before-markers ?\n) (goto-char (marker-position end)) (set-marker end nil) (and (not (bolp)) (eq 0 (forward-line)) (eobp) (insert ?\n)) (insert fold-bottom-mark) (insert ?\n) (setq fold-stack (if fold-stack (cons (cons (point-min-marker) (point-max-marker)) fold-stack) '(folded))) (fold-narrow-to-region start (1- (point))) (goto-char saved-point) (fold-set-mode-line)) (save-excursion (fold-tidy-inside))) ;;}}} ;;{{{ fold-tidy-inside ;; Note to self: The long looking code for checking and modifying those ;; blank lines is to make sure the text isn't modified unnecessarily. ;; Don't remove it again! (defun fold-tidy-inside () "Adds or removes blank lines at the top and bottom of the current fold. Also adds fold marks at the top and bottom (after asking), if they are not there already. The amount of space left depends on the variable `fold-internal-margins', which is one by default." (interactive) (if buffer-read-only nil (goto-char (point-min)) (and (eolp) (progn (skip-chars-forward "\n\t ") (delete-region (point-min) (point)))) (and (if (looking-at fold-top-regexp) (progn (forward-line 1) (and (eobp) (insert ?\n)) t) (and (y-or-n-p "Insert missing fold-top-mark? ") (progn (insert (concat fold-top-mark "" (or fold-secondary-top-mark "") "\n")) t))) fold-internal-margins (<= 0 fold-internal-margins) (let* ((p1 (point)) (p2 (progn (skip-chars-forward "\n") (point))) (p3 (progn (skip-chars-forward "\n\t ") (skip-chars-backward "\t " p2) (point)))) (if (eq p2 p3) (or (eq p2 (setq p3 (+ p1 fold-internal-margins))) (if (< p2 p3) (newline (- p3 p2)) (delete-region p3 p2))) (delete-region p1 p3) (or (eq 0 fold-internal-margins) (newline fold-internal-margins))))) (goto-char (point-max)) (and (bolp) (progn (skip-chars-backward "\n") (delete-region (point) (point-max)))) (beginning-of-line) (and (or (looking-at fold-bottom-regexp) (progn (goto-char (point-max)) nil) (and (y-or-n-p "Insert missing fold-bottom-mark? ") (progn (insert (concat "\n" fold-bottom-mark)) (beginning-of-line) t))) fold-internal-margins (<= 0 fold-internal-margins) (let* ((p1 (point)) (p2 (progn (skip-chars-backward "\n") (point))) (p3 (progn (skip-chars-backward "\n\t ") (skip-chars-forward "\t " p2) (point)))) (if (eq p2 p3) (or (eq p2 (setq p3 (- p1 1 fold-internal-margins))) (if (> p2 p3) (newline (- p2 p3)) (delete-region p2 p3))) (delete-region p3 p1) (newline (1+ fold-internal-margins))))))) ;;}}} ;;}}} ;;{{{ Operations on the whole buffer ;;{{{ fold-whole-buffer (defun fold-whole-buffer () "Folds every fold in the current buffer. Fails if the fold markers are not balanced correctly. If the buffer is being viewed in a fold, folds are repeatedly exited to get to the top level first (this allows the folds to be tidied on the way out). The buffer modification flag is not affected, and this function will work on read-only buffers." (interactive) (message "Folding buffer...") (let ((narrow-min (point-min)) (narrow-max (point-max)) fold-list fold) (save-excursion (widen) (goto-char 1) (setq fold-list (fold-skip-folds nil t)) (narrow-to-region narrow-min narrow-max) (and (eq t fold-list) (error "Cannot fold whole buffer -- unmatched begin-fold mark")) (and (integerp (car fold-list)) (error "Cannot fold whole buffer -- extraneous end-fold mark")) (fold-top-level) (widen) (goto-char 1) ;; Do the modifications forwards. (fold-subst-regions (nreverse (cdr fold-list)) ?\n ?\r)) (beginning-of-line) (fold-narrow-to-region nil nil t) (message "Folding buffer... done"))) ;;}}} ;;{{{ fold-open-buffer (defun fold-open-buffer () "Unfolds the entire buffer, leaving the point where it is. Does not affect the buffer-modified flag, and can be used on read-only buffers." (interactive) (message "Unfolding buffer...") (fold-clear-stack) (fold-set-mode-line) (unwind-protect (progn (widen) (fold-subst-regions (list 1 (point-max)) ?\r ?\n)) (fold-narrow-to-region nil nil t)) (message "Unfolding buffer... done")) ;;}}} ;;{{{ fold-remove-folds (defun fold-remove-folds (&optional buffer pre-title post-title pad) "Removes folds from a buffer, for printing. It copies the contents of the (hopefully) folded buffer BUFFER into a buffer called `*Unfolded: *', removing all of the fold marks. It keeps the titles of the folds, however, and numbers them. Subfolds are numbered in the form 5.1, 5.2, 5.3 etc., and the titles are indented to eleven characters. It accepts four arguments. BUFFER is the name of the buffer to be operated on, or a buffer. nil means use the current buffer. PRE-TITLE is the text to go before the replacement fold titles, POST-TITLE is the text to go afterwards. Finally, if PAD is non-nil, the titles are all indented to the same column, which is eleven plus the length of PRE-TITLE. Otherwise just one space is placed between the number and the title." (interactive (list (read-buffer "Remove folds from buffer: " (buffer-name) t) (read-string "String to go before enumerated titles: ") (read-string "String to go after enumerated titles: ") (y-or-n-p "Pad section numbers with spaces? "))) (set-buffer (setq buffer (get-buffer buffer))) (setq pre-title (or pre-title "") post-title (or post-title "")) (or folding-mode (error "Must be in Folding mode before removing folds")) (let ((new-buffer (get-buffer-create (concat "*Unfolded: " (buffer-name buffer) "*"))) (section-list '(1)) (section-prefix-list '("")) title (secondary-mark-length (length fold-secondary-top-mark)) (regexp fold-regexp) (secondary-mark fold-secondary-top-mark) prefix (mode major-mode)) (buffer-flush-undo new-buffer) (save-excursion (set-buffer new-buffer) (delete-region (point-min) (point-max))) (save-restriction (widen) (copy-to-buffer new-buffer (point-min) (point-max))) (display-buffer new-buffer t) (set-buffer new-buffer) (subst-char-in-region (point-min) (point-max) ?\r ?\n) (funcall mode) (while (re-search-forward regexp nil t) (if (match-beginning 4) (progn (goto-char (match-end 4)) (setq title (buffer-substring (point) (progn (end-of-line) (point)))) (delete-region (save-excursion (goto-char (match-beginning 4)) (skip-chars-backward "\n\r") (point)) (progn (skip-chars-forward "\n\r") (point))) (and (<= secondary-mark-length (length title)) (string-equal secondary-mark (substring title (- secondary-mark-length))) (setq title (substring title 0 (- secondary-mark-length)))) (setq section-prefix-list (cons (setq prefix (concat (car section-prefix-list) (int-to-string (car section-list)) ".")) section-prefix-list)) (or (cdr section-list) (insert ?\n)) (setq section-list (cons 1 (cons (1+ (car section-list)) (cdr section-list)))) (setq title (concat prefix (if pad (make-string (max 2 (- 8 (length prefix))) ? ) " ") title)) (message "Reformatting: %s%s%s" pre-title title post-title) (insert "\n\n" pre-title title post-title "\n\n")) (goto-char (match-beginning 5)) (or (setq section-list (cdr section-list)) (error "Too many bottom-of-fold marks")) (setq section-prefix-list (cdr section-prefix-list)) (delete-region (point) (progn (forward-line 1) (point))))) (and (cdr section-list) (error "Too many top-of-fold marks -- reached end of file prematurely")) (goto-char (point-min)) (buffer-enable-undo) (set-buffer-modified-p nil) (message "All folds reformatted."))) ;;}}} ;;}}} ;;{{{ Standard fold marks for various major modes ;;{{{ A function to set default marks, `fold-add-to-marks-list' (defun fold-add-to-marks-list (mode top bottom &optional secondary noforce message) "Add/set fold marks for a particular major mode. When called interactively, asks for a major-mode name, and for fold marks to be used in that mode. It adds the new set to `fold-mode-marks-alist', and if the mode name is the same as the current major mode for the current buffer, the marks in use are also changed. If called non-interactively, arguments are MODE, TOP, BOTTOM and SECONDARY. MODE is the symbol for the major mode for which marks are being set. TOP, BOTTOM and SECONDARY are strings, the three fold marks to be used. SECONDARY may be nil (as opposed to the empty string), but the other two must be non-empty strings, and is an optional argument. Two other optional arguments are NOFORCE, meaning do not change the marks if marks are already set for the specified mode if non-nil, and MESSAGE, which causes a message to be displayed if it is non-nil. This is also the message displayed if the function is called interactively. To set default fold marks for a particular mode, put something like the following in your .emacs: \(fold-add-to-marks-list 'major-mode \"(** {{{ \" \"(** }}} **)\" \" **)\") Look at the variable `fold-mode-marks-alist' to see what default settings already apply. `fold-set-marks' can be used to set the fold marks in use in the current buffer without affecting the default value for a particular mode." (interactive (let* ((mode (completing-read (concat "Add fold marks for major mode (" (symbol-name major-mode) "): ") obarray (function (lambda (arg) (and (commandp arg) (string-match "-mode\\'" (symbol-name arg))))) t)) (mode (if (equal mode "") major-mode (intern mode))) (object (assq mode fold-mode-marks-alist)) (old-top (and object (nth 1 object))) top (old-bottom (and object (nth 2 object))) bottom (secondary (and object (nth 3 object))) (prompt "Top fold marker: ")) (and (equal secondary "") (setq secondary nil)) (while (not top) (setq top (read-string prompt (or old-top "{{{ "))) (and (equal top "") (setq top nil))) (setq prompt (concat prompt top ", Bottom marker: ")) (while (not bottom) (setq bottom (read-string prompt (or old-bottom "}}}"))) (and (equal bottom "") (setq bottom nil))) (setq prompt (concat prompt bottom (if secondary ", Secondary marker: " ", Secondary marker (none): ")) secondary (read-string prompt secondary)) (and (equal secondary "") (setq secondary nil)) (list mode top bottom secondary nil t))) (let ((object (assq mode fold-mode-marks-alist))) (if (and object noforce message) (message "Fold markers for `%s' are already set." (symbol-name mode)) (if object (or noforce (setcdr object (if secondary (list top bottom secondary) (list top bottom)))) (setq fold-mode-marks-alist (cons (if secondary (list mode top bottom secondary) (list mode top bottom)) fold-mode-marks-alist))) (and message (message "Set fold marks for `%s' to \"%s\" and \"%s\"." (symbol-name mode) (if secondary (concat top "name" secondary) (concat top "name")) bottom) (and (eq major-mode mode) (fold-set-marks top bottom secondary)))))) ;;}}} ;;{{{ Set some useful default fold marks (fold-add-to-marks-list 'c-mode "/* {{{ " "/* }}} */" " */" t) (fold-add-to-marks-list 'emacs-lisp-mode ";;{{{ " ";;}}}" nil t) (fold-add-to-marks-list 'lisp-interaction-mode ";;{{{ " ";;}}}" nil t) (fold-add-to-marks-list 'plain-tex-mode "%{{{ " "%}}}" nil t) (fold-add-to-marks-list 'plain-TeX-mode "%{{{ " "%}}}" nil t) (fold-add-to-marks-list 'latex-mode "%{{{ " "%}}}" nil t) (fold-add-to-marks-list 'LaTeX-mode "%{{{ " "%}}}" nil t) (fold-add-to-marks-list 'orwell-mode "{{{ " "}}}" nil t) (fold-add-to-marks-list 'modula-2-mode "(* {{{ " "(* }}} *)" " *)" t) (fold-add-to-marks-list 'shellscript-mode "# {{{ " "# }}}" nil t) (fold-add-to-marks-list 'perl-mode "# {{{ " "# }}}" nil t) (fold-add-to-marks-list 'texinfo-mode "@c {{{ " "@c {{{endfold}}}" " }}}" t) (fold-add-to-marks-list 'occam-mode "-- {{{ " "-- }}}" nil t) (fold-add-to-marks-list 'lisp-mode ";;{{{ " ";;}}}" nil t) (fold-add-to-marks-list 'tex-mode "%{{{ " "%}}}" nil t) (fold-add-to-marks-list 'TeX-mode "%{{{ " "%}}}" nil t) (fold-add-to-marks-list 'c++-mode "// {{{ " "// }}}" nil t) (fold-add-to-marks-list 'bison-mode "/* {{{ " "/* }}} */" " */" t) (fold-add-to-marks-list 'Bison-mode "/* {{{ " "/* }}} */" " */" t) (fold-add-to-marks-list 'gofer-mode "-- {{{ " "-- }}}" nil t) (fold-add-to-marks-list 'ml-mode "(* {{{ " "(* }}} *)" " *)" t) (fold-add-to-marks-list 'sml-mode "(* {{{ " "(* }}} *)" " *)" t) ;;; my changes (Jari Aalto ssjaaa@uta.fi) ;;; heavy shell-perl-awk programmer need # prefix... (fold-add-to-marks-list 'fundamental-mode "# {{{ " "# }}}" nil t) (fold-add-to-marks-list 'text-mode "{{{ " "}}}" nil t) ;;}}} ;;}}} ;;{{{ Start Folding mode automatically for folded files ;;{{{ folding-mode-find-file-hook (defun folding-mode-find-file-hook () "One of the hooks called whenever a `find-file' is successful. It checks to see if `folded-file' has been set as a buffer-local variable, and automatically starts Folding mode if it has. This allows folded files to be automatically folded when opened. To make this hook effective, the symbol `folding-mode-find-file-hook' should be placed at the end of `find-file-hooks'. If you have some other hook in the list, for example a hook to automatically uncompress or decrypt a buffer, it should go earlier on in the list. See also `folding-mode-add-find-file-hook'." (and (assq 'folded-file (buffer-local-variables)) folded-file (folding-mode 1) (kill-local-variable 'folded-file))) ;;}}} ;;{{{ folding-mode-add-find-file-hook (defun folding-mode-add-find-file-hook () "Appends `folding-mode-find-file-hook' to the list `find-file-hooks'. This has the effect that afterwards, when a folded file is visited, if appropriate Emacs local variable entries are recognised at the end of the file, Folding mode is started automatically. If `inhibit-local-variables' is non-nil, this will not happen regardless of the setting of `find-file-hooks'. To declare a file to be folded, put `folded-file: t' in the file's local variables. eg., at the end of a C source file, put: /* Local variables: folded-file: t */ The local variables can be inside a fold." (interactive) (or (memq 'folding-mode-find-file-hook find-file-hooks) (setq find-file-hooks (append find-file-hooks '(folding-mode-find-file-hook))))) ;;}}} ;;}}} ;;{{{ Gross, crufty hacks that seem necessary ;; The functions here have been tested with Emacs 18.55, Emacs 18.58, ;; Epoch 4.0p2 (based on Emacs 18.58) and Lucid Emacs 19.6. ;; Note that Lucid Emacs 19.6 can't do selective-display, and its ;; "invisible extents" don't work either, so Folding mode just won't ;; work with that version. ;; They shouldn't do the wrong thing with later versions of Emacs, but ;; they might not have the special effects either. They may appear to ;; be excessive; that is not the case. All of the peculiar things these ;; functions do is done to avoid some side-effect of Emacs' internal ;; logic that I have met. Some of them work around bugs or unfortunate ;; (lack of) features in Emacs. In most cases, it would be better to ;; move this into the Emacs C code. ;; Folding mode is designed to be simple to cooperate with as many ;; things as possible. These functions go against that principle at the ;; coding level, but make life for the user bearable. ;;{{{ fold-merge-keymaps ;; Merge keymaps, because miner-mode keymaps aren't available in Emacs ;; 18. In Lucid Emacs, keymaps can have parent keymaps, so that ;; mechanism is used instead and MAP isn't copied. ;; Takes two keymaps, MAP and EXTRA. Merges each binding in EXTRA into ;; a copy of MAP, and returns the new keymap (bindings in EXTRA override ;; those in MAP). MAP or EXTRA may be nil, indicating an empty keymap. ;; If they are both nil, nil is returned. Sub-keymaps and even cons ;; cells containing bindings are not copied unnecessarily (well, ;; sometimes they are). This means that if you modify the local map ;; when Folding mode is active, the effects are unpredictable: you may ;; also affect the keymap that was active before Folding mdoe was ;; started, and you may affect folding-mode-map. (defun fold-merge-keymaps (map extra) (or map (setq map extra extra nil)) (if (null extra) (and map (copy-keymap map)) (if fold-lucid-keymaps-p (let ((new (copy-keymap extra))) (set-keymap-parent new map) new) (or (keymapp extra) (signal 'wrong-type-argument (list 'keymapp extra))) (or (keymapp map) (signal 'wrong-type-argument (list 'keymapp map))) (and (vectorp extra) (let ((key (length extra)) (oldextra extra)) (setq extra nil) (while (<= 0 (setq key (1- key))) (and (aref oldextra key) (setq extra (cons (cons key (aref oldextra key)) extra)))) (setq extra (cons 'keymap extra)))) (and (cdr extra) (let (key keycode cons-binding realdef def submap) ;; Note that this copy-sequence will copy the spine of the ;; sparse keymap, but it will not copy the cons cell used ;; for each binding. This is important; define-key does a ;; setcdr to rebind a key, if that key was bound already, ;; so define-key can't be used to change a binding. Using ;; copy-keymap instead would be excessive and slow, because ;; it would be repeatedly invoked, as this function is ;; called recursively. (setq map (copy-sequence map)) (while (setq extra (cdr extra)) (setq keycode (car (car extra)) key (char-to-string keycode) def (cdr (car extra)) realdef def) (while (and def (if (symbolp def) (setq def (symbol-function def)) (and (consp def) (integerp (cdr def)) (keymapp (car def)) (setq def (lookup-key (car def) (char-to-string (cdr def)))))))) (if (and (keymapp def) (setq submap (lookup-key map key))) (progn (while (and submap (if (symbolp submap) (setq submap (symbol-function submap)) (and (consp submap) (integerp (cdr submap)) (keymapp (car submap)) (setq submap (lookup-key (car submap) (char-to-string (cdr submap)))))))) (if (keymapp submap) (if (vectorp map) (aset map keycode (fold-merge-keymaps submap def)) (setcdr (setq map (delq (assq keycode map) map)) (cons (cons keycode (fold-merge-keymaps submap def)) (cdr map)))) (if (vectorp map) (aset map keycode realdef) (setcdr (setq map (delq (assq keycode map) map)) (cons (cons keycode realdef) (cdr map)))))) (and def (if (vectorp map) (aset map keycode realdef) (and (setq cons-binding (assq keycode map)) (setq map (delq cons-binding map))) (setcdr map (cons (cons keycode realdef) (cdr map))))))))) map))) ;;}}} ;;{{{ fold-subst-regions ;; Substitute newlines for carriage returns or vice versa. ;; Avoid excessive file locking. ;; Substitutes characters in the buffer, even in a read-only buffer. ;; Takes LIST, a list of regions specified as sequence in the form ;; (START1 END1 START2 END2 ...). In every region specified by each ;; pair, substitutes each occurence of character FIND by REPLACE. ;; The buffer-modified flag is not affected, undo information is not ;; kept for the change, and the function works on read-only files. This ;; function is much more efficient called with a long sequence than ;; called for each region in the sequence. ;; If the buffer is not modified when the function is called, the ;; modified-flag is set before performing all the substitutions, and ;; locking is temporarily disabled. This prevents Emacs from trying to ;; make then delete a lock file for *every* substitution, which slows ;; folding considerably, especially on a slow networked filesystem. ;; Without this, on my system, folding files on startup (and reading ;; other peoples' folded files) takes about five times longer. Emacs ;; still locks the file once for this call under those circumstances; I ;; can't think of a way around that, but it isn't really a problem. ;; I consider these problems to be a bug in `subst-char-in-region'. (defun fold-subst-regions (list find replace) (let ((buffer-read-only buffer-read-only) ;; Protect read-only flag. (modified (buffer-modified-p)) (ask1 (symbol-function 'ask-user-about-supersession-threat)) (ask2 (symbol-function 'ask-user-about-lock))) (unwind-protect (progn (setq buffer-read-only nil) (or modified (progn (fset 'ask-user-about-supersession-threat '(lambda (&rest x) nil)) (fset 'ask-user-about-lock '(lambda (&rest x) nil)) (set-buffer-modified-p t))) ; Prevent file locking in the loop (while list (subst-char-in-region (car list) (nth 1 list) find replace t) (setq list (cdr (cdr list))))) ;; buffer-read-only is restored by the let. ;; Don't want to change MODIFF time if it was modified before. (or modified (unwind-protect (set-buffer-modified-p nil) (fset 'ask-user-about-supersession-threat ask1) (fset 'ask-user-about-lock ask2)))))) ;;}}} ;;{{{ fold-narrow-to-region ;; Narrow to region, without surprising displays. ;; Similar to `narrow-to-region', but also adjusts window-start to be ;; the start of the narrowed region. If an optional argument CENTRE is ;; non-nil, the window-start is positioned to leave the point at the ;; centre of the window, like `recenter'. START may be nil, in which ;; case the function acts more like `widen'. ;; Actually, all the window-starts for every window displaying the ;; buffer, as well as the last_window_start for the buffer are set. The ;; points in every window are set to the point in the current buffer. ;; All this logic is necessary to prevent the display getting really ;; weird occasionally, even if there is only one window. Try making ;; this function like normal `narrow-to-region' with a touch of ;; `recenter', then moving around lots of folds in a buffer displayed in ;; several windows. You'll see what I mean. ;; last_window_start is set by making sure that the selected window is ;; displaying the current buffer, then setting the window-start, then ;; making the selected window display another buffer (which sets ;; last_window_start), then setting the selected window to redisplay the ;; buffer it displayed originally. ;; Note that whenever window-start is set, the point cannot be moved ;; outside the displayed area until after a proper redisplay. If this ;; is possible, centre the display on the point. ;; In Emacs 19; Epoch or Lucid Emacs, searches all screens for all ;; windows. In Emacs 19, they are called "frames". (defun fold-narrow-to-region (&optional start end centre) (let* ((the-window (selected-window)) (the-screen (and fold-epoch-screens-p (epoch::current-screen))) (screens (and fold-epoch-screens-p (epoch::screens-of-buffer))) (selected-buffer (window-buffer the-window)) (window-ring the-window) (window the-window) (point (point)) (buffer (current-buffer)) temp) (unwind-protect (progn (unwind-protect (progn (if start (narrow-to-region start end) (widen)) (setq point (point)) (set-window-buffer window buffer) (while (progn (and (eq buffer (window-buffer window)) (if centre (progn (select-window window) (goto-char point) (vertical-motion (- (lsh (window-height window) -1))) (set-window-start window (point)) (set-window-point window point)) (set-window-start window (or start 1)) (set-window-point window point))) (or (not (eq (setq window (if fold-emacs-frames-p (next-window window nil t) (if fold-lucid-screens-p (next-window window nil t t) (next-window window)))) window-ring)) (and (setq screens (cdr screens)) (setq window (epoch::first-window (car screens)) window-ring window)))))) (and the-screen (epoch::select-screen the-screen)) (select-window the-window)) ;; Set last_window_start. (unwind-protect (if (not (eq buffer selected-buffer)) (set-window-buffer the-window selected-buffer) (if (get-buffer "*scratch*") (set-window-buffer the-window (get-buffer "*scratch*")) (set-window-buffer the-window (setq temp (generate-new-buffer " *temp*")))) (set-window-buffer the-window buffer)) (and temp (kill-buffer temp)))) ;; Undo this side-effect of set-window-buffer. (set-buffer buffer) (goto-char (point))))) ;;}}} ;;}}} ;;{{{ Miscellaneous ;;{{{ kill-all-local-variables-hooks ;; This does not normally have any effect in Emacs. In my setup, ;; this hook is called when the major mode changes, and it gives ;; Folding mode a chance to clear up first. (and (boundp 'kill-all-local-variables-hooks) (or (memq 'fold-end-mode-quickly kill-all-local-variables-hooks) (setq kill-all-local-variables-hooks (cons 'fold-end-mode-quickly kill-all-local-variables-hooks)))) ;;}}} ;;{{{ list-buffers-mode-alist ;; Also has no effect in standard Emacs. With this variable set, ;; my setup shows "Folding" in the mode name part of the buffer list, ;; which looks nice :-). (and (boundp 'list-buffers-mode-alist) (or (assq 'folding-mode list-buffers-mode-alist) (setq list-buffers-mode-alist (cons '(folding-mode folding-mode-v-str) list-buffers-mode-alist)))) ;;}}} ;;{{{ fold-end-mode-quickly (defun fold-end-mode-quickly () "Replaces all ^M's with linefeeds and widen a folded buffer. Only has any effect if Folding mode is active. This should not in general be used for anything. It is used when changing major modes, by being placed in kill-mode-tidy-alist, to tidy the buffer slightly. It is similar to `(folding-mode 0)', except that it does not restore saved keymaps etc. Repeat: Do not use this function. Its behaviour is liable to change." (and (boundp 'folding-mode) (assq 'folding-mode (buffer-local-variables)) folding-mode (progn (widen) (fold-clear-stack) (fold-subst-regions (list 1 (point-max)) ?\r ?\n)))) ;;}}} ;;{{{ eval-current-buffer-open-folds (defun eval-current-buffer-open-folds (&optional printflag) "Evaluate all of a folded buffer as Lisp code. Unlike `eval-current-buffer', this function will evaluate all of a buffer, even if it is folded. It will also work correctly on non-folded buffers, so is a good candidate for being bound to a key if you program in Emacs-Lisp. It works by making a copy of the current buffer in another buffer, unfolding it and evaluating it. It then deletes the copy. Programs can pass argument PRINTFLAG which controls printing of output: nil means discard it; anything else is stream for print." (interactive) (if (or (and (boundp 'folding-mode-flag) folding-mode-flag) (and (boundp 'folding-mode) folding-mode)) (let ((temp-buffer (generate-new-buffer (buffer-name)))) (message "Evaluating unfolded buffer...") (save-restriction (widen) (copy-to-buffer temp-buffer 1 (point-max))) (set-buffer temp-buffer) (subst-char-in-region 1 (point-max) ?\r ?\n) (let ((real-message-def (symbol-function 'message)) (suppress-eval-message)) (fset 'message (function (lambda (&rest args) (setq suppress-eval-message t) (fset 'message real-message-def) (apply 'message args)))) (unwind-protect (eval-current-buffer printflag) (fset 'message real-message-def) (kill-buffer temp-buffer)) (or suppress-eval-message (message "Evaluating unfolded buffer... Done")))) (eval-current-buffer printflag))) ;;}}} ;;}}} ;;{{{ Emacs local variables ;; Local variables: ;; folded-file: t ;; end: ;;}}} singular-4.0.3+ds/factory/bin/gen-readcf000077500000000000000000000003541266270727000201170ustar00rootroot00000000000000#!/bin/sh BISON=$1 if test -r readcf.cc then touch readcf.cc else if test "$BISON" = where-is-your-bison then echo Error: no bison given, could not rebuilt readcf.cc exit 1 fi $BISON readcf.y -o readcf.cc fi singular-4.0.3+ds/factory/bin/makeheader000077500000000000000000000070071266270727000202140ustar00rootroot00000000000000#! /bin/sh # # makeheader.sh - generate a header file out of several header files. # # Type 'makeheader -?' for instructions on syntax/usage. # # print usage if necessary if test "$#" = 0 || test "$1" = "-?" || test "$1" = "-help"; then cat 1>&2 << \EOT usage: makeheader [-?] {-I} This is makeheader, a header file generation tool. With makeheader it is possible to generate a single header file out of several other header files. To include a header file into the generated header file (= ) use the two lines /*MAKEHEADER*/ #include "" in . If you use the alternate form /*MAKEHEADER PUBLIC ONLY*/ #include "" only sections marked with /*BEGINPUBLIC*/ and /*ENDPUBLIC*/ are pasted from into . is looked up in all s, then in the current directory, then in the base directory of . EOT exit 1 fi # get list of include directories includes="" while echo "$1" | grep '^-I' > /dev/null 2> /dev/null; do # get argument to option -I if test "$1" = "-I"; then shift includes="$includes$1:" else include=`echo "$1" | sed 's/^-I//'` includes="$includes$include:" fi shift done includes="$includes.:" # check for rest of arguments if test "$#" -lt 2; then echo "usage: makeheader [-?] {-I} " 1>&2 exit 1 fi infile="$1" outfile="makeheader.$$" final_outfile="$2" # get basename of $infile if echo "$infile" | grep '.*/' > /dev/null 2> /dev/null; then include=`echo "$infile" | sed 's/\/[^\/]*$//'` includes="$includes$include:" fi if test ! -r "$infile"; then echo "makeheader: Cannot open template file $infile for reading" 1>&2 exit 1 fi # try to create $outfile if it does not exist if test -w "$outfile" || cp /dev/null "$outfile" > /dev/null 2> /dev/null; then : else echo "makeheader: Cannot open header file $outfile for writing" 1>&2 exit 1 fi echo "/* $final_outfile automatically generated by makeheader from $infile */" > "$outfile" # scan through template while read line; do if test "$line" = '/*MAKEHEADER*/'; then readmode=1 elif test "$line" = '/*MAKEHEADER PUBLIC ONLY*/'; then readmode=2 else echo "$line" continue fi # get include file from next line read line # if echo "$line" | grep -v '^#include $' > /dev/null 2> /dev/null; then if echo "$line" | grep -v '^#include ".*"$' > /dev/null 2> /dev/null; then echo "makeheader: Invalid include statement $line" 1>&2 exit 1 fi includefile=`echo "$line" | sed 's/^#include "//; s/"$//'` # includefile=`echo "$line" | sed 's/^#include $//'` # search for includefile found=0 saveIFS="$IFS"; IFS=: for dir in $includes; do if test -r "$dir/$includefile"; then found=1 break fi done IFS="$saveIFS" if test $found = 0; then echo "makeheader: Include file $includefile not found" 1>&2 exit 1 else includefile="$dir/$includefile" fi # now paste includefile into outfile echo "/* stuff included from $includefile */" echo if test $readmode = 1; then # read whole includefile cat "$includefile" elif test $readmode = 2; then # read only public sections of includefile sed -n ' \@^/\*BEGINPUBLIC\*/$@!d \@^/\*BEGINPUBLIC\*/$@{ : loop n \@^/\*ENDPUBLIC\*/$@d p b loop }' "$includefile" fi done < "$infile" >> "$outfile" mv "$outfile" "$final_outfile" singular-4.0.3+ds/factory/canonicalform.cc000066400000000000000000001605071266270727000205570ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #include "config.h" #include "cf_assert.h" #include "cf_factory.h" #include "cf_defs.h" #include "cf_globals.h" #include "canonicalform.h" #include "cf_iter.h" #include "int_cf.h" #include "cf_algorithm.h" #include "imm.h" #include "gfops.h" #include "facMul.h" #include "FLINTconvert.h" #include #ifndef NOSTREAMIO CanonicalForm readCF( ISTREAM& ); #endif /* NOSTREAMIO */ /** constructors, destructors, selectors **/ CanonicalForm::CanonicalForm( const char * str, const int base ) : value( CFFactory::basic( str, base ) ) { } InternalCF* CanonicalForm::getval() const { if ( is_imm( value ) ) return value; else return value->copyObject(); } CanonicalForm CanonicalForm::deepCopy() const { if ( is_imm( value ) ) return *this; else return CanonicalForm( value->deepCopyObject() ); } void CanonicalForm::mpzval(mpz_t val) const { ASSERT (!is_imm (value) && value->levelcoeff() == IntegerDomain, "non-immediate integer expected"); getmpi (value, val); } /** predicates **/ #if 0 bool CanonicalForm::isImm() const { return is_imm( value ); } #endif bool CanonicalForm::inZ() const { if ( is_imm( value ) == INTMARK ) return true; else if ( is_imm( value ) ) return false; else return value->levelcoeff() == IntegerDomain; } bool CanonicalForm::inQ() const { if ( is_imm( value ) == INTMARK ) return true; else if ( is_imm( value ) ) return false; else return value->levelcoeff() == IntegerDomain || value->levelcoeff() == RationalDomain; } bool CanonicalForm::inFF() const { return is_imm( value ) == FFMARK; } bool CanonicalForm::inGF() const { return is_imm( value ) == GFMARK; } bool CanonicalForm::inBaseDomain() const { if ( is_imm( value ) ) return true; else return value->inBaseDomain(); } bool CanonicalForm::inExtension() const { if ( is_imm( value ) ) return false; else return value->inExtension(); } bool CanonicalForm::inCoeffDomain() const { if ( is_imm( value ) ) return true; else return value->inCoeffDomain(); } bool CanonicalForm::inPolyDomain() const { if ( is_imm( value ) ) return false; else return value->inPolyDomain(); } bool CanonicalForm::inQuotDomain() const { if ( is_imm( value ) ) return false; else return value->inQuotDomain(); } bool CanonicalForm::isFFinGF() const { return is_imm( value ) == GFMARK && gf_isff( imm2int( value ) ); } bool CanonicalForm::isUnivariate() const { if ( is_imm( value ) ) return false; else return value->isUnivariate(); } // is_homogeneous returns 1 iff f is homogeneous, 0 otherwise// bool CanonicalForm::isHomogeneous() const { if (this->isZero()) return true; else if (this->inCoeffDomain()) return true; else { #if 0 CFIterator i; int cdeg = -2, dummy; for ( i = *this; i.hasTerms(); i++ ) { if (!(i.coeff().isHomogeneous())) return false; if ( (dummy = totaldegree( i.coeff() ) + i.exp()) != cdeg ) { if (cdeg == -2) cdeg = dummy; else return false; } } return true; #else CFList termlist= get_Terms(*this); CFListIterator i; int deg= totaldegree(termlist.getFirst()); for ( i=termlist; i.hasItem(); i++ ) if ( totaldegree(i.getItem()) != deg ) return false; return true; #endif } } /** conversion functions **/ long CanonicalForm::intval() const { if ( is_imm( value ) ) return imm_intval( value ); else return value->intval(); } CanonicalForm CanonicalForm::mapinto () const { //ASSERT( is_imm( value ) || ! value->inExtension(), "cannot map into different Extension" ); if ( is_imm( value ) ) if ( getCharacteristic() == 0 ) if ( is_imm( value ) == FFMARK ) return CanonicalForm( int2imm( ff_symmetric( imm2int( value ) ) ) ); else if ( is_imm( value ) == GFMARK ) return CanonicalForm( int2imm( ff_symmetric( gf_gf2ff( imm2int( value ) ) ) ) ); else return *this; else if ( getGFDegree() == 1 ) return CanonicalForm( int2imm_p( ff_norm( imm2int( value ) ) ) ); else return CanonicalForm( int2imm_gf( gf_int2gf( imm2int( value ) ) ) ); else if ( value->inBaseDomain() ) if ( getCharacteristic() == 0 ) return *this; else { int val; if ( value->levelcoeff() == IntegerDomain ) val = value->intmod( ff_prime ); else if ( value->levelcoeff() == RationalDomain ) return num().mapinto() / den().mapinto(); else { ASSERT( 0, "illegal domain" ); return 0; } if ( getGFDegree() > 1 ) return CanonicalForm( int2imm_gf( gf_int2gf( val ) ) ); else return CanonicalForm( int2imm_p( val ) ); } else { Variable x = value->variable(); CanonicalForm result; for ( CFIterator i = *this; i.hasTerms(); i++ ) result += (power( x, i.exp() ) * i.coeff().mapinto()); return result; } } /** CanonicalForm CanonicalForm::lc (), Lc (), LC (), LC ( v ) const * * lc(), Lc(), LC() - leading coefficient functions. * * All methods return CO if CO is in a base domain. * * lc() returns the leading coefficient of CO with respect to * lexicographic ordering. Elements in an algebraic extension * are considered polynomials so lc() always returns a leading * coefficient in a base domain. This method is useful to get * the base domain over which CO is defined. * * Lc() returns the leading coefficient of CO with respect to * lexicographic ordering. In contrast to lc() elements in an * algebraic extension are considered coefficients so Lc() always * returns a leading coefficient in a coefficient domain. * * LC() returns the leading coefficient of CO where CO is * considered a univariate polynomial in its main variable. An * element of an algebraic extension is considered an univariate * polynomial, too. * * LC( v ) returns the leading coefficient of CO where CO is * considered an univariate polynomial in the polynomial variable * v. * Note: If v is less than the main variable of CO we have to * swap variables which may be quite expensive. * * Examples: * > Let x < y be polynomial variables, a an algebraic variable. * * > (3*a*x*y^2+y+x).lc() = 3 * * > (3*a*x*y^2+y+x).Lc() = 3*a * * > (3*a*x*y^2+y+x).LC() = 3*a*x * * > (3*a*x*y^2+y+x).LC( x ) = 3*a*y^2+1 * * * > (3*a^2+4*a).lc() = 3 * * > (3*a^2+4*a).Lc() = 3*a^2+4*a * * > (3*a^2+4*a).LC() = 3 * * > (3*a^2+4*a).LC( x ) = 3*a^2+4*a * * @sa InternalCF::lc(), InternalCF::Lc(), InternalCF::LC(), * InternalPoly::lc(), InternalPoly::Lc(), InternalPoly::LC(), * ::lc(), ::Lc(), ::LC(), ::LC( v ) * **/ CanonicalForm CanonicalForm::lc () const { if ( is_imm( value ) ) return *this; else return value->lc(); } /** * @sa CanonicalForm::lc(), CanonicalForm::LC(), InternalCF::lc(), * InternalCF::Lc(), InternalCF::LC(), * InternalPoly::lc(), InternalPoly::Lc(), InternalPoly::LC(), * ::lc(), ::Lc(), ::LC(), ::LC( v ) **/ CanonicalForm CanonicalForm::Lc () const { if ( is_imm( value ) || value->inCoeffDomain() ) return *this; else return value->Lc(); } /** * @sa CanonicalForm::lc(), CanonicalForm::Lc(), InternalCF::lc(), * InternalCF::Lc(), InternalCF::LC(), * InternalPoly::lc(), InternalPoly::Lc(), InternalPoly::LC(), * ::lc(), ::Lc(), ::LC(), ::LC( v ) **/ CanonicalForm CanonicalForm::LC () const { if ( is_imm( value ) ) return *this; else return value->LC(); } /** * @sa CanonicalForm::lc(), CanonicalForm::Lc(), InternalCF::lc(), * InternalCF::Lc(), InternalCF::LC(), * InternalPoly::lc(), InternalPoly::Lc(), InternalPoly::LC(), * ::lc(), ::Lc(), ::LC(), ::LC( v ) **/ CanonicalForm CanonicalForm::LC ( const Variable & v ) const { if ( is_imm( value ) || value->inCoeffDomain() ) return *this; Variable x = value->variable(); if ( v > x ) return *this; else if ( v == x ) return value->LC(); else { CanonicalForm f = swapvar( *this, v, x ); if ( f.mvar() == x ) return swapvar( f.value->LC(), v, x ); else // v did not occur in f return *this; } } /** * Returns -1 for the zero polynomial and 0 if * CO is in a base domain. * * degree() returns the degree of CO in its main variable. * Elements in an algebraic extension are considered polynomials. * * @sa InternalCF::degree(), InternalPoly::degree(), * ::degree(), ::degree( v ) * **/ int CanonicalForm::degree() const { int what = is_imm( value ); if ( what ) if ( what == FFMARK ) return imm_iszero_p( value ) ? -1 : 0; else if ( what == INTMARK ) return imm_iszero( value ) ? -1 : 0; else return imm_iszero_gf( value ) ? -1 : 0; else return value->degree(); } /** * returns -1 for the zero polynomial and 0 if * CO is in a base domain. * * degree( v ) returns the degree of CO with respect to v. * Elements in an algebraic extension are considered polynomials, * and v may be algebraic. * * @sa InternalCF::degree(), InternalPoly::degree(), * ::degree(), ::degree( v ) **/ int CanonicalForm::degree( const Variable & v ) const { int what = is_imm( value ); #if 0 if ( what ) if ( what == FFMARK ) return imm_iszero_p( value ) ? -1 : 0; else if ( what == INTMARK ) return imm_iszero( value ) ? -1 : 0; else return imm_iszero_gf( value ) ? -1 : 0; else if ( value->inBaseDomain() ) return value->degree(); #else switch(what) { case FFMARK: return imm_iszero_p( value ) ? -1 : 0; case INTMARK: return imm_iszero( value ) ? -1 : 0; case GFMARK: return imm_iszero_gf( value ) ? -1 : 0; case 0: if ( value->inBaseDomain() ) return value->degree(); break; } #endif Variable x = value->variable(); if ( v == x ) return value->degree(); else if ( v > x ) // relatively to v, f is in a coefficient ring return 0; else { int coeffdeg, result = 0; // search for maximum of coefficient degree for ( CFIterator i = *this; i.hasTerms(); i++ ) { coeffdeg = i.coeff().degree( v ); if ( coeffdeg > result ) result = coeffdeg; } return result; } } /** * * tailcoeff() - return least coefficient * * tailcoeff() returns the coefficient of the term with the least * degree in CO where CO is considered an univariate polynomial * in its main variable. Elements in an algebraic extension are * considered coefficients. * * @sa CanonicalForm::taildegree(), InternalCF::tailcoeff(), InternalCF::tailcoeff(), * InternalPoly::tailcoeff(), InternalPoly::taildegree, * ::tailcoeff(), ::taildegree() * **/ CanonicalForm CanonicalForm::tailcoeff () const { if ( is_imm( value ) || value->inCoeffDomain() ) return *this; else return value->tailcoeff(); } /** * tailcoeff( v ) returns the tail coefficient of CO where CO is * considered an univariate polynomial in the polynomial variable * v. * Note: If v is less than the main variable of CO we have to * swap variables which may be quite expensive. * * @sa CanonicalForm::taildegree(), InternalCF::tailcoeff(), InternalCF::tailcoeff(), * InternalPoly::tailcoeff(), InternalPoly::taildegree, * ::tailcoeff(), ::taildegree() **/ CanonicalForm CanonicalForm::tailcoeff (const Variable& v) const { if ( is_imm( value ) || value->inCoeffDomain() ) return *this; Variable x = value->variable(); if ( v > x ) return *this; else if ( v == x ) return value->tailcoeff(); else { CanonicalForm f = swapvar( *this, v, x ); if ( f.mvar() == x ) return swapvar( f.value->tailcoeff(), v, x ); else // v did not occur in f return *this; } } /** * taildegree() returns -1 for the zero polynomial, 0 if CO is in * a base domain, otherwise the least degree of CO where CO is * considered a univariate polynomial in its main variable. In * contrast to tailcoeff(), elements in an algebraic extension * are considered polynomials, not coefficients, and such may * have a taildegree larger than zero. * * @sa CanonicalForm::tailcoeff(), InternalCF::tailcoeff(), InternalCF::tailcoeff(), * InternalPoly::tailcoeff(), InternalPoly::taildegree, * ::tailcoeff(), ::taildegree() **/ int CanonicalForm::taildegree () const { int what = is_imm( value ); if ( what ) if ( what == FFMARK ) return imm_iszero_p( value ) ? -1 : 0; else if ( what == INTMARK ) return imm_iszero( value ) ? -1 : 0; else return imm_iszero_gf( value ) ? -1 : 0; else return value->taildegree(); } /** * level() returns the level of CO. For a list of the levels and * their meanings, see cf_defs.h. * * @sa InternalCF::level(), InternalCF::variable(), * InternalPoly::level(), InternalPoly::variable(), ::level(), * ::mvar() * **/ int CanonicalForm::level () const { if ( is_imm( value ) ) return LEVELBASE; else return value->level(); } /** * mvar() returns the main variable of CO or Variable() if CO is * in a base domain. * * @sa InternalCF::level(), InternalCF::variable(), * InternalPoly::level(), InternalPoly::variable(), ::level(), * ::mvar() **/ Variable CanonicalForm::mvar () const { if ( is_imm( value ) ) return Variable(); else return value->variable(); } /** * num() returns the numerator of CO if CO is a rational number, * CO itself otherwise. * * @sa InternalCF::num(), InternalCF::den(), * InternalRational::num(), InternalRational::den(), ::num(), * ::den() * **/ CanonicalForm CanonicalForm::num () const { if ( is_imm( value ) ) return *this; else return CanonicalForm( value->num() ); } /** * den() returns the denominator of CO if CO is a rational * number, 1 (from the current domain!) otherwise. * * @sa InternalCF::num(), InternalCF::den(), * InternalRational::num(), InternalRational::den(), ::num(), * ::den() **/ CanonicalForm CanonicalForm::den () const { if ( is_imm( value ) ) return CanonicalForm( 1 ); else return CanonicalForm( value->den() ); } /** assignment operators **/ CanonicalForm & CanonicalForm::operator += ( const CanonicalForm & cf ) { int what = is_imm( value ); if ( what ) { ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" ); if ( (what = is_imm( cf.value )) == FFMARK ) value = imm_add_p( value, cf.value ); else if ( what == GFMARK ) value = imm_add_gf( value, cf.value ); else if ( what ) value = imm_add( value, cf.value ); else { InternalCF * dummy = cf.value->copyObject(); value = dummy->addcoeff( value ); } } else if ( is_imm( cf.value ) ) value = value->addcoeff( cf.value ); else if ( value->level() == cf.value->level() ) { if ( value->levelcoeff() == cf.value->levelcoeff() ) value = value->addsame( cf.value ); else if ( value->levelcoeff() > cf.value->levelcoeff() ) value = value->addcoeff( cf.value ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->addcoeff( value ); if ( value->deleteObject() ) delete value; value = dummy; } } else if ( level() > cf.level() ) value = value->addcoeff( cf.value ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->addcoeff( value ); if ( value->deleteObject() ) delete value; value = dummy; } return *this; } CanonicalForm & CanonicalForm::operator -= ( const CanonicalForm & cf ) { int what = is_imm( value ); if ( what ) { ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" ); if ( (what = is_imm( cf.value )) == FFMARK ) value = imm_sub_p( value, cf.value ); else if ( what == GFMARK ) value = imm_sub_gf( value, cf.value ); else if ( what ) value = imm_sub( value, cf.value ); else { InternalCF * dummy = cf.value->copyObject(); value = dummy->subcoeff( value, true ); } } else if ( is_imm( cf.value ) ) value = value->subcoeff( cf.value, false ); else if ( value->level() == cf.value->level() ) { if ( value->levelcoeff() == cf.value->levelcoeff() ) value = value->subsame( cf.value ); else if ( value->levelcoeff() > cf.value->levelcoeff() ) value = value->subcoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->subcoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } } else if ( level() > cf.level() ) value = value->subcoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->subcoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } return *this; } CanonicalForm & CanonicalForm::operator *= ( const CanonicalForm & cf ) { int what = is_imm( value ); if ( what ) { ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" ); if ( (what = is_imm( cf.value )) == FFMARK ) value = imm_mul_p( value, cf.value ); else if ( what == GFMARK ) value = imm_mul_gf( value, cf.value ); else if ( what ) value = imm_mul( value, cf.value ); else { InternalCF * dummy = cf.value->copyObject(); value = dummy->mulcoeff( value ); } } else if ( is_imm( cf.value ) ) value = value->mulcoeff( cf.value ); else if ( value->level() == cf.value->level() ) { #if (HAVE_NTL && HAVE_FLINT && __FLINT_RELEASE >= 20400) if (value->levelcoeff() == cf.value->levelcoeff() && cf.isUnivariate() && (*this).isUnivariate()) { if (value->level() < 0 || CFFactory::gettype() == GaloisFieldDomain || (size (cf) <= 10 || size (*this) <= 10) ) value = value->mulsame( cf.value ); else *this= mulNTL (*this, cf); } else if (value->levelcoeff() == cf.value->levelcoeff() && (!cf.isUnivariate() || !(*this).isUnivariate())) value = value->mulsame( cf.value ); #else if ( value->levelcoeff() == cf.value->levelcoeff() ) value = value->mulsame( cf.value ); #endif else if ( value->levelcoeff() > cf.value->levelcoeff() ) value = value->mulcoeff( cf.value ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->mulcoeff( value ); if ( value->deleteObject() ) delete value; value = dummy; } } else if ( level() > cf.level() ) value = value->mulcoeff( cf.value ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->mulcoeff( value ); if ( value->deleteObject() ) delete value; value = dummy; } return *this; } CanonicalForm & CanonicalForm::operator /= ( const CanonicalForm & cf ) { int what = is_imm( value ); if ( what ) { ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" ); if ( (what = is_imm( cf.value )) == FFMARK ) value = imm_div_p( value, cf.value ); else if ( what == GFMARK ) value = imm_div_gf( value, cf.value ); else if ( what ) value = imm_divrat( value, cf.value ); else { InternalCF * dummy = cf.value->copyObject(); value = dummy->dividecoeff( value, true ); } } else if ( is_imm( cf.value ) ) value = value->dividecoeff( cf.value, false ); else if ( value->level() == cf.value->level() ) { #if (HAVE_NTL && HAVE_FLINT && __FLINT_RELEASE >= 20400) if ( value->levelcoeff() == cf.value->levelcoeff() && (*this).isUnivariate() && cf.isUnivariate()) { if (value->level() < 0 || CFFactory::gettype() == GaloisFieldDomain) value = value->dividesame( cf.value ); else *this= divNTL (*this, cf); } else if (value->levelcoeff() == cf.value->levelcoeff() && (!cf.isUnivariate() || !(*this).isUnivariate())) value = value->dividesame( cf.value ); #else if (value->levelcoeff() == cf.value->levelcoeff() ) value = value->dividesame( cf.value ); #endif else if ( value->levelcoeff() > cf.value->levelcoeff() ) value = value->dividecoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->dividecoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } } else if ( level() > cf.level() ) value = value->dividecoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->dividecoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } return *this; } CanonicalForm & CanonicalForm::div ( const CanonicalForm & cf ) { int what = is_imm( value ); if ( what ) { ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" ); if ( (what = is_imm( cf.value )) == FFMARK ) value = imm_div_p( value, cf.value ); else if ( what == GFMARK ) value = imm_div_gf( value, cf.value ); else if ( what ) value = imm_div( value, cf.value ); else { InternalCF * dummy = cf.value->copyObject(); value = dummy->divcoeff( value, true ); } } else if ( is_imm( cf.value ) ) value = value->divcoeff( cf.value, false ); else if ( value->level() == cf.value->level() ) { if ( value->levelcoeff() == cf.value->levelcoeff() ) value = value->divsame( cf.value ); else if ( value->levelcoeff() > cf.value->levelcoeff() ) value = value->divcoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->divcoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } } else if ( level() > cf.level() ) value = value->divcoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->divcoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } return *this; } ///same as divremt but handles zero divisors in case we are in Z_p[x]/(f) where f is not irreducible CanonicalForm & CanonicalForm::tryDiv ( const CanonicalForm & cf, const CanonicalForm& M, bool& fail ) { ASSERT (getCharacteristic() > 0, "expected positive characteristic"); ASSERT (!getReduce (M.mvar()), "do not reduce modulo M"); fail= false; int what = is_imm( value ); if ( what ) { ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" ); if ( (what = is_imm( cf.value )) == FFMARK ) value = imm_div_p( value, cf.value ); else if ( what == GFMARK ) value = imm_div_gf( value, cf.value ); else { InternalCF * dummy = cf.value->copyObject(); value = dummy->divcoeff( value, true ); } } else if ( is_imm( cf.value ) ) value = value->tryDivcoeff (cf.value, false, M, fail); else if ( value->level() == cf.value->level() ) { if ( value->levelcoeff() == cf.value->levelcoeff() ) value = value->tryDivsame( cf.value, M, fail ); else if ( value->levelcoeff() > cf.value->levelcoeff() ) value = value->tryDivcoeff( cf.value, false, M, fail ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->tryDivcoeff( value, true, M, fail ); if ( value->deleteObject() ) delete value; value = dummy; } } else if ( level() > cf.level() ) value = value->tryDivcoeff( cf.value, false, M, fail ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->tryDivcoeff( value, true, M, fail ); if ( value->deleteObject() ) delete value; value = dummy; } return *this; } CanonicalForm & CanonicalForm::operator %= ( const CanonicalForm & cf ) { int what = is_imm( value ); if ( what ) { ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" ); if ( (what = is_imm( cf.value )) == FFMARK ) value = imm_mod_p( value, cf.value ); else if ( what == GFMARK ) value = imm_mod_gf( value, cf.value ); else if ( what ) value = imm_mod( value, cf.value ); else { InternalCF * dummy = cf.value->copyObject(); value = dummy->modulocoeff( value, true ); } } else if ( is_imm( cf.value ) ) value = value->modulocoeff( cf.value, false ); else if ( value->level() == cf.value->level() ) { if ( value->levelcoeff() == cf.value->levelcoeff() ) value = value->modulosame( cf.value ); else if ( value->levelcoeff() > cf.value->levelcoeff() ) value = value->modulocoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->modulocoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } } else if ( level() > cf.level() ) value = value->modulocoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->modulocoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } return *this; } CanonicalForm & CanonicalForm::mod ( const CanonicalForm & cf ) { int what = is_imm( value ); if ( what ) { ASSERT ( ! is_imm( cf.value ) || (what==is_imm( cf.value )), "illegal base coefficients" ); if ( (what = is_imm( cf.value )) == FFMARK ) value = imm_mod_p( value, cf.value ); else if ( what == GFMARK ) value = imm_mod_gf( value, cf.value ); else if ( what ) value = imm_mod( value, cf.value ); else { InternalCF * dummy = cf.value->copyObject(); value = dummy->modcoeff( value, true ); } } else if ( is_imm( cf.value ) ) value = value->modcoeff( cf.value, false ); else if ( value->level() == cf.value->level() ) { if ( value->levelcoeff() == cf.value->levelcoeff() ) value = value->modsame( cf.value ); else if ( value->levelcoeff() > cf.value->levelcoeff() ) value = value->modcoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->modcoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } } else if ( level() > cf.level() ) value = value->modcoeff( cf.value, false ); else { InternalCF * dummy = cf.value->copyObject(); dummy = dummy->modcoeff( value, true ); if ( value->deleteObject() ) delete value; value = dummy; } return *this; } void divrem ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r ) { InternalCF * qq = 0, * rr = 0; int what = is_imm( f.value ); if ( what ) if ( is_imm( g.value ) ) { if ( what == FFMARK ) imm_divrem_p( f.value, g.value, qq, rr ); else if ( what == GFMARK ) imm_divrem_gf( f.value, g.value, qq, rr ); else imm_divrem( f.value, g.value, qq, rr ); } else g.value->divremcoeff( f.value, qq, rr, true ); else if ( (what=is_imm( g.value )) ) f.value->divremcoeff( g.value, qq, rr, false ); else if ( f.value->level() == g.value->level() ) if ( f.value->levelcoeff() == g.value->levelcoeff() ) f.value->divremsame( g.value, qq, rr ); else if ( f.value->levelcoeff() > g.value->levelcoeff() ) f.value->divremcoeff( g.value, qq, rr, false ); else g.value->divremcoeff( f.value, qq, rr, true ); else if ( f.value->level() > g.value->level() ) f.value->divremcoeff( g.value, qq, rr, false ); else g.value->divremcoeff( f.value, qq, rr, true ); ASSERT( qq != 0 && rr != 0, "error in divrem" ); q = CanonicalForm( qq ); r = CanonicalForm( rr ); } bool divremt ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r ) { InternalCF * qq = 0, * rr = 0; int what = is_imm( f.value ); bool result = true; if ( what ) if ( is_imm( g.value ) ) { if ( what == FFMARK ) imm_divrem_p( f.value, g.value, qq, rr ); else if ( what == GFMARK ) imm_divrem_gf( f.value, g.value, qq, rr ); else imm_divrem( f.value, g.value, qq, rr ); } else result = g.value->divremcoefft( f.value, qq, rr, true ); else if ( (what=is_imm( g.value )) ) result = f.value->divremcoefft( g.value, qq, rr, false ); else if ( f.value->level() == g.value->level() ) if ( f.value->levelcoeff() == g.value->levelcoeff() ) result = f.value->divremsamet( g.value, qq, rr ); else if ( f.value->levelcoeff() > g.value->levelcoeff() ) result = f.value->divremcoefft( g.value, qq, rr, false ); else result = g.value->divremcoefft( f.value, qq, rr, true ); else if ( f.value->level() > g.value->level() ) result = f.value->divremcoefft( g.value, qq, rr, false ); else result = g.value->divremcoefft( f.value, qq, rr, true ); if ( result ) { ASSERT( qq != 0 && rr != 0, "error in divrem" ); q = CanonicalForm( qq ); r = CanonicalForm( rr ); } else { q = 0; r = 0; } return result; } ///same as divremt but handles zero divisors in case we are in Z_p[x]/(f) where f is not irreducible bool tryDivremt ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r, const CanonicalForm& M, bool& fail ) { ASSERT (getCharacteristic() > 0, "expected positive characteristic"); ASSERT (!getReduce (M.mvar()), "do not reduce modulo M"); fail= false; InternalCF * qq = 0, * rr = 0; int what = is_imm( f.value ); bool result = true; if ( what ) if ( is_imm( g.value ) ) { if ( what == FFMARK ) imm_divrem_p( f.value, g.value, qq, rr ); else if ( what == GFMARK ) imm_divrem_gf( f.value, g.value, qq, rr ); } else result = g.value->tryDivremcoefft( f.value, qq, rr, true, M, fail ); else if ( (what=is_imm( g.value )) ) result = f.value->tryDivremcoefft( g.value, qq, rr, false, M, fail ); else if ( f.value->level() == g.value->level() ) if ( f.value->levelcoeff() == g.value->levelcoeff() ) result = f.value->tryDivremsamet( g.value, qq, rr, M, fail ); else if ( f.value->levelcoeff() > g.value->levelcoeff() ) result = f.value->tryDivremcoefft( g.value, qq, rr, false, M, fail ); else result = g.value->tryDivremcoefft( f.value, qq, rr, true, M, fail ); else if ( f.value->level() > g.value->level() ) result = f.value->tryDivremcoefft( g.value, qq, rr, false, M, fail ); else result = g.value->tryDivremcoefft( f.value, qq, rr, true, M, fail ); if (fail) { q= 0; r= 0; return false; } if ( result ) { ASSERT( qq != 0 && rr != 0, "error in divrem" ); q = CanonicalForm( qq ); r = CanonicalForm( rr ); q= reduce (q, M); r= reduce (r, M); } else { q = 0; r = 0; } return result; } /** * * operator ()() - evaluation operator. * * Returns CO if CO is in a base domain. * * operator () ( f ) returns CO with f inserted for the main * variable. Elements in an algebraic extension are considered * polynomials. * **/ CanonicalForm CanonicalForm::operator () ( const CanonicalForm & f ) const { if ( is_imm( value ) || value->inBaseDomain() ) return *this; else { #if 0 CFIterator i = *this; int lastExp = i.exp(); CanonicalForm result = i.coeff(); i++; while ( i.hasTerms() ) { if ( (lastExp - i.exp()) == 1 ) result *= f; else result *= power( f, lastExp - i.exp() ); result += i.coeff(); lastExp = i.exp(); i++; } if ( lastExp != 0 ) result *= power( f, lastExp ); #else CFIterator i = *this; int lastExp = i.exp(); CanonicalForm result = i.coeff(); i++; while ( i.hasTerms() ) { int i_exp=i.exp(); if ( (lastExp - i_exp /* i.exp()*/) == 1 ) result *= f; else result *= power( f, lastExp - i_exp /*i.exp()*/ ); result += i.coeff(); lastExp = i_exp /*i.exp()*/; i++; } if ( lastExp != 0 ) result *= power( f, lastExp ); #endif return result; } } /** * Returns CO if CO is in a base domain. * * operator () ( f, v ) returns CO with f inserted for v. * Elements in an algebraic extension are considered polynomials * and v may be an algebraic variable. **/ CanonicalForm CanonicalForm::operator () ( const CanonicalForm & f, const Variable & v ) const { if ( is_imm( value ) || value->inBaseDomain() ) return *this; Variable x = value->variable(); if ( v > x ) return *this; else if ( v == x ) return (*this)( f ); else { // v is less than main variable of f CanonicalForm result = 0; for ( CFIterator i = *this; i.hasTerms(); i++ ) result += i.coeff()( f, v ) * power( x, i.exp() ); return result; } } /** * * operator []() - return i'th coefficient from CO. * * Returns CO if CO is in a base domain and i equals zero. * Returns zero (from the current domain) if CO is in a base * domain and i is larger than zero. Otherwise, returns the * coefficient to x^i in CO (if x denotes the main variable of * CO) or zero if CO does not contain x^i. Elements in an * algebraic extension are considered polynomials. i should be * larger or equal zero. * * Note: Never use a loop like * ~~~~~~~~~~~~~~~~~~~~~{.c} for ( int i = degree( f ); i >= 0; i-- ) foo( i, f[ i ] ); ~~~~~~~~~~~~~~~~~~~~~ * * which is much slower than * ~~~~~~~~~~~~~~~~~~~~~{.c} * for ( int i = degree( f ), CFIterator I = f; I.hasTerms(); I++ ) { * // fill gap with zeroes * for ( ; i > I.exp(); i-- ) * foo( i, 0 ); * // at this point, i == I.exp() * foo( i, i.coeff() ); * i--; * } * // work through trailing zeroes * for ( ; i >= 0; i-- ) * foo( i, 0 ); ~~~~~~~~~~~~~~~~~~~~~ * **/ CanonicalForm CanonicalForm::operator [] ( int i ) const { ASSERT( i >= 0, "index to operator [] less than zero" ); if ( is_imm( value ) ) if ( i == 0 ) return *this; else return CanonicalForm( 0 ); else return value->coeff( i ); } /** * * deriv() - return the formal derivation of CO. * * deriv() derives CO with respect to its main variable. Returns * zero from the current domain if f is in a coefficient domain. * * @sa CanonicalForm::deriv ( const Variable & x ) * **/ CanonicalForm CanonicalForm::deriv () const { if ( is_imm( value ) || value->inCoeffDomain() ) return CanonicalForm( 0 ); else { CanonicalForm result = 0; Variable x = value->variable(); for ( CFIterator i = *this; i.hasTerms(); i++ ) if ( i.exp() > 0 ) result += power( x, i.exp()-1 ) * i.coeff() * i.exp(); return result; } } /** * deriv( x ) derives CO with respect to x. x should be a * polynomial variable. Returns zero from the current domain if * f is in a coefficient domain. **/ CanonicalForm CanonicalForm::deriv ( const Variable & x ) const { ASSERT( x.level() > 0, "cannot derive with respect to algebraic variables" ); if ( is_imm( value ) || value->inCoeffDomain() ) return CanonicalForm( 0 ); Variable y = value->variable(); if ( x > y ) return CanonicalForm( 0 ); else if ( x == y ) return deriv(); else { CanonicalForm result = 0; for ( CFIterator i = *this; i.hasTerms(); i++ ) result += i.coeff().deriv( x ) * power( y, i.exp() ); return result; } } /** int CanonicalForm::sign () const * * sign() - return sign of CO. * * If CO is an integer or a rational number, the sign is defined * as usual. If CO is an element of a prime power domain or of * FF(p) and SW_SYMMETRIC_FF is on, the sign of CO is the sign of * the symmetric representation of CO. If CO is in GF(q) or in * FF(p) and SW_SYMMETRIC_FF is off, the sign of CO is zero iff * CO is zero, otherwise the sign is one. * * If CO is a polynomial or in an extension of one of the base * domains, the sign of CO is the sign of its leading * coefficient. * * @sa InternalCF::sign(), InternalInteger::sign(), * InternalRational::sign(), * InternalPoly::sign(), imm_sign(), gf_sign() * **/ int CanonicalForm::sign () const { if ( is_imm( value ) ) return imm_sign( value ); else return value->sign(); } /** CanonicalForm CanonicalForm::sqrt () const * * sqrt() - calculate integer square root. * * CO has to be an integer greater or equal zero. Returns the * largest integer less or equal sqrt(CO). * * In the immediate case, we use the newton method to find the * root. The algorithm is from H. Cohen - 'A Course in * Computational Algebraic Number Theory', ch. 1.7.1. * * @sa InternalCF::sqrt(), InternalInteger::sqrt(), ::sqrt() * **/ CanonicalForm CanonicalForm::sqrt () const { if ( is_imm( value ) ) { ASSERT( is_imm( value ) == INTMARK, "sqrt() not implemented" ); long n = imm2int( value ); ASSERT( n >= 0, "arg to sqrt() less than zero" ); if ( n == 0 || n == 1 ) return CanonicalForm( n ); else { long x, y = n; do { x = y; // the intermediate result may not fit into an // integer, but the result does y = (unsigned long)(x + n/x)/2; } while ( y < x ); return CanonicalForm( x ); } } else return CanonicalForm( value->sqrt() ); } /** int CanonicalForm::ilog2 () const * * ilog2() - integer logarithm to base 2. * * Returns the largest integer less or equal logarithm of CO to * base 2. CO should be a positive integer. * * @sa InternalCF::ilog2(), InternalInteger::ilog2(), ::ilog2() * **/ int CanonicalForm::ilog2 () const { if ( is_imm( value ) ) { ASSERT( is_imm( value ) == INTMARK, "ilog2() not implemented" ); long a = imm2int( value ); ASSERT( a > 0, "arg to ilog2() less or equal zero" ); int n = -1; while ( a > 0 ) { n++; a /=2; } return n; } else return value->ilog2(); } /** * * operator ==() - compare canonical forms on * (in)equality. * * operator ==() returns true iff lhs equals rhs. * * This is the point in factory where we essentially use that * CanonicalForms in fact are canonical. There must not be two * different representations of the same mathematical object, * otherwise, such (in)equality will not be recognized by these * operators. In other word, we rely on the fact that structural * different factory objects in any case represent different * mathematical objects. * * So we use the following procedure to test on equality (and * analogously on inequality). First, we check whether lhs.value * equals rhs.value. If so we are ready and return true. * Second, if one of the operands is immediate, but the other one * not, we return false. Third, if the operand's levels differ * we return false. Fourth, if the operand's levelcoeffs differ * we return false. At last, we call the corresponding internal * method to compare both operands. * * Both operands should have coefficients from the same base domain. * * Note: To compare with the zero or the unit of the current domain, * you better use the methods `CanonicalForm::isZero()' or * `CanonicalForm::isOne()', resp., than something like `f == 0', * since the latter is quite a lot slower. * * @sa CanonicalForm::operator !=(), InternalCF::comparesame(), * InternalInteger::comparesame(), InternalRational::comparesame(), * InternalPoly::comparesame() * **/ bool operator == ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { if ( lhs.value == rhs.value ) return true; else if ( is_imm( rhs.value ) || is_imm( lhs.value ) ) { ASSERT( ! is_imm( rhs.value ) || ! is_imm( lhs.value ) || is_imm( rhs.value ) == is_imm( lhs.value ), "incompatible operands" ); return false; } else if ( lhs.value->level() != rhs.value->level() ) return false; else if ( lhs.value->levelcoeff() != rhs.value->levelcoeff() ) return false; else return rhs.value->comparesame( lhs.value ) == 0; } /** * operator !=() returns true iff lhs does not equal rhs. * * @sa CanonicalForm::operator ==() **/ bool operator != ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { if ( lhs.value == rhs.value ) return false; else if ( is_imm( rhs.value ) || is_imm( lhs.value ) ) { ASSERT( ! is_imm( rhs.value ) || ! is_imm( lhs.value ) || is_imm( rhs.value ) == is_imm( lhs.value ), "incompatible operands" ); return true; } else if ( lhs.value->level() != rhs.value->level() ) return true; else if ( lhs.value->levelcoeff() != rhs.value->levelcoeff() ) return true; else return rhs.value->comparesame( lhs.value ) != 0; } /** * * operator >() - compare canonical forms. on size or * level. * * The most common and most useful application of these operators * is to compare two integers or rationals, of course. However, * these operators are defined on all other base domains and on * polynomials, too. From a mathematical point of view this may * seem meaningless, since there is no ordering on finite fields * or on polynomials respecting the algebraic structure. * Nevertheless, from a programmer's point of view it may be * sensible to order these objects, e.g. to sort them. * * Therefore, the ordering defined by these operators in any case * is a total ordering which fulfills the law of trichotomy. * * It is clear how this is done in the case of the integers and * the rationals. For finite fields, all you can say is that * zero is the minimal element w.r.t. the ordering, the other * elements are ordered in an arbitrary (but total!) way. For * polynomials, you have an ordering derived from the * lexicographical ordering of monomials. E.g. if lm(f) < lm(g) * w.r.t. lexicographic ordering, then f < g. For more details, * refer to the documentation of `InternalPoly::operator <()'. * * Both operands should have coefficients from the same base domain. * * The scheme how both operators are implemented is allmost the * same as for the assignment operators (check for immediates, * then check levels, then check levelcoeffs, then call the * appropriate internal comparesame()/comparecoeff() method). * For more information, confer to the overview for the * arithmetic operators. * * @sa CanonicalForm::operator <(), InternalCF::comparesame(), * InternalInteger::comparesame(), InternalRational::comparesame(), * InternalPoly::comparesame(), * InternalCF::comparecoeff(), InternalInteger::comparecoeff(), * InternalRational::comparecoeff(), * InternalPoly::comparecoeff(), * imm_cmp(), imm_cmp_p(), imm_cmp_gf() * **/ bool operator > ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { int what = is_imm( rhs.value ); if ( is_imm( lhs.value ) ) { ASSERT( ! what || (what == is_imm( lhs.value )), "incompatible operands" ); if ( what == 0 ) return rhs.value->comparecoeff( lhs.value ) < 0; else if ( what == INTMARK ) return imm_cmp( lhs.value, rhs.value ) > 0; else if ( what == FFMARK ) return imm_cmp_p( lhs.value, rhs.value ) > 0; else return imm_cmp_gf( lhs.value, rhs.value ) > 0; } else if ( what ) return lhs.value->comparecoeff( rhs.value ) > 0; else if ( lhs.value->level() == rhs.value->level() ) if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() ) return lhs.value->comparesame( rhs.value ) > 0; else if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() ) return lhs.value->comparecoeff( rhs.value ) > 0; else return rhs.value->comparecoeff( lhs.value ) < 0; else return lhs.value->level() > rhs.value->level(); } /** * @sa CanonicalForm::operator >() **/ bool operator < ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { int what = is_imm( rhs.value ); if ( is_imm( lhs.value ) ) { ASSERT( ! what || (what == is_imm( lhs.value )), "incompatible operands" ); if ( what == 0 ) return rhs.value->comparecoeff( lhs.value ) > 0; else if ( what == INTMARK ) return imm_cmp( lhs.value, rhs.value ) < 0; else if ( what == FFMARK ) return imm_cmp_p( lhs.value, rhs.value ) < 0; else return imm_cmp_gf( lhs.value, rhs.value ) < 0; } else if ( what ) return lhs.value->comparecoeff( rhs.value ) < 0; else if ( lhs.value->level() == rhs.value->level() ) if ( lhs.value->levelcoeff() == rhs.value->levelcoeff() ) return lhs.value->comparesame( rhs.value ) < 0; else if ( lhs.value->levelcoeff() > rhs.value->levelcoeff() ) return lhs.value->comparecoeff( rhs.value ) < 0; else return rhs.value->comparecoeff( lhs.value ) > 0; else return lhs.value->level() < rhs.value->level(); } /** CanonicalForm bgcd ( const CanonicalForm & f, const CanonicalForm & g ) * * bgcd() - return base coefficient gcd. * * If both f and g are integers and `SW_RATIONAL' is off the * positive greatest common divisor of f and g is returned. * Otherwise, if `SW_RATIONAL' is on or one of f and g is not an * integer, the greatest common divisor is trivial: either zero * if f and g equal zero or one (both from the current domain). * * f and g should come from one base domain which should be not * the prime power domain. * * Implementation: * * CanonicalForm::bgcd() handles the immediate case with a * standard euclidean algorithm. For the non-immediate cases * `InternalCF::bgcdsame()' or `InternalCF::bgcdcoeff()', resp. are * called following the usual level/levelcoeff approach. * * InternalCF::bgcdsame() and * InternalCF::bgcdcoeff() throw an assertion ("not implemented") * * InternalInteger::bgcdsame() is a wrapper around `mpz_gcd()' * which takes some care about immediate results and the sign * of the result * InternalInteger::bgcdcoeff() is a wrapper around * `mpz_gcd_ui()' which takes some care about the sign * of the result * * InternalRational::bgcdsame() and * InternalRational::bgcdcoeff() always return one * **/ CanonicalForm bgcd ( const CanonicalForm & f, const CanonicalForm & g ) { // check immediate cases int what = is_imm( g.value ); if ( is_imm( f.value ) ) { ASSERT( ! what || (what == is_imm( f.value )), "incompatible operands" ); if ( what == 0 ) return g.value->bgcdcoeff( f.value ); else if ( what == INTMARK && ! cf_glob_switches.isOn( SW_RATIONAL ) ) { // calculate gcd using standard integer // arithmetic long fInt = imm2int( f.value ); long gInt = imm2int( g.value ); if ( fInt < 0 ) fInt = -fInt; if ( gInt < 0 ) gInt = -gInt; // swap fInt and gInt if ( gInt > fInt ) { long swap = gInt; gInt = fInt; fInt = swap; } // now, 0 <= gInt <= fInt. Start the loop. while ( gInt ) { // calculate (fInt, gInt) = (gInt, fInt%gInt) long r = fInt % gInt; fInt = gInt; gInt = r; } return CanonicalForm( fInt ); } else // we do not go for maximal speed for these stupid // special cases return CanonicalForm( f.isZero() && g.isZero() ? 0 : 1 ); } else if ( what ) return f.value->bgcdcoeff( g.value ); int fLevel = f.value->level(); int gLevel = g.value->level(); // check levels if ( fLevel == gLevel ) { fLevel = f.value->levelcoeff(); gLevel = g.value->levelcoeff(); // check levelcoeffs if ( fLevel == gLevel ) return f.value->bgcdsame( g.value ); else if ( fLevel < gLevel ) return g.value->bgcdcoeff( f.value ); else return f.value->bgcdcoeff( g.value ); } else if ( fLevel < gLevel ) return g.value->bgcdcoeff( f.value ); else return f.value->bgcdcoeff( g.value ); } /** CanonicalForm bextgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b ) * * bextgcd() - return base coefficient extended gcd. * **/ CanonicalForm bextgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b ) { // check immediate cases int what = is_imm( g.value ); if ( is_imm( f.value ) ) { ASSERT( ! what || (what == is_imm( f.value )), "incompatible operands" ); if ( what == 0 ) return g.value->bextgcdcoeff( f.value, b, a ); else if ( what == INTMARK && ! cf_glob_switches.isOn( SW_RATIONAL ) ) { // calculate extended gcd using standard integer // arithmetic long fInt = imm2int( f.value ); long gInt = imm2int( g.value ); // to avoid any system dpendencies with `%', we work // with positive numbers only. To a pity, we have to // redo all the checks when assigning to a and b. if ( fInt < 0 ) fInt = -fInt; if ( gInt < 0 ) gInt = -gInt; // swap fInt and gInt if ( gInt > fInt ) { long swap = gInt; gInt = fInt; fInt = swap; } long u = 1; long v = 0; long uNext = 0; long vNext = 1; // at any step, we have: // fInt_0 * u + gInt_0 * v = fInt // fInt_0 * uNext + gInt_0 * vNext = gInt // where fInt_0 and gInt_0 denote the values of fint // and gInt, resp., at the beginning while ( gInt ) { long r = fInt % gInt; long q = fInt / gInt; long uSwap = u - q * uNext; long vSwap = v - q * vNext; // update variables fInt = gInt; gInt = r; u = uNext; v = vNext; uNext = uSwap; vNext = vSwap; } // now, assign to a and b long fTest = imm2int( f.value ); long gTest = imm2int( g.value ); if ( gTest > fTest ) { a = v; b = u; } else { a = u; b = v; } if ( fTest < 0 ) a = -a; if ( gTest < 0 ) b = -b; return CanonicalForm( fInt ); } else // stupid special cases if ( ! f.isZero() ) { a = 1/f; b = 0; return CanonicalForm( 1 ); } else if ( ! g.isZero() ) { a = 0; b = 1/g; return CanonicalForm( 1 ); } else { a = 0; b = 0; return CanonicalForm( 0 ); } } else if ( what ) return f.value->bextgcdcoeff( g.value, a, b ); int fLevel = f.value->level(); int gLevel = g.value->level(); // check levels if ( fLevel == gLevel ) { fLevel = f.value->levelcoeff(); gLevel = g.value->levelcoeff(); // check levelcoeffs if ( fLevel == gLevel ) return f.value->bextgcdsame( g.value, a, b ); else if ( fLevel < gLevel ) return g.value->bextgcdcoeff( f.value, b, a ); else return f.value->bextgcdcoeff( g.value, a, b ); } else if ( fLevel < gLevel ) return g.value->bextgcdcoeff( f.value, b, a ); else return f.value->bextgcdcoeff( g.value, a, b ); } CanonicalForm blcm ( const CanonicalForm & f, const CanonicalForm & g ) { if ( f.isZero() || g.isZero() ) return CanonicalForm( 0 ); /* else if (f.isOne()) return g; else if (g.isOne()) return f; */ else return (f / bgcd( f, g )) * g; } /** input/output **/ #ifndef NOSTREAMIO void CanonicalForm::print( OSTREAM & os, char * str ) const { if ( is_imm( value ) ) imm_print( os, value, str ); else value->print( os, str ); } void CanonicalForm::print( OSTREAM & os ) const { if ( is_imm( value ) ) imm_print( os, value, "" ); else value->print( os, "" ); } OSTREAM& operator << ( OSTREAM & os, const CanonicalForm & cf ) { cf.print( os, "" ); return os; } ISTREAM& operator >> ( ISTREAM & is, CanonicalForm & cf ) { cf = readCF( is ); return is; } #endif /* NOSTREAMIO */ /** genOne(), genZero() **/ CanonicalForm CanonicalForm::genZero() const { int what = is_imm( value ); if ( what == FFMARK ) return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 0L ) ); else if ( what == GFMARK ) return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 0L ) ); else if ( what ) return CanonicalForm( CFFactory::basic( IntegerDomain, 0L ) ); else return CanonicalForm( value->genZero() ); } CanonicalForm CanonicalForm::genOne() const { int what = is_imm( value ); if ( what == FFMARK ) return CanonicalForm( CFFactory::basic( FiniteFieldDomain, 1L ) ); else if ( what == GFMARK ) return CanonicalForm( CFFactory::basic( GaloisFieldDomain, 1L ) ); else if ( what ) return CanonicalForm( CFFactory::basic( IntegerDomain, 1L ) ); else return CanonicalForm( value->genOne() ); } /** exponentiation **/ CanonicalForm power ( const CanonicalForm & f, int n ) { ASSERT( n >= 0, "illegal exponent" ); if ( f.isZero() ) return 0; else if ( f.isOne() ) return f; else if ( f == -1 ) { if ( n % 2 == 0 ) return 1; else return -1; } else if ( n == 0 ) return 1; //else if (f.inGF()) //{ //} else { CanonicalForm g,h; h=f; while(n%2==0) { h*=h; n/=2; } g=h; while(1) { n/=2; if(n==0) return g; h*=h; if(n%2!=0) g*=h; } } } /** exponentiation **/ CanonicalForm power ( const Variable & v, int n ) { //ASSERT( n >= 0, "illegal exponent" ); if ( n == 0 ) return 1; else if ( n == 1 ) return v; else if (( v.level() < 0 ) && (hasMipo(v))) { CanonicalForm result( v, n-1 ); return result * v; } else return CanonicalForm( v, n ); } /** switches **/ void On( int sw ) { cf_glob_switches.On( sw ); } /** switches **/ void Off( int sw ) { cf_glob_switches.Off( sw ); } /** switches **/ bool isOn( int sw ) { return cf_glob_switches.isOn( sw ); } singular-4.0.3+ds/factory/canonicalform.h000066400000000000000000000257021266270727000204160ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file canonicalform.h * * Header for factory's main class CanonicalForm **/ #ifndef INCL_CANONICALFORM_H #define INCL_CANONICALFORM_H // #include "config.h" #ifndef NOSTREAMIO # ifdef HAVE_IOSTREAM # include # define OSTREAM std::ostream # define ISTREAM std::istream # elif defined(HAVE_IOSTREAM_H) # include # define OSTREAM ostream # define ISTREAM istream # endif #endif /* NOSTREAMIO */ #include #include "cf_defs.h" #include "variable.h" #include #include #include #include #include #include #ifdef HAVE_OMALLOC #include #endif /*BEGINPUBLIC*/ #undef CF_INLINE #define CF_INLINE #undef CF_NO_INLINE #define CF_NO_INLINE /*ENDPUBLIC*/ #ifdef CF_USE_INLINE #undef CF_INLINE #define CF_INLINE inline #else #undef CF_INLINE #define CF_INLINE #endif /*BEGINPUBLIC*/ class InternalCF; inline int is_imm ( const InternalCF * const ptr ) { // returns 0 if ptr is not immediate return ( ((int)((intptr_t)ptr)) & 3 ); } /** * factory's main class * * a CanonicalForm can represent a polynomial over or a constant in F_p, * F_p(alpha), GF (F_p[t]/(Conway polynomial)), Z, or Q * * @sa int_poly.h, variable.h, ffops.h, gfops.h, imm.h, int_int.h, int_rat.h **/ class CanonicalForm #ifdef HAVE_OMALLOC : public omallocClass #endif { private: InternalCF *value; public: // constructors, destructors, selectors CF_INLINE CanonicalForm(); CF_INLINE CanonicalForm( const CanonicalForm& ); CF_INLINE CanonicalForm( InternalCF* ); CF_INLINE CanonicalForm( const int ); CF_INLINE CanonicalForm( const long ); CF_INLINE CanonicalForm( const Variable & ); CF_INLINE CanonicalForm( const Variable &, int ); CanonicalForm( const char *, const int base=10 ); // use with caution - does only handle integers !!! CF_NO_INLINE ~CanonicalForm(); InternalCF* getval() const; // use with caution !!! CanonicalForm deepCopy() const; void mpzval(mpz_t val) const; // predicates CF_NO_INLINE bool isOne() const; CF_NO_INLINE bool isZero() const; inline bool isImm() const { return is_imm( value ); }; bool inZ() const; bool inQ() const; bool inFF() const; bool inGF() const; bool inBaseDomain() const; bool inExtension() const; bool inCoeffDomain() const; bool inPolyDomain() const; bool inQuotDomain() const; bool isFFinGF() const; bool isUnivariate() const; bool isHomogeneous() const; // conversion functions long intval() const; CanonicalForm mapinto () const; CanonicalForm lc () const; CanonicalForm Lc () const; CanonicalForm LC () const; CanonicalForm LC ( const Variable & v ) const; int degree () const; int degree ( const Variable & v ) const; CanonicalForm tailcoeff () const; CanonicalForm tailcoeff ( const Variable & v ) const; int taildegree () const; int level () const; Variable mvar () const; CanonicalForm num () const; CanonicalForm den () const; // assignment operators CF_NO_INLINE CanonicalForm& operator = ( const CanonicalForm& ); CF_NO_INLINE CanonicalForm& operator = ( const long ); CanonicalForm& operator += ( const CanonicalForm& ); CanonicalForm& operator -= ( const CanonicalForm& ); CanonicalForm& operator *= ( const CanonicalForm& ); CanonicalForm& operator /= ( const CanonicalForm& ); CanonicalForm& operator %= ( const CanonicalForm& ); CanonicalForm& div ( const CanonicalForm& ); CanonicalForm& tryDiv (const CanonicalForm&, const CanonicalForm&, bool& ); CanonicalForm& mod ( const CanonicalForm& ); // evaluation operators CanonicalForm operator () ( const CanonicalForm & f ) const; CanonicalForm operator () ( const CanonicalForm & f, const Variable & v ) const; CanonicalForm operator [] ( int i ) const; CanonicalForm deriv() const; CanonicalForm deriv( const Variable & x ) const; int sign() const; CanonicalForm sqrt() const; int ilog2() const; // comparison operators friend bool operator == ( const CanonicalForm&, const CanonicalForm& ); friend bool operator != ( const CanonicalForm&, const CanonicalForm& ); friend bool operator > ( const CanonicalForm&, const CanonicalForm& ); friend bool operator < ( const CanonicalForm&, const CanonicalForm& ); // arithmetic operators friend CF_NO_INLINE CanonicalForm operator - ( const CanonicalForm& ); friend void divrem ( const CanonicalForm&, const CanonicalForm&, CanonicalForm&, CanonicalForm& ); friend bool divremt ( const CanonicalForm&, const CanonicalForm&, CanonicalForm&, CanonicalForm& ); friend bool tryDivremt ( const CanonicalForm&, const CanonicalForm&, CanonicalForm&, CanonicalForm&, const CanonicalForm&, bool& ); friend CanonicalForm bgcd ( const CanonicalForm &, const CanonicalForm & ); friend CanonicalForm bextgcd ( const CanonicalForm &, const CanonicalForm &, CanonicalForm &, CanonicalForm & ); // input/output #ifndef NOSTREAMIO void print( OSTREAM&, char * ) const; void print( OSTREAM& ) const; friend OSTREAM& operator << ( OSTREAM&, const CanonicalForm& ); friend ISTREAM& operator >> ( ISTREAM&, CanonicalForm& ); #endif /* NOSTREAMIO */ // obsolete methods CanonicalForm genZero() const; CanonicalForm genOne() const; friend class CFIterator; }; CF_INLINE CanonicalForm operator + ( const CanonicalForm&, const CanonicalForm& ); CF_NO_INLINE CanonicalForm operator - ( const CanonicalForm&, const CanonicalForm& ); CF_INLINE CanonicalForm operator * ( const CanonicalForm&, const CanonicalForm& ); CF_NO_INLINE CanonicalForm operator / ( const CanonicalForm&, const CanonicalForm& ); CF_NO_INLINE CanonicalForm operator % ( const CanonicalForm&, const CanonicalForm& ); CF_NO_INLINE CanonicalForm div ( const CanonicalForm&, const CanonicalForm& ); CF_NO_INLINE CanonicalForm mod ( const CanonicalForm&, const CanonicalForm& ); /*ENDPUBLIC*/ #ifdef CF_USE_INLINE #include "cf_inline.cc" #endif /*BEGINPUBLIC*/ //{{{ function declarations from canonicalform.cc CanonicalForm blcm ( const CanonicalForm & f, const CanonicalForm & g ); CanonicalForm power ( const CanonicalForm & f, int n ); CanonicalForm power ( const Variable & v, int n ); //}}} //{{{ function declarations from cf_gcd.cc CanonicalForm gcd ( const CanonicalForm&, const CanonicalForm& ); CanonicalForm gcd_poly ( const CanonicalForm & f, const CanonicalForm & g ); CanonicalForm lcm ( const CanonicalForm&, const CanonicalForm& ); CanonicalForm pp ( const CanonicalForm& ); CanonicalForm content ( const CanonicalForm& ); CanonicalForm content ( const CanonicalForm&, const Variable& ); CanonicalForm icontent ( const CanonicalForm & f ); CanonicalForm vcontent ( const CanonicalForm & f, const Variable & x ); //}}} //{{{ function declarations from cf_ops.cc CanonicalForm swapvar ( const CanonicalForm &, const Variable &, const Variable & ); CanonicalForm replacevar ( const CanonicalForm &, const Variable &, const Variable & ); int getNumVars( const CanonicalForm & f ); CanonicalForm getVars( const CanonicalForm & f ); CanonicalForm apply ( const CanonicalForm & f, void (*mf)( CanonicalForm &, int & ) ); CanonicalForm mapdomain ( const CanonicalForm & f, CanonicalForm (*mf)( const CanonicalForm & ) ); int * degrees ( const CanonicalForm & f, int * degs = 0 ); int totaldegree ( const CanonicalForm & f ); int totaldegree ( const CanonicalForm & f, const Variable & v1, const Variable & v2 ); int size ( const CanonicalForm & f, const Variable & v ); int size ( const CanonicalForm & f ); CanonicalForm reduce ( const CanonicalForm& f, const CanonicalForm & M); bool hasFirstAlgVar( const CanonicalForm & f, Variable & a); CanonicalForm leftShift (const CanonicalForm& F, int n); //}}} //{{{ inline functions corresponding to CanonicalForm methods //{{{ docu // // - inline functions corresponding to CanonicalForm methods. // // These function exist for convenience only and because it is // more beautiful to write 'degree( f )' than 'f.degree()'. // //}}} inline CanonicalForm lc ( const CanonicalForm & f ) { return f.lc(); } inline CanonicalForm Lc ( const CanonicalForm & f ) { return f.Lc(); } inline CanonicalForm LC ( const CanonicalForm & f ) { return f.LC(); } inline CanonicalForm LC ( const CanonicalForm & f, const Variable & v ) { return f.LC( v ); } inline int degree ( const CanonicalForm & f ) { return f.degree(); } inline int degree ( const CanonicalForm & f, const Variable & v ) { return f.degree( v ); } inline int taildegree ( const CanonicalForm & f ) { return f.taildegree(); } inline CanonicalForm tailcoeff ( const CanonicalForm & f ) { return f.tailcoeff(); } inline CanonicalForm tailcoeff (const CanonicalForm& f, const Variable& v) { return f.tailcoeff(v); } inline int level ( const CanonicalForm & f ) { return f.level(); } inline Variable mvar ( const CanonicalForm & f ) { return f.mvar(); } inline CanonicalForm num ( const CanonicalForm & f ) { return f.num(); } inline CanonicalForm den ( const CanonicalForm & f ) { return f.den(); } inline int sign ( const CanonicalForm & a ) { return a.sign(); } inline CanonicalForm deriv ( const CanonicalForm & f, const Variable & x ) { return f.deriv( x ); } inline CanonicalForm sqrt ( const CanonicalForm & a ) { return a.sqrt(); } inline int ilog2 ( const CanonicalForm & a ) { return a.ilog2(); } inline CanonicalForm mapinto ( const CanonicalForm & f ) { return f.mapinto(); } //}}} //{{{ inline functions inline CanonicalForm head ( const CanonicalForm & f ) { if ( f.level() > 0 ) return power( f.mvar(), f.degree() ) * f.LC(); else return f; } inline int headdegree ( const CanonicalForm & f ) { return totaldegree( head( f ) ); } //}}} //{{{ other function declarations void setCharacteristic( int c ); // -> Fp && Q void setCharacteristic( int c, int n ); // -> PrimePower void setCharacteristic( int c, int n, char name ); // -> GF(q) int getCharacteristic(); int getGFDegree(); CanonicalForm getGFGenerator(); void On( int ); void Off( int ); bool isOn( int ); //}}} //{{{ type definitions typedef AFactor CFAFactor; typedef List CFAFList; typedef ListIterator CFAFListIterator; typedef Factor CFFactor; typedef List CFFList; typedef ListIterator CFFListIterator; typedef List CFList; typedef ListIterator CFListIterator; typedef Array CFArray; typedef Matrix CFMatrix; typedef List ListCFList; typedef ListIterator ListCFListIterator ; typedef List IntList; typedef ListIterator IntListIterator; typedef List Varlist; typedef ListIterator VarlistIterator; typedef Array Intarray; //}}} /*ENDPUBLIC*/ #endif /* ! INCL_CANONICALFORM_H */ singular-4.0.3+ds/factory/cfCharSets.cc000066400000000000000000000365531266270727000177740ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfCharSets.cc * * This file provides functions to compute characteristic sets * * @note some of the code is code from libfac or derived from code from libfac. * Libfac is written by M. Messollen. See also COPYING for license information * and README for general information on characteristic sets. * * ABSTRACT: Descriptions can be found in Wang "On the Parallelization of * characteristic-set based algorithms" or Greuel/Pfister "A Singular * Introduction to Commutative Algebra". * * @authors Martin Lee * **/ /*****************************************************************************/ #include "config.h" #include "timing.h" #include "canonicalform.h" #include "cfCharSets.h" #include "cfCharSetsUtil.h" #include "cf_algorithm.h" #include "facAlgFunc.h" TIMING_DEFINE_PRINT(neworder_time) // set up a new orderd list of Variables. // we try to reorder the variables heuristically optimal. Varlist neworder (const CFList & PolyList) { CFList PS= PolyList, PS1=PolyList; Varlist oldorder, reorder, difference; TIMING_START (neworder_time); int highest_level= level (get_max_var (PS)); // set up oldorder and first criterion: only_in_one for (int i= highest_level; i>=1; i--) { oldorder.insert (Variable (i)); CFList is_one= only_in_one (PS1, Variable (i)); if (is_one.length() == 1) { reorder.insert (Variable (i)); PS1= Difference (PS1, is_one); } else if (is_one.length() == 0) { reorder.append (Variable (i)); // assigne it the highest level PS1= Difference (PS1, is_one); } } difference= Difference (oldorder, reorder); // rearrange the ordering of the variables! difference= reorderb (difference, PS, highest_level); reorder= Union (reorder, difference); TIMING_END(neworder_time); TIMING_PRINT(neworder_time, "\ntime used for neworder : "); return Union (reorder, Difference (oldorder, reorder)); } // the same as above, only returning a list of CanonicalForms CFList newordercf (const CFList & PolyList) { Varlist reorder= neworder (PolyList); CFList output; for (VarlistIterator i=reorder; i.hasItem(); i++) output.append (CanonicalForm (i.getItem())); return output; } // the same as above, only returning a list of ints IntList neworderint (const CFList & PolyList) { Varlist reorder= neworder (PolyList); IntList output; for (VarlistIterator i= reorder; i.hasItem(); i++) output.append (level (i.getItem())); return output; } // a library function: we reorganize the global variable ordering CFList reorder (const Varlist & betterorder, const CFList & PS) { int i= 1, n= betterorder.length(); Intarray v (1, n); CFList ps= PS; //initalize: for (VarlistIterator j= betterorder; j.hasItem(); j++) { v[i]= level (j.getItem()); i++; } // reorder: for (i= 1; i <= n; i++) ps= swapvar (ps, Variable (v[i]), Variable (n + i)); return ps; } CFFList reorder (const Varlist & betterorder, const CFFList & PS) { int i= 1, n= betterorder.length(); Intarray v (1, n); CFFList ps= PS; //initalize: for (VarlistIterator j= betterorder; j.hasItem(); j++) { v[i]= level (j.getItem()); i++; } // reorder: for (i= 1; i <= n; i++) ps= swapvar (ps, Variable (v[i]), Variable (n + i)); return ps; } ListCFList reorder (const Varlist & betterorder, const ListCFList & Q) { ListCFList Q1; for (ListCFListIterator i= Q; i.hasItem(); i++) Q1.append (reorder (betterorder, i.getItem())); return Q1; } CFList basicSet (const CFList &PS) { CFList QS= PS, BS, RS; CanonicalForm b; int cb, degb; if (PS.length() < 2) return PS; CFListIterator i; while (!QS.isEmpty()) { b= lowestRank (QS); cb= b.level(); BS= Union(CFList (b), BS); if (cb <= 0) return CFList(); else { degb= degree (b); RS= CFList(); for (i= QS; i.hasItem(); i++) { if (degree (i.getItem(), cb) < degb) RS= Union (CFList (i.getItem()), RS); } QS= RS; } } return BS; } CFList charSet (const CFList &PS) { CFList QS= PS, RS= PS, CSet, tmp; CFListIterator i; CanonicalForm r; while (!RS.isEmpty()) { CSet= basicSet (QS); RS= CFList(); if (CSet.length() > 0 && CSet.getFirst().level() > 0) { tmp= Difference (QS, CSet); for (i= tmp; i.hasItem(); i++) { r= Prem (i.getItem(), CSet); if (r != 0) RS= Union (RS, CFList (r)); } QS= Union (QS, RS); } } return CSet; } /// medial set CFList charSetN (const CFList &PS) { CFList QS= PS, RS= PS, CSet, tmp; CFListIterator i; CanonicalForm r; while (!RS.isEmpty()) { QS= uniGcd (QS); CSet= basicSet (QS); RS= CFList(); if (CSet.length() > 0 && CSet.getFirst().level() > 0) { tmp= Difference (QS, CSet); for (i= tmp; i.hasItem(); i++) { r= Prem (i.getItem(), CSet); if (!r.isZero()) RS= Union (RS, CFList (r)); } QS= Union (CSet, RS); } } return CSet; } /// compute a characteristic set via medial set CFList charSetViaCharSetN (const CFList& PS) { CFList L; CFFList sqrfFactors; CanonicalForm sqrf; CFFListIterator iter2; for (CFListIterator iter= PS; iter.hasItem(); iter++) { sqrf= 1; sqrfFactors= sqrFree (iter.getItem()); for (iter2= sqrfFactors; iter2.hasItem(); iter2++) sqrf *= iter2.getItem().factor(); L= Union (L, CFList (normalize (sqrf))); } CFList result= charSetN (L); if (result.isEmpty() || result.getFirst().inCoeffDomain()) return CFList(1); CanonicalForm r; CFList RS; CFList tmp= Difference (L, result); for (CFListIterator i= tmp; i.hasItem(); i++) { r= Premb (i.getItem(), result); if (!r.isZero()) RS= Union (RS, CFList (r)); } if (RS.isEmpty()) return result; return charSetViaCharSetN (Union (L, Union (RS, result))); } /// modified medial set CFList modCharSet (const CFList& L, StoreFactors& StoredFactors, bool removeContents) { CFList QS, RS= L, CSet, tmp, contents, initial, removedFactors; CFListIterator i; CanonicalForm r, cF; bool noRemainder= true; StoreFactors StoredFactors2; QS= uniGcd (L); while (!RS.isEmpty()) { noRemainder= true; CSet= basicSet (QS); initial= factorsOfInitials (CSet); StoredFactors2.FS1= StoredFactors.FS1; StoredFactors2.FS2= Union (StoredFactors2.FS2, initial); RS= CFList(); if (CSet.length() > 0 && CSet.getFirst().level() > 0) { tmp= Difference (QS, CSet); for (i= tmp; i.hasItem(); i++) { r= Prem (i.getItem(), CSet); if (!r.isZero()) { noRemainder= false; if (removeContents) { removeContent (r, cF); if (!cF.isZero()) contents= Union (contents, factorPSet (CFList(cF))); //factorPSet maybe too much it should suffice to do a squarefree factorization instead } removeFactors (r, StoredFactors2, removedFactors); StoredFactors2.FS1= Union (StoredFactors2.FS1, removedFactors); StoredFactors2.FS2= Difference (StoredFactors2.FS2, removedFactors); removedFactors= CFList(); RS= Union (RS, CFList (r)); } } if (removeContents && !noRemainder) { StoredFactors.FS1= Union (StoredFactors2.FS1, contents); StoredFactors.FS2= StoredFactors2.FS2; } else StoredFactors= StoredFactors2; QS= Union (CSet, RS); contents= CFList(); removedFactors= CFList(); } else StoredFactors= StoredFactors2; } return CSet; } /// characteristic set via modified medial set CFList charSetViaModCharSet (const CFList& PS, StoreFactors& StoredFactors, bool removeContents) { CFList L; CFFList sqrfFactors; CanonicalForm sqrf; CFFListIterator iter2; for (CFListIterator iter= PS; iter.hasItem(); iter++) { sqrf= 1; sqrfFactors= sqrFree (iter.getItem()); for (iter2= sqrfFactors; iter2.hasItem(); iter2++) sqrf *= iter2.getItem().factor(); L= Union (L, CFList (normalize (sqrf))); } L= uniGcd (L); CFList result= modCharSet (L, StoredFactors, removeContents); if (result.isEmpty() || result.getFirst().inCoeffDomain()) return CFList(1); CanonicalForm r; CFList RS; CFList tmp= Difference (L, result); for (CFListIterator i= tmp; i.hasItem(); i++) { r= Premb (i.getItem(), result); if (!r.isZero()) RS= Union (RS, CFList (r)); } if (RS.isEmpty()) return result; return charSetViaModCharSet (Union (L, Union (RS, result)), StoredFactors, removeContents); } CFList charSetViaModCharSet (const CFList& PS, bool removeContents) { StoreFactors tmp; return charSetViaModCharSet (PS, tmp, removeContents); } CFList modCharSet (const CFList& PS, bool removeContents) { StoreFactors tmp; return modCharSet (PS, tmp, removeContents); } ListCFList charSeries (const CFList& L) { ListCFList tmp, result, tmp2, ppi1, ppi2, qqi, ppi, alreadyConsidered; CFList l, charset, ini; int count= 0; int highestLevel= 1; CFListIterator iter; StoreFactors StoredFactors; l= L; for (iter= l; iter.hasItem(); iter++) { iter.getItem()= normalize (iter.getItem()); if (highestLevel < iter.getItem().level()) highestLevel= iter.getItem().level(); } tmp= ListCFList (l); while (!tmp.isEmpty()) { sortListCFList (tmp); l= tmp.getFirst(); tmp= Difference (tmp, l); select (ppi, l.length(), ppi1, ppi2); inplaceUnion (ppi2, qqi); if (count > 0) ppi= Union (ppi1, ListCFList (l)); else ppi= ListCFList(); if (l.length() - 3 < highestLevel) charset= charSetViaModCharSet (l, StoredFactors); else charset= charSetViaCharSetN (l); if (charset.length() > 0 && charset.getFirst().level() > 0) { result= Union (ListCFList (charset), result); ini= factorsOfInitials (charset); ini= Union (ini, factorPSet (StoredFactors.FS1)); sortCFListByLevel (ini); } else { ini= factorPSet (StoredFactors.FS1); sortCFListByLevel (ini); } tmp2= adjoin (ini, l, qqi); tmp= Union (tmp2, tmp); StoredFactors.FS1= CFList(); StoredFactors.FS2= CFList(); ppi1= ListCFList(); ppi2= ListCFList(); count++; } //TODO need to remove superflous components return result; } static bool irreducible (const CFList & AS) { // AS is given by AS = { A1, A2, .. Ar }, d_i = degree(Ai) // 1) we test: if d_i > 1, d_j =1 for all j<>i, then AS is irreducible. bool deg1= true; for (CFListIterator i= AS ; i.hasItem(); i++) { if (degree (i.getItem()) > 1) { if (deg1) deg1= false; else return false; // found 2nd poly with deg > 1 } } return true; } static CFList irredAS (CFList & AS, int & indexRed, CanonicalForm & reducible) { CFFList qs; CFList ts, as; CanonicalForm elem; bool ind= true; int nr= 0; CFListIterator i; indexRed= 0; for (i= AS; i.hasItem(); i++ ) { nr += 1; qs= factorize (i.getItem()); if (qs.getFirst().factor().inCoeffDomain()) qs.removeFirst(); if ((qs.length() >= 2 ) || (qs.getFirst().exp() > 1)) { indexRed= nr; ind= false; reducible= i.getItem(); break; } } if (ind) { if (irreducible (AS)) // as quasilinear? => irreducible! indexRed= 0; else { i= AS; for (nr= 1; nr< AS.length(); nr++) { as.append (i.getItem()); i++; if (degree (i.getItem()) > 1) { // search for a non linear elem qs= facAlgFunc2 (i.getItem(), as); if (qs.length() > 0) { if (qs.getFirst().factor().inCoeffDomain()) qs.removeFirst(); if (qs.length() > 1 || qs.getFirst().exp() > 1) { //found elem is reducible reducible= i.getItem(); indexRed= nr + 1; break; } } } } } } for (CFFListIterator k= qs; k.hasItem(); k++) ts.append (normalize (k.getItem().factor())); return ts; } ListCFList irrCharSeries (const CFList & PS) { CanonicalForm reducible, reducible2; CFList qs, cs, factorset, is, ts, L; CanonicalForm sqrf; CFFList sqrfFactors; CFFListIterator iter2; for (CFListIterator iter= PS; iter.hasItem(); iter++) { sqrf= 1; sqrfFactors= sqrFree (iter.getItem()); if (sqrfFactors.getFirst().factor().inCoeffDomain()) sqrfFactors.removeFirst(); for (iter2= sqrfFactors; iter2.hasItem(); iter2++) sqrf *= iter2.getItem().factor(); sqrf= normalize (sqrf); L= Union (CFList (sqrf), L); } ListCFList pi, ppi, qqi, qsi, iss, qhi= ListCFList(L); int nr_of_iteration= 0, indexRed, highestlevel= 0; for (CFListIterator iter= PS; iter.hasItem(); iter++) { if (level (iter.getItem()) > highestlevel) highestlevel= level(iter.getItem()); } while (!qhi.isEmpty()) { sortListCFList (qhi); qs= qhi.getFirst(); ListCFList ppi1,ppi2; select (ppi, qs.length(), ppi1, ppi2); inplaceUnion (ppi2, qqi); if (nr_of_iteration == 0) { nr_of_iteration += 1; ppi= ListCFList(); } else { nr_of_iteration += 1; ppi= Union (ppi1, ListCFList (qs)); } StoreFactors StoredFactors; if (qs.length() - 3 < highestlevel) cs= modCharSet (qs, StoredFactors, false); else cs= charSetN (qs); cs= removeContent (cs, StoredFactors); factorset= StoredFactors.FS1; if (!cs.isEmpty() && cs.getFirst().level() > 0) { ts= irredAS (cs, indexRed, reducible); if (indexRed <= 0) // irreducible { if (!isSubset (cs,qs)) cs= charSetViaCharSetN (Union (qs,cs)); if (!find (pi, cs)) { pi= Union (ListCFList (cs), pi); if (cs.getFirst().level() > 0) { ts= irredAS (cs, indexRed, reducible); if (indexRed <= 0) //irreducible { qsi= Union (ListCFList(cs), qsi); if (cs.length() == highestlevel) is= factorPSet (factorset); else is= Union (factorsOfInitials (cs), factorPSet (factorset)); iss= adjoin (is, qs, qqi); } } else iss= adjoin (factorPSet (factorset), qs, qqi); } else iss= adjoin (factorPSet (factorset), qs, qqi); } if (indexRed > 0) { is= factorPSet (factorset); if (indexRed > 1) { CFList cst; for (CFListIterator i= cs ; i.hasItem(); i++) { if (i.getItem() == reducible) break; else cst.append (i.getItem()); } is= Union (factorsOfInitials (Union (cst, CFList (reducible))), is); iss= Union (adjoinb (ts, qs, qqi, cst), adjoin (is, qs, qqi)); } else iss= adjoin (Union (is, ts), qs, qqi); } } else iss= adjoin (factorPSet (factorset), qs, qqi); if (qhi.length() > 1) { qhi.removeFirst(); qhi= Union (iss, qhi); } else qhi= iss; } if (!qsi.isEmpty()) return contract (qsi); return ListCFList(CFList (1)) ; } singular-4.0.3+ds/factory/cfCharSets.h000066400000000000000000000063261266270727000176310ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfCharSets.h * * This file provides functions to compute characteristic sets * * @note some of the code is code from libfac or derived from code from libfac. * Libfac is written by M. Messollen. See also COPYING for license information * and README for general information on characteristic sets. * * ABSTRACT: Descriptions can be found in Wang "On the Parallelization of * characteristic-set based algorithms" or Greuel/Pfister "A Singular * Introduction to Commutative Algebra". * * @author Martin Lee * **/ /*****************************************************************************/ #ifndef CF_CHARSETS #define CF_CHARSETS #include "cfCharSetsUtil.h" /*BEGINPUBLIC*/ /// basic set in the sense of Wang a.k.a. minimal ascending set in the sense of /// Greuel/Pfister CFList basicSet (const CFList& PS); /// characteristic set CFList charSet (const CFList& PS); /// modified medial set CFList modCharSet (const CFList& PS, StoreFactors& StoredFactors, bool removeContents= true); CFList modCharSet (const CFList& PS, bool removeContents); CFList charSetViaCharSetN (const CFList& PS); CFList charSetN (const CFList &PS); /// modified characteristic set, i.e. a characteristic set with certain /// factors removed CFList charSetViaModCharSet (const CFList& PS, StoreFactors& StoredFactors, bool removeContents= true); /// modified characteristic set, i.e. a characteristic set with certain /// factors removed CFList charSetViaModCharSet (const CFList& PS, bool removeContents= true); /// characteristic series ListCFList charSeries (const CFList& L); /// irreducible characteristic series ListCFList irrCharSeries (const CFList & PS); // the next three give you a heuristically optimal reorderd list of the // variables. For internal and external (e.g. Singular/Macaulay2) library use. // This is really experimental! // See the comments in reorder.cc. // // this gives you a heuristically optimal ordering for the ring variables // if you use the irreducible characteristic series. Varlist neworder (const CFList & PolyList); // the same as neworder(...) only returning a list of CanonicalForm 's // (i.e. the variables as CanonicalForms) CFList newordercf (const CFList & PolyList); // the same as neworder(...) only returning a list of int 's (i.e. the levels) IntList neworderint (const CFList & PolyList); // for library internal use only: // next function reorders the variables in PS: // a code segment to use: // ... // #include // for typedef's // CFList PS= ; // Varlist betterorder= neworder(PS); // PS= reorder(betterorder,PS); // reorder variables in PS from oldorder // to betterorder // ListCFList Q= IrrCharSeries( PS ); // Q= reorder(betterorder,Q); // revert ordering to oldorder // CFList reorder (const Varlist & betterorder, const CFList & PS); CFFList reorder (const Varlist & betterorder, const CFFList & PS); ListCFList reorder (const Varlist & betterorder, const ListCFList & Q); /*ENDPUBLIC*/ #endif singular-4.0.3+ds/factory/cfCharSetsUtil.cc000066400000000000000000000510041266270727000206160ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfCharSetsUtil.cc * * This file provides utility functions to compute characteristic sets * * @note some of the code is code from libfac or derived from code from libfac. * Libfac is written by M. Messollen. See also COPYING for license information * and README for general information on characteristic sets. * * @authors Martin Lee * **/ /*****************************************************************************/ #include "config.h" #include "canonicalform.h" #include "cf_algorithm.h" #include "cfCharSetsUtil.h" #define __ARRAY_INIT__ -1 // the maximal degree of polys in PS wrt. variable x int degpsmax (const CFList & PS, const Variable & x, Intarray & A, Intarray & C) { int varlevel= level(x); if (A[varlevel] != __ARRAY_INIT__) return A[varlevel]; int max= 0, temp, count= 0; for (CFListIterator i= PS; i.hasItem(); i++) { temp= degree (i.getItem(), x); if (temp > max) { max= temp; count = 0; } if (temp == max) count += max; // we count the number of polys } A[varlevel]= max; C[varlevel]= count; return max; } // the minimal non-zero degree of polys in PS wrt. x // returns 0 if variable x doesn't occure in any of the polys int degpsmin (const CFList & PS, const Variable & x, Intarray & A, Intarray & B, Intarray & C, Intarray & D) { int varlevel= level(x); if (B[varlevel] != __ARRAY_INIT__ ) return B[varlevel]; int min= degpsmax (PS, x, A, C), temp, count= 0; if (min == 0) { B[varlevel]= min; D[varlevel]= min; return min; } else { for (CFListIterator i= PS; i.hasItem(); i++) { temp= degree (i.getItem(), x); if (temp < min && temp != 0) { min= temp; count= 0; } if (temp == min) count += min; // we count the number of polys } } B[varlevel]= min; D[varlevel]= count; return min; } // the minimal total degree of lcoeffs of polys in PS wrt. x // for those polys having degree degpsmin in x. // F will be assigned the minimal number of terms of those lcoeffs int Tdeg (const CFList & PS, const Variable & x, Intarray & A, Intarray & B, Intarray & C, Intarray & D, Intarray & E, Intarray & F) { int k= degpsmin (PS, x, A, B, C, D), varlevel= level(x), min= 0; if (E[varlevel] != __ARRAY_INIT__) return E [varlevel]; if (k == 0) { E[varlevel]= 0; F[varlevel]= 0; } else { int nopslc= 0; CFList LCdegList; CanonicalForm elem; CFListIterator i; for (i= PS; i.hasItem(); i++) { elem= i.getItem(); if (degree (elem, x) == k) LCdegList.append (LC (elem, x)); } if (LCdegList.length() > 0) { CFList TermList; int newmin, newnopslc; min= totaldegree (LCdegList.getFirst()); TermList= get_Terms (LCdegList.getFirst()); nopslc= TermList.length(); for (i= LCdegList; i.hasItem(); i++) { elem= i.getItem(); newmin= totaldegree(elem); TermList= get_Terms(elem); newnopslc= TermList.length(); if (newmin < min) min= newmin; if (newnopslc < nopslc) nopslc= newnopslc; } } E[varlevel]= min; F[varlevel]= nopslc; } return min; } // The number of the poly in which Variable x first occures int nr_of_poly( const CFList & PS, const Variable & x, Intarray & G) { int min= 0, varlevel= level(x); if (G[varlevel] != __ARRAY_INIT__) return G[varlevel]; for (CFListIterator i= PS; i.hasItem(); i++) { min += 1; if (degree (i.getItem(), x) > 0) break; } G[varlevel]= min; return min; } int degord (const Variable & x, const Variable & y, const CFList & PS, Intarray & A, Intarray & B, Intarray & C, Intarray & D, Intarray & E, Intarray & F, Intarray & G) { int xlevel= level(x), ylevel= level(y); if (degpsmax(PS,y,A,C) < degpsmax(PS,x,A,C)) return 1; else if (degpsmax(PS,x,A,C) < degpsmax(PS,y,A,C) ) return 0; else if (C[ylevel] < C[xlevel]) return 1; else if (C[xlevel] < C[ylevel]) return 0; else if (degpsmin(PS,x,A,B,C,D) < degpsmin(PS,y,A,B,C,D)) return 1; else if (degpsmin(PS,y,A,B,C,D) < degpsmin(PS,x,A,B,C,D)) return 0; else if (D[ylevel] < D[xlevel]) return 1; else if (D[xlevel] < D[ylevel]) return 0; else if (Tdeg(PS,y,A,B,C,D,E,F) < Tdeg(PS,x,A,B,C,D,E,F)) return 1; else if (Tdeg(PS,x,A,B,C,D,E,F) < Tdeg(PS,y,A,B,C,D,E,F)) return 0; else if (F[ylevel] < F[xlevel]) return 1; else if (F[xlevel] < F[ylevel]) return 0; else if (nr_of_poly(PS,x,G) <= nr_of_poly(PS,y,G)) return 1; else return 0; } // determine the highest variable of all involved Variables in PS // NOTE: // this doesn't give always the correct answer: // If a variable is assigned the highest level in the definition of the // original ring, but doesn't occure in any of the // polynomials, get_max_var returns the variable with a level lower than // the highest level. // Is there a workaround? // But for the redefinition of the ring this doesn't matter due to the // implementation of neworder(). Variable get_max_var (const CFList & PS) { Variable x= PS.getFirst().mvar(), y; for (CFListIterator i= PS; i.hasItem(); i++) { y= i.getItem().mvar(); if (y > x) x= y; } return x; } // determine if variable x is in one and only one of the polynomials in PS // first criterion for neworder CFList only_in_one (const CFList & PS, const Variable & x) { CFList output; for (CFListIterator i= PS; i.hasItem(); i++ ) { if (degree (i.getItem(), x) >= 1) output.insert (i.getItem()); if (output.length() >= 2) break; } return output; } // initialize all Arrays (of same range) with __ARRAY_INIT__ void initArray (const int highest_level, Intarray & A, Intarray & B, Intarray & C, Intarray & D, Intarray & E, Intarray & F, Intarray & G) { for (int i=1 ; i <= highest_level; i ++) { A[i]= __ARRAY_INIT__; B[i]= __ARRAY_INIT__; C[i]= __ARRAY_INIT__; D[i]= __ARRAY_INIT__; E[i]= __ARRAY_INIT__; F[i]= __ARRAY_INIT__; G[i]= __ARRAY_INIT__; } } // now for the second criterion; a little more complex // // idea: set up seven arrays of lenth highest_level // (of which some entries may be empty, because of only_in_one!) // A saves maxdegree of Variable x in A(level(x)) // B saves mindegree of Variable x in B(level(x)) // C saves the number of polys in PS which have degree A(level(x)) in // D(level(x)) // D saves the number of polys in PS which have degree B(level(x)) in // D(level(x)) // E saves the minimal total degree of lcoeffs of polys wrt x in E(level(x)) // F saves the minimal number of terms of lcoeffs of E(level(x)) in F(~) // G saves nr of poly Variable x has first deg <> 0 #define __INIT_GAP__ 3 Varlist reorderb (const Varlist & difference, const CFList & PS, const int highest_level) { Intarray A(1, highest_level), B(1, highest_level), C(1, highest_level), D(1, highest_level), E(1, highest_level), F(1, highest_level), G(1, highest_level); initArray (highest_level, A, B, C, D, E, F, G); int i= 0, j, n= difference.length(), gap= 1 + __INIT_GAP__; Variable temp; Array v(0, n); VarlistIterator J; for (J= difference; J.hasItem(); J++ ) { v[i]= J.getItem(); i++; } while (gap <= n) gap = __INIT_GAP__ * gap + 1; gap /= __INIT_GAP__; while (gap > 0) { for (i= gap; i <= n - 1; i++) { temp= v[i]; for (j= i - gap; j >=0 ; j -= gap) { if (degord (v[j], temp, PS, A, B, C, D, E, F, G)) break; v[j + gap]= v[j]; } v[j + gap]= temp; } gap /= __INIT_GAP__; } Varlist output; for (i= 0; i <= n - 1; i++) output.append (v[i]); return output; } /// swapvar a whole list of CanonicalForms CFList swapvar (const CFList & PS, const Variable & x, const Variable & y) { CFList ps; for (CFListIterator i= PS; i.hasItem(); i++) ps.append (swapvar (i.getItem(), x, y)); return ps; } CFFList swapvar (const CFFList & PS, const Variable & x, const Variable & y) { CFFList ps; for (CFFListIterator i= PS; i.hasItem(); i++) ps.append (CFFactor (swapvar (i.getItem().factor(), x, y), i.getItem().exp())); return ps; } bool lowerRank (const CanonicalForm & F, const CanonicalForm & G, int & ind) { int degF, degG, levelF, levelG; levelF= F.level(); levelG= G.level(); if (F.inCoeffDomain()) { if (G.inCoeffDomain()) ind= 1; return true; } else if (G.inCoeffDomain()) return false; else if (levelF < levelG) return true; else if (levelF == levelG) { degF= degree(F); degG= degree(G); if (degF < degG) return true; else if (degF == degG) return lowerRank (LC (F), LC (G), ind); else return false; } return false; } CanonicalForm lowestRank (const CFList & L) { CFListIterator i= L; CanonicalForm f; int ind= 0; if (!i.hasItem()) return f; f= i.getItem(); i++; while (i.hasItem()) { if (lowerRank (i.getItem(), f, ind)) { if (ind) { if (size (i.getItem()) < size (f)) f= i.getItem(); ind= 0; } else f= i.getItem(); } i++; } return f; } int minLevel (const CFList& L) { if (L.isEmpty()) return 0; int min= size (L.getFirst()); return min; } /// sort in descending order of length of elements void sortListCFList (ListCFList& list) { int l= 1; int k= 1; CFList buf; ListCFListIterator m; for (ListCFListIterator i= list; l <= list.length(); i++, l++) { for (ListCFListIterator j= list; k <= list.length() - l; k++) { m= j; m++; if ((j.getItem().length() < m.getItem().length()) || (j.getItem().length() == m.getItem().length() && minLevel (j.getItem()) > minLevel (m.getItem()))) { buf= m.getItem(); m.getItem()= j.getItem(); j.getItem()= buf; j++; j.getItem()= m.getItem(); } else j++; } k= 1; } } /// sort in descending order of level of elements void sortCFListByLevel (CFList& list) { int l= 1; int k= 1; CanonicalForm buf; CFListIterator m; for (CFListIterator i= list; l <= list.length(); i++, l++) { for (CFListIterator j= list; k <= list.length() - l; k++) { m= j; m++; if ((size (j.getItem()) < size (m.getItem())) || ((size (j.getItem()) == size (m.getItem())) && (j.getItem().level() < m.getItem().level()))) { buf= m.getItem(); m.getItem()= j.getItem(); j.getItem()= buf; j++; j.getItem()= m.getItem(); } else j++; } k= 1; } } /* basic operations on lists */ /// is PS a subset of Cset ? bool isSubset (const CFList &PS, const CFList& Cset) { for (CFListIterator i= PS; i.hasItem(); i++) { if (!find (Cset, i.getItem())) return 0; } return 1; } /// Union of a and b stored in b void inplaceUnion (const ListCFList& a, ListCFList& b) { if (a.isEmpty()) return; if (b.isEmpty()) { b= a; return; } ListCFListIterator i; CFList elem; for (i= a; i.hasItem(); i++) { elem= i.getItem(); if ((!elem.isEmpty()) && (!find (b, elem))) b.insert(elem); } } ListCFList adjoin (const CFList& is, const CFList& qs, const ListCFList& qh) { ListCFList iss, qhi; ListCFListIterator j; CFList iscopy, itt; CFListIterator i; int ind, length; for (i= is; i.hasItem(); i++) { if (i.getItem().level() > 0) iscopy= Union (CFList (i.getItem()), iscopy); } if (iscopy.isEmpty()) return iss; qhi= Difference (qh, qs); length= qhi.length(); for (i= iscopy; i.hasItem(); i++) { itt= Union (qs, CFList (i.getItem())); ind= 0; if (length > 0) { for (j= qhi; j.hasItem(); j++) { if (isSubset (j.getItem(), itt)) ind= 1; } } if (ind == 0) iss.append (itt); } return iss; } ListCFList adjoinb (const CFList & is, const CFList & qs, const ListCFList & qh, const CFList & cs) { ListCFList iss, qhi; ListCFListIterator j; CFList iscopy, itt; CFListIterator i; int ind, length; for (i= is ; i.hasItem(); i++) { if (i.getItem().level() > 0) iscopy= Union (CFList (i.getItem()), iscopy); } if (iscopy.isEmpty()) return iss; qhi= Difference (qh, qs); length= qhi.length(); for (i= iscopy; i.hasItem(); i++) { itt= Union (Union (qs, CFList (i.getItem())), cs); ind= 0; if (length > 0) { for (j= qhi; j.hasItem(); j++) { if (isSubset (j.getItem(), itt)) ind= 1; } } if (ind == 0) iss.append(itt); } return iss; } void select (const ListCFList& ppi, int length, ListCFList& ppi1, ListCFList& ppi2) { CFList elem; for (ListCFListIterator i= ppi; i.hasItem(); i++) { elem= i.getItem(); if (!elem.isEmpty()) { if (length <= elem.length()) ppi2.append(elem); else ppi1.append(elem); } } } /* end basic operations on lists */ /// normalize a poly, i.e. in char 0 clear denominators, remove integer content /// in char p divide by leading coeff CanonicalForm normalize (const CanonicalForm& F) { if (F.isZero()) return F; if (getCharacteristic() == 0) { CanonicalForm G; bool isRat= isOn (SW_RATIONAL); if (!isRat) On (SW_RATIONAL); G= F; G *= bCommonDen (G); Off (SW_RATIONAL); G /= icontent (G); if (isRat) On (SW_RATIONAL); if (lc(G) < 0) G= -G; return G; } return F/lc (F); } /// pseudo remainder of F by G with certain factors of LC (g) cancelled CanonicalForm Prem (const CanonicalForm& F, const CanonicalForm& G) { CanonicalForm f, g, l, test, lu, lv, t, retvalue; int degF, degG, levelF, levelG; bool reord; Variable v, vg= G.mvar(); if ( (levelF= F.level()) < (levelG= G.level())) return F; else { if ( levelF == levelG ) { f= F; g= G; reord= false; v= F.mvar(); } else { v= Variable (levelF + 1); f= swapvar (F, vg, v); g= swapvar (G, vg, v); reord= true; } degG= degree (g, v ); degF= degree (f, v ); if (degG <= degF) { l= LC (g); g= g - l*power (v, degG); } else l= 1; while ((degG <= degF) && (!f.isZero())) { test= gcd (l, LC(f)); lu= l / test; lv= LC(f) / test; t= g*lv*power (v, degF - degG); if (degF == 0) f= 0; else f= f - LC (f)*power (v, degF); f= f*lu - t; degF= degree (f, v); } if (reord) retvalue= swapvar (f, vg, v); else retvalue= f; return retvalue; } } /// pseudo remainder of f by L with faster test for remainder being zero CanonicalForm Premb (const CanonicalForm &f, const CFList &L) { CanonicalForm rem= f; CFList l= L; l.removeFirst(); CFListIterator i= l; for (i.lastItem(); i.hasItem(); i--) rem= normalize (Prem (rem, i.getItem())); CanonicalForm tmp= L.getFirst()/content (L.getFirst()); bool isRat= isOn (SW_RATIONAL); if (getCharacteristic() == 0 && !isRat) On (SW_RATIONAL); if (fdivides (tmp, rem)) { if (getCharacteristic() == 0 && !isRat) Off (SW_RATIONAL); return 0; } if (getCharacteristic() == 0 && !isRat) Off (SW_RATIONAL); rem= normalize (Prem (rem, L.getFirst())); return rem; } /// pseudo remainder of f by L CanonicalForm Prem (const CanonicalForm &f, const CFList &L) { CanonicalForm rem= f; CFListIterator i= L; for (i.lastItem(); i.hasItem(); i--) rem= normalize (Prem (rem, i.getItem())); return rem; } CFList uniGcd (const CFList& L) { CFList tmp; CanonicalForm g; CFListIterator i; for (i= L; i.hasItem(); i++) { if (i.getItem().isUnivariate() && i.getItem().level() == 1) tmp.append (i.getItem()); } if (tmp.length() <= 2) return L; i= tmp; g= i.getItem(); i++; g= gcd (g,i.getItem()); i++; for (; i.hasItem(); i++) g= gcd (g, i.getItem()); return Union (Difference (L, tmp), CFList (g)); } CFList initials (const CFList& L) { CFList result; for (CFListIterator iter= L; iter.hasItem(); iter++) { if (!LC(iter.getItem()).inCoeffDomain()) result.append (LC (iter.getItem())); } return result; } CFList factorsOfInitials(const CFList & L) { CFList result; CFFList factors; CanonicalForm tmp; for (CFListIterator i= L; i.hasItem(); i++) { factors= factorize (LC (i.getItem())); for (CFFListIterator j= factors; j.hasItem(); j++) { tmp= j.getItem().factor(); if (!tmp.inCoeffDomain()) result= Union (result, CFList (normalize (tmp))); } } return result; } void removeContent (CanonicalForm& F, CanonicalForm& cF) { if (size (F) == 1) { CanonicalForm tmp= F; F= F.mvar(); cF= tmp/F; if (!cF.inCoeffDomain()) cF= normalize (cF); else cF= 0; F= normalize (F); return; } cF= content (F); if (cF.inCoeffDomain()) cF= 0; else { cF= normalize (cF); F /= cF; F= normalize (F); } } CFList factorPSet (const CFList& PS) { CFList result; CFFList factors; CFFListIterator j; for (CFListIterator i= PS; i. hasItem(); i++) { factors= factorize (i.getItem()); if (factors.getFirst().factor().inCoeffDomain()) factors.removeFirst(); for (j= factors; j.hasItem(); j++ ) result= Union (result, CFList (normalize (j.getItem().factor()))); } return result; } void removeFactors (CanonicalForm& r, StoreFactors& StoredFactors, CFList& removedFactors) { CanonicalForm quot; CFList testlist; int n= level(r); bool divides; CFListIterator j; for (int i=1; i<= n; i++) testlist.append (CanonicalForm (Variable (i))); // remove already removed factors for (j= StoredFactors.FS1; j.hasItem(); j++) { while (fdivides (j.getItem(), r, quot)) { r= quot; } } for (j= StoredFactors.FS2; j.hasItem(); j++) { divides= false; if (j.getItem() != r) { while (fdivides (j.getItem(), r, quot)) { divides= true; r= quot; } if (divides) removedFactors= Union (removedFactors, CFList (j.getItem())); } } r= normalize (r); // remove variables for (j= testlist; j.hasItem() && !r.isOne(); j++) { divides= false; if (j.getItem() != r) { while (fdivides (j.getItem(), r, quot)) { divides= true; r= quot; } if (divides) removedFactors= Union (removedFactors, CFList (j.getItem())); } } r= normalize (r); } CFList removeContent (const CFList & PS, StoreFactors & StoredFactors) { CFListIterator i= PS; if ((!i.hasItem()) || (PS.getFirst().level() == 0 )) return PS; CFList output; CanonicalForm cc,elem; for (; i.hasItem(); i++) { elem= i.getItem(); cc= content (elem, elem.mvar()); if (cc.level() > 0 ) { output.append (normalize (elem / cc)); StoredFactors.FS1 = Union (CFList (normalize (cc)), StoredFactors.FS1); } else output.append(normalize (elem)); } return output; } bool contractsub (const CFList& cs1, const CFList& cs2) { CFListIterator i; CanonicalForm r; for (i= cs1; i.hasItem(); i++) { if (Prem (i.getItem(), cs2) != 0) return false; } CFList is= factorsOfInitials (cs1); for (i= is; i.hasItem(); i++) { if (Prem (i.getItem(), cs2) == 0) return false; } return true; } ListCFList contract (const ListCFList& cs) { ListCFList mem, ts; CFList iitem, jitem; if (cs.length() < 2) return cs; int l= cs.length(); int ii= 1; ListCFListIterator j; for (ListCFListIterator i= cs; i.hasItem() && ii < l; i++, ii++) { iitem= i.getItem(); if (!find (mem, iitem)) { j= i; j++; for (; j.hasItem(); j++) { jitem= j.getItem(); if (!find (mem, jitem)) { if (contractsub (iitem, jitem)) { ts.append (jitem); mem.append (jitem); } else { if (contractsub (jitem, iitem)) ts.append (iitem); // no mem.append (item) because we assume cs does not contain duplicate entries } } } } } return Difference (cs,ts); } singular-4.0.3+ds/factory/cfCharSetsUtil.h000066400000000000000000000055071266270727000204670ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfCharSetsUtil.h * * This file provides utility functions to compute characteristic sets * * @note some of the code is code from libfac or derived from code from libfac. * Libfac is written by M. Messollen. See also COPYING for license information * and README for general information on characteristic sets. * * ABSTRACT: Descriptions can be found in Wang "On the Parallelization of * characteristic-set based algorithms" or Greuel/Pfister "A Singular * Introduction to Commutative Algebra". * * @author Martin Lee * **/ /*****************************************************************************/ #ifndef CF_CHARSETS_UTIL #define CF_CHARSETS_UTIL /*BEGINPUBLIC*/ /** * class to store factors that get removed during char set computation **/ class StoreFactors { public: CFList FS1; ///< factors that were removed CFList FS2; ///< candidate factors that might get removed inline StoreFactors& operator= (const StoreFactors& value) { if ( this != &value ) { FS1 = value.FS1; FS2 = value.FS2; } return *this; } }; /*ENDPUBLIC*/ Variable get_max_var (const CFList & PS); CFList only_in_one (const CFList & PS, const Variable & x); Varlist reorderb (const Varlist & difference, const CFList & PS, const int highest_level); CFList swapvar (const CFList & PS, const Variable & x, const Variable & y); CFFList swapvar (const CFFList & PS, const Variable & x, const Variable & y); CanonicalForm lowestRank (const CFList & L); CFList initials (const CFList& L); void sortListCFList (ListCFList& list); void sortCFListByLevel (CFList& list); CanonicalForm Prem (const CanonicalForm& F, const CanonicalForm& G); CanonicalForm Premb (const CanonicalForm &f, const CFList &L); CanonicalForm Prem (const CanonicalForm &f, const CFList &L); CFList uniGcd (const CFList& L); CFList factorsOfInitials(const CFList & L); void removeContent (CanonicalForm& F, CanonicalForm& cF); CFList factorPSet (const CFList& PS); void removeFactors (CanonicalForm& r, StoreFactors& StoredFactors, CFList& removedFactors); CFList removeContent (const CFList & PS, StoreFactors & StoredFactors); ListCFList contract (const ListCFList& cs); bool isSubset (const CFList &PS, const CFList& Cset); ListCFList adjoin (const CFList& is, const CFList& qs, const ListCFList& qh); ListCFList adjoinb (const CFList & is, const CFList & qs, const ListCFList & qh, const CFList & cs); void inplaceUnion (const ListCFList& a, ListCFList& b); void select (const ListCFList& ppi, int length, ListCFList& ppi1, ListCFList& ppi2); CanonicalForm normalize (const CanonicalForm& F); #endif singular-4.0.3+ds/factory/cfEzgcd.cc000066400000000000000000001042561266270727000173100ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfEzgcd.cc * * This file implements the GCD of two multivariate polynomials over Q or F_q * using EZ-GCD as described in "Algorithms for Computer Algebra" by Geddes, * Czapor, Labahnn * * @author Martin Lee * **/ /*****************************************************************************/ #include "config.h" #include "timing.h" #include "cf_assert.h" #include "debug.h" #include "cf_defs.h" #include "canonicalform.h" #include "cfEzgcd.h" #include "cfModGcd.h" #include "cf_util.h" #include "cf_map_ext.h" #include "cf_algorithm.h" #include "cf_reval.h" #include "cf_random.h" #include "cf_primes.h" #include "templates/ftmpl_functions.h" #include "cf_map.h" #include "facHensel.h" #ifdef HAVE_NTL #include "NTLconvert.h" static const double log2exp= 1.442695041; TIMING_DEFINE_PRINT(ez_eval) TIMING_DEFINE_PRINT(ez_compress) TIMING_DEFINE_PRINT(ez_hensel_lift) TIMING_DEFINE_PRINT(ez_content) TIMING_DEFINE_PRINT(ez_termination) static int compress4EZGCD (const CanonicalForm& F, const CanonicalForm& G, CFMap & M, CFMap & N, int& both_non_zero) { int n= tmax (F.level(), G.level()); int * degsf= new int [n + 1]; int * degsg= new int [n + 1]; for (int i = 0; i <= n; i++) degsf[i]= degsg[i]= 0; degsf= degrees (F, degsf); degsg= degrees (G, degsg); both_non_zero= 0; int f_zero= 0; int g_zero= 0; for (int i= 1; i <= n; i++) { if (degsf[i] != 0 && degsg[i] != 0) { both_non_zero++; continue; } if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level()) { f_zero++; continue; } if (degsg[i] == 0 && degsf[i] && i <= F.level()) { g_zero++; continue; } } if (both_non_zero == 0) { delete [] degsf; delete [] degsg; return 0; } // map Variables which do not occur in both polynomials to higher levels int k= 1; int l= 1; for (int i= 1; i <= n; i++) { if (degsf[i] != 0 && degsg[i] == 0 && i <= F.level()) { if (k + both_non_zero != i) { M.newpair (Variable (i), Variable (k + both_non_zero)); N.newpair (Variable (k + both_non_zero), Variable (i)); } k++; } if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level()) { if (l + g_zero + both_non_zero != i) { M.newpair (Variable (i), Variable (l + g_zero + both_non_zero)); N.newpair (Variable (l + g_zero + both_non_zero), Variable (i)); } l++; } } // sort Variables x_{i} in decreasing order of // min(deg_{x_{i}}(f),deg_{x_{i}}(g)) int m= tmin (F.level(), G.level()); int max_min_deg; k= both_non_zero; l= 0; int i= 1; while (k > 0) { max_min_deg= tmin (degsf[i], degsg[i]); while (max_min_deg == 0) { i++; max_min_deg= tmin (degsf[i], degsg[i]); } for (int j= i + 1; j <= m; j++) { if ((tmin (degsf[j],degsg[j]) < max_min_deg) && (tmin (degsf[j], degsg[j]) != 0)) { max_min_deg= tmin (degsf[j], degsg[j]); l= j; } } if (l != 0) { if (l != k) { M.newpair (Variable (l), Variable(k)); N.newpair (Variable (k), Variable(l)); degsf[l]= 0; degsg[l]= 0; l= 0; } else { degsf[l]= 0; degsg[l]= 0; l= 0; } } else if (l == 0) { if (i != k) { M.newpair (Variable (i), Variable (k)); N.newpair (Variable (k), Variable (i)); degsf[i]= 0; degsg[i]= 0; } else { degsf[i]= 0; degsg[i]= 0; } i++; } k--; } delete [] degsf; delete [] degsg; return both_non_zero; } static inline CanonicalForm myShift2Zero (const CanonicalForm& F, CFList& Feval, const CFList& evaluation) { CanonicalForm A= F; int k= 2; for (CFListIterator i= evaluation; i.hasItem(); i++, k++) A= A (Variable (k) + i.getItem(), k); CanonicalForm buf= A; Feval= CFList(); Feval.append (buf); for (k= evaluation.length() + 1; k > 2; k--) { buf= mod (buf, Variable (k)); Feval.insert (buf); } return A; } static inline CanonicalForm myReverseShift (const CanonicalForm& F, const CFList& evaluation) { int l= evaluation.length() + 1; CanonicalForm result= F; CFListIterator j= evaluation; for (int i= 2; i < l + 1; i++, j++) { if (F.level() < i) continue; result= result (Variable (i) - j.getItem(), i); } return result; } static inline Evaluation optimize4Lift (const CanonicalForm& F, CFMap & M, CFMap & N, const Evaluation& A) { int n= F.level(); int * degsf= new int [n + 1]; for (int i = 0; i <= n; i++) degsf[i]= 0; degsf= degrees (F, degsf); Evaluation result= Evaluation (A.min(), A.max()); ASSERT (A.min() == 2, "expected A.min() == 2"); int max_deg; int k= n; int l= 1; int i= 2; int pos= 2; while (k > 1) { max_deg= degsf [i]; while (max_deg == 0) { i++; max_deg= degsf [i]; } l= i; for (int j= i + 1; j <= n; j++) { if (degsf[j] > max_deg) { max_deg= degsf[j]; l= j; } } if (l <= n) { if (l != pos) { result.setValue (pos, A [l]); M.newpair (Variable (l), Variable (pos)); N.newpair (Variable (pos), Variable (l)); degsf[l]= 0; l= 2; if (k == 2 && n == 3) { result.setValue (l, A [pos]); M.newpair (Variable (pos), Variable (l)); N.newpair (Variable (l), Variable (pos)); degsf[pos]= 0; } } else { result.setValue (l, A [l]); degsf [l]= 0; } } pos++; k--; l= 2; } delete [] degsf; return result; } static inline int Hensel (const CanonicalForm & UU, CFArray & G, const Evaluation & AA, const CFArray& LeadCoeffs ) { CFList factors; factors.append (G[1]); factors.append (G[2]); CFMap NN, MM; Evaluation A= optimize4Lift (UU, MM, NN, AA); CanonicalForm U= MM (UU); CFArray LCs= CFArray (1,2); LCs [1]= MM (LeadCoeffs [1]); LCs [2]= MM (LeadCoeffs [2]); CFList evaluation; long termEstimate= size (U); for (int i= A.min(); i <= A.max(); i++) { if (!A[i].isZero() && ((getCharacteristic() > degree (U,i)) || getCharacteristic() == 0)) { termEstimate *= degree (U,i)*2; termEstimate /= 3; } evaluation.append (A [i]); } if (termEstimate/getNumVars(U) > 500) return -1; CFList UEval; CanonicalForm shiftedU= myShift2Zero (U, UEval, evaluation); if (size (shiftedU)/getNumVars (U) > 500) return -1; CFArray shiftedLCs= CFArray (2); CFList shiftedLCsEval1, shiftedLCsEval2; shiftedLCs[0]= myShift2Zero (LCs[1], shiftedLCsEval1, evaluation); shiftedLCs[1]= myShift2Zero (LCs[2], shiftedLCsEval2, evaluation); factors.insert (1); int liftBound= degree (UEval.getLast(), 2) + 1; CFArray Pi; CFMatrix M= CFMatrix (liftBound, factors.length() - 1); CFList diophant; CFArray lcs= CFArray (2); lcs [0]= shiftedLCsEval1.getFirst(); lcs [1]= shiftedLCsEval2.getFirst(); nonMonicHenselLift12 (UEval.getFirst(), factors, liftBound, Pi, diophant, M, lcs, false); for (CFListIterator i= factors; i.hasItem(); i++) { if (!fdivides (i.getItem(), UEval.getFirst())) return 0; } int * liftBounds; bool noOneToOne= false; if (U.level() > 2) { liftBounds= new int [U.level() - 1]; /* index: 0.. U.level()-2 */ liftBounds[0]= liftBound; for (int i= 1; i < U.level() - 1; i++) liftBounds[i]= degree (shiftedU, Variable (i + 2)) + 1; factors= nonMonicHenselLift2 (UEval, factors, liftBounds, U.level() - 1, false, shiftedLCsEval1, shiftedLCsEval2, Pi, diophant, noOneToOne); delete [] liftBounds; if (noOneToOne) return 0; } G[1]= factors.getFirst(); G[2]= factors.getLast(); G[1]= myReverseShift (G[1], evaluation); G[2]= myReverseShift (G[2], evaluation); G[1]= NN (G[1]); G[2]= NN (G[2]); return 1; } static bool findeval (const CanonicalForm & F, const CanonicalForm & G, CanonicalForm & Fb, CanonicalForm & Gb, CanonicalForm & Db, REvaluation & b, int delta, int degF, int degG, int maxeval, int & count, int& k, int bound, int& l) { if( count == 0 && delta != 0) { if( count++ > maxeval ) return false; } if (count > 0) { b.nextpoint(k); if (k == 0) k++; l++; if (l > bound) { l= 1; k++; if (k > tmax (F.level(), G.level()) - 1) return false; b.nextpoint (k); } if (count++ > maxeval) return false; } while( true ) { Fb = b( F ); if( degree( Fb, 1 ) == degF ) { Gb = b( G ); if( degree( Gb, 1 ) == degG ) { Db = gcd( Fb, Gb ); if( delta > 0 ) { if( degree( Db, 1 ) <= delta ) return true; } else { k++; return true; } } } if (k == 0) k++; b.nextpoint(k); l++; if (l > bound) { l= 1; k++; if (k > tmax (F.level(), G.level()) - 1) return false; b.nextpoint (k); } if( count++ > maxeval ) return false; } } /// real implementation of EZGCD over Z static CanonicalForm ezgcd ( const CanonicalForm & FF, const CanonicalForm & GG, REvaluation & b, bool internal ) { bool isRat= isOn (SW_RATIONAL); int maxNumVars= tmax (getNumVars (FF), getNumVars (GG)); int sizeF= size (FF); int sizeG= size (GG); if (!isRat) On (SW_RATIONAL); if (sizeF/maxNumVars > 500 && sizeG/maxNumVars > 500) { Off(SW_USE_EZGCD); CanonicalForm result=gcd( FF, GG ); On(SW_USE_EZGCD); if (!isRat) Off (SW_RATIONAL); result /= icontent (result); DEBDECLEVEL( cerr, "ezgcd" ); return result; } CanonicalForm F, G, f, g, d, Fb, Gb, Db, Fbt, Gbt, Dbt, B0, B, D0, lcF, lcG, lcD, cand, contcand, result; CFArray DD( 1, 2 ), lcDD( 1, 2 ); int degF, degG, delta, t, count, maxeval; REvaluation bt; int gcdfound = 0; Variable x = Variable(1); count= 0; maxeval= 200; int o, l; o= 0; l= 1; if (!isRat) On (SW_RATIONAL); F= FF*bCommonDen (FF); G= GG*bCommonDen (GG); if (!isRat) Off (SW_RATIONAL); TIMING_START (ez_compress) CFMap M,N; int smallestDegLev; int best_level= compress4EZGCD (F, G, M, N, smallestDegLev); if (best_level == 0) { DEBDECLEVEL( cerr, "ezgcd" ); return G.genOne(); } F= M (F); G= M (G); TIMING_END_AND_PRINT (ez_compress, "time for compression in EZ: ") DEBINCLEVEL( cerr, "ezgcd" ); DEBOUTLN( cerr, "FF = " << FF ); DEBOUTLN( cerr, "GG = " << GG ); TIMING_START (ez_content) f = content( F, x ); g = content( G, x ); d = gcd( f, g ); DEBOUTLN( cerr, "f = " << f ); DEBOUTLN( cerr, "g = " << g ); F /= f; G /= g; TIMING_END_AND_PRINT (ez_content, "time to extract content in EZ: ") if ( F.isUnivariate() && G.isUnivariate() ) { DEBDECLEVEL( cerr, "ezgcd" ); if(F.mvar()==G.mvar()) d*=gcd(F,G); else return N (d); return N (d); } if ( F.isUnivariate()) { g= content (G,G.mvar()); return N(d*gcd(F,g)); } if ( G.isUnivariate()) { f= content (F,F.mvar()); return N(d*gcd(G,f)); } maxNumVars= tmax (getNumVars (F), getNumVars (G)); sizeF= size (F); sizeG= size (G); if (!isRat) On (SW_RATIONAL); if (sizeF/maxNumVars > 500 && sizeG/maxNumVars > 500) { Off(SW_USE_EZGCD); result=gcd( F, G ); On(SW_USE_EZGCD); if (!isRat) Off (SW_RATIONAL); result /= icontent (result); DEBDECLEVEL( cerr, "ezgcd" ); return N (d*result); } int dummy= 0; if ( gcd_test_one( F, G, false, dummy ) ) { DEBDECLEVEL( cerr, "ezgcd" ); if (!isRat) Off (SW_RATIONAL); return N (d); } lcF = LC( F, x ); lcG = LC( G, x ); lcD = gcd( lcF, lcG ); delta = 0; degF = degree( F, x ); degG = degree( G, x ); t = tmax( F.level(), G.level() ); if ( ! internal ) b = REvaluation( 2, t, IntRandom( 25 ) ); while ( ! gcdfound ) { /// ---> A2 DEBOUTLN( cerr, "search for evaluation, delta = " << delta ); DEBOUTLN( cerr, "F = " << F ); DEBOUTLN( cerr, "G = " << G ); TIMING_START (ez_eval) if (!findeval( F, G, Fb, Gb, Db, b, delta, degF, degG, maxeval, count, o, 25, l)) { Off(SW_USE_EZGCD); result=gcd( F, G ); On(SW_USE_EZGCD); if (!isRat) Off (SW_RATIONAL); DEBDECLEVEL( cerr, "ezgcd" ); result /= icontent (result); return N (d*result); } TIMING_END_AND_PRINT (ez_eval, "time to find eval point in EZ1: ") DEBOUTLN( cerr, "found evaluation b = " << b ); DEBOUTLN( cerr, "F(b) = " << Fb ); DEBOUTLN( cerr, "G(b) = " << Gb ); DEBOUTLN( cerr, "D(b) = " << Db ); delta = degree( Db ); /// ---> A3 if (delta == degF) { if (degF <= degG && fdivides (F, G)) { DEBDECLEVEL( cerr, "ezgcd" ); if (!isRat) Off (SW_RATIONAL); return N (d*F); } else delta--; } else if (delta == degG) { if (degG <= degF && fdivides( G, F )) { DEBDECLEVEL( cerr, "ezgcd" ); if (!isRat) Off (SW_RATIONAL); return N (d*G); } else delta--; } if ( delta == 0 ) { DEBDECLEVEL( cerr, "ezgcd" ); if (!isRat) Off (SW_RATIONAL); return N (d); } /// ---> A4 //deltaold = delta; while ( 1 ) { bt = b; TIMING_START (ez_eval) if (!findeval( F, G, Fbt, Gbt, Dbt, bt, delta, degF, degG, maxeval, count, o, 25,l )) { Off(SW_USE_EZGCD); result=gcd( F, G ); On(SW_USE_EZGCD); if (!isRat) Off (SW_RATIONAL); DEBDECLEVEL( cerr, "ezgcd" ); result /= icontent (result); return N (d*result); } TIMING_END_AND_PRINT (ez_eval, "time to find eval point in EZ2: ") int dd=degree( Dbt ); if ( dd /*degree( Dbt )*/ == 0 ) { DEBDECLEVEL( cerr, "ezgcd" ); if (!isRat) Off (SW_RATIONAL); return N (d); } if ( dd /*degree( Dbt )*/ == delta ) break; else if ( dd /*degree( Dbt )*/ < delta ) { delta = dd /*degree( Dbt )*/; b = bt; Db = Dbt; Fb = Fbt; Gb = Gbt; } DEBOUTLN( cerr, "now after A4, delta = " << delta ); /// ---> A5 if (delta == degF) { if (degF <= degG && fdivides (F, G)) { DEBDECLEVEL( cerr, "ezgcd" ); if (!isRat) Off (SW_RATIONAL); return N (d*F); } else delta--; } else if (delta == degG) { if (degG <= degF && fdivides( G, F )) { DEBDECLEVEL( cerr, "ezgcd" ); if (!isRat) Off (SW_RATIONAL); return N (d*G); } else delta--; } if ( delta == 0 ) { DEBDECLEVEL( cerr, "ezgcd" ); if (!isRat) Off (SW_RATIONAL); return N (d); } } if ( delta != degF && delta != degG ) { /// ---> A6 bool B_is_F; CanonicalForm xxx1, xxx2; CanonicalForm buf; DD[1] = Fb / Db; buf= Gb/Db; xxx1 = gcd( DD[1], Db ); xxx2 = gcd( buf, Db ); if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) && (size (F) <= size (G))) || (xxx1.inCoeffDomain() && !xxx2.inCoeffDomain())) { B = F; DD[2] = Db; lcDD[1] = lcF; lcDD[2] = lcD; B_is_F = true; } else if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) && (size (G) < size (F))) || (!xxx1.inCoeffDomain() && xxx2.inCoeffDomain())) { DD[1] = buf; B = G; DD[2] = Db; lcDD[1] = lcG; lcDD[2] = lcD; B_is_F = false; } else { //special case Off(SW_USE_EZGCD); result=gcd( F, G ); On(SW_USE_EZGCD); if (!isRat) Off (SW_RATIONAL); DEBDECLEVEL( cerr, "ezgcd" ); result /= icontent (result); return N (d*result); } /// ---> A7 DD[2] = DD[2] * ( b( lcDD[2] ) / lc( DD[2] ) ); DD[1] = DD[1] * ( b( lcDD[1] ) / lc( DD[1] ) ); DEBOUTLN( cerr, "(hensel) B = " << B ); DEBOUTLN( cerr, "(hensel) lcB = " << LC( B, Variable(1) ) ); DEBOUTLN( cerr, "(hensel) b(B) = " << b(B) ); DEBOUTLN( cerr, "(hensel) DD = " << DD ); DEBOUTLN( cerr, "(hensel) lcDD = " << lcDD ); TIMING_START (ez_hensel_lift) gcdfound= Hensel (B*lcD, DD, b, lcDD); TIMING_END_AND_PRINT (ez_hensel_lift, "time to hensel lift in EZ: ") DEBOUTLN( cerr, "(hensel finished) DD = " << DD ); if (gcdfound == -1) { Off (SW_USE_EZGCD); result= gcd (F,G); On (SW_USE_EZGCD); if (!isRat) Off (SW_RATIONAL); DEBDECLEVEL( cerr, "ezgcd" ); result /= icontent (result); return N (d*result); } if (gcdfound) { TIMING_START (ez_termination) contcand= content (DD[2], Variable (1)); cand = DD[2] / contcand; if (B_is_F) gcdfound = fdivides( cand, G ) && cand*(DD[1]/(lcD/contcand)) == F; else gcdfound = fdivides( cand, F ) && cand*(DD[1]/(lcD/contcand)) == G; TIMING_END_AND_PRINT (ez_termination, "time for termination test in EZ: ") } /// ---> A8 (gcdfound) } delta--; } /// ---> A9 DEBDECLEVEL( cerr, "ezgcd" ); cand *= bCommonDen (cand); if (!isRat) Off (SW_RATIONAL); cand /= icontent (cand); return N (d*cand); } #endif /// Extended Zassenhaus GCD over Z. /// In case things become too dense we switch to a modular algorithm. CanonicalForm ezgcd ( const CanonicalForm & FF, const CanonicalForm & GG ) { #ifdef HAVE_NTL REvaluation b; return ezgcd( FF, GG, b, false ); #else Off (SW_USE_EZGCD); return gcd (FF, GG); On (SW_USE_EZGCD); #endif } #ifdef HAVE_NTL // parameters for heuristic static int maxNumEval= 200; static int sizePerVars1= 500; //try dense gcd if size/#variables is bigger /// Extended Zassenhaus GCD for finite fields. /// In case things become too dense we switch to a modular algorithm. CanonicalForm EZGCD_P( const CanonicalForm & FF, const CanonicalForm & GG ) { if (FF.isZero() && degree(GG) > 0) return GG/Lc(GG); else if (GG.isZero() && degree (FF) > 0) return FF/Lc(FF); else if (FF.isZero() && GG.isZero()) return FF.genOne(); if (FF.inBaseDomain() || GG.inBaseDomain()) return FF.genOne(); if (FF.isUnivariate() && fdivides(FF, GG)) return FF/Lc(FF); if (GG.isUnivariate() && fdivides(GG, FF)) return GG/Lc(GG); if (FF == GG) return FF/Lc(FF); int maxNumVars= tmax (getNumVars (FF), getNumVars (GG)); Variable a, oldA; int sizeF= size (FF); int sizeG= size (GG); if (sizeF/maxNumVars > sizePerVars1 && sizeG/maxNumVars > sizePerVars1) { if (hasFirstAlgVar (FF, a) || hasFirstAlgVar (GG, a)) return modGCDFq (FF, GG, a); else if (CFFactory::gettype() == GaloisFieldDomain) return modGCDGF (FF, GG); else return modGCDFp (FF, GG); } CanonicalForm F, G, f, g, d, Fb, Gb, Db, Fbt, Gbt, Dbt, B0, B, D0, lcF, lcG, lcD; CFArray DD( 1, 2 ), lcDD( 1, 2 ); int degF, degG, delta, count; int maxeval; maxeval= tmin((getCharacteristic()/ (int)(ilog2(getCharacteristic())*log2exp))*2, maxNumEval); count= 0; // number of eval. used REvaluation b, bt; int gcdfound = 0; Variable x = Variable(1); F= FF; G= GG; CFMap M,N; int smallestDegLev; TIMING_START (ez_p_compress) int best_level= compress4EZGCD (F, G, M, N, smallestDegLev); if (best_level == 0) return G.genOne(); F= M (F); G= M (G); TIMING_END_AND_PRINT (ez_p_compress, "time for compression in EZ_P: ") TIMING_START (ez_p_content) f = content( F, x ); g = content( G, x ); d = gcd( f, g ); F /= f; G /= g; TIMING_END_AND_PRINT (ez_p_content, "time to extract content in EZ_P: ") if( F.isUnivariate() && G.isUnivariate() ) { if( F.mvar() == G.mvar() ) d *= gcd( F, G ); else return N (d); return N (d); } if ( F.isUnivariate()) { g= content (G,G.mvar()); return N(d*gcd(F,g)); } if ( G.isUnivariate()) { f= content (F,F.mvar()); return N(d*gcd(G,f)); } maxNumVars= tmax (getNumVars (F), getNumVars (G)); sizeF= size (F); sizeG= size (G); if (sizeF/maxNumVars > sizePerVars1 && sizeG/maxNumVars > sizePerVars1) { if (hasFirstAlgVar (F, a) || hasFirstAlgVar (G, a)) return N (d*modGCDFq (F, G, a)); else if (CFFactory::gettype() == GaloisFieldDomain) return N (d*modGCDGF (F, G)); else return N (d*modGCDFp (F, G)); } int dummy= 0; if( gcd_test_one( F, G, false, dummy ) ) { return N (d); } bool passToGF= false; bool extOfExt= false; int p= getCharacteristic(); bool algExtension= (hasFirstAlgVar(F,a) || hasFirstAlgVar(G,a)); int k= 1; CanonicalForm primElem, imPrimElem; CFList source, dest; if (p < 50 && CFFactory::gettype() != GaloisFieldDomain && !algExtension) { if (p == 2) setCharacteristic (2, 12, 'Z'); else if (p == 3) setCharacteristic (3, 4, 'Z'); else if (p == 5 || p == 7) setCharacteristic (p, 3, 'Z'); else setCharacteristic (p, 2, 'Z'); passToGF= true; F= F.mapinto(); G= G.mapinto(); maxeval= 2*ipower (p, getGFDegree()); } else if (CFFactory::gettype() == GaloisFieldDomain && ipower (p , getGFDegree()) < 50) { k= getGFDegree(); if (ipower (p, 2*k) > 50) setCharacteristic (p, 2*k, gf_name); else setCharacteristic (p, 3*k, gf_name); F= GFMapUp (F, k); G= GFMapUp (G, k); maxeval= tmin (2*ipower (p, getGFDegree()), maxNumEval); } else if (p < 50 && algExtension && CFFactory::gettype() != GaloisFieldDomain) { int d= degree (getMipo (a)); oldA= a; Variable v2; if (p == 2 && d < 6) { if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } bool primFail= false; Variable vBuf; primElem= primitiveElement (a, vBuf, primFail); ASSERT (!primFail, "failure in integer factorizer"); if (d < 3) { zz_pX NTLIrredpoly; BuildIrred (NTLIrredpoly, d*3); CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1)); v2= rootOf (newMipo); } else { zz_pX NTLIrredpoly; BuildIrred (NTLIrredpoly, d*2); CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1)); v2= rootOf (newMipo); } imPrimElem= mapPrimElem (primElem, a, v2); extOfExt= true; } else if ((p == 3 && d < 4) || ((p == 5 || p == 7) && d < 3)) { if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } bool primFail= false; Variable vBuf; primElem= primitiveElement (a, vBuf, primFail); ASSERT (!primFail, "failure in integer factorizer"); zz_pX NTLIrredpoly; BuildIrred (NTLIrredpoly, d*2); CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1)); v2= rootOf (newMipo); imPrimElem= mapPrimElem (primElem, a, v2); extOfExt= true; } if (extOfExt) { maxeval= tmin (2*ipower (p, degree (getMipo (v2))), maxNumEval); F= mapUp (F, a, v2, primElem, imPrimElem, source, dest); G= mapUp (G, a, v2, primElem, imPrimElem, source, dest); a= v2; } } lcF = LC( F, x ); lcG = LC( G, x ); lcD = gcd( lcF, lcG ); delta = 0; degF = degree( F, x ); degG = degree( G, x ); if (algExtension) b = REvaluation( 2, tmax(F.level(), G.level()), AlgExtRandomF( a ) ); else { // both not in extension given by algebraic variable if (CFFactory::gettype() != GaloisFieldDomain) b = REvaluation( 2, tmax(F.level(), G.level()), FFRandom() ); else b = REvaluation( 2, tmax(F.level(), G.level()), GFRandom() ); } CanonicalForm cand, contcand; CanonicalForm result; int o, t; o= 0; t= 1; int goodPointCount= 0; while( !gcdfound ) { TIMING_START (ez_p_eval); if( !findeval( F, G, Fb, Gb, Db, b, delta, degF, degG, maxeval, count, o, maxeval/maxNumVars, t )) { // too many eval. used --> try another method Off (SW_USE_EZGCD_P); result= gcd (F,G); On (SW_USE_EZGCD_P); if (passToGF) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); result= GF2FalphaRep (result, alpha); prune (alpha); } if (k > 1) { result= GFMapDown (result, k); setCharacteristic (p, k, gf_name); } if (extOfExt) { result= mapDown (result, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } return N (d*result); } TIMING_END_AND_PRINT (ez_p_eval, "time for eval point search in EZ_P1: "); delta = degree( Db ); if (delta == degF) { if (degF <= degG && fdivides (F, G)) { if (passToGF) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); F= GF2FalphaRep (F, alpha); prune (alpha); } if (k > 1) { F= GFMapDown (F, k); setCharacteristic (p, k, gf_name); } if (extOfExt) { F= mapDown (F, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } return N (d*F); } else delta--; } else if (delta == degG) { if (degG <= degF && fdivides (G, F)) { if (passToGF) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); G= GF2FalphaRep (G, alpha); prune (alpha); } if (k > 1) { G= GFMapDown (G, k); setCharacteristic (p, k, gf_name); } if (extOfExt) { G= mapDown (G, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } return N (d*G); } else delta--; } if( delta == 0 ) { if (passToGF) setCharacteristic (p); if (k > 1) setCharacteristic (p, k, gf_name); return N (d); } while( true ) { bt = b; TIMING_START (ez_p_eval); if( !findeval(F,G,Fbt,Gbt,Dbt, bt, delta, degF, degG, maxeval, count, o, maxeval/maxNumVars, t )) { // too many eval. used --> try another method Off (SW_USE_EZGCD_P); result= gcd (F,G); On (SW_USE_EZGCD_P); if (passToGF) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); result= GF2FalphaRep (result, alpha); prune (alpha); } if (k > 1) { result= GFMapDown (result, k); setCharacteristic (p, k, gf_name); } if (extOfExt) { result= mapDown (result, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } return N (d*result); } TIMING_END_AND_PRINT (ez_p_eval, "time for eval point search in EZ_P2: "); int dd = degree( Dbt ); if( dd == 0 ) { if (passToGF) setCharacteristic (p); if (k > 1) setCharacteristic (p, k, gf_name); return N (d); } if( dd == delta ) { goodPointCount++; if (goodPointCount == 5) break; } if( dd < delta ) { goodPointCount= 0; delta = dd; b = bt; Db = Dbt; Fb = Fbt; Gb = Gbt; } if (delta == degF) { if (degF <= degG && fdivides (F, G)) { if (passToGF) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); F= GF2FalphaRep (F, alpha); prune (alpha); } if (k > 1) { F= GFMapDown (F, k); setCharacteristic (p, k, gf_name); } if (extOfExt) { F= mapDown (F, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } return N (d*F); } else delta--; } else if (delta == degG) { if (degG <= degF && fdivides (G, F)) { if (passToGF) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); G= GF2FalphaRep (G, alpha); prune (alpha); } if (k > 1) { G= GFMapDown (G, k); setCharacteristic (p, k, gf_name); } if (extOfExt) { G= mapDown (G, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } return N (d*G); } else delta--; } if( delta == 0 ) { if (passToGF) setCharacteristic (p); if (k > 1) setCharacteristic (p, k, gf_name); return N (d); } } if( delta != degF && delta != degG ) { bool B_is_F; CanonicalForm xxx1, xxx2; CanonicalForm buf; DD[1] = Fb / Db; buf= Gb/Db; xxx1 = gcd( DD[1], Db ); xxx2 = gcd( buf, Db ); if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) && (size (F) <= size (G))) || (xxx1.inCoeffDomain() && !xxx2.inCoeffDomain())) { B = F; DD[2] = Db; lcDD[1] = lcF; lcDD[2] = lcD; B_is_F = true; } else if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) && (size (G) < size (F))) || (!xxx1.inCoeffDomain() && xxx2.inCoeffDomain())) { DD[1] = buf; B = G; DD[2] = Db; lcDD[1] = lcG; lcDD[2] = lcD; B_is_F = false; } else // special case handling { Off (SW_USE_EZGCD_P); result= gcd (F,G); On (SW_USE_EZGCD_P); if (passToGF) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); result= GF2FalphaRep (result, alpha); prune (alpha); } if (k > 1) { result= GFMapDown (result, k); setCharacteristic (p, k, gf_name); } if (extOfExt) { result= mapDown (result, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } return N (d*result); } DD[2] = DD[2] * ( b( lcDD[2] ) / lc( DD[2] ) ); DD[1] = DD[1] * ( b( lcDD[1] ) / lc( DD[1] ) ); if (size (B*lcDD[2])/maxNumVars > sizePerVars1) { if (algExtension) { result= modGCDFq (F, G, a); if (extOfExt) { result= mapDown (result, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } return N (d*result); } if (CFFactory::gettype() == GaloisFieldDomain) { result= modGCDGF (F, G); if (passToGF) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); result= GF2FalphaRep (result, alpha); prune (alpha); } if (k > 1) { result= GFMapDown (result, k); setCharacteristic (p, k, gf_name); } return N (d*result); } else return N (d*modGCDFp (F,G)); } TIMING_START (ez_p_hensel_lift); gcdfound= Hensel (B*lcD, DD, b, lcDD); TIMING_END_AND_PRINT (ez_p_hensel_lift, "time for Hensel lift in EZ_P: "); if (gcdfound == -1) //things became dense { if (algExtension) { result= modGCDFq (F, G, a); if (extOfExt) { result= mapDown (result, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } return N (d*result); } if (CFFactory::gettype() == GaloisFieldDomain) { result= modGCDGF (F, G); if (passToGF) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); result= GF2FalphaRep (result, alpha); prune (alpha); } if (k > 1) { result= GFMapDown (result, k); setCharacteristic (p, k, gf_name); } return N (d*result); } else { if (p >= cf_getBigPrime(0)) return N (d*sparseGCDFp (F,G)); else return N (d*modGCDFp (F,G)); } } if (gcdfound == 1) { TIMING_START (termination_test); contcand= content (DD[2], Variable (1)); cand = DD[2] / contcand; if (B_is_F) gcdfound = fdivides( cand, G ) && cand*(DD[1]/(lcD/contcand)) == F; else gcdfound = fdivides( cand, F ) && cand*(DD[1]/(lcD/contcand)) == G; TIMING_END_AND_PRINT (termination_test, "time for termination test EZ_P: "); if (passToGF && gcdfound) { CanonicalForm mipo= gf_mipo; setCharacteristic (p); Variable alpha= rootOf (mipo.mapinto()); cand= GF2FalphaRep (cand, alpha); prune (alpha); } if (k > 1 && gcdfound) { cand= GFMapDown (cand, k); setCharacteristic (p, k, gf_name); } if (extOfExt && gcdfound) { cand= mapDown (cand, primElem, imPrimElem, oldA, dest, source); prune1 (oldA); } } } delta--; goodPointCount= 0; } return N (d*cand); } #endif singular-4.0.3+ds/factory/cfEzgcd.h000066400000000000000000000004251266270727000171430ustar00rootroot00000000000000/** * @file cfEzgcd.h * * Extended Zassenhaus GCD over finite fields and Z **/ #ifndef CF_EZ_GCD_H #define CF_EZ_GCD_H CanonicalForm EZGCD_P (const CanonicalForm& A, const CanonicalForm& B); CanonicalForm ezgcd ( const CanonicalForm & f, const CanonicalForm & g ); #endif singular-4.0.3+ds/factory/cfGcdAlgExt.cc000066400000000000000000000665211266270727000200600ustar00rootroot00000000000000 #include "config.h" #ifndef NOSTREAMIO #ifdef HAVE_CSTDIO #include #else #include #endif #ifdef HAVE_IOSTREAM_H #include #elif defined(HAVE_IOSTREAM) #include #endif #endif #include "cf_assert.h" #include "timing.h" #include "templates/ftmpl_functions.h" #include "cf_defs.h" #include "canonicalform.h" #include "cf_iter.h" #include "cf_primes.h" #include "cf_algorithm.h" #include "cfGcdAlgExt.h" #include "cfUnivarGcd.h" #include "cf_map.h" #include "cf_generator.h" #include "facMul.h" #include "cfNTLzzpEXGCD.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif #ifdef HAVE_FLINT #include "FLINTconvert.h" #endif TIMING_DEFINE_PRINT(alg_content_p) TIMING_DEFINE_PRINT(alg_content) TIMING_DEFINE_PRINT(alg_compress) TIMING_DEFINE_PRINT(alg_termination) TIMING_DEFINE_PRINT(alg_termination_p) TIMING_DEFINE_PRINT(alg_reconstruction) TIMING_DEFINE_PRINT(alg_newton_p) TIMING_DEFINE_PRINT(alg_recursion_p) TIMING_DEFINE_PRINT(alg_gcd_p) TIMING_DEFINE_PRINT(alg_euclid_p) /// compressing two polynomials F and G, M is used for compressing, /// N to reverse the compression static int myCompress (const CanonicalForm& F, const CanonicalForm& G, CFMap & M, CFMap & N, bool topLevel) { int n= tmax (F.level(), G.level()); int * degsf= new int [n + 1]; int * degsg= new int [n + 1]; for (int i = 0; i <= n; i++) degsf[i]= degsg[i]= 0; degsf= degrees (F, degsf); degsg= degrees (G, degsg); int both_non_zero= 0; int f_zero= 0; int g_zero= 0; int both_zero= 0; if (topLevel) { for (int i= 1; i <= n; i++) { if (degsf[i] != 0 && degsg[i] != 0) { both_non_zero++; continue; } if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level()) { f_zero++; continue; } if (degsg[i] == 0 && degsf[i] && i <= F.level()) { g_zero++; continue; } } if (both_non_zero == 0) { delete [] degsf; delete [] degsg; return 0; } // map Variables which do not occur in both polynomials to higher levels int k= 1; int l= 1; for (int i= 1; i <= n; i++) { if (degsf[i] != 0 && degsg[i] == 0 && i <= F.level()) { if (k + both_non_zero != i) { M.newpair (Variable (i), Variable (k + both_non_zero)); N.newpair (Variable (k + both_non_zero), Variable (i)); } k++; } if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level()) { if (l + g_zero + both_non_zero != i) { M.newpair (Variable (i), Variable (l + g_zero + both_non_zero)); N.newpair (Variable (l + g_zero + both_non_zero), Variable (i)); } l++; } } // sort Variables x_{i} in increasing order of // min(deg_{x_{i}}(f),deg_{x_{i}}(g)) int m= tmax (F.level(), G.level()); int min_max_deg; k= both_non_zero; l= 0; int i= 1; while (k > 0) { if (degsf [i] != 0 && degsg [i] != 0) min_max_deg= tmax (degsf[i], degsg[i]); else min_max_deg= 0; while (min_max_deg == 0) { i++; min_max_deg= tmax (degsf[i], degsg[i]); if (degsf [i] != 0 && degsg [i] != 0) min_max_deg= tmax (degsf[i], degsg[i]); else min_max_deg= 0; } for (int j= i + 1; j <= m; j++) { if (tmax (degsf[j],degsg[j]) <= min_max_deg && degsf[j] != 0 && degsg [j] != 0) { min_max_deg= tmax (degsf[j], degsg[j]); l= j; } } if (l != 0) { if (l != k) { M.newpair (Variable (l), Variable(k)); N.newpair (Variable (k), Variable(l)); degsf[l]= 0; degsg[l]= 0; l= 0; } else { degsf[l]= 0; degsg[l]= 0; l= 0; } } else if (l == 0) { if (i != k) { M.newpair (Variable (i), Variable (k)); N.newpair (Variable (k), Variable (i)); degsf[i]= 0; degsg[i]= 0; } else { degsf[i]= 0; degsg[i]= 0; } i++; } k--; } } else { //arrange Variables such that no gaps occur for (int i= 1; i <= n; i++) { if (degsf[i] == 0 && degsg[i] == 0) { both_zero++; continue; } else { if (both_zero != 0) { M.newpair (Variable (i), Variable (i - both_zero)); N.newpair (Variable (i - both_zero), Variable (i)); } } } } delete [] degsf; delete [] degsg; return 1; } void tryInvert( const CanonicalForm & F, const CanonicalForm & M, CanonicalForm & inv, bool & fail ) { // F, M are required to be "univariate" polynomials in an algebraic variable // we try to invert F modulo M if(F.inBaseDomain()) { if(F.isZero()) { fail = true; return; } inv = 1/F; return; } CanonicalForm b; Variable a = M.mvar(); Variable x = Variable(1); if(!extgcd( replacevar( F, a, x ), replacevar( M, a, x ), inv, b ).isOne()) fail = true; else inv = replacevar( inv, x, a ); // change back to alg var } #ifndef HAVE_NTL void tryDivrem (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q, CanonicalForm& R, CanonicalForm& inv, const CanonicalForm& mipo, bool& fail) { if (F.inCoeffDomain()) { Q= 0; R= F; return; } CanonicalForm A, B; Variable x= F.mvar(); A= F; B= G; int degA= degree (A, x); int degB= degree (B, x); if (degA < degB) { R= A; Q= 0; return; } tryInvert (Lc (B), mipo, inv, fail); if (fail) return; R= A; Q= 0; CanonicalForm Qi; for (int i= degA -degB; i >= 0; i--) { if (degree (R, x) == i + degB) { Qi= Lc (R)*inv*power (x, i); Qi= reduce (Qi, mipo); R -= Qi*B; R= reduce (R, mipo); Q += Qi; } } } void tryEuclid( const CanonicalForm & A, const CanonicalForm & B, const CanonicalForm & M, CanonicalForm & result, bool & fail ) { CanonicalForm P; if(A.inCoeffDomain()) { tryInvert( A, M, P, fail ); if(fail) return; result = 1; return; } if(B.inCoeffDomain()) { tryInvert( B, M, P, fail ); if(fail) return; result = 1; return; } // here: both not inCoeffDomain if( A.degree() > B.degree() ) { P = A; result = B; } else { P = B; result = A; } CanonicalForm inv; if( result.isZero() ) { tryInvert( Lc(P), M, inv, fail ); if(fail) return; result = inv*P; // monify result (not reduced, yet) result= reduce (result, M); return; } Variable x = P.mvar(); CanonicalForm rem, Q; // here: degree(P) >= degree(result) while(true) { tryDivrem (P, result, Q, rem, inv, M, fail); if (fail) return; if( rem.isZero() ) { result *= inv; result= reduce (result, M); return; } if(result.degree(x) >= rem.degree(x)) { P = result; result = rem; } else P = rem; } } #endif CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G ); int * leadDeg(const CanonicalForm & f, int *degs); bool isLess(int *a, int *b, int lower, int upper); bool isEqual(int *a, int *b, int lower, int upper); CanonicalForm firstLC(const CanonicalForm & f); static CanonicalForm trycontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail ); static CanonicalForm tryvcontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail ); static CanonicalForm trycf_content ( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, bool & fail ); static inline CanonicalForm tryNewtonInterp (const CanonicalForm & alpha, const CanonicalForm & u, const CanonicalForm & newtonPoly, const CanonicalForm & oldInterPoly, const Variable & x, const CanonicalForm& M, bool& fail) { CanonicalForm interPoly; CanonicalForm inv; tryInvert (newtonPoly (alpha, x), M, inv, fail); if (fail) return 0; interPoly= oldInterPoly+reduce ((u - oldInterPoly (alpha, x))*inv*newtonPoly, M); return interPoly; } void tryBrownGCD( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, bool & fail, bool topLevel ) { // assume F,G are multivariate polys over Z/p(a) for big prime p, M "univariate" polynomial in an algebraic variable // M is assumed to be monic if(F.isZero()) { if(G.isZero()) { result = G; // G is zero return; } if(G.inCoeffDomain()) { tryInvert(G,M,result,fail); if(fail) return; result = 1; return; } // try to make G monic modulo M CanonicalForm inv; tryInvert(Lc(G),M,inv,fail); if(fail) return; result = inv*G; result= reduce (result, M); return; } if(G.isZero()) // F is non-zero { if(F.inCoeffDomain()) { tryInvert(F,M,result,fail); if(fail) return; result = 1; return; } // try to make F monic modulo M CanonicalForm inv; tryInvert(Lc(F),M,inv,fail); if(fail) return; result = inv*F; result= reduce (result, M); return; } // here: F,G both nonzero if(F.inCoeffDomain()) { tryInvert(F,M,result,fail); if(fail) return; result = 1; return; } if(G.inCoeffDomain()) { tryInvert(G,M,result,fail); if(fail) return; result = 1; return; } TIMING_START (alg_compress) CFMap MM,NN; int lev= myCompress (F, G, MM, NN, topLevel); if (lev == 0) { result= 1; return; } CanonicalForm f=MM(F); CanonicalForm g=MM(G); TIMING_END_AND_PRINT (alg_compress, "time to compress in alg gcd: ") // here: f,g are compressed // compute largest variable in f or g (least one is Variable(1)) int mv = f.level(); if(g.level() > mv) mv = g.level(); // here: mv is level of the largest variable in f, g Variable v1= Variable (1); #ifdef HAVE_NTL Variable v= M.mvar(); if (fac_NTL_char != getCharacteristic()) { fac_NTL_char= getCharacteristic(); zz_p::init (getCharacteristic()); } zz_pX NTLMipo= convertFacCF2NTLzzpX (M); zz_pE::init (NTLMipo); zz_pEX NTLResult; zz_pEX NTLF; zz_pEX NTLG; #endif if(mv == 1) // f,g univariate { TIMING_START (alg_euclid_p) #ifdef HAVE_NTL NTLF= convertFacCF2NTLzz_pEX (f, NTLMipo); NTLG= convertFacCF2NTLzz_pEX (g, NTLMipo); tryNTLGCD (NTLResult, NTLF, NTLG, fail); if (fail) return; result= convertNTLzz_pEX2CF (NTLResult, f.mvar(), v); #else tryEuclid(f,g,M,result,fail); if(fail) return; #endif TIMING_END_AND_PRINT (alg_euclid_p, "time for euclidean alg mod p: ") result= NN (reduce (result, M)); // do not forget to map back return; } TIMING_START (alg_content_p) // here: mv > 1 CanonicalForm cf = tryvcontent(f, Variable(2), M, fail); // cf is univariate poly in var(1) if(fail) return; CanonicalForm cg = tryvcontent(g, Variable(2), M, fail); if(fail) return; CanonicalForm c; #ifdef HAVE_NTL NTLF= convertFacCF2NTLzz_pEX (cf, NTLMipo); NTLG= convertFacCF2NTLzz_pEX (cg, NTLMipo); tryNTLGCD (NTLResult, NTLF, NTLG, fail); if (fail) return; c= convertNTLzz_pEX2CF (NTLResult, v1, v); #else tryEuclid(cf,cg,M,c,fail); if(fail) return; #endif // f /= cf f.tryDiv (cf, M, fail); if(fail) return; // g /= cg g.tryDiv (cg, M, fail); if(fail) return; TIMING_END_AND_PRINT (alg_content_p, "time for content in alg gcd mod p: ") if(f.inCoeffDomain()) { tryInvert(f,M,result,fail); if(fail) return; result = NN(c); return; } if(g.inCoeffDomain()) { tryInvert(g,M,result,fail); if(fail) return; result = NN(c); return; } int *L = new int[mv+1]; // L is addressed by i from 2 to mv int *N = new int[mv+1]; for(int i=2; i<=mv; i++) L[i] = N[i] = 0; L = leadDeg(f, L); N = leadDeg(g, N); CanonicalForm gamma; TIMING_START (alg_euclid_p) #ifdef HAVE_NTL NTLF= convertFacCF2NTLzz_pEX (firstLC (f), NTLMipo); NTLG= convertFacCF2NTLzz_pEX (firstLC (g), NTLMipo); tryNTLGCD (NTLResult, NTLF, NTLG, fail); if (fail) return; gamma= convertNTLzz_pEX2CF (NTLResult, v1, v); #else tryEuclid( firstLC(f), firstLC(g), M, gamma, fail ); if(fail) return; #endif TIMING_END_AND_PRINT (alg_euclid_p, "time for gcd of lcs in alg mod p: ") for(int i=2; i<=mv; i++) // entries at i=0,1 not visited if(N[i] < L[i]) L[i] = N[i]; // L is now upper bound for degrees of gcd int *dg_im = new int[mv+1]; // for the degree vector of the image we don't need any entry at i=1 for(int i=2; i<=mv; i++) dg_im[i] = 0; // initialize CanonicalForm gamma_image, m=1; CanonicalForm gm=0; CanonicalForm g_image, alpha, gnew; FFGenerator gen = FFGenerator(); Variable x= Variable (1); bool divides= true; for(FFGenerator gen = FFGenerator(); gen.hasItems(); gen.next()) { alpha = gen.item(); gamma_image = reduce(gamma(alpha, x),M); // plug in alpha for var(1) if(gamma_image.isZero()) // skip lc-bad points var(1)-alpha continue; TIMING_START (alg_recursion_p) tryBrownGCD( f(alpha, x), g(alpha, x), M, g_image, fail, false ); // recursive call with one var less TIMING_END_AND_PRINT (alg_recursion_p, "time for recursive calls in alg gcd mod p: ") if(fail) return; g_image = reduce(g_image, M); if(g_image.inCoeffDomain()) // early termination { tryInvert(g_image,M,result,fail); if(fail) return; result = NN(c); return; } for(int i=2; i<=mv; i++) dg_im[i] = 0; // reset (this is necessary, because some entries may not be updated by call to leadDeg) dg_im = leadDeg(g_image, dg_im); // dg_im cannot be NIL-pointer if(isEqual(dg_im, L, 2, mv)) { CanonicalForm inv; tryInvert (firstLC (g_image), M, inv, fail); if (fail) return; g_image *= inv; g_image *= gamma_image; // multiply by multiple of image lc(gcd) g_image= reduce (g_image, M); TIMING_START (alg_newton_p) gnew= tryNewtonInterp (alpha, g_image, m, gm, x, M, fail); TIMING_END_AND_PRINT (alg_newton_p, "time for Newton interpolation in alg gcd mod p: ") // gnew = gm mod m // gnew = g_image mod var(1)-alpha // mnew = m * (var(1)-alpha) if(fail) return; m *= (x - alpha); if((firstLC(gnew) == gamma) || (gnew == gm)) // gnew did not change { TIMING_START (alg_termination_p) cf = tryvcontent(gnew, Variable(2), M, fail); if(fail) return; divides = true; g_image= gnew; g_image.tryDiv (cf, M, fail); if(fail) return; divides= tryFdivides (g_image,f, M, fail); // trial division (f) if(fail) return; if(divides) { bool divides2= tryFdivides (g_image,g, M, fail); // trial division (g) if(fail) return; if(divides2) { result = NN(reduce (c*g_image, M)); TIMING_END_AND_PRINT (alg_termination_p, "time for successful termination test in alg gcd mod p: ") return; } } TIMING_END_AND_PRINT (alg_termination_p, "time for unsuccessful termination test in alg gcd mod p: ") } gm = gnew; continue; } if(isLess(L, dg_im, 2, mv)) // dg_im > L --> current point unlucky continue; // here: isLess(dg_im, L, 2, mv) --> all previous points were unlucky m = CanonicalForm(1); // reset gm = 0; // reset for(int i=2; i<=mv; i++) // tighten bound L[i] = dg_im[i]; } // we are out of evaluation points fail = true; } static CanonicalForm myicontent ( const CanonicalForm & f, const CanonicalForm & c ) { #ifdef HAVE_NTL if (f.isOne() || c.isOne()) return 1; if ( f.inBaseDomain() && c.inBaseDomain()) { if (c.isZero()) return abs(f); return bgcd( f, c ); } else if ( (f.inCoeffDomain() && c.inCoeffDomain()) || (f.inCoeffDomain() && c.inBaseDomain()) || (f.inBaseDomain() && c.inCoeffDomain())) { if (c.isZero()) return abs (f); #ifdef HAVE_FLINT fmpz_poly_t FLINTf, FLINTc; convertFacCF2Fmpz_poly_t (FLINTf, f); convertFacCF2Fmpz_poly_t (FLINTc, c); fmpz_poly_gcd (FLINTc, FLINTc, FLINTf); CanonicalForm result; if (f.inCoeffDomain()) result= convertFmpz_poly_t2FacCF (FLINTc, f.mvar()); else result= convertFmpz_poly_t2FacCF (FLINTc, c.mvar()); fmpz_poly_clear (FLINTc); fmpz_poly_clear (FLINTf); return result; #else ZZX NTLf= convertFacCF2NTLZZX (f); ZZX NTLc= convertFacCF2NTLZZX (c); NTLc= GCD (NTLc, NTLf); if (f.inCoeffDomain()) return convertNTLZZX2CF(NTLc,f.mvar()); else return convertNTLZZX2CF(NTLc,c.mvar()); #endif } else { CanonicalForm g = c; for ( CFIterator i = f; i.hasTerms() && ! g.isOne(); i++ ) g = myicontent( i.coeff(), g ); return g; } #else return 1; #endif } CanonicalForm myicontent ( const CanonicalForm & f ) { #ifdef HAVE_NTL return myicontent( f, 0 ); #else return 1; #endif } CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G ) { // f,g in Q(a)[x1,...,xn] if(F.isZero()) { if(G.isZero()) return G; // G is zero if(G.inCoeffDomain()) return CanonicalForm(1); CanonicalForm lcinv= 1/Lc (G); return G*lcinv; // return monic G } if(G.isZero()) // F is non-zero { if(F.inCoeffDomain()) return CanonicalForm(1); CanonicalForm lcinv= 1/Lc (F); return F*lcinv; // return monic F } if(F.inCoeffDomain() || G.inCoeffDomain()) return CanonicalForm(1); // here: both NOT inCoeffDomain CanonicalForm f, g, tmp, M, q, D, Dp, cl, newq, mipo; int p, i; int *bound, *other; // degree vectors bool fail; bool off_rational=!isOn(SW_RATIONAL); On( SW_RATIONAL ); // needed by bCommonDen f = F * bCommonDen(F); g = G * bCommonDen(G); TIMING_START (alg_content) CanonicalForm contf= myicontent (f); CanonicalForm contg= myicontent (g); f /= contf; g /= contg; CanonicalForm gcdcfcg= myicontent (contf, contg); TIMING_END_AND_PRINT (alg_content, "time for content in alg gcd: ") Variable a, b; if(hasFirstAlgVar(f,a)) { if(hasFirstAlgVar(g,b)) { if(b.level() > a.level()) a = b; } } else { if(!hasFirstAlgVar(g,a))// both not in extension { Off( SW_RATIONAL ); Off( SW_USE_QGCD ); tmp = gcdcfcg*gcd( f, g ); On( SW_USE_QGCD ); if (off_rational) Off(SW_RATIONAL); return tmp; } } // here: a is the biggest alg. var in f and g AND some of f,g is in extension setReduce(a,false); // do not reduce expressions modulo mipo tmp = getMipo(a); M = tmp * bCommonDen(tmp); // here: f, g in Z[a][x1,...,xn], M in Z[a] not necessarily monic Off( SW_RATIONAL ); // needed by mod // calculate upper bound for degree vector of gcd int mv = f.level(); i = g.level(); if(i > mv) mv = i; // here: mv is level of the largest variable in f, g bound = new int[mv+1]; // 'bound' could be indexed from 0 to mv, but we will only use from 1 to mv other = new int[mv+1]; for(int i=1; i<=mv; i++) // initialize 'bound', 'other' with zeros bound[i] = other[i] = 0; bound = leadDeg(f,bound); // 'bound' is set the leading degree vector of f other = leadDeg(g,other); for(int i=1; i<=mv; i++) // entry at i=0 not visited if(other[i] < bound[i]) bound[i] = other[i]; // now 'bound' is the smaller vector cl = lc(M) * lc(f) * lc(g); q = 1; D = 0; CanonicalForm test= 0; bool equal= false; for( i=cf_getNumBigPrimes()-1; i>-1; i-- ) { p = cf_getBigPrime(i); if( mod( cl, p ).isZero() ) // skip lc-bad primes continue; fail = false; setCharacteristic(p); mipo = mapinto(M); mipo /= mipo.lc(); // here: mipo is monic TIMING_START (alg_gcd_p) tryBrownGCD( mapinto(f), mapinto(g), mipo, Dp, fail ); TIMING_END_AND_PRINT (alg_gcd_p, "time for alg gcd mod p: ") if( fail ) // mipo splits in char p continue; if( Dp.inCoeffDomain() ) // early termination { tryInvert(Dp,mipo,tmp,fail); // check if zero divisor if(fail) continue; setReduce(a,true); if (off_rational) Off(SW_RATIONAL); else On(SW_RATIONAL); setCharacteristic(0); return gcdcfcg; } setCharacteristic(0); // here: Dp NOT inCoeffDomain for(int i=1; i<=mv; i++) other[i] = 0; // reset (this is necessary, because some entries may not be updated by call to leadDeg) other = leadDeg(Dp,other); if(isEqual(bound, other, 1, mv)) // equal { chineseRemainder( D, q, mapinto(Dp), p, tmp, newq ); // tmp = Dp mod p // tmp = D mod q // newq = p*q q = newq; if( D != tmp ) D = tmp; On( SW_RATIONAL ); TIMING_START (alg_reconstruction) tmp = Farey( D, q ); // Farey tmp *= bCommonDen (tmp); TIMING_END_AND_PRINT (alg_reconstruction, "time for rational reconstruction in alg gcd: ") setReduce(a,true); // reduce expressions modulo mipo On( SW_RATIONAL ); // needed by fdivides if (test != tmp) test= tmp; else equal= true; // modular image did not add any new information TIMING_START (alg_termination) #ifdef HAVE_NTL #ifdef HAVE_FLINT if (equal && tmp.isUnivariate() && f.isUnivariate() && g.isUnivariate() && f.level() == tmp.level() && tmp.level() == g.level()) { CanonicalForm Q, R; newtonDivrem (f, tmp, Q, R); if (R.isZero()) { newtonDivrem (g, tmp, Q, R); if (R.isZero()) { Off (SW_RATIONAL); setReduce (a,true); if (off_rational) Off(SW_RATIONAL); else On(SW_RATIONAL); TIMING_END_AND_PRINT (alg_termination, "time for successful termination test in alg gcd: ") return tmp*gcdcfcg; } } } else #endif #endif if(equal && fdivides( tmp, f ) && fdivides( tmp, g )) // trial division { Off( SW_RATIONAL ); setReduce(a,true); if (off_rational) Off(SW_RATIONAL); else On(SW_RATIONAL); TIMING_END_AND_PRINT (alg_termination, "time for successful termination test in alg gcd: ") return tmp*gcdcfcg; } TIMING_END_AND_PRINT (alg_termination, "time for unsuccessful termination test in alg gcd: ") Off( SW_RATIONAL ); setReduce(a,false); // do not reduce expressions modulo mipo continue; } if( isLess(bound, other, 1, mv) ) // current prime unlucky continue; // here: isLess(other, bound, 1, mv) ) ==> all previous primes unlucky q = p; D = mapinto(Dp); // shortcut CRA // shortcut CRA for(int i=1; i<=mv; i++) // tighten bound bound[i] = other[i]; } // hopefully, we never reach this point setReduce(a,true); Off( SW_USE_QGCD ); D = gcdcfcg*gcd( f, g ); On( SW_USE_QGCD ); if (off_rational) Off(SW_RATIONAL); else On(SW_RATIONAL); return D; } int * leadDeg(const CanonicalForm & f, int *degs) { // leading degree vector w.r.t. lex. monomial order x(i+1) > x(i) // if f is in a coeff domain, the zero pointer is returned // 'a' should point to an array of sufficient size level(f)+1 if(f.inCoeffDomain()) return 0; CanonicalForm tmp = f; do { degs[tmp.level()] = tmp.degree(); tmp = LC(tmp); } while(!tmp.inCoeffDomain()); return degs; } bool isLess(int *a, int *b, int lower, int upper) { // compares the degree vectors a,b on the specified part. Note: x(i+1) > x(i) for(int i=upper; i>=lower; i--) if(a[i] == b[i]) continue; else return a[i] < b[i]; return true; } bool isEqual(int *a, int *b, int lower, int upper) { // compares the degree vectors a,b on the specified part. Note: x(i+1) > x(i) for(int i=lower; i<=upper; i++) if(a[i] != b[i]) return false; return true; } CanonicalForm firstLC(const CanonicalForm & f) { // returns the leading coefficient (LC) of level <= 1 CanonicalForm ret = f; while(ret.level() > 1) ret = LC(ret); return ret; } #ifndef HAVE_NTL void tryExtgcd( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, CanonicalForm & s, CanonicalForm & t, bool & fail ) { // F, G are univariate polynomials (i.e. they have exactly one polynomial variable) // F and G must have the same level AND level > 0 // we try to calculate gcd(F,G) = s*F + t*G // if a zero divisor is encountered, 'fail' is set to one // M is assumed to be monic CanonicalForm P; if(F.inCoeffDomain()) { tryInvert( F, M, P, fail ); if(fail) return; result = 1; s = P; t = 0; return; } if(G.inCoeffDomain()) { tryInvert( G, M, P, fail ); if(fail) return; result = 1; s = 0; t = P; return; } // here: both not inCoeffDomain CanonicalForm inv, rem, tmp, u, v, q, sum=0; if( F.degree() > G.degree() ) { P = F; result = G; s=v=0; t=u=1; } else { P = G; result = F; s=v=1; t=u=0; } Variable x = P.mvar(); // here: degree(P) >= degree(result) while(true) { tryDivrem (P, result, q, rem, inv, M, fail); if(fail) return; if( rem.isZero() ) { s*=inv; s= reduce (s, M); t*=inv; t= reduce (t, M); result *= inv; // monify result result= reduce (result, M); return; } sum += q; if(result.degree(x) >= rem.degree(x)) { P=result; result=rem; tmp=u-sum*s; u=s; s=tmp; tmp=v-sum*t; v=t; t=tmp; sum = 0; // reset } else P = rem; } } #endif static CanonicalForm trycontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail ) { // as 'content', but takes care of zero divisors ASSERT( x.level() > 0, "cannot calculate content with respect to algebraic variable" ); Variable y = f.mvar(); if ( y == x ) return trycf_content( f, 0, M, fail ); if ( y < x ) return f; return swapvar( trycontent( swapvar( f, y, x ), y, M, fail ), y, x ); } static CanonicalForm tryvcontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail ) { // as vcontent, but takes care of zero divisors ASSERT( x.level() > 0, "cannot calculate vcontent with respect to algebraic variable" ); if ( f.mvar() <= x ) return trycontent( f, x, M, fail ); CFIterator i; CanonicalForm d = 0, e, ret; for ( i = f; i.hasTerms() && ! d.isOne() && ! fail; i++ ) { e = tryvcontent( i.coeff(), x, M, fail ); if(fail) break; tryBrownGCD( d, e, M, ret, fail ); d = ret; } return d; } static CanonicalForm trycf_content ( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, bool & fail ) { // as cf_content, but takes care of zero divisors if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) ) { CFIterator i = f; CanonicalForm tmp = g, result; while ( i.hasTerms() && ! tmp.isOne() && ! fail ) { tryBrownGCD( i.coeff(), tmp, M, result, fail ); tmp = result; i++; } return result; } return abs( f ); } singular-4.0.3+ds/factory/cfGcdAlgExt.h000066400000000000000000000030011266270727000177020ustar00rootroot00000000000000/** * @file cfGcdAlgExt.h * * GCD over Q(a) * * ABSTRACT: Implementation of Encarnacion's GCD algorithm over number fields, * see M.J. Encarnacion "Computing GCDs of polynomials over number fields", * extended to the multivariate case. * * @sa cfNTLzzpEXGCD.h **/ #ifndef CF_GCD_ALGEXT_H #define CF_GCD_ALGEXT_H // #include "config.h" #include "canonicalform.h" #include "variable.h" /// gcd over Q(a) CanonicalForm QGCD( const CanonicalForm &, const CanonicalForm & ); #ifndef HAVE_NTL void tryDivrem (const CanonicalForm&, const CanonicalForm&, CanonicalForm&, CanonicalForm&, CanonicalForm&, const CanonicalForm&, bool&); void tryEuclid( const CanonicalForm &, const CanonicalForm &, const CanonicalForm &, CanonicalForm &, bool & ); void tryExtgcd( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm& M, CanonicalForm & result, CanonicalForm & s, CanonicalForm & t, bool & fail ); #endif void tryInvert( const CanonicalForm &, const CanonicalForm &, CanonicalForm &, bool & ); /// modular gcd over F_p[x]/(M) for not necessarily irreducible M. /// If a zero divisor is encountered fail is set to true. void tryBrownGCD( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, bool & fail, bool topLevel= true ); int * leadDeg(const CanonicalForm & f, int *degs); bool isLess(int *a, int *b, int lower, int upper); bool isEqual(int *a, int *b, int lower, int upper); CanonicalForm firstLC(const CanonicalForm & f); #endif singular-4.0.3+ds/factory/cfGcdUtil.cc000066400000000000000000000156341266270727000176100ustar00rootroot00000000000000#include "config.h" #include "canonicalform.h" #include "cf_factory.h" #include "cf_reval.h" #include "cf_util.h" #include "cf_iter.h" #include "gfops.h" #include "cf_map_ext.h" #include "templates/ftmpl_functions.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif /// Coprimality Check. f and g are assumed to have the same level. If swap is /// true, the main variables of f and g are swapped with Variable(1). If the /// result is false, d is set to the degree of the gcd of f and g evaluated at a /// random point in K^n-1. This gcd is a gcd of univariate polynomials. bool gcd_test_one ( const CanonicalForm & f, const CanonicalForm & g, bool swap, int & d ) { d= 0; int count = 0; // assume polys have same level; Variable v= Variable (1); bool algExtension= (hasFirstAlgVar (f, v) || hasFirstAlgVar (g, v)); CanonicalForm lcf, lcg; if ( swap ) { lcf = swapvar( LC( f ), Variable(1), f.mvar() ); lcg = swapvar( LC( g ), Variable(1), f.mvar() ); } else { lcf = LC( f, Variable(1) ); lcg = LC( g, Variable(1) ); } CanonicalForm F, G; if ( swap ) { F=swapvar( f, Variable(1), f.mvar() ); G=swapvar( g, Variable(1), g.mvar() ); } else { F = f; G = g; } #define TEST_ONE_MAX 50 int p= getCharacteristic(); bool passToGF= false; int k= 1; bool extOfExt= false; Variable v3; if (p > 0 && p < TEST_ONE_MAX && CFFactory::gettype() != GaloisFieldDomain && !algExtension) { if (p == 2) setCharacteristic (2, 6, 'Z'); else if (p == 3) setCharacteristic (3, 4, 'Z'); else if (p == 5 || p == 7) setCharacteristic (p, 3, 'Z'); else setCharacteristic (p, 2, 'Z'); passToGF= true; } else if (p > 0 && CFFactory::gettype() == GaloisFieldDomain && ipower (p , getGFDegree()) < TEST_ONE_MAX) { k= getGFDegree(); if (ipower (p, 2*k) > TEST_ONE_MAX) setCharacteristic (p, 2*k, gf_name); else setCharacteristic (p, 3*k, gf_name); F= GFMapUp (F, k); G= GFMapUp (G, k); lcf= GFMapUp (lcf, k); lcg= GFMapUp (lcg, k); } else if (p > 0 && p < TEST_ONE_MAX && algExtension) { #ifdef HAVE_NTL int d= degree (getMipo (v)); CFList source, dest; Variable v2; CanonicalForm primElem, imPrimElem; if (p == 2 && d < 6) { if (fac_NTL_char != 2) { fac_NTL_char= 2; zz_p::init (p); } bool primFail= false; Variable vBuf; primElem= primitiveElement (v, vBuf, primFail); ASSERT (!primFail, "failure in integer factorizer"); if (d < 3) { zz_pX NTLIrredpoly; BuildIrred (NTLIrredpoly, d*3); CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1)); v2= rootOf (newMipo); } else { zz_pX NTLIrredpoly; BuildIrred (NTLIrredpoly, d*2); CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1)); v2= rootOf (newMipo); } imPrimElem= mapPrimElem (primElem, v, v2); extOfExt= true; } else if ((p == 3 && d < 4) || ((p == 5 || p == 7) && d < 3)) { if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } bool primFail= false; Variable vBuf; primElem= primitiveElement (v, vBuf, primFail); ASSERT (!primFail, "failure in integer factorizer"); zz_pX NTLIrredpoly; BuildIrred (NTLIrredpoly, d*2); CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1)); v2= rootOf (newMipo); imPrimElem= mapPrimElem (primElem, v, v2); extOfExt= true; } if (extOfExt) { v3= v; F= mapUp (F, v, v2, primElem, imPrimElem, source, dest); G= mapUp (G, v, v2, primElem, imPrimElem, source, dest); lcf= mapUp (lcf, v, v2, primElem, imPrimElem, source, dest); lcg= mapUp (lcg, v, v2, primElem, imPrimElem, source, dest); v= v2; } #endif } CFRandom * sample; if ((!algExtension && p > 0) || p == 0) sample = CFRandomFactory::generate(); else sample = AlgExtRandomF (v).clone(); REvaluation e( 2, tmax( f.level(), g.level() ), *sample ); delete sample; if (passToGF) { lcf= lcf.mapinto(); lcg= lcg.mapinto(); } CanonicalForm eval1, eval2; if (passToGF) { eval1= e (lcf); eval2= e (lcg); } else { eval1= e (lcf); eval2= e (lcg); } while ( ( eval1.isZero() || eval2.isZero() ) && count < TEST_ONE_MAX ) { e.nextpoint(); count++; eval1= e (lcf); eval2= e (lcg); } if ( count >= TEST_ONE_MAX ) { if (passToGF) setCharacteristic (p); if (k > 1) setCharacteristic (p, k, gf_name); if (extOfExt) prune1 (v3); return false; } if (passToGF) { F= F.mapinto(); G= G.mapinto(); eval1= e (F); eval2= e (G); } else { eval1= e (F); eval2= e (G); } CanonicalForm c= gcd (eval1, eval2); d= c.degree(); bool result= d < 1; if (d < 0) d= 0; if (passToGF) setCharacteristic (p); if (k > 1) setCharacteristic (p, k, gf_name); if (extOfExt) prune1 (v3); return result; } /** * same as balance_p ( const CanonicalForm & f, const CanonicalForm & q ) * but qh= q/2 is provided, too. **/ CanonicalForm balance_p ( const CanonicalForm & f, const CanonicalForm & q, const CanonicalForm & qh ) { Variable x = f.mvar(); CanonicalForm result = 0; CanonicalForm c; CFIterator i; for ( i = f; i.hasTerms(); i++ ) { c = i.coeff(); if ( c.inCoeffDomain()) { if ( c > qh ) result += power( x, i.exp() ) * (c - q); else result += power( x, i.exp() ) * c; } else result += power( x, i.exp() ) * balance_p(c,q,qh); } return result; } /** static CanonicalForm balance_p ( const CanonicalForm & f, const CanonicalForm & q ) * * balance_p() - map f from positive to symmetric representation * mod q. * * This makes sense for polynomials over Z only. * q should be an integer. * **/ CanonicalForm balance_p ( const CanonicalForm & f, const CanonicalForm & q ) { CanonicalForm qh = q / 2; return balance_p (f, q, qh); } /*static CanonicalForm balance ( const CanonicalForm & f, const CanonicalForm & q ) { Variable x = f.mvar(); CanonicalForm result = 0, qh = q / 2; CanonicalForm c; CFIterator i; for ( i = f; i.hasTerms(); i++ ) { c = mod( i.coeff(), q ); if ( c > qh ) result += power( x, i.exp() ) * (c - q); else result += power( x, i.exp() ) * c; } return result; }*/ singular-4.0.3+ds/factory/cfGcdUtil.h000066400000000000000000000006401266270727000174410ustar00rootroot00000000000000/** * @file cfGcdUtil.h * * coprimality check and change of representation mod n **/ #ifndef CF_GCD_UTIL_H #define CF_GCD_UTIL_H bool gcd_test_one ( const CanonicalForm & f, const CanonicalForm & g, bool swap, int & d ); CanonicalForm balance_p ( const CanonicalForm & f, const CanonicalForm & q, const CanonicalForm & qh ); CanonicalForm balance_p ( const CanonicalForm & f, const CanonicalForm & q ); #endif singular-4.0.3+ds/factory/cfModGcd.cc000066400000000000000000003456551266270727000174230ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file cfModGcd.cc * * This file implements the GCD of two polynomials over \f$ F_{p} \f$ , * \f$ F_{p}(\alpha ) \f$, GF or Z based on Alg. 7.1. and 7.2. as described in * "Algorithms for Computer Algebra" by Geddes, Czapor, Labahn via modular * computations. And sparse modular variants as described in Zippel * "Effective Polynomial Computation", deKleine, Monagan, Wittkopf * "Algorithms for the non-monic case of the sparse modular GCD algorithm" and * Javadi "A new solution to the normalization problem" * * @author Martin Lee * @date 22.10.2009 * * @par Copyright: * (c) by The SINGULAR Team, see LICENSE file * **/ //***************************************************************************** #include "config.h" #include "cf_assert.h" #include "debug.h" #include "timing.h" #include "canonicalform.h" #include "cfGcdUtil.h" #include "cf_map.h" #include "cf_util.h" #include "cf_irred.h" #include "templates/ftmpl_functions.h" #include "cf_random.h" #include "cf_reval.h" #include "facHensel.h" #include "cf_iter.h" #include "cfNewtonPolygon.h" #include "cf_algorithm.h" #include "cf_primes.h" // inline helper functions: #include "cf_map_ext.h" #ifdef HAVE_NTL #include #endif #ifdef HAVE_FLINT #include "FLINTconvert.h" #endif #include "cfModGcd.h" TIMING_DEFINE_PRINT(gcd_recursion) TIMING_DEFINE_PRINT(newton_interpolation) TIMING_DEFINE_PRINT(termination_test) TIMING_DEFINE_PRINT(ez_p_compress) TIMING_DEFINE_PRINT(ez_p_hensel_lift) TIMING_DEFINE_PRINT(ez_p_eval) TIMING_DEFINE_PRINT(ez_p_content) bool terminationTest (const CanonicalForm& F, const CanonicalForm& G, const CanonicalForm& coF, const CanonicalForm& coG, const CanonicalForm& cand) { CanonicalForm LCCand= abs (LC (cand)); if (LCCand*abs (LC (coF)) == abs (LC (F))) { if (LCCand*abs (LC (coG)) == abs (LC (G))) { if (abs (cand)*abs (coF) == abs (F)) { if (abs (cand)*abs (coG) == abs (G)) return true; } return false; } return false; } return false; } #ifdef HAVE_NTL static const double log2exp= 1.442695041; /// compressing two polynomials F and G, M is used for compressing, /// N to reverse the compression int myCompress (const CanonicalForm& F, const CanonicalForm& G, CFMap & M, CFMap & N, bool topLevel) { int n= tmax (F.level(), G.level()); int * degsf= new int [n + 1]; int * degsg= new int [n + 1]; for (int i = 0; i <= n; i++) degsf[i]= degsg[i]= 0; degsf= degrees (F, degsf); degsg= degrees (G, degsg); int both_non_zero= 0; int f_zero= 0; int g_zero= 0; int both_zero= 0; if (topLevel) { for (int i= 1; i <= n; i++) { if (degsf[i] != 0 && degsg[i] != 0) { both_non_zero++; continue; } if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level()) { f_zero++; continue; } if (degsg[i] == 0 && degsf[i] && i <= F.level()) { g_zero++; continue; } } if (both_non_zero == 0) { delete [] degsf; delete [] degsg; return 0; } // map Variables which do not occur in both polynomials to higher levels int k= 1; int l= 1; for (int i= 1; i <= n; i++) { if (degsf[i] != 0 && degsg[i] == 0 && i <= F.level()) { if (k + both_non_zero != i) { M.newpair (Variable (i), Variable (k + both_non_zero)); N.newpair (Variable (k + both_non_zero), Variable (i)); } k++; } if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level()) { if (l + g_zero + both_non_zero != i) { M.newpair (Variable (i), Variable (l + g_zero + both_non_zero)); N.newpair (Variable (l + g_zero + both_non_zero), Variable (i)); } l++; } } // sort Variables x_{i} in increasing order of // min(deg_{x_{i}}(f),deg_{x_{i}}(g)) int m= tmax (F.level(), G.level()); int min_max_deg; k= both_non_zero; l= 0; int i= 1; while (k > 0) { if (degsf [i] != 0 && degsg [i] != 0) min_max_deg= tmax (degsf[i], degsg[i]); else min_max_deg= 0; while (min_max_deg == 0) { i++; if (degsf [i] != 0 && degsg [i] != 0) min_max_deg= tmax (degsf[i], degsg[i]); else min_max_deg= 0; } for (int j= i + 1; j <= m; j++) { if (degsf[j] != 0 && degsg [j] != 0 && tmax (degsf[j],degsg[j]) <= min_max_deg) { min_max_deg= tmax (degsf[j], degsg[j]); l= j; } } if (l != 0) { if (l != k) { M.newpair (Variable (l), Variable(k)); N.newpair (Variable (k), Variable(l)); degsf[l]= 0; degsg[l]= 0; l= 0; } else { degsf[l]= 0; degsg[l]= 0; l= 0; } } else if (l == 0) { if (i != k) { M.newpair (Variable (i), Variable (k)); N.newpair (Variable (k), Variable (i)); degsf[i]= 0; degsg[i]= 0; } else { degsf[i]= 0; degsg[i]= 0; } i++; } k--; } } else { //arrange Variables such that no gaps occur for (int i= 1; i <= n; i++) { if (degsf[i] == 0 && degsg[i] == 0) { both_zero++; continue; } else { if (both_zero != 0) { M.newpair (Variable (i), Variable (i - both_zero)); N.newpair (Variable (i - both_zero), Variable (i)); } } } } delete [] degsf; delete [] degsg; return 1; } static inline CanonicalForm uni_content (const CanonicalForm & F); CanonicalForm uni_content (const CanonicalForm& F, const Variable& x) { if (F.inCoeffDomain()) return F.genOne(); if (F.level() == x.level() && F.isUnivariate()) return F; if (F.level() != x.level() && F.isUnivariate()) return F.genOne(); if (x.level() != 1) { CanonicalForm f= swapvar (F, x, Variable (1)); CanonicalForm result= uni_content (f); return swapvar (result, x, Variable (1)); } else return uni_content (F); } /// compute the content of F, where F is considered as an element of /// \f$ R[x_{1}][x_{2},\ldots ,x_{n}] \f$ static inline CanonicalForm uni_content (const CanonicalForm & F) { if (F.inBaseDomain()) return F.genOne(); if (F.level() == 1 && F.isUnivariate()) return F; if (F.level() != 1 && F.isUnivariate()) return F.genOne(); if (degree (F,1) == 0) return F.genOne(); int l= F.level(); if (l == 2) return content(F); else { CanonicalForm pol, c = 0; CFIterator i = F; for (; i.hasTerms(); i++) { pol= i.coeff(); pol= uni_content (pol); c= gcd (c, pol); if (c.isOne()) return c; } return c; } } CanonicalForm extractContents (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& contentF, CanonicalForm& contentG, CanonicalForm& ppF, CanonicalForm& ppG, const int d) { CanonicalForm uniContentF, uniContentG, gcdcFcG; contentF= 1; contentG= 1; ppF= F; ppG= G; CanonicalForm result= 1; for (int i= 1; i <= d; i++) { uniContentF= uni_content (F, Variable (i)); uniContentG= uni_content (G, Variable (i)); gcdcFcG= gcd (uniContentF, uniContentG); contentF *= uniContentF; contentG *= uniContentG; ppF /= uniContentF; ppG /= uniContentG; result *= gcdcFcG; } return result; } /// compute the leading coefficient of F, where F is considered as an element /// of \f$ R[x_{1}][x_{2},\ldots ,x_{n}] \f$, order on /// \f$ Mon (x_{2},\ldots ,x_{n}) \f$ is dp. static inline CanonicalForm uni_lcoeff (const CanonicalForm& F) { if (F.level() > 1) { Variable x= Variable (2); int deg= totaldegree (F, x, F.mvar()); for (CFIterator i= F; i.hasTerms(); i++) { if (i.exp() + totaldegree (i.coeff(), x, i.coeff().mvar()) == deg) return uni_lcoeff (i.coeff()); } } return F; } /// Newton interpolation - Incremental algorithm. /// Given a list of values alpha_i and a list of polynomials u_i, 1 <= i <= n, /// computes the interpolation polynomial assuming that /// the polynomials in u are the results of evaluating the variabe x /// of the unknown polynomial at the alpha values. /// This incremental version receives only the values of alpha_n and u_n and /// the previous interpolation polynomial for points 1 <= i <= n-1, and computes /// the polynomial interpolating in all the points. /// newtonPoly must be equal to (x - alpha_1) * ... * (x - alpha_{n-1}) static inline CanonicalForm newtonInterp(const CanonicalForm & alpha, const CanonicalForm & u, const CanonicalForm & newtonPoly, const CanonicalForm & oldInterPoly, const Variable & x) { CanonicalForm interPoly; interPoly= oldInterPoly + ((u - oldInterPoly(alpha, x))/newtonPoly(alpha, x)) *newtonPoly; return interPoly; } /// compute a random element a of \f$ F_{p}(\alpha ) \f$ , /// s.t. F(a) \f$ \neq 0 \f$ , F is a univariate polynomial, returns /// fail if there are no field elements left which have not been used before static inline CanonicalForm randomElement (const CanonicalForm & F, const Variable & alpha, CFList & list, bool & fail) { fail= false; Variable x= F.mvar(); AlgExtRandomF genAlgExt (alpha); FFRandom genFF; CanonicalForm random, mipo; mipo= getMipo (alpha); int p= getCharacteristic (); int d= degree (mipo); double bound= pow ((double) p, (double) d); do { if (list.length() == bound) { fail= true; break; } if (list.length() < p) { random= genFF.generate(); while (find (list, random)) random= genFF.generate(); } else { random= genAlgExt.generate(); while (find (list, random)) random= genAlgExt.generate(); } if (F (random, x) == 0) { list.append (random); continue; } } while (find (list, random)); return random; } static inline Variable chooseExtension (const Variable & alpha) { if (fac_NTL_char != getCharacteristic()) { fac_NTL_char= getCharacteristic(); zz_p::init (getCharacteristic()); } zz_pX NTLIrredpoly; int i, m; // extension of F_p needed if (alpha.level() == 1) { i= 1; m= 2; } //extension of F_p(alpha) if (alpha.level() != 1) { i= 4; m= degree (getMipo (alpha)); } BuildIrred (NTLIrredpoly, i*m); CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1)); return rootOf (newMipo); } CanonicalForm modGCDFq (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& coF, CanonicalForm& coG, Variable & alpha, CFList& l, bool& topLevel); CanonicalForm modGCDFq (const CanonicalForm& F, const CanonicalForm& G, Variable & alpha, CFList& l, bool& topLevel) { CanonicalForm dummy1, dummy2; CanonicalForm result= modGCDFq (F, G, dummy1, dummy2, alpha, l, topLevel); return result; } /// GCD of F and G over \f$ F_{p}(\alpha ) \f$ , /// l and topLevel are only used internally, output is monic /// based on Alg. 7.2. as described in "Algorithms for /// Computer Algebra" by Geddes, Czapor, Labahn CanonicalForm modGCDFq (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& coF, CanonicalForm& coG, Variable & alpha, CFList& l, bool& topLevel) { CanonicalForm A= F; CanonicalForm B= G; if (F.isZero() && degree(G) > 0) { coF= 0; coG= Lc (G); return G/Lc(G); } else if (G.isZero() && degree (F) > 0) { coF= Lc (F); coG= 0; return F/Lc(F); } else if (F.isZero() && G.isZero()) { coF= coG= 0; return F.genOne(); } if (F.inBaseDomain() || G.inBaseDomain()) { coF= F; coG= G; return F.genOne(); } if (F.isUnivariate() && fdivides(F, G, coG)) { coF= Lc (F); return F/Lc(F); } if (G.isUnivariate() && fdivides(G, F, coF)) { coG= Lc (G); return G/Lc(G); } if (F == G) { coF= coG= Lc (F); return F/Lc(F); } CFMap M,N; int best_level= myCompress (A, B, M, N, topLevel); if (best_level == 0) { coF= F; coG= G; return B.genOne(); } A= M(A); B= M(B); Variable x= Variable(1); //univariate case if (A.isUnivariate() && B.isUnivariate()) { CanonicalForm result= gcd (A, B); coF= N (A/result); coG= N (B/result); return N (result); } CanonicalForm cA, cB; // content of A and B CanonicalForm ppA, ppB; // primitive part of A and B CanonicalForm gcdcAcB; cA = uni_content (A); cB = uni_content (B); gcdcAcB= gcd (cA, cB); ppA= A/cA; ppB= B/cB; CanonicalForm lcA, lcB; // leading coefficients of A and B CanonicalForm gcdlcAlcB; lcA= uni_lcoeff (ppA); lcB= uni_lcoeff (ppB); gcdlcAlcB= gcd (lcA, lcB); int d= totaldegree (ppA, Variable(2), Variable (ppA.level())); if (d == 0) { coF= N (ppA*(cA/gcdcAcB)); coG= N (ppB*(cB/gcdcAcB)); return N(gcdcAcB); } int d0= totaldegree (ppB, Variable(2), Variable (ppB.level())); if (d0 < d) d= d0; if (d == 0) { coF= N (ppA*(cA/gcdcAcB)); coG= N (ppB*(cB/gcdcAcB)); return N(gcdcAcB); } CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH; CanonicalForm newtonPoly, coF_random_element, coG_random_element, coF_m, coG_m, ppCoF, ppCoG; newtonPoly= 1; m= gcdlcAlcB; G_m= 0; coF= 0; coG= 0; H= 0; bool fail= false; topLevel= false; bool inextension= false; Variable V_buf= alpha, V_buf4= alpha; CanonicalForm prim_elem, im_prim_elem; CanonicalForm prim_elem_alpha, im_prim_elem_alpha; CFList source, dest; int bound1= degree (ppA, 1); int bound2= degree (ppB, 1); do { random_element= randomElement (m*lcA*lcB, V_buf, l, fail); if (fail) { source= CFList(); dest= CFList(); Variable V_buf3= V_buf; V_buf= chooseExtension (V_buf); bool prim_fail= false; Variable V_buf2; prim_elem= primitiveElement (V_buf4, V_buf2, prim_fail); if (V_buf4 == alpha) prim_elem_alpha= prim_elem; if (V_buf3 != V_buf4) { m= mapDown (m, prim_elem, im_prim_elem, V_buf4, source, dest); G_m= mapDown (G_m, prim_elem, im_prim_elem, V_buf4, source, dest); coF_m= mapDown (coF_m, prim_elem, im_prim_elem, V_buf4, source, dest); coG_m= mapDown (coG_m, prim_elem, im_prim_elem, V_buf4, source, dest); newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, V_buf4, source, dest); ppA= mapDown (ppA, prim_elem, im_prim_elem, V_buf4, source, dest); ppB= mapDown (ppB, prim_elem, im_prim_elem, V_buf4, source, dest); gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, V_buf4, source, dest); lcA= mapDown (lcA, prim_elem, im_prim_elem, V_buf4, source, dest); lcB= mapDown (lcB, prim_elem, im_prim_elem, V_buf4, source, dest); for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, V_buf4, source, dest); } ASSERT (!prim_fail, "failure in integer factorizer"); if (prim_fail) ; //ERROR else im_prim_elem= mapPrimElem (prim_elem, V_buf4, V_buf); if (V_buf4 == alpha) im_prim_elem_alpha= im_prim_elem; else im_prim_elem_alpha= mapUp (im_prim_elem_alpha, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); DEBOUTLN (cerr, "getMipo (V_buf4)= " << getMipo (V_buf4)); DEBOUTLN (cerr, "getMipo (V_buf2)= " << getMipo (V_buf2)); inextension= true; for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapUp (i.getItem(), V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); m= mapUp (m, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); G_m= mapUp (G_m, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); coF_m= mapUp (coF_m, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); coG_m= mapUp (coG_m, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); newtonPoly= mapUp (newtonPoly, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); ppA= mapUp (ppA, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); ppB= mapUp (ppB, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); gcdlcAlcB= mapUp (gcdlcAlcB, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); lcA= mapUp (lcA, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); lcB= mapUp (lcB, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); fail= false; random_element= randomElement (m*lcA*lcB, V_buf, l, fail ); DEBOUTLN (cerr, "fail= " << fail); CFList list; TIMING_START (gcd_recursion); G_random_element= modGCDFq (ppA (random_element, x), ppB (random_element, x), coF_random_element, coG_random_element, V_buf, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); V_buf4= V_buf; } else { CFList list; TIMING_START (gcd_recursion); G_random_element= modGCDFq (ppA(random_element, x), ppB(random_element, x), coF_random_element, coG_random_element, V_buf, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 == 0) { if (inextension) { CFList u, v; ppA= mapDown (ppA, prim_elem_alpha, im_prim_elem_alpha, alpha, u, v); ppB= mapDown (ppB, prim_elem_alpha, im_prim_elem_alpha, alpha, u, v); prune1 (alpha); } coF= N (ppA*(cA/gcdcAcB)); coG= N (ppB*(cB/gcdcAcB)); return N(gcdcAcB); } if (d0 > d) { if (!find (l, random_element)) l.append (random_element); continue; } G_random_element= (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element)) * G_random_element; coF_random_element= (lcA(random_element,x)/uni_lcoeff(coF_random_element)) *coF_random_element; coG_random_element= (lcB(random_element,x)/uni_lcoeff(coG_random_element)) *coG_random_element; if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 < d) { m= gcdlcAlcB; newtonPoly= 1; G_m= 0; d= d0; coF_m= 0; coG_m= 0; } TIMING_START (newton_interpolation); H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x); coF= newtonInterp (random_element, coF_random_element, newtonPoly, coF_m,x); coG= newtonInterp (random_element, coG_random_element, newtonPoly, coG_m,x); TIMING_END_AND_PRINT (newton_interpolation, "time for newton interpolation: "); //termination test if ((uni_lcoeff (H) == gcdlcAlcB) || (G_m == H)) { TIMING_START (termination_test); if (gcdlcAlcB.isOne()) cH= 1; else cH= uni_content (H); ppH= H/cH; ppH /= Lc (ppH); CanonicalForm lcppH= gcdlcAlcB/cH; CanonicalForm ccoF= lcppH/Lc (lcppH); CanonicalForm ccoG= lcppH/Lc (lcppH); ppCoF= coF/ccoF; ppCoG= coG/ccoG; if (inextension) { if (((degree (ppCoF,1)+degree (ppH,1) == bound1) && (degree (ppCoG,1)+degree (ppH,1) == bound2) && terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) || (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG))) { CFList u, v; DEBOUTLN (cerr, "ppH before mapDown= " << ppH); ppH= mapDown (ppH, prim_elem_alpha, im_prim_elem_alpha, alpha, u, v); ppCoF= mapDown (ppCoF, prim_elem_alpha, im_prim_elem_alpha, alpha, u, v); ppCoG= mapDown (ppCoG, prim_elem_alpha, im_prim_elem_alpha, alpha, u, v); DEBOUTLN (cerr, "ppH after mapDown= " << ppH); coF= N ((cA/gcdcAcB)*ppCoF); coG= N ((cB/gcdcAcB)*ppCoG); TIMING_END_AND_PRINT (termination_test, "time for successful termination test Fq: "); prune1 (alpha); return N(gcdcAcB*ppH); } } else if (((degree (ppCoF,1)+degree (ppH,1) == bound1) && (degree (ppCoG,1)+degree (ppH,1) == bound2) && terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) || (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG))) { coF= N ((cA/gcdcAcB)*ppCoF); coG= N ((cB/gcdcAcB)*ppCoG); TIMING_END_AND_PRINT (termination_test, "time for successful termination test Fq: "); return N(gcdcAcB*ppH); } TIMING_END_AND_PRINT (termination_test, "time for unsuccessful termination test Fq: "); } G_m= H; coF_m= coF; coG_m= coG; newtonPoly= newtonPoly*(x - random_element); m= m*(x - random_element); if (!find (l, random_element)) l.append (random_element); } while (1); } /// compute a random element a of GF, s.t. F(a) \f$ \neq 0 \f$ , F is a /// univariate polynomial, returns fail if there are no field elements left /// which have not been used before static inline CanonicalForm GFRandomElement (const CanonicalForm& F, CFList& list, bool& fail) { fail= false; Variable x= F.mvar(); GFRandom genGF; CanonicalForm random; int p= getCharacteristic(); int d= getGFDegree(); int bound= ipower (p, d); do { if (list.length() == bound) { fail= true; break; } if (list.length() < 1) random= 0; else { random= genGF.generate(); while (find (list, random)) random= genGF.generate(); } if (F (random, x) == 0) { list.append (random); continue; } } while (find (list, random)); return random; } CanonicalForm modGCDGF (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& coF, CanonicalForm& coG, CFList& l, bool& topLevel); CanonicalForm modGCDGF (const CanonicalForm& F, const CanonicalForm& G, CFList& l, bool& topLevel) { CanonicalForm dummy1, dummy2; CanonicalForm result= modGCDGF (F, G, dummy1, dummy2, l, topLevel); return result; } /// GCD of F and G over GF, based on Alg. 7.2. as described in "Algorithms for /// Computer Algebra" by Geddes, Czapor, Labahn /// Usually this algorithm will be faster than modGCDFq since GF has /// faster field arithmetics, however it might fail if the input is large since /// the size of the base field is bounded by 2^16, output is monic CanonicalForm modGCDGF (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& coF, CanonicalForm& coG, CFList& l, bool& topLevel) { CanonicalForm A= F; CanonicalForm B= G; if (F.isZero() && degree(G) > 0) { coF= 0; coG= Lc (G); return G/Lc(G); } else if (G.isZero() && degree (F) > 0) { coF= Lc (F); coG= 0; return F/Lc(F); } else if (F.isZero() && G.isZero()) { coF= coG= 0; return F.genOne(); } if (F.inBaseDomain() || G.inBaseDomain()) { coF= F; coG= G; return F.genOne(); } if (F.isUnivariate() && fdivides(F, G, coG)) { coF= Lc (F); return F/Lc(F); } if (G.isUnivariate() && fdivides(G, F, coF)) { coG= Lc (G); return G/Lc(G); } if (F == G) { coF= coG= Lc (F); return F/Lc(F); } CFMap M,N; int best_level= myCompress (A, B, M, N, topLevel); if (best_level == 0) { coF= F; coG= G; return B.genOne(); } A= M(A); B= M(B); Variable x= Variable(1); //univariate case if (A.isUnivariate() && B.isUnivariate()) { CanonicalForm result= gcd (A, B); coF= N (A/result); coG= N (B/result); return N (result); } CanonicalForm cA, cB; // content of A and B CanonicalForm ppA, ppB; // primitive part of A and B CanonicalForm gcdcAcB; cA = uni_content (A); cB = uni_content (B); gcdcAcB= gcd (cA, cB); ppA= A/cA; ppB= B/cB; CanonicalForm lcA, lcB; // leading coefficients of A and B CanonicalForm gcdlcAlcB; lcA= uni_lcoeff (ppA); lcB= uni_lcoeff (ppB); gcdlcAlcB= gcd (lcA, lcB); int d= totaldegree (ppA, Variable(2), Variable (ppA.level())); if (d == 0) { coF= N (ppA*(cA/gcdcAcB)); coG= N (ppB*(cB/gcdcAcB)); return N(gcdcAcB); } int d0= totaldegree (ppB, Variable(2), Variable (ppB.level())); if (d0 < d) d= d0; if (d == 0) { coF= N (ppA*(cA/gcdcAcB)); coG= N (ppB*(cB/gcdcAcB)); return N(gcdcAcB); } CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH; CanonicalForm newtonPoly, coF_random_element, coG_random_element, coF_m, coG_m, ppCoF, ppCoG; newtonPoly= 1; m= gcdlcAlcB; G_m= 0; coF= 0; coG= 0; H= 0; bool fail= false; topLevel= false; bool inextension= false; int p=-1; int k= getGFDegree(); int kk; int expon; char gf_name_buf= gf_name; int bound1= degree (ppA, 1); int bound2= degree (ppB, 1); do { random_element= GFRandomElement (m*lcA*lcB, l, fail); if (fail) { p= getCharacteristic(); expon= 2; kk= getGFDegree(); if (ipower (p, kk*expon) < (1 << 16)) setCharacteristic (p, kk*(int)expon, 'b'); else { expon= (int) floor((log ((double)((1<<16) - 1)))/(log((double)p)*kk)); ASSERT (expon >= 2, "not enough points in modGCDGF"); setCharacteristic (p, (int)(kk*expon), 'b'); } inextension= true; fail= false; for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= GFMapUp (i.getItem(), kk); m= GFMapUp (m, kk); G_m= GFMapUp (G_m, kk); newtonPoly= GFMapUp (newtonPoly, kk); coF_m= GFMapUp (coF_m, kk); coG_m= GFMapUp (coG_m, kk); ppA= GFMapUp (ppA, kk); ppB= GFMapUp (ppB, kk); gcdlcAlcB= GFMapUp (gcdlcAlcB, kk); lcA= GFMapUp (lcA, kk); lcB= GFMapUp (lcB, kk); random_element= GFRandomElement (m*lcA*lcB, l, fail); DEBOUTLN (cerr, "fail= " << fail); CFList list; TIMING_START (gcd_recursion); G_random_element= modGCDGF (ppA(random_element, x), ppB(random_element, x), coF_random_element, coG_random_element, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else { CFList list; TIMING_START (gcd_recursion); G_random_element= modGCDGF (ppA(random_element, x), ppB(random_element, x), coF_random_element, coG_random_element, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 == 0) { if (inextension) { ppA= GFMapDown (ppA, k); ppB= GFMapDown (ppB, k); setCharacteristic (p, k, gf_name_buf); } coF= N (ppA*(cA/gcdcAcB)); coG= N (ppB*(cB/gcdcAcB)); return N(gcdcAcB); } if (d0 > d) { if (!find (l, random_element)) l.append (random_element); continue; } G_random_element= (gcdlcAlcB(random_element, x)/uni_lcoeff(G_random_element)) * G_random_element; coF_random_element= (lcA(random_element,x)/uni_lcoeff(coF_random_element)) *coF_random_element; coG_random_element= (lcB(random_element,x)/uni_lcoeff(coG_random_element)) *coG_random_element; if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 < d) { m= gcdlcAlcB; newtonPoly= 1; G_m= 0; d= d0; coF_m= 0; coG_m= 0; } TIMING_START (newton_interpolation); H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x); coF= newtonInterp (random_element, coF_random_element, newtonPoly, coF_m,x); coG= newtonInterp (random_element, coG_random_element, newtonPoly, coG_m,x); TIMING_END_AND_PRINT (newton_interpolation, "time for newton interpolation: "); //termination test if ((uni_lcoeff (H) == gcdlcAlcB) || (G_m == H)) { TIMING_START (termination_test); if (gcdlcAlcB.isOne()) cH= 1; else cH= uni_content (H); ppH= H/cH; ppH /= Lc (ppH); CanonicalForm lcppH= gcdlcAlcB/cH; CanonicalForm ccoF= lcppH/Lc (lcppH); CanonicalForm ccoG= lcppH/Lc (lcppH); ppCoF= coF/ccoF; ppCoG= coG/ccoG; if (inextension) { if (((degree (ppCoF,1)+degree (ppH,1) == bound1) && (degree (ppCoG,1)+degree (ppH,1) == bound2) && terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) || (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG))) { DEBOUTLN (cerr, "ppH before mapDown= " << ppH); ppH= GFMapDown (ppH, k); ppCoF= GFMapDown (ppCoF, k); ppCoG= GFMapDown (ppCoG, k); DEBOUTLN (cerr, "ppH after mapDown= " << ppH); coF= N ((cA/gcdcAcB)*ppCoF); coG= N ((cB/gcdcAcB)*ppCoG); setCharacteristic (p, k, gf_name_buf); TIMING_END_AND_PRINT (termination_test, "time for successful termination GF: "); return N(gcdcAcB*ppH); } } else { if (((degree (ppCoF,1)+degree (ppH,1) == bound1) && (degree (ppCoG,1)+degree (ppH,1) == bound2) && terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) || (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG))) { coF= N ((cA/gcdcAcB)*ppCoF); coG= N ((cB/gcdcAcB)*ppCoG); TIMING_END_AND_PRINT (termination_test, "time for successful termination GF: "); return N(gcdcAcB*ppH); } } TIMING_END_AND_PRINT (termination_test, "time for unsuccessful termination GF: "); } G_m= H; coF_m= coF; coG_m= coG; newtonPoly= newtonPoly*(x - random_element); m= m*(x - random_element); if (!find (l, random_element)) l.append (random_element); } while (1); } static inline CanonicalForm FpRandomElement (const CanonicalForm& F, CFList& list, bool& fail) { fail= false; Variable x= F.mvar(); FFRandom genFF; CanonicalForm random; int p= getCharacteristic(); int bound= p; do { if (list.length() == bound) { fail= true; break; } if (list.length() < 1) random= 0; else { random= genFF.generate(); while (find (list, random)) random= genFF.generate(); } if (F (random, x) == 0) { list.append (random); continue; } } while (find (list, random)); return random; } CanonicalForm modGCDFp (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& coF, CanonicalForm& coG, bool& topLevel, CFList& l); CanonicalForm modGCDFp (const CanonicalForm& F, const CanonicalForm& G, bool& topLevel, CFList& l) { CanonicalForm dummy1, dummy2; CanonicalForm result= modGCDFp (F, G, dummy1, dummy2, topLevel, l); return result; } CanonicalForm modGCDFp (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& coF, CanonicalForm& coG, bool& topLevel, CFList& l) { CanonicalForm A= F; CanonicalForm B= G; if (F.isZero() && degree(G) > 0) { coF= 0; coG= Lc (G); return G/Lc(G); } else if (G.isZero() && degree (F) > 0) { coF= Lc (F); coG= 0; return F/Lc(F); } else if (F.isZero() && G.isZero()) { coF= coG= 0; return F.genOne(); } if (F.inBaseDomain() || G.inBaseDomain()) { coF= F; coG= G; return F.genOne(); } if (F.isUnivariate() && fdivides(F, G, coG)) { coF= Lc (F); return F/Lc(F); } if (G.isUnivariate() && fdivides(G, F, coF)) { coG= Lc (G); return G/Lc(G); } if (F == G) { coF= coG= Lc (F); return F/Lc(F); } CFMap M,N; int best_level= myCompress (A, B, M, N, topLevel); if (best_level == 0) { coF= F; coG= G; return B.genOne(); } A= M(A); B= M(B); Variable x= Variable (1); //univariate case if (A.isUnivariate() && B.isUnivariate()) { CanonicalForm result= gcd (A, B); coF= N (A/result); coG= N (B/result); return N (result); } CanonicalForm cA, cB; // content of A and B CanonicalForm ppA, ppB; // primitive part of A and B CanonicalForm gcdcAcB; cA = uni_content (A); cB = uni_content (B); gcdcAcB= gcd (cA, cB); ppA= A/cA; ppB= B/cB; CanonicalForm lcA, lcB; // leading coefficients of A and B CanonicalForm gcdlcAlcB; lcA= uni_lcoeff (ppA); lcB= uni_lcoeff (ppB); gcdlcAlcB= gcd (lcA, lcB); int d= totaldegree (ppA, Variable (2), Variable (ppA.level())); int d0; if (d == 0) { coF= N (ppA*(cA/gcdcAcB)); coG= N (ppB*(cB/gcdcAcB)); return N(gcdcAcB); } d0= totaldegree (ppB, Variable (2), Variable (ppB.level())); if (d0 < d) d= d0; if (d == 0) { coF= N (ppA*(cA/gcdcAcB)); coG= N (ppB*(cB/gcdcAcB)); return N(gcdcAcB); } CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH; CanonicalForm newtonPoly, coF_random_element, coG_random_element, coF_m, coG_m, ppCoF, ppCoG; newtonPoly= 1; m= gcdlcAlcB; H= 0; coF= 0; coG= 0; G_m= 0; Variable alpha, V_buf, cleanUp; bool fail= false; bool inextension= false; topLevel= false; CFList source, dest; int bound1= degree (ppA, 1); int bound2= degree (ppB, 1); do { if (inextension) random_element= randomElement (m*lcA*lcB, V_buf, l, fail); else random_element= FpRandomElement (m*lcA*lcB, l, fail); if (!fail && !inextension) { CFList list; TIMING_START (gcd_recursion); G_random_element= modGCDFp (ppA (random_element,x), ppB (random_element,x), coF_random_element, coG_random_element, topLevel, list); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else if (!fail && inextension) { CFList list; TIMING_START (gcd_recursion); G_random_element= modGCDFq (ppA (random_element, x), ppB (random_element, x), coF_random_element, coG_random_element, V_buf, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else if (fail && !inextension) { source= CFList(); dest= CFList(); CFList list; CanonicalForm mipo; int deg= 2; bool initialized= false; do { mipo= randomIrredpoly (deg, x); if (initialized) setMipo (alpha, mipo); else alpha= rootOf (mipo); inextension= true; initialized= true; fail= false; random_element= randomElement (m*lcA*lcB, alpha, l, fail); deg++; } while (fail); list= CFList(); V_buf= alpha; cleanUp= alpha; TIMING_START (gcd_recursion); G_random_element= modGCDFq (ppA (random_element, x), ppB (random_element, x), coF_random_element, coG_random_element, alpha, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else if (fail && inextension) { source= CFList(); dest= CFList(); Variable V_buf3= V_buf; V_buf= chooseExtension (V_buf); bool prim_fail= false; Variable V_buf2; CanonicalForm prim_elem, im_prim_elem; prim_elem= primitiveElement (alpha, V_buf2, prim_fail); if (V_buf3 != alpha) { m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest); G_m= mapDown (G_m, prim_elem, im_prim_elem, alpha, source, dest); coF_m= mapDown (coF_m, prim_elem, im_prim_elem, alpha, source, dest); coG_m= mapDown (coG_m, prim_elem, im_prim_elem, alpha, source, dest); newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, alpha, source, dest); ppA= mapDown (ppA, prim_elem, im_prim_elem, alpha, source, dest); ppB= mapDown (ppB, prim_elem, im_prim_elem, alpha, source, dest); gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, alpha, source, dest); lcA= mapDown (lcA, prim_elem, im_prim_elem, alpha, source, dest); lcB= mapDown (lcB, prim_elem, im_prim_elem, alpha, source, dest); for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, alpha, source, dest); } ASSERT (!prim_fail, "failure in integer factorizer"); if (prim_fail) ; //ERROR else im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf); DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha)); DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2)); for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem, im_prim_elem, source, dest); m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest); G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest); coF_m= mapUp (coF_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest); coG_m= mapUp (coG_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest); newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem, source, dest); ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest); ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest); gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem, source, dest); lcA= mapUp (lcA, alpha, V_buf, prim_elem, im_prim_elem, source, dest); lcB= mapUp (lcB, alpha, V_buf, prim_elem, im_prim_elem, source, dest); fail= false; random_element= randomElement (m*lcA*lcB, V_buf, l, fail ); DEBOUTLN (cerr, "fail= " << fail); CFList list; TIMING_START (gcd_recursion); G_random_element= modGCDFq (ppA (random_element, x), ppB (random_element, x), coF_random_element, coG_random_element, V_buf, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); alpha= V_buf; } if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 == 0) { if (inextension) prune (cleanUp); coF= N (ppA*(cA/gcdcAcB)); coG= N (ppB*(cB/gcdcAcB)); return N(gcdcAcB); } if (d0 > d) { if (!find (l, random_element)) l.append (random_element); continue; } G_random_element= (gcdlcAlcB(random_element,x)/uni_lcoeff(G_random_element)) *G_random_element; coF_random_element= (lcA(random_element,x)/uni_lcoeff(coF_random_element)) *coF_random_element; coG_random_element= (lcB(random_element,x)/uni_lcoeff(coG_random_element)) *coG_random_element; if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 < d) { m= gcdlcAlcB; newtonPoly= 1; G_m= 0; d= d0; coF_m= 0; coG_m= 0; } TIMING_START (newton_interpolation); H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x); coF= newtonInterp (random_element, coF_random_element, newtonPoly, coF_m,x); coG= newtonInterp (random_element, coG_random_element, newtonPoly, coG_m,x); TIMING_END_AND_PRINT (newton_interpolation, "time for newton_interpolation: "); //termination test if ((uni_lcoeff (H) == gcdlcAlcB) || (G_m == H)) { TIMING_START (termination_test); if (gcdlcAlcB.isOne()) cH= 1; else cH= uni_content (H); ppH= H/cH; ppH /= Lc (ppH); CanonicalForm lcppH= gcdlcAlcB/cH; CanonicalForm ccoF= lcppH/Lc (lcppH); CanonicalForm ccoG= lcppH/Lc (lcppH); ppCoF= coF/ccoF; ppCoG= coG/ccoG; DEBOUTLN (cerr, "ppH= " << ppH); if (((degree (ppCoF,1)+degree (ppH,1) == bound1) && (degree (ppCoG,1)+degree (ppH,1) == bound2) && terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) || (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG))) { if (inextension) prune (cleanUp); coF= N ((cA/gcdcAcB)*ppCoF); coG= N ((cB/gcdcAcB)*ppCoG); TIMING_END_AND_PRINT (termination_test, "time for successful termination Fp: "); return N(gcdcAcB*ppH); } TIMING_END_AND_PRINT (termination_test, "time for unsuccessful termination Fp: "); } G_m= H; coF_m= coF; coG_m= coG; newtonPoly= newtonPoly*(x - random_element); m= m*(x - random_element); if (!find (l, random_element)) l.append (random_element); } while (1); } CFArray solveVandermonde (const CFArray& M, const CFArray& A) { int r= M.size(); ASSERT (A.size() == r, "vector does not have right size"); if (r == 1) { CFArray result= CFArray (1); result [0]= A [0] / M [0]; return result; } // check solvability bool notDistinct= false; for (int i= 0; i < r - 1; i++) { for (int j= i + 1; j < r; j++) { if (M [i] == M [j]) { notDistinct= true; break; } } } if (notDistinct) return CFArray(); CanonicalForm master= 1; Variable x= Variable (1); for (int i= 0; i < r; i++) master *= x - M [i]; CFList Pj; CanonicalForm tmp; for (int i= 0; i < r; i++) { tmp= master/(x - M [i]); tmp /= tmp (M [i], 1); Pj.append (tmp); } CFArray result= CFArray (r); CFListIterator j= Pj; for (int i= 1; i <= r; i++, j++) { tmp= 0; for (int l= 0; l < A.size(); l++) tmp += A[l]*j.getItem()[l]; result[i - 1]= tmp; } return result; } CFArray solveGeneralVandermonde (const CFArray& M, const CFArray& A) { int r= M.size(); ASSERT (A.size() == r, "vector does not have right size"); if (r == 1) { CFArray result= CFArray (1); result [0]= A[0] / M [0]; return result; } // check solvability bool notDistinct= false; for (int i= 0; i < r - 1; i++) { for (int j= i + 1; j < r; j++) { if (M [i] == M [j]) { notDistinct= true; break; } } } if (notDistinct) return CFArray(); CanonicalForm master= 1; Variable x= Variable (1); for (int i= 0; i < r; i++) master *= x - M [i]; master *= x; CFList Pj; CanonicalForm tmp; for (int i= 0; i < r; i++) { tmp= master/(x - M [i]); tmp /= tmp (M [i], 1); Pj.append (tmp); } CFArray result= CFArray (r); CFListIterator j= Pj; for (int i= 1; i <= r; i++, j++) { tmp= 0; for (int l= 1; l <= A.size(); l++) tmp += A[l - 1]*j.getItem()[l]; result[i - 1]= tmp; } return result; } /// M in row echolon form, rk rank of M CFArray readOffSolution (const CFMatrix& M, const long rk) { CFArray result= CFArray (rk); CanonicalForm tmp1, tmp2, tmp3; for (int i= rk; i >= 1; i--) { tmp3= 0; tmp1= M (i, M.columns()); for (int j= M.columns() - 1; j >= 1; j--) { tmp2= M (i, j); if (j == i) break; else tmp3 += tmp2*result[j - 1]; } result[i - 1]= (tmp1 - tmp3)/tmp2; } return result; } CFArray readOffSolution (const CFMatrix& M, const CFArray& L, const CFArray& partialSol) { CFArray result= CFArray (M.rows()); CanonicalForm tmp1, tmp2, tmp3; int k; for (int i= M.rows(); i >= 1; i--) { tmp3= 0; tmp1= L[i - 1]; k= 0; for (int j= M.columns(); j >= 1; j--, k++) { tmp2= M (i, j); if (j == i) break; else { if (k > partialSol.size() - 1) tmp3 += tmp2*result[j - 1]; else tmp3 += tmp2*partialSol[partialSol.size() - k - 1]; } } result [i - 1]= (tmp1 - tmp3)/tmp2; } return result; } long gaussianElimFp (CFMatrix& M, CFArray& L) { ASSERT (L.size() <= M.rows(), "dimension exceeded"); CFMatrix *N; N= new CFMatrix (M.rows(), M.columns() + 1); for (int i= 1; i <= M.rows(); i++) for (int j= 1; j <= M.columns(); j++) (*N) (i, j)= M (i, j); int j= 1; for (int i= 0; i < L.size(); i++, j++) (*N) (j, M.columns() + 1)= L[i]; #ifdef HAVE_FLINT nmod_mat_t FLINTN; convertFacCFMatrix2nmod_mat_t (FLINTN, *N); long rk= nmod_mat_rref (FLINTN); delete N; N= convertNmod_mat_t2FacCFMatrix (FLINTN); nmod_mat_clear (FLINTN); #else int p= getCharacteristic (); if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } mat_zz_p *NTLN= convertFacCFMatrix2NTLmat_zz_p(*N); delete N; long rk= gauss (*NTLN); N= convertNTLmat_zz_p2FacCFMatrix (*NTLN); delete NTLN; #endif L= CFArray (M.rows()); for (int i= 0; i < M.rows(); i++) L[i]= (*N) (i + 1, M.columns() + 1); M= (*N) (1, M.rows(), 1, M.columns()); delete N; return rk; } long gaussianElimFq (CFMatrix& M, CFArray& L, const Variable& alpha) { ASSERT (L.size() <= M.rows(), "dimension exceeded"); CFMatrix *N; N= new CFMatrix (M.rows(), M.columns() + 1); for (int i= 1; i <= M.rows(); i++) for (int j= 1; j <= M.columns(); j++) (*N) (i, j)= M (i, j); int j= 1; for (int i= 0; i < L.size(); i++, j++) (*N) (j, M.columns() + 1)= L[i]; int p= getCharacteristic (); if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha)); zz_pE::init (NTLMipo); mat_zz_pE *NTLN= convertFacCFMatrix2NTLmat_zz_pE(*N); long rk= gauss (*NTLN); delete N; N= convertNTLmat_zz_pE2FacCFMatrix (*NTLN, alpha); delete NTLN; M= (*N) (1, M.rows(), 1, M.columns()); L= CFArray (M.rows()); for (int i= 0; i < M.rows(); i++) L[i]= (*N) (i + 1, M.columns() + 1); delete N; return rk; } CFArray solveSystemFp (const CFMatrix& M, const CFArray& L) { ASSERT (L.size() <= M.rows(), "dimension exceeded"); CFMatrix *N; N= new CFMatrix (M.rows(), M.columns() + 1); for (int i= 1; i <= M.rows(); i++) for (int j= 1; j <= M.columns(); j++) (*N) (i, j)= M (i, j); int j= 1; for (int i= 0; i < L.size(); i++, j++) (*N) (j, M.columns() + 1)= L[i]; #ifdef HAVE_FLINT nmod_mat_t FLINTN; convertFacCFMatrix2nmod_mat_t (FLINTN, *N); long rk= nmod_mat_rref (FLINTN); #else int p= getCharacteristic (); if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } mat_zz_p *NTLN= convertFacCFMatrix2NTLmat_zz_p(*N); long rk= gauss (*NTLN); #endif delete N; if (rk != M.columns()) { #ifdef HAVE_FLINT nmod_mat_clear (FLINTN); #else delete NTLN; #endif return CFArray(); } #ifdef HAVE_FLINT N= convertNmod_mat_t2FacCFMatrix (FLINTN); nmod_mat_clear (FLINTN); #else N= convertNTLmat_zz_p2FacCFMatrix (*NTLN); delete NTLN; #endif CFArray A= readOffSolution (*N, rk); delete N; return A; } CFArray solveSystemFq (const CFMatrix& M, const CFArray& L, const Variable& alpha) { ASSERT (L.size() <= M.rows(), "dimension exceeded"); CFMatrix *N; N= new CFMatrix (M.rows(), M.columns() + 1); for (int i= 1; i <= M.rows(); i++) for (int j= 1; j <= M.columns(); j++) (*N) (i, j)= M (i, j); int j= 1; for (int i= 0; i < L.size(); i++, j++) (*N) (j, M.columns() + 1)= L[i]; int p= getCharacteristic (); if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha)); zz_pE::init (NTLMipo); mat_zz_pE *NTLN= convertFacCFMatrix2NTLmat_zz_pE(*N); long rk= gauss (*NTLN); delete N; if (rk != M.columns()) { delete NTLN; return CFArray(); } N= convertNTLmat_zz_pE2FacCFMatrix (*NTLN, alpha); delete NTLN; CFArray A= readOffSolution (*N, rk); delete N; return A; } #endif CFArray getMonoms (const CanonicalForm& F) { if (F.inCoeffDomain()) { CFArray result= CFArray (1); result [0]= 1; return result; } if (F.isUnivariate()) { CFArray result= CFArray (size(F)); int j= 0; for (CFIterator i= F; i.hasTerms(); i++, j++) result[j]= power (F.mvar(), i.exp()); return result; } int numMon= size (F); CFArray result= CFArray (numMon); int j= 0; CFArray recResult; Variable x= F.mvar(); CanonicalForm powX; for (CFIterator i= F; i.hasTerms(); i++) { powX= power (x, i.exp()); recResult= getMonoms (i.coeff()); for (int k= 0; k < recResult.size(); k++) result[j+k]= powX*recResult[k]; j += recResult.size(); } return result; } #ifdef HAVE_NTL CFArray evaluateMonom (const CanonicalForm& F, const CFList& evalPoints) { if (F.inCoeffDomain()) { CFArray result= CFArray (1); result [0]= F; return result; } if (F.isUnivariate()) { ASSERT (evalPoints.length() == 1, "expected an eval point with only one component"); CFArray result= CFArray (size(F)); int j= 0; CanonicalForm evalPoint= evalPoints.getLast(); for (CFIterator i= F; i.hasTerms(); i++, j++) result[j]= power (evalPoint, i.exp()); return result; } int numMon= size (F); CFArray result= CFArray (numMon); int j= 0; CanonicalForm evalPoint= evalPoints.getLast(); CFList buf= evalPoints; buf.removeLast(); CFArray recResult; CanonicalForm powEvalPoint; for (CFIterator i= F; i.hasTerms(); i++) { powEvalPoint= power (evalPoint, i.exp()); recResult= evaluateMonom (i.coeff(), buf); for (int k= 0; k < recResult.size(); k++) result[j+k]= powEvalPoint*recResult[k]; j += recResult.size(); } return result; } CFArray evaluate (const CFArray& A, const CFList& evalPoints) { CFArray result= A.size(); CanonicalForm tmp; int k; for (int i= 0; i < A.size(); i++) { tmp= A[i]; k= 1; for (CFListIterator j= evalPoints; j.hasItem(); j++, k++) tmp= tmp (j.getItem(), k); result[i]= tmp; } return result; } CFList evaluationPoints (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Feval, CanonicalForm& Geval, const CanonicalForm& LCF, const bool& GF, const Variable& alpha, bool& fail, CFList& list ) { int k= tmax (F.level(), G.level()) - 1; Variable x= Variable (1); CFList result; FFRandom genFF; GFRandom genGF; int p= getCharacteristic (); double bound; if (alpha != Variable (1)) { bound= pow ((double) p, (double) degree (getMipo(alpha))); bound= pow (bound, (double) k); } else if (GF) { bound= pow ((double) p, (double) getGFDegree()); bound= pow ((double) bound, (double) k); } else bound= pow ((double) p, (double) k); CanonicalForm random; int j; bool zeroOneOccured= false; bool allEqual= false; CanonicalForm buf; do { random= 0; // possible overflow if list.length() does not fit into a int if (list.length() >= bound) { fail= true; break; } for (int i= 0; i < k; i++) { if (GF) { result.append (genGF.generate()); random += result.getLast()*power (x, i); } else if (alpha.level() != 1) { AlgExtRandomF genAlgExt (alpha); result.append (genAlgExt.generate()); random += result.getLast()*power (x, i); } else { result.append (genFF.generate()); random += result.getLast()*power (x, i); } if (result.getLast().isOne() || result.getLast().isZero()) zeroOneOccured= true; } if (find (list, random)) { zeroOneOccured= false; allEqual= false; result= CFList(); continue; } if (zeroOneOccured) { list.append (random); zeroOneOccured= false; allEqual= false; result= CFList(); continue; } // no zero at this point if (k > 1) { allEqual= true; CFIterator iter= random; buf= iter.coeff(); iter++; for (; iter.hasTerms(); iter++) if (buf != iter.coeff()) allEqual= false; } if (allEqual) { list.append (random); allEqual= false; zeroOneOccured= false; result= CFList(); continue; } Feval= F; Geval= G; CanonicalForm LCeval= LCF; j= 1; for (CFListIterator i= result; i.hasItem(); i++, j++) { Feval= Feval (i.getItem(), j); Geval= Geval (i.getItem(), j); LCeval= LCeval (i.getItem(), j); } if (LCeval.isZero()) { if (!find (list, random)) list.append (random); zeroOneOccured= false; allEqual= false; result= CFList(); continue; } if (list.length() >= bound) { fail= true; break; } } while (find (list, random)); return result; } /// multiply two lists componentwise void mult (CFList& L1, const CFList& L2) { ASSERT (L1.length() == L2.length(), "lists of the same size expected"); CFListIterator j= L2; for (CFListIterator i= L1; i.hasItem(); i++, j++) i.getItem() *= j.getItem(); } void eval (const CanonicalForm& A, const CanonicalForm& B, CanonicalForm& Aeval, CanonicalForm& Beval, const CFList& L) { Aeval= A; Beval= B; int j= 1; for (CFListIterator i= L; i.hasItem(); i++, j++) { Aeval= Aeval (i.getItem(), j); Beval= Beval (i.getItem(), j); } } CanonicalForm monicSparseInterpol (const CanonicalForm& F, const CanonicalForm& G, const CanonicalForm& skeleton, const Variable& alpha, bool& fail, CFArray*& coeffMonoms, CFArray& Monoms ) { CanonicalForm A= F; CanonicalForm B= G; if (F.isZero() && degree(G) > 0) return G/Lc(G); else if (G.isZero() && degree (F) > 0) return F/Lc(F); else if (F.isZero() && G.isZero()) return F.genOne(); if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne(); if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F); if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G); if (F == G) return F/Lc(F); ASSERT (degree (A, 1) == 0, "expected degree (F, 1) == 0"); ASSERT (degree (B, 1) == 0, "expected degree (G, 1) == 0"); CFMap M,N; int best_level= myCompress (A, B, M, N, false); if (best_level == 0) return B.genOne(); A= M(A); B= M(B); Variable x= Variable (1); //univariate case if (A.isUnivariate() && B.isUnivariate()) return N (gcd (A, B)); CanonicalForm skel= M(skeleton); CanonicalForm cA, cB; // content of A and B CanonicalForm ppA, ppB; // primitive part of A and B CanonicalForm gcdcAcB; cA = uni_content (A); cB = uni_content (B); gcdcAcB= gcd (cA, cB); ppA= A/cA; ppB= B/cB; CanonicalForm lcA, lcB; // leading coefficients of A and B CanonicalForm gcdlcAlcB; lcA= uni_lcoeff (ppA); lcB= uni_lcoeff (ppB); if (fdivides (lcA, lcB)) { if (fdivides (A, B)) return F/Lc(F); } if (fdivides (lcB, lcA)) { if (fdivides (B, A)) return G/Lc(G); } gcdlcAlcB= gcd (lcA, lcB); int skelSize= size (skel, skel.mvar()); int j= 0; int biggestSize= 0; for (CFIterator i= skel; i.hasTerms(); i++, j++) biggestSize= tmax (biggestSize, size (i.coeff())); CanonicalForm g, Aeval, Beval; CFList evalPoints; bool evalFail= false; CFList list; bool GF= false; CanonicalForm LCA= LC (A); CanonicalForm tmp; CFArray gcds= CFArray (biggestSize); CFList * pEvalPoints= new CFList [biggestSize]; Variable V_buf= alpha, V_buf4= alpha; CFList source, dest; CanonicalForm prim_elem, im_prim_elem; CanonicalForm prim_elem_alpha, im_prim_elem_alpha; for (int i= 0; i < biggestSize; i++) { if (i == 0) evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf, evalFail, list); else { mult (evalPoints, pEvalPoints [0]); eval (A, B, Aeval, Beval, evalPoints); } if (evalFail) { if (V_buf.level() != 1) { do { Variable V_buf3= V_buf; V_buf= chooseExtension (V_buf); source= CFList(); dest= CFList(); bool prim_fail= false; Variable V_buf2; prim_elem= primitiveElement (V_buf4, V_buf2, prim_fail); if (V_buf4 == alpha && alpha.level() != 1) prim_elem_alpha= prim_elem; ASSERT (!prim_fail, "failure in integer factorizer"); if (prim_fail) ; //ERROR else im_prim_elem= mapPrimElem (prim_elem, V_buf4, V_buf); DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf)); DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2)); if (V_buf4 == alpha && alpha.level() != 1) im_prim_elem_alpha= im_prim_elem; else if (alpha.level() != 1) im_prim_elem_alpha= mapUp (im_prim_elem_alpha, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); for (CFListIterator j= list; j.hasItem(); j++) j.getItem()= mapUp (j.getItem(), V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); for (int k= 0; k < i; k++) { for (CFListIterator j= pEvalPoints[k]; j.hasItem(); j++) j.getItem()= mapUp (j.getItem(), V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); gcds[k]= mapUp (gcds[k], V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); } if (alpha.level() != 1) { A= mapUp (A, V_buf4, V_buf, prim_elem, im_prim_elem, source,dest); B= mapUp (B, V_buf4, V_buf, prim_elem, im_prim_elem, source,dest); } V_buf4= V_buf; evalFail= false; evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf, evalFail, list); } while (evalFail); } else { CanonicalForm mipo; int deg= 2; bool initialized= false; do { mipo= randomIrredpoly (deg, x); if (initialized) setMipo (V_buf, mipo); else V_buf= rootOf (mipo); evalFail= false; initialized= true; evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf, evalFail, list); deg++; } while (evalFail); V_buf4= V_buf; } } g= gcd (Aeval, Beval); g /= Lc (g); if (degree (g) != degree (skel) || (skelSize != size (g))) { delete[] pEvalPoints; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } CFIterator l= skel; for (CFIterator k= g; k.hasTerms(); k++, l++) { if (k.exp() != l.exp()) { delete[] pEvalPoints; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } } pEvalPoints[i]= evalPoints; gcds[i]= g; tmp= 0; int j= 0; for (CFListIterator k= evalPoints; k.hasItem(); k++, j++) tmp += k.getItem()*power (x, j); list.append (tmp); } if (Monoms.size() == 0) Monoms= getMonoms (skel); coeffMonoms= new CFArray [skelSize]; j= 0; for (CFIterator i= skel; i.hasTerms(); i++, j++) coeffMonoms[j]= getMonoms (i.coeff()); CFArray* pL= new CFArray [skelSize]; CFArray* pM= new CFArray [skelSize]; for (int i= 0; i < biggestSize; i++) { CFIterator l= gcds [i]; evalPoints= pEvalPoints [i]; for (int k= 0; k < skelSize; k++, l++) { if (i == 0) pL[k]= CFArray (biggestSize); pL[k] [i]= l.coeff(); if (i == 0) pM[k]= evaluate (coeffMonoms [k], evalPoints); } } CFArray solution; CanonicalForm result= 0; int ind= 0; CFArray bufArray; CFMatrix Mat; for (int k= 0; k < skelSize; k++) { if (biggestSize != coeffMonoms[k].size()) { bufArray= CFArray (coeffMonoms[k].size()); for (int i= 0; i < coeffMonoms[k].size(); i++) bufArray [i]= pL[k] [i]; solution= solveGeneralVandermonde (pM [k], bufArray); } else solution= solveGeneralVandermonde (pM [k], pL[k]); if (solution.size() == 0) { delete[] pEvalPoints; delete[] pM; delete[] pL; delete[] coeffMonoms; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } for (int l= 0; l < solution.size(); l++) result += solution[l]*Monoms [ind + l]; ind += solution.size(); } delete[] pEvalPoints; delete[] pM; delete[] pL; delete[] coeffMonoms; if (alpha.level() != 1 && V_buf != alpha) { CFList u, v; result= mapDown (result, prim_elem_alpha, im_prim_elem_alpha, alpha, u, v); prune1 (alpha); } result= N(result); if (fdivides (result, F) && fdivides (result, G)) return result; else { fail= true; return 0; } } CanonicalForm nonMonicSparseInterpol (const CanonicalForm& F, const CanonicalForm& G, const CanonicalForm& skeleton, const Variable& alpha, bool& fail, CFArray*& coeffMonoms, CFArray& Monoms ) { CanonicalForm A= F; CanonicalForm B= G; if (F.isZero() && degree(G) > 0) return G/Lc(G); else if (G.isZero() && degree (F) > 0) return F/Lc(F); else if (F.isZero() && G.isZero()) return F.genOne(); if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne(); if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F); if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G); if (F == G) return F/Lc(F); ASSERT (degree (A, 1) == 0, "expected degree (F, 1) == 0"); ASSERT (degree (B, 1) == 0, "expected degree (G, 1) == 0"); CFMap M,N; int best_level= myCompress (A, B, M, N, false); if (best_level == 0) return B.genOne(); A= M(A); B= M(B); Variable x= Variable (1); //univariate case if (A.isUnivariate() && B.isUnivariate()) return N (gcd (A, B)); CanonicalForm skel= M(skeleton); CanonicalForm cA, cB; // content of A and B CanonicalForm ppA, ppB; // primitive part of A and B CanonicalForm gcdcAcB; cA = uni_content (A); cB = uni_content (B); gcdcAcB= gcd (cA, cB); ppA= A/cA; ppB= B/cB; CanonicalForm lcA, lcB; // leading coefficients of A and B CanonicalForm gcdlcAlcB; lcA= uni_lcoeff (ppA); lcB= uni_lcoeff (ppB); if (fdivides (lcA, lcB)) { if (fdivides (A, B)) return F/Lc(F); } if (fdivides (lcB, lcA)) { if (fdivides (B, A)) return G/Lc(G); } gcdlcAlcB= gcd (lcA, lcB); int skelSize= size (skel, skel.mvar()); int j= 0; int biggestSize= 0; int bufSize; int numberUni= 0; for (CFIterator i= skel; i.hasTerms(); i++, j++) { bufSize= size (i.coeff()); biggestSize= tmax (biggestSize, bufSize); numberUni += bufSize; } numberUni--; numberUni= (int) ceil ( (double) numberUni / (skelSize - 1)); biggestSize= tmax (biggestSize , numberUni); numberUni= biggestSize + size (LC(skel)) - 1; int biggestSize2= tmax (numberUni, biggestSize); CanonicalForm g, Aeval, Beval; CFList evalPoints; CFArray coeffEval; bool evalFail= false; CFList list; bool GF= false; CanonicalForm LCA= LC (A); CanonicalForm tmp; CFArray gcds= CFArray (biggestSize); CFList * pEvalPoints= new CFList [biggestSize]; Variable V_buf= alpha, V_buf4= alpha; CFList source, dest; CanonicalForm prim_elem, im_prim_elem; CanonicalForm prim_elem_alpha, im_prim_elem_alpha; for (int i= 0; i < biggestSize; i++) { if (i == 0) { if (getCharacteristic() > 3) evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf, evalFail, list); else evalFail= true; if (evalFail) { if (V_buf.level() != 1) { do { Variable V_buf3= V_buf; V_buf= chooseExtension (V_buf); source= CFList(); dest= CFList(); bool prim_fail= false; Variable V_buf2; prim_elem= primitiveElement (V_buf4, V_buf2, prim_fail); if (V_buf4 == alpha && alpha.level() != 1) prim_elem_alpha= prim_elem; ASSERT (!prim_fail, "failure in integer factorizer"); if (prim_fail) ; //ERROR else im_prim_elem= mapPrimElem (prim_elem, V_buf4, V_buf); DEBOUTLN (cerr, "getMipo (V_buf)= " << getMipo (V_buf)); DEBOUTLN (cerr, "getMipo (V_buf2)= " << getMipo (V_buf2)); if (V_buf4 == alpha && alpha.level() != 1) im_prim_elem_alpha= im_prim_elem; else if (alpha.level() != 1) im_prim_elem_alpha= mapUp (im_prim_elem_alpha, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); for (CFListIterator i= list; i.hasItem(); i++) i.getItem()= mapUp (i.getItem(), V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); if (alpha.level() != 1) { A= mapUp (A, V_buf4, V_buf, prim_elem, im_prim_elem, source,dest); B= mapUp (B, V_buf4, V_buf, prim_elem, im_prim_elem, source,dest); } evalFail= false; V_buf4= V_buf; evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf, evalFail, list); } while (evalFail); } else { CanonicalForm mipo; int deg= 2; bool initialized= false; do { mipo= randomIrredpoly (deg, x); if (initialized) setMipo (V_buf, mipo); else V_buf= rootOf (mipo); evalFail= false; initialized= true; evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf, evalFail, list); deg++; } while (evalFail); V_buf4= V_buf; } } } else { mult (evalPoints, pEvalPoints[0]); eval (A, B, Aeval, Beval, evalPoints); } g= gcd (Aeval, Beval); g /= Lc (g); if (degree (g) != degree (skel) || (skelSize != size (g))) { delete[] pEvalPoints; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } CFIterator l= skel; for (CFIterator k= g; k.hasTerms(); k++, l++) { if (k.exp() != l.exp()) { delete[] pEvalPoints; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } } pEvalPoints[i]= evalPoints; gcds[i]= g; tmp= 0; int j= 0; for (CFListIterator k= evalPoints; k.hasItem(); k++, j++) tmp += k.getItem()*power (x, j); list.append (tmp); } if (Monoms.size() == 0) Monoms= getMonoms (skel); coeffMonoms= new CFArray [skelSize]; j= 0; for (CFIterator i= skel; i.hasTerms(); i++, j++) coeffMonoms[j]= getMonoms (i.coeff()); int minimalColumnsIndex; if (skelSize > 1) minimalColumnsIndex= 1; else minimalColumnsIndex= 0; int minimalColumns=-1; CFArray* pM= new CFArray [skelSize]; CFMatrix Mat; // find the Matrix with minimal number of columns for (int i= 0; i < skelSize; i++) { pM[i]= CFArray (coeffMonoms[i].size()); if (i == 1) minimalColumns= coeffMonoms[i].size(); if (i > 1) { if (minimalColumns > coeffMonoms[i].size()) { minimalColumns= coeffMonoms[i].size(); minimalColumnsIndex= i; } } } CFMatrix* pMat= new CFMatrix [2]; pMat[0]= CFMatrix (biggestSize, coeffMonoms[0].size()); pMat[1]= CFMatrix (biggestSize, coeffMonoms[minimalColumnsIndex].size()); CFArray* pL= new CFArray [skelSize]; for (int i= 0; i < biggestSize; i++) { CFIterator l= gcds [i]; evalPoints= pEvalPoints [i]; for (int k= 0; k < skelSize; k++, l++) { if (i == 0) pL[k]= CFArray (biggestSize); pL[k] [i]= l.coeff(); if (i == 0 && k != 0 && k != minimalColumnsIndex) pM[k]= evaluate (coeffMonoms[k], evalPoints); else if (i == 0 && (k == 0 || k == minimalColumnsIndex)) coeffEval= evaluate (coeffMonoms[k], evalPoints); if (i > 0 && (k == 0 || k == minimalColumnsIndex)) coeffEval= evaluate (coeffMonoms[k], evalPoints); if (k == 0) { if (pMat[k].rows() >= i + 1) { for (int ind= 1; ind < coeffEval.size() + 1; ind++) pMat[k] (i + 1, ind)= coeffEval[ind - 1]; } } if (k == minimalColumnsIndex) { if (pMat[1].rows() >= i + 1) { for (int ind= 1; ind < coeffEval.size() + 1; ind++) pMat[1] (i + 1, ind)= coeffEval[ind - 1]; } } } } CFArray solution; CanonicalForm result= 0; int ind= 1; int matRows, matColumns; matRows= pMat[1].rows(); matColumns= pMat[0].columns() - 1; matColumns += pMat[1].columns(); Mat= CFMatrix (matRows, matColumns); for (int i= 1; i <= matRows; i++) for (int j= 1; j <= pMat[1].columns(); j++) Mat (i, j)= pMat[1] (i, j); for (int j= pMat[1].columns() + 1; j <= matColumns; j++, ind++) { for (int i= 1; i <= matRows; i++) Mat (i, j)= (-pMat [0] (i, ind + 1))*pL[minimalColumnsIndex] [i - 1]; } CFArray firstColumn= CFArray (pMat[0].rows()); for (int i= 0; i < pMat[0].rows(); i++) firstColumn [i]= pMat[0] (i + 1, 1); CFArray bufArray= pL[minimalColumnsIndex]; for (int i= 0; i < biggestSize; i++) pL[minimalColumnsIndex] [i] *= firstColumn[i]; CFMatrix bufMat= pMat[1]; pMat[1]= Mat; if (V_buf.level() != 1) solution= solveSystemFq (pMat[1], pL[minimalColumnsIndex], V_buf); else solution= solveSystemFp (pMat[1], pL[minimalColumnsIndex]); if (solution.size() == 0) { //Javadi's method failed, try deKleine, Monagan, Wittkopf instead CFMatrix bufMat0= pMat[0]; delete [] pMat; pMat= new CFMatrix [skelSize]; pL[minimalColumnsIndex]= bufArray; CFList* bufpEvalPoints= NULL; CFArray bufGcds; if (biggestSize != biggestSize2) { bufpEvalPoints= pEvalPoints; pEvalPoints= new CFList [biggestSize2]; bufGcds= gcds; gcds= CFArray (biggestSize2); for (int i= 0; i < biggestSize; i++) { pEvalPoints[i]= bufpEvalPoints [i]; gcds[i]= bufGcds[i]; } for (int i= 0; i < biggestSize2 - biggestSize; i++) { mult (evalPoints, pEvalPoints[0]); eval (A, B, Aeval, Beval, evalPoints); g= gcd (Aeval, Beval); g /= Lc (g); if (degree (g) != degree (skel) || (skelSize != size (g))) { delete[] pEvalPoints; delete[] pMat; delete[] pL; delete[] coeffMonoms; delete[] pM; if (bufpEvalPoints != NULL) delete [] bufpEvalPoints; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } CFIterator l= skel; for (CFIterator k= g; k.hasTerms(); k++, l++) { if (k.exp() != l.exp()) { delete[] pEvalPoints; delete[] pMat; delete[] pL; delete[] coeffMonoms; delete[] pM; if (bufpEvalPoints != NULL) delete [] bufpEvalPoints; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } } pEvalPoints[i + biggestSize]= evalPoints; gcds[i + biggestSize]= g; } } for (int i= 0; i < biggestSize; i++) { CFIterator l= gcds [i]; evalPoints= pEvalPoints [i]; for (int k= 1; k < skelSize; k++, l++) { if (i == 0) pMat[k]= CFMatrix (biggestSize2,coeffMonoms[k].size()+biggestSize2-1); if (k == minimalColumnsIndex) continue; coeffEval= evaluate (coeffMonoms[k], evalPoints); if (pMat[k].rows() >= i + 1) { for (int ind= 1; ind < coeffEval.size() + 1; ind++) pMat[k] (i + 1, ind)= coeffEval[ind - 1]; } } } Mat= bufMat0; pMat[0]= CFMatrix (biggestSize2, coeffMonoms[0].size() + biggestSize2 - 1); for (int j= 1; j <= Mat.rows(); j++) for (int k= 1; k <= Mat.columns(); k++) pMat [0] (j,k)= Mat (j,k); Mat= bufMat; for (int j= 1; j <= Mat.rows(); j++) for (int k= 1; k <= Mat.columns(); k++) pMat [minimalColumnsIndex] (j,k)= Mat (j,k); // write old matrix entries into new matrices for (int i= 0; i < skelSize; i++) { bufArray= pL[i]; pL[i]= CFArray (biggestSize2); for (int j= 0; j < bufArray.size(); j++) pL[i] [j]= bufArray [j]; } //write old vector entries into new and add new entries to old matrices for (int i= 0; i < biggestSize2 - biggestSize; i++) { CFIterator l= gcds [i + biggestSize]; evalPoints= pEvalPoints [i + biggestSize]; for (int k= 0; k < skelSize; k++, l++) { pL[k] [i + biggestSize]= l.coeff(); coeffEval= evaluate (coeffMonoms[k], evalPoints); if (pMat[k].rows() >= i + biggestSize + 1) { for (int ind= 1; ind < coeffEval.size() + 1; ind++) pMat[k] (i + biggestSize + 1, ind)= coeffEval[ind - 1]; } } } // begin new for (int i= 0; i < skelSize; i++) { if (pL[i].size() > 1) { for (int j= 2; j <= pMat[i].rows(); j++) pMat[i] (j, coeffMonoms[i].size() + j - 1)= -pL[i] [j - 1]; } } matColumns= biggestSize2 - 1; matRows= 0; for (int i= 0; i < skelSize; i++) { if (V_buf.level() == 1) (void) gaussianElimFp (pMat[i], pL[i]); else (void) gaussianElimFq (pMat[i], pL[i], V_buf); if (pMat[i] (coeffMonoms[i].size(), coeffMonoms[i].size()) == 0) { delete[] pEvalPoints; delete[] pMat; delete[] pL; delete[] coeffMonoms; delete[] pM; if (bufpEvalPoints != NULL) delete [] bufpEvalPoints; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } matRows += pMat[i].rows() - coeffMonoms[i].size(); } CFMatrix bufMat; Mat= CFMatrix (matRows, matColumns); ind= 0; bufArray= CFArray (matRows); CFArray bufArray2; for (int i= 0; i < skelSize; i++) { if (coeffMonoms[i].size() + 1 >= pMat[i].rows() || coeffMonoms[i].size() + 1 >= pMat[i].columns()) { delete[] pEvalPoints; delete[] pMat; delete[] pL; delete[] coeffMonoms; delete[] pM; if (bufpEvalPoints != NULL) delete [] bufpEvalPoints; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } bufMat= pMat[i] (coeffMonoms[i].size() + 1, pMat[i].rows(), coeffMonoms[i].size() + 1, pMat[i].columns()); for (int j= 1; j <= bufMat.rows(); j++) for (int k= 1; k <= bufMat.columns(); k++) Mat (j + ind, k)= bufMat(j, k); bufArray2= coeffMonoms[i].size(); for (int j= 1; j <= pMat[i].rows(); j++) { if (j > coeffMonoms[i].size()) bufArray [j-coeffMonoms[i].size() + ind - 1]= pL[i] [j - 1]; else bufArray2 [j - 1]= pL[i] [j - 1]; } pL[i]= bufArray2; ind += bufMat.rows(); pMat[i]= pMat[i] (1, coeffMonoms[i].size(), 1, pMat[i].columns()); } if (V_buf.level() != 1) solution= solveSystemFq (Mat, bufArray, V_buf); else solution= solveSystemFp (Mat, bufArray); if (solution.size() == 0) { delete[] pEvalPoints; delete[] pMat; delete[] pL; delete[] coeffMonoms; delete[] pM; if (bufpEvalPoints != NULL) delete [] bufpEvalPoints; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } ind= 0; result= 0; CFArray bufSolution; for (int i= 0; i < skelSize; i++) { bufSolution= readOffSolution (pMat[i], pL[i], solution); for (int i= 0; i < bufSolution.size(); i++, ind++) result += Monoms [ind]*bufSolution[i]; } if (alpha.level() != 1 && V_buf != alpha) { CFList u, v; result= mapDown (result,prim_elem_alpha, im_prim_elem_alpha, alpha, u, v); prune1 (alpha); } result= N(result); delete[] pEvalPoints; delete[] pMat; delete[] pL; delete[] coeffMonoms; delete[] pM; if (bufpEvalPoints != NULL) delete [] bufpEvalPoints; if (fdivides (result, F) && fdivides (result, G)) return result; else { fail= true; return 0; } } // end of deKleine, Monagan & Wittkopf result += Monoms[0]; int ind2= 0, ind3= 2; ind= 0; for (int l= 0; l < minimalColumnsIndex; l++) ind += coeffMonoms[l].size(); for (int l= solution.size() - pMat[0].columns() + 1; l < solution.size(); l++, ind2++, ind3++) { result += solution[l]*Monoms [1 + ind2]; for (int i= 0; i < pMat[0].rows(); i++) firstColumn[i] += solution[l]*pMat[0] (i + 1, ind3); } for (int l= 0; l < solution.size() + 1 - pMat[0].columns(); l++) result += solution[l]*Monoms [ind + l]; ind= coeffMonoms[0].size(); for (int k= 1; k < skelSize; k++) { if (k == minimalColumnsIndex) { ind += coeffMonoms[k].size(); continue; } if (k != minimalColumnsIndex) { for (int i= 0; i < biggestSize; i++) pL[k] [i] *= firstColumn [i]; } if (biggestSize != coeffMonoms[k].size() && k != minimalColumnsIndex) { bufArray= CFArray (coeffMonoms[k].size()); for (int i= 0; i < bufArray.size(); i++) bufArray [i]= pL[k] [i]; solution= solveGeneralVandermonde (pM[k], bufArray); } else solution= solveGeneralVandermonde (pM[k], pL[k]); if (solution.size() == 0) { delete[] pEvalPoints; delete[] pMat; delete[] pL; delete[] coeffMonoms; delete[] pM; fail= true; if (alpha.level() != 1 && V_buf != alpha) prune1 (alpha); return 0; } if (k != minimalColumnsIndex) { for (int l= 0; l < solution.size(); l++) result += solution[l]*Monoms [ind + l]; ind += solution.size(); } } delete[] pEvalPoints; delete[] pMat; delete[] pL; delete[] pM; delete[] coeffMonoms; if (alpha.level() != 1 && V_buf != alpha) { CFList u, v; result= mapDown (result, prim_elem, im_prim_elem, alpha, u, v); prune1 (alpha); } result= N(result); if (fdivides (result, F) && fdivides (result, G)) return result; else { fail= true; return 0; } } CanonicalForm sparseGCDFq (const CanonicalForm& F, const CanonicalForm& G, const Variable & alpha, CFList& l, bool& topLevel) { CanonicalForm A= F; CanonicalForm B= G; if (F.isZero() && degree(G) > 0) return G/Lc(G); else if (G.isZero() && degree (F) > 0) return F/Lc(F); else if (F.isZero() && G.isZero()) return F.genOne(); if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne(); if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F); if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G); if (F == G) return F/Lc(F); CFMap M,N; int best_level= myCompress (A, B, M, N, topLevel); if (best_level == 0) return B.genOne(); A= M(A); B= M(B); Variable x= Variable (1); //univariate case if (A.isUnivariate() && B.isUnivariate()) return N (gcd (A, B)); CanonicalForm cA, cB; // content of A and B CanonicalForm ppA, ppB; // primitive part of A and B CanonicalForm gcdcAcB; cA = uni_content (A); cB = uni_content (B); gcdcAcB= gcd (cA, cB); ppA= A/cA; ppB= B/cB; CanonicalForm lcA, lcB; // leading coefficients of A and B CanonicalForm gcdlcAlcB; lcA= uni_lcoeff (ppA); lcB= uni_lcoeff (ppB); if (fdivides (lcA, lcB)) { if (fdivides (A, B)) return F/Lc(F); } if (fdivides (lcB, lcA)) { if (fdivides (B, A)) return G/Lc(G); } gcdlcAlcB= gcd (lcA, lcB); int d= totaldegree (ppA, Variable (2), Variable (ppA.level())); int d0; if (d == 0) return N(gcdcAcB); d0= totaldegree (ppB, Variable (2), Variable (ppB.level())); if (d0 < d) d= d0; if (d == 0) return N(gcdcAcB); CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH, skeleton; CanonicalForm newtonPoly= 1; m= gcdlcAlcB; G_m= 0; H= 0; bool fail= false; topLevel= false; bool inextension= false; Variable V_buf= alpha, V_buf4= alpha; CanonicalForm prim_elem, im_prim_elem; CanonicalForm prim_elem_alpha, im_prim_elem_alpha; CFList source, dest; do // first do { random_element= randomElement (m, V_buf, l, fail); if (random_element == 0 && !fail) { if (!find (l, random_element)) l.append (random_element); continue; } if (fail) { source= CFList(); dest= CFList(); Variable V_buf3= V_buf; V_buf= chooseExtension (V_buf); bool prim_fail= false; Variable V_buf2; prim_elem= primitiveElement (V_buf4, V_buf2, prim_fail); if (V_buf4 == alpha) prim_elem_alpha= prim_elem; if (V_buf3 != V_buf4) { m= mapDown (m, prim_elem, im_prim_elem, V_buf4, source, dest); G_m= mapDown (m, prim_elem, im_prim_elem, V_buf4, source, dest); newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, V_buf4, source, dest); ppA= mapDown (ppA, prim_elem, im_prim_elem, V_buf4, source, dest); ppB= mapDown (ppB, prim_elem, im_prim_elem, V_buf4, source, dest); gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, V_buf4, source, dest); for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, V_buf4, source, dest); } ASSERT (!prim_fail, "failure in integer factorizer"); if (prim_fail) ; //ERROR else im_prim_elem= mapPrimElem (prim_elem, V_buf4, V_buf); if (V_buf4 == alpha) im_prim_elem_alpha= im_prim_elem; else im_prim_elem_alpha= mapUp (im_prim_elem_alpha, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); DEBOUTLN (cerr, "getMipo (V_buf4)= " << getMipo (V_buf4)); DEBOUTLN (cerr, "getMipo (V_buf2)= " << getMipo (V_buf2)); inextension= true; for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapUp (i.getItem(), V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); m= mapUp (m, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); G_m= mapUp (G_m, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); newtonPoly= mapUp (newtonPoly, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); ppA= mapUp (ppA, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); ppB= mapUp (ppB, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); gcdlcAlcB= mapUp (gcdlcAlcB, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); fail= false; random_element= randomElement (m, V_buf, l, fail ); DEBOUTLN (cerr, "fail= " << fail); CFList list; TIMING_START (gcd_recursion); G_random_element= sparseGCDFq (ppA (random_element, x), ppB (random_element, x), V_buf, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); V_buf4= V_buf; } else { CFList list; TIMING_START (gcd_recursion); G_random_element= sparseGCDFq (ppA(random_element, x), ppB(random_element, x), V_buf, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 == 0) { if (inextension) prune1 (alpha); return N(gcdcAcB); } if (d0 > d) { if (!find (l, random_element)) l.append (random_element); continue; } G_random_element= (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element)) * G_random_element; skeleton= G_random_element; if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 < d) { m= gcdlcAlcB; newtonPoly= 1; G_m= 0; d= d0; } H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x); if (uni_lcoeff (H) == gcdlcAlcB) { cH= uni_content (H); ppH= H/cH; if (inextension) { CFList u, v; //maybe it's better to test if ppH is an element of F(\alpha) before //mapping down if (fdivides (ppH, ppA) && fdivides (ppH, ppB)) { DEBOUTLN (cerr, "ppH before mapDown= " << ppH); ppH= mapDown (ppH, prim_elem_alpha, im_prim_elem_alpha, alpha, u, v); ppH /= Lc(ppH); DEBOUTLN (cerr, "ppH after mapDown= " << ppH); prune1 (alpha); return N(gcdcAcB*ppH); } } else if (fdivides (ppH, ppA) && fdivides (ppH, ppB)) return N(gcdcAcB*ppH); } G_m= H; newtonPoly= newtonPoly*(x - random_element); m= m*(x - random_element); if (!find (l, random_element)) l.append (random_element); if (getCharacteristic () > 3 && size (skeleton) < 100) { CFArray Monoms; CFArray *coeffMonoms; do //second do { random_element= randomElement (m, V_buf, l, fail); if (random_element == 0 && !fail) { if (!find (l, random_element)) l.append (random_element); continue; } if (fail) { source= CFList(); dest= CFList(); Variable V_buf3= V_buf; V_buf= chooseExtension (V_buf); bool prim_fail= false; Variable V_buf2; prim_elem= primitiveElement (V_buf4, V_buf2, prim_fail); if (V_buf4 == alpha) prim_elem_alpha= prim_elem; if (V_buf3 != V_buf4) { m= mapDown (m, prim_elem, im_prim_elem, V_buf4, source, dest); G_m= mapDown (m, prim_elem, im_prim_elem, V_buf4, source, dest); newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, V_buf4, source, dest); ppA= mapDown (ppA, prim_elem, im_prim_elem, V_buf4, source, dest); ppB= mapDown (ppB, prim_elem, im_prim_elem, V_buf4, source, dest); gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, V_buf4, source, dest); for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, V_buf4, source, dest); } ASSERT (!prim_fail, "failure in integer factorizer"); if (prim_fail) ; //ERROR else im_prim_elem= mapPrimElem (prim_elem, V_buf4, V_buf); if (V_buf4 == alpha) im_prim_elem_alpha= im_prim_elem; else im_prim_elem_alpha= mapUp (im_prim_elem_alpha, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); DEBOUTLN (cerr, "getMipo (V_buf4)= " << getMipo (V_buf4)); DEBOUTLN (cerr, "getMipo (V_buf2)= " << getMipo (V_buf2)); inextension= true; for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapUp (i.getItem(), V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); m= mapUp (m, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); G_m= mapUp (G_m, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); newtonPoly= mapUp (newtonPoly, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); ppA= mapUp (ppA, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); ppB= mapUp (ppB, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); gcdlcAlcB= mapUp (gcdlcAlcB, V_buf4, V_buf, prim_elem, im_prim_elem, source, dest); fail= false; random_element= randomElement (m, V_buf, l, fail); DEBOUTLN (cerr, "fail= " << fail); CFList list; TIMING_START (gcd_recursion); V_buf4= V_buf; //sparseInterpolation bool sparseFail= false; if (LC (skeleton).inCoeffDomain()) G_random_element= monicSparseInterpol (ppA (random_element, x), ppB(random_element,x), skeleton,V_buf, sparseFail, coeffMonoms,Monoms); else G_random_element= nonMonicSparseInterpol (ppA(random_element,x),ppB(random_element,x), skeleton, V_buf, sparseFail, coeffMonoms, Monoms); if (sparseFail) break; TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else { CFList list; TIMING_START (gcd_recursion); bool sparseFail= false; if (LC (skeleton).inCoeffDomain()) G_random_element= monicSparseInterpol (ppA (random_element, x),ppB(random_element, x), skeleton,V_buf, sparseFail,coeffMonoms, Monoms); else G_random_element= nonMonicSparseInterpol (ppA(random_element,x),ppB(random_element,x), skeleton, V_buf, sparseFail, coeffMonoms, Monoms); if (sparseFail) break; TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 == 0) { if (inextension) prune1 (alpha); return N(gcdcAcB); } if (d0 > d) { if (!find (l, random_element)) l.append (random_element); continue; } G_random_element= (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element)) * G_random_element; if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 < d) { m= gcdlcAlcB; newtonPoly= 1; G_m= 0; d= d0; } TIMING_START (newton_interpolation); H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x); TIMING_END_AND_PRINT (newton_interpolation, "time for newton interpolation: "); //termination test if (uni_lcoeff (H) == gcdlcAlcB) { cH= uni_content (H); ppH= H/cH; if (inextension) { CFList u, v; //maybe it's better to test if ppH is an element of F(\alpha) before //mapping down if (fdivides (ppH, ppA) && fdivides (ppH, ppB)) { DEBOUTLN (cerr, "ppH before mapDown= " << ppH); ppH= mapDown (ppH, prim_elem_alpha, im_prim_elem_alpha, alpha, u, v); ppH /= Lc(ppH); DEBOUTLN (cerr, "ppH after mapDown= " << ppH); prune1 (alpha); return N(gcdcAcB*ppH); } } else if (fdivides (ppH, ppA) && fdivides (ppH, ppB)) { return N(gcdcAcB*ppH); } } G_m= H; newtonPoly= newtonPoly*(x - random_element); m= m*(x - random_element); if (!find (l, random_element)) l.append (random_element); } while (1); } } while (1); } CanonicalForm sparseGCDFp (const CanonicalForm& F, const CanonicalForm& G, bool& topLevel, CFList& l) { CanonicalForm A= F; CanonicalForm B= G; if (F.isZero() && degree(G) > 0) return G/Lc(G); else if (G.isZero() && degree (F) > 0) return F/Lc(F); else if (F.isZero() && G.isZero()) return F.genOne(); if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne(); if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F); if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G); if (F == G) return F/Lc(F); CFMap M,N; int best_level= myCompress (A, B, M, N, topLevel); if (best_level == 0) return B.genOne(); A= M(A); B= M(B); Variable x= Variable (1); //univariate case if (A.isUnivariate() && B.isUnivariate()) return N (gcd (A, B)); CanonicalForm cA, cB; // content of A and B CanonicalForm ppA, ppB; // primitive part of A and B CanonicalForm gcdcAcB; cA = uni_content (A); cB = uni_content (B); gcdcAcB= gcd (cA, cB); ppA= A/cA; ppB= B/cB; CanonicalForm lcA, lcB; // leading coefficients of A and B CanonicalForm gcdlcAlcB; lcA= uni_lcoeff (ppA); lcB= uni_lcoeff (ppB); if (fdivides (lcA, lcB)) { if (fdivides (A, B)) return F/Lc(F); } if (fdivides (lcB, lcA)) { if (fdivides (B, A)) return G/Lc(G); } gcdlcAlcB= gcd (lcA, lcB); int d= totaldegree (ppA, Variable (2), Variable (ppA.level())); int d0; if (d == 0) return N(gcdcAcB); d0= totaldegree (ppB, Variable (2), Variable (ppB.level())); if (d0 < d) d= d0; if (d == 0) return N(gcdcAcB); CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH, skeleton; CanonicalForm newtonPoly= 1; m= gcdlcAlcB; G_m= 0; H= 0; bool fail= false; topLevel= false; bool inextension= false; Variable V_buf, alpha, cleanUp; CanonicalForm prim_elem, im_prim_elem; CFList source, dest; do //first do { if (inextension) random_element= randomElement (m, V_buf, l, fail); else random_element= FpRandomElement (m, l, fail); if (random_element == 0 && !fail) { if (!find (l, random_element)) l.append (random_element); continue; } if (!fail && !inextension) { CFList list; TIMING_START (gcd_recursion); G_random_element= sparseGCDFp (ppA (random_element,x), ppB (random_element,x), topLevel, list); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else if (!fail && inextension) { CFList list; TIMING_START (gcd_recursion); G_random_element= sparseGCDFq (ppA (random_element, x), ppB (random_element, x), alpha, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else if (fail && !inextension) { source= CFList(); dest= CFList(); CFList list; CanonicalForm mipo; int deg= 2; bool initialized= false; do { mipo= randomIrredpoly (deg, x); if (initialized) setMipo (alpha, mipo); else alpha= rootOf (mipo); inextension= true; fail= false; initialized= true; random_element= randomElement (m, alpha, l, fail); deg++; } while (fail); cleanUp= alpha; V_buf= alpha; list= CFList(); TIMING_START (gcd_recursion); G_random_element= sparseGCDFq (ppA (random_element, x), ppB (random_element, x), alpha, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else if (fail && inextension) { source= CFList(); dest= CFList(); Variable V_buf3= V_buf; V_buf= chooseExtension (V_buf); bool prim_fail= false; Variable V_buf2; CanonicalForm prim_elem, im_prim_elem; prim_elem= primitiveElement (alpha, V_buf2, prim_fail); if (V_buf3 != alpha) { m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest); G_m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest); newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, alpha, source, dest); ppA= mapDown (ppA, prim_elem, im_prim_elem, alpha, source, dest); ppB= mapDown (ppB, prim_elem, im_prim_elem, alpha, source, dest); gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, alpha, source, dest); for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, alpha, source, dest); } ASSERT (!prim_fail, "failure in integer factorizer"); if (prim_fail) ; //ERROR else im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf); DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha)); DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2)); for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem, im_prim_elem, source, dest); m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest); G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest); newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem, source, dest); ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest); ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest); gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem, source, dest); fail= false; random_element= randomElement (m, V_buf, l, fail ); DEBOUTLN (cerr, "fail= " << fail); CFList list; TIMING_START (gcd_recursion); G_random_element= sparseGCDFq (ppA (random_element, x), ppB (random_element, x), V_buf, list, topLevel); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); alpha= V_buf; } if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 == 0) { if (inextension) prune (cleanUp); return N(gcdcAcB); } if (d0 > d) { if (!find (l, random_element)) l.append (random_element); continue; } G_random_element= (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element)) * G_random_element; skeleton= G_random_element; if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 < d) { m= gcdlcAlcB; newtonPoly= 1; G_m= 0; d= d0; } H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x); if (uni_lcoeff (H) == gcdlcAlcB) { cH= uni_content (H); ppH= H/cH; ppH /= Lc (ppH); DEBOUTLN (cerr, "ppH= " << ppH); if (fdivides (ppH, ppA) && fdivides (ppH, ppB)) { if (inextension) prune (cleanUp); return N(gcdcAcB*ppH); } } G_m= H; newtonPoly= newtonPoly*(x - random_element); m= m*(x - random_element); if (!find (l, random_element)) l.append (random_element); if ((getCharacteristic() > 3 && size (skeleton) < 200)) { CFArray Monoms; CFArray* coeffMonoms; do //second do { if (inextension) random_element= randomElement (m, alpha, l, fail); else random_element= FpRandomElement (m, l, fail); if (random_element == 0 && !fail) { if (!find (l, random_element)) l.append (random_element); continue; } bool sparseFail= false; if (!fail && !inextension) { CFList list; TIMING_START (gcd_recursion); if (LC (skeleton).inCoeffDomain()) G_random_element= monicSparseInterpol(ppA(random_element, x), ppB (random_element, x), skeleton, x, sparseFail, coeffMonoms, Monoms); else G_random_element= nonMonicSparseInterpol(ppA(random_element,x), ppB(random_element,x), skeleton, x, sparseFail, coeffMonoms, Monoms); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else if (!fail && inextension) { CFList list; TIMING_START (gcd_recursion); if (LC (skeleton).inCoeffDomain()) G_random_element= monicSparseInterpol(ppA (random_element,x), ppB (random_element, x), skeleton, alpha, sparseFail, coeffMonoms, Monoms); else G_random_element= nonMonicSparseInterpol(ppA(random_element,x), ppB(random_element,x), skeleton, alpha, sparseFail, coeffMonoms, Monoms); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else if (fail && !inextension) { source= CFList(); dest= CFList(); CFList list; CanonicalForm mipo; int deg= 2; bool initialized= false; do { mipo= randomIrredpoly (deg, x); if (initialized) setMipo (alpha, mipo); else alpha= rootOf (mipo); inextension= true; fail= false; initialized= true; random_element= randomElement (m, alpha, l, fail); deg++; } while (fail); cleanUp= alpha; V_buf= alpha; list= CFList(); TIMING_START (gcd_recursion); if (LC (skeleton).inCoeffDomain()) G_random_element= monicSparseInterpol (ppA (random_element,x), ppB (random_element,x), skeleton, alpha, sparseFail, coeffMonoms, Monoms); else G_random_element= nonMonicSparseInterpol(ppA(random_element,x), ppB(random_element,x), skeleton, alpha, sparseFail, coeffMonoms, Monoms); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); } else if (fail && inextension) { source= CFList(); dest= CFList(); Variable V_buf3= V_buf; V_buf= chooseExtension (V_buf); bool prim_fail= false; Variable V_buf2; CanonicalForm prim_elem, im_prim_elem; prim_elem= primitiveElement (alpha, V_buf2, prim_fail); if (V_buf3 != alpha) { m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest); G_m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest); newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, alpha, source, dest); ppA= mapDown (ppA, prim_elem, im_prim_elem, alpha, source, dest); ppB= mapDown (ppB, prim_elem, im_prim_elem, alpha, source, dest); gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, alpha, source, dest); for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, alpha, source, dest); } ASSERT (!prim_fail, "failure in integer factorizer"); if (prim_fail) ; //ERROR else im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf); DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha)); DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2)); for (CFListIterator i= l; i.hasItem(); i++) i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem, im_prim_elem, source, dest); m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest); G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest); newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem, source, dest); ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest); ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest); gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem, source, dest); fail= false; random_element= randomElement (m, V_buf, l, fail ); DEBOUTLN (cerr, "fail= " << fail); CFList list; TIMING_START (gcd_recursion); if (LC (skeleton).inCoeffDomain()) G_random_element= monicSparseInterpol (ppA (random_element, x), ppB (random_element, x), skeleton, V_buf, sparseFail, coeffMonoms, Monoms); else G_random_element= nonMonicSparseInterpol (ppA(random_element,x), ppB(random_element,x), skeleton, V_buf, sparseFail, coeffMonoms, Monoms); TIMING_END_AND_PRINT (gcd_recursion, "time for recursive call: "); DEBOUTLN (cerr, "G_random_element= " << G_random_element); alpha= V_buf; } if (sparseFail) break; if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 == 0) { if (inextension) prune (cleanUp); return N(gcdcAcB); } if (d0 > d) { if (!find (l, random_element)) l.append (random_element); continue; } G_random_element= (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element)) * G_random_element; if (!G_random_element.inCoeffDomain()) d0= totaldegree (G_random_element, Variable(2), Variable (G_random_element.level())); else d0= 0; if (d0 < d) { m= gcdlcAlcB; newtonPoly= 1; G_m= 0; d= d0; } TIMING_START (newton_interpolation); H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x); TIMING_END_AND_PRINT (newton_interpolation, "time for newton interpolation: "); //termination test if (uni_lcoeff (H) == gcdlcAlcB) { cH= uni_content (H); ppH= H/cH; ppH /= Lc (ppH); DEBOUTLN (cerr, "ppH= " << ppH); if (fdivides (ppH, ppA) && fdivides (ppH, ppB)) { if (inextension) prune (cleanUp); return N(gcdcAcB*ppH); } } G_m= H; newtonPoly= newtonPoly*(x - random_element); m= m*(x - random_element); if (!find (l, random_element)) l.append (random_element); } while (1); //end of second do } else { if (inextension) prune (cleanUp); return N(gcdcAcB*modGCDFp (ppA, ppB)); } } while (1); //end of first do } TIMING_DEFINE_PRINT(modZ_termination) TIMING_DEFINE_PRINT(modZ_recursion) /// modular gcd algorithm, see Keith, Czapor, Geddes "Algorithms for Computer /// Algebra", Algorithm 7.1 CanonicalForm modGCDZ ( const CanonicalForm & FF, const CanonicalForm & GG ) { CanonicalForm f, g, cl, q(0), Dp, newD, D, newq, newqh; int p, i, dp_deg, d_deg=-1; CanonicalForm cd ( bCommonDen( FF )); f=cd*FF; Variable x= Variable (1); CanonicalForm cf, cg; cf= icontent (f); f /= cf; //cd = bCommonDen( f ); f *=cd; //f /=vcontent(f,Variable(1)); cd = bCommonDen( GG ); g=cd*GG; cg= icontent (g); g /= cg; //cd = bCommonDen( g ); g *=cd; //g /=vcontent(g,Variable(1)); CanonicalForm Dn, test= 0; CanonicalForm lcf, lcg; lcf= f.lc(); lcg= g.lc(); cl = gcd (f.lc(),g.lc()); CanonicalForm gcdcfcg= gcd (cf, cg); CanonicalForm fp, gp; CanonicalForm b= 1; int minCommonDeg= 0; for (i= tmax (f.level(), g.level()); i > 0; i--) { if (degree (f, i) <= 0 || degree (g, i) <= 0) continue; else { minCommonDeg= tmin (degree (g, i), degree (f, i)); break; } } if (i == 0) return gcdcfcg; for (; i > 0; i--) { if (degree (f, i) <= 0 || degree (g, i) <= 0) continue; else minCommonDeg= tmin (minCommonDeg, tmin (degree (g, i), degree (f, i))); } b= 2*tmin (maxNorm (f), maxNorm (g))*abs (cl)* power (CanonicalForm (2), minCommonDeg); bool equal= false; i = cf_getNumBigPrimes() - 1; CanonicalForm cof, cog, cofp, cogp, newCof, newCog, cofn, cogn, cDn; int maxNumVars= tmax (getNumVars (f), getNumVars (g)); //Off (SW_RATIONAL); while ( true ) { p = cf_getBigPrime( i ); i--; while ( i >= 0 && mod( cl*(lc(f)/cl)*(lc(g)/cl), p ) == 0 ) { p = cf_getBigPrime( i ); i--; } //printf("try p=%d\n",p); setCharacteristic( p ); fp= mapinto (f); gp= mapinto (g); TIMING_START (modZ_recursion) #ifdef HAVE_NTL if (size (fp)/maxNumVars > 500 && size (gp)/maxNumVars > 500) Dp = modGCDFp (fp, gp, cofp, cogp); else { Dp= gcd_poly (fp, gp); cofp= fp/Dp; cogp= gp/Dp; } #else Dp= gcd_poly (fp, gp); cofp= fp/Dp; cogp= gp/Dp; #endif TIMING_END_AND_PRINT (modZ_recursion, "time for gcd mod p in modular gcd: "); Dp /=Dp.lc(); Dp *= mapinto (cl); cofp /= lc (cofp); cofp *= mapinto (lcf); cogp /= lc (cogp); cogp *= mapinto (lcg); setCharacteristic( 0 ); dp_deg=totaldegree(Dp); if ( dp_deg == 0 ) { //printf(" -> 1\n"); return CanonicalForm(gcdcfcg); } if ( q.isZero() ) { D = mapinto( Dp ); cof= mapinto (cofp); cog= mapinto (cogp); d_deg=dp_deg; q = p; Dn= balance_p (D, p); cofn= balance_p (cof, p); cogn= balance_p (cog, p); } else { if ( dp_deg == d_deg ) { chineseRemainder( D, q, mapinto( Dp ), p, newD, newq ); chineseRemainder( cof, q, mapinto (cofp), p, newCof, newq); chineseRemainder( cog, q, mapinto (cogp), p, newCog, newq); cof= newCof; cog= newCog; newqh= newq/2; Dn= balance_p (newD, newq, newqh); cofn= balance_p (newCof, newq, newqh); cogn= balance_p (newCog, newq, newqh); if (test != Dn) //balance_p (newD, newq)) test= balance_p (newD, newq); else equal= true; q = newq; D = newD; } else if ( dp_deg < d_deg ) { //printf(" were all bad, try more\n"); // all previous p's are bad primes q = p; D = mapinto( Dp ); cof= mapinto (cof); cog= mapinto (cog); d_deg=dp_deg; test= 0; equal= false; Dn= balance_p (D, p); cofn= balance_p (cof, p); cogn= balance_p (cog, p); } else { //printf(" was bad, try more\n"); } //else dp_deg > d_deg: bad prime } if ( i >= 0 ) { cDn= icontent (Dn); Dn /= cDn; cofn /= cl/cDn; //cofn /= icontent (cofn); cogn /= cl/cDn; //cogn /= icontent (cogn); TIMING_START (modZ_termination); if ((terminationTest (f,g, cofn, cogn, Dn)) || ((equal || q > b) && fdivides (Dn, f) && fdivides (Dn, g))) { TIMING_END_AND_PRINT (modZ_termination, "time for successful termination in modular gcd: "); //printf(" -> success\n"); return Dn*gcdcfcg; } TIMING_END_AND_PRINT (modZ_termination, "time for unsuccessful termination in modular gcd: "); equal= false; //else: try more primes } else { // try other method //printf("try other gcd\n"); Off(SW_USE_CHINREM_GCD); D=gcd_poly( f, g ); On(SW_USE_CHINREM_GCD); return D*gcdcfcg; } } } #endif singular-4.0.3+ds/factory/cfModGcd.h000066400000000000000000000076251266270727000172550ustar00rootroot00000000000000#ifndef CF_MOD_GCD_H #define CF_MOD_GCD_H // -*- c++ -*- //***************************************************************************** /** @file cfModGcd.h * * modular and sparse modular GCD algorithms over finite fields and Z. * * @author Martin Lee * @date 22.10.2009 * * @par Copyright: * (c) by The SINGULAR Team, see LICENSE file * **/ //***************************************************************************** // #include "config.h" #include "cf_assert.h" #include "cf_factory.h" CanonicalForm modGCDFq (const CanonicalForm& F, const CanonicalForm& G, Variable & alpha, CFList& l, bool& top_level); /// GCD of A and B over \f$ F_{p}(\alpha ) \f$ static inline CanonicalForm modGCDFq (const CanonicalForm& A, ///<[in] poly over F_q const CanonicalForm& B, ///<[in] poly over F_q Variable & alpha ///<[in] algebraic variable ) { CFList list; bool top_level= true; return modGCDFq (A, B, alpha, list, top_level); } CanonicalForm modGCDFp (const CanonicalForm& F, const CanonicalForm& G, bool& top_level, CFList& l); CanonicalForm modGCDFp (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& coF, CanonicalForm& coG, bool& topLevel, CFList& l); ///GCD of A and B over \f$ F_{p} \f$ static inline CanonicalForm modGCDFp (const CanonicalForm& A, ///<[in] poly over F_p const CanonicalForm& B ///<[in] poly over F_p ) { CFList list; bool top_level= true; return modGCDFp (A, B, top_level, list); } static inline CanonicalForm modGCDFp (const CanonicalForm& A, const CanonicalForm& B, CanonicalForm& coA, CanonicalForm& coB) { CFList list; bool top_level= true; return modGCDFp (A, B, coA, coB, top_level, list); } CanonicalForm modGCDGF (const CanonicalForm& F, const CanonicalForm& G, CFList& l, bool& top_level); /// GCD of A and B over GF static inline CanonicalForm modGCDGF (const CanonicalForm& A, ///<[in] poly over GF const CanonicalForm& B ///<[in] poly over GF ) { ASSERT (CFFactory::gettype() == GaloisFieldDomain, "GF as base field expected"); CFList list; bool top_level= true; return modGCDGF (A, B, list, top_level); } CanonicalForm sparseGCDFp (const CanonicalForm& F, const CanonicalForm& G, bool& topLevel, CFList& l); /// Zippel's sparse GCD over Fp static inline CanonicalForm sparseGCDFp (const CanonicalForm& A, ///<[in] poly over F_p const CanonicalForm& B ///<[in] poly over F_p ) { ASSERT (CFFactory::gettype() == FiniteFieldDomain, "Fp as base field expected"); CFList list; bool topLevel= true; return sparseGCDFp (A, B, topLevel, list); } CanonicalForm sparseGCDFq (const CanonicalForm& F, const CanonicalForm& G, const Variable& alpha, CFList& l, bool& topLevel); /// Zippel's sparse GCD over Fq static inline CanonicalForm sparseGCDFq (const CanonicalForm& A, ///<[in] poly over F_q const CanonicalForm& B, ///<[in] poly over F_q const Variable& alpha ///<[in] algebraic variable ) { CFList list; bool topLevel= true; return sparseGCDFq (A, B, alpha, list, topLevel); } /// extract monomials of F, parts in algebraic variable are considered /// coefficients CFArray getMonoms (const CanonicalForm& F ///<[in] some poly ); bool terminationTest (const CanonicalForm& F, const CanonicalForm& G, const CanonicalForm& coF, const CanonicalForm& coG, const CanonicalForm& cand); /// modular GCD over Z CanonicalForm modGCDZ (const CanonicalForm & FF, ///<[in] poly over Z const CanonicalForm & GG ///<[in] poly over Z ); #endif singular-4.0.3+ds/factory/cfModResultant.cc000066400000000000000000000410221266270727000206640ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfModResultant.cc * * modular resultant algorithm * * @author Martin Lee * **/ /*****************************************************************************/ #include "config.h" #include "cf_assert.h" #include "timing.h" #include "cfModResultant.h" #include "cf_primes.h" #include "templates/ftmpl_functions.h" #include "cf_map.h" #include "cf_algorithm.h" #include "cf_iter.h" #include "cf_irred.h" #include "cf_generator.h" #include "cf_random.h" #include "cf_map_ext.h" #include "facFqBivarUtil.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif #ifdef HAVE_FLINT #include "FLINTconvert.h" #endif #ifdef HAVE_NTL TIMING_DEFINE_PRINT(fac_resultant_p) //TODO arrange by bound= deg (F,xlevel)*deg (G,i)+deg (G,xlevel)*deg (F, i) static inline void myCompress (const CanonicalForm& F, const CanonicalForm& G, CFMap & M, CFMap & N, const Variable& x) { int n= tmax (F.level(), G.level()); int * degsf= new int [n + 1]; int * degsg= new int [n + 1]; for (int i = 0; i <= n; i++) degsf[i]= degsg[i]= 0; degsf= degrees (F, degsf); degsg= degrees (G, degsg); int both_non_zero= 0; int f_zero= 0; int g_zero= 0; int both_zero= 0; int degsfx, degsgx; if (x.level() != 1) { int xlevel= x.level(); for (int i= 1; i <= n; i++) { if (degsf[i] != 0 && degsg[i] != 0) { both_non_zero++; continue; } if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level()) { f_zero++; continue; } if (degsg[i] == 0 && degsf[i] && i <= F.level()) { g_zero++; continue; } } M.newpair (Variable (xlevel), Variable (1)); N.newpair (Variable (1), Variable (xlevel)); degsfx= degsf [xlevel]; degsgx= degsg [xlevel]; degsf [xlevel]= 0; degsg [xlevel]= 0; if ((getNumVars (F) == 2 && getNumVars (G) == 1) || (getNumVars (G) == 2 && getNumVars (F) == 1) || (getNumVars (F) == 2 && getNumVars (F) == getNumVars (G) && getVars (F) == getVars (G))) { int pos= 2; for (int i= 1; i <= n; i++) { if (i != xlevel) { if (i != pos && (degsf[i] != 0 || degsg [i] != 0)) { M.newpair (Variable (i), Variable (pos)); N.newpair (Variable (pos), Variable (i)); pos++; } } } delete [] degsf; delete [] degsg; return; } if (both_non_zero == 0) { delete [] degsf; delete [] degsg; return; } // map Variables which do not occur in both polynomials to higher levels int k= 1; int l= 1; for (int i= 1; i <= n; i++) { if (i == xlevel) continue; if (degsf[i] != 0 && degsg[i] == 0 && i <= F.level()) { if (k + both_non_zero != i) { M.newpair (Variable (i), Variable (k + both_non_zero)); N.newpair (Variable (k + both_non_zero), Variable (i)); } k++; } if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level()) { if (l + g_zero + both_non_zero != i) { M.newpair (Variable (i), Variable (l + g_zero + both_non_zero)); N.newpair (Variable (l + g_zero + both_non_zero), Variable (i)); } l++; } } int m= n; int min_max_deg; k= both_non_zero; l= 0; int i= 1; while (k > 0) { if (degsf [i] != 0 && degsg [i] != 0) min_max_deg= degsgx*degsf[i] + degsfx*degsg[i]; else min_max_deg= 0; while (min_max_deg == 0 && i < m + 1) { i++; if (degsf [i] != 0 && degsg [i] != 0) min_max_deg= degsgx*degsf[i] + degsfx*degsg[i]; else min_max_deg= 0; } for (int j= i + 1; j <= m; j++) { if (degsgx*degsf[j] + degsfx*degsg[j] <= min_max_deg && degsf[j] != 0 && degsg [j] != 0) { min_max_deg= degsgx*degsf[j] + degsfx*degsg[j]; l= j; } } if (l != 0) { if (l != k && l != xlevel && k != 1) { M.newpair (Variable (l), Variable(k)); N.newpair (Variable (k), Variable(l)); degsf[l]= 0; degsg[l]= 0; l= 0; } else if (l < m + 1) { degsf[l]= 0; degsg[l]= 0; l= 0; } } else if (l == 0) { if (i != k && i != xlevel && k != 1) { M.newpair (Variable (i), Variable (k)); N.newpair (Variable (k), Variable (i)); degsf[i]= 0; degsg[i]= 0; } else if (i < m + 1) { degsf[i]= 0; degsg[i]= 0; } i++; } k--; } } else { //arrange Variables such that no gaps occur for (int i= 1; i <= n; i++) { if (degsf[i] == 0 && degsg[i] == 0) { both_zero++; continue; } else { if (both_zero != 0 && i != 1) { M.newpair (Variable (i), Variable (i - both_zero)); N.newpair (Variable (i - both_zero), Variable (i)); } } } } delete [] degsf; delete [] degsg; } static inline CanonicalForm oneNorm (const CanonicalForm& F) { if (F.inZ()) return abs (F); CanonicalForm result= 0; for (CFIterator i= F; i.hasTerms(); i++) result += oneNorm (i.coeff()); return result; } // if F and G are both non constant, make sure their level is equal static inline CanonicalForm uniResultant (const CanonicalForm& F, const CanonicalForm& G) { #ifdef HAVE_NTL ASSERT (getCharacteristic() > 0, "characteristic > 0 expected"); if (F.inCoeffDomain() && G.inCoeffDomain()) return 1; if (F.isZero() || G.isZero()) return 0; Variable alpha; #ifdef HAVE_FLINT if (!hasFirstAlgVar (F, alpha) && !hasFirstAlgVar (G,alpha)) { nmod_poly_t FLINTF, FLINTG; convertFacCF2nmod_poly_t (FLINTF, F); convertFacCF2nmod_poly_t (FLINTG, G); mp_limb_t FLINTresult= nmod_poly_resultant (FLINTF, FLINTG); nmod_poly_clear (FLINTF); nmod_poly_clear (FLINTG); return CanonicalForm ((long) FLINTresult); } #else if (!hasFirstAlgVar (F, alpha) && !hasFirstAlgVar (G,alpha)) { if (fac_NTL_char != getCharacteristic()) { fac_NTL_char= getCharacteristic(); zz_p::init (getCharacteristic()); } zz_pX NTLF= convertFacCF2NTLzzpX (F); zz_pX NTLG= convertFacCF2NTLzzpX (G); zz_p NTLResult= resultant (NTLF, NTLG); return CanonicalForm (to_long (rep (NTLResult))); } #endif //at this point F or G has an algebraic var. if (fac_NTL_char != getCharacteristic()) { fac_NTL_char= getCharacteristic(); zz_p::init (getCharacteristic()); } zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha)); zz_pE::init (NTLMipo); zz_pEX NTLF= convertFacCF2NTLzz_pEX (F, NTLMipo); zz_pEX NTLG= convertFacCF2NTLzz_pEX (G, NTLMipo); zz_pE NTLResult= resultant (NTLF, NTLG); return convertNTLzzpE2CF (NTLResult, alpha); #else return resultant (F, G, F.mvar()); #endif } static inline void evalPoint (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& FEval, CanonicalForm& GEval, CFGenerator& evalPoint) { int degF, degG; Variable x= Variable (1); degF= degree (F, x); degG= degree (G, x); do { if (!evalPoint.hasItems()) break; FEval= F (evalPoint.item(), 2); GEval= G (evalPoint.item(), 2); if (degree (FEval, 1) < degF || degree (GEval, 1) < degG) { evalPoint.next(); continue; } else return; } while (evalPoint.hasItems()); } static inline CanonicalForm newtonInterp (const CanonicalForm & alpha, const CanonicalForm & u, const CanonicalForm & newtonPoly, const CanonicalForm & oldInterPoly, const Variable & x) { CanonicalForm interPoly; interPoly= oldInterPoly+((u - oldInterPoly (alpha, x))/newtonPoly (alpha, x)) *newtonPoly; return interPoly; } CanonicalForm resultantFp (const CanonicalForm& A, const CanonicalForm& B, const Variable& x, bool prob) { ASSERT (getCharacteristic() > 0, "characteristic > 0 expected"); if (A.isZero() || B.isZero()) return 0; int degAx= degree (A, x); int degBx= degree (B, x); if (A.level() < x.level()) return power (A, degBx); if (B.level() < x.level()) return power (B, degAx); if (degAx == 0) return power (A, degBx); else if (degBx == 0) return power (B, degAx); if (A.isUnivariate() && B.isUnivariate() && A.level() == B.level()) return uniResultant (A, B); CanonicalForm F= A; CanonicalForm G= B; CFMap M, N; myCompress (F, G, M, N, x); F= M (F); G= M (G); Variable y= Variable (2); CanonicalForm GEval, FEval, recResult, H; CanonicalForm newtonPoly= 1; CanonicalForm modResult= 0; Variable z= Variable (1); int bound= degAx*degree (G, 2) + degree (F, 2)*degBx; int p= getCharacteristic(); CanonicalForm minpoly; Variable alpha= Variable (tmax (F.level(), G.level()) + 1); bool algExt= hasFirstAlgVar (F, alpha) || hasFirstAlgVar (G, alpha); CFGenerator * gen; bool extOfExt= false; Variable v= alpha; CanonicalForm primElemAlpha, imPrimElemAlpha; CFList source,dest; if (!algExt && (p < (1 << 28))) { // pass to an extension of size at least 2^29 // for very very large input that is maybe too small though int deg= ceil (29.0*((double) log (2)/log (p)))+1; minpoly= randomIrredpoly (deg, z); alpha= rootOf (minpoly); AlgExtGenerator AlgExtGen (alpha); gen= AlgExtGen.clone(); for (int i= 0; i < p; i++) // skip values from the prime field (*gen).next(); } else if (!algExt) { FFGenerator FFGen; gen= FFGen.clone(); } else { int deg= ceil (29.0*((double) log (2)/log (p))); if (degree (getMipo (alpha)) < deg) { mpz_t field_size; mpz_init (field_size); mpz_ui_pow_ui (field_size, p, deg + degree (getMipo (alpha)) - deg%degree (getMipo (alpha))); // field_size needs to fit in an int because of mapUp, mapDown, length of lists etc. if (mpz_fits_sint_p (field_size)) { minpoly= randomIrredpoly (deg + degree (getMipo (alpha)) - deg%degree (getMipo (alpha)), z); v= rootOf (minpoly); Variable V_buf2; bool primFail= false; extOfExt= true; primElemAlpha= primitiveElement (alpha, V_buf2, primFail); ASSERT (!primFail, "failure in integer factorizer"); if (primFail) ; //ERROR else imPrimElemAlpha= mapPrimElem (primElemAlpha, alpha, v); F= mapUp (F, alpha, v, primElemAlpha, imPrimElemAlpha, source, dest); G= mapUp (G, alpha, v, primElemAlpha, imPrimElemAlpha, source, dest); } else { deg= deg - deg % degree (getMipo (alpha)); mpz_ui_pow_ui (field_size, p, deg); while (deg / degree (getMipo (alpha)) >= 2 && !mpz_fits_sint_p (field_size)) { deg -= degree (getMipo (alpha)); mpz_ui_pow_ui (field_size, p, deg); } if (deg != degree (getMipo (alpha))) { minpoly= randomIrredpoly (deg, z); v= rootOf (minpoly); Variable V_buf2; bool primFail= false; extOfExt= true; primElemAlpha= primitiveElement (alpha, V_buf2, primFail); ASSERT (!primFail, "failure in integer factorizer"); if (primFail) ; //ERROR else imPrimElemAlpha= mapPrimElem (primElemAlpha, alpha, v); F= mapUp (F, alpha, v, primElemAlpha, imPrimElemAlpha, source, dest); G= mapUp (G, alpha, v, primElemAlpha, imPrimElemAlpha, source, dest); } } mpz_clear (field_size); } AlgExtGenerator AlgExtGen (v); gen= AlgExtGen.clone(); for (int i= 0; i < p; i++) (*gen).next(); } int count= 0; int equalCount= 0; CanonicalForm point; do { evalPoint (F, G, FEval, GEval, *gen); recResult= resultantFp (FEval, GEval, z, prob); H= newtonInterp ((*gen).item(), recResult, newtonPoly, modResult, y); if (H == modResult) equalCount++; else equalCount= 0; count++; if (count > bound || (prob && equalCount == 2 && !H.inCoeffDomain())) { if (!algExt && degree (H, alpha) <= 0) break; else if (algExt) { if (extOfExt && !isInExtension (H, imPrimElemAlpha, 1, primElemAlpha, dest, source)) { H= mapDown (H, primElemAlpha, imPrimElemAlpha, alpha, dest, source); prune (v); break; } else if (!extOfExt) break; } } modResult= H; newtonPoly *= (y - (*gen).item()); if ((*gen).hasItems()) (*gen).next(); else STICKYASSERT (0, "out of evaluation points"); } while (1); delete gen; return N (H); } static inline CanonicalForm balanceUni ( const CanonicalForm & f, const CanonicalForm & q ) { Variable x = f.mvar(); CanonicalForm result = 0, qh = q / 2; CanonicalForm c; CFIterator i; for ( i = f; i.hasTerms(); i++ ) { c = mod( i.coeff(), q ); if ( c > qh ) result += power( x, i.exp() ) * (c - q); else result += power( x, i.exp() ) * c; } return result; } static inline CanonicalForm symmetricRemainder (const CanonicalForm& f, const CanonicalForm& q) { CanonicalForm result= 0; if (f.isUnivariate() || f.inCoeffDomain()) return balanceUni (f, q); else { Variable x= f.mvar(); for (CFIterator i= f; i.hasTerms(); i++) result += power (x, i.exp())*symmetricRemainder (i.coeff(), q); } return result; } CanonicalForm resultantZ (const CanonicalForm& A, const CanonicalForm& B, const Variable& x, bool prob) { ASSERT (getCharacteristic() == 0, "characteristic > 0 expected"); #ifndef NOASSERT bool isRat= isOn (SW_RATIONAL); On (SW_RATIONAL); ASSERT (bCommonDen (A).isOne(), "input A is rational"); ASSERT (bCommonDen (B).isOne(), "input B is rational"); if (!isRat) Off (SW_RATIONAL); #endif int degAx= degree (A, x); int degBx= degree (B, x); if (A.level() < x.level()) return power (A, degBx); if (B.level() < x.level()) return power (B, degAx); if (degAx == 0) return power (A, degBx); else if (degBx == 0) return power (B, degAx); CanonicalForm F= A; CanonicalForm G= B; Variable X= x; if (F.level() != x.level() || G.level() != x.level()) { if (F.level() > G.level()) X= F.mvar(); else X= G.mvar(); F= swapvar (F, X, x); G= swapvar (G, X, x); } // now X is the main variable CanonicalForm d= 0; CanonicalForm dd= 0; CanonicalForm buf; for (CFIterator i= F; i.hasTerms(); i++) { buf= oneNorm (i.coeff()); d= (buf > d) ? buf : d; } CanonicalForm e= 0, ee= 0; for (CFIterator i= G; i.hasTerms(); i++) { buf= oneNorm (i.coeff()); e= (buf > e) ? buf : e; } d= power (d, degBx); e= power (e, degAx); CanonicalForm bound= 1; for (int i= degBx + degAx; i > 1; i--) bound *= i; bound *= d*e; bound *= 2; bool onRational= isOn (SW_RATIONAL); if (onRational) Off (SW_RATIONAL); int i = cf_getNumBigPrimes() - 1; int p; CanonicalForm l= lc (F)*lc(G); CanonicalForm resultModP, q (0), newResult, newQ; CanonicalForm result; int equalCount= 0; CanonicalForm test, newTest; int count= 0; do { p = cf_getBigPrime( i ); i--; while ( i >= 0 && mod( l, p ) == 0) { p = cf_getBigPrime( i ); i--; } if (i <= 0) return resultant (A, B, x); setCharacteristic (p); TIMING_START (fac_resultant_p); resultModP= resultantFp (mapinto (F), mapinto (G), X, prob); TIMING_END_AND_PRINT (fac_resultant_p, "time to compute resultant mod p: "); setCharacteristic (0); count++; if ( q.isZero() ) { result= mapinto(resultModP); q= p; } else { chineseRemainder( result, q, mapinto (resultModP), p, newResult, newQ ); q= newQ; result= newResult; test= symmetricRemainder (result,q); if (test != newTest) { newTest= test; equalCount= 0; } else equalCount++; if (newQ > bound || (prob && equalCount == 2)) { result= test; break; } } } while (1); if (onRational) On (SW_RATIONAL); return swapvar (result, X, x); } #endif singular-4.0.3+ds/factory/cfModResultant.h000066400000000000000000000025511266270727000205320ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfModResultant.h * * modular resultant algorithm as described by G. E. Collins in "The Calculation * of multivariate polynomial resultants" * * @author Martin Lee * **/ /*****************************************************************************/ #ifndef CF_MOD_RESULTANT_H #define CF_MOD_RESULTANT_H #include "canonicalform.h" /// modular resultant algorihtm over Fp /// /// @return @a resultantFp returns the resultant of A and B wrt. x CanonicalForm resultantFp (const CanonicalForm& A,///<[in] some poly const CanonicalForm& B,///<[in] some poly const Variable& x, ///<[in] some polynomial variable bool prob= true ///<[in] if true use probabilistic algorithm ); /*BEGINPUBLIC*/ /// modular resultant algorihtm over Z /// /// @return @a resultantZ returns the resultant of A and B wrt. x CanonicalForm resultantZ (const CanonicalForm& A, ///<[in] some poly const CanonicalForm& B, ///<[in] some poly const Variable& x, ///<[in] some polynomial variable bool prob= true ///<[in] if true use probabilistic algorithm ); /*ENDPUBLIC*/ #endif singular-4.0.3+ds/factory/cfNTLzzpEXGCD.cc000066400000000000000000000172501266270727000202250ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file cfNTLzzpEXGCD.cc * * @author Martin Lee * * Univariate GCD and extended GCD over Z/p[t]/(f)[x] for reducible f * * @note the following code is slightly modified code out of * lzz_pEX.c from Victor Shoup's NTL. Below is NTL's copyright notice. * * @par Copyright: * (c) by The SINGULAR Team, see LICENSE file * COPYRIGHT NOTICE for NTL 5.5 (modified for Singular 2-0-6 - 3-1) NTL -- A Library for Doing Number Theory Copyright (C) 1996-2009 Victor Shoup The most recent version of NTL is available at http://www.shoup.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. This entire copyright notice should be placed in an appropriately conspicuous place accompanying all distributions of software that make use of NTL. The above terms apply to all of the software modules distributed with NTL, i.e., all source files in either the ntl-xxx.tar.gz or WinNTL-xxx.zip distributions. In general, the individual files do not contain copyright notices. Note that the quad_float package is derived from the doubledouble package, originally developed by Keith Briggs, and also licensed unger the GNU GPL. The files quad_float.c and quad_float.h contain more detailed copyright notices. Note that the traditional long integer package used by NTL, lip.c, is derived from---and represents an extensive modification of--- a package originally developed and copyrighted by Arjen Lenstra, who has agreed to renounce any copyright claims on the particular version of the long integer package appearing in NTL, so that the this package now is covered by the GNU GPL as well. Note that the alternative long integer package used by NTL is GMP, which is written by Torbjorn Granlund . GMP is licensed under the terms of the GNU Lesser General Public License. Note that NTL makes use of the RSA Data Security, Inc. MD5 Message Digest Algorithm. Note that prior to version 4.0, NTL was distributed under the following terms: NTL is freely available for research and educational purposes. I don't want to attach any legalistic licensing restrictions on users of NTL. However, NTL should not be linked in a commercial program (although using data in a commercial product produced by a program that used NTL is fine). The hope is that the GNU GPL is actually less restrictive than these older terms; however, in any circumstances such that GNU GPL is more restrictive, then the following rule is in force: versions prior to 4.0 may continue to be used under the old terms, but users of versions 4.0 or later should adhere to the terms of the GNU GPL. **/ #include "config.h" #include "cfNTLzzpEXGCD.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif #ifdef HAVE_NTL long InvModStatus (zz_pE& x, const zz_pE& a) { return InvModStatus(x._zz_pE__rep, a._zz_pE__rep, zz_pE::modulus()); } static void SetSize(vec_zz_pX& x, long n, long m) { x.SetLength(n); long i; for (i = 0; i < n; i++) x[i].rep.SetMaxLength(m); } void tryPlainRem(zz_pEX& r, const zz_pEX& a, const zz_pEX& b, vec_zz_pX& x, bool& fail) { long da, db, dq, i, j, LCIsOne; const zz_pE *bp; zz_pX *xp; zz_pE LCInv, t; zz_pX s; da = deg(a); db = deg(b); if (db < 0) Error("zz_pEX: division by zero"); if (da < db) { r = a; return; } bp = b.rep.elts(); if (IsOne(bp[db])) LCIsOne = 1; else { LCIsOne = 0; fail= InvModStatus (LCInv, bp[db]); //inv(LCInv, bp[db]); if (fail) return; } for (i = 0; i <= da; i++) x[i] = rep(a.rep[i]); xp = x.elts(); dq = da - db; for (i = dq; i >= 0; i--) { conv(t, xp[i+db]); if (!LCIsOne) mul(t, t, LCInv); NTL::negate(t, t); for (j = db-1; j >= 0; j--) { mul(s, rep(t), rep(bp[j])); add(xp[i+j], xp[i+j], s); } } r.rep.SetLength(db); for (i = 0; i < db; i++) conv(r.rep[i], xp[i]); r.normalize(); } void tryPlainDivRem(zz_pEX& q, zz_pEX& r, const zz_pEX& a, const zz_pEX& b, bool& fail) { long da, db, dq, i, j, LCIsOne; const zz_pE *bp; zz_pE *qp; zz_pX *xp; zz_pE LCInv, t; zz_pX s; da = deg(a); db = deg(b); if (db < 0) Error("zz_pEX: division by zero"); if (da < db) { r = a; clear(q); return; } zz_pEX lb; if (&q == &b) { lb = b; bp = lb.rep.elts(); } else bp = b.rep.elts(); if (IsOne(bp[db])) LCIsOne = 1; else { LCIsOne = 0; fail= InvModStatus (LCInv, bp[db]); //inv(LCInv, bp[db]); if (fail) return; } vec_zz_pX x; SetSize(x, da+1, 2*zz_pE::degree()); for (i = 0; i <= da; i++) x[i] = rep(a.rep[i]); xp = x.elts(); dq = da - db; q.rep.SetLength(dq+1); qp = q.rep.elts(); for (i = dq; i >= 0; i--) { conv(t, xp[i+db]); if (!LCIsOne) mul(t, t, LCInv); qp[i] = t; NTL::negate(t, t); for (j = db-1; j >= 0; j--) { mul(s, rep(t), rep(bp[j])); add(xp[i+j], xp[i+j], s); } } r.rep.SetLength(db); for (i = 0; i < db; i++) conv(r.rep[i], xp[i]); r.normalize(); } void tryNTLGCD(zz_pEX& x, const zz_pEX& a, const zz_pEX& b, bool& fail) { zz_pE t; if (IsZero(b)) x = a; else if (IsZero(a)) x = b; else { long n = max(deg(a),deg(b)) + 1; zz_pEX u(INIT_SIZE, n), v(INIT_SIZE, n); vec_zz_pX tmp; SetSize(tmp, n, 2*zz_pE::degree()); u = a; v = b; do { tryPlainRem(u, u, v, tmp, fail); if (fail) return; swap(u, v); } while (!IsZero(v)); x = u; } if (IsZero(x)) return; if (IsOne(LeadCoeff(x))) return; /* make gcd monic */ fail= InvModStatus (t, LeadCoeff(x)); if (fail) return; mul(x, x, t); } void tryNTLXGCD(zz_pEX& d, zz_pEX& s, zz_pEX& t, const zz_pEX& a, const zz_pEX& b, bool& fail) { zz_pE z; if (IsZero(b)) { set(s); clear(t); d = a; } else if (IsZero(a)) { clear(s); set(t); d = b; } else { long e = max(deg(a), deg(b)) + 1; zz_pEX temp(INIT_SIZE, e), u(INIT_SIZE, e), v(INIT_SIZE, e), u0(INIT_SIZE, e), v0(INIT_SIZE, e), u1(INIT_SIZE, e), v1(INIT_SIZE, e), u2(INIT_SIZE, e), v2(INIT_SIZE, e), q(INIT_SIZE, e); set(u1); clear(v1); clear(u2); set(v2); u = a; v = b; do { fail= InvModStatus (z, LeadCoeff(v)); if (fail) return; DivRem(q, u, u, v); swap(u, v); u0 = u2; v0 = v2; mul(temp, q, u2); sub(u2, u1, temp); mul(temp, q, v2); sub(v2, v1, temp); u1 = u0; v1 = v0; } while (!IsZero(v)); d = u; s = u1; t = v1; } if (IsZero(d)) return; if (IsOne(LeadCoeff(d))) return; /* make gcd monic */ fail= InvModStatus (z, LeadCoeff(d)); if (fail) return; mul(d, d, z); mul(s, s, z); mul(t, t, z); } #endif singular-4.0.3+ds/factory/cfNTLzzpEXGCD.h000066400000000000000000000105441266270727000200660ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfNTLzzpEXGCD.h * * This file defines functions for univariate GCD and extended GCD * over Z/p[t]/(f)[x] for reducible f * * @note the following code is slightly modified code out of * lzz_pEX.h from Victor Shoup's NTL. Below is NTL's copyright notice. * * ABSTRACT: Langemyr, McCallum "The Computation of Polynomial Greatest Common * Divisors over an algebraic number fields" * * @author Martin Lee * COPYRIGHT NOTICE for NTL 5.5 (modified for Singular 2-0-6 - 3-1) NTL -- A Library for Doing Number Theory Copyright (C) 1996-2009 Victor Shoup The most recent version of NTL is available at http://www.shoup.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. This entire copyright notice should be placed in an appropriately conspicuous place accompanying all distributions of software that make use of NTL. The above terms apply to all of the software modules distributed with NTL, i.e., all source files in either the ntl-xxx.tar.gz or WinNTL-xxx.zip distributions. In general, the individual files do not contain copyright notices. Note that the quad_float package is derived from the doubledouble package, originally developed by Keith Briggs, and also licensed unger the GNU GPL. The files quad_float.c and quad_float.h contain more detailed copyright notices. Note that the traditional long integer package used by NTL, lip.c, is derived from---and represents an extensive modification of--- a package originally developed and copyrighted by Arjen Lenstra, who has agreed to renounce any copyright claims on the particular version of the long integer package appearing in NTL, so that the this package now is covered by the GNU GPL as well. Note that the alternative long integer package used by NTL is GMP, which is written by Torbjorn Granlund . GMP is licensed under the terms of the GNU Lesser General Public License. Note that NTL makes use of the RSA Data Security, Inc. MD5 Message Digest Algorithm. Note that prior to version 4.0, NTL was distributed under the following terms: NTL is freely available for research and educational purposes. I don't want to attach any legalistic licensing restrictions on users of NTL. However, NTL should not be linked in a commercial program (although using data in a commercial product produced by a program that used NTL is fine). The hope is that the GNU GPL is actually less restrictive than these older terms; however, in any circumstances such that GNU GPL is more restrictive, then the following rule is in force: versions prior to 4.0 may continue to be used under the old terms, but users of versions 4.0 or later should adhere to the terms of the GNU GPL. **/ #ifndef CF_NTL_ZZ_PEX_GCD_H #define CF_NTL_ZZ_PEX_GCD_H // #include "config.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif #ifdef HAVE_NTL /// compute the GCD x of a and b, fail is set to true if a zero divisor is /// encountered void tryNTLGCD(zz_pEX& x, ///<[in,out] GCD of a and b const zz_pEX& a,///<[in] s.a. const zz_pEX& b,///<[in] s.a. bool& fail ///<[in,out] s.a. ); /// compute the extended GCD d=s*a+t*b, fail is set to true if a zero divisor is /// encountered void tryNTLXGCD(zz_pEX& d, ///<[in,out] GCD of a and b zz_pEX& s, ///<[in,out] s. a. zz_pEX& t, ///<[in,out] s. a. const zz_pEX& a,///<[in] s. a. const zz_pEX& b,///<[in] s. a. bool& fail ///<[in,out] s. a. ); #endif #endif singular-4.0.3+ds/factory/cfNewtonPolygon.cc000066400000000000000000000767231266270727000211050ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfNewtonPolygon.cc * * This file provides functions to compute the Newton polygon of a bivariate * polynomial * * @author Martin Lee * **/ /*****************************************************************************/ #include "config.h" #include "cf_assert.h" #include #include "canonicalform.h" #include "cf_iter.h" #include "cf_algorithm.h" #include "cf_primes.h" #include "cf_reval.h" #include "cf_factory.h" #include "gfops.h" #include "cfNewtonPolygon.h" #include "templates/ftmpl_functions.h" static void translate (int** points, int* point, int sizePoints) //make point to 0 { for (int i= 0; i < sizePoints; i++) { points[i] [0] -= point [0]; points[i] [1] -= point [1]; } } static int smallestPointIndex (int** points, int sizePoints) { int min= 0; for (int i= 1; i < sizePoints; i++) { if (points[i][0] < points[min][0] || (points[i] [0] == points[min] [0] && points[i] [1] < points[min] [1])) min= i; } return min; } static void swap (int** points, int i, int j) { int* tmp= points[i]; points[i]= points[j]; points[j]= tmp; } static bool isLess (int* point1, int* point2) { long area= point1[0]*point2[1]- point1[1]*point2[0]; if (area > 0) return true; if (area == 0) { return (abs (point1[0]) + abs (point1[1]) > abs (point2[0]) + abs (point2[1])); } return false; } static void quickSort (int lo, int hi, int** points) { int i= lo, j= hi; int* point= new int [2]; point [0]= points [(lo+hi)/2] [0]; point [1]= points [(lo+hi)/2] [1]; while (i <= j) { while (isLess (points [i], point) && i < hi) i++; while (isLess (point, points[j]) && j > lo) j--; if (i <= j) { swap (points, i, j); i++; j--; } } delete [] point; if (lo < j) quickSort (lo, j, points); if (i < hi) quickSort (i, hi, points); } static void sort (int** points, int sizePoints) { quickSort (1, sizePoints - 1, points); } // check whether p2 is convex static bool isConvex (int* point1, int* point2, int* point3) { long relArea= (point1[0] - point2[0])*(point3[1] - point2[1]) - (point1[1] - point2[1])*(point3[0] - point2[0]); if (relArea < 0) return true; if (relArea == 0) { return !(abs (point1[0] - point3[0]) + abs (point1[1] - point3[1]) >= (abs (point2[0] - point1[0]) + abs (point2[1] - point1[1]) + abs (point2[0] - point3[0]) + abs (point2[1] - point3[1]))); } return false; } static bool isConvex (int** points, int i) { return isConvex (points[i - 1], points [i], points [i + 1]); } int grahamScan (int** points, int sizePoints) { swap (points, 0, smallestPointIndex (points, sizePoints)); int * minusPoint= new int [2]; minusPoint [0]= points[0] [0]; minusPoint [1]= points[0] [1]; translate (points, minusPoint, sizePoints); sort (points, sizePoints); minusPoint[0]= - minusPoint[0]; minusPoint[1]= - minusPoint[1]; translate (points, minusPoint, sizePoints); //reverse translation delete [] minusPoint; int i= 3, k= 3; while (k < sizePoints) { swap (points, i, k); while (!isConvex (points, i - 1)) { swap (points, i - 1, i); i--; } k++; i++; } if (i + 1 <= sizePoints || i == sizePoints) { long relArea= (points [i-2][0] - points [i-1][0])*(points [0][1] - points [i-1][1])- (points [i-2][1] - points [i-1][1])*(points [0][0] - points [i-1][0]); if (relArea == 0) { if (abs (points [i-2][0] - points [0][0]) + abs (points [i-2][1] - points [0][1]) >= abs (points [i-1][0] - points [i-2][0]) + abs (points [i-1][1] - points [i-2][1]) + abs (points [i-1][0] - points [0][0]) + abs (points [i-1][1] - points [0][1])) i--; } } return i; } //points[i] [0] is x-coordinate, points [i] [1] is y-coordinate int polygon (int** points, int sizePoints) { if (sizePoints < 3) return sizePoints; return grahamScan (points, sizePoints); } static int* getDegrees (const CanonicalForm& F, int& sizeOfOutput) { if (F.inCoeffDomain()) { int* result= new int [1]; result [0]= 0; sizeOfOutput= 1; return result; } sizeOfOutput= size (F); int* result= new int [sizeOfOutput]; int j= 0; for (CFIterator i= F; i.hasTerms(); i++, j++) result [j]= i.exp(); return result; } //get points in Z^2 whose convex hull is the Newton polygon int ** getPoints (const CanonicalForm& F, int& n) { n= size (F); int ** points= new int* [n]; for (int i= 0; i < n; i++) points [i]= new int [2]; int j= 0; int * buf; int bufSize; if (F.isUnivariate() && F.level() == 1) { for (CFIterator i= F; i.hasTerms(); i++, j++) { points [j] [0]= i.exp(); points [j] [1]= 0; } return points; } for (CFIterator i= F; i.hasTerms(); i++) { buf= getDegrees (i.coeff(), bufSize); for (int k= 0; k < bufSize; k++, j++) { points [j] [0]= i.exp(); points [j] [1]= buf [k]; } delete [] buf; } return points; } int ** merge (int ** points1, int sizePoints1, int ** points2, int sizePoints2, int& sizeResult) { int i, j; sizeResult= sizePoints1+sizePoints2; for (i= 0; i < sizePoints1; i++) { for (j= 0; j < sizePoints2; j++) { if (points1[i][0] != points2[j][0]) continue; else { if (points1[i][1] != points2[j][1]) continue; else { points2[j][0]= -1; points2[j][1]= -1; sizeResult--; } } } } if (sizeResult == 0) return points1; int ** result= new int *[sizeResult]; for (i= 0; i < sizeResult; i++) result [i]= new int [2]; int k= 0; for (i= 0; i < sizePoints1; i++, k++) { result[k][0]= points1[i][0]; result[k][1]= points1[i][1]; } for (i= 0; i < sizePoints2; i++) { if (points2[i][0] < 0) continue; else { result[k][0]= points2[i][0]; result[k][1]= points2[i][1]; k++; } } return result; } // assumes a bivariate poly as input int ** newtonPolygon (const CanonicalForm& F, int& sizeOfNewtonPoly) { int sizeF= size (F); int ** points= new int* [sizeF]; for (int i= 0; i < sizeF; i++) points [i]= new int [2]; int j= 0; int * buf; int bufSize; for (CFIterator i= F; i.hasTerms(); i++) { buf= getDegrees (i.coeff(), bufSize); for (int k= 0; k < bufSize; k++, j++) { points [j] [0]= i.exp(); points [j] [1]= buf [k]; } delete [] buf; } int n= polygon (points, sizeF); int ** result= new int* [n]; for (int i= 0; i < n; i++) { result [i]= new int [2]; result [i] [0]= points [i] [0]; result [i] [1]= points [i] [1]; } sizeOfNewtonPoly= n; for (int i= 0; i < sizeF; i++) delete [] points[i]; delete [] points; return result; } // assumes a bivariate polys as input int ** newtonPolygon (const CanonicalForm& F, const CanonicalForm& G, int& sizeOfNewtonPoly) { int sizeF= size (F); int ** pointsF= new int* [sizeF]; for (int i= 0; i < sizeF; i++) pointsF [i]= new int [2]; int j= 0; int * buf; int bufSize; for (CFIterator i= F; i.hasTerms(); i++) { buf= getDegrees (i.coeff(), bufSize); for (int k= 0; k < bufSize; k++, j++) { pointsF [j] [0]= i.exp(); pointsF [j] [1]= buf [k]; } delete [] buf; } int sizeG= size (G); int ** pointsG= new int* [sizeG]; for (int i= 0; i < sizeG; i++) pointsG [i]= new int [2]; j= 0; for (CFIterator i= G; i.hasTerms(); i++) { buf= getDegrees (i.coeff(), bufSize); for (int k= 0; k < bufSize; k++, j++) { pointsG [j] [0]= i.exp(); pointsG [j] [1]= buf [k]; } delete [] buf; } int sizePoints; int ** points= merge (pointsF, sizeF, pointsG, sizeG, sizePoints); int n= polygon (points, sizePoints); int ** result= new int* [n]; for (int i= 0; i < n; i++) { result [i]= new int [2]; result [i] [0]= points [i] [0]; result [i] [1]= points [i] [1]; } sizeOfNewtonPoly= n; for (int i= 0; i < sizeF; i++) delete [] pointsF[i]; delete [] pointsF; for (int i= 0; i < sizeG; i++) delete [] pointsG[i]; delete [] pointsG; return result; } // assumes first sizePoints entries of points form a Newton polygon bool isInPolygon (int ** points, int sizePoints, int* point) { int ** buf= new int* [sizePoints + 1]; for (int i= 0; i < sizePoints; i++) { buf [i]= new int [2]; buf [i] [0]= points [i] [0]; buf [i] [1]= points [i] [1]; } buf [sizePoints]= new int [2]; buf [sizePoints] [0]= point [0]; buf [sizePoints] [1]= point [1]; int sizeBuf= sizePoints + 1; swap (buf, 0, smallestPointIndex (buf, sizeBuf)); int * minusPoint= new int [2]; minusPoint [0]= buf[0] [0]; minusPoint [1]= buf[0] [1]; translate (buf, minusPoint, sizeBuf); sort (buf, sizeBuf); minusPoint[0]= - minusPoint[0]; minusPoint[1]= - minusPoint[1]; translate (buf, minusPoint, sizeBuf); //reverse translation delete [] minusPoint; if (buf [0] [0] == point [0] && buf [0] [1] == point [1]) { for (int i= 0; i < sizeBuf; i++) delete [] buf[i]; delete [] buf; return false; } for (int i= 1; i < sizeBuf-1; i++) { if (buf [i] [0] == point [0] && buf [i] [1] == point [1]) { bool result= !isConvex (buf, i); for (int i= 0; i < sizeBuf; i++) delete [] buf [i]; delete [] buf; return result; } } if (buf [sizeBuf - 1] [0] == point [0] && buf [sizeBuf-1] [1] == point [1]) { buf [1] [0]= point [0]; buf [1] [1]= point [1]; buf [2] [0]= buf [0] [0]; buf [2] [1]= buf [0] [1]; buf [0] [0]= buf [sizeBuf-2] [0]; buf [0] [1]= buf [sizeBuf-2] [1]; bool result= !isConvex (buf, 1); for (int i= 0; i < sizeBuf; i++) delete [] buf [i]; delete [] buf; return result; } for (int i= 0; i < sizeBuf; i++) delete [] buf [i]; delete [] buf; return false; } void lambda (int** points, int sizePoints) { for (int i= 0; i < sizePoints; i++) points [i] [1]= points [i] [1] - points [i] [0]; } void lambdaInverse (int** points, int sizePoints) { for (int i= 0; i < sizePoints; i++) points [i] [1]= points [i] [1] + points [i] [0]; } void tau (int** points, int sizePoints, int k) { for (int i= 0; i < sizePoints; i++) points [i] [1]= points [i] [1] + k; } void mu (int** points, int sizePoints) { int tmp; for (int i= 0; i < sizePoints; i++) { tmp= points [i] [0]; points [i] [0]= points [i] [1]; points [i] [1]= tmp; } } void getMaxMin (int** points, int sizePoints, int& minDiff, int& minSum, int& maxDiff, int& maxSum, int& maxX, int& maxY ) { minDiff= points [0] [1] - points [0] [0]; minSum= points [0] [1] + points [0] [0]; maxDiff= points [0] [1] - points [0] [0]; maxSum= points [0] [1] + points [0] [0]; maxX= points [0] [1]; maxY= points [0] [0]; int diff, sum; for (int i= 1; i < sizePoints; i++) { diff= points [i] [1] - points [i] [0]; sum= points [i] [1] + points [i] [0]; minDiff= tmin (minDiff, diff); minSum= tmin (minSum, sum); maxDiff= tmax (maxDiff, diff); maxSum= tmax (maxSum, sum); maxX= tmax (maxX, points [i] [1]); maxY= tmax (maxY, points [i] [0]); } } void mpz_mat_mul (const mpz_t* N, mpz_t*& M) { mpz_t * tmp= new mpz_t[4]; mpz_init_set (tmp[0], N[0]); mpz_mul (tmp[0], tmp[0], M[0]); mpz_addmul (tmp[0], N[1], M[2]); mpz_init_set (tmp[1], N[0]); mpz_mul (tmp[1], tmp[1], M[1]); mpz_addmul (tmp[1], N[1], M[3]); mpz_init_set (tmp[2], N[2]); mpz_mul (tmp[2], tmp[2], M[0]); mpz_addmul (tmp[2], N[3], M[2]); mpz_init_set (tmp[3], N[2]); mpz_mul (tmp[3], tmp[3], M[1]); mpz_addmul (tmp[3], N[3], M[3]); mpz_set (M[0], tmp[0]); mpz_set (M[1], tmp[1]); mpz_set (M[2], tmp[2]); mpz_set (M[3], tmp[3]); mpz_clear (tmp[0]); mpz_clear (tmp[1]); mpz_clear (tmp[2]); mpz_clear (tmp[3]); delete [] tmp; } void mpz_mat_inv (mpz_t*& M) { mpz_t det; mpz_init_set (det, M[0]); mpz_mul (det, det, M[3]); mpz_submul (det, M[1], M[2]); mpz_t tmp; mpz_init_set (tmp, M[0]); mpz_divexact (tmp, tmp, det); mpz_set (M[0], M[3]); mpz_divexact (M[0], M[0], det); mpz_set (M[3], tmp); mpz_neg (M[1], M[1]); mpz_divexact (M[1], M[1], det); mpz_neg (M[2], M[2]); mpz_divexact (M[2], M[2], det); mpz_clear (det); mpz_clear (tmp); } void convexDense(int** points, int sizePoints, mpz_t*& M, mpz_t*& A) { if (sizePoints < 3) { if (sizePoints == 2) { mpz_t u,v,g,maxX,maxY; mpz_init (u); mpz_init (v); mpz_init (g); mpz_init_set_si (maxX, (points[1][1] < points[0][1])?points[0][1]:points[1][1]); mpz_init_set_si (maxY, (points[1][0] < points[0][0])?points[0][0]:points[1][0]); mpz_gcdext (g, u, v, maxX, maxY); if (points [0] [1] != points [0] [0] && points [1] [0] != points [1] [1]) { mpz_set (A[0], u); mpz_mul (A[0], A[0], maxX); mpz_set (M[2], maxY); mpz_divexact (M[2], M[2], g); mpz_set (A[1], M[2]); mpz_neg (A[1], A[1]); mpz_mul (A[1], A[1], maxX); mpz_neg (u, u); mpz_set (M[0], u); mpz_set (M[1], v); mpz_set (M[3], maxX); mpz_divexact (M[3], M[3], g); } else { mpz_set (M[0], u); mpz_set (M[1], v); mpz_set (M[2], maxY); mpz_divexact (M[2], M[2], g); mpz_neg (M[2], M[2]); mpz_set (M[3], maxX); mpz_divexact (M[3], M[3], g); } mpz_clear (u); mpz_clear (v); mpz_clear (g); mpz_clear (maxX); mpz_clear (maxY); } else if (sizePoints == 1) { mpz_set_si (M[0], 1); mpz_set_si (M[3], 1); } return; } mpz_set_si (M[0], 1); mpz_set_si (M[3], 1); mpz_t * Mu= new mpz_t[4]; mpz_init_set_si (Mu[1], 1); mpz_init_set_si (Mu[2], 1); mpz_init (Mu[0]); mpz_init (Mu[3]); mpz_t * Lambda= new mpz_t[4]; mpz_init_set_si (Lambda[0], 1); mpz_init_set_si (Lambda[1], -1); mpz_init_set_si (Lambda[3], 1); mpz_init (Lambda[2]); mpz_t * InverseLambda= new mpz_t[4]; mpz_init_set_si (InverseLambda[0], 1); mpz_init_set_si (InverseLambda[1], 1); mpz_init_set_si (InverseLambda[3], 1); mpz_init (InverseLambda[2]); mpz_t tmp; mpz_init (tmp); int minDiff, minSum, maxDiff, maxSum, maxX, maxY, b, d, f, h; getMaxMin(points, sizePoints, minDiff, minSum, maxDiff, maxSum, maxX, maxY); do { if (maxX < maxY) { mu (points, sizePoints); mpz_mat_mul (Mu, M); mpz_set (tmp, A[0]); mpz_set (A[0], A[1]); mpz_set (A[1], tmp); } getMaxMin(points, sizePoints, minDiff, minSum, maxDiff, maxSum, maxX, maxY); b= maxX - maxDiff; d= maxX + maxY - maxSum; f= maxY + minDiff; h= minSum; if (b + f > maxY) { lambda (points, sizePoints); tau (points, sizePoints, maxY - f); mpz_mat_mul (Lambda, M); if (maxY-f > 0) mpz_add_ui (A[0], A[0], maxY-f); else mpz_add_ui (A[0], A[0], f-maxY); maxX= maxX + maxY - b - f; } else if (d + h > maxY) { lambdaInverse (points, sizePoints); tau (points, sizePoints, -h); mpz_mat_mul (InverseLambda, M); if (h < 0) mpz_add_ui (A[0], A[0], -h); else mpz_sub_ui (A[0], A[0], h); maxX= maxX + maxY - d - h; } else { mpz_clear (tmp); mpz_clear (Mu[0]); mpz_clear (Mu[1]); mpz_clear (Mu[2]); mpz_clear (Mu[3]); delete [] Mu; mpz_clear (Lambda[0]); mpz_clear (Lambda[1]); mpz_clear (Lambda[2]); mpz_clear (Lambda[3]); delete [] Lambda; mpz_clear (InverseLambda[0]); mpz_clear (InverseLambda[1]); mpz_clear (InverseLambda[2]); mpz_clear (InverseLambda[3]); delete [] InverseLambda; return; } } while (1); } CanonicalForm compress (const CanonicalForm& F, mpz_t*& M, mpz_t*& A, bool computeMA) { int n; int ** newtonPolyg= NULL; if (computeMA) { newtonPolyg= newtonPolygon (F, n); convexDense (newtonPolyg, n, M, A); } CanonicalForm result= 0; Variable x= Variable (1); Variable y= Variable (2); mpz_t expX, expY, minExpX, minExpY; mpz_init (expX); mpz_init (expY); mpz_init (minExpX); mpz_init (minExpY); int k= 0; Variable alpha; mpz_t * exps= new mpz_t [2*size (F)]; int count= 0; for (CFIterator i= F; i.hasTerms(); i++) { if (i.coeff().inCoeffDomain() && hasFirstAlgVar (i.coeff(), alpha)) { mpz_set (expX, A[0]); mpz_set (expY, A[1]); mpz_addmul_ui (expX, M[1], i.exp()); mpz_addmul_ui (expY, M[3], i.exp()); if (k == 0) { mpz_set (minExpX, expX); mpz_set (minExpY, expY); k= 1; } else { if (mpz_cmp (minExpY, expY) > 0) mpz_set (minExpY, expY); if (mpz_cmp (minExpX, expX) > 0) mpz_set (minExpX, expX); } mpz_init_set (exps[count], expX); count++; mpz_init_set (exps[count], expY); count++; continue; } CFIterator j= i.coeff(); if (k == 0) { mpz_set (expX, A[0]); mpz_addmul_ui (expX, M[1], i.exp()); mpz_addmul_ui (expX, M[0], j.exp()); mpz_set (expY, A[1]); mpz_addmul_ui (expY, M[3], i.exp()); mpz_addmul_ui (expY, M[2], j.exp()); mpz_set (minExpX, expX); mpz_set (minExpY, expY); mpz_init_set (exps[count], expX); count++; mpz_init_set (exps[count], expY); count++; j++; k= 1; } for (; j.hasTerms(); j++) { mpz_set (expX, A[0]); mpz_addmul_ui (expX, M[1], i.exp()); mpz_addmul_ui (expX, M[0], j.exp()); mpz_set (expY, A[1]); mpz_addmul_ui (expY, M[3], i.exp()); mpz_addmul_ui (expY, M[2], j.exp()); mpz_init_set (exps[count], expX); count++; mpz_init_set (exps[count], expY); count++; if (mpz_cmp (minExpY, expY) > 0) mpz_set (minExpY, expY); if (mpz_cmp (minExpX, expX) > 0) mpz_set (minExpX, expX); } } count= 0; int mExpX= mpz_get_si (minExpX); int mExpY= mpz_get_si (minExpY); for (CFIterator i= F; i.hasTerms(); i++) { if (i.coeff().inCoeffDomain() && hasFirstAlgVar (i.coeff(), alpha)) { result += i.coeff()*power (x, mpz_get_si (exps[count])-mExpX)* power (y, mpz_get_si (exps[count+1])-mExpY); count += 2; continue; } CFIterator j= i.coeff(); for (; j.hasTerms(); j++) { result += j.coeff()*power (x, mpz_get_si (exps[count])-mExpX)* power (y, mpz_get_si (exps[count+1])-mExpY); count += 2; } } CanonicalForm tmp= LC (result); if (tmp.inPolyDomain() && degree (tmp) <= 0) { int d= degree (result); Variable x= result.mvar(); result -= tmp*power (x, d); result += Lc (tmp)*power (x, d); } if (computeMA) { for (int i= 0; i < n; i++) delete [] newtonPolyg [i]; delete [] newtonPolyg; mpz_mat_inv (M); } delete [] exps; mpz_clear (expX); mpz_clear (expY); mpz_clear (minExpX); mpz_clear (minExpY); return result; } CanonicalForm decompress (const CanonicalForm& F, const mpz_t* inverseM, const mpz_t * A) { CanonicalForm result= 0; Variable x= Variable (1); Variable y= Variable (2); mpz_t expX, expY, minExpX, minExpY; mpz_init (expX); mpz_init (expY); mpz_init (minExpX); mpz_init (minExpY); mpz_t * exps= new mpz_t [2*size(F)]; int count= 0; if (F.isUnivariate() && F.level() == 1) { CFIterator i= F; mpz_set_si (expX, i.exp()); mpz_sub (expX, expX, A[0]); mpz_mul (expX, expX, inverseM[0]); mpz_submul (expX, inverseM[1], A[1]); mpz_set_si (expY, i.exp()); mpz_sub (expY, expY, A[0]); mpz_mul (expY, expY, inverseM[2]); mpz_submul (expY, inverseM[3], A[1]); mpz_set (minExpX, expX); mpz_set (minExpY, expY); mpz_init_set (exps[count], expX); mpz_init_set (exps[count+1], expY); count += 2; i++; for (; i.hasTerms(); i++) { mpz_set_si (expX, i.exp()); mpz_sub (expX, expX, A[0]); mpz_mul (expX, expX, inverseM[0]); mpz_submul (expX, inverseM[1], A[1]); mpz_set_si (expY, i.exp()); mpz_sub (expY, expY, A[0]); mpz_mul (expY, expY, inverseM[2]); mpz_submul (expY, inverseM[3], A[1]); mpz_init_set (exps[count], expX); mpz_init_set (exps[count+1], expY); count += 2; if (mpz_cmp (minExpY, expY) > 0) mpz_set (minExpY, expY); if (mpz_cmp (minExpX, expX) > 0) mpz_set (minExpX, expX); } int mExpX= mpz_get_si (minExpX); int mExpY= mpz_get_si (minExpY); count= 0; for (i= F; i.hasTerms(); i++) { result += i.coeff()*power (x, mpz_get_si (exps[count])-mExpX)* power (y, mpz_get_si (exps[count+1])-mExpY); count += 2; } mpz_clear (expX); mpz_clear (expY); mpz_clear (minExpX); mpz_clear (minExpY); delete [] exps; return result/ Lc (result); //normalize } mpz_t tmp; mpz_init (tmp); int k= 0; Variable alpha; for (CFIterator i= F; i.hasTerms(); i++) { if (i.coeff().inCoeffDomain() && hasFirstAlgVar (i.coeff(), alpha)) { mpz_set_si (expX, i.exp()); mpz_sub (expX, expX, A[1]); mpz_mul (expX, expX, inverseM[1]); mpz_submul (expX, A[0], inverseM[0]); mpz_set_si (expY, i.exp()); mpz_sub (expY, expY, A[1]); mpz_mul (expY, expY, inverseM[3]); mpz_submul (expY, A[0], inverseM[2]); if (k == 0) { mpz_set (minExpX, expX); mpz_set (minExpY, expY); k= 1; } else { if (mpz_cmp (minExpY, expY) > 0) mpz_set (minExpY, expY); if (mpz_cmp (minExpX, expX) > 0) mpz_set (minExpX, expX); } mpz_init_set (exps[count], expX); mpz_init_set (exps[count+1], expY); count += 2; continue; } CFIterator j= i.coeff(); if (k == 0) { mpz_set_si (expX, j.exp()); mpz_sub (expX, expX, A[0]); mpz_mul (expX, expX, inverseM[0]); mpz_set_si (tmp, i.exp()); mpz_sub (tmp, tmp, A[1]); mpz_addmul (expX, tmp, inverseM[1]); mpz_set_si (expY, j.exp()); mpz_sub (expY, expY, A[0]); mpz_mul (expY, expY, inverseM[2]); mpz_set_si (tmp, i.exp()); mpz_sub (tmp, tmp, A[1]); mpz_addmul (expY, tmp, inverseM[3]); mpz_set (minExpX, expX); mpz_set (minExpY, expY); mpz_init_set (exps[count], expX); mpz_init_set (exps[count+1], expY); count += 2; j++; k= 1; } for (; j.hasTerms(); j++) { mpz_set_si (expX, j.exp()); mpz_sub (expX, expX, A[0]); mpz_mul (expX, expX, inverseM[0]); mpz_set_si (tmp, i.exp()); mpz_sub (tmp, tmp, A[1]); mpz_addmul (expX, tmp, inverseM[1]); mpz_set_si (expY, j.exp()); mpz_sub (expY, expY, A[0]); mpz_mul (expY, expY, inverseM[2]); mpz_set_si (tmp, i.exp()); mpz_sub (tmp, tmp, A[1]); mpz_addmul (expY, tmp, inverseM[3]); mpz_init_set (exps[count], expX); mpz_init_set (exps[count+1], expY); count += 2; if (mpz_cmp (minExpY, expY) > 0) mpz_set (minExpY, expY); if (mpz_cmp (minExpX, expX) > 0) mpz_set (minExpX, expX); } } int mExpX= mpz_get_si (minExpX); int mExpY= mpz_get_si (minExpY); count= 0; for (CFIterator i= F; i.hasTerms(); i++) { if (i.coeff().inCoeffDomain() && hasFirstAlgVar (i.coeff(), alpha)) { result += i.coeff()*power (x, mpz_get_si (exps[count])-mExpX)* power (y, mpz_get_si (exps[count+1])-mExpY); count += 2; continue; } for (CFIterator j= i.coeff(); j.hasTerms(); j++) { result += j.coeff()*power (x, mpz_get_si (exps[count])-mExpX)* power (y, mpz_get_si (exps[count+1])-mExpY); count += 2; } } mpz_clear (expX); mpz_clear (expY); mpz_clear (minExpX); mpz_clear (minExpY); mpz_clear (tmp); delete [] exps; return result/Lc (result); //normalize } //assumes the input is a Newton polygon of a bivariate polynomial which is //primitive wrt. x and y, i.e. there is at least one point of the polygon lying //on the x-axis and one lying on the y-axis int* getRightSide (int** polygon, int sizeOfPolygon, int& sizeOfOutput) { int maxY= polygon [0][0]; int indexY= 0; for (int i= 1; i < sizeOfPolygon; i++) { if (maxY < polygon [i][0]) { maxY= polygon [i][0]; indexY= i; } else if (maxY == polygon [i][0]) { if (polygon [indexY][1] < polygon[i][1]) indexY= i; } if (maxY > polygon [i][0]) break; } int count= -1; for (int i= indexY; i < sizeOfPolygon; i++) { if (polygon[i][0] == 0) { count= i - indexY; break; } } int * result; int index= 0; if (count < 0) { result= new int [sizeOfPolygon - indexY]; sizeOfOutput= sizeOfPolygon - indexY; count= sizeOfPolygon - indexY - 1; result [0]= polygon[sizeOfPolygon - 1][0] - polygon [0] [0]; index= 1; } else { sizeOfOutput= count; result= new int [count]; } for (int i= indexY + count; i > indexY; i--, index++) result [index]= polygon [i - 1] [0] - polygon [i] [0]; return result; } bool irreducibilityTest (const CanonicalForm& F) { ASSERT (getNumVars (F) == 2, "expected bivariate polynomial"); ASSERT (getCharacteristic() == 0, "expected polynomial over integers or rationals"); int sizeOfNewtonPolygon; int ** newtonPolyg= newtonPolygon (F, sizeOfNewtonPolygon); if (sizeOfNewtonPolygon == 3) { bool check1= (newtonPolyg[0][0]==0 || newtonPolyg[1][0]==0 || newtonPolyg[2][0]==0); if (check1) { bool check2= (newtonPolyg[0][1]==0 || newtonPolyg[1][1]==0 || newtonPolyg[2][0]==0); if (check2) { bool isRat= isOn (SW_RATIONAL); if (isRat) Off (SW_RATIONAL); CanonicalForm tmp= gcd (newtonPolyg[0][0],newtonPolyg[0][1]); // maybe it's better to use plain intgcd tmp= gcd (tmp, newtonPolyg[1][0]); tmp= gcd (tmp, newtonPolyg[1][1]); tmp= gcd (tmp, newtonPolyg[2][0]); tmp= gcd (tmp, newtonPolyg[2][1]); if (isRat) On (SW_RATIONAL); for (int i= 0; i < sizeOfNewtonPolygon; i++) delete [] newtonPolyg [i]; delete [] newtonPolyg; return (tmp==1); } } } for (int i= 0; i < sizeOfNewtonPolygon; i++) delete [] newtonPolyg [i]; delete [] newtonPolyg; return false; } bool absIrredTest (const CanonicalForm& F) { ASSERT (getNumVars (F) == 2, "expected bivariate polynomial"); ASSERT (factorize (F).length() <= 2, " expected irreducible polynomial"); int sizeOfNewtonPolygon; int ** newtonPolyg= newtonPolygon (F, sizeOfNewtonPolygon); bool isRat= isOn (SW_RATIONAL); if (isRat) Off (SW_RATIONAL); int p=getCharacteristic(); int d=1; char bufGFName='Z'; bool GF= (CFFactory::gettype()==GaloisFieldDomain); if (GF) { d= getGFDegree(); bufGFName=gf_name; } setCharacteristic(0); CanonicalForm g= gcd (newtonPolyg[0][0], newtonPolyg[0][1]); //maybe it's better to use plain intgcd int i= 1; while (!g.isOne() && i < sizeOfNewtonPolygon) { g= gcd (g, newtonPolyg[i][0]); g= gcd (g, newtonPolyg[i][1]); i++; } bool result= g.isOne(); if (GF) setCharacteristic (p, d, bufGFName); else setCharacteristic(p); if (isRat) On (SW_RATIONAL); for (int i= 0; i < sizeOfNewtonPolygon; i++) delete [] newtonPolyg[i]; delete [] newtonPolyg; return result; } bool modularIrredTest (const CanonicalForm& F) { ASSERT (getNumVars (F) == 2, "expected bivariate polynomial"); ASSERT (factorize (F).length() <= 2, " expected irreducible polynomial"); bool isRat= isOn (SW_RATIONAL); if (isRat) Off (SW_RATIONAL); if (isRat) { ASSERT (bCommonDen (F).isOne(), "poly over Z expected"); } CanonicalForm Fp, N= maxNorm (F); int tdeg= totaldegree (F); int i= 0; //TODO: maybe it's better to choose the characteristic as large as possible // as factorization over large finite field will be faster //TODO: handle those cases where our factory primes are not enough //TODO: factorize coefficients corresponding to the vertices of the Newton // polygon and only try the obtained factors if (N < cf_getSmallPrime (cf_getNumSmallPrimes()-1)) { while (i < cf_getNumSmallPrimes() && N > cf_getSmallPrime(i)) { setCharacteristic (cf_getSmallPrime (i)); Fp= F.mapinto(); i++; if (totaldegree (Fp) == tdeg) { if (absIrredTest (Fp)) { CFFList factors= factorize (Fp); if (factors.length() == 2 && factors.getLast().exp() == 1) { if (isRat) On (SW_RATIONAL); setCharacteristic (0); return true; } } } setCharacteristic (0); } } else { while (i < cf_getNumPrimes() && N > cf_getPrime (i)) { setCharacteristic (cf_getPrime (i)); Fp= F.mapinto(); i++; if (totaldegree (Fp) == tdeg) { if (absIrredTest (Fp)) { CFFList factors= factorize (Fp); if (factors.length() == 2 && factors.getLast().exp() == 1) { if (isRat) On (SW_RATIONAL); setCharacteristic (0); return true; } } } setCharacteristic (0); } } if (isRat) On (SW_RATIONAL); return false; } bool modularIrredTestWithShift (const CanonicalForm& F) { ASSERT (getNumVars (F) == 2, "expected bivariate polynomial"); ASSERT (factorize (F).length() <= 2, " expected irreducible polynomial"); bool isRat= isOn (SW_RATIONAL); if (isRat) Off (SW_RATIONAL); if (isRat) { ASSERT (bCommonDen (F).isOne(), "poly over Z expected"); } Variable x= Variable (1); Variable y= Variable (2); CanonicalForm Fp; int tdeg= totaldegree (F); REvaluation E; setCharacteristic (2); Fp= F.mapinto(); E= REvaluation (1,2, FFRandom()); E.nextpoint(); Fp= Fp (x+E[1], x); Fp= Fp (y+E[2], y); if (tdeg == totaldegree (Fp)) { if (absIrredTest (Fp)) { CFFList factors= factorize (Fp); if (factors.length() == 2 && factors.getLast().exp() == 1) { if (isRat) On (SW_RATIONAL); setCharacteristic (0); return true; } } } E.nextpoint(); Fp= Fp (x+E[1], x); Fp= Fp (y+E[2], y); if (tdeg == totaldegree (Fp)) { if (absIrredTest (Fp)) { CFFList factors= factorize (Fp); if (factors.length() == 2 && factors.getLast().exp() == 1) { if (isRat) On (SW_RATIONAL); setCharacteristic (0); return true; } } } int i= 0; while (cf_getSmallPrime (i) < 102) { setCharacteristic (cf_getSmallPrime (i)); i++; E= REvaluation (1, 2, FFRandom()); for (int j= 0; j < 3; j++) { Fp= F.mapinto(); E.nextpoint(); Fp= Fp (x+E[1], x); Fp= Fp (y+E[2], y); if (tdeg == totaldegree (Fp)) { if (absIrredTest (Fp)) { CFFList factors= factorize (Fp); if (factors.length() == 2 && factors.getLast().exp() == 1) { if (isRat) On (SW_RATIONAL); setCharacteristic (0); return true; } } } } } setCharacteristic (0); if (isRat) On (SW_RATIONAL); return false; } singular-4.0.3+ds/factory/cfNewtonPolygon.h000066400000000000000000000130551266270727000207340ustar00rootroot00000000000000/*****************************************************************************\ * Computer Algebra System SINGULAR \*****************************************************************************/ /** @file cfNewtonPolygon.h * * This file provides functions to compute the Newton polygon of a bivariate * polynomial * * @author Martin Lee * **/ /*****************************************************************************/ #ifndef CF_NEWTON_POLYGON_H #define CF_NEWTON_POLYGON_H // #include "config.h" /// compute a polygon /// /// @return an integer n such that the first n entries of @a points are the /// vertices of the convex hull of @a points int polygon (int** points, ///< [in,out] an array of points in the plane int sizePoints///< [in] number of elements in @a points ); /// compute the Newton polygon of a bivariate polynomial /// /// @return an array of points in the plane which are the vertices of the Newton /// polygon of F int ** newtonPolygon (const CanonicalForm& F,///< [in] a bivariate polynomial int& sizeOfNewtonPoly ///< [in, out] size of the result ); /// compute the convex hull of the support of two bivariate polynomials /// /// @return an array of points in the plane which are the vertices of the convex /// hull of the support of F and G int ** newtonPolygon (const CanonicalForm& F,///< [in] a bivariate polynomial const CanonicalForm& G,///< [in] a bivariate polynomial int& sizeOfNewtonPoly ///< [in, out] size of the result ); /// check if @a point is inside a polygon described by points /// /// @return true if @a point is inside a polygon described by points bool isInPolygon (int ** points, ///< [in] an array of points in the ///< plane describing a polygon int sizePoints,///< [in] size of @a points int* point ///< [in] a point in the plane ); /// get the y-direction slopes of all edges with positive slope in y-direction /// of a convex polygon with at least one point of the polygon lying on the /// x-axis and one lying on the y-axis /// /// @return an array containing the slopes as described above int* getRightSide (int** polygon, ///<[in] vertices of a polygon int sizeOfPolygon, ///<[in] number of vertices int& sizeOfOutput ///<[in,out] size of the output ); /// computes the Newton polygon of F and checks if it satisfies the /// irreducibility criterion from S.Gao "Absolute irreducibility of polynomials /// via polytopes", Example 1 /// /// @return true if it satisfies the above criterion, false otherwise bool irreducibilityTest (const CanonicalForm& F ///<[in] a bivariate polynomial ); /// absolute irreducibility test as described in "Modular Las Vegas Algorithms /// for Polynomial Absolute Factorization" by C. Bertone, G. Cheze, A. Galligo /// /// @return true if F satisfies condition (C) from the above paper and thus /// is absolutely irreducible, false otherwise bool absIrredTest (const CanonicalForm& F ///< [in] a bivariate polynomial ///< irreducible over ground field ); /// modular absolute irreducibility test as described in "Modular Las Vegas /// Algorithms for Polynomial Absolute Factorization" by C. Bertone, G. Cheze, /// A. Galligo /// /// @return true if F is absolutely irreducible, false otherwise bool modularIrredTest (const CanonicalForm& F ///< [in] a bivariate polynomial ///< irreducible over Z ); /// modular absolute irreducibility test with shift as described in "Modular Las /// Vegas Algorithms for Polynomial Absolute Factorization" by C. Bertone, /// G. Cheze, A. Galligo /// /// @return true if F is absolutely irreducible, false otherwise bool modularIrredTestWithShift (const CanonicalForm& F ///< [in] a bivariate polynomial ///< irreducible over Z ); /// Algorithm 5 as described in Convex-Dense Bivariate Polynomial Factorization /// by Berthomieu, Lecerf void convexDense (int** points, ///< [in, out] a set of points in Z^2, returns ///< M (points)+A int sizePoints,///< [in] size of points mpz_t*& M, ///< [in,out] returns an invertible 2x2 matrix mpz_t*& A ///< [in,out] returns translation ); /// compress a bivariate poly /// /// @return @a compress returns a compressed bivariate poly /// @sa convexDense, decompress CanonicalForm compress (const CanonicalForm& F, ///< [in] compressed, i.e. F.level()==2, ///< bivariate poly mpz_t*& inverseM, ///< [in,out] returns the inverse of M, ///< if computeMA==true, M otherwise mpz_t*& A, ///< [in,out] returns translation bool computeMA= true ///< [in] whether to compute M and A ); /// decompress a bivariate poly /// /// @return @a decompress returns a decompressed bivariate poly /// @sa convexDense, decompress CanonicalForm decompress (const CanonicalForm& F,///< [in] compressed, i.e. F.level()<= 2, ///< uni- or bivariate poly const mpz_t* M, ///< [in] matrix M obtained from compress const mpz_t* A ///< [in] vector A obtained from compress ); #endif singular-4.0.3+ds/factory/cfSubResGcd.cc000066400000000000000000000131171266270727000200700ustar00rootroot00000000000000#include "config.h" #include "cf_defs.h" #include "cf_algorithm.h" #include "cfEzgcd.h" #include "cfGcdUtil.h" #include "templates/ftmpl_functions.h" #include "cf_factory.h" #include "cfUnivarGcd.h" CanonicalForm subResGCD_p( const CanonicalForm & f, const CanonicalForm & g ) { if (f.inCoeffDomain() || g.inCoeffDomain()) //zero case should be caught by gcd return 1; CanonicalForm pi, pi1; CanonicalForm C, Ci, Ci1, Hi, bi, pi2; bool bpure, ezgcdon= isOn (SW_USE_EZGCD_P); int delta = degree( f ) - degree( g ); if ( delta >= 0 ) { pi = f; pi1 = g; } else { pi = g; pi1 = f; delta = -delta; } if (pi.isUnivariate()) Ci= 1; else { if (!ezgcdon) On (SW_USE_EZGCD_P); Ci = content( pi ); if (!ezgcdon) Off (SW_USE_EZGCD_P); pi = pi / Ci; } if (pi1.isUnivariate()) Ci1= 1; else { if (!ezgcdon) On (SW_USE_EZGCD_P); Ci1 = content( pi1 ); if (!ezgcdon) Off (SW_USE_EZGCD_P); pi1 = pi1 / Ci1; } C = gcd( Ci, Ci1 ); int d= 0; if ( !( pi.isUnivariate() && pi1.isUnivariate() ) ) { if ( gcd_test_one( pi1, pi, true, d ) ) { C=abs(C); //out_cf("GCD:",C,"\n"); return C; } bpure = false; } else { bpure = isPurePoly(pi) && isPurePoly(pi1); #ifdef HAVE_FLINT if (bpure && (CFFactory::gettype() != GaloisFieldDomain)) return gcd_univar_flintp(pi,pi1)*C; #else #ifdef HAVE_NTL if (bpure && (CFFactory::gettype() != GaloisFieldDomain)) return gcd_univar_ntlp(pi, pi1 ) * C; #endif #endif } Variable v = f.mvar(); Hi = power( LC( pi1, v ), delta ); int maxNumVars= tmax (getNumVars (pi), getNumVars (pi1)); if (!(pi.isUnivariate() && pi1.isUnivariate())) { if (size (Hi)*size (pi)/(maxNumVars*3) > 500) //maybe this needs more tuning { On (SW_USE_FF_MOD_GCD); C *= gcd (pi, pi1); Off (SW_USE_FF_MOD_GCD); return C; } } if ( (delta+1) % 2 ) bi = 1; else bi = -1; CanonicalForm oldPi= pi, oldPi1= pi1, powHi; while ( degree( pi1, v ) > 0 ) { if (!(pi.isUnivariate() && pi1.isUnivariate())) { if (size (pi)/maxNumVars > 500 || size (pi1)/maxNumVars > 500) { On (SW_USE_FF_MOD_GCD); C *= gcd (oldPi, oldPi1); Off (SW_USE_FF_MOD_GCD); return C; } } pi2 = psr( pi, pi1, v ); pi2 = pi2 / bi; pi = pi1; pi1 = pi2; maxNumVars= tmax (getNumVars (pi), getNumVars (pi1)); if (!pi1.isUnivariate() && (size (pi1)/maxNumVars > 500)) { On (SW_USE_FF_MOD_GCD); C *= gcd (oldPi, oldPi1); Off (SW_USE_FF_MOD_GCD); return C; } if ( degree( pi1, v ) > 0 ) { delta = degree( pi, v ) - degree( pi1, v ); powHi= power (Hi, delta-1); if ( (delta+1) % 2 ) bi = LC( pi, v ) * powHi*Hi; else bi = -LC( pi, v ) * powHi*Hi; Hi = power( LC( pi1, v ), delta ) / powHi; if (!(pi.isUnivariate() && pi1.isUnivariate())) { if (size (Hi)*size (pi)/(maxNumVars*3) > 1500) //maybe this needs more tuning { On (SW_USE_FF_MOD_GCD); C *= gcd (oldPi, oldPi1); Off (SW_USE_FF_MOD_GCD); return C; } } } } if ( degree( pi1, v ) == 0 ) { C=abs(C); //out_cf("GCD:",C,"\n"); return C; } if (!pi.isUnivariate()) { if (!ezgcdon) On (SW_USE_EZGCD_P); Ci= gcd (LC (oldPi,v), LC (oldPi1,v)); pi /= LC (pi,v)/Ci; Ci= content (pi); pi /= Ci; if (!ezgcdon) Off (SW_USE_EZGCD_P); } if ( bpure ) pi /= pi.lc(); C=abs(C*pi); //out_cf("GCD:",C,"\n"); return C; } CanonicalForm subResGCD_0( const CanonicalForm & f, const CanonicalForm & g ) { CanonicalForm pi, pi1; CanonicalForm C, Ci, Ci1, Hi, bi, pi2; int delta = degree( f ) - degree( g ); if ( delta >= 0 ) { pi = f; pi1 = g; } else { pi = g; pi1 = f; delta = -delta; } Ci = content( pi ); Ci1 = content( pi1 ); pi1 = pi1 / Ci1; pi = pi / Ci; C = gcd( Ci, Ci1 ); int d= 0; if ( pi.isUnivariate() && pi1.isUnivariate() ) { #ifdef HAVE_FLINT if (isPurePoly(pi) && isPurePoly(pi1) ) return gcd_univar_flint0(pi, pi1 ) * C; #else #ifdef HAVE_NTL if (isPurePoly(pi) && isPurePoly(pi1) ) return gcd_univar_ntl0(pi, pi1 ) * C; #endif #endif #ifndef HAVE_NTL return gcd_poly_univar0( pi, pi1, true ) * C; #endif } else if ( gcd_test_one( pi1, pi, true, d ) ) return C; Variable v = f.mvar(); Hi = power( LC( pi1, v ), delta ); if ( (delta+1) % 2 ) bi = 1; else bi = -1; while ( degree( pi1, v ) > 0 ) { pi2 = psr( pi, pi1, v ); pi2 = pi2 / bi; pi = pi1; pi1 = pi2; if ( degree( pi1, v ) > 0 ) { delta = degree( pi, v ) - degree( pi1, v ); if ( (delta+1) % 2 ) bi = LC( pi, v ) * power( Hi, delta ); else bi = -LC( pi, v ) * power( Hi, delta ); Hi = power( LC( pi1, v ), delta ) / power( Hi, delta-1 ); } } if ( degree( pi1, v ) == 0 ) return C; else return C * pp( pi ); } singular-4.0.3+ds/factory/cfSubResGcd.h000066400000000000000000000011041266270727000177230ustar00rootroot00000000000000/** * @file cfSubResGcd.h * * subresultant pseudo remainder sequence GCD over finite fields and Z **/ #ifndef CF_SUB_RES_GCD_H #define CF_SUB_RES_GCD_H /// subresultant GCD over finite fields. /// In case things become too dense we switch to a modular algorithm CanonicalForm subResGCD_p( const CanonicalForm & f, const CanonicalForm & g ); /// subresultant GCD over Z. /// @note in contrast to subResGCD_p we do not switch to a modular algorithm /// in case things become too dense CanonicalForm subResGCD_0( const CanonicalForm & f, const CanonicalForm & g ); #endif singular-4.0.3+ds/factory/cfUnivarGcd.cc000066400000000000000000000200731266270727000201300ustar00rootroot00000000000000#include "config.h" #include "debug.h" #include "cf_algorithm.h" #include "templates/ftmpl_functions.h" #include "cf_primes.h" #include "cfGcdUtil.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif #ifdef HAVE_FLINT #include "FLINTconvert.h" #endif #ifdef HAVE_NTL #ifndef HAVE_FLINT CanonicalForm gcd_univar_ntl0( const CanonicalForm & F, const CanonicalForm & G ) { ZZX F1=convertFacCF2NTLZZX(F); ZZX G1=convertFacCF2NTLZZX(G); ZZX R=GCD(F1,G1); return convertNTLZZX2CF(R,F.mvar()); } CanonicalForm gcd_univar_ntlp( const CanonicalForm & F, const CanonicalForm & G ) { if (fac_NTL_char!=getCharacteristic()) { fac_NTL_char=getCharacteristic(); zz_p::init(getCharacteristic()); } zz_pX F1=convertFacCF2NTLzzpX(F); zz_pX G1=convertFacCF2NTLzzpX(G); zz_pX R=GCD(F1,G1); return convertNTLzzpX2CF(R,F.mvar()); } #endif #endif #ifdef HAVE_FLINT CanonicalForm gcd_univar_flintp (const CanonicalForm& F, const CanonicalForm& G) { nmod_poly_t F1, G1; convertFacCF2nmod_poly_t (F1, F); convertFacCF2nmod_poly_t (G1, G); nmod_poly_gcd (F1, F1, G1); CanonicalForm result= convertnmod_poly_t2FacCF (F1, F.mvar()); nmod_poly_clear (F1); nmod_poly_clear (G1); return result; } CanonicalForm gcd_univar_flint0( const CanonicalForm & F, const CanonicalForm & G ) { fmpz_poly_t F1, G1; convertFacCF2Fmpz_poly_t(F1, F); convertFacCF2Fmpz_poly_t(G1, G); fmpz_poly_gcd (F1, F1, G1); CanonicalForm result= convertFmpz_poly_t2FacCF (F1, F.mvar()); fmpz_poly_clear (F1); fmpz_poly_clear (G1); return result; } #endif #ifndef HAVE_NTL CanonicalForm gcd_poly_univar0( const CanonicalForm & F, const CanonicalForm & G, bool primitive ) { CanonicalForm f, g, c, cg, cl, BB, B, M, q, Dp, newD, D, newq; int p, i; if ( primitive ) { f = F; g = G; c = 1; } else { CanonicalForm cF = content( F ), cG = content( G ); f = F / cF; g = G / cG; c = bgcd( cF, cG ); } cg = gcd( f.lc(), g.lc() ); cl = ( f.lc() / cg ) * g.lc(); // B = 2 * cg * tmin( // maxnorm(f)*power(CanonicalForm(2),f.degree())*isqrt(f.degree()+1), // maxnorm(g)*power(CanonicalForm(2),g.degree())*isqrt(g.degree()+1) // )+1; M = tmin( maxNorm(f), maxNorm(g) ); BB = power(CanonicalForm(2),tmin(f.degree(),g.degree()))*M; q = 0; i = cf_getNumSmallPrimes() - 1; while ( true ) { B = BB; while ( i >= 0 && q < B ) { p = cf_getSmallPrime( i ); i--; while ( i >= 0 && mod( cl, p ) == 0 ) { p = cf_getSmallPrime( i ); i--; } setCharacteristic( p ); Dp = gcd( mapinto( f ), mapinto( g ) ); Dp = ( Dp / Dp.lc() ) * mapinto( cg ); setCharacteristic( 0 ); if ( Dp.degree() == 0 ) return c; if ( q.isZero() ) { D = mapinto( Dp ); q = p; B = power(CanonicalForm(2),D.degree())*M+1; } else { if ( Dp.degree() == D.degree() ) { chineseRemainder( D, q, mapinto( Dp ), p, newD, newq ); q = newq; D = newD; } else if ( Dp.degree() < D.degree() ) { // all previous p's are bad primes q = p; D = mapinto( Dp ); B = power(CanonicalForm(2),D.degree())*M+1; } // else p is a bad prime } } if ( i >= 0 ) { // now balance D mod q D = pp( balance_p( D, q ) ); if ( fdivides( D, f ) && fdivides( D, g ) ) return D * c; else q = 0; } else return gcd_poly( F, G ); DEBOUTLN( cerr, "another try ..." ); } } #endif /** CanonicalForm extgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b ) * * extgcd() - returns polynomial extended gcd of f and g. * * Returns gcd(f, g) and a and b sucht that f*a+g*b=gcd(f, g). * The gcd is calculated using an extended euclidean polynomial * remainder sequence, so f and g should be polynomials over an * euclidean domain. Normalizes result. * * Note: be sure that f and g have the same level! * **/ CanonicalForm extgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b ) { if (f.isZero()) { a= 0; b= 1; return g; } else if (g.isZero()) { a= 1; b= 0; return f; } #ifdef HAVE_NTL #ifdef HAVE_FLINT if (( getCharacteristic() > 0 ) && (CFFactory::gettype() != GaloisFieldDomain) && (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g)) { nmod_poly_t F1, G1, A, B, R; convertFacCF2nmod_poly_t (F1, f); convertFacCF2nmod_poly_t (G1, g); nmod_poly_init (R, getCharacteristic()); nmod_poly_init (A, getCharacteristic()); nmod_poly_init (B, getCharacteristic()); nmod_poly_xgcd (R, A, B, F1, G1); a= convertnmod_poly_t2FacCF (A, f.mvar()); b= convertnmod_poly_t2FacCF (B, f.mvar()); CanonicalForm r= convertnmod_poly_t2FacCF (R, f.mvar()); nmod_poly_clear (F1); nmod_poly_clear (G1); nmod_poly_clear (A); nmod_poly_clear (B); nmod_poly_clear (R); return r; } #else if (( getCharacteristic() > 0 ) && (CFFactory::gettype() != GaloisFieldDomain) && (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g)) { if (fac_NTL_char!=getCharacteristic()) { fac_NTL_char=getCharacteristic(); zz_p::init(getCharacteristic()); } zz_pX F1=convertFacCF2NTLzzpX(f); zz_pX G1=convertFacCF2NTLzzpX(g); zz_pX R; zz_pX A,B; XGCD(R,A,B,F1,G1); a=convertNTLzzpX2CF(A,f.mvar()); b=convertNTLzzpX2CF(B,f.mvar()); return convertNTLzzpX2CF(R,f.mvar()); } #endif #ifdef HAVE_FLINT if (( getCharacteristic() ==0) && (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g)) { fmpq_poly_t F1, G1; convertFacCF2Fmpq_poly_t (F1, f); convertFacCF2Fmpq_poly_t (G1, g); fmpq_poly_t R, A, B; fmpq_poly_init (R); fmpq_poly_init (A); fmpq_poly_init (B); fmpq_poly_xgcd (R, A, B, F1, G1); a= convertFmpq_poly_t2FacCF (A, f.mvar()); b= convertFmpq_poly_t2FacCF (B, f.mvar()); CanonicalForm r= convertFmpq_poly_t2FacCF (R, f.mvar()); fmpq_poly_clear (F1); fmpq_poly_clear (G1); fmpq_poly_clear (A); fmpq_poly_clear (B); fmpq_poly_clear (R); return r; } #else if (( getCharacteristic() ==0) && (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g)) { CanonicalForm fc=bCommonDen(f); CanonicalForm gc=bCommonDen(g); ZZX F1=convertFacCF2NTLZZX(f*fc); ZZX G1=convertFacCF2NTLZZX(g*gc); ZZX R=GCD(F1,G1); CanonicalForm r=convertNTLZZX2CF(R,f.mvar()); ZZ RR; ZZX A,B; if (r.inCoeffDomain()) { XGCD(RR,A,B,F1,G1,1); CanonicalForm rr=convertZZ2CF(RR); if(!rr.isZero()) { a=convertNTLZZX2CF(A,f.mvar())*fc/rr; b=convertNTLZZX2CF(B,f.mvar())*gc/rr; return CanonicalForm(1); } else { F1 /= R; G1 /= R; XGCD (RR, A,B,F1,G1,1); rr=convertZZ2CF(RR); a=convertNTLZZX2CF(A,f.mvar())*(fc/rr); b=convertNTLZZX2CF(B,f.mvar())*(gc/rr); } } else { XGCD(RR,A,B,F1,G1,1); CanonicalForm rr=convertZZ2CF(RR); if (!rr.isZero()) { a=convertNTLZZX2CF(A,f.mvar())*fc; b=convertNTLZZX2CF(B,f.mvar())*gc; } else { F1 /= R; G1 /= R; XGCD (RR, A,B,F1,G1,1); rr=convertZZ2CF(RR); a=convertNTLZZX2CF(A,f.mvar())*(fc/rr); b=convertNTLZZX2CF(B,f.mvar())*(gc/rr); } return r; } } #endif #endif // may contain bug in the co-factors, see track 107 CanonicalForm contf = content( f ); CanonicalForm contg = content( g ); CanonicalForm p0 = f / contf, p1 = g / contg; CanonicalForm f0 = 1, f1 = 0, g0 = 0, g1 = 1, q, r; while ( ! p1.isZero() ) { divrem( p0, p1, q, r ); p0 = p1; p1 = r; r = g0 - g1 * q; g0 = g1; g1 = r; r = f0 - f1 * q; f0 = f1; f1 = r; } CanonicalForm contp0 = content( p0 ); a = f0 / ( contf * contp0 ); b = g0 / ( contg * contp0 ); p0 /= contp0; if ( p0.sign() < 0 ) { p0 = -p0; a = -a; b = -b; } return p0; } singular-4.0.3+ds/factory/cfUnivarGcd.h000066400000000000000000000020071266270727000177670ustar00rootroot00000000000000/** * @file cfUnivarGcd.h * * univariate Gcd over finite fields and Z, extended GCD over finite fields * and Q * * @note if NTL or FLINT are available they are used to compute the (ext)Gcd **/ #ifndef CF_UNIVAR_GCD_H #define CF_UNIVAR_GCD_H #ifdef HAVE_NTL #include #include "NTLconvert.h" bool isPurePoly(const CanonicalForm & ); #ifndef HAVE_FLINT CanonicalForm gcd_univar_ntl0( const CanonicalForm &, const CanonicalForm & ); CanonicalForm gcd_univar_ntlp( const CanonicalForm &, const CanonicalForm & ); #endif #endif #ifdef HAVE_FLINT #include "FLINTconvert.h" CanonicalForm gcd_univar_flint0 (const CanonicalForm &, const CanonicalForm &); CanonicalForm gcd_univar_flintp (const CanonicalForm &, const CanonicalForm &); #endif #ifndef HAVE_NTL CanonicalForm gcd_poly_univar0( const CanonicalForm & F, const CanonicalForm & G, bool primitive ); #endif /*BEGINPUBLIC*/ CanonicalForm extgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b ); /*ENDPUBLIC*/ #endif singular-4.0.3+ds/factory/cf_algorithm.cc000066400000000000000000000375501266270727000204030ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * * cf_algorithm.cc - simple mathematical algorithms. * * Hierarchy: mathematical algorithms on canonical forms * * Developers note: * ---------------- * A "mathematical" algorithm is an algorithm which calculates * some mathematical function in contrast to a "structural" * algorithm which gives structural information on polynomials. * * Compare these functions to the functions in `cf_ops.cc', which * are structural algorithms. * **/ #include "config.h" #include "cf_assert.h" #include "cf_factory.h" #include "cf_defs.h" #include "canonicalform.h" #include "cf_algorithm.h" #include "variable.h" #include "cf_iter.h" #include "templates/ftmpl_functions.h" #include "cfGcdAlgExt.h" void out_cf(const char *s1,const CanonicalForm &f,const char *s2); /** CanonicalForm psr ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) * * * psr() - return pseudo remainder of `f' and `g' with respect * to `x'. * * `g' must not equal zero. * * For f and g in R[x], R an arbitrary ring, g != 0, there is a * representation * * LC(g)^s*f = g*q + r * * with r = 0 or deg(r) < deg(g) and s = 0 if f = 0 or * s = max( 0, deg(f)-deg(g)+1 ) otherwise. * r = psr(f, g) and q = psq(f, g) are called "pseudo remainder" * and "pseudo quotient", resp. They are uniquely determined if * LC(g) is not a zero divisor in R. * * See H.-J. Reiffen/G. Scheja/U. Vetter - "Algebra", 2nd ed., * par. 15, for a reference. * * Type info: * ---------- * f, g: Current * x: Polynomial * * Polynomials over prime power domains are admissible if * lc(LC(`g',`x')) is not a zero divisor. This is a slightly * stronger precondition than mathematically necessary since * pseudo remainder and quotient are well-defined if LC(`g',`x') * is not a zero divisor. * * For example, psr(y^2, (13*x+1)*y) is well-defined in * (Z/13^2[x])[y] since (13*x+1) is not a zero divisor. But * calculating it with Factory would fail since 13 is a zero * divisor in Z/13^2. * * Due to this inconsistency with mathematical notion, we decided * not to declare type `CurrentPP' for `f' and `g'. * * Developers note: * ---------------- * This is not an optimal implementation. Better would have been * an implementation in `InternalPoly' avoiding the * exponentiation of the leading coefficient of `g'. In contrast * to `psq()' and `psqr()' it definitely seems worth to implement * the pseudo remainder on the internal level. * * @sa psq(), psqr() **/ CanonicalForm #if 0 psr ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) { ASSERT( x.level() > 0, "type error: polynomial variable expected" ); ASSERT( ! g.isZero(), "math error: division by zero" ); // swap variables such that x's level is larger or equal // than both f's and g's levels. Variable X = tmax( tmax( f.mvar(), g.mvar() ), x ); CanonicalForm F = swapvar( f, x, X ); CanonicalForm G = swapvar( g, x, X ); // now, we have to calculate the pseudo remainder of F and G // w.r.t. X int fDegree = degree( F, X ); int gDegree = degree( G, X ); if ( (fDegree < 0) || (fDegree < gDegree) ) return f; else { CanonicalForm xresult = (power( LC( G, X ), fDegree-gDegree+1 ) * F) ; CanonicalForm result = xresult -(xresult/G)*G; return swapvar( result, x, X ); } } #else psr ( const CanonicalForm &rr, const CanonicalForm &vv, const Variable & x ) { CanonicalForm r=rr, v=vv, l, test, lu, lv, t, retvalue; int dr, dv, d,n=0; dr = degree( r, x ); if (dr>0) { dv = degree( v, x ); if (dv <= dr) {l=LC(v,x); v = v -l*power(x,dv);} else { l = 1; } d= dr-dv+1; //out_cf("psr(",rr," "); //out_cf("",vv," "); //printf(" var=%d\n",x.level()); while ( ( dv <= dr ) && ( !r.isZero()) ) { test = power(x,dr-dv)*v*LC(r,x); if ( dr == 0 ) { r= CanonicalForm(0); } else { r= r - LC(r,x)*power(x,dr); } r= l*r -test; dr= degree(r,x); n+=1; } r= power(l, d-n)*r; } return r; } #endif /** CanonicalForm psq ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) * * * psq() - return pseudo quotient of `f' and `g' with respect * to `x'. * * `g' must not equal zero. * * Type info: * ---------- * f, g: Current * x: Polynomial * * Developers note: * ---------------- * This is not an optimal implementation. Better would have been * an implementation in `InternalPoly' avoiding the * exponentiation of the leading coefficient of `g'. It seemed * not worth to do so. * * @sa psr(), psqr() * **/ CanonicalForm psq ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) { ASSERT( x.level() > 0, "type error: polynomial variable expected" ); ASSERT( ! g.isZero(), "math error: division by zero" ); // swap variables such that x's level is larger or equal // than both f's and g's levels. Variable X = tmax( tmax( f.mvar(), g.mvar() ), x ); CanonicalForm F = swapvar( f, x, X ); CanonicalForm G = swapvar( g, x, X ); // now, we have to calculate the pseudo remainder of F and G // w.r.t. X int fDegree = degree( F, X ); int gDegree = degree( G, X ); if ( fDegree < 0 || fDegree < gDegree ) return 0; else { CanonicalForm result = (power( LC( G, X ), fDegree-gDegree+1 ) * F) / G; return swapvar( result, x, X ); } } /** void psqr ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r, const Variable & x ) * * * psqr() - calculate pseudo quotient and remainder of `f' and * `g' with respect to `x'. * * Returns the pseudo quotient of `f' and `g' in `q', the pseudo * remainder in `r'. `g' must not equal zero. * * See `psr()' for more detailed information. * * Type info: * ---------- * f, g: Current * q, r: Anything * x: Polynomial * * Developers note: * ---------------- * This is not an optimal implementation. Better would have been * an implementation in `InternalPoly' avoiding the * exponentiation of the leading coefficient of `g'. It seemed * not worth to do so. * * @sa psr(), psq() * **/ void psqr ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r, const Variable& x ) { ASSERT( x.level() > 0, "type error: polynomial variable expected" ); ASSERT( ! g.isZero(), "math error: division by zero" ); // swap variables such that x's level is larger or equal // than both f's and g's levels. Variable X = tmax( tmax( f.mvar(), g.mvar() ), x ); CanonicalForm F = swapvar( f, x, X ); CanonicalForm G = swapvar( g, x, X ); // now, we have to calculate the pseudo remainder of F and G // w.r.t. X int fDegree = degree( F, X ); int gDegree = degree( G, X ); if ( fDegree < 0 || fDegree < gDegree ) { q = 0; r = f; } else { divrem( power( LC( G, X ), fDegree-gDegree+1 ) * F, G, q, r ); q = swapvar( q, x, X ); r = swapvar( r, x, X ); } } /** static CanonicalForm internalBCommonDen ( const CanonicalForm & f ) * * * internalBCommonDen() - recursively calculate multivariate * common denominator of coefficients of `f'. * * Used by: bCommonDen() * * Type info: * ---------- * f: Poly( Q ) * Switches: isOff( SW_RATIONAL ) * **/ static CanonicalForm internalBCommonDen ( const CanonicalForm & f ) { if ( f.inBaseDomain() ) return f.den(); else { CanonicalForm result = 1; for ( CFIterator i = f; i.hasTerms(); i++ ) result = blcm( result, internalBCommonDen( i.coeff() ) ); return result; } } /** CanonicalForm bCommonDen ( const CanonicalForm & f ) * * * bCommonDen() - calculate multivariate common denominator of * coefficients of `f'. * * The common denominator is calculated with respect to all * coefficients of `f' which are in a base domain. In other * words, common_den( `f' ) * `f' is guaranteed to have integer * coefficients only. The common denominator of zero is one. * * Returns something non-trivial iff the current domain is Q. * * Type info: * ---------- * f: CurrentPP * **/ CanonicalForm bCommonDen ( const CanonicalForm & f ) { if ( getCharacteristic() == 0 && isOn( SW_RATIONAL ) ) { // otherwise `bgcd()' returns one Off( SW_RATIONAL ); CanonicalForm result = internalBCommonDen( f ); On( SW_RATIONAL ); return result; } else return CanonicalForm( 1 ); } /** bool fdivides ( const CanonicalForm & f, const CanonicalForm & g ) * * * fdivides() - check whether `f' divides `g'. * * Returns true iff `f' divides `g'. Uses some extra heuristic * to avoid polynomial division. Without the heuristic, the test * essentialy looks like `divremt(g, f, q, r) && r.isZero()'. * * Type info: * ---------- * f, g: Current * * Elements from prime power domains (or polynomials over such * domains) are admissible if `f' (or lc(`f'), resp.) is not a * zero divisor. This is a slightly stronger precondition than * mathematically necessary since divisibility is a well-defined * notion in arbitrary rings. Hence, we decided not to declare * the weaker type `CurrentPP'. * * Developers note: * ---------------- * One may consider the the test `fdivides( f.LC(), g.LC() )' in * the main `if'-test superfluous since `divremt()' in the * `if'-body repeats the test. However, `divremt()' does not use * any heuristic to do so. * * It seems not reasonable to call `fdivides()' from `divremt()' * to check divisibility of leading coefficients. `fdivides()' is * on a relatively high level compared to `divremt()'. * **/ bool fdivides ( const CanonicalForm & f, const CanonicalForm & g ) { // trivial cases if ( g.isZero() ) return true; else if ( f.isZero() ) return false; if ( (f.inCoeffDomain() || g.inCoeffDomain()) && ((getCharacteristic() == 0 && isOn( SW_RATIONAL )) || (getCharacteristic() > 0) )) { // if we are in a field all elements not equal to zero are units if ( f.inCoeffDomain() ) return true; else // g.inCoeffDomain() return false; } // we may assume now that both levels either equal LEVELBASE // or are greater zero int fLevel = f.level(); int gLevel = g.level(); if ( (gLevel > 0) && (fLevel == gLevel) ) // f and g are polynomials in the same main variable if ( degree( f ) <= degree( g ) && fdivides( f.tailcoeff(), g.tailcoeff() ) && fdivides( f.LC(), g.LC() ) ) { CanonicalForm q, r; return divremt( g, f, q, r ) && r.isZero(); } else return false; else if ( gLevel < fLevel ) // g is a coefficient w.r.t. f return false; else { // either f is a coefficient w.r.t. polynomial g or both // f and g are from a base domain (should be Z or Z/p^n, // then) CanonicalForm q, r; return divremt( g, f, q, r ) && r.isZero(); } } /// same as fdivides if true returns quotient quot of g by f otherwise quot == 0 bool fdivides ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm& quot ) { quot= 0; // trivial cases if ( g.isZero() ) return true; else if ( f.isZero() ) return false; if ( (f.inCoeffDomain() || g.inCoeffDomain()) && ((getCharacteristic() == 0 && isOn( SW_RATIONAL )) || (getCharacteristic() > 0) )) { // if we are in a field all elements not equal to zero are units if ( f.inCoeffDomain() ) { quot= g/f; return true; } else // g.inCoeffDomain() return false; } // we may assume now that both levels either equal LEVELBASE // or are greater zero int fLevel = f.level(); int gLevel = g.level(); if ( (gLevel > 0) && (fLevel == gLevel) ) // f and g are polynomials in the same main variable if ( degree( f ) <= degree( g ) && fdivides( f.tailcoeff(), g.tailcoeff() ) && fdivides( f.LC(), g.LC() ) ) { CanonicalForm q, r; if (divremt( g, f, q, r ) && r.isZero()) { quot= q; return true; } else return false; } else return false; else if ( gLevel < fLevel ) // g is a coefficient w.r.t. f return false; else { // either f is a coefficient w.r.t. polynomial g or both // f and g are from a base domain (should be Z or Z/p^n, // then) CanonicalForm q, r; if (divremt( g, f, q, r ) && r.isZero()) { quot= q; return true; } else return false; } } /// same as fdivides but handles zero divisors in Z_p[t]/(f)[x1,...,xn] for reducible f bool tryFdivides ( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm& M, bool& fail ) { fail= false; // trivial cases if ( g.isZero() ) return true; else if ( f.isZero() ) return false; if (f.inCoeffDomain() || g.inCoeffDomain()) { // if we are in a field all elements not equal to zero are units if ( f.inCoeffDomain() ) { CanonicalForm inv; tryInvert (f, M, inv, fail); return !fail; } else { return false; } } // we may assume now that both levels either equal LEVELBASE // or are greater zero int fLevel = f.level(); int gLevel = g.level(); if ( (gLevel > 0) && (fLevel == gLevel) ) { if (degree( f ) > degree( g )) return false; bool dividestail= tryFdivides (f.tailcoeff(), g.tailcoeff(), M, fail); if (fail || !dividestail) return false; bool dividesLC= tryFdivides (f.LC(),g.LC(), M, fail); if (fail || !dividesLC) return false; CanonicalForm q,r; bool divides= tryDivremt (g, f, q, r, M, fail); if (fail || !divides) return false; return r.isZero(); } else if ( gLevel < fLevel ) { // g is a coefficient w.r.t. f return false; } else { // either f is a coefficient w.r.t. polynomial g or both // f and g are from a base domain (should be Z or Z/p^n, // then) CanonicalForm q, r; bool divides= tryDivremt (g, f, q, r, M, fail); if (fail || !divides) return false; return r.isZero(); } } /** CanonicalForm maxNorm ( const CanonicalForm & f ) * * * maxNorm() - return maximum norm of `f'. * * That is, the base coefficient of `f' with the largest absolute * value. * * Valid for arbitrary polynomials over arbitrary domains, but * most useful for multivariate polynomials over Z. * * Type info: * ---------- * f: CurrentPP * **/ CanonicalForm maxNorm ( const CanonicalForm & f ) { if ( f.inBaseDomain() ) return abs( f ); else { CanonicalForm result = 0; for ( CFIterator i = f; i.hasTerms(); i++ ) { CanonicalForm coeffMaxNorm = maxNorm( i.coeff() ); if ( coeffMaxNorm > result ) result = coeffMaxNorm; } return result; } } /** CanonicalForm euclideanNorm ( const CanonicalForm & f ) * * * euclideanNorm() - return Euclidean norm of `f'. * * Returns the largest integer smaller or equal norm(`f') = * sqrt(sum( `f'[i]^2 )). * * Type info: * ---------- * f: UVPoly( Z ) * **/ CanonicalForm euclideanNorm ( const CanonicalForm & f ) { ASSERT( (f.inBaseDomain() || f.isUnivariate()) && f.LC().inZ(), "type error: univariate poly over Z expected" ); CanonicalForm result = 0; for ( CFIterator i = f; i.hasTerms(); i++ ) { CanonicalForm coeff = i.coeff(); result += coeff*coeff; } return sqrt( result ); } singular-4.0.3+ds/factory/cf_algorithm.h000066400000000000000000000077321266270727000202440ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_algorithm.h * declarations of higher level algorithms. * * Header file corresponds to: cf_algorithm.cc, cf_chinese.cc, * cf_factor.cc, cf_linsys.cc, cf_resultant.cc * * Hierarchy: mathematical algorithms on canonical forms * * Developers note: * ---------------- * This header file collects declarations of most of the * functions in Factory which implement higher level algorithms * on canonical forms (factorization, gcd, etc.) and declarations * of some low level mathematical functions, too (absolute value, * euclidean norm, etc.). * **/ #ifndef INCL_CF_ALGORITHM_H #define INCL_CF_ALGORITHM_H // #include "config.h" #include "canonicalform.h" #include "variable.h" /*BEGINPUBLIC*/ //{{{ function declarations from cf_algorithm.cc CanonicalForm psr ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ); CanonicalForm psq ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ); void psqr ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r, const Variable & x ); CanonicalForm bCommonDen ( const CanonicalForm & f ); bool fdivides ( const CanonicalForm & f, const CanonicalForm & g ); bool fdivides ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm& quot ); bool tryFdivides ( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm& M, bool& fail ); CanonicalForm maxNorm ( const CanonicalForm & f ); CanonicalForm euclideanNorm ( const CanonicalForm & f ); //}}} //{{{ function declarations from cf_chinese.cc void chineseRemainder ( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew ); void chineseRemainder ( const CFArray & x, const CFArray & q, CanonicalForm & xnew, CanonicalForm & qnew ); void chineseRemainderCached(CFArray &a, CFArray &n, CanonicalForm &xnew, CanonicalForm &prod, CFArray &inv); CanonicalForm Farey ( const CanonicalForm & f, const CanonicalForm & q ); //}}} //{{{ function declarations from cf_factor.cc extern int singular_homog_flag; bool isPurePoly(const CanonicalForm & f); bool isPurePoly_m(const CanonicalForm & f); CFFList factorize ( const CanonicalForm & f, bool issqrfree = false ); CFFList factorize ( const CanonicalForm & f, const Variable & alpha ); CFFList sqrFree ( const CanonicalForm & f, bool sort= false ); CanonicalForm homogenize( const CanonicalForm & f, const Variable & x); CanonicalForm homogenize( const CanonicalForm & f, const Variable & x, const Variable & v1, const Variable & v2); Variable get_max_degree_Variable(const CanonicalForm & f); CFList get_Terms( const CanonicalForm & f ); void getTerms( const CanonicalForm & f, const CanonicalForm & t, CFList & result ); //}}} //{{{ function declarations from cf_linsys.cc bool linearSystemSolve ( CFMatrix & M ); CanonicalForm determinant ( const CFMatrix & M, int n ); //}}} //{{{ function declarations from cf_resultant.cc CFArray subResChain ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ); CanonicalForm resultant ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ); //}}} /** inline CanonicalForm abs ( const CanonicalForm & f ) * * abs() - return absolute value of `f'. * * The absolute value is defined in terms of the function * `sign()'. If it reports negative sign for `f' than -`f' is * returned, otherwise `f'. * * This behaviour is most useful for integers and rationals. But * it may be used to sign-normalize the leading coefficient of * arbitrary polynomials, too. * * Type info: * ---------- * f: CurrentPP * **/ inline CanonicalForm abs ( const CanonicalForm & f ) { // it is not only more general to use `sign()' instead of a // direct comparison `f < 0', it is faster, too if ( sign( f ) < 0 ) return -f; else return f; } //}}} /*ENDPUBLIC*/ #endif /* ! INCL_CF_ALGORITHM_H */ singular-4.0.3+ds/factory/cf_assert.h000066400000000000000000000115671266270727000175600ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C -*- */ /** * @file cf_assert.h * * assertions for Factory * * @note needs --enable-assertions at configure **/ /* This is for compatibility with standard cf_assert.h */ #if defined (SING_NDEBUG) && ! defined (NOASSERT) #define NOASSERT #endif /* It should be possible to include this file multiple times for different */ /* settings of NOASSERT */ /* {{{ undefines */ #undef __ASSERT #undef __ASSERT1 #undef STICKYASSERT #undef STICKYASSERT1 #undef ASSERT #undef ASSERT1 #undef __WARN #undef STICKYWARN #undef WARN #undef PVIRT_VOID #undef PVIRT_INTCF #undef PVIRT_BOOL #undef PVIRT_INT #undef PVIRT_CHARCC /* }}} */ #ifdef __cplusplus #ifndef NOSTREAMIO #ifdef HAVE_CSTDIO #include #include #else extern "C" { #include #include } #endif #else #include #include #endif #endif /* {{{ permanent macro definitions */ #ifndef __GNUC__ #define __ASSERT(expression, message, file, line) \ (fprintf( stderr, "error: " message "\n%s:%u: failed assertion `%s'\n", \ file, line, expression ), abort(), 0 ) #define __ASSERT1(expression, message, parameter1, file, line) \ (fprintf( stderr, "error: " message "\n%s:%u: failed assertion `%s'\n", \ parameter1, file, line, expression ), abort(), 0 ) #define STICKYASSERT(expression, message) \ ((void)((expression) ? 0 : __ASSERT(#expression, message, __FILE__, __LINE__))) #define STICKYASSERT1(expression, message, parameter1) \ ((void)((expression) ? 0 : __ASSERT1(#expression, message, parameter1, __FILE__, __LINE__))) #define __WARN(expression, message, file, line) \ (fprintf( stderr, "warning: " message "\n%s:%u: failed assertion `%s'\n", \ file, line, expression ), 0 ) #define STICKYWARN(expression, message) \ ((void)((expression) ? 0 : __WARN(#expression, message, __FILE__, __LINE__))) #else /* __GNUCC__ */ /* use preprocessor macro __PRETTY_FUNCTION__ for more informative output */ #define __ASSERT(expression, message, file, line, function) \ (fprintf( stderr, "error: " message "\n%s:%u: In function `%s':\nfailed assertion `%s'\n", \ file, line, function, expression ), abort(), 0 ) #define __ASSERT1(expression, message, parameter1, file, line, function) \ (fprintf( stderr, "error: " message "\n%s:%u: In function `%s':\nfailed assertion `%s'\n", \ parameter1, file, line, function, expression ), abort(), 0 ) #define STICKYASSERT(expression, message) \ ((void)((expression) ? 0 : __ASSERT(#expression, message, __FILE__, __LINE__, __PRETTY_FUNCTION__))) #define STICKYASSERT1(expression, message, parameter1) \ ((void)((expression) ? 0 : __ASSERT1(#expression, message, parameter1, __FILE__, __LINE__, __PRETTY_FUNCTION__))) #define __WARN(expression, message, file, line, function) \ (fprintf( stderr, "warning: " message "\n%s:%u: In function `%s':\nfailed assertion `%s'\n", \ file, line, function, expression ), 0 ) #define STICKYWARN(expression, message) \ ((void)((expression) ? 0 : __WARN(#expression, message, __FILE__, __LINE__, __PRETTY_FUNCTION__))) #endif /* __GNUCC__ */ /* }}} */ /* {{{ macro definitions dependent on NOASSERT */ #ifndef NOASSERT #ifndef __GNUC__ #define ASSERT(expression, message) \ ((void)((expression) ? 0 : __ASSERT(#expression, message, __FILE__, __LINE__))) #define ASSERT1(expression, message, parameter1) \ ((void)((expression) ? 0 : __ASSERT1(#expression, message, parameter1, __FILE__, __LINE__))) #define WARN(expression, message) \ ((void)((expression) ? 0 : __WARN(#expression, message, __FILE__, __LINE__))) #else /* __GNUCC__ */ /* use preprocessor macro __PRETTY_FUNCTION__ for more informative output */ #define ASSERT(expression, message) \ ((void)((expression) ? 0 : __ASSERT(#expression, message, __FILE__, __LINE__, __PRETTY_FUNCTION__))) #define ASSERT1(expression, message, parameter1) \ ((void)((expression) ? 0 : __ASSERT1(#expression, message, parameter1, __FILE__, __LINE__, __PRETTY_FUNCTION__))) #define WARN(expression, message) \ ((void)((expression) ? 0 : __WARN(#expression, message, __FILE__, __LINE__, __PRETTY_FUNCTION__))) #endif /* __GNUCC__ */ #define PVIRT_VOID(msg) \ { fprintf( stderr, "pure method( " msg " ) called\n" ); abort(); } #define PVIRT_INTCF(msg) \ { fprintf( stderr, "pure method( " msg " ) called\n" ); abort(); return 0; } #define PVIRT_BOOL(msg) \ { fprintf( stderr, "pure method( " msg " ) called\n" ); abort(); return false; } #define PVIRT_INT(msg) \ { fprintf( stderr, "pure method( " msg " ) called\n" ); abort(); return 0; } #define PVIRT_CHARCC(msg) \ { fprintf( stderr, "pure method( " msg " ) called\n" ); abort(); return 0; } #else /* NOASSERT */ #define ASSERT(expression, message) do {} while (0) #define ASSERT1(expression, message, parameter1) do {} while (0) #define WARN(expression, message) do {} while (0) #define PVIRT_VOID(msg) = 0 #define PVIRT_INTCF(msg) = 0 #define PVIRT_BOOL(msg) = 0 #define PVIRT_INT(msg) = 0 #define PVIRT_CHARCC(msg) = 0 #endif /* NOASSERT */ /* }}} */ singular-4.0.3+ds/factory/cf_char.cc000066400000000000000000000024531266270727000173240ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_char.cc * * getting and setting the characteristic of a finite field **/ #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "canonicalform.h" #include "imm.h" #include "cf_primes.h" #include "cf_util.h" static int theCharacteristic = 0; static int theDegree = 1; void setCharacteristic( int c ) { if ( c == 0 ) { theDegree = 0; CFFactory::settype( IntegerDomain ); theCharacteristic = 0; } else { theDegree = 1; CFFactory::settype( FiniteFieldDomain ); theCharacteristic = c; ff_big = c > cf_getSmallPrime( cf_getNumSmallPrimes()-1 ); if (c > 536870909) factoryError("characteristic is too large(max is 2^29)"); ff_setprime( c ); } } void setCharacteristic( int c, int n, char name ) { ASSERT( c != 0 && n > 1, "illegal GF(q)" ); setCharacteristic( c ); gf_setcharacteristic( c, n, name ); theDegree = n; CFFactory::settype( GaloisFieldDomain ); } int getCharacteristic() { return theCharacteristic; } int getGFDegree() { //ASSERT( theDegree > 0, "not in GF(q)" ); return theDegree; } CanonicalForm getGFGenerator() { ASSERT( theDegree > 1, "not in GF(q)" ); return int2imm_gf( 1 ); } singular-4.0.3+ds/factory/cf_chinese.cc000066400000000000000000000171721266270727000200310ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_chinese.cc * * algorithms for chinese remaindering and rational reconstruction * * Used by: cf_gcd.cc, cf_linsys.cc * * Header file: cf_algorithm.h * **/ #include "config.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif #include "cf_assert.h" #include "debug.h" #include "canonicalform.h" #include "cf_iter.h" /** void chineseRemainder ( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew ) * * chineseRemainder - integer chinese remaindering. * * Calculate xnew such that xnew=x1 (mod q1) and xnew=x2 (mod q2) * and qnew = q1*q2. q1 and q2 should be positive integers, * pairwise prime, x1 and x2 should be polynomials with integer * coefficients. If x1 and x2 are polynomials with positive * coefficients, the result is guaranteed to have positive * coefficients, too. * * Note: This algorithm is optimized for the case q1>>q2. * * This is a standard algorithm. See, for example, * Geddes/Czapor/Labahn - 'Algorithms for Computer Algebra', * par. 5.6 and 5.8, or the article of M. Lauer - 'Computing by * Homomorphic Images' in B. Buchberger - 'Computer Algebra - * Symbolic and Algebraic Computation'. * * Note: Be sure you are calculating in Z, and not in Q! * **/ void chineseRemainder ( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew ) { DEBINCLEVEL( cerr, "chineseRemainder" ); DEBOUTLN( cerr, "log(q1) = " << q1.ilog2() ); DEBOUTLN( cerr, "log(q2) = " << q2.ilog2() ); // We calculate xnew as follows: // xnew = v1 + v2 * q1 // where // v1 = x1 (mod q1) // v2 = (x2-v1)/q1 (mod q2) (*) // // We do one extra test to check whether x2-v1 vanishes (mod // q2) in (*) since it is not costly and may save us // from calculating the inverse of q1 (mod q2). // // u: v1 (mod q2) // d: x2-v1 (mod q2) // s: 1/q1 (mod q2) // CanonicalForm v2, v1; CanonicalForm u, d, s, dummy; v1 = mod( x1, q1 ); u = mod( v1, q2 ); d = mod( x2-u, q2 ); if ( d.isZero() ) { xnew = v1; qnew = q1 * q2; DEBDECLEVEL( cerr, "chineseRemainder" ); return; } (void)bextgcd( q1, q2, s, dummy ); v2 = mod( d*s, q2 ); xnew = v1 + v2*q1; // After all, calculate new modulus. It is important that // this is done at the very end of the algorithm, since q1 // and qnew may refer to the same object (same is true for x1 // and xnew). qnew = q1 * q2; DEBDECLEVEL( cerr, "chineseRemainder" ); } //}}} /** void chineseRemainder ( const CFArray & x, const CFArray & q, CanonicalForm & xnew, CanonicalForm & qnew ) * * chineseRemainder - integer chinese remaindering. * * Calculate xnew such that xnew=x[i] (mod q[i]) and qnew is the * product of all q[i]. q[i] should be positive integers, * pairwise prime. x[i] should be polynomials with integer * coefficients. If all coefficients of all x[i] are positive * integers, the result is guaranteed to have positive * coefficients, too. * * This is a standard algorithm, too, except for the fact that we * use a divide-and-conquer method instead of a linear approach * to calculate the remainder. * * Note: Be sure you are calculating in Z, and not in Q! * **/ void chineseRemainder ( const CFArray & x, const CFArray & q, CanonicalForm & xnew, CanonicalForm & qnew ) { DEBINCLEVEL( cerr, "chineseRemainder( ... CFArray ... )" ); ASSERT( x.min() == q.min() && x.size() == q.size(), "incompatible arrays" ); CFArray X(x), Q(q); int i, j, n = x.size(), start = x.min(); DEBOUTLN( cerr, "array size = " << n ); while ( n != 1 ) { i = j = start; while ( i < start + n - 1 ) { // This is a little bit dangerous: X[i] and X[j] (and // Q[i] and Q[j]) may refer to the same object. But // xnew and qnew in the above function are modified // at the very end of the function, so we do not // modify x1 and q1, resp., by accident. chineseRemainder( X[i], Q[i], X[i+1], Q[i+1], X[j], Q[j] ); i += 2; j++; } if ( n & 1 ) { X[j] = X[i]; Q[j] = Q[i]; } // Maybe we would get some memory back at this point if // we would set X[j+1, ..., n] and Q[j+1, ..., n] to zero // at this point? n = ( n + 1) / 2; } xnew = X[start]; qnew = Q[q.min()]; DEBDECLEVEL( cerr, "chineseRemainder( ... CFArray ... )" ); } #ifndef HAVE_NTL CanonicalForm Farey_n (CanonicalForm N, const CanonicalForm P) //"USAGE: Farey_n (N,P); P, N number; //RETURN: a rational number a/b such that a/b=N mod P // and |a|,|b|<(P/2)^{1/2} { //assume(P>0); // assume !isOn(SW_RATIONAL): mod is a no-op otherwise if (N<0) N +=P; CanonicalForm A,B,C,D,E; E=P; B=1; while (!N.isZero()) { if (2*N*N #endif int* integerFactorizer (const long integer, int& length, bool& fail) { ASSERT (integer != 0 && integer != 1 && integer != -1, "non-zero non-unit expected"); int* result=NULL; length= 0; fail= false; int i= integer; if (integer < 0) i = -integer; int exp= 0; while ((i != 1) && (i%2 == 0)) { i /= 2; exp++; } if (exp != 0) { result= new int [exp]; for (int k= 0; k < exp; k++) result[k]= 2; length += exp; } if (i == 1) return result; long j= 0; exp= 0; int* buf; int next_prime; while ((i != 1) && (j < 31937)) { next_prime= cf_getPrime (j); while ((i != 1) && (i%next_prime == 0)) { i /= next_prime; exp++; } if (exp != 0) { buf= result; result= new int [length + exp]; for (int k= 0; k < length; k++) result [k]= buf[k]; for (int k= 0; k < exp; k++) result [k + length]= next_prime; length += exp; } exp= 0; j++; } if (j >= 31397) fail= true; ASSERT (j < 31397, "integer factorizer ran out of primes"); //sic return result; } /// make prime factorization distinct static inline int* makeDistinct (int* factors, const int factors_length, int& length) { length= 1; int* result= new int [length]; int* buf; result[0]= factors [0]; for (int i= 1; i < factors_length; i++) { if (factors[i - 1] != factors[i]) { buf= result; result= new int [length + 1]; for (int j= 0; j < length; j++) result[j]= buf [j]; result[length]= factors[i]; length++; } } return result; } CanonicalForm cyclotomicPoly (int n, bool& fail) { fail= false; Variable x= Variable (1); CanonicalForm result= x - 1; if (n == 1) return result; int* prime_factors; int prime_factors_length; int distinct_factors_length; prime_factors= integerFactorizer (n, prime_factors_length, fail); int* distinct_factors= makeDistinct (prime_factors, prime_factors_length, distinct_factors_length); if (fail) return 1; CanonicalForm buf; int prod= 1; for (int i= 0; i < distinct_factors_length; i++) { result= leftShift (result, distinct_factors[i])/result; prod *= distinct_factors[i]; } return leftShift (result, n/prod); } #ifdef HAVE_NTL bool isPrimitive (const Variable& alpha, bool& fail) { int p= getCharacteristic(); CanonicalForm mipo= getMipo (alpha); int order= ipower(p, degree(mipo)) - 1; CanonicalForm cyclo= cyclotomicPoly (order, fail); if (fail) return false; if (mod(cyclo, mipo (Variable(1), alpha)) == 0) return true; else return false; } #endif singular-4.0.3+ds/factory/cf_cyclo.h000066400000000000000000000025041266270727000173570ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file cf_cyclo.h * * Compute cyclotomic polynomials and factorize integers by brute force * * @par Copyright: * (c) by The SINGULAR Team, see LICENSE file * * @author Martin Lee **/ //***************************************************************************** #ifndef CF_CYCLO_H #define CF_CYCLO_H // #include "config.h" /// integer factorization using table look-ups, /// function may fail if integer contains primes which exceed the largest prime /// in our table int* integerFactorizer (const long integer, ///< [in] some integer int& length, ///< [in,out] number of factors bool& fail ///< [in,out] failure? ); /// compute the n-th cyclotomic polynomial, /// function may fail if integer_factorizer fails to factorize n CanonicalForm cyclotomicPoly (int n, ///< [in] some integer bool& fail ///< [in,out] failure? ); /// checks if alpha is a primitive element, alpha is assumed to be an algebraic /// variable over some finite prime field bool isPrimitive (const Variable& alpha, ///< [in] some algebraic variable bool& fail ///< [in,out] failure? ); #endif singular-4.0.3+ds/factory/cf_defs.h000066400000000000000000000021141266270727000171640ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_defs.h * * factory switches. **/ #ifndef INCL_CF_DEFS_H #define INCL_CF_DEFS_H // #include "config.h" /*BEGINPUBLIC*/ #define LEVELBASE -1000000 #define LEVELTRANS -500000 #define LEVELQUOT 1000000 #define LEVELEXPR 1000001 #define UndefinedDomain 32000 #define GaloisFieldDomain 4 #define FiniteFieldDomain 3 #define RationalDomain 2 #define IntegerDomain 1 /// set to 1 for computations over Q static const int SW_RATIONAL = 0; /// set to 1 for symmetric representation over F_q static const int SW_SYMMETRIC_FF = 1; /// set to 1 to use EZGCD over Z static const int SW_USE_EZGCD = 2; /// set to 1 to use EZGCD over F_q static const int SW_USE_EZGCD_P = 3; /// set to 1 to sort factors in a factorization static const int SW_USE_NTL_SORT=4; /// set to 1 to use modular gcd over Z static const int SW_USE_CHINREM_GCD=5; /// set to 1 to use Encarnacion GCD over Q(a) static const int SW_USE_QGCD=6; /// set to 1 to use modular GCD over F_q static const int SW_USE_FF_MOD_GCD=7; /*ENDPUBLIC*/ #endif /* ! INCL_CF_DEFS_H */ singular-4.0.3+ds/factory/cf_eval.cc000066400000000000000000000032201266270727000173270ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "cf_eval.h" static CanonicalForm evalCF ( const CanonicalForm & f, const CFArray & a, int m, int n ); Evaluation& Evaluation::operator= ( const Evaluation & e ) { if ( this != &e ) { values = e.values; } return *this; } CanonicalForm Evaluation::operator() ( const CanonicalForm & f ) const { if ( f.inCoeffDomain() || f.level() < values.min() ) return f; else if ( f.level() < values.max() ) return evalCF( f, values, values.min(), f.level() ); else return evalCF( f, values, values.min(), values.max() ); } CanonicalForm Evaluation::operator() ( const CanonicalForm & f, int i, int j ) const { if ( i > j ) return f; return evalCF( f, values, i, j ); } void Evaluation::nextpoint() { int n = values.max(); for ( int i = values.min(); i <= n; i++ ) values[i] += 1; } void Evaluation::setValue(int i, const CanonicalForm& f) { if (i < values.min() || i > values.max()) return; values[i]= f; } #ifndef NOSTREAMIO OSTREAM& operator<< ( OSTREAM& s, const Evaluation &e ) { e.values.print(s); return s; } #endif /* NOSTREAMIO */ CanonicalForm evalCF ( const CanonicalForm & f, const CFArray & a, int m, int n ) { if ( m > n ) return f; else { CanonicalForm result = f; while ( n >= m ) { result = result( a[n], Variable( n ) ); n--; } return result; } // iterated method turned out to be faster than // return evalCF( f( a[n], Variable( n ) ), a, m, n-1 ); } singular-4.0.3+ds/factory/cf_eval.h000066400000000000000000000026021266270727000171740ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_eval.h * * evaluate polynomials at points **/ #ifndef INCL_CF_EVAL_H #define INCL_CF_EVAL_H // #include "config.h" #ifndef NOSTREAMIO #ifdef HAVE_IOSTREAM #include #define OSTREAM std::ostream #elif defined(HAVE_IOSTREAM_H) #include #define OSTREAM ostream #endif #endif /* NOSTREAMIO */ #include "canonicalform.h" /*BEGINPUBLIC*/ /** * class to evaluate a polynomial at points **/ class Evaluation { protected: CFArray values; public: Evaluation() : values() {} Evaluation( int min0, int max0 ) : values( min0, max0 ) {} Evaluation( const Evaluation & e ) : values( e.values ) {} virtual ~Evaluation() {} Evaluation& operator= ( const Evaluation & e ); int min() const { return values.min(); } int max() const { return values.max(); } CanonicalForm operator[] ( int i ) const { return values[i]; } CanonicalForm operator[] ( const Variable & v ) const { return operator[](v.level()); } CanonicalForm operator() ( const CanonicalForm& f ) const; CanonicalForm operator() ( const CanonicalForm & f, int i, int j ) const; void setValue (int i, const CanonicalForm& f); virtual void nextpoint(); #ifndef NOSTREAMIO friend OSTREAM& operator<< ( OSTREAM& s, const Evaluation &e ); #endif /* NOSTREAMIO */ }; /*ENDPUBLIC*/ #endif /* ! INCL_CF_EVAL_H */ singular-4.0.3+ds/factory/cf_factor.cc000066400000000000000000000453501266270727000176700ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_factor.cc * * Interface to factorization and square free factorization algorithms. * * Used by: cf_irred.cc * * Header file: cf_algorithm.h * **/ #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "canonicalform.h" #include "cf_iter.h" #include "fac_sqrfree.h" #include "cf_algorithm.h" #include "facFqFactorize.h" #include "facFqSquarefree.h" #include "cf_map.h" #include "facAlgExt.h" #include "facFactorize.h" #include "singext.h" #include "cf_util.h" #include "int_int.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif #include #ifdef HAVE_FLINT #include "FLINTconvert.h" #endif //static bool isUnivariateBaseDomain( const CanonicalForm & f ) //{ // CFIterator i = f; // bool ok = i.coeff().inBaseDomain(); // i++; // while ( i.hasTerms() && ( ok = ok && i.coeff().inBaseDomain() ) ) i++; // return ok; //} void find_exp(const CanonicalForm & f, int * exp_f) { if ( ! f.inCoeffDomain() ) { int e=f.level(); CFIterator i = f; if (e>=0) { if (i.exp() > exp_f[e]) exp_f[e]=i.exp(); } for (; i.hasTerms(); i++ ) { find_exp(i.coeff(), exp_f); } } } int find_mvar(const CanonicalForm & f) { int mv=f.level(); int *exp_f=new int[mv+1]; int i; for(i=mv;i>0;i--) exp_f[i]=0; find_exp(f,exp_f); for(i=mv;i>0;i--) { if ((exp_f[i]>0) && (exp_f[i]0) { t*=tt; j--; } } if (!(f-t).isZero()) { printf("problem:\n");out_cf("factor:",f," has problems\n");} } //#endif #endif bool isPurePoly_m(const CanonicalForm & f) { if (f.inBaseDomain()) return true; if (f.level()<0) return false; for (CFIterator i=f;i.hasTerms();i++) { if (!isPurePoly_m(i.coeff())) return false; } return true; } bool isPurePoly(const CanonicalForm & f) { if (f.level()<=0) return false; for (CFIterator i=f;i.hasTerms();i++) { if (!(i.coeff().inBaseDomain())) return false; } return true; } /** * get_max_degree_Variable returns Variable with * highest degree. We assume f is *not* a constant! **/ Variable get_max_degree_Variable(const CanonicalForm & f) { ASSERT( ( ! f.inCoeffDomain() ), "no constants" ); int max=0, maxlevel=0, n=level(f); for ( int i=1; i<=n; i++ ) { if (degree(f,Variable(i)) >= max) { max= degree(f,Variable(i)); maxlevel= i; } } return Variable(maxlevel); } /** * get_Terms: Split the polynomial in the containing terms. * getTerms: the real work is done here. **/ void getTerms( const CanonicalForm & f, const CanonicalForm & t, CFList & result ) { if ( getNumVars(f) == 0 ) result.append(f*t); else{ Variable x(level(f)); for ( CFIterator i=f; i.hasTerms(); i++ ) getTerms( i.coeff(), t*power(x,i.exp()), result); } } CFList get_Terms( const CanonicalForm & f ){ CFList result,dummy,dummy2; CFIterator i; CFListIterator j; if ( getNumVars(f) == 0 ) result.append(f); else{ Variable _x(level(f)); for ( i=f; i.hasTerms(); i++ ){ getTerms(i.coeff(), 1, dummy); for ( j=dummy; j.hasItem(); j++ ) result.append(j.getItem() * power(_x, i.exp())); dummy= dummy2; // have to initalize new } } return result; } /** * homogenize homogenizes f with Variable x **/ CanonicalForm homogenize( const CanonicalForm & f, const Variable & x) { #if 0 int maxdeg=totaldegree(f), deg; CFIterator i; CanonicalForm elem, result(0); for (i=f; i.hasTerms(); i++) { elem= i.coeff()*power(f.mvar(),i.exp()); deg = totaldegree(elem); if ( deg < maxdeg ) result += elem * power(x,maxdeg-deg); else result+=elem; } return result; #else CFList Newlist, Termlist= get_Terms(f); int maxdeg=totaldegree(f), deg; CFListIterator i; CanonicalForm elem, result(0); for (i=Termlist; i.hasItem(); i++) { elem= i.getItem(); deg = totaldegree(elem); if ( deg < maxdeg ) Newlist.append(elem * power(x,maxdeg-deg)); else Newlist.append(elem); } for (i=Newlist; i.hasItem(); i++) // rebuild result += i.getItem(); return result; #endif } CanonicalForm homogenize( const CanonicalForm & f, const Variable & x, const Variable & v1, const Variable & v2) { #if 0 int maxdeg=totaldegree(f), deg; CFIterator i; CanonicalForm elem, result(0); for (i=f; i.hasTerms(); i++) { elem= i.coeff()*power(f.mvar(),i.exp()); deg = totaldegree(elem); if ( deg < maxdeg ) result += elem * power(x,maxdeg-deg); else result+=elem; } return result; #else CFList Newlist, Termlist= get_Terms(f); int maxdeg=totaldegree(f), deg; CFListIterator i; CanonicalForm elem, result(0); for (i=Termlist; i.hasItem(); i++) { elem= i.getItem(); deg = totaldegree(elem,v1,v2); if ( deg < maxdeg ) Newlist.append(elem * power(x,maxdeg-deg)); else Newlist.append(elem); } for (i=Newlist; i.hasItem(); i++) // rebuild result += i.getItem(); return result; #endif } int singular_homog_flag=1; int cmpCF( const CFFactor & f, const CFFactor & g ) { if (f.exp() > g.exp()) return 1; if (f.exp() < g.exp()) return 0; if (f.factor() > g.factor()) return 1; return 0; } /** * factorization over \f$ F_p \f$ or \f$ Q \f$ **/ CFFList factorize ( const CanonicalForm & f, bool issqrfree ) { if ( f.inCoeffDomain() ) return CFFList( f ); #ifndef NOASSERT Variable a; ASSERT (!hasFirstAlgVar (f, a), "f has an algebraic variable use factorize \ ( const CanonicalForm & f, const Variable & alpha ) instead"); #endif //out_cf("factorize:",f,"==================================\n"); if (! f.isUnivariate() ) { if ( singular_homog_flag && f.isHomogeneous()) { Variable xn = get_max_degree_Variable(f); int d_xn = degree(f,xn); CFMap n; CanonicalForm F = compress(f(1,xn),n); CFFList Intermediatelist; Intermediatelist = factorize(F); CFFList Homoglist; CFFListIterator j; for ( j=Intermediatelist; j.hasItem(); j++ ) { Homoglist.append( CFFactor( n(j.getItem().factor()), j.getItem().exp()) ); } CFFList Unhomoglist; CanonicalForm unhomogelem; for ( j=Homoglist; j.hasItem(); j++ ) { unhomogelem= homogenize(j.getItem().factor(),xn); Unhomoglist.append(CFFactor(unhomogelem,j.getItem().exp())); d_xn -= (degree(unhomogelem,xn)*j.getItem().exp()); } if ( d_xn != 0 ) // have to append xn^(d_xn) Unhomoglist.append(CFFactor(CanonicalForm(xn),d_xn)); if(isOn(SW_USE_NTL_SORT)) Unhomoglist.sort(cmpCF); return Unhomoglist; } } CFFList F; if ( getCharacteristic() > 0 ) { if (f.isUnivariate()) { #ifdef HAVE_NTL #ifdef HAVE_FLINT if (degree (f) < 300) { nmod_poly_t f1; convertFacCF2nmod_poly_t (f1, f); nmod_poly_factor_t result; nmod_poly_factor_init (result); mp_limb_t leadingCoeff= nmod_poly_factor (result, f1); F= convertFLINTnmod_poly_factor2FacCFFList (result, leadingCoeff, f.mvar()); nmod_poly_factor_clear (result); nmod_poly_clear (f1); } else #endif { // USE NTL if (getCharacteristic()!=2) { if (fac_NTL_char != getCharacteristic()) { fac_NTL_char = getCharacteristic(); zz_p::init(getCharacteristic()); } // convert to NTL zz_pX f1=convertFacCF2NTLzzpX(f); zz_p leadcoeff = LeadCoeff(f1); //make monic f1=f1 / LeadCoeff(f1); // factorize vec_pair_zz_pX_long factors; CanZass(factors,f1); F=convertNTLvec_pair_zzpX_long2FacCFFList(factors,leadcoeff,f.mvar()); //test_cff(F,f); } else /*getCharacteristic()==2*/ { // Specialcase characteristic==2 if (fac_NTL_char != 2) { fac_NTL_char = 2; zz_p::init(2); } // convert to NTL using the faster conversion routine for characteristic 2 GF2X f1=convertFacCF2NTLGF2X(f); // no make monic necessary in GF2 //factorize vec_pair_GF2X_long factors; CanZass(factors,f1); // convert back to factory again using the faster conversion routine for vectors over GF2X F=convertNTLvec_pair_GF2X_long2FacCFFList(factors,LeadCoeff(f1),f.mvar()); } } #else // Use Factory without NTL factoryError ("univariate factorization depends on NTL(missing)"); return CFFList (CFFactor (f, 1)); #endif //HAVE_NTL } else { #ifdef HAVE_NTL if (issqrfree) { CFList factors; Variable alpha; if (CFFactory::gettype() == GaloisFieldDomain) factors= GFSqrfFactorize (f); else factors= FpSqrfFactorize (f); for (CFListIterator i= factors; i.hasItem(); i++) F.append (CFFactor (i.getItem(), 1)); } else { Variable alpha; if (CFFactory::gettype() == GaloisFieldDomain) F= GFFactorize (f); else F= FpFactorize (f); } #else ASSERT( f.isUnivariate(), "multivariate factorization depends on NTL(missing)" ); factoryError ("multivariate factorization depends on NTL(missing)"); return CFFList (CFFactor (f, 1)); #endif } } else { bool on_rational = isOn(SW_RATIONAL); On(SW_RATIONAL); CanonicalForm cd = bCommonDen( f ); CanonicalForm fz = f * cd; Off(SW_RATIONAL); if ( f.isUnivariate() ) { #ifdef HAVE_NTL //USE NTL CanonicalForm ic=icontent(fz); fz/=ic; ZZ c; vec_pair_ZZX_long factors; //factorize the converted polynomial factor(c,factors,convertFacCF2NTLZZX(fz)); //convert the result back to Factory F=convertNTLvec_pair_ZZX_long2FacCFFList(factors,c,fz.mvar()); if ( ! ic.isOne() ) { if ( F.getFirst().factor().inCoeffDomain() ) { CFFactor new_first( F.getFirst().factor() * ic ); F.removeFirst(); F.insert( new_first ); } else F.insert( CFFactor( ic ) ); } else { if ( !F.getFirst().factor().inCoeffDomain() ) { CFFactor new_first( 1 ); F.insert( new_first ); } } #else factoryError ("univariate factorization over Z depends on NTL(missing)"); return CFFList (CFFactor (f, 1)); #endif } else { #ifdef HAVE_NTL On (SW_RATIONAL); if (issqrfree) { CFList factors; factors= ratSqrfFactorize (fz); for (CFListIterator i= factors; i.hasItem(); i++) F.append (CFFactor (i.getItem(), 1)); } else F = ratFactorize (fz); Off (SW_RATIONAL); #else factoryError ("multivariate factorization depends on NTL(missing)"); return CFFList (CFFactor (f, 1)); #endif } if ( on_rational ) On(SW_RATIONAL); if ( ! cd.isOne() ) { if ( F.getFirst().factor().inCoeffDomain() ) { CFFactor new_first( F.getFirst().factor() / cd ); F.removeFirst(); F.insert( new_first ); } else { F.insert( CFFactor( 1/cd ) ); } } } //out_cff(F); if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF); return F; } /** * factorization over \f$ F_p(\alpha) \f$ or \f$ Q(\alpha) \f$ **/ CFFList factorize ( const CanonicalForm & f, const Variable & alpha ) { if ( f.inCoeffDomain() ) return CFFList( f ); //out_cf("factorize:",f,"==================================\n"); //out_cf("mipo:",getMipo(alpha),"\n"); CFFList F; ASSERT( alpha.level() < 0 && getReduce (alpha), "not an algebraic extension" ); #ifndef NOASSERT Variable beta; if (hasFirstAlgVar(f, beta)) ASSERT (beta == alpha, "f has an algebraic variable that \ does not coincide with alpha"); #endif int ch=getCharacteristic(); if (f.isUnivariate()&& (ch>0)) { #ifdef HAVE_NTL //USE NTL if (ch>2) { #if (HAVE_FLINT && __FLINT_RELEASE >= 20400) nmod_poly_t FLINTmipo, leadingCoeff; fq_nmod_ctx_t fq_con; nmod_poly_init (FLINTmipo, getCharacteristic()); nmod_poly_init (leadingCoeff, getCharacteristic()); convertFacCF2nmod_poly_t (FLINTmipo, getMipo (alpha)); fq_nmod_ctx_init_modulus (fq_con, FLINTmipo, "Z"); fq_nmod_poly_t FLINTF; convertFacCF2Fq_nmod_poly_t (FLINTF, f, fq_con); fq_nmod_poly_factor_t res; fq_nmod_poly_factor_init (res, fq_con); fq_nmod_poly_factor (res, leadingCoeff, FLINTF, fq_con); F= convertFLINTFq_nmod_poly_factor2FacCFFList (res, f.mvar(), alpha, fq_con); F.insert (CFFactor (Lc (f), 1)); fq_nmod_poly_factor_clear (res, fq_con); fq_nmod_poly_clear (FLINTF, fq_con); nmod_poly_clear (FLINTmipo); nmod_poly_clear (leadingCoeff); fq_nmod_ctx_clear (fq_con); #else // First all cases with characteristic !=2 // set remainder if (fac_NTL_char != getCharacteristic()) { fac_NTL_char = getCharacteristic(); zz_p::init(getCharacteristic()); } // set minimal polynomial in NTL zz_pX minPo=convertFacCF2NTLzzpX(getMipo(alpha)); zz_pE::init (minPo); // convert to NTL zz_pEX f1=convertFacCF2NTLzz_pEX(f,minPo); zz_pE leadcoeff= LeadCoeff(f1); //make monic f1=f1 / leadcoeff; // factorize using NTL vec_pair_zz_pEX_long factors; CanZass(factors,f1); // return converted result F=convertNTLvec_pair_zzpEX_long2FacCFFList(factors,leadcoeff,f.mvar(),alpha); #endif } else if (/*getCharacteristic()*/ch==2) { // special case : GF2 // remainder is two ==> nothing to do // set minimal polynomial in NTL using the optimized conversion routines for characteristic 2 GF2X minPo=convertFacCF2NTLGF2X(getMipo(alpha,f.mvar())); GF2E::init (minPo); // convert to NTL again using the faster conversion routines GF2EX f1; if (isPurePoly(f)) { GF2X f_tmp=convertFacCF2NTLGF2X(f); f1=to_GF2EX(f_tmp); } else f1=convertFacCF2NTLGF2EX(f,minPo); // make monic (in Z/2(a)) GF2E f1_coef=LeadCoeff(f1); MakeMonic(f1); // factorize using NTL vec_pair_GF2EX_long factors; CanZass(factors,f1); // return converted result F=convertNTLvec_pair_GF2EX_long2FacCFFList(factors,f1_coef,f.mvar(),alpha); } #else factoryError ("univariate factorization depends on NTL(missing)"); return CFFList (CFFactor (f, 1)); #endif //HAVE_NTL } else if (ch>0) { #ifdef HAVE_NTL F= FqFactorize (f, alpha); #else ASSERT( f.isUnivariate(), "multivariate factorization depends on NTL(missing)" ); factoryError ("multivariate factorization depends on NTL(missing)"); return CFFList (CFFactor (f, 1)); #endif } else if (f.isUnivariate() && (ch == 0)) // Q(a)[x] { F= AlgExtFactorize (f, alpha); } else //Q(a)[x1,...,xn] { #ifdef HAVE_NTL F= ratFactorize (f, alpha); #else ASSERT( f.isUnivariate(), "multivariate factorization depends on NTL(missing)" ); factoryError ("multivariate factorization depends on NTL(missing)"); return CFFList (CFFactor (f, 1)); #endif } if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF); return F; } /** * squarefree factorization **/ CFFList sqrFree ( const CanonicalForm & f, bool sort ) { // ASSERT( f.isUnivariate(), "multivariate factorization not implemented" ); CFFList result; if ( getCharacteristic() == 0 ) result = sqrFreeZ( f ); else { Variable alpha; if (hasFirstAlgVar (f, alpha)) result = FqSqrf( f, alpha ); else result= FpSqrf (f); } if (sort) { CFFactor buf= result.getFirst(); result.removeFirst(); result= sortCFFList (result); result.insert (buf); } return result; } singular-4.0.3+ds/factory/cf_factory.cc000066400000000000000000000164211266270727000200560ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "cf_factory.h" #include "canonicalform.h" #include "int_cf.h" #include "int_int.h" #include "int_rat.h" #include "int_poly.h" #include "imm.h" int CFFactory::currenttype = IntegerDomain; void CFFactory::settype ( int type ) { ASSERT( type==FiniteFieldDomain || type==GaloisFieldDomain || type==IntegerDomain || type==RationalDomain, "illegal basic domain!" ); currenttype = type; } InternalCF * CFFactory::basic ( long value ) { if ( currenttype == IntegerDomain ) if ( value >= MINIMMEDIATE && value <= MAXIMMEDIATE ) return int2imm( value ); else return new InternalInteger( value ); // else if ( currenttype == RationalDomain ) // if ( value >= MINIMMEDIATE && value <= MAXIMMEDIATE ) // return int2imm( value ); // else // return new InternalRational( value ); else if ( currenttype == FiniteFieldDomain ) return int2imm_p( ff_norm( value ) ); else if ( currenttype == GaloisFieldDomain ) return int2imm_gf( gf_int2gf( value ) ); else { ASSERT( 0, "illegal basic domain!" ); return 0; } } InternalCF * CFFactory::basic ( int type, long value ) { if ( type == IntegerDomain ) if ( value >= MINIMMEDIATE && value <= MAXIMMEDIATE ) return int2imm( value ); else return new InternalInteger( value ); // else if ( type == RationalDomain ) // if ( value >= MINIMMEDIATE && value <= MAXIMMEDIATE ) // return int2imm( value ); // else // return new InternalRational( value ); else if ( type == FiniteFieldDomain ) return int2imm_p( ff_norm( value ) ); else if ( type == GaloisFieldDomain ) return int2imm_gf( gf_int2gf( value ) ); else { ASSERT1( 0, "illegal basic domain (type = %d)!", type ); return 0; } } InternalCF * CFFactory::basic ( const char * str ) { if ( currenttype == IntegerDomain ) { InternalInteger * dummy = new InternalInteger( str ); if ( dummy->is_imm() ) { InternalCF * res = int2imm( dummy->intval() ); delete dummy; return res; } else return dummy; } // else if ( currenttype == RationalDomain ) { // InternalRational * dummy = new InternalRational( str ); // if ( dummy->is_imm() ) { // InternalCF * res = int2imm( dummy->intval() ); // delete dummy; // return res; // } // else // return dummy; // } else if ( currenttype == FiniteFieldDomain ) { InternalInteger * dummy = new InternalInteger( str ); InternalCF * res = int2imm_p( dummy->intmod( ff_prime ) ); delete dummy; return res; } else if ( currenttype == GaloisFieldDomain ) { InternalInteger * dummy = new InternalInteger( str ); InternalCF * res = int2imm_gf( gf_int2gf( dummy->intmod( ff_prime ) ) ); delete dummy; return res; } else { ASSERT( 0, "illegal basic domain!" ); return 0; } } InternalCF * CFFactory::basic ( const char * str, int base ) { if ( currenttype == IntegerDomain ) { InternalInteger * dummy = new InternalInteger( str, base ); if ( dummy->is_imm() ) { InternalCF * res = int2imm( dummy->intval() ); delete dummy; return res; } else return dummy; } // else if ( currenttype == RationalDomain ) { // InternalRational * dummy = new InternalRational( str ); // if ( dummy->is_imm() ) { // InternalCF * res = int2imm( dummy->intval() ); // delete dummy; // return res; // } // else // return dummy; // } else if ( currenttype == FiniteFieldDomain ) { InternalInteger * dummy = new InternalInteger( str, base ); InternalCF * res = int2imm_p( dummy->intmod( ff_prime ) ); delete dummy; return res; } else if ( currenttype == GaloisFieldDomain ) { InternalInteger * dummy = new InternalInteger( str, base ); InternalCF * res = int2imm_gf( gf_int2gf( dummy->intmod( ff_prime ) ) ); delete dummy; return res; } else { ASSERT( 0, "illegal basic domain!" ); return 0; } } InternalCF * CFFactory::basic ( int type, const char * const str ) { if ( type == IntegerDomain ) { InternalInteger * dummy = new InternalInteger( str ); if ( dummy->is_imm() ) { InternalCF * res = int2imm( dummy->intval() ); delete dummy; return res; } else return dummy; } // else if ( type == RationalDomain ) { // InternalRational * dummy = new InternalRational( str ); // if ( dummy->is_imm() ) { // InternalCF * res = int2imm( dummy->intval() ); // delete dummy; // return res; // } // else // return dummy; // } else if ( type == FiniteFieldDomain ) { InternalInteger * dummy = new InternalInteger( str ); InternalCF * res = int2imm( dummy->intmod( ff_prime ) ); delete dummy; return res; } else if ( type == GaloisFieldDomain ) { InternalInteger * dummy = new InternalInteger( str ); InternalCF * res = int2imm_gf( gf_int2gf( dummy->intmod( ff_prime ) ) ); delete dummy; return res; } else { ASSERT( 0, "illegal basic domain!" ); return 0; } } InternalCF * CFFactory::basic ( int type, long value, bool nonimm ) { if ( nonimm ) if ( type == IntegerDomain ) return new InternalInteger( value ); else if ( type == RationalDomain ) return new InternalRational( value ); else { ASSERT( 0, "illegal basic domain!" ); return 0; } else return CFFactory::basic( type, value ); } InternalCF * CFFactory::basic ( const mpz_ptr num ) { ASSERT (currenttype == IntegerDomain, "Integer domain expected"); return new InternalInteger( num ); } InternalCF * CFFactory::rational ( long num, long den ) { InternalRational * res = new InternalRational( num, den ); return res->normalize_myself(); } InternalCF * CFFactory::rational ( const mpz_ptr num, const mpz_ptr den, bool normalize ) { if ( normalize ) { InternalRational * result = new InternalRational( num, den ); return result->normalize_myself(); } else return new InternalRational( num, den ); } InternalCF * CFFactory::poly ( const Variable & v, int exp, const CanonicalForm & c ) { if ( v.level() == LEVELBASE ) return c.getval(); else return new InternalPoly( v, exp, c ); } InternalCF * CFFactory::poly ( const Variable & v, int exp ) { if ( v.level() == LEVELBASE ) return CFFactory::basic( 1L ); else return new InternalPoly( v, exp, 1 ); } void getmpi ( InternalCF * value, mpz_t mpi) { ASSERT( ! is_imm( value ) && (value->levelcoeff() == IntegerDomain ), "illegal operation" ); mpz_init_set (mpi, ((InternalInteger*)value)->thempi); } singular-4.0.3+ds/factory/cf_factory.h000066400000000000000000000024371266270727000177220ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_factory.h * * Interface to generate InternalCF's over various domains from intrinsic types * or mpz_t's **/ #ifndef INCL_CF_FACTORY_H #define INCL_CF_FACTORY_H // #include "config.h" #include "cf_defs.h" #include "variable.h" #include class InternalCF; class CanonicalForm; class CFFactory { private: static int currenttype; public: static int gettype () { return currenttype; } static void settype ( int type ); static InternalCF * basic ( long value ); static InternalCF * basic ( int type, long value ); static InternalCF * basic ( const char * str ); static InternalCF * basic ( const char * str, int base ); static InternalCF * basic ( int type, const char * const str ); static InternalCF * basic ( int type, long value, bool nonimm ); static InternalCF * basic ( const mpz_ptr num ); static InternalCF * rational ( long num, long den ); static InternalCF * rational ( const mpz_ptr num, const mpz_ptr den, bool normalize ); static InternalCF * poly ( const Variable & v, int exp, const CanonicalForm & c ); static InternalCF * poly ( const Variable & v, int exp = 1 ); }; void getmpi ( InternalCF * value, mpz_t mpi); #endif /* ! INCL_CF_FACTORY_H */ singular-4.0.3+ds/factory/cf_gcd.cc000066400000000000000000000206171266270727000171460ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_gcd.cc * * gcd/content/lcm of polynomials * * To compute the GCD different variants are chosen automatically **/ #include "config.h" #include "timing.h" #include "cf_assert.h" #include "debug.h" #include "cf_defs.h" #include "canonicalform.h" #include "cf_iter.h" #include "cf_reval.h" #include "cf_primes.h" #include "cf_algorithm.h" #include "cfEzgcd.h" #include "cfGcdAlgExt.h" #include "cfSubResGcd.h" #include "cfModGcd.h" #ifdef HAVE_NTL #include #include "NTLconvert.h" bool isPurePoly(const CanonicalForm & ); #endif void out_cf(const char *s1,const CanonicalForm &f,const char *s2); /** static CanonicalForm icontent ( const CanonicalForm & f, const CanonicalForm & c ) * * icontent() - return gcd of c and all coefficients of f which * are in a coefficient domain. * * @sa icontent(). * **/ static CanonicalForm icontent ( const CanonicalForm & f, const CanonicalForm & c ) { if ( f.inBaseDomain() ) { if (c.isZero()) return abs(f); return bgcd( f, c ); } //else if ( f.inCoeffDomain() ) // return gcd(f,c); else { CanonicalForm g = c; for ( CFIterator i = f; i.hasTerms() && ! g.isOne(); i++ ) g = icontent( i.coeff(), g ); return g; } } /** CanonicalForm icontent ( const CanonicalForm & f ) * * icontent() - return gcd over all coefficients of f which are * in a coefficient domain. * **/ CanonicalForm icontent ( const CanonicalForm & f ) { return icontent( f, 0 ); } /** CanonicalForm gcd_poly ( const CanonicalForm & f, const CanonicalForm & g ) * * gcd_poly() - calculate polynomial gcd. * * This is the dispatcher for polynomial gcd calculation. * Different gcd variants get called depending the input, characteristic, and * on switches (cf_defs.h) * * With the current settings from Singular (i.e. SW_USE_EZGCD= on, * SW_USE_EZGCD_P= on, SW_USE_CHINREM_GCD= on, the EZ GCD variants are the * default algorithms for multivariate polynomial GCD computations) * * @sa gcd(), cf_defs.h * **/ #if 0 int si_factor_reminder=1; #endif CanonicalForm gcd_poly ( const CanonicalForm & f, const CanonicalForm & g ) { CanonicalForm fc, gc, d1; bool fc_isUnivariate=f.isUnivariate(); bool gc_isUnivariate=g.isUnivariate(); bool fc_and_gc_Univariate=fc_isUnivariate && gc_isUnivariate; fc = f; gc = g; if ( getCharacteristic() != 0 ) { #ifdef HAVE_NTL if ((!fc_and_gc_Univariate) && (isOn( SW_USE_EZGCD_P ))) { fc= EZGCD_P (fc, gc); } else if (isOn(SW_USE_FF_MOD_GCD) && !fc_and_gc_Univariate) { Variable a; if (hasFirstAlgVar (fc, a) || hasFirstAlgVar (gc, a)) fc=modGCDFq (fc, gc, a); else if (CFFactory::gettype() == GaloisFieldDomain) fc=modGCDGF (fc, gc); else fc=modGCDFp (fc, gc); } else #endif fc = subResGCD_p( fc, gc ); } else if (!fc_and_gc_Univariate) { if ( isOn( SW_USE_EZGCD ) ) fc= ezgcd (fc, gc); #ifdef HAVE_NTL else if (isOn(SW_USE_CHINREM_GCD)) fc = modGCDZ( fc, gc); #endif else { fc = subResGCD_0( fc, gc ); } } else { fc = subResGCD_0( fc, gc ); } if ( d1.degree() > 0 ) fc *= d1; return fc; } /** static CanonicalForm cf_content ( const CanonicalForm & f, const CanonicalForm & g ) * * cf_content() - return gcd(g, content(f)). * * content(f) is calculated with respect to f's main variable. * * @sa gcd(), content(), content( CF, Variable ). * **/ static CanonicalForm cf_content ( const CanonicalForm & f, const CanonicalForm & g ) { if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) ) { CFIterator i = f; CanonicalForm result = g; while ( i.hasTerms() && ! result.isOne() ) { result = gcd( i.coeff(), result ); i++; } return result; } else return abs( f ); } /** CanonicalForm content ( const CanonicalForm & f ) * * content() - return content(f) with respect to main variable. * * Normalizes result. * **/ CanonicalForm content ( const CanonicalForm & f ) { if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) ) { CFIterator i = f; CanonicalForm result = abs( i.coeff() ); i++; while ( i.hasTerms() && ! result.isOne() ) { result = gcd( i.coeff(), result ); i++; } return result; } else return abs( f ); } /** CanonicalForm content ( const CanonicalForm & f, const Variable & x ) * * content() - return content(f) with respect to x. * * x should be a polynomial variable. * **/ CanonicalForm content ( const CanonicalForm & f, const Variable & x ) { if (f.inBaseDomain()) return f; ASSERT( x.level() > 0, "cannot calculate content with respect to algebraic variable" ); Variable y = f.mvar(); if ( y == x ) return cf_content( f, 0 ); else if ( y < x ) return f; else return swapvar( content( swapvar( f, y, x ), y ), y, x ); } /** CanonicalForm vcontent ( const CanonicalForm & f, const Variable & x ) * * vcontent() - return content of f with repect to variables >= x. * * The content is recursively calculated over all coefficients in * f having level less than x. x should be a polynomial * variable. * **/ CanonicalForm vcontent ( const CanonicalForm & f, const Variable & x ) { ASSERT( x.level() > 0, "cannot calculate vcontent with respect to algebraic variable" ); if ( f.mvar() <= x ) return content( f, x ); else { CFIterator i; CanonicalForm d = 0; for ( i = f; i.hasTerms() && ! d.isOne(); i++ ) d = gcd( d, vcontent( i.coeff(), x ) ); return d; } } /** CanonicalForm pp ( const CanonicalForm & f ) * * pp() - return primitive part of f. * * Returns zero if f equals zero, otherwise f / content(f). * **/ CanonicalForm pp ( const CanonicalForm & f ) { if ( f.isZero() ) return f; else return f / content( f ); } CanonicalForm gcd ( const CanonicalForm & f, const CanonicalForm & g ) { bool b = f.isZero(); if ( b || g.isZero() ) { if ( b ) return abs( g ); else return abs( f ); } if ( f.inPolyDomain() || g.inPolyDomain() ) { if ( f.mvar() != g.mvar() ) { if ( f.mvar() > g.mvar() ) return cf_content( f, g ); else return cf_content( g, f ); } if (isOn(SW_USE_QGCD)) { Variable m; if ( (getCharacteristic() == 0) && (hasFirstAlgVar(f,m) || hasFirstAlgVar(g,m)) ) { bool on_rational = isOn(SW_RATIONAL); CanonicalForm r=QGCD(f,g); On(SW_RATIONAL); CanonicalForm cdF = bCommonDen( r ); if (!on_rational) Off(SW_RATIONAL); return cdF*r; } } if ( f.inExtension() && getReduce( f.mvar() ) ) return CanonicalForm(1); else { if ( fdivides( f, g ) ) return abs( f ); else if ( fdivides( g, f ) ) return abs( g ); if ( !( getCharacteristic() == 0 && isOn( SW_RATIONAL ) ) ) { CanonicalForm d; d = gcd_poly( f, g ); return abs( d ); } else { CanonicalForm cdF = bCommonDen( f ); CanonicalForm cdG = bCommonDen( g ); Off( SW_RATIONAL ); CanonicalForm l = lcm( cdF, cdG ); On( SW_RATIONAL ); CanonicalForm F = f * l, G = g * l; Off( SW_RATIONAL ); l = gcd_poly( F, G ); On( SW_RATIONAL ); return abs( l ); } } } if ( f.inBaseDomain() && g.inBaseDomain() ) return bgcd( f, g ); else return 1; } /** CanonicalForm lcm ( const CanonicalForm & f, const CanonicalForm & g ) * * lcm() - return least common multiple of f and g. * * The lcm is calculated using the formula lcm(f, g) = f * g / gcd(f, g). * * Returns zero if one of f or g equals zero. * **/ CanonicalForm lcm ( const CanonicalForm & f, const CanonicalForm & g ) { if ( f.isZero() || g.isZero() ) return 0; else return ( f / gcd( f, g ) ) * g; } singular-4.0.3+ds/factory/cf_generator.cc000066400000000000000000000103231266270727000203700ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "cf_generator.h" #include "imm.h" #include "gfops.h" #include "ffops.h" bool IntGenerator::hasItems() const { return 1; } CanonicalForm IntGenerator::item() const { return mapinto (CanonicalForm (current)); } void IntGenerator::next() { current++; } CFGenerator * IntGenerator::clone () const { return new IntGenerator(); } bool FFGenerator::hasItems() const { return current < ff_prime; } CanonicalForm FFGenerator::item() const { ASSERT( current < ff_prime, "no more items" ); return CanonicalForm( int2imm_p( current ) ); } void FFGenerator::next() { ASSERT( current < ff_prime, "no more items" ); current++; } CFGenerator * FFGenerator::clone () const { return new FFGenerator(); } GFGenerator::GFGenerator() { current = gf_zero(); } bool GFGenerator::hasItems() const { return ( current != gf_q + 1 ); } void GFGenerator::reset() { current = gf_zero(); } CanonicalForm GFGenerator::item() const { ASSERT( current != gf_q + 1, "no more items" ); return CanonicalForm( int2imm_gf( current ) ); } void GFGenerator::next() { ASSERT( current != gf_q + 1, "no more items" ); if ( gf_iszero( current ) ) current = 0; else if ( current == gf_q1 - 1 ) current = gf_q + 1; else current++; } CFGenerator * GFGenerator::clone () const { return new GFGenerator(); } AlgExtGenerator::AlgExtGenerator() { ASSERT( 0, "not a valid generator" ); } AlgExtGenerator::AlgExtGenerator( const AlgExtGenerator & ) { ASSERT( 0, "not a valid generator" ); } AlgExtGenerator& AlgExtGenerator::operator= ( const AlgExtGenerator & ) { ASSERT( 0, "not a valid generator" ); return *this; } AlgExtGenerator::AlgExtGenerator( const Variable & a ) { ASSERT( a.level() < 0, "not an algebraic extension" ); ASSERT( getCharacteristic() > 0, "not a finite field" ); algext = a; n = degree( getMipo( a ) ); if ( getGFDegree() > 1 ) { gensg = new GFGenerator * [n]; for ( int i = 0; i < n; i++ ) gensg[i] = new GFGenerator(); } else { gensf = new FFGenerator * [n]; for ( int i = 0; i < n; i++ ) gensf[i] = new FFGenerator(); } nomoreitems = false; } AlgExtGenerator::~AlgExtGenerator() { if ( getGFDegree() > 1 ) { for ( int i = 0; i < n; i++ ) delete gensg[i]; delete [] gensg; } else { for ( int i = 0; i < n; i++ ) delete gensf[i]; delete [] gensf; } } void AlgExtGenerator::reset() { if ( getGFDegree() > 1 ) { for ( int i = 0; i < n; i++ ) gensg[i]->reset(); } else { for ( int i = 0; i < n; i++ ) gensf[i]->reset(); } nomoreitems = false; } CanonicalForm AlgExtGenerator::item() const { ASSERT( ! nomoreitems, "no more items" ); CanonicalForm result = 0; if ( getGFDegree() > 1 ) { for ( int i = 0; i < n; i++ ) result += power( algext, i ) * gensg[i]->item(); } else { for ( int i = 0; i < n; i++ ) result += power( algext, i ) * gensf[i]->item(); } return result; } void AlgExtGenerator::next() { ASSERT( ! nomoreitems, "no more items" ); int i = 0; bool stop = false; if ( getGFDegree() > 1 ) { while ( ! stop && i < n ) { gensg[i]->next(); if ( ! gensg[i]->hasItems() ) { gensg[i]->reset(); i++; } else stop = true; } } else { while ( ! stop && i < n ) { gensf[i]->next(); if ( ! gensf[i]->hasItems() ) { gensf[i]->reset(); i++; } else stop = true; } } if ( ! stop ) nomoreitems = true; } CFGenerator * AlgExtGenerator::clone () const { return new AlgExtGenerator(algext); } CFGenerator * CFGenFactory::generate() { if (getCharacteristic() == 0) return new IntGenerator(); else if ( getGFDegree() > 1 ) return new GFGenerator(); else return new FFGenerator(); } singular-4.0.3+ds/factory/cf_generator.h000066400000000000000000000050241266270727000202340ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_generator.h * * generate integers, elements of finite fields **/ #ifndef INCL_CF_GENERATOR_H #define INCL_CF_GENERATOR_H // #include "config.h" #include "canonicalform.h" /*BEGINPUBLIC*/ /** * virtual class for generators **/ class CFGenerator { public: CFGenerator() {} virtual ~CFGenerator() {} virtual bool hasItems() const { return false; } virtual void reset() {}; virtual CanonicalForm item() const { return 0; } virtual void next() {}; virtual CFGenerator * clone() const { return new CFGenerator();} }; /** * generate integers starting from 0 **/ class IntGenerator : public CFGenerator { private: int current; public: IntGenerator() : current(0) {} ~IntGenerator() {} bool hasItems() const; void reset() { current = 0; } CanonicalForm item() const; void next(); void operator++ () { next(); } void operator++ ( int ) { next(); } CFGenerator * clone() const; }; /** * generate all elements in F_p starting from 0 **/ class FFGenerator : public CFGenerator { private: int current; public: FFGenerator() : current(0) {} ~FFGenerator() {} bool hasItems() const; void reset() { current = 0; } CanonicalForm item() const; void next(); void operator++ () { next(); } void operator++ ( int ) { next(); } CFGenerator * clone() const; }; /** * generate all elements in GF starting from 0 **/ class GFGenerator : public CFGenerator { private: int current; public: GFGenerator(); ~GFGenerator() {} bool hasItems() const; void reset(); CanonicalForm item() const; void next(); void operator++ () { next(); } void operator++ ( int ) { next(); } CFGenerator * clone() const; }; /** * generate all elements in F_p(alpha) starting from 0 **/ class AlgExtGenerator: public CFGenerator { private: Variable algext; FFGenerator **gensf; GFGenerator **gensg; int n; bool nomoreitems; AlgExtGenerator(); AlgExtGenerator( const AlgExtGenerator & ); AlgExtGenerator& operator= ( const AlgExtGenerator & ); public: AlgExtGenerator( const Variable & a ); ~AlgExtGenerator(); bool hasItems() const { return ! nomoreitems; } void reset(); CanonicalForm item() const; void next(); void operator++ () { next(); } void operator++ ( int ) { next(); } CFGenerator * clone() const; }; class CFGenFactory { public: static CFGenerator* generate(); }; /*ENDPUBLIC*/ #endif /* ! INCL_CF_GENERATOR_H */ singular-4.0.3+ds/factory/cf_globals.cc000066400000000000000000000017001266270727000200240ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_globals.cc * * definitions of global variables. * * Used by: canonicalform.cc, int_int.cc, ffops.h, imm.h * **/ #include "config.h" /** extern const char factoryVersion[]; * * factoryVersion - factory version string. * * factoryVersion is initialized from #define FACTORYVERSION * which is defined in config.h. It is not used in factory * itself. * **/ extern const char factoryVersion[] = "@(#) factoryVersion = " FACTORYVERSION; /** extern const char factoryConfiguration[]; * * factoryConfiguration - factory configuration. * * factoryConfiguration is initialized from #define * FACTORYCONFIGURATION which is defined in config.h. It is set * to the option configure was called with plus the directory it * was called in. It is not used in factory itself. * **/ extern const char factoryConfiguration[] = "@(#) factoryConfiguration = " FACTORYCONFIGURATION; singular-4.0.3+ds/factory/cf_globals.h000066400000000000000000000005571266270727000176770ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #ifndef INCL_CF_GLOBALS_H #define INCL_CF_GLOBALS_H //{{{ docu // // cf_globals.h - header to cf_globals.cc. // //}}} // #include "config.h" #include "cf_switches.h" /*BEGINPUBLIC*/ extern const char factoryVersion[]; extern const char factoryConfiguration[]; /*ENDPUBLIC*/ #endif /* ! INCL_CF_GLOBALS_H */ singular-4.0.3+ds/factory/cf_hnf.cc000066400000000000000000000023501266270727000171560ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_hnf.cc * * HNF/LLL of NTL * * Header file: cf_hnf.h * **/ #include "config.h" #ifdef HAVE_NTL #include "NTLconvert.h" #include "canonicalform.h" #include "cf_defs.h" #include "cf_hnf.h" #include #include #include /** * The input matrix A is an n x m matrix of rank m (so n >= m), and D * is a multiple of the determinant of the lattice L spanned by the * rows of A. W is computed as the Hermite Normal Form of A; that is, * W is the unique m x m matrix whose rows span L, such that * * - W is lower triangular, * - the diagonal entries are positive, * - any entry below the diagonal is a non-negative number * strictly less than the diagonal entry in its column. * **/ CFMatrix* cf_HNF(CFMatrix& A) { mat_ZZ *AA=convertFacCFMatrix2NTLmat_ZZ(A); ZZ DD=convertFacCF2NTLZZ(determinant(A,A.rows())); mat_ZZ WW; HNF(WW,*AA,DD); delete AA; return convertNTLmat_ZZ2FacCFMatrix(WW); } CFMatrix* cf_LLL(CFMatrix& A) { mat_ZZ *AA=convertFacCFMatrix2NTLmat_ZZ(A); #if 0 LLL_RR(*AA); #else ZZ det2; LLL(det2,*AA,0L); #endif CFMatrix *r= convertNTLmat_ZZ2FacCFMatrix(*AA); delete AA; return r; } #endif singular-4.0.3+ds/factory/cf_hnf.h000066400000000000000000000024611266270727000170230ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #ifndef CF_HNF_H #define CF_HNF_H /*BEGINPUBLIC*/ #ifdef HAVE_NTL /** * * The input matrix A is square matrix of integers * output: the Hermite Normal Form of A; that is, * the unique m x m matrix whose rows span L, such that * * - lower triangular, * - the diagonal entries are positive, * - any entry below the diagonal is a non-negative number * strictly less than the diagonal entry in its column. * * @note: uses NTL * **/ CFMatrix* cf_HNF(CFMatrix& A); /** * performs LLL reduction. * * B is an m x n matrix, viewed as m rows of n-vectors. m may be less * than, equal to, or greater than n, and the rows need not be * linearly independent. B is transformed into an LLL-reduced basis, * and the return value is the rank r of B. The first m-r rows of B * are zero. * * More specifically, elementary row transformations are performed on * B so that the non-zero rows of new-B form an LLL-reduced basis * for the lattice spanned by the rows of old-B. * The default reduction parameter is delta=3/4, which means * that the squared length of the first non-zero basis vector * is no more than 2^{r-1} times that of the shortest vector in * the lattice. * * @note: uses NTL **/ CFMatrix* cf_LLL(CFMatrix& A); #endif /*ENDPUBLIC*/ #endif singular-4.0.3+ds/factory/cf_inline.cc000066400000000000000000000353021266270727000176640ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_inline.cc * * definition of configurable inline * `CanonicalForm' methods. * * Hierarchy: canonicalform * * Header file: canonicalform.h * * Developers note: * ---------------- * The central class in Factory is, of course, `CanonicalForm'. * Hence it is a quiet reasonable to assume that inlining its * most important methods will improve execution speed. The same * holds for some methods of the `CFIterator' class. Everything * on configurable inline `CanonicalForm' methods explained here * applies mutatis mutandis to the `CFIterator' methods. * * However, inlining `CanonicalForm' methods has two major * drawbacks: * * o If `CanonicalForm' methods simply would have been declared * `inline' it would have been necessary to include the * definition of `InternalCF' in `factory.h'. This would have * been quite a contradiction to the internal nature of the * class. * Hence it seemed desirable to introduce a mechanism to have * both the inlined versions for internal use and compiled * versions for the library. * * o Second, inlining in most cases leads to larger object code. * E.g., inlining `CanonicalForm::~CanonicalForm()' increases the * object code by approx. 15% without any effect on computation * speed. * Thus another design aim was to keep things configurable. * That is why the methods defined here are called * "configurable inline methods". * * The low level solution to both problems is the macro * `CF_INLINE' which either expands to `inline' or nothing. The * counterpart `CF_NO_INLINE' exists only for convenience, it * always expands to nothing. `CF_INLINE' is set immediately * before defining resp. declaring the methods to exclude any * esoteric influences from included files. * * The high level interface is the macro `CF_USE_INLINE'. If it * is defined any header file that uses configurable inline * methods defines them to be `inline', otherwise they are * defined as ordinary methods. `CF_USE_INLINE' is defined in * `config.h' only. * * To switch on (off) all configurable inline methods, it is * sufficient to define (undefine) `CF_USE_INLINE' in `config.h'. * To switch off separate configurable inline methods it is * necessary to prefix their declaration in `canonicalform.h' by * `CF_NO_INLINE' instead of `CF_INLINE'. Furthermore, to avoid * duplicate symbols at link time, their definition in this file * has to be wrapped by an `#ifndef INCL_CF_INLINE_CC'. * * It turned out that inlining the following methods (and only * them) results in the best time to size ratio on Linux and HP * machines: * o all `CanonicalForm' constructors * o the binary `CanonicalForm' operators `+' and `*' * **/ // check whether we are included or translated and // define `INCL_CF_INLINE_CC' if we are included #ifdef INCL_CANONICALFORM_H #define INCL_CF_INLINE_CC #endif #include "config.h" #include "cf_assert.h" // temporarily switch off `CF_USE_INLINE' and include // `canonicalform.h' if we are being translated. // `CF_USE_INLINE_SAVE' is used to save the state of // `CF_USE_INLINE'. It is unset after use. #ifndef INCL_CF_INLINE_CC #ifdef CF_USE_INLINE #define CF_USE_INLINE_SAVE #undef CF_USE_INLINE #endif #include "canonicalform.h" #ifdef CF_USE_INLINE_SAVE #define CF_USE_INLINE #undef CF_USE_INLINE_SAVE #endif #endif /* ! INCL_CF_INLINE_CC */ // regular include files #include "int_cf.h" #include "imm.h" #include "cf_factory.h" // set the value of `CF_INLINE' for the following methods and // functions #if defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC ) #undef CF_INLINE #define CF_INLINE inline #else #undef CF_INLINE #define CF_INLINE #endif /* ! defined( CF_USE_INLINE ) && defined( INCL_CF_INLINE_CC ) */ // constructors, destructors, assignment /** CF_INLINE CanonicalForm::CanonicalForm () * * * CanonicalForm() - create the default canonical form. * * The canonical form is initialized to zero from the current * domain. * **/ CF_INLINE CanonicalForm::CanonicalForm () : value( CFFactory::basic( (long)0 ) ) { } /** CF_INLINE CanonicalForm::CanonicalForm ( const int i ) * * * CanonicalForm() - create a canonical form from an integer. * * The canonical form is initialized to the "canonical image" of * `i' in the current domain. This is `i' itself for * characteristic zero, `i' mod p for finite fields of * characteristic p, and `i' mod p^n for prime power domains with * p^n elements. * **/ CF_INLINE CanonicalForm::CanonicalForm ( const int i ) : value( CFFactory::basic( (long)i ) ) { } CF_INLINE CanonicalForm::CanonicalForm ( const long i ) : value( CFFactory::basic( i ) ) { } /** CF_INLINE CanonicalForm::CanonicalForm ( const CanonicalForm & cf ) * * * CanonicalForm() - create a copy of a canonical form. * * Type info: * ---------- * cf: Anything * **/ CF_INLINE CanonicalForm::CanonicalForm ( const CanonicalForm & cf ) : value( is_imm( cf.value ) ? cf.value : cf.value->copyObject() ) { } /** CF_INLINE CanonicalForm::CanonicalForm ( InternalCF * cf ) * * * CanonicalForm() - create a canonical form from a pointer to an * internal canonical form. * * This constructor is reserved for internal usage. * * Developers note: * ---------------- * The canonical form gets its value immediately from `cf'. * `cf's reference counter is not incremented, so be careful with * this constructor. * **/ CF_INLINE CanonicalForm::CanonicalForm ( InternalCF * cf ) : value( cf ) { } /** CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v ) * * * CanonicalForm() - create a canonical form from a variable. * * If `v' is a polynomial variable or an algebraic element the * resulting polynomial (or algebraic element) is 1*`v'^1, the * one being from the current domain. * * Variables of level `LEVELBASE' are transformed to one from the * current domain. * * Type info: * ---------- * v: Anything * **/ CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v ) : value( CFFactory::poly( v ) ) { } /** CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v, int e ) * * * CanonicalForm() - create a canonical form from a power of a * variable. * * If `v' is a polynomial variable or an algebraic element the * resulting polynomial (or algebraic element) is 1*`v'^`e', the * one being from the current domain. Algebraic elements are * reduced modulo their minimal polynomial. * * Variables of level `LEVELBASE' are transformed to one from the * current domain. * * Type info: * ---------- * v: Anything * **/ CF_INLINE CanonicalForm::CanonicalForm ( const Variable & v, int e ) : value( CFFactory::poly( v, e ) ) { //ASSERT( e > 0, "math error: exponent has to be positive" ); } #ifndef INCL_CF_INLINE_CC /** CF_INLINE CanonicalForm::~CanonicalForm () * * * ~CanonicalForm() - delete CO. * * Type info: * ---------- * CO: Anything * **/ CF_INLINE CanonicalForm::~CanonicalForm () { if ( (! is_imm( value )) && value->deleteObject() ) delete value; } #endif #ifndef INCL_CF_INLINE_CC /** CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf ) * * * operator =() - assign `cf' to CO. * * Type info: * ---------- * CO, cf: Anything * **/ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const CanonicalForm & cf ) { if ( this != &cf ) { if ( (! is_imm( value )) && value->deleteObject() ) delete value; value = (is_imm( cf.value )) ? cf.value : cf.value->copyObject(); } return *this; } /** * * operator =() - assign long `cf' to CO. * * `cf' converted to a canonical form as described in the * canonical form constructor which creates a canonical form from * an integer. * * Type info: * ---------- * CO: Anything * * Developers note: * ---------------- * Strictly speaking, this operator is superfluous. The ordinary * assignment operator together with automatic conversion from * `int' to `CanonicalForm' would do the job, too. But this way * the common operation of assigning an integer is faster. * **/ CF_INLINE CanonicalForm & CanonicalForm::operator = ( const long cf ) { if ( (! is_imm( value )) && value->deleteObject() ) delete value; value = CFFactory::basic( cf ); return *this; } #endif // predicates #ifndef INCL_CF_INLINE_CC /** CF_INLINE bool CanonicalForm::isOne, isZero () const * * * isOne(), isZero() - test whether a `CanonicalForm' equals one * or zero, resp. * * The predicates `isOne()' and `isZero()' are much faster than * the comparison operators. Furthermore, a test `f.isZero()' is * independent from the current domain, whereas an expression * `f == 0' is not. * * Type info: * ---------- * CO: Anything * * Internal implementation: * ------------------------ * Note that only immediate objects and objects of class * `InternalPrimePower' may equal one or zero, resp. * * imm_isone(), imm_iszero() * Trivial. * * imm_isone_p(), imm_iszero_p() * Trivial. * * imm_isone_gf(), imm_iszero_gf() * Use `gf_isone()' and `gf_iszero()', resp., to test whether CO * equals zero or one, resp. * * InternalCF::isOne(), isZero() * Always return false. * * InternalPrimePower::isOne(), isZero() * Use `mpz_cpm_ui()' resp. `mpz_sgn()' to check the underlying * mpi. * * @sa CanonicalForm::isZero() **/ CF_INLINE bool CanonicalForm::isOne () const { int what = is_imm( value ); if ( ! what ) return value->isOne(); else if ( what == INTMARK ) return imm_isone( value ); else if ( what == FFMARK ) return imm_isone_p( value ); else return imm_isone_gf( value ); } /** * @sa CanonicalForm::isOne() **/ CF_INLINE bool CanonicalForm::isZero () const { int what = is_imm( value ); if ( what == 0 ) return value->isZero(); else if ( what == INTMARK ) return imm_iszero( value ); else if ( what == FFMARK ) return imm_iszero_p( value ); else return imm_iszero_gf( value ); } #endif // arithmetic operators #ifndef INCL_CF_INLINE_CC /** CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf ) * * * operator -() - return additive inverse of `cf'. * * Returns the additive inverse of `cf'. One should keep in mind * that to negate a canonical form a complete (deep) copy of it * has to be created. * * Type info: * ---------- * cf: CurrentPP * * In fact, the type is almost `Anything', but it is, e.g., not * possible to invert an element from a finite field when the * characteristic of the current domain has changed. * * Internal implementation: * ------------------------ * All internal methods check whether the reference counter * equals one. If so CO is negated in-place. Otherwise, a new * copy of CO is created and negated. * * imm_neg() * Trivial. * * imm_neg_p() * Use `ff_neg()' to negate CO. * * imm_neg_gf() * Use `gf_neg()' to negate CO. * * InternalInteger::neg() * Use `mpz_neg()' to negate the underlying mpi. * * InternalRational::neg () * Use `mpz_neg()' to negate the denominator. * * InternalPrimePower::neg() * Subtract CO from `primepow' using `mpz_sub'. * * InternalPoly::neg() * If reference counter is one use `negateTermList()' to negate * the terms, otherwise create a negated copy using * `copyTermList()'. * * @sa CanonicalForm::operator -=() **/ CF_INLINE CanonicalForm operator - ( const CanonicalForm & cf ) { CanonicalForm result( cf ); int what = is_imm( result.value ); if ( ! what ) result.value = result.value->neg(); else if ( what == INTMARK ) result.value = imm_neg( result.value ); else if ( what == FFMARK ) result.value = imm_neg_p( result.value ); else result.value = imm_neg_gf( result.value ); return result; } #endif // binary arithmetic operators and functions /** CF_INLINE CanonicalForm operator +, -, *, /, % ( const CanonicalForm & lhs, const CanonicalForm & rhs ) * * * operators +, -, *, /, %(), div(), mod() - binary arithmetic * operators. * * The binary operators have their standard (mathematical) * semantics. As explained for the corresponding arithmetic * assignment operators, the operators `/' and `%' return the * quotient resp. remainder of (polynomial) division with * remainder, whereas `div()' and `mod()' may be used for exact * division and term-wise remaindering, resp. * * It is faster to use the arithmetic assignment operators (e.g., * `f += g;') instead of the binary operators (`f = f+g;' ). * * Type info: * ---------- * lhs, rhs: CurrentPP * * There are weaker preconditions for some cases (e.g., * arithmetic operations with elements from Q or Z work in any * domain), but type `CurrentPP' is the only one guaranteed to * work for all cases. * * Developers note: * ---------------- * All binary operators have their corresponding `CanonicalForm' * assignment operators (e.g., `operator +()' corresponds to * `CanonicalForm::operator +=()', `div()' corresponds to * `CanonicalForm::div()). * * And that is how they are implemented, too: Each of the binary * operators first creates a copy of `lhs', adds `rhs' to this * copy using the assignment operator, and returns the result. * * @sa CanonicalForm::operator +=() **/ CF_INLINE CanonicalForm operator + ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { CanonicalForm result( lhs ); result += rhs; return result; } #ifndef INCL_CF_INLINE_CC CF_INLINE CanonicalForm operator - ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { CanonicalForm result( lhs ); result -= rhs; return result; } #endif /** * @sa CanonicalForm::operator *=() **/ CF_INLINE CanonicalForm operator * ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { CanonicalForm result( lhs ); result *= rhs; return result; } #ifndef INCL_CF_INLINE_CC /** * @sa CanonicalForm::operator /=() **/ CF_INLINE CanonicalForm operator / ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { CanonicalForm result( lhs ); result /= rhs; return result; } /** * @sa CanonicalForm::operator %=() **/ CF_INLINE CanonicalForm operator % ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { CanonicalForm result( lhs ); result %= rhs; return result; } #endif #ifndef INCL_CF_INLINE_CC /** CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs ) * @sa mod(), operator/(), CanonicalForm::operator /=() **/ CF_INLINE CanonicalForm div ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { CanonicalForm result( lhs ); result.div( rhs ); return result; } /** * @sa div(), operator%(), CanonicalForm::operator %=() **/ CF_INLINE CanonicalForm mod ( const CanonicalForm & lhs, const CanonicalForm & rhs ) { CanonicalForm result( lhs ); result.mod( rhs ); return result; } #endif singular-4.0.3+ds/factory/cf_irred.cc000066400000000000000000000022051266270727000175070ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "canonicalform.h" #include "cf_algorithm.h" #include "cf_random.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif static bool is_irreducible ( const CanonicalForm & f ) { CFFList F = factorize( f ); return F.length() == 1 && F.getFirst().exp() == 1; } CanonicalForm find_irreducible ( int deg, CFRandom & gen, const Variable & x ) { CanonicalForm result; int i; do { result = power( x, deg ); for ( i = deg-1; i >= 0; i-- ) result += gen.generate() * power( x, i ); } while ( ! is_irreducible( result ) ); return result; } #ifdef HAVE_NTL /// computes a random monic irreducible univariate polynomial in x over Fp of /// degree i via NTL CanonicalForm randomIrredpoly (int i, const Variable & x) { int p= getCharacteristic(); if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } zz_pX NTLirredpoly; CanonicalForm CFirredpoly; BuildIrred (NTLirredpoly, i); CFirredpoly= convertNTLzzpX2CF (NTLirredpoly, x); return CFirredpoly; } #endif singular-4.0.3+ds/factory/cf_irred.h000066400000000000000000000011331266270727000173500ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_irred.h * * generate random irreducible univariate polynomials **/ #ifndef INCL_CF_IRRED_H #define INCL_CF_IRRED_H // #include "config.h" #include "canonicalform.h" #include "cf_random.h" /** generate a random irreducible polynomial in x of degree deg * * @warning this is done in the most naive way, i.e. a random is generated and * then factorized **/ CanonicalForm find_irreducible ( int deg, CFRandom & gen, const Variable & x ); CanonicalForm randomIrredpoly (int i, const Variable & x); #endif /* ! INCL_CF_IRRED_H */ singular-4.0.3+ds/factory/cf_iter.cc000066400000000000000000000045311266270727000173510ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "cf_iter.h" #include "int_cf.h" #include "int_poly.h" CFIterator::CFIterator() { data = 0; cursor = 0; ispoly = false; hasterms = false; } CFIterator::CFIterator( const CFIterator & i ) { data = i.data; cursor = i.cursor; ispoly = i.ispoly; hasterms = i.hasterms; } CFIterator::CFIterator( const CanonicalForm & f ) { if ( f.inBaseDomain() || f.inQuotDomain() ) { data = f; cursor = 0; ispoly = false; hasterms = true; } else { data = f; cursor = ((InternalPoly*)(f.value))->firstTerm; ispoly = true; hasterms = true; } } CFIterator::CFIterator( const CanonicalForm & f, const Variable & v ) { ASSERT( !f.inQuotDomain(), "illegal iterator" ); ASSERT( v.level() > 0, "illegal iterator" ); if ( f.inBaseDomain() ) { data = f; cursor = 0; ispoly = false; hasterms = true; } else { if ( f.mvar() == v ) { data = f; cursor = ((InternalPoly*)(f.value))->firstTerm; ispoly = true; hasterms = true; } else if ( v > f.mvar() ) { data = f; cursor = 0; ispoly = false; hasterms = true; } else { data = swapvar( f, v, f.mvar().next() ); if ( data.mvar() == f.mvar().next() ) { cursor = ((InternalPoly*)(data.value))->firstTerm; ispoly = true; hasterms = true; } else { cursor = 0; ispoly = false; hasterms = true; } } } } CFIterator::~CFIterator() { data = 0; cursor = 0; } CFIterator& CFIterator::operator= ( const CFIterator & i ) { if ( this != &i ) { data = i.data; cursor = i.cursor; ispoly = i.ispoly; hasterms = i.hasterms; } return *this; } CFIterator& CFIterator::operator= ( const CanonicalForm & f ) { if ( f.inBaseDomain() || f.inQuotDomain() ) { data = f; cursor = 0; ispoly = false; hasterms = true; } else { data = f; cursor = ((InternalPoly*)(f.value))->firstTerm; ispoly = true; hasterms = true; } return *this; } singular-4.0.3+ds/factory/cf_iter.h000066400000000000000000000030101266270727000172020ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_iter.h * * Iterators for CanonicalForm's **/ #ifndef INCL_CF_ITER_H #define INCL_CF_ITER_H // #include "config.h" #include "canonicalform.h" /*BEGINPUBLIC*/ #undef CF_INLINE #define CF_INLINE #undef CF_NO_INLINE #define CF_NO_INLINE /*ENDPUBLIC*/ #ifdef CF_USE_INLINE #undef CF_INLINE #define CF_INLINE inline #else #undef CF_INLINE #define CF_INLINE #endif /*BEGINPUBLIC*/ class term; typedef term * termList; /** * class to iterate through CanonicalForm's * * @note a (multivariate) polynomial is viewed as a univariate poly in its main * variable **/ class CFIterator { private: CanonicalForm data; termList cursor; bool ispoly, hasterms; public: CFIterator (); CFIterator ( const CFIterator& ); CFIterator ( const CanonicalForm& ); CFIterator ( const CanonicalForm&, const Variable& ); ~CFIterator (); CFIterator& operator= ( const CFIterator& ); CFIterator& operator= ( const CanonicalForm& ); CF_NO_INLINE CFIterator& operator++ (); CF_NO_INLINE CFIterator& operator++ ( int ); CF_NO_INLINE int hasTerms () const; ///< check if iterator has reached ///< the end of CanonicalForm CF_NO_INLINE CanonicalForm coeff () const;///< get the current coefficient CF_NO_INLINE int exp () const; ///< get the current exponent }; /*ENDPUBLIC*/ #ifdef CF_USE_INLINE #include "cf_iter_inline.cc" #endif #endif /* ! INCL_CF_ITER_H */ singular-4.0.3+ds/factory/cf_iter_inline.cc000066400000000000000000000063011266270727000207040ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_iter_inline.cc * * definition of configurable inline * `CFIterator' methods. * * Hierarchy: canonicalform, utility class * * Header file: cf_iter.h * * See `cf_inline.cc' for a description of "configurable inline * methods". * **/ // check whether we are included or translated and // define `INCL_CF_ITER_INLINE_CC' if we are included #ifdef INCL_CF_ITER_H #define INCL_CF_ITER_INLINE_CC #endif #include "config.h" #include "cf_assert.h" // regular include file #include "canonicalform.h" // temporarily switch off `CF_USE_INLINE' and include // `cf_iter.h' if we are being translated. // `CF_USE_INLINE_SAVE' is used to save the state of // `CF_USE_INLINE'. It is unset after use. #ifndef INCL_CF_ITER_INLINE_CC #ifdef CF_USE_INLINE #define CF_USE_INLINE_SAVE #undef CF_USE_INLINE #endif #include "cf_iter.h" #ifdef CF_USE_INLINE_SAVE #define CF_USE_INLINE #undef CF_USE_INLINE_SAVE #endif #endif /* ! INCL_CF_ITER_INLINE_CC */ // more regular include files #include "int_cf.h" #include "int_poly.h" // set the value of `CF_INLINE' for the following methods and // functions #if defined( CF_USE_INLINE ) && defined( INCL_CF_ITER_INLINE_CC ) #undef CF_INLINE #define CF_INLINE inline #else #undef CF_INLINE #define CF_INLINE #endif /* ! defined( CF_USE_INLINE ) && defined( INCL_CF_ITER_INLINE_CC ) */ #ifndef INCL_CF_ITER_INLINE_CC // selectors /** CF_INLINE int CFIterator::hasTerms () const * * hasTerm() - check whether CO points to a valid term. * * Return true if CO points to a valid term, false if CO points * to the end of the sequence of terms. * **/ CF_INLINE int CFIterator::hasTerms () const { return hasterms; } /** CF_INLINE CanonicalForm CFIterator::coeff () const * * coeff() - return coefficient of current term of CO. * * CO has to point to a valid term. * **/ CF_INLINE CanonicalForm CFIterator::coeff () const { ASSERT( hasterms, "lib error: iterator out of terms" ); if ( ispoly ) return cursor->coeff; else return data; } /** CF_INLINE int CFIterator::exp () const * * exp() - return exponent of current term of CO. * * CO has to point to a valid term. * **/ CF_INLINE int CFIterator::exp () const { ASSERT( hasterms, "lib error: iterator out of terms" ); if ( ispoly ) return cursor->exp; else return 0; } // implementor methods /** CFIterator::operator ++ (), operator ++ ( int ) * * operator ++() - advance CO to next term. * * Advance current term to next term in the sequence of terms or * to end of sequence. CO has to point to a valid term. * * The postfix and prefix operator are identical. * **/ CF_INLINE CFIterator & CFIterator::operator ++ () { ASSERT( hasterms, "lib error: iterator out of terms" ); if ( ispoly ) { cursor = cursor->next; hasterms = cursor != 0; } else hasterms = false; return *this; } /** * @sa CFIterator::operator **/ CF_INLINE CFIterator & CFIterator::operator ++ ( int ) { ASSERT( hasterms, "lib error: iterator out of terms" ); if ( ispoly ) { cursor = cursor->next; hasterms = cursor != 0; } else hasterms = false; return *this; } #endif singular-4.0.3+ds/factory/cf_linsys.cc000066400000000000000000000426341266270727000177350ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_linsys.cc * * solve linear systems and compute determinants of matrices **/ #include "config.h" #include "cf_assert.h" #include "debug.h" #include "timing.h" #include "cf_defs.h" #include "cf_primes.h" #include "canonicalform.h" #include "cf_iter.h" #include "cf_algorithm.h" #include "ffops.h" #include "cf_primes.h" TIMING_DEFINE_PRINT(det_mapping) TIMING_DEFINE_PRINT(det_determinant) TIMING_DEFINE_PRINT(det_chinese) TIMING_DEFINE_PRINT(det_bound) TIMING_DEFINE_PRINT(det_numprimes) static bool solve ( int **extmat, int nrows, int ncols ); int determinant ( int **extmat, int n ); static CanonicalForm bound ( const CFMatrix & M ); CanonicalForm detbound ( const CFMatrix & M, int rows ); bool matrix_in_Z( const CFMatrix & M, int rows ) { int i, j; for ( i = 1; i <= rows; i++ ) for ( j = 1; j <= rows; j++ ) if ( ! M(i,j).inZ() ) return false; return true; } bool matrix_in_Z( const CFMatrix & M ) { int i, j, rows = M.rows(), cols = M.columns(); for ( i = 1; i <= rows; i++ ) for ( j = 1; j <= cols; j++ ) if ( ! M(i,j).inZ() ) return false; return true; } bool betterpivot ( const CanonicalForm & oldpivot, const CanonicalForm & newpivot ) { if ( newpivot.isZero() ) return false; else if ( oldpivot.isZero() ) return true; else if ( level( oldpivot ) > level( newpivot ) ) return true; else if ( level( oldpivot ) < level( newpivot ) ) return false; else return ( newpivot.lc() < oldpivot.lc() ); } bool fuzzy_result; bool linearSystemSolve( CFMatrix & M ) { typedef int* int_ptr; if ( ! matrix_in_Z( M ) ) { int nrows = M.rows(), ncols = M.columns(); int i, j, k; CanonicalForm rowpivot, pivotrecip; // triangularization for ( i = 1; i <= nrows; i++ ) { //find "pivot" for (j = i; j <= nrows; j++ ) if ( M(j,i) != 0 ) break; if ( j > nrows ) return false; if ( j != i ) M.swapRow( i, j ); pivotrecip = 1 / M(i,i); for ( j = 1; j <= ncols; j++ ) M(i,j) *= pivotrecip; for ( j = i+1; j <= nrows; j++ ) { rowpivot = M(j,i); if ( rowpivot == 0 ) continue; for ( k = i; k <= ncols; k++ ) M(j,k) -= M(i,k) * rowpivot; } } // matrix is now upper triangular with 1s down the diagonal // back-substitute for ( i = nrows-1; i > 0; i-- ) { for ( j = nrows+1; j <= ncols; j++ ) { for ( k = i+1; k <= nrows; k++ ) M(i,j) -= M(k,j) * M(i,k); } } return true; } else { int rows = M.rows(), cols = M.columns(); CFMatrix MM( rows, cols ); int ** mm = new int_ptr[rows]; CanonicalForm Q, Qhalf, mnew, qnew, B; int i, j, p, pno; bool ok; // initialize room to hold the result and the result mod p for ( i = 0; i < rows; i++ ) { mm[i] = new int[cols]; } // calculate the bound for the result B = bound( M ); DEBOUTLN( cerr, "bound = " << B ); // find a first solution mod p pno = 0; do { DEBOUTSL( cerr ); DEBOUT( cerr, "trying prime(" << pno << ") = " ); p = cf_getBigPrime( pno ); DEBOUT( cerr, p ); DEBOUTENDL( cerr ); setCharacteristic( p ); // map matrix into char p for ( i = 1; i <= rows; i++ ) for ( j = 1; j <= cols; j++ ) mm[i-1][j-1] = mapinto( M(i,j) ).intval(); // solve mod p ok = solve( mm, rows, cols ); pno++; } while ( ! ok ); // initialize the result matrix with first solution setCharacteristic( 0 ); for ( i = 1; i <= rows; i++ ) for ( j = rows+1; j <= cols; j++ ) MM(i,j) = mm[i-1][j-1]; // Q so far Q = p; while ( Q < B && pno < cf_getNumBigPrimes() ) { do { DEBOUTSL( cerr ); DEBOUT( cerr, "trying prime(" << pno << ") = " ); p = cf_getBigPrime( pno ); DEBOUT( cerr, p ); DEBOUTENDL( cerr ); setCharacteristic( p ); for ( i = 1; i <= rows; i++ ) for ( j = 1; j <= cols; j++ ) mm[i-1][j-1] = mapinto( M(i,j) ).intval(); // solve mod p ok = solve( mm, rows, cols ); pno++; } while ( ! ok ); // found a solution mod p // now chinese remainder it to a solution mod Q*p setCharacteristic( 0 ); for ( i = 1; i <= rows; i++ ) for ( j = rows+1; j <= cols; j++ ) { chineseRemainder( MM[i][j], Q, CanonicalForm(mm[i-1][j-1]), CanonicalForm(p), mnew, qnew ); MM(i, j) = mnew; } Q = qnew; } if ( pno == cf_getNumBigPrimes() ) fuzzy_result = true; else fuzzy_result = false; // store the result in M Qhalf = Q / 2; for ( i = 1; i <= rows; i++ ) { for ( j = rows+1; j <= cols; j++ ) if ( MM(i,j) > Qhalf ) M(i,j) = MM(i,j) - Q; else M(i,j) = MM(i,j); delete [] mm[i-1]; } delete [] mm; return ! fuzzy_result; } } static bool fill_int_mat( const CFMatrix & M, int ** m, int rows ) { int i, j; bool ok = true; for ( i = 0; i < rows && ok; i++ ) for ( j = 0; j < rows && ok; j++ ) { if ( M(i+1,j+1).isZero() ) m[i][j] = 0; else { m[i][j] = mapinto( M(i+1,j+1) ).intval(); // ok = m[i][j] != 0; } } return ok; } CanonicalForm determinant( const CFMatrix & M, int rows ) { typedef int* int_ptr; ASSERT( rows <= M.rows() && rows <= M.columns() && rows > 0, "undefined determinant" ); if ( rows == 1 ) return M(1,1); else if ( rows == 2 ) return M(1,1)*M(2,2)-M(2,1)*M(1,2); else if ( matrix_in_Z( M, rows ) ) { int ** mm = new int_ptr[rows]; CanonicalForm x, q, Qhalf, B; int n, i, intdet, p, pno; for ( i = 0; i < rows; i++ ) { mm[i] = new int[rows]; } pno = 0; n = 0; TIMING_START(det_bound); B = detbound( M, rows ); TIMING_END(det_bound); q = 1; TIMING_START(det_numprimes); while ( B > q && n < cf_getNumBigPrimes() ) { q *= cf_getBigPrime( n ); n++; } TIMING_END(det_numprimes); CFArray X(1,n), Q(1,n); while ( pno < n ) { p = cf_getBigPrime( pno ); setCharacteristic( p ); // map matrix into char p TIMING_START(det_mapping); fill_int_mat( M, mm, rows ); TIMING_END(det_mapping); pno++; DEBOUT( cerr, "." ); TIMING_START(det_determinant); intdet = determinant( mm, rows ); TIMING_END(det_determinant); setCharacteristic( 0 ); X[pno] = intdet; Q[pno] = p; } TIMING_START(det_chinese); chineseRemainder( X, Q, x, q ); TIMING_END(det_chinese); Qhalf = q / 2; if ( x > Qhalf ) x = x - q; for ( i = 0; i < rows; i++ ) delete [] mm[i]; delete [] mm; return x; } else { CFMatrix m( M ); CanonicalForm divisor = 1, pivot, mji; int i, j, k, sign = 1; for ( i = 1; i <= rows; i++ ) { pivot = m(i,i); k = i; for ( j = i+1; j <= rows; j++ ) { if ( betterpivot( pivot, m(j,i) ) ) { pivot = m(j,i); k = j; } } if ( pivot.isZero() ) return 0; if ( i != k ) { m.swapRow( i, k ); sign = -sign; } for ( j = i+1; j <= rows; j++ ) { if ( ! m(j,i).isZero() ) { divisor *= pivot; mji = m(j,i); m(j,i) = 0; for ( k = i+1; k <= rows; k++ ) m(j,k) = m(j,k) * pivot - m(i,k)*mji; } } } pivot = sign; for ( i = 1; i <= rows; i++ ) pivot *= m(i,i); return pivot / divisor; } } CanonicalForm determinant2( const CFMatrix & M, int rows ) { typedef int* int_ptr; ASSERT( rows <= M.rows() && rows <= M.columns() && rows > 0, "undefined determinant" ); if ( rows == 1 ) return M(1,1); else if ( rows == 2 ) return M(1,1)*M(2,2)-M(2,1)*M(1,2); else if ( matrix_in_Z( M, rows ) ) { int ** mm = new int_ptr[rows]; CanonicalForm QQ, Q, Qhalf, mnew, q, qnew, B; CanonicalForm det, detnew, qdet; int i, p, pcount, pno, intdet; bool ok; // initialize room to hold the result and the result mod p for ( i = 0; i < rows; i++ ) { mm[i] = new int[rows]; } // calculate the bound for the result B = detbound( M, rows ); // find a first solution mod p pno = 0; do { p = cf_getBigPrime( pno ); setCharacteristic( p ); // map matrix into char p ok = fill_int_mat( M, mm, rows ); pno++; } while ( ! ok && pno < cf_getNumPrimes() ); // initialize the result matrix with first solution // solve mod p DEBOUT( cerr, "." ); intdet = determinant( mm, rows ); setCharacteristic( 0 ); det = intdet; // Q so far Q = p; QQ = p; while ( Q < B && cf_getNumPrimes() > pno ) { // find a first solution mod p do { p = cf_getBigPrime( pno ); setCharacteristic( p ); // map matrix into char p ok = fill_int_mat( M, mm, rows ); pno++; } while ( ! ok && pno < cf_getNumPrimes() ); // initialize the result matrix with first solution // solve mod p DEBOUT( cerr, "." ); intdet = determinant( mm, rows ); setCharacteristic( 0 ); qdet = intdet; // Q so far q = p; QQ *= p; pcount = 0; while ( QQ < B && cf_getNumPrimes() > pno && pcount < 500 ) { do { p = cf_getBigPrime( pno ); setCharacteristic( p ); ok = true; // map matrix into char p ok = fill_int_mat( M, mm, rows ); pno++; } while ( ! ok && cf_getNumPrimes() > pno ); // solve mod p DEBOUT( cerr, "." ); intdet = determinant( mm, rows ); // found a solution mod p // now chinese remainder it to a solution mod Q*p setCharacteristic( 0 ); chineseRemainder( qdet, q, intdet, p, detnew, qnew ); qdet = detnew; q = qnew; QQ *= p; pcount++; } DEBOUT( cerr, "*" ); chineseRemainder( det, Q, qdet, q, detnew, qnew ); Q = qnew; QQ = Q; det = detnew; } if ( ! ok ) fuzzy_result = true; else fuzzy_result = false; // store the result in M Qhalf = Q / 2; if ( det > Qhalf ) det = det - Q; for ( i = 0; i < rows; i++ ) delete [] mm[i]; delete [] mm; return det; } else { CFMatrix m( M ); CanonicalForm divisor = 1, pivot, mji; int i, j, k, sign = 1; for ( i = 1; i <= rows; i++ ) { pivot = m(i,i); k = i; for ( j = i+1; j <= rows; j++ ) { if ( betterpivot( pivot, m(j,i) ) ) { pivot = m(j,i); k = j; } } if ( pivot.isZero() ) return 0; if ( i != k ) { m.swapRow( i, k ); sign = -sign; } for ( j = i+1; j <= rows; j++ ) { if ( ! m(j,i).isZero() ) { divisor *= pivot; mji = m(j,i); m(j,i) = 0; for ( k = i+1; k <= rows; k++ ) m(j,k) = m(j,k) * pivot - m(i,k)*mji; } } } pivot = sign; for ( i = 1; i <= rows; i++ ) pivot *= m(i,i); return pivot / divisor; } } static CanonicalForm bound ( const CFMatrix & M ) { DEBINCLEVEL( cerr, "bound" ); int rows = M.rows(), cols = M.columns(); CanonicalForm sum = 0; int i, j; for ( i = 1; i <= rows; i++ ) for ( j = 1; j <= rows; j++ ) sum += M(i,j) * M(i,j); DEBOUTLN( cerr, "bound(matrix)^2 = " << sum ); CanonicalForm vmax = 0, vsum; for ( j = rows+1; j <= cols; j++ ) { vsum = 0; for ( i = 1; i <= rows; i++ ) vsum += M(i,j) * M(i,j); if ( vsum > vmax ) vmax = vsum; } DEBOUTLN( cerr, "bound(lhs)^2 = " << vmax ); sum += vmax; DEBOUTLN( cerr, "bound(overall)^2 = " << sum ); DEBDECLEVEL( cerr, "bound" ); return sqrt( sum ) + 1; } CanonicalForm detbound ( const CFMatrix & M, int rows ) { CanonicalForm sum = 0, prod = 2; int i, j; for ( i = 1; i <= rows; i++ ) { sum = 0; for ( j = 1; j <= rows; j++ ) sum += M(i,j) * M(i,j); prod *= 1 + sqrt(sum); } return prod; } // solve returns false if computation failed // extmat is overwritten: output is Id mat followed by solution(s) bool solve ( int **extmat, int nrows, int ncols ) { DEBINCLEVEL( cerr, "solve" ); int i, j, k; int rowpivot, pivotrecip; // all FF int * rowi; // FF int * rowj; // FF int * swap; // FF // triangularization for ( i = 0; i < nrows; i++ ) { //find "pivot" for (j = i; j < nrows; j++ ) if ( extmat[j][i] != 0 ) break; if ( j == nrows ) { DEBOUTLN( cerr, "solve failed" ); DEBDECLEVEL( cerr, "solve" ); return false; } if ( j != i ) { swap = extmat[i]; extmat[i] = extmat[j]; extmat[j] = swap; } pivotrecip = ff_inv( extmat[i][i] ); rowi = extmat[i]; for ( j = 0; j < ncols; j++ ) rowi[j] = ff_mul( pivotrecip, rowi[j] ); for ( j = i+1; j < nrows; j++ ) { rowj = extmat[j]; rowpivot = rowj[i]; if ( rowpivot == 0 ) continue; for ( k = i; k < ncols; k++ ) rowj[k] = ff_sub( rowj[k], ff_mul( rowpivot, rowi[k] ) ); } } // matrix is now upper triangular with 1s down the diagonal // back-substitute for ( i = nrows-1; i >= 0; i-- ) { rowi = extmat[i]; for ( j = 0; j < i; j++ ) { rowj = extmat[j]; rowpivot = rowj[i]; if ( rowpivot == 0 ) continue; for ( k = i; k < ncols; k++ ) rowj[k] = ff_sub( rowj[k], ff_mul( rowpivot, rowi[k] ) ); // for (k=nrows; k S"). * **/ OSTREAM & operator << ( OSTREAM & s, const MapPair & p ) { s << p.var() << " -> " << p.subst(); return s; } void MapPair::print( OSTREAM&) const { } #endif /* NOSTREAMIO */ /** CFMap::CFMap ( const CFList & L ) * * CFMap::CFMap() - construct a CFMap from a CFList. * * Variable[i] will be mapped to CFList[i] under the resulting * map. * **/ CFMap::CFMap ( const CFList & L ) { CFListIterator i; int j; for ( i = L, j = 1; i.hasItem(); i++, j++ ) P.insert( MapPair( Variable(j), i.getItem() ) ); } /** CFMap & CFMap::operator = ( const CFMap & m ) * * CFMap::operator = - assignment operator. * **/ CFMap & CFMap::operator = ( const CFMap & m ) { if ( this != &m ) P = m.P; return *this; } /** static int cmpfunc ( const MapPair & p1, const MapPair & p2 ) * * cmpfunc() - compare two map pairs. * * Return -1 if p2's variable is less than p1's, 0 if they are * equal, 1 if p2's level is greater than p1's. * **/ static int cmpfunc ( const MapPair & p1, const MapPair & p2 ) { if ( p1.var() > p2.var() ) return -1; else if ( p1.var() == p2.var() ) return 0; else return 1; } /** static void insfunc ( MapPair & orgp, const MapPair & newp ) * * insfunc() - assign newp to orgp. * * cmpfunc() and insfunc() are used as functions for inserting a * map pair into a map by CFMap::newpair(). * **/ static void insfunc ( MapPair & orgp, const MapPair & newp ) { orgp = newp; } /** void CFMap::newpair ( const Variable & v, const CanonicalForm & s ) * * CFMap::newpair() - insert a MapPair into a CFMap. * **/ void CFMap::newpair ( const Variable & v, const CanonicalForm & s ) { P.insert( MapPair( v, s ), cmpfunc, insfunc ); } /** static CanonicalForm subsrec ( const CanonicalForm & f, const MPListIterator & i ) * * subsrec() - recursively apply the substitutions in i to f. * * Substitutes algebraic variables, too. The substituted * expression are not subject to further substitutions. * * Used by: CFMap::operator ()(). * **/ static CanonicalForm subsrec ( const CanonicalForm & f, const MPListIterator & i ) { if ( f.inBaseDomain() ) return f; MPListIterator j = i; // skip MapPairs larger than the main variable of f while ( j.hasItem() && j.getItem().var() > f.mvar() ) j++; if ( j.hasItem() ) if ( j.getItem().var() != f.mvar() ) { // simply descend if the current MapPair variable is // not the main variable of f CanonicalForm result = 0; CFIterator I; for ( I = f; I.hasTerms(); I++ ) result += power( f.mvar(), I.exp() ) * subsrec( I.coeff(), j ); return result; } else { // replace the main variable of f with the image of // the current variable under MapPair CanonicalForm result = 0; CanonicalForm s = j.getItem().subst(); CFIterator I; // move on to the next MapPair j++; for ( I = f; I.hasTerms(); I++ ) result += subsrec( I.coeff(), j ) * power( s, I.exp() ); return result; } else return f; } /** CanonicalForm CFMap::operator () ( const CanonicalForm & f ) const * * CFMap::operator () - apply CO to f. * * See subsrec() for more detailed information. * **/ CanonicalForm CFMap::operator () ( const CanonicalForm & f ) const { MPListIterator i = P; return subsrec( f, i ); } #ifndef NOSTREAMIO /** OSTREAM & operator << ( OSTREAM & s, const CFMap & m ) * * operator << - print a CFMap ("( V[1] -> S[1], ..., V[n] -> * S[n] )". * **/ OSTREAM & operator << ( OSTREAM & s, const CFMap & m ) { m.P.print(s); return s; } #endif /* NOSTREAMIO */ /** CanonicalForm compress ( const CanonicalForm & f, CFMap & m ) * * compress() - compress the canonical form f. * * Compress the polynomial f such that the levels of its * polynomial variables are ordered without any gaps starting * from level 1. Return the compressed polynomial and a map m to * undo the compression. That is, if f' = compress(f, m), than f * = m(f'). * **/ CanonicalForm compress ( const CanonicalForm & f, CFMap & m ) { CanonicalForm result = f; int i, n; int * degs = degrees( f ); m = CFMap(); n = i = 1; while ( i <= level( f ) ) { while( degs[i] == 0 ) i++; if ( i != n ) { // swap variables and remember the swap in the map m.newpair( Variable( n ), Variable( i ) ); result = swapvar( result, Variable( i ), Variable( n ) ); } n++; i++; } delete [] degs; return result; } /** void compress ( const CFArray & a, CFMap & M, CFMap & N ) * * compress() - compress the variables occuring in an a. * * Compress the polynomial variables occuring in a so that their * levels are ordered without any gaps starting from level 1. * Return the CFMap M to realize the compression and its inverse, * the CFMap N. Note that if you compress a member of a using M * the result of the compression is not necessarily compressed, * since the map is constructed using all variables occuring in * a. * **/ void compress ( const CFArray & a, CFMap & M, CFMap & N ) { M = N = CFMap(); if ( a.size() == 0 ) return; int maxlevel = level( a[a.min()] ); int i, j; // get the maximum of levels in a for ( i = a.min() + 1; i <= a.max(); i++ ) if ( level( a[i] ) > maxlevel ) maxlevel = level( a[i] ); if ( maxlevel <= 0 ) return; int * degs = new int[maxlevel+1]; int * tmp = new int[maxlevel+1]; for ( i = 1; i <= maxlevel; i++ ) degs[i] = 0; // calculate the union of all levels occuring in a for ( i = a.min(); i <= a.max(); i++ ) { tmp = degrees( a[i], tmp ); for ( j = 1; j <= level( a[i] ); j++ ) if ( tmp[j] != 0 ) degs[j] = 1; } // create the maps i = 1; j = 1; while ( i <= maxlevel ) { if ( degs[i] != 0 ) { M.newpair( Variable(i), Variable(j) ); N.newpair( Variable(j), Variable(i) ); j++; } i++; } delete [] tmp; delete [] degs; } /* * compute positions p1 and pe of optimal variables: * pe is used in "ezgcd" and * p1 in "gcd_poly1" */ static void optvalues ( const int * df, const int * dg, const int n, int & p1, int &pe ) { int i, o1, oe; i = p1 = pe = 0; do { i++; if ( i > n ) return; } while ( ( df[i] == 0 ) || ( dg[i] == 0 ) ); p1 = pe = i; if ( df[i] > dg[i] ) { o1 = df[i]; oe = dg[i]; } else { o1 = dg[i]; oe = df[i]; } while ( i < n ) { i++; if ( ( df[i] != 0 ) && ( dg[i] != 0 ) ) { if ( df[i] > dg[i] ) { if ( o1 >= df[i]) { o1 = df[i]; p1 = i; } if ( oe < dg[i]) { oe = dg[i]; pe = i; } } else { if ( o1 >= dg[i]) { o1 = dg[i]; p1 = i; } if ( oe < df[i]) { oe = df[i]; pe = i; } } } } } /** void compress ( const CanonicalForm & f, const CanonicalForm & g, CFMap & M, CFMap & N ) * * compress() - compress the variables occurring in f and g with respect * to optimal variables * * Compress the polynomial variables occurring in f and g so that * the levels of variables common to f and g are ordered without * any gaps starting from level 1, whereas the variables occuring * in only one of f or g are moved to levels higher than the * levels of the common variables. Return the CFMap M to realize * the compression and its inverse, the CFMap N. * N needs only variables common to f and g. * **/ void compress ( const CanonicalForm & f, const CanonicalForm & g, CFMap & M, CFMap & N ) { int n = tmax( f.level(), g.level() ); int i, k, p1, pe; int * degsf = new int[n+1]; int * degsg = new int[n+1]; for ( i = 0; i <= n; i++ ) { degsf[i] = degsg[i] = 0; } degsf = degrees( f, degsf ); degsg = degrees( g, degsg ); optvalues( degsf, degsg, n, p1, pe ); i = 1; k = 1; if ( pe > 1 ) { M.newpair( Variable(pe), Variable(k) ); N.newpair( Variable(k), Variable(pe) ); k++; } while ( i <= n ) { if ( degsf[i] > 0 && degsg[i] > 0 ) { if ( ( i != k ) && ( i != pe ) && ( i != p1 ) ) { M.newpair( Variable(i), Variable(k) ); N.newpair( Variable(k), Variable(i) ); } k++; } i++; } if ( p1 != pe ) { M.newpair( Variable(p1), Variable(k) ); N.newpair( Variable(k), Variable(p1) ); k++; } i = 1; while ( i <= n ) { if ( degsf[i] > 0 && degsg[i] == 0 ) { if ( i != k ) { M.newpair( Variable(i), Variable(k) ); k++; } } else if ( degsf[i] == 0 && degsg[i] > 0 ) { if ( i != k ) { M.newpair( Variable(i), Variable(k) ); k++; } } i++; } delete [] degsf; delete [] degsg; } singular-4.0.3+ds/factory/cf_map.h000066400000000000000000000053621266270727000170300ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #ifndef INCL_CF_MAP_H #define INCL_CF_MAP_H /** * @file cf_map.h * * map polynomials * **/ // #include "config.h" #ifndef NOSTREAMIO #ifdef HAVE_IOSTREAM #include #define OSTREAM std::ostream #elif defined(HAVE_IOSTREAM_H) #include #define OSTREAM ostream #endif #endif /* NOSTREAMIO */ #include "variable.h" #include "canonicalform.h" #include /*BEGINPUBLIC*/ /** class MapPair * * class MapPair - stores one mapping pair (Variable -> CanonicalForm). * * This class is only used to store such pairs. It has no * methods to transform a CanonicalForm as the class CFMap has. * * V, S: the pair (V -> S) * **/ /** inline method * * Variable var () const * CanonicalForm subst () const * * var(), subst() - selectors, return V and P, resp. * **/ class MapPair { private: Variable V; CanonicalForm S; public: MapPair ( const Variable & v, const CanonicalForm & s ) : V(v), S(s) {} MapPair () : V(), S(1) {} MapPair ( const MapPair & p ) : V(p.V), S(p.S) {} ~MapPair () {} MapPair & operator = ( const MapPair & p ); Variable var () const { return V; } CanonicalForm subst () const { return S; } #ifndef NOSTREAMIO void print( OSTREAM&) const; friend OSTREAM & operator << ( OSTREAM & s, const MapPair & p ); #endif /* NOSTREAMIO */ }; typedef List MPList; typedef ListIterator MPListIterator; /** class CFMap * * class CFMap - class to map canonical forms. * * Use an object of class CFMap to insert 'values' into canonical * form. Such a mapping is defined by a list of MapPairs (V -> S) * describing which canonical form S to insert for variable V. * Hereby, the substituted canonical forms are not subject to * further substitutions. * * P: list of MapPairs, sorted by level in descending order * **/ class CFMap { private: MPList P; public: CFMap () {} CFMap ( const CanonicalForm & s ) : P( MapPair( Variable(), s ) ) {} CFMap ( const Variable & v ) : P( MapPair( v, 1 ) ) {} CFMap ( const Variable & v, const CanonicalForm & s ) : P( MapPair( v, s ) ) {} ~CFMap () {} CFMap ( const CFList & L ); CFMap ( const CFMap & m ) : P( m.P ) {} CFMap & operator = ( const CFMap & m ); void newpair ( const Variable & v, const CanonicalForm & s ); CanonicalForm operator () ( const CanonicalForm & f ) const; #ifndef NOSTREAMIO friend OSTREAM & operator << ( OSTREAM & s, const CFMap & m ); #endif /* NOSTREAMIO */ }; CanonicalForm compress ( const CanonicalForm & f, CFMap & m ); void compress ( const CFArray & a, CFMap & M, CFMap & N ); void compress ( const CanonicalForm & f, const CanonicalForm & g, CFMap & M, CFMap & N ); /*ENDPUBLIC*/ #endif /* ! INCL_CF_MAP_H */ singular-4.0.3+ds/factory/cf_map_ext.cc000066400000000000000000000260031266270727000200410ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file cf_map_ext.cc * * This file implements functions to map between extensions of finite fields * * @par Copyright: * (c) by The SINGULAR Team, see LICENSE file * * @author Martin Lee * @date 16.11.2009 **/ //***************************************************************************** #include "config.h" #include "cf_assert.h" #include "debug.h" #include "canonicalform.h" #include "cf_util.h" #include "imm.h" #include "cf_iter.h" #ifdef HAVE_NTL #include "NTLconvert.h" #endif // cyclotomoic polys: #include "cf_cyclo.h" #include "cf_map_ext.h" /// helper function int findItem (const CFList& list, const CanonicalForm& item) { int result= 1; for (CFListIterator i= list; i.hasItem(); i++, result++) { if (i.getItem() == item) return result; } return 0; } /// helper function CanonicalForm getItem (const CFList& list, const int& pos) { int j= 1; if ((pos > 0) && (pos <= list.length())) { for (CFListIterator i= list; j <= pos; i++, j++) { if (j == pos) return i.getItem(); } } return 0; } #ifdef HAVE_NTL /// \f$ F_{p} (\alpha ) \subset F_{p}(\beta ) \f$ and \f$ \alpha \f$ is a /// primitive element, returns the image of \f$ \alpha \f$ static inline CanonicalForm mapUp (const Variable& alpha, const Variable& beta) { int p= getCharacteristic (); if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } zz_pX NTL_mipo= convertFacCF2NTLzzpX (getMipo (beta)); zz_pE::init (NTL_mipo); zz_pEX NTL_alpha_mipo= convertFacCF2NTLzz_pEX (getMipo(alpha), NTL_mipo); zz_pE root= FindRoot (NTL_alpha_mipo); return convertNTLzzpE2CF (root, beta); } #endif /// the CanonicalForm G is the output of map_up, returns F considered as an /// element over \f$ F_{p}(\alpha ) \f$, WARNING: make sure coefficients of F /// are really elements of a subfield of \f$ F_{p}(\beta ) \f$ which is /// isomorphic to \f$ F_{p}(\alpha ) \f$ static inline CanonicalForm mapDown (const CanonicalForm& F, const Variable& alpha, const CanonicalForm& G, CFList& source, CFList& dest) { CanonicalForm buf, buf2; int counter= 0; int pos; int p= getCharacteristic(); int d= degree(getMipo(alpha)); int bound= ipower(p, d); CanonicalForm result= 0; CanonicalForm remainder; CanonicalForm alpha_power; if (degree(F) == 0) return F; if (F.level() < 0 && F.isUnivariate()) { buf= F; remainder= mod (buf, G); ASSERT (remainder.isZero(), "alpha is not primitive"); pos= findItem (source, buf); if (pos == 0) source.append (buf); buf2= buf; while (degree (buf) != 0 && counter < bound) { buf /= G; counter++; if (buf == buf2) break; } ASSERT (counter >= bound, "alpha is not primitive"); if (pos == 0) { alpha_power= power (alpha, counter); dest.append (alpha_power); } else alpha_power= getItem (dest, pos); result = alpha_power; return result; } else { for (CFIterator i= F; i.hasTerms(); i++) { buf= mapDown (i.coeff(), alpha, G, source, dest); result += buf*power(F.mvar(), i.exp()); } return result; } } /// helper function static inline CanonicalForm GF2FalphaHelper (const CanonicalForm& F, const Variable& alpha) { if (F.isZero()) return 0; int exp; CanonicalForm result= 0; InternalCF* buf; if (F.inBaseDomain()) { if (F.isOne()) return 1; buf= F.getval(); exp= imm2int(buf); result= power (alpha, exp).mapinto(); return result; } for (CFIterator i= F; i.hasTerms(); i++) result += GF2FalphaHelper (i.coeff(), alpha)*power (F.mvar(), i.exp()); return result; } CanonicalForm GF2FalphaRep (const CanonicalForm& F, const Variable& alpha) { Variable beta= rootOf (gf_mipo); CanonicalForm result= GF2FalphaHelper (F, beta) (alpha, beta); prune (beta); return result; } CanonicalForm Falpha2GFRep (const CanonicalForm& F) { CanonicalForm result= 0; InternalCF* buf; if (F.inCoeffDomain()) { if (F.inBaseDomain()) return F.mapinto(); else { for (CFIterator i= F; i.hasTerms(); i++) { buf= int2imm_gf (i.exp()); result += i.coeff().mapinto()*CanonicalForm (buf); } } return result; } for (CFIterator i= F; i.hasTerms(); i++) result += Falpha2GFRep (i.coeff())*power (F.mvar(), i.exp()); return result; } /// GF_map_up helper static inline CanonicalForm GFPowUp (const CanonicalForm & F, int k) { if (F.isOne()) return F; CanonicalForm result= 0; if (F.inBaseDomain()) return power(F, k); for (CFIterator i= F; i.hasTerms(); i++) result += GFPowUp (i.coeff(), k)*power (F.mvar(), i.exp()); return result; } CanonicalForm GFMapUp (const CanonicalForm & F, int k) { int d= getGFDegree(); ASSERT (d%k == 0, "multiple of GF degree expected"); int p= getCharacteristic(); int ext_field_size= ipower (p, d); int field_size= ipower ( p, k); int diff= (ext_field_size - 1)/(field_size - 1); return GFPowUp (F, diff); } /// GFMapDown helper static inline CanonicalForm GFPowDown (const CanonicalForm & F, int k) { if (F.isOne()) return F; CanonicalForm result= 0; int exp; InternalCF* buf; if (F.inBaseDomain()) { buf= F.getval(); exp= imm2int (buf); if ((exp % k) == 0) exp= exp/k; else return -1; buf= int2imm_gf (exp); return CanonicalForm (buf); } for (CFIterator i= F; i.hasTerms(); i++) result += GFPowDown (i.coeff(), k)*power (F.mvar(), i.exp()); return result; } CanonicalForm GFMapDown (const CanonicalForm & F, int k) { int d= getGFDegree(); ASSERT (d % k == 0, "multiple of GF degree expected"); int p= getCharacteristic(); int ext_field_size= ipower (p, d); int field_size= ipower ( p, k); int diff= (ext_field_size - 1)/(field_size - 1); return GFPowDown (F, diff); } /// map F in \f$ F_{p} (\alpha ) \f$ which is generated by G into some /// \f$ F_{p}(\beta ) \f$ which is generated by H static inline CanonicalForm mapUp (const CanonicalForm& F, const CanonicalForm& G, const Variable& alpha, const CanonicalForm& H, CFList& source, CFList& dest) { CanonicalForm buf, buf2; int counter= 0; int pos; int p= getCharacteristic(); int d= degree (getMipo(alpha)); int bound= ipower(p, d); CanonicalForm result= 0; CanonicalForm remainder; CanonicalForm H_power; if (degree(F) <= 0) return F; if (F.level() < 0 && F.isUnivariate()) { buf= F; remainder= mod (buf, G); ASSERT (remainder.isZero(), "alpha is not primitive"); pos= findItem (source, buf); if (pos == 0) source.append (buf); buf2= buf; while (degree (buf) != 0 && counter < bound) { buf /= G; counter++; if (buf == buf2) break; } ASSERT (counter <= bound, "alpha is not primitive"); if (pos == 0) { H_power= buf*power (H, counter); dest.append (H_power); } else H_power= getItem (dest, pos); result = H_power; return result; } else { for (CFIterator i= F; i.hasTerms(); i++) { buf= mapUp (i.coeff(), G, alpha, H, source, dest); result += buf*power(F.mvar(), i.exp()); } return result; } } #ifdef HAVE_NTL CanonicalForm primitiveElement (const Variable& alpha, Variable& beta, bool& fail) { bool primitive= false; fail= false; primitive= isPrimitive (alpha, fail); if (fail) return 0; if (primitive) { beta= alpha; return alpha; } CanonicalForm mipo= getMipo (alpha); int d= degree (mipo); int p= getCharacteristic (); if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } zz_pX NTL_mipo; CanonicalForm mipo2; primitive= false; fail= false; bool initialized= false; do { BuildIrred (NTL_mipo, d); mipo2= convertNTLzzpX2CF (NTL_mipo, Variable (1)); if (!initialized) beta= rootOf (mipo2); else setMipo (beta, mipo2); primitive= isPrimitive (beta, fail); if (primitive) break; if (fail) return 0; } while (1); zz_pX alpha_mipo= convertFacCF2NTLzzpX (mipo); zz_pE::init (alpha_mipo); zz_pEX NTL_beta_mipo= to_zz_pEX (NTL_mipo); zz_pE root= FindRoot (NTL_beta_mipo); return convertNTLzzpE2CF (root, alpha); } #endif CanonicalForm mapDown (const CanonicalForm& F, const CanonicalForm& prim_elem, const CanonicalForm& im_prim_elem, const Variable& alpha, CFList& source, CFList& dest) { return mapUp (F, im_prim_elem, alpha, prim_elem, dest, source); } CanonicalForm mapUp (const CanonicalForm& F, const Variable& alpha, const Variable& /*beta*/, const CanonicalForm& prim_elem, const CanonicalForm& im_prim_elem, CFList& source, CFList& dest) { if (prim_elem == alpha) return F (im_prim_elem, alpha); return mapUp (F, prim_elem, alpha, im_prim_elem, source, dest); } #ifdef HAVE_NTL CanonicalForm mapPrimElem (const CanonicalForm& primElem, const Variable& alpha, const Variable& beta) { if (primElem == alpha) return mapUp (alpha, beta); else { CanonicalForm primElemMipo= findMinPoly (primElem, alpha); int p= getCharacteristic (); if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (beta)); zz_pE::init (NTLMipo); zz_pEX NTLPrimElemMipo= convertFacCF2NTLzz_pEX (primElemMipo, NTLMipo); zz_pE root= FindRoot (NTLPrimElemMipo); return convertNTLzzpE2CF (root, beta); } } CanonicalForm map (const CanonicalForm& primElem, const Variable& alpha, const CanonicalForm& F, const Variable& beta) { CanonicalForm G= F; int order= 0; while (!G.isOne()) { G /= primElem; order++; } int p= getCharacteristic (); if (fac_NTL_char != p) { fac_NTL_char= p; zz_p::init (p); } zz_pX NTL_mipo= convertFacCF2NTLzzpX (getMipo (beta)); zz_pE::init (NTL_mipo); zz_pEX NTL_alpha_mipo= convertFacCF2NTLzz_pEX (getMipo(alpha), NTL_mipo); zz_pE NTLBeta= to_zz_pE (convertFacCF2NTLzzpX (beta)); vec_zz_pE roots= FindRoots (NTL_alpha_mipo); long ind=-1; for (long i= 0; i < roots.length(); i++) { if (power (roots [i], order)== NTLBeta) { ind= i; break; } } return (convertNTLzzpE2CF (roots[ind], beta)); } CanonicalForm findMinPoly (const CanonicalForm& F, const Variable& alpha) { ASSERT (F.isUnivariate() && F.mvar()==alpha,"expected element of F_p(alpha)"); if (fac_NTL_char != getCharacteristic()) { fac_NTL_char= getCharacteristic(); zz_p::init (getCharacteristic()); } zz_pX NTLF= convertFacCF2NTLzzpX (F); int d= degree (getMipo (alpha)); zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo(alpha)); zz_pE::init (NTLMipo); vec_zz_p pows; pows.SetLength (2*d); zz_pE powNTLF; set (powNTLF); zz_pE NTLFE= to_zz_pE (NTLF); zz_pX buf; for (int i= 0; i < 2*d; i++) { buf= rep (powNTLF); buf.rep.SetLength (d); pows [i]= buf.rep[0]; powNTLF *= NTLFE; } zz_pX NTLMinPoly; MinPolySeq (NTLMinPoly, pows, d); return convertNTLzzpX2CF (NTLMinPoly, Variable (1)); } #endif singular-4.0.3+ds/factory/cf_map_ext.h000066400000000000000000000122411266270727000177020ustar00rootroot00000000000000// -*- c++ -*- //***************************************************************************** /** @file cf_map_ext.h * * This file implements functions to map between extensions of finite fields * * @par Copyright: * (c) by The SINGULAR Team, see LICENSE file * * @author Martin Lee * @date 16.11.2009 **/ //***************************************************************************** #ifndef CF_MAP_EXT_H #define CF_MAP_EXT_H // #include "config.h" int findItem (const CFList& list, const CanonicalForm& item); CanonicalForm getItem (const CFList& list, const int& pos); /// maps a polynomial over \f$ GF(p^{k}) \f$ to a polynomial over /// \f$ GF(p^{d}) \f$ , d needs to be a multiple of k CanonicalForm GFMapUp (const CanonicalForm & F, int k); /// maps a polynomial over \f$ GF(p^{d}) \f$ to a polynomial over /// \f$ GF(p^{k})\f$ , d needs to be a multiple of k CanonicalForm GFMapDown (const CanonicalForm & F, int k); /// map F from \f$ F_{p} (\alpha ) \f$ to \f$ F_{p}(\beta ) \f$. /// We assume \f$ F_{p} (\alpha ) \subset F_{p}(\beta ) \f$. CanonicalForm mapUp (const CanonicalForm& F, ///<[in] poly over \f$ F_{p} (\alpha ) \f$ const Variable& alpha, ///<[in] alg. variable const Variable& beta, ///<[in] alg. variable const CanonicalForm& prim_elem, ///<[in] primitive element of \f$ F_{p} (\alpha ) \f$ const CanonicalForm& im_prim_elem,///<[in] image of prim_elem in \f$ F_{p} (\beta ) \f$ CFList& source, ///<[in,out] look up lists CFList& dest ///<[in,out] look up lists ); /// map F from \f$ F_{p} (\beta ) \f$ to \f$ F_{p}(\alpha ) \f$. /// We assume \f$ F_{p} (\alpha ) \subset F_{p}(\beta ) \f$ and F in /// \f$ F_{p}(\alpha ) \f$. CanonicalForm mapDown (const CanonicalForm& F, ///<[in] poly over \f$ F_{p} (\beta ) \f$ const CanonicalForm& prim_elem, ///<[in] primitive element of \f$ F_{p} (\alpha ) \f$ const CanonicalForm& im_prim_elem,///<[in] image of prim_elem in \f$ F_{p} (\beta ) \f$ const Variable& alpha, ///<[in] alg. variable CFList& source, ///<[in,out] look up lists CFList& dest ///<[in,out] look up lists ); /// determine a primitive element of \f$ F_{p} (\alpha ) \f$, /// \f$ \beta \f$ is a primitive element of a field which is isomorphic to /// \f$ F_{p}(\alpha ) \f$ CanonicalForm primitiveElement (const Variable& alpha, ///< [in] some algebraic variable Variable& beta, ///< [in,out] s.a. bool& fail ///< [in,out] failure due to integer ///< factorization failure? ); /// compute the image of a primitive element of \f$ F_{p} (\alpha ) \f$ /// in \f$ F_{p}(\beta ) \f$. /// We assume \f$ F_{p} (\alpha ) \subset F_{p}(\beta ) \f$. CanonicalForm mapPrimElem (const CanonicalForm& prim_elem, ///< [in] primitive element const Variable& alpha, ///< [in] algebraic variable const Variable& beta ///< [in] algebraic variable ); /// changes representation by primitive element to representation by residue /// classes modulo a Conway polynomial CanonicalForm GF2FalphaRep (const CanonicalForm& F, ///< [in] some poly over GF const Variable& alpha ///< [in] root of a Conway ///< poly ); /// change representation by residue classes modulo a Conway polynomial /// to representation by primitive element CanonicalForm Falpha2GFRep (const CanonicalForm& F ///<[in] some poly over ///< F_p(alpha) where alpha ///< is a root of a Conway ///< poly ); /// map from \f$ F_p(\alpha) \f$ to \f$ F_p(\beta) \f$ such that /// \f$ F\in F_p(\alpha) \f$ is mapped onto \f$ \beta \f$ /// /// @return @a map returns the image of @a primElem such that the above /// described properties hold CanonicalForm map (const CanonicalForm& primElem,///< [in] primitive element of ///< \f$ F_p (\alpha) \f$ const Variable& alpha, ///< [in] algebraic variable const CanonicalForm& F, ///< [in] an element of \f$ F_p (\alpha) \f$, ///< whose minimal polynomial defines a field ///< extension of \f$ F_p \f$ of degree ///< \f$ F_p (\alpha):F_p \f$ const Variable& beta ///< [in] algebraic variable, root of \a F's ///< minimal polynomial ); /// compute minimal polynomial of \f$ F\in F_p(\alpha)\backslash F_p \f$ via NTL /// /// @return @a findMinPoly computes the minimal polynomial of F CanonicalForm findMinPoly (const CanonicalForm& F, ///< [in] an element of ///< \f$ F_p(\alpha)\backslash F_p \f$ const Variable& alpha ///< [in] algebraic variable ); #endif singular-4.0.3+ds/factory/cf_ops.cc000066400000000000000000000447271266270727000172220ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_ops.cc * * simple structural algorithms. * * A 'structural' algorithm is an algorithm which gives * structural information on polynomials in contrast to a * 'mathematical' algorithm which calculates some mathematical * function. * * Compare these functions with the functions in cf_algorithm.cc, * which are mathematical algorithms. * * * Header file: canonicalform.h * **/ #include "config.h" #include "cf_assert.h" #include "canonicalform.h" #include "variable.h" #include "cf_iter.h" /** static Variable sv_x1, sv_x2; * * sv_x1, sv_x2 - variables to swap by swapvar() and replacevar. * * These variables are initialized by swapvar() such that sv_x1 < * sv_x2. They are used by swapvar_between() and swapvar_rec() * to swap variables efficiently. * Furthermore, sv_x1 and sv_x2 are used by replacevar() and * replacevar_between(). * **/ static Variable sv_x1, sv_x2; /** static void swapvar_between ( const CanonicalForm & f, CanonicalForm & result, const CanonicalForm & term, int expx2 ) * * swapvar_between() - replace occurences of sv_x1 in f with sv_x2. * * If Psi denotes the map which maps sv_x1 to sv_x2, this * function returns * * result + Psi(f) * term * sv_x1^expx2 * * Used by: swapvar() * **/ static void swapvar_between ( const CanonicalForm & f, CanonicalForm & result, const CanonicalForm & term, int expx2 ) { if ( f.inCoeffDomain() || f.mvar() < sv_x1 ) // in this case, we do not have to replace anything result += term * power( sv_x1, expx2 ) * f; else if ( f.mvar() == sv_x1 ) // this is where the real work is done: this iterator // replaces sv_x1 with sv_x2 for ( CFIterator i = f; i.hasTerms(); i++ ) result += power( sv_x2, i.exp() ) * term * power( sv_x1, expx2 ) * i.coeff(); else // f's level is larger than sv_x1: descend down for ( CFIterator i = f; i.hasTerms(); i++ ) swapvar_between( i.coeff(), result, term * power( f.mvar(), i.exp() ), expx2 ); } #if 0 static CanonicalForm swapvar_between1 ( const CanonicalForm & f ) { if ( f.inCoeffDomain() || f.mvar() < sv_x1 ) // in this case, we do not have to replace anything return f; else if ( f.mvar() == sv_x1 ) { // this is where the real work is done: this iterator // replaces sv_x1 with sv_x2 CanonicalForm result; for ( CFIterator i = f; i.hasTerms(); i++ ) result += power( sv_x2, i.exp() ) * i.coeff(); return result; } else { // f's level is larger than sv_x1: descend down CanonicalForm result; for ( CFIterator i = f; i.hasTerms(); i++ ) result += swapvar_between1( i.coeff() ) * power( f.mvar(), i.exp() ); return result; } } #endif /** * * swapvar_between() - swap occurences of sv_x1 and sv_x2 in f. * * If Psi denotes the map which swaps sv_x1 and sv_x2, this * function returns * * result + Psi(f) * term * * Used by: swapvar() * **/ static void swapvar_rec ( const CanonicalForm & f, CanonicalForm & result, const CanonicalForm & term ) { if ( f.inCoeffDomain() || f.mvar() < sv_x1 ) // in this case, we do not have to swap anything result += term * f; else if ( f.mvar() == sv_x2 ) // this is where the real work is done: this iterator // replaces sv_x1 with sv_x2 in the coefficients of f and // remembers the exponents of sv_x2 in the last argument // of the call to swapvar_between() for ( CFIterator i = f; i.hasTerms(); i++ ) swapvar_between( i.coeff(), result, term, i.exp() ); else if ( f.mvar() < sv_x2 ) // sv_x2 does not occur in f, but sv_x1 does. Replace it. swapvar_between( f, result, term, 0 ); else // f's level is larger than sv_x2: descend down for ( CFIterator i = f; i.hasTerms(); i++ ) swapvar_rec( i.coeff(), result, term * power( f.mvar(), i.exp() ) ); } #if 0 static CanonicalForm swapvar_rec1 ( const CanonicalForm & f ) { if ( f.inCoeffDomain() || f.mvar() < sv_x1 ) return f; else if ( f.mvar() == sv_x2 ) { CanonicalForm result; for ( CFIterator i = f; i.hasTerms(); i++ ) result += swapvar_between1( i.coeff() ) * power( sv_x1, i.exp() ); return result; } else if ( f.mvar() < sv_x2 ) return swapvar_between1( f ); else { CanonicalForm result; for ( CFIterator i = f; i.hasTerms(); i++ ) result += swapvar_rec1( i.coeff() ) * power( f.mvar(), i.exp() ); return result; } } #endif /** * * swapvar() - swap variables x1 and x2 in f. * * Returns the image of f under the map which maps x1 to x2 and * x2 to x1. This is done quite efficiently because it is used * really often. x1 and x2 should be polynomial variables. * **/ CanonicalForm swapvar ( const CanonicalForm & f, const Variable & x1, const Variable & x2 ) { ASSERT( x1.level() > 0 && x2.level() > 0, "cannot swap algebraic Variables" ); if ( f.inCoeffDomain() || x1 == x2 || ( x1 > f.mvar() && x2 > f.mvar() ) ) return f; else { CanonicalForm result = 0; if ( x1 > x2 ) { sv_x1 = x2; sv_x2 = x1; } else { sv_x1 = x1; sv_x2 = x2; } if ( f.mvar() < sv_x2 ) // we only have to replace sv_x1 by sv_x2 swapvar_between( f, result, 1, 0 ); else // we really have to swap variables swapvar_rec( f, result, 1 ); return result; } } #if 0 CanonicalForm swapvar1 ( const CanonicalForm & f, const Variable & x1, const Variable & x2 ) { ASSERT( x1.level() > 0 && x2.level() > 0, "cannot swap algebraic variables" ); if ( f.inCoeffDomain() || x1 == x2 || ( x1 > f.mvar() && x2 > f.mvar() ) ) return f; else { CanonicalForm result = 0; if ( x1 > x2 ) { sv_x1 = x2; sv_x2 = x1; } else { sv_x1 = x1; sv_x2 = x2; } if ( f.mvar() < sv_x2 ) // we only have to replace sv_x1 by sv_x2 return swapvar_between1( f ); else // we really have to swap variables return swapvar_rec1( f ); } } #endif /** * * replacevar_between() - replace occurences of sv_x1 in f with sv_x2. * * This is allmost the same as swapvar_between() except that * sv_x1 may be an algebraic variable, so we have to test on * 'f.inBaseDomain()' instead of 'f.inCoeffDomain()' in the * beginning. * * Used by: replacevar() * **/ static CanonicalForm replacevar_between ( const CanonicalForm & f ) { if ( f.inBaseDomain() ) return f; Variable x = f.mvar(); if ( x < sv_x1 ) // in this case, we do not have to replace anything return f; else if ( x == sv_x1 ) { // this is where the real work is done: this iterator // replaces sv_x1 with sv_x2 CanonicalForm result; for ( CFIterator i = f; i.hasTerms(); i++ ) result += power( sv_x2, i.exp() ) * i.coeff(); return result; } else { // f's level is larger than sv_x1: descend down CanonicalForm result; for ( CFIterator i = f; i.hasTerms(); i++ ) result += replacevar_between( i.coeff() ) * power( x, i.exp() ); return result; } } /** CanonicalForm replacevar ( const CanonicalForm & f, const Variable & x1, const Variable & x2 ) * * replacevar() - replace all occurences of x1 in f by x2. * * In contrast to swapvar(), x1 may be an algebraic variable, but * x2 must be a polynomial variable. * **/ CanonicalForm replacevar ( const CanonicalForm & f, const Variable & x1, const Variable & x2 ) { //ASSERT( x2.level() > 0, "cannot replace with algebraic variable" ); if ( f.inBaseDomain() || x1 == x2 || ( x1 > f.mvar() ) ) return f; else { sv_x1 = x1; sv_x2 = x2; return replacevar_between( f ); } } /** static void fillVarsRec ( const CanonicalForm & f, int * vars ) * * fillVarsRec - fill array describing occurences of variables in f. * * Only polynomial variables are looked up. The information is * stored in the arrary vars. vars should be large enough to * hold all information, i.e. larger than the level of f. * * Used by getVars() and getNumVars(). * **/ static void fillVarsRec ( const CanonicalForm & f, int * vars ) { int n; if ( (n = f.level()) > 0 ) { vars[n] = 1; CFIterator i; for ( i = f; i.hasTerms(); ++i ) fillVarsRec( i.coeff(), vars ); } } /** int getNumVars ( const CanonicalForm & f ) * * getNumVars() - get number of polynomial variables in f. * **/ int getNumVars ( const CanonicalForm & f ) { int n; if ( f.inCoeffDomain() ) return 0; else if ( (n = f.level()) == 1 ) return 1; else { int * vars = new int[ n+1 ]; int i; for ( i = 0; i < n; i++ ) vars[i] = 0; // look for variables for ( CFIterator I = f; I.hasTerms(); ++I ) fillVarsRec( I.coeff(), vars ); // count them int m = 0; for ( i = 1; i < n; i++ ) if ( vars[i] != 0 ) m++; delete [] vars; // do not forget to count our own variable return m+1; } } /** CanonicalForm getVars ( const CanonicalForm & f ) * * getVars() - get polynomial variables of f. * * Return the product of all of them, 1 if there are not any. * **/ CanonicalForm getVars ( const CanonicalForm & f ) { int n; if ( f.inCoeffDomain() ) return 1; else if ( (n = f.level()) == 1 ) return Variable( 1 ); else { int * vars = new int[ n+1 ]; int i; for ( i = 0; i <= n; i++ ) vars[i] = 0; // look for variables for ( CFIterator I = f; I.hasTerms(); ++I ) fillVarsRec( I.coeff(), vars ); // multiply them all CanonicalForm result = 1; for ( i = n; i > 0; i-- ) if ( vars[i] != 0 ) result *= Variable( i ); delete [] vars; // do not forget our own variable return f.mvar() * result; } } /** CanonicalForm apply ( const CanonicalForm & f, void (*mf)( CanonicalForm &, int & ) ) * * apply() - apply mf to terms of f. * * Calls mf( f[i], i ) for each term f[i]*x^i of f and builds a * new term from the result. If f is in a coefficient domain, * mf( f, i ) should result in an i == 0, since otherwise it is * not clear which variable to use for the resulting term. * * An example: * ~~~~~~~~~~~~~~~~~~~~~{.c} void diff( CanonicalForm & f, int & i ) { f = f * i; if ( i > 0 ) i--; } ~~~~~~~~~~~~~~~~~~~~~ * Then apply( f, diff ) is differentation of f with respect to the * main variable of f. * **/ CanonicalForm apply ( const CanonicalForm & f, void (*mf)( CanonicalForm &, int & ) ) { if ( f.inCoeffDomain() ) { int exp = 0; CanonicalForm result = f; mf( result, exp ); ASSERT( exp == 0, "illegal result, do not know what variable to use" ); return result; } else { CanonicalForm result, coeff; CFIterator i; int exp; Variable x = f.mvar(); for ( i = f; i.hasTerms(); i++ ) { coeff = i.coeff(); exp = i.exp(); mf( coeff, exp ); if ( ! coeff.isZero() ) result += power( x, exp ) * coeff; } return result; } } /** CanonicalForm mapdomain ( const CanonicalForm & f, CanonicalForm (*mf)( const CanonicalForm & ) ) * * mapdomain() - map all coefficients of f through mf. * * Recursively descends down through f to the coefficients which * are in a coefficient domain mapping each such coefficient * through mf and returns the result. * **/ CanonicalForm mapdomain ( const CanonicalForm & f, CanonicalForm (*mf)( const CanonicalForm & ) ) { if ( f.inBaseDomain() ) return mf( f ); else { CanonicalForm result = 0; CFIterator i; Variable x = f.mvar(); for ( i = f; i.hasTerms(); i++ ) result += power( x, i.exp() ) * mapdomain( i.coeff(), mf ); return result; } } /** static void degreesRec ( const CanonicalForm & f, int * degs ) * * degreesRec() - recursively get degrees of f. * * Used by degrees(). * **/ static void degreesRec ( const CanonicalForm & f, int * degs ) { if ( ! f.inCoeffDomain() ) { int level = f.level(); int deg = f.degree(); // calculate the maximum degree of all coefficients which // are in the same level if ( degs[level] < deg ) degs[level] = f.degree(); for ( CFIterator i = f; i.hasTerms(); i++ ) degreesRec( i.coeff(), degs ); } } /** int * degrees ( const CanonicalForm & f, int * degs ) * * degress() - return the degrees of all polynomial variables in f. * * Returns 0 if f is in a coefficient domain, the degrees of f in * all its polynomial variables in an array of int otherwise: * * degrees( f, 0 )[i] = degree( f, Variable(i) ) * * If degs is not the zero pointer the degrees are stored in this * array. In this case degs should be larger than the level of * f. If degs is the zero pointer, an array of sufficient size * is allocated automatically. * **/ int * degrees ( const CanonicalForm & f, int * degs ) { if ( f.inCoeffDomain() ) { if (degs != 0) return degs; else return 0; } else { int level = f.level(); if ( degs == 0 ) degs = new int[level+1]; for ( int i = 0; i <= level; i++ ) degs[i] = 0; degreesRec( f, degs ); return degs; } } /** int totaldegree ( const CanonicalForm & f ) * * totaldegree() - return the total degree of f. * * If f is zero, return -1. If f is in a coefficient domain, * return 0. Otherwise return the total degree of f in all * polynomial variables. * **/ int totaldegree ( const CanonicalForm & f ) { if ( f.isZero() ) return -1; else if ( f.inCoeffDomain() ) return 0; else { CFIterator i; int cdeg = 0, dummy; // calculate maximum over all coefficients of f, taking // in account our own exponent for ( i = f; i.hasTerms(); i++ ) if ( (dummy = totaldegree( i.coeff() ) + i.exp()) > cdeg ) cdeg = dummy; return cdeg; } } /** int totaldegree ( const CanonicalForm & f, const Variable & v1, const Variable & v2 ) * * totaldegree() - return the total degree of f as a polynomial * in the polynomial variables between v1 and v2 (inclusively). * * If f is zero, return -1. If f is in a coefficient domain, * return 0. Also, return 0 if v1 > v2. Otherwise, take f to be * a polynomial in the polynomial variables between v1 and v2 and * return its total degree. * **/ int totaldegree ( const CanonicalForm & f, const Variable & v1, const Variable & v2 ) { if ( f.isZero() ) return -1; else if ( v1 > v2 ) return 0; else if ( f.inCoeffDomain() ) return 0; else if ( f.mvar() < v1 ) return 0; else if ( f.mvar() == v1 ) return f.degree(); else if ( f.mvar() > v2 ) { // v2's level is larger than f's level, descend down CFIterator i; int cdeg = 0, dummy; // calculate maximum over all coefficients of f for ( i = f; i.hasTerms(); i++ ) if ( (dummy = totaldegree( i.coeff(), v1, v2 )) > cdeg ) cdeg = dummy; return cdeg; } else { // v1 < f.mvar() <= v2 CFIterator i; int cdeg = 0, dummy; // calculate maximum over all coefficients of f, taking // in account our own exponent for ( i = f; i.hasTerms(); i++ ) if ( (dummy = totaldegree( i.coeff(), v1, v2 ) + i.exp()) > cdeg ) cdeg = dummy; return cdeg; } } /** int size ( const CanonicalForm & f, const Variable & v ) * * size() - count number of monomials of f with level higher * or equal than level of v. * * Returns one if f is in an base domain. * **/ int size ( const CanonicalForm & f, const Variable & v ) { if ( f.inBaseDomain() ) return 1; if ( f.mvar() < v ) // polynomials with level < v1 are counted as coefficients return 1; else { CFIterator i; int result = 0; // polynomials with level > v2 are not counted al all for ( i = f; i.hasTerms(); i++ ) result += size( i.coeff(), v ); return result; } } /** int size ( const CanonicalForm & f ) * * size() - return number of monomials in f which are in an * coefficient domain. * * Returns one if f is in an coefficient domain. * **/ int size ( const CanonicalForm & f ) { if ( f.inCoeffDomain() ) return 1; else { int result = 0; CFIterator i; for ( i = f; i.hasTerms(); i++ ) result += size( i.coeff() ); return result; } } /** polynomials in M.mvar() are considered coefficients * M univariate monic polynomial * the coefficients of f are reduced modulo M **/ CanonicalForm reduce(const CanonicalForm & f, const CanonicalForm & M) { if(f.inBaseDomain() || f.level() < M.level()) return f; if(f.level() == M.level()) { if(f.degree() < M.degree()) return f; CanonicalForm tmp = mod (f, M); return tmp; } // here: f.level() > M.level() CanonicalForm result = 0; for(CFIterator i=f; i.hasTerms(); i++) result += reduce(i.coeff(),M) * power(f.mvar(),i.exp()); return result; } /** check if poly f contains an algebraic variable a **/ bool hasFirstAlgVar( const CanonicalForm & f, Variable & a ) { if( f.inBaseDomain() ) // f has NO alg. variable return false; if( f.level()<0 ) // f has only alg. vars, so take the first one { a = f.mvar(); return true; } for(CFIterator i=f; i.hasTerms(); i++) if( hasFirstAlgVar( i.coeff(), a )) return true; // 'a' is already set return false; } /** left shift the main variable of F by n * @return if x is the main variable of F the result is F(x^n) **/ CanonicalForm leftShift (const CanonicalForm& F, int n) { ASSERT (n >= 0, "cannot left shift by negative number"); if (F.inBaseDomain()) return F; if (n == 0) return F; Variable x=F.mvar(); CanonicalForm result= 0; for (CFIterator i= F; i.hasTerms(); i++) result += i.coeff()*power (x, i.exp()*n); return result; } singular-4.0.3+ds/factory/cf_primes.cc000066400000000000000000000014461266270727000177070ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "cf_primes.h" #include "cf_primetab.h" int cf_getPrime( int i ) { ASSERT( i >= 0 && i < NUMPRIMES, "index to primes too high" ); if ( i >= NUMSMALLPRIMES ) return bigprimes[i-NUMSMALLPRIMES]; else return smallprimes[i]; } int cf_getNumPrimes() { return NUMPRIMES; } int cf_getSmallPrime( int i ) { ASSERT( i >= 0 && i < NUMSMALLPRIMES, "index to primes too high" ); return smallprimes[i]; } int cf_getNumSmallPrimes() { return NUMSMALLPRIMES; } int cf_getBigPrime( int i ) { ASSERT( i >= 0 && i < NUMBIGPRIMES, "index to primes too high" ); return bigprimes[i]; } int cf_getNumBigPrimes() { return NUMBIGPRIMES; } singular-4.0.3+ds/factory/cf_primes.h000066400000000000000000000006431266270727000175470ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_primes.h * * access to prime tables **/ #ifndef INCL_CF_PRIMES_H #define INCL_CF_PRIMES_H // #include "config.h" /*BEGINPUBLIC*/ int cf_getPrime( int i ); int cf_getNumPrimes(); int cf_getSmallPrime( int i ); int cf_getNumSmallPrimes(); int cf_getBigPrime( int i ); int cf_getNumBigPrimes(); /*ENDPUBLIC*/ #endif /* ! INCL_CF_PRIMES_H */ singular-4.0.3+ds/factory/cf_primetab.h000066400000000000000000012721711266270727000200630ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #ifndef INCL_CF_PRIMETAB_H #define INCL_CF_PRIMETAB_H // #include "config.h" #define NUMSMALLPRIMES 3511 #define NUMBIGPRIMES 28427 #define NUMPRIMES NUMSMALLPRIMES+NUMBIGPRIMES static const int smallprimes [] = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, 32719, 32749, 0 }; static const int bigprimes [] = { 536300041, 536300047, 536300053, 536300069, 536300081, 536300117, 536300119, 536300129, 536300143, 536300153, 536300159, 536300179, 536300197, 536300231, 536300239, 536300249, 536300287, 536300321, 536300339, 536300357, 536300419, 536300431, 536300437, 536300447, 536300477, 536300489, 536300521, 536300537, 536300563, 536300573, 536300579, 536300621, 536300641, 536300657, 536300663, 536300731, 536300747, 536300759, 536300761, 536300767, 536300777, 536300801, 536300803, 536300813, 536300861, 536300881, 536300909, 536300911, 536300927, 536300939, 536300969, 536301001, 536301041, 536301043, 536301149, 536301169, 536301179, 536301187, 536301191, 536301221, 536301229, 536301253, 536301287, 536301317, 536301341, 536301343, 536301377, 536301401, 536301407, 536301497, 536301523, 536301527, 536301539, 536301583, 536301587, 536301589, 536301613, 536301641, 536301673, 536301713, 536301743, 536301751, 536301769, 536301781, 536301793, 536301827, 536301841, 536301851, 536301863, 536301881, 536301889, 536301919, 536301929, 536301943, 536301947, 536301967, 536302001, 536302003, 536302027, 536302051, 536302061, 536302069, 536302073, 536302141, 536302157, 536302183, 536302229, 536302231, 536302253, 536302279, 536302313, 536302369, 536302381, 536302397, 536302421, 536302433, 536302439, 536302441, 536302447, 536302463, 536302513, 536302517, 536302541, 536302549, 536302567, 536302577, 536302589, 536302681, 536302687, 536302691, 536302733, 536302783, 536302801, 536302817, 536302847, 536302867, 536302889, 536302903, 536302909, 536302931, 536302957, 536302969, 536302993, 536302997, 536303021, 536303039, 536303071, 536303087, 536303099, 536303107, 536303143, 536303179, 536303191, 536303263, 536303281, 536303297, 536303303, 536303359, 536303363, 536303371, 536303377, 536303381, 536303401, 536303407, 536303413, 536303447, 536303459, 536303477, 536303483, 536303497, 536303501, 536303507, 536303513, 536303527, 536303623, 536303681, 536303693, 536303701, 536303707, 536303731, 536303737, 536303759, 536303809, 536303819, 536303827, 536303843, 536303849, 536303881, 536303891, 536303893, 536303921, 536303927, 536303939, 536303941, 536303951, 536303959, 536303987, 536304001, 536304007, 536304017, 536304019, 536304029, 536304037, 536304059, 536304091, 536304103, 536304143, 536304161, 536304187, 536304239, 536304269, 536304283, 536304311, 536304319, 536304331, 536304359, 536304361, 536304401, 536304413, 536304443, 536304449, 536304463, 536304473, 536304479, 536304481, 536304487, 536304499, 536304523, 536304539, 536304541, 536304551, 536304553, 536304589, 536304611, 536304653, 536304683, 536304761, 536304779, 536304803, 536304877, 536304911, 536304913, 536304941, 536304953, 536304959, 536304971, 536305013, 536305027, 536305057, 536305097, 536305123, 536305157, 536305163, 536305181, 536305193, 536305201, 536305213, 536305219, 536305261, 536305277, 536305279, 536305291, 536305313, 536305327, 536305333, 536305369, 536305423, 536305489, 536305501, 536305519, 536305537, 536305577, 536305591, 536305607, 536305621, 536305631, 536305661, 536305691, 536305699, 536305703, 536305711, 536305727, 536305751, 536305753, 536305769, 536305793, 536305831, 536305843, 536305849, 536305873, 536305879, 536305897, 536305909, 536305937, 536305949, 536305967, 536305997, 536305999, 536306003, 536306011, 536306039, 536306081, 536306087, 536306101, 536306129, 536306159, 536306161, 536306167, 536306171, 536306213, 536306219, 536306227, 536306233, 536306317, 536306333, 536306339, 536306347, 536306357, 536306371, 536306473, 536306489, 536306503, 536306513, 536306539, 536306569, 536306579, 536306581, 536306587, 536306593, 536306653, 536306669, 536306671, 536306677, 536306717, 536306753, 536306761, 536306767, 536306777, 536306783, 536306809, 536306821, 536306839, 536306843, 536306887, 536306917, 536306921, 536306933, 536306987, 536306999, 536307017, 536307029, 536307043, 536307047, 536307067, 536307097, 536307113, 536307131, 536307139, 536307197, 536307217, 536307229, 536307241, 536307251, 536307259, 536307283, 536307293, 536307311, 536307349, 536307367, 536307383, 536307389, 536307397, 536307427, 536307437, 536307451, 536307539, 536307589, 536307599, 536307613, 536307649, 536307691, 536307749, 536307797, 536307799, 536307833, 536307847, 536307899, 536307917, 536307953, 536307971, 536307977, 536308021, 536308033, 536308051, 536308063, 536308093, 536308099, 536308103, 536308109, 536308121, 536308139, 536308141, 536308147, 536308177, 536308217, 536308243, 536308261, 536308291, 536308313, 536308343, 536308363, 536308387, 536308391, 536308403, 536308417, 536308447, 536308453, 536308471, 536308481, 536308501, 536308517, 536308519, 536308529, 536308547, 536308559, 536308601, 536308603, 536308613, 536308637, 536308651, 536308691, 536308697, 536308699, 536308723, 536308739, 536308753, 536308769, 536308783, 536308807, 536308813, 536308847, 536308849, 536308853, 536308859, 536308873, 536308909, 536308921, 536308933, 536308951, 536308967, 536309003, 536309041, 536309051, 536309063, 536309087, 536309099, 536309107, 536309113, 536309119, 536309129, 536309131, 536309141, 536309161, 536309167, 536309171, 536309197, 536309203, 536309227, 536309303, 536309369, 536309401, 536309419, 536309429, 536309437, 536309453, 536309467, 536309497, 536309503, 536309507, 536309549, 536309623, 536309629, 536309633, 536309651, 536309663, 536309671, 536309681, 536309687, 536309689, 536309707, 536309737, 536309747, 536309759, 536309797, 536309801, 536309819, 536309821, 536309833, 536309843, 536309849, 536309867, 536309869, 536309887, 536309911, 536309923, 536309933, 536309989, 536310023, 536310043, 536310077, 536310083, 536310097, 536310119, 536310133, 536310139, 536310149, 536310161, 536310179, 536310191, 536310197, 536310221, 536310241, 536310259, 536310263, 536310293, 536310331, 536310337, 536310347, 536310349, 536310403, 536310409, 536310433, 536310461, 536310493, 536310563, 536310569, 536310581, 536310583, 536310589, 536310613, 536310617, 536310653, 536310661, 536310673, 536310689, 536310703, 536310793, 536310809, 536310811, 536310821, 536310823, 536310839, 536310851, 536310871, 536310877, 536310889, 536310911, 536310959, 536310961, 536310977, 536310989, 536311021, 536311051, 536311091, 536311109, 536311133, 536311141, 536311159, 536311163, 536311199, 536311213, 536311229, 536311277, 536311301, 536311327, 536311333, 536311339, 536311379, 536311397, 536311403, 536311417, 536311429, 536311481, 536311513, 536311541, 536311549, 536311553, 536311561, 536311583, 536311603, 536311619, 536311621, 536311639, 536311663, 536311747, 536311757, 536311759, 536311771, 536311793, 536311799, 536311807, 536311847, 536311849, 536311859, 536311913, 536311943, 536311949, 536311973, 536311987, 536311991, 536312009, 536312011, 536312017, 536312033, 536312047, 536312057, 536312081, 536312083, 536312089, 536312099, 536312113, 536312129, 536312143, 536312171, 536312173, 536312197, 536312207, 536312251, 536312269, 536312291, 536312333, 536312339, 536312377, 536312389, 536312401, 536312437, 536312473, 536312477, 536312479, 536312507, 536312509, 536312519, 536312533, 536312587, 536312627, 536312659, 536312681, 536312683, 536312737, 536312779, 536312801, 536312831, 536312849, 536312879, 536312897, 536312939, 536312951, 536312971, 536313023, 536313061, 536313079, 536313119, 536313143, 536313179, 536313221, 536313223, 536313227, 536313233, 536313301, 536313313, 536313341, 536313347, 536313389, 536313397, 536313451, 536313461, 536313469, 536313473, 536313499, 536313527, 536313529, 536313539, 536313581, 536313593, 536313641, 536313677, 536313683, 536313689, 536313749, 536313781, 536313809, 536313829, 536313859, 536313871, 536313881, 536313889, 536313913, 536313917, 536313923, 536313937, 536313941, 536313949, 536313971, 536313983, 536314003, 536314019, 536314021, 536314063, 536314087, 536314109, 536314123, 536314127, 536314151, 536314157, 536314171, 536314199, 536314201, 536314217, 536314241, 536314271, 536314279, 536314301, 536314319, 536314369, 536314417, 536314421, 536314423, 536314433, 536314531, 536314547, 536314549, 536314567, 536314591, 536314613, 536314631, 536314637, 536314651, 536314673, 536314679, 536314687, 536314763, 536314783, 536314817, 536314841, 536314853, 536314879, 536314903, 536314907, 536314913, 536314927, 536314939, 536314969, 536315027, 536315029, 536315047, 536315069, 536315077, 536315093, 536315113, 536315141, 536315161, 536315189, 536315239, 536315243, 536315257, 536315291, 536315293, 536315309, 536315363, 536315387, 536315389, 536315401, 536315411, 536315419, 536315431, 536315443, 536315447, 536315453, 536315459, 536315471, 536315497, 536315551, 536315561, 536315569, 536315573, 536315581, 536315623, 536315653, 536315671, 536315701, 536315713, 536315729, 536315749, 536315789, 536315807, 536315827, 536315833, 536315849, 536315891, 536315921, 536315929, 536315951, 536315963, 536315971, 536315977, 536316019, 536316023, 536316061, 536316091, 536316163, 536316191, 536316197, 536316217, 536316233, 536316241, 536316251, 536316269, 536316281, 536316299, 536316311, 536316353, 536316373, 536316427, 536316433, 536316467, 536316481, 536316491, 536316499, 536316509, 536316541, 536316587, 536316601, 536316617, 536316631, 536316637, 536316643, 536316653, 536316673, 536316689, 536316713, 536316727, 536316763, 536316779, 536316811, 536316827, 536316839, 536316841, 536316863, 536316899, 536316917, 536316929, 536316947, 536316973, 536316997, 536317043, 536317073, 536317079, 536317091, 536317121, 536317129, 536317147, 536317153, 536317157, 536317163, 536317219, 536317231, 536317261, 536317283, 536317297, 536317319, 536317321, 536317337, 536317361, 536317363, 536317367, 536317399, 536317409, 536317417, 536317451, 536317469, 536317477, 536317501, 536317511, 536317567, 536317591, 536317609, 536317643, 536317681, 536317687, 536317709, 536317721, 536317783, 536317811, 536317861, 536317879, 536317891, 536317897, 536317907, 536317913, 536317927, 536317931, 536317939, 536317963, 536317981, 536318047, 536318051, 536318053, 536318093, 536318099, 536318113, 536318143, 536318173, 536318177, 536318207, 536318213, 536318221, 536318239, 536318249, 536318297, 536318303, 536318311, 536318351, 536318353, 536318381, 536318401, 536318407, 536318413, 536318429, 536318459, 536318467, 536318473, 536318483, 536318509, 536318543, 536318557, 536318591, 536318611, 536318621, 536318633, 536318647, 536318683, 536318707, 536318711, 536318767, 536318773, 536318777, 536318789, 536318801, 536318891, 536318903, 536318929, 536318933, 536318957, 536318999, 536319001, 536319013, 536319041, 536319059, 536319067, 536319089, 536319139, 536319143, 536319149, 536319151, 536319187, 536319193, 536319239, 536319253, 536319257, 536319283, 536319299, 536319317, 536319323, 536319337, 536319353, 536319361, 536319373, 536319409, 536319431, 536319463, 536319467, 536319493, 536319529, 536319541, 536319559, 536319577, 536319599, 536319601, 536319611, 536319613, 536319629, 536319659, 536319671, 536319673, 536319677, 536319697, 536319701, 536319709, 536319733, 536319737, 536319739, 536319803, 536319827, 536319829, 536319877, 536319907, 536319913, 536319919, 536319923, 536319943, 536319967, 536319989, 536320033, 536320051, 536320067, 536320121, 536320153, 536320159, 536320219, 536320249, 536320271, 536320283, 536320289, 536320307, 536320331, 536320349, 536320361, 536320387, 536320397, 536320399, 536320423, 536320427, 536320457, 536320459, 536320481, 536320501, 536320517, 536320523, 536320531, 536320537, 536320567, 536320579, 536320597, 536320627, 536320637, 536320643, 536320649, 536320669, 536320699, 536320717, 536320747, 536320769, 536320783, 536320787, 536320793, 536320817, 536320819, 536320927, 536320931, 536320937, 536320951, 536320963, 536320973, 536320991, 536321003, 536321039, 536321057, 536321063, 536321077, 536321087, 536321141, 536321207, 536321231, 536321237, 536321249, 536321251, 536321267, 536321293, 536321339, 536321419, 536321449, 536321459, 536321473, 536321479, 536321503, 536321509, 536321551, 536321579, 536321581, 536321587, 536321603, 536321629, 536321651, 536321657, 536321663, 536321693, 536321711, 536321749, 536321789, 536321809, 536321813, 536321833, 536321837, 536321867, 536321869, 536321879, 536321881, 536321887, 536321897, 536321923, 536321957, 536322011, 536322023, 536322049, 536322091, 536322097, 536322113, 536322131, 536322161, 536322169, 536322191, 536322197, 536322209, 536322229, 536322287, 536322301, 536322343, 536322377, 536322383, 536322419, 536322463, 536322467, 536322497, 536322509, 536322541, 536322559, 536322581, 536322583, 536322637, 536322643, 536322667, 536322679, 536322697, 536322707, 536322727, 536322757, 536322767, 536322769, 536322779, 536322793, 536322799, 536322877, 536322883, 536322887, 536322923, 536322929, 536322979, 536323001, 536323003, 536323027, 536323037, 536323061, 536323097, 536323153, 536323181, 536323213, 536323237, 536323283, 536323289, 536323297, 536323313, 536323321, 536323349, 536323351, 536323357, 536323423, 536323441, 536323457, 536323471, 536323519, 536323537, 536323561, 536323597, 536323609, 536323631, 536323643, 536323657, 536323661, 536323679, 536323681, 536323699, 536323717, 536323751, 536323757, 536323787, 536323789, 536323813, 536323831, 536323841, 536323859, 536323873, 536323889, 536323897, 536323933, 536323937, 536323943, 536323967, 536323979, 536323981, 536324027, 536324053, 536324069, 536324071, 536324093, 536324099, 536324147, 536324161, 536324197, 536324203, 536324207, 536324209, 536324227, 536324237, 536324291, 536324297, 536324317, 536324323, 536324351, 536324359, 536324387, 536324401, 536324407, 536324417, 536324441, 536324479, 536324489, 536324491, 536324513, 536324597, 536324623, 536324629, 536324671, 536324693, 536324743, 536324771, 536324779, 536324797, 536324801, 536324839, 536324851, 536324863, 536324911, 536324923, 536324963, 536324969, 536325011, 536325019, 536325047, 536325071, 536325077, 536325121, 536325133, 536325161, 536325221, 536325227, 536325239, 536325269, 536325287, 536325289, 536325329, 536325337, 536325353, 536325403, 536325443, 536325463, 536325473, 536325479, 536325487, 536325509, 536325527, 536325529, 536325533, 536325563, 536325599, 536325617, 536325631, 536325641, 536325667, 536325679, 536325689, 536325697, 536325701, 536325719, 536325731, 536325743, 536325763, 536325851, 536325887, 536325893, 536325917, 536325929, 536325931, 536325949, 536325967, 536326001, 536326003, 536326019, 536326033, 536326039, 536326069, 536326097, 536326111, 536326117, 536326127, 536326139, 536326151, 536326159, 536326177, 536326187, 536326249, 536326267, 536326279, 536326283, 536326303, 536326321, 536326327, 536326337, 536326391, 536326411, 536326429, 536326501, 536326519, 536326529, 536326537, 536326597, 536326607, 536326621, 536326631, 536326639, 536326643, 536326649, 536326669, 536326717, 536326733, 536326751, 536326793, 536326799, 536326801, 536326837, 536326849, 536326853, 536326873, 536326937, 536326963, 536327009, 536327021, 536327039, 536327053, 536327059, 536327093, 536327119, 536327147, 536327149, 536327153, 536327171, 536327219, 536327243, 536327257, 536327263, 536327303, 536327329, 536327333, 536327369, 536327399, 536327411, 536327447, 536327503, 536327531, 536327557, 536327567, 536327579, 536327581, 536327587, 536327629, 536327651, 536327663, 536327707, 536327717, 536327767, 536327783, 536327789, 536327791, 536327819, 536327843, 536327879, 536327881, 536327923, 536327927, 536327933, 536327947, 536327959, 536327971, 536327983, 536328031, 536328047, 536328049, 536328083, 536328097, 536328103, 536328119, 536328127, 536328161, 536328167, 536328173, 536328187, 536328203, 536328259, 536328263, 536328269, 536328301, 536328307, 536328311, 536328337, 536328343, 536328347, 536328361, 536328383, 536328413, 536328449, 536328469, 536328497, 536328509, 536328553, 536328593, 536328601, 536328643, 536328647, 536328649, 536328671, 536328679, 536328691, 536328701, 536328721, 536328731, 536328773, 536328781, 536328829, 536328839, 536328847, 536328851, 536328853, 536328857, 536328893, 536328901, 536328907, 536328997, 536329007, 536329009, 536329021, 536329063, 536329069, 536329081, 536329091, 536329181, 536329193, 536329223, 536329229, 536329247, 536329253, 536329271, 536329273, 536329279, 536329309, 536329363, 536329403, 536329459, 536329463, 536329489, 536329513, 536329517, 536329531, 536329559, 536329601, 536329603, 536329621, 536329627, 536329681, 536329687, 536329697, 536329699, 536329723, 536329757, 536329861, 536329877, 536329879, 536329909, 536329919, 536329933, 536329943, 536329987, 536329993, 536329999, 536330009, 536330021, 536330027, 536330029, 536330057, 536330063, 536330071, 536330083, 536330129, 536330149, 536330153, 536330159, 536330189, 536330213, 536330231, 536330299, 536330323, 536330339, 536330381, 536330383, 536330393, 536330419, 536330453, 536330507, 536330513, 536330533, 536330539, 536330567, 536330617, 536330653, 536330681, 536330699, 536330713, 536330741, 536330749, 536330777, 536330791, 536330819, 536330831, 536330867, 536330869, 536330887, 536330891, 536330911, 536330939, 536330941, 536330953, 536330957, 536331023, 536331041, 536331049, 536331071, 536331091, 536331097, 536331137, 536331167, 536331179, 536331193, 536331233, 536331277, 536331353, 536331359, 536331377, 536331407, 536331421, 536331431, 536331437, 536331443, 536331461, 536331463, 536331469, 536331473, 536331479, 536331491, 536331559, 536331571, 536331577, 536331599, 536331661, 536331673, 536331709, 536331737, 536331743, 536331767, 536331769, 536331781, 536331797, 536331811, 536331823, 536331833, 536331839, 536331853, 536331863, 536331877, 536331881, 536331893, 536331919, 536331923, 536331953, 536331959, 536331967, 536331977, 536332037, 536332039, 536332051, 536332063, 536332079, 536332117, 536332123, 536332127, 536332157, 536332169, 536332189, 536332217, 536332259, 536332273, 536332283, 536332289, 536332297, 536332319, 536332339, 536332373, 536332403, 536332411, 536332417, 536332441, 536332451, 536332477, 536332483, 536332487, 536332499, 536332543, 536332553, 536332571, 536332619, 536332631, 536332633, 536332721, 536332739, 536332781, 536332787, 536332799, 536332843, 536332859, 536332861, 536332879, 536332903, 536332919, 536332921, 536332961, 536332967, 536332981, 536332999, 536333003, 536333009, 536333011, 536333041, 536333053, 536333087, 536333101, 536333107, 536333131, 536333137, 536333183, 536333233, 536333243, 536333249, 536333269, 536333339, 536333351, 536333381, 536333401, 536333443, 536333477, 536333489, 536333507, 536333521, 536333531, 536333543, 536333549, 536333563, 536333579, 536333621, 536333639, 536333641, 536333657, 536333689, 536333713, 536333719, 536333789, 536333813, 536333839, 536333851, 536333857, 536333869, 536333887, 536333893, 536333911, 536333927, 536333933, 536333939, 536333953, 536333971, 536333989, 536333999, 536334011, 536334023, 536334041, 536334067, 536334077, 536334101, 536334103, 536334119, 536334163, 536334179, 536334199, 536334209, 536334221, 536334233, 536334247, 536334257, 536334283, 536334301, 536334311, 536334319, 536334347, 536334353, 536334389, 536334457, 536334511, 536334517, 536334523, 536334529, 536334551, 536334583, 536334599, 536334607, 536334637, 536334691, 536334707, 536334709, 536334791, 536334797, 536334803, 536334809, 536334859, 536334893, 536334913, 536334977, 536334979, 536335003, 536335031, 536335069, 536335073, 536335081, 536335147, 536335157, 536335169, 536335181, 536335231, 536335243, 536335273, 536335279, 536335301, 536335337, 536335339, 536335343, 536335357, 536335379, 536335381, 536335441, 536335463, 536335493, 536335511, 536335529, 536335537, 536335549, 536335559, 536335573, 536335577, 536335649, 536335663, 536335691, 536335721, 536335727, 536335733, 536335741, 536335747, 536335769, 536335777, 536335799, 536335823, 536335841, 536335903, 536335927, 536335931, 536335937, 536335939, 536335951, 536335963, 536335967, 536335993, 536335997, 536336023, 536336051, 536336069, 536336071, 536336083, 536336093, 536336117, 536336131, 536336147, 536336153, 536336167, 536336173, 536336191, 536336209, 536336219, 536336221, 536336233, 536336249, 536336257, 536336261, 536336263, 536336267, 536336299, 536336321, 536336387, 536336399, 536336419, 536336431, 536336453, 536336459, 536336467, 536336477, 536336483, 536336513, 536336531, 536336557, 536336573, 536336597, 536336629, 536336639, 536336651, 536336653, 536336657, 536336659, 536336681, 536336683, 536336687, 536336711, 536336741, 536336753, 536336803, 536336887, 536336903, 536336909, 536336929, 536336947, 536336981, 536336987, 536336989, 536337013, 536337019, 536337037, 536337047, 536337091, 536337127, 536337173, 536337247, 536337283, 536337287, 536337343, 536337349, 536337413, 536337421, 536337433, 536337457, 536337481, 536337499, 536337509, 536337511, 536337563, 536337577, 536337623, 536337631, 536337647, 536337653, 536337673, 536337677, 536337691, 536337721, 536337731, 536337751, 536337761, 536337773, 536337779, 536337797, 536337799, 536337827, 536337883, 536337953, 536337979, 536337983, 536338001, 536338013, 536338027, 536338043, 536338057, 536338063, 536338067, 536338073, 536338079, 536338091, 536338141, 536338163, 536338181, 536338193, 536338207, 536338241, 536338247, 536338279, 536338303, 536338367, 536338391, 536338393, 536338427, 536338433, 536338477, 536338493, 536338501, 536338513, 536338531, 536338549, 536338553, 536338577, 536338603, 536338619, 536338637, 536338639, 536338651, 536338687, 536338709, 536338711, 536338741, 536338801, 536338813, 536338823, 536338837, 536338841, 536338849, 536338877, 536338879, 536338883, 536338903, 536338919, 536338921, 536338927, 536338931, 536338937, 536338951, 536338981, 536338991, 536339003, 536339071, 536339077, 536339099, 536339101, 536339107, 536339113, 536339117, 536339123, 536339159, 536339173, 536339261, 536339263, 536339291, 536339299, 536339303, 536339317, 536339333, 536339351, 536339393, 536339399, 536339411, 536339449, 536339497, 536339501, 536339521, 536339539, 536339563, 536339567, 536339597, 536339641, 536339719, 536339759, 536339761, 536339777, 536339779, 536339801, 536339813, 536339821, 536339831, 536339861, 536339887, 536339933, 536339977, 536340011, 536340017, 536340023, 536340029, 536340041, 536340043, 536340053, 536340061, 536340073, 536340109, 536340131, 536340143, 536340163, 536340173, 536340187, 536340193, 536340209, 536340221, 536340241, 536340283, 536340317, 536340377, 536340403, 536340449, 536340491, 536340523, 536340533, 536340551, 536340583, 536340613, 536340619, 536340643, 536340647, 536340653, 536340659, 536340661, 536340691, 536340719, 536340733, 536340737, 536340767, 536340781, 536340799, 536340809, 536340811, 536340821, 536340823, 536340851, 536340881, 536340907, 536340929, 536340941, 536340983, 536340991, 536340997, 536341027, 536341037, 536341061, 536341073, 536341081, 536341087, 536341123, 536341133, 536341181, 536341217, 536341243, 536341259, 536341297, 536341321, 536341331, 536341343, 536341361, 536341363, 536341373, 536341391, 536341469, 536341489, 536341543, 536341567, 536341583, 536341621, 536341639, 536341643, 536341651, 536341661, 536341697, 536341699, 536341723, 536341733, 536341763, 536341777, 536341811, 536341831, 536341837, 536341847, 536341859, 536341879, 536341907, 536341913, 536341931, 536341961, 536341997, 536342011, 536342029, 536342041, 536342057, 536342063, 536342087, 536342111, 536342113, 536342117, 536342119, 536342141, 536342159, 536342179, 536342189, 536342227, 536342237, 536342243, 536342249, 536342281, 536342291, 536342329, 536342341, 536342347, 536342369, 536342371, 536342381, 536342383, 536342399, 536342423, 536342459, 536342473, 536342489, 536342519, 536342539, 536342549, 536342567, 536342593, 536342603, 536342629, 536342657, 536342663, 536342693, 536342701, 536342767, 536342797, 536342857, 536342869, 536342903, 536342909, 536342959, 536342977, 536342993, 536343011, 536343019, 536343029, 536343053, 536343079, 536343097, 536343127, 536343131, 536343133, 536343151, 536343161, 536343163, 536343169, 536343193, 536343209, 536343253, 536343259, 536343277, 536343317, 536343397, 536343413, 536343433, 536343449, 536343491, 536343499, 536343503, 536343551, 536343553, 536343559, 536343589, 536343653, 536343697, 536343707, 536343721, 536343757, 536343791, 536343793, 536343809, 536343811, 536343833, 536343851, 536343887, 536343889, 536343901, 536343947, 536343953, 536343961, 536344007, 536344019, 536344021, 536344057, 536344097, 536344099, 536344111, 536344121, 536344129, 536344139, 536344157, 536344181, 536344219, 536344243, 536344273, 536344283, 536344309, 536344327, 536344343, 536344399, 536344409, 536344421, 536344439, 536344453, 536344463, 536344481, 536344507, 536344511, 536344537, 536344541, 536344553, 536344591, 536344603, 536344607, 536344619, 536344621, 536344639, 536344649, 536344687, 536344693, 536344703, 536344709, 536344717, 536344727, 536344759, 536344771, 536344799, 536344829, 536344847, 536344867, 536344957, 536344961, 536344967, 536344979, 536344993, 536345041, 536345057, 536345071, 536345077, 536345101, 536345113, 536345137, 536345171, 536345197, 536345203, 536345207, 536345209, 536345221, 536345233, 536345237, 536345267, 536345339, 536345351, 536345363, 536345371, 536345387, 536345389, 536345399, 536345413, 536345429, 536345437, 536345473, 536345479, 536345497, 536345501, 536345503, 536345561, 536345567, 536345569, 536345587, 536345603, 536345609, 536345627, 536345647, 536345651, 536345681, 536345683, 536345687, 536345701, 536345707, 536345731, 536345779, 536345791, 536345867, 536345899, 536345933, 536345939, 536345941, 536345963, 536345983, 536345987, 536346007, 536346023, 536346037, 536346059, 536346091, 536346103, 536346119, 536346137, 536346149, 536346197, 536346199, 536346203, 536346263, 536346319, 536346331, 536346347, 536346367, 536346401, 536346409, 536346479, 536346491, 536346511, 536346523, 536346533, 536346571, 536346607, 536346641, 536346731, 536346737, 536346743, 536346761, 536346799, 536346827, 536346847, 536346887, 536346901, 536346907, 536346911, 536346919, 536346947, 536346949, 536346961, 536346973, 536347001, 536347013, 536347057, 536347061, 536347073, 536347087, 536347103, 536347129, 536347139, 536347159, 536347247, 536347271, 536347303, 536347307, 536347313, 536347321, 536347351, 536347393, 536347417, 536347423, 536347429, 536347453, 536347457, 536347463, 536347481, 536347531, 536347549, 536347573, 536347589, 536347613, 536347619, 536347633, 536347657, 536347687, 536347711, 536347733, 536347769, 536347783, 536347793, 536347813, 536347817, 536347831, 536347843, 536347853, 536347859, 536347871, 536347913, 536347919, 536347951, 536347963, 536347991, 536347993, 536348027, 536348039, 536348047, 536348053, 536348083, 536348123, 536348149, 536348167, 536348177, 536348179, 536348203, 536348209, 536348213, 536348231, 536348233, 536348237, 536348251, 536348257, 536348273, 536348299, 536348311, 536348363, 536348377, 536348381, 536348383, 536348399, 536348401, 536348441, 536348471, 536348479, 536348497, 536348509, 536348543, 536348551, 536348567, 536348629, 536348671, 536348699, 536348713, 536348717, 536348719, 536348741, 536348749, 536348789, 536348797, 536348801, 536348803, 536348807, 536348821, 536348831, 536348833, 536348849, 536348863, 536348867, 536348903, 536348947, 536348951, 536349001, 536349041, 536349059, 536349083, 536349089, 536349139, 536349179, 536349193, 536349199, 536349257, 536349301, 536349311, 536349343, 536349349, 536349389, 536349419, 536349427, 536349467, 536349479, 536349481, 536349487, 536349493, 536349497, 536349503, 536349533, 536349553, 536349557, 536349563, 536349599, 536349607, 536349623, 536349629, 536349647, 536349661, 536349679, 536349683, 536349721, 536349731, 536349733, 536349767, 536349769, 536349797, 536349851, 536349859, 536349871, 536349883, 536349887, 536349899, 536349911, 536349937, 536349953, 536349959, 536349971, 536350013, 536350021, 536350049, 536350057, 536350141, 536350147, 536350159, 536350163, 536350201, 536350207, 536350219, 536350231, 536350237, 536350253, 536350267, 536350279, 536350307, 536350327, 536350333, 536350351, 536350361, 536350387, 536350403, 536350429, 536350433, 536350453, 536350471, 536350489, 536350531, 536350609, 536350669, 536350687, 536350691, 536350693, 536350709, 536350721, 536350751, 536350781, 536350847, 536350861, 536350877, 536350883, 536350921, 536350931, 536350949, 536350951, 536350957, 536350963, 536350967, 536350993, 536350999, 536351009, 536351017, 536351029, 536351041, 536351047, 536351051, 536351059, 536351077, 536351087, 536351117, 536351129, 536351131, 536351141, 536351159, 536351183, 536351197, 536351261, 536351267, 536351273, 536351293, 536351311, 536351351, 536351363, 536351419, 536351423, 536351441, 536351447, 536351489, 536351503, 536351507, 536351531, 536351567, 536351579, 536351587, 536351623, 536351657, 536351681, 536351687, 536351693, 536351737, 536351747, 536351749, 536351773, 536351807, 536351813, 536351843, 536351903, 536351917, 536351923, 536351929, 536351957, 536351983, 536352017, 536352041, 536352043, 536352079, 536352101, 536352139, 536352143, 536352149, 536352169, 536352217, 536352239, 536352293, 536352367, 536352371, 536352403, 536352437, 536352473, 536352491, 536352503, 536352541, 536352559, 536352581, 536352667, 536352679, 536352683, 536352689, 536352697, 536352701, 536352721, 536352727, 536352763, 536352779, 536352787, 536352797, 536352863, 536352899, 536352911, 536352953, 536352997, 536353019, 536353039, 536353087, 536353093, 536353177, 536353183, 536353189, 536353211, 536353217, 536353243, 536353277, 536353283, 536353309, 536353313, 536353333, 536353343, 536353373, 536353379, 536353459, 536353469, 536353501, 536353507, 536353511, 536353529, 536353547, 536353711, 536353729, 536353747, 536353777, 536353817, 536353819, 536353877, 536353889, 536353891, 536353901, 536353903, 536353913, 536353931, 536353943, 536353967, 536353969, 536353981, 536353991, 536353999, 536354017, 536354057, 536354081, 536354107, 536354113, 536354129, 536354197, 536354213, 536354237, 536354261, 536354293, 536354303, 536354311, 536354321, 536354341, 536354359, 536354381, 536354407, 536354431, 536354443, 536354473, 536354491, 536354501, 536354521, 536354537, 536354557, 536354561, 536354563, 536354603, 536354669, 536354677, 536354711, 536354737, 536354747, 536354759, 536354773, 536354809, 536354831, 536354837, 536354873, 536354893, 536354911, 536354921, 536354969, 536354993, 536354999, 536355007, 536355011, 536355019, 536355041, 536355059, 536355067, 536355077, 536355089, 536355109, 536355121, 536355133, 536355173, 536355221, 536355223, 536355227, 536355233, 536355241, 536355257, 536355271, 536355277, 536355289, 536355343, 536355359, 536355361, 536355409, 536355451, 536355499, 536355509, 536355553, 536355557, 536355581, 536355619, 536355623, 536355629, 536355637, 536355643, 536355719, 536355733, 536355739, 536355751, 536355761, 536355773, 536355793, 536355817, 536355823, 536355889, 536355949, 536355979, 536355983, 536355991, 536356003, 536356019, 536356031, 536356049, 536356063, 536356087, 536356091, 536356129, 536356147, 536356193, 536356207, 536356217, 536356229, 536356231, 536356253, 536356267, 536356277, 536356291, 536356321, 536356333, 536356349, 536356351, 536356357, 536356361, 536356367, 536356369, 536356397, 536356399, 536356417, 536356423, 536356427, 536356441, 536356463, 536356519, 536356531, 536356543, 536356559, 536356577, 536356651, 536356663, 536356693, 536356721, 536356727, 536356729, 536356753, 536356771, 536356789, 536356813, 536356829, 536356861, 536356883, 536356901, 536356907, 536356927, 536356969, 536356973, 536356981, 536356999, 536357011, 536357047, 536357051, 536357093, 536357161, 536357183, 536357219, 536357231, 536357243, 536357267, 536357299, 536357317, 536357321, 536357351, 536357363, 536357383, 536357399, 536357411, 536357453, 536357473, 536357477, 536357527, 536357543, 536357557, 536357573, 536357597, 536357621, 536357641, 536357651, 536357659, 536357671, 536357761, 536357819, 536357831, 536357903, 536357917, 536357993, 536358013, 536358029, 536358037, 536358061, 536358073, 536358107, 536358113, 536358149, 536358157, 536358169, 536358181, 536358197, 536358209, 536358223, 536358227, 536358281, 536358323, 536358337, 536358341, 536358349, 536358397, 536358443, 536358481, 536358503, 536358523, 536358527, 536358539, 536358547, 536358553, 536358577, 536358607, 536358617, 536358659, 536358661, 536358677, 536358703, 536358709, 536358749, 536358763, 536358817, 536358821, 536358833, 536358839, 536358841, 536358859, 536358871, 536358899, 536358937, 536358947, 536358983, 536359013, 536359051, 536359073, 536359111, 536359127, 536359157, 536359183, 536359193, 536359199, 536359207, 536359211, 536359249, 536359261, 536359273, 536359277, 536359309, 536359331, 536359337, 536359349, 536359357, 536359381, 536359391, 536359409, 536359423, 536359451, 536359477, 536359507, 536359513, 536359541, 536359547, 536359559, 536359561, 536359567, 536359583, 536359627, 536359643, 536359651, 536359661, 536359667, 536359687, 536359729, 536359739, 536359751, 536359753, 536359757, 536359777, 536359781, 536359783, 536359801, 536359819, 536359867, 536359871, 536359933, 536359937, 536359939, 536359961, 536359963, 536359969, 536359997, 536360039, 536360059, 536360089, 536360093, 536360107, 536360117, 536360119, 536360147, 536360173, 536360179, 536360189, 536360203, 536360257, 536360261, 536360267, 536360347, 536360411, 536360417, 536360471, 536360479, 536360491, 536360509, 536360533, 536360537, 536360567, 536360581, 536360599, 536360623, 536360653, 536360677, 536360707, 536360743, 536360749, 536360753, 536360777, 536360779, 536360807, 536360809, 536360831, 536360833, 536360849, 536360873, 536360879, 536360911, 536360939, 536360947, 536360953, 536360969, 536361011, 536361017, 536361019, 536361041, 536361047, 536361071, 536361073, 536361103, 536361109, 536361131, 536361143, 536361187, 536361191, 536361233, 536361239, 536361251, 536361263, 536361269, 536361283, 536361289, 536361299, 536361307, 536361323, 536361341, 536361347, 536361379, 536361383, 536361401, 536361421, 536361451, 536361461, 536361487, 536361493, 536361499, 536361517, 536361547, 536361559, 536361563, 536361613, 536361629, 536361653, 536361677, 536361703, 536361719, 536361737, 536361751, 536361797, 536361803, 536361823, 536361851, 536361857, 536361871, 536361901, 536361911, 536361913, 536361929, 536361983, 536361997, 536362033, 536362037, 536362049, 536362061, 536362111, 536362157, 536362159, 536362201, 536362213, 536362241, 536362243, 536362331, 536362357, 536362391, 536362399, 536362423, 536362441, 536362469, 536362487, 536362493, 536362531, 536362559, 536362639, 536362643, 536362681, 536362709, 536362741, 536362753, 536362759, 536362789, 536362817, 536362843, 536362847, 536362891, 536362907, 536362927, 536362933, 536362963, 536362969, 536362973, 536362979, 536362987, 536362993, 536363017, 536363071, 536363081, 536363101, 536363111, 536363117, 536363161, 536363213, 536363231, 536363237, 536363263, 536363279, 536363309, 536363363, 536363393, 536363411, 536363417, 536363431, 536363441, 536363459, 536363461, 536363489, 536363533, 536363563, 536363593, 536363677, 536363689, 536363713, 536363741, 536363747, 536363761, 536363783, 536363797, 536363809, 536363813, 536363851, 536363857, 536363909, 536363959, 536363987, 536364007, 536364043, 536364067, 536364079, 536364083, 536364097, 536364109, 536364113, 536364131, 536364137, 536364149, 536364151, 536364181, 536364223, 536364233, 536364239, 536364271, 536364299, 536364379, 536364383, 536364391, 536364401, 536364473, 536364497, 536364527, 536364559, 536364581, 536364589, 536364593, 536364607, 536364613, 536364649, 536364659, 536364667, 536364677, 536364683, 536364707, 536364709, 536364767, 536364781, 536364797, 536364809, 536364827, 536364859, 536364869, 536364877, 536364953, 536364967, 536364971, 536364989, 536365019, 536365031, 536365043, 536365051, 536365099, 536365127, 536365153, 536365171, 536365177, 536365199, 536365201, 536365241, 536365289, 536365303, 536365331, 536365369, 536365381, 536365387, 536365397, 536365409, 536365429, 536365433, 536365447, 536365471, 536365481, 536365513, 536365517, 536365597, 536365601, 536365631, 536365633, 536365667, 536365673, 536365693, 536365717, 536365723, 536365733, 536365747, 536365771, 536365787, 536365799, 536365811, 536365829, 536365859, 536365871, 536365891, 536365897, 536365901, 536365909, 536365919, 536365931, 536365943, 536365979, 536365981, 536365987, 536365993, 536366041, 536366053, 536366063, 536366081, 536366101, 536366119, 536366179, 536366183, 536366189, 536366231, 536366267, 536366297, 536366321, 536366323, 536366329, 536366353, 536366357, 536366359, 536366377, 536366399, 536366401, 536366407, 536366419, 536366443, 536366483, 536366521, 536366539, 536366543, 536366549, 536366573, 536366587, 536366639, 536366651, 536366653, 536366707, 536366729, 536366771, 536366819, 536366849, 536366851, 536366891, 536366917, 536366933, 536366947, 536367019, 536367047, 536367067, 536367077, 536367089, 536367109, 536367113, 536367179, 536367191, 536367211, 536367217, 536367229, 536367233, 536367257, 536367263, 536367277, 536367313, 536367319, 536367341, 536367343, 536367373, 536367379, 536367401, 536367437, 536367463, 536367479, 536367523, 536367539, 536367547, 536367551, 536367569, 536367589, 536367599, 536367649, 536367653, 536367679, 536367691, 536367737, 536367743, 536367749, 536367757, 536367773, 536367787, 536367817, 536367857, 536367869, 536367877, 536367959, 536367991, 536368033, 536368039, 536368061, 536368067, 536368069, 536368093, 536368099, 536368127, 536368141, 536368153, 536368159, 536368171, 536368219, 536368229, 536368247, 536368267, 536368307, 536368319, 536368333, 536368337, 536368361, 536368373, 536368397, 536368409, 536368457, 536368463, 536368477, 536368523, 536368531, 536368571, 536368597, 536368607, 536368631, 536368633, 536368643, 536368661, 536368663, 536368691, 536368697, 536368709, 536368733, 536368769, 536368771, 536368787, 536368801, 536368813, 536368829, 536368831, 536368843, 536368849, 536368867, 536368927, 536368933, 536368939, 536368951, 536368961, 536368981, 536369017, 536369047, 536369081, 536369083, 536369087, 536369089, 536369129, 536369153, 536369167, 536369173, 536369191, 536369201, 536369233, 536369291, 536369293, 536369299, 536369369, 536369377, 536369423, 536369443, 536369459, 536369467, 536369507, 536369569, 536369579, 536369599, 536369651, 536369689, 536369693, 536369711, 536369731, 536369747, 536369759, 536369777, 536369783, 536369809, 536369849, 536369851, 536369857, 536369863, 536369879, 536369881, 536369903, 536369929, 536369963, 536369971, 536369989, 536370007, 536370047, 536370049, 536370061, 536370067, 536370071, 536370083, 536370101, 536370103, 536370137, 536370169, 536370181, 536370187, 536370217, 536370223, 536370257, 536370269, 536370293, 536370299, 536370311, 536370313, 536370343, 536370379, 536370397, 536370409, 536370469, 536370473, 536370503, 536370509, 536370539, 536370607, 536370613, 536370619, 536370661, 536370673, 536370697, 536370713, 536370727, 536370761, 536370763, 536370811, 536370839, 536370841, 536370853, 536370881, 536370883, 536370917, 536370929, 536370937, 536370943, 536370953, 536370977, 536370997, 536371027, 536371039, 536371067, 536371081, 536371093, 536371117, 536371127, 536371139, 536371141, 536371151, 536371163, 536371229, 536371249, 536371259, 536371271, 536371279, 536371313, 536371333, 536371343, 536371361, 536371391, 536371397, 536371399, 536371427, 536371441, 536371453, 536371487, 536371519, 536371609, 536371621, 536371631, 536371639, 536371643, 536371657, 536371679, 536371727, 536371747, 536371757, 536371763, 536371793, 536371831, 536371853, 536371867, 536371873, 536371883, 536371903, 536371921, 536371933, 536371973, 536371991, 536372003, 536372021, 536372027, 536372069, 536372077, 536372087, 536372093, 536372101, 536372129, 536372149, 536372183, 536372231, 536372279, 536372293, 536372327, 536372341, 536372359, 536372393, 536372401, 536372407, 536372471, 536372479, 536372483, 536372533, 536372563, 536372579, 536372597, 536372611, 536372647, 536372653, 536372657, 536372671, 536372677, 536372723, 536372741, 536372743, 536372779, 536372801, 536372803, 536372807, 536372839, 536372867, 536372873, 536372887, 536372891, 536372909, 536372911, 536372929, 536372957, 536372981, 536372987, 536373017, 536373023, 536373049, 536373083, 536373113, 536373119, 536373139, 536373151, 536373169, 536373199, 536373209, 536373217, 536373247, 536373283, 536373293, 536373337, 536373361, 536373367, 536373373, 536373379, 536373403, 536373407, 536373419, 536373437, 536373449, 536373463, 536373479, 536373517, 536373527, 536373557, 536373569, 536373577, 536373583, 536373623, 536373653, 536373707, 536373713, 536373737, 536373791, 536373797, 536373829, 536373847, 536373853, 536373863, 536373883, 536373889, 536373911, 536373923, 536373947, 536373967, 536374001, 536374019, 536374073, 536374117, 536374147, 536374187, 536374193, 536374229, 536374249, 536374271, 536374273, 536374277, 536374291, 536374309, 536374357, 536374367, 536374381, 536374409, 536374417, 536374439, 536374477, 536374507, 536374511, 536374519, 536374543, 536374549, 536374571, 536374589, 536374603, 536374627, 536374637, 536374739, 536374771, 536374781, 536374799, 536374879, 536374901, 536374907, 536374919, 536374931, 536374961, 536374963, 536375009, 536375017, 536375027, 536375093, 536375129, 536375153, 536375171, 536375173, 536375207, 536375221, 536375297, 536375303, 536375351, 536375383, 536375429, 536375447, 536375459, 536375467, 536375473, 536375513, 536375519, 536375527, 536375537, 536375557, 536375629, 536375633, 536375639, 536375641, 536375683, 536375711, 536375731, 536375747, 536375767, 536375771, 536375773, 536375779, 536375837, 536375839, 536375869, 536375887, 536375911, 536375923, 536375929, 536375933, 536375977, 536376007, 536376017, 536376067, 536376089, 536376091, 536376121, 536376131, 536376149, 536376179, 536376193, 536376221, 536376223, 536376241, 536376283, 536376287, 536376301, 536376331, 536376343, 536376371, 536376433, 536376437, 536376481, 536376521, 536376523, 536376557, 536376569, 536376619, 536376623, 536376647, 536376649, 536376661, 536376689, 536376697, 536376751, 536376773, 536376781, 536376791, 536376811, 536376817, 536376823, 536376829, 536376851, 536376881, 536376887, 536376913, 536376949, 536376961, 536376977, 536376991, 536377001, 536377067, 536377073, 536377111, 536377157, 536377169, 536377187, 536377223, 536377229, 536377241, 536377249, 536377253, 536377297, 536377307, 536377327, 536377333, 536377339, 536377343, 536377349, 536377351, 536377363, 536377379, 536377393, 536377397, 536377427, 536377433, 536377441, 536377459, 536377477, 536377481, 536377483, 536377507, 536377511, 536377559, 536377561, 536377601, 536377603, 536377651, 536377711, 536377741, 536377747, 536377763, 536377811, 536377837, 536377843, 536377873, 536377889, 536377921, 536377927, 536377957, 536377969, 536377979, 536377993, 536378041, 536378071, 536378077, 536378093, 536378099, 536378137, 536378177, 536378191, 536378197, 536378221, 536378251, 536378257, 536378273, 536378291, 536378309, 536378327, 536378329, 536378389, 536378393, 536378413, 536378471, 536378473, 536378489, 536378501, 536378503, 536378533, 536378537, 536378539, 536378567, 536378597, 536378599, 536378651, 536378671, 536378681, 536378707, 536378719, 536378761, 536378767, 536378807, 536378813, 536378827, 536378891, 536378893, 536378903, 536378959, 536378963, 536378977, 536379007, 536379013, 536379017, 536379071, 536379131, 536379149, 536379167, 536379169, 536379187, 536379191, 536379197, 536379241, 536379301, 536379307, 536379317, 536379341, 536379409, 536379433, 536379439, 536379457, 536379497, 536379499, 536379521, 536379541, 536379553, 536379559, 536379581, 536379611, 536379629, 536379643, 536379673, 536379677, 536379719, 536379773, 536379841, 536379847, 536379859, 536379863, 536379871, 536379881, 536379919, 536379929, 536379989, 536380007, 536380037, 536380043, 536380067, 536380069, 536380153, 536380189, 536380211, 536380261, 536380283, 536380333, 536380337, 536380349, 536380391, 536380423, 536380451, 536380459, 536380463, 536380477, 536380487, 536380489, 536380499, 536380501, 536380513, 536380519, 536380531, 536380541, 536380547, 536380553, 536380577, 536380597, 536380639, 536380657, 536380673, 536380681, 536380687, 536380699, 536380709, 536380711, 536380721, 536380727, 536380729, 536380739, 536380751, 536380759, 536380771, 536380799, 536380837, 536380891, 536380903, 536380921, 536380939, 536380951, 536380961, 536380969, 536380987, 536381051, 536381107, 536381117, 536381171, 536381173, 536381207, 536381221, 536381233, 536381239, 536381243, 536381273, 536381309, 536381347, 536381353, 536381387, 536381423, 536381471, 536381513, 536381519, 536381537, 536381543, 536381581, 536381591, 536381653, 536381663, 536381687, 536381693, 536381707, 536381717, 536381737, 536381759, 536381777, 536381831, 536381849, 536381861, 536381863, 536381869, 536381887, 536381903, 536381953, 536381987, 536382017, 536382019, 536382029, 536382031, 536382059, 536382083, 536382107, 536382127, 536382167, 536382169, 536382193, 536382199, 536382247, 536382277, 536382281, 536382299, 536382391, 536382401, 536382421, 536382449, 536382461, 536382529, 536382571, 536382593, 536382661, 536382683, 536382751, 536382767, 536382799, 536382823, 536382829, 536382851, 536382859, 536382871, 536382877, 536382881, 536382887, 536382893, 536382907, 536382923, 536382953, 536382961, 536382967, 536382971, 536382991, 536383007, 536383021, 536383093, 536383123, 536383139, 536383171, 536383229, 536383249, 536383259, 536383271, 536383273, 536383301, 536383321, 536383327, 536383343, 536383369, 536383381, 536383387, 536383399, 536383409, 536383417, 536383447, 536383451, 536383481, 536383489, 536383493, 536383501, 536383511, 536383543, 536383597, 536383619, 536383649, 536383657, 536383697, 536383717, 536383753, 536383769, 536383777, 536383781, 536383801, 536383807, 536383817, 536383829, 536383867, 536383871, 536383873, 536383879, 536383901, 536383909, 536383973, 536383997, 536383999, 536384011, 536384027, 536384039, 536384053, 536384077, 536384083, 536384113, 536384131, 536384141, 536384143, 536384171, 536384201, 536384207, 536384209, 536384213, 536384273, 536384287, 536384293, 536384309, 536384341, 536384369, 536384389, 536384441, 536384467, 536384501, 536384521, 536384533, 536384549, 536384557, 536384669, 536384699, 536384707, 536384743, 536384791, 536384803, 536384809, 536384851, 536384869, 536384879, 536384903, 536384911, 536384917, 536384921, 536384923, 536384941, 536384983, 536384987, 536385007, 536385019, 536385023, 536385079, 536385089, 536385119, 536385127, 536385137, 536385149, 536385163, 536385167, 536385217, 536385221, 536385233, 536385253, 536385299, 536385331, 536385341, 536385347, 536385361, 536385401, 536385449, 536385469, 536385481, 536385497, 536385503, 536385539, 536385557, 536385587, 536385593, 536385601, 536385611, 536385613, 536385659, 536385709, 536385721, 536385763, 536385779, 536385799, 536385809, 536385833, 536385841, 536385907, 536385911, 536385937, 536385953, 536385961, 536385973, 536386009, 536386049, 536386061, 536386073, 536386139, 536386141, 536386163, 536386177, 536386217, 536386241, 536386259, 536386267, 536386339, 536386369, 536386439, 536386451, 536386453, 536386489, 536386531, 536386547, 536386561, 536386573, 536386589, 536386619, 536386633, 536386649, 536386661, 536386679, 536386691, 536386709, 536386727, 536386787, 536386793, 536386801, 536386819, 536386843, 536386849, 536386901, 536386927, 536386957, 536386973, 536386993, 536387021, 536387053, 536387107, 536387123, 536387177, 536387191, 536387207, 536387221, 536387227, 536387263, 536387329, 536387333, 536387339, 536387351, 536387353, 536387377, 536387407, 536387419, 536387431, 536387437, 536387441, 536387443, 536387447, 536387471, 536387477, 536387521, 536387539, 536387563, 536387581, 536387591, 536387639, 536387647, 536387671, 536387713, 536387717, 536387737, 536387767, 536387771, 536387773, 536387809, 536387827, 536387851, 536387911, 536387933, 536387941, 536387963, 536387987, 536388007, 536388049, 536388077, 536388079, 536388091, 536388103, 536388113, 536388119, 536388161, 536388163, 536388169, 536388179, 536388197, 536388211, 536388239, 536388253, 536388269, 536388271, 536388289, 536388323, 536388329, 536388337, 536388341, 536388343, 536388383, 536388431, 536388439, 536388499, 536388509, 536388521, 536388569, 536388571, 536388583, 536388631, 536388649, 536388653, 536388661, 536388683, 536388701, 536388703, 536388707, 536388719, 536388731, 536388733, 536388821, 536388823, 536388833, 536388851, 536388857, 536388869, 536388871, 536388893, 536388899, 536388917, 536388949, 536388953, 536388961, 536388971, 536388973, 536388989, 536388997, 536389013, 536389093, 536389157, 536389159, 536389169, 536389193, 536389201, 536389207, 536389213, 536389261, 536389277, 536389283, 536389291, 536389303, 536389349, 536389367, 536389391, 536389397, 536389459, 536389489, 536389499, 536389507, 536389517, 536389519, 536389523, 536389541, 536389543, 536389547, 536389549, 536389613, 536389639, 536389657, 536389669, 536389673, 536389681, 536389691, 536389717, 536389747, 536389769, 536389781, 536389801, 536389859, 536389871, 536389879, 536389927, 536389937, 536389949, 536389963, 536390009, 536390021, 536390047, 536390077, 536390087, 536390189, 536390191, 536390201, 536390219, 536390233, 536390237, 536390243, 536390269, 536390287, 536390339, 536390353, 536390359, 536390363, 536390377, 536390399, 536390401, 536390411, 536390453, 536390509, 536390527, 536390531, 536390549, 536390609, 536390623, 536390633, 536390639, 536390663, 536390671, 536390689, 536390711, 536390779, 536390791, 536390809, 536390909, 536390927, 536390941, 536390963, 536390983, 536391017, 536391019, 536391059, 536391091, 536391133, 536391161, 536391169, 536391181, 536391187, 536391199, 536391253, 536391263, 536391269, 536391301, 536391311, 536391313, 536391353, 536391367, 536391379, 536391391, 536391407, 536391433, 536391461, 536391467, 536391521, 536391523, 536391529, 536391587, 536391601, 536391607, 536391629, 536391631, 536391659, 536391673, 536391689, 536391707, 536391719, 536391731, 536391781, 536391787, 536391799, 536391827, 536391851, 536391857, 536391887, 536391893, 536391949, 536391953, 536391979, 536392009, 536392037, 536392049, 536392061, 536392063, 536392081, 536392099, 536392117, 536392121, 536392123, 536392133, 536392139, 536392141, 536392159, 536392183, 536392201, 536392229, 536392237, 536392267, 536392301, 536392309, 536392327, 536392331, 536392333, 536392369, 536392387, 536392399, 536392403, 536392421, 536392427, 536392511, 536392547, 536392559, 536392561, 536392567, 536392573, 536392583, 536392607, 536392609, 536392643, 536392657, 536392669, 536392673, 536392679, 536392697, 536392711, 536392733, 536392757, 536392837, 536392841, 536392877, 536392889, 536392897, 536392919, 536392937, 536392939, 536392951, 536392963, 536392973, 536392981, 536392991, 536393003, 536393021, 536393057, 536393059, 536393063, 536393071, 536393083, 536393087, 536393141, 536393149, 536393171, 536393177, 536393213, 536393233, 536393257, 536393293, 536393303, 536393321, 536393339, 536393359, 536393381, 536393399, 536393437, 536393471, 536393521, 536393531, 536393573, 536393609, 536393623, 536393629, 536393659, 536393677, 536393743, 536393749, 536393783, 536393791, 536393849, 536393863, 536393881, 536393887, 536393903, 536393909, 536393927, 536393981, 536393983, 536393989, 536393993, 536394031, 536394037, 536394049, 536394059, 536394071, 536394077, 536394119, 536394139, 536394151, 536394197, 536394203, 536394211, 536394227, 536394239, 536394323, 536394329, 536394337, 536394343, 536394359, 536394361, 536394371, 536394373, 536394401, 536394403, 536394473, 536394493, 536394497, 536394499, 536394511, 536394517, 536394539, 536394541, 536394601, 536394613, 536394629, 536394637, 536394641, 536394647, 536394667, 536394679, 536394689, 536394713, 536394731, 536394743, 536394751, 536394763, 536394769, 536394797, 536394811, 536394869, 536394893, 536394913, 536394917, 536394919, 536394967, 536394979, 536395007, 536395009, 536395051, 536395063, 536395081, 536395091, 536395103, 536395117, 536395151, 536395157, 536395177, 536395193, 536395231, 536395241, 536395243, 536395247, 536395291, 536395297, 536395303, 536395309, 536395319, 536395361, 536395399, 536395411, 536395417, 536395427, 536395439, 536395451, 536395477, 536395481, 536395529, 536395567, 536395589, 536395603, 536395621, 536395633, 536395663, 536395667, 536395721, 536395757, 536395789, 536395793, 536395799, 536395807, 536395813, 536395837, 536395843, 536395877, 536395879, 536395927, 536395961, 536395967, 536396009, 536396023, 536396027, 536396033, 536396039, 536396051, 536396059, 536396083, 536396111, 536396167, 536396183, 536396191, 536396207, 536396213, 536396221, 536396227, 536396249, 536396269, 536396321, 536396347, 536396369, 536396431, 536396449, 536396453, 536396459, 536396489, 536396507, 536396513, 536396519, 536396527, 536396579, 536396587, 536396617, 536396633, 536396647, 536396701, 536396717, 536396719, 536396723, 536396747, 536396761, 536396821, 536396837, 536396849, 536396867, 536396909, 536396953, 536396981, 536397013, 536397023, 536397089, 536397097, 536397131, 536397139, 536397161, 536397167, 536397181, 536397187, 536397193, 536397203, 536397221, 536397223, 536397263, 536397271, 536397299, 536397317, 536397347, 536397359, 536397409, 536397431, 536397469, 536397479, 536397539, 536397541, 536397551, 536397593, 536397613, 536397637, 536397643, 536397647, 536397677, 536397689, 536397703, 536397739, 536397751, 536397761, 536397767, 536397773, 536397791, 536397811, 536397839, 536397847, 536397859, 536397899, 536397931, 536397937, 536397947, 536397959, 536398003, 536398021, 536398043, 536398067, 536398073, 536398117, 536398153, 536398189, 536398217, 536398223, 536398237, 536398259, 536398271, 536398307, 536398309, 536398327, 536398333, 536398337, 536398339, 536398391, 536398403, 536398411, 536398417, 536398439, 536398453, 536398459, 536398463, 536398477, 536398493, 536398517, 536398523, 536398537, 536398547, 536398591, 536398601, 536398619, 536398631, 536398649, 536398669, 536398693, 536398699, 536398721, 536398741, 536398769, 536398771, 536398787, 536398789, 536398829, 536398843, 536398873, 536398901, 536398931, 536398969, 536398997, 536399033, 536399041, 536399057, 536399063, 536399099, 536399117, 536399131, 536399141, 536399153, 536399179, 536399189, 536399207, 536399209, 536399219, 536399257, 536399309, 536399321, 536399327, 536399371, 536399377, 536399407, 536399429, 536399459, 536399483, 536399489, 536399509, 536399519, 536399527, 536399569, 536399593, 536399599, 536399653, 536399663, 536399711, 536399713, 536399723, 536399741, 536399771, 536399797, 536399869, 536399873, 536399933, 536399953, 536399957, 536399971, 536399977, 536399987, 536399993, 536400041, 536400061, 536400079, 536400083, 536400107, 536400119, 536400127, 536400157, 536400173, 536400187, 536400217, 536400287, 536400289, 536400341, 536400349, 536400379, 536400401, 536400407, 536400421, 536400451, 536400479, 536400481, 536400509, 536400521, 536400547, 536400587, 536400589, 536400607, 536400611, 536400653, 536400691, 536400703, 536400713, 536400751, 536400817, 536400841, 536400857, 536400899, 536400901, 536400937, 536400941, 536400947, 536400971, 536401039, 536401069, 536401079, 536401087, 536401093, 536401097, 536401123, 536401157, 536401163, 536401189, 536401211, 536401213, 536401223, 536401241, 536401249, 536401279, 536401363, 536401381, 536401409, 536401433, 536401441, 536401447, 536401451, 536401471, 536401501, 536401507, 536401511, 536401577, 536401589, 536401633, 536401643, 536401667, 536401709, 536401721, 536401727, 536401757, 536401763, 536401783, 536401793, 536401819, 536401849, 536401903, 536401967, 536401979, 536402033, 536402039, 536402047, 536402059, 536402063, 536402077, 536402093, 536402107, 536402147, 536402149, 536402171, 536402177, 536402197, 536402203, 536402227, 536402239, 536402249, 536402263, 536402287, 536402291, 536402327, 536402333, 536402351, 536402353, 536402359, 536402387, 536402401, 536402413, 536402417, 536402441, 536402443, 536402507, 536402551, 536402567, 536402569, 536402591, 536402593, 536402599, 536402611, 536402627, 536402651, 536402701, 536402719, 536402749, 536402753, 536402761, 536402767, 536402773, 536402837, 536402861, 536402873, 536402897, 536402899, 536402939, 536402953, 536402981, 536403019, 536403031, 536403067, 536403071, 536403121, 536403143, 536403157, 536403173, 536403229, 536403233, 536403247, 536403251, 536403253, 536403271, 536403277, 536403289, 536403299, 536403313, 536403337, 536403347, 536403377, 536403379, 536403389, 536403391, 536403403, 536403419, 536403521, 536403529, 536403551, 536403563, 536403583, 536403587, 536403599, 536403613, 536403643, 536403653, 536403667, 536403701, 536403719, 536403739, 536403773, 536403821, 536403853, 536403859, 536403863, 536403871, 536403883, 536403929, 536403961, 536403971, 536404007, 536404019, 536404027, 536404061, 536404069, 536404081, 536404087, 536404093, 536404117, 536404153, 536404177, 536404199, 536404201, 536404237, 536404261, 536404273, 536404289, 536404313, 536404331, 536404339, 536404357, 536404487, 536404493, 536404571, 536404579, 536404633, 536404639, 536404667, 536404697, 536404703, 536404711, 536404721, 536404777, 536404807, 536404837, 536404849, 536404861, 536404867, 536404889, 536404907, 536404933, 536404951, 536404963, 536404969, 536404987, 536404993, 536405039, 536405087, 536405113, 536405117, 536405123, 536405153, 536405161, 536405171, 536405189, 536405197, 536405203, 536405227, 536405281, 536405297, 536405329, 536405341, 536405347, 536405381, 536405393, 536405399, 536405423, 536405447, 536405491, 536405557, 536405579, 536405591, 536405599, 536405629, 536405651, 536405657, 536405699, 536405711, 536405713, 536405717, 536405719, 536405773, 536405801, 536405809, 536405851, 536405861, 536405867, 536405869, 536405897, 536405939, 536405959, 536405999, 536406019, 536406041, 536406053, 536406061, 536406067, 536406077, 536406089, 536406139, 536406173, 536406179, 536406187, 536406191, 536406223, 536406281, 536406307, 536406313, 536406317, 536406329, 536406371, 536406373, 536406379, 536406397, 536406401, 536406463, 536406503, 536406509, 536406517, 536406523, 536406539, 536406551, 536406557, 536406569, 536406683, 536406691, 536406709, 536406719, 536406749, 536406751, 536406779, 536406853, 536406869, 536406877, 536406887, 536406901, 536406907, 536406929, 536406931, 536406961, 536406991, 536407009, 536407021, 536407049, 536407051, 536407063, 536407073, 536407121, 536407133, 536407147, 536407169, 536407243, 536407283, 536407349, 536407351, 536407367, 536407369, 536407379, 536407423, 536407439, 536407447, 536407481, 536407493, 536407523, 536407549, 536407559, 536407589, 536407603, 536407609, 536407621, 536407637, 536407657, 536407661, 536407687, 536407691, 536407727, 536407733, 536407813, 536407847, 536407877, 536407889, 536407891, 536407931, 536407933, 536407957, 536407967, 536407979, 536408003, 536408009, 536408023, 536408051, 536408113, 536408137, 536408141, 536408143, 536408149, 536408153, 536408219, 536408233, 536408237, 536408239, 536408261, 536408269, 536408287, 536408291, 536408297, 536408317, 536408357, 536408363, 536408381, 536408413, 536408419, 536408423, 536408443, 536408449, 536408459, 536408501, 536408557, 536408569, 536408591, 536408597, 536408611, 536408623, 536408651, 536408659, 536408681, 536408723, 536408749, 536408773, 536408797, 536408819, 536408833, 536408857, 536408867, 536408881, 536408897, 536408941, 536408981, 536408987, 536409043, 536409067, 536409101, 536409103, 536409193, 536409217, 536409227, 536409233, 536409241, 536409253, 536409281, 536409287, 536409299, 536409301, 536409353, 536409359, 536409361, 536409373, 536409397, 536409407, 536409413, 536409439, 536409451, 536409469, 536409547, 536409553, 536409583, 536409589, 536409623, 536409631, 536409667, 536409673, 536409677, 536409689, 536409719, 536409733, 536409737, 536409739, 536409751, 536409779, 536409793, 536409817, 536409883, 536409901, 536409911, 536409931, 536409947, 536409949, 536409961, 536409967, 536410003, 536410051, 536410057, 536410067, 536410103, 536410141, 536410151, 536410169, 536410177, 536410207, 536410213, 536410229, 536410279, 536410289, 536410309, 536410327, 536410331, 536410363, 536410373, 536410397, 536410409, 536410417, 536410429, 536410471, 536410487, 536410493, 536410499, 536410519, 536410541, 536410549, 536410561, 536410573, 536410583, 536410597, 536410601, 536410619, 536410649, 536410687, 536410723, 536410757, 536410781, 536410783, 536410813, 536410837, 536410891, 536410943, 536410993, 536410997, 536411053, 536411093, 536411119, 536411123, 536411153, 536411189, 536411191, 536411201, 536411209, 536411219, 536411243, 536411257, 536411263, 536411273, 536411327, 536411389, 536411399, 536411411, 536411471, 536411531, 536411549, 536411573, 536411587, 536411597, 536411639, 536411671, 536411683, 536411699, 536411717, 536411719, 536411723, 536411731, 536411737, 536411741, 536411747, 536411767, 536411783, 536411797, 536411807, 536411809, 536411831, 536411833, 536411851, 536411873, 536411881, 536411899, 536411917, 536411921, 536411929, 536412001, 536412013, 536412053, 536412073, 536412109, 536412131, 536412137, 536412179, 536412181, 536412193, 536412211, 536412241, 536412301, 536412329, 536412341, 536412353, 536412397, 536412413, 536412473, 536412479, 536412493, 536412497, 536412521, 536412529, 536412557, 536412581, 536412593, 536412641, 536412683, 536412689, 536412697, 536412707, 536412733, 536412749, 536412761, 536412763, 536412803, 536412829, 536412847, 536412857, 536412869, 536412887, 536412889, 536412893, 536412931, 536412937, 536412967, 536412977, 536412991, 536413001, 536413039, 536413043, 536413049, 536413051, 536413063, 536413067, 536413069, 536413079, 536413091, 536413099, 536413103, 536413117, 536413123, 536413139, 536413151, 536413183, 536413211, 536413217, 536413249, 536413253, 536413259, 536413279, 536413351, 536413357, 536413369, 536413379, 536413399, 536413403, 536413411, 536413421, 536413441, 536413447, 536413459, 536413469, 536413489, 536413513, 536413517, 536413541, 536413561, 536413571, 536413573, 536413601, 536413621, 536413627, 536413673, 536413721, 536413723, 536413729, 536413747, 536413763, 536413771, 536413807, 536413817, 536413819, 536413849, 536413883, 536413897, 536413907, 536413919, 536413921, 536413963, 536413967, 536414041, 536414057, 536414069, 536414071, 536414077, 536414083, 536414129, 536414167, 536414191, 536414233, 536414237, 536414267, 536414279, 536414323, 536414339, 536414383, 536414387, 536414401, 536414407, 536414449, 536414471, 536414519, 536414563, 536414573, 536414587, 536414609, 536414611, 536414621, 536414623, 536414629, 536414639, 536414687, 536414693, 536414741, 536414759, 536414771, 536414779, 536414803, 536414831, 536414881, 536414899, 536414909, 536414911, 536414927, 536414929, 536414933, 536414941, 536414953, 536414987, 536414999, 536415007, 536415017, 536415031, 536415053, 536415073, 536415083, 536415091, 536415097, 536415109, 536415133, 536415167, 536415203, 536415221, 536415241, 536415251, 536415281, 536415311, 536415329, 536415337, 536415359, 536415367, 536415377, 536415389, 536415409, 536415419, 536415421, 536415431, 536415449, 536415457, 536415469, 536415479, 536415511, 536415521, 536415527, 536415541, 536415547, 536415553, 536415557, 536415563, 536415643, 536415647, 536415673, 536415689, 536415701, 536415707, 536415731, 536415749, 536415779, 536415811, 536415851, 536415877, 536415889, 536415937, 536415941, 536415947, 536415953, 536415967, 536415989, 536415991, 536416007, 536416031, 536416073, 536416087, 536416093, 536416117, 536416129, 536416159, 536416169, 536416187, 536416201, 536416207, 536416213, 536416229, 536416273, 536416291, 536416297, 536416369, 536416409, 536416423, 536416427, 536416459, 536416469, 536416471, 536416523, 536416553, 536416579, 536416597, 536416637, 536416679, 536416733, 536416747, 536416753, 536416801, 536416813, 536416819, 536416823, 536416883, 536416897, 536416919, 536416931, 536416943, 536416957, 536416961, 536417041, 536417047, 536417093, 536417107, 536417111, 536417143, 536417183, 536417221, 536417243, 536417257, 536417261, 536417279, 536417281, 536417317, 536417327, 536417341, 536417369, 536417377, 536417417, 536417419, 536417461, 536417489, 536417491, 536417501, 536417503, 536417509, 536417551, 536417587, 536417593, 536417599, 536417603, 536417617, 536417653, 536417681, 536417683, 536417699, 536417701, 536417743, 536417759, 536417771, 536417773, 536417789, 536417839, 536417887, 536417933, 536417989, 536418007, 536418019, 536418023, 536418049, 536418059, 536418061, 536418083, 536418107, 536418109, 536418139, 536418143, 536418199, 536418229, 536418263, 536418313, 536418359, 536418361, 536418371, 536418401, 536418403, 536418427, 536418437, 536418521, 536418569, 536418601, 536418607, 536418613, 536418643, 536418677, 536418691, 536418763, 536418767, 536418803, 536418809, 536418821, 536418853, 536418907, 536418913, 536418959, 536418991, 536419033, 536419043, 536419049, 536419057, 536419067, 536419069, 536419097, 536419099, 536419151, 536419157, 536419187, 536419217, 536419223, 536419237, 536419259, 536419283, 536419291, 536419313, 536419337, 536419369, 536419391, 536419393, 536419417, 536419423, 536419427, 536419463, 536419469, 536419483, 536419529, 536419553, 536419561, 536419577, 536419579, 536419589, 536419619, 536419633, 536419661, 536419721, 536419729, 536419733, 536419739, 536419759, 536419781, 536419813, 536419831, 536419903, 536419907, 536419957, 536419963, 536420009, 536420029, 536420039, 536420077, 536420081, 536420111, 536420113, 536420149, 536420197, 536420231, 536420251, 536420263, 536420281, 536420299, 536420309, 536420327, 536420341, 536420359, 536420371, 536420387, 536420411, 536420459, 536420461, 536420471, 536420477, 536420491, 536420527, 536420539, 536420551, 536420587, 536420603, 536420609, 536420629, 536420681, 536420723, 536420777, 536420803, 536420813, 536420837, 536420879, 536420891, 536420959, 536420987, 536421023, 536421029, 536421037, 536421047, 536421049, 536421059, 536421107, 536421131, 536421133, 536421143, 536421161, 536421191, 536421209, 536421211, 536421257, 536421269, 536421311, 536421317, 536421329, 536421331, 536421337, 536421343, 536421419, 536421443, 536421461, 536421467, 536421493, 536421503, 536421511, 536421541, 536421559, 536421577, 536421583, 536421629, 536421637, 536421643, 536421649, 536421653, 536421659, 536421667, 536421673, 536421701, 536421703, 536421727, 536421731, 536421761, 536421773, 536421793, 536421797, 536421811, 536421839, 536421841, 536421881, 536421887, 536421911, 536421959, 536421973, 536421979, 536422001, 536422037, 536422049, 536422067, 536422069, 536422091, 536422093, 536422099, 536422129, 536422141, 536422151, 536422157, 536422181, 536422213, 536422259, 536422283, 536422297, 536422303, 536422333, 536422343, 536422361, 536422373, 536422409, 536422429, 536422457, 536422477, 536422489, 536422507, 536422511, 536422519, 536422531, 536422547, 536422553, 536422567, 536422571, 536422597, 536422603, 536422637, 536422651, 536422693, 536422697, 536422717, 536422739, 536422741, 536422759, 536422769, 536422771, 536422829, 536422883, 536422897, 536422919, 536422933, 536422937, 536422969, 536422973, 536422987, 536423011, 536423021, 536423023, 536423051, 536423059, 536423071, 536423087, 536423119, 536423137, 536423141, 536423149, 536423159, 536423161, 536423177, 536423183, 536423197, 536423201, 536423243, 536423263, 536423269, 536423281, 536423291, 536423359, 536423369, 536423413, 536423417, 536423429, 536423431, 536423449, 536423453, 536423467, 536423477, 536423497, 536423501, 536423533, 536423557, 536423567, 536423579, 536423603, 536423639, 536423651, 536423663, 536423683, 536423689, 536423707, 536423731, 536423747, 536423761, 536423773, 536423791, 536423801, 536423807, 536423809, 536423837, 536423843, 536423857, 536423861, 536423887, 536423939, 536423947, 536423977, 536424013, 536424037, 536424059, 536424061, 536424071, 536424079, 536424139, 536424143, 536424151, 536424167, 536424173, 536424191, 536424209, 536424233, 536424247, 536424257, 536424293, 536424313, 536424319, 536424323, 536424337, 536424347, 536424349, 536424373, 536424379, 536424389, 536424407, 536424419, 536424461, 536424463, 536424503, 536424509, 536424521, 536424529, 536424563, 536424593, 536424661, 536424683, 536424697, 536424703, 536424727, 536424731, 536424743, 536424751, 536424761, 536424797, 536424799, 536424827, 536424829, 536424839, 536424857, 536424859, 536424869, 536424881, 536424913, 536424923, 536424937, 536424971, 536424979, 536424989, 536425009, 536425061, 536425063, 536425069, 536425103, 536425111, 536425117, 536425121, 536425139, 536425171, 536425187, 536425193, 536425199, 536425207, 536425213, 536425217, 536425261, 536425273, 536425303, 536425363, 536425367, 536425391, 536425411, 536425447, 536425451, 536425453, 536425459, 536425469, 536425489, 536425501, 536425567, 536425649, 536425657, 536425679, 536425691, 536425693, 536425739, 536425783, 536425807, 536425823, 536425861, 536425867, 536425927, 536425949, 536425961, 536425979, 536425999, 536426017, 536426027, 536426039, 536426063, 536426071, 536426113, 536426123, 536426167, 536426227, 536426249, 536426269, 536426273, 536426281, 536426291, 536426299, 536426339, 536426383, 536426431, 536426441, 536426467, 536426477, 536426489, 536426503, 536426507, 536426519, 536426531, 536426549, 536426567, 536426581, 536426603, 536426609, 536426633, 536426647, 536426699, 536426719, 536426729, 536426743, 536426771, 536426773, 536426819, 536426881, 536426911, 536426951, 536426971, 536426977, 536426983, 536427013, 536427049, 536427079, 536427113, 536427127, 536427167, 536427179, 536427211, 536427217, 536427253, 536427263, 536427277, 536427289, 536427319, 536427329, 536427337, 536427373, 536427377, 536427383, 536427389, 536427467, 536427491, 536427523, 536427539, 536427569, 536427581, 536427583, 536427599, 536427601, 536427607, 536427629, 536427659, 536427677, 536427713, 536427719, 536427743, 536427757, 536427763, 536427803, 536427833, 536427841, 536427869, 536427889, 536427907, 536427923, 536427943, 536427949, 536427989, 536428001, 536428003, 536428019, 536428033, 536428037, 536428073, 536428093, 536428097, 536428153, 536428169, 536428171, 536428201, 536428219, 536428231, 536428259, 536428267, 536428303, 536428313, 536428339, 536428357, 536428369, 536428381, 536428441, 536428447, 536428513, 536428547, 536428589, 536428597, 536428603, 536428637, 536428667, 536428679, 536428699, 536428703, 536428759, 536428777, 536428787, 536428807, 536428817, 536428819, 536428873, 536428889, 536428901, 536428909, 536428943, 536428969, 536428973, 536428993, 536429009, 536429011, 536429027, 536429029, 536429041, 536429087, 536429093, 536429099, 536429107, 536429119, 536429123, 536429129, 536429137, 536429141, 536429167, 536429209, 536429273, 536429297, 536429317, 536429321, 536429323, 536429347, 536429351, 536429393, 536429449, 536429479, 536429507, 536429521, 536429533, 536429539, 536429561, 536429567, 536429591, 536429599, 536429633, 536429639, 536429681, 536429693, 536429741, 536429767, 536429771, 536429783, 536429807, 536429809, 536429813, 536429819, 536429827, 536429857, 536429893, 536429953, 536429977, 536430001, 536430007, 536430047, 536430049, 536430113, 536430143, 536430151, 536430161, 536430163, 536430199, 536430239, 536430241, 536430259, 536430263, 536430361, 536430373, 536430379, 536430407, 536430431, 536430443, 536430491, 536430497, 536430509, 536430533, 536430539, 536430581, 536430589, 536430637, 536430647, 536430677, 536430683, 536430689, 536430701, 536430707, 536430709, 536430749, 536430751, 536430779, 536430793, 536430821, 536430823, 536430827, 536430833, 536430841, 536430859, 536430899, 536430907, 536430919, 536430929, 536430931, 536430941, 536430953, 536431013, 536431019, 536431031, 536431061, 536431079, 536431081, 536431097, 536431121, 536431153, 536431169, 536431177, 536431187, 536431193, 536431201, 536431219, 536431253, 536431261, 536431267, 536431283, 536431289, 536431303, 536431319, 536431327, 536431333, 536431373, 536431387, 536431393, 536431403, 536431411, 536431421, 536431429, 536431433, 536431457, 536431459, 536431463, 536431501, 536431517, 536431559, 536431601, 536431663, 536431703, 536431729, 536431733, 536431757, 536431759, 536431793, 536431799, 536431817, 536431867, 536431897, 536431901, 536431927, 536431943, 536431963, 536431969, 536431993, 536432003, 536432021, 536432023, 536432063, 536432077, 536432087, 536432107, 536432173, 536432191, 536432203, 536432261, 536432287, 536432321, 536432341, 536432359, 536432363, 536432371, 536432389, 536432417, 536432437, 536432441, 536432461, 536432489, 536432497, 536432509, 536432527, 536432531, 536432551, 536432563, 536432581, 536432591, 536432599, 536432609, 536432621, 536432627, 536432683, 536432713, 536432717, 536432731, 536432737, 536432791, 536432797, 536432801, 536432803, 536432839, 536432843, 536432849, 536432863, 536432873, 536432879, 536432881, 536432921, 536432951, 536432987, 536432999, 536433013, 536433017, 536433019, 536433031, 536433049, 536433059, 536433077, 536433089, 536433091, 536433101, 536433103, 536433143, 536433169, 536433173, 536433179, 536433203, 536433211, 536433223, 536433259, 536433263, 536433353, 536433367, 536433371, 536433397, 536433421, 536433427, 536433431, 536433433, 536433509, 536433533, 536433539, 536433551, 536433647, 536433661, 536433673, 536433679, 536433697, 536433727, 536433743, 536433749, 536433757, 536433767, 536433773, 536433809, 536433839, 536433917, 536433949, 536433971, 536433977, 536434007, 536434009, 536434021, 536434033, 536434051, 536434079, 536434091, 536434117, 536434139, 536434193, 536434207, 536434211, 536434231, 536434243, 536434271, 536434273, 536434279, 536434291, 536434319, 536434351, 536434357, 536434471, 536434477, 536434487, 536434511, 536434513, 536434517, 536434519, 536434531, 536434559, 536434573, 536434583, 536434627, 536434631, 536434649, 536434669, 536434687, 536434697, 536434699, 536434729, 536434739, 536434753, 536434781, 536434807, 536434831, 536434841, 536434849, 536434859, 536434963, 536434973, 536434979, 536434981, 536435023, 536435063, 536435071, 536435077, 536435083, 536435087, 536435089, 536435093, 536435131, 536435147, 536435161, 536435177, 536435183, 536435203, 536435327, 536435351, 536435353, 536435369, 536435381, 536435401, 536435407, 536435411, 536435413, 536435423, 536435447, 536435489, 536435491, 536435507, 536435519, 536435539, 536435579, 536435597, 536435617, 536435633, 536435689, 536435717, 536435719, 536435777, 536435803, 536435813, 536435821, 536435849, 536435869, 536435903, 536435917, 536435927, 536435941, 536435983, 536436001, 536436023, 536436041, 536436049, 536436067, 536436091, 536436119, 536436127, 536436157, 536436191, 536436203, 536436209, 536436227, 536436259, 536436269, 536436289, 536436293, 536436347, 536436353, 536436361, 536436389, 536436419, 536436421, 536436449, 536436451, 536436457, 536436469, 536436487, 536436499, 536436503, 536436529, 536436541, 536436559, 536436583, 536436611, 536436643, 536436763, 536436779, 536436787, 536436793, 536436821, 536436833, 536436881, 536436917, 536436931, 536436941, 536436961, 536436977, 536437003, 536437007, 536437039, 536437043, 536437123, 536437133, 536437151, 536437177, 536437201, 536437267, 536437277, 536437289, 536437313, 536437339, 536437351, 536437357, 536437373, 536437387, 536437409, 536437463, 536437523, 536437553, 536437591, 536437597, 536437619, 536437633, 536437637, 536437663, 536437667, 536437687, 536437777, 536437787, 536437789, 536437793, 536437801, 536437807, 536437813, 536437817, 536437829, 536437831, 536437871, 536437879, 536437897, 536437921, 536437927, 536437939, 536437961, 536437999, 536438017, 536438041, 536438059, 536438083, 536438101, 536438107, 536438141, 536438239, 536438261, 536438303, 536438311, 536438323, 536438339, 536438341, 536438347, 536438351, 536438363, 536438393, 536438411, 536438429, 536438431, 536438449, 536438467, 536438479, 536438489, 536438527, 536438531, 536438537, 536438557, 536438563, 536438597, 536438627, 536438633, 536438641, 536438653, 536438659, 536438671, 536438701, 536438713, 536438719, 536438741, 536438743, 536438753, 536438759, 536438789, 536438827, 536438869, 536438873, 536438879, 536438923, 536439011, 536439019, 536439037, 536439041, 536439047, 536439073, 536439089, 536439091, 536439107, 536439109, 536439149, 536439161, 536439173, 536439227, 536439287, 536439289, 536439317, 536439329, 536439383, 536439413, 536439433, 536439443, 536439451, 536439457, 536439473, 536439481, 536439493, 536439499, 536439517, 536439523, 536439569, 536439581, 536439601, 536439619, 536439643, 536439647, 536439661, 536439679, 536439689, 536439691, 536439703, 536439713, 536439733, 536439773, 536439791, 536439793, 536439809, 536439821, 536439829, 536439877, 536439881, 536439887, 536439889, 536439907, 536439919, 536439923, 536439983, 536439997, 536440031, 536440061, 536440087, 536440147, 536440159, 536440169, 536440181, 536440183, 536440199, 536440207, 536440211, 536440217, 536440237, 536440241, 536440273, 536440277, 536440301, 536440343, 536440363, 536440369, 536440381, 536440409, 536440439, 536440447, 536440459, 536440481, 536440501, 536440517, 536440529, 536440589, 536440631, 536440633, 536440643, 536440651, 536440673, 536440691, 536440733, 536440757, 536440783, 536440787, 536440819, 536440823, 536440829, 536440901, 536440903, 536440909, 536440913, 536440999, 536441021, 536441027, 536441051, 536441053, 536441063, 536441071, 536441099, 536441119, 536441123, 536441153, 536441189, 536441197, 536441209, 536441261, 536441291, 536441299, 536441357, 536441387, 536441471, 536441491, 536441501, 536441509, 536441531, 536441551, 536441557, 536441561, 536441569, 536441599, 536441617, 536441657, 536441671, 536441677, 536441693, 536441729, 536441761, 536441767, 536441771, 536441791, 536441803, 536441809, 536441831, 536441833, 536441861, 536441863, 536441881, 536441923, 536441933, 536441951, 536441959, 536441963, 536441977, 536441981, 536441993, 536442013, 536442019, 536442037, 536442043, 536442047, 536442059, 536442091, 536442103, 536442119, 536442139, 536442173, 536442199, 536442211, 536442217, 536442239, 536442251, 536442289, 536442341, 536442343, 536442359, 536442397, 536442419, 536442421, 536442461, 536442481, 536442499, 536442503, 536442553, 536442619, 536442649, 536442653, 536442659, 536442707, 536442719, 536442721, 536442743, 536442749, 536442787, 536442833, 536442853, 536442877, 536442887, 536442901, 536442917, 536442971, 536442989, 536442997, 536443001, 536443009, 536443013, 536443031, 536443049, 536443069, 536443079, 536443087, 536443097, 536443129, 536443133, 536443147, 536443151, 536443181, 536443183, 536443213, 536443217, 536443253, 536443309, 536443343, 536443357, 536443393, 536443423, 536443429, 536443433, 536443441, 536443459, 536443469, 536443487, 536443507, 536443547, 536443591, 536443601, 536443603, 536443613, 536443669, 536443679, 536443717, 536443727, 536443729, 536443781, 536443783, 536443799, 536443807, 536443813, 536443819, 536443829, 536443841, 536443867, 536443889, 536443907, 536443961, 536443981, 536443987, 536443997, 536444011, 536444039, 536444089, 536444099, 536444137, 536444149, 536444159, 536444171, 536444177, 536444191, 536444213, 536444219, 536444257, 536444327, 536444383, 536444399, 536444437, 536444453, 536444473, 536444483, 536444509, 536444591, 536444609, 536444621, 536444647, 536444659, 536444669, 536444683, 536444717, 536444773, 536444789, 536444819, 536444827, 536444837, 536444873, 536444903, 536444927, 536444941, 536444971, 536444977, 536444989, 536445011, 536445023, 536445043, 536445053, 536445061, 536445073, 536445109, 536445127, 536445137, 536445187, 536445191, 536445193, 536445197, 536445199, 536445223, 536445229, 536445241, 536445289, 536445311, 536445331, 536445361, 536445397, 536445433, 536445439, 536445577, 536445589, 536445593, 536445649, 536445667, 536445671, 536445703, 536445737, 536445739, 536445757, 536445817, 536445821, 536445823, 536445851, 536445883, 536445887, 536445907, 536445929, 536445947, 536445953, 536445983, 536446003, 536446013, 536446021, 536446037, 536446039, 536446063, 536446093, 536446187, 536446193, 536446201, 536446217, 536446219, 536446223, 536446241, 536446243, 536446291, 536446303, 536446307, 536446357, 536446363, 536446409, 536446433, 536446439, 536446459, 536446481, 536446483, 536446499, 536446507, 536446511, 536446597, 536446601, 536446613, 536446621, 536446633, 536446639, 536446643, 536446657, 536446663, 536446667, 536446681, 536446693, 536446697, 536446717, 536446739, 536446759, 536446769, 536446777, 536446789, 536446837, 536446873, 536446891, 536446903, 536446907, 536446913, 536446921, 536446943, 536446987, 536446991, 536447003, 536447027, 536447039, 536447089, 536447123, 536447137, 536447141, 536447179, 536447207, 536447221, 536447251, 536447267, 536447279, 536447297, 536447299, 536447309, 536447323, 536447333, 536447339, 536447347, 536447363, 536447383, 536447413, 536447419, 536447437, 536447447, 536447449, 536447453, 536447459, 536447473, 536447477, 536447521, 536447543, 536447573, 536447579, 536447617, 536447621, 536447623, 536447629, 536447633, 536447657, 536447669, 536447693, 536447711, 536447741, 536447753, 536447789, 536447797, 536447819, 536447831, 536447851, 536447893, 536447897, 536447909, 536447911, 536447917, 536447953, 536447983, 536448041, 536448043, 536448047, 536448053, 536448169, 536448181, 536448191, 536448193, 536448197, 536448203, 536448217, 536448233, 536448247, 536448257, 536448281, 536448287, 536448317, 536448323, 536448329, 536448359, 536448361, 536448373, 536448377, 536448383, 536448391, 536448401, 536448439, 536448461, 536448499, 536448503, 536448511, 536448529, 536448541, 536448547, 536448557, 536448581, 536448613, 536448637, 536448659, 536448667, 536448697, 536448713, 536448743, 536448761, 536448763, 536448767, 536448817, 536448839, 536448851, 536448883, 536448901, 536448919, 536448937, 536448943, 536449007, 536449019, 536449031, 536449057, 536449073, 536449087, 536449099, 536449103, 536449139, 536449153, 536449157, 536449183, 536449223, 536449231, 536449237, 536449259, 536449267, 536449271, 536449313, 536449349, 536449357, 536449387, 536449391, 536449409, 536449457, 536449489, 536449519, 536449523, 536449531, 536449549, 536449561, 536449577, 536449583, 536449597, 536449607, 536449619, 536449621, 536449633, 536449657, 536449687, 536449703, 536449709, 536449747, 536449763, 536449783, 536449787, 536449813, 536449817, 536449829, 536449843, 536449871, 536449877, 536449883, 536449913, 536449951, 536449967, 536449981, 536449993, 536450017, 536450029, 536450041, 536450051, 536450107, 536450129, 536450141, 536450143, 536450177, 536450179, 536450197, 536450203, 536450219, 536450221, 536450231, 536450263, 536450269, 536450279, 536450311, 536450333, 536450353, 536450357, 536450359, 536450363, 536450377, 536450423, 536450429, 536450483, 536450507, 536450533, 536450539, 536450573, 536450581, 536450587, 536450639, 536450669, 536450687, 536450701, 536450737, 536450741, 536450743, 536450771, 536450773, 536450777, 536450851, 536450869, 536450911, 536450987, 536450989, 536451023, 536451067, 536451127, 536451131, 536451143, 536451151, 536451163, 536451169, 536451173, 536451191, 536451203, 536451217, 536451277, 536451343, 536451347, 536451361, 536451389, 536451397, 536451401, 536451403, 536451427, 536451431, 536451449, 536451451, 536451463, 536451479, 536451521, 536451533, 536451569, 536451589, 536451611, 536451623, 536451661, 536451689, 536451697, 536451733, 536451737, 536451763, 536451767, 536451787, 536451823, 536451829, 536451857, 536451899, 536451901, 536451917, 536451919, 536451941, 536451967, 536451973, 536452027, 536452057, 536452087, 536452109, 536452129, 536452141, 536452151, 536452181, 536452193, 536452211, 536452223, 536452229, 536452243, 536452261, 536452271, 536452283, 536452351, 536452363, 536452393, 536452417, 536452421, 536452463, 536452481, 536452513, 536452537, 536452541, 536452559, 536452577, 536452601, 536452607, 536452619, 536452627, 536452633, 536452661, 536452711, 536452753, 536452757, 536452789, 536452801, 536452831, 536452841, 536452883, 536452921, 536452949, 536452951, 536452967, 536452997, 536453017, 536453023, 536453059, 536453083, 536453089, 536453101, 536453119, 536453131, 536453147, 536453179, 536453191, 536453221, 536453237, 536453249, 536453257, 536453263, 536453279, 536453297, 536453317, 536453327, 536453387, 536453399, 536453413, 536453431, 536453453, 536453473, 536453507, 536453539, 536453551, 536453557, 536453579, 536453591, 536453597, 536453611, 536453627, 536453647, 536453663, 536453669, 536453693, 536453707, 536453741, 536453779, 536453821, 536453839, 536453849, 536453851, 536453867, 536453917, 536453971, 536454029, 536454041, 536454067, 536454071, 536454089, 536454103, 536454131, 536454133, 536454167, 536454187, 536454239, 536454241, 536454263, 536454271, 536454293, 536454299, 536454361, 536454367, 536454371, 536454377, 536454389, 536454407, 536454409, 536454419, 536454421, 536454433, 536454437, 536454439, 536454467, 536454469, 536454521, 536454539, 536454551, 536454559, 536454637, 536454649, 536454661, 536454697, 536454739, 536454781, 536454791, 536454803, 536454811, 536454827, 536454857, 536454869, 536454871, 536454899, 536454901, 536454917, 536454929, 536454937, 536454943, 536454973, 536455001, 536455061, 536455091, 536455103, 536455123, 536455141, 536455187, 536455189, 536455207, 536455223, 536455237, 536455259, 536455301, 536455313, 536455327, 536455343, 536455351, 536455363, 536455373, 536455379, 536455457, 536455459, 536455463, 536455499, 536455501, 536455511, 536455531, 536455537, 536455547, 536455597, 536455663, 536455681, 536455691, 536455693, 536455721, 536455729, 536455739, 536455753, 536455769, 536455781, 536455793, 536455807, 536455811, 536455883, 536455897, 536455901, 536455919, 536455943, 536455951, 536455957, 536455973, 536455991, 536455993, 536456009, 536456017, 536456047, 536456077, 536456093, 536456111, 536456113, 536456149, 536456197, 536456237, 536456251, 536456299, 536456351, 536456381, 536456383, 536456399, 536456411, 536456419, 536456429, 536456441, 536456521, 536456533, 536456549, 536456561, 536456563, 536456579, 536456593, 536456611, 536456653, 536456663, 536456671, 536456699, 536456717, 536456729, 536456737, 536456749, 536456797, 536456803, 536456839, 536456909, 536456927, 536456959, 536456983, 536456989, 536457041, 536457059, 536457073, 536457091, 536457113, 536457127, 536457169, 536457193, 536457199, 536457209, 536457211, 536457227, 536457281, 536457301, 536457319, 536457329, 536457353, 536457371, 536457391, 536457421, 536457499, 536457517, 536457529, 536457541, 536457547, 536457563, 536457587, 536457599, 536457601, 536457617, 536457619, 536457629, 536457641, 536457667, 536457673, 536457703, 536457721, 536457731, 536457737, 536457739, 536457751, 536457781, 536457787, 536457791, 536457793, 536457829, 536457833, 536457869, 536457871, 536457877, 536457881, 536457893, 536457907, 536457917, 536457923, 536457937, 536458099, 536458127, 536458147, 536458159, 536458163, 536458177, 536458229, 536458261, 536458271, 536458297, 536458313, 536458333, 536458337, 536458357, 536458451, 536458471, 536458499, 536458513, 536458543, 536458547, 536458553, 536458567, 536458589, 536458607, 536458639, 536458649, 536458661, 536458667, 536458679, 536458691, 536458729, 536458759, 536458771, 536458789, 536458807, 536458837, 536458843, 536458859, 536458873, 536458913, 536458957, 536459029, 536459069, 536459083, 536459101, 536459113, 536459137, 536459149, 536459207, 536459213, 536459227, 536459249, 536459299, 536459359, 536459369, 536459389, 536459393, 536459479, 536459491, 536459503, 536459543, 536459563, 536459579, 536459593, 536459647, 536459653, 536459657, 536459669, 536459711, 536459747, 536459753, 536459767, 536459771, 536459789, 536459809, 536459827, 536459831, 536459839, 536459863, 536459879, 536459881, 536459909, 536459921, 536459941, 536459983, 536460013, 536460017, 536460061, 536460091, 536460107, 536460157, 536460181, 536460203, 536460233, 536460251, 536460311, 536460317, 536460341, 536460377, 536460427, 536460433, 536460437, 536460467, 536460479, 536460493, 536460539, 536460559, 536460563, 536460577, 536460581, 536460599, 536460641, 536460689, 536460707, 536460709, 536460713, 536460719, 536460737, 536460739, 536460751, 536460767, 536460787, 536460803, 536460811, 536460889, 536460913, 536460929, 536460931, 536460971, 536460973, 536460979, 536460989, 536460997, 536461001, 536461103, 536461147, 536461151, 536461153, 536461171, 536461193, 536461207, 536461213, 536461253, 536461259, 536461273, 536461279, 536461291, 536461327, 536461349, 536461363, 536461403, 536461439, 536461441, 536461463, 536461477, 536461489, 536461493, 536461553, 536461559, 536461567, 536461577, 536461649, 536461657, 536461661, 536461669, 536461693, 536461699, 536461771, 536461781, 536461787, 536461817, 536461819, 536461823, 536461837, 536461841, 536461847, 536461859, 536461873, 536461943, 536461967, 536461969, 536462009, 536462027, 536462083, 536462107, 536462123, 536462141, 536462153, 536462167, 536462231, 536462239, 536462263, 536462287, 536462291, 536462293, 536462317, 536462389, 536462411, 536462413, 536462417, 536462467, 536462483, 536462497, 536462513, 536462567, 536462579, 536462629, 536462669, 536462681, 536462743, 536462791, 536462809, 536462827, 536462837, 536462881, 536462887, 536462893, 536462917, 536462923, 536462933, 536462959, 536462977, 536462989, 536463023, 536463047, 536463049, 536463073, 536463131, 536463173, 536463197, 536463211, 536463241, 536463251, 536463281, 536463283, 536463289, 536463299, 536463329, 536463337, 536463391, 536463413, 536463427, 536463443, 536463451, 536463457, 536463467, 536463469, 536463479, 536463511, 536463553, 536463643, 536463647, 536463667, 536463673, 536463701, 536463709, 536463731, 536463737, 536463749, 536463751, 536463757, 536463761, 536463791, 536463817, 536463833, 536463839, 536463847, 536463857, 536463871, 536463911, 536463919, 536463923, 536463979, 536463989, 536464007, 536464043, 536464099, 536464153, 536464163, 536464217, 536464231, 536464237, 536464241, 536464249, 536464261, 536464277, 536464289, 536464309, 536464343, 536464349, 536464361, 536464363, 536464433, 536464457, 536464469, 536464471, 536464477, 536464493, 536464501, 536464543, 536464567, 536464573, 536464613, 536464651, 536464657, 536464679, 536464693, 536464697, 536464717, 536464727, 536464759, 536464769, 536464777, 536464783, 536464793, 536464871, 536464879, 536464883, 536464919, 536464931, 536464979, 536464991, 536465009, 536465023, 536465029, 536465071, 536465129, 536465161, 536465201, 536465203, 536465207, 536465213, 536465219, 536465231, 536465233, 536465297, 536465299, 536465339, 536465351, 536465381, 536465407, 536465441, 536465453, 536465459, 536465467, 536465477, 536465483, 536465497, 536465521, 536465533, 536465543, 536465557, 536465591, 536465609, 536465687, 536465723, 536465737, 536465773, 536465789, 536465791, 536465857, 536465861, 536465887, 536465899, 536465911, 536465939, 536465953, 536465959, 536465987, 536465999, 536466019, 536466079, 536466097, 536466113, 536466143, 536466179, 536466211, 536466223, 536466239, 536466317, 536466347, 536466473, 536466479, 536466481, 536466487, 536466493, 536466503, 536466523, 536466529, 536466571, 536466607, 536466613, 536466629, 536466631, 536466659, 536466661, 536466703, 536466713, 536466761, 536466769, 536466793, 536466803, 536466817, 536466823, 536466869, 536466871, 536466893, 536466913, 536466937, 536466967, 536466979, 536466989, 536467037, 536467081, 536467159, 536467163, 536467171, 536467187, 536467193, 536467229, 536467231, 536467271, 536467279, 536467301, 536467313, 536467333, 536467381, 536467391, 536467417, 536467427, 536467439, 536467469, 536467483, 536467513, 536467567, 536467577, 536467601, 536467609, 536467639, 536467649, 536467667, 536467669, 536467681, 536467697, 536467747, 536467753, 536467777, 536467787, 536467819, 536467829, 536467837, 536467843, 536467853, 536467879, 536467889, 536467931, 536467979, 536468017, 536468027, 536468033, 536468047, 536468063, 536468083, 536468087, 536468131, 536468159, 536468183, 536468203, 536468209, 536468213, 536468239, 536468311, 536468321, 536468323, 536468327, 536468333, 536468341, 536468347, 536468351, 536468357, 536468389, 536468407, 536468417, 536468431, 536468467, 536468503, 536468509, 536468551, 536468561, 536468623, 536468633, 536468657, 536468659, 536468707, 536468719, 536468741, 536468747, 536468759, 536468791, 536468797, 536468839, 536468861, 536468869, 536468893, 536468899, 536468917, 536468929, 536469029, 536469061, 536469071, 536469097, 536469107, 536469151, 536469211, 536469251, 536469257, 536469317, 536469331, 536469337, 536469343, 536469361, 536469371, 536469377, 536469383, 536469413, 536469443, 536469449, 536469473, 536469491, 536469533, 536469547, 536469553, 536469569, 536469607, 536469649, 536469653, 536469667, 536469671, 536469679, 536469683, 536469691, 536469709, 536469721, 536469727, 536469841, 536469851, 536469877, 536469889, 536469893, 536469907, 536469937, 536469977, 536469979, 536470013, 536470019, 536470027, 536470031, 536470057, 536470087, 536470127, 536470133, 536470157, 536470163, 536470169, 536470171, 536470177, 536470189, 536470201, 536470213, 536470223, 536470313, 536470379, 536470381, 536470387, 536470433, 536470447, 536470457, 536470463, 536470471, 536470483, 536470577, 536470589, 536470603, 536470621, 536470631, 536470663, 536470667, 536470673, 536470721, 536470723, 536470747, 536470763, 536470789, 536470793, 536470799, 536470811, 536470813, 536470843, 536470861, 536470867, 536470873, 536470901, 536470919, 536470927, 536470951, 536470973, 536470981, 536470997, 536470999, 536471009, 536471051, 536471063, 536471093, 536471107, 536471123, 536471153, 536471161, 536471167, 536471179, 536471191, 536471209, 536471219, 536471249, 536471269, 536471279, 536471281, 536471317, 536471339, 536471381, 536471423, 536471437, 536471447, 536471449, 536471491, 536471503, 536471521, 536471539, 536471591, 536471623, 536471629, 536471641, 536471653, 536471713, 536471723, 536471753, 536471791, 536471801, 536471809, 536471813, 536471851, 536471867, 536471869, 536471879, 536471927, 536471939, 536471951, 536472007, 536472017, 536472023, 536472031, 536472037, 536472047, 536472059, 536472061, 536472071, 536472091, 536472107, 536472113, 536472119, 536472127, 536472161, 536472193, 536472199, 536472203, 536472253, 536472259, 536472269, 536472289, 536472311, 536472317, 536472319, 536472341, 536472367, 536472373, 536472389, 536472403, 536472407, 536472437, 536472439, 536472457, 536472473, 536472529, 536472533, 536472571, 536472589, 536472593, 536472667, 536472697, 536472707, 536472709, 536472779, 536472787, 536472799, 536472817, 536472829, 536472877, 536472883, 536472889, 536472901, 536472917, 536472919, 536472931, 536472941, 536472967, 536472973, 536472977, 536473009, 536473013, 536473051, 536473061, 536473081, 536473103, 536473111, 536473123, 536473127, 536473153, 536473177, 536473187, 536473193, 536473207, 536473211, 536473213, 536473241, 536473297, 536473309, 536473313, 536473319, 536473339, 536473361, 536473381, 536473387, 536473391, 536473393, 536473409, 536473411, 536473429, 536473433, 536473447, 536473499, 536473513, 536473517, 536473529, 536473541, 536473583, 536473621, 536473649, 536473661, 536473681, 536473723, 536473727, 536473739, 536473741, 536473771, 536473783, 536473787, 536473789, 536473793, 536473829, 536473837, 536473859, 536473901, 536473907, 536473909, 536473937, 536473939, 536473943, 536473967, 536473969, 536473997, 536474009, 536474017, 536474033, 536474051, 536474087, 536474119, 536474123, 536474131, 536474203, 536474209, 536474231, 536474233, 536474269, 536474273, 536474317, 536474339, 536474363, 536474369, 536474371, 536474399, 536474417, 536474431, 536474447, 536474473, 536474483, 536474489, 536474513, 536474527, 536474569, 536474621, 536474657, 536474663, 536474677, 536474711, 536474749, 536474753, 536474759, 536474761, 536474767, 536474789, 536474819, 536474821, 536474843, 536474921, 536474929, 536474941, 536474971, 536474987, 536474989, 536475011, 536475059, 536475067, 536475073, 536475091, 536475113, 536475133, 536475139, 536475157, 536475167, 536475187, 536475193, 536475197, 536475257, 536475287, 536475319, 536475349, 536475371, 536475389, 536475403, 536475463, 536475473, 536475479, 536475481, 536475497, 536475509, 536475547, 536475571, 536475601, 536475619, 536475623, 536475631, 536475671, 536475673, 536475679, 536475701, 536475703, 536475707, 536475757, 536475763, 536475803, 536475827, 536475847, 536475853, 536475859, 536475871, 536475889, 536475899, 536475917, 536475923, 536475931, 536475937, 536475949, 536475983, 536475991, 536476007, 536476019, 536476043, 536476121, 536476163, 536476177, 536476181, 536476211, 536476223, 536476231, 536476271, 536476289, 536476301, 536476313, 536476331, 536476351, 536476373, 536476399, 536476453, 536476459, 536476469, 536476487, 536476561, 536476583, 536476627, 536476631, 536476637, 536476657, 536476673, 536476691, 536476709, 536476739, 536476741, 536476747, 536476757, 536476807, 536476823, 536476861, 536476873, 536476931, 536476933, 536476937, 536476981, 536476999, 536477009, 536477059, 536477063, 536477069, 536477089, 536477099, 536477101, 536477111, 536477167, 536477197, 536477209, 536477213, 536477233, 536477237, 536477243, 536477261, 536477267, 536477269, 536477273, 536477287, 536477299, 536477329, 536477339, 536477363, 536477401, 536477419, 536477423, 536477429, 536477441, 536477453, 536477471, 536477479, 536477549, 536477581, 536477593, 536477603, 536477621, 536477639, 536477651, 536477659, 536477677, 536477717, 536477731, 536477741, 536477791, 536477807, 536477813, 536477827, 536477831, 536477947, 536477951, 536477969, 536477999, 536478023, 536478037, 536478043, 536478079, 536478097, 536478101, 536478109, 536478121, 536478139, 536478149, 536478161, 536478181, 536478193, 536478211, 536478223, 536478227, 536478247, 536478259, 536478269, 536478287, 536478301, 536478307, 536478323, 536478361, 536478377, 536478379, 536478391, 536478431, 536478463, 536478479, 536478491, 536478541, 536478559, 536478583, 536478587, 536478599, 536478601, 536478617, 536478629, 536478641, 536478643, 536478659, 536478697, 536478757, 536478781, 536478791, 536478797, 536478827, 536478829, 536478857, 536478869, 536478881, 536478907, 536478937, 536478949, 536478953, 536478989, 536478997, 536479063, 536479093, 536479121, 536479133, 536479159, 536479171, 536479199, 536479213, 536479247, 536479249, 536479261, 536479297, 536479327, 536479357, 536479367, 536479373, 536479457, 536479469, 536479477, 536479483, 536479487, 536479501, 536479513, 536479529, 536479543, 536479553, 536479561, 536479589, 536479597, 536479609, 536479627, 536479631, 536479637, 536479673, 536479679, 536479709, 536479717, 536479721, 536479733, 536479771, 536479789, 536479843, 536479871, 536479873, 536479883, 536479891, 536479913, 536479919, 536479967, 536479969, 536480003, 536480011, 536480041, 536480051, 536480059, 536480089, 536480099, 536480111, 536480117, 536480149, 536480167, 536480173, 536480179, 536480201, 536480209, 536480249, 536480261, 536480297, 536480381, 536480393, 536480411, 536480437, 536480443, 536480459, 536480467, 536480471, 536480507, 536480521, 536480533, 536480587, 536480597, 536480603, 536480621, 536480627, 536480641, 536480663, 536480729, 536480731, 536480741, 536480767, 536480779, 536480783, 536480837, 536480851, 536480873, 536480881, 536480891, 536480927, 536480933, 536480939, 536480953, 536480969, 536481037, 536481047, 536481059, 536481073, 536481083, 536481103, 536481109, 536481137, 536481139, 536481163, 536481191, 536481193, 536481199, 536481217, 536481247, 536481251, 536481259, 536481271, 536481289, 536481299, 536481313, 536481331, 536481367, 536481383, 536481391, 536481431, 536481457, 536481479, 536481487, 536481493, 536481499, 536481557, 536481559, 536481571, 536481593, 536481623, 536481677, 536481713, 536481727, 536481809, 536481839, 536481859, 536481947, 536481949, 536481961, 536481983, 536482013, 536482021, 536482069, 536482091, 536482097, 536482139, 536482151, 536482159, 536482181, 536482189, 536482201, 536482207, 536482217, 536482229, 536482279, 536482283, 536482321, 536482327, 536482363, 536482381, 536482399, 536482411, 536482439, 536482553, 536482579, 536482591, 536482637, 536482643, 536482649, 536482669, 536482673, 536482691, 536482697, 536482717, 536482729, 536482763, 536482781, 536482789, 536482799, 536482873, 536482883, 536482927, 536482951, 536483021, 536483053, 536483099, 536483113, 536483147, 536483153, 536483177, 536483197, 536483231, 536483273, 536483279, 536483309, 536483317, 536483327, 536483359, 536483393, 536483407, 536483413, 536483419, 536483447, 536483473, 536483477, 536483491, 536483527, 536483573, 536483587, 536483641, 536483653, 536483669, 536483767, 536483777, 536483797, 536483833, 536483851, 536483891, 536483951, 536483957, 536483971, 536483999, 536484059, 536484061, 536484077, 536484103, 536484107, 536484121, 536484149, 536484161, 536484163, 536484187, 536484199, 536484217, 536484239, 536484241, 536484251, 536484259, 536484271, 536484281, 536484313, 536484329, 536484331, 536484353, 536484359, 536484371, 536484397, 536484401, 536484439, 536484457, 536484479, 536484491, 536484493, 536484503, 536484517, 536484523, 536484577, 536484587, 536484607, 536484617, 536484643, 536484653, 536484701, 536484731, 536484737, 536484749, 536484757, 536484761, 536484769, 536484797, 536484803, 536484869, 536484881, 536484887, 536484901, 536484911, 536484917, 536484943, 536484947, 536484979, 536484983, 536484989, 536485003, 536485043, 536485069, 536485073, 536485091, 536485109, 536485127, 536485139, 536485153, 536485199, 536485219, 536485223, 536485231, 536485253, 536485259, 536485343, 536485351, 536485361, 536485393, 536485427, 536485429, 536485441, 536485483, 536485487, 536485489, 536485519, 536485559, 536485571, 536485601, 536485613, 536485627, 536485669, 536485679, 536485699, 536485717, 536485723, 536485739, 536485751, 536485753, 536485771, 536485811, 536485823, 536485837, 536485867, 536485883, 536485897, 536485921, 536485987, 536486009, 536486023, 536486029, 536486039, 536486053, 536486081, 536486099, 536486131, 536486143, 536486161, 536486183, 536486191, 536486231, 536486243, 536486257, 536486263, 536486267, 536486297, 536486311, 536486317, 536486329, 536486359, 536486387, 536486429, 536486441, 536486453, 536486471, 536486473, 536486497, 536486501, 536486537, 536486581, 536486591, 536486677, 536486759, 536486761, 536486777, 536486801, 536486827, 536486849, 536486861, 536486893, 536486911, 536486917, 536486947, 536486957, 536486971, 536486987, 536487011, 536487031, 536487079, 536487089, 536487101, 536487113, 536487137, 536487143, 536487151, 536487163, 536487191, 536487197, 536487233, 536487239, 536487257, 536487277, 536487299, 536487317, 536487323, 536487353, 536487373, 536487389, 536487403, 536487437, 536487451, 536487481, 536487491, 536487493, 536487533, 536487577, 536487599, 536487607, 536487613, 536487631, 536487661, 536487701, 536487703, 536487709, 536487739, 536487769, 536487793, 536487797, 536487803, 536487821, 536487851, 536487893, 536487899, 536487929, 536487937, 536487943, 536487979, 536488021, 536488031, 536488037, 536488079, 536488093, 536488109, 536488129, 536488213, 536488217, 536488219, 536488241, 536488243, 536488297, 536488331, 536488369, 536488391, 536488439, 536488471, 536488481, 536488531, 536488549, 536488553, 536488559, 536488577, 536488591, 536488613, 536488627, 536488633, 536488637, 536488643, 536488651, 536488657, 536488723, 536488727, 536488747, 536488783, 536488793, 536488819, 536488831, 536488837, 536488859, 536488877, 536488889, 536488963, 536488969, 536488991, 536488999, 536489017, 536489039, 536489071, 536489117, 536489137, 536489143, 536489197, 536489203, 536489227, 536489231, 536489269, 536489287, 536489293, 536489347, 536489351, 536489489, 536489501, 536489533, 536489557, 536489573, 536489579, 536489581, 536489599, 536489663, 536489699, 536489717, 536489729, 536489731, 536489749, 536489803, 536489809, 536489827, 536489843, 536489857, 536489861, 536489867, 536489897, 536489917, 536489929, 536489939, 536489957, 536489963, 536489969, 536490001, 536490011, 536490041, 536490049, 536490091, 536490109, 536490113, 536490151, 536490167, 536490173, 536490191, 536490193, 536490197, 536490209, 536490223, 536490257, 536490259, 536490263, 536490319, 536490323, 536490329, 536490347, 536490379, 536490389, 536490391, 536490421, 536490431, 536490497, 536490523, 536490529, 536490551, 536490583, 536490587, 536490629, 536490649, 536490653, 536490683, 536490701, 536490739, 536490803, 536490809, 536490881, 536490883, 536490887, 536490901, 536490937, 536490959, 536490967, 536490971, 536490979, 536491003, 536491051, 536491061, 536491073, 536491099, 536491139, 536491183, 536491223, 536491283, 536491297, 536491339, 536491357, 536491409, 536491411, 536491441, 536491447, 536491477, 536491513, 536491541, 536491567, 536491591, 536491603, 536491609, 536491621, 536491643, 536491679, 536491727, 536491759, 536491777, 536491789, 536491807, 536491829, 536491849, 536491853, 536491867, 536491883, 536491903, 536491919, 536491927, 536491931, 536491937, 536491957, 536491973, 536491979, 536492003, 536492039, 536492051, 536492059, 536492071, 536492087, 536492153, 536492161, 536492167, 536492179, 536492183, 536492197, 536492207, 536492221, 536492237, 536492309, 536492311, 536492321, 536492371, 536492387, 536492389, 536492399, 536492423, 536492449, 536492459, 536492471, 536492483, 536492497, 536492513, 536492521, 536492527, 536492557, 536492587, 536492599, 536492611, 536492653, 536492689, 536492729, 536492753, 536492777, 536492791, 536492807, 536492839, 536492843, 536492849, 536492861, 536492927, 536492939, 536492941, 536492951, 536492989, 536493017, 536493049, 536493073, 536493079, 536493103, 536493107, 536493119, 536493121, 536493131, 536493137, 536493143, 536493149, 536493169, 536493179, 536493247, 536493263, 536493281, 536493317, 536493371, 536493407, 536493421, 536493457, 536493467, 536493509, 536493521, 536493523, 536493527, 536493541, 536493563, 536493583, 536493611, 536493637, 536493647, 536493739, 536493743, 536493773, 536493787, 536493809, 536493817, 536493833, 536493901, 536493907, 536493913, 536493943, 536493961, 536494003, 536494027, 536494031, 536494081, 536494087, 536494103, 536494121, 536494129, 536494163, 536494169, 536494181, 536494201, 536494213, 536494219, 536494223, 536494243, 536494261, 536494303, 536494333, 536494367, 536494369, 536494379, 536494397, 536494417, 536494421, 536494429, 536494433, 536494477, 536494513, 536494537, 536494549, 536494571, 536494579, 536494589, 536494597, 536494627, 536494639, 536494643, 536494657, 536494691, 536494727, 536494741, 536494747, 536494769, 536494787, 536494793, 536494831, 536494837, 536494841, 536494853, 536494873, 536494883, 536494909, 536494943, 536494979, 536494999, 536495009, 536495053, 536495059, 536495119, 536495123, 536495143, 536495149, 536495213, 536495221, 536495233, 536495237, 536495243, 536495249, 536495257, 536495261, 536495321, 536495339, 536495369, 536495423, 536495461, 536495473, 536495501, 536495513, 536495527, 536495543, 536495551, 536495581, 536495591, 536495633, 536495657, 536495693, 536495717, 536495731, 536495759, 536495767, 536495797, 536495801, 536495831, 536495833, 536495857, 536495881, 536495923, 536495957, 536496007, 536496043, 536496049, 536496061, 536496101, 536496109, 536496131, 536496167, 536496197, 536496209, 536496223, 536496227, 536496241, 536496277, 536496283, 536496329, 536496341, 536496379, 536496419, 536496431, 536496437, 536496449, 536496461, 536496481, 536496487, 536496503, 536496511, 536496517, 536496529, 536496533, 536496553, 536496563, 536496589, 536496619, 536496677, 536496691, 536496703, 536496731, 536496739, 536496743, 536496791, 536496797, 536496817, 536496833, 536496841, 536496847, 536496859, 536496871, 536496887, 536496889, 536496893, 536496911, 536496937, 536496953, 536496973, 536497063, 536497099, 536497121, 536497133, 536497141, 536497147, 536497193, 536497211, 536497223, 536497231, 536497261, 536497277, 536497289, 536497301, 536497321, 536497349, 536497399, 536497411, 536497427, 536497459, 536497469, 536497483, 536497487, 536497537, 536497553, 536497567, 536497573, 536497579, 536497583, 536497601, 536497667, 536497681, 536497693, 536497697, 536497727, 536497729, 536497837, 536497859, 536497861, 536497909, 536497919, 536497933, 536497967, 536497987, 536497993, 536498029, 536498047, 536498051, 536498077, 536498101, 536498129, 536498167, 536498197, 536498219, 536498227, 536498267, 536498323, 536498399, 536498423, 536498447, 536498449, 536498503, 536498509, 536498513, 536498527, 536498533, 536498539, 536498581, 536498591, 536498593, 536498609, 536498647, 536498657, 536498693, 536498723, 536498731, 536498737, 536498747, 536498789, 536498821, 536498849, 536498857, 536498861, 536498873, 536498909, 536498951, 536498957, 536498959, 536498999, 536499011, 536499037, 536499053, 536499059, 536499071, 536499077, 536499109, 536499133, 536499157, 536499163, 536499169, 536499211, 536499233, 536499239, 536499259, 536499269, 536499287, 536499307, 536499319, 536499323, 536499329, 536499367, 536499419, 536499427, 536499451, 536499461, 536499463, 536499487, 536499493, 536499503, 536499533, 536499539, 536499571, 536499589, 536499629, 536499631, 536499647, 536499653, 536499659, 536499661, 536499683, 536499721, 536499737, 536499757, 536499763, 536499767, 536499811, 536499851, 536499869, 536499947, 536499961, 536499967, 536500007, 536500009, 536500031, 536500057, 536500073, 536500103, 536500123, 536500163, 536500171, 536500187, 536500189, 536500213, 536500241, 536500249, 536500267, 536500301, 536500309, 536500337, 536500339, 536500351, 536500361, 536500373, 536500381, 536500387, 536500409, 536500417, 536500453, 536500483, 536500487, 536500499, 536500519, 536500543, 536500561, 536500649, 536500669, 536500681, 536500687, 536500709, 536500711, 536500717, 536500721, 536500733, 536500763, 536500781, 536500793, 536500819, 536500823, 536500831, 536500837, 536500843, 536500847, 536500859, 536500903, 536500919, 536501003, 536501023, 536501041, 536501051, 536501117, 536501143, 536501183, 536501191, 536501201, 536501209, 536501257, 536501267, 536501291, 536501321, 536501323, 536501341, 536501377, 536501387, 536501393, 536501431, 536501477, 536501491, 536501501, 536501503, 536501507, 536501533, 536501549, 536501587, 536501599, 536501617, 536501621, 536501639, 536501671, 536501677, 536501683, 536501699, 536501729, 536501731, 536501741, 536501743, 536501761, 536501789, 536501831, 536501863, 536501869, 536501873, 536501899, 536501923, 536501951, 536501969, 536501989, 536502007, 536502011, 536502017, 536502019, 536502023, 536502037, 536502047, 536502049, 536502139, 536502143, 536502157, 536502283, 536502353, 536502359, 536502361, 536502377, 536502397, 536502401, 536502403, 536502409, 536502419, 536502431, 536502451, 536502493, 536502497, 536502569, 536502587, 536502611, 536502653, 536502683, 536502689, 536502719, 536502727, 536502731, 536502739, 536502749, 536502773, 536502793, 536502821, 536502851, 536502877, 536502893, 536502907, 536502913, 536502931, 536502937, 536502961, 536502973, 536502977, 536503007, 536503013, 536503039, 536503043, 536503049, 536503067, 536503109, 536503127, 536503139, 536503157, 536503181, 536503183, 536503189, 536503223, 536503229, 536503241, 536503249, 536503273, 536503291, 536503339, 536503349, 536503369, 536503379, 536503417, 536503423, 536503433, 536503439, 536503483, 536503489, 536503501, 536503507, 536503519, 536503537, 536503571, 536503603, 536503613, 536503657, 536503687, 536503757, 536503769, 536503787, 536503813, 536503823, 536503843, 536503861, 536503871, 536503879, 536503883, 536503927, 536503939, 536503943, 536503951, 536503997, 536504009, 536504053, 536504063, 536504069, 536504113, 536504117, 536504119, 536504123, 536504167, 536504179, 536504183, 536504191, 536504209, 536504219, 536504251, 536504299, 536504303, 536504323, 536504351, 536504363, 536504369, 536504399, 536504401, 536504413, 536504459, 536504461, 536504473, 536504489, 536504543, 536504561, 536504567, 536504587, 536504599, 536504621, 536504651, 536504713, 536504723, 536504777, 536504783, 536504789, 536504791, 536504797, 536504807, 536504827, 536504861, 536504863, 536504869, 536504893, 536504929, 536504951, 536504977, 536504981, 536504993, 536505001, 536505007, 536505059, 536505103, 536505121, 536505149, 536505173, 536505197, 536505239, 536505241, 536505257, 536505287, 536505301, 536505311, 536505331, 536505401, 536505407, 536505421, 536505427, 536505449, 536505461, 536505479, 536505493, 536505503, 536505523, 536505547, 536505631, 536505643, 536505677, 536505701, 536505707, 536505709, 536505719, 536505721, 536505727, 536505733, 536505743, 536505757, 536505763, 536505773, 536505779, 536505817, 536505833, 536505841, 536505847, 536505859, 536505899, 536505911, 536505943, 536505979, 536505989, 536505997, 536506001, 536506049, 536506063, 536506079, 536506099, 536506109, 536506123, 536506133, 536506153, 536506169, 536506199, 536506207, 536506219, 536506231, 536506241, 536506283, 536506309, 536506331, 536506379, 536506381, 536506387, 536506391, 536506403, 536506423, 536506427, 536506433, 536506463, 536506469, 536506493, 536506541, 536506543, 536506561, 536506567, 536506573, 536506603, 536506609, 536506627, 536506631, 536506643, 536506673, 536506693, 536506703, 536506741, 536506777, 536506793, 536506807, 536506813, 536506871, 536506891, 536506897, 536506907, 536506951, 536506973, 536506979, 536507071, 536507089, 536507093, 536507129, 536507143, 536507159, 536507171, 536507189, 536507201, 536507203, 536507227, 536507273, 536507333, 536507341, 536507347, 536507357, 536507371, 536507401, 536507417, 536507443, 536507467, 536507479, 536507501, 536507513, 536507519, 536507527, 536507537, 536507557, 536507567, 536507581, 536507599, 536507611, 536507663, 536507687, 536507717, 536507747, 536507759, 536507789, 536507809, 536507819, 536507833, 536507843, 536507863, 536507869, 536507953, 536507957, 536507969, 536507977, 536507989, 536507999, 536508013, 536508017, 536508019, 536508023, 536508053, 536508101, 536508121, 536508139, 536508173, 536508191, 536508209, 536508211, 536508257, 536508307, 536508311, 536508331, 536508353, 536508361, 536508383, 536508391, 536508433, 536508487, 536508499, 536508503, 536508517, 536508601, 536508611, 536508629, 536508641, 536508647, 536508659, 536508689, 536508697, 536508751, 536508761, 536508767, 536508793, 536508799, 536508823, 536508839, 536508857, 536508881, 536508923, 536508937, 536508949, 536508953, 536509027, 536509031, 536509049, 536509079, 536509093, 536509111, 536509117, 536509147, 536509187, 536509229, 536509241, 536509283, 536509291, 536509319, 536509381, 536509397, 536509417, 536509433, 536509451, 536509453, 536509459, 536509481, 536509487, 536509499, 536509507, 536509537, 536509549, 536509553, 536509573, 536509601, 536509607, 536509609, 536509639, 536509691, 536509709, 536509741, 536509763, 536509781, 536509789, 536509801, 536509819, 536509843, 536509871, 536509903, 536509913, 536509927, 536509957, 536509991, 536510003, 536510017, 536510041, 536510057, 536510059, 536510113, 536510119, 536510147, 536510159, 536510171, 536510173, 536510197, 536510263, 536510267, 536510279, 536510309, 536510383, 536510407, 536510413, 536510419, 536510449, 536510477, 536510479, 536510503, 536510509, 536510563, 536510609, 536510621, 536510647, 536510651, 536510683, 536510729, 536510731, 536510747, 536510761, 536510773, 536510797, 536510801, 536510813, 536510839, 536510851, 536510867, 536510869, 536510879, 536510917, 536510929, 536510951, 536510959, 536510963, 536510983, 536510993, 536511023, 536511071, 536511089, 536511097, 536511167, 536511181, 536511193, 536511197, 536511229, 536511257, 536511259, 536511289, 536511299, 536511307, 536511319, 536511337, 536511427, 536511431, 536511467, 536511487, 536511557, 536511583, 536511617, 536511631, 536511649, 536511659, 536511667, 536511709, 536511719, 536511727, 536511743, 536511749, 536511757, 536511769, 536511791, 536511793, 536511799, 536511809, 536511827, 536511841, 536511851, 536511853, 536511863, 536511883, 536511889, 536511893, 536511923, 536511929, 536511953, 536511973, 536512001, 536512037, 536512051, 536512069, 536512073, 536512087, 536512111, 536512117, 536512121, 536512153, 536512157, 536512189, 536512199, 536512213, 536512243, 536512289, 536512331, 536512343, 536512351, 536512357, 536512363, 536512387, 536512393, 536512397, 536512451, 536512517, 536512573, 536512577, 536512589, 536512601, 536512607, 536512609, 536512637, 536512649, 536512657, 536512663, 536512729, 536512733, 536512771, 536512817, 536512819, 536512841, 536512859, 536512871, 536512883, 536512903, 536512931, 536512957, 536512969, 536512997, 536513017, 536513027, 536513041, 536513053, 536513057, 536513059, 536513077, 536513101, 536513113, 536513123, 536513161, 536513171, 536513177, 536513191, 536513207, 536513231, 536513291, 536513297, 536513303, 536513363, 536513399, 536513401, 536513407, 536513423, 536513437, 536513441, 536513443, 536513447, 536513459, 536513501, 536513531, 536513533, 536513563, 536513599, 536513603, 536513629, 536513639, 536513651, 536513669, 536513707, 536513711, 536513723, 536513749, 536513759, 536513779, 536513827, 536513867, 536513899, 536513903, 536513921, 536513933, 536513953, 536513981, 536514049, 536514073, 536514079, 536514107, 536514113, 536514119, 536514133, 536514163, 536514193, 536514211, 536514221, 536514247, 536514263, 536514287, 536514289, 536514301, 536514367, 536514379, 536514383, 536514409, 536514431, 536514439, 536514481, 536514487, 536514499, 536514521, 536514527, 536514593, 536514599, 536514619, 536514623, 536514637, 536514653, 536514659, 536514661, 536514683, 536514697, 536514701, 536514733, 536514749, 536514757, 536514779, 536514787, 536514817, 536514829, 536514871, 536514943, 536514973, 536514977, 536514983, 536515009, 536515061, 536515093, 536515097, 536515127, 536515129, 536515139, 536515193, 536515201, 536515241, 536515247, 536515253, 536515271, 536515277, 536515279, 536515289, 536515327, 536515363, 536515373, 536515391, 536515417, 536515433, 536515453, 536515493, 536515501, 536515517, 536515519, 536515541, 536515561, 536515589, 536515619, 536515621, 536515649, 536515657, 536515663, 536515697, 536515717, 536515739, 536515783, 536515789, 536515813, 536515817, 536515849, 536515867, 536515883, 536515933, 536515957, 536515981, 536515999, 536516003, 536516023, 536516033, 536516041, 536516047, 536516051, 536516063, 536516081, 536516131, 536516159, 536516161, 536516179, 536516207, 536516213, 536516237, 536516251, 536516303, 536516329, 536516333, 536516353, 536516381, 536516389, 536516401, 536516419, 536516437, 536516467, 536516489, 536516527, 536516531, 536516557, 536516567, 536516593, 536516599, 536516627, 536516641, 536516671, 536516681, 536516711, 536516749, 536516759, 536516789, 536516801, 536516807, 536516809, 536516819, 536516833, 536516843, 536516861, 536516863, 536516873, 536516951, 536516963, 536516971, 536516987, 536517011, 536517013, 536517017, 536517019, 536517053, 536517061, 536517073, 536517083, 536517101, 536517167, 536517169, 536517211, 536517227, 536517253, 536517257, 536517277, 536517323, 536517409, 536517437, 536517473, 536517479, 536517491, 536517517, 536517521, 536517523, 536517529, 536517533, 536517551, 536517557, 536517563, 536517577, 536517617, 536517623, 536517629, 536517659, 536517689, 536517691, 536517697, 536517701, 536517799, 536517811, 536517823, 536517853, 536517869, 536517889, 536517907, 536517911, 536517913, 536517931, 536518007, 536518027, 536518051, 536518063, 536518069, 536518091, 536518117, 536518121, 536518139, 536518189, 536518193, 536518201, 536518243, 536518259, 536518261, 536518277, 536518289, 536518319, 536518327, 536518331, 536518337, 536518343, 536518361, 536518369, 536518397, 536518399, 536518403, 536518469, 536518471, 536518501, 536518517, 536518559, 536518603, 536518613, 536518627, 536518663, 536518673, 536518693, 536518709, 536518711, 536518727, 536518817, 536518823, 536518831, 536518837, 536518847, 536518859, 536518877, 536518921, 536518943, 536518951, 536518991, 536519003, 536519029, 536519057, 536519101, 536519117, 536519119, 536519161, 536519189, 536519197, 536519209, 536519219, 536519251, 536519281, 536519327, 536519353, 536519363, 536519369, 536519383, 536519407, 536519519, 536519521, 536519531, 536519561, 536519591, 536519603, 536519611, 536519623, 536519629, 536519639, 536519651, 536519653, 536519713, 536519717, 536519741, 536519747, 536519849, 536519861, 536519887, 536519927, 536519933, 536519939, 536519941, 536519947, 536519953, 536520041, 536520059, 536520077, 536520079, 536520133, 536520151, 536520161, 536520163, 536520197, 536520199, 536520227, 536520247, 536520253, 536520269, 536520277, 536520293, 536520319, 536520343, 536520353, 536520367, 536520377, 536520403, 536520407, 536520433, 536520443, 536520449, 536520451, 536520487, 536520529, 536520533, 536520539, 536520617, 536520637, 536520641, 536520661, 536520671, 536520709, 536520713, 536520737, 536520763, 536520767, 536520773, 536520779, 536520811, 536520821, 536520827, 536520863, 536520869, 536520877, 536520913, 536520983, 536520991, 536521009, 536521021, 536521033, 536521049, 536521079, 536521081, 536521087, 536521133, 536521157, 536521163, 536521211, 536521229, 536521231, 536521243, 536521261, 536521289, 536521319, 536521333, 536521361, 536521387, 536521399, 536521409, 536521417, 536521421, 536521439, 536521463, 536521471, 536521477, 536521499, 536521561, 536521567, 536521589, 536521669, 536521679, 536521693, 536521723, 536521763, 536521807, 536521813, 536521831, 536521847, 536521883, 536521907, 536521913, 536521927, 536521939, 536521949, 536521957, 536522009, 536522017, 536522047, 536522059, 536522099, 536522117, 536522123, 536522141, 536522179, 536522197, 536522291, 536522299, 536522321, 536522387, 536522401, 536522407, 536522419, 536522443, 536522489, 536522491, 536522501, 536522521, 536522561, 536522563, 536522579, 536522593, 536522603, 536522621, 536522641, 536522663, 536522671, 536522677, 536522687, 536522699, 536522711, 536522729, 536522731, 536522747, 536522837, 536522879, 536522887, 536522923, 536522927, 536522933, 536522951, 536522953, 536522957, 536522971, 536522981, 536522989, 536523037, 536523041, 536523079, 536523101, 536523103, 536523131, 536523133, 536523149, 536523151, 536523161, 536523173, 536523191, 536523217, 536523227, 536523233, 536523257, 536523259, 536523263, 536523269, 536523271, 536523289, 536523307, 536523313, 536523319, 536523409, 536523431, 536523433, 536523439, 536523457, 536523497, 536523503, 536523509, 536523571, 536523619, 536523649, 536523667, 536523677, 536523679, 536523683, 536523709, 536523721, 536523733, 536523761, 536523763, 536523803, 536523811, 536523899, 536523917, 536523947, 536523973, 536523979, 536524003, 536524031, 536524049, 536524057, 536524127, 536524133, 536524159, 536524171, 536524193, 536524211, 536524213, 536524217, 536524249, 536524253, 536524277, 536524283, 536524333, 536524357, 536524393, 536524433, 536524453, 536524529, 536524537, 536524561, 536524567, 536524577, 536524589, 536524591, 536524619, 536524627, 536524633, 536524649, 536524661, 536524691, 536524697, 536524739, 536524759, 536524763, 536524771, 536524783, 536524817, 536524847, 536524867, 536524871, 536524873, 536524897, 536524909, 536524927, 536524931, 536524939, 536524949, 536524991, 536524999, 536525009, 536525023, 536525039, 536525047, 536525081, 536525111, 536525131, 536525137, 536525149, 536525177, 536525179, 536525189, 536525239, 536525281, 536525323, 536525357, 536525369, 536525371, 536525377, 536525411, 536525417, 536525441, 536525443, 536525459, 536525461, 536525489, 536525503, 536525533, 536525543, 536525551, 536525557, 536525573, 536525599, 536525651, 536525653, 536525659, 536525681, 536525687, 536525699, 536525701, 536525753, 536525767, 536525783, 536525809, 536525813, 536525849, 536525879, 536525887, 536525903, 536525929, 536525939, 536525981, 536525993, 536526019, 536526043, 536526059, 536526119, 536526121, 536526127, 536526131, 536526139, 536526157, 536526217, 536526229, 536526251, 536526257, 536526271, 536526283, 536526317, 536526323, 536526329, 536526343, 536526377, 536526379, 536526383, 536526391, 536526413, 536526433, 536526499, 536526509, 536526521, 536526527, 536526539, 536526581, 536526629, 536526631, 536526637, 536526673, 536526689, 536526701, 536526719, 536526733, 536526737, 536526743, 536526763, 536526787, 536526797, 536526829, 536526853, 536526863, 536526869, 536526901, 536526917, 536526929, 536526931, 536526961, 536526967, 536526971, 536526979, 536526983, 536526989, 536527007, 536527027, 536527067, 536527081, 536527087, 536527129, 536527133, 536527139, 536527153, 536527163, 536527169, 536527193, 536527207, 536527217, 536527237, 536527241, 536527249, 536527307, 536527319, 536527337, 536527373, 536527393, 536527403, 536527441, 536527457, 536527471, 536527477, 536527507, 536527543, 536527547, 536527549, 536527591, 536527603, 536527669, 536527679, 536527699, 536527709, 536527711, 536527723, 536527793, 536527799, 536527807, 536527891, 536527903, 536527919, 536527921, 536527931, 536527949, 536527961, 536527967, 536527987, 536527997, 536528021, 536528033, 536528039, 536528087, 536528089, 536528093, 536528141, 536528183, 536528197, 536528203, 536528219, 536528273, 536528309, 536528323, 536528341, 536528357, 536528393, 536528417, 536528431, 536528467, 536528491, 536528513, 536528537, 536528539, 536528543, 536528549, 536528557, 536528569, 536528581, 536528599, 536528609, 536528617, 536528647, 536528711, 536528719, 536528723, 536528743, 536528761, 536528771, 536528807, 536528809, 536528813, 536528819, 536528833, 536528893, 536528917, 536528921, 536528933, 536528939, 536528947, 536528969, 536528983, 536529013, 536529031, 536529041, 536529047, 536529089, 536529101, 536529139, 536529143, 536529173, 536529241, 536529269, 536529281, 536529293, 536529373, 536529419, 536529437, 536529439, 536529451, 536529509, 536529517, 536529523, 536529559, 536529569, 536529577, 536529583, 536529599, 536529607, 536529611, 536529613, 536529641, 536529677, 536529683, 536529701, 536529703, 536529737, 536529739, 536529743, 536529787, 536529817, 536529823, 536529827, 536529869, 536529871, 536529883, 536529907, 536529913, 536529943, 536529991, 536529997, 536530021, 536530103, 536530109, 536530117, 536530123, 536530133, 536530153, 536530219, 536530231, 536530259, 536530277, 536530301, 536530349, 536530391, 536530459, 536530471, 536530481, 536530513, 536530567, 536530597, 536530619, 536530627, 536530649, 536530663, 536530723, 536530739, 536530763, 536530777, 536530793, 536530817, 536530831, 536530843, 536530871, 536530877, 536530901, 536530979, 536530993, 536531041, 536531057, 536531077, 536531123, 536531129, 536531131, 536531161, 536531209, 536531213, 536531231, 536531251, 536531257, 536531279, 536531293, 536531341, 536531351, 536531357, 536531381, 536531383, 536531389, 536531393, 536531399, 536531431, 536531459, 536531483, 536531497, 536531507, 536531537, 536531551, 536531621, 536531627, 536531651, 536531659, 536531689, 536531707, 536531711, 536531753, 536531759, 536531771, 536531789, 536531791, 536531803, 536531819, 536531839, 536531869, 536531887, 536531909, 536531953, 536531977, 536531981, 536531999, 536532001, 536532011, 536532041, 536532049, 536532107, 536532131, 536532151, 536532187, 536532193, 536532229, 536532239, 536532299, 536532323, 536532383, 536532419, 536532439, 536532497, 536532499, 536532527, 536532547, 536532551, 536532613, 536532617, 536532643, 536532653, 536532713, 536532719, 536532721, 536532739, 536532743, 536532749, 536532769, 536532791, 536532803, 536532809, 536532817, 536532853, 536532863, 536532877, 536532883, 536532889, 536532917, 536532923, 536532959, 536533007, 536533009, 536533021, 536533033, 536533037, 536533043, 536533097, 536533099, 536533111, 536533133, 536533139, 536533159, 536533171, 536533177, 536533187, 536533201, 536533219, 536533241, 536533273, 536533279, 536533289, 536533301, 536533409, 536533423, 536533427, 536533441, 536533453, 536533463, 536533493, 536533507, 536533519, 536533531, 536533567, 536533579, 536533597, 536533601, 536533603, 536533619, 536533639, 536533649, 536533703, 536533733, 536533801, 536533807, 536533817, 536533819, 536533853, 536533859, 536533891, 536533909, 536533931, 536533937, 536533969, 536534039, 536534071, 536534083, 536534111, 536534147, 536534171, 536534189, 536534213, 536534227, 536534239, 536534261, 536534269, 536534279, 536534287, 536534303, 536534347, 536534353, 536534381, 536534393, 536534443, 536534489, 536534491, 536534503, 536534513, 536534533, 536534543, 536534561, 536534573, 536534591, 536534599, 536534611, 536534617, 536534623, 536534629, 536534653, 536534689, 536534707, 536534729, 536534737, 536534753, 536534767, 536534797, 536534813, 536534827, 536534837, 536534893, 536534959, 536534969, 536534983, 536534989, 536535017, 536535029, 536535031, 536535047, 536535071, 536535121, 536535151, 536535229, 536535239, 536535257, 536535269, 536535277, 536535289, 536535299, 536535301, 536535313, 536535347, 536535359, 536535361, 536535367, 536535379, 536535401, 536535437, 536535469, 536535479, 536535481, 536535511, 536535529, 536535541, 536535551, 536535563, 536535577, 536535613, 536535667, 536535707, 536535709, 536535719, 536535751, 536535761, 536535773, 536535803, 536535829, 536535841, 536535859, 536535863, 536535893, 536535913, 536535917, 536535919, 536535943, 536535959, 536535971, 536536009, 536536027, 536536051, 536536087, 536536093, 536536103, 536536109, 536536129, 536536151, 536536171, 536536181, 536536207, 536536229, 536536243, 536536271, 536536283, 536536289, 536536361, 536536367, 536536379, 536536417, 536536471, 536536493, 536536513, 536536523, 536536529, 536536531, 536536549, 536536577, 536536601, 536536661, 536536669, 536536681, 536536691, 536536697, 536536703, 536536723, 536536727, 536536753, 536536807, 536536829, 536536849, 536536853, 536536873, 536536883, 536536937, 536536943, 536536951, 536536961, 536536969, 536536993, 536536999, 536537003, 536537021, 536537041, 536537063, 536537069, 536537087, 536537107, 536537117, 536537137, 536537147, 536537159, 536537161, 536537171, 536537189, 536537191, 536537249, 536537263, 536537279, 536537293, 536537297, 536537317, 536537321, 536537329, 536537369, 536537377, 536537431, 536537437, 536537501, 536537539, 536537543, 536537549, 536537569, 536537581, 536537587, 536537591, 536537623, 536537633, 536537641, 536537653, 536537693, 536537717, 536537741, 536537773, 536537779, 536537803, 536537819, 536537831, 536537839, 536537843, 536537857, 536537861, 536537873, 536537887, 536537893, 536537927, 536537929, 536538007, 536538011, 536538053, 536538097, 536538109, 536538143, 536538157, 536538179, 536538199, 536538203, 536538253, 536538281, 536538293, 536538307, 536538313, 536538329, 536538347, 536538383, 536538407, 536538413, 536538419, 536538463, 536538469, 536538487, 536538521, 536538559, 536538589, 536538593, 536538601, 536538617, 536538623, 536538631, 536538637, 536538659, 536538703, 536538713, 536538757, 536538763, 536538781, 536538791, 536538799, 536538811, 536538823, 536538829, 536538839, 536538883, 536538911, 536538923, 536538931, 536539001, 536539013, 536539067, 536539111, 536539151, 536539163, 536539177, 536539181, 536539187, 536539207, 536539229, 536539231, 536539247, 536539249, 536539253, 536539273, 536539277, 536539291, 536539303, 536539321, 536539343, 536539349, 536539361, 536539369, 536539387, 536539427, 536539441, 536539447, 536539457, 536539459, 536539483, 536539513, 536539517, 536539519, 536539541, 536539543, 536539609, 536539657, 536539667, 536539709, 536539739, 536539741, 536539753, 536539763, 536539769, 536539777, 536539781, 536539799, 536539811, 536539831, 536539889, 536539903, 536539919, 536539937, 536539961, 536539963, 536539973, 536540003, 536540023, 536540029, 536540057, 536540099, 536540117, 536540129, 536540131, 536540143, 536540161, 536540167, 536540177, 536540189, 536540261, 536540267, 536540299, 536540317, 536540341, 536540351, 536540353, 536540371, 536540377, 536540399, 536540423, 536540447, 536540471, 536540533, 536540561, 536540603, 536540617, 536540633, 536540647, 536540651, 536540657, 536540701, 536540789, 536540857, 536540869, 536540887, 536540923, 536540929, 536540969, 536541017, 536541041, 536541043, 536541053, 536541067, 536541127, 536541179, 536541191, 536541227, 536541259, 536541277, 536541283, 536541287, 536541319, 536541353, 536541367, 536541409, 536541413, 536541443, 536541469, 536541479, 536541541, 536541553, 536541569, 536541587, 536541601, 536541623, 536541637, 536541647, 536541653, 536541667, 536541697, 536541713, 536541749, 536541757, 536541767, 536541821, 536541827, 536541833, 536541839, 536541857, 536541877, 536541881, 536541883, 536541899, 536541919, 536541923, 536541937, 536541961, 536542001, 536542051, 536542057, 536542087, 536542147, 536542169, 536542207, 536542301, 536542309, 536542339, 536542351, 536542379, 536542399, 536542403, 536542417, 536542453, 536542469, 536542511, 536542537, 536542549, 536542561, 536542571, 536542607, 536542613, 536542631, 536542639, 536542663, 536542681, 536542693, 536542711, 536542723, 536542733, 536542751, 536542757, 536542801, 536542807, 536542817, 536542829, 536542841, 536542861, 536542889, 536542907, 536542913, 536542921, 536542927, 536542931, 536542961, 536542999, 536543027, 536543041, 536543053, 536543087, 536543113, 536543143, 536543173, 536543191, 536543219, 536543233, 536543243, 536543309, 536543311, 536543321, 536543347, 536543363, 536543389, 536543393, 536543417, 536543419, 536543509, 536543597, 536543599, 536543621, 536543633, 536543669, 536543713, 536543743, 536543759, 536543773, 536543803, 536543807, 536543837, 536543873, 536543893, 536543897, 536543899, 536543927, 536544037, 536544079, 536544119, 536544133, 536544137, 536544143, 536544149, 536544209, 536544269, 536544271, 536544301, 536544343, 536544347, 536544383, 536544389, 536544419, 536544427, 536544431, 536544443, 536544451, 536544469, 536544473, 536544479, 536544521, 536544557, 536544571, 536544577, 536544601, 536544607, 536544611, 536544637, 536544641, 536544653, 536544661, 536544719, 536544721, 536544727, 536544751, 536544763, 536544779, 536544791, 536544793, 536544797, 536544839, 536544847, 536544859, 536544887, 536544889, 536544907, 536544919, 536544923, 536544929, 536544949, 536545001, 536545033, 536545043, 536545049, 536545057, 536545069, 536545151, 536545159, 536545171, 536545183, 536545213, 536545253, 536545267, 536545277, 536545291, 536545297, 536545309, 536545337, 536545349, 536545369, 536545411, 536545417, 536545439, 536545441, 536545463, 536545507, 536545531, 536545577, 536545601, 536545637, 536545649, 536545657, 536545661, 536545697, 536545727, 536545747, 536545753, 536545811, 536545831, 536545837, 536545853, 536545901, 536545903, 536545913, 536545927, 536545957, 536545973, 536545981, 536546009, 536546033, 536546039, 536546041, 536546051, 536546071, 536546089, 536546099, 536546141, 536546147, 536546159, 536546173, 536546183, 536546191, 536546207, 536546237, 536546249, 536546267, 536546273, 536546281, 536546327, 536546341, 536546347, 536546363, 536546393, 536546411, 536546443, 536546449, 536546477, 536546489, 536546497, 536546513, 536546551, 536546573, 536546627, 536546651, 536546671, 536546677, 536546701, 536546797, 536546827, 536546863, 536546891, 536546897, 536546903, 536546917, 536546963, 536546987, 536547017, 536547019, 536547043, 536547073, 536547097, 536547139, 536547191, 536547199, 536547203, 536547227, 536547257, 536547281, 536547283, 536547293, 536547307, 536547313, 536547329, 536547337, 536547371, 536547379, 536547383, 536547409, 536547419, 536547433, 536547437, 536547439, 536547467, 536547493, 536547511, 536547547, 536547551, 536547553, 536547569, 536547587, 536547601, 536547677, 536547691, 536547731, 536547733, 536547769, 536547793, 536547827, 536547839, 536547889, 536547901, 536547919, 536547929, 536547943, 536547953, 536547961, 536547967, 536547983, 536547997, 536548007, 536548039, 536548073, 536548079, 536548123, 536548153, 536548213, 536548231, 536548267, 536548273, 536548283, 536548289, 536548357, 536548379, 536548387, 536548399, 536548417, 536548477, 536548483, 536548501, 536548513, 536548549, 536548643, 536548681, 536548697, 536548699, 536548703, 536548751, 536548787, 536548801, 536548819, 536548823, 536548829, 536548843, 536548879, 536548889, 536548897, 536548907, 536548921, 536548963, 536548967, 536548993, 536548997, 536549011, 536549029, 536549033, 536549063, 536549077, 536549093, 536549159, 536549161, 536549171, 536549183, 536549191, 536549203, 536549207, 536549261, 536549281, 536549309, 536549311, 536549323, 536549353, 536549383, 536549401, 536549423, 536549441, 536549443, 536549491, 536549501, 536549527, 536549537, 536549539, 536549609, 536549621, 536549623, 536549633, 536549641, 536549653, 536549693, 536549701, 536549737, 536549747, 536549779, 536549789, 536549803, 536549807, 536549809, 536549813, 536549887, 536549917, 536549947, 536549989, 536550011, 536550013, 536550019, 536550041, 536550059, 536550089, 536550143, 536550151, 536550163, 536550191, 536550221, 536550247, 536550251, 536550281, 536550293, 536550299, 536550317, 536550319, 536550349, 536550361, 536550389, 536550397, 536550409, 536550437, 536550439, 536550451, 536550467, 536550503, 536550529, 536550533, 536550577, 536550613, 536550631, 536550691, 536550701, 536550733, 536550757, 536550799, 536550841, 536550851, 536550863, 536550871, 536550881, 536550901, 536550907, 536550913, 536550967, 536550977, 536550983, 536551019, 536551021, 536551027, 536551031, 536551039, 536551049, 536551079, 536551109, 536551117, 536551121, 536551123, 536551129, 536551139, 536551177, 536551187, 536551271, 536551273, 536551333, 536551349, 536551373, 536551381, 536551391, 536551397, 536551403, 536551409, 536551423, 536551439, 536551481, 536551511, 536551559, 536551571, 536551573, 536551579, 536551643, 536551657, 536551667, 536551681, 536551699, 536551727, 536551733, 536551747, 536551777, 536551781, 536551783, 536551787, 536551793, 536551801, 536551819, 536551861, 536551867, 536551901, 536551903, 536551919, 536551931, 536551987, 536551991, 536552017, 536552033, 536552099, 536552161, 536552179, 536552197, 536552201, 536552221, 536552227, 536552239, 536552243, 536552293, 536552333, 536552339, 536552347, 536552353, 536552399, 536552411, 536552413, 536552447, 536552449, 536552477, 536552491, 536552507, 536552531, 536552537, 536552543, 536552593, 536552603, 536552663, 536552669, 536552707, 536552713, 536552741, 536552749, 536552777, 536552791, 536552801, 536552833, 536552851, 536552959, 536552969, 536552977, 536552999, 536553007, 536553013, 536553067, 536553071, 536553089, 536553109, 536553113, 536553119, 536553161, 536553163, 536553181, 536553203, 536553211, 536553221, 536553233, 536553253, 536553271, 536553289, 536553307, 536553341, 536553349, 536553359, 536553419, 536553421, 536553497, 536553547, 536553553, 536553557, 536553617, 536553649, 536553659, 536553671, 536553691, 536553727, 536553733, 536553763, 536553767, 536553781, 536553793, 536553803, 536553811, 536553841, 536553893, 536553907, 536553923, 536553929, 536553931, 536553947, 536553967, 536553971, 536553989, 536553991, 536554009, 536554013, 536554037, 536554079, 536554093, 536554121, 536554127, 536554147, 536554177, 536554181, 536554217, 536554219, 536554229, 536554237, 536554267, 536554297, 536554309, 536554321, 536554339, 536554349, 536554393, 536554399, 536554429, 536554463, 536554477, 536554481, 536554507, 536554537, 536554573, 536554583, 536554619, 536554637, 536554639, 536554651, 536554687, 536554721, 536554729, 536554757, 536554769, 536554783, 536554831, 536554853, 536554877, 536554933, 536554937, 536554951, 536554999, 536555009, 536555021, 536555039, 536555053, 536555057, 536555111, 536555137, 536555147, 536555177, 536555179, 536555191, 536555197, 536555213, 536555237, 536555251, 536555287, 536555291, 536555311, 536555317, 536555323, 536555353, 536555359, 536555399, 536555401, 536555417, 536555441, 536555483, 536555489, 536555491, 536555599, 536555603, 536555609, 536555627, 536555639, 536555647, 536555671, 536555681, 536555689, 536555711, 536555749, 536555797, 536555837, 536555917, 536555947, 536555951, 536555963, 536555977, 536556011, 536556103, 536556127, 536556133, 536556191, 536556197, 536556221, 536556233, 536556247, 536556269, 536556287, 536556313, 536556343, 536556359, 536556367, 536556379, 536556403, 536556413, 536556457, 536556467, 536556469, 536556473, 536556491, 536556511, 536556563, 536556589, 536556593, 536556607, 536556611, 536556613, 536556659, 536556667, 536556689, 536556697, 536556739, 536556803, 536556817, 536556829, 536556859, 536556863, 536556871, 536556887, 536556893, 536556899, 536556929, 536556931, 536556953, 536556983, 536556989, 536556991, 536557003, 536557039, 536557057, 536557067, 536557117, 536557163, 536557181, 536557183, 536557193, 536557199, 536557211, 536557253, 536557279, 536557291, 536557297, 536557309, 536557361, 536557367, 536557379, 536557423, 536557459, 536557471, 536557487, 536557523, 536557577, 536557627, 536557633, 536557643, 536557657, 536557669, 536557673, 536557699, 536557711, 536557727, 536557783, 536557799, 536557817, 536557829, 536557837, 536557843, 536557871, 536557877, 536557919, 536557921, 536557933, 536557963, 536557991, 536557993, 536557997, 536558017, 536558069, 536558083, 536558101, 536558111, 536558123, 536558153, 536558161, 536558179, 536558207, 536558263, 536558279, 536558291, 536558299, 536558339, 536558353, 536558357, 536558383, 536558401, 536558419, 536558453, 536558489, 536558521, 536558543, 536558557, 536558569, 536558593, 536558629, 536558639, 536558683, 536558707, 536558723, 536558741, 536558747, 536558767, 536558779, 536558791, 536558801, 536558807, 536558821, 536558837, 536558843, 536558851, 536558903, 536558929, 536558933, 536558951, 536558959, 536558963, 536559029, 536559047, 536559053, 536559077, 536559091, 536559109, 536559119, 536559173, 536559193, 536559197, 536559217, 536559223, 536559229, 536559269, 536559299, 536559307, 536559313, 536559319, 536559337, 536559343, 536559347, 536559403, 536559407, 536559431, 536559467, 536559469, 536559523, 536559539, 536559553, 536559577, 536559613, 536559619, 536559643, 536559689, 536559691, 536559731, 536559761, 536559799, 536559809, 536559823, 536559833, 536559841, 536559853, 536559889, 536559913, 536559917, 536559923, 536559941, 536560009, 536560027, 536560049, 536560061, 536560099, 536560111, 536560139, 536560151, 536560159, 536560249, 536560259, 536560267, 536560301, 536560313, 536560327, 536560373, 536560417, 536560463, 536560483, 536560487, 536560543, 536560571, 536560597, 536560603, 536560621, 536560631, 536560667, 536560669, 536560693, 536560709, 536560729, 536560733, 536560747, 536560753, 536560763, 536560777, 536560799, 536560807, 536560831, 536560861, 536560889, 536560901, 536560909, 536560933, 536560963, 536560967, 536561027, 536561101, 536561107, 536561141, 536561167, 536561203, 536561209, 536561213, 536561257, 536561297, 536561303, 536561323, 536561341, 536561357, 536561371, 536561401, 536561407, 536561449, 536561471, 536561477, 536561479, 536561483, 536561579, 536561581, 536561617, 536561639, 536561651, 536561681, 536561689, 536561699, 536561719, 536561747, 536561789, 536561791, 536561801, 536561807, 536561819, 536561821, 536561833, 536561849, 536561867, 536561897, 536561941, 536561959, 536562029, 536562067, 536562119, 536562137, 536562139, 536562151, 536562157, 536562163, 536562179, 536562181, 536562217, 536562227, 536562251, 536562277, 536562289, 536562311, 536562319, 536562371, 536562401, 536562421, 536562457, 536562463, 536562473, 536562491, 536562497, 536562503, 536562529, 536562541, 536562563, 536562569, 536562673, 536562683, 536562709, 536562737, 536562749, 536562773, 536562781, 536562797, 536562809, 536562811, 536562827, 536562841, 536562853, 536562877, 536562899, 536562931, 536562979, 536562991, 536562997, 536563003, 536563009, 536563033, 536563057, 536563063, 536563081, 536563087, 536563091, 536563109, 536563141, 536563147, 536563193, 536563201, 536563217, 536563219, 536563229, 536563253, 536563273, 536563303, 536563309, 536563319, 536563387, 536563397, 536563399, 536563427, 536563441, 536563471, 536563483, 536563487, 536563493, 536563549, 536563583, 536563613, 536563627, 536563631, 536563637, 536563691, 536563721, 536563789, 536563801, 536563861, 536563873, 536563879, 536563901, 536563931, 536563957, 536563961, 536563999, 536564023, 536564029, 536564051, 536564059, 536564069, 536564107, 536564141, 536564167, 536564219, 536564243, 536564279, 536564311, 536564317, 536564333, 536564339, 536564377, 536564411, 536564423, 536564437, 536564443, 536564471, 536564477, 536564513, 536564533, 536564543, 536564551, 536564573, 536564593, 536564597, 536564627, 536564653, 536564657, 536564669, 536564671, 536564683, 536564711, 536564753, 536564779, 536564803, 536564813, 536564837, 536564849, 536564869, 536564923, 536564933, 536564947, 536564969, 536564971, 536564993, 536565013, 536565017, 536565041, 536565053, 536565097, 536565131, 536565167, 536565173, 536565179, 536565191, 536565199, 536565251, 536565299, 536565311, 536565313, 536565347, 536565353, 536565397, 536565409, 536565431, 536565433, 536565451, 536565457, 536565467, 536565473, 536565479, 536565487, 536565503, 536565521, 536565553, 536565559, 536565563, 536565581, 536565593, 536565599, 536565619, 536565649, 536565661, 536565683, 536565691, 536565727, 536565761, 536565767, 536565769, 536565773, 536565779, 536565793, 536565803, 536565817, 536565829, 536565851, 536565853, 536565857, 536565863, 536565899, 536565937, 536565941, 536565989, 536566003, 536566013, 536566039, 536566109, 536566153, 536566181, 536566201, 536566229, 536566231, 536566249, 536566253, 536566301, 536566307, 536566319, 536566397, 536566453, 536566463, 536566477, 536566501, 536566543, 536566577, 536566579, 536566603, 536566627, 536566633, 536566643, 536566651, 536566663, 536566673, 536566739, 536566757, 536566763, 536566799, 536566813, 536566819, 536566831, 536566847, 536566871, 536566889, 536566907, 536566949, 536566957, 536566969, 536566981, 536566991, 536567033, 536567047, 536567051, 536567089, 536567099, 536567111, 536567113, 536567117, 536567137, 536567147, 536567153, 536567173, 536567179, 536567183, 536567191, 536567257, 536567261, 536567281, 536567329, 536567333, 536567351, 536567363, 536567371, 536567393, 536567401, 536567419, 536567453, 536567489, 536567497, 536567501, 536567513, 536567567, 536567573, 536567597, 536567627, 536567663, 536567687, 536567699, 536567701, 536567737, 536567741, 536567749, 536567783, 536567789, 536567791, 536567807, 536567833, 536567849, 536567873, 536567887, 536567893, 536567953, 536567987, 536568023, 536568029, 536568041, 536568077, 536568167, 536568169, 536568203, 536568209, 536568211, 536568223, 536568239, 536568247, 536568251, 536568281, 536568287, 536568293, 536568301, 536568359, 536568377, 536568407, 536568419, 536568421, 536568443, 536568457, 536568463, 536568481, 536568521, 536568547, 536568559, 536568563, 536568581, 536568589, 536568601, 536568631, 536568649, 536568653, 536568691, 536568713, 536568719, 536568731, 536568737, 536568751, 536568803, 536568811, 536568827, 536568847, 536568853, 536568883, 536568887, 536568899, 536568913, 536568917, 536568937, 536568947, 536568961, 536568971, 536569013, 536569037, 536569039, 536569109, 536569123, 536569133, 536569141, 536569157, 536569217, 536569247, 536569261, 536569273, 536569279, 536569331, 536569349, 536569357, 536569373, 536569391, 536569399, 536569417, 536569441, 536569459, 536569463, 536569489, 536569493, 536569499, 536569543, 536569547, 536569559, 536569577, 536569601, 536569619, 536569639, 536569651, 536569667, 536569673, 536569681, 536569729, 536569739, 536569753, 536569771, 536569799, 536569801, 536569811, 536569837, 536569853, 536569877, 536569879, 536569883, 536569897, 536569909, 536569931, 536569949, 536569987, 536570063, 536570071, 536570077, 536570087, 536570107, 536570117, 536570119, 536570137, 536570141, 536570149, 536570159, 536570161, 536570173, 536570261, 536570273, 536570299, 536570311, 536570327, 536570401, 536570417, 536570429, 536570453, 536570467, 536570509, 536570521, 536570527, 536570539, 536570561, 536570563, 536570581, 536570591, 536570597, 536570623, 536570663, 536570689, 536570717, 536570747, 536570777, 536570791, 536570821, 536570831, 536570857, 536570861, 536570869, 536570873, 536570897, 536570917, 536570939, 536570953, 536570959, 536570987, 536570989, 536571011, 536571019, 536571029, 536571031, 536571037, 536571047, 536571053, 536571089, 536571107, 536571109, 536571131, 536571149, 536571169, 536571173, 536571197, 536571247, 536571257, 536571263, 536571293, 536571307, 536571319, 536571367, 536571379, 536571401, 536571449, 536571463, 536571479, 536571487, 536571517, 536571559, 536571589, 536571593, 536571619, 536571667, 536571689, 536571703, 536571719, 536571733, 536571757, 536571767, 536571769, 536571803, 536571821, 536571823, 536571829, 536571857, 536571877, 536571883, 536571887, 536571923, 536571953, 536571977, 536572061, 536572067, 536572081, 536572111, 536572117, 536572193, 536572219, 536572237, 536572243, 536572271, 536572303, 536572307, 536572321, 536572327, 536572363, 536572433, 536572469, 536572523, 536572571, 536572573, 536572577, 536572601, 536572613, 536572627, 536572637, 536572651, 536572709, 536572741, 536572747, 536572753, 536572759, 536572843, 536572847, 536572867, 536572879, 536572909, 536572937, 536572973, 536572979, 536573029, 536573047, 536573069, 536573071, 536573087, 536573111, 536573119, 536573131, 536573161, 536573173, 536573183, 536573201, 536573207, 536573209, 536573231, 536573237, 536573239, 536573267, 536573299, 536573309, 536573311, 536573321, 536573339, 536573347, 536573351, 536573353, 536573383, 536573413, 536573423, 536573441, 536573447, 536573461, 536573489, 536573497, 536573501, 536573539, 536573551, 536573563, 536573591, 536573599, 536573627, 536573641, 536573657, 536573663, 536573677, 536573701, 536573717, 536573743, 536573783, 536573809, 536573867, 536573879, 536573893, 536573911, 536574019, 536574091, 536574113, 536574131, 536574149, 536574169, 536574187, 536574287, 536574323, 536574343, 536574377, 536574403, 536574413, 536574461, 536574523, 536574583, 536574589, 536574637, 536574641, 536574653, 536574673, 536574677, 536574679, 536574707, 536574739, 536574781, 536574799, 536574811, 536574817, 536574823, 536574833, 536574847, 536574853, 536574881, 536574887, 536574911, 536574917, 536574949, 536574979, 536574989, 536575003, 536575009, 536575019, 536575049, 536575057, 536575079, 536575103, 536575129, 536575153, 536575157, 536575177, 536575183, 536575201, 536575217, 536575229, 536575357, 536575363, 536575379, 536575397, 536575399, 536575411, 536575421, 536575423, 536575483, 536575489, 536575519, 536575531, 536575541, 536575549, 536575553, 536575577, 536575583, 536575601, 536575639, 536575643, 536575649, 536575667, 536575673, 536575681, 536575691, 536575747, 536575841, 536575847, 536575877, 536575909, 536575939, 536575943, 536575997, 536576021, 536576023, 536576041, 536576057, 536576063, 536576071, 536576077, 536576087, 536576101, 536576107, 536576141, 536576203, 536576251, 536576263, 536576273, 536576297, 536576311, 536576329, 536576333, 536576363, 536576377, 536576419, 536576429, 536576441, 536576483, 536576497, 536576501, 536576527, 536576533, 536576561, 536576563, 536576569, 536576597, 536576609, 536576629, 536576693, 536576713, 536576723, 536576731, 536576767, 536576779, 536576783, 536576809, 536576827, 536576851, 536576893, 536576921, 536576939, 536576947, 536576993, 536577011, 536577017, 536577029, 536577037, 536577049, 536577061, 536577079, 536577089, 536577163, 536577187, 536577191, 536577199, 536577221, 536577277, 536577299, 536577323, 536577389, 536577397, 536577403, 536577407, 536577421, 536577463, 536577491, 536577493, 536577527, 536577553, 536577563, 536577593, 536577599, 536577659, 536577697, 536577733, 536577761, 536577763, 536577773, 536577781, 536577793, 536577799, 536577809, 536577823, 536577827, 536577857, 536577869, 536577871, 536577893, 536577913, 536577931, 536577949, 536577983, 536578013, 536578067, 536578087, 536578099, 536578153, 536578171, 536578177, 536578199, 536578243, 536578261, 536578267, 536578279, 536578283, 536578291, 536578303, 536578309, 536578313, 536578319, 536578321, 536578337, 536578351, 536578379, 536578409, 536578417, 536578423, 536578457, 536578459, 536578481, 536578517, 536578541, 536578577, 536578607, 536578621, 536578643, 536578657, 536578673, 536578681, 536578711, 536578727, 536578733, 536578739, 536578747, 536578759, 536578789, 536578807, 536578853, 536578859, 536578919, 536578927, 536578979, 536578993, 536579027, 536579033, 536579047, 536579063, 536579077, 536579123, 536579149, 536579159, 536579161, 536579203, 536579227, 536579231, 536579237, 536579293, 536579311, 536579317, 536579321, 536579339, 536579357, 536579389, 536579429, 536579441, 536579509, 536579573, 536579599, 536579611, 536579647, 536579677, 536579707, 536579717, 536579723, 536579759, 536579761, 536579773, 536579783, 536579801, 536579831, 536579881, 536579941, 536579947, 536579971, 536580001, 536580029, 536580047, 536580049, 536580073, 536580089, 536580113, 536580119, 536580131, 536580167, 536580173, 536580193, 536580203, 536580221, 536580229, 536580257, 536580259, 536580263, 536580281, 536580307, 536580329, 536580347, 536580371, 536580413, 536580437, 536580467, 536580479, 536580553, 536580559, 536580589, 536580599, 536580601, 536580637, 536580647, 536580661, 536580679, 536580683, 536580739, 536580743, 536580749, 536580761, 536580763, 536580773, 536580787, 536580799, 536580859, 536580871, 536580883, 536580887, 536580943, 536580977, 536580991, 536581043, 536581057, 536581079, 536581103, 536581117, 536581159, 536581163, 536581181, 536581207, 536581231, 536581271, 536581273, 536581307, 536581313, 536581321, 536581327, 536581361, 536581379, 536581393, 536581417, 536581429, 536581447, 536581453, 536581501, 536581537, 536581553, 536581607, 536581613, 536581663, 536581691, 536581723, 536581729, 536581763, 536581769, 536581777, 536581823, 536581841, 536581849, 536581873, 536581879, 536581889, 536581891, 536581909, 536581933, 536581937, 536581943, 536581961, 536582077, 536582089, 536582093, 536582113, 536582119, 536582143, 536582153, 536582159, 536582191, 536582231, 536582261, 536582279, 536582281, 536582359, 536582381, 536582411, 536582443, 536582461, 536582483, 536582489, 536582491, 536582531, 536582561, 536582567, 536582569, 536582587, 536582593, 536582609, 536582623, 536582677, 536582701, 536582719, 536582749, 536582789, 536582791, 536582861, 536582899, 536582927, 536582941, 536582947, 536582957, 536582983, 536582987, 536582989, 536583011, 536583013, 536583029, 536583037, 536583043, 536583049, 536583059, 536583079, 536583097, 536583119, 536583127, 536583133, 536583149, 536583193, 536583221, 536583227, 536583239, 536583251, 536583263, 536583293, 536583319, 536583323, 536583331, 536583337, 536583391, 536583409, 536583413, 536583457, 536583497, 536583517, 536583569, 536583571, 536583589, 536583599, 536583613, 536583647, 536583659, 536583667, 536583703, 536583739, 536583757, 536583779, 536583787, 536583793, 536583809, 536583823, 536583829, 536583841, 536583857, 536583871, 536583881, 536583889, 536583911, 536583917, 536583941, 536583947, 536583967, 536583973, 536583977, 536583979, 536584019, 536584051, 536584067, 536584159, 536584163, 536584171, 536584199, 536584207, 536584211, 536584231, 536584241, 536584259, 536584297, 536584333, 536584337, 536584369, 536584381, 536584387, 536584421, 536584423, 536584439, 536584493, 536584519, 536584523, 536584547, 536584553, 536584579, 536584613, 536584627, 536584661, 536584679, 536584717, 536584729, 536584751, 536584771, 536584781, 536584793, 536584823, 536584849, 536584877, 536584913, 536584933, 536584973, 536584987, 536585011, 536585029, 536585047, 536585069, 536585167, 536585171, 536585177, 536585201, 536585209, 536585221, 536585233, 536585267, 536585311, 536585317, 536585333, 536585339, 536585351, 536585369, 536585383, 536585389, 536585407, 536585447, 536585531, 536585537, 536585591, 536585611, 536585639, 536585641, 536585657, 536585663, 536585677, 536585689, 536585711, 536585713, 536585723, 536585743, 536585747, 536585759, 536585771, 536585779, 536585801, 536585849, 536585857, 536585873, 536585893, 536585921, 536585923, 536585941, 536585947, 536585957, 536585999, 536586007, 536586023, 536586031, 536586077, 536586097, 536586107, 536586109, 536586139, 536586143, 536586191, 536586203, 536586221, 536586301, 536586313, 536586329, 536586359, 536586361, 536586367, 536586371, 536586373, 536586377, 536586403, 536586473, 536586529, 536586541, 536586553, 536586559, 536586563, 536586569, 536586601, 536586653, 536586707, 536586731, 536586737, 536586763, 536586767, 536586779, 536586821, 536586829, 536586857, 536586863, 536586877, 536586977, 536586991, 536587001, 536587003, 536587013, 536587021, 536587069, 536587081, 536587111, 536587169, 536587193, 536587229, 536587231, 536587237, 536587243, 536587279, 536587301, 536587307, 536587313, 536587349, 536587369, 536587421, 536587433, 536587483, 536587487, 536587501, 536587511, 536587547, 536587553, 536587561, 536587567, 536587577, 536587589, 536587663, 536587679, 536587691, 536587697, 536587703, 536587739, 536587747, 536587771, 536587789, 536587817, 536587819, 536587837, 536587871, 536587879, 536587937, 536587963, 536587969, 536588011, 536588029, 536588069, 536588089, 536588149, 536588191, 536588203, 536588219, 536588249, 536588263, 536588267, 536588281, 536588293, 536588317, 536588341, 536588347, 536588369, 536588407, 536588441, 536588453, 536588489, 536588509, 536588567, 536588573, 536588627, 536588681, 536588683, 536588693, 536588719, 536588807, 536588809, 536588813, 536588821, 536588839, 536588849, 536588881, 536588887, 536588891, 536588929, 536588933, 536588939, 536588947, 536588971, 536588977, 536588993, 536588999, 536589019, 536589023, 536589041, 536589047, 536589049, 536589061, 536589073, 536589077, 536589113, 536589143, 536589187, 536589197, 536589211, 536589259, 536589269, 536589289, 536589307, 536589311, 536589329, 536589373, 536589401, 536589413, 536589421, 536589461, 536589463, 536589491, 536589497, 536589527, 536589539, 536589541, 536589551, 536589589, 536589593, 536589607, 536589617, 536589619, 536589629, 536589631, 536589707, 536589731, 536589737, 536589743, 536589787, 536589797, 536589817, 536589829, 536589847, 536589863, 536589869, 536589917, 536589923, 536589961, 536589971, 536589973, 536590007, 536590049, 536590051, 536590063, 536590079, 536590081, 536590123, 536590147, 536590189, 536590213, 536590217, 536590231, 536590283, 536590297, 536590319, 536590321, 536590349, 536590423, 536590433, 536590447, 536590463, 536590489, 536590547, 536590553, 536590559, 536590577, 536590583, 536590589, 536590591, 536590619, 536590633, 536590643, 536590693, 536590699, 536590721, 536590751, 536590753, 536590763, 536590787, 536590793, 536590829, 536590841, 536590849, 536590861, 536590867, 536590883, 536590927, 536590931, 536590979, 536590987, 536591021, 536591039, 536591047, 536591053, 536591087, 536591189, 536591191, 536591221, 536591227, 536591243, 536591249, 536591257, 536591261, 536591267, 536591269, 536591299, 536591309, 536591317, 536591323, 536591347, 536591351, 536591387, 536591399, 536591401, 536591423, 536591479, 536591509, 536591533, 536591579, 536591593, 536591609, 536591647, 536591651, 536591707, 536591729, 536591773, 536591813, 536591819, 536591827, 536591879, 536591933, 536591941, 536591953, 536591963, 536592013, 536592031, 536592071, 536592103, 536592107, 536592149, 536592179, 536592181, 536592187, 536592211, 536592223, 536592239, 536592257, 536592269, 536592271, 536592283, 536592293, 536592317, 536592337, 536592341, 536592401, 536592431, 536592439, 536592443, 536592449, 536592451, 536592487, 536592493, 536592521, 536592527, 536592541, 536592587, 536592601, 536592629, 536592647, 536592649, 536592673, 536592677, 536592697, 536592703, 536592731, 536592739, 536592751, 536592757, 536592767, 536592779, 536592799, 536592809, 536592821, 536592839, 536592863, 536592893, 536592911, 536592923, 536592941, 536592949, 536592971, 536592989, 536593019, 536593033, 536593051, 536593063, 536593069, 536593093, 536593121, 536593139, 536593171, 536593217, 536593223, 536593241, 536593249, 536593283, 536593297, 536593301, 536593303, 536593319, 536593333, 536593349, 536593403, 536593411, 536593429, 536593441, 536593451, 536593469, 536593481, 536593483, 536593493, 536593579, 536593591, 536593619, 536593643, 536593667, 536593679, 536593693, 536593711, 536593777, 536593781, 536593807, 536593817, 536593819, 536593823, 536593843, 536593859, 536593891, 536593901, 536593907, 536593909, 536593913, 536593949, 536593961, 536593963, 536593969, 536593987, 536593997, 536593999, 536594027, 536594057, 536594077, 536594099, 536594111, 536594153, 536594189, 536594243, 536594249, 536594251, 536594263, 536594269, 536594281, 536594287, 536594293, 536594297, 536594299, 536594309, 536594323, 536594327, 536594381, 536594389, 536594423, 536594437, 536594467, 536594473, 536594479, 536594483, 536594501, 536594521, 536594537, 536594563, 536594567, 536594659, 536594687, 536594689, 536594693, 536594699, 536594711, 536594731, 536594741, 536594753, 536594771, 536594777, 536594797, 536594803, 536594819, 536594833, 536594879, 536594909, 536594951, 536594957, 536594963, 536594983, 536595011, 536595019, 536595043, 536595061, 536595109, 536595121, 536595139, 536595179, 536595181, 536595203, 536595247, 536595251, 536595253, 536595271, 536595299, 536595307, 536595347, 536595377, 536595379, 536595403, 536595421, 536595443, 536595457, 536595469, 536595503, 536595517, 536595533, 536595541, 536595557, 536595623, 536595707, 536595713, 536595721, 536595743, 536595767, 536595791, 536595799, 536595809, 536595811, 536595817, 536595841, 536595877, 536595893, 536595923, 536595937, 536595953, 536596031, 536596033, 536596051, 536596057, 536596111, 536596117, 536596127, 536596129, 536596169, 536596189, 536596201, 536596231, 536596241, 536596253, 536596261, 536596273, 536596297, 536596301, 536596303, 536596339, 536596343, 536596369, 536596373, 536596387, 536596399, 536596409, 536596429, 536596439, 536596457, 536596471, 536596481, 536596493, 536596507, 536596513, 536596579, 536596589, 536596591, 536596637, 536596661, 536596703, 536596777, 536596783, 536596787, 536596811, 536596813, 536596817, 536596847, 536596867, 536596883, 536596927, 536596943, 536596967, 536596981, 536597021, 536597029, 536597057, 536597077, 536597093, 536597099, 536597101, 536597123, 536597137, 536597207, 536597209, 536597249, 536597293, 536597311, 536597323, 536597329, 536597357, 536597359, 536597363, 536597393, 536597417, 536597437, 536597491, 536597533, 536597561, 536597587, 536597591, 536597603, 536597641, 536597657, 536597683, 536597689, 536597767, 536597773, 536597777, 536597801, 536597807, 536597813, 536597819, 536597833, 536597837, 536597839, 536597851, 536597857, 536597863, 536597891, 536597927, 536597947, 536597969, 536597993, 536598001, 536598011, 536598059, 536598061, 536598077, 536598089, 536598103, 536598137, 536598143, 536598163, 536598169, 536598187, 536598193, 536598197, 536598199, 536598229, 536598233, 536598287, 536598299, 536598317, 536598329, 536598331, 536598343, 536598347, 536598367, 536598373, 536598409, 536598427, 536598431, 536598481, 536598493, 536598497, 536598509, 536598527, 536598541, 536598613, 536598619, 536598641, 536598661, 536598707, 536598709, 536598719, 536598721, 536598739, 536598743, 536598757, 536598773, 536598793, 536598841, 536598877, 536598899, 536598911, 536598917, 536598941, 536598967, 536598971, 536598973, 536598991, 536599013, 536599051, 536599061, 536599069, 536599073, 536599109, 536599157, 536599201, 536599289, 536599309, 536599313, 536599319, 536599331, 536599337, 536599351, 536599369, 536599379, 536599381, 536599397, 536599403, 536599417, 536599439, 536599471, 536599477, 536599487, 536599519, 536599523, 536599549, 536599559, 536599561, 536599571, 536599579, 536599603, 536599607, 536599627, 536599639, 536599643, 536599667, 536599669, 536599703, 536599727, 536599733, 536599751, 536599831, 536599871, 536599927, 536599939, 536599961, 536599969, 536599991, 536599997, 536600017, 536600039, 536600089, 536600101, 536600123, 536600161, 536600167, 536600177, 536600201, 536600209, 536600243, 536600377, 536600423, 536600429, 536600431, 536600437, 536600447, 536600459, 536600473, 536600479, 536600503, 536600539, 536600573, 536600611, 536600621, 536600633, 536600653, 536600681, 536600689, 536600737, 536600749, 536600761, 536600797, 536600803, 536600807, 536600821, 536600839, 536600843, 536600849, 536600863, 536600941, 536600951, 536600959, 536600963, 536600969, 536601029, 536601049, 536601067, 536601113, 536601119, 536601133, 536601161, 536601217, 536601313, 536601341, 536601347, 536601361, 536601383, 536601407, 536601419, 536601421, 536601427, 536601449, 536601467, 536601473, 536601479, 536601487, 536601497, 536601503, 536601509, 536601511, 536601547, 536601551, 536601607, 536601613, 536601623, 536601641, 536601649, 536601671, 536601673, 536601701, 536601739, 536601817, 536601827, 536601833, 536601851, 536601853, 536601869, 536601887, 536601893, 536601911, 536601917, 536601929, 536601977, 536601997, 536602019, 536602021, 536602037, 536602039, 536602043, 536602057, 536602091, 536602141, 536602153, 536602159, 536602169, 536602201, 536602247, 536602277, 536602291, 536602303, 536602307, 536602321, 536602373, 536602393, 536602403, 536602439, 536602459, 536602481, 536602511, 536602513, 536602567, 536602621, 536602667, 536602669, 536602691, 536602709, 536602721, 536602757, 536602771, 536602819, 536602853, 536602873, 536602879, 536602907, 536602919, 536602931, 536602951, 536602973, 536602991, 536602993, 536602999, 536603003, 536603027, 536603029, 536603047, 536603057, 536603059, 536603069, 536603077, 536603099, 536603101, 536603167, 536603191, 536603209, 536603219, 536603233, 536603237, 536603251, 536603311, 536603329, 536603387, 536603393, 536603399, 536603401, 536603411, 536603413, 536603437, 536603461, 536603467, 536603479, 536603503, 536603527, 536603533, 536603537, 536603581, 536603633, 536603647, 536603677, 536603687, 536603701, 536603723, 536603773, 536603779, 536603797, 536603807, 536603813, 536603819, 536603857, 536603867, 536603887, 536603917, 536603989, 536603993, 536604001, 536604041, 536604043, 536604059, 536604071, 536604091, 536604109, 536604113, 536604149, 536604161, 536604193, 536604199, 536604209, 536604223, 536604227, 536604241, 536604253, 536604287, 536604301, 536604317, 536604323, 536604347, 536604361, 536604391, 536604401, 536604413, 536604437, 536604443, 536604449, 536604463, 536604511, 536604521, 536604529, 536604533, 536604583, 536604613, 536604641, 536604647, 536604659, 536604667, 536604683, 536604721, 536604737, 536604767, 536604769, 536604773, 536604791, 536604811, 536604829, 536604833, 536604841, 536604851, 536604857, 536604863, 536604889, 536604911, 536604917, 536604919, 536604923, 536604961, 536604997, 536605001, 536605031, 536605079, 536605093, 536605129, 536605169, 536605207, 536605259, 536605301, 536605313, 536605327, 536605331, 536605343, 536605351, 536605379, 536605393, 536605403, 536605409, 536605411, 536605423, 536605453, 536605477, 536605481, 536605501, 536605547, 536605577, 536605579, 536605591, 536605609, 536605631, 536605673, 536605679, 536605681, 536605687, 536605711, 536605723, 536605759, 536605777, 536605787, 536605789, 536605793, 536605807, 536605819, 536605889, 536605891, 536605913, 536605919, 536605957, 536605967, 536606011, 536606017, 536606023, 536606041, 536606089, 536606107, 536606131, 536606141, 536606167, 536606197, 536606209, 536606251, 536606267, 536606297, 536606347, 536606359, 536606381, 536606407, 536606423, 536606431, 536606437, 536606443, 536606507, 536606519, 536606533, 536606561, 536606563, 536606579, 536606591, 536606611, 536606627, 536606639, 536606641, 536606677, 536606701, 536606713, 536606723, 536606731, 536606747, 536606779, 536606783, 536606801, 536606803, 536606827, 536606831, 536606843, 536606881, 536606897, 536606909, 536606969, 536606977, 536607011, 536607017, 536607059, 536607061, 536607067, 536607079, 536607107, 536607119, 536607157, 536607163, 536607167, 536607173, 536607187, 536607199, 536607283, 536607287, 536607299, 536607307, 536607311, 536607347, 536607361, 536607377, 536607391, 536607403, 536607439, 536607469, 536607473, 536607493, 536607497, 536607509, 536607527, 536607541, 536607553, 536607581, 536607583, 536607607, 536607637, 536607661, 536607683, 536607689, 536607727, 536607739, 536607761, 536607769, 536607791, 536607803, 536607809, 536607817, 536607901, 536607931, 536607943, 536607947, 536607983, 536608021, 536608057, 536608069, 536608157, 536608183, 536608207, 536608231, 536608243, 536608271, 536608283, 536608291, 536608301, 536608321, 536608333, 536608337, 536608343, 536608367, 536608379, 536608381, 536608421, 536608433, 536608439, 536608441, 536608453, 536608483, 536608487, 536608493, 536608511, 536608571, 536608603, 536608609, 536608613, 536608649, 536608651, 536608687, 536608711, 536608727, 536608733, 536608763, 536608769, 536608783, 536608801, 536608819, 536608847, 536608871, 536608889, 536608907, 536608931, 536608957, 536608973, 536608979, 536608987, 536608999, 536609023, 536609053, 536609093, 536609111, 536609149, 536609167, 536609197, 536609209, 536609237, 536609273, 536609299, 536609321, 536609327, 536609347, 536609351, 536609371, 536609377, 536609383, 536609393, 536609401, 536609431, 536609449, 536609453, 536609459, 536609467, 536609477, 536609501, 536609519, 536609531, 536609611, 536609621, 536609627, 536609651, 536609677, 536609699, 536609729, 536609753, 536609797, 536609807, 536609813, 536609819, 536609839, 536609963, 536609999, 536610007, 536610037, 536610043, 536610047, 536610097, 536610101, 536610163, 536610187, 536610241, 536610247, 536610259, 536610289, 536610307, 536610323, 536610343, 536610397, 536610409, 536610413, 536610439, 536610443, 536610449, 536610511, 536610523, 536610587, 536610611, 536610629, 536610647, 536610649, 536610689, 536610691, 536610709, 536610727, 536610731, 536610761, 536610793, 536610799, 536610817, 536610857, 536610859, 536610917, 536610923, 536610929, 536610979, 536610989, 536611003, 536611007, 536611013, 536611067, 536611073, 536611093, 536611121, 536611139, 536611181, 536611193, 536611219, 536611223, 536611249, 536611277, 536611297, 536611303, 536611337, 536611343, 536611363, 536611373, 536611417, 536611421, 536611441, 536611451, 536611463, 536611489, 536611499, 536611507, 536611513, 536611531, 536611541, 536611553, 536611561, 536611583, 536611589, 536611609, 536611633, 536611639, 536611651, 536611657, 536611709, 536611717, 536611721, 536611739, 536611753, 536611759, 536611771, 536611841, 536611847, 536611861, 536611897, 536611939, 536611961, 536611963, 536611979, 536611991, 536611993, 536612029, 536612033, 536612039, 536612047, 536612081, 536612099, 536612101, 536612159, 536612171, 536612183, 536612233, 536612243, 536612267, 536612273, 536612291, 536612299, 536612309, 536612311, 536612389, 536612393, 536612411, 536612413, 536612467, 536612501, 536612539, 536612579, 536612639, 536612641, 536612647, 536612653, 536612731, 536612873, 536612893, 536612911, 536612929, 536612933, 536613019, 536613061, 536613097, 536613139, 536613191, 536613199, 536613221, 536613223, 536613247, 536613263, 536613269, 536613271, 536613373, 536613487, 536613521, 536613547, 536613557, 536613601, 536613607, 536613611, 536613613, 536613631, 536613643, 536613647, 536613659, 536613691, 536613697, 536613703, 536613731, 536613743, 536613799, 536613853, 536613871, 536613877, 536613893, 536613901, 536613929, 536613947, 536613949, 536613977, 536613983, 536614003, 536614031, 536614049, 536614073, 536614079, 536614103, 536614147, 536614171, 536614193, 536614217, 536614223, 536614229, 536614259, 536614279, 536614291, 536614297, 536614301, 536614307, 536614327, 536614349, 536614361, 536614387, 536614423, 536614471, 536614493, 536614627, 536614669, 536614693, 536614703, 536614711, 536614721, 536614733, 536614763, 536614781, 536614783, 536614787, 536614807, 536614823, 536614831, 536614849, 536614861, 536614913, 536614937, 536614999, 536615021, 536615039, 536615063, 536615069, 536615099, 536615113, 536615117, 536615137, 536615201, 536615221, 536615227, 536615263, 536615267, 536615269, 536615273, 536615279, 536615281, 536615291, 536615293, 536615297, 536615311, 536615357, 536615371, 536615383, 536615413, 536615419, 536615459, 536615473, 536615509, 536615531, 536615539, 536615567, 536615579, 536615581, 536615617, 536615633, 536615641, 536615671, 536615707, 536615759, 536615777, 536615789, 536615801, 536615813, 536615819, 536615843, 536615851, 536615861, 536615927, 536615939, 536615951, 536616007, 536616019, 536616097, 536616103, 536616121, 536616137, 536616139, 536616187, 536616191, 536616209, 536616229, 536616239, 536616247, 536616251, 536616263, 536616281, 536616287, 536616349, 536616359, 536616391, 536616397, 536616413, 536616433, 536616461, 536616469, 536616481, 536616491, 536616499, 536616523, 536616527, 536616539, 536616557, 536616571, 536616583, 536616593, 536616607, 536616629, 536616637, 536616643, 536616653, 536616709, 536616767, 536616779, 536616797, 536616811, 536616881, 536616893, 536616911, 536616929, 536616931, 536616937, 536616947, 536616961, 536616973, 536616991, 536617013, 536617033, 536617063, 536617069, 536617079, 536617097, 536617111, 536617129, 536617139, 536617153, 536617157, 536617177, 536617181, 536617199, 536617229, 536617241, 536617261, 536617267, 536617297, 536617309, 536617313, 536617321, 536617349, 536617381, 536617387, 536617429, 536617441, 536617447, 536617453, 536617457, 536617507, 536617547, 536617561, 536617591, 536617607, 536617619, 536617621, 536617651, 536617663, 536617681, 536617687, 536617723, 536617751, 536617777, 536617811, 536617819, 536617859, 536617867, 536617891, 536617897, 536617997, 536617999, 536618011, 536618023, 536618041, 536618077, 536618081, 536618087, 536618111, 536618123, 536618149, 536618167, 536618179, 536618183, 536618207, 536618231, 536618237, 536618279, 536618287, 536618293, 536618297, 536618321, 536618333, 536618419, 536618443, 536618471, 536618473, 536618479, 536618491, 536618507, 536618531, 536618557, 536618603, 536618623, 536618669, 536618671, 536618689, 536618699, 536618777, 536618791, 536618833, 536618857, 536618867, 536618903, 536618933, 536618941, 536618981, 536618989, 536619001, 536619007, 536619019, 536619023, 536619037, 536619047, 536619053, 536619067, 536619073, 536619079, 536619089, 536619133, 536619143, 536619157, 536619173, 536619211, 536619217, 536619227, 536619247, 536619253, 536619283, 536619287, 536619289, 536619367, 536619383, 536619401, 536619431, 536619449, 536619469, 536619481, 536619493, 536619511, 536619533, 536619571, 536619607, 536619613, 536619667, 536619673, 536619697, 536619701, 536619731, 536619749, 536619763, 536619781, 536619791, 536619823, 536619829, 536619851, 536619883, 536619899, 536619901, 536619929, 536619949, 536619953, 536619959, 536619997, 536620027, 536620037, 536620043, 536620069, 536620127, 536620129, 536620141, 536620157, 536620159, 536620169, 536620187, 536620207, 536620229, 536620289, 536620307, 536620309, 536620313, 536620333, 536620367, 536620387, 536620411, 536620457, 536620499, 536620501, 536620523, 536620529, 536620531, 536620537, 536620543, 536620559, 536620577, 536620597, 536620619, 536620639, 536620649, 536620687, 536620697, 536620709, 536620723, 536620741, 536620771, 536620787, 536620789, 536620801, 536620811, 536620829, 536620853, 536620891, 536620913, 536620927, 536620937, 536620991, 536620999, 536621021, 536621051, 536621081, 536621083, 536621089, 536621093, 536621147, 536621149, 536621159, 536621171, 536621177, 536621207, 536621219, 536621251, 536621263, 536621287, 536621329, 536621333, 536621339, 536621341, 536621357, 536621359, 536621399, 536621413, 536621443, 536621509, 536621521, 536621537, 536621543, 536621551, 536621573, 536621581, 536621587, 536621611, 536621629, 536621647, 536621689, 536621699, 536621707, 536621753, 536621791, 536621797, 536621801, 536621843, 536621849, 536621867, 536621909, 536621929, 536621951, 536621977, 536622041, 536622043, 536622089, 536622101, 536622133, 536622143, 536622167, 536622209, 536622239, 536622253, 536622257, 536622259, 536622277, 536622313, 536622319, 536622329, 536622337, 536622349, 536622353, 536622379, 536622397, 536622419, 536622421, 536622439, 536622487, 536622503, 536622511, 536622539, 536622553, 536622571, 536622613, 536622623, 536622659, 536622677, 536622701, 536622707, 536622739, 536622787, 536622809, 536622817, 536622839, 536622851, 536622857, 536622907, 536622943, 536622953, 536622967, 536623001, 536623013, 536623049, 536623057, 536623067, 536623069, 536623081, 536623093, 536623117, 536623121, 536623141, 536623169, 536623249, 536623259, 536623397, 536623421, 536623427, 536623433, 536623471, 536623481, 536623499, 536623501, 536623519, 536623523, 536623541, 536623559, 536623573, 536623579, 536623589, 536623597, 536623601, 536623613, 536623699, 536623723, 536623727, 536623729, 536623739, 536623753, 536623757, 536623777, 536623811, 536623847, 536623849, 536623883, 536623891, 536623907, 536623909, 536623963, 536623979, 536623991, 536623999, 536624003, 536624069, 536624093, 536624119, 536624171, 536624183, 536624191, 536624213, 536624237, 536624251, 536624267, 536624287, 536624303, 536624321, 536624351, 536624371, 536624377, 536624393, 536624401, 536624423, 536624437, 536624449, 536624453, 536624471, 536624513, 536624527, 536624531, 536624537, 536624551, 536624573, 536624593, 536624597, 536624609, 536624617, 536624659, 536624677, 536624701, 536624713, 536624731, 536624749, 536624783, 536624791, 536624827, 536624861, 536624951, 536624969, 536624981, 536624987, 536624989, 536625013, 536625059, 536625073, 536625107, 536625149, 536625161, 536625163, 536625169, 536625181, 536625209, 536625217, 536625241, 536625253, 536625293, 536625317, 536625347, 536625359, 536625373, 536625377, 536625431, 536625457, 536625487, 536625491, 536625517, 536625521, 536625527, 536625559, 536625577, 536625611, 536625613, 536625619, 536625623, 536625629, 536625641, 536625647, 536625653, 536625659, 536625697, 536625707, 536625731, 536625737, 536625781, 536625821, 536625823, 536625863, 536625883, 536625899, 536625923, 536625977, 536625979, 536625997, 536626009, 536626021, 536626037, 536626049, 536626061, 536626067, 536626093, 536626109, 536626127, 536626141, 536626147, 536626169, 536626171, 536626183, 536626201, 536626243, 536626273, 536626351, 536626357, 536626361, 536626393, 536626421, 536626423, 536626439, 536626477, 536626529, 536626553, 536626561, 536626579, 536626583, 536626603, 536626609, 536626613, 536626619, 536626637, 536626661, 536626679, 536626703, 536626711, 536626751, 536626757, 536626763, 536626781, 536626787, 536626801, 536626829, 536626841, 536626843, 536626847, 536626877, 536626891, 536626903, 536626907, 536626949, 536626969, 536626973, 536626997, 536627011, 536627023, 536627071, 536627087, 536627093, 536627111, 536627129, 536627131, 536627137, 536627141, 536627167, 536627177, 536627209, 536627213, 536627233, 536627251, 536627263, 536627303, 536627327, 536627353, 536627359, 536627381, 536627387, 536627407, 536627411, 536627419, 536627447, 536627471, 536627473, 536627477, 536627503, 536627549, 536627551, 536627591, 536627603, 536627617, 536627647, 536627657, 536627677, 536627699, 536627719, 536627731, 536627753, 536627759, 536627771, 536627779, 536627783, 536627827, 536627843, 536627851, 536627863, 536627879, 536627911, 536627921, 536627941, 536627957, 536627969, 536627989, 536628031, 536628047, 536628109, 536628121, 536628133, 536628143, 536628161, 536628173, 536628199, 536628221, 536628289, 536628311, 536628331, 536628349, 536628359, 536628397, 536628401, 536628413, 536628431, 536628461, 536628487, 536628503, 536628523, 536628539, 536628559, 536628601, 536628607, 536628643, 536628667, 536628671, 536628683, 536628689, 536628727, 536628733, 536628737, 536628739, 536628779, 536628809, 536628811, 536628877, 536628887, 536628889, 536628923, 536628931, 536628959, 536629007, 536629061, 536629087, 536629111, 536629133, 536629183, 536629193, 536629199, 536629231, 536629243, 536629273, 536629277, 536629309, 536629319, 536629339, 536629349, 536629391, 536629393, 536629433, 536629441, 536629451, 536629459, 536629469, 536629477, 536629481, 536629487, 536629517, 536629519, 536629529, 536629657, 536629679, 536629703, 536629757, 536629763, 536629811, 536629937, 536629979, 536630009, 536630011, 536630027, 536630111, 536630147, 536630179, 536630183, 536630209, 536630231, 536630249, 536630291, 536630317, 536630321, 536630363, 536630371, 536630383, 536630387, 536630389, 536630401, 536630407, 536630417, 536630467, 536630531, 536630533, 536630569, 536630579, 536630581, 536630599, 536630609, 536630617, 536630629, 536630639, 536630651, 536630659, 536630663, 536630681, 536630711, 536630713, 536630729, 536630741, 536630747, 536630749, 536630797, 536630807, 536630821, 536630827, 536630839, 536630873, 536630923, 536630947, 536630971, 536630981, 536630999, 536631023, 536631031, 536631071, 536631131, 536631143, 536631157, 536631169, 536631187, 536631191, 536631209, 536631211, 536631217, 536631229, 536631253, 536631259, 536631343, 536631379, 536631391, 536631479, 536631509, 536631517, 536631533, 536631581, 536631587, 536631593, 536631637, 536631661, 536631691, 536631709, 536631713, 536631749, 536631827, 536631829, 536631841, 536631899, 536631913, 536631941, 536631967, 536631973, 536631989, 536632003, 536632007, 536632027, 536632043, 536632051, 536632073, 536632079, 536632091, 536632093, 536632097, 536632099, 536632139, 536632147, 536632177, 536632193, 536632223, 536632237, 536632247, 536632249, 536632253, 536632309, 536632321, 536632331, 536632337, 536632357, 536632361, 536632363, 536632373, 536632379, 536632391, 536632399, 536632427, 536632429, 536632441, 536632457, 536632471, 536632487, 536632519, 536632529, 536632541, 536632549, 536632609, 536632627, 536632631, 536632633, 536632651, 536632667, 536632721, 536632739, 536632763, 536632769, 536632813, 536632823, 536632843, 536632919, 536632933, 536632937, 536632939, 536632951, 536632961, 536632997, 536633047, 536633057, 536633059, 536633063, 536633087, 536633113, 536633117, 536633129, 536633137, 536633159, 536633183, 536633189, 536633191, 536633213, 536633233, 536633239, 536633257, 536633267, 536633303, 536633329, 536633369, 536633381, 536633413, 536633417, 536633423, 536633431, 536633477, 536633527, 536633551, 536633561, 536633563, 536633597, 536633633, 536633659, 536633683, 536633729, 536633737, 536633813, 536633819, 536633821, 536633837, 536633863, 536633869, 536633873, 536633941, 536633983, 536633987, 536634001, 536634013, 536634029, 536634037, 536634041, 536634127, 536634143, 536634151, 536634179, 536634187, 536634193, 536634209, 536634227, 536634239, 536634269, 536634283, 536634337, 536634341, 536634349, 536634353, 536634389, 536634403, 536634407, 536634433, 536634443, 536634451, 536634463, 536634467, 536634493, 536634541, 536634547, 536634599, 536634611, 536634701, 536634719, 536634731, 536634799, 536634809, 536634851, 536634907, 536634929, 536634977, 536634979, 536634983, 536634991, 536635003, 536635007, 536635027, 536635063, 536635091, 536635097, 536635109, 536635129, 536635139, 536635157, 536635171, 536635181, 536635193, 536635207, 536635213, 536635223, 536635247, 536635249, 536635279, 536635301, 536635349, 536635357, 536635367, 536635381, 536635397, 536635433, 536635453, 536635469, 536635499, 536635501, 536635529, 536635573, 536635591, 536635643, 536635681, 536635733, 536635751, 536635783, 536635817, 536635873, 536635877, 536635903, 536635909, 536635933, 536635949, 536635951, 536635961, 536635969, 536635973, 536635993, 536635997, 536635999, 536636029, 536636033, 536636063, 536636101, 536636117, 536636119, 536636131, 536636141, 536636143, 536636153, 536636159, 536636231, 536636279, 536636281, 536636291, 536636293, 536636311, 536636339, 536636357, 536636369, 536636377, 536636407, 536636449, 536636461, 536636473, 536636521, 536636537, 536636549, 536636557, 536636563, 536636591, 536636593, 536636599, 536636609, 536636623, 536636663, 536636687, 536636707, 536636719, 536636743, 536636767, 536636777, 536636783, 536636791, 536636827, 536636839, 536636857, 536636873, 536636879, 536636899, 536636911, 536636917, 536636927, 536636941, 536636953, 536636983, 536637019, 536637043, 536637053, 536637067, 536637071, 536637133, 536637163, 536637169, 536637203, 536637217, 536637223, 536637253, 536637263, 536637281, 536637289, 536637293, 536637329, 536637347, 536637379, 536637389, 536637427, 536637443, 536637469, 536637481, 536637499, 536637553, 536637581, 536637593, 536637637, 536637649, 536637671, 536637697, 536637709, 536637713, 536637719, 536637737, 536637797, 536637799, 536637811, 536637821, 536637823, 536637839, 536637877, 536637961, 536637989, 536637991, 536638009, 536638019, 536638027, 536638051, 536638079, 536638153, 536638163, 536638169, 536638183, 536638189, 536638229, 536638247, 536638279, 536638307, 536638321, 536638331, 536638363, 536638379, 536638391, 536638397, 536638477, 536638481, 536638493, 536638499, 536638511, 536638513, 536638523, 536638537, 536638579, 536638589, 536638601, 536638637, 536638657, 536638673, 536638693, 536638703, 536638789, 536638801, 536638811, 536638819, 536638853, 536638871, 536638877, 536638901, 536638909, 536638913, 536638951, 536638981, 536639003, 536639023, 536639039, 536639041, 536639093, 536639099, 536639141, 536639149, 536639177, 536639219, 536639237, 536639251, 536639293, 536639297, 536639321, 536639329, 536639339, 536639359, 536639399, 536639417, 536639429, 536639437, 536639449, 536639483, 536639489, 536639491, 536639533, 536639557, 536639569, 536639581, 536639617, 536639627, 536639639, 536639641, 536639669, 536639671, 536639689, 536639713, 536639723, 536639759, 536639767, 536639773, 536639813, 536639837, 536639839, 536639879, 536639881, 536639921, 536639927, 536639953, 536639963, 536639981, 536640001, 536640023, 536640029, 536640053, 536640061, 536640073, 536640089, 536640113, 536640179, 536640187, 536640217, 536640233, 536640239, 536640253, 536640263, 536640271, 536640289, 536640329, 536640353, 536640359, 536640373, 536640413, 536640421, 536640437, 536640449, 536640451, 536640457, 536640469, 536640487, 536640491, 536640523, 536640527, 536640551, 536640557, 536640571, 536640589, 536640619, 536640647, 536640653, 536640673, 536640757, 536640773, 536640779, 536640781, 536640799, 536640829, 536640901, 536640943, 536640967, 536641009, 536641019, 536641069, 536641097, 536641099, 536641109, 536641139, 536641141, 536641211, 536641213, 536641223, 536641283, 536641291, 536641321, 536641337, 536641349, 536641361, 536641367, 536641379, 536641387, 536641411, 536641459, 536641471, 536641481, 536641519, 536641531, 536641537, 536641597, 536641613, 536641627, 536641649, 536641667, 536641687, 536641691, 536641697, 536641753, 536641759, 536641789, 536641811, 536641841, 536641843, 536641867, 536641877, 536641883, 536641891, 536641913, 536641933, 536641939, 536641967, 536641999, 536642011, 536642017, 536642033, 536642081, 536642083, 536642087, 536642089, 536642131, 536642159, 536642167, 536642173, 536642237, 536642243, 536642269, 536642299, 536642377, 536642387, 536642401, 536642411, 536642453, 536642459, 536642473, 536642489, 536642501, 536642521, 536642539, 536642551, 536642567, 536642573, 536642591, 536642609, 536642611, 536642633, 536642641, 536642657, 536642671, 536642683, 536642747, 536642753, 536642773, 536642789, 536642807, 536642833, 536642863, 536642867, 536642917, 536642947, 536642957, 536642993, 536643001, 536643007, 536643013, 536643017, 536643043, 536643067, 536643071, 536643083, 536643089, 536643109, 536643157, 536643161, 536643193, 536643197, 536643229, 536643241, 536643257, 536643259, 536643269, 536643293, 536643323, 536643329, 536643361, 536643377, 536643379, 536643431, 536643469, 536643491, 536643529, 536643551, 536643553, 536643571, 536643577, 536643587, 536643589, 536643599, 536643623, 536643647, 536643739, 536643749, 536643769, 536643799, 536643829, 536643871, 536643931, 536643949, 536643953, 536643959, 536643997, 536644001, 536644021, 536644033, 536644051, 536644063, 536644103, 536644109, 536644139, 536644181, 536644247, 536644271, 536644301, 536644307, 536644309, 536644331, 536644363, 536644397, 536644439, 536644477, 536644517, 536644519, 536644553, 536644567, 536644597, 536644609, 536644621, 536644631, 536644639, 536644657, 536644679, 536644727, 536644733, 536644753, 536644811, 536644819, 536644841, 536644847, 536644853, 536644861, 536644891, 536644897, 536644907, 536644921, 536644931, 536645071, 536645093, 536645099, 536645113, 536645173, 536645189, 536645191, 536645209, 536645227, 536645237, 536645257, 536645287, 536645293, 536645321, 536645323, 536645357, 536645363, 536645437, 536645441, 536645449, 536645467, 536645471, 536645497, 536645507, 536645513, 536645531, 536645539, 536645567, 536645569, 536645573, 536645621, 536645639, 536645653, 536645663, 536645717, 536645741, 536645773, 536645777, 536645797, 536645801, 536645819, 536645831, 536645839, 536645873, 536645909, 536645969, 536645971, 536646031, 536646043, 536646079, 536646107, 536646109, 536646137, 536646161, 536646163, 536646167, 536646197, 536646221, 536646263, 536646269, 536646277, 536646323, 536646413, 536646427, 536646457, 536646491, 536646521, 536646541, 536646547, 536646563, 536646577, 536646629, 536646641, 536646647, 536646679, 536646703, 536646739, 536646743, 536646749, 536646757, 536646793, 536646809, 536646821, 536646823, 536646839, 536646857, 536646863, 536646883, 536646899, 536646911, 536646917, 536646941, 536646953, 536646959, 536646967, 536646977, 536646989, 536646997, 536647049, 536647091, 536647093, 536647121, 536647147, 536647183, 536647187, 536647213, 536647219, 536647249, 536647253, 536647259, 536647261, 536647271, 536647273, 536647277, 536647289, 536647301, 536647351, 536647361, 536647367, 536647379, 536647387, 536647399, 536647403, 536647429, 536647451, 536647459, 536647481, 536647487, 536647511, 536647513, 536647567, 536647583, 536647591, 536647627, 536647637, 536647663, 536647679, 536647681, 536647717, 536647733, 536647751, 536647763, 536647801, 536647829, 536647831, 536647841, 536647847, 536647873, 536647879, 536647883, 536647901, 536647999, 536648009, 536648023, 536648051, 536648107, 536648131, 536648149, 536648153, 536648173, 536648183, 536648191, 536648201, 536648239, 536648243, 536648251, 536648257, 536648261, 536648269, 536648297, 536648309, 536648353, 536648363, 536648377, 536648381, 536648389, 536648417, 536648473, 536648507, 536648513, 536648531, 536648543, 536648569, 536648579, 536648599, 536648611, 536648633, 536648641, 536648647, 536648677, 536648687, 536648753, 536648771, 536648779, 536648789, 536648807, 536648821, 536648873, 536648899, 536648921, 536648929, 536648953, 536648963, 536648969, 536648993, 536649007, 536649019, 536649037, 536649049, 536649067, 536649097, 536649101, 536649107, 536649137, 536649181, 536649187, 536649203, 536649227, 536649283, 536649313, 536649329, 536649343, 536649349, 536649361, 536649371, 536649403, 536649439, 536649457, 536649497, 536649511, 536649563, 536649569, 536649571, 536649577, 536649583, 536649599, 536649601, 536649637, 536649643, 536649653, 536649677, 536649683, 536649689, 536649703, 536649709, 536649721, 536649749, 536649793, 536649809, 536649811, 536649853, 536649859, 536649877, 536649913, 536649917, 536649929, 536649983, 536650013, 536650043, 536650063, 536650091, 536650111, 536650141, 536650199, 536650201, 536650223, 536650243, 536650333, 536650349, 536650357, 536650381, 536650403, 536650417, 536650451, 536650483, 536650507, 536650519, 536650523, 536650529, 536650537, 536650547, 536650601, 536650603, 536650613, 536650633, 536650661, 536650729, 536650753, 536650759, 536650817, 536650837, 536650867, 536650897, 536650913, 536650921, 536650943, 536650949, 536650999, 536651021, 536651033, 536651069, 536651081, 536651083, 536651113, 536651147, 536651153, 536651161, 536651179, 536651201, 536651207, 536651233, 536651267, 536651287, 536651347, 536651377, 536651383, 536651389, 536651407, 536651413, 536651417, 536651449, 536651471, 536651477, 536651497, 536651513, 536651537, 536651573, 536651603, 536651611, 536651623, 536651651, 536651671, 536651681, 536651693, 536651701, 536651711, 536651719, 536651729, 536651741, 536651777, 536651779, 536651839, 536651851, 536651923, 536651963, 536651987, 536652001, 536652007, 536652013, 536652043, 536652049, 536652059, 536652071, 536652079, 536652091, 536652097, 536652113, 536652119, 536652143, 536652211, 536652229, 536652247, 536652269, 536652299, 536652313, 536652331, 536652349, 536652383, 536652437, 536652449, 536652461, 536652463, 536652469, 536652497, 536652499, 536652539, 536652541, 536652559, 536652607, 536652661, 536652667, 536652679, 536652703, 536652709, 536652713, 536652737, 536652761, 536652793, 536652817, 536652827, 536652841, 536652877, 536652901, 536652953, 536652971, 536652983, 536652989, 536653021, 536653063, 536653079, 536653099, 536653111, 536653133, 536653147, 536653153, 536653171, 536653189, 536653193, 536653199, 536653259, 536653261, 536653333, 536653339, 536653343, 536653361, 536653409, 536653427, 536653477, 536653483, 536653529, 536653531, 536653561, 536653573, 536653591, 536653609, 536653657, 536653693, 536653699, 536653709, 536653721, 536653723, 536653751, 536653753, 536653759, 536653763, 536653769, 536653771, 536653781, 536653823, 536653829, 536653907, 536653913, 536653919, 536653933, 536653937, 536653939, 536653951, 536653967, 536653969, 536654021, 536654059, 536654087, 536654093, 536654117, 536654137, 536654141, 536654143, 536654161, 536654177, 536654213, 536654219, 536654227, 536654243, 536654269, 536654291, 536654303, 536654323, 536654329, 536654341, 536654353, 536654357, 536654387, 536654399, 536654431, 536654441, 536654467, 536654471, 536654519, 536654527, 536654533, 536654543, 536654551, 536654557, 536654579, 536654581, 536654593, 536654611, 536654647, 536654659, 536654669, 536654719, 536654743, 536654747, 536654761, 536654779, 536654803, 536654809, 536654819, 536654879, 536654887, 536654891, 536654933, 536654971, 536654999, 536655017, 536655061, 536655083, 536655101, 536655103, 536655107, 536655131, 536655139, 536655143, 536655173, 536655181, 536655199, 536655233, 536655241, 536655271, 536655281, 536655293, 536655299, 536655307, 536655311, 536655347, 536655403, 536655409, 536655433, 536655451, 536655463, 536655499, 536655503, 536655533, 536655547, 536655569, 536655593, 536655653, 536655719, 536655737, 536655739, 536655761, 536655773, 536655797, 536655811, 536655827, 536655841, 536655851, 536655887, 536655901, 536655907, 536655913, 536655937, 536655943, 536655961, 536656009, 536656019, 536656031, 536656067, 536656117, 536656139, 536656157, 536656181, 536656201, 536656213, 536656247, 536656259, 536656261, 536656277, 536656279, 536656321, 536656381, 536656403, 536656409, 536656427, 536656433, 536656441, 536656451, 536656487, 536656529, 536656541, 536656583, 536656597, 536656609, 536656619, 536656639, 536656643, 536656649, 536656709, 536656741, 536656759, 536656781, 536656793, 536656807, 536656817, 536656819, 536656823, 536656847, 536656849, 536656871, 536656873, 536656877, 536656921, 536656931, 536656933, 536656937, 536656961, 536656963, 536656973, 536657021, 536657039, 536657041, 536657063, 536657083, 536657087, 536657101, 536657117, 536657123, 536657129, 536657131, 536657179, 536657197, 536657201, 536657269, 536657279, 536657347, 536657371, 536657417, 536657437, 536657449, 536657491, 536657497, 536657503, 536657519, 536657521, 536657543, 536657567, 536657617, 536657623, 536657663, 536657669, 536657699, 536657729, 536657741, 536657749, 536657767, 536657783, 536657791, 536657801, 536657813, 536657837, 536657843, 536657867, 536657881, 536657893, 536657909, 536657911, 536657917, 536657951, 536657969, 536657977, 536657999, 536658043, 536658047, 536658049, 536658151, 536658167, 536658229, 536658233, 536658251, 536658263, 536658281, 536658301, 536658359, 536658373, 536658403, 536658413, 536658433, 536658449, 536658469, 536658481, 536658491, 536658503, 536658527, 536658547, 536658569, 536658571, 536658589, 536658637, 536658641, 536658649, 536658653, 536658713, 536658721, 536658751, 536658757, 536658797, 536658803, 536658817, 536658823, 536658847, 536658937, 536658961, 536659001, 536659033, 536659037, 536659051, 536659061, 536659091, 536659117, 536659129, 536659141, 536659163, 536659169, 536659171, 536659187, 536659223, 536659229, 536659243, 536659267, 536659309, 536659327, 536659337, 536659367, 536659369, 536659379, 536659381, 536659421, 536659477, 536659493, 536659499, 536659531, 536659547, 536659559, 536659567, 536659589, 536659597, 536659601, 536659633, 536659649, 536659661, 536659681, 536659699, 536659741, 536659777, 536659793, 536659847, 536659867, 536659873, 536659901, 536659913, 536659919, 536659967, 536659987, 536659999, 536660009, 536660021, 536660023, 536660039, 536660041, 536660057, 536660071, 536660101, 536660107, 536660119, 536660123, 536660161, 536660171, 536660197, 536660207, 536660221, 536660227, 536660231, 536660261, 536660291, 536660297, 536660317, 536660323, 536660329, 536660353, 536660393, 536660407, 536660413, 536660417, 536660431, 536660447, 536660479, 536660483, 536660489, 536660497, 536660503, 536660549, 536660557, 536660609, 536660629, 536660651, 536660699, 536660713, 536660717, 536660731, 536660753, 536660779, 536660783, 536660857, 536660869, 536660897, 536660903, 536660911, 536660923, 536660959, 536660963, 536661007, 536661031, 536661053, 536661067, 536661079, 536661091, 536661127, 536661131, 536661143, 536661149, 536661157, 536661161, 536661221, 536661241, 536661247, 536661313, 536661331, 536661337, 536661361, 536661373, 536661383, 536661401, 536661421, 536661439, 536661467, 536661473, 536661497, 536661529, 536661539, 536661551, 536661569, 536661607, 536661637, 536661647, 536661659, 536661679, 536661731, 536661761, 536661767, 536661779, 536661799, 536661803, 536661841, 536661857, 536661877, 536661883, 536661929, 536661959, 536661977, 536661989, 536661991, 536662019, 536662039, 536662051, 536662109, 536662123, 536662129, 536662141, 536662177, 536662183, 536662193, 536662223, 536662229, 536662237, 536662261, 536662271, 536662303, 536662333, 536662337, 536662351, 536662363, 536662367, 536662369, 536662387, 536662433, 536662447, 536662463, 536662513, 536662531, 536662549, 536662559, 536662573, 536662583, 536662627, 536662691, 536662729, 536662741, 536662751, 536662769, 536662807, 536662813, 536662829, 536662859, 536662871, 536662891, 536662901, 536662921, 536662927, 536662949, 536662957, 536662963, 536663003, 536663033, 536663053, 536663093, 536663111, 536663129, 536663159, 536663173, 536663201, 536663203, 536663219, 536663261, 536663279, 536663287, 536663291, 536663321, 536663359, 536663363, 536663383, 536663389, 536663411, 536663419, 536663431, 536663441, 536663443, 536663447, 536663453, 536663467, 536663527, 536663539, 536663557, 536663563, 536663573, 536663579, 536663593, 536663597, 536663609, 536663627, 536663663, 536663707, 536663711, 536663717, 536663747, 536663749, 536663839, 536663851, 536663921, 536663923, 536664067, 536664077, 536664091, 536664103, 536664113, 536664119, 536664131, 536664133, 536664179, 536664217, 536664229, 536664239, 536664257, 536664259, 536664263, 536664307, 536664311, 536664319, 536664341, 536664361, 536664383, 536664389, 536664437, 536664461, 536664463, 536664493, 536664521, 536664523, 536664559, 536664631, 536664673, 536664677, 536664679, 536664731, 536664781, 536664797, 536664853, 536664881, 536664889, 536664893, 536664929, 536664943, 536664971, 536664979, 536665009, 536665079, 536665081, 536665099, 536665111, 536665139, 536665153, 536665177, 536665289, 536665291, 536665331, 536665343, 536665379, 536665391, 536665433, 536665447, 536665453, 536665489, 536665513, 536665541, 536665553, 536665603, 536665631, 536665637, 536665663, 536665681, 536665691, 536665709, 536665729, 536665771, 536665777, 536665781, 536665819, 536665859, 536665867, 536665873, 536665897, 536665931, 536665957, 536665981, 536665993, 536666063, 536666071, 536666087, 536666089, 536666147, 536666159, 536666161, 536666213, 536666219, 536666281, 536666321, 536666329, 536666399, 536666413, 536666441, 536666467, 536666483, 536666509, 536666527, 536666549, 536666551, 536666563, 536666569, 536666597, 536666639, 536666651, 536666657, 536666681, 536666729, 536666731, 536666737, 536666749, 536666791, 536666813, 536666831, 536666857, 536666861, 536666899, 536666903, 536666927, 536666929, 536666939, 536666941, 536666957, 536666969, 536666971, 536667023, 536667031, 536667037, 536667049, 536667083, 536667107, 536667113, 536667149, 536667151, 536667191, 536667193, 536667221, 536667251, 536667323, 536667337, 536667343, 536667361, 536667377, 536667427, 536667431, 536667433, 536667493, 536667529, 536667539, 536667541, 536667553, 536667581, 536667589, 536667613, 536667689, 536667697, 536667743, 536667751, 536667757, 536667767, 536667773, 536667779, 536667793, 536667797, 536667811, 536667827, 536667851, 536667871, 536667893, 536667941, 536667961, 536668031, 536668037, 536668061, 536668081, 536668103, 536668109, 536668133, 536668163, 536668193, 536668211, 536668217, 536668219, 536668241, 536668259, 536668267, 536668271, 536668283, 536668303, 536668331, 536668343, 536668351, 536668369, 536668397, 536668399, 536668411, 536668421, 536668441, 536668477, 536668493, 536668511, 536668523, 536668537, 536668541, 536668579, 536668687, 536668697, 536668711, 536668723, 536668747, 536668763, 536668777, 536668819, 536668823, 536668837, 536668841, 536668877, 536668919, 536668933, 536668961, 536668969, 536668973, 536668981, 536668997, 536668999, 536669017, 536669047, 536669059, 536669083, 536669137, 536669227, 536669233, 536669261, 536669323, 536669339, 536669381, 536669407, 536669411, 536669417, 536669429, 536669437, 536669443, 536669479, 536669519, 536669527, 536669533, 536669543, 536669579, 536669629, 536669633, 536669659, 536669663, 536669671, 536669677, 536669681, 536669729, 536669743, 536669747, 536669779, 536669797, 536669807, 536669813, 536669843, 536669873, 536669897, 536669899, 536669921, 536669981, 536669983, 536669999, 536670007, 536670011, 536670019, 536670023, 536670041, 536670061, 536670073, 536670083, 536670097, 536670107, 536670119, 536670133, 536670139, 536670149, 536670151, 536670187, 536670191, 536670193, 536670203, 536670223, 536670269, 536670287, 536670301, 536670307, 536670341, 536670349, 536670373, 536670383, 536670389, 536670391, 536670397, 536670403, 536670427, 536670439, 536670457, 536670473, 536670493, 536670499, 536670509, 536670517, 536670551, 536670553, 536670571, 536670583, 536670593, 536670601, 536670643, 536670649, 536670677, 536670679, 536670683, 536670721, 536670727, 536670809, 536670811, 536670821, 536670847, 536670851, 536670857, 536670859, 536670877, 536670887, 536670923, 536670929, 536670989, 536670991, 536671001, 536671043, 536671087, 536671103, 536671123, 536671133, 536671151, 536671183, 536671193, 536671217, 536671231, 536671243, 536671271, 536671297, 536671301, 536671319, 536671337, 536671379, 536671381, 536671403, 536671439, 536671441, 536671501, 536671507, 536671559, 536671561, 536671567, 536671579, 536671601, 536671621, 536671631, 536671753, 536671781, 536671787, 536671801, 536671813, 536671841, 536671843, 536671867, 536671879, 536671973, 536671979, 536671981, 536672021, 536672029, 536672033, 536672039, 536672053, 536672063, 536672111, 536672137, 536672183, 536672203, 536672221, 536672249, 536672261, 536672267, 536672299, 536672351, 536672377, 536672399, 536672407, 536672419, 536672483, 536672491, 536672497, 536672503, 536672519, 536672557, 536672561, 536672597, 536672611, 536672623, 536672641, 536672681, 536672687, 536672699, 536672707, 536672729, 536672761, 536672767, 536672839, 536672849, 536672863, 536672887, 536672891, 536672897, 536672911, 536672921, 536672933, 536672957, 536672959, 536672963, 536672971, 536672989, 536673013, 536673041, 536673061, 536673073, 536673083, 536673127, 536673133, 536673143, 536673169, 536673199, 536673227, 536673233, 536673253, 536673281, 536673287, 536673331, 536673337, 536673341, 536673343, 536673353, 536673367, 536673383, 536673407, 536673427, 536673433, 536673437, 536673463, 536673469, 536673481, 536673503, 536673517, 536673541, 536673607, 536673653, 536673667, 536673691, 536673719, 536673721, 536673733, 536673769, 536673773, 536673803, 536673847, 536673859, 536673889, 536673899, 536673911, 536673923, 536673931, 536673941, 536673961, 536673967, 536673979, 536673989, 536673997, 536674007, 536674031, 536674043, 536674063, 536674091, 536674093, 536674123, 536674129, 536674141, 536674169, 536674181, 536674211, 536674213, 536674217, 536674219, 536674223, 536674267, 536674273, 536674277, 536674321, 536674331, 536674337, 536674349, 536674367, 536674409, 536674417, 536674423, 536674429, 536674451, 536674483, 536674507, 536674517, 536674549, 536674583, 536674591, 536674639, 536674681, 536674693, 536674753, 536674769, 536674771, 536674781, 536674807, 536674813, 536674829, 536674843, 536674861, 536674867, 536674909, 536674927, 536674961, 536674967, 536674981, 536674987, 536674993, 536674997, 536675003, 536675017, 536675039, 536675053, 536675063, 536675129, 536675137, 536675143, 536675147, 536675149, 536675171, 536675177, 536675213, 536675219, 536675221, 536675231, 536675239, 536675323, 536675351, 536675369, 536675393, 536675401, 536675407, 536675411, 536675413, 536675467, 536675471, 536675483, 536675497, 536675507, 536675549, 536675551, 536675599, 536675617, 536675641, 536675687, 536675693, 536675701, 536675719, 536675753, 536675837, 536675879, 536675891, 536675899, 536675969, 536676011, 536676029, 536676031, 536676067, 536676073, 536676103, 536676131, 536676139, 536676167, 536676169, 536676209, 536676229, 536676253, 536676269, 536676271, 536676277, 536676289, 536676293, 536676307, 536676313, 536676317, 536676367, 536676391, 536676401, 536676431, 536676443, 536676461, 536676479, 536676493, 536676521, 536676541, 536676559, 536676577, 536676611, 536676617, 536676643, 536676649, 536676661, 536676671, 536676677, 536676709, 536676713, 536676737, 536676761, 536676769, 536676799, 536676809, 536676821, 536676857, 536676863, 536676883, 536676911, 536676919, 536676949, 536676977, 536676989, 536676997, 536677007, 536677051, 536677069, 536677117, 536677151, 536677153, 536677159, 536677187, 536677213, 536677217, 536677279, 536677307, 536677343, 536677391, 536677397, 536677399, 536677441, 536677481, 536677499, 536677517, 536677529, 536677543, 536677597, 536677613, 536677619, 536677627, 536677633, 536677639, 536677649, 536677681, 536677717, 536677723, 536677753, 536677763, 536677769, 536677789, 536677829, 536677849, 536677861, 536677871, 536677877, 536677901, 536677907, 536677927, 536677957, 536677961, 536677963, 536678003, 536678017, 536678029, 536678033, 536678039, 536678041, 536678057, 536678171, 536678173, 536678201, 536678209, 536678239, 536678257, 536678269, 536678273, 536678291, 536678327, 536678339, 536678341, 536678353, 536678357, 536678447, 536678449, 536678473, 536678489, 536678531, 536678533, 536678543, 536678551, 536678557, 536678567, 536678683, 536678749, 536678761, 536678771, 536678783, 536678827, 536678833, 536678881, 536678897, 536678929, 536678951, 536678957, 536678963, 536678983, 536679029, 536679061, 536679089, 536679107, 536679109, 536679119, 536679181, 536679193, 536679233, 536679251, 536679329, 536679343, 536679349, 536679361, 536679379, 536679419, 536679421, 536679427, 536679499, 536679547, 536679551, 536679587, 536679593, 536679599, 536679607, 536679623, 536679629, 536679653, 536679659, 536679679, 536679683, 536679707, 536679739, 536679779, 536679823, 536679853, 536679859, 536679863, 536679889, 536679893, 536679959, 536679991, 536680009, 536680069, 536680087, 536680093, 536680097, 536680103, 536680141, 536680163, 536680171, 536680211, 536680247, 536680253, 536680273, 536680363, 536680369, 536680381, 536680387, 536680411, 536680423, 536680433, 536680453, 536680471, 536680477, 536680483, 536680489, 536680493, 536680499, 536680511, 536680553, 536680559, 536680589, 536680601, 536680609, 536680619, 536680637, 536680657, 536680663, 536680673, 536680679, 536680681, 536680717, 536680801, 536680811, 536680813, 536680817, 536680831, 536680841, 536680847, 536680909, 536680913, 536680961, 536680981, 536681003, 536681009, 536681017, 536681023, 536681039, 536681113, 536681137, 536681141, 536681147, 536681153, 536681209, 536681227, 536681231, 536681251, 536681281, 536681293, 536681329, 536681351, 536681399, 536681401, 536681407, 536681459, 536681489, 536681491, 536681521, 536681549, 536681557, 536681567, 536681611, 536681617, 536681623, 536681689, 536681711, 536681713, 536681723, 536681731, 536681741, 536681749, 536681777, 536681779, 536681851, 536681863, 536681921, 536681927, 536681941, 536681969, 536681987, 536682017, 536682053, 536682059, 536682071, 536682073, 536682089, 536682103, 536682119, 536682121, 536682131, 536682173, 536682217, 536682229, 536682239, 536682247, 536682257, 536682277, 536682353, 536682413, 536682457, 536682481, 536682499, 536682547, 536682551, 536682593, 536682623, 536682637, 536682649, 536682691, 536682701, 536682737, 536682799, 536682827, 536682829, 536682857, 536682869, 536682889, 536682899, 536682917, 536682967, 536682997, 536683009, 536683073, 536683093, 536683097, 536683099, 536683157, 536683171, 536683201, 536683223, 536683241, 536683267, 536683283, 536683313, 536683321, 536683327, 536683337, 536683351, 536683363, 536683369, 536683373, 536683379, 536683393, 536683447, 536683463, 536683487, 536683507, 536683571, 536683573, 536683597, 536683603, 536683607, 536683661, 536683699, 536683703, 536683723, 536683739, 536683757, 536683769, 536683789, 536683837, 536683841, 536683843, 536683871, 536683877, 536683879, 536683907, 536683913, 536683921, 536683943, 536683949, 536683993, 536684009, 536684017, 536684041, 536684077, 536684081, 536684107, 536684123, 536684129, 536684153, 536684167, 536684189, 536684221, 536684249, 536684263, 536684327, 536684359, 536684363, 536684381, 536684387, 536684389, 536684437, 536684471, 536684479, 536684497, 536684531, 536684563, 536684567, 536684581, 536684623, 536684627, 536684633, 536684641, 536684647, 536684651, 536684671, 536684719, 536684749, 536684779, 536684789, 536684791, 536684851, 536684857, 536684867, 536684903, 536684909, 536684923, 536684947, 536684959, 536684971, 536684983, 536685011, 536685031, 536685043, 536685067, 536685073, 536685089, 536685101, 536685131, 536685169, 536685199, 536685239, 536685241, 536685263, 536685283, 536685287, 536685293, 536685313, 536685319, 536685337, 536685389, 536685437, 536685469, 536685493, 536685509, 536685599, 536685637, 536685697, 536685701, 536685739, 536685769, 536685781, 536685833, 536685847, 536685899, 536685911, 536685917, 536685923, 536686069, 536686123, 536686127, 536686181, 536686193, 536686219, 536686237, 536686247, 536686253, 536686303, 536686343, 536686349, 536686399, 536686417, 536686429, 536686453, 536686463, 536686489, 536686529, 536686537, 536686603, 536686621, 536686637, 536686649, 536686687, 536686697, 536686721, 536686747, 536686757, 536686781, 536686811, 536686837, 536686861, 536686877, 536686907, 536686921, 536686949, 536686979, 536686981, 536686993, 536687003, 536687009, 536687071, 536687077, 536687087, 536687111, 536687227, 536687233, 536687251, 536687273, 536687299, 536687303, 536687317, 536687329, 536687339, 536687383, 536687401, 536687449, 536687453, 536687483, 536687491, 536687507, 536687519, 536687521, 536687537, 536687539, 536687563, 536687579, 536687609, 536687611, 536687617, 536687707, 536687791, 536687861, 536687863, 536687873, 536687887, 536687917, 536687929, 536687941, 536687951, 536687969, 536688059, 536688107, 536688137, 536688161, 536688169, 536688179, 536688199, 536688241, 536688247, 536688259, 536688287, 536688311, 536688343, 536688389, 536688391, 536688403, 536688437, 536688457, 536688491, 536688511, 536688517, 536688533, 536688557, 536688569, 536688599, 536688617, 536688619, 536688637, 536688661, 536688667, 536688679, 536688701, 536688727, 536688743, 536688767, 536688769, 536688809, 536688829, 536688853, 536688857, 536688899, 536688931, 536688937, 536688947, 536688967, 536688973, 536688989, 536689001, 536689007, 536689037, 536689117, 536689123, 536689129, 536689169, 536689217, 536689243, 536689273, 536689277, 536689297, 536689301, 536689327, 536689331, 536689379, 536689421, 536689441, 536689451, 536689459, 536689463, 536689471, 536689499, 536689511, 536689553, 536689583, 536689693, 536689697, 536689709, 536689717, 536689721, 536689729, 536689753, 536689799, 536689807, 536689817, 536689823, 536689831, 536689841, 536689849, 536689859, 536689871, 536689873, 536689891, 536689913, 536689927, 536689939, 536689963, 536689987, 536690023, 536690029, 536690047, 536690053, 536690057, 536690083, 536690107, 536690111, 536690117, 536690129, 536690171, 536690177, 536690183, 536690191, 536690263, 536690293, 536690299, 536690317, 536690333, 536690387, 536690389, 536690411, 536690417, 536690423, 536690431, 536690471, 536690477, 536690489, 536690503, 536690543, 536690551, 536690573, 536690591, 536690593, 536690599, 536690639, 536690641, 536690653, 536690657, 536690659, 536690689, 536690719, 536690723, 536690729, 536690741, 536690743, 536690753, 536690761, 536690767, 536690789, 536690797, 536690801, 536690813, 536690851, 536690863, 536690897, 536690899, 536690911, 536690923, 536690927, 536690933, 536690977, 536690983, 536690989, 536691007, 536691019, 536691049, 536691083, 536691097, 536691121, 536691137, 536691151, 536691187, 536691191, 536691193, 536691209, 536691229, 536691277, 536691283, 536691289, 536691329, 536691341, 536691403, 536691413, 536691427, 536691431, 536691433, 536691439, 536691509, 536691511, 536691521, 536691539, 536691541, 536691559, 536691569, 536691587, 536691619, 536691629, 536691677, 536691721, 536691737, 536691761, 536691773, 536691781, 536691791, 536691823, 536691829, 536691863, 536691899, 536691931, 536691937, 536691943, 536691971, 536691973, 536691977, 536691997, 536692001, 536692081, 536692133, 536692139, 536692153, 536692171, 536692217, 536692223, 536692231, 536692249, 536692253, 536692271, 536692279, 536692283, 536692301, 536692307, 536692309, 536692313, 536692319, 536692361, 536692381, 536692421, 536692441, 536692451, 536692463, 536692477, 536692493, 536692523, 536692547, 536692571, 536692573, 536692613, 536692661, 536692687, 536692711, 536692769, 536692777, 536692811, 536692831, 536692841, 536692853, 536692901, 536692931, 536692939, 536692957, 536693021, 536693107, 536693117, 536693119, 536693123, 536693137, 536693159, 536693167, 536693197, 536693233, 536693257, 536693279, 536693291, 536693303, 536693309, 536693341, 536693347, 536693371, 536693429, 536693461, 536693501, 536693503, 536693533, 536693557, 536693561, 536693593, 536693623, 536693657, 536693681, 536693693, 536693701, 536693711, 536693777, 536693803, 536693819, 536693837, 536693881, 536693897, 536693909, 536693929, 536693939, 536693947, 536694001, 536694047, 536694049, 536694061, 536694101, 536694107, 536694157, 536694161, 536694203, 536694211, 536694229, 536694241, 536694251, 536694283, 536694331, 536694341, 536694359, 536694371, 536694391, 536694401, 536694419, 536694427, 536694449, 536694533, 536694553, 536694569, 536694601, 536694617, 536694649, 536694667, 536694671, 536694679, 536694689, 536694701, 536694721, 536694727, 536694749, 536694757, 536694779, 536694827, 536694853, 536694869, 536694883, 536694887, 536694901, 536694929, 536694931, 536694989, 536695037, 536695057, 536695069, 536695091, 536695099, 536695121, 536695123, 536695127, 536695129, 536695193, 536695217, 536695279, 536695297, 536695301, 536695309, 536695339, 536695387, 536695417, 536695433, 536695459, 536695463, 536695483, 536695487, 536695493, 536695553, 536695561, 536695567, 536695573, 536695597, 536695613, 536695631, 536695657, 536695667, 536695703, 536695711, 536695727, 536695741, 536695759, 536695787, 536695799, 536695813, 536695847, 536695853, 536695871, 536695889, 536695891, 536695937, 536695949, 536695979, 536695987, 536696071, 536696081, 536696093, 536696101, 536696113, 536696119, 536696131, 536696159, 536696207, 536696221, 536696227, 536696261, 536696269, 536696291, 536696297, 536696311, 536696317, 536696323, 536696339, 536696353, 536696357, 536696371, 536696393, 536696399, 536696411, 536696423, 536696449, 536696453, 536696471, 536696491, 536696543, 536696557, 536696569, 536696593, 536696609, 536696617, 536696621, 536696639, 536696701, 536696711, 536696747, 536696761, 536696773, 536696791, 536696843, 536696899, 536696903, 536696917, 536696969, 536696983, 536696989, 536697041, 536697059, 536697071, 536697097, 536697137, 536697163, 536697169, 536697179, 536697181, 536697193, 536697211, 536697221, 536697251, 536697263, 536697281, 536697283, 536697289, 536697299, 536697347, 536697349, 536697353, 536697367, 536697373, 536697379, 536697383, 536697401, 536697407, 536697439, 536697457, 536697467, 536697523, 536697529, 536697547, 536697587, 536697593, 536697611, 536697619, 536697641, 536697643, 536697649, 536697659, 536697673, 536697677, 536697697, 536697719, 536697737, 536697743, 536697757, 536697767, 536697773, 536697781, 536697787, 536697793, 536697827, 536697829, 536697853, 536697859, 536697869, 536697901, 536697923, 536697929, 536697937, 536697943, 536697949, 536697991, 536698013, 536698021, 536698033, 536698037, 536698039, 536698049, 536698103, 536698139, 536698147, 536698153, 536698163, 536698171, 536698181, 536698189, 536698219, 536698247, 536698259, 536698277, 536698291, 536698297, 536698333, 536698361, 536698363, 536698387, 536698433, 536698469, 536698471, 536698493, 536698507, 536698541, 536698549, 536698559, 536698573, 536698601, 536698627, 536698649, 536698663, 536698699, 536698709, 536698711, 536698717, 536698739, 536698759, 536698777, 536698787, 536698807, 536698861, 536698873, 536698889, 536698901, 536698913, 536698927, 536698931, 536698961, 536698991, 536699077, 536699083, 536699087, 536699173, 536699221, 536699239, 536699257, 536699269, 536699287, 536699309, 536699321, 536699353, 536699357, 536699369, 536699399, 536699407, 536699419, 536699453, 536699461, 536699473, 536699507, 536699509, 536699519, 536699539, 536699543, 536699551, 536699563, 536699573, 536699599, 536699659, 536699671, 536699701, 536699729, 536699749, 536699767, 536699771, 536699773, 536699791, 536699819, 536699833, 536699857, 536699879, 536699893, 536699903, 536699921, 536699927, 536699929, 536699951, 536699953, 536699957, 536699971, 536699983, 536700007, 536700019, 536700023, 536700037, 536700041, 536700067, 536700079, 536700107, 536700137, 536700169, 536700173, 536700181, 536700211, 536700221, 536700223, 536700247, 536700253, 536700257, 536700271, 536700287, 536700323, 536700347, 536700443, 536700449, 536700457, 536700481, 536700487, 536700491, 536700517, 536700529, 536700539, 536700547, 536700559, 536700583, 536700611, 536700629, 536700667, 536700677, 536700679, 536700707, 536700719, 536700743, 536700751, 536700817, 536700833, 536700839, 536700851, 536700859, 536700869, 536700877, 536700911, 536700937, 536700959, 536700973, 536700977, 536701007, 536701027, 536701043, 536701063, 536701069, 536701091, 536701127, 536701133, 536701163, 536701177, 536701181, 536701211, 536701213, 536701223, 536701247, 536701261, 536701301, 536701309, 536701327, 536701331, 536701337, 536701369, 536701387, 536701397, 536701409, 536701411, 536701421, 536701433, 536701453, 536701471, 536701483, 536701511, 536701519, 536701547, 536701549, 536701559, 536701591, 536701597, 536701639, 536701681, 536701699, 536701727, 536701751, 536701771, 536701783, 536701793, 536701799, 536701813, 536701817, 536701829, 536701843, 536701861, 536701889, 536701943, 536701969, 536702003, 536702011, 536702017, 536702027, 536702029, 536702051, 536702069, 536702081, 536702119, 536702123, 536702137, 536702141, 536702143, 536702161, 536702197, 536702209, 536702251, 536702273, 536702293, 536702297, 536702303, 536702311, 536702347, 536702357, 536702371, 536702377, 536702389, 536702399, 536702407, 536702417, 536702431, 536702437, 536702483, 536702489, 536702503, 536702513, 536702521, 536702533, 536702549, 536702591, 536702599, 536702611, 536702641, 536702657, 536702689, 536702701, 536702713, 536702731, 536702741, 536702743, 536702753, 536702759, 536702779, 536702819, 536702839, 536702893, 536702921, 536702927, 536702977, 536703001, 536703007, 536703023, 536703059, 536703077, 536703113, 536703121, 536703163, 536703173, 536703239, 536703257, 536703287, 536703313, 536703329, 536703337, 536703347, 536703421, 536703443, 536703457, 536703467, 536703473, 536703487, 536703491, 536703499, 536703509, 536703521, 536703523, 536703529, 536703533, 536703539, 536703631, 536703641, 536703649, 536703691, 536703721, 536703733, 536703751, 536703757, 536703767, 536703779, 536703809, 536703911, 536703913, 536703929, 536703931, 536703967, 536703977, 536703989, 536703997, 536704019, 536704097, 536704111, 536704121, 536704183, 536704187, 536704193, 536704211, 536704303, 536704307, 536704367, 536704369, 536704373, 536704387, 536704409, 536704417, 536704423, 536704429, 536704439, 536704451, 536704459, 536704463, 536704481, 536704513, 536704523, 536704529, 536704547, 536704559, 536704561, 536704579, 536704627, 536704631, 536704669, 536704699, 536704717, 536704759, 536704771, 536704787, 536704811, 536704823, 536704849, 536704867, 536704873, 536704877, 536704897, 536704937, 536704957, 536704967, 536704969, 536704997, 536704999, 536705033, 536705051, 536705053, 536705063, 536705089, 536705093, 536705119, 536705131, 536705153, 536705159, 536705203, 536705227, 536705237, 536705243, 536705251, 536705261, 536705287, 536705341, 536705353, 536705357, 536705371, 536705383, 536705441, 536705447, 536705479, 536705497, 536705503, 536705537, 536705551, 536705557, 536705579, 536705593, 536705641, 536705651, 536705669, 536705671, 536705723, 536705773, 536705791, 536705803, 536705839, 536705887, 536705891, 536705893, 536705909, 536705921, 536705993, 536706011, 536706041, 536706089, 536706097, 536706101, 536706151, 536706169, 536706197, 536706199, 536706229, 536706241, 536706251, 536706257, 536706307, 536706341, 536706361, 536706367, 536706419, 536706463, 536706481, 536706491, 536706589, 536706593, 536706601, 536706617, 536706641, 536706671, 536706691, 536706697, 536706701, 536706707, 536706727, 536706733, 536706739, 536706743, 536706749, 536706761, 536706763, 536706767, 536706773, 536706787, 536706839, 536706883, 536706887, 536706899, 536706931, 536706943, 536706979, 536707009, 536707019, 536707021, 536707027, 536707043, 536707049, 536707057, 536707063, 536707109, 536707121, 536707151, 536707159, 536707177, 536707181, 536707183, 536707229, 536707253, 536707279, 536707313, 536707333, 536707351, 536707361, 536707363, 536707373, 536707417, 536707427, 536707447, 536707477, 536707481, 536707487, 536707511, 536707541, 536707583, 536707651, 536707657, 536707741, 536707781, 536707789, 536707807, 536707817, 536707823, 536707861, 536707879, 536707889, 536707891, 536707937, 536707949, 536707973, 536707979, 536708009, 536708047, 536708057, 536708063, 536708083, 536708089, 536708093, 536708101, 536708113, 536708141, 536708153, 536708167, 536708171, 536708189, 536708201, 536708287, 536708297, 536708311, 536708321, 536708399, 536708401, 536708407, 536708429, 536708437, 536708443, 536708449, 536708467, 536708503, 536708521, 536708527, 536708533, 536708551, 536708563, 536708639, 536708707, 536708719, 536708729, 536708747, 536708761, 536708801, 536708803, 536708807, 536708833, 536708881, 536708911, 536708917, 536708923, 536708947, 536708969, 536708999, 536709037, 536709059, 536709073, 536709077, 536709083, 536709127, 536709143, 536709149, 536709179, 536709181, 536709203, 536709211, 536709221, 536709263, 536709269, 536709281, 536709307, 536709337, 536709343, 536709379, 536709421, 536709469, 536709529, 536709559, 536709571, 536709599, 536709629, 536709637, 536709643, 536709653, 536709671, 536709673, 536709683, 536709689, 536709697, 536709749, 536709791, 536709829, 536709857, 536709863, 536709869, 536709871, 536709883, 536709893, 536709911, 536709917, 536709919, 536709977, 536710039, 536710051, 536710067, 536710093, 536710103, 536710117, 536710127, 536710151, 536710169, 536710189, 536710193, 536710201, 536710217, 536710243, 536710253, 536710259, 536710261, 536710289, 536710303, 536710327, 536710373, 536710393, 536710403, 536710457, 536710463, 536710483, 536710487, 536710507, 536710549, 536710561, 536710579, 536710591, 536710597, 536710631, 536710633, 536710679, 536710687, 536710693, 536710711, 536710717, 536710721, 536710747, 536710771, 536710777, 536710829, 536710871, 536710883, 536710897, 536710903, 536710921, 536710973, 536710987, 536711027, 536711039, 536711051, 536711057, 536711059, 536711083, 536711089, 536711099, 536711101, 536711137, 536711167, 536711179, 536711209, 536711237, 536711243, 536711249, 536711269, 536711291, 536711293, 536711317, 536711321, 536711333, 536711353, 536711359, 536711393, 536711407, 536711419, 536711431, 536711453, 536711459, 536711501, 536711503, 536711519, 536711533, 536711569, 536711621, 536711629, 536711653, 536711657, 536711687, 536711699, 536711713, 536711737, 536711783, 536711789, 536711803, 536711807, 536711809, 536711837, 536711839, 536711863, 536711869, 536711873, 536711881, 536711909, 536711911, 536711921, 536711927, 536711957, 536711971, 536711993, 536711999, 536712037, 536712041, 536712067, 536712073, 536712089, 536712103, 536712131, 536712139, 536712149, 536712157, 536712161, 536712167, 536712191, 536712233, 536712257, 536712289, 536712299, 536712301, 536712329, 536712373, 536712377, 536712391, 536712409, 536712413, 536712461, 536712487, 536712493, 536712511, 536712563, 536712577, 536712581, 536712601, 536712623, 536712647, 536712667, 536712689, 536712691, 536712697, 536712719, 536712721, 536712727, 536712731, 536712769, 536712811, 536712853, 536712887, 536712901, 536712949, 536712961, 536712977, 536712991, 536712997, 536713031, 536713039, 536713087, 536713127, 536713141, 536713183, 536713201, 536713207, 536713213, 536713223, 536713241, 536713249, 536713253, 536713259, 536713267, 536713279, 536713321, 536713339, 536713357, 536713361, 536713363, 536713367, 536713381, 536713417, 536713423, 536713433, 536713481, 536713517, 536713519, 536713531, 536713559, 536713589, 536713621, 536713627, 536713673, 536713679, 536713687, 536713693, 536713733, 536713741, 536713747, 536713777, 536713781, 536713789, 536713829, 536713841, 536713847, 536713861, 536713867, 536713873, 536713907, 536713909, 536713927, 536713949, 536713963, 536713967, 536713979, 536713981, 536713997, 536713999, 536714023, 536714041, 536714081, 536714083, 536714111, 536714117, 536714141, 536714201, 536714203, 536714207, 536714221, 536714237, 536714251, 536714263, 536714309, 536714317, 536714329, 536714359, 536714363, 536714419, 536714441, 536714443, 536714509, 536714543, 536714557, 536714569, 536714579, 536714597, 536714609, 536714621, 536714627, 536714653, 536714669, 536714671, 536714713, 536714719, 536714807, 536714813, 536714819, 536714833, 536714851, 536714881, 536714947, 536714989, 536714993, 536714999, 536715013, 536715029, 536715071, 536715073, 536715079, 536715119, 536715131, 536715163, 536715167, 536715169, 536715187, 536715197, 536715203, 536715217, 536715227, 536715239, 536715251, 536715269, 536715323, 536715331, 536715353, 536715367, 536715391, 536715397, 536715407, 536715427, 536715463, 536715467, 536715469, 536715497, 536715523, 536715533, 536715541, 536715547, 536715563, 536715581, 536715601, 536715611, 536715623, 536715659, 536715661, 536715677, 536715703, 536715713, 536715737, 536715749, 536715757, 536715763, 536715769, 536715793, 536715827, 536715859, 536715863, 536715887, 536715911, 536715937, 536715943, 536716073, 536716087, 536716093, 536716099, 536716139, 536716181, 536716183, 536716189, 536716249, 536716259, 536716261, 536716273, 536716277, 536716289, 536716291, 536716331, 536716337, 536716357, 536716373, 536716381, 536716393, 536716403, 536716409, 536716421, 536716459, 536716483, 536716489, 536716501, 536716511, 536716529, 536716549, 536716559, 536716567, 536716573, 536716633, 536716651, 536716679, 536716729, 536716751, 536716759, 536716771, 536716819, 536716823, 536716853, 536716861, 536716889, 536716897, 536716913, 536716933, 536716969, 536716991, 536717011, 536717021, 536717023, 536717033, 536717039, 536717053, 536717057, 536717059, 536717119, 536717143, 536717161, 536717173, 536717189, 536717191, 536717197, 536717249, 536717257, 536717261, 536717267, 536717287, 536717303, 536717317, 536717371, 536717381, 536717411, 536717431, 536717479, 536717483, 536717497, 536717521, 536717537, 536717543, 536717561, 536717563, 536717579, 536717603, 536717617, 536717647, 536717651, 536717669, 536717683, 536717743, 536717747, 536717809, 536717821, 536717851, 536717869, 536717879, 536717917, 536717927, 536717933, 536717941, 536717981, 536717989, 536718019, 536718031, 536718043, 536718047, 536718073, 536718079, 536718107, 536718113, 536718151, 536718191, 536718211, 536718229, 536718233, 536718241, 536718253, 536718257, 536718277, 536718293, 536718311, 536718349, 536718359, 536718361, 536718367, 536718431, 536718463, 536718503, 536718551, 536718569, 536718599, 536718601, 536718617, 536718643, 536718649, 536718661, 536718691, 536718701, 536718769, 536718773, 536718797, 536718799, 536718827, 536718857, 536718881, 536718887, 536718901, 536718913, 536718937, 536718947, 536718953, 536718967, 536718971, 536718997, 536719013, 536719061, 536719063, 536719097, 536719103, 536719109, 536719123, 536719133, 536719147, 536719159, 536719177, 536719187, 536719219, 536719231, 536719243, 536719247, 536719259, 536719321, 536719349, 536719361, 536719363, 536719387, 536719411, 536719453, 536719457, 536719471, 536719487, 536719489, 536719553, 536719577, 536719591, 536719607, 536719609, 536719613, 536719621, 536719633, 536719691, 536719753, 536719763, 536719769, 536719787, 536719819, 536719861, 536719879, 536719901, 536719933, 536719951, 536720003, 536720011, 536720057, 536720087, 536720099, 536720101, 536720117, 536720137, 536720147, 536720153, 536720179, 536720221, 536720237, 536720257, 536720263, 536720269, 536720287, 536720291, 536720293, 536720297, 536720321, 536720333, 536720339, 536720351, 536720399, 536720411, 536720419, 536720423, 536720449, 536720461, 536720491, 536720501, 536720521, 536720593, 536720609, 536720677, 536720689, 536720713, 536720731, 536720809, 536720827, 536720831, 536720837, 536720851, 536720869, 536720897, 536720917, 536720941, 536720953, 536720963, 536720999, 536721007, 536721013, 536721019, 536721043, 536721047, 536721049, 536721061, 536721091, 536721137, 536721179, 536721187, 536721271, 536721287, 536721337, 536721377, 536721379, 536721391, 536721401, 536721421, 536721457, 536721461, 536721463, 536721469, 536721487, 536721499, 536721509, 536721517, 536721539, 536721547, 536721551, 536721587, 536721599, 536721617, 536721641, 536721649, 536721677, 536721697, 536721707, 536721781, 536721793, 536721827, 536721833, 536721847, 536721853, 536721869, 536721881, 536721883, 536721917, 536721923, 536721929, 536721961, 536721967, 536721973, 536722007, 536722057, 536722063, 536722091, 536722099, 536722117, 536722133, 536722139, 536722159, 536722163, 536722171, 536722201, 536722223, 536722237, 536722253, 536722261, 536722301, 536722309, 536722321, 536722331, 536722357, 536722367, 536722369, 536722387, 536722399, 536722423, 536722429, 536722463, 536722471, 536722489, 536722493, 536722523, 536722531, 536722547, 536722567, 536722577, 536722601, 536722607, 536722661, 536722673, 536722699, 536722727, 536722783, 536722799, 536722829, 536722859, 536722873, 536722889, 536722897, 536722909, 536722943, 536722951, 536722961, 536722969, 536722973, 536723023, 536723051, 536723071, 536723081, 536723093, 536723129, 536723203, 536723237, 536723263, 536723279, 536723281, 536723287, 536723321, 536723339, 536723347, 536723351, 536723353, 536723357, 536723417, 536723431, 536723437, 536723461, 536723477, 536723483, 536723563, 536723573, 536723581, 536723617, 536723639, 536723641, 536723657, 536723659, 536723687, 536723713, 536723729, 536723731, 536723741, 536723749, 536723771, 536723809, 536723819, 536723903, 536723923, 536723963, 536723969, 536724007, 536724029, 536724031, 536724073, 536724077, 536724079, 536724101, 536724127, 536724143, 536724169, 536724191, 536724193, 536724211, 536724229, 536724233, 536724263, 536724271, 536724277, 536724313, 536724361, 536724367, 536724401, 536724413, 536724437, 536724449, 536724457, 536724467, 536724469, 536724497, 536724509, 536724511, 536724541, 536724569, 536724577, 536724599, 536724637, 536724649, 536724653, 536724659, 536724677, 536724719, 536724751, 536724761, 536724781, 536724791, 536724817, 536724847, 536724857, 536724869, 536724883, 536724919, 536724931, 536724943, 536724949, 536724961, 536724971, 536724983, 536724989, 536725039, 536725043, 536725051, 536725073, 536725081, 536725099, 536725157, 536725159, 536725169, 536725177, 536725187, 536725229, 536725297, 536725303, 536725307, 536725313, 536725327, 536725333, 536725339, 536725349, 536725361, 536725439, 536725451, 536725457, 536725459, 536725489, 536725499, 536725507, 536725517, 536725531, 536725561, 536725577, 536725597, 536725619, 536725621, 536725627, 536725633, 536725643, 536725669, 536725691, 536725703, 536725729, 536725741, 536725771, 536725801, 536725807, 536725829, 536725831, 536725841, 536725873, 536725879, 536725913, 536725961, 536725963, 536725979, 536726059, 536726077, 536726081, 536726087, 536726119, 536726131, 536726147, 536726153, 536726173, 536726191, 536726207, 536726209, 536726279, 536726297, 536726299, 536726341, 536726353, 536726357, 536726419, 536726501, 536726503, 536726527, 536726539, 536726621, 536726623, 536726629, 536726633, 536726647, 536726651, 536726657, 536726683, 536726713, 536726759, 536726779, 536726797, 536726803, 536726807, 536726821, 536726837, 536726851, 536726891, 536726893, 536726909, 536726987, 536727001, 536727013, 536727097, 536727119, 536727167, 536727193, 536727203, 536727209, 536727239, 536727251, 536727271, 536727277, 536727299, 536727311, 536727337, 536727341, 536727407, 536727413, 536727461, 536727467, 536727469, 536727509, 536727533, 536727547, 536727557, 536727577, 536727589, 536727601, 536727619, 536727629, 536727649, 536727691, 536727727, 536727731, 536727787, 536727799, 536727803, 536727811, 536727823, 536727847, 536727857, 536727871, 536727907, 536727913, 536728001, 536728019, 536728061, 536728103, 536728151, 536728177, 536728187, 536728211, 536728229, 536728249, 536728271, 536728277, 536728307, 536728333, 536728337, 536728351, 536728373, 536728393, 536728411, 536728429, 536728441, 536728453, 536728501, 536728541, 536728567, 536728603, 536728609, 536728613, 536728627, 536728639, 536728649, 536728657, 536728669, 536728681, 536728711, 536728729, 536728757, 536728769, 536728783, 536728807, 536728817, 536728849, 536728883, 536728889, 536728921, 536728939, 536728949, 536728979, 536729003, 536729107, 536729159, 536729177, 536729183, 536729197, 536729201, 536729209, 536729267, 536729279, 536729293, 536729317, 536729339, 536729353, 536729371, 536729383, 536729393, 536729411, 536729447, 536729471, 536729489, 536729527, 536729539, 536729551, 536729573, 536729579, 536729581, 536729597, 536729621, 536729639, 536729657, 536729693, 536729717, 536729723, 536729747, 536729759, 536729761, 536729779, 536729819, 536729833, 536729839, 536729861, 536729873, 536729891, 536729929, 536729957, 536729959, 536729983, 536730011, 536730023, 536730037, 536730043, 536730113, 536730119, 536730143, 536730163, 536730169, 536730193, 536730211, 536730223, 536730281, 536730283, 536730301, 536730317, 536730329, 536730353, 536730371, 536730401, 536730419, 536730433, 536730479, 536730533, 536730541, 536730583, 536730653, 536730659, 536730673, 536730697, 536730709, 536730721, 536730731, 536730739, 536730743, 536730757, 536730763, 536730767, 536730781, 536730793, 536730809, 536730839, 536730853, 536730893, 536730907, 536730911, 536730941, 536731049, 536731067, 536731073, 536731079, 536731087, 536731093, 536731099, 536731177, 536731183, 536731193, 536731199, 536731219, 536731229, 536731231, 536731277, 536731297, 536731309, 536731331, 536731373, 536731379, 536731397, 536731417, 536731423, 536731469, 536731471, 536731483, 536731523, 536731541, 536731549, 536731561, 536731567, 536731571, 536731579, 536731603, 536731607, 536731651, 536731669, 536731687, 536731691, 536731709, 536731711, 536731721, 536731751, 536731753, 536731771, 536731801, 536731849, 536731873, 536731889, 536731903, 536731919, 536731999, 536732017, 536732059, 536732069, 536732081, 536732089, 536732093, 536732123, 536732129, 536732173, 536732179, 536732221, 536732227, 536732257, 536732267, 536732291, 536732297, 536732303, 536732309, 536732341, 536732447, 536732461, 536732491, 536732503, 536732519, 536732533, 536732549, 536732561, 536732563, 536732569, 536732587, 536732591, 536732593, 536732597, 536732639, 536732663, 536732683, 536732699, 536732701, 536732723, 536732731, 536732747, 536732759, 536732821, 536732827, 536732831, 536732879, 536732893, 536732909, 536732939, 536732953, 536732981, 536733013, 536733023, 536733053, 536733059, 536733077, 536733097, 536733121, 536733143, 536733187, 536733203, 536733227, 536733251, 536733259, 536733271, 536733289, 536733317, 536733341, 536733343, 536733383, 536733403, 536733427, 536733437, 536733481, 536733511, 536733521, 536733529, 536733539, 536733551, 536733557, 536733569, 536733607, 536733661, 536733671, 536733677, 536733733, 536733737, 536733761, 536733763, 536733779, 536733787, 536733823, 536733839, 536733863, 536733871, 536733929, 536733947, 536733949, 536733971, 536733997, 536734027, 536734039, 536734073, 536734091, 536734103, 536734129, 536734153, 536734193, 536734223, 536734229, 536734259, 536734277, 536734333, 536734343, 536734399, 536734423, 536734427, 536734441, 536734507, 536734529, 536734531, 536734537, 536734571, 536734579, 536734607, 536734609, 536734613, 536734619, 536734621, 536734633, 536734637, 536734663, 536734673, 536734699, 536734717, 536734733, 536734747, 536734753, 536734771, 536734777, 536734799, 536734811, 536734823, 536734841, 536734883, 536734889, 536734921, 536734943, 536734949, 536734951, 536734963, 536734973, 536734981, 536734997, 536735029, 536735041, 536735053, 536735077, 536735099, 536735113, 536735117, 536735131, 536735179, 536735183, 536735189, 536735233, 536735239, 536735249, 536735261, 536735263, 536735299, 536735323, 536735327, 536735359, 536735447, 536735453, 536735477, 536735483, 536735489, 536735491, 536735531, 536735533, 536735539, 536735561, 536735597, 536735609, 536735627, 536735677, 536735701, 536735711, 536735791, 536735813, 536735831, 536735833, 536735863, 536735873, 536735893, 536735897, 536735957, 536735999, 536736001, 536736007, 536736041, 536736059, 536736061, 536736091, 536736113, 536736131, 536736169, 536736173, 536736181, 536736199, 536736203, 536736217, 536736229, 536736259, 536736269, 536736283, 536736329, 536736331, 536736341, 536736373, 536736391, 536736413, 536736419, 536736433, 536736443, 536736463, 536736481, 536736521, 536736559, 536736587, 536736589, 536736619, 536736647, 536736649, 536736653, 536736709, 536736721, 536736749, 536736769, 536736797, 536736817, 536736877, 536736881, 536736919, 536736923, 536736943, 536736973, 536736997, 536737001, 536737021, 536737057, 536737063, 536737079, 536737081, 536737087, 536737121, 536737127, 536737151, 536737163, 536737199, 536737211, 536737247, 536737291, 536737303, 536737319, 536737363, 536737381, 536737463, 536737477, 536737507, 536737529, 536737571, 536737589, 536737609, 536737633, 536737639, 536737667, 536737673, 536737679, 536737681, 536737699, 536737703, 536737727, 536737801, 536737807, 536737823, 536737879, 536737891, 536737933, 536737987, 536738017, 536738023, 536738029, 536738057, 536738063, 536738117, 536738129, 536738131, 536738141, 536738159, 536738171, 536738173, 536738197, 536738219, 536738221, 536738227, 536738233, 536738249, 536738291, 536738303, 536738333, 536738369, 536738393, 536738437, 536738491, 536738497, 536738591, 536738611, 536738623, 536738669, 536738689, 536738693, 536738701, 536738707, 536738729, 536738759, 536738767, 536738777, 536738801, 536738803, 536738819, 536738821, 536738837, 536738861, 536738863, 536738869, 536738887, 536738893, 536738903, 536738933, 536738963, 536738981, 536739001, 536739059, 536739083, 536739089, 536739097, 536739101, 536739179, 536739191, 536739209, 536739257, 536739263, 536739311, 536739319, 536739347, 536739361, 536739367, 536739377, 536739403, 536739433, 536739443, 536739449, 536739451, 536739547, 536739551, 536739557, 536739587, 536739601, 536739629, 536739641, 536739659, 536739737, 536739751, 536739757, 536739761, 536739767, 536739769, 536739773, 536739787, 536739811, 536739821, 536739839, 536739883, 536739899, 536739923, 536739967, 536739977, 536739989, 536740003, 536740007, 536740079, 536740103, 536740109, 536740117, 536740151, 536740153, 536740187, 536740199, 536740219, 536740249, 536740297, 536740301, 536740363, 536740387, 536740409, 536740441, 536740459, 536740483, 536740511, 536740513, 536740531, 536740543, 536740573, 536740579, 536740583, 536740591, 536740597, 536740619, 536740637, 536740639, 536740649, 536740661, 536740669, 536740679, 536740681, 536740691, 536740693, 536740697, 536740723, 536740739, 536740741, 536740793, 536740801, 536740807, 536740829, 536740837, 536740843, 536740849, 536740859, 536740871, 536740879, 536740909, 536740943, 536740951, 536740991, 536740999, 536741003, 536741011, 536741047, 536741063, 536741071, 536741131, 536741141, 536741143, 536741189, 536741207, 536741213, 536741267, 536741281, 536741311, 536741339, 536741341, 536741369, 536741377, 536741383, 536741389, 536741399, 536741417, 536741419, 536741461, 536741519, 536741531, 536741539, 536741581, 536741603, 536741627, 536741641, 536741651, 536741707, 536741749, 536741797, 536741801, 536741813, 536741819, 536741873, 536741893, 536741903, 536741911, 536741921, 536741941, 536741951, 536741981, 536741983, 536741999, 536742043, 536742047, 536742083, 536742097, 536742113, 536742119, 536742131, 536742163, 536742169, 536742197, 536742221, 536742251, 536742257, 536742307, 536742317, 536742319, 536742331, 536742341, 536742347, 536742359, 536742389, 536742391, 536742413, 536742431, 536742497, 536742517, 536742541, 536742617, 536742629, 536742631, 536742653, 536742659, 536742673, 536742677, 536742733, 536742769, 536742779, 536742781, 536742797, 536742803, 536742841, 536742859, 536742901, 536742907, 536742917, 536742919, 536742929, 536742949, 536742953, 536742967, 536742977, 536743007, 536743099, 536743117, 536743133, 536743153, 536743183, 536743199, 536743219, 536743267, 536743271, 536743297, 536743303, 536743307, 536743309, 536743327, 536743343, 536743421, 536743429, 536743447, 536743463, 536743469, 536743489, 536743507, 536743531, 536743541, 536743547, 536743621, 536743631, 536743661, 536743679, 536743681, 536743717, 536743721, 536743723, 536743733, 536743799, 536743849, 536743877, 536743897, 536743927, 536743937, 536743957, 536743979, 536744003, 536744023, 536744027, 536744051, 536744057, 536744069, 536744071, 536744141, 536744177, 536744203, 536744233, 536744251, 536744269, 536744287, 536744293, 536744347, 536744393, 536744419, 536744431, 536744501, 536744503, 536744531, 536744539, 536744561, 536744569, 536744573, 536744581, 536744599, 536744617, 536744641, 536744651, 536744669, 536744683, 536744693, 536744711, 536744749, 536744753, 536744759, 536744777, 536744779, 536744797, 536744801, 536744807, 536744861, 536744863, 536744909, 536744911, 536744921, 536744933, 536744947, 536744969, 536744987, 536745023, 536745031, 536745047, 536745059, 536745061, 536745071, 536745101, 536745113, 536745119, 536745127, 536745149, 536745173, 536745179, 536745203, 536745247, 536745263, 536745281, 536745289, 536745299, 536745337, 536745343, 536745353, 536745373, 536745397, 536745401, 536745409, 536745413, 536745467, 536745481, 536745487, 536745533, 536745553, 536745577, 536745617, 536745619, 536745631, 536745689, 536745721, 536745731, 536745761, 536745799, 536745841, 536745863, 536745899, 536745929, 536745943, 536745967, 536745971, 536745973, 536746027, 536746037, 536746051, 536746079, 536746097, 536746103, 536746109, 536746141, 536746159, 536746163, 536746201, 536746207, 536746247, 536746277, 536746319, 536746337, 536746349, 536746351, 536746363, 536746387, 536746391, 536746403, 536746417, 536746429, 536746433, 536746453, 536746477, 536746487, 536746499, 536746519, 536746543, 536746547, 536746583, 536746591, 536746601, 536746603, 536746633, 536746643, 536746649, 536746663, 536746669, 536746681, 536746709, 536746711, 536746757, 536746781, 536746829, 536746841, 536746843, 536746853, 536746871, 536746913, 536746919, 536746943, 536747011, 536747023, 536747033, 536747053, 536747077, 536747083, 536747129, 536747147, 536747153, 536747177, 536747179, 536747209, 536747213, 536747219, 536747221, 536747261, 536747279, 536747287, 536747293, 536747303, 536747311, 536747329, 536747381, 536747411, 536747413, 536747429, 536747437, 536747459, 536747461, 536747467, 536747503, 536747513, 536747521, 536747531, 536747539, 536747557, 536747569, 536747591, 536747597, 536747599, 536747639, 536747693, 536747767, 536747773, 536747791, 536747797, 536747807, 536747819, 536747821, 536747837, 536747867, 536747881, 536747909, 536747917, 536747927, 536747947, 536747971, 536747999, 536748071, 536748077, 536748109, 536748127, 536748133, 536748137, 536748151, 536748169, 536748209, 536748221, 536748227, 536748241, 536748283, 536748299, 536748313, 536748337, 536748379, 536748397, 536748431, 536748451, 536748469, 536748481, 536748503, 536748533, 536748551, 536748557, 536748581, 536748593, 536748683, 536748703, 536748713, 536748739, 536748743, 536748767, 536748811, 536748827, 536748847, 536748887, 536748929, 536748959, 536748997, 536749013, 536749033, 536749039, 536749043, 536749061, 536749063, 536749067, 536749093, 536749123, 536749133, 536749201, 536749219, 536749243, 536749247, 536749253, 536749267, 536749289, 536749333, 536749361, 536749379, 536749387, 536749399, 536749439, 536749457, 536749471, 536749481, 536749489, 536749519, 536749547, 536749571, 536749589, 536749637, 536749679, 536749691, 536749711, 536749723, 536749739, 536749747, 536749769, 536749783, 536749793, 536749813, 536749859, 536749883, 536749933, 536749979, 536749987, 536750003, 536750017, 536750021, 536750023, 536750047, 536750059, 536750063, 536750077, 536750087, 536750101, 536750107, 536750119, 536750141, 536750153, 536750167, 536750173, 536750219, 536750233, 536750243, 536750257, 536750303, 536750321, 536750341, 536750363, 536750377, 536750419, 536750429, 536750443, 536750449, 536750479, 536750507, 536750579, 536750587, 536750603, 536750611, 536750629, 536750633, 536750659, 536750689, 536750713, 536750737, 536750743, 536750759, 536750777, 536750783, 536750801, 536750899, 536750909, 536750927, 536750939, 536750941, 536750947, 536750953, 536750993, 536751031, 536751037, 536751071, 536751091, 536751107, 536751109, 536751113, 536751133, 536751167, 536751199, 536751203, 536751209, 536751247, 536751263, 536751361, 536751367, 536751389, 536751431, 536751451, 536751569, 536751581, 536751583, 536751599, 536751601, 536751619, 536751629, 536751641, 536751661, 536751689, 536751707, 536751737, 536751769, 536751773, 536751779, 536751781, 536751821, 536751827, 536751841, 536751877, 536751883, 536751959, 536751961, 536751967, 536751973, 536751983, 536752001, 536752009, 536752037, 536752043, 536752057, 536752091, 536752093, 536752103, 536752129, 536752133, 536752141, 536752193, 536752199, 536752201, 536752241, 536752243, 536752277, 536752309, 536752327, 536752367, 536752379, 536752393, 536752399, 536752409, 536752417, 536752421, 536752459, 536752487, 536752523, 536752589, 536752597, 536752613, 536752621, 536752637, 536752663, 536752709, 536752729, 536752739, 536752751, 536752753, 536752759, 536752837, 536752841, 536752873, 536752877, 536752891, 536752897, 536752901, 536752919, 536752921, 536752933, 536752943, 536752963, 536752999, 536753011, 536753027, 536753029, 536753033, 536753069, 536753081, 536753111, 536753123, 536753137, 536753167, 536753183, 536753237, 536753293, 536753299, 536753303, 536753309, 536753311, 536753317, 536753351, 536753377, 536753389, 536753407, 536753411, 536753417, 536753423, 536753429, 536753467, 536753473, 536753501, 536753519, 536753543, 536753587, 536753603, 536753611, 536753617, 536753627, 536753653, 536753687, 536753741, 536753759, 536753761, 536753773, 536753803, 536753839, 536753851, 536753863, 536753873, 536753879, 536753923, 536753939, 536753941, 536753957, 536753963, 536754007, 536754017, 536754061, 536754091, 536754103, 536754109, 536754131, 536754157, 536754167, 536754187, 536754191, 536754193, 536754223, 536754263, 536754287, 536754319, 536754331, 536754343, 536754347, 536754349, 536754401, 536754403, 536754419, 536754431, 536754457, 536754469, 536754499, 536754557, 536754563, 536754571, 536754587, 536754601, 536754607, 536754613, 536754637, 536754653, 536754697, 536754727, 536754761, 536754763, 536754791, 536754917, 536754929, 536754947, 536754961, 536754973, 536754983, 536754989, 536755001, 536755013, 536755031, 536755039, 536755069, 536755081, 536755091, 536755099, 536755103, 536755133, 536755147, 536755169, 536755199, 536755207, 536755259, 536755277, 536755333, 536755363, 536755447, 536755487, 536755493, 536755507, 536755517, 536755553, 536755621, 536755679, 536755691, 536755697, 536755699, 536755711, 536755717, 536755741, 536755759, 536755777, 536755847, 536755873, 536755883, 536755907, 536755913, 536755927, 536755931, 536755939, 536755949, 536755951, 536755993, 536756021, 536756029, 536756039, 536756047, 536756053, 536756071, 536756089, 536756111, 536756167, 536756173, 536756183, 536756197, 536756219, 536756243, 536756261, 536756287, 536756291, 536756323, 536756333, 536756393, 536756399, 536756417, 536756431, 536756443, 536756471, 536756489, 536756503, 536756509, 536756527, 536756533, 536756567, 536756569, 536756639, 536756653, 536756677, 536756683, 536756699, 536756711, 536756729, 536756771, 536756797, 536756813, 536756837, 536756849, 536756851, 536756863, 536756879, 536756921, 536756939, 536756977, 536757007, 536757037, 536757041, 536757059, 536757107, 536757121, 536757139, 536757149, 536757217, 536757223, 536757229, 536757241, 536757271, 536757283, 536757313, 536757323, 536757359, 536757383, 536757401, 536757407, 536757443, 536757449, 536757469, 536757479, 536757493, 536757497, 536757503, 536757517, 536757547, 536757583, 536757587, 536757589, 536757623, 536757629, 536757707, 536757713, 536757721, 536757731, 536757757, 536757791, 536757811, 536757827, 536757829, 536757841, 536757857, 536757887, 536757899, 536757919, 536757953, 536758043, 536758069, 536758081, 536758099, 536758109, 536758111, 536758147, 536758177, 536758181, 536758193, 536758213, 536758219, 536758231, 536758241, 536758247, 536758279, 536758301, 536758307, 536758363, 536758381, 536758393, 536758423, 536758447, 536758457, 536758463, 536758489, 536758543, 536758559, 536758591, 536758603, 536758631, 536758679, 536758681, 536758699, 536758727, 536758763, 536758771, 536758777, 536758787, 536758819, 536758841, 536758861, 536758877, 536758879, 536758897, 536758907, 536758913, 536758961, 536758967, 536759009, 536759011, 536759029, 536759033, 536759053, 536759081, 536759137, 536759189, 536759213, 536759261, 536759263, 536759281, 536759339, 536759369, 536759381, 536759383, 536759387, 536759393, 536759429, 536759449, 536759453, 536759473, 536759477, 536759501, 536759507, 536759527, 536759569, 536759609, 536759647, 536759653, 536759681, 536759687, 536759719, 536759723, 536759749, 536759771, 536759791, 536759807, 536759813, 536759833, 536759843, 536759863, 536759893, 536759903, 536759911, 536759917, 536759941, 536759969, 536760001, 536760017, 536760019, 536760031, 536760047, 536760053, 536760079, 536760121, 536760137, 536760139, 536760143, 536760173, 536760181, 536760197, 536760239, 536760281, 536760307, 536760337, 536760349, 536760373, 536760377, 536760401, 536760409, 536760437, 536760451, 536760463, 536760481, 536760487, 536760491, 536760493, 536760527, 536760541, 536760551, 536760563, 536760613, 536760617, 536760641, 536760647, 536760649, 536760661, 536760673, 536760713, 536760761, 536760803, 536760817, 536760823, 536760853, 536760859, 536760893, 536760947, 536760977, 536760989, 536761007, 536761013, 536761019, 536761031, 536761037, 536761061, 536761067, 536761073, 536761079, 536761123, 536761259, 536761271, 536761273, 536761283, 536761297, 536761333, 536761367, 536761397, 536761399, 536761411, 536761483, 536761487, 536761499, 536761507, 536761529, 536761543, 536761549, 536761567, 536761579, 536761583, 536761591, 536761597, 536761601, 536761613, 536761619, 536761661, 536761679, 536761681, 536761721, 536761727, 536761739, 536761777, 536761781, 536761789, 536761811, 536761829, 536761831, 536761853, 536761871, 536761877, 536761891, 536761903, 536761909, 536761933, 536761963, 536761987, 536762033, 536762047, 536762069, 536762087, 536762099, 536762101, 536762113, 536762129, 536762173, 536762221, 536762243, 536762273, 536762299, 536762309, 536762311, 536762327, 536762341, 536762351, 536762371, 536762377, 536762389, 536762399, 536762449, 536762461, 536762491, 536762497, 536762531, 536762533, 536762557, 536762563, 536762599, 536762621, 536762623, 536762651, 536762719, 536762741, 536762773, 536762801, 536762813, 536762819, 536762843, 536762867, 536762903, 536762917, 536762953, 536762957, 536762969, 536762999, 536763013, 536763041, 536763131, 536763133, 536763137, 536763163, 536763191, 536763193, 536763211, 536763223, 536763247, 536763257, 536763299, 536763307, 536763323, 536763343, 536763347, 536763391, 536763421, 536763427, 536763463, 536763473, 536763497, 536763499, 536763527, 536763529, 536763571, 536763587, 536763589, 536763607, 536763613, 536763649, 536763653, 536763659, 536763707, 536763713, 536763743, 536763749, 536763761, 536763767, 536763779, 536763781, 536763803, 536763809, 536763839, 536763881, 536763893, 536763901, 536763907, 536763911, 536763917, 536763943, 536763947, 536763959, 536763961, 536763971, 536763979, 536763991, 536764021, 536764027, 536764037, 536764043, 536764049, 536764099, 536764121, 536764139, 536764177, 536764181, 536764187, 536764211, 536764213, 536764223, 536764259, 536764301, 536764303, 536764309, 536764339, 536764433, 536764441, 536764447, 536764453, 536764463, 536764469, 536764471, 536764507, 536764517, 536764561, 536764609, 536764619, 536764651, 536764667, 536764717, 536764727, 536764733, 536764759, 536764807, 536764843, 536764849, 536764859, 536764873, 536764897, 536764903, 536764909, 536764927, 536764951, 536764967, 536764981, 536764993, 536764999, 536765003, 536765011, 536765027, 536765057, 536765059, 536765077, 536765107, 536765111, 536765137, 536765167, 536765171, 536765227, 536765269, 536765323, 536765407, 536765443, 536765459, 536765461, 536765477, 536765479, 536765507, 536765519, 536765587, 536765591, 536765629, 536765653, 536765717, 536765767, 536765773, 536765783, 536765797, 536765833, 536765909, 536765917, 536766001, 536766049, 536766059, 536766071, 536766079, 536766089, 536766127, 536766163, 536766173, 536766227, 536766239, 536766259, 536766311, 536766317, 536766337, 536766379, 536766401, 536766409, 536766421, 536766497, 536766499, 536766509, 536766521, 536766553, 536766569, 536766577, 536766599, 536766613, 536766623, 536766647, 536766673, 536766679, 536766691, 536766749, 536766751, 536766761, 536766779, 536766781, 536766787, 536766799, 536766803, 536766809, 536766821, 536766827, 536766869, 536766871, 536766889, 536766899, 536766911, 536766913, 536766943, 536766961, 536766983, 536767037, 536767051, 536767067, 536767079, 536767111, 536767117, 536767183, 536767193, 536767219, 536767241, 536767247, 536767249, 536767291, 536767369, 536767379, 536767397, 536767403, 536767433, 536767453, 536767463, 536767481, 536767489, 536767501, 536767523, 536767529, 536767549, 536767591, 536767601, 536767607, 536767661, 536767681, 536767691, 536767709, 536767717, 536767783, 536767787, 536767789, 536767793, 536767799, 536767801, 536767807, 536767817, 536767823, 536767849, 536767867, 536767901, 536767921, 536767927, 536767937, 536767939, 536767943, 536767981, 536768003, 536768033, 536768053, 536768077, 536768083, 536768087, 536768119, 536768129, 536768147, 536768161, 536768189, 536768201, 536768231, 536768233, 536768257, 536768327, 536768333, 536768339, 536768347, 536768363, 536768383, 536768417, 536768437, 536768447, 536768459, 536768497, 536768501, 536768521, 536768537, 536768539, 536768567, 536768587, 536768593, 536768611, 536768621, 536768633, 536768651, 536768653, 536768663, 536768671, 536768747, 536768767, 536768783, 536768797, 536768821, 536768831, 536768851, 536768861, 536768899, 536768909, 536768923, 536768941, 536768977, 536768987, 536768993, 536769047, 536769071, 536769109, 536769119, 536769127, 536769131, 536769137, 536769157, 536769161, 536769179, 536769199, 536769221, 536769223, 536769257, 536769263, 536769283, 536769293, 536769307, 536769313, 536769347, 536769353, 536769379, 536769403, 536769427, 536769461, 536769463, 536769479, 536769503, 536769533, 536769539, 536769593, 536769601, 536769631, 536769659, 536769661, 536769707, 536769721, 536769733, 536769757, 536769811, 536769833, 536769859, 536769889, 536769899, 536769913, 536769923, 536769953, 536769983, 536770009, 536770043, 536770051, 536770081, 536770103, 536770109, 536770111, 536770123, 536770147, 536770151, 536770181, 536770217, 536770219, 536770229, 536770243, 536770261, 536770271, 536770307, 536770313, 536770327, 536770357, 536770361, 536770397, 536770411, 536770441, 536770447, 536770469, 536770471, 536770511, 536770517, 536770519, 536770607, 536770627, 536770643, 536770649, 536770669, 536770681, 536770687, 536770709, 536770777, 536770789, 536770799, 536770813, 536770823, 536770841, 536770933, 536770943, 536770979, 536771017, 536771023, 536771041, 536771047, 536771051, 536771087, 536771089, 536771111, 536771119, 536771153, 536771239, 536771273, 536771317, 536771363, 536771377, 536771381, 536771399, 536771429, 536771471, 536771503, 536771507, 536771561, 536771581, 536771591, 536771593, 536771621, 536771657, 536771659, 536771689, 536771737, 536771743, 536771761, 536771791, 536771797, 536771801, 536771827, 536771843, 536771849, 536771903, 536771909, 536771929, 536771941, 536771947, 536771951, 536771981, 536772011, 536772031, 536772077, 536772079, 536772113, 536772143, 536772163, 536772169, 536772193, 536772199, 536772221, 536772227, 536772253, 536772259, 536772293, 536772317, 536772319, 536772329, 536772337, 536772349, 536772359, 536772361, 536772389, 536772391, 536772403, 536772427, 536772437, 536772469, 536772497, 536772541, 536772581, 536772583, 536772601, 536772641, 536772673, 536772679, 536772701, 536772707, 536772751, 536772757, 536772791, 536772823, 536772829, 536772833, 536772881, 536772917, 536772941, 536772953, 536772959, 536772961, 536772991, 536773001, 536773019, 536773033, 536773049, 536773063, 536773073, 536773087, 536773117, 536773169, 536773177, 536773217, 536773219, 536773231, 536773243, 536773297, 536773357, 536773373, 536773397, 536773399, 536773411, 536773451, 536773469, 536773537, 536773553, 536773591, 536773597, 536773607, 536773613, 536773619, 536773631, 536773639, 536773669, 536773697, 536773717, 536773751, 536773823, 536773829, 536773889, 536773901, 536773903, 536773943, 536773967, 536773969, 536774027, 536774039, 536774053, 536774071, 536774081, 536774093, 536774101, 536774113, 536774123, 536774131, 536774171, 536774177, 536774179, 536774209, 536774233, 536774243, 536774257, 536774291, 536774309, 536774323, 536774327, 536774333, 536774351, 536774383, 536774387, 536774401, 536774411, 536774423, 536774431, 536774467, 536774477, 536774479, 536774531, 536774597, 536774599, 536774629, 536774653, 536774657, 536774669, 536774687, 536774723, 536774741, 536774761, 536774789, 536774801, 536774837, 536774857, 536774893, 536774899, 536774923, 536774933, 536774939, 536774957, 536774971, 536775053, 536775079, 536775103, 536775133, 536775143, 536775163, 536775223, 536775233, 536775247, 536775259, 536775263, 536775269, 536775277, 536775293, 536775299, 536775347, 536775419, 536775427, 536775431, 536775461, 536775511, 536775521, 536775557, 536775559, 536775583, 536775607, 536775619, 536775637, 536775641, 536775647, 536775671, 536775677, 536775689, 536775709, 536775719, 536775763, 536775779, 536775791, 536775803, 536775829, 536775839, 536775851, 536775919, 536775931, 536775937, 536775989, 536775991, 536776013, 536776063, 536776091, 536776127, 536776147, 536776151, 536776153, 536776169, 536776171, 536776183, 536776187, 536776211, 536776213, 536776217, 536776321, 536776327, 536776333, 536776381, 536776397, 536776403, 536776423, 536776483, 536776489, 536776511, 536776529, 536776531, 536776567, 536776579, 536776589, 536776607, 536776609, 536776651, 536776663, 536776673, 536776727, 536776741, 536776813, 536776817, 536776837, 536776859, 536776861, 536776883, 536776897, 536776909, 536776937, 536776939, 536776973, 536777027, 536777029, 536777047, 536777053, 536777069, 536777089, 536777099, 536777123, 536777141, 536777147, 536777161, 536777173, 536777201, 536777209, 536777237, 536777239, 536777257, 536777309, 536777317, 536777323, 536777333, 536777357, 536777383, 536777387, 536777399, 536777441, 536777447, 536777467, 536777489, 536777513, 536777561, 536777573, 536777581, 536777621, 536777627, 536777629, 536777641, 536777651, 536777663, 536777671, 536777707, 536777719, 536777723, 536777743, 536777753, 536777767, 536777777, 536777789, 536777827, 536777837, 536777851, 536777893, 536777909, 536777939, 536777953, 536778007, 536778049, 536778059, 536778089, 536778097, 536778103, 536778119, 536778127, 536778169, 536778241, 536778293, 536778343, 536778353, 536778373, 536778379, 536778391, 536778413, 536778433, 536778461, 536778479, 536778497, 536778511, 536778611, 536778653, 536778677, 536778701, 536778707, 536778727, 536778731, 536778751, 536778769, 536778779, 536778793, 536778817, 536778821, 536778839, 536778841, 536778871, 536778887, 536778901, 536778917, 536778923, 536778989, 536778997, 536779027, 536779031, 536779069, 536779073, 536779081, 536779121, 536779123, 536779141, 536779153, 536779157, 536779163, 536779189, 536779207, 536779253, 536779259, 536779261, 536779297, 536779319, 536779351, 536779361, 536779417, 536779423, 536779427, 536779429, 536779447, 536779459, 536779489, 536779553, 536779571, 536779619, 536779657, 536779717, 536779753, 536779769, 536779781, 536779807, 536779823, 536779829, 536779843, 536779847, 536779871, 536779889, 536779891, 536779907, 536779909, 536779927, 536779939, 536780029, 536780119, 536780143, 536780147, 536780149, 536780183, 536780203, 536780207, 536780239, 536780243, 536780261, 536780263, 536780291, 536780327, 536780329, 536780341, 536780347, 536780369, 536780393, 536780429, 536780441, 536780471, 536780477, 536780513, 536780521, 536780537, 536780539, 536780557, 536780591, 536780599, 536780641, 536780683, 536780687, 536780701, 536780731, 536780759, 536780821, 536780833, 536780857, 536780863, 536780917, 536780929, 536780947, 536780953, 536780957, 536781059, 536781067, 536781071, 536781079, 536781109, 536781127, 536781131, 536781149, 536781181, 536781187, 536781209, 536781227, 536781247, 536781263, 536781269, 536781281, 536781283, 536781317, 536781359, 536781361, 536781373, 536781391, 536781431, 536781433, 536781437, 536781451, 536781491, 536781499, 536781547, 536781551, 536781571, 536781577, 536781601, 536781617, 536781631, 536781643, 536781649, 536781671, 536781701, 536781703, 536781743, 536781767, 536781769, 536781781, 536781803, 536781841, 536781859, 536781913, 536781923, 536781989, 536781991, 536782009, 536782031, 536782069, 536782109, 536782117, 536782121, 536782171, 536782219, 536782283, 536782297, 536782307, 536782321, 536782343, 536782417, 536782423, 536782427, 536782447, 536782481, 536782517, 536782541, 536782553, 536782559, 536782567, 536782573, 536782607, 536782613, 536782621, 536782679, 536782681, 536782691, 536782709, 536782711, 536782751, 536782777, 536782787, 536782789, 536782811, 536782819, 536782861, 536782867, 536782877, 536782891, 536782907, 536782921, 536782931, 536782937, 536782951, 536782957, 536782963, 536782991, 536782997, 536783017, 536783021, 536783033, 536783047, 536783059, 536783063, 536783101, 536783113, 536783123, 536783141, 536783167, 536783179, 536783209, 536783227, 536783249, 536783251, 536783281, 536783293, 536783323, 536783393, 536783413, 536783441, 536783477, 536783503, 536783509, 536783537, 536783549, 536783563, 536783627, 536783651, 536783657, 536783671, 536783761, 536783771, 536783777, 536783783, 536783887, 536783977, 536783981, 536784019, 536784037, 536784041, 536784071, 536784077, 536784089, 536784091, 536784103, 536784119, 536784121, 536784139, 536784161, 536784167, 536784217, 536784233, 536784263, 536784289, 536784293, 536784319, 536784329, 536784337, 536784349, 536784359, 536784379, 536784427, 536784433, 536784449, 536784481, 536784487, 536784491, 536784527, 536784529, 536784541, 536784559, 536784581, 536784617, 536784629, 536784667, 536784719, 536784733, 536784739, 536784757, 536784761, 536784763, 536784767, 536784793, 536784817, 536784823, 536784847, 536784869, 536784887, 536784893, 536784907, 536784929, 536784947, 536784949, 536784959, 536784977, 536785019, 536785037, 536785049, 536785087, 536785103, 536785111, 536785129, 536785141, 536785231, 536785241, 536785267, 536785289, 536785313, 536785349, 536785351, 536785357, 536785373, 536785391, 536785393, 536785411, 536785423, 536785453, 536785471, 536785507, 536785517, 536785519, 536785531, 536785583, 536785619, 536785699, 536785703, 536785721, 536785729, 536785741, 536785747, 536785759, 536785771, 536785783, 536785793, 536785819, 536785831, 536785849, 536785859, 536785861, 536785867, 536785889, 536785903, 536785979, 536786011, 536786017, 536786023, 536786053, 536786077, 536786137, 536786171, 536786179, 536786197, 536786287, 536786333, 536786353, 536786363, 536786377, 536786387, 536786399, 536786527, 536786533, 536786557, 536786563, 536786567, 536786573, 536786599, 536786603, 536786609, 536786617, 536786623, 536786629, 536786681, 536786683, 536786693, 536786699, 536786711, 536786749, 536786753, 536786791, 536786797, 536786837, 536786851, 536786881, 536786891, 536786893, 536786923, 536786927, 536786941, 536786947, 536786977, 536786983, 536786989, 536787001, 536787011, 536787059, 536787109, 536787137, 536787143, 536787149, 536787151, 536787161, 536787197, 536787269, 536787299, 536787301, 536787337, 536787343, 536787353, 536787371, 536787389, 536787397, 536787401, 536787421, 536787439, 536787463, 536787467, 536787473, 536787479, 536787499, 536787521, 536787523, 536787557, 536787577, 536787583, 536787607, 536787637, 536787653, 536787683, 536787697, 536787701, 536787721, 536787781, 536787787, 536787803, 536787821, 536787859, 536787871, 536787917, 536787919, 536787931, 536787947, 536787967, 536787991, 536788001, 536788003, 536788097, 536788117, 536788123, 536788127, 536788159, 536788201, 536788211, 536788223, 536788229, 536788249, 536788253, 536788271, 536788279, 536788309, 536788321, 536788337, 536788381, 536788387, 536788411, 536788423, 536788477, 536788493, 536788507, 536788531, 536788543, 536788597, 536788621, 536788673, 536788727, 536788793, 536788807, 536788831, 536788867, 536788877, 536788891, 536788919, 536788939, 536788951, 536788999, 536789027, 536789041, 536789047, 536789051, 536789063, 536789069, 536789089, 536789107, 536789117, 536789129, 536789207, 536789213, 536789233, 536789237, 536789291, 536789293, 536789299, 536789329, 536789359, 536789369, 536789371, 536789389, 536789401, 536789413, 536789423, 536789443, 536789489, 536789531, 536789537, 536789543, 536789551, 536789557, 536789563, 536789579, 536789581, 536789587, 536789593, 536789609, 536789621, 536789629, 536789711, 536789717, 536789719, 536789723, 536789779, 536789809, 536789819, 536789833, 536789837, 536789849, 536789857, 536789887, 536789899, 536789921, 536789927, 536789983, 536789993, 536790013, 536790019, 536790041, 536790127, 536790139, 536790151, 536790167, 536790253, 536790257, 536790259, 536790311, 536790329, 536790349, 536790383, 536790407, 536790439, 536790467, 536790469, 536790473, 536790517, 536790539, 536790563, 536790587, 536790689, 536790697, 536790733, 536790757, 536790763, 536790803, 536790809, 536790811, 536790833, 536790847, 536790853, 536790889, 536790913, 536790923, 536790937, 536790959, 536790977, 536790979, 536791001, 536791039, 536791067, 536791081, 536791103, 536791117, 536791121, 536791127, 536791139, 536791141, 536791163, 536791187, 536791193, 536791207, 536791217, 536791237, 536791267, 536791271, 536791279, 536791289, 536791291, 536791327, 536791331, 536791349, 536791351, 536791369, 536791373, 536791379, 536791391, 536791429, 536791433, 536791441, 536791447, 536791459, 536791469, 536791481, 536791487, 536791511, 536791513, 536791547, 536791573, 536791589, 536791601, 536791613, 536791621, 536791657, 536791681, 536791709, 536791741, 536791777, 536791799, 536791811, 536791817, 536791831, 536791861, 536791867, 536791891, 536791901, 536791903, 536791951, 536791987, 536792023, 536792027, 536792107, 536792159, 536792171, 536792173, 536792219, 536792227, 536792257, 536792279, 536792293, 536792303, 536792309, 536792329, 536792353, 536792359, 536792369, 536792401, 536792413, 536792461, 536792479, 536792489, 536792491, 536792513, 536792519, 536792567, 536792569, 536792573, 536792587, 536792591, 536792611, 536792647, 536792671, 536792681, 536792689, 536792713, 536792771, 536792777, 536792783, 536792803, 536792819, 536792849, 536792887, 536792899, 536792939, 536793011, 536793013, 536793109, 536793167, 536793181, 536793199, 536793221, 536793233, 536793253, 536793259, 536793307, 536793311, 536793317, 536793331, 536793379, 536793391, 536793401, 536793407, 536793431, 536793463, 536793497, 536793503, 536793511, 536793557, 536793559, 536793563, 536793577, 536793589, 536793599, 536793629, 536793637, 536793659, 536793707, 536793709, 536793713, 536793727, 536793779, 536793787, 536793791, 536793797, 536793809, 536793823, 536793827, 536793863, 536793869, 536793899, 536793931, 536793967, 536793991, 536794127, 536794133, 536794207, 536794211, 536794253, 536794259, 536794267, 536794273, 536794277, 536794301, 536794303, 536794337, 536794351, 536794369, 536794399, 536794417, 536794421, 536794429, 536794439, 536794469, 536794501, 536794507, 536794519, 536794529, 536794537, 536794541, 536794603, 536794619, 536794637, 536794649, 536794679, 536794681, 536794691, 536794721, 536794747, 536794751, 536794789, 536794801, 536794813, 536794823, 536794829, 536794847, 536794871, 536794877, 536794879, 536794889, 536794931, 536794933, 536794939, 536794957, 536794969, 536794981, 536794991, 536794997, 536795029, 536795053, 536795071, 536795099, 536795141, 536795153, 536795159, 536795173, 536795177, 536795209, 536795219, 536795221, 536795227, 536795267, 536795269, 536795291, 536795317, 536795327, 536795341, 536795431, 536795477, 536795489, 536795509, 536795527, 536795537, 536795549, 536795561, 536795563, 536795569, 536795603, 536795627, 536795681, 536795683, 536795719, 536795737, 536795773, 536795803, 536795839, 536795851, 536795867, 536795869, 536795891, 536795921, 536795951, 536795957, 536795993, 536796019, 536796023, 536796049, 536796079, 536796089, 536796121, 536796163, 536796187, 536796203, 536796223, 536796257, 536796269, 536796289, 536796317, 536796319, 536796329, 536796343, 536796373, 536796427, 536796431, 536796433, 536796451, 536796479, 536796499, 536796511, 536796553, 536796571, 536796577, 536796581, 536796599, 536796643, 536796677, 536796679, 536796727, 536796731, 536796751, 536796761, 536796779, 536796847, 536796857, 536796859, 536796901, 536796943, 536796983, 536797039, 536797057, 536797067, 536797087, 536797103, 536797109, 536797111, 536797141, 536797189, 536797201, 536797213, 536797243, 536797267, 536797273, 536797319, 536797361, 536797363, 536797403, 536797411, 536797441, 536797463, 536797477, 536797487, 536797489, 536797523, 536797531, 536797553, 536797561, 536797571, 536797607, 536797649, 536797663, 536797687, 536797693, 536797697, 536797711, 536797717, 536797733, 536797741, 536797757, 536797771, 536797777, 536797819, 536797837, 536797867, 536797879, 536797883, 536797949, 536798029, 536798047, 536798057, 536798099, 536798147, 536798153, 536798159, 536798177, 536798189, 536798191, 536798209, 536798261, 536798293, 536798333, 536798347, 536798351, 536798359, 536798371, 536798407, 536798441, 536798447, 536798459, 536798473, 536798491, 536798501, 536798533, 536798539, 536798557, 536798567, 536798593, 536798651, 536798683, 536798693, 536798723, 536798737, 536798741, 536798747, 536798753, 536798767, 536798803, 536798827, 536798833, 536798879, 536798881, 536798921, 536798989, 536799031, 536799037, 536799041, 536799049, 536799061, 536799073, 536799083, 536799113, 536799119, 536799161, 536799181, 536799187, 536799223, 536799227, 536799253, 536799269, 536799271, 536799299, 536799311, 536799331, 536799337, 536799353, 536799359, 536799397, 536799421, 536799437, 536799443, 536799449, 536799481, 536799499, 536799509, 536799517, 536799521, 536799559, 536799583, 536799619, 536799629, 536799661, 536799671, 536799677, 536799743, 536799827, 536799841, 536799859, 536799881, 536799919, 536799929, 536799931, 536799941, 536799943, 536799983, 536799997, 536800001, 536800009, 536800021, 536800031, 536800051, 536800067, 536800081, 536800097, 536800111, 536800127, 536800139, 536800157, 536800163, 536800189, 536800213, 536800219, 536800241, 536800273, 536800283, 536800307, 536800351, 536800391, 536800409, 536800417, 536800423, 536800457, 536800493, 536800499, 536800507, 536800543, 536800567, 536800573, 536800601, 536800633, 536800637, 536800651, 536800697, 536800727, 536800729, 536800829, 536800861, 536800871, 536800937, 536800969, 536800973, 536800981, 536801003, 536801009, 536801017, 536801021, 536801033, 536801051, 536801077, 536801081, 536801113, 536801123, 536801171, 536801249, 536801261, 536801269, 536801273, 536801327, 536801329, 536801341, 536801351, 536801359, 536801381, 536801383, 536801389, 536801399, 536801467, 536801497, 536801519, 536801539, 536801563, 536801581, 536801591, 536801593, 536801597, 536801599, 536801609, 536801633, 536801653, 536801659, 536801689, 536801719, 536801731, 536801767, 536801821, 536801827, 536801833, 536801849, 536801857, 536801893, 536801929, 536801933, 536801939, 536801999, 536802029, 536802043, 536802059, 536802121, 536802127, 536802137, 536802157, 536802163, 536802187, 536802223, 536802247, 536802281, 536802317, 536802323, 536802337, 536802347, 536802349, 536802377, 536802389, 536802419, 536802503, 536802527, 536802533, 536802547, 536802599, 536802601, 536802631, 536802647, 536802683, 536802703, 536802713, 536802719, 536802733, 536802737, 536802781, 536802787, 536802803, 536802809, 536802811, 536802821, 536802823, 536802857, 536802869, 536802883, 536802887, 536802899, 536802901, 536802923, 536802941, 536802943, 536802967, 536802979, 536803031, 536803039, 536803123, 536803139, 536803151, 536803177, 536803213, 536803229, 536803231, 536803259, 536803291, 536803303, 536803387, 536803391, 536803429, 536803439, 536803457, 536803459, 536803481, 536803483, 536803489, 536803507, 536803517, 536803549, 536803559, 536803571, 536803583, 536803621, 536803627, 536803649, 536803651, 536803661, 536803667, 536803669, 536803691, 536803753, 536803763, 536803783, 536803793, 536803811, 536803819, 536803823, 536803829, 536803837, 536803879, 536803907, 536803909, 536803937, 536803957, 536803987, 536803999, 536804011, 536804101, 536804129, 536804161, 536804197, 536804221, 536804227, 536804231, 536804263, 536804269, 536804287, 536804311, 536804327, 536804347, 536804351, 536804357, 536804363, 536804369, 536804377, 536804407, 536804419, 536804459, 536804503, 536804507, 536804519, 536804581, 536804591, 536804623, 536804627, 536804651, 536804683, 536804687, 536804707, 536804831, 536804837, 536804861, 536804867, 536804881, 536804893, 536804911, 536804953, 536804963, 536805011, 536805019, 536805023, 536805029, 536805067, 536805097, 536805173, 536805193, 536805223, 536805263, 536805289, 536805317, 536805323, 536805343, 536805383, 536805389, 536805397, 536805403, 536805419, 536805439, 536805449, 536805559, 536805587, 536805649, 536805697, 536805701, 536805713, 536805721, 536805739, 536805749, 536805751, 536805757, 536805767, 536805791, 536805799, 536805817, 536805853, 536805887, 536805949, 536805961, 536805967, 536806007, 536806009, 536806019, 536806021, 536806033, 536806043, 536806087, 536806103, 536806117, 536806133, 536806139, 536806159, 536806169, 536806253, 536806273, 536806279, 536806321, 536806337, 536806339, 536806349, 536806351, 536806409, 536806423, 536806469, 536806477, 536806483, 536806489, 536806493, 536806511, 536806519, 536806531, 536806541, 536806547, 536806553, 536806607, 536806609, 536806651, 536806663, 536806687, 536806703, 536806763, 536806769, 536806783, 536806813, 536806861, 536806877, 536806901, 536806903, 536806939, 536806961, 536807003, 536807017, 536807027, 536807039, 536807093, 536807099, 536807107, 536807153, 536807177, 536807221, 536807261, 536807269, 536807273, 536807287, 536807303, 536807309, 536807321, 536807333, 536807339, 536807347, 536807353, 536807387, 536807393, 536807407, 536807431, 536807443, 536807461, 536807473, 536807543, 536807569, 536807573, 536807587, 536807599, 536807611, 536807651, 536807653, 536807659, 536807717, 536807767, 536807773, 536807801, 536807807, 536807837, 536807839, 536807849, 536807891, 536807899, 536807977, 536807987, 536808023, 536808029, 536808037, 536808043, 536808047, 536808049, 536808071, 536808119, 536808127, 536808143, 536808149, 536808161, 536808169, 536808179, 536808191, 536808229, 536808253, 536808281, 536808287, 536808313, 536808319, 536808343, 536808353, 536808361, 536808403, 536808413, 536808443, 536808451, 536808457, 536808521, 536808527, 536808551, 536808557, 536808563, 536808583, 536808697, 536808709, 536808773, 536808781, 536808791, 536808809, 536808817, 536808823, 536808829, 536808851, 536808887, 536808893, 536808901, 536808971, 536808997, 536809019, 536809027, 536809079, 536809087, 536809093, 536809123, 536809151, 536809171, 536809183, 536809201, 536809241, 536809253, 536809277, 536809279, 536809297, 536809313, 536809319, 536809321, 536809331, 536809363, 536809381, 536809409, 536809417, 536809453, 536809457, 536809519, 536809541, 536809591, 536809613, 536809649, 536809753, 536809759, 536809781, 536809783, 536809817, 536809841, 536809853, 536809859, 536809879, 536809883, 536809909, 536809927, 536809939, 536809957, 536809961, 536809991, 536809993, 536810011, 536810033, 536810047, 536810063, 536810093, 536810101, 536810107, 536810159, 536810189, 536810191, 536810221, 536810227, 536810243, 536810273, 536810297, 536810321, 536810347, 536810381, 536810383, 536810399, 536810459, 536810471, 536810489, 536810507, 536810557, 536810567, 536810627, 536810647, 536810693, 536810699, 536810713, 536810719, 536810723, 536810737, 536810741, 536810759, 536810773, 536810801, 536810809, 536810821, 536810831, 536810863, 536810873, 536810881, 536810891, 536810893, 536810899, 536810903, 536810917, 536810947, 536810959, 536810993, 536810999, 536811001, 536811019, 536811029, 536811071, 536811089, 536811109, 536811127, 536811131, 536811217, 536811229, 536811259, 536811277, 536811307, 536811337, 536811343, 536811367, 536811377, 536811391, 536811433, 536811479, 536811481, 536811491, 536811511, 536811523, 536811553, 536811607, 536811629, 536811659, 536811661, 536811679, 536811701, 536811707, 536811733, 536811749, 536811761, 536811763, 536811767, 536811787, 536811809, 536811823, 536811833, 536811859, 536811929, 536811949, 536811971, 536811991, 536812007, 536812033, 536812049, 536812061, 536812093, 536812103, 536812117, 536812121, 536812181, 536812201, 536812217, 536812219, 536812223, 536812313, 536812319, 536812321, 536812361, 536812421, 536812439, 536812457, 536812459, 536812477, 536812487, 536812499, 536812531, 536812537, 536812541, 536812561, 536812583, 536812597, 536812603, 536812651, 536812721, 536812733, 536812751, 536812769, 536812807, 536812813, 536812819, 536812831, 536812853, 536812867, 536812889, 536812891, 536812931, 536812937, 536812943, 536812951, 536812967, 536813027, 536813083, 536813087, 536813089, 536813129, 536813149, 536813209, 536813269, 536813323, 536813339, 536813357, 536813363, 536813371, 536813383, 536813401, 536813477, 536813489, 536813507, 536813509, 536813531, 536813549, 536813551, 536813561, 536813569, 536813597, 536813609, 536813653, 536813657, 536813663, 536813729, 536813731, 536813741, 536813759, 536813789, 536813791, 536813803, 536813819, 536813857, 536813869, 536813891, 536813899, 536813903, 536813911, 536813917, 536813923, 536813933, 536813957, 536813987, 536814013, 536814017, 536814053, 536814067, 536814077, 536814079, 536814097, 536814101, 536814121, 536814127, 536814133, 536814139, 536814149, 536814169, 536814217, 536814221, 536814281, 536814323, 536814347, 536814349, 536814359, 536814371, 536814373, 536814403, 536814409, 536814419, 536814431, 536814449, 536814461, 536814497, 536814527, 536814539, 536814547, 536814571, 536814601, 536814637, 536814659, 536814671, 536814673, 536814689, 536814703, 536814713, 536814721, 536814731, 536814739, 536814767, 536814769, 536814799, 536814829, 536814841, 536814869, 536814913, 536814931, 536814959, 536814977, 536814979, 536814983, 536814989, 536815007, 536815031, 536815039, 536815057, 536815073, 536815133, 536815141, 536815163, 536815177, 536815187, 536815267, 536815319, 536815327, 536815339, 536815343, 536815361, 536815369, 536815387, 536815393, 536815399, 536815441, 536815459, 536815463, 536815471, 536815523, 536815537, 536815547, 536815577, 536815589, 536815603, 536815621, 536815633, 536815639, 536815649, 536815661, 536815663, 536815667, 536815673, 536815753, 536815757, 536815771, 536815787, 536815831, 536815841, 536815843, 536815847, 536815891, 536815901, 536815957, 536815963, 536815967, 536815969, 536815973, 536816003, 536816009, 536816047, 536816083, 536816099, 536816107, 536816143, 536816149, 536816201, 536816207, 536816219, 536816221, 536816233, 536816263, 536816317, 536816339, 536816351, 536816353, 536816363, 536816381, 536816393, 536816407, 536816411, 536816417, 536816437, 536816503, 536816509, 536816549, 536816551, 536816591, 536816611, 536816617, 536816641, 536816689, 536816699, 536816713, 536816719, 536816723, 536816759, 536816779, 536816809, 536816821, 536816843, 536816857, 536816879, 536816887, 536816893, 536816911, 536816933, 536816947, 536816953, 536816971, 536816983, 536817037, 536817077, 536817103, 536817119, 536817131, 536817157, 536817161, 536817163, 536817187, 536817233, 536817251, 536817257, 536817271, 536817287, 536817293, 536817299, 536817301, 536817311, 536817329, 536817331, 536817361, 536817371, 536817373, 536817389, 536817427, 536817451, 536817487, 536817499, 536817509, 536817553, 536817557, 536817559, 536817569, 536817703, 536817707, 536817709, 536817737, 536817767, 536817781, 536817791, 536817833, 536817859, 536817863, 536817881, 536817937, 536817947, 536817949, 536817989, 536817991, 536817997, 536818019, 536818031, 536818057, 536818099, 536818109, 536818111, 536818123, 536818141, 536818147, 536818151, 536818157, 536818201, 536818241, 536818277, 536818279, 536818301, 536818309, 536818313, 536818319, 536818339, 536818357, 536818411, 536818423, 536818463, 536818487, 536818501, 536818511, 536818517, 536818531, 536818543, 536818547, 536818559, 536818561, 536818573, 536818577, 536818589, 536818603, 536818613, 536818621, 536818627, 536818637, 536818649, 536818651, 536818663, 536818687, 536818691, 536818721, 536818729, 536818753, 536818771, 536818783, 536818831, 536818871, 536818879, 536818889, 536818901, 536818921, 536818937, 536818943, 536818969, 536819039, 536819069, 536819077, 536819083, 536819089, 536819099, 536819113, 536819119, 536819159, 536819161, 536819167, 536819177, 536819189, 536819197, 536819201, 536819233, 536819263, 536819291, 536819317, 536819323, 536819363, 536819399, 536819401, 536819429, 536819501, 536819509, 536819513, 536819527, 536819537, 536819579, 536819599, 536819617, 536819627, 536819639, 536819687, 536819707, 536819713, 536819719, 536819743, 536819771, 536819797, 536819809, 536819821, 536819837, 536819849, 536819851, 536819861, 536819873, 536819911, 536819989, 536819993, 536820001, 536820061, 536820107, 536820113, 536820157, 536820181, 536820187, 536820217, 536820223, 536820259, 536820289, 536820311, 536820341, 536820367, 536820379, 536820419, 536820439, 536820461, 536820467, 536820497, 536820533, 536820593, 536820607, 536820617, 536820631, 536820637, 536820659, 536820673, 536820689, 536820709, 536820727, 536820743, 536820773, 536820787, 536820803, 536820857, 536820899, 536820953, 536820961, 536820983, 536820997, 536821027, 536821031, 536821067, 536821069, 536821093, 536821097, 536821099, 536821111, 536821139, 536821147, 536821163, 536821171, 536821199, 536821237, 536821261, 536821277, 536821279, 536821283, 536821309, 536821319, 536821339, 536821361, 536821379, 536821387, 536821399, 536821409, 536821423, 536821447, 536821457, 536821469, 536821499, 536821501, 536821531, 536821547, 536821553, 536821583, 536821591, 536821603, 536821627, 536821657, 536821693, 536821711, 536821717, 536821739, 536821781, 536821783, 536821787, 536821793, 536821843, 536821853, 536821861, 536821867, 536821891, 536821913, 536821919, 536822017, 536822087, 536822113, 536822123, 536822177, 536822183, 536822227, 536822239, 536822261, 536822263, 536822303, 536822339, 536822353, 536822357, 536822383, 536822431, 536822437, 536822477, 536822479, 536822483, 536822519, 536822521, 536822537, 536822563, 536822591, 536822609, 536822623, 536822639, 536822747, 536822749, 536822761, 536822779, 536822807, 536822837, 536822863, 536822911, 536822927, 536822981, 536823019, 536823037, 536823041, 536823043, 536823083, 536823107, 536823113, 536823179, 536823191, 536823193, 536823211, 536823251, 536823257, 536823299, 536823307, 536823341, 536823361, 536823409, 536823461, 536823479, 536823487, 536823493, 536823527, 536823541, 536823571, 536823589, 536823593, 536823647, 536823659, 536823667, 536823673, 536823719, 536823757, 536823761, 536823779, 536823809, 536823817, 536823821, 536823839, 536823883, 536823923, 536824003, 536824031, 536824049, 536824051, 536824063, 536824069, 536824073, 536824097, 536824103, 536824151, 536824153, 536824199, 536824213, 536824297, 536824331, 536824349, 536824381, 536824391, 536824403, 536824429, 536824433, 536824447, 536824469, 536824523, 536824529, 536824559, 536824571, 536824579, 536824627, 536824637, 536824643, 536824649, 536824667, 536824697, 536824711, 536824747, 536824763, 536824789, 536824801, 536824867, 536824877, 536824889, 536824901, 536824907, 536824909, 536824913, 536824927, 536824933, 536824961, 536824973, 536825027, 536825039, 536825041, 536825053, 536825059, 536825087, 536825101, 536825123, 536825131, 536825153, 536825203, 536825207, 536825209, 536825251, 536825273, 536825279, 536825281, 536825299, 536825323, 536825329, 536825339, 536825353, 536825363, 536825369, 536825389, 536825407, 536825441, 536825477, 536825501, 536825537, 536825539, 536825557, 536825573, 536825581, 536825599, 536825603, 536825623, 536825629, 536825647, 536825659, 536825671, 536825683, 536825689, 536825701, 536825713, 536825761, 536825767, 536825789, 536825831, 536825843, 536825879, 536825903, 536825917, 536825929, 536825951, 536826001, 536826067, 536826091, 536826097, 536826107, 536826109, 536826113, 536826127, 536826131, 536826137, 536826139, 536826193, 536826217, 536826239, 536826253, 536826259, 536826263, 536826293, 536826299, 536826313, 536826359, 536826397, 536826443, 536826457, 536826461, 536826467, 536826481, 536826517, 536826533, 536826539, 536826541, 536826547, 536826553, 536826617, 536826623, 536826637, 536826643, 536826649, 536826671, 536826679, 536826683, 536826751, 536826793, 536826827, 536826839, 536826863, 536826869, 536826887, 536826911, 536826919, 536826943, 536826949, 536826959, 536826989, 536827001, 536827009, 536827013, 536827051, 536827087, 536827097, 536827099, 536827111, 536827129, 536827133, 536827141, 536827147, 536827157, 536827163, 536827169, 536827171, 536827189, 536827211, 536827223, 536827229, 536827303, 536827367, 536827393, 536827397, 536827399, 536827427, 536827433, 536827471, 536827531, 536827537, 536827541, 536827553, 536827579, 536827583, 536827601, 536827639, 536827721, 536827723, 536827747, 536827769, 536827777, 536827789, 536827793, 536827799, 536827807, 536827813, 536827817, 536827829, 536827849, 536827901, 536827979, 536827997, 536828009, 536828011, 536828063, 536828087, 536828093, 536828101, 536828113, 536828141, 536828183, 536828213, 536828221, 536828239, 536828249, 536828263, 536828269, 536828323, 536828351, 536828353, 536828359, 536828371, 536828377, 536828381, 536828399, 536828417, 536828419, 536828423, 536828459, 536828471, 536828497, 536828587, 536828623, 536828627, 536828639, 536828651, 536828693, 536828701, 536828711, 536828713, 536828791, 536828797, 536828801, 536828827, 536828833, 536828849, 536828879, 536828881, 536828959, 536829101, 536829119, 536829149, 536829151, 536829169, 536829193, 536829197, 536829203, 536829283, 536829289, 536829299, 536829317, 536829323, 536829343, 536829389, 536829467, 536829497, 536829539, 536829541, 536829547, 536829589, 536829703, 536829721, 536829737, 536829749, 536829751, 536829827, 536829841, 536829901, 536829919, 536829983, 536829989, 536830027, 536830061, 536830067, 536830109, 536830121, 536830157, 536830159, 536830171, 536830181, 536830183, 536830207, 536830211, 536830241, 536830249, 536830297, 536830309, 536830337, 536830363, 536830391, 536830421, 536830423, 536830429, 536830451, 536830457, 536830477, 536830523, 536830529, 536830531, 536830543, 536830577, 536830583, 536830621, 536830639, 536830667, 536830673, 536830681, 536830691, 536830703, 536830717, 536830727, 536830729, 536830783, 536830829, 536830837, 536830843, 536830859, 536830873, 536830897, 536830901, 536830939, 536830949, 536830961, 536830967, 536830979, 536831023, 536831033, 536831041, 536831051, 536831089, 536831101, 536831137, 536831143, 536831167, 536831177, 536831231, 536831233, 536831249, 536831279, 536831297, 536831299, 536831303, 536831333, 536831341, 536831359, 536831381, 536831401, 536831411, 536831419, 536831429, 536831437, 536831443, 536831447, 536831459, 536831527, 536831539, 536831549, 536831551, 536831591, 536831641, 536831663, 536831683, 536831693, 536831741, 536831747, 536831773, 536831783, 536831803, 536831807, 536831809, 536831837, 536831839, 536831857, 536831863, 536831873, 536831879, 536831917, 536831941, 536831957, 536831969, 536831989, 536831993, 536832007, 536832011, 536832041, 536832077, 536832089, 536832113, 536832119, 536832133, 536832139, 536832157, 536832169, 536832203, 536832221, 536832227, 536832281, 536832287, 536832293, 536832299, 536832313, 536832337, 536832343, 536832347, 536832353, 536832379, 536832383, 536832407, 536832419, 536832433, 536832451, 536832493, 536832497, 536832523, 536832551, 536832559, 536832577, 536832607, 536832617, 536832643, 536832649, 536832661, 536832671, 536832679, 536832697, 536832713, 536832733, 536832767, 536832773, 536832841, 536832853, 536832871, 536832883, 536832893, 536832929, 536832971, 536832977, 536832979, 536832997, 536833009, 536833019, 536833051, 536833067, 536833081, 536833097, 536833177, 536833183, 536833189, 536833217, 536833261, 536833273, 536833303, 536833307, 536833331, 536833337, 536833373, 536833399, 536833411, 536833439, 536833447, 536833469, 536833567, 536833571, 536833573, 536833589, 536833601, 536833613, 536833621, 536833643, 536833651, 536833673, 536833729, 536833741, 536833753, 536833763, 536833783, 536833811, 536833831, 536833867, 536833879, 536833901, 536833903, 536833919, 536833963, 536833991, 536834003, 536834009, 536834017, 536834057, 536834063, 536834093, 536834131, 536834149, 536834203, 536834209, 536834213, 536834251, 536834267, 536834269, 536834273, 536834293, 536834299, 536834323, 536834327, 536834377, 536834401, 536834437, 536834477, 536834503, 536834527, 536834537, 536834549, 536834593, 536834603, 536834647, 536834671, 536834681, 536834737, 536834741, 536834761, 536834777, 536834791, 536834807, 536834821, 536834839, 536834899, 536834983, 536835001, 536835007, 536835023, 536835031, 536835053, 536835071, 536835083, 536835107, 536835133, 536835149, 536835193, 536835199, 536835227, 536835241, 536835307, 536835373, 536835389, 536835391, 536835413, 536835419, 536835491, 536835517, 536835529, 536835547, 536835581, 536835583, 536835623, 536835641, 536835643, 536835659, 536835661, 536835697, 536835721, 536835727, 536835737, 536835743, 536835751, 536835763, 536835787, 536835811, 536835821, 536835839, 536835851, 536835881, 536835917, 536835947, 536835953, 536835967, 536835983, 536835989, 536836049, 536836057, 536836061, 536836063, 536836129, 536836133, 536836141, 536836187, 536836189, 536836243, 536836253, 536836259, 536836271, 536836273, 536836283, 536836291, 536836327, 536836343, 536836357, 536836409, 536836423, 536836451, 536836453, 536836459, 536836463, 536836483, 536836511, 536836543, 536836549, 536836571, 536836649, 536836669, 536836673, 536836681, 536836687, 536836691, 536836723, 536836733, 536836757, 536836771, 536836801, 536836823, 536836831, 536836847, 536836879, 536836891, 536836901, 536836907, 536836913, 536836921, 536836933, 536836981, 536836987, 536836991, 536837003, 536837023, 536837057, 536837117, 536837141, 536837167, 536837173, 536837219, 536837221, 536837233, 536837263, 536837269, 536837291, 536837333, 536837341, 536837363, 536837369, 536837417, 536837423, 536837429, 536837437, 536837459, 536837467, 536837491, 536837501, 536837507, 536837513, 536837527, 536837537, 536837569, 536837573, 536837579, 536837593, 536837597, 536837621, 536837629, 536837683, 536837711, 536837731, 536837783, 536837803, 536837809, 536837827, 536837831, 536837891, 536837893, 536837897, 536837923, 536837981, 536837993, 536838011, 536838013, 536838037, 536838073, 536838077, 536838079, 536838083, 536838097, 536838139, 536838149, 536838151, 536838167, 536838173, 536838229, 536838233, 536838307, 536838311, 536838317, 536838353, 536838361, 536838383, 536838389, 536838403, 536838437, 536838509, 536838527, 536838539, 536838541, 536838553, 536838557, 536838583, 536838611, 536838619, 536838629, 536838667, 536838677, 536838697, 536838713, 536838763, 536838769, 536838793, 536838803, 536838821, 536838823, 536838829, 536838839, 536838919, 536838943, 536838949, 536838959, 536839001, 536839027, 536839057, 536839063, 536839081, 536839087, 536839187, 536839211, 536839229, 536839231, 536839249, 536839283, 536839339, 536839351, 536839409, 536839421, 536839427, 536839439, 536839463, 536839469, 536839483, 536839507, 536839517, 536839627, 536839657, 536839663, 536839673, 536839717, 536839727, 536839747, 536839763, 536839769, 536839777, 536839783, 536839799, 536839801, 536839819, 536839829, 536839837, 536839841, 536839859, 536839861, 536839873, 536839921, 536839931, 536839939, 536839949, 536839981, 536839999, 536840009, 536840047, 536840053, 536840069, 536840081, 536840119, 536840123, 536840137, 536840179, 536840197, 536840201, 536840203, 536840207, 536840219, 536840243, 536840261, 536840281, 536840327, 536840329, 536840333, 536840377, 536840407, 536840411, 536840503, 536840527, 536840531, 536840561, 536840567, 536840581, 536840599, 536840651, 536840653, 536840683, 536840701, 536840713, 536840729, 536840741, 536840743, 536840797, 536840819, 536840831, 536840867, 536840873, 536840893, 536840897, 536840903, 536840911, 536840923, 536840959, 536841001, 536841007, 536841017, 536841031, 536841037, 536841077, 536841131, 536841139, 536841157, 536841161, 536841163, 536841169, 536841199, 536841203, 536841209, 536841259, 536841281, 536841289, 536841299, 536841307, 536841397, 536841401, 536841421, 536841443, 536841451, 536841457, 536841479, 536841511, 536841559, 536841581, 536841631, 536841653, 536841667, 536841709, 536841737, 536841743, 536841749, 536841757, 536841797, 536841803, 536841817, 536841839, 536841847, 536841853, 536841887, 536841889, 536841901, 536841937, 536841959, 536842001, 536842021, 536842027, 536842043, 536842049, 536842087, 536842109, 536842127, 536842129, 536842153, 536842157, 536842183, 536842211, 536842217, 536842231, 536842237, 536842249, 536842259, 536842277, 536842349, 536842373, 536842399, 536842421, 536842429, 536842451, 536842477, 536842513, 536842529, 536842543, 536842597, 536842613, 536842633, 536842651, 536842661, 536842667, 536842681, 536842697, 536842723, 536842741, 536842759, 536842763, 536842769, 536842783, 536842819, 536842837, 536842849, 536842877, 536842907, 536842919, 536842939, 536842961, 536842963, 536842973, 536842979, 536842981, 536842993, 536843011, 536843033, 536843039, 536843059, 536843063, 536843077, 536843093, 536843113, 536843117, 536843123, 536843129, 536843137, 536843143, 536843149, 536843173, 536843191, 536843297, 536843327, 536843341, 536843401, 536843441, 536843467, 536843477, 536843491, 536843513, 536843521, 536843539, 536843543, 536843579, 536843617, 536843641, 536843653, 536843669, 536843743, 536843809, 536843819, 536843831, 536843869, 536843887, 536843893, 536843899, 536843921, 536843927, 536843929, 536843939, 536843941, 536843977, 536844001, 536844023, 536844029, 536844043, 536844059, 536844067, 536844151, 536844163, 536844197, 536844229, 536844233, 536844239, 536844247, 536844281, 536844307, 536844323, 536844337, 536844389, 536844437, 536844457, 536844461, 536844509, 536844521, 536844523, 536844533, 536844571, 536844617, 536844619, 536844631, 536844641, 536844643, 536844647, 536844653, 536844661, 536844667, 536844673, 536844689, 536844691, 536844719, 536844731, 536844739, 536844743, 536844757, 536844769, 536844799, 536844823, 536844859, 536844881, 536844911, 536844983, 536845027, 536845061, 536845117, 536845147, 536845151, 536845157, 536845181, 536845207, 536845213, 536845217, 536845223, 536845237, 536845273, 536845289, 536845297, 536845313, 536845319, 536845409, 536845423, 536845447, 536845451, 536845459, 536845471, 536845481, 536845487, 536845489, 536845537, 536845559, 536845613, 536845633, 536845649, 536845663, 536845679, 536845733, 536845763, 536845781, 536845787, 536845807, 536845831, 536845847, 536845849, 536845853, 536845861, 536845867, 536845877, 536845919, 536845949, 536845951, 536845961, 536845973, 536845979, 536846017, 536846021, 536846033, 536846041, 536846047, 536846053, 536846113, 536846117, 536846171, 536846201, 536846207, 536846237, 536846249, 536846257, 536846263, 536846269, 536846293, 536846351, 536846377, 536846467, 536846483, 536846491, 536846509, 536846551, 536846567, 536846603, 536846617, 536846641, 536846647, 536846669, 536846707, 536846711, 536846719, 536846741, 536846759, 536846771, 536846789, 536846861, 536846897, 536846923, 536846929, 536846953, 536846977, 536846983, 536846987, 536847011, 536847013, 536847049, 536847053, 536847061, 536847167, 536847169, 536847187, 536847191, 536847193, 536847203, 536847221, 536847239, 536847247, 536847251, 536847253, 536847281, 536847287, 536847331, 536847341, 536847343, 536847371, 536847419, 536847461, 536847463, 536847473, 536847529, 536847533, 536847551, 536847589, 536847593, 536847599, 536847601, 536847613, 536847659, 536847691, 536847697, 536847713, 536847721, 536847737, 536847791, 536847799, 536847803, 536847823, 536847847, 536847881, 536847893, 536847917, 536847931, 536847937, 536847977, 536847979, 536848009, 536848031, 536848033, 536848073, 536848079, 536848099, 536848121, 536848141, 536848159, 536848181, 536848187, 536848199, 536848231, 536848243, 536848283, 536848307, 536848309, 536848339, 536848357, 536848381, 536848391, 536848393, 536848409, 536848427, 536848471, 536848531, 536848541, 536848549, 536848567, 536848601, 536848603, 536848619, 536848621, 536848657, 536848673, 536848691, 536848709, 536848717, 536848733, 536848757, 536848769, 536848771, 536848787, 536848817, 536848843, 536848877, 536848889, 536848903, 536848951, 536848973, 536848981, 536848987, 536849011, 536849029, 536849111, 536849113, 536849129, 536849143, 536849147, 536849177, 536849179, 536849207, 536849249, 536849251, 536849293, 536849297, 536849323, 536849329, 536849333, 536849381, 536849399, 536849407, 536849419, 536849429, 536849459, 536849497, 536849501, 536849527, 536849581, 536849587, 536849597, 536849603, 536849609, 536849629, 536849633, 536849639, 536849641, 536849669, 536849671, 536849683, 536849741, 536849759, 536849771, 536849809, 536849843, 536849857, 536849891, 536849899, 536849917, 536849939, 536850007, 536850031, 536850037, 536850077, 536850113, 536850133, 536850161, 536850173, 536850211, 536850217, 536850221, 536850229, 536850247, 536850253, 536850257, 536850271, 536850277, 536850289, 536850323, 536850329, 536850331, 536850367, 536850373, 536850389, 536850421, 536850439, 536850469, 536850487, 536850511, 536850547, 536850553, 536850607, 536850637, 536850661, 536850703, 536850709, 536850733, 536850737, 536850739, 536850749, 536850763, 536850791, 536850841, 536850859, 536850907, 536850911, 536850913, 536850917, 536850959, 536850997, 536851009, 536851013, 536851033, 536851037, 536851039, 536851043, 536851069, 536851097, 536851111, 536851127, 536851129, 536851157, 536851169, 536851187, 536851199, 536851223, 536851243, 536851261, 536851307, 536851333, 536851409, 536851411, 536851429, 536851433, 536851489, 536851507, 536851573, 536851607, 536851633, 536851657, 536851673, 536851699, 536851729, 536851751, 536851781, 536851793, 536851829, 536851867, 536851871, 536851873, 536851877, 536851883, 536851927, 536851933, 536851943, 536851949, 536851951, 536851969, 536851979, 536852009, 536852021, 536852059, 536852083, 536852093, 536852111, 536852137, 536852143, 536852149, 536852167, 536852179, 536852191, 536852213, 536852227, 536852273, 536852297, 536852347, 536852357, 536852369, 536852419, 536852431, 536852489, 536852501, 536852507, 536852509, 536852531, 536852557, 536852587, 536852593, 536852599, 536852627, 536852629, 536852689, 536852711, 536852713, 536852747, 536852759, 536852783, 536852801, 536852819, 536852851, 536852857, 536852863, 536852891, 536852903, 536852909, 536852929, 536852933, 536852951, 536852971, 536852993, 536853001, 536853011, 536853061, 536853127, 536853137, 536853197, 536853241, 536853283, 536853293, 536853299, 536853301, 536853311, 536853329, 536853371, 536853403, 536853413, 536853433, 536853437, 536853479, 536853491, 536853503, 536853517, 536853521, 536853529, 536853533, 536853563, 536853571, 536853617, 536853661, 536853671, 536853677, 536853679, 536853689, 536853719, 536853739, 536853749, 536853799, 536853827, 536853857, 536853859, 536853869, 536853893, 536853913, 536853937, 536853943, 536854009, 536854027, 536854037, 536854057, 536854081, 536854117, 536854133, 536854147, 536854159, 536854181, 536854193, 536854211, 536854223, 536854259, 536854309, 536854313, 536854333, 536854361, 536854379, 536854387, 536854391, 536854403, 536854429, 536854459, 536854463, 536854469, 536854471, 536854499, 536854517, 536854553, 536854589, 536854607, 536854609, 536854657, 536854663, 536854711, 536854723, 536854729, 536854789, 536854859, 536854889, 536854909, 536854963, 536854973, 536854991, 536855023, 536855119, 536855131, 536855149, 536855153, 536855159, 536855171, 536855201, 536855339, 536855369, 536855383, 536855413, 536855441, 536855471, 536855477, 536855519, 536855567, 536855591, 536855611, 536855647, 536855653, 536855677, 536855747, 536855777, 536855783, 536855789, 536855807, 536855819, 536855831, 536855833, 536855843, 536855897, 536855899, 536855911, 536855939, 536855953, 536855959, 536855981, 536855983, 536855987, 536856011, 536856017, 536856029, 536856049, 536856097, 536856101, 536856127, 536856143, 536856169, 536856211, 536856217, 536856223, 536856227, 536856241, 536856269, 536856293, 536856329, 536856361, 536856389, 536856391, 536856407, 536856431, 536856433, 536856443, 536856479, 536856487, 536856493, 536856499, 536856521, 536856577, 536856581, 536856611, 536856653, 536856659, 536856743, 536856757, 536856779, 536856797, 536856851, 536856877, 536856883, 536856893, 536856907, 536856917, 536856949, 536856953, 536856959, 536856967, 536857001, 536857033, 536857049, 536857091, 536857147, 536857151, 536857187, 536857207, 536857231, 536857247, 536857259, 536857327, 536857339, 536857351, 536857357, 536857361, 536857381, 536857417, 536857423, 536857439, 536857441, 536857487, 536857493, 536857499, 536857507, 536857561, 536857571, 536857589, 536857609, 536857619, 536857661, 536857681, 536857691, 536857703, 536857729, 536857751, 536857757, 536857771, 536857777, 536857817, 536857823, 536857847, 536857883, 536857921, 536857963, 536857991, 536857999, 536858039, 536858071, 536858089, 536858099, 536858117, 536858143, 536858159, 536858173, 536858177, 536858183, 536858191, 536858209, 536858213, 536858219, 536858227, 536858233, 536858261, 536858263, 536858297, 536858321, 536858369, 536858381, 536858383, 536858389, 536858401, 536858423, 536858437, 536858447, 536858459, 536858503, 536858507, 536858513, 536858519, 536858563, 536858587, 536858599, 536858603, 536858611, 536858639, 536858659, 536858683, 536858689, 536858711, 536858723, 536858731, 536858767, 536858809, 536858843, 536858849, 536858869, 536858887, 536858891, 536858923, 536858941, 536858981, 536858983, 536858989, 536859019, 536859053, 536859119, 536859121, 536859139, 536859151, 536859163, 536859179, 536859181, 536859199, 536859229, 536859241, 536859251, 536859259, 536859263, 536859287, 536859293, 536859299, 536859341, 536859359, 536859377, 536859403, 536859413, 536859451, 536859461, 536859469, 536859493, 536859523, 536859539, 536859551, 536859559, 536859569, 536859577, 536859599, 536859619, 536859623, 536859647, 536859667, 536859671, 536859679, 536859683, 536859689, 536859691, 536859731, 536859769, 536859787, 536859797, 536859809, 536859857, 536859889, 536859901, 536859923, 536859941, 536859959, 536859971, 536859979, 536860021, 536860061, 536860073, 536860081, 536860111, 536860123, 536860127, 536860157, 536860169, 536860199, 536860217, 536860229, 536860231, 536860241, 536860243, 536860249, 536860253, 536860271, 536860283, 536860297, 536860301, 536860307, 536860309, 536860327, 536860381, 536860399, 536860421, 536860427, 536860477, 536860487, 536860507, 536860531, 536860567, 536860579, 536860589, 536860603, 536860609, 536860613, 536860631, 536860669, 536860717, 536860721, 536860729, 536860741, 536860747, 536860771, 536860781, 536860783, 536860811, 536860813, 536860829, 536860843, 536860859, 536860879, 536860913, 536860937, 536860943, 536860949, 536860957, 536860967, 536860981, 536860997, 536861047, 536861057, 536861077, 536861099, 536861107, 536861113, 536861123, 536861153, 536861161, 536861167, 536861177, 536861189, 536861191, 536861197, 536861203, 536861209, 536861219, 536861233, 536861243, 536861251, 536861279, 536861287, 536861291, 536861293, 536861329, 536861333, 536861357, 536861363, 536861387, 536861389, 536861431, 536861447, 536861461, 536861467, 536861497, 536861519, 536861597, 536861609, 536861621, 536861629, 536861681, 536861707, 536861723, 536861753, 536861761, 536861771, 536861779, 536861797, 536861803, 536861807, 536861851, 536861863, 536861869, 536861873, 536861879, 536861903, 536861911, 536861933, 536861939, 536861947, 536861957, 536861981, 536862031, 536862047, 536862071, 536862097, 536862101, 536862103, 536862107, 536862127, 536862133, 536862191, 536862197, 536862199, 536862203, 536862211, 536862269, 536862283, 536862289, 536862301, 536862307, 536862331, 536862373, 536862377, 536862419, 536862427, 536862451, 536862457, 536862479, 536862511, 536862539, 536862541, 536862551, 536862577, 536862581, 536862589, 536862607, 536862617, 536862629, 536862643, 536862679, 536862701, 536862719, 536862731, 536862751, 536862793, 536862827, 536862829, 536862847, 536862871, 536862901, 536862947, 536863001, 536863037, 536863039, 536863057, 536863073, 536863091, 536863099, 536863121, 536863139, 536863189, 536863193, 536863199, 536863231, 536863237, 536863253, 536863267, 536863289, 536863331, 536863333, 536863343, 536863367, 536863403, 536863421, 536863427, 536863433, 536863441, 536863489, 536863511, 536863567, 536863571, 536863577, 536863583, 536863627, 536863637, 536863651, 536863693, 536863703, 536863709, 536863711, 536863721, 536863727, 536863763, 536863771, 536863787, 536863793, 536863801, 536863813, 536863823, 536863843, 536863879, 536863889, 536863897, 536863903, 536863937, 536863997, 536864011, 536864021, 536864023, 536864089, 536864123, 536864149, 536864161, 536864197, 536864213, 536864227, 536864239, 536864297, 536864333, 536864347, 536864353, 536864357, 536864359, 536864381, 536864407, 536864429, 536864453, 536864509, 536864521, 536864527, 536864569, 536864609, 536864621, 536864651, 536864681, 536864693, 536864707, 536864723, 536864729, 536864747, 536864759, 536864767, 536864771, 536864773, 536864837, 536864891, 536864957, 536864963, 536864987, 536864989, 536865001, 536865059, 536865061, 536865071, 536865073, 536865097, 536865101, 536865107, 536865127, 536865167, 536865187, 536865211, 536865233, 536865239, 536865269, 536865281, 536865289, 536865317, 536865323, 536865353, 536865359, 536865377, 536865383, 536865397, 536865403, 536865419, 536865437, 536865451, 536865503, 536865529, 536865541, 536865607, 536865613, 536865619, 536865629, 536865649, 536865683, 536865689, 536865709, 536865713, 536865727, 536865737, 536865761, 536865773, 536865787, 536865799, 536865809, 536865851, 536865859, 536865863, 536865869, 536865877, 536865887, 536865911, 536865949, 536865961, 536865983, 536866019, 536866087, 536866111, 536866117, 536866129, 536866133, 536866151, 536866199, 536866201, 536866247, 536866249, 536866303, 536866321, 536866333, 536866349, 536866381, 536866387, 536866397, 536866399, 536866439, 536866441, 536866459, 536866513, 536866523, 536866543, 536866573, 536866607, 536866609, 536866637, 536866639, 536866651, 536866657, 536866663, 536866697, 536866723, 536866727, 536866769, 536866807, 536866819, 536866823, 536866849, 536866861, 536866931, 536866933, 536867011, 536867027, 536867029, 536867033, 536867057, 536867099, 536867119, 536867141, 536867143, 536867147, 536867153, 536867167, 536867179, 536867189, 536867197, 536867237, 536867291, 536867347, 536867351, 536867377, 536867381, 536867389, 536867411, 536867473, 536867503, 536867509, 536867519, 536867533, 536867537, 536867557, 536867593, 536867651, 536867657, 536867663, 536867677, 536867741, 536867753, 536867761, 536867797, 536867809, 536867813, 536867833, 536867839, 536867843, 536867867, 536867869, 536867873, 536867879, 536867897, 536867911, 536867917, 536867927, 536867941, 536867993, 536868019, 536868053, 536868067, 536868071, 536868083, 536868091, 536868103, 536868107, 536868149, 536868181, 536868191, 536868193, 536868197, 536868209, 536868221, 536868223, 536868289, 536868341, 536868377, 536868379, 536868403, 536868407, 536868419, 536868433, 536868443, 536868467, 536868511, 536868539, 536868547, 536868569, 536868583, 536868587, 536868589, 536868593, 536868623, 536868649, 536868659, 536868697, 536868707, 536868743, 536868749, 536868781, 536868797, 536868799, 536868811, 536868821, 536868863, 536868901, 536868953, 536868961, 536868973, 536868977, 536868979, 536869043, 536869097, 536869117, 536869153, 536869159, 536869189, 536869217, 536869247, 536869283, 536869331, 536869387, 536869409, 536869423, 536869447, 536869471, 536869483, 536869523, 536869549, 536869559, 536869573, 536869583, 536869589, 536869603, 536869607, 536869631, 536869633, 536869637, 536869651, 536869679, 536869693, 536869747, 536869769, 536869771, 536869777, 536869787, 536869793, 536869829, 536869831, 536869891, 536869901, 536869919, 536869937, 536869943, 536869951, 536869999, 536870027, 536870041, 536870057, 536870063, 536870123, 536870153, 536870167, 536870171, 536870219, 536870233, 536870239, 536870267, 536870273, 536870297, 536870303, 536870317, 536870363, 536870401, 536870473, 536870497, 536870501, 536870513, 536870561, 536870563, 536870569, 536870573, 536870599, 536870603, 536870611, 536870627, 536870641, 536870657, 536870683, 536870701, 536870717, 536870723, 536870729, 536870743, 536870767, 536870779, 536870791, 536870813, 536870819, 536870837, 536870839, 536870849, 536870869, 536870879, 536870909, 0 }; #endif /* ! INCL_CF_PRIMETAB_H */ singular-4.0.3+ds/factory/cf_random.cc000066400000000000000000000063501266270727000176670ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #include "config.h" #include #include "cf_assert.h" #include "cf_defs.h" #include "cf_random.h" #include "ffops.h" #include "gfops.h" #include "imm.h" class RandomGenerator { private: const int ia, im, iq, ir, deflt; int s; // s must not equal zero! void seedInit( int ss ) { s = ((ss == 0) ? deflt : ss); } public: RandomGenerator(); RandomGenerator( int ss ); ~RandomGenerator() {} int generate(); void seed( int ss ) { seedInit( ss ); } }; RandomGenerator::RandomGenerator() : ia(16807), im(2147483647), iq(127773), ir(2836), deflt(123459876) { seedInit( (int)time( 0 ) ); } RandomGenerator::RandomGenerator( int ss ) : ia(16807), im(2147483647), iq(127773), ir(2836), deflt(123459876) { seedInit( ss ); } int RandomGenerator::generate() { int k; k = s/iq; s = ia*(s-k*iq)-ir*k; if ( s < 0 ) s += im; return s; } RandomGenerator ranGen; CanonicalForm FFRandom::generate () const { return CanonicalForm( int2imm_p( factoryrandom( ff_prime ) ) ); } CFRandom * FFRandom::clone () const { return new FFRandom(); } CanonicalForm GFRandom::generate () const { int i= factoryrandom( gf_q ); if ( i == gf_q1 ) i++; return CanonicalForm( int2imm_gf( i ) ); } CFRandom * GFRandom::clone () const { return new GFRandom(); } IntRandom::IntRandom() { max = 50; } IntRandom::IntRandom( int m ) { max = m; } IntRandom::~IntRandom() {} CanonicalForm IntRandom::generate() const { return factoryrandom( 2*max )-max; } CFRandom * IntRandom::clone() const { return new IntRandom( max ); } AlgExtRandomF::AlgExtRandomF() { ASSERT( 0, "not a valid random generator" ); } AlgExtRandomF::AlgExtRandomF( const AlgExtRandomF & ) { ASSERT( 0, "not a valid random generator" ); } AlgExtRandomF& AlgExtRandomF::operator= ( const AlgExtRandomF & ) { ASSERT( 0, "not a valid random generator" ); return *this; } AlgExtRandomF::AlgExtRandomF( const Variable & v ) { ASSERT( v.level() < 0, "not an algebraic extension" ); algext = v; n = degree( getMipo( v ) ); gen = CFRandomFactory::generate(); } AlgExtRandomF::AlgExtRandomF( const Variable & v1, const Variable & v2 ) { ASSERT( v1.level() < 0 && v2.level() < 0 && v1 != v2, "not an algebraic extension" ); algext = v2; n = degree( getMipo( v2 ) ); gen = new AlgExtRandomF( v1 ); } AlgExtRandomF::AlgExtRandomF( const Variable & v, CFRandom * g, int nn ) { algext = v; n = nn; gen = g; } AlgExtRandomF::~AlgExtRandomF() { delete gen; } CanonicalForm AlgExtRandomF::generate() const { CanonicalForm result; for ( int i = 0; i < n; i++ ) result += power( algext, i ) * gen->generate(); return result; } CFRandom * AlgExtRandomF::clone () const { return new AlgExtRandomF( algext, gen->clone(), n ); } CFRandom * CFRandomFactory::generate() { if ( getCharacteristic() == 0 ) return new IntRandom(); if ( getGFDegree() > 1 ) return new GFRandom(); else return new FFRandom(); } int factoryrandom( int n ) { if ( n == 0 ) return (int)ranGen.generate(); else return ranGen.generate() % n; } void factoryseed ( int s ) { ranGen.seed( s ); } singular-4.0.3+ds/factory/cf_random.h000066400000000000000000000035521266270727000175320ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_random.h * * generate random integers, random elements of finite fields **/ #ifndef INCL_CF_RANDOM_H #define INCL_CF_RANDOM_H // #include "config.h" #include "canonicalform.h" /*BEGINPUBLIC*/ /** * virtual class for random element generation **/ class CFRandom { public: virtual ~CFRandom() {} virtual CanonicalForm generate() const { return 0; } virtual CFRandom * clone() const { return new CFRandom(); } }; /** * generate random elements in GF **/ class GFRandom : public CFRandom { public: GFRandom() {}; ~GFRandom() {} CanonicalForm generate() const; CFRandom * clone() const; }; /** * generate random elements in F_p **/ class FFRandom : public CFRandom { public: FFRandom() {} ~FFRandom() {} CanonicalForm generate() const; CFRandom * clone() const; }; /** * generate random integers **/ class IntRandom : public CFRandom { private: int max; public: IntRandom(); IntRandom( int m ); ~IntRandom(); CanonicalForm generate() const; CFRandom * clone() const; }; /** * generate random elements in F_p(alpha) **/ class AlgExtRandomF : public CFRandom { private: Variable algext; CFRandom * gen; int n; AlgExtRandomF(); AlgExtRandomF( const Variable & v, CFRandom * g, int nn ); AlgExtRandomF& operator= ( const AlgExtRandomF & ); public: AlgExtRandomF( const AlgExtRandomF & ); AlgExtRandomF( const Variable & v ); AlgExtRandomF( const Variable & v1, const Variable & v2 ); ~AlgExtRandomF(); CanonicalForm generate() const; CFRandom * clone() const; }; class CFRandomFactory { public: static CFRandom * generate(); }; /// random integers with abs less than n int factoryrandom( int n ); /// random seed initializer void factoryseed( int s ); /*ENDPUBLIC*/ #endif /* ! INCL_CF_RANDOM_H */ singular-4.0.3+ds/factory/cf_resultant.cc000066400000000000000000000150061266270727000204260ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_resultant.cc * * algorithms for calculating resultants. * * Header file: cf_algorithm.h * **/ #include "config.h" #include "cf_assert.h" #include "canonicalform.h" #include "variable.h" #include "cf_algorithm.h" /** CFArray subResChain ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) * * subResChain() - caculate extended subresultant chain. * * The chain is calculated from f and g with respect to variable * x which should not be an algebraic variable. If f or q equals * zero, an array consisting of one zero entry is returned. * * Note: this is not the standard subresultant chain but the * *extended* chain! * * This algorithm is from the article of R. Loos - 'Generalized * Polynomial Remainder Sequences' in B. Buchberger - 'Computer * Algebra - Symbolic and Algebraic Computation' with some * necessary extensions concerning the calculation of the first * step. * **/ CFArray subResChain ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) { ASSERT( x.level() > 0, "cannot calculate subresultant sequence with respect to algebraic variables" ); CFArray trivialResult( 0, 0 ); CanonicalForm F, G; Variable X; // some checks on triviality if ( f.isZero() || g.isZero() ) { trivialResult[0] = 0; return trivialResult; } // make x main variable if ( f.mvar() > x || g.mvar() > x ) { if ( f.mvar() > g.mvar() ) X = f.mvar(); else X = g.mvar(); F = swapvar( f, X, x ); G = swapvar( g, X, x ); } else { X = x; F = f; G = g; } // at this point, we have to calculate the sequence of F and // G in respect to X where X is equal to or greater than the // main variables of F and G // initialization of chain int m = degree( F, X ); int n = degree( G, X ); int j = (m <= n) ? n : m-1; int r; CFArray S( 0, j+1 ); CanonicalForm R; S[j+1] = F; S[j] = G; // make sure that S[j+1] is regular and j < n if ( m == n && j > 0 ) { S[j-1] = LC( S[j], X ) * psr( S[j+1], S[j], X ); j--; } else if ( m < n ) { S[j-1] = LC( S[j], X ) * LC( S[j], X ) * S[j+1]; j--; } else if ( m > n && j > 0 ) { // calculate first step r = degree( S[j], X ); R = LC( S[j+1], X ); // if there was a gap calculate similar polynomial if ( j > r && r >= 0 ) S[r] = power( LC( S[j], X ), j - r ) * S[j] * power( R, j - r ); if ( r > 0 ) { // calculate remainder S[r-1] = psr( S[j+1], S[j], X ) * power( -R, j - r ); j = r-1; } } while ( j > 0 ) { // at this point, 0 < j < n and S[j+1] is regular r = degree( S[j], X ); R = LC( S[j+1], X ); // if there was a gap calculate similar polynomial if ( j > r && r >= 0 ) S[r] = (power( LC( S[j], X ), j - r ) * S[j]) / power( R, j - r ); if ( r <= 0 ) break; // calculate remainder S[r-1] = psr( S[j+1], S[j], X ) / power( -R, j - r + 2 ); j = r-1; // again 0 <= j < r <= jOld and S[j+1] is regular } for ( j = 0; j <= S.max(); j++ ) { // reswap variables if necessary if ( X != x ) { S[j] = swapvar( S[j], X, x ); } } return S; } /** static CanonicalForm trivialResultant ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) * * trivialResultant - calculate trivial resultants. * * x's level should be larger than f's and g's levels. Either f * or g should be constant or both linear. * * Used by resultant(). * **/ static CanonicalForm trivialResultant ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) { // f or g in R if ( degree( f, x ) == 0 ) return power( f, degree( g, x ) ); if ( degree( g, x ) == 0 ) return power( g, degree( f, x ) ); // f and g are linear polynomials return LC( f, x ) * g - LC( g, x ) * f; } /** CanonicalForm resultant ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) * * resultant() - return resultant of f and g with respect to x. * * The chain is calculated from f and g with respect to variable * x which should not be an algebraic variable. If f or q equals * zero, zero is returned. If f is a coefficient with respect to * x, f^degree(g, x) is returned, analogously for g. * * This algorithm serves as a wrapper around other resultant * algorithms which do the real work. Here we use standard * properties of resultants only. * **/ CanonicalForm resultant ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) { ASSERT( x.level() > 0, "cannot calculate resultant with respect to algebraic variables" ); // some checks on triviality. We will not use degree( v ) // here because this may involve variable swapping. if ( f.isZero() || g.isZero() ) return 0; if ( f.mvar() < x ) return power( f, g.degree( x ) ); if ( g.mvar() < x ) return power( g, f.degree( x ) ); // make x main variale CanonicalForm F, G; Variable X; if ( f.mvar() > x || g.mvar() > x ) { if ( f.mvar() > g.mvar() ) X = f.mvar(); else X = g.mvar(); F = swapvar( f, X, x ); G = swapvar( g, X, x ); } else { X = x; F = f; G = g; } // at this point, we have to calculate resultant( F, G, X ) // where X is equal to or greater than the main variables // of F and G int m = degree( F, X ); int n = degree( G, X ); // catch trivial cases if ( m+n <= 2 || m == 0 || n == 0 ) return swapvar( trivialResultant( F, G, X ), X, x ); // exchange F and G if necessary int flipFactor; if ( m < n ) { CanonicalForm swap = F; F = G; G = swap; int degswap = m; m = n; n = degswap; if ( m & 1 && n & 1 ) flipFactor = -1; else flipFactor = 1; } else flipFactor = 1; // this is not an effective way to calculate the resultant! CanonicalForm extFactor; if ( m == n ) { if ( n & 1 ) extFactor = -LC( G, X ); else extFactor = LC( G, X ); } else extFactor = power( LC( F, X ), m-n-1 ); CanonicalForm result; result = subResChain( F, G, X )[0] / extFactor; return swapvar( result, X, x ) * flipFactor; } singular-4.0.3+ds/factory/cf_reval.cc000066400000000000000000000021701266270727000175140ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #define MORE_ZEROES #include "config.h" #include "cf_assert.h" #include "cf_defs.h" #include "cf_reval.h" REvaluation::REvaluation( const REvaluation & e ):Evaluation() { if ( e.gen == 0 ) gen = 0; else gen = e.gen->clone(); values = e.values; } REvaluation::~REvaluation() { if ( gen != 0 ) delete gen; } REvaluation& REvaluation::operator= ( const REvaluation & e ) { if ( this != &e ) { if (gen!=0) delete gen; values = e.values; if ( e.gen == 0 ) gen = 0; else gen = e.gen->clone(); } return *this; } void REvaluation::nextpoint() { int n = values.max(); for ( int i = values.min(); i <= n; i++ ) values[i] = gen->generate(); } void REvaluation::nextpoint (int n) { int m= values.max(); int t= values.min(); for (int i= t; i <= m; i++) values [i]= 0; if (m == t) { values [t]= gen->generate(); return; } for (int i= 0; i < n; i++) { int l= factoryrandom (m - t + 1) + t; values [l]= gen->generate(); } } singular-4.0.3+ds/factory/cf_reval.h000066400000000000000000000015071266270727000173610ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file cf_reval.h * * generate random evaluation points **/ #ifndef INCL_CF_REVAL_H #define INCL_CF_REVAL_H // #include "config.h" #include "canonicalform.h" #include "cf_eval.h" #include "cf_random.h" /*BEGINPUBLIC*/ /** * class to generate random evaluation points * * @sa cf_eval.h **/ class REvaluation : public Evaluation { protected: // neeeded in FFREvaluation CFRandom * gen; public: REvaluation() : Evaluation(), gen(0) {} REvaluation( int min0, int max0, const CFRandom & sample ) : Evaluation( min0, max0 ), gen( sample.clone() ) {} REvaluation( const REvaluation & e ); ~REvaluation(); REvaluation& operator= ( const REvaluation & e ); void nextpoint(); void nextpoint(int n); }; /*ENDPUBLIC*/ #endif /* ! INCL_CF_REVAL_H */ singular-4.0.3+ds/factory/cf_switches.cc000066400000000000000000000012211266270727000202300ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_switches.cc * * definition of class CFSwitches. * * Used by: cf_globals.cc * **/ #include "config.h" #include "cf_switches.h" #include "cf_defs.h" /** CFSwitches::CFSwitches () * * CFSwitches::CFSwitches() - default constructor. * * Turns all switches off. * **/ CFSwitches::CFSwitches () { for ( int i = 0; i < CFSwitchesMax; i++ ) switches[i] = false; // and set the default (recommended) On-values: #ifdef HAVE_NTL On(SW_USE_CHINREM_GCD); //Off(SW_USE_NTL_SORT); #endif On(SW_USE_EZGCD); //On(SW_USE_EZGCD_P); // still testing On(SW_USE_QGCD); } singular-4.0.3+ds/factory/cf_switches.h000066400000000000000000000034421266270727000201010ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_switches.h * * header to cf_switches.cc. * **/ #ifndef INCL_CF_SWITCHES_H #define INCL_CF_SWITCHES_H // #include "config.h" /** const int CFSwitchesMax * * const CFSwitchesMax - maximum number of switches. * **/ const int CFSwitchesMax = 8; /** class CFSwitches * * class CFSwitches - manages boolean switches. * * An object of class `CFSwitches' is simply an array of booleans * with some comfortable access methods (`On()', `isOn()', etc.). * Each object may contain `CFSwitchesMax' switches. When a new * object of type `CFSwitches' is created, all its switches are * turned off. * * Note: No range checking is done when accessing switches. * * switches: the switches * **/ class CFSwitches { private: bool switches [CFSwitchesMax]; CFSwitches (); public: // constructors, destructors ~CFSwitches () {} static inline CFSwitches& getInstance() { static CFSwitches singleton; return singleton; } // selectors /// switch 's' on void On ( int s ) { switches[s] = true; } /// switch 's' off void Off ( int s ) { switches[s] = false; } /// check if 's' is on bool isOn ( int s ) const { return switches[s]; } /// check if 's' is off bool isOff ( int s ) const { return ! switches[s]; } }; /** CFSwitches cf_glob_switches; * * cf_glob_switches - factory switches. * * This is the only object of type CFSwitches in factory. It is * used either directly in the low level algorithms or by the * functions On(), Off(), isOn() defined in canonicalform.cc. * **/ // extern CFSwitches& cf_glob_switches; // CFSwitches& cf_glob_switches = CFSwitches::getInstance(); #define cf_glob_switches (CFSwitches::getInstance()) #endif /* ! INCL_CF_SWITCHES_H */ singular-4.0.3+ds/factory/cf_util.cc000066400000000000000000000020101266270727000173510ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * * @file cf_util.cc * * miscellaneous functions, not necessarily related * to canonical forms. * * Used by: fac_cantzass.cc, gfops.cc * **/ #include "config.h" /** int ipower ( int b, int m ) * * ipower() - calculate b^m in standard integer arithmetic. * * Note: Beware of overflows. * **/ int ipower ( int b, int m ) { int prod = 1; while ( m != 0 ) { if ( m % 2 != 0 ) prod *= b; m /= 2; if ( m != 0 ) b *= b; } return prod; } int ilog2 (int a) { int n = -1; while ( a > 0 ) { n++; a /=2; } return n; } int igcd( int a, int b ) { if ( a < 0 ) a = -a; if ( b < 0 ) b = -b; int c; while ( b != 0 ) { c = a % b; a = b; b = c; } return a; } #include #include void factoryError_intern(const char *s) { fputs(s,stderr); abort(); } void (*factoryError)(const char *s) = factoryError_intern; singular-4.0.3+ds/factory/cf_util.h000066400000000000000000000005301266270727000172200ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ #ifndef INCL_CF_UTIL_H #define INCL_CF_UTIL_H // #include "config.h" int ilog2 (int a); /*BEGINPUBLIC*/ int igcd (int a, int b); int ipower ( int b, int n ); void factoryError_intern(const char *s); extern void (*factoryError)(const char *s); /*ENDPUBLIC*/ #endif /* ! INCL_CF_UTIL_H */ singular-4.0.3+ds/factory/configure.ac000066400000000000000000000256361266270727000177260ustar00rootroot00000000000000 dnl # emacs edit mode for this file is -*- sh -*- dnl # dnl # configure.in - process this file with `autoconf' to generate dnl # a `configure' script. dnl # dnl # See the `INSTALL' file for information on how the `configure' dnl # script works. dnl # # # - initialisation. # AC_INIT([factory], [4.0.3]) AC_CONFIG_SRCDIR(canonicalform.cc) AC_CONFIG_MACRO_DIR([../m4]) AC_CONFIG_AUX_DIR([../build-aux]) AC_CONFIG_HEADER([_config.h]) AM_INIT_AUTOMAKE([-Wall foreign subdir-objects]) # -Wno-extra-portability -Werror silent-rules m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AM_MAINTAINER_MODE([enable]) # Add pre'prefixed config AX_PREFIX_CONFIG_H([config.h],[],[_config.h]) # # - check for CC and CXX but be careful about CFLAGS. # SING_RESET_FLAGS() SING_CHECK_SET_ARGS() #AC_PROG_CC #AC_PROG_CXX # # - check for some other programs. # AC_PROG_CPP AC_PROG_CXXCPP AC_PROG_LN_S AC_PROG_INSTALL ## AC_DISABLE_STATIC AC_PROG_YACC LT_INIT AC_PROG_MAKE_SET AC_CHECK_PROG(AR, ar, ar, where-is-your-ar) AC_CHECK_PROG(M4, m4, m4, where-is-your-m4) AC_CHECK_PROG(BISON, bison, bison, where-is-your-bison) AC_CHECK_SIZEOF(long,4) AC_C_CONST AC_C_INLINE # # - check withs and enables. # AC_ARG_ENABLE( cf-inline, [AS_HELP_STRING([--enable-cf-inline],[build Factory with \"configurable inline methods\" enabled.])], [enable_cf_inline=$enableval], [enable_cf_inline=no]) AC_ARG_ENABLE( assertions, [AS_HELP_STRING([--disable-assertions],[build Factory with no assertions])], , enable_assertions=yes) AC_ARG_ENABLE( timing, [AS_HELP_STRING([--enable-timing],[build Factory so it will print timing information])], , enable_timing=no) AC_ARG_ENABLE( debugoutput, [AS_HELP_STRING([--enable-debugoutput],[build Factory so it will print debugging information])], , enable_debugoutput=no) AC_ARG_ENABLE( streamio, [AS_HELP_STRING([--enable-streamio],[build Factory with stream IO])], , [enable_streamio=no]) AH_TEMPLATE([NOSTREAMIO], [define to build factory without stream IO]) AC_ARG_WITH( Singular, [AS_HELP_STRING([--without-Singular],[(obsolete) build NOT for the use with CAS Singular.])], , [with_Singular=yes]) PKG_REQUIRE="$PKG_REQUIRE" AC_SUBST(PKG_REQUIRE) SING_CHECK_OMALLOC() AH_TEMPLATE([SINGULAR], [define if linked to Singular]) AH_TEMPLATE([DISABLE_GMP_CPP],[DISABLE_GMP_CPP]) # Singular if test "x$with_Singular" = xyes; then AC_DEFINE([SINGULAR],[1]) AC_DEFINE([DISABLE_GMP_CPP],[1]) # AC_DEFINE([NOSTREAMIO],[1]) fi # || test "x$with_Singular" = xyes # Use no streamio (C++) if SINGULAR or explicitely disabled if test "x$enable_streamio" = xno; then AC_DEFINE([NOSTREAMIO],[1]) fi AM_CONDITIONAL( [WITH_PARSER_FOR_CANONICAL_FORM], [test "x$enable_streamio" = xyes]) AC_ARG_VAR( [RESOURCES_INCLUDES], [INCLUDES for libresources] ) AC_ARG_VAR( [RESOURCES_LIBS], [LIBS for libresources] ) AC_MSG_CHECKING(whether libresources should be used) if test "x$with_Singular" = xyes; then AC_MSG_RESULT(yes) AC_MSG_CHECKING([ RESOURCES_INCLUDES?..]) AC_MSG_RESULT(${RESOURCES_INCLUDES:-unset}) AC_MSG_CHECKING([ RESOURCES_LIBS?..]) AC_MSG_RESULT(${RESOURCES_LIBS:-unset}) PKG_REQUIRE="$PKG_REQUIRE resources" AC_SUBST(PKG_REQUIRE) else AC_MSG_RESULT(no) fi AM_CONDITIONAL([ENABLE_RESOURCES],[test "x$with_Singular" = xyes]) AH_TEMPLATE([FACTORY_INT64], [Defenition for FACTORY_INT64]) # Always long long int???! AC_DEFINE([FACTORY_INT64], [long long int]) DX_INIT_DOXYGEN($PACKAGE_NAME, doxygen.cfg, $srcdir/docu) # do not use `MKINSTALLDIRS' and `MAKEHEADER' since there may be # name clashes with other peoples configure scripts via # `config.cache'. Furthermore, we do not use cache at all to # avoid some nasty problems with our own development environment. #unset ac_cv_path_FACTORY_MKINSTALLDIRS #unset ac_cv_path_FACTORY_MAKEHEADER #save_path="$PATH" #PATH="$PATH:$srcdir/bin" #AC_PATH_PROG(FACTORY_MKINSTALLDIRS, mkinstalldirs, -mkdir) #PATH="$srcdir/bin:$save_path" #AC_PATH_PROG(FACTORY_MAKEHEADER, makeheader) #PATH="$save_path" # # - expand paths. # #AC_MSG_CHECKING(and generating explicit install paths) ## generate Makefile #save_prefix="$prefix" #save_exec_prefix="$exec_prefix" #test "x$prefix" = xNONE && prefix=$ac_default_prefix #test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' #for dir in prefix exec_prefix bindir sbindir libexecdir \ # datadir sysconfdir sharedstatedir localstatedir libdir \ # includedir oldincludedir infodir mandir; do # eval "dir_value=\$$dir" # cat >> ./conftest.mk << EXPLPATHEOT #$dir=$dir_value #explicit_$dir: # @ echo \$($dir) # @ if echo \$($dir) | grep '^/'; \\ # then echo \$($dir) > ./conftest.dir; \\ # else echo \`pwd\`/\$($dir) > ./conftest.dir; fi #EXPLPATHEOT #done #prefix="$save_prefix" #exec_prefix="$save_exec_prefix" # generate the explicit paths #make >&5 2>&1 -f ./conftest.mk explicit_datadir #explicit_datadir=`cat ./conftest.dir` #make >&5 2>&1 -f ./conftest.mk explicit_libdir #explicit_libdir=`cat ./conftest.dir` #make >&5 2>&1 -f ./conftest.mk explicit_includedir #explicit_includedir=`cat ./conftest.dir` # clean up #rm -f ./conftest.mk ./conftest.dir #AC_MSG_RESULT(done) # # - check for libraries. # AC_CHECK_LIB(m, atof, , [ AC_MSG_ERROR(libm.a not found) ]) LB_CHECK_GMP(3.1.1,,AC_MSG_ERROR([Unable to find GMP on your machine: please use --with-gmp=PATH_TO_DIR_CONTAINING_LIB_AND_INCLUDE (see also ./configure --help if you do not understand what we are talking about)])) LB_CHECK_NTL(5.0,,AC_MSG_WARN([Unable to find NTL (which is strongly recommended) on your machine: please use --with-ntl=PATH_TO_DIR_CONTAINING_LIB_AND_INCLUDE (see also ./configure --help if you do not understand what we are talking about)])) LB_CHECK_FLINT(2.4,,AC_MSG_WARN([Unable to find FLINT (which is strongly recommended) on your machine: please use --with-flint=PATH_TO_DIR_CONTAINING_LIB_AND_INCLUDE (see also ./configure --help if you do not understand what we are talking about)])) # arithmetic shift #AC_MSG_CHECKING(whether your compiler does arithmetic shifts) #AC_CACHE_VAL(ac_cv_shift, # [ LDFLAGS="-L$explicit_libdir $LDFLAGS" # AC_TRY_RUN( # [ int main() { if (-2 >> 1 == -1) return(0); else return(1); } ], # ac_cv_shift=yes, ac_cv_shift=no, ac_cv_shift=yes) ]) #if test "x$ac_cv_shift" = xyes; then # AC_MSG_RESULT(yes) #else # AC_MSG_RESULT(no) #fi # # - check for header files. # AC_LANG_CPLUSPLUS AC_LANG_PUSH([C++]) AC_CHECK_HEADERS(stdio.h stdlib.h string.h time.h math.h, , [ AC_MSG_ERROR(C header files not found) ]) AC_CHECK_HEADERS(cstdio) if test "x$enable_streamio" != xno; then AC_CHECK_HEADERS(iostream.h strstream.h fstream.h iostream string fstream) AC_CHECK_HEADERS(ctype.h, , [ AC_MSG_ERROR(standard C header files not found) ]) # since the FTE will compile only with stream IO enabled we will not # check for the necessary header files if stream IO is disabled AC_CHECK_HEADERS(stdarg.h signal.h errno.h unistd.h, , [ AC_MSG_WARN(C/C++ header files not found. You will not be able to build the Factory Test Environment (though Factory itself should compile)) ]) fi if test "x$enable_timing" != xno; then AC_CHECK_HEADERS(sys/param.h sys/times.h, , [ AC_MSG_ERROR(\`sys/times.h' or \`sys/param.h' not found. Try \`configure --disable-timing') ]) fi # font-lock-trick: ' # # - check for compiler characteristics. # # use C to check compiler characteristics instead of C++. On # nextstep, checking with C++ may fail. # AC_LANG_C # cross-compiling ?! #AC_C_CROSS #if test "x$cross_compiling" = xyes; then # AC_MSG_WARN([you better specify a cache file to get the values for # cross-compiling right (e.g., call \`configure # --cache-file=yourTarget.cache'). In particular, you # should make sure that your target machine supports # arithmetic shift.]) #fi # font-lock-trick: ' # # - paths. # # note that Singular has its own mechanism to search the tables, # hence we do not need to mind it here #gftabledir='${datadir}/factory/gftables' #explicit_gftabledir="$explicit_datadir/gftables" # for installation of the templates #templatedir='${includedir}/templates' # # - set defines and variables according to our tests. # ## CFLAGS #if test "x$GCC" = xyes && test "x$cflags_expl_set" = xno; then # CFLAGS="" #fi # CXXFLAGS #if test "x$GXX" = xyes && test "x$cxxflags_expl_set" = xno; then # CXXFLAGS="" # #AC_LANG_SAVE #AC_LANG_CPLUSPLUS # check whether CXX accepts -fno-rtti #AC_MSG_CHECKING(whether gcc accepts -fno-rtti) #tmp_flags=${CXXFLAGS} #CXXFLAGS="${CXXFLAGS}" #AC_CACHE_VAL(ac_cv_cxx_have_rtti, #AC_TRY_COMPILE(,,ac_cv_cxx_have_rtti=yes,ac_cv_cxx_have_rtti=no) #) #AC_MSG_RESULT(${ac_cv_cxx_have_rtti}) #CXXFLAGS=$tmp_flags #if test "${ac_cv_cxx_have_rtti}" = yes; then #CXXFLAGS="$CXXFLAGS" #fi #AC_MSG_CHECKING(whether gcc accepts -fno-exceptions) #tmp_flags=${CXXFLAGS} #CXXFLAGS="${CXXFLAGS} -fno-exceptions" #AC_CACHE_VAL(ac_cv_cxx_have_exceptions, #AC_TRY_LINK(,,ac_cv_cxx_have_exceptions=yes,ac_cv_cxx_have_exceptions=no) #) #AC_MSG_RESULT(${ac_cv_cxx_have_exceptions}) #CXXFLAGS=$tmp_flags #if test "${ac_cv_cxx_have_exceptions}" = yes; then #CXXFLAGS="$CXXFLAGS -fno-exceptions" #fi #AC_LANG_RESTORE # #fi # ARFLAGS #test "${ARFLAGS+set}" = set || ARFLAGS=cr # M4FLAGS #test "${M4FLAGS+set}" = set || M4FLAGS= # arithmetic shift #if test "x$ac_cv_shift" = xyes; then # AC_DEFINE([HAS_ARITHMETIC_SHIFT],[1],[HAS_ARITHMETIC_SHIFT]) #fi AH_TEMPLATE([CF_USE_INLINE], [define to use "configurable inline methods" (see cf_inline.cc)]) # "configurable inline methods" if test "x$enable_cf_inline" != xno; then AC_DEFINE([CF_USE_INLINE],[1]) fi AH_TEMPLATE([NOASSERT], [define if you do not want to activate assertions]) # assertions if test "x$enable_assertions" = xno; then AC_DEFINE([NOASSERT],[1]) fi AH_TEMPLATE([TIMING], [define if you want to activate the timing stuff]) # timing if test "x$enable_timing" != xno; then AC_DEFINE([TIMING],[1]) fi # debugoutput AH_TEMPLATE([DEBUGOUTPUT], [define if you want to have debugging output]) if test "x$enable_debugoutput" != xno; then AC_DEFINE([DEBUGOUTPUT],[1]) fi # # - complete and substitute variables, defines. # #AC_SUBST(gftabledir) #AC_SUBST(templatedir) # AC_SUBST(libfactory) #AC_SUBST(ARFLAGS) #AC_SUBST(M4FLAGS) AC_SUBST(MAKEHEADERFLAGS) #AC_SUBST(factorysrc) #AC_SUBST(factoryincl) #AC_SUBST(alltargets) #AC_SUBST(installtargets) #AC_SUBST(uninstalltargets) factory_version="4.0.1" factory_configuration="'$ac_configure_args' in `pwd`" AC_SUBST(factory_version) AH_TEMPLATE([FACTORYVERSION], [factory version]) AC_DEFINE_UNQUOTED([FACTORYVERSION], "$factory_version") AH_TEMPLATE([FACTORYCONFIGURATION], [factory configuration]) AC_DEFINE_UNQUOTED([FACTORYCONFIGURATION], "$factory_configuration") #AH_TEMPLATE([GFTABLEDIR], [where the gftables live]) #AC_DEFINE_UNQUOTED([GFTABLEDIR], "$explicit_gftabledir") AC_CONFIG_FILES([Makefile include/factory/Makefile factory.pc]) # ftest/GNUmakefile AC_OUTPUT singular-4.0.3+ds/factory/cplusplus.cc000066400000000000000000000015631266270727000177720ustar00rootroot00000000000000#include #define QUOTEME_(x) #x #define QUOTEME(x) QUOTEME_(x) int main(void) { int ret; # ifdef __cplusplus printf("#ifndef __cplusplus \n" ); printf("/*BEWARE: this fix can lead to problems if cf_gmp.h is publicly installed, while mixing different (versions of) compilers!!!*/\n" ); printf("#define __cplusplus %s\n", QUOTEME( __cplusplus )); // System current compiler DEPENDENT!!! printf("#endif /*__cplusplus*/\n" ); ret = 0; # else ret = 1; # endif return ret; /* #define __cplusplus_backup __cplusplus #ifdef __cplusplus_backup printf("__cplusplus_backup: %s\n", QUOTEME(__cplusplus_backup) ); #else printf("undefined __cplusplus_backup!\n"); #endif #undef __cplusplus #ifdef __cplusplus_backup printf("__cplusplus_backup: %s\n", QUOTEME(__cplusplus_backup) ); #else printf("undefined __cplusplus_backup!\n"); #endif */ } singular-4.0.3+ds/factory/debug.cc000066400000000000000000000014331266270727000170220ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ static int deb_level = -1; char * deb_level_msg = (char *)""; void deb_inc_level() { int i; // deb_level == -1 iff we enter this function for the first time if ( deb_level == -1 ) deb_level = 0; else delete [] deb_level_msg; deb_level++; deb_level_msg = new char[3*deb_level+1]; for ( i = 0; i < 3*deb_level; i++ ) deb_level_msg[i] = ' '; deb_level_msg[3*deb_level] = '\0'; } void deb_dec_level() { if ( deb_level > 0 ) { int i; deb_level--; delete [] deb_level_msg; deb_level_msg = new char[3*deb_level+1]; for ( i = 0; i < 3*deb_level; i++ ) deb_level_msg[i] = ' '; deb_level_msg[3*deb_level] = '\0'; } } singular-4.0.3+ds/factory/debug.h000066400000000000000000000026011266270727000166620ustar00rootroot00000000000000/* emacs edit mode for this file is -*- C++ -*- */ /** * @file debug.h * * functions to print debug output * * @note needs --enable-debugoutput --enable-streamio at configure **/ /* It should be possible to include this file multiple times for different */ /* settings of DEBUGOUTPUT */ #undef DEBINCLEVEL #undef DEBDECLEVEL #undef DEBOUTSL #undef DEBOUT #undef DEBOUTENDL #undef DEBOUTLN #ifdef DEBUGOUTPUT #include #ifdef HAVE_IOSTREAM #include #elif defined(HAVE_IOSTREAM_H) #include #endif void deb_inc_level(); void deb_dec_level(); extern char * deb_level_msg; #define DEBINCLEVEL(stream, msg) \ (std::stream << deb_level_msg << "entering << " << msg << " >>" << std::endl, deb_inc_level()) #define DEBDECLEVEL(stream, msg) \ (deb_dec_level(), std::stream << deb_level_msg << "leaving << " << msg << " >>" << std::endl) #define DEBOUTSL(stream) \ (std::stream << deb_level_msg, std::stream.flush()) #define DEBOUT(stream, objects) \ (std::stream << objects, std::stream.flush()) #define DEBOUTENDL(stream) \ (std::stream << std::endl) #define DEBOUTLN(stream, objects) \ (std::stream << deb_level_msg << objects << std::endl) #else /* DEBUGOUTPUT */ #define DEBINCLEVEL(stream, msg) #define DEBDECLEVEL(stream, msg) #define DEBOUTSL(stream) #define DEBOUT(stream, objects) #define DEBOUTENDL(stream) #define DEBOUTLN(stream, objects) #endif /* DEBUGOUTPUT */ singular-4.0.3+ds/factory/doxygen.cfg000066400000000000000000003044641266270727000175750ustar00rootroot00000000000000# Doxyfile 1.8.6 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = $(PROJECT)-$(VERSION) # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = $(DOCDIR) # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = YES # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = $(SRCDIR) # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = YES # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = YES # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 0 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = $(SRCDIR) # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = $(SRCDIR)/include/factory/factory.h $(SRCDIR)/include/factory/factoryconf.h $(SRCDIR)/old # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = ./.. # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = $(GENERATE_HTML) # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = $(GENERATE_HTMLHELP) # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = ../$(PROJECT).chm # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = $(HHC_PATH) # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = $(GENERATE_CHI) # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = YES # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /